diff --git a/.checkpatch.conf b/.checkpatch.conf index e2783af81d..511019b260 100644 --- a/.checkpatch.conf +++ b/.checkpatch.conf @@ -1,3 +1,7 @@ +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + # Not Linux, so don't expect a Linux tree. --no-tree @@ -9,3 +13,19 @@ --ignore C99_COMMENT_TOLERANCE --ignore VSPRINTF_POINTER_EXTENSION + +# Shorter KConfig descriptions are OK. +--min-conf-desc-length=2 + +# Zephyr has a function named "printk" with different facilities than +# the printk in the Linux kernel this check is made for. +--ignore PRINTK_WITHOUT_KERN_LEVEL + +# Zephyr coding style requires braces even when not explicitly +# required (unlike the Linux kernel). In the interest of making code +# easier to upstream into the Zephyr tree, we should do the same. +# Tell checkpatch to ignore Linux style here. +--ignore BRACES + +# Zephyr uses ENOSYS to indicate unsupported API calls +--ignore ENOSYS diff --git a/.clang-format b/.clang-format index ee759ab79c..78649d65ca 100644 --- a/.clang-format +++ b/.clang-format @@ -66,11 +66,16 @@ DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false FixNamespaceComments: false -IncludeBlocks: Preserve +IncludeBlocks: Regroup IncludeCategories: - - Regex: '.*' + - Regex: '^".*\.h"$' + Priority: 0 + - Regex: '^<(assert|complex|ctype|errno|fenv|float|inttypes|limits|locale|math|setjmp|signal|stdarg|stdbool|stddef|stdint|stdio|stdlib|string|tgmath|time|wchar|wctype)\.h>$' Priority: 1 -IncludeIsMainRegex: '(Test)?$' + - Regex: '^\$' + Priority: 2 + - Regex: '.*' + Priority: 3 IndentCaseLabels: false IndentPPDirectives: None IndentWidth: 8 @@ -98,7 +103,6 @@ PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right ReflowComments: true -SortIncludes: false SortUsingDeclarations: false SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true diff --git a/.clangd b/.clangd new file mode 100644 index 0000000000..a2f9a678e5 --- /dev/null +++ b/.clangd @@ -0,0 +1,10 @@ +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +CompileFlags: + # Remove gcc-specific flags for clangd + Remove: [ + -fno-reorder-functions, + -mfp16-format=ieee, + ] diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000000..f5d6acc820 --- /dev/null +++ b/.flake8 @@ -0,0 +1,8 @@ +[flake8] +extend-ignore = E203 +exclude = + .hypothesis, + .pytest_cache, + __pycache__, + build, + dist diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000000..acde12f6b1 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,39 @@ +name: lint code in pull request + +on: + pull_request: + push: + +jobs: + build: + name: lint new changes + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: get checkpatch + run: | + wget "https://raw.githubusercontent.com/torvalds/linux/master/scripts/checkpatch.pl" + wget "https://raw.githubusercontent.com/torvalds/linux/master/scripts/spelling.txt" + chmod +x checkpatch.pl + + - name: checkpatch + run: | + git diff origin/${{ github.base_ref }} | ./checkpatch.pl --mailback --no-tree --ignore MAINTAINERS,FILE_PATH_CHANGES,SPDX_LICENSE_TAG - > checkpatch.txt || true + exit=0 + if [ -s checkpatch.txt ]; then + errors=$(cat checkpatch.txt) + errors="${errors//'%'/'%25'}" + errors="${errors//$'\n'/'%0A'}" + errors="${errors//$'\r'/'%0D'}" + echo "::error file=Checkpatch.txt::$errors" + exit=1 + fi + if [ $exit = 1 ]; then + exit 1; + fi + - name: output + run: | + cat checkpatch.txt diff --git a/.github/workflows/lotus-azalea-build.yml b/.github/workflows/lotus-azalea-build.yml new file mode 100644 index 0000000000..16feebed44 --- /dev/null +++ b/.github/workflows/lotus-azalea-build.yml @@ -0,0 +1,83 @@ +name: build lotus, azalea firmware + +on: + push: + branches: + - fwk-* + - pr-* + +jobs: + build: + name: Build lotus/azalea + runs-on: [marigold-builders] + + strategy: + # Only build one at a time because we have only one working directory + max-parallel: 1 + matrix: + platform: [ + # c1488028cf525335b95b277112795219dc6b7688 is bad and won't build with our lotus EC branch + { name: lotus, folder: marigold1, ver: "0.0.0", sha_len: 7, zephyr_ref: "lotus-zephyr", cmsis_ref: "c1488028cf525335b95b277112795219dc6b7688^", remote: "github-private" }, + { name: azalea, folder: marigold1, ver: "0.0.0", sha_len: 7, zephyr_ref: "lotus-zephyr", cmsis_ref: "c1488028cf525335b95b277112795219dc6b7688^", remote: "github-private" }, + ] + + + # Build not in $GITHUB_HOME but in the chroot env + defaults: + run: + working-directory: /${{ matrix.platform.folder }}/ec_home/chromiumos + + steps: + # Need to use git + #- name: Checkout EC code + # uses: actions/checkout@v4 + # with: + # path: /lotus/ec_home/chromiumos/src/platform/ec + + #- name: Checkout Zephyr code + # uses: actions/checkout@v2 + # path: /lotus/ec_home/chromiumos/src/third_party/zephyr/main + # ref: lotus-zephyr + # repository: ssh://git@github.com/FrameworkComputer/zephyr-ec + + # Need to manually checkout + # actions/checkout@v4 complains: + # Error: Repository path '/lotus/ec_home/chromiumos/src/platform/ec' is not under '/data/ec_home/actions-runner/_work/ec/ec' + # See: https://github.com/actions/checkout/issues/197 + - name: Manual checkout + run: | + pushd src/platform/ec + git fetch ${{ matrix.platform.remote }} + git clean -ffdx + # TODO: Doesn't work with on PR, only push + git reset --hard ${{ matrix.platform.remote }}/$GITHUB_REF_NAME + popd + + pushd src/third_party/zephyr/main + git fetch ${{ matrix.platform.remote }} + git clean -ffdx + git reset --hard ${{ matrix.platform.remote }}/${{ matrix.platform.zephyr_ref }} + popd + + pushd src/third_party/zephyr/cmsis + git fetch cros + git clean -ffdx + git reset --hard ${{ matrix.platform.cmsis_ref }} + popd + + - name: Build ${{ matrix.platform.name }} + run: | + cros_sdk zmake build ${{ matrix.platform.name }} + echo Built ${{ matrix.platform.name }} EC + + - name: File sha256 + run: sha256sum src/platform/ec/build/zephyr/${{ matrix.platform.name }}/output/ec.bin + + - name: Generate artifact version + run: | + echo "VERSIONINFO=$(date -u +'%Y-%m-%d-%H-%M-%S')_$GITHUB_SHA" >> $GITHUB_ENV + + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.platform.name }}.${{ env.VERSIONINFO }} + path: /${{ matrix.platform.folder }}/ec_home/chromiumos/src/platform/ec/build/zephyr/${{ matrix.platform.name }}/output diff --git a/.gitignore b/.gitignore index 6532cf43ee..bc93291213 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,42 @@ build/ -private*/ +/private*/ # A "local" directory for hiding scripts and artifacts from git. local/ *~ *.swp -*.pyc tags TAGS +/ctags cscope.* .tests-passed .failedboards/ .sizes.txt +.gdb_history +# Git commit message template (see https://crbug.com/gerrit/10963) +.gitmessage + +# Clion IDE +.idea/ + +# VSCode IDE +.vscode/* +!.vscode/README.md +!.vscode/settings.json.default +*.code-workspace + +# Python ignores +*.pyc +__pycache__ +*.egg-info +.hypothesis/ +zephyr/zmake/.coverage +zephyr/zmake/htmlcov/ +zephyr/zmake/coverage.json + +# Clangd language server +.cache/clangd/index/* +compile_commands.json + +# Twister test output directories +twister-out* +flash.bin diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..762c43ba88 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,514 @@ +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +image: jbettis/ubuntu-26apr23 + +# You can update that image using this repo: +# https://gitlab.com/zephyr-ec/gitlab-ci-runner/-/tree/main + +# Only run on main and coverage branches +workflow: + rules: + - if: ($CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "coverage") + +# The directory structure is: +# +# ${CI_PROJECT_DIR} +# |_ ec_dir/ - EC repo (${EC_DIR}) +# |_ build/ - make and zmake artifacts (${BUILD_DIR}) +# |_ twister-out/ - Twister artifacts (${TWISTER_OUT_DIR}) +# |_ modules/ - Additional Zephyr modules (${MODULES_DIR}) +# | |_ cmsis/ +# | |_ hal_stm32/ +# | |_ nanopb/ +# | |_ cryptoc/ +# | |_ boringssl/ +# |_ zephyr/ +# |_ main/ - Zephyr repo (${ZEPHYR_BASE}) +# +# On Gitlab builds, ${CI_PROJECT_DIR} is at /builds/zephyr-ec/ec. On local +# builds, it will be /builds/0/project-0. + +before_script: + - echo "CI_PROJECT_DIR is at ${CI_PROJECT_DIR}" + # Move freshly-checked out ec code to subdirectory + - cd ${CI_PROJECT_DIR} + - mkdir -p ec_dir + - find . -mindepth 1 -maxdepth 1 -name ec_dir -o -print0 | xargs -0 -I {} mv {} ec_dir + - export EC_DIR="${CI_PROJECT_DIR}/ec_dir" + - export MODULES_DIR="$CI_PROJECT_DIR/modules" + - export ZEPHYR_BASE="${CI_PROJECT_DIR}/zephyr/main" + - export REPO_BASE="${CI_PROJECT_DIR}/repo" + - git config --global --add safe.directory '*' + # Get Zephyr repo and modules + - checkout_at_date() { + local url="$1" ; + local branch="$2" ; + local path="$3" ; + local date="$4" ; + local retries=5 ; + + while [ ${retries} -gt 0 ] ; do + rm -rf "${path}" ; + mkdir -p "${path}" ; + if git clone --depth 1 -b "${branch}" "${url}" "${path}"; then + break ; + else + echo "git clone failed will retry ${retries} times"; + fi ; + retries="$(( ${retries} - 1 ))" ; + done ; + cd "${path}" ; + rev="$(git rev-list -n 1 --before="${date}" "${branch}")" ; + depth=1 ; + while [ -z "${rev}" ] ; do + depth="$(( ${depth} + 100 ))" ; + git fetch --depth="${depth}" ; + rev="$(git rev-list -n 1 --before="${date}" "${branch}")" ; + done ; + git checkout -d "${rev}" ; + } + - repo_clone_at_data() { + local repo="$1" ; + local branch="$2" ; + local path="$3" ; + local date="$4" ; + + mkdir -p "${REPO_BASE}" ; + cd "${REPO_BASE}" ; + repo init -u https://chromium.googlesource.com/chromiumos/manifest -b main ; + repo sync "${repo}" ; + + mkdir -p "${path}" ; + cp -rTLf "${repo}" "${path}" ; + + cd "${path}" ; + rev="$(git rev-list -n 1 --before="${date}" "${branch}")" ; + depth=1 ; + while [ -z "${rev}" ] ; do + depth="$(( ${depth} + 100 ))" ; + git fetch --depth="${depth}" ; + rev="$(git rev-list -n 1 --before="${date}" "${branch}")" ; + done ; + git checkout -d "${rev}" ; + rev="$(git rev-list -n 1 --before="${date}" "${branch}")" ; + } + - ec_commit_date="$(cd ${EC_DIR} ; git log -1 HEAD --format=%cd --date=iso)" + - checkout_at_date "https://chromium.googlesource.com/chromium/tools/depot_tools.git" "main" "${CI_PROJECT_DIR}/depot_tools" "${ec_commit_date}" + - export PATH="${CI_PROJECT_DIR}/depot_tools:$PATH" + - checkout_at_date "https://chromium.googlesource.com/chromiumos/third_party/zephyr" "main" "${ZEPHYR_BASE}" "${ec_commit_date}" + - checkout_at_date "https://chromium.googlesource.com/chromiumos/third_party/zephyr/cmsis" "chromeos-main" "${MODULES_DIR}/cmsis" "${ec_commit_date}" + - checkout_at_date "https://chromium.googlesource.com/chromiumos/third_party/zephyr/hal_stm32" "chromeos-main" "${MODULES_DIR}/hal_stm32" "${ec_commit_date}" + - checkout_at_date "https://chromium.googlesource.com/chromiumos/third_party/zephyr/nanopb" "main" "${MODULES_DIR}/nanopb" "${ec_commit_date}" + - checkout_at_date "https://chromium.googlesource.com/chromiumos/third_party/cryptoc" "main" "${MODULES_DIR}/cryptoc" "${ec_commit_date}" + - repo_clone_at_data "src/third_party/boringssl" "m/main" "${MODULES_DIR}/boringssl" "${ec_commit_date}" + # Add a symlink so the ec appears in modules directory (hack to make zmake work) + - ln -s "${EC_DIR}" "${MODULES_DIR}/ec" + # Install Python and packages + - python3 -V # Print out python version for debugging + - python3 -m pip install "${EC_DIR}/zephyr/zmake[tests]" --user + - python3 -m pip install natsort + - export PATH="$PATH:$HOME/.local/bin" + - export PYTHONIOENCODING=utf-8 + # Build directory + - export BUILD_DIR=${EC_DIR}/build + - export TWISTER_OUT_DIR=${EC_DIR}/twister-out + +# Users of this template must set: +# $PROJECT to the project to build. E.g., "lazor" +.build_template: &build_template + stage: build + needs: [] + script: + - zmake --zephyr-base "${ZEPHYR_BASE}" + --modules-dir "${MODULES_DIR}" -l DEBUG build + -B "${BUILD_DIR}" -t ${TOOLCHAIN:-zephyr} + "${PROJECT}" + - for b in "${BUILD_DIR}/${PROJECT}"/build-* ; do + bdir=$(basename ${b}) ; + if ninja -C ${b} ram_report >"${BUILD_DIR}/${PROJECT}/output/${bdir}_ram_report.txt" ; then + cp ${b}/ram.json "${BUILD_DIR}/${PROJECT}/output/${bdir}_ram.json" ; + else + echo "Ram report failed" ; + fi ; + if ninja -C ${b} rom_report >"${BUILD_DIR}/${PROJECT}/output/${bdir}_rom_report.txt" ; then + cp ${b}/rom.json "${BUILD_DIR}/${PROJECT}/output/${bdir}_rom.json" ; + else + echo "Rom report failed" ; + fi ; + done + - ls "${BUILD_DIR}/${PROJECT}" "${BUILD_DIR}/${PROJECT}/output" + artifacts: + paths: + - ec_dir/build/${PROJECT}/output/* + expire_in: 1 week + +# Users of this template must set: +# $PROJECT to the project to build. E.g., "lazor" +# Builds the project with coverage enabled, removes the non-ec files. +# Then merges with the tests, excludes all files not used by this project, +# and generates a report. +# NOTE: If you change the lcov -r command below, also edit the one in +# merged_coverage +.coverage_template: &coverage_template + stage: test + needs: + - "merged_coverage" + - "zephyr_coverage" + script: + - cd ${EC_DIR} + - zmake --zephyr-base "${ZEPHYR_BASE}" + --modules-dir "${MODULES_DIR}" -l DEBUG build --coverage + -B "${BUILD_DIR}" -t ${TOOLCHAIN:-zephyr} + "${PROJECT}" + - lcov --rc lcov_branch_coverage=1 -o "${BUILD_DIR}/${PROJECT}/output/merged.info" + -a "${BUILD_DIR}/${PROJECT}/output/zephyr.info" + -a "${BUILD_DIR}/merged.info" + - lcov --rc lcov_branch_coverage=1 + -o "${BUILD_DIR}/${PROJECT}/output/no_zephyr.info" + -r "${BUILD_DIR}/${PROJECT}/output/zephyr.info" "${ZEPHYR_BASE}/**" + "${MODULES_DIR}/**" + "${EC_DIR}/zephyr/drivers/**" "${EC_DIR}/zephyr/include/drivers/**" + "${EC_DIR}/zephyr/shim/chip/**" "${EC_DIR}/zephyr/shim/core/**" + "/usr/include/**" + "${EC_DIR}/build/**" "${EC_DIR}/twister-out*/**" + "${EC_DIR}/test/**" + "${EC_DIR}/zephyr/shim/chip/npcx/npcx_monitor/**" + "${EC_DIR}/zephyr/emul/**" "${EC_DIR}/zephyr/test/**" + "**/testsuite/**" "**/subsys/emul/**" + - util/lcov_stencil.py -o "${BUILD_DIR}/${PROJECT}/output/prefiltered.info" + "${BUILD_DIR}/${PROJECT}/output/no_zephyr.info" + "${BUILD_DIR}/${PROJECT}/output/merged.info" + - lcov --rc lcov_branch_coverage=1 + -o "${BUILD_DIR}/${PROJECT}/output/filtered_no_zephyr.info" + -r "${BUILD_DIR}/${PROJECT}/output/prefiltered.info" + "${ZEPHYR_BASE}/**" "${MODULES_DIR}/**" + "${EC_DIR}/zephyr/drivers/**" "${EC_DIR}/zephyr/include/drivers/**" + "${EC_DIR}/zephyr/shim/chip/**" "${EC_DIR}/zephyr/shim/core/**" + "/usr/include/**" + "${EC_DIR}/build/**" "${EC_DIR}/twister-out*/**" + "${EC_DIR}/zephyr/shim/chip/npcx/npcx_monitor/**" + "${EC_DIR}/test/**" + "${EC_DIR}/include/tests/**" + "${EC_DIR}/private/test/**" + "${EC_DIR}/private/fingerprint/*/mcutest/**" + "${EC_DIR}/zephyr/test/**" + "${EC_DIR}/include/mock/**" + "${EC_DIR}/common/mock/**" + "${EC_DIR}/board/host/**" + "${EC_DIR}/chip/host/**" + "${EC_DIR}/core/host/**" + "${EC_DIR}/zephyr/emul/**" + "${EC_DIR}/zephyr/mock/**" + "${EC_DIR}/zephyr/program/dev/**" + "**/*_test.c" + "**/*_test.h" + "**/*_emul.c" + "**/*_emul.h" + "${EC_DIR}/include/test_util.h" + "${EC_DIR}/common/test_util.c" + "${EC_DIR}/zephyr/shim/src/test_util.c" + "${EC_DIR}/zephyr/shim/src/ztest_system.c" + "${EC_DIR}/driver/tcpm/it8xxx2.c" + - /usr/bin/genhtml --branch-coverage -q + -o "${BUILD_DIR}/${PROJECT}/output/filtered_no_zephyr_rpt" + -t "${PROJECT} coverage w/o zephyr" + -p ${EC_DIR} + -s "${BUILD_DIR}/${PROJECT}/output/filtered_no_zephyr.info" + artifacts: + paths: + - ec_dir/build/${PROJECT}/output/*.info + - ec_dir/build/${PROJECT}/output/*_rpt + expire_in: 1 week + when: always + coverage: '/lines\.*: \d+\.\d+%/' + +herobrine: + variables: + PROJECT: "herobrine" + <<: *build_template + +herobrine_coverage: + variables: + PROJECT: "herobrine" + <<: *coverage_template + +nivviks_coverage: + variables: + PROJECT: "nivviks" + <<: *coverage_template + +nereid_coverage: + variables: + PROJECT: "nereid" + <<: *coverage_template + +it8xxx2_evb: + variables: + PROJECT: "it8xxx2_evb" + <<: *build_template + +kingler: + variables: + PROJECT: "kingler" + <<: *build_template + +kingler_coverage: + variables: + PROJECT: "kingler" + <<: *coverage_template + +krabby: + variables: + PROJECT: "krabby" + <<: *build_template + +krabby_coverage: + variables: + PROJECT: "krabby" + <<: *coverage_template + +lazor: + variables: + PROJECT: "lazor" + <<: *build_template + +npcx7_evb: + variables: + PROJECT: "npcx7" + <<: *build_template + +npcx9_evb: + variables: + PROJECT: "npcx9" + <<: *build_template + +skyrim: + variables: + PROJECT: "skyrim" + <<: *build_template + +skyrim_coverage: + variables: + PROJECT: "skyrim" + <<: *coverage_template + +winterhold: + variables: + PROJECT: "winterhold" + <<: *build_template + +winterhold_coverage: + variables: + PROJECT: "winterhold" + <<: *coverage_template + +frostflow: + variables: + PROJECT: "frostflow" + <<: *build_template + +frostflow_coverage: + variables: + PROJECT: "frostflow" + <<: *coverage_template + +crystaldrift: + variables: + PROJECT: "crystaldrift" + <<: *build_template + +crystaldrift_coverage: + variables: + PROJECT: "crystaldrift" + <<: *coverage_template + +markarth: + variables: + PROJECT: "markarth" + <<: *build_template + +markarth_coverage: + variables: + PROJECT: "markarth" + <<: *coverage_template + +rex: + variables: + PROJECT: "rex" + <<: *build_template + +rex_coverage: + variables: + PROJECT: "rex" + <<: *coverage_template + +geralt: + variables: + PROJECT: "geralt" + <<: *build_template + +geralt_coverage: + variables: + PROJECT: "geralt" + <<: *coverage_template + +myst: + variables: + PROJECT: "myst" + <<: *build_template + +myst_coverage: + variables: + PROJECT: "myst" + <<: *coverage_template + +ec_coverage: + stage: test + needs: [] + script: + - cd ${EC_DIR} + - make -j$(nproc) BORINGSSL_DIR="${MODULES_DIR}/boringssl" + CRYPTOC_DIR="${MODULES_DIR}/cryptoc" + CROSS_COMPILE_arm=/opt/zephyr-sdk/arm-zephyr-eabi/bin/arm-zephyr-eabi- + CROSS_COMPILE_host=/usr/bin/ + test-coverage + artifacts: + paths: + - ec_dir/build/coverage/coverage_rpt/* + - ec_dir/build/coverage/lcov.info + expire_in: 1 week + coverage: '/lines\.*: \d+\.\d+%/' + +zephyr_coverage: + stage: test + needs: [] + script: + - python3 ${EC_DIR}/twister --coverage --outdir "${TWISTER_OUT_DIR}" + -v -i -x=ALLOW_WARNINGS=ON + artifacts: + paths: + - ec_dir/twister-out/coverage.info + expire_in: 1 week + coverage: '/lines\.*: \d+\.\d+%/' + +zephyr_boards_coverage: + stage: build + needs: [] + parallel: 5 + script: + - cd ${EC_DIR} + - projects=( $(zmake --zephyr-base "${ZEPHYR_BASE}" + --modules-dir "${MODULES_DIR}" list-projects | + split -n r/"${CI_NODE_INDEX}"/"${CI_NODE_TOTAL}") ) + - zmake --zephyr-base "${ZEPHYR_BASE}" + --modules-dir "${MODULES_DIR}" -l DEBUG build + --coverage --delete-intermediates "${projects[@]}" + - mv build/zephyr/all_builds.info "build/zephyr/all_builds${CI_NODE_INDEX}.info" + artifacts: + paths: + - ec_dir/build/zephyr/all_builds*.info + expire_in: 1 week + coverage: '/lines\.*: \d+\.\d+%/' + +# NOTE: If you change the lcov -r command below, also edit the one in +# .coverage_template +merged_coverage: + stage: test + needs: ["ec_coverage", "zephyr_coverage", "zephyr_boards_coverage"] + script: + # build_dir / "all_tests.info" -> "${BUILD_DIR}/merged.info" + - lcov --rc lcov_branch_coverage=1 -o "${BUILD_DIR}/merged.info" + -a "${BUILD_DIR}/coverage/lcov.info" -a "${TWISTER_OUT_DIR}/coverage.info" + - printf ' -a %s' ${BUILD_DIR}/zephyr/all_builds[0-9]*.info | xargs -x + lcov --rc lcov_branch_coverage=1 -o "${BUILD_DIR}/zephyr/zephyr_merged.info" + -a "${BUILD_DIR}/merged.info" + - lcov --rc lcov_branch_coverage=1 + -o "${BUILD_DIR}/all_builds_filtered.info" + -r "${BUILD_DIR}/zephyr/zephyr_merged.info" + "${EC_DIR}/build/**" "${EC_DIR}/twister-out*/**" "/usr/include/**" + "/usr/lib/**" + "${EC_DIR}/test/**" + "${EC_DIR}/include/tests/**" + "${EC_DIR}/private/test/**" + "${EC_DIR}/private/fingerprint/*/mcutest/**" + "${EC_DIR}/zephyr/test/**" + "${ZEPHYR_BASE}/main/subsys/testsuite/**" + "${EC_DIR}/include/mock/**" + "${EC_DIR}/common/mock/**" + "${EC_DIR}/board/host/**" + "${EC_DIR}/chip/host/**" + "${EC_DIR}/core/host/**" + "${EC_DIR}/zephyr/emul/**" + "${EC_DIR}/zephyr/mock/**" + "${EC_DIR}/zephyr/program/dev/**" + "${ZEPHYR_BASE}/main/subsys/emul/**" + "**/*_test.c" + "**/*_test.h" + "**/*_emul.c" + "**/*_emul.h" + "${EC_DIR}/include/test_util.h" + "${EC_DIR}/common/test_util.c" + "${EC_DIR}/zephyr/shim/src/test_util.c" + "${EC_DIR}/zephyr/shim/src/ztest_system.c" + - /usr/bin/genhtml --branch-coverage -q + -o "${BUILD_DIR}/all_builds_filtered_rpt" + -t "All boards and tests merged" + -p ${EC_DIR} + -s "${BUILD_DIR}/all_builds_filtered.info" + artifacts: + paths: + - ec_dir/build/*.info + - ec_dir/build/*_rpt + expire_in: 1 week + coverage: '/lines\.*: \d+\.\d+%/' + +testall: + stage: test + needs: [] + script: + - python3 ${EC_DIR}/twister --outdir "${TWISTER_OUT_DIR}" -v -i + -x=ALLOW_WARNINGS=ON + +# The download url changed. Disable until we can figure it out. +# twister_coverage: +# stage: test +# needs: [] +# script: +# - mkdir -p ${BUILD_DIR}/zephyr_codecov +# - for commitid in $(cd "${ZEPHYR_BASE}" ; git fetch --depth=100 ; git log | awk '/GitOrigin-RevId:/ {print $2}') ; do +# echo "COMMITID = ${commitid?}" ; +# if wget -O /tmp/coverage.html "https://app.codecov.io/gh/zephyrproject-rtos/zephyr/commit/${commitid?}" ; then +# downloadurl=$(sed -e '/download\/build/!d' -e 's|^.*href="|https://codecov.io|' -e 's|".*$||' /tmp/coverage.html | head -1) ; +# echo "DOWNLOADURL = ${downloadurl?}" ; +# wget -O ${BUILD_DIR}/zephyr_codecov/merged.info.raw "${downloadurl?}" ; +# sed <${BUILD_DIR}/zephyr_codecov/merged.info.raw >${BUILD_DIR}/zephyr_codecov/merged.info +# -e '1,/<<<<<< network/d' -e '/<<<<<< EOF/,$d' ; +# sed <${BUILD_DIR}/zephyr_codecov/merged.info >${BUILD_DIR}/zephyr_codecov/fixed.info +# -e "s|/__w/zephyr/zephyr|${ZEPHYR_BASE}|" +# -e "s|/__w/zephyr/modules/hal/cmsis|${MODULES_DIR}/cmsis|" +# -e "s|/__w/zephyr/modules|${MODULES_DIR}|" ; +# break ; +# fi ; +# done +# - lcov --rc lcov_branch_coverage=1 --summary ${BUILD_DIR}/zephyr_codecov/fixed.info +# artifacts: +# paths: +# - ec_dir/build/zephyr_codecov/fixed.info +# expire_in: 1 week +# coverage: '/lines\.*: \d+\.\d+%/' + +zmake_coverage: + stage: test + needs: [] + script: + - cd ${EC_DIR}/zephyr/zmake + - coverage run --source=zmake -m pytest . + - coverage report + - coverage html + artifacts: + paths: + - ec_dir/zephyr/zmake/htmlcov/* + expire_in: 1 week + coverage: '/^TOTAL.+?(\d+\%)$/' diff --git a/.vscode/README.md b/.vscode/README.md new file mode 100644 index 0000000000..1e83806519 --- /dev/null +++ b/.vscode/README.md @@ -0,0 +1,3 @@ +# VSCode Setting + +See [docs/ide-support.md](/docs/ide-support.md). diff --git a/.vscode/settings.json.default b/.vscode/settings.json.default new file mode 100644 index 0000000000..2c9497413a --- /dev/null +++ b/.vscode/settings.json.default @@ -0,0 +1,36 @@ +/* Copy this file to settings.json to active these defaults. */ +{ + "editor.rulers": [ + 80 + ], + /* C, Makefiles, ASM, Linkerfiles, Properties */ + "editor.insertSpaces": false, + "editor.tabSize": 8, + "python.formatting.provider": "black", + /* Some exceptions based on current trends */ + "[markdown]": { + "editor.insertSpaces": true, + "editor.tabSize": 2 + }, + "[python]": { + "editor.insertSpaces": true, + "editor.tabSize": 4 + }, + "[shellscript]": { + "editor.insertSpaces": true, + "editor.tabSize": 2 + }, + "[yaml]": { + "editor.insertSpaces": true, + "editor.tabSize": 2 + }, + "files.associations": { + "Makefile.*": "makefile", + "*.inc": "c", + "*.wrap": "c", + "*.tasklist": "c", + "*.irqlist": "c", + "*.mocklist": "c", + "*.testlist": "c" + } +} \ No newline at end of file diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000000..a814a38237 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,231 @@ +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +load( + "@cros_firmware//platform/rules_cros_firmware/cros_firmware:ec.bzl", + "ec_binary", +) + +ec_binary( + name = "adlrvp_mchp", +) + +ec_binary( + name = "adlrvp_npcx", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "brya", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "craask", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "crystaldrift", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "dev-posix", +) + +ec_binary( + name = "evoker", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "frostflow", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "geralt", +) + +ec_binary( + name = "gothrax", +) + +ec_binary( + name = "herobrine", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "hoglin", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "it8xxx2_evb", +) + +ec_binary( + name = "joxer", +) + +ec_binary( + name = "kingler", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "krabby", +) + +ec_binary( + name = "lazor", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "magikarp", +) + +ec_binary( + name = "markarth", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "minimal-it8xxx2", +) + +ec_binary( + name = "minimal-npcx9", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "minimal-posix", +) + +ec_binary( + name = "mtlrvpp_mchp", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "mtlrvpp_npcx", +) + +ec_binary( + name = "myst", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "nereid", +) + +ec_binary( + name = "nereid_cx", +) + +ec_binary( + name = "nivviks", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "npcx7", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "npcx9", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "pujjo", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "rex", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "rex-ish-ec", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "screebo", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "skyrim", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "starmie", +) + +ec_binary( + name = "steelix", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "tentacruel", +) + +ec_binary( + name = "uldren", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "villager", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "voltorb", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "winterhold", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "xivu", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "xivur", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "yaviks", +) + +ec_binary( + name = "yavilla", +) + +ec_binary( + name = "zoglin", + extra_modules = ["cmsis"], +) + +ec_binary( + name = "zombie", + extra_modules = ["cmsis"], +) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..34e81f2be9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Note: this cmake system implements only a zephyr module, and is not +# intended to build a complete EC. To build projects in platform/ec, +# you should continue to use the Makefile system. +# +# Googlers can find the design doc at go/zephyr-shim. + +if(NOT DEFINED ZEPHYR_CURRENT_MODULE_DIR) + message(FATAL_ERROR "This Cmake system implements only a Zephyr module, and + should not be invoked directly. Please continue to use the Makefile + system for non-Zephyr builds.") +endif() + +set(PLATFORM_EC "${ZEPHYR_CURRENT_MODULE_DIR}" CACHE PATH + "Path to the platform/ec repo.") + +set(PLATFORM_EC_PROGRAM_DIR "${PLATFORM_EC}/zephyr/program" CACHE PATH + "Path to the root directory containing all Zephyr EC programs and projects.") + +if(NOT EXISTS "${PLATFORM_EC}/zephyr/module.yml") + message(FATAL_ERROR "Failed to resolve PLATFORM_EC at + ${PLATFORM_EC}/zephyr/module.yml") +endif() + +add_subdirectory(zephyr) +add_subdirectory(common) diff --git a/CPPLINT.cfg b/CPPLINT.cfg new file mode 100644 index 0000000000..d260909910 --- /dev/null +++ b/CPPLINT.cfg @@ -0,0 +1,4 @@ +set noparent +# Disable cpplint, since EC is a C project that follows Linux kernel style. +# cpplint is called by "cros lint". +exclude_files=.* diff --git a/DIR_METADATA b/DIR_METADATA new file mode 100644 index 0000000000..526b1dd7ed --- /dev/null +++ b/DIR_METADATA @@ -0,0 +1,17 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +buganizer { + component_id: 167114 # ChromeOS > Platform > Enablement > Firmware > EC +} + +buganizer_public { + component_id: 960650 # ChromeOS Public Tracker > Core Systems > Firmware > EC +} + +team_email: "cros-ec@google.com" diff --git a/Kconfig b/Kconfig new file mode 100644 index 0000000000..d3705151e3 --- /dev/null +++ b/Kconfig @@ -0,0 +1,6 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +rsource "zephyr/Kconfig" +rsource "common/Kconfig" diff --git a/LICENSE b/LICENSE index da112abc64..a55bf15b9d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -// Copyright 2010 The Chromium OS Authors. All rights reserved. +// Copyright 2010 The ChromiumOS Authors // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. -// * Neither the name of Google Inc. nor the names of its +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/Makefile b/Makefile index 1db6de37b2..812b5dc2c4 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# Copyright 2011 The Chromium OS Authors. All rights reserved. +# Copyright 2011 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -13,7 +13,7 @@ # This is used to exclude build targets that depend on sanitizers such as # fuzzers on architectures that don't support sanitizers yet (e.g. arm). ARCH?=amd64 -BOARD ?= bds +BOARD ?= elm # Directory where the board is configured (includes /$(BOARD) at the end) BDIR:=$(wildcard board/$(BOARD)) @@ -50,6 +50,8 @@ EMPTY= ifdef CTS_MODULE # CTS builds need different directories per board per suite. out?=build/$(BOARD)/cts_$(CTS_MODULE) +else ifdef TEST_COVERAGE +out?=build/coverage/initial-$(BOARD) else out?=build/$(BOARD) endif @@ -113,6 +115,12 @@ CFLAGS_BASEBOARD= endif include chip/$(CHIP)/build.mk +# The toolchain must be set before referencing any toolchain-related variables +# (CC, CPP, CXX, etc.) so that the correct toolchain is used. The CORE variable +# is set in the CHIP build file, so this include must come after including the +# CHIP build file. +include core/$(CORE)/toolchain.mk + # Create uppercase config variants, to avoid mixed case constants. # Also translate '-' to '_', so 'cortex-m' turns into 'CORTEX_M'. This must # be done before evaluating config.h. @@ -128,7 +136,7 @@ UC_PROJECT:=$(call uppercase,$(PROJECT)) # Transform the configuration into make variables. This must be done after # the board/baseboard/project/chip/core variables are defined, since some of # the configs are dependent on particular configurations. -includes=include core/$(CORE)/include $(dirs) $(out) fuzz test +includes=include core/$(CORE)/include include/driver $(dirs) $(out) fuzz test third_party ifdef CTS_MODULE includes+=cts/$(CTS_MODULE) cts endif @@ -148,6 +156,7 @@ endif _tsk_lst_flags+=-I$(BDIR) -DBOARD_$(UC_BOARD)=$(EMPTY) -I$(BASEDIR) \ -DBASEBOARD_$(UC_BASEBOARD)=$(EMPTY) \ -D_MAKEFILE=$(EMPTY) -imacros $(_tsk_lst_file) +-include private/task_list_flags.mk _tsk_lst_ro:=$(shell $(CPP) -P -DSECTION_IS_RO=$(EMPTY) \ $(_tsk_lst_flags) include/task_filter.h) @@ -210,7 +219,8 @@ _mock_cfg := $(foreach t,$(_mock_lst) ,HAS_MOCK_$(t)) CPPFLAGS += $(foreach t,$(_mock_cfg),-D$(t)=$(EMPTY)) $(foreach c,$(_mock_cfg),$(eval $(c)=y)) -ifneq "$(CONFIG_COMMON_RUNTIME)" "y" +ifneq ($(CONFIG_COMMON_RUNTIME),y) +ifneq ($(CONFIG_DFU_BOOTMANAGER_MAIN),ro) _irq_list:=$(shell $(CPP) $(CPPFLAGS) -P -Ichip/$(CHIP) -I$(BASEDIR) \ -I$(BDIR) -D"ENABLE_IRQ(x)=EN_IRQ x" \ -imacros chip/$(CHIP)/registers.h \ @@ -218,6 +228,7 @@ ifneq "$(CONFIG_COMMON_RUNTIME)" "y" CPPFLAGS+=$(foreach irq,$(_irq_list),\ -D"irq_$(irq)_handler_optional=irq_$(irq)_handler") endif +endif # Compute RW firmware size and offset _rw_off_str:=$(shell echo "CONFIG_RW_MEM_OFF" | $(CPP) $(CPPFLAGS) -P \ @@ -255,7 +266,13 @@ include $(BASEDIR)/build.mk ifneq ($(BASEDIR),$(BDIR)) include $(BDIR)/build.mk endif +ifeq ($(USE_BUILTIN_STDLIB), 1) +include builtin/build.mk +else +include libc/build.mk +endif include chip/$(CHIP)/build.mk +include core/build.mk include core/$(CORE)/build.mk include common/build.mk include driver/build.mk @@ -273,6 +290,12 @@ include test/build.mk include util/build.mk include util/lock/build.mk + +ifeq ($(CONFIG_BORINGSSL_CRYPTO), y) +include third_party/boringssl/common/build.mk +include crypto/build.mk +endif + includes+=$(includes-y) # Wrapper for fetching all the sources relevant to this build @@ -294,6 +317,11 @@ ifneq ($(PBDIR),) all-obj-$(1)+=$(call objs_from_dir_p,$(PBDIR),board-private,$(1)) endif all-obj-$(1)+=$(call objs_from_dir_p,common,common,$(1)) +ifeq ($(USE_BUILTIN_STDLIB), 1) +all-obj-$(1)+=$(call objs_from_dir_p,builtin,builtin,$(1)) +else +all-obj-$(1)+=$(call objs_from_dir_p,libc,libc,$(1)) +endif all-obj-$(1)+=$(call objs_from_dir_p,driver,driver,$(1)) all-obj-$(1)+=$(call objs_from_dir_p,power,power,$(1)) ifdef CTS_MODULE @@ -304,17 +332,61 @@ all-obj-$(1)+=$(call objs_from_dir_p,fuzz,$(PROJECT),$(1)) else all-obj-$(1)+=$(call objs_from_dir_p,test,$(PROJECT),$(1)) endif +ifeq ($(CONFIG_BORINGSSL_CRYPTO), y) +all-obj-$(1)+= \ + $(call objs_from_dir_p,third_party/boringssl/common,boringssl,$(1)) +all-obj-$(1)+= $(call objs_from_dir_p,crypto,crypto,$(1)) +endif endef # Get all sources to build $(eval $(call get_sources,y)) $(eval $(call get_sources,ro)) +# The following variables are meant to be initialized in the baseboard or +# board's build.mk. They will later be appended to in util/build.mk with +# utils that should be generated for all boards. +# +# build-util-bin-y - Utils for the system doing the "build". +# For example, the 64-bit x86 GNU/Linux running make. +# These are often program that are needed by the build +# system to generate code for use in firmware. +# host-util-bin-y - Utils for the target platform on top of the EC. +# For example, the 32-bit x86 Chromebook. +# build-util-art-y - Build ?artifacts? for the system doing the "build" +# +# The util targets added to these variable will pickup extra build objects +# from their optional -objs make variable. +# +# See commit bc4c1b4 for more context. +build-utils := $(call objs_from_dir,$(out)/util,build-util-bin) +ifeq ($(BOARD),host) +host-utils := $(call objs_from_dir,$(out)/util,host-util-bin) +host-utils-cxx := $(call objs_from_dir,$(out)/util,host-util-bin-cxx) +endif +build-art := $(call objs_from_dir,$(out),build-util-art) +# Use the util_name with an added .c AND the special -objs variable. +build-srcs := $(foreach u,$(build-util-bin-y),$(sort $($(u)-objs:%.o=util/%.c) \ + $(wildcard util/$(u).c))) +host-srcs := $(foreach u,$(host-util-bin-y),$(sort $($(u)-objs:%.o=util/%.c) \ + $(wildcard util/$(u).c))) +host-srcs-cxx := $(foreach u,$(host-util-bin-cxx-y), \ + $(sort $($(u)-objs:%.o=util/%.cc) $(wildcard util/$(u).cc))) + dirs=core/$(CORE) chip/$(CHIP) $(BASEDIR) $(BDIR) common fuzz power test \ cts/common cts/$(CTS_MODULE) $(out)/gen dirs+= private private-kandou $(PDIR) $(PBDIR) dirs+=$(shell find common -type d) dirs+=$(shell find driver -type d) +ifeq ($(USE_BUILTIN_STDLIB), 1) +dirs+=builtin +else +dirs+=libc +endif +ifeq ($(CONFIG_BORINGSSL_CRYPTO), y) +dirs+=third_party/boringssl/common +dirs+=crypto +endif common_dirs=util ifeq ($(custom-ro_objs-y),) @@ -352,6 +424,7 @@ def_all_deps+=ro endif all_deps?=$(def_all_deps) all: $(all_deps) +compile-only: $(ro-objs) $(rw-objs) ro: override BLD:=RO ro: $(libsharedobjs_elf-y) $(out)/RO/$(PROJECT).RO.flat diff --git a/Makefile.ide b/Makefile.ide new file mode 100644 index 0000000000..a87ea0b809 --- /dev/null +++ b/Makefile.ide @@ -0,0 +1,143 @@ +# -*- makefile -*- +# vim: set filetype=make : +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Embedded Controller firmware build system - IDE support +# +# One caveat with this approach is that we still don't capture modified make +# variables that are associated with a specific build target, like the following: +# +# $(out)/RW/common/blah.o: CFLAGS += -g +# +# This is because our compile commands json targets will not match this rule. + +# If env EXTERNAL_TRUNK_PATH is defined, we use this to build the +# absolute path to the ec directory. Otherwise, we just take the abspath of ".". +ide-ec-path-ext = \ + $(if $(EXTERNAL_TRUNK_PATH),$(EXTERNAL_TRUNK_PATH)/src/platform/ec) +ide-ec-path-abs = $(abspath .) +ide-ec-path = $(or $(ide-ec-path-ext),$(ide-ec-path-abs)) + +# Clang doesn't support these GCC options. +ide-filters = -mno-sched-prolog -fconserve-stack + +# The complete compile_commands.json targets. +ide-compile-cmds-y = $(out)/RW/compile_commands.json +ide-compile-cmds-$(CONFIG_FW_INCLUDE_RO) += $(out)/RO/compile_commands.json +ide-compile-cmds-y += $(out)/util/compile_commands.json + +# All individual .compile_cmds.json targets. +ide-rw-objs = $(rw-objs:.o=.compile_cmd.json) +ide-ro-objs = $(ro-objs:.o=.compile_cmd.json) + +ide-build-utils = $(build-utils:=.compile_cmd.json) +ide-host-utils = $(host-utils:=.compile_cmd.json) +ide-host-utils-cxx = $(host-utils-cxx:=.compile_cmd.json) + +ide-utils = $(ide-build-utils) $(ide-host-utils) $(ide-host-utils-cxx) + +# The all-ide-compile-cmds target takes about 2 minutes using 8 cores when all +# work is replaced by the |true| command. Thus, the build system itself +# takes 2m independent of the text manipulation. +.PHONY: all-ide-compile-cmds +all-ide-compile-cmds: $(foreach b, $(BOARDS), ide-compile-cmds-$(b)) +ide-compile-cmds-%: + $(MAKE) BOARD=$* V=$(V) ide-compile-cmds + +.PHONY: ide-compile-cmds +ide-compile-cmds: $(ide-compile-cmds-y) + +# All but the last file/json-object need to have a trailing comma. +# +# The first sed line prepends 4 spaces to all lines and then adds a +# comma + implicit-newline to the end of the last line of the file. +# The second sed line prepends 4 spaces to all lines and then adds an +# implicit new line. +cmd_combine_compile_cmd_json = \ + printf '[\n' >$@ ;\ + echo $^ | xargs -n1 | head -n-1 | xargs -n1 sed 's/^/ /;$$s/$$/,/' \ + >>$@ ;\ + sed 's/^/ /' $(lastword $^) >>$@ ;\ + printf ']\n' >>$@ ; + +$(out)/RW/compile_commands.json: override BLD := RW +$(out)/RW/compile_commands.json: private objs := $(rw-objs) +$(out)/RW/compile_commands.json: $(ide-rw-objs) +$(out)/RW/compile_commands.json: $(ide-utils) + $(call quiet,combine_compile_cmd_json,COMBINE) +$(out)/RO/compile_commands.json: override BLD := RO +$(out)/RO/compile_commands.json: private objs := $(ro-objs) +$(out)/RO/compile_commands.json: $(ide-ro-objs) +$(out)/RO/compile_commands.json: $(ide-utils) + $(call quiet,combine_compile_cmd_json,COMBINE) +$(out)/util/compile_commands.json: $(ide-utils) + $(call quiet,combine_compile_cmd_json,COMBINE) + +# Quote all words and add a comma between words. +# The quotes are applied as \", so that they will escape shell removal. +# +# $(1) - The space separated list of words. +ide-comma = , +ide-space = $() $() +ide-esc-quoted = $(patsubst %,\"%\",$(1)) +cmd_json_list = $(subst $(ide-space),$(ide-comma)$(ide-space),$(ide-esc-quoted)) + +# Replace any ".compile_cmd.json" with ".o" and filter out $(ide-filters) words. +# The replace is needed because we are invoking build commands from within our +# make rules that have targets set to files of type .compile_cmd.json. +# The compile commands will use special variables that pull this name into +# the command. +# +# $(1) - The compilation command. +# $(2) - The original target extension, like ".o" or "". +cmd_rep_filter = $(subst .compile_cmd.json,$(2),$(filter-out $(ide-filters),$(1))) + +# Form a compile command JSON block. +# +# $(1) - Used by quiet function, but it is this command name. +# $(2) - Used by quiet function, but it is the pretty action label. +# $(3) - The compilation command to place in the JSON blob. +# $(4) - The original target extension, like ".o" or "". +# $(5) - The source file this compile command applies to. +cmd_to_compile_cmd_json = \ + printf '{\n' >$@ ;\ + printf ' "arguments": [\n' >>$@ ;\ + printf ' %s\n' \ + $(call cmd_json_list,$(call cmd_rep_filter,$(3),$(4))) >>$@ ;\ + printf ' ],\n' >>$@ ;\ + printf ' "directory": "$(ide-ec-path)",\n' >>$@ ;\ + printf ' "file": "$(5)"\n' >>$@ ;\ + printf '}\n' >>$@ ; + +# Disable ccache, since this is only going to control whether the ccache +# executable shows in the compile_commands.json file. +%.compile_cmd.json: CCACHE := + +$(out)/RO/%.compile_cmd.json:%.c + $(call quiet,to_compile_cmd_json,JSON ,$(cmd_c_to_o),.o,$<) +$(out)/RW/%.compile_cmd.json:%.c + $(call quiet,to_compile_cmd_json,JSON ,$(cmd_c_to_o),.o,$<) + +$(out)/RO/%.compile_cmd.json:%.cc + $(call quiet,to_compile_cmd_json,JSON ,$(cmd_cxx_to_o),.o,$<) +$(out)/RW/%.compile_cmd.json: %.cc + $(call quiet,to_compile_cmd_json,JSON ,$(cmd_cxx_to_o),.o,$<) + +$(out)/RO/%.compile_cmd.json:%.S + $(call quiet,to_compile_cmd_json,JSON ,$(cmd_c_to_o),.o,$<) +$(out)/RW/%.compile_cmd.json:%.S + $(call quiet,to_compile_cmd_json,JSON ,$(cmd_c_to_o),.o,$<) + +$(ide-build-utils): $(out)/%.compile_cmd.json:$(build-srcs) + $(call quiet,to_compile_cmd_json,JSON ,$(cmd_c_to_build),\ + $(EMPTY),$*.c) + +$(ide-host-utils): $(out)/%.compile_cmd.json:$(host-srcs) + $(call quiet,to_compile_cmd_json,JSON ,$(cmd_c_to_host),\ + $(EMPTY),$*.c) + +$(ide-host-utils-cxx): $(out)/%.compile_cmd.json:$(host-srcs-cxx) + $(call quiet,to_compile_cmd_json,JSON ,$(cmd_cxx_to_host),\ + $(EMPTY),$*.cc) diff --git a/Makefile.rules b/Makefile.rules index e8c9ebec62..16c24e16f7 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -1,6 +1,6 @@ # -*- makefile -*- # vim: set filetype=make : -# Copyright 2012 The Chromium OS Authors. All rights reserved. +# Copyright 2012 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,12 +10,6 @@ FLATSIZE_FILE ?= .sizes.txt BUILD_DIR := $(firstword $(subst /, ,$(out))) -build-utils := $(foreach u,$(build-util-bin),$(out)/util/$(u)) -host-utils := $(foreach u,$(host-util-bin),$(out)/util/$(u)) -build-art := $(foreach u,$(build-util-art),$(out)/$(u)) -build-srcs := $(foreach u,$(build-util-bin),$(sort $($(u)-objs:%.o=util/%.c) $(wildcard util/$(u).c))) -host-srcs := $(foreach u,$(host-util-bin),$(sort $($(u)-objs:%.o=util/%.c) $(wildcard util/$(u).c))) - # Don't do a build test on the following boards: skip_boards = OWNERS cr50 host boards := $(filter-out $(skip_boards),$(notdir $(wildcard board/* private*/board/*))) @@ -34,25 +28,30 @@ _dir_create := $(foreach d,$(dirs) $(dirs-y),\ # Note: if cmd_* includes a $(MAKE) invocation, use the '+' prefix # to inherit parallel make execution: "+$(call quiet,...)" ifeq ($(V),0) +# V=0 Q := @ echo = echo -n; quiet = echo -n; $(cmd_$(1)) silent = 1>/dev/null silent_err = 2>/dev/null MAKEFLAGS += --no-print-directory -else -echo = echo $(1); -ifeq ($(V),) +else ifeq ($(V),) +# V= Q := @ -quiet = @echo ' $(2)' $(patsubst $(out)/%,%,$@) ; $(cmd_$(1)) +echo = echo $(1); +echo-cmd = $(if $(quiet_cmd_$(1)), \ + $(quiet_cmd_$(1)), \ + $(2) $(patsubst $(out)/%,%,$@)) +quiet = @echo ' $(echo-cmd)' ; $(cmd_$(1)) silent = 1>/dev/null silent_err = 2>/dev/null MAKEFLAGS += --no-print-directory else +# V=* Q := +echo = echo $(1); quiet = $(cmd_$(1)) endif -endif # Provide an option to use a consistent ec_version.h file when # compiling, which is useful to verify that a commit does not modify @@ -87,15 +86,24 @@ cmd_elf_to_hex = $(OBJCOPY) -O ihex $< $@ cmd_bin_to_hex = $(OBJCOPY) -I binary -O ihex \ --change-addresses $(_program_memory_base) $^ $@ cmd_smap = $(NM) $< | sort > $@ -cmd_elf = $(CC) $(objs) $(libsharedobjs_elf-y) $(LDFLAGS) \ +cmd_elf = $(COMPILER) $(objs) $(libsharedobjs_elf-y) $(LDFLAGS) \ -o $@ -Wl,-T,$< -Wl,-Map,$(patsubst %.elf,%.map,$@) +ifeq ($(cc-name),gcc) +cmd_elf+= -flto-partition=one +endif +ifneq ($(MEMSIZE_FLAGS),) +cmd_elf+= $(MEMSIZE_FLAGS) >$@.memsize.txt +endif + cmd_fuzz_exe = $(CXX) $^ $(HOST_TEST_LDFLAGS) $(LDFLAGS_EXTRA) -o $@ cmd_run_fuzz = build/host/$*/$*.exe -seed=1 -runs=1 $(silent) \ $(silent_err) || (echo "Test $* failed!" && false) -cmd_exe = $(CC) $(ro-objs) $(HOST_TEST_LDFLAGS) $(LDFLAGS_EXTRA) -o $@ -cmd_c_to_o = $(CC) $(C_WARN) $(CFLAGS) -MMD -MP -MF $@.d -c $< \ +cmd_exe = $(CXX) $(ro-objs) $(HOST_TEST_LDFLAGS) $(LDFLAGS_EXTRA) -o $@ +cmd_c_to_o = $(CC) -std=gnu11 $(C_WARN) $(CFLAGS) -MMD -MP -MF $@.d -c $< \ + -MT $(@D)/$(@F) -o $(@D)/$(@F) +cmd_c_to_s = $(CC) -S $(C_WARN) $(CFLAGS) -fno-lto -MMD -MP -MF $@.d -c $< \ -MT $(@D)/$(@F) -o $(@D)/$(@F) -cmd_cxx_to_o = $(CXX) -std=c++11 $(CFLAGS) $(CXXFLAGS) -MMD -MP -MF $@.d -c $< \ +cmd_cxx_to_o = $(CXX) -std=gnu++17 $(CFLAGS) $(CXXFLAGS) -MMD -MP -MF $@.d -c $< \ -MT $(@D)/$(@F) -o $(@D)/$(@F) cmd_c_to_build = $(BUILDCC) $(BUILD_CFLAGS) \ $(sort $(foreach c,$($(*F)-objs),util/$(c:%.o=%.c)) $(wildcard $*.c)) \ @@ -105,11 +113,12 @@ cmd_c_to_vif = $(BUILDCC) $(BUILD_CFLAGS) $(STANDALONE_FLAGS) \ -MMD -MF $@.d -c $< -flto -MT $@ -o $@ cmd_c_to_host = $(HOSTCC) $(HOST_CFLAGS) -MMD -MF $@.d -MT $@ -o $@ \ $(sort $(foreach c,$($(*F)-objs),util/$(c:%.o=%.c)) $(wildcard $*.c)) $(HOST_LDFLAGS) -cmd_cxx_to_host = $(HOSTCXX) -std=c++0x $(COMMON_WARN) $(HOST_CXXFLAGS)\ - -I ./$($(notdir $@)_ROOT) -o $@ $(filter %.cc,$^) $($(notdir $@)_LIBS) +cmd_cxx_to_host = $(HOSTCXX) -std=gnu++17 $(HOST_CXXFLAGS) \ + -MMD -MF $@.d -MT $@ -o $@ \ + $(sort $(foreach c,$($(*F)-objs),util/$(c:%.o=%.cc)) $(wildcard $*.cc)) $(HOST_LDFLAGS) cmd_o_to_a = $(AR) rcs $@ $^ cmd_host_test = $(MAKE) BOARD=host PROJECT=$* \ - V=$(V) out=build/host/$* TEST_BUILD=y EMU_BUILD=y CROSS_COMPILE= \ + V=$(V) out=build/host/$* TEST_BUILD=y EMU_BUILD=y \ $(if $(TEST_SCRIPT),TEST_SCRIPT=$(TEST_SCRIPT)) $(TEST_FLAG) \ build/host/$*/$*.exe cmd_coverage_test = $(subst build/host,build/coverage,$(cmd_host_test)) @@ -118,12 +127,13 @@ cmd_run_coverage_test = ./util/run_host_test --coverage $* $(silent) # generate new version.h, compare if it changed and replace if so cmd_version = ./util/getversion.sh > $@.tmp && \ cmp -s $@.tmp $@ && rm -f $@.tmp || mv $@.tmp $@ -cmd_vif = $(out)/util/genvif -b $(BOARD) -o $(out) +cmd_vif = $(out)/util/genvif -b $(BOARD) -o $(out) \ + -v board/$(BOARD)/vif_override.xml cmd_mv_from_tmp = mv $(out)/$*.bin.tmp $(out)/$*.bin cmd_extractrw-y = dd if=$(out)/$(PROJECT).bin.tmp of=$(out)/$(PROJECT).RW.bin \ bs=1 count=$(_rw_size) skip=$(_rw_off) $(silent_err) cmd_copyrw-y = cd $(out) && cp RW/$(PROJECT).RW.flat RW/$(PROJECT).RW.bin -cmd_sharedlib_elf = $(CC) $(libsharedobjs_deps) \ +cmd_sharedlib_elf = $(COMPILER) $(libsharedobjs_deps) \ -Wl,-T,common/ec.$(SHOBJLIB).ld $(LDFLAGS) \ -o $(out)/$(SHOBJLIB)/$(SHOBJLIB).elf \ -Wl,-Map,$(out)/$(SHOBJLIB)/$(SHOBJLIB).map @@ -143,11 +153,6 @@ cmd_emmc_bootblock = $(out)/util/gen_emmc_transfer_data \ cmd_ipi_table = $(out)/util/gen_ipi_table $@ cmd_cp_script = cp "$<" "$@" && chmod +x "$@" -cmd_libcryptoc_make = $(MAKE) -C $(CRYPTOCLIB) \ - obj=$(realpath $(out))/cryptoc \ - SUPPORT_UNALIGNED=1 -cmd_libcryptoc = $(cmd_libcryptoc_make) -q || $(cmd_libcryptoc_make) - # commands for RSA signature: rwsig does not need to sign the whole image # (it signs the RW part separately). usbpd1 type needs to sign the final image. ifeq ($(CONFIG_RWSIG_TYPE_RWSIG),) @@ -163,7 +168,7 @@ cmd_rsasign_rwsig = futility sign --type rwsig \ # commands to build optional xref files cmd_deps_to_list = cat $(deps) | tr -d ':\\' | tr ' ' '\012' \ - | egrep '\.[chS]$$' | sort | uniq > $@ + | grep -E '\.[chS]$$' | sort | uniq > $@ cmd_etags = etags -o $@ $(shell cat $<) cmd_ctags = ctags -o $@ $(shell cat $<) targ_if_prog = $(if $(shell which $(1) 2>/dev/null),$(2),) @@ -198,8 +203,13 @@ build_boards: | $(FAILED_BOARDS_DIR) @rm -f $(FAILED_BOARDS_DIR)/* $(MAKE) try_build_boards +.PHONY: check_undef +check_undef: + $(call quiet,check_undef) + .PHONY: buildall_only -buildall_only: build_boards build_cros_ec_commands +buildall_only: build_boards build_cros_ec_commands check_undef + $(MAKE) BOARD=host utils $(MAKE) build_cts $(MAKE) buildfuzztests @@ -230,6 +240,48 @@ print-boards: $(call cmd_pretty_print_list,\ $(sort $(boards))) +# The zephyr path can be overridden on invocation, as in the following example: +# $ make ZEPHYR_BASE=~/zephyr/main BOARD=dartmonkey +ZEPHYR_BASE ?= $(abspath ../../../src/third_party/zephyr/main) +export ZEPHYR_BASE + +ifeq ($(ALLOW_CONFIG),) + +# These are options defined by both ECOS and Zephyr. We need to tolerate this +# rather than begging the user to drop them from config_allowed since when the +# Zephyr Kconfig is not available (-I argument below does not point to the right +# place), they will not be considered a problem. +# You may add new options here if needed, although this should only occur if +# Zephyr upstream happens to add the same option, since we are requiring new +# ECOS options to have a corresponding Kconfig anyway. +conflicting_options := \ + ADC \ + AUDIO_CODEC \ + DAC \ + DMA \ + EEPROM \ + I2C_BITBANG \ + INA219 \ + MPU \ + PECI \ + PS2 \ + SMBUS \ + SPI \ + UART_CONSOLE + +cmd_check_allowed = ./util/kconfig_check.py -c ${config} \ + -a util/config_allowed.txt -p PLATFORM_EC_ -s "" \ + -I "${ZEPHYR_BASE}" \ + $(foreach opt,$(conflicting_options),-i $(opt)) check +cmd_check_undef = ./util/kconfig_check.py -s "" -I "${ZEPHYR_BASE}" \ + check_undef +else +cmd_check_allowed = true +cmd_check_undef = true +endif +quiet_cmd_check_allowed = CHECK_ALLOWED ${config} +quiet_cmd_check_undef = CHECK_UNDEF + # Print any important notices at the end of the build. .PHONY: notice notice: $(config) @@ -240,6 +292,7 @@ ifeq ($(TEST_BUILD),) @echo "directory! Otherwise, you won't be able to enter any commands." endif # not a TEST_BUILD endif # CONFIG_EXPERIMENTAL_CONSOLE=y + $(call quiet,check_allowed) proj-%: | $(FAILED_BOARDS_DIR) @touch $(FAILED_BOARDS_DIR)/$* @@ -266,13 +319,21 @@ hex: $(hex-y) utils-art: $(build-art) .PHONY: utils-host -utils-host: $(host-utils) +ifeq ($(BOARD),host) +utils-host: $(host-utils) $(host-utils-cxx) +else +utils-host: + $(error Building utils-host not supported when BOARD is not "host") +endif .PHONY: utils-build utils-build: $(build-utils) .PHONY: utils -utils: utils-host utils-build utils-art +utils: utils-build utils-art +ifeq ($(BOARD),host) +utils: utils-host +endif # On board test binaries test-targets=$(foreach t,$(test-list-y),test-$(t)) @@ -334,8 +395,7 @@ run-fuzz-test-targets=$(foreach t,$(fuzz-test-list-host),run-$(t)) $(fuzz-test-targets): TEST_FLAG=TEST_FUZZ=y TEST_ASAN=$(TEST_ASAN) \ TEST_MSAN=$(TEST_MSAN) TEST_UBSAN=$(TEST_UBSAN) \ - CROSS_COMPILE=$(shell echo $(HOSTCC) | grep -v ccache | \ - sed -e 's/[^-]*$$//') + CROSS_COMPILE=$(HOST_CROSS_COMPILE) $(fuzz-test-targets): host-%: | $(FAILED_BOARDS_DIR) @touch $(FAILED_BOARDS_DIR)/test-$* +$(call quiet,host_test,BUILD ) @@ -359,7 +419,7 @@ hosttests: $(host-test-targets) runhosttests: TEST_FLAG=TEST_HOSTTEST=y runhosttests: $(run-test-targets) runfuzztests: $(run-fuzz-test-targets) -runtests: runhosttests runfuzztests +runtests: runhosttests runfuzztests run-genvif_test # Automatically enumerate all suites. cts_excludes := common @@ -394,14 +454,21 @@ $(foreach b, $(cts_boards), \ ) \ ) +cov-boards=lazor volteer cov-test-targets=$(foreach t,$(cov-test-list-host),build/coverage/$(t).info) +cov-initial-targets=$(foreach t,$(cov-boards),build/coverage/initial-$(t).info) bldversion=$(shell (./util/getversion.sh ; echo VERSION) | $(CPP) -P -) -# lcov fails when multiple instances run at the same time. -# We need to run them sequentially by using flock -cmd_lcov=flock /tmp/ec-lcov-lock -c "lcov -q -o $@ -c -d build/coverage/$*" -cmd_report_cov=genhtml -q -o build/coverage/coverage_rpt -t \ - "EC Unittest "$(bldversion) $^ +cmd_lcov=lcov --rc lcov_branch_coverage=1 --gcov-tool \ + $(HOSTGCOV) -q -o $@ -c -d build/coverage/$* -t $* \ + --exclude '*/ec/test/*' --exclude '*/ec/include/tests/*' +cmd_lcov-initial=lcov --rc lcov_branch_coverage=1 --gcov-tool \ + $(GCOV) -q -o $@ -c -d build/coverage/initial-$* \ + -i -t $* --exclude '*/ec/test/*' --exclude '*/ec/include/tests/*' +cmd_merge_cov=lcov --rc lcov_branch_coverage=1 -o build/coverage/lcov.info \ + $(foreach info,$^,-a ${info}) +cmd_report_cov=genhtml --branch-coverage -q -o build/coverage/coverage_rpt -t \ + "EC Unittest "$(bldversion) -s $^ # Unless V is set to 0 we always want the 'size:' target to report its output, # there is no point in generating a short form command trace when calculating @@ -411,9 +478,9 @@ ifeq ($(V),0) cmd_size= else cmd_size=$(Q)awk '\ - /__flash_used =/ {flash_used = strtonum($$1)} \ - /^FLASH/ {flash_size = strtonum($$3)} \ - /__ram_free =/ {ram_free = strtonum($$1)} \ + /__flash_used/ {flash_used = strtonum("0x" $$1)} \ + /__flash_size/ {flash_size = strtonum("0x" $$1)} \ + /__ram_free/ {ram_free = strtonum("0x" $$1)} \ END {room_free = flash_size - flash_used; \ print ram_free > "$(out)/$(1)/space_free_ram.txt"; \ printf " *** "; \ @@ -423,7 +490,7 @@ cmd_size=$(Q)awk '\ } \ printf ("%s bytes in RAM still available on $(BOARD) $(1) ****\n", \ ram_free) \ - }' $(out)/$(1)/$(PROJECT).$(1).map + }' $(out)/$(1)/$(PROJECT).$(1).smap endif # List the smallest free flash spaces @@ -437,12 +504,21 @@ cmd_stats= \ printf "%-10s: %6d\n" $$board $$size; \ done +.DELETE_ON_ERROR: build/coverage/initial-%.info build/coverage/%.info +build/coverage/initial-%.info: + $(MAKE) TEST_COVERAGE=y BOARD=$* compile-only + $(call quiet,lcov-initial,COV ) build/coverage/%.info: run-coverage-% $(call quiet,lcov,COV ) -.PHONY: coverage +.PHONY: coverage test-coverage coverage: TEST_FLAG=TEST_COVERAGE=y -coverage: $(cov-test-targets) +coverage: $(cov-test-targets) $(cov-initial-targets) + $(call quiet,merge_cov,MERGE ) + $(call quiet,report_cov,REPORT ) +test-coverage: TEST_FLAG=TEST_COVERAGE=y +test-coverage: $(cov-test-targets) + $(call quiet,merge_cov,MERGE ) $(call quiet,report_cov,REPORT ) $(out)/libec.a: $(ro-objs) @@ -463,7 +539,7 @@ $(out)/%.bin: $(out)/%.obj $(call quiet,copyrw-y,COPY_RW)) $(call quiet,mv_from_tmp,MV ) -$(out)/$(BOARD)_vif.txt: $(out)/util/genvif +$(out)/$(BOARD)_vif.xml: $(out)/util/genvif board/$(BOARD)/vif_override.xml $(call quiet,vif,VIF ) flat-y := $(out)/RW/$(PROJECT).RW.flat @@ -554,6 +630,11 @@ $(out)/RO/%.o:%.c $(out)/RW/%.o:%.c $(call quiet,c_to_o,CC ) +$(out)/RO/%.s:%.c + $(call quiet,c_to_s,CC ) +$(out)/RW/%.s:%.c + $(call quiet,c_to_s,CC ) + $(out)/RO/%.o:%.cc $(call quiet,cxx_to_o,CXX ) $(out)/RW/%.o:%.cc @@ -616,6 +697,9 @@ $(build-utils): $(out)/%:$(build-srcs) $(host-utils): $(out)/%:$(host-srcs) $(call quiet,c_to_host,HOSTCC ) +$(host-utils-cxx): $(out)/%:$(host-srcs-cxx) + $(call quiet,cxx_to_host,HOSTCXX ) + $(out)/cscope.files: $(out)/$(PROJECT).bin $(call quiet,deps_to_list,SH ) @@ -642,14 +726,14 @@ $(npcx-monitor-fw-bin):$(npcx-monitor-fw).c npx-monitor-dir $(Q)$(OBJCOPY) -O binary $(out)/$(npcx-monitor-fw).elf $@ $(out)/$(npcx-monitor-hdr)_ro.o:$(npcx-monitor-hdr).c npx-monitor-dir - $(Q)$(CC) $(CFLAGS) -DSECTION_IS_RO=$(EMPTY) -MMD -c $< -MT $@ -o $@ + $(Q)$(CC) $(CFLAGS) -DSECTION_IS_RO=$(EMPTY) -MMD -fno-lto -c $< -MT $@ -o $@ $(npcx-monitor-hdr-ro-bin):$(out)/$(npcx-monitor-hdr)_ro.o $(if $(V),,@echo ' EXTBIN ' $(subst $(out)/,,$@) ; ) $(Q)$(OBJCOPY) -O binary $< $@ $(out)/$(npcx-monitor-hdr)_rw.o:$(npcx-monitor-hdr).c npx-monitor-dir - $(Q)$(CC) $(CFLAGS) -MMD -c $< -MT $@ -o $@ + $(Q)$(CC) $(CFLAGS) -MMD -fno-lto -c $< -MT $@ -o $@ $(npcx-monitor-hdr-rw-bin):$(out)/$(npcx-monitor-hdr)_rw.o $(if $(V),,@echo ' EXTBIN ' $(subst $(out)/,,$@) ; ) @@ -676,6 +760,14 @@ flash_ec: $(out)/ec.bin flash_dfu: $(out)/ec.bin sudo ./$(BDIR)/dfu $(out)/ec.bin +.PHONY: print-all-baseboards +print-all-baseboards: $(foreach b, $(BOARDS), print-baseboard-$(b)) +print-baseboard-%: + @$(MAKE) BOARD=$* V=$(V) print-one-baseboard +.PHONY: print-one-baseboard +print-one-baseboard: + @echo "${BOARD}=${BASEBOARD}" + # Deprecated, use print-make-vars instead .PHONY: print-baseboard print-baseboard: @@ -732,41 +824,57 @@ endif .PHONY: help help: @echo "Google Chromium EC build" + @echo "" @echo "Common Targets:" @echo " all [BOARD=] - Build a single board (Default target)" @echo " clean [BOARD=] - Clean a single board" - @echo " buildall - Build and test all boards" + @echo " buildall - Build all boards and build/run host unit tests" + @echo " buildall_only - Build all boards and host unit tests" + @echo " build_boards - Build all boards" @echo " clobber - Clean all boards" @echo " proj- - Build a single board (similar to 'all BOARD=boardname')" @echo " savesizes - Save the filesizes of currently built boards for comparison" @echo " newsizes - Compare previously saved filesizes against new sizes" - @echo " utils - Build all host utilities" + @echo " utils [BOARD=] - Build all host side utilities" + @echo " dis [BOARD=] - Generate the complete disassembly of the RO and RW images" + @echo " hex [BOARD=] - Generate an Intel hex formated output binary" @echo "" - @echo " tests [BOARD=] - Build all unit tests for a specific board" + @echo " tests [BOARD=] - Build all on-device unit tests for a specific board" @echo " hosttests - Build all host unit tests" @echo " runhosttests - Build and run all host unit tests" @echo " coverage - Build and run all host unit tests for code coverage" @echo " buildfuzztests - Build all host fuzzers" @echo " runfuzztests - Build and run all host fuzzers for one round" + @echo " analyzestack [BOARD=]- Run max stack size analysis" @echo "" @echo " flash [BOARD=] - Use OpenOCD to flash the latest image" @echo " flash_ec [BOARD=] - Use flash_ec to flash the latest image" @echo " flash_dfu [BOARD=] - Use DFU to flash the latest image" @echo "" - @echo " print-tests - Prints all device specific test targets" - @echo " print-host-tests - Prints all host test targets" - @echo " print-host-fuzzers - Prints all host fuzz targets" - @echo " print-boards - Prints all boards" - @echo " print-configs [BOARD=] - Print CONFIG_* options for the target board" - @echo " print-defines [BOARD=] - Print forced defines passed to the compiler" - @echo " print-includes [BOARD=] - Print include paths passed to the compiler" + @echo " print-tests [BOARD=] - Print on-device test targets" + @echo " print-host-tests - Print all host unit test targets" + @echo " print-host-fuzzers - Print all host fuzz targets" + @echo " print-boards - Print all boards" + @echo " print-configs [BOARD=] - Print CONFIG_* options for the target board" + @echo " print-defines [BOARD=] - Print forced defines passed to the compiler" + @echo " print-includes [BOARD=] - Print include paths passed to the compiler" + @echo " print-baseboard [BOARD=] - Print include paths passed to the compiler" + @echo " print-make-vars [BOARD=] - Print chip/core/board make variables for a board" + @echo "" @echo "Common Variables:" @echo " V=1 - Show make output" @echo " BOARD= - Set the board name to build (Default is $(BOARD))" + @echo " STATIC_VERSION=1 - Force a constant version string for reproducable builds" + @echo " BUILDCC_PREFIX= - Set the compiler prefix for the system doing " + @echo " the build (defaults to 'x86_64-pc-linux-gnu-')." @echo " CROSS_COMPILE= - Set the compiler for the board" @echo " CROSS_COMPILE_arch= - Set the compiler for arch" @echo " The board picks its CROSS_COMPILE_arch if CROSS_COMPILE is not set." @echo " arch may be one of 'arm', 'i386', 'nds32'." + @echo " HOST_CROSS_COMPILE= - Set the compiler for the target platform on top of" + @echo " the EC. For example, this may be 32-bit x86 linux ('i686-pc-linux-gnu-')," + @echo " 64-bit x86 linux ('x86_64-pc-linux-gnu-'), or maybe 64-bit ARM linux" + @echo " ('aarch64-cros-linux-gnu-')." @echo "Example:" @echo " make BOARD=reef CROSS_COMPILE_arm='arm-eabi-'" @@ -874,6 +982,12 @@ build_cros_ec_commands: $(out_cros_ec_commands) $(out_cros_ec_commands): include/ec_commands.h util/make_linux_ec_commands_h.sh util/make_linux_ec_commands_h.sh $< $@ +# Include IDE configurations targets. +include Makefile.ide + +# Pull in special rules/targets for third_party software +-include third_party/rules.mk + .SECONDARY: -include $(deps) diff --git a/Makefile.toolchain b/Makefile.toolchain index 01252ba14f..a4ed9fb1de 100644 --- a/Makefile.toolchain +++ b/Makefile.toolchain @@ -1,12 +1,15 @@ # -*- makefile -*- -# Copyright 2012 The Chromium OS Authors. All rights reserved. +# Copyright 2012 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # -# Toolchain configuration build system -# - # Toolchain configuration +# +# BUILD - Refers to the system doing the "build". +# For example, you would compile servo_ectool to run on your local +# build machine. +# HOST - Refers to target platform on top of the EC. +# For example, you would compile ectool to run on the Chrome OS device. min_make_version:=3.82 make_version_ok:=$(filter $(min_make_version), \ @@ -20,34 +23,125 @@ ifneq ($(TEST_FUZZ)$(TEST_ASAN)$(TEST_MSAN)$(TEST_UBSAN),) CC=clang endif +# When set to 1, use the subset of the C standard library implemented in EC +# (the "builtin" directory). +# When set to 0, link against the toolchain's implementation of the C standard +# library. +USE_BUILTIN_STDLIB:=1 + +# When set to 1, link with the C++ compiler. +# When set to 0, link with the C compiler. +USE_CXX_COMPILER:=0 + +# Boards that compile with clang by default. +# We can't use a config for this since the config generation uses the compiler. +CLANG_BOARDS:= \ + bloonchipper \ + dartmonkey \ + hatch_fp \ + helipilot \ + nami_fp \ + nocturne_fp \ + nucleo-dartmonkey \ + nucleo-h743zi \ + nucleo-f412zg \ + +ifeq ($(filter $(BOARD), $(CLANG_BOARDS)), $(BOARD)) +CC=clang +USE_BUILTIN_STDLIB:=0 +USE_CXX_COMPILER:=1 +# b/144957935: Generate exception on signed integer overflow. +COMMON_WARN+=-ftrapv +endif + +ifeq ($(USE_CXX_COMPILER), 1) +COMPILER=$(CXX) +else +COMPILER=$(CC) +endif + +# Set the prefix for the compiler if specified (e.g., "x86_64-pc-linux-gnu-"). +ifeq ($(origin BUILDCC_PREFIX),undefined) +# If building with Portage use the environment variable it provides. +# https://wiki.gentoo.org/wiki/Embedded_Handbook/General/Introduction#Environment_variables +ifneq ($(CBUILD),) +BUILDCC_PREFIX:=$(CBUILD)- +else +BUILDCC_PREFIX:=x86_64-pc-linux-gnu- +endif +endif + # Extract cc-name -cc-name:=$(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc) +cc-name:=$(shell $(BUILDCC_PREFIX)$(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc) + +# Assume we want to use same compiler for both C and C++ +ifeq ($(cc-name),gcc) +cxx-name:=g++ +else +cxx-name:=clang++ +endif # Try not to assume too much about optional tools and prefixes CCACHE:=$(shell which ccache 2>/dev/null) ifeq ($(origin HOST_CROSS_COMPILE),undefined) -HOST_CROSS_COMPILE:=$(if $(shell which x86_64-pc-linux-gnu-gcc 2>/dev/null),x86_64-pc-linux-gnu-,) +# If building with Portage use the environment variable it provides. +# https://wiki.gentoo.org/wiki/Embedded_Handbook/General/Introduction#Environment_variables +ifneq ($(CHOST),) +HOST_CROSS_COMPILE:=$(CHOST)- +else +HOST_CROSS_COMPILE:=$(if $(shell which x86_64-pc-linux-gnu-$(cc-name) 2>/dev/null),x86_64-pc-linux-gnu-,) +endif endif AR=$(CROSS_COMPILE)ar CC=$(CCACHE) $(CROSS_COMPILE)$(cc-name) CPP=$(CC) -E -CXX=$(CROSS_COMPILE)clang++ +CXX=$(CROSS_COMPILE)$(cxx-name) LD=$(CROSS_COMPILE)ld NM=$(CROSS_COMPILE)nm OBJCOPY=$(CROSS_COMPILE)objcopy OBJDUMP=$(CROSS_COMPILE)objdump ADDR2LINE=$(CROSS_COMPILE)addr2line PKG_CONFIG?=pkg-config -BUILDCC?=$(CCACHE) gcc -HOSTCC?=$(CCACHE) $(HOST_CROSS_COMPILE)gcc -HOSTCXX?=$(CCACHE) $(HOST_CROSS_COMPILE)g++ +BUILD_PKG_CONFIG?=$(PKG_CONFIG) +BUILDCC?=$(CCACHE) $(BUILDCC_PREFIX)$(cc-name) +HOSTCC?=$(CCACHE) $(HOST_CROSS_COMPILE)$(cc-name) +HOSTCXX?=$(CCACHE) $(HOST_CROSS_COMPILE)clang++ +HOST_PKG_CONFIG?=$(HOST_CROSS_COMPILE)pkg-config PROTOC?=protoc +GCOV=$(CROSS_COMPILE)gcov +ifeq ($(cc-name),gcc) +HOSTGCOV=$(HOST_CROSS_COMPILE)gcov +else +HOSTGCOV=$(CURDIR)/util/llvm-gcov.sh +endif -C_WARN = -Wstrict-prototypes -Wdeclaration-after-statement -Wno-pointer-sign -COMMON_WARN = -Wall -Wundef -Werror -Werror-implicit-function-declaration \ +C_WARN = -Wstrict-prototypes -Wno-pointer-sign +C_WARN += -Werror-implicit-function-declaration +COMMON_WARN += -Wall -Wundef \ -Wno-trigraphs -Wno-format-security -Wno-address-of-packed-member \ - -fno-common -fno-strict-aliasing -fno-strict-overflow + -fno-common -fno-strict-aliasing -fno-strict-overflow -Wimplicit-fallthrough +# See https://www.chromium.org/chromium-os/build/c-exception-support +COMMON_WARN+=-fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables + +ifndef ALLOW_WARNINGS +COMMON_WARN+=-Werror +ifeq ($(cc-name),clang) +COMMON_WARN+=-Werror=uninitialized +endif +ifeq ($(cc-name),gcc) +COMMON_WARN+=-Werror=maybe-uninitialized +endif +endif + +ifeq ($(cc-name),clang) +# TODO(b/172020503): Re-enabling this warning requires a large CL. +C_WARN+= -Wno-ignored-attributes +# TODO(b/172020503): Re-enabling this warning requires the following large CLs: +# https://crrev.com/c/3223973 +# https://crrev.com/c/3227261 +COMMON_WARN+= -Wno-unused-function +endif UBSAN_FLAGS=-fsanitize=array-bounds,vla-bound \ -fno-sanitize=vptr \ @@ -57,8 +151,9 @@ CFLAGS_WARN = $(COMMON_WARN) $(C_WARN) CXXFLAGS_WARN = $(COMMON_WARN) CFLAGS_DEBUG= -g CFLAGS_DEBUG+=$(CFLAGS_DEBUG_CHIP) -CFLAGS_INCLUDE=$(foreach i,$(includes),-I$(i) ) -I. +CFLAGS_INCLUDE=$(foreach i,$(filter-out builtin, $(includes)),-I$(i) ) -I. CFLAGS_TEST=$(if $(TEST_BUILD),-DTEST_BUILD=$(EMPTY) \ + -DTEST_LEGACY_BUILD=$(EMPTY) \ -DTEST_TASKFILE=$(PROJECT).tasklist,) \ $(if $(CTS_MODULE), $(CFLAGS_CTS)) \ $(if $(EMU_BUILD),-DEMU_BUILD=$(EMPTY)) \ @@ -66,11 +161,11 @@ CFLAGS_TEST=$(if $(TEST_BUILD),-DTEST_BUILD=$(EMPTY) \ $(if $(TEST_ASAN),-fsanitize=address) \ $(if $(TEST_MSAN),-fsanitize=memory) \ $(if $(TEST_UBSAN),$(UBSAN_FLAGS)) \ - $(if $(TEST_FUZZ),-fsanitize=fuzzer-no-link \ - -fno-experimental-new-pass-manager -DTEST_FUZZ=$(EMPTY)) + $(if $(TEST_FUZZ),-fsanitize=fuzzer-no-link -fno-PIE \ + -DTEST_FUZZ=$(EMPTY)) CFLAGS_COVERAGE=$(if $(TEST_COVERAGE),--coverage \ -DTEST_COVERAGE=$(EMPTY),) -CFLAGS_HOSTTEST=$(if $(TEST_HOSTTEST),-DTEST_HOSTTEST=$(EMPTY),) +CFLAGS_HOSTTEST=$(if $(TEST_HOSTTEST),-DTEST_HOSTTEST=$(EMPTY),) -Iinclude/driver CFLAGS_DEFINE=-DOUTDIR=$(out)/$(BLD) -DCHIP=$(CHIP) -DBOARD_TASKFILE=$(_tsk_lst_file) \ -DBOARD=$(BOARD) -DCORE=$(CORE) -DPROJECT=$(PROJECT) \ -DCHIP_VARIANT=$(CHIP_VARIANT) -DCHIP_FAMILY=$(UC_CHIP_FAMILY) \ @@ -92,30 +187,46 @@ HOST_CPPFLAGS=$(CFLAGS_DEFINE) $(CFLAGS_INCLUDE) $(CFLAGS_TEST) \ $(EXTRA_CFLAGS) $(CFLAGS_COVERAGE) $(CFLAGS_HOSTTEST) $(LATE_CFLAGS_DEFINE) \ -DSECTION_IS_$(BLD)=$(EMPTY) -DSECTION=$(BLD) $(CPPFLAGS_$(BLD)) ifneq ($(BOARD),host) +CPPFLAGS+=-fno-PIC +ifeq ($(USE_BUILTIN_STDLIB), 1) CPPFLAGS+=-ffreestanding -fno-builtin -nostdinc -nostdlib CPPFLAGS+=-Ibuiltin/ +endif else CPPFLAGS+=-Og endif CPPFLAGS+= -DCHROMIUM_EC=$(EMPTY) CFLAGS=$(CPPFLAGS) $(CFLAGS_CPU) $(CFLAGS_DEBUG) $(COMMON_WARN) $(CFLAGS_y) -CFLAGS+= -ffunction-sections -fshort-wchar +CFLAGS+= -ffunction-sections CFLAGS+= -fno-delete-null-pointer-checks +CFLAGS+= -fno-PIC ifneq ($(cc-name),clang) CFLAGS+= -ffat-lto-objects CFLAGS+= -fconserve-stack endif +CXXFLAGS=$(CXXFLAGS_WARN) CXXFLAGS+=-DPROTOBUF_INLINE_NOT_IN_HEADERS=0 +ifeq ($(USE_BUILTIN_STDLIB), 1) +CPPFLAGS+=-DUSE_BUILTIN_STDLIB +endif +ifeq ($(LIBFTDI_NAME),) FTDIVERSION:=$(shell $(PKG_CONFIG) --modversion libftdi1 2>/dev/null) ifneq ($(FTDIVERSION),) LIBFTDI_NAME=ftdi1 else LIBFTDI_NAME=ftdi endif +endif + +LIBFTDIUSB_HOST_CFLAGS:=$(shell $(HOST_PKG_CONFIG) --cflags lib${LIBFTDI_NAME} libusb-1.0) +LIBFTDIUSB_HOST_LDLIBS:=$(shell $(HOST_PKG_CONFIG) --libs lib${LIBFTDI_NAME} libusb-1.0) + +LIBFTDIUSB_BUILD_CFLAGS:=$(shell $(BUILD_PKG_CONFIG) --cflags lib${LIBFTDI_NAME} libusb-1.0) +LIBFTDIUSB_BUILD_LDLIBS:=$(shell $(BUILD_PKG_CONFIG) --libs lib${LIBFTDI_NAME} libusb-1.0) -LIBFTDIUSB_CFLAGS:=$(shell $(PKG_CONFIG) --cflags lib${LIBFTDI_NAME} libusb-1.0) -LIBFTDIUSB_LDLIBS:=$(shell $(PKG_CONFIG) --libs lib${LIBFTDI_NAME} libusb-1.0) +LIBEC_HOST_CFLAGS:=$(shell $(HOST_PKG_CONFIG) --cflags libec) +LIBEC_HOST_LDLIBS:=$(shell $(HOST_PKG_CONFIG) --libs libec) ifeq ($(TEST_FUZZ),y) LIBPROTOBUF_CFLAGS:=$(shell $(PKG_CONFIG) --cflags protobuf) @@ -127,22 +238,37 @@ LIBPROTOBUF_MUTATOR_LDLIBS:=$(shell $(PKG_CONFIG) --libs libprotobuf-mutator) \ ${LIBPROTOBUF_LDLIBS} endif -BUILD_CFLAGS=$(LIBFTDIUSB_CFLAGS) $(BUILD_CPPFLAGS) -O3 $(CFLAGS_DEBUG) +BUILD_CFLAGS=$(LIBFTDIUSB_BUILD_CFLAGS) $(BUILD_CPPFLAGS) -O3 $(CFLAGS_DEBUG) BUILD_CFLAGS+=$(CFLAGS_WARN) BUILD_CFLAGS+=-DCHROMIUM_EC=$(EMPTY) HOST_CFLAGS=$(HOST_CPPFLAGS) -O3 $(CFLAGS_DEBUG) $(CFLAGS_WARN) \ -DHOST_TOOLS_BUILD=$(EMPTY) -HOST_CFLAGS+=$(LIBFTDIUSB_CFLAGS) +HOST_CFLAGS+=$(LIBFTDIUSB_HOST_CFLAGS) HOST_CFLAGS+=-DCHROMIUM_EC=$(EMPTY) +HOST_CXXFLAGS=$(HOST_CFLAGS) -Wno-c99-designator +HOST_CXXFLAGS+=$(LIBEC_HOST_CFLAGS) ifneq (${SYSROOT},) LDFLAGS_EXTRA+=--sysroot=${SYSROOT} endif -LDFLAGS=-nostdlib -g -Wl,-X -Wl,--gc-sections -Wl,--build-id=none \ +LDFLAGS=-g -no-pie -Wl,-X -Wl,--gc-sections -Wl,--build-id=none \ $(LDFLAGS_EXTRA) $(CFLAGS_CPU) -BUILD_LDFLAGS=$(LIBFTDIUSB_LDLIBS) -HOST_LDFLAGS=$(LIBFTDIUSB_LDLIBS) +ifeq ($(USE_BUILTIN_STDLIB), 1) +LDFLAGS+=-nostdlib +else +LDFLAGS+=-lnosys +endif +MEMSIZE_FLAGS= +ifeq ($(cc-name),gcc) +MEMSIZE_FLAGS+=-Wl,--print-memory-usage +endif +BUILD_LDFLAGS=$(LIBFTDIUSB_BUILD_LDLIBS) +HOST_LDFLAGS=$(LIBFTDIUSB_HOST_LDLIBS) +ifneq (${HOST_SYSROOT},) + HOST_LDFLAGS+=--sysroot=${HOST_SYSROOT} +endif +HOST_LDFLAGS+=$(LIBEC_HOST_LDLIBS) HOST_TEST_LDFLAGS=-Wl,-T core/host/host_exe.lds -lrt -pthread -rdynamic -lm\ - -fuse-ld=bfd \ + -no-pie -flto\ $(if $(TEST_COVERAGE), --coverage,) \ $(if $(TEST_ASAN), -fsanitize=address) \ $(if $(TEST_MSAN), -fsanitize=memory) \ diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg index 5d83f2b980..c925185270 100644 --- a/PRESUBMIT.cfg +++ b/PRESUBMIT.cfg @@ -1,22 +1,41 @@ [Hook Overrides] +black_check: true +clang_format_check: true branch_check: true checkpatch_check: true kerneldoc_check: true -signoff_check: true # We are using Linux style indentation with tabs # The indentation is checked by checkpatch not the python script tab_check: false [Hook Overrides Options] -checkpatch_check: --no-tree --ignore=MSLEEP,VOLATILE,SPDX_LICENSE_TAG +black_check: --include_regex=^util/chargen$ +branch_check: --optional +checkpatch_check: --no-tree --no-signoff --ignore=MSLEEP,VOLATILE,SPDX_LICENSE_TAG kerneldoc_check: --include_regex=\bec_commands\.h$ +keyword_check: --block=zassume_ cros_license_check : + --exclude_regex=^third_party/bmi220/ + --exclude_regex=^third_party/bmi260/ + --exclude_regex=^third_party/boringssl/ + --exclude_regex=^third_party/incbin/ + --exclude_regex=^third_party/libaeabi-cortexm0/ --exclude_regex=^third_party/linux/ + --exclude_regex=^third_party/sha2/ + --exclude_regex=^third_party/unacl-curve25519/ [Hook Scripts] -presubmit_check = util/presubmit_check.sh +cros lint = cros lint ${PRESUBMIT_FILES} +check_cprints = util/check_cprints.py --commit ${PRESUBMIT_COMMIT} ${PRESUBMIT_FILES} +check_ztest = util/check_ztest.py --commit ${PRESUBMIT_COMMIT} ${PRESUBMIT_FILES} config_option_check = util/config_option_check.py host_command_check = util/host_command_check.sh ec_commands_h = util/linux_ec_commands_h_check.sh +migrated_files = util/migrated_files.sh ${PRESUBMIT_FILES} +twister_test_tags = util/twister_tags.py --validate-files ${PRESUBMIT_FILES} +check_zephyr_project_config = util/check_zephyr_project_config.py -d ${PRESUBMIT_FILES} +zephyr_check_compliance = util/zephyr_check_compliance.py ${PRESUBMIT_COMMIT} +zephyr_check_testcase_yaml = ./util/zephyr_check_testcase_yaml.py --commit ${PRESUBMIT_COMMIT} ${PRESUBMIT_FILES} +low_coverage_reason = ./util/check_low_coverage_reason.py ${PRESUBMIT_COMMIT} diff --git a/README.md b/README.md index e3274487de..dacff1d4cc 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,20 @@ [TOC] +> **Note** - This document covers the legacy Chrome EC implementation. The +> legacy EC implementation is used by all Chromebook reference designs prior to +> July 2021. On newer Chromebook designs, the EC implementation is based on the +> Zephyr RTOS. Refer to the [Zephyr EC Introduction](./docs/zephyr/README.md) +> for details on the Zephyr EC implementation. + ## Introduction The Chromium OS project includes open source software for embedded controllers (EC) used in recent ARM and x86 based Chromebooks. This software includes a lightweight, multitasking OS with modules for power sequencing, keyboard control, thermal control, battery charging, and verified boot. The EC software -is written in C and supports [a variety of micro-controllers](https://chromium.googlesource.com/chromiumos/platform/ec/+/master/chip/). +is written in C and supports +[a variety of micro-controllers](https://chromium.googlesource.com/chromiumos/platform/ec/+/main/chip/). This document is a guide to help make you familiar with the EC code, current features, and the process for submitting code patches. @@ -25,8 +32,8 @@ and [video](http://youtu.be/Ie7LRGgCXC8) from the (inclusive). See the [Chrome OS devices](http://dev.chromium.org/chromium-os/developer-information-for-chrome-os-devices) page for a list. -1. A Linux development environment. Ubuntu 14.04 Trusty (x86_64) is well - supported. Linux in a VM may work if you have a powerful host machine. +1. A Linux development environment. The latest Debian Stable (x86_64) is commonly used. + Linux in a VM may work if you have a powerful host machine. 1. A [servo debug board](http://dev.chromium.org/chromium-os/servo) (and header) is highly recommended for serial console and JTAG access to the EC. 1. A sense of adventure! @@ -40,8 +47,8 @@ documentation due to historical reasons. If you just see the term "EC", it probably refers to "the" EC (i.e. the first one that existed). Most Chrome OS devices have an MCU, known as "the EC" that controls lots of things (key presses, turning the AP on/off). The OS that was written for "the" EC is now -running on several different MCUs on Chrome OS devices with various tweaks -(e.g. the FPMCU, the touchpad one that can do palm rejection, etc.). It's quite +running on several different MCUs on Chrome OS devices with various tweaks (e.g. +the FPMCU, the touchpad one that can do palm rejection, etc.). It's quite confusing, so try to be specific and use terms like FPMCU to distinguish the fingerprint MCU from "the EC". @@ -97,21 +104,18 @@ I2C/onewire LED controllers, and I2C temperature sensors. **util** - Host utilities and scripts for flashing the EC. Also includes “ectool” used to query and send commands to the EC from userspace. -**test** - Unit tests for EC components. These can be run locally in - a mock "host" environment or compiled for a target board. - If building for a target board, the test must be flashed and - run manually on the device. - All unit tests and fuzzers are build/run using the local - host environment during a `buildall`. - To run all unit tests locally, run `make runhosttests -j`. - To build a specific unit test for a specific board, run - `make test- BOARD=`. - Please contribute new tests if writing new functionality. - Please run `make help` for more detail. - -**fuzz** - Fuzzers for EC components. These fuzzers are expected to - run in the mock host environment. They follow the same rules - as unit tests, as thus use the same commands to build and run. +**test** - Unit tests for EC components. These can be run locally in a mock +"host" environment or compiled for a target board. If building for a target +board, the test must be flashed and run manually on the device. All unit tests +and fuzzers are build/run using the local host environment during a `buildall`. +To run all unit tests locally, run `make runhosttests -j`. To build a specific +unit test for a specific board, run `make test- BOARD=`. +Please contribute new tests if writing new functionality. Please run `make help` +for more detail. + +**fuzz** - Fuzzers for EC components. These fuzzers are expected to run in the +mock host environment. They follow the same rules as unit tests, as thus use the +same commands to build and run. ## Firmware Branches @@ -119,7 +123,7 @@ Each Chrome device has a firmware branch created when the read-only firmware is locked down prior to launch. This is done so that updates can be made to the read-write firmware with a minimal set of changes from the read-only. Some Chrome devices only have build targets on firmware branches and not on -cros/master. Run “`git branch -a | grep firmware`” to locate the firmware branch +cros/main. Run “`git branch -a | grep firmware`” to locate the firmware branch for your board. Note that for devices still under development, the board configuration may be on the branch for the platform reference board. @@ -153,11 +157,11 @@ branch1...branch2 as needed): git log --left-right --graph --cherry-pick --oneline branch1...branch2 ``` -For example, to see the difference between cros/master and the HEAD of the -current branch: +For example, to see the difference between cros/main and the HEAD of the current +branch: ```bash -git log --left-right --graph --cherry-pick --oneline cros/master...HEAD +git log --left-right --graph --cherry-pick --oneline cros/main...HEAD # Note: Use three dots “...” or it won’t work! ``` @@ -171,11 +175,11 @@ Building directly from the EC repository: ```bash cros_sdk -cd ~/trunk/src/platform/ec +cd ~/chromiumos/src/platform/ec make -j BOARD= ``` -Where **** is replaced by the name of the board you want to build an +Where `` is replaced by the name of the board you want to build an EC binary for. For example, the boardname for the Chromebook Pixel is “link”. The make command will generate an EC binary at `build//ec.bin`. The `-j` tells make to build multi-threaded which can be much faster on a multi-core @@ -206,8 +210,16 @@ The generated EC binary from emerge is found at: (chroot) $ /build//firmware/ec.bin ``` +or + +``` +(chroot) $ /build//firmware//ec.bin +``` + +The `devicename` is the name of a device (also referred as board or variant) which belongs to a family of baseboard. `boardname` is the baseboard name in this case. Example : `/build/dedede/firmware/madoo/ec.bin` + The ebuild file used by Chromium OS is found -[here](https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/chromeos-base/chromeos-ec/chromeos-ec-9999.ebuild): +[here](https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/main/chromeos-base/chromeos-ec/chromeos-ec-9999.ebuild): ```bash (chroot) $ ~/trunk/src/third_party/chromiumos-overlay/chromeos-base/chromeos-ec/chromeos-ec-9999.ebuild @@ -245,6 +257,14 @@ If you build Chrome OS with `build_packages` the firmware image will be at: (chroot) $ /build//firmware/ec.bin ``` +or + +``` +(chroot) $ /build//firmware//ec.bin +``` + +The `devicename` is the name of a device (also referred as board or variant) which belongs to a family of baseboard. `boardname` is the baseboard name in this case. Example : `/build/dedede/firmware/madoo/ec.bin` + Specifying `--image` is optional. If you leave off the `--image` argument, the `flash_ec` script will first look for a locally built `ec.bin` followed by one generated by `emerge`. @@ -274,11 +294,11 @@ and turn on other developer-friendly flags (note that write protect must be disabled for this to work): ```bash -(chroot) $ /usr/share/vboot/bin/set_gbb_flags.sh 0x239 +# futility gbb --set --flash --flags=0x239 ``` ```bash -(chroot) $ reboot +# reboot ``` This turns on the following flags: @@ -289,8 +309,15 @@ This turns on the following flags: * `GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK` * `GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC` + +Alternatively, if the OS cannot be accessed, the same flag can be set over a servo with: + +```bash +$ sudo futility gbb -s --flags=0x239 --servo +``` + The `GBB` (Google Binary Block) flags are defined in the -[vboot_reference source](https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/master/firmware/include/gbb_header.h). +[vboot_reference source](https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/main/firmware/2lib/include/2struct.h). A varying subset of these flags are implemented and/or relevant for any particular board. @@ -391,7 +418,7 @@ in priority order if more than one callback needs to be run. There are also hooks for running functions periodically: `HOOK_TICK` (fires every `HOOK_TICK_INVERVAL` ms which varies by EC chip) and `HOOK_SECOND`. See hook_type in -[include/hooks.h](https://chromium.googlesource.com/chromiumos/platform/ec/+/master/include/hooks.h) +[include/hooks.h](https://chromium.googlesource.com/chromiumos/platform/ec/+/main/include/hooks.h) for a complete list. ### Deferred Functions @@ -432,7 +459,7 @@ void some_interrupt(enum gpio_signal signal) While there is no heap, there is a shared memory buffer that can be borrowed temporarily (ideally before a context switch). The size of the buffer depends on the EC chip being used. The buffer can only be used by one task at a time. See -[common/shared_mem.c](https://chromium.googlesource.com/chromiumos/platform/ec/+/master/common/shared_mem.c) +[common/shared_mem.c](https://chromium.googlesource.com/chromiumos/platform/ec/+/main/common/shared_mem.c) for more information. At present (May 2014), this buffer is only used by debug commands. @@ -463,13 +490,13 @@ Other style notes: not use globals to pass information between modules without accessors. For module scope, accessors are not needed. 1. If you add a new `#define` config option to the code, please document it in - [include/config.h](https://chromium.googlesource.com/chromiumos/platform/ec/+/master/include/config.h) + [include/config.h](https://chromium.googlesource.com/chromiumos/platform/ec/+/main/include/config.h) with an `#undef` statement and descriptive comment. 1. The Chromium copyright header must be included at the top of new files in all contributions to the Chromium project: ``` - /* Copyright The Chromium OS Authors. All rights reserved. + /* Copyright The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -489,7 +516,7 @@ Prior to uploading a new change for review, please run the EC unit tests with: These commands will build and run unit tests in an emulator on your host. -Pre-submit checks are run when you try to upload a change-list. If you wish to +Pre-upload checks are run when you try to upload a change-list. If you wish to run these checks manually first, commit your change locally then run the following command from within the chroot and while in the `src/platform/ec` directory: @@ -498,14 +525,16 @@ directory: (chroot) $ ~/trunk/src/repohooks/pre-upload.py ``` -The pre-submit checks include checking the commit message. Commit messages must -have a `BUG`, `BRANCH`, and `TEST` line along with `Signed-off-by: First Last -`. The signed-off-by line is a statement that you have written -this code and it can be contributed under the terms of the `LICENSE` file. +The pre-upload checks include checking the commit message. Commit messages must +have a `BUG` and `TEST`. You may also optionally include a `BRANCH` line with a +list of board names for which the CL should be cherry-picked back to old +branches for. Please refer to existing commits (`git log`) to see the proper format for the -commit message. If you have configured git properly, running `git commit` with -the `-s` argument will add the Signed-off-by line for you. +commit message. + +Note that code you submit must adhere to the [ChromeOS EC Firmware Test +Requirements]. ## Debugging @@ -608,8 +637,8 @@ If the version is: `rambi_v1.6.68-a6608c8`: The branch numbers (as of May 2014) are: -* v1.0.0 cros/master -* v1.1.0 cros/master +* v1.0.0 cros/main +* v1.1.0 cros/main * v1.2.0 cros/firmware-link-2695.2.B * v1.3.0 cros/firmware-snow-2695.90.B * v1.4.0 cros/firmware-skate-3824.129.B @@ -640,3 +669,22 @@ cheese_v1.1.1755-4da9520 ``` [Firmware Write Protection]: ./docs/write_protection.md + +## CQ builder + +To test the cq builder script run these commands: + +### firmware-ec-cq +``` +rm -rf /tmp/artifact_bundles /tmp/artifact_bundle_metadata \ + ~/chromiumos/src/platform/ec/build +./firmware_builder.py --metrics /tmp/metrics_build build && \ +./firmware_builder.py --metrics /tmp/metrics_test test && \ +./firmware_builder.py --metrics /tmp/metrics_bundle bundle && \ +echo PASSED +cat /tmp/artifact_bundle_metadata +cat /tmp/metrics_build +ls -l /tmp/artifact_bundles/ +``` + +[ChromeOS EC Firmware Test Requirements]: ./docs/chromeos-ec-firmware-test-requirements.md diff --git a/baseboard/asurada/baseboard.c b/baseboard/asurada/baseboard.c new file mode 100644 index 0000000000..7ff873963d --- /dev/null +++ b/baseboard/asurada/baseboard.c @@ -0,0 +1,120 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Asurada baseboard-specific configuration */ + +#include "adc.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/als_tcs3400.h" +#include "driver/bc12/mt6360.h" +#include "driver/charger/isl923x.h" +#include "driver/ppc/syv682x.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/temp_sensor/thermistor.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "it5205_sbu.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "power.h" +#include "power_button.h" +#include "regulator.h" +#include "spi.h" +#include "switch.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "timer.h" +#include "uart.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Wake-up pins for hibernate */ +enum gpio_signal hibernate_wake_pins[] = { + GPIO_AC_PRESENT, + GPIO_LID_OPEN, + GPIO_POWER_BUTTON_L, +}; +int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/* + * I2C channels (A, B, and C) are using the same timing registers (00h~07h) + * at default. + * In order to set frequency independently for each channels, + * We use timing registers 09h~0Bh, and the supported frequency will be: + * 50KHz, 100KHz, 400KHz, or 1MHz. + * I2C channels (D, E and F) can be set different frequency on different ports. + * The I2C(D/E/F) frequency depend on the frequency of SMBus Module and + * the individual prescale register. + * The frequency of SMBus module is 24MHz on default. + * The allowed range of I2C(D/E/F) frequency is as following setting. + * SMBus Module Freq = PLL_CLOCK / ((IT83XX_ECPM_SCDCR2 & 0x0F) + 1) + * (SMBus Module Freq / 510) <= I2C Freq <= (SMBus Module Freq / 8) + * Channel D has multi-function and can be used as UART interface. + * Channel F is reserved for EC debug. + */ + +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "bat_chg", + .port = IT83XX_I2C_CH_A, + .kbps = 100, + .scl = GPIO_I2C_A_SCL, + .sda = GPIO_I2C_A_SDA }, + { .name = "sensor", + .port = IT83XX_I2C_CH_B, + .kbps = 400, + .scl = GPIO_I2C_B_SCL, + .sda = GPIO_I2C_B_SDA }, + { .name = "usb0", + .port = IT83XX_I2C_CH_C, + .kbps = 400, + .scl = GPIO_I2C_C_SCL, + .sda = GPIO_I2C_C_SDA }, + { .name = "usb1", + .port = IT83XX_I2C_CH_E, + .kbps = 400, + .scl = GPIO_I2C_E_SCL, + .sda = GPIO_I2C_E_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc) +{ + return (cmd_desc->port == I2C_PORT_VIRTUAL_BATTERY); +} + +const struct cc_para_t *board_get_cc_tuning_parameter(enum usbpd_port port) +{ + const static struct cc_para_t + cc_parameter[CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT] = { + { + .rising_time = + IT83XX_TX_PRE_DRIVING_TIME_1_UNIT, + .falling_time = + IT83XX_TX_PRE_DRIVING_TIME_2_UNIT, + }, + { + .rising_time = + IT83XX_TX_PRE_DRIVING_TIME_1_UNIT, + .falling_time = + IT83XX_TX_PRE_DRIVING_TIME_2_UNIT, + }, + }; + + return &cc_parameter[port]; +} diff --git a/baseboard/asurada/baseboard.h b/baseboard/asurada/baseboard.h new file mode 100644 index 0000000000..a8b62ccf59 --- /dev/null +++ b/baseboard/asurada/baseboard.h @@ -0,0 +1,195 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Asurada board configuration */ + +#ifndef __CROS_EC_BASEBOARD_H +#define __CROS_EC_BASEBOARD_H + +/* IT81202-bx config */ +/* + * NOTE: we need to make correct VCC voltage selection here if EC's VCC isn't + * connect to 1.8v on other versions. + */ +#define CONFIG_IT83XX_VCC_1P8V + +/* + * On power-on, H1 releases the EC from reset but then quickly asserts and + * releases the reset a second time. This means the EC sees 2 resets: + * (1) power-on reset, (2) reset-pin reset. This config will + * allow the second reset to be treated as a power-on. + */ +#define CONFIG_BOARD_RESET_AFTER_POWER_ON +#define CONFIG_CHIPSET_MT8192 +#define CONFIG_EXTPOWER_GPIO +#define CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE + +/* Chipset */ +#define CONFIG_CMD_AP_RESET_LOG +#define CONFIG_CMD_POWERINDEBUG +#define CONFIG_HOST_COMMAND_STATUS +#define CONFIG_LOW_POWER_IDLE +#define CONFIG_LOW_POWER_S0 +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_COMMON +#define CONFIG_PWM +#define CONFIG_VBOOT_HASH +#define CONFIG_VOLUME_BUTTONS +#define CONFIG_WP_ACTIVE_HIGH + +/* Battery */ +#define CONFIG_BATTERY_CUT_OFF +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_BATTERY_SMART + +/* BC12 */ +#define CONFIG_BC12_DETECT_MT6360 +#define CONFIG_BC12_DETECT_PI3USB9201 +#undef CONFIG_BC12_SINGLE_DRIVER +#define CONFIG_USB_CHARGER + +/* Charger */ +#define ADC_AMON_BMON ADC_CHARGER_AMON_R /* ADC name remap */ +#define ADC_PSYS ADC_CHARGER_PMON /* ADC name remap */ +#define CONFIG_CHARGE_MANAGER +#define CONFIG_CHARGER +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_DISCHARGE_ON_AC +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_ISL9238C +#define CONFIG_CHARGER_MAINTAIN_VBAT +#define CONFIG_CHARGER_OTG +#define CONFIG_CHARGER_PSYS +#define CONFIG_CHARGER_PSYS_READ +#define CONFIG_CHARGER_SENSE_RESISTOR 10 /* BOARD_RS2 */ +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 /* BOARD_RS1 */ +#define CONFIG_CMD_CHARGER_ADC_AMON_BMON + +/* Keyboard */ +#define CONFIG_CMD_KEYBOARD +#define CONFIG_KEYBOARD_COL2_INVERTED +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_USE_GPIO + +/* I2C */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER +#define CONFIG_I2C_PASSTHRU_RESTRICTED +#define CONFIG_I2C_VIRTUAL_BATTERY +#define I2C_PORT_CHARGER IT83XX_I2C_CH_A +#define I2C_PORT_BATTERY IT83XX_I2C_CH_A +#define I2C_PORT_POWER IT83XX_I2C_CH_A +#define I2C_PORT_ACCEL IT83XX_I2C_CH_B +#define I2C_PORT_PPC0 IT83XX_I2C_CH_C +#define I2C_PORT_PPC1 IT83XX_I2C_CH_E +#define I2C_PORT_USB_MUX0 IT83XX_I2C_CH_C +#define I2C_PORT_USB_MUX1 IT83XX_I2C_CH_E +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define CONFIG_SMBUS_PEC + +/* LED */ +#define CONFIG_LED_COMMON + +/* PD / USB-C / PPC */ +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_HOSTCMD_PD_CONTROL +#define CONFIG_IT83XX_TUNE_CC_PHY +#define CONFIG_USB_MUX_VIRTUAL +#define CONFIG_USBC_PPC +#define CONFIG_USBC_PPC_DEDICATED_INT +#define CONFIG_USBC_PPC_POLARITY +#define CONFIG_USBC_PPC_SYV682C +#define CONFIG_USBC_PPC_VCONN +#define CONFIG_USBC_SS_MUX +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USB_MUX_IT5205 /* C0 */ +#define CONFIG_USB_MUX_PS8743 /* C1 */ +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_USB_PD_DISCHARGE +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_DP_HPD_GPIO +#define CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_FRS_PPC +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 +#define CONFIG_USB_PD_LOGGING +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_REV30 +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_PD_TRY_SRC +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT +#define CONFIG_USB_PID 0x5053 +#define CONFIG_USB_POWER_DELIVERY + +/* USB-A */ +#define CONFIG_USB_PORT_POWER_DUMB +#define CONFIG_USB_PORT_POWER_DUMB_CUSTOM_HOOK +#define USB_PORT_COUNT USBA_PORT_COUNT + +/* UART */ +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Sensor */ +#ifdef HAS_TASK_MOTIONSENSE +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_CMD_ACCELS + +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) +#endif + +/* SPI / Host Command */ +#define CONFIG_SPI + +/* MKBP */ +#define CONFIG_MKBP_EVENT + +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_USE_GPIO + +/* Voltage regulator control */ +#define CONFIG_HOSTCMD_REGULATOR + +/* Define the host events which are allowed to wakeup AP in S3. */ +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_HANG_DETECT) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* And the MKBP events */ +#define CONFIG_MKBP_EVENT_WAKEUP_MASK \ + (BIT(EC_MKBP_EVENT_KEY_MATRIX) | BIT(EC_MKBP_EVENT_HOST_EVENT)) + +#include "baseboard_common.h" + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "power/mt8192.h" +#include "registers.h" + +void board_reset_pd_mcu(void); +enum board_sub_board board_get_sub_board(void); +void usb_a0_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/asurada/baseboard_common.h b/baseboard/asurada/baseboard_common.h new file mode 100644 index 0000000000..4b8892e5b7 --- /dev/null +++ b/baseboard/asurada/baseboard_common.h @@ -0,0 +1,44 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Asurada baseboard-specific onfiguration common to ECOS and Zephyr */ + +#ifndef __CROS_EC_BASEBOARD_COMMON_H +#define __CROS_EC_BASEBOARD_COMMON_H + +/* GPIO name remapping */ +#define GPIO_EN_HDMI_PWR GPIO_EC_X_GPIO1 +#define GPIO_USB_C1_FRS_EN GPIO_EC_X_GPIO1 +#define GPIO_USB_C1_PPC_INT_ODL GPIO_X_EC_GPIO2 +#define GPIO_PS185_EC_DP_HPD GPIO_X_EC_GPIO2 +#define GPIO_USB_C1_DP_IN_HPD GPIO_EC_X_GPIO3 +#define GPIO_PS185_PWRDN_ODL GPIO_EC_X_GPIO3 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" + +enum board_sub_board { + SUB_BOARD_NONE = -1, + SUB_BOARD_TYPEC, + SUB_BOARD_HDMI, + SUB_BOARD_COUNT, +}; + +/** + * board_get_version() - Get the board version + * + * Read the ADC to obtain the board version + * + * @return board version in the range 0 to 14 inclusive + */ +int board_get_version(void); + +void ppc_interrupt(enum gpio_signal signal); +void bc12_interrupt(enum gpio_signal signal); +void x_ec_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BASEBOARD_COMMON_H */ diff --git a/baseboard/asurada/board_chipset.c b/baseboard/asurada/board_chipset.c new file mode 100644 index 0000000000..24754f597f --- /dev/null +++ b/baseboard/asurada/board_chipset.c @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Asurada baseboard-chipset specific configuration */ + +#include "common.h" +#include "gpio.h" +#include "hooks.h" + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + gpio_set_level(GPIO_EC_BL_EN_OD, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + gpio_set_level(GPIO_EC_BL_EN_OD, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); diff --git a/baseboard/asurada/board_id.c b/baseboard/asurada/board_id.c new file mode 100644 index 0000000000..9a316d8d40 --- /dev/null +++ b/baseboard/asurada/board_id.c @@ -0,0 +1,94 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "timer.h" +#include "util.h" + +/** + * Conversion based on following table: + * + * ID | Rp | Rd | Voltage + * | kOhm | kOhm | mV + * ---+------+------+-------- + * 0 | 51.1 | 2.2 | 136.2 + * 1 | 51.1 | 6.81 | 388.1 + * 2 | 51.1 | 11 | 584.5 + * 3 | 57.6 | 18 | 785.7 + * 4 | 51.1 | 22 | 993.2 + * 5 | 51.1 | 30 | 1220.7 + * 6 | 51.1 | 39.2 | 1432.6 + * 7 | 56 | 56 | 1650.0 + * 8 | 47 | 61.9 | 1875.8 + * 9 | 47 | 80.6 | 2084.5 + * 10 | 56 | 124 | 2273.3 + * 11 | 51.1 | 150 | 2461.5 + * 12 | 47 | 200 | 2672.1 + * 13 | 47 | 330 | 2888.6 + * 14 | 47 | 680 | 3086.7 + */ +const static int voltage_map[] = { + 136, 388, 584, 785, 993, 1220, 1432, 1650, + 1875, 2084, 2273, 2461, 2672, 2888, 3086, +}; + +const int threshold_mv = 100; + +/** + * Convert ADC value to board id using the voltage table above. + * + * @param ch ADC channel to read, usually ADC_BOARD_ID_0 or ADC_BOARD_ID_1. + * + * @return a non-negative board id, or negative value if error. + */ +static int adc_value_to_numeric_id(enum adc_channel ch) +{ + int mv; + + gpio_set_level(GPIO_EN_EC_ID_ODL, 0); + /* Wait to allow cap charge */ + msleep(10); + + mv = adc_read_channel(ch); + if (mv == ADC_READ_ERROR) + mv = adc_read_channel(ch); + + gpio_set_level(GPIO_EN_EC_ID_ODL, 1); + + if (mv == ADC_READ_ERROR) + return -EC_ERROR_UNKNOWN; + + for (int i = 0; i < ARRAY_SIZE(voltage_map); i++) { + if (IN_RANGE(mv, voltage_map[i] - threshold_mv, + voltage_map[i] + threshold_mv - 1)) + return i; + } + + return -EC_ERROR_UNKNOWN; +} + +static int version = -1; + +/* b/163963220: Cache ADC value before board_hibernate_late() reads it */ +static void board_version_init(void) +{ + version = adc_value_to_numeric_id(ADC_BOARD_ID_0); + if (version < 0) { + ccprints("WARN:BOARD_ID_0"); + ccprints("Assuming board id = 0"); + + version = 0; + } +} +DECLARE_HOOK(HOOK_INIT, board_version_init, HOOK_PRIO_INIT_ADC + 1); + +__override int board_get_version(void) +{ + return version; +} diff --git a/baseboard/asurada/build.mk b/baseboard/asurada/build.mk new file mode 100644 index 0000000000..ac4f1489d2 --- /dev/null +++ b/baseboard/asurada/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Baseboard specific files build +# + +baseboard-y=baseboard.o +baseboard-y+=board_chipset.o +baseboard-y+=board_id.o +baseboard-y+=hibernate.o +baseboard-y+=regulator.o +baseboard-y+=usbc_config.o +baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o diff --git a/baseboard/asurada/hibernate.c b/baseboard/asurada/hibernate.c new file mode 100644 index 0000000000..21c2de41e3 --- /dev/null +++ b/baseboard/asurada/hibernate.c @@ -0,0 +1,40 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charger.h" +#include "driver/charger/isl923x_public.h" +#include "gpio.h" +#include "system.h" + +/* Hayato board specific hibernate implementation */ +__override void board_hibernate_late(void) +{ + /* + * Turn off PP5000_A. Required for devices without Z-state. + * Don't care for devices with Z-state. + */ + gpio_set_level(GPIO_EN_PP5000_A, 0); + + /* + * GPIO_EN_SLP_Z not implemented in rev0/1, + * fallback to usual hibernate process. + */ + if (board_get_version() <= 1) { + if (IS_ENABLED(BOARD_ASURADA) || + (IS_ENABLED(CONFIG_ZEPHYR) && + IS_ENABLED(CONFIG_BOARD_ASURADA))) + return; + } + + gpio_set_level(GPIO_EN_SLP_Z, 1); + + /* should not reach here */ + __builtin_unreachable(); +} + +void board_hibernate(void) +{ + isl9238c_hibernate(CHARGER_SOLO); +} diff --git a/board/asurada/it5205_sbu.c b/baseboard/asurada/it5205_sbu.c similarity index 89% rename from board/asurada/it5205_sbu.c rename to baseboard/asurada/it5205_sbu.c index 9ee59a5cc3..fc2cefd208 100644 --- a/board/asurada/it5205_sbu.c +++ b/baseboard/asurada/it5205_sbu.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -12,8 +12,8 @@ #include "timer.h" #include "usb_mux.h" -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) #define OVP_RETRY_DELAY_US_MIN (100 * MSEC) diff --git a/board/asurada/it5205_sbu.h b/baseboard/asurada/it5205_sbu.h similarity index 83% rename from board/asurada/it5205_sbu.h rename to baseboard/asurada/it5205_sbu.h index 8dc59520dd..2a17506cad 100644 --- a/board/asurada/it5205_sbu.h +++ b/baseboard/asurada/it5205_sbu.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/baseboard/asurada/regulator.c b/baseboard/asurada/regulator.c new file mode 100644 index 0000000000..0487f8faa6 --- /dev/null +++ b/baseboard/asurada/regulator.c @@ -0,0 +1,45 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "bc12/mt6360_public.h" +#include "common.h" + +/* SD Card */ +int board_regulator_get_info(uint32_t index, char *name, uint16_t *num_voltages, + uint16_t *voltages_mv) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_get_info(id, name, num_voltages, voltages_mv); +} + +int board_regulator_enable(uint32_t index, uint8_t enable) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_enable(id, enable); +} + +int board_regulator_is_enabled(uint32_t index, uint8_t *enabled) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_is_enabled(id, enabled); +} + +int board_regulator_set_voltage(uint32_t index, uint32_t min_mv, + uint32_t max_mv) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_set_voltage(id, min_mv, max_mv); +} + +int board_regulator_get_voltage(uint32_t index, uint32_t *voltage_mv) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_get_voltage(id, voltage_mv); +} diff --git a/baseboard/asurada/usb_pd_policy.c b/baseboard/asurada/usb_pd_policy.c new file mode 100644 index 0000000000..afec537330 --- /dev/null +++ b/baseboard/asurada/usb_pd_policy.c @@ -0,0 +1,237 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "atomic.h" +#include "baseboard_common.h" +#include "charge_manager.h" +#include "chipset.h" +#include "console.h" +#include "gpio.h" +#include "timer.h" +#include "usb_dp_alt_mode.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_ppc.h" + +#if CONFIG_USB_PD_3A_PORTS != 1 +#error Asurada reference must have at least one 3.0 A port +#endif + +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) + +int svdm_get_hpd_gpio(int port) +{ + /* HPD is low active, inverse the result */ + return !gpio_get_level(GPIO_EC_DPBRDG_HPD_ODL); +} + +void svdm_set_hpd_gpio(int port, int en) +{ + /* + * HPD is low active, inverse the en + * TODO: C0&C1 shares the same HPD, implement FCFS policy. + */ + gpio_set_level(GPIO_EC_DPBRDG_HPD_ODL, !en); +} + +/** + * Is the port fine to be muxed its DisplayPort lines? + * + * Only one port can be muxed to DisplayPort at a time. + * + * @param port Port number of TCPC. + * @return 1 is fine; 0 is bad as other port is already muxed; + */ +static int is_dp_muxable(int port) +{ + int i; + + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i != port) { + if (usb_mux_get(i) & USB_PD_MUX_DP_ENABLED) + return 0; + } + } + + return 1; +} + +__override int svdm_dp_attention(int port, uint32_t *payload) +{ + int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); + int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + int cur_lvl = svdm_get_hpd_gpio(port); +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + mux_state_t mux_state; + + dp_status[port] = payload[1]; + + if (!is_dp_muxable(port)) { + /* TODO(waihong): Info user? */ + CPRINTS("p%d: The other port is already muxed.", port); + return 0; /* nak */ + } + + if (lvl) + gpio_set_level_verbose(CC_USBPD, GPIO_DP_AUX_PATH_SEL, port); + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && (irq || lvl)) + /* + * Wake up the AP. IRQ or level high indicates a DP sink is now + * present. + */ + if (IS_ENABLED(CONFIG_MKBP_EVENT)) + pd_notify_dp_alt_mode_entry(port); + + /* Its initial DP status message prior to config */ + if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { + if (lvl) + dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; + return 1; + } + +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + if (irq && !lvl) { + /* + * IRQ can only be generated when the level is high, because + * the IRQ is signaled by a short low pulse from the high level. + */ + CPRINTF("ERR:HPD:IRQ&LOW\n"); + return 0; /* nak */ + } + + if (irq && cur_lvl) { + uint64_t now = get_time().val; + /* wait for the minimum spacing between IRQ_HPD if needed */ + if (now < svdm_hpd_deadline[port]) + usleep(svdm_hpd_deadline[port] - now); + + /* generate IRQ_HPD pulse */ + svdm_set_hpd_gpio(port, 0); + /* + * b/171172053#comment14: since the HPD_DSTREAM_DEBOUNCE_IRQ is + * very short (500us), we can use udelay instead of usleep for + * more stable pulse period. + */ + udelay(HPD_DSTREAM_DEBOUNCE_IRQ); + svdm_set_hpd_gpio(port, 1); + } else { + svdm_set_hpd_gpio(port, lvl); + } + + /* set the minimum time delay (2ms) for the next HPD IRQ */ + svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + + mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | + (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); + usb_mux_hpd_update(port, mux_state); + +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, lvl); +#endif + + /* ack */ + return 1; +} + +__override void svdm_exit_dp_mode(int port) +{ +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + svdm_set_hpd_gpio(port, 0); +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); + +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, 0); +#endif +} + +int pd_snk_is_vbus_provided(int port) +{ + static atomic_t vbus_prev[CONFIG_USB_PD_PORT_MAX_COUNT]; + int vbus; + + if ((IS_ENABLED(BOARD_HAYATO) && board_get_version() < 4) || + (IS_ENABLED(BOARD_SPHERION) && board_get_version() < 1)) + return ppc_is_vbus_present(port); + + /* + * (b:181203590#comment20) TODO(yllin): use + * PD_VSINK_DISCONNECT_PD for non-5V case. + */ + vbus = adc_read_channel(board_get_vbus_adc(port)) >= + PD_V_SINK_DISCONNECT_MAX; + +#ifdef CONFIG_USB_CHARGER + /* + * There's no PPC to inform VBUS change for usb_charger, so inform + * the usb_charger now. + */ + if (!!(vbus_prev[port] != vbus)) + usb_charger_vbus_change(port, vbus); + + if (vbus) + atomic_or(&vbus_prev[port], 1); + else + atomic_clear(&vbus_prev[port]); +#endif + return vbus; +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + prev_en = ppc_is_sourcing_vbus(port); + + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_check_vconn_swap(int port) +{ + /* Allow Vconn swap if AP is on. */ + return chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_ON); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +int board_vbus_source_enabled(int port) +{ + return ppc_is_sourcing_vbus(port); +} diff --git a/baseboard/asurada/usbc_config.c b/baseboard/asurada/usbc_config.c new file mode 100644 index 0000000000..391b9134c5 --- /dev/null +++ b/baseboard/asurada/usbc_config.c @@ -0,0 +1,435 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Asurada baseboard-specific USB-C configuration */ + +#include "adc.h" +#include "baseboard_common.h" +#include "bc12/mt6360_public.h" +#include "bc12/pi3usb9201_public.h" +#include "button.h" +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "console.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "ppc/syv682x_public.h" +#include "spi.h" +#include "switch.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/it8xxx2_pd_public.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_mux/it5205_public.h" +#include "usb_mux/ps8743_public.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* Baseboard */ + +static void baseboard_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_AP_XHCI_INIT_DONE); +} +DECLARE_HOOK(HOOK_INIT, baseboard_init, HOOK_PRIO_DEFAULT - 1); + +/* Sub-board */ + +enum board_sub_board board_get_sub_board(void) +{ + static enum board_sub_board sub = SUB_BOARD_NONE; + + if (sub != SUB_BOARD_NONE) + return sub; + + /* HDMI board has external pull high. */ + if (gpio_get_level(GPIO_EC_X_GPIO3)) { + sub = SUB_BOARD_HDMI; + /* Only has 1 PPC with HDMI subboard */ + ppc_cnt = 1; + /* EC_X_GPIO1 */ + gpio_set_flags(GPIO_EN_HDMI_PWR, GPIO_OUT_HIGH); + /* X_EC_GPIO2 */ + gpio_set_flags(GPIO_PS185_EC_DP_HPD, GPIO_INT_BOTH); + /* EC_X_GPIO3 */ + gpio_set_flags(GPIO_PS185_PWRDN_ODL, GPIO_ODR_HIGH); + } else { + sub = SUB_BOARD_TYPEC; + /* EC_X_GPIO1 */ + gpio_set_flags(GPIO_USB_C1_FRS_EN, GPIO_OUT_LOW); + /* X_EC_GPIO2 */ + gpio_set_flags(GPIO_USB_C1_PPC_INT_ODL, + GPIO_INT_BOTH | GPIO_PULL_UP); + /* EC_X_GPIO3 */ + gpio_set_flags(GPIO_USB_C1_DP_IN_HPD, GPIO_OUT_LOW); + } + + CPRINTS("Detect %s SUB", sub == SUB_BOARD_HDMI ? "HDMI" : "TYPEC"); + return sub; +} + +static void sub_board_init(void) +{ + board_get_sub_board(); +} +DECLARE_HOOK(HOOK_INIT, sub_board_init, HOOK_PRIO_INIT_I2C - 1); + +/* Detect subboard */ +static void board_tcpc_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + /* C1: GPIO_USB_C1_PPC_INT_ODL & HDMI: GPIO_PS185_EC_DP_HPD */ + gpio_enable_interrupt(GPIO_X_EC_GPIO2); + + /* If this is not a Type-C subboard, disable the task. */ + if (board_get_sub_board() != SUB_BOARD_TYPEC) + task_disable_task(TASK_ID_PD_C1); +} +/* Must be done after I2C and subboard */ +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +/* PPC */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .i2c_port = I2C_PORT_PPC0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + .frs_en = GPIO_USB_C0_FRS_EN, + }, + { + .i2c_port = I2C_PORT_PPC1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + .frs_en = GPIO_USB_C1_FRS_EN, + }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* BC12 */ +const struct mt6360_config_t mt6360_config = { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = MT6360_PMU_I2C_ADDR_FLAGS, +}; + +const struct pi3usb9201_config_t + pi3usb9201_bc12_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + /* [0]: unused */ + [1] = { + .i2c_port = I2C_PORT_PPC1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + } +}; + +struct bc12_config bc12_ports[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { .drv = &mt6360_drv }, + { .drv = &pi3usb9201_drv }, +}; + +void bc12_interrupt(enum gpio_signal signal) +{ + if (signal == GPIO_USB_C0_BC12_INT_ODL) + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + else + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void board_sub_bc12_init(void) +{ + if (board_get_sub_board() == SUB_BOARD_TYPEC) + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + else + /* If this is not a Type-C subboard, disable the task. */ + task_disable_task(TASK_ID_USB_CHG_P1); +} +/* Must be done after I2C and subboard */ +DECLARE_HOOK(HOOK_INIT, board_sub_bc12_init, HOOK_PRIO_INIT_I2C + 1); + +void ppc_interrupt(enum gpio_signal signal) +{ + if (signal == GPIO_USB_C0_PPC_INT_ODL) + /* C0: PPC interrupt */ + syv682x_interrupt(0); +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + if (board_get_sub_board() == SUB_BOARD_TYPEC) + return CONFIG_USB_PD_PORT_MAX_COUNT; + else + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; +} + +/* USB-A */ +const int usb_port_enable[] = { + GPIO_EN_PP5000_USB_A0_VBUS, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +void usb_a0_interrupt(enum gpio_signal signal) +{ + enum usb_charge_mode mode = gpio_get_level(signal) ? + USB_CHARGE_MODE_ENABLED : + USB_CHARGE_MODE_DISABLED; + + for (int i = 0; i < USB_PORT_COUNT; i++) + usb_charge_set_mode(i, mode, USB_ALLOW_SUSPEND_CHARGE); +} + +static int board_ps8743_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + int reg = 0; + + rv = ps8743_read(me, PS8743_REG_MODE, ®); + if (rv) + return rv; + + /* Disable FLIP pin, enable I2C control. */ + reg |= PS8743_MODE_FLIP_REG_CONTROL; + /* Disable CE_USB pin, enable I2C control. */ + reg |= PS8743_MODE_USB_REG_CONTROL; + /* Disable CE_DP pin, enable I2C control. */ + reg |= PS8743_MODE_DP_REG_CONTROL; + + /* + * DP specific config + * + * Enable/Disable IN_HPD on the DB. + */ + gpio_set_level(GPIO_USB_C1_DP_IN_HPD, + mux_state & USB_PD_MUX_DP_ENABLED); + + return ps8743_write(me, PS8743_REG_MODE, reg); +} + +const struct usb_mux_chain usbc0_virtual_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usbc1_virtual_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + .next = &usbc0_virtual_mux, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_USB_MUX1, + .i2c_addr_flags = PS8743_I2C_ADDR0_FLAG, + .driver = &ps8743_usb_mux_driver, + .board_set = &board_ps8743_mux_set, + }, + .next = &usbc1_virtual_mux, + }, +}; + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO: check correct operation for Asurada */ +} + +/* TCPC */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + /* TCPC is embedded within EC so no i2c config needed */ + .drv = &it8xxx2_tcpm_drv, + /* Alert is active-low, push-pull */ + .flags = 0, + }, + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + /* TCPC is embedded within EC so no i2c config needed */ + .drv = &it8xxx2_tcpm_drv, + /* Alert is active-low, push-pull */ + .flags = 0, + }, +}; + +uint16_t tcpc_get_alert_status(void) +{ + /* + * C0 & C1: TCPC is embedded in the EC and processes interrupts in the + * chip code (it83xx/intc.c) + */ + return 0; +} + +void board_reset_pd_mcu(void) +{ + /* + * C0 & C1: TCPC is embedded in the EC and processes interrupts in the + * chip code (it83xx/intc.c) + */ +} + +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* + * We ignore the cc_pin and PPC vconn because polarity and PPC vconn + * should already be set correctly in the PPC driver via the pd + * state machine. + */ +} + +int board_set_active_charge_port(int port) +{ + int i; + int is_valid_port = port == 0 || (port == 1 && board_get_sub_board() == + SUB_BOARD_TYPEC); + + if (!is_valid_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTS("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTS("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTS("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTS("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +/** + * Handle PS185 HPD changing state. + */ +int debounced_hpd; + +static void ps185_hdmi_hpd_deferred(void) +{ + const int new_hpd = gpio_get_level(GPIO_PS185_EC_DP_HPD); + + /* HPD status not changed, probably a glitch, just return. */ + if (debounced_hpd == new_hpd) + return; + + debounced_hpd = new_hpd; + + gpio_set_level(GPIO_EC_DPBRDG_HPD_ODL, !debounced_hpd); + CPRINTS(debounced_hpd ? "HDMI plug" : "HDMI unplug"); +} +DECLARE_DEFERRED(ps185_hdmi_hpd_deferred); + +#define PS185_HPD_DEBOUCE 250 + +static void hdmi_hpd_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&ps185_hdmi_hpd_deferred_data, PS185_HPD_DEBOUCE); +} + +/* HDMI/TYPE-C function shared subboard interrupt */ +void x_ec_interrupt(enum gpio_signal signal) +{ + int sub = board_get_sub_board(); + + if (sub == SUB_BOARD_TYPEC) + /* C1: PPC interrupt */ + syv682x_interrupt(1); + else if (sub == SUB_BOARD_HDMI) + hdmi_hpd_interrupt(signal); + else + CPRINTS("Undetected subboard interrupt."); +} + +int ppc_get_alert_status(int port) +{ + if (port == 0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + if (port == 1 && board_get_sub_board() == SUB_BOARD_TYPEC) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + + return 0; +} + +#ifdef CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT +enum adc_channel board_get_vbus_adc(int port) +{ + if (port == 0) + return ADC_VBUS_C0; + if (port == 1) + return ADC_VBUS_C1; + CPRINTSUSB("Unknown vbus adc port id: %d", port); + return ADC_VBUS_C0; +} +#endif /* CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT */ diff --git a/baseboard/brask/baseboard.c b/baseboard/brask/baseboard.c new file mode 100644 index 0000000000..33a3d9acf4 --- /dev/null +++ b/baseboard/brask/baseboard.c @@ -0,0 +1,12 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "gpio_signal.h" + +/* Wake up pins */ +const enum gpio_signal hibernate_wake_pins[] = {}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); diff --git a/baseboard/brask/baseboard.h b/baseboard/brask/baseboard.h new file mode 100644 index 0000000000..8f10ebb8aa --- /dev/null +++ b/baseboard/brask/baseboard.h @@ -0,0 +1,215 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brask baseboard configuration */ + +#ifndef __CROS_EC_BASEBOARD_H +#define __CROS_EC_BASEBOARD_H + +/* + * By default, enable all console messages excepted HC + */ +#define CC_DEFAULT (CC_ALL & ~(BIT(CC_HOSTCMD))) + +/* NPCX9 config */ +#define NPCX9_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ +/* + * This defines which pads (GPIO10/11 or GPIO64/65) are connected to + * the "UART1" (NPCX_UART_PORT0) controller when used for + * CONSOLE_UART. + */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 for UART1 */ + +/* CrOS Board Info */ +#define CONFIG_CBI_EEPROM +#define CONFIG_BOARD_VERSION_CBI +#define CONFIG_CRC8 + +/* EC Defines */ +#define CONFIG_LTO +#define CONFIG_FPU + +/* Verified boot configs */ +#define CONFIG_VBOOT_EFS2 +#define CONFIG_VBOOT_HASH +#define CONFIG_VSTORE +#define CONFIG_VSTORE_SLOT_COUNT 1 + +/* Work around double CR50 reset by waiting in initial power on. */ +#define CONFIG_BOARD_RESET_AFTER_POWER_ON + +/* Host communication */ +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S5 +#define CONFIG_HOST_INTERFACE_ESPI_RESET_SLP_SX_VW_ON_ESPI_RST + +/* LED */ +#define CONFIG_LED_COMMON + +/* Common charger defines */ +#define CONFIG_CHARGE_MANAGER + +/* USBC BC1.2 */ +#define CONFIG_USB_CHARGER +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Support Barrel Jack */ +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 45000 + +/* Chipset config */ +#define CONFIG_CHIPSET_ALDERLAKE_SLG4BD44540 +#define CONFIG_CHIPSET_RESET_HOOK +#define CONFIG_CHIPSET_CAN_THROTTLE +#define CONFIG_CPU_PROCHOT_ACTIVE_LOW +#define CONFIG_EXTPOWER_GPIO +#define CONFIG_POWER_S0IX +#define CONFIG_POWER_S4_RESIDENCY +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define CONFIG_CHIPSET_X86_RSMRST_AFTER_S5 + +/* + * TODO(b/191742284): When DAM enabled coreboot image is flashed on top of DAM + * disabled coreboot, S5 exit is taking more than 4 seconds, then EC triggers + * system shutdown. This WA deselects CONFIG_BOARD_HAS_RTC_RESET to prevent + * EC from system shutdown. + */ +/* #define CONFIG_BOARD_HAS_RTC_RESET */ + +#define CONFIG_CMD_AP_RESET_LOG +#define CONFIG_HOSTCMD_AP_RESET + +/* ADL has new low-power features that requires extra-wide virtual wire + * pulses. The EDS specifies 100 microseconds. */ +#undef CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US +#define CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US 100 + +/* Buttons */ +#define CONFIG_DEDICATED_RECOVERY_BUTTON +#define CONFIG_EMULATED_SYSRQ +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_IGNORE_LID +#define CONFIG_POWER_BUTTON_INIT_IDLE +#define CONFIG_POWER_BUTTON_X86 +#undef CONFIG_BUTTON_DEBOUNCE +#define CONFIG_BUTTON_DEBOUNCE (100 * MSEC) + +/* Matrix Keyboard Protocol */ +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_INPUT_DEVICES +#define CONFIG_MKBP_USE_GPIO_AND_HOST_EVENT + +/* Thermal features */ +#define CONFIG_DPTF +#define CONFIG_THROTTLE_AP + +#define CONFIG_PWM + +/* Enable I2C Support */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER + +/* UART COMMAND */ +#define CONFIG_CMD_CHARGEN + +/* USB Type C and USB PD defines */ +/* Enable the new USB-C PD stack */ +#define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USB_PD_REV30 + +#define CONFIG_CMD_HCDEBUG +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_CMD_TCPC_DUMP + +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_ALT_MODE_UFP +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_TCPM_NCT38XX + +#define CONFIG_USB_PD_TCPM_MUX +#define CONFIG_HOSTCMD_PD_CONTROL /* Needed for TCPC FW update */ +#define CONFIG_CMD_USB_PD_PE + +/* + * The PS8815 TCPC was found to require a 50ms delay to consistently work + * with non-PD chargers. Override the default low-power mode exit delay. + */ +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (50 * MSEC) + +/* Enable USB3.2 DRD */ +#define CONFIG_USB_PD_USB32_DRD + +#define CONFIG_USB_PD_TRY_SRC +#define CONFIG_USB_PD_VBUS_DETECT_TCPC + +#define CONFIG_USBC_PPC +#define CONFIG_USBC_PPC_POLARITY +#define CONFIG_USBC_PPC_SBU +#define CONFIG_USBC_PPC_VCONN +#define CONFIG_USBC_PPC_DEDICATED_INT + +#define CONFIG_USBC_SS_MUX +#define CONFIG_USB_MUX_VIRTUAL + +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP + +/* Enabling SOP* communication */ +#define CONFIG_CMD_USB_PD_CABLE +#define CONFIG_USB_PD_DECODE_SOP + +/* + * USB ID + * This is allocated specifically for Brask + * http://google3/hardware/standards/usb/ + */ +#define CONFIG_USB_PID 0x5058 +/* Device version of product. */ +#define CONFIG_USB_BCD_DEV 0x0000 + +/* Remove predefined features */ +#undef CONFIG_HIBERNATE +#undef CONFIG_KEYBOARD_BOOT_KEYS +#undef CONFIG_KEYBOARD_RUNTIME_KEYS +#undef CONFIG_LID_SWITCH +#undef CONFIG_KEYBOARD_VIVALDI + +#ifndef __ASSEMBLER__ + +#include "baseboard_usbc_config.h" +#include "common.h" +#include "extpower.h" + +#include +#include + +/* + * Configure run-time data structures and operation based on CBI data. This + * typically includes customization for changes in the BOARD_VERSION and + * FW_CONFIG fields in CBI. This routine is called from the baseboard after + * the CBI data has been initialized. + */ +__override_proto void board_cbi_init(void); + +/* + * Initialize the FW_CONFIG from CBI data. If the CBI data is not valid, set the + * FW_CONFIG to the board specific defaults. + */ +__override_proto void board_init_fw_config(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/brask/baseboard_usbc_config.h b/baseboard/brask/baseboard_usbc_config.h new file mode 100644 index 0000000000..8ebf4f9b6a --- /dev/null +++ b/baseboard/brask/baseboard_usbc_config.h @@ -0,0 +1,19 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* brask family-specific USB-C configuration */ + +#ifndef __CROS_EC_BASEBOARD_USBC_CONFIG_H +#define __CROS_EC_BASEBOARD_USBC_CONFIG_H + +#include "gpio_signal.h" + +/* Common definition for the USB PD interrupt handlers. */ +void bc12_interrupt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); +void retimer_interrupt(enum gpio_signal signal); +void tcpc_alert_event(enum gpio_signal signal); + +#endif /* __CROS_EC_BASEBOARD_USBC_CONFIG_H */ diff --git a/baseboard/brask/build.mk b/baseboard/brask/build.mk new file mode 100644 index 0000000000..4b540d94ad --- /dev/null +++ b/baseboard/brask/build.mk @@ -0,0 +1,12 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brask baseboard specific files build +# + +baseboard-y= +baseboard-y+=baseboard.o +baseboard-y+=cbi.o +baseboard-y+=usb_pd_policy.o diff --git a/baseboard/brask/cbi.c b/baseboard/brask/cbi.c new file mode 100644 index 0000000000..0ff0e4c7f7 --- /dev/null +++ b/baseboard/brask/cbi.c @@ -0,0 +1,58 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#include + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +static uint8_t board_id; + +uint8_t get_board_id(void) +{ + return board_id; +} + +__overridable void board_cbi_init(void) +{ +} + +__overridable void board_init_fw_config(void) +{ +} + +__overridable void board_init_ssfc(void) +{ +} + +/* + * Read CBI from I2C EEPROM and initialize variables for board variants. + */ +static void cbi_init(void) +{ + uint32_t cbi_val; + + /* Board ID */ + if (cbi_get_board_version(&cbi_val) != EC_SUCCESS || + cbi_val > UINT8_MAX) + CPRINTS("CBI: Read Board ID failed"); + else + board_id = cbi_val; + + CPRINTS("Board ID: %d", board_id); + + board_init_fw_config(); + + board_init_ssfc(); + + /* Allow the board project to make runtime changes based on CBI data */ + board_cbi_init(); +} +DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_FIRST); diff --git a/baseboard/brask/cbi.h b/baseboard/brask/cbi.h new file mode 100644 index 0000000000..219718763f --- /dev/null +++ b/baseboard/brask/cbi.h @@ -0,0 +1,38 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* brask family-specific CBI functions, shared with Zephyr */ + +#ifndef __CROS_EC_BASEBOARD_CBI_H +#define __CROS_EC_BASEBOARD_CBI_H + +#include "common.h" + +/* + * Return the board revision number. + */ +uint8_t get_board_id(void); + +/** + * Configure run-time data structures and operation based on CBI data. This + * typically includes customization for changes in the BOARD_VERSION and + * FW_CONFIG fields in CBI. This routine is called from the baseboard after + * the CBI data has been initialized. + */ +__override_proto void board_cbi_init(void); + +/** + * Initialize the FW_CONFIG from CBI data. If the CBI data is not valid, set the + * FW_CONFIG to the board specific defaults. + */ +__override_proto void board_init_fw_config(void); + +/** + * Initialize the SSFC from CBI data. If the CBI data is not valid, set the + * SSFC to the board specific defaults. + */ +__override_proto void board_init_ssfc(void); + +#endif /* __CROS_EC_BASEBOARD_CBI_H */ diff --git a/baseboard/brask/usb_pd_policy.c b/baseboard/brask/usb_pd_policy.c new file mode 100644 index 0000000000..e20ad13f98 --- /dev/null +++ b/baseboard/brask/usb_pd_policy.c @@ -0,0 +1,228 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Shared USB-C policy for Brask boards */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "timer.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "usb_pd_vdo.h" +#include "usbc_ppc.h" +#include "util.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Only allow vconn swap after the PP5000_Z1 rail is enabled */ + return gpio_get_level(GPIO_SEQ_EC_DSW_PWROK); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + prev_en = ppc_is_sourcing_vbus(port); + + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +int board_vbus_source_enabled(int port) +{ + /* Ignore non-PD ports (the barrel jack). */ + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return 0; + return ppc_is_sourcing_vbus(port); +} + +#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE +/* ----------------- Vendor Defined Messages ------------------ */ +/* Responses specifically for the enablement of TBT mode in the role of UFP */ + +#define OPOS_TBT 1 + +static const union tbt_mode_resp_device vdo_tbt_modes[1] = { { + .tbt_alt_mode = 0x0001, + .tbt_adapter = TBT_ADAPTER_TBT3, + .intel_spec_b0 = 0, + .vendor_spec_b0 = 0, + .vendor_spec_b1 = 0, +} }; + +static const uint32_t vdo_idh = VDO_IDH(1, /* Data caps as USB host */ + 0, /* Not a USB device */ + IDH_PTYPE_PERIPH, 1, /* Supports alt + modes */ + USB_VID_GOOGLE); + +static const uint32_t vdo_idh_rev30 = + VDO_IDH_REV30(1, /* Data caps as USB host */ + 0, /* Not a USB device */ + IDH_PTYPE_PERIPH, 1, /* Supports alt modes */ + IDH_PTYPE_DFP_HOST, USB_TYPEC_RECEPTACLE, USB_VID_GOOGLE); + +static const uint32_t vdo_product = + VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); + +/* TODO(b/168890624): add USB4 to capability once USB4 response implemented */ +static const uint32_t vdo_ufp1 = VDO_UFP1( + (VDO_UFP1_CAPABILITY_USB20 | VDO_UFP1_CAPABILITY_USB32), + USB_TYPEC_RECEPTACLE, VDO_UFP1_ALT_MODE_TBT3, USB_R30_SS_U40_GEN3); + +static const uint32_t vdo_dfp = + VDO_DFP((VDO_DFP_HOST_CAPABILITY_USB20 | VDO_DFP_HOST_CAPABILITY_USB32 | + VDO_DFP_HOST_CAPABILITY_USB4), + USB_TYPEC_RECEPTACLE, 1 /* Port 1 */); + +static int svdm_tbt_compat_response_identity(int port, uint32_t *payload) +{ + /* TODO(b/154962766): Get an XID */ + payload[VDO_I(CSTAT)] = VDO_CSTAT(0); + payload[VDO_I(PRODUCT)] = vdo_product; + + if (pd_get_rev(port, TCPCI_MSG_SOP) == PD_REV30) { + /* PD Revision 3.0 */ + payload[VDO_I(IDH)] = vdo_idh_rev30; + payload[VDO_I(PTYPE_UFP1_VDO)] = vdo_ufp1; + /* TODO(b/181620145): Customize for brya */ + payload[VDO_I(PTYPE_UFP2_VDO)] = 0; + payload[VDO_I(PTYPE_DFP_VDO)] = vdo_dfp; + return VDO_I(PTYPE_DFP_VDO) + 1; + } + + /* PD Revision 2.0 */ + payload[VDO_I(IDH)] = vdo_idh; + return VDO_I(PRODUCT) + 1; +} + +static int svdm_tbt_compat_response_svids(int port, uint32_t *payload) +{ + payload[1] = VDO_SVID(USB_VID_INTEL, 0); + return 2; +} + +static int svdm_tbt_compat_response_modes(int port, uint32_t *payload) +{ + if (PD_VDO_VID(payload[0]) == USB_VID_INTEL) { + memcpy(payload + 1, vdo_tbt_modes, sizeof(vdo_tbt_modes)); + return ARRAY_SIZE(vdo_tbt_modes) + 1; + } else { + return 0; /* NAK */ + } +} + +/* Track whether we've been enabled to ACK TBT EnterModes requests */ +static bool tbt_ufp_ack_allowed[CONFIG_USB_PD_PORT_MAX_COUNT]; + +__override enum ec_status +board_set_tbt_ufp_reply(int port, enum typec_tbt_ufp_reply reply) +{ + /* Note: Host command has already bounds-checked port */ + if (reply == TYPEC_TBT_UFP_REPLY_ACK) + tbt_ufp_ack_allowed[port] = true; + else if (reply == TYPEC_TBT_UFP_REPLY_NAK) + tbt_ufp_ack_allowed[port] = false; + else + return EC_RES_INVALID_PARAM; + + return EC_RES_SUCCESS; +} + +static int svdm_tbt_compat_response_enter_mode(int port, uint32_t *payload) +{ + mux_state_t mux_state = 0; + + /* Do not enter mode while CPU is off. */ + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) + return 0; /* NAK */ + + /* Do not enter mode while policy disallows it */ + if (!tbt_ufp_ack_allowed[port]) + return 0; /* NAK */ + + if ((PD_VDO_VID(payload[0]) != USB_VID_INTEL) || + (PD_VDO_OPOS(payload[0]) != OPOS_TBT)) + return 0; /* NAK */ + + mux_state = usb_mux_get(port); + /* + * Ref: USB PD 3.0 Spec figure 6-21 Successful Enter Mode sequence + * UFP (responder) should be in USB mode or safe mode before entering a + * Mode that requires the reconfiguring of any pins. + */ + if ((mux_state & USB_PD_MUX_USB_ENABLED) || + (mux_state & USB_PD_MUX_SAFE_MODE)) { + pd_ufp_set_enter_mode(port, payload); + set_tbt_compat_mode_ready(port); + + /* + * Ref: Above figure 6-21: UFP (responder) should be in the new + * mode before sending the ACK. However, our mux set sequence + * may exceed tVDMEnterMode, so wait as long as we can + * before sending the reply without violating that timer. + */ + if (!usb_mux_set_completed(port)) + usleep(PD_T_VDM_E_MODE / 2); + + CPRINTS("UFP Enter TBT mode"); + return 1; /* ACK */ + } + + CPRINTS("UFP failed to enter TBT mode(mux=0x%x)", mux_state); + return 0; +} + +const struct svdm_response svdm_rsp = { + .identity = &svdm_tbt_compat_response_identity, + .svids = &svdm_tbt_compat_response_svids, + .modes = &svdm_tbt_compat_response_modes, + .enter_mode = &svdm_tbt_compat_response_enter_mode, + .amode = NULL, + .exit_mode = NULL, +}; +#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */ diff --git a/baseboard/brya/baseboard.c b/baseboard/brya/baseboard.c new file mode 100644 index 0000000000..e65a384578 --- /dev/null +++ b/baseboard/brya/baseboard.c @@ -0,0 +1,45 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio_signal.h" +#include "keyboard_scan.h" +#include "tablet_mode.h" + +/* Wake up pins */ +const enum gpio_signal hibernate_wake_pins[] = { + GPIO_ACOK_OD, + GPIO_GSC_EC_PWR_BTN_ODL, + GPIO_LID_OPEN, +}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ +#ifdef CONFIG_TABLET_MODE + if (tablet_get_mode()) + enable = 0; +#endif + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * When the chipset is on, the EC keeps the keyboard enabled and + * Ensure that the chipset is off before disabling the keyboard. + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_state(CHIPSET_STATE_ON)) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} diff --git a/baseboard/brya/baseboard.h b/baseboard/brya/baseboard.h new file mode 100644 index 0000000000..22a07d761d --- /dev/null +++ b/baseboard/brya/baseboard.h @@ -0,0 +1,260 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya baseboard configuration */ + +#ifndef __CROS_EC_BASEBOARD_H +#define __CROS_EC_BASEBOARD_H + +/* + * By default, enable all console messages excepted HC, ACPI and event: + * The sensor stack is generating a lot of activity. + */ +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + +/* NPCX9 config */ +#define NPCX9_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ +/* + * This defines which pads (GPIO10/11 or GPIO64/65) are connected to + * the "UART1" (NPCX_UART_PORT0) controller when used for + * CONSOLE_UART. + */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 for UART1 */ + +/* EC Defines */ +#define CONFIG_LTO +#define CONFIG_CBI_EEPROM +#define CONFIG_BOARD_VERSION_CBI +#define CONFIG_CRC8 +#define CONFIG_DPTF +#define CONFIG_FPU + +/* Verified boot configs */ +#define CONFIG_VBOOT_EFS2 +#define CONFIG_VBOOT_HASH +#define CONFIG_VSTORE +#define CONFIG_VSTORE_SLOT_COUNT 1 + +#define CONFIG_HIBERNATE_PSL + +/* Work around double CR50 reset by waiting in initial power on. */ +#define CONFIG_BOARD_RESET_AFTER_POWER_ON + +/* Host communication */ +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S5 + +/* + * TODO(b/179648721): implement sensors + */ +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +#define CONFIG_MKBP_EVENT +/* GPIO is needed for EC events to show up in eventlog - b/222375516 */ +#define CONFIG_MKBP_USE_GPIO_AND_HOST_EVENT +#define CONFIG_MKBP_INPUT_DEVICES + +/* LED */ +#define CONFIG_LED_COMMON + +/* Common charger defines */ +#define CONFIG_CHARGE_MANAGER +#define CONFIG_CHARGER +#define CONFIG_CHARGER_DISCHARGE_ON_AC +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 + +#define CONFIG_CMD_CHARGER_DUMP + +#define CONFIG_USB_CHARGER +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* + * Don't allow the system to boot to S0 when the battery is low and unable to + * communicate on locked systems (which haven't PD negotiated) + */ +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000 +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 15001 + +/* Common battery defines */ +#define CONFIG_BATTERY_SMART +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_CUT_OFF +#define CONFIG_BATTERY_PRESENT_CUSTOM +#define CONFIG_BATTERY_HW_PRESENT_CUSTOM +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_CMD_BATT_MFG_ACCESS +/* + * Enable support for battery hostcmd, supporting longer strings. + * support for EC_CMD_BATTERY_GET_STATIC version 1. + */ +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 + +/* Chipset config */ +#define CONFIG_CHIPSET_ALDERLAKE_SLG4BD44540 +#define CONFIG_CHIPSET_X86_RSMRST_AFTER_S5 + +#define CONFIG_CHIPSET_RESET_HOOK +#define CONFIG_CPU_PROCHOT_ACTIVE_LOW +#define CONFIG_EXTPOWER_GPIO +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_X86 +#define CONFIG_POWER_S0IX +#define CONFIG_POWER_S4_RESIDENCY +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define CONFIG_LOW_POWER_IDLE + +#define CONFIG_HOST_INTERFACE_ESPI_RESET_SLP_SX_VW_ON_ESPI_RST + +#define CONFIG_BOARD_HAS_RTC_RESET +#undef CONFIG_S5_EXIT_WAIT +#define CONFIG_S5_EXIT_WAIT 10 + +#define CONFIG_CMD_AP_RESET_LOG +#define CONFIG_HOSTCMD_AP_RESET + +/* ADL has new lower-power features that require extra-wide virtual wire + * pulses. The EDS specifies 100 microseconds. */ +#undef CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US +#define CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US 100 + +/* Buttons / Switches */ +#define CONFIG_VOLUME_BUTTONS +#define CONFIG_SWITCH + +/* Common Keyboard Defines */ +#define CONFIG_CMD_KEYBOARD + +#define CONFIG_KEYBOARD_COL2_INVERTED +#define CONFIG_KEYBOARD_KEYPAD +#define CONFIG_KEYBOARD_PROTOCOL_8042 +#ifdef CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2 +#else +#define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI3 +#endif + +/* Thermal features */ +#define CONFIG_THROTTLE_AP +#define CONFIG_CHIPSET_CAN_THROTTLE + +#define CONFIG_PWM + +/* Enable I2C Support */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER + +/* EDP back-light control defines */ +#define CONFIG_BACKLIGHT_LID + +/* UART COMMAND */ +#define CONFIG_CMD_CHARGEN + +/* USB Type C and USB PD defines */ +/* Enable the new USB-C PD stack */ +#define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USB_PD_REV30 + +#define CONFIG_CMD_HCDEBUG +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_CMD_TCPC_DUMP + +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_ALT_MODE_UFP +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_TCPM_NCT38XX + +#define CONFIG_USB_PD_TCPM_MUX +#define CONFIG_HOSTCMD_PD_CONTROL /* Needed for TCPC FW update */ +#define CONFIG_CMD_USB_PD_PE + +/* + * The PS8815 TCPC was found to require a 50ms delay to consistently work + * with non-PD chargers. Override the default low-power mode exit delay. + */ +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (50 * MSEC) + +/* Enable USB3.2 DRD */ +#define CONFIG_USB_PD_USB32_DRD + +#define CONFIG_USB_PD_TRY_SRC +#define CONFIG_USB_PD_VBUS_DETECT_TCPC + +#define CONFIG_USBC_PPC +/* Note - SN5S330 support automatically adds + * CONFIG_USBC_PPC_POLARITY + * CONFIG_USBC_PPC_SBU + * CONFIG_USBC_PPC_VCONN + */ +#define CONFIG_USBC_PPC_DEDICATED_INT + +#define CONFIG_USBC_SS_MUX +#define CONFIG_USB_MUX_VIRTUAL + +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP + +/* Enabling SOP* communication */ +#define CONFIG_CMD_USB_PD_CABLE +#define CONFIG_USB_PD_DECODE_SOP + +/* + * USB ID + * This is allocated specifically for Brya + * http://google3/hardware/standards/usb/ + */ +#define CONFIG_USB_PID 0x504F +/* Device version of product. */ +#define CONFIG_USB_BCD_DEV 0x0000 + +/* + * These stack sizes were determined using "make analyzestack" for brya + * and include about 15% headroom. Sizes are rounded to multiples of 64 + * bytes. Task stack sizes not listed here use more generic values (see + * ec.tasklist). + */ +#define BASEBOARD_CHARGER_TASK_STACK_SIZE 1088 +#define BASEBOARD_CHG_RAMP_TASK_STACK_SIZE 1088 +#define BASEBOARD_CHIPSET_TASK_STACK_SIZE 1152 +#define BASEBOARD_PD_INT_TASK_STACK_SIZE 800 +#define BASEBOARD_PD_TASK_STACK_SIZE 1216 +#define BASEBOARD_POWERBTN_TASK_STACK_SIZE 1088 +#define BASEBOARD_RGBKBD_TASK_STACK_SIZE 2048 + +#ifndef __ASSEMBLER__ + +#include "baseboard_usbc_config.h" +#include "cbi.h" +#include "common.h" +#include "extpower.h" + +#include +#include + +/* + * Check battery disconnect state. + * This function will return if battery is initialized or not. + * @return true - initialized. false - not. + */ +__override_proto bool board_battery_is_initialized(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/brya/baseboard_usbc_config.h b/baseboard/brya/baseboard_usbc_config.h new file mode 100644 index 0000000000..17f1fe6b06 --- /dev/null +++ b/baseboard/brya/baseboard_usbc_config.h @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* brya family-specific USB-C configuration */ + +#ifndef __CROS_EC_BASEBOARD_USBC_CONFIG_H +#define __CROS_EC_BASEBOARD_USBC_CONFIG_H + +#include "gpio_signal.h" + +/* Common definition for the USB PD interrupt handlers. */ +#ifdef CONFIG_USB_CHARGER +void bc12_interrupt(enum gpio_signal signal); +#endif +void ppc_interrupt(enum gpio_signal signal); +void retimer_interrupt(enum gpio_signal signal); +void tcpc_alert_event(enum gpio_signal signal); + +#endif /* __CROS_EC_BASEBOARD_USBC_CONFIG_H */ diff --git a/baseboard/brya/battery_presence.c b/baseboard/brya/battery_presence.c new file mode 100644 index 0000000000..ad055c1d12 --- /dev/null +++ b/baseboard/brya/battery_presence.c @@ -0,0 +1,70 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Common battery presence checking for Brya family. + * Each board should implement board_battery_info[] to define the specific + * battery packs supported. + */ +#include "battery.h" +#include "battery_smart.h" +#include "common.h" + +#include + +static enum battery_present batt_pres_prev = BP_NOT_SURE; + +__overridable bool board_battery_is_initialized(void) +{ + int batt_status; + + return battery_status(&batt_status) != EC_SUCCESS ? + false : + !!(batt_status & STATUS_INITIALIZED); +} + +/* + * Physical detection of battery. + */ +static enum battery_present battery_check_present_status(void) +{ + enum battery_present batt_pres; + + if (battery_is_cut_off()) + return BP_NO; + + /* Get the physical hardware status */ + batt_pres = battery_hw_present(); + + /* + * If the battery is not physically connected, then no need to perform + * any more checks. + */ + if (batt_pres == BP_NO) + return BP_NO; + + /* + * If the battery is present now and was present last time we checked, + * return early. + */ + if ((batt_pres == BP_YES) && (batt_pres == batt_pres_prev)) + return BP_YES; + + /* + * Check battery initialization. If the battery is not initialized, + * then return BP_NOT_SURE. Battery could be in ship + * mode and might require pre-charge current to wake it up. BP_NO is not + * returned here because charger state machine will not provide + * pre-charge current assuming that battery is not present. + */ + if (!board_battery_is_initialized()) + return BP_NOT_SURE; + + return BP_YES; +} + +enum battery_present battery_is_present(void) +{ + batt_pres_prev = battery_check_present_status(); + return batt_pres_prev; +} diff --git a/baseboard/brya/build.mk b/baseboard/brya/build.mk new file mode 100644 index 0000000000..c6e93c63f2 --- /dev/null +++ b/baseboard/brya/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya baseboard specific files build +# + +baseboard-y= +baseboard-y+=baseboard.o +baseboard-y+=battery_presence.o +baseboard-y+=cbi.o +baseboard-$(HAS_TASK_PROCHOT)+=prochot.o +baseboard-y+=usb_pd_policy.o diff --git a/baseboard/brya/cbi.c b/baseboard/brya/cbi.c new file mode 100644 index 0000000000..f6e5034561 --- /dev/null +++ b/baseboard/brya/cbi.c @@ -0,0 +1,58 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#include + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +static uint8_t board_id; + +uint8_t get_board_id(void) +{ + return board_id; +} + +__overridable void board_cbi_init(void) +{ +} + +__overridable void board_init_fw_config(void) +{ +} + +__overridable void board_init_ssfc(void) +{ +} + +/* + * Read CBI from I2C EEPROM and initialize variables for board variants. + */ +static void cbi_init(void) +{ + uint32_t cbi_val; + + /* Board ID */ + if (cbi_get_board_version(&cbi_val) != EC_SUCCESS || + cbi_val > UINT8_MAX) + CPRINTS("CBI: Read Board ID failed"); + else + board_id = cbi_val; + + CPRINTS("Board ID: %d", board_id); + + board_init_fw_config(); + + board_init_ssfc(); + + /* Allow the board project to make runtime changes based on CBI data */ + board_cbi_init(); +} +DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_FIRST); diff --git a/baseboard/brya/cbi.h b/baseboard/brya/cbi.h new file mode 100644 index 0000000000..37e02806bd --- /dev/null +++ b/baseboard/brya/cbi.h @@ -0,0 +1,38 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* brya family-specific CBI functions, shared with Zephyr */ + +#ifndef __CROS_EC_BASEBOARD_CBI_H +#define __CROS_EC_BASEBOARD_CBI_H + +#include "common.h" + +/* + * Return the board revision number. + */ +uint8_t get_board_id(void); + +/** + * Configure run-time data structures and operation based on CBI data. This + * typically includes customization for changes in the BOARD_VERSION and + * FW_CONFIG fields in CBI. This routine is called from the baseboard after + * the CBI data has been initialized. + */ +__override_proto void board_cbi_init(void); + +/** + * Initialize the FW_CONFIG from CBI data. If the CBI data is not valid, set the + * FW_CONFIG to the board specific defaults. + */ +__override_proto void board_init_fw_config(void); + +/** + * Initialize the SSFC from CBI data. If the CBI data is not valid, set the + * SSFC to the board specific defaults. + */ +__override_proto void board_init_ssfc(void); + +#endif /* __CROS_EC_BASEBOARD_CBI_H */ diff --git a/baseboard/brya/charger_bq25720.c b/baseboard/brya/charger_bq25720.c new file mode 100644 index 0000000000..827152e115 --- /dev/null +++ b/baseboard/brya/charger_bq25720.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/baseboard/brya/prochot.c b/baseboard/brya/prochot.c new file mode 100644 index 0000000000..f89ec5a263 --- /dev/null +++ b/baseboard/brya/prochot.c @@ -0,0 +1,266 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "battery.h" +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "console.h" +#include "driver/charger/bq257x0_regs.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "math_util.h" +#include "task.h" + +/* Console output macros */ +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +#define ADT_RATING_W (PD_MAX_POWER_MW / 1000) +#define PROCHOT_EVENT_200MS_TICK TASK_EVENT_CUSTOM_BIT(0) + +struct batt_para { + int battery_continuous_discharge_mw; + int battery_design_mWh; + int flags; + int state_of_charge; +}; + +struct batt_para batt_params; + +static int cal_sys_watt(void) +{ + int adapter_voltage_v; + int IDPM; + int Vacpacn; + int V_iadpt; + int W_adpt; + + Vacpacn = adc_read_channel(ADC_IADPT); + + /* the ratio selectable through IADPT_GAIN bit. */ + V_iadpt = Vacpacn * 1000 / 40; + + IDPM = V_iadpt / CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC; + + adapter_voltage_v = charge_manager_get_charger_voltage() / 1000; + + W_adpt = IDPM * adapter_voltage_v * PROCHOT_ADAPTER_WATT_RATIO / 100; + + return W_adpt; +} + +static int get_batt_parameter(void) +{ + int battery_voltage; + int battery_current; + int battery_design_voltage_mv; + int battery_design_capacity_mAh; + int rv = 0; + + batt_params.flags = 0; + + /* read battery voltage */ + if (sb_read(SB_VOLTAGE, &battery_voltage)) + batt_params.flags |= BATT_FLAG_BAD_VOLTAGE; + + /* Battery_current sometimes return a very huge number + * and cause prochot keep toggling so add (int16_t) to guard it. + */ + if (sb_read(SB_CURRENT, &battery_current)) + batt_params.flags |= BATT_FLAG_BAD_CURRENT; + else + battery_current = (int16_t)battery_current; + + /* calculate battery wattage and convert to mW */ + batt_params.battery_continuous_discharge_mw = + (battery_voltage * battery_current) / 1000; + + rv |= sb_read(SB_DESIGN_VOLTAGE, &battery_design_voltage_mv); + rv |= sb_read(SB_DESIGN_CAPACITY, &battery_design_capacity_mAh); + batt_params.battery_design_mWh = + (battery_design_voltage_mv * battery_design_capacity_mAh) / + 1000; + + if (sb_read(SB_RELATIVE_STATE_OF_CHARGE, &batt_params.state_of_charge)) + batt_params.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; + + return (batt_params.flags || rv); +} + +static int get_chg_watt(void) +{ + int adapter_current_ma; + int adapter_voltage_mv; + int adapter_wattage; + + /* Get adapter wattage */ + adapter_current_ma = charge_manager_get_charger_current(); + adapter_voltage_mv = charge_manager_get_charger_voltage(); + adapter_wattage = adapter_current_ma * adapter_voltage_mv / 1000 / 1000; + + return adapter_wattage; +} + +static int set_register_charge_option(void) +{ + int reg; + int rv; + + rv = i2c_read16(I2C_PORT_CHARGER, BQ25710_SMBUS_ADDR1_FLAGS, + BQ25710_REG_CHARGE_OPTION_0, ®); + if (rv == EC_SUCCESS) { + reg = SET_BQ_FIELD(BQ257X0, CHARGE_OPTION_0, IADP_GAIN, 1, reg); + /* if AC only, disable IDPM, + * because it will cause charger keep asserting PROCHOT + */ + if (!battery_hw_present()) + reg = SET_BQ_FIELD(BQ257X0, CHARGE_OPTION_0, EN_IDPM, 0, + reg); + else + reg = SET_BQ_FIELD(BQ257X0, CHARGE_OPTION_0, EN_IDPM, 1, + reg); + } else { + CPRINTS("Failed to read bq25720"); + return rv; + } + + return i2c_write16(I2C_PORT_CHARGER, BQ25710_SMBUS_ADDR1_FLAGS, + BQ25710_REG_CHARGE_OPTION_0, reg); +} + +static void assert_prochot(void) +{ + int adapter_wattage; + int adpt_mw; + int total_W; + + /* Set 0x12 bit4=1 */ + if (set_register_charge_option()) { + CPRINTS("Failed to set bq25720"); + return; + } + + /* Calculate actual system W */ + adpt_mw = cal_sys_watt(); + + /* If any battery flag is set and no AC, skip this cycle and hope + * the next cycle succeeds + */ + if (get_batt_parameter() && !extpower_is_present()) + return; + + /* When battery is discharging, the battery current will be negative */ + if (batt_params.battery_continuous_discharge_mw < 0) { + total_W = adpt_mw + + ABS(batt_params.battery_continuous_discharge_mw); + } else { + /* we won't assert prochot when battery is charging. */ + total_W = adpt_mw; + } + total_W /= 1000; + + /* Get adapter wattage */ + adapter_wattage = get_chg_watt(); + + /* + * no AC, don't assert PROCHOT. + * If AC exists, PROCHOT will only be asserted when the battery + * is physical present and the battery wattage is over 95% of + * the max continue discharge current of battery spec. + * When the battery wattage is lower than 85% of the max + * continue discharge current of battery spec, PROCHOT will be + * deasserted. + */ + if (!extpower_is_present()) { + if (!battery_hw_present()) { + gpio_set_level(GPIO_EC_PROCHOT_ODL, 1); + } else { + batt_params.battery_continuous_discharge_mw = ABS( + batt_params.battery_continuous_discharge_mw); + if ((batt_params.battery_continuous_discharge_mw / + 1000) > BATT_MAX_CONTINUE_DISCHARGE_WATT * + PROCHOT_ASSERTION_BATTERY_RATIO / + 100) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 0); + else if ((batt_params.battery_continuous_discharge_mw / + 1000) < + BATT_MAX_CONTINUE_DISCHARGE_WATT * + PROCHOT_DEASSERTION_BATTERY_RATIO / + 100) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 1); + } + return; + } + + if (adapter_wattage >= ADT_RATING_W) { + /* if adapter >= 60W */ + /* if no battery or battery < 10% */ + if (!battery_hw_present() || + batt_params.state_of_charge <= 10) { + if (total_W > + ADT_RATING_W * PROCHOT_ASSERTION_PD_RATIO / 100) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 0); + else if (total_W <= + ADT_RATING_W * PROCHOT_DEASSERTION_PD_RATIO / + 100) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 1); + } else { + /* AC + battery */ + if (total_W > + (ADT_RATING_W + BATT_MAX_CONTINUE_DISCHARGE_WATT)) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 0); + else if (total_W < + (ADT_RATING_W + + BATT_MAX_CONTINUE_DISCHARGE_WATT) * + PROCHOT_DEASSERTION_PD_BATTERY_RATIO / + 100) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 1); + } + } else { + /* if adapter < 60W */ + /* if no battery or battery < 10% */ + if (!battery_hw_present() || + batt_params.state_of_charge <= 10) { + if (total_W > (adapter_wattage * + PROCHOT_ASSERTION_ADAPTER_RATIO / 100)) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 0); + else if (total_W <= + (adapter_wattage * + PROCHOT_DEASSERTION_ADAPTER_RATIO / 100)) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 1); + } else { + /* AC + battery */ + if (total_W > (adapter_wattage + + BATT_MAX_CONTINUE_DISCHARGE_WATT)) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 0); + else if (total_W < + (adapter_wattage + + (BATT_MAX_CONTINUE_DISCHARGE_WATT * + PROCHOT_DEASSERTION_ADAPTER_BATT_RATIO / + 100))) + gpio_set_level(GPIO_EC_PROCHOT_ODL, 1); + } + } +} + +/* Called by hook task every 200 ms */ +static void control_prochot_tick(void) +{ + task_set_event(TASK_ID_PROCHOT, PROCHOT_EVENT_200MS_TICK); +} +DECLARE_HOOK(HOOK_TICK, control_prochot_tick, HOOK_PRIO_DEFAULT); + +void prochot_task(void *u) +{ + uint32_t evt; + + while (1) { + evt = task_wait_event(-1); + + if (evt & PROCHOT_EVENT_200MS_TICK) + assert_prochot(); + } +} diff --git a/baseboard/brya/relevant-paths.txt b/baseboard/brya/relevant-paths.txt new file mode 100644 index 0000000000..6133d9947f --- /dev/null +++ b/baseboard/brya/relevant-paths.txt @@ -0,0 +1,27 @@ +# Here you can place files of interest to be included in the commit message for +# merge commits to firmware-brya-14505.B +# +# Brya branching strategy is to merge all changes from ToT on a weekly basis. +# No separate cherry-picks allowed for EC repo in the firmware branch. +# How to perform a merge: +# $ cd /path/to/src/platform/ec +# $ git checkout cros/main +# $ util/update_release_branch.py --baseboard brya --relevant_paths_file +# baseboard/brya/relevant-paths.txt firmware-brya-14505.B-main +# $ make buildall +# $ repo upload --cbr . --no-verify +# Remove the cq-orchestrator line form the commit message +# Assign one of Brya EC owners as a reviewer +# +driver/bc12/pi3usb9201_public.* +driver/charger/bq25710.* +driver/ppc/nx20p348x.* +driver/ppc/syv682x_public.* +driver/retimer/bb_retimer_public.* +driver/tcpm/nct38xx.* +driver/tcpm/ps8xxx_public.* +driver/tcpm/tcpci.* +include/power/alderlake* +include/intel_x86.h +power/alderlake* +power/intel_x86.c diff --git a/baseboard/brya/usb_pd_policy.c b/baseboard/brya/usb_pd_policy.c new file mode 100644 index 0000000000..377ef0462e --- /dev/null +++ b/baseboard/brya/usb_pd_policy.c @@ -0,0 +1,244 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Shared USB-C policy for Brya boards */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "timer.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "usb_pd_vdo.h" +#include "usbc_ppc.h" +#include "util.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Only allow vconn swap after the PP5000_Z1 rail is enabled */ + return gpio_get_level(GPIO_SEQ_EC_DSW_PWROK); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + prev_en = ppc_is_sourcing_vbus(port); + + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +int board_vbus_source_enabled(int port) +{ + /* BJ port is always sink. */ + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return 0; + return ppc_is_sourcing_vbus(port); +} + +#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE +/* ----------------- Vendor Defined Messages ------------------ */ +/* Responses specifically for the enablement of TBT mode in the role of UFP */ + +#define OPOS_TBT 1 + +static const union tbt_mode_resp_device vdo_tbt_modes[1] = { { + .tbt_alt_mode = 0x0001, + .tbt_adapter = TBT_ADAPTER_TBT3, + .intel_spec_b0 = 0, + .vendor_spec_b0 = 0, + .vendor_spec_b1 = 0, +} }; + +static const uint32_t vdo_idh = VDO_IDH(1, /* Data caps as USB host */ + 0, /* Not a USB device */ + IDH_PTYPE_PERIPH, 1, /* Supports alt + modes */ + USB_VID_GOOGLE); + +static const uint32_t vdo_idh_rev30 = + VDO_IDH_REV30(1, /* Data caps as USB host */ + 0, /* Not a USB device */ + IDH_PTYPE_PERIPH, 1, /* Supports alt modes */ + IDH_PTYPE_DFP_HOST, USB_TYPEC_RECEPTACLE, USB_VID_GOOGLE); + +static const uint32_t vdo_product = + VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); + +/* TODO(b/168890624): add USB4 to capability once USB4 response implemented */ +static const uint32_t vdo_ufp1 = VDO_UFP1( + (VDO_UFP1_CAPABILITY_USB20 | VDO_UFP1_CAPABILITY_USB32), + USB_TYPEC_RECEPTACLE, VDO_UFP1_ALT_MODE_TBT3, USB_R30_SS_U40_GEN3); + +static const uint32_t vdo_dfp = + VDO_DFP((VDO_DFP_HOST_CAPABILITY_USB20 | VDO_DFP_HOST_CAPABILITY_USB32 | + VDO_DFP_HOST_CAPABILITY_USB4), + USB_TYPEC_RECEPTACLE, 1 /* Port 1 */); + +static int svdm_tbt_compat_response_identity(int port, uint32_t *payload) +{ + /* + * For PD 3.1 compliance test TEST.PD.VDM.SRC.2, + * we should return NAK if we cannot recognized the incoming SVID. + */ + if (PD_VDO_VID(payload[0]) == USB_SID_PD) { + /* TODO(b/154962766): Get an XID */ + payload[VDO_I(CSTAT)] = VDO_CSTAT(0); + payload[VDO_I(PRODUCT)] = vdo_product; + + if (pd_get_rev(port, TCPCI_MSG_SOP) == PD_REV30) { + /* PD Revision 3.0 */ + payload[VDO_I(IDH)] = vdo_idh_rev30; + payload[VDO_I(PTYPE_UFP1_VDO)] = vdo_ufp1; + /* TODO(b/181620145): Customize for brya */ + payload[VDO_I(PTYPE_UFP2_VDO)] = 0; + payload[VDO_I(PTYPE_DFP_VDO)] = vdo_dfp; + return VDO_I(PTYPE_DFP_VDO) + 1; + } + + /* PD Revision 2.0 */ + payload[VDO_I(IDH)] = vdo_idh; + return VDO_I(PRODUCT) + 1; + } else { + return 0; /* NAK */ + } +} + +static int svdm_tbt_compat_response_svids(int port, uint32_t *payload) +{ + /* + * For PD 3.1 compliance test TEST.PD.VDM.SRC.2, + * we should return NAK if we cannot recognized the incoming SVID. + */ + if (PD_VDO_VID(payload[0]) == USB_SID_PD) { + payload[1] = VDO_SVID(USB_VID_INTEL, 0); + return 2; + } else { + return 0; /* NAK */ + } +} + +static int svdm_tbt_compat_response_modes(int port, uint32_t *payload) +{ + if (PD_VDO_VID(payload[0]) == USB_VID_INTEL) { + memcpy(payload + 1, vdo_tbt_modes, sizeof(vdo_tbt_modes)); + return ARRAY_SIZE(vdo_tbt_modes) + 1; + } else { + return 0; /* NAK */ + } +} + +/* Track whether we've been enabled to ACK TBT EnterModes requests */ +static bool tbt_ufp_ack_allowed[CONFIG_USB_PD_PORT_MAX_COUNT]; + +__override enum ec_status +board_set_tbt_ufp_reply(int port, enum typec_tbt_ufp_reply reply) +{ + /* Note: Host command has already bounds-checked port */ + if (reply == TYPEC_TBT_UFP_REPLY_ACK) + tbt_ufp_ack_allowed[port] = true; + else if (reply == TYPEC_TBT_UFP_REPLY_NAK) + tbt_ufp_ack_allowed[port] = false; + else + return EC_RES_INVALID_PARAM; + + return EC_RES_SUCCESS; +} + +static int svdm_tbt_compat_response_enter_mode(int port, uint32_t *payload) +{ + mux_state_t mux_state = 0; + + /* Do not enter mode while CPU is off. */ + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) + return 0; /* NAK */ + + /* Do not enter mode while policy disallows it */ + if (!tbt_ufp_ack_allowed[port]) + return 0; /* NAK */ + + if ((PD_VDO_VID(payload[0]) != USB_VID_INTEL) || + (PD_VDO_OPOS(payload[0]) != OPOS_TBT)) + return 0; /* NAK */ + + mux_state = usb_mux_get(port); + /* + * Ref: USB PD 3.0 Spec figure 6-21 Successful Enter Mode sequence + * UFP (responder) should be in USB mode or safe mode before entering a + * Mode that requires the reconfiguring of any pins. + */ + if ((mux_state & USB_PD_MUX_USB_ENABLED) || + (mux_state & USB_PD_MUX_SAFE_MODE)) { + pd_ufp_set_enter_mode(port, payload); + set_tbt_compat_mode_ready(port); + + /* + * Ref: Above figure 6-21: UFP (responder) should be in the new + * mode before sending the ACK. However, our mux set sequence + * may exceed tVDMEnterMode, so wait as long as we can + * before sending the reply without violating that timer. + */ + if (!usb_mux_set_completed(port)) + usleep(PD_T_VDM_E_MODE / 2); + + CPRINTS("UFP Enter TBT mode"); + return 1; /* ACK */ + } + + CPRINTS("UFP failed to enter TBT mode(mux=0x%x)", mux_state); + return 0; +} + +const struct svdm_response svdm_rsp = { + .identity = &svdm_tbt_compat_response_identity, + .svids = &svdm_tbt_compat_response_svids, + .modes = &svdm_tbt_compat_response_modes, + .enter_mode = &svdm_tbt_compat_response_enter_mode, + .amode = NULL, + .exit_mode = NULL, +}; +#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */ diff --git a/baseboard/cherry/baseboard.c b/baseboard/cherry/baseboard.c new file mode 100644 index 0000000000..c162331f89 --- /dev/null +++ b/baseboard/cherry/baseboard.c @@ -0,0 +1,524 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Cherry baseboard-specific configuration */ + +#include "adc.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/bc12/mt6360.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/ppc/rt1718s.h" +#include "driver/ppc/syv682x.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/tcpm/rt1718s.h" +#include "driver/temp_sensor/thermistor.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "regulator.h" +#include "spi.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "timer.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usb_tc_sm.h" +#include "usbc_ppc.h" + +static void bc12_interrupt(enum gpio_signal signal); +static void ppc_interrupt(enum gpio_signal signal); +static void xhci_init_done_interrupt(enum gpio_signal signal); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +/* Wake-up pins for hibernate */ +enum gpio_signal hibernate_wake_pins[] = { + GPIO_AC_PRESENT, + GPIO_LID_OPEN, + GPIO_POWER_BUTTON_L, +}; +int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* Override default setting, called after charger_chips_init */ +static void baseboard_charger_init(void) +{ + /* b/198707662#comment9 */ + int reg = (4096 / ISL9238_INPUT_VOLTAGE_REF_STEP) + << ISL9238_INPUT_VOLTAGE_REF_SHIFT; + + i2c_write16(I2C_PORT_CHARGER, ISL923X_ADDR_FLAGS, + ISL9238_REG_INPUT_VOLTAGE, reg); +} +DECLARE_HOOK(HOOK_INIT, baseboard_charger_init, HOOK_PRIO_DEFAULT + 2); + +__override void board_hibernate_late(void) +{ + /* + * Turn off PP5000_A. Required for devices without Z-state. + * Don't care for devices with Z-state. + */ + gpio_set_level(GPIO_EN_PP5000_A, 0); + gpio_set_level(GPIO_EN_SLP_Z, 1); + + /* should not reach here */ + __builtin_unreachable(); +} + +void board_hibernate(void) +{ + isl9238c_hibernate(CHARGER_SOLO); +} + +static void board_tcpc_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_INT_ODL); +} +/* Must be done after I2C */ +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void rt1718s_tcpc_interrupt(enum gpio_signal signal) +{ + schedule_deferred_pd_interrupt(1); +} + +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + /* Convert to mV (3000mV/1024). */ + { "VBUS", ADC_MAX_MVOLT * 10, ADC_READ_MAX + 1, 0, CHIP_ADC_CH0 }, + { "BOARD_ID_0", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH1 }, + { "BOARD_ID_1", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH2 }, + /* AMON/BMON gain = 17.97 */ + { "CHARGER_AMON_R", ADC_MAX_MVOLT * 1000 / 17.97, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH3 }, + { "CHARGER_PMON", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH6 }, + { "TEMP_SENSOR_CHG", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH7 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER, + }, +}; + +/* PPC */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .i2c_port = I2C_PORT_PPC0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + .frs_en = GPIO_USB_C0_FRS_EN, + }, + { + .i2c_port = I2C_PORT_PPC1, + .i2c_addr_flags = RT1718S_I2C_ADDR1_FLAGS, + .drv = &rt1718s_ppc_drv, + }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* BC12 */ +const struct mt6360_config_t mt6360_config = { + .i2c_port = 0, + .i2c_addr_flags = MT6360_PMU_I2C_ADDR_FLAGS, +}; + +__maybe_unused const struct pi3usb9201_config_t + pi3usb9201_bc12_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [0] = { + .i2c_port = I2C_PORT_USB0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + } + /* [1]: unused */ +}; + +struct bc12_config bc12_ports[CONFIG_USB_PD_PORT_MAX_COUNT] = { +#ifdef CONFIG_BC12_DETECT_PI3USB9201 + { .drv = &pi3usb9201_drv }, +#elif defined(CONFIG_BC12_DETECT_MT6360) + { .drv = &mt6360_drv }, +#else +#error must pick one of PI3USB9201 or MT6360 for port 0 +#endif + { .drv = &rt1718s_bc12_drv }, +}; + +static void bc12_interrupt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void ppc_interrupt(enum gpio_signal signal) +{ + syv682x_interrupt(0); +} + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + gpio_set_level(GPIO_EC_BL_EN_OD, 1); + gpio_set_level(GPIO_DP_DEMUX_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + gpio_set_level(GPIO_EC_BL_EN_OD, 0); + gpio_set_level(GPIO_DP_DEMUX_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* USB-A */ +const int usb_port_enable[] = { + GPIO_EN_PP5000_USB_A0_VBUS_X, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +__maybe_unused void xhci_init_done_interrupt(enum gpio_signal signal) +{ + enum usb_charge_mode mode = gpio_get_level(signal) ? + USB_CHARGE_MODE_ENABLED : + USB_CHARGE_MODE_DISABLED; + + for (int i = 0; i < USB_PORT_COUNT; i++) + usb_charge_set_mode(i, mode, USB_ALLOW_SUSPEND_CHARGE); + + /* + * Trigger hard reset to cycle Vbus on Type-C ports, recommended by + * USB 3.2 spec 10.3.1.1. + */ + if (gpio_get_level(signal)) { + for (int i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (tc_is_attached_src(i)) + pd_dpm_request(i, DPM_REQUEST_HARD_RESET_SEND); + } + } +} + +/* + * I2C channels (A, B, and C) are using the same timing registers (00h~07h) + * at default. + * In order to set frequency independently for each channels, + * We use timing registers 09h~0Bh, and the supported frequency will be: + * 50KHz, 100KHz, 400KHz, or 1MHz. + * I2C channels (D, E and F) can be set different frequency on different ports. + * The I2C(D/E/F) frequency depend on the frequency of SMBus Module and + * the individual prescale register. + * The frequency of SMBus module is 24MHz on default. + * The allowed range of I2C(D/E/F) frequency is as following setting. + * SMBus Module Freq = PLL_CLOCK / ((IT83XX_ECPM_SCDCR2 & 0x0F) + 1) + * (SMBus Module Freq / 510) <= I2C Freq <= (SMBus Module Freq / 8) + * Channel D has multi-function and can be used as UART interface. + * Channel F is reserved for EC debug. + */ + +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "bat_chg", + .port = IT83XX_I2C_CH_A, + .kbps = 100, + .scl = GPIO_I2C_A_SCL, + .sda = GPIO_I2C_A_SDA }, + { .name = "sensor", + .port = IT83XX_I2C_CH_B, + .kbps = 400, + .scl = GPIO_I2C_B_SCL, + .sda = GPIO_I2C_B_SDA }, + { .name = "usb0", + .port = IT83XX_I2C_CH_C, + .kbps = 400, + .scl = GPIO_I2C_C_SCL, + .sda = GPIO_I2C_C_SDA }, + { .name = "usb1", + .port = IT83XX_I2C_CH_E, + .kbps = 1000, + .scl = GPIO_I2C_E_SCL, + .sda = GPIO_I2C_E_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc) +{ + return (cmd_desc->port == I2C_PORT_VIRTUAL_BATTERY); +} + +/* TCPC */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + /* TCPC is embedded within EC so no i2c config needed */ + .drv = &it8xxx2_tcpm_drv, + /* Alert is active-low, push-pull */ + .flags = 0, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB1, + .addr_flags = RT1718S_I2C_ADDR1_FLAGS, + }, + .drv = &rt1718s_tcpm_drv, + }, +}; + +__override int board_rt1718s_init(int port) +{ + static bool gpio_initialized; + + if (!system_jumped_late() && !gpio_initialized) { + /* set GPIO 1~3 as push pull, as output, output low. */ + rt1718s_gpio_set_flags(port, RT1718S_GPIO1, GPIO_OUT_LOW); + rt1718s_gpio_set_flags(port, RT1718S_GPIO2, GPIO_OUT_LOW); + rt1718s_gpio_set_flags(port, RT1718S_GPIO3, GPIO_OUT_LOW); + gpio_initialized = true; + } + + /* gpio 1/2 output high when receiving frx signal */ + RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_GPIO1_VBUS_CTRL, + RT1718S_GPIO_VBUS_CTRL_FRS_RX_VBUS, + 0xFF)); + RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_GPIO2_VBUS_CTRL, + RT1718S_GPIO_VBUS_CTRL_FRS_RX_VBUS, + 0xFF)); + + /* Turn on SBU switch */ + RETURN_ERROR( + rt1718s_update_bits8(port, RT1718S_RT2_SBU_CTRL_01, + RT1718S_RT2_SBU_CTRL_01_SBU_VIEN | + RT1718S_RT2_SBU_CTRL_01_SBU2_SWEN | + RT1718S_RT2_SBU_CTRL_01_SBU1_SWEN, + 0xFF)); + /* Trigger GPIO 1/2 change when FRS signal received */ + RETURN_ERROR(rt1718s_update_bits8( + port, RT1718S_FRS_CTRL3, + RT1718S_FRS_CTRL3_FRS_RX_WAIT_GPIO2 | + RT1718S_FRS_CTRL3_FRS_RX_WAIT_GPIO1, + RT1718S_FRS_CTRL3_FRS_RX_WAIT_GPIO2 | + RT1718S_FRS_CTRL3_FRS_RX_WAIT_GPIO1)); + /* Set FRS signal detect time to 46.875us */ + RETURN_ERROR(rt1718s_update_bits8(port, RT1718S_FRS_CTRL1, + RT1718S_FRS_CTRL1_FRSWAPRX_MASK, + 0xFF)); + + return EC_SUCCESS; +} + +const struct cc_para_t *board_get_cc_tuning_parameter(enum usbpd_port port) +{ + const static struct cc_para_t cc_parameter = { + .rising_time = IT83XX_TX_PRE_DRIVING_TIME_1_UNIT, + .falling_time = IT83XX_TX_PRE_DRIVING_TIME_2_UNIT, + }; + + if (port == USBPD_PORT_A) + return &cc_parameter; + return NULL; +} + +uint16_t tcpc_get_alert_status(void) +{ + /* + * C0 TCPC is embedded in the EC and processes interrupts in the + * chip code (it83xx/intc.c) + */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) + return PD_STATUS_TCPC_ALERT_1; + return 0; +} + +void board_reset_pd_mcu(void) +{ + /* + * C0: The internal TCPC on ITE EC does not have a reset signal, + * but it will get reset when the EC gets reset. + */ + /* C1: Add code if TCPC chips need a reset */ +} + +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* + * We ignore the cc_pin and PPC vconn because polarity and PPC vconn + * should already be set correctly in the PPC driver via the pd + * state machine. + */ +} + +int board_set_active_charge_port(int port) +{ + int i; + bool is_valid_port = (port == 0 || port == 1); + + if (!is_valid_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTS("Disabling C%d as sink failed.", i); + } + rt1718s_gpio_set_level(1, GPIO_EN_USB_C1_VBUS_L, 1); + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTS("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTS("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTS("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + rt1718s_gpio_set_level(1, GPIO_EN_USB_C1_VBUS_L, !(port == 1)); + + return EC_SUCCESS; +} + +int ppc_get_alert_status(int port) +{ + if (port == 0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + + /* TODO: add rt1718s */ + return 0; +} +/* SD Card */ +int board_regulator_get_info(uint32_t index, char *name, uint16_t *num_voltages, + uint16_t *voltages_mv) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_get_info(id, name, num_voltages, voltages_mv); +} + +int board_regulator_enable(uint32_t index, uint8_t enable) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_enable(id, enable); +} + +int board_regulator_is_enabled(uint32_t index, uint8_t *enabled) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_is_enabled(id, enabled); +} + +int board_regulator_set_voltage(uint32_t index, uint32_t min_mv, + uint32_t max_mv) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_set_voltage(id, min_mv, max_mv); +} + +int board_regulator_get_voltage(uint32_t index, uint32_t *voltage_mv) +{ + enum mt6360_regulator_id id = index; + + return mt6360_regulator_get_voltage(id, voltage_mv); +} + +static void baseboard_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); +#ifndef BOARD_CHERRY + gpio_enable_interrupt(GPIO_AP_XHCI_INIT_DONE); +#endif +} +DECLARE_HOOK(HOOK_INIT, baseboard_init, HOOK_PRIO_DEFAULT - 1); + +__override int board_rt1718s_set_frs_enable(int port, int enable) +{ + if (port == 1) + /* + * Use set_flags (implemented by a single i2c write) instead + * of set_level (= i2c_update) to save one read operation in + * FRS path. + */ + rt1718s_gpio_set_flags(port, GPIO_EN_USB_C1_FRS, + enable ? GPIO_OUT_HIGH : GPIO_OUT_LOW); + return EC_SUCCESS; +} + +__override int board_get_vbus_voltage(int port) +{ + int voltage = 0; + + switch (port) { + case 0: + voltage = adc_read_channel(ADC_VBUS); + break; + case 1: + rt1718s_get_adc(port, RT1718S_ADC_VBUS1, &voltage); + break; + default: + return 0; + } + + return voltage; +} diff --git a/baseboard/cherry/baseboard.h b/baseboard/cherry/baseboard.h new file mode 100644 index 0000000000..e49222fc9e --- /dev/null +++ b/baseboard/cherry/baseboard.h @@ -0,0 +1,246 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Cherry board configuration */ + +#ifndef __CROS_EC_BASEBOARD_H +#define __CROS_EC_BASEBOARD_H + +/* IT81202-bx config */ +/* + * NOTE: we need to make correct VCC voltage selection here if EC's VCC isn't + * connect to 1.8v on other versions. + */ +#define CONFIG_IT83XX_VCC_1P8V +#define CONFIG_IT83XX_I2C_CMD_QUEUE + +/* + * On power-on, H1 releases the EC from reset but then quickly asserts and + * releases the reset a second time. This means the EC sees 2 resets: + * (1) power-on reset, (2) reset-pin reset. This config will + * allow the second reset to be treated as a power-on. + */ +#define CONFIG_BOARD_RESET_AFTER_POWER_ON +#define CONFIG_CHIPSET_MT8192 +#define CONFIG_EXTPOWER_GPIO +#define CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE + +/* Chipset */ +#define CONFIG_CMD_AP_RESET_LOG +#undef CONFIG_CMD_POWERINDEBUG +#define CONFIG_HOST_COMMAND_STATUS +#define CONFIG_LOW_POWER_IDLE +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_COMMON +#define CONFIG_PWM +#define CONFIG_PWM_KBLIGHT +#define CONFIG_VBOOT_HASH +#define CONFIG_VOLUME_BUTTONS +#define CONFIG_WP_ACTIVE_HIGH + +/* Battery */ +#define CONFIG_BATTERY_CUT_OFF +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_BATTERY_SMART + +/* BC12 */ +#ifdef BOARD_CHERRY +#define CONFIG_BC12_DETECT_PI3USB9201 +#endif +#define CONFIG_BC12_DETECT_MT6360 +#undef CONFIG_BC12_SINGLE_DRIVER +#define CONFIG_USB_CHARGER + +/* CBI */ +#define CONFIG_BOARD_VERSION_CBI +#define CONFIG_CBI_EEPROM +#define CONFIG_CMD_CBI +#define I2C_PORT_EEPROM IT83XX_I2C_CH_A +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* Charger */ +#define ADC_AMON_BMON ADC_CHARGER_AMON_R /* ADC name remap */ +#define ADC_PSYS ADC_CHARGER_PMON /* ADC name remap */ +#define CONFIG_CHARGE_MANAGER +#define CONFIG_CHARGER +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_DISCHARGE_ON_AC +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_ISL9238C +#define CONFIG_CHARGER_MAINTAIN_VBAT +/* Not used in boot flow, set to 0 to suppress system_can_boot_ap warning */ +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 0 +#define CONFIG_CHARGER_OTG +#define CONFIG_CHARGER_PSYS +#define CONFIG_CHARGER_PSYS_READ +#define CONFIG_CHARGER_SENSE_RESISTOR 10 /* BOARD_RS2 */ +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 /* BOARD_RS1 */ +#define CONFIG_CMD_CHARGER_ADC_AMON_BMON + +/* Keyboard */ +#define CONFIG_CMD_KEYBOARD +#define CONFIG_KEYBOARD_COL2_INVERTED +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_USE_GPIO + +/* I2C */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER +#define CONFIG_I2C_PASSTHRU_RESTRICTED +#define CONFIG_I2C_VIRTUAL_BATTERY +#define I2C_PORT_CHARGER IT83XX_I2C_CH_A +#define I2C_PORT_BATTERY IT83XX_I2C_CH_A +#define I2C_PORT_ACCEL IT83XX_I2C_CH_B +#define I2C_PORT_PPC0 IT83XX_I2C_CH_C +#define I2C_PORT_PPC1 IT83XX_I2C_CH_E +#define I2C_PORT_USB0 IT83XX_I2C_CH_C +#define I2C_PORT_USB1 IT83XX_I2C_CH_E +#define I2C_PORT_USB_MUX0 IT83XX_I2C_CH_C +#define I2C_PORT_USB_MUX1 IT83XX_I2C_CH_E +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define CONFIG_SMBUS_PEC + +/* LED */ +#define CONFIG_LED_COMMON + +/* PD / USB-C / PPC */ +#define CONFIG_BC12_DETECT_RT1718S +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_HOSTCMD_PD_CONTROL +#define CONFIG_IT83XX_TUNE_CC_PHY +#define CONFIG_USBC_PPC +#define CONFIG_USBC_PPC_DEDICATED_INT +#define CONFIG_USBC_PPC_POLARITY +#define CONFIG_USBC_PPC_RT1718S +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_VCONN +#define CONFIG_USBC_SS_MUX +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USBC_RETIMER_PS8802 /* C0 */ +#define CONFIG_USB_MUX_ANX3443 /* C1 */ +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_USB_PD_DISCHARGE +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_DPS +#define CONFIG_USB_PD_DP_HPD_GPIO +#define CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_FRS_PPC +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 +#define CONFIG_USB_PD_LOGGING +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_PPC +#define CONFIG_USB_PD_REV30 +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP +#define CONFIG_USB_PD_TCPM_RT1718S +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_PD_TRY_SRC +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USB_PD_VBUS_MEASURE_BY_BOARD +#define CONFIG_USB_PID 0x5054 +#define CONFIG_USB_POWER_DELIVERY + +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ + +/* USB-A */ +#define CONFIG_USB_PORT_POWER_DUMB +#ifndef BOARD_CHERRY +#define CONFIG_USB_PORT_POWER_DUMB_CUSTOM_HOOK +#endif +#define USB_PORT_COUNT USBA_PORT_COUNT + +/* UART */ +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Sensor */ +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_CMD_ACCELS + +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* SPI / Host Command */ +#define CONFIG_SPI + +/* MKBP */ +#define CONFIG_MKBP_EVENT + +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_USE_GPIO + +/* Vboot Config */ +#define CONFIG_CRC8 +#define CONFIG_VBOOT_EFS2 +#define CONFIG_VBOOT_HASH +#define CONFIG_VSTORE +#define CONFIG_VSTORE_SLOT_COUNT 1 + +/* Voltage regulator control */ +#define CONFIG_HOSTCMD_REGULATOR + +/* Define the host events which are allowed to wakeup AP in S3. */ +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_HANG_DETECT) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* And the MKBP events */ +#define CONFIG_MKBP_EVENT_WAKEUP_MASK \ + (BIT(EC_MKBP_EVENT_KEY_MATRIX) | BIT(EC_MKBP_EVENT_HOST_EVENT)) + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "power/mt8192.h" +#include "registers.h" + +enum adc_channel { + ADC_VBUS, /* ADC 0 */ + ADC_BOARD_ID, /* ADC 1 */ + ADC_SKU_ID, /* ADC 2 */ + ADC_CHARGER_AMON_R, /* ADC 3 */ + ADC_CHARGER_PMON, /* ADC 6 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC 7 */ + + /* Number of ADC channels */ + ADC_CH_COUNT, +}; + +enum temp_sensor_id { + TEMP_SENSOR_CHARGER, + TEMP_SENSOR_COUNT, +}; + +void board_reset_pd_mcu(void); +void rt1718s_tcpc_interrupt(enum gpio_signal signal); + +/* RT1718S gpio to pin name mapping */ +#define GPIO_EN_USB_C1_VBUS_L RT1718S_GPIO1 +#define GPIO_EN_USB_C1_5V_OUT RT1718S_GPIO2 +#define GPIO_EN_USB_C1_FRS RT1718S_GPIO3 + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/cherry/build.mk b/baseboard/cherry/build.mk new file mode 100644 index 0000000000..74609511c3 --- /dev/null +++ b/baseboard/cherry/build.mk @@ -0,0 +1,10 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Baseboard specific files build +# + +baseboard-y=baseboard.o +baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o diff --git a/baseboard/cherry/usb_pd_policy.c b/baseboard/cherry/usb_pd_policy.c new file mode 100644 index 0000000000..450f5c06d7 --- /dev/null +++ b/baseboard/cherry/usb_pd_policy.c @@ -0,0 +1,253 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "atomic.h" +#include "charge_manager.h" +#include "chipset.h" +#include "driver/tcpm/rt1718s.h" +#include "driver/tcpm/tcpci.h" +#include "gpio.h" +#include "timer.h" +#include "usb_dp_alt_mode.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_ppc.h" + +#if CONFIG_USB_PD_3A_PORTS != 1 +#error Cherry reference must have at least one 3.0 A port +#endif + +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) + +/* The port that the aux channel is on. */ +static enum { + AUX_PORT_NONE = -1, + AUX_PORT_C0 = 0, + AUX_PORT_C1HDMI = 1, +} aux_port = AUX_PORT_NONE; + +static void aux_switch_port(int port) +{ + if (port != AUX_PORT_NONE) + gpio_set_level_verbose(CC_USBPD, GPIO_DP_PATH_SEL, !port); + aux_port = port; +} + +static void aux_display_disconnected(int port) +{ + /* Gets the other port. C0 -> C1, C1 -> C0. */ + int other_port = !port; + + /* If the current port is not the aux port, nothing needs to be done. */ + if (aux_port != port) + return; + + /* If the other port is connected to a external display, switch aux. */ + if (dp_status[other_port] & DP_FLAGS_DP_ON) + aux_switch_port(other_port); + else + aux_switch_port(AUX_PORT_NONE); +} + +int svdm_get_hpd_gpio(int port) +{ + /* HPD is low active, inverse the result */ + return !gpio_get_level(GPIO_EC_AP_DP_HPD_ODL); +} + +void svdm_set_hpd_gpio(int port, int en) +{ + /* + * Cherry can only output to 1 display port at a time. + * This implements FCFS policy by changing the aux channel. If a + * display is connected to the either port (says A), and the port A + * will be served until the display is disconnected from port A. + * It won't output to the other display which connects to port B. + */ + if (en) { + if (aux_port == AUX_PORT_NONE) + aux_switch_port(port); + } else { + aux_display_disconnected(port); + } + /* + * HPD is low active, inverse the en + */ + gpio_set_level_verbose(CC_USBPD, GPIO_EC_AP_DP_HPD_ODL, !en); +} + +__override int svdm_dp_attention(int port, uint32_t *payload) +{ + int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); + int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + int cur_lvl = svdm_get_hpd_gpio(port); +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + mux_state_t mux_state; + + dp_status[port] = payload[1]; + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && (irq || lvl)) + /* + * Wake up the AP. IRQ or level high indicates a DP sink is now + * present. + */ + if (IS_ENABLED(CONFIG_MKBP_EVENT)) + pd_notify_dp_alt_mode_entry(port); + + /* Its initial DP status message prior to config */ + if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { + if (lvl) + dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; + return 1; + } + +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + if (irq && !lvl) { + /* + * IRQ can only be generated when the level is high, because + * the IRQ is signaled by a short low pulse from the high level. + */ + CPRINTF("ERR:HPD:IRQ&LOW\n"); + return 0; /* nak */ + } + + if (irq && cur_lvl) { + uint64_t now = get_time().val; + /* wait for the minimum spacing between IRQ_HPD if needed */ + if (now < svdm_hpd_deadline[port]) + usleep(svdm_hpd_deadline[port] - now); + + /* generate IRQ_HPD pulse */ + svdm_set_hpd_gpio(port, 0); + /* + * b/171172053#comment14: since the HPD_DSTREAM_DEBOUNCE_IRQ is + * very short (500us), we can use udelay instead of usleep for + * more stable pulse period. + * + * Note that this should be the only difference between our code + * and common code. + */ + udelay(HPD_DSTREAM_DEBOUNCE_IRQ); + svdm_set_hpd_gpio(port, 1); + } else { + svdm_set_hpd_gpio(port, lvl); + } + + /* set the minimum time delay (2ms) for the next HPD IRQ */ + svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + + mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | + (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); + usb_mux_hpd_update(port, mux_state); + +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, lvl); +#endif + + /* ack */ + return 1; +} + +__override void svdm_exit_dp_mode(int port) +{ + dp_flags[port] = 0; + dp_status[port] = 0; +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + if (aux_port == port) + svdm_set_hpd_gpio(port, 0); +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, 0); +#endif +} + +int pd_snk_is_vbus_provided(int port) +{ + static atomic_t vbus_prev[CONFIG_USB_PD_PORT_MAX_COUNT]; + int vbus; + + /* + * Use ppc_is_vbus_present for all ports on Cherry, and + * port 1 on other devices. + */ + if (IS_ENABLED(BOARD_CHERRY) || port == 1) + return ppc_is_vbus_present(port); + + /* b/181203590: use ADC for port 0 (syv682x) */ + vbus = (adc_read_channel(ADC_VBUS) >= PD_V_SINK_DISCONNECT_MAX); + +#ifdef CONFIG_USB_CHARGER + /* + * There's no PPC to inform VBUS change for usb_charger, so inform + * the usb_charger now. + */ + if (!!(vbus_prev[port] != vbus)) + usb_charger_vbus_change(port, vbus); + + if (vbus) + atomic_or(&vbus_prev[port], 1); + else + atomic_clear(&vbus_prev[port]); +#endif + return vbus; +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + pd_set_vbus_discharge(port, 1); + + if (port == 1) + rt1718s_gpio_set_level(port, GPIO_EN_USB_C1_5V_OUT, 0); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_check_vconn_swap(int port) +{ + /* Allow Vconn swap if AP is on. */ + return chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_ON); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + if (port == 1) + rt1718s_gpio_set_level(port, GPIO_EN_USB_C1_5V_OUT, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +int board_vbus_source_enabled(int port) +{ + return ppc_is_sourcing_vbus(port); +} diff --git a/baseboard/dedede/baseboard.c b/baseboard/dedede/baseboard.c index 87eba1771b..22034a09bd 100644 --- a/baseboard/dedede/baseboard.c +++ b/baseboard/dedede/baseboard.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,16 +8,24 @@ #include "adc.h" #include "board_config.h" #include "cbi_fw_config.h" +#include "charger/isl923x_public.h" +#include "charger/sm5803.h" #include "chipset.h" #include "common.h" +#include "console.h" #include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" -#include "intel_x86.h" +#include "power/icelake.h" +#include "power/intel_x86.h" #include "system.h" #include "usb_pd.h" +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + /******************************************************************************/ /* * PWROK signal configuration, see the PWROK Generation Flow Diagram in the @@ -73,7 +81,6 @@ const struct intel_x86_pwrok_signal pwrok_signal_deassert_list[] = { }; const int pwrok_signal_deassert_count = ARRAY_SIZE(pwrok_signal_deassert_list); - /* * Dedede does not use hibernate wake pins, but the super low power "Z-state" * instead in which the EC is powered off entirely. Power will be restored to @@ -104,7 +111,7 @@ __override void board_after_rsmrst(int rsmrst) * can call this function once it detects a VBUS presence change with which we * can trigger the HOOK_AC_CHANGE hook. */ -__override void board_vbus_present_change(void) +__override void board_check_extpower(void) { static int last_extpower_present; int extpower_present = extpower_is_present(); @@ -115,7 +122,7 @@ __override void board_vbus_present_change(void) last_extpower_present = extpower_present; } -uint32_t pp3300_a_pgood; +atomic_t pp3300_a_pgood; __override int intel_x86_get_pg_ec_dsw_pwrok(void) { /* @@ -124,12 +131,25 @@ __override int intel_x86_get_pg_ec_dsw_pwrok(void) * read the ADC values during an interrupt, therefore, this power good * value is updated via ADC threshold interrupts. */ + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* + * The ADC interrupts are disabled in suspend for PP3000_A, + * therefore this value may be stale. Assume that the PGOOD + * follows the enable signal for this case only. + */ + if (!gpio_get_level(GPIO_EN_PP3300_A)) { + CPRINTS("EN_PP3300_A is low, assuming PG is low!"); + atomic_clear(&pp3300_a_pgood); + } else { + atomic_or(&pp3300_a_pgood, 1); + } + } return pp3300_a_pgood; } /* Store away PP300_A good status before sysjumps */ -#define BASEBOARD_SYSJUMP_TAG 0x4242 /* BB */ -#define BASEBOARD_HOOK_VERSION 1 +#define BASEBOARD_SYSJUMP_TAG 0x4242 /* BB */ +#define BASEBOARD_HOOK_VERSION 1 static void pp3300_a_pgood_preserve(void) { @@ -146,13 +166,13 @@ static void baseboard_prepare_power_signals(void) stored = (const int *)system_get_jump_tag(BASEBOARD_SYSJUMP_TAG, &version, &size); if (stored && (version == BASEBOARD_HOOK_VERSION) && - (size == sizeof(pp3300_a_pgood))) + (size == sizeof(pp3300_a_pgood))) /* Valid PP3300 status found, restore before CHIPSET init */ pp3300_a_pgood = *stored; /* Restore pull-up on PG_PP1050_ST_OD */ if (system_jumped_to_this_image() && - gpio_get_level(GPIO_RSMRST_L_PGOOD)) + gpio_get_level(GPIO_PG_EC_RSMRST_ODL)) board_after_rsmrst(1); } DECLARE_HOOK(HOOK_INIT, baseboard_prepare_power_signals, HOOK_PRIO_FIRST); @@ -170,8 +190,8 @@ __override int intel_x86_get_pg_ec_all_sys_pwrgd(void) * PGOOD. */ return gpio_get_level(GPIO_PG_PP1050_ST_OD) && - gpio_get_level(GPIO_PG_DRAM_OD) && - gpio_get_level(GPIO_PG_VCCIO_EXT_OD); + gpio_get_level(GPIO_PG_DRAM_OD) && + gpio_get_level(GPIO_PG_VCCIO_EXT_OD); } __override int power_signal_get_level(enum gpio_signal signal) @@ -182,13 +202,12 @@ __override int power_signal_get_level(enum gpio_signal signal) if (signal == GPIO_PG_EC_ALL_SYS_PWRGD) return intel_x86_get_pg_ec_all_sys_pwrgd(); - if (IS_ENABLED(CONFIG_HOSTCMD_ESPI)) { + if (IS_ENABLED(CONFIG_HOST_INTERFACE_ESPI)) { /* Check signal is from GPIOs or VWs */ if (espi_signal_is_vw(signal)) - return espi_vw_get_wire(signal); + return espi_vw_get_wire((enum espi_vw_signal)signal); } return gpio_get_level(signal); - } void baseboard_all_sys_pgood_interrupt(enum gpio_signal signal) @@ -199,13 +218,14 @@ void baseboard_all_sys_pgood_interrupt(enum gpio_signal signal) * driver to. * Early protos do not pull VCCST_PWRGD below Vil in hardware logic, * so we need to do the same for this signal. - * Pull EN_VCCIO_EXT to LOW, which ensures VCCST_PWRGD remains LOW during - * SLP_S3_L assertion. + * Pull EN_VCCIO_EXT to LOW, which ensures VCCST_PWRGD remains LOW + * during SLP_S3_L assertion. */ if (!gpio_get_level(GPIO_SLP_S3_L)) { gpio_set_level(GPIO_ALL_SYS_PWRGD, 0); gpio_set_level(GPIO_EN_VCCIO_EXT, 0); gpio_set_level(GPIO_EC_AP_VCCST_PWRGD_OD, 0); + gpio_set_level(GPIO_EC_AP_PCH_PWROK_OD, 0); } /* Now chain off to the normal power signal interrupt handler. */ power_signal_interrupt(signal); @@ -213,31 +233,56 @@ void baseboard_all_sys_pgood_interrupt(enum gpio_signal signal) void baseboard_chipset_startup(void) { +#ifdef CONFIG_PWM_KBLIGHT /* Allow keyboard backlight to be enabled */ gpio_set_level(GPIO_EN_KB_BL, 1); +#endif } DECLARE_HOOK(HOOK_CHIPSET_STARTUP, baseboard_chipset_startup, HOOK_PRIO_DEFAULT); void baseboard_chipset_shutdown(void) { +#ifdef CONFIG_PWM_KBLIGHT /* Turn off the keyboard backlight if it's on. */ gpio_set_level(GPIO_EN_KB_BL, 0); +#endif } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, baseboard_chipset_shutdown, HOOK_PRIO_DEFAULT); void board_hibernate_late(void) { + volatile uint32_t busy = 0; + /* Disable any pull-ups on C0 and C1 interrupt lines */ gpio_set_flags(GPIO_USB_C0_INT_ODL, GPIO_INPUT); +#if CONFIG_USB_PD_PORT_MAX_COUNT > 1 gpio_set_flags(GPIO_USB_C1_INT_ODL, GPIO_INPUT); - +#endif /* * Turn on the Z state. This will not return as it will cut power to * the EC. */ gpio_set_level(GPIO_EN_SLP_Z, 1); + + /* + * Interrupts are disabled at this point, so busy-loop to consume some + * time (something on the order of at least 1 second, depending on EC + * chip being used) + */ + while (busy < 100000) + busy++; + + /* + * Still awake despite turning on zombie state? Reset with AP off is + * the best we can do in this situation. + */ + system_reset(SYSTEM_RESET_LEAVE_AP_OFF); + + /* Await our reset */ + while (1) + ; } int board_is_i2c_port_powered(int port) @@ -249,21 +294,28 @@ int board_is_i2c_port_powered(int port) return chipset_in_state(CHIPSET_STATE_ANY_OFF) ? 0 : 1; } -int extpower_is_present(void) +#if defined(CONFIG_CHARGER_RAA489000) || defined(CONFIG_CHARGER_SM5803) +__overridable int extpower_is_present(void) { - int vbus_present = 0; int port; + int rv; + bool acok; + enum ec_error_list (*check_acok)(int port, bool *acok); + + if (IS_ENABLED(CONFIG_CHARGER_RAA489000)) + check_acok = raa489000_is_acok; + else if (IS_ENABLED(CONFIG_CHARGER_SM5803)) + check_acok = sm5803_is_acok; + + for (port = 0; port < board_get_usb_pd_port_count(); port++) { + rv = check_acok(port, &acok); + if ((rv == EC_SUCCESS) && acok) + return 1; + } - /* - * Boards define pd_snk_is_vbus_provided() with something appropriate - * for their hardware - */ - for (port = 0; port < board_get_usb_pd_port_count(); port++) - if (pd_get_power_role(port) == PD_ROLE_SINK) - vbus_present |= pd_snk_is_vbus_provided(port); - - return vbus_present; + return 0; } +#endif __override uint32_t board_override_feature_flags0(uint32_t flags0) { diff --git a/baseboard/dedede/baseboard.h b/baseboard/dedede/baseboard.h index 42fad27e71..6cb781add6 100644 --- a/baseboard/dedede/baseboard.h +++ b/baseboard/dedede/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,79 +8,110 @@ #ifndef __CROS_EC_BASEBOARD_H #define __CROS_EC_BASEBOARD_H +#define CONFIG_LTO + +/* Free up additional flash space. */ +#undef CONFIG_CMD_I2C_SCAN +#undef CONFIG_CMD_I2C_XFER + /* * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_USB_PD_DISCOVERY,\ - EC_CMD_USB_PD_POWER_INFO, EC_CMD_PD_GET_LOG_ENTRY, \ - EC_CMD_MOTION_SENSE_CMD, EC_CMD_GET_NEXT_EVENT +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* * Variant EC defines. Pick one: * VARIANT_DEDEDE_EC_NPCX796FC */ -#if defined(VARIANT_DEDEDE_EC_NPCX796FC) - /* NPCX7 config */ - #define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ - #define NPCX_TACH_SEL2 0 /* No tach. */ - - /* Internal SPI flash on NPCX7 */ - #define CONFIG_FLASH_SIZE (512 * 1024) - #define CONFIG_SPI_FLASH_REGS - #define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ -#elif defined(VARIANT_DEDEDE_EC_IT8320) - #define I2C_PORT_EEPROM IT83XX_I2C_CH_A - #define I2C_PORT_BATTERY IT83XX_I2C_CH_B - #define I2C_PORT_SENSOR IT83XX_I2C_CH_C - #define I2C_PORT_SUB_USB_C1 IT83XX_I2C_CH_E - #define I2C_PORT_USB_C0 IT83XX_I2C_CH_F - - #define I2C_ADDR_EEPROM_FLAGS 0x50 - - #define CONFIG_ADC_VOLTAGE_COMPARATOR /* ITE ADC thresholds */ - - #undef CONFIG_UART_TX_BUF_SIZE /* UART */ - #define CONFIG_UART_TX_BUF_SIZE 4096 +#if defined(VARIANT_DEDEDE_EC_NPCX796FC) || defined(VARIANT_KEEBY_EC_NPCX797FC) +/* NPCX7 config */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX_TACH_SEL2 0 /* No tach. */ + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) +#define CONFIG_SPI_FLASH_REGS +#define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ +#elif defined(VARIANT_DEDEDE_EC_IT8320) || defined(VARIANT_KEEBY_EC_IT8320) +/* IT83XX config */ +#define CONFIG_IT83XX_VCC_1P8V +/* I2C Bus Configuration */ +#define I2C_PORT_EEPROM IT83XX_I2C_CH_A +#define I2C_PORT_BATTERY IT83XX_I2C_CH_B +#define I2C_PORT_SENSOR IT83XX_I2C_CH_C +#define I2C_PORT_SUB_USB_C1 IT83XX_I2C_CH_E +#define I2C_PORT_USB_C0 IT83XX_I2C_CH_F + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define CONFIG_ADC_VOLTAGE_COMPARATOR /* ITE ADC thresholds */ + +#undef CONFIG_UART_TX_BUF_SIZE /* UART */ +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* + * Limit maximal ODR to 125Hz, the EC is using ~5ms per sample at + * 48MHz core cpu clock. + */ +#define CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ 125000 #else -#error "Must define a VARIANT_DEDEDE_EC!" +#error "Must define a VARIANT_[DEDEDE|KEEBY]_EC!" +#endif + +/* + * The key difference between Keeby and Dedede is that Keeby variants don't have + * a connection to H1 and therefore do not use EFS2. + */ +#if defined(VARIANT_KEEBY_EC_NPCX797FC) || defined(VARIANT_KEEBY_EC_IT8320) +#define KEEBY_VARIANT 1 +#else +#define KEEBY_VARIANT 0 #endif /* * Remapping of schematic GPIO names to common GPIO names expected (hardcoded) * in the EC code base. */ -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_EC_INT_L GPIO_EC_AP_MKBP_INT_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_U -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_ECH1_PACKET_MODE -#define GPIO_PCH_DSW_PWROK GPIO_EC_AP_DPWROK -#define GPIO_PCH_PWRBTN_L GPIO_EC_AP_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_AP_RSMRST_L -#define GPIO_PCH_RTCRST GPIO_EC_AP_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_PCH_WAKE_L GPIO_EC_AP_WAKE_ODL -#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_PWRGD_L -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_RSMRST_PWRGD_L -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_USB_C0_DP_HPD GPIO_EC_AP_USB_C0_HPD -#define GPIO_USB_C1_DP_HPD GPIO_EC_AP_USB_C1_HDMI_HPD -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL -#define GPIO_WP GPIO_EC_WP_OD -#define GMR_TABLET_MODE_GPIO_L GPIO_LID_360_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_MKBP_INT_L +#define GPIO_EN_PP5000 GPIO_EN_PP5000_U +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#if !KEEBY_VARIANT +#define GPIO_PACKET_MODE_EN GPIO_ECH1_PACKET_MODE +#endif +#define GPIO_PCH_DSW_PWROK GPIO_EC_AP_DPWROK +#define GPIO_PCH_PWRBTN_L GPIO_EC_AP_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_AP_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_AP_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_PCH_WAKE_L GPIO_EC_AP_WAKE_ODL +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_PWRGD_L +#if KEEBY_VARIANT +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#else +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#endif +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_PWRGD_L +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_USB_C0_DP_HPD GPIO_EC_AP_USB_C0_HPD +#define GPIO_USB_C1_DP_HPD GPIO_EC_AP_USB_C1_HDMI_HPD +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_WP GPIO_EC_WP_OD +#define GPIO_TABLET_MODE_L GPIO_LID_360_L /* Common EC defines */ /* Work around double CR50 reset by waiting in initial power on. */ +#if !KEEBY_VARIANT #define CONFIG_BOARD_RESET_AFTER_POWER_ON +#endif /* Optional console commands */ #define CONFIG_CMD_CHARGER_DUMP @@ -92,20 +123,27 @@ /* Enable i2ctrace command */ #define CONFIG_I2C_DEBUG +/* Assert CCD when a debug device is connected */ +#if !KEEBY_VARIANT +#define CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT +#endif + /* EC Modules */ #define CONFIG_ADC #define CONFIG_CRC8 -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #define CONFIG_HOSTCMD_EVENTS #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_I2C_BUS_MAY_BE_UNPOWERED #define CONFIG_LOW_POWER_IDLE #define CONFIG_POWER_PP5000_CONTROL #define CONFIG_VBOOT_HASH #define CONFIG_VSTORE #define CONFIG_VSTORE_SLOT_COUNT 1 +#if !KEEBY_VARIANT #define CONFIG_VBOOT_EFS2 +#endif /* Battery */ #define CONFIG_BATTERY_CUT_OFF @@ -120,32 +158,42 @@ #define CONFIG_WP_ACTIVE_HIGH /* CBI */ -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_BOARD_VERSION_CBI +#if KEEBY_VARIANT +#define CONFIG_EEPROM_CBI_WP +#endif /* Charger */ #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 256 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 256 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 256 #define CONFIG_USB_CHARGER #define CONFIG_TRICKLE_CHARGING /* Keyboard */ #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PROTOCOL_8042 +#define CONFIG_MKBP_INPUT_DEVICES /* Backlight */ #define CONFIG_BACKLIGHT_LID -#define GPIO_ENABLE_BACKLIGHT GPIO_EN_BL_OD +#define GPIO_ENABLE_BACKLIGHT GPIO_EN_BL_OD /* LED */ #define CONFIG_LED_COMMON +/* Sensors */ +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_EVENT_WAKEUP_MASK 0 +#define CONFIG_MKBP_USE_GPIO_AND_HOST_EVENT + /* SoC */ #define CONFIG_BOARD_HAS_RTC_RESET #define CONFIG_CHIPSET_JASPERLAKE +#define CONFIG_CHIPSET_RESET_HOOK #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 #define CONFIG_POWER_COMMON @@ -161,13 +209,17 @@ #define CONFIG_USBC_VCONN #define CONFIG_USBC_VCONN_SWAP +/* Temp Sensor */ +#define CONFIG_TEMP_SENSOR_POWER +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_PP3300_A +#define CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS 500 + /* USB PD */ #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_DP_HPD_GPIO #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_REV30 #define CONFIG_USB_PD_TCPM_MUX #define CONFIG_USB_PD_TCPM_TCPCI @@ -175,41 +227,43 @@ /* #define CONFIG_USB_PD_VBUS_DETECT_CHARGER */ #define CONFIG_USB_PD_VBUS_MEASURE_CHARGER #define CONFIG_USB_PD_DECODE_SOP +#if KEEBY_VARIANT +#define CONFIG_USB_PID 0x5059 +#else #define CONFIG_USB_PID 0x5042 +#endif #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_TCPMV2 #define CONFIG_USB_DRP_ACC_TRYSRC #define CONFIG_HOSTCMD_PD_CONTROL +#if !KEEBY_VARIANT /* UART COMMAND */ #define CONFIG_CMD_CHARGEN +#endif /* Define typical operating power and max power. */ -#define PD_MAX_VOLTAGE_MV 20000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_POWER_MW 45000 #define PD_OPERATING_POWER_MW 15000 /* TODO(b:147314141): Verify these timings */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ + +/* System safe mode for improved panic debugging */ +#define CONFIG_SYSTEM_SAFE_MODE #ifndef __ASSEMBLER__ +#include "atomic_t.h" #include "common.h" #include "gpio_signal.h" /* Common enums */ #if defined(VARIANT_DEDEDE_EC_NPCX796FC) -#elif defined(VARIANT_DEDEDE_EC_IT8320) - enum board_vcmp { - VCMP_SNS_PP3300_LOW, - VCMP_SNS_PP3300_HIGH, - VCMP_COUNT - }; -#else -#error "Must define a VARIANT_DEDEDE_EC!" +#elif defined(VARIANT_DEDEDE_EC_IT8320) || defined(VARIANT_KEEBY_EC_IT8320) +enum board_vcmp { VCMP_SNS_PP3300_LOW, VCMP_SNS_PP3300_HIGH, VCMP_COUNT }; #endif /* Interrupt handler for signals that are used to generate ALL_SYS_PGOOD. */ @@ -222,7 +276,7 @@ void board_reset_pd_mcu(void); * Bit to indicate if the PP3000_A rail's power is good. Will be updated by ADC * interrupt. */ -extern uint32_t pp3300_a_pgood; +extern atomic_t pp3300_a_pgood; #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/dedede/build.mk b/baseboard/dedede/build.mk index e86d1976ed..af71eb2222 100644 --- a/baseboard/dedede/build.mk +++ b/baseboard/dedede/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2021 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,4 +8,6 @@ baseboard-y=baseboard.o cbi_fw_config.o baseboard-$(VARIANT_DEDEDE_EC_NPCX796FC)+=variant_ec_npcx796fc.o +baseboard-$(VARIANT_KEEBY_EC_NPCX797FC)+=variant_ec_npcx796fc.o baseboard-$(VARIANT_DEDEDE_EC_IT8320)+=variant_ec_it8320.o +baseboard-$(VARIANT_KEEBY_EC_IT8320)+=variant_ec_it8320.o diff --git a/baseboard/dedede/cbi_fw_config.c b/baseboard/dedede/cbi_fw_config.c index 62b582e3b9..612c51700d 100644 --- a/baseboard/dedede/cbi_fw_config.c +++ b/baseboard/dedede/cbi_fw_config.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -33,20 +33,38 @@ enum fw_config_db get_cbi_fw_config_db(void) return ((cached_fw_config & FW_CONFIG_DB_MASK) >> FW_CONFIG_DB_OFFSET); } +enum fw_config_stylus get_cbi_fw_config_stylus(void) +{ + return ((cached_fw_config & FW_CONFIG_STYLUS_MASK) >> + FW_CONFIG_STYLUS_OFFSET); +} + enum fw_config_kblight_type get_cbi_fw_config_kblight(void) { - return ((cached_fw_config & FW_CONFIG_KB_BL_MASK) - >> FW_CONFIG_KB_BL_OFFSET); + return ((cached_fw_config & FW_CONFIG_KB_BL_MASK) >> + FW_CONFIG_KB_BL_OFFSET); } enum fw_config_tablet_mode_type get_cbi_fw_config_tablet_mode(void) { - return ((cached_fw_config & FW_CONFIG_TABLET_MODE_MASK) - >> FW_CONFIG_TABLET_MODE_OFFSET); + return ((cached_fw_config & FW_CONFIG_TABLET_MODE_MASK) >> + FW_CONFIG_TABLET_MODE_OFFSET); } int get_cbi_fw_config_keyboard(void) { - return ((cached_fw_config & FW_CONFIG_KB_LAYOUT_MASK) - >> FW_CONFIG_KB_LAYOUT_OFFSET); + return ((cached_fw_config & FW_CONFIG_KB_LAYOUT_MASK) >> + FW_CONFIG_KB_LAYOUT_OFFSET); +} + +enum fw_config_numeric_pad_type get_cbi_fw_config_numeric_pad(void) +{ + return ((cached_fw_config & FW_CONFIG_KB_NUMPAD_MASK) >> + FW_CONFIG_KB_NUMPAD_OFFSET); +} + +enum fw_config_hdmi_type get_cbi_fw_config_hdmi(void) +{ + return ((cached_fw_config & FW_CONFIG_HDMI_MASK) >> + FW_CONFIG_HDMI_OFFSET); } diff --git a/baseboard/dedede/cbi_fw_config.h b/baseboard/dedede/cbi_fw_config.h index 8c10df03e3..80712f2849 100644 --- a/baseboard/dedede/cbi_fw_config.h +++ b/baseboard/dedede/cbi_fw_config.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,10 +18,24 @@ enum fw_config_db { DB_2C, DB_1C_LTE, DB_1A_HDMI, + DB_1C_1A, + DB_LTE_HDMI, + DB_1C_1A_LTE, DB_1C, + DB_1A_HDMI_LTE, }; -#define FW_CONFIG_DB_OFFSET 0 -#define FW_CONFIG_DB_MASK GENMASK(3, 0) +#define FW_CONFIG_DB_OFFSET 0 +#define FW_CONFIG_DB_MASK GENMASK(3, 0) + +/* + * Stylus (1 bit) + */ +enum fw_config_stylus { + STYLUS_ABSENT = 0, + STYLUS_PRESENT = 1, +}; +#define FW_CONFIG_STYLUS_OFFSET 4 +#define FW_CONFIG_STYLUS_MASK GENMASK(4, 4) /* * Keyboard backlight (1 bit) @@ -30,8 +44,18 @@ enum fw_config_kblight_type { KB_BL_ABSENT = 0, KB_BL_PRESENT = 1, }; -#define FW_CONFIG_KB_BL_OFFSET 8 -#define FW_CONFIG_KB_BL_MASK GENMASK(8, 8) +#define FW_CONFIG_KB_BL_OFFSET 8 +#define FW_CONFIG_KB_BL_MASK GENMASK(8, 8) + +/* + * Keyboard numeric pad (1 bit) + */ +enum fw_config_numeric_pad_type { + NUMERIC_PAD_ABSENT = 0, + NUMERIC_PAD_PRESENT = 1, +}; +#define FW_CONFIG_KB_NUMPAD_OFFSET 9 +#define FW_CONFIG_KB_NUMPAD_MASK GENMASK(9, 9) /* * Tablet Mode (1 bit) @@ -40,15 +64,28 @@ enum fw_config_tablet_mode_type { TABLET_MODE_ABSENT = 0, TABLET_MODE_PRESENT = 1, }; -#define FW_CONFIG_TABLET_MODE_OFFSET 10 -#define FW_CONFIG_TABLET_MODE_MASK GENMASK(10, 10) +#define FW_CONFIG_TABLET_MODE_OFFSET 10 +#define FW_CONFIG_TABLET_MODE_MASK GENMASK(10, 10) + +#define FW_CONFIG_KB_LAYOUT_OFFSET 12 +#define FW_CONFIG_KB_LAYOUT_MASK GENMASK(13, 12) -#define FW_CONFIG_KB_LAYOUT_OFFSET 12 -#define FW_CONFIG_KB_LAYOUT_MASK GENMASK(13, 12) +/* + * Hdmi (1 bit) + */ +enum fw_config_hdmi_type { + HDMI_ABSENT = 0, + HDMI_PRESENT = 1, +}; +#define FW_CONFIG_HDMI_OFFSET 17 +#define FW_CONFIG_HDMI_MASK GENMASK(17, 17) enum fw_config_db get_cbi_fw_config_db(void); +enum fw_config_stylus get_cbi_fw_config_stylus(void); enum fw_config_kblight_type get_cbi_fw_config_kblight(void); enum fw_config_tablet_mode_type get_cbi_fw_config_tablet_mode(void); +enum fw_config_numeric_pad_type get_cbi_fw_config_numeric_pad(void); +enum fw_config_hdmi_type get_cbi_fw_config_hdmi(void); int get_cbi_fw_config_keyboard(void); diff --git a/baseboard/dedede/variant_ec_it8320.c b/baseboard/dedede/variant_ec_it8320.c index d7e2785c4a..f03af6ccd9 100644 --- a/baseboard/dedede/variant_ec_it8320.c +++ b/baseboard/dedede/variant_ec_it8320.c @@ -1,9 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* Common code for VARIANT_DEDEDE_IT8320 configuration */ +/* Common code for VARIANT_[DEDEDE|KEEBY]_IT8320 configuration */ #include "adc_chip.h" #include "atomic.h" @@ -16,11 +16,11 @@ #include "power.h" #include "registers.h" -#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) static void pp3300_a_pgood_low(void) { - deprecated_atomic_clear_bits(&pp3300_a_pgood, 1); + atomic_clear_bits(&pp3300_a_pgood, 1); /* Disable low interrupt while asserted */ vcmp_enable(VCMP_SNS_PP3300_LOW, 0); @@ -37,7 +37,7 @@ static void pp3300_a_pgood_low(void) static void pp3300_a_pgood_high(void) { - deprecated_atomic_or(&pp3300_a_pgood, 1); + atomic_or(&pp3300_a_pgood, 1); /* Disable high interrupt while asserted */ vcmp_enable(VCMP_SNS_PP3300_HIGH, 0); @@ -73,34 +73,42 @@ const struct vcmp_t vcmp_list[] = { BUILD_ASSERT(ARRAY_SIZE(vcmp_list) <= CHIP_VCMP_COUNT); BUILD_ASSERT(ARRAY_SIZE(vcmp_list) == VCMP_COUNT); +#if !defined(BOARD_DIBBI) && !defined(BOARD_TARANZA) && !defined(BOARD_BOXY) /* I2C Ports */ const struct i2c_port_t i2c_ports[] = { - { - "eeprom", I2C_PORT_EEPROM, 400, GPIO_EC_I2C_EEPROM_SCL, - GPIO_EC_I2C_EEPROM_SDA - }, - - { - "battery", I2C_PORT_BATTERY, 100, GPIO_EC_I2C_BATTERY_SCL, - GPIO_EC_I2C_BATTERY_SDA - }, - - { - "sensor", I2C_PORT_SENSOR, 400, GPIO_EC_I2C_SENSOR_SCL, - GPIO_EC_I2C_SENSOR_SDA - }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + + { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BATTERY_SCL, + .sda = GPIO_EC_I2C_BATTERY_SDA }, + +#if defined(HAS_TASK_MOTIONSENSE) || defined(BOARD_SHOTZO) + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +#endif #if CONFIG_USB_PD_PORT_MAX_COUNT > 1 - { - "sub_usbc1", I2C_PORT_SUB_USB_C1, 1000, - GPIO_EC_I2C_SUB_USB_C1_SCL, GPIO_EC_I2C_SUB_USB_C1_SDA - }, + { .name = "sub_usbc1", + .port = I2C_PORT_SUB_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C_SUB_USB_C1_SCL, + .sda = GPIO_EC_I2C_SUB_USB_C1_SDA }, #endif - { - "usbc0", I2C_PORT_USB_C0, 1000, GPIO_EC_I2C_USB_C0_SCL, - GPIO_EC_I2C_USB_C0_SDA - }, + { .name = "usbc0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_SCL, + .sda = GPIO_EC_I2C_USB_C0_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - +#endif diff --git a/baseboard/dedede/variant_ec_npcx796fc.c b/baseboard/dedede/variant_ec_npcx796fc.c index ae7890c473..366fca878e 100644 --- a/baseboard/dedede/variant_ec_npcx796fc.c +++ b/baseboard/dedede/variant_ec_npcx796fc.c @@ -1,11 +1,11 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* Common code for VARIANT_DEDEDE_NPCX796FC configuration */ +/* Common code for VARIANT_[DEDEDE|KEEBY]_NPCX79[6/7]FC configuration */ -#include "adc_chip.h" +#include "adc.h" #include "atomic.h" #include "chipset.h" #include "common.h" @@ -21,12 +21,12 @@ #include "timer.h" /* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) void pp3300_a_pgood_high(void) { - deprecated_atomic_or(&pp3300_a_pgood, 1); + atomic_or(&pp3300_a_pgood, 1); /* Disable this interrupt while it's asserted. */ npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 0); @@ -42,7 +42,7 @@ void pp3300_a_pgood_high(void) void pp3300_a_pgood_low(void) { - deprecated_atomic_clear_bits(&pp3300_a_pgood, 1); + atomic_clear_bits(&pp3300_a_pgood, 1); /* Disable this interrupt while it's asserted. */ npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 0); @@ -79,7 +79,7 @@ static void set_up_adc_irqs(void) npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 1); npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 1); } -DECLARE_HOOK(HOOK_INIT, set_up_adc_irqs, HOOK_PRIO_INIT_ADC+1); +DECLARE_HOOK(HOOK_INIT, set_up_adc_irqs, HOOK_PRIO_INIT_ADC + 1); static void disable_adc_irqs_deferred(void) { @@ -101,10 +101,11 @@ static void disable_adc_irqs_deferred(void) DECLARE_DEFERRED(disable_adc_irqs_deferred); /* - * The ADC interrupts are only needed for booting up. The assumption is that - * the PP3300_A rail will not go down during runtime. Therefore, we'll disable - * the ADC interrupts shortly after booting up and also after shutting down. + * The assumption is that the PP3300_A rail will not go down during runtime. + * Therefore, we'll disable the ADC interrupts shortly after booting up + * and also after shutting down. */ +static void enable_adc_irqs(void); static void disable_adc_irqs(void) { int delay = 200 * MSEC; @@ -114,8 +115,10 @@ static void disable_adc_irqs(void) * to G3. Therefore, we'll postpone disabling the ADC IRQs until after * this occurs. */ - if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) { delay = 15 * SECOND; + enable_adc_irqs(); + } hook_call_deferred(&disable_adc_irqs_deferred_data, delay); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, disable_adc_irqs, HOOK_PRIO_DEFAULT); @@ -138,11 +141,11 @@ DECLARE_HOOK(HOOK_CHIPSET_RESUME, disable_adc_irqs, HOOK_PRIO_DEFAULT); */ static void enable_adc_irqs(void) { - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) { CPRINTS("%s", __func__); hook_call_deferred(&disable_adc_irqs_deferred_data, -1); - npcx_set_adc_repetitive(adc_channels[ADC_VSNS_PP3300_A].input_ch, - 1); + npcx_set_adc_repetitive( + adc_channels[ADC_VSNS_PP3300_A].input_ch, 1); npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 1); npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 1); } @@ -158,31 +161,45 @@ static void enable_adc_irqs_via_lid(void) DECLARE_HOOK(HOOK_LID_CHANGE, enable_adc_irqs_via_lid, HOOK_PRIO_DEFAULT); /* I2C Ports */ -const struct i2c_port_t i2c_ports[] = { - { - "eeprom", I2C_PORT_EEPROM, 1000, GPIO_EC_I2C_EEPROM_SCL, - GPIO_EC_I2C_EEPROM_SDA - }, - - { - "battery", I2C_PORT_BATTERY, 100, GPIO_EC_I2C_BATTERY_SCL, - GPIO_EC_I2C_BATTERY_SDA - }, - - { - "sensor", I2C_PORT_SENSOR, 400, GPIO_EC_I2C_SENSOR_SCL, - GPIO_EC_I2C_SENSOR_SDA - }, - - { - "usbc0", I2C_PORT_USB_C0, 1000, GPIO_EC_I2C_USB_C0_SCL, - GPIO_EC_I2C_USB_C0_SDA - }, - - { - "sub_usbc1", I2C_PORT_SUB_USB_C1, 1000, - GPIO_EC_I2C_SUB_USB_C1_SCL, GPIO_EC_I2C_SUB_USB_C1_SDA - }, +__attribute__((weak)) const struct i2c_port_t i2c_ports[] = { + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 1000, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + + { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BATTERY_SCL, + .sda = GPIO_EC_I2C_BATTERY_SDA }, + +#ifdef HAS_TASK_MOTIONSENSE + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +#endif + + { .name = "usbc0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_SCL, + .sda = GPIO_EC_I2C_USB_C0_SDA }, +#if CONFIG_USB_PD_PORT_MAX_COUNT > 1 + { .name = "sub_usbc1", + .port = I2C_PORT_SUB_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C_SUB_USB_C1_SCL, + .sda = GPIO_EC_I2C_SUB_USB_C1_SDA }, +#endif +#ifdef BOARD_BUGZZY + { .name = "lcd", + .port = I2C_PORT_LCD, + .kbps = 400, + .scl = GPIO_EC_I2C_LCD_SCL, + .sda = GPIO_EC_I2C_LCD_SDA }, +#endif }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - diff --git a/baseboard/dragonegg/baseboard.c b/baseboard/dragonegg/baseboard.c deleted file mode 100644 index 5841bef1b1..0000000000 --- a/baseboard/dragonegg/baseboard.c +++ /dev/null @@ -1,369 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* DragonEgg family-specific configuration */ -#include "charge_manager.h" -#include "charge_state_v2.h" -#include "chipset.h" -#include "console.h" -#include "driver/bc12/max14637.h" -#include "driver/charger/bq25710.h" -#include "driver/ppc/nx20p348x.h" -#include "driver/ppc/sn5s330.h" -#include "driver/ppc/syv682x.h" -#include "driver/tcpm/it83xx_pd.h" -#include "driver/tcpm/tcpci.h" -#include "driver/tcpm/tcpm.h" -#include "driver/tcpm/tusb422.h" -#include "espi.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "icelake.h" -#include "keyboard_scan.h" -#include "power.h" -#include "timer.h" -#include "util.h" -#include "tcpci.h" -#include "usbc_ppc.h" -#include "util.h" - -#define USB_PD_PORT_ITE_0 0 -#define USB_PD_PORT_ITE_1 1 -#define USB_PD_PORT_TUSB422_2 2 - -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) - -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -/******************************************************************************/ -/* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { - /* - * F3 key scan cycle completed but scan input is not - * charging to logic high when EC start scan next - * column for "T" key, so we set .output_settle_us - * to 80us from 50us. - */ - .output_settle_us = 80, - .debounce_down_us = 9 * MSEC, - .debounce_up_us = 30 * MSEC, - .scan_period_us = 3 * MSEC, - .min_post_scan_delay_us = 1000, - .poll_timeout_us = 100 * MSEC, - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ - }, -}; - -/******************************************************************************/ -/* Wake up pins */ -const enum gpio_signal hibernate_wake_pins[] = { - GPIO_LID_OPEN, - GPIO_AC_PRESENT, - GPIO_POWER_BUTTON_L, -}; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); - -/* I2C port map configuration */ -/* TODO(b/111125177): Increase these speeds to 400 kHz and verify operation */ -const struct i2c_port_t i2c_ports[] = { - {"eeprom", IT83XX_I2C_CH_A, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"sensor", IT83XX_I2C_CH_B, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"usbc12", IT83XX_I2C_CH_C, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"usbc0", IT83XX_I2C_CH_E, 100, GPIO_I2C4_SCL, GPIO_I2C4_SDA}, - {"power", IT83XX_I2C_CH_F, 100, GPIO_I2C5_SCL, GPIO_I2C5_SDA} -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/* Charger Chips */ -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, - .drv = &bq25710_drv, - }, -}; - -/******************************************************************************/ -/* PWROK signal configuration */ -/* - * On Dragonegg the ALL_SYS_PWRGD, VCCST_PWRGD, PCH_PWROK, and SYS_PWROK - * signals are handled by the board. No EC control needed. - */ -const struct intel_x86_pwrok_signal pwrok_signal_assert_list[] = {}; -const int pwrok_signal_assert_count = ARRAY_SIZE(pwrok_signal_assert_list); - -const struct intel_x86_pwrok_signal pwrok_signal_deassert_list[] = {}; -const int pwrok_signal_deassert_count = ARRAY_SIZE(pwrok_signal_assert_list); - -/******************************************************************************/ -/* Chipset callbacks/hooks */ - -/* Called on AP S5 -> S3 transition */ -static void baseboard_chipset_startup(void) -{ - /* TODD(b/111121615): Need to fill out this hook */ -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, baseboard_chipset_startup, - HOOK_PRIO_DEFAULT); - -/* Called on AP S0iX -> S0 transition */ -static void baseboard_chipset_resume(void) -{ - /* TODD(b/111121615): Need to fill out this hook */ - /* Enable display backlight. */ - gpio_set_level(GPIO_EDP_BKTLEN_OD, 1); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, baseboard_chipset_resume, HOOK_PRIO_DEFAULT); - -/* Called on AP S0 -> S0iX transition */ -static void baseboard_chipset_suspend(void) -{ - /* TODD(b/111121615): Need to fill out this hook */ - /* Enable display backlight. */ - gpio_set_level(GPIO_EDP_BKTLEN_OD, 0); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, baseboard_chipset_suspend, - HOOK_PRIO_DEFAULT); - -/* Called on AP S3 -> S5 transition */ -static void baseboard_chipset_shutdown(void) -{ - /* TODD(b/111121615): Need to fill out this hook */ -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, baseboard_chipset_shutdown, - HOOK_PRIO_DEFAULT); - -void board_hibernate(void) -{ - int timeout_ms = 20; - /* - * Disable the TCPC power rail and the PP5000 rail before going into - * hibernate. Note, these 2 rails are powered up as the default state in - * gpio.inc. - */ - gpio_set_level(GPIO_EN_PP5000, 0); - /* Wait for PP5000 to drop before disabling PP3300_TCPC */ - while (gpio_get_level(GPIO_PP5000_PG_OD) && timeout_ms > 0) { - msleep(1); - timeout_ms--; - } - if (!timeout_ms) - CPRINTS("PP5000_PG didn't go low after 20 msec"); - gpio_set_level(GPIO_EN_PP3300_TCPC, 0); -} -/******************************************************************************/ -/* USB-C TPCP Configuration */ -const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - [USB_PD_PORT_ITE_0] = { - .bus_type = EC_BUS_TYPE_EMBEDDED, - /* TCPC is embedded within EC so no i2c config needed */ - .drv = &it83xx_tcpm_drv, - /* Alert is active-low, push-pull */ - .flags = 0, - }, - - [USB_PD_PORT_ITE_1] = { - .bus_type = EC_BUS_TYPE_EMBEDDED, - /* TCPC is embedded within EC so no i2c config needed */ - .drv = &it83xx_tcpm_drv, - /* Alert is active-low, push-pull */ - .flags = 0, - }, - - [USB_PD_PORT_TUSB422_2] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USBC1C2, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - /* Alert is active-low, push-pull */ - .flags = 0, - }, -}; - -/******************************************************************************/ -/* USB-C PPC Configuration */ -struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { - [USB_PD_PORT_ITE_0] = { - .i2c_port = I2C_PORT_USBC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, - - [USB_PD_PORT_ITE_1] = { - .i2c_port = I2C_PORT_USBC1C2, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv - }, - - [USB_PD_PORT_TUSB422_2] = { - .i2c_port = I2C_PORT_USBC1C2, - .i2c_addr_flags = NX20P3481_ADDR2_FLAGS, - .drv = &nx20p348x_drv, - }, -}; -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - [USB_PD_PORT_ITE_0] = { - .usb_port = USB_PD_PORT_ITE_0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - - [USB_PD_PORT_ITE_1] = { - .usb_port = USB_PD_PORT_ITE_1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - - [USB_PD_PORT_TUSB422_2] = { - .usb_port = USB_PD_PORT_TUSB422_2, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, -}; - -/******************************************************************************/ -/* BC 1.2 chip Configuration */ -const struct max14637_config_t max14637_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .chip_enable_pin = GPIO_USB_C0_BC12_VBUS_ON_ODL, - .chg_det_pin = GPIO_USB_C0_BC12_CHG_MAX, - .flags = MAX14637_FLAGS_ENABLE_ACTIVE_LOW, - }, - { - .chip_enable_pin = GPIO_USB_C1_BC12_VBUS_ON_ODL, - .chg_det_pin = GPIO_USB_C1_BC12_CHG_MAX, - .flags = MAX14637_FLAGS_ENABLE_ACTIVE_LOW, - }, - { - .chip_enable_pin = GPIO_USB_C2_BC12_VBUS_ON_ODL, - .chg_det_pin = GPIO_USB_C2_BC12_CHG_MAX, - .flags = MAX14637_FLAGS_ENABLE_ACTIVE_LOW, - }, -}; - -/* Power Delivery and charging functions */ - -void baseboard_tcpc_init(void) -{ - /* Enable PPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_TCPPC_INT_L); - gpio_enable_interrupt(GPIO_USB_C2_TCPPC_INT_ODL); - - /* Enable TCPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C2_TCPC_INT_ODL); - -} -DECLARE_HOOK(HOOK_INIT, baseboard_tcpc_init, HOOK_PRIO_INIT_I2C + 1); - -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - /* - * Since C0/C1 TCPC are embedded within EC, we don't need the PDCMD - * tasks.The (embedded) TCPC status since chip driver code will - * handles its own interrupts and forward the correct events to - * the PD_C0 task. See it83xx/intc.c - */ - - if (!gpio_get_level(GPIO_USB_C2_TCPC_INT_ODL)) - status = PD_STATUS_TCPC_ALERT_2; - - return status; -} - -/** - * Reset all system PD/TCPC MCUs -- currently only called from - * handle_pending_reboot() in common/power.c just before hard - * resetting the system. This logic is likely not needed as the - * PP3300_A rail should be dropped on EC reset. - */ -void board_reset_pd_mcu(void) -{ - /* - * C0 & C1: The internal TCPC on ITE EC does not have a reset signal, - * but it will get reset when the EC gets reset. - */ -} -void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) -{ - /* - * We ignore the cc_pin because the polarity should already be set - * correctly in the PPC driver via the pd state machine. - */ - if (ppc_set_vconn(port, enabled) != EC_SUCCESS) - cprints(CC_USBPD, "C%d: Failed %sabling vconn", - port, enabled ? "en" : "dis"); -} - -int board_set_active_charge_port(int port) -{ - int is_valid_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); - int i; - - if (!is_valid_port && port != CHARGE_PORT_NONE) - return EC_ERROR_INVAL; - - if (port == CHARGE_PORT_NONE) { - CPRINTSUSB("Disabling all charger ports"); - - /* Disable all ports. */ - for (i = 0; i < ppc_cnt; i++) { - /* - * Do not return early if one fails otherwise we can - * get into a boot loop assertion failure. - */ - if (ppc_vbus_sink_enable(i, 0)) - CPRINTSUSB("Disabling C%d as sink failed.", i); - } - - return EC_SUCCESS; - } - - /* Check if the port is sourcing VBUS. */ - if (ppc_is_sourcing_vbus(port)) { - CPRINTFUSB("Skip enable C%d", port); - return EC_ERROR_INVAL; - } - - CPRINTSUSB("New charge port: C%d", port); - - /* - * Turn off the other ports' sink path FETs, before enabling the - * requested charge port. - */ - for (i = 0; i < ppc_cnt; i++) { - if (i == port) - continue; - - if (ppc_vbus_sink_enable(i, 0)) - CPRINTSUSB("C%d: sink path disable failed.", i); - } - - /* Enable requested charge port. */ - if (ppc_vbus_sink_enable(port, 1)) { - CPRINTSUSB("C%d: sink path enable failed.", port); - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} diff --git a/baseboard/dragonegg/baseboard.h b/baseboard/dragonegg/baseboard.h deleted file mode 100644 index dccabccbde..0000000000 --- a/baseboard/dragonegg/baseboard.h +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* DragonEgg board configuration */ - -#ifndef __CROS_EC_BASEBOARD_H -#define __CROS_EC_BASEBOARD_H - -/* EC console commands */ -#define CONFIG_CMD_BATT_MFG_ACCESS - -#define CONFIG_CHIPSET_ICELAKE -#define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_EXTPOWER_GPIO -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 -#define CONFIG_MKBP_EVENT -#define CONFIG_MKBP_USE_HOST_EVENT -#define CONFIG_POWER_BUTTON -#define CONFIG_POWER_BUTTON_X86 -#define CONFIG_POWER_PP5000_CONTROL -/* TODO(b/111155507): Don't enable SOiX for now */ -/* #define CONFIG_POWER_S0IX */ -/* #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE */ - -/* EC Defines */ -#define CONFIG_ADC -#define CONFIG_PWM -#define CONFIG_VBOOT_HASH -#define CONFIG_VSTORE -#define CONFIG_VSTORE_SLOT_COUNT 1 - -/* CBI */ -/* - * TODO (b/117174246): When EEPROMs are programmed, can use EEPROM for board - * version. But for P0/P1 boards rely on GPIO signals. - */ -/* #define CONFIG_BOARD_VERSION_CBI */ -#define CONFIG_CROS_BOARD_INFO -#define CONFIG_CRC8 - -/* Common Keyboard Defines */ -#define CONFIG_CMD_KEYBOARD -#define CONFIG_KEYBOARD_BOARD_CONFIG -#define CONFIG_KEYBOARD_PROTOCOL_8042 -#define CONFIG_KEYBOARD_COL2_INVERTED -#define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2 - -/* Common charger defines */ -#define CONFIG_CHARGE_MANAGER -#define CONFIG_CHARGE_RAMP_HW -#define CONFIG_CHARGER -#define CONFIG_CHARGER_BQ25710 -#define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 /* Allow low-current USB charging */ -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 -#define CONFIG_CHARGER_NARROW_VDC -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 - -/* Common battery defines */ -#define CONFIG_BATTERY_CUT_OFF -#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" -#define CONFIG_BATTERY_FUEL_GAUGE -#define CONFIG_BATTERY_HW_PRESENT_CUSTOM -#define CONFIG_BATTERY_PRESENT_CUSTOM -#define CONFIG_BATTERY_REVIVE_DISCONNECT -#define CONFIG_BATTERY_SMART - -/* BC 1.2 Detection */ -#define CONFIG_BC12_DETECT_MAX14637 -#define CONFIG_USB_CHARGER - -/* USB Type C and USB PD defines */ -#undef CONFIG_USB_PD_TCPC_LOW_POWER -#undef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -#define CONFIG_USB_PD_VBUS_DETECT_PPC -#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0 & C1 TCPC: ITE EC */ -#define CONFIG_USB_PD_TCPM_TUSB422 /* C1 TCPC: TUSB422 */ -#define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV1 -#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 - -/* - * TODO (b/111281797): DragonEgg has 3 ports. Only adding support for the port - * on the MLB for now. In addition, this config option will likely move to - * board.h as it likely board dependent and not same across all follower boards. - */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 3 -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 -#define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_ALT_MODE -#define CONFIG_USB_PD_ALT_MODE_DFP -#define CONFIG_USB_PD_DISCHARGE_PPC -#define CONFIG_USB_PD_TRY_SRC -#define CONFIG_USB_PD_VBUS_DETECT_PPC -/* - * TODO(b/113541930): ADC measurements are available for port 0 and 1, but not - * port 2. - */ -#define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT -#define CONFIG_USB_PD_TCPM_TCPCI -#define CONFIG_USB_MUX_VIRTUAL -#define CONFIG_USBC_PPC_SN5S330 /* C0 PPC */ -#define CONFIG_USBC_PPC_SYV682X /* C1 PPC */ -#define CONFIG_USBC_PPC_NX20P3481 /* C2 PPC */ -#define CONFIG_USBC_PPC_VCONN -#define CONFIG_USBC_SS_MUX -#define CONFIG_USBC_VCONN -#define CONFIG_USBC_VCONN_SWAP - -#define CONFIG_HOSTCMD_PD_CONTROL -#define CONFIG_CMD_PPC_DUMP - -/* TODO(b/111281797): Use correct PD delay values */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - -/* TODO(b/111281797): Use correct PD power values */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 - -/* I2C Bus Configuration */ -#define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define I2C_PORT_BATTERY IT83XX_I2C_CH_F /* Shared bus */ -#define I2C_PORT_CHARGER IT83XX_I2C_CH_F /* Shared bus */ -#define I2C_PORT_SENSOR IT83XX_I2C_CH_B -#define I2C_PORT_USBC0 IT83XX_I2C_CH_E -#define I2C_PORT_USBC1C2 IT83XX_I2C_CH_C -#define I2C_PORT_EEPROM IT83XX_I2C_CH_A -#define I2C_ADDR_EEPROM_FLAGS 0x50 - -#ifndef __ASSEMBLER__ - -/* Forward declare common (within DragonEgg) board-specific functions */ -void board_reset_pd_mcu(void); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/dragonegg/battery.c b/baseboard/dragonegg/battery.c deleted file mode 100644 index 0c4ec32903..0000000000 --- a/baseboard/dragonegg/battery.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery.h" -#include "battery_fuel_gauge.h" -#include "battery_smart.h" -#include "gpio.h" -#include "system.h" - -static enum battery_present batt_pres_prev = BP_NOT_SURE; - -enum battery_present battery_hw_present(void) -{ - enum battery_present bp; - /* The GPIO is low when the battery is physically present */ - /* - * TODO(b/111704193): The signal GPIO_EC_BATT_PRES_ODL has an issue - * where it's floating (?) at ~2V when it should be low when the battery - * is connected. The signal will read correctly following a cold reset - * and the battery is connected, but following a warm reboot, it reads - * high. In order to allow charging to work, replacing this with the a - * check that the Operation Status register can be read. Once the HW - * issue is resolved then change this back to checking the physical - * presence pin. - * - */ - - if (system_get_board_version() == 0) - /* P0 boards can't use gpio signal */ - bp = (battery_get_disconnect_state() == - BATTERY_DISCONNECT_ERROR) ? BP_NO : BP_YES; - else - /* P1 boards can read presence from gpio signal */ - bp = gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; - - return bp; -} - -static int battery_init(void) -{ - int batt_status; - - return battery_status(&batt_status) ? 0 : - !!(batt_status & STATUS_INITIALIZED); -} - -/* - * Physical detection of battery. - */ -static enum battery_present battery_check_present_status(void) -{ - enum battery_present batt_pres; - - /* Get the physical hardware status */ - batt_pres = battery_hw_present(); - - /* - * If the battery is not physically connected, then no need to perform - * any more checks. - */ - if (batt_pres != BP_YES) - return batt_pres; - - /* - * If the battery is present now and was present last time we checked, - * return early. - */ - if (batt_pres == batt_pres_prev) - return batt_pres; - - /* - * Ensure that battery is: - * 1. Not in cutoff - * 2. Initialized - */ - if (battery_is_cut_off() != BATTERY_CUTOFF_STATE_NORMAL || - battery_init() == 0) { - batt_pres = BP_NO; - } - - return batt_pres; -} - -enum battery_present battery_is_present(void) -{ - batt_pres_prev = battery_check_present_status(); - return batt_pres_prev; -} diff --git a/baseboard/dragonegg/build.mk b/baseboard/dragonegg/build.mk deleted file mode 100644 index 7f3c8a3669..0000000000 --- a/baseboard/dragonegg/build.mk +++ /dev/null @@ -1,11 +0,0 @@ -# -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# DragonEgg baseboard specific files build -# - -baseboard-y=baseboard.o -baseboard-$(CONFIG_BATTERY_SMART)+=battery.o -baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o diff --git a/baseboard/dragonegg/usb_pd_policy.c b/baseboard/dragonegg/usb_pd_policy.c deleted file mode 100644 index cc1cfd5aca..0000000000 --- a/baseboard/dragonegg/usb_pd_policy.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Shared USB-C policy for DragonEgg boards */ - -#include "charge_manager.h" -#include "common.h" -#include "compile_time_macros.h" -#include "console.h" -#include "ec_commands.h" -#include "gpio.h" -#include "system.h" -#include "tcpci.h" -#include "tcpm.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usbc_ppc.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -int pd_check_vconn_swap(int port) -{ - /* Only allow vconn swap if pp5000_A rail is enabled */ - return gpio_get_level(GPIO_EN_PP5000); -} - -__override void pd_execute_data_swap(int port, - enum pd_data_role data_role) -{ - /* On DragonEgg, only the first port can act as OTG */ - if (port == 0) - gpio_set_level(GPIO_CHG_VAP_OTG_EN, (data_role == PD_ROLE_UFP)); -} - -void pd_power_supply_reset(int port) -{ - int prev_en; - - prev_en = ppc_is_sourcing_vbus(port); - - /* Disable VBUS. */ - ppc_vbus_source_enable(port, 0); - - /* Enable discharge if we were previously sourcing 5V */ - if (prev_en) - pd_set_vbus_discharge(port, 1); - -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - - /* Notify host of power info change. */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -int pd_set_power_supply_ready(int port) -{ - int rv; - - /* Disable charging. */ - rv = ppc_vbus_sink_enable(port, 0); - if (rv) - return rv; - - pd_set_vbus_discharge(port, 0); - - /* Provide Vbus. */ - rv = ppc_vbus_source_enable(port, 1); - if (rv) - return rv; - -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - - /* Notify host of power info change. */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; -} - -#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC -int pd_snk_is_vbus_provided(int port) -{ - /* - * TODO(b/112661747): Until per port VBUS detection methods are - * supported, DragonEgg needs to have CONFIG_USB_PD_VBUS_DETECT_PPC - * defined, but the nx20p3481 PPC on port 2 does not support VBUS - * detection. In the meantime, check specifically for port 2, and rely - * on the TUSB422 TCPC for VBUS status. Note that the tcpm method can't - * be called directly here as it's not supported unless - * CONFIG_USB_PD_VBUS_DETECT_TCPC is defined. - */ - int reg; - - if (port == 2) { - if (tcpc_read(port, TCPC_REG_POWER_STATUS, ®)) - return 0; - return reg & TCPC_REG_POWER_STATUS_VBUS_PRES ? 1 : 0; - } - return ppc_is_vbus_present(port); -} -#endif - -int board_vbus_source_enabled(int port) -{ - return ppc_is_sourcing_vbus(port); -} diff --git a/baseboard/goroh/baseboard.c b/baseboard/goroh/baseboard.c new file mode 100644 index 0000000000..554437ab6e --- /dev/null +++ b/baseboard/goroh/baseboard.c @@ -0,0 +1,267 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Goroh baseboard-specific configuration */ + +#include "adc.h" +#include "adc_chip.h" +#include "baseboard_usbc_config.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/als_tcs3400.h" +#include "driver/charger/isl923x.h" +#include "driver/ppc/syv682x.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/temp_sensor/thermistor.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "power.h" +#include "power_button.h" +#include "spi.h" +#include "switch.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "timer.h" +#include "uart.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +/* Wake-up pins for hibernate */ +enum gpio_signal hibernate_wake_pins[] = { + GPIO_ACOK_OD, + GPIO_LID_OPEN, + GPIO_POWER_BUTTON_L, +}; +int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* BC12 skeleton to make build happy. */ +struct bc12_config bc12_ports[CHARGE_PORT_COUNT] = {}; + +const int usb_port_enable[USB_PORT_COUNT] = {}; + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + gpio_set_level(GPIO_EC_BL_EN_OD, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + gpio_set_level(GPIO_EC_BL_EN_OD, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* USB Mux */ + +/* + * I2C channels (A, B, and C) are using the same timing registers (00h~07h) + * at default. + * In order to set frequency independently for each channels, + * We use timing registers 09h~0Bh, and the supported frequency will be: + * 50KHz, 100KHz, 400KHz, or 1MHz. + * I2C channels (D, E and F) can be set different frequency on different ports. + * The I2C(D/E/F) frequency depend on the frequency of SMBus Module and + * the individual prescale register. + * The frequency of SMBus module is 24MHz on default. + * The allowed range of I2C(D/E/F) frequency is as following setting. + * SMBus Module Freq = PLL_CLOCK / ((IT83XX_ECPM_SCDCR2 & 0x0F) + 1) + * (SMBus Module Freq / 510) <= I2C Freq <= (SMBus Module Freq / 8) + * Channel D has multi-function and can be used as UART interface. + * Channel F is reserved for EC debug. + */ + +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "bat_chg", + .port = IT83XX_I2C_CH_A, + .kbps = 100, + .scl = GPIO_I2C_A_SCL, + .sda = GPIO_I2C_A_SDA }, + { .name = "sensor", + .port = IT83XX_I2C_CH_B, + .kbps = 400, + .scl = GPIO_I2C_B_SCL, + .sda = GPIO_I2C_B_SDA }, + { .name = "usb0", + .port = IT83XX_I2C_CH_C, + .kbps = 400, + .scl = GPIO_I2C_C_SCL, + .sda = GPIO_I2C_C_SDA }, + { .name = "usb1", + .port = IT83XX_I2C_CH_E, + .kbps = 400, + .scl = GPIO_I2C_E_SCL, + .sda = GPIO_I2C_E_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc) +{ + return (cmd_desc->port == I2C_PORT_VIRTUAL_BATTERY); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO: check correct operation for GOROH */ +} + +const struct cc_para_t *board_get_cc_tuning_parameter(enum usbpd_port port) +{ + const static struct cc_para_t + cc_parameter[CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT] = { + { + .rising_time = + IT83XX_TX_PRE_DRIVING_TIME_1_UNIT, + .falling_time = + IT83XX_TX_PRE_DRIVING_TIME_2_UNIT, + }, + { + .rising_time = + IT83XX_TX_PRE_DRIVING_TIME_1_UNIT, + .falling_time = + IT83XX_TX_PRE_DRIVING_TIME_2_UNIT, + }, + }; + + return &cc_parameter[port]; +} + +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* + * We ignore the cc_pin and PPC vconn because polarity and PPC vconn + * should already be set correctly in the PPC driver via the pd + * state machine. + */ +} + +int board_set_active_charge_port(int port) +{ + int i; + int is_valid_port = ((port == 0) || (port == 1)); + + if (!is_valid_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTS("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTS("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTS("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTS("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +int ppc_get_alert_status(int port) +{ + if (port == 0) + return gpio_get_level(GPIO_USB_C0_FAULT_ODL) == 0; + if (port == 1) + return gpio_get_level(GPIO_USB_C1_FAULT_ODL) == 0; + + return 0; +} + +/* Lid */ +#ifndef TEST_BUILD +/* This callback disables keyboard when convertibles are fully open */ +void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} +#endif + +/* Called on AP S5 -> S3 transition */ +static void board_chipset_startup(void) +{ + gpio_set_level(GPIO_EN_USB_C1_MUX_PWR, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S5 transition */ +static void board_chipset_shutdown(void) +{ + gpio_set_level(GPIO_EN_USB_C1_MUX_PWR, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); diff --git a/baseboard/goroh/baseboard.h b/baseboard/goroh/baseboard.h new file mode 100644 index 0000000000..594686f0bf --- /dev/null +++ b/baseboard/goroh/baseboard.h @@ -0,0 +1,195 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Goroh board configuration */ + +#ifndef __CROS_EC_BASEBOARD_H +#define __CROS_EC_BASEBOARD_H + +/* IT81202-bx config */ +/* + * NOTE: we need to make correct VCC voltage selection here if EC's VCC isn't + * connect to 1.8v on other versions. + */ +#define CONFIG_IT83XX_VCC_1P8V + +/* + * On power-on, H1 releases the EC from reset but then quickly asserts and + * releases the reset a second time. This means the EC sees 2 resets: + * (1) power-on reset, (2) reset-pin reset. This config will + * allow the second reset to be treated as a power-on. + */ +#define CONFIG_BOARD_RESET_AFTER_POWER_ON +#define CONFIG_CHIPSET_FALCONLITE +#define CONFIG_EXTPOWER_GPIO +#define CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC + +/* EC defines */ +#define CONFIG_CBI_EEPROM + +/* Chipset */ +#define CONFIG_CMD_AP_RESET_LOG +#define CONFIG_HOSTCMD_AP_RESET +#define CONFIG_HOST_COMMAND_STATUS +#define CONFIG_LOW_POWER_IDLE +#define CONFIG_LOW_POWER_S0 +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_COMMON +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define CONFIG_PWM +#define CONFIG_VBOOT_HASH +#define CONFIG_VOLUME_BUTTONS +#define CONFIG_WP_ACTIVE_HIGH + +/* Battery */ +#define CONFIG_BATTERY_CRITICAL_SHUTDOWN_CUT_OFF +#define CONFIG_BATTERY_CUT_OFF +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_BATTERY_SMART + +/* Charger */ +#define ADC_AMON_BMON ADC_CHARGER_AMON_R /* ADC name remap */ +#define ADC_PSYS ADC_CHARGER_PMON /* ADC name remap */ +#define CONFIG_CHARGE_MANAGER +#define CONFIG_CHARGER +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_DISCHARGE_ON_AC +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_ISL9238C +#define CONFIG_CHARGER_MAINTAIN_VBAT +#define CONFIG_CHARGER_OTG +#define CONFIG_CHARGER_PSYS +#define CONFIG_CHARGER_SENSE_RESISTOR 10 /* BOARD_RS2 */ +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 /* BOARD_RS1 */ + +/* Keyboard */ +#define CONFIG_CMD_KEYBOARD +#define CONFIG_KEYBOARD_COL2_INVERTED +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_USE_GPIO +#define CONFIG_KEYBOARD_BACKLIGHT +#define CONFIG_PWM_KBLIGHT +#define CONFIG_KBLIGHT_ENABLE_PIN +#define GPIO_EN_KEYBOARD_BACKLIGHT GPIO_EN_PPVAR_KB_BL_X + +/* I2C */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER +#define CONFIG_I2C_PASSTHRU_RESTRICTED +#define CONFIG_I2C_VIRTUAL_BATTERY +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_PORT_EEPROM IT83XX_I2C_CH_A +#define I2C_PORT_CHARGER IT83XX_I2C_CH_A +#define I2C_PORT_BATTERY IT83XX_I2C_CH_A +#define I2C_PORT_ACCEL IT83XX_I2C_CH_B +#define I2C_PORT_USB_C0 IT83XX_I2C_CH_C +#define I2C_PORT_USB_C1 IT83XX_I2C_CH_E +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define CONFIG_SMBUS_PEC + +/* LED */ +#define CONFIG_LED_COMMON + +/* PD / USB-C / PPC */ +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_HOSTCMD_PD_CONTROL +#define CONFIG_IT83XX_TUNE_CC_PHY +#define CONFIG_USB_MUX_VIRTUAL +#define CONFIG_USBC_PPC +#define CONFIG_USBC_PPC_DEDICATED_INT +#define CONFIG_USBC_PPC_POLARITY +#define CONFIG_USBC_PPC_SYV682C +#define CONFIG_USBC_PPC_VCONN +#define CONFIG_USBC_SS_MUX +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USBC_RETIMER_PS8818 /* C1 */ +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_USB_PD_DISCHARGE +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_DP_HPD_GPIO +#define CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_FRS_PPC +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 +#define CONFIG_USB_PD_LOGGING +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_REV30 +#define CONFIG_USB_PD_VBUS_MEASURE_CHARGER +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_PD_TRY_SRC +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USB_PID 0x5566 /* TODO: update PID */ +#define CONFIG_USB_POWER_DELIVERY + +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ + +/* USB-A */ +#define CONFIG_USB_PORT_POWER_DUMB +#define USB_PORT_COUNT USBA_PORT_COUNT + +/* UART */ +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Sensor */ +#ifdef HAS_TASK_MOTIONSENSE +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_CMD_ACCELS + +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) +#endif +#define CONFIG_LID_SWITCH + +/* Fan */ +#define CONFIG_FANS 1 + +/* SPI / Host Command */ +#define CONFIG_SPI + +/* MKBP */ +#define CONFIG_MKBP_EVENT + +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_USE_GPIO + +/* Define the host events which are allowed to wakeup AP in S3. */ +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* GPIO name remapping */ +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "power/falconlite.h" +#include "registers.h" + +int board_get_version(void); +void board_reset_pd_mcu(void); +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/goroh/baseboard_usbc_config.h b/baseboard/goroh/baseboard_usbc_config.h new file mode 100644 index 0000000000..7da00c17d6 --- /dev/null +++ b/baseboard/goroh/baseboard_usbc_config.h @@ -0,0 +1,15 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* goroh family-specific USB-C configuration */ + +#ifndef __CROS_EC_BASEBOARD_USBC_CONFIG_H +#define __CROS_EC_BASEBOARD_USBC_CONFIG_H + +#include "gpio_signal.h" + +/* Common definition for the USB PD interrupt handlers. */ +void ppc_interrupt(enum gpio_signal signal); +#endif /* __CROS_EC_BASEBOARD_USBC_CONFIG_H */ diff --git a/baseboard/goroh/board_id.c b/baseboard/goroh/board_id.c new file mode 100644 index 0000000000..7bc77d5229 --- /dev/null +++ b/baseboard/goroh/board_id.c @@ -0,0 +1,94 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "timer.h" +#include "util.h" + +/** + * Conversion based on following table: + * + * ID | Rp | Rd | Voltage + * | kOhm | kOhm | mV + * ---+------+------+-------- + * 0 | 51.1 | 2.2 | 136.2 + * 1 | 51.1 | 6.81 | 388.1 + * 2 | 51.1 | 11 | 584.5 + * 3 | 57.6 | 18 | 785.7 + * 4 | 51.1 | 22 | 993.2 + * 5 | 51.1 | 30 | 1220.7 + * 6 | 51.1 | 39.2 | 1432.6 + * 7 | 56 | 56 | 1650.0 + * 8 | 47 | 61.9 | 1875.8 + * 9 | 47 | 80.6 | 2084.5 + * 10 | 56 | 124 | 2273.3 + * 11 | 51.1 | 150 | 2461.5 + * 12 | 47 | 200 | 2672.1 + * 13 | 47 | 330 | 2888.6 + * 14 | 47 | 680 | 3086.7 + */ +const static int voltage_map[] = { + 136, 388, 584, 785, 993, 1220, 1432, 1650, + 1875, 2084, 2273, 2461, 2672, 2888, 3086, +}; + +const int threshold_mv = 100; + +/** + * Convert ADC value to board id using the voltage table above. + * + * @param ch ADC channel to read, usually ADC_BOARD_ID_0 or ADC_BOARD_ID_1. + * + * @return a non-negative board id, or negative value if error. + */ +static int adc_value_to_numeric_id(enum adc_channel ch) +{ + int mv; + + gpio_set_level(GPIO_EN_EC_ID_ODL, 0); + /* Wait to allow cap charge */ + msleep(10); + + mv = adc_read_channel(ch); + if (mv == ADC_READ_ERROR) + mv = adc_read_channel(ch); + + gpio_set_level(GPIO_EN_EC_ID_ODL, 1); + + if (mv == ADC_READ_ERROR) + return -EC_ERROR_UNKNOWN; + + for (int i = 0; i < ARRAY_SIZE(voltage_map); i++) { + if (IN_RANGE(mv, voltage_map[i] - threshold_mv, + voltage_map[i] + threshold_mv - 1)) + return i; + } + + return -EC_ERROR_UNKNOWN; +} + +static int version = -1; + +/* b/163963220: Cache ADC value before board_hibernate_late() reads it */ +static void board_version_init(void) +{ + version = adc_value_to_numeric_id(ADC_BOARD_ID); + if (version < 0) { + ccprints("WARN:BOARD_ID_0"); + ccprints("Assuming board id = 0"); + + version = 0; + } +} +DECLARE_HOOK(HOOK_INIT, board_version_init, HOOK_PRIO_INIT_ADC + 1); + +int board_get_version(void) +{ + return version; +} diff --git a/baseboard/goroh/build.mk b/baseboard/goroh/build.mk new file mode 100644 index 0000000000..6a3a386efb --- /dev/null +++ b/baseboard/goroh/build.mk @@ -0,0 +1,12 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Baseboard specific files build +# + +baseboard-y+=baseboard.o +baseboard-y+=board_id.o +baseboard-y+=usbc_config.o +baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o diff --git a/baseboard/goroh/usb_pd_policy.c b/baseboard/goroh/usb_pd_policy.c new file mode 100644 index 0000000000..e92ced5e89 --- /dev/null +++ b/baseboard/goroh/usb_pd_policy.c @@ -0,0 +1,92 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "charge_manager.h" +#include "chipset.h" +#include "gpio.h" +#include "timer.h" +#include "usb_dp_alt_mode.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_ppc.h" + +#if CONFIG_USB_PD_3A_PORTS != 1 +#error Goroh reference must have at least one 3.0 A port +#endif + +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) + +void svdm_set_hpd_gpio(int port, int en) +{ + if (port == 0) { + gpio_set_level(GPIO_USB_C0_HPD_3V3, en); + } else if (port == 1) { + gpio_set_level(GPIO_USB_C1_HPD_3V3, en); + gpio_set_level(GPIO_USB_C1_HPD_IN, en); + } +} + +int svdm_get_hpd_gpio(int port) +{ + if (port == 0) + return gpio_get_level(GPIO_USB_C0_HPD_3V3); + else + return gpio_get_level(GPIO_USB_C1_HPD_3V3); +} + +int pd_snk_is_vbus_provided(int port) +{ + return ppc_is_vbus_present(port); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + prev_en = ppc_is_sourcing_vbus(port); + + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_check_vconn_swap(int port) +{ + /* Allow Vconn swap if AP is on. */ + return chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_ON); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +int board_vbus_source_enabled(int port) +{ + return ppc_is_sourcing_vbus(port); +} diff --git a/baseboard/goroh/usbc_config.c b/baseboard/goroh/usbc_config.c new file mode 100644 index 0000000000..f604a090d1 --- /dev/null +++ b/baseboard/goroh/usbc_config.c @@ -0,0 +1,159 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Goroh family-specific USB-C configuration */ +#include "common.h" +#include "compile_time_macros.h" +#include "config.h" +#include "console.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/ps8818_public.h" +#include "driver/tcpm/it8xxx2_pd_public.h" +#include "driver/tcpm/tcpci.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "usb_pd.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +#ifdef CONFIG_BRINGUP +#define GPIO_SET_LEVEL(pin, lvl) gpio_set_level_verbose(CC_USBPD, pin, lvl) +#else +#define GPIO_SET_LEVEL(pin, lvl) gpio_set_level(pin, lvl) +#endif + +/* PPC */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USB Mux */ +static int goroh_usb_c0_init_mux(const struct usb_mux *me) +{ + return virtual_usb_mux_driver.init(me); +} + +static int goroh_usb_c0_set_mux(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) +{ + /* + * b/188376636: Inverse C0 polarity. + * Goroh rev0 CC1/CC2 SBU1/SBU2 are reversed. + * We report inversed polarity to the SoC and SoC we reverse the SBU + * accordingly. + */ + mux_state = mux_state ^ USB_PD_MUX_POLARITY_INVERTED; + + return virtual_usb_mux_driver.set(me, mux_state, ack_required); +} + +static int goroh_usb_c0_get_mux(const struct usb_mux *me, + mux_state_t *mux_state) +{ + return virtual_usb_mux_driver.get(me, mux_state); +} + +static struct usb_mux_driver goroh_usb_c0_mux_driver = { + .init = goroh_usb_c0_init_mux, + .set = goroh_usb_c0_set_mux, + .get = goroh_usb_c0_get_mux, +}; + +static const struct usb_mux_chain goroh_usb_c1_ps8818_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = PS8818_I2C_ADDR0_FLAGS, + .driver = &ps8818_usb_retimer_driver, + }, + .next = NULL, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &goroh_usb_c0_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &goroh_usb_c1_ps8818_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* TCPC */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + /* TCPC is embedded within EC so no i2c config needed */ + .drv = &it8xxx2_tcpm_drv, + /* Alert is active-low, push-pull */ + .flags = 0, + }, + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + /* TCPC is embedded within EC so no i2c config needed */ + .drv = &it8xxx2_tcpm_drv, + /* Alert is active-low, push-pull */ + .flags = 0, + }, +}; + +void ppc_interrupt(enum gpio_signal signal) +{ + if (signal == GPIO_USB_C0_FAULT_ODL) + /* C0: PPC interrupt */ + syv682x_interrupt(0); + else + /* C1: PPC interrupt */ + syv682x_interrupt(1); +} + +static void board_tcpc_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_FAULT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_FAULT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_reset_pd_mcu(void) +{ + /* + * C0 & C1: TCPC is embedded in the EC and processes interrupts in the + * chip code (it83xx/intc.c) + */ +} + +uint16_t tcpc_get_alert_status(void) +{ + /* + * C0 & C1: TCPC is embedded in the EC and processes interrupts in the + * chip code (it83xx/intc.c) + */ + return 0; +} diff --git a/baseboard/grunt/baseboard.c b/baseboard/grunt/baseboard.c index a6192e8789..10e66c50dc 100644 --- a/baseboard/grunt/baseboard.c +++ b/baseboard/grunt/baseboard.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,11 +6,9 @@ /* Grunt family-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_manager.h" #include "charge_state.h" -#include "charge_state_v2.h" #include "common.h" #include "compile_time_macros.h" #include "console.h" @@ -39,43 +37,38 @@ #include "switch.h" #include "system.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_CHARGER] = { - "CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0 - }, - [ADC_TEMP_SENSOR_SOC] = { - "SOC", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0 - }, - [ADC_VBUS] = { - "VBUS", NPCX_ADC_CH8, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0 - }, - [ADC_SKU_ID1] = { - "SKU1", NPCX_ADC_CH9, ADC_MAX_VOLT, ADC_READ_MAX+1, 0 - }, - [ADC_SKU_ID2] = { - "SKU2", NPCX_ADC_CH4, ADC_MAX_VOLT, ADC_READ_MAX+1, 0 - }, + [ADC_TEMP_SENSOR_CHARGER] = { "CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_SOC] = { "SOC", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH8, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + [ADC_SKU_ID1] = { "SKU1", NPCX_ADC_CH9, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_SKU_ID2] = { "SKU2", NPCX_ADC_CH4, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* Power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_PCH_SLP_S3_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S3_DEASSERTED"}, - {GPIO_PCH_SLP_S5_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S5_DEASSERTED"}, - {GPIO_S0_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "S0_PGOOD"}, - {GPIO_S5_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "S5_PGOOD"}, + { GPIO_PCH_SLP_S3_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S3_DEASSERTED" }, + { GPIO_PCH_SLP_S5_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S5_DEASSERTED" }, + { GPIO_S0_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "S0_PGOOD" }, + { GPIO_S5_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "S5_PGOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); @@ -107,7 +100,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, /* Alert is active-low, push-pull */ @@ -156,7 +149,8 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); @@ -197,7 +191,7 @@ static void anx74xx_cable_det_handler(void) * and if in normal mode, then there is no need to trigger a tcpc reset. */ if (cable_det && !reset_n) - task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); + task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET); } DECLARE_DEFERRED(anx74xx_cable_det_handler); @@ -278,45 +272,48 @@ static uint32_t sku_id; static int ps8751_tune_mux(const struct usb_mux *me) { /* Tune USB mux registers for treeya's port 1 Rx measurement */ - if ((sku_id >= 0xa0) && (sku_id <= 0xaf)) + if (((sku_id >= 0xa0) && (sku_id <= 0xaf)) || sku_id == 0xbe || + sku_id == 0xbf) mux_write(me, PS8XXX_REG_MUX_USB_C2SS_EQ, 0x40); return EC_SUCCESS; } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { #ifdef VARIANT_GRUNT_TCPC_0_ANX3429 [USB_PD_PORT_ANX74XX] = { - .usb_port = USB_PD_PORT_ANX74XX, - .driver = &anx74xx_tcpm_usb_mux_driver, - .hpd_update = &anx74xx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_ANX74XX, + .driver = &anx74xx_tcpm_usb_mux_driver, + .hpd_update = &anx74xx_tcpc_update_hpd_status, + }, }, #elif defined(VARIANT_GRUNT_TCPC_0_ANX3447) [USB_PD_PORT_ANX74XX] = { - .usb_port = USB_PD_PORT_ANX74XX, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_ANX74XX, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, #endif [USB_PD_PORT_PS8751] = { - .usb_port = USB_PD_PORT_PS8751, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .board_init = &ps8751_tune_mux, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_PS8751, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .board_init = &ps8751_tune_mux, + }, } }; struct ppc_config_t ppc_chips[] = { - { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, - { - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, }; unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); @@ -337,8 +334,8 @@ int ppc_get_alert_status(int port) void board_overcurrent_event(int port, int is_overcurrented) { - enum gpio_signal signal = (port == 0) ? GPIO_USB_C0_OC_L - : GPIO_USB_C1_OC_L; + enum gpio_signal signal = (port == 0) ? GPIO_USB_C0_OC_L : + GPIO_USB_C1_OC_L; /* Note that the levels are inverted because the pin is active low. */ int lvl = is_overcurrented ? 0 : 1; @@ -370,7 +367,6 @@ const struct charger_config_t chg_chips[] = { }, }; - const int usb_port_enable[USB_PORT_COUNT] = { GPIO_EN_USB_A0_5V, GPIO_EN_USB_A1_5V, @@ -392,7 +388,6 @@ static void baseboard_chipset_resume(void) { /* Allow display backlight to turn on. See above backlight comment */ gpio_set_level(GPIO_ENABLE_BACKLIGHT_L, 0); - } DECLARE_HOOK(HOOK_CHIPSET_RESUME, baseboard_chipset_resume, HOOK_PRIO_DEFAULT); @@ -468,21 +463,8 @@ int board_set_active_charge_port(int port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* - * Limit the input current to 95% negotiated limit, - * to account for the charger chip margin. - */ - charge_ma = charge_ma * 95 / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} - /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * F3 key scan cycle completed but scan input is not * charging to logic high when EC start scan next @@ -512,19 +494,19 @@ struct keyboard_scan_config keyscan_config = { * Murata page for part NCP15WB473F03RC. Vdd=3.3V, R=30.9Kohm. */ static const struct thermistor_data_pair thermistor_data[] = { - { 2761 / THERMISTOR_SCALING_FACTOR, 0}, - { 2492 / THERMISTOR_SCALING_FACTOR, 10}, - { 2167 / THERMISTOR_SCALING_FACTOR, 20}, - { 1812 / THERMISTOR_SCALING_FACTOR, 30}, - { 1462 / THERMISTOR_SCALING_FACTOR, 40}, - { 1146 / THERMISTOR_SCALING_FACTOR, 50}, - { 878 / THERMISTOR_SCALING_FACTOR, 60}, - { 665 / THERMISTOR_SCALING_FACTOR, 70}, - { 500 / THERMISTOR_SCALING_FACTOR, 80}, - { 434 / THERMISTOR_SCALING_FACTOR, 85}, - { 376 / THERMISTOR_SCALING_FACTOR, 90}, - { 326 / THERMISTOR_SCALING_FACTOR, 95}, - { 283 / THERMISTOR_SCALING_FACTOR, 100} + { 2761 / THERMISTOR_SCALING_FACTOR, 0 }, + { 2492 / THERMISTOR_SCALING_FACTOR, 10 }, + { 2167 / THERMISTOR_SCALING_FACTOR, 20 }, + { 1812 / THERMISTOR_SCALING_FACTOR, 30 }, + { 1462 / THERMISTOR_SCALING_FACTOR, 40 }, + { 1146 / THERMISTOR_SCALING_FACTOR, 50 }, + { 878 / THERMISTOR_SCALING_FACTOR, 60 }, + { 665 / THERMISTOR_SCALING_FACTOR, 70 }, + { 500 / THERMISTOR_SCALING_FACTOR, 80 }, + { 434 / THERMISTOR_SCALING_FACTOR, 85 }, + { 376 / THERMISTOR_SCALING_FACTOR, 90 }, + { 326 / THERMISTOR_SCALING_FACTOR, 95 }, + { 283 / THERMISTOR_SCALING_FACTOR, 100 } }; static const struct thermistor_info thermistor_info = { @@ -536,8 +518,8 @@ static const struct thermistor_info thermistor_info = { static int board_get_temp(int idx, int *temp_k) { /* idx is the sensor index set below in temp_sensors[] */ - int mv = adc_read_channel( - idx ? ADC_TEMP_SENSOR_SOC : ADC_TEMP_SENSOR_CHARGER); + int mv = adc_read_channel(idx ? ADC_TEMP_SENSOR_SOC : + ADC_TEMP_SENSOR_CHARGER); int temp_c; if (mv < 0) @@ -549,9 +531,9 @@ static int board_get_temp(int idx, int *temp_k) } const struct temp_sensor_t temp_sensors[] = { - {"Charger", TEMP_SENSOR_TYPE_BOARD, board_get_temp, 0}, - {"SOC", TEMP_SENSOR_TYPE_BOARD, board_get_temp, 1}, - {"CPU", TEMP_SENSOR_TYPE_CPU, sb_tsi_get_val, 0}, + { "Charger", TEMP_SENSOR_TYPE_BOARD, board_get_temp, 0 }, + { "SOC", TEMP_SENSOR_TYPE_BOARD, board_get_temp, 1 }, + { "CPU", TEMP_SENSOR_TYPE_CPU, sb_tsi_get_val, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -606,7 +588,7 @@ struct motion_sensor_t motion_sensors[] = { .drv_data = &g_bmi160_data, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .default_range = 2, /* g, enough for laptop */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ .rot_standard_ref = NULL, .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, @@ -645,22 +627,20 @@ unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); #endif /* HAS_TASK_MOTIONSENSE */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif static const int sku_thresh_mv[] = { /* Vin = 3.3V, Ideal voltage, R2 values listed below */ /* R1 = 51.1 kOhm */ - 200, /* 124 mV, 2.0 Kohm */ - 366, /* 278 mV, 4.7 Kohm */ - 550, /* 456 mV, 8.2 Kohm */ - 752, /* 644 mV, 12.4 Kohm */ - 927, /* 860 mV, 18.0 Kohm */ + 200, /* 124 mV, 2.0 Kohm */ + 366, /* 278 mV, 4.7 Kohm */ + 550, /* 456 mV, 8.2 Kohm */ + 752, /* 644 mV, 12.4 Kohm */ + 927, /* 860 mV, 18.0 Kohm */ 1073, /* 993 mV, 22.0 Kohm */ 1235, /* 1152 mV, 27.4 Kohm */ 1386, /* 1318 mV, 34.0 Kohm */ @@ -707,10 +687,9 @@ static uint32_t board_get_adc_sku_id(void) static int board_get_gpio_board_version(void) { - return - (!!gpio_get_level(GPIO_BOARD_VERSION1) << 0) | - (!!gpio_get_level(GPIO_BOARD_VERSION2) << 1) | - (!!gpio_get_level(GPIO_BOARD_VERSION3) << 2); + return (!!gpio_get_level(GPIO_BOARD_VERSION1) << 0) | + (!!gpio_get_level(GPIO_BOARD_VERSION2) << 1) | + (!!gpio_get_level(GPIO_BOARD_VERSION3) << 2); } static int board_version; @@ -724,7 +703,7 @@ static void cbi_init(void) * Use board version and SKU ID from CBI EEPROM if the board supports * it and the SKU ID set via resistors + ADC is not valid. */ -#ifdef CONFIG_CROS_BOARD_INFO +#ifdef CONFIG_CBI_EEPROM if (sku_id == 0 || sku_id == 0xff) { uint32_t val; @@ -748,7 +727,7 @@ static void cbi_init(void) */ DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_ADC + 1); -uint32_t system_get_sku_id(void) +__override uint32_t board_get_sku_id(void) { return sku_id; } @@ -766,9 +745,10 @@ int board_is_convertible(void) { /* Grunt: 6 */ /* Kasumi360: 82 */ - /* Treeya360: a8-af */ + /* Treeya360: a8-af, be, bf*/ return (sku_id == 6 || sku_id == 82 || - ((sku_id >= 0xa8) && (sku_id <= 0xaf))); + ((sku_id >= 0xa8) && (sku_id <= 0xaf)) || sku_id == 0xbe || + sku_id == 0xbf); } int board_is_lid_angle_tablet_mode(void) @@ -782,11 +762,11 @@ __override uint32_t board_override_feature_flags0(uint32_t flags0) * Remove keyboard backlight feature for devices that don't support it. * All Treeya and Treeya360 models do not support keyboard backlight. */ - if (sku_id == 16 || sku_id == 17 || - sku_id == 20 || sku_id == 21 || - sku_id == 32 || sku_id == 33 || - sku_id == 40 || sku_id == 41 || - ((sku_id >= 0xa0) && (sku_id <= 0xaf))) + if (sku_id == 16 || sku_id == 17 || sku_id == 20 || sku_id == 21 || + sku_id == 32 || sku_id == 33 || sku_id == 40 || sku_id == 41 || + sku_id == 44 || sku_id == 45 || + ((sku_id >= 0xa0) && (sku_id <= 0xaf)) || sku_id == 0xbe || + sku_id == 0xbf) return (flags0 & ~EC_FEATURE_MASK_0(EC_FEATURE_PWM_KEYB)); else return flags0; @@ -803,4 +783,20 @@ void board_hibernate(void) */ ppc_vbus_source_enable(0, 0); ppc_vbus_sink_enable(0, 1); + /* + * PPC1 therefore now needs to be configured the same way as PPC0, + * to mimic the previous dead-battery behavior and allow wake on AC + * plug. + */ + if (!IS_ENABLED(CONFIG_HIBERNATE_PSL)) { + ppc_vbus_source_enable(1, 0); + ppc_vbus_sink_enable(1, 1); + } + + /* + * If CCD not active, set port 0 SBU_EN=0 to avoid power leakage during + * hibernation (b/175674973). + */ + if (gpio_get_level(GPIO_CCD_MODE_ODL)) + ppc_set_sbu(0, 0); } diff --git a/baseboard/grunt/baseboard.h b/baseboard/grunt/baseboard.h index 589c2454ed..30ffb885a2 100644 --- a/baseboard/grunt/baseboard.h +++ b/baseboard/grunt/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,19 +8,19 @@ #ifndef __CROS_EC_BASEBOARD_H #define __CROS_EC_BASEBOARD_H -#if (defined(VARIANT_GRUNT_TCPC_0_ANX3429) \ - + defined(VARIANT_GRUNT_TCPC_0_ANX3447)) != 1 +#if (defined(VARIANT_GRUNT_TCPC_0_ANX3429) + \ + defined(VARIANT_GRUNT_TCPC_0_ANX3447)) != 1 #error Must choose VARIANT_GRUNT_TCPC_0_ANX3429 or VARIANT_GRUNT_TCPC_0_ANX3447 #endif /* NPCX7 config */ -#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ -#define NPCX_TACH_SEL2 0 /* No tach. */ -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX_TACH_SEL2 0 /* No tach. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ /* Internal SPI flash on NPCX7 */ /* Flash is 1MB but reserve half for future use. */ -#define CONFIG_FLASH_SIZE (512 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ @@ -34,14 +34,13 @@ #define CONFIG_ADC #define CONFIG_BACKLIGHT_LID #define CONFIG_BACKLIGHT_LID_ACTIVE_LOW -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_CMD_AP_RESET_LOG #define CONFIG_HIBERNATE_PSL -#define CONFIG_HOSTCMD_LPC +#define CONFIG_HOST_INTERFACE_LPC #define CONFIG_HOSTCMD_SKUID #define CONFIG_I2C #define CONFIG_I2C_BUS_MAY_BE_UNPOWERED -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_LOW_POWER_IDLE #define CONFIG_LOW_POWER_S0 #define CONFIG_LTO @@ -73,7 +72,10 @@ * * See also b/111214767 */ -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_ISL9238 #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 @@ -86,7 +88,7 @@ * ACOK from ISL9238 sometimes has a negative pulse after connecting * USB-C power. We want to ignore it. b/77455171 */ -#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#undef CONFIG_EXTPOWER_DEBOUNCE_MS #define CONFIG_EXTPOWER_DEBOUNCE_MS 200 #define CONFIG_EXTPOWER_GPIO #define CONFIG_POWER_COMMON @@ -102,7 +104,6 @@ */ #define CONFIG_BOARD_RESET_AFTER_POWER_ON -#define CONFIG_KEYBOARD_BOARD_CONFIG #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PROTOCOL_8042 @@ -140,21 +141,13 @@ #define CONFIG_USB_PORT_POWER_DUMB #define USB_PORT_COUNT 2 -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 - -/* - * Minimum conditions to start AP and perform swsync. Note that when the - * charger is connected via USB-PD analog signaling, the boot will proceed - * regardless. - */ -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 3 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* * Require PD negotiation to be complete when we are in a low-battery condition @@ -167,15 +160,15 @@ #undef CONFIG_PORT80_HISTORY_LEN #define CONFIG_PORT80_HISTORY_LEN 256 -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_POWER -#define I2C_PORT_POWER NPCX_I2C_PORT0_0 -#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 -#define I2C_PORT_THERMAL_AP NPCX_I2C_PORT3_0 -#define I2C_PORT_SENSOR NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_POWER +#define I2C_PORT_POWER NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 +#define I2C_PORT_THERMAL_AP NPCX_I2C_PORT3_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT7_0 /* Accelerometer and Gyroscope are the same device. */ -#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_ACCEL I2C_PORT_SENSOR /* Sensors */ #define CONFIG_MKBP_EVENT @@ -193,13 +186,12 @@ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) #endif /* VARIANT_GRUNT_NO_SENSORS */ -#define USB_PD_PORT_ANX74XX 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX74XX 0 +#define USB_PD_PORT_PS8751 1 #ifndef __ASSEMBLER__ #include "gpio_signal.h" -#include "math_util.h" #include "registers.h" enum adc_channel { @@ -233,23 +225,6 @@ enum sensor_id { SENSOR_COUNT, }; -/* - * Matrix to rotate accelerators into the standard reference frame. The default - * is the identity which is correct for the reference design. Variations of - * Grunt may need to change it for manufacturability. - * For the lid: - * +x to the right - * +y up - * +z out of the page - * - * The principle axes of the body are aligned with the lid when the lid is in - * the 180 degree position (open, flat). - * - * Boards within the Grunt family may need to modify this definition at - * board_init() time. - */ -extern mat33_fp_t grunt_base_standard_ref; - /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK (1 << LID_ACCEL) diff --git a/baseboard/grunt/build.mk b/baseboard/grunt/build.mk index cb9d607c36..c8a02aa85d 100644 --- a/baseboard/grunt/build.mk +++ b/baseboard/grunt/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/baseboard/grunt/usb_pd_policy.c b/baseboard/grunt/usb_pd_policy.c index 4b28081785..9cae485bc9 100644 --- a/baseboard/grunt/usb_pd_policy.c +++ b/baseboard/grunt/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,11 +17,11 @@ #include "usbc_ppc.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP) +#define PDO_FIXED_FLAGS \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_COMM_CAP) int pd_check_vconn_swap(int port) { @@ -96,7 +96,7 @@ mux_state_t svdm_dp_mux_mode(int port) __override int svdm_dp_config(int port, uint32_t *payload) { - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]); mux_state_t mux_mode = svdm_dp_mux_mode(port); @@ -116,13 +116,13 @@ __override int svdm_dp_config(int port, uint32_t *payload) */ if (mux_mode == USB_PD_MUX_DP_ENABLED) usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_CONNECT, - pd_get_polarity(port)); + polarity_rm_dts(pd_get_polarity(port))); - payload[0] = VDO(USB_SID_DISPLAYPORT, 1, - CMD_DP_CONFIG | VDO_OPOS(opos)); - payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ - 1, /* DPv1.3 signaling */ - 2); /* UFP connected */ + payload[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); + payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ + 1, /* DPv1.3 signaling */ + 2); /* UFP connected */ return 2; }; @@ -132,7 +132,7 @@ __override void svdm_dp_post_config(int port) /* Connect the SBU and USB lines to the connector. */ ppc_set_sbu(port, 1); usb_mux_set(port, svdm_dp_mux_mode(port), USB_SWITCH_CONNECT, - pd_get_polarity(port)); + polarity_rm_dts(pd_get_polarity(port))); dp_flags[port] |= DP_FLAGS_DP_ON; if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) @@ -142,7 +142,8 @@ __override void svdm_dp_post_config(int port) /* set the minimum time delay (2ms) for the next HPD IRQ */ svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; - usb_mux_hpd_update(port, 1, 0); + usb_mux_hpd_update(port, + USB_PD_MUX_HPD_LVL | USB_PD_MUX_HPD_IRQ_DEASSERTED); } #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/baseboard/guybrush/base_fw_config.h b/baseboard/guybrush/base_fw_config.h new file mode 100644 index 0000000000..a9504a6b45 --- /dev/null +++ b/baseboard/guybrush/base_fw_config.h @@ -0,0 +1,51 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _GUYBRUSH_BASE_FW_CONFIG__H_ +#define _GUYBRUSH_BASE_FW_CONFIG__H_ + +#define UNINITIALIZED_FW_CONFIG 0xFFFFFFFF + +#include +#include + +/* + * Takes a bit offset and bit width and returns the fw_config field at that + * offset and width. Returns -1 if an error occurs. + */ +int get_fw_config_field(uint8_t offset, uint8_t width); + +/* + * Each Guybrush board variant will define a board specific fw_config schema. + * Below is the schema agnostic interface for fw_config fields. + * Fields that are not applicable outside a specific Guybrush variant do not + * need to be included here. + */ + +enum board_usb_a1_retimer { + USB_A1_RETIMER_UNKNOWN, + USB_A1_RETIMER_PS8811, + USB_A1_RETIMER_ANX7491 +}; + +enum board_usb_c1_mux { + USB_C1_MUX_UNKNOWN, + USB_C1_MUX_PS8818, + USB_C1_MUX_ANX7451 +}; + +enum board_form_factor { + FORM_FACTOR_UNKNOWN, + FORM_FACTOR_CLAMSHELL, + FORM_FACTOR_CONVERTIBLE +}; + +bool board_has_kblight(void); +enum board_usb_a1_retimer board_get_usb_a1_retimer(void); +enum board_usb_c1_mux board_get_usb_c1_mux(void); +enum board_form_factor board_get_form_factor(void); +bool board_is_convertible(void); + +#endif /* _GUYBRUSH_BASE_FW_CONFIG__H_ */ diff --git a/baseboard/guybrush/base_gpio.inc b/baseboard/guybrush/base_gpio.inc new file mode 100644 index 0000000000..82b042f890 --- /dev/null +++ b/baseboard/guybrush/base_gpio.inc @@ -0,0 +1,148 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* GSC Signals */ +GPIO_INT(EC_WP_L, PIN(5, 0), GPIO_INT_BOTH, switch_interrupt) /* Write Protect Enabled */ +GPIO(CCD_MODE_ODL, PIN(C, 6), GPIO_ODR_HIGH) /* Case Closed Debug Mode */ +GPIO(EC_GSC_PACKET_MODE, PIN(B, 1), GPIO_OUT_LOW) /* GSC Packet Mode */ +ALTERNATE( PIN_MASK(6, BIT(4) | BIT(5)), 0, MODULE_UART, 0) /* UART_EC_TX_GSC_DBG_RX_R, UART_GSC_DBG_TX_EC_RX_R */ + +/* Power Signals */ +GPIO_INT(MECH_PWR_BTN_ODL, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) /* Mechanical Power Button */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power Button */ +GPIO_INT(SLP_S3_L, PIN(6, 1), GPIO_INT_BOTH, baseboard_en_pwr_s0) /* Sleep S3 */ +GPIO_INT(SLP_S5_L, PIN(7, 2), GPIO_INT_BOTH, power_signal_interrupt) /* Sleep S5 */ +GPIO_INT(SLP_S3_S0I3_L, PIN(7, 4), GPIO_INT_BOTH, power_signal_interrupt) /* Sleep S0ix */ +GPIO_INT(PG_PWR_S5, PIN(C, 0), GPIO_INT_BOTH, baseboard_en_pwr_s0) /* S5 Power OK */ +GPIO_INT(PG_PCORE_S0_R_OD, PIN(B, 6), GPIO_INT_BOTH, power_signal_interrupt) /* S0 Power OK */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) /* AC Power Present */ +GPIO_INT(EC_PCORE_INT_ODL, PIN(F, 0), GPIO_INT_BOTH | GPIO_PULL_UP, power_signal_interrupt) /* Power Core Interrupt */ +GPIO_INT(PG_GROUPC_S0_OD, PIN(A, 3), GPIO_INT_BOTH, baseboard_en_pwr_pcore_signal) /* Power Group C S0 */ +GPIO_INT(PG_LPDDR4X_S3_OD, PIN(9, 5), GPIO_INT_BOTH, baseboard_en_pwr_pcore_signal) /* Power Group LPDDR4 S3 */ +GPIO(EN_PWR_S5, PIN(B, 7), GPIO_OUT_LOW) /* Enable S5 Power */ +GPIO(EN_PWR_S0_R, PIN(F, 1), GPIO_OUT_LOW) +GPIO(EN_PWR_PCORE_S0_R, PIN(E, 1), GPIO_OUT_LOW) +ALTERNATE(/*MECH_PWR_BTN_ODL*/ PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* PSL - Mechanical Power Button */ +ALTERNATE(/*LID_OPEN*/ PIN_MASK(0, BIT(2)), 0, MODULE_PMU, 0) /* PSL - Lid Open */ +ALTERNATE(/*ACOK_OD*/ PIN_MASK(0, BIT(0)), 0, MODULE_PMU, 0) /* PSL - AC Power Present */ + +/* SOC Signals */ +GPIO(EC_ENTERING_RW, PIN(6, 6), GPIO_OUT_LOW) /* Tell SOC we entered RW */ +GPIO(EC_SYS_RST_L, PIN(7, 6), GPIO_ODR_HIGH) /* Cold Reset SOC */ +GPIO(EC_SOC_RSMRST_L, PIN(C, 5), GPIO_OUT_LOW) /* Resume Reset SOC */ +GPIO(EC_CLR_CMOS, PIN(A, 1), GPIO_OUT_LOW) /* Clear SOC CMOS */ +GPIO(EC_MEM_EVENT, PIN(A, 5), GPIO_OUT_LOW) /* Memory Thermal Event to SOC*/ +GPIO(EC_SOC_PWR_BTN_L, PIN(6, 3), GPIO_OUT_HIGH) /* Power Button to SOC */ +GPIO(EC_SOC_PWR_GOOD, PIN(D, 3), GPIO_OUT_LOW) /* Power Good to SOC */ +GPIO(EC_SOC_WAKE_L, PIN(0, 3), GPIO_OUT_HIGH) /* Wake SOC */ +GPIO(EC_SOC_INT_L, PIN(8, 3), GPIO_OUT_HIGH) /* Matrix Keyboard Protocol Event to SOC */ +GPIO(PROCHOT_ODL, PIN(D, 5), GPIO_ODR_HIGH) /* Force SOC into HTC-active state */ +GPIO(SOC_ALERT_EC_L, PIN(E, 2), GPIO_INPUT) /* Sideband-Temperature Iterrupt */ +GPIO(SOC_THERMTRIP_ODL, PIN(E, 5), GPIO_INPUT) /* Temperature Trip Sensor */ + +/* USB Signals */ +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(C, 7), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(7, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(D, 4), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_PULL_UP, bc12_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(9, 6), GPIO_INT_FALLING | GPIO_PULL_UP, bc12_interrupt) +GPIO(USB_C0_C1_FAULT_ODL, PIN(7, 3), GPIO_ODR_HIGH) /* C0/C1 Fault to SOC */ +GPIO(USB_C0_TCPC_RST_L, PIN(3, 4), GPIO_OUT_HIGH) /* C0 TCPC Reset */ +GPIO(USB_C1_TCPC_RST_L, PIN(3, 7), GPIO_OUT_HIGH) /* C1 TCPC Reset */ +GPIO(USB_C0_HPD, PIN(F, 5), GPIO_OUT_LOW) /* C0 DP Hotplug Detect */ +GPIO(USB_C1_HPD, PIN(F, 4), GPIO_OUT_LOW) /* C1 DP Hotplug Detect */ + +/* Sensor Signals */ +GPIO(3AXIS_INT_L, PIN(A, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* 3 Axis Accel */ +GPIO_INT(LID_OPEN, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) /* Lid Open */ +GPIO_INT(VOLDN_BTN_ODL, PIN(A, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down */ +GPIO_INT(VOLUP_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up */ +GPIO(EC_BATT_PRES_ODL, PIN(9, 4), GPIO_INPUT) /* Battery Present */ +ALTERNATE(/*TEMP_SOC|CHRG|MEM*/ PIN_MASK(4, BIT(3) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* SOC, Charger and Memory Temperature */ +ALTERNATE( PIN_MASK(4, BIT(1) | BIT(2)), 0, MODULE_ADC, 0) /* EC_ADC_CORE_IMON1, EC_ADC_SOC_IMON2 */ + +/* LED Signals */ +GPIO(EC_DISABLE_DISP_BL, PIN(A, 6), GPIO_OUT_HIGH) /* Disable Display Backlight */ + +/* Fan Signals */ +ALTERNATE( PIN_MASK(C, BIT(3)), 0, MODULE_PWM, 0) /* EC_FAN_PWM - Fan PWM */ +ALTERNATE( PIN_MASK(4, BIT(0)), 0, MODULE_PWM, 0) /* EC_FAN_SPEED - Fan Speed */ + +/* I2C Signals -- i2c pins need to be exposed as GPIO for bit banging, even though set to alternate mode below */ +GPIO(EC_I2C_USB_A0_C0_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_C0_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_A1_C1_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_A1_C1_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_BATT_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_BATT_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USBC_MUX_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USBC_MUX_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_POWER_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_I2C_CBI_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_CBI_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(E, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(E, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SOC_SIC, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_SOC_SID, PIN(B, 2), GPIO_INPUT) + +ALTERNATE( PIN_MASK(B, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE( PIN_MASK(9, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ +ALTERNATE( PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE( PIN_MASK(D, BIT(0) | BIT(1)), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE( PIN_MASK(F, BIT(2) | BIT(3)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE( PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE( PIN_MASK(E, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C6 */ +ALTERNATE( PIN_MASK(B, BIT(2) | BIT(3)), 0, MODULE_I2C, 0) /* I2C7 */ + +/* Keyboard Signals */ +GPIO(EN_KB_BL, PIN(9, 7), GPIO_OUT_HIGH) /* Enable Keyboard Backlight */ +ALTERNATE(/*PWM_KB_BL*/ PIN_MASK(C, BIT(2)), 0, MODULE_PWM, 0) /* Keyboard Backlight Level */ +ALTERNATE(/*KSI_00-01*/ PIN_MASK(3, BIT(0) | BIT(1)), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT) +ALTERNATE(/*KSI_02-07*/ PIN_MASK(2, GENMASK(7, 2)), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT) +ALTERNATE(/*KSO_00-01*/ PIN_MASK(2, BIT(0) | BIT(1)), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 inverted */ +ALTERNATE(/*KSO_03-09*/ PIN_MASK(1, GENMASK(6, 0)), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) +ALTERNATE(/*KSO_10-13*/ PIN_MASK(0, GENMASK(7, 4)), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) +ALTERNATE(/*KSO_14*/ PIN_MASK(8, BIT(2)), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) + +#if 0 +/* + * SOC eSPI Bus + * These signals do not need to be explicitly configured. + * Leaving here so all signals are documented. + */ +GPIO(ESPI_SOC_CLK, PIN(5, 5), GPIO_DEFAULT) +GPIO(ESPI_SOC_CS_EC_L, PIN(5, 3), GPIO_DEFAULT) +GPIO(ESPI_SOC_D0_EC, PIN(4, 6), GPIO_DEFAULT) +GPIO(ESPI_SOC_D1_EC, PIN(4, 7), GPIO_DEFAULT) +GPIO(ESPI_SOC_D2_EC, PIN(5, 1), GPIO_DEFAULT) +GPIO(ESPI_SOC_D3_EC, PIN(5, 2), GPIO_DEFAULT) +GPIO(EC_ESPI_RST_L, PIN(5, 4), GPIO_DEFAULT) +GPIO(ESPI_EC_ALERT_SOC_L, PIN(5, 7), GPIO_DEFAULT) +#endif + +/* TCPC C0 */ +IOEX(USB_C0_TCPC_FASTSW_CTL_EN, EXPIN(USBC_PORT_C0, 0, 4), GPIO_OUT_LOW) +IOEX(USB_C0_PPC_EN_L, EXPIN(USBC_PORT_C0, 1, 0), GPIO_OUT_LOW) +IOEX(USB_C0_PPC_ILIM_3A_EN, EXPIN(USBC_PORT_C0, 1, 1), GPIO_OUT_LOW) +IOEX_INT(USB_C0_SBU_FAULT_ODL, EXPIN(USBC_PORT_C0, 1, 2), GPIO_INT_FALLING, sbu_fault_interrupt) +IOEX(EN_PP5000_USB_A0_VBUS, EXPIN(USBC_PORT_C0, 1, 5), GPIO_OUT_LOW) +IOEX(USB_A0_LIMIT_SDP, EXPIN(USBC_PORT_C0, 1, 6), GPIO_OUT_LOW) +IOEX(USB_C0_SBU_FLIP, EXPIN(USBC_PORT_C0, 1, 7), GPIO_OUT_LOW) + +/* TCPC C1 */ +IOEX(USB_A1_RETIMER_EN, EXPIN(USBC_PORT_C1, 0, 0), GPIO_OUT_LOW) +IOEX(USB_A1_RETIMER_RST, EXPIN(USBC_PORT_C1, 0, 1), GPIO_OUT_LOW) +IOEX(USB_C1_IN_HPD, EXPIN(USBC_PORT_C1, 0, 3), GPIO_OUT_LOW) +IOEX(USB_C1_TCPC_FASTSW_CTL_EN, EXPIN(USBC_PORT_C1, 0, 4), GPIO_OUT_LOW) +IOEX(USB_C1_PPC_EN_L, EXPIN(USBC_PORT_C1, 1, 0), GPIO_OUT_LOW) +IOEX(USB_C1_PPC_ILIM_3A_EN, EXPIN(USBC_PORT_C1, 1, 1), GPIO_OUT_LOW) +IOEX_INT(USB_C1_SBU_FAULT_ODL, EXPIN(USBC_PORT_C1, 1, 2), GPIO_INT_FALLING, sbu_fault_interrupt) +IOEX(EN_PP5000_USB_A1_VBUS_DB, EXPIN(USBC_PORT_C1, 1, 5), GPIO_OUT_LOW) +IOEX(USB_A1_LIMIT_SDP_DB, EXPIN(USBC_PORT_C1, 1, 6), GPIO_OUT_LOW) diff --git a/baseboard/guybrush/baseboard.c b/baseboard/guybrush/baseboard.c new file mode 100644 index 0000000000..b65aa5ba8b --- /dev/null +++ b/baseboard/guybrush/baseboard.c @@ -0,0 +1,1031 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush family-specific configuration */ + +#include "base_fw_config.h" +#include "battery_fuel_gauge.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "chip/npcx/ps2_chip.h" +#include "chip/npcx/pwm_chip.h" +#include "chipset.h" +#include "cros_board_info.h" +#include "driver/ppc/aoz1380_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/retimer/anx7491.h" +#include "driver/retimer/ps8811.h" +#include "driver/retimer/ps8818_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/usb_mux/amd_fp6.h" +#include "driver/usb_mux/anx7451.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "ioexpander.h" +#include "isl9241.h" +#include "keyboard_scan.h" +#include "nct38xx.h" +#include "pi3usb9201.h" +#include "power.h" +#include "pwm.h" +#include "usb_mux.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define CPRINTSCHIP(format, args...) cprints(CC_CHIPSET, format##args) + +static void reset_nct38xx_port(int port); + +/* Wake Sources */ +const enum gpio_signal hibernate_wake_pins[] = { + GPIO_LID_OPEN, + GPIO_AC_PRESENT, + GPIO_POWER_BUTTON_L, +}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/* Power Signal Input List */ +const struct power_signal_info power_signal_list[] = { + [X86_SLP_S0_N] = { + .gpio = GPIO_PCH_SLP_S0_L, + .flags = POWER_SIGNAL_ACTIVE_HIGH, + .name = "SLP_S0_DEASSERTED", + }, + [X86_SLP_S3_N] = { + .gpio = GPIO_PCH_SLP_S3_L, + .flags = POWER_SIGNAL_ACTIVE_HIGH, + .name = "SLP_S3_DEASSERTED", + }, + [X86_SLP_S5_N] = { + .gpio = GPIO_PCH_SLP_S5_L, + .flags = POWER_SIGNAL_ACTIVE_HIGH, + .name = "SLP_S5_DEASSERTED", + }, + [X86_S0_PGOOD] = { + .gpio = GPIO_S0_PGOOD, + .flags = POWER_SIGNAL_ACTIVE_HIGH, + .name = "S0_PGOOD", + }, + [X86_S5_PGOOD] = { + .gpio = GPIO_S5_PGOOD, + .flags = POWER_SIGNAL_ACTIVE_HIGH, + .name = "S5_PGOOD", + }, +}; +BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); + +const struct i2c_port_t i2c_ports[] = { + { + .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_A0_C0_SCL, + .sda = GPIO_EC_I2C_USB_A0_C0_SDA, + }, + { + .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_A1_C1_SCL, + .sda = GPIO_EC_I2C_USB_A1_C1_SDA, + }, + { + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BATT_SCL, + .sda = GPIO_EC_I2C_BATT_SDA, + }, + { + .name = "usb_mux", + .port = I2C_PORT_USB_MUX, + .kbps = 400, + .scl = GPIO_EC_I2C_USBC_MUX_SCL, + .sda = GPIO_EC_I2C_USBC_MUX_SDA, + }, + { + .name = "charger", + .port = I2C_PORT_CHARGER, + .kbps = 400, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA, + }, + { + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_CBI_SCL, + .sda = GPIO_EC_I2C_CBI_SDA, + }, + { + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + .name = "soc_thermal", + .port = I2C_PORT_THERMAL_AP, + .kbps = 400, + .scl = GPIO_EC_I2C_SOC_SIC, + .sda = GPIO_EC_I2C_SOC_SID, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; + +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +const int usb_port_enable[USBA_PORT_COUNT] = { + IOEX_EN_PP5000_USB_A0_VBUS, + IOEX_EN_PP5000_USB_A1_VBUS_DB, +}; + +static void baseboard_interrupt_init(void) +{ + /* Enable Power Group interrupts. */ + gpio_enable_interrupt(GPIO_PG_GROUPC_S0_OD); + gpio_enable_interrupt(GPIO_PG_LPDDR4X_S3_OD); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC 1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); + + /* Enable SBU fault interrupts */ + ioex_enable_interrupt(IOEX_USB_C0_SBU_FAULT_ODL); + ioex_enable_interrupt(IOEX_USB_C1_SBU_FAULT_ODL); +} +DECLARE_HOOK(HOOK_INIT, baseboard_interrupt_init, HOOK_PRIO_INIT_I2C + 1); + +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + /* Device does not talk I2C */ + .drv = &aoz1380_drv + }, + + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = NX20P3483_ADDR1_FLAGS, + .drv = &nx20p348x_drv + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +static int fsusb42umx_set_mux(const struct usb_mux *, mux_state_t); + +__overridable int board_c1_ps8818_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + CPRINTSUSB("C1: PS8818 mux using default tuning"); + return 0; +} + +const struct usb_mux usbc1_ps8818 = { + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_TCPC1, + .flags = USB_MUX_FLAG_RESETS_IN_G3, + .i2c_addr_flags = PS8818_I2C_ADDR0_FLAGS, + .driver = &ps8818_usb_retimer_driver, + .board_set = &board_c1_ps8818_mux_set, +}; + +__overridable int board_c1_anx7451_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + CPRINTSUSB("C1: ANX7451 mux using default tuning"); + return 0; +} + +const struct usb_mux usbc1_anx7451 = { + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_TCPC1, + .flags = USB_MUX_FLAG_RESETS_IN_G3, + .i2c_addr_flags = ANX7491_I2C_ADDR3_FLAGS, + .driver = &anx7451_usb_mux_driver, + .board_set = &board_c1_anx7451_mux_set, +}; + +/* Filled in by setup_mux based on fw_config */ +struct usb_mux_chain usbc1_mux1; + +struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = AMD_FP6_C0_MUX_I2C_ADDR, + .driver = &amd_fp6_usb_mux_driver, + .board_set = &fsusb42umx_set_mux, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = AMD_FP6_C4_MUX_I2C_ADDR, + .driver = &amd_fp6_usb_mux_driver, + }, + .next = &usbc1_mux1, + } +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +struct ioexpander_config_t ioex_config[] = { + [USBC_PORT_C0] = { + .i2c_host_port = I2C_PORT_TCPC0, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + }, + [USBC_PORT_C1] = { + .i2c_host_port = I2C_PORT_TCPC1, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_IO_EXPANDER_PORT_COUNT == USBC_PORT_COUNT); + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* + * F3 key scan cycle completed but scan input is not + * charging to logic high when EC start scan next + * column for "T" key, so we set .output_settle_us + * to 80us + */ + .output_settle_us = 80, + .debounce_down_us = 6 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 1500, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = SECOND, + .actual_key_mask = { + 0x3c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { + .channel = 0, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000, + }, + [PWM_CH_KBLIGHT] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP, + .freq = 100, + }, + [PWM_CH_LED_CHRG] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP, + .freq = 100, + }, + [PWM_CH_LED_FULL] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP, + .freq = 100, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +/* + * USB C0 port SBU mux use standalone FSUSB42UMX + * chip and it needs a board specific driver. + * It is called through the C0 mux's board_set. + */ +static int fsusb42umx_set_mux(const struct usb_mux *me, mux_state_t mux_state) +{ + if (mux_state & USB_PD_MUX_POLARITY_INVERTED) + ioex_set_level(IOEX_USB_C0_SBU_FLIP, 1); + else + ioex_set_level(IOEX_USB_C0_SBU_FLIP, 0); + + return EC_SUCCESS; +} + +static void setup_mux(void) +{ + switch (board_get_usb_c1_mux()) { + case USB_C1_MUX_PS8818: + CPRINTSUSB("C1: Setting PS8818 mux"); + usbc1_mux1.mux = &usbc1_ps8818; + break; + case USB_C1_MUX_ANX7451: + CPRINTSUSB("C1: Setting ANX7451 mux"); + usbc1_mux1.mux = &usbc1_anx7451; + break; + default: + CPRINTSUSB("C1: Mux is unknown"); + usb_muxes[USBC_PORT_C1].next = NULL; + } +} +DECLARE_HOOK(HOOK_INIT, setup_mux, HOOK_PRIO_INIT_I2C); + +int board_set_active_charge_port(int port) +{ + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + int rv; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * If this port had booted in dead battery mode, go + * ahead and reset it so EN_SNK responds properly. + */ + if (nct38xx_get_boot_type(i) == + NCT38XX_BOOT_DEAD_BATTERY) { + reset_nct38xx_port(i); + pd_set_error_recovery(i); + } + + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* + * Check if we can reset any ports in dead battery mode + * + * The NCT3807 may continue to keep EN_SNK low on the dead battery port + * and allow a dangerous level of voltage to pass through to the initial + * charge port (see b/183660105). We must reset the ports if we have + * sufficient battery to do so, which will bring EN_SNK back under + * normal control. + */ + rv = EC_SUCCESS; + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (nct38xx_get_boot_type(i) == NCT38XX_BOOT_DEAD_BATTERY) { + CPRINTSUSB("Found dead battery on %d", i); + /* + * If we have battery, get this port reset ASAP. + * This means temporarily rejecting charge manager + * sets to it. + */ + if (pd_is_battery_capable()) { + reset_nct38xx_port(i); + pd_set_error_recovery(i); + + if (port == i) + rv = EC_ERROR_INVAL; + } else if (port != i) { + /* + * If other port is selected and in dead battery + * mode, reset this port. Otherwise, reject + * change because we'll brown out. + */ + if (nct38xx_get_boot_type(port) == + NCT38XX_BOOT_DEAD_BATTERY) { + reset_nct38xx_port(i); + pd_set_error_recovery(i); + } else { + rv = EC_ERROR_INVAL; + } + } + } + } + + if (rv != EC_SUCCESS) + return rv; + + /* Check if the port is sourcing VBUS. */ + if (tcpm_get_src_ctrl(port)) { + CPRINTSUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +int board_is_i2c_port_powered(int port) +{ + switch (port) { + case I2C_PORT_USB_MUX: + case I2C_PORT_SENSOR: + /* USB mux and sensor i2c bus is unpowered in Z1 */ + return chipset_in_state(CHIPSET_STATE_HARD_OFF) ? 0 : 1; + case I2C_PORT_THERMAL_AP: + /* SOC thermal i2c bus is unpowered in S0i3/S3/S5/Z1 */ + return chipset_in_state(CHIPSET_STATE_ANY_OFF | + CHIPSET_STATE_ANY_SUSPEND) ? + 0 : + 1; + default: + return 1; + } +} + +/* + * In the AOZ1380 PPC, there are no programmable features. We use + * the attached NCT3807 to control a GPIO to indicate 1A5 or 3A0 + * current limits. + */ +int board_aoz1380_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) +{ + int rv; + + /* Use the TCPC to set the current limit */ + rv = ioex_set_level(IOEX_USB_C0_PPC_ILIM_3A_EN, + (rp == TYPEC_RP_3A0) ? 1 : 0); + + return rv; +} + +void sbu_fault_interrupt(enum ioex_signal signal) +{ + int port = (signal == IOEX_USB_C0_SBU_FAULT_ODL) ? 0 : 1; + + CPRINTSUSB("C%d: SBU fault", port); + pd_handle_overcurrent(port); +} + +static void set_ac_prochot(void) +{ + isl9241_set_ac_prochot(CHARGER_SOLO, GUYBRUSH_AC_PROCHOT_CURRENT_MA); +} +DECLARE_HOOK(HOOK_INIT, set_ac_prochot, HOOK_PRIO_DEFAULT); + +void tcpc_alert_event(enum gpio_signal signal) +{ + int port; + + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_TCPC_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +static void reset_nct38xx_port(int port) +{ + int rv; + int saved_state[IOEX_COUNT] = { 0 }; + enum gpio_signal reset_gpio_l = (port == USBC_PORT_C0) ? + GPIO_USB_C0_TCPC_RST_L : + GPIO_USB_C1_TCPC_RST_L; + + if (port < 0 || port >= USBC_PORT_COUNT) { + CPRINTSUSB("%s invalid port %d", __func__, port); + return; + } + + /* Save ioexpander GPIO state */ + rv = ioex_save_gpio_state(port, saved_state, ARRAY_SIZE(saved_state)); + if (rv) { + CPRINTSUSB("%s failed to save ioex state rv=%d", __func__, rv); + return; + } + + gpio_set_level(reset_gpio_l, 0); + msleep(NCT38XX_RESET_HOLD_DELAY_MS); + gpio_set_level(reset_gpio_l, 1); + nct38xx_reset_notify(port); + if (NCT3807_RESET_POST_DELAY_MS != 0) + msleep(NCT3807_RESET_POST_DELAY_MS); + + /* Re-init ioex after resetting the TCPC */ + ioex_init(port); + /* Restore ioexpander GPIO state */ + rv = ioex_restore_gpio_state(port, saved_state, + ARRAY_SIZE(saved_state)); + if (rv) { + CPRINTSUSB("%s failed to restore ioex state rv=%d", __func__, + rv); + return; + } +} + +void board_reset_pd_mcu(void) +{ + /* Reset TCPC0 */ + reset_nct38xx_port(USBC_PORT_C0); + + /* Reset TCPC1 */ + reset_nct38xx_port(USBC_PORT_C1); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set and ignore if that TCPC has + * its reset line active. + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) { + if (gpio_get_level(GPIO_USB_C0_TCPC_RST_L) != 0) + status |= PD_STATUS_TCPC_ALERT_0; + } + + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) { + if (gpio_get_level(GPIO_USB_C1_TCPC_RST_L) != 0) + status |= PD_STATUS_TCPC_ALERT_1; + } + + return status; +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + aoz1380_interrupt(USBC_PORT_C0); + break; + + case GPIO_USB_C1_PPC_INT_ODL: + nx20p348x_interrupt(USBC_PORT_C1); + break; + + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + + default: + break; + } +} + +/** + * Return if VBUS is sagging too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage = 0; + int rv; + + rv = charger_get_vbus_voltage(port, &voltage); + + if (rv) { + CPRINTSUSB("%s rv=%d", __func__, rv); + return 0; + } + + /* + * b/168569046: The ISL9241 sometimes incorrectly reports 0 for unknown + * reason, causing ramp to stop at 0.5A. Workaround this by ignoring 0. + * This partly defeats the point of ramping, but will still catch + * VBUS below 4.5V and above 0V. + */ + if (voltage == 0) { + CPRINTSUSB("%s vbus=0", __func__); + return 0; + } + + if (voltage < BC12_MIN_VOLTAGE) + CPRINTSUSB("%s vbus=%d", __func__, voltage); + + return voltage < BC12_MIN_VOLTAGE; +} + +/** + * b/175324615: On G3->S5, wait for RSMRST_L to be deasserted before asserting + * PCH_PWRBTN_L. + */ +void board_pwrbtn_to_pch(int level) +{ + timestamp_t start; + const uint32_t timeout_rsmrst_rise_us = 30 * MSEC; + + /* Add delay for G3 exit if asserting PWRBTN_L and RSMRST_L is low. */ + if (!level && !gpio_get_level(GPIO_PCH_RSMRST_L)) { + start = get_time(); + do { + usleep(200); + if (gpio_get_level(GPIO_PCH_RSMRST_L)) + break; + } while (time_since32(start) < timeout_rsmrst_rise_us); + + if (!gpio_get_level(GPIO_PCH_RSMRST_L)) + ccprints("Error pwrbtn: RSMRST_L still low"); + + msleep(G3_TO_PWRBTN_DELAY_MS); + } + gpio_set_level(GPIO_PCH_PWRBTN_L, level); +} + +void board_hibernate(void) +{ + int port; + enum ec_error_list ret; + + /* + * If we are charging, then drop the Vbus level down to 5V to ensure + * that we don't get locked out of the 6.8V OVLO for our PPCs in + * dead-battery mode. This is needed when the TCPC/PPC rails go away. + * (b/79218851, b/143778351, b/147007265) + */ + port = charge_manager_get_active_charge_port(); + if (port != CHARGE_PORT_NONE) { + pd_request_source_voltage(port, SAFE_RESET_VBUS_MV); + + /* Give PD task and PPC chip time to get to 5V */ + msleep(SAFE_RESET_VBUS_DELAY_MS); + } + + /* Try to put our battery fuel gauge into sleep mode */ + ret = battery_sleep_fuel_gauge(); + if ((ret != EC_SUCCESS) && (ret != EC_ERROR_UNIMPLEMENTED)) + cprints(CC_SYSTEM, "Failed to send battery sleep command"); +} + +__overridable enum ec_error_list +board_a1_ps8811_retimer_init(const struct usb_mux *me) +{ + return EC_SUCCESS; +} + +static int baseboard_a1_ps8811_retimer_init(const struct usb_mux *me) +{ + int rv; + int tries = 2; + + do { + int val; + + rv = ps8811_i2c_read(me, PS8811_REG_PAGE1, + PS8811_REG1_USB_BEQ_LEVEL, &val); + } while (rv && --tries); + + if (rv) { + CPRINTSUSB("A1: PS8811 retimer not detected!"); + return rv; + } + CPRINTSUSB("A1: PS8811 retimer detected"); + rv = board_a1_ps8811_retimer_init(me); + if (rv) + CPRINTSUSB("A1: Error during PS8811 setup rv:%d", rv); + return rv; +} + +/* PS8811 is just a type-A USB retimer, reusing mux structure for convience. */ +const struct usb_mux usba1_ps8811 = { + .usb_port = USBA_PORT_A1, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PS8811_I2C_ADDR_FLAGS3, + .board_init = &baseboard_a1_ps8811_retimer_init, +}; + +__overridable enum ec_error_list +board_a1_anx7491_retimer_init(const struct usb_mux *me) +{ + return EC_SUCCESS; +} + +static int baseboard_a1_anx7491_retimer_init(const struct usb_mux *me) +{ + int rv; + int tries = 2; + + do { + int val; + + rv = i2c_read8(me->i2c_port, me->i2c_addr_flags, 0, &val); + } while (rv && --tries); + if (rv) { + CPRINTSUSB("A1: ANX7491 retimer not detected!"); + return rv; + } + CPRINTSUSB("A1: ANX7491 retimer detected"); + rv = board_a1_anx7491_retimer_init(me); + if (rv) + CPRINTSUSB("A1: Error during ANX7491 setup rv:%d", rv); + return rv; +} + +/* ANX7491 is just a type-A USB retimer, reusing mux structure for convience. */ +const struct usb_mux usba1_anx7491 = { + .usb_port = USBA_PORT_A1, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = ANX7491_I2C_ADDR0_FLAGS, + .board_init = &baseboard_a1_anx7491_retimer_init, +}; + +void baseboard_a1_retimer_setup(void) +{ + struct usb_mux a1_retimer; + switch (board_get_usb_a1_retimer()) { + case USB_A1_RETIMER_ANX7491: + a1_retimer = usba1_anx7491; + break; + case USB_A1_RETIMER_PS8811: + a1_retimer = usba1_ps8811; + break; + default: + CPRINTSUSB("A1: Unknown retimer!"); + return; + } + a1_retimer.board_init(&a1_retimer); +} +DECLARE_DEFERRED(baseboard_a1_retimer_setup); + +static void baseboard_chipset_suspend(void) +{ + ioex_set_level(IOEX_USB_A1_RETIMER_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, baseboard_chipset_suspend, + HOOK_PRIO_DEFAULT); + +static void baseboard_chipset_resume(void) +{ + ioex_set_level(IOEX_USB_A1_RETIMER_EN, 1); + /* Some retimers take several ms to be ready, so defer setup call */ + hook_call_deferred(&baseboard_a1_retimer_setup_data, 20 * MSEC); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, baseboard_chipset_resume, HOOK_PRIO_DEFAULT); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + switch (port) { + case USBC_PORT_C0: + case USBC_PORT_C1: + gpio_set_level(GPIO_USB_C0_C1_FAULT_ODL, !is_overcurrented); + break; + + default: + break; + } +} + +static void baseboard_set_en_pwr_pcore(void) +{ + /* + * EC must AND signals PG_LPDDR4X_S3_OD, PG_GROUPC_S0_OD, and + * EN_PWR_S0_R. + */ + gpio_set_level(GPIO_EN_PWR_PCORE_S0_R, + gpio_get_level(GPIO_PG_LPDDR4X_S3_OD) && + gpio_get_level(GPIO_PG_GROUPC_S0_OD) && + gpio_get_level(GPIO_EN_PWR_S0_R)); +} + +void baseboard_en_pwr_pcore_signal(enum gpio_signal signal) +{ + baseboard_set_en_pwr_pcore(); +} + +static void baseboard_check_groupc_low(void) +{ + /* Warn if we see unexpected sequencing here */ + if (!gpio_get_level(GPIO_EN_PWR_S0_R) && + gpio_get_level(GPIO_PG_GROUPC_S0_OD)) + CPRINTSCHIP("WARN: PG_GROUPC_S0_OD high while EN_PWR_S0_R low"); +} +DECLARE_DEFERRED(baseboard_check_groupc_low); + +void baseboard_en_pwr_s0(enum gpio_signal signal) +{ + /* EC must AND signals SLP_S3_L and PG_PWR_S5 */ + gpio_set_level(GPIO_EN_PWR_S0_R, + gpio_get_level(GPIO_SLP_S3_L) && + gpio_get_level(GPIO_PG_PWR_S5)); + + /* + * If we set EN_PWR_S0_R low, then check PG_GROUPC_S0_OD went low as + * well some reasonable time later + */ + if (!gpio_get_level(GPIO_EN_PWR_S0_R)) + hook_call_deferred(&baseboard_check_groupc_low_data, + 100 * MSEC); + + /* Change EN_PWR_PCORE_S0_R if needed */ + baseboard_set_en_pwr_pcore(); + + /* Now chain off to the normal power signal interrupt handler. */ + power_signal_interrupt(signal); +} + +#if defined(SECTION_IS_RW) && defined(CONFIG_POWER_SLEEP_FAILURE_DETECTION) + +/** + * S0ix Hang Recovery Fallback Routines. + * + * Only runs in RW to de-risk an unrecoverable boot loop in RO. + * power_board_s0ix_hang_detected is triggered by the common host_sleep S0ix + * hang detection. The default behavior is to send a wake event. Additional + * hang recovery fallback remedies are defined here. + * S3 sleep is not supported on guybrush, so not handled here. + */ + +/* This timeout begins after CONFIG_SLEEP_TIMEOUT_MS */ +#define HARD_SLEEP_HANG_TIMEOUT 10000 + +/* These counters are reset whenever there's a successful resume */ +static int soft_sleep_hang_count; +static int hard_sleep_hang_count; + +/* Shutdown or reset on hard hang */ +static int shutdown_on_hard_hang; + +static void board_handle_hard_sleep_hang(void); +DECLARE_DEFERRED(board_handle_hard_sleep_hang); + +static void stop_hard_hang_timer(void); + +__override void power_board_handle_sleep_hang(enum sleep_hang_type hang_type) +{ + soft_sleep_hang_count += 1; + + /* Avoid race condition */ + stop_hard_hang_timer(); + + if (hang_type == SLEEP_HANG_S0IX_SUSPEND) + ccprints("S0ix suspend sleep hang detected!"); + else if (hang_type == SLEEP_HANG_S0IX_RESUME) + ccprints("S0ix resume sleep hang detected!"); + + ccprints("Consecutive sleep hang count: soft=%d hard=%d", + soft_sleep_hang_count, hard_sleep_hang_count); + + if (hard_sleep_hang_count == 0) { + /* Try an AP reset first */ + shutdown_on_hard_hang = false; + ccprints("AP will be force reset in %dms if hang persists", + HARD_SLEEP_HANG_TIMEOUT); + } else { + /* Avoid reboot loop that drains battery and just shutdown */ + shutdown_on_hard_hang = true; + ccprints("Consecutive(%d) hard sleep hangs detected!", + hard_sleep_hang_count); + ccprints("AP will be force shutdown in %dms if hang persists", + HARD_SLEEP_HANG_TIMEOUT); + } + + hook_call_deferred(&board_handle_hard_sleep_hang_data, + HARD_SLEEP_HANG_TIMEOUT * MSEC); +} + +/** + * Reboot or shutdown when hard sleep hang detected. + * This timer is stopped on suspend, resume, reset or shutdown events. + */ +static void board_handle_hard_sleep_hang(void) +{ + hard_sleep_hang_count += 1; + /* Avoid race condition */ + stop_hard_hang_timer(); + + if (shutdown_on_hard_hang) { + ccprints("Very hard S0ix sleep hang detected!!! " + "Shutting down AP now!"); + chipset_force_shutdown(CHIPSET_SHUTDOWN_BOARD_CUSTOM); + } else { + ccprints("Hard S0ix sleep hang detected!! Resetting AP now!"); + /* If AP reset does not break hang, force a shutdown */ + shutdown_on_hard_hang = true; + ccprints("AP will be shutdown in %dms if hang persists", + HARD_SLEEP_HANG_TIMEOUT); + hook_call_deferred(&board_handle_hard_sleep_hang_data, + HARD_SLEEP_HANG_TIMEOUT * MSEC); + chipset_reset(CHIPSET_RESET_HANG_REBOOT); + } +} + +/** + * Reset hang counters whenever a resume is successful + */ +static void reset_hang_counters(void) +{ + if (hard_sleep_hang_count || soft_sleep_hang_count) + ccprints("Successful S0ix resume after consecutive hangs: " + "soft=%d hard=%d", + soft_sleep_hang_count, hard_sleep_hang_count); + hard_sleep_hang_count = 0; + soft_sleep_hang_count = 0; +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, reset_hang_counters, HOOK_PRIO_DEFAULT); + +/** + * Hard hang detection timers are stopped on any suspend, resume, reset or + * shutdown event. + */ +static void stop_hard_hang_timer(void) +{ + hook_call_deferred(&board_handle_hard_sleep_hang_data, -1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, stop_hard_hang_timer, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, stop_hard_hang_timer, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, stop_hard_hang_timer, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, stop_hard_hang_timer, HOOK_PRIO_DEFAULT); + +#endif /* SECTION_IS_RW && CONFIG_POWER_SLEEP_FAILURE_DETECTION */ diff --git a/baseboard/guybrush/baseboard.h b/baseboard/guybrush/baseboard.h new file mode 100644 index 0000000000..5e97bf1585 --- /dev/null +++ b/baseboard/guybrush/baseboard.h @@ -0,0 +1,358 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush baseboard configuration */ + +#ifndef __CROS_EC_BASEBOARD_H +#define __CROS_EC_BASEBOARD_H + +/* NPCX9 config */ +#define CONFIG_PORT80_4_BYTE +#define NPCX9_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ + +/* Optional features */ +#define CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT +#define CONFIG_LTO /* Link-Time Optimizations to reduce code size */ + +/* Detect sleep hang after 10s */ +#undef CONFIG_SLEEP_TIMEOUT_MS +#define CONFIG_SLEEP_TIMEOUT_MS 10000 + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Vboot Config */ +#define CONFIG_CRC8 +#define CONFIG_VBOOT_EFS2 +#define CONFIG_VBOOT_HASH +#define CONFIG_VSTORE +#define CONFIG_VSTORE_SLOT_COUNT 1 +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE + +/* CBI Config */ +#define CONFIG_CBI_EEPROM +#define CONFIG_BOARD_VERSION_CBI + +/* Power Config */ +#define CONFIG_CHIPSET_X86_RSMRST_DELAY +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 200 +#define CONFIG_EXTPOWER_GPIO +#define CONFIG_HIBERNATE_PSL +#define CONFIG_LOW_POWER_IDLE +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_TO_PCH_CUSTOM +#define CONFIG_POWER_BUTTON_X86 +#define CONFIG_POWER_COMMON +#define CONFIG_POWER_S0IX +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define G3_TO_PWRBTN_DELAY_MS 16 +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EN_PWR_A GPIO_EN_PWR_S5 +#define GPIO_PCH_PWRBTN_L GPIO_EC_SOC_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_SOC_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S3_S0I3_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_SOC_PWR_GOOD +#define GPIO_PCH_WAKE_L GPIO_EC_SOC_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_MECH_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_PG_PCORE_S0_R_OD +#define GPIO_S5_PGOOD GPIO_PG_PWR_S5 +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define SAFE_RESET_VBUS_DELAY_MS 900 +#define SAFE_RESET_VBUS_MV 5000 +/* + * On power-on, H1 releases the EC from reset but then quickly asserts and + * releases the reset a second time. This means the EC sees 2 resets: + * (1) power-on reset, (2) reset-pin reset. This config will + * allow the second reset to be treated as a power-on. + */ +#define CONFIG_BOARD_RESET_AFTER_POWER_ON + +/* Thermal Config */ +#define CONFIG_ADC +#define CONFIG_AMD_SB_RMI +#define CONFIG_AMD_STT +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B +#define CONFIG_THROTTLE_AP +#define CONFIG_TEMP_SENSOR_SB_TSI +#define CONFIG_THERMISTOR +#define CONFIG_CPU_PROCHOT_ACTIVE_LOW +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL + +/* Flash Config */ +/* See config_chip-npcx9.h for SPI flash configuration */ +#undef CONFIG_SPI_FLASH /* Don't enable external flash interface */ +#define GPIO_WP_L GPIO_EC_WP_L + +/* Host communication */ +#define CONFIG_CMD_APTHROTTLE +#define CONFIG_CMD_CHARGEN +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_USE_GPIO_AND_HOST_EVENT +#define GPIO_EC_INT_L GPIO_EC_SOC_INT_L + +/* Chipset config */ +#define CONFIG_CHIPSET_CEZANNE +#define CONFIG_CHIPSET_CAN_THROTTLE +#define CONFIG_CHIPSET_RESET_HOOK + +/* Keyboard Config */ +#define CONFIG_MKBP_INPUT_DEVICES +#define CONFIG_KEYBOARD_BACKLIGHT + +#define CONFIG_KEYBOARD_COL2_INVERTED +#define CONFIG_KEYBOARD_PROTOCOL_8042 +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KBLIGHT_ENABLE_PIN +#define GPIO_EN_KEYBOARD_BACKLIGHT GPIO_EN_KB_BL +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV + +/* Sensors */ +#ifdef HAS_TASK_MOTIONSENSE + +#define CONFIG_TABLET_MODE +#define CONFIG_GMR_TABLET_MODE +#define GPIO_TABLET_MODE_L GPIO_TABLET_MODE +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is a power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs. */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK (1 << LID_ACCEL) +#endif /* HAS_TASK_MOTIONSENSE */ + +/* Backlight config */ +#define CONFIG_BACKLIGHT_LID +#define CONFIG_BACKLIGHT_LID_ACTIVE_LOW +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_DISABLE_DISP_BL + +/* Battery Config */ +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_BATTERY_CUT_OFF +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_SMART +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 +#define CONFIG_BC12_DETECT_PI3USB9201 +/* Enable PEC to detect potential corruption on read (b/230520109) */ +#define CONFIG_SMBUS_PEC + +/* Charger Config */ +#define CONFIG_CHARGER +#define CONFIG_CHARGE_MANAGER +#define CONFIG_CHARGER_DISCHARGE_ON_AC +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 + +/* + * EC will boot AP to depthcharge if: (BAT >= 2%) || (AC >= 65W) + * CONFIG_CHARGER_LIMIT_* is not set, so there is no additional restriction on + * Depthcharge to boot OS. + */ +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 65000 + +/* + * We would prefer to use CONFIG_CHARGE_RAMP_HW to enable legacy BC1.2 charging + * but that feature of ISL9241 is broken (b/160287056) so we have to use + * CONFIG_CHARGE_RAMP_SW instead. + */ +#define CONFIG_CHARGE_RAMP_SW + +/* USB Type C and USB PD config */ +#define CONFIG_USB_PD_REV30 +#define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_HOSTCMD_PD_CONTROL +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_USB_CHARGER +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PD_5V_EN_CUSTOM +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_DP_HPD_GPIO +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_FRS_TCPC +#define CONFIG_USB_PD_LOGGING +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_TCPM_MUX +#define CONFIG_USB_PD_TCPM_NCT38XX +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USBC_PPC +#define CONFIG_USBC_PPC_SBU +#define CONFIG_USBC_PPC_AOZ1380 +#define CONFIG_USBC_RETIMER_PI3HDX1204 +#define CONFIG_USBC_SS_MUX +#define CONFIG_USBC_SS_MUX_DFP_ONLY +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USBC_PPC_NX20P3483 +#define CONFIG_USBC_RETIMER_PS8811 +#define CONFIG_USBC_RETIMER_PS8818 +#define CONFIG_USB_MUX_RUNTIME_CONFIG +#define CONFIG_USB_MUX_AMD_FP6 + +#define GPIO_USB_C0_DP_HPD GPIO_USB_C0_HPD +#define GPIO_USB_C1_DP_HPD GPIO_USB_C1_HPD + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT USBC_PORT_COUNT + +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ + +/* USB-A config */ +#define USB_PORT_COUNT USBA_PORT_COUNT +#define CONFIG_USB_PORT_POWER_SMART +#define CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY +#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_CDP +#define CONFIG_USB_PORT_POWER_SMART_INVERTED + +#define GPIO_USB1_ILIM_SEL IOEX_USB_A0_LIMIT_SDP +#define GPIO_USB2_ILIM_SEL IOEX_USB_A1_LIMIT_SDP_DB + +/* Round up 5000 max current to multiple of 128mA for ISL9241 AC prochot. */ +#define GUYBRUSH_AC_PROCHOT_CURRENT_MA 5120 + +/* + * USB ID - This is allocated specifically for Guybrush + */ +#define CONFIG_USB_PID 0x504D + +/* BC 1.2 */ +/* + * For legacy BC1.2 charging with CONFIG_CHARGE_RAMP_SW, ramp up input current + * until voltage drops to 4.5V. Don't go lower than this to be kind to the + * charger (see b/67964166). + */ +#define BC12_MIN_VOLTAGE 4500 + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define CONFIG_I2C_BUS_MAY_BE_UNPOWERED +#define CONFIG_I2C_CONTROLLER +#define CONFIG_I2C_UPDATE_IF_CHANGED +#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT1_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT4_1 +#define I2C_PORT_CHARGER I2C_PORT_POWER +#define I2C_PORT_EEPROM NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT6_1 +#define I2C_PORT_THERMAL_AP NPCX_I2C_PORT7_0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* Volume Button Config */ +#define CONFIG_VOLUME_BUTTONS +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL + +/* Fan Config */ +#define CONFIG_FANS FAN_CH_COUNT + +/* LED Config */ +#define CONFIG_PWM +#define CONFIG_PWM_KBLIGHT + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +/* Power input signals */ +enum power_signal { + X86_SLP_S0_N, /* SOC -> SLP_S3_S0I3_L */ + X86_SLP_S3_N, /* SOC -> SLP_S3_L */ + X86_SLP_S5_N, /* SOC -> SLP_S5_L */ + + X86_S0_PGOOD, /* PMIC -> S0_PWROK_OD */ + X86_S5_PGOOD, /* PMIC -> S5_PWROK */ + + /* Number of X86 signals */ + POWER_SIGNAL_COUNT, +}; + +/* USB-C ports */ +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +/* USB-A ports */ +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; + +/* TMP112 sensors */ +enum tmp112_sensor { + TMP112_SOC, + TMP112_AMB, + TMP112_COUNT, +}; + +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* PWM Channels */ +enum pwm_channel { + PWM_CH_FAN = 0, + PWM_CH_KBLIGHT, + PWM_CH_LED_CHRG, + PWM_CH_LED_FULL, + PWM_CH_COUNT +}; + +/* Fan Channels */ +enum fan_channel { + FAN_CH_0 = 0, + /* Number of FAN channels */ + FAN_CH_COUNT, +}; +enum mft_channel { + MFT_CH_0 = 0, + /* Number of MFT channels */ + MFT_CH_COUNT, +}; + +/* Common definition for the USB PD interrupt handlers. */ +void tcpc_alert_event(enum gpio_signal signal); +void bc12_interrupt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); +void sbu_fault_interrupt(enum ioex_signal signal); + +void baseboard_en_pwr_pcore_signal(enum gpio_signal signal); +void baseboard_en_pwr_s0(enum gpio_signal signal); + +int board_get_soc_temp_k(int idx, int *temp_k); + +/* CBI utility functions */ +uint32_t get_sku_id(void); +uint32_t get_board_version(void); +uint32_t get_fw_config(void); +/* Board callback after CBI has been initialized */ +__overridable void board_cbi_init(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/guybrush/build.mk b/baseboard/guybrush/build.mk new file mode 100644 index 0000000000..8110e6e6c4 --- /dev/null +++ b/baseboard/guybrush/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Guybrush baseboard specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f + +baseboard-y=baseboard.o +baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +baseboard-$(CONFIG_CBI_EEPROM)+=cbi.o diff --git a/baseboard/guybrush/cbi.c b/baseboard/guybrush/cbi.c new file mode 100644 index 0000000000..1baf506297 --- /dev/null +++ b/baseboard/guybrush/cbi.c @@ -0,0 +1,94 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush CrOS Board Info(CBI) utilities */ + +#include "base_fw_config.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +uint32_t get_sku_id(void) +{ + static uint32_t sku_id; + + if (sku_id == 0) { + uint32_t val; + + if (cbi_get_sku_id(&val) != EC_SUCCESS) + return 0; + sku_id = val; + } + return sku_id; +} + +uint32_t get_board_version(void) +{ + static uint32_t board_version; + + if (board_version == 0) { + uint32_t val; + + if (cbi_get_board_version(&val) != EC_SUCCESS) + return -1; + board_version = val; + } + return board_version; +} + +uint32_t get_fw_config(void) +{ + static uint32_t fw_config = UNINITIALIZED_FW_CONFIG; + + if (fw_config == UNINITIALIZED_FW_CONFIG) { + uint32_t val; + + if (cbi_get_fw_config(&val) != EC_SUCCESS) + return UNINITIALIZED_FW_CONFIG; + fw_config = val; + } + return fw_config; +} + +int get_fw_config_field(uint8_t offset, uint8_t width) +{ + uint32_t fw_config = get_fw_config(); + + if (fw_config == UNINITIALIZED_FW_CONFIG) + return -1; + + return (fw_config >> offset) & ((1 << width) - 1); +} + +__overridable void board_cbi_init(void) +{ +} + +static void cbi_init(void) +{ + uint32_t board_ver = get_board_version(); + uint32_t sku_id = get_sku_id(); + uint32_t fw_config = get_fw_config(); + + if (board_ver != 0) + ccprints("Board Version: %d (0x%x)", board_ver, board_ver); + else + ccprints("Board Version: not set in cbi"); + + if (sku_id != 0) + ccprints("SKU ID: %d (0x%x)", sku_id, sku_id); + else + ccprints("SKU ID: not set in cbi"); + + if (fw_config != UNINITIALIZED_FW_CONFIG) + ccprints("FW Config: %d (0x%x)", fw_config, fw_config); + else + ccprints("FW Config: not set in cbi"); + + /* Allow the board project to make runtime changes based on CBI data */ + board_cbi_init(); +} +DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); diff --git a/baseboard/guybrush/usb_pd_policy.c b/baseboard/guybrush/usb_pd_policy.c new file mode 100644 index 0000000000..8acb2c7a23 --- /dev/null +++ b/baseboard/guybrush/usb_pd_policy.c @@ -0,0 +1,92 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Shared USB-C policy for Zork boards */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "ioexpander.h" +#include "system.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +int pd_check_vconn_swap(int port) +{ + /* + * Do not allow vconn swap 5V rail is off + * S5_PGOOD depends on PG_PP5000_S5 being asserted, + * so GPIO_S5_PGOOD is a reasonable proxy for PP5000_S5 + */ + return gpio_get_level(GPIO_S5_PGOOD); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE)) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE)) + pd_set_vbus_discharge(port, 0); + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +__override int board_pd_set_frs_enable(int port, int enable) +{ + /* + * Both PPCs require the FRS GPIO to be set as soon as FRS capability + * is established. + */ + if (port == 0) + ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, enable); + else if (port == 1) + ioex_set_level(IOEX_USB_C1_TCPC_FASTSW_CTL_EN, enable); + + return EC_SUCCESS; +} + +/* Used by Vbus discharge common code with CONFIG_USB_PD_DISCHARGE */ +int board_vbus_source_enabled(int port) +{ + return tcpm_get_src_ctrl(port); +} + +/* Used by USB charger task with CONFIG_USB_PD_5V_EN_CUSTOM */ +int board_is_sourcing_vbus(int port) +{ + return board_vbus_source_enabled(port); +} diff --git a/baseboard/hatch/baseboard.c b/baseboard/hatch/baseboard.c index 367f83e8d2..b342cd74ed 100644 --- a/baseboard/hatch/baseboard.c +++ b/baseboard/hatch/baseboard.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,7 +7,7 @@ #include "atomic.h" #include "battery_fuel_gauge.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "chipset.h" #include "console.h" #include "cros_board_info.h" @@ -26,16 +26,16 @@ #include "power.h" #include "stdbool.h" #include "system.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "timer.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) /******************************************************************************/ /* Wake up pins */ @@ -52,25 +52,65 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* I2C port map configuration */ const struct i2c_port_t i2c_ports[] = { #ifdef CONFIG_ACCEL_FIFO - {"sensor", I2C_PORT_SENSOR, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, #endif - {"ppc0", I2C_PORT_PPC0, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, + { .name = "ppc0", + .port = I2C_PORT_PPC0, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, #if CONFIG_USB_PD_PORT_MAX_COUNT > 1 - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, #endif - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, #ifdef BOARD_AKEMI - {"thermal", I2C_PORT_THERMAL, 400, GPIO_I2C4_SCL, GPIO_I2C4_SDA}, + { .name = "thermal", + .port = I2C_PORT_THERMAL, + .kbps = 400, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA }, #endif #ifdef BOARD_JINLON - {"thermal", I2C_PORT_THERMAL, 100, GPIO_I2C4_SCL, GPIO_I2C4_SDA}, + { .name = "thermal", + .port = I2C_PORT_THERMAL, + .kbps = 100, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA }, #endif #ifdef BOARD_MUSHU - {"f75303_temp", I2C_PORT_THERMAL, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"gpu_temp", I2C_PORT_GPU, 100, GPIO_I2C4_SCL, GPIO_I2C4_SDA}, + { .name = "f75303_temp", + .port = I2C_PORT_THERMAL, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "gpu_temp", + .port = I2C_PORT_GPU, + .kbps = 100, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA }, #endif - {"power", I2C_PORT_POWER, 100, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, - {"eeprom", I2C_PORT_EEPROM, 100, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 100, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -93,14 +133,6 @@ __attribute__((weak)) bool board_has_kb_backlight(void) return true; } -/* Called on AP S5 -> S3 transition */ -static void baseboard_chipset_startup(void) -{ - /* TODD(b/122266850): Need to fill out this hook */ -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, baseboard_chipset_startup, - HOOK_PRIO_DEFAULT); - /* Called on AP S0iX -> S0 transition */ static void baseboard_chipset_resume(void) { @@ -118,14 +150,6 @@ static void baseboard_chipset_suspend(void) DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, baseboard_chipset_suspend, HOOK_PRIO_DEFAULT); -/* Called on AP S3 -> S5 transition */ -static void baseboard_chipset_shutdown(void) -{ - -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, baseboard_chipset_shutdown, - HOOK_PRIO_DEFAULT); - void board_hibernate(void) { int port; @@ -134,7 +158,7 @@ void board_hibernate(void) * To support hibernate from ectool, keyboard, and console, * ensure that the AP is fully shutdown before hibernating. */ -#ifdef HAS_TASK_CHIPSET +#ifdef CONFIG_AP_POWER_CONTROL chipset_force_shutdown(CHIPSET_SHUTDOWN_BOARD_CUSTOM); #endif @@ -158,17 +182,13 @@ void board_hibernate(void) /******************************************************************************/ /* USB-C PPC Configuration */ struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { - [USB_PD_PORT_TCPC_0] = { - .i2c_port = I2C_PORT_PPC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, + [USB_PD_PORT_TCPC_0] = { .i2c_port = I2C_PORT_PPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, #if CONFIG_USB_PD_PORT_MAX_COUNT > 1 - [USB_PD_PORT_TCPC_1] = { - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, + [USB_PD_PORT_TCPC_1] = { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, #endif }; unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); @@ -226,8 +246,8 @@ uint16_t tcpc_get_alert_status(void) return status; } -static void reset_pd_port(int port, enum gpio_signal reset_gpio, - int hold_delay, int finish_delay) +static void reset_pd_port(int port, enum gpio_signal reset_gpio, int hold_delay, + int finish_delay) { int level = !!(tcpc_config[port].flags & TCPC_FLAGS_RESET_ACTIVE_HIGH); @@ -264,8 +284,7 @@ void board_reset_pd_mcu(void) int board_set_active_charge_port(int port) { - int is_valid_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); int i; if (!is_valid_port && port != CHARGE_PORT_NONE) @@ -321,39 +340,30 @@ int ppc_get_alert_status(int port) if (port == USB_PD_PORT_TCPC_0) return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; return port == USB_PD_PORT_TCPC_0 ? - gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0 : + gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0 : #if CONFIG_USB_PD_PORT_MAX_COUNT > 1 - gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; #else - EC_SUCCESS; + EC_SUCCESS; #endif } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} - #ifdef USB_PD_PORT_TCPC_MST void baseboard_mst_enable_control(enum mst_source src, int level) { - static uint32_t mst_input_levels; + static atomic_t mst_input_levels; if (level) - deprecated_atomic_or(&mst_input_levels, 1 << src); + atomic_or(&mst_input_levels, 1 << src); else - deprecated_atomic_clear_bits(&mst_input_levels, 1 << src); + atomic_clear_bits(&mst_input_levels, 1 << src); gpio_set_level(GPIO_EN_MST, mst_input_levels ? 1 : 0); } #endif /* Enable or disable input devices, based on chipset state */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { if (board_is_convertible()) { if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) @@ -361,7 +371,6 @@ void lid_angle_peripheral_enable(int enable) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } } -#endif static uint8_t sku_id; static uint8_t board_id; diff --git a/baseboard/hatch/baseboard.h b/baseboard/hatch/baseboard.h index 00ce1e0dac..4aee5200de 100644 --- a/baseboard/hatch/baseboard.h +++ b/baseboard/hatch/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,21 +8,22 @@ #ifndef __CROS_EC_BASEBOARD_H #define __CROS_EC_BASEBOARD_H +#include "compiler.h" #include "stdbool.h" /* * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* NPCX7 config */ -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ -#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ /* Internal SPI flash on NPCX796FC is 512 kB */ -#define CONFIG_FLASH_SIZE (512 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ #define CONFIG_I2C @@ -34,7 +35,7 @@ #define CONFIG_ADC #define CONFIG_BOARD_VERSION_CBI #define CONFIG_CRC8 -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_DPTF #define CONFIG_HIBERNATE_PSL #define CONFIG_LED_ONOFF_STATES @@ -95,30 +96,31 @@ #define CONFIG_CHARGER #define CONFIG_CHARGER_BQ25710 #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 /* Allow low-current USB charging */ +/* Allow low-current USB charging */ +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#undef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 -#define CONFIG_CHARGER_NARROW_VDC #define CONFIG_CHARGE_RAMP_HW -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 /* * Don't allow the system to boot to S0 when the battery is low and unable to * communicate on locked systems (which haven't PD negotiated) */ #define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC 1 #define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 15001 /* Common battery defines */ #define CONFIG_BATTERY_CUT_OFF -#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_FUEL_GAUGE #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_BATTERY_PRESENT_CUSTOM #define CONFIG_BATTERY_REVIVE_DISCONNECT #define CONFIG_BATTERY_SMART -#undef CONFIG_BATT_HOST_FULL_FACTOR -#define CONFIG_BATT_HOST_FULL_FACTOR 100 +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 100 /* USB Type C and USB PD defines */ #define CONFIG_USB_POWER_DELIVERY @@ -153,9 +155,9 @@ /* Include CLI command needed to support CCD testing. */ #define CONFIG_CMD_CHARGEN -#define USB_PD_PORT_TCPC_0 0 +#define USB_PD_PORT_TCPC_0 0 #if CONFIG_USB_PD_PORT_MAX_COUNT > 1 -#define USB_PD_PORT_TCPC_1 1 +#define USB_PD_PORT_TCPC_1 1 #endif /* BC 1.2 */ @@ -167,33 +169,32 @@ #endif /* TODO(b/122273953): Use correct PD delay values */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* TODO(b/122273953): Use correct PD power values */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* I2C Bus Configuration */ #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_PPC0 NPCX_I2C_PORT1_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 -#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 -#define I2C_PORT_THERMAL NPCX_I2C_PORT4_1 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_POWER +#define CONFIG_I2C_CONTROLLER +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_PPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 +#define I2C_PORT_THERMAL NPCX_I2C_PORT4_1 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_POWER /* Other common defines */ #define CONFIG_BACKLIGHT_LID -#define GPIO_ENABLE_BACKLIGHT GPIO_EDP_BKLTEN_OD +#define GPIO_ENABLE_BACKLIGHT GPIO_EDP_BKLTEN_OD #define PP5000_PGOOD_POWER_SIGNAL_MASK POWER_SIGNAL_MASK(X86_PP5000_A_PGOOD) @@ -213,6 +214,8 @@ void board_reset_pd_mcu(void); void baseboard_mst_enable_control(enum mst_source, int level); bool board_is_convertible(void); +FORWARD_DECLARE_ENUM(battery_present); + /* Check with variant about battery presence. */ enum battery_present variant_battery_present(void); diff --git a/baseboard/hatch/battery.c b/baseboard/hatch/battery.c index 063aa3721d..5ae92e8ec8 100644 --- a/baseboard/hatch/battery.c +++ b/baseboard/hatch/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -32,8 +32,9 @@ static int battery_init(void) { int batt_status; - return battery_status(&batt_status) ? 0 : - !!(batt_status & STATUS_INITIALIZED); + return battery_status(&batt_status) ? + 0 : + !!(batt_status & STATUS_INITIALIZED); } /* diff --git a/baseboard/hatch/build.mk b/baseboard/hatch/build.mk index 864225f605..f98ffdcb3f 100644 --- a/baseboard/hatch/build.mk +++ b/baseboard/hatch/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/baseboard/hatch/usb_pd_policy.c b/baseboard/hatch/usb_pd_policy.c index c0c75f9cdb..6abb6e4454 100644 --- a/baseboard/hatch/usb_pd_policy.c +++ b/baseboard/hatch/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,15 +12,15 @@ #include "ec_commands.h" #include "gpio.h" #include "system.h" -#include "tcpci.h" -#include "tcpm.h" +#include "tcpm/tcpci.h" +#include "tcpm/tcpm.h" #include "usb_mux.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { diff --git a/baseboard/herobrine/baseboard.c b/baseboard/herobrine/baseboard.c new file mode 100644 index 0000000000..fca6e9c66d --- /dev/null +++ b/baseboard/herobrine/baseboard.c @@ -0,0 +1,13 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Herobrine baseboard-specific configuration */ + +#include "i2c.h" + +int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc) +{ + return (cmd_desc->port == I2C_PORT_VIRTUAL_BATTERY); +} diff --git a/baseboard/herobrine/baseboard.h b/baseboard/herobrine/baseboard.h new file mode 100644 index 0000000000..72b8b02b04 --- /dev/null +++ b/baseboard/herobrine/baseboard.h @@ -0,0 +1,217 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Herobrine baseboard configuration */ + +#ifndef __CROS_EC_BASEBOARD_H +#define __CROS_EC_BASEBOARD_H + +/* + * By default, enable all console messages excepted event and HC: + * The sensor stack is generating a lot of activity. + * They can be enabled through the console command 'chan'. + */ +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_HOSTCMD))) + +/* NPCX7 config */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX_TACH_SEL2 0 /* No tach. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_SPI_FLASH_REGS +#define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ + +/* EC Modules */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER +#define CONFIG_I2C_VIRTUAL_BATTERY +#define CONFIG_I2C_PASSTHRU_RESTRICTED +#define CONFIG_LED_COMMON +#define CONFIG_LOW_POWER_IDLE +#define CONFIG_ADC +#define CONFIG_BACKLIGHT_LID +#define CONFIG_FPU +#define CONFIG_PWM +#define CONFIG_PWM_DISPLIGHT +#define CONFIG_HIBERNATE_PSL + +#define CONFIG_VBOOT_HASH + +#undef CONFIG_PECI + +#define CONFIG_HOST_INTERFACE_SHI +#define CONFIG_HOST_COMMAND_STATUS +#define CONFIG_HOSTCMD_SECTION_SORTED +#define CONFIG_KEYBOARD_COL2_INVERTED +#define CONFIG_MKBP_USE_GPIO + +#define CONFIG_BOARD_VERSION_GPIO +#define CONFIG_CBI_GPIO +#define CONFIG_CRC8 +#define CONFIG_POWER_BUTTON +#define CONFIG_VOLUME_BUTTONS +#define CONFIG_EMULATED_SYSRQ +#define CONFIG_CMD_BUTTON +#define CONFIG_SWITCH +#define CONFIG_LID_SWITCH +#define CONFIG_EXTPOWER_GPIO + +/* + * On power-on, H1 releases the EC from reset but then quickly asserts and + * releases the reset a second time. This means the EC sees 2 resets: + * (1) power-on reset, (2) reset-pin reset. This config will + * allow the second reset to be treated as a power-on. + */ +#define CONFIG_BOARD_RESET_AFTER_POWER_ON + +/* Increase console output buffer since we have the RAM available. */ +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Battery */ +#define CONFIG_BATTERY_CUT_OFF +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_BATT_PRES_ODL +#define CONFIG_BATTERY_SMART + +/* Charger */ +#define CONFIG_CHARGER +#define CONFIG_CHARGE_MANAGER +#define CONFIG_CHARGER_ISL9238 +#define CONFIG_CHARGER_PROFILE_OVERRIDE +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_USB_CHARGER +#define CONFIG_CMD_CHARGER_ADC_AMON_BMON +#define CONFIG_CHARGER_PSYS +#define CONFIG_CHARGER_PSYS_READ +#define CONFIG_CHARGER_DISCHARGE_ON_AC + +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 10000 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 + +/* + * USB ID + * + * This is allocated specifically for Herobrine + * http://google3/hardware/standards/usb/ + */ +#define CONFIG_USB_PID 0x5055 + +/* USB */ +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_HOSTCMD_PD_CONTROL +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_LOGGING +#define CONFIG_USB_PD_TCPM_MUX +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_USB_PD_TRY_SRC +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_5V_EN_CUSTOM +#define CONFIG_USBC_SS_MUX +#define CONFIG_USBC_SS_MUX_DFP_ONLY +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP + +/* RTC */ +#define CONFIG_CMD_RTC +#define CONFIG_HOSTCMD_RTC + +/* Sensors */ +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is a power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs. */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* PD */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ + +#define PD_OPERATING_POWER_MW 10000 +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* Chipset */ +#define CONFIG_CHIPSET_SC7280 +#define CONFIG_CHIPSET_RESET_HOOK +#define CONFIG_CHIPSET_RESUME_INIT_HOOK +#define CONFIG_POWER_COMMON +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_CMD_AP_RESET_LOG + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_LID_OPEN GPIO_LID_OPEN_EC +#define GPIO_SHI_CS_L GPIO_AP_EC_SPI_CS_L +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_BATT_PRES_ODL GPIO_EC_BATT_PRES_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_BL_DISABLE_L +#define GPIO_BOARD_VERSION1 GPIO_BRD_ID0 +#define GPIO_BOARD_VERSION2 GPIO_BRD_ID1 +#define GPIO_BOARD_VERSION3 GPIO_BRD_ID2 +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV + +/* I2C Ports */ +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_CHARGER I2C_PORT_POWER +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_POWER NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 +#define I2C_PORT_WLC NPCX_I2C_PORT3_0 +#define I2C_PORT_RTC NPCX_I2C_PORT4_1 +#define I2C_PORT_EEPROM NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT7_0 + +/* UART */ +#define CONFIG_CMD_CHARGEN + +/* Define the host events which are allowed to wake AP up from S3 */ +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_HANG_DETECT) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_DEVICE)) + +/* And the MKBP events */ +#ifdef HAS_TASK_KEYSCAN +#define CONFIG_MKBP_EVENT_WAKEUP_MASK \ + (BIT(EC_MKBP_EVENT_KEY_MATRIX) | BIT(EC_MKBP_EVENT_HOST_EVENT) | \ + BIT(EC_MKBP_EVENT_SENSOR_FIFO)) +#else +#define CONFIG_MKBP_EVENT_WAKEUP_MASK \ + (BIT(EC_MKBP_EVENT_HOST_EVENT) | BIT(EC_MKBP_EVENT_SENSOR_FIFO)) +#endif + +#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/herobrine/build.mk b/baseboard/herobrine/build.mk new file mode 100644 index 0000000000..67c2e2143f --- /dev/null +++ b/baseboard/herobrine/build.mk @@ -0,0 +1,11 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Baseboard specific files build +# + +baseboard-y+=baseboard.o +baseboard-y+=usbc_config.o +baseboard-y+=usb_pd_policy.o diff --git a/baseboard/herobrine/usb_pd_policy.c b/baseboard/herobrine/usb_pd_policy.c new file mode 100644 index 0000000000..9fa725c845 --- /dev/null +++ b/baseboard/herobrine/usb_pd_policy.c @@ -0,0 +1,259 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "console.h" +#include "gpio.h" +#include "system.h" +#include "usb_mux.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* In G3, do not allow vconn swap since PP5000 rail is off */ + return gpio_get_level(GPIO_EN_PP5000); +} + +static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; +#if CONFIG_USB_PD_PORT_MAX_COUNT == 1 +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5 }; +#else +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; +#endif + +static void board_vbus_update_source_current(int port) +{ + /* Both port are controlled by PPC SN5S330. */ + ppc_set_vbus_source_current_limit(port, vbus_rp[port]); + ppc_vbus_source_enable(port, vbus_en[port]); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + prev_en = vbus_en[port]; + + /* Disable VBUS */ + vbus_en[port] = 0; + board_vbus_update_source_current(port); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* notify host of power info change */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + /* Disable charging */ + board_vbus_sink_enable(port, 0); + + pd_set_vbus_discharge(port, 0); + + /* Provide VBUS */ + vbus_en[port] = 1; + board_vbus_update_source_current(port); + + /* notify host of power info change */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; /* we are ready */ +} + +int board_vbus_source_enabled(int port) +{ + return vbus_en[port]; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + vbus_rp[port] = rp; + board_vbus_update_source_current(port); +} + +int pd_snk_is_vbus_provided(int port) +{ + return tcpm_check_vbus_level(port, VBUS_PRESENT); +} + +/* ----------------- Vendor Defined Messages ------------------ */ +#ifdef CONFIG_USB_PD_ALT_MODE_DFP +__override int svdm_dp_config(int port, uint32_t *payload) +{ + int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); + uint8_t pin_mode = get_dp_pin_mode(port); + + if (!pin_mode) + return 0; + + /* + * Defer setting the usb_mux until HPD goes high, svdm_dp_attention(). + * The AP only supports one DP phy. An external DP mux switches between + * the two ports. Should switch those muxes when it is really used, + * i.e. HPD high; otherwise, the real use case is preempted, like: + * (1) plug a dongle without monitor connected to port-0, + * (2) plug a dongle without monitor connected to port-1, + * (3) plug a monitor to the port-1 dongle. + */ + + payload[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); + payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ + 1, /* DPv1.3 signaling */ + 2); /* UFP connected */ + return 2; +}; + +__override void svdm_dp_post_config(int port) +{ + dp_flags[port] |= DP_FLAGS_DP_ON; +} + +/** + * Is the port fine to be muxed its DisplayPort lines? + * + * Only one port can be muxed to DisplayPort at a time. + * + * @param port Port number of TCPC. + * @return 1 is fine; 0 is bad as other port is already muxed; + */ +static int is_dp_muxable(int port) +{ + int i; + + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + if (i != port) { + if (usb_mux_get(i) & USB_PD_MUX_DP_ENABLED) + return 0; + } + + return 1; +} + +__override int svdm_dp_attention(int port, uint32_t *payload) +{ + enum gpio_signal hpd = GPIO_DP_HOT_PLUG_DET; + int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); + int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); + int cur_lvl = gpio_get_level(hpd); + mux_state_t mux_state; + + dp_status[port] = payload[1]; + + if (!is_dp_muxable(port)) { + /* TODO(waihong): Info user? */ + CPRINTS("p%d: The other port is already muxed.", port); + return 0; + } + + /* + * Initial implementation to handle HPD. Only the first-plugged port + * works, i.e. sending HPD signal to AP. The second-plugged port + * will be ignored. + * + * TODO(waihong): Continue the above case, if the first-plugged port + * is then unplugged, switch to the second-plugged port and signal AP? + */ + if (lvl) { + /* + * Enable and switch the DP port selection mux to the + * correct port. + * + * TODO(waihong): Better to move switching DP mux to + * the usb_mux abstraction. + */ + gpio_set_level(GPIO_DP_MUX_SEL, port == 1); + gpio_set_level(GPIO_DP_MUX_OE_L, 0); + + /* Connect the SBU lines in PPC chip. */ + if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) + ppc_set_sbu(port, 1); + + /* + * Connect the USB SS/DP lines in TCPC chip. + * + * When mf_pref not true, still use the dock muxing + * because of the board USB-C topology (limited to 2 + * lanes DP). + */ + usb_mux_set(port, USB_PD_MUX_DOCK, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); + } else { + /* Disconnect the DP port selection mux. */ + gpio_set_level(GPIO_DP_MUX_OE_L, 1); + gpio_set_level(GPIO_DP_MUX_SEL, 0); + + /* Disconnect the SBU lines in PPC chip. */ + if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) + ppc_set_sbu(port, 0); + + /* Disconnect the DP but keep the USB SS lines in TCPC chip. */ + usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); + } + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && (irq || lvl)) + /* + * Wake up the AP. IRQ or level high indicates a DP sink is now + * present. + */ + pd_notify_dp_alt_mode_entry(port); + + /* Configure TCPC for the HPD event, for proper muxing */ + mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | + (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); + usb_mux_hpd_update(port, mux_state); + + /* Signal AP for the HPD event, through GPIO to AP */ + if (irq & cur_lvl) { + uint64_t now = get_time().val; + /* Wait for the minimum spacing between IRQ_HPD if needed */ + if (now < svdm_hpd_deadline[port]) + usleep(svdm_hpd_deadline[port] - now); + + /* Generate IRQ_HPD pulse */ + gpio_set_level(hpd, 0); + usleep(HPD_DSTREAM_DEBOUNCE_IRQ); + gpio_set_level(hpd, 1); + + /* Set the minimum time delay (2ms) for the next HPD IRQ */ + svdm_hpd_deadline[port] = + get_time().val + HPD_USTREAM_DEBOUNCE_LVL; + } else if (irq & !lvl) { + CPRINTF("ERR:HPD:IRQ&LOW\n"); + return 0; + } else { + gpio_set_level(hpd, lvl); + /* Set the minimum time delay (2ms) for the next HPD IRQ */ + svdm_hpd_deadline[port] = + get_time().val + HPD_USTREAM_DEBOUNCE_LVL; + } + + return 1; +} + +__override void svdm_exit_dp_mode(int port) +{ + if (is_dp_muxable(port)) { + /* Disconnect the DP port selection mux. */ + gpio_set_level(GPIO_DP_MUX_OE_L, 1); + gpio_set_level(GPIO_DP_MUX_SEL, 0); + + /* Signal AP for the HPD low event */ + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); + gpio_set_level(GPIO_DP_HOT_PLUG_DET, 0); + } +} +#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/baseboard/herobrine/usbc_config.c b/baseboard/herobrine/usbc_config.c new file mode 100644 index 0000000000..a5df0a0d4c --- /dev/null +++ b/baseboard/herobrine/usbc_config.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Herobrine family-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "console.h" +#include "usb_pd.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/baseboard/honeybuns/baseboard.c b/baseboard/honeybuns/baseboard.c index bb0a1c832d..430eb488e7 100644 --- a/baseboard/honeybuns/baseboard.c +++ b/baseboard/honeybuns/baseboard.c @@ -1,48 +1,492 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Honeybuns family-specific configuration */ #include "console.h" +#include "cros_board_info.h" +#include "driver/mp4245.h" +#include "driver/tcpm/tcpm.h" #include "gpio.h" #include "hooks.h" #include "i2c.h" +#include "system.h" +#include "task.h" #include "timer.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) -/******************************************************************************/ -__overridable const struct power_seq board_power_seq[] = { }; +#define POWER_BUTTON_SHORT_USEC (300 * MSEC) +#define POWER_BUTTON_LONG_USEC (5000 * MSEC) +#define POWER_BUTTON_DEBOUNCE_USEC (30) + +#define BUTTON_EVT_CHANGE BIT(0) +#define BUTTON_EVT_INFO BIT(1) + +enum power { POWER_OFF, POWER_ON }; -__overridable const size_t board_power_seq_count = - ARRAY_SIZE(board_power_seq); +enum button { + BUTTON_RELEASE, + BUTTON_PRESS, + BUTTON_PRESS_POWER_ON, + BUTTON_PRESS_SHORT, + BUTTON_PRESS_LONG, +}; + +#define LED_ON_OFF_BIT BIT(0) +#define LED_COLOR_BIT BIT(2) +#define LED_FLASH_SEQ_LENGTH 8 -static void board_power_sequence(void) +enum led_color { + GREEN, + YELLOW, + OFF, +}; + +static enum power dock_state; +#ifdef SECTION_IS_RW +static int button_level; +static int button_level_pending; +static int dock_mf; +static int led_count; +#endif + +/******************************************************************************/ + +__maybe_unused static void board_power_sequence(int enable) { int i; - for(i = 0; i < board_power_seq_count; i++) { - gpio_set_level(board_power_seq[i].signal, - board_power_seq[i].level); - msleep(board_power_seq[i].delay_ms); + if (enable) { + for (i = 0; i < board_power_seq_count; i++) { + gpio_set_level(board_power_seq[i].signal, + board_power_seq[i].level); + CPRINTS("power seq: rail = %d", i); + if (board_power_seq[i].delay_ms) + msleep(board_power_seq[i].delay_ms); + } + } else { + for (i = board_power_seq_count - 1; i >= 0; i--) { + gpio_set_level(board_power_seq[i].signal, + !board_power_seq[i].level); + CPRINTS("sequence[%d]: level = %d", i, + !board_power_seq[i].level); + } } + + dock_state = enable; + CPRINTS("board: Power rails %s", dock_state ? "on" : "off"); } /******************************************************************************/ /* I2C port map configuration */ const struct i2c_port_t i2c_ports[] = { - {"usbc", I2C_PORT_USBC, 400, GPIO_EC_I2C1_SCL, GPIO_EC_I2C1_SDA}, - {"usb_mst", I2C_PORT_MST, 400, GPIO_EC_I2C2_SCL, GPIO_EC_I2C2_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_EC_I2C3_SCL, GPIO_EC_I2C3_SDA}, + { .name = "i2c1", + .port = I2C_PORT_I2C1, + .kbps = 400, + .scl = GPIO_EC_I2C1_SCL, + .sda = GPIO_EC_I2C1_SDA }, + { .name = "i2c3", + .port = I2C_PORT_I2C3, + .kbps = 400, + .scl = GPIO_EC_I2C3_SCL, + .sda = GPIO_EC_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +#ifdef SECTION_IS_RW +static void baseboard_set_led(enum led_color color) +{ + /* + * TODO(b/164157329): The power button feature should be connected to a + * 2 color LED which is part of the button. Currently, the power button + * LED is a single color LED which is controlled by on the of the power + * rails. Using the status LED now to demonstrate the LED behavior + * associated with a power button press. + */ + CPRINTS("led: color = %d", color); + + /* Not all boards may have LEDs under EC control */ +#if defined(GPIO_PWR_BUTTON_RED) && defined(GPIO_PWR_BUTTON_GREEN) + if (color == OFF) { + gpio_set_level(GPIO_PWR_BUTTON_RED, 1); + gpio_set_level(GPIO_PWR_BUTTON_GREEN, 1); + } else if (color == GREEN) { + gpio_set_level(GPIO_PWR_BUTTON_RED, 1); + gpio_set_level(GPIO_PWR_BUTTON_GREEN, 0); + } else if (color == YELLOW) { + gpio_set_level(GPIO_PWR_BUTTON_RED, 0); + gpio_set_level(GPIO_PWR_BUTTON_GREEN, 0); + } +#endif +} + +static void baseboard_led_callback(void); +DECLARE_DEFERRED(baseboard_led_callback); + +static void baseboard_led_callback(void) +{ + /* + * Flash LED on transition using a simple 3 bit counter. Bit 0 controls + * LED on/off and bit 2 controls which color to set during the on phase. + */ + int color = led_count & LED_COLOR_BIT ? dock_mf : dock_mf ^ 1; + + /* + * TODO(b/164157329): This function implements a simple flashing + * transition when the MF preference bit is changed via a long power + * button press sequence. This might need to move to the board function + * if not required/desired on all variants. + */ + + if (led_count & LED_ON_OFF_BIT) + baseboard_set_led(color); + else + baseboard_set_led(OFF); + + /* Flash sequence is 8 steps */ + if (++led_count < LED_FLASH_SEQ_LENGTH) + hook_call_deferred(&baseboard_led_callback_data, 150 * MSEC); +} + +static void baseboard_change_mf_led(void) +{ + led_count = 0; + baseboard_led_callback(); +} + +void baseboard_set_mst_lane_control(int mf) +{ + /* + * The parameter mf reflects the desired lane control value. If the + * current value does not match the desired, then the MST hub must first + * be put into reset, so the MST hub will latch in the correct value + * when it's taken out of reset. + */ + if (mf != gpio_get_level(GPIO_MST_HUB_LANE_SWITCH)) { + /* put MST into reset */ + gpio_set_level(GPIO_MST_RST_L, 0); + msleep(1); + gpio_set_level(GPIO_MST_HUB_LANE_SWITCH, mf); + CPRINTS("MST: lane control = %s", mf ? "high" : "low"); + msleep(1); + /* lane control is set, take MST out of reset */ + gpio_set_level(GPIO_MST_RST_L, 1); + } +} + +static void baseboard_enable_mp4245(void) +{ + int mv; + int ma; + + mp4245_set_voltage_out(5000); + mp4245_votlage_out_enable(1); + msleep(MP4245_VOUT_5V_DELAY_MS); + mp3245_get_vbus(&mv, &ma); + CPRINTS("mp4245: vout @ %d mV enabled", mv); +} + +#endif /* SECTION_IS_RW */ + static void baseboard_init(void) { +#ifdef SECTION_IS_RW + uint32_t fw_config; +#endif + /* Turn on power rails */ - board_power_sequence(); + board_power_sequence(1); CPRINTS("board: Power rails enabled"); + +#ifdef SECTION_IS_RW + /* Force TC state machine to start in TC_ERROR_RECOVERY */ + system_clear_reset_flags(EC_RESET_FLAG_POWER_ON); + /* Make certain SN5S330 PPC does full initialization */ + system_set_reset_flags(EC_RESET_FLAG_EFS); + + /* + * Dock multi function (mf) preference is stored in bit 0 of fw_config + * field of the CBI. If this value is programmed, then make sure the + * MST_LANE_CONTROL gpio matches the mf bit. + */ + if (!cbi_get_fw_config(&fw_config)) { + dock_mf = CBI_FW_MF_PREFERENCE(fw_config); + baseboard_set_mst_lane_control(dock_mf); + } else { + dock_mf = dock_get_mf_preference(); + cbi_set_fw_config(dock_mf); + CPRINTS("cbi: setting default result = %s", + cbi_get_fw_config(&fw_config) ? "pass" : "fail"); + } + +#ifdef GPIO_USBC_UF_ATTACHED_SRC + /* Configure UF usbc ppc and check usbc state */ + baseboard_config_usbc_usb3_ppc(); +#endif /* GPIO_USBC_UF_ATTACHED_SRC */ + + /* Enable power button interrupt */ + gpio_enable_interrupt(GPIO_PWR_BTN); + /* Set dock mf preference LED */ + baseboard_set_led(dock_mf); + /* Setup VBUS to default value */ + baseboard_enable_mp4245(); + +#else + /* Set up host port usbc to present Rd on CC lines */ + if (baseboard_usbc_init(USB_PD_PORT_HOST)) + CPRINTS("usbc: Failed to set up sink path"); + else + CPRINTS("usbc: sink path configure success!"); +#endif /* SECTION_IS_RW */ } -DECLARE_HOOK(HOOK_INIT, baseboard_init, HOOK_PRIO_DEFAULT); +/* + * Power sequencing must run before any other chip init is attempted, so run + * power sequencing as soon as I2C bus is initialized. + */ +DECLARE_HOOK(HOOK_INIT, baseboard_init, HOOK_PRIO_INIT_I2C + 1); + +#ifdef SECTION_IS_RW +static void baseboard_power_on(void) +{ + int port_max = board_get_usb_pd_port_count(); + int port; + + CPRINTS("pwrbtn: power on: mf = %d", dock_mf); + /* Adjust system flags to full PPC init occurs */ + system_clear_reset_flags(EC_RESET_FLAG_POWER_ON); + system_set_reset_flags(EC_RESET_FLAG_EFS); + /* Enable power rails and release reset signals */ + board_power_sequence(1); + /* Set VBUS to 5V and enable output from mp4245 */ + baseboard_enable_mp4245(); + /* Set dock mf preference LED */ + baseboard_set_led(dock_mf); + /* + * Lane control (realtek MST) must be set prior to releasing MST + * reset. + */ + baseboard_set_mst_lane_control(dock_mf); + /* + * When the power to the PPC is turned off, then back on, the PPC will + * default into dead battery mode. Dead battery resistors are disabled + * as part of the full PPC intializaiton sequence. This is required to + * force a detach event with port parter which can be attached as usbc + * source when honeybuns power rails are off. + */ + for (port = 0; port < port_max; port++) { + ppc_init(port); + msleep(1000); + /* Inform TC state machine that it can resume */ + pd_set_suspend(port, 0); + } + /* Enable usbc interrupts */ + board_enable_usbc_interrupts(); + +#ifdef GPIO_USBC_UF_ATTACHED_SRC + baseboard_config_usbc_usb3_ppc(); +#endif +} + +static void baseboard_power_off(void) +{ + int port_max = board_get_usb_pd_port_count(); + int port; + + CPRINTS("pwrbtn: power off"); + /* Put ports in TC suspend state */ + for (port = 0; port < port_max; port++) + pd_set_suspend(port, 1); + + /* Disable ucpd peripheral (prevents interrupts) */ + tcpm_release(USB_PD_PORT_HOST); + /* Disable PPC/TCPC interrupts */ + board_disable_usbc_interrupts(); + +#ifdef GPIO_USBC_UF_ATTACHED_SRC + /* Disable PPC interrupts for PS8803 managed port */ + baseboard_usbc_usb3_enable_interrupts(0); +#endif + /* Set dock power button/MF preference LED */ + baseboard_set_led(OFF); + /* Go into power off state */ + board_power_sequence(0); +} + +static void baseboard_toggle_mf(void) +{ + uint32_t fw_config; + + if (!cbi_get_fw_config(&fw_config)) { + /* Update the user MF preference stored in CBI */ + fw_config ^= CBI_FW_MF_MASK; + cbi_set_fw_config(fw_config); + /* Update variable used to track user MF preference */ + dock_mf = CBI_FW_MF_PREFERENCE(fw_config); + /* Flash led for visual indication of user MF change */ + baseboard_change_mf_led(); + + /* + * Suspend, then release host port to force new MF setting to + * take effect. + */ + pd_set_suspend(USB_PD_PORT_HOST, 1); + msleep(250); + pd_set_suspend(USB_PD_PORT_HOST, 0); + } +} + +/* + * Main task entry point for UCPD task + */ +void power_button_task(void *u) +{ + int timer_us = POWER_BUTTON_DEBOUNCE_USEC * 4; + enum button state = BUTTON_RELEASE; + uint32_t evt; + + /* + * Capture current button level in case it's being pressed when the dock + * is powered on. Note timer_us is initialized for debounce time to + * double check. + */ + button_level = gpio_get_level(GPIO_PWR_BTN); + + while (1) { + evt = task_wait_event(timer_us); + timer_us = -1; + + if (evt == BUTTON_EVT_INFO) { + /* Only used for console command for debug */ + CPRINTS("pwrbtn: pwr = %d, state = %d, level = %d", + dock_state, state, button_level); + continue; + } + + switch (state) { + case BUTTON_RELEASE: + /* + * Default wait state: Only need to check if the button + * is pressed and start the short press timer. + */ + if (evt & BUTTON_EVT_CHANGE && + button_level == BUTTON_PRESSED_LEVEL) { + state = BUTTON_PRESS; + timer_us = (POWER_BUTTON_SHORT_USEC - + POWER_BUTTON_DEBOUNCE_USEC); + } + break; + case BUTTON_PRESS: + /* + * Validate short press by ensuring that button is still + * pressed after short press timer expires. + */ + if (evt & BUTTON_EVT_CHANGE && + button_level == BUTTON_RELEASED_LEVEL) { + state = BUTTON_RELEASE; + } else { + /* Start long press timer */ + timer_us = POWER_BUTTON_LONG_USEC - + POWER_BUTTON_SHORT_USEC; + /* + * If dock is currently off, then change to the + * power on state. If dock is already on, then + * advance to short press state. + */ + if (dock_state == POWER_OFF) { + baseboard_power_on(); + state = BUTTON_PRESS_POWER_ON; + } else { + state = BUTTON_PRESS_SHORT; + } + } + break; + case BUTTON_PRESS_POWER_ON: + /* + * Short press recognized and dock was just powered + * on. If button is no longer pressed, then just return + * to the default state. Else, button is still pressed + * after long press timer has expired. + */ + if (evt & BUTTON_EVT_CHANGE && + button_level == BUTTON_RELEASED_LEVEL) { + state = BUTTON_RELEASE; + } else { + state = BUTTON_PRESS_LONG; + baseboard_toggle_mf(); + } + break; + case BUTTON_PRESS_SHORT: + /* + * Short press was recognized and dock power state was + * already on. If button is now released, then turn dock + * off. + */ + if (evt & BUTTON_EVT_CHANGE && + button_level == BUTTON_RELEASED_LEVEL) { + state = BUTTON_RELEASE; + baseboard_power_off(); + } else { + state = BUTTON_PRESS_LONG; + baseboard_toggle_mf(); + } + break; + case BUTTON_PRESS_LONG: + if (evt & BUTTON_EVT_CHANGE && + button_level == BUTTON_RELEASED_LEVEL) { + state = BUTTON_RELEASE; + } + break; + } + } +} + +static void baseboard_power_button_debounce(void) +{ + int level = gpio_get_level(GPIO_PWR_BTN); + + /* Sanity check, level should be same after debounce interval */ + if (level != button_level_pending) + return; + + button_level = level; + task_set_event(TASK_ID_POWER_BUTTON, BUTTON_EVT_CHANGE); +} +DECLARE_DEFERRED(baseboard_power_button_debounce); + +void baseboard_power_button_evt(int level) +{ + button_level_pending = level; + + hook_call_deferred(&baseboard_power_button_debounce_data, + POWER_BUTTON_DEBOUNCE_USEC); +} + +static int command_pwr_btn(int argc, const char **argv) +{ + if (argc == 1) { + task_set_event(TASK_ID_POWER_BUTTON, BUTTON_EVT_INFO); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[1], "on")) { + baseboard_power_on(); + } else if (!strcasecmp(argv[1], "off")) { + baseboard_power_off(); + } else if (!strcasecmp(argv[1], "mf")) { + baseboard_toggle_mf(); + } else { + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(pwr_btn, command_pwr_btn, "", + "Simulate Power Button Press"); + +#endif diff --git a/baseboard/honeybuns/baseboard.h b/baseboard/honeybuns/baseboard.h index 0703ea0b33..a2dc18ccdb 100644 --- a/baseboard/honeybuns/baseboard.h +++ b/baseboard/honeybuns/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,14 +11,58 @@ /* EC Defines */ #define CONFIG_CRC8 -/* TODO Define FLASH_PSTATE_LOCKED prior to building MP FW. */ -#undef CONFIG_FLASH_PSTATE_LOCKED +/* Flash Lyaout */ +/* + * Flash layout: we redefine the sections offsets and sizes as we will use + * RO/RW regions of different sizes. + */ +#undef _IMAGE_SIZE +#undef CONFIG_ROLLBACK_OFF +#undef CONFIG_ROLLBACK_SIZE +#undef CONFIG_FLASH_PSTATE +#undef CONFIG_FW_PSTATE_SIZE +#undef CONFIG_FW_PSTATE_OFF +#undef CONFIG_SHAREDLIB_SIZE +#undef CONFIG_RO_MEM_OFF +#undef CONFIG_RO_STORAGE_OFF +#undef CONFIG_RO_SIZE +#undef CONFIG_RW_MEM_OFF +#undef CONFIG_RW_STORAGE_OFF +#undef CONFIG_RW_SIZE +#undef CONFIG_EC_PROTECTED_STORAGE_OFF +#undef CONFIG_EC_PROTECTED_STORAGE_SIZE +#undef CONFIG_EC_WRITABLE_STORAGE_OFF +#undef CONFIG_EC_WRITABLE_STORAGE_SIZE +#undef CONFIG_WP_STORAGE_OFF +#undef CONFIG_WP_STORAGE_SIZE + +#define CONFIG_FLASH_PSTATE +/* Do not use a dedicated PSTATE bank */ +#undef CONFIG_FLASH_PSTATE_BANK + +#define CONFIG_SHAREDLIB_SIZE 0 + +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (64 * 1024) + +#define CONFIG_RW_MEM_OFF (CONFIG_RO_SIZE + CONFIG_RO_MEM_OFF) +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) + +#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE + +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* 48 MHz SYSCLK clock frequency */ #define CPU_CLOCK 48000000 -#define CONFIG_STM_HWTIMER32 #define TIM_CLOCK32 2 -#define TIM_CLOCK_MSB 3 +#define TIM_CLOCK_MSB 3 #define TIM_CLOCK_LSB 15 #define TIM_WATCHDOG 7 @@ -35,23 +79,135 @@ #define CONFIG_UART_TX_DMA_PH DMAMUX_REQ_USART3_TX /* CBI Configs */ -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_CROS_BOARD_INFO +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_CBI_EEPROM #define CONFIG_BOARD_VERSION_CBI #define CONFIG_CMD_CBI +#define CONFIG_EEPROM_CBI_WP +#define CONFIG_BYPASS_CBI_EEPROM_WP_CHECK +#define GPIO_EC_CBI_WP GPIO_EC_FLASH_WP_ODL +#define CBI_FW_MF_MASK BIT(0) +#define CBI_FW_MF_PREFERENCE(val) (val & (CBI_FW_MF_MASK)) +/* USB Configuration */ +#define CONFIG_USB +#define CONFIG_STREAM_USB +#define CONFIG_USB_UPDATE +#define CONFIG_USB_SERIALNO +#define DEFAULT_SERIALNO "Uninitialized" +#define CONFIG_MAC_ADDR +#define DEFAULT_MAC_ADDR "Uninitialized" +#define CONFIG_USB_MS_EXTENDED_COMPAT_ID_DESCRIPTOR + +/* USB endpoint indexes (use define rather than enum to expand them) */ +#define USB_EP_CONTROL 0 +#define USB_EP_UPDATE 1 +#define USB_EP_COUNT 2 + +#define USB_IFACE_UPDATE 0 +#define USB_IFACE_COUNT 1 + +#ifndef __ASSEMBLER__ +/* USB string indexes */ +enum usb_strings { + USB_STR_DESC = 0, + USB_STR_VENDOR, + USB_STR_PRODUCT, + USB_STR_SERIALNO, + USB_STR_VERSION, + USB_STR_UPDATE_NAME, + USB_STR_COUNT +}; +#endif + +/* RW Specific Config Options */ +#ifdef SECTION_IS_RW +/* No AP on any honeybuns variants */ +#undef CONFIG_USB_PD_HOST_CMD /* USB Type C and USB PD defines */ +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_CUSTOM_PDO +#define CONFIG_USB_PD_ALT_MODE_UFP_DP +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_REV30 +/* + * Source current limit pull options. Honeybuns always wants TYPEC_RP_3A0 + * current limits for the usbc host port (C0). For port C1, some variants are + * designed with a 1.5A current limit. This variation is handled via + * BOARD_C1_1A5_LIMIT which would be set in a variant's board.h file. + * + * CONFIG_USB_PD_3A_PORTS should be left at 0 as this will disable DPM from + * doing any dynamic current limit management. + */ +#undef CONFIG_USB_PD_PULLUP +#define CONFIG_USB_PD_PULLUP TYPEC_RP_3A0 +#define CONFIG_USB_PD_3A_PORTS 0 +#define CONFIG_USB_PD_TCPM_MUX +#define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USB_PD_TCPM_STM32GX +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USBC_PPC_VCONN +#define CONFIG_USBC_PPC_DEDICATED_INT +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP +#define CONFIG_USBC_SS_MUX + +#define CONFIG_HAS_TASK_PD_INT +#define CONFIG_STM32G4_UCPD_DEBUG +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_CMD_TCPC_DUMP + +#define CONFIG_MP4245 +#define USB_HUB_OCP_RESET_MSEC (10 * MSEC) + +#else /* RO Specific Config Options */ + +/* RWSIG Config Options */ +/* Sign and switch to RW partition on boot. */ +#define CONFIG_RWSIG +#define CONFIG_RSA +#define CONFIG_SHA256_UNROLLED +#undef CONFIG_RWSIG_JUMP_TIMEOUT +#define CONFIG_RWSIG_JUMP_TIMEOUT (7000 * MSEC) + +/* Don't build PD console command for RO */ +#undef CONFIG_CMD_PD +#undef CONFIG_USB_PD_CONSOLE_CMD +#undef CONFIG_USB_PD_HOST_CMD +/* Make sure these files aren't built in RO */ +#undef CONFIG_USB_PRL_SM +#undef CONFIG_USB_TYPEC_SM +#undef CONFIG_USB_PE_SM + +#endif /* SECTION_IS_RW */ -/* BC 1.2 */ +#define CONFIG_RWSIG_TYPE_RWSIG +#define CONFIG_RSA_KEY_SIZE 3072 +#define CONFIG_RSA_EXPONENT_3 +#define CONFIG_SHA256 + +/* Define typical operating power and max power. */ +#define PD_MAX_VOLTAGE_MV 5000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_POWER_MW 15000 +#define PD_OPERATING_POWER_MW 15000 + +/* TODO(b:147314141): Verify these timings */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* I2C Bus Configuration */ #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define I2C_PORT_USBC 0 -#define I2C_PORT_MST 1 -#define I2C_PORT_EEPROM 2 - +#define CONFIG_I2C_CONTROLLER /* * Macros for GPIO signals used in common code that don't match the @@ -59,8 +215,8 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_WP_L GPIO_EC_WP_L #ifndef __ASSEMBLER__ @@ -69,13 +225,103 @@ struct power_seq { enum gpio_signal signal; /* power/reset gpio_signal to control */ - int level; /* level to set in power sequence */ - unsigned int delay_ms; /* delay (in msec) after setting gpio_signal */ + int level; /* level to set in power sequence */ + unsigned int delay_ms; /* delay (in msec) after setting gpio_signal */ }; +enum mf_preference { + MF_OFF = 0, + MF_ON, +}; + +/* + * This is required as adc_channel is included in adc.h which ends up being + * included when TCPMv2 functions are included + */ +enum adc_channel { ADC_CH_COUNT }; + extern const struct power_seq board_power_seq[]; extern const size_t board_power_seq_count; +void baseboard_power_button_evt(int level); + +/* + * Configure the host port to present Rd on both CC lines. This function is + * called in RO which does not otherwise have usbc/usb-pd support. + * + * @return true - initialized. false - not. + */ +int baseboard_usbc_init(int port); + +/* + * Get a board's desired multi-function (MF) prefernce. This allows for board + * specific policy. + * + * @return 1 if multi function (DP + USB3) is preferred, 0 otherwise + */ +int dock_get_mf_preference(void); + +/* + * Initialize and configure PPC used for USB3 only port + * + * @return EC success if PPC initialization is successful + */ +int baseboard_config_usbc_usb3_ppc(void); + +/* + * Called from interrupt handler for PS8803 attached.src gpio. This gpio signal + * will be set high by the PS8803 when it's in the attached.src state and low + * otherwise. For boards wich have a PPC on this port, this signal is used to + * enable/disable VBUS in the PPC. + */ +void baseboard_usb3_check_state(void); + +/* + * Set MST_LANE_CONTROL gpio to match the DP pin configuration selected + * by the host in the DP Configure SVDM message. + * + * @param dock_mf 1 -> 2 lanes DP, 0 -> 4 lanes DP + */ +void baseboard_set_mst_lane_control(int dock_mf); + +/* + * Control enable/disable for interrupts used for usb3 only usbc port. + * + * @param enable -> 1 for enable, 0 for disable + */ +void baseboard_usbc_usb3_enable_interrupts(int enable); + +/* + * Called from interrupt handler for PPC used on usb3 only port. + * + */ +void baseboard_usbc_usb3_irq(void); + +/** + * Determine if VBUS is present or not. + * + * @param port: The Type-C port number. + * @return 1 if VBUS is present, 0 if not. + */ +int c1_ps8805_is_vbus_present(int port); + +/** + * Is the port sourcing Vbus? + * + * @param port: The Type-C port number. + * @return 1 if sourcing Vbus, 0 if not. + */ +int c1_ps8805_is_sourcing_vbus(int port); + +/** + * Turn on/off VBUS for port C1 + * + * @param port: The Type-C port number. + * @param enable: 1: Turn on VBUS, 0: turn off VBUS. + * @return EC_SUCCESS on success, error otherwise. + */ +int c1_ps8805_vbus_source_enable(int port, int enable); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/honeybuns/build.mk b/baseboard/honeybuns/build.mk index 2a572df114..57e93b0587 100644 --- a/baseboard/honeybuns/build.mk +++ b/baseboard/honeybuns/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -7,3 +7,5 @@ # baseboard-y=baseboard.o +baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +baseboard-y+=usbc_support.o diff --git a/baseboard/honeybuns/usb_pd_policy.c b/baseboard/honeybuns/usb_pd_policy.c new file mode 100644 index 0000000000..f2e13d9ed9 --- /dev/null +++ b/baseboard/honeybuns/usb_pd_policy.c @@ -0,0 +1,618 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chip/stm32/ucpd-stm32gx.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/mp4245.h" +#include "driver/tcpm/tcpci.h" +#include "gpio.h" +#include "hooks.h" +#include "task.h" +#include "timer.h" +#include "usb_common.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_dp_ufp.h" +#include "usb_tc_sm.h" +#include "usbc_ppc.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +#define MP4245_VOLTAGE_WINDOW BIT(2) +#define MP4245_VOLTAGE_WINDOW_MASK (MP4245_VOLTAGE_WINDOW - 1) + +#define PDO_FIXED_FLAGS \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_COMM_CAP | \ + PDO_FIXED_UNCONSTRAINED) + +/* Voltage indexes for the PDOs */ +enum volt_idx { + PDO_IDX_5V = 0, + PDO_IDX_9V = 1, + PDO_IDX_15V = 2, + PDO_IDX_20V = 3, + PDO_IDX_COUNT +}; + +/* PDOs */ +const uint32_t pd_src_host_pdo[] = { + [PDO_IDX_5V] = PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), + [PDO_IDX_9V] = PDO_FIXED(9000, 3000, 0), + [PDO_IDX_15V] = PDO_FIXED(15000, 3000, 0), + [PDO_IDX_20V] = PDO_FIXED(20000, 3000, 0), +}; +BUILD_ASSERT(ARRAY_SIZE(pd_src_host_pdo) == PDO_IDX_COUNT); + +#ifdef BOARD_C1_1A5_LIMIT +const uint32_t pd_src_display_pdo[] = { + [PDO_IDX_5V] = PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), +}; +#else +const uint32_t pd_src_display_pdo[] = { + [PDO_IDX_5V] = PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +#endif + +const uint32_t pd_snk_pdo[] = { + [PDO_IDX_5V] = PDO_FIXED(5000, 0, PDO_FIXED_FLAGS), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); + +static int src_host_pdo_cnt_override; + +#define PD_DR_SWAP_ATTEMPT_MAX 3 +static int pd_dr_swap_attempt_count[CONFIG_USB_PD_PORT_MAX_COUNT]; + +static int command_hostpdo(int argc, const char **argv) +{ + char *e; + int limit; + + if (argc >= 2) { + limit = strtoi(argv[1], &e, 10); + if ((limit < 0) || (limit > PDO_IDX_COUNT)) + return EC_ERROR_PARAM1; + + src_host_pdo_cnt_override = limit; + } + ccprintf("src host pdo override = %d\n", src_host_pdo_cnt_override); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(hostpdo, command_hostpdo, "<0|1|2|3|4>", + "Limit number of PDOs for C0"); + +int dpm_get_source_pdo(const uint32_t **src_pdo, const int port) +{ + int pdo_cnt = 0; + + if (port == USB_PD_PORT_HOST) { + *src_pdo = pd_src_host_pdo; + pdo_cnt = ARRAY_SIZE(pd_src_host_pdo); + /* + * This override is only active via a console command. Only used + * for debug to limit the level of VBUS offered to port partner + * if desired. The console command only allows 0 -> + * PDO_IDX_COUNT for this value. + */ + if (src_host_pdo_cnt_override) + pdo_cnt = src_host_pdo_cnt_override; + } else { + *src_pdo = pd_src_display_pdo; + pdo_cnt = ARRAY_SIZE(pd_src_display_pdo); + } + + return pdo_cnt; +} + +/* + * Default Port Discovery DR Swap Policy. + * + * 1) If port == 0 and port data role is DFP, transition to pe_drs_send_swap + * 2) If port == 1 and port data role is UFP, transition to pe_drs_send_swap + */ +__override bool port_discovery_dr_swap_policy(int port, enum pd_data_role dr, + bool dr_swap_flag) +{ + /* + * Port0: test if role is DFP + * Port1: test if role is UFP + */ + enum pd_data_role role_test = (port == USB_PD_PORT_HOST) ? PD_ROLE_DFP : + PD_ROLE_UFP; + + /* + * Request data role swap if not in the port's desired data role and if + * the attempt count is less than the max allowed. This function is + * called for each PE run once in a PD contract. If the port partner + * rejects data role swap requests (eg compliance tester), want to limit + * how many DR swap requests are attempted. + */ + if (dr == role_test && + (pd_dr_swap_attempt_count[port]++ < PD_DR_SWAP_ATTEMPT_MAX)) + return true; + + /* Do not perform a DR swap */ + return false; +} + +/* + * Default Port Discovery VCONN Swap Policy. + * + * 1) No need to Vconn swap. This board does not require any cable information. + */ +__override bool port_discovery_vconn_swap_policy(int port, bool vconn_swap_flag) +{ + return false; +} + +int pd_check_vconn_swap(int port) +{ + /*TODO: Dock is the Vconn source */ + return 1; +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + if (port < 0 || port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return; + + if (IS_ENABLED(BOARD_C1_NO_PPC) && port) { + prev_en = c1_ps8805_is_sourcing_vbus(port); + /* Disable VBUS via PPC. */ + c1_ps8805_vbus_source_enable(port, 0); + } else { + prev_en = ppc_is_sourcing_vbus(port); + /* Disable VBUS via PPC. */ + ppc_vbus_source_enable(port, 0); + } + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + if (port == USB_PD_PORT_HOST) { + int mv; + int ma; + int unused_mv; + + /* + * Because VBUS on C0 is turned on/off via the PPC, the + * voltage from the mp4245 does not need to be turned off, or + * set to 0V. Instead, reset VBUS voltage to default value + * (fixed 5V SRC_CAP) so VBUS is ready to be applied at the next + * attached.src condition. + */ + pd_extract_pdo_power(pd_src_host_pdo[0], &ma, &mv, &unused_mv); + mp4245_set_voltage_out(mv); + /* Ensure voltage is back to 5V */ + pd_transition_voltage(1); + } +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* + * Note: For host port, the mp4245 output voltage is set for 5V by + * default and each time VBUS is turned off. VOUT from the mp4245 is + * left enabled as there is a switch (either PPC or discrete) to turn + * VBUS on/off on the wire. + */ + if (IS_ENABLED(BOARD_C1_NO_PPC) && port) + rv = c1_ps8805_vbus_source_enable(port, 1); + else + rv = ppc_vbus_source_enable(port, 1); + + if (rv) + return rv; + + return EC_SUCCESS; +} + +void pd_transition_voltage(int idx) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + int mv; + int target_mv; + int mv_average = 0; + int ma; + int vbus_hi; + int vbus_lo; + int i; + int mv_buffer[MP4245_VOLTAGE_WINDOW]; + + /* Only C0 can provide more than 5V */ + if (port != USB_PD_PORT_HOST) + return; + + /* + * Set the VBUS output voltage and current limit to the values specified + * by the PDO requested by sink. Note that USB PD uses idx = 1 for 1st + * PDO of SRC_CAP which must always be 5V fixed supply. + */ + pd_extract_pdo_power(pd_src_host_pdo[idx - 1], &ma, &target_mv, &mv); + + /* Initialize sample delay buffer */ + for (i = 0; i < MP4245_VOLTAGE_WINDOW; i++) + mv_buffer[i] = 0; + + /* Set VBUS level to value specified in the requested PDO */ + mp4245_set_voltage_out(target_mv); + /* Wait for vbus to be within ~5% of its target value */ + vbus_hi = target_mv + (target_mv >> 4); + vbus_lo = target_mv - (target_mv >> 4); + + for (i = 0; i < 20; i++) { + /* Read current sample */ + mv = 0; + mp3245_get_vbus(&mv, &ma); + /* Add new sample to cicrcular delay buffer */ + mv_buffer[i & MP4245_VOLTAGE_WINDOW_MASK] = mv; + /* + * Don't compute average until sample delay buffer is + * full. + */ + if (i >= (MP4245_VOLTAGE_WINDOW_MASK)) { + int sum = 0; + int j; + + /* Sum the voltage samples */ + for (j = 0; j < MP4245_VOLTAGE_WINDOW; j++) + sum += mv_buffer[j]; + /* Add rounding */ + sum += MP4245_VOLTAGE_WINDOW / 2; + mv_average = sum / MP4245_VOLTAGE_WINDOW; + /* + * Check if average is within the target + * voltage range. + */ + if ((mv_average >= vbus_lo) && + (mv_average <= vbus_hi)) { + CPRINTS("usbc[%d]: VBUS to %d mV in %d steps", + port, target_mv, i); + return; + } + } + + /* + * The voltage ramp from 5V to 20V requires ~30 + * msec. The max loop count and this sleep time gives plenty + * of time for this change. + */ + msleep(2); + } + + CPRINTS("usbc[%d]: Vbus transition timeout: target = %d, measure = %d", + port, target_mv, mv_average); +} + +int pd_snk_is_vbus_provided(int port) +{ + if (IS_ENABLED(BOARD_C1_NO_PPC) && port) + return c1_ps8805_is_vbus_present(port); + else + return ppc_is_vbus_present(port); +} + +__override bool pd_check_vbus_level(int port, enum vbus_level level) +{ + if (level == VBUS_PRESENT) + return pd_snk_is_vbus_provided(port); + else + return !pd_snk_is_vbus_provided(port); +} + +int board_vbus_source_enabled(int port) +{ + if (IS_ENABLED(BOARD_C1_NO_PPC) && port) + return c1_ps8805_is_sourcing_vbus(port); + else + return ppc_is_sourcing_vbus(port); +} + +void pd_set_input_current_limit(int port, uint32_t max_ma, + uint32_t supply_voltage) +{ +} + +int pd_check_data_swap(int port, enum pd_data_role data_role) +{ + int swap = 0; + + if (port == 0) + swap = (data_role == PD_ROLE_DFP); + else if (port == 1) + swap = (data_role == PD_ROLE_UFP); + + return swap; +} + +int pd_check_power_swap(int port) +{ + if (pd_get_power_role(port) == PD_ROLE_SINK) + return 1; + + return 0; +} + +#ifdef BOARD_C1_1A5_LIMIT +__override int typec_get_default_current_limit_rp(int port) +{ + int rp = TYPEC_RP_USB; + + if (port == USB_PD_PORT_HOST) + rp = TYPEC_RP_3A0; + else if (port == USB_PD_PORT_DP) + rp = TYPEC_RP_1A5; + + return rp; +} +#endif + +static void usb_tc_connect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* Clear data role swap attempt counter at each usbc attach */ + pd_dr_swap_attempt_count[port] = 0; + + /* + * The EC needs to indicate to the USB hub when the host port is + * attached so that the USB-EP can be properly enumerated. GPIO_BPWR_DET + * is used for this purpose. + */ + if (port == USB_PD_PORT_HOST) + gpio_set_level(GPIO_BPWR_DET, 1); +} +DECLARE_HOOK(HOOK_USB_PD_CONNECT, usb_tc_connect, HOOK_PRIO_DEFAULT); + +static void usb_tc_disconnect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* Only the host port disconnect is relevant */ + if (port == USB_PD_PORT_HOST) + gpio_set_level(GPIO_BPWR_DET, 0); +} +DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, usb_tc_disconnect, HOOK_PRIO_DEFAULT); + +__override bool pd_can_charge_from_device(int port, const int pdo_cnt, + const uint32_t *pdos) +{ + /* + * This function is called to determine if this port can be charged by + * the port partner. We always want to be a power role source, so always + * return false. + */ + + return false; +} + +static int vdm_is_dp_enabled(int port) +{ + mux_state_t mux_state = usb_mux_get(port); + + return !!(mux_state & USB_PD_MUX_DP_ENABLED); +} + +/* ----------------- Vendor Defined Messages ------------------ */ + +const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ + 1, /* data caps as USB device */ + IDH_PTYPE_HUB, /* UFP product type usbpd hub */ + 1, /* supports alt modes */ + USB_VID_GOOGLE); + +static const uint32_t vdo_idh_rev30 = VDO_IDH_REV30( + 0, /* Data caps as USB host */ + 1, /* Data caps as USB device */ + IDH_PTYPE_HUB, 1, /* Supports alt modes */ + IDH_PTYPE_DFP_UNDEFINED, USB_TYPEC_RECEPTACLE, USB_VID_GOOGLE); + +const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); + +static const uint32_t vdo_ufp1 = + VDO_UFP1((VDO_UFP1_CAPABILITY_USB20 | VDO_UFP1_CAPABILITY_USB32), + USB_TYPEC_RECEPTACLE, VDO_UFP1_ALT_MODE_RECONFIGURE, + USB_R30_SS_U32_U40_GEN2); + +static int svdm_response_identity(int port, uint32_t *payload) +{ + int vdo_count; + + /* Verify that SVID is PD SID */ + if (PD_VDO_VID(payload[0]) != USB_SID_PD) { + return 0; + } + + /* Cstat and Product VDOs don't depend on spec revision */ + payload[VDO_INDEX_CSTAT] = VDO_CSTAT(0); + payload[VDO_INDEX_PRODUCT] = vdo_product; + + if (pd_get_rev(port, TCPCI_MSG_SOP) == PD_REV30) { + /* PD Revision 3.0 */ + payload[VDO_INDEX_IDH] = vdo_idh_rev30; + payload[VDO_INDEX_PTYPE_UFP1_VDO] = vdo_ufp1; + vdo_count = VDO_INDEX_PTYPE_UFP1_VDO; + } else { + payload[VDO_INDEX_IDH] = vdo_idh; + vdo_count = VDO_INDEX_PRODUCT; + } + + /* Adjust VDO count for VDM header */ + return vdo_count + 1; +} + +static int svdm_response_svids(int port, uint32_t *payload) +{ + /* Verify that SVID is PD SID */ + if (PD_VDO_VID(payload[0]) != USB_SID_PD) { + return 0; + } + + payload[1] = USB_SID_DISPLAYPORT << 16; + /* number of data objects VDO header + 1 SVID for DP */ + return 2; +} + +#define OPOS_DP 1 + +const uint32_t vdo_dp_modes[1] = { + VDO_MODE_DP(/* Must support C and E. D is required for 2 lanes */ + MODE_DP_PIN_C | MODE_DP_PIN_D | MODE_DP_PIN_E, + 0, /* DFP pin + cfg + supported + */ + 0, /* usb2.0 signalling in AMode may be req */ + CABLE_RECEPTACLE, /* its a receptacle */ + MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ + MODE_DP_SNK) /* Its a sink only */ +}; + +static int svdm_response_modes(int port, uint32_t *payload) +{ + if (PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) { + memcpy(payload + 1, vdo_dp_modes, sizeof(vdo_dp_modes)); + return ARRAY_SIZE(vdo_dp_modes) + 1; + } else { + return 0; /* nak */ + } +} + +static int amode_dp_status(int port, uint32_t *payload) +{ + int opos = PD_VDO_OPOS(payload[0]); + int hpd = gpio_get_level(GPIO_DP_HPD); + int mf = dock_get_mf_preference(); + + if (opos != OPOS_DP) + return 0; /* nak */ + + payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + (hpd == 1), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + mf, /* MF pref */ + vdm_is_dp_enabled(port), 0, /* power low */ + 0x2); + return 2; +} + +static void svdm_configure_demux(int port, int enable, int mf) +{ + mux_state_t demux = usb_mux_get(port); + + if (enable) { + demux |= USB_PD_MUX_DP_ENABLED; + /* 4 lane mode if MF is not preferred */ + if (!mf) + demux &= ~USB_PD_MUX_USB_ENABLED; + /* + * Make sure the MST_LANE_CONTROL gpio is set to match the DP + * pin configuration selected by the host. Note that the mf + * passed into this function reflects the pin configuration + * selected by the host and not the user mf preference which is + * stored in bit 0 of CBI fw_config. + */ + baseboard_set_mst_lane_control(mf); + CPRINTS("DP[%d]: DFP-D selected pin config %s", port, + mf ? "D" : "C"); + } else { + demux &= ~USB_PD_MUX_DP_ENABLED; + demux |= USB_PD_MUX_USB_ENABLED; + } + + /* Configure demux for 2/4 lane DP and USB3 configuration */ + usb_mux_set(port, demux, USB_SWITCH_CONNECT, pd_get_polarity(port)); +} + +static int amode_dp_config(int port, uint32_t *payload) +{ + uint32_t dp_config = payload[1]; + int mf; + + /* + * Check pin assignment selected by DFP_D to determine if 2 lane or 4 + * lane DP ALT-MODe is required. (note PIN_C is for 4 lane and PIN_D is + * for 2 lane mode). + */ + mf = ((dp_config >> 8) & 0xff) == MODE_DP_PIN_D ? 1 : 0; + /* Configure demux for DP mode */ + svdm_configure_demux(port, 1, mf); + /* Notify hpd->pd conv that a DP_CONFIG message has been received */ + pd_ufp_enable_hpd_send(port); + + return 1; +} + +static int svdm_enter_mode(int port, uint32_t *payload) +{ + int rv = 0; /* will generate a NAK */ + + /* SID & mode request is valid */ + if ((PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) && + (PD_VDO_OPOS(payload[0]) == OPOS_DP)) { + /* Store valid object position to indicate mode is active */ + pd_ufp_set_dp_opos(port, OPOS_DP); + + /* Entering ALT-DP mode, enable DP connection in demux */ + usb_pd_hpd_converter_enable(1); + + /* ACK response has 1 VDO */ + rv = 1; + } + + CPRINTS("svdm_enter[%d]: svid = %x, ret = %d", port, + PD_VDO_VID(payload[0]), rv); + + return rv; +} + +static int svdm_exit_mode(int port, uint32_t *payload) +{ + int opos = pd_ufp_get_dp_opos(port); + + if ((PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) && + (opos == OPOS_DP)) { + /* Clear mode active object position */ + pd_ufp_set_dp_opos(port, 0); + /* Configure demux to disable DP mode */ + svdm_configure_demux(port, 0, 0); + usb_pd_hpd_converter_enable(0); + + return 1; + } else { + CPRINTF("Unknown exit mode req:0x%08x\n", payload[0]); + return 0; + } +} + +static struct amode_fx dp_fx = { + .status = &amode_dp_status, + .config = &amode_dp_config, +}; + +const struct svdm_response svdm_rsp = { + .identity = &svdm_response_identity, + .svids = &svdm_response_svids, + .modes = &svdm_response_modes, + .enter_mode = &svdm_enter_mode, + .amode = &dp_fx, + .exit_mode = &svdm_exit_mode, +}; + +int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) +{ + /* We don't support, so ignore this message */ + return 0; +} diff --git a/baseboard/honeybuns/usbc_support.c b/baseboard/honeybuns/usbc_support.c new file mode 100644 index 0000000000..9c94f3f0ba --- /dev/null +++ b/baseboard/honeybuns/usbc_support.c @@ -0,0 +1,474 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* USBC functions for RO */ + +#include "common.h" +#include "console.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "registers.h" +#include "sn5s330.h" +#include "system.h" +#include "timer.h" +#include "ucpd-stm32gx.h" +#include "usb_charge.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +enum usbc_states { + UNATTACHED_SNK, + ATTACH_WAIT_SNK, + ATTACHED_SNK, +}; + +/* Variables used to manage the simple usbc state machine */ +static int usbc_port; +static int usbc_state; +static int usbc_vbus; +static enum tcpc_cc_voltage_status cc1_v; +static enum tcpc_cc_voltage_status cc2_v; + +__maybe_unused static __const_data const char *const usbc_state_names[] = { + [UNATTACHED_SNK] = "Unattached.SNK", + [ATTACH_WAIT_SNK] = "AttachWait.SNK", + [ATTACHED_SNK] = "Attached.SNK", +}; + +static int read_reg(uint8_t port, int reg, int *regval) +{ + return i2c_read8(ppc_chips[port].i2c_port, + ppc_chips[port].i2c_addr_flags, reg, regval); +} + +static int write_reg(uint8_t port, int reg, int regval) +{ + return i2c_write8(ppc_chips[port].i2c_port, + ppc_chips[port].i2c_addr_flags, reg, regval); +} + +static int baseboard_ppc_enable_sink_path(int port) +{ + int regval; + int status; + int retries; + + /* + * It seems that sometimes setting the FUNC_SET1 register fails + * initially. Therefore, we'll retry a couple of times. + */ + retries = 0; + do { + status = write_reg(port, SN5S330_FUNC_SET1, SN5S330_ILIM_3_06); + if (status) { + retries++; + msleep(1); + } else { + break; + } + } while (retries < 10); + + /* Turn off dead battery resistors, turn on CC FETs */ + status = read_reg(port, SN5S330_FUNC_SET4, ®val); + if (!status) { + regval |= SN5S330_CC_EN; + status = write_reg(port, SN5S330_FUNC_SET4, regval); + } + if (status) { + return status; + } + + /* Enable sink path via PP2 */ + status = read_reg(port, SN5S330_FUNC_SET3, ®val); + if (!status) { + regval &= ~SN5S330_PP1_EN; + regval |= SN5S330_PP2_EN; + status = write_reg(port, SN5S330_FUNC_SET3, regval); + } + if (status) { + return status; + } + + return EC_SUCCESS; +} + +static void baseboard_ucpd_apply_rd(int port) +{ + uint32_t cfgr1_reg; + uint32_t moder_reg; + uint32_t cr; + + /* Ensure that clock to UCPD is enabled */ + STM32_RCC_APB1ENR2 |= STM32_RCC_APB1ENR2_UPCD1EN; + + /* Make sure CC1/CC2 pins PB4/PB6 are set for analog mode */ + moder_reg = STM32_GPIO_MODER(GPIO_B); + moder_reg |= 0x3300; + STM32_GPIO_MODER(GPIO_B) = moder_reg; + /* + * CFGR1 must be written when UCPD peripheral is disabled. Note that + * disabling ucpd causes the peripheral to quit any ongoing activity and + * sets all ucpd registers back their default values. + */ + + cfgr1_reg = STM32_UCPD_CFGR1_PSC_CLK_VAL(UCPD_PSC_DIV - 1) | + STM32_UCPD_CFGR1_TRANSWIN_VAL(UCPD_TRANSWIN_CNT - 1) | + STM32_UCPD_CFGR1_IFRGAP_VAL(UCPD_IFRGAP_CNT - 1) | + STM32_UCPD_CFGR1_HBITCLKD_VAL(UCPD_HBIT_DIV - 1); + STM32_UCPD_CFGR1(port) = cfgr1_reg; + + /* Enable ucpd */ + STM32_UCPD_CFGR1(port) |= STM32_UCPD_CFGR1_UCPDEN; + + /* Apply Rd to both CC lines */ + cr = STM32_UCPD_CR(port); + cr |= STM32_UCPD_CR_ANAMODE | STM32_UCPD_CR_CCENABLE_MASK; + STM32_UCPD_CR(port) = cr; + + /* + * After exiting reset, stm32gx will have dead battery mode enabled by + * default which connects Rd to CC1/CC2. This should be disabled when EC + * is powered up. + */ + STM32_PWR_CR3 |= STM32_PWR_CR3_UCPD1_DBDIS; +} + +static void baseboard_ucpd_get_cc(int port, enum tcpc_cc_voltage_status *cc1, + enum tcpc_cc_voltage_status *cc2) +{ + int vstate_cc1; + int vstate_cc2; + int anamode; + uint32_t sr; + + /* + * cc_voltage_status is determined from vstate_cc bit field in the + * status register. The meaning of the value vstate_cc depends on + * current value of ANAMODE (src/snk). + * + * vstate_cc maps directly to cc_state from tcpci spec when ANAMODE = 1, + * but needs to be modified slightly for case ANAMODE = 0. + * + * If presenting Rp (source), then need to to a circular shift of + * vstate_ccx value: + * vstate_cc | cc_state + * ------------------ + * 0 -> 1 + * 1 -> 2 + * 2 -> 0 + */ + + /* Get vstate_ccx values and power role */ + sr = STM32_UCPD_SR(port); + /* Get Rp or Rd active */ + anamode = !!(STM32_UCPD_CR(port) & STM32_UCPD_CR_ANAMODE); + vstate_cc1 = (sr & STM32_UCPD_SR_VSTATE_CC1_MASK) >> + STM32_UCPD_SR_VSTATE_CC1_SHIFT; + vstate_cc2 = (sr & STM32_UCPD_SR_VSTATE_CC2_MASK) >> + STM32_UCPD_SR_VSTATE_CC2_SHIFT; + + /* Do circular shift if port == source */ + if (anamode) { + if (vstate_cc1 != STM32_UCPD_SR_VSTATE_RA) + vstate_cc1 += 4; + if (vstate_cc2 != STM32_UCPD_SR_VSTATE_RA) + vstate_cc2 += 4; + } else { + if (vstate_cc1 != STM32_UCPD_SR_VSTATE_OPEN) + vstate_cc1 = (vstate_cc1 + 1) % 3; + if (vstate_cc2 != STM32_UCPD_SR_VSTATE_OPEN) + vstate_cc2 = (vstate_cc2 + 1) % 3; + } + + *cc1 = vstate_cc1; + *cc2 = vstate_cc2; +} + +static int baseboard_rp_is_present(enum tcpc_cc_voltage_status cc1, + enum tcpc_cc_voltage_status cc2) +{ + return (cc1 >= TYPEC_CC_VOLT_RP_DEF || cc2 >= TYPEC_CC_VOLT_RP_DEF); +} + +static void baseboard_usbc_check_connect(void); +DECLARE_DEFERRED(baseboard_usbc_check_connect); + +static void baseboard_usbc_check_connect(void) +{ + enum tcpc_cc_voltage_status cc1; + enum tcpc_cc_voltage_status cc2; + int ppc_reg; + enum usbc_states enter_state = usbc_state; + + /* + * In RO, the only usbc related requirement is to enable the stm32g4 + * USB-EP to be enumerated by the host attached to C0. To prevent D+ + * being pulled high prior to VBUS presence, the EC uses GPIO_BPWR_DET + * to signal the USB hub that VBUS is present. Therefore, we need a + * simple usbc state machine to detect an attach (Rp and VBUS) event so + * this GPIO signal is properly controlled in RO. + * + * Note that RO only runs until the RWSIG timer expires and jumps to RW, + * and in RW, the full usb-pd stack is initialized and run. + */ + + /* Get current CC voltage levels */ + baseboard_ucpd_get_cc(usbc_port, &cc1, &cc2); + /* Update VBUS state */ + if (!read_reg(usbc_port, SN5S330_INT_STATUS_REG3, &ppc_reg)) + usbc_vbus = ppc_reg & SN5S330_VBUS_GOOD; + + switch (usbc_state) { + case UNATTACHED_SNK: + /* + * Require either CC1 or CC2 to have a valid Rp CC voltage level + * to advance to ATTACH_WAIT_SNK. + */ + if (baseboard_rp_is_present(cc1, cc2)) + usbc_state = ATTACH_WAIT_SNK; + break; + case ATTACH_WAIT_SNK: + /* + * This state handles debounce by ensuring the CC voltages are + * the same between two state machine iterations. If this + * condition is met, and VBUS is present, then advance to + * ATTACHED_SNK and set GPIO_BPWR_DET. + * + * If Rp voltage is no longer detected, then return to + * UNATTACHED_SNK. + */ + if (usbc_vbus && cc1 == cc1_v && cc2 == cc2_v) { + usbc_state = ATTACHED_SNK; + gpio_set_level(GPIO_BPWR_DET, 1); + } else if (!baseboard_rp_is_present(cc1, cc2)) { + usbc_state = UNATTACHED_SNK; + } + break; + case ATTACHED_SNK: + /* + * In this state, only checking for VBUS going away to indicate + * a detach event and inform the USB hub via GPIO_BPWR_DET. + */ + if (!usbc_vbus) { + usbc_state = UNATTACHED_SNK; + gpio_set_level(GPIO_BPWR_DET, 0); + } + break; + } + + /* Save CC voltage for debounce check */ + cc1_v = cc1; + cc2_v = cc2; + + if (enter_state != usbc_state) + CPRINTS("%s: cc1 = %d, cc2 = %d vbus = %d", + usbc_state_names[usbc_state], cc1, cc2, usbc_vbus); + + hook_call_deferred(&baseboard_usbc_check_connect_data, + PD_T_TRY_CC_DEBOUNCE); +} + +int baseboard_usbc_init(int port) +{ + int rv; + + /* Initialize ucpd and apply Rd to CC lines */ + baseboard_ucpd_apply_rd(port); + /* Initialize ppc to enable sink path */ + rv = baseboard_ppc_enable_sink_path(port); + if (rv) + CPRINTS("ppc init failed!"); + /* Save host port value */ + usbc_port = port; + /* Start RO usbc attach state machine */ + gpio_set_level(GPIO_BPWR_DET, 0); + /* Start simple usbc state machine */ + baseboard_usbc_check_connect(); + + return rv; +} + +#ifdef SECTION_IS_RW +int c1_ps8805_is_vbus_present(int port) +{ + int vbus; + + vbus = tcpm_check_vbus_level(port, VBUS_PRESENT); + + return vbus; +} + +int c1_ps8805_is_sourcing_vbus(int port) +{ + int rv; + int level; + + rv = ps8805_gpio_get_level(port, PS8805_GPIO_1, &level); + if (rv) + return 0; + + return level; +} + +int c1_ps8805_vbus_source_enable(int port, int enable) +{ + return ps8805_gpio_set_level(port, PS8805_GPIO_1, enable); +} + +__override bool usb_ufp_check_usb3_enable(int port) +{ + /* USB3.1 mux should be enabled based on UFP data role */ + return port == USB_PD_PORT_HOST; +} + +#ifdef GPIO_USBC_UF_ATTACHED_SRC +static int ppc_ocp_count; + +static void baseboard_usb3_manage_vbus(void) +{ + int level = gpio_get_level(GPIO_USBC_UF_ATTACHED_SRC); + + /* + * GPIO_USBC_UF_MUX_VBUS_EN is an output from the PS8803 which tracks if + * C2 is attached. When it's attached, this signal will be high. Use + * this level to control PPC VBUS on/off. + */ + ppc_vbus_source_enable(USB_PD_PORT_USB3, level); + CPRINTS("C2: State = %s", level ? "Attached.SRC " : "Unattached.SRC"); + + /* Reset OCP event counter for detach */ + if (!level) { + ppc_ocp_count = 0; + +#ifdef GPIO_USB_HUB_OCP_NOTIFY + /* + * In the case of an OCP event on this port, the usb hub should + * be notified via a GPIO signal. Following, an OCP, the + * attached.src state for the usb3 only port is checked again. + * If it's attached, then make sure the OCP notify signal is + * reset. + */ + gpio_set_level(GPIO_USB_HUB_OCP_NOTIFY, 1); +#endif + } +} +DECLARE_DEFERRED(baseboard_usb3_manage_vbus); + +void baseboard_usb3_check_state(void) +{ + hook_call_deferred(&baseboard_usb3_manage_vbus_data, 0); +} + +void baseboard_usbc_usb3_enable_interrupts(int enable) +{ + if (enable) { + /* Enable VBUS control interrupt for C2 */ + gpio_enable_interrupt(GPIO_USBC_UF_ATTACHED_SRC); + /* Enable PPC interrupt */ + gpio_enable_interrupt(GPIO_USBC_UF_PPC_INT_ODL); + } else { + /* Disable VBUS control interrupt for C2 */ + gpio_disable_interrupt(GPIO_USBC_UF_ATTACHED_SRC); + /* Disable PPC interrupt */ + gpio_disable_interrupt(GPIO_USBC_UF_PPC_INT_ODL); + } +} + +int baseboard_config_usbc_usb3_ppc(void) +{ + int rv; + + /* + * This port is not usb-pd capable, but there is a ppc which must be + * initialized, and keep the VBUS switch enabled. + */ + rv = ppc_init(USB_PD_PORT_USB3); + if (rv) + return rv; + + /* Need to set current limit to 3A to match advertised value */ + ppc_set_vbus_source_current_limit(USB_PD_PORT_USB3, TYPEC_RP_3A0); + /* Reset OCP event counter */ + ppc_ocp_count = 0; + + /* Check state at init time */ + baseboard_usb3_manage_vbus(); + + /* Enable attached.src and PPC interrupts */ + baseboard_usbc_usb3_enable_interrupts(1); + + return EC_SUCCESS; +} + +static void baseboard_usbc_usb3_handle_interrupt(void) +{ + int port = USB_PD_PORT_USB3; + + /* + * SN5S330's /INT pin is level, so process interrupts until it + * deasserts if the chip has a dedicated interrupt pin. + */ + while (gpio_get_level(GPIO_USBC_UF_PPC_INT_ODL) == 0) { + int rise = 0; + int fall = 0; + + read_reg(port, SN5S330_INT_TRIP_RISE_REG1, &rise); + read_reg(port, SN5S330_INT_TRIP_FALL_REG1, &fall); + + /* Notify the system about the overcurrent event. */ + if (rise & SN5S330_ILIM_PP1_MASK) { + CPRINTS("usb3_ppc: VBUS OC!"); + gpio_set_level(GPIO_USB_HUB_OCP_NOTIFY, 0); + if (++ppc_ocp_count < 5) + hook_call_deferred( + &baseboard_usb3_manage_vbus_data, + USB_HUB_OCP_RESET_MSEC); + else + CPRINTS("usb3_ppc: VBUS OC limit reached!"); + } + + /* Clear the interrupt sources. */ + write_reg(port, SN5S330_INT_TRIP_RISE_REG1, rise); + write_reg(port, SN5S330_INT_TRIP_FALL_REG1, fall); + + read_reg(port, SN5S330_INT_TRIP_RISE_REG2, &rise); + read_reg(port, SN5S330_INT_TRIP_FALL_REG2, &fall); + + /* + * VCONN may be latched off due to an overcurrent. Indicate + * when the VCONN overcurrent happens. + */ + if (rise & SN5S330_VCONN_ILIM) + CPRINTS("usb3_ppc: VCONN OC!"); + + /* + * CC overvoltage event. There is not action to take here, but + * log the event. + */ + if (rise & SN5S330_CC1_CON || rise & SN5S330_CC2_CON) + CPRINTS("usb3_ppc: CC OV!"); + + /* Clear the interrupt sources. */ + write_reg(port, SN5S330_INT_TRIP_RISE_REG2, rise); + write_reg(port, SN5S330_INT_TRIP_FALL_REG2, fall); + } +} +DECLARE_DEFERRED(baseboard_usbc_usb3_handle_interrupt); + +void baseboard_usbc_usb3_irq(void) +{ + hook_call_deferred(&baseboard_usbc_usb3_handle_interrupt_data, 0); +} + +#endif /* defined(GPIO_USBC_UF_ATTACHED_SRC) */ +#endif /* defined(SECTION_IS_RW) */ diff --git a/baseboard/intelrvp/README.md b/baseboard/intelrvp/README.md index b72d653d33..3405633132 100644 --- a/baseboard/intelrvp/README.md +++ b/baseboard/intelrvp/README.md @@ -1,25 +1,41 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - This folder is for the baseboard for the board specific files which use Intel Reference Validation Platform (RVP) for developing the EC and other peripherals which can be hooked on EC or RVP. This baseboard follows the Intel Modular Embedded Controller Card (MECC) -specification for pinout and these pin definitions remain same on all the -RVPs. Chrome MECC spec is standardized for Icelake and successor RVPs hence -this baseboard code is applicable to Icelake and its successors only. +specification for pinout and these pin definitions remain same on all the RVPs. +Chrome MECC spec is standardized for Icelake and successor RVPs hence this +baseboard code is applicable to Icelake and its successors only. Following hardware features are supported on MECC header by RVP and can be validated by software by MECC. -1. Power to MECC is provide by RVP (battery + DC Jack + Type C) -2. Power control pins for Intel SOC are added -3. Servo V2 header need to be added by MECC -4. Google H1 chip need to be added by MECC (optional for EC vendors) -4. 2 Type-C port support (SRC/SNK/BC1.2/MUX/Rerimer) -5. 6 Temperature sensors -6. 4 ADC -7. 4 I2C Channels -8. 1 Fan control + +## MECC version 1.0 features + +1. Power to MECC is provided by RVP (battery + DC Jack + Type C) +2. Power control pins for Intel SOC are added +3. Servo V2 header need to be added by MECC +4. Google H1 chip need to be added by MECC (optional for EC vendors) +5. 4 Type-C port support (SRC/SNK/MUX/Rerimer) as Add In Card (AIC) on + RVP +6. Optional 2 Type-C port routed to MECC for integrated TCPC support +7. 6 I2C Channels +8. 2 SMLINK Channels +9. 2 I3C channels + +## MECC version 1.1 features + +1. Power to MECC is provided by RVP (battery + DC Jack + Type C) +2. Power control pins for Intel SOC are added +3. Servo V2 header is added on RVP as an AIC +4. Google H1 chip is added on RVP as an AIC +5. 4 Type-C port support (SRC/SNK/MUX/Rerimer) as an (AIC) +6. Optional 2 Type-C port routed to MECC for integrated TCPC support +7. 6 I2C Channels +8. 2 SMLINK Channels +9. 2 I3C channels +10. 1 Fan control +11. 4 ADC based temperature sensors +12. PECI control +13. I2C based Keyboard is added on RVP as an AIC +14. Both Google & Intel CCD support is added on RVP on Type-C port 0 diff --git a/baseboard/intelrvp/adlrvp.c b/baseboard/intelrvp/adlrvp.c new file mode 100644 index 0000000000..5f307ac066 --- /dev/null +++ b/baseboard/intelrvp/adlrvp.c @@ -0,0 +1,603 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADLRVP board-specific common configuration */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "bq25710.h" +#include "charger.h" +#include "common.h" +#include "driver/retimer/bb_retimer_public.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "ioexpander.h" +#include "isl9241.h" +#include "pca9675.h" +#include "power/icelake.h" +#include "sn5s330.h" +#include "system.h" +#include "task.h" +#include "tusb1064.h" +#include "usb_mux.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_COMMAND, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_COMMAND, format, ##args) + +/* TCPC AIC GPIO Configuration */ +const struct tcpc_aic_gpio_config_t tcpc_aic_gpios[] = { + [TYPE_C_PORT_0] = { + .tcpc_alert = GPIO_USBC_TCPC_ALRT_P0, + .ppc_alert = GPIO_USBC_TCPC_PPC_ALRT_P0, + .ppc_intr_handler = sn5s330_interrupt, + }, +#if defined(HAS_TASK_PD_C1) + [TYPE_C_PORT_1] = { + .tcpc_alert = GPIO_USBC_TCPC_ALRT_P1, + .ppc_alert = GPIO_USBC_TCPC_PPC_ALRT_P1, + .ppc_intr_handler = sn5s330_interrupt, + }, +#endif +#if defined(HAS_TASK_PD_C2) + [TYPE_C_PORT_2] = { + .tcpc_alert = GPIO_USBC_TCPC_ALRT_P2, + .ppc_alert = GPIO_USBC_TCPC_PPC_ALRT_P2, + .ppc_intr_handler = sn5s330_interrupt, + }, +#endif +#if defined(HAS_TASK_PD_C3) + [TYPE_C_PORT_3] = { + .tcpc_alert = GPIO_USBC_TCPC_ALRT_P3, + .ppc_alert = GPIO_USBC_TCPC_PPC_ALRT_P3, + .ppc_intr_handler = sn5s330_interrupt, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_aic_gpios) == CONFIG_USB_PD_PORT_MAX_COUNT); + +/* USB-C PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [TYPE_C_PORT_0] = { + .i2c_port = I2C_PORT_TYPEC_0, + .i2c_addr_flags = I2C_ADDR_SN5S330_TCPC_AIC_PPC, + .drv = &sn5s330_drv, + }, +#if defined(HAS_TASK_PD_C1) + [TYPE_C_PORT_1] = { + .i2c_port = I2C_PORT_TYPEC_1, + .i2c_addr_flags = I2C_ADDR_SN5S330_TCPC_AIC_PPC, + .drv = &sn5s330_drv + }, +#endif +#if defined(HAS_TASK_PD_C2) + [TYPE_C_PORT_2] = { + .i2c_port = I2C_PORT_TYPEC_2, + .i2c_addr_flags = I2C_ADDR_SN5S330_TCPC_AIC_PPC, + .drv = &sn5s330_drv, + }, +#endif +#if defined(HAS_TASK_PD_C3) + [TYPE_C_PORT_3] = { + .i2c_port = I2C_PORT_TYPEC_3, + .i2c_addr_flags = I2C_ADDR_SN5S330_TCPC_AIC_PPC, + .drv = &sn5s330_drv, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == CONFIG_USB_PD_PORT_MAX_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USB-C retimer Configuration */ +struct usb_mux bb_retimer0_usb_mux = { + .usb_port = TYPE_C_PORT_0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_TYPEC_0, + .i2c_addr_flags = I2C_PORT0_BB_RETIMER_ADDR, +}; +struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = TYPE_C_PORT_0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +#if defined(HAS_TASK_PD_C1) +struct usb_mux bb_retimer1_usb_mux = { + .usb_port = TYPE_C_PORT_1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_TYPEC_1, + .i2c_addr_flags = I2C_PORT1_BB_RETIMER_ADDR, +}; +struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = TYPE_C_PORT_1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +#endif +#if defined(HAS_TASK_PD_C2) +struct usb_mux bb_retimer2_usb_mux = { + .usb_port = TYPE_C_PORT_2, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_TYPEC_2, + .i2c_addr_flags = I2C_PORT2_BB_RETIMER_ADDR, +}; +struct usb_mux_chain usbc2_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = TYPE_C_PORT_2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +#endif +#if defined(HAS_TASK_PD_C3) +struct usb_mux_chain usbc3_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = TYPE_C_PORT_3, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +#endif + +/* USB muxes Configuration */ +struct usb_mux_chain usb_muxes[] = { + [TYPE_C_PORT_0] = { + .mux = &bb_retimer0_usb_mux, + .next = &usbc0_tcss_usb_mux, + }, +#if defined(HAS_TASK_PD_C1) + [TYPE_C_PORT_1] = { + .mux = &bb_retimer1_usb_mux, + .next = &usbc1_tcss_usb_mux, + }, +#endif +#if defined(HAS_TASK_PD_C2) + [TYPE_C_PORT_2] = { + .mux = &bb_retimer2_usb_mux, + .next = &usbc2_tcss_usb_mux, + }, +#endif +#if defined(HAS_TASK_PD_C3) + [TYPE_C_PORT_3] = { + .mux = &(const struct usb_mux) { + .usb_port = TYPE_C_PORT_3, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_TYPEC_3, + .i2c_addr_flags = I2C_PORT3_BB_RETIMER_ADDR, + }, + .next = &usbc3_tcss_usb_mux, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == CONFIG_USB_PD_PORT_MAX_COUNT); + +/* USB Mux Configuration for Soc side BB-Retimers for Dual retimer config */ +struct usb_mux_chain soc_side_bb_retimer0_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = TYPE_C_PORT_0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_TYPEC_0, + .i2c_addr_flags = I2C_PORT0_BB_RETIMER_SOC_ADDR, + }, + .next = &usbc0_tcss_usb_mux, +}; + +#if defined(HAS_TASK_PD_C1) +struct usb_mux_chain soc_side_bb_retimer1_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = TYPE_C_PORT_1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_TYPEC_1, + .i2c_addr_flags = I2C_PORT1_BB_RETIMER_SOC_ADDR, + }, + .next = &usbc1_tcss_usb_mux, +}; +#endif + +const struct bb_usb_control bb_controls[] = { + [TYPE_C_PORT_0] = { + .retimer_rst_gpio = (enum gpio_signal) + IOEX_USB_C0_BB_RETIMER_RST, + .usb_ls_en_gpio = (enum gpio_signal) + IOEX_USB_C0_BB_RETIMER_LS_EN, + }, +#if defined(HAS_TASK_PD_C1) + [TYPE_C_PORT_1] = { + .retimer_rst_gpio = (enum gpio_signal) + IOEX_USB_C1_BB_RETIMER_RST, + .usb_ls_en_gpio = (enum gpio_signal) + IOEX_USB_C1_BB_RETIMER_LS_EN, + }, +#endif +#if defined(HAS_TASK_PD_C2) + [TYPE_C_PORT_2] = { + .retimer_rst_gpio = (enum gpio_signal) + IOEX_USB_C2_BB_RETIMER_RST, + .usb_ls_en_gpio = (enum gpio_signal) + IOEX_USB_C2_BB_RETIMER_LS_EN, + }, +#endif +#if defined(HAS_TASK_PD_C3) + [TYPE_C_PORT_3] = { + .retimer_rst_gpio = (enum gpio_signal) + IOEX_USB_C3_BB_RETIMER_RST, + .usb_ls_en_gpio = (enum gpio_signal) + IOEX_USB_C3_BB_RETIMER_LS_EN, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(bb_controls) == CONFIG_USB_PD_PORT_MAX_COUNT); + +/* Cache BB retimer power state */ +static bool cache_bb_enable[CONFIG_USB_PD_PORT_MAX_COUNT]; + +/* Each TCPC have corresponding IO expander and are available in pair */ +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_PCA9675] = { + .i2c_host_port = I2C_PORT_TYPEC_0, + .i2c_addr_flags = I2C_ADDR_PCA9675_TCPC_AIC_IOEX, + .drv = &pca9675_ioexpander_drv, + }, + [IOEX_C1_PCA9675] = { + .i2c_host_port = I2C_PORT_TYPEC_1, + .i2c_addr_flags = I2C_ADDR_PCA9675_TCPC_AIC_IOEX, + .drv = &pca9675_ioexpander_drv, + }, +#if defined(HAS_TASK_PD_C2) + [IOEX_C2_PCA9675] = { + .i2c_host_port = I2C_PORT_TYPEC_2, + .i2c_addr_flags = I2C_ADDR_PCA9675_TCPC_AIC_IOEX, + .drv = &pca9675_ioexpander_drv, + }, + [IOEX_C3_PCA9675] = { + .i2c_host_port = I2C_PORT_TYPEC_3, + .i2c_addr_flags = I2C_ADDR_PCA9675_TCPC_AIC_IOEX, + .drv = &pca9675_ioexpander_drv, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +/* Charger Chips */ +struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Port 0 & 1 and 2 & 3 share same line for over current indication */ +#if defined(HAS_TASK_PD_C2) + enum ioex_signal oc_signal = port < TYPE_C_PORT_2 ? IOEX_USB_C0_C1_OC : + IOEX_USB_C2_C3_OC; +#else + enum ioex_signal oc_signal = IOEX_USB_C0_C1_OC; +#endif + + /* Overcurrent indication is active low signal */ + ioex_set_level(oc_signal, is_overcurrented ? 0 : 1); +} + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + /* + * ADL-P-DDR5 RVP SKU has cascaded retimer topology. + * Ports with cascaded retimers share common load switch and reset pin + * hence no need to set the power state again if the 1st retimer's power + * status has already changed. + */ + if (cache_bb_enable[me->usb_port] == enable) + return EC_SUCCESS; + + cache_bb_enable[me->usb_port] = enable; + + /* Handle retimer's power domain.*/ + if (enable) { + ioex_set_level((enum ioex_signal)bb_controls[me->usb_port] + .usb_ls_en_gpio, + 1); + + /* + * minimum time from VCC to RESET_N de-assertion is 100us + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + msleep(1); + ioex_set_level((enum ioex_signal)bb_controls[me->usb_port] + .retimer_rst_gpio, + 1); + + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + + } else { + ioex_set_level((enum ioex_signal)bb_controls[me->usb_port] + .retimer_rst_gpio, + 0); + msleep(1); + ioex_set_level((enum ioex_signal)bb_controls[me->usb_port] + .usb_ls_en_gpio, + 0); + } + return EC_SUCCESS; +} + +static void board_connect_c0_sbu_deferred(void) +{ + int ccd_intr_level = gpio_get_level(GPIO_CCD_MODE_ODL); + + if (ccd_intr_level) { + /* Default set the SBU lines to AUX mode on TCPC-AIC */ + ioex_set_level(IOEX_USB_C0_USB_MUX_CNTRL_1, 0); + ioex_set_level(IOEX_USB_C0_USB_MUX_CNTRL_0, 0); + } else { + /* Set the SBU lines to CCD mode on TCPC-AIC */ + ioex_set_level(IOEX_USB_C0_USB_MUX_CNTRL_1, 1); + ioex_set_level(IOEX_USB_C0_USB_MUX_CNTRL_0, 0); + } +} +DECLARE_DEFERRED(board_connect_c0_sbu_deferred); + +void board_connect_c0_sbu(enum gpio_signal s) +{ + hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); +} + +static void enable_h1_irq(void) +{ + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); +} +DECLARE_HOOK(HOOK_INIT, enable_h1_irq, HOOK_PRIO_LAST); + +void set_charger_system_voltage(void) +{ + switch (ADL_RVP_BOARD_ID(board_get_version())) { + case ADLN_LP5_ERB_SKU_BOARD_ID: + case ADLN_LP5_RVP_SKU_BOARD_ID: + /* + * As per b:196184163 configure the PPVAR_SYS depend + * on AC or AC+battery + */ + if (extpower_is_present() && battery_is_present()) { + bq25710_set_min_system_voltage( + CHARGER_SOLO, battery_get_info()->voltage_min); + } else { + bq25710_set_min_system_voltage( + CHARGER_SOLO, battery_get_info()->voltage_max); + } + break; + + /* Add additional board SKUs */ + default: + break; + } +} +DECLARE_HOOK(HOOK_AC_CHANGE, set_charger_system_voltage, HOOK_PRIO_DEFAULT); + +static void configure_charger(void) +{ + switch (ADL_RVP_BOARD_ID(board_get_version())) { + case ADLN_LP5_ERB_SKU_BOARD_ID: + case ADLN_LP5_RVP_SKU_BOARD_ID: + /* charger chip BQ25720 support */ + chg_chips[0].i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS; + chg_chips[0].drv = &bq25710_drv; + set_charger_system_voltage(); + break; + + /* Add additional board SKUs */ + default: + break; + } +} + +static void configure_retimer_usbmux(void) +{ + switch (ADL_RVP_BOARD_ID(board_get_version())) { + case ADLN_LP5_ERB_SKU_BOARD_ID: + case ADLN_LP5_RVP_SKU_BOARD_ID: + /* enable TUSB1044RNQR redriver on Port0 */ + bb_retimer0_usb_mux.i2c_addr_flags = TUSB1064_I2C_ADDR14_FLAGS; + bb_retimer0_usb_mux.driver = &tusb1064_usb_mux_driver; + bb_retimer0_usb_mux.hpd_update = tusb1044_hpd_update; + +#if defined(HAS_TASK_PD_C1) + bb_retimer1_usb_mux.driver = NULL; + bb_retimer1_usb_mux.hpd_update = NULL; +#endif + break; + + case ADLP_LP5_T4_RVP_SKU_BOARD_ID: + /* No retimer on Port-2 */ +#if defined(HAS_TASK_PD_C2) + bb_retimer2_usb_mux.driver = NULL; +#endif + break; + + case ADLP_DDR5_RVP_SKU_BOARD_ID: + /* + * ADL-P-DDR5 RVP has dual BB-retimers for port0 & port1. + * Change the default usb mux config on runtime to support + * dual retimer topology. + */ + usb_muxes[TYPE_C_PORT_0].next = &soc_side_bb_retimer0_usb_mux; +#if defined(HAS_TASK_PD_C1) + usb_muxes[TYPE_C_PORT_1].next = &soc_side_bb_retimer1_usb_mux; +#endif + break; + + /* Add additional board SKUs */ + + default: + break; + } +} + +static void configure_battery_type(void) +{ + int bat_cell_type; + + switch (ADL_RVP_BOARD_ID(board_get_version())) { + case ADLM_LP4_RVP1_SKU_BOARD_ID: + case ADLM_LP5_RVP2_SKU_BOARD_ID: + case ADLM_LP5_RVP3_SKU_BOARD_ID: + case ADLN_LP5_ERB_SKU_BOARD_ID: + case ADLN_LP5_RVP_SKU_BOARD_ID: + /* configure Battery to 2S based */ + bat_cell_type = BATTERY_GETAC_SMP_HHP_408_2S; + break; + default: + /* configure Battery to 3S based */ + bat_cell_type = BATTERY_GETAC_SMP_HHP_408_3S; + break; + } + + /* Set the fixed battery type */ + battery_set_fixed_battery_type(bat_cell_type); +} +/******************************************************************************/ +/* PWROK signal configuration */ +/* + * On ADLRVP, SYS_PWROK_EC is an output controlled by EC and uses ALL_SYS_PWRGD + * as input. + */ +const struct intel_x86_pwrok_signal pwrok_signal_assert_list[] = { + { + .gpio = GPIO_SYS_PWROK_EC, + .delay_ms = 3, + }, +}; +const int pwrok_signal_assert_count = ARRAY_SIZE(pwrok_signal_assert_list); + +const struct intel_x86_pwrok_signal pwrok_signal_deassert_list[] = { + { + .gpio = GPIO_SYS_PWROK_EC, + }, +}; +const int pwrok_signal_deassert_count = ARRAY_SIZE(pwrok_signal_assert_list); + +/* + * Returns board information (board id[7:0] and Fab id[15:8]) on success + * -1 on error. + */ +__override int board_get_version(void) +{ + /* Cache the ADLRVP board ID */ + static int adlrvp_board_id; + + int port0, port1; + int fab_id, board_id, bom_id; + + /* Board ID is already read */ + if (adlrvp_board_id) + return adlrvp_board_id; + + if (ioexpander_read_intelrvp_version(&port0, &port1)) + return -1; + /* + * Port0: bit 0 - BOM ID(2) + * bit 2:1 - FAB ID(1:0) + 1 + * Port1: bit 7:6 - BOM ID(1:0) + * bit 5:0 - BOARD ID(5:0) + */ + bom_id = ((port1 & 0xC0) >> 6) | ((port0 & 0x01) << 2); + fab_id = ((port0 & 0x06) >> 1) + 1; + board_id = port1 & 0x3F; + + CPRINTS("BID:0x%x, FID:0x%x, BOM:0x%x", board_id, fab_id, bom_id); + + adlrvp_board_id = board_id | (fab_id << 8); + return adlrvp_board_id; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + bool tbt_usb4 = true; + + switch (ADL_RVP_BOARD_ID(board_get_version())) { + case ADLN_LP5_ERB_SKU_BOARD_ID: + case ADLN_LP5_RVP_SKU_BOARD_ID: + /* No retimer on both ports */ + tbt_usb4 = false; + break; + + case ADLP_LP5_T4_RVP_SKU_BOARD_ID: + /* No retimer on Port-2 hence no platform level AUX & LSx mux */ +#if defined(HAS_TASK_PD_C2) + if (port == TYPE_C_PORT_2) + tbt_usb4 = false; +#endif + break; + + /* Add additional board SKUs */ + default: + break; + } + + return tbt_usb4; +} + +__override void board_pre_task_i2c_peripheral_init(void) +{ + /* Initialized IOEX-0 to access IOEX-GPIOs needed pre-task */ + ioex_init(IOEX_C0_PCA9675); + + /* Make sure SBU are routed to CCD or AUX based on CCD status at init */ + board_connect_c0_sbu_deferred(); + + /* Configure battery type */ + configure_battery_type(); + + /* Reconfigure board specific charger drivers */ + configure_charger(); + + /* Configure board specific retimer & mux */ + configure_retimer_usbmux(); +} + +/* + * ADL RVP has both ITE and FUSB based TCPC chips. By default, the PD + * state of a non-attached port remains in PD_DRP_TOGGLE_ON in active + * state. Also, FUSB TCPC chip does not support 'dual role auto toggle' + * which contradicts the default set S0 state of PD_DRP_TOGGLE_ON, + * while ITE based TCPC can support dual role auto toggle. The + * default PD_DRP_TOGGLE_ON state in Active state doesnot allow TCPC + * ports to enter Low power mode. To fix the issue, added board specific + * code to remove the default DRP state - PD_DRP_TOGGLE_ON in S0. Also, + * eventhough 'dual role auto toggle' is not supported by FUSB, the ports + * supports both source and sink. Hence, setting the default DRP state + * as PD_DRP_FORCE_SOURCE in S0, would be the ideal board based solution to + * support for both source and sink devices for this RVP. + * Note:For ITE based TCPC, low power mode entry does makes no + * difference, as it is controlled by ITE TCPC clk in deep sleepmode. + */ +__override enum pd_dual_role_states pd_get_drp_state_in_s0(void) +{ + return PD_DRP_FORCE_SOURCE; +} diff --git a/baseboard/intelrvp/adlrvp.h b/baseboard/intelrvp/adlrvp.h new file mode 100644 index 0000000000..2159adf92c --- /dev/null +++ b/baseboard/intelrvp/adlrvp.h @@ -0,0 +1,229 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADL-RVP specific configuration */ + +#ifndef __ADLRVP_BOARD_H +#define __ADLRVP_BOARD_H + +/* Temperature sensor */ +#define CONFIG_TEMP_SENSOR + +#include "baseboard.h" + +/* RVP Board ids */ +#define CONFIG_BOARD_VERSION_GPIO +#define ADLM_LP4_RVP1_SKU_BOARD_ID 0x01 +#define ADLM_LP5_RVP2_SKU_BOARD_ID 0x02 +#define ADLM_LP5_RVP3_SKU_BOARD_ID 0x03 +#define ADLN_LP5_ERB_SKU_BOARD_ID 0x06 +#define ADLN_LP5_RVP_SKU_BOARD_ID 0x07 +#define ADLP_DDR5_RVP_SKU_BOARD_ID 0x12 +#define ADLP_LP5_T4_RVP_SKU_BOARD_ID 0x13 +#define ADL_RVP_BOARD_ID(id) ((id)&0x3F) + +/* MECC config */ +#define CONFIG_INTEL_RVP_MECC_VERSION_1_0 + +/* Support early firmware selection */ +#define CONFIG_VBOOT_EFS2 + +/* Chipset */ +#define CONFIG_CHIPSET_ALDERLAKE + +/* ADL has new low-power features that require extra-wide virtual wire + * pulses. The EDS specifies 100 microseconds. */ +#undef CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US +#define CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US 100 + +/* USB PD config */ +#if defined(HAS_TASK_PD_C3) +#define CONFIG_USB_PD_PORT_MAX_COUNT 4 +#elif defined(HAS_TASK_PD_C2) +#define CONFIG_USB_PD_PORT_MAX_COUNT 3 +#elif defined(HAS_TASK_PD_C1) +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#else +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#endif +#define CONFIG_USB_MUX_VIRTUAL +#define CONFIG_USB_MUX_TUSB1044 +#define PD_MAX_POWER_MW 100000 + +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +/* TCPC AIC config */ +/* Support NXP PCA9675 I/O expander. */ +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_PCA9675 +#define I2C_ADDR_PCA9675_TCPC_AIC_IOEX 0x21 + +/* DC Jack charge ports */ +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 +#define DEDICATED_CHARGE_PORT CONFIG_USB_PD_PORT_MAX_COUNT + +/* PPC */ +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USB_PD_DISCHARGE_PPC +#define I2C_ADDR_SN5S330_TCPC_AIC_PPC 0x40 + +/* TCPC */ +#define CONFIG_USB_PD_DISCHARGE +#define CONFIG_USB_PD_TCPM_FUSB302 +#define I2C_ADDR_FUSB302_TCPC_AIC 0x22 + +/* Config BB retimer */ +#define CONFIG_USBC_RETIMER_INTEL_BB +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Connector side BB retimers */ +#define I2C_PORT0_BB_RETIMER_ADDR 0x56 +#if defined(HAS_TASK_PD_C1) +#define I2C_PORT1_BB_RETIMER_ADDR 0x57 +#endif +#if defined(HAS_TASK_PD_C2) +#define I2C_PORT2_BB_RETIMER_ADDR 0x58 +#endif +#if defined(HAS_TASK_PD_C3) +#define I2C_PORT3_BB_RETIMER_ADDR 0x59 +#endif + +/* SOC side BB retimers (dual retimer config) */ +#define I2C_PORT0_BB_RETIMER_SOC_ADDR 0x54 +#if defined(HAS_TASK_PD_C1) +#define I2C_PORT1_BB_RETIMER_SOC_ADDR 0x55 +#endif + +/* I2C EEPROM */ +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_PORT_EEPROM I2C_PORT_PCA9555_BOARD_ID_GPIO + +/* Enable CBI */ +#define CONFIG_CBI_EEPROM + +/* Configure mux at runtime */ +#define CONFIG_USB_MUX_RUNTIME_CONFIG + +/* Enable VCONN */ +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 + +/* Enable low power mode */ +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Config Fan */ +#define CONFIG_FANS 1 +#define BOARD_FAN_MIN_RPM 3000 +#define BOARD_FAN_MAX_RPM 10000 + +/* Charger Configs */ +#define CONFIG_CHARGER_RUNTIME_CONFIG +/* Charger chip on ADL-P, ADL-M */ +#define CONFIG_CHARGER_ISL9241 +/* Charger chip on ADL-N */ +#define CONFIG_CHARGER_BQ25720 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 70 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 + +/* Port 80 */ +#define PORT80_I2C_ADDR MAX695X_I2C_ADDR1_FLAGS + +/* Board Id */ +#define I2C_ADDR_PCA9555_BOARD_ID_GPIO 0x22 + +/* + * Frequent watchdog timer resets are seen, with the + * increase in number of type-c ports. So increase + * the timer value to support more type-c ports. + */ +#ifdef VARIANT_INTELRVP_EC_IT8320 +#if defined(HAS_TASK_PD_C2) && defined(HAS_TASK_PD_C3) +#undef CONFIG_WATCHDOG_PERIOD_MS +#define CONFIG_WATCHDOG_PERIOD_MS 4000 +#endif +#endif + +/* + * Enable support for battery hostcmd, supporting longer strings. + * Support for EC_CMD_BATTERY_GET_STATIC version 1. + */ +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 + +/* Config to indicate battery type doesn't auto detect */ +#define CONFIG_BATTERY_TYPE_NO_AUTO_DETECT + +/* Enable system boot time logging */ +#define CONFIG_SYSTEM_BOOT_TIME_LOGGING + +#ifndef __ASSEMBLER__ + +enum adlrvp_charge_ports { + TYPE_C_PORT_0, +#if defined(HAS_TASK_PD_C1) + TYPE_C_PORT_1, +#endif +#if defined(HAS_TASK_PD_C2) + TYPE_C_PORT_2, +#endif +#if defined(HAS_TASK_PD_C3) + TYPE_C_PORT_3, +#endif +}; + +/* + * Each Type-C add in card has two I/O expanders hence even if one Type-C port + * is enabled other I/O expander is available for usage. + */ +enum ioex_port { + IOEX_C0_PCA9675, + IOEX_C1_PCA9675, +#if defined(HAS_TASK_PD_C2) + IOEX_C2_PCA9675, + IOEX_C3_PCA9675, +#endif + IOEX_PORT_COUNT +}; +#define CONFIG_IO_EXPANDER_PORT_COUNT IOEX_PORT_COUNT + +enum battery_type { + BATTERY_GETAC_SMP_HHP_408_3S, + BATTERY_GETAC_SMP_HHP_408_2S, + BATTERY_TYPE_COUNT, +}; + +/* I2C access in polling mode before task is initialized */ +#define CONFIG_I2C_BITBANG + +enum adlrvp_bitbang_i2c_channel { + I2C_BITBANG_CHAN_BRD_ID, + I2C_BITBANG_CHAN_IOEX_0, + I2C_BITBANG_CHAN_COUNT +}; +#define I2C_BITBANG_PORT_COUNT I2C_BITBANG_CHAN_COUNT + +void espi_reset_pin_asserted_interrupt(enum gpio_signal signal); +void extpower_interrupt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); +void tcpc_alert_event(enum gpio_signal signal); +void board_connect_c0_sbu(enum gpio_signal s); +int board_get_version(void); +void battery_detect_interrupt(enum gpio_signal signal); +void set_charger_system_voltage(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __ADLRVP_BOARD_H */ diff --git a/baseboard/intelrvp/adlrvp_battery.c b/baseboard/intelrvp/adlrvp_battery.c new file mode 100644 index 0000000000..f7107cb1a4 --- /dev/null +++ b/baseboard/intelrvp/adlrvp_battery.c @@ -0,0 +1,83 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "common.h" +#include "util.h" + +#ifdef CONFIG_BATTERY_TYPE_NO_AUTO_DETECT +/* Battery configuration */ +const struct board_batt_params board_battery_info[] = { + /* + * 3S based battery configuration + * Getac Battery (Getac SMP-HHP-408) Information + * Fuel gauge: BQ40Z50-R3 + */ + [BATTERY_GETAC_SMP_HHP_408_3S] = { + .fuel_gauge = { + .manuf_name = "Getac", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = 0, + .discharging_max_c = 60, + }, + }, + /* + * 2S based battery configuration + * Getac Battery (Getac SMP-HHP-408) Information + * Fuel gauge: BQ40Z50-R3 + */ + [BATTERY_GETAC_SMP_HHP_408_2S] = { + .fuel_gauge = { + .manuf_name = "Getac", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = 0, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_GETAC_SMP_HHP_408_3S; +#endif /* CONFIG_BATTERY_TYPE_NO_AUTO_DETECT */ diff --git a/baseboard/intelrvp/adlrvp_ioex_gpio.inc b/baseboard/intelrvp/adlrvp_ioex_gpio.inc new file mode 100644 index 0000000000..b62dcf53a3 --- /dev/null +++ b/baseboard/intelrvp/adlrvp_ioex_gpio.inc @@ -0,0 +1,32 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +IOEX(USB_C0_BB_RETIMER_RST, EXPIN(IOEX_C0_PCA9675, 0, PCA9675_IO_P00), GPIO_OUT_LOW) +IOEX(USB_C0_BB_RETIMER_LS_EN, EXPIN(IOEX_C0_PCA9675, 0, PCA9675_IO_P01), GPIO_OUT_LOW) +IOEX(USB_C0_USB_MUX_CNTRL_1, EXPIN(IOEX_C0_PCA9675, 0, PCA9675_IO_P04), GPIO_OUT_LOW) +IOEX(USB_C0_USB_MUX_CNTRL_0, EXPIN(IOEX_C0_PCA9675, 0, PCA9675_IO_P05), GPIO_OUT_LOW) + +IOEX(USB_C1_BB_RETIMER_RST, EXPIN(IOEX_C1_PCA9675, 0, PCA9675_IO_P00), GPIO_OUT_LOW) +IOEX(USB_C1_BB_RETIMER_LS_EN, EXPIN(IOEX_C1_PCA9675, 0, PCA9675_IO_P01), GPIO_OUT_LOW) +IOEX(USB_C1_HPD, EXPIN(IOEX_C1_PCA9675, 0, PCA9675_IO_P02), GPIO_OUT_LOW) +IOEX(USB_C0_C1_OC, EXPIN(IOEX_C1_PCA9675, 0, PCA9675_IO_P10), GPIO_OUT_HIGH) + +#if defined(HAS_TASK_PD_C2) +IOEX(USB_C2_BB_RETIMER_RST, EXPIN(IOEX_C2_PCA9675, 0, PCA9675_IO_P00), GPIO_OUT_LOW) +IOEX(USB_C2_BB_RETIMER_LS_EN, EXPIN(IOEX_C2_PCA9675, 0, PCA9675_IO_P01), GPIO_OUT_LOW) +IOEX(USB_C2_USB_MUX_CNTRL_1, EXPIN(IOEX_C2_PCA9675, 0, PCA9675_IO_P04), GPIO_OUT_LOW) +IOEX(USB_C2_USB_MUX_CNTRL_0, EXPIN(IOEX_C2_PCA9675, 0, PCA9675_IO_P05), GPIO_OUT_LOW) + +IOEX(USB_C3_BB_RETIMER_RST, EXPIN(IOEX_C3_PCA9675, 0, PCA9675_IO_P00), GPIO_OUT_LOW) +IOEX(USB_C3_BB_RETIMER_LS_EN, EXPIN(IOEX_C3_PCA9675, 0, PCA9675_IO_P01), GPIO_OUT_LOW) +IOEX(USB_C2_C3_OC, EXPIN(IOEX_C3_PCA9675, 0, PCA9675_IO_P10), GPIO_OUT_HIGH) +#endif + +/* ADL-RVP has custom GPIO implementation for reading board ID */ +UNIMPLEMENTED(BOARD_VERSION1) +UNIMPLEMENTED(BOARD_VERSION2) +UNIMPLEMENTED(BOARD_VERSION3) diff --git a/baseboard/intelrvp/baseboard.c b/baseboard/intelrvp/baseboard.c index bf1127bb76..41bcdc26c2 100644 --- a/baseboard/intelrvp/baseboard.c +++ b/baseboard/intelrvp/baseboard.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,12 +9,13 @@ #include "charge_state.h" #include "espi.h" #include "fan.h" +#include "gpio.h" #include "hooks.h" #include "pca9555.h" #include "peci.h" #include "power.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "timer.h" /* Wake-up pins for hibernate */ @@ -25,39 +26,6 @@ const enum gpio_signal hibernate_wake_pins[] = { }; const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); -/* ADC channels */ -const struct adc_t adc_channels[] = { - [ADC_TEMP_SNS_AMBIENT] = { - .name = "ADC_TEMP_SNS_AMBIENT", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = ADC_TEMP_SNS_AMBIENT_CHANNEL, - }, - [ADC_TEMP_SNS_DDR] = { - .name = "ADC_TEMP_SNS_DDR", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = ADC_TEMP_SNS_DDR_CHANNEL, - }, - [ADC_TEMP_SNS_SKIN] = { - .name = "ADC_TEMP_SNS_SKIN", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = ADC_TEMP_SNS_SKIN_CHANNEL, - }, - [ADC_TEMP_SNS_VR] = { - .name = "ADC_TEMP_SNS_VR", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = ADC_TEMP_SNS_VR_CHANNEL, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - #ifdef CONFIG_TEMP_SENSOR /* Temperature sensors */ const struct temp_sensor_t temp_sensors[] = { @@ -101,6 +69,33 @@ const struct temp_sensor_t temp_sensors[] = { }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(15), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SNS_AMBIENT] = THERMAL_A, [TEMP_SNS_BATTERY] = THERMAL_A, + [TEMP_SNS_DDR] = THERMAL_A, +#ifdef CONFIG_PECI + [TEMP_SNS_PECI] = THERMAL_A, +#endif + [TEMP_SNS_SKIN] = THERMAL_A, [TEMP_SNS_VR] = THERMAL_A, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); #endif /* CONFIG_TEMP_SENSOR */ #ifdef CONFIG_FANS @@ -127,33 +122,6 @@ const struct fan_t fans[] = { }, }; BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); - -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(15), - .temp_fan_max = C_TO_K(50), -}; - -struct ec_thermal_config thermal_params[] = { - [TEMP_SNS_AMBIENT] = thermal_a, - [TEMP_SNS_BATTERY] = thermal_a, - [TEMP_SNS_DDR] = thermal_a, -#ifdef CONFIG_PECI - [TEMP_SNS_PECI] = thermal_a, -#endif - [TEMP_SNS_SKIN] = thermal_a, - [TEMP_SNS_VR] = thermal_a, -}; -BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); #endif /* CONFIG_FANS */ static void board_init(void) @@ -172,14 +140,23 @@ DECLARE_HOOK(HOOK_INIT, board_interrupts_init, HOOK_PRIO_FIRST); int ioexpander_read_intelrvp_version(int *port0, int *port1) { - if (pca9555_read(I2C_PORT_PCA9555_BOARD_ID_GPIO, - I2C_ADDR_PCA9555_BOARD_ID_GPIO, - PCA9555_CMD_INPUT_PORT_0, port0)) - return -1; - - return pca9555_read(I2C_PORT_PCA9555_BOARD_ID_GPIO, - I2C_ADDR_PCA9555_BOARD_ID_GPIO, - PCA9555_CMD_INPUT_PORT_1, port1); + int i, rv; + + for (i = 0; i < RVP_VERSION_READ_RETRY_CNT; i++) { + rv = pca9555_read(I2C_PORT_PCA9555_BOARD_ID_GPIO, + I2C_ADDR_PCA9555_BOARD_ID_GPIO, + PCA9555_CMD_INPUT_PORT_0, port0); + + if (!rv && !pca9555_read(I2C_PORT_PCA9555_BOARD_ID_GPIO, + I2C_ADDR_PCA9555_BOARD_ID_GPIO, + PCA9555_CMD_INPUT_PORT_1, port1)) + return 0; + + msleep(1); + } + + /* pca9555 read failed */ + return -1; } __override void intel_x86_sys_reset_delay(void) @@ -190,4 +167,3 @@ __override void intel_x86_sys_reset_delay(void) */ udelay(60 * MSEC); } - diff --git a/baseboard/intelrvp/baseboard.h b/baseboard/intelrvp/baseboard.h index 5b7f969619..e47434c4af 100644 --- a/baseboard/intelrvp/baseboard.h +++ b/baseboard/intelrvp/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,9 +8,23 @@ #ifndef __CROS_EC_BASEBOARD_H #define __CROS_EC_BASEBOARD_H -#ifdef CHIP_FAMILY_IT83XX - #include "ite_ec.h" -#endif /* CHIP_FAMILY_IT83XX */ +#include "compiler.h" +#include "stdbool.h" + +#ifdef VARIANT_INTELRVP_EC_IT8320 +#include "ite_ec.h" +#elif defined(VARIANT_INTELRVP_EC_MCHP) +#include "mchp_ec.h" +#elif defined(VARIANT_INTELRVP_EC_NPCX) +#include "npcx_ec.h" +#else +#error "Define EC chip variant" +#endif + +/* + * TODO: b/241322365 - Watchdog error are observed if LTO is enabled + * hence disabled it. Enable LTO once the fix is found. + */ /* * Allow dangerous commands. @@ -18,7 +32,7 @@ */ #define CONFIG_SYSTEM_UNLOCKED -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE /* @@ -41,10 +55,12 @@ /* Port80 display */ #define CONFIG_MAX695X_SEVEN_SEGMENT_DISPLAY +/* RVP ID read retry count */ +#define RVP_VERSION_READ_RETRY_CNT 2 + /* Battery */ #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_FUEL_GAUGE -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_L #define CONFIG_BATTERY_REVIVE_DISCONNECT #define CONFIG_BATTERY_SMART @@ -52,16 +68,24 @@ #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_SENSE_RESISTOR 5 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 -#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#undef CONFIG_EXTPOWER_DEBOUNCE_MS #define CONFIG_EXTPOWER_DEBOUNCE_MS 200 #define CONFIG_EXTPOWER_GPIO #define CONFIG_TRICKLE_CHARGING +/* + * Don't allow the system to boot to S0 when the battery is low and unable to + * communicate on locked systems (which haven't PD negotiated) + */ +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000 +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 15001 + /* Keyboard */ -#define CONFIG_KEYBOARD_BOARD_CONFIG + #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2 @@ -71,55 +95,46 @@ /* USB-A config */ -/* BC1.2 config */ -#ifdef HAS_TASK_USB_CHG_P0 - #define CONFIG_CHARGE_RAMP_HW -#endif - /* Enable USB-PD REV 3.0 */ #define CONFIG_USB_PD_REV30 #define CONFIG_USB_PID 0x8086 /* USB PD config */ -#if defined(BOARD_TGLRVPU_ITE_TCPMV1) || defined(BOARD_TGLRVPY_ITE_TCPMV1) - #define CONFIG_USB_PD_TCPMV1 -#else - #define CONFIG_USB_DRP_ACC_TRYSRC - #define CONFIG_USB_PD_DECODE_SOP - #define CONFIG_USB_PD_TCPMV2 - #define CONFIG_USB_PD_TCPM_MUX -#endif +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_PD_TCPM_MUX #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_TCPM_TCPCI #define CONFIG_USB_PD_TRY_SRC -#define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT #define CONFIG_USB_POWER_DELIVERY +/* Treat 2nd reset from H1 as Power-On */ +#define CONFIG_BOARD_RESET_AFTER_POWER_ON /* USB MUX */ #ifdef CONFIG_USB_MUX_VIRTUAL - #define CONFIG_HOSTCMD_LOCATE_CHIP - #define CONFIG_INTEL_VIRTUAL_MUX +#define CONFIG_HOSTCMD_LOCATE_CHIP #endif #define CONFIG_USBC_SS_MUX /* SoC / PCH */ #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S5 #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_HOST_EVENT #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 #define CONFIG_POWER_COMMON #define CONFIG_POWER_S0IX +#define CONFIG_POWER_S4_RESIDENCY #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE /* EC */ -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_LED_COMMON #define CONFIG_LID_SWITCH #define CONFIG_VOLUME_BUTTONS @@ -128,7 +143,6 @@ /* Tablet mode */ #define CONFIG_TABLET_MODE #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L /* Verified boot */ #define CONFIG_CRC8 @@ -144,17 +158,19 @@ /* Temperature sensor */ #ifdef CONFIG_TEMP_SENSOR - #define CONFIG_STEINHART_HART_3V0_22K6_47K_4050B - #define CONFIG_THERMISTOR - #define CONFIG_THROTTLE_AP +#define CONFIG_STEINHART_HART_3V0_22K6_47K_4050B +#define CONFIG_TEMP_SENSOR_POWER +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_PP3300_A +#define CONFIG_THERMISTOR +#define CONFIG_THROTTLE_AP #ifdef CONFIG_PECI - #define CONFIG_PECI_COMMON +#define CONFIG_PECI_COMMON #endif /* CONFIG_PECI */ #endif /* CONFIG_TEMP_SENSOR */ /* I2C ports */ #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER /* EC exclude modules */ @@ -164,13 +180,10 @@ #include "module_id.h" #include "registers.h" -enum tcpc_rp_value; +FORWARD_DECLARE_ENUM(tcpc_rp_value); /* PWM channels */ -enum pwm_channel { - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_FAN, PWM_CH_COUNT }; /* FAN channels */ enum fan_channel { @@ -200,21 +213,14 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT, }; -/* List of supported batteries */ -enum battery_type { - BATTERY_SIMPLO_SMP_HHP_408, - BATTERY_SIMPLO_SMP_CA_445, - BATTERY_TYPE_COUNT, -}; - /* TODO(b:132652892): Verify the below numbers. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* Define typical operating power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_CURRENT_MA ((PD_MAX_POWER_MW / PD_MAX_VOLTAGE_MV) * 1000) #define DC_JACK_MAX_VOLTAGE_MV 19000 /* TCPC gpios */ @@ -246,14 +252,23 @@ struct tcpc_gpio_config_t { }; extern const struct tcpc_gpio_config_t tcpc_gpios[]; -/* Reset PD MCU */ -void board_reset_pd_mcu(void); +struct tcpc_aic_gpio_config_t { + /* TCPC interrupt */ + enum gpio_signal tcpc_alert; + /* PPC interrupt */ + enum gpio_signal ppc_alert; + /* PPC interrupt handler */ + void (*ppc_intr_handler)(int port); +}; +extern const struct tcpc_aic_gpio_config_t tcpc_aic_gpios[]; + void board_charging_enable(int port, int enable); void board_vbus_enable(int port, int enable); void board_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp); int ioexpander_read_intelrvp_version(int *port0, int *port1); void board_dc_jack_interrupt(enum gpio_signal signal); void tcpc_alert_event(enum gpio_signal signal); +bool is_typec_port(int port); #endif /* !__ASSEMBLER__ */ diff --git a/baseboard/intelrvp/battery.c b/baseboard/intelrvp/battery.c deleted file mode 100644 index cf4464ce55..0000000000 --- a/baseboard/intelrvp/battery.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery_fuel_gauge.h" -#include "battery_smart.h" -#include "common.h" -#include "util.h" - -const struct board_batt_params board_battery_info[] = { - /* - * Simplo Battery (SMP-HHP-408) Information - * Fuel gauge: BQ40Z50 - */ - [BATTERY_SIMPLO_SMP_HHP_408] = { - .fuel_gauge = { - .manuf_name = "SMP-HHP-408", - .ship_mode = { - .reg_addr = 0x00, - .reg_data = { 0x0010, 0x0010 }, - }, - .fet = { - .reg_addr = SB_BATTERY_STATUS, - .reg_mask = STATUS_INITIALIZED, - .disconnect_val = 0x0, - } - }, - .batt_info = { - .voltage_max = 8700, /* mV */ - .voltage_normal = 7600, - .voltage_min = 6100, - .precharge_current = 204, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 45, - .discharging_min_c = 0, - .discharging_max_c = 60, - }, - }, - - /* - * Simplo Battery (SMP-CA-445) Information - * Fuel gauge: BQ30Z554 - * TODO: SYSCROS-25972 - */ - [BATTERY_SIMPLO_SMP_CA_445] = { - .fuel_gauge = { - .manuf_name = "SMP-CA-445", - .ship_mode = { - .reg_addr = 0x00, - .reg_data = { 0x0010, 0x0010 }, - }, - .fet = { - .reg_addr = SB_BATTERY_STATUS, - .reg_mask = STATUS_INITIALIZED, - .disconnect_val = 0x0, - } - }, - .batt_info = { - .voltage_max = 8700, /* mV */ - .voltage_normal = 7600, - .voltage_min = 6100, - .precharge_current = 150, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 45, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); - -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO_SMP_HHP_408; diff --git a/baseboard/intelrvp/bc12.c b/baseboard/intelrvp/bc12.c deleted file mode 100644 index 9f212fba4e..0000000000 --- a/baseboard/intelrvp/bc12.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel BASEBOARD-RVP BC1.2 specific configuration */ - -#include "common.h" -#include "max14637.h" - -/* BC1.2 chip Configuration */ -#ifdef CONFIG_BC12_DETECT_MAX14637 -const struct max14637_config_t max14637_config[] = { - [TYPE_C_PORT_0] = { - .chip_enable_pin = GPIO_USB_C0_BC12_VBUS_ON_ODL, - .chg_det_pin = GPIO_USB_C0_BC12_CHG_DET_L, - .flags = MAX14637_FLAGS_CHG_DET_ACTIVE_LOW, - }, -#ifdef HAS_TASK_PD_C1 - [TYPE_C_PORT_1] = { - .chip_enable_pin = GPIO_USB_C1_BC12_VBUS_ON_ODL, - .chg_det_pin = GPIO_USB_C1_BC12_CHG_DET_L, - .flags = MAX14637_FLAGS_CHG_DET_ACTIVE_LOW, - }, -#endif /* HAS_TASK_PD_C1 */ -}; -BUILD_ASSERT(ARRAY_SIZE(max14637_config) == CONFIG_USB_PD_PORT_MAX_COUNT); -#endif /* CONFIG_BC12_DETECT_MAX14637 */ diff --git a/baseboard/intelrvp/build.mk b/baseboard/intelrvp/build.mk index d48d862fd5..b4cacf4cc2 100644 --- a/baseboard/intelrvp/build.mk +++ b/baseboard/intelrvp/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -9,18 +9,22 @@ #Intel RVP common files baseboard-y=baseboard.o baseboard-$(CONFIG_LED_COMMON)+=led.o led_states.o -baseboard-$(CONFIG_BATTERY_SMART)+=battery.o -baseboard-$(CONFIG_USB_POWER_DELIVERY)+=chg_usb_pd.o usb_pd_policy.o -#EC specific files -baseboard-$(CONFIG_USB_PD_TCPM_ITE_ON_CHIP)+=ite_ec.o - -#BC1.2 specific files -baseboard-$(CONFIG_BC12_DETECT_MAX14637)+=bc12.o +ifneq ($(CONFIG_USB_POWER_DELIVERY),) +baseboard-$(CONFIG_USB_POWER_DELIVERY)+=chg_usb_pd.o +baseboard-$(CONFIG_INTEL_RVP_MECC_VERSION_1_0)+=chg_usb_pd_mecc_1_0.o +baseboard-$(CONFIG_INTEL_RVP_MECC_VERSION_1_0)+=usb_pd_policy_mecc_1_0.o +endif -#USB MUX specific files -baseboard-$(CONFIG_USB_MUX_VIRTUAL)+=usb_mux.o -baseboard-$(CONFIG_USB_MUX_ANX7440)+=usb_mux.o +#EC specific files +baseboard-$(VARIANT_INTELRVP_EC_IT8320)+=ite_ec.o +baseboard-$(VARIANT_INTELRVP_EC_MCHP)+=mchp_ec.o +baseboard-$(VARIANT_INTELRVP_EC_NPCX)+=npcx_ec.o -#USB Retimer specific files -baseboard-$(CONFIG_USBC_RETIMER_INTEL_BB)+=retimer.o +#Common board specific files +ifneq ($(filter y,$(BOARD_ADLRVPP_ITE) $(BOARD_ADLRVPM_ITE) \ + $(BOARD_ADLRVPP_MCHP1521) $(BOARD_ADLRVPP_NPCX) \ + $(BOARD_ADLRVPP_MCHP1727)),) +baseboard-y+=adlrvp.o +baseboard-$(CONFIG_BATTERY_SMART)+=adlrvp_battery.o +endif diff --git a/baseboard/intelrvp/chg_usb_pd.c b/baseboard/intelrvp/chg_usb_pd.c index 8620268263..60ad6e5cdb 100644 --- a/baseboard/intelrvp/chg_usb_pd.c +++ b/baseboard/intelrvp/chg_usb_pd.c @@ -1,124 +1,50 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* Intel-RVP family-specific configuration */ +/* Common USB PD charge configuration */ #include "charge_manager.h" -#include "charge_state_v2.h" -#include "console.h" +#include "charge_state.h" +#include "gpio.h" #include "hooks.h" -#include "tcpci.h" -#include "system.h" +#include "tcpm/tcpci.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#ifdef CONFIG_ZEPHYR +#include "intelrvp.h" +#endif /* CONFIG_ZEPHYR */ -static inline int is_typec_port(int port) -{ - return !(port == DEDICATED_CHARGE_PORT || port == CHARGE_PORT_NONE); -} - - -int board_vbus_source_enabled(int port) -{ - int src_en = 0; +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) - /* Only Type-C ports can source VBUS */ - if (is_typec_port(port)) { - src_en = gpio_get_level(tcpc_gpios[port].src.pin); - - src_en = tcpc_gpios[port].src.pin_pol ? src_en : !src_en; - } - - return src_en; -} - -void board_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) +bool is_typec_port(int port) { - int ilim_en; - - /* Only Type-C ports can source VBUS */ - if (is_typec_port(port)) { - /* Enable SRC ILIM if rp is MAX single source current */ - ilim_en = (rp == CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT && - board_vbus_source_enabled(port)); - - gpio_set_level(tcpc_gpios[port].src_ilim.pin, - tcpc_gpios[port].src_ilim.pin_pol ? - ilim_en : !ilim_en); - } -} - -void board_charging_enable(int port, int enable) -{ - gpio_set_level(tcpc_gpios[port].snk.pin, - tcpc_gpios[port].snk.pin_pol ? enable : !enable); - -} - -void board_vbus_enable(int port, int enable) -{ - gpio_set_level(tcpc_gpios[port].src.pin, - tcpc_gpios[port].src.pin_pol ? enable : !enable); -} - -int pd_snk_is_vbus_provided(int port) -{ - int vbus_intr; - - if (port == DEDICATED_CHARGE_PORT) - return 1; - - vbus_intr = gpio_get_level(tcpc_gpios[port].vbus.pin); - - return tcpc_gpios[port].vbus.pin_pol ? vbus_intr : !vbus_intr; -} - -void tcpc_alert_event(enum gpio_signal signal) -{ - int port = -1; - int i; - - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - if (tcpc_gpios[i].vbus.pin == signal) { - port = i; - break; - } - } - - if (port != -1) - schedule_deferred_pd_interrupt(port); -} - -void board_tcpc_init(void) -{ - int i; - - /* Only reset TCPC if not sysjump */ - if (!system_jumped_late()) - board_reset_pd_mcu(); - - /* Enable TCPCx interrupt */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) - gpio_enable_interrupt(tcpc_gpios[i].vbus.pin); +#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 + return !(port == DEDICATED_CHARGE_PORT || port == CHARGE_PORT_NONE); +#else + return !(port == CHARGE_PORT_NONE); +#endif /* CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 */ } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); static inline int board_dc_jack_present(void) { +#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 return gpio_get_level(GPIO_DC_JACK_PRESENT); +#else + return 0; +#endif } +#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 static void board_dc_jack_handle(void) { struct charge_port_info charge_dc_jack; /* System is booted from DC Jack */ if (board_dc_jack_present()) { - charge_dc_jack.current = (PD_MAX_POWER_MW * 1000) / - DC_JACK_MAX_VOLTAGE_MV; + charge_dc_jack.current = + (PD_MAX_POWER_MW * 1000) / DC_JACK_MAX_VOLTAGE_MV; charge_dc_jack.voltage = DC_JACK_MAX_VOLTAGE_MV; } else { charge_dc_jack.current = 0; @@ -126,12 +52,15 @@ static void board_dc_jack_handle(void) } charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, - DEDICATED_CHARGE_PORT, &charge_dc_jack); + DEDICATED_CHARGE_PORT, &charge_dc_jack); } +#endif void board_dc_jack_interrupt(enum gpio_signal signal) { +#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 board_dc_jack_handle(); +#endif } static void board_charge_init(void) @@ -146,10 +75,12 @@ static void board_charge_init(void) for (port = 0; port < CHARGE_PORT_COUNT; port++) { for (supplier = 0; supplier < CHARGE_SUPPLIER_COUNT; supplier++) charge_manager_update_charge(supplier, port, - &charge_init); + &charge_init); } +#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 board_dc_jack_handle(); +#endif /* CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 */ } DECLARE_HOOK(HOOK_INIT, board_charge_init, HOOK_PRIO_DEFAULT); @@ -157,8 +88,7 @@ int board_set_active_charge_port(int port) { int i; /* charge port is a realy physical port */ - int is_real_port = (port >= 0 && - port < CHARGE_PORT_COUNT); + int is_real_port = (port >= 0 && port < CHARGE_PORT_COUNT); /* check if we are source vbus on that port */ int source = board_vbus_source_enabled(port); @@ -167,6 +97,7 @@ int board_set_active_charge_port(int port) return EC_ERROR_INVAL; } +#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 /* * Do not enable Type-C port if the DC Jack is present. * When the Type-C is active port, hardware circuit will @@ -176,6 +107,7 @@ int board_set_active_charge_port(int port) CPRINTS("DC Jack present, Skip enable p%d", port); return EC_ERROR_INVAL; } +#endif /* CONFIG_DEDICATED_CHARGE_PORT_COUNT */ /* Make sure non-charging ports are disabled */ for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { @@ -193,10 +125,3 @@ int board_set_active_charge_port(int port) return EC_SUCCESS; } - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} diff --git a/baseboard/intelrvp/chg_usb_pd_mecc_1_0.c b/baseboard/intelrvp/chg_usb_pd_mecc_1_0.c new file mode 100644 index 0000000000..1d18109f6f --- /dev/null +++ b/baseboard/intelrvp/chg_usb_pd_mecc_1_0.c @@ -0,0 +1,114 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel-RVP family-specific configuration */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "console.h" +#include "driver/ppc/sn5s330.h" +#include "gpio.h" +#include "hooks.h" +#include "system.h" +#include "tcpm/tcpci.h" +#include "usbc_ppc.h" + +#ifdef CONFIG_ZEPHYR +#include "intelrvp.h" +#endif /* CONFIG_ZEPHYR */ + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* Reset PD MCU */ +void board_reset_pd_mcu(void) +{ + /* Add code if TCPC chips need a reset */ +} + +static void baseboard_tcpc_init(void) +{ + int i; + + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* Enable PPC interrupts. */ + if (tcpc_aic_gpios[i].ppc_intr_handler) + gpio_enable_interrupt(tcpc_aic_gpios[i].ppc_alert); + + /* Enable TCPC interrupts. */ + if (tcpc_config[i].bus_type != EC_BUS_TYPE_EMBEDDED) + gpio_enable_interrupt(tcpc_aic_gpios[i].tcpc_alert); + } +} +DECLARE_HOOK(HOOK_INIT, baseboard_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +#ifndef CONFIG_ZEPHYR +void tcpc_alert_event(enum gpio_signal signal) +{ + int i; + + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* No alerts for embdeded TCPC */ + if (tcpc_config[i].bus_type == EC_BUS_TYPE_EMBEDDED) + continue; + + if (signal == tcpc_aic_gpios[i].tcpc_alert) { + schedule_deferred_pd_interrupt(i); + break; + } + } +} +#endif + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int i; + + /* Check which port has the ALERT line set */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* No alerts for embdeded TCPC */ + if (tcpc_config[i].bus_type == EC_BUS_TYPE_EMBEDDED) + continue; + + if (!gpio_get_level(tcpc_aic_gpios[i].tcpc_alert)) + status |= PD_STATUS_TCPC_ALERT_0 << i; + } + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (!tcpc_aic_gpios[port].ppc_intr_handler) + return 0; + + return !gpio_get_level(tcpc_aic_gpios[port].ppc_alert); +} + +/* PPC support routines */ +void ppc_interrupt(enum gpio_signal signal) +{ + int i; + + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (tcpc_aic_gpios[i].ppc_intr_handler && + signal == tcpc_aic_gpios[i].ppc_alert) { + tcpc_aic_gpios[i].ppc_intr_handler(i); + break; + } + } +} + +void board_charging_enable(int port, int enable) +{ + if (ppc_vbus_sink_enable(port, enable)) + CPRINTS("C%d: sink path %s failed", port, + enable ? "en" : "dis"); +} diff --git a/baseboard/intelrvp/ite_ec.c b/baseboard/intelrvp/ite_ec.c index 2a847e5132..76703d4f82 100644 --- a/baseboard/intelrvp/ite_ec.c +++ b/baseboard/intelrvp/ite_ec.c @@ -1,10 +1,11 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Intel BASEBOARD-RVP ITE EC specific configuration */ +#include "adc_chip.h" #include "common.h" #include "it83xx_pd.h" #include "keyboard_scan.h" @@ -13,49 +14,8 @@ #include "timer.h" #include "usb_pd_tcpm.h" -/* USB-C TPCP Configuration */ -const struct tcpc_config_t tcpc_config[] = { - [TYPE_C_PORT_0] = { - .bus_type = EC_BUS_TYPE_EMBEDDED, - /* TCPC is embedded within EC so no i2c config needed */ - .drv = &it83xx_tcpm_drv, -#ifdef CONFIG_INTEL_VIRTUAL_MUX - .usb23 = TYPE_C_PORT_0_USB2_NUM | (TYPE_C_PORT_0_USB3_NUM << 4), -#endif - }, -#ifdef HAS_TASK_PD_C1 - [TYPE_C_PORT_1] = { - .bus_type = EC_BUS_TYPE_EMBEDDED, - /* TCPC is embedded within EC so no i2c config needed */ - .drv = &it83xx_tcpm_drv, -#ifdef CONFIG_INTEL_VIRTUAL_MUX - .usb23 = TYPE_C_PORT_1_USB2_NUM | (TYPE_C_PORT_1_USB3_NUM << 4), -#endif - }, -#endif /* HAS_TASK_PD_C1 */ -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == CONFIG_USB_PD_PORT_MAX_COUNT); - -/* Reset PD MCU */ -void board_reset_pd_mcu(void) -{ - /* Not applicable for ITE TCPC */ -} - -uint16_t tcpc_get_alert_status(void) -{ - /* - * Since C0/C1 TCPC are embedded within EC, we don't need the - * PDCMD tasks. The (embedded) TCPC status since chip driver - * code handles its own interrupts and forward the correct - * events to the PD_C0 task. See it83xx/intc.c - */ - - return 0; -} - /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { .output_settle_us = 35, .debounce_down_us = 5 * MSEC, .debounce_up_us = 40 * MSEC, @@ -68,6 +28,39 @@ struct keyboard_scan_config keyscan_config = { }, }; +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SNS_AMBIENT] = { + .name = "ADC_TEMP_SNS_AMBIENT", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = ADC_TEMP_SNS_AMBIENT_CHANNEL, + }, + [ADC_TEMP_SNS_DDR] = { + .name = "ADC_TEMP_SNS_DDR", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = ADC_TEMP_SNS_DDR_CHANNEL, + }, + [ADC_TEMP_SNS_SKIN] = { + .name = "ADC_TEMP_SNS_SKIN", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = ADC_TEMP_SNS_SKIN_CHANNEL, + }, + [ADC_TEMP_SNS_VR] = { + .name = "ADC_TEMP_SNS_VR", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = ADC_TEMP_SNS_VR_CHANNEL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + /* * PWM HW channelx binding tachometer channelx for fan control. * Four tachometer input pins but two tachometer modules only, @@ -137,22 +130,24 @@ const struct pwm_t pwm_channels[] = { }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -#ifdef CONFIG_USBC_VCONN +#if defined(CONFIG_USBC_VCONN) && defined(CONFIG_USB_PD_TCPM_ITE_ON_CHIP) void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) { +#ifndef CONFIG_USBC_PPC_VCONN /* * Setting VCONN low by disabling the power switch before * enabling the VCONN on respective CC line */ gpio_set_level(tcpc_gpios[port].vconn.cc1_pin, - !tcpc_gpios[port].vconn.pin_pol); + !tcpc_gpios[port].vconn.pin_pol); gpio_set_level(tcpc_gpios[port].vconn.cc2_pin, - !tcpc_gpios[port].vconn.pin_pol); + !tcpc_gpios[port].vconn.pin_pol); if (enabled) gpio_set_level((cc_pin != USBPD_CC_PIN_1) ? - tcpc_gpios[port].vconn.cc2_pin : - tcpc_gpios[port].vconn.cc1_pin, - tcpc_gpios[port].vconn.pin_pol); + tcpc_gpios[port].vconn.cc2_pin : + tcpc_gpios[port].vconn.cc1_pin, + tcpc_gpios[port].vconn.pin_pol); +#endif } #endif diff --git a/baseboard/intelrvp/ite_ec.h b/baseboard/intelrvp/ite_ec.h index a09923dbb0..7ad147a5f9 100644 --- a/baseboard/intelrvp/ite_ec.h +++ b/baseboard/intelrvp/ite_ec.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,22 +8,18 @@ #ifndef __CROS_EC_ITE_EC_H #define __CROS_EC_ITE_EC_H -/* USB PD config */ -#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP -#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 - /* Optional feature - used by ITE */ #define CONFIG_IT83XX_FLASH_CLOCK_48MHZ +#define CONFIG_IT83XX_VCC_1P8V /* ADC channels */ -#define ADC_TEMP_SNS_AMBIENT_CHANNEL CHIP_ADC_CH13 -#define ADC_TEMP_SNS_DDR_CHANNEL CHIP_ADC_CH15 -#define ADC_TEMP_SNS_SKIN_CHANNEL CHIP_ADC_CH6 -#define ADC_TEMP_SNS_VR_CHANNEL CHIP_ADC_CH1 +#define ADC_TEMP_SNS_AMBIENT_CHANNEL CHIP_ADC_CH13 +#define ADC_TEMP_SNS_DDR_CHANNEL CHIP_ADC_CH15 +#define ADC_TEMP_SNS_SKIN_CHANNEL CHIP_ADC_CH6 +#define ADC_TEMP_SNS_VR_CHANNEL CHIP_ADC_CH1 #ifdef CONFIG_USBC_VCONN - #define CONFIG_USBC_VCONN_SWAP - /* delay to turn on/off vconn */ - #define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define CONFIG_USBC_VCONN_SWAP +/* delay to turn on/off vconn */ #endif #endif /* __CROS_EC_ITE_EC_H */ diff --git a/baseboard/intelrvp/led.c b/baseboard/intelrvp/led.c index 8e98f8e10f..10e4e08e63 100644 --- a/baseboard/intelrvp/led.c +++ b/baseboard/intelrvp/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -14,64 +14,87 @@ #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -#define GPIO_BAT_LED_RED_L GPIO_BAT_LED_GREEN_L -#define GPIO_PWR_LED_WHITE_L GPIO_AC_LED_GREEN_L - const int led_charge_lvl_1 = 5; const int led_charge_lvl_2 = 97; struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC } }, }; const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) +#ifdef CONFIG_ZEPHYR + gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(led_white_l), + LED_ON_LVL); +#else gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_ON_LVL); +#endif /* CONFIG_ZEPHYR */ else - /* LED_OFF and unsupported colors */ + /* LED_OFF and unsupported colors */ +#ifdef CONFIG_ZEPHYR + gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(led_white_l), + LED_OFF_LVL); +#else gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_OFF_LVL); +#endif /* CONFIG_ZEPHYR */ } void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_RED: +#ifdef CONFIG_ZEPHYR + gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(led_red_l), LED_ON_LVL); +#else gpio_set_level(GPIO_BAT_LED_RED_L, LED_ON_LVL); +#endif /* CONFIG_ZEPHYR */ break; case EC_LED_COLOR_AMBER: +#ifdef CONFIG_ZEPHYR + gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(led_red_l), LED_ON_LVL); +#else gpio_set_level(GPIO_BAT_LED_RED_L, LED_ON_LVL); +#endif /* CONFIG_ZEPHYR */ break; case EC_LED_COLOR_GREEN: +#ifdef CONFIG_ZEPHYR + gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(led_red_l), LED_OFF_LVL); +#else gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); +#endif /* CONFIG_ZEPHYR */ break; default: /* LED_OFF and other unsupported colors */ +#ifdef CONFIG_ZEPHYR + gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(led_red_l), LED_OFF_LVL); +#else gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); +#endif /* CONFIG_ZEPHYR */ break; } } diff --git a/baseboard/intelrvp/led_states.c b/baseboard/intelrvp/led_states.c index 5f8768bdd9..5fdbe0c67e 100644 --- a/baseboard/intelrvp/led_states.c +++ b/baseboard/intelrvp/led_states.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -15,15 +15,15 @@ #include "led_common.h" #include "led_states.h" -#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args) +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) static enum led_states led_get_state(void) { - int charge_lvl; + int charge_lvl; enum led_states new_state = LED_NUM_STATES; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Get percent charge */ charge_lvl = charge_get_percent(); /* Determine which charge state to use */ @@ -34,13 +34,13 @@ static enum led_states led_get_state(void) else new_state = STATE_CHARGING_FULL_CHARGE; break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { new_state = STATE_CHARGING_FULL_CHARGE; break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE /* and PWR_STATE_DISCHARGE_FULL */: + __fallthrough; + case LED_PWRS_DISCHARGE /* and LED_PWRS_DISCHARGE_FULL */: if (chipset_in_state(CHIPSET_STATE_ON)) new_state = STATE_DISCHARGE_S0; else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) @@ -48,17 +48,17 @@ static enum led_states led_get_state(void) else new_state = STATE_DISCHARGE_S5; break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: new_state = STATE_BATTERY_ERROR; break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: new_state = STATE_CHARGING_FULL_CHARGE; break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE) - new_state = STATE_FACTORY_TEST; - else - new_state = STATE_DISCHARGE_S0; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + new_state = STATE_DISCHARGE_S0; + break; + case LED_PWRS_FORCED_IDLE: + new_state = STATE_FACTORY_TEST; break; default: /* Other states don't alter LED behavior */ @@ -88,14 +88,14 @@ static void led_update_battery(void) ticks = 0; period = led_bat_state_table[led_state][LED_PHASE_0].time + - led_bat_state_table[led_state][LED_PHASE_1].time; - + led_bat_state_table[led_state][LED_PHASE_1].time; } /* If this state is undefined, turn the LED off */ if (period == 0) { CPRINTS("Undefined LED behavior for battery state %d," - "turning off LED", led_state); + "turning off LED", + led_state); led_set_color_battery(LED_OFF); return; } @@ -104,8 +104,8 @@ static void led_update_battery(void) * Determine which phase of the state table to use. The phase is * determined if it falls within first phase time duration. */ - phase = ticks < led_bat_state_table[led_state][LED_PHASE_0].time ? - 0 : 1; + phase = ticks < led_bat_state_table[led_state][LED_PHASE_0].time ? 0 : + 1; ticks = (ticks + 1) % period; /* Set the color for the given state and phase */ @@ -115,7 +115,7 @@ static void led_update_battery(void) static enum pwr_led_states pwr_led_get_state(void) { if (extpower_is_present()) { - if (charge_get_state() == PWR_STATE_CHARGE_NEAR_FULL) + if (led_pwr_get_state() == LED_PWRS_CHARGE_NEAR_FULL) return PWR_LED_STATE_OFF; else return PWR_LED_STATE_ON; @@ -141,14 +141,14 @@ static void led_update_power(void) ticks = 0; period = led_pwr_state_table[led_state][LED_PHASE_0].time + - led_pwr_state_table[led_state][LED_PHASE_1].time; - + led_pwr_state_table[led_state][LED_PHASE_1].time; } /* If this state is undefined, turn the LED off */ if (period == 0) { CPRINTS("Undefined LED behavior for power state %d," - "turning off LED", led_state); + "turning off LED", + led_state); led_set_color_power(LED_OFF); return; } @@ -157,8 +157,8 @@ static void led_update_power(void) * Determine which phase of the state table to use. The phase is * determined if it falls within first phase time duration. */ - phase = ticks < led_pwr_state_table[led_state][LED_PHASE_0].time ? - 0 : 1; + phase = ticks < led_pwr_state_table[led_state][LED_PHASE_0].time ? 0 : + 1; ticks = (ticks + 1) % period; /* Set the color for the given state and phase */ diff --git a/baseboard/intelrvp/led_states.h b/baseboard/intelrvp/led_states.h index 907ff5c8b8..3b584c6efc 100644 --- a/baseboard/intelrvp/led_states.h +++ b/baseboard/intelrvp/led_states.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,19 +10,15 @@ #include "ec_commands.h" -#define LED_INDEFINITE UINT8_MAX -#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) -#define LED_OFF EC_LED_COLOR_COUNT +#define LED_INDEFINITE UINT8_MAX +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +#define LED_OFF EC_LED_COLOR_COUNT /* * All LED states should have one phase defined, * and an additional phase can be defined for blinking */ -enum led_phase { - LED_PHASE_0, - LED_PHASE_1, - LED_NUM_PHASES -}; +enum led_phase { LED_PHASE_0, LED_PHASE_1, LED_NUM_PHASES }; /* * STATE_CHARGING_LVL_1 is when 0 <= charge_percentage < led_charge_level_1 @@ -51,10 +47,8 @@ struct led_descriptor { uint8_t time; }; - /* Charging LED state table - defined in board's led.c */ -extern struct led_descriptor - led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES]; +extern struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES]; /* Charging LED state level 1 - defined in board's led.c */ extern const int led_charge_lvl_1; @@ -71,8 +65,8 @@ enum pwr_led_states { }; /* Power LED state table - defined in board's led.c */ -extern const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES]; +extern const struct led_descriptor led_pwr_state_table[PWR_LED_NUM_STATES] + [LED_NUM_PHASES]; /** * Set battery LED color - defined in board's led.c diff --git a/baseboard/intelrvp/mchp_ec.c b/baseboard/intelrvp/mchp_ec.c new file mode 100644 index 0000000000..7ede17569b --- /dev/null +++ b/baseboard/intelrvp/mchp_ec.c @@ -0,0 +1,88 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel BASEBOARD-RVP MCHP EC specific configuration */ + +#include "adc_chip.h" +#include "common.h" +#include "keyboard_scan.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "timer.h" +#include "usb_pd_tcpm.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* + * F3 key scan cycle completed but scan input is not + * charging to logic high when EC start scan next + * column for "T" key, so we set .output_settle_us + * to 80 us from 50 us. + */ + .output_settle_us = 80, + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SNS_AMBIENT] = { + .name = "ADC_TEMP_SNS_AMBIENT", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = ADC_TEMP_SNS_AMBIENT_CHANNEL, + }, + [ADC_TEMP_SNS_DDR] = { + .name = "ADC_TEMP_SNS_DDR", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = ADC_TEMP_SNS_DDR_CHANNEL, + }, + [ADC_TEMP_SNS_SKIN] = { + .name = "ADC_TEMP_SNS_SKIN", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = ADC_TEMP_SNS_SKIN_CHANNEL, + }, + [ADC_TEMP_SNS_VR] = { + .name = "ADC_TEMP_SNS_VR", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = ADC_TEMP_SNS_VR_CHANNEL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* + * TODO - Fan and tach table. + * MCHP MEC1322 and MEC170x have fan speed controller(s) + * whereas MEC152x only has multiple TACH and PWM modules. + * MEC152x fan control will require a firmware layer that uses + * specified TACH and PWM modules. + */ + +/* PWM channels */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { +#ifdef CHIP_FAMILY_MEC172X + .channel = PWM_HW_CH_0, +#else + .channel = PWM_HW_CH_4, +#endif + .flags = PWM_CONFIG_HAS_RPM_MODE, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/baseboard/intelrvp/mchp_ec.h b/baseboard/intelrvp/mchp_ec.h new file mode 100644 index 0000000000..ec1e47c030 --- /dev/null +++ b/baseboard/intelrvp/mchp_ec.h @@ -0,0 +1,26 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel BASEBOARD-RVP MCHP EC specific configuration */ + +#ifndef __CROS_EC_MCHP_EC_H +#define __CROS_EC_MCHP_EC_H + +/* ADC channels */ +#define ADC_TEMP_SNS_AMBIENT_CHANNEL CHIP_ADC_CH7 +#define ADC_TEMP_SNS_DDR_CHANNEL CHIP_ADC_CH4 +#define ADC_TEMP_SNS_SKIN_CHANNEL CHIP_ADC_CH3 +#define ADC_TEMP_SNS_VR_CHANNEL CHIP_ADC_CH1 + +/* + * ADC maximum voltage is a board level configuration. + * MEC152x ADC can use an external 3.0 or 3.3V reference with + * maximum values up to the reference voltage. + * The ADC maximum voltage depends upon the external reference + * voltage connected to MEC152x. + */ +#define ADC_MAX_MVOLT 3000 + +#endif /* __CROS_EC_MCHP_EC_H */ diff --git a/baseboard/intelrvp/npcx_ec.c b/baseboard/intelrvp/npcx_ec.c new file mode 100644 index 0000000000..a90442e8b1 --- /dev/null +++ b/baseboard/intelrvp/npcx_ec.c @@ -0,0 +1,78 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel BASEBOARD-RVP NPCX EC specific configuration */ + +#include "adc_chip.h" +#include "fan_chip.h" +#include "keyboard_scan.h" +#include "pwm_chip.h" +#include "time.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + .output_settle_us = 35, + .debounce_down_us = 5 * MSEC, + .debounce_up_us = 40 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SNS_AMBIENT] = { + .name = "ADC_TEMP_SNS_AMBIENT", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .input_ch = ADC_TEMP_SNS_AMBIENT_CHANNEL, + }, + [ADC_TEMP_SNS_DDR] = { + .name = "ADC_TEMP_SNS_DDR", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .input_ch = ADC_TEMP_SNS_DDR_CHANNEL, + }, + [ADC_TEMP_SNS_SKIN] = { + .name = "ADC_TEMP_SNS_SKIN", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .input_ch = ADC_TEMP_SNS_SKIN_CHANNEL, + }, + [ADC_TEMP_SNS_VR] = { + .name = "ADC_TEMP_SNS_VR", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .input_ch = ADC_TEMP_SNS_VR_CHANNEL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* PWM configuration */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { + .channel = PWN_FAN_CHANNEL, + .flags = 0, + .freq = 30000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); diff --git a/baseboard/intelrvp/npcx_ec.h b/baseboard/intelrvp/npcx_ec.h new file mode 100644 index 0000000000..5fe6aa9786 --- /dev/null +++ b/baseboard/intelrvp/npcx_ec.h @@ -0,0 +1,38 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel BASEBOARD-RVP NPCX EC specific configuration */ + +#ifndef __CROS_EC_NPCX_EC_H +#define __CROS_EC_NPCX_EC_H + +#if !defined(__ASSEMBLER__) + +enum mft_channel { + MFT_CH_0 = 0, + /* Number of MFT channels */ + MFT_CH_COUNT, +}; + +#endif /* __ASSEMBLER__ */ + +/* ADC channels */ +#define ADC_MAX_MVOLT ADC_MAX_VOLT +#define ADC_TEMP_SNS_AMBIENT_CHANNEL NPCX_ADC_CH3 +#define ADC_TEMP_SNS_DDR_CHANNEL NPCX_ADC_CH4 +#define ADC_TEMP_SNS_SKIN_CHANNEL NPCX_ADC_CH2 +#define ADC_TEMP_SNS_VR_CHANNEL NPCX_ADC_CH1 + +/* KSO2 is inverted */ +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV + +/* Fan */ +#define CONFIG_PWM +#define PWN_FAN_CHANNEL 3 + +/* GPIO64/65 are used as UART pins. */ +#define NPCX_UART_MODULE2 1 + +#endif /* __CROS_EC_NPCX_EC_H */ diff --git a/baseboard/intelrvp/retimer.c b/baseboard/intelrvp/retimer.c deleted file mode 100644 index c64ad64bcb..0000000000 --- a/baseboard/intelrvp/retimer.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel BASEBOARD-RVP Retimer specific configuration */ - -#include "bb_retimer.h" -#include "compile_time_macros.h" -#include "common.h" - -/* USB Retimers configuration */ -#ifdef CONFIG_USBC_RETIMER_INTEL_BB -const struct bb_usb_control bb_controls[] = { - [TYPE_C_PORT_0] = { - .usb_ls_en_gpio = GPIO_USB_C0_LS_EN, - .retimer_rst_gpio = GPIO_USB_C0_RETIMER_RST, - }, -#ifdef HAS_TASK_PD_C1 - [TYPE_C_PORT_1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RETIMER_RST, - }, -#endif /* HAS_TASK_PD_C1 */ -}; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == CONFIG_USB_PD_PORT_MAX_COUNT); - -#endif /* CONFIG_USBC_RETIMER_INTEL_BB */ diff --git a/baseboard/intelrvp/usb_mux.c b/baseboard/intelrvp/usb_mux.c deleted file mode 100644 index 644ae1735c..0000000000 --- a/baseboard/intelrvp/usb_mux.c +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel BASEBOARD-RVP USB MUX specific configuration */ - -#include "common.h" -#include "anx7440.h" -#include "bb_retimer.h" -#include "timer.h" -#include "usb_mux.h" - -#ifdef CONFIG_USBC_RETIMER_INTEL_BB -struct usb_mux usbc0_retimer = { - .usb_port = TYPE_C_PORT_0, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT0_BB_RETIMER, - .i2c_addr_flags = I2C_PORT0_BB_RETIMER_ADDR, -}; -#ifdef HAS_TASK_PD_C1 -struct usb_mux usbc1_retimer = { - .usb_port = TYPE_C_PORT_1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT1_BB_RETIMER, - .i2c_addr_flags = I2C_PORT1_BB_RETIMER_ADDR, -}; -#endif /* HAS_TASK_PD_C1 */ -#endif - -/* USB muxes Configuration */ -#ifdef CONFIG_USB_MUX_VIRTUAL -const struct usb_mux usb_muxes[] = { - [TYPE_C_PORT_0] = { - .usb_port = TYPE_C_PORT_0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, -#ifdef CONFIG_USBC_RETIMER_INTEL_BB - .next_mux = &usbc0_retimer, -#endif - }, -#ifdef HAS_TASK_PD_C1 - [TYPE_C_PORT_1] = { - .usb_port = TYPE_C_PORT_1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, -#ifdef CONFIG_USBC_RETIMER_INTEL_BB - .next_mux = &usbc1_retimer, -#endif - }, -#endif /* HAS_TASK_PD_C1 */ -}; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == CONFIG_USB_PD_PORT_MAX_COUNT); -#endif /* CONFIG_USB_MUX_VIRTUAL */ - -#ifdef CONFIG_USB_MUX_ANX7440 -const struct usb_mux usb_muxes[] = { - [TYPE_C_PORT_0] = { - .usb_port = TYPE_C_PORT_0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = I2C_ADDR_USB_MUX0_FLAGS, - .driver = &anx7440_usb_mux_driver, -#ifdef CONFIG_USBC_RETIMER_INTEL_BB - .next_mux = &usbc0_retimer, -#endif - }, -#ifdef HAS_TASK_PD_C1 - [TYPE_C_PORT_1] = { - .usb_port = TYPE_C_PORT_1, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = I2C_ADDR_USB_MUX1_FLAGS, - .driver = &anx7440_usb_mux_driver, -#ifdef CONFIG_USBC_RETIMER_INTEL_BB - .next_mux = &usbc1_retimer, -#endif - }, -#endif /* HAS_TASK_PD_C1 */ -}; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == CONFIG_USB_PD_PORT_MAX_COUNT); -#endif /* CONFIG_USB_MUX_ANX7440 */ diff --git a/baseboard/intelrvp/usb_pd_policy.c b/baseboard/intelrvp/usb_pd_policy.c deleted file mode 100644 index d0ca3d6025..0000000000 --- a/baseboard/intelrvp/usb_pd_policy.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "charge_manager.h" -#include "console.h" -#include "gpio.h" -#include "system.h" -#include "usb_mux.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -int pd_set_power_supply_ready(int port) -{ - /* Disable charging */ - board_charging_enable(port, 0); - - /* Provide VBUS */ - board_vbus_enable(port, 1); - - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; /* we are ready */ -} - -void pd_power_supply_reset(int port) -{ - /* Disable VBUS */ - board_vbus_enable(port, 0); - - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -int pd_check_vconn_swap(int port) -{ - /* Only allow vconn swap if PP5000 rail is enabled */ - return gpio_get_level(GPIO_EN_PP5000); -} - -__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) -{ - board_set_vbus_source_current_limit(port, rp); -} diff --git a/baseboard/intelrvp/usb_pd_policy_mecc_1_0.c b/baseboard/intelrvp/usb_pd_policy_mecc_1_0.c new file mode 100644 index 0000000000..303d176405 --- /dev/null +++ b/baseboard/intelrvp/usb_pd_policy_mecc_1_0.c @@ -0,0 +1,76 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "console.h" +#include "gpio.h" +#include "system.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_ppc.h" + +#ifdef CONFIG_ZEPHYR +#include "intelrvp.h" +#endif /* CONFIG_ZEPHYR */ + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + prev_en = board_vbus_source_enabled(port); + + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_check_vconn_swap(int port) +{ + /* Only allow vconn swap if PP3300 rail is enabled */ + return gpio_get_level(GPIO_EN_PP3300_A); +} + +int pd_snk_is_vbus_provided(int port) +{ + return ppc_is_vbus_present(port); +} + +int board_vbus_source_enabled(int port) +{ + if (is_typec_port(port)) + return ppc_is_sourcing_vbus(port); + return 0; +} diff --git a/baseboard/ite_evb/baseboard.c b/baseboard/ite_evb/baseboard.c index 0bd537ef4f..f2077197ff 100644 --- a/baseboard/ite_evb/baseboard.c +++ b/baseboard/ite_evb/baseboard.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -25,6 +25,8 @@ #include "timer.h" #include "uart.h" #include "util.h" + +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" #if defined(CONFIG_FANS) || defined(CONFIG_PWM) @@ -42,8 +44,10 @@ const struct fan_rpm fan_rpm_0 = { }; const struct fan_t fans[] = { - { .conf = &fan_conf_0, - .rpm = &fan_rpm_0, }, + { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, }; BUILD_ASSERT(ARRAY_SIZE(fans) == CONFIG_FANS); @@ -106,9 +110,8 @@ const struct fan_tach_t fan_tach[] = { BUILD_ASSERT(ARRAY_SIZE(fan_tach) == PWM_HW_CH_TOTAL); #endif /* defined(CONFIG_FANS) || defined(CONFIG_PWM) */ -#if defined(CONFIG_KEYBOARD_BOARD_CONFIG) /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { .output_settle_us = 35, .debounce_down_us = 5 * MSEC, .debounce_up_us = 40 * MSEC, @@ -120,16 +123,13 @@ struct keyboard_scan_config keyscan_config = { 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ }, }; -#endif #if defined(CONFIG_SPI_FLASH_PORT) /* SPI devices */ const struct spi_device_t spi_devices[] = { - [CONFIG_SPI_FLASH_PORT] = { - .port = CONFIG_SPI_FLASH_PORT, - .div = 0, - .gpio_cs = -1 - }, + [CONFIG_SPI_FLASH_PORT] = { .port = CONFIG_SPI_FLASH_PORT, + .div = 0, + .gpio_cs = -1 }, }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); #endif @@ -141,9 +141,8 @@ static void board_init(void) DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); /* Wake-up pins for hibernate */ -const enum gpio_signal hibernate_wake_pins[] = { - GPIO_POWER_BUTTON_L, GPIO_LID_OPEN -}; +const enum gpio_signal hibernate_wake_pins[] = { GPIO_POWER_BUTTON_L, + GPIO_LID_OPEN }; const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* diff --git a/baseboard/ite_evb/baseboard.h b/baseboard/ite_evb/baseboard.h index 34c4fee278..5140e22962 100644 --- a/baseboard/ite_evb/baseboard.h +++ b/baseboard/ite_evb/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,10 +13,11 @@ #define CONFIG_BOARD_VERSION_GPIO #define CONFIG_FANS 1 #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_IT83XX_ENABLE_MOUSE_DEVICE #define CONFIG_IT83XX_SMCLK2_ON_GPC7 -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_IT83XX_VCC_3P3V + #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_LOW_POWER_IDLE #define CONFIG_LOW_POWER_S0 @@ -26,15 +27,14 @@ #define CONFIG_POWER_BUTTON #define CONFIG_PWM /* Use CS0 of SSPI */ -#define CONFIG_SPI_MASTER +#define CONFIG_SPI_CONTROLLER #define CONFIG_SPI_FLASH_PORT 0 #define CONFIG_UART_HOST -#define CONFIG_HOSTCMD_LPC +#define CONFIG_HOST_INTERFACE_LPC /* Optional console commands */ #define CONFIG_CMD_FLASH #define CONFIG_CMD_SCRATCHPAD -#define CONFIG_CMD_STACKOVERFLOW /* Debug */ #undef CONFIG_CMD_FORCETIME diff --git a/baseboard/ite_evb/build.mk b/baseboard/ite_evb/build.mk index 77352145ee..38a49ff8b6 100644 --- a/baseboard/ite_evb/build.mk +++ b/baseboard/ite_evb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -7,4 +7,4 @@ # baseboard-y=baseboard.o -baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_pdo.o diff --git a/baseboard/ite_evb/usb_pd_pdo.c b/baseboard/ite_evb/usb_pd_pdo.c new file mode 100644 index 0000000000..0da735e458 --- /dev/null +++ b/baseboard/ite_evb/usb_pd_pdo.c @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +#define PDO_FIXED_FLAGS \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_UNCONSTRAINED | \ + PDO_FIXED_COMM_CAP) + +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_BATT(4500, 14000, 10000), + PDO_VAR(4500, 14000, 3000), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/baseboard/ite_evb/usb_pd_pdo.h b/baseboard/ite_evb/usb_pd_pdo.h new file mode 100644 index 0000000000..4b19ca32d3 --- /dev/null +++ b/baseboard/ite_evb/usb_pd_pdo.h @@ -0,0 +1,20 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BASEBOARD_ITE_EVB_USB_PD_PDO_H +#define __CROS_EC_BASEBOARD_ITE_EVB_USB_PD_PDO_H + +#include "config.h" +#include "stdint.h" + +/* Threshold voltage of VBUS provided (mV) */ +#define PD_VBUS_PROVIDED_THRESHOLD 3900 + +extern const uint32_t pd_src_pdo[1]; +extern const int pd_src_pdo_cnt; +extern const uint32_t pd_snk_pdo[3]; +extern const int pd_snk_pdo_cnt; + +#endif /* __CROS_EC_BASEBOARD_ITE_EVB_USB_PD_PDO_H */ diff --git a/baseboard/ite_evb/usb_pd_policy.c b/baseboard/ite_evb/usb_pd_policy.c index 59f3da13f5..c7d10787bb 100644 --- a/baseboard/ite_evb/usb_pd_policy.c +++ b/baseboard/ite_evb/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,8 +6,8 @@ /* Shared USB-C policy for ite_evb baseboard */ #include "adc.h" -#include "config.h" #include "common.h" +#include "config.h" #include "console.h" #include "gpio.h" #include "hooks.h" @@ -16,32 +16,12 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" +#include "usb_pd_pdo.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -/* ---------------- Power Data Objects (PDOs) ----------------- */ -#ifdef CONFIG_USB_PD_CUSTOM_PDO -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_UNCONSTRAINED | PDO_FIXED_COMM_CAP) - -/* Threshold voltage of VBUS provided (mV) */ -#define PD_VBUS_PROVIDED_THRESHOLD 3900 - -const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); - -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), - PDO_BATT(4500, 14000, 10000), - PDO_VAR(4500, 14000, 3000), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); -#endif +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_is_max_request_allowed(void) { @@ -82,7 +62,6 @@ void pd_power_supply_reset(int port) board_pd_vbus_ctrl(port, 0); } - __override int pd_check_data_swap(int port, enum pd_data_role data_role) { /* Always allow data swap: we can be DFP or UFP for USB */ @@ -127,7 +106,7 @@ __override void svdm_exit_dp_mode(int port) } __override int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) + uint32_t **rpayload) { /* Return length 0, means nothing needn't tx */ return 0; diff --git a/baseboard/kalista/baseboard.c b/baseboard/kalista/baseboard.c index 6592033c83..7972dcdcb7 100644 --- a/baseboard/kalista/baseboard.c +++ b/baseboard/kalista/baseboard.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,23 +6,23 @@ /* Kalista baseboard configuration */ #include "adc.h" -#include "adc_chip.h" #include "baseboard.h" #include "battery.h" #include "bd99992gw.h" #include "board_config.h" #include "button.h" +#include "cec.h" #include "chipset.h" #include "console.h" #include "cros_board_info.h" +#include "driver/cec/bitbang.h" #include "driver/pmic_tps650x30.h" -#include "driver/temp_sensor/tmp432.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" +#include "driver/temp_sensor/tmp432.h" #include "espi.h" #include "extpower.h" -#include "espi.h" #include "fan.h" #include "fan_chip.h" #include "gpio.h" @@ -49,8 +49,8 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static uint8_t board_version; static uint32_t oem; @@ -89,6 +89,7 @@ void vbus0_evt(enum gpio_signal signal) task_wake(TASK_ID_PD_C0); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Hibernate wake configuration */ @@ -100,14 +101,15 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* ADC channels */ const struct adc_t adc_channels[] = { /* Vbus sensing (1/10 voltage divider). */ - [ADC_VBUS] = {"VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* TODO: Verify fan control and mft */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_FAN_PWR_EN, }; @@ -124,19 +126,48 @@ const struct fan_t fans[] = { BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); -const struct i2c_port_t i2c_ports[] = { - {"tcpc", I2C_PORT_TCPC0, 400, GPIO_I2C0_0_SCL, GPIO_I2C0_0_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_I2C0_1_SCL, GPIO_I2C0_1_SDA}, - {"backlight", I2C_PORT_BACKLIGHT, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"pmic", I2C_PORT_PMIC, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"thermal", I2C_PORT_THERMAL, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "tcpc", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C0_0_SCL, + .sda = GPIO_I2C0_0_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_I2C0_1_SCL, + .sda = GPIO_I2C0_1_SDA }, + { .name = "backlight", + .port = I2C_PORT_BACKLIGHT, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "pmic", + .port = I2C_PORT_PMIC, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "thermal", + .port = I2C_PORT_THERMAL, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + /* TCPC mux configuration */ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { /* Alert is active-low, push-pull */ @@ -157,12 +188,15 @@ static int ps8751_tune_mux(const struct usb_mux *me) return EC_SUCCESS; } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .board_init = &ps8751_tune_mux, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .board_init = &ps8751_tune_mux, + }, }, }; @@ -204,14 +238,15 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); uint16_t tcpc_get_alert_status(void) { if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL) && - gpio_get_level(GPIO_USB_C0_PD_RST_ODL)) + gpio_get_level(GPIO_USB_C0_PD_RST_ODL)) return PD_STATUS_TCPC_ALERT_0; return 0; } @@ -224,10 +259,10 @@ uint16_t tcpc_get_alert_status(void) * src/mainboard/google/${board}/acpi/dptf.asl */ const struct temp_sensor_t temp_sensors[] = { - {"TMP431_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_LOCAL}, - {"TMP431_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE1}, + { "TMP431_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_LOCAL }, + { "TMP431_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE1 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -235,14 +270,18 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); * Thermal limits for each temp sensor. All temps are in degrees K. Must be in * same order as enum temp_sensor_id. To always ignore any temp, use 0. */ +static const int temp_fan_off = C_TO_K(30); +static const int temp_fan_max = C_TO_K(55); struct ec_thermal_config thermal_params[] = { /* {Twarn, Thigh, Thalt}, * {Twarn, Thigh, X }, * fan_off, fan_max */ - {{0, C_TO_K(80), C_TO_K(81)}, {0, C_TO_K(78), 0}, - C_TO_K(4), C_TO_K(76)}, /* TMP431_Internal */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* TMP431_Sensor_1 */ + { { 0, C_TO_K(80), C_TO_K(81) }, + { 0, C_TO_K(78), 0 }, + temp_fan_off, + temp_fan_max }, /* TMP431_Internal */ + { { 0, 0, 0 }, { 0, 0, 0 }, 0, 0 }, /* TMP431_Sensor_1 */ }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -411,34 +450,38 @@ int64_t get_time_dsw_pwrok(void) } const struct pwm_t pwm_channels[] = { - [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, [PWM_CH_LED_BLUE] = { 5, PWM_CONFIG_DSLEEP, 100 }, - [PWM_CH_FAN] = {4, PWM_CONFIG_OPEN_DRAIN, 25000}, + [PWM_CH_FAN] = { 4, PWM_CONFIG_OPEN_DRAIN, 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -struct fan_step { - int on; - int off; - int rpm; -}; - -/* Note: Do not make the fan on/off point equal to 0 or 100 */ -static const struct fan_step fan_table0[] = { - {.on = 0, .off = 5, .rpm = 0}, - {.on = 30, .off = 5, .rpm = 2180}, - {.on = 49, .off = 46, .rpm = 2680}, - {.on = 53, .off = 50, .rpm = 3300}, - {.on = 58, .off = 54, .rpm = 3760}, - {.on = 63, .off = 59, .rpm = 4220}, - {.on = 68, .off = 64, .rpm = 4660}, - {.on = 75, .off = 70, .rpm = 4900}, +static const struct fan_step_1_1 fan_table0[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(30), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(37), + .rpm = 2180 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(36), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(41), + .rpm = 2680 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(43), + .rpm = 3300 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(45), + .rpm = 3760 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(47), + .rpm = 4220 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(49), + .rpm = 4660 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(55), + .rpm = 4900 }, }; -/* All fan tables must have the same number of levels */ #define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) -static const struct fan_step *fan_table = fan_table0; - +static const struct fan_step_1_1 *fan_table = fan_table0; static void cbi_init(void) { @@ -459,8 +502,8 @@ DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); static void setup_bj(void) { - enum bj_adapter bj = (BJ_ADAPTER_135W_MASK & (1 << sku)) ? - BJ_135W_19V : BJ_90W_19V; + enum bj_adapter bj = (BJ_ADAPTER_135W_MASK & (1 << sku)) ? BJ_135W_19V : + BJ_90W_19V; gpio_set_level(GPIO_U22_90W, bj == BJ_90W_19V); } @@ -474,43 +517,8 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -int fan_percent_to_rpm(int fan, int pct) +int fan_percent_to_rpm(int fan, int temp_ratio) { - static int current_level; - static int previous_pct; - int i; - - /* - * Compare the pct and previous pct, we have the three paths : - * 1. decreasing path. (check the off point) - * 2. increasing path. (check the on point) - * 3. invariant path. (return the current RPM) - */ - if (pct < previous_pct) { - for (i = current_level; i >= 0; i--) { - if (pct <= fan_table[i].off) - current_level = i - 1; - else - break; - } - } else if (pct > previous_pct) { - for (i = current_level + 1; i < NUM_FAN_LEVELS; i++) { - if (pct >= fan_table[i].on) - current_level = i; - else - break; - } - } - - if (current_level < 0) - current_level = 0; - - previous_pct = pct; - - if (fan_table[current_level].rpm != - fan_get_rpm_target(FAN_CH(fan))) - cprints(CC_THERMAL, "Setting fan RPM to %d", - fan_table[current_level].rpm); - - return fan_table[current_level].rpm; + return temp_ratio_to_rpm_hysteresis(fan_table, NUM_FAN_LEVELS, fan, + temp_ratio, NULL); } diff --git a/baseboard/kalista/baseboard.h b/baseboard/kalista/baseboard.h index ede6388b39..fc40207526 100644 --- a/baseboard/kalista/baseboard.h +++ b/baseboard/kalista/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,7 +12,7 @@ * Allow dangerous commands. * TODO: Remove this config before production. */ -#undef CONFIG_SYSTEM_UNLOCKED +#undef CONFIG_SYSTEM_UNLOCKED #define CONFIG_USB_PD_COMM_LOCKED /* EC */ @@ -21,18 +21,19 @@ #define CONFIG_BOARD_HAS_RTC_RESET #define CONFIG_CRC8 #define CONFIG_CEC -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CEC_BITBANG +#define CONFIG_CBI_EEPROM #define CONFIG_DEDICATED_RECOVERY_BUTTON #define CONFIG_EMULATED_SYSRQ #define CONFIG_LED_COMMON -#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_USE_HOST_EVENT #define CONFIG_DPTF -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#undef CONFIG_LID_SWITCH +#define CONFIG_I2C_CONTROLLER +#undef CONFIG_LID_SWITCH #define CONFIG_POWER_BUTTON_IGNORE_LID #define CONFIG_PWM #define CONFIG_LTO @@ -47,15 +48,13 @@ #define WIRELESS_GPIO_WLAN_POWER GPIO_PP3300_DX_WLAN #define WIRELESS_GPIO_WWAN GPIO_PP3300_DX_LTE #define CEC_GPIO_OUT GPIO_CEC_OUT -#define CEC_GPIO_IN GPIO_CEC_IN +#define CEC_GPIO_IN GPIO_CEC_IN #define CEC_GPIO_PULL_UP GPIO_CEC_PULL_UP #define CONFIG_FANS 1 #define CONFIG_FAN_RPM_CUSTOM #define CONFIG_THROTTLE_AP #define CONFIG_CHIPSET_CAN_THROTTLE #define CONFIG_PWM -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY /* EC console commands */ #define CONFIG_CMD_BUTTON @@ -65,13 +64,14 @@ #define CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET #define CONFIG_CHIPSET_HAS_PRE_INIT_CALLBACK #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD #define CONFIG_HOSTCMD_PD_CONTROL #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#undef CONFIG_EXTPOWER_DEBOUNCE_MS #define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 @@ -106,20 +106,20 @@ #define USB_PORT_COUNT 4 /* Optional feature to configure npcx chip */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ -#define NPCX_TACH_SEL2 1 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ +#define NPCX_TACH_SEL2 1 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ /* I2C ports */ -#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT0_1 -#define I2C_PORT_BACKLIGHT NPCX_I2C_PORT1 -#define I2C_PORT_PMIC NPCX_I2C_PORT2 -#define I2C_PORT_THERMAL NPCX_I2C_PORT3 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT0_1 +#define I2C_PORT_BACKLIGHT NPCX_I2C_PORT1 +#define I2C_PORT_PMIC NPCX_I2C_PORT2 +#define I2C_PORT_THERMAL NPCX_I2C_PORT3 /* I2C addresses */ -#define I2C_ADDR_TCPC0_FLAGS 0x0b -#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_ADDR_TCPC0_FLAGS 0x0b +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* Verify and jump to RW image on boot */ #define CONFIG_VBOOT_EFS @@ -141,23 +141,22 @@ * end of RW_A and RW_B, respectively. */ #define CONFIG_RW_B -#define CONFIG_RW_B_MEM_OFF CONFIG_RO_MEM_OFF -#undef CONFIG_RO_SIZE -#define CONFIG_RO_SIZE (CONFIG_FLASH_SIZE / 4) -#undef CONFIG_RW_SIZE -#define CONFIG_RW_SIZE CONFIG_RO_SIZE -#define CONFIG_RW_A_STORAGE_OFF CONFIG_RW_STORAGE_OFF -#define CONFIG_RW_B_STORAGE_OFF (CONFIG_RW_A_STORAGE_OFF + \ - CONFIG_RW_SIZE) -#define CONFIG_RW_A_SIGN_STORAGE_OFF (CONFIG_RW_A_STORAGE_OFF + \ - CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) -#define CONFIG_RW_B_SIGN_STORAGE_OFF (CONFIG_RW_B_STORAGE_OFF + \ - CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) +#define CONFIG_RW_B_MEM_OFF CONFIG_RO_MEM_OFF +#undef CONFIG_RO_SIZE +#define CONFIG_RO_SIZE (CONFIG_FLASH_SIZE_BYTES / 4) +#undef CONFIG_RW_SIZE +#define CONFIG_RW_SIZE CONFIG_RO_SIZE +#define CONFIG_RW_A_STORAGE_OFF CONFIG_RW_STORAGE_OFF +#define CONFIG_RW_B_STORAGE_OFF (CONFIG_RW_A_STORAGE_OFF + CONFIG_RW_SIZE) +#define CONFIG_RW_A_SIGN_STORAGE_OFF \ + (CONFIG_RW_A_STORAGE_OFF + CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) +#define CONFIG_RW_B_SIGN_STORAGE_OFF \ + (CONFIG_RW_B_STORAGE_OFF + CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) #undef CONFIG_EC_PROTECTED_STORAGE_SIZE -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE #undef CONFIG_EC_WRITABLE_STORAGE_SIZE -#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE #define CONFIG_RWSIG #define CONFIG_RWSIG_TYPE_RWSIG @@ -183,15 +182,12 @@ enum charge_port { }; enum temp_sensor_id { - TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ - TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ + TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ + TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ TEMP_SENSOR_COUNT }; -enum adc_channel { - ADC_VBUS, - ADC_CH_COUNT -}; +enum adc_channel { ADC_VBUS, ADC_CH_COUNT }; enum pwm_channel { PWM_CH_LED_RED, @@ -213,6 +209,8 @@ enum mft_channel { MFT_CH_COUNT }; +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + enum OEM_ID { OEM_KARMA = 7, /* Number of OEM IDs */ @@ -224,11 +222,10 @@ enum OEM_ID { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Board specific handlers */ void board_reset_pd_mcu(void); diff --git a/baseboard/kalista/build.mk b/baseboard/kalista/build.mk index e64b6a2d71..6bb55b2023 100644 --- a/baseboard/kalista/build.mk +++ b/baseboard/kalista/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,4 +8,4 @@ baseboard-y=baseboard.o baseboard-y+=led.o -baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o \ No newline at end of file +baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_pdo.o diff --git a/baseboard/kalista/led.c b/baseboard/kalista/led.c index e04eecf5e3..c72ce84bb0 100644 --- a/baseboard/kalista/led.c +++ b/baseboard/kalista/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -15,7 +15,7 @@ #include "timer.h" #include "util.h" -const enum ec_led_id supported_led_ids[] = {EC_LED_ID_POWER_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); enum led_color { @@ -76,9 +76,9 @@ static int set_color(enum ec_led_id id, enum led_color color, int duty) } } -#define LED_PULSE_US (2 * SECOND) +#define LED_PULSE_US (2 * SECOND) /* 40 msec for nice and smooth transition. */ -#define LED_PULSE_TICK_US (40 * MSEC) +#define LED_PULSE_TICK_US (40 * MSEC) /* When pulsing is enabled, brightness is incremented by every * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented @@ -181,7 +181,7 @@ void led_critical(void) set_color(EC_LED_ID_POWER_LED, LED_RED, 100); } -static int command_led(int argc, char **argv) +static int command_led(int argc, const char **argv) { enum ec_led_id id = EC_LED_ID_POWER_LED; diff --git a/baseboard/kalista/usb_pd_pdo.c b/baseboard/kalista/usb_pd_pdo.c new file mode 100644 index 0000000000..067b8eb9e7 --- /dev/null +++ b/baseboard/kalista/usb_pd_pdo.c @@ -0,0 +1,16 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +#define PDO_FIXED_FLAGS \ + (PDO_FIXED_UNCONSTRAINED | PDO_FIXED_DATA_SWAP | PDO_FIXED_COMM_CAP) + +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); diff --git a/baseboard/kalista/usb_pd_pdo.h b/baseboard/kalista/usb_pd_pdo.h new file mode 100644 index 0000000000..119658b8a5 --- /dev/null +++ b/baseboard/kalista/usb_pd_pdo.h @@ -0,0 +1,15 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BASEBOARD_KALISTA_USB_PD_PDO_H +#define __CROS_EC_BASEBOARD_KALISTA_USB_PD_PDO_H + +#include "config.h" +#include "stdint.h" + +extern const uint32_t pd_src_pdo[1]; +extern const int pd_src_pdo_cnt; + +#endif /* __CROS_EC_BASEBOARD_KALISTA_USB_PD_PDO_H */ diff --git a/baseboard/kalista/usb_pd_policy.c b/baseboard/kalista/usb_pd_policy.c index 89af4b50fb..b2f4656519 100644 --- a/baseboard/kalista/usb_pd_policy.c +++ b/baseboard/kalista/usb_pd_policy.c @@ -1,15 +1,15 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -17,22 +17,14 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_pdo.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define PDO_FIXED_FLAGS (PDO_FIXED_UNCONSTRAINED | \ - PDO_FIXED_DATA_SWAP | \ - PDO_FIXED_COMM_CAP) - -const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int board_vbus_source_enabled(int port) { @@ -66,8 +58,7 @@ int pd_snk_is_vbus_provided(int port) return !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L); } -__override void pd_check_pr_role(int port, - enum pd_power_role pr_role, +__override void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { } diff --git a/baseboard/keeby b/baseboard/keeby new file mode 120000 index 0000000000..14558486f6 --- /dev/null +++ b/baseboard/keeby @@ -0,0 +1 @@ +dedede \ No newline at end of file diff --git a/baseboard/kukui/base_detect_kukui.c b/baseboard/kukui/base_detect_kukui.c index ac7d9f7616..a3ccf4d507 100644 --- a/baseboard/kukui/base_detect_kukui.c +++ b/baseboard/kukui/base_detect_kukui.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,7 +14,7 @@ #include "usb_pd.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) /* Krane base detection code */ @@ -41,11 +41,11 @@ enum kukui_pogo_device_type { struct { int mv_low, mv_high; } static const pogo_detect_table[] = { - [DEVICE_TYPE_DETACHED] = {2700, 3500}, /* 10K, NC, around 3.3V */ + [DEVICE_TYPE_DETACHED] = { 2700, 3500 }, /* 10K, NC, around 3.3V */ #ifdef VARIANT_KUKUI_POGO_DOCK - [DEVICE_TYPE_DOCK] = {141, 173}, /* 10K, 0.5K ohm */ + [DEVICE_TYPE_DOCK] = { 141, 173 }, /* 10K, 0.5K ohm */ #endif - [DEVICE_TYPE_KEYBOARD] = {270, 400}, /* 10K, 1K ohm */ + [DEVICE_TYPE_KEYBOARD] = { 270, 400 }, /* 10K, 1K ohm */ }; BUILD_ASSERT(ARRAY_SIZE(pogo_detect_table) == DEVICE_TYPE_COUNT); @@ -71,7 +71,7 @@ static enum kukui_pogo_device_type get_device_type(int mv) for (i = 0; i < DEVICE_TYPE_COUNT; i++) { if (pogo_detect_table[i].mv_low <= mv && - mv <= pogo_detect_table[i].mv_high) + mv <= pogo_detect_table[i].mv_high) return i; } @@ -82,17 +82,17 @@ static void enable_charge(int enable) { #ifdef VARIANT_KUKUI_POGO_DOCK if (enable) { - struct charge_port_info info = { - .voltage = 5000, .current = 1500}; + struct charge_port_info info = { .voltage = 5000, + .current = 1500 }; /* * Set supplier type to PD to have same priority as type c * port. */ - charge_manager_update_charge( - CHARGE_SUPPLIER_DEDICATED, CHARGE_PORT_POGO, &info); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + CHARGE_PORT_POGO, &info); } else { - charge_manager_update_charge( - CHARGE_SUPPLIER_DEDICATED, CHARGE_PORT_POGO, NULL); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + CHARGE_PORT_POGO, NULL); } pd_send_host_event(PD_EVENT_POWER_CHANGE); #endif @@ -112,7 +112,7 @@ static void base_set_device_type(enum kukui_pogo_device_type device_type) case DEVICE_TYPE_ERROR: case DEVICE_TYPE_UNKNOWN: hook_call_deferred(&base_detect_deferred_data, - BASE_DETECT_RETRY_US); + BASE_DETECT_RETRY_US); break; case DEVICE_TYPE_DETACHED: @@ -200,9 +200,9 @@ static void pogo_chipset_shutdown(void) } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pogo_chipset_shutdown, HOOK_PRIO_DEFAULT); -void base_force_state(int state) +void base_force_state(enum ec_set_base_state_cmd state) { - if (state != 1 && state != 0) { + if (state >= EC_SET_BASE_STATE_RESET) { CPRINTS("BD forced reset"); pogo_chipset_init(); return; @@ -210,9 +210,11 @@ void base_force_state(int state) gpio_disable_interrupt(GPIO_POGO_ADC_INT_L); pogo_type = (state == 1 ? DEVICE_TYPE_KEYBOARD : DEVICE_TYPE_DETACHED); - base_set_device_type(state == 1 ? DEVICE_TYPE_KEYBOARD : - DEVICE_TYPE_DETACHED); - CPRINTS("BD forced %sconnected", state == 1 ? "" : "dis"); + base_set_device_type(state == EC_SET_BASE_STATE_ATTACH ? + DEVICE_TYPE_KEYBOARD : + DEVICE_TYPE_DETACHED); + CPRINTS("BD forced %sconnected", + state == EC_SET_BASE_STATE_ATTACH ? "" : "dis"); } #ifdef VARIANT_KUKUI_POGO_DOCK @@ -225,5 +227,5 @@ static void board_pogo_charge_init(void) charge_manager_update_charge(i, CHARGE_PORT_POGO, NULL); } DECLARE_HOOK(HOOK_INIT, board_pogo_charge_init, - HOOK_PRIO_CHARGE_MANAGER_INIT + 1); + HOOK_PRIO_INIT_CHARGE_MANAGER + 1); #endif diff --git a/baseboard/kukui/baseboard.c b/baseboard/kukui/baseboard.c index baf915407a..372e60c1e8 100644 --- a/baseboard/kukui/baseboard.c +++ b/baseboard/kukui/baseboard.c @@ -1,18 +1,21 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "charger.h" +#include "chipset.h" +#include "dma.h" #include "gpio.h" #include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" #include "registers.h" #include "timer.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) #ifndef CONFIG_CHARGER_RUNTIME_CONFIG #if defined(VARIANT_KUKUI_CHARGER_MT6370) @@ -43,6 +46,7 @@ void board_reset_pd_mcu(void) void board_config_pre_init(void) { +#ifdef VARIANT_KUKUI_EC_STM32F098 STM32_RCC_AHBENR |= STM32_RCC_HB_DMA1; /* * Remap USART1 and SPI2 DMA: @@ -50,8 +54,28 @@ void board_config_pre_init(void) * Ch4: USART1_TX / Ch5: USART1_RX (1000) * Ch6: SPI2_RX / Ch7: SPI2_TX (0011) */ - STM32_DMA_CSELR(STM32_DMAC_CH4) = (8 << 12) | (8 << 16) | - (3 << 20) | (3 << 24); + STM32_DMA_CSELR(STM32_DMAC_CH4) = (8 << 12) | (8 << 16) | (3 << 20) | + (3 << 24); + +#elif defined(VARIANT_KUKUI_EC_STM32L431) +#ifdef CONFIG_DMA_CROS + dma_init(); +#endif + /* + * Remap USART1 and SPI2 DMA: + * + * DMA2_CH=DMA1_CH+8 + * + * Ch6 (DMA2): USART1_TX / Ch7: USART1_RX (0010) + * Ch4 (DMA1): SPI2_RX / Ch5: SPI2_TX (0010) + * + * (*((volatile unsigned long *)(0x400200A8UL))) = 0x00011000; + * (*((volatile unsigned long *)(0x400204A8UL))) = 0x00200000; + */ + + STM32_DMA_CSELR(STM32_DMAC_CH4) = (1 << 12) | (1 << 16); + STM32_DMA_CSELR(STM32_DMAC_CH14) = (2 << 20) | (2 << 24); +#endif } enum kukui_board_version { @@ -76,27 +100,50 @@ enum kukui_board_version { }; /* map from kukui_board_version to board id voltage in mv */ +#ifdef VARIANT_KUKUI_EC_IT81202 const int16_t kukui_board_id_map[] = { - 109, /* 51.1K , 2.2K(gru 3.3K) ohm */ - 211, /* 51.1k , 6.8K ohm */ - 319, /* 51.1K , 11K ohm */ - 427, /* 56K , 17.4K ohm */ - 542, /* 51.1K , 22K ohm */ - 666, /* 51.1K , 30K ohm */ - 781, /* 51.1K , 39.2K ohm */ - 900, /* 56K , 56K ohm */ - 1023, /* 47K , 61.9K ohm */ - 1137, /* 47K , 80.6K ohm */ - 1240, /* 56K , 124K ohm */ - 1343, /* 51.1K , 150K ohm */ - 1457, /* 47K , 200K ohm */ - 1576, /* 47K , 330K ohm */ - 1684, /* 47K , 680K ohm */ - 1800, /* 56K , NC */ + 136, /* 51.1K , 2.2K(gru 3.3K) ohm */ + 388, /* 51.1k , 6.8K ohm */ + 584, /* 51.1K , 11K ohm */ + 785, /* 56K , 17.4K ohm */ + 993, /* 51.1K , 22K ohm */ + 1221, /* 51.1K , 30K ohm */ + 1433, /* 51.1K , 39.2K ohm */ + 1650, /* 56K , 56K ohm */ + 1876, /* 47K , 61.9K ohm */ + 2084, /* 47K , 80.6K ohm */ + 2273, /* 56K , 124K ohm */ + 2461, /* 51.1K , 150K ohm */ + 2672, /* 47K , 200K ohm */ + 2889, /* 47K , 330K ohm */ + 3086, /* 47K , 680K ohm */ + 3300, /* 56K , NC */ +}; + +#define THRESHOLD_MV 103 /* Simply assume 3300/16/2 */ +#else +const int16_t kukui_board_id_map[] = { + 109, /* 51.1K , 2.2K(gru 3.3K) ohm */ + 211, /* 51.1k , 6.8K ohm */ + 319, /* 51.1K , 11K ohm */ + 427, /* 56K , 17.4K ohm */ + 542, /* 51.1K , 22K ohm */ + 666, /* 51.1K , 30K ohm */ + 781, /* 51.1K , 39.2K ohm */ + 900, /* 56K , 56K ohm */ + 1023, /* 47K , 61.9K ohm */ + 1137, /* 47K , 80.6K ohm */ + 1240, /* 56K , 124K ohm */ + 1343, /* 51.1K , 150K ohm */ + 1457, /* 47K , 200K ohm */ + 1576, /* 47K , 330K ohm */ + 1684, /* 47K , 680K ohm */ + 1800, /* 56K , NC */ }; -BUILD_ASSERT(ARRAY_SIZE(kukui_board_id_map) == BOARD_VERSION_COUNT); #define THRESHOLD_MV 56 /* Simply assume 1800/16/2 */ +#endif /* VARIANT_KUKUI_EC_IT81202 */ +BUILD_ASSERT(ARRAY_SIZE(kukui_board_id_map) == BOARD_VERSION_COUNT); int board_get_version(void) { @@ -109,7 +156,7 @@ int board_get_version(void) gpio_set_level(GPIO_EC_BOARD_ID_EN_L, 0); /* Wait to allow cap charge */ - msleep(10); + msleep(20); mv = adc_read_channel(ADC_BOARD_ID); if (mv == ADC_READ_ERROR) @@ -124,27 +171,52 @@ int board_get_version(void) } } +#ifdef VARIANT_KUKUI_EC_STM32F098 /* * For devices without pogo, Disable ADC module after we detect the * board version, since this is the only thing ADC module needs to do * for this board. */ if (CONFIG_DEDICATED_CHARGE_PORT_COUNT == 0 && - version != BOARD_VERSION_UNKNOWN) + version != BOARD_VERSION_UNKNOWN) adc_disable(); +#endif return version; } static void baseboard_spi_init(void) { +#if defined(VARIANT_KUKUI_EC_STM32F098) || defined(VARIANT_KUKUI_EC_STM32L431) /* Set SPI PA15,PB3/4/5/13/14/15 pins to high speed */ STM32_GPIO_OSPEEDR(GPIO_A) |= 0xc0000000; STM32_GPIO_OSPEEDR(GPIO_B) |= 0xfc000fc0; +#endif } DECLARE_HOOK(HOOK_INIT, baseboard_spi_init, HOOK_PRIO_INIT_SPI + 1); -int board_allow_i2c_passthru(int port) +int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc) { - return (port == I2C_PORT_VIRTUAL_BATTERY); + return (cmd_desc->port == I2C_PORT_VIRTUAL_BATTERY); +} + +/* Enable or disable input devices, based on chipset state and tablet mode */ +#ifdef VARIANT_KUKUI_JACUZZI +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the + * keyboard. When the chipset is on, the EC keeps the + * keyboard enabled and the AP decides whether to + * ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } } +#endif diff --git a/baseboard/kukui/baseboard.h b/baseboard/kukui/baseboard.h index d4019f1fb1..6cb18b0d4e 100644 --- a/baseboard/kukui/baseboard.h +++ b/baseboard/kukui/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,14 +12,17 @@ * Variant battery defines, pick one: * VARIANT_KUKUI_BATTERY_MAX17055 * VARIANT_KUKUI_BATTERY_MM8013 + * VARIANT_KUKUI_BATTERY_BQ27541 * VARIANT_KUKUI_BATTERY_SMART */ #if defined(VARIANT_KUKUI_BATTERY_MAX17055) #define CONFIG_BATTERY_MAX17055 #define CONFIG_BATTERY_MAX17055_ALERT -#define BATTERY_MAX17055_RSENSE 5 /* m-ohm */ +#define BATTERY_MAX17055_RSENSE 5 /* m-ohm */ #elif defined(VARIANT_KUKUI_BATTERY_MM8013) #define CONFIG_BATTERY_MM8013 +#elif defined(VARIANT_KUKUI_BATTERY_BQ27541) +#define CONFIG_BATTERY_BQ27541 #elif defined(VARIANT_KUKUI_BATTERY_SMART) #define CONFIG_BATTERY_SMART #define CONFIG_BATTERY_FUEL_GAUGE @@ -44,9 +47,8 @@ #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE /* TCPC MT6370 */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* * The Maximum input voltage is 13.5V, need another 5% tolerance. @@ -60,11 +62,11 @@ #define CONFIG_CHARGER_SENSE_RESISTOR 10 /* BOARD_RS2 */ #define CONFIG_CHARGER_OTG #define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 /* TCPC FUSB302 */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 160000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 160000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* b/2230219: 15V has better charging performance than 20V */ #define PD_MAX_VOLTAGE_MV 15000 @@ -94,22 +96,44 @@ /* define this if the board is jacuzzi family */ #ifdef VARIANT_KUKUI_JACUZZI #define CONFIG_HOSTCMD_AP_SET_SKUID +/* + * IT81202 based boards are variant of jacuzzi and I/O expander isn't required + * on them. + */ +#if defined(VARIANT_KUKUI_EC_STM32F098) || defined(VARIANT_KUKUI_EC_STM32L431) #define CONFIG_IO_EXPANDER #define CONFIG_IO_EXPANDER_IT8801 #define CONFIG_IO_EXPANDER_PORT_COUNT 1 -#define CONFIG_KEYBOARD_NOT_RAW -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_KEYBOARD_DISCRETE + +#endif + #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L #define CONFIG_TABLET_MODE #define CONFIG_TABLET_MODE_SWITCH #define PD_OPERATING_POWER_MW 30000 -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 + +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +#else /* !VARIANT_KUKUI_JACUZZI */ + +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE)) + #endif /* VARIANT_KUKUI_JACUZZI */ +#if defined(SECTION_IS_RW) || defined(VARIANT_KUKUI_EC_IT81202) +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#endif + /* * Define this flag if board controls dp mux via gpio pins USB_C0_DP_OE_L and * USB_C0_DP_POLARITY. @@ -121,23 +145,19 @@ /* Optional modules */ #define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG +#undef CONFIG_ADC_WATCHDOG #define CONFIG_CHIPSET_MT8183 -#define CONFIG_CMD_ACCELS +#undef CONFIG_CMD_ACCELS #define CONFIG_EMULATED_SYSRQ -#undef CONFIG_HIBERNATE #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_I2C_VIRTUAL_BATTERY #define CONFIG_I2C_PASSTHRU_RESTRICTED #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE #define CONFIG_POWER_COMMON #define CONFIG_SPI -#define CONFIG_SPI_MASTER -#define CONFIG_STM_HWTIMER32 #define CONFIG_SWITCH -#define CONFIG_WATCHDOG_HELP #ifdef SECTION_IS_RO #undef CONFIG_SYSTEM_UNLOCKED /* Disabled in RO to save space */ @@ -145,17 +165,6 @@ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */ #endif -/* free flash space */ -#ifdef SECTION_IS_RO -#undef CONFIG_USB_PD_DEBUG_LEVEL -#define CONFIG_USB_PD_DEBUG_LEVEL 0 -#define CONFIG_COMMON_GPIO_SHORTNAMES -#endif - -#undef CONFIG_UART_CONSOLE -#define CONFIG_UART_CONSOLE 1 -#define CONFIG_UART_RX_DMA - /* Bootblock */ #ifdef SECTION_IS_RO #define CONFIG_BOOTBLOCK @@ -165,7 +174,6 @@ /* Optional features */ #define CONFIG_BOARD_PRE_INIT -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_BUTTON_TRIGGERED_RECOVERY #define CONFIG_CHARGER_ILIM_PIN_DISABLED #define CONFIG_FORCE_CONSOLE_RESUME @@ -180,19 +188,15 @@ /* By default, set hcdebug to off */ #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_MOTION_SENSE_CMD #define CONFIG_LTO #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_IGNORE_LID #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE -#define CONFIG_SOFTWARE_PANIC #define CONFIG_VBOOT_HASH #define CONFIG_CHARGER -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT 2 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 15000 #define CONFIG_CHARGER_DISCHARGE_ON_AC @@ -204,6 +208,7 @@ #define CONFIG_UART_TX_BUF_SIZE 4096 #define GPIO_LID_OPEN GPIO_HALL_INT_L +#define GPIO_KB_DISCRETE_INT GPIO_IT8801_SMB_INT #ifndef VARIANT_KUKUI_NO_SENSORS #define CONFIG_ACCEL_FIFO @@ -219,18 +224,12 @@ /* USB PD config */ #define CONFIG_CHARGE_MANAGER #define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV1 -/* Exclude PD state names from RO image to save space */ -#ifdef SECTION_IS_RO -#undef CONFIG_USB_PD_TCPMV1_DEBUG -#endif #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_LOGGING #define CONFIG_USB_PD_PORT_MAX_COUNT 1 #define CONFIG_USB_PD_TCPM_TCPCI -#define CONFIG_USB_PD_VBUS_DETECT_TCPC #define CONFIG_USB_PD_5V_EN_CUSTOM #define CONFIG_USBC_SS_MUX #define CONFIG_USBC_VCONN @@ -242,55 +241,121 @@ #define CONFIG_BATTERY_PRESENT_CUSTOM #define CONFIG_BATTERY_REVIVE_DISCONNECT -#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) #ifdef BOARD_KODAMA -#define PD_MAX_CURRENT_MA 2000 +#define PD_MAX_CURRENT_MA 2000 #else -#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_CURRENT_MA 3000 #endif +/* Optional for testing */ +#undef CONFIG_PECI +#undef CONFIG_PSTORE + +#define CONFIG_TASK_PROFILING +#define CONFIG_MKBP_USE_GPIO + +/* + * Variant EC defines. Pick one: + * VARIANT_KUKUI_EC_STM32F098 + * VARIANT_KUKUI_EC_IT81202 + * VARIANT_KUKUI_EC_STM32L431 + */ +#if defined(VARIANT_KUKUI_EC_STM32F098) || defined(VARIANT_KUKUI_EC_STM32L431) /* Timer selection */ -#define TIM_CLOCK32 2 +#define TIM_CLOCK32 2 #define TIM_WATCHDOG 7 /* 48 MHz SYSCLK clock frequency */ +#ifdef VARIANT_KUKUI_EC_STM32L431 +#define CPU_CLOCK 80000000 +#else #define CPU_CLOCK 48000000 +#endif -/* Optional for testing */ -#undef CONFIG_PECI -#undef CONFIG_PSTORE +#undef CONFIG_HIBERNATE +#define CONFIG_SPI_CONTROLLER +#define CONFIG_WATCHDOG_HELP +#undef CONFIG_UART_CONSOLE +#define CONFIG_UART_CONSOLE 1 +#define CONFIG_UART_RX_DMA + +/* This option is limited to TCPMv1 */ +#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 +/* STM32F098 based boards use TCPMv1 */ +#define CONFIG_USB_PD_TCPMV1 +#define CONFIG_USB_PD_VBUS_DETECT_TCPC /* Modules we want to exclude */ +#undef CONFIG_ACCEL_SPOOF_MODE +#undef CONFIG_CMD_ACCELSPOOF #undef CONFIG_CMD_BATTFAKE #undef CONFIG_CMD_FLASH +#undef CONFIG_CMD_FLASH_WP +#undef CONFIG_CMD_FLASHINFO +#undef CONFIG_CMD_GETTIME #undef CONFIG_CMD_HASH #undef CONFIG_CMD_MD +#undef CONFIG_CMD_MEM #undef CONFIG_CMD_POWERINDEBUG +#undef CONFIG_CMD_SHMEM +#undef CONFIG_CMD_SYSLOCK #undef CONFIG_CMD_TIMERINFO +#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CONSOLE_HISTORY +/* save space at RO image */ #ifdef SECTION_IS_RO +#undef CONFIG_CMD_ADC #undef CONFIG_CMD_APTHROTTLE +#undef CONFIG_CMD_CHARGE_SUPPLIER_INFO #undef CONFIG_CMD_CRASH #undef CONFIG_CMD_HCDEBUG #undef CONFIG_CMD_IDLE_STATS +#undef CONFIG_CMD_KEYBOARD +#undef CONFIG_CMD_MFALLOW #undef CONFIG_CMD_MMAPINFO +#undef CONFIG_CMD_PD +#undef CONFIG_CMD_POWER_AP #undef CONFIG_CMD_PWR_AVG #undef CONFIG_CMD_REGULATOR #undef CONFIG_CMD_RW -#undef CONFIG_CMD_SHMEM #undef CONFIG_CMD_SLEEPMASK #undef CONFIG_CMD_SLEEPMASK_SET -#undef CONFIG_CMD_SYSLOCK +#undef CONFIG_CMD_SYSINFO +#undef CONFIG_CMD_TYPEC +#undef CONFIG_CMD_WAITMS #undef CONFIG_HOSTCMD_FLASHPD #undef CONFIG_HOSTCMD_RWHASHPD -#undef CONFIG_CONSOLE_CMDHELP -#endif -#define CONFIG_TASK_PROFILING +#undef CONFIG_HOSTCMD_GET_UPTIME_INFO +#undef CONFIG_CMD_AP_RESET_LOG +#undef CONFIG_CMD_I2C_SCAN +#undef CONFIG_CMD_I2C_XFER -#define CONFIG_KEYBOARD_PROTOCOL_MKBP -#define CONFIG_MKBP_EVENT -#define CONFIG_MKBP_USE_GPIO +/* free flash space */ +#undef CONFIG_USB_PD_DEBUG_LEVEL +#define CONFIG_USB_PD_DEBUG_LEVEL 0 +#undef CONFIG_USB_PD_LOGGING +#define CONFIG_COMMON_GPIO_SHORTNAMES +#define CONFIG_DEBUG_ASSERT_BRIEF +/* Exclude PD state names from RO image to save space */ +#undef CONFIG_USB_PD_TCPMV1_DEBUG +#undef CONFIG_TASK_PROFILING +#endif /* SECTION_IS_RO */ + +#elif defined(VARIANT_KUKUI_EC_IT81202) +#define CONFIG_IT83XX_HARD_RESET_BY_GPG1 +#define CONFIG_IT83XX_VCC_1P8V + +/* IT81202 based boards use TCPMv2 */ +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 +#define CONFIG_USB_PD_TCPMV2 +#else +#error "Must define a VARIANT_KUKUI_EC_XXX!" +#endif #ifndef __ASSEMBLER__ #ifdef VARIANT_KUKUI_DP_MUX_GPIO diff --git a/baseboard/kukui/battery_bq27541.c b/baseboard/kukui/battery_bq27541.c new file mode 100644 index 0000000000..453d5e984f --- /dev/null +++ b/baseboard/kukui/battery_bq27541.c @@ -0,0 +1,220 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "builtin/assert.h" +#include "charge_state.h" +#include "charger_mt6370.h" +#include "console.h" +#include "driver/tcpm/mt6370.h" +#include "ec_commands.h" +#include "util.h" + +#define TEMP_OUT_OF_RANGE TEMP_ZONE_COUNT + +#define BATT_ID 0 + +#define BATTERY_CPT_CHARGE_MIN_TEMP 0 +#define BATTERY_CPT_CHARGE_MAX_TEMP 50 + +#define CHARGER_LIMIT_TIMEOUT_HOURS 48 +#define CHARGER_LIMIT_TIMEOUT_HOURS_TEMP 2 + +#define BAT_LEVEL_PD_LIMIT 85 + +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +enum battery_type { BATTERY_CPT = 0, BATTERY_COUNT }; + +static const struct battery_info info[] = { + [BATTERY_CPT] = { + .voltage_max = 4400, + .voltage_normal = 3850, + .voltage_min = 3000, + .precharge_voltage = 3400, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, +}; + +const struct battery_info *battery_get_info(void) +{ + return &info[BATT_ID]; +} + +int charger_profile_override(struct charge_state_data *curr) +{ + static timestamp_t deadline_48; + static timestamp_t deadline_2; + int cycle_count = 0, rv, val; + unsigned char rcv = 0, rcv_cycle = 0, rcv_soh = 0; + /* (FullCharge Capacity / Design Capacity) * 100 = SOH */ + int full_cap = 0, design_cap = 0, soh = 0; + /* battery temp in 0.1 deg C */ + int bat_temp_c = curr->batt.temperature - 2731; + /* + * Keep track of battery temperature range: + * + * ZONE_0 ZONE_1 ZONE_2 + * -----+--------+--------+------------+----- Temperature (C) + * t0 t1 t2 t3 + */ + enum { + TEMP_ZONE_0, /* t0 < bat_temp_c <= t1 */ + TEMP_ZONE_1, /* t1 < bat_temp_c <= t2 */ + TEMP_ZONE_2, /* t2 < bat_temp_c <= t3 */ + TEMP_ZONE_3, /* t3 < bat_temp_c <= t4 */ + TEMP_ZONE_COUNT + } temp_zone; + + static struct { + int temp_min; /* 0.1 deg C */ + int temp_max; /* 0.1 deg C */ + int desired_current; /* mA */ + int desired_voltage; /* mV */ + } temp_zones[BATTERY_COUNT][TEMP_ZONE_COUNT] = { + [BATTERY_CPT] = { + /* TEMP_ZONE_0 */ + {BATTERY_CPT_CHARGE_MIN_TEMP * 10, 150, 1408, 4370}, + /* TEMP_ZONE_1 */ + {150, 430, 3520, 4370}, + /* TEMP_ZONE_2 */ + {430, 450, 2112, 4320}, + /* TEMP_ZONE_3 */ + {450, BATTERY_CPT_CHARGE_MAX_TEMP * 10, 1760, 4170}, + }, + }; + BUILD_ASSERT(ARRAY_SIZE(temp_zones[0]) == TEMP_ZONE_COUNT); + BUILD_ASSERT(ARRAY_SIZE(temp_zones) == BATTERY_COUNT); + + if ((curr->batt.flags & BATT_FLAG_BAD_TEMPERATURE) || + (bat_temp_c < temp_zones[BATT_ID][0].temp_min) || + (bat_temp_c >= temp_zones[BATT_ID][TEMP_ZONE_COUNT - 1].temp_max)) + temp_zone = TEMP_OUT_OF_RANGE; + else { + for (temp_zone = 0; temp_zone < TEMP_ZONE_COUNT; temp_zone++) { + if (bat_temp_c < + temp_zones[BATT_ID][temp_zone].temp_max) + break; + } + } + + switch (temp_zone) { + case TEMP_ZONE_0: + case TEMP_ZONE_1: + case TEMP_ZONE_2: + case TEMP_ZONE_3: + curr->requested_current = + temp_zones[BATT_ID][temp_zone].desired_current; + curr->requested_voltage = + temp_zones[BATT_ID][temp_zone].desired_voltage; + break; + case TEMP_OUT_OF_RANGE: + curr->requested_current = curr->requested_voltage = 0; + curr->batt.flags &= ~BATT_FLAG_WANT_CHARGE; + curr->state = ST_IDLE; + break; + } + + /* Check cycle count to decrease charging voltage. */ + rv = battery_cycle_count(&val); + if (!rv) + cycle_count = val; + if (cycle_count > 20 && cycle_count <= 50) + rcv_cycle = 50; + else if (cycle_count > 50 && cycle_count <= 300) + rcv_cycle = 65; + else if (cycle_count > 300 && cycle_count <= 600) + rcv_cycle = 80; + else if (cycle_count > 600 && cycle_count <= 1000) + rcv_cycle = 100; + else if (cycle_count > 1000) + rcv_cycle = 150; + /* Check SOH to decrease charging voltage. */ + if (!battery_full_charge_capacity(&full_cap) && + !battery_design_capacity(&design_cap)) + soh = ((full_cap * 100) / design_cap); + if (soh > 70 && soh <= 75) + rcv_soh = 50; + else if (soh > 60 && soh <= 70) + rcv_soh = 65; + else if (soh > 55 && soh <= 60) + rcv_soh = 80; + else if (soh > 50 && soh <= 55) + rcv_soh = 100; + else if (soh <= 50) + rcv_soh = 150; + rcv = MAX(rcv_cycle, rcv_soh); + curr->requested_voltage -= rcv; + + /* Should not keep charging voltage > 4250mV for 48hrs. */ + if ((curr->state == ST_DISCHARGE) || curr->chg.voltage < 4250) { + deadline_48.val = 0; + /* Starting count 48hours */ + } else if (curr->state == ST_CHARGE || curr->state == ST_PRECHARGE) { + if (deadline_48.val == 0) + deadline_48.val = get_time().val + + CHARGER_LIMIT_TIMEOUT_HOURS * HOUR; + /* If charging voltage keep > 4250 for 48hrs, + * set charging voltage = 4250 + */ + else if (timestamp_expired(deadline_48, NULL)) + curr->requested_voltage = 4250; + } + /* Should not keeep battery voltage > 4100mV and + * battery temperature > 45C for two hour + */ + if (curr->state == ST_DISCHARGE || curr->batt.voltage < 4100 || + bat_temp_c < 450) { + deadline_2.val = 0; + } else if (curr->state == ST_CHARGE || curr->state == ST_PRECHARGE) { + if (deadline_2.val == 0) + deadline_2.val = + get_time().val + + CHARGER_LIMIT_TIMEOUT_HOURS_TEMP * HOUR; + else if (timestamp_expired(deadline_2, NULL)) { + /* Set discharge and charging voltage = 4100mV */ + if (curr->batt.voltage >= 4100) { + curr->requested_current = 0; + curr->requested_voltage = 4100; + } + } + } + +#ifdef VARIANT_KUKUI_CHARGER_MT6370 + mt6370_charger_profile_override(curr); +#endif /* CONFIG_CHARGER_MT6370 */ + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +int get_battery_manufacturer_name(char *dest, int size) +{ + static const char *const name[] = { + [BATTERY_CPT] = "AS1XXXD3Ka", + }; + ASSERT(dest); + strzcpy(dest, name[BATT_ID], size); + return EC_SUCCESS; +} diff --git a/baseboard/kukui/battery_max17055.c b/baseboard/kukui/battery_max17055.c index 972bd13700..5ebb220b0c 100644 --- a/baseboard/kukui/battery_max17055.c +++ b/baseboard/kukui/battery_max17055.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,6 +6,7 @@ */ #include "battery.h" +#include "builtin/assert.h" #include "charge_state.h" #include "charger_mt6370.h" #include "console.h" @@ -15,25 +16,14 @@ #define TEMP_OUT_OF_RANGE TEMP_ZONE_COUNT -#ifdef BOARD_KAKADU -#define BATT_ID 1 -#else #define BATT_ID 0 -#endif #define BATTERY_SIMPLO_CHARGE_MIN_TEMP 0 #define BATTERY_SIMPLO_CHARGE_MAX_TEMP 60 -#define BATTERY_ATL_CHARGE_MIN_TEMP -20 -#define BATTERY_ATL_CHARGE_MAX_TEMP 60 +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -enum battery_type { - BATTERY_SIMPLO = 0, - BATTERY_ATL, - BATTERY_COUNT -}; +enum battery_type { BATTERY_SIMPLO = 0, BATTERY_COUNT }; static const struct battery_info info[] = { [BATTERY_SIMPLO] = { @@ -48,18 +38,6 @@ static const struct battery_info info[] = { .discharging_min_c = -20, .discharging_max_c = 60, }, - [BATTERY_ATL] = { - .voltage_max = 4370, - .voltage_normal = 3860, - .voltage_min = 3150, - .precharge_current = 256, - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, }; static const struct max17055_batt_profile batt_profile[] = { @@ -69,12 +47,6 @@ static const struct max17055_batt_profile batt_profile[] = { .ichg_term = MAX17055_ICHGTERM_REG(235), .v_empty_detect = MAX17055_VEMPTY_REG(3000, 3600), }, - [BATTERY_ATL] = { - .is_ez_config = 1, - .design_cap = MAX17055_DESIGNCAP_REG(7270), - .ichg_term = MAX17055_ICHGTERM_REG(500), - .v_empty_detect = MAX17055_VEMPTY_REG(3000, 3600), - }, }; static const struct max17055_alert_profile alert_profile[] = { @@ -86,14 +58,6 @@ static const struct max17055_alert_profile alert_profile[] = { .s_alert_mxmn = SALRT_DISABLE, .i_alert_mxmn = IALRT_DISABLE, }, - [BATTERY_ATL] = { - .v_alert_mxmn = VALRT_DISABLE, - .t_alert_mxmn = MAX17055_TALRTTH_REG( - BATTERY_ATL_CHARGE_MAX_TEMP, - BATTERY_ATL_CHARGE_MIN_TEMP), - .s_alert_mxmn = SALRT_DISABLE, - .i_alert_mxmn = IALRT_DISABLE, - }, }; const struct max17055_batt_profile *max17055_get_batt_profile(void) @@ -120,11 +84,6 @@ enum battery_disconnect_state battery_get_disconnect_state(void) int charger_profile_override(struct charge_state_data *curr) { -#ifdef BOARD_KAKADU - static timestamp_t deadline_48; - static timestamp_t deadline_2; - int cycle_count = 0, rv, val; -#endif /* battery temp in 0.1 deg C */ int bat_temp_c = curr->batt.temperature - 2731; @@ -160,16 +119,6 @@ int charger_profile_override(struct charge_state_data *curr) /* TEMP_ZONE_3 */ {450, BATTERY_SIMPLO_CHARGE_MAX_TEMP * 10, 3350, 4300}, }, - [BATTERY_ATL] = { - /* TEMP_ZONE_0 */ - {BATTERY_ATL_CHARGE_MIN_TEMP * 10, 50, 719, 4370}, - /* TEMP_ZONE_1 */ - {50, 100, 2157, 4370}, - /* TEMP_ZONE_2 */ - {100, 450, 3595, 4370}, - /* TEMP_ZONE_3 */ - {450, BATTERY_ATL_CHARGE_MAX_TEMP * 10, 2516, 4100}, - }, }; BUILD_ASSERT(ARRAY_SIZE(temp_zones[BATT_ID]) == TEMP_ZONE_COUNT); BUILD_ASSERT(ARRAY_SIZE(temp_zones) == BATTERY_COUNT); @@ -181,7 +130,7 @@ int charger_profile_override(struct charge_state_data *curr) else { for (temp_zone = 0; temp_zone < TEMP_ZONE_COUNT; temp_zone++) { if (bat_temp_c < - temp_zones[BATT_ID][temp_zone].temp_max) + temp_zones[BATT_ID][temp_zone].temp_max) break; } } @@ -206,53 +155,6 @@ int charger_profile_override(struct charge_state_data *curr) break; } -#ifdef BOARD_KAKADU - /* Check cycle count to decrease charging voltage. */ - rv = battery_cycle_count(&val); - if (!rv) - cycle_count = val; - if (cycle_count > 300 && cycle_count <= 600) - curr->requested_voltage = 4320; - else if (cycle_count > 600 && cycle_count <= 1000) - curr->requested_voltage = 4300; - else if (cycle_count > 1000) - curr->requested_voltage = 4250; - /* Should not keep charging voltage > 4250mV for 48hrs. */ - if ((curr->state == ST_DISCHARGE) || - curr->chg.voltage < 4250) { - deadline_48.val = 0; - /* Starting count 48hours */ - } else if (curr->state == ST_CHARGE || - curr->state == ST_PRECHARGE) { - if (deadline_48.val == 0) - deadline_48.val = get_time().val + - CHARGER_LIMIT_TIMEOUT_HOURS * HOUR; - /* If charging voltage keep > 4250 for 48hrs, - set charging voltage = 4250 */ - else if (timestamp_expired(deadline_48, NULL)) - curr->requested_voltage = 4250; - } - /* Should not keeep battery voltage > 4100mV and - battery temperature > 45C for two hour */ - if (curr->state == ST_DISCHARGE || - curr->batt.voltage < 4100 || - bat_temp_c < 450) { - deadline_2.val = 0; - } else if (curr->state == ST_CHARGE || - curr->state == ST_PRECHARGE) { - if (deadline_2.val == 0) - deadline_2.val = get_time().val + - CHARGER_LIMIT_TIMEOUT_HOURS_TEMP * HOUR; - else if (timestamp_expired(deadline_2, NULL)) { - /* Set discharge and charging voltage = 4100mV */ - if (curr->batt.voltage >= 4100) { - curr->requested_current = 0; - curr->requested_voltage = 4100; - } - } - } -#endif - #ifdef VARIANT_KUKUI_CHARGER_MT6370 mt6370_charger_profile_override(curr); #endif /* CONFIG_CHARGER_MT6370 */ @@ -274,12 +176,10 @@ enum ec_status charger_profile_override_set_param(uint32_t param, int get_battery_manufacturer_name(char *dest, int size) { - static const char * const name[] = { + static const char *const name[] = { [BATTERY_SIMPLO] = "SIMPLO", - [BATTERY_ATL] = "Celxpert", }; ASSERT(dest); strzcpy(dest, name[BATT_ID], size); return EC_SUCCESS; } - diff --git a/baseboard/kukui/battery_mm8013.c b/baseboard/kukui/battery_mm8013.c index e7f422e561..26507d5915 100644 --- a/baseboard/kukui/battery_mm8013.c +++ b/baseboard/kukui/battery_mm8013.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -22,12 +22,9 @@ #define BAT_LEVEL_PD_LIMIT 85 -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) -enum battery_type { - BATTERY_SCUD = 0, - BATTERY_COUNT -}; +enum battery_type { BATTERY_SCUD = 0, BATTERY_COUNT }; static const struct battery_info info[] = { [BATTERY_SCUD] = { @@ -100,7 +97,7 @@ int charger_profile_override(struct charge_state_data *curr) else { for (temp_zone = 0; temp_zone < TEMP_ZONE_COUNT; temp_zone++) { if (bat_temp_c < - temp_zones[BATT_ID][temp_zone].temp_max) + temp_zones[BATT_ID][temp_zone].temp_max) break; } } diff --git a/baseboard/kukui/battery_smart.c b/baseboard/kukui/battery_smart.c index ba2af17443..b924b2e3a9 100644 --- a/baseboard/kukui/battery_smart.c +++ b/baseboard/kukui/battery_smart.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -98,39 +98,30 @@ __override void board_battery_compensate_params(struct batt_params *batt) /* return cached values for at most CACHE_INVALIDATION_TIME_US */ fix_single_param(batt->flags & BATT_FLAG_BAD_STATE_OF_CHARGE, - &batt_cache.state_of_charge, - &batt->state_of_charge); + &batt_cache.state_of_charge, &batt->state_of_charge); fix_single_param(batt->flags & BATT_FLAG_BAD_VOLTAGE, - &batt_cache.voltage, - &batt->voltage); + &batt_cache.voltage, &batt->voltage); fix_single_param(batt->flags & BATT_FLAG_BAD_CURRENT, - &batt_cache.current, - &batt->current); + &batt_cache.current, &batt->current); fix_single_param(batt->flags & BATT_FLAG_BAD_DESIRED_VOLTAGE, - &batt_cache.desired_voltage, - &batt->desired_voltage); + &batt_cache.desired_voltage, &batt->desired_voltage); fix_single_param(batt->flags & BATT_FLAG_BAD_DESIRED_CURRENT, - &batt_cache.desired_current, - &batt->desired_current); + &batt_cache.desired_current, &batt->desired_current); fix_single_param(batt->flags & BATT_FLAG_BAD_REMAINING_CAPACITY, - &batt_cache.remaining_capacity, - &batt->remaining_capacity); + &batt_cache.remaining_capacity, + &batt->remaining_capacity); fix_single_param(batt->flags & BATT_FLAG_BAD_FULL_CAPACITY, - &batt_cache.full_capacity, - &batt->full_capacity); - fix_single_param(batt->flags & BATT_FLAG_BAD_STATUS, - &batt_cache.status, - &batt->status); + &batt_cache.full_capacity, &batt->full_capacity); + fix_single_param(batt->flags & BATT_FLAG_BAD_STATUS, &batt_cache.status, + &batt->status); fix_single_param(batt->flags & BATT_FLAG_BAD_TEMPERATURE, - &batt_cache.temperature, - &batt->temperature); + &batt_cache.temperature, &batt->temperature); /* * If battery_compensate_params() didn't calculate display_charge * for us, also update it with last good value. */ - fix_single_param(batt->display_charge == 0, - &batt_cache.display_charge, - &batt->display_charge); + fix_single_param(batt->display_charge == 0, &batt_cache.display_charge, + &batt->display_charge); /* remove bad flags after applying cached values */ batt->flags &= ~BATT_FLAG_BAD_ANY; diff --git a/baseboard/kukui/build.mk b/baseboard/kukui/build.mk index ab62483bc7..f35ed1f4ce 100644 --- a/baseboard/kukui/build.mk +++ b/baseboard/kukui/build.mk @@ -1,24 +1,28 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Baseboard specific files build # +# Select eMMC CMD0 driver. +EMMC_CMD0_DRIVER=$(if $(CHIP_IT83XX),emmc_ite.o,emmc.o) + baseboard-y=baseboard.o baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o -baseboard-$(CONFIG_BOOTBLOCK)+=emmc.o +baseboard-$(CONFIG_BOOTBLOCK)+=$(EMMC_CMD0_DRIVER) baseboard-$(VARIANT_KUKUI_BATTERY_MAX17055)+=battery_max17055.o baseboard-$(VARIANT_KUKUI_BATTERY_MM8013)+=battery_mm8013.o +baseboard-$(VARIANT_KUKUI_BATTERY_BQ27541)+=battery_bq27541.o baseboard-$(VARIANT_KUKUI_BATTERY_SMART)+=battery_smart.o baseboard-$(VARIANT_KUKUI_CHARGER_MT6370)+=charger_mt6370.o baseboard-$(VARIANT_KUKUI_POGO_KEYBOARD)+=base_detect_kukui.o -$(out)/RO/baseboard/$(BASEBOARD)/emmc.o: $(out)/bootblock_data.h +$(out)/RO/baseboard/$(BASEBOARD)/$(EMMC_CMD0_DRIVER): $(out)/bootblock_data.h # bootblock size from 12769.0 DEFAULT_BOOTBLOCK_SIZE:=21504 diff --git a/baseboard/kukui/charger_mt6370.c b/baseboard/kukui/charger_mt6370.c index 5e78a100c5..c4300c5552 100644 --- a/baseboard/kukui/charger_mt6370.c +++ b/baseboard/kukui/charger_mt6370.c @@ -1,10 +1,10 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger_mt6370.h" #include "console.h" #include "driver/charger/rt946x.h" @@ -51,7 +51,7 @@ static void update_plt_resume(void) } DECLARE_HOOK(HOOK_CHIPSET_RESUME, update_plt_resume, HOOK_PRIO_DEFAULT); -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) /* wait time to evaluate charger thermal status */ static timestamp_t thermal_wait_until; @@ -77,7 +77,8 @@ int board_cut_off_battery(void) static void board_set_charge_limit_throttle(int charge_ma, int charge_mv) { charge_set_input_current_limit( - MIN(throttled_ma, MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)), + MIN(throttled_ma, + MAX(charge_ma, CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT)), charge_mv); } @@ -117,7 +118,7 @@ static void battery_thermal_control(struct charge_state_data *curr) return; /* If we fail to read input curr limit, skip for this cycle. */ - if (charger_get_input_current(CHARGER_SOLO, &input_current)) + if (charger_get_input_current_limit(CHARGER_SOLO, &input_current)) return; /* @@ -155,7 +156,7 @@ static void battery_thermal_control(struct charge_state_data *curr) thermal_wait_until.val = get_time().val + (3 * SECOND); } -int command_jc(int argc, char **argv) +static int command_jc(int argc, const char **argv) { static int prev_jc_temp; int jc_temp; @@ -304,8 +305,8 @@ void mt6370_charger_profile_override(struct charge_state_data *curr) * and TE function. */ hook_call_deferred( - &charge_enable_eoc_and_te_data, - (4.5 * SECOND)); + &charge_enable_eoc_and_te_data, + (4.5 * SECOND)); } } } @@ -329,17 +330,16 @@ void mt6370_charger_profile_override(struct charge_state_data *curr) /* * When the charger says it's done charging, even if fuel gauge says - * SOC < BATTERY_LEVEL_NEAR_FULL, we'll overwrite SOC with - * BATTERY_LEVEL_NEAR_FULL. So we can ensure both Chrome OS UI + * SOC < CONFIG_BATT_HOST_FULL_FACTOR, we'll overwrite SOC with + * CONFIG_BATT_HOST_FULL_FACTOR. So we can ensure both Chrome OS UI * and battery LED indicate full charge. * * Enable this hack on on-board gauge only (b/142097561) */ if (IS_ENABLED(CONFIG_BATTERY_MAX17055) && rt946x_is_charge_done()) { - curr->batt.state_of_charge = MAX(BATTERY_LEVEL_NEAR_FULL, + curr->batt.state_of_charge = MAX(CONFIG_BATT_HOST_FULL_FACTOR, curr->batt.state_of_charge); } - } #ifndef CONFIG_BATTERY_SMART @@ -352,13 +352,12 @@ static void board_charge_termination(void) te = 1; } } -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, - board_charge_termination, +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, board_charge_termination, HOOK_PRIO_DEFAULT); #endif -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { prev_charge_limit = charge_ma; prev_charge_mv = charge_mv; diff --git a/baseboard/kukui/charger_mt6370.h b/baseboard/kukui/charger_mt6370.h index 880b00a1a8..1de4e66b0b 100644 --- a/baseboard/kukui/charger_mt6370.h +++ b/baseboard/kukui/charger_mt6370.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/baseboard/kukui/emmc.c b/baseboard/kukui/emmc.c index 4735f4aea8..416d44c634 100644 --- a/baseboard/kukui/emmc.c +++ b/baseboard/kukui/emmc.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -28,6 +28,7 @@ * case we interrupt the transfer, and the BootROM will try again. */ +#include "bootblock_data.h" #include "chipset.h" #include "clock.h" #include "console.h" @@ -41,10 +42,8 @@ #include "timer.h" #include "util.h" -#include "bootblock_data.h" - -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SPI, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SPI, format, ##args) #if EMMC_SPI_PORT == 1 #define STM32_SPI_EMMC_REGS STM32_SPI1_REGS @@ -68,7 +67,7 @@ static timestamp_t boot_deadline; /* 1024 bytes circular buffer is enough for ~0.6ms @ 13Mhz. */ #define SPI_RX_BUF_BYTES 1024 -#define SPI_RX_BUF_WORDS (SPI_RX_BUF_BYTES/4) +#define SPI_RX_BUF_WORDS (SPI_RX_BUF_BYTES / 4) static uint32_t in_msg[SPI_RX_BUF_WORDS]; /* Macros to advance in the circular buffer. */ @@ -92,7 +91,7 @@ static const struct dma_option dma_tx_option = { static const struct dma_option dma_rx_option = { STM32_DMAC_SPI_EMMC_RX, (void *)&STM32_SPI_EMMC_REGS->dr, STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CIRC + STM32_DMA_CCR_CIRC }; /* Setup DMA to transfer bootblock. */ @@ -123,7 +122,7 @@ static void bootblock_stop(void) */ start = __hw_clock_source_read(); while (STM32_SPI_EMMC_REGS->sr & STM32_SPI_SR_FTLVL && - __hw_clock_source_read() - start < timeout) + __hw_clock_source_read() - start < timeout) ; /* Then flush SPI FIFO, and make sure DAT line stays idle (high). */ @@ -152,8 +151,8 @@ static enum emmc_cmd emmc_parse_command(int index) /* Number of leading ones. */ shift0 = __builtin_clz(~data[0]); - data[0] = (data[0] << shift0) | (data[1] >> (32-shift0)); - data[1] = (data[1] << shift0) | (data[2] >> (32-shift0)); + data[0] = (data[0] << shift0) | (data[1] >> (32 - shift0)); + data[1] = (data[1] << shift0) | (data[2] >> (32 - shift0)); if (data[0] == 0x40000000 && data[1] == 0x0095ffff) { /* 400000000095 GO_IDLE_STATE */ @@ -177,7 +176,6 @@ static enum emmc_cmd emmc_parse_command(int index) return EMMC_ERROR; } - /* * Wake the EMMC task when there is a falling edge on the CMD line, so that we * can capture the command. @@ -198,12 +196,21 @@ static void emmc_init_spi(void) /* Enable clocks to SPI module */ STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI1; #elif EMMC_SPI_PORT == 2 +#ifdef CHIP_FAMILY_STM32L4 + /* Reset SPI */ + STM32_RCC_APB1RSTR1 |= STM32_RCC_PB1_SPI2; + STM32_RCC_APB1RSTR1 &= ~STM32_RCC_PB1_SPI2; + + /* Enable clocks to SPI module */ + STM32_RCC_APB1ENR1 |= STM32_RCC_PB1_SPI2; +#else /* Reset SPI */ STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; /* Enable clocks to SPI module */ STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; +#endif #else #error "Please define EMMC_SPI_PORT in board.h." #endif diff --git a/baseboard/kukui/emmc_ite.c b/baseboard/kukui/emmc_ite.c new file mode 100644 index 0000000000..6ac0200c1d --- /dev/null +++ b/baseboard/kukui/emmc_ite.c @@ -0,0 +1,204 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "bootblock_data.h" +#include "chipset.h" +#include "console.h" +#include "endian.h" +#include "gpio.h" +#include "hooks.h" +#include "hwtimer.h" +#include "intc.h" +#include "system.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) + +enum emmc_cmd { + EMMC_ERROR = -1, + EMMC_IDLE = 0, + EMMC_PRE_IDLE, + EMMC_BOOT, +}; + +static void emmc_reset_spi_tx(void) +{ + /* Reset TX FIFO and count monitor */ + IT83XX_SPI_TXFCR = IT83XX_SPI_TXFR | IT83XX_SPI_TXFCMR; + /* Send idle state (high/0xff) if master clocks in data. */ + IT83XX_SPI_FCR = 0; +} + +static void emmc_reset_spi_rx(void) +{ + /* End Rx FIFO access */ + IT83XX_SPI_TXRXFAR = 0; + /* Reset RX FIFO and count monitor */ + IT83XX_SPI_FCR = IT83XX_SPI_RXFR | IT83XX_SPI_RXFCMR; +} + +/* + * Set SPI module work as eMMC Alternative Boot Mode. + * (CS# pin isn't required, and dropping data until CMD goes low) + */ +static void emmc_enable_spi(void) +{ + /* Set SPI pin mux to eMMC (GPM2:CLK, GPM3:CMD, GPM6:DATA0) */ + IT83XX_GCTRL_PIN_MUX0 |= BIT(7); + /* Enable eMMC Alternative Boot Mode */ + IT83XX_SPI_EMMCBMR |= IT83XX_SPI_EMMCABM; + /* Reset TX and RX FIFO */ + emmc_reset_spi_tx(); + emmc_reset_spi_rx(); + /* Response idle state (high) */ + IT83XX_SPI_SPISRDR = 0xff; + /* FIFO will be overwritten once it's full */ + IT83XX_SPI_GCR2 = 0; + /* Write to clear pending interrupt bits */ + IT83XX_SPI_ISR = 0xff; + IT83XX_SPI_RX_VLISR = IT83XX_SPI_RVLI; + /* Enable RX fifo full interrupt */ + IT83XX_SPI_IMR = 0xff; + IT83XX_SPI_RX_VLISMR |= IT83XX_SPI_RVLIM; + IT83XX_SPI_IMR &= ~IT83XX_SPI_RX_FIFO_FULL; + /* + * Enable interrupt to detect AP's BOOTBLOCK_EN_L. So EC is able to + * switch SPI module back to communication mode once BOOTBLOCK_EN_L + * goes high (AP Jumped to bootloader). + */ + gpio_clear_pending_interrupt(GPIO_BOOTBLOCK_EN_L); + gpio_enable_interrupt(GPIO_BOOTBLOCK_EN_L); + + disable_sleep(SLEEP_MASK_EMMC); + CPRINTS("eMMC emulation enabled"); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, emmc_enable_spi, HOOK_PRIO_FIRST); + +static void emmc_init_spi(void) +{ + /* Enable alternate function */ + gpio_config_module(MODULE_SPI_FLASH, 1); +} +DECLARE_HOOK(HOOK_INIT, emmc_init_spi, HOOK_PRIO_INIT_SPI + 1); + +static void emmc_send_data_over_spi(uint8_t *tx, int tx_size, int rst_tx) +{ + int i; + + /* Reset TX FIFO and count monitor */ + if (rst_tx) + IT83XX_SPI_TXFCR = IT83XX_SPI_TXFR | IT83XX_SPI_TXFCMR; + /* CPU access TX FIFO1 and FIFO2 */ + IT83XX_SPI_TXRXFAR = IT83XX_SPI_CPUTFA; + + /* Write response data to TX FIFO */ + for (i = 0; i < tx_size; i += 4) + IT83XX_SPI_CPUWTFDB0 = *(uint32_t *)(tx + i); + /* + * After writing data to TX FIFO is finished, this bit will + * be to indicate the SPI peripheral controller. + */ + IT83XX_SPI_TXFCR = IT83XX_SPI_TXFS; + /* End CPU access TX FIFO */ + IT83XX_SPI_TXRXFAR = 0; + /* SPI module access TX FIFO */ + IT83XX_SPI_FCR = IT83XX_SPI_SPISRTXF; +} + +static void emmc_bootblock_transfer(void) +{ + int tx_size, sent = 0, remaining = sizeof(bootblock_raw_data); + uint8_t *raw = (uint8_t *)bootblock_raw_data; + const uint32_t timeout_us = 200; + uint32_t start; + + /* + * HW will transmit the data of FIFO1 or FIFO2 in turn. + * So when a FIFO is empty, we need to fill the FIFO out + * immediately. + */ + emmc_send_data_over_spi(&raw[sent], 256, 1); + sent += 256; + + while (sent < remaining) { + /* Wait for FIFO1 or FIFO2 have been transmitted */ + start = __hw_clock_source_read(); + while (!(IT83XX_SPI_TXFSR & BIT(0)) && + (__hw_clock_source_read() - start < timeout_us)) + ; + /* Abort an ongoing transfer due to a command is received. */ + if (IT83XX_SPI_ISR & IT83XX_SPI_RX_FIFO_FULL) + break; + /* fill out next 128 bytes to FIFO1 or FIFO2 */ + tx_size = (remaining - sent) < 128 ? (remaining - sent) : 128; + emmc_send_data_over_spi(&raw[sent], tx_size, 0); + sent += tx_size; + } +} + +static enum emmc_cmd emmc_parse_command(int index, uint32_t *cmd0) +{ + int32_t shift0; + uint32_t data[3]; + + data[0] = htobe32(cmd0[index]); + data[1] = htobe32(cmd0[index + 1]); + data[2] = htobe32(cmd0[index + 2]); + + if ((data[0] & 0xff000000) != 0x40000000) { + /* Figure out alignment (cmd starts with 01) */ + /* Number of leading ones. */ + shift0 = __builtin_clz(~data[0]); + + data[0] = (data[0] << shift0) | (data[1] >> (32 - shift0)); + data[1] = (data[1] << shift0) | (data[2] >> (32 - shift0)); + } + + if (data[0] == 0x40000000 && data[1] == 0x0095ffff) { + /* 400000000095 GO_IDLE_STATE */ + CPRINTS("goIdle"); + return EMMC_IDLE; + } + + if (data[0] == 0x40f0f0f0 && data[1] == 0xf0fdffff) { + /* 40f0f0f0f0fd GO_PRE_IDLE_STATE */ + CPRINTS("goPreIdle"); + return EMMC_PRE_IDLE; + } + + if (data[0] == 0x40ffffff && data[1] == 0xfae5ffff) { + /* 40fffffffae5 BOOT_INITIATION */ + CPRINTS("bootInit"); + return EMMC_BOOT; + } + + CPRINTS("eMMC error"); + return EMMC_ERROR; +} + +void spi_emmc_cmd0_isr(uint32_t *cmd0_payload) +{ + enum emmc_cmd cmd; + + for (int i = 0; i < 8; i++) { + if (cmd0_payload[i] == 0xffffffff) + continue; + + cmd = emmc_parse_command(i, &cmd0_payload[i]); + + if (cmd == EMMC_IDLE || cmd == EMMC_PRE_IDLE) { + /* Abort an ongoing transfer. */ + emmc_reset_spi_tx(); + break; + } + + if (cmd == EMMC_BOOT) { + emmc_bootblock_transfer(); + break; + } + } +} diff --git a/baseboard/kukui/usb_pd_policy.c b/baseboard/kukui/usb_pd_policy.c index b2ff65b849..1ca7935762 100644 --- a/baseboard/kukui/usb_pd_policy.c +++ b/baseboard/kukui/usb_pd_policy.c @@ -1,13 +1,14 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "console.h" #include "gpio.h" +#include "hooks.h" #include "system.h" #include "timer.h" #include "usb_mux.h" @@ -15,20 +16,45 @@ #include "usb_pd_policy.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static int board_get_polarity(int port) { /* Krane's aux mux polarity is reversed. Workaround to flip it back. */ if (IS_ENABLED(BOARD_KRANE) && board_get_version() == 3) - return !pd_get_polarity(port); + return !polarity_rm_dts(pd_get_polarity(port)); - return pd_get_polarity(port); + return polarity_rm_dts(pd_get_polarity(port)); } static uint8_t vbus_en; +#define VBUS_EN_SYSJUMP_TAG 0x5645 /* VE */ +#define VBUS_EN_HOOK_VERSION 1 + +static void vbus_en_preserve_state(void) +{ + system_add_jump_tag(VBUS_EN_SYSJUMP_TAG, VBUS_EN_HOOK_VERSION, + sizeof(vbus_en), &vbus_en); +} +DECLARE_HOOK(HOOK_SYSJUMP, vbus_en_preserve_state, HOOK_PRIO_DEFAULT); + +static void vbus_en_restore_state(void) +{ + const uint8_t *prev_vbus_en; + int size, version; + + prev_vbus_en = (const uint8_t *)system_get_jump_tag(VBUS_EN_SYSJUMP_TAG, + &version, &size); + + if (prev_vbus_en && version == VBUS_EN_HOOK_VERSION && + size == sizeof(*prev_vbus_en)) { + memcpy(&vbus_en, prev_vbus_en, sizeof(vbus_en)); + } +} +DECLARE_HOOK(HOOK_INIT, vbus_en_restore_state, HOOK_PRIO_DEFAULT); + int board_vbus_source_enabled(int port) { return vbus_en; @@ -63,7 +89,8 @@ int pd_set_power_supply_ready(int port) gpio_set_level(GPIO_EN_USBC_CHARGE_L, 1); gpio_set_level(GPIO_EN_PP5000_USBC, 1); - if (IS_ENABLED(CONFIG_CHARGER_OTG) && IS_ENABLED(CONFIG_CHARGER_ISL9238C)) + if (IS_ENABLED(CONFIG_CHARGER_OTG) && + IS_ENABLED(CONFIG_CHARGER_ISL9238C)) charger_set_current(CHARGER_SOLO, 0); /* notify host of power info change */ @@ -104,11 +131,8 @@ void pd_power_supply_reset(int port) int pd_check_vconn_swap(int port) { - /* - * VCONN is provided directly by the battery (PPVAR_SYS) - * but use the same rules as power swap. - */ - return pd_get_dual_role(port) == PD_DRP_TOGGLE_ON ? 1 : 0; + /* always allow vconn swap, since PSYS sources VCONN */ + return 1; } /* ----------------- Vendor Defined Messages ------------------ */ @@ -119,7 +143,7 @@ __overridable int board_has_virtual_mux(void) } static void board_usb_mux_set(int port, mux_state_t mux_mode, - enum usb_switch usb_mode, int polarity) + enum usb_switch usb_mode, int polarity) { usb_mux_set(port, mux_mode, usb_mode, polarity); @@ -140,8 +164,9 @@ __override void svdm_safe_dp_mode(int port) __override int svdm_enter_dp_mode(int port, uint32_t mode_caps) { /* Kukui/Krane doesn't support superspeed lanes. */ - const uint32_t support_pin_mode = board_has_virtual_mux() ? - (MODE_DP_PIN_C | MODE_DP_PIN_E) : MODE_DP_PIN_ALL; + const uint32_t support_pin_mode = + board_has_virtual_mux() ? (MODE_DP_PIN_C | MODE_DP_PIN_E) : + MODE_DP_PIN_ALL; /** * Only enter mode if device is DFP_D (and PIN_C/E for Kukui/Krane) @@ -160,7 +185,7 @@ __override int svdm_enter_dp_mode(int port, uint32_t mode_caps) __override int svdm_dp_config(int port, uint32_t *payload) { - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); int status = dp_status[port]; int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); int pin_mode; @@ -182,11 +207,11 @@ __override int svdm_dp_config(int port, uint32_t *payload) port, mf_pref ? USB_PD_MUX_DOCK : USB_PD_MUX_DP_ENABLED, USB_SWITCH_CONNECT, board_get_polarity(port)); - payload[0] = VDO(USB_SID_DISPLAYPORT, 1, - CMD_DP_CONFIG | VDO_OPOS(opos)); - payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ - 1, /* DPv1.3 signaling */ - 2); /* UFP connected */ + payload[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); + payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ + 1, /* DPv1.3 signaling */ + 2); /* UFP connected */ return 2; }; @@ -204,7 +229,8 @@ __override void svdm_dp_post_config(int port) /* set the minimum time delay (2ms) for the next HPD IRQ */ svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; - usb_mux_hpd_update(port, 1, 0); + usb_mux_hpd_update(port, + USB_PD_MUX_HPD_LVL | USB_PD_MUX_HPD_IRQ_DEASSERTED); } __override int svdm_dp_attention(int port, uint32_t *payload) @@ -212,6 +238,7 @@ __override int svdm_dp_attention(int port, uint32_t *payload) int cur_lvl = gpio_get_level(GPIO_USB_C0_HPD_OD); int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); + mux_state_t mux_state; dp_status[port] = payload[1]; @@ -222,7 +249,9 @@ __override int svdm_dp_attention(int port, uint32_t *payload) return 1; } - usb_mux_hpd_update(port, lvl, irq); + mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | + (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); + usb_mux_hpd_update(port, mux_state); if (irq & cur_lvl) { uint64_t now = get_time().val; @@ -240,8 +269,8 @@ __override int svdm_dp_attention(int port, uint32_t *payload) #endif /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + - HPD_USTREAM_DEBOUNCE_LVL; + svdm_hpd_deadline[port] = + get_time().val + HPD_USTREAM_DEBOUNCE_LVL; } else if (irq & !lvl) { CPRINTF("ERR:HPD:IRQ&LOW\n"); return 0; /* nak */ @@ -251,8 +280,8 @@ __override int svdm_dp_attention(int port, uint32_t *payload) board_set_dp_mux_control(lvl, board_get_polarity(port)); #endif /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + - HPD_USTREAM_DEBOUNCE_LVL; + svdm_hpd_deadline[port] = + get_time().val + HPD_USTREAM_DEBOUNCE_LVL; } /* ack */ @@ -261,11 +290,11 @@ __override int svdm_dp_attention(int port, uint32_t *payload) __override void svdm_exit_dp_mode(int port) { - svdm_safe_dp_mode(port); gpio_set_level(GPIO_USB_C0_HPD_OD, 0); #ifdef VARIANT_KUKUI_DP_MUX_GPIO board_set_dp_mux_control(0, 0); #endif - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/baseboard/kukui/usb_pd_policy.h b/baseboard/kukui/usb_pd_policy.h index 78e0213f53..62d6bda062 100644 --- a/baseboard/kukui/usb_pd_policy.h +++ b/baseboard/kukui/usb_pd_policy.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/baseboard/mtscp-rv32i/baseboard.c b/baseboard/mtscp-rv32i/baseboard.c new file mode 100644 index 0000000000..e9ec4c6924 --- /dev/null +++ b/baseboard/mtscp-rv32i/baseboard.c @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* MT SCP RV32i configuration */ + +#include "cache.h" +#include "csr.h" +#include "hooks.h" +#include "panic.h" +#include "registers.h" + +#define SCP_SRAM_END (CONFIG_IPC_SHARED_OBJ_ADDR & (~(0x400 - 1))) + +struct mpu_entry mpu_entries[NR_MPU_ENTRIES] = { + /* SRAM (for most code, data) */ + { 0, SCP_SRAM_END, MPU_ATTR_C | MPU_ATTR_W | MPU_ATTR_R }, + /* SRAM (for IPI shared buffer) */ + { SCP_SRAM_END, SCP_FW_END, MPU_ATTR_W | MPU_ATTR_R }, +/* For AP domain */ +#ifdef CHIP_VARIANT_MT8195 + { 0x60000000, 0x70000000, MPU_ATTR_W | MPU_ATTR_R | MPU_ATTR_P }, +#else + { 0x60000000, 0x70000000, MPU_ATTR_W | MPU_ATTR_R }, +#endif + /* For SCP sys */ + { 0x70000000, 0x80000000, MPU_ATTR_W | MPU_ATTR_R }, +#ifdef CHIP_VARIANT_MT8195 + { 0x10000000, 0x11400000, MPU_ATTR_C | MPU_ATTR_W | MPU_ATTR_R }, + { CONFIG_PANIC_DRAM_BASE, + CONFIG_PANIC_DRAM_BASE + CONFIG_PANIC_DRAM_SIZE, + MPU_ATTR_W | MPU_ATTR_R }, +#else + { 0x10000000, 0x11400000, MPU_ATTR_W | MPU_ATTR_R }, +#endif +}; + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#ifdef CONFIG_PANIC_CONSOLE_OUTPUT +static void report_previous_panic(void) +{ + struct panic_data *panic = panic_get_data(); + + if (panic == NULL && SCP_CORE0_MON_PC_LATCH == 0) + return; + + ccprintf("[Previous Panic]\n"); + if (panic) { + panic_data_ccprint(panic); + } else { + ccprintf("No panic data\n"); + } + ccprintf("Latch PC:%x LR:%x SP:%x\n", SCP_CORE0_MON_PC_LATCH, + SCP_CORE0_MON_LR_LATCH, SCP_CORE0_MON_SP_LATCH); +} +DECLARE_HOOK(HOOK_INIT, report_previous_panic, HOOK_PRIO_DEFAULT); +#endif diff --git a/baseboard/mtscp-rv32i/baseboard.h b/baseboard/mtscp-rv32i/baseboard.h new file mode 100644 index 0000000000..49a18c8d9d --- /dev/null +++ b/baseboard/mtscp-rv32i/baseboard.h @@ -0,0 +1,76 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* MT SCP RV32i board configuration */ + +#ifndef __CROS_EC_BASEBOARD_H +#define __CROS_EC_BASEBOARD_H + +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_HOSTCMD) | CC_MASK(CC_IPI))) + +#define CONFIG_FLASH_SIZE_BYTES CONFIG_RAM_BASE +#define CONFIG_LTO +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define CONFIG_UART_CONSOLE 0 + +#ifdef CHIP_VARIANT_MT8195 +#define CONFIG_PANIC_CONSOLE_OUTPUT +#endif + +/* IPI configs */ +#define CONFIG_IPC_SHARED_OBJ_BUF_SIZE 288 +#define CONFIG_IPC_SHARED_OBJ_ADDR \ + (SCP_FW_END - \ + (CONFIG_IPC_SHARED_OBJ_BUF_SIZE + 2 * 4 /* int32_t */) * 2) +#define CONFIG_IPI +#define CONFIG_RPMSG_NAME_SERVICE + +#define SCP_IPI_INIT 0 +#define SCP_IPI_VDEC_H264 1 +#define SCP_IPI_VDEC_VP8 2 +#define SCP_IPI_VDEC_VP9 3 +#define SCP_IPI_VENC_H264 4 +#define SCP_IPI_VENC_VP8 5 +#define SCP_IPI_MDP_INIT 6 +#define SCP_IPI_MDP_DEINIT 7 +#define SCP_IPI_MDP_FRAME 8 +#define SCP_IPI_DIP 9 +#define SCP_IPI_ISP_CMD 10 +#define SCP_IPI_ISP_FRAME 11 +#define SCP_IPI_FD_CMD 12 +#define SCP_IPI_HOST_COMMAND 13 +#define SCP_IPI_VDEC_LAT 14 +#define SCP_IPI_VDEC_CORE 15 +#define SCP_IPI_COUNT 16 + +#define IPI_COUNT SCP_IPI_COUNT + +#define SCP_IPI_NS_SERVICE 0xFF + +/* Access DRAM through cached access */ +#define CONFIG_DRAM_BASE 0x10000000 +/* Shared memory address in AP physical address space. */ +#define CONFIG_DRAM_BASE_LOAD 0x50000000 +#define CONFIG_DRAM_SIZE 0x01400000 /* 20 MB */ + +/* Add some space (0x100) before panic for jump data */ +#define CONFIG_PANIC_DRAM_BASE (CONFIG_DRAM_BASE + CONFIG_DRAM_SIZE) +#define CONFIG_PANIC_DRAM_SIZE 0x00001000 /* 4K */ + +#define CONFIG_PANIC_BASE_OFFSET 0x100 /* reserved for jump data */ + +#ifdef CHIP_VARIANT_MT8195 +#define CONFIG_PANIC_DATA_BASE \ + (CONFIG_PANIC_DRAM_BASE + CONFIG_PANIC_BASE_OFFSET) +#endif + +/* MPU settings */ +#define NR_MPU_ENTRIES 16 + +#ifndef __ASSEMBLER__ +#include "gpio_signal.h" +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/mtscp-rv32i/build.mk b/baseboard/mtscp-rv32i/build.mk new file mode 100644 index 0000000000..90b8ded4a1 --- /dev/null +++ b/baseboard/mtscp-rv32i/build.mk @@ -0,0 +1,12 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Baseboard specific files build +# +baseboard-y+=baseboard.o + +baseboard-$(HAS_TASK_VDEC_SERVICE)+=vdec.o +baseboard-$(HAS_TASK_VENC_SERVICE)+=venc.o +baseboard-$(HAS_TASK_MDP_SERVICE)+=mdp.o diff --git a/baseboard/mtscp-rv32i/mdp.c b/baseboard/mtscp-rv32i/mdp.c new file mode 100644 index 0000000000..4c054dc029 --- /dev/null +++ b/baseboard/mtscp-rv32i/mdp.c @@ -0,0 +1,85 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "console.h" +#include "ipi_chip.h" +#include "mdp.h" +#include "queue_policies.h" +#include "registers.h" +#include "task.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) +#define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) + +static void event_mdp_written(struct consumer const *consumer, size_t count) +{ + task_wake(TASK_ID_MDP_SERVICE); +} +static struct consumer const event_mdp_consumer; +static struct queue const event_mdp_queue = QUEUE_DIRECT( + 4, struct mdp_msg_service, null_producer, event_mdp_consumer); +static struct consumer const event_mdp_consumer = { + .queue = &event_mdp_queue, + .ops = &((struct consumer_ops const){ + .written = event_mdp_written, + }), +}; + +/* Stub functions only provided by private overlays. */ +#ifndef HAVE_PRIVATE_MT_SCP +void mdp_common_init(void) +{ +} +void mdp_ipi_task_handler(void *pvParameters) +{ +} +#endif + +static void mdp_ipi_handler(int id, void *data, unsigned int len) +{ + struct mdp_msg_service rsv_msg; + + if (!len) { + CPRINTS("len is zero."); + return; + } + + rsv_msg.id = id; + memcpy(rsv_msg.msg, data, MIN(len, sizeof(rsv_msg.msg))); + + /* + * If there is no other IPI handler touch this queue, we don't need to + * interrupt_disable() or task_disable_irq(). + */ + if (!queue_add_unit(&event_mdp_queue, &rsv_msg)) + CPRINTS("Could not send mdp id: %d to the queue.", id); +} +DECLARE_IPI(SCP_IPI_MDP_INIT, mdp_ipi_handler, 0); +DECLARE_IPI(SCP_IPI_MDP_FRAME, mdp_ipi_handler, 0); +DECLARE_IPI(SCP_IPI_MDP_DEINIT, mdp_ipi_handler, 0); + +void mdp_service_task(void *u) +{ + struct mdp_msg_service rsv_msg; + size_t size; + + mdp_common_init(); + + while (1) { + /* + * Queue unit is added in IPI handler, which is in ISR context. + * Disable IRQ to prevent a clobbered queue. + */ + ipi_disable_irq(); + size = queue_remove_unit(&event_mdp_queue, &rsv_msg); + ipi_enable_irq(); + + if (!size) + task_wait_event(-1); + else + mdp_ipi_task_handler(&rsv_msg); + } +} diff --git a/baseboard/mtscp-rv32i/mdp.h b/baseboard/mtscp-rv32i/mdp.h new file mode 100644 index 0000000000..48f4937ace --- /dev/null +++ b/baseboard/mtscp-rv32i/mdp.h @@ -0,0 +1,20 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_SCP_MDP_H +#define __CROS_EC_SCP_MDP_H + +struct mdp_msg_service { + int id; + unsigned char msg[20]; +}; +BUILD_ASSERT(member_size(struct mdp_msg_service, msg) <= + CONFIG_IPC_SHARED_OBJ_BUF_SIZE); + +/* Functions provided by private overlay. */ +void mdp_common_init(void); +void mdp_ipi_task_handler(void *pvParameters); + +#endif /* __CROS_EC_SCP_MDP_H */ diff --git a/baseboard/mtscp-rv32i/vdec.c b/baseboard/mtscp-rv32i/vdec.c new file mode 100644 index 0000000000..7ff98fff10 --- /dev/null +++ b/baseboard/mtscp-rv32i/vdec.c @@ -0,0 +1,140 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "console.h" +#include "hooks.h" +#include "ipi_chip.h" +#include "queue.h" +#include "queue_policies.h" +#include "registers.h" +#include "task.h" +#include "util.h" +#include "vdec.h" + +#define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) +#define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) + +static void event_vdec_written(struct consumer const *consumer, size_t count) +{ + task_wake(TASK_ID_VDEC_SERVICE); +} +static struct consumer const event_vdec_consumer; +static struct queue const event_vdec_queue = + QUEUE_DIRECT(8, struct vdec_msg, null_producer, event_vdec_consumer); +static struct consumer const event_vdec_consumer = { + .queue = &event_vdec_queue, + .ops = &((struct consumer_ops const){ + .written = event_vdec_written, + }), +}; + +static void event_vdec_core_written(struct consumer const *consumer, + size_t count) +{ + task_wake(TASK_ID_VDEC_CORE_SERVICE); +} +static struct consumer const event_vdec_core_consumer; +static struct queue const event_vdec_core_queue = QUEUE_DIRECT( + 8, struct vdec_msg, null_producer, event_vdec_core_consumer); +static struct consumer const event_vdec_core_consumer = { + .queue = &event_vdec_core_queue, + .ops = &((struct consumer_ops const){ + .written = event_vdec_core_written, + }), +}; + +/* Stub functions only provided by private overlays. */ +#ifndef HAVE_PRIVATE_MT_SCP +void vdec_msg_handler(void *data) +{ +} +void vdec_core_msg_handler(void *data) +{ +} +#endif + +static void vdec_h264_ipi_handler(int id, void *data, uint32_t len) +{ + struct vdec_msg rsv_msg; + + if (!len) { + CPRINTS("len is zero."); + return; + } + + rsv_msg.type = VDEC_LAT; + memcpy(rsv_msg.msg, data, MIN(len, sizeof(rsv_msg.msg))); + + /* + * If there is no other IPI handler touch this queue, we don't need to + * interrupt_disable() or task_disable_irq(). + */ + if (!queue_add_unit(&event_vdec_queue, &rsv_msg)) + CPRINTS("Could not send vdec %d to the queue.", rsv_msg.type); +} +DECLARE_IPI(SCP_IPI_VDEC_LAT, vdec_h264_ipi_handler, 0); + +static void vdec_h264_ipi_core_handler(int id, void *data, uint32_t len) +{ + struct vdec_msg rsv_msg; + + if (!len) { + CPRINTS("len is zero."); + return; + } + + rsv_msg.type = VDEC_CORE; + memcpy(rsv_msg.msg, data, MIN(len, sizeof(rsv_msg.msg))); + + /* + * If there is no other IPI handler touch this queue, we don't need to + * interrupt_disable() or task_disable_irq(). + */ + if (!queue_add_unit(&event_vdec_core_queue, &rsv_msg)) + CPRINTS("Could not send vdec %d to core queue.", rsv_msg.type); +} +DECLARE_IPI(SCP_IPI_VDEC_CORE, vdec_h264_ipi_core_handler, 0); + +void vdec_service_task(void *u) +{ + struct vdec_msg rsv_msg; + size_t size; + + while (1) { + /* + * Queue unit is added in IPI handler, which is in ISR context. + * Disable IRQ to prevent a clobbered queue. + */ + ipi_disable_irq(); + size = queue_remove_unit(&event_vdec_queue, &rsv_msg); + ipi_enable_irq(); + + if (!size) + task_wait_event(-1); + else + vdec_msg_handler(rsv_msg.msg); + } +} + +void vdec_core_service_task(void *u) +{ + struct vdec_msg rsv_msg; + size_t size; + + while (1) { + /* + * Queue unit is added in IPI handler, which is in ISR context. + * Disable IRQ to prevent a clobbered queue. + */ + ipi_disable_irq(); + size = queue_remove_unit(&event_vdec_core_queue, &rsv_msg); + ipi_enable_irq(); + + if (!size) + task_wait_event(-1); + else + vdec_core_msg_handler(rsv_msg.msg); + } +} diff --git a/baseboard/mtscp-rv32i/vdec.h b/baseboard/mtscp-rv32i/vdec.h new file mode 100644 index 0000000000..c203c09fae --- /dev/null +++ b/baseboard/mtscp-rv32i/vdec.h @@ -0,0 +1,28 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_SCP_VDEC_H +#define __CROS_EC_SCP_VDEC_H + +#include "compile_time_macros.h" + +enum vdec_type { + VDEC_LAT, + VDEC_CORE, + VDEC_MAX, +}; + +struct vdec_msg { + enum vdec_type type; + unsigned char msg[48]; +}; +BUILD_ASSERT(member_size(struct vdec_msg, msg) <= + CONFIG_IPC_SHARED_OBJ_BUF_SIZE); + +/* Functions provided by private overlay. */ +void vdec_core_msg_handler(void *msg); +void vdec_msg_handler(void *msg); + +#endif /* __CROS_EC_SCP_VDEC_H */ diff --git a/baseboard/mtscp-rv32i/venc.c b/baseboard/mtscp-rv32i/venc.c new file mode 100644 index 0000000000..bed2a2dbc6 --- /dev/null +++ b/baseboard/mtscp-rv32i/venc.c @@ -0,0 +1,87 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "console.h" +#include "hooks.h" +#include "ipi_chip.h" +#include "queue.h" +#include "queue_policies.h" +#include "registers.h" +#include "task.h" +#include "util.h" +#include "venc.h" + +#define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) +#define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) + +static void event_venc_written(struct consumer const *consumer, size_t count) +{ + task_wake(TASK_ID_VENC_SERVICE); +} +static struct consumer const event_venc_consumer; +static struct queue const event_venc_queue = + QUEUE_DIRECT(8, struct venc_msg, null_producer, event_venc_consumer); +static struct consumer const event_venc_consumer = { + .queue = &event_venc_queue, + .ops = &((struct consumer_ops const){ + .written = event_venc_written, + }), +}; + +/* Stub functions only provided by private overlays. */ +#ifndef HAVE_PRIVATE_MT_SCP +void venc_h264_msg_handler(void *data) +{ +} +#endif + +static void venc_h264_ipi_handler(int id, void *data, uint32_t len) +{ + struct venc_msg rsv_msg; + + if (!len) { + CPRINTS("len is zero."); + return; + } + + rsv_msg.type = VENC_H264; + memcpy(rsv_msg.msg, data, MIN(len, sizeof(rsv_msg.msg))); + + /* + * If there is no other IPI handler touch this queue, we don't need to + * interrupt_disable() or task_disable_irq(). + */ + if (!queue_add_unit(&event_venc_queue, &rsv_msg)) + CPRINTS("Could not send venc %d to the queue.", rsv_msg.type); +} +DECLARE_IPI(SCP_IPI_VENC_H264, venc_h264_ipi_handler, 0); + +void venc_service_task(void *u) +{ + struct venc_msg rsv_msg; + size_t size; + + typedef void (*venc_msg_handler)(void *msg); + static venc_msg_handler mtk_venc_msg_handle[VENC_MAX] = { + [VENC_H264] = venc_h264_msg_handler, + }; + + while (1) { + /* + * Queue unit is added in IPI handler, which is in ISR context. + * Disable IRQ to prevent a clobbered queue. + */ + ipi_disable_irq(); + size = queue_remove_unit(&event_venc_queue, &rsv_msg); + ipi_enable_irq(); + + if (!size) + task_wait_event(-1); + else if (mtk_venc_msg_handle[rsv_msg.type]) + mtk_venc_msg_handle[rsv_msg.type](rsv_msg.msg); + else + CPRINTS("venc handler %d not exists.", rsv_msg.type); + } +} diff --git a/baseboard/mtscp-rv32i/venc.h b/baseboard/mtscp-rv32i/venc.h new file mode 100644 index 0000000000..c5c7df3883 --- /dev/null +++ b/baseboard/mtscp-rv32i/venc.h @@ -0,0 +1,26 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_SCP_VENC_H +#define __CROS_EC_SCP_VENC_H + +#include "compile_time_macros.h" + +enum venc_type { + VENC_H264, + VENC_MAX, +}; + +struct venc_msg { + enum venc_type type; + unsigned char msg[288]; +}; +BUILD_ASSERT(member_size(struct venc_msg, msg) <= + CONFIG_IPC_SHARED_OBJ_BUF_SIZE); + +/* Functions provided by private overlay. */ +void venc_h264_msg_handler(void *data); + +#endif /* __CROS_EC_SCP_VENC_H */ diff --git a/baseboard/nucleo-f412zg/base-board.c b/baseboard/nucleo-f412zg/base-board.c index 15e46f006e..53c42e5a26 100644 --- a/baseboard/nucleo-f412zg/base-board.c +++ b/baseboard/nucleo-f412zg/base-board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/baseboard/nucleo-f412zg/base-board.h b/baseboard/nucleo-f412zg/base-board.h index 7b69fde7c5..18e88df48c 100644 --- a/baseboard/nucleo-f412zg/base-board.h +++ b/baseboard/nucleo-f412zg/base-board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -50,28 +50,28 @@ #define CONFIG_FLASH_WRITE_SIZE STM32_FLASH_WRITE_SIZE_3300 -#define CONFIG_SHAREDLIB_SIZE 0 +#define CONFIG_SHAREDLIB_SIZE 0 -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RO_SIZE (128 * 1024) +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (128 * 1024) /* EC rollback protection block */ #define CONFIG_ROLLBACK_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) #define CONFIG_ROLLBACK_SIZE (128 * 1024 * 2) /* 2 blocks of 128KB each */ -#define CONFIG_RW_MEM_OFF (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) -#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE - \ - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) +#define CONFIG_RW_MEM_OFF (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) -#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE +#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* * We want to prevent flash readout, and use it as indicator of protection @@ -116,7 +116,7 @@ */ #undef CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE #ifdef SECTION_IS_RW - #undef CONFIG_ROLLBACK_UPDATE +#undef CONFIG_ROLLBACK_UPDATE #endif /*-------------------------------------------------------------------------* @@ -124,9 +124,9 @@ *-------------------------------------------------------------------------*/ #ifdef SECTION_IS_RO - /* RO verifies the RW partition signature */ - #define CONFIG_RSA - #define CONFIG_RWSIG +/* RO verifies the RW partition signature */ +#define CONFIG_RSA +#define CONFIG_RWSIG #endif /* SECTION_IS_RO */ #define CONFIG_RSA_KEY_SIZE 3072 #define CONFIG_RSA_EXPONENT_3 @@ -157,44 +157,40 @@ * Other *-------------------------------------------------------------------------*/ -#define CONFIG_AES -#define CONFIG_AES_GCM -#define CONFIG_DMA +#define CONFIG_BORINGSSL_CRYPTO +#define CONFIG_DMA_CROS #define CONFIG_FPU #define CONFIG_HOST_COMMAND_STATUS #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -#define CONFIG_PRINTF_LEGACY_LI_FORMAT +#define CONFIG_PRINTF_LONG_IS_32BITS #define CONFIG_RNG #define CONFIG_SHA256 #define CONFIG_SHA256_UNROLLED -#define CONFIG_STM_HWTIMER32 -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY #define CONFIG_WP_ACTIVE_HIGH #ifndef TEST_BUILD - /* TODO(hesling): Fix the illogical dependency between spi.c - * and host_command.c - * - * Currently, the chip/stm32/spi.c depends on functions defined in - * common/host_command.c. When unit test builds use their own tasklist - * without the HOSTCMD task, host_command.c is excluded from the build, - * but chip/stm32/spi.c remains (because of CONFIG_SPI). - * This triggers an undefined reference linker error. - * The reproduce case: - * - Allow CONFIG_SPI in TEST_BUILDs - * - make BOARD=nucleo-h743zi tests - */ - #define CONFIG_SPI +/* TODO(hesling): Fix the illogical dependency between spi.c + * and host_command.c + * + * Currently, the chip/stm32/spi.c depends on functions defined in + * common/host_command.c. When unit test builds use their own tasklist + * without the HOSTCMD task, host_command.c is excluded from the build, + * but chip/stm32/spi.c remains (because of CONFIG_SPI). + * This triggers an undefined reference linker error. + * The reproduce case: + * - Allow CONFIG_SPI in TEST_BUILDs + * - make BOARD=nucleo-h743zi tests + */ +#define CONFIG_SPI #endif #ifndef __ASSEMBLER__ - /* Timer selection */ - #define TIM_CLOCK32 2 - #define TIM_WATCHDOG 16 - #include "gpio_signal.h" - void button_event(enum gpio_signal signal); +/* Timer selection */ +#define TIM_CLOCK32 2 +#define TIM_WATCHDOG 16 +#include "gpio_signal.h" +void button_event(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BASE_BOARD_H */ diff --git a/baseboard/nucleo-f412zg/base-gpio.inc b/baseboard/nucleo-f412zg/base-gpio.inc index 4ebd99f91f..d0c48a46e5 100644 --- a/baseboard/nucleo-f412zg/base-gpio.inc +++ b/baseboard/nucleo-f412zg/base-gpio.inc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/baseboard/nucleo-f412zg/build.mk b/baseboard/nucleo-f412zg/build.mk index 1456331fec..d38a618d8c 100644 --- a/baseboard/nucleo-f412zg/build.mk +++ b/baseboard/nucleo-f412zg/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/baseboard/nucleo-f412zg/openocd-flash.cfg b/baseboard/nucleo-f412zg/openocd-flash.cfg index 3333d1163a..cbc9fe0218 100644 --- a/baseboard/nucleo-f412zg/openocd-flash.cfg +++ b/baseboard/nucleo-f412zg/openocd-flash.cfg @@ -1,4 +1,4 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/baseboard/nucleo-f412zg/openocd.cfg b/baseboard/nucleo-f412zg/openocd.cfg index 589d4400f4..3b286a4ebc 100644 --- a/baseboard/nucleo-f412zg/openocd.cfg +++ b/baseboard/nucleo-f412zg/openocd.cfg @@ -1,4 +1,4 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/baseboard/nucleo-h743zi/base-board.c b/baseboard/nucleo-h743zi/base-board.c index 15e46f006e..53c42e5a26 100644 --- a/baseboard/nucleo-h743zi/base-board.c +++ b/baseboard/nucleo-h743zi/base-board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/baseboard/nucleo-h743zi/base-board.h b/baseboard/nucleo-h743zi/base-board.h index 0bf91efd83..936b2c6e1c 100644 --- a/baseboard/nucleo-h743zi/base-board.h +++ b/baseboard/nucleo-h743zi/base-board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -53,24 +53,25 @@ * * We need 2 independently erasable blocks, at a minimum. */ -#define CONFIG_ROLLBACK_SIZE (2 * CONFIG_FLASH_BANK_SIZE) -#define CONFIG_ROLLBACK_OFF ((CONFIG_FLASH_SIZE / 2) - CONFIG_ROLLBACK_SIZE) +#define CONFIG_ROLLBACK_SIZE (2 * CONFIG_FLASH_BANK_SIZE) +#define CONFIG_ROLLBACK_OFF \ + ((CONFIG_FLASH_SIZE_BYTES / 2) - CONFIG_ROLLBACK_SIZE) -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_SIZE CONFIG_ROLLBACK_OFF -#define CONFIG_RW_MEM_OFF (CONFIG_FLASH_SIZE / 2) -#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE / 2) +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_SIZE CONFIG_ROLLBACK_OFF +#define CONFIG_RW_MEM_OFF (CONFIG_FLASH_SIZE_BYTES / 2) +#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE_BYTES / 2) -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE +#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* Disabled features */ @@ -82,42 +83,38 @@ /* Enabled features */ -#define CONFIG_AES -#define CONFIG_AES_GCM -#define CONFIG_DMA +#define CONFIG_BORINGSSL_CRYPTO +#define CONFIG_DMA_CROS #define CONFIG_FORCE_CONSOLE_RESUME #define CONFIG_FPU #define CONFIG_HOST_COMMAND_STATUS #define CONFIG_LOW_POWER_IDLE #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -#define CONFIG_PRINTF_LEGACY_LI_FORMAT +#define CONFIG_PRINTF_LONG_IS_32BITS #define CONFIG_RNG #define CONFIG_RWSIG_TYPE_RWSIG #define CONFIG_SHA256 #define CONFIG_SHA256_UNROLLED #undef CONFIG_SHAREDLIB_SIZE -#define CONFIG_SHAREDLIB_SIZE 0 -#define CONFIG_STM_HWTIMER32 -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY +#define CONFIG_SHAREDLIB_SIZE 0 #define CONFIG_WATCHDOG_HELP #define CONFIG_WP_ACTIVE_HIGH #ifndef TEST_BUILD - /* TODO(hesling): Fix the illogical dependency between spi.c - * and host_command.c - * - * Currently, the chip/stm32/spi.c depends on functions defined in - * common/host_command.c. When unit test builds use their own tasklist - * without the HOSTCMD task, host_command.c is excluded from the build, - * but chip/stm32/spi.c remains (because of CONFIG_SPI). - * This triggers an undefined reference linker error. - * The reproduce case: - * - Allow CONFIG_SPI in TEST_BUILDs - * - make BOARD=nucleo-h743zi tests - */ -# define CONFIG_SPI +/* TODO(hesling): Fix the illogical dependency between spi.c + * and host_command.c + * + * Currently, the chip/stm32/spi.c depends on functions defined in + * common/host_command.c. When unit test builds use their own tasklist + * without the HOSTCMD task, host_command.c is excluded from the build, + * but chip/stm32/spi.c remains (because of CONFIG_SPI). + * This triggers an undefined reference linker error. + * The reproduce case: + * - Allow CONFIG_SPI in TEST_BUILDs + * - make BOARD=nucleo-h743zi tests + */ +#define CONFIG_SPI #endif /* @@ -147,10 +144,10 @@ #define CONFIG_CMD_IDLE_STATS #ifdef SECTION_IS_RO - /* RO verifies the RW partition signature */ -# define CONFIG_RSA -# define CONFIG_RWSIG -#endif /* SECTION_IS_RO */ +/* RO verifies the RW partition signature */ +#define CONFIG_RSA +#define CONFIG_RWSIG +#endif /* SECTION_IS_RO */ #define CONFIG_RSA_KEY_SIZE 3072 #define CONFIG_RSA_EXPONENT_3 @@ -161,7 +158,7 @@ */ #undef CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE #ifdef SECTION_IS_RW -# undef CONFIG_ROLLBACK_UPDATE +#undef CONFIG_ROLLBACK_UPDATE #endif /* * Add rollback protection @@ -170,11 +167,11 @@ #define CONFIG_ROLLBACK_MPU_PROTECT #ifndef __ASSEMBLER__ - /* Timer selection */ -# define TIM_CLOCK32 2 -# define TIM_WATCHDOG 16 -# include "gpio_signal.h" - void button_event(enum gpio_signal signal); +/* Timer selection */ +#define TIM_CLOCK32 2 +#define TIM_WATCHDOG 16 +#include "gpio_signal.h" +void button_event(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BASE_BOARD_H */ diff --git a/baseboard/nucleo-h743zi/base-ec.tasklist b/baseboard/nucleo-h743zi/base-ec.tasklist index fae8952113..e8e752aa4e 100644 --- a/baseboard/nucleo-h743zi/base-ec.tasklist +++ b/baseboard/nucleo-h743zi/base-ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/baseboard/nucleo-h743zi/base-gpio.inc b/baseboard/nucleo-h743zi/base-gpio.inc index ef224cbaf1..ad7d313328 100644 --- a/baseboard/nucleo-h743zi/base-gpio.inc +++ b/baseboard/nucleo-h743zi/base-gpio.inc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/baseboard/nucleo-h743zi/build.mk b/baseboard/nucleo-h743zi/build.mk index e9f9ae3faa..36c0cfdf50 100644 --- a/baseboard/nucleo-h743zi/build.mk +++ b/baseboard/nucleo-h743zi/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,4 +11,4 @@ CHIP:=stm32 CHIP_FAMILY:=stm32h7 CHIP_VARIANT:=stm32h7x3 -baseboard-y=base-board.o \ No newline at end of file +baseboard-y=base-board.o diff --git a/baseboard/nucleo-h743zi/openocd-flash.cfg b/baseboard/nucleo-h743zi/openocd-flash.cfg index 4517266d7b..8ee5dd6707 100644 --- a/baseboard/nucleo-h743zi/openocd-flash.cfg +++ b/baseboard/nucleo-h743zi/openocd-flash.cfg @@ -1,4 +1,4 @@ -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/baseboard/nucleo-h743zi/openocd.cfg b/baseboard/nucleo-h743zi/openocd.cfg index 528e8d6cab..9fa8aa89a9 100644 --- a/baseboard/nucleo-h743zi/openocd.cfg +++ b/baseboard/nucleo-h743zi/openocd.cfg @@ -1,4 +1,4 @@ -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/baseboard/octopus/baseboard.c b/baseboard/octopus/baseboard.c index 105a3bf71c..164e28b480 100644 --- a/baseboard/octopus/baseboard.c +++ b/baseboard/octopus/baseboard.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -27,12 +27,12 @@ #include "usbc_ppc.h" #include "util.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) /******************************************************************************/ /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * F3 key scan cycle completed but scan input is not * charging to logic high when EC start scan next @@ -218,9 +218,9 @@ int board_is_i2c_port_powered(int port) enum adc_channel board_get_vbus_adc(int port) { if (port == 0) - return ADC_VBUS_C0; + return ADC_VBUS_C0; if (port == 1) - return ADC_VBUS_C1; + return ADC_VBUS_C1; CPRINTSUSB("Unknown vbus adc port id: %d", port); return ADC_VBUS_C0; } @@ -237,27 +237,27 @@ void baseboard_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < board_get_usb_pd_port_count(); ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } /* Called after the cbi_init (via +2) */ DECLARE_HOOK(HOOK_INIT, baseboard_tcpc_init, HOOK_PRIO_INIT_I2C + 2); int board_set_active_charge_port(int port) { - int is_valid_port = (port >= 0 && - port < board_get_usb_pd_port_count()); + int is_valid_port = (port >= 0 && port < board_get_usb_pd_port_count()); int i; if (!is_valid_port && port != CHARGE_PORT_NONE) return EC_ERROR_INVAL; - if (port == CHARGE_PORT_NONE) { CPRINTSUSB("Disabling all charger ports"); /* Disable all ports. */ - for (i = 0; (i < ppc_cnt) && - (i < board_get_usb_pd_port_count()); i++) { + for (i = 0; + (i < ppc_cnt) && (i < board_get_usb_pd_port_count()); + i++) { /* * Do not return early if one fails otherwise we can * get into a boot loop assertion failure. @@ -281,8 +281,7 @@ int board_set_active_charge_port(int port) * Turn off the other ports' sink path FETs, before enabling the * requested charge port. */ - for (i = 0; (i < ppc_cnt) && - (i < board_get_usb_pd_port_count()); i++) { + for (i = 0; (i < ppc_cnt) && (i < board_get_usb_pd_port_count()); i++) { if (i == port) continue; @@ -299,21 +298,6 @@ int board_set_active_charge_port(int port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* - * Empirically, the charger seems to draw a little more current that - * it is set to, so we reduce our limit by 5%. - */ -#ifdef VARIANT_OCTOPUS_CHARGER_ISL9238 - charge_ma = (charge_ma * 95) / 100; -#endif - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} - void board_hibernate(void) { int port; @@ -379,5 +363,5 @@ void board_hibernate(void) * with any PD contract renegotiation, and tcpm to put TCPC into low * power mode if required. */ - msleep(300); + msleep(1500); } diff --git a/baseboard/octopus/baseboard.h b/baseboard/octopus/baseboard.h index c8e4b24e56..cb09ca8e89 100644 --- a/baseboard/octopus/baseboard.h +++ b/baseboard/octopus/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,15 +12,13 @@ * EC Config */ +#define CONFIG_LTO + /* * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_USB_PD_DISCOVERY,\ - EC_CMD_USB_PD_POWER_INFO, EC_CMD_PD_GET_LOG_ENTRY, \ - EC_CMD_MOTION_SENSE_CMD, EC_CMD_GET_NEXT_EVENT +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) /* * Variant EC defines. Pick one: @@ -28,65 +26,82 @@ * VARIANT_OCTOPUS_EC_ITE8320 */ #if defined(VARIANT_OCTOPUS_EC_NPCX796FB) - /* NPCX7 config */ - #define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ - #define NPCX_TACH_SEL2 0 /* [0:GPIO40/73, 1:GPIO93/A6] as TACH */ - #define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ - - /* Internal SPI flash on NPCX7 */ - /* Flash is 1MB but reserve half for future use. */ - #define CONFIG_FLASH_SIZE (512 * 1024) - - #define CONFIG_SPI_FLASH_REGS - #define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ - - /* I2C Bus Configuration */ - #define I2C_PORT_BATTERY NPCX_I2C_PORT0_0 - #define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 - #define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 - #define I2C_PORT_EEPROM NPCX_I2C_PORT3_0 - #define I2C_PORT_CHARGER NPCX_I2C_PORT4_1 - #define I2C_PORT_SENSOR NPCX_I2C_PORT7_0 - #define I2C_ADDR_EEPROM_FLAGS 0x50 - - /* Enable PSL hibernate mode. */ - #define CONFIG_HIBERNATE_PSL - - /* EC variant determines USB-C variant */ - #define VARIANT_OCTOPUS_USBC_STANDALONE_TCPCS - - /* Allow the EC to enter deep sleep in S0 */ - #define CONFIG_LOW_POWER_S0 +/* NPCX7 config */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX_TACH_SEL2 0 /* [0:GPIO40/73, 1:GPIO93/A6] as TACH */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ + +/* Internal SPI flash on NPCX7 */ +/* Flash is 1MB but reserve half for future use. */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) + +#define CONFIG_SPI_FLASH_REGS +#define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ + +/* I2C Bus Configuration */ +#define I2C_PORT_BATTERY NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT3_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT4_1 +#define I2C_PORT_SENSOR NPCX_I2C_PORT7_0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* Enable PSL hibernate mode. */ +#define CONFIG_HIBERNATE_PSL + +/* EC variant determines USB-C variant */ +#define VARIANT_OCTOPUS_USBC_STANDALONE_TCPCS + +/* Allow the EC to enter deep sleep in S0 */ +#define CONFIG_LOW_POWER_S0 + +/* + * Increase period to prevent false positive hangs (b/255368431). + * TODO(b/281584278): Reevaluate period when more data is available. + */ +#undef CONFIG_WATCHDOG_PERIOD_MS +#define CONFIG_WATCHDOG_PERIOD_MS 2100 + #elif defined(VARIANT_OCTOPUS_EC_ITE8320) - /* I2C Bus Configuration */ - #define I2C_PORT_BATTERY IT83XX_I2C_CH_A /* Shared bus */ - #define I2C_PORT_CHARGER IT83XX_I2C_CH_A /* Shared bus */ - #define I2C_PORT_SENSOR IT83XX_I2C_CH_B - #define I2C_PORT_USBC0 IT83XX_I2C_CH_C - #define I2C_PORT_USBC1 IT83XX_I2C_CH_E - #define I2C_PORT_USB_MUX I2C_PORT_USBC0 /* For MUX driver */ - #define I2C_PORT_EEPROM IT83XX_I2C_CH_F - #define I2C_ADDR_EEPROM_FLAGS 0x50 - #define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 - - /* EC variant determines USB-C variant */ - #define VARIANT_OCTOPUS_USBC_ITE_EC_TCPCS +/* IT83XX config */ +#define CONFIG_IT83XX_VCC_1P8V +/* I2C Bus Configuration */ +#define I2C_PORT_BATTERY IT83XX_I2C_CH_A /* Shared bus */ +#define I2C_PORT_CHARGER IT83XX_I2C_CH_A /* Shared bus */ +#define I2C_PORT_SENSOR IT83XX_I2C_CH_B +#define I2C_PORT_USBC0 IT83XX_I2C_CH_C +#define I2C_PORT_USBC1 IT83XX_I2C_CH_E +#define I2C_PORT_USB_MUX I2C_PORT_USBC0 /* For MUX driver */ +#define I2C_PORT_EEPROM IT83XX_I2C_CH_F +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 + +/* EC variant determines USB-C variant */ +#define VARIANT_OCTOPUS_USBC_ITE_EC_TCPCS + +/* + * Limit maximal ODR to 125Hz, the EC is using ~5ms per sample at + * 48MHz core cpu clock. + */ +#define CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ 125000 #else - #error Must define a VARIANT_OCTOPUS_EC +#error Must define a VARIANT_OCTOPUS_EC #endif /* VARIANT_OCTOPUS_EC */ /* Common EC defines */ #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_I2C_BUS_MAY_BE_UNPOWERED #define CONFIG_VBOOT_HASH #define CONFIG_VSTORE #define CONFIG_VSTORE_SLOT_COUNT 1 #define CONFIG_CRC8 -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_BOARD_VERSION_CBI #define CONFIG_LOW_POWER_IDLE #define CONFIG_DPTF +#define CONFIG_DO_NOT_INCLUDE_RV32I_PANIC_DATA #define CONFIG_BOARD_HAS_RTC_RESET #define CONFIG_LED_ONOFF_STATES #define CONFIG_CMD_CHARGEN @@ -110,39 +125,55 @@ * VARIANT_OCTOPUS_CHARGER_BQ25703 */ #if defined(VARIANT_OCTOPUS_CHARGER_ISL9238) - #define CONFIG_CHARGER_ISL9238 - #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 - /* - * ISL923x driver sets "Adapter insertion to Switching Debounce" - * CONTROL2 REG 0x3DH to 1 which is 150 ms - */ - #undef CONFIG_EXTPOWER_DEBOUNCE_MS - #define CONFIG_EXTPOWER_DEBOUNCE_MS 200 +#define CONFIG_CHARGER_ISL9238 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 +/* + * ISL923x driver sets "Adapter insertion to Switching Debounce" + * CONTROL2 REG 0x3DH to 1 which is 150 ms + */ +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 200 +/* Charger seems to overdraw by about 5% */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #elif defined(VARIANT_OCTOPUS_CHARGER_BQ25703) - #define CONFIG_CHARGER_BQ25703 - #define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 - /* - * From BQ25703: CHRG_OK is HIGH after 50ms deglitch time. - */ - #undef CONFIG_EXTPOWER_DEBOUNCE_MS - #define CONFIG_EXTPOWER_DEBOUNCE_MS 50 +#define CONFIG_CHARGER_BQ25703 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +/* + * From BQ25703: CHRG_OK is HIGH after 50ms deglitch time. + */ +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 50 +/* Charger seems to overdraw by about 5% */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 +#elif defined(CONFIG_CHARGER_RUNTIME_CONFIG) +#define CONFIG_CHARGER_ISL9238 +#define CONFIG_CHARGER_BQ25710 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC_ISL9238 20 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 + +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 200 #else - #error Must define a VARIANT_OCTOPUS_CHARGER +#error Must define a VARIANT_OCTOPUS_CHARGER #endif /* VARIANT_OCTOPUS_CHARGER */ /* Common charger defines */ #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGE_RAMP_HW #define CONFIG_CHARGER -#define CONFIG_CHARGER_INPUT_CURRENT 512 /* Allow low-current USB charging */ -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 +/* Allow low-current USB charging */ +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_DISCHARGE_ON_AC #define CONFIG_USB_CHARGER /* Common battery defines */ #define CONFIG_BATTERY_CUT_OFF -#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_FUEL_GAUGE #define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_L #define CONFIG_BATTERY_REVIVE_DISCONNECT @@ -153,43 +184,45 @@ * Automatically defined by VARIANT_OCTOPUS_EC_ variant. */ - /* - * Variant USBC defines. Pick one: - * VARIANT_OCTOPUS_USBC_STANDALONE_TCPCS - * VARIANT_OCTOPUS_USBC_ITE_EC_TCPCS (requires) - */ +/* + * Variant USBC defines. Pick one: + * VARIANT_OCTOPUS_USBC_STANDALONE_TCPCS + * VARIANT_OCTOPUS_USBC_ITE_EC_TCPCS (requires) + */ #if defined(VARIANT_OCTOPUS_USBC_STANDALONE_TCPCS) - #define CONFIG_USB_PD_TCPC_LOW_POWER - #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE #if !defined(VARIANT_OCTOPUS_TCPC_0_PS8751) - #define CONFIG_USB_PD_TCPM_ANX7447 /* C0 TCPC: ANX7447QN */ +#define CONFIG_USB_PD_TCPM_ANX7447 /* C0 TCPC: ANX7447QN */ #endif - #define CONFIG_USB_PD_TCPM_PS8751 /* C1 TCPC: PS8751 */ - #define CONFIG_USB_PD_VBUS_DETECT_TCPC - #define CONFIG_USBC_PPC_NX20P3483 +#define CONFIG_USB_PD_TCPM_PS8751 /* C1 TCPC: PS8751 */ +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USBC_PPC_NX20P3483 #elif defined(VARIANT_OCTOPUS_USBC_ITE_EC_TCPCS) - #undef CONFIG_USB_PD_TCPC_LOW_POWER - #undef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - #define CONFIG_USB_PD_VBUS_DETECT_PPC - #define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0 & C1 TCPC: ITE EC */ - #define CONFIG_USB_MUX_IT5205 /* C0 MUX: IT5205 */ - #define CONFIG_USB_PD_TCPM_PS8751 /* C1 Mux: PS8751 */ - #define CONFIG_USBC_PPC_SN5S330 /* C0 & C1 PPC: each SN5S330 */ - #define CONFIG_USBC_PPC_VCONN - #define CONFIG_USBC_PPC_DEDICATED_INT +#undef CONFIG_USB_PD_TCPC_LOW_POWER +#undef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0 & C1 TCPC: ITE EC */ +#define CONFIG_USB_MUX_IT5205 /* C0 MUX: IT5205 */ +#define CONFIG_USB_PD_TCPM_PS8751 /* C1 Mux: PS8751 */ +#define CONFIG_USB_PD_TCPM_PS8751_CUSTOM_MUX_DRIVER +#define CONFIG_USBC_PPC_SN5S330 /* C0 & C1 PPC: each SN5S330 */ +#define CONFIG_USBC_PPC_VCONN +#define CONFIG_USBC_PPC_DEDICATED_INT #else - #error Must define a VARIANT_OCTOPUS_USBC +#error Must define a VARIANT_OCTOPUS_USBC #endif /* VARIANT_OCTOPUS_USBC */ /* Common USB-C defines */ -#define USB_PD_PORT_TCPC_0 0 -#define USB_PD_PORT_TCPC_1 1 +#define USB_PD_PORT_TCPC_0 0 +#define USB_PD_PORT_TCPC_1 1 #define CONFIG_USB_PID 0x5046 #define CONFIG_USB_DRP_ACC_TRYSRC #define CONFIG_USB_PD_DECODE_SOP #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_TCPMV2 +#define CONFIG_USB_PD_3A_PORTS 0 #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_LOGGING @@ -205,19 +238,20 @@ #define CONFIG_USB_PD_TCPM_MUX #define CONFIG_USB_PD_TCPM_TCPCI #define CONFIG_BC12_DETECT_MAX14637 +#undef CONFIG_BC12_MAX14637_DELAY_FROM_OFF_TO_ON_MS +#define CONFIG_BC12_MAX14637_DELAY_FROM_OFF_TO_ON_MS 100 #define CONFIG_HOSTCMD_PD_CONTROL #define CONFIG_CMD_PPC_DUMP /* TODO(b/76218141): Use correct PD delay values */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* TODO(b/76218141): Use correct PD power values */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /******************************************************************************* * USB-A Configs @@ -236,10 +270,10 @@ * SoC / PCH Config */ - /* Common SoC / PCH defines */ +/* Common SoC / PCH defines */ #define CONFIG_CHIPSET_GEMINILAKE #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI /* TODO(b/74123961): Enable Virtual Wires after bringup */ #define CONFIG_POWER_COMMON #define CONFIG_POWER_S0IX @@ -255,11 +289,11 @@ /* Common Keyboard Defines */ #define CONFIG_CMD_KEYBOARD -#define CONFIG_KEYBOARD_BOARD_CONFIG + #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2 -#undef CONFIG_KEYBOARD_VIVALDI +#undef CONFIG_KEYBOARD_VIVALDI /******************************************************************************* * Sensor Config @@ -268,11 +302,10 @@ /* Common Sensor Defines */ #define CONFIG_TABLET_MODE #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L /* * Slew rate on the PP1800_SENSOR load switch requires a short delay on startup. */ -#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US +#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US #define CONFIG_MOTION_SENSE_RESUME_DELAY_US (10 * MSEC) #ifndef VARIANT_OCTOPUS_NO_SENSORS @@ -280,7 +313,6 @@ * Interrupt and fifo are only used for base accelerometer * and the lid sensor is polled real-time (in forced mode). */ -#define CONFIG_ACCEL_INTERRUPTS /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO /* Power of 2 - Too large of a fifo causes too much timestamp jitter */ @@ -289,6 +321,9 @@ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) #endif /* VARIANT_OCTOPUS_NO_SENSORS */ +/* System safe mode for improved panic debugging */ +#define CONFIG_SYSTEM_SAFE_MODE + /* * Sensor stack in EC/Kernel depends on a hardware interrupt pin from EC->AP, so * do not define CONFIG_MKBP_USE_HOST_EVENT since all octopus boards use @@ -297,6 +332,14 @@ #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO +/* Free up more flash. */ +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_MFALLOW +#undef CONFIG_CMD_MD +#undef CONFIG_CMD_MMAPINFO +#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CONSOLE_HISTORY + #ifndef __ASSEMBLER__ #include "gpio_signal.h" diff --git a/baseboard/octopus/build.mk b/baseboard/octopus/build.mk index bb8a6f8267..696f60d42e 100644 --- a/baseboard/octopus/build.mk +++ b/baseboard/octopus/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/baseboard/octopus/cbi_ssfc.c b/baseboard/octopus/cbi_ssfc.c index 1fa45f7338..827d2e045e 100644 --- a/baseboard/octopus/cbi_ssfc.c +++ b/baseboard/octopus/cbi_ssfc.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -37,3 +37,13 @@ enum ssfc_ppc_p1 get_cbi_ssfc_ppc_p1(void) { return ((cached_ssfc & SSFC_PPC_P1_MASK) >> SSFC_PPC_P1_OFFSET); } + +enum ssfc_charger get_cbi_ssfc_charger(void) +{ + return ((cached_ssfc & SSFC_CHARGER_MASK) >> SSFC_CHARGER_OFFSET); +} + +enum ssfc_sensor get_cbi_ssfc_sensor(void) +{ + return ((cached_ssfc & SSFC_SENSOR_MASK) >> SSFC_SENSOR_OFFSET); +} diff --git a/baseboard/octopus/cbi_ssfc.h b/baseboard/octopus/cbi_ssfc.h index 07ed4c958d..570c240da1 100644 --- a/baseboard/octopus/cbi_ssfc.h +++ b/baseboard/octopus/cbi_ssfc.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,8 +18,8 @@ enum ssfc_tcpc_p1 { SSFC_TCPC_P1_PS8751, SSFC_TCPC_P1_PS8755, }; -#define SSFC_TCPC_P1_OFFSET 0 -#define SSFC_TCPC_P1_MASK GENMASK(2, 0) +#define SSFC_TCPC_P1_OFFSET 0 +#define SSFC_TCPC_P1_MASK GENMASK(2, 0) /* * PPC Port 1 (Bits 3-5) @@ -29,10 +29,39 @@ enum ssfc_ppc_p1 { SSFC_PPC_P1_NX20P348X, SSFC_PPC_P1_SYV682X, }; -#define SSFC_PPC_P1_OFFSET 3 -#define SSFC_PPC_P1_MASK GENMASK(5, 3) +#define SSFC_PPC_P1_OFFSET 3 +#define SSFC_PPC_P1_MASK GENMASK(5, 3) + +/* + * Charger (Bits 8-6) + */ +enum ssfc_charger { + SSFC_CHARGER_DEFAULT, + SSFC_CHARGER_ISL9238, + SSFC_CHARGER_BQ25710, +}; +#define SSFC_CHARGER_OFFSET 6 +#define SSFC_CHARGER_MASK GENMASK(8, 6) + +/* + * Audio (Bits 11-9) + */ + +/* + * Sensor (Bits 14-12) + */ +enum ssfc_sensor { + SSFC_SENSOR_DEFAULT, + SSFC_SENSOR_BMI160, + SSFC_SENSOR_ICM426XX, + SSFC_SENSOR_BMI260, +}; +#define SSFC_SENSOR_OFFSET 12 +#define SSFC_SENSOR_MASK GENMASK(14, 12) enum ssfc_tcpc_p1 get_cbi_ssfc_tcpc_p1(void); enum ssfc_ppc_p1 get_cbi_ssfc_ppc_p1(void); +enum ssfc_charger get_cbi_ssfc_charger(void); +enum ssfc_sensor get_cbi_ssfc_sensor(void); #endif /* _OCTOPUS_CBI_SSFC__H_ */ diff --git a/baseboard/octopus/usb_pd_policy.c b/baseboard/octopus/usb_pd_policy.c index dcd7b41ee1..c8b8b96d3a 100644 --- a/baseboard/octopus/usb_pd_policy.c +++ b/baseboard/octopus/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,8 +17,8 @@ #include "usbc_ppc.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -39,11 +39,6 @@ void pd_power_supply_reset(int port) if (prev_en) pd_set_vbus_discharge(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -64,11 +59,6 @@ int pd_set_power_supply_ready(int port) if (rv) return rv; -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/baseboard/octopus/variant_ec_ite8320.c b/baseboard/octopus/variant_ec_ite8320.c index 459ea113b3..e79f4cdb01 100644 --- a/baseboard/octopus/variant_ec_ite8320.c +++ b/baseboard/octopus/variant_ec_ite8320.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -28,10 +28,30 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /******************************************************************************/ /* I2C port map configuration */ const struct i2c_port_t i2c_ports[] = { - {"power", IT83XX_I2C_CH_A, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"sensor", IT83XX_I2C_CH_B, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"usbc0", IT83XX_I2C_CH_C, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"usbc1", IT83XX_I2C_CH_E, 400, GPIO_I2C4_SCL, GPIO_I2C4_SDA}, - {"eeprom", IT83XX_I2C_CH_F, 100, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, + { .name = "power", + .port = IT83XX_I2C_CH_A, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "sensor", + .port = IT83XX_I2C_CH_B, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "usbc0", + .port = IT83XX_I2C_CH_C, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "usbc1", + .port = IT83XX_I2C_CH_E, + .kbps = 400, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA }, + { .name = "eeprom", + .port = IT83XX_I2C_CH_F, + .kbps = 100, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/baseboard/octopus/variant_ec_npcx796fb.c b/baseboard/octopus/variant_ec_npcx796fb.c index bccb360563..23a4f58bae 100644 --- a/baseboard/octopus/variant_ec_npcx796fb.c +++ b/baseboard/octopus/variant_ec_npcx796fb.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -31,13 +31,37 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /******************************************************************************/ /* I2C port map configuration */ const struct i2c_port_t i2c_ports[] = { - {"battery", I2C_PORT_BATTERY, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"eeprom", I2C_PORT_EEPROM, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"charger", I2C_PORT_CHARGER, 100, GPIO_I2C4_SCL, GPIO_I2C4_SDA}, + { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "charger", + .port = I2C_PORT_CHARGER, + .kbps = 100, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA }, #ifndef VARIANT_OCTOPUS_NO_SENSORS - {"sensor", I2C_PORT_SENSOR, 100, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 100, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, #endif }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -46,8 +70,9 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = PWM_CONFIG_DSLEEP, - .freq = 100 }, + [PWM_CH_KBLIGHT] = { .channel = 3, + .flags = PWM_CONFIG_DSLEEP, + .freq = 100 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); #endif diff --git a/baseboard/octopus/variant_usbc_ec_tcpcs.c b/baseboard/octopus/variant_usbc_ec_tcpcs.c index 2635850bd8..a93dfe3535 100644 --- a/baseboard/octopus/variant_usbc_ec_tcpcs.c +++ b/baseboard/octopus/variant_usbc_ec_tcpcs.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,20 +10,20 @@ #include "console.h" #include "driver/ppc/sn5s330.h" #include "driver/tcpm/it83xx_pd.h" -#include "driver/usb_mux/it5205.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" +#include "driver/usb_mux/it5205.h" #include "gpio.h" #include "hooks.h" #include "system.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define USB_PD_PORT_ITE_0 0 -#define USB_PD_PORT_ITE_1 1 +#define USB_PD_PORT_ITE_0 0 +#define USB_PD_PORT_ITE_1 1 /******************************************************************************/ /* USB-C TPCP Configuration */ @@ -49,10 +49,15 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { /* TODO(crbug.com/826441): Consolidate this logic with other impls */ static void board_it83xx_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) + mux_state_t mux_state, bool *ack_required) { - enum gpio_signal gpio = me->usb_port ? - GPIO_USB_C1_HPD_1V8_ODL : GPIO_USB_C0_HPD_1V8_ODL; + int hpd_lvl = (mux_state & USB_PD_MUX_HPD_LVL) ? 1 : 0; + int hpd_irq = (mux_state & USB_PD_MUX_HPD_IRQ) ? 1 : 0; + enum gpio_signal gpio = me->usb_port ? GPIO_USB_C1_HPD_1V8_ODL : + GPIO_USB_C0_HPD_1V8_ODL; + + /* This driver does not use host command ACKs */ + *ack_required = false; /* Invert HPD level since GPIOs are active low. */ hpd_lvl = !hpd_lvl; @@ -66,38 +71,38 @@ static void board_it83xx_hpd_status(const struct usb_mux *me, } /* This configuration might be override by each boards */ -struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_ITE_0] = { - .usb_port = USB_PD_PORT_ITE_0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_it83xx_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_ITE_0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_it83xx_hpd_status, + }, }, [USB_PD_PORT_ITE_1] = { - .usb_port = USB_PD_PORT_ITE_1, - /* Use PS8751 as mux only */ - .i2c_port = I2C_PORT_USBC1, - .i2c_addr_flags = PS8751_I2C_ADDR1_FLAGS, - .flags = USB_MUX_FLAG_NOT_TCPC, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_ITE_1, + /* Use PS8751 as mux only */ + .i2c_port = I2C_PORT_USBC1, + .i2c_addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + .flags = USB_MUX_FLAG_NOT_TCPC, + .driver = &ps8xxx_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; /******************************************************************************/ /* USB-C PPC Configuration */ struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { - [USB_PD_PORT_ITE_0] = { - .i2c_port = I2C_PORT_USBC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, - [USB_PD_PORT_ITE_1] = { - .i2c_port = I2C_PORT_USBC1, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, + [USB_PD_PORT_ITE_0] = { .i2c_port = I2C_PORT_USBC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + [USB_PD_PORT_ITE_1] = { .i2c_port = I2C_PORT_USBC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, }; unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); @@ -152,6 +157,6 @@ void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) * correctly in the PPC driver via the pd state machine. */ if (ppc_set_vconn(port, enabled) != EC_SUCCESS) - cprints(CC_USBPD, "C%d: Failed %sabling vconn", - port, enabled ? "en" : "dis"); + cprints(CC_USBPD, "C%d: Failed %sabling vconn", port, + enabled ? "en" : "dis"); } diff --git a/baseboard/octopus/variant_usbc_standalone_tcpcs.c b/baseboard/octopus/variant_usbc_standalone_tcpcs.c index e383c486c0..abc325dfa3 100644 --- a/baseboard/octopus/variant_usbc_standalone_tcpcs.c +++ b/baseboard/octopus/variant_usbc_standalone_tcpcs.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,13 +16,13 @@ #include "gpio.h" #include "hooks.h" #include "system.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) /******************************************************************************/ /* USB-C TPCP Configuration */ @@ -32,7 +32,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, #else @@ -48,7 +48,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -66,22 +66,26 @@ static int ps8751_tune_mux(const struct usb_mux *me) } #endif -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, #if defined(VARIANT_OCTOPUS_TCPC_0_PS8751) - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .board_init = &ps8751_tune_mux, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .board_init = &ps8751_tune_mux, #else - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, #endif + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; diff --git a/baseboard/trogdor/baseboard.c b/baseboard/trogdor/baseboard.c index ecc8dc59f7..3f3c778ea5 100644 --- a/baseboard/trogdor/baseboard.c +++ b/baseboard/trogdor/baseboard.c @@ -1,66 +1,25 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Trogdor baseboard-specific configuration */ -#include "charger.h" -#include "driver/charger/isl923x.h" #include "i2c.h" -#include "power.h" /* Wake-up pins for hibernate */ -const enum gpio_signal hibernate_wake_pins[] = { +enum gpio_signal hibernate_wake_pins[] = { GPIO_LID_OPEN, GPIO_AC_PRESENT, GPIO_POWER_BUTTON_L, GPIO_EC_RST_ODL, }; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +BUILD_ASSERT(ARRAY_SIZE(hibernate_wake_pins) >= 3); -/* Power signal list. Must match order of enum power_signal. */ -const struct power_signal_info power_signal_list[] = { - [SC7180_AP_RST_ASSERTED] = { - GPIO_AP_RST_L, - POWER_SIGNAL_ACTIVE_LOW | POWER_SIGNAL_DISABLE_AT_BOOT, - "AP_RST_ASSERTED"}, - [SC7180_PS_HOLD] = { - GPIO_PS_HOLD, - POWER_SIGNAL_ACTIVE_HIGH, - "PS_HOLD"}, - [SC7180_PMIC_FAULT_L] = { - GPIO_PMIC_FAULT_L, - POWER_SIGNAL_ACTIVE_HIGH | POWER_SIGNAL_DISABLE_AT_BOOT, - "PMIC_FAULT_L"}, - [SC7180_POWER_GOOD] = { - GPIO_POWER_GOOD, - POWER_SIGNAL_ACTIVE_HIGH, - "POWER_GOOD"}, - [SC7180_WARM_RESET] = { - GPIO_WARM_RESET_L, - POWER_SIGNAL_ACTIVE_HIGH, - "WARM_RESET_L"}, - [SC7180_AP_SUSPEND] = { - GPIO_AP_SUSPEND, - POWER_SIGNAL_ACTIVE_HIGH, - "AP_SUSPEND"}, - [SC7180_DEPRECATED_AP_RST_REQ] = { - GPIO_DEPRECATED_AP_RST_REQ, - POWER_SIGNAL_ACTIVE_HIGH, - "DEPRECATED_AP_RST_REQ"}, -}; -BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); - -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = ISL923X_ADDR_FLAGS, - .drv = &isl923x_drv, - }, -}; - -int board_allow_i2c_passthru(int port) +int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc) { - return (port == I2C_PORT_VIRTUAL_BATTERY); + return (cmd_desc->port == I2C_PORT_VIRTUAL_BATTERY || + cmd_desc->port == I2C_PORT_TCPC0 || + cmd_desc->port == I2C_PORT_TCPC1); } diff --git a/baseboard/trogdor/baseboard.h b/baseboard/trogdor/baseboard.h index 20b990b258..37d56a4cec 100644 --- a/baseboard/trogdor/baseboard.h +++ b/baseboard/trogdor/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,17 +8,30 @@ #ifndef __CROS_EC_BASEBOARD_H #define __CROS_EC_BASEBOARD_H +#define CONFIG_LTO + +/* Free flash space */ +#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CONSOLE_HISTORY +#undef CONFIG_CMD_BATTFAKE +#undef CONFIG_CMD_I2C_SCAN +#undef CONFIG_CMD_MFALLOW +#undef CONFIG_CMD_MD +#undef CONFIG_CMD_RTC +#undef CONFIG_CMD_TCPC_DUMP +#undef CONFIG_CMD_TYPEC + /* * By default, enable all console messages excepted event and HC: * The sensor stack is generating a lot of activity. * They can be enabled through the console command 'chan'. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_HOSTCMD))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_HOSTCMD))) /* NPCX7 config */ -#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ -#define NPCX_TACH_SEL2 0 /* No tach. */ -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX_TACH_SEL2 0 /* No tach. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ /* Internal SPI flash on NPCX7 */ #define CONFIG_SPI_FLASH_REGS @@ -26,7 +39,7 @@ /* EC Modules */ #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_I2C_VIRTUAL_BATTERY #define CONFIG_I2C_PASSTHRU_RESTRICTED #define CONFIG_LED_COMMON @@ -41,11 +54,9 @@ #undef CONFIG_PECI -#define CONFIG_HOSTCMD_SPS +#define CONFIG_HOST_INTERFACE_SHI #define CONFIG_HOST_COMMAND_STATUS #define CONFIG_HOSTCMD_SECTION_SORTED -#define CONFIG_MKBP_EVENT -#define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_MKBP_USE_GPIO @@ -58,6 +69,8 @@ #define CONFIG_LID_SWITCH #define CONFIG_EXTPOWER_GPIO +#define CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC + /* * On power-on, H1 releases the EC from reset but then quickly asserts and * releases the reset a second time. This means the EC sees 2 resets: @@ -66,15 +79,23 @@ */ #define CONFIG_BOARD_RESET_AFTER_POWER_ON +/* Increase console output buffer since we have the RAM available. */ +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + /* Battery */ #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_PRESENT_GPIO GPIO_BATT_PRES_ODL #define CONFIG_BATTERY_SMART +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 /* Charger */ #define CONFIG_CHARGER #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER_ISL9238 +#define CONFIG_CHARGER_PROFILE_OVERRIDE #define CONFIG_CHARGE_RAMP_HW #define CONFIG_USB_CHARGER #define CONFIG_CMD_CHARGER_ADC_AMON_BMON @@ -82,8 +103,8 @@ #define CONFIG_CHARGER_PSYS_READ #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 10000 #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 @@ -109,7 +130,6 @@ #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE #define CONFIG_USB_PD_TCPC_LOW_POWER #define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_TCPM_MUX #define CONFIG_USB_PD_TCPM_TCPCI #define CONFIG_CMD_TCPC_DUMP @@ -117,6 +137,7 @@ #define CONFIG_USB_PD_VBUS_DETECT_TCPC #define CONFIG_USB_PD_5V_EN_CUSTOM #define CONFIG_USBC_SS_MUX +#define CONFIG_USBC_SS_MUX_DFP_ONLY #define CONFIG_USBC_VCONN #define CONFIG_USBC_VCONN_SWAP @@ -135,14 +156,13 @@ #define CONFIG_CMD_ACCEL_INFO /* PD */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_OPERATING_POWER_MW 10000 -#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 10000 +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Chipset */ #define CONFIG_CHIPSET_SC7180 @@ -152,9 +172,7 @@ #define CONFIG_POWER_PP5000_CONTROL #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE #define CONFIG_POWER_SLEEP_FAILURE_DETECTION - -/* NPCX Features */ -#define CONFIG_HIBERNATE_PSL +#define CONFIG_CMD_AP_RESET_LOG /* * Macros for GPIO signals used in common code that don't match the @@ -162,61 +180,54 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_LID_OPEN GPIO_LID_OPEN_EC -#define GPIO_SHI_CS_L GPIO_AP_EC_SPI_CS_L -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_BATT_PRES_ODL GPIO_EC_BATT_PRES_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENABLE_BACKLIGHT GPIO_EC_BL_DISABLE_L -#define GPIO_BOARD_VERSION1 GPIO_BRD_ID0 -#define GPIO_BOARD_VERSION2 GPIO_BRD_ID1 -#define GPIO_BOARD_VERSION3 GPIO_BRD_ID2 -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_LID_OPEN GPIO_LID_OPEN_EC +#define GPIO_SHI_CS_L GPIO_AP_EC_SPI_CS_L +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_BATT_PRES_ODL GPIO_EC_BATT_PRES_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_BL_DISABLE_L +#define GPIO_BOARD_VERSION1 GPIO_BRD_ID0 +#define GPIO_BOARD_VERSION2 GPIO_BRD_ID1 +#define GPIO_BOARD_VERSION3 GPIO_BRD_ID2 +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV /* I2C Ports */ #define I2C_PORT_BATTERY I2C_PORT_POWER #define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY #define I2C_PORT_CHARGER I2C_PORT_POWER -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_POWER NPCX_I2C_PORT0_0 -#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 -#define I2C_PORT_WLC NPCX_I2C_PORT3_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT5_0 -#define I2C_PORT_SENSOR NPCX_I2C_PORT7_0 +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_POWER NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 +#define I2C_PORT_WLC NPCX_I2C_PORT3_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT7_0 + +/* UART */ +#define CONFIG_CMD_CHARGEN /* Define the host events which are allowed to wake AP up from S3 */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE)) +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_HANG_DETECT) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_DEVICE)) /* And the MKBP events */ +#ifdef HAS_TASK_KEYSCAN +#define CONFIG_MKBP_EVENT_WAKEUP_MASK \ + (BIT(EC_MKBP_EVENT_KEY_MATRIX) | BIT(EC_MKBP_EVENT_HOST_EVENT) | \ + BIT(EC_MKBP_EVENT_SENSOR_FIFO)) +#else #define CONFIG_MKBP_EVENT_WAKEUP_MASK \ - (BIT(EC_MKBP_EVENT_KEY_MATRIX) | \ - BIT(EC_MKBP_EVENT_HOST_EVENT) | \ - BIT(EC_MKBP_EVENT_SENSOR_FIFO)) - -#ifndef __ASSEMBLER__ - -enum power_signal { - SC7180_AP_RST_ASSERTED = 0, - SC7180_PS_HOLD, - SC7180_PMIC_FAULT_L, - SC7180_POWER_GOOD, - SC7180_WARM_RESET, - SC7180_AP_SUSPEND, - SC7180_DEPRECATED_AP_RST_REQ, - /* Number of power signals */ - POWER_SIGNAL_COUNT -}; - -#endif /* !defined(__ASSEMBLER__) */ + (BIT(EC_MKBP_EVENT_HOST_EVENT) | BIT(EC_MKBP_EVENT_SENSOR_FIFO)) +#endif #endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/trogdor/build.mk b/baseboard/trogdor/build.mk index d882755a64..02ed466d2b 100644 --- a/baseboard/trogdor/build.mk +++ b/baseboard/trogdor/build.mk @@ -1,9 +1,12 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Baseboard specific files build # -baseboard-y=baseboard.o usb_pd_policy.o +baseboard-y+=baseboard.o +baseboard-y+=hibernate.o +baseboard-y+=power.o +baseboard-y+=usb_pd_policy.o diff --git a/baseboard/trogdor/hibernate.c b/baseboard/trogdor/hibernate.c new file mode 100644 index 0000000000..19af7cfe2e --- /dev/null +++ b/baseboard/trogdor/hibernate.c @@ -0,0 +1,13 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gpio.h" +#include "system.h" + +void board_hibernate_late(void) +{ + /* Set the hibernate GPIO to turn off the rails */ + gpio_set_level(GPIO_HIBERNATE_L, 0); +} diff --git a/baseboard/trogdor/power.c b/baseboard/trogdor/power.c new file mode 100644 index 0000000000..a8076d0ed5 --- /dev/null +++ b/baseboard/trogdor/power.c @@ -0,0 +1,38 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gpio.h" +#include "hooks.h" +#include "power.h" +#include "task.h" + +void board_chipset_pre_init(void) +{ + /* Turn on the 3.3V rail */ + gpio_set_level(GPIO_EN_PP3300_A, 1); + + /* Turn on the 5V rail. */ +#ifdef CONFIG_POWER_PP5000_CONTROL + power_5v_enable(task_get_current(), 1); +#else /* !defined(CONFIG_POWER_PP5000_CONTROL) */ + gpio_set_level(GPIO_EN_PP5000, 1); +#endif /* defined(CONFIG_POWER_PP5000_CONTROL) */ +} +DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, board_chipset_pre_init, HOOK_PRIO_DEFAULT); + +void board_chipset_shutdown_complete(void) +{ + /* Turn off the 5V rail. */ +#ifdef CONFIG_POWER_PP5000_CONTROL + power_5v_enable(task_get_current(), 0); +#else /* !defined(CONFIG_POWER_PP5000_CONTROL) */ + gpio_set_level(GPIO_EN_PP5000, 0); +#endif /* defined(CONFIG_POWER_PP5000_CONTROL) */ + + /* Turn off the 3.3V and 5V rails. */ + gpio_set_level(GPIO_EN_PP3300_A, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN_COMPLETE, board_chipset_shutdown_complete, + HOOK_PRIO_DEFAULT); diff --git a/baseboard/trogdor/usb_pd_policy.c b/baseboard/trogdor/usb_pd_policy.c index f66ea1f276..04a2e78519 100644 --- a/baseboard/trogdor/usb_pd_policy.c +++ b/baseboard/trogdor/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,8 +12,8 @@ #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) int pd_check_vconn_swap(int port) { @@ -23,10 +23,10 @@ int pd_check_vconn_swap(int port) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; #if CONFIG_USB_PD_PORT_MAX_COUNT == 1 -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5 }; #else -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; #endif static void board_vbus_update_source_current(int port) @@ -50,11 +50,6 @@ void pd_power_supply_reset(int port) if (prev_en) pd_set_vbus_discharge(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -70,9 +65,6 @@ int pd_set_power_supply_ready(int port) vbus_en[port] = 1; board_vbus_update_source_current(port); - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); - /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -99,14 +91,14 @@ int pd_snk_is_vbus_provided(int port) #ifdef CONFIG_USB_PD_ALT_MODE_DFP __override int svdm_dp_config(int port, uint32_t *payload) { - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); uint8_t pin_mode = get_dp_pin_mode(port); if (!pin_mode) return 0; /* - * Defer setting the usb_mux until HPD goes high, svdm_dp_attention(). + * Defer setting the DP mux until HPD goes high, svdm_dp_attention(). * The AP only supports one DP phy. An external DP mux switches between * the two ports. Should switch those muxes when it is really used, * i.e. HPD high; otherwise, the real use case is preempted, like: @@ -115,17 +107,45 @@ __override int svdm_dp_config(int port, uint32_t *payload) * (3) plug a monitor to the port-1 dongle. */ - payload[0] = VDO(USB_SID_DISPLAYPORT, 1, - CMD_DP_CONFIG | VDO_OPOS(opos)); - payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ - 1, /* DPv1.3 signaling */ - 2); /* UFP connected */ + payload[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); + payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ + 1, /* DPv1.3 signaling */ + 2); /* UFP connected */ return 2; }; __override void svdm_dp_post_config(int port) { + /* + * Connect the SBU lines in PPC chip such that the AUX termination + * can be passed through. + */ + if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) + ppc_set_sbu(port, 1); + + /* + * Connect the USB SS/DP lines in TCPC chip. + * + * When mf_pref not true, still use the dock muxing + * because of the board USB-C topology (limited to 2 + * lanes DP). + */ + usb_mux_set(port, USB_PD_MUX_DOCK, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); + dp_flags[port] |= DP_FLAGS_DP_ON; + if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) + return; + + CPRINTS("C%d: Pending HPD. HPD->1", port); + gpio_set_level(GPIO_DP_HOT_PLUG_DET, 1); + + /* set the minimum time delay (2ms) for the next HPD IRQ */ + svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; + + usb_mux_hpd_update(port, + USB_PD_MUX_HPD_LVL | USB_PD_MUX_HPD_IRQ_DEASSERTED); } /** @@ -138,15 +158,13 @@ __override void svdm_dp_post_config(int port) */ static int is_dp_muxable(int port) { - int i; - - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) - if (i != port) { - if (usb_mux_get(i) & USB_PD_MUX_DP_ENABLED) - return 0; - } - - return 1; + /* + * Check the DP port selection mux, positive either: + * - no port is muxed, OE_L deasserted, HIGH, or + * - already muxed to the same port. + */ + return gpio_get_level(GPIO_DP_MUX_OE_L) || + (gpio_get_level(GPIO_DP_MUX_SEL) == port); } __override int svdm_dp_attention(int port, uint32_t *payload) @@ -155,9 +173,16 @@ __override int svdm_dp_attention(int port, uint32_t *payload) int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); int cur_lvl = gpio_get_level(hpd); + mux_state_t mux_state; dp_status[port] = payload[1]; + if (!is_dp_muxable(port)) { + /* TODO(waihong): Info user? */ + CPRINTS("p%d: The other port is already muxed.", port); + return 0; + } + /* * Initial implementation to handle HPD. Only the first-plugged port * works, i.e. sending HPD signal to AP. The second-plugged port @@ -167,58 +192,39 @@ __override int svdm_dp_attention(int port, uint32_t *payload) * is then unplugged, switch to the second-plugged port and signal AP? */ if (lvl) { - if (is_dp_muxable(port)) { - /* - * Enable and switch the DP port selection mux to the - * correct port. - * - * TODO(waihong): Better to move switching DP mux to - * the usb_mux abstraction. - */ - gpio_set_level(GPIO_DP_MUX_SEL, port == 1); - gpio_set_level(GPIO_DP_MUX_OE_L, 0); - - /* Connect the SBU lines in PPC chip. */ - if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) - ppc_set_sbu(port, 1); - - /* - * Connect the USB SS/DP lines in TCPC chip. - * - * When mf_pref not true, still use the dock muxing - * because of the board USB-C topology (limited to 2 - * lanes DP). - */ - usb_mux_set(port, USB_PD_MUX_DOCK, - USB_SWITCH_CONNECT, pd_get_polarity(port)); - } else { - /* TODO(waihong): Info user? */ - CPRINTS("p%d: The other port is already muxed.", port); - return 0; /* Nack */ - } + /* + * Enable and switch the DP port selection mux to the + * correct port. + * + * TODO(waihong): Better to move switching DP mux to + * the usb_mux abstraction. + */ + gpio_set_level(GPIO_DP_MUX_SEL, port == 1); + gpio_set_level(GPIO_DP_MUX_OE_L, 0); } else { /* Disconnect the DP port selection mux. */ gpio_set_level(GPIO_DP_MUX_OE_L, 1); - - /* Disconnect the SBU lines in PPC chip. */ - if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) - ppc_set_sbu(port, 0); - - /* Disconnect the DP but keep the USB SS lines in TCPC chip. */ - usb_mux_set(port, USB_PD_MUX_USB_ENABLED, - USB_SWITCH_CONNECT, pd_get_polarity(port)); + gpio_set_level(GPIO_DP_MUX_SEL, 0); } - if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && - (irq || lvl)) + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && (irq || lvl)) /* * Wake up the AP. IRQ or level high indicates a DP sink is now * present. */ - pd_notify_dp_alt_mode_entry(); + pd_notify_dp_alt_mode_entry(port); + + /* Its initial DP status message prior to config */ + if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { + if (lvl) + dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; + return 1; + } /* Configure TCPC for the HPD event, for proper muxing */ - usb_mux_hpd_update(port, lvl, irq); + mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | + (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); + usb_mux_hpd_update(port, mux_state); /* Signal AP for the HPD event, through GPIO to AP */ if (irq & cur_lvl) { @@ -228,36 +234,44 @@ __override int svdm_dp_attention(int port, uint32_t *payload) usleep(svdm_hpd_deadline[port] - now); /* Generate IRQ_HPD pulse */ + CPRINTS("C%d: Recv IRQ. HPD->0", port); gpio_set_level(hpd, 0); usleep(HPD_DSTREAM_DEBOUNCE_IRQ); gpio_set_level(hpd, 1); + CPRINTS("C%d: Recv IRQ. HPD->1", port); /* Set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + - HPD_USTREAM_DEBOUNCE_LVL; + svdm_hpd_deadline[port] = + get_time().val + HPD_USTREAM_DEBOUNCE_LVL; } else if (irq & !lvl) { CPRINTF("ERR:HPD:IRQ&LOW\n"); - return 0; /* Nak */ + return 0; } else { + CPRINTS("C%d: Recv lvl. HPD->%d", port, lvl); gpio_set_level(hpd, lvl); /* Set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + - HPD_USTREAM_DEBOUNCE_LVL; + svdm_hpd_deadline[port] = + get_time().val + HPD_USTREAM_DEBOUNCE_LVL; } - return 1; /* Ack */ + return 1; } __override void svdm_exit_dp_mode(int port) { - /* Disconnect the DP port selection mux. */ - gpio_set_level(GPIO_DP_MUX_OE_L, 1); - - /* Below svdm_safe_dp_mode() will disconnect SBU and DP/USB SS lines. */ - svdm_safe_dp_mode(port); + CPRINTS("%s(%d)", __func__, port); + dp_flags[port] = 0; + dp_status[port] = 0; + if (is_dp_muxable(port)) { + /* Disconnect the DP port selection mux. */ + gpio_set_level(GPIO_DP_MUX_OE_L, 1); + gpio_set_level(GPIO_DP_MUX_SEL, 0); - /* Signal AP for the HPD low event */ - usb_mux_hpd_update(port, 0, 0); - gpio_set_level(GPIO_DP_HOT_PLUG_DET, 0); + /* Signal AP for the HPD low event */ + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); + CPRINTS("C%d: DP exit. HPD->0", port); + gpio_set_level(GPIO_DP_HOT_PLUG_DET, 0); + } } #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/baseboard/volteer/baseboard.c b/baseboard/volteer/baseboard.c index f42bcba930..b9f10fd360 100644 --- a/baseboard/volteer/baseboard.c +++ b/baseboard/volteer/baseboard.c @@ -1,35 +1,30 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer family-specific configuration */ -#include "adc_chip.h" +#include "adc.h" #include "button.h" #include "cbi_ec_fw_config.h" -#include "charge_manager.h" #include "charge_ramp.h" -#include "charge_state.h" +#include "charger.h" #include "cros_board_info.h" #include "driver/charger/isl9241.h" #include "driver/tcpm/ps8xxx.h" #include "driver/temp_sensor/thermistor.h" #include "gpio.h" -#include "hooks.h" #include "i2c.h" -#include "icelake.h" #include "keyboard_scan.h" #include "system.h" #include "task.h" #include "temp_sensor.h" -#include "usbc_ppc.h" -#include "util.h" +#ifdef CONFIG_ZEPHYR +#include "usbc_config.h" +#endif -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ##args) /******************************************************************************/ /* ADC configuration */ @@ -75,252 +70,24 @@ const enum gpio_signal hibernate_wake_pins[] = { }; const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); -/******************************************************************************/ -/* Charger Chip Configuration */ -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = ISL9241_ADDR_FLAGS, - .drv = &isl9241_drv, - }, -}; - -/******************************************************************************/ -/* - * PWROK signal configuration, see the PWROK Generation Flow Diagram (Figure - * 235) in the Tiger Lake Platform Design Guide for the list of potential - * signals. - * - * Volteer uses this power sequence: - * GPIO_EN_PPVAR_VCCIN - Turns on the VCCIN rail. Also used as a delay to - * the VCCST_PWRGD input to the AP so this signal must be delayed - * 5 ms to meet the tCPU00 timing requirement. - * GPIO_EC_PCH_SYS_PWROK - Asserts the SYS_PWROK input to the AP. Delayed - * a total of 50 ms after ALL_SYS_PWRGD input is asserted. See - * b/144478941 for full discussion. - * - * Volteer does not provide direct EC control for the VCCST_PWRGD and PCH_PWROK - * signals. If your board adds these signals to the EC, copy this array - * to your board.c file and modify as needed. - */ -const struct intel_x86_pwrok_signal pwrok_signal_assert_list[] = { - { - .gpio = GPIO_EN_PPVAR_VCCIN, - .delay_ms = 5, - }, - { - .gpio = GPIO_EC_PCH_SYS_PWROK, - .delay_ms = 50 - 5, - }, -}; -const int pwrok_signal_assert_count = ARRAY_SIZE(pwrok_signal_assert_list); - -const struct intel_x86_pwrok_signal pwrok_signal_deassert_list[] = { - /* No delays needed during S0 exit */ - { - .gpio = GPIO_EC_PCH_SYS_PWROK, - }, - /* Turn off VCCIN last */ - { - .gpio = GPIO_EN_PPVAR_VCCIN, - }, -}; -const int pwrok_signal_deassert_count = ARRAY_SIZE(pwrok_signal_deassert_list); - /******************************************************************************/ /* Temperature sensor configuration */ const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1_CHARGER}, - [TEMP_SENSOR_2_PP3300_REGULATOR] = {.name = "PP3300 Regulator", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2_PP3300_REGULATOR}, - [TEMP_SENSOR_3_DDR_SOC] = {.name = "DDR and SOC", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_3_DDR_SOC}, - [TEMP_SENSOR_4_FAN] = {.name = "Fan", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_4_FAN}, + [TEMP_SENSOR_1_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_CHARGER }, + [TEMP_SENSOR_2_PP3300_REGULATOR] = { .name = "PP3300 Regulator", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_PP3300_REGULATOR }, + [TEMP_SENSOR_3_DDR_SOC] = { .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_DDR_SOC }, + [TEMP_SENSOR_4_FAN] = { .name = "Fan", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - -/******************************************************************************/ -void tcpc_alert_event(enum gpio_signal signal) -{ - /* TODO: b/140572591 - check correct operation for Volteer */ - - int port = -1; - - switch (signal) { - case GPIO_USB_C0_TCPC_INT_ODL: - port = USBC_PORT_C0; - break; - case GPIO_USB_C1_TCPC_INT_ODL: - port = USBC_PORT_C1; - break; - default: - return; - } - - schedule_deferred_pd_interrupt(port); -} - -void bc12_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); - break; - - case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); - break; - - default: - break; - } -} - -int board_set_active_charge_port(int port) -{ - int is_valid_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); - int i; - - if (port == CHARGE_PORT_NONE) { - CPRINTSUSB("Disabling all charger ports"); - - /* Disable all ports. */ - for (i = 0; i < ppc_cnt; i++) { - /* - * Do not return early if one fails otherwise we can - * get into a boot loop assertion failure. - */ - if (ppc_vbus_sink_enable(i, 0)) - CPRINTSUSB("Disabling C%d as sink failed.", i); - } - - return EC_SUCCESS; - } else if (!is_valid_port) { - return EC_ERROR_INVAL; - } - - - /* Check if the port is sourcing VBUS. */ - if (ppc_is_sourcing_vbus(port)) { - CPRINTFUSB("Skip enable C%d", port); - return EC_ERROR_INVAL; - } - - CPRINTSUSB("New charge port: C%d", port); - - /* - * Turn off the other ports' sink path FETs, before enabling the - * requested charge port. - */ - for (i = 0; i < ppc_cnt; i++) { - if (i == port) - continue; - - if (ppc_vbus_sink_enable(i, 0)) - CPRINTSUSB("C%d: sink path disable failed.", i); - } - - /* Enable requested charge port. */ - if (ppc_vbus_sink_enable(port, 1)) { - CPRINTSUSB("C%d: sink path enable failed.", port); - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -__overridable void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} - -void board_overcurrent_event(int port, int is_overcurrented) -{ - /* Note that the level is inverted because the pin is active low. */ - switch (port) { - case USBC_PORT_C0: - gpio_set_level(GPIO_USB_C0_OC_ODL, !is_overcurrented); - break; - case USBC_PORT_C1: - gpio_set_level(GPIO_USB_C1_OC_ODL, !is_overcurrented); - break; - } -} - -static void baseboard_init(void) -{ - /* Enable monitoring of the PROCHOT input to the EC */ - gpio_enable_interrupt(GPIO_EC_PROCHOT_IN_L); -} -DECLARE_HOOK(HOOK_INIT, baseboard_init, HOOK_PRIO_DEFAULT); - -static uint8_t board_id; - -uint8_t get_board_id(void) -{ - return board_id; -} - -__overridable void board_cbi_init(void) -{ -} - -/* - * Read CBI from i2c eeprom and initialize variables for board variants - * - * Example for configuring for a USB3 DB: - * ectool cbi set 6 2 4 10 - */ -static void cbi_init(void) -{ - uint32_t cbi_val; - - /* Board ID */ - if (cbi_get_board_version(&cbi_val) != EC_SUCCESS || - cbi_val > UINT8_MAX) - CPRINTS("CBI: Read Board ID failed"); - else - board_id = cbi_val; - - CPRINTS("Board ID: %d", board_id); - - /* FW config */ - init_fw_config(); - - /* Allow the board project to make runtime changes based on CBI data */ - board_cbi_init(); -} -DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_FIRST); - -/** - * Return if VBUS is too low - */ -int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) -{ - int voltage; - - if (charger_get_vbus_voltage(port, &voltage)) - voltage = 0; - - /* - * For legacy BC1.2 charging with CONFIG_CHARGE_RAMP_SW, ramp up input - * current until voltage drops to the minimum input voltage of the - * charger, 4.096V. - */ - return voltage < ISL9241_BC12_MIN_VOLTAGE; -} - diff --git a/baseboard/volteer/baseboard.h b/baseboard/volteer/baseboard.h index d63c0062d5..d3c82f0651 100644 --- a/baseboard/volteer/baseboard.h +++ b/baseboard/volteer/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,13 +13,13 @@ /* * By default, enable all console messages excepted HC */ -#define CC_DEFAULT (CC_ALL & ~(BIT(CC_HOSTCMD))) +#define CC_DEFAULT (CC_ALL & ~(BIT(CC_HOSTCMD))) /* NPCX7 config */ -#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ -#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ /* Internal SPI flash on NPCX796FC is 512 kB */ -#define CONFIG_FLASH_SIZE (512 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ @@ -30,7 +30,7 @@ #define CONFIG_LTO #define CONFIG_BOARD_VERSION_CBI #define CONFIG_CRC8 -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_DPTF #define CONFIG_FPU #define CONFIG_HIBERNATE_PSL @@ -43,8 +43,9 @@ #define CONFIG_BOARD_RESET_AFTER_POWER_ON /* Host communication */ -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S5 /* Chipset config */ #define CONFIG_CHIPSET_TIGERLAKE @@ -58,13 +59,14 @@ #define CONFIG_POWER_BUTTON_X86 #define CONFIG_POWER_COMMON #define CONFIG_POWER_S0IX +#define CONFIG_POWER_S4_RESIDENCY #define CONFIG_POWER_SLEEP_FAILURE_DETECTION #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE #define CONFIG_BOARD_HAS_RTC_RESET /* Common Keyboard Defines */ #define CONFIG_CMD_KEYBOARD -#define CONFIG_KEYBOARD_BOARD_CONFIG + #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_KEYPAD #define CONFIG_KEYBOARD_PROTOCOL_8042 @@ -77,8 +79,8 @@ #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT -#define CONFIG_ACCEL_INTERRUPTS /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO @@ -92,9 +94,10 @@ #define CONFIG_CMD_ACCEL_INFO /* Thermal features */ -#define CONFIG_FANS FAN_CH_COUNT +#define CONFIG_FANS FAN_CH_COUNT #define CONFIG_TEMP_SENSOR -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_PP3300_A +#define CONFIG_TEMP_SENSOR_POWER +#define GPIO_TEMP_SENSOR_POWER GPIO_PG_EC_DSW_PWROK #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B #define CONFIG_THROTTLE_AP @@ -104,13 +107,16 @@ #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 /* * Hardware based charge ramp is broken in the ISL9241 (b/169350714). */ #define CONFIG_CHARGE_RAMP_SW #define CONFIG_CHARGER_ISL9241 +/* Setting ISL9241 Register Control1 switching frequency to 724kHz. */ +#define CONFIG_ISL9241_SWITCHING_FREQ ISL9241_CONTROL1_SWITCHING_FREQ_724KHZ #define CONFIG_USB_CHARGER #define CONFIG_BC12_DETECT_PI3USB9201 @@ -119,10 +125,8 @@ * Don't allow the system to boot to S0 when the battery is low and unable to * communicate on locked systems (which haven't PD negotiated) */ -#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 3 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC 1 -#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 15001 +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000 +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 15001 /* Common battery defines */ #define CONFIG_BATTERY_SMART @@ -137,7 +141,7 @@ /* EDP back-light control defines */ #define CONFIG_BACKLIGHT_LID -#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EDP_BL_EN +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EDP_BL_EN /* USB Type C and USB PD defines */ /* Enable the new USB-C PD stack */ @@ -158,19 +162,19 @@ #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_ALT_MODE_UFP #define CONFIG_USB_PD_DISCHARGE_PPC #define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_TCPC_RUNTIME_CONFIG #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE #define CONFIG_USB_PD_TCPC_LOW_POWER #define CONFIG_USB_PD_TCPM_TCPCI #define CONFIG_USB_PD_TCPM_RT1715 -#define CONFIG_USB_PD_TCPM_TUSB422 /* USBC port C0 */ -#define CONFIG_USB_PD_TCPM_PS8815 /* USBC port USB3 DB */ +#define CONFIG_USB_PD_TCPM_TUSB422 /* USBC port C0 */ +#define CONFIG_USB_PD_TCPM_PS8815 /* USBC port USB3 DB */ #define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID #define CONFIG_USB_PD_TCPM_MUX -#define CONFIG_HOSTCMD_PD_CONTROL /* Needed for TCPC FW update */ +#define CONFIG_HOSTCMD_PD_CONTROL /* Needed for TCPC FW update */ #define CONFIG_CMD_USB_PD_PE /* @@ -187,14 +191,13 @@ * with non-PD chargers. Override the default low-power mode exit delay. */ #undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE -#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (50*MSEC) +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (50 * MSEC) /* Enable USB3.2 DRD */ #define CONFIG_USB_PD_USB32_DRD #define CONFIG_USB_PD_TRY_SRC #define CONFIG_USB_PD_VBUS_DETECT_TCPC -#define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT #define CONFIG_USB_MUX_RUNTIME_CONFIG @@ -206,7 +209,6 @@ */ #define CONFIG_USBC_PPC_DEDICATED_INT -#define CONFIG_INTEL_VIRTUAL_MUX #define CONFIG_USBC_SS_MUX #define CONFIG_USB_MUX_VIRTUAL @@ -226,15 +228,26 @@ * http://google3/hardware/standards/usb/ */ #define CONFIG_USB_PID 0x503E +/* Device version of product. */ +#define CONFIG_USB_BCD_DEV 0x0000 /* Retimer */ #define CONFIG_USBC_RETIMER_INTEL_BB #define CONFIG_USBC_RETIMER_INTEL_BB_RUNTIME_CONFIG +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Enable volume button command in EC console */ +#define CONFIG_CMD_BUTTON + +/* Enable volume button in ectool */ +#define CONFIG_HOSTCMD_BUTTON #ifndef __ASSEMBLER__ -#include "gpio_signal.h" +#include "baseboard_usbc_config.h" +#include "cbi.h" #include "common.h" +#include "gpio_signal.h" enum adc_channel { ADC_TEMP_SENSOR_1_CHARGER, @@ -264,21 +277,6 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -/* Common definition for the USB PD interrupt handlers. */ -void ppc_interrupt(enum gpio_signal signal); -void tcpc_alert_event(enum gpio_signal signal); -void bc12_interrupt(enum gpio_signal signal); - -unsigned char get_board_id(void); - -/** - * Configure run-time data structures and operation based on CBI data. This - * typically includes customization for changes in the BOARD_VERSION and - * FW_CONFIG fields in CBI. This routine is called from the baseboard after - * the CBI data has been initialized. - */ -__override_proto void board_cbi_init(void); - /* * Check battery disconnect state. * This function will return if battery is initialized or not. diff --git a/baseboard/volteer/baseboard_usbc_config.h b/baseboard/volteer/baseboard_usbc_config.h new file mode 100644 index 0000000000..db5e296d46 --- /dev/null +++ b/baseboard/volteer/baseboard_usbc_config.h @@ -0,0 +1,18 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* volteer family-specific USB-C configuration */ + +#ifndef __CROS_EC_BASEBOARD_USBC_CONFIG_H +#define __CROS_EC_BASEBOARD_USBC_CONFIG_H + +#include "gpio_signal.h" + +/* Common definition for the USB PD interrupt handlers. */ +void ppc_interrupt(enum gpio_signal signal); +void tcpc_alert_event(enum gpio_signal signal); +void bc12_interrupt(enum gpio_signal signal); + +#endif /* __CROS_EC_BASEBOARD_USBC_CONFIG_H */ diff --git a/baseboard/volteer/battery_presence.c b/baseboard/volteer/battery_presence.c index 4953d7a49e..d656b7b626 100644 --- a/baseboard/volteer/battery_presence.c +++ b/baseboard/volteer/battery_presence.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,12 +6,12 @@ * Each board should implement board_battery_info[] to define the specific * battery packs supported. */ -#include - #include "battery.h" #include "battery_smart.h" #include "gpio.h" +#include + static enum battery_present batt_pres_prev = BP_NOT_SURE; enum battery_present battery_hw_present(void) @@ -24,8 +24,9 @@ static bool battery_init(void) { int batt_status; - return battery_status(&batt_status) ? 0 : - !!(batt_status & STATUS_INITIALIZED); + return battery_status(&batt_status) ? + 0 : + !!(batt_status & STATUS_INITIALIZED); } __overridable bool board_battery_is_initialized(void) diff --git a/baseboard/volteer/build.mk b/baseboard/volteer/build.mk index 662f3abdee..2b2f4e97b1 100644 --- a/baseboard/volteer/build.mk +++ b/baseboard/volteer/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,5 +8,10 @@ baseboard-y=baseboard.o baseboard-y+=battery_presence.o +baseboard-y+=charger.o baseboard-y+=usb_pd_policy.o +baseboard-y+=cbi.o baseboard-y+=cbi_ec_fw_config.o +baseboard-y+=cbi_ssfc.o +baseboard-y+=power.o +baseboard-y+=usbc_config.o diff --git a/baseboard/volteer/cbi.c b/baseboard/volteer/cbi.c new file mode 100644 index 0000000000..28606d7eaf --- /dev/null +++ b/baseboard/volteer/cbi.c @@ -0,0 +1,53 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific functions, shared with Zephyr */ + +#include "cbi_ec_fw_config.h" +#include "common.h" +#include "cros_board_info.h" +#include "hooks.h" +#include "system.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ##args) + +static uint8_t board_id; + +uint8_t get_board_id(void) +{ + return board_id; +} + +__overridable void board_cbi_init(void) +{ +} + +/* + * Read CBI from i2c eeprom and initialize variables for board variants + * + * Example for configuring for a USB3 DB: + * ectool cbi set 6 2 4 10 + */ +static void cbi_init(void) +{ + uint32_t cbi_val; + + /* Board ID */ + if (cbi_get_board_version(&cbi_val) != EC_SUCCESS || + cbi_val > UINT8_MAX) + CPRINTS("CBI: Read Board ID failed"); + else + board_id = cbi_val; + + CPRINTS("Board ID: %d", board_id); + + /* FW config */ + init_fw_config(); + + /* Allow the board project to make runtime changes based on CBI data */ + board_cbi_init(); +} +DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_FIRST); diff --git a/baseboard/volteer/cbi.h b/baseboard/volteer/cbi.h new file mode 100644 index 0000000000..4b4044ea3c --- /dev/null +++ b/baseboard/volteer/cbi.h @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific CBI functions, shared with Zephyr */ + +#ifndef __CROS_EC_BASEBOARD_CBI_H +#define __CROS_EC_BASEBOARD_CBI_H + +#include "common.h" + +unsigned char get_board_id(void); + +/** + * Configure run-time data structures and operation based on CBI data. This + * typically includes customization for changes in the BOARD_VERSION and + * FW_CONFIG fields in CBI. This routine is called from the baseboard after + * the CBI data has been initialized. + */ +__override_proto void board_cbi_init(void); + +#endif /* __CROS_EC_BASEBOARD_CBI_H */ diff --git a/baseboard/volteer/cbi_ec_fw_config.c b/baseboard/volteer/cbi_ec_fw_config.c index 12b96ff5b4..f925498774 100644 --- a/baseboard/volteer/cbi_ec_fw_config.c +++ b/baseboard/volteer/cbi_ec_fw_config.c @@ -1,14 +1,14 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "cbi_ec_fw_config.h" #include "common.h" #include "console.h" -#include "cbi_ec_fw_config.h" #include "cros_board_info.h" -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) static union volteer_cbi_fw_config fw_config; BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); @@ -49,3 +49,7 @@ bool ec_cfg_has_numeric_pad(void) return (fw_config.num_pad == NUMERIC_PAD_ENABLED); } +enum ec_cfg_keyboard_layout ec_cfg_keyboard_layout(void) +{ + return fw_config.kb_layout; +} diff --git a/baseboard/volteer/cbi_ec_fw_config.h b/baseboard/volteer/cbi_ec_fw_config.h index 5b97f778ec..da91dff27b 100644 --- a/baseboard/volteer/cbi_ec_fw_config.h +++ b/baseboard/volteer/cbi_ec_fw_config.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -43,17 +43,20 @@ enum ec_cfg_numeric_pad_type { NUMERIC_PAD_ENABLED = 1 }; +enum ec_cfg_keyboard_layout { KB_LAYOUT_DEFAULT = 0, KB_LAYOUT_1 = 1 }; + union volteer_cbi_fw_config { struct { - enum ec_cfg_usb_db_type usb_db : 4; - uint32_t thermal : 4; - uint32_t audio : 3; - enum ec_cfg_tabletmode_type tabletmode : 1; - uint32_t lte_db : 2; - enum ec_cfg_keyboard_backlight_type kb_bl : 1; - enum ec_cfg_numeric_pad_type num_pad : 1; - uint32_t sd_db : 4; - uint32_t reserved_2 : 12; + enum ec_cfg_usb_db_type usb_db : 4; + uint32_t thermal : 4; + uint32_t audio : 3; + enum ec_cfg_tabletmode_type tabletmode : 1; + uint32_t lte_db : 2; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + enum ec_cfg_numeric_pad_type num_pad : 1; + uint32_t sd_db : 4; + enum ec_cfg_keyboard_layout kb_layout : 2; + uint32_t reserved_2 : 10; }; uint32_t raw_value; }; @@ -108,4 +111,11 @@ bool ec_cfg_has_keyboard_backlight(void); */ bool ec_cfg_has_numeric_pad(void); +/** + * Get keyboard type from FW_CONFIG. + * + * @return the keyboard type. + */ +enum ec_cfg_keyboard_layout ec_cfg_keyboard_layout(void); + #endif /* __VOLTEER_CBI_EC_FW_CONFIG_H_ */ diff --git a/baseboard/volteer/cbi_ssfc.c b/baseboard/volteer/cbi_ssfc.c new file mode 100644 index 0000000000..f68602b558 --- /dev/null +++ b/baseboard/volteer/cbi_ssfc.c @@ -0,0 +1,46 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union volteer_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return cached_ssfc.lid_sensor; +} + +enum ec_ssfc_lightbar get_cbi_ssfc_lightbar(void) +{ + return cached_ssfc.lightbar; +} + +enum ec_ssfc_keyboard get_cbi_ssfc_keyboard(void) +{ + return cached_ssfc.keyboard; +} diff --git a/baseboard/volteer/cbi_ssfc.h b/baseboard/volteer/cbi_ssfc.h new file mode 100644 index 0000000000..225ff8670e --- /dev/null +++ b/baseboard/volteer/cbi_ssfc.h @@ -0,0 +1,88 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _VOLTEER_CBI_SSFC__H_ +#define _VOLTEER_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Volteer CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BASE_BMI160 = 1, + SSFC_SENSOR_BASE_ICM426XX = 2, + SSFC_SENSOR_BASE_ICM42607 = 3 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_LID_BMA255 = 1, + SSFC_SENSOR_LID_KX022 = 2 +}; + +/* + * Lightbar (Bits 6-7) + */ +enum ec_ssfc_lightbar { + SSFC_LIGHTBAR_NONE = 0, + SSFC_LIGHTBAR_10_LED = 1, + SSFC_LIGHTBAR_12_LED = 2 +}; + +/* + * Keyboard Type (Bit 12) + */ +enum ec_ssfc_keyboard { SSFC_KEYBOARD_DEFAULT = 0, SSFC_KEYBOARD_GAMING = 1 }; + +union volteer_cbi_ssfc { + struct { + enum ec_ssfc_base_sensor base_sensor : 3; + enum ec_ssfc_lid_sensor lid_sensor : 3; + enum ec_ssfc_lightbar lightbar : 2; + uint32_t reserved_2 : 4; + enum ec_ssfc_keyboard keyboard : 1; + uint32_t reserved_3 : 19; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +/** + * Get lightbar type from SSFC_CONFIG. + * + * @return the lightbar type. + */ +enum ec_ssfc_lightbar get_cbi_ssfc_lightbar(void); + +/** + * Get keyboard type from SSFC_CONFIG. + * + * @return the keyboard type. + */ +enum ec_ssfc_keyboard get_cbi_ssfc_keyboard(void); + +#endif /* _Volteer_CBI_SSFC__H_ */ diff --git a/baseboard/volteer/charger.c b/baseboard/volteer/charger.c new file mode 100644 index 0000000000..17f1fe5f7d --- /dev/null +++ b/baseboard/volteer/charger.c @@ -0,0 +1,94 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific configuration */ +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "driver/charger/isl9241_public.h" +#include "gpio.h" +#ifdef CONFIG_ZEPHYR +#include "usbc_config.h" +#endif +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; + +int board_set_active_charge_port(int port) +{ + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Note that the level is inverted because the pin is active low. */ + switch (port) { + case USBC_PORT_C0: + gpio_set_level(GPIO_USB_C0_OC_ODL, !is_overcurrented); + break; + case USBC_PORT_C1: + gpio_set_level(GPIO_USB_C1_OC_ODL, !is_overcurrented); + break; + } +} diff --git a/baseboard/volteer/power.c b/baseboard/volteer/power.c new file mode 100644 index 0000000000..882c067b6d --- /dev/null +++ b/baseboard/volteer/power.c @@ -0,0 +1,70 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gpio.h" +#include "hooks.h" +#include "power/icelake.h" +#include "throttle_ap.h" + +/* + * PWROK signal configuration, see the PWROK Generation Flow Diagram (Figure + * 235) in the Tiger Lake Platform Design Guide for the list of potential + * signals. + * + * Volteer uses this power sequence: + * GPIO_EN_PPVAR_VCCIN - Turns on the VCCIN rail. Also used as a delay to + * the VCCST_PWRGD input to the AP so this signal must be delayed + * 5 ms to meet the tCPU00 timing requirement. + * GPIO_EC_PCH_SYS_PWROK - Asserts the SYS_PWROK input to the AP. Delayed + * a total of 50 ms after ALL_SYS_PWRGD input is asserted. See + * b/144478941 for full discussion. + * + * Volteer does not provide direct EC control for the VCCST_PWRGD and PCH_PWROK + * signals. If your board adds these signals to the EC, copy this array + * to your board.c file and modify as needed. + */ +const struct intel_x86_pwrok_signal pwrok_signal_assert_list[] = { + { + .gpio = GPIO_EN_PPVAR_VCCIN, + .delay_ms = 5, + }, + { + .gpio = GPIO_EC_PCH_SYS_PWROK, + .delay_ms = 50 - 5, + }, +}; +const int pwrok_signal_assert_count = ARRAY_SIZE(pwrok_signal_assert_list); + +const struct intel_x86_pwrok_signal pwrok_signal_deassert_list[] = { + /* No delays needed during S0 exit */ + { + .gpio = GPIO_EC_PCH_SYS_PWROK, + }, + /* Turn off VCCIN last */ + { + .gpio = GPIO_EN_PPVAR_VCCIN, + }, +}; +const int pwrok_signal_deassert_count = ARRAY_SIZE(pwrok_signal_deassert_list); + +static const struct prochot_cfg volteer_prochot_cfg = { + .gpio_prochot_in = GPIO_EC_PROCHOT_IN_L, +#ifdef CONFIG_CPU_PROCHOT_GATE_ON_C10 + .gpio_c10_in = GPIO_CPU_C10_GATE_L, + .c10_active_high = false, +#endif +}; + +static void baseboard_init(void) +{ + /* Enable monitoring of the PROCHOT input to the EC */ + throttle_ap_config_prochot(&volteer_prochot_cfg); + gpio_enable_interrupt(GPIO_EC_PROCHOT_IN_L); + +#ifdef CONFIG_CPU_PROCHOT_GATE_ON_C10 + gpio_enable_interrupt(GPIO_CPU_C10_GATE_L); +#endif +} +DECLARE_HOOK(HOOK_INIT, baseboard_init, HOOK_PRIO_DEFAULT); diff --git a/baseboard/volteer/usb_pd_policy.c b/baseboard/volteer/usb_pd_policy.c index 39bbd918a5..18c24b64ef 100644 --- a/baseboard/volteer/usb_pd_policy.c +++ b/baseboard/volteer/usb_pd_policy.c @@ -1,19 +1,21 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Shared USB-C policy for Volteer boards */ #include "charge_manager.h" +#include "chipset.h" #include "compile_time_macros.h" #include "console.h" #include "gpio.h" +#include "system.h" +#include "usb_common.h" #include "usb_mux.h" -#include "usbc_ppc.h" #include "usb_pd.h" -#include "system.h" +#include "usbc_ppc.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -34,11 +36,6 @@ void pd_power_supply_reset(int port) if (prev_en) pd_set_vbus_discharge(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -59,23 +56,167 @@ int pd_set_power_supply_ready(int port) if (rv) return rv; -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); return EC_SUCCESS; } +#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC int pd_snk_is_vbus_provided(int port) { return ppc_is_vbus_present(port); } +#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ int board_vbus_source_enabled(int port) { return ppc_is_sourcing_vbus(port); } + +#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE +/* ----------------- Vendor Defined Messages ------------------ */ +/* Responses specifically for the enablement of TBT mode in the role of UFP */ + +#define OPOS_TBT 1 + +static const union tbt_mode_resp_device vdo_tbt_modes[1] = { { + .tbt_alt_mode = 0x0001, + .tbt_adapter = TBT_ADAPTER_TBT3, + .intel_spec_b0 = 0, + .vendor_spec_b0 = 0, + .vendor_spec_b1 = 0, +} }; + +static const uint32_t vdo_idh = VDO_IDH(1, /* Data caps as USB host */ + 0, /* Not a USB device */ + IDH_PTYPE_PERIPH, 1, /* Supports alt + modes */ + USB_VID_GOOGLE); + +static const uint32_t vdo_idh_rev30 = + VDO_IDH_REV30(1, /* Data caps as USB host */ + 0, /* Not a USB device */ + IDH_PTYPE_PERIPH, 1, /* Supports alt modes */ + IDH_PTYPE_DFP_HOST, USB_TYPEC_RECEPTACLE, USB_VID_GOOGLE); + +static const uint32_t vdo_product = + VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); + +/* TODO(b/168890624): add USB4 to capability once USB4 response implemented */ +static const uint32_t vdo_ufp1 = VDO_UFP1( + (VDO_UFP1_CAPABILITY_USB20 | VDO_UFP1_CAPABILITY_USB32), + USB_TYPEC_RECEPTACLE, VDO_UFP1_ALT_MODE_TBT3, USB_R30_SS_U40_GEN3); + +static const uint32_t vdo_dfp = + VDO_DFP((VDO_DFP_HOST_CAPABILITY_USB20 | VDO_DFP_HOST_CAPABILITY_USB32 | + VDO_DFP_HOST_CAPABILITY_USB4), + USB_TYPEC_RECEPTACLE, 1 /* Port 1 */); + +static int svdm_tbt_compat_response_identity(int port, uint32_t *payload) +{ + /* TODO(b/154962766): Get an XID */ + payload[VDO_I(CSTAT)] = VDO_CSTAT(0); + payload[VDO_I(PRODUCT)] = vdo_product; + + if (pd_get_rev(port, TCPCI_MSG_SOP) == PD_REV30) { + /* PD Revision 3.0 */ + payload[VDO_I(IDH)] = vdo_idh_rev30; + payload[VDO_I(PTYPE_UFP1_VDO)] = vdo_ufp1; + /* TODO(b/156749387): Find power number for USB3/4 */ + payload[VDO_I(PTYPE_UFP2_VDO)] = 0; + payload[VDO_I(PTYPE_DFP_VDO)] = vdo_dfp; + return VDO_I(PTYPE_DFP_VDO) + 1; + } + + /* PD Revision 2.0 */ + payload[VDO_I(IDH)] = vdo_idh; + return VDO_I(PRODUCT) + 1; +} + +static int svdm_tbt_compat_response_svids(int port, uint32_t *payload) +{ + payload[1] = VDO_SVID(USB_VID_INTEL, 0); + return 2; +} + +static int svdm_tbt_compat_response_modes(int port, uint32_t *payload) +{ + if (PD_VDO_VID(payload[0]) == USB_VID_INTEL) { + memcpy(payload + 1, vdo_tbt_modes, sizeof(vdo_tbt_modes)); + return ARRAY_SIZE(vdo_tbt_modes) + 1; + } else { + return 0; /* NAK */ + } +} + +/* Track whether we've been enabled to ACK TBT EnterModes requests */ +static bool tbt_ufp_ack_allowed[CONFIG_USB_PD_PORT_MAX_COUNT]; + +__override enum ec_status +board_set_tbt_ufp_reply(int port, enum typec_tbt_ufp_reply reply) +{ + /* Note: Host command has already bounds-checked port */ + if (reply == TYPEC_TBT_UFP_REPLY_ACK) + tbt_ufp_ack_allowed[port] = true; + else if (reply == TYPEC_TBT_UFP_REPLY_NAK) + tbt_ufp_ack_allowed[port] = false; + else + return EC_RES_INVALID_PARAM; + + return EC_RES_SUCCESS; +} + +static int svdm_tbt_compat_response_enter_mode(int port, uint32_t *payload) +{ + mux_state_t mux_state = 0; + + /* Do not enter mode while CPU is off. */ + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) + return 0; /* NAK */ + + /* Do not enter mode while policy disallows it */ + if (!tbt_ufp_ack_allowed[port]) + return 0; /* NAK */ + + if ((PD_VDO_VID(payload[0]) != USB_VID_INTEL) || + (PD_VDO_OPOS(payload[0]) != OPOS_TBT)) + return 0; /* NAK */ + + mux_state = usb_mux_get(port); + /* + * Ref: USB PD 3.0 Spec figure 6-21 Successful Enter Mode sequence + * UFP (responder) should be in USB mode or safe mode before entering a + * Mode that requires the reconfiguring of any pins. + */ + if ((mux_state & USB_PD_MUX_USB_ENABLED) || + (mux_state & USB_PD_MUX_SAFE_MODE)) { + pd_ufp_set_enter_mode(port, payload); + set_tbt_compat_mode_ready(port); + + /* + * Ref: Above figure 6-21: UFP (responder) should be in the new + * mode before sending the ACK. However, our mux set sequence + * may exceed tVDMEnterMode, so wait as long as we can + * before sending the reply without violating that timer. + */ + if (!usb_mux_set_completed(port)) + usleep(PD_T_VDM_E_MODE / 2); + + CPRINTS("UFP Enter TBT mode"); + return 1; /* ACK */ + } + + CPRINTS("UFP failed to enter TBT mode(mux=0x%x)", mux_state); + return 0; +} + +const struct svdm_response svdm_rsp = { + .identity = &svdm_tbt_compat_response_identity, + .svids = &svdm_tbt_compat_response_svids, + .modes = &svdm_tbt_compat_response_modes, + .enter_mode = &svdm_tbt_compat_response_enter_mode, + .amode = NULL, + .exit_mode = NULL, +}; +#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */ diff --git a/baseboard/volteer/usbc_config.c b/baseboard/volteer/usbc_config.c new file mode 100644 index 0000000000..d77e275282 --- /dev/null +++ b/baseboard/volteer/usbc_config.c @@ -0,0 +1,78 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific USB-C configuration */ + +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "common.h" +#include "driver/charger/isl9241_public.h" +#include "gpio.h" +#include "task.h" +#include "usb_charge.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#ifdef CONFIG_ZEPHYR +#include "baseboard_usbc_config.h" +#include "usbc_config.h" +#endif + +/******************************************************************************/ +void tcpc_alert_event(enum gpio_signal signal) +{ + /* TODO: b/140572591 - check correct operation for Volteer */ + + int port = -1; + + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + port = USBC_PORT_C0; + break; + case GPIO_USB_C1_TCPC_INT_ODL: + port = USBC_PORT_C1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + + default: + break; + } +} + +/** + * Return if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + /* + * For legacy BC1.2 charging with CONFIG_CHARGE_RAMP_SW, ramp up input + * current until voltage drops to the minimum input voltage of the + * charger, 4.096V. + */ + return voltage < ISL9241_BC12_MIN_VOLTAGE; +} diff --git a/baseboard/zork/baseboard.c b/baseboard/zork/baseboard.c index 36591bb4f2..e54656f08a 100644 --- a/baseboard/zork/baseboard.c +++ b/baseboard/zork/baseboard.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,13 +6,11 @@ /* Zork family-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "cbi_ec_fw_config.h" #include "charge_manager.h" #include "charge_ramp.h" #include "charge_state.h" -#include "charge_state_v2.h" #include "common.h" #include "compile_time_macros.h" #include "console.h" @@ -25,22 +23,23 @@ #include "extpower.h" #include "gpio.h" #include "hooks.h" -#include "ioexpander.h" #include "i2c.h" +#include "ioexpander.h" #include "keyboard_scan.h" #include "lid_switch.h" #include "motion_sense.h" #include "power.h" #include "power_button.h" +#include "printf.h" #include "pwm.h" #include "pwm_chip.h" #include "registers.h" #include "switch.h" #include "system.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_mux.h" #include "usb_pd.h" #include "util.h" @@ -60,15 +59,15 @@ const enum gpio_signal hibernate_wake_pins[] = { GPIO_POWER_BUTTON_L, GPIO_EC_RST_ODL, }; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* * In the AOZ1380 PPC, there are no programmable features. We use * the attached NCT3807 to control a GPIO to indicate 1A5 or 3A0 * current limits. */ -__overridable int board_aoz1380_set_vbus_source_current_limit(int port, - enum tcpc_rp_value rp) +__overridable int +board_aoz1380_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) { int rv; @@ -96,16 +95,8 @@ static void baseboard_chipset_resume(void) } DECLARE_HOOK(HOOK_CHIPSET_RESUME, baseboard_chipset_resume, HOOK_PRIO_DEFAULT); -__overridable void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} - /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * F3 key scan cycle completed but scan input is not * charging to logic high when EC start scan next @@ -135,19 +126,19 @@ struct keyboard_scan_config keyscan_config = { * Murata page for part NCP15WB473F03RC. Vdd=3.3V, R=30.9Kohm. */ const struct thermistor_data_pair thermistor_data[] = { - { 2761 / THERMISTOR_SCALING_FACTOR, 0}, - { 2492 / THERMISTOR_SCALING_FACTOR, 10}, - { 2167 / THERMISTOR_SCALING_FACTOR, 20}, - { 1812 / THERMISTOR_SCALING_FACTOR, 30}, - { 1462 / THERMISTOR_SCALING_FACTOR, 40}, - { 1146 / THERMISTOR_SCALING_FACTOR, 50}, - { 878 / THERMISTOR_SCALING_FACTOR, 60}, - { 665 / THERMISTOR_SCALING_FACTOR, 70}, - { 500 / THERMISTOR_SCALING_FACTOR, 80}, - { 434 / THERMISTOR_SCALING_FACTOR, 85}, - { 376 / THERMISTOR_SCALING_FACTOR, 90}, - { 326 / THERMISTOR_SCALING_FACTOR, 95}, - { 283 / THERMISTOR_SCALING_FACTOR, 100} + { 2761 / THERMISTOR_SCALING_FACTOR, 0 }, + { 2492 / THERMISTOR_SCALING_FACTOR, 10 }, + { 2167 / THERMISTOR_SCALING_FACTOR, 20 }, + { 1812 / THERMISTOR_SCALING_FACTOR, 30 }, + { 1462 / THERMISTOR_SCALING_FACTOR, 40 }, + { 1146 / THERMISTOR_SCALING_FACTOR, 50 }, + { 878 / THERMISTOR_SCALING_FACTOR, 60 }, + { 665 / THERMISTOR_SCALING_FACTOR, 70 }, + { 500 / THERMISTOR_SCALING_FACTOR, 80 }, + { 434 / THERMISTOR_SCALING_FACTOR, 85 }, + { 376 / THERMISTOR_SCALING_FACTOR, 90 }, + { 326 / THERMISTOR_SCALING_FACTOR, 95 }, + { 283 / THERMISTOR_SCALING_FACTOR, 100 } }; const struct thermistor_info thermistor_info = { @@ -156,8 +147,7 @@ const struct thermistor_info thermistor_info = { .data = thermistor_data, }; -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { if (ec_config_has_lid_angle_tablet_mode()) { int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); @@ -177,7 +167,6 @@ void lid_angle_peripheral_enable(int enable) } } } -#endif static void cbi_init(void) { @@ -236,7 +225,7 @@ void board_hibernate(void) pd_request_source_voltage(port, SAFE_RESET_VBUS_MV); /* Give PD task and PPC chip time to get to 5V */ - msleep(300); + msleep(900); } } @@ -266,8 +255,10 @@ void board_print_temps(void) { int t, i; int rv; + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; - cprintf(CC_THERMAL, "[%pT ", PRINTF_TIMESTAMP_NOW); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + cprintf(CC_THERMAL, "[%s ", ts_str); for (i = 0; i < TEMP_SENSOR_COUNT; ++i) { rv = temp_sensor_read(i, &t); if (rv == EC_SUCCESS) @@ -281,7 +272,7 @@ void board_print_temps(void) temps_interval * SECOND); } -static int command_temps_log(int argc, char **argv) +static int command_temps_log(int argc, const char **argv) { char *e = NULL; @@ -296,8 +287,7 @@ static int command_temps_log(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(tempslog, command_temps_log, - "seconds", +DECLARE_CONSOLE_COMMAND(tempslog, command_temps_log, "seconds", "Print temp sensors periodically"); /* diff --git a/baseboard/zork/baseboard.h b/baseboard/zork/baseboard.h index cd3bb4cbb9..c55ca12c76 100644 --- a/baseboard/zork/baseboard.h +++ b/baseboard/zork/baseboard.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,22 +8,21 @@ #ifndef __CROS_EC_BASEBOARD_H #define __CROS_EC_BASEBOARD_H -#if (defined(VARIANT_ZORK_TREMBYLE) \ - + defined(VARIANT_ZORK_DALBOZ)) != 1 +#if (defined(VARIANT_ZORK_TREMBYLE) + defined(VARIANT_ZORK_DALBOZ)) != 1 #error Must choose VARIANT_ZORK_TREMBYLE or VARIANT_ZORK_DALBOZ #endif /* NPCX7 config */ -#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ -#define NPCX_TACH_SEL2 0 /* No tach. */ -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX_TACH_SEL2 0 /* No tach. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ /* Internal SPI flash on NPCX7 */ -#define CONFIG_FLASH_SIZE (512 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q40 /* Internal SPI flash type. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_HOSTCMD))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_HOSTCMD) | CC_MASK(CC_LPC))) /* * Enable 1 slot of secure temporary storage to support @@ -38,9 +37,9 @@ #define CONFIG_CMD_AP_RESET_LOG #define CONFIG_CPU_PROCHOT_ACTIVE_LOW #define CONFIG_HIBERNATE_PSL -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_I2C_UPDATE_IF_CHANGED #define CONFIG_LOW_POWER_IDLE #define CONFIG_LTO @@ -53,7 +52,7 @@ #define CONFIG_VOLUME_BUTTONS /* CBI EEPROM for board version and SKU ID */ -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_BOARD_VERSION_CBI #define CONFIG_CRC8 @@ -61,13 +60,24 @@ #define CONFIG_BATTERY_FUEL_GAUGE #define CONFIG_BATTERY_REVIVE_DISCONNECT #define CONFIG_BATTERY_SMART +/* + * Enable support for battery hostcmd, supporting longer strings. + * + * Vilboz battery options' model names vary in the 8th character, which is + * truncated in the memory mapped battery info; differentiating them requires + * support for EC_CMD_BATTERY_GET_STATIC version 1. + */ +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 #define CONFIG_BC12_DETECT_PI3USB9201 #define CONFIG_CHARGER #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_ISL9241 #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 @@ -82,20 +92,19 @@ #define CONFIG_CHIPSET_CAN_THROTTLE #define CONFIG_CHIPSET_RESET_HOOK -#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#undef CONFIG_EXTPOWER_DEBOUNCE_MS #define CONFIG_EXTPOWER_DEBOUNCE_MS 200 #define CONFIG_EXTPOWER_GPIO #define CONFIG_POWER_COMMON -#define CONFIG_POWER_SHUTDOWN_PAUSE_IN_S5 #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 #define CONFIG_POWER_BUTTON_TO_PCH_CUSTOM +#define CONFIG_THROTTLE_AP #ifdef VARIANT_ZORK_TREMBYLE - #define CONFIG_FANS FAN_CH_COUNT - #undef CONFIG_FAN_INIT_SPEED - #define CONFIG_FAN_INIT_SPEED 50 - #define CONFIG_THROTTLE_AP +#define CONFIG_FANS FAN_CH_COUNT +#undef CONFIG_FAN_INIT_SPEED +#define CONFIG_FAN_INIT_SPEED 50 #endif #define CONFIG_LED_COMMON @@ -113,10 +122,9 @@ #define CONFIG_IO_EXPANDER #define CONFIG_IO_EXPANDER_NCT38XX -#define CONFIG_KEYBOARD_BOARD_CONFIG #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PROTOCOL_8042 -#undef CONFIG_KEYBOARD_VIVALDI +#undef CONFIG_KEYBOARD_VIVALDI /* * USB ID @@ -132,14 +140,14 @@ #define CONFIG_USB_PD_TCPMV2 #ifndef CONFIG_USB_PD_TCPMV2 - #define CONFIG_USB_PD_TCPMV1 +#define CONFIG_USB_PD_TCPMV1 #else - #define CONFIG_USB_PD_DECODE_SOP - #define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_USB_DRP_ACC_TRYSRC - /* Enable TCPMv2 Fast Role Swap */ - /* Turn off until FRSwap is working */ - #undef CONFIG_USB_PD_FRS_TCPC +/* Enable TCPMv2 Fast Role Swap */ +/* Turn off until FRSwap is working */ +#undef CONFIG_USB_PD_FRS_TCPC #endif #define CONFIG_HOSTCMD_PD_CONTROL @@ -156,12 +164,11 @@ * Use a custom HPD function that supports HPD on IO expander. * TODO(b/165622386) remove this when HPD is on EC GPIO. */ -# define CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM +#define CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM #endif #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE #define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_TCPC_LOW_POWER #define CONFIG_USB_PD_TCPM_MUX #define CONFIG_USB_PD_TCPM_NCT38XX @@ -179,17 +186,19 @@ #define CONFIG_USB_MUX_AMD_FP5 #if defined(VARIANT_ZORK_TREMBYLE) - #define CONFIG_USB_PD_PORT_MAX_COUNT 2 - #define CONFIG_USBC_PPC_NX20P3483 - #define CONFIG_USBC_RETIMER_PS8802 - #define CONFIG_USBC_RETIMER_PS8818 - #define CONFIG_IO_EXPANDER_PORT_COUNT USBC_PORT_COUNT - #define CONFIG_USB_MUX_RUNTIME_CONFIG - /* USB-A config */ - #define GPIO_USB1_ILIM_SEL IOEX_USB_A0_CHARGE_EN_L - #define GPIO_USB2_ILIM_SEL IOEX_USB_A1_CHARGE_EN_DB_L +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USBC_PPC_NX20P3483 +#define CONFIG_USBC_RETIMER_PS8802 +#define CONFIG_USBC_RETIMER_PS8818 +#define CONFIG_IO_EXPANDER_PORT_COUNT USBC_PORT_COUNT +#define CONFIG_USB_MUX_RUNTIME_CONFIG +/* USB-A config */ +#define GPIO_USB1_ILIM_SEL IOEX_USB_A0_CHARGE_EN_L +#define GPIO_USB2_ILIM_SEL IOEX_USB_A1_CHARGE_EN_DB_L +/* PS8818 RX Input Termination - default value */ +#define ZORK_PS8818_RX_INPUT_TERM PS8818_RX_INPUT_TERM_112_OHM #elif defined(VARIANT_ZORK_DALBOZ) - #define CONFIG_IO_EXPANDER_PORT_COUNT IOEX_PORT_COUNT +#define CONFIG_IO_EXPANDER_PORT_COUNT IOEX_PORT_COUNT #endif /* USB-A config */ @@ -199,14 +208,13 @@ #define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_CDP #define CONFIG_USB_PORT_POWER_SMART_INVERTED -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 65000 -#define PD_MAX_CURRENT_MA 3250 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 65000 +#define PD_MAX_CURRENT_MA 3250 +#define PD_MAX_VOLTAGE_MV 20000 /* Round up 3250 max current to multiple of 128mA for ISL9241 AC prochot. */ #define ZORK_AC_PROCHOT_CURRENT_MA 3328 @@ -216,8 +224,7 @@ * CONFIG_CHARGER_LIMIT_* is not set, so there is no additional restriction on * Depthcharge to boot OS. */ -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 4 -#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 50000 +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 50000 /* Increase length of history buffer for port80 messages. */ #undef CONFIG_PORT80_HISTORY_LEN @@ -227,33 +234,38 @@ #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 -#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 -#define I2C_PORT_USBA0 NPCX_I2C_PORT0_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT1_0 -#define I2C_PORT_USBA1 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_AP_MUX NPCX_I2C_PORT3_0 -#define I2C_PORT_THERMAL_AP NPCX_I2C_PORT4_1 -#define I2C_PORT_SENSOR NPCX_I2C_PORT5_0 -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_EEPROM I2C_PORT_SENSOR -#define I2C_PORT_AP_AUDIO NPCX_I2C_PORT6_1 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 +#define I2C_PORT_USBA0 NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT1_0 +#define I2C_PORT_USBA1 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_AP_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_THERMAL_AP NPCX_I2C_PORT4_1 +#define I2C_PORT_SENSOR NPCX_I2C_PORT5_0 +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_EEPROM I2C_PORT_SENSOR +#define I2C_PORT_AP_AUDIO NPCX_I2C_PORT6_1 #if defined(VARIANT_ZORK_TREMBYLE) - #define CONFIG_CHARGER_RUNTIME_CONFIG - #define I2C_PORT_BATTERY NPCX_I2C_PORT2_0 - #define I2C_PORT_CHARGER_V0 NPCX_I2C_PORT2_0 - #define I2C_PORT_CHARGER_V1 NPCX_I2C_PORT4_1 - #define I2C_PORT_AP_HDMI NPCX_I2C_PORT7_0 +#define CONFIG_CHARGER_RUNTIME_CONFIG +#define I2C_PORT_BATTERY NPCX_I2C_PORT2_0 +#define I2C_PORT_CHARGER_V0 NPCX_I2C_PORT2_0 +#define I2C_PORT_CHARGER_V1 NPCX_I2C_PORT4_1 +#define I2C_PORT_AP_HDMI NPCX_I2C_PORT7_0 #elif defined(VARIANT_ZORK_DALBOZ) - #define I2C_PORT_BATTERY_V0 NPCX_I2C_PORT2_0 - #define I2C_PORT_BATTERY_V1 NPCX_I2C_PORT7_0 - #define I2C_PORT_CHARGER NPCX_I2C_PORT2_0 +#define I2C_PORT_BATTERY_V0 NPCX_I2C_PORT2_0 +#define I2C_PORT_BATTERY_V1 NPCX_I2C_PORT7_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT2_0 #endif -#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_ADDR_EEPROM_FLAGS 0x50 -/* Sensors */ #define CONFIG_MKBP_EVENT +/* Host event is required to wake from sleep */ +#define CONFIG_MKBP_USE_GPIO_AND_HOST_EVENT +/* Required to enable runtime configuration */ +#define CONFIG_MKBP_EVENT_WAKEUP_MASK (BIT(EC_MKBP_EVENT_DP_ALT_MODE_ENTERED)) + +/* Sensors */ #define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT /* Thermal */ @@ -279,7 +291,6 @@ #ifndef __ASSEMBLER__ #include "gpio_signal.h" -#include "math_util.h" #include "registers.h" enum power_signal { @@ -297,11 +308,7 @@ enum fan_channel { }; #ifdef VARIANT_ZORK_TREMBYLE -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; #endif enum sensor_id { @@ -311,23 +318,6 @@ enum sensor_id { SENSOR_COUNT, }; -/* - * Matrix to rotate accelerators into the standard reference frame. The default - * is the identity which is correct for the reference design. Variations of - * Zork may need to change it for manufacturability. - * For the lid: - * +x to the right - * +y up - * +z out of the page - * - * The principle axes of the body are aligned with the lid when the lid is in - * the 180 degree position (open, flat). - * - * Boards within the Zork family may need to modify this definition at - * board_init() time. - */ -extern mat33_fp_t zork_base_standard_ref; - extern const struct thermistor_info thermistor_info; /* Sensors without hardware FIFO are in forced mode */ diff --git a/baseboard/zork/build.mk b/baseboard/zork/build.mk index 740252ac9a..6cf67a1a39 100644 --- a/baseboard/zork/build.mk +++ b/baseboard/zork/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,6 +8,7 @@ baseboard-y=baseboard.o baseboard-y+=cbi_ec_fw_config.o +baseboard-y+=cbi_ssfc.o baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o baseboard-$(VARIANT_ZORK_TREMBYLE)+=variant_trembyle.o baseboard-$(VARIANT_ZORK_DALBOZ)+=variant_dalboz.o diff --git a/baseboard/zork/cbi_ec_fw_config.c b/baseboard/zork/cbi_ec_fw_config.c index d8101855f7..555aeab9d7 100644 --- a/baseboard/zork/cbi_ec_fw_config.c +++ b/baseboard/zork/cbi_ec_fw_config.c @@ -1,10 +1,10 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "common.h" #include "cbi_ec_fw_config.h" +#include "common.h" #include "cros_board_info.h" /**************************************************************************** @@ -28,8 +28,7 @@ uint32_t get_cbi_fw_config(void) */ enum ec_cfg_usb_db_type ec_config_get_usb_db(void) { - return ((get_cbi_fw_config() & EC_CFG_USB_DB_MASK) - >> EC_CFG_USB_DB_L); + return ((get_cbi_fw_config() & EC_CFG_USB_DB_MASK) >> EC_CFG_USB_DB_L); } /* @@ -37,8 +36,7 @@ enum ec_cfg_usb_db_type ec_config_get_usb_db(void) */ enum ec_cfg_usb_mb_type ec_config_get_usb_mb(void) { - return ((get_cbi_fw_config() & EC_CFG_USB_MB_MASK) - >> EC_CFG_USB_MB_L); + return ((get_cbi_fw_config() & EC_CFG_USB_MB_MASK) >> EC_CFG_USB_MB_L); } /* @@ -46,35 +44,52 @@ enum ec_cfg_usb_mb_type ec_config_get_usb_mb(void) */ enum ec_cfg_lid_accel_sensor_type ec_config_has_lid_accel_sensor(void) { - return ((get_cbi_fw_config() & EC_CFG_LID_ACCEL_SENSOR_MASK) - >> EC_CFG_LID_ACCEL_SENSOR_L); + return ((get_cbi_fw_config() & EC_CFG_LID_ACCEL_SENSOR_MASK) >> + EC_CFG_LID_ACCEL_SENSOR_L); } /* * ec_config_has_base_gyro_sensor() will return ec_cfg_base_gyro_sensor_type */ -enum ec_cfg_base_gyro_sensor_type ec_config_has_base_gyro_sensor(void) +enum ec_ssfc_base_gyro_sensor ec_config_has_base_gyro_sensor(void) { - return ((get_cbi_fw_config() & EC_CFG_BASE_GYRO_SENSOR_MASK) - >> EC_CFG_BASE_GYRO_SENSOR_L); + return ((get_cbi_fw_config() & EC_CFG_BASE_GYRO_SENSOR_MASK) >> + EC_CFG_BASE_GYRO_SENSOR_L); } /* * ec_config_has_pwm_keyboard_backlight() will return 1 is present or 0 */ -enum ec_cfg_pwm_keyboard_backlight_type ec_config_has_pwm_keyboard_backlight( - void) +enum ec_cfg_pwm_keyboard_backlight_type +ec_config_has_pwm_keyboard_backlight(void) { - return ((get_cbi_fw_config() & EC_CFG_PWM_KEYBOARD_BACKLIGHT_MASK) - >> EC_CFG_PWM_KEYBOARD_BACKLIGHT_L); + return ((get_cbi_fw_config() & EC_CFG_PWM_KEYBOARD_BACKLIGHT_MASK) >> + EC_CFG_PWM_KEYBOARD_BACKLIGHT_L); } /* * ec_config_has_lid_angle_tablet_mode() will return 1 is present or 0 */ -enum ec_cfg_lid_angle_tablet_mode_type ec_config_has_lid_angle_tablet_mode( - void) +enum ec_cfg_lid_angle_tablet_mode_type ec_config_has_lid_angle_tablet_mode(void) +{ + return ((get_cbi_fw_config() & EC_CFG_LID_ANGLE_TABLET_MODE_MASK) >> + EC_CFG_LID_ANGLE_TABLET_MODE_L); +} + +/* + * ec_config_lte_present() will return 1 if present else 0. + */ +enum ec_cfg_lte_present_type ec_config_lte_present(void) +{ + return ((get_cbi_fw_config() & EC_CFG_LTE_PRESENT_MASK) >> + EC_CFG_LTE_PRESENT_L); +} + +/* + * ec_config_keyboard_layout() will return keyboard layout type. + */ +enum ec_cfg_keyboard_layout_type ec_config_keyboard_layout(void) { - return ((get_cbi_fw_config() & EC_CFG_LID_ANGLE_TABLET_MODE_MASK) - >> EC_CFG_LID_ANGLE_TABLET_MODE_L); + return ((get_cbi_fw_config() & EC_CFG_KEYBOARD_LAYOUT_MASK) >> + EC_CFG_KEYBOARD_LAYOUT_L); } diff --git a/baseboard/zork/cbi_ec_fw_config.h b/baseboard/zork/cbi_ec_fw_config.h index 9222dd9f45..a73e4504bb 100644 --- a/baseboard/zork/cbi_ec_fw_config.h +++ b/baseboard/zork/cbi_ec_fw_config.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,8 @@ #ifndef _ZORK_CBI_EC_FW_CONFIG__H_ #define _ZORK_CBI_EC_FW_CONFIG__H_ +#include "cbi_ssfc.h" + /**************************************************************************** * CBI Zork EC FW Configuration */ @@ -17,11 +19,9 @@ * get_cbi_ec_cfg_usb_db() will return the DB option number. * The option number will be defined in a variant or board level enumeration */ -#define EC_CFG_USB_DB_L 0 -#define EC_CFG_USB_DB_H 3 -#define EC_CFG_USB_DB_MASK \ - GENMASK(EC_CFG_USB_DB_H,\ - EC_CFG_USB_DB_L) +#define EC_CFG_USB_DB_L 0 +#define EC_CFG_USB_DB_H 3 +#define EC_CFG_USB_DB_MASK GENMASK(EC_CFG_USB_DB_H, EC_CFG_USB_DB_L) /* * USB Main Board (4 bits) @@ -29,11 +29,9 @@ * get_cbi_ec_cfg_usb_mb() will return the MB option number. * The option number will be defined in a variant or board level enumeration */ -#define EC_CFG_USB_MB_L 4 -#define EC_CFG_USB_MB_H 7 -#define EC_CFG_USB_MB_MASK \ - GENMASK(EC_CFG_USB_MB_H,\ - EC_CFG_USB_MB_L) +#define EC_CFG_USB_MB_L 4 +#define EC_CFG_USB_MB_H 7 +#define EC_CFG_USB_MB_MASK GENMASK(EC_CFG_USB_MB_H, EC_CFG_USB_MB_L) /* * Lid Accelerometer Sensor (3 bits) @@ -45,27 +43,20 @@ enum ec_cfg_lid_accel_sensor_type { LID_ACCEL_KX022 = 1, LID_ACCEL_LIS2DWL = 2, }; -#define EC_CFG_LID_ACCEL_SENSOR_L 8 -#define EC_CFG_LID_ACCEL_SENSOR_H 10 -#define EC_CFG_LID_ACCEL_SENSOR_MASK \ - GENMASK(EC_CFG_LID_ACCEL_SENSOR_H,\ - EC_CFG_LID_ACCEL_SENSOR_L) +#define EC_CFG_LID_ACCEL_SENSOR_L 8 +#define EC_CFG_LID_ACCEL_SENSOR_H 10 +#define EC_CFG_LID_ACCEL_SENSOR_MASK \ + GENMASK(EC_CFG_LID_ACCEL_SENSOR_H, EC_CFG_LID_ACCEL_SENSOR_L) /* * Base Gyro Sensor (3 bits) * * ec_config_has_base_gyro_sensor() will return ec_cfg_base_gyro_sensor_type */ -enum ec_cfg_base_gyro_sensor_type { - BASE_GYRO_NONE = 0, - BASE_GYRO_BMI160 = 1, - BASE_GYRO_LSM6DSM = 2, -}; -#define EC_CFG_BASE_GYRO_SENSOR_L 11 -#define EC_CFG_BASE_GYRO_SENSOR_H 13 -#define EC_CFG_BASE_GYRO_SENSOR_MASK \ - GENMASK(EC_CFG_BASE_GYRO_SENSOR_H,\ - EC_CFG_BASE_GYRO_SENSOR_L) +#define EC_CFG_BASE_GYRO_SENSOR_L 11 +#define EC_CFG_BASE_GYRO_SENSOR_H 13 +#define EC_CFG_BASE_GYRO_SENSOR_MASK \ + GENMASK(EC_CFG_BASE_GYRO_SENSOR_H, EC_CFG_BASE_GYRO_SENSOR_L) /* * PWM Keyboard Backlight (1 bit) @@ -76,11 +67,11 @@ enum ec_cfg_pwm_keyboard_backlight_type { PWM_KEYBOARD_BACKLIGHT_NO = 0, PWM_KEYBOARD_BACKLIGHT_YES = 1, }; -#define EC_CFG_PWM_KEYBOARD_BACKLIGHT_L 14 -#define EC_CFG_PWM_KEYBOARD_BACKLIGHT_H 14 -#define EC_CFG_PWM_KEYBOARD_BACKLIGHT_MASK \ - GENMASK(EC_CFG_PWM_KEYBOARD_BACKLIGHT_H,\ - EC_CFG_PWM_KEYBOARD_BACKLIGHT_L) +#define EC_CFG_PWM_KEYBOARD_BACKLIGHT_L 14 +#define EC_CFG_PWM_KEYBOARD_BACKLIGHT_H 14 +#define EC_CFG_PWM_KEYBOARD_BACKLIGHT_MASK \ + GENMASK(EC_CFG_PWM_KEYBOARD_BACKLIGHT_H, \ + EC_CFG_PWM_KEYBOARD_BACKLIGHT_L) /* * Lid Angle Tablet Mode (1 bit) @@ -91,21 +82,49 @@ enum ec_cfg_lid_angle_tablet_mode_type { LID_ANGLE_TABLET_MODE_NO = 0, LID_ANGLE_TABLET_MODE_YES = 1, }; -#define EC_CFG_LID_ANGLE_TABLET_MODE_L 15 -#define EC_CFG_LID_ANGLE_TABLET_MODE_H 15 +#define EC_CFG_LID_ANGLE_TABLET_MODE_L 15 +#define EC_CFG_LID_ANGLE_TABLET_MODE_H 15 #define EC_CFG_LID_ANGLE_TABLET_MODE_MASK \ - GENMASK(EC_CFG_LID_ANGLE_TABLET_MODE_H,\ - EC_CFG_LID_ANGLE_TABLET_MODE_L) + GENMASK(EC_CFG_LID_ANGLE_TABLET_MODE_H, EC_CFG_LID_ANGLE_TABLET_MODE_L) +/* + * LTE Modem Present (1 bit) + * + * ec_config_lte_present() will return 1 if present else 0. + */ +enum ec_cfg_lte_present_type { + LTE_NONE = 0, + LTE_PRESENT = 1, +}; +#define EC_CFG_LTE_PRESENT_L 29 +#define EC_CFG_LTE_PRESENT_H 29 +#define EC_CFG_LTE_PRESENT_MASK \ + GENMASK(EC_CFG_LTE_PRESENT_H, EC_CFG_LTE_PRESENT_L) + +/* + * Keyboard Layout (2 bit) + * + * ec_config_keyboard_layout() will return keyboard layout type. + */ +enum ec_cfg_keyboard_layout_type { + KB_LAYOUT_DEFAULT = 0, + KB_LAYOUT_1 = 1, +}; +#define EC_CFG_KEYBOARD_LAYOUT_L 30 +#define EC_CFG_KEYBOARD_LAYOUT_H 31 +#define EC_CFG_KEYBOARD_LAYOUT_MASK \ + GENMASK(EC_CFG_KEYBOARD_LAYOUT_H, EC_CFG_KEYBOARD_LAYOUT_L) uint32_t get_cbi_fw_config(void); enum ec_cfg_usb_db_type ec_config_get_usb_db(void); enum ec_cfg_usb_mb_type ec_config_get_usb_mb(void); enum ec_cfg_lid_accel_sensor_type ec_config_has_lid_accel_sensor(void); -enum ec_cfg_base_gyro_sensor_type ec_config_has_base_gyro_sensor(void); -enum ec_cfg_pwm_keyboard_backlight_type ec_config_has_pwm_keyboard_backlight( - void); -enum ec_cfg_lid_angle_tablet_mode_type ec_config_has_lid_angle_tablet_mode( - void); +enum ec_ssfc_base_gyro_sensor ec_config_has_base_gyro_sensor(void); +enum ec_cfg_pwm_keyboard_backlight_type +ec_config_has_pwm_keyboard_backlight(void); +enum ec_cfg_lid_angle_tablet_mode_type +ec_config_has_lid_angle_tablet_mode(void); +enum ec_cfg_lte_present_type ec_config_lte_present(void); +enum ec_cfg_keyboard_layout_type ec_config_keyboard_layout(void); #endif /* _ZORK_CBI_EC_FW_CONFIG__H_ */ diff --git a/baseboard/zork/cbi_ssfc.c b/baseboard/zork/cbi_ssfc.c new file mode 100644 index 0000000000..9cc2fdcef3 --- /dev/null +++ b/baseboard/zork/cbi_ssfc.c @@ -0,0 +1,47 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static uint32_t cached_ssfc; + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_gyro_sensor get_cbi_ssfc_base_sensor(void) +{ + return (cached_ssfc & SSFC_BASE_GYRO_MASK) >> SSFC_BASE_GYRO_OFFSET; +} + +enum ec_ssfc_spkr_auto_mode get_cbi_ssfc_spkr_auto_mode(void) +{ + return (cached_ssfc & SSFC_SPKR_AUTO_MODE_MASK) >> + SSFC_SPKR_AUTO_MODE_OFFSET; +} + +enum ec_ssfc_edp_phy_alt_tuning get_cbi_ssfc_edp_phy_alt_tuning(void) +{ + return (cached_ssfc & SSFC_EDP_PHY_ALT_TUNING_MASK) >> + SSFC_EDP_PHY_ALT_TUNING_OFFSET; +} + +enum ec_ssfc_c1_mux get_cbi_ssfc_c1_mux(void) +{ + return (cached_ssfc & SSFC_C1_MUX_MASK) >> SSFC_C1_MUX_OFFSET; +} diff --git a/baseboard/zork/cbi_ssfc.h b/baseboard/zork/cbi_ssfc.h new file mode 100644 index 0000000000..95bf5ba6e4 --- /dev/null +++ b/baseboard/zork/cbi_ssfc.h @@ -0,0 +1,80 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _ZORK_CBI_SSFC__H_ +#define _ZORK_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Zork CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_gyro_sensor { + SSFC_BASE_GYRO_NONE = 0, + SSFC_BASE_GYRO_BMI160 = 1, + SSFC_BASE_GYRO_LSM6DSM = 2, + SSFC_BASE_GYRO_ICM426XX = 3, + SSFC_BASE_GYRO_ICM42607 = 4, +}; +#define SSFC_BASE_GYRO_OFFSET 0 +#define SSFC_BASE_GYRO_MASK GENMASK(2, 0) + +enum ec_ssfc_spkr_auto_mode { + SSFC_SPKR_AUTO_MODE_OFF = 0, + SSFC_SPKR_AUTO_MODE_ON = 1, +}; +#define SSFC_SPKR_AUTO_MODE_OFFSET 3 +#define SSFC_SPKR_AUTO_MODE_MASK GENMASK(3, 3) + +/* + * eDP PHY Alternate Tuning (Bits 4-5) + */ +enum ec_ssfc_edp_phy_alt_tuning { + SSFC_EDP_PHY_ALT_TUNING_0 = 0, + SSFC_EDP_PHY_ALT_TUNING_1 = 1, + SSFC_EDP_PHY_ALT_TUNING_2 = 2, + SSFC_EDP_PHY_ALT_TUNING_3 = 3, +}; +#define SSFC_EDP_PHY_ALT_TUNING_OFFSET 4 +#define SSFC_EDP_PHY_ALT_TUNING_MASK GENMASK(5, 4) + +/* + * TypeC port 1 secondary MUX (Bits 6-7) + */ +enum ec_ssfc_c1_mux { + SSFC_C1_MUX_NONE = 0, + SSFC_C1_MUX_TUSB544 = 1, + SSFC_C1_MUX_PS8818 = 2, +}; +#define SSFC_C1_MUX_OFFSET 6 +#define SSFC_C1_MUX_MASK GENMASK(7, 6) + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_gyro_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get whether speaker amp auto mode is enabled from SSFC. + */ +enum ec_ssfc_spkr_auto_mode get_cbi_ssfc_spkr_auto_mode(void); + +/** + * Get the eDP PHY alternate tuning from SSFC. + */ +enum ec_ssfc_edp_phy_alt_tuning get_cbi_ssfc_edp_phy_alt_tuning(void); + +/** + * Get the C1 usb mux from SSFC. + */ +enum ec_ssfc_c1_mux get_cbi_ssfc_c1_mux(void); + +#endif /* _ZORK_CBI_SSFC__H_ */ diff --git a/baseboard/zork/usb_pd_policy.c b/baseboard/zork/usb_pd_policy.c index 513772213e..aeca706eb2 100644 --- a/baseboard/zork/usb_pd_policy.c +++ b/baseboard/zork/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,8 +18,8 @@ #include "usbc_ppc.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -39,11 +39,6 @@ void pd_power_supply_reset(int port) pd_set_vbus_discharge(port, 1); } -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -65,11 +60,6 @@ int pd_set_power_supply_ready(int port) if (rv) return rv; -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -80,83 +70,3 @@ int board_vbus_source_enabled(int port) { return ppc_is_sourcing_vbus(port); } - -/* ----------------- Vendor Defined Messages ------------------ */ -#ifdef CONFIG_USB_PD_ALT_MODE_DFP -mux_state_t svdm_dp_mux_mode(int port) -{ - int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); - int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]); - /* - * Multi-function operation is only allowed if that pin config is - * supported. - */ - if ((pin_mode & MODE_DP_PIN_MF_MASK) && mf_pref) - return USB_PD_MUX_DOCK; - else - return USB_PD_MUX_DP_ENABLED; -} - -__override int svdm_dp_config(int port, uint32_t *payload) -{ - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); - int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); - int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]); - mux_state_t mux_mode = svdm_dp_mux_mode(port); - - if (!pin_mode) - return 0; - - CPRINTS("pin_mode: %x, mf: %d, mux: %d", pin_mode, mf_pref, mux_mode); - - /* - * Place the USB Type-C pins that are to be re-configured to DisplayPort - * Configuration into the Safe state. For USB_PD_MUX_DOCK, the - * superspeed signals can remain connected. For USB_PD_MUX_DP_ENABLED, - * disconnect the superspeed signals here, before the pins are - * re-configured to DisplayPort (in svdm_dp_post_config, when we receive - * the config ack). - */ - if (mux_mode == USB_PD_MUX_DP_ENABLED) - usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_CONNECT, - pd_get_polarity(port)); - - payload[0] = VDO(USB_SID_DISPLAYPORT, 1, - CMD_DP_CONFIG | VDO_OPOS(opos)); - payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ - 1, /* DPv1.3 signaling */ - 2); /* UFP connected */ - return 2; -}; - -__override void svdm_dp_post_config(int port) -{ - /* Connect the SBU and USB lines to the connector. */ - ppc_set_sbu(port, 1); - usb_mux_set(port, svdm_dp_mux_mode(port), USB_SWITCH_CONNECT, - pd_get_polarity(port)); - - dp_flags[port] |= DP_FLAGS_DP_ON; - if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) - return; - - gpio_or_ioex_set_level(PORT_TO_HPD(port), 1); - - /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; - - usb_mux_hpd_update(port, 1, 0); -} - -__override void svdm_exit_dp_mode(int port) -{ - dp_flags[port] = 0; - dp_status[port] = 0; - - usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_CONNECT, - pd_get_polarity(port)); - gpio_or_ioex_set_level(PORT_TO_HPD(port), 0); - - usb_mux_hpd_update(port, 0, 0); -} -#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/baseboard/zork/variant_dalboz.c b/baseboard/zork/variant_dalboz.c index 6e76034ced..599f29618b 100644 --- a/baseboard/zork/variant_dalboz.c +++ b/baseboard/zork/variant_dalboz.c @@ -1,10 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "charger.h" #include "chipset.h" #include "common.h" @@ -15,7 +14,7 @@ #include "i2c.h" #include "power.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" const struct power_signal_info power_signal_list[] = { [X86_SLP_S3_N] = { @@ -57,6 +56,11 @@ int board_get_temp(int idx, int *temp_k) if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) return EC_ERROR_NOT_POWERED; + /* adc power not ready when transition to S5 */ + if (chipset_in_or_transitioning_to_state( + CHIPSET_STATE_SOFT_OFF)) + return EC_ERROR_NOT_POWERED; + channel = ADC_TEMP_SENSOR_SOC; break; default: @@ -112,6 +116,37 @@ const struct temp_sensor_t temp_sensors[] = { }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); +__overridable struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT] = { + [TEMP_SENSOR_CHARGER] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), + [EC_TEMP_THRESH_HALT] = C_TO_K(92), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + } + }, + [TEMP_SENSOR_SOC] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), + [EC_TEMP_THRESH_HALT] = C_TO_K(92), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + } + }, + [TEMP_SENSOR_CPU] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), + [EC_TEMP_THRESH_HALT] = C_TO_K(92), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + } + }, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + const struct i2c_port_t i2c_ports[] = { { .name = "tcpc0", diff --git a/baseboard/zork/variant_trembyle.c b/baseboard/zork/variant_trembyle.c index 32151cf0f9..4542ea562c 100644 --- a/baseboard/zork/variant_trembyle.c +++ b/baseboard/zork/variant_trembyle.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,10 +9,10 @@ #include "console.h" #include "driver/bc12/pi3usb9201.h" #include "driver/charger/isl9241.h" -#include "driver/ppc/aoz1380.h" +#include "driver/ppc/aoz1380_public.h" #include "driver/ppc/nx20p348x.h" #include "driver/retimer/ps8802.h" -#include "driver/retimer/ps8818.h" +#include "driver/retimer/ps8818_public.h" #include "driver/retimer/tusb544.h" #include "driver/tcpm/nct38xx.h" #include "driver/usb_mux/amd_fp5.h" @@ -28,8 +28,8 @@ #include "usb_pd_tcpm.h" #include "usbc_ppc.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) const struct i2c_port_t i2c_ports[] = { { @@ -160,8 +160,7 @@ __overridable void ppc_interrupt(enum gpio_signal signal) int board_set_active_charge_port(int port) { - int is_valid_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); int i; if (port == CHARGE_PORT_NONE) { @@ -182,7 +181,6 @@ int board_set_active_charge_port(int port) return EC_ERROR_INVAL; } - /* Check if the port is sourcing VBUS. */ if (ppc_is_sourcing_vbus(port)) { CPRINTFUSB("Skip enable C%d", port); @@ -264,27 +262,33 @@ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { }; BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); -static void reset_pd_port(int port, enum gpio_signal reset_gpio_l, - int hold_delay, int finish_delay) +static void reset_nct38xx_port(int port) { + enum gpio_signal reset_gpio_l; + + if (port == USBC_PORT_C0) + reset_gpio_l = GPIO_USB_C0_TCPC_RST_L; + else if (port == USBC_PORT_C1) + reset_gpio_l = GPIO_USB_C1_TCPC_RST_L; + else + /* Invalid port: do nothing */ + return; + gpio_set_level(reset_gpio_l, 0); - msleep(hold_delay); + msleep(NCT38XX_RESET_HOLD_DELAY_MS); gpio_set_level(reset_gpio_l, 1); - if (finish_delay) - msleep(finish_delay); + nct38xx_reset_notify(port); + if (NCT3807_RESET_POST_DELAY_MS != 0) + msleep(NCT3807_RESET_POST_DELAY_MS); } void board_reset_pd_mcu(void) { /* Reset TCPC0 */ - reset_pd_port(USBC_PORT_C0, GPIO_USB_C0_TCPC_RST_L, - NCT38XX_RESET_HOLD_DELAY_MS, - NCT38XX_RESET_POST_DELAY_MS); + reset_nct38xx_port(USBC_PORT_C0); /* Reset TCPC1 */ - reset_pd_port(USBC_PORT_C1, GPIO_USB_C1_TCPC_RST_L, - NCT38XX_RESET_HOLD_DELAY_MS, - NCT38XX_RESET_POST_DELAY_MS); + reset_nct38xx_port(USBC_PORT_C1); } uint16_t tcpc_get_alert_status(void) @@ -326,18 +330,15 @@ void tcpc_alert_event(enum gpio_signal signal) schedule_deferred_pd_interrupt(port); } - int board_pd_set_frs_enable(int port, int enable) { int rv = EC_SUCCESS; /* Use the TCPC to enable fast switch when FRS included */ if (port == USBC_PORT_C0) { - rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, - !!enable); + rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, !!enable); } else { - rv = ioex_set_level(IOEX_USB_C1_TCPC_FASTSW_CTL_EN, - !!enable); + rv = ioex_set_level(IOEX_USB_C1_TCPC_FASTSW_CTL_EN, !!enable); } return rv; @@ -347,11 +348,11 @@ void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -366,12 +367,12 @@ void bc12_interrupt(enum gpio_signal signal) struct ioexpander_config_t ioex_config[] = { [USBC_PORT_C0] = { .i2c_host_port = I2C_PORT_TCPC0, - .i2c_slave_addr = NCT38XX_I2C_ADDR1_1_FLAGS, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, .drv = &nct38xx_ioexpander_drv, }, [USBC_PORT_C1] = { .i2c_host_port = I2C_PORT_TCPC1, - .i2c_slave_addr = NCT38XX_I2C_ADDR1_1_FLAGS, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, .drv = &nct38xx_ioexpander_drv, }, }; @@ -386,8 +387,7 @@ BUILD_ASSERT(CONFIG_IO_EXPANDER_PORT_COUNT == USBC_PORT_COUNT); * PS8802 set mux board tuning. * Adds in board specific gain and DP lane count configuration */ -static int board_ps8802_mux_set(const struct usb_mux *me, - mux_state_t mux_state) +static int board_ps8802_mux_set(const struct usb_mux *me, mux_state_t mux_state) { int rv = EC_SUCCESS; @@ -399,11 +399,10 @@ static int board_ps8802_mux_set(const struct usb_mux *me, /* USB specific config */ if (mux_state & USB_PD_MUX_USB_ENABLED) { /* Boost the USB gain */ - rv = ps8802_i2c_field_update16(me, - PS8802_REG_PAGE2, - PS8802_REG2_USB_SSEQ_LEVEL, - PS8802_USBEQ_LEVEL_UP_MASK, - PS8802_USBEQ_LEVEL_UP_19DB); + rv = ps8802_i2c_field_update16(me, PS8802_REG_PAGE2, + PS8802_REG2_USB_SSEQ_LEVEL, + PS8802_USBEQ_LEVEL_UP_MASK, + PS8802_USBEQ_LEVEL_UP_19DB); if (rv) return rv; } @@ -411,19 +410,12 @@ static int board_ps8802_mux_set(const struct usb_mux *me, /* DP specific config */ if (mux_state & USB_PD_MUX_DP_ENABLED) { /* Boost the DP gain */ - rv = ps8802_i2c_field_update8(me, - PS8802_REG_PAGE2, - PS8802_REG2_DPEQ_LEVEL, - PS8802_DPEQ_LEVEL_UP_MASK, - PS8802_DPEQ_LEVEL_UP_19DB); + rv = ps8802_i2c_field_update8(me, PS8802_REG_PAGE2, + PS8802_REG2_DPEQ_LEVEL, + PS8802_DPEQ_LEVEL_UP_MASK, + PS8802_DPEQ_LEVEL_UP_19DB); if (rv) return rv; - - /* Enable IN_HPD on the DB */ - gpio_or_ioex_set_level(board_usbc1_retimer_inhpd, 1); - } else { - /* Disable IN_HPD on the DB */ - gpio_or_ioex_set_level(board_usbc1_retimer_inhpd, 0); } return rv; @@ -433,43 +425,46 @@ static int board_ps8802_mux_set(const struct usb_mux *me, * PS8818 set mux board tuning. * Adds in board specific gain and DP lane count configuration */ -static int board_ps8818_mux_set(const struct usb_mux *me, - mux_state_t mux_state) +static int board_ps8818_mux_set(const struct usb_mux *me, mux_state_t mux_state) { int rv = EC_SUCCESS; /* USB specific config */ if (mux_state & USB_PD_MUX_USB_ENABLED) { /* Boost the USB gain */ - rv = ps8818_i2c_field_update8(me, - PS8818_REG_PAGE1, - PS8818_REG1_APTX1EQ_10G_LEVEL, - PS8818_EQ_LEVEL_UP_MASK, - PS8818_EQ_LEVEL_UP_19DB); + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); if (rv) return rv; - rv = ps8818_i2c_field_update8(me, - PS8818_REG_PAGE1, - PS8818_REG1_APTX2EQ_10G_LEVEL, - PS8818_EQ_LEVEL_UP_MASK, - PS8818_EQ_LEVEL_UP_19DB); + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); if (rv) return rv; - rv = ps8818_i2c_field_update8(me, - PS8818_REG_PAGE1, - PS8818_REG1_APTX1EQ_5G_LEVEL, - PS8818_EQ_LEVEL_UP_MASK, - PS8818_EQ_LEVEL_UP_19DB); + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); if (rv) return rv; - rv = ps8818_i2c_field_update8(me, - PS8818_REG_PAGE1, - PS8818_REG1_APTX2EQ_5G_LEVEL, - PS8818_EQ_LEVEL_UP_MASK, - PS8818_EQ_LEVEL_UP_19DB); + /* Set the RX input termination */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_RX_PHY, + PS8818_RX_INPUT_TERM_MASK, + ZORK_PS8818_RX_INPUT_TERM); if (rv) return rv; } @@ -477,11 +472,10 @@ static int board_ps8818_mux_set(const struct usb_mux *me, /* DP specific config */ if (mux_state & USB_PD_MUX_DP_ENABLED) { /* Boost the DP gain */ - rv = ps8818_i2c_field_update8(me, - PS8818_REG_PAGE1, - PS8818_REG1_DPEQ_LEVEL, - PS8818_DPEQ_LEVEL_UP_MASK, - PS8818_DPEQ_LEVEL_UP_19DB); + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_DPEQ_LEVEL, + PS8818_DPEQ_LEVEL_UP_MASK, + PS8818_DPEQ_LEVEL_UP_19DB); if (rv) return rv; @@ -495,7 +489,7 @@ static int board_ps8818_mux_set(const struct usb_mux *me, return rv; } -const struct usb_mux usbc1_ps8802 = { +struct usb_mux usbc1_ps8802 = { .usb_port = USBC_PORT_C1, .i2c_port = I2C_PORT_TCPC1, .i2c_addr_flags = PS8802_I2C_ADDR_FLAGS, @@ -505,7 +499,7 @@ const struct usb_mux usbc1_ps8802 = { const struct usb_mux usbc1_ps8818 = { .usb_port = USBC_PORT_C1, .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = PS8818_I2C_ADDR_FLAGS, + .i2c_addr_flags = PS8818_I2C_ADDR0_FLAGS, .driver = &ps8818_usb_retimer_driver, .board_set = &board_ps8818_mux_set, }; diff --git a/board/adl_ish_lite b/board/adl_ish_lite new file mode 120000 index 0000000000..e43fd15937 --- /dev/null +++ b/board/adl_ish_lite @@ -0,0 +1 @@ +tglrvp_ish \ No newline at end of file diff --git a/board/adlrvpm_ite/board.c b/board/adlrvpm_ite/board.c new file mode 120000 index 0000000000..ea1b98c873 --- /dev/null +++ b/board/adlrvpm_ite/board.c @@ -0,0 +1 @@ +../adlrvpp_ite/board.c \ No newline at end of file diff --git a/board/adlrvpm_ite/board.h b/board/adlrvpm_ite/board.h new file mode 100644 index 0000000000..37662a5d52 --- /dev/null +++ b/board/adlrvpm_ite/board.h @@ -0,0 +1,102 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADL-P-RVP-ITE board-specific configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* ITE EC variant */ +#define VARIANT_INTELRVP_EC_IT8320 + +#include "adlrvp.h" + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_BC_ACOK_EC +#define GPIO_EC_INT_L GPIO_EC_PCH_MKBP_INT_ODL_EC +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW_EC +#define GPIO_LID_OPEN GPIO_SMC_LID +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE_EC +#define GPIO_PCH_WAKE_L GPIO_PCH_WAKE_N +#define GPIO_PCH_PWRBTN_L GPIO_PM_PWRBTN_N_EC +#define GPIO_PCH_RSMRST_L GPIO_PM_RSMRST_EC +#define GPIO_PCH_SLP_S0_L GPIO_PCH_SLP_S0_N +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_R_L +#define GPIO_PG_EC_DSW_PWROK GPIO_VCCPDSW_3P3_EC +#define GPIO_POWER_BUTTON_L GPIO_MECH_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_EC +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL_EC +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUME_UP +#define GPIO_VOLUME_DOWN_L GPIO_VOL_DN_EC_R +#define GPIO_DC_JACK_PRESENT GPIO_STD_ADP_PRSNT +#define GPIO_ESPI_RESET_L GPIO_ESPI_RST_R +#define GPIO_UART1_RX GPIO_UART_SERVO_TX_EC_RX +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_BAT_DET_EC +#define GPIO_BAT_LED_RED_L GPIO_LED_1_L_EC +#define GPIO_PWR_LED_WHITE_L GPIO_LED_2_L_EC +#define GPIO_SLP_SUS_L GPIO_PM_SLP_SUS_EC +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_PWRGD_EC +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_ALL_SYS_PWRGD_EC +#define GPIO_PCH_DSW_PWROK GPIO_DSW_PWROK_EC +#define GPIO_EN_PP3300_A GPIO_EC_DS3 +#define GPIO_TABLET_MODE_L GPIO_SLATE_MODE_INDICATION + +/* I2C ports & Configs */ +#define CONFIG_IT83XX_SMCLK2_ON_GPC7 + +#define I2C_PORT_CHARGER IT83XX_I2C_CH_B + +/* Battery */ +#define I2C_PORT_BATTERY IT83XX_I2C_CH_B + +/* Board ID */ +#define I2C_PORT_PCA9555_BOARD_ID_GPIO IT83XX_I2C_CH_B + +/* Port 80 */ +#define I2C_PORT_PORT80 IT83XX_I2C_CH_B + +/* USB-C I2C */ +#define I2C_PORT_TYPEC_0 IT83XX_I2C_CH_C +#define I2C_PORT_TYPEC_1 IT83XX_I2C_CH_F +#if defined(HAS_TASK_PD_C2) +#define I2C_PORT_TYPEC_2 IT83XX_I2C_CH_E +#define I2C_PORT_TYPEC_3 IT83XX_I2C_CH_D +#endif + +/* TCPC */ +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 + +/* Config Fan */ +#define GPIO_FAN_POWER_EN GPIO_EC_THRM_SEN_PWRGATE_N +#define GPIO_ALL_SYS_PWRGD GPIO_ALL_SYS_PWRGD_EC + +/* Increase EC speed */ +#undef PLL_CLOCK +#define PLL_CLOCK 96000000 + +#ifndef __ASSEMBLER__ + +enum adlrvp_i2c_channel { + I2C_CHAN_FLASH, + I2C_CHAN_BATT_CHG, + I2C_CHAN_TYPEC_0, + I2C_CHAN_TYPEC_1, +#if defined(HAS_TASK_PD_C2) + I2C_CHAN_TYPEC_2, + I2C_CHAN_TYPEC_3, +#endif + I2C_CHAN_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/adlrvpm_ite/build.mk b/board/adlrvpm_ite/build.mk new file mode 120000 index 0000000000..ceffb75d7e --- /dev/null +++ b/board/adlrvpm_ite/build.mk @@ -0,0 +1 @@ +../adlrvpp_ite/build.mk \ No newline at end of file diff --git a/board/adlrvpm_ite/ec.tasklist b/board/adlrvpm_ite/ec.tasklist new file mode 100644 index 0000000000..b0afc9e9a7 --- /dev/null +++ b/board/adlrvpm_ite/ec.tasklist @@ -0,0 +1,24 @@ +/* + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Intel ADL-M-RVP-ITE board-specific configuration. + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/adlrvpm_ite/gpio.inc b/board/adlrvpm_ite/gpio.inc new file mode 120000 index 0000000000..23611687c6 --- /dev/null +++ b/board/adlrvpm_ite/gpio.inc @@ -0,0 +1 @@ +../adlrvpp_ite/gpio.inc \ No newline at end of file diff --git a/board/adlrvpm_ite/vif_override.xml b/board/adlrvpm_ite/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/adlrvpm_ite/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/adlrvpp_ite/board.c b/board/adlrvpp_ite/board.c new file mode 100644 index 0000000000..63bbbfd78c --- /dev/null +++ b/board/adlrvpp_ite/board.c @@ -0,0 +1,155 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADLRVP-ITE board-specific configuration */ +#include "button.h" +#include "fan.h" +#include "fusb302.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "i2c_bitbang.h" +#include "it83xx_pd.h" +#include "lid_switch.h" +#include "pca9675.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "tablet_mode.h" +#include "uart.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + [I2C_CHAN_FLASH] = { + .name = "ec_flash", + .port = IT83XX_I2C_CH_A, + .kbps = 100, + .scl = GPIO_EC_I2C_PROG_SCL, + .sda = GPIO_EC_I2C_PROG_SDA, + }, + [I2C_CHAN_BATT_CHG] = { + .name = "batt_chg", + .port = IT83XX_I2C_CH_B, + .kbps = 100, + .scl = GPIO_SMB_BS_CLK, + .sda = GPIO_SMB_BS_DATA, + }, + [I2C_CHAN_TYPEC_0] = { + .name = "typec_0", + .port = IT83XX_I2C_CH_C, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P0, + .sda = GPIO_USBC_TCPC_I2C_DATA_P0, + }, + [I2C_CHAN_TYPEC_1] = { + .name = "typec_1", + .port = IT83XX_I2C_CH_F, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P2, + .sda = GPIO_USBC_TCPC_I2C_DATA_P2, + }, +#if defined(HAS_TASK_PD_C2) + [I2C_CHAN_TYPEC_2] = { + .name = "typec_2", + .port = IT83XX_I2C_CH_E, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P1, + .sda = GPIO_USBC_TCPC_I2C_DATA_P1, + }, + [I2C_CHAN_TYPEC_3] = { + .name = "typec_3", + .port = IT83XX_I2C_CH_D, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P3, + .sda = GPIO_USBC_TCPC_I2C_DATA_P3, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_ports) == I2C_CHAN_COUNT); +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct i2c_port_t i2c_bitbang_ports[] = { + [I2C_BITBANG_CHAN_BRD_ID] = { + .name = "bitbang_brd_id", + .port = IT83XX_I2C_CH_B, + .kbps = 100, + .scl = GPIO_SMB_BS_CLK, + .sda = GPIO_SMB_BS_DATA, + .drv = &bitbang_drv, + }, + [I2C_BITBANG_CHAN_IOEX_0] = { + .name = "bitbang_ioex_0", + .port = IT83XX_I2C_CH_C, + .kbps = 100, + .scl = GPIO_USBC_TCPC_I2C_CLK_P0, + .sda = GPIO_USBC_TCPC_I2C_DATA_P0, + .drv = &bitbang_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_bitbang_ports) == I2C_BITBANG_CHAN_COUNT); +const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); + +/* USB-C TCPC Configuration */ +const struct tcpc_config_t tcpc_config[] = { + [TYPE_C_PORT_0] = { + .bus_type = EC_BUS_TYPE_EMBEDDED, + /* TCPC is embedded within EC so no i2c config needed */ + .drv = &it83xx_tcpm_drv, + }, +#if defined(HAS_TASK_PD_C1) + [TYPE_C_PORT_1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_1, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#endif +#if defined(HAS_TASK_PD_C2) + [TYPE_C_PORT_2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_2, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#endif +#if defined(HAS_TASK_PD_C3) + [TYPE_C_PORT_3] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_3, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == CONFIG_USB_PD_PORT_MAX_COUNT); + +static void enable_irq(void) +{ + gpio_enable_interrupt(CONFIG_BATTERY_PRESENT_GPIO); +} +DECLARE_HOOK(HOOK_INIT, enable_irq, HOOK_PRIO_LAST); + +DECLARE_DEFERRED(set_charger_system_voltage); + +void battery_detect_interrupt(enum gpio_signal signal) +{ + /* Trigger deferred notification of battery interrupt */ + hook_call_deferred(&set_charger_system_voltage_data, 0); +} diff --git a/board/adlrvpp_ite/board.h b/board/adlrvpp_ite/board.h new file mode 100644 index 0000000000..37662a5d52 --- /dev/null +++ b/board/adlrvpp_ite/board.h @@ -0,0 +1,102 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADL-P-RVP-ITE board-specific configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* ITE EC variant */ +#define VARIANT_INTELRVP_EC_IT8320 + +#include "adlrvp.h" + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_BC_ACOK_EC +#define GPIO_EC_INT_L GPIO_EC_PCH_MKBP_INT_ODL_EC +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW_EC +#define GPIO_LID_OPEN GPIO_SMC_LID +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE_EC +#define GPIO_PCH_WAKE_L GPIO_PCH_WAKE_N +#define GPIO_PCH_PWRBTN_L GPIO_PM_PWRBTN_N_EC +#define GPIO_PCH_RSMRST_L GPIO_PM_RSMRST_EC +#define GPIO_PCH_SLP_S0_L GPIO_PCH_SLP_S0_N +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_R_L +#define GPIO_PG_EC_DSW_PWROK GPIO_VCCPDSW_3P3_EC +#define GPIO_POWER_BUTTON_L GPIO_MECH_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_EC +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL_EC +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUME_UP +#define GPIO_VOLUME_DOWN_L GPIO_VOL_DN_EC_R +#define GPIO_DC_JACK_PRESENT GPIO_STD_ADP_PRSNT +#define GPIO_ESPI_RESET_L GPIO_ESPI_RST_R +#define GPIO_UART1_RX GPIO_UART_SERVO_TX_EC_RX +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_BAT_DET_EC +#define GPIO_BAT_LED_RED_L GPIO_LED_1_L_EC +#define GPIO_PWR_LED_WHITE_L GPIO_LED_2_L_EC +#define GPIO_SLP_SUS_L GPIO_PM_SLP_SUS_EC +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_PWRGD_EC +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_ALL_SYS_PWRGD_EC +#define GPIO_PCH_DSW_PWROK GPIO_DSW_PWROK_EC +#define GPIO_EN_PP3300_A GPIO_EC_DS3 +#define GPIO_TABLET_MODE_L GPIO_SLATE_MODE_INDICATION + +/* I2C ports & Configs */ +#define CONFIG_IT83XX_SMCLK2_ON_GPC7 + +#define I2C_PORT_CHARGER IT83XX_I2C_CH_B + +/* Battery */ +#define I2C_PORT_BATTERY IT83XX_I2C_CH_B + +/* Board ID */ +#define I2C_PORT_PCA9555_BOARD_ID_GPIO IT83XX_I2C_CH_B + +/* Port 80 */ +#define I2C_PORT_PORT80 IT83XX_I2C_CH_B + +/* USB-C I2C */ +#define I2C_PORT_TYPEC_0 IT83XX_I2C_CH_C +#define I2C_PORT_TYPEC_1 IT83XX_I2C_CH_F +#if defined(HAS_TASK_PD_C2) +#define I2C_PORT_TYPEC_2 IT83XX_I2C_CH_E +#define I2C_PORT_TYPEC_3 IT83XX_I2C_CH_D +#endif + +/* TCPC */ +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 + +/* Config Fan */ +#define GPIO_FAN_POWER_EN GPIO_EC_THRM_SEN_PWRGATE_N +#define GPIO_ALL_SYS_PWRGD GPIO_ALL_SYS_PWRGD_EC + +/* Increase EC speed */ +#undef PLL_CLOCK +#define PLL_CLOCK 96000000 + +#ifndef __ASSEMBLER__ + +enum adlrvp_i2c_channel { + I2C_CHAN_FLASH, + I2C_CHAN_BATT_CHG, + I2C_CHAN_TYPEC_0, + I2C_CHAN_TYPEC_1, +#if defined(HAS_TASK_PD_C2) + I2C_CHAN_TYPEC_2, + I2C_CHAN_TYPEC_3, +#endif + I2C_CHAN_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/adlrvpp_ite/build.mk b/board/adlrvpp_ite/build.mk new file mode 100644 index 0000000000..9da9f60561 --- /dev/null +++ b/board/adlrvpp_ite/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Intel ADL-P-RVP-ITE board-specific configuration +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=intelrvp + +board-y=board.o diff --git a/board/adlrvpp_ite/ec.tasklist b/board/adlrvpp_ite/ec.tasklist new file mode 100644 index 0000000000..8bd63b1730 --- /dev/null +++ b/board/adlrvpp_ite/ec.tasklist @@ -0,0 +1,28 @@ +/* + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Intel ADL-P-RVP-ITE board-specific configuration. + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C2, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C3, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C2, pd_interrupt_handler_task, 2, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C3, pd_interrupt_handler_task, 3, ULTRA_TASK_STACK_SIZE) diff --git a/board/adlrvpp_ite/gpio.inc b/board/adlrvpp_ite/gpio.inc new file mode 100644 index 0000000000..22b97a7eff --- /dev/null +++ b/board/adlrvpp_ite/gpio.inc @@ -0,0 +1,207 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADL-P-RVP-ITE board-specific configuration */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +#include "baseboard/intelrvp/adlrvp_ioex_gpio.inc" + +/* Power sequencing interrupts */ +GPIO_INT(ALL_SYS_PWRGD_EC, PIN(F, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_EC, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PCH_SLP_S0_N, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCPDSW_3P3_EC, PIN(I, 3), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCST_PWRGD, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PM_SLP_SUS_EC, PIN(K, 2), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_R_L, PIN(F, 2), GPIO_INT_BOTH, power_signal_interrupt) +#endif +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +GPIO_INT(SLP_S4_R_L, PIN(F, 3), GPIO_INT_BOTH, power_signal_interrupt) +#endif + +/* Button interrupts */ +GPIO_INT(VOLUME_UP, PIN(D, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOL_DN_EC_R, PIN(D, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(SMC_LID, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) +GPIO_INT(MECH_PWR_BTN_ODL, PIN(E, 4), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(I, 4), GPIO_INT_BOTH, switch_interrupt) + +/* DC Jack presence coming from +VADP_OUT */ +GPIO_INT(STD_ADP_PRSNT, PIN(J, 2), GPIO_INT_BOTH, board_dc_jack_interrupt) /* DC_JACK_PRESENT */ + +GPIO_INT(BC_ACOK_EC, PIN(K, 3), GPIO_INT_BOTH, extpower_interrupt) /* AC Present */ + +GPIO_INT(UART_SERVO_TX_EC_RX, PIN(B, 0), GPIO_INT_FALLING, uart_deepsleep_interrupt) + +/* Battery present */ +GPIO_INT(BAT_DET_EC, PIN(K, 0), GPIO_INT_BOTH, battery_detect_interrupt) + +/* USB-C interrupts */ +/* Using embedded TCPC for Port-0 */ +UNIMPLEMENTED(USBC_TCPC_ALRT_P0) +GPIO(NC_USBC_TCPC_ALRT_P0, PIN(I, 7), GPIO_INPUT) +GPIO_INT(USBC_TCPC_PPC_ALRT_P0, PIN(J, 5), GPIO_INT_FALLING, ppc_interrupt) + +/* + * b:200265672 External pull-up resistor of port 1 is removed to fix port 3 + * TCPC interrupt issue. So add internal pull-up for port 1 instead. + * This change is only applied to ITE chip. + */ +#if defined(HAS_TASK_PD_C1) +GPIO_INT(USBC_TCPC_ALRT_P1, PIN(G, 0), GPIO_INT_FALLING | GPIO_PULL_UP, tcpc_alert_event) +GPIO_INT(USBC_TCPC_PPC_ALRT_P1, PIN(C, 4), GPIO_INT_FALLING, ppc_interrupt) +#else +GPIO(USBC_TCPC_ALRT_P1, PIN(G, 0), GPIO_INPUT) +GPIO(USBC_TCPC_PPC_ALRT_P1, PIN(C, 4), GPIO_INPUT) +#endif + +#if defined(HAS_TASK_PD_C2) +GPIO_INT(USBC_TCPC_ALRT_P2, PIN(J, 1), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USBC_TCPC_PPC_ALRT_P2, PIN(E, 5), GPIO_INT_FALLING, ppc_interrupt) +#else +GPIO(USBC_TCPC_ALRT_P2, PIN(J, 1), GPIO_INPUT) +GPIO(USBC_TCPC_PPC_ALRT_P2, PIN(E, 5), GPIO_INPUT) +#endif + +#if defined(HAS_TASK_PD_C3) +GPIO_INT(USBC_TCPC_ALRT_P3, PIN(J, 3), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USBC_TCPC_PPC_ALRT_P3, PIN(E, 6), GPIO_INT_FALLING, ppc_interrupt) +#else +GPIO(USBC_TCPC_ALRT_P3, PIN(J, 3), GPIO_INPUT) +GPIO(USBC_TCPC_PPC_ALRT_P3, PIN(E, 6), GPIO_INPUT) +#endif + +#ifndef CONFIG_HOST_INTERFACE_ESPI +GPIO_INT(ESPI_RST_R, PIN(D, 2), GPIO_INPUT) +#endif + +#ifdef CONFIG_HOST_INTERFACE_ESPI +/* enable 1.8v input of EC's espi_reset pin, and then this pin takes effect. */ +GPIO_INT(ESPI_RST_R, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) /* eSPI_reset# */ +#endif + +/* Sensor Interrupts */ +GPIO_INT(SLATE_MODE_INDICATION, PIN(K, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, gmr_tablet_switch_isr) + +/* Power sequencing GPIOs */ +GPIO(SYS_RST_ODL_EC, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(PROCHOT_EC, PIN(C, 0), GPIO_INPUT) +GPIO(PM_RSMRST_EC, PIN(C, 6), GPIO_OUT_LOW) +GPIO(PM_PWRBTN_N_EC, PIN(D, 0), GPIO_ODR_HIGH) +GPIO(EC_SPI_OE_N, PIN(I, 2), GPIO_OUT_LOW) + +GPIO(EC_PCH_MKBP_INT_ODL_EC, PIN(B, 7), GPIO_ODR_HIGH) +GPIO(EDP_BKLT_EN, PIN(J, 6), GPIO_OUT_HIGH) +GPIO(EC_DS3, PIN(L, 4), GPIO_OUT_LOW) +UNIMPLEMENTED(EN_PP5000) + +/* + * PCH_SYS_PWROK is an input, driven by the Silego chip. The common x86 + * power sequencing expects that PCH_SYS_PWROK is an output and will drive + * this signal if GPIO_PCH_SYS_PWROK is configured. Map this pin as no-connect + * so that state can be monitored using the console. + */ +GPIO(PCH_PWROK_EC_R, PIN(K, 4), GPIO_INPUT) +GPIO(SYS_PWROK_EC, PIN(D, 1), GPIO_OUT_LOW) +GPIO(DSW_PWROK_EC, PIN(L, 6), GPIO_OUT_LOW) + +/* Host communication GPIOs */ +#ifndef CONFIG_HOST_INTERFACE_ESPI +GPIO(PLT_RST_L, PIN(H, 6), GPIO_INPUT | GPIO_PULL_UP) /* PCH_PLTRST_L */ +#endif +GPIO(PCH_WAKE_N, PIN(J, 0), GPIO_ODR_HIGH) + +/* LED */ +GPIO(LED_1_L_EC, PIN(A, 6), GPIO_OUT_HIGH) /* BAT_LED_GREEN_L LED_2_L */ +GPIO(LED_2_L_EC, PIN(A, 7), GPIO_OUT_HIGH) /* AC_LED_GREEN_L LED_1_L */ + +/* H1 pins */ +GPIO(EC_H1_PACKET_MODE_EC, PIN(J, 4), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW_EC, PIN(K, 7), GPIO_OUT_LOW) + +/* Case Closed Debug Mode */ +GPIO_INT(CCD_MODE_ODL, PIN(B, 5), GPIO_INT_BOTH, board_connect_c0_sbu) + +/* FAN control pins */ +GPIO(EC_THRM_SEN_PWRGATE_N, PIN(K, 6), GPIO_OUT_LOW) + +/* + * I2C pins should be configure as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(EC_I2C_PROG_SCL, PIN(B, 3), GPIO_INPUT) /* I2C_A_SCL */ +GPIO(EC_I2C_PROG_SDA, PIN(B, 4), GPIO_INPUT) /* I2C_A_SDA */ +GPIO(SMB_BS_CLK, PIN(C, 1), GPIO_INPUT) /* I2C_B_SCL */ +GPIO(SMB_BS_DATA, PIN(C, 2), GPIO_INPUT) /* I2C_B_SDA */ + +/* P0 IT83XX_I2C_CH_C */ +GPIO(USBC_TCPC_I2C_CLK_P0, PIN(C, 7), GPIO_INPUT) /* I2C_C_SCL */ +GPIO(USBC_TCPC_I2C_DATA_P0, PIN(F, 7), GPIO_INPUT) /* I2C_C_SDA */ + +/* P1 IT83XX_I2C_CH_F */ +GPIO(USBC_TCPC_I2C_CLK_P2, PIN(A, 4), GPIO_INPUT) /* I2C_F_SCL */ +GPIO(USBC_TCPC_I2C_DATA_P2, PIN(A, 5), GPIO_INPUT) /* I2C_F_SDA */ + +/* P2 IT83XX_I2C_CH_E */ +GPIO(USBC_TCPC_I2C_CLK_P1, PIN(E, 0), GPIO_INPUT) /* I2C_E_SCL */ +GPIO(USBC_TCPC_I2C_DATA_P1, PIN(E, 7), GPIO_INPUT) /* I2C_E_SDA */ + +/* P3 IT83XX_I2C_CH_D */ +GPIO(USBC_TCPC_I2C_CLK_P3, PIN(H, 1), GPIO_INPUT) /* I2C_D_SCL */ +GPIO(USBC_TCPC_I2C_DATA_P3, PIN(H, 2), GPIO_INPUT) /* I2C_D_SDA */ + +/* Unused 1.8V or 3.3V compatiable pins */ +GPIO(TP_DEVELOPER_MODE_EC, PIN(B, 2), GPIO_INPUT) +GPIO(ESPI_CS1_N_R, PIN(D, 3), GPIO_INPUT) +GPIO(SUSWARN, PIN(E, 1), GPIO_INPUT) +GPIO(CPU_C10_GATE, PIN(G, 1), GPIO_INPUT) +GPIO(TP_GPIO_G2, PIN(G, 2), GPIO_INPUT) +GPIO(TP_GPIO_G6, PIN(G, 6), GPIO_INPUT) +GPIO(BATT_DISABLE_EC, PIN(H, 0), GPIO_INPUT) +GPIO(ME_G3_TO_M3_EC, PIN(H, 5), GPIO_INPUT) +GPIO(SLP_S0_CS_EC, PIN(I, 0), GPIO_INPUT) +GPIO(SMC_SHUTDOWN, PIN(K, 5), GPIO_INPUT) +GPIO(CPU_CAT_ERR_MECC, PIN(L, 1), GPIO_INPUT) +GPIO(SMC_ONOFF_N, PIN(L, 3), GPIO_INPUT) /* Power button interrupt without H1 */ +GPIO(STD_ADPT_CNTRL_EC, PIN(L, 5), GPIO_INPUT) +GPIO(SMB_PCH_ALRT, PIN(L, 7), GPIO_INPUT) +GPIO(ESPI_ALERT0_R, PIN(M, 6), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Unused 3.3V compatiable pins */ +GPIO(TP_GPIO_A0, PIN(A, 0), GPIO_INPUT) +GPIO(TP_GPIO_A1, PIN(A, 1), GPIO_INPUT) +GPIO(TP_GPIO_A3, PIN(A, 3), GPIO_INPUT) +GPIO(TP_GPC3, PIN(C, 3), GPIO_INPUT) +GPIO(TP_GPC5, PIN(C, 5), GPIO_INPUT) +GPIO(TP_GPIO_E3, PIN(E, 3), GPIO_INPUT) +GPIO(TP_GPIO_H3, PIN(H, 3), GPIO_INPUT) +GPIO(TP_GPIO_H4, PIN(H, 4), GPIO_INPUT) + +/* Alternate pins for I2C */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C F SCL/SDA A4/A5 */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C A SCL/SDA B3/B4 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C B SCL/SDA C1/C2 */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C E SCL/SDA E0/E7 */ +ALTERNATE(PIN_MASK(C, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C C SCL C7 */ +ALTERNATE(PIN_MASK(F, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C C SDA F7 */ +ALTERNATE(PIN_MASK(H, BIT(1) | BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C D SCL/SDA H1/H2 */ + +/* Alternate pins for UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), GPIO_ALT_FUNC_DEFAULT, MODULE_UART, GPIO_FLAG_NONE) /* UART1 B0/B1 */ + +/* Alternate pins for ADC */ +ALTERNATE(PIN_MASK(I, BIT(1) | BIT(6)), GPIO_ALT_FUNC_DEFAULT, MODULE_ADC, GPIO_FLAG_NONE) /* ADC 1,6 -> I1,I6 */ +ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_ADC, GPIO_FLAG_NONE) /* ADC 13,15 -> L0,L2 */ + +/* Alternate pins for FAN */ +ALTERNATE(PIN_MASK(A, BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_PWM, GPIO_FLAG_NONE) /* PWM2 A2 */ +ALTERNATE(PIN_MASK(D, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_PWM, GPIO_FLAG_NONE) /* TACH1A D7 */ diff --git a/board/adlrvpp_ite/vif_override.xml b/board/adlrvpp_ite/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/adlrvpp_ite/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/adlrvpp_mchp1521/board.c b/board/adlrvpp_mchp1521/board.c new file mode 100644 index 0000000000..0ec53d1eb5 --- /dev/null +++ b/board/adlrvpp_mchp1521/board.c @@ -0,0 +1,111 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADLRVP-P-DDR4-MEC1521 board-specific configuration */ + +#include "button.h" +#include "fan.h" +#include "fusb302.h" +#include "gpio.h" +#include "i2c.h" +#include "i2c_bitbang.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "pca9675.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "spi_chip.h" +#include "switch.h" +#include "tablet_mode.h" +#include "timer.h" +#include "uart.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + /* + * Port-80 Display, Charger, Battery, IO-expander, EEPROM, + * ISH sensor, AUX-rail, power-monitor. + */ + [I2C_CHAN_BATT_CHG] = { + .name = "batt_chg", + .port = I2C_PORT_CHARGER, + .kbps = 100, + .scl = GPIO_SMB_BS_CLK, + .sda = GPIO_SMB_BS_DATA, + }, + [I2C_CHAN_TCPC_0] = { + .name = "typec_0", + .port = I2C_PORT_TYPEC_0, + .kbps = 400, + .scl = GPIO_TYPEC_EC_SMBUS1_CLK_EC, + .sda = GPIO_TYPEC_EC_SMBUS1_DATA_EC, + }, + [I2C_CHAN_TCPC_1] = { + .name = "typec_1", + .port = I2C_PORT_TYPEC_1, + .kbps = 400, + .scl = GPIO_TYPEC_EC_SMBUS3_CLK, + .sda = GPIO_TYPEC_EC_SMBUS3_DATA, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_ports) == I2C_CHAN_COUNT); +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct i2c_port_t i2c_bitbang_ports[] = { + [I2C_BITBANG_CHAN_BRD_ID] = { + .name = "bitbang_brd_id", + .port = I2C_PORT_CHARGER, + .kbps = 100, + .scl = GPIO_SMB_BS_CLK, + .sda = GPIO_SMB_BS_DATA, + .drv = &bitbang_drv, + }, + [I2C_BITBANG_CHAN_IOEX_0] = { + .name = "bitbang_ioex_0", + .port = I2C_PORT_TYPEC_0, + .kbps = 100, + .scl = GPIO_TYPEC_EC_SMBUS1_CLK_EC, + .sda = GPIO_TYPEC_EC_SMBUS1_DATA_EC, + .drv = &bitbang_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_bitbang_ports) == I2C_BITBANG_CHAN_COUNT); +const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); + +/* USB-C TCPC Configuration */ +const struct tcpc_config_t tcpc_config[] = { + [TYPE_C_PORT_0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_0, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, + [TYPE_C_PORT_1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_1, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == CONFIG_USB_PD_PORT_MAX_COUNT); + +/* SPI devices */ +const struct spi_device_t spi_devices[] = { + { QMSPI0_PORT, 4, GPIO_QMSPI_CS0 }, +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); diff --git a/board/adlrvpp_mchp1521/board.h b/board/adlrvpp_mchp1521/board.h new file mode 100644 index 0000000000..645bfc0598 --- /dev/null +++ b/board/adlrvpp_mchp1521/board.h @@ -0,0 +1,159 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADLRVP-P-DDR4-MEC1521 board-specific configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Microchip EC variant */ +#define VARIANT_INTELRVP_EC_MCHP + +/* UART for EC console */ +#undef CONFIG_UART_CONSOLE +#define CONFIG_UART_CONSOLE 2 + +#include "adlrvp.h" + +#undef CONFIG_CMD_ADC +#undef CONFIG_CMD_APTHROTTLE +#undef CONFIG_CMD_BATTFAKE +#undef CONFIG_CMD_GETTIME + +/* Enable LTO */ +#define CONFIG_LTO + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +/* Power sequencing */ +#define GPIO_EC_SPI_OE_N GPIO_EC_PCH_SPI_OE_N +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_ALL_SYS_PWRGD +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_PWRGD_EC_N +#define GPIO_PCH_SLP_S0_L GPIO_PM_SLP_S0_R_N +#define GPIO_PG_EC_DSW_PWROK GPIO_EC_TRACE_DATA_2 +#define GPIO_VCCST_PWRGD GPIO_EC_TRACE_DATA_3 +#define GPIO_SLP_SUS_L GPIO_PM_SLP_SUS_N +#define GPIO_SYS_RESET_L GPIO_DG2_PRESENT +#define GPIO_PCH_RSMRST_L GPIO_PM_RSMRST_R +#define GPIO_PCH_PWRBTN_L GPIO_PM_PWRBTN_N_R +#define GPIO_EN_PP3300_A GPIO_EC_DS3_R +#define GPIO_SYS_PWROK_EC GPIO_SYS_PWROK_EC_R +#define GPIO_PCH_DSW_PWROK GPIO_EC_TRACE_DATA_1 + +/* Buttons */ +#define GPIO_LID_OPEN GPIO_SMC_LID +#define GPIO_VOLUME_UP_L GPIO_VOL_UP_EC +#define GPIO_VOLUME_DOWN_L GPIO_VOL_DOWN_EC +#define GPIO_POWER_BUTTON_L GPIO_PWRBTN_EC_IN_N + +/* Sensors */ +#define GPIO_TABLET_MODE_L GPIO_EC_SLATEMODE_HALLOUT_SNSR_R +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_EC_R + +/* AC & Battery */ +#define GPIO_DC_JACK_PRESENT GPIO_STD_ADP_PRSNT_EC +#define GPIO_AC_PRESENT GPIO_BC_ACOK_EC_IN +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_BATT_ID_R + +/* eSPI/Host communication */ +#define GPIO_ESPI_RESET_L GPIO_ESPI_RST_EC_R_N +#define GPIO_PCH_WAKE_L GPIO_SMC_WAKE_SCI_N +#define GPIO_EC_INT_L GPIO_EC_TRACE_DATA_0 + +/* H1 */ +#define GPIO_WP_L GPIO_EC_WAKE_CLK_R +#define GPIO_PACKET_MODE_EN GPIO_EC_TRACE_CLK +#define GPIO_ENTERING_RW GPIO_DNX_FORCE_RELOAD_EC_R + +/* FAN */ +#define GPIO_FAN_POWER_EN GPIO_FAN_PWR_DISABLE + +/* LEDs */ +#define GPIO_BAT_LED_RED_L GPIO_PM_BAT_STATUS_LED2 +#define GPIO_PWR_LED_WHITE_L GPIO_PM_PWRBTN_LED + +/* Uart */ +#define GPIO_UART2_RX GPIO_EC_UART_RX + +/* Case Closed Debug Mode interrupt */ +#define GPIO_CCD_MODE_ODL GPIO_KBC_NUMLOCK + +/* USB-C interrupts */ +#define GPIO_USBC_TCPC_ALRT_P0 GPIO_TYPEC_EC_SMBUS_ALERT_0_R +#define GPIO_USBC_TCPC_ALRT_P1 GPIO_TYPEC_EC_SMBUS_ALERT_1_R +#define GPIO_USBC_TCPC_PPC_ALRT_P0 GPIO_KBC_SCANOUT_15 +#define GPIO_USBC_TCPC_PPC_ALRT_P1 GPIO_KBC_CAPSLOCK + +/* I2C ports & Configs */ +/* Charger */ +#define I2C_PORT_CHARGER MCHP_I2C_PORT0 +/* Port 80 */ +#define I2C_PORT_PORT80 MCHP_I2C_PORT0 +/* Board ID */ +#define I2C_PORT_PCA9555_BOARD_ID_GPIO MCHP_I2C_PORT0 +/* Battery */ +#define I2C_PORT_BATTERY MCHP_I2C_PORT0 +/* USB-C I2C */ +#define I2C_PORT_TYPEC_0 MCHP_I2C_PORT1 +#define I2C_PORT_TYPEC_1 MCHP_I2C_PORT5 + +/* + * MEC1521H loads firmware using QMSPI controller + * CONFIG_SPI_FLASH_PORT is the index into + * spi_devices[] in board.c + */ +#define CONFIG_SPI_FLASH_PORT 0 +#define CONFIG_SPI_FLASH + +/* + * ADLRVP uses 32MB SPI flash- W25R256JVEIQ.But, EC binary to be generated + * is of size 512KB. This bin is then later appended with 0xFF to become 32MB + * binary for flashing purpose. + */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) +#define CONFIG_SPI_FLASH_W25X40 /* TODO: change to W25R256 */ + +/* ADC channels */ +/* + * Undefining below and redefining based on ADL RVP schematics, + * as they are already defined with different channels in mchp_ec.h. + */ +#undef ADC_TEMP_SNS_AMBIENT_CHANNEL +#undef ADC_TEMP_SNS_VR_CHANNEL +#undef ADC_TEMP_SNS_DDR_CHANNEL +#undef ADC_TEMP_SNS_SKIN_CHANNEL + +#define ADC_TEMP_SNS_AMBIENT_CHANNEL CHIP_ADC_CH4 +#define ADC_TEMP_SNS_VR_CHANNEL CHIP_ADC_CH5 +#define ADC_TEMP_SNS_DDR_CHANNEL CHIP_ADC_CH6 +#define ADC_TEMP_SNS_SKIN_CHANNEL CHIP_ADC_CH7 + +/* To do: Remove once fan register details are added in mchp/fan.c */ +#undef CONFIG_FANS + +/* Use internal silicon 32KHz oscillator */ +#undef CONFIG_CLOCK_SRC_EXTERNAL + +/* Free up flash space. */ +#undef CONFIG_CONSOLE_CMDHELP + +#ifndef __ASSEMBLER__ + +enum adlrvp_i2c_channel { + I2C_CHAN_BATT_CHG, + I2C_CHAN_TCPC_0, + I2C_CHAN_TCPC_1, + I2C_CHAN_COUNT, +}; + +/* Map I2C port to controller */ +int board_i2c_p2c(int port); +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/adlrvpp_mchp1521/build.mk b/board/adlrvpp_mchp1521/build.mk new file mode 100644 index 0000000000..5bc76c4429 --- /dev/null +++ b/board/adlrvpp_mchp1521/build.mk @@ -0,0 +1,18 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Intel ADLRVP-P-DDR4-MEC1521 board-specific configuration +# + +# the IC is Microchip MEC1521 with SRAM of 256KB +# external SPI is 32MB +# external clock is crystal +CHIP:=mchp +CHIP_FAMILY:=mec152x +CHIP_VARIANT:=mec1521 +CHIP_SPI_SIZE_KB:=512 +BASEBOARD:=intelrvp + +board-y=board.o diff --git a/board/adlrvpp_mchp1521/ec.tasklist b/board/adlrvpp_mchp1521/ec.tasklist new file mode 100644 index 0000000000..0019755448 --- /dev/null +++ b/board/adlrvpp_mchp1521/ec.tasklist @@ -0,0 +1,25 @@ +/* + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Intel ADLRVP-P-DDR4-MEC1521 board-specific configuration. + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, VENTI_TASK_STACK_SIZE) diff --git a/board/adlrvpp_mchp1521/gpio.inc b/board/adlrvpp_mchp1521/gpio.inc new file mode 100644 index 0000000000..848253fa17 --- /dev/null +++ b/board/adlrvpp_mchp1521/gpio.inc @@ -0,0 +1,314 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADLRVP-P-DDR4-MEC1521 board-specific configuration. */ + +/* + * MEC152X data sheets GPIO numbers are OCTAL. + */ + +/* + * MEC1521H-SZ MECC board SPI flash is connected to MEC1521H-SZ shared SPI port. + * GPIO055/SHD_CS0# pin is used to determine the boot source (eSPI Flash channel + * or shared SPI). On RVP, SHD_CS0_N is connected to Flash0 and SHD_CS1_N is + * connected to Flash1. Based on RVP design, Flash1 is meant for EC & Flash0 + * for Coreboot.But, for MEC, it is mandatory to route CS0 to external Flash + * for EC to boot load the image. Hence, necessary rework must be taken care to + * route CS0 to external Flash1. + */ +/* Include common gpios needed for LFW loader and main process FW */ +#include "chip/mchp/lfw/gpio.inc" + +#include "baseboard/intelrvp/adlrvp_ioex_gpio.inc" + +/* As all signal names used here are supposed to match the schematic, + * few pin names may not indicate the real purpose.Refer comments to clarify the pin usage. + * Such pins are further renamed in board.h. + */ + +/* Power sequencing interrupts */ +GPIO_INT(ALL_SYS_PWRGD, PIN(057), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_EC_N, PIN(012), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PM_SLP_S0_R_N, PIN(0243), GPIO_INT_BOTH, power_signal_interrupt) +/* Below meaningless pin names are to match the schematic.*/ +/* PG_EC_DSW_PWROK signal */ +GPIO_INT(EC_TRACE_DATA_2, PIN(0202), GPIO_INT_BOTH, power_signal_interrupt) +/* VCCST_PWRGD signal */ +GPIO_INT(EC_TRACE_DATA_3, PIN(0203), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PM_SLP_SUS_N, PIN(000), GPIO_INT_BOTH, power_signal_interrupt) + +/* Button interrupts */ +GPIO_INT(VOL_UP_EC, PIN(0242), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOL_DOWN_EC, PIN(0246), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(SMC_LID, PIN(033), GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) +/* Buffered power button input from + * PMIC-SLG7NT4192VTR / PWRBTN_EC_SILEGO_OUTPUT */ +GPIO_INT(PWRBTN_EC_IN_N, PIN(0163), GPIO_INT_BOTH, power_button_interrupt) + +/* DC Jack presence coming from +VADP_OUT */ +/* DC_JACK_PRESENT */ +GPIO_INT(STD_ADP_PRSNT_EC, PIN(052), GPIO_INT_BOTH, board_dc_jack_interrupt) +/* AC Present */ +GPIO_INT(BC_ACOK_EC_IN, PIN(0172), GPIO_INT_BOTH, extpower_interrupt) + +/* H1 */ +/* WP_L interrupt pin */ +GPIO_INT(EC_WAKE_CLK_R, PIN(0241), GPIO_INT_BOTH, switch_interrupt) + +/* Case Closed Debug Mode */ +/* CCD_MODE_ODL pin */ +GPIO_INT(KBC_NUMLOCK, PIN(0255), GPIO_INT_BOTH, board_connect_c0_sbu) + +/* USB-C interrupts */ +/* Below meaningless pin names are to match the schematic */ +/* TCPC & PPC Alerts */ +/* USBC_TCPC_ALRT_P0 */ +GPIO_INT(TYPEC_EC_SMBUS_ALERT_0_R, PIN(0132), GPIO_INT_BOTH, tcpc_alert_event) +/* USBC_TCPC_ALRT_P1 */ +GPIO_INT(TYPEC_EC_SMBUS_ALERT_1_R, PIN(0245), GPIO_INT_BOTH, tcpc_alert_event) +/* USBC_TCPC_PPC_ALRT_P0 */ +GPIO_INT(KBC_SCANOUT_15, PIN(0151), GPIO_INT_BOTH, ppc_interrupt) +/* USBC_TCPC_PPC_ALRT_P1 */ +GPIO_INT(KBC_CAPSLOCK, PIN(0127), GPIO_INT_BOTH, ppc_interrupt) + +/* Sensor Interrupts */ +/* GPIO_TABLET_MODE_L */ +GPIO_INT(EC_SLATEMODE_HALLOUT_SNSR_R, PIN(064), GPIO_INT_BOTH | + GPIO_SEL_1P8V, gmr_tablet_switch_isr) + +/* UART Interrupt */ +GPIO_INT(EC_UART_RX, PIN(0145), GPIO_INT_BOTH_DSLEEP | GPIO_PULL_UP, + uart_deepsleep_interrupt) + +/* Power sequencing GPIOs */ +GPIO(PM_RSMRST_R, PIN(054), GPIO_OUT_LOW) +GPIO(PM_PWRBTN_N_R, PIN(0101), GPIO_ODR_HIGH) +GPIO(EC_PCH_SPI_OE_N, PIN(024), GPIO_OUT_LOW) +GPIO(SYS_PWROK_EC_R, PIN(043), GPIO_OUT_LOW) +/* Below names are meaningless to match schematic */ +/* PCH_DSW_PWROK */ +GPIO(EC_TRACE_DATA_1, PIN(0201), GPIO_OUT_LOW) +/* SYS_RESET_L */ +GPIO(DG2_PRESENT, PIN(0165), GPIO_ODR_HIGH) +/* EN_PP3300_A */ +GPIO(EC_DS3_R, PIN(0226), GPIO_OUT_LOW) +/* PCH_PWROK_EC is an input, as it is driven by the Silego chip on RVP */ +GPIO(EC_PM_PCH_PWROK, PIN(0106), GPIO_INPUT) +UNIMPLEMENTED(EN_PP5000) + +/* Host communication GPIOs */ +/* PCH_WAKE_L pin*/ +GPIO(SMC_WAKE_SCI_N, PIN(0114), GPIO_ODR_HIGH) +/* EC_INT_L pin */ +GPIO(EC_TRACE_DATA_0, PIN(0200), GPIO_ODR_HIGH) +#ifndef CONFIG_HOST_INTERFACE_ESPI +GPIO(ESPI_RST_EC_R_N, PIN(061), GPIO_INPUT) +#endif + +/* H1 Pins */ +/* PACKET_MODE_EN */ +GPIO(EC_TRACE_CLK, PIN(0105), GPIO_OUT_LOW) +/* ENTERING_RW */ +GPIO(DNX_FORCE_RELOAD_EC_R, PIN(0115), GPIO_OUT_LOW) + +/* FAN control pins */ +GPIO(FAN_PWR_DISABLE, PIN(060), GPIO_OUT_LOW) + +/* EDP */ +GPIO(EC_EDP1_BKLT_EN, PIN(0157), GPIO_OUT_HIGH) + +/* LEDs */ +GPIO(PM_BAT_STATUS_LED2, PIN(035), GPIO_OUT_LOW) +GPIO(PM_PWRBTN_LED, PIN(0254), GPIO_OUT_LOW) + +/* Battery present */ +GPIO(BATT_ID_R, PIN(0162), GPIO_INPUT) + +/* VTR2 STRAP PIN - GPIO0104_UART0_TX + * Voltage level strap used to determine, + * if shared flash interface must be configured + * for 3.3V or 1.8V. + * 1 = 3.3V operation + * 0 = 1.8V operation + */ +GPIO(EC_VTR2_STRAP, PIN(0104), GPIO_INPUT) + +/* Tap Controller select strap - GPIO0170_UART1_TX + * If any of the JTAG TAP controllers are used, GPIO170 must only + * be configured as an output to a VTRx powered external function. + * GPIO170 may only be configured as an input when + * the JTAG TAP controllers are not needed or when an external driver + * does not violate the Slave Select Timing. + */ +GPIO(EC_JTAG_STRAP, PIN(0170), GPIO_ODR_HIGH) + +/* I2C pins */ +/* I2C pins should be configure as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(SMB_BS_CLK, PIN(004), GPIO_INPUT) +GPIO(SMB_BS_DATA, PIN(003), GPIO_INPUT) +GPIO(TYPEC_EC_SMBUS1_CLK_EC, PIN(0131), GPIO_INPUT) +GPIO(TYPEC_EC_SMBUS1_DATA_EC, PIN(0130), GPIO_INPUT) +GPIO(TYPEC_EC_SMBUS3_DATA, PIN(0142), GPIO_INPUT) +GPIO(TYPEC_EC_SMBUS3_CLK, PIN(0141), GPIO_INPUT) + +/* Unused Pins */ +/* These have different meaning on RVP for alternate OS + * support.Hence, keep them as input. + */ +GPIO(PROCHOT_EC_R, PIN(0253), GPIO_INPUT) +GPIO(BC_PROCHOT_EC_N, PIN(034), GPIO_INPUT) +GPIO(EC_PEG_PLI_N_DG2, PIN(036), GPIO_INPUT) +GPIO(PEG_PIM_DG2, PIN(0240), GPIO_INPUT) +GPIO(KBD_BKLT_CTRL, PIN(014), GPIO_INPUT) +GPIO(STD_ADPT_CNTRL_GPIO_R, PIN(0171), GPIO_INPUT) +GPIO(SAF_G3_DETECT, PIN(013), GPIO_INPUT) +GPIO(EC_GPIO015_PWM7, PIN(015), GPIO_INPUT) +GPIO(EC_GPPC_B14, PIN(0244), GPIO_INPUT) +GPIO(SX_EXIT_HOLDOFF_N, PIN(0175), GPIO_INPUT) +GPIO(MIC_PRIVACY_EC, PIN(0100), GPIO_INPUT) +GPIO(MIC_PRIVACY_SWITCH, PIN(011), GPIO_INPUT) +GPIO(PECI_MUX_CTRL_ER_INT, PIN(025), GPIO_INPUT) +GPIO(PEG_RTD3_COLD_MOD_SW_R, PIN(0156), GPIO_INPUT) +GPIO(H_CATERR_EC_N, PIN(0153), GPIO_INPUT) +GPIO(PM_BATLOW_N, PIN(0140), GPIO_INPUT) +GPIO(HOME_BTN_EC_RVP_AEP_ID, PIN(023), GPIO_INPUT) +GPIO(CPU_C10_GATE_N_R, PIN(022), GPIO_INPUT) +GPIO(VREF_VTT, PIN(044), GPIO_INPUT) +GPIO(HB_NVDC_SEL, PIN(0161), GPIO_INPUT) +GPIO(EC_VCI_OUT_WAKE_R, PIN(0250), GPIO_INPUT) +GPIO(PM_SLP_S0_CS_N, PIN(0221), GPIO_INPUT) +GPIO(GPPC_E7_EC_SMI_N_R, PIN(0102), GPIO_INPUT) +GPIO(TC_RETIMER_FORCE_PWR_BTP_EC_R, PIN(0222), GPIO_INPUT) + +/* Alternate functions */ + +/* Alternate functions GPIO definitions */ + +/* + * MCHP has 6 banks/ports each containing 32 GPIO's. + * Each bank/port is connected to a GIRQ. + * Port numbering Example: + * GPIO_015 = 13 decimal. Port/bank = 13/32 = 0, bit = 13 % 32 = 13 + * GPIO_0123 = 83 decimal. Port/bank = 83/32 = 2, bit = 83 % 32 = 19 + * OR port = 0123 >> 5, bit = 0123 & 037(0x1F) = 023 = 19 decimal. + */ + +/* + * Configure I2C as alternate function + * I2C00_SDA = GPIO_0003(Bank=0, bit=3) Func1 + * I2C00_SCL = GPIO_0004(Bank=0, bit=4) Func1 + * I2C01_SDA = GPIO_0130(Bank=2, bit=24) Func1 + * I2C01_SCL = GPIO_0131(Bank=2, bit=25) Func1 + * I2C04_SDA = GPIO_0143(Bank=3, bit=3) Func1 + * I2C04_SCL = GPIO_0144(Bank=3, bit=4) Func1 + * I2C05_SDA = GPIO_0141(Bank=3, bit=1) Func1 + * I2C05_SDL = GPIO_0142(Bank=3, bit=2) Func1 + */ +ALTERNATE(PIN_MASK(0, 0x00000018), GPIO_ALT_FUNC_1, MODULE_I2C, + GPIO_ODR_HIGH) +ALTERNATE(PIN_MASK(2, 0x03000000), GPIO_ALT_FUNC_1, MODULE_I2C, + GPIO_ODR_HIGH) +ALTERNATE(PIN_MASK(3, 0x0000001E), GPIO_ALT_FUNC_1, MODULE_I2C, + GPIO_ODR_HIGH) + +/* Alternate pins for ADC */ +/* + * ADC04 - ADC07 + * GPIO_0204 Func 1 = ADC04 - AMBIET_THERM_IN0 + * GPIO_0205 Func 1 = ADC05 - VR_THERM_IN + * GPIO_0206 Func 1 = ADC06 - DDR_THERM_IN + * GPIO_0207 Func 1 = ADC07 - SKIN_THERM_IN1 + * Bank 4 bits[4:5:6:7] + */ +ALTERNATE(PIN_MASK(4, 0x00000F0), GPIO_ALT_FUNC_1, MODULE_ADC, + GPIO_ANALOG) +/* + * VREF2_ADC_R + * GPIO_067 Func 1 = VREF2_ADC + * Bank 1 bit [23] + */ +ALTERNATE(PIN_MASK(1, 0x0800000), GPIO_ALT_FUNC_1, MODULE_ADC, + GPIO_ANALOG) + +/* Alternate pins for FAN */ +/* + * GPIO_050 Func 1 = TACH0 - CPU_TACHO_FAN + * GPIO_053 Func 1 = PWM0 - CPU_PWM_FAN + * Bank 1 bits[8:11] + */ +ALTERNATE(PIN_MASK(1, 0x0000900), GPIO_ALT_FUNC_1, MODULE_PWM, + GPIO_FLAG_NONE) + +/* KB pins */ +/* + * MEC1521H-SZ (144 pin package) + * KSO00 = GPIO_0040 Func2 bank 1 bit 0 + * KSO01 = GPIO_0045 Func1 bank 1 bit 5 + * KSO02 = GPIO_0046 Func1 bank 1 bit 6 + * KSO03 = GPIO_0047 Func1 bank 1 bit 7 + * KSO04 = GPIO_0107 Func2 bank 2 bit 7 + * KSO05 = GPIO_0112 Func1 bank 2 bit 10 + * KSO06 = GPIO_0113 Func1 bank 2 bit 11 + * KSO07 = GPIO_0120 Func1 bank 2 bit 16 + * KSO08 = GPIO_0121 Func2 bank 2 bit 17 + * KSO09 = GPIO_0122 Func2 bank 2 bit 18 + * KSO10 = GPIO_0123 Func2 bank 2 bit 19 + * KSO11 = GPIO_0124 Func2 bank 2 bit 20 + * KSO12 = GPIO_0125 Func2 bank 2 bit 21 + * For 8x16 test keyboard add KSO13 - KSO15 + * KSO13 = GPIO_0126 Func2 bank 2 bit 22 + * KSO14 = GPIO_0152 Func1 bank 3 bit 10 + * KSO15 = GPIO_0151 Func2 bank 3 bit 9 + * + * KSI0 = GPIO_0017 Func1 bank 0 bit 15 + * KSI1 = GPIO_0020 Func1 bank 0 bit 16 + * KSI2 = GPIO_0021 Func1 bank 0 bit 17 + * KSI3 = GPIO_0026 Func1 bank 0 bit 22 + * KSI4 = GPIO_0027 Func1 bank 0 bit 23 + * KSI5 = GPIO_0030 Func1 bank 0 bit 24 + * KSI6 = GPIO_0031 Func1 bank 0 bit 25 + * KSI7 = GPIO_0032 Func1 bank 0 bit 26 + */ +/* KSO 0 Bank 1, Func2, bit 0 */ +ALTERNATE(PIN_MASK(1, 0x01), 2, MODULE_KEYBOARD_SCAN, + GPIO_ODR_HIGH) + +#ifdef CONFIG_KEYBOARD_COL2_INVERTED +/* KSO 1-3 Bank 1, Func1, bits 5-7 */ +ALTERNATE(PIN_MASK(1, 0xA0), 1, MODULE_KEYBOARD_SCAN, + GPIO_ODR_HIGH) +GPIO(KBD_KSO2, PIN(046), GPIO_OUT_LOW) +#else +/* KSO 1-3 Bank 1, Func1, bits 5-7 */ +ALTERNATE(PIN_MASK(1, 0xE0), 1, MODULE_KEYBOARD_SCAN, + GPIO_ODR_HIGH) +#endif + +/* KSO 4, 8-12 Bank 2, Func2, bits 7, 17-21 */ +ALTERNATE(PIN_MASK(2, 0x003E0080), 2, MODULE_KEYBOARD_SCAN, + GPIO_ODR_HIGH) +/* KSO 5-7, Bank 2, Func1, bits 10-11, 16 */ +ALTERNATE(PIN_MASK(2, 0x00010C00), 1, MODULE_KEYBOARD_SCAN, + GPIO_ODR_HIGH) + +/* KSI 0-7, Bank 0, Func1, bit 15-17, 22-26 */ +ALTERNATE(PIN_MASK(0, 0x07C38000), 1, MODULE_KEYBOARD_SCAN, + (GPIO_INPUT | GPIO_PULL_UP)) + +/* + * ESPI_RST_EC_R_N# - GPIO_0061 Func 1, Bank 1 bit[17] + * ESPI_ALERT0_EC_R_N# - GPIO_0063 Func 1, Bank 1 bit[19] + * ESPI_CLK_EC_R - GPIO_0065 Func 1, Bank 1 bit[21] + * ESPI_CS0_EC_R_N# - GPIO_0066 Func 1, Bank 1 bit[22] + * ESPI_IO0_EC_R - GPIO_0070 Func 1, Bank 1 bit[24] + * ESPI_IO1_EC_R - GPIO_0071 Func 1, Bank 1 bit[25] + * ESPI_IO2_EC_R - GPIO_0072 Func 1, Bank 1 bit[26] + * ESPI_IO3_EC_R - GPIO_0073 Func 1, Bank 1 bit[27] + */ +ALTERNATE(PIN_MASK(1, 0x0F6A0000), 1, MODULE_LPC, GPIO_FLAG_NONE) diff --git a/board/adlrvpp_mchp1521/vif_override.xml b/board/adlrvpp_mchp1521/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/adlrvpp_mchp1521/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/adlrvpp_mchp1727/board.c b/board/adlrvpp_mchp1727/board.c new file mode 100644 index 0000000000..1d0189d90b --- /dev/null +++ b/board/adlrvpp_mchp1727/board.c @@ -0,0 +1,139 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADL-P-RVP-MCHP1727 board-specific configuration */ +#include "button.h" +#include "fusb302.h" +#include "i2c_bitbang.h" +#include "lid_switch.h" +#include "pca9675.h" +#include "power.h" +#include "power_button.h" +#include "spi.h" +#include "spi_chip.h" +#include "switch.h" +#include "tablet_mode.h" +#include "uart.h" +#include "usb_pd_tcpm.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + [I2C_CHAN_BATT_CHG] = { + .name = "batt_chg", + .port = I2C_PORT_CHARGER, + .kbps = 100, + .scl = GPIO_SMB_BS_CLK, + .sda = GPIO_SMB_BS_DATA, + }, + [I2C_CHAN_TYPEC_0] = { + .name = "typec_0", + .port = I2C_PORT_TYPEC_0, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P0, + .sda = GPIO_USBC_TCPC_I2C_DATA_P0, + }, + [I2C_CHAN_TYPEC_1] = { + .name = "typec_1", + .port = I2C_PORT_TYPEC_1, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P2, + .sda = GPIO_USBC_TCPC_I2C_DATA_P2, + }, +#if defined(HAS_TASK_PD_C2) + [I2C_CHAN_TYPEC_2] = { + .name = "typec_2", + .port = I2C_PORT_TYPEC_2, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P1, + .sda = GPIO_USBC_TCPC_I2C_DATA_P1, + }, + [I2C_CHAN_TYPEC_3] = { + .name = "typec_3", + .port = I2C_PORT_TYPEC_3, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P3, + .sda = GPIO_USBC_TCPC_I2C_DATA_P3, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_ports) == I2C_CHAN_COUNT); +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* I2C access in polling mode before task is initialized */ +#ifdef CONFIG_I2C_BITBANG +const struct i2c_port_t i2c_bitbang_ports[] = { + [I2C_BITBANG_CHAN_BRD_ID] = { + .name = "bitbang_brd_id", + .port = I2C_PORT_CHARGER, + .kbps = 100, + .scl = GPIO_SMB_BS_CLK, + .sda = GPIO_SMB_BS_DATA, + .drv = &bitbang_drv, + }, + [I2C_BITBANG_CHAN_IOEX_0] = { + .name = "bitbang_ioex_0", + .port = I2C_PORT_TYPEC_0, + .kbps = 100, + .scl = GPIO_USBC_TCPC_I2C_CLK_P0, + .sda = GPIO_USBC_TCPC_I2C_DATA_P0, + .drv = &bitbang_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_bitbang_ports) == I2C_BITBANG_CHAN_COUNT); +const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); +#endif + +/* USB-C TCPC Configuration */ +const struct tcpc_config_t tcpc_config[] = { + [TYPE_C_PORT_0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_0, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#if defined(HAS_TASK_PD_C1) + [TYPE_C_PORT_1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_1, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#endif +#if defined(HAS_TASK_PD_C2) + [TYPE_C_PORT_2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_2, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#endif +#if defined(HAS_TASK_PD_C3) + [TYPE_C_PORT_3] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_3, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == CONFIG_USB_PD_PORT_MAX_COUNT); + +/* SPI devices */ +const struct spi_device_t spi_devices[] = { + { QMSPI0_PORT, 4, GPIO_QMSPI_CS0 }, +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); diff --git a/board/adlrvpp_mchp1727/board.h b/board/adlrvpp_mchp1727/board.h new file mode 100644 index 0000000000..ad4d189b42 --- /dev/null +++ b/board/adlrvpp_mchp1727/board.h @@ -0,0 +1,161 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADL-P-RVP-MCHP1727 board-specific configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* MCHP EC variant */ +#define VARIANT_INTELRVP_EC_MCHP + +/* UART for EC console */ +#undef CONFIG_UART_CONSOLE +#define CONFIG_UART_CONSOLE 0 + +#include "adlrvp.h" + +/* Heavy I2C communication as POR, increase WDT expired time */ +#undef CONFIG_WATCHDOG_PERIOD_MS +#define CONFIG_WATCHDOG_PERIOD_MS 5000 + +/* + * External parallel crystal between XTAL1 and XTAL2 pins. + * #define CONFIG_CLOCK_SRC_EXTERNAL + * #define CONFIG_CLOCK_CRYSTAL + * External single ended 32KHz 50% duty cycle input clock. + * #define CONFIG_CLOCK_SRC_EXTERNAL + * #undef CONFIG_CLOCK_CRYSTAL + * Use internal silicon 32KHz oscillator + * #undef CONFIG_CLOCK_SRC_EXTERNAL + * CONFIG_CLOCK_CRYSTAL is a don't care + */ +#undef CONFIG_CLOCK_SRC_EXTERNAL + +/* MEC1727 integrated SPI chip 512KB SST25PF040C */ +#define CONFIG_SPI_FLASH_W25X40 + +/* + * Enable extra SPI flash and generic SPI + * commands via EC UART + */ +#define CONFIG_CMD_SPI_FLASH +#define CONFIG_CMD_SPI_XFER + +/* MEC172x does not apply GP-SPI controllers */ +#undef CONFIG_MCHP_GPSPI + +/* ADC channels */ +#undef ADC_TEMP_SNS_AMBIENT_CHANNEL +#undef ADC_TEMP_SNS_DDR_CHANNEL +#undef ADC_TEMP_SNS_SKIN_CHANNEL +#undef ADC_TEMP_SNS_VR_CHANNEL +#define ADC_TEMP_SNS_AMBIENT_CHANNEL CHIP_ADC_CH3 +#define ADC_TEMP_SNS_DDR_CHANNEL CHIP_ADC_CH5 +#define ADC_TEMP_SNS_SKIN_CHANNEL CHIP_ADC_CH4 +#define ADC_TEMP_SNS_VR_CHANNEL CHIP_ADC_CH0 + +/* + * ADC maximum voltage is a board level configuration. + * MEC172x ADC can use an external 3.0 or 3.3V reference with + * maximum values up to the reference voltage. + * The ADC maximum voltage depends upon the external reference + * voltage connected to MEC172x. + */ +#undef ADC_MAX_MVOLT +#define ADC_MAX_MVOLT 3300 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +/* Power sequencing */ +#define GPIO_EC_SPI_OE_N GPIO_EC_SPI_OE_MECC +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_ALL_SYS_PWRGD +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_PWRGD +#define GPIO_PCH_SLP_S0_L GPIO_PCH_SLP_S0_N +#define GPIO_PG_EC_DSW_PWROK GPIO_VCCPDSW_3P3 +#define GPIO_SLP_SUS_L GPIO_PM_SLP_SUS_EC_N +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_PCH_RSMRST_L GPIO_PM_RSMRST_N +#define GPIO_PCH_PWRBTN_L GPIO_PM_PWRBTN_N +#define GPIO_EN_PP3300_A GPIO_EC_DS3 +#define GPIO_SYS_PWROK_EC GPIO_SYS_PWROK +#define GPIO_PCH_DSW_PWROK GPIO_EC_DSW_PWROK + +/* Sensors */ +#define GPIO_TABLET_MODE_L GPIO_SLATE_MODE_INDICATION +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_EC_N + +/* Buttons */ +#define GPIO_LID_OPEN GPIO_SMC_LID +#define GPIO_VOLUME_UP_L GPIO_VOLUME_UP +#define GPIO_VOLUME_DOWN_L GPIO_VOL_DN_EC +#define GPIO_POWER_BUTTON_L GPIO_MECH_PWR_BTN_ODL + +/* H1 */ +#define GPIO_WP_L GPIO_EC_FLASH_WP_ODL +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW + +/* AC & Battery */ +#define GPIO_DC_JACK_PRESENT GPIO_STD_ADP_PRSNT +#define GPIO_AC_PRESENT GPIO_BC_ACOK +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_BAT_DET + +/* eSPI/Host communication */ +#define GPIO_ESPI_RESET_L GPIO_LPC_ESPI_RST_N +#define GPIO_PCH_WAKE_L GPIO_SMC_WAKE_SCI_N_MECC +#define GPIO_EC_INT_L GPIO_EC_PCH_MKBP_INT_ODL + +/* LED */ +#define GPIO_BAT_LED_RED_L GPIO_LED_1_L +#define GPIO_PWR_LED_WHITE_L GPIO_LED_2_L + +/* FAN */ +#define GPIO_FAN_POWER_EN GPIO_THERM_SEN_MECC + +/* Charger */ +#define I2C_PORT_CHARGER MCHP_I2C_PORT0 + +/* Battery */ +#define I2C_PORT_BATTERY MCHP_I2C_PORT0 + +/* Board ID */ +#define I2C_PORT_PCA9555_BOARD_ID_GPIO MCHP_I2C_PORT0 + +/* Port 80 */ +#define I2C_PORT_PORT80 MCHP_I2C_PORT0 + +/* USB-C I2C */ +#define I2C_PORT_TYPEC_0 MCHP_I2C_PORT6 +/* + * Note: I2C for Type-C Port-1 is swapped with Type-C Port-2 + * on the RVP to reduce BOM stuffing options. + */ +#define I2C_PORT_TYPEC_1 MCHP_I2C_PORT3 +#if defined(HAS_TASK_PD_C2) +#define I2C_PORT_TYPEC_2 MCHP_I2C_PORT7 +#define I2C_PORT_TYPEC_3 MCHP_I2C_PORT2 +#endif + +#ifndef __ASSEMBLER__ + +enum adlrvp_i2c_channel { + I2C_CHAN_BATT_CHG, + I2C_CHAN_TYPEC_0, + I2C_CHAN_TYPEC_1, +#if defined(HAS_TASK_PD_C2) + I2C_CHAN_TYPEC_2, + I2C_CHAN_TYPEC_3, +#endif + I2C_CHAN_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/adlrvpp_mchp1727/build.mk b/board/adlrvpp_mchp1727/build.mk new file mode 100644 index 0000000000..0527f50d24 --- /dev/null +++ b/board/adlrvpp_mchp1727/build.mk @@ -0,0 +1,20 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Intel ADL-P-RVP-MCHP1727 board-specific configuration +# + +# the IC is Microchip MEC172x 416 KB total SRAM +# MEC1723SZ variant is 144 pin, loads from external SPI flash +# MEC1727SZ variant is 144 pin, loads from 512KB internal SPI flash +# external SPI is 512KB +# clock is Internal ROSC +CHIP:=mchp +CHIP_FAMILY:=mec172x +CHIP_VARIANT:=mec1727sz +CHIP_SPI_SIZE_KB:=512 +BASEBOARD:=intelrvp + +board-y=board.o diff --git a/board/adlrvpp_mchp1727/ec.tasklist b/board/adlrvpp_mchp1727/ec.tasklist new file mode 100644 index 0000000000..3ae4784397 --- /dev/null +++ b/board/adlrvpp_mchp1727/ec.tasklist @@ -0,0 +1,25 @@ +/* + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Intel ADL-P-RVP-MCHP1727 board-specific configuration. + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/adlrvpp_mchp1727/gpio.inc b/board/adlrvpp_mchp1727/gpio.inc new file mode 100644 index 0000000000..582da4c46a --- /dev/null +++ b/board/adlrvpp_mchp1727/gpio.inc @@ -0,0 +1,262 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADL-P-RVP-MCHP1727 board-specific configuration */ + +#include "baseboard/intelrvp/adlrvp_ioex_gpio.inc" +/* include common gpio.inc under chip/mchp/lfw/... */ +#include "chip/mchp/lfw/gpio.inc" + +/* Power sequencing interrupts */ +GPIO_INT(ALL_SYS_PWRGD, PIN(057), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD, PIN(0221), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PCH_SLP_S0_N, PIN(0243), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCPDSW_3P3, PIN(0201), GPIO_INT_BOTH, power_signal_interrupt) +/* TODO: GPIO_INT(VCCST_PWRGD_MECC, PIN(0207), GPIO_INT_BOTH, power_signal_interrupt) */ +GPIO_INT(PM_SLP_SUS_EC_N, PIN(0227), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(PM_SLP_S3_N, PIN(0161), GPIO_INT_BOTH, power_signal_interrupt) +#else +GPIO(PM_SLP_S3_N, PIN(0161), GPIO_INPUT) +#endif +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +GPIO_INT(PM_SLP_S4_N, PIN(0162), GPIO_INT_BOTH, power_signal_interrupt) +#else +GPIO(PM_SLP_S4_N, PIN(0162), GPIO_INPUT) +#endif + +/* Button interrupts */ +GPIO_INT(VOLUME_UP, PIN(036), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOL_DN_EC, PIN(0254), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(SMC_LID, PIN(0226), GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) +GPIO_INT(MECH_PWR_BTN_ODL, PIN(0115), GPIO_INT_BOTH, power_button_interrupt) + +/* DC / AC interrupts, DC Jack presence coming from +VADP_OUT */ +GPIO_INT(STD_ADP_PRSNT, PIN(043), GPIO_INT_BOTH, board_dc_jack_interrupt) /* DC_JACK_PRESENT */ +GPIO_INT(BC_ACOK, PIN(0156), GPIO_INT_BOTH, extpower_interrupt) /* AC Present */ + +/* Sensor interrupt */ +GPIO_INT(SLATE_MODE_INDICATION, PIN(0222), GPIO_INT_BOTH, gmr_tablet_switch_isr) + +/* Flash WP interrupt */ +GPIO_INT(EC_FLASH_WP_ODL, PIN(014), GPIO_INT_BOTH, switch_interrupt) + +/* Case Closed Debug Mode interrupt */ +GPIO_INT(CCD_MODE_ODL, PIN(0175), GPIO_INT_BOTH, board_connect_c0_sbu) + +/* UART0 RX interrupt, RX input wake event */ +GPIO_INT(UART0_RX, PIN(0105), GPIO_INT_BOTH_DSLEEP | GPIO_PULL_UP, uart_deepsleep_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USBC_TCPC_ALRT_P0, PIN(0143), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USBC_TCPC_PPC_ALRT_P0, PIN(0240), GPIO_INT_BOTH, ppc_interrupt) + +#if defined(HAS_TASK_PD_C1) +GPIO_INT(USBC_TCPC_ALRT_P1, PIN(0241), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USBC_TCPC_PPC_ALRT_P1, PIN(0101), GPIO_INT_BOTH, ppc_interrupt) +#else +GPIO(USBC_TCPC_ALRT_P1, PIN(0241), GPIO_INPUT) +GPIO(USBC_TCPC_PPC_ALRT_P1, PIN(0101), GPIO_INPUT) +#endif + +#if defined(HAS_TASK_PD_C2) +/* w/o rework: USBC_TCPC_ALRT_P2 -> VCI_OVRD_IN */ +GPIO_INT(USBC_TCPC_ALRT_P2, PIN(0130), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USBC_TCPC_PPC_ALRT_P2, PIN(0144), GPIO_INT_BOTH, ppc_interrupt) +#else +GPIO(USBC_TCPC_ALRT_P2, PIN(0130), GPIO_INPUT) +GPIO(USBC_TCPC_PPC_ALRT_P2, PIN(0144), GPIO_INPUT) +#endif + +#if defined(HAS_TASK_PD_C3) +GPIO_INT(USBC_TCPC_ALRT_P3, PIN(0242), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USBC_TCPC_PPC_ALRT_P3, PIN(0142), GPIO_INT_BOTH, ppc_interrupt) +#else +GPIO(USBC_TCPC_ALRT_P3, PIN(0242), GPIO_INPUT) +GPIO(USBC_TCPC_PPC_ALRT_P3, PIN(0142), GPIO_INPUT) +#endif + +/* Host communication GPIOs */ +GPIO(SMC_WAKE_SCI_N_MECC, PIN(051), GPIO_ODR_HIGH) +GPIO(EC_PCH_MKBP_INT_ODL, PIN(0127), GPIO_ODR_HIGH) +#ifndef CONFIG_HOST_INTERFACE_ESPI +GPIO(LPC_ESPI_RST_N, PIN(061), GPIO_INPUT) +GPIO(PLT_RST_L, PIN(052), GPIO_INPUT) /* PCH_PLTRST_L */ +#endif + +/* Prochot GPIO */ +GPIO(PROCHOT_EC_N, PIN(002), GPIO_INPUT) + +/* Power sequencing GPIOs */ +GPIO(SYS_RST_ODL, PIN(060), GPIO_ODR_HIGH) +GPIO(PM_RSMRST_N, PIN(054), GPIO_OUT_LOW) +GPIO(PM_PWRBTN_N, PIN(016), GPIO_ODR_HIGH) +/* w/o rework: EC_SPI_OE_MECC -> BGPO0 */ +GPIO(EC_SPI_OE_MECC, PIN(042), GPIO_OUT_LOW) +/* w/o rework: EC_DS3 -> VCI_OUT2 */ +GPIO(EC_DS3, PIN(025), GPIO_OUT_LOW) +UNIMPLEMENTED(EN_PP5000) + +/* PCH_PWROK_EC is an input, as it's driven by the Silego chip on RVP */ +GPIO(PCH_PWROK_EC, PIN(0106), GPIO_INPUT) +GPIO(SYS_PWROK, PIN(0202), GPIO_OUT_LOW) +GPIO(EC_DSW_PWROK, PIN(034), GPIO_OUT_LOW) + +/* H1 GPIOs */ +GPIO(EC_H1_PACKET_MODE, PIN(035), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW, PIN(0102), GPIO_OUT_LOW) + +/* Battery present */ +GPIO(BAT_DET, PIN(0206), GPIO_INPUT) + +/* EDP */ +GPIO(EDP_BKLT_EN_MECC, PIN(022), GPIO_OUT_HIGH) + +/* LED */ +GPIO(LED_1_L, PIN(0157), GPIO_OUT_HIGH) +GPIO(LED_2_L, PIN(0153), GPIO_OUT_HIGH) + +/* FAN control pins */ +GPIO(THERM_SEN_MECC, PIN(0141), GPIO_OUT_LOW) + +/* + * I2C pins should be configure as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(SMB_BS_CLK, PIN(004), GPIO_INPUT) /* I2C00_SCL */ +GPIO(SMB_BS_DATA, PIN(003), GPIO_INPUT) /* I2C00_SDA */ +GPIO(USBC_TCPC_I2C_CLK_P0, PIN(0140), GPIO_INPUT) /* I2C06_SCL */ +GPIO(USBC_TCPC_I2C_DATA_P0, PIN(0132), GPIO_INPUT) /* I2C06_SDA */ +GPIO(USBC_TCPC_I2C_CLK_P1, PIN(013), GPIO_INPUT) /* I2C07_SCL */ +GPIO(USBC_TCPC_I2C_DATA_P1, PIN(012), GPIO_INPUT) /* I2C07_SDA */ +GPIO(USBC_TCPC_I2C_CLK_P2, PIN(010), GPIO_INPUT) /* I2C03_SCL */ +GPIO(USBC_TCPC_I2C_DATA_P2, PIN(007), GPIO_INPUT) /* I2C03_SDA */ +GPIO(USBC_TCPC_I2C_CLK_P3, PIN(0155), GPIO_INPUT) /* I2C02_SCL */ +GPIO(USBC_TCPC_I2C_DATA_P3, PIN(0154), GPIO_INPUT) /* I2C02_SDA */ + +/* Unused pins */ +GPIO(SML1_CLK_MECC, PIN(0131), GPIO_INPUT) +GPIO(CPU_CAT_ERR_MECC, PIN(000), GPIO_INPUT) +GPIO(ESPI_ALERT0_N, PIN(063), GPIO_INPUT) +GPIO(BATT_DISABLE_EC, PIN(067), GPIO_INPUT) +/* Unused: GPIO(SLP_S0_CS_N, PIN(nVCI_IN0), GPIO_INPUT) */ +GPIO(CPU_C10_GATE_MECC, PIN(023), GPIO_INPUT) +GPIO(SMC_SDOWN_MECC, PIN(0255), GPIO_INPUT) +GPIO(STD_ADPT_CNTRL_GPIO, PIN(0244), GPIO_INPUT) +GPIO(SMC_ONOFF_N, PIN(0114), GPIO_INPUT) /* Power button interrupt without H1 */ +GPIO(SUSWARN, PIN(024), GPIO_INPUT) +GPIO(ME_G3_TO_M3_EC, PIN(033), GPIO_INPUT) + +/* Alternate pins for I2C */ +/* I2C pins alternate functions for ports 0, 2-3, 6-7 + * Configure I2C ports as I2C alternate function. + * If board does not use external pull-ups then change GPIO flags + * to enable internal pull-ups. + * I2C00_SDA = GPIO_0003(Bank=0, bit=3) Func1 + * I2C00_SCL = GPIO_0004(Bank=0, bit=4) Func1 + * I2C02_SDA = GPIO_0154(Bank=3, bit=12) Func1 + * I2C02_SCL = GPIO_0155(Bank=3, bit=13) Func1 + * I2C03_SDA = GPIO_0007(Bank=0, bit=7) Func1 + * I2C03_SDL = GPIO_0010(Bank=0, bit=8) Func1 + * I2C06_SDA = GPIO_0132(Bank=2, bit=26) Func1 + * I2C06_SCL = GPIO_0140(Bank=3, bit=0) Func1 + * I2C07_SDA = GPIO_0012(Bank=0, bit=10) Func1 + * I2C07_SDL = GPIO_0013(Bank=0, bit=11) Func1 + */ +ALTERNATE(PIN_MASK(0, 0x00000D98), 1, MODULE_I2C, GPIO_ODR_HIGH) +ALTERNATE(PIN_MASK(2, 0x04000000), 1, MODULE_I2C, GPIO_ODR_HIGH) +ALTERNATE(PIN_MASK(3, 0x00003001), 1, MODULE_I2C, GPIO_ODR_HIGH) + +/* Alternate pins for ADC */ +/* VR_TMP/V_1P05 - GPIO44, SKIN_THERM_IN_EC - GPIO43, AMBIENT_TEMP - GPIO42, DDR_TEMP/EC_5V - GPIO41 */ +/* ADC pins + * GPIO200/ADC00 = VR_TMP/V_1P05 + * GPIO203/ADC03 = AMBIENT_TEMP + * GPIO204/ADC04 = SKIN_THERM_IN_EC + * GPIO205/ADC05 = DDR_TEMP/EC_5V + * ADC00 = GPIO_0200(Bank=4, bit=0) Func1 + * ADC03 = GPIO_0203(Bank=4, bit=3) Func1 + * ADC04 = GPIO_0204(Bank=4, bit=4) Func1 + * ADC05 = GPIO_0205(Bank=4, bit=5) Func1 + */ +ALTERNATE(PIN_MASK(4, 0x0039), 1, MODULE_ADC, GPIO_ANALOG) + +/* + * Alternate pins for RPM-FAN control + * + * GPIO050/GTACH0 = CPU_TACHO_FAN + * GPIO053/GPWM0 = CPU_PWM_FAN + * GTACH0 = GPIO_050(Bank=1, bit=8) Func2 + * GPWM0 = GPIO_053(Bank=1, bit=11) Func3 + */ +ALTERNATE(PIN_MASK(1, 0x0100), 2, MODULE_PWM, GPIO_FLAG_NONE) +ALTERNATE(PIN_MASK(1, 0x0800), 3, MODULE_PWM, GPIO_FLAG_NONE) + +/* Keyboard pins */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +#define GPIO_KB_OUTPUT (GPIO_ODR_HIGH) +#define GPIO_KB_OUTPUT_COL2 (GPIO_OUT_LOW) +/* + * MEC172xH-SZ (144 pin package) + * KSO00 = GPIO_0040 Func2 bank 1 bit 0 + * KSO01 = GPIO_0045 Func1 bank 1 bit 5 + * KSO02 = GPIO_0046 Func1 bank 1 bit 6 + * KSO03 = GPIO_0047 Func1 bank 1 bit 7 + * KSO04 = GPIO_0107 Func2 bank 2 bit 7 + * KSO05 = GPIO_0112 Func1 bank 2 bit 10 + * KSO06 = GPIO_0113 Func1 bank 2 bit 11 + * KSO07 = GPIO_0120 Func1 bank 2 bit 16 + * KSO08 = GPIO_0121 Func2 bank 2 bit 17 + * KSO09 = GPIO_0122 Func2 bank 2 bit 18 + * KSO10 = GPIO_0123 Func2 bank 2 bit 19 + * KSO11 = GPIO_0124 Func2 bank 2 bit 20 + * KSO12 = GPIO_0125 Func2 bank 2 bit 21 + * For 8x16 keyboard add KSO13 - KSO15 + * KSO13 = GPIO_0126 Func2 bank 2 bit 22 + * KSO14 = GPIO_0152 Func1 bank 3 bit 10 + * KSO15 = GPIO_0151 Func2 bank 3 bit 9 + * + * KSI0 = GPIO_0017 Func1 bank 0 bit 15 + * KSI1 = GPIO_0020 Func1 bank 0 bit 16 + * KSI2 = GPIO_0021 Func1 bank 0 bit 17 + * KSI3 = GPIO_0026 Func1 bank 0 bit 22 + * KSI4 = GPIO_0027 Func1 bank 0 bit 23 + * KSI5 = GPIO_0030 Func1 bank 0 bit 24 + * KSI6 = GPIO_0031 Func1 bank 0 bit 25 + * KSI7 = GPIO_0032 Func1 bank 0 bit 26 + */ +/* KSO 0 Bank 1, Func2, bit 0 */ +ALTERNATE(PIN_MASK(1, 0x01), 2, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) + +#ifdef CONFIG_KEYBOARD_COL2_INVERTED +/* KSO 1-3 Bank 1, Func1, bits 5-7 */ +ALTERNATE(PIN_MASK(1, 0xA0), 1, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) +GPIO(KBD_KSO2, PIN(046), GPIO_KB_OUTPUT_COL2) +#else +/* KSO 1-3 Bank 1, Func1, bits 5-7 */ +ALTERNATE(PIN_MASK(1, 0xE0), 1, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) +#endif + +/* KSO 4, 8-12 Bank 2, Func2, bits 7, 17-21 */ +ALTERNATE(PIN_MASK(2, 0x003E0080), 2, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) +/* KSO 5-7, Bank 2, Func1, bits 10-11, 16 */ +ALTERNATE(PIN_MASK(2, 0x00010C00), 1, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) + +/* KSI 0-7, Bank 0, Func1, bit 15-17, 22-26 */ +ALTERNATE(PIN_MASK(0, 0x07C38000), 1, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) + +/* + * ESPI_RESET# - GPIO_0061 Func 1, Bank 1 bit[17] + * ESPI_ALERT# - GPIO_0063 Func 1, Bank 1 bit[19] + * ESPI_CLK - GPIO_0065 Func 1, Bank 1 bit[21] + * ESPI_CS# - GPIO_0066 Func 1, Bank 1 bit[22] + * ESPI_IO0 - GPIO_0070 Func 1, Bank 1 bit[24] + * ESPI_IO1 - GPIO_0071 Func 1, Bank 1 bit[25] + * ESPI_IO2 - GPIO_0072 Func 1, Bank 1 bit[26] + * ESPI_IO3 - GPIO_0073 Func 1, Bank 1 bit[27] + */ +ALTERNATE(PIN_MASK(1, 0x0F6A0000), 1, MODULE_LPC, 0) diff --git a/board/adlrvpp_mchp1727/vif_override.xml b/board/adlrvpp_mchp1727/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/adlrvpp_mchp1727/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/adlrvpp_npcx/board.c b/board/adlrvpp_npcx/board.c new file mode 100644 index 0000000000..9736f81807 --- /dev/null +++ b/board/adlrvpp_npcx/board.c @@ -0,0 +1,128 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADLRVP-NPCX board-specific configuration */ +#include "button.h" +#include "fusb302.h" +#include "i2c_bitbang.h" +#include "lid_switch.h" +#include "pca9675.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "tablet_mode.h" +#include "uart.h" +#include "usb_pd_tcpm.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + [I2C_CHAN_BATT_CHG] = { + .name = "batt_chg", + .port = I2C_PORT_CHARGER, + .kbps = 100, + .scl = GPIO_SMB_BS_CLK, + .sda = GPIO_SMB_BS_DATA, + }, + [I2C_CHAN_TYPEC_0] = { + .name = "typec_0", + .port = I2C_PORT_TYPEC_0, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P0, + .sda = GPIO_USBC_TCPC_I2C_DATA_P0, + }, + [I2C_CHAN_TYPEC_1] = { + .name = "typec_1", + .port = I2C_PORT_TYPEC_1, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P2, + .sda = GPIO_USBC_TCPC_I2C_DATA_P2, + }, +#if defined(HAS_TASK_PD_C2) + [I2C_CHAN_TYPEC_2] = { + .name = "typec_2", + .port = I2C_PORT_TYPEC_2, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P1, + .sda = GPIO_USBC_TCPC_I2C_DATA_P1, + }, +#endif +#if defined(HAS_TASK_PD_C3) + [I2C_CHAN_TYPEC_3] = { + .name = "typec_3", + .port = I2C_PORT_TYPEC_3, + .kbps = 400, + .scl = GPIO_USBC_TCPC_I2C_CLK_P3, + .sda = GPIO_USBC_TCPC_I2C_DATA_P3, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_ports) == I2C_CHAN_COUNT); +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct i2c_port_t i2c_bitbang_ports[] = { + [I2C_BITBANG_CHAN_BRD_ID] = { + .name = "bitbang_brd_id", + .port = I2C_PORT_CHARGER, + .kbps = 100, + .scl = GPIO_SMB_BS_CLK, + .sda = GPIO_SMB_BS_DATA, + .drv = &bitbang_drv, + }, + [I2C_BITBANG_CHAN_IOEX_0] = { + .name = "bitbang_ioex_0", + .port = I2C_PORT_TYPEC_0, + .kbps = 100, + .scl = GPIO_USBC_TCPC_I2C_CLK_P0, + .sda = GPIO_USBC_TCPC_I2C_DATA_P0, + .drv = &bitbang_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_bitbang_ports) == I2C_BITBANG_CHAN_COUNT); +const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); + +/* USB-C TCPC Configuration */ +const struct tcpc_config_t tcpc_config[] = { + [TYPE_C_PORT_0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_0, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, + [TYPE_C_PORT_1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_1, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#if defined(HAS_TASK_PD_C2) + [TYPE_C_PORT_2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_2, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#endif +#if defined(HAS_TASK_PD_C3) + [TYPE_C_PORT_3] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TYPEC_3, + .addr_flags = I2C_ADDR_FUSB302_TCPC_AIC, + }, + .drv = &fusb302_tcpm_drv, + }, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == CONFIG_USB_PD_PORT_MAX_COUNT); diff --git a/board/adlrvpp_npcx/board.h b/board/adlrvpp_npcx/board.h new file mode 100644 index 0000000000..ff214ddec2 --- /dev/null +++ b/board/adlrvpp_npcx/board.h @@ -0,0 +1,112 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADL-P-RVP-NPCX board-specific configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* ITE EC variant */ +#define VARIANT_INTELRVP_EC_NPCX + +#include "adlrvp.h" + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +/* Power sequencing */ +#define GPIO_EC_SPI_OE_N GPIO_EC_SPI_OE_MECC +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_ALL_SYS_PWRGD +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_PWRGD +#define GPIO_PCH_SLP_S0_L GPIO_PCH_SLP_S0_N +#define GPIO_PG_EC_DSW_PWROK GPIO_VCCPDSW_3P3 +#define GPIO_SLP_SUS_L GPIO_PM_SLP_SUS_EC_N +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_PCH_RSMRST_L GPIO_PM_RSMRST_N +#define GPIO_PCH_PWRBTN_L GPIO_PM_PWRBTN_N +#define GPIO_EN_PP3300_A GPIO_EC_DS3 +#define GPIO_SYS_PWROK_EC GPIO_SYS_PWROK +#define GPIO_PCH_DSW_PWROK GPIO_EC_DSW_PWROK + +/* Sensors */ +#define GPIO_TABLET_MODE_L GPIO_SLATE_MODE_INDICATION +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_EC_N + +/* Buttons */ +#define GPIO_LID_OPEN GPIO_SMC_LID +#define GPIO_VOLUME_UP_L GPIO_VOLUME_UP +#define GPIO_VOLUME_DOWN_L GPIO_VOL_DN_EC +#define GPIO_POWER_BUTTON_L GPIO_MECH_PWR_BTN_ODL + +/* H1 */ +#define GPIO_WP_L GPIO_EC_FLASH_WP_ODL +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW + +/* AC & Battery */ +#define GPIO_DC_JACK_PRESENT GPIO_STD_ADP_PRSNT +#define GPIO_AC_PRESENT GPIO_BC_ACOK +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_BAT_DET + +/* eSPI/Host communication */ +#define GPIO_ESPI_RESET_L GPIO_LPC_ESPI_RST_N +#define GPIO_PCH_WAKE_L GPIO_SMC_WAKE_SCI_N_MECC +#define GPIO_EC_INT_L GPIO_EC_PCH_MKBP_INT_ODL + +/* LED */ +#define GPIO_BAT_LED_RED_L GPIO_LED_1_L +#define GPIO_PWR_LED_WHITE_L GPIO_LED_2_L + +/* FAN */ +#define GPIO_FAN_POWER_EN GPIO_THERM_SEN_MECC + +/* I2C ports & Configs */ +/* Charger */ +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 + +/* Battery */ +#define I2C_PORT_BATTERY NPCX_I2C_PORT7_0 + +/* Board ID */ +#define I2C_PORT_PCA9555_BOARD_ID_GPIO NPCX_I2C_PORT7_0 + +/* Port 80 */ +#define I2C_PORT_PORT80 NPCX_I2C_PORT7_0 + +/* USB-C I2C */ +#define I2C_PORT_TYPEC_0 NPCX_I2C_PORT0_0 +/* + * Note: I2C for Type-C Port-1 is swapped with Type-C Port-2 + * on the RVP to reduce BOM stuffing options. + */ +#define I2C_PORT_TYPEC_1 NPCX_I2C_PORT2_0 +#if defined(HAS_TASK_PD_C2) +#define I2C_PORT_TYPEC_2 NPCX_I2C_PORT1_0 +#endif +#if defined(HAS_TASK_PD_C3) +#define I2C_PORT_TYPEC_3 NPCX_I2C_PORT3_0 +#endif + +#ifndef __ASSEMBLER__ + +enum adlrvp_i2c_channel { + I2C_CHAN_BATT_CHG, + I2C_CHAN_TYPEC_0, + I2C_CHAN_TYPEC_1, +#if defined(HAS_TASK_PD_C2) + I2C_CHAN_TYPEC_2, +#endif +#if defined(HAS_TASK_PD_C3) + I2C_CHAN_TYPEC_3, +#endif + I2C_CHAN_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/adlrvpp_npcx/build.mk b/board/adlrvpp_npcx/build.mk new file mode 100644 index 0000000000..db43110a34 --- /dev/null +++ b/board/adlrvpp_npcx/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Intel ADL-P-RVP-NPCX board-specific configuration +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=intelrvp + +board-y=board.o diff --git a/board/adlrvpp_npcx/ec.tasklist b/board/adlrvpp_npcx/ec.tasklist new file mode 100644 index 0000000000..df3dc2c67d --- /dev/null +++ b/board/adlrvpp_npcx/ec.tasklist @@ -0,0 +1,29 @@ +/* + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Intel ADL-P-RVP-NPCX board-specific configuration. + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C2, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C3, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C2, pd_interrupt_handler_task, 2, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C3, pd_interrupt_handler_task, 3, ULTRA_TASK_STACK_SIZE) diff --git a/board/adlrvpp_npcx/gpio.inc b/board/adlrvpp_npcx/gpio.inc new file mode 100644 index 0000000000..ebc04045bf --- /dev/null +++ b/board/adlrvpp_npcx/gpio.inc @@ -0,0 +1,176 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Intel ADL-P-RVP-NPCX board-specific configuration */ + +#include "baseboard/intelrvp/adlrvp_ioex_gpio.inc" + +/* Power sequencing interrupts */ +GPIO_INT(ALL_SYS_PWRGD, PIN(7, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD, PIN(3, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PCH_SLP_S0_N, PIN(A, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCPDSW_3P3, PIN(4, 5), GPIO_INT_BOTH, power_signal_interrupt) +/* TODO: GPIO_INT(VCCST_PWRGD_MECC, PIN(7, 1), GPIO_INT_BOTH, power_signal_interrupt) */ +GPIO_INT(PM_SLP_SUS_EC_N, PIN(8, 6), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(PM_SLP_S3_N, PIN(B, 0), GPIO_INT_BOTH, power_signal_interrupt) +#else +GPIO(PM_SLP_S3_N, PIN(B, 0), GPIO_INPUT) +#endif +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +GPIO_INT(PM_SLP_S4_N, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +#else +GPIO(PM_SLP_S4_N, PIN(A, 5), GPIO_INPUT) +#endif + +/* Button interrupts */ +GPIO_INT(VOLUME_UP, PIN(6, 1), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOL_DN_EC, PIN(0, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(SMC_LID, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) +GPIO_INT(MECH_PWR_BTN_ODL, PIN(0, 0), GPIO_INT_BOTH, power_button_interrupt) + +/* DC Jack presence coming from +VADP_OUT */ +GPIO_INT(STD_ADP_PRSNT, PIN(0, 2), GPIO_INT_BOTH, board_dc_jack_interrupt) /* DC_JACK_PRESENT */ + +GPIO_INT(BC_ACOK, PIN(C, 6), GPIO_INT_BOTH, extpower_interrupt) /* AC Present */ + +/* USB-C interrupts */ +GPIO_INT(USBC_TCPC_ALRT_P0, PIN(4, 0), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USBC_TCPC_ALRT_P1, PIN(6, 2), GPIO_INT_BOTH, tcpc_alert_event) +#if defined(HAS_TASK_PD_C2) +GPIO_INT(USBC_TCPC_ALRT_P2, PIN(6, 3), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USBC_TCPC_ALRT_P3, PIN(6, 7), GPIO_INT_BOTH, tcpc_alert_event) +#else +GPIO(USBC_TCPC_ALRT_P2, PIN(6, 3), GPIO_INPUT) +GPIO(USBC_TCPC_ALRT_P3, PIN(6, 7), GPIO_INPUT) +#endif + +GPIO_INT(USBC_TCPC_PPC_ALRT_P0, PIN(F, 0), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USBC_TCPC_PPC_ALRT_P1, PIN(F, 1), GPIO_INT_BOTH, ppc_interrupt) +#if defined(HAS_TASK_PD_C2) +GPIO_INT(USBC_TCPC_PPC_ALRT_P2, PIN(F, 2), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USBC_TCPC_PPC_ALRT_P3, PIN(F, 3), GPIO_INT_BOTH, ppc_interrupt) +#else +GPIO(USBC_TCPC_PPC_ALRT_P2, PIN(F, 2), GPIO_INPUT) +GPIO(USBC_TCPC_PPC_ALRT_P3, PIN(F, 3), GPIO_INPUT) +#endif + +/* Host communication GPIOs */ +GPIO(SMC_WAKE_SCI_N_MECC, PIN(A, 4), GPIO_ODR_HIGH) +GPIO(EC_PCH_MKBP_INT_ODL, PIN(F, 5), GPIO_ODR_HIGH) +#ifndef CONFIG_HOST_INTERFACE_ESPI +GPIO(LPC_ESPI_RST_N, PIN(5, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(PLT_RST_L, PIN(A, 2), GPIO_INPUT | GPIO_SEL_1P8V) /* PCH_PLTRST_L */ +#endif + +/* Sensor Interrupts */ +GPIO_INT(SLATE_MODE_INDICATION, PIN(E, 5), GPIO_INT_BOTH | GPIO_SEL_1P8V, gmr_tablet_switch_isr) +GPIO(PROCHOT_EC_N, PIN(A, 7), GPIO_INPUT) + +/* Power sequencing GPIOs */ +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +/* GPIOD3 (Rework: CPU_TACHO_FAN is swapped with PM_RSMRST_N) */ +GPIO(PM_RSMRST_N, PIN(D, 3), GPIO_OUT_LOW) +GPIO(PM_PWRBTN_N, PIN(9, 7), GPIO_ODR_HIGH) +GPIO(EC_SPI_OE_MECC, PIN(6, 0), GPIO_OUT_LOW) +GPIO(EC_DS3, PIN(C, 4), GPIO_OUT_LOW) +UNIMPLEMENTED(EN_PP5000) + +/* PCH_PWROK_EC is an input, as it's driven by the Silego chip on RVP */ +GPIO(PCH_PWROK_EC, PIN(A, 0), GPIO_INPUT) +GPIO(SYS_PWROK, PIN(9, 3), GPIO_OUT_LOW) +GPIO(EC_DSW_PWROK, PIN(9, 5), GPIO_OUT_LOW) + +/* H1 pins */ +GPIO_INT(EC_FLASH_WP_ODL, PIN(9, 4), GPIO_INT_BOTH, switch_interrupt) +GPIO(EC_H1_PACKET_MODE, PIN(E, 2), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW, PIN(D, 4), GPIO_OUT_LOW) + +/* Case Closed Debug Mode */ +GPIO_INT(CCD_MODE_ODL, PIN(F, 4), GPIO_INT_BOTH, board_connect_c0_sbu) + +/* Battery present */ +GPIO(BAT_DET, PIN(7, 6), GPIO_INPUT) + +/* EDP */ +GPIO(EDP_BKLT_EN_MECC, PIN(E, 1), GPIO_OUT_HIGH) + +/* LED */ +GPIO(LED_1_L, PIN(B, 6), GPIO_OUT_HIGH) +GPIO(LED_2_L, PIN(B, 7), GPIO_OUT_HIGH) + +/* FAN control pins */ +GPIO(THERM_SEN_MECC, PIN(C, 0), GPIO_OUT_LOW) + +/* + * I2C pins should be configure as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(SMB_BS_CLK, PIN(B, 3), GPIO_INPUT) /* I2C7_SCL0 */ +GPIO(SMB_BS_DATA, PIN(B, 2), GPIO_INPUT) /* I2C7_SDA0 */ +GPIO(USBC_TCPC_I2C_CLK_P0, PIN(B, 5), GPIO_INPUT) /* I2C0_SCL0 */ +GPIO(USBC_TCPC_I2C_DATA_P0, PIN(B, 4), GPIO_INPUT) /* I2C0_SDA0 */ +GPIO(USBC_TCPC_I2C_CLK_P2, PIN(9, 2), GPIO_INPUT) /* I2C2_SCL0 */ +GPIO(USBC_TCPC_I2C_DATA_P2, PIN(9, 1), GPIO_INPUT) /* I2C2_SDA0 */ +GPIO(USBC_TCPC_I2C_CLK_P1, PIN(9, 0), GPIO_INPUT) /* I2C1_SCL0 */ +GPIO(USBC_TCPC_I2C_DATA_P1, PIN(8, 7), GPIO_INPUT) /* I2C1_SCL0 */ +GPIO(USBC_TCPC_I2C_CLK_P3, PIN(D, 1), GPIO_INPUT) /* I2C3_SCL0 */ +GPIO(USBC_TCPC_I2C_DATA_P3, PIN(D, 0), GPIO_INPUT) /* I2C3_SCL0 */ + +/* Unused pins */ +GPIO(SML1_CLK_MECC, PIN(3, 3), GPIO_INPUT) +GPIO(SML1_DATA_MECC, PIN(3, 6), GPIO_INPUT) +GPIO(SMB_PCH_CLK, PIN(C, 2), GPIO_INPUT) +GPIO(SMB_PCH_DATA, PIN(C, 1), GPIO_INPUT) +GPIO(I3C_0_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(I3C_0_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(CPU_CAT_ERR_MECC, PIN(3, 4), GPIO_INPUT) +GPIO(TP29, PIN(5, 0), GPIO_INPUT) +GPIO(TP28, PIN(5, 6), GPIO_INPUT) +GPIO(ESPI_ALERT0_N, PIN(5, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(BATT_DISABLE_EC, PIN(6, 6), GPIO_INPUT) +GPIO(TP33, PIN(7, 2), GPIO_INPUT) +GPIO(TP26, PIN(7, 3), GPIO_INPUT) +GPIO(SLP_S0_CS_N, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PECI, PIN(8, 1), GPIO_INPUT) +GPIO(CPU_C10_GATE_MECC, PIN(9, 6), GPIO_INPUT) +GPIO(SMB_PCH_ALRT, PIN(A, 3), GPIO_INPUT) +GPIO(SMC_SDOWN_MECC, PIN(B, 1), GPIO_INPUT) +GPIO(STD_ADPT_CNTRL_GPIO, PIN(C, 3), GPIO_INPUT) +GPIO(SML1_ALERT, PIN(C, 7), GPIO_INPUT) +GPIO(SMC_ONOFF_N, PIN(D, 2), GPIO_INPUT) /* Power button interrupt without H1 */ +GPIO(SUSWARN, PIN(D, 5), GPIO_INPUT) +GPIO(TP_GPIOD6_EC, PIN(D, 6), GPIO_INPUT) +GPIO(TP_GPIOD7_EC, PIN(D, 7), GPIO_INPUT) +GPIO(ME_G3_TO_M3_EC, PIN(E, 0), GPIO_INPUT) + +/* Alternate pins for I2C */ +ALTERNATE(PIN_MASK(8, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) +ALTERNATE(PIN_MASK(9, BIT(0) | BIT(1) | BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) +ALTERNATE(PIN_MASK(B, BIT(2) | BIT(3) | BIT(4) | BIT(5)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) +ALTERNATE(PIN_MASK(D, BIT(0) | BIT(1)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) + +/* Alternate pins for UART */ +ALTERNATE(PIN_MASK(6, BIT(4) | BIT(5)), GPIO_ALT_FUNC_DEFAULT, MODULE_UART, GPIO_PULL_UP) + +/* Alternate pins for ADC */ +/* VR_TMP/V_1P05 - GPIO44, SKIN_THERM_IN_EC - GPIO43, AMBIENT_TEMP - GPIO42, DDR_TEMP/EC_5V - GPIO41 */ +ALTERNATE(PIN_MASK(4, BIT(1) | BIT(2) | BIT(3) | BIT(4)), GPIO_ALT_FUNC_DEFAULT, MODULE_ADC, GPIO_FLAG_NONE) + +/* Alternate pins for FAN */ +ALTERNATE(PIN_MASK(8, BIT(0)), GPIO_ALT_FUNC_DEFAULT, MODULE_PWM, GPIO_FLAG_NONE) /* CPU_FAN_MECC GPIO80/PWM3_LED3 */ +/* GPIOA6 (Rework: CPU_TACHO_FAN is swapped with PM_RSMRST_N) */ +ALTERNATE(PIN_MASK(A, BIT(6)), GPIO_ALT_FUNC_DEFAULT, MODULE_PWM, GPIO_FLAG_NONE) + +/* Keyboard pins */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT) /* KSI_00-01 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT) /* KSI_02-07 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ +ALTERNATE(PIN_MASK(1, 0xFF), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_02-09 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ +ALTERNATE(PIN_MASK(8, 0x0C), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14-15 */ diff --git a/board/adlrvpp_npcx/vif_override.xml b/board/adlrvpp_npcx/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/adlrvpp_npcx/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/agah/battery.c b/board/agah/battery.c new file mode 100644 index 0000000000..92e2ad4b07 --- /dev/null +++ b/board/agah/battery.c @@ -0,0 +1,107 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Agah battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* DYNAPACK COSMAX Battery Information */ + [BATTERY_DYNAPACK_COSMX] = { + /* RAJ240045 Fuel Gauge */ + .fuel_gauge = { + .manuf_name = "333-2C-4C-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x43, + .reg_mask = 0x0003, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 17600, + .voltage_normal = 15400, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + /* DYNAPACK HIGHPOWER Battery Information */ + [BATTERY_DYNAPACK_HIGHPOWER] = { + /* RAJ240045 Fuel Gauge */ + .fuel_gauge = { + .manuf_name = "333-2D-4C-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x43, + .reg_mask = 0x0003, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 17600, + .voltage_normal = 15400, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COSMX; + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} diff --git a/board/agah/board.c b/board/agah/board.c new file mode 100644 index 0000000000..7884ac1e97 --- /dev/null +++ b/board/agah/board.c @@ -0,0 +1,120 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/nvidia_gpu.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "system.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static int block_sequence; + +struct d_notify_policy d_notify_policies[] = { + [D_NOTIFY_1] = AC_ATLEAST_W(100), + [D_NOTIFY_2] = AC_ATLEAST_W(65), + [D_NOTIFY_3] = AC_DC, + [D_NOTIFY_4] = DC_ATMOST_SOC(20), + [D_NOTIFY_5] = DC_ATMOST_SOC(5), +}; +BUILD_ASSERT(ARRAY_SIZE(d_notify_policies) == D_NOTIFY_COUNT); + +__override void board_cbi_init(void) +{ +} + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +static void board_init(void) +{ + if ((system_get_reset_flags() & EC_RESET_FLAG_AP_OFF) || + (keyboard_scan_get_boot_keys() & BOOT_KEY_DOWN_ARROW)) { + CPRINTS("PG_PP3300_S5_OD block is enabled"); + block_sequence = 1; + } + gpio_enable_interrupt(GPIO_PG_PP3300_S5_OD); + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + + nvidia_gpu_init_policy(d_notify_policies); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/** + * Deferred function to handle GPIO PG_PP3300_S5_OD change + */ +static void bypass_pp3300_s5_deferred(void) +{ + if (block_sequence) { + CPRINTS("PG_PP3300_S5_OD is blocked."); + return; + } + + gpio_set_level(GPIO_PG_PP3300_S5_EC_SEQ_OD, + gpio_get_level(GPIO_PG_PP3300_S5_OD)); +} +DECLARE_DEFERRED(bypass_pp3300_s5_deferred); + +void board_power_interrupt(enum gpio_signal signal) +{ + /* Trigger deferred notification of gpio PG_PP3300_S5_OD change */ + hook_call_deferred(&bypass_pp3300_s5_deferred_data, 0); +} + +static int cc_blockseq(int argc, const char *argv[]) +{ + if (argc > 1) { + if (!parse_bool(argv[1], &block_sequence)) { + ccprintf("Invalid argument: %s\n", argv[1]); + return EC_ERROR_INVAL; + } + } + + ccprintf("PG_PP3300_S5_OD block is %s\n", + block_sequence ? "enabled" : "disabled"); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(blockseq, cc_blockseq, "[on/off]", NULL); + +void gpu_overt_interrupt(enum gpio_signal signal) +{ + nvidia_gpu_over_temp(gpio_get_level(signal)); +} diff --git a/board/agah/board.h b/board/agah/board.h new file mode 100644 index 0000000000..802b0f232e --- /dev/null +++ b/board/agah/board.h @@ -0,0 +1,225 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Agah board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * Nvidia GPU + */ +#define CONFIG_GPU_NVIDIA + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +/* + * Agah blocks PG_PP3300_S5_OD instead to control AP power-on. + */ +#undef CONFIG_CHIPSET_X86_RSMRST_AFTER_S5 + +/* Sensors */ +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE + +/* Buttons */ +#undef CONFIG_VOLUME_BUTTONS + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_TCPM_RT1715 +#undef CONFIG_USB_PD_TCPM_NCT38XX +#define CONFIG_USBC_RETIMER_PS8818 + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USB_PD_FRS_PPC +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 500 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PCH_DSW_PWROK GPIO_PCH_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C2_TCPC NPCX_I2C_PORT2_0 + +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C2_PPC NPCX_I2C_PORT2_0 + +#define I2C_PORT_USB_C0_BC12 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C2_BC12 NPCX_I2C_PORT2_0 + +#define I2C_PORT_USBA1_RT NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS 500 +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_BYPASS_MODE +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +/* Round down 7700 max current to multiple of 128mA for ISL9241 AC prochot. */ +#define AGAH_AC_PROCHOT_CURRENT_MA 7680 + +/* Barrel jack adapter settings */ +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 +/* This is the next available port # after USB-C ports. */ +#define DEDICATED_CHARGE_PORT 2 + +/* + * Older boards have a different ADC assignment. + */ + +#define CONFIG_ADC_CHANNELS_RUNTIME_CONFIG + +/* + * Give power signals higher priority to reduce the chance of damaging the PCH + * on urgent power loss. + */ +#define NPCX_MIWU0_GROUP_F 1 /* SEQ_EC_DSW_PWROK */ +#define NPCX_MIWU0_GROUP_H 2 /* RSMRST */ + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_GPU, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_CHARGER_IADP, + ADC_ADP_TYP, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_GPU, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_COUNT +}; + +enum battery_type { + BATTERY_DYNAPACK_COSMX, + BATTERY_DYNAPACK_HIGHPOWER, + BATTERY_TYPE_COUNT +}; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_FAN2, /* PWM4 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_1, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_1, MFT_CH_COUNT }; + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_TYPEC1, + CHARGE_PORT_BARRELJACK, +}; + +/** + * Interrupt handler for PG_PP3300_S5_OD changes. + * + * @param signal Signal which triggered the interrupt. + */ +void board_power_interrupt(enum gpio_signal signal); + +/* IRQ for BJ plug/unplug. */ +void bj_present_interrupt(enum gpio_signal signal); + +/* IRQ for over temperature. */ +void gpu_overt_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/agah/build.mk b/board/agah/build.mk new file mode 100644 index 0000000000..d2f2db68df --- /dev/null +++ b/board/agah/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Agah board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger_isl9241.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/agah/charger_isl9241.c b/board/agah/charger_isl9241.c new file mode 100644 index 0000000000..892c857ad6 --- /dev/null +++ b/board/agah/charger_isl9241.c @@ -0,0 +1,275 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * + * We need to deal with plug / unplug of AC chargers: + * + * +---------+ +USB +---------+ + * | BATTERY |------------>| BATTERY | + * | |<------------| +USB | + * +---------+ -USB +---------+ + * | ^ | ^ + * +BJ | | -BJ +BJ | | -BJ + * v | v | + * +---------+ +USB +---------+ + * | BATTERY |------------>| BATTERY | + * | +BJ |<------------| +BJ+USB | + * +---------+ -USB +---------+ + * + * Depending on available battery charge, power rating of the new charger, and + * the system power state, transition/throttling may or may not occur but + * switching chargers is handled as follows: + * + * 1. Detects a new charger or removal of an existing charger. + * 2. charge_manager_update_charge is called with new charger's info. + * 3. board_set_active_charge_port is called. + * 3.1 It triggers hard & soft throttling for AP & GPU. + * 3.2 It disable active port then enables the new port. + * 4. HOOK_POWER_SUPPLY_CHANGE is called. We disables hard throttling. + * 5. charger task wakes up on HOOK_POWER_SUPPLY_CHANGE, enables (or disables) + * bypass mode. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "gpio.h" +#include "hooks.h" +#include "stdbool.h" +#include "throttle_ap.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +static int board_enable_bj_port(bool enable) +{ + if (enable) { + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + } else { + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + } + + CPRINTS("BJ power is %sabled", enable ? "en" : "dis"); + + return EC_SUCCESS; +} + +static void board_throttle_ap_gpu(void) +{ + throttle_ap(THROTTLE_ON, THROTTLE_HARD, THROTTLE_SRC_AC); + throttle_gpu(THROTTLE_ON, THROTTLE_HARD, THROTTLE_SRC_AC); +} + +/* Disable all VBUS sink ports except . = -1 disables all ports. */ +static int board_disable_other_vbus_sink(int except_port) +{ + int i, r, rv = EC_SUCCESS; + + for (i = 0; i < ppc_cnt; i++) { + if (i == except_port) + continue; + /* + * Do not return early if one fails otherwise we can get into a + * boot loop assertion failure. + */ + r = ppc_vbus_sink_enable(i, 0); + if (r) + CPRINTS("Failed to disable sink path C%d (%d)", i, r); + rv |= r; + } + + return rv; +} + +/* Minimum battery SoC required for switching source port. */ +#define MIN_BATT_FOR_SWITCHING_SOURCE_PORT 1 + +/* + * TODO: Recover from incomplete execution: + */ +int board_set_active_charge_port(int port) +{ + enum charge_supplier active_supplier = charge_manager_get_supplier(); + int active_port = charge_manager_get_active_charge_port(); + + CPRINTS("Switching charger from P%d (supplier=%d) to P%d", active_port, + active_supplier, port); + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charger ports"); + + board_enable_bj_port(false); + board_disable_other_vbus_sink(-1); + + return EC_SUCCESS; + } + + /* Return on invalid or no-op call. */ + if (port < 0 || CHARGE_PORT_COUNT <= port) { + return EC_ERROR_INVAL; + } else if (port == active_port) { + return EC_SUCCESS; + } else if (board_vbus_source_enabled(port)) { + /* Don't charge from a USBC source port */ + CPRINTS("Don't enable P%d. It's sourcing.", port); + return EC_ERROR_INVAL; + } + + /* + * If we're in S0, throttle AP and GPU. They'll be unthrottled when + * a port/supply switch completes (via HOOK_POWER_SUPPLY_CHANGE). + * + * If we're running currently on a battery (active_supplier == NONE), we + * don't need to throttle because we're not disabling any port. + */ + if (chipset_in_state(CHIPSET_STATE_ON) && + active_supplier != CHARGE_SUPPLIER_NONE) + board_throttle_ap_gpu(); + + /* + * We're here for the two cases: + * 1. A new charger was connected. + * 2. One charger was disconnected and we're switching to another. + */ + + /* + * We need to check the battery if we're switching a source port. If + * we're just starting up or no AC was previously plugged, we shouldn't + * check the battery. Both cases can be caught by supplier == NONE. + */ + if (active_supplier != CHARGE_SUPPLIER_NONE) { + if (charge_get_percent() < MIN_BATT_FOR_SWITCHING_SOURCE_PORT) + return EC_ERROR_NOT_POWERED; + } + + /* Turn off other ports' sink paths before enabling requested port. */ + if (is_pd_port(port)) { + /* + * BJ port is enabled on start-up. So, we need to turn it off + * even if we were not previously on BJ. + */ + board_enable_bj_port(false); + if (board_disable_other_vbus_sink(port)) + return EC_ERROR_UNCHANGED; + + /* Enable requested USBC charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTS("Failed to enable sink path for C%d", port); + return EC_ERROR_UNKNOWN; + } + } else if (port == CHARGE_PORT_BARRELJACK) { + /* + * We can't proceed unless both ports are successfully + * disconnected as sources. + */ + if (board_disable_other_vbus_sink(-1)) + return EC_ERROR_UNKNOWN; + board_enable_bj_port(true); + } + + CPRINTS("New charger P%d", port); + + return EC_SUCCESS; +} + +static const struct charge_port_info bj_power = { + /* 150W (also default) */ + .voltage = 19500, + .current = 7700, +}; + +/* Debounce time for BJ plug/unplug */ +#define BJ_DEBOUNCE_MS CONFIG_EXTPOWER_DEBOUNCE_MS + +int board_should_charger_bypass(void) +{ + return charge_manager_get_active_charge_port() == DEDICATED_CHARGE_PORT; +} + +static void bj_connect(void) +{ + static int8_t bj_connected = -1; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == bj_connected) + return; + + bj_connected = connected; + CPRINTS("BJ %sconnected", connected ? "" : "dis"); + + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, + connected ? &bj_power : NULL); +} +DECLARE_DEFERRED(bj_connect); + +/* This handler shouldn't be needed if ACOK from isl9241 is working. */ +void bj_present_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&bj_connect_data, BJ_DEBOUNCE_MS * MSEC); +} + +void ac_change(void) +{ + /* + * Serialize. We don't handle USB-C here because we'll get a + * notification from TCPC. + */ + hook_call_deferred(&bj_connect_data, 0); +} +DECLARE_HOOK(HOOK_AC_CHANGE, ac_change, HOOK_PRIO_DEFAULT); + +static void power_supply_changed(void) +{ + /* + * We've switched to a new charge port (or no port). Hardware throttles + * can be removed now. Software throttles may stay enabled and change + * as the situation changes. + */ + throttle_ap(THROTTLE_OFF, THROTTLE_HARD, THROTTLE_SRC_AC); + /* + * Unthrottling GPU is done through a deferred call scheduled when it + * was throttled. + */ +} +DECLARE_HOOK(HOOK_POWER_SUPPLY_CHANGE, power_supply_changed, HOOK_PRIO_DEFAULT); + +static void bj_state_init(void) +{ + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + bj_connect(); + + isl9241_set_ac_prochot(CHARGER_SOLO, AGAH_AC_PROCHOT_CURRENT_MA); +} +DECLARE_HOOK(HOOK_INIT, bj_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); diff --git a/board/agah/ec.tasklist b/board/agah/ec.tasklist new file mode 100644 index 0000000000..ebbfd239f9 --- /dev/null +++ b/board/agah/ec.tasklist @@ -0,0 +1,29 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(LED, led_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/agah/fans.c b/board/agah/fans.c new file mode 100644 index 0000000000..be4d335cfe --- /dev/null +++ b/board/agah/fans.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, + [MFT_CH_1] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN2, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_conf fan_conf_1 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_1, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN2, +}; + +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 4300, +}; + +static const struct fan_rpm fan_rpm_1 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 4300, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, + [FAN_CH_1] = { + .conf = &fan_conf_1, + .rpm = &fan_rpm_1, + }, +}; diff --git a/board/agah/fw_config.c b/board/agah/fw_config.c new file mode 100644 index 0000000000..a16cf10d5a --- /dev/null +++ b/board/agah/fw_config.c @@ -0,0 +1,40 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union agah_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for agah if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union agah_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Agah FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union agah_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} diff --git a/board/agah/fw_config.h b/board/agah/fw_config.h new file mode 100644 index 0000000000..7efdae51ac --- /dev/null +++ b/board/agah/fw_config.h @@ -0,0 +1,38 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_AGAH_FW_CONFIG_H_ +#define __BOARD_AGAH_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Agah board. + * + * Source of truth is the project/draco/agah/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +union agah_cbi_fw_config { + struct { + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t reserved_1 : 21; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union agah_cbi_fw_config get_fw_config(void); + +#endif /* __BOARD_AGAH_FW_CONFIG_H_ */ diff --git a/board/agah/gpio.inc b/board/agah/gpio.inc new file mode 100644 index 0000000000..bfec03bfe1 --- /dev/null +++ b/board/agah/gpio.inc @@ -0,0 +1,135 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, intel_x86_pwrok_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(PG_PP3300_S5_OD, PIN(B, 4), GPIO_INT_BOTH | GPIO_PULL_UP, board_power_interrupt) +GPIO_INT(USB_C2_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C2_TCPC_INT_ODL, PIN(A, 7), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C2_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(5, 6), GPIO_INT_BOTH | GPIO_PULL_UP, bj_present_interrupt) +GPIO_INT(GPU_OVERT_ODL, PIN(5, 0), GPIO_INT_BOTH, gpu_overt_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USBA_RT_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USBA_RT_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_FAN2, PIN(F, 5), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(9, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(EC_USB_PCH_C0_OC_ODL, PIN(9, 4), GPIO_ODR_HIGH) +GPIO(EC_USB_PCH_C2_OC_ODL, PIN(9, 7), GPIO_ODR_HIGH) +GPIO(USB_C0_FRS_EN, PIN(A, 0), GPIO_OUT_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(EN_USB_A_LOW_POWER, PIN(9, 3), GPIO_OUT_LOW) +GPIO(PG_PP3300_S5_EC_SEQ_OD, PIN(B, 5), GPIO_OUT_LOW) +GPIO(USB_C2_FRS_EN, PIN(D, 4), GPIO_OUT_LOW) +GPIO(NVIDIA_GPU_ACOFF_ODL, PIN(9, 5), GPIO_ODR_HIGH) +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_LOW) +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_LOW) + +/* + * Barrel-jack adapter enable switch. When starting up on a depleted battery, + * we'll be powered by either BJ or USB-C but not both. The EC will detect BJ + * or USBC and disable the other ports. + */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(A, 2), GPIO_OUT_LOW) + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0xC0), 0, MODULE_PWM, 0) /* GPIOB7/PWM5, GPIOB6/PWM4 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x36), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1, GPIO41/ADC4 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(0, 2)) /* GPIO02 */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ +UNUSED(PIN(8, 1)) /* GPIO81 */ +UNUSED(PIN(6, 0)) /* GPIO60 */ +UNUSED(PIN(C, 2)) /* GPIOC2 */ +UNUSED(PIN(E, 1)) /* GPIOE1 */ diff --git a/board/agah/i2c.c b/board/agah/i2c.c new file mode 100644 index 0000000000..5bdf6936c1 --- /dev/null +++ b/board/agah/i2c.c @@ -0,0 +1,56 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "i2c.h" + +#define BOARD_ID_FAST_PLUS_CAPABLE 2 + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_SCL, + .sda = GPIO_EC_I2C_USB_C0_SDA, + }, + { + /* I2C2 */ + .name = "tcpc2", + .port = I2C_PORT_USB_C2_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C2_SCL, + .sda = GPIO_EC_I2C_USB_C2_SDA, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "usba1", + .port = I2C_PORT_USBA1_RT, + .kbps = 400, + .scl = GPIO_EC_I2C_USBA_RT_SCL, + .sda = GPIO_EC_I2C_USBA_RT_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/agah/keyboard.c b/board/agah/keyboard.c new file mode 100644 index 0000000000..cb34543db8 --- /dev/null +++ b/board/agah/keyboard.c @@ -0,0 +1,52 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xa4, 0xff, 0xf6, 0x55, 0xfe, 0xff, 0xff, 0xff, /* full set */ + }, +}; + +static const struct ec_response_keybd_config keybd = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_KBD_BKLIGHT_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + /* There's no screen lock key on agah */ + .capabilities = KEYBD_CAP_NUMERIC_KEYPAD, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &keybd; +} diff --git a/board/agah/led.c b/board/agah/led.c new file mode 100644 index 0000000000..f581da6ebc --- /dev/null +++ b/board/agah/led.c @@ -0,0 +1,192 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery LED control for Agah + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "host_command.h" +#include "led_common.h" +#include "task.h" + +#include + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define BATT_LOW_BCT 10 + +#define LED_TICK_INTERVAL_MS (500 * MSEC) +#define LED_CYCLE_TIME_MS (2000 * MSEC) +#define LED_TICKS_PER_CYCLE (LED_CYCLE_TIME_MS / LED_TICK_INTERVAL_MS) +#define LED_ON_TIME_MS (1000 * MSEC) +#define LED_ON_TICKS (LED_ON_TIME_MS / LED_TICK_INTERVAL_MS) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color_battery(enum led_color color) +{ + enum gpio_signal amber_led, white_led; + + amber_led = GPIO_LED_1_L; + white_led = GPIO_LED_2_L; + + switch (color) { + case LED_WHITE: + gpio_set_level(white_led, BAT_LED_ON); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_ON); + break; + case LED_OFF: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + default: + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + default: + break; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LED_AMBER); + else + led_set_color_battery(LED_OFF); + break; + default: + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + led_set_color_battery(color); +} + +static void led_set_battery(void) +{ + static unsigned int battery_ticks; + static unsigned int suspend_ticks; + + battery_ticks++; + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + suspend_ticks++; + + led_set_color_battery( + (suspend_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); + + return; + } + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + /* + * Blinking amber LEDs slowly if battery is lower 10 + * percentage. + */ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + if (charge_get_percent() < BATT_LOW_BCT) + led_set_color_battery( + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(LED_OFF); + } + + break; + case LED_PWRS_ERROR: + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + led_set_color_battery( + (battery_ticks & 0x1) ? LED_AMBER : LED_OFF); + } + + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +void led_task(void *u) +{ + uint32_t start_time; + uint32_t task_duration; + + while (1) { + start_time = get_time().le.lo; + + led_set_battery(); + + /* Compute time for this iteration */ + task_duration = get_time().le.lo - start_time; + /* + * Compute wait time required to for next desired LED tick. If + * the duration exceeds the tick time, then don't sleep. + */ + if (task_duration < LED_TICK_INTERVAL_MS) + usleep(LED_TICK_INTERVAL_MS - task_duration); + } +} diff --git a/board/agah/pwm.c b/board/agah/pwm.c new file mode 100644 index 0000000000..e936feabfb --- /dev/null +++ b/board/agah/pwm.c @@ -0,0 +1,47 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, + [PWM_CH_FAN2] = { + .channel = 4, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn off all the LEDs. + * Turn on the fan at 100%. + */ + + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/agah/sensors.c b/board/agah/sensors.c new file mode 100644 index 0000000000..591eb9fccd --- /dev/null +++ b/board/agah/sensors.c @@ -0,0 +1,135 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_GPU] = { + .name = "TEMP_GPU", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_CHARGER_IADP] = { + .name = "CHARGER_IADP", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_ADP_TYP] = { + .name = "ADP_TYP", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { + .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC, + }, + [TEMP_SENSOR_2_GPU] = { + .name = "GPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_GPU, + }, + [TEMP_SENSOR_3_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +#define THERMAL_GPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_gpu = THERMAL_GPU; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 125C, max absolute temperature 150C + * PP3300 regulator: operating range -40 C to 125 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(105), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(120), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(65), \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_GPU] = THERMAL_GPU, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/agah/usbc_config.c b/board/agah/usbc_config.c new file mode 100644 index 0000000000..ac2fb54b86 --- /dev/null +++ b/board/agah/usbc_config.c @@ -0,0 +1,332 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/ps8818_public.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C2_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .frs_en = GPIO_USB_C2_FRS_EN, + .drv = &syv682x_drv, + }, +}; + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +const static struct ps8818_reg_val equalizer_default_table[] = { + { + .reg = PS8818_REG1_APTX1EQ_10G_LEVEL, + .mask = PS8818_EQ_LEVEL_UP_MASK, + .val = PS8818_EQ_LEVEL_UP_19DB, + }, + { + .reg = PS8818_REG1_APTX2EQ_10G_LEVEL, + .mask = PS8818_EQ_LEVEL_UP_MASK, + .val = PS8818_EQ_LEVEL_UP_19DB, + }, + { + .reg = PS8818_REG1_APTX1EQ_5G_LEVEL, + .mask = PS8818_EQ_LEVEL_UP_MASK, + .val = PS8818_EQ_LEVEL_UP_19DB, + }, + { + .reg = PS8818_REG1_APTX2EQ_5G_LEVEL, + .mask = PS8818_EQ_LEVEL_UP_MASK, + .val = PS8818_EQ_LEVEL_UP_19DB, + }, + { + .reg = PS8818_REG1_RX_PHY, + .mask = PS8818_RX_INPUT_TERM_MASK, + .val = PS8818_RX_INPUT_TERM_112_OHM, + }, +}; + +#define NUM_EQ_DEFAULT_ARRAY ARRAY_SIZE(equalizer_default_table) + +int board_ps8818_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + int i; + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + for (i = 0; i < NUM_EQ_DEFAULT_ARRAY; i++) + rv |= ps8818_i2c_field_update8( + me, PS8818_REG_PAGE1, + equalizer_default_table[i].reg, + equalizer_default_table[i].mask, + equalizer_default_table[i].val); + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* Boost the DP gain */ + rv |= ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_DPEQ_LEVEL, + PS8818_DPEQ_LEVEL_UP_MASK, + PS8818_DPEQ_LEVEL_UP_19DB); + } + + return rv; +} + +const static struct usb_mux_chain usbc2_ps8818 = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C2, + .i2c_port = I2C_PORT_USB_C2_TCPC, + .i2c_addr_flags = PS8818_I2C_ADDR0_FLAGS, + .driver = &ps8818_usb_retimer_driver, + .board_set = &board_ps8818_mux_set, + }, +}; + +/* USBC mux configuration - Alder Lake includes internal mux */ +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C2] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc2_ps8818, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +void board_reset_pd_mcu(void) +{ + /* There's no reset pin on TCPC */ +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + + if (port == USBC_PORT_C2) + return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; + + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C2_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C2_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return false; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/agah/usbc_config.h b/board/agah/usbc_config.h new file mode 100644 index 0000000000..e353263f5f --- /dev/null +++ b/board/agah/usbc_config.h @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Agah board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C2, USBC_PORT_COUNT }; + +struct ps8818_reg_val { + uint8_t reg; + uint8_t mask; + uint16_t val; +}; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/agah/vif_override.xml b/board/agah/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/agah/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/akemi/battery.c b/board/akemi/battery.c index 238716b116..de380ac01c 100644 --- a/board/akemi/battery.c +++ b/board/akemi/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/akemi/board.c b/board/akemi/board.c index cc78e77f0c..0665ca1c4e 100644 --- a/board/akemi/board.c +++ b/board/akemi/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,7 @@ /* Hatch board-specific configuration */ #include "adc.h" -#include "adc_chip.h" +#include "battery_smart.h" #include "button.h" #include "common.h" #include "cros_board_info.h" @@ -35,17 +35,16 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#include "battery_smart.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* GPIO to enable/disable the USB Type-A port. */ const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { @@ -90,11 +89,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -102,20 +101,21 @@ static void bc12_interrupt(enum gpio_signal signal) } } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, - [PWM_CH_FAN] = {.channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -135,22 +135,26 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -178,17 +182,13 @@ static struct stprivate_data g_lis2dwl_data; static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -228,8 +228,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_ACCEL, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &base_standard_ref, @@ -260,8 +258,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_ACCEL, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -272,13 +268,12 @@ struct motion_sensor_t motion_sensors[] = { }; unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - /******************************************************************************/ /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -297,56 +292,60 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Temp1", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Temp2", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, - [TEMP_SENSOR_3] = {.name = "Temp3", - .type = TEMP_SENSOR_TYPE_CPU, - .read = g753_get_val, - .idx = 0}, + [TEMP_SENSOR_1] = { .name = "Temp1", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Temp2", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Temp3", + .type = TEMP_SENSOR_TYPE_CPU, + .read = g753_get_val, + .idx = 0 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - /* Hatch Temperature sensors */ /* * TODO(b/124316213): These setting need to be reviewed and set appropriately * for Hatch. They matter when the EC is controlling the fan as opposed to DPTF * control. */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -391,12 +390,12 @@ __override uint32_t board_override_feature_flags0(uint32_t flags0) } /* Battery functions */ -#define SB_OPTIONALMFG_FUNCTION2 0x26 -#define QUICK_CHARGE_SUPPORT 0x01 -#define QUICK_CHARGE_ENABLE 0x02 +#define SB_OPTIONALMFG_FUNCTION2 0x26 +#define QUICK_CHARGE_SUPPORT 0x01 +#define QUICK_CHARGE_ENABLE 0x02 -#define SB_QUICK_CHARGE_ENABLE 1 -#define SB_QUICK_CHARGE_DISABLE 0 +#define SB_QUICK_CHARGE_ENABLE 1 +#define SB_QUICK_CHARGE_DISABLE 0 static void sb_quick_charge_mode(int enable) { @@ -422,7 +421,8 @@ static void board_chipset_startup(void) /* Normal charge current */ sb_quick_charge_mode(SB_QUICK_CHARGE_DISABLE); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, + HOOK_PRIO_INIT_I2C + 1); /* Called on AP S0 -> S5 transition */ static void board_chipset_shutdown(void) @@ -437,5 +437,5 @@ bool board_is_convertible(void) const uint8_t sku = get_board_sku(); return (sku == 255) || (sku == 1) || (sku == 2) || (sku == 3) || - (sku == 4); + (sku == 4); } diff --git a/board/akemi/board.h b/board/akemi/board.h index 2d4482a8d6..bdc18638f8 100644 --- a/board/akemi/board.h +++ b/board/akemi/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,9 +15,8 @@ #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE -#define CONFIG_LED_POWER_LED -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -27,7 +26,6 @@ /* Sensors */ /* LSM6DS3TR-C Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_LSM6DSM #define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) @@ -92,7 +90,7 @@ #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 50 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B @@ -104,15 +102,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -120,8 +119,8 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ ADC_CH_COUNT }; @@ -132,11 +131,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, diff --git a/board/akemi/build.mk b/board/akemi/build.mk index 733912454f..13153c1526 100644 --- a/board/akemi/build.mk +++ b/board/akemi/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/akemi/ec.tasklist b/board/akemi/ec.tasklist index 4a1024a091..829be2b7c8 100644 --- a/board/akemi/ec.tasklist +++ b/board/akemi/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/akemi/gpio.inc b/board/akemi/gpio.inc index 1ea8cca58a..05466078c7 100644 --- a/board/akemi/gpio.inc +++ b/board/akemi/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,10 +16,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) diff --git a/board/akemi/led.c b/board/akemi/led.c index 977acb86ab..b1fa2ddbb6 100644 --- a/board/akemi/led.c +++ b/board/akemi/led.c @@ -1,54 +1,57 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Akemi */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; - -const int led_charge_lvl_2 = 97; - -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED -}; +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); @@ -57,8 +60,7 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_LED_3_L, LED_OFF_LVL); } - -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_RED: @@ -111,4 +113,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/akemi/vif_override.xml b/board/akemi/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/akemi/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/aleena/battery.c b/board/aleena/battery.c index b3abae7f73..0862ba209f 100644 --- a/board/aleena/battery.c +++ b/board/aleena/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/aleena/board.c b/board/aleena/board.c index 102115ef7f..920b339bdf 100644 --- a/board/aleena/board.c +++ b/board/aleena/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,10 @@ /* Aleena board-specific configuration */ #include "button.h" +#include "console.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/led/lm3630a.h" #include "extpower.h" #include "hooks.h" @@ -18,7 +21,9 @@ #include "pwm_chip.h" #include "switch.h" #include "tablet_mode.h" +#include "task.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" const enum gpio_signal hibernate_wake_pins[] = { @@ -27,16 +32,40 @@ const enum gpio_signal hibernate_wake_pins[] = { GPIO_POWER_BUTTON_L, GPIO_EC_RST_ODL, }; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* I2C port map. */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"thermal", I2C_PORT_THERMAL_AP, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"kblight", I2C_PORT_KBLIGHT, 100, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "thermal", + .port = I2C_PORT_THERMAL_AP, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "kblight", + .port = I2C_PORT_KBLIGHT, + .kbps = 100, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -50,6 +79,113 @@ const struct pwm_t pwm_channels[] = { }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); +/* Motion sensors */ +static struct mutex icm426xx_mutex; + +static struct icm_drv_data_t g_icm426xx_data; + +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI160 = 1, + BASE_GYRO_ICM426XX = 2, +}; + +const mat33_fp_t base_standard_ref_icm426xx = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &icm426xx_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_standard_ref_icm426xx, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &icm426xx_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm426xx, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +static enum base_accelgyro_type base_accelgyro_config; + +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_accelgyro_config) { + case BASE_GYRO_ICM426XX: + icm426xx_interrupt(signal); + break; + case BASE_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +static void board_detect_motionsensor(void) +{ + int ret; + int val; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + if (base_accelgyro_config != BASE_GYRO_NONE) + return; + + if (board_is_convertible()) { + /* Check base accelgyro chip */ + ret = icm_read8(&icm426xx_base_accel, ICM426XX_REG_WHO_AM_I, + &val); + if (ret) + ccprints("Get ICM fail."); + if (val == ICM426XX_CHIP_ICM40608) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + } + base_accelgyro_config = (val == ICM426XX_CHIP_ICM40608) ? + BASE_GYRO_ICM426XX : + BASE_GYRO_BMI160; + ccprints("Base Accelgyro: %s", (val == ICM426XX_CHIP_ICM40608) ? + "ICM40608" : + "BMI160"); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_INIT_ADC + 2); + void board_update_sensor_config_from_sku(void) { if (board_is_convertible()) { @@ -58,10 +194,9 @@ void board_update_sensor_config_from_sku(void) } else { motion_sensor_count = 0; /* Device is clamshell only */ - tablet_set_mode(0); + tablet_set_mode(0, TABLET_TRIGGER_LID); /* Gyro is not present, don't allow line to float */ - gpio_set_flags(GPIO_6AXIS_INT_L, - GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); } } @@ -83,15 +218,14 @@ DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_kblight_init, HOOK_PRIO_DEFAULT); * The connector has 30 pins total, and there is no pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {-1, -1}, {-1, -1}, {1, 4}, {1, 3}, - {-1, -1}, {1, 6}, {1, 7}, {3, 1}, {2, 0}, - {1, 5}, {2, 6}, {2, 7}, {2, 1}, {2, 4}, - {2, 5}, {1, 2}, {2, 3}, {2, 2}, {3, 0}, - {-1, -1}, {0, 4}, {-1, -1}, {8, 2}, {-1, -1}, - {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); #endif diff --git a/board/aleena/board.h b/board/aleena/board.h index 76350a76e6..f51b7b3e16 100644 --- a/board/aleena/board.h +++ b/board/aleena/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF @@ -37,7 +37,9 @@ #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel second source*/ +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCEL_KX022 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -49,17 +51,14 @@ /* * Slew rate on the PP1800_SENSOR load switch requires a short delay on startup. */ -#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US +#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US #define CONFIG_MOTION_SENSE_RESUME_DELAY_US (10 * MSEC) #define CONFIG_KEYBOARD_FACTORY_TEST #ifndef __ASSEMBLER__ -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_COUNT }; enum battery_type { BATTERY_PANASONIC, @@ -68,10 +67,7 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -#ifdef CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; -#endif +void motion_interrupt(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ diff --git a/board/aleena/build.mk b/board/aleena/build.mk index c808e65aed..d24127ddae 100644 --- a/board/aleena/build.mk +++ b/board/aleena/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/aleena/ec.tasklist b/board/aleena/ec.tasklist index dc898c4502..9572d61c8f 100644 --- a/board/aleena/ec.tasklist +++ b/board/aleena/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/aleena/gpio.inc b/board/aleena/gpio.inc index e5cf59ba53..669c833e56 100644 --- a/board/aleena/gpio.inc +++ b/board/aleena/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -23,7 +23,7 @@ GPIO_INT(WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) GPIO_INT(VOLUME_DOWN_L, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) GPIO_INT(VOLUME_UP_L, PIN(7, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) GPIO_INT(USB_C0_CABLE_DET, PIN(3, 7), GPIO_INT_RISING, anx74xx_cable_det_interrupt) -GPIO_INT(6AXIS_INT_L, PIN(8, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) +GPIO_INT(6AXIS_INT_L, PIN(8, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) /* GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an interrupt handler. */ GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH | GPIO_LOCKED) diff --git a/board/aleena/led.c b/board/aleena/led.c index 430400e6ae..359e9814ca 100644 --- a/board/aleena/led.c +++ b/board/aleena/led.c @@ -1,23 +1,23 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" -#include "led_onoff_states.h" -#include "led_common.h" +#include "console.h" #include "gpio.h" #include "hooks.h" -#include "console.h" +#include "led_common.h" +#include "led_onoff_states.h" -#define CPRINTS(format, args...) cprints(CC_HOOK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_HOOK, format, ##args) -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1; +__override const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* * board_id others 5, 6 @@ -28,19 +28,25 @@ static enum gpio_signal led_amber = GPIO_BAT_LED_1_L; static enum gpio_signal led_blue = GPIO_BAT_LED_2_L; /* Note there is only LED for charge / power */ -struct led_descriptor - led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; @@ -48,10 +54,9 @@ const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); static void board_led_init(void) { - int board_id = - (gpio_get_level(GPIO_BOARD_VERSION3) << 2) | - (gpio_get_level(GPIO_BOARD_VERSION2) << 1) | - (gpio_get_level(GPIO_BOARD_VERSION1) << 0); + int board_id = (gpio_get_level(GPIO_BOARD_VERSION3) << 2) | + (gpio_get_level(GPIO_BOARD_VERSION2) << 1) | + (gpio_get_level(GPIO_BOARD_VERSION1) << 0); CPRINTS("board_id=%d", board_id); @@ -60,11 +65,10 @@ static void board_led_init(void) led_blue = GPIO_BAT_LED_1_L; CPRINTS("LED: switch LED"); } - } DECLARE_HOOK(HOOK_INIT, board_led_init, HOOK_PRIO_DEFAULT); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_BLUE: diff --git a/board/aleena/vif_override.xml b/board/aleena/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/aleena/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/ambassador/board.c b/board/ambassador/board.c new file mode 100644 index 0000000000..dd839574b5 --- /dev/null +++ b/board/ambassador/board.c @@ -0,0 +1,987 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Puff board-specific configuration */ + +#include "adc.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "common.h" +#include "core/cortex-m/cpu.h" +#include "cros_board_info.h" +#include "driver/ina3221.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/anx7447.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "lid_switch.h" +#include "power.h" +#include "power/cometlake-discrete.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "spi.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_common.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +static void ppc_interrupt(enum gpio_signal signal) +{ + if (signal == GPIO_USB_C0_TCPPC_INT_ODL) + sn5s330_interrupt(0); +} + +int ppc_get_alert_status(int port) +{ + return gpio_get_level(GPIO_USB_C0_TCPPC_INT_ODL) == 0; +} + +static void tcpc_alert_event(enum gpio_signal signal) +{ + if (signal == GPIO_USB_C0_TCPC_INT_ODL) + schedule_deferred_pd_interrupt(0); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int level; + + /* + * Check which port has the ALERT line set and ignore if that TCPC has + * its reset line active. + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) { + level = !!(tcpc_config[USB_PD_PORT_TCPC_0].flags & + TCPC_FLAGS_RESET_ACTIVE_HIGH); + if (gpio_get_level(GPIO_USB_C0_TCPC_RST) != level) + status |= PD_STATUS_TCPC_ALERT_0; + } + + return status; +} + +/* Called when the charge manager has switched to a new port. */ +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Blink alert if insufficient power per system_can_boot_ap(). */ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + led_alert(insufficient_power); +} + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ +#define PWR_BASE_LOAD (5 * 1335) +#define PWR_FRONT_HIGH (5 * 1603) +#define PWR_FRONT_LOW (5 * 963) +#define PWR_REAR (5 * 1075) +#define PWR_HDMI (5 * 562) +#define PWR_C_HIGH (5 * 3740) +#define PWR_C_LOW (5 * 2090) +#define PWR_MAX (5 * 10000) + +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int front_ports = 0; + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power = PWR_BASE_LOAD; + if (!gpio_get_level(GPIO_USB_A0_OC_ODL)) { + front_ports++; + base_5v_power += PWR_FRONT_LOW; + } + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) { + front_ports++; + base_5v_power += PWR_FRONT_LOW; + } + /* + * Only 1 front port can run higher power at a time. + */ + if (front_ports > 0) + base_5v_power += PWR_FRONT_HIGH - PWR_FRONT_LOW; + if (!gpio_get_level(GPIO_USB_A2_OC_ODL)) + base_5v_power += PWR_REAR; + if (!gpio_get_level(GPIO_USB_A3_OC_ODL)) + base_5v_power += PWR_REAR; + if (ec_config_get_usb4_present() && !gpio_get_level(GPIO_USB_A4_OC_ODL)) + base_5v_power += PWR_REAR; + if (!gpio_get_level(GPIO_HDMI_CONN0_OC_ODL)) + base_5v_power += PWR_HDMI; + if (!gpio_get_level(GPIO_HDMI_CONN1_OC_ODL)) + base_5v_power += PWR_HDMI; + if (usbc_overcurrent) + base_5v_power += PWR_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +/* + * Barrel-jack power adapter ratings. + */ +static const struct { + int voltage; + int current; +} bj_power[] = { + { /* 0 - 65W (also default) */ + .voltage = 19000, + .current = 3420 }, + { /* 1 - 90W */ + .voltage = 19000, + .current = 4740 }, +}; + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_L); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) { + unsigned int bj = ec_config_get_bj_power(); + + pi.voltage = bj_power[bj].voltage; + pi.current = bj_power[bj].current; + } + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +static void adp_state_init(void) +{ + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* SPI devices */ +const struct spi_device_t spi_devices[] = {}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +/******************************************************************************/ +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_LED_WHITE] = { .channel = 2, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; + +/******************************************************************************/ +/* USB-C TCPC Configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_TCPC_0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = AN7447_TCPC0_I2C_ADDR_FLAGS, + }, + .drv = &anx7447_tcpm_drv, + .flags = TCPC_FLAGS_RESET_ACTIVE_HIGH, + }, +}; +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_TCPC_0] = { + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, + }, +}; + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { .name = "ina", + .port = I2C_PORT_INA, + .kbps = 400, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "ppc0", + .port = I2C_PORT_PPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 400, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct adc_t adc_channels[] = { + [ADC_SNS_PP3300] = { + /* + * 4700/5631 voltage divider: can take the value out of range + * for 32-bit signed integers, so truncate to 470/563 yielding + * <0.1% error and a maximum intermediate value of 1623457792, + * which comfortably fits in int32. + */ + .name = "SNS_PP3300", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 563, + .factor_div = (ADC_READ_MAX + 1) * 470, + }, + [ADC_SNS_PP1050] = { + .name = "SNS_PP1050", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 500 mV/A */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT * 2, /* Milliamps */ + .factor_div = ADC_READ_MAX + 1, + }, + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR_1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_CORE] = { + .name = "Core", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/******************************************************************************/ +/* Wake up pins */ +const enum gpio_signal hibernate_wake_pins[] = {}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/******************************************************************************/ +/* Physical fans. These are logically separate from pwm_channels. */ +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = -1, +}; + +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 5200, +}; + +const struct fan_t fans[] = { + [FAN_CH_0] = { .conf = &fan_conf_0, .rpm = &fan_rpm_0, }, +}; +BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); + +/******************************************************************************/ +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +/******************************************************************************/ +/* Thermal control; drive fan based on temperature sensors. */ +static const int temp_fan_off = C_TO_K(35); +static const int temp_fan_max = C_TO_K(55); +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(78), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = temp_fan_off, \ + .temp_fan_max = temp_fan_max, \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; + +static const struct ec_thermal_config thermal_b = { + .temp_host = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(78), + [EC_TEMP_THRESH_HALT] = C_TO_K(85), + }, + .temp_host_release = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), + [EC_TEMP_THRESH_HALT] = 0, + }, + }; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_CORE] = THERMAL_A, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +static const struct fan_step_1_1 fan_table0[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(35), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(41), + .rpm = 2500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .rpm = 2900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .rpm = 3400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .rpm = 3900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .rpm = 4400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(52), + .rpm = 4900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(55), + .rpm = 5200 }, +}; +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) + +static const struct fan_step_1_1 *fan_table = fan_table0; + +int fan_percent_to_rpm(int fan, int temp_ratio) +{ + return temp_ratio_to_rpm_hysteresis(fan_table, NUM_FAN_LEVELS, fan, + temp_ratio, NULL); +} + +/* Power sensors */ +const struct ina3221_t ina3221[] = { + { I2C_PORT_INA, 0x40, { "PP3300_G", "PP5000_A", "PP3300_WLAN" } }, + { I2C_PORT_INA, 0x42, { "PP3300_A", "PP3300_SSD", "PP3300_LAN" } }, + { I2C_PORT_INA, 0x43, { NULL, "PP1200_U", "PP2500_DRAM" } } +}; +const unsigned int ina3221_count = ARRAY_SIZE(ina3221); + +static uint16_t board_version; +static uint32_t sku_id; +static uint32_t fw_config; + +static void cbi_init(void) +{ + /* + * Load board info from CBI to control per-device configuration. + * + * If unset it's safe to treat the board as a proto, just C10 gating + * won't be enabled. + */ + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS && val <= UINT16_MAX) + board_version = val; + if (cbi_get_sku_id(&val) == EC_SUCCESS) + sku_id = val; + if (cbi_get_fw_config(&val) == EC_SUCCESS) + fw_config = val; + CPRINTS("Board Version: %d, SKU ID: 0x%08x, F/W config: 0x%08x", + board_version, sku_id, fw_config); +} +DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); + +static void board_init(void) +{ + uint8_t *memmap_batt_flags; + + /* Override some GPIO interrupt priorities. + * + * These interrupts are timing-critical for AP power sequencing, so we + * increase their NVIC priority from the default of 3. This affects + * whole MIWU groups of 8 GPIOs since they share an IRQ. + * + * Latency at the default priority level can be hundreds of + * microseconds while other equal-priority IRQs are serviced, so GPIOs + * requiring faster response must be higher priority. + */ + /* CPU_C10_GATE_L on GPIO6.7: must be ~instant for ~60us response. */ + cpu_set_interrupt_priority(NPCX_IRQ_WKINTH_1, 1); + /* + * slp_s3_interrupt (GPIOA.5 on WKINTC_0) must respond within 200us + * (tPLT18); less critical than the C10 gate. + */ + cpu_set_interrupt_priority(NPCX_IRQ_WKINTC_0, 2); + + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_L); + + /* Always claim AC is online, because we don't have a battery. */ + memmap_batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); + *memmap_batt_flags |= EC_BATT_FLAG_AC_PRESENT; + /* + * For board version < 2, the directly connected recovery + * button is not available. + */ + if (board_version < 2) + button_disable_gpio(BUTTON_RECOVERY); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_chipset_startup(void) +{ + /* + * Workaround to restore VBUS on PPC. + * PP1 is sourced from PP5000_A, and when the CPU shuts down and + * this rail drops, the PPC will internally turn off PP1_EN. + * When the CPU starts again, and the rail is restored, the PPC + * does not turn PP1_EN on again, causing VBUS to stay turned off. + * The workaround is to check whether the PPC is sourcing VBUS, and + * if so, make sure it is enabled. + */ + if (ppc_is_sourcing_vbus(0)) + ppc_vbus_source_enable(0, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); +/******************************************************************************/ +/* USB-C PPC Configuration */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_TCPC_0] = { .i2c_port = I2C_PORT_PPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USB-A port control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USB_VBUS, +}; + +/* Power Delivery and charging functions */ +static void board_tcpc_init(void) +{ + /* + * Reset TCPC if we have had a system reset. + * With EFSv2, it is possible to be in RW without + * having reset the TCPC. + */ + if (system_get_reset_flags() & EC_RESET_FLAG_POWER_ON) + board_reset_pd_mcu(); + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + /* Enable other overcurrent interrupts */ + gpio_enable_interrupt(GPIO_HDMI_CONN0_OC_ODL); + gpio_enable_interrupt(GPIO_HDMI_CONN1_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A2_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A3_OC_ODL); + if (ec_config_get_usb4_present()) { + /* + * By default configured as output low. + */ + gpio_set_flags(GPIO_USB_A4_OC_ODL, GPIO_INPUT | GPIO_INT_BOTH); + gpio_enable_interrupt(GPIO_USB_A4_OC_ODL); + } else { + /* Ensure no interrupts from pin */ + gpio_disable_interrupt(GPIO_USB_A4_OC_ODL); + } +} +/* Make sure this is called after fw_config is initialised */ +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 2); + +int64_t get_time_dsw_pwrok(void) +{ + /* DSW_PWROK is turned on before EC was powered. */ + return -20 * MSEC; +} + +void board_reset_pd_mcu(void) +{ + int level = !!(tcpc_config[USB_PD_PORT_TCPC_0].flags & + TCPC_FLAGS_RESET_ACTIVE_HIGH); + + gpio_set_level(GPIO_USB_C0_TCPC_RST, level); + msleep(BOARD_TCPC_C0_RESET_HOLD_DELAY); + gpio_set_level(GPIO_USB_C0_TCPC_RST, !level); + if (BOARD_TCPC_C0_RESET_POST_DELAY) + msleep(BOARD_TCPC_C0_RESET_POST_DELAY); +} + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + /* TODO(b/143975429) need to touch the PD controller? */ + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_L)) + return EC_ERROR_INVAL; + /* TODO(b/143975429) need to touch the PD controller? */ + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Check that port number is valid. */ + if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) + return; + usbc_overcurrent = is_overcurrented; + update_5v_usage(); +} + +int extpower_is_present(void) +{ + return adp_connected; +} + +int board_is_c10_gate_enabled(void) +{ + /* + * Puff proto drives EN_PP5000_HDMI from EN_S0_RAILS so we cannot gate + * core rails while in S0 because HDMI should remain powered. + * EN_PP5000_HDMI is a separate EC output on all other boards. + */ + return board_version != 0; +} + +void board_enable_s0_rails(int enable) +{ + /* This output isn't connected on protos; safe to set anyway. */ + gpio_set_level(GPIO_EN_PP5000_HDMI, enable); +} + +unsigned int ec_config_get_bj_power(void) +{ + unsigned int bj = (fw_config & EC_CFG_BJ_POWER_MASK) >> + EC_CFG_BJ_POWER_L; + /* Out of range value defaults to 0 */ + if (bj >= ARRAY_SIZE(bj_power)) + bj = 0; + return bj; +} + +int ec_config_get_usb4_present(void) +{ + return !(fw_config & EC_CFG_NO_USB4_MASK); +} + +unsigned int ec_config_get_thermal_solution(void) +{ + return (fw_config & EC_CFG_THERMAL_MASK) >> EC_CFG_THERMAL_L; +} + +static void setup_thermal(void) +{ + unsigned int table = ec_config_get_thermal_solution(); + /* Configure Fan */ + switch (table) { + /* Default and table0 use single fan */ + case 0: + default: + thermal_params[TEMP_SENSOR_CORE] = thermal_a; + break; + /* Table1 is fanless */ + case 1: + fan_set_count(0); + thermal_params[TEMP_SENSOR_CORE] = thermal_b; + break; + } +} +/* fan_set_count should be called before HOOK_INIT/HOOK_PRIO_DEFAULT */ +DECLARE_HOOK(HOOK_INIT, setup_thermal, HOOK_PRIO_DEFAULT - 1); + +/* + * Power monitoring and management. + * + * The overall goal is to gracefully manage the power demand so that + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 2 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A BIT(0) +#define THROT_TYPE_C BIT(1) +#define THROT_PROCHOT BIT(2) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + static uint32_t history[POWER_READINGS]; + static uint8_t index; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v = PWR_MAX - base_5v_power; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + /* + * Clear the first entry of the power table so that + * it is re-initilalised when the CPU starts. + */ + history[0] = 0; + } else { + int32_t charger_mw; + + delay = POWER_DELAY_MS * MSEC; + /* + * Get current charger limit (in mw). + * If not configured yet, skip. + */ + charger_mw = charge_manager_get_power_limit_uw() / 1000; + if (charger_mw != 0) { + int32_t gap, total, max, power; + int i; + + /* + * Read power usage. + */ + power = (adc_read_channel(ADC_VBUS) * + adc_read_channel(ADC_PPVAR_IMON)) / + 1000; + /* Init power table */ + if (history[0] == 0) { + for (i = 0; i < POWER_READINGS; i++) + history[i] = power; + } + /* + * Update the power readings and + * calculate the average and max. + */ + history[index] = power; + index = (index + 1) % POWER_READINGS; + total = 0; + max = history[0]; + for (i = 0; i < POWER_READINGS; i++) { + total += history[i]; + if (history[i] > max) + max = history[i]; + } + /* + * For Type-C power supplies, there is + * less tolerance for exceeding the rating, + * so use the max power that has been measured + * over the measuring period. + * For barrel-jack supplies, the rating can be + * exceeded briefly, so use the average. + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + power = max; + else + power = total / POWER_READINGS; + /* + * Calculate gap, and if negative, power + * demand is exceeding configured power budget, so + * throttling is required to reduce the demand. + */ + gap = charger_mw - power; + /* + * Limiting type-A power. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A; + headroom_5v += PWR_FRONT_HIGH - PWR_FRONT_LOW; + if (!(current_state & THROT_TYPE_A)) + gap += POWER_GAIN_TYPE_A; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(0) && gap <= 0) { + new_state |= THROT_TYPE_C; + headroom_5v += PWR_C_HIGH - PWR_C_LOW; + if (!(current_state & THROT_TYPE_C)) + gap += POWER_GAIN_TYPE_C; + } + /* + * As a last resort, turn on PROCHOT to + * throttle the CPU. + */ + if (gap <= 0) + new_state |= THROT_PROCHOT; + } + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v += PWR_C_HIGH - PWR_C_LOW; + new_state |= THROT_TYPE_C; + } + /* + * [2] If type A not already throttled, and power still + * needed, limit type A. + */ + if (!(new_state & THROT_TYPE_A) && headroom_5v < 0) { + headroom_5v += PWR_FRONT_HIGH - PWR_FRONT_LOW; + new_state |= THROT_TYPE_A; + } + /* + * [3] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v < 0) + new_state |= THROT_TYPE_C; + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_C) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + } + if (diff & THROT_TYPE_A) { + int typea_bc = (new_state & THROT_TYPE_A) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/ambassador/board.h b/board/ambassador/board.h new file mode 100644 index 0000000000..bc6e94a8d5 --- /dev/null +++ b/board/ambassador/board.h @@ -0,0 +1,287 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Puff board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* NPCX7 config */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ + +/* Internal SPI flash on NPCX796FC is 512 kB */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) +#define CONFIG_SPI_FLASH_REGS +#define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ + +/* EC Defines */ +#define CONFIG_ADC +#define CONFIG_BOARD_HAS_RTC_RESET +#define CONFIG_BOARD_VERSION_CBI +#define CONFIG_DEDICATED_RECOVERY_BUTTON +#define CONFIG_DEDICATED_RECOVERY_BUTTON_2 +#define CONFIG_BUTTONS_RUNTIME_CONFIG +#define CONFIG_BOARD_RESET_AFTER_POWER_ON +/* TODO: (b/143496253) re-enable CEC */ +/* #define CONFIG_CEC */ +#define CONFIG_CRC8 +#define CONFIG_CBI_EEPROM +#define CONFIG_EMULATED_SYSRQ +#undef CONFIG_KEYBOARD_BOOT_KEYS +#define CONFIG_MKBP_INPUT_DEVICES +#define CONFIG_MKBP_USE_HOST_EVENT +#undef CONFIG_KEYBOARD_RUNTIME_KEYS +#undef CONFIG_HIBERNATE +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_LED_COMMON +#undef CONFIG_LID_SWITCH +#define CONFIG_LTO +#define CONFIG_PWM +#define CONFIG_VBOOT_EFS2 +#define CONFIG_VBOOT_HASH +#define CONFIG_VSTORE +#define CONFIG_VSTORE_SLOT_COUNT 1 +#define CONFIG_SHA256 + +/* EC Commands */ +#define CONFIG_CMD_BUTTON +/* Include CLI command needed to support CCD testing. */ +#define CONFIG_CMD_CHARGEN +#undef CONFIG_CMD_FASTCHARGE +#undef CONFIG_CMD_KEYBOARD +#define CONFIG_HOSTCMD_PD_CONTROL +#undef CONFIG_CMD_PWR_AVG +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_CMD_TCPC_DUMP +#ifdef SECTION_IS_RO +/* Reduce RO size by removing less-relevant commands. */ +#undef CONFIG_CMD_APTHROTTLE +#undef CONFIG_CMD_CHARGEN +#undef CONFIG_CMD_HCDEBUG +#undef CONFIG_CMD_MMAPINFO +#endif + +#undef CONFIG_CONSOLE_CMDHELP + +/* Don't generate host command debug by default */ +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + +/* Enable AP Reset command for TPM with old firmware version to detect it. */ +#define CONFIG_CMD_AP_RESET_LOG +#define CONFIG_HOSTCMD_AP_RESET + +/* Chipset config */ +#define CONFIG_CHIPSET_COMETLAKE_DISCRETE +/* check */ +#define CONFIG_CHIPSET_CAN_THROTTLE +#define CONFIG_CHIPSET_RESET_HOOK +#define CONFIG_CPU_PROCHOT_ACTIVE_LOW + +/* Dedicated barreljack charger port */ +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 +#define DEDICATED_CHARGE_PORT 1 + +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_IGNORE_LID +#define CONFIG_POWER_BUTTON_X86 +/* Check: */ +#define CONFIG_POWER_BUTTON_INIT_IDLE +#define CONFIG_POWER_COMMON +#define CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD 30 +#define CONFIG_DELAY_DSW_PWROK_TO_PWRBTN +#define CONFIG_POWER_PP5000_CONTROL +#define CONFIG_POWER_S0IX +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define CONFIG_INA3221 + +/* b/143501304 */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 4000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 2000 /* us */ +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +#define CONFIG_USBC_VCONN_SWAP_DELAY_US 8000 /* us */ + +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* Fan and temp. */ +#define CONFIG_FANS 1 +#undef CONFIG_FAN_INIT_SPEED +#define CONFIG_FAN_INIT_SPEED 0 +#define CONFIG_FAN_RPM_CUSTOM +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B +#define CONFIG_THROTTLE_AP + +/* Charger */ +#define CONFIG_CHARGE_MANAGER +/* Less than this much blocks AP power-on. */ +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 30000 +#undef CONFIG_CHARGE_MANAGER_SAFE_MODE + +/* USB type C */ +#define CONFIG_USB_PD_TCPMV2 /* Use TCPMv2 */ +#define CONFIG_USB_PD_REV30 /* Enable PD 3.0 functionality */ +#define CONFIG_USB_PD_DECODE_SOP +#undef CONFIG_USB_CHARGER +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PID 0x5040 +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_LOGGING +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USBC_PPC_DEDICATED_INT +#define CONFIG_USB_PD_TCPM_MUX +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_TCPM_ANX7447 +#define CONFIG_USB_PD_TRY_SRC +#define CONFIG_USB_DRP_ACC_TRYSRC +#define CONFIG_USBC_SS_MUX +#define CONFIG_USBC_SS_MUX_DFP_ONLY +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP + +#define USB_PD_PORT_TCPC_0 0 +#define BOARD_TCPC_C0_RESET_HOLD_DELAY ANX74XX_RESET_HOLD_MS +#define BOARD_TCPC_C0_RESET_POST_DELAY ANX74XX_RESET_HOLD_MS + +/* USB Type A Features */ +#define CONFIG_USB_PORT_POWER_DUMB +/* There are five ports, but power enable is ganged across all of them. */ +#define USB_PORT_COUNT 1 + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER +#define I2C_PORT_INA NPCX_I2C_PORT0_0 +#define I2C_PORT_PPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define PP5000_PGOOD_POWER_SIGNAL_MASK POWER_SIGNAL_MASK(PP5000_A_PGOOD) + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_BARRELJACK, +}; + +enum adc_channel { + ADC_SNS_PP3300, /* ADC2 */ + ADC_SNS_PP1050, /* ADC7 */ + ADC_VBUS, /* ADC4 */ + ADC_PPVAR_IMON, /* ADC9 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + /* Number of ADC channels */ + ADC_CH_COUNT +}; + +enum pwm_channel { + PWM_CH_FAN, + PWM_CH_LED_RED, + PWM_CH_LED_WHITE, + /* Number of PWM channels */ + PWM_CH_COUNT +}; + +enum fan_channel { + FAN_CH_0, + /* Number of FAN channels */ + FAN_CH_COUNT +}; + +enum mft_channel { + MFT_CH_0 = 0, + /* Number of MFT channels */ + MFT_CH_COUNT, +}; + +enum temp_sensor_id { TEMP_SENSOR_CORE, TEMP_SENSOR_COUNT }; + +/* Board specific handlers */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); +void led_alert(int enable); +void show_critical_error(void); + +/* + * firmware config fields + */ +/* + * Barrel-jack power (4 bits). + */ +#define EC_CFG_BJ_POWER_L 0 +#define EC_CFG_BJ_POWER_H 3 +#define EC_CFG_BJ_POWER_MASK GENMASK(EC_CFG_BJ_POWER_H, EC_CFG_BJ_POWER_L) +/* + * USB Connector 4 not present (1 bit). + */ +#define EC_CFG_NO_USB4_L 4 +#define EC_CFG_NO_USB4_H 4 +#define EC_CFG_NO_USB4_MASK GENMASK(EC_CFG_NO_USB4_H, EC_CFG_NO_USB4_L) +/* + * Thermal solution config (3 bits). + */ +#define EC_CFG_THERMAL_L 5 +#define EC_CFG_THERMAL_H 7 +#define EC_CFG_THERMAL_MASK GENMASK(EC_CFG_THERMAL_H, EC_CFG_THERMAL_L) + +unsigned int ec_config_get_bj_power(void); +int ec_config_get_usb4_present(void); +unsigned int ec_config_get_thermal_solution(void); + +#endif /* !__ASSEMBLER__ */ + +/* Pin renaming */ +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_PP5000_A_PG_OD GPIO_PG_PP5000_A_OD +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL +#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_ROA_RAILS +#define GPIO_AC_PRESENT GPIO_BJ_ADP_PRESENT_L + +/* + * There is no RSMRST input, so alias it to the output. This short-circuits + * common_intel_x86_handle_rsmrst. + */ +#define GPIO_PG_EC_RSMRST_ODL GPIO_PCH_RSMRST_L + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/ambassador/build.mk b/board/ambassador/build.mk new file mode 100644 index 0000000000..f9096c64ff --- /dev/null +++ b/board/ambassador/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc + +board-y=board.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-y+=led.o diff --git a/board/ambassador/ec.tasklist b/board/ambassador/ec.tasklist new file mode 100644 index 0000000000..42b9542d96 --- /dev/null +++ b/board/ambassador/ec.tasklist @@ -0,0 +1,17 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 2048) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) diff --git a/board/ambassador/gpio.inc b/board/ambassador/gpio.inc new file mode 100644 index 0000000000..46b6118ce2 --- /dev/null +++ b/board/ambassador/gpio.inc @@ -0,0 +1,169 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Pin names follow the schematic, and are aliased to other names if necessary. + * Note: Those with interrupt handlers must be declared first. */ + +/* Latency on this interrupt is extremely critical, so it comes first to ensure + * it gets placed first in gpio_wui_table so gpio_interrupt() needs to do + * minimal scanning. */ +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, c10_gate_interrupt) + +/* Wake Source interrupts */ +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(PG_PP5000_A_OD, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1800_A_OD, PIN(3, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VPRIM_CORE_A_OD, PIN(2, 3), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1050_A_OD, PIN(2, 2), GPIO_INT_BOTH, power_signal_interrupt) +/* EC output, but also interrupt so this can be polled as a power signal */ +GPIO_INT(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUTPUT | GPIO_INT_F_RISING | GPIO_INT_F_FALLING, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(PG_PP2500_DRAM_U_OD, PIN(2, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1200_U_OD, PIN(2, 1), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, slp_s3_interrupt) +#endif +GPIO_INT(PG_PP950_VCCIO_OD, PIN(1, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(IMVP8_VRRDY_OD, PIN(1, 6), GPIO_INT_BOTH, power_signal_interrupt) + +/* Other interrupts */ +GPIO_INT(USB_C0_TCPPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, tcpc_alert_event) +/* + * Directly connected recovery button (not available on some boards). + */ +GPIO_INT(EC_RECOVERY_BTN_ODL, PIN(F, 1), GPIO_INT_BOTH, button_interrupt) +/* + * Recovery button input from H1. + */ +GPIO_INT(H1_EC_RECOVERY_BTN_ODL, PIN(2, 4), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(BJ_ADP_PRESENT_L, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) + +/* Port power control interrupts */ +GPIO_INT(HDMI_CONN0_OC_ODL, PIN(0, 7), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(HDMI_CONN1_OC_ODL, PIN(0, 6), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A0_OC_ODL, PIN(E, 4), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(A, 2), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A2_OC_ODL, PIN(F, 5), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A3_OC_ODL, PIN(0, 3), GPIO_INT_BOTH, port_ocp_interrupt) +/* May be reconfigured as input */ +GPIO_INT(USB_A4_OC_ODL, PIN(B, 0), GPIO_OUT_LOW | GPIO_INT_BOTH, port_ocp_interrupt) + +/* PCH/CPU signals */ +GPIO(EC_PCH_PWROK, PIN(0, 5), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_IN_OD, PIN(3, 4), GPIO_INPUT) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +/* Power control outputs */ +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PP3300_INA_H1_EC_ODL, PIN(5, 7), GPIO_ODR_HIGH) +GPIO(EN_PP1800_A, PIN(1, 5), GPIO_OUT_LOW) +GPIO(VCCST_PG_OD, PIN(1, 4), GPIO_ODR_LOW) +GPIO(EN_S0_RAILS, PIN(1, 1), GPIO_OUT_LOW) +GPIO(EN_ROA_RAILS, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP950_VCCIO, PIN(1, 0), GPIO_OUT_LOW) +GPIO(EC_IMVP8_PE, PIN(A, 7), GPIO_OUT_LOW) +GPIO(EN_IMVP8_VR, PIN(F, 4), GPIO_OUT_LOW) + +/* Barreljack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 4), GPIO_OUT_LOW) + +/* USB type A */ +GPIO(EN_PP5000_USB_VBUS, PIN(8, 3), GPIO_OUT_LOW) +GPIO(USB_A_LOW_PWR_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(USB_A2_STATUS_L, PIN(6, 1), GPIO_INPUT) +GPIO(USB_A3_STATUS_L, PIN(C, 7), GPIO_INPUT) + +/* USB type C */ +GPIO(USB_C0_TCPC_RST, PIN(9, 7), GPIO_OUT_LOW) + +/* Misc. */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) +GPIO(EN_PP_MST_OD, PIN(9, 6), GPIO_ODR_HIGH) +GPIO(PACKET_MODE_EN, PIN(7, 5), GPIO_OUT_LOW) + +/* HDMI/CEC */ +GPIO(EN_PP5000_HDMI, PIN(5, 0), GPIO_OUT_LOW) +GPIO(HDMI_CONN0_CEC_OUT, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(HDMI_CONN0_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CONN1_CEC_OUT, PIN(9, 5), GPIO_ODR_HIGH) +GPIO(HDMI_CONN1_CEC_IN, PIN(D, 3), GPIO_INPUT) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(I2C0_SCL, PIN(B, 5), GPIO_INPUT) /* EC_I2C_INA_SCL */ +GPIO(I2C0_SDA, PIN(B, 4), GPIO_INPUT) /* EC_I2C_INA_SDA */ +GPIO(I2C1_SCL, PIN(9, 0), GPIO_INPUT) /* EC_I2C_USB_C0_TCPPC_SCL */ +GPIO(I2C1_SDA, PIN(8, 7), GPIO_INPUT) /* EC_I2C_USB_C0_TCPPC_SDA */ +GPIO(I2C3_SCL, PIN(D, 1), GPIO_INPUT) /* EC_I2C_USB_C0_TCPC_SCL */ +GPIO(I2C3_SDA, PIN(D, 0), GPIO_INPUT) /* EC_I2C_USB_C0_TCPC_SDA */ +GPIO(I2C5_SCL, PIN(3, 3), GPIO_INPUT) /* EC_I2C_IMVP8_SCL */ +GPIO(I2C5_SDA, PIN(3, 6), GPIO_INPUT) /* EC_I2C_IMVP8_SDA */ +GPIO(I2C7_SCL, PIN(B, 3), GPIO_INPUT) /* EC_I2C_EEPROM_SCL */ +GPIO(I2C7_SDA, PIN(B, 2), GPIO_INPUT) /* EC_I2C_EEPROM_SDA */ + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(9, 0x01), 0, MODULE_I2C, 0) /* I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, 0x0C), 0, MODULE_I2C, 0) /* I2C7 */ + +/* PWM */ +ALTERNATE(PIN_MASK(C, 0x08), 0, MODULE_PWM, 0) /* PWM0 - Red Led */ +ALTERNATE(PIN_MASK(C, 0x10), 0, MODULE_PWM, 0) /* PWM2 - White Led */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* PWM5 - Fan 1 */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* TA2 - Fan Tachometer */ + +/* ADC */ +ALTERNATE(PIN_MASK(4, 0x2A), 0, MODULE_ADC, 0) /* ADC0, ADC2, ADC4 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* ADC7 */ +ALTERNATE(PIN_MASK(F, 0x01), 0, MODULE_ADC, 0) /* ADC9 */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Unused pins */ +UNUSED(PIN(1, 3)) /* EC_GP_SEL1_ODL */ +UNUSED(PIN(F, 2)) /* EC_I2C_RFU_SDA */ +UNUSED(PIN(F, 3)) /* EC_I2C_RFU_SCL */ +UNUSED(PIN(C, 0)) /* FAN_PWM_2 */ +UNUSED(PIN(8, 0)) /* LED_BLUE_L */ +UNUSED(PIN(4, 4)) /* ADC1/TEMP_SENSOR_2 */ +UNUSED(PIN(4, 2)) /* ADC3/TEMP_SENSOR_3 */ +UNUSED(PIN(C, 2)) /* A12 NC */ +UNUSED(PIN(9, 2)) /* K8 NC */ +UNUSED(PIN(9, 1)) /* L8 NC */ +UNUSED(PIN(1, 2)) /* C6 NC */ +UNUSED(PIN(6, 6)) /* H4 NC */ +UNUSED(PIN(8, 1)) /* L6 NC */ +UNUSED(PIN(C, 6)) /* B11 NC */ +UNUSED(PIN(E, 2)) /* B8 NC */ +UNUSED(PIN(8, 5)) /* L7 NC */ +UNUSED(PIN(0, 0)) /* D11 NC */ +UNUSED(PIN(3, 2)) /* E5 NC */ +UNUSED(PIN(D, 6)) /* F6 NC */ +UNUSED(PIN(3, 5)) /* F5 NC */ +UNUSED(PIN(5, 6)) /* M2 NC */ +UNUSED(PIN(D, 2)) /* C11 NC */ +UNUSED(PIN(8, 6)) /* J8 NC */ +UNUSED(PIN(9, 3)) /* M11 NC */ +UNUSED(PIN(7, 2)) /* H6 NC */ diff --git a/board/ambassador/led.c b/board/ambassador/led.c new file mode 100644 index 0000000000..3baf867580 --- /dev/null +++ b/board/ambassador/led.c @@ -0,0 +1,267 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Puff. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_WHITE, + LED_AMBER, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int white = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_WHITE: + white = 1; + break; + case LED_RED: + red = 1; + break; + case LED_AMBER: + red = 1; + white = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (white) + pwm_set_duty(PWM_CH_LED_WHITE, duty); + else + pwm_set_duty(PWM_CH_LED_WHITE, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_WHITE); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_WHITE, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +static void led_init(void) +{ + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_WHITE, 1); +} +DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_INIT_PWM + 1); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "white")) { + set_color(id, LED_WHITE, 100); + } else if (!strcasecmp(argv[1], "amber")) { + set_color(id, LED_AMBER, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, + "[debug|red|white|amber|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; + brightness_range[EC_LED_COLOR_AMBER] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_WHITE]) + return set_color(id, LED_WHITE, brightness[EC_LED_COLOR_WHITE]); + else if (brightness[EC_LED_COLOR_AMBER]) + return set_color(id, LED_AMBER, brightness[EC_LED_COLOR_AMBER]); + else + return set_color(id, LED_OFF, 0); +} diff --git a/board/ambassador/usb_pd_policy.c b/board/ambassador/usb_pd_policy.c new file mode 100644 index 0000000000..fbb4edf23e --- /dev/null +++ b/board/ambassador/usb_pd_policy.c @@ -0,0 +1,83 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Shared USB-C policy for Puff boards */ + +#include "charge_manager.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "system.h" +#include "tcpm/tcpci.h" +#include "tcpm/tcpm.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Only allow vconn swap if pp5000_A rail is enabled */ + return gpio_get_level(GPIO_EN_PP5000_A); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + prev_en = ppc_is_sourcing_vbus(port); + + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC +int pd_snk_is_vbus_provided(int port) +{ + return ppc_is_vbus_present(port); +} +#endif + +int board_vbus_source_enabled(int port) +{ + /* Ignore non-PD ports (the barrel jack). */ + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return 0; + return ppc_is_sourcing_vbus(port); +} diff --git a/board/ambassador/vif_override.xml b/board/ambassador/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/ambassador/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/ampton/battery.c b/board/ampton/battery.c index 481216cf61..18bf4e591a 100644 --- a/board/ampton/battery.c +++ b/board/ampton/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -116,30 +116,35 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 60, }, }, + [BATTERY_C204_SECOND] = { + .fuel_gauge = { + .manuf_name = "AS3FXXd3KB", + .device_name = "C214-43", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x10, 0x10 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000C, + .disconnect_val = 0x000C, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0004 + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C214; - -/* Lower our input voltage to 5V in S5/G3 when battery is full. */ -static void reduce_input_voltage_when_full(void) -{ - int max_pd_voltage_mv; - int port; - - if (charge_get_percent() == 100 && - chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) - max_pd_voltage_mv = 5000; - else - max_pd_voltage_mv = PD_MAX_VOLTAGE_MV; - if (pd_get_max_voltage() != max_pd_voltage_mv) { - for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) - pd_set_external_voltage_limit(port, max_pd_voltage_mv); - } -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); diff --git a/board/ampton/board.c b/board/ampton/board.c index 3e5ab18510..ccd82d4e71 100644 --- a/board/ampton/board.c +++ b/board/ampton/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Ampton/Apel board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_state.h" #include "common.h" @@ -14,6 +13,8 @@ #include "driver/accel_bma2x2.h" #include "driver/accel_kionix.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" #include "driver/ppc/sn5s330.h" #include "driver/sync.h" #include "driver/tcpm/it83xx_pd.h" @@ -33,9 +34,9 @@ #include "switch.h" #include "system.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "uart.h" #include "usb_mux.h" #include "usbc_ppc.h" @@ -59,13 +60,14 @@ int ppc_get_alert_status(int port) return gpio_get_level(GPIO_USB_C1_PD_INT_ODL) == 0; } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* USB-C MUX Configuration */ -#define USB_PD_PORT_ITE_0 0 -#define USB_PD_PORT_ITE_1 1 +#define USB_PD_PORT_ITE_0 0 +#define USB_PD_PORT_ITE_1 1 static int tune_mux(const struct usb_mux *me); @@ -74,9 +76,9 @@ const struct usb_mux ampton_usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { /* Use PS8751 as mux only */ .usb_port = USB_PD_PORT_ITE_0, .i2c_port = I2C_PORT_USBC0, - .i2c_addr_flags = PS8751_I2C_ADDR1_FLAGS, + .i2c_addr_flags = PS8XXX_I2C_ADDR1_FLAGS, .flags = USB_MUX_FLAG_NOT_TCPC, - .driver = &tcpci_tcpm_usb_mux_driver, + .driver = &ps8xxx_usb_mux_driver, .hpd_update = &ps8xxx_tcpc_update_hpd_status, .board_init = &tune_mux, }, @@ -84,9 +86,9 @@ const struct usb_mux ampton_usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { /* Use PS8751 as mux only */ .usb_port = USB_PD_PORT_ITE_1, .i2c_port = I2C_PORT_USBC1, - .i2c_addr_flags = PS8751_I2C_ADDR1_FLAGS, + .i2c_addr_flags = PS8XXX_I2C_ADDR1_FLAGS, .flags = USB_MUX_FLAG_NOT_TCPC, - .driver = &tcpci_tcpm_usb_mux_driver, + .driver = &ps8xxx_usb_mux_driver, .hpd_update = &ps8xxx_tcpc_update_hpd_status, .board_init = &tune_mux, } @@ -98,9 +100,10 @@ const struct usb_mux ampton_usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { static int tune_mux(const struct usb_mux *me) { /* Auto EQ disabled, compensate for channel lost up to 3.6dB */ - mux_write(me, PS8XXX_REG_MUX_DP_EQ_CONFIGURATION, 0x98); + RETURN_ERROR(mux_write(me, PS8XXX_REG_MUX_DP_EQ_CONFIGURATION, 0x98)); /* DP output swing adjustment +15% */ - mux_write(me, PS8XXX_REG_MUX_DP_OUTPUT_CONFIGURATION, 0xc0); + RETURN_ERROR( + mux_write(me, PS8XXX_REG_MUX_DP_OUTPUT_CONFIGURATION, 0xc0)); return EC_SUCCESS; } @@ -108,44 +111,44 @@ static int tune_mux(const struct usb_mux *me) /* ADC channels */ const struct adc_t adc_channels[] = { /* Vbus C0 sensing (10x voltage divider). PPVAR_USB_C0_VBUS */ - [ADC_VBUS_C0] = {.name = "VBUS_C0", - .factor_mul = 10 * ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH13}, + [ADC_VBUS_C0] = { .name = "VBUS_C0", + .factor_mul = 10 * ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, /* Vbus C1 sensing (10x voltage divider). SUB_EC_ADC */ - [ADC_VBUS_C1] = {.name = "VBUS_C1", - .factor_mul = 10 * ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH14}, + [ADC_VBUS_C1] = { .name = "VBUS_C1", + .factor_mul = 10 * ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH14 }, /* Convert to raw mV for thermistor table lookup */ - [ADC_TEMP_SENSOR_AMB] = {.name = "TEMP_AMB", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH3}, + [ADC_TEMP_SENSOR_AMB] = { .name = "TEMP_AMB", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, /* Convert to raw mV for thermistor table lookup */ - [ADC_TEMP_SENSOR_CHARGER] = {.name = "TEMP_CHARGER", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH5}, + [ADC_TEMP_SENSOR_CHARGER] = { .name = "TEMP_CHARGER", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH5 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -154,27 +157,29 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); static struct mutex g_lid_mutex; static struct mutex g_base_mutex; -const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -const mat33_fp_t gyro_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t gyro_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t base_standard_ref_icm42607 = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +const mat33_fp_t lid_standard_ref_sku57 = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm42607_data; /* BMA253 private data */ static struct accelgyro_saved_data_t g_bma253_data; @@ -208,6 +213,49 @@ static const struct motion_sensor_t motion_sensor_bma253 = { }, }; +struct motion_sensor_t motion_sensor_accel_icm42607 = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs. */ + .rot_standard_ref = &base_standard_ref_icm42607, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t motion_sensor_gyro_icm42607 = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm42607, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; + /* Drivers */ struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -298,9 +346,9 @@ unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); static int board_is_convertible(void) { /* SKU IDs of Ampton & unprovisioned: 1, 2, 3, 4, 255 */ - return sku_id == 1 || sku_id == 2 || sku_id == 3 || sku_id == 4 - || sku_id == 255; - } + return sku_id == 1 || sku_id == 2 || sku_id == 3 || sku_id == 4 || + sku_id == 57 || sku_id == 255; +} static int board_with_sensor_bma253(void) { @@ -308,6 +356,20 @@ static int board_with_sensor_bma253(void) return sku_id == 3 || sku_id == 4; } +static int board_with_sensor_icm42607(void) +{ + /* SKU ID 3 and 4 of Ampton with BMA253 */ + return sku_id == 57; +} + +void motion_interrupt(enum gpio_signal signal) +{ + if (board_with_sensor_icm42607()) + icm42607_interrupt(signal); + else + bmi160_interrupt(signal); +} + static void board_update_sensor_config_from_sku(void) { if (board_is_convertible()) { @@ -315,6 +377,15 @@ static void board_update_sensor_config_from_sku(void) if (board_with_sensor_bma253()) motion_sensors[LID_ACCEL] = motion_sensor_bma253; + if (board_with_sensor_icm42607()) { + motion_sensors[BASE_ACCEL] = + motion_sensor_accel_icm42607; + motion_sensors[BASE_GYRO] = motion_sensor_gyro_icm42607; + ccprints("Gyro sensor: ICM-42607"); + } + if (sku_id == 57) + motion_sensors[LID_ACCEL].rot_standard_ref = + &lid_standard_ref_sku57; /* Enable Base Accel interrupt */ gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); @@ -373,9 +444,8 @@ void board_overcurrent_event(int port, int is_overcurrented) cprints(CC_USBPD, "p%d: overcurrent!", port); } -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -387,4 +457,3 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif diff --git a/board/ampton/board.h b/board/ampton/board.h index 69304cb7c8..4a00f82cd2 100644 --- a/board/ampton/board.h +++ b/board/ampton/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,8 +13,10 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + /* I2C bus configuraiton */ -#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_ACCEL I2C_PORT_SENSOR /* EC console commands */ #define CONFIG_CMD_ACCELS @@ -26,17 +28,21 @@ #define CONFIG_LED_COMMON +#define CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV 5000 + /* Sensors */ #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B #define CONFIG_STEINHART_HART_3V3_13K7_47K_4050B -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_PP3300 +#define CONFIG_TEMP_SENSOR_POWER +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_PP3300 -#define CONFIG_ACCEL_BMA255 /* Lid accel */ -#define CONFIG_ACCEL_KX022 /* Lid accel */ -#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_SYNC /* Camera VSYNC */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_ICM42607 /* Base accel */ +#define CONFIG_SYNC /* Camera VSYNC */ #define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT /* Sensors without hardware FIFO are in forced mode */ @@ -49,8 +55,9 @@ #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) /* Keyboard backlight is unimplemented in hardware */ #undef CONFIG_PWM @@ -82,22 +89,19 @@ enum temp_sensor_id { }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - VSYNC, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, VSYNC, SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { BATTERY_C214, BATTERY_C204EE, BATTERY_C424, + BATTERY_C204_SECOND, BATTERY_TYPE_COUNT, }; +void motion_interrupt(enum gpio_signal signal); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/ampton/build.mk b/board/ampton/build.mk index cc6b73093e..daf4529f19 100644 --- a/board/ampton/build.mk +++ b/board/ampton/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/ampton/ec.tasklist b/board/ampton/ec.tasklist index 2703dd0b5c..466dd4c60f 100644 --- a/board/ampton/ec.tasklist +++ b/board/ampton/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/ampton/gpio.inc b/board/ampton/gpio.inc index 724d9a98d9..c1d7769668 100644 --- a/board/ampton/gpio.inc +++ b/board/ampton/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -32,7 +32,7 @@ GPIO_INT(RSMRST_L_PGOOD, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) /* PM GPIO_INT(ALL_SYS_PGOOD, PIN(F, 0), GPIO_INT_BOTH, power_signal_interrupt) /* PMIC_EC_PWROK_OD */ GPIO_INT(AC_PRESENT, PIN(A, 7), GPIO_INT_BOTH, extpower_interrupt) /* ACOK_OD */ -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI /* enable 1.8v input of EC's espi_reset pin, and then this pin takes effect. */ GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) /* eSPI_reset# */ #endif @@ -41,7 +41,7 @@ GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset GPIO_INT(TABLET_MODE_L, PIN(H, 4), GPIO_INT_BOTH, gmr_tablet_switch_isr) GPIO_INT(EC_VOLDN_BTN_ODL, PIN(D, 6), GPIO_INT_BOTH, button_interrupt) GPIO_INT(EC_VOLUP_BTN_ODL, PIN(D, 5), GPIO_INT_BOTH, button_interrupt) -GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) GPIO(LID_ACCEL_INT_L, PIN(J, 3), GPIO_INPUT | GPIO_SEL_1P8V) GPIO(PCH_PLTRST_L, PIN(E, 3), GPIO_INPUT) /* PLT_RST_L: Platform Reset from SoC */ diff --git a/board/ampton/led.c b/board/ampton/led.c index 68f9e3eac8..02bafec4e0 100644 --- a/board/ampton/led.c +++ b/board/ampton/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,34 +10,43 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 0 -#define LED_ON_LVL 1 +#define LED_OFF_LVL 0 +#define LED_ON_LVL 1 -const int led_charge_lvl_1 = 0; +__override const int led_charge_lvl_1; -const int led_charge_lvl_2 = 94; +__override const int led_charge_lvl_2 = 94; /* Ampton: Note there is only LED for charge / power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: @@ -72,4 +81,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/ampton/vif_override.xml b/board/ampton/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/ampton/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/anahera/battery.c b/board/anahera/battery.c new file mode 100644 index 0000000000..f7b0b6f43f --- /dev/null +++ b/board/anahera/battery.c @@ -0,0 +1,94 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "compile_time_macros.h" + +/* + * Battery info for all Anahera battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* 996QA193H Simplo HIGHPOWER Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-1D-11-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + /* B00C407792D0001 CosMX Battery Information */ + [BATTERY_COSMX] = { + .fuel_gauge = { + .manuf_name = "333-AC-11-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO_HIGHPOWER; diff --git a/board/anahera/board.c b/board/anahera/board.c new file mode 100644 index 0000000000..f5fc90a9aa --- /dev/null +++ b/board/anahera/board.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "peripheral_charger.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + gpio_set_level(GPIO_EC_KB_BL_EN, 1); + ioex_set_level(IOEX_USB_A1_PD_R_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + gpio_set_level(GPIO_EC_KB_BL_EN, 0); + ioex_set_level(IOEX_USB_A1_PD_R_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +enum battery_present battery_hw_present(void) +{ + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/anahera/board.h b/board/anahera/board.h new file mode 100644 index 0000000000..517e934f87 --- /dev/null +++ b/board/anahera/board.h @@ -0,0 +1,211 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Anahera board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +/* Sensors */ +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE + +/* No side buttons */ +#undef CONFIG_MKBP_INPUT_DEVICES +#undef CONFIG_VOLUME_BUTTONS + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB +#define CONFIG_USBC_RETIMER_PS8811 + +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USB_PD_FRS_PPC + +#define CONFIG_USBC_RETIMER_INTEL_BB + +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_NX20P3483 + +/* TODO: b/193452481 - measure and check these values on redrix */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_PORT_USB_A0_RETIMER NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_A1_RETIMER NPCX_I2C_PORT6_1 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* + * see b/174768555#comment22 + */ +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x58 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* Fan features */ +#define CONFIG_FANS FAN_CH_COUNT +#define CONFIG_CUSTOM_FAN_CONTROL +#define RPM_DEVIATION 1 + +/* Charger defines */ +#define CONFIG_CHARGER_BQ25720 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 70 +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 + +/* Keyboard features */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_FAN, + ADC_TEMP_SENSOR_2_SOC, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_TEMP_SENSOR_4_REGULATOR, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_FAN, + TEMP_SENSOR_2_SOC, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_4_REGULATOR, + TEMP_SENSOR_COUNT +}; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C1_NCT38XX, IOEX_PORT_COUNT }; + +enum battery_type { + BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COSMX, + BATTERY_TYPE_COUNT +}; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +extern const int keyboard_factory_scan_pins[][2]; +extern const int keyboard_factory_scan_pins_used; +#endif + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/anahera/build.mk b/board/anahera/build.mk new file mode 100644 index 0000000000..dda59fdd82 --- /dev/null +++ b/board/anahera/build.mk @@ -0,0 +1,26 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Anahera board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=thermal.o +board-y+=usbc_config.o diff --git a/board/anahera/charger.c b/board/anahera/charger.c new file mode 100644 index 0000000000..827152e115 --- /dev/null +++ b/board/anahera/charger.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/anahera/ec.tasklist b/board/anahera/ec.tasklist new file mode 100644 index 0000000000..ebbfd239f9 --- /dev/null +++ b/board/anahera/ec.tasklist @@ -0,0 +1,29 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(LED, led_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/anahera/fans.c b/board/anahera/fans.c new file mode 100644 index 0000000000..f60adb9cb4 --- /dev/null +++ b/board/anahera/fans.c @@ -0,0 +1,44 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2800, + .rpm_start = 2800, + .rpm_max = 5000, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/anahera/fw_config.c b/board/anahera/fw_config.c new file mode 100644 index 0000000000..c44343bdb7 --- /dev/null +++ b/board/anahera/fw_config.c @@ -0,0 +1,73 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union anahera_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for anahera if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union anahera_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_DISABLED, +}; + +static uint32_t cbi_sku_id; + +/**************************************************************************** + * Anahera FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* + * Early boards have a zero'd out FW_CONFIG, so replace + * it with a sensible default value. + */ + if (fw_config.raw_value == 0) { + CPRINTS("CBI: FW_CONFIG is zero, using board defaults"); + fw_config = fw_config_defaults; + } + } + + /* Saving sku for later use */ + if (cbi_get_sku_id(&cbi_sku_id) != EC_SUCCESS) + cbi_sku_id = 0; +} + +union anahera_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +bool ec_cfg_has_eps(void) +{ + return (fw_config.eps == EPS_ENABLED); +} + +bool ec_cfg_has_kblight(void) +{ + return (fw_config.kb_bl == KEYBOARD_BACKLIGHT_ENABLED); +} + +bool ec_cfg_has_lte(void) +{ + /* Also check for mis-configured skus 0xA0108~0xA010B */ + return (fw_config.lte_db == LTE_PRESENT) || + ((cbi_sku_id >= 0xA0108) && (cbi_sku_id <= 0xA010B)); +} diff --git a/board/anahera/fw_config.h b/board/anahera/fw_config.h new file mode 100644 index 0000000000..32787c1e4f --- /dev/null +++ b/board/anahera/fw_config.h @@ -0,0 +1,74 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_ANAHERA_FW_CONFIG_H_ +#define __BOARD_ANAHERA_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Anahera board. + * + * Source of truth is the project/brya/anahera/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_eps_type { EPS_DISABLED = 0, EPS_ENABLED = 1 }; + +enum ec_cfg_ite_type { + LTE_NOT_PRESENT = 0, + LTE_PRESENT = 1, +}; + +union anahera_cbi_fw_config { + struct { + uint32_t sd_db : 2; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + enum ec_cfg_ite_type lte_db : 2; + uint32_t ufc : 2; + enum ec_cfg_eps_type eps : 1; + uint32_t boot_device : 2; + uint32_t reserved_1 : 19; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union anahera_cbi_fw_config get_fw_config(void); + +/** + * Check if the FW_CONFIG has enabled privacy screen. + * + * @return true if board supports privacy screen, false if the board + * doesn't support it. + */ +bool ec_cfg_has_eps(void); + +/** + * Check if the FW_CONFIG has enabled keyboard backlight. + * + * @return true if board supports keyboard backlight, false if the board + * doesn't support it. + */ +bool ec_cfg_has_kblight(void); + +/** + * Check if the FW_CONFIG has LTE present. + * + * @return true if board supports LTE, false if the board + * doesn't support it. + */ +bool ec_cfg_has_lte(void); + +#endif /* __BOARD_ANAHERA_FW_CONFIG_H_ */ diff --git a/board/anahera/gpio.inc b/board/anahera/gpio.inc new file mode 100644 index 0000000000..5cce74abff --- /dev/null +++ b/board/anahera/gpio.inc @@ -0,0 +1,150 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(9, 6), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_TCPC_RST_ODL, PIN(A, 0), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) + +/* LED */ +GPIO(C0_CHARGE_LED_AMBER_L, PIN(C, 4), GPIO_OUT_HIGH) /* Amber C0 port */ +GPIO(C0_CHARGE_LED_WHITE_L, PIN(C, 3), GPIO_OUT_HIGH) /* White C0 port */ +GPIO(C1_CHARGE_LED_AMBER_L, PIN(5, 7), GPIO_OUT_HIGH) /* Amber C1 port */ +GPIO(C1_CHARGE_LED_WHITE_L, PIN(9, 4), GPIO_OUT_HIGH) /* White C1 port */ + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPO66/ARM_L_x86 */ +UNUSED(PIN(0, 2)) /* GPIO02/PSL_IN4 */ +UNUSED(PIN(5, 0)) /* GPIO50 */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN_L */ +UNUSED(PIN(6, 0)) /* GPIO60/PWM7 */ +UNUSED(PIN(7, 3)) /* GPIO73/TA2 */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(9, 5)) /* GPIO95/SPIP_MISO */ +UNUSED(PIN(B, 4)) /* GPIOB4/I2C0_SDA0 */ +UNUSED(PIN(B, 5)) /* GPIOB5/I2C0_SCL0 */ +UNUSED(PIN(C, 2)) /* GPIOC2/PWM1/I2C6_SCL0 */ +UNUSED(PIN(D, 4)) /* GPIOD4/CR_SIN3 */ +UNUSED(PIN(F, 5)) /* GPIOF5/I2C5_SCL1 */ +UNUSED(PIN(9, 3)) /* GPIO93/TA1/F_DIO2 */ +UNUSED(PIN(9, 7)) /* GPIO97 */ + +/* Pre-configured PSL balls: J8 K6 */ + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C1_FRS_EN, EXPIN(IOEX_C1_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C1_RT_RST_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 7), GPIO_ODR_LOW) +IOEX(USB_A1_PD_R_L, EXPIN(IOEX_C1_NCT38XX, 1, 7), GPIO_OUT_LOW) diff --git a/board/anahera/i2c.c b/board/anahera/i2c.c new file mode 100644 index 0000000000..e9ccf2d928 --- /dev/null +++ b/board/anahera/i2c.c @@ -0,0 +1,69 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,usba0_retimer", + .port = I2C_PORT_USB_C0_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0", + .port = I2C_PORT_USB_C0_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_RT_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1,retimer1,usba1_retimer", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/anahera/keyboard.c b/board/anahera/keyboard.c new file mode 100644 index 0000000000..8588191460 --- /dev/null +++ b/board/anahera/keyboard.c @@ -0,0 +1,166 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config keybd_wo_privacy_w_kblight = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_KBD_BKLIGHT_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config + keybd_wo_privacy_wo_kblight_old = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PREV_TRACK, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config + keybd_wo_privacy_wo_kblight_new = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PLAY_PAUSE, /* T8 */ + TK_MICMUTE, /* T9 */ + TK_VOL_MUTE, /* T10 */ + TK_VOL_DOWN, /* T11 */ + TK_VOL_UP, /* T12 */ + TK_MENU, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config keybd_w_privacy_w_kblight = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PRIVACY_SCRN_TOGGLE, /* T8 */ + TK_KBD_BKLIGHT_TOGGLE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config keybd_w_privacy_wo_kblight = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PRIVACY_SCRN_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (ec_cfg_has_eps()) { + if (ec_cfg_has_kblight()) + return &keybd_w_privacy_w_kblight; + else + return &keybd_w_privacy_wo_kblight; + } else { + if (ec_cfg_has_kblight()) + return &keybd_wo_privacy_w_kblight; + else { + if (get_board_id() <= 3) + return &keybd_wo_privacy_wo_kblight_old; + else + return &keybd_wo_privacy_wo_kblight_new; + } + } +} + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/anahera/led.c b/board/anahera/led.c new file mode 100644 index 0000000000..06e557c81d --- /dev/null +++ b/board/anahera/led.c @@ -0,0 +1,223 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Redrix + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "host_command.h" +#include "led_common.h" +#include "task.h" + +#include + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +#define BATT_LOW_BCT 10 + +#define LED_TICK_INTERVAL_MS (500 * MSEC) +#define LED_CYCLE_TIME_MS (2000 * MSEC) +#define LED_TICKS_PER_CYCLE (LED_CYCLE_TIME_MS / LED_TICK_INTERVAL_MS) +#define LED_ON_TIME_MS (1000 * MSEC) +#define LED_ON_TICKS (LED_ON_TIME_MS / LED_TICK_INTERVAL_MS) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +enum led_port { LEFT_PORT = 0, RIGHT_PORT }; + +static void led_set_color_battery(int port, enum led_color color) +{ + enum gpio_signal amber_led, white_led; + + amber_led = (port == RIGHT_PORT ? GPIO_C1_CHARGE_LED_AMBER_L : + GPIO_C0_CHARGE_LED_AMBER_L); + white_led = (port == RIGHT_PORT ? GPIO_C1_CHARGE_LED_WHITE_L : + GPIO_C0_CHARGE_LED_WHITE_L); + + switch (color) { + case LED_WHITE: + gpio_set_level(white_led, BAT_LED_ON); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_ON); + break; + case LED_OFF: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + default: + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_RIGHT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + default: + break; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LEFT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LEFT_PORT, LED_AMBER); + else + led_set_color_battery(LEFT_PORT, LED_OFF); + break; + case EC_LED_ID_RIGHT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(RIGHT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(RIGHT_PORT, LED_AMBER); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + break; + default: + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + led_set_color_battery(RIGHT_PORT, + (port == RIGHT_PORT) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, + (port == LEFT_PORT) ? color : LED_OFF); +} + +static void led_set_battery(void) +{ + static unsigned int battery_ticks; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + /* + * Blinking amber LEDs slowly if battery is lower 10 + * percentage. + */ + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + if (charge_get_percent() < BATT_LOW_BCT) + led_set_color_battery( + RIGHT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) { + if (charge_get_percent() < BATT_LOW_BCT) + led_set_color_battery( + LEFT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(LEFT_PORT, LED_OFF); + } + break; + case LED_PWRS_ERROR: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + led_set_color_battery( + RIGHT_PORT, + (battery_ticks & 0x1) ? LED_AMBER : LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) { + led_set_color_battery(LEFT_PORT, (battery_ticks & 0x1) ? + LED_AMBER : + LED_OFF); + } + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +void led_task(void *u) +{ + uint32_t start_time; + uint32_t task_duration; + + while (1) { + start_time = get_time().le.lo; + + led_set_battery(); + + /* Compute time for this iteration */ + task_duration = get_time().le.lo - start_time; + /* + * Compute wait time required to for next desired LED tick. If + * the duration exceeds the tick time, then don't sleep. + */ + if (task_duration < LED_TICK_INTERVAL_MS) + usleep(LED_TICK_INTERVAL_MS - task_duration); + } +} diff --git a/board/anahera/pwm.c b/board/anahera/pwm.c new file mode 100644 index 0000000000..1d1747413f --- /dev/null +++ b/board/anahera/pwm.c @@ -0,0 +1,30 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/board/anahera/sensors.c b/board/anahera/sensors.c new file mode 100644 index 0000000000..6946e0cd13 --- /dev/null +++ b/board/anahera/sensors.c @@ -0,0 +1,140 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_FAN] = { + .name = "TEMP_FAN", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_SOC] = { + .name = "TEMP_SOC", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_REGULATOR] = { + .name = "TEMP_REGULATOR", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_FAN] = { .name = "Fan", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_FAN }, + [TEMP_SENSOR_2_SOC] = { .name = "SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_SOC }, + [TEMP_SENSOR_3_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER }, + [TEMP_SENSOR_4_REGULATOR] = { .name = "Regulator", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_REGULATOR }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan = THERMAL_FAN; + +/* + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to SOC, so we need to use the lower + * SOC temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_REGULATOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(55), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(60), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(48), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_regulator = + THERMAL_REGULATOR; + +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_FAN] = THERMAL_FAN, + [TEMP_SENSOR_2_SOC] = THERMAL_CPU, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, + [TEMP_SENSOR_4_REGULATOR] = THERMAL_REGULATOR, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/anahera/thermal.c b/board/anahera/thermal.c new file mode 100644 index 0000000000..b5b5a0c1cc --- /dev/null +++ b/board/anahera/thermal.c @@ -0,0 +1,146 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "fan.h" +#include "hooks.h" +#include "host_command.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +struct fan_step { + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t on[TEMP_SENSOR_COUNT]; + + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t off[TEMP_SENSOR_COUNT]; + + /* Fan 1~2 rpm */ + uint16_t rpm[FAN_CH_COUNT]; +}; + +static const struct fan_step fan_table[] = { + { + /* level 0 */ + .on = { 53, 51, 0, -1 }, + .off = { 99, 99, 99, -1 }, + .rpm = { 0 }, + }, + { + /* level 1 */ + .on = { 54, 52, 0, -1 }, + .off = { 52, 50, 99, -1 }, + .rpm = { 3000 }, + }, + { + /* level 2 */ + .on = { 55, 53, 0, -1 }, + .off = { 53, 51, 99, -1 }, + .rpm = { 3400 }, + }, + { + /* level 3 */ + .on = { 56, 54, 0, -1 }, + .off = { 54, 52, 99, -1 }, + .rpm = { 3800 }, + }, + { + /* level 4 */ + .on = { 57, 55, 54, -1 }, + .off = { 55, 53, 51, -1 }, + .rpm = { 4100 }, + }, + { + /* level 5 */ + .on = { 58, 56, 60, -1 }, + .off = { 56, 54, 52, -1 }, + .rpm = { 4400 }, + }, + { + /* level 6 */ + .on = { 100, 100, 100, -1 }, + .off = { 57, 59, 58, -1 }, + .rpm = { 4900 }, + }, +}; + +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_table) + +int fan_table_to_rpm(int fan, int *temp) +{ + static int current_level; + static int prev_tmp[TEMP_SENSOR_COUNT]; + int i; + + /* + * Compare the current and previous temperature, we have + * the three paths : + * 1. decreasing path. (check the release point) + * 2. increasing path. (check the trigger point) + * 3. invariant path. (return the current RPM) + */ + if (temp[TEMP_SENSOR_1_FAN] < prev_tmp[TEMP_SENSOR_1_FAN] || + temp[TEMP_SENSOR_2_SOC] < prev_tmp[TEMP_SENSOR_2_SOC] || + temp[TEMP_SENSOR_3_CHARGER] < prev_tmp[TEMP_SENSOR_3_CHARGER]) { + for (i = current_level; i > 0; i--) { + if (temp[TEMP_SENSOR_1_FAN] < + fan_table[i].off[TEMP_SENSOR_1_FAN] && + temp[TEMP_SENSOR_3_CHARGER] < + fan_table[i].off[TEMP_SENSOR_3_CHARGER] && + temp[TEMP_SENSOR_2_SOC] < + fan_table[i].off[TEMP_SENSOR_2_SOC]) + current_level = i - 1; + else + break; + } + } else if (temp[TEMP_SENSOR_1_FAN] > prev_tmp[TEMP_SENSOR_1_FAN] || + temp[TEMP_SENSOR_2_SOC] > prev_tmp[TEMP_SENSOR_2_SOC] || + temp[TEMP_SENSOR_3_CHARGER] > + prev_tmp[TEMP_SENSOR_3_CHARGER]) { + for (i = current_level; i < NUM_FAN_LEVELS; i++) { + if ((temp[TEMP_SENSOR_1_FAN] > + fan_table[i].on[TEMP_SENSOR_1_FAN] && + temp[TEMP_SENSOR_3_CHARGER] > + fan_table[i].on[TEMP_SENSOR_3_CHARGER]) || + temp[TEMP_SENSOR_2_SOC] > + fan_table[i].on[TEMP_SENSOR_2_SOC]) + current_level = i + 1; + else + break; + } + } + + if (current_level < 0) + current_level = 0; + + if (current_level >= NUM_FAN_LEVELS) + current_level = NUM_FAN_LEVELS - 1; + + for (i = 0; i < TEMP_SENSOR_COUNT; ++i) + prev_tmp[i] = temp[i]; + + return fan_table[current_level].rpm[FAN_CH_0]; +} + +void board_override_fan_control(int fan, int *tmp) +{ + if (chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND)) { + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), fan_table_to_rpm(fan, tmp)); + } +} diff --git a/board/anahera/usbc_config.c b/board/anahera/usbc_config.c new file mode 100644 index 0000000000..907f236d70 --- /dev/null +++ b/board/anahera/usbc_config.c @@ -0,0 +1,448 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/retimer/ps8811.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_4_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .frs_en = IOEX_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C1 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C1_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_4_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = IOEX_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C1) { + rst_signal = IOEX_USB_C1_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 0); + gpio_set_level(GPIO_USB_C1_TCPC_RST_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + msleep(NCT38XX_RESET_HOLD_DELAY_MS); + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_TCPC_RST_ODL, 1); + + nct38xx_reset_notify(USBC_PORT_C0); + nct38xx_reset_notify(USBC_PORT_C1); + + /* wait for chips to come up */ + if (NCT3807_RESET_POST_DELAY_MS != 0) + msleep(NCT3807_RESET_POST_DELAY_MS); +} + +static void board_tcpc_init(void) +{ + int i; + + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C1 TCPCs, so they must be set up after the TCPCs has + * been taken out of reset. + */ + for (i = 0; i < CONFIG_IO_EXPANDER_PORT_COUNT; ++i) + ioex_init(i); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +const struct usb_mux usba_ps8811[] = { + [USBA_PORT_A0] = { + .usb_port = USBA_PORT_A0, + .i2c_port = I2C_PORT_USB_A0_RETIMER, + .i2c_addr_flags = PS8811_I2C_ADDR_FLAGS0, + }, + [USBA_PORT_A1] = { + .usb_port = USBA_PORT_A1, + .i2c_port = I2C_PORT_USB_A1_RETIMER, + .i2c_addr_flags = PS8811_I2C_ADDR_FLAGS0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usba_ps8811) == USBA_PORT_COUNT); + +const static struct ps8811_reg_val equalizer_wwan_table[] = { + { + /* Set channel A EQ setting */ + .reg = PS8811_REG1_USB_AEQ_LEVEL, + .val = (PS8811_AEQ_I2C_LEVEL_UP_13DB + << PS8811_AEQ_I2C_LEVEL_UP_SHIFT) | + (PS8811_AEQ_PIN_LEVEL_UP_18DB + << PS8811_AEQ_PIN_LEVEL_UP_SHIFT), + }, + { + /* Set ADE pin setting */ + .reg = PS8811_REG1_USB_ADE_CONFIG, + .val = (PS8811_ADE_PIN_MID_LEVEL_3DB + << PS8811_ADE_PIN_MID_LEVEL_SHIFT) | + PS8811_AEQ_CONFIG_REG_ENABLE | + PS8811_AEQ_ADAPTIVE_REG_ENABLE, + }, + { + /* Set channel B EQ setting */ + .reg = PS8811_REG1_USB_BEQ_LEVEL, + .val = (PS8811_BEQ_I2C_LEVEL_UP_10P5DB + << PS8811_BEQ_I2C_LEVEL_UP_SHIFT) | + (PS8811_BEQ_PIN_LEVEL_UP_18DB + << PS8811_BEQ_PIN_LEVEL_UP_SHIFT), + }, + { + /* Set BDE pin setting */ + .reg = PS8811_REG1_USB_BDE_CONFIG, + .val = (PS8811_BDE_PIN_MID_LEVEL_3DB + << PS8811_BDE_PIN_MID_LEVEL_SHIFT) | + PS8811_BEQ_CONFIG_REG_ENABLE, + }, +}; + +#define NUM_EQ_WWAN_ARRAY ARRAY_SIZE(equalizer_wwan_table) + +const static struct ps8811_reg_val equalizer_wlan_table[] = { + { + /* Set 50ohm adjust for B channel */ + .reg = PS8811_REG1_50OHM_ADJUST_CHAN_B, + .val = (PS8811_50OHM_ADJUST_CHAN_B_MINUS_9PCT + << PS8811_50OHM_ADJUST_CHAN_B_SHIFT), + }, +}; + +#define NUM_EQ_WLAN_ARRAY ARRAY_SIZE(equalizer_wlan_table) + +static int usba_retimer_init(int port) +{ + int rv; + int val; + int i; + const struct usb_mux *me = &usba_ps8811[port]; + + rv = ps8811_i2c_read(me, PS8811_REG_PAGE1, PS8811_REG1_USB_BEQ_LEVEL, + &val); + + switch (port) { + case USBA_PORT_A0: + /* Set channel A output swing */ + rv = ps8811_i2c_field_update(me, PS8811_REG_PAGE1, + PS8811_REG1_USB_CHAN_A_SWING, + PS8811_CHAN_A_SWING_MASK, + 0x2 << PS8811_CHAN_A_SWING_SHIFT); + break; + case USBA_PORT_A1: + if (ec_cfg_has_lte()) { + /* Set channel A output swing */ + rv = ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, + PS8811_REG1_USB_CHAN_A_SWING, + PS8811_CHAN_A_SWING_MASK, + 0x2 << PS8811_CHAN_A_SWING_SHIFT); + + /* Set channel B output PS level */ + rv |= ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, + PS8811_REG1_USB_CHAN_B_DE_PS_LSB, + PS8811_CHAN_B_DE_PS_LSB_MASK, 0x06); + + /* Set channel B output DE level */ + rv |= ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, + PS8811_REG1_USB_CHAN_B_DE_PS_MSB, + PS8811_CHAN_B_DE_PS_MSB_MASK, 0x16); + + for (i = 0; i < NUM_EQ_WWAN_ARRAY; i++) + rv |= ps8811_i2c_write( + me, PS8811_REG_PAGE1, + equalizer_wwan_table[i].reg, + equalizer_wwan_table[i].val); + } else { + /* Set channel A output swing */ + rv = ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, + PS8811_REG1_USB_CHAN_A_SWING, + PS8811_CHAN_A_SWING_MASK, + 0x2 << PS8811_CHAN_A_SWING_SHIFT); + + for (i = 0; i < NUM_EQ_WLAN_ARRAY; i++) + rv |= ps8811_i2c_write( + me, PS8811_REG_PAGE1, + equalizer_wlan_table[i].reg, + equalizer_wlan_table[i].val); + } + break; + } + + return rv; +} + +void board_chipset_startup(void) +{ + int i; + + for (i = 0; i < USBA_PORT_COUNT; ++i) + usba_retimer_init(i); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); diff --git a/board/anahera/usbc_config.h b/board/anahera/usbc_config.h new file mode 100644 index 0000000000..c476919027 --- /dev/null +++ b/board/anahera/usbc_config.h @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Anahera board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* USB-A ports */ +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; + +/* USB-C ports */ +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +struct ps8811_reg_val { + uint8_t reg; + uint16_t val; +}; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/anahera/vif_override.xml b/board/anahera/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/anahera/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/arcada_ish/board.c b/board/arcada_ish/board.c index 624a376dca..efd0f8a0ca 100644 --- a/board/arcada_ish/board.c +++ b/board/arcada_ish/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,7 +19,8 @@ #include "tablet_mode.h" #include "task.h" -#include "gpio_list.h" /* has to be included last */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /* I2C port map */ const struct i2c_port_t i2c_ports[] = { @@ -42,11 +43,9 @@ static struct stprivate_data g_lis2dh_data; static struct lis2mdl_private_data lis2mdl_a_data; /* Matrix to rotate lid sensor into standard reference frame */ -const mat33_fp_t lid_rot_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t lid_rot_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* Drivers */ struct motion_sensor_t motion_sensors[] = { @@ -60,8 +59,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_lid_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_a_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_ACCEL_GYRO_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR1_FLAGS, .rot_standard_ref = &lid_rot_ref, @@ -90,8 +87,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_lid_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_a_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_ACCEL_GYRO_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR1_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -159,8 +154,7 @@ int board_sensor_at_360(void) * closed at 0 degrees. Ignore the hall sensor when the lid close is * also active. */ - return lid_is_open() && - !gpio_get_level(GMR_TABLET_MODE_GPIO_L); + return lid_is_open() && !gpio_get_level(GPIO_TABLET_MODE_L); } /* Initialize board. */ diff --git a/board/arcada_ish/board.h b/board/arcada_ish/board.h index ca69c1ba15..129640d60f 100644 --- a/board/arcada_ish/board.h +++ b/board/arcada_ish/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,24 +16,23 @@ #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* ISH specific*/ -#undef CONFIG_DEBUG_ASSERT +#undef CONFIG_DEBUG_ASSERT #define CONFIG_CLOCK_CRYSTAL /* EC */ -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER - -#define CONFIG_ACCEL_LNG2DM /* Base sensor: LNG2DM - * (uses LIS2DH driver) - */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Lid sensor: LSM6DS3 - * (uses LSM6DSM driver) - */ -#define CONFIG_MAG_LIS2MDL /* Lid sensor: LIS2DML */ +#define CONFIG_I2C_CONTROLLER + +#define CONFIG_ACCEL_LNG2DM /* Base sensor: LNG2DM \ + * (uses LIS2DH driver) \ + */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Lid sensor: LSM6DS3 \ + * (uses LSM6DSM driver) \ + */ +#define CONFIG_MAG_LIS2MDL /* Lid sensor: LIS2DML */ #define CONFIG_MAG_CALIBRATE -#define CONFIG_ACCEL_INTERRUPTS /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO /* FIFO size is a power of 2. */ @@ -41,7 +40,7 @@ /* Depends on how fast the AP boots and typical ODRs. */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) /* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(BASE_ACCEL) | BIT(LID_MAG)) +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(BASE_ACCEL) | BIT(LID_MAG)) #define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) @@ -56,13 +55,12 @@ #define CONFIG_TABLET_MODE #define CONFIG_GMR_TABLET_MODE #define CONFIG_GMR_TABLET_MODE_CUSTOM -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L /* DMA paging between SRAM and DRAM */ #define CONFIG_DMA_PAGING /* Host command over HECI */ -#define CONFIG_HOSTCMD_HECI +#define CONFIG_HOST_INTERFACE_HECI /* I2C ports */ #define I2C_PORT_SENSOR ISH_I2C0 @@ -82,7 +80,7 @@ #undef CONFIG_CMD_SHMEM #undef CONFIG_EXTPOWER #undef CONFIG_KEYBOARD_KSO_BASE -#undef CONFIG_FLASH +#undef CONFIG_FLASH_CROS #undef CONFIG_FMAP #undef CONFIG_SWITCH @@ -101,8 +99,8 @@ #define CONFIG_ISH_PM_D3 #define CONFIG_ISH_PM_RESET_PREP -#define CONFIG_ISH_D0I2_MIN_USEC (15*MSEC) /* need final tune */ -#define CONFIG_ISH_D0I3_MIN_USEC (100*MSEC) /* need final tune */ +#define CONFIG_ISH_D0I2_MIN_USEC (15 * MSEC) /* need final tune */ +#define CONFIG_ISH_D0I3_MIN_USEC (100 * MSEC) /* need final tune */ #ifndef __ASSEMBLER__ @@ -114,13 +112,7 @@ * Note: Since we aren't using LPC memory map to transmit sensor data, the * order of this enum does not need to be accel, accel, gyro */ -enum sensor_id { - LID_ACCEL, - LID_GYRO, - BASE_ACCEL, - LID_MAG, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, LID_GYRO, BASE_ACCEL, LID_MAG, SENSOR_COUNT }; #endif /* !__ASSEMBLER__ */ diff --git a/board/arcada_ish/build.mk b/board/arcada_ish/build.mk index a57c08e6ba..80cf4886eb 100644 --- a/board/arcada_ish/build.mk +++ b/board/arcada_ish/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/arcada_ish/ec.tasklist b/board/arcada_ish/ec.tasklist index d72fdf309e..81d3c5dc20 100644 --- a/board/arcada_ish/ec.tasklist +++ b/board/arcada_ish/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/arcada_ish/gpio.inc b/board/arcada_ish/gpio.inc index 336f807269..6a577d0efe 100644 --- a/board/arcada_ish/gpio.inc +++ b/board/arcada_ish/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/asurada/battery.c b/board/asurada/battery.c index f8fc47034f..ad49477366 100644 --- a/board/asurada/battery.c +++ b/board/asurada/battery.c @@ -1,11 +1,17 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "battery.h" #include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_manager.h" +#include "chipset.h" #include "gpio.h" +#include "hooks.h" +#include "system.h" +#include "usb_pd.h" const struct board_batt_params board_battery_info[] = { [BATTERY_C235] = { diff --git a/board/asurada/board.c b/board/asurada/board.c index 712a89289e..a9b5e0aab4 100644 --- a/board/asurada/board.c +++ b/board/asurada/board.c @@ -1,31 +1,24 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Asurada board configuration */ #include "adc.h" -#include "adc_chip.h" -#include "board/asurada/it5205_sbu.h" #include "button.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" #include "common.h" #include "console.h" #include "driver/accel_lis2dw12.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/als_tcs3400.h" -#include "driver/bc12/mt6360.h" -#include "driver/bc12/pi3usb9201.h" -#include "driver/charger/isl923x.h" -#include "driver/ppc/syv682x.h" #include "driver/tcpm/it83xx_pd.h" #include "driver/temp_sensor/thermistor.h" -#include "driver/usb_mux/it5205.h" -#include "driver/usb_mux/ps8743.h" -#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "i2c.h" @@ -33,7 +26,6 @@ #include "lid_switch.h" #include "motion_sense.h" #include "power.h" -#include "power_button.h" #include "pwm.h" #include "pwm_chip.h" #include "regulator.h" @@ -44,583 +36,47 @@ #include "temp_sensor.h" #include "timer.h" #include "uart.h" -#include "usb_charge.h" -#include "usb_mux.h" -#include "usb_pd_tcpm.h" -#include "usbc_ppc.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -static void bc12_interrupt(enum gpio_signal signal); -static void ppc_interrupt(enum gpio_signal signal); -static void x_ec_interrupt(enum gpio_signal signal); - -#include "gpio_list.h" - -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = ISL923X_ADDR_FLAGS, - .drv = &isl923x_drv, - }, -}; - -/* - * PWM channels. Must be in the exactly same order as in enum pwm_channel. - * There total three 16 bits clock prescaler registers for all pwm channels, - * so use the same frequency and prescaler register setting is required if - * number of pwm channel greater than three. - */ -const struct pwm_t pwm_channels[] = { - [PWM_CH_LED1] = { - .channel = 0, - .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, - .freq_hz = 324, /* maximum supported frequency */ - .pcfsr_sel = PWM_PRESCALER_C4 - }, - [PWM_CH_LED2] = { - .channel = 1, - .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, - .freq_hz = 324, /* maximum supported frequency */ - .pcfsr_sel = PWM_PRESCALER_C4 - }, - [PWM_CH_LED3] = { - .channel = 2, - .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, - .freq_hz = 324, /* maximum supported frequency */ - .pcfsr_sel = PWM_PRESCALER_C4 - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -/* Wake-up pins for hibernate */ -enum gpio_signal hibernate_wake_pins[] = { - GPIO_AC_PRESENT, - GPIO_LID_OPEN, - GPIO_POWER_BUTTON_L, -}; -int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); - -__override void board_hibernate_late(void) -{ - /* - * Turn off PP5000_A. Required for devices without Z-state. - * Don't care for devices with Z-state. - */ - gpio_set_level(GPIO_EN_PP5000_A, 0); - - /* - * GPIO_EN_SLP_Z not implemented in rev0/1, - * fallback to usual hibernate process. - */ - if (board_get_version() <= 1) - return; - - isl9238c_hibernate(CHARGER_SOLO); - - gpio_set_level(GPIO_EN_SLP_Z, 1); - - /* should not reach here */ - __builtin_unreachable(); -} - -/* power signal list. Must match order of enum power_signal. */ -const struct power_signal_info power_signal_list[] = { - {GPIO_PMIC_EC_PWRGD, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_AP_EC_WATCHDOG_L, - POWER_SIGNAL_ACTIVE_LOW | POWER_SIGNAL_DISABLE_AT_BOOT, - "AP_WDT_ASSERTED"}, -}; -BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); - -/* Detect subboard */ -static enum board_sub_board board_get_sub_board(void); /* Initialize board. */ static void board_init(void) { - /* For Rev0 only. Set GPM0~6 1.8V input. */ - IT83XX_GPIO_GCR30 |= BIT(4); - - gpio_enable_interrupt(GPIO_AC_PRESENT); - - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); - /* Enable motion sensor interrupt */ gpio_enable_interrupt(GPIO_BASE_IMU_INT_L); gpio_enable_interrupt(GPIO_LID_ACCEL_INT_L); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -static void board_tcpc_init(void) -{ - gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); - /* C1: GPIO_USB_C1_PPC_INT_ODL & HDMI: GPIO_PS185_EC_DP_HPD */ - gpio_enable_interrupt(GPIO_X_EC_GPIO2); - - /* If this is not a Type-C subboard, disable the task. */ - if (board_get_sub_board() != SUB_BOARD_TYPEC) - task_disable_task(TASK_ID_PD_C1); -} -/* Must be done after I2C and subboard */ -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); - -/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ -const struct adc_t adc_channels[] = { - /* Convert to mV (3000mV/1024). */ - {"VBUS", ADC_MAX_MVOLT * 10, ADC_READ_MAX + 1, 0, CHIP_ADC_CH0}, - {"BOARD_ID_0", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH1}, - {"BOARD_ID_1", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH2}, - {"CHARGER_AMON_R", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH3}, - {"CHARGER_PMON", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH6}, -}; -BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - -/* BC12 */ -const struct mt6360_config_t mt6360_config = { - .i2c_port = 0, - .i2c_addr_flags = MT6360_PMU_SLAVE_ADDR_FLAGS, -}; - -const struct pi3usb9201_config_t - pi3usb9201_bc12_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { - /* [0]: unused */ - [1] = { - .i2c_port = 4, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - } -}; - -struct bc12_config bc12_ports[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { .drv = &mt6360_drv }, - { .drv = &pi3usb9201_drv }, -}; - -static void bc12_interrupt(enum gpio_signal signal) -{ - if (signal == GPIO_USB_C0_BC12_INT_ODL) - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); - else - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); -} - -static void board_sub_bc12_init(void) -{ - if (board_get_sub_board() == SUB_BOARD_TYPEC) - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); - else - /* If this is not a Type-C subboard, disable the task. */ - task_disable_task(TASK_ID_USB_CHG_P1); -} -/* Must be done after I2C and subboard */ -DECLARE_HOOK(HOOK_INIT, board_sub_bc12_init, HOOK_PRIO_INIT_I2C + 1); - -/* - * I2C channels (A, B, and C) are using the same timing registers (00h~07h) - * at default. - * In order to set frequency independently for each channels, - * We use timing registers 09h~0Bh, and the supported frequency will be: - * 50KHz, 100KHz, 400KHz, or 1MHz. - * I2C channels (D, E and F) can be set different frequency on different ports. - * The I2C(D/E/F) frequency depend on the frequency of SMBus Module and - * the individual prescale register. - * The frequency of SMBus module is 24MHz on default. - * The allowed range of I2C(D/E/F) frequency is as following setting. - * SMBus Module Freq = PLL_CLOCK / ((IT83XX_ECPM_SCDCR2 & 0x0F) + 1) - * (SMBus Module Freq / 510) <= I2C Freq <= (SMBus Module Freq / 8) - * Channel D has multi-function and can be used as UART interface. - * Channel F is reserved for EC debug. - */ - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"bat_chg", IT83XX_I2C_CH_A, 100, GPIO_I2C_A_SCL, GPIO_I2C_A_SDA}, - {"sensor", IT83XX_I2C_CH_B, 100, GPIO_I2C_B_SCL, GPIO_I2C_B_SDA}, - {"usb0", IT83XX_I2C_CH_C, 100, GPIO_I2C_C_SCL, GPIO_I2C_C_SDA}, - {"usb1", IT83XX_I2C_CH_E, 100, GPIO_I2C_E_SCL, GPIO_I2C_E_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -int board_allow_i2c_passthru(int port) -{ - return (port == I2C_PORT_VIRTUAL_BATTERY); -} - -/* PPC */ -struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .i2c_port = I2C_PORT_PPC0, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - .frs_en = GPIO_USB_C0_FRS_EN, - }, - { - .i2c_port = I2C_PORT_PPC1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - .frs_en = GPIO_USB_C1_FRS_EN, - }, -}; -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -static void ppc_interrupt(enum gpio_signal signal) -{ - if (signal == GPIO_USB_C0_PPC_INT_ODL) - /* C0: PPC interrupt */ - syv682x_interrupt(0); -} - -int debounced_hpd; - -/** - * Handle PS185 HPD changing state. - */ -static void ps185_hdmi_hpd_deferred(void) -{ - const int new_hpd = gpio_get_level(GPIO_PS185_EC_DP_HPD); - - /* HPD status not changed, probably a glitch, just return. */ - if (debounced_hpd == new_hpd) - return; - - debounced_hpd = new_hpd; - - gpio_set_level(GPIO_EC_DPBRDG_HPD_ODL, !debounced_hpd); - CPRINTS(debounced_hpd ? "HDMI plug" : "HDMI unplug"); -} -DECLARE_DEFERRED(ps185_hdmi_hpd_deferred); - -#define PS185_HPD_DEBOUCE 250 - -static void hdmi_hpd_interrupt(enum gpio_signal signal) -{ - hook_call_deferred(&ps185_hdmi_hpd_deferred_data, PS185_HPD_DEBOUCE); -} - -/* HDMI/TYPE-C function shared subboard interrupt */ -static void x_ec_interrupt(enum gpio_signal signal) -{ - int sub = board_get_sub_board(); - - if (sub == SUB_BOARD_TYPEC) - /* C1: PPC interrupt */ - syv682x_interrupt(1); - else if (sub == SUB_BOARD_HDMI) - hdmi_hpd_interrupt(signal); - else - CPRINTS("Undetected subboard interrupt."); -} - -int ppc_get_alert_status(int port) -{ - if (port == 0) - return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; - if (port == 1 && board_get_sub_board() == SUB_BOARD_TYPEC) - return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; - - return 0; -} - -void board_overcurrent_event(int port, int is_overcurrented) -{ - /* TODO: check correct operation for Asurada */ -} - -/* TCPC */ -const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .bus_type = EC_BUS_TYPE_EMBEDDED, - /* TCPC is embedded within EC so no i2c config needed */ - .drv = &it83xx_tcpm_drv, - /* Alert is active-low, push-pull */ - .flags = 0, - }, - { - .bus_type = EC_BUS_TYPE_EMBEDDED, - /* TCPC is embedded within EC so no i2c config needed */ - .drv = &it83xx_tcpm_drv, - /* Alert is active-low, push-pull */ - .flags = 0, - }, -}; - -uint16_t tcpc_get_alert_status(void) -{ - /* - * C0 & C1: TCPC is embedded in the EC and processes interrupts in the - * chip code (it83xx/intc.c) - */ - return 0; -} +/* Sensor */ +static struct mutex g_base_mutex; +static struct mutex g_lid_mutex; -void board_reset_pd_mcu(void) -{ - /* - * C0 & C1: TCPC is embedded in the EC and processes interrupts in the - * chip code (it83xx/intc.c) - */ -} +static struct bmi_drv_data_t g_bmi160_data; +static struct stprivate_data g_lis2dwl_data; +static struct icm_drv_data_t g_icm426xx_data; -/* USB-A */ -const int usb_port_enable[] = { - GPIO_EN_PP5000_USB_A0_VBUS, +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI160 = 1, + BASE_GYRO_ICM426XX = 2, }; -BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); - -/* USB Mux */ -static int board_ps8743_mux_set(const struct usb_mux *me, - mux_state_t mux_state) -{ - int rv = EC_SUCCESS; - int reg = 0; - - rv = ps8743_read(me, PS8743_REG_MODE, ®); - if (rv) - return rv; - - /* Disable FLIP pin, enable I2C control. */ - reg |= PS8743_MODE_FLIP_REG_CONTROL; - /* Disable CE_USB pin, enable I2C control. */ - reg |= PS8743_MODE_USB_REG_CONTROL; - /* Disable CE_DP pin, enable I2C control. */ - reg |= PS8743_MODE_DP_REG_CONTROL; - - /* - * DP specific config - * - * Enable/Disable IN_HPD on the DB. - */ - gpio_set_level(GPIO_USB_C1_DP_IN_HPD, - mux_state & USB_PD_MUX_DP_ENABLED); - return ps8743_write(me, PS8743_REG_MODE, reg); -} +static enum base_accelgyro_type base_accelgyro_config; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX0, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - }, - { - .usb_port = 1, - .i2c_port = I2C_PORT_USB_MUX1, - .i2c_addr_flags = PS8743_I2C_ADDR0_FLAG, - .driver = &ps8743_usb_mux_driver, - .board_set = &board_ps8743_mux_set, - }, +#ifdef BOARD_ASURADA_REV0 +/* Matrix to rotate accelerometer into standard reference frame */ +/* for rev 0 */ +static const mat33_fp_t base_standard_ref_rev0 = { + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) }, }; -int board_set_active_charge_port(int port) -{ - int i; - int is_valid_port = port == 0 || (port == 1 && board_get_sub_board() == - SUB_BOARD_TYPEC); - - if (!is_valid_port && port != CHARGE_PORT_NONE) - return EC_ERROR_INVAL; - - if (port == CHARGE_PORT_NONE) { - CPRINTS("Disabling all charger ports"); - - /* Disable all ports. */ - for (i = 0; i < ppc_cnt; i++) { - /* - * Do not return early if one fails otherwise we can - * get into a boot loop assertion failure. - */ - if (ppc_vbus_sink_enable(i, 0)) - CPRINTS("Disabling C%d as sink failed.", i); - } - - return EC_SUCCESS; - } - - /* Check if the port is sourcing VBUS. */ - if (ppc_is_sourcing_vbus(port)) { - CPRINTF("Skip enable C%d", port); - return EC_ERROR_INVAL; - } - - CPRINTS("New charge port: C%d", port); - - /* - * Turn off the other ports' sink path FETs, before enabling the - * requested charge port. - */ - for (i = 0; i < ppc_cnt; i++) { - if (i == port) - continue; - - if (ppc_vbus_sink_enable(i, 0)) - CPRINTS("C%d: sink path disable failed.", i); - } - - /* Enable requested charge port. */ - if (ppc_vbus_sink_enable(port, 1)) { - CPRINTS("C%d: sink path enable failed.", port); - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit( - MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - -void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) -{ - /* - * We ignore the cc_pin and PPC vconn because polarity and PPC vconn - * should already be set correctly in the PPC driver via the pd - * state machine. - */ -} - -/* Called on AP S3 -> S0 transition */ -static void board_chipset_resume(void) -{ - gpio_set_level(GPIO_EC_BL_EN_OD, 1); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); - -/* Called on AP S0 -> S3 transition */ -static void board_chipset_suspend(void) -{ - gpio_set_level(GPIO_EC_BL_EN_OD, 0); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); - -/* Sub-board */ - -static enum board_sub_board board_get_sub_board(void) -{ - static enum board_sub_board sub = SUB_BOARD_NONE; - - if (sub != SUB_BOARD_NONE) - return sub; - - /* HDMI board has external pull high. */ - if (gpio_get_level(GPIO_EC_X_GPIO3)) { - sub = SUB_BOARD_HDMI; - /* Only has 1 PPC with HDMI subboard */ - ppc_cnt = 1; - /* EC_X_GPIO1 */ - gpio_set_flags(GPIO_EN_HDMI_PWR, GPIO_OUT_HIGH); - /* X_EC_GPIO2 */ - gpio_set_flags(GPIO_PS185_EC_DP_HPD, GPIO_INT_BOTH); - /* EC_X_GPIO3 */ - gpio_set_flags(GPIO_PS185_PWRDN_ODL, GPIO_ODR_HIGH); - } else { - sub = SUB_BOARD_TYPEC; - /* EC_X_GPIO1 */ - gpio_set_flags(GPIO_USB_C1_FRS_EN, GPIO_OUT_LOW); - /* X_EC_GPIO2 */ - gpio_set_flags(GPIO_USB_C1_PPC_INT_ODL, - GPIO_INT_BOTH | GPIO_PULL_UP); - /* EC_X_GPIO3 */ - gpio_set_flags(GPIO_USB_C1_DP_IN_HPD, GPIO_OUT_LOW); - } - - CPRINTS("Detect %s SUB", sub == SUB_BOARD_HDMI ? "HDMI" : "TYPEC"); - return sub; -} - -static void sub_board_init(void) -{ - board_get_sub_board(); -} -DECLARE_HOOK(HOOK_INIT, sub_board_init, HOOK_PRIO_INIT_I2C - 1); - -__override uint8_t board_get_usb_pd_port_count(void) -{ - if (board_get_sub_board() == SUB_BOARD_TYPEC) - return CONFIG_USB_PD_PORT_MAX_COUNT; - else - return CONFIG_USB_PD_PORT_MAX_COUNT - 1; -} - -/* Lid */ -#ifndef TEST_BUILD -/* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) -{ - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); - - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif - -/* SD Card */ -int board_regulator_get_info(uint32_t index, char *name, - uint16_t *num_voltages, uint16_t *voltages_mv) -{ - enum mt6360_regulator_id id = index; - - return mt6360_regulator_get_info(id, name, num_voltages, - voltages_mv); -} - -int board_regulator_enable(uint32_t index, uint8_t enable) -{ - enum mt6360_regulator_id id = index; - - return mt6360_regulator_enable(id, enable); -} - -int board_regulator_is_enabled(uint32_t index, uint8_t *enabled) -{ - enum mt6360_regulator_id id = index; - - return mt6360_regulator_is_enabled(id, enabled); -} - -int board_regulator_set_voltage(uint32_t index, uint32_t min_mv, - uint32_t max_mv) -{ - enum mt6360_regulator_id id = index; - - return mt6360_regulator_set_voltage(id, min_mv, max_mv); -} - -int board_regulator_get_voltage(uint32_t index, uint32_t *voltage_mv) +static void update_rotation_matrix(void) { - enum mt6360_regulator_id id = index; - - return mt6360_regulator_get_voltage(id, voltage_mv); + motion_sensors[BASE_ACCEL].rot_standard_ref = &base_standard_ref_rev0; + motion_sensors[BASE_GYRO].rot_standard_ref = &base_standard_ref_rev0; } - -/* Sensor */ -static struct mutex g_base_mutex; -static struct mutex g_lid_mutex; - -static struct bmi_drv_data_t g_bmi160_data; -static struct stprivate_data g_lis2dwl_data; - -/* Matrix to rotate accelrator into standard reference frame */ -/* TODO: update the matrix after we have assembled unit */ -static const mat33_fp_t mag_standard_ref = { - {0, FLOAT_TO_FP(-1), 0}, - {FLOAT_TO_FP(-1), 0, 0}, - {0, 0, FLOAT_TO_FP(-1)}, -}; +DECLARE_HOOK(HOOK_INIT, update_rotation_matrix, HOOK_PRIO_INIT_ADC + 2); /* TCS3400 private data */ static struct als_drv_data_t g_tcs3400_data = { @@ -633,25 +89,6 @@ static struct als_drv_data_t g_tcs3400_data = { }, }; -#ifdef BOARD_ASURADA -/* Matrix to rotate accelerometer into standard reference frame */ -/* for rev 0 */ -static const mat33_fp_t base_standard_ref_rev0 = { - {FLOAT_TO_FP(-1), 0, 0}, - {0, FLOAT_TO_FP(1), 0}, - {0, 0, FLOAT_TO_FP(-1)}, -}; - -static void update_rotation_matrix(void) -{ - motion_sensors[BASE_ACCEL].rot_standard_ref = - &base_standard_ref_rev0; - motion_sensors[BASE_GYRO].rot_standard_ref = - &base_standard_ref_rev0; -} -DECLARE_HOOK(HOOK_INIT, update_rotation_matrix, HOOK_PRIO_INIT_ADC + 1); -#endif - static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { /* * TODO: calculate the actual coefficients and scaling factors @@ -693,6 +130,75 @@ static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { .saturation.again = TCS_DEFAULT_AGAIN, .saturation.atime = TCS_DEFAULT_ATIME, }; +#endif /* BOARD_ASURADA_REV0 */ + +#ifdef BOARD_HAYATO +/* Matrix to rotate accelerometer into standard reference frame */ +/* for Hayato */ +static const mat33_fp_t base_standard_ref = { + { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) }, +}; + +static void update_rotation_matrix(void) +{ + if (base_accelgyro_config == BASE_GYRO_ICM426XX) + return; + + if (board_get_version() >= 2) { + motion_sensors[BASE_ACCEL].rot_standard_ref = + &base_standard_ref; + motion_sensors[BASE_GYRO].rot_standard_ref = &base_standard_ref; + } +} +DECLARE_HOOK(HOOK_INIT, update_rotation_matrix, HOOK_PRIO_INIT_ADC + 2); + +#endif + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs. */ + .rot_standard_ref = NULL, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = NULL, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; struct motion_sensor_t motion_sensors[] = { /* @@ -744,22 +250,6 @@ struct motion_sensor_t motion_sensors[] = { .min_frequency = BMI_GYRO_MIN_FREQ, .max_frequency = BMI_GYRO_MAX_FREQ, }, - [BASE_MAG] = { - .name = "Base Mag", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMI160, - .type = MOTIONSENSE_TYPE_MAG, - .location = MOTIONSENSE_LOC_BASE, - .drv = &bmi160_drv, - .mutex = &g_base_mutex, - .drv_data = &g_bmi160_data, - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .default_range = BIT(11), /* 16LSB / uT, fixed */ - .rot_standard_ref = &mag_standard_ref, - .min_frequency = BMM150_MAG_MIN_FREQ, - .max_frequency = BMM150_MAG_MAX_FREQ(SPECIAL), - }, [LID_ACCEL] = { .name = "Lid Accel", .active_mask = SENSOR_ACTIVE_S0_S3, @@ -769,10 +259,8 @@ struct motion_sensor_t motion_sensors[] = { .drv = &lis2dw12_drv, .mutex = &g_lid_mutex, .drv_data = &g_lis2dwl_data, - .int_signal = GPIO_LID_ACCEL_INT_L, .port = I2C_PORT_ACCEL, .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .rot_standard_ref = NULL, /* identity matrix */ .default_range = 2, /* g */ .min_frequency = LIS2DW12_ODR_MIN_VAL, @@ -788,6 +276,7 @@ struct motion_sensor_t motion_sensors[] = { }, }, }, +#ifdef BOARD_ASURADA_REV0 [CLEAR_ALS] = { .name = "Clear Light", .active_mask = SENSOR_ACTIVE_S0_S3, @@ -823,5 +312,89 @@ struct motion_sensor_t motion_sensors[] = { .min_frequency = 0, .max_frequency = 0, }, +#endif /* BOARD_ASURADA_REV0 */ }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void motion_interrupt(enum gpio_signal signal) +{ + if (base_accelgyro_config == BASE_GYRO_ICM426XX) + icm426xx_interrupt(signal); + else + bmi160_interrupt(signal); +} + +static void board_detect_motionsense(void) +{ + int val; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + if (base_accelgyro_config != BASE_GYRO_NONE) + return; + + icm_read8(&icm426xx_base_accel, ICM426XX_REG_WHO_AM_I, &val); + if (val == ICM426XX_CHIP_ICM40608) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + base_accelgyro_config = BASE_GYRO_ICM426XX; + ccprints("Base Accelgyro: ICM426XX"); + } else { + base_accelgyro_config = BASE_GYRO_BMI160; + ccprints("Base Accelgyro: BMI160"); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsense, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsense, HOOK_PRIO_DEFAULT); + +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + /* Convert to mV (3000mV/1024). */ + { "VBUS_C0", ADC_MAX_MVOLT * 10, ADC_READ_MAX + 1, 0, CHIP_ADC_CH0 }, + { "BOARD_ID_0", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH1 }, + { "BOARD_ID_1", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH2 }, + /* AMON/BMON gain = 17.97 */ + { "CHARGER_AMON_R", ADC_MAX_MVOLT * 1000 / 17.97, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH3 }, + { "VBUS_C1", ADC_MAX_MVOLT * 10, ADC_READ_MAX + 1, 0, CHIP_ADC_CH5 }, + { "CHARGER_PMON", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH6 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* PWM */ + +/* + * PWM channels. Must be in the exactly same order as in enum pwm_channel. + * There total three 16 bits clock prescaler registers for all pwm channels, + * so use the same frequency and prescaler register setting is required if + * number of pwm channel greater than three. + */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED1] = { .channel = 0, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4 }, + [PWM_CH_LED2] = { .channel = 1, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4 }, + [PWM_CH_LED3] = { .channel = 2, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_suspend(void) +{ + if (board_get_version() >= 3) + gpio_set_level(GPIO_EN_5V_USM, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + +static void board_resume(void) +{ + if (board_get_version() >= 3) + gpio_set_level(GPIO_EN_5V_USM, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); diff --git a/board/asurada/board.h b/board/asurada/board.h index 26e74ae78f..619be7cb5d 100644 --- a/board/asurada/board.h +++ b/board/asurada/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,215 +7,93 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H +#include "baseboard.h" + /* Chipset config */ -#define CONFIG_BOARD_RESET_AFTER_POWER_ON -#define CONFIG_BRINGUP -#define CONFIG_CHIPSET_MT8192 -#define CONFIG_CMD_POWERINDEBUG -#define CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC -#define CONFIG_POWER_COMMON /* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED -#define CONFIG_BOARD_VERSION_CUSTOM -#define CONFIG_EXTPOWER_GPIO +#define CONFIG_LTO + /* * TODO: Remove this option once the VBAT no longer keeps high when * system's power isn't presented. */ #define CONFIG_IT83XX_RESET_PD_CONTRACT_IN_BRAM -#define CONFIG_LOW_POWER_IDLE -#define CONFIG_LOW_POWER_S0 -#define CONFIG_POWER_BUTTON -#define CONFIG_PWM -#define CONFIG_VBOOT_HASH -#define CONFIG_VOLUME_BUTTONS -#define CONFIG_WP_ACTIVE_HIGH - -/* Battery */ -#define CONFIG_BATTERY_CUT_OFF -#define CONFIG_BATTERY_FUEL_GAUGE -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL -#define CONFIG_BATTERY_SMART /* BC12 */ -#define CONFIG_BC12_DETECT_MT6360 -#define CONFIG_BC12_DETECT_PI3USB9201 -#undef CONFIG_BC12_SINGLE_DRIVER /* TODO(b/159583342): remove after rev0 deprecated */ #define CONFIG_MT6360_BC12_GPIO -#define CONFIG_USB_CHARGER - -/* Charger */ -#define ADC_PSYS ADC_CHARGER_PMON /* ADC name remap */ -#define CONFIG_CHARGER -#define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_ISL9238C -#define CONFIG_CHARGER_MAINTAIN_VBAT -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 /* BOARD_RS1 */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 /* BOARD_RS2 */ -#define CONFIG_CHARGER_OTG -#define CONFIG_CHARGER_PSYS -#define CONFIG_CHARGER_PSYS_READ -#define CONFIG_CHARGE_RAMP_HW -#define CONFIG_CHARGE_MANAGER - -/* Chipset */ - -/* Keyboard */ -#define CONFIG_CMD_KEYBOARD -#define CONFIG_KEYBOARD_COL2_INVERTED -#define CONFIG_KEYBOARD_PROTOCOL_MKBP -#define CONFIG_MKBP_USE_GPIO - -/* I2C */ -#define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_I2C_PASSTHRU_RESTRICTED -#define CONFIG_I2C_VIRTUAL_BATTERY -#define I2C_PORT_CHARGER IT83XX_I2C_CH_A -#define I2C_PORT_BATTERY IT83XX_I2C_CH_A -#define I2C_PORT_ACCEL IT83XX_I2C_CH_B -#define I2C_PORT_PPC0 IT83XX_I2C_CH_C -#define I2C_PORT_PPC1 IT83XX_I2C_CH_E -#define I2C_PORT_USB_MUX0 IT83XX_I2C_CH_C -#define I2C_PORT_USB_MUX1 IT83XX_I2C_CH_E -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY -#define CONFIG_SMBUS_PEC /* LED */ -#define CONFIG_LED_COMMON +#ifdef BOARD_HAYATO +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 +#endif /* PD / USB-C / PPC */ -#define CONFIG_CMD_PPC_DUMP -#define CONFIG_HOSTCMD_PD_CONTROL -#define CONFIG_USBC_PPC -#define CONFIG_USBC_PPC_DEDICATED_INT -#define CONFIG_USBC_PPC_POLARITY -#define CONFIG_USBC_PPC_SYV682X -#define CONFIG_USBC_PPC_VCONN -#define CONFIG_USBC_SS_MUX -#define CONFIG_USBC_VCONN -#define CONFIG_USBC_VCONN_SWAP -#define CONFIG_USB_DRP_ACC_TRYSRC -#define CONFIG_USB_MUX_IT5205 /* C0 */ -#define CONFIG_USB_MUX_IT5205H_SBU_OVP -#define CONFIG_USB_MUX_PS8743 /* C1 */ -#define CONFIG_USB_PD_ALT_MODE -#define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_DEBUG_LEVEL 3 -#define CONFIG_USB_PD_DECODE_SOP -#define CONFIG_USB_PD_DISCHARGE -#define CONFIG_USB_PD_DISCHARGE_PPC -#define CONFIG_USB_PD_DP_HPD_GPIO -#define CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM -#define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_REV30 -#define CONFIG_USB_PD_FRS_PPC -#define CONFIG_USB_PD_FRS_TCPC -#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 -#define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define CONFIG_USB_PD_TCPMV2 -#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP -#define CONFIG_USB_PD_TCPM_TCPCI -#define CONFIG_USB_PD_TRY_SRC -#define CONFIG_USB_PD_VBUS_DETECT_PPC -#define CONFIG_USB_PID 0x5566 /* TODO: update PID */ -#define CONFIG_USB_POWER_DELIVERY - #define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 #define PD_OPERATING_POWER_MW 15000 +#ifdef BOARD_HAYATO +#define PD_MAX_VOLTAGE_MV 15000 +#define PD_MAX_POWER_MW 45000 +#else +#define PD_MAX_VOLTAGE_MV 20000 #define PD_MAX_POWER_MW 60000 -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#endif +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Optional console commands */ #define CONFIG_CMD_FLASH #define CONFIG_CMD_SCRATCHPAD -#define CONFIG_CMD_STACKOVERFLOW + +#define CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV 9000 /* Sensor */ #define CONFIG_GMR_TABLET_MODE #define CONFIG_TABLET_MODE #define CONFIG_TABLET_MODE_SWITCH -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L -#define CONFIG_ACCEL_FIFO -#define CONFIG_ACCEL_FIFO_SIZE 256 -#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160 /* Base accel */ #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCELGYRO_SEC_ADDR_FLAGS BMM150_ADDR0_FLAGS +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel */ +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCEL_LIS2DWL -#define CONFIG_ACCEL_LIS2DW_AS_BASE -#define CONFIG_ACCEL_LIS2DW12_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL #define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_CMD_ACCEL_INFO -#define CONFIG_CMD_ACCELS - -#define CONFIG_MAG_BMI_BMM150 -#define CONFIG_MAG_CALIBRATE - +#ifdef BOARD_ASURADA_REV0 +#define CONFIG_ALS #define ALS_COUNT 1 #define CONFIG_ALS_TCS3400 #define CONFIG_ALS_TCS3400_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) #define CONFIG_ALS_TCS3400_EMULATED_IRQ_EVENT -#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(CLEAR_ALS) +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) +#else +#define CONFIG_ACCEL_LIS2DW12_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) +#endif /* SPI / Host Command */ #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF -#define CONFIG_SPI -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_MOTION_SENSE_CMD, \ - EC_CMD_PD_GET_LOG_ENTRY - -/* MKBP */ -#define CONFIG_MKBP_EVENT - -#define CONFIG_KEYBOARD_PROTOCOL_MKBP -#define CONFIG_MKBP_USE_GPIO - -/* Define the host events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE) /* for DP */) - -/* UART */ -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 4096 /* USB-A */ -#define CONFIG_USB_PORT_POWER_DUMB -#define USB_PORT_COUNT 1 - -/* GPIO name remapping */ -#define GPIO_EN_HDMI_PWR GPIO_EC_X_GPIO1 -#define GPIO_USB_C1_FRS_EN GPIO_EC_X_GPIO1 -#define GPIO_USB_C1_PPC_INT_ODL GPIO_X_EC_GPIO2 -#define GPIO_PS185_EC_DP_HPD GPIO_X_EC_GPIO2 -#define GPIO_USB_C1_DP_IN_HPD GPIO_EC_X_GPIO3 -#define GPIO_PS185_PWRDN_ODL GPIO_EC_X_GPIO3 +#define USBA_PORT_COUNT 1 -/* Voltage regulator control */ -#define CONFIG_HOSTCMD_REGULATOR +#ifdef BOARD_HAYATO +/* Virutal battery optional MFG function */ +#define CONFIG_SMART_BATTERY_OPTIONAL_MFG_FUNC +#endif #ifndef __ASSEMBLER__ @@ -227,51 +105,38 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -enum pwm_channel { - PWM_CH_LED1, - PWM_CH_LED2, - PWM_CH_LED3, - PWM_CH_COUNT, +enum sensor_id { + BASE_ACCEL = 0, + BASE_GYRO, + LID_ACCEL, +#ifdef BOARD_ASURADA_REV0 + CLEAR_ALS, + RGB_ALS, +#endif + SENSOR_COUNT, }; enum adc_channel { - ADC_VBUS, /* ADC 0 */ - ADC_BOARD_ID_0, /* ADC 1 */ - ADC_BOARD_ID_1, /* ADC 2 */ - ADC_CHARGER_AMON_R, /* ADC 3 */ - ADC_CHARGER_PMON, /* ADC 6 */ + ADC_VBUS_C0, /* ADC 0 */ + ADC_BOARD_ID_0, /* ADC 1 */ + ADC_BOARD_ID_1, /* ADC 2 */ + ADC_CHARGER_AMON_R, /* ADC 3 */ + ADC_VBUS_C1, /* ADC 5 */ + ADC_CHARGER_PMON, /* ADC 6 */ /* Number of ADC channels */ ADC_CH_COUNT, }; -enum power_signal { - PMIC_PWR_GOOD, - AP_IN_S3_L, - AP_WDT_ASSERTED, - POWER_SIGNAL_COUNT, -}; - -enum board_sub_board { - SUB_BOARD_NONE = -1, - SUB_BOARD_TYPEC, - SUB_BOARD_HDMI, - - SUB_BOARD_COUNT, -}; - -enum sensor_id { - BASE_ACCEL = 0, - BASE_GYRO, - BASE_MAG, - LID_ACCEL, - CLEAR_ALS, - RGB_ALS, - SENSOR_COUNT, +enum pwm_channel { + PWM_CH_LED1, + PWM_CH_LED2, + PWM_CH_LED3, + PWM_CH_COUNT, }; -void board_reset_pd_mcu(void); -int board_get_version(void); +int board_accel_force_mode_mask(void); +void motion_interrupt(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/asurada/board_id.c b/board/asurada/board_id.c deleted file mode 100644 index f57863e03b..0000000000 --- a/board/asurada/board_id.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include -#include -#include -#include -#include -#include - -/** - * Conversion based on following table: - * - * ID | Rp | Rd | Voltage - * | kOhm | kOhm | mV - * ---+------+------+-------- - * 0 | 51.1 | 2.2 | 136.2 - * 1 | 51.1 | 6.81 | 388.1 - * 2 | 51.1 | 11 | 584.5 - * 3 | 57.6 | 18 | 785.7 - * 4 | 51.1 | 22 | 993.2 - * 5 | 51.1 | 30 | 1220.7 - * 6 | 51.1 | 39.2 | 1432.6 - * 7 | 56 | 56 | 1650.0 - * 8 | 47 | 61.9 | 1875.8 - * 9 | 47 | 80.6 | 2084.5 - * 10 | 56 | 124 | 2273.3 - * 11 | 51.1 | 150 | 2461.5 - * 12 | 47 | 200 | 2672.1 - * 13 | 47 | 330 | 2888.6 - * 14 | 47 | 680 | 3086.7 - */ -const static int voltage_map[] = { - 136, - 388, - 584, - 785, - 993, - 1220, - 1432, - 1650, - 1875, - 2084, - 2273, - 2461, - 2672, - 2888, - 3086, -}; - -const int threshold_mv = 100; - -/** - * Convert ADC value to board id using the voltage table above. - * - * @param ch ADC channel to read, usually ADC_BOARD_ID_0 or ADC_BOARD_ID_1. - * - * @return a non-negative board id, or negative value if error. - */ -static int adc_value_to_numeric_id(enum adc_channel ch) -{ - int mv; - - gpio_set_level(GPIO_EN_EC_ID_ODL, 0); - /* Wait to allow cap charge */ - msleep(10); - - mv = adc_read_channel(ch); - if (mv == ADC_READ_ERROR) - mv = adc_read_channel(ch); - - gpio_set_level(GPIO_EN_EC_ID_ODL, 1); - - if (mv == ADC_READ_ERROR) - return -EC_ERROR_UNKNOWN; - - for (int i = 0; i < ARRAY_SIZE(voltage_map); i++) { - if (IN_RANGE(mv, voltage_map[i] - threshold_mv, - voltage_map[i] + threshold_mv)) - return i; - } - - return -EC_ERROR_UNKNOWN; -} - -int board_get_version(void) -{ - static int version = -1; - - if (version >= 0) - return version; - - version = adc_value_to_numeric_id(ADC_BOARD_ID_0); - if (version < 0) { - ccprints("WARNING: failed to read ADC_BOARD_ID_0"); - ccprints("Assuming board id = 0"); - - version = 0; - } - - return version; -} diff --git a/board/asurada/build.mk b/board/asurada/build.mk index 33f069093d..72015fba95 100644 --- a/board/asurada/build.mk +++ b/board/asurada/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,6 +8,10 @@ # the IC is ITE IT8xxx2 CHIP:=it83xx CHIP_FAMILY:=it8xxx2 -CHIP_VARIANT:=it81202ax_1024 +CHIP_VARIANT:=it81202bx_1024 +BASEBOARD:=asurada -board-y=battery.o board.o board_id.o led.o usb_pd_policy.o +board-$(BOARD_HAYATO)=led_hayato.o +board-$(BOARD_ASURADA)=led.o +board-y+=battery.o board.o +board-y+=usbc_config.o diff --git a/board/asurada/ec.tasklist b/board/asurada/ec.tasklist index ff47718bae..c8e234a412 100644 --- a/board/asurada/ec.tasklist +++ b/board/asurada/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/asurada/gpio.inc b/board/asurada/gpio.inc index 02458ec518..46700a7749 100644 --- a/board/asurada/gpio.inc +++ b/board/asurada/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -30,11 +30,15 @@ GPIO_INT(PMIC_EC_PWRGD, PIN(F, 3), /* Sensor Interrupts */ GPIO_INT(BASE_IMU_INT_L, PIN(J, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, - bmi160_interrupt) + motion_interrupt) GPIO_INT(LID_ACCEL_INT_L, PIN(J, 3), GPIO_INT_FALLING | GPIO_SEL_1P8V, lis2dw12_interrupt) +#ifdef BOARD_ASURADA_REV0 GPIO_INT(ALS_RGB_INT_ODL, PIN(F, 0), GPIO_INT_FALLING, tcs3400_interrupt) +#else +GPIO(ALS_RGB_INT_ODL, PIN(F, 0), GPIO_INPUT) +#endif /* USB-C interrupts */ GPIO_INT(USB_C0_PPC_INT_ODL, PIN(D, 1), GPIO_INT_BOTH, ppc_interrupt) @@ -49,7 +53,9 @@ GPIO_INT(VOLUME_UP_L, PIN(D, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* EC_VOLUP_BTN_ODL */ /* Other interrupts */ -#ifdef BOARD_ASURADA +GPIO_INT(AP_XHCI_INIT_DONE, PIN(D, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + usb_a0_interrupt) +#ifdef BOARD_ASURADA_REV0 GPIO_INT(AC_PRESENT, PIN(M, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) /* AC_OK / AC_PRESENT in rev0 */ #else /* HAYATO */ @@ -58,7 +64,7 @@ GPIO_INT(AC_PRESENT, PIN(E, 5), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, #endif GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, uart_deepsleep_interrupt) /* UART_DEBUG_TX_EC_RX */ -GPIO_INT(WP, PIN(I, 4), GPIO_INT_BOTH, +GPIO_INT(WP, PIN(I, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, switch_interrupt) /* EC_FLASH_WP_OD */ GPIO_INT(SPI0_CS, PIN(M, 5), GPIO_INT_FALLING, spi_event) /* SPI slave Chip Select -- AP_SPI_EC_CS_L */ @@ -73,14 +79,14 @@ GPIO(PG_MT6360_ODL, PIN(F, 1), GPIO_INPUT) GPIO(PG_PP5000_A_ODL, PIN(A, 6), GPIO_INPUT) GPIO(EN_SLP_Z, PIN(E, 3), GPIO_OUT_LOW) GPIO(SYS_RST_ODL, PIN(B, 6), GPIO_ODR_LOW) -GPIO(EC_BL_EN_OD, PIN(B, 5), GPIO_ODR_LOW) +GPIO(EC_BL_EN_OD, PIN(B, 5), GPIO_ODR_LOW | GPIO_SEL_1P8V) /* MKBP event synchronization */ -GPIO(EC_INT_L, PIN(E, 6), GPIO_ODR_HIGH) /* EC_AP_INT_ODL */ +GPIO(EC_INT_L, PIN(E, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_AP_INT_ODL */ /* USB and USBC Signals */ GPIO(DP_AUX_PATH_SEL, PIN(G, 0), GPIO_OUT_HIGH) -GPIO(EC_DPBRDG_HPD_ODL, PIN(J, 0), GPIO_ODR_HIGH) +GPIO(EC_DPBRDG_HPD_ODL, PIN(J, 0), GPIO_ODR_HIGH | GPIO_SEL_1P8V) GPIO(EN_PP5000_USB_A0_VBUS, PIN(B, 7), GPIO_OUT_LOW) GPIO(USB_C0_FRS_EN, PIN(H, 3), GPIO_OUT_LOW) @@ -89,13 +95,13 @@ GPIO(EC_BATT_PRES_ODL, PIN(C, 0), GPIO_INPUT) GPIO(BC12_DET_EN, PIN(J, 5), GPIO_OUT_LOW) /* EN_USB_C0_BC12_DET */ GPIO(EN_EC_ID_ODL, PIN(H, 5), GPIO_ODR_LOW) GPIO(ENTERING_RW, PIN(C, 5), GPIO_OUT_LOW) /* EC_ENTERING_RW */ -GPIO(EC_USB_C0_MUX_RESET_L, PIN(D, 7), GPIO_OUT_HIGH) +GPIO(EN_5V_USM, PIN(D, 7), GPIO_OUT_LOW) /* I2C pins - Alternate function below configures I2C module on these pins */ GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) /* I2C_CHG_BATT_SCL */ GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) /* I2C_CHG_BATT_SDA */ -GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT) /* I2C_SENSOR_SCL */ -GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT) /* I2C_SENSOR_SDA */ +GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SCL */ +GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SDA */ GPIO(I2C_C_SCL, PIN(F, 6), GPIO_INPUT) /* I2C_USB_C0_SCL */ GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) /* I2C_USB_C0_SCL */ GPIO(I2C_E_SCL, PIN(E, 0), GPIO_INPUT) /* I2C_USB_C1_SCL */ @@ -113,7 +119,7 @@ GPIO(EC_X_GPIO3, PIN(J, 1), GPIO_INPUT) /* Alternate functions GPIO definitions */ ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A */ -ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, 0) /* I2C B */ +ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C B */ ALTERNATE(PIN_MASK(F, 0xC0), 1, MODULE_I2C, 0) /* I2C C */ ALTERNATE(PIN_MASK(E, 0x81), 1, MODULE_I2C, 0) /* I2C E */ @@ -124,31 +130,41 @@ ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, 0) /* EC to Servo */ ALTERNATE(PIN_MASK(A, 0x07), 1, MODULE_PWM, 0) /* PWM 0~2 */ /* ADC */ -ALTERNATE(PIN_MASK(I, 0x4F), 0, MODULE_ADC, 0) /* ADC 0,1,2,3,6 */ +ALTERNATE(PIN_MASK(I, 0x6F), 0, MODULE_ADC, 0) /* ADC 0,1,2,3,5,6 */ /* SPI */ ALTERNATE(PIN_MASK(M, 0x33), 0, MODULE_SPI, 0) /* SPI */ -/* Power Switch Logic (PSL) inputs */ -GPIO(EC_RST_ODL, PIN(L, 1), GPIO_INPUT) - /* Unimplemented Pins */ -UNIMPLEMENTED(PCH_SMI_L) -UNIMPLEMENTED(PCH_SCI_L) -UNIMPLEMENTED(PCH_WAKE_L) -UNIMPLEMENTED(PCH_PLTRST_L) - -#define UNIMPLEMENTED_GPIO(name, pin) UNIMPLEMENTED(name) - -UNIMPLEMENTED_GPIO(SET_VMC_VOLT_AT_1V8, PIN(D, 4)) -UNIMPLEMENTED_GPIO(EN_PP3000_VMC_PMU, PIN(D, 2)) -UNIMPLEMENTED_GPIO(PACKET_MODE_EN, PIN(A, 3)) +GPIO(SET_VMC_VOLT_AT_1V8, PIN(D, 4), GPIO_INPUT | GPIO_PULL_DOWN | GPIO_SEL_1P8V) +GPIO(PACKET_MODE_EN, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) /* b/160218054: behavior not defined */ -UNIMPLEMENTED_GPIO(USB_A0_FAULT_ODL, PIN(A, 7)) -UNIMPLEMENTED_GPIO(CHARGER_PROCHOT_ODL, PIN(C, 3)) -UNIMPLEMENTED_GPIO(PG_MT6315_GPU_ODL, PIN(H, 6)) -UNIMPLEMENTED_GPIO(EN_PP3000_SD_U, PIN(G, 1)) +/* *_ODL pin has external pullup so don't pull it down. */ +GPIO(USB_A0_FAULT_ODL, PIN(A, 7), GPIO_INPUT) +GPIO(CHARGER_PROCHOT_ODL, PIN(C, 3), GPIO_INPUT) +GPIO(PG_MT6315_GPU_ODL, PIN(H, 6), GPIO_INPUT) +GPIO(EN_PP3000_SD_U, PIN(G, 1), GPIO_INPUT | GPIO_PULL_DOWN | GPIO_SEL_1P8V) /* reserved for future use */ -UNIMPLEMENTED_GPIO(CCD_MODE_ODL, PIN(C, 4)) - -#undef UNIMPLEMENTED_GPIO +GPIO(CCD_MODE_ODL, PIN(C, 4), GPIO_INPUT) +/* + * ADC pins don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(NC_GPI7, PIN(I, 7), GPIO_OUT_LOW) +/* NC pins, enable internal pull-up/down to avoid floating state. */ +#ifdef BOARD_ASURADA_REV0 +GPIO(NC_GPE5, PIN(E, 5), GPIO_INPUT | GPIO_PULL_UP) +#else /* HAYATO */ +GPIO(NC_GPM2, PIN(M, 2), GPIO_INPUT | GPIO_PULL_DOWN) +#endif +GPIO(NC_GPM3, PIN(M, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPM6, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(SPI_CLK_GPG6, PIN(G, 6), GPIO_INPUT | GPIO_PULL_UP) +/* + * These 4 pins don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(NC_GPG3, PIN(G, 3), GPIO_OUT_LOW) +GPIO(SPI_MOSI_GPG4, PIN(G, 4), GPIO_OUT_LOW) +GPIO(SPI_MISO_GPG5, PIN(G, 5), GPIO_OUT_LOW) +GPIO(SPI_CS_GPG7, PIN(G, 7), GPIO_OUT_LOW) diff --git a/board/asurada/led.c b/board/asurada/led.c index 166ece92e9..96093cd8a9 100644 --- a/board/asurada/led.c +++ b/board/asurada/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -15,18 +15,16 @@ #include "stdbool.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_PWM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_PWM, format, ##args) #define LED_OFF EC_LED_COLOR_COUNT const enum ec_led_id supported_led_ids[] = { /* Main LED */ - EC_LED_ID_LEFT_LED, - EC_LED_ID_RIGHT_LED, + EC_LED_ID_LEFT_LED, EC_LED_ID_RIGHT_LED, /* Not used, give them some random name for testing */ - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED + EC_LED_ID_POWER_LED, EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -85,8 +83,7 @@ static void led_set_color_battery(enum ec_led_colors color, int duty) } static enum ec_error_list set_color(enum ec_led_id led_id, - enum ec_led_colors color, - int duty) + enum ec_led_colors color, int duty) { switch (led_id) { case EC_LED_ID_LEFT_LED: @@ -146,13 +143,13 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) static void update_led(enum ec_led_id led_id, bool is_active_charge_port, int duty, int tick) { - enum charge_state power_state = charge_get_state(); + enum led_pwr_state power_state = led_pwr_get_state(); - if (power_state == PWR_STATE_IDLE) { + if (power_state == LED_PWRS_IDLE) { /* Factory mode: blinking white (2sec on + 2sec off) */ set_color(led_id, (tick % 8 < 4) ? EC_LED_COLOR_WHITE : LED_OFF, duty); - } else if (power_state == PWR_STATE_ERROR) { + } else if (power_state == LED_PWRS_ERROR) { /* Battery error: blinking amber (1sec on + 1sec off) */ set_color(led_id, (tick % 4 < 2) ? EC_LED_COLOR_AMBER : LED_OFF, duty); @@ -161,7 +158,7 @@ static void update_led(enum ec_led_id led_id, bool is_active_charge_port, * Active charge port: amber when charging, white if fully * charged. */ - if (power_state == PWR_STATE_CHARGE) + if (power_state == LED_PWRS_CHARGE) set_color(led_id, EC_LED_COLOR_AMBER, duty); else set_color(led_id, EC_LED_COLOR_WHITE, duty); @@ -174,13 +171,11 @@ static void update_led(enum ec_led_id led_id, bool is_active_charge_port, if (chipset_in_state(CHIPSET_STATE_ON)) set_color(led_id, EC_LED_COLOR_WHITE, duty); else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) - set_color( - led_id, - (tick % 8 < 6) ? EC_LED_COLOR_AMBER : LED_OFF, - duty); + set_color(led_id, + (tick % 8 < 6) ? EC_LED_COLOR_AMBER : LED_OFF, + duty); else set_color(led_id, LED_OFF, 0); - } } diff --git a/board/asurada/led_hayato.c b/board/asurada/led_hayato.c new file mode 100644 index 0000000000..2243895257 --- /dev/null +++ b/board/asurada/led_hayato.c @@ -0,0 +1,129 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "driver/bc12/mt6360.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + mt6360_led_set_brightness(MT6360_LED_RGB2, 50); + mt6360_led_set_brightness(MT6360_LED_RGB3, 50); + + switch (color) { + case EC_LED_COLOR_AMBER: + mt6360_led_enable(MT6360_LED_RGB2, 0); + mt6360_led_enable(MT6360_LED_RGB3, 1); + break; + case EC_LED_COLOR_WHITE: + mt6360_led_enable(MT6360_LED_RGB2, 1); + mt6360_led_enable(MT6360_LED_RGB3, 0); + break; + default: /* LED_OFF and other unsupported colors */ + mt6360_led_enable(MT6360_LED_RGB2, 0); + mt6360_led_enable(MT6360_LED_RGB3, 0); + break; + } +} + +__override void led_set_color_power(enum ec_led_colors color) +{ + mt6360_led_set_brightness(MT6360_LED_RGB1, 1); + mt6360_led_enable(MT6360_LED_RGB1, color == EC_LED_COLOR_WHITE); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = + MT6360_LED_BRIGHTNESS_MAX; + brightness_range[EC_LED_COLOR_WHITE] = + MT6360_LED_BRIGHTNESS_MAX; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = + MT6360_LED_BRIGHTNESS_MAX; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } + + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/asurada/usb_pd_policy.c b/board/asurada/usb_pd_policy.c deleted file mode 100644 index 8cc8b0a922..0000000000 --- a/board/asurada/usb_pd_policy.c +++ /dev/null @@ -1,230 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "charge_manager.h" -#include "chipset.h" -#include "timer.h" -#include "usb_dp_alt_mode.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usbc_ppc.h" - -#ifndef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT -#error Asurada reference must define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT -#endif - -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) - -/* The port that the aux channel is on. */ -static enum { - AUX_PORT_NONE = -1, - AUX_PORT_C0 = 0, - AUX_PORT_C1HDMI = 1, -} aux_port = AUX_PORT_NONE; - -int svdm_get_hpd_gpio(int port) -{ - /* HPD is low active, inverse the result */ - return !gpio_get_level(GPIO_EC_DPBRDG_HPD_ODL); -} - -void svdm_set_hpd_gpio(int port, int en) -{ - /* - * HPD is low active, inverse the en - * TODO: C0&C1 shares the same HPD, implement FCFS policy. - */ - gpio_set_level(GPIO_EC_DPBRDG_HPD_ODL, !en); -} - -static void aux_switch_port(int port) -{ - if (port != AUX_PORT_NONE) - gpio_set_level_verbose(CC_USBPD, GPIO_DP_AUX_PATH_SEL, port); - aux_port = port; -} - -static void aux_display_disconnected(int port) -{ - /* Gets the other port. C0 -> C1, C1 -> C0. */ - int other_port = !port; - - /* If the current port is not the aux port, nothing needs to be done. */ - if (aux_port != port) - return; - - /* If the other port is connected to a external display, switch aux. */ - if (dp_status[other_port] & DP_FLAGS_DP_ON) - aux_switch_port(other_port); - else - aux_switch_port(AUX_PORT_NONE); -} - -__override int svdm_dp_attention(int port, uint32_t *payload) -{ - int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); - int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - int cur_lvl = svdm_get_hpd_gpio(port); -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - - dp_status[port] = payload[1]; - - if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && - (irq || lvl)) - /* - * Wake up the AP. IRQ or level high indicates a DP sink is now - * present. - */ - if (IS_ENABLED(CONFIG_MKBP_EVENT)) - pd_notify_dp_alt_mode_entry(); - - /* Its initial DP status message prior to config */ - if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { - if (lvl) - dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; - return 1; - } - -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - if (irq && !lvl) { - /* - * IRQ can only be generated when the level is high, because - * the IRQ is signaled by a short low pulse from the high level. - */ - CPRINTF("ERR:HPD:IRQ&LOW\n"); - return 0; /* nak */ - } - - if (irq && cur_lvl) { - uint64_t now = get_time().val; - /* wait for the minimum spacing between IRQ_HPD if needed */ - if (now < svdm_hpd_deadline[port]) - usleep(svdm_hpd_deadline[port] - now); - - /* generate IRQ_HPD pulse */ - svdm_set_hpd_gpio(port, 0); - usleep(HPD_DSTREAM_DEBOUNCE_IRQ); - svdm_set_hpd_gpio(port, 1); - } else { - svdm_set_hpd_gpio(port, lvl); - } - - /* - * Asurada can only output to 1 display port at a time. - * This implements FCFS policy by changing the aux channel. If a - * display is connected to the either port (says A), and the port A - * will be served until the display is disconnected from port A. - * It won't output to the other display which connects to port B. - */ - if (lvl && aux_port == AUX_PORT_NONE) - /* - * A display is connected, and no display was plugged on either - * port. - */ - aux_switch_port(port); - else if (!lvl) - aux_display_disconnected(port); - - - /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - - usb_mux_hpd_update(port, lvl, irq); - -#ifdef USB_PD_PORT_TCPC_MST - if (port == USB_PD_PORT_TCPC_MST) - baseboard_mst_enable_control(port, lvl); -#endif - - /* ack */ - return 1; -} - -__override void svdm_exit_dp_mode(int port) -{ - svdm_safe_dp_mode(port); -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - svdm_set_hpd_gpio(port, 0); -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - usb_mux_hpd_update(port, 0, 0); - - aux_display_disconnected(port); - -#ifdef USB_PD_PORT_TCPC_MST - if (port == USB_PD_PORT_TCPC_MST) - baseboard_mst_enable_control(port, 0); -#endif -#ifdef CONFIG_USB_PD_TCPMV2 - dp_teardown(port); -#endif -} - -int pd_snk_is_vbus_provided(int port) -{ - return ppc_is_vbus_present(port); -} - -void pd_power_supply_reset(int port) -{ - int prev_en; - - prev_en = ppc_is_sourcing_vbus(port); - - /* Disable VBUS. */ - ppc_vbus_source_enable(port, 0); - - /* Enable discharge if we were previously sourcing 5V */ - if (prev_en) - pd_set_vbus_discharge(port, 1); - -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - - /* Notify host of power info change. */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -int pd_check_vconn_swap(int port) -{ - /* TODO: Only allow vconn swap if PP4200_G rail is enabled , s3/s0 on */ - return 0; -} - -int pd_set_power_supply_ready(int port) -{ - int rv; - - /* Disable charging. */ - rv = ppc_vbus_sink_enable(port, 0); - if (rv) - return rv; - - pd_set_vbus_discharge(port, 0); - - /* Provide Vbus. */ - rv = ppc_vbus_source_enable(port, 1); - if (rv) - return rv; - -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - - /* Notify host of power info change. */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; -} - -int board_vbus_source_enabled(int port) -{ - return ppc_is_sourcing_vbus(port); -} - diff --git a/board/asurada/usbc_config.c b/board/asurada/usbc_config.c new file mode 100644 index 0000000000..ba6461b0f8 --- /dev/null +++ b/board/asurada/usbc_config.c @@ -0,0 +1,29 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Asurada board-specific USB-C configuration */ + +#include "driver/ppc/syv682x.h" +#include "driver/usb_mux/ps8743.h" +#include "hooks.h" + +__override int syv682x_board_is_syv682c(int port) +{ + return board_get_version() > 2; +} + +void board_usb_mux_init(void) +{ + if (board_get_sub_board() == SUB_BOARD_TYPEC) { + ps8743_tune_usb_eq(usb_muxes[1].mux, PS8743_USB_EQ_TX_12_8_DB, + PS8743_USB_EQ_RX_12_8_DB); + ps8743_write(usb_muxes[1].mux, PS8743_REG_HS_DET_THRESHOLD, + PS8743_USB_HS_THRESH_NEG_10); + ps8743_field_update(usb_muxes[1].mux, PS8743_REG_DCI_CONFIG_2, + PS8743_AUTO_DCI_MODE_MASK, + PS8743_AUTO_DCI_MODE_FORCE_USB); + } +} +DECLARE_HOOK(HOOK_INIT, board_usb_mux_init, HOOK_PRIO_INIT_I2C + 1); diff --git a/board/asurada/vif_override.xml b/board/asurada/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/asurada/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/asurada_scp/board.c b/board/asurada_scp/board.c deleted file mode 100644 index 06b790cd81..0000000000 --- a/board/asurada_scp/board.c +++ /dev/null @@ -1,9 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -/* Asurada SCP configuration */ - -#include "registers.h" - -#include "gpio_list.h" diff --git a/board/asurada_scp/board.h b/board/asurada_scp/board.h index 58296e0c23..b70a39d20d 100644 --- a/board/asurada_scp/board.h +++ b/board/asurada_scp/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,11 +8,7 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_HOSTCMD) | CC_MASK(CC_IPI))) - -#define CONFIG_FLASH_SIZE 0x58000 -#define CONFIG_LTO -#define CONFIG_UART_CONSOLE 0 +#include "baseboard.h" /* * RW only, no flash @@ -20,53 +16,18 @@ * | ROM vectortable, .text, .rodata, .data LMA * +-------------------- 0x58000 * | RAM .bss, .data - * +-------------------- 0x7BDB0 + * +-------------------- 0x0ffc00 + * | Reserved (padding for 1k-alignment) + * +-------------------- 0x0ffdb0 * | IPI shared buffer with AP (288 + 8) * 2 - * +-------------------- 0x7C000 - * | 8KB I-CACHE - * +-------------------- 0x7E000 - * | 8KB D-CACHE - * +-------------------- 0x80000 + * +-------------------- 0x100000 */ -#define ICACHE_BASE 0x7C000 #define CONFIG_ROM_BASE 0x0 #define CONFIG_RAM_BASE 0x58000 #define CONFIG_ROM_SIZE (CONFIG_RAM_BASE - CONFIG_ROM_BASE) -#define CONFIG_RAM_SIZE (CONFIG_IPC_SHARED_OBJ_ADDR - CONFIG_RAM_BASE) -#define CONFIG_CODE_RAM_SIZE CONFIG_RAM_BASE -#define CONFIG_DATA_RAM_SIZE (ICACHE_BASE - CONFIG_RAM_BASE) -#define CONFIG_RO_MEM_OFF 0 - -/* IPI configs */ -#define CONFIG_IPC_SHARED_OBJ_BUF_SIZE 288 -#define CONFIG_IPC_SHARED_OBJ_ADDR \ - (ICACHE_BASE - \ - (CONFIG_IPC_SHARED_OBJ_BUF_SIZE + 2 * 4 /* int32_t */) * 2) -#define CONFIG_IPI -#define CONFIG_RPMSG_NAME_SERVICE - -#define SCP_IPI_INIT 0 -#define SCP_IPI_VDEC_H264 1 -#define SCP_IPI_VDEC_VP8 2 -#define SCP_IPI_VDEC_VP9 3 -#define SCP_IPI_VENC_H264 4 -#define SCP_IPI_VENC_VP8 5 -#define SCP_IPI_MDP_INIT 6 -#define SCP_IPI_MDP_DEINIT 7 -#define SCP_IPI_MDP_FRAME 8 -#define SCP_IPI_DIP 9 -#define SCP_IPI_ISP_CMD 10 -#define SCP_IPI_ISP_FRAME 11 -#define SCP_IPI_FD_CMD 12 -#define SCP_IPI_HOST_COMMAND 13 -#define SCP_IPI_COUNT 14 - -#define IPI_COUNT SCP_IPI_COUNT - -#define SCP_IPI_NS_SERVICE 0xFF +#define CONFIG_RAM_SIZE \ + ((CONFIG_IPC_SHARED_OBJ_ADDR & (~(0x400 - 1))) - CONFIG_RAM_BASE) -#ifndef __ASSEMBLER__ -#include "gpio_signal.h" -#endif /* !__ASSEMBLER__ */ +#define SCP_FW_END 0x100000 #endif /* __CROS_EC_BOARD_H */ diff --git a/board/asurada_scp/build.mk b/board/asurada_scp/build.mk index 33debd81a6..94efa82a6f 100644 --- a/board/asurada_scp/build.mk +++ b/board/asurada_scp/build.mk @@ -1,12 +1,11 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Board specific files build # -CHIP:=mt8192_scp +CHIP:=mt_scp CHIP_VARIANT:=mt8192 - -board-y=board.o +BASEBOARD:=mtscp-rv32i diff --git a/board/asurada_scp/ec.tasklist b/board/asurada_scp/ec.tasklist index a6ea775286..1e43d6d30d 100644 --- a/board/asurada_scp/ec.tasklist +++ b/board/asurada_scp/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,4 +10,8 @@ #define CONFIG_TASK_LIST \ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(VDEC_SERVICE, vdec_service_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_ALWAYS(VDEC_CORE_SERVICE, vdec_core_service_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_ALWAYS(VENC_SERVICE, venc_service_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MDP_SERVICE, mdp_service_task, NULL, TRENTA_TASK_STACK_SIZE) diff --git a/board/asurada_scp/gpio.inc b/board/asurada_scp/gpio.inc index 3222a34e08..efc5675875 100644 --- a/board/asurada_scp/gpio.inc +++ b/board/asurada_scp/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/atlas/battery.c b/board/atlas/battery.c index fb2fba18be..78b3be16a4 100644 --- a/board/atlas/battery.c +++ b/board/atlas/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -18,10 +18,10 @@ #include "i2c.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) /* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHUTDOWN_DATA 0x0010 +#define SB_SHUTDOWN_DATA 0x0010 enum battery_type { BATTERY_LG, @@ -52,16 +52,16 @@ static int battery_report_present = 1; * limits are given by discharging_min/max_c. */ static const struct battery_info batt_info_lg = { - .voltage_max = TARGET_WITH_MARGIN(8800, 5), /* mV */ - .voltage_normal = 7700, - .voltage_min = 6100, /* Add 100mV for charger accuracy */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 46, - .charging_min_c = 10, - .charging_max_c = 50, - .discharging_min_c = 0, - .discharging_max_c = 60, + .voltage_max = TARGET_WITH_MARGIN(8800, 5), /* mV */ + .voltage_normal = 7700, + .voltage_min = 6100, /* Add 100mV for charger accuracy */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 46, + .charging_min_c = 10, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 60, }; /* @@ -70,16 +70,16 @@ static const struct battery_info batt_info_lg = { * limits are given by discharging_min/max_c. */ static const struct battery_info batt_info_lishen = { - .voltage_max = TARGET_WITH_MARGIN(8800, 5), /* mV */ - .voltage_normal = 7700, - .voltage_min = 6100, /* Add 100mV for charger accuracy */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 46, - .charging_min_c = 10, - .charging_max_c = 50, - .discharging_min_c = 0, - .discharging_max_c = 60, + .voltage_max = TARGET_WITH_MARGIN(8800, 5), /* mV */ + .voltage_normal = 7700, + .voltage_min = 6100, /* Add 100mV for charger accuracy */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 46, + .charging_min_c = 10, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 60, }; static const struct board_batt_params info[] = { @@ -110,7 +110,7 @@ static int board_get_battery_type(void) if (!battery_manufacturer_name(name, sizeof(name))) { for (i = 0; i < BATTERY_TYPE_COUNT; i++) { if (!strncasecmp(name, info[i].manuf_name, - ARRAY_SIZE(name)-1)) { + ARRAY_SIZE(name) - 1)) { board_battery_type = i; break; } @@ -139,7 +139,9 @@ DECLARE_HOOK(HOOK_INIT, board_init_battery_type, HOOK_PRIO_INIT_I2C + 1); const struct battery_info *battery_get_info(void) { return info[board_battery_type == BATTERY_TYPE_COUNT ? - DEFAULT_BATTERY_TYPE : board_battery_type].batt_info; + DEFAULT_BATTERY_TYPE : + board_battery_type] + .batt_info; } int board_cut_off_battery(void) @@ -183,7 +185,7 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) */ if (!battery_is_cut_off() && !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - (curr->batt.status & STATUS_FULLY_CHARGED)) + (curr->batt.status & STATUS_FULLY_CHARGED)) return 1; return 0; diff --git a/board/atlas/board.c b/board/atlas/board.c index 0ef9a591da..4ce7f97461 100644 --- a/board/atlas/board.c +++ b/board/atlas/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,13 +9,13 @@ #include "bd99992gw.h" #include "board_config.h" #include "charge_manager.h" -#include "charger.h" #include "charge_state.h" +#include "charger.h" #include "chipset.h" #include "console.h" #include "driver/als_opt3001.h" -#include "driver/pmic_bd99992gw.h" #include "driver/charger/isl923x.h" +#include "driver/pmic_bd99992gw.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" @@ -29,10 +29,11 @@ #include "keyboard_scan.h" #include "lid_switch.h" #include "motion_sense.h" -#include "power_button.h" +#include "panic.h" #include "power.h" -#include "pwm_chip.h" +#include "power_button.h" #include "pwm.h" +#include "pwm_chip.h" #include "spi.h" #include "switch.h" #include "system.h" @@ -46,8 +47,8 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { @@ -67,10 +68,11 @@ static void tcpc_alert_event(enum gpio_signal signal) schedule_deferred_pd_interrupt(port); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Keyboard scan. Increase output_settle_us to 80us from default 50us. */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { .output_settle_us = 80, .debounce_down_us = 9 * MSEC, .debounce_up_us = 30 * MSEC, @@ -85,19 +87,19 @@ struct keyboard_scan_config keyscan_config = { /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { 3, 0, 10000 }, - [PWM_CH_DB0_LED_BLUE] = { - 0, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, 2400 }, - [PWM_CH_DB0_LED_RED] = { - 2, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, 2400 }, - [PWM_CH_DB0_LED_GREEN] = { - 6, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, 2400 }, - [PWM_CH_DB1_LED_BLUE] = { - 1, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, 2400 }, - [PWM_CH_DB1_LED_RED] = { - 7, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, 2400 }, - [PWM_CH_DB1_LED_GREEN] = { - 5, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, 2400 }, + [PWM_CH_KBLIGHT] = { 3, 0, 10000 }, + [PWM_CH_DB0_LED_BLUE] = { 0, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 2400 }, + [PWM_CH_DB0_LED_RED] = { 2, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 2400 }, + [PWM_CH_DB0_LED_GREEN] = { 6, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 2400 }, + [PWM_CH_DB1_LED_BLUE] = { 1, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 2400 }, + [PWM_CH_DB1_LED_RED] = { 7, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 2400 }, + [PWM_CH_DB1_LED_GREEN] = { 5, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 2400 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -114,41 +116,46 @@ const struct adc_t adc_channels[] = { * Adapter current output or battery charging/discharging current (uV) * 18x amplification on charger side. */ - [ADC_AMON_BMON] = { - "AMON_BMON", - NPCX_ADC_CH2, - ADC_MAX_VOLT*1000/18, - ADC_READ_MAX+1, - 0 - }, + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, /* * ISL9238 PSYS output is 1.44 uA/W over 12.4K resistor, to read * 0.8V @ 45 W, i.e. 56250 uW/mV. Using ADC_MAX_VOLT*56250 and * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we * only divide by 2 (enough to avoid precision issues). */ - [ADC_PSYS] = { - "PSYS", - NPCX_ADC_CH3, - ADC_MAX_VOLT*56250*2/(ADC_READ_MAX+1), - 2, - 0 - }, + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 56250 * 2 / (ADC_READ_MAX + 1), 2, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* I2C port map */ -const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, - GPIO_EC_I2C0_POWER_SCL, GPIO_EC_I2C0_POWER_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 1000, - GPIO_EC_I2C1_USB_C0_SCL, GPIO_EC_I2C1_USB_C0_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 1000, - GPIO_EC_I2C2_USB_C1_SCL, GPIO_EC_I2C2_USB_C1_SDA}, - {"sensor", I2C_PORT_SENSOR, 100, - GPIO_EC_I2C3_SENSOR_3V3_SCL, GPIO_EC_I2C3_SENSOR_3V3_SDA}, - {"battery", I2C_PORT_BATTERY, 100, - GPIO_EC_I2C4_BATTERY_SCL, GPIO_EC_I2C4_BATTERY_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C0_POWER_SCL, + .sda = GPIO_EC_I2C0_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C1_USB_C0_SCL, + .sda = GPIO_EC_I2C1_USB_C0_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C2_USB_C1_SCL, + .sda = GPIO_EC_I2C2_USB_C1_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 100, + .scl = GPIO_EC_I2C3_SENSOR_3V3_SCL, + .sda = GPIO_EC_I2C3_SENSOR_3V3_SDA }, + { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C4_BATTERY_SCL, + .sda = GPIO_EC_I2C4_BATTERY_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -187,16 +194,22 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, { - .usb_port = 1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, }; @@ -221,9 +234,10 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); uint16_t tcpc_get_alert_status(void) { @@ -243,16 +257,16 @@ uint16_t tcpc_get_alert_status(void) } const struct temp_sensor_t temp_sensors[] = { - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0}, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0 }, /* BD99992GW temp sensors are only readable in S0 */ - {"Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM0}, - {"Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM1}, - {"DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM2}, - {"eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM3}, + { "Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM0 }, + { "Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM1 }, + { "DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM2 }, + { "eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM3 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -278,12 +292,12 @@ static void board_report_pmic_fault(const char *str) /* VRFAULT has occurred, print VRFAULT status bits. */ /* PWRSTAT1 */ - i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, - BD99992GW_REG_PWRSTAT1, &pwrstat1); + i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, BD99992GW_REG_PWRSTAT1, + &pwrstat1); /* PWRSTAT2 */ - i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, - BD99992GW_REG_PWRSTAT2, &pwrstat2); + i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, BD99992GW_REG_PWRSTAT2, + &pwrstat2); CPRINTS("PMIC VRFAULT: %s", str); CPRINTS("PMIC VRFAULT: PWRSTAT1=0x%02x PWRSTAT2=0x%02x", pwrstat1, @@ -324,8 +338,8 @@ static void board_pmic_disable_slp_s0_vr_decay(void) * Bits 3:2 (10) - VR set to AUTO on SLP_S0# de-assertion * Bits 1:0 (10) - VR set to AUTO operating mode */ - i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, - BD99992GW_REG_V18ACNT, 0x2a); + i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, BD99992GW_REG_V18ACNT, + 0x2a); /* * V085ACNT: @@ -357,8 +371,8 @@ static void board_pmic_enable_slp_s0_vr_decay(void) * Bits 3:2 (10) - VR set to AUTO on SLP_S0# de-assertion * Bits 1:0 (10) - VR set to AUTO operating mode */ - i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, - BD99992GW_REG_V18ACNT, 0x6a); + i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, BD99992GW_REG_V18ACNT, + 0x6a); /* * V085ACNT: @@ -371,8 +385,7 @@ static void board_pmic_enable_slp_s0_vr_decay(void) BD99992GW_REG_V085ACNT, 0x6a); } -__override void power_board_handle_host_sleep_event( - enum host_sleep_event state) +__override void power_board_handle_host_sleep_event(enum host_sleep_event state) { if (state == HOST_SLEEP_EVENT_S0IX_SUSPEND) board_pmic_enable_slp_s0_vr_decay(); @@ -491,8 +504,8 @@ int board_set_active_charge_port(int charge_port) int is_real_port = (charge_port >= 0 && charge_port < CONFIG_USB_PD_PORT_MAX_COUNT); /* check if we are sourcing VBUS on the port */ - int is_source = gpio_get_level(charge_port == 0 ? - GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN); + int is_source = gpio_get_level(charge_port == 0 ? GPIO_USB_C0_5V_EN : + GPIO_USB_C1_5V_EN); if (is_real_port && is_source) { CPRINTS("No charging from p%d", charge_port); @@ -508,48 +521,26 @@ int board_set_active_charge_port(int charge_port) } else { /* Make sure non-charging port is disabled */ gpio_set_level(charge_port ? GPIO_EN_USB_C0_CHARGE_L : - GPIO_EN_USB_C1_CHARGE_L, 1); + GPIO_EN_USB_C1_CHARGE_L, + 1); /* Enable charging port */ gpio_set_level(charge_port ? GPIO_EN_USB_C1_CHARGE_L : - GPIO_EN_USB_C0_CHARGE_L, 0); + GPIO_EN_USB_C0_CHARGE_L, + 0); } return EC_SUCCESS; } -/* - * Limit the input current to 95% negotiated limit, - * to account for the charger chip margin. - */ - -static int charger_derate(int current) -{ - return current * 95 / 100; -} - static void board_charger_init(void) { - charger_set_input_current(CHARGER_SOLO, charger_derate - (PD_MAX_CURRENT_MA)); + charger_set_input_current_limit( + CHARGER_SOLO, + PD_MAX_CURRENT_MA * + (100 - CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT) / 100); } DECLARE_HOOK(HOOK_INIT, board_charger_init, HOOK_PRIO_DEFAULT); -/** - * Set the charge limit based upon desired maximum. - * - * @param port Port number. - * @param supplier Charge supplier type. - * @param charge_ma Desired charge limit (mA). - * @param charge_mv Negotiated charge voltage (mV). - */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_ma = charger_derate(charge_ma); - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - static void board_chipset_suspend(void) { gpio_set_level(GPIO_KBD_BL_EN, 0); diff --git a/board/atlas/board.h b/board/atlas/board.h index 8910d39198..bde6d3e07a 100644 --- a/board/atlas/board.h +++ b/board/atlas/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,29 +12,27 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* EC */ #define CONFIG_ADC -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_BOARD_FORCE_RESET_PIN #define CONFIG_DPTF #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_LID_SWITCH #define CONFIG_LOW_POWER_IDLE #define CONFIG_LTO #define CONFIG_CHIP_PANIC_BACKUP -#define CONFIG_SOFTWARE_PANIC #define CONFIG_PWM #define CONFIG_PWM_KBLIGHT #define CONFIG_SHA256_UNROLLED /* Internal SPI flash on NPCX7 */ -#define CONFIG_FLASH_SIZE (512 * 1024) /* It's really 1MB. */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* It's really 1MB. */ #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ @@ -55,10 +53,10 @@ #define CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET #define CONFIG_CHIPSET_RESET_HOOK #define CONFIG_CPU_PROCHOT_ACTIVE_LOW -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 + #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_REFRESH_ROW3 @@ -66,7 +64,8 @@ /* Battery */ #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" -#define CONFIG_BATTERY_LEVEL_NEAR_FULL 95 +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 95 #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_BATTERY_PRESENT_CUSTOM #define CONFIG_BATTERY_SMART @@ -79,8 +78,10 @@ #define CONFIG_CHARGER #define CONFIG_CHARGER_ISL9238 #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_PROFILE_OVERRIDE #define CONFIG_CHARGER_PSYS #define CONFIG_CHARGER_PSYS_READ @@ -120,7 +121,6 @@ #define CONFIG_ACCEL_FIFO_SIZE 1024 /* Depends on how fast the AP boots and typical ODRs. */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) -#define CONFIG_ACCEL_INTERRUPTS /* USB */ #define CONFIG_USB_PD_ALT_MODE @@ -150,29 +150,29 @@ #define CONFIG_USBC_VCONN_SWAP /* Optional feature to configure npcx chip */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ -#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ -#define CONFIG_HIBERNATE_PSL /* Enable PSL pins for wakeup */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ +#define CONFIG_HIBERNATE_PSL /* Enable PSL pins for wakeup */ /* I2C ports */ -#define I2C_PORT_POWER NPCX_I2C_PORT0_0 /* pmic/charger */ -#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 -#define I2C_PORT_SENSOR NPCX_I2C_PORT3_0 /* als */ -#define I2C_PORT_BATTERY NPCX_I2C_PORT4_1 -#define I2C_PORT_GYRO NPCX_I2C_PORT5_0 /* accel/gyro */ - -#define I2C_PORT_ACCEL I2C_PORT_GYRO -#define I2C_PORT_CHARGER I2C_PORT_POWER -#define I2C_PORT_PMIC I2C_PORT_POWER -#define I2C_PORT_THERMAL I2C_PORT_POWER +#define I2C_PORT_POWER NPCX_I2C_PORT0_0 /* pmic/charger */ +#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT3_0 /* als */ +#define I2C_PORT_BATTERY NPCX_I2C_PORT4_1 +#define I2C_PORT_GYRO NPCX_I2C_PORT5_0 /* accel/gyro */ + +#define I2C_PORT_ACCEL I2C_PORT_GYRO +#define I2C_PORT_CHARGER I2C_PORT_POWER +#define I2C_PORT_PMIC I2C_PORT_POWER +#define I2C_PORT_THERMAL I2C_PORT_POWER /* I2C addresses */ -#define I2C_ADDR_TCPC_FLAGS 0x0B -#define I2C_ADDR_MP2949_FLAGS 0x20 -#define I2C_ADDR_BD99992_FLAGS 0x30 +#define I2C_ADDR_TCPC_FLAGS 0x0B +#define I2C_ADDR_MP2949_FLAGS 0x20 +#define I2C_ADDR_BD99992_FLAGS 0x30 #ifndef __ASSEMBLER__ @@ -180,11 +180,11 @@ #include "registers.h" enum temp_sensor_id { - TEMP_SENSOR_BATTERY, /* BD99956GW TSENSE */ - TEMP_SENSOR_SYSTHERM0, /* BD99992GW SYSTHERM0 */ - TEMP_SENSOR_SYSTHERM1, /* BD99992GW SYSTHERM1 */ - TEMP_SENSOR_SYSTHERM2, /* BD99992GW SYSTHERM2 */ - TEMP_SENSOR_SYSTHERM3, /* BD99992GW SYSTHERM3 */ + TEMP_SENSOR_BATTERY, /* BD99956GW TSENSE */ + TEMP_SENSOR_SYSTHERM0, /* BD99992GW SYSTHERM0 */ + TEMP_SENSOR_SYSTHERM1, /* BD99992GW SYSTHERM1 */ + TEMP_SENSOR_SYSTHERM2, /* BD99992GW SYSTHERM2 */ + TEMP_SENSOR_SYSTHERM3, /* BD99992GW SYSTHERM3 */ TEMP_SENSOR_COUNT }; @@ -205,29 +205,24 @@ enum sensor_id { }; /* LID_ALS needs to be polled */ -#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ALS) +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ALS) -enum adc_channel { - ADC_AMON_BMON, - ADC_PSYS, - ADC_CH_COUNT -}; +enum adc_channel { ADC_AMON_BMON, ADC_PSYS, ADC_CH_COUNT }; /* * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Board specific handlers */ int board_get_version(void); @@ -240,33 +235,33 @@ void board_reset_pd_mcu(void); * vs. names hard-coded in various parts of the EC codebase. */ -#define GPIO_AC_PRESENT GPIO_ROP_EC_ACOK -#define GPIO_BATTERY_PRESENT_L GPIO_EC_BATT_PRES_L -#define GPIO_BOARD_VERSION1 GPIO_EC_BRD_ID1 -#define GPIO_BOARD_VERSION2 GPIO_EC_BRD_ID2 -#define GPIO_BOARD_VERSION3 GPIO_EC_BRD_ID3 -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KB_ROW02_INV -#define GPIO_PCH_ACOK GPIO_EC_PCH_ACPRESENT -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_L -#define GPIO_PCH_RSMRST_L GPIO_RSMRST_L -#define GPIO_PCH_SLP_SUS_L GPIO_SLP_SUS_L_PCH -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_L -#define GPIO_PMIC_DPWROK GPIO_ROP_DSW_PWROK_EC -#define GPIO_PMIC_SLP_SUS_L GPIO_SLP_SUS_L_PMIC -#define GPIO_POWER_BUTTON_L GPIO_MECH_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_ROP_EC_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_USB_C0_5V_EN GPIO_EN_USB_C0_5V_OUT -#define GPIO_USB_C0_PD_RST_L GPIO_USB_PD_RST_L -#define GPIO_USB_C1_5V_EN GPIO_EN_USB_C1_5V_OUT -#define GPIO_USB_C1_PD_RST_L GPIO_USB_PD_RST_L -#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_AC_PRESENT GPIO_ROP_EC_ACOK +#define GPIO_BATTERY_PRESENT_L GPIO_EC_BATT_PRES_L +#define GPIO_BOARD_VERSION1 GPIO_EC_BRD_ID1 +#define GPIO_BOARD_VERSION2 GPIO_EC_BRD_ID2 +#define GPIO_BOARD_VERSION3 GPIO_EC_BRD_ID3 +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KB_ROW02_INV +#define GPIO_PCH_ACOK GPIO_EC_PCH_ACPRESENT +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_RSMRST_L +#define GPIO_PCH_SLP_SUS_L GPIO_SLP_SUS_L_PCH +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_L +#define GPIO_PMIC_DPWROK GPIO_ROP_DSW_PWROK_EC +#define GPIO_PMIC_SLP_SUS_L GPIO_SLP_SUS_L_PMIC +#define GPIO_POWER_BUTTON_L GPIO_MECH_PWR_BTN_ODL +#define GPIO_PG_EC_RSMRST_ODL GPIO_ROP_EC_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_USB_C0_5V_EN GPIO_EN_USB_C0_5V_OUT +#define GPIO_USB_C0_PD_RST_L GPIO_USB_PD_RST_L +#define GPIO_USB_C1_5V_EN GPIO_EN_USB_C1_5V_OUT +#define GPIO_USB_C1_PD_RST_L GPIO_USB_PD_RST_L +#define GPIO_WP_L GPIO_EC_WP_L /* ps8751 requires 1ms reset down assertion */ -#define PS8XXX_RST_L_RST_H_DELAY_MS 1 +#define PS8XXX_RST_L_RST_H_DELAY_MS 1 -#define ATLAS_REV_FIXED_EC_WP 4 +#define ATLAS_REV_FIXED_EC_WP 4 #endif /* __CROS_EC_BOARD_H */ diff --git a/board/atlas/build.mk b/board/atlas/build.mk index f1619f73cd..b7eeeb0a61 100644 --- a/board/atlas/build.mk +++ b/board/atlas/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/atlas/ec.tasklist b/board/atlas/ec.tasklist index 33e3cccb16..b0bf043717 100644 --- a/board/atlas/ec.tasklist +++ b/board/atlas/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/atlas/gpio.inc b/board/atlas/gpio.inc index 4ce44cc130..ea76ab8841 100644 --- a/board/atlas/gpio.inc +++ b/board/atlas/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/atlas/led.c b/board/atlas/led.c index ec46d9d206..2a297848e3 100644 --- a/board/atlas/led.c +++ b/board/atlas/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,14 +17,14 @@ const enum ec_led_id supported_led_ids[] = { }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -struct pwm_led led_color_map[EC_LED_COLOR_COUNT] = { - /* Red, Green, Blue */ - [EC_LED_COLOR_RED] = { 70, 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 35, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, - [EC_LED_COLOR_YELLOW] = { 55, 15, 0 }, - [EC_LED_COLOR_WHITE] = { 62, 100, 31 }, - [EC_LED_COLOR_AMBER] = { 100, 31, 0 }, +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Red, Green, Blue */ + [EC_LED_COLOR_RED] = { 70, 0, 0 }, + [EC_LED_COLOR_GREEN] = { 0, 35, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, + [EC_LED_COLOR_YELLOW] = { 55, 15, 0 }, + [EC_LED_COLOR_WHITE] = { 62, 100, 31 }, + [EC_LED_COLOR_AMBER] = { 100, 31, 0 }, }; /* diff --git a/board/atlas/usb_pd_policy.c b/board/atlas/usb_pd_policy.c index cb9a460330..6ade3c0b82 100644 --- a/board/atlas/usb_pd_policy.c +++ b/board/atlas/usb_pd_policy.c @@ -1,34 +1,34 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "chipset.h" #include "common.h" #include "console.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "registers.h" #include "system.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { @@ -38,9 +38,9 @@ int board_vbus_source_enabled(int port) static void board_vbus_update_source_current(int port) { enum gpio_signal gpio_5v_en = port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN; + GPIO_USB_C0_5V_EN; enum gpio_signal gpio_3a_en = port ? GPIO_EN_USB_C1_3A : - GPIO_EN_USB_C0_3A; + GPIO_EN_USB_C0_3A; /* * 1.5 vs 3.0 A limit is controlled by a dedicated gpio where @@ -67,8 +67,8 @@ int pd_snk_is_vbus_provided(int port) int pd_set_power_supply_ready(int port) { /* Disable charging */ - gpio_set_level(port ? GPIO_EN_USB_C1_CHARGE_L : - GPIO_EN_USB_C0_CHARGE_L, 1); + gpio_set_level(port ? GPIO_EN_USB_C1_CHARGE_L : GPIO_EN_USB_C0_CHARGE_L, + 1); /* Ensure we advertise the proper available current quota */ charge_manager_source_port(port, 1); @@ -111,15 +111,12 @@ int pd_check_vconn_swap(int port) return gpio_get_level(GPIO_PMIC_SLP_SUS_L); } -__override void pd_execute_data_swap(int port, - enum pd_data_role data_role) +__override void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* Only port 0 supports device mode. */ if (port != 0) return; - gpio_set_level(GPIO_USB2_ID, - (data_role == PD_ROLE_UFP) ? 1 : 0); - gpio_set_level(GPIO_USB2_VBUSSENSE, - (data_role == PD_ROLE_UFP) ? 1 : 0); + gpio_set_level(GPIO_USB2_ID, (data_role == PD_ROLE_UFP) ? 1 : 0); + gpio_set_level(GPIO_USB2_VBUSSENSE, (data_role == PD_ROLE_UFP) ? 1 : 0); } diff --git a/board/atlas/vif_override.xml b/board/atlas/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/atlas/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/atlas_ish/board.c b/board/atlas_ish/board.c deleted file mode 100644 index 066767638c..0000000000 --- a/board/atlas_ish/board.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Atlas ISH board-specific configuration */ - -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "math_util.h" -#include "task.h" -#include "uart.h" - -#include "gpio_list.h" /* has to be included last */ -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -/* I2C port map */ -const struct i2c_port_t i2c_ports[] = { - {"trackpad", I2C_PORT_TP, 1000, - GPIO_I2C_PORT_TP_SCL, GPIO_I2C_PORT_TP_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/atlas_ish/board.h b/board/atlas_ish/board.h deleted file mode 100644 index 4e590f033e..0000000000 --- a/board/atlas_ish/board.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Atlas ISH board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* - * Allow dangerous commands. - * TODO: Remove this config before production. - */ -#define CONFIG_SYSTEM_UNLOCKED - -/* - * By default, enable all console messages except HC, ACPI and event - * The sensor stack is generating a lot of activity. - */ -#undef CONFIG_HOSTCMD_DEBUG_MODE -#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF - -/* ISH specific*/ -#undef CONFIG_DEBUG_ASSERT -#define CONFIG_CLOCK_CRYSTAL -/* EC */ -#define CONFIG_FLASH_SIZE 0x80000 -#define CONFIG_FPU -#define CONFIG_I2C -#define CONFIG_I2C_MASTER - -/* HID subsystem */ -#define CONFIG_HID_HECI - -/* I2C ports */ -#define I2C_PORT_TP ISH_I2C0 -#define GPIO_I2C_PORT_TP_SCL GPIO_ISH_I2C0_SCL -#define GPIO_I2C_PORT_TP_SDA GPIO_ISH_I2C0_SDA - -/* Undefine unfeatures */ -#undef CONFIG_CMD_HASH -#undef CONFIG_CMD_I2C_SCAN -#undef CONFIG_CMD_I2C_XFER -#undef CONFIG_CMD_KEYBOARD -#undef CONFIG_CMD_POWER_AP -#undef CONFIG_CMD_POWERINDEBUG -#undef CONFIG_CMD_SHMEM -#undef CONFIG_CMD_TIMERINFO -#undef CONFIG_EXTPOWER -#undef CONFIG_KEYBOARD_KSO_BASE -#undef CONFIG_FLASH -#undef CONFIG_FMAP -#undef CONFIG_LID_SWITCH -#undef CONFIG_SWITCH -#undef CONFIG_WATCHDOG - -/* Modules we want to exclude */ -#undef CONFIG_CMD_ACCELS -#undef CONFIG_CMD_HASH -#undef CONFIG_CMD_TEMP_SENSOR -#undef CONFIG_CMD_TIMERINFO -#undef CONFIG_ADC -#undef CONFIG_SHA256 - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/atlas_ish/build.mk b/board/atlas_ish/build.mk deleted file mode 100644 index 9cdcbb2253..0000000000 --- a/board/atlas_ish/build.mk +++ /dev/null @@ -1,13 +0,0 @@ -# -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -CHIP:=ish -CHIP_FAMILY:=ish3 -CHIP_VARIANT:=ish3p0 - -board-y=board.o diff --git a/board/atlas_ish/ec.tasklist b/board/atlas_ish/ec.tasklist deleted file mode 100644 index 15f856131a..0000000000 --- a/board/atlas_ish/ec.tasklist +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, HUGE_TASK_STACK_SIZE, 0) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE, 0) \ - TASK_ALWAYS(HECI_RX, heci_rx_task, NULL, HUGE_TASK_STACK_SIZE, 0) \ - TASK_ALWAYS(IPC_MNG, ipc_mng_task, NULL, LARGER_TASK_STACK_SIZE, 0) diff --git a/board/atlas_ish/gpio.inc b/board/atlas_ish/gpio.inc deleted file mode 100644 index 0ddac6ccbe..0000000000 --- a/board/atlas_ish/gpio.inc +++ /dev/null @@ -1,15 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Trackpad interrupt pin */ -/*TODO: touchpad driver is not in gerrit yet, so comment out this for now */ -/*GPIO_INT(TOUCHPAD_INT, PIN(1), GPIO_INT_F_FALLING, touchpad_event)*/ - -/* Those are used by common code, don't change*/ -UNIMPLEMENTED(ENTERING_RW) -UNIMPLEMENTED(ISH_I2C0_SDA) -UNIMPLEMENTED(ISH_I2C0_SCL) diff --git a/board/aurash/board.c b/board/aurash/board.c new file mode 100644 index 0000000000..8a0a5218fe --- /dev/null +++ b/board/aurash/board.c @@ -0,0 +1,529 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "builtin/assert.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/cec/bitbang.h" +#include "driver/tcpm/tcpci.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +/******************************************************************************/ +/* Power on by HDMI/ DP monitor */ +struct monitor_config { + enum gpio_signal gpio; + uint8_t state; +}; + +static struct monitor_config monitors[MONITOR_COUNT] = { + [HDMI1_MONITOR] = { + .gpio = GPIO_HDMI1_MONITOR_ON, + .state = MONITOR_OFF, + }, + + [HDMI2_MONITOR] = { + .gpio = GPIO_HDMI2_MONITOR_ON, + .state = MONITOR_OFF, + }, + + [OPTION_MONITOR] = { + .gpio = GPIO_OPTION_MONITOR_ON, + .state = MONITOR_OFF, + }, +}; + +/******************************************************************************/ + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + case CHARGE_PORT_TYPEC1: + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static uint8_t usbc_overcurrent; + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) + ec_bj_power(&pi.voltage, &pi.current); + + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +static void adp_state_init(void) +{ + ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT); + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +static void board_init(void) +{ + int i; + + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + gpio_enable_interrupt(GPIO_HDMI_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A2_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A3_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A4_OC_ODL); + + if (ec_cfg_power_on_monitor() == POWER_ON_MONITOR_ENABLE) { + /* + * Only enable interrupt when fw_config set it as enable. + */ + gpio_enable_interrupt(GPIO_HDMI1_MONITOR_ON); + gpio_enable_interrupt(GPIO_HDMI2_MONITOR_ON); + gpio_enable_interrupt(GPIO_OPTION_MONITOR_ON); + + /* + * Initialize the monitor state to corresponding gpio state. + */ + for (i = 0; i < MONITOR_COUNT; i++) + monitors[i].state = gpio_get_level(monitors[i].gpio); + } +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Check that port number is valid. */ + if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) + return; + usbc_overcurrent = is_overcurrented; +} +/* + * Power monitoring and management. + * + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * The overall goal is to gracefully manage the power demand so that + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type A BC1.2 rear port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 3 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A_FRONT BIT(0) +#define THROT_TYPE_A_REAR BIT(1) +#define THROT_TYPE_C0 BIT(2) +#define THROT_TYPE_C1 BIT(3) +#define THROT_PROCHOT BIT(5) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +static void power_monitor(void) +{ + static uint32_t current_state; + static uint32_t history[POWER_READINGS]; + static uint8_t index; + int32_t delay; + uint32_t new_state = 0, diff; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + /* + * Clear the first entry of the power table so that + * it is re-initilalised when the CPU starts. + */ + history[0] = 0; + } else { + int32_t charger_mw; + + delay = POWER_DELAY_MS * MSEC; + /* + * Get current charger limit (in mw). + * If not configured yet, skip. + */ + charger_mw = charge_manager_get_power_limit_uw() / 1000; + if (charger_mw != 0) { + int32_t gap, total, max, power; + int i; + + /* + * Read power usage. + */ + power = (adc_read_channel(ADC_VBUS) * + adc_read_channel(ADC_PPVAR_IMON)) / + 1000; + /* Init power table */ + if (history[0] == 0) { + for (i = 0; i < POWER_READINGS; i++) + history[i] = power; + } + /* + * Update the power readings and + * calculate the average and max. + */ + history[index] = power; + index = (index + 1) % POWER_READINGS; + total = 0; + max = history[0]; + for (i = 0; i < POWER_READINGS; i++) { + total += history[i]; + if (history[i] > max) + max = history[i]; + } + /* + * For Type-C power supplies, there is + * less tolerance for exceeding the rating, + * so use the max power that has been measured + * over the measuring period. + * For barrel-jack supplies, the rating can be + * exceeded briefly, so use the average. + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + power = max; + else + power = total / POWER_READINGS; + /* + * Calculate gap, and if negative, power + * demand is exceeding configured power budget, so + * throttling is required to reduce the demand. + */ + gap = charger_mw - power; + /* + * Limiting type-A power rear ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_REAR; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * Limiting type-A power front ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_FRONT; + if (!(current_state & THROT_TYPE_A_FRONT)) + gap += POWER_GAIN_TYPE_A; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(0) && gap <= 0) { + new_state |= THROT_TYPE_C0; + if (!(current_state & THROT_TYPE_C0)) + gap += POWER_GAIN_TYPE_C; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(1) && gap <= 0) { + new_state |= THROT_TYPE_C1; + if (!(current_state & THROT_TYPE_C1)) + gap += POWER_GAIN_TYPE_C; + } + /* + * As a last resort, turn on PROCHOT to + * throttle the CPU. + */ + if (gap <= 0) + new_state |= THROT_PROCHOT; + } + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_C0) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C0) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + } + if (diff & THROT_TYPE_C1) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C1) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(1, rp); + tcpm_select_rp_value(1, rp); + pd_update_contract(1); + } + if (diff & THROT_TYPE_A_REAR) { + int typea_bc = (new_state & THROT_TYPE_A_REAR) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR1_OD, typea_bc); + } + if (diff & THROT_TYPE_A_FRONT) { + int typea_bc = (new_state & THROT_TYPE_A_FRONT) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR2_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, power_monitor, HOOK_PRIO_INIT_ADC + 1); + +/******************************************************************************/ +/* + * System power on and wake up by monitor power button. + * + * After pressing power button of monitor for power on, monitor will send power + * on signal with 3.3V / 200ms to DT. If DT detect that pulse, there are three + * DT behavior: + * + * - Do nothing in state S0. + * - Wake up from state S0ix. + * - Power on from state S5 and G3. + */ + +/* Debounce time for HDMI power button press */ +#define MONITOR_DEBOUNCE_MS 100 + +static void monitor_irq_deferred(void); +DECLARE_DEFERRED(monitor_irq_deferred); + +static void monitor_irq_deferred(void) +{ + int i; + + for (i = 0; i < MONITOR_COUNT; i++) { + if (monitors[i].state && gpio_get_level(monitors[i].gpio)) { + /* + * System power on from state S5 and G3. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + chipset_power_on(); + /* + * System wake up from state S0ix. + */ + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + power_button_simulate_press(200); + } + monitors[i].state = MONITOR_OFF; + } +} + +/* Power on by HDMI/ DP monitor. */ +void monitor_interrupt(enum gpio_signal signal) +{ + /* + * Power on by HDMI/ DP monitor only works + * when system is not in S0. + */ + if (chipset_in_state(CHIPSET_STATE_ON)) + return; + + if (ec_cfg_power_on_monitor() == POWER_ON_MONITOR_ENABLE) { + switch (signal) { + case GPIO_HDMI1_MONITOR_ON: + monitors[HDMI1_MONITOR].state = MONITOR_ON; + break; + case GPIO_HDMI2_MONITOR_ON: + monitors[HDMI2_MONITOR].state = MONITOR_ON; + break; + case GPIO_OPTION_MONITOR_ON: + monitors[OPTION_MONITOR].state = MONITOR_ON; + break; + default: + break; + } + hook_call_deferred(&monitor_irq_deferred_data, + MONITOR_DEBOUNCE_MS * MSEC); + } +} diff --git a/board/aurash/board.h b/board/aurash/board.h new file mode 100644 index 0000000000..80848e70f0 --- /dev/null +++ b/board/aurash/board.h @@ -0,0 +1,191 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Aurash board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +#define CONFIG_MP2964 + +/* Barrel Jack */ +#define DEDICATED_CHARGE_PORT 2 + +/* HDMI CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMI_CEC_OUT +#define CEC_GPIO_IN GPIO_HDMI_CEC_IN +#define CEC_GPIO_PULL_UP GPIO_HDMI_CEC_PULL_UP + +/* USB Type A Features */ +#define USB_PORT_COUNT 4 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USB_PD_PPC +#define CONFIG_USBC_RETIMER_INTEL_BB + +#undef CONFIG_CMD_POWERINDEBUG + +#define CONFIG_USBC_PPC_SYV682X +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* The design should support up to 100W. */ +/* TODO(b/197702356): Set the max PD to 60W now and change it + * to 100W after we verify it. + */ +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL +#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_ODL + +/* I2C Bus Configuration */ + +#define I2C_PORT_USB_C0_C1_TCPC NPCX_I2C_PORT1_0 + +#define I2C_PORT_USB_C0_C1_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_A0_A1_MIX NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C1_BC12 NPCX_I2C_PORT2_0 + +#define I2C_PORT_USB_C0_C1_MUX NPCX_I2C_PORT3_0 + +#define I2C_PORT_QI NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x57 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* ADC */ +#define CONFIG_ADC + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_TYPEC1, + CHARGE_PORT_BARRELJACK, + CHARGE_PORT_ENUM_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1_SSD, + ADC_TEMP_SENSOR_2_CPU_VR, + ADC_TEMP_SENSOR_4_DIMM, + ADC_VBUS, + ADC_PPVAR_IMON, /* ADC3 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_SSD, + TEMP_SENSOR_2_CPU_VR, + TEMP_SENSOR_4_DIMM, + TEMP_SENSOR_COUNT +}; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C1_NCT38XX, IOEX_PORT_COUNT }; + +enum pwm_channel { + PWM_CH_LED_AMBER, /* PWM0 */ + PWM_CH_LED_BLUE, /* PWM2 */ + PWM_CH_COUNT +}; + +enum monitor_port { + HDMI1_MONITOR, + HDMI2_MONITOR, + OPTION_MONITOR, + MONITOR_COUNT +}; + +enum monitor_state { MONITOR_OFF, MONITOR_ON }; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +extern void adp_connect_interrupt(enum gpio_signal signal); +extern void monitor_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/aurash/build.mk b/board/aurash/build.mk new file mode 100644 index 0000000000..8f1b8bfc78 --- /dev/null +++ b/board/aurash/build.mk @@ -0,0 +1,21 @@ +# -*- makefile -*- +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Aurash board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brask + +board-y= +board-y+=board.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/aurash/ec.tasklist b/board/aurash/ec.tasklist new file mode 100644 index 0000000000..a3189950ab --- /dev/null +++ b/board/aurash/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(1) | BIT(0)), LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/aurash/fw_config.c b/board/aurash/fw_config.c new file mode 100644 index 0000000000..2c312acea6 --- /dev/null +++ b/board/aurash/fw_config.c @@ -0,0 +1,73 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union aurash_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for aurash if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union aurash_cbi_fw_config fw_config_defaults = { + .bj_power = BJ_90W, + .po_mon = POWER_ON_MONITOR_ENABLE, +}; + +/* + * Barrel-jack power adapter ratings. + */ +static const struct { + int voltage; + int current; +} bj_power[] = { + [BJ_90W] = { /* 0 - 90W (also default) */ + .voltage = 19000, + .current = 4740 }, + [BJ_135W] = { /* 1 - 135W */ + .voltage = 19500, + .current = 6920 }, +}; + +/**************************************************************************** + * Aurash FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union aurash_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +void ec_bj_power(uint32_t *voltage, uint32_t *current) +{ + unsigned int bj; + + bj = fw_config.bj_power; + /* Out of range value defaults to 0 */ + if (bj >= ARRAY_SIZE(bj_power)) + bj = 0; + *voltage = bj_power[bj].voltage; + *current = bj_power[bj].current; +} + +enum ec_cfg_power_on_monitor ec_cfg_power_on_monitor(void) +{ + return fw_config.po_mon; +} diff --git a/board/aurash/fw_config.h b/board/aurash/fw_config.h new file mode 100644 index 0000000000..e498831966 --- /dev/null +++ b/board/aurash/fw_config.h @@ -0,0 +1,53 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_AURASH_FW_CONFIG_H_ +#define __BOARD_AURASH_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Aurash board. + * + * Source of truth is the project/brask/aurash/config.star configuration file. + */ + +enum ec_cfg_bj_power { BJ_90W = 0, BJ_135W = 1 }; + +enum ec_cfg_power_on_monitor { + POWER_ON_MONITOR_ENABLE = 0, + POWER_ON_MONITOR_DISABLE = 1 +}; + +union aurash_cbi_fw_config { + struct { + uint32_t bj_power : 2; + uint32_t mlb_usb_tbt : 2; + uint32_t storage : 2; + uint32_t audio : 1; + enum ec_cfg_power_on_monitor po_mon : 1; + uint32_t reserved_1 : 24; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union aurash_cbi_fw_config get_fw_config(void); + +/** + * Get the barrel-jack power from FW_CONFIG. + */ +void ec_bj_power(uint32_t *voltage, uint32_t *current); + +/** + * Get enable/disable power on by monitor from FW_CONFIG. + */ +enum ec_cfg_power_on_monitor ec_cfg_power_on_monitor(void); + +#endif /* __BOARD_AURASH_FW_CONFIG_H_ */ diff --git a/board/aurash/gpio.inc b/board/aurash/gpio.inc new file mode 100644 index 0000000000..702c79df25 --- /dev/null +++ b/board/aurash/gpio.inc @@ -0,0 +1,177 @@ +/* -*- mode:c -*- + * + * Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C1_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(EC_RECOVERY_BTN_ODL, PIN(2, 3), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(USB_C1_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(HDMI1_MONITOR_ON, PIN(B, 4), GPIO_INT_RISING, monitor_interrupt) +GPIO_INT(HDMI2_MONITOR_ON, PIN(B, 5), GPIO_INT_RISING, monitor_interrupt) +GPIO_INT(OPTION_MONITOR_ON, PIN(1, 0), GPIO_INT_RISING, monitor_interrupt) + +/* CCD */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + +/* Security */ +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Fan */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) + +/* ADC, need to check the usage */ +GPIO(ANALOG_PPVAR_PWR_IN_IMON_EC, PIN(4, 2), GPIO_INPUT) + +/* BarrelJack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 7), GPIO_OUT_LOW) + +/* Chipset PCH */ +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) + +/* Button */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(GSC_EC_RECOVERY_BTN_ODL, PIN(2, 2), GPIO_INPUT) + +/* NFC */ +/* TODO(b/194068530): Enable NFC */ +GPIO(NFC_COIL_ACT_L, PIN(D, 4), GPIO_INPUT) +GPIO(NFC_LOW_POWER_MODE, PIN(9, 5), GPIO_OUT_HIGH) +GPIO(NFC_CARD_DET_L, PIN(A, 3), GPIO_INPUT) +GPIO(EN_NFC_BUZZER, PIN(0, 5), GPIO_OUT_LOW) + +/* Wireless Charger */ +/* TODO(b/191418683): Implement Qi Driver */ +GPIO(EC_QI_PWR, PIN(D, 2), GPIO_OUT_HIGH) +GPIO(EC_I2C_QI_RESET_L, PIN(9, 3), GPIO_OUT_HIGH) +GPIO(EC_I2C_QI_INT_ODL, PIN(9, 6), GPIO_INPUT) + +/* HDMI */ +GPIO(HDMI_CONN_OC_ODL, PIN(2, 4), GPIO_INPUT) + +/* HDMI CEC */ +/* TODO(b/197474873): Enable HDMI CEC */ +GPIO(HDMI_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CEC_OUT, PIN(D, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMI_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH) + +/* I2C SCL/SDA */ +GPIO(EC_I2C_QI_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_QI_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_A1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_A1_MIX_SDA, PIN(E, 3), GPIO_INPUT) + +/* USBA */ +GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW) +GPIO(USB_A1_STATUS_L, PIN(2, 0), GPIO_INPUT) +GPIO(USB_A2_STATUS_L, PIN(1, 7), GPIO_INPUT) +GPIO(USB_A_LOW_PWR1_OD, PIN(1, 4), GPIO_OUT_LOW) +GPIO(USB_A_LOW_PWR2_OD, PIN(1, 1), GPIO_OUT_LOW) +GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH) +GPIO(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT) +GPIO(USB_A2_OC_ODL, PIN(2, 7), GPIO_INPUT) +GPIO(USB_A3_OC_ODL, PIN(2, 6), GPIO_INPUT) +GPIO(USB_A4_OC_ODL, PIN(0, 6), GPIO_INPUT) + +/* USBC */ +GPIO(USB_C0_C1_TCPC_RST_ODL, PIN(F, 5), GPIO_ODR_LOW) + +/* LAN */ +GPIO(LAN_PWR_GOOD, PIN(0, 2), GPIO_INPUT) + +/* LED */ +GPIO(LED_ORANGE_CONTROL, PIN(3, 1), GPIO_ODR_LOW) +GPIO(LED_BLUE_CONTROL, PIN(2, 5), GPIO_ODR_LOW) + +/* Option Board */ +GPIO(HDMI1_MONON_SIO, PIN(1, 6), GPIO_INPUT) +GPIO(HDMI2_MONON_SIO, PIN(1, 5), GPIO_INPUT) +GPIO(OPTION_MONON_SIO, PIN(2, 1), GPIO_INPUT) + +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C1_RT_RST_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C1_FRS_EN, EXPIN(IOEX_C1_NCT38XX, 0, 6), GPIO_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */ +UNUSED(PIN(9, 7)) /* GPIO97 */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2/FLPRG2_L */ +UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */ +UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */ +UNUSED(PIN(0, 4)) /* KSO13/GPIO04 */ +UNUSED(PIN(A, 2)) /* F_SCLK/GPIOA2 */ +UNUSED(PIN(5, 0)) /* GPIO50 */ +UNUSED(PIN(9, 4)) /* GPIO94 */ +UNUSED(PIN(A, 0)) /* F_CS0_L/GPIOA0 */ +UNUSED(PIN(3, 4)) /* GPIO34/PS2_DAT2/ADC6 */ +UNUSED(PIN(F, 3)) /* GPIOF3/I2C4_SCL1 */ +UNUSED(PIN(F, 2)) /* GPIOF2/I2C4_SDA1 */ +UNUSED(PIN(A, 7)) /* GPIOA7/PS2_DAT3/TB2/F_DIO3 */ +UNUSED(PIN(B, 7)) /* GPIOB7/PWM5 */ +UNUSED(PIN(7, 3)) /* GPIO73/TA2 */ diff --git a/board/aurash/i2c.c b/board/aurash/i2c.c new file mode 100644 index 0000000000..5df3b5b7e7 --- /dev/null +++ b/board/aurash/i2c.c @@ -0,0 +1,61 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C1 */ + .name = "tcpc0,1", + .port = I2C_PORT_USB_C0_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,1", + .port = I2C_PORT_USB_C0_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,1", + .port = I2C_PORT_USB_C0_C1_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_RT_SDA, + }, + { + /* I2C5 */ + .name = "wireless_charger", + .port = I2C_PORT_QI, + .kbps = 400, + .scl = GPIO_EC_I2C_QI_SCL, + .sda = GPIO_EC_I2C_QI_SDA, + }, + { + /* I2C6 */ + .name = "usba_mix0,1", + .port = I2C_PORT_USB_A0_A1_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C_USB_A0_A1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_A0_A1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL, + .sda = GPIO_EC_I2C_MISC_SDA, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/aurash/led.c b/board/aurash/led.c new file mode 100644 index 0000000000..21c4a2dafc --- /dev/null +++ b/board/aurash/led.c @@ -0,0 +1,281 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Brask. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_BLUE, + LED_AMBER, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int amber = 0; + int blue = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_AMBER: + amber = 1; + break; + case LED_BLUE: + blue = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (blue && duty) { + gpio_set_level(GPIO_LED_BLUE_CONTROL, 1); + pwm_set_duty(PWM_CH_LED_BLUE, duty); + } else { + gpio_set_level(GPIO_LED_BLUE_CONTROL, 0); + pwm_set_duty(PWM_CH_LED_BLUE, 0); + } + + if (amber && duty) { + gpio_set_level(GPIO_LED_ORANGE_CONTROL, 1); + pwm_set_duty(PWM_CH_LED_AMBER, duty); + } else { + gpio_set_level(GPIO_LED_ORANGE_CONTROL, 0); + pwm_set_duty(PWM_CH_LED_AMBER, 0); + } + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PERIOD (4 * SECOND) +#define LED_DUTY_CYCLE (25) +#define LED_PULSE_US (LED_PERIOD * LED_DUTY_CYCLE / 100 / 2) +/* 10 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (10 * MSEC) + +/* + * When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; + uint32_t time_off; +} led_pulse; + +/* + * LED_PERIOD = time_on + time_off; + * time_on = LED_PULSE_US * 2; + * time_off = LED_PERIOD - LED_PULSE_US * 2; + */ +#define CONFIG_TICK(interval, period, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), \ + LED_PERIOD - LED_PULSE_US * 2, (color)) + +static void config_tick(uint32_t interval, int duty_inc, int time_off, + enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; + led_pulse.time_off = time_off; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + next = (led_pulse.duty - led_pulse.duty_inc) ? + next : + next + led_pulse.time_off; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_PERIOD, LED_BLUE); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* + * Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_BLUE, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, 0, LED_AMBER); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_AMBER, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "blue")) { + set_color(id, LED_BLUE, 100); + } else if (!strcasecmp(argv[1], "amber")) { + set_color(id, LED_AMBER, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|blue|amber|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_AMBER] = 100; + brightness_range[EC_LED_COLOR_BLUE] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_BLUE]) + return set_color(id, LED_BLUE, brightness[EC_LED_COLOR_BLUE]); + else if (brightness[EC_LED_COLOR_AMBER]) + return set_color(id, LED_AMBER, brightness[EC_LED_COLOR_AMBER]); + else + return set_color(id, LED_OFF, 0); +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Blink alert if insufficient power per system_can_boot_ap(). */ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + led_alert(insufficient_power); +} diff --git a/board/aurash/pwm.c b/board/aurash/pwm.c new file mode 100644 index 0000000000..be400d2ea6 --- /dev/null +++ b/board/aurash/pwm.c @@ -0,0 +1,29 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_AMBER] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_LED_BLUE] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + pwm_enable(PWM_CH_LED_BLUE, 1); + pwm_enable(PWM_CH_LED_AMBER, 1); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/aurash/sensors.c b/board/aurash/sensors.c new file mode 100644 index 0000000000..517a6ed905 --- /dev/null +++ b/board/aurash/sensors.c @@ -0,0 +1,102 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_SSD] = { + .name = "TEMP_SSD", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CPU_VR] = { + .name = "TEMP_CPU_VR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DIMM] = { + .name = "TEMP_DIMM", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 20/(20+8.66)*50/200 current divider */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT * 1433, + .factor_div = (ADC_READ_MAX + 1) * 250, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_SSD] = { .name = "SSD", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_SSD }, + [TEMP_SENSOR_2_CPU_VR] = { .name = "CPU VR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CPU_VR }, + [TEMP_SENSOR_4_DIMM] = { .name = "DIMM", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DIMM }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +#define THERMAL_SSD \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_ssd = THERMAL_SSD; + +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HALT] = C_TO_K(125), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +#define THERMAL_DIMM \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HALT] = C_TO_K(95), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_dimm = + THERMAL_DIMM; +/* + * TODO(b/197478860): add the thermal sensor setting + */ +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_SSD] = THERMAL_SSD, + [TEMP_SENSOR_2_CPU_VR] = THERMAL_CPU, + [TEMP_SENSOR_4_DIMM] = THERMAL_DIMM, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/aurash/usbc_config.c b/board/aurash/usbc_config.c new file mode 100644 index 0000000000..68a08a2d45 --- /dev/null +++ b/board/aurash/usbc_config.c @@ -0,0 +1,345 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C1_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = IOEX_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C1) { + rst_signal = IOEX_USB_C1_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +__override int bb_retimer_reset(const struct usb_mux *me) +{ + /* + * TODO(b/193402306, b/195375738): Remove this once transition to + * QS Silicon is complete + */ + bb_retimer_power_enable(me, false); + msleep(5); + bb_retimer_power_enable(me, true); + msleep(25); + + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + enum gpio_signal tcpc_rst; + + tcpc_rst = GPIO_USB_C0_C1_TCPC_RST_ODL; + + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(tcpc_rst, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(tcpc_rst, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void enable_ioex(int ioex) +{ + ioex_init(ioex); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C1 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + enable_ioex(IOEX_C0_NCT38XX); + enable_ioex(IOEX_C1_NCT38XX); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C1_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return true; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/aurash/usbc_config.h b/board/aurash/usbc_config.h new file mode 100644 index 0000000000..28e43d0e9d --- /dev/null +++ b/board/aurash/usbc_config.h @@ -0,0 +1,15 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Aurash board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/aurash/vif_override.xml b/board/aurash/vif_override.xml new file mode 100644 index 0000000000..9fc397cd40 --- /dev/null +++ b/board/aurash/vif_override.xml @@ -0,0 +1,129 @@ + + + + + 2 + 0 + + + + + + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 463E + + + + + + + + + + Gen 3 (40Gb) + + + + + + + + HBR3 + 4 Lanes + + + + USB 3.2 Gen 2x1 + + + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + + + + + PSD + PDUSB Host + + + + + + + + Gen 3 (40Gb) + + + + + + + + HBR3 + 4 Lanes + + + + USB 3.2 Gen 2x1 + + + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + + + + + PSD + PDUSB Host + + diff --git a/board/baklava/board.c b/board/baklava/board.c new file mode 100644 index 0000000000..7b945a11d9 --- /dev/null +++ b/board/baklava/board.c @@ -0,0 +1,356 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Baklava board-specific configuration */ + +#include "common.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/stm32gx.h" +#include "driver/tcpm/tcpci.h" +#include "driver/usb_mux/ps8822.h" +#include "ec_version.h" +#include "gpio.h" +#include "hooks.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "uart.h" +#include "usb_descriptor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_dp_ufp.h" +#include "usb_pe_sm.h" +#include "usb_prl_sm.h" +#include "usb_tc_sm.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +#define QUICHE_PD_DEBUG_LVL 1 + +#ifdef SECTION_IS_RW +#define CROS_EC_SECTION "RW" +#else +#define CROS_EC_SECTION "RO" +#endif + +#ifdef SECTION_IS_RW +static int pd_dual_role_init[CONFIG_USB_PD_PORT_MAX_COUNT] = { + PD_DRP_TOGGLE_ON, +}; + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_HOST_USBC_PPC_INT_ODL: + sn5s330_interrupt(USB_PD_PORT_HOST); + break; + default: + break; + } +} + +void hpd_interrupt(enum gpio_signal signal) +{ + usb_pd_hpd_edge_event(signal); +} + +static void board_uf_manage_vbus_interrupt(enum gpio_signal signal) +{ + baseboard_usb3_check_state(); +} + +static void board_pwr_btn_interrupt(enum gpio_signal signal) +{ + baseboard_power_button_evt(gpio_get_level(signal)); +} + +static void board_usbc_usb3_interrupt(enum gpio_signal signal) +{ + baseboard_usbc_usb3_irq(); +} +#endif /* SECTION_IS_RW */ + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* + * Table GPIO signals control both power rails and reset lines to various chips + * on the board. The order the signals are changed and the delay between GPIO + * signals is driven by USB/MST hub power sequencing requirements. + */ +const struct power_seq board_power_seq[] = { + { GPIO_EN_AC_JACK, 1, 20 }, + { GPIO_EC_DFU_MUX_CTRL, 0, 0 }, + { GPIO_EN_PP5000_A, 1, 31 }, + { GPIO_MST_LP_CTL_L, 1, 0 }, + { GPIO_EN_PP3300_B, 1, 1 }, + { GPIO_EN_PP1100_A, 1, 100 + 30 }, + { GPIO_EN_BB, 1, 30 }, + { GPIO_EN_PP1050_A, 1, 30 }, + { GPIO_EN_PP1200_A, 1, 20 }, + { GPIO_EN_PP5000_C, 1, 20 }, + { GPIO_EN_PP5000_HSPORT, 1, 31 }, + { GPIO_EN_DP_SINK, 1, 80 }, + { GPIO_MST_RST_L, 1, 61 }, + { GPIO_EC_HUB2_RESET_L, 1, 41 }, + { GPIO_EC_HUB3_RESET_L, 1, 33 }, + { GPIO_DP_SINK_RESET, 1, 100 }, + { GPIO_USBC_UF_RESET_L, 1, 33 }, + { GPIO_DEMUX_DP_HDMI_PD_N, 1, 10 }, + { GPIO_DEMUX_DP_HDMI_MODE, 1, 5 }, +}; +const size_t board_power_seq_count = ARRAY_SIZE(board_power_seq); + +/* + * Define the strings used in our USB descriptors. + */ +const void *const usb_strings[] = { + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Acer"), + [USB_STR_PRODUCT] = USB_STRING_DESC("D501"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = + USB_STRING_DESC(CROS_EC_SECTION ":" CROS_EC_VERSION32), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), +}; +BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); + +#ifndef SECTION_IS_RW +/* USB-C PPC Configuration */ +struct ppc_config_t ppc_chips[] = { + [USB_PD_PORT_HOST] = { + .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + }, +}; +#endif + +#ifdef SECTION_IS_RW +/* + * PS8802 set mux board tuning. + * Adds in board specific gain and DP lane count configuration + */ +static int board_ps8822_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) + rv = ps8822_set_dp_rx_eq(me, PS8822_DPEQ_LEVEL_UP_20DB); + + return rv; +} + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &stm32gx_tcpm_drv, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_HOST, + .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = PS8822_I2C_ADDR3_FLAG, + .driver = &ps8822_usb_mux_driver, + .board_set = &board_ps8822_mux_set, + }, + }, +}; + +/* USB-C PPC Configuration */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + [USB_PD_PORT_USB3] = { .i2c_port = I2C_PORT_I2C3, + .i2c_addr_flags = SN5S330_ADDR1_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +const struct hpd_to_pd_config_t hpd_config = { + .port = USB_PD_PORT_HOST, + .signal = GPIO_DDI_MST_IN_HPD, +}; + +void board_reset_pd_mcu(void) +{ + cprints(CC_SYSTEM, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USBC_UF_RESET_L, 0); + msleep(PS8805_FW_INIT_DELAY_MS); + gpio_set_level(GPIO_USBC_UF_RESET_L, 1); + msleep(PS8805_FW_INIT_DELAY_MS); +} + +void board_enable_usbc_interrupts(void) +{ + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_HOST_USBC_PPC_INT_ODL); + /* Enable HPD interrupt */ + gpio_enable_interrupt(GPIO_DDI_MST_IN_HPD); + /* Enable VBUS control interrupt for C1 */ + gpio_enable_interrupt(GPIO_USBC_UF_MUX_VBUS_EN); +} + +void board_disable_usbc_interrupts(void) +{ + /* Disable PPC interrupts. */ + gpio_disable_interrupt(GPIO_HOST_USBC_PPC_INT_ODL); + /* Disable HPD interrupt */ + gpio_disable_interrupt(GPIO_DDI_MST_IN_HPD); + /* Disable VBUS control interrupt for C1 */ + gpio_disable_interrupt(GPIO_USBC_UF_MUX_VBUS_EN); +} + +void board_tcpc_init(void) +{ + board_reset_pd_mcu(); + + /* Enable board usbc interrupts */ + board_enable_usbc_interrupts(); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 2); + +enum pd_dual_role_states board_tc_get_initial_drp_mode(int port) +{ + return pd_dual_role_init[port]; +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + /* + * CONFIG_USB_PD_PORT_MAX_COUNT must be defined to account for C0 + * and C1, but TCPMv2 only knows about C0, as C1 is a type-c only + * port that is managed directly by the PS8803 TCPC. + */ + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; +} + +int ppc_get_alert_status(int port) +{ + if (port == USB_PD_PORT_HOST) + return gpio_get_level(GPIO_HOST_USBC_PPC_INT_ODL) == 0; + + return 0; +} + +uint16_t tcpc_get_alert_status(void) +{ + return 0; +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/174825406): check correct operation for honeybuns */ +} + +int dock_get_mf_preference(void) +{ + return MF_ON; +} + +static void board_usb_tc_connect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* + * The EC needs to indicate to the MST hub when the host port is + * attached. GPIO_UFP_PLUG_DET is used for this purpose. + */ + if (port == USB_PD_PORT_HOST) + gpio_set_level(GPIO_UFP_PLUG_DET, 0); +} +DECLARE_HOOK(HOOK_USB_PD_CONNECT, board_usb_tc_connect, HOOK_PRIO_DEFAULT); + +static void board_usb_tc_disconnect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* Only the host port disconnect is relevant */ + if (port == USB_PD_PORT_HOST) + gpio_set_level(GPIO_UFP_PLUG_DET, 1); +} +DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, board_usb_tc_disconnect, + HOOK_PRIO_DEFAULT); + +#endif /* SECTION_IS_RW */ + +static void board_init(void) +{ +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_debug_gpio_1_pulse(void) +{ + gpio_set_level(GPIO_TRIGGER_1, 0); +} +DECLARE_DEFERRED(board_debug_gpio_1_pulse); + +static void board_debug_gpio_2_pulse(void) +{ + gpio_set_level(GPIO_TRIGGER_2, 0); +} +DECLARE_DEFERRED(board_debug_gpio_2_pulse); + +void board_debug_gpio(enum debug_gpio trigger, int level, int pulse_usec) +{ + switch (trigger) { + case TRIGGER_1: + gpio_set_level(GPIO_TRIGGER_1, level); + if (pulse_usec) + hook_call_deferred(&board_debug_gpio_1_pulse_data, + pulse_usec); + break; + case TRIGGER_2: + gpio_set_level(GPIO_TRIGGER_2, level); + if (pulse_usec) + hook_call_deferred(&board_debug_gpio_2_pulse_data, + pulse_usec); + break; + default: + CPRINTS("bad debug gpio selection"); + break; + } +} + +static int command_dplane(int argc, const char **argv) +{ + char *e; + int lane; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + lane = strtoi(argv[1], &e, 10); + + if ((lane != 2) && (lane != 4)) + return EC_ERROR_PARAM1; + + /* put MST into reset */ + gpio_set_level(GPIO_MST_RST_L, 0); + msleep(1); + /* Set lane control to requested level */ + gpio_set_level(GPIO_MST_HUB_LANE_SWITCH, lane == 2 ? 1 : 0); + msleep(1); + /* Take MST out of reset */ + gpio_set_level(GPIO_MST_RST_L, 1); + + ccprintf("MST lane set: %s, lane_ctrl = %d\n", + lane == 2 ? "2 lane" : "4 lane", + gpio_get_level(GPIO_MST_HUB_LANE_SWITCH)); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(dplane, command_dplane, "<2 | 4>", "MST lane control."); diff --git a/board/baklava/board.h b/board/baklava/board.h new file mode 100644 index 0000000000..8cbe1cdc76 --- /dev/null +++ b/board/baklava/board.h @@ -0,0 +1,98 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Baklava board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* Optional features */ +/* + * For MP release, CONFIG_SYSTEM_UNLOCKED must be undefined, and + * CONFIG_FLASH_PSTATE_LOCKED must be defined in order to enable write protect + * using option bytes WRP registers. + */ +#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ +#undef CONFIG_FLASH_PSTATE_LOCKED + +/* USB Type C and USB PD defines */ +#define USB_PD_PORT_HOST 0 +#define USB_PD_PORT_USB3 1 + +/* + * Only the host and display usbc ports are usb-pd capable. There is a 2nd usbc + * port, but this is type-c capable only. Only the PPC for this port needs to be + * controlled by FW. + */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_MUX_PS8822 + +#undef CONFIG_USB_VID +#define CONFIG_USB_VID 0x502 +#define CONFIG_USB_PID 0x1195 +#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ +#define CONFIG_USB_PD_IDENTITY_HW_VERS 1 +#define CONFIG_USB_PD_IDENTITY_SW_VERS 1 + +/* I2C port names */ +#define I2C_PORT_I2C1 0 +#define I2C_PORT_I2C2 1 +#define I2C_PORT_I2C3 2 + +/* Required symbolic I2C port names */ +#define I2C_PORT_MP4245 I2C_PORT_I2C3 +#define I2C_PORT_EEPROM I2C_PORT_I2C3 +#define MP4245_I2C_ADDR_FLAGS MP4245_I2C_ADDR_0_FLAGS + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "registers.h" + +#define GPIO_DP_HPD GPIO_DDI_MST_IN_HPD +#define GPIO_USBC_UF_ATTACHED_SRC GPIO_USBC_UF_MUX_VBUS_EN +#define GPIO_BPWR_DET GPIO_HUB_BPWRDET +#define GPIO_USB_HUB_OCP_NOTIFY GPIO_USBC_DATA_OCP_NOTIFY +#define GPIO_UFP_PLUG_DET GPIO_MST_UFP_PLUG_DET + +#define BUTTON_PRESSED_LEVEL 1 +#define BUTTON_RELEASED_LEVEL 0 + +#define GPIO_TRIGGER_1 GPIO_USB3_A5_CDP_EN +#define GPIO_TRIGGER_2 GPIO_USB3_A6_CDP_EN + +enum debug_gpio { + TRIGGER_1 = 0, + TRIGGER_2, +}; + +/* + * Function used to control GPIO signals as a timing marker. This is intended to + * be used for development/debugging purposes. + * + * @param trigger GPIO debug signal selection + * @param level desired level of the debug gpio signal + * @param pulse_usec pulse width if non-zero + */ +void board_debug_gpio(enum debug_gpio trigger, int level, int pulse_usec); + +/* + * Function called in power on case to enable usbc related interrupts + */ +void board_enable_usbc_interrupts(void); + +/* + * Function called in power off case to disable usbc related interrupts + */ +void board_disable_usbc_interrupts(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/baklava/build.mk b/board/baklava/build.mk new file mode 100644 index 0000000000..258bafe87d --- /dev/null +++ b/board/baklava/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=stm32 +CHIP_FAMILY:=stm32g4 +CHIP_VARIANT:=stm32g473xc +BASEBOARD:=honeybuns + +board-y=board.o diff --git a/board/baklava/dev_key.pem b/board/baklava/dev_key.pem new file mode 100644 index 0000000000..4897ceb44e --- /dev/null +++ b/board/baklava/dev_key.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEAyiT9PsD2wW3mhfuxMtihnLDKC+PY9l6j+j405G5Wd3BBtLLl +2uEoSD8cFQfnVTeFH7wggVf+SMAP3Y2aTnXIfdTX3N0skAdq/kYNUlQAK0xsa3Z7 +bRZ8puvzu+XNqsSS/tvsdYbNE5WC5sXtt7Wkm3mKn7PAti7oQrKbW1beFD0FgdAq +JoweIdpkuOwDYtFBcF92LWWGziDcEXlc2v5Xj3qvixMLnhy+Ny1Byr2ApVaYZ56H +JfjHKxbirNj4IrgmhdzfBIKxDf4mGibG0K1aC1io+SixtRV1cS6JRB0D+GS4QIcq +y9bCMkBeVQLHhSo1UYZqbB7Qef0blQ2sxsXklo8Q5EIQOd6yiXiTelApOWDn3zTi +uTkUo+99SPDLw/S3sR3uESxt+OYO2Yt6BWe2JSYBhHWB0Xc0PGItq7DUpm2cEWke +vS91I/lBfqhOxQOvnEx5NM97/RBQMa3jJ5Jv/72X5oU6OcGmaliBJy3Tv0CSiI06 +qgRgWxMym/XA0ui/AgEDAoIBgQCGw1N/K08rnpmup8t3OxZoddwH7TtO6cKm1CNC +9Dmk9YEjIe6R63AwKhK4r++OJQNqfWsA5VQwgAqTs7w0ToWpOI/ok3MKr5yphAjh +jVVyMvLyTvzzZFMZ8qJ9Q95x2GH/PUhOWd4NDldEg/PPzm28+7G/zSskH0WBzGeS +Oeli01kBNXFvCBQWkZh7SAJB4NZK6k7I7lnewJK2UOiR/uUKUcpct10UEyl6Hivc +flXDjxBFFFoZUITHZJcd5frB0Bh+EiqJ3CnkSIjD4sTnZs/TP8CKhmYriabfBHdH +j6ffcr5y8VhqDJK/ISSmWQO1c/rSziJLhx/ZrWvWp1FAbRg+kdh+RmV8hYIdEOq8 +PYOiERihd+eHVhtzsc74+cRGxPbaFJ2rpuJt+xk1Zp7IfGyyPWDmvXFKZgX+vo2s +vJL6q9pPR57uUHL0xsxDrMH3HFxkl1ta5PsiBGXs+zG0EUzNKGtoRTCi176xUWyo +NG+eWiL9ddeZVBzWeKfJGfwQ53sCgcEA+JE2E5kjvVCasSqERfDfIkSeOKoqWdZ2 +sAvTHibq6+vMBkRubNA0glHcUrMEBblDg3ds2z1A9YvwjwEUq9UFpVH3qfX9vaTX +lLYFRZjcA3PkCJvFAt5eIlVXp+vgaEo6OcodLjDiqkYKzbMC13k5uM1wsEEwo2vI +38vhHQlH1PHVTd8pt2Y7mOpDgxOOJLrvwuew7Lj9QSBRZ0EJxqv+1QA4EQ1cPr1H +hGqggtL0ChLRV7KBHiLz9ggS5vHTEkFNAoHBANAwaSIfTnpAvkMoGy+iQyw0afC0 +7hnwhHKcAzqenT1Mzo3Yt7/zsZE8ywjKPe9C+ZHZyh+W373tCUQRnjpNOpNiVHzi +ekFxl8kpLhpbB8LTXuRlQmtZjVQPbyuORPGDCzA05GGBN6mnXju+iQEz2WD8f3oY +Jz5yYl54eAuMsFl5/0yehqBQjRvky5YRna2eNUKBvz+/BgjpZeb0DtLMffcAvrkQ +FQbAwNvzvagMOEemjLSp9iXjQSNWJAdc86dMOwKBwQCltiQNEMJ+Nbx2HFguoJTB +gxQlxsbmjvnKsoy+xJydR91ZgvRIis2sNpLhzK1ZJi0CT53nfitOXUsKALhyjgPD +i/pxTqkpGI+4eVjZEJKs9+1bEoNXPulsOOUanUBFhtF73BN0IJccLrHed1c6UNEl +3ksgK3XCR9s/3UC+Bi/jS+OJP3Ek7tJl8YJXYl7DJ0qB78tIe1OAwDZE1gaEcqnj +VXq2COgp04UC8cBXN01cDIuPzFYUF01OsAyZ9oy21jMCgcEAisrwwWo0UYB+13AS +H8GCHXhGoHieu/Wtob1XfGm+KN3fCTslKqJ2YNMyBdwpSiymYTvcFQ8/0/NbgrZp +fDN8YkGNqJb8K6EP23DJZudageI/Qu4sR5EI4rT0x7Qt9ldcys3tllYlG8TpfSmw +q3fmQKhU/BAaKaGW6aWlXQh1kPv/iGmvFYsIvUMyZAu+c77OLFZ/f9SusJuZRKK0 +jIhT+gB/Jgq4rysrPU0pGrLQL8RdzcakGUIrbOQYBOiib4gnAoHAVrvbmZGxyeeA +oDE2QlXXmd1higPaQe3u+7vmh6itVpJ71n9wmu9xei7IiTOtGDYjHLXa8Qg0y37/ +FVCUiFxhOz05hpnB1ts70tuIWUJbWttMnhZPTpKa1dzZFB6qrlk2o/ONaSfNzpOZ +FgKxBURFVzNMTlIh7QOZGoOeRg5BkFG5z21g8egYQ/1cY61BhaxJTz93HGKb0jYn +QnC0WfVF9amWNGwocKATkwjoSVC7rQRsB2FMbY/WCqgE92lXsU9W +-----END RSA PRIVATE KEY----- diff --git a/board/baklava/ec.tasklist b/board/baklava/ec.tasklist new file mode 100644 index 0000000000..a478fbe2e0 --- /dev/null +++ b/board/baklava/ec.tasklist @@ -0,0 +1,16 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS_RO(RWSIG, rwsig_task, NULL, 1280) \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(POWER_BUTTON, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(UCPD, ucpd_task, 0, LARGER_TASK_STACK_SIZE) diff --git a/board/baklava/gpio.inc b/board/baklava/gpio.inc new file mode 100644 index 0000000000..2745ae7caf --- /dev/null +++ b/board/baklava/gpio.inc @@ -0,0 +1,93 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +#ifdef SECTION_IS_RW +GPIO_INT(HOST_USBC_PPC_INT_ODL, PIN(D, 9), GPIO_INT_FALLING | GPIO_PULL_UP, ppc_interrupt) +GPIO_INT(DDI_MST_IN_HPD, PIN(C, 14), GPIO_INT_BOTH, hpd_interrupt) +GPIO_INT(USBC_UF_MUX_VBUS_EN, PIN(C, 12), GPIO_INT_BOTH, board_uf_manage_vbus_interrupt) +GPIO_INT(PWR_BTN, PIN(A, 0), GPIO_INT_BOTH, board_pwr_btn_interrupt) +GPIO_INT(USBC_UF_PPC_INT_ODL, PIN(B, 5), GPIO_INT_FALLING | GPIO_PULL_UP, board_usbc_usb3_interrupt) +#endif + +/* Power sequencing signals */ +GPIO(EN_AC_JACK, PIN(A, 1), GPIO_OUT_LOW) +GPIO(EN_BB, PIN(A, 8), GPIO_OUT_LOW) +GPIO(EN_PP3300_B, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EN_PP5000_A, PIN(C, 6), GPIO_OUT_LOW) +GPIO(EN_PP1200_A, PIN(E, 8), GPIO_OUT_LOW) +GPIO(EN_PP1100_A, PIN(C, 7), GPIO_OUT_LOW) +GPIO(EN_PP1050_A, PIN(A, 2), GPIO_OUT_LOW) +GPIO(EN_PP5000_C, PIN(D, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_HSPORT, PIN(D, 0), GPIO_OUT_LOW) + +/* MST Hub signals */ +GPIO(MST_LP_CTL_L, PIN(D, 10), GPIO_ODR_LOW) +GPIO(MST_RST_L, PIN(E, 14), GPIO_ODR_LOW) +GPIO(MST_HUB_LANE_SWITCH, PIN(C, 15), GPIO_OUT_HIGH) +GPIO(MST_UFP_PLUG_DET, PIN(B, 12), GPIO_OUT_HIGH) + +/* Display Demux signals */ +GPIO(DEMUX_DP_HDMI_MODE, PIN(E, 15), GPIO_OUT_LOW) +GPIO(DEMUX_DP_HDMI_PD_N, PIN(B, 13), GPIO_ODR_LOW) + +/* USBC Mux and Demux Signals */ +GPIO(EN_DP_SINK, PIN(B, 14), GPIO_OUT_LOW) +GPIO(DP_SINK_RESET, PIN(B, 15), GPIO_OUT_LOW) +GPIO(USBC_UF_RESET_L, PIN(D, 2), GPIO_ODR_LOW) + +/* USB Hubs signals */ +GPIO(EC_HUB2_RESET_L, PIN(C, 5), GPIO_ODR_LOW) +GPIO(EC_HUB3_RESET_L, PIN(B, 10), GPIO_ODR_LOW) +GPIO(USBC_DATA_OCP_NOTIFY, PIN(C, 2), GPIO_OUT_HIGH) +GPIO(HUB_BPWRDET, PIN(C, 1), GPIO_OUT_LOW) + +/* USB-A Current limit switches, set default to 1.5A */ +GPIO(GBE_RESET_EC, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EC_DFU_MUX_CTRL, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(USB3_A5_CDP_EN, PIN(B, 9), GPIO_OUT_LOW) +GPIO(USB3_A6_CDP_EN, PIN(C, 13), GPIO_OUT_LOW) + + +/* Write protect */ +GPIO(EC_FLASH_WP_ODL, PIN(A, 3), GPIO_ODR_HIGH) +GPIO(EC_WP_L, PIN(E, 11), GPIO_INT_BOTH) + +/* UART Bus */ +GPIO(EC_UART_TX, PIN(C, 10), GPIO_INT_BOTH) +GPIO(EC_UART_RX, PIN(C, 11), GPIO_INT_BOTH) + +/* + * I2C SCL/SDA pins. These will normally be under control of the peripheral from + * alt fucntion setting below. But if a port gets wedged, the unwedge code uses + * these signals as regular GPIOs. + */ +GPIO(EC_I2C1_SCL, PIN(A, 15), GPIO_ODR_HIGH) +GPIO(EC_I2C1_SDA, PIN(B, 7), GPIO_ODR_HIGH) +GPIO(EC_I2C3_SCL, PIN(C, 8), GPIO_ODR_HIGH) +GPIO(EC_I2C3_SDA, PIN(C, 9), GPIO_ODR_HIGH) + +/* misc signals */ +GPIO(BOOT0, PIN(B, 8), GPIO_INPUT) + +/* Unimplemented signals since we are not an EC */ +UNIMPLEMENTED(ENTERING_RW) + +/* USART3_TX/RX GPIOC 10-11*/ +ALTERNATE(PIN_MASK(C, 0x0C00), 7, MODULE_UART, GPIO_PULL_UP) +/* I2C Ports + * I2C1: SDA/SCL -> PB7/PA15 + * I2C2: SDA/SCL -> PA8/PA9 + * I2C3: SDA/SCL -> PC8/PC9 + */ +ALTERNATE(PIN_MASK(B, 0x0080), 4, MODULE_I2C, GPIO_OPEN_DRAIN) +ALTERNATE(PIN_MASK(A, 0X8000), 4, MODULE_I2C, GPIO_OPEN_DRAIN) +ALTERNATE(PIN_MASK(C, 0x0300), 8, MODULE_I2C, GPIO_OPEN_DRAIN) +/* GPIOA4-7: SPI Signals */ +ALTERNATE(PIN_MASK(A, 0x00F0), 5, MODULE_SPI, 0) diff --git a/board/banshee/battery.c b/board/banshee/battery.c new file mode 100644 index 0000000000..35d6a7a935 --- /dev/null +++ b/board/banshee/battery.c @@ -0,0 +1,77 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Banshee battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* NVT Battery Information */ + [BATTERY_NVT] = { + .fuel_gauge = { + .manuf_name = "NVT", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = TARGET_WITH_MARGIN(17600, 5), + .voltage_normal = 15400, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 72, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 55, + .charging_min_c = 0, + .charging_max_c = 55, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_NVT; + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} diff --git a/board/banshee/board.c b/board/banshee/board.c new file mode 100644 index 0000000000..55922d056b --- /dev/null +++ b/board/banshee/board.c @@ -0,0 +1,149 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/als_tcs3400.h" +#include "driver/charger/isl9241.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "keyboard_customization.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "watchdog.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +void board_set_charger_current_limit_deferred(void) +{ + int action; + int rv; + + if (extpower_is_present() && + (battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED)) + /* AC only or AC+DC but battery is disconnect */ + action = MASK_SET; + else + action = MASK_CLR; + + rv = i2c_update16(chg_chips[CHARGER_SOLO].i2c_port, + chg_chips[CHARGER_SOLO].i2c_addr_flags, + ISL9241_REG_CONTROL3, + ISL9241_CONTROL3_INPUT_CURRENT_LIMIT, action); + + if (rv) + CPRINTF("Could not set charger input current limit! Error: %d\n", + rv); +} + +DECLARE_DEFERRED(board_set_charger_current_limit_deferred); +DECLARE_HOOK(HOOK_SECOND, board_set_charger_current_limit_deferred, + HOOK_PRIO_DEFAULT); + +void battery_present_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&board_set_charger_current_limit_deferred_data, 0); +} + +static uint32_t board_id; +static void configure_keyboard(void) +{ + uint32_t cbi_val; + + /* Board ID */ + if (cbi_get_board_version(&cbi_val) != EC_SUCCESS || + cbi_val > UINT8_MAX) + CPRINTS("CBI: Read Board ID failed"); + else + board_id = cbi_val; + + CPRINTS("Read Board ID: %d", board_id); + + if (board_id == 0) { + /* keyboard_col2_inverted on board id 0 */ + gpio_set_flags(GPIO_EC_KSO_04_INV, GPIO_ODR_HIGH); + gpio_set_flags(GPIO_EC_KSO_05_INV, GPIO_ODR_HIGH); + gpio_set_alternate_function(GPIO_PORT_1, (BIT(4) | BIT(5)), + GPIO_ALT_FUNC_DEFAULT); + } else if (board_id == 1) { + /* keyboard_col4_inverted on board id 1 */ + gpio_set_flags(GPIO_EC_KSO_02_INV, GPIO_ODR_HIGH); + gpio_set_flags(GPIO_EC_KSO_05_INV, GPIO_ODR_HIGH); + gpio_set_alternate_function(GPIO_PORT_1, (BIT(4) | BIT(7)), + GPIO_ALT_FUNC_DEFAULT); + } else { + /* keyboard_col5_inverted on board id 2 and later */ + gpio_set_flags(GPIO_EC_KSO_02_INV, GPIO_ODR_HIGH); + gpio_set_flags(GPIO_EC_KSO_04_INV, GPIO_ODR_HIGH); + gpio_set_alternate_function(GPIO_PORT_1, (BIT(5) | BIT(7)), + GPIO_ALT_FUNC_DEFAULT); + key_typ.col_refresh = KEYBOARD_COL_ID2_REFRESH; + key_typ.row_refresh = KEYBOARD_ROW_ID2_REFRESH; + } + + board_id_keyboard_col_inverted((int)board_id); +} + +void board_init(void) +{ + gpio_enable_interrupt(GPIO_EC_BATT_PRES_ODL); + hook_call_deferred(&board_set_charger_current_limit_deferred_data, 0); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +__override void board_pre_task_i2c_peripheral_init(void) +{ + /* Configure board specific keyboard */ + configure_keyboard(); + + /* Workaround for b:238683420 with board id >= 2 */ + +#ifdef SECTION_IS_RO + if (board_id >= 2) { + udelay(500 * MSEC); + watchdog_reload(); + CPRINTS("Add delay to check boot key"); + } +#endif +} + +__override uint8_t board_keyboard_row_refresh(void) +{ + if (board_id < 2) + return KEYBOARD_ROW_ID1_REFRESH; + else + return KEYBOARD_ROW_ID2_REFRESH; +} diff --git a/board/banshee/board.h b/board/banshee/board.h new file mode 100644 index 0000000000..c456a17e68 --- /dev/null +++ b/board/banshee/board.h @@ -0,0 +1,252 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Banshee board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* + * Early banshee boards are not set up for vivaldi + */ +#undef CONFIG_KEYBOARD_VIVALDI + +/* Baseboard features */ +#include "baseboard.h" + +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE + +/* No side buttons */ +#undef CONFIG_MKBP_INPUT_DEVICES +#undef CONFIG_VOLUME_BUTTONS + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* KEYBOARD */ +#define CONFIG_KEYBOARD_MULTIPLE +#define CONFIG_KEYBOARD_CUSTOMIZATION +#define CONFIG_KEYBOARD_VIVALDI + +/* LED */ +#define CONFIG_LED_PWM_COUNT 2 +#define CONFIG_LED_PWM_TASK_DISABLED +#define CONFIG_CMD_LEDTEST + +/* CM32183 ALS */ +#define CONFIG_ALS +#define ALS_COUNT 1 +#define CONFIG_ALS_CM32183 + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(CLEAR_ALS) + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 4 + +#define CONFIG_USB_PD_FRS_PPC + +#define CONFIG_USBC_RETIMER_INTEL_BB + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USB_PD_PPC + +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +#define GPIO_ID_1_EC_KB_BL_EN GPIO_EC_BATT_PRES_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_C1_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C2_C3_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_PPC_BC12 NPCX_I2C_PORT2_0 + +#define I2C_PORT_USB_C0_C1_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C2_C3_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x57 +#define USBC_PORT_C2_BB_RETIMER_I2C_ADDR 0x58 +#define USBC_PORT_C3_BB_RETIMER_I2C_ADDR 0x59 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* + * TODO: Disable BBR firmware update temporally, + * revert this patch once confirm BBR firmware update is ready + * on kernel. + */ +/* Retimer */ +#if 0 +#define CONFIG_USBC_RETIMER_FW_UPDATE +#endif + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 + +/* + * Older boards have a different ADC assignment. + */ + +#define CONFIG_ADC_CHANNELS_RUNTIME_CONFIG + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +/* I2C access in polling mode before task is initialized */ +#define CONFIG_I2C_BITBANG + +enum banshee_bitbang_i2c_channel { + I2C_BITBANG_CHAN_BRD_ID, + I2C_BITBANG_CHAN_COUNT +}; +#define I2C_BITBANG_PORT_COUNT I2C_BITBANG_CHAN_COUNT + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_AMBIENT, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_AMBIENT, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { CLEAR_ALS = 0, SENSOR_COUNT }; + +enum ioex_port { + IOEX_C0_NCT38XX = 0, + IOEX_C1_NCT38XX, + IOEX_C2_NCT38XX, + IOEX_C3_NCT38XX, + IOEX_PORT_COUNT +}; + +enum battery_type { BATTERY_NVT, BATTERY_TYPE_COUNT }; + +enum pwm_channel { + PWM_CH_SIDE_LED_R = 0, /* PWM0 (Red charger) */ + PWM_CH_SIDE_LED_G, /* PWM1 (Green charger) */ + PWM_CH_SIDE_LED_B, /* PWM2 (Blue charger) */ + PWM_CH_KBLIGHT, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_POWER_LED_W, /* PWM7 (white LED) */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +void battery_present_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/banshee/build.mk b/board/banshee/build.mk new file mode 100644 index 0000000000..78c675a67a --- /dev/null +++ b/board/banshee/build.mk @@ -0,0 +1,26 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o +board-y+=keyboard_customization.o diff --git a/board/banshee/charger.c b/board/banshee/charger.c new file mode 100644 index 0000000000..76e2712181 --- /dev/null +++ b/board/banshee/charger.c @@ -0,0 +1,80 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/banshee/ec.tasklist b/board/banshee/ec.tasklist new file mode 100644 index 0000000000..b193da8f9f --- /dev/null +++ b/board/banshee/ec.tasklist @@ -0,0 +1,34 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P2, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P3, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C2, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C3, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(1) | BIT(0)), BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_shared_alert_task, (BIT(3) | BIT(2)), BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/banshee/fans.c b/board/banshee/fans.c new file mode 100644 index 0000000000..72bf05527f --- /dev/null +++ b/board/banshee/fans.c @@ -0,0 +1,89 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/181271666): thermistor placement and calibration + * + * Prototype fan spins at about 4200 RPM at 100% PWM, this + * is specific to board ID 2 and might also apears in later + * boards as well. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1800, + .rpm_start = 1800, + .rpm_max = 6800, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/181271666): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/banshee/fw_config.c b/board/banshee/fw_config.c new file mode 100644 index 0000000000..dc7fe7ca2a --- /dev/null +++ b/board/banshee/fw_config.c @@ -0,0 +1,53 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union banshee_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brya if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union banshee_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Banshee FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* + * Early boards have a zero'd out FW_CONFIG, so replace + * it with a sensible default value. If DB_USB_ABSENT2 + * was used as an alternate encoding of DB_USB_ABSENT to + * avoid the zero check, then fix it. + */ + if (fw_config.raw_value == 0) { + CPRINTS("CBI: FW_CONFIG is zero, using board defaults"); + fw_config = fw_config_defaults; + } + } +} + +union banshee_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} diff --git a/board/banshee/fw_config.h b/board/banshee/fw_config.h new file mode 100644 index 0000000000..912aebca7e --- /dev/null +++ b/board/banshee/fw_config.h @@ -0,0 +1,40 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_BRYA_FW_CONFIG_H_ +#define __BOARD_BRYA_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Banshee board. + * + * Source of truth is the project/brya/brya/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +union banshee_cbi_fw_config { + struct { + uint32_t sd_db : 2; + uint32_t lte_db : 1; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t reserved_1 : 21; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union banshee_cbi_fw_config get_fw_config(void); + +#endif /* __BOARD_BRYA_FW_CONFIG_H_ */ diff --git a/board/banshee/gpio.inc b/board/banshee/gpio.inc new file mode 100644 index 0000000000..e33fa5ec06 --- /dev/null +++ b/board/banshee/gpio.inc @@ -0,0 +1,177 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN +/* + * This file was auto-generated. + */ + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +/*TODO(b/208721153): check CM32183 interrupt method */ +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INT_BOTH, battery_present_interrupt) + +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C2_BC12_INT_ODL, PIN(9, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C3_BC12_INT_ODL, PIN(9, 5), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C2_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C3_PPC_INT_ODL, PIN(5, 6), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_C1_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C2_C3_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C2_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C3_RT_INT_ODL, PIN(8, 1), GPIO_INT_FALLING, retimer_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_C3_RT_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_C3_RT_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_C3_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_C3_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_PCH_WAKE_D_ODL, PIN(8, 6), GPIO_ODR_LOW) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(USBC1_VBUS_ON, PIN(D, 7), GPIO_OUT_HIGH) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_C1_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C2_C3_TCPC_RST_ODL, PIN(9, 3), GPIO_ODR_LOW) +GPIO(USBC3_VBUS_ON, PIN(9, 4), GPIO_OUT_HIGH) +GPIO(RIGHT_SIDE, PIN(C, 0), GPIO_OUT_LOW) +GPIO(LEFT_SIDE, PIN(B, 6), GPIO_OUT_LOW) +GPIO(USBC0_VBUS_ON, PIN(0, 2), GPIO_OUT_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(EN_S5_RAILS, PIN(E, 1), GPIO_OUT_LOW) +GPIO(USBC2_VBUS_ON, PIN(9, 7), GPIO_OUT_HIGH) +GPIO(EC_ALS_RGB_INT_R_L, PIN(D, 4), GPIO_INPUT) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(6, 0x01), 0, MODULE_PWM, 0) /* GPIO60/PWM7 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x1c), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0, GPIOC2/PWM1/I2C6_SCL0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x4F), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x0c), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82, KSO15/GPIO83 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ + +/* Pre-configured PSL balls: J8 K6 */ + +/* + * Generated-gpio.inc is produced using a Brya specific tool that + * parses the GPIO definitions derived from the board schematics and + * EC pinout descriptions derived form the chip datasheets to generate + * the Chrome EC GPIO pinout definitions. Due to the confidential + * nature of schematics and datasheets, they are not provided here. + * + * Variants that do not auto-generate their GPIO definitions should + * combine the Brya gpio.inc and generated-gpio.inc into their + * gpio.inc and customize as appropriate. + */ + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + * + * GPIO14 needs to be inverted on BOARD ID 2 and later + * GPIO15 needs to be inverted on BOARD ID 1 + * GPIO17 needs to be inverted on BOARD ID 0 + */ +GPIO(EC_KSO_05_INV, PIN(1, 4), GPIO_OUT_LOW) +GPIO(EC_KSO_04_INV, PIN(1, 5), GPIO_OUT_LOW) +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* IO expander configuration */ + +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) + +IOEX(USB_C1_RT_RST_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 3), GPIO_ODR_HIGH) +IOEX(USB_C1_FRS_EN, EXPIN(IOEX_C1_NCT38XX, 0, 6), GPIO_OUT_LOW) + +IOEX(USB_C2_RT_RST_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 7), GPIO_ODR_LOW) +IOEX(USB_C2_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C2_FRS_EN, EXPIN(IOEX_C2_NCT38XX, 0, 6), GPIO_OUT_LOW) + +IOEX(USB_C3_RT_RST_ODL, EXPIN(IOEX_C3_NCT38XX, 0, 7), GPIO_ODR_LOW) +IOEX(USB_C3_OC_ODL, EXPIN(IOEX_C3_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C3_FRS_EN, EXPIN(IOEX_C3_NCT38XX, 0, 6), GPIO_OUT_LOW) diff --git a/board/banshee/i2c.c b/board/banshee/i2c.c new file mode 100644 index 0000000000..ea3fd38e62 --- /dev/null +++ b/board/banshee/i2c.c @@ -0,0 +1,94 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "i2c.h" +#include "i2c_bitbang.h" + +#define BOARD_ID_FAST_PLUS_CAPABLE 2 + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,1", + .port = I2C_PORT_USB_C0_C1_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc, bc12", + .port = I2C_PORT_USB_PPC_BC12, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,1", + .port = I2C_PORT_USB_C0_C1_MUX, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_C1_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_RT_SDA, + }, + { + /* I2C4 */ + .name = "tcpc2,3", + .port = I2C_PORT_USB_C2_C3_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C2_C3_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C2_C3_TCPC_SDA, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "retimer2,3", + .port = I2C_PORT_USB_C2_C3_MUX, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C2_C3_RT_SCL, + .sda = GPIO_EC_I2C_USB_C2_C3_RT_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct i2c_port_t i2c_bitbang_ports[] = { + [I2C_BITBANG_CHAN_BRD_ID] = { + .name = "bitbang_brd_id", + .port = I2C_PORT_EEPROM, + .kbps = 100, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + .drv = &bitbang_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_bitbang_ports) == I2C_BITBANG_CHAN_COUNT); +const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); diff --git a/board/banshee/keyboard.c b/board/banshee/keyboard.c new file mode 100644 index 0000000000..928f02e025 --- /dev/null +++ b/board/banshee/keyboard.c @@ -0,0 +1,100 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, + 0xff, 0xef /* full set */ + }, +}; + +static const struct ec_response_keybd_config banshee_kb_id1 = { + .num_top_row_keys = 12, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_SNAPSHOT, /* T6 */ + TK_BRIGHTNESS_DOWN, /* T7 */ + TK_BRIGHTNESS_UP, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_VOL_MUTE, /* T10 */ + TK_VOL_DOWN, /* T11 */ + TK_VOL_UP, /* T12 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config banshee_kb_id2 = { + .num_top_row_keys = 12, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_KBD_BKLIGHT_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_VOL_MUTE, /* T10 */ + TK_VOL_DOWN, /* T11 */ + TK_VOL_UP, /* T12 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (get_board_id() <= 1) + return &banshee_kb_id1; + else + return &banshee_kb_id2; +} + +/* + * Row Column info for Top row keys T1 - T15. + * on banshee keyboard Row Column is customization + * need define row col to mapping matrix layout. + */ +__override const struct key { + uint8_t row; + uint8_t col; +} vivaldi_keys[] = { + { .row = 3, .col = 5 }, /* T1 */ + { .row = 2, .col = 5 }, /* T2 */ + { .row = 6, .col = 4 }, /* T3 */ + { .row = 3, .col = 4 }, /* T4 */ + { .row = 4, .col = 10 }, /* T5 */ + { .row = 3, .col = 10 }, /* T6 */ + { .row = 2, .col = 10 }, /* T7 */ + { .row = 1, .col = 15 }, /* T8 */ + { .row = 3, .col = 11 }, /* T9 */ + { .row = 4, .col = 8 }, /* T10 */ + { .row = 6, .col = 8 }, /* T11 */ + { .row = 3, .col = 13 }, /* T12 */ + { .row = 3, .col = 5 }, /* T13 */ + { .row = 0, .col = 9 }, /* T14 */ + { .row = 0, .col = 11 }, /* T15 */ +}; +BUILD_ASSERT(ARRAY_SIZE(vivaldi_keys) == MAX_TOP_ROW_KEYS); diff --git a/board/banshee/keyboard_customization.c b/board/banshee/keyboard_customization.c new file mode 100644 index 0000000000..d561ee6445 --- /dev/null +++ b/board/banshee/keyboard_customization.c @@ -0,0 +1,145 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "gpio.h" +#include "keyboard_8042_sharedlib.h" +#include "keyboard_config.h" +#include "keyboard_customization.h" +#include "keyboard_protocol.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" + +enum gpio_signal signal; +static int colinv; + +static uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 0x0021, 0x007B, 0x0079, 0x0072, 0x007A, 0x0071, 0x0069, 0xe04A }, + { 0x002f, 0xe070, 0x007D, 0xe01f, 0x006c, 0xe06c, 0xe07d, 0x0077 }, + { 0x0015, 0x0070, 0x00ff, 0x000D, 0x000E, 0x0016, 0x0067, 0x001c }, + { 0xe011, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0xe05a, 0x0029, 0x0024, 0xe01d, 0xe01f, 0x0026, 0xe020, 0xe07a }, + { 0x0022, 0x001a, 0xe030, 0xe038, 0x001b, 0x001e, 0x001d, 0x0076 }, + { 0x002A, 0x0032, 0x0034, 0x002c, 0x002e, 0x0025, 0x002d, 0x002b }, + { 0x003a, 0x0031, 0x0033, 0x0035, 0x0036, 0x003d, 0x003c, 0x003b }, + { 0x0049, 0xe072, 0x005d, 0x0044, 0xe023, 0x0046, 0xe021, 0x004b }, + { 0x0059, 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0041, 0x007c, 0xe02c, 0xe02d, 0xe024, 0x003e, 0x0043, 0x0042 }, + { 0x0013, 0x0064, 0x0075, 0xe054, 0x0051, 0x0061, 0xe06b, 0xe02f }, + { 0xe014, 0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x004a, 0xe075, 0x004e, 0xe032, 0x0045, 0x004d, 0x0054, 0x004c }, + { 0x0052, 0x005a, 0xe03c, 0xe069, 0x0055, 0x0066, 0x005b, 0x0023 }, + { 0x006a, 0xe035, 0xe074, 0xe054, 0x0000, 0x006b, 0x0073, 0x0074 }, +}; + +uint16_t get_scancode_set2(uint8_t row, uint8_t col) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + return scancode_set2[col][row]; + return 0; +} + +void set_scancode_set2(uint8_t row, uint8_t col, uint16_t val) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + scancode_set2[col][row] = val; +} + +struct keyboard_type key_typ = { + .col_esc = KEYBOARD_COL_ESC, + .row_esc = KEYBOARD_ROW_ESC, + .col_down = KEYBOARD_COL_DOWN, + .row_down = KEYBOARD_ROW_DOWN, + .col_left_shift = KEYBOARD_COL_LEFT_SHIFT, + .row_left_shift = KEYBOARD_ROW_LEFT_SHIFT, + .col_refresh = KEYBOARD_COL_ID1_REFRESH, + .row_refresh = KEYBOARD_ROW_ID1_REFRESH, + .col_right_alt = KEYBOARD_COL_RIGHT_ALT, + .row_right_alt = KEYBOARD_ROW_RIGHT_ALT, + .col_left_alt = KEYBOARD_COL_LEFT_ALT, + .row_left_alt = KEYBOARD_ROW_LEFT_ALT, + .col_key_r = KEYBOARD_COL_KEY_R, + .row_key_r = KEYBOARD_ROW_KEY_R, + .col_key_h = KEYBOARD_COL_KEY_H, + .row_key_h = KEYBOARD_ROW_KEY_H, +}; + +void board_id_keyboard_col_inverted(int board_id) +{ + if (board_id == 0) { + /* keyboard_col2_inverted on board id 0 */ + signal = GPIO_EC_KSO_02_INV; + colinv = 2; + } else if (board_id == 1) { + /* keyboard_col4_inverted on board id 1 */ + signal = GPIO_EC_KSO_04_INV; + colinv = 4; + } else { + /* keyboard_col5_inverted on board id 2 and later */ + signal = GPIO_EC_KSO_05_INV; + colinv = 5; + } +} + +void board_keyboard_drive_col(int col) +{ + /* Drive all lines to high */ + if (col == KEYBOARD_COLUMN_NONE) + gpio_set_level(signal, 0); + + /* Set KBSOUT to zero to detect key-press */ + else if (col == KEYBOARD_COLUMN_ALL) + gpio_set_level(signal, 1); + + /* Drive one line for detection */ + else { + if (col == colinv) + gpio_set_level(signal, 1); + else + gpio_set_level(signal, 0); + } +} + +#ifdef CONFIG_KEYBOARD_DEBUG +static uint8_t keycap_label[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 'c', KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { 'q', KLLI_UNKNO, KLLI_UNKNO, KLLI_TAB, '`', '1', KLLI_UNKNO, 'a' }, + { KLLI_R_ALT, KLLI_L_ALT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_UNKNO, KLLI_SPACE, 'e', KLLI_F4, KLLI_SEARC, '3', KLLI_F3, + KLLI_UNKNO }, + { 'x', 'z', KLLI_F2, KLLI_F1, 's', '2', 'w', KLLI_ESC }, + { 'v', 'b', 'g', 't', '5', '4', 'r', 'f' }, + { 'm', 'n', 'h', 'y', '6', '7', 'u', 'j' }, + { '.', KLLI_DOWN, '\\', 'o', KLLI_F10, '9', KLLI_UNKNO, 'l' }, + { KLLI_R_SHT, KLLI_L_SHT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { ',', KLLI_UNKNO, KLLI_F7, KLLI_F6, KLLI_F5, '8', 'i', 'k' }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_F9, KLLI_UNKNO, KLLI_UNKNO, + KLLI_LEFT, KLLI_UNKNO }, + { KLLI_R_CTR, KLLI_L_CTR, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { '/', KLLI_UP, '-', KLLI_UNKNO, '0', 'p', '[', ';' }, + { '\'', KLLI_ENTER, KLLI_UNKNO, KLLI_UNKNO, '=', KLLI_B_SPC, ']', 'd' }, + { KLLI_UNKNO, KLLI_F8, KLLI_RIGHT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO }, +}; + +uint8_t get_keycap_label(uint8_t row, uint8_t col) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + return keycap_label[col][row]; + return KLLI_UNKNO; +} + +void set_keycap_label(uint8_t row, uint8_t col, uint8_t val) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + keycap_label[col][row] = val; +} +#endif diff --git a/board/banshee/keyboard_customization.h b/board/banshee/keyboard_customization.h new file mode 100644 index 0000000000..1b4994ded0 --- /dev/null +++ b/board/banshee/keyboard_customization.h @@ -0,0 +1,77 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Keyboard configuration */ + +#ifndef __KEYBOARD_CUSTOMIZATION_H +#define __KEYBOARD_CUSTOMIZATION_H + +/* + * KEYBOARD_COLS_MAX has the build time column size. It's used to allocate + * exact spaces for arrays. Actual keyboard scanning is done using + * keyboard_cols, which holds a runtime column size. + */ +#define KEYBOARD_COLS_MAX 16 +#define KEYBOARD_ROWS 8 + +/* + * WARNING: Do not directly modify it. You should call keyboard_raw_set_cols, + * instead. It checks whether you're eligible or not. + */ +extern uint8_t keyboard_cols; + +#define KEYBOARD_ROW_TO_MASK(r) (1 << (r)) + +/* Columns and masks for keys we particularly care about */ +#define KEYBOARD_COL_DOWN 8 +#define KEYBOARD_ROW_DOWN 1 +#define KEYBOARD_MASK_DOWN KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_DOWN) +#define KEYBOARD_COL_ESC 5 +#define KEYBOARD_ROW_ESC 7 +#define KEYBOARD_MASK_ESC KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_ESC) +#define KEYBOARD_COL_KEY_H 7 +#define KEYBOARD_ROW_KEY_H 2 +#define KEYBOARD_MASK_KEY_H KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_H) +#define KEYBOARD_COL_KEY_R 6 +#define KEYBOARD_ROW_KEY_R 6 +#define KEYBOARD_MASK_KEY_R KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_R) +#define KEYBOARD_COL_LEFT_ALT 3 +#define KEYBOARD_ROW_LEFT_ALT 1 +#define KEYBOARD_MASK_LEFT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_ALT) +#define KEYBOARD_COL_ID1_REFRESH 4 +#define KEYBOARD_ROW_ID1_REFRESH 6 +#define KEYBOARD_COL_ID2_REFRESH 5 +#define KEYBOARD_ROW_ID2_REFRESH 2 +#define KEYBOARD_MASK_REFRESH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_ID1_REFRESH) +#define KEYBOARD_COL_RIGHT_ALT 3 +#define KEYBOARD_ROW_RIGHT_ALT 0 +#define KEYBOARD_MASK_RIGHT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_ALT) +#define KEYBOARD_DEFAULT_COL_VOL_UP 13 +#define KEYBOARD_DEFAULT_ROW_VOL_UP 3 +#define KEYBOARD_COL_LEFT_CTRL 12 +#define KEYBOARD_ROW_LEFT_CTRL 1 +#define KEYBOARD_MASK_LEFT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_CTRL) +#define KEYBOARD_COL_RIGHT_CTRL 12 +#define KEYBOARD_ROW_RIGHT_CTRL 0 +#define KEYBOARD_MASK_RIGHT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_CTRL) +#define KEYBOARD_COL_SEARCH 4 +#define KEYBOARD_ROW_SEARCH 4 +#define KEYBOARD_MASK_SEARCH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_SEARCH) +#define KEYBOARD_COL_KEY_0 13 +#define KEYBOARD_ROW_KEY_0 4 +#define KEYBOARD_MASK_KEY_0 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_0) +#define KEYBOARD_COL_KEY_1 2 +#define KEYBOARD_ROW_KEY_1 5 +#define KEYBOARD_MASK_KEY_1 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_1) +#define KEYBOARD_COL_KEY_2 5 +#define KEYBOARD_ROW_KEY_2 5 +#define KEYBOARD_MASK_KEY_2 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_2) +#define KEYBOARD_COL_LEFT_SHIFT 9 +#define KEYBOARD_ROW_LEFT_SHIFT 1 +#define KEYBOARD_MASK_LEFT_SHIFT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_SHIFT) + +void board_id_keyboard_col_inverted(int board_id); + +#endif /* __KEYBOARD_CUSTOMIZATION_H */ diff --git a/board/banshee/led.c b/board/banshee/led.c new file mode 100644 index 0000000000..7333cfcd4f --- /dev/null +++ b/board/banshee/led.c @@ -0,0 +1,364 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Banshee specific PWM LED settings: + * there are 2 LEDs on each side of the board, + * each one can be controlled separately. The LED colors are white or amber, + * and the default behavior is tied to the charging process: both sides are + * amber while charging the battery and white when the battery is charged. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "compile_time_macros.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "led_pwm.h" +#include "lid_switch.h" +#include "pwm.h" +#include "util.h" + +#include + +#define LED_TICKS_PER_CYCLE 10 +#define LED_ON_TICKS 5 + +#define BREATH_LIGHT_LENGTH 100 +#define BREATH_HOLD_LENGTH 50 +#define BREATH_OFF_LENGTH 200 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED, +}; + +enum breath_status { + BREATH_LIGHT_UP = 0, + BREATH_LIGHT_DOWN, + BREATH_HOLD, + BREATH_OFF, +}; + +enum led_port { RIGHT_PORT = 1, LEFT_PORT }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Red, Green, Blue */ + [EC_LED_COLOR_RED] = { 50, 0, 0 }, + [EC_LED_COLOR_GREEN] = { 0, 50, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0, 8 }, + [EC_LED_COLOR_YELLOW] = { 40, 50, 0 }, + [EC_LED_COLOR_WHITE] = { 4, 10, 5 }, + [EC_LED_COLOR_AMBER] = { 45, 5, 0 }, +}; + +struct pwm_led_color_map pwr_led_color_map[EC_LED_COLOR_COUNT] = { + /* White, Green, Red */ + [EC_LED_COLOR_WHITE] = { BREATH_LIGHT_LENGTH, 0, 0 }, +}; + +/* + * Three logical LEDs with red、 blue、green channels + * and one logical LED with white channels. + */ +struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = { + [PWM_LED0] = { + .ch0 = PWM_CH_SIDE_LED_R, + .ch1 = PWM_CH_SIDE_LED_G, + .ch2 = PWM_CH_SIDE_LED_B, + .enable = &pwm_enable, + .set_duty = &pwm_set_duty, + }, + [PWM_LED1] = { + .ch0 = PWM_CH_POWER_LED_W, + .ch1 = PWM_LED_NO_CHANNEL, + .ch2 = PWM_LED_NO_CHANNEL, + .enable = &pwm_enable, + .set_duty = &pwm_set_duty, + }, +}; + +uint8_t breath_led_light_up; +uint8_t breath_led_light_down; +uint8_t breath_led_hold; +uint8_t breath_led_off; + +int breath_pwm_enable; +int breath_led_status; +static void breath_led_pwm_deferred(void); +DECLARE_DEFERRED(breath_led_pwm_deferred); + +/* + * Breath LED API + * Max duty (percentage) = BREATH_LIGHT_LENGTH (100%) + * Fade time (second) = 1000ms(In) / 1000ms(Out) + * Duration time (second) = BREATH_HOLD_LENGTH(500ms) + * Interval time (second) = BREATH_OFF_LENGTH(2000ms) + */ + +static void breath_led_pwm_deferred(void) +{ + switch (breath_led_status) { + case BREATH_LIGHT_UP: + + if (breath_led_light_up <= BREATH_LIGHT_LENGTH) + pwm_set_duty(PWM_CH_POWER_LED_W, breath_led_light_up++); + else { + breath_led_light_up = 0; + breath_led_light_down = BREATH_LIGHT_LENGTH; + breath_led_status = BREATH_HOLD; + } + + break; + case BREATH_HOLD: + + if (breath_led_hold <= BREATH_HOLD_LENGTH) + breath_led_hold++; + else { + breath_led_hold = 0; + breath_led_status = BREATH_LIGHT_DOWN; + } + + break; + case BREATH_LIGHT_DOWN: + + if (breath_led_light_down != 0) + pwm_set_duty(PWM_CH_POWER_LED_W, + breath_led_light_down--); + else { + breath_led_light_down = BREATH_LIGHT_LENGTH; + breath_led_status = BREATH_OFF; + } + + break; + case BREATH_OFF: + + if (breath_led_off <= BREATH_OFF_LENGTH) + breath_led_off++; + else { + breath_led_off = 0; + breath_led_status = BREATH_LIGHT_UP; + } + + break; + } + + if (breath_pwm_enable) + hook_call_deferred(&breath_led_pwm_deferred_data, 10 * MSEC); +} + +void breath_led_run(uint8_t enable) +{ + if (enable && !breath_pwm_enable) { + breath_pwm_enable = true; + breath_led_status = BREATH_LIGHT_UP; + hook_call_deferred(&breath_led_pwm_deferred_data, 10 * MSEC); + } else if (!enable && breath_pwm_enable) { + breath_pwm_enable = false; + breath_led_light_up = 0; + breath_led_light_down = 0; + breath_led_hold = 0; + breath_led_off = 0; + breath_led_status = BREATH_OFF; + hook_call_deferred(&breath_led_pwm_deferred_data, -1); + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_GREEN] = 100; + brightness_range[EC_LED_COLOR_YELLOW] = 100; + brightness_range[EC_LED_COLOR_AMBER] = 100; + brightness_range[EC_LED_COLOR_BLUE] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; + } else if (led_id == EC_LED_ID_POWER_LED) + brightness_range[EC_LED_COLOR_WHITE] = 100; +} + +void set_pwr_led_color(enum pwm_led_id id, int color) +{ + struct pwm_led duty = { 0 }; + const struct pwm_led *led = &pwm_leds[id]; + + if ((id >= CONFIG_LED_PWM_COUNT) || (id < 0) || + (color >= EC_LED_COLOR_COUNT) || (color < -1)) + return; + + if (color != -1) { + duty.ch0 = pwr_led_color_map[color].ch0; + duty.ch1 = pwr_led_color_map[color].ch1; + duty.ch2 = pwr_led_color_map[color].ch2; + } + + if (led->ch0 != (enum pwm_channel)PWM_LED_NO_CHANNEL) + led->set_duty(led->ch0, duty.ch0); + if (led->ch1 != (enum pwm_channel)PWM_LED_NO_CHANNEL) + led->set_duty(led->ch1, duty.ch1); + if (led->ch2 != (enum pwm_channel)PWM_LED_NO_CHANNEL) + led->set_duty(led->ch2, duty.ch2); +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + enum pwm_led_id pwm_id; + + /* Convert ec_led_id to pwm_led_id. */ + if (led_id == EC_LED_ID_BATTERY_LED) + pwm_id = PWM_LED0; + else if (led_id == EC_LED_ID_POWER_LED) + pwm_id = PWM_LED1; + else + return EC_ERROR_UNKNOWN; + + if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE]) + set_pwr_led_color(pwm_id, EC_LED_COLOR_WHITE); + else + /* Otherwise, the "color" is "off". */ + set_pwr_led_color(pwm_id, -1); + } else { + if (brightness[EC_LED_COLOR_RED]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_GREEN]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN); + else if (brightness[EC_LED_COLOR_BLUE]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_YELLOW]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_YELLOW); + else if (brightness[EC_LED_COLOR_WHITE]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); + else + /* Otherwise, the "color" is "off". */ + set_pwm_led_color(pwm_id, -1); + } + + return EC_SUCCESS; +} + +static int led_get_charge_percent(void) +{ + return DIV_ROUND_NEAREST(charge_get_display_charge(), 10); +} + +static void select_active_port_led(int port) +{ + if ((led_pwr_get_state() == LED_PWRS_DISCHARGE && + led_get_charge_percent() < 10) || + led_pwr_get_state() == LED_PWRS_ERROR) { + gpio_set_level(GPIO_LEFT_SIDE, 1); + gpio_set_level(GPIO_RIGHT_SIDE, 1); + } else if (port == RIGHT_PORT) { + gpio_set_level(GPIO_LEFT_SIDE, 0); + gpio_set_level(GPIO_RIGHT_SIDE, 1); + } else if (port == LEFT_PORT) { + gpio_set_level(GPIO_LEFT_SIDE, 1); + gpio_set_level(GPIO_RIGHT_SIDE, 0); + } else { + gpio_set_level(GPIO_LEFT_SIDE, 0); + gpio_set_level(GPIO_RIGHT_SIDE, 0); + } +} + +static int led_power_enable(void) +{ + if (gpio_get_level(GPIO_LEFT_SIDE) || gpio_get_level(GPIO_RIGHT_SIDE)) + return true; + + return false; +} + +static void set_active_port_color(int color) +{ + int usbc_port = charge_manager_get_active_charge_port(); + int port = 0; + + if ((usbc_port == USBC_PORT_C0) || (usbc_port == USBC_PORT_C1)) + port = RIGHT_PORT; + else if ((usbc_port == USBC_PORT_C2) || (usbc_port == USBC_PORT_C3)) + port = LEFT_PORT; + + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + select_active_port_led(port); + set_pwm_led_color(PWM_LED0, led_power_enable() ? color : -1); + } +} + +static void led_set_battery(void) +{ + static int battery_ticks; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(EC_LED_COLOR_AMBER); + break; + case LED_PWRS_DISCHARGE: + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + if (led_get_charge_percent() < 10) + set_active_port_color((battery_ticks & 0x2) ? + EC_LED_COLOR_RED : + -1); + else + set_active_port_color(-1); + } + break; + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? EC_LED_COLOR_RED : + -1); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(EC_LED_COLOR_WHITE); + break; + case LED_PWRS_IDLE: + set_active_port_color(EC_LED_COLOR_AMBER); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks & 0x4) ? EC_LED_COLOR_AMBER : -1); + break; + default: + break; + } +} + +static void led_set_power(void) +{ + /* turn off led when lid is close*/ + if (!lid_is_open()) { + set_pwr_led_color(PWM_LED1, -1); + return; + } + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + breath_led_run(1); + return; + } else + breath_led_run(0); + + if (chipset_in_state(CHIPSET_STATE_ON)) { + set_pwr_led_color(PWM_LED1, EC_LED_COLOR_WHITE); + } else + set_pwr_led_color(PWM_LED1, -1); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + led_set_battery(); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + led_set_power(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/banshee/pwm.c b/board/banshee/pwm.c new file mode 100644 index 0000000000..41e762d6f8 --- /dev/null +++ b/board/banshee/pwm.c @@ -0,0 +1,70 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_SIDE_LED_R] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000, + }, + [PWM_CH_SIDE_LED_G] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000, + }, + [PWM_CH_SIDE_LED_B] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000, + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, + [PWM_CH_POWER_LED_W] = { + .channel = 7, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn off all the LEDs. + * Turn on the fan at 100%. + */ + pwm_enable(PWM_CH_SIDE_LED_R, 1); + pwm_set_duty(PWM_CH_SIDE_LED_R, 0); + pwm_enable(PWM_CH_SIDE_LED_G, 1); + pwm_set_duty(PWM_CH_SIDE_LED_G, 0); + pwm_enable(PWM_CH_SIDE_LED_B, 1); + pwm_set_duty(PWM_CH_SIDE_LED_B, 0); + + pwm_set_duty(PWM_CH_POWER_LED_W, 0); + pwm_enable(PWM_CH_POWER_LED_W, 1); + + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/banshee/sensors.c b/board/banshee/sensors.c new file mode 100644 index 0000000000..a6bd3d3863 --- /dev/null +++ b/board/banshee/sensors.c @@ -0,0 +1,244 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc.h" +#include "common.h" +#include "driver/als_cm32183.h" +#include "hooks.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_AMBIENT] = { + .name = "TEMP_AMBIENT", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* CM32183 private data */ +static struct als_drv_data_t g_cm32183_data = { + /** + * adjusted_value = raw_value * scale + raw_value * uscale / 10000 + * the coeficient we need is 3.2 + */ + .als_cal.scale = 3, + .als_cal.uscale = 2000, + .als_cal.offset = 0, + .als_cal.channel_scale = { + /* TODO(b/219424210): Calibrate ALS CM32183A3OP */ + }, +}; + +struct motion_sensor_t motion_sensors[] = { + [CLEAR_ALS] = { + .name = "Clear Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_CM32183, + .type = MOTIONSENSE_TYPE_LIGHT, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &cm32183_drv, + .drv_data = &g_cm32183_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = CM32183_I2C_ADDR, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + .config = { + /* Run ALS sensor in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 1000, + }, + }, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ +const struct motion_sensor_t *motion_als_sensors[] = { + &motion_sensors[CLEAR_ALS], +}; +BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); + +/*TODO(b/208721153): check CM32183 interrupt method */ + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { + .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC, + }, + [TEMP_SENSOR_2_AMBIENT] = { + .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_AMBIENT, + }, + [TEMP_SENSOR_3_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Alder Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(80), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(75), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(81), \ + }, \ + .temp_fan_off = C_TO_K(50), \ + .temp_fan_max = C_TO_K(58), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_AMBIENT \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(85), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(95), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(105), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(70), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(86), \ + }, \ + .temp_fan_off = C_TO_K(50), \ + .temp_fan_max = C_TO_K(58), \ + } +__maybe_unused static const struct ec_thermal_config thermal_ambient = + THERMAL_AMBIENT; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 125C, max absolute temperature 150C + * PP3300 regulator: operating range -40 C to 125 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(90), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(100), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(110), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(85), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(91), \ + }, \ + .temp_fan_off = C_TO_K(50), \ + .temp_fan_max = C_TO_K(58), \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +/* + * TODO(b/180681346): update for brya WWAN module + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_WWAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(130), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(130), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(100), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_wwan = + THERMAL_WWAN; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_AMBIENT] = THERMAL_AMBIENT, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +static void board_thermals_init(void) +{ + if (get_board_id() == 1) { + /* + * Board ID 1 only has 3 sensors and the AMBIENT sensor + * ADC pins have been reassigned, so we're down to 2 + * sensors that can easily be configured. So, alias the + * AMBIENT sensor ADC channel to the unimplemented ADC + * slots. + */ + adc_channels[ADC_TEMP_SENSOR_3_CHARGER].input_ch = NPCX_ADC_CH1; + } +} + +DECLARE_HOOK(HOOK_INIT, board_thermals_init, HOOK_PRIO_INIT_CHIPSET); diff --git a/board/banshee/usbc_config.c b/board/banshee/usbc_config.c new file mode 100644 index 0000000000..7f6dd15d66 --- /dev/null +++ b/board/banshee/usbc_config.c @@ -0,0 +1,522 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C2_C3_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C3] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C2_C3_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); +/******************************************************************************/ +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_PPC_BC12, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_PPC_BC12, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .frs_en = IOEX_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_PPC_BC12, + .i2c_addr_flags = SYV682X_ADDR1_FLAGS, + .frs_en = IOEX_USB_C2_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C3] = { + .i2c_port = I2C_PORT_USB_PPC_BC12, + .i2c_addr_flags = SYV682X_ADDR3_FLAGS, + .frs_en = IOEX_USB_C3_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +int is_framework_dp_hdmi_card(int port) +{ + uint16_t USB_VID = pd_get_identity_vid(port); + uint16_t USB_PID = pd_get_identity_pid(port); + + if (((USB_PID == USB_PID_FRAMEWORK_HDMI_CARD) || + (USB_PID == USB_PID_FRAMEWORK_DP_CARD)) && + (USB_VID == USB_VID_FRAMEWORK)) + return 1; + + return 0; +} + +void board_prefix(const struct usb_mux *me, mux_state_t hpd_state, + bool *ack_required) +{ + int port = me->usb_port; + + bb_retimer_hpd_update(me, hpd_state, ack_required); + + if (!is_framework_dp_hdmi_card(port)) + return; + + if (hpd_state & USB_PD_MUX_HPD_LVL) + bb_retimer_set_dp_connection(me, true); + else + bb_retimer_set_dp_connection(me, false); +} + +int board_virtual_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = 0; + int port = me->usb_port; + + if (is_framework_dp_hdmi_card(port)) + rv = bb_retimer_set_dp_connection(me, false); + + return rv; +} + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc2_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc3_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C3, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + /* + * When a USB-A card is connected to the + * chromebook, the USB_3_CONNECTION bit will be + * enabled. This increases BBR power + * consumption, so clear the USB3_CONNECTION bit + * in S0ix and re-enable when returning to S0. + */ + .flags = USB_MUX_FLAG_CAN_IDLE, + .driver = &bb_usb_retimer, + .hpd_update = board_prefix, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + .board_set = &board_virtual_mux_set, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .flags = USB_MUX_FLAG_CAN_IDLE, + .driver = &bb_usb_retimer, + .hpd_update = board_prefix, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + .board_set = &board_virtual_mux_set, + }, + .next = &usbc1_tcss_usb_mux, + }, + [USBC_PORT_C2] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C2, + .flags = USB_MUX_FLAG_CAN_IDLE, + .driver = &bb_usb_retimer, + .hpd_update = board_prefix, + .i2c_port = I2C_PORT_USB_C2_C3_MUX, + .i2c_addr_flags = USBC_PORT_C2_BB_RETIMER_I2C_ADDR, + .board_set = &board_virtual_mux_set, + }, + .next = &usbc2_tcss_usb_mux, + }, + [USBC_PORT_C3] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C3, + .flags = USB_MUX_FLAG_CAN_IDLE, + .driver = &bb_usb_retimer, + .hpd_update = board_prefix, + .i2c_port = I2C_PORT_USB_C2_C3_MUX, + .i2c_addr_flags = USBC_PORT_C3_BB_RETIMER_I2C_ADDR, + .board_set = &board_virtual_mux_set, + }, + .next = &usbc3_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_PPC_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_PPC_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_PPC_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_2_FLAGS, + }, + [USBC_PORT_C3] = { + .i2c_port = I2C_PORT_USB_PPC_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_0_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C1_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C2_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C2_C3_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C3_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C2_C3_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) + rst_signal = IOEX_USB_C0_RT_RST_ODL; + else if (me->usb_port == USBC_PORT_C1) + rst_signal = IOEX_USB_C1_RT_RST_ODL; + else if (me->usb_port == USBC_PORT_C2) + rst_signal = IOEX_USB_C2_RT_RST_ODL; + else if (me->usb_port == USBC_PORT_C3) + rst_signal = IOEX_USB_C3_RT_RST_ODL; + else + return EC_ERROR_INVAL; + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/179648104): figure out correct timing + */ + gpio_set_level(GPIO_USB_C0_C1_TCPC_RST_ODL, 0); + gpio_set_level(GPIO_USB_C2_C3_TCPC_RST_ODL, 0); + /* + * delay for power-on to reset-off and min. assertion time + */ + msleep(NCT38XX_RESET_HOLD_DELAY_MS); + gpio_set_level(GPIO_USB_C0_C1_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C2_C3_TCPC_RST_ODL, 1); + + nct38xx_reset_notify(USBC_PORT_C0); + nct38xx_reset_notify(USBC_PORT_C1); + nct38xx_reset_notify(USBC_PORT_C2); + nct38xx_reset_notify(USBC_PORT_C3); + + /* wait for chips to come up */ + if (NCT3808_RESET_POST_DELAY_MS != 0) + msleep(NCT3808_RESET_POST_DELAY_MS); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0,C1,C2,C3 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + ioex_init(IOEX_C0_NCT38XX); + ioex_init(IOEX_C1_NCT38XX); + ioex_init(IOEX_C2_NCT38XX); + ioex_init(IOEX_C3_NCT38XX); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C3_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C1_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_C3_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C3_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_1; + + if (gpio_get_level(GPIO_USB_C2_C3_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_2 | PD_STATUS_TCPC_ALERT_3; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C2) + return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C3) + return gpio_get_level(GPIO_USB_C3_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C2_C3_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C2_BC12_INT_ODL: + usb_charger_task_set_event(2, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C3_BC12_INT_ODL: + usb_charger_task_set_event(3, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + case GPIO_USB_C2_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C2); + break; + case GPIO_USB_C3_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C3); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} diff --git a/board/banshee/usbc_config.h b/board/banshee/usbc_config.h new file mode 100644 index 0000000000..5085b28bec --- /dev/null +++ b/board/banshee/usbc_config.h @@ -0,0 +1,21 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Banshee board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 4 + +enum usbc_port { + USBC_PORT_C0 = 0, + USBC_PORT_C1, + USBC_PORT_C2, + USBC_PORT_C3, + USBC_PORT_COUNT +}; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/banshee/vif_override.xml b/board/banshee/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/banshee/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/bds/board.c b/board/bds/board.c deleted file mode 100644 index 95f3ef6cfd..0000000000 --- a/board/bds/board.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -/* Stellaris EKB-LM4F-EAC board-specific configuration */ - -#include "adc.h" -#include "adc_chip.h" -#include "gpio.h" -#include "i2c.h" -#include "registers.h" -#include "util.h" - -/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ -const struct adc_t adc_channels[] = { - /* EC internal temperature is calculated by - * 273 + (295 - 450 * ADC_VALUE / ADC_READ_MAX) / 2 - * = -225 * ADC_VALUE / ADC_READ_MAX + 420.5 - */ - {"ECTemp", LM4_ADC_SEQ0, -225, ADC_READ_MAX, 420, - LM4_AIN_NONE, 0x0e /* TS0 | IE0 | END0 */, 0, 0}, - - /* Charger current is mapped from 0~4000mA to 0~1.6V. - * And ADC maps 0~3.3V to ADC_READ_MAX. - * - * Note that on BDS, this is really just the turn pot on the Badger - * board, but that's good enough for debugging the ADC. - */ - {"BDSPot", LM4_ADC_SEQ1, 33 * 4000, ADC_READ_MAX * 16, 0, - LM4_AIN(0), 0x06 /* IE0 | END0 */, LM4_GPIO_E, (1<<3)}, -}; -BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"lightbar", 5, 400}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -#include "gpio_list.h" diff --git a/board/bds/board.h b/board/bds/board.h deleted file mode 100644 index f43ea6ee92..0000000000 --- a/board/bds/board.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Stellaris EKB-LM4F-EAC board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands */ -#define CONFIG_I2C -#define CONFIG_I2C_MASTER - -/* LM4 modules we don't use on link but still want to keep compiling */ -#define CONFIG_EEPROM -#define CONFIG_PSTORE - -/* Modules we want to exclude */ -#undef CONFIG_LID_SWITCH -#undef CONFIG_HOSTCMD_LPC -#undef CONFIG_PECI -#undef CONFIG_SWITCH - -/* Write protect is active high */ -#define CONFIG_WP_ACTIVE_HIGH - -#ifndef __ASSEMBLER__ - -enum adc_channel { - ADC_CH_EC_TEMP = 0, /* EC internal die temperature in degrees K. */ - ADC_CH_BDS_POT, /* BDS pot input. */ - ADC_CH_COUNT -}; - -enum pwm_channel { - PWM_CH_COUNT -}; - -/* I2C ports */ -#define I2C_PORT_LIGHTBAR 5 /* Port 5 / PA6:7 on link, but PG6:7 on badger */ - -/* Second UART port */ -#define CONFIG_UART_HOST 1 - -#include "gpio_signal.h" - -/* EEPROM blocks */ -#define EEPROM_BLOCK_START_PSTORE 16 /* Host persistent storage */ -#define EEPROM_BLOCK_COUNT_PSTORE 16 - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/bds/build.mk b/board/bds/build.mk deleted file mode 100644 index e3e91f0bb2..0000000000 --- a/board/bds/build.mk +++ /dev/null @@ -1,12 +0,0 @@ -# -*- makefile -*- -# Copyright 2012 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -# the IC is TI Stellaris LM4 -CHIP:=lm4 - -board-y=board.o diff --git a/board/bds/ec.tasklist b/board/bds/ec.tasklist deleted file mode 100644 index 7329da7d2d..0000000000 --- a/board/bds/ec.tasklist +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/** - * See CONFIG_TASK_LIST in config.h for details. - */ -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(LIGHTBAR, lightbar_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) diff --git a/board/bds/gpio.inc b/board/bds/gpio.inc deleted file mode 100644 index 374894f932..0000000000 --- a/board/bds/gpio.inc +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -/* Recovery signal from DOWN button */ -GPIO(RECOVERY_L, PIN(D, 1), GPIO_PULL_UP) -GPIO(DEBUG_LED, PIN(A, 7), GPIO_OUT_LOW) - -/* - * Signals which aren't implemented on BDS but we'll emulate anyway, to - * make it more convenient to debug other code. - */ -UNIMPLEMENTED(WP) /* Write protect input */ -UNIMPLEMENTED(ENTERING_RW) /* EC entering RW code */ - -ALTERNATE(PIN_MASK(A, 0x03), 1, MODULE_UART, 0) /* UART0 */ -ALTERNATE(PIN_MASK(G, 0x40), 3, MODULE_I2C, 0) /* I2C5 SCL */ -ALTERNATE(PIN_MASK(G, 0x80), 3, GPIO_OPEN_DRAIN, 0) /* I2C5 SDA */ -ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, 0) /* UART1 */ diff --git a/board/beadrix/battery.c b/board/beadrix/battery.c new file mode 100644 index 0000000000..ba6f295e53 --- /dev/null +++ b/board/beadrix/battery.c @@ -0,0 +1,95 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all beadrix battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* GanFeng SG20 Battery Information */ + [BATTERY_GANFENG] = { + .fuel_gauge = { + .manuf_name = "Ganfeng", + .device_name = "SG20", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0003, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 8700, /* mV */ + .voltage_normal = 7600, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + /* Pow-Tech SG20JL1C2S5900-P1P1 Battery Information */ + [BATTERY_POWTECH_SG20JL1C] = { + .fuel_gauge = { + .manuf_name = "POW-TECH", + .device_name = "SG20", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x54, + .reg_mask = 0x0006, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 350, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 55, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_GANFENG; diff --git a/board/beadrix/board.c b/board/beadrix/board.c new file mode 100644 index 0000000000..92da9f5295 --- /dev/null +++ b/board/beadrix/board.c @@ -0,0 +1,583 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledee board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/nb7v904m.h" +#include "driver/tcpm/anx7447.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "driver/usb_mux/pi3usb3x532.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_USB_C1_INT_V1_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_SUB_ANALOG] = { .name = "SUB_ANALOG", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, + { /* Used as TCPC + Charger */ + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +static int board_nb7v904m_mux_set(const struct usb_mux *me, + mux_state_t mux_state); + +/* USB Retimer */ +const struct usb_mux_chain usbc1_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = NB7V904M_I2C_ADDR0, + .driver = &nb7v904m_usb_redriver_drv, + .board_set = &board_nb7v904m_mux_set, + }, +}; + +/* USB Muxes */ +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, + { + /* Used as MUX only*/ + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = AN7447_TCPC0_I2C_ADDR_FLAGS, + .flags = USB_MUX_FLAG_NOT_TCPC, + .driver = &anx7447_usb_mux_driver, + }, + .next = &usbc1_retimer, + }, +}; + +/* USB Mux */ +static int board_nb7v904m_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + int flipped = !!(mux_state & USB_PD_MUX_POLARITY_INVERTED); + + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* USB with DP */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + if (flipped) { /* CC2 */ + rv |= nb7v904m_tune_usb_set_eq( + me, NB7V904M_CH_A_EQ_0_DB, + NB7V904M_CH_B_EQ_4_DB, + NB7V904M_CH_C_EQ_0_DB, + NB7V904M_CH_D_EQ_0_DB); + rv |= nb7v904m_tune_usb_flat_gain( + me, NB7V904M_CH_A_GAIN_0_DB, + NB7V904M_CH_B_GAIN_3P5_DB, + NB7V904M_CH_C_GAIN_0_DB, + NB7V904M_CH_D_GAIN_0_DB); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_D, + NB7V904M_LOSS_PROFILE_D); + } /* CC1 */ + else { + rv |= nb7v904m_tune_usb_set_eq( + me, NB7V904M_CH_A_EQ_0_DB, + NB7V904M_CH_B_EQ_0_DB, + NB7V904M_CH_C_EQ_4_DB, + NB7V904M_CH_D_EQ_0_DB); + rv |= nb7v904m_tune_usb_flat_gain( + me, NB7V904M_CH_A_GAIN_0_DB, + NB7V904M_CH_B_GAIN_0_DB, + NB7V904M_CH_C_GAIN_3P5_DB, + NB7V904M_CH_D_GAIN_0_DB); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_D, + NB7V904M_LOSS_PROFILE_D, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A); + } + } else { + /* USB only */ + rv |= nb7v904m_tune_usb_set_eq(me, + NB7V904M_CH_A_EQ_0_DB, + NB7V904M_CH_B_EQ_4_DB, + NB7V904M_CH_C_EQ_4_DB, + NB7V904M_CH_D_EQ_0_DB); + rv |= nb7v904m_tune_usb_flat_gain( + me, NB7V904M_CH_A_GAIN_0_DB, + NB7V904M_CH_B_GAIN_3P5_DB, + NB7V904M_CH_C_GAIN_3P5_DB, + NB7V904M_CH_D_GAIN_0_DB); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A); + } + + } else if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* 4 lanes DP */ + rv |= nb7v904m_tune_usb_set_eq(me, NB7V904M_CH_A_EQ_0_DB, + NB7V904M_CH_B_EQ_0_DB, + NB7V904M_CH_C_EQ_0_DB, + NB7V904M_CH_D_EQ_0_DB); + rv |= nb7v904m_tune_usb_flat_gain(me, NB7V904M_CH_A_GAIN_0_DB, + NB7V904M_CH_B_GAIN_0_DB, + NB7V904M_CH_C_GAIN_0_DB, + NB7V904M_CH_D_GAIN_0_DB); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_D, NB7V904M_LOSS_PROFILE_D, + NB7V904M_LOSS_PROFILE_D, NB7V904M_LOSS_PROFILE_D); + } + + return rv; +} + +void board_init(void) +{ + int on; + + /* Enable C0 interrupt and check if it needs processing */ + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + + /* Enable C1 interrupt and check if it needs processing */ + gpio_enable_interrupt(GPIO_USB_C1_INT_V1_ODL); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + check_c0_line(); + check_c1_line(); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + gpio_set_level(GPIO_EN_USB_A0_VBUS, !!enable); + + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", enable ? "en" : "dis"); +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("Old chg p%d", old_port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charge ports"); + + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + CPRINTS("New chg p%d", port); + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + if (old_port != CHARGE_PORT_NONE && old_port != port) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. + * Otherwise, we can overcurrent the adapter we're switching to. + * (crbug.com/926056) + */ + charger_discharge_on_ac(1); + } + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > CONFIG_USB_PD_PORT_MAX_COUNT) + return; + + raa489000_set_output_current(port, rp); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + if (board_get_usb_pd_port_count() > 1 && + !gpio_get_level(GPIO_USB_C1_INT_V1_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + /* TCPCI spec Rev 1.0 says to ignore bits 14:12. */ + if (!(tcpc_config[1].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 10000, + } }; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +static const struct ec_response_keybd_config keybd1 = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad and no screenlock key */ +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + /* + * Future boards should use fw_config if needed. + */ + + return &keybd1; +} diff --git a/board/beadrix/board.h b/board/beadrix/board.h new file mode 100644 index 0000000000..09ef205ee1 --- /dev/null +++ b/board/beadrix/board.h @@ -0,0 +1,126 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledee board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +#undef CONFIG_I2C_DEBUG + +/* EC console commands */ +#define CONFIG_CMD_CHARGER_DUMP + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_LOW_VOLTAGE_PROTECTION + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGE_RAMP_HW +#undef CONFIG_CHARGER_SINGLE_CHIP +#define CONFIG_OCPC +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ + +/* + * GPIO for C1 interrupts, for baseboard use + * + * Note this will only be valid for board revision 1 + */ +#define GPIO_USB_C1_INT_ODL GPIO_USB_C1_INT_V1_ODL + +/* PWM */ +#define CONFIG_PWM + +/* TCPC */ +#define CONFIG_USB_PD_TCPM_ANX7447 /* C1: MUX only*/ +#define CONFIG_USB_PD_TCPM_MUX +#define CONFIG_USB_PD_TCPM_ANX7447_AUX_PU_PD + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 +#define CONFIG_USB_MUX_RUNTIME_CONFIG +#define CONFIG_USB_MUX_IT5205 /* C0: ITE MUX */ + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_RAA489000 /* C1: TCPC + Charger */ +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_RUNTIME_CONFIG +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define CONFIG_USBC_RETIMER_NB7V904M + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +#undef PD_POWER_SUPPLY_TURN_ON_DELAY +#undef PD_POWER_SUPPLY_TURN_OFF_DELAY +/* 20% margin added for these timings */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 13080 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 16080 /* us */ + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_SUB_ANALOG, /* ADC13 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_GANFENG, + BATTERY_POWTECH_SG20JL1C, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/beadrix/build.mk b/board/beadrix/build.mk new file mode 100644 index 0000000000..01b890bf29 --- /dev/null +++ b/board/beadrix/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/beadrix/cbi_ssfc.c b/board/beadrix/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/beadrix/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/beadrix/cbi_ssfc.h b/board/beadrix/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/beadrix/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/beadrix/ec.tasklist b/board/beadrix/ec.tasklist new file mode 100644 index 0000000000..253501100e --- /dev/null +++ b/board/beadrix/ec.tasklist @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TRENTA_TASK_STACK_SIZE) diff --git a/board/beadrix/gpio.inc b/board/beadrix/gpio.inc new file mode 100644 index 0000000000..b450c520e8 --- /dev/null +++ b/board/beadrix/gpio.inc @@ -0,0 +1,146 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(USB_C1_INT_V1_ODL, PIN(E, 6), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c1_interrupt) /* TCPC, charger, BC12 - board version 1 */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_HIGH) +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) /* Board rev 1, NC board rev 0 */ + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc pins which will run to the I/O board */ +GPIO(EC_SUB_IO_1_1, PIN(L, 3), GPIO_INPUT) +GPIO(EC_SUB_IO_1_2, PIN(F, 0), GPIO_INPUT) +GPIO(EC_SUB_IO_2_1, PIN(F, 1), GPIO_INPUT) +GPIO(EC_SUB_IO_2_2, PIN(L, 2), GPIO_INPUT) + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(IMVP9_PE, PIN(J, 3), GPIO_OUT_LOW) +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) + +/* LEDs */ +GPIO(EC_LED_R_ODL, PIN(A, 1), GPIO_OUT_LOW) +GPIO(EC_LED_B_ODL, PIN(A, 3), GPIO_OUT_LOW) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOA0_NC, PIN(A, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA2_NC, PIN(A, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA7_NC, PIN(A, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOB5_NC, PIN(B, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF4_NC, PIN(F, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ0_NC, PIN(J, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ1_NC, PIN(J, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(0)), 0, MODULE_ADC, 0) /* ADC13: EC_SUB_ANALOG */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(0)), 0, MODULE_PWM, 0) /* KB_BL_PWM */ diff --git a/board/beadrix/led.c b/board/beadrix/led.c new file mode 100644 index 0000000000..cc78a5e0b3 --- /dev/null +++ b/board/beadrix/led.c @@ -0,0 +1,151 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Beadrix specific LED settings. */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "common.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_BLUE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color(enum led_color color) +{ + gpio_set_level(GPIO_EC_LED_R_ODL, + (color == LED_RED) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(GPIO_EC_LED_B_ODL, + (color == LED_BLUE) ? BAT_LED_ON : BAT_LED_OFF); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color(LED_BLUE); + else if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color(LED_RED); + else + led_set_color(LED_OFF); + + return EC_SUCCESS; +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + enum led_color color = LED_OFF; + int period = 0; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate amber on when charging. */ + color = LED_RED; + break; + case LED_PWRS_DISCHARGE: + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* Discharging in S3: Red 1 sec, off 3 sec */ + period = (1 + 3) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_OFF; + } else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + /* Discharging in S5: off */ + color = LED_OFF; + } else if (chipset_in_state(CHIPSET_STATE_ON)) { + /* Discharging in S0: Blue on */ + color = LED_BLUE; + } + break; + case LED_PWRS_ERROR: + /* Battery error: Red 1 sec, off 1 sec */ + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_OFF; + break; + case LED_PWRS_CHARGE_NEAR_FULL: + /* Full Charged: Blue on */ + color = LED_BLUE; + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_BLUE; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode: Blue 2 sec, Red 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) + color = LED_BLUE; + else + color = LED_RED; + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + led_set_color(color); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_BATTERY_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_BLUE : LED_OFF; + + led_auto_control(EC_LED_ID_BATTERY_LED, 0); + + led_set_color(color); +} diff --git a/board/beadrix/usb_pd_policy.c b/board/beadrix/usb_pd_policy.c new file mode 100644 index 0000000000..c22c68d224 --- /dev/null +++ b/board/beadrix/usb_pd_policy.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + if (port < 0 || port >= board_get_usb_pd_port_count()) + return; + + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/beadrix/vif_override.xml b/board/beadrix/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/beadrix/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/beetley/battery.c b/board/beetley/battery.c new file mode 100644 index 0000000000..0402ef33fd --- /dev/null +++ b/board/beetley/battery.c @@ -0,0 +1,192 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all beetley battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* SMP L20M3PG0 Battery Information */ + [BATTERY_SMP1] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L20M3PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* SMP L20M3PG3 Battery Information */ + [BATTERY_SMP2] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L20M3PG3", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* LGC L20L3PG0 Battery Information */ + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "LGC", + .device_name = "L20L3PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 73, + }, + }, + + /* Sunwoda L20D3PG0 Battery Information */ + [BATTERY_SUNWODA] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "L20D3PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 205, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* Celxert L20C3PG0 Battery Information */ + [BATTERY_CELXPERT] = { + .fuel_gauge = { + .manuf_name = "Celxpert", + .device_name = "L20C3PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP1; diff --git a/board/beetley/board.c b/board/beetley/board.c new file mode 100644 index 0000000000..7bd12e9bdb --- /dev/null +++ b/board/beetley/board.c @@ -0,0 +1,496 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Beetley board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "cros_board_info.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define INT_RECHECK_US 5000 + +__override struct keyboard_scan_config keyscan_config = { + .output_settle_us = 80, + .debounce_down_us = 30 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void hdmi_hpd_interrupt(enum gpio_signal s) +{ + gpio_set_level(GPIO_USB_C1_DP_HPD, !gpio_get_level(s)); +} + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, +}; + +static const struct ec_response_keybd_config beetley_keybd = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &beetley_keybd; +} + +/* USB-A charging control */ +const int usb_port_enable[USB_PORT_COUNT] = { GPIO_EN_USB_A0_VBUS }; + +/* Sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t base_lsm6dsm_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* Lid accel private data */ +static struct stprivate_data g_lis2dwl_data; +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DWL, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2dwl_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, + .rot_standard_ref = NULL, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DS3, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_lsm6dsm_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DS3, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_lsm6dsm_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, +}; + +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void board_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + gpio_enable_interrupt(GPIO_HDMI_HPD_SUB_ODL); + + /* Set LEDs luminance */ + pwm_set_duty(PWM_CH_LED_RED, 70); + pwm_set_duty(PWM_CH_LED_GREEN, 70); + pwm_set_duty(PWM_CH_LED_WHITE, 70); + + /*Enable Base Accel interrupt*/ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + + /* Setting scan mask KSO11, KSO12, KSO13 and KSO14 */ + keyscan_config.actual_key_mask[11] = 0xfe; + keyscan_config.actual_key_mask[12] = 0xff; + keyscan_config.actual_key_mask[13] = 0xff; + keyscan_config.actual_key_mask[14] = 0xff; +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Charger IC need to be put into their "low power mode" before + * entering the Z-state. + * + * b:186717219: In order to solve the power consumption problem of + * hibernate,HW solution is adopted after board id 3 to solve the + * problem that AC cannot wake up hibernate mode. + */ + raa489000_hibernate(0, true); +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + return status; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + if (port != 0 && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + CPRINTUSB("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + tcpc_write(0, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(0, false); + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTUSB("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(0, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTUSB("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_RED] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_GREEN] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_WHITE] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Charge", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "5V_Inductor", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} diff --git a/board/beetley/board.h b/board/beetley/board.h new file mode 100644 index 0000000000..f2d43534fa --- /dev/null +++ b/board/beetley/board.h @@ -0,0 +1,154 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Beetley board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSYCMD_BATTERY_V2 + +/* Sysetem unlocked in early development */ +#define CONFIG_SYSTEM_UNLOCKED + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_RAA489000 +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) + +/* DAC for PSYS */ +#define CONFIG_DAC + +/* LED */ +#define CONFIG_LED_ONOFF_STATES + +/*SENSOR*/ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* PWM */ +#define CONFIG_PWM + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux */ +#define CONFIG_USB_MUX_IT5205 + +/* KeyBoard */ +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_KEYPAD +#define CONFIG_KEYBOARD_STRICT_DEBOUNCE + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum pwm_channel { + PWM_CH_LED_RED, + PWM_CH_LED_GREEN, + PWM_CH_LED_WHITE, + PWM_CH_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_SMP1, + BATTERY_SMP2, + BATTERY_LGC, + BATTERY_SUNWODA, + BATTERY_CELXPERT, + BATTERY_TYPE_COUNT, +}; + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/beetley/build.mk b/board/beetley/build.mk new file mode 100644 index 0000000000..01b890bf29 --- /dev/null +++ b/board/beetley/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/beetley/cbi_ssfc.c b/board/beetley/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/beetley/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/beetley/cbi_ssfc.h b/board/beetley/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/beetley/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/beetley/ec.tasklist b/board/beetley/ec.tasklist new file mode 100644 index 0000000000..8ccdfc81b2 --- /dev/null +++ b/board/beetley/ec.tasklist @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/beetley/gpio.inc b/board/beetley/gpio.inc new file mode 100644 index 0000000000..0677e5a2ac --- /dev/null +++ b/board/beetley/gpio.inc @@ -0,0 +1,152 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(HDMI_HPD_SUB_ODL, PIN(E, 7), GPIO_INT_BOTH, hdmi_hpd_interrupt) + + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Used by baseboard z-state enable, but not present on beetley */ +UNIMPLEMENTED(USB_C1_INT_ODL) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_A1_VBUS, PIN(E, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_LOW) + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc pins which will run to the I/O board */ + + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) + +/*TP*/ +GPIO(TP, PIN(C, 3), GPIO_INPUT | GPIO_HIGH) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOA0_NC, PIN(A, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOB5_NC, PIN(B, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC4_NC, PIN(C, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF0_NC, PIN(F, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF1_NC, PIN(F, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF4_NC, PIN(F, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH2_NC, PIN(H, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ1_NC, PIN(J, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ3_NC, PIN(J, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL0_NC, PIN(L, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL3_NC, PIN(L, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V SENSOR */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(2)), 0, MODULE_ADC, 0) /* ADC15: TEMP_SENSOR_3 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + +/* DAC */ +ALTERNATE(PIN_MASK(J, BIT(2)), 0, MODULE_DAC, 0) /* DAC2: EC_AP_PSYS */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(1) | BIT(2) | BIT(3)), 0, MODULE_PWM, 0) /* RED led, GREEN led, WHITE led */ diff --git a/board/beetley/led.c b/board/beetley/led.c new file mode 100644 index 0000000000..8a79e41773 --- /dev/null +++ b/board/beetley/led.c @@ -0,0 +1,117 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Beetley specific PWM LED settings. + */ + +#include "common.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "pwm.h" + +#define LED_OFF_LVL 0 +#define LED_ON_LVL 1 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_RED: + pwm_enable(PWM_CH_LED_RED, LED_ON_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + pwm_enable(PWM_CH_LED_RED, LED_ON_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_ON_LVL); + break; + case EC_LED_COLOR_GREEN: + pwm_enable(PWM_CH_LED_RED, LED_OFF_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + pwm_enable(PWM_CH_LED_RED, LED_OFF_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_OFF_LVL); + break; + } +} + +__override void led_set_color_power(enum ec_led_colors color) +{ + if (color == EC_LED_COLOR_WHITE) + pwm_enable(PWM_CH_LED_WHITE, LED_ON_LVL); + else + pwm_enable(PWM_CH_LED_WHITE, LED_OFF_LVL); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_battery(EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_battery(LED_OFF); + } else { + return EC_ERROR_INVAL; + } + return EC_SUCCESS; +} diff --git a/board/beetley/usb_pd_policy.c b/board/beetley/usb_pd_policy.c new file mode 100644 index 0000000000..a7633b73ac --- /dev/null +++ b/board/beetley/usb_pd_policy.c @@ -0,0 +1,71 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + if (port != 0) + return; + + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port != 0) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} diff --git a/board/beetley/vif_override.xml b/board/beetley/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/beetley/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/bellis/battery.c b/board/bellis/battery.c new file mode 100644 index 0000000000..d74876ec27 --- /dev/null +++ b/board/bellis/battery.c @@ -0,0 +1,104 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "gpio.h" + +const struct board_batt_params board_battery_info[] = { + /* LGC L20L3PG2, Gauge IC: RAJ240047A20DNP. */ + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "LGC", + .device_name = "L20L3PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 73, + }, + }, + /* Sunwoda L20D3PG2, Gauge IC: BQ40Z697A. */ + [BATTERY_SUNWODA] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "L20D3PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11250, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* SIMPLO L20M3PG2, Gauge IC: BQ40Z697A. */ + [BATTERY_SMP] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L20M3PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + }, + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11250, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -40, + .discharging_max_c = 73, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC; + +enum battery_present battery_hw_present(void) +{ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/bellis/board.c b/board/bellis/board.c new file mode 100644 index 0000000000..9a2054a399 --- /dev/null +++ b/board/bellis/board.c @@ -0,0 +1,595 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "backlight.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/battery/max17055.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/fusb302.h" +#include "driver/usb_mux/it5205.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "i2c_bitbang.h" +#include "it8801.h" +#include "keyboard_backlight.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "panic.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "spi.h" +#include "system.h" +#include "task.h" +#include "tcpm/tcpm.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +static void tcpc_alert_event(enum gpio_signal signal) +{ + schedule_deferred_pd_interrupt(0 /* port */); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(5) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(15) }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 2, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct i2c_port_t i2c_bitbang_ports[] = { + { .name = "battery", + .port = 3, + .kbps = 100, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA, + .drv = &bitbang_drv }, +}; +const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); + +#define BC12_I2C_ADDR PI3USB9201_I2C_ADDR_3 + +/* power signal list. Must match order of enum power_signal. */ +const struct power_signal_info power_signal_list[] = { + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, +}; +BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* + * TODO(b/133200075): Tune this once we have the final performance + * out of the driver and the i2c bus. + */ + .output_settle_us = 35, + .debounce_down_us = 5 * MSEC, + .debounce_up_us = 40 * MSEC, + .scan_period_us = 10 * MSEC, + .min_post_scan_delay_us = 10 * MSEC, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { + [0] = { + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, + .drv = &it8801_ioexpander_drv, + }, +}; + +/******************************************************************************/ +/* SPI devices */ +const struct spi_device_t spi_devices[] = { + { CONFIG_SPI_ACCEL_PORT, 2, GPIO_EC_SENSOR_SPI_NSS }, +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/******************************************************************************/ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, + }, + .drv = &fusb302_tcpm_drv, + }, +}; + +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) +{ + /* This driver does not use host command ACKs */ + *ack_required = false; + + /* + * svdm_dp_attention() did most of the work, we only need to notify + * host here. + */ + host_set_single_event(EC_HOST_EVENT_USB_MUX); +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, + }, +}; + +/* Charger config. Start i2c address at 1, update during runtime */ +struct charger_config_t chg_chips[] = { + { + .i2c_port = 2, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* Board version depends on ADCs, so init i2c port after ADC */ +static void charger_config_complete(void) +{ + chg_chips[0].i2c_port = board_get_charger_i2c(); +} +DECLARE_HOOK(HOOK_INIT, charger_config_complete, HOOK_PRIO_INIT_ADC + 1); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} + +static int force_discharge; + +int board_set_active_charge_port(int charge_port) +{ + CPRINTS("New chg p%d", charge_port); + + /* ignore all request when discharge mode is on */ + if (force_discharge && charge_port != CHARGE_PORT_NONE) + return EC_SUCCESS; + + switch (charge_port) { + case CHARGE_PORT_USB_C: + /* Don't charge from a source port */ + if (board_vbus_source_enabled(charge_port)) + return -1; + break; + default: + /* + * To ensure the fuel gauge (max17055) is always powered + * even when battery is disconnected, keep VBAT rail on but + * set the charging current to minimum. + */ + charger_set_current(CHARGER_SOLO, 0); + break; + } + + return EC_SUCCESS; +} + +int board_discharge_on_ac(int enable) +{ + int ret, port; + + if (enable) { + port = CHARGE_PORT_NONE; + } else { + /* restore the charge port state */ + port = charge_manager_get_override(); + if (port == OVERRIDE_OFF) + port = charge_manager_get_active_charge_port(); + } + + ret = charger_discharge_on_ac(enable); + if (ret) + return ret; + + force_discharge = enable; + return board_set_active_charge_port(port); +} + +int pd_snk_is_vbus_provided(int port) +{ + /* TODO(b:138352732): read IT8801 GPIO EN_USBC_CHARGE_L */ + return EC_ERROR_UNIMPLEMENTED; +} + +void bc12_interrupt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +#ifndef VARIANT_KUKUI_NO_SENSORS +static void board_spi_enable(void) +{ + /* + * Pin mux spi peripheral away from emmc, since RO might have + * left them there. + */ + gpio_config_module(MODULE_SPI_FLASH, 0); +#ifdef CHIP_FAMILY_STM32L4 + /* Set I/O speed before AF configured */ + /* EMMC SPI SLAVE: PB13/14/15 */ + /* SENSORS SPI controller: PB10, PB12, PC2, PC3 */ + STM32_GPIO_OSPEEDR(GPIO_B) |= 0xFF300000; + STM32_GPIO_OSPEEDR(GPIO_C) |= 0x000000F0; + + /* Enable clocks to SPI2 module. */ + STM32_RCC_APB1ENR1 |= STM32_RCC_PB1_SPI2; + + /* Reset SPI2 to clear state left over from the emmc slave. */ + STM32_RCC_APB1RSTR1 |= STM32_RCC_PB1_SPI2; + STM32_RCC_APB1RSTR1 &= ~STM32_RCC_PB1_SPI2; +#else + /* Enable clocks to SPI2 module. */ + STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; + + /* Reset SPI2 to clear state left over from the emmc slave. */ + STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; + STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; +#endif + /* Reinitialize spi peripheral. */ + spi_enable(&spi_devices[0], 1); + + /* Pin mux spi peripheral toward the sensor. */ + gpio_config_module(MODULE_SPI_CONTROLLER, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, + MOTION_SENSE_HOOK_PRIO - 1); + +static void board_spi_disable(void) +{ + /* Set pins to a state calming the sensor down. */ + gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); + gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); + + /* Disable spi peripheral and clocks. */ + spi_enable(&spi_devices[0], 0); +#ifdef CHIP_FAMILY_STM32L4 + STM32_RCC_APB1ENR1 &= ~STM32_RCC_PB1_SPI2; +#else + STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; +#endif +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, + MOTION_SENSE_HOOK_PRIO + 1); +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + +static void board_init(void) +{ + /* If the reset cause is external, pulse PMIC force reset. */ + if (system_get_reset_flags() == EC_RESET_FLAG_RESET_PIN) { + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 0); + msleep(100); + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 1); + } + + /* Enable TCPC alert interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + +#ifndef VARIANT_KUKUI_NO_SENSORS + /* Enable interrupts from BMI160 sensor. */ + gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); + + /* For some reason we have to do this again in case of sysjump */ + board_spi_enable(); +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + + /* Enable interrupt from PMIC. */ + gpio_enable_interrupt(GPIO_PMIC_EC_RESETB); + + /* Enable BC12 interrupt */ + gpio_enable_interrupt(GPIO_BC12_EC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +#ifndef VARIANT_KUKUI_NO_SENSORS +/* Motion sensors */ +/* Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Rotation matrixes */ +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* sensor private data */ +/* Lid accel private data */ +static struct stprivate_data g_lis2dwl_data; +/* Base accel private data */ +static struct bmi_drv_data_t g_bmi160_data; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DWL, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2dwl_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +const struct it8801_pwm_t it8801_pwm_channels[] = { + [IT8801_PWM_CH_KBLIGHT] = { .index = 4 }, +}; + +void board_kblight_init(void) +{ + kblight_register(&kblight_it8801); +} + +bool board_has_kb_backlight(void) +{ + /* Default enable keyboard backlight */ + return true; +} +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + +/* Battery functions */ +#define SB_SMARTCHARGE 0x26 +/* Quick charge enable bit */ +#define SMART_QUICK_CHARGE 0x02 +/* Quick charge support bit */ +#define MODE_QUICK_CHARGE_SUPPORT 0x01 + +static void sb_quick_charge_mode(int enable) +{ + int val, rv; + + rv = sb_read(SB_SMARTCHARGE, &val); + if (rv || !(val & MODE_QUICK_CHARGE_SUPPORT)) + return; + + if (enable) + val |= SMART_QUICK_CHARGE; + else + val &= ~SMART_QUICK_CHARGE; + + sb_write(SB_SMARTCHARGE, val); +} + +/* Called on AP S0iX -> S0 transition */ +static void board_chipset_resume(void) +{ +#ifndef VARIANT_KUKUI_NO_SENSORS + if (board_has_kb_backlight()) + ioex_set_level(IOEX_KB_BL_EN, 1); +#endif + + /* Normal charge mode */ + sb_quick_charge_mode(0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S0iX transition */ +static void board_chipset_suspend(void) +{ +#ifndef VARIANT_KUKUI_NO_SENSORS + if (board_has_kb_backlight()) + ioex_set_level(IOEX_KB_BL_EN, 0); +#endif + + /* Quick charge mode */ + sb_quick_charge_mode(1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S5 -> S3 transition */ +static void board_chipset_startup(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S5 transition */ +static void board_chipset_shutdown(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); + +int board_get_charger_i2c(void) +{ + /* TODO(b:138415463): confirm the bus allocation for future builds */ + return I2C_PORT_CHARGER; +} + +int board_get_battery_i2c(void) +{ + return I2C_PORT_BATTERY; +} + +#ifdef SECTION_IS_RW +static int it8801_get_target_channel(enum pwm_channel *channel, int type, + int index) +{ + switch (type) { + case EC_PWM_TYPE_GENERIC: + *channel = index; + break; + default: + return -1; + } + + return *channel >= 1; +} + +static enum ec_status +host_command_pwm_set_duty(struct host_cmd_handler_args *args) +{ + const struct ec_params_pwm_set_duty *p = args->params; + enum pwm_channel channel; + uint16_t duty; + + if (it8801_get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + duty = (uint32_t)p->duty * 255 / 65535; + it8801_pwm_set_raw_duty(channel, duty); + it8801_pwm_enable(channel, p->duty > 0); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_DUTY, host_command_pwm_set_duty, + EC_VER_MASK(0)); + +static enum ec_status +host_command_pwm_get_duty(struct host_cmd_handler_args *args) +{ + const struct ec_params_pwm_get_duty *p = args->params; + struct ec_response_pwm_get_duty *r = args->response; + + enum pwm_channel channel; + + if (it8801_get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + r->duty = (uint32_t)it8801_pwm_get_raw_duty(channel) * 65535 / 255; + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_DUTY, host_command_pwm_get_duty, + EC_VER_MASK(0)); +#endif diff --git a/board/bellis/board.h b/board/bellis/board.h new file mode 100644 index 0000000000..7720b5a391 --- /dev/null +++ b/board/bellis/board.h @@ -0,0 +1,190 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Configuration for Bellis */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KUKUI_JACUZZI +#define VARIANT_KUKUI_BATTERY_SMART +#define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32L431 + +#ifndef SECTION_IS_RW +#define VARIANT_KUKUI_NO_SENSORS +#endif /* SECTION_IS_RW */ + +#include "baseboard.h" + +#undef CONFIG_CHIPSET_POWER_SEQ_VERSION +#define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 +#undef CONFIG_SYSTEM_UNLOCKED + +/* PLL configuration. Freq = STM32_HSE_CLOCK or HSI (16MHz) * n/m/r */ +#undef STM32_PLLM +#undef STM32_PLLN +#undef STM32_PLLR +#define STM32_PLLM 1 +#ifdef STM32_HSE_CLOCK +#define STM32_PLLN 12 +#else +#define STM32_PLLN 10 +#endif +#define STM32_PLLR 2 + +#define STM32_USE_PLL + +#define CONFIG_BATTERY_HW_PRESENT_CUSTOM + +#define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +#define CONFIG_CHARGER_RUNTIME_CONFIG + +#define CONFIG_BC12_DETECT_PI3USB9201 + +#define CONFIG_EXTPOWER_GPIO +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 200 + +#define CONFIG_I2C_BITBANG +#undef I2C_BITBANG_PORT_COUNT +#define I2C_BITBANG_PORT_COUNT 1 +#undef CONFIG_I2C_NACK_RETRY_COUNT +#define CONFIG_I2C_NACK_RETRY_COUNT 10 +#define CONFIG_SMBUS_PEC + +#define CONFIG_USB_PD_TCPM_FUSB302 +#define CONFIG_USB_PD_DISCHARGE_GPIO +#define CONFIG_USB_PD_TCPC_LOW_POWER + +#define CONFIG_USB_MUX_IT5205 + +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_POWER_LED + +#undef CONFIG_WATCHDOG_PERIOD_MS +#define CONFIG_WATCHDOG_PERIOD_MS 4000 + +/* Motion Sensors */ +#ifndef VARIANT_KUKUI_NO_SENSORS +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ALS +#define CONFIG_CMD_ACCEL_INFO + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#ifdef SECTION_IS_RW +#define CONFIG_IO_EXPANDER_IT8801_PWM +#define CONFIG_KEYBOARD_BACKLIGHT +#endif + +#endif /* VARIANT_KUKUI_NO_SENSORS */ + +/* I2C ports */ +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_CHARGER 2 +#define I2C_PORT_SENSORS 2 +#define I2C_PORT_KB_DISCRETE 2 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BATTERY 3 +#define I2C_PORT_TCPC0 0 + +#undef I2C_CONTROLLER_COUNT +#undef I2C_PORT_COUNT +#define I2C_CONTROLLER_COUNT 3 +#define I2C_PORT_COUNT 3 + +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 + +/* Enable Accel over SPI */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ + +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_USE_GPIO +/* Define the MKBP events which are allowed to wakeup AP in S3. */ +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +#undef CONFIG_GMR_TABLET_MODE +#undef GPIO_TABLET_MODE_L +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH + +#ifndef __ASSEMBLER__ + +enum adc_channel { + /* Real ADC channels begin here */ + ADC_BOARD_ID = 0, + ADC_EC_SKU_ID, + ADC_CH_COUNT +}; + +/* power signal definitions */ +enum power_signal { + AP_IN_S3_L, + PMIC_PWR_GOOD, + + /* Number of signals */ + POWER_SIGNAL_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum charge_port { + CHARGE_PORT_USB_C, +}; + +enum battery_type { + BATTERY_LGC, + BATTERY_SUNWODA, + BATTERY_SMP, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { + IT8801_PWM_CH_KBLIGHT = 0, +}; + +#include "gpio_signal.h" +#include "registers.h" + +#ifdef SECTION_IS_RO +/* Interrupt handler for emmc task */ +void emmc_cmd_interrupt(enum gpio_signal signal); +#endif + +void bc12_interrupt(enum gpio_signal signal); +void board_reset_pd_mcu(void); +int board_get_version(void); + +/* returns the i2c port number of charger/battery */ +int board_get_charger_i2c(void); +int board_get_battery_i2c(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/bellis/build.mk b/board/bellis/build.mk new file mode 100644 index 0000000000..604790d66c --- /dev/null +++ b/board/bellis/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# +# +# STmicro STM32L431RCI +CHIP:=stm32 +CHIP_FAMILY:=stm32l4 +CHIP_VARIANT:=stm32l431x +BASEBOARD:=kukui + +board-y=battery.o board.o led.o diff --git a/board/bellis/ec.tasklist b/board/bellis/ec.tasklist new file mode 100644 index 0000000000..2d69c1b113 --- /dev/null +++ b/board/bellis/ec.tasklist @@ -0,0 +1,20 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, 1024) \ + TASK_ALWAYS_RO(EMMC, emmc_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/bellis/gpio.inc b/board/bellis/gpio.inc new file mode 100644 index 0000000000..a80ef27c97 --- /dev/null +++ b/board/bellis/gpio.inc @@ -0,0 +1,120 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(B, 1), GPIO_INT_FALLING | GPIO_PULL_UP, + tcpc_alert_event) +GPIO_INT(POWER_BUTTON_L, PIN(A, 11), GPIO_INT_BOTH | GPIO_PULL_UP, + power_button_interrupt) /* EC_PWR_BTN_ODL */ +GPIO_INT(AP_IN_SLEEP_L, PIN(C, 12), GPIO_INT_BOTH | GPIO_PULL_DOWN, + power_signal_interrupt) +GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, + power_signal_interrupt) +GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, + chipset_reset_request_interrupt) +GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, + bmi160_interrupt) +GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, + emmc_cmd_interrupt) +GPIO_INT(SPI1_NSS, PIN(A, 15), GPIO_INT_BOTH | GPIO_PULL_UP, + spi_event) /* SPI_AP_EC_CS_L */ +GPIO_INT(LID_OPEN, PIN(C, 5), GPIO_INT_BOTH, + lid_interrupt) +GPIO_INT(AC_PRESENT, PIN(A, 6), GPIO_INT_BOTH, + extpower_interrupt) /* ACOK_OD */ +GPIO_INT(BC12_EC_INT_ODL, PIN(C, 9), GPIO_INT_FALLING, + bc12_interrupt) +GPIO_INT(IT8801_SMB_INT, PIN(A, 8), GPIO_INT_FALLING | GPIO_PULL_UP, + io_expander_it8801_interrupt) /* KB_INT_ODL */ +GPIO_INT(AP_EC_WATCHDOG_L, PIN(D, 2), GPIO_INT_FALLING, + chipset_watchdog_interrupt) + +/* Unimplemented interrupts */ +GPIO(ALS_RGB_INT_ODL, PIN(C, 10), GPIO_INPUT) +GPIO(TABLET_MODE_L, PIN(B, 11), GPIO_INPUT) + +/* Reset pins */ +GPIO(AP_SYS_RST_L, PIN(C, 11), GPIO_OUT_LOW) +GPIO(PMIC_WATCHDOG_L, PIN(A, 2), GPIO_OUT_LOW) +GPIO(PMIC_EN_ODL, PIN(H, 0), GPIO_ODR_HIGH) + +/* + * I2C pins should be configured as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(I2C1_SCL, PIN(B, 8), GPIO_INPUT) +GPIO(I2C1_SDA, PIN(B, 9), GPIO_INPUT) +GPIO(I2C3_SCL, PIN(C, 0), GPIO_INPUT) +GPIO(I2C3_SDA, PIN(C, 1), GPIO_INPUT) +GPIO(I2C4_SCL, PIN(A, 5), GPIO_ODR_HIGH) +GPIO(I2C4_SDA, PIN(C, 4), GPIO_ODR_HIGH) + +/* Analog pins */ +GPIO(BOARD_ID, PIN(A, 0), GPIO_ANALOG) +GPIO(EC_SKU_ID, PIN(B, 0), GPIO_ANALOG) + +/* Other input pins */ +GPIO(WP_L, PIN(C, 8), GPIO_INPUT) /* EC_FLASH_WP_ODL */ +GPIO(BOOT0, PIN(H, 3), GPIO_INPUT) +GPIO(CCD_MODE_ODL, PIN(A, 1), GPIO_INPUT) + +/* Other output pins */ +GPIO(EC_BATT_PRES_ODL, PIN(A, 7), GPIO_INPUT) +GPIO(EC_BL_EN_OD, PIN(A, 13), GPIO_ODR_HIGH) +GPIO(EN_USBA_5V, PIN(C, 14), GPIO_OUT_LOW) +GPIO(EC_SENSOR_SPI_MISO, PIN(C, 2), GPIO_INPUT) +GPIO(EC_SENSOR_SPI_MOSI, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_SENSOR_SPI_NSS, PIN(B, 12), GPIO_OUT_HIGH) +GPIO(EC_SENSOR_SPI_CK, PIN(B, 10), GPIO_OUT_LOW) +GPIO(ENTERING_RW, PIN(C, 6), GPIO_ODR_HIGH) /* EC_ENTERING_RW_ODL */ +GPIO(EC_INT_L, PIN(C, 7), GPIO_ODR_HIGH) /* EC_AP_INT_ODL */ +GPIO(EC_BOARD_ID_EN_L, PIN(C, 15), GPIO_ODR_HIGH) /* EC_BOARD_ID_EN_ODL */ +GPIO(USB_C0_HPD_OD, PIN(H, 1), GPIO_ODR_LOW) +GPIO(BOOTBLOCK_EN_L, PIN(A, 12), GPIO_ODR_HIGH) +GPIO(EN_PP1800_S5_L, PIN(A, 14), GPIO_OUT_LOW) +GPIO(USB_C0_DISCHARGE, PIN(B, 6), GPIO_OUT_LOW) + +IOEX(PWR_LED_WHITE_L, EXPIN(0, 1, 4), GPIO_OUT_HIGH) +IOEX(BAT_LED_GREEN_FULL_L, EXPIN(0, 1, 3), GPIO_OUT_HIGH) +IOEX(BAT_LED_RED_L, EXPIN(0, 1, 2), GPIO_OUT_HIGH) +IOEX(KB_BL_EN, EXPIN(0, 0, 7), GPIO_OUT_LOW) + +/* + * TODO(b:138352732): On IT88801 expander, To be readded once IT8801 driver and + * gpio expander framework has landed. + */ +UNIMPLEMENTED(EN_PP5000_USBC) +UNIMPLEMENTED(PMIC_FORCE_RESET_ODL) +UNIMPLEMENTED(EN_USBC_CHARGE_L) + +/* USART1: PA9/PA10 */ +ALTERNATE(PIN_MASK(A, 0x0600), 7, MODULE_UART, 0) +/* I2C MASTER: PB8/9 */ +ALTERNATE(PIN_MASK(B, 0x0300), 4, MODULE_I2C, GPIO_ODR_HIGH ) +/* I2C MASTER: PC0/C1 */ +ALTERNATE(PIN_MASK(C, 0x0003), 4, MODULE_I2C, GPIO_ODR_HIGH ) + + +/* SPI1 */ +/* SPI SLAVE: PB3/4/5 */ +ALTERNATE(PIN_MASK(B, 0x0038), 5, MODULE_SPI, 0) +/* SPI SLAVE CS: PA15 */ +ALTERNATE(PIN_MASK(A, 0x8000), 5, MODULE_SPI, 0) + +/* SPI2 */ +/* Shared between slave for emmc and master for bmi160 */ +/* They're mutually exclusive with gpio_config_module. */ +/* EMMC SPI SLAVE: PB13/14/15 */ +ALTERNATE(PIN_MASK(B, 0xE000), 5, MODULE_SPI_FLASH, 0) +/* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 5, MODULE_SPI_CONTROLLER, 0) diff --git a/board/bellis/led.c b/board/bellis/led.c new file mode 100644 index 0000000000..420c491308 --- /dev/null +++ b/board/bellis/led.c @@ -0,0 +1,120 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Bellis + */ +#include "common.h" +#include "driver/ioexpander/it8801.h" +#include "ec_commands.h" +#include "ioexpander.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_GREEN: + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_ON_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_ON_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_ON_LVL); + break; + case EC_LED_COLOR_RED: + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_OFF_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_OFF_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_OFF_LVL); + break; + } +} + +__override void led_set_color_power(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + ioex_set_level(IOEX_PWR_LED_WHITE_L, LED_ON_LVL); + break; + default: + ioex_set_level(IOEX_PWR_LED_WHITE_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_RED] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_battery(EC_LED_COLOR_RED); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } else { + return EC_ERROR_INVAL; + } + return EC_SUCCESS; +} diff --git a/board/bellis/vif_override.xml b/board/bellis/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/bellis/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/berknip/battery.c b/board/berknip/battery.c index 526375c0db..d024e710c3 100644 --- a/board/berknip/battery.c +++ b/board/berknip/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/berknip/board.c b/board/berknip/board.c index 9e7be926b7..ee4158e671 100644 --- a/board/berknip/board.c +++ b/board/berknip/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,14 +6,13 @@ /* Berknip board configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" -#include "charger.h" #include "cbi_ec_fw_config.h" +#include "charger.h" #include "cros_board_info.h" -#include "driver/accelgyro_bmi_common.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" +#include "driver/accelgyro_bmi_common.h" #include "driver/retimer/pi3hdx1204.h" #include "driver/retimer/tusb544.h" #include "driver/temp_sensor/sb_tsi.h" @@ -33,14 +32,17 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_charge.h" #include "usb_mux.h" +static void hdmi_hpd_interrupt(enum gpio_signal signal); + +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { @@ -78,6 +80,11 @@ const struct pi3hdx1204_tuning pi3hdx1204_tuning = { .de_offset = PI3HDX1204_DE_DB_MINUS5, }; +static int check_hdmi_hpd_status(void) +{ + return gpio_get_level(GPIO_DP1_HPD_EC_IN); +} + /***************************************************************************** * Board suspend / resume */ @@ -89,9 +96,8 @@ static void board_chipset_resume(void) if (ec_config_has_hdmi_retimer_pi3hdx1204()) { ioex_set_level(IOEX_HDMI_POWER_EN_DB, 1); msleep(PI3HDX1204_POWER_ON_DELAY_MS); - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - 1); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, + check_hdmi_hpd_status()); } } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); @@ -99,9 +105,7 @@ DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); static void board_chipset_suspend(void) { if (ec_config_has_hdmi_retimer_pi3hdx1204()) { - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - 0); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, 0); ioex_set_level(IOEX_HDMI_POWER_EN_DB, 0); } @@ -114,8 +118,12 @@ DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); * chip and it need a board specific driver. * Overall, it will use chained mux framework. */ -static int pi3usb221_set_mux(const struct usb_mux *me, mux_state_t mux_state) +static int pi3usb221_set_mux(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + if (mux_state & USB_PD_MUX_POLARITY_INVERTED) ioex_set_level(IOEX_USB_C0_SBU_FLIP, 0); else @@ -135,14 +143,21 @@ const struct usb_mux_driver usbc0_sbu_mux_driver = { * Since PI3USB221 is not a i2c device, .i2c_port and * .i2c_addr_flags are not required here. */ -const struct usb_mux usbc0_sbu_mux = { - .usb_port = USBC_PORT_C0, - .driver = &usbc0_sbu_mux_driver, +const struct usb_mux_chain usbc0_sbu_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &usbc0_sbu_mux_driver, + }, }; /***************************************************************************** * USB-C MUX/Retimer dynamic configuration */ + +/* Place holder for second mux in USBC1 chain */ +struct usb_mux_chain usbc1_mux1; + static void setup_mux(void) { if (ec_config_has_usbc1_retimer_tusb544()) { @@ -153,11 +168,9 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the AMD FP5 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_amd_fp5_usb_mux, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_amd_fp5_usb_mux; /* Set the TUSB544 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_tusb544; + usbc1_mux1.mux = &usbc1_tusb544; } else if (ec_config_has_usbc1_retimer_ps8743()) { ccprints("C1 PS8743 detected"); /* @@ -166,34 +179,87 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the PS8743 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_ps8743, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_ps8743; /* Set the AMD FP5 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_amd_fp5_usb_mux; + usbc1_mux1.mux = &usbc1_amd_fp5_usb_mux; /* Don't have the AMD FP5 flip */ usbc1_amd_fp5_usb_mux.flags = USB_MUX_FLAG_SET_WITHOUT_FLIP; } } -struct usb_mux usb_muxes[] = { +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .next_mux = &usbc0_sbu_mux, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_sbu_mux, }, [USBC_PORT_C1] = { /* Filled in dynamically at startup */ + .next = &usbc1_mux1, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); static int board_tusb544_mux_set(const struct usb_mux *me, - mux_state_t mux_state) + mux_state_t mux_state) { + int rv = EC_SUCCESS; + + if (mux_state & USB_PD_MUX_USB_ENABLED) { + rv = tusb544_i2c_field_update8( + me, TUSB544_REG_USB3_1_1, TUSB544_EQ_RX_MASK, + TUSB544_EQ_RX_DFP_04_UFP_MINUS15); + if (rv) + return rv; + + rv = tusb544_i2c_field_update8( + me, TUSB544_REG_USB3_1_1, TUSB544_EQ_TX_MASK, + TUSB544_EQ_TX_DFP_MINUS14_UFP_MINUS33); + if (rv) + return rv; + + rv = tusb544_i2c_field_update8( + me, TUSB544_REG_USB3_1_2, TUSB544_EQ_RX_MASK, + TUSB544_EQ_RX_DFP_04_UFP_MINUS15); + if (rv) + return rv; + + rv = tusb544_i2c_field_update8( + me, TUSB544_REG_USB3_1_2, TUSB544_EQ_TX_MASK, + TUSB544_EQ_TX_DFP_MINUS14_UFP_MINUS33); + if (rv) + return rv; + } + if (mux_state & USB_PD_MUX_DP_ENABLED) { + rv = tusb544_i2c_field_update8(me, TUSB544_REG_DISPLAYPORT_1, + TUSB544_EQ_RX_MASK, + TUSB544_EQ_RX_DFP_61_UFP_43); + if (rv) + return rv; + + rv = tusb544_i2c_field_update8(me, TUSB544_REG_DISPLAYPORT_1, + TUSB544_EQ_TX_MASK, + TUSB544_EQ_TX_DFP_61_UFP_43); + if (rv) + return rv; + + rv = tusb544_i2c_field_update8(me, TUSB544_REG_DISPLAYPORT_2, + TUSB544_EQ_RX_MASK, + TUSB544_EQ_RX_DFP_61_UFP_43); + if (rv) + return rv; + + rv = tusb544_i2c_field_update8(me, TUSB544_REG_DISPLAYPORT_2, + TUSB544_EQ_TX_MASK, + TUSB544_EQ_TX_DFP_61_UFP_43); + if (rv) + return rv; + /* Enable IN_HPD on the DB */ gpio_or_ioex_set_level(board_usbc1_retimer_inhpd, 1); } else { @@ -203,19 +269,6 @@ static int board_tusb544_mux_set(const struct usb_mux *me, return EC_SUCCESS; } -static int board_ps8743_mux_set(const struct usb_mux *me, - mux_state_t mux_state) -{ - if (mux_state & USB_PD_MUX_DP_ENABLED) - /* Enable IN_HPD on the DB */ - gpio_or_ioex_set_level(board_usbc1_retimer_inhpd, 1); - else - /* Disable IN_HPD on the DB */ - gpio_or_ioex_set_level(board_usbc1_retimer_inhpd, 0); - - return EC_SUCCESS; -} - const struct usb_mux usbc1_tusb544 = { .usb_port = USBC_PORT_C1, .i2c_port = I2C_PORT_TCPC1, @@ -228,7 +281,6 @@ const struct usb_mux usbc1_ps8743 = { .i2c_port = I2C_PORT_TCPC1, .i2c_addr_flags = PS8743_I2C_ADDR1_FLAG, .driver = &ps8743_usb_mux_driver, - .board_set = &board_ps8743_mux_set, }; /***************************************************************************** @@ -265,6 +317,10 @@ static void board_remap_gpio(void) */ gpio_set_flags(GPIO_USB_C1_HPD_IN_DB_V1, GPIO_OUT_LOW); board_usbc1_retimer_inhpd = GPIO_USB_C1_HPD_IN_DB_V1; + + if (ec_config_has_hdmi_retimer_pi3hdx1204()) + gpio_enable_interrupt(GPIO_DP1_HPD_EC_IN); + } else board_usbc1_retimer_inhpd = IOEX_USB_C1_HPD_IN_DB; } @@ -278,6 +334,25 @@ static void setup_fw_config(void) /* Use HOOK_PRIO_INIT_I2C + 2 to be after ioex_init(). */ DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); +static void hdmi_hpd_handler(void) +{ + /* Pass HPD through DB OPT1 HDMI connector to AP's DP1 */ + int hpd = check_hdmi_hpd_status(); + + gpio_set_level(GPIO_EC_DP1_HPD, hpd); + ccprints("HDMI HPD %d", hpd); + pi3hdx1204_enable( + I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, + chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON) && hpd); +} +DECLARE_DEFERRED(hdmi_hpd_handler); + +static void hdmi_hpd_interrupt(enum gpio_signal signal) +{ + /* Debounce for 2 msec */ + hook_call_deferred(&hdmi_hpd_handler_data, (2 * MSEC)); +} + /***************************************************************************** * Fan */ @@ -285,7 +360,7 @@ DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = -1, }; @@ -318,6 +393,11 @@ int board_get_temp(int idx, int *temp_k) if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) return EC_ERROR_NOT_POWERED; + /* adc power not ready when transition to S5 */ + if (chipset_in_or_transitioning_to_state( + CHIPSET_STATE_SOFT_OFF)) + return EC_ERROR_NOT_POWERED; + channel = ADC_TEMP_SENSOR_SOC; break; case TEMP_SENSOR_5V_REGULATOR: @@ -325,6 +405,11 @@ int board_get_temp(int idx, int *temp_k) if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) return EC_ERROR_NOT_POWERED; + /* adc power not ready when transition to S5 */ + if (chipset_in_or_transitioning_to_state( + CHIPSET_STATE_SOFT_OFF)) + return EC_ERROR_NOT_POWERED; + channel = ADC_TEMP_SENSOR_5V_REGULATOR; break; default: @@ -393,53 +478,74 @@ const struct temp_sensor_t temp_sensors[] = { }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -const static struct ec_thermal_config thermal_thermistor_soc = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(73), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(39), - .temp_fan_max = C_TO_K(60), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_THERMISTOR_SOC \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(62), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(66), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(57), \ + }, \ + .temp_fan_off = C_TO_K(39), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_thermistor_soc = + THERMAL_THERMISTOR_SOC; -const static struct ec_thermal_config thermal_thermistor_charger = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(99), - [EC_TEMP_THRESH_HALT] = C_TO_K(99), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(98), - }, - .temp_fan_off = C_TO_K(98), - .temp_fan_max = C_TO_K(99), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_THERMISTOR_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(99), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(99), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(98), \ + }, \ + .temp_fan_off = C_TO_K(98), \ + .temp_fan_max = C_TO_K(99), \ + } +__maybe_unused static const struct ec_thermal_config thermal_thermistor_charger = + THERMAL_THERMISTOR_CHARGER; -const static struct ec_thermal_config thermal_thermistor_5v = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(60), - [EC_TEMP_THRESH_HALT] = C_TO_K(99), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(50), - }, - .temp_fan_off = C_TO_K(98), - .temp_fan_max = C_TO_K(99), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_THERMISTOR_5V \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(60), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(99), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(50), \ + }, \ + .temp_fan_off = C_TO_K(98), \ + .temp_fan_max = C_TO_K(99), \ + } +__maybe_unused static const struct ec_thermal_config thermal_thermistor_5v = + THERMAL_THERMISTOR_5V; -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(100), - [EC_TEMP_THRESH_HALT] = C_TO_K(105), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(99), - }, - .temp_fan_off = C_TO_K(105), - .temp_fan_max = C_TO_K(105), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(100), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(105), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(99), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -450,13 +556,13 @@ struct fan_step { }; static const struct fan_step fan_table0[] = { - {.on = 0, .off = 5, .rpm = 0}, - {.on = 29, .off = 5, .rpm = 3700}, - {.on = 38, .off = 19, .rpm = 4000}, - {.on = 48, .off = 33, .rpm = 4500}, - {.on = 62, .off = 43, .rpm = 4800}, - {.on = 76, .off = 52, .rpm = 5200}, - {.on = 100, .off = 67, .rpm = 6200}, + { .on = 0, .off = 5, .rpm = 0 }, + { .on = 29, .off = 5, .rpm = 3700 }, + { .on = 38, .off = 19, .rpm = 4000 }, + { .on = 48, .off = 33, .rpm = 4500 }, + { .on = 62, .off = 43, .rpm = 4800 }, + { .on = 76, .off = 52, .rpm = 5200 }, + { .on = 100, .off = 67, .rpm = 6200 }, }; /* All fan tables must have the same number of levels */ #define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) @@ -496,8 +602,7 @@ int fan_percent_to_rpm(int fan, int pct) previous_pct = pct; - if (fan_table[current_level].rpm != - fan_get_rpm_target(FAN_CH(fan))) + if (fan_table[current_level].rpm != fan_get_rpm_target(FAN_CH(fan))) cprints(CC_THERMAL, "Setting fan RPM to %d", fan_table[current_level].rpm); @@ -520,15 +625,14 @@ DECLARE_HOOK(HOOK_INIT, setup_fans, HOOK_PRIO_DEFAULT); * The connector has 24 pins total, and there is no pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {0, 5}, {1, 1}, {1, 0}, {0, 6}, {0, 7}, - {1, 4}, {1, 3}, {1, 6}, {1, 7}, {3, 1}, - {2, 0}, {1, 5}, {2, 6}, {2, 7}, {2, 1}, - {2, 4}, {2, 5}, {1, 2}, {2, 3}, {2, 2}, - {3, 0}, {-1, -1}, {-1, -1}, {-1, -1}, + { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, { 1, 4 }, + { 1, 3 }, { 1, 6 }, { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, + { 2, 6 }, { 2, 7 }, { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, + { 2, 3 }, { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); #endif /***************************************************************************** @@ -573,9 +677,8 @@ enum gpio_signal board_usbc_port_to_hpd_gpio(int port) * from USB-PD messages.. */ else if (ec_config_has_mst_hub_rtd2141b()) - return (board_ver >= 3) - ? GPIO_USB_C1_HPD_IN_DB_V1 - : GPIO_NO_HPD; + return (board_ver >= 3) ? GPIO_USB_C1_HPD_IN_DB_V1 : + GPIO_NO_HPD; /* USB-C1 OPT1 DB uses DP2_HPD. */ return GPIO_DP2_HPD; diff --git a/board/berknip/board.h b/board/berknip/board.h index d6e127ca3c..454432ba0a 100644 --- a/board/berknip/board.h +++ b/board/berknip/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,10 +10,9 @@ #define VARIANT_ZORK_TREMBYLE -#include #include "baseboard.h" -#define CONFIG_MKBP_USE_GPIO +#include #define RPM_DEVIATION 1 #define CONFIG_FAN_RPM_CUSTOM @@ -27,31 +26,32 @@ #define CONFIG_USB_MUX_PS8743 #define CONFIG_USBC_RETIMER_TUSB544 #define TUSB544_I2C_ADDR_FLAGS1 0x0F +#define CONFIG_TUSB544_EQ_BY_REGISTER #define CONFIG_POWER_SIGNAL_RUNTIME_CONFIG /* GPIO mapping from board specific name to EC common name. */ -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL -#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL -#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL -#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L -#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK -#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L -#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL -#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD -#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE #ifndef __ASSEMBLER__ @@ -77,11 +77,7 @@ enum mft_channel { MFT_CH_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_FAN, PWM_CH_COUNT }; enum temp_sensor_id { TEMP_SENSOR_CHARGER = 0, @@ -91,16 +87,11 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum usba_port { - USBA_PORT_A0 = 0, - USBA_PORT_A1, - USBA_PORT_COUNT -}; +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; /***************************************************************************** * CBI EC FW Configuration */ -#include "cbi_ec_fw_config.h" /** * BERKNIP_MB_USBAC @@ -147,50 +138,41 @@ enum ec_cfg_usb_db_type { BERKNIP_DB_T_OPT3_USBAC_HDMI_MSTHUB = 1, }; +#include "cbi_ec_fw_config.h" -#define HAS_USBC1_RETIMER_PS8743 \ - (BIT(BERKNIP_DB_T_OPT3_USBAC_HDMI_MSTHUB)) +#define HAS_USBC1_RETIMER_PS8743 (BIT(BERKNIP_DB_T_OPT3_USBAC_HDMI_MSTHUB)) static inline bool ec_config_has_usbc1_retimer_ps8743(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8743); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_PS8743); } -#define HAS_USBC1_RETIMER_TUSB544 \ - (BIT(BERKNIP_DB_T_OPT1_USBAC_HMDI)) +#define HAS_USBC1_RETIMER_TUSB544 (BIT(BERKNIP_DB_T_OPT1_USBAC_HMDI)) static inline bool ec_config_has_usbc1_retimer_tusb544(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_TUSB544); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_TUSB544); } -#define HAS_HDMI_RETIMER_PI3HDX1204 \ - (BIT(BERKNIP_DB_T_OPT1_USBAC_HMDI)) +#define HAS_HDMI_RETIMER_PI3HDX1204 (BIT(BERKNIP_DB_T_OPT1_USBAC_HMDI)) static inline bool ec_config_has_hdmi_retimer_pi3hdx1204(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_RETIMER_PI3HDX1204); + return !!(BIT(ec_config_get_usb_db()) & HAS_HDMI_RETIMER_PI3HDX1204); } -#define HAS_MST_HUB_RTD2141B \ - (BIT(BERKNIP_DB_T_OPT3_USBAC_HDMI_MSTHUB)) +#define HAS_MST_HUB_RTD2141B (BIT(BERKNIP_DB_T_OPT3_USBAC_HDMI_MSTHUB)) static inline bool ec_config_has_mst_hub_rtd2141b(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_MST_HUB_RTD2141B); + return !!(BIT(ec_config_get_usb_db()) & HAS_MST_HUB_RTD2141B); } -#define HAS_HDMI_CONN_HPD \ - (BIT(BERKNIP_DB_T_OPT1_USBAC_HMDI)) +#define HAS_HDMI_CONN_HPD (BIT(BERKNIP_DB_T_OPT1_USBAC_HMDI)) static inline bool ec_config_has_hdmi_conn_hpd(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_CONN_HPD); + return !!(BIT(ec_config_get_usb_db()) & HAS_HDMI_CONN_HPD); } enum gpio_signal board_usbc_port_to_hpd_gpio(int port); @@ -200,13 +182,6 @@ extern const struct usb_mux usbc1_tusb544; extern const struct usb_mux usbc1_ps8743; extern struct usb_mux usbc1_amd_fp5_usb_mux; -void hdmi_hpd_interrupt(enum ioex_signal signal); - -#ifdef CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; -#endif - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/berknip/build.mk b/board/berknip/build.mk index 1c0cbc4f63..45c71f962c 100644 --- a/board/berknip/build.mk +++ b/board/berknip/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/berknip/ec.tasklist b/board/berknip/ec.tasklist index 3a08ebc972..779bd4fdd6 100644 --- a/board/berknip/ec.tasklist +++ b/board/berknip/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/berknip/gpio.inc b/board/berknip/gpio.inc index e265101d2b..1bba6a3a69 100644 --- a/board/berknip/gpio.inc +++ b/board/berknip/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -36,6 +36,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_inter GPIO_INT(EC_WP_L, PIN(5, 0), GPIO_INT_BOTH, switch_interrupt) GPIO_INT(VOLDN_BTN_ODL, PIN(A, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) GPIO_INT(VOLUP_BTN_ODL, PIN(9, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(DP1_HPD_EC_IN, PIN(7, 5), GPIO_INT_BOTH, hdmi_hpd_interrupt) /* GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an interrupt handler. */ GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) @@ -60,7 +61,6 @@ GPIO(USB_C0_HPD, PIN(F, 5), GPIO_OUT_LOW) /* C0 DP Hotplug Detect */ GPIO(USB_C0_IN_HPD, PIN(7, 3), GPIO_OUT_LOW) /* C0 IN Hotplug Detect */ GPIO(EC_DP1_HPD, PIN(F, 4), GPIO_OUT_LOW) /* C1 DP Hotplug Detect */ GPIO(DP2_HPD, PIN(C, 1), GPIO_OUT_LOW) /* C1 DP Hotplug Detect */ -GPIO(DP1_HPD_EC_IN, PIN(7, 5), GPIO_INPUT) /* C1 IN Hotplug Detect */ GPIO(EC_H1_PACKET_MODE, PIN(8, 6), GPIO_OUT_LOW) /* H1 Packet Mode */ UNIMPLEMENTED(NO_HPD) diff --git a/board/berknip/led.c b/board/berknip/led.c index 2042186623..431d517572 100644 --- a/board/berknip/led.c +++ b/board/berknip/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,9 +9,9 @@ #include "chipset.h" #include "ec_commands.h" #include "gpio.h" +#include "hooks.h" #include "host_command.h" #include "led_common.h" -#include "hooks.h" #define BAT_LED_ON 0 #define BAT_LED_OFF 1 @@ -20,7 +20,9 @@ #define POWER_LED_OFF 1 #define LED_TICKS_PER_CYCLE 10 +#define LED_TICKS_PER_CYCLE_S3 35 #define LED_ON_TICKS 5 +#define POWER_LED_ON_S3_TICKS 5 const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, @@ -33,22 +35,19 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; -enum led_port { - RIGHT_PORT = 0, - LEFT_PORT -}; +enum led_port { RIGHT_PORT = 0, LEFT_PORT }; static void led_set_color_battery(int port, enum led_color color) { enum gpio_signal amber_led, white_led; amber_led = (port == RIGHT_PORT ? GPIO_LED_CHRG_L : - GPIO_C1_CHARGE_LED_AMBER_DB_L); + GPIO_C1_CHARGE_LED_AMBER_DB_L); white_led = (port == RIGHT_PORT ? GPIO_LED_FULL_L : - GPIO_C1_CHARGE_LED_WHITE_DB_L); + GPIO_C1_CHARGE_LED_WHITE_DB_L); switch (color) { case LED_WHITE: @@ -120,17 +119,16 @@ static void set_active_port_color(enum led_color color) if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) led_set_color_battery(RIGHT_PORT, - (port == RIGHT_PORT) ? color : LED_OFF); + (port == RIGHT_PORT) ? color : LED_OFF); if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) led_set_color_battery(LEFT_PORT, - (port == LEFT_PORT) ? color : LED_OFF); + (port == LEFT_PORT) ? color : LED_OFF); } static void led_set_battery(void) { static int battery_ticks; static int power_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; @@ -139,32 +137,39 @@ static void led_set_battery(void) * design, blinking both two side battery white LEDs to indicate * system suspend with non-charging state. */ - if (chipset_in_state(CHIPSET_STATE_SUSPEND | - CHIPSET_STATE_STANDBY) && - charge_get_state() != PWR_STATE_CHARGE) { - + if (chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_STANDBY) && + led_pwr_get_state() != LED_PWRS_CHARGE) { power_ticks++; - led_set_color_battery(RIGHT_PORT, power_ticks & 0x4 ? - LED_WHITE : LED_OFF); - led_set_color_battery(LEFT_PORT, power_ticks & 0x4 ? - LED_WHITE : LED_OFF); + led_set_color_battery(RIGHT_PORT, + power_ticks % LED_TICKS_PER_CYCLE_S3 < + POWER_LED_ON_S3_TICKS ? + LED_WHITE : + LED_OFF); + led_set_color_battery(LEFT_PORT, + power_ticks % LED_TICKS_PER_CYCLE_S3 < + POWER_LED_ON_S3_TICKS ? + LED_WHITE : + LED_OFF); return; } power_ticks = 0; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate when charging, even in suspend. */ set_active_port_color(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { if (charge_get_percent() < 10) - led_set_color_battery(RIGHT_PORT, - (battery_ticks % LED_TICKS_PER_CYCLE - < LED_ON_TICKS) ? LED_WHITE : LED_OFF); + led_set_color_battery( + RIGHT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); else led_set_color_battery(RIGHT_PORT, LED_OFF); } @@ -172,20 +177,21 @@ static void led_set_battery(void) if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) led_set_color_battery(LEFT_PORT, LED_OFF); break; - case PWR_STATE_ERROR: - set_active_port_color((battery_ticks & 0x2) ? - LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: set_active_port_color(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - set_active_port_color((battery_ticks % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_AMBER : LED_OFF); - else - set_active_port_color(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ diff --git a/board/berknip/vif_override.xml b/board/berknip/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/berknip/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/bland b/board/bland new file mode 120000 index 0000000000..7f4a914148 --- /dev/null +++ b/board/bland @@ -0,0 +1 @@ +hammer \ No newline at end of file diff --git a/board/blipper/battery.c b/board/blipper/battery.c new file mode 100644 index 0000000000..61ad95d4b7 --- /dev/null +++ b/board/blipper/battery.c @@ -0,0 +1,192 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all blipper battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* SMP L20M3PG0 Battery Information */ + [BATTERY_SMP1] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L20M3PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* SMP L20M3PG3 Battery Information */ + [BATTERY_SMP2] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L20M3PG3", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* LGC L20L3PG0 Battery Information */ + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "LGC", + .device_name = "L20L3PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 73, + }, + }, + + /* Sunwoda L20D3PG0 Battery Information */ + [BATTERY_SUNWODA] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "L20D3PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 205, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* Celxert L20C3PG0 Battery Information */ + [BATTERY_CELXPERT] = { + .fuel_gauge = { + .manuf_name = "Celxpert", + .device_name = "L20C3PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + .cfet_mask = 0x0008, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP1; diff --git a/board/blipper/board.c b/board/blipper/board.c new file mode 100644 index 0000000000..15a2d4b520 --- /dev/null +++ b/board/blipper/board.c @@ -0,0 +1,648 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Blipper board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "cros_board_info.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi260.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTF(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define INT_RECHECK_US 5000 + +__override struct keyboard_scan_config keyscan_config = { + .output_settle_us = 80, + .debounce_down_us = 30 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void hdmi_hpd_interrupt(enum gpio_signal s) +{ + gpio_set_level(GPIO_USB_C1_DP_HPD, !gpio_get_level(s)); +} + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, +}; + +static const struct ec_response_keybd_config blipper_keybd = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &blipper_keybd; +} + +/* USB-A charging control */ +const int usb_port_enable[USB_PORT_COUNT] = { GPIO_EN_USB_A0_VBUS }; + +static uint32_t board_id; + +/* Sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_lis2dwl_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* Lid accel private data */ +static struct stprivate_data g_lis2dwl_data; +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DWL, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2dwl_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, + .rot_standard_ref = &lid_lis2dwl_ref, + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DS3, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = NULL, /* identity matrix */ + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DS3, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = NULL, /* identity matrix */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, +}; + +static struct icm_drv_data_t g_icm42607_data; +const mat33_fp_t based_ref_icm42607 = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; +struct motion_sensor_t icm42607_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &based_ref_icm42607, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; +struct motion_sensor_t icm42607_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &based_ref_icm42607, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; + +static struct bmi_drv_data_t g_bmi220_data; +const mat33_fp_t based_ref_bmi220 = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; +struct motion_sensor_t bmi220_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI220, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi220_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &based_ref_bmi220, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; +struct motion_sensor_t bmi220_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI220, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi220_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &based_ref_bmi220, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void board_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + gpio_enable_interrupt(GPIO_HDMI_HPD_SUB_ODL); + + /* Set LEDs luminance */ + pwm_set_duty(PWM_CH_LED_RED, 70); + pwm_set_duty(PWM_CH_LED_GREEN, 70); + pwm_set_duty(PWM_CH_LED_WHITE, 70); + + /* Enable Base Accel interrupt for Beetley */ + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_PRESENT) + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + + /* Setting scan mask KSO11, KSO12, KSO13 and KSO14 */ + keyscan_config.actual_key_mask[11] = 0xfe; + keyscan_config.actual_key_mask[12] = 0xff; + keyscan_config.actual_key_mask[13] = 0xff; + keyscan_config.actual_key_mask[14] = 0xff; + + cbi_get_board_version(&board_id); + + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_ABSENT) { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* + * Base accel is not stuffed, don't allow + * line to float. + */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + + /* Disable Volume keys for blipper */ + button_disable_gpio(BUTTON_VOLUME_UP); + button_disable_gpio(BUTTON_VOLUME_DOWN); + gpio_set_flags(GPIO_VOLDN_BTN_ODL, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_VOLUP_BTN_ODL, GPIO_INPUT | GPIO_PULL_DOWN); + } else { + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_ICM42607) { + motion_sensors[BASE_ACCEL] = icm42607_base_accel; + motion_sensors[BASE_GYRO] = icm42607_base_gyro; + CPRINTF("BASE GYRO is ICM42607"); + } else if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BMI220) { + motion_sensors[BASE_ACCEL] = bmi220_base_accel; + motion_sensors[BASE_GYRO] = bmi220_base_gyro; + CPRINTF("BASE GYRO is BMI220"); + } else { + CPRINTF("BASE GYRO is LSM6DSM"); + } + } +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (get_cbi_ssfc_base_sensor()) { + case SSFC_SENSOR_ICM42607: + icm42607_interrupt(signal); + break; + case SSFC_SENSOR_BMI220: + bmi260_interrupt(signal); + break; + case SSFC_SENSOR_LSM6DSM: + default: + lsm6dsm_interrupt(signal); + break; + } +} + +void board_hibernate(void) +{ + /* + * Charger IC need to be put into their "low power mode" before + * entering the Z-state. + * + * b:186717219: In order to solve the power consumption problem of + * hibernate,HW solution is adopted after board id 3 to solve the + * problem that AC cannot wake up hibernate mode. + */ + if (board_id > 2) + raa489000_hibernate(0, true); + else + raa489000_hibernate(0, false); +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + return status; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + if (port != 0 && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + CPRINTUSB("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + tcpc_write(0, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(0, false); + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTUSB("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(0, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTUSB("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_RED] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_GREEN] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_WHITE] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Charge", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "5V_Inductor", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} diff --git a/board/blipper/board.h b/board/blipper/board.h new file mode 100644 index 0000000000..1a911da1df --- /dev/null +++ b/board/blipper/board.h @@ -0,0 +1,167 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Blipper board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 + +/* DAC for PSYS */ +#define CONFIG_DAC + +/* LED */ +#define CONFIG_LED_ONOFF_STATES + +/*SENSOR*/ +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_BMI220 + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_I2C_XFER_LARGE_TRANSFER + +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* ICM426XX Base accel/gyro */ +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* PWM */ +#define CONFIG_PWM + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux */ +#define CONFIG_USB_MUX_IT5205 + +/* KeyBoard */ +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_KEYPAD +#define CONFIG_KEYBOARD_STRICT_DEBOUNCE + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* Button Config*/ +#define CONFIG_BUTTONS_RUNTIME_CONFIG + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum pwm_channel { + PWM_CH_LED_RED, + PWM_CH_LED_GREEN, + PWM_CH_LED_WHITE, + PWM_CH_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_SMP1, + BATTERY_SMP2, + BATTERY_LGC, + BATTERY_SUNWODA, + BATTERY_CELXPERT, + BATTERY_TYPE_COUNT, +}; + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/blipper/build.mk b/board/blipper/build.mk new file mode 100644 index 0000000000..01b890bf29 --- /dev/null +++ b/board/blipper/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/blipper/cbi_ssfc.c b/board/blipper/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/blipper/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/blipper/cbi_ssfc.h b/board/blipper/cbi_ssfc.h new file mode 100644 index 0000000000..bc6bc92286 --- /dev/null +++ b/board/blipper/cbi_ssfc.h @@ -0,0 +1,60 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4, + SSFC_SENSOR_BMI220 = 5 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/blipper/ec.tasklist b/board/blipper/ec.tasklist new file mode 100644 index 0000000000..8ccdfc81b2 --- /dev/null +++ b/board/blipper/ec.tasklist @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/blipper/gpio.inc b/board/blipper/gpio.inc new file mode 100644 index 0000000000..215f31a281 --- /dev/null +++ b/board/blipper/gpio.inc @@ -0,0 +1,151 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(HDMI_HPD_SUB_ODL, PIN(E, 7), GPIO_INT_BOTH, hdmi_hpd_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Used by baseboard z-state enable, but not present on blipper */ +UNIMPLEMENTED(USB_C1_INT_ODL) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_A1_VBUS, PIN(E, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_LOW) + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc pins which will run to the I/O board */ + + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) + +/*TP*/ +GPIO(TP, PIN(C, 3), GPIO_INPUT | GPIO_HIGH) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOA0_NC, PIN(A, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOB5_NC, PIN(B, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC4_NC, PIN(C, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF0_NC, PIN(F, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF1_NC, PIN(F, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF4_NC, PIN(F, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH2_NC, PIN(H, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ1_NC, PIN(J, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ3_NC, PIN(J, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL0_NC, PIN(L, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL3_NC, PIN(L, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V SENSOR */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(2)), 0, MODULE_ADC, 0) /* ADC15: TEMP_SENSOR_3 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + +/* DAC */ +ALTERNATE(PIN_MASK(J, BIT(2)), 0, MODULE_DAC, 0) /* DAC2: EC_AP_PSYS */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(1) | BIT(2) | BIT(3)), 0, MODULE_PWM, 0) /* RED led, GREEN led, WHITE led */ diff --git a/board/blipper/led.c b/board/blipper/led.c new file mode 100644 index 0000000000..afba103db6 --- /dev/null +++ b/board/blipper/led.c @@ -0,0 +1,117 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Blipper specific PWM LED settings. + */ + +#include "common.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "pwm.h" + +#define LED_OFF_LVL 0 +#define LED_ON_LVL 1 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_RED: + pwm_enable(PWM_CH_LED_RED, LED_ON_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + pwm_enable(PWM_CH_LED_RED, LED_ON_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_ON_LVL); + break; + case EC_LED_COLOR_GREEN: + pwm_enable(PWM_CH_LED_RED, LED_OFF_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + pwm_enable(PWM_CH_LED_RED, LED_OFF_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_OFF_LVL); + break; + } +} + +__override void led_set_color_power(enum ec_led_colors color) +{ + if (color == EC_LED_COLOR_WHITE) + pwm_enable(PWM_CH_LED_WHITE, LED_ON_LVL); + else + pwm_enable(PWM_CH_LED_WHITE, LED_OFF_LVL); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_battery(EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } else { + return EC_ERROR_INVAL; + } + return EC_SUCCESS; +} diff --git a/board/blipper/usb_pd_policy.c b/board/blipper/usb_pd_policy.c new file mode 100644 index 0000000000..a7633b73ac --- /dev/null +++ b/board/blipper/usb_pd_policy.c @@ -0,0 +1,71 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + if (port != 0) + return; + + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port != 0) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} diff --git a/board/blipper/vif_override.xml b/board/blipper/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/blipper/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/bloog/battery.c b/board/bloog/battery.c index b8ff4b5823..af3282576a 100644 --- a/board/bloog/battery.c +++ b/board/bloog/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -33,7 +33,7 @@ */ const struct board_batt_params board_battery_info[] = { /* DynaPack Coslight BDAK126150-W0P0703HT attery Information */ - [BATTERY_DANAPACK_COS] = { + [BATTERY_DYNAPACK_COS] = { .fuel_gauge = { .manuf_name = "333-2C-DA-A", .ship_mode = { @@ -62,7 +62,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack ATL DynaPack DAK126150-W0G0703HT Battery Information */ - [BATTERY_DANAPACK_ATL] = { + [BATTERY_DYNAPACK_ATL] = { .fuel_gauge = { .manuf_name = "333-27-DA-A", .ship_mode = { @@ -91,7 +91,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack SDI DAK126150-W020703HT Battery Information */ - [BATTERY_DANAPACK_SDI] = { + [BATTERY_DYNAPACK_SDI] = { .fuel_gauge = { .manuf_name = "333-24-DA-A", .ship_mode = { @@ -292,7 +292,36 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 60, }, }, + + /* CosMX B00C4473A9D0002 Battery Information */ + [BATTERY_COS_2] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DANAPACK_COS; +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; diff --git a/board/bloog/board.c b/board/bloog/board.c index 2973b5c6dd..9250dfe299 100644 --- a/board/bloog/board.c +++ b/board/bloog/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Bloog/Blooguard board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery.h" #include "button.h" #include "charge_manager.h" @@ -34,20 +33,20 @@ #include "switch.h" #include "system.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) -#define USB_PD_PORT_ANX7447 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 static uint8_t sku_id; @@ -72,32 +71,32 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, /* Vbus C0 sensing (10x voltage divider). PPVAR_USB_C0_VBUS */ - [ADC_VBUS_C0] = { - "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C0] = { "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* Vbus C1 sensing (10x voltage divider). PPVAR_USB_C1_VBUS */ - [ADC_VBUS_C1] = { - "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C1] = { "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -107,23 +106,17 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t lid_a_cover_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t lid_a_cover_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t lid_b_cover_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t lid_b_cover_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct kionix_accel_data kx022_data; @@ -168,8 +161,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &base_standard_ref, @@ -200,8 +191,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -225,10 +214,10 @@ int board_is_convertible(void) * Bipship: 53, 54, 55, 56 * Unprovisioned: 255 */ - return sku_id == 33 || sku_id == 34 || sku_id == 35 || sku_id == 36 - || sku_id == 49 || sku_id == 50 || sku_id == 51 || sku_id == 52 - || sku_id == 53 || sku_id == 54 || sku_id == 55 || sku_id == 56 - || sku_id == 255; + return sku_id == 33 || sku_id == 34 || sku_id == 35 || sku_id == 36 || + sku_id == 49 || sku_id == 50 || sku_id == 51 || sku_id == 52 || + sku_id == 53 || sku_id == 54 || sku_id == 55 || sku_id == 56 || + sku_id == 255; } static void board_update_sensor_config_from_sku(void) @@ -239,8 +228,8 @@ static void board_update_sensor_config_from_sku(void) gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); /* Override sensor marix for Bipship. */ - if (sku_id == 53 || sku_id == 54 || sku_id == 55 - || sku_id == 56) + if (sku_id == 53 || sku_id == 54 || sku_id == 55 || + sku_id == 56) motion_sensors[LID_ACCEL].rot_standard_ref = &lid_b_cover_ref; } else { @@ -270,19 +259,18 @@ void board_hibernate_late(void) const uint32_t hibernate_pins[][2] = { /* Turn off LEDs before going to hibernate */ - {GPIO_LED_WHITE_C0_L, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_LED_AMBER_C0_L, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_LED_WHITE_C1_L, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_LED_AMBER_C1_L, GPIO_INPUT | GPIO_PULL_UP}, + { GPIO_LED_WHITE_C0_L, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_LED_AMBER_C0_L, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_LED_WHITE_C1_L, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_LED_AMBER_C1_L, GPIO_INPUT | GPIO_PULL_UP }, }; for (i = 0; i < ARRAY_SIZE(hibernate_pins); ++i) gpio_set_flags(hibernate_pins[i][0], hibernate_pins[i][1]); } -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -295,7 +283,6 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif #ifdef CONFIG_KEYBOARD_FACTORY_TEST /* @@ -304,15 +291,15 @@ void lid_angle_peripheral_enable(int enable) * The connector has 24 pins total, and there is no pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {1, 4}, {1, 3}, {1, 6}, {1, 7}, - {3, 1}, {2, 0}, {1, 5}, {2, 6}, {2, 7}, - {2, 1}, {2, 4}, {2, 5}, {1, 2}, {2, 3}, - {2, 2}, {3, 0}, {-1, -1}, {-1, -1}, {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); #endif void board_overcurrent_event(int port, int is_overcurrented) @@ -330,9 +317,8 @@ __override uint32_t board_override_feature_flags0(uint32_t flags0) /* * Remove keyboard backlight feature for devices that don't support it. */ - if (sku_id == 33 || sku_id == 36 || sku_id == 51 || - sku_id == 52 || sku_id == 53 || sku_id == 55 || - sku_id == 66 || sku_id == 68) + if (sku_id == 33 || sku_id == 36 || sku_id == 51 || sku_id == 52 || + sku_id == 53 || sku_id == 55 || sku_id == 66 || sku_id == 68) return (flags0 & ~EC_FEATURE_MASK_0(EC_FEATURE_PWM_KEYB)); else return flags0; diff --git a/board/bloog/board.h b/board/bloog/board.h index c472543589..38e8484df2 100644 --- a/board/bloog/board.h +++ b/board/bloog/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,6 +13,8 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + #define CONFIG_VOLUME_BUTTONS #define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL #define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL @@ -25,8 +27,8 @@ #define CONFIG_LED_COMMON /* Sensors */ -#define CONFIG_ACCEL_KX022 /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK (1 << LID_ACCEL) @@ -57,10 +59,10 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ - ADC_VBUS_C0, /* ADC9 */ - ADC_VBUS_C1, /* ADC4 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_VBUS_C0, /* ADC9 */ + ADC_VBUS_C1, /* ADC4 */ ADC_CH_COUNT }; @@ -71,37 +73,25 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; enum battery_type { - BATTERY_DANAPACK_COS, - BATTERY_DANAPACK_ATL, - BATTERY_DANAPACK_SDI, + BATTERY_DYNAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_DYNAPACK_SDI, BATTERY_SAMSUNG_SDI, BATTERY_SIMPLO_COS, BATTERY_SIMPLO_ATL, BATTERY_SIMPLO_HIGHPOWER, BATTERY_LGC, BATTERY_COS, + BATTERY_COS_2, BATTERY_TYPE_COUNT, }; -#ifdef CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; -#endif - int board_is_convertible(void); #endif /* !__ASSEMBLER__ */ diff --git a/board/bloog/build.mk b/board/bloog/build.mk index 137e208b53..fee77e38b5 100644 --- a/board/bloog/build.mk +++ b/board/bloog/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/bloog/ec.tasklist b/board/bloog/ec.tasklist index 6eac78a042..6c56976091 100644 --- a/board/bloog/ec.tasklist +++ b/board/bloog/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/bloog/gpio.inc b/board/bloog/gpio.inc index 3ee2f88eb1..f07b380974 100644 --- a/board/bloog/gpio.inc +++ b/board/bloog/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/bloog/led.c b/board/bloog/led.c index ba1a865890..914e286741 100644 --- a/board/bloog/led.c +++ b/board/bloog/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,9 +11,9 @@ #include "chipset.h" #include "ec_commands.h" #include "gpio.h" +#include "hooks.h" #include "host_command.h" #include "led_common.h" -#include "hooks.h" #define BAT_LED_ON 0 #define BAT_LED_OFF 1 @@ -24,11 +24,9 @@ #define LED_TICKS_PER_CYCLE 10 #define LED_ON_TICKS 5 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_LEFT_LED, - EC_LED_ID_RIGHT_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -36,18 +34,18 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static void led_set_color_battery(int port, enum led_color color) { gpio_set_level(port ? GPIO_LED_AMBER_C1_L : GPIO_LED_AMBER_C0_L, - (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); gpio_set_level(port ? GPIO_LED_WHITE_C1_L : GPIO_LED_WHITE_C0_L, - (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); } -void led_set_color_power(enum ec_led_colors color) +void led_set_color_power(enum led_color color) { switch (color) { case LED_OFF: @@ -101,7 +99,7 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) break; case EC_LED_ID_POWER_LED: if (brightness[EC_LED_COLOR_WHITE] != 0) - led_set_color_power(EC_LED_COLOR_WHITE); + led_set_color_power(LED_WHITE); else led_set_color_power(LED_OFF); break; @@ -130,7 +128,6 @@ static void led_set_battery(void) { static int battery_ticks; static int power_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; @@ -141,32 +138,34 @@ static void led_set_battery(void) */ if (!board_is_convertible()) { if (chipset_in_state(CHIPSET_STATE_SUSPEND | - CHIPSET_STATE_STANDBY) && - charge_get_state() != PWR_STATE_CHARGE) { - + CHIPSET_STATE_STANDBY) && + led_pwr_get_state() != LED_PWRS_CHARGE) { power_ticks++; - led_set_color_battery(0, power_ticks & 0x4 ? - LED_WHITE : LED_OFF); - led_set_color_battery(1, power_ticks & 0x4 ? - LED_WHITE : LED_OFF); + led_set_color_battery(0, power_ticks & 0x4 ? LED_WHITE : + LED_OFF); + led_set_color_battery(1, power_ticks & 0x4 ? LED_WHITE : + LED_OFF); return; } } power_ticks = 0; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate when charging, even in suspend. */ set_active_port_color(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { if (charge_get_percent() < 10) - led_set_color_battery(1, (battery_ticks % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_WHITE : LED_OFF); + led_set_color_battery( + 1, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); else led_set_color_battery(1, LED_OFF); } @@ -174,20 +173,21 @@ static void led_set_battery(void) if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) led_set_color_battery(0, LED_OFF); break; - case PWR_STATE_ERROR: - set_active_port_color((battery_ticks & 0x2) ? - LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: set_active_port_color(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - set_active_port_color((battery_ticks % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_AMBER : LED_OFF); - else - set_active_port_color(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ @@ -205,9 +205,10 @@ static void led_set_power(void) led_set_color_power(LED_WHITE); else if (chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_STANDBY)) - led_set_color_power((power_tick % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_WHITE : LED_OFF); + led_set_color_power( + (power_tick % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); else led_set_color_power(LED_OFF); } diff --git a/board/bloog/vif_override.xml b/board/bloog/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/bloog/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/bobba/battery.c b/board/bobba/battery.c index e53e839a68..ab77c44062 100644 --- a/board/bobba/battery.c +++ b/board/bobba/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -277,6 +277,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x43, .reg_mask = 0x0001, .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0, }, }, .batt_info = { diff --git a/board/bobba/board.c b/board/bobba/board.c index c0902ec9ee..64e713a55e 100644 --- a/board/bobba/board.c +++ b/board/bobba/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,15 +6,17 @@ /* Bobba board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery.h" #include "button.h" +#include "cbi_ssfc.h" #include "charge_manager.h" #include "charge_state.h" #include "common.h" #include "cros_board_info.h" #include "driver/accel_kionix.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/charger/bd9995x.h" #include "driver/ppc/nx20p348x.h" #include "driver/ppc/syv682x.h" @@ -38,19 +40,19 @@ #include "switch.h" #include "system.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_charge.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define USB_PD_PORT_ANX7447 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 static uint8_t sku_id; @@ -60,17 +62,16 @@ static uint8_t sku_id; * that we don't have pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {-1, -1}, {-1, -1}, {1, 4}, {1, 3}, - {-1, -1}, {1, 6}, {1, 7}, {3, 1}, {2, 0}, - {1, 5}, {2, 6}, {2, 7}, {2, 1}, {2, 4}, - {2, 5}, {1, 2}, {2, 3}, {2, 2}, {3, 0}, - {-1, -1}, {0, 4}, {-1, -1}, {8, 2}, {-1, -1}, - {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); /* Check PPC ID Pin and Board ver to decide which one ppc is used. */ static bool support_syv_ppc(void) @@ -113,31 +114,31 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, /* Vbus sensing (1/10 voltage divider). */ - [ADC_VBUS_C0] = { - "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, - [ADC_VBUS_C1] = { - "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C0] = { "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + [ADC_VBUS_C1] = { "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -147,11 +148,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* * Sparky360 SKU ID 26 has AR Cam, and move base accel/gryo to AR Cam board. @@ -166,14 +169,15 @@ const mat33_fp_t base_standard_ref = { * |0 0.27564 0.96126| */ const mat33_fp_t base_ar_cam_ref = { - { 0, FLOAT_TO_FP(-0.96126), FLOAT_TO_FP(0.27564)}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(0.27564), FLOAT_TO_FP(0.96126)} + { 0, FLOAT_TO_FP(-0.96126), FLOAT_TO_FP(0.27564) }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(0.27564), FLOAT_TO_FP(0.96126) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; /* Drivers */ struct motion_sensor_t motion_sensors[] = { @@ -262,15 +266,60 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_icm_ref, + .default_range = 4, /* g */ + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + static int board_is_convertible(void) { /* * SKU ID of Bobba360, Sparky360, & unprovisioned: 9, 10, 11, 12, * 25, 26, 27, 255 */ - return sku_id == 9 || sku_id == 10 || sku_id == 11 || sku_id == 12 - || sku_id == 25 || sku_id == 26 || sku_id == 27 - || sku_id == 255; + return sku_id == 9 || sku_id == 10 || sku_id == 11 || sku_id == 12 || + sku_id == 25 || sku_id == 26 || sku_id == 27 || sku_id == 255; } static int board_with_ar_cam(void) @@ -278,10 +327,17 @@ static int board_with_ar_cam(void) /* SKU ID of Sparky360 with AR Cam: 26 */ return sku_id == 26; } - +static int base_gyro_config; static void board_update_sensor_config_from_sku(void) { if (board_is_convertible()) { + base_gyro_config = get_cbi_ssfc_sensor(); + if (base_gyro_config == SSFC_SENSOR_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE GYRO is ICM426XX"); + } else + ccprints("BASE GYRO is BMI160"); motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Enable Base Accel interrupt */ gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); @@ -306,6 +362,19 @@ static void board_update_sensor_config_from_sku(void) } } +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_gyro_config) { + case SSFC_SENSOR_ICM426XX: + icm426xx_interrupt(signal); + break; + case SSFC_SENSOR_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + static int board_has_keypad(void) { return sku_id == 41 || sku_id == 42 || sku_id == 43 || sku_id == 44; @@ -332,8 +401,9 @@ static void board_usb_charge_mode_init(void) int i; /* - * Only overriding the USB_DISALLOW_SUSPEND_CHARGE in RO is enough because - * USB_SYSJUMP_TAG preserves the settings to RW. And we should honor to it. + * Only overriding the USB_DISALLOW_SUSPEND_CHARGE in RO is enough + * because USB_SYSJUMP_TAG preserves the settings to RW. And we should + * honor to it. */ if (system_jumped_late()) return; @@ -350,7 +420,7 @@ static void board_usb_charge_mode_init(void) */ for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++) usb_charge_set_mode(i, CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE, - USB_DISALLOW_SUSPEND_CHARGE); + USB_DISALLOW_SUSPEND_CHARGE); } /* * usb_charge_init() is hooked in HOOK_PRIO_DEFAULT and set inhibit_charge to @@ -387,15 +457,15 @@ __override uint32_t board_override_feature_flags0(uint32_t flags0) } static const struct ppc_config_t ppc_syv682x_port0 = { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, }; static const struct ppc_config_t ppc_syv682x_port1 = { - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, }; static void board_setup_ppc(void) @@ -403,11 +473,9 @@ static void board_setup_ppc(void) if (!support_syv_ppc()) return; - memcpy(&ppc_chips[USB_PD_PORT_TCPC_0], - &ppc_syv682x_port0, + memcpy(&ppc_chips[USB_PD_PORT_TCPC_0], &ppc_syv682x_port0, sizeof(struct ppc_config_t)); - memcpy(&ppc_chips[USB_PD_PORT_TCPC_1], - &ppc_syv682x_port1, + memcpy(&ppc_chips[USB_PD_PORT_TCPC_1], &ppc_syv682x_port1, sizeof(struct ppc_config_t)); gpio_set_flags(GPIO_USB_PD_C0_INT_ODL, GPIO_INT_BOTH); @@ -415,23 +483,22 @@ static void board_setup_ppc(void) } DECLARE_HOOK(HOOK_INIT, board_setup_ppc, HOOK_PRIO_INIT_I2C + 2); -void board_hibernate_late(void) { - +void board_hibernate_late(void) +{ int i; const uint32_t hibernate_pins[][2] = { /* Turn off LEDs before going to hibernate */ - {GPIO_BAT_LED_BLUE_L, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_BAT_LED_ORANGE_L, GPIO_INPUT | GPIO_PULL_UP}, + { GPIO_BAT_LED_BLUE_L, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_BAT_LED_ORANGE_L, GPIO_INPUT | GPIO_PULL_UP }, }; for (i = 0; i < ARRAY_SIZE(hibernate_pins); ++i) gpio_set_flags(hibernate_pins[i][0], hibernate_pins[i][1]); } -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -443,7 +510,6 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif void board_overcurrent_event(int port, int is_overcurrented) { @@ -455,7 +521,6 @@ void board_overcurrent_event(int port, int is_overcurrented) gpio_set_level(GPIO_USB_C_OC, !is_overcurrented); } - int ppc_get_alert_status(int port) { if (port == 0) diff --git a/board/bobba/board.h b/board/bobba/board.h index a26e047d76..2a1be082e8 100644 --- a/board/bobba/board.h +++ b/board/bobba/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,12 +13,22 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + /* I2C bus configuraiton */ -#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_ACCEL I2C_PORT_SENSOR /* EC console commands */ -#define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_MFALLOW + +/* Reduce flash space usage */ +#define CONFIG_DEBUG_ASSERT_BRIEF +#define CONFIG_USB_PD_DEBUG_LEVEL 2 +#undef CONFIG_CMD_ADC +#undef CONFIG_CMD_BATTFAKE +#undef CONFIG_CMD_CBI #define CONFIG_LED_COMMON @@ -30,9 +40,10 @@ #define CONFIG_USB_PD_RESET_MIN_BATT_SOC 2 /* Sensors */ -#define CONFIG_ACCEL_KX022 /* Lid accel */ -#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_SYNC /* Camera VSYNC */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel main source*/ +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel second source*/ +#define CONFIG_SYNC /* Camera VSYNC */ #define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT /* Sensors without hardware FIFO are in forced mode */ @@ -41,9 +52,10 @@ /* Motion Sense Task Events */ #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE @@ -71,22 +83,29 @@ #define CONFIG_USBC_PPC_DEDICATED_INT #undef CONFIG_SYV682X_HV_ILIM #define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 +/* SYV682 isn't connected to CC, so TCPC must provide VCONN */ +#define CONFIG_USBC_PPC_SYV682X_NO_CC + +/* + * SMP battery sleep mode time is 5 second. + * Change max sleep time from once/min to once/4sec to prevent + * battery entering sleeping mode. See b/226259582. + */ +#define CHARGE_MAX_SLEEP_USEC (4 * SECOND) #ifndef __ASSEMBLER__ /* support factory keyboard test */ #define CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; #include "gpio_signal.h" #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ - ADC_VBUS_C0, /* ADC9 */ - ADC_VBUS_C1, /* ADC4 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_VBUS_C0, /* ADC9 */ + ADC_VBUS_C1, /* ADC4 */ ADC_CH_COUNT }; @@ -97,19 +116,10 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - VSYNC, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, VSYNC, SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { @@ -127,6 +137,8 @@ enum battery_type { BATTERY_TYPE_COUNT, }; +void motion_interrupt(enum gpio_signal signal); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/bobba/build.mk b/board/bobba/build.mk index 3d04b75731..998a65a3de 100644 --- a/board/bobba/build.mk +++ b/board/bobba/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/bobba/ec.tasklist b/board/bobba/ec.tasklist index d98db145e7..977b8b01be 100644 --- a/board/bobba/ec.tasklist +++ b/board/bobba/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/bobba/gpio.inc b/board/bobba/gpio.inc index cc69cc2618..f57ea6bf12 100644 --- a/board/bobba/gpio.inc +++ b/board/bobba/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -37,7 +37,7 @@ GPIO_INT(TABLET_MODE_L, PIN(8, 6), GPIO_INT_BOTH, gmr_tablet_switch_isr) GPIO_INT(EC_VOLUP_BTN_ODL, PIN(7, 5), GPIO_INT_BOTH, button_interrupt) GPIO_INT(EC_VOLDN_BTN_ODL, PIN(4, 0), GPIO_INT_BOTH, button_interrupt) -GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) GPIO_INT(WFCAM_VSYNC, PIN(0, 3), GPIO_INT_RISING , sync_interrupt) GPIO(LID_ACCEL_INT_L, PIN(5, 0), GPIO_INPUT | GPIO_SEL_1P8V) diff --git a/board/bobba/led.c b/board/bobba/led.c index 6c5ae18272..54227ed107 100644 --- a/board/bobba/led.c +++ b/board/bobba/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,32 +10,39 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1 = 0; +__override const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* Bobba: Note there is only LED for charge / power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_BLUE: @@ -70,4 +77,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/bobba/vif_override.xml b/board/bobba/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/bobba/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/boldar/battery.c b/board/boldar/battery.c index 9b356a8efd..2b2a9f4842 100644 --- a/board/boldar/battery.c +++ b/board/boldar/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -62,6 +62,34 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 75, }, }, + /* LGC AP18C8K Battery Information */ + [BATTERY_LGC_AP18C8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G020", + .device_name = "AP18C8K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); diff --git a/board/boldar/board.c b/board/boldar/board.c index 1993b241fb..3972c6746a 100644 --- a/board/boldar/board.c +++ b/board/boldar/board.c @@ -1,21 +1,20 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "common.h" #include "accelgyro.h" +#include "button.h" #include "cbi_ec_fw_config.h" +#include "common.h" #include "driver/accel_bma2x2.h" #include "driver/accelgyro_bmi260.h" #include "driver/als_tcs3400.h" #include "driver/bc12/pi3usb9201.h" #include "driver/ppc/sn5s330.h" #include "driver/ppc/syv682x.h" -#include "driver/retimer/bb_retimer.h" +#include "driver/retimer/bb_retimer_public.h" #include "driver/sync.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/rt1715.h" @@ -35,8 +34,8 @@ #include "pwm_chip.h" #include "switch.h" #include "system.h" -#include "task.h" #include "tablet_mode.h" +#include "task.h" #include "throttle_ap.h" #include "uart.h" #include "usb_mux.h" @@ -46,12 +45,13 @@ #include "usbc_ppc.h" #include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Increase from 50 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* Other values should be the same as the default configuration. */ @@ -82,68 +82,21 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - if (port == USBC_PORT_C1) { - if (usb_db == DB_USB4_GEN2) { - /* - * Older boards violate 205mm trace length prior - * to connection to the re-timer and only support up - * to GEN2 speeds. - */ - return TBT_SS_U32_GEN1_GEN2; - } else if (usb_db == DB_USB4_GEN3) { - return TBT_SS_TBT_GEN3; - } - } - - /* - * Thunderbolt-compatible mode not supported - * - * TODO (b/147726366): All the USB-C ports need to support same speed. - * Need to fix once USB-C feature set is known for Volteer. - */ - return TBT_SS_RES_0; -} - -__override bool board_is_tbt_usb4_port(int port) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - /* - * Volteer reference design only supports TBT & USB4 on port 1 - * if the USB4 DB is present. - * - * TODO (b/147732807): All the USB-C ports need to support same - * features. Need to fix once USB-C feature set is known for Volteer. - */ - return ((port == USBC_PORT_C1) - && ((usb_db == DB_USB4_GEN2) || (usb_db == DB_USB4_GEN3))); -} - /******************************************************************************/ /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; -/* - * Fan specs from datasheet: - * Max speed 5900 rpm (+/- 7%), minimum duty cycle 30%. - * Minimum speed not specified by RPM. Set minimum RPM to max speed (with - * margin) x 30%. - * 5900 x 1.07 x 0.30 = 1894, round up to 1900 - */ +/* Default */ const struct fan_rpm fan_rpm_0 = { - .rpm_min = 1900, - .rpm_start = 1900, - .rpm_max = 5900, + .rpm_min = 3000, + .rpm_start = 3000, + .rpm_max = 10000, }; const struct fan_t fans[FAN_CH_COUNT] = { @@ -157,51 +110,50 @@ const struct fan_t fans[FAN_CH_COUNT] = { /* EC thermal management configuration */ /* - * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at - * 130 C. However, sensor is located next to DDR, so we need to use the lower - * DDR temperature limit (85 C) + * TODO(b/202062363): Remove when clang is fixed. */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(15), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; /* * Inductor limits - used for both charger and PP3300 regulator * * Need to use the lower of the charger IC, PP3300 regulator, and the inductors - * - * Charger max recommended temperature 100C, max absolute temperature 125C - * PP3300 regulator: operating range -40 C to 145 C - * - * Inductors: limit of 125c - * PCB: limit is 80c */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(15), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -319,11 +271,10 @@ static const struct tcpc_config_t tcpc_config_p1_usb3 = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .flags = TCPC_FLAGS_TCPCI_REV2_0 | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, .drv = &ps8xxx_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), }; /* @@ -331,24 +282,33 @@ static const struct tcpc_config_t tcpc_config_p1_usb3 = { * virtual_usb_mux_driver so the AP gets notified of mux changes and updates * the TCSS configuration on state changes. */ -static const struct usb_mux usbc1_usb3_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .next_mux = NULL, +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, }; -static const struct usb_mux mux_config_p1_usb3_active = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb3_db_retimer, +static const struct usb_mux_chain mux_config_p1_usb3_active = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, }; -static const struct usb_mux mux_config_p1_usb3_passive = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, +static const struct usb_mux_chain mux_config_p1_usb3_passive = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }; /******************************************************************************/ @@ -358,16 +318,13 @@ const int usb_port_enable[USB_PORT_COUNT] = { GPIO_EN_PP5000_USBA, }; -static enum gpio_signal ps8xxx_rst_odl = GPIO_USB_C1_RT_RST_ODL; - static void ps8815_reset(void) { int val; - gpio_set_level(ps8xxx_rst_odl, 0); - msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, - PS8815_PWR_H_RST_H_DELAY_MS)); - gpio_set_level(ps8xxx_rst_odl, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 0); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 1); msleep(PS8815_FW_INIT_DELAY_MS); /* @@ -377,16 +334,16 @@ static void ps8815_reset(void) CPRINTS("%s: patching ps8815 registers", __func__); - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) CPRINTS("ps8815: reg 0x0f was %02x", val); - if (i2c_write8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, 0x31) == EC_SUCCESS) + if (i2c_write8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) CPRINTS("ps8815: reg 0x0f set to 0x31"); - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) CPRINTS("ps8815: reg 0x0f now %02x", val); } @@ -398,7 +355,9 @@ void board_reset_pd_mcu(void) /* Daughterboard specific reset for port 1 */ if (usb_db == DB_USB3_ACTIVE) { ps8815_reset(); - usb_mux_hpd_update(USBC_PORT_C1, 0, 0); + usb_mux_hpd_update(USBC_PORT_C1, + USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } } @@ -458,16 +417,6 @@ __override void board_cbi_init(void) { enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - /* Reconfigure Volteer GPIOs based on the board ID */ - if (get_board_id() == 0) { - CPRINTS("Configuring GPIOs for board ID 0"); - CPRINTS("VOLUME_UP button disabled"); - - /* Reassign USB_C1_RT_RST_ODL */ - bb_controls[USBC_PORT_C1].retimer_rst_gpio = - GPIO_USB_C1_RT_RST_ODL_BOARDID_0; - ps8xxx_rst_odl = GPIO_USB_C1_RT_RST_ODL_BOARDID_0; - } config_port_discrete_tcpc(0); switch (usb_db) { case DB_USB_ABSENT: @@ -526,6 +475,7 @@ void ppc_interrupt(enum gpio_signal signal) break; case GPIO_USB_C1_PPC_INT_ODL: syv682x_interrupt(USBC_PORT_C1); + break; default: break; } @@ -555,7 +505,6 @@ struct tcpc_config_t tcpc_config[] = { .addr_flags = TUSB422_I2C_ADDR_FLAGS, }, .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), }, [USBC_PORT_C1] = { .bus_type = EC_BUS_TYPE_I2C, @@ -564,7 +513,6 @@ struct tcpc_config_t tcpc_config[] = { .addr_flags = TUSB422_I2C_ADDR_FLAGS, }, .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), }, }; BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); @@ -572,30 +520,51 @@ BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); /******************************************************************************/ /* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, +struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }; -struct usb_mux usb_muxes[] = { + +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_1_MIX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, }, [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_1_MIX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); struct bb_usb_control bb_controls[] = { [USBC_PORT_C0] = { - /* USB-C port 0 doesn't have a retimer */ + .usb_ls_en_gpio = GPIO_USB_C0_LS_EN, + .retimer_rst_gpio = GPIO_USB_C0_RT_RST_ODL, }, [USBC_PORT_C1] = { .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, diff --git a/board/boldar/board.h b/board/boldar/board.h index 64efbf82af..f2a76dab82 100644 --- a/board/boldar/board.h +++ b/board/boldar/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,28 +11,22 @@ /* Baseboard features */ #include "baseboard.h" -#ifdef BOARD_VOLTEER_TCPMV1 -/* Disable TCPMv2 configuration options */ -#undef CONFIG_USB_PD_TCPMV2 - -/* Enable the required TCPMv1 options */ -#define CONFIG_USB_PD_TCPMV1 +/* Optional features */ /* - * Because the TPCMv1 stack has considerably smaller flash footprint, disable - * the CONFIG_CHIP_INIT_ROM_REGION for testing of the init_rom API and the - * BMI260 driver. + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. */ #undef CONFIG_CHIP_INIT_ROM_REGION -#endif -/* Optional features */ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ #define CONFIG_VBOOT_EFS2 #define CONFIG_POWER_BUTTON +#define CONFIG_HOST_INTERFACE_ESPI_RESET_SLP_SX_VW_ON_ESPI_RST + #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -47,29 +41,28 @@ /* Keyboard features */ /* Sensors */ -/* BMA253 accelerometer in base */ -#define CONFIG_ACCEL_BMA255 +/* LIS2DH12 Lid accel */ +#define CONFIG_ACCEL_LIS2DH /* BMI260 accel/gyro in base */ #define CONFIG_ACCELGYRO_BMI260 #define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -/* TCS3400 ALS */ +/* TCS3400 ALS/RGB */ #define CONFIG_ALS -#define ALS_COUNT 1 +#define ALS_COUNT 1 #define CONFIG_ALS_TCS3400 #define CONFIG_ALS_TCS3400_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) /* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL /* USB Type C and USB PD defines */ /* @@ -79,47 +72,36 @@ */ #define CONFIG_USB_PID 0x503E -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 /* TODO: b/144165680 - measure and check these values on Volteer */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ /* * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C * cables only support up to 60W. */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Enabling Thunderbolt-compatible mode */ #define CONFIG_USB_PD_TBT_COMPAT_MODE /* Enabling USB4 mode */ #define CONFIG_USB_PD_USB4 -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x37 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 /* USB Type A Features */ -#define USB_PORT_COUNT 1 +#define USB_PORT_COUNT 1 #define CONFIG_USB_PORT_POWER_DUMB /* USBC PPC*/ -#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ +#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ /* BC 1.2 */ @@ -128,8 +110,8 @@ /* Fan features */ /* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 /* * Macros for GPIO signals used in common code that don't match the @@ -137,46 +119,43 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL /* I2C Bus Configuration */ #define CONFIG_I2C -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM - -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER #ifndef __ASSEMBLER__ @@ -185,6 +164,7 @@ enum battery_type { BATTERY_LGC011, + BATTERY_LGC_AP18C8K, BATTERY_TYPE_COUNT, }; @@ -207,11 +187,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; void board_reset_pd_mcu(void); diff --git a/board/boldar/build.mk b/board/boldar/build.mk index b78172d3cf..c994631759 100644 --- a/board/boldar/build.mk +++ b/board/boldar/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,7 +8,7 @@ CHIP:=npcx CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc +CHIP_VARIANT:=npcx7m7fc BASEBOARD:=volteer board-y=board.o diff --git a/board/boldar/ec.tasklist b/board/boldar/ec.tasklist index 292de51cdb..c29125d517 100644 --- a/board/boldar/ec.tasklist +++ b/board/boldar/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,6 +16,7 @@ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/boldar/gpio.inc b/board/boldar/gpio.inc index d0055671ca..f06541ebbb 100644 --- a/board/boldar/gpio.inc +++ b/board/boldar/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -84,21 +84,16 @@ GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) /* USB and USBC Signals */ GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ - -/* - * USB_C1 moved from GPIO32 to GPIO83 on boards with board ID >=1. - * GPIO83/EN_PP1800_A is DNS on board ID 0 and GPIO32 is N/C on board ID >=1 - * so it's safe to define GPIOs compatible with both designs. - * TODO (b/149858568): remove board ID=0 support. - */ -GPIO(USB_C1_RT_RST_ODL_BOARDID_0, PIN(3, 2), GPIO_ODR_LOW) /* USB_C1 Reset on boards without board ID */ -GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset on boards board ID >=1 */ -GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) -GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) +GPIO(USB_C0_RT_RST_ODL, PIN(4, 1), GPIO_ODR_LOW) /* RST to Burnside bridge */ +GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) +GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) /* There is currently no need to service this interrupt. */ -GPIO(USB_C1_RT_INT_ODL, PIN(F, 3), GPIO_INPUT) +GPIO(USB_C0_RT_INT_ODL, PIN(F, 2), GPIO_INPUT) +GPIO(USB_C1_RT_INT_ODL, PIN(F, 3), GPIO_INPUT) /* Don't have a load switch for retimer */ +UNIMPLEMENTED(USB_C0_LS_EN) UNIMPLEMENTED(USB_C1_LS_EN) /* Misc Signals */ @@ -113,11 +108,8 @@ GPIO(M2_SSD_PLA, PIN(7, 0), GPIO_INPUT) /* SSD power-loss acknowledgment */ GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ GPIO(EC_SLP_S0IX, PIN(7, 2), GPIO_INPUT | GPIO_PULL_UP) -/* Unused signals */ -GPIO(UNUSED_GPIO41, PIN(4, 1), GPIO_INPUT | GPIO_PULL_UP) -GPIO(UNUSED_GPIOF2, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) -GPIO(UNUSED_GPIO96, PIN(9, 6), GPIO_INPUT | GPIO_PULL_UP) -GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(CATERR_L, PIN(3, 4), GPIO_INPUT) /* Catastrophic error */ +GPIO(EC_ESPI_ALERT_L, PIN(5, 7), GPIO_INPUT | GPIO_SEL_1P8V) /* * eDP backlight - both PCH and EC have enable pins that must be high @@ -126,6 +118,9 @@ GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) */ GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) +/* Unused signals */ +GPIO(UNUSED_GPIO96, PIN(9, 6), GPIO_INPUT | GPIO_PULL_UP) + /* I2C pins - Alternate function below configures I2C module on these pins */ GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) @@ -182,3 +177,6 @@ ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = GPIO01 = H1_EC_PWR_BTN_ODL GPIO02 = EC_RST_ODL */ +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ diff --git a/board/boldar/led.c b/board/boldar/led.c index 4486bcb912..d2425d13b6 100644 --- a/board/boldar/led.c +++ b/board/boldar/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -18,17 +18,17 @@ const enum ec_led_id supported_led_ids[] = { }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -struct pwm_led led_color_map[] = { - /* Red, Green, Blue */ - [EC_LED_COLOR_RED] = { 100, 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, +struct pwm_led_color_map led_color_map[] = { + /* Red, Green, Blue */ + [EC_LED_COLOR_RED] = { 100, 0, 0 }, + [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, /* The green LED seems to be brighter than the others, so turn down * green from its natural level for these secondary colors. */ - [EC_LED_COLOR_YELLOW] = { 100, 70, 0 }, - [EC_LED_COLOR_WHITE] = { 100, 70, 100 }, - [EC_LED_COLOR_AMBER] = { 100, 20, 0 }, + [EC_LED_COLOR_YELLOW] = { 100, 70, 0 }, + [EC_LED_COLOR_WHITE] = { 100, 70, 100 }, + [EC_LED_COLOR_AMBER] = { 100, 20, 0 }, }; struct pwm_led pwm_leds[] = { diff --git a/board/boldar/sensors.c b/board/boldar/sensors.c index 9e34812131..90c79a8675 100644 --- a/board/boldar/sensors.c +++ b/board/boldar/sensors.c @@ -1,21 +1,22 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer family-specific sensor configuration */ -#include "common.h" #include "accelgyro.h" -#include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi_common.h" +#include "common.h" +#include "driver/accel_lis2dh.h" #include "driver/accelgyro_bmi260.h" +#include "driver/accelgyro_bmi_common.h" #include "driver/als_tcs3400.h" #include "driver/sync.h" -#include "keyboard_scan.h" +#include "gpio.h" #include "hooks.h" #include "i2c.h" -#include "task.h" +#include "keyboard_scan.h" #include "tablet_mode.h" +#include "task.h" #include "util.h" /******************************************************************************/ @@ -23,8 +24,8 @@ static struct mutex g_lid_accel_mutex; static struct mutex g_base_mutex; -/* BMA253 private data */ -static struct accelgyro_saved_data_t g_bma253_data; +/* Lid accel private data */ +static struct stprivate_data g_lis2dh_data; /* BMI260 private data */ static struct bmi_drv_data_t g_bmi260_data; @@ -84,33 +85,29 @@ static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { }; /* Rotation matrix for the lid accelerometer */ -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { .name = "Lid Accel", .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMA255, + .chip = MOTIONSENSE_CHIP_LIS2DH, .type = MOTIONSENSE_TYPE_ACCEL, .location = MOTIONSENSE_LOC_LID, - .drv = &bma2x2_accel_drv, + .drv = &lis2dh_drv, .mutex = &g_lid_accel_mutex, - .drv_data = &g_bma253_data, + .drv_data = &g_lis2dh_data, .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .i2c_spi_addr_flags = LIS2DH_ADDR0_FLAGS, .rot_standard_ref = &lid_standard_ref, - .min_frequency = BMA255_ACCEL_MIN_FREQ, - .max_frequency = BMA255_ACCEL_MAX_FREQ, + .min_frequency = LIS2DH_ODR_MIN_VAL, + .max_frequency = LIS2DH_ODR_MAX_VAL, .default_range = 2, /* g, to support tablet mode */ .config = { /* EC use accel for angle detection */ @@ -224,22 +221,3 @@ static void baseboard_sensors_init(void) gpio_enable_interrupt(GPIO_EC_IMU_INT_L); } DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); - -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); - - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif diff --git a/board/boldar/vif_override.xml b/board/boldar/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/boldar/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/boten/battery.c b/board/boten/battery.c index 3b6304937d..c4b4f9261d 100644 --- a/board/boten/battery.c +++ b/board/boten/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -41,9 +41,9 @@ const struct board_batt_params board_battery_info[] = { .reg_data = { 0x0000, 0x1000 }, }, .fet = { - .reg_addr = 0x34, - .reg_mask = 0x0100, - .disconnect_val = 0x0100, + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, } }, .batt_info = { @@ -69,9 +69,9 @@ const struct board_batt_params board_battery_info[] = { .reg_data = { 0x0000, 0x1000 }, }, .fet = { - .reg_addr = 0x34, - .reg_mask = 0x0100, - .disconnect_val = 0x0100, + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, } }, .batt_info = { @@ -97,9 +97,9 @@ const struct board_batt_params board_battery_info[] = { .reg_data = { 0x0000, 0x1000 }, }, .fet = { - .reg_addr = 0x34, - .reg_mask = 0x0100, - .disconnect_val = 0x0100, + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, } }, .batt_info = { diff --git a/board/boten/board.c b/board/boten/board.c index bf7fdb17bf..c352d12f78 100644 --- a/board/boten/board.c +++ b/board/boten/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,16 +7,17 @@ #include "adc_chip.h" #include "button.h" +#include "cbi_fw_config.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "driver/accel_lis2dw12.h" #include "driver/accelgyro_lsm6dsm.h" #include "driver/bc12/pi3usb9201.h" #include "driver/charger/isl923x.h" -#include "driver/temp_sensor/thermistor.h" #include "driver/tcpm/raa489000.h" #include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" #include "driver/usb_mux/it5205.h" #include "gpio.h" #include "hooks.h" @@ -31,7 +32,7 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" #include "uart.h" #include "usb_charge.h" @@ -39,21 +40,50 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" -#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); static void hdmi_hpd_interrupt(enum gpio_signal s) { gpio_set_level(GPIO_USB_C1_DP_HPD, !gpio_get_level(s)); } -static void usb_c0_interrupt(enum gpio_signal s) +static void notify_c0_chips(void) { /* * The interrupt line is shared between the TCPC and BC 1.2 detection - * chip. + * chip. Therefore we'll need to check both ICs. */ schedule_deferred_pd_interrupt(0); - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); } static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) @@ -62,39 +92,74 @@ static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) pd_handle_cc_overvoltage(0); } +/** + * Deferred function to handle pen detect change + */ +static void pendetect_deferred(void) +{ + static int debounced_pen_detect; + int pen_detect = !gpio_get_level(GPIO_PEN_DET_ODL); + + if (pen_detect == debounced_pen_detect) + return; + + debounced_pen_detect = pen_detect; + + gpio_set_level(GPIO_EN_PP5000_PEN, debounced_pen_detect); + gpio_set_level(GPIO_PEN_DET_PCH, !debounced_pen_detect); +} +DECLARE_DEFERRED(pendetect_deferred); + +void pen_detect_interrupt(enum gpio_signal s) +{ + /* Trigger deferred notification of pen detect change */ + hook_call_deferred(&pendetect_deferred_data, 500 * MSEC); +} + +void board_hibernate(void) +{ + /* + * Charger IC need to be put into their "low power mode" before + * entering the Z-state. + */ + raa489000_hibernate(0, false); +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + /* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_VSNS_PP3300_A] = { - .name = "PP3300_A_PGOOD", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH0 - }, - [ADC_TEMP_SENSOR_1] = { - .name = "TEMP_SENSOR1", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH2 - }, - [ADC_TEMP_SENSOR_2] = { - .name = "TEMP_SENSOR2", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH3 - }, - [ADC_SUB_ANALOG] = { - .name = "SUB_ANALOG", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH13 - }, + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -130,31 +195,22 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }; /* USB Muxes */ -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, }, }; -void board_init(void) -{ - gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); - /* Enable gpio interrupt for base accelgyro sensor */ - gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); - gpio_enable_interrupt(GPIO_HDMI_HPD_SUB_ODL); - - gpio_set_level(GPIO_HDMI_EN_SUB_ODL, 0); - - /* Set LEDs luminance */ - pwm_set_duty(PWM_CH_LED_RED, 70); - pwm_set_duty(PWM_CH_LED_GREEN, 70); - pwm_set_duty(PWM_CH_LED_WHITE, 70); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +/* USB-A charging control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, +}; void board_reset_pd_mcu(void) { @@ -188,16 +244,12 @@ uint16_t tcpc_get_alert_status(void) return status; } -void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma, - int charge_mv) +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) { - int icl = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); + if (port < 0 || port > board_get_usb_pd_port_count()) + return; - /* - * TODO(b/151955431): Characterize the input current limit in case a - * scaling needs to be applied here - */ - charge_set_input_current_limit(icl, charge_mv); + raa489000_set_output_current(port, rp); } int board_is_sourcing_vbus(int port) @@ -206,7 +258,6 @@ int board_is_sourcing_vbus(int port) tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); - } int board_set_active_charge_port(int port) @@ -218,9 +269,8 @@ int board_set_active_charge_port(int port) /* Disable all ports. */ if (port == CHARGE_PORT_NONE) { - tcpc_write(0, TCPC_REG_COMMAND, - TCPC_REG_COMMAND_SNK_CTRL_LOW); - + tcpc_write(0, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(0, false); return EC_SUCCESS; } @@ -231,8 +281,8 @@ int board_set_active_charge_port(int port) } /* Enable requested charge port. */ - if (tcpc_write(0, TCPC_REG_COMMAND, - TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + if (raa489000_enable_asgate(port, true) || + tcpc_write(0, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { CPRINTUSB("p%d: sink path enable failed.", port); return EC_ERROR_UNKNOWN; } @@ -273,6 +323,15 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); static struct mutex g_lid_mutex; static struct mutex g_base_mutex; +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + /* Sensor Data */ static struct stprivate_data g_lis2dwl_data; static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; @@ -290,7 +349,7 @@ struct motion_sensor_t motion_sensors[] = { .drv_data = &g_lis2dwl_data, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, - .rot_standard_ref = NULL, + .rot_standard_ref = &lid_standard_ref, .default_range = 2, /* g */ .min_frequency = LIS2DW12_ODR_MIN_VAL, .max_frequency = LIS2DW12_ODR_MAX_VAL, @@ -313,11 +372,9 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .rot_standard_ref = NULL, + .rot_standard_ref = &base_standard_ref, .default_range = 4, /* g */ .min_frequency = LSM6DSM_ODR_MIN_VAL, .max_frequency = LSM6DSM_ODR_MAX_VAL, @@ -342,35 +399,83 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ - .rot_standard_ref = NULL, + .rot_standard_ref = &base_standard_ref, .min_frequency = LSM6DSM_ODR_MIN_VAL, .max_frequency = LSM6DSM_ODR_MAX_VAL, }, }; -const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void board_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + gpio_enable_interrupt(GPIO_HDMI_HPD_SUB_ODL); + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_PRESENT) { + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + /* Enable gpio interrupt for pen detect */ + gpio_enable_interrupt(GPIO_PEN_DET_ODL); + + /* Make sure pen detection is triggered or not at sysjump */ + if (!gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_EN_PP5000_PEN, 1); + + if (gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_PEN_DET_PCH, 1); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + + /* only clamshell sku todo */ + gpio_set_flags(GPIO_PEN_DET_ODL, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_PEN_DET_PCH, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_EN_PP5000_PEN, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_LID_360_L, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_VOLUP_BTN_ODL, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_VOLDN_BTN_ODL, GPIO_INPUT | GPIO_PULL_DOWN); + button_disable_gpio(BUTTON_VOLUME_UP); + button_disable_gpio(BUTTON_VOLUME_DOWN); + } + + /* Set LEDs luminance */ + pwm_set_duty(PWM_CH_LED_RED, 70); + pwm_set_duty(PWM_CH_LED_GREEN, 70); + pwm_set_duty(PWM_CH_LED_WHITE, 70); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); /* Thermistors */ const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Memory", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); @@ -394,4 +499,3 @@ void lid_angle_peripheral_enable(int enable) keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); } } -#endif diff --git a/board/boten/board.h b/board/boten/board.h index f8ce11b817..f429d7c942 100644 --- a/board/boten/board.h +++ b/board/boten/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,11 +12,11 @@ #define VARIANT_DEDEDE_EC_IT8320 #include "baseboard.h" -/* System unlocked in early development */ -#define CONFIG_SYSTEM_UNLOCKED - /* Battery */ #define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 /* BC 1.2 */ #define CONFIG_BC12_DETECT_PI3USB9201 @@ -24,27 +24,38 @@ /* Charger */ #define CONFIG_CHARGE_RAMP_HW #define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 #define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_OCPC_DEF_RBATT_MOHMS 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr */ +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 /* DAC for PSYS */ #define CONFIG_DAC /* LED */ -#define CONFIG_LED_POWER_LED #define CONFIG_LED_ONOFF_STATES /* PWM */ #define CONFIG_PWM /* Sensors */ -#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO /* Power of 2 - Too large of a fifo causes too much timestamp jitter */ @@ -70,6 +81,11 @@ #define CONFIG_USB_PD_DISCHARGE_TCPC #define CONFIG_USB_PD_TCPC_LOW_POWER +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + /* Variant references the TCPCs to determine Vbus sourcing */ #define CONFIG_USB_PD_5V_EN_CUSTOM @@ -77,11 +93,17 @@ #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_PP3300_A /* USB Mux */ #define CONFIG_USB_MUX_IT5205 +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT +#define CONFIG_BUTTONS_RUNTIME_CONFIG + #ifndef __ASSEMBLER__ #include "gpio_signal.h" @@ -96,27 +118,17 @@ enum pwm_channel { }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; /* ADC channels */ enum adc_channel { - ADC_VSNS_PP3300_A, /* ADC0 */ - ADC_TEMP_SENSOR_1, /* ADC2 */ - ADC_TEMP_SENSOR_2, /* ADC3 */ - ADC_SUB_ANALOG, /* ADC13 */ + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ ADC_CH_COUNT }; -enum temp_sensor_id { - TEMP_SENSOR_1, - TEMP_SENSOR_2, - TEMP_SENSOR_COUNT -}; +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { @@ -126,7 +138,7 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -int board_is_sourcing_vbus(int port); +void pen_detect_interrupt(enum gpio_signal s); #endif /* !__ASSEMBLER__ */ diff --git a/board/boten/build.mk b/board/boten/build.mk index 00e4e0bb5d..9b862c7624 100644 --- a/board/boten/build.mk +++ b/board/boten/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,5 +11,5 @@ CHIP_FAMILY:=it8320 CHIP_VARIANT:=it8320dx BASEBOARD:=dedede -board-y=board.o led.o usb_pd_policy.o +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/boten/cbi_ssfc.c b/board/boten/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/boten/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/boten/cbi_ssfc.h b/board/boten/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/boten/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/boten/ec.tasklist b/board/boten/ec.tasklist index e1fd188d7c..e610e8ad33 100644 --- a/board/boten/ec.tasklist +++ b/board/boten/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,12 +11,12 @@ TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/boten/gpio.inc b/board/boten/gpio.inc index d355338bee..4c9890441d 100644 --- a/board/boten/gpio.inc +++ b/board/boten/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -80,27 +80,26 @@ GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) /* USB pins */ -GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_HIGH) +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) GPIO(EN_USB_A1_VBUS, PIN(E, 6), GPIO_OUT_LOW) GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_LOW) -GPIO(HDMI_EN_SUB_ODL, PIN(E, 0), GPIO_OUT_HIGH) /* MKBP event synchronization */ GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) /* Misc pins which will run to the I/O board */ -GPIO(EC_SUB_IO_1_1, PIN(L, 3), GPIO_INPUT) -GPIO(EC_SUB_IO_1_2, PIN(F, 0), GPIO_INPUT) /* Misc */ -GPIO(EN_BL_OD, PIN(K, 4), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) -GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_INPUT) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) -GPIO(PEN_DET_ODL, PIN(J, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO_INT(PEN_DET_ODL, PIN(J, 1), GPIO_INT_BOTH | GPIO_PULL_UP, pen_detect_interrupt) GPIO(EN_PP5000_PEN, PIN(B, 5), GPIO_OUT_LOW) +GPIO(PEN_DET_PCH, PIN(F, 1), GPIO_OUT_LOW) GPIO(EN_KB_BL, PIN(J, 3), GPIO_OUT_LOW) /* Currently unused */ GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) @@ -108,8 +107,8 @@ GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOC4_NC, PIN(C, 4), GPIO_INPUT | GPIO_PULL_DOWN) -GPIO(GPIOC7_NC, PIN(C, 7), GPIO_INPUT | GPIO_PULL_DOWN) -GPIO(GPIOF1_NC, PIN(F, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF0_NC, PIN(F, 0), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOF4_NC, PIN(F, 4), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) @@ -122,7 +121,9 @@ GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL0_NC, PIN(L, 0), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOL2_NC, PIN(L, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL3_NC, PIN(L, 3), GPIO_INPUT | GPIO_PULL_DOWN) GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) /* Alternate functions GPIO definitions */ @@ -136,7 +137,6 @@ ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ /* ADC */ -ALTERNATE(PIN_MASK(L, BIT(0)), 0, MODULE_ADC, 0) /* ADC13: EC_SUB_ANALOG */ ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ /* DAC */ diff --git a/board/boten/led.c b/board/boten/led.c index fe0a03e8db..c61ffba6fe 100644 --- a/board/boten/led.c +++ b/board/boten/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,48 +6,55 @@ */ #include "common.h" -#include "led_onoff_states.h" -#include "led_common.h" #include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" #include "pwm.h" -#define LED_OFF_LVL 0 -#define LED_ON_LVL 1 +#define LED_OFF_LVL 0 +#define LED_ON_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 97; +__override const int led_charge_lvl_2 = 97; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, + 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) pwm_enable(PWM_CH_LED_WHITE, LED_ON_LVL); @@ -55,7 +62,7 @@ void led_set_color_power(enum ec_led_colors color) pwm_enable(PWM_CH_LED_WHITE, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_RED: diff --git a/board/boten/usb_pd_policy.c b/board/boten/usb_pd_policy.c index 47acd5e67e..74167850ee 100644 --- a/board/boten/usb_pd_policy.c +++ b/board/boten/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,12 +9,12 @@ #include "chipset.h" #include "common.h" #include "console.h" -#include "driver/charger/sm5803.h" +#include "driver/charger/isl923x_public.h" #include "driver/tcpm/tcpci.h" #include "usb_pd.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -30,11 +30,6 @@ void pd_power_supply_reset(int port) /* Disable VBUS */ tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -60,10 +55,9 @@ int pd_set_power_supply_ready(int port) if (rv) return rv; -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -73,8 +67,5 @@ int pd_set_power_supply_ready(int port) int pd_snk_is_vbus_provided(int port) { - int regval = 0; - - tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); - return regval & TCPC_REG_POWER_STATUS_VBUS_PRES; + return pd_check_vbus_level(port, VBUS_PRESENT); } diff --git a/board/boten/vif_override.xml b/board/boten/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/boten/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/boxy/board.c b/board/boxy/board.c new file mode 100644 index 0000000000..a0f8dd6683 --- /dev/null +++ b/board/boxy/board.c @@ -0,0 +1,333 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Boxy board-specific configuration */ + +#include "adc_chip.h" +#include "board.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_VBUS] = { .name = "VBUS", /* 113/1113 voltage divider */ + .factor_mul = ADC_MAX_MVOLT * 1113, + .factor_div = (ADC_READ_MAX + 1) * 113, + .shift = 0, + .channel = CHIP_ADC_CH4 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, + [ADC_PPVAR_PWR_IN_IMON] = { .name = "ADC_PPVAR_PWR_IN_IMON", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, + [ADC_SNS_PPVAR_PWR_IN] = { .name = "ADC_SNS_PPVAR_PWR_IN", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH16 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &it83xx_tcpm_drv, + }, +}; + +/* PPCs */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, +}; + +/* USB-A ports */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, + GPIO_EN_USB_A1_VBUS, +}; + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_RED] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_GREEN] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_BLUE] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + } + +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "SoC power", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +void board_init(void) +{ + /* Enable PPC interrupt */ + gpio_enable_interrupt(GPIO_USB_C0_FAULT_L); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Nothing to do. 5V should always be enabled while in Z1 or above. + */ +} + +void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma, + int charge_mv) +{ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + /* TODO(b/259467280) blink LED on error */ + (void)insufficient_power; +} + +int board_vbus_source_enabled(int port) +{ + if (port != CHARGE_PORT_TYPEC0) + return 0; + + return ppc_is_sourcing_vbus(port); +} + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* + * We ignore the cc_pin and PPC vconn because polarity and PPC vconn + * should already be set correctly in the PPC driver via the pd + * state machine. + */ +} + +/******************************************************************************/ +/* + * Since boxy has no battery, it must source all of its power from either + * USB-C or the barrel jack (preferred). Fizz operates in continuous safe + * mode (charge_manager_leave_safe_mode() will never be called), which + * modifies port selection as follows: + * + * - Dual-role / dedicated capability of the port partner is ignored. + * - Charge ceiling on PD voltage transition is ignored. + * - CHARGE_PORT_NONE will never be selected. + */ + +int board_set_active_charge_port(int port) +{ + const int active_port = charge_manager_get_active_charge_port(); + + CPRINTUSB("Requested charge port change to %d", port); + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == active_port) + return EC_SUCCESS; + + /* Don't sink from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + + /* TODO: add this part after two type-c function is finished. */ + } + + CPRINTUSB("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + ppc_vbus_sink_enable(USBC_PORT_C0, 1); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static void board_charge_manager_init(void) +{ + enum charge_port port; + + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + port = CHARGE_PORT_TYPEC0; + CPRINTUSB("Power source is p%d (USB-C)", port); + + /* Initialize the power source supplier */ + switch (port) { + case CHARGE_PORT_TYPEC0: + typec_set_input_current_limit(port, 3000, 5000); + break; + } +} +DECLARE_HOOK(HOOK_INIT, board_charge_manager_init, + HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +__override int extpower_is_present(void) +{ + /* + * There's no battery, so running this method implies we have power. + */ + return 1; +} + +void ppc_interrupt(enum gpio_signal signal) +{ + if (signal == GPIO_USB_C0_FAULT_L) + syv682x_interrupt(USBC_PORT_C0); +} + +/* I2C Ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + + { .name = "usbc0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_SCL, + .sda = GPIO_EC_I2C_USB_C0_SDA }, + + { .name = "hdmi1_edid", + .port = I2C_PORT_HDMI1_EDID, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI1_EDID_SCL, + .sda = GPIO_EC_I2C_HDMI1_EDID_SDA }, + + { .name = "hdmi1_src_ddc", + .port = I2C_PORT_HDMI1_SRC_DDC, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI1_SRC_DDC_SCL, + .sda = GPIO_EC_I2C_HDMI1_SRC_DDC_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" diff --git a/board/boxy/board.h b/board/boxy/board.h new file mode 100644 index 0000000000..c48d9fe29f --- /dev/null +++ b/board/boxy/board.h @@ -0,0 +1,166 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Boxy board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +/* System unlocked in early development */ +#define CONFIG_SYSTEM_UNLOCKED + +#define CONFIG_CMD_CHARGER_DUMP + +/* I2C Bus Configuration */ +#define I2C_PORT_HDMI2_EDID IT83XX_I2C_CH_B +#undef I2C_PORT_USB_C0 +#define I2C_PORT_USB_C0 IT83XX_I2C_CH_C +#define I2C_PORT_HDMI2_SRC_DDC IT83XX_I2C_CH_D +#define I2C_PORT_HDMI1_EDID IT83XX_I2C_CH_E +#define I2C_PORT_HDMI1_SRC_DDC IT83XX_I2C_CH_F + +/* Power */ +#undef CONFIG_CHARGER +#undef CONFIG_CHARGER_DISCHARGE_ON_AC +#undef CONFIG_USB_PD_VBUS_MEASURE_CHARGER +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 16000 +#define PD_MAX_VOLTAGE_MV 20000 +#undef PD_MAX_CURRENT_MA +#define PD_MAX_CURRENT_MA 3250 +#undef PD_MAX_POWER_MW +#define PD_MAX_POWER_MW 65000 +#define CONFIG_USB_PD_VBUS_DETECT_GPIO + +/* Override macro for C0 only */ +#define PORT_TO_HPD(port) (GPIO_USB_C0_DP_HPD) + +/* Power: Dedicated barreljack charger port */ +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 +#define DEDICATED_CHARGE_PORT 1 + +/* USB Type-C */ +#undef CONFIG_USB_CHARGER +#undef CONFIG_USB_MUX_PI3USB31532 + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 + +/* PPC */ +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USBC_PPC +#define CONFIG_USBC_PPC_SYV682X + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C0: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +/* USB Type A Features */ +#define CONFIG_USB_PORT_POWER_DUMB +#define USB_PORT_COUNT 2 /* Type A ports */ + +/* No battery */ +#undef CONFIG_BATTERY_CUT_OFF +#undef CONFIG_BATTERY_PRESENT_GPIO +#undef CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD +#undef CONFIG_BATTERY_REVIVE_DISCONNECT +#undef CONFIG_BATTERY_SMART + +/* LED */ +#define CONFIG_LED_PWM +#define CONFIG_LED_PWM_COUNT 1 + +/* PWM */ +#define CONFIG_PWM + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* Buttons */ +#define CONFIG_DEDICATED_RECOVERY_BUTTON +#define CONFIG_DEDICATED_RECOVERY_BUTTON_2 +#define CONFIG_DEDICATED_RECOVERY_BUTTON_FLAGS BUTTON_FLAG_ACTIVE_HIGH +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_IGNORE_LID +#define CONFIG_POWER_BUTTON_X86 +#define CONFIG_EMULATED_SYSRQ + +/* No Keyboard */ +#undef CONFIG_KEYBOARD_COL2_INVERTED +#undef CONFIG_KEYBOARD_PROTOCOL_8042 +#undef CONFIG_CMD_KEYBOARD +#undef CONFIG_KEYBOARD_BOOT_KEYS +#undef CONFIG_KEYBOARD_RUNTIME_KEYS + +/* No backlight */ +#undef CONFIG_BACKLIGHT_LID +#undef GPIO_ENABLE_BACKLIGHT + +/* Unused features - Misc */ +#undef CONFIG_HIBERNATE +#undef CONFIG_VOLUME_BUTTONS +#undef CONFIG_LID_SWITCH +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE +#undef GPIO_TABLET_MODE_L + +/* Unused GPIOs */ +#undef GPIO_USB_C1_DP_HPD + +/* Pin renaming */ +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, +}; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_COUNT }; + +enum pwm_channel { + PWM_CH_LED_RED, + PWM_CH_LED_GREEN, + PWM_CH_LED_BLUE, + PWM_CH_COUNT, +}; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_VBUS, /* ADC4 */ + ADC_TEMP_SENSOR_3, /* ADC13 */ + ADC_PPVAR_PWR_IN_IMON, /* ADC15 */ + ADC_SNS_PPVAR_PWR_IN, /* ADC16 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/boxy/build.mk b/board/boxy/build.mk new file mode 100644 index 0000000000..5593502527 --- /dev/null +++ b/board/boxy/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede +BOARD:=boxy + +board-y=board.o led.o usb_pd_policy.o diff --git a/board/boxy/ec.tasklist b/board/boxy/ec.tasklist new file mode 100644 index 0000000000..4aad682d14 --- /dev/null +++ b/board/boxy/ec.tasklist @@ -0,0 +1,16 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) diff --git a/board/boxy/gpio.inc b/board/boxy/gpio.inc new file mode 100644 index 0000000000..c21ff3e870 --- /dev/null +++ b/board/boxy/gpio.inc @@ -0,0 +1,165 @@ +/* -*- mode:c -*- + * + * Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, + baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(EC_VSNS_PP3300_S5, PIN(I, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, + baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, + espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, + power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, + uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX + */ +#endif + +/* Other interrupts */ +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +/* Directly connected recovery button */ +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(K, 7), GPIO_INT_BOTH, button_interrupt) +/* Recovery button input from H1 */ +GPIO_INT(H1_EC_RECOVERY_BTN_ODL, PIN(K, 4), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(USB_C0_FAULT_L, PIN(K, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_FAULT_L, PIN(K, 3), GPIO_INT_FALLING, ppc_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_PSYS, PIN(J, 2), GPIO_OUT_LOW) +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(J, 0), GPIO_INPUT) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_HIGH) +GPIO(PG_PP3300_A, PIN(B, 5), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for + * dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Required for dedede baseboard but not used in boxy */ +UNIMPLEMENTED(USB_C0_INT_ODL) +UNIMPLEMENTED(EN_SLP_Z) +UNIMPLEMENTED(EC_BATTERY_PRES_ODL) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(F, 6), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(F, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_EDID_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_EDID_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_SRC_DDC_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_SRC_DDC_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HPD, PIN(J, 6), GPIO_OUT_LOW) +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_A1_VBUS, PIN(C, 6), GPIO_OUT_LOW) +GPIO(USB_C0_SBU_MUX_FAULT, PIN(I, 7), GPIO_INPUT) + +/* MKBP event synchronization */ +/* TODO(b/257833880) Check whether this pin is needed */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* HDMI */ +GPIO(HDMI1_CEC, PIN(F, 0), GPIO_OUT_LOW) +GPIO(HDMI1_SRC_HPD, PIN(F, 3), GPIO_INPUT) +GPIO(EC_HDMI1_SRC_HPD_OUT, PIN(K, 6), GPIO_OUT_LOW) +GPIO(HDMI1_EDID_SEL, PIN(J, 1), GPIO_OUT_LOW) +GPIO(EDID_BTN_ODL, PIN(C, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_EN_PP5000_HDMI1, PIN(KSO_L, 6), GPIO_OUT_LOW) + +/* Misc */ +GPIO(EC_ENTERING_RW, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(ECH1_PACKET_MODE, PIN(C, 0), GPIO_OUT_LOW) +GPIO(UART0_RX, PIN(B, 1), GPIO_OUT_LOW) /* UART_EC_TX_DBG_RX */ + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOG0_NC, PIN(G, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOI4_NC, PIN(I, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE3_NC, PIN(E, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF1_NC, PIN(F, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE6_NC, PIN(E, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC4_NC, PIN(C, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOI6_NC, PIN(I, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA0_NC, PIN(A, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ3_NC, PIN(J, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 - EEPROM */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 - USB_C1*/ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, 0) /* I2C2 - USB_C0 */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 - HDMI1_EDID + */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 - + HDMI1_SRC_DDC */ + +/* ADC */ +/* ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2, ADC4: VBUS */ +ALTERNATE(PIN_MASK(I, BIT(2) | BIT(3) | BIT(4)), 0, MODULE_ADC, 0) +/* + * ADC13: TEMP_SENSOR_3 + * ADC15: ANALOG_PPVAR_PWR_IN_IMON + * ADC16: SNS_PPVAR_PWR_IN + */ +ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(1) | BIT(2) | BIT(3)), 0, MODULE_PWM, + 0) /* LED_[R,G,B]_ODL + */ \ No newline at end of file diff --git a/board/boxy/led.c b/board/boxy/led.c new file mode 100644 index 0000000000..9ed4f3c413 --- /dev/null +++ b/board/boxy/led.c @@ -0,0 +1,80 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Boxy specific PWM LED settings. */ + +#include "common.h" +#include "ec_commands.h" +#include "led_pwm.h" +#include "pwm.h" +#include "util.h" + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_POWER_LED, +}; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +/* One physical LED with red, green, and blue. */ +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Red, Green, Blue */ + [EC_LED_COLOR_RED] = { 100, 0, 0 }, + [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, + [EC_LED_COLOR_YELLOW] = { 50, 50, 0 }, + [EC_LED_COLOR_WHITE] = { 50, 50, 50 }, + [EC_LED_COLOR_AMBER] = { 70, 30, 0 }, +}; + +/* One logical LED with red, green, and blue channels. */ +struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = { + { + .ch0 = PWM_CH_LED_RED, + .ch1 = PWM_CH_LED_GREEN, + .ch2 = PWM_CH_LED_BLUE, + .enable = &pwm_enable, + .set_duty = &pwm_set_duty, + }, +}; + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + memset(brightness_range, '\0', + sizeof(*brightness_range) * EC_LED_COLOR_COUNT); + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_GREEN] = 100; + brightness_range[EC_LED_COLOR_BLUE] = 100; + brightness_range[EC_LED_COLOR_YELLOW] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; + brightness_range[EC_LED_COLOR_AMBER] = 100; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + enum pwm_led_id pwm_id; + + /* Convert ec_led_id to pwm_led_id. */ + if (led_id == EC_LED_ID_POWER_LED) + pwm_id = PWM_LED0; + else + return EC_ERROR_UNKNOWN; + + if (brightness[EC_LED_COLOR_RED]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_GREEN]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN); + else if (brightness[EC_LED_COLOR_BLUE]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_YELLOW]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_YELLOW); + else if (brightness[EC_LED_COLOR_WHITE]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); + else + /* Otherwise, the "color" is "off". */ + set_pwm_led_color(pwm_id, -1); + + return EC_SUCCESS; +} diff --git a/board/boxy/usb_pd_policy.c b/board/boxy/usb_pd_policy.c new file mode 100644 index 0000000000..58bc80170f --- /dev/null +++ b/board/boxy/usb_pd_policy.c @@ -0,0 +1,72 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "usb_pd.h" +#include "usbc_ppc.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return gpio_get_level(GPIO_EN_PP5000_U); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + if (port < 0 || port >= board_get_usb_pd_port_count()) + return; + + prev_en = ppc_is_sourcing_vbus(port); + + /* Disable VBUS source */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Enable VBUS source */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +__override int pd_snk_is_vbus_provided(int port) +{ + if (port != CHARGE_PORT_TYPEC0) + return 0; + + return ppc_is_vbus_present(port); +} diff --git a/board/boxy/vif_override.xml b/board/boxy/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/boxy/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/brask/board.c b/board/brask/board.c new file mode 100644 index 0000000000..793c2889f8 --- /dev/null +++ b/board/brask/board.c @@ -0,0 +1,611 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "builtin/assert.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/cec/bitbang.h" +#include "driver/tcpm/tcpci.h" +#include "driver/wpc/cps8100.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "peripheral_charger.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +struct pchg pchgs[] = { + [0] = { + .cfg = &(const struct pchg_config) { + .drv = &cps8100_drv, + .i2c_port = I2C_PORT_QI, + .irq_pin = GPIO_QI_INT_ODL, + .full_percent = 96, + .block_size = 128, + }, + .policy = { + [PCHG_CHIPSET_STATE_ON] = &pchg_policy_on, + [PCHG_CHIPSET_STATE_SUSPEND] = &pchg_policy_suspend, + }, + .events = QUEUE_NULL(PCHG_EVENT_QUEUE_SIZE, enum pchg_event), + }, +}; + +int board_get_pchg_count(void) +{ + return ARRAY_SIZE(pchgs); +} + +__override void board_pchg_power_on(int port, bool on) +{ + if (port == 0) + gpio_set_level(GPIO_EC_QI_PWR, on); + else + CPRINTS("%s: Invalid port=%d", __func__, port); +} + +/******************************************************************************/ + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + case CHARGE_PORT_TYPEC1: + case CHARGE_PORT_TYPEC2: + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power_s5; +static int32_t base_5v_power_z1; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ + +/* PP5000_S5 loads */ +#define PWR_S5_BASE_LOAD (5 * 1431) +#define PWR_S5_FRONT_HIGH (5 * 1737) +#define PWR_S5_FRONT_LOW (5 * 1055) +#define PWR_S5_REAR_HIGH (5 * 1737) +#define PWR_S5_REAR_LOW (5 * 1055) +#define PWR_S5_HDMI (5 * 580) +#define PWR_S5_MAX (5 * 10000) +#define FRONT_DELTA (PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW) +#define REAR_DELTA (PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW) + +/* PP5000_Z1 loads */ +#define PWR_Z1_BASE_LOAD (5 * 5) +#define PWR_Z1_C_HIGH (5 * 3600) +#define PWR_Z1_C_LOW (5 * 2000) +#define PWR_Z1_MAX (5 * 9000) +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int front_ports = 0; + int rear_ports = 0; + + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power_s5 = PWR_S5_BASE_LOAD; + if (!gpio_get_level(GPIO_USB_A0_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + /* + * Only 1 front port can run higher power at a time. + */ + if (front_ports > 0) + base_5v_power_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + + if (!gpio_get_level(GPIO_USB_A2_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + if (!gpio_get_level(GPIO_USB_A3_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + /* + * Only 1 rear port can run higher power at a time. + */ + if (rear_ports > 0) + base_5v_power_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + if (!gpio_get_level(GPIO_HDMI_CONN_OC_ODL)) + base_5v_power_s5 += PWR_S5_HDMI; + base_5v_power_z1 = PWR_Z1_BASE_LOAD; + if (usbc_overcurrent) + base_5v_power_z1 += PWR_Z1_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) + ec_bj_power(&pi.voltage, &pi.current); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +static void adp_state_init(void) +{ + ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT); + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +static void board_init(void) +{ + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + gpio_enable_interrupt(GPIO_HDMI_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A2_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A3_OC_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Check that port number is valid. */ + if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) + return; + usbc_overcurrent = is_overcurrented; + update_5v_usage(); +} +/* + * Power monitoring and management. + * + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * The overall goal is to gracefully manage the power demand so that + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type A BC1.2 rear port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 3 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A_FRONT BIT(0) +#define THROT_TYPE_A_REAR BIT(1) +#define THROT_TYPE_C0 BIT(2) +#define THROT_TYPE_C1 BIT(3) +#define THROT_TYPE_C2 BIT(4) +#define THROT_PROCHOT BIT(5) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + static uint32_t history[POWER_READINGS]; + static uint8_t index; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v_s5 = PWR_S5_MAX - base_5v_power_s5; + int32_t headroom_5v_z1 = PWR_Z1_MAX - base_5v_power_z1; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + /* + * Clear the first entry of the power table so that + * it is re-initilalised when the CPU starts. + */ + history[0] = 0; + } else { + int32_t charger_mw; + + delay = POWER_DELAY_MS * MSEC; + /* + * Get current charger limit (in mw). + * If not configured yet, skip. + */ + charger_mw = charge_manager_get_power_limit_uw() / 1000; + if (charger_mw != 0) { + int32_t gap, total, max, power; + int i; + + /* + * Read power usage. + */ + power = (adc_read_channel(ADC_VBUS) * + adc_read_channel(ADC_PPVAR_IMON)) / + 1000; + /* Init power table */ + if (history[0] == 0) { + for (i = 0; i < POWER_READINGS; i++) + history[i] = power; + } + /* + * Update the power readings and + * calculate the average and max. + */ + history[index] = power; + index = (index + 1) % POWER_READINGS; + total = 0; + max = history[0]; + for (i = 0; i < POWER_READINGS; i++) { + total += history[i]; + if (history[i] > max) + max = history[i]; + } + /* + * For Type-C power supplies, there is + * less tolerance for exceeding the rating, + * so use the max power that has been measured + * over the measuring period. + * For barrel-jack supplies, the rating can be + * exceeded briefly, so use the average. + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + power = max; + else + power = total / POWER_READINGS; + /* + * Calculate gap, and if negative, power + * demand is exceeding configured power budget, so + * throttling is required to reduce the demand. + */ + gap = charger_mw - power; + /* + * Limiting type-A power rear ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_REAR; + headroom_5v_s5 += REAR_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * Limiting type-A power front ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_FRONT; + headroom_5v_s5 += FRONT_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(0) && gap <= 0) { + new_state |= THROT_TYPE_C0; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C0)) + gap += POWER_GAIN_TYPE_C; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(1) && gap <= 0) { + new_state |= THROT_TYPE_C1; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C1)) + gap += POWER_GAIN_TYPE_C; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(2) && gap <= 0) { + new_state |= THROT_TYPE_C2; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C2)) + gap += POWER_GAIN_TYPE_C; + } + /* + * As a last resort, turn on PROCHOT to + * throttle the CPU. + */ + if (gap <= 0) + new_state |= THROT_PROCHOT; + } + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v_z1 < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C0) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + new_state |= THROT_TYPE_C0; + } + /* + * [2] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v_z1 < 0) + new_state |= THROT_TYPE_C0; + } + if (headroom_5v_s5 < 0) { + /* + * [1] If type A rear not already throttled, and power still + * needed, limit type A rear. + */ + if (!(new_state & THROT_TYPE_A_REAR) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + new_state |= THROT_TYPE_A_REAR; + } + /* + * [2] If type A front not already throttled, and power still + * needed, limit type A front. + */ + if (!(new_state & THROT_TYPE_A_FRONT) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + new_state |= THROT_TYPE_A_FRONT; + } + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_C0) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C0) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + } + if (diff & THROT_TYPE_C1) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C1) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(1, rp); + tcpm_select_rp_value(1, rp); + pd_update_contract(1); + } + if (diff & THROT_TYPE_C2) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C2) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(2, rp); + tcpm_select_rp_value(2, rp); + pd_update_contract(2); + } + if (diff & THROT_TYPE_A_REAR) { + int typea_bc = (new_state & THROT_TYPE_A_REAR) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR0_OD, typea_bc); + gpio_set_level(GPIO_USB_A_LOW_PWR1_OD, typea_bc); + } + if (diff & THROT_TYPE_A_FRONT) { + int typea_bc = (new_state & THROT_TYPE_A_FRONT) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR2_OD, typea_bc); + gpio_set_level(GPIO_USB_A_LOW_PWR3_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/brask/board.h b/board/brask/board.h new file mode 100644 index 0000000000..cfd7b8b557 --- /dev/null +++ b/board/brask/board.h @@ -0,0 +1,207 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brask board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +#define CONFIG_MP2964 + +/* Barrel Jack */ +#define DEDICATED_CHARGE_PORT 3 + +/* HDMI CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMI_CEC_OUT +#define CEC_GPIO_IN GPIO_HDMI_CEC_IN +#define CEC_GPIO_PULL_UP GPIO_HDMI_CEC_PULL_UP + +/* USB Type A Features */ +#define USB_PORT_COUNT 4 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USB_PD_PPC +#define CONFIG_USB_PD_TCPM_RT1715 +#define CONFIG_USBC_RETIMER_INTEL_BB + +#define CONFIG_USBC_RETIMER_KB800X +#define CONFIG_KB800X_CUSTOM_XBAR +#define CONFIG_USBC_PPC_SYV682X +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* The design should support up to 100W. */ +/* TODO(b/197702356): Set the max PD to 60W now and change it + * to 100W after we verify it. + */ +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_OD + +/* I2C Bus Configuration */ + +#define I2C_PORT_DP_REDRIVER NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_C2_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_C2_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_QI NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x58 +#define USBC_PORT_C2_BB_RETIMER_I2C_ADDR 0x59 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* ADC */ +#define CONFIG_ADC + +/* + * TODO(b/197478860): Enable the fan control. We need + * to check the sensor value and adjust the fan speed. + */ +#define CONFIG_FANS FAN_CH_COUNT + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +/* WPC/Qi charger */ +#ifdef SECTION_IS_RW +#define CONFIG_PERIPHERAL_CHARGER +#define CONFIG_CPS8100 +#endif + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_TYPEC1, + CHARGE_PORT_TYPEC2, + CHARGE_PORT_BARRELJACK, + CHARGE_PORT_ENUM_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1_CPU, + ADC_TEMP_SENSOR_2_CPU_VR, + ADC_TEMP_SENSOR_3_WIFI, + ADC_TEMP_SENSOR_4_DIMM, + ADC_VBUS, + ADC_PPVAR_IMON, /* ADC3 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_CPU, + TEMP_SENSOR_2_CPU_VR, + TEMP_SENSOR_3_WIFI, + TEMP_SENSOR_4_DIMM, + TEMP_SENSOR_COUNT +}; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C2_NCT38XX, IOEX_PORT_COUNT }; + +enum pwm_channel { + PWM_CH_LED_GREEN, /* PWM0 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED_RED, /* PWM2 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +extern void adp_connect_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/brask/build.mk b/board/brask/build.mk new file mode 100644 index 0000000000..f180fcb8ef --- /dev/null +++ b/board/brask/build.mk @@ -0,0 +1,22 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brask board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brask + +board-y= +board-y+=board.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/brask/ec.tasklist b/board/brask/ec.tasklist new file mode 100644 index 0000000000..3572543743 --- /dev/null +++ b/board/brask/ec.tasklist @@ -0,0 +1,29 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PCHG, pchg_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P2, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C2, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(2) | BIT(0)), LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/brask/fans.c b/board/brask/fans.c new file mode 100644 index 0000000000..3f3ad3ccea --- /dev/null +++ b/board/brask/fans.c @@ -0,0 +1,50 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/197478860): need to update for real fan + * + * Prototype fan spins at about 7200 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2200, + .rpm_start = 2200, + .rpm_max = 7200, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/brask/fw_config.c b/board/brask/fw_config.c new file mode 100644 index 0000000000..3ee71e6a0f --- /dev/null +++ b/board/brask/fw_config.c @@ -0,0 +1,65 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union brask_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brask if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union brask_cbi_fw_config fw_config_defaults = { + .audio = DB_NAU88L25B_I2S, + .bj_power = BJ_135W, +}; + +/* + * Barrel-jack power adapter ratings. + */ +static const struct { + int voltage; + int current; +} bj_power[] = { + [BJ_135W] = { /* 0 - 135W (also default) */ + .voltage = 19500, + .current = 6920 + }, + [BJ_230W] = { /* 1 - 230W */ + .voltage = 19500, + .current = 11800 + } +}; + +/**************************************************************************** + * Brask FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +void ec_bj_power(uint32_t *voltage, uint32_t *current) +{ + unsigned int bj; + + bj = fw_config.bj_power; + /* Out of range value defaults to 0 */ + if (bj >= ARRAY_SIZE(bj_power)) + bj = 0; + *voltage = bj_power[bj].voltage; + *current = bj_power[bj].current; +} diff --git a/board/brask/fw_config.h b/board/brask/fw_config.h new file mode 100644 index 0000000000..95d81f1e05 --- /dev/null +++ b/board/brask/fw_config.h @@ -0,0 +1,41 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_BRASK_FW_CONFIG_H_ +#define __BOARD_BRASK_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Brask board. + * + * Source of truth is the project/brask/brask/config.star configuration file. + */ +enum ec_cfg_audio_type { DB_AUDIO_UNKNOWN = 0, DB_NAU88L25B_I2S = 1 }; + +enum ec_cfg_bj_power { BJ_135W = 0, BJ_230W = 1 }; + +union brask_cbi_fw_config { + struct { + uint32_t audio : 3; + uint32_t bj_power : 2; + uint32_t reserved_1 : 27; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union brask_cbi_fw_config get_fw_config(void); + +/** + * Get the barrel-jack power from FW_CONFIG. + */ +void ec_bj_power(uint32_t *voltage, uint32_t *current); + +#endif /* __BOARD_BRASK_FW_CONFIG_H_ */ diff --git a/board/brask/gpio.inc b/board/brask/gpio.inc new file mode 100644 index 0000000000..5fa07523f6 --- /dev/null +++ b/board/brask/gpio.inc @@ -0,0 +1,187 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTERRUPT GPIOs: */ + +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C2_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C2_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C2_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(2, 3), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(HDMI_CONN_OC_ODL, PIN(2, 4), GPIO_INPUT | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A0_OC_ODL, PIN(3, 1), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A2_OC_ODL, PIN(2, 7), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A3_OC_ODL, PIN(2, 6), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +#ifdef SECTION_IS_RW +GPIO_INT(QI_INT_ODL, PIN(9, 6), GPIO_INT_FALLING, pchg_irq) +#else +UNIMPLEMENTED(QI_INT_ODL) +#endif + +/* CCD */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + +/* Security */ +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Fan */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) + +/* ADC, need to check the usage */ +GPIO(ANALOG_PPVAR_PWR_IN_IMON_EC, PIN(4, 2), GPIO_INPUT) + +/* Display */ +GPIO(DP_CONN_OC_ODL, PIN(2, 5), GPIO_INPUT) + + +/* BarrelJack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 7), GPIO_OUT_LOW) + +/* Chipset PCH */ +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) + +/* Button */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(GSC_EC_RECOVERY_BTN_OD, PIN(2, 2), GPIO_INPUT) + +/* NFC */ +/* TODO(b/194068530): Enable NFC */ +GPIO(NFC_COIL_ACT_L, PIN(D, 4), GPIO_INPUT) +GPIO(NFC_LOW_POWER_MODE, PIN(9, 5), GPIO_OUT_HIGH) +GPIO(NFC_CARD_DET_L, PIN(A, 3), GPIO_INPUT) +GPIO(EN_NFC_BUZZER, PIN(0, 5), GPIO_OUT_LOW) + +/* Wireless Charger */ +GPIO(EC_QI_PWR, PIN(D, 2), GPIO_OUT_LOW) +GPIO(QI_RESET_L, PIN(9, 3), GPIO_OUT_HIGH) + +/* HDMI CEC */ +/* TODO(b/197474873): Enable HDMI CEC */ +GPIO(HDMI_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CEC_OUT, PIN(D, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMI_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH) + +/* I2C SCL/SDA */ +GPIO(EC_I2C_QI_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_QI_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_DP_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_DP_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) + +/* USBA */ +GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW) +GPIO(USB_A0_STATUS_L, PIN(2, 1), GPIO_INPUT) +GPIO(USB_A1_STATUS_L, PIN(2, 0), GPIO_INPUT) +GPIO(USB_A2_STATUS_L, PIN(1, 7), GPIO_INPUT) +GPIO(USB_A3_STATUS_L, PIN(1, 6), GPIO_INPUT) +GPIO(USB_A_LOW_PWR0_OD, PIN(1, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR1_OD, PIN(1, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR2_OD, PIN(1, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR3_OD, PIN(1, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH) + +/* LED */ +/* TODO(b/197471359): LED implementation */ +GPIO(LED_GREEN_L, PIN(C, 3), GPIO_OUT_LOW) +GPIO(LED_RED_L, PIN(C, 4), GPIO_OUT_LOW) + +/* USBC */ +GPIO(USB_C0_C2_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_L, PIN(0, 2), GPIO_OUT_LOW) + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C2_RT_RST_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 3), GPIO_ODR_HIGH) +IOEX(USB_C2_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C2_FRS_EN, EXPIN(IOEX_C2_NCT38XX, 0, 6), GPIO_LOW) +/* GPIO07_P2 to PU */ + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, 0) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */ +UNUSED(PIN(9, 7)) /* GPIO97 */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */ +UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */ +UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */ +UNUSED(PIN(0, 6)) /* KSO11/GPIO06/P80_CLK */ +UNUSED(PIN(0, 4)) /* KSO13/GPIO04 */ diff --git a/board/brask/i2c.c b/board/brask/i2c.c new file mode 100644 index 0000000000..b7666edc60 --- /dev/null +++ b/board/brask/i2c.c @@ -0,0 +1,77 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "dp_redriver", + .port = I2C_PORT_DP_REDRIVER, + .kbps = 400, + .scl = GPIO_EC_I2C_DP_SCL, + .sda = GPIO_EC_I2C_DP_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,2", + .port = I2C_PORT_USB_C0_C2_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,2", + .port = I2C_PORT_USB_C0_C2_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,2", + .port = I2C_PORT_USB_C0_C2_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + }, + { + /* I2C5 */ + .name = "wireless_charger", + .port = I2C_PORT_QI, + .kbps = 400, + .scl = GPIO_EC_I2C_QI_SCL, + .sda = GPIO_EC_I2C_QI_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/brask/led.c b/board/brask/led.c new file mode 100644 index 0000000000..b86a291625 --- /dev/null +++ b/board/brask/led.c @@ -0,0 +1,260 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Brask. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_GREEN, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int green = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_GREEN: + green = 1; + break; + case LED_RED: + red = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (green) + pwm_set_duty(PWM_CH_LED_GREEN, duty); + else + pwm_set_duty(PWM_CH_LED_GREEN, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* + * When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_GREEN); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* + * Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_GREEN, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "green")) { + set_color(id, LED_GREEN, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|red|green|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_GREEN] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_GREEN]) + return set_color(id, LED_GREEN, brightness[EC_LED_COLOR_GREEN]); + else + return set_color(id, LED_OFF, 0); +} +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Blink alert if insufficient power per system_can_boot_ap(). */ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + led_alert(insufficient_power); +} diff --git a/board/brask/pwm.c b/board/brask/pwm.c new file mode 100644 index 0000000000..35fc1f5a98 --- /dev/null +++ b/board/brask/pwm.c @@ -0,0 +1,39 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_GREEN] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN | PWM_CONFIG_DSLEEP, + .freq = 1000 }, + [PWM_CH_LED_RED] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * TODO(b/197478860): Turn on the fan at 100% by default + * We need to find tune the fan speed according to the + * thermal sensor value. + */ + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, 100); + + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_GREEN, 1); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/brask/sensors.c b/board/brask/sensors.c new file mode 100644 index 0000000000..c6b12a84bf --- /dev/null +++ b/board/brask/sensors.c @@ -0,0 +1,114 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_CPU] = { + .name = "TEMP_CPU", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CPU_VR] = { + .name = "TEMP_CPU_VR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_WIFI] = { + .name = "TEMP_WIFI", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DIMM] = { + .name = "TEMP_DIMM", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 872.3 mV/A */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT * 1433, + .factor_div = (ADC_READ_MAX + 1) * 1250, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_CPU] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_CPU }, + [TEMP_SENSOR_2_CPU_VR] = { .name = "CPU VR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CPU_VR }, + [TEMP_SENSOR_3_WIFI] = { .name = "WIFI", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_WIFI }, + [TEMP_SENSOR_4_DIMM] = { .name = "DIMM", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DIMM }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/197478860): add the thermal sensor setting + */ +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CPU] = THERMAL_CPU, + [TEMP_SENSOR_2_CPU_VR] = THERMAL_CPU, + [TEMP_SENSOR_3_WIFI] = THERMAL_CPU, + [TEMP_SENSOR_4_DIMM] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/brask/usbc_config.c b/board/brask/usbc_config.c new file mode 100644 index 0000000000..b28f6dc28d --- /dev/null +++ b/board/brask/usbc_config.c @@ -0,0 +1,416 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/retimer/kb800x.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc2_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +struct kb800x_control_t kb800x_control[] = { + [USBC_PORT_C0] = { + }, + [USBC_PORT_C1] = { + .retimer_rst_gpio = GPIO_USB_C1_RT_RST_R_L, + .ss_lanes = { + [KB800X_A0] = KB800X_TX0, [KB800X_A1] = KB800X_RX0, + [KB800X_B0] = KB800X_RX1, [KB800X_B1] = KB800X_TX1, + [KB800X_C0] = KB800X_RX0, [KB800X_C1] = KB800X_TX0, + [KB800X_D0] = KB800X_TX1, [KB800X_D1] = KB800X_RX1, + } + }, + [USBC_PORT_C2] = { + }, +}; +BUILD_ASSERT(ARRAY_SIZE(kb800x_control) == USBC_PORT_COUNT); + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C2_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &kb800x_usb_mux_driver, + .i2c_port = I2C_PORT_USB_C1_MUX, + .i2c_addr_flags = KB800X_I2C_ADDR0_FLAGS, + }, + .next = &usbc1_tcss_usb_mux, + }, + [USBC_PORT_C2] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C2, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C2_MUX, + .i2c_addr_flags = USBC_PORT_C2_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc2_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C2_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = IOEX_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C2) { + rst_signal = IOEX_USB_C2_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +__override int bb_retimer_reset(const struct usb_mux *me) +{ + /* + * TODO(b/193402306, b/195375738): Remove this once transition to + * QS Silicon is complete + */ + bb_retimer_power_enable(me, false); + msleep(5); + bb_retimer_power_enable(me, true); + msleep(25); + + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + enum gpio_signal tcpc_rst; + + tcpc_rst = GPIO_USB_C0_C2_TCPC_RST_ODL; + + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(tcpc_rst, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_L, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(tcpc_rst, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_L, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void enable_ioex(int ioex) +{ + ioex_init(ioex); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C2 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + enable_ioex(IOEX_C0_NCT38XX); + enable_ioex(IOEX_C2_NCT38XX); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); + + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_2; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C2) + return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C2_BC12_INT_ODL: + usb_charger_task_set_event(2, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + case GPIO_USB_C2_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return true; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/brask/usbc_config.h b/board/brask/usbc_config.h new file mode 100644 index 0000000000..0d4f62651a --- /dev/null +++ b/board/brask/usbc_config.h @@ -0,0 +1,20 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 3 + +enum usbc_port { + USBC_PORT_C0 = 0, + USBC_PORT_C1, + USBC_PORT_C2, + USBC_PORT_COUNT +}; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/brask/vif_override.xml b/board/brask/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/brask/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/brya/battery.c b/board/brya/battery.c new file mode 100644 index 0000000000..71b46082d8 --- /dev/null +++ b/board/brya/battery.c @@ -0,0 +1,109 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Brya battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* POW-TECH GQA05 Battery Information */ + [BATTERY_POWER_TECH] = { + /* BQ40Z50 Fuel Gauge */ + .fuel_gauge = { + .manuf_name = "POW-TECH", + .device_name = "BATGQA05L22", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x00, + .reg_mask = 0x2000, /* XDSG */ + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = TARGET_WITH_MARGIN(13050, 5), + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 280, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + /* LGC L17L3PB0 Battery Information */ + /* + * Battery info provided by ODM on b/143477210, comment #11 + */ + [BATTERY_LGC011] = { + .fuel_gauge = { + .manuf_name = "LGC", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = TARGET_WITH_MARGIN(13200, 5), + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = 0, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_POWER_TECH; + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} diff --git a/board/brya/board.c b/board/brya/board.c new file mode 100644 index 0000000000..66c25e0641 --- /dev/null +++ b/board/brya/board.c @@ -0,0 +1,58 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "button.h" +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "driver/als_tcs3400.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +__override void board_cbi_init(void) +{ + config_usb_db_type(); +} + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + + if (IS_ENABLED(CONFIG_PWM_KBLIGHT)) + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + + if (IS_ENABLED(CONFIG_PWM_KBLIGHT)) + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); diff --git a/board/brya/board.h b/board/brya/board.h new file mode 100644 index 0000000000..8b0aceb93b --- /dev/null +++ b/board/brya/board.h @@ -0,0 +1,267 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* + * Early brya boards are not set up for vivaldi + */ +#undef CONFIG_KEYBOARD_VIVALDI + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* LED */ +#define CONFIG_LED_PWM +#define CONFIG_LED_PWM_COUNT 2 +#undef CONFIG_LED_PWM_NEAR_FULL_COLOR +#undef CONFIG_LED_PWM_SOC_ON_COLOR +#undef CONFIG_LED_PWM_SOC_SUSPEND_COLOR +#undef CONFIG_LED_PWM_LOW_BATT_COLOR +#define CONFIG_LED_PWM_NEAR_FULL_COLOR EC_LED_COLOR_WHITE +#define CONFIG_LED_PWM_SOC_ON_COLOR EC_LED_COLOR_WHITE +#define CONFIG_LED_PWM_SOC_SUSPEND_COLOR EC_LED_COLOR_WHITE +#define CONFIG_LED_PWM_LOW_BATT_COLOR EC_LED_COLOR_AMBER + +/* Sensors */ +#define CONFIG_ACCELGYRO_LSM6DSO /* Base accel */ +#define CONFIG_ACCEL_LSM6DSO_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* TCS3400 ALS */ +#define CONFIG_ALS +#define ALS_COUNT 1 +#define CONFIG_ALS_TCS3400 +#define CONFIG_ALS_TCS3400_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensors without hardware interrupt are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(CLEAR_ALS) + +/* Lid accel */ +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_ACCEL_LIS2DWL +#define CONFIG_ACCEL_LIS2DW12_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USB_PD_FRS_PPC + +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID +#define CONFIG_USBC_RETIMER_INTEL_BB + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_NX20P3483 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_C2_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_C2_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* + * see b/174768555#comment22 + */ +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C2_BB_RETIMER_I2C_ADDR 0x57 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_BQ25720 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 70 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_BQ25710_PSYS_SENSING + +/* + * Older boards have a different ADC assignment. + */ + +#define CONFIG_ADC_CHANNELS_RUNTIME_CONFIG + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_AMBIENT, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_TEMP_SENSOR_4_WWAN, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_AMBIENT, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_4_WWAN, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + CLEAR_ALS, + RGB_ALS, + SENSOR_COUNT +}; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C2_NCT38XX, IOEX_PORT_COUNT }; + +enum battery_type { BATTERY_POWER_TECH, BATTERY_LGC011, BATTERY_TYPE_COUNT }; + +enum pwm_channel { + PWM_CH_LED2 = 0, /* PWM0 (white charger) */ + PWM_CH_LED3, /* PWM1 (orange on DB) */ + PWM_CH_LED1, /* PWM2 (orange charger) */ + PWM_CH_KBLIGHT, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED4, /* PWM7 (white on DB) */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/brya/build.mk b/board/brya/build.mk new file mode 100644 index 0000000000..bc3e3cd31e --- /dev/null +++ b/board/brya/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/brya/charger.c b/board/brya/charger.c new file mode 100644 index 0000000000..827152e115 --- /dev/null +++ b/board/brya/charger.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/brya/ec.tasklist b/board/brya/ec.tasklist new file mode 100644 index 0000000000..3b94575196 --- /dev/null +++ b/board/brya/ec.tasklist @@ -0,0 +1,32 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P2, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C2, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(2) | BIT(0)), BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/brya/fans.c b/board/brya/fans.c new file mode 100644 index 0000000000..ff8f27c69e --- /dev/null +++ b/board/brya/fans.c @@ -0,0 +1,89 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/181271666): thermistor placement and calibration + * + * Prototype fan spins at about 4200 RPM at 100% PWM, this + * is specific to board ID 2 and might also apears in later + * boards as well. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2200, + .rpm_start = 2200, + .rpm_max = 4200, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/181271666): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/brya/fw_config.c b/board/brya/fw_config.c new file mode 100644 index 0000000000..3a4c91acf1 --- /dev/null +++ b/board/brya/fw_config.c @@ -0,0 +1,46 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union brya_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brya if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union brya_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_PS8815, + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Brya FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union brya_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void) +{ + return fw_config.usb_db; +} diff --git a/board/brya/fw_config.h b/board/brya/fw_config.h new file mode 100644 index 0000000000..fea6c9a8da --- /dev/null +++ b/board/brya/fw_config.h @@ -0,0 +1,54 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_BRYA_FW_CONFIG_H_ +#define __BOARD_BRYA_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Brya board. + * + * Source of truth is the project/brya/brya/config.star configuration file. + */ + +enum ec_cfg_usb_db_type { + DB_USB_ABSENT = 0, + DB_USB3_PS8815 = 1, + DB_USB_ABSENT2 = 15 +}; + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +union brya_cbi_fw_config { + struct { + enum ec_cfg_usb_db_type usb_db : 4; + uint32_t sd_db : 2; + uint32_t lte_db : 1; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t reserved_1 : 21; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union brya_cbi_fw_config get_fw_config(void); + +/** + * Get the USB daughter board type from FW_CONFIG. + * + * @return the USB daughter board type. + */ +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void); + +#endif /* __BOARD_BRYA_FW_CONFIG_H_ */ diff --git a/board/brya/generated-gpio.inc b/board/brya/generated-gpio.inc new file mode 100644 index 0000000000..f4772188a5 --- /dev/null +++ b/board/brya/generated-gpio.inc @@ -0,0 +1,125 @@ +/* + * This file was auto-generated. + */ + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_ACCEL_INT_R_L, PIN(8, 1), GPIO_SEL_1P8V | GPIO_INT_FALLING, lis2dw12_interrupt) +GPIO_INT(EC_ALS_RGB_INT_R_L, PIN(D, 4), GPIO_INT_FALLING, tcs3400_interrupt) +GPIO_INT(EC_IMU_INT_R_L, PIN(5, 6), GPIO_SEL_1P8V | GPIO_INT_FALLING, lsm6dso_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C2_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C2_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C2_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_C2_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RST_ODL, PIN(9, 6), GPIO_ODR_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(6, 0x01), 0, MODULE_PWM, 0) /* GPIO60/PWM7 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x1c), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0, GPIOC2/PWM1/I2C6_SCL0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ + +/* Pre-configured PSL balls: J8 K6 */ diff --git a/board/brya/gpio.inc b/board/brya/gpio.inc new file mode 100644 index 0000000000..d68dfc4dd0 --- /dev/null +++ b/board/brya/gpio.inc @@ -0,0 +1,43 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* + * Generated-gpio.inc is produced using a Brya specific tool that + * parses the GPIO definitions derived from the board schematics and + * EC pinout descriptions derived form the chip datasheets to generate + * the Chrome EC GPIO pinout definitions. Due to the confidential + * nature of schematics and datasheets, they are not provided here. + * + * Variants that do not auto-generate their GPIO definitions should + * combine the Brya gpio.inc and generated-gpio.inc into their + * gpio.inc and customize as appropriate. + */ + +#include "generated-gpio.inc" + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* IO expander configuration */ + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C2_RT_RST_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 3), GPIO_ODR_HIGH) +IOEX(USB_C2_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C2_FRS_EN, EXPIN(IOEX_C2_NCT38XX, 0, 6), GPIO_OUT_LOW) +/* GPIO07_P2 to PU */ diff --git a/board/brya/i2c.c b/board/brya/i2c.c new file mode 100644 index 0000000000..feed4023d7 --- /dev/null +++ b/board/brya/i2c.c @@ -0,0 +1,81 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "hooks.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,2", + .port = I2C_PORT_USB_C0_C2_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,2", + .port = I2C_PORT_USB_C0_C2_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,2", + .port = I2C_PORT_USB_C0_C2_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/brya/keyboard.c b/board/brya/keyboard.c new file mode 100644 index 0000000000..156d4b49dd --- /dev/null +++ b/board/brya/keyboard.c @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; diff --git a/board/brya/led.c b/board/brya/led.c new file mode 100644 index 0000000000..80814523e7 --- /dev/null +++ b/board/brya/led.c @@ -0,0 +1,90 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya specific PWM LED settings: there are 2 LEDs on each side of the board, + * each one can be controlled separately. The LED colors are white or amber, + * and the default behavior is tied to the charging process: both sides are + * amber while charging the battery and white when the battery is charged. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "ec_commands.h" +#include "led_pwm.h" +#include "pwm.h" +#include "util.h" + +#include + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +/* + * We only have a white and an amber LED, so setting any other color results in + * both LEDs being off. Cap at 50% to save power. + */ +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Amber, White */ + [EC_LED_COLOR_RED] = { 0, 0 }, [EC_LED_COLOR_GREEN] = { 0, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0 }, [EC_LED_COLOR_YELLOW] = { 0, 0 }, + [EC_LED_COLOR_WHITE] = { 0, 50 }, [EC_LED_COLOR_AMBER] = { 50, 0 }, +}; + +/* Two logical LEDs with amber and white channels. */ +struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = { + { + .ch0 = PWM_CH_LED1, + .ch1 = PWM_CH_LED2, + .ch2 = PWM_LED_NO_CHANNEL, + .enable = &pwm_enable, + .set_duty = &pwm_set_duty, + }, + { + .ch0 = PWM_CH_LED3, + .ch1 = PWM_CH_LED4, + .ch2 = PWM_LED_NO_CHANNEL, + .enable = &pwm_enable, + .set_duty = &pwm_set_duty, + }, +}; + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + memset(brightness_range, '\0', + sizeof(*brightness_range) * EC_LED_COLOR_COUNT); + brightness_range[EC_LED_COLOR_AMBER] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + enum pwm_led_id pwm_id; + + /* Convert ec_led_id to pwm_led_id. */ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + pwm_id = PWM_LED0; + break; + case EC_LED_ID_RIGHT_LED: + pwm_id = PWM_LED1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (brightness[EC_LED_COLOR_WHITE]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); + else + /* Otherwise, the "color" is "off". */ + set_pwm_led_color(pwm_id, -1); + + return EC_SUCCESS; +} diff --git a/board/brya/pwm.c b/board/brya/pwm.c new file mode 100644 index 0000000000..dad5d5c444 --- /dev/null +++ b/board/brya/pwm.c @@ -0,0 +1,70 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED2] = { + .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_LED3] = { + .channel = 1, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_LED1] = { + .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 12000, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000, + }, + [PWM_CH_LED4] = { + .channel = 7, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn off all the LEDs. + * Turn on the fan at 100%. + */ + pwm_enable(PWM_CH_LED1, 1); + pwm_set_duty(PWM_CH_LED1, 0); + pwm_enable(PWM_CH_LED2, 1); + pwm_set_duty(PWM_CH_LED2, 0); + pwm_enable(PWM_CH_LED3, 1); + pwm_set_duty(PWM_CH_LED3, 0); + pwm_enable(PWM_CH_LED4, 1); + pwm_set_duty(PWM_CH_LED4, 0); + + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/brya/sensors.c b/board/brya/sensors.c new file mode 100644 index 0000000000..5868ba12ef --- /dev/null +++ b/board/brya/sensors.c @@ -0,0 +1,392 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc.h" +#include "common.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "driver/als_tcs3400_public.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_AMBIENT] = { + .name = "TEMP_AMBIENT", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_WWAN] = { + .name = "TEMP_WWAN", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +static struct stprivate_data g_lis2dw12_data; +static struct lsm6dso_data lsm6dso_data; + +/* TODO(b/184779333): calibrate the orientation matrix on later board stage */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* TODO(b/184779743): verify orientation matrix */ +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* TCS3400 private data */ +static struct als_drv_data_t g_tcs3400_data = { + .als_cal.scale = 1, + .als_cal.uscale = 0, + .als_cal.offset = 0, + .als_cal.channel_scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ + .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */ + }, +}; + +/* + * TODO: b/184702900 need to calibrate ALS/RGB sensor. At default settings, + * shining phone flashlight on sensor pegs all readings at 0xFFFF. + */ +static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { + .calibration.rgb_cal[X] = { + .offset = 0, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(1.0), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + } + }, + .calibration.rgb_cal[Y] = { + .offset = 0, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(1.0), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + }, + .calibration.rgb_cal[Z] = { + .offset = 0, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(1.0), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + } + }, + .calibration.irt = INT_TO_FP(1), + .saturation.again = TCS_DEFAULT_AGAIN, + .saturation.atime = TCS_DEFAULT_ATIME, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DW12, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_lis2dw12_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DW12_ADDR0, + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + }, + + [CLEAR_ALS] = { + .name = "Clear Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &tcs3400_drv, + .drv_data = &g_tcs3400_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + .min_frequency = TCS3400_LIGHT_MIN_FREQ, + .max_frequency = TCS3400_LIGHT_MAX_FREQ, + .config = { + /* Run ALS sensor in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 1000, + }, + }, + }, + + [RGB_ALS] = { + /* + * RGB channels read by CLEAR_ALS and so the i2c port and + * address do not need to be defined for RGB_ALS. + */ + .name = "RGB Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT_RGB, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &tcs3400_rgb_drv, + .drv_data = &g_tcs3400_rgb_data, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ +const struct motion_sensor_t *motion_als_sensors[] = { + &motion_sensors[CLEAR_ALS], +}; +BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); + +static void baseboard_sensors_init(void) +{ + /* Enable gpio interrupt for lid accel sensor */ + gpio_enable_interrupt(GPIO_EC_ACCEL_INT_R_L); + /* Enable interrupt for the TCS3400 color light sensor */ + gpio_enable_interrupt(GPIO_EC_ALS_RGB_INT_R_L); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_R_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { + .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC, + }, + [TEMP_SENSOR_2_AMBIENT] = { + .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_AMBIENT, + }, + [TEMP_SENSOR_3_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER, + }, + [TEMP_SENSOR_4_WWAN] = { + .name = "WWAN", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_WWAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Alder Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_AMBIENT \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_ambient = + THERMAL_AMBIENT; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 125C, max absolute temperature 150C + * PP3300 regulator: operating range -40 C to 125 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(105), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(120), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(65), \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +/* + * TODO(b/180681346): update for brya WWAN module + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_WWAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(130), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(130), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(100), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_wwan = + THERMAL_WWAN; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_AMBIENT] = THERMAL_AMBIENT, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, + [TEMP_SENSOR_4_WWAN] = THERMAL_WWAN, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/brya/usbc_config.c b/board/brya/usbc_config.c new file mode 100644 index 0000000000..fbec72f20b --- /dev/null +++ b/board/brya/usbc_config.c @@ -0,0 +1,524 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +#ifdef CONFIG_ZEPHYR +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C2_NCT38XX, IOEX_PORT_COUNT }; +#endif /* CONFIG_ZEPHYR */ + +#ifndef CONFIG_ZEPHYR +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_VCONN | + TCPC_FLAGS_CONTROL_FRS, + }, + [USBC_PORT_C2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); +#endif /* !CONFIG_ZEPHYR */ + +/******************************************************************************/ +/* USB-A charging control */ + +#ifndef CONFIG_ZEPHYR +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +#endif +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +#ifndef CONFIG_ZEPHYR +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM5360A */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = NX20P3483_ADDR2_FLAGS, + .drv = &nx20p348x_drv, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .frs_en = IOEX_USB_C2_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc2_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +/* + * USB3 DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .flags = USB_MUX_FLAG_CAN_IDLE, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C2_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, + [USBC_PORT_C2] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C2, + .flags = USB_MUX_FLAG_CAN_IDLE, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C2_MUX, + .i2c_addr_flags = USBC_PORT_C2_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc2_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C2_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); +#endif /* !CONFIG_ZEPHYR */ + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +void config_usb_db_type(void) +{ + enum ec_cfg_usb_db_type db_type = ec_cfg_usb_db_type(); + + /* + * TODO(b/180434685): implement multiple DB types + */ + + CPRINTS("Configured USB DB type number is %d", db_type); +} + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { +/* TODO: explore how to handle board id in zephyr*/ +#ifndef CONFIG_ZEPHYR + rst_signal = IOEX_USB_C0_RT_RST_ODL; +#else + /* On Zephyr use bb_controls generated from DTS */ + rst_signal = bb_controls[me->usb_port].retimer_rst_gpio; +#endif /* !CONFIG_ZEPHYR */ + } else if (me->usb_port == USBC_PORT_C2) { +/* TODO: explore how to handle board id in zephyr*/ +#ifndef CONFIG_ZEPHYR + rst_signal = IOEX_USB_C2_RT_RST_ODL; +#else + /* On Zephyr use bb_controls generated from DTS */ + rst_signal = bb_controls[me->usb_port].retimer_rst_gpio; +#endif /* !CONFIG_ZEPHYR */ + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + enum gpio_signal tcpc_rst; + +#ifndef CONFIG_ZEPHYR + tcpc_rst = GPIO_USB_C0_C2_TCPC_RST_ODL; +#else + tcpc_rst = GPIO_UNIMPLEMENTED; +#endif /* !CONFIG_ZEPHYR */ + + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(tcpc_rst, 0); + if (ec_cfg_usb_db_type() != DB_USB_ABSENT) { + gpio_set_level(GPIO_USB_C1_RST_ODL, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + } + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(tcpc_rst, 1); + if (ec_cfg_usb_db_type() != DB_USB_ABSENT) { + gpio_set_level(GPIO_USB_C1_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + } + + /* wait for chips to come up */ + + msleep(50); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C2 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ +#ifndef CONFIG_ZEPHYR + ioex_init(IOEX_C0_NCT38XX); + ioex_init(IOEX_C2_NCT38XX); +#else + gpio_reset_port(DEVICE_DT_GET(DT_NODELABEL(ioex_port1))); + gpio_reset_port(DEVICE_DT_GET(DT_NODELABEL(ioex_port2))); +#endif + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); + +#ifndef CONFIG_ZEPHYR + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_BC12_INT_ODL); +#endif /* !CONFIG_ZEPHYR */ + + if (ec_cfg_usb_db_type() != DB_USB_ABSENT) { + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); +#ifndef CONFIG_ZEPHYR + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +#else + } else { + tcpc_config[1].irq_gpio.port = NULL; +#endif /* !CONFIG_ZEPHYR */ + } +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +#ifndef CONFIG_ZEPHYR +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_2; + + if ((ec_cfg_usb_db_type() != DB_USB_ABSENT) && + gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} +#endif + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if ((port == USBC_PORT_C1) && + (ec_cfg_usb_db_type() != DB_USB_ABSENT)) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C2) + return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; + return 0; +} + +#ifndef CONFIG_ZEPHYR +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + if (ec_cfg_usb_db_type() == DB_USB_ABSENT) + break; + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} +#endif + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + if (ec_cfg_usb_db_type() == DB_USB_ABSENT) + break; + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C2_BC12_INT_ODL: + usb_charger_task_set_event(2, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + switch (ec_cfg_usb_db_type()) { + case DB_USB_ABSENT: + case DB_USB_ABSENT2: + break; + case DB_USB3_PS8815: + nx20p348x_interrupt(USBC_PORT_C1); + break; + } + break; + case GPIO_USB_C2_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + if (port == USBC_PORT_C0 || port == USBC_PORT_C2) + return true; + + return false; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/brya/usbc_config.h b/board/brya/usbc_config.h new file mode 100644 index 0000000000..bff89438d4 --- /dev/null +++ b/board/brya/usbc_config.h @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#ifndef CONFIG_ZEPHYR +#define CONFIG_USB_PD_PORT_MAX_COUNT 3 +#endif + +enum usbc_port { + USBC_PORT_C0 = 0, + USBC_PORT_C1, + USBC_PORT_C2, + USBC_PORT_COUNT +}; + +void config_usb_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/brya/vif_override.xml b/board/brya/vif_override.xml new file mode 100644 index 0000000000..6ade5d2f92 --- /dev/null +++ b/board/brya/vif_override.xml @@ -0,0 +1,148 @@ + + + 2 + 0 + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 9A1B + + + + + + Gen 3 (40Gb) + + + + USB 3.2 Gen 2x2 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + + + + + + USB 3.2 Gen 2x1 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PSD + PDUSB Host + + + + + Gen 3 (40Gb) + + USB 3.2 Gen 2x2 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + diff --git a/board/bugzzy/battery.c b/board/bugzzy/battery.c new file mode 100644 index 0000000000..2df4848d05 --- /dev/null +++ b/board/bugzzy/battery.c @@ -0,0 +1,134 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" +#include "hooks.h" +#include "usb_pd.h" +#include "util.h" + +/* + * Battery info for all bugzzy battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + * + * Battery FET Status in Manufacture Access : bit15 & bit14 + * b'00 - dfet : on / cfet : on + * b'01 - dfet : on / cfet : off + * b'10 - dfet : off / cfet : off + * b'11 - dfet : off / cfet : on + * The value b'10 is disconnect_val, so we can use b'01 for cfet_off_val + */ + +/* charging current is limited to 0.45C */ +#define CHARGING_CURRENT_45C 2601 + +const struct board_batt_params board_battery_info[] = { + /* SDI Battery Information */ + [BATTERY_SDI] = { + .fuel_gauge = { + .manuf_name = "SDI", + .device_name = "4404D57", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0xc000, + .disconnect_val = 0x8000, + .cfet_mask = 0xc000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 8700, + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 55, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SDI; + +int charger_profile_override(struct charge_state_data *curr) +{ + if ((chipset_in_state(CHIPSET_STATE_ON)) && + (curr->requested_current > CHARGING_CURRENT_45C)) + curr->requested_current = CHARGING_CURRENT_45C; + + return 0; +} + +/* Customs options controllable by host command. */ +#define PARAM_FASTCHARGE (CS_PARAM_CUSTOM_PROFILE_MIN + 0) + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +/* Lower our input voltage to 5V in S0iX when battery is full. */ +#define PD_VOLTAGE_WHEN_FULL 5000 +static void reduce_input_voltage_when_full(void) +{ + static int saved_input_voltage = -1; + int max_pd_voltage_mv = pd_get_max_voltage(); + int port; + + if (charge_get_percent() == 100 && + chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + if (max_pd_voltage_mv != PD_VOLTAGE_WHEN_FULL) { + saved_input_voltage = max_pd_voltage_mv; + max_pd_voltage_mv = PD_VOLTAGE_WHEN_FULL; + } + } else if (saved_input_voltage != -1) { + if (max_pd_voltage_mv == PD_VOLTAGE_WHEN_FULL) + max_pd_voltage_mv = saved_input_voltage; + saved_input_voltage = -1; + } + + if (pd_get_max_voltage() != max_pd_voltage_mv) { + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, max_pd_voltage_mv); + } +} +DECLARE_HOOK(HOOK_SECOND, reduce_input_voltage_when_full, HOOK_PRIO_DEFAULT); diff --git a/board/bugzzy/board.c b/board/bugzzy/board.c new file mode 100644 index 0000000000..5102db15be --- /dev/null +++ b/board/bugzzy/board.c @@ -0,0 +1,906 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "cros_board_info.h" +#include "driver/accel_lis2ds.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/ps8743.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_8042.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "power.h" +#include "power_button.h" +#include "stdbool.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void sub_usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + int hdmi_hpd_odl = gpio_get_level(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, !hdmi_hpd_odl); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3] = { + .name = "TEMP_SENSOR3", + .input_ch = NPCX_ADC_CH5, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4] = { + .name = "TEMP_SENSOR4", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SUB_ANALOG] = { + .name = "SUB_ANALOG", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Skin1", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "Skin2", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +static int board_id = -1; + +void board_init(void) +{ + int on; + + /* Enable C0 interrupt and check if it needs processing */ + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + check_c0_line(); + + if (get_cbi_fw_config_db() == DB_1A_HDMI) { + /* Disable i2c on HDMI pins */ + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, + 0); + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, + 0); + + /* Set HDMI and sub-rail enables to output */ + gpio_set_flags(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, + chipset_in_state(CHIPSET_STATE_ON) ? + GPIO_ODR_LOW : + GPIO_ODR_HIGH); + gpio_set_flags(GPIO_SUB_C1_INT_EN_RAILS_ODL, GPIO_ODR_HIGH); + + /* Select HDMI option */ + gpio_set_level(GPIO_HDMI_SEL_L, 0); + + /* Enable interrupt for passing through HPD */ + gpio_enable_interrupt(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + } else { + /* Set SDA as an input */ + gpio_set_flags(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, GPIO_INPUT); + + /* Enable C1 interrupt and check if it needs processing */ + gpio_enable_interrupt(GPIO_SUB_C1_INT_EN_RAILS_ODL); + check_c1_line(); + } + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Enable HDMI any time the SoC is on */ +static void hdmi_enable(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + gpio_set_level(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, hdmi_enable, HOOK_PRIO_DEFAULT); + +static void hdmi_disable(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + gpio_set_level(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, hdmi_disable, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(1, true); + raa489000_hibernate(0, false); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +static void set_5v_gpio(int level) +{ + gpio_set_level(GPIO_EN_PP5000, level); +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC, or send enable signal to HDMI + * DB. + */ + set_5v_gpio(!!enable); + + if (get_cbi_fw_config_db() == DB_1A_HDMI) { + gpio_set_level(GPIO_SUB_C1_INT_EN_RAILS_ODL, !enable); + } else { + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", + enable ? "en" : "dis"); + } +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; + else + return CONFIG_USB_PD_PORT_MAX_COUNT; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + return CHARGER_NUM - 1; + else + return CHARGER_NUM; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +/* Sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref_lsm = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t ldm6dsm_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_lsm, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; +struct motion_sensor_t ldm6dsm_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref_lsm, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + +}; + +static struct stprivate_data g_lis2ds_data; +static struct bmi_drv_data_t g_bmi160_data; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DS, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2ds_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2ds_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DS_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = LIS2DS_ODR_MIN_VAL, + .max_frequency = LIS2DS_ODR_MAX_VAL, + .default_range = 2, /* g, to support lid angle calculation. */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI160 = 1, + BASE_GYRO_LSM6DSM = 2, +}; + +static enum base_accelgyro_type base_accelgyro_config; +static void board_set_motionsensor(void) +{ + if (board_id == -1) { + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS) + board_id = val; + } + + base_accelgyro_config = BASE_GYRO_BMI160; + if (board_id > 6) { + motion_sensors[BASE_ACCEL] = ldm6dsm_base_accel; + motion_sensors[BASE_GYRO] = ldm6dsm_base_gyro; + base_accelgyro_config = BASE_GYRO_LSM6DSM; + } +} +DECLARE_HOOK(HOOK_INIT, board_set_motionsensor, HOOK_PRIO_INIT_I2C + 2); + +void motion_interrupt(enum gpio_signal signal) +{ + if (base_accelgyro_config == BASE_GYRO_BMI160) + bmi160_interrupt(signal); + else + lsm6dsm_interrupt(signal); +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, + + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +static int ps8743_tune_mux_c0(const struct usb_mux *me); +static int ps8743_tune_mux_c1(const struct usb_mux *me); + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PS8743_I2C_ADDR0_FLAG, + .driver = &ps8743_usb_mux_driver, + .board_init = &ps8743_tune_mux_c0, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8743_I2C_ADDR0_FLAG, + .driver = &ps8743_usb_mux_driver, + .board_init = &ps8743_tune_mux_c1, + }, + } +}; +/* USB Mux C0 : board_init of PS8743 */ +static int ps8743_tune_mux_c0(const struct usb_mux *me) +{ + ps8743_tune_usb_eq(me, PS8743_USB_EQ_TX_3_6_DB, + PS8743_USB_EQ_RX_16_0_DB); + + return EC_SUCCESS; +} +/* USB Mux C1 : board_init of PS8743 */ +static int ps8743_tune_mux_c1(const struct usb_mux *me) +{ + ps8743_tune_usb_eq(me, PS8743_USB_EQ_TX_3_6_DB, + PS8743_USB_EQ_RX_16_0_DB); + + ps8743_write(me, PS8743_REG_USB_SWING, PS8743_LFPS_SWG_TD); + ps8743_write(me, PS8743_REG_DP_SETTING, PS8743_DP_SWG_ADJ_P15P); + + return EC_SUCCESS; +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + if (board_get_usb_pd_port_count() > 1 && + !gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + /* TCPCI spec Rev 1.0 says to ignore bits 14:12. */ + if (!(tcpc_config[1].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} +static const struct ec_response_keybd_config keybd1 = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad, has screenlock key */ + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + /* + * Future boards should use fw_config if needed. + */ + + return &keybd1; +} + +#ifndef TEST_BUILD +/* This callback disables keyboard when convertibles are fully open */ +void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} +#endif +/** + * Enable panel power detection + */ +static void panel_power_detect_init(void) +{ + gpio_enable_interrupt(GPIO_EN_PP1800_PANEL_S0); +} +DECLARE_HOOK(HOOK_INIT, panel_power_detect_init, HOOK_PRIO_DEFAULT); + +/** + * Handle VPN / VSN for mipi display. + */ +static void panel_power_change_deferred(void) +{ + int signal = gpio_get_level(GPIO_EN_PP1800_PANEL_S0); + + if (board_id == -1) { + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS) + board_id = val; + } + if (board_id < 4) { + gpio_set_level(GPIO_EN_LCD_ENP, signal); + msleep(1); + gpio_set_level(GPIO_EN_LCD_ENN, signal); + } else if (signal != 0) { + i2c_write8(I2C_PORT_LCD, I2C_ADDR_ISL98607_FLAGS, + ISL98607_REG_VBST_OUT, ISL98607_VBST_OUT_5P65); + i2c_write8(I2C_PORT_LCD, I2C_ADDR_ISL98607_FLAGS, + ISL98607_REG_VN_OUT, ISL98607_VN_OUT_5P5); + i2c_write8(I2C_PORT_LCD, I2C_ADDR_ISL98607_FLAGS, + ISL98607_REG_VP_OUT, ISL98607_VP_OUT_5P5); + } + gpio_set_level(GPIO_TSP_TA, signal & extpower_is_present()); +} +DECLARE_DEFERRED(panel_power_change_deferred); + +void panel_power_change_interrupt(enum gpio_signal signal) +{ + /* Reset lid debounce time */ + hook_call_deferred(&panel_power_change_deferred_data, 1 * MSEC); +} + +/* + * Detect LCD reset & control LCD DCDC power + */ +static void lcd_reset_detect_init(void) +{ + if (board_id == -1) { + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS) + board_id = val; + } + + if (board_id < 4) + return; + gpio_enable_interrupt(GPIO_DDI0_DDC_SCL); +} +DECLARE_HOOK(HOOK_INIT, lcd_reset_detect_init, HOOK_PRIO_DEFAULT); +/* + * Handle VSP / VSN for mipi display when lcd turns off + */ +static void lcd_reset_change_deferred(void) +{ + int signal = gpio_get_level(GPIO_DDI0_DDC_SCL); + + if (signal != 0) + return; + + signal = gpio_get_level(GPIO_EN_PP1800_PANEL_S0); + + if (signal == 0) + return; + + i2c_write8(I2C_PORT_LCD, I2C_ADDR_ISL98607_FLAGS, ISL98607_REG_ENABLE, + ISL97607_VP_VN_VBST_DIS); +} +DECLARE_DEFERRED(lcd_reset_change_deferred); +void lcd_reset_change_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&lcd_reset_change_deferred_data, 45 * MSEC); +} + +/** + * Handle TSP_TA according to AC status + */ +static void handle_tsp_ta(void) +{ + int signal = gpio_get_level(GPIO_EN_PP1800_PANEL_S0); + + gpio_set_level(GPIO_TSP_TA, signal & extpower_is_present()); +} +DECLARE_HOOK(HOOK_AC_CHANGE, handle_tsp_ta, HOOK_PRIO_DEFAULT); + +/******************************************************************************/ +/* USB-A charging control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, +}; + +/* + * Change LED Driver Current + * LED driver current must be written when EN_BL_OD goes from Low to High. + */ +static int backup_enable_backlight = -1; +void backlit_gpio_tick(void) +{ + int signal = gpio_get_level(GPIO_ENABLE_BACKLIGHT); + + if (backup_enable_backlight == signal) + return; + + backup_enable_backlight = signal; + if (board_id == -1) { + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS) + board_id = val; + } + + if (board_id >= 4 && signal == 1) + i2c_write16(I2C_PORT_LCD, I2C_ADDR_MP3372_FLAGS, + MP3372_REG_ISET_CHEN, MP3372_ISET_15P3_CHEN_ALL); +} +DECLARE_HOOK(HOOK_TICK, backlit_gpio_tick, HOOK_PRIO_DEFAULT); diff --git a/board/bugzzy/board.h b/board/bugzzy/board.h new file mode 100644 index 0000000000..b62928b5e1 --- /dev/null +++ b/board/bugzzy/board.h @@ -0,0 +1,244 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_DEDEDE_EC_NPCX796FC +#include "baseboard.h" + +#undef CONFIG_I2C_DEBUG +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +/* Save some flash space */ +#define CONFIG_DEBUG_ASSERT_BRIEF +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_BATTFAKE + +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_CMD_CHARGER_DUMP + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +#define CONFIG_OCPC +#define CONFIG_CHARGE_RAMP_HW +#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 +#define CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS +#define CONFIG_CHARGER_PROFILE_OVERRIDE + +/* + * GPIO for C1 interrupts, for baseboard use + * + * Note this line might already have its pull up disabled for HDMI DBs, but + * it should be fine to set again before z-state. + */ +#define GPIO_USB_C1_INT_ODL GPIO_SUB_C1_INT_EN_RAILS_ODL + +/* Keyboard */ + +/* LED */ +#define CONFIG_LED_COMMON +#define CONFIG_LED_ONOFF_STATES +#define GPIO_BAT_LED_RED_L GPIO_LED_R_ODL +#define GPIO_BAT_LED_GREEN_L GPIO_LED_G_ODL +#define GPIO_PWR_LED_BLUE_L GPIO_LED_B_ODL + +/* PWM */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 +#define CONFIG_USB_MUX_PS8743 + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_RAA489000 +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +#define CONFIG_USB_PD_COMM_LOCKED + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +#undef PD_POWER_SUPPLY_TURN_ON_DELAY +#undef PD_POWER_SUPPLY_TURN_OFF_DELAY +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +/* 20% margin added for these timings */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 13080 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 16080 /* us */ +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +#define CONFIG_USBC_VCONN_SWAP_DELAY_US 787 /* us */ + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +#define I2C_PORT_LCD NPCX_I2C_PORT3_0 +/* TODO(b:147440290): Need to handle multiple charger ICs */ +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ +#define I2C_ADDR_ISL98607_FLAGS 0x29 +#define I2C_ADDR_MP3372_FLAGS 0x28 + +/* ISL98607 registers and value */ +/* Enable VP / VN / VBST */ +#define ISL98607_REG_ENABLE 0x05 +#define ISL98607_VP_VN_VBST_EN 0x07 +#define ISL97607_VP_VN_VBST_DIS 0x00 + +/* VBST Voltage Adjustment */ +#define ISL98607_REG_VBST_OUT 0x06 +#define ISL98607_VBST_OUT_5P65 0x0a + +/* VN Voltage Adjustment */ +#define ISL98607_REG_VN_OUT 0x08 +#define ISL98607_VN_OUT_5P5 0x0a + +/* VP Voltage Adjustment */ +#define ISL98607_REG_VP_OUT 0x09 +#define ISL98607_VP_OUT_5P5 0x0a + +/* MP3372 registers and value */ +/* ISET & CHEN */ +#define MP3372_REG_ISET_CHEN 0x00 +#define MP3372_ISET_21P8_CHEN_ALL 0x70ff +#define MP3372_ISET_19P4_CHEN_ALL 0x63ff +#define MP3372_ISET_18P0_CHEN_ALL 0x5cff +#define MP3372_ISET_15P8_CHEN_ALL 0x50ff +#define MP3372_ISET_15P3_CHEN_ALL 0x4eff +/* + * I2C pin names for baseboard + * + * Note: these lines will be set as i2c on start-up, but this should be + * okay since they're ODL. + */ +#define GPIO_EC_I2C_SUB_USB_C1_SCL GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL +#define GPIO_EC_I2C_SUB_USB_C1_SDA GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL + +/* Sensors */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ + +/* Lid operates in forced mode, base in interrupt mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH + +/* On-body detection */ +#define CONFIG_BODY_DETECTION +#define CONFIG_BODY_DETECTION_SENSOR BASE_ACCEL +#define CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR 150 /* % */ +#define CONFIG_GESTURE_DETECTION +#define CONFIG_GESTURE_DETECTION_MASK BIT(CONFIG_BODY_DETECTION_SENSOR) +#define CONFIG_GESTURE_HOST_DETECTION + +/* LIS2DS Lid accel */ +#define CONFIG_ACCEL_LIS2DS + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_4, + TEMP_SENSOR_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_3, /* ADC5 */ + ADC_TEMP_SENSOR_4, /* ADC6 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_SDI, + BATTERY_TYPE_COUNT, +}; + +void panel_power_change_interrupt(enum gpio_signal signal); +void lcd_reset_change_interrupt(enum gpio_signal signal); +void motion_interrupt(enum gpio_signal signal); +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/bugzzy/build.mk b/board/bugzzy/build.mk new file mode 100644 index 0000000000..5b37e085ef --- /dev/null +++ b/board/bugzzy/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=dedede + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/bugzzy/cbi_ssfc.c b/board/bugzzy/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/bugzzy/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/bugzzy/cbi_ssfc.h b/board/bugzzy/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/bugzzy/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/bugzzy/ec.tasklist b/board/bugzzy/ec.tasklist new file mode 100644 index 0000000000..29666dd959 --- /dev/null +++ b/board/bugzzy/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/bugzzy/gpio.inc b/board/bugzzy/gpio.inc new file mode 100644 index 0000000000..8e0fa56768 --- /dev/null +++ b/board/bugzzy/gpio.inc @@ -0,0 +1,140 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) +GPIO_INT(SUB_C1_INT_EN_RAILS_ODL, PIN(F, 5), GPIO_INT_FALLING | GPIO_PULL_UP, sub_usb_c1_interrupt) /* C1 interrupt OR 5V power en */ +GPIO_INT(EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, PIN(9, 1), GPIO_INT_BOTH, sub_hdmi_hpd_interrupt) /* C1 I2C SDA OR HDMI_HPD */ + +/* Button interrupts */ +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +GPIO_INT(VOLDN_BTN_ODL, PIN(4, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(7, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(EN_PP1800_PANEL_S0, PIN(4, 1), GPIO_INT_BOTH, panel_power_change_interrupt) +GPIO_INT(DDI0_DDC_SCL, PIN(6, 0), GPIO_INT_FALLING, lcd_reset_change_interrupt) + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, PIN(9, 2), GPIO_INPUT) /* C1 I2C SCL OR HDMI en */ +GPIO(EC_I2C_LCD_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_LCD_SDA, PIN(D, 0), GPIO_INPUT) + +/* Misc Enables */ +GPIO(LID_360_L, PIN(9, 5), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(IMVP9_PE, PIN(E, 0), GPIO_OUT_LOW) +GPIO(ECH1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(LED_R_ODL, PIN(C, 4), GPIO_OUT_HIGH) +GPIO(LED_G_ODL, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(LED_B_ODL, PIN(C, 2), GPIO_OUT_HIGH) +GPIO(EN_LCD_ENN, PIN(9, 7), GPIO_OUT_LOW) +GPIO(EN_LCD_ENP, PIN(8, 6), GPIO_OUT_LOW) +GPIO(TSP_TA, PIN(A, 2), GPIO_OUT_LOW) + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) + +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(7, 2), GPIO_OUT_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(EN_USB_A0_VBUS, PIN(6, 3), GPIO_OUT_LOW) + +/* + * Waddledoo doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* ADC0-2 */ +ALTERNATE(PIN_MASK(3, 0x90), 0, MODULE_ADC, 0) /* ADC5-6 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* I2C3 */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO00_NC, PIN(0, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO50_NC, PIN(5, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO80_NC, PIN(8, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_DOWN) diff --git a/board/bugzzy/led.c b/board/bugzzy/led.c new file mode 100644 index 0000000000..cad2d5ed0b --- /dev/null +++ b/board/bugzzy/led.c @@ -0,0 +1,156 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for bugzzy + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1 = 1; + +__override const int led_charge_lvl_2 = 100; + +/* bugzzy : There are 3 leds for AC, Battery and Power */ +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_BLUE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_power(enum ec_led_colors color) +{ + static enum ec_led_colors prev_color = EC_LED_COLOR_COUNT; + + /* Don't set led if led_auto_control is disabled. */ + if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + return; + } + + /* + * Sometimes system wakes and sleeps automatically. + * Add LED debounce time to prevent blinking led by this. + */ + if (prev_color != color) { + prev_color = color; + return; + } + + if (color == EC_LED_COLOR_BLUE) { + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_ON_LVL); + } else { + /* LED_OFF and unsupported colors */ + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); + } +} + +__override void led_set_color_battery(enum ec_led_colors color) +{ + static enum ec_led_colors prev_color = EC_LED_COLOR_COUNT; + + /* Don't set led if led_auto_control is disabled. */ + if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + return; + } + + /* + * Sometimes system wakes and sleeps automatically. + * Add LED debounce time to prevent blinking led by this. + */ + if (prev_color != color) { + prev_color = color; + return; + } + /* + * Battery leds must be turn off when blue led is on + * because bugzzy has 3-in-1 led. + */ + if (!gpio_get_level(GPIO_PWR_LED_BLUE_L)) { + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + return; + } + + switch (color) { + case EC_LED_COLOR_GREEN: + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_ON_LVL); /*green*/ + break; + case EC_LED_COLOR_RED: + gpio_set_level(GPIO_BAT_LED_RED_L, LED_ON_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_RED] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_GREEN_L, + !brightness[EC_LED_COLOR_GREEN]); + gpio_set_level(GPIO_BAT_LED_RED_L, + !brightness[EC_LED_COLOR_RED]); + } else if (led_id == EC_LED_ID_POWER_LED) { + gpio_set_level(GPIO_PWR_LED_BLUE_L, + !brightness[EC_LED_COLOR_BLUE]); + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); + } + + return EC_SUCCESS; +} diff --git a/board/bugzzy/usb_pd_policy.c b/board/bugzzy/usb_pd_policy.c new file mode 100644 index 0000000000..83c09bb99e --- /dev/null +++ b/board/bugzzy/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/bugzzy/vif_override.xml b/board/bugzzy/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/bugzzy/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/burnet/battery.c b/board/burnet/battery.c index 6373040d45..d76634d6ce 100644 --- a/board/burnet/battery.c +++ b/board/burnet/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,7 +9,7 @@ const struct board_batt_params board_battery_info[] = { /* Dynapack ATL Battery Information */ - [BATTERY_DANAPACK_ATL] = { + [BATTERY_DYNAPACK_ATL] = { .fuel_gauge = { .manuf_name = "333-27-DA-A", .ship_mode = { @@ -34,10 +34,11 @@ const struct board_batt_params board_battery_info[] = { .charging_max_c = 45, .discharging_min_c = -10, .discharging_max_c = 60, + .vendor_param_start = 0x70, }, }, /* Dynapack CosMX Battery Information */ - [BATTERY_DANAPACK_COS] = { + [BATTERY_DYNAPACK_COS] = { .fuel_gauge = { .manuf_name = "333-2C-DA-A", .ship_mode = { @@ -62,6 +63,7 @@ const struct board_batt_params board_battery_info[] = { .charging_max_c = 45, .discharging_min_c = -10, .discharging_max_c = 60, + .vendor_param_start = 0x70, }, }, /* Simplo CosMX Battery Information */ @@ -90,6 +92,7 @@ const struct board_batt_params board_battery_info[] = { .charging_max_c = 45, .discharging_min_c = -10, .discharging_max_c = 60, + .vendor_param_start = 0x70, }, }, /* Simplo HIGHPOWER Battery Information */ @@ -118,6 +121,7 @@ const struct board_batt_params board_battery_info[] = { .charging_max_c = 45, .discharging_min_c = -10, .discharging_max_c = 60, + .vendor_param_start = 0x70, }, }, /* Samsung SDI Battery Information */ @@ -146,6 +150,7 @@ const struct board_batt_params board_battery_info[] = { .charging_max_c = 45, .discharging_min_c = -10, .discharging_max_c = 60, + .vendor_param_start = 0x70, }, }, /* CosMX Battery Information */ @@ -174,12 +179,100 @@ const struct board_batt_params board_battery_info[] = { .charging_max_c = 45, .discharging_min_c = -10, .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* DynaPack CosMX DAK125720-W0P0701HT Battery Information */ + [BATTERY_DYNAPACK_COS_44WH] = { + .fuel_gauge = { + .manuf_name = "333-2C-DB-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* DynaPack ATL DAK125720-W0G0701HT Battery Information */ + [BATTERY_DYNAPACK_ATL_44WH] = { + .fuel_gauge = { + .manuf_name = "333-27-DB-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* Simplo HIGHPOWER 996Q4242H Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER_44WH] = { + .fuel_gauge = { + .manuf_name = "333-1D-DB-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, }, }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DANAPACK_ATL; +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_ATL; enum battery_present battery_hw_present(void) { diff --git a/board/burnet/board.c b/board/burnet/board.c index 18929f50d2..95fa8e2d85 100644 --- a/board/burnet/board.c +++ b/board/burnet/board.c @@ -1,10 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" #include "charge_manager.h" @@ -15,7 +14,10 @@ #include "common.h" #include "console.h" #include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" #include "driver/battery/max17055.h" #include "driver/bc12/pi3usb9201.h" #include "driver/charger/isl923x.h" @@ -32,6 +34,7 @@ #include "it8801.h" #include "keyboard_scan.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "registers.h" @@ -39,41 +42,55 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { schedule_deferred_pd_interrupt(0 /* port */); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct i2c_port_t i2c_bitbang_ports[] = { - {"battery", 2, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA, .drv = &bitbang_drv}, + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, }; const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); @@ -81,13 +98,13 @@ const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * TODO(b/133200075): Tune this once we have the final performance * out of the driver and the i2c bus. @@ -106,8 +123,8 @@ struct keyboard_scan_config keyscan_config = { struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { [0] = { - .i2c_host_port = I2C_PORT_IO_EXPANDER_IT8801, - .i2c_slave_addr = IT8801_I2C_ADDR, + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, .drv = &it8801_ioexpander_drv, }, }; @@ -132,15 +149,18 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -static void board_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -148,13 +168,16 @@ static void board_hpd_status(const struct usb_mux *me, host_set_single_event(EC_HOST_EVENT_USB_MUX); } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, }, }; @@ -184,7 +207,7 @@ int board_set_active_charge_port(int charge_port) if (board_vbus_source_enabled(charge_port)) return -1; break; - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -192,22 +215,11 @@ int board_set_active_charge_port(int charge_port) */ charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - int board_discharge_on_ac(int enable) { int ret, port; @@ -237,7 +249,7 @@ int pd_snk_is_vbus_provided(int port) void bc12_interrupt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } /* @@ -270,13 +282,12 @@ static void board_spi_enable(void) STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; /* Reinitialize spi peripheral. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); /* Pin mux spi peripheral toward the sensor. */ - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_spi_enable, +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, MOTION_SENSE_HOOK_PRIO - 1); static void board_spi_disable(void) @@ -284,14 +295,15 @@ static void board_spi_disable(void) /* Set pins to a state calming the sensor down. */ gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); - gpio_config_module(MODULE_SPI_MASTER, 0); + gpio_set_flags(GPIO_EC_SENSOR_SPI_NSS, GPIO_OUT_LOW); + gpio_set_level(GPIO_EC_SENSOR_SPI_NSS, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); /* Disable spi peripheral and clocks. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_spi_disable, +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, MOTION_SENSE_HOOK_PRIO + 1); #endif /* !VARIANT_KUKUI_NO_SENSORS */ @@ -302,21 +314,90 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Rotation matrixes */ -static const mat33_fp_t lid_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(-1), 0}, - {0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t base_standard_ref = { - {FLOAT_TO_FP(-1), 0, 0}, - {0, FLOAT_TO_FP(1), 0}, - {0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t base_bmi160_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_icm42607_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* sensor private data */ static struct accelgyro_saved_data_t g_bma253_data; +static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm42607_data; + +struct motion_sensor_t lid_accel_kx022 = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t base_accel_icm42607 = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .default_range = 4, + .rot_standard_ref = &base_icm42607_ref, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t base_gyro_icm42607 = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm42607_ref, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -358,9 +439,10 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), - .rot_standard_ref = &base_standard_ref, - .default_range = 2, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .i2c_spi_addr_flags = + ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .rot_standard_ref = &base_bmi160_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, .config = { @@ -386,15 +468,52 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = + ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ - .rot_standard_ref = &base_standard_ref, + .rot_standard_ref = &base_bmi160_ref, .min_frequency = BMI_GYRO_MIN_FREQ, .max_frequency = BMI_GYRO_MAX_FREQ, }, }; unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +void sensor_interrupt(enum gpio_signal signal) +{ + switch (motion_sensors[BASE_ACCEL].chip) { + case MOTIONSENSE_CHIP_ICM42607: + icm42607_interrupt(signal); + break; + case MOTIONSENSE_CHIP_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +static void board_update_config(void) +{ + int val; + enum ec_error_list rv; + + /* Ping for ack */ + rv = i2c_read8(I2C_PORT_SENSORS, KX022_ADDR1_FLAGS, KX022_WHOAMI, &val); + + if (rv == EC_SUCCESS) + motion_sensors[LID_ACCEL] = lid_accel_kx022; + + /* Read icm-42607 chip content */ + rv = icm_read8(&base_accel_icm42607, ICM42607_REG_WHO_AM_I, &val); + + if (rv == EC_SUCCESS && val == ICM42607_CHIP_ICM42607P) { + motion_sensors[BASE_ACCEL] = base_accel_icm42607; + motion_sensors[BASE_GYRO] = base_gyro_icm42607; + } + + CPRINTS("Lid Accel Chip: %d", motion_sensors[LID_ACCEL].chip); + CPRINTS("Base Accel Chip: %d", motion_sensors[BASE_ACCEL].chip); +} + #endif /* !VARIANT_KUKUI_NO_SENSORS */ static void board_init(void) @@ -414,13 +533,18 @@ static void board_init(void) motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Enable interrupts from BMI160 sensor. */ gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); - /* For some reason we have to do this again in case of sysjump */ + /* For some reason we have to do this again in case of sysjump + */ board_spi_enable(); + board_update_config(); } else { motion_sensor_count = 0; + /* Device is clamshell only */ + tablet_set_mode(0, TABLET_TRIGGER_LID); + /* Turn off GMR interrupt */ + gmr_tablet_switch_disable(); /* Base accel is not stuffed, don't allow line to float */ - gpio_set_flags(GPIO_ACCEL_INT_ODL, - GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_ACCEL_INT_ODL, GPIO_INPUT | GPIO_PULL_DOWN); board_spi_disable(); } #endif /* !VARIANT_KUKUI_NO_SENSORS */ @@ -446,25 +570,3 @@ static void board_chipset_shutdown(void) gpio_set_level(GPIO_EN_USBA_5V, 0); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); - -int battery_get_vendor_param(uint32_t param, uint32_t *value) -{ - int rv; - uint8_t data[16] = {}; - - /* only allow reading 0x70~0x7F, 16 byte data */ - if (param < 0x70 || param >= 0x80) - return EC_ERROR_ACCESS_DENIED; - - rv = sb_read_string(0x70, data, sizeof(data)); - if (rv) - return rv; - - *value = data[param - 0x70]; - return EC_SUCCESS; -} - -int battery_set_vendor_param(uint32_t param, uint32_t value) -{ - return EC_ERROR_UNIMPLEMENTED; -} diff --git a/board/burnet/board.h b/board/burnet/board.h index 898beb058b..6d6870da2b 100644 --- a/board/burnet/board.h +++ b/board/burnet/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,9 +8,13 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H +/* Free up flash space. */ +#undef CONFIG_CMD_KEYBOARD + #define VARIANT_KUKUI_JACUZZI #define VARIANT_KUKUI_BATTERY_SMART #define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32F098 #ifndef SECTION_IS_RW #define VARIANT_KUKUI_NO_SENSORS @@ -23,8 +27,12 @@ #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_BATTERY_VENDOR_PARAM +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 #define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_BC12_DETECT_PI3USB9201 @@ -44,18 +52,26 @@ #define CONFIG_USB_MUX_IT5205 +/* Disable verbose output in EC pd */ +#define CONFIG_CMD_PD_SRCCAPS_REDUCED_SIZE + /* Motion Sensors */ #ifndef VARIANT_KUKUI_NO_SENSORS -#define CONFIG_ACCEL_BMA255 /* Lid accel */ -#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_ACCEL_INTERRUPTS +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCEL_KX022 +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +/* ICM42607 Base accel/gyro */ +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ALS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT #define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL @@ -64,25 +80,24 @@ #endif /* VARIANT_KUKUI_NO_SENSORS */ /* I2C ports */ -#define I2C_PORT_BC12 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_BATTERY 2 -#define I2C_PORT_CHARGER 1 -#define I2C_PORT_SENSORS 1 -#define I2C_PORT_IO_EXPANDER_IT8801 1 -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_BATTERY 2 +#define I2C_PORT_CHARGER 1 +#define I2C_PORT_SENSORS 1 +#define I2C_PORT_KB_DISCRETE 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY + +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -/* Define the MKBP events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) #ifndef __ASSEMBLER__ @@ -115,12 +130,15 @@ enum charge_port { }; enum battery_type { - BATTERY_DANAPACK_ATL, - BATTERY_DANAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_DYNAPACK_COS, BATTERY_SIMPLO_COS, BATTERY_SIMPLO_HIGHPOWER, BATTERY_SAMSUNG_SDI, BATTERY_COS, + BATTERY_DYNAPACK_COS_44WH, + BATTERY_DYNAPACK_ATL_44WH, + BATTERY_SIMPLO_HIGHPOWER_44WH, BATTERY_TYPE_COUNT, }; @@ -135,13 +153,15 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void bc12_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); /* returns the i2c port number of charger */ int board_get_charger_i2c(void); int board_is_convertible(void); +/* Motion sensor interrupt */ +void sensor_interrupt(enum gpio_signal signal); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/burnet/build.mk b/board/burnet/build.mk index a6e1c010d7..f583684804 100644 --- a/board/burnet/build.mk +++ b/board/burnet/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/burnet/ec.tasklist b/board/burnet/ec.tasklist index c1330b86f8..fb131b8eb4 100644 --- a/board/burnet/ec.tasklist +++ b/board/burnet/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/burnet/gpio.inc b/board/burnet/gpio.inc index a08ef74c3c..9bb0aa73db 100644 --- a/board/burnet/gpio.inc +++ b/board/burnet/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,7 +22,7 @@ GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, chipset_reset_request_interrupt) GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, - bmi160_interrupt) + sensor_interrupt) GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, emmc_cmd_interrupt) GPIO_INT(SPI1_NSS, PIN(A, 15), GPIO_INT_BOTH | GPIO_PULL_UP, @@ -116,5 +116,5 @@ ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) /* EMMC SPI SLAVE: PB13/14/15 */ ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) /* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ -ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_MASTER, 0) -ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/burnet/led.c b/board/burnet/led.c index 1f2b75325c..97e30f24be 100644 --- a/board/burnet/led.c +++ b/board/burnet/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -17,10 +17,8 @@ #define POWER_LED_ON 0 #define POWER_LED_OFF 1 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -28,7 +26,7 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int led_set_color_battery(enum led_color color) @@ -52,7 +50,7 @@ static int led_set_color_battery(enum led_color color) return EC_SUCCESS; } -static int led_set_color_power(enum ec_led_colors color) +static int led_set_color_power(enum led_color color) { switch (color) { case LED_OFF: @@ -111,8 +109,7 @@ static void led_set_power(void) if (chipset_in_state(CHIPSET_STATE_ON)) led_set_color_power(LED_WHITE); else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) - led_set_color_power( - (power_tick & 0x2) ? LED_WHITE : LED_OFF); + led_set_color_power((power_tick & 0x2) ? LED_WHITE : LED_OFF); else led_set_color_power(LED_OFF); } @@ -121,7 +118,6 @@ static void led_set_battery(void) { static int battery_ticks; static int power_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; @@ -132,27 +128,27 @@ static void led_set_battery(void) */ if (!board_is_convertible()) { if (chipset_in_state(CHIPSET_STATE_SUSPEND | - CHIPSET_STATE_STANDBY) && - charge_get_state() != PWR_STATE_CHARGE) { - led_set_color_battery(power_ticks++ & 0x2 ? - LED_WHITE : LED_OFF); + CHIPSET_STATE_STANDBY) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + led_set_color_battery(power_ticks++ & 0x2 ? LED_WHITE : + LED_OFF); return; } } power_ticks = 0; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: led_set_color_battery(LED_AMBER); break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { led_set_color_battery(LED_WHITE); break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE: + __fallthrough; + case LED_PWRS_DISCHARGE: /* * Blink white light (1 sec on, 1 sec off) * when battery capacity is less than 10% @@ -163,19 +159,19 @@ static void led_set_battery(void) else led_set_color_battery(LED_OFF); break; - case PWR_STATE_ERROR: - led_set_color_battery( - (battery_ticks % 0x2) ? LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + led_set_color_battery((battery_ticks % 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: led_set_color_battery(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - led_set_color_battery( - (battery_ticks & 0x2) ? LED_AMBER : LED_OFF); - else - led_set_color_battery(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + led_set_color_battery(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + led_set_color_battery((battery_ticks & 0x2) ? LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ diff --git a/board/burnet/vif_override.xml b/board/burnet/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/burnet/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/c2d2/OWNERS b/board/c2d2/OWNERS new file mode 100644 index 0000000000..e4d6123372 --- /dev/null +++ b/board/c2d2/OWNERS @@ -0,0 +1,3 @@ +bnemec@google.com +jettrink@chromium.org +matthewb@chromium.org diff --git a/board/c2d2/board.c b/board/c2d2/board.c index 7e8af674c1..d8cf0f0e0a 100644 --- a/board/c2d2/board.c +++ b/board/c2d2/board.c @@ -1,10 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* C2D2 debug device board configuration */ -#include "adc_chip.h" #include "adc.h" #include "common.h" #include "console.h" @@ -20,19 +19,20 @@ #include "task.h" #include "timer.h" #include "update_fw.h" +#include "usart-stm32f0.h" #include "usart_rx_dma.h" #include "usart_tx_dma.h" -#include "usart-stm32f0.h" +#include "usb-stream.h" #include "usb_hw.h" #include "usb_i2c.h" #include "usb_spi.h" -#include "usb-stream.h" #include "util.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) /* Forward declarations */ static void update_vrefs_and_shifters(void); @@ -42,19 +42,19 @@ static bool is_ec_i2c_enabled(void); /* Global state tracking current pin configuration and operations */ static struct mutex vref_bus_state_mutex; static int vref_monitor_disable; -#define VREF_MON_DIS_H1_RST_HELD BIT(0) -#define VREF_MON_DIS_EC_PWR_HELD BIT(1) -#define VREF_MON_DIS_SPI_MODE BIT(2) +#define VREF_MON_DIS_H1_RST_HELD BIT(0) +#define VREF_MON_DIS_EC_PWR_HELD BIT(1) +#define VREF_MON_DIS_SPI_MODE BIT(2) /* * Tracks if bus pins are locked by a function like UART holding, I2C, * or SPI. */ enum bus_lock { - BUS_UNLOCKED, /* Normal UART; pins available for other functions */ - BUS_UART_HELD, /* UART locked to pins while holding RX low */ - BUS_SPI, /* SPI locked to pins */ - BUS_I2C, /* I2C bus locked to pins */ + BUS_UNLOCKED, /* Normal UART; pins available for other functions */ + BUS_UART_HELD, /* UART locked to pins while holding RX low */ + BUS_SPI, /* SPI locked to pins */ + BUS_I2C, /* I2C bus locked to pins */ }; /* A0/A1 (H1 UART or SPI) */ enum bus_lock h1_pins; @@ -78,7 +78,7 @@ static const char *lock_to_string(const enum bus_lock val) return names[val]; } -static int command_bus_status(int argc, char **argv) +static int command_bus_status(int argc, const char **argv) { if (argc > 1) return EC_ERROR_PARAM_COUNT; @@ -89,11 +89,9 @@ static int command_bus_status(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(bus_status, command_bus_status, - "", +DECLARE_CONSOLE_COMMAND(bus_status, command_bus_status, "", "Gets the bus state for swappable pins"); - /****************************************************************************** ** Chip-specific board configuration */ @@ -115,12 +113,11 @@ void board_config_pre_init(void) * i2c : no dma * tim16/17: no dma */ - STM32_SYSCFG_CFGR1 |= BIT(24); /* Remap SPI2_RX to channel 6 */ - STM32_SYSCFG_CFGR1 |= BIT(26); /* Remap USART3 RX/TX DMA */ - STM32_SYSCFG_CFGR1 |= BIT(10); /* Remap USART1 RX/TX DMA */ + STM32_SYSCFG_CFGR1 |= BIT(24); /* Remap SPI2_RX to channel 6 */ + STM32_SYSCFG_CFGR1 |= BIT(26); /* Remap USART3 RX/TX DMA */ + STM32_SYSCFG_CFGR1 |= BIT(10); /* Remap USART1 RX/TX DMA */ } - /****************************************************************************** ** ADC channels */ @@ -148,17 +145,18 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("C2D2"), - [USB_STR_SERIALNO] = 0, - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_USART4_STREAM_NAME] = USB_STRING_DESC("CR50"), - [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), - [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("C2D2 Shell"), - [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), - [USB_STR_USART3_STREAM_NAME] = USB_STRING_DESC("CPU"), - [USB_STR_USART1_STREAM_NAME] = USB_STRING_DESC("EC"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("C2D2"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_USART4_STREAM_NAME] = USB_STRING_DESC("CR50"), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), + [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("C2D2 Shell"), + [USB_STR_SPI_NAME] = USB_STRING_DESC("SPI"), + [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), + [USB_STR_USART3_STREAM_NAME] = USB_STRING_DESC("CPU"), + [USB_STR_USART1_STREAM_NAME] = USB_STRING_DESC("EC"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); @@ -174,7 +172,7 @@ const struct i2c_port_t i2c_ports[] = { .port = I2C_PORT_EC, .kbps = 100, .scl = GPIO_UART_DBG_TX_EC_RX_SCL, - .sda = GPIO_UART_EC_TX_DBG_RX_SDA, + .sda = GPIO_UART_EC_TX_DBG_RX_SDA, .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, }, { @@ -182,7 +180,7 @@ const struct i2c_port_t i2c_ports[] = { .port = I2C_PORT_AUX, .kbps = 100, .scl = GPIO_UART_DBG_TX_AP_RX_INA_SCL, - .sda = GPIO_UART_AP_TX_DBG_RX_INA_SDA, + .sda = GPIO_UART_AP_TX_DBG_RX_INA_SDA, .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, }, }; @@ -203,14 +201,19 @@ const struct ite_dfu_config_t ite_dfu_config = { * let the i2c transactions fail instead of using the USB endpoint disable * status. */ -int usb_i2c_board_is_enabled(void) { return 1; } +int usb_i2c_board_is_enabled(void) +{ + return 1; +} /****************************************************************************** * Forward UARTs as a USB serial interface. */ -#define USB_STREAM_RX_SIZE 32 -#define USB_STREAM_TX_SIZE 64 +#define USB_STREAM_RX_SIZE 32 +#define USB_STREAM_TX_SIZE 64 +#define USART_TO_USB_SIZE 1024 +#define USB_TO_USART_SIZE 64 /****************************************************************************** * Forward USART1 (EC) as a simple USB serial interface. @@ -219,33 +222,22 @@ int usb_i2c_board_is_enabled(void) { return 1; } static struct usart_config const usart1; struct usb_stream_config const usart1_usb; -static struct queue const usart1_to_usb = QUEUE_DIRECT(128, uint8_t, - usart1.producer, usart1_usb.consumer); -static struct queue const usb_to_usart1 = QUEUE_DIRECT(64, uint8_t, - usart1_usb.producer, usart1.consumer); +static struct queue const usart1_to_usb = QUEUE_DIRECT( + USART_TO_USB_SIZE, uint8_t, usart1.producer, usart1_usb.consumer); +static struct queue const usb_to_usart1 = QUEUE_DIRECT( + USB_TO_USART_SIZE, uint8_t, usart1_usb.producer, usart1.consumer); static struct usart_rx_dma const usart1_rx_dma = USART_RX_DMA(STM32_DMAC_CH5, 32); static struct usart_config const usart1 = - USART_CONFIG(usart1_hw, - usart1_rx_dma.usart_rx, - usart_tx_interrupt, - 115200, - 0, - usart1_to_usb, - usb_to_usart1); - -USB_STREAM_CONFIG_USART_IFACE(usart1_usb, - USB_IFACE_USART1_STREAM, - USB_STR_USART1_STREAM_NAME, - USB_EP_USART1_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart1, - usart1_to_usb, - usart1) + USART_CONFIG(usart1_hw, usart1_rx_dma.usart_rx, usart_tx_interrupt, + 115200, 0, usart1_to_usb, usb_to_usart1); +USB_STREAM_CONFIG_USART_IFACE(usart1_usb, USB_IFACE_USART1_STREAM, + USB_STR_USART1_STREAM_NAME, USB_EP_USART1_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, + usb_to_usart1, usart1_to_usb, usart1) /****************************************************************************** * Forward USART3 (CPU) as a simple USB serial interface. @@ -254,33 +246,22 @@ USB_STREAM_CONFIG_USART_IFACE(usart1_usb, static struct usart_config const usart3; struct usb_stream_config const usart3_usb; -static struct queue const usart3_to_usb = QUEUE_DIRECT(1024, uint8_t, - usart3.producer, usart3_usb.consumer); -static struct queue const usb_to_usart3 = QUEUE_DIRECT(64, uint8_t, - usart3_usb.producer, usart3.consumer); +static struct queue const usart3_to_usb = QUEUE_DIRECT( + USART_TO_USB_SIZE, uint8_t, usart3.producer, usart3_usb.consumer); +static struct queue const usb_to_usart3 = QUEUE_DIRECT( + USB_TO_USART_SIZE, uint8_t, usart3_usb.producer, usart3.consumer); static struct usart_rx_dma const usart3_rx_dma = USART_RX_DMA(STM32_DMAC_CH3, 32); static struct usart_config const usart3 = - USART_CONFIG(usart3_hw, - usart3_rx_dma.usart_rx, - usart_tx_interrupt, - 115200, - 0, - usart3_to_usb, - usb_to_usart3); - -USB_STREAM_CONFIG_USART_IFACE(usart3_usb, - USB_IFACE_USART3_STREAM, - USB_STR_USART3_STREAM_NAME, - USB_EP_USART3_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart3, - usart3_to_usb, - usart3) + USART_CONFIG(usart3_hw, usart3_rx_dma.usart_rx, usart_tx_interrupt, + 115200, 0, usart3_to_usb, usb_to_usart3); +USB_STREAM_CONFIG_USART_IFACE(usart3_usb, USB_IFACE_USART3_STREAM, + USB_STR_USART3_STREAM_NAME, USB_EP_USART3_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, + usb_to_usart3, usart3_to_usb, usart3) /****************************************************************************** * Forward USART4 (cr50) as a simple USB serial interface. @@ -291,29 +272,19 @@ USB_STREAM_CONFIG_USART_IFACE(usart3_usb, static struct usart_config const usart4; struct usb_stream_config const usart4_usb; -static struct queue const usart4_to_usb = QUEUE_DIRECT(1024, uint8_t, - usart4.producer, usart4_usb.consumer); -static struct queue const usb_to_usart4 = QUEUE_DIRECT(64, uint8_t, - usart4_usb.producer, usart4.consumer); +static struct queue const usart4_to_usb = QUEUE_DIRECT( + USART_TO_USB_SIZE, uint8_t, usart4.producer, usart4_usb.consumer); +static struct queue const usb_to_usart4 = QUEUE_DIRECT( + USB_TO_USART_SIZE, uint8_t, usart4_usb.producer, usart4.consumer); static struct usart_config const usart4 = - USART_CONFIG(usart4_hw, - usart_rx_interrupt, - usart_tx_interrupt, - 115200, - 0, - usart4_to_usb, - usb_to_usart4); - -USB_STREAM_CONFIG_USART_IFACE(usart4_usb, - USB_IFACE_USART4_STREAM, - USB_STR_USART4_STREAM_NAME, - USB_EP_USART4_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart4, - usart4_to_usb, - usart4) + USART_CONFIG(usart4_hw, usart_rx_interrupt, usart_tx_interrupt, 115200, + 0, usart4_to_usb, usb_to_usart4); + +USB_STREAM_CONFIG_USART_IFACE(usart4_usb, USB_IFACE_USART4_STREAM, + USB_STR_USART4_STREAM_NAME, USB_EP_USART4_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, + usb_to_usart4, usart4_to_usb, usart4) /****************************************************************************** * Set up SPI over USB @@ -322,11 +293,11 @@ USB_STREAM_CONFIG_USART_IFACE(usart4_usb, /* SPI devices */ const struct spi_device_t spi_devices[] = { - { CONFIG_SPI_FLASH_PORT, 1, GPIO_SPI_CSN}, + { CONFIG_SPI_FLASH_PORT, 1, GPIO_SPI_CSN, USB_SPI_ENABLED }, }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); -void usb_spi_board_enable(struct usb_spi_config const *config) +void usb_spi_board_enable(void) { /* Configure SPI GPIOs */ gpio_config_module(MODULE_SPI_FLASH, 1); @@ -341,12 +312,12 @@ void usb_spi_board_enable(struct usb_spi_config const *config) STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(&spi_devices[0], 1); } -void usb_spi_board_disable(struct usb_spi_config const *config) +void usb_spi_board_disable(void) { - spi_enable(CONFIG_SPI_FLASH_PORT, 0); + spi_enable(&spi_devices[0], 0); /* Disable clocks to SPI2 module */ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; @@ -358,13 +329,10 @@ void usb_spi_board_disable(struct usb_spi_config const *config) STM32_GPIO_OSPEEDR(GPIO_B) &= ~0xff000000; } -USB_SPI_CONFIG(usb_spi, USB_IFACE_SPI, USB_EP_SPI, - USB_SPI_CONFIG_FLAGS_IGNORE_HOST_SIDE_ENABLE); - /****************************************************************************** * Check parity setting on usarts. */ -static int command_uart_parity(int argc, char **argv) +static int command_uart_parity(int argc, const char **argv) { int parity = 0, newparity; struct usart_config const *usart; @@ -398,14 +366,13 @@ static int command_uart_parity(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(parity, command_uart_parity, - "usart[2|3|4] [0|1|2]", +DECLARE_CONSOLE_COMMAND(parity, command_uart_parity, "usart[2|3|4] [0|1|2]", "Set parity on uart"); /****************************************************************************** * Set baud rate setting on usarts. */ -static int command_uart_baud(int argc, char **argv) +static int command_uart_baud(int argc, const char **argv) { int baud = 0; struct usart_config const *usart; @@ -431,14 +398,13 @@ static int command_uart_baud(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(baud, command_uart_baud, - "usart[2|3|4] rate", +DECLARE_CONSOLE_COMMAND(baud, command_uart_baud, "usart[2|3|4] rate", "Set baud rate on uart"); /****************************************************************************** * Hold the usart pins low while disabling it, or return it to normal. */ -static int command_hold_usart_low(int argc, char **argv) +static int command_hold_usart_low(int argc, const char **argv) { enum bus_lock *bus; enum gpio_signal rx; @@ -501,7 +467,7 @@ static int command_hold_usart_low(int argc, char **argv) /* Print status for get and set case. */ ccprintf("USART status: %s\n", - *bus == BUS_UART_HELD ? "held low" : "normal"); + *bus == BUS_UART_HELD ? "held low" : "normal"); return EC_SUCCESS; @@ -513,7 +479,6 @@ DECLARE_CONSOLE_COMMAND(hold_usart_low, command_hold_usart_low, "usart[1|3|4] [0|1]?", "Get/set the hold-low state for usart port"); - /****************************************************************************** * Console commands SPI programming */ @@ -523,7 +488,7 @@ enum vref { PP3300 = 3300, }; -static int command_enable_spi(int argc, char **argv) +static int command_enable_spi(int argc, const char **argv) { static enum vref current_spi_vref_state; @@ -563,7 +528,7 @@ static int command_enable_spi(int argc, char **argv) gpio_set_level(GPIO_EN_CLK_CSN_EC_UART, 0); /* Disable SPI. Sets SPI pins to inputs. */ - usb_spi_enable(&usb_spi, 0); + usb_spi_enable(0); /* Set default state for chip select */ gpio_set_flags(GPIO_SPI_CSN, GPIO_INPUT); @@ -616,7 +581,7 @@ static int command_enable_spi(int argc, char **argv) gpio_set_flags(GPIO_SPI_CSN, GPIO_OUT_HIGH); /* Enable SPI. Sets SPI pins to SPI alternate mode. */ - usb_spi_enable(&usb_spi, 1); + usb_spi_enable(1); /* Set requested Vref voltage */ gpio_set_level(GPIO_SEL_SPIVREF_H1VREF_3V3, @@ -650,8 +615,7 @@ static int command_enable_spi(int argc, char **argv) mutex_unlock(&vref_bus_state_mutex); return EC_ERROR_BUSY; } -DECLARE_CONSOLE_COMMAND(enable_spi, command_enable_spi, - "[0|1800|3300]?", +DECLARE_CONSOLE_COMMAND(enable_spi, command_enable_spi, "[0|1800|3300]?", "Get/set the SPI Vref"); /****************************************************************************** @@ -686,7 +650,7 @@ static inline int to_kbps(enum i2c_freq freq) } } -static int command_enable_i2c(int argc, char **argv) +static int command_enable_i2c(int argc, const char **argv) { int i2c_index; enum bus_lock *bus; @@ -770,7 +734,7 @@ DECLARE_CONSOLE_COMMAND(enable_i2c, command_enable_i2c, * Console commands for asserting H1 reset and EC Power button */ -static int command_vref_alternate(int argc, char **argv, +static int command_vref_alternate(int argc, const char **argv, const enum gpio_signal vref_signal, const enum gpio_signal en_signal, const int state_flag, @@ -819,7 +783,6 @@ static int command_vref_alternate(int argc, char **argv, ccprintf("%s held: %s\n", print_name, vref_monitor_disable & state_flag ? "yes" : "no"); - return EC_SUCCESS; busy_error_unlock: @@ -827,29 +790,47 @@ static int command_vref_alternate(int argc, char **argv, return EC_ERROR_BUSY; } -static int command_pwr_button(int argc, char **argv) +static int command_pwr_button(int argc, const char **argv) { return command_vref_alternate(argc, argv, GPIO_SPIVREF_HOLDN_ECVREF_H1_PWRBTN_ODL, GPIO_EN_SPIVREF_HOLDN_ECVREF_H1_PWRBTN, VREF_MON_DIS_EC_PWR_HELD, "Power button"); } -DECLARE_CONSOLE_COMMAND(pwr_button, command_pwr_button, - "[0|1]?", +DECLARE_CONSOLE_COMMAND(pwr_button, command_pwr_button, "[0|1]?", "Get/set the power button state"); -static int command_h1_reset(int argc, char **argv) +static int command_h1_reset(int argc, const char **argv) { + if ((argc == 2) && !strncasecmp("pulse", argv[1], strlen(argv[1]))) { + int rv; + int c = 2; + const char *cmd_on[] = { "", "1", "" }; + const char *cmd_off[] = { "", "0", "" }; + + rv = command_vref_alternate(c, cmd_on, + GPIO_SPIVREF_RSVD_H1VREF_H1_RST_ODL, + GPIO_EN_SPIVREF_RSVD_H1VREF_H1_RST, + VREF_MON_DIS_H1_RST_HELD, + "H1 reset"); + if (rv == EC_SUCCESS) { + msleep(100); + rv = command_vref_alternate( + c, cmd_off, GPIO_SPIVREF_RSVD_H1VREF_H1_RST_ODL, + GPIO_EN_SPIVREF_RSVD_H1VREF_H1_RST, + VREF_MON_DIS_H1_RST_HELD, "H1 reset"); + } + return rv; + } + return command_vref_alternate(argc, argv, GPIO_SPIVREF_RSVD_H1VREF_H1_RST_ODL, GPIO_EN_SPIVREF_RSVD_H1VREF_H1_RST, VREF_MON_DIS_H1_RST_HELD, "H1 reset"); } -DECLARE_CONSOLE_COMMAND(h1_reset, command_h1_reset, - "[0|1]?", +DECLARE_CONSOLE_COMMAND(h1_reset, command_h1_reset, "[0|1|pulse]?", "Get/set the h1 reset state"); - /****************************************************************************** * Vref detection logic */ @@ -858,14 +839,13 @@ DECLARE_CONSOLE_COMMAND(h1_reset, command_h1_reset, static enum vref h1_vref; static enum vref ec_vref; -static int command_h1_vref_present(int argc, char **argv) +static int command_h1_vref_present(int argc, const char **argv) { ccprintf("H1 Vref: %s\n", h1_vref ? "on" : "off"); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(h1_vref, command_h1_vref_present, - "", +DECLARE_CONSOLE_COMMAND(h1_vref, command_h1_vref_present, "", "Get if the h1 vref is present"); /* Voltage thresholds for rail detection */ @@ -1011,11 +991,9 @@ static void update_vrefs_and_shifters(void) void set_up_comparator(void) { /* Overwrite any previous values. This is the only comparator usage */ - STM32_COMP_CSR = STM32_COMP_CMP2HYST_HI | - STM32_COMP_CMP2OUTSEL_NONE | + STM32_COMP_CSR = STM32_COMP_CMP2HYST_HI | STM32_COMP_CMP2OUTSEL_NONE | STM32_COMP_CMP2INSEL_INM5 | /* Watch DAC_OUT2 (PA5) */ - STM32_COMP_CMP2MODE_LSPEED | - STM32_COMP_CMP2EN; + STM32_COMP_CMP2MODE_LSPEED | STM32_COMP_CMP2EN; /* Set Falling and Rising interrupts for COMP2 */ STM32_EXTI_FTSR |= EXTI_COMP2_EVENT; @@ -1091,6 +1069,6 @@ static void board_jump(void) usart_shutdown(&usart4); /* Ensure SPI2 is disabled as well */ - usb_spi_enable(&usb_spi, 0); + usb_spi_enable(0); } DECLARE_HOOK(HOOK_SYSJUMP, board_jump, HOOK_PRIO_DEFAULT); diff --git a/board/c2d2/board.h b/board/c2d2/board.h index 2aa129ef25..dc9b8321a2 100644 --- a/board/c2d2/board.h +++ b/board/c2d2/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -21,9 +21,9 @@ /* Enable USART */ #define CONFIG_STREAM_USART -#define CONFIG_STREAM_USART1 /* EC USART */ -#define CONFIG_STREAM_USART3 /* AP USART - not connected by default */ -#define CONFIG_STREAM_USART4 /* H1 USART */ +#define CONFIG_STREAM_USART1 /* EC USART */ +#define CONFIG_STREAM_USART3 /* AP USART - not connected by default */ +#define CONFIG_STREAM_USART4 /* H1 USART */ #define CONFIG_STREAM_USB #define CONFIG_CMD_USART_INFO @@ -34,7 +34,6 @@ #undef CONFIG_UART_RX_DMA /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_HW_CRC /* USB Configuration */ @@ -45,50 +44,50 @@ #define DEFAULT_SERIALNO "Uninitialized" #define CONFIG_USB_UPDATE - /* USB interface indexes (use define rather than enum to expand them) * * Note these values are used in servo_interface.py for the 'interface' value */ -#define USB_IFACE_USART4_STREAM 0 /* H1 */ -#define USB_IFACE_UPDATE 1 -#define USB_IFACE_SPI 2 -#define USB_IFACE_CONSOLE 3 -#define USB_IFACE_I2C 4 -#define USB_IFACE_USART3_STREAM 5 /* AP (not connected by default) */ -#define USB_IFACE_USART1_STREAM 6 /* EC */ -#define USB_IFACE_COUNT 7 +#define USB_IFACE_USART4_STREAM 0 /* H1 */ +#define USB_IFACE_UPDATE 1 +#define USB_IFACE_SPI 2 +#define USB_IFACE_CONSOLE 3 +#define USB_IFACE_I2C 4 +#define USB_IFACE_USART3_STREAM 5 /* AP (not connected by default) */ +#define USB_IFACE_USART1_STREAM 6 /* EC */ +#define USB_IFACE_COUNT 7 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_USART4_STREAM 1 -#define USB_EP_UPDATE 2 -#define USB_EP_SPI 3 -#define USB_EP_CONSOLE 4 -#define USB_EP_I2C 5 -#define USB_EP_USART3_STREAM 6 -#define USB_EP_USART1_STREAM 7 -#define USB_EP_COUNT 8 +#define USB_EP_CONTROL 0 +#define USB_EP_USART4_STREAM 1 +#define USB_EP_UPDATE 2 +#define USB_EP_SPI 3 +#define USB_EP_CONSOLE 4 +#define USB_EP_I2C 5 +#define USB_EP_USART3_STREAM 6 +#define USB_EP_USART1_STREAM 7 +#define USB_EP_COUNT 8 /* Enable control of SPI over USB */ #define CONFIG_USB_SPI -#define CONFIG_SPI_MASTER -#define CONFIG_SPI_FLASH_PORT 0 /* SPI2 is 0th in stm's SPI_REGS var */ +#define CONFIG_USB_SPI_IGNORE_HOST_SIDE_ENABLE +#define CONFIG_SPI_CONTROLLER +#define CONFIG_SPI_FLASH_PORT 0 /* SPI2 is 0th in stm's SPI_REGS var */ /* Enable control of I2C over USB */ #define CONFIG_USB_I2C #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define I2C_PORT_EC 0 #define I2C_PORT_AUX 1 /* See i2c_ite_flash_support.c for more information about these values */ #define CONFIG_ITE_FLASH_SUPPORT -#define CONFIG_I2C_XFER_LARGE_READ +#define CONFIG_I2C_XFER_LARGE_TRANSFER #undef CONFIG_USB_I2C_MAX_WRITE_COUNT #undef CONFIG_USB_I2C_MAX_READ_COUNT -#define CONFIG_USB_I2C_MAX_WRITE_COUNT ((1<<9) - 4) -#define CONFIG_USB_I2C_MAX_READ_COUNT ((1<<9) - 6) +#define CONFIG_USB_I2C_MAX_WRITE_COUNT ((1 << 9) - 4) +#define CONFIG_USB_I2C_MAX_READ_COUNT ((1 << 9) - 6) /* * Set all ADC samples to take 239.5 clock cycles. This allows us to measure @@ -114,7 +113,7 @@ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 +#define TIM_ADC 3 #include "gpio_signal.h" @@ -128,6 +127,7 @@ enum usb_strings { USB_STR_USART4_STREAM_NAME, USB_STR_UPDATE_NAME, USB_STR_CONSOLE_NAME, + USB_STR_SPI_NAME, USB_STR_I2C_NAME, USB_STR_USART3_STREAM_NAME, USB_STR_USART1_STREAM_NAME, diff --git a/board/c2d2/build.mk b/board/c2d2/build.mk index 559b6b8e95..d5940c3885 100644 --- a/board/c2d2/build.mk +++ b/board/c2d2/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/c2d2/ec.tasklist b/board/c2d2/ec.tasklist index c1fb169118..c45a1e89a7 100644 --- a/board/c2d2/ec.tasklist +++ b/board/c2d2/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/c2d2/gpio.inc b/board/c2d2/gpio.inc index 485a603453..b100250f20 100644 --- a/board/c2d2/gpio.inc +++ b/board/c2d2/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/cappy2/battery.c b/board/cappy2/battery.c new file mode 100644 index 0000000000..19be1825eb --- /dev/null +++ b/board/cappy2/battery.c @@ -0,0 +1,177 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_state.h" +#include "common.h" +#include "util.h" + +#define CHARGING_VOLTAGE_MV_SAFE 8400 +#define CHARGING_CURRENT_MA_SAFE 1500 + +/* + * Battery info for lalala battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* SDI Battery Information */ + [BATTERY_SDI] = { + .fuel_gauge = { + .manuf_name = "SDI", + .device_name = "4402D51", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0xc000, + .disconnect_val = 0x8000, + .cfet_mask = 0xc000, + .cfet_off_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + } +}; + +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SDI; + +int charger_profile_override(struct charge_state_data *curr) +{ + int current; + int voltage; + /* battery temp in 0.1 deg C */ + int bat_temp_c; + const struct battery_info *batt_info; + + /* + * Keep track of battery temperature range: + * + * ZONE_0 ZONE_1 ZONE_2 ZONE_3 + * ---+------+--------+--------+------+--- Temperature (C) + * 0 5 12 45 50 + */ + enum { + TEMP_ZONE_0, /* 0 <= bat_temp_c <= 5 */ + TEMP_ZONE_1, /* 5 < bat_temp_c <= 12 */ + TEMP_ZONE_2, /* 12 < bat_temp_c <= 45 */ + TEMP_ZONE_3, /* 45 < bat_temp_c <= 50 */ + TEMP_ZONE_COUNT, + TEMP_OUT_OF_RANGE = TEMP_ZONE_COUNT + } temp_zone; + + /* + * Precharge must be executed when communication is failed on + * dead battery. + */ + if (!(curr->batt.flags & BATT_FLAG_RESPONSIVE)) + return 0; + + current = curr->requested_current; + voltage = curr->requested_voltage; + bat_temp_c = curr->batt.temperature - 2731; + batt_info = battery_get_info(); + + /* + * If the temperature reading is bad, assume the temperature + * is out of allowable range. + */ + if ((curr->batt.flags & BATT_FLAG_BAD_TEMPERATURE) || + (bat_temp_c < 0) || (bat_temp_c > 500)) + temp_zone = TEMP_OUT_OF_RANGE; + else if (bat_temp_c <= 50) + temp_zone = TEMP_ZONE_0; + else if (bat_temp_c <= 120) + temp_zone = TEMP_ZONE_1; + else if (bat_temp_c <= 450) + temp_zone = TEMP_ZONE_2; + else + temp_zone = TEMP_ZONE_3; + + switch (temp_zone) { + case TEMP_ZONE_0: + voltage = CHARGING_VOLTAGE_MV_SAFE; + current = CHARGING_CURRENT_MA_SAFE; + break; + + case TEMP_ZONE_1: + voltage += 100; + current = CHARGING_CURRENT_MA_SAFE; + break; + + case TEMP_ZONE_2: + voltage += 100; + break; + + case TEMP_ZONE_3: + voltage = CHARGING_VOLTAGE_MV_SAFE; + break; + + case TEMP_OUT_OF_RANGE: + /* Don't charge if outside of allowable temperature range */ + current = 0; + voltage = 0; + curr->batt.flags &= ~BATT_FLAG_WANT_CHARGE; + if (curr->state != ST_DISCHARGE) + curr->state = ST_IDLE; + break; + } + + if (voltage > batt_info->voltage_max) + voltage = batt_info->voltage_max; + + curr->requested_voltage = voltage; + curr->requested_current = MIN(curr->requested_current, current); + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/cappy2/board.c b/board/cappy2/board.c new file mode 100644 index 0000000000..9525e9c1f2 --- /dev/null +++ b/board/cappy2/board.c @@ -0,0 +1,348 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* cappy2 board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/raa489000.h" +#include "driver/temp_sensor/thermistor.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "math_util.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_mux/ps8743_public.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/* Keyboard scan setting */ + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SUB_ANALOG] = { + .name = "SUB_ANALOG", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3] = { + .name = "TEMP_SENSOR3", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + raa489000_hibernate(0, true); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + gpio_set_level(GPIO_EN_USB_A0_VBUS, !!enable); +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* BC 1.2 chip*/ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PS8743_I2C_ADDR0_FLAG, + .driver = &ps8743_usb_mux_driver, + }, + }, +}; + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + return status; +} + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + /* modify AC DC prochot value */ + isl923x_set_ac_prochot(CHARGER_SOLO, 4096); + isl923x_set_dc_prochot(CHARGER_SOLO, 6000); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Cpu", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); diff --git a/board/cappy2/board.h b/board/cappy2/board.h new file mode 100644 index 0000000000..d9b027eed9 --- /dev/null +++ b/board/cappy2/board.h @@ -0,0 +1,126 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* cappy2 board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KEEBY_EC_NPCX797FC +#include "baseboard.h" + +#undef GPIO_VOLUME_UP_L +#undef GPIO_VOLUME_DOWN_L +#undef CONFIG_VOLUME_BUTTONS + +/* System unlocked in early development */ +#define CONFIG_SYSTEM_UNLOCKED + +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SINGLE_CHIP +#define CONFIG_CHARGER_PROFILE_OVERRIDE +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 + +/* Keyboard */ +#undef CONFIG_PWM_KBLIGHT + +/* LED defines */ +#define CONFIG_LED_COMMON +#define CONFIG_LED_ONOFF_STATES +#define GPIO_BAT_LED_RED_L GPIO_LED_R_ODL +#define GPIO_BAT_LED_GREEN_L GPIO_LED_G_ODL +#define GPIO_PWR_LED_BLUE_L GPIO_LED_B_ODL + +/* PWM */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is used as PWM1. */ + +/******************************************************************************/ + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* BC1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* MUX */ +#define CONFIG_USB_MUX_PS8743 + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B +#define CONFIG_TEMP_SENSOR_POWER +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_PP3300_A + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_TEMP_SENSOR_3, /* ADC6 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +enum battery_type { + BATTERY_SDI, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/cappy2/build.mk b/board/cappy2/build.mk new file mode 100644 index 0000000000..eb422dae93 --- /dev/null +++ b/board/cappy2/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=keeby + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/cappy2/cbi_ssfc.c b/board/cappy2/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/cappy2/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/cappy2/cbi_ssfc.h b/board/cappy2/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/cappy2/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/cappy2/ec.tasklist b/board/cappy2/ec.tasklist new file mode 100644 index 0000000000..386e8625b3 --- /dev/null +++ b/board/cappy2/ec.tasklist @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/cappy2/gpio.inc b/board/cappy2/gpio.inc new file mode 100644 index 0000000000..1a32f31e06 --- /dev/null +++ b/board/cappy2/gpio.inc @@ -0,0 +1,148 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(A, 2), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) + +/* Button interrupts */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) + +/* Extra Sub-board I/O pins */ +GPIO(LTE_EN, PIN(6, 0), GPIO_OUT_LOW) + +/* Misc Enables */ +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(EC_CBI_WP, PIN(E, 5), GPIO_OUT_LOW) + +/* LED */ +GPIO(LED_B_ODL, PIN(C, 2), GPIO_OUT_HIGH) /* PWM_CH_LED2_BLUE */ +GPIO(LED_G_ODL, PIN(C, 3), GPIO_OUT_HIGH) /* PWM_CH_LED1_GREEN */ +GPIO(LED_R_ODL, PIN(C, 4), GPIO_OUT_HIGH) /* PWM_CH_LED2_ORANGE */ + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +/* USB pins */ +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(7, 2), GPIO_OUT_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(EN_USB_A0_VBUS, PIN(4, 1), GPIO_OUT_LOW) /* Enable A1 5V Charging */ +/* + * cappy2 doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) +UNIMPLEMENTED(VOLDN_BTN_ODL) +UNIMPLEMENTED(VOLUP_BTN_ODL) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(3, BIT(4)), 0, MODULE_ADC, 0) /* ADC6 */ +ALTERNATE(PIN_MASK(4, BIT(3)|BIT(4)|BIT(5)), 0, MODULE_ADC, 0) /* ADC0-2 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(6, BIT(4)|BIT(5)), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(2)|BIT(3)), 0, MODULE_I2C, 0) /* I2C7 */ +ALTERNATE(PIN_MASK(3, BIT(3)|BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, BIT(0)), 0, MODULE_I2C, 0) /* I2C1 SCL */ +ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO00_NC, PIN(0, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO37_NC, PIN(3, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO50_NC, PIN(5, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO56_NC, PIN(5, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO63_NC, PIN(6, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO73_NC, PIN(7, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO75_NC, PIN(7, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO80_NC, PIN(8, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO91_NC, PIN(9, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO92_NC, PIN(9, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO95_NC, PIN(9, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO97_NC, PIN(9, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOB4_NC, PIN(B, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOB5_NC, PIN(B, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO40_NC, PIN(4, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOF2_NC, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOF3_NC, PIN(F, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/cappy2/led.c b/board/cappy2/led.c new file mode 100644 index 0000000000..dba215ab51 --- /dev/null +++ b/board/cappy2/led.c @@ -0,0 +1,134 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for lalala + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 1; + +__override const int led_charge_lvl_2 = 100; + +/* cappy2 : There are 3 leds for AC, Battery and Power */ +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_BLUE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_power(enum ec_led_colors color) +{ + /* Don't set led if led_auto_control is disabled. */ + if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + return; + } + + if (color == EC_LED_COLOR_BLUE) { + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_ON_LVL); + } else { + /* LED_OFF and unsupported colors */ + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); + } +} + +__override void led_set_color_battery(enum ec_led_colors color) +{ + /* Don't set led if led_auto_control is disabled. */ + if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + return; + } + + /* Battery leds must be turn off when blue led is on + * because the led is 3-in-1 led. + */ + if (!gpio_get_level(GPIO_PWR_LED_BLUE_L)) { + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + return; + } + + switch (color) { + case EC_LED_COLOR_GREEN: + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_ON_LVL); /*green*/ + break; + case EC_LED_COLOR_RED: + gpio_set_level(GPIO_BAT_LED_RED_L, LED_ON_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_RED] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_GREEN_L, + !brightness[EC_LED_COLOR_GREEN]); + gpio_set_level(GPIO_BAT_LED_RED_L, + !brightness[EC_LED_COLOR_RED]); + } else if (led_id == EC_LED_ID_POWER_LED) { + gpio_set_level(GPIO_PWR_LED_BLUE_L, + !brightness[EC_LED_COLOR_BLUE]); + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); + } + + return EC_SUCCESS; +} diff --git a/board/cappy2/usb_pd_policy.c b/board/cappy2/usb_pd_policy.c new file mode 100644 index 0000000000..3410726e87 --- /dev/null +++ b/board/cappy2/usb_pd_policy.c @@ -0,0 +1,56 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/cappy2/vif_override.xml b/board/cappy2/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/cappy2/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/careena/battery.c b/board/careena/battery.c index 695bbaa63a..ae8b2f905a 100644 --- a/board/careena/battery.c +++ b/board/careena/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -33,7 +33,7 @@ */ const struct board_batt_params board_battery_info[] = { /* DynaPack Coslight Battery Information */ - [BATTERY_DANAPACK_COS] = { + [BATTERY_DYNAPACK_COS] = { .fuel_gauge = { .manuf_name = "333-2C-DA-A", .ship_mode = { @@ -63,7 +63,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack ATL Battery Information */ - [BATTERY_DANAPACK_ATL] = { + [BATTERY_DYNAPACK_ATL] = { .fuel_gauge = { .manuf_name = "333-27-DA-A", .ship_mode = { @@ -93,7 +93,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack SDI Battery Information */ - [BATTERY_DANAPACK_SDI] = { + [BATTERY_DYNAPACK_SDI] = { .fuel_gauge = { .manuf_name = "333-24-DA-A", .ship_mode = { @@ -241,7 +241,37 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 60, }, }, + + /* CosMX B00C4473A9D0002 Battery Information */ + [BATTERY_COS] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + .imbalance_mv = &battery_default_imbalance_mv, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DANAPACK_COS; +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; diff --git a/board/careena/board.c b/board/careena/board.c index 082a47ab50..01c92dfe1a 100644 --- a/board/careena/board.c +++ b/board/careena/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #include "button.h" #include "driver/tcpm/ps8xxx.h" #include "extpower.h" +#include "hooks.h" #include "i2c.h" #include "lid_switch.h" #include "power.h" @@ -15,7 +16,9 @@ #include "pwm.h" #include "pwm_chip.h" #include "switch.h" +#include "thermal.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" const enum gpio_signal hibernate_wake_pins[] = { @@ -24,15 +27,35 @@ const enum gpio_signal hibernate_wake_pins[] = { GPIO_POWER_BUTTON_L, GPIO_EC_RST_ODL, }; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* I2C port map. */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"thermal", I2C_PORT_THERMAL_AP, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "thermal", + .port = I2C_PORT_THERMAL_AP, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -46,6 +69,35 @@ const struct pwm_t pwm_channels[] = { }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT] = { + [TEMP_SENSOR_SOC] = { + .temp_host = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(74), + [EC_TEMP_THRESH_HALT] = C_TO_K(79), + }, + .temp_host_release = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(71), + [EC_TEMP_THRESH_HALT] = 0, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +static void board_init(void) +{ + /* + * Ensure PROCHOT is deasserted after sysjump. + * The GPIO was an input in old RO images. On sysjump to new RW, the + * direction is changed to output but the level is not set, which + * results in the output driving low, which asserts PROCHOT incorrectly. + * (crbug.com/1226694) + */ + gpio_set_level(GPIO_CPU_PROCHOT, 1); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + #ifdef CONFIG_KEYBOARD_FACTORY_TEST /* * We have total 24 pins for keyboard connecter, {-1, -1} mean @@ -53,15 +105,15 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); * that we don't have pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {1, 4}, {1, 3}, {1, 6}, {-1, -1}, - {3, 1}, {2, 0}, {1, 5}, {2, 6}, {-1, -1}, - {2, 1}, {2, 4}, {2, 5}, {1, 2}, {2, 3}, - {2, 2}, {3, 0}, {-1, -1}, {-1, -1}, {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { -1, -1 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { -1, -1 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); static int board_is_support_ps8755_tcpc(void) { diff --git a/board/careena/board.h b/board/careena/board.h index ed17d38646..86b88b64f0 100644 --- a/board/careena/board.h +++ b/board/careena/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,7 +17,7 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF @@ -27,6 +27,11 @@ #define CONFIG_CMD_LEDTEST #define CONFIG_KEYBOARD_FACTORY_TEST +/* Thermal */ +#define CONFIG_CHIPSET_CAN_THROTTLE +#define CONFIG_CPU_PROCHOT_ACTIVE_LOW +#define CONFIG_THROTTLE_AP + #define CONFIG_BATTERY_MEASURE_IMBALANCE #define CONFIG_BATTERY_BQ4050 @@ -36,27 +41,20 @@ #ifndef __ASSEMBLER__ -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_COUNT }; enum battery_type { - BATTERY_DANAPACK_COS, - BATTERY_DANAPACK_ATL, - BATTERY_DANAPACK_SDI, + BATTERY_DYNAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_DYNAPACK_SDI, BATTERY_SAMSUNG_SDI, BATTERY_SIMPLO_COS, BATTERY_SIMPLO_ATL, BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COS, BATTERY_TYPE_COUNT, }; -#ifdef CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; -#endif - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/careena/build.mk b/board/careena/build.mk index c808e65aed..d24127ddae 100644 --- a/board/careena/build.mk +++ b/board/careena/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/careena/ec.tasklist b/board/careena/ec.tasklist index b562761311..24300fe7da 100644 --- a/board/careena/ec.tasklist +++ b/board/careena/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/careena/gpio.inc b/board/careena/gpio.inc index eeccf9f50d..477b17234e 100644 --- a/board/careena/gpio.inc +++ b/board/careena/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -38,7 +38,7 @@ GPIO(CCD_MODE_ODL, PIN(E, 3), GPIO_INPUT) /* Case Closed Debug Mode */ GPIO(ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* EC Entering RW */ GPIO(EC_BATT_PRES_L, PIN(E, 5), GPIO_INPUT | GPIO_PULL_UP) /* Battery Present */ GPIO(PCH_SYS_PWROK, PIN(D, 6), GPIO_OUT_LOW) /* Power OK to SOC */ -GPIO(CPU_PROCHOT, PIN(3, 4), GPIO_INPUT | GPIO_SEL_1P8V) /* PROCHOT to SOC */ +GPIO(CPU_PROCHOT, PIN(3, 4), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PROCHOT to SOC */ GPIO(APU_ALERT_L, PIN(A, 2), GPIO_INPUT) /* Alert to SOC */ GPIO(3AXIS_INT_L, PIN(5, 0), GPIO_INPUT | GPIO_SEL_1P8V) /* 3 Axis Accel */ GPIO(TCPC_ID, PIN(E, 0), GPIO_INPUT | GPIO_PULL_DOWN) /* TCPC ID pin */ diff --git a/board/careena/led.c b/board/careena/led.c index 4188290b4f..dd5cffc385 100644 --- a/board/careena/led.c +++ b/board/careena/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -14,13 +14,13 @@ #include "hooks.h" #include "host_command.h" #include "led_common.h" -#include "util.h" #include "system.h" +#include "util.h" #define BAT_LED_ON 0 #define BAT_LED_OFF 1 -const enum ec_led_id supported_led_ids[] = {EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -28,7 +28,7 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int led_set_color_battery(enum led_color color) @@ -88,32 +88,30 @@ static void led_set_battery(void) { static int battery_ticks; static int power_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; /* override battery led for system suspend */ - if (chipset_in_state(CHIPSET_STATE_SUSPEND | - CHIPSET_STATE_STANDBY) && - charge_get_state() != PWR_STATE_CHARGE) { - led_set_color_battery(power_ticks++ & 0x4 ? - LED_WHITE : LED_OFF); + if (chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_STANDBY) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + led_set_color_battery(power_ticks++ & 0x4 ? LED_WHITE : + LED_OFF); return; } power_ticks = 0; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: led_set_color_battery(LED_AMBER); break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { led_set_color_battery(LED_WHITE); break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE: + __fallthrough; + case LED_PWRS_DISCHARGE: /* * Blink white light (1 sec on, 1 sec off) * when battery capacity is less than 10% @@ -124,19 +122,19 @@ static void led_set_battery(void) else led_set_color_battery(LED_OFF); break; - case PWR_STATE_ERROR: - led_set_color_battery( - (battery_ticks & 0x2) ? LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + led_set_color_battery((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: led_set_color_battery(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - led_set_color_battery( - (battery_ticks & 0x4) ? LED_AMBER : LED_OFF); - else - led_set_color_battery(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + led_set_color_battery(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + led_set_color_battery((battery_ticks & 0x4) ? LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ diff --git a/board/careena/vif_override.xml b/board/careena/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/careena/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/casta/battery.c b/board/casta/battery.c index 0ced18e734..846165ff13 100644 --- a/board/casta/battery.c +++ b/board/casta/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -12,9 +12,10 @@ #include "common.h" #include "util.h" -#define CHARGING_VOLTAGE_MV_SAFE 8400 -#define CHARGING_CURRENT_MA_SAFE 1500 - +#define CHARGING_VOLTAGE_MV_SAFE 8400 +#define CHARGING_CURRENT_MA_SAFE 1500 +#define CHARGING_VOLTAGE_MV_ADJUST 8600 +#define CHARGING_CURRENT_MA_ADJUST 3200 /* * Battery info for all casta battery types. Note that the fields * start_charging_min/max and charging_min/max are not used for the charger. @@ -54,7 +55,7 @@ const struct board_batt_params board_battery_info[] = { } }, .batt_info = { - .voltage_max = 8650, + .voltage_max = 8600, .voltage_normal = 7700, /* mV */ .voltage_min = 6000, /* mV */ .precharge_current = 200, /* mA */ @@ -95,15 +96,19 @@ int charger_profile_override(struct charge_state_data *curr) TEMP_OUT_OF_RANGE = TEMP_ZONE_COUNT } temp_zone; - /* - * Precharge must be executed when communication is failed on + /* + * Precharge must be executed when communication is failed on * dead battery. - */ - if(!(curr->batt.flags & BATT_FLAG_RESPONSIVE)) - return 0; + */ + if (!(curr->batt.flags & BATT_FLAG_RESPONSIVE)) + return 0; current = curr->requested_current; + if (current > CHARGING_CURRENT_MA_ADJUST) + current = CHARGING_CURRENT_MA_ADJUST; voltage = curr->requested_voltage; + if (voltage > CHARGING_VOLTAGE_MV_ADJUST) + voltage = CHARGING_VOLTAGE_MV_ADJUST; bat_temp_c = curr->batt.temperature - 2731; batt_info = battery_get_info(); @@ -146,7 +151,7 @@ int charger_profile_override(struct charge_state_data *curr) break; } - if(voltage > batt_info->voltage_max) + if (voltage > batt_info->voltage_max) voltage = batt_info->voltage_max; curr->requested_voltage = MIN(curr->requested_voltage, voltage); diff --git a/board/casta/board.c b/board/casta/board.c index e1d7630e3f..5529c3a36d 100644 --- a/board/casta/board.c +++ b/board/casta/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,13 +6,15 @@ /* Casta board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery.h" +#include "cbi_ssfc.h" #include "charge_manager.h" #include "charge_state.h" #include "common.h" #include "cros_board_info.h" #include "driver/charger/bd9995x.h" +#include "driver/charger/bq25710.h" +#include "driver/charger/isl923x.h" #include "driver/ppc/nx20p348x.h" #include "driver/tcpm/anx7447.h" #include "driver/tcpm/ps8xxx.h" @@ -28,17 +30,17 @@ #include "power_button.h" #include "switch.h" #include "system.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) static uint8_t sku_id; @@ -58,46 +60,55 @@ static void ppc_interrupt(enum gpio_signal signal) } } -/* Must come after other header files and GPIO interrupts*/ +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* TODO(b/119872005): Casta: confirm thermistor parts */ const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); +/* Charger config. Start i2c address at isl9238, update during runtime */ +struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; +const unsigned int chg_cnt = ARRAY_SIZE(chg_chips); + /* * I2C callbacks to ensure bus free time for battery I2C transactions is at * least 5ms. */ -#define BATTERY_FREE_MIN_DELTA_US (5 * MSEC) +#define BATTERY_FREE_MIN_DELTA_US (5 * MSEC) static timestamp_t battery_last_i2c_time; -static int is_battery_i2c(const int port, const uint16_t slave_addr_flags) +static int is_battery_i2c(const int port, const uint16_t addr_flags) { - return (port == I2C_PORT_BATTERY) - && (slave_addr_flags == BATTERY_ADDR_FLAGS); + return (port == I2C_PORT_BATTERY) && (addr_flags == BATTERY_ADDR_FLAGS); } static int is_battery_port(int port) @@ -105,11 +116,11 @@ static int is_battery_port(int port) return (port == I2C_PORT_BATTERY); } -void i2c_start_xfer_notify(const int port, const uint16_t slave_addr_flags) +void i2c_start_xfer_notify(const int port, const uint16_t addr_flags) { unsigned int time_delta_us; - if (!is_battery_i2c(port, slave_addr_flags)) + if (!is_battery_i2c(port, addr_flags)) return; time_delta_us = time_since32(battery_last_i2c_time); @@ -119,7 +130,7 @@ void i2c_start_xfer_notify(const int port, const uint16_t slave_addr_flags) usleep(BATTERY_FREE_MIN_DELTA_US - time_delta_us); } -void i2c_end_xfer_notify(const int port, const uint16_t slave_addr_flags) +void i2c_end_xfer_notify(const int port, const uint16_t addr_flags) { /* * The bus free time needs to be maintained from last transaction @@ -141,18 +152,30 @@ static void cbi_init(void) sku_id = val; CPRINTS("SKU: %d", sku_id); } -DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); +DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C); -/* TODO: Casta: remove this routine after rev0 is not supported */ static void board_init(void) { - uint32_t val; - if (cbi_get_board_version(&val) == EC_SUCCESS && val > 0) + if (get_cbi_ssfc_charger() != SSFC_CHARGER_BQ25710) + return; + + chg_chips[0].drv = &bq25710_drv; + chg_chips[0].i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS; +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_INIT_I2C); + +static void set_input_limit_on_ac_removal(void) +{ + if (extpower_is_present()) + return; + + if (get_cbi_ssfc_charger() != SSFC_CHARGER_BQ25710) return; - gpio_set_flags(GPIO_USB_C0_MUX_INT_ODL, GPIO_INT_FALLING | GPIO_PULL_UP); + charger_set_input_current_limit(0, + CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT); } -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_AC_CHANGE, set_input_limit_on_ac_removal, HOOK_PRIO_DEFAULT); void board_overcurrent_event(int port, int is_overcurrented) { diff --git a/board/casta/board.h b/board/casta/board.h index 7f934dc4c6..3e7fe066cc 100644 --- a/board/casta/board.h +++ b/board/casta/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,17 +10,22 @@ /* Select Baseboard features */ #define VARIANT_OCTOPUS_EC_NPCX796FB -#define VARIANT_OCTOPUS_CHARGER_ISL9238 #define VARIANT_OCTOPUS_TCPC_0_PS8751 #define VARIANT_OCTOPUS_NO_SENSORS +#define CONFIG_CHARGER_RUNTIME_CONFIG #include "baseboard.h" +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + #define CONFIG_LED_COMMON -#define CONFIG_LED_POWER_LED /* USB PD */ #undef CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT -#define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT +/* + * This board configures two chargers, one of which can measure VBUS and one of + * which cannot. Leave the default config, which defines + * CONFIG_USB_PD_VBUS_MEASURE_CHARGER. + */ #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR @@ -30,7 +35,6 @@ * communicate on locked systems (which haven't PD negotiated). */ #define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC 1 #define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 15001 @@ -50,24 +54,28 @@ /* All casta systems are clamshells */ #undef CONFIG_TABLET_MODE -#undef CONFIG_TABLET_SWITCH /* TODO(b/119872005): Casta: confirm thermistor parts */ #define CONFIG_STEINHART_HART_3V3_13K7_47K_4050B #define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B /* Battery W/A */ +#define CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA 6144 #define CONFIG_CHARGER_PROFILE_OVERRIDE #define CONFIG_I2C_XFER_BOARD_CALLBACK +/* The board needs 100ms for VBUS_C[0|1]_BC12 to drop to lower VvbusUVLO */ +#undef CONFIG_BC12_MAX14637_DELAY_FROM_OFF_TO_ON_MS +#define CONFIG_BC12_MAX14637_DELAY_FROM_OFF_TO_ON_MS 100 + #ifndef __ASSEMBLER__ #include "gpio_signal.h" #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ ADC_CH_COUNT }; diff --git a/board/casta/build.mk b/board/casta/build.mk index 3d04b75731..998a65a3de 100644 --- a/board/casta/build.mk +++ b/board/casta/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/casta/ec.tasklist b/board/casta/ec.tasklist index ac41d643dc..5a1dc02a25 100644 --- a/board/casta/ec.tasklist +++ b/board/casta/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/casta/gpio.inc b/board/casta/gpio.inc index e37926b72e..724efd36ce 100644 --- a/board/casta/gpio.inc +++ b/board/casta/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/casta/led.c b/board/casta/led.c index 2f1a8a6b35..7dfdc39151 100644 --- a/board/casta/led.c +++ b/board/casta/led.c @@ -1,8 +1,8 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * - * Power and battery LED control for Casta + * Power and battery LED control for Casta */ #include "chipset.h" @@ -12,56 +12,59 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1 = 1; +__override const int led_charge_lvl_1 = 1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* Casta : There are 3 leds for AC, Battery and Power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0_BAT_LOW] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 0.5 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_BLUE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { /* Don't set led if led_auto_control is disabled. */ if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || - !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { return; - } + } - if (color == EC_LED_COLOR_BLUE) - { - gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); - gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); + if (color == EC_LED_COLOR_BLUE) { + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_ON_LVL); } else { /* LED_OFF and unsupported colors */ @@ -69,21 +72,20 @@ void led_set_color_power(enum ec_led_colors color) } } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { /* Don't set led if led_auto_control is disabled. */ if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || - !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { return; - } + } /* Battery leds must be turn off when blue led is on * because casta has 3-in-1 led. */ - if(!gpio_get_level(GPIO_PWR_LED_BLUE_L)) - { + if (!gpio_get_level(GPIO_PWR_LED_BLUE_L)) { gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ - gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ return; } @@ -117,14 +119,16 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { if (led_id == EC_LED_ID_BATTERY_LED) { gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); - gpio_set_level(GPIO_BAT_LED_GREEN_L, !brightness[EC_LED_COLOR_GREEN]); - gpio_set_level(GPIO_BAT_LED_RED_L, !brightness[EC_LED_COLOR_RED]); + gpio_set_level(GPIO_BAT_LED_GREEN_L, + !brightness[EC_LED_COLOR_GREEN]); + gpio_set_level(GPIO_BAT_LED_RED_L, + !brightness[EC_LED_COLOR_RED]); } else if (led_id == EC_LED_ID_POWER_LED) { - gpio_set_level(GPIO_PWR_LED_BLUE_L, !brightness[EC_LED_COLOR_BLUE]); + gpio_set_level(GPIO_PWR_LED_BLUE_L, + !brightness[EC_LED_COLOR_BLUE]); gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); } return EC_SUCCESS; } - diff --git a/board/casta/vif_override.xml b/board/casta/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/casta/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/cerise/battery.c b/board/cerise/battery.c index 50d2bf397c..9edab52867 100644 --- a/board/cerise/battery.c +++ b/board/cerise/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/cerise/board.c b/board/cerise/board.c index 0a04842e35..5ac4835abb 100644 --- a/board/cerise/board.c +++ b/board/cerise/board.c @@ -1,10 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" #include "charge_manager.h" @@ -31,6 +30,7 @@ #include "it8801.h" #include "keyboard_scan.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -40,41 +40,55 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { schedule_deferred_pd_interrupt(0 /* port */); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct i2c_port_t i2c_bitbang_ports[] = { - {"battery", 2, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA, .drv = &bitbang_drv}, + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, }; const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); @@ -82,13 +96,13 @@ const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * TODO(b/133200075): Tune this once we have the final performance * out of the driver and the i2c bus. @@ -107,8 +121,8 @@ struct keyboard_scan_config keyscan_config = { struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { [0] = { - .i2c_host_port = I2C_PORT_IO_EXPANDER_IT8801, - .i2c_slave_addr = IT8801_I2C_ADDR, + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, .drv = &it8801_ioexpander_drv, }, }; @@ -133,15 +147,18 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -static void board_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -149,13 +166,16 @@ static void board_hpd_status(const struct usb_mux *me, host_set_single_event(EC_HOST_EVENT_USB_MUX); } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, }, }; @@ -201,7 +221,7 @@ int board_set_active_charge_port(int charge_port) if (board_vbus_source_enabled(charge_port)) return -1; break; - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -209,22 +229,11 @@ int board_set_active_charge_port(int charge_port) */ charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - int board_discharge_on_ac(int enable) { int ret, port; @@ -254,7 +263,7 @@ int pd_snk_is_vbus_provided(int port) void bc12_interrupt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } #ifndef VARIANT_KUKUI_NO_SENSORS @@ -274,13 +283,12 @@ static void board_spi_enable(void) STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; /* Reinitialize spi peripheral. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); /* Pin mux spi peripheral toward the sensor. */ - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_spi_enable, +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, MOTION_SENSE_HOOK_PRIO - 1); static void board_spi_disable(void) @@ -288,14 +296,13 @@ static void board_spi_disable(void) /* Set pins to a state calming the sensor down. */ gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); - gpio_config_module(MODULE_SPI_MASTER, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); /* Disable spi peripheral and clocks. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_spi_disable, +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, MOTION_SENSE_HOOK_PRIO + 1); #endif /* !VARIANT_KUKUI_NO_SENSORS */ @@ -324,6 +331,9 @@ static void board_init(void) /* Enable BC12 interrupt */ gpio_enable_interrupt(GPIO_BC12_EC_INT_ODL); + + /* Enable USM mode */ + ioex_set_level(IOEX_5V_DC_DC_MODE_CTRL, 1); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -334,17 +344,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Rotation matrixes */ -static const mat33_fp_t base_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(-1), 0}, - {0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t lid_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(1), 0}, - {0, 0, FLOAT_TO_FP(1) } -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* sensor private data */ /* Lid accel private data */ @@ -394,9 +400,10 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = + ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .rot_standard_ref = &base_standard_ref, - .default_range = 2, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, .config = { @@ -422,7 +429,8 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = + ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_GYRO_MIN_FREQ, @@ -447,21 +455,24 @@ static void board_chipset_shutdown(void) } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); -int board_get_charger_i2c(void) +/* Called on AP S3 -> S0 transition, 5V DC-DC ctrl */ +static void board_chipset_resume(void) { - /* TODO(b:138415463): confirm the bus allocation for future builds */ - return board_get_version() == 1 ? 2 : 1; + /* Enable USM mode */ + ioex_set_level(IOEX_5V_DC_DC_MODE_CTRL, 1); } +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); -/* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) { - /* If the lid is in 360 position, ignore the lid angle, - * which might be faulty. Disable keyboard. - */ - if (tablet_get_mode() || chipset_in_state(CHIPSET_STATE_ANY_OFF)) - enable = 0; - keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); + /* Enable Normal mode */ + ioex_set_level(IOEX_5V_DC_DC_MODE_CTRL, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +int board_get_charger_i2c(void) +{ + /* TODO(b:138415463): confirm the bus allocation for future builds */ + return board_get_version() == 1 ? 2 : 1; } -#endif diff --git a/board/cerise/board.h b/board/cerise/board.h index 1ee3d931eb..cce105ae27 100644 --- a/board/cerise/board.h +++ b/board/cerise/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,6 +11,7 @@ #define VARIANT_KUKUI_JACUZZI #define VARIANT_KUKUI_BATTERY_SMART #define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32F098 #ifndef SECTION_IS_RW #define VARIANT_KUKUI_NO_SENSORS @@ -18,6 +19,9 @@ #include "baseboard.h" +/* Disable deferred (async) flash protect*/ +#undef CONFIG_FLASH_PROTECT_DEFERRED + #undef CONFIG_CHIPSET_POWER_SEQ_VERSION #define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 @@ -27,6 +31,8 @@ #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_RUNTIME_CONFIG @@ -50,14 +56,13 @@ #define CONFIG_USB_MUX_IT5205 #define CONFIG_LED_ONOFF_STATES -#define CONFIG_LED_POWER_LED +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 #define CONFIG_LED_COMMON /* Motion Sensors */ #ifndef VARIANT_KUKUI_NO_SENSORS -#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ #define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_CMD_ACCEL_INFO @@ -72,25 +77,24 @@ #endif /* VARIANT_KUKUI_NO_SENSORS */ /* I2C ports */ -#define I2C_PORT_BC12 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_BATTERY 2 -#define I2C_PORT_CHARGER board_get_charger_i2c() -#define I2C_PORT_SENSORS 1 -#define I2C_PORT_IO_EXPANDER_IT8801 1 -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_BATTERY 2 +#define I2C_PORT_CHARGER board_get_charger_i2c() +#define I2C_PORT_SENSORS 1 +#define I2C_PORT_KB_DISCRETE 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY + +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -/* Define the MKBP events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) #ifndef __ASSEMBLER__ @@ -127,6 +131,13 @@ enum battery_type { BATTERY_TYPE_COUNT, }; +enum BOARD_SKU_ID { + BOARD_SKU_ID_UNKNOWN = -1, + BOARD_SKU_ID_REV0 = 0, + BOARD_SKU_ID_REV1 = 1, + BOARD_SKU_ID_COUNT, +}; + #include "gpio_signal.h" #include "registers.h" @@ -138,7 +149,6 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void bc12_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); /* returns the i2c port number of charger */ int board_get_charger_i2c(void); diff --git a/board/cerise/build.mk b/board/cerise/build.mk index a6e1c010d7..f583684804 100644 --- a/board/cerise/build.mk +++ b/board/cerise/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/cerise/ec.tasklist b/board/cerise/ec.tasklist index 36be2e96a4..e77603a8e2 100644 --- a/board/cerise/ec.tasklist +++ b/board/cerise/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/cerise/gpio.inc b/board/cerise/gpio.inc index 51972ec367..6edf1f1eab 100644 --- a/board/cerise/gpio.inc +++ b/board/cerise/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -87,6 +87,8 @@ GPIO(USB_C0_DISCHARGE, PIN(B, 6), GPIO_OUT_LOW) IOEX(PWR_LED_WHITE_L, EXPIN(0, 1, 4), GPIO_OUT_HIGH) IOEX(BAT_LED_WHITE_L, EXPIN(0, 1, 3), GPIO_OUT_HIGH) IOEX(BAT_LED_AMBER_L, EXPIN(0, 1, 2), GPIO_OUT_HIGH) +IOEX(5V_DC_DC_MODE_CTRL, EXPIN(0, 0, 7), GPIO_OUT_LOW) + /* * TODO(b:138352732): On IT88801 expander, To be readded once IT8801 driver and * gpio expander framework has landed. @@ -111,5 +113,5 @@ ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) /* EMMC SPI SLAVE: PB13/14/15 */ ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) /* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ -ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_MASTER, 0) -ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/cerise/led.c b/board/cerise/led.c index ff5f9f2373..622ab9feb6 100644 --- a/board/cerise/led.c +++ b/board/cerise/led.c @@ -1,50 +1,53 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Damu */ #include "common.h" -#include "ioexpander.h" #include "driver/ioexpander/it8801.h" #include "ec_commands.h" +#include "hooks.h" +#include "ioexpander.h" #include "led_common.h" #include "led_onoff_states.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: @@ -62,25 +65,11 @@ void led_set_color_battery(enum ec_led_colors color) } } -void led_set_color_power(enum ec_led_colors color) -{ - switch (color) { - case EC_LED_COLOR_WHITE: - ioex_set_level(IOEX_PWR_LED_WHITE_L, LED_ON_LVL); - break; - default: - ioex_set_level(IOEX_PWR_LED_WHITE_L, LED_OFF_LVL); - break; - } -} - void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) { if (led_id == EC_LED_ID_BATTERY_LED) { brightness_range[EC_LED_COLOR_AMBER] = 1; brightness_range[EC_LED_COLOR_WHITE] = 1; - } else if (led_id == EC_LED_ID_POWER_LED) { - brightness_range[EC_LED_COLOR_WHITE] = 1; } } @@ -93,11 +82,6 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) led_set_color_battery(EC_LED_COLOR_WHITE); else led_set_color_battery(LED_OFF); - } else if (led_id == EC_LED_ID_POWER_LED) { - if (brightness[EC_LED_COLOR_WHITE] != 0) - led_set_color_power(EC_LED_COLOR_WHITE); - else - led_set_color_power(LED_OFF); } else { return EC_ERROR_INVAL; } diff --git a/board/cerise/vif_override.xml b/board/cerise/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/cerise/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/cherry/battery.c b/board/cherry/battery.c new file mode 100644 index 0000000000..4f3a12e43d --- /dev/null +++ b/board/cherry/battery.c @@ -0,0 +1,126 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "battery_smart.h" + +const struct board_batt_params board_battery_info[] = { + /* Panasonic AP16L5J Battery Information */ + [BATTERY_PANASONIC_AC16L5J] = { + .fuel_gauge = { + .manuf_name = "PANASONIC", + .device_name = "AP16L5J", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x4000, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + [BATTERY_PANASONIC_AC16L5J_KT00205009] = { + .fuel_gauge = { + .manuf_name = "PANASONIC KT00205009", + .device_name = "AP16L5J", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x4000, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* AP16L8J */ + [BATTERY_AP16L8J] = { + .fuel_gauge = { + .manuf_name = "LGC KT0020G010", + .device_name = "AP16L8J", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8700, + .voltage_normal = 7500, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* LGC AP18C8K Battery Information */ + [BATTERY_LGC_AP18C8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G020", + .device_name = "AP18C8K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_PANASONIC_AC16L5J; diff --git a/board/cherry/board.c b/board/cherry/board.c new file mode 100644 index 0000000000..8d3faaf621 --- /dev/null +++ b/board/cherry/board.c @@ -0,0 +1,294 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Cherry board configuration */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "console.h" +#include "driver/accel_bma422.h" +#include "driver/accel_kionix.h" +#include "driver/accel_kx022.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/retimer/ps8802.h" +#include "driver/usb_mux/anx3443.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "system.h" +#include "usb_mux.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Sensor */ +static struct mutex g_base_mutex; +static struct mutex g_lid_mutex; + +static struct icm_drv_data_t g_icm42607_data; +static struct kionix_accel_data g_kx022_data; +static struct accelgyro_saved_data_t g_bma422_data; + +/* Matrix to rotate accelrator into standard reference frame */ +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t motion_sensors[] = { + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_standard_ref, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, + }, + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g, enough for laptop. */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t bma422_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_PRIMARY, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .default_range = 2, /* g, enough for laptop. */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, +}; + +static void board_update_motion_sensor_config(void) +{ + if (system_get_board_version() >= 2) { + motion_sensors[LID_ACCEL] = bma422_lid_accel; + ccprints("LID ACCEL is BMA422"); + } else { + ccprints("LID ACCEL is KX022"); + } +} + +/* PWM */ + +/* + * PWM channels. Must be in the exactly same order as in enum pwm_channel. + * There total three 16 bits clock prescaler registers for all pwm channels, + * so use the same frequency and prescaler register setting is required if + * number of pwm channel greater than three. + */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED1] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4, + }, + [PWM_CH_LED2] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4, + }, + [PWM_CH_LED3] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4, + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .freq_hz = 10000, + .pcfsr_sel = PWM_PRESCALER_C6, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* USB Mux */ + +static int board_ps8762_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + /* Make sure the PS8802 is awake */ + RETURN_ERROR(ps8802_i2c_wake(me)); + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + RETURN_ERROR(ps8802_i2c_field_update16( + me, PS8802_REG_PAGE2, PS8802_REG2_USB_SSEQ_LEVEL, + PS8802_USBEQ_LEVEL_UP_MASK, + PS8802_USBEQ_LEVEL_UP_12DB)); + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* Boost the DP gain */ + RETURN_ERROR(ps8802_i2c_field_update8( + me, PS8802_REG_PAGE2, PS8802_REG2_DPEQ_LEVEL, + PS8802_DPEQ_LEVEL_UP_MASK, PS8802_DPEQ_LEVEL_UP_12DB)); + } + + return EC_SUCCESS; +} + +static int board_ps8762_mux_init(const struct usb_mux *me) +{ + return ps8802_i2c_field_update8(me, PS8802_REG_PAGE1, PS8802_REG_DCIRX, + PS8802_AUTO_DCI_MODE_DISABLE | + PS8802_FORCE_DCI_MODE, + PS8802_AUTO_DCI_MODE_DISABLE); +} + +static int board_anx3443_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + gpio_set_level(GPIO_USB_C1_DP_IN_HPD, + mux_state & USB_PD_MUX_DP_ENABLED); + return EC_SUCCESS; +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX0, + .i2c_addr_flags = PS8802_I2C_ADDR_FLAGS, + .driver = &ps8802_usb_mux_driver, + .board_init = &board_ps8762_mux_init, + .board_set = &board_ps8762_mux_set, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_USB_MUX1, + .i2c_addr_flags = ANX3443_I2C_ADDR0_FLAGS, + .driver = &anx3443_usb_mux_driver, + .board_set = &board_anx3443_mux_set, + }, + }, +}; + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable motion sensor interrupt */ + gpio_enable_interrupt(GPIO_BASE_IMU_INT_L); + gpio_enable_interrupt(GPIO_LID_ACCEL_INT_L); + + /* Disable PWM_CH_LED2(Green) for unuse */ + pwm_enable(PWM_CH_LED2, 0); + + board_update_motion_sensor_config(); + + if (board_get_version() >= 2) { + gpio_set_flags(GPIO_I2C_H_SCL, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_I2C_H_SDA, GPIO_INPUT | GPIO_PULL_DOWN); + } +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_do_chipset_resume(void) +{ + gpio_set_level(GPIO_EN_KB_BL, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_do_chipset_resume, HOOK_PRIO_DEFAULT); + +static void board_do_chipset_suspend(void) +{ + gpio_set_level(GPIO_EN_KB_BL, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_do_chipset_suspend, HOOK_PRIO_DEFAULT); diff --git a/board/cherry/board.h b/board/cherry/board.h new file mode 100644 index 0000000000..e15239dd64 --- /dev/null +++ b/board/cherry/board.h @@ -0,0 +1,107 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Cherry board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* Optional features */ +#define CONFIG_LTO +#define CONFIG_PRESERVE_LOGS + +/* + * TODO: Remove this option once the VBAT no longer keeps high when + * system's power isn't presented. + */ +#define CONFIG_IT83XX_RESET_PD_CONTRACT_IN_BRAM + +/* BC12 */ + +/* LED */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* PD / USB-C / PPC */ +#undef CONFIG_USB_PD_DEBUG_LEVEL /* default to 1, configurable in ec console \ + */ + +/* Optional console commands */ +#define CONFIG_CMD_FLASH +#define CONFIG_CMD_SCRATCHPAD + +#define CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV 9000 + +/* Keyboard */ +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* Sensor */ +#define CONFIG_GMR_TABLET_MODE +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH + +/* ICM426XX Base accel/gyro */ +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* KX022 Lid accel */ +#define CONFIG_ACCEL_KX022 + +/* BMA422 Lid accel */ +#define CONFIG_ACCEL_BMA4XX + +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_UPDATE + +/* SPI / Host Command */ +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + +/* USB-A */ +#define USBA_PORT_COUNT 1 + +/* Temperature */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum battery_type { + BATTERY_PANASONIC_AC16L5J, + BATTERY_PANASONIC_AC16L5J_KT00205009, + BATTERY_AP16L8J, + BATTERY_LGC_AP18C8K, + BATTERY_TYPE_COUNT, +}; + +enum sensor_id { + BASE_ACCEL = 0, + BASE_GYRO, + LID_ACCEL, + SENSOR_COUNT, +}; + +enum pwm_channel { + PWM_CH_LED1, + PWM_CH_LED2, + PWM_CH_LED3, + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +int board_accel_force_mode_mask(void); + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/cherry/build.mk b/board/cherry/build.mk new file mode 100644 index 0000000000..998e4d2750 --- /dev/null +++ b/board/cherry/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build + +# the IC is ITE IT8xxx2 +CHIP:=it83xx +CHIP_FAMILY:=it8xxx2 +CHIP_VARIANT:=it81202bx_1024 +BASEBOARD:=cherry + +board-y+=led.o battery.o board.o diff --git a/board/cherry/ec.tasklist b/board/cherry/ec.tasklist new file mode 100644 index 0000000000..5ce0fab583 --- /dev/null +++ b/board/cherry/ec.tasklist @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(DPS, dps_task, NULL, 1280) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, 1024) \ + diff --git a/board/cherry/gpio.inc b/board/cherry/gpio.inc new file mode 100644 index 0000000000..b953b16b27 --- /dev/null +++ b/board/cherry/gpio.inc @@ -0,0 +1,164 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH | GPIO_PULL_UP | + GPIO_HIB_WAKE_HIGH, power_button_interrupt) /* GSC_EC_PWR_BTN_ODL */ +GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, + lid_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(J, 7), GPIO_INT_BOTH, + gmr_tablet_switch_isr) + +/* Chipset interrupts */ +GPIO_INT(AP_EC_WARM_RST_REQ, PIN(D, 3), GPIO_INT_RISING | GPIO_SEL_1P8V, + chipset_reset_request_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 7), GPIO_INT_BOTH | GPIO_SEL_1P8V, + chipset_watchdog_interrupt) +GPIO_INT(AP_IN_SLEEP_L, PIN(F, 2), + GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PMIC_EC_PWRGD, PIN(F, 3), + GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) + +/* Sensor Interrupts */ +GPIO_INT(BASE_IMU_INT_L, PIN(M, 3), GPIO_INT_FALLING | GPIO_SEL_1P8V, + icm42607_interrupt) +/* USB-C interrupts */ +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(D, 1), GPIO_INT_BOTH, ppc_interrupt) +#ifdef BOARD_CHERRY +GPIO_INT(USB_C0_BC12_INT_ODL,PIN(J, 4), GPIO_INT_FALLING, bc12_interrupt) +#else /* TOMATO */ +GPIO_INT(USB_C0_BC12_INT_ODL,PIN(I, 5), GPIO_INT_FALLING, bc12_interrupt) +#endif +GPIO_INT(USB_C1_INT_ODL, PIN(B, 2), GPIO_INT_FALLING, rt1718s_tcpc_interrupt) +/* TODO: not used in other devices? */ +GPIO(LID_ACCEL_INT_L, PIN(M, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V) + +/* Volume button interrupts */ +GPIO_INT(VOLUME_DOWN_L, PIN(D, 5), GPIO_INT_BOTH | GPIO_PULL_UP, + button_interrupt) /* EC_VOLDN_BTN_ODL */ +GPIO_INT(VOLUME_UP_L, PIN(D, 6), GPIO_INT_BOTH | GPIO_PULL_UP, + button_interrupt) /* EC_VOLUP_BTN_ODL */ + +/* Other interrupts */ +GPIO_INT(AC_PRESENT, PIN(E, 5), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, + extpower_interrupt) /* AC_OK / AC_PRESENT in rev1+ */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, + uart_deepsleep_interrupt) /* UART_DEBUG_TX_EC_RX */ +GPIO_INT(WP, PIN(I, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, + switch_interrupt) /* EC_FLASH_WP_OD */ +GPIO_INT(SPI0_CS, PIN(M, 5), GPIO_INT_FALLING, + spi_event) /* SPI slave Chip Select -- AP_SPI_EC_CS_L */ +#ifndef BOARD_CHERRY +GPIO_INT(AP_XHCI_INIT_DONE, PIN(J, 5), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + xhci_init_done_interrupt) +#endif + +/* Power Sequencing Signals */ +GPIO(EC_PMIC_EN_ODL, PIN(D, 0), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_PMIC_WATCHDOG_L, PIN(H, 0), GPIO_ODR_LOW | GPIO_SEL_1P8V) +GPIO(EN_PP5000_A, PIN(C, 6), GPIO_OUT_HIGH) +GPIO(PG_MT6315_PROC_B_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(PG_MT6360_ODL, PIN(F, 1), GPIO_INPUT) +GPIO(EN_SLP_Z, PIN(E, 3), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(B, 6), GPIO_ODR_LOW) +GPIO(EC_BL_EN_OD, PIN(B, 5), GPIO_ODR_LOW | GPIO_SEL_1P8V) + +/* MKBP event synchronization */ +GPIO(EC_INT_L, PIN(E, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_AP_INT_ODL */ + +/* USB and USBC Signals */ +GPIO(DP_PATH_SEL, PIN(G, 0), GPIO_OUT_HIGH) +GPIO(DP_DEMUX_EN, PIN(G, 1), GPIO_OUT_LOW) +GPIO(EC_AP_DP_HPD_ODL, PIN(J, 0), GPIO_ODR_HIGH) +GPIO(EN_PP5000_USB_A0_VBUS_X,PIN(B, 7), GPIO_OUT_LOW) +GPIO(USB_C0_DP_IN_HPD, PIN(H, 4), GPIO_OUT_LOW) +GPIO(USB_C1_DP_IN_HPD, PIN(J, 1), GPIO_OUT_LOW) +GPIO(USB_C0_FRS_EN, PIN(F, 0), GPIO_OUT_LOW) + +/* Misc Signals */ +GPIO(EN_KB_BL, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_BATT_PRES_ODL, PIN(C, 0), GPIO_INPUT) +GPIO(EN_EC_ID_ODL, PIN(H, 5), GPIO_ODR_LOW) +GPIO(ENTERING_RW, PIN(C, 5), GPIO_OUT_LOW) /* EC_ENTERING_RW */ +GPIO(EN_5V_USM, PIN(G, 3), GPIO_OUT_LOW) +GPIO(USB_A0_FAULT_ODL, PIN(J, 6), GPIO_INPUT) +GPIO(PACKET_MODE_EN, PIN(D, 4), GPIO_OUT_LOW) /* EC_GSC_PACKET_MODE */ + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) /* I2C_CHG_BATT_SCL */ +GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) /* I2C_CHG_BATT_SDA */ +GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SCL */ +GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SDA */ +GPIO(I2C_C_SCL, PIN(F, 6), GPIO_INPUT) /* I2C_USB_C0_SCL */ +GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) /* I2C_USB_C0_SDA */ +GPIO(I2C_E_SCL, PIN(E, 0), GPIO_INPUT) /* I2C_USB_C1_SCL */ +GPIO(I2C_E_SDA, PIN(E, 7), GPIO_INPUT) /* I2C_USB_C1_SDA */ +GPIO(I2C_F_SCL, PIN(A, 4), GPIO_INPUT) /* Rev 2+ I2C_PROG_SCL */ +GPIO(I2C_F_SDA, PIN(A, 5), GPIO_INPUT) /* Rev 2+ I2C_PROG_SDA */ +GPIO(I2C_H_SCL, PIN(H, 1), GPIO_INPUT) /* Rev 0,1 I2C_PROG_SCL */ +GPIO(I2C_H_SDA, PIN(H, 2), GPIO_INPUT) /* Rev 0,1 I2C_PROG_SDA */ + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A */ +ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C B */ +ALTERNATE(PIN_MASK(F, 0xC0), 1, MODULE_I2C, 0) /* I2C C */ +ALTERNATE(PIN_MASK(E, 0x81), 1, MODULE_I2C, 0) /* I2C E */ + +/* UART */ +ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, 0) /* EC to Servo */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, 0b1111), 1, MODULE_PWM, 0) /* PWM 0,1,2,3 */ + +/* ADC */ +ALTERNATE(PIN_MASK(I, 0b11001001), 0, MODULE_ADC, 0) /* ADC 0,3,6,7 */ + +/* SPI */ +ALTERNATE(PIN_MASK(M, 0x33), 0, MODULE_SPI, 0) /* SPI */ + +/* Unimplemented Pins */ +GPIO(PG_PP5000_S5_OD, PIN(D, 2), GPIO_INPUT) +/* *_ODL pin has external pullup so don't pull it down. */ +GPIO(PG_MT6315_GPU_ODL, PIN(H, 6), GPIO_INPUT) +/* reserved for future use */ +GPIO(CCD_MODE_ODL, PIN(C, 4), GPIO_INPUT) +/* + * ADC pins don't have internal pull-down capability, + * so we set them as output low. + */ +#ifdef BOARD_CHERRY +GPIO(NC_GPI5, PIN(I, 5), GPIO_OUT_LOW) +#else +GPIO(NC_GPJ4, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +#endif +/* NC pins, enable internal pull-up/down to avoid floating state. */ +GPIO(NC_GPA1, PIN(A, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(PWM7, PIN(A, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(EC_NVME_PLN_ODL, PIN(D, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(SPI_CLK_GPG6, PIN(G, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(PG_NVME_OD, PIN(H, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(EN_PP2500_NVME_X, PIN(J, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(EN_PP1200_NVME_X, PIN(J, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPM6, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) +/* + * These pins don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(SPI_MOSI_GPG4, PIN(G, 4), GPIO_OUT_LOW) +GPIO(SPI_MISO_GPG5, PIN(G, 5), GPIO_OUT_LOW) +GPIO(SPI_CS_GPG7, PIN(G, 7), GPIO_OUT_LOW) +GPIO(EC_ID0, PIN(I, 1), GPIO_OUT_LOW) +GPIO(EC_ID1, PIN(I, 2), GPIO_OUT_LOW) + +/* Other unused pins */ +GPIO(NVME_EC_PLA_S3_ODL, PIN(I, 7), GPIO_INPUT) + diff --git a/board/cherry/led.c b/board/cherry/led.c new file mode 100644 index 0000000000..0607301d4c --- /dev/null +++ b/board/cherry/led.c @@ -0,0 +1,96 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "pwm.h" + +#define LED_OFF_LVL 0 +#define LED_ON_LVL 1 + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_S5] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + pwm_enable(PWM_CH_LED1, LED_ON_LVL); + pwm_enable(PWM_CH_LED3, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + pwm_enable(PWM_CH_LED1, LED_OFF_LVL); + pwm_enable(PWM_CH_LED3, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + pwm_enable(PWM_CH_LED1, LED_OFF_LVL); + pwm_enable(PWM_CH_LED3, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else + led_set_color_battery(LED_OFF); + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/cherry/vif_override.xml b/board/cherry/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/cherry/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/cherry_scp/board.h b/board/cherry_scp/board.h new file mode 100644 index 0000000000..28c9d8cc5e --- /dev/null +++ b/board/cherry_scp/board.h @@ -0,0 +1,33 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Cherry SCP configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* + * RW only, no flash + * +-------------------- 0x0 + * | ROM vectortable, .text, .rodata, .data LMA + * +-------------------- 0x6f000 + * | RAM .bss, .data + * +-------------------- 0xbfc00 + * | Reserved (padding for 1k-alignment) + * +-------------------- 0xbfdb0 + * | IPI shared buffer with AP (288 + 8) * 2 + * +-------------------- 0xc0000 + */ +#define CONFIG_ROM_BASE 0x0 +#define CONFIG_RAM_BASE 0x6f000 +#define CONFIG_ROM_SIZE (CONFIG_RAM_BASE - CONFIG_ROM_BASE) +#define CONFIG_RAM_SIZE \ + ((CONFIG_IPC_SHARED_OBJ_ADDR & (~(0x400 - 1))) - CONFIG_RAM_BASE) + +#define SCP_FW_END 0xc0000 + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/cherry_scp/build.mk b/board/cherry_scp/build.mk new file mode 100644 index 0000000000..498bee2848 --- /dev/null +++ b/board/cherry_scp/build.mk @@ -0,0 +1,11 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=mt_scp +CHIP_VARIANT:=mt8195 +BASEBOARD:=mtscp-rv32i diff --git a/board/cherry_scp/ec.tasklist b/board/cherry_scp/ec.tasklist new file mode 100644 index 0000000000..353e5ee686 --- /dev/null +++ b/board/cherry_scp/ec.tasklist @@ -0,0 +1,18 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(VDEC_SERVICE, vdec_service_task, NULL, 4096) \ + TASK_ALWAYS(VDEC_CORE_SERVICE, vdec_core_service_task, NULL, 4096) \ + TASK_ALWAYS(VENC_SERVICE, venc_service_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MDP_SERVICE, mdp_service_task, NULL, 4096) \ + TASK_ALWAYS(SR, sr_task, NULL, TASK_STACK_SIZE) diff --git a/board/cherry_scp/gpio.inc b/board/cherry_scp/gpio.inc new file mode 100644 index 0000000000..8301fb437f --- /dev/null +++ b/board/cherry_scp/gpio.inc @@ -0,0 +1,10 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Unimplemented signals which we need to emulate for now */ +UNIMPLEMENTED(ENTERING_RW) +UNIMPLEMENTED(WP_L) diff --git a/board/cheza/base_detect.c b/board/cheza/base_detect.c deleted file mode 100644 index 3999ad022f..0000000000 --- a/board/cheza/base_detect.c +++ /dev/null @@ -1,216 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Lux base without battery detection code */ - -#include "adc.h" -#include "adc_chip.h" -#include "board.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "system.h" -#include "tablet_mode.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) - -/* Base detection and debouncing */ -#define BASE_DETECT_DEBOUNCE_US (20 * MSEC) - -/* - * If the base status is unclear (i.e. not within expected ranges, read - * the ADC value again every 500ms. - */ -#define BASE_DETECT_RETRY_US (500 * MSEC) - -/* - * When base is disconnected, and gets connected: - * Lid has 1M pull-up, base has 200K pull-down, so the ADC - * value should be around 200/(200+1000)*3300 = 550. - * - * Idle value should be ~3300: lid has 1M pull-up, and nothing else (i.e. ADC - * maxing out at 2813). - */ -#define BASE_DISCONNECTED_CONNECT_MIN_MV 450 -#define BASE_DISCONNECTED_CONNECT_MAX_MV 650 - -#define BASE_DISCONNECTED_MIN_MV 2800 -#define BASE_DISCONNECTED_MAX_MV (ADC_MAX_VOLT+1) - -/* - * When base is connected, then gets disconnected: - * Lid has 1M pull-up, lid has 10.0K pull-down, so the ADC - * value should be around 10.0/(10.0+1000)*3300 = 33. - * - * Idle level when connected should be: - * Lid has 10K pull-down, base has 5.1K pull-up, so the ADC value should be - * around 10.0/(10.0+5.1)*3300 = 2185 (actual value is 2153 as there is still - * a 1M pull-up on lid, and 200K pull-down on base). - */ -#define BASE_CONNECTED_DISCONNECT_MIN_MV 20 -#define BASE_CONNECTED_DISCONNECT_MAX_MV 45 - -#define BASE_CONNECTED_MIN_MV 2050 -#define BASE_CONNECTED_MAX_MV 2300 - -static uint64_t base_detect_debounce_time; - -static void base_detect_deferred(void); -DECLARE_DEFERRED(base_detect_deferred); - -enum base_status { - BASE_UNKNOWN = 0, - BASE_DISCONNECTED = 1, - BASE_CONNECTED = 2, -}; - -static enum base_status current_base_status; - -/* - * This function is called whenever there is a change in the base detect - * status. Actions taken include: - * 1. Enable/disable pull-down on half-duplex UART line - * 2. Enable/disable power to base. - * 3. Indicate mode change to host. - * 4. Indicate tablet mode to host. Current assumption is that if base is - * disconnected then the system is in tablet mode, else if the base is - * connected, then the system is not in tablet mode. - */ -static void base_detect_change(enum base_status status) -{ - int connected = (status == BASE_CONNECTED); - - if (current_base_status == status) - return; - - current_base_status = status; - - /* Enable pull-down if connected. */ - gpio_set_level(GPIO_EN_CC_LID_BASE_PULLDN, !connected); - - /* We don't enable dual-battery support. Set the base power directly. */ - gpio_set_level(GPIO_EN_PPVAR_VAR_BASE, connected); - - tablet_set_mode(!connected); -} - -static void print_base_detect_value(const char *str, int v) -{ - CPRINTS("Base %s. ADC: %d", str, v); -} - -static void base_detect_deferred(void) -{ - uint64_t time_now = get_time().val; - int v; - - if (base_detect_debounce_time > time_now) { - hook_call_deferred(&base_detect_deferred_data, - base_detect_debounce_time - time_now); - return; - } - - v = adc_read_channel(ADC_BASE_DET); - if (v == ADC_READ_ERROR) - goto retry; - - if (current_base_status == BASE_CONNECTED) { - if (v >= BASE_CONNECTED_DISCONNECT_MIN_MV && - v <= BASE_CONNECTED_DISCONNECT_MAX_MV) { - print_base_detect_value("disconnected", v); - base_detect_change(BASE_DISCONNECTED); - return; - } else if (v >= BASE_CONNECTED_MIN_MV && - v <= BASE_CONNECTED_MAX_MV) { - /* Still connected. */ - return; - } - } else { /* Disconnected or unknown. */ - if (v >= BASE_DISCONNECTED_CONNECT_MIN_MV && - v <= BASE_DISCONNECTED_CONNECT_MAX_MV) { - print_base_detect_value("connected", v); - base_detect_change(BASE_CONNECTED); - return; - } else if (v >= BASE_DISCONNECTED_MIN_MV && - v <= BASE_DISCONNECTED_MAX_MV) { - if (current_base_status == BASE_UNKNOWN) { - print_base_detect_value("disconnected", v); - base_detect_change(BASE_DISCONNECTED); - } - /* Still disconnected. */ - return; - } - } - -retry: - print_base_detect_value("status unclear", v); - /* Unclear base status, schedule again in a while. */ - hook_call_deferred(&base_detect_deferred_data, - BASE_DETECT_RETRY_US); -} - -void base_detect_interrupt(enum gpio_signal signal) -{ - uint64_t time_now = get_time().val; - - if (base_detect_debounce_time <= time_now) - hook_call_deferred(&base_detect_deferred_data, - BASE_DETECT_DEBOUNCE_US); - - base_detect_debounce_time = time_now + BASE_DETECT_DEBOUNCE_US; -} - -static void base_detect_enable(void) -{ - /* Enable base detection interrupt. */ - base_detect_debounce_time = get_time().val; - hook_call_deferred(&base_detect_deferred_data, 0); - gpio_enable_interrupt(GPIO_CC_LID_BASE_ADC); -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, base_detect_enable, HOOK_PRIO_DEFAULT); - -static void base_detect_disable(void) -{ - /* Disable base detection interrupt and disable power to base. */ - gpio_disable_interrupt(GPIO_CC_LID_BASE_ADC); - base_detect_change(BASE_DISCONNECTED); -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, base_detect_disable, HOOK_PRIO_DEFAULT); - -static void base_init(void) -{ - /* - * Make sure base power and pull-down are off. This will reset the base - * if it is already connected. - */ - gpio_set_level(GPIO_EN_PPVAR_VAR_BASE, 0); - gpio_set_level(GPIO_EN_CC_LID_BASE_PULLDN, 1); -} -DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT+1); - -void base_force_state(int state) -{ - if (state == 1) { - gpio_disable_interrupt(GPIO_CC_LID_BASE_ADC); - base_detect_change(BASE_CONNECTED); - CPRINTS("BD forced connected"); - } else if (state == 0) { - gpio_disable_interrupt(GPIO_CC_LID_BASE_ADC); - base_detect_change(BASE_DISCONNECTED); - CPRINTS("BD forced disconnected"); - } else { - hook_call_deferred(&base_detect_deferred_data, 0); - gpio_enable_interrupt(GPIO_CC_LID_BASE_ADC); - CPRINTS("BD forced reset"); - } -} diff --git a/board/cheza/battery.c b/board/cheza/battery.c deleted file mode 100644 index ab98864a9a..0000000000 --- a/board/cheza/battery.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery.h" -#include "battery_smart.h" - -/* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS -#define SB_SHUTDOWN_DATA 0x0010 - -/* Battery info */ -static const struct battery_info info = { - .voltage_max = 8800, - .voltage_normal = 7700, - .voltage_min = 6000, - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 45, - .discharging_min_c = -10, - .discharging_max_c = 60, -}; - -const struct battery_info *battery_get_info(void) -{ - return &info; -} - -int board_cut_off_battery(void) -{ - int rv; - - /* Ship mode command must be sent twice to take effect */ - rv = sb_write(SB_SHIP_MODE_REG, SB_SHUTDOWN_DATA); - - if (rv != EC_SUCCESS) - return rv; - - return sb_write(SB_SHIP_MODE_REG, SB_SHUTDOWN_DATA); -} diff --git a/board/cheza/board.c b/board/cheza/board.c deleted file mode 100644 index d8901bc845..0000000000 --- a/board/cheza/board.c +++ /dev/null @@ -1,706 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Cheza board-specific configuration */ - -#include "adc_chip.h" -#include "als.h" -#include "button.h" -#include "charge_manager.h" -#include "charge_state.h" -#include "chipset.h" -#include "extpower.h" -#include "driver/accelgyro_bmi_common.h" -#include "driver/als_opt3001.h" -#include "driver/charger/isl923x.h" -#include "driver/ppc/sn5s330.h" -#include "driver/tcpm/anx74xx.h" -#include "driver/tcpm/ps8xxx.h" -#include "driver/tcpm/tcpci.h" -#include "gpio.h" -#include "hooks.h" -#include "lid_switch.h" -#include "pi3usb9281.h" -#include "power.h" -#include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "system.h" -#include "shi_chip.h" -#include "switch.h" -#include "task.h" -#include "usb_charge.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usbc_ppc.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -#define USB_PD_PORT_ANX3429 0 -#define USB_PD_PORT_PS8751 1 - -/* Forward declaration */ -static void tcpc_alert_event(enum gpio_signal signal); -static void vbus0_evt(enum gpio_signal signal); -static void vbus1_evt(enum gpio_signal signal); -static void usb0_evt(enum gpio_signal signal); -static void usb1_evt(enum gpio_signal signal); -static void ppc_interrupt(enum gpio_signal signal); -static void anx74xx_cable_det_interrupt(enum gpio_signal signal); -static void usb1_oc_evt(enum gpio_signal signal); - -#include "gpio_list.h" - -/* GPIO Interrupt Handlers */ -static void tcpc_alert_event(enum gpio_signal signal) -{ - int port = -1; - - switch (signal) { - case GPIO_USB_C0_PD_INT_ODL: - port = 0; - break; - case GPIO_USB_C1_PD_INT_ODL: - port = 1; - break; - default: - return; - } - - schedule_deferred_pd_interrupt(port); -} - -static void vbus0_evt(enum gpio_signal signal) -{ - /* VBUS present GPIO is inverted */ - usb_charger_vbus_change(0, !gpio_get_level(GPIO_USB_C0_VBUS_DET_L)); - task_wake(TASK_ID_PD_C0); -} - -static void vbus1_evt(enum gpio_signal signal) -{ - /* VBUS present GPIO is inverted */ - usb_charger_vbus_change(1, !gpio_get_level(GPIO_USB_C1_VBUS_DET_L)); - task_wake(TASK_ID_PD_C1); -} - -static void usb0_evt(enum gpio_signal signal) -{ - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); -} - -static void usb1_evt(enum gpio_signal signal) -{ - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); -} - -static void anx74xx_cable_det_handler(void) -{ - int cable_det = gpio_get_level(GPIO_USB_C0_CABLE_DET); - int reset_n = gpio_get_level(GPIO_USB_C0_PD_RST_R_L); - - /* - * A cable_det low->high transition was detected. If following the - * debounce time, cable_det is high, and reset_n is low, then ANX3429 is - * currently in standby mode and needs to be woken up. Set the - * TCPC_RESET event which will bring the ANX3429 out of standby - * mode. Setting this event is gated on reset_n being low because the - * ANX3429 will always set cable_det when transitioning to normal mode - * and if in normal mode, then there is no need to trigger a tcpc reset. - */ - if (cable_det && !reset_n) - task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); -} -DECLARE_DEFERRED(anx74xx_cable_det_handler); - -static void anx74xx_cable_det_interrupt(enum gpio_signal signal) -{ - /* debounce for 2 msec */ - hook_call_deferred(&anx74xx_cable_det_handler_data, (2 * MSEC)); -} - -static void ppc_interrupt(enum gpio_signal signal) -{ - /* Only port-0 uses PPC chip */ - sn5s330_interrupt(0); -} - -static void usb1_oc_evt_deferred(void) -{ - /* Only port-1 has overcurrent GPIO interrupt */ - board_overcurrent_event(1, 1); -} -DECLARE_DEFERRED(usb1_oc_evt_deferred); - -static void usb1_oc_evt(enum gpio_signal signal) -{ - /* Switch the context to handle the event */ - hook_call_deferred(&usb1_oc_evt_deferred_data, 0); -} - -/* Wake-up pins for hibernate */ -const enum gpio_signal hibernate_wake_pins[] = { - GPIO_LID_OPEN, - GPIO_AC_PRESENT, - GPIO_POWER_BUTTON_L, - GPIO_EC_RST_ODL, -}; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); - -/* ADC channels */ -const struct adc_t adc_channels[] = { - /* Base detection */ - [ADC_BASE_DET] = { - "BASE_DET", - NPCX_ADC_CH0, - ADC_MAX_VOLT, - ADC_READ_MAX + 1, - 0 - }, - /* Measure VBUS through a 1/10 voltage divider */ - [ADC_VBUS] = { - "VBUS", - NPCX_ADC_CH1, - ADC_MAX_VOLT * 10, - ADC_READ_MAX + 1, - 0 - }, - /* - * Adapter current output or battery charging/discharging current (uV) - * 18x amplification on charger side. - */ - [ADC_AMON_BMON] = { - "AMON_BMON", - NPCX_ADC_CH2, - ADC_MAX_VOLT * 1000 / 18, - ADC_READ_MAX + 1, - 0 - }, - /* - * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read - * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and - * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we - * only divide by 2 (enough to avoid precision issues). - */ - [ADC_PSYS] = { - "PSYS", - NPCX_ADC_CH3, - ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), - 2, - 0 - }, -}; -BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - -const struct pwm_t pwm_channels[] = { - /* TODO(waihong): Assign a proper frequency. */ - [PWM_CH_DISPLIGHT] = { 5, 0, 4800 }, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - - -/* Power signal list. Must match order of enum power_signal. */ -const struct power_signal_info power_signal_list[] = { - [SDM845_AP_RST_ASSERTED] = { - GPIO_AP_RST_L, - POWER_SIGNAL_ACTIVE_LOW | POWER_SIGNAL_DISABLE_AT_BOOT, - "AP_RST_ASSERTED"}, - [SDM845_PS_HOLD] = { - GPIO_PS_HOLD, - POWER_SIGNAL_ACTIVE_HIGH, - "PS_HOLD"}, - [SDM845_PMIC_FAULT_L] = { - GPIO_PMIC_FAULT_L, - POWER_SIGNAL_ACTIVE_HIGH | POWER_SIGNAL_DISABLE_AT_BOOT, - "PMIC_FAULT_L"}, - [SDM845_POWER_GOOD] = { - GPIO_POWER_GOOD, - POWER_SIGNAL_ACTIVE_HIGH, - "POWER_GOOD"}, - [SDM845_WARM_RESET] = { - GPIO_WARM_RESET_L, - POWER_SIGNAL_ACTIVE_HIGH, - "WARM_RESET_L"}, -}; -BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); - -/* I2C port map */ -const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - /* TODO(b/78189419): ANX7428 operates at 400kHz initially. */ - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 1000, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/* Power Path Controller */ -struct ppc_config_t ppc_chips[] = { - { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, - /* - * Port 1 uses two power switches instead: - * NX5P3290: to source VBUS - * NX20P5090: to sink VBUS (charge battery) - * which are controlled directly by EC GPIOs. - */ -}; -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -/* TCPC mux configuration */ -const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - /* Alert is active-low, open-drain */ - [USB_PD_PORT_ANX3429] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_TCPC0, - .addr_flags = 0x28, - }, - .drv = &anx74xx_tcpm_drv, - .flags = TCPC_FLAGS_ALERT_OD, - }, - [USB_PD_PORT_PS8751] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_TCPC1, - .addr_flags = 0x0B, - }, - .drv = &ps8xxx_tcpm_drv, - }, -}; - -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = ISL923X_ADDR_FLAGS, - .drv = &isl923x_drv, - }, -}; - -/* - * Port-0 USB mux driver. - * - * The USB mux is handled by TCPC chip and the HPD is handled by AP. - * Redirect to anx74xx_tcpm_usb_mux_driver but override the get() function - * to check the HPD_IRQ mask from virtual_usb_mux_driver. - */ -static int port0_usb_mux_init(const struct usb_mux *me) -{ - return anx74xx_tcpm_usb_mux_driver.init(me); -} - -static int port0_usb_mux_set(const struct usb_mux *me, mux_state_t mux_state) -{ - return anx74xx_tcpm_usb_mux_driver.set(me, mux_state); -} - -static int port0_usb_mux_get(const struct usb_mux *me, mux_state_t *mux_state) -{ - int rv; - mux_state_t virtual_mux_state; - - rv = anx74xx_tcpm_usb_mux_driver.get(me, mux_state); - rv |= virtual_usb_mux_driver.get(me, &virtual_mux_state); - - if (virtual_mux_state & USB_PD_MUX_HPD_IRQ) - *mux_state |= USB_PD_MUX_HPD_IRQ; - return rv; -} - -const struct usb_mux_driver port0_usb_mux_driver = { - .init = port0_usb_mux_init, - .set = port0_usb_mux_set, - .get = port0_usb_mux_get, -}; - -/* - * Port-1 USB mux driver. - * - * The USB mux is handled by TCPC chip and the HPD is handled by AP. - * Redirect to tcpci_tcpm_usb_mux_driver but override the get() function - * to check the HPD_IRQ mask from virtual_usb_mux_driver. - */ -static int port1_usb_mux_init(const struct usb_mux *me) -{ - return tcpci_tcpm_usb_mux_driver.init(me); -} - -static int port1_usb_mux_set(const struct usb_mux *me, mux_state_t mux_state) -{ - return tcpci_tcpm_usb_mux_driver.set(me, mux_state); -} - -static int port1_usb_mux_get(const struct usb_mux *me, mux_state_t *mux_state) -{ - int rv; - mux_state_t virtual_mux_state; - - rv = tcpci_tcpm_usb_mux_driver.get(me, mux_state); - rv |= virtual_usb_mux_driver.get(me, &virtual_mux_state); - - if (virtual_mux_state & USB_PD_MUX_HPD_IRQ) - *mux_state |= USB_PD_MUX_HPD_IRQ; - return rv; -} - -static int port1_usb_mux_enter_low_power(const struct usb_mux *me) -{ - return tcpci_tcpm_usb_mux_driver.enter_low_power_mode(me); -} - -const struct usb_mux_driver port1_usb_mux_driver = { - .init = &port1_usb_mux_init, - .set = &port1_usb_mux_set, - .get = &port1_usb_mux_get, - .enter_low_power_mode = &port1_usb_mux_enter_low_power, -}; - -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .driver = &port0_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - { - .usb_port = 1, - .driver = &port1_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - } -}; - -/* BC1.2 */ -struct pi3usb9281_config pi3usb9281_chips[] = { - { - .i2c_port = I2C_PORT_POWER, - }, - { - .i2c_port = I2C_PORT_EEPROM, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) == - CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT); - -/* Initialize board. */ -static void board_init(void) -{ - /* Enable BC1.2 VBUS detection */ - gpio_enable_interrupt(GPIO_USB_C0_VBUS_DET_L); - gpio_enable_interrupt(GPIO_USB_C1_VBUS_DET_L); - - /* Enable BC1.2 interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); - - /* Enable interrupt for BMI160 sensor */ - gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -void board_tcpc_init(void) -{ - /* Only reset TCPC if not sysjump */ - if (!system_jumped_late()) { - /* TODO(crosbug.com/p/61098): How long do we need to wait? */ - board_reset_pd_mcu(); - } - - /* Enable PPC interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); - - /* Enable TCPC interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); - - /* Enable CABLE_DET interrupt for ANX3429 wake from standby */ - gpio_enable_interrupt(GPIO_USB_C0_CABLE_DET); - - /* - * Initialize HPD to low; after sysjump SOC needs to see - * HPD pulse to enable video path - */ - for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); - -/* Called on AP S0 -> S3 transition */ -static void board_chipset_suspend(void) -{ - /* - * Turn off display backlight in S3. AP has its own control. The EC's - * and the AP's will be AND'ed together in hardware. - */ - gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); - -/* Called on AP S3 -> S0 transition */ -static void board_chipset_resume(void) -{ - /* Turn on display backlight in S0. */ - gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); - -/* Called on AP S5 -> S3 transition */ -static void board_chipset_startup(void) -{ - gpio_set_flags(GPIO_USB_C1_OC_ODL, GPIO_INT_FALLING | GPIO_PULL_UP); - gpio_enable_interrupt(GPIO_USB_C1_OC_ODL); -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); - -/* Called on AP S3 -> S5 transition */ -static void board_chipset_shutdown(void) -{ - /* 5V is off in S5. Disable pull-up to prevent current leak. */ - gpio_disable_interrupt(GPIO_USB_C1_OC_ODL); - gpio_set_flags(GPIO_USB_C1_OC_ODL, GPIO_INT_FALLING); -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); - -/** - * Power on (or off) a single TCPC. - * minimum on/off delays are included. - * - * @param port Port number of TCPC. - * @param mode 0: power off, 1: power on. - */ -void board_set_tcpc_power_mode(int port, int mode) -{ - if (port != USB_PD_PORT_ANX3429) - return; - - if (mode) { - gpio_set_level(GPIO_EN_USB_C0_TCPC_PWR, 1); - msleep(ANX74XX_PWR_H_RST_H_DELAY_MS); - gpio_set_level(GPIO_USB_C0_PD_RST_R_L, 1); - } else { - gpio_set_level(GPIO_USB_C0_PD_RST_R_L, 0); - msleep(ANX74XX_RST_L_PWR_L_DELAY_MS); - gpio_set_level(GPIO_EN_USB_C0_TCPC_PWR, 0); - msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS); - } -} - -void board_reset_pd_mcu(void) -{ - /* Assert reset */ - gpio_set_level(GPIO_USB_C0_PD_RST_R_L, 0); - gpio_set_level(GPIO_USB_C1_PD_RST_ODL, 0); - - msleep(MAX(1, ANX74XX_RST_L_PWR_L_DELAY_MS)); - gpio_set_level(GPIO_USB_C1_PD_RST_ODL, 1); - /* Disable TCPC0 (anx3429) power */ - gpio_set_level(GPIO_EN_USB_C0_TCPC_PWR, 0); - - msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS); - board_set_tcpc_power_mode(USB_PD_PORT_ANX3429, 1); -} - -int board_vbus_sink_enable(int port, int enable) -{ - if (port == USB_PD_PORT_ANX3429) { - /* Port 0 is controlled by a PPC SN5S330 */ - return ppc_vbus_sink_enable(port, enable); - } else if (port == USB_PD_PORT_PS8751) { - /* Port 1 is controlled by a power switch NX20P5090 */ - gpio_set_level(GPIO_EN_USB_C1_CHARGE_EC_L, !enable); - return EC_SUCCESS; - } - return EC_ERROR_INVAL; -} - -int board_is_sourcing_vbus(int port) -{ - if (port == USB_PD_PORT_ANX3429) { - /* Port 0 is controlled by a PPC SN5S330 */ - return ppc_is_sourcing_vbus(port); - } else if (port == USB_PD_PORT_PS8751) { - /* Port 1 is controlled by a power switch NX5P3290 */ - return gpio_get_level(GPIO_EN_USB_C1_5V_OUT); - } - return EC_ERROR_INVAL; -} - -void board_overcurrent_event(int port, int is_overcurrented) -{ - /* TODO(b/120231371): Notify AP */ - CPRINTS("p%d: overcurrent!", port); -} - -int board_set_active_charge_port(int port) -{ - int is_real_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); - int i; - int rv; - - if (!is_real_port && port != CHARGE_PORT_NONE) - return EC_ERROR_INVAL; - - CPRINTS("New chg p%d", port); - - if (port == CHARGE_PORT_NONE) { - /* Disable all ports. */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - rv = board_vbus_sink_enable(i, 0); - if (rv) { - CPRINTS("Disabling p%d sink path failed.", i); - return rv; - } - } - - return EC_SUCCESS; - } - - /* Check if the port is sourcing VBUS. */ - if (board_is_sourcing_vbus(port)) { - CPRINTF("Skip enable p%d", port); - return EC_ERROR_INVAL; - } - - /* - * Turn off the other ports' sink path FETs, before enabling the - * requested charge port. - */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - if (i == port) - continue; - - if (board_vbus_sink_enable(i, 0)) - CPRINTS("p%d: sink path disable failed.", i); - } - - /* Enable requested charge port. */ - if (board_vbus_sink_enable(port, 1)) { - CPRINTS("p%d: sink path enable failed.", port); - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* - * Ignore lower charge ceiling on PD transition if our battery is - * critical, as we may brownout. - */ - if (supplier == CHARGE_SUPPLIER_PD && - charge_ma < 1500 && - charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { - CPRINTS("Using max ilim %d", max_ma); - charge_ma = max_ma; - } - - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} - -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) - if (gpio_get_level(GPIO_USB_C0_PD_RST_R_L)) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) - if (gpio_get_level(GPIO_USB_C1_PD_RST_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} - -/* Mutexes */ -static struct mutex g_lid_mutex; - -static struct bmi_drv_data_t g_bmi160_data; -static struct opt3001_drv_data_t g_opt3001_data = { - .scale = 1, - .uscale = 0, - .offset = 0, -}; - -/* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; - -struct motion_sensor_t motion_sensors[] = { - /* - * Note: bmi160: supports accelerometer and gyro sensor - * Requirement: accelerometer sensor must init before gyro sensor - * DO NOT change the order of the following table. - */ - [LID_ACCEL] = { - .name = "Accel", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, - .chip = MOTIONSENSE_CHIP_BMI160, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &bmi160_drv, - .mutex = &g_lid_mutex, - .drv_data = &g_bmi160_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .rot_standard_ref = &base_standard_ref, - .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ - .min_frequency = BMI_ACCEL_MIN_FREQ, - .max_frequency = BMI_ACCEL_MAX_FREQ, - .config = { - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - }, - }, - [LID_GYRO] = { - .name = "Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, - .chip = MOTIONSENSE_CHIP_BMI160, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_LID, - .drv = &bmi160_drv, - .mutex = &g_lid_mutex, - .drv_data = &g_bmi160_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .default_range = 1000, /* dps */ - .rot_standard_ref = &base_standard_ref, - .min_frequency = BMI_GYRO_MIN_FREQ, - .max_frequency = BMI_GYRO_MAX_FREQ, - }, - [LID_ALS] = { - .name = "Light", - .active_mask = SENSOR_ACTIVE_S0, - .chip = MOTIONSENSE_CHIP_OPT3001, - .type = MOTIONSENSE_TYPE_LIGHT, - .location = MOTIONSENSE_LOC_LID, - .drv = &opt3001_drv, - .drv_data = &g_opt3001_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = OPT3001_I2C_ADDR_FLAGS, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1; uscale = 0 */ - .min_frequency = OPT3001_LIGHT_MIN_FREQ, - .max_frequency = OPT3001_LIGHT_MAX_FREQ, - .config = { - [SENSOR_CONFIG_EC_S0] = { - .odr = 1000, - }, - }, - }, -}; -const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); diff --git a/board/cheza/board.h b/board/cheza/board.h deleted file mode 100644 index 23a6b9f81a..0000000000 --- a/board/cheza/board.h +++ /dev/null @@ -1,229 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Cheza board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* TODO(waihong): Remove the following bringup features */ -#define CONFIG_BRINGUP -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands. */ -#define CONFIG_USB_PD_DEBUG_LEVEL 3 -#define CONFIG_CMD_AP_RESET_LOG -#define CONFIG_HOSTCMD_AP_RESET - -/* - * By default, enable all console messages excepted event and HC: - * The sensor stack is generating a lot of activity. - * They can be enabled through the console command 'chan'. - */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_HOSTCMD))) - -/* NPCX7 config */ -#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ -#define NPCX_TACH_SEL2 0 /* No tach. */ -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ - -/* Internal SPI flash on NPCX7 */ -#define CONFIG_FLASH_SIZE (1024 * 1024) /* 1MB internal spi flash */ -#define CONFIG_SPI_FLASH_REGS -#define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ -#define CONFIG_HOSTCMD_FLASH_SPI_INFO - -/* EC Modules */ -#define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_LED_COMMON -#define CONFIG_LOW_POWER_IDLE -#define CONFIG_ADC -#define CONFIG_BACKLIGHT_LID -#define CONFIG_FPU -#define CONFIG_PWM -#define CONFIG_PWM_DISPLIGHT - -#define CONFIG_VBOOT_HASH - -#define CONFIG_DETACHABLE_BASE - -#undef CONFIG_PECI - -#define CONFIG_HOSTCMD_SPS -#define CONFIG_HOST_COMMAND_STATUS -#define CONFIG_HOSTCMD_SECTION_SORTED /* Host commands are sorted. */ -#define CONFIG_MKBP_EVENT -#define CONFIG_KEYBOARD_PROTOCOL_MKBP -#define CONFIG_MKBP_USE_GPIO - -#define CONFIG_BOARD_VERSION_GPIO -#define CONFIG_POWER_BUTTON -#define CONFIG_VOLUME_BUTTONS -#define CONFIG_BUTTON_TRIGGERED_RECOVERY -#define CONFIG_EMULATED_SYSRQ -#define CONFIG_CMD_BUTTON -#define CONFIG_SWITCH -#define CONFIG_LID_SWITCH -#define CONFIG_EXTPOWER_GPIO - -#define CONFIG_TABLET_MODE -#define CONFIG_TABLET_MODE_SWITCH - -/* Battery */ -#define CONFIG_BATTERY_CUT_OFF -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_BATT_PRES_ODL -#define CONFIG_BATTERY_SMART - -/* Charger */ -#define CONFIG_CHARGER -#define CONFIG_CHARGE_MANAGER -#define CONFIG_CHARGER_ISL9238 -#define CONFIG_CHARGE_RAMP_HW -#define CONFIG_USB_CHARGER -#define CONFIG_CMD_CHARGER_ADC_AMON_BMON -#define CONFIG_CHARGER_PSYS -#define CONFIG_CHARGER_PSYS_READ -#define CONFIG_CHARGER_DISCHARGE_ON_AC - -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 -#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 7500 -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 - -/* BC 1.2 Charger */ -#define CONFIG_BC12_DETECT_PI3USB9281 -#define CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT 2 - -/* USB */ -#define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV1 -#define CONFIG_HOSTCMD_PD_CONTROL -#define CONFIG_USB_PD_ALT_MODE -#define CONFIG_USB_PD_ALT_MODE_DFP -#define CONFIG_USB_PD_DISCHARGE_PPC -#define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -#define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define CONFIG_USB_PD_TCPC_LOW_POWER -#define CONFIG_USB_PD_TCPM_ANX3429 -#define CONFIG_USB_PD_TCPM_PS8751 -#define CONFIG_USB_PD_TCPM_MUX -#define CONFIG_USB_PD_TCPM_TCPCI -#define CONFIG_USB_PD_TRY_SRC -#define CONFIG_USB_PD_VBUS_DETECT_CHARGER -#define CONFIG_USB_PD_5V_EN_CUSTOM -#define CONFIG_USB_MUX_VIRTUAL -#define CONFIG_USBC_PPC_SN5S330 -#define CONFIG_USBC_SS_MUX -#define CONFIG_USBC_VCONN -#define CONFIG_USBC_VCONN_SWAP - -/* RTC */ -#define CONFIG_CMD_RTC -#define CONFIG_HOSTCMD_RTC - -/* Sensors */ -#define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS -#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) -/* Enable sensor fifo, must also define the _SIZE and _THRES */ -#define CONFIG_ACCEL_FIFO -/* FIFO size is a power of 2. */ -#define CONFIG_ACCEL_FIFO_SIZE 256 -/* Depends on how fast the AP boots and typical ODRs. */ -#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) -#define CONFIG_CMD_ACCELS -#define CONFIG_CMD_ACCEL_INFO -#define CONFIG_ALS -#define CONFIG_ALS_OPT3001 -#define ALS_COUNT 1 -#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS - -/* PD */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 - -/* Chipset */ -#define CONFIG_CHIPSET_SDM845 -#define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_POWER_COMMON -#define CONFIG_POWER_PP5000_CONTROL - -/* NPCX Features */ -#define CONFIG_HIBERNATE_PSL - -/* I2C Ports */ -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_POWER -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_POWER NPCX_I2C_PORT0_0 -#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT5_0 -#define I2C_PORT_SENSOR NPCX_I2C_PORT7_0 - -/* GPIO alias */ -#define GPIO_PMIC_RESIN_L GPIO_PM845_RESIN_L - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -enum power_signal { - SDM845_AP_RST_ASSERTED = 0, - SDM845_PS_HOLD, - SDM845_PMIC_FAULT_L, - SDM845_POWER_GOOD, - SDM845_WARM_RESET, - /* Number of power signals */ - POWER_SIGNAL_COUNT -}; - -enum adc_channel { - ADC_BASE_DET, - ADC_VBUS, - ADC_AMON_BMON, - ADC_PSYS, - ADC_CH_COUNT -}; - -/* Motion sensors */ -enum sensor_id { - LID_ACCEL = 0, - LID_GYRO, - LID_ALS, - SENSOR_COUNT, -}; - -enum pwm_channel { - PWM_CH_DISPLIGHT, - PWM_CH_COUNT -}; - -/* Custom function to indicate if sourcing VBUS */ -int board_is_sourcing_vbus(int port); -/* Enable VBUS sink for a given port */ -int board_vbus_sink_enable(int port, int enable); -/* Reset all TCPCs. */ -void board_reset_pd_mcu(void); -/* Base detection interrupt handler */ -void base_detect_interrupt(enum gpio_signal signal); - -/* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ALS) - -#endif /* !defined(__ASSEMBLER__) */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/cheza/build.mk b/board/cheza/build.mk deleted file mode 100644 index 2e8e53ec88..0000000000 --- a/board/cheza/build.mk +++ /dev/null @@ -1,13 +0,0 @@ -# -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -CHIP:=npcx -CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m7wb - -board-y=battery.o board.o led.o usb_pd_policy.o base_detect.o diff --git a/board/cheza/ec.tasklist b/board/cheza/ec.tasklist deleted file mode 100644 index ef70197bac..0000000000 --- a/board/cheza/ec.tasklist +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/cheza/gpio.inc b/board/cheza/gpio.inc deleted file mode 100644 index bc9d12ad79..0000000000 --- a/board/cheza/gpio.inc +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -/* USB-C interrupts */ -GPIO_INT(USB_C0_PD_INT_ODL, PIN(A, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ -GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ -GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ -GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING, usb0_evt) /* Interrupt from port-0 BC1.2 */ -GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING, usb1_evt) /* Interrupt from port-1 BC1.2 */ -GPIO_INT(USB_C0_VBUS_DET_L, PIN(6, 2), GPIO_INT_BOTH | GPIO_PULL_UP, vbus0_evt) /* BC1.2 VBUS detection on port-0 */ -GPIO_INT(USB_C1_VBUS_DET_L, PIN(8, 3), GPIO_INT_BOTH | GPIO_PULL_UP, vbus1_evt) /* BC1.2 VBUS detection on port-1 */ -GPIO_INT(USB_C0_CABLE_DET, PIN(3, 7), GPIO_INT_RISING, anx74xx_cable_det_interrupt) /* Cable detection from port-0 TCPC */ -GPIO_INT(USB_C1_OC_ODL, PIN(7, 2), GPIO_INT_FALLING, usb1_oc_evt) /* Port-1 power switch over-current */ -GPIO_INT(ACCEL_GYRO_INT_L, PIN(D, 3), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) /* Accelerometer/gyro interrupt */ - -/* System interrupts */ -GPIO_INT(AC_PRESENT, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) /* ACOK_OD */ -GPIO_INT(POWER_BUTTON_L, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* EC_PWR_BTN_ODL */ -GPIO_INT(VOLUME_DOWN_L, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* EC_VOLDN_BTN_ODL */ -GPIO_INT(VOLUME_UP_L, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* EC_VOLUP_BTN_ODL */ -GPIO_INT(WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* EC_WP_ODL */ -GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) /* LID_OPEN_EC */ -GPIO_INT(AP_RST_REQ, PIN(C, 2), GPIO_INT_RISING | GPIO_PULL_DOWN | GPIO_SEL_1P8V, chipset_reset_request_interrupt) /* Reset request from AP */ -GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) -GPIO_INT(PS_HOLD, PIN(D, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ -GPIO_INT(PMIC_FAULT_L, PIN(7, 6), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) /* Any PMIC fault? */ -/* - * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down - * to make it low. Overload the interrupt function chipset_warm_reset_interrupt - * for not only signalling power_signal_interrupt but also handling the logic - * of WARM_RESET_L which is pulled-up by the same rail of POWER_GOOD. - */ -GPIO_INT(POWER_GOOD, PIN(5, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, chipset_warm_reset_interrupt) /* SRC_PP1800_S4A from PMIC */ -GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_warm_reset_interrupt) /* AP warm reset */ -GPIO_INT(SHI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* AP_EC_SPI_CS_L */ -GPIO_INT(CC_LID_BASE_ADC, PIN(4, 5), GPIO_INT_BOTH, base_detect_interrupt) /* Base detection */ - -/* - * EC_RST_ODL acts as a wake source from PSL hibernate mode. However, it does - * not need to be an interrupt for normal EC operations. Thus, configure it as - * GPIO_INT_BOTH with wake on low-to-high edge using GPIO_HIB_WAKE_HIGH so that - * PSL common code can configure PSL_IN correctly. - * - * Use the rising edge to wake EC up. If we chose the falling edge, it would - * still wake EC up, but EC is in an intermediate state until the signal goes - * back to high. - */ -GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* Wake source: EC reset */ -GPIO(ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* EC_ENTERING_RW: Indicate when EC is entering RW code */ -GPIO(CCD_MODE_ODL, PIN(E, 3), GPIO_INPUT) /* Case Closed Debug Mode */ -GPIO(BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* EC_BATT_PRES_ODL: Battery Present */ -GPIO(PROCHOT_L, PIN(3, 4), GPIO_INPUT) - -/* PMIC/AP 1.8V */ -GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC reset trigger */ -GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC power button */ -GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ -GPIO(AP_SUSPEND_L, PIN(5, 7), GPIO_INPUT) /* Suspend signal from AP */ - -/* Power enables */ -GPIO(SWITCHCAP_ON_L, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap. XXX: It's active-high */ -GPIO(VBOB_EN, PIN(9, 5), GPIO_OUT_LOW) /* Enable VBOB */ -GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ -GPIO(EN_PP5000, PIN(6, 7), GPIO_OUT_LOW) /* EN_PP5000_A: Enable PP5000 */ -GPIO(ENABLE_BACKLIGHT, PIN(B, 6), GPIO_OUT_LOW) /* EC_BL_DISABLE_L: Backlight disable signal from EC */ - -/* Sensors */ -GPIO(ALS_INT_L, PIN(5, 0), GPIO_INPUT) /* ALS sensor interrupt */ -GPIO(P_SENSOR_INT_L, PIN(F, 3), GPIO_INPUT | GPIO_SEL_1P8V) /* P-sensor interrupt */ -GPIO(RCAM_VSYNC, PIN(4, 0), GPIO_INPUT | GPIO_SEL_1P8V) /* VSYNC from rear camera */ - -/* Base */ -GPIO(EN_PPVAR_VAR_BASE, PIN(0, 4), GPIO_OUT_LOW) /* Power to the base */ -GPIO(EN_CC_LID_BASE_PH, PIN(D, 1), GPIO_ODR_HIGH) -GPIO(EN_CC_LID_BASE_PULLDN, PIN(D, 0), GPIO_ODR_HIGH) -GPIO(REVERSE_DOCK_EC, PIN(C, 6), GPIO_INPUT) /* Indicate if the dock is reversed */ -GPIO(CC_LID_RX_BASE_TX, PIN(7, 5), GPIO_INPUT) -GPIO(CC_LID_RX_BASE_RX, PIN(8, 6), GPIO_INPUT) - -/* LEDs */ -GPIO(CHG_LED_Y_C0, PIN(C, 3), GPIO_OUT_LOW) /* EC_CHG_LED_Y_C0 */ -GPIO(CHG_LED_W_C0, PIN(C, 4), GPIO_OUT_LOW) /* EC_CHG_LED_W_C0 */ -GPIO(CHG_LED_Y_C1, PIN(6, 0), GPIO_OUT_LOW) /* EC_CHG_LED_Y_C1 */ -GPIO(CHG_LED_W_C1, PIN(C, 0), GPIO_OUT_LOW) /* EC_CHG_LED_W_C1 */ - -/* - * USB HS muxes - * - * C0_MUX:D ----- C0_BC12 ---- C0_PORT - * AP --+------- C0_MUX:D1 - * | +--- C0_MUX:D2 - * | | - * | | - * | | C1_MUX:D ----- C1_BC12 ---- C1_PORT - * | | +- C1_MUX:D1 - * +------- C1_MUX:D2 - * | | - * AP --- USB_HUB - */ -/* Switch both port-0 and port-1 to the hub, which matches the SS path. */ -GPIO(USB_C0_HS_MUX_OE_L, PIN(A, 4), GPIO_OUT_LOW) -GPIO(USB_C0_HS_MUX_SEL, PIN(A, 3), GPIO_OUT_HIGH) /* L:D1(AP), H:D2(hub) */ -GPIO(USB_C1_HS_MUX_OE_L, PIN(7, 3), GPIO_OUT_LOW) -GPIO(USB_C1_HS_MUX_SEL, PIN(7, 4), GPIO_OUT_LOW) /* L:D1(hub), H:D2(AP) */ - -/* USB-C port-0 controls */ -GPIO(USB_C0_PD_RST_R_L, PIN(F, 1), GPIO_OUT_HIGH) /* Port-0 TCPC chip reset */ -GPIO(EN_USB_C0_TCPC_PWR, PIN(C, 5), GPIO_OUT_LOW) /* Port-0 TCPC power enable */ - -/* USB-C port-1 controls */ -GPIO(USB_C1_PD_RST_ODL, PIN(E, 4), GPIO_ODR_HIGH) /* Port-1 TCPC chip reset */ -GPIO(EN_USB_C1_5V_OUT, PIN(6, 3), GPIO_OUT_LOW) /* Port-1 power switch 5V output */ -GPIO(EN_USB_C1_3A, PIN(5, 6), GPIO_OUT_LOW) /* Port-1 power switch 3A current */ -GPIO(EN_USB_C1_CHARGE_EC_L, PIN(B, 1), GPIO_OUT_LOW) /* Port-1 enable charging */ -GPIO(USBC_MUX_CONF1, PIN(5, 1), GPIO_OUT_HIGH) /* Port-1 enable DP switch */ - -/* USB-C port-1 interrupts */ -GPIO(USB_C1_DP_HPD, PIN(9, 6), GPIO_INPUT) /* DP HPD from port-1 TCPC */ - -/* I2C */ -GPIO(I2C0_SCL, PIN(B, 5), GPIO_INPUT) /* EC_I2C_POWER_SCL */ -GPIO(I2C0_SDA, PIN(B, 4), GPIO_INPUT) /* EC_I2C_POWER_SDA */ -GPIO(I2C1_SCL, PIN(9, 0), GPIO_INPUT) /* EC_I2C_USB_C0_PD_SCL */ -GPIO(I2C1_SDA, PIN(8, 7), GPIO_INPUT) /* EC_I2C_USB_C0_PD_SDA */ -GPIO(I2C2_SCL, PIN(9, 2), GPIO_INPUT) /* EC_I2C_USB_C1_PD_SCL */ -GPIO(I2C2_SDA, PIN(9, 1), GPIO_INPUT) /* EC_I2C_USB_C1_PD_SDA */ -GPIO(I2C5_SCL, PIN(3, 3), GPIO_INPUT) /* EC_I2C_EEPROM_SCL */ -GPIO(I2C5_SDA, PIN(3, 6), GPIO_INPUT) /* EC_I2C_EEPROM_SDA */ -GPIO(I2C7_SCL, PIN(B, 3), GPIO_INPUT | - GPIO_SEL_1P8V) /* EC_I2C_SENSOR_SCL */ -GPIO(I2C7_SDA, PIN(B, 2), GPIO_INPUT | - GPIO_SEL_1P8V) /* EC_I2C_SENSOR_SDA */ - -/* Board/SKU IDs */ -GPIO(BOARD_VERSION1, PIN(C, 7), GPIO_INPUT) /* BRD_ID1 */ -GPIO(BOARD_VERSION2, PIN(9, 3), GPIO_INPUT) /* BRD_ID2 */ -GPIO(BOARD_VERSION3, PIN(8, 0), GPIO_INPUT) /* BRD_ID3 */ -GPIO(SKU_ID1, PIN(F, 0), GPIO_INPUT) -GPIO(SKU_ID2, PIN(4, 1), GPIO_INPUT) - -/* Switchcap */ -/* - * GPIO0 is configured as PVC_PG. When the chip in power down mode, it outputs - * high-Z. Set pull-down to avoid floating. - */ -GPIO(DA9313_GPIO0, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ - -/* Alternate functions GPIO definitions */ -ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ -ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ -ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1 SDA (GPIO90), I2C2 (GPIO91/92) */ -ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) */ -ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ -ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ -ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ -ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ -ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ -ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) */ -ALTERNATE(PIN_MASK(D, 0x04), 1, MODULE_PMU, 0) /* PSL_IN1 (GPIOD2) - LID_OPEN_EC */ -ALTERNATE(PIN_MASK(0, 0x01), 1, MODULE_PMU, 0) /* PSL_IN2 (GPIO00) - ACOK_OD */ -ALTERNATE(PIN_MASK(0, 0x02), 1, MODULE_PMU, 0) /* PSL_IN3 (GPIO01) - EC_PWR_BTN_ODL */ -ALTERNATE(PIN_MASK(0, 0x04), 1, MODULE_PMU, 0) /* PSL_IN4 (GPIO02) - EC_RST_ODL */ diff --git a/board/cheza/led.c b/board/cheza/led.c deleted file mode 100644 index 21ca78cb5c..0000000000 --- a/board/cheza/led.c +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Power and battery LED control. - */ - -#include "battery.h" -#include "charge_manager.h" -#include "charge_state.h" -#include "chipset.h" -#include "ec_commands.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "led_common.h" -#include "system.h" -#include "util.h" - -#define BAT_LED_ON 1 -#define BAT_LED_OFF 0 - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_RIGHT_LED, - EC_LED_ID_LEFT_LED, -}; - -const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); - -enum led_color { - LED_OFF = 0, - LED_AMBER, - LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ -}; - -static void side_led_set_color(int port, enum led_color color) -{ - gpio_set_level(port ? GPIO_CHG_LED_Y_C1 : GPIO_CHG_LED_Y_C0, - (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); - gpio_set_level(port ? GPIO_CHG_LED_W_C1 : GPIO_CHG_LED_W_C0, - (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); -} - -void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) -{ - brightness_range[EC_LED_COLOR_AMBER] = 1; - brightness_range[EC_LED_COLOR_WHITE] = 1; -} - -int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) -{ - int port; - - switch (led_id) { - case EC_LED_ID_RIGHT_LED: - port = 0; - break; - case EC_LED_ID_LEFT_LED: - port = 1; - break; - default: - return EC_ERROR_PARAM1; - } - - if (brightness[EC_LED_COLOR_WHITE] != 0) - side_led_set_color(port, LED_WHITE); - else if (brightness[EC_LED_COLOR_AMBER] != 0) - side_led_set_color(port, LED_AMBER); - else - side_led_set_color(port, LED_OFF); - - return EC_SUCCESS; -} - -/* - * Set active charge port color to the parameter, turn off all others. - * If no port is active (-1), turn off all LEDs. - */ -static void set_active_port_color(enum led_color color) -{ - int port = charge_manager_get_active_charge_port(); - - if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) - side_led_set_color(0, (port == 0) ? color : LED_OFF); - if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) - side_led_set_color(1, (port == 1) ? color : LED_OFF); -} - -static void board_led_set_battery(void) -{ - static int battery_ticks; - uint32_t chflags = charge_get_flags(); - - battery_ticks++; - - switch (charge_get_state()) { - case PWR_STATE_CHARGE: - /* Always indicate when charging, even in suspend. */ - set_active_port_color(LED_AMBER); - break; - case PWR_STATE_DISCHARGE: - if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { - if (charge_get_percent() <= 10) - side_led_set_color(0, - (battery_ticks & 0x4) ? LED_WHITE : LED_OFF); - else - side_led_set_color(0, LED_OFF); - } - - if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) - side_led_set_color(1, LED_OFF); - break; - case PWR_STATE_ERROR: - set_active_port_color((battery_ticks & 0x2) ? - LED_WHITE : LED_OFF); - break; - case PWR_STATE_CHARGE_NEAR_FULL: - set_active_port_color(LED_WHITE); - break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - set_active_port_color((battery_ticks & 0x4) ? - LED_AMBER : LED_OFF); - else - set_active_port_color(LED_WHITE); - break; - default: - /* Other states don't alter LED behavior */ - break; - } -} - -/* Called by hook task every TICK */ -static void led_tick(void) -{ - board_led_set_battery(); -} -DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); - -void led_control(enum ec_led_id led_id, enum ec_led_state state) -{ - enum led_color color; - - if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && - (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) - return; - - if (state == LED_STATE_RESET) { - led_auto_control(EC_LED_ID_LEFT_LED, 1); - led_auto_control(EC_LED_ID_RIGHT_LED, 1); - board_led_set_battery(); - return; - } - - color = state ? LED_WHITE : LED_OFF; - - led_auto_control(EC_LED_ID_LEFT_LED, 0); - led_auto_control(EC_LED_ID_RIGHT_LED, 0); - - side_led_set_color(0, color); - side_led_set_color(1, color); -} diff --git a/board/cheza/usb_pd_policy.c b/board/cheza/usb_pd_policy.c deleted file mode 100644 index 694899ab79..0000000000 --- a/board/cheza/usb_pd_policy.c +++ /dev/null @@ -1,203 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "charge_manager.h" -#include "console.h" -#include "gpio.h" -#include "pi3usb9281.h" -#include "system.h" -#include "usb_mux.h" -#include "usbc_ppc.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -int pd_check_vconn_swap(int port) -{ - /* TODO(waihong): Check any case we do not allow. */ - return 1; -} - -__override void pd_execute_data_swap(int port, - enum pd_data_role data_role) -{ - int enable = (data_role == PD_ROLE_UFP); - int type; - - /* - * Exclude the PD charger, in which the "USB Communications Capable" - * bit is unset in the Fixed Supply PDO. - */ - if (pd_capable(port)) - enable = enable && pd_get_partner_usb_comm_capable(port); - - /* - * The hub behind the BC1.2 chip may advertise a BC1.2 type. So - * disconnect the switch when getting the charger type to ensure - * the detected type is from external. - */ - usb_charger_set_switches(port, USB_SWITCH_DISCONNECT); - type = pi3usb9281_get_device_type(port); - usb_charger_set_switches(port, USB_SWITCH_RESTORE); - - /* Exclude the BC1.2 charger, which is not detected as CDP or SDP. */ - enable = enable && (type & (PI3USB9281_TYPE_CDP | PI3USB9281_TYPE_SDP)); - - /* Only mux one port to AP. If already muxed, return. */ - if (enable && (!gpio_get_level(GPIO_USB_C0_HS_MUX_SEL) || - gpio_get_level(GPIO_USB_C1_HS_MUX_SEL))) - return; - - /* Port-0 and port-1 have different polarities. */ - if (port == 0) - gpio_set_level(GPIO_USB_C0_HS_MUX_SEL, enable ? 0 : 1); - else if (port == 1) - gpio_set_level(GPIO_USB_C1_HS_MUX_SEL, enable ? 1 : 0); -} - -static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; - -static void board_vbus_update_source_current(int port) -{ - if (port == 0) { - /* - * Port 0 is controlled by a USB-C PPC SN5S330. - */ - ppc_set_vbus_source_current_limit(port, vbus_rp[port]); - ppc_vbus_source_enable(port, vbus_en[port]); - } else if (port == 1) { - /* - * Port 1 is controlled by a USB-C current-limited power - * switch, NX5P3290. Change the GPIO driving the load switch. - * - * 1.5 vs 3.0 A limit is controlled by a dedicated gpio. - * If the GPIO is asserted, it shorts a n-MOSFET to put a - * 16.5k resistance (2x 33k in parallel) on the NX5P3290 load - * switch ILIM pin, setting a minimum OCP current of 3100 mA. - * If the GPIO is deasserted, the n-MOSFET is open that makes - * a single 33k resistor on ILIM, setting a minimum OCP - * current of 1505 mA. - */ - gpio_set_level(GPIO_EN_USB_C1_3A, - vbus_rp[port] == TYPEC_RP_3A0 ? 1 : 0); - gpio_set_level(GPIO_EN_USB_C1_5V_OUT, vbus_en[port]); - } -} - -void pd_power_supply_reset(int port) -{ - int prev_en; - - prev_en = vbus_en[port]; - - /* Disable VBUS */ - vbus_en[port] = 0; - board_vbus_update_source_current(port); - - /* Enable discharge if we were previously sourcing 5V */ - if (prev_en) - pd_set_vbus_discharge(port, 1); - -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -int pd_set_power_supply_ready(int port) -{ - /* Disable charging */ - board_vbus_sink_enable(port, 0); - - pd_set_vbus_discharge(port, 0); - - /* Provide VBUS */ - vbus_en[port] = 1; - board_vbus_update_source_current(port); - - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; /* we are ready */ -} - -int board_vbus_source_enabled(int port) -{ - return vbus_en[port]; -} - -__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) -{ - vbus_rp[port] = rp; - board_vbus_update_source_current(port); -} - -int pd_snk_is_vbus_provided(int port) -{ - return !gpio_get_level(port ? GPIO_USB_C1_VBUS_DET_L : - GPIO_USB_C0_VBUS_DET_L); -} - -/* ----------------- Vendor Defined Messages ------------------ */ -/** - * Is the port fine to be muxed its DisplayPort lines? - * - * Only one port can be muxed to DisplayPort at a time. - * - * @param port Port number of TCPC. - * @return 1 is fine; 0 is bad as other port is already muxed; - */ -static int is_dp_muxable(int port) -{ - int i; - - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) - if (i != port) { - if (usb_mux_get(i) & USB_PD_MUX_DP_ENABLED) - return 0; - } - - return 1; -} - -extern uint32_t dp_status[CONFIG_USB_PD_PORT_MAX_COUNT]; -__override int svdm_dp_attention(int port, uint32_t *payload) -{ - int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); - int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); - int mf_pref = PD_VDO_DPSTS_MF_PREF(payload[1]); - - dp_status[port] = payload[1]; - - usb_mux_hpd_update(port, lvl, irq); - - if (lvl && is_dp_muxable(port)) { - /* - * The GPIO USBC_MUX_CONF1 enables the mux of the DP redriver - * for the port 1. - */ - gpio_set_level(GPIO_USBC_MUX_CONF1, port == 1); - - usb_mux_set(port, mf_pref ? - USB_PD_MUX_DOCK : USB_PD_MUX_DP_ENABLED, - USB_SWITCH_CONNECT, pd_get_polarity(port)); - } else { - usb_mux_set(port, mf_pref ? - USB_PD_MUX_USB_ENABLED : USB_PD_MUX_NONE, - USB_SWITCH_CONNECT, pd_get_polarity(port)); - } - - /* ack */ - return 1; -} diff --git a/board/chocodile_vpdmcu/board.c b/board/chocodile_vpdmcu/board.c index ea4d129502..098d7bb61b 100644 --- a/board/chocodile_vpdmcu/board.c +++ b/board/chocodile_vpdmcu/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* chocodile board configuration */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "gpio.h" #include "hooks.h" @@ -21,7 +20,7 @@ #include "util.h" #include "vpd_api.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) void board_config_pre_init(void) { @@ -29,6 +28,7 @@ void board_config_pre_init(void) STM32_RCC_APB2ENR |= 1 << 0; } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Initialize board. */ @@ -41,26 +41,26 @@ DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); /* ADC channels */ const struct adc_t adc_channels[] = { /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_VCONN_VSENSE] = { - "VCONN_VSENSE", 3000, 4096, 0, STM32_AIN(ADC_VCONN_VSENSE)}, - [ADC_CC_VPDMCU] = { - "CC_VPDMCU", 3000, 4096, 0, STM32_AIN(ADC_CC_VPDMCU)}, - [ADC_CC_RP3A0_RD_L] = { - "CC_RP3A0_RD_L", 3000, 4096, 0, STM32_AIN(ADC_CC_RP3A0_RD_L)}, - [ADC_RDCONNECT_REF] = { - "RDCONNECT_REF", 3000, 4096, 0, STM32_AIN(ADC_RDCONNECT_REF)}, - [ADC_CC1_RP3A0_RD_L] = { - "CC1_RP1A5_ODH", 3000, 4096, 0, STM32_AIN(ADC_CC1_RP3A0_RD_L)}, - [ADC_CC2_RP3A0_RD_L] = { - "CC2_RP1A5_ODH", 3000, 4096, 0, STM32_AIN(ADC_CC2_RP3A0_RD_L)}, - [ADC_HOST_VBUS_VSENSE] = { - "HOST_VBUS_VSENSE", 3000, 4096, 0, STM32_AIN(ADC_HOST_VBUS_VSENSE)}, - [ADC_CHARGE_VBUS_VSENSE] = { - "CHARGE_VBUS_VSENSE", 3000, 4096, 0, STM32_AIN(ADC_CHARGE_VBUS_VSENSE)}, - [ADC_CC1_RPUSB_ODH] = { - "CC1_RPUSB_ODH", 3000, 4096, 0, STM32_AIN(ADC_CC1_RPUSB_ODH)}, - [ADC_CC2_RPUSB_ODH] = { - "CC2_RPUSB_ODH", 3000, 4096, 0, STM32_AIN(ADC_CC2_RPUSB_ODH)}, + [ADC_VCONN_VSENSE] = { "VCONN_VSENSE", 3000, 4096, 0, + STM32_AIN(ADC_VCONN_VSENSE) }, + [ADC_CC_VPDMCU] = { "CC_VPDMCU", 3000, 4096, 0, + STM32_AIN(ADC_CC_VPDMCU) }, + [ADC_CC_RP3A0_RD_L] = { "CC_RP3A0_RD_L", 3000, 4096, 0, + STM32_AIN(ADC_CC_RP3A0_RD_L) }, + [ADC_RDCONNECT_REF] = { "RDCONNECT_REF", 3000, 4096, 0, + STM32_AIN(ADC_RDCONNECT_REF) }, + [ADC_CC1_RP3A0_RD_L] = { "CC1_RP1A5_ODH", 3000, 4096, 0, + STM32_AIN(ADC_CC1_RP3A0_RD_L) }, + [ADC_CC2_RP3A0_RD_L] = { "CC2_RP1A5_ODH", 3000, 4096, 0, + STM32_AIN(ADC_CC2_RP3A0_RD_L) }, + [ADC_HOST_VBUS_VSENSE] = { "HOST_VBUS_VSENSE", 3000, 4096, 0, + STM32_AIN(ADC_HOST_VBUS_VSENSE) }, + [ADC_CHARGE_VBUS_VSENSE] = { "CHARGE_VBUS_VSENSE", 3000, 4096, 0, + STM32_AIN(ADC_CHARGE_VBUS_VSENSE) }, + [ADC_CC1_RPUSB_ODH] = { "CC1_RPUSB_ODH", 3000, 4096, 0, + STM32_AIN(ADC_CC1_RPUSB_ODH) }, + [ADC_CC2_RPUSB_ODH] = { "CC2_RPUSB_ODH", 3000, 4096, 0, + STM32_AIN(ADC_CC2_RPUSB_ODH) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); diff --git a/board/chocodile_vpdmcu/board.h b/board/chocodile_vpdmcu/board.h index 09adee47b5..0e0ff70ab8 100644 --- a/board/chocodile_vpdmcu/board.h +++ b/board/chocodile_vpdmcu/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -27,14 +27,14 @@ #define CONFIG_RO_SIZE 0 /* Fake full size if we had a RO partition */ #undef CONFIG_RW_SIZE -#define CONFIG_RW_SIZE CONFIG_FLASH_SIZE +#define CONFIG_RW_SIZE CONFIG_FLASH_SIZE_BYTES #endif /* HAS_TASK_CONSOLE */ /* 48 MHz SYSCLK clock frequency */ #define CPU_CLOCK 48000000 /* the UART console is on USART1 (PA9/PA10) */ -#undef CONFIG_UART_CONSOLE +#undef CONFIG_UART_CONSOLE #define CONFIG_UART_CONSOLE 1 /* Optional features */ @@ -43,23 +43,22 @@ #undef CONFIG_CMD_PD #undef CONFIG_USBC_VCONN #define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG +#undef CONFIG_ADC_WATCHDOG #define CONFIG_ADC_SAMPLE_TIME STM32_ADC_SMPR_41_5_CY #define CONFIG_BOARD_PRE_INIT #define CONFIG_COMMON_GPIO_SHORTNAMES -#undef CONFIG_DEBUG_ASSERT +#undef CONFIG_DEBUG_ASSERT #define CONFIG_FORCE_CONSOLE_RESUME #define CONFIG_HIBERNATE -#undef CONFIG_HOSTCMD_EVENTS +#undef CONFIG_HOSTCMD_EVENTS #define CONFIG_HW_CRC -#undef CONFIG_LID_SWITCH +#undef CONFIG_LID_SWITCH #define CONFIG_LOW_POWER_IDLE #define CONFIG_LTO -#define CONFIG_STM_HWTIMER32 -#undef CONFIG_TASK_PROFILING -#undef CONFIG_UART_TX_BUF_SIZE -#undef CONFIG_UART_TX_DMA -#undef CONFIG_UART_RX_DMA +#undef CONFIG_TASK_PROFILING +#undef CONFIG_UART_TX_BUF_SIZE +#undef CONFIG_UART_TX_DMA +#undef CONFIG_UART_RX_DMA #define CONFIG_UART_TX_BUF_SIZE 128 #define CONFIG_USB_PD_PORT_MAX_COUNT 1 #define CONFIG_USB_PD_TCPC @@ -72,9 +71,10 @@ #define CONFIG_USB_PD_DECODE_SOP #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_INTERNAL_COMP +#undef CONFIG_USB_DPM_SM #define CONFIG_VBOOT_HASH #define CONFIG_WATCHDOG -#undef CONFIG_WATCHDOG_HELP +#undef CONFIG_WATCHDOG_HELP #define CONFIG_USB_PID 0x5036 #define VPD_HW_VERSION 0x0001 @@ -83,16 +83,19 @@ /* USB bcdDevice */ #define USB_BCD_DEVICE 0 +/* Charge Through Current */ +#define VPD_CT_CURRENT VPD_CT_CURRENT_3A + /* Vbus impedance in milliohms */ #define VPD_VBUS_IMPEDANCE 65 /* GND impedance in milliohms */ #define VPD_GND_IMPEDANCE 33 -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* * TODO(crosbug.com/p/50519): Remove CONFIG_SYSTEM_UNLOCKED prior to building * MP FW. @@ -100,26 +103,29 @@ #define CONFIG_SYSTEM_UNLOCKED #ifdef HAS_TASK_CONSOLE -#undef CONFIG_CONSOLE_HISTORY +#undef CONFIG_CONSOLE_HISTORY #define CONFIG_CONSOLE_HISTORY 2 #else -#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CONSOLE_CMDHELP #define CONFIG_DEBUG_PRINTF #define UARTN CONFIG_UART_CONSOLE #define UARTN_BASE STM32_USART_BASE(CONFIG_UART_CONSOLE) #endif /* HAS_TASK_CONSOLE */ /* Use PSTATE embedded in the RO image, not in its own erase block */ -#undef CONFIG_FLASH_PSTATE_BANK -#undef CONFIG_FW_PSTATE_SIZE +#undef CONFIG_FLASH_PSTATE_BANK +#undef CONFIG_FW_PSTATE_SIZE #define CONFIG_FW_PSTATE_SIZE 0 +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + #ifndef __ASSEMBLER__ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 +#define TIM_ADC 3 #include "gpio_signal.h" @@ -140,8 +146,8 @@ enum adc_channel { }; /* 1.5A Rp */ -#define PD_SRC_VNC PD_SRC_1_5_VNC_MV -#define PD_SRC_RD_THRESHOLD PD_SRC_1_5_RD_THRESH_MV +#define PD_SRC_VNC PD_SRC_1_5_VNC_MV +#define PD_SRC_RD_THRESHOLD PD_SRC_1_5_RD_THRESH_MV #endif /* !__ASSEMBLER__ */ diff --git a/board/chocodile_vpdmcu/build.mk b/board/chocodile_vpdmcu/build.mk index d4e5f58962..21c257bd7e 100644 --- a/board/chocodile_vpdmcu/build.mk +++ b/board/chocodile_vpdmcu/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/chocodile_vpdmcu/chocodile.html b/board/chocodile_vpdmcu/chocodile.html index b38edf94ec..6aec670f2a 100644 --- a/board/chocodile_vpdmcu/chocodile.html +++ b/board/chocodile_vpdmcu/chocodile.html @@ -866,7 +866,7 @@

chocodile/page1: TABLE OF CONTENTS

10 1 A -FOLLOWING NOTICE SHALL APPLY:  COPYRIGHT C 2009 GOOGLE, INC.  ALL RIGHTS RESERVED. +FOLLOWING NOTICE SHALL APPLY:  COPYRIGHT 2009 GOOGLE LLC H 12 THESE MATERIALS (INCLUDING ALL TEXT, SOFTWARE,CODE, DISPLAYS, ARTWORK, AND IMAGES) CONTAIN TRADE SECRETS AND CONFIDENTIAL INFORMATION WHICH ARE PROPRIETARY TO GOOGLE, INC.  ANY USE, REPRODUCTION, DISTRIBUTION, diff --git a/board/chocodile_vpdmcu/ec.tasklist b/board/chocodile_vpdmcu/ec.tasklist index 6753502b92..ecbd3b052c 100644 --- a/board/chocodile_vpdmcu/ec.tasklist +++ b/board/chocodile_vpdmcu/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/chocodile_vpdmcu/gpio.inc b/board/chocodile_vpdmcu/gpio.inc index a34c617ef1..060054f719 100644 --- a/board/chocodile_vpdmcu/gpio.inc +++ b/board/chocodile_vpdmcu/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/chocodile_vpdmcu/usb_pd_config.h b/board/chocodile_vpdmcu/usb_pd_config.h index a6c1adbc61..7fe608eb2a 100644 --- a/board/chocodile_vpdmcu/usb_pd_config.h +++ b/board/chocodile_vpdmcu/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -55,7 +55,7 @@ static inline void spi_enable_clock(int port) #define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 #define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 -#define TIM_CCR_CS 1 +#define TIM_CCR_CS 1 /* EXTI line 21 is connected to the CMP1 output */ #define EXTI_COMP1_MASK (1 << 21) @@ -95,13 +95,15 @@ static inline void pd_tx_spi_reset(int port) static inline void pd_tx_enable(int port, int polarity) { /* USB_CC_TX_DATA: PB4 is SPI1 MISO */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - & ~(3 << (2*4))) /* PB4 disable ADC */ - | (2 << (2*4)); /* Set as SPI1_MISO */ + STM32_GPIO_MODER(GPIO_B) = + (STM32_GPIO_MODER(GPIO_B) & ~(3 << (2 * 4))) /* PB4 disable ADC + */ + | (2 << (2 * 4)); /* Set as SPI1_MISO */ /* MCU ADC PA1 pin output low */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - & ~(3 << (2*1))) /* PA1 disable ADC */ - | (1 << (2*1)); /* Set as GPO */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) & ~(3 << (2 * 1))) /* PA1 disable ADC + */ + | (1 << (2 * 1)); /* Set as GPO */ gpio_set_level(GPIO_CC_VPDMCU, 0); } @@ -109,11 +111,10 @@ static inline void pd_tx_enable(int port, int polarity) static inline void pd_tx_disable(int port, int polarity) { /* Set CC_TX_DATA to Hi-Z, PB4 is SPI1 MISO */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - & ~(3 << (2*4))); + STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) & ~(3 << (2 * 4))); /* set ADC PA1 pin to ADC function (Hi-Z) */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - | (3 << (2*1))); /* PA1 as ADC */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) | (3 << (2 * 1))); /* PA1 as ADC */ } /* we know the plug polarity, do the right configuration */ @@ -123,8 +124,8 @@ static inline void pd_select_polarity(int port, int polarity) * use the right comparator : CC1 -> PA1 (COMP1 INP) * use VrefInt / 2 as INM (about 600mV) */ - STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) - | STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12; + STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) | + STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12; } /* Initialize pins used for TX and put them in Hi-Z */ @@ -160,4 +161,3 @@ static inline int pd_adc_read(int port, int cc) } #endif /* __CROS_EC_USB_PD_CONFIG_H */ - diff --git a/board/chocodile_vpdmcu/vif_override.xml b/board/chocodile_vpdmcu/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/chocodile_vpdmcu/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/chocodile_vpdmcu/vpd_api.c b/board/chocodile_vpdmcu/vpd_api.c index 857ca46d1c..53cc0fa733 100644 --- a/board/chocodile_vpdmcu/vpd_api.c +++ b/board/chocodile_vpdmcu/vpd_api.c @@ -1,13 +1,13 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" +#include "driver/tcpm/tcpm.h" #include "gpio.h" #include "registers.h" #include "vpd_api.h" -#include "driver/tcpm/tcpm.h" /* * Polarity based on 'DFP Perspective' (see table 4-10 USB Type-C Cable and @@ -35,7 +35,7 @@ #endif #undef CC_RA -#define CC_RA(cc, sel) (cc < pd_src_rd_threshold[sel]) +#define CC_RA(cc, sel) (cc < pd_src_rd_threshold[sel]) #undef CC_RD #define CC_RD(cc, sel) ((cc >= pd_src_rd_threshold[sel]) && (cc < PD_SRC_VNC)) @@ -47,16 +47,16 @@ #define VBUS_DETECT_THRESHOLD 2500 /* mV */ #define VCONN_DETECT_THRESHOLD 2500 /* mV */ -#define SCALE(vmeas, sfactor) (((vmeas) * 1000) / (sfactor)) +#define SCALE(vmeas, sfactor) (((vmeas)*1000) / (sfactor)) /* * Type C power source charge current limits are identified by their cc * voltage (set by selecting the proper Rd resistor). Any voltage below * TYPE_C_SRC_500_THRESHOLD will not be identified as a type C charger. */ -#define TYPE_C_SRC_DEFAULT_THRESHOLD 200 /* mV */ -#define TYPE_C_SRC_1500_THRESHOLD 660 /* mV */ -#define TYPE_C_SRC_3000_THRESHOLD 1230 /* mV */ +#define TYPE_C_SRC_DEFAULT_THRESHOLD 200 /* mV */ +#define TYPE_C_SRC_1500_THRESHOLD 660 /* mV */ +#define TYPE_C_SRC_3000_THRESHOLD 1230 /* mV */ /* Charge-Through pull up/down enabled */ static int ct_cc_pull; @@ -86,7 +86,7 @@ static int vpd_cc_voltage_to_status(int cc_volt, int cc_pull) return TYPEC_CC_VOLT_RA; else return TYPEC_CC_VOLT_OPEN; - /* If we have a pull-down, then we are sink, check for Rp. */ + /* If we have a pull-down, then we are sink, check for Rp. */ } else if (cc_pull == TYPEC_CC_RD || cc_pull == TYPEC_CC_RA_RD) { if (cc_volt >= TYPE_C_SRC_3000_THRESHOLD) return TYPEC_CC_VOLT_RP_3_0; @@ -200,13 +200,13 @@ void vpd_host_set_pull(int pull, int rp_value) break; case TYPEC_CC_RA_RD: vpd_cc_rpusb_odh(GPO_HZ); - vpd_config_cc_rp3a0_rd_l(PIN_GPO, 0); + vpd_config_cc_rp3a0_rd_l(PIN_CMP, 0); /* * RA is connected to VCONN * RD is connected to CC */ - vpd_cc_db_en_od(GPO_HZ); + vpd_cc_db_en_od(GPO_HIGH); break; case TYPEC_CC_OPEN: vpd_cc_rpusb_odh(GPO_HZ); @@ -218,8 +218,8 @@ void vpd_host_set_pull(int pull, int rp_value) void vpd_host_get_cc(int *cc) { - *cc = vpd_cc_voltage_to_status( - adc_read_channel(ADC_CC_VPDMCU), host_cc_pull); + *cc = vpd_cc_voltage_to_status(adc_read_channel(ADC_CC_VPDMCU), + host_cc_pull); } void vpd_rx_enable(int en) @@ -237,17 +237,23 @@ void vpd_config_cc_rp3a0_rd_l(enum vpd_pin cfg, int en) gpio_set_level(GPIO_CC_RP3A0_RD_L, en ? 1 : 0); /* Disable Analog mode and Enable GPO */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - & ~(3 << (2*2))) /* PA2 disable ADC */ - | (1 << (2*2)); /* Set as GPO */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) & ~(3 << (2 * 2))) /* PA2 + disable + ADC */ + | (1 << (2 * 2)); /* Set as GPO */ } else { /* Set PA2 pin to ANALOG function */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - | (3 << (2*2))); /* PA2 in ANALOG mode */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) | (3 << (2 * 2))); /* PA2 in + ANALOG + mode */ /* Set PA3 pin to ANALOG function */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - | (3 << (2*3))); /* PA3 in ANALOG mode */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) | (3 << (2 * 3))); /* PA3 in + ANALOG + mode */ /* Disable Window Mode. Select PA3 */ STM32_COMP_CSR &= ~STM32_COMP_WNDWEN; @@ -276,9 +282,11 @@ void vpd_config_cc1_rp3a0_rd_l(enum vpd_pin cfg, int en) gpio_set_level(GPIO_CC1_RP3A0_RD_L, en ? 1 : 0); /* Disable Analog mode and Enable GPO */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - & ~(3 << (2*4))) /* PA4 disable ADC */ - | (1 << (2*4)); /* Set as GPO */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) & ~(3 << (2 * 4))) /* PA4 + disable + ADC */ + | (1 << (2 * 4)); /* Set as GPO */ } if (cfg == PIN_ADC || cfg == PIN_CMP) { @@ -286,13 +294,17 @@ void vpd_config_cc1_rp3a0_rd_l(enum vpd_pin cfg, int en) STM32_COMP_CSR &= ~STM32_COMP_CMP2EN; /* Set PA4 pin to Analog mode */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - | (3 << (2*4))); /* PA4 in ANALOG mode */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) | (3 << (2 * 4))); /* PA4 in + ANALOG + mode */ if (cfg == PIN_CMP) { /* Set PA3 pin to ANALOG function */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - | (3 << (2*3))); /* PA3 in ANALOG mode */ + STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) | + (3 << (2 * 3))); /* PA3 in + ANALOG + mode */ /* Disable Window Mode. Select PA3*/ STM32_COMP_CSR &= ~STM32_COMP_WNDWEN; @@ -319,9 +331,11 @@ void vpd_config_cc2_rp3a0_rd_l(enum vpd_pin cfg, int en) gpio_set_level(GPIO_CC2_RP3A0_RD_L, en ? 1 : 0); /* Disable Analog mode and Enable GPO */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - & ~(3 << (2*5))) /* PA5 disable ADC */ - | (1 << (2*5)); /* Set as GPO */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) & ~(3 << (2 * 5))) /* PA5 + disable + ADC */ + | (1 << (2 * 5)); /* Set as GPO */ } if (cfg == PIN_ADC || cfg == PIN_CMP) { @@ -329,13 +343,17 @@ void vpd_config_cc2_rp3a0_rd_l(enum vpd_pin cfg, int en) STM32_COMP_CSR &= ~STM32_COMP_CMP2EN; /* Set PA5 pin to ANALOG function */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - | (3 << (2*5))); /* PA5 in ANALOG mode */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) | (3 << (2 * 5))); /* PA5 in + ANALOG + mode */ if (cfg == PIN_CMP) { /* Set PA3 pin to ANALOG function */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - | (3 << (2*3))); /* PA3 in ANALOG mode */ + STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) | + (3 << (2 * 3))); /* PA3 in + ANALOG + mode */ /* Disable Window Mode. */ STM32_COMP_CSR &= ~STM32_COMP_WNDWEN; @@ -362,13 +380,17 @@ void vpd_config_cc1_rpusb_odh(enum vpd_pin cfg, int en) gpio_set_level(GPIO_CC1_RPUSB_ODH, en ? 1 : 0); /* Disable Analog mode and Enable GPO */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - & ~(3 << (2*0))) /* PB0 disable ADC */ - | (1 << (2*0)); /* Set as GPO */ + STM32_GPIO_MODER(GPIO_B) = + (STM32_GPIO_MODER(GPIO_B) & ~(3 << (2 * 0))) /* PB0 + disable + ADC */ + | (1 << (2 * 0)); /* Set as GPO */ } else { /* Enable Analog mode */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - | (3 << (2*0))); /* PB0 in ANALOG mode */ + STM32_GPIO_MODER(GPIO_B) = + (STM32_GPIO_MODER(GPIO_B) | (3 << (2 * 0))); /* PB0 in + ANALOG + mode */ } } @@ -382,13 +404,17 @@ void vpd_config_cc2_rpusb_odh(enum vpd_pin cfg, int en) gpio_set_level(GPIO_CC2_RPUSB_ODH, en ? 1 : 0); /* Disable Analog mode and Enable GPO */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - & ~(3 << (2*1))) /* PB1 disable ADC */ - | (1 << (2*1)); /* Set as GPO */ + STM32_GPIO_MODER(GPIO_B) = + (STM32_GPIO_MODER(GPIO_B) & ~(3 << (2 * 1))) /* PB1 + disable + ADC */ + | (1 << (2 * 1)); /* Set as GPO */ } else { /* Enable Analog mode */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - | (3 << (2*1))); /* PB1 in ANALOG mode */ + STM32_GPIO_MODER(GPIO_B) = + (STM32_GPIO_MODER(GPIO_B) | (3 << (2 * 1))); /* PB1 in + ANALOG + mode */ } } @@ -405,7 +431,7 @@ inline int vpd_read_host_vbus(void) inline int vpd_read_ct_vbus(void) { return SCALE(adc_read_channel(ADC_CHARGE_VBUS_VSENSE), - VBUS_SCALE_FACTOR); + VBUS_SCALE_FACTOR); } inline int vpd_read_vconn(void) diff --git a/board/chocodile_vpdmcu/vpd_api.h b/board/chocodile_vpdmcu/vpd_api.h index df50f92006..5d2fd24afb 100644 --- a/board/chocodile_vpdmcu/vpd_api.h +++ b/board/chocodile_vpdmcu/vpd_api.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,34 +12,18 @@ #include "gpio.h" #include "usb_pd.h" -enum vpd_pin { - PIN_ADC, - PIN_CMP, - PIN_GPO -}; +enum vpd_pin { PIN_ADC, PIN_CMP, PIN_GPO }; -enum vpd_gpo { - GPO_HZ, - GPO_HIGH, - GPO_LOW -}; +enum vpd_gpo { GPO_HZ, GPO_HIGH, GPO_LOW }; enum vpd_pwr { PWR_VCONN, PWR_VBUS, }; -enum vpd_cc { - CT_OPEN, - CT_CC1, - CT_CC2 -}; +enum vpd_cc { CT_OPEN, CT_CC1, CT_CC2 }; -enum vpd_billboard { - BB_NONE, - BB_SRC, - BB_SNK -}; +enum vpd_billboard { BB_NONE, BB_SRC, BB_SNK }; /** * Set Charge-Through Rp or Rd on CC lines diff --git a/board/chronicler/battery.c b/board/chronicler/battery.c new file mode 100644 index 0000000000..1d885607b7 --- /dev/null +++ b/board/chronicler/battery.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all Chronicler battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* NVT CP813907-01 Battery Information */ + [BATTERY_NVT_CP813907] = { + .fuel_gauge = { + .manuf_name = "NVT", + .device_name = "CP813907-01", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x10, 0x10 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 128, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 55, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_NVT_CP813907; diff --git a/board/chronicler/board.c b/board/chronicler/board.c new file mode 100644 index 0000000000..ca6ae5c392 --- /dev/null +++ b/board/chronicler/board.c @@ -0,0 +1,455 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Chronicler board-specific configuration */ +#include "accelgyro.h" +#include "battery.h" +#include "battery_smart.h" +#include "button.h" +#include "cbi_ec_fw_config.h" +#include "charge_state.h" +#include "common.h" +#include "driver/sync.h" +#include "driver/tcpm/ps8xxx.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_8042.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "throttle_ap.h" +#include "uart.h" +#include "usb_pd.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +/******************************************************************************/ +/* Physical fans. These are logically separate from pwm_channels. */ + +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 3000, + .rpm_start = 5000, + .rpm_max = 5100, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +/******************************************************************************/ +/* EC thermal management configuration */ + +/* + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (80 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CONFIG_WITHOUT_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(77), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_config_without_fan = + THERMAL_CONFIG_WITHOUT_FAN; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CONFIG_WITH_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(77), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + /* For real temperature fan_table (0 ~ 99C) */ \ + .temp_fan_off = C_TO_K(0), \ + .temp_fan_max = C_TO_K(99), \ + } +__maybe_unused static const struct ec_thermal_config thermal_config_with_fan = + THERMAL_CONFIG_WITH_FAN; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CHARGER] = THERMAL_CONFIG_WITH_FAN, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_CONFIG_WITHOUT_FAN, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CONFIG_WITHOUT_FAN, + [TEMP_SENSOR_4_FAN] = THERMAL_CONFIG_WITHOUT_FAN, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +struct fan_step { + int on; + int off; + int rpm; +}; + +/* Fan control table */ +static const struct fan_step fan_table0[] = { + { .on = 30, .off = 0, .rpm = 3150 }, /* Fan level 0 */ + { .on = 47, .off = 43, .rpm = 3500 }, /* Fan level 1 */ + { .on = 50, .off = 47, .rpm = 3750 }, /* Fan level 2 */ + { .on = 53, .off = 50, .rpm = 4200 }, /* Fan level 3 */ + { .on = 56, .off = 53, .rpm = 4500 }, /* Fan level 4 */ + { .on = 59, .off = 56, .rpm = 5000 }, /* Fan level 5 */ +}; + +/* All fan tables must have the same number of levels */ +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) + +static const struct fan_step *fan_table = fan_table0; + +#define FAN_AVERAGE_TIME_SEC 5 + +int fan_percent_to_rpm(int fan, int pct) +{ + static int current_level; + static int previous_level = NUM_FAN_LEVELS; + static int cnt, avg_pct, previous_pct; + int i; + + /* Average several times to smooth fan rotating speed. */ + avg_pct += pct; + + if (++cnt != FAN_AVERAGE_TIME_SEC) + return fan_table[previous_level].rpm; + + avg_pct = (int)avg_pct / FAN_AVERAGE_TIME_SEC; + + /* + * Compare the pct and previous pct, we have the three paths : + * 1. decreasing path. (check the off point) + * 2. increasing path. (check the on point) + * 3. invariant path. (return the current RPM) + */ + if (avg_pct < previous_pct) { + for (i = current_level; i >= 0; i--) { + if (avg_pct <= fan_table[i].off) + current_level = i - 1; + else + break; + } + } else if (avg_pct > previous_pct) { + for (i = current_level + 1; i < NUM_FAN_LEVELS; i++) { + if (avg_pct >= fan_table[i].on) + current_level = i; + else + break; + } + } + + if (current_level < 0) + current_level = 0; + + if (current_level != previous_level) + cprints(CC_THERMAL, "Setting fan RPM to %d", + fan_table[current_level].rpm); + + previous_pct = avg_pct; + previous_level = current_level; + + cnt = 0; + avg_pct = 0; + + return fan_table[current_level].rpm; +} + +/******************************************************************************/ +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + .name = "usb_c0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C1_USB_C0_SCL, + .sda = GPIO_EC_I2C1_USB_C0_SDA, + }, + { + .name = "usb_c1", + .port = I2C_PORT_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C2_USB_C1_SCL, + .sda = GPIO_EC_I2C2_USB_C1_SDA, + }, + { + .name = "usb_1_mix", + .port = I2C_PORT_USB_1_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C3_USB_1_MIX_SCL, + .sda = GPIO_EC_I2C3_USB_1_MIX_SDA, + }, + { + .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C5_BATTERY_SCL, + .sda = GPIO_EC_I2C5_BATTERY_SDA, + }, + { + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C7_EEPROM_PWR_SCL_R, + .sda = GPIO_EC_I2C7_EEPROM_PWR_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/******************************************************************************/ +/* PWM configuration */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/******************************************************************************/ +/* keyboard config */ +static const struct ec_response_keybd_config main_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + /* + * Chronicler keyboard swaps T2 and T3 in the keyboard + * matrix,So swap the actions key lookup to match. + * The physical keyboard still orders the top row as + * Back, Refresh, Fullscreen, etc. + */ + TK_FULLSCREEN, /* T3 */ + TK_REFRESH, /* T2 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &main_kb; +} + +/******************************************************************************/ +/* keyboard factory test */ +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ + +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif + +/******************************************************************************/ +/* drop battery charging voltage depending on battery run time */ + +#ifdef BATTERY_RUNTIME_TEST +static int manual_run_time = -1; +#endif + +struct drop_step { + int run_time; /* battery run time (day) */ + int drop_volt; /* drop voltage (mV) */ +}; + +/* voltage drop table */ +static const struct drop_step voltage_drop_table[] = { + { .run_time = 90, .drop_volt = 13200 }, /* drop level 0 */ + { .run_time = 198, .drop_volt = 13125 }, /* drop level 1 */ + { .run_time = 305, .drop_volt = 13050 }, /* drop level 2 */ + { .run_time = 412, .drop_volt = 12975 }, /* drop level 3 */ + { .run_time = 519, .drop_volt = 12900 }, /* drop level 4 */ + { .run_time = 626, .drop_volt = 12825 }, /* drop level 5 */ + { .run_time = __INT_MAX__, .drop_volt = 12750 }, /* drop level 6 */ +}; + +#define NUM_DROP_LEVELS ARRAY_SIZE(voltage_drop_table) + +static int get_battery_run_time_day(uint32_t *battery_run_time) +{ + int rv; + uint32_t run_time; + uint8_t data[6]; + + /* get battery run time */ + rv = sb_read_mfgacc(PARAM_FIRMWARE_RUNTIME, SB_ALT_MANUFACTURER_ACCESS, + data, sizeof(data)); + + if (rv) + return EC_ERROR_UNKNOWN; + /* + * The response is 6 bytes; the runtime in seconds is the last 4 bytes. + */ + run_time = *(int32_t *)(&data[2]); + +#ifdef BATTERY_RUNTIME_TEST + cprints(CC_CHARGER, "run_time : 0x%08x (%d day)", run_time, + (run_time / 86400)); + + /* manual battery run time fot test */ + if (manual_run_time != -1) + run_time = manual_run_time; +#endif + /* second to day */ + *battery_run_time = run_time / 86400; + + return EC_SUCCESS; +} + +/* charger profile override */ +int charger_profile_override(struct charge_state_data *curr) +{ + int i; + uint32_t batt_run_time = 0; + + /* Should not do anything if battery not present */ + if (battery_hw_present() != BP_YES) + return 0; + + if (get_battery_run_time_day(&batt_run_time)) + return EC_ERROR_UNKNOWN; + + for (i = 0; i < NUM_DROP_LEVELS; i++) { + if (batt_run_time <= voltage_drop_table[i].run_time) + break; + } + + curr->requested_voltage = + MIN(curr->requested_voltage, voltage_drop_table[i].drop_volt); +#ifdef BATTERY_RUNTIME_TEST + cprints(CC_CHARGER, + "Charger: run time(day): %d, drop level: %d, CV: %d", + batt_run_time, i, curr->requested_voltage); +#endif + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +static void battery_runtime_init(void) +{ + uint32_t batt_run_time = 0; + + /* Should not do anything if battery not present */ + if (battery_hw_present() != BP_YES) + return; + + if (get_battery_run_time_day(&batt_run_time)) + return; + + cprints(CC_CHARGER, "battery run time(day): %d", batt_run_time); +} +DECLARE_HOOK(HOOK_INIT, battery_runtime_init, HOOK_PRIO_LAST); + +#ifdef BATTERY_RUNTIME_TEST +/* test command */ +static int command_manual_run_time(int argc, const char **argv) +{ + char *e = NULL; + + if (argc < 2) { + manual_run_time = -1; + cprints(CC_CHARGER, "manual run time reset"); + return EC_SUCCESS; + } + + if (argc != 2) + return EC_ERROR_PARAM_COUNT; + + manual_run_time = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM1; + + cprints(CC_CHARGER, "manual run time set to %d sec (%d day)", + manual_run_time, (manual_run_time / 86400)); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(rt, command_manual_run_time, "", + "Set manual run time for test"); +#endif diff --git a/board/chronicler/board.h b/board/chronicler/board.h new file mode 100644 index 0000000000..d017b896be --- /dev/null +++ b/board/chronicler/board.h @@ -0,0 +1,151 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Chronicler board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* + * The RAM and flash size combination on the NPCX797FC dose not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +/* Optional features */ + +#define CONFIG_VBOOT_EFS2 + +#define CONFIG_POWER_BUTTON + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Chipset features */ +#define CONFIG_POWER_PP5000_CONTROL +#define CONFIG_CPU_PROCHOT_GATE_ON_C10 + +/* Sensors */ +#undef CONFIG_TABLET_MODE +#undef CONFIG_GMR_TABLET_MODE +#undef CONFIG_ACCEL_FIFO +#undef CONFIG_ACCEL_FIFO_SIZE + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* TODO: b/144165680 - measure and check these values on Volteer */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +/* + * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C + * cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USBC PPC*/ +#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ +#define CONFIG_USB_PD_FRS_PPC +#undef CONFIG_USB_PD_TCPC_RUNTIME_CONFIG +#undef CONFIG_USB_PD_TCPM_TUSB422 +#undef CONFIG_USB_MUX_RUNTIME_CONFIG + +/* BC 1.2 */ + +/* Volume Button feature */ +#undef CONFIG_VOLUME_BUTTONS + +/* Fan features */ +#define CONFIG_FAN_RPM_CUSTOM + +/* charger defines */ +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_PROFILE_OVERRIDE + +/* Retimer */ +#undef CONFIG_USBC_RETIMER_INTEL_BB +#undef CONFIG_USBC_RETIMER_INTEL_BB_RUNTIME_CONFIG + +/* Keyboard feature */ +#define CONFIG_KEYBOARD_FACTORY_TEST + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM + +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER + +#define CONFIG_DEBUG_ASSERT_BRIEF + +/* Disable volume button command in EC console */ +#undef CONFIG_CMD_BUTTON + +/* Disable volume button in ectool */ +#undef CONFIG_HOSTCMD_BUTTON + +/* battery runtime test */ +#undef BATTERY_RUNTIME_TEST + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" +#include "usbc_config.h" + +enum battery_type { BATTERY_NVT_CP813907, BATTERY_TYPE_COUNT }; + +enum pwm_channel { PWM_CH_FAN, PWM_CH_KBLIGHT, PWM_CH_COUNT }; + +void board_reset_pd_mcu(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/chronicler/build.mk b/board/chronicler/build.mk new file mode 100644 index 0000000000..f317b88795 --- /dev/null +++ b/board/chronicler/build.mk @@ -0,0 +1,19 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=volteer + +board-y=board.o +board-y+=battery.o +board-y+=cbi.o +board-y+=led.o +board-y+=keyboard.o +board-y+=usbc_config.o diff --git a/board/chronicler/cbi.c b/board/chronicler/cbi.c new file mode 100644 index 0000000000..a9c458b88d --- /dev/null +++ b/board/chronicler/cbi.c @@ -0,0 +1,26 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Features common to ECOS and Zephyr */ +#include "cbi.h" +#include "cbi_ec_fw_config.h" +#include "common.h" +#include "keyboard_raw.h" +#include "usbc_config.h" + +/******************************************************************************/ +/* + * FW_CONFIG defaults for Chronicler if the CBI data is not initialized. + */ +union volteer_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_ACTIVE, +}; + +__override void board_cbi_init(void) +{ + if ((!IS_ENABLED(TEST_BUILD) && !ec_cfg_has_numeric_pad()) || + get_board_id() <= 2) + keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); +} diff --git a/board/chronicler/ec.tasklist b/board/chronicler/ec.tasklist new file mode 100644 index 0000000000..644c36cd37 --- /dev/null +++ b/board/chronicler/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/chronicler/gpio.inc b/board/chronicler/gpio.inc new file mode 100644 index 0000000000..b0a9ad6981 --- /dev/null +++ b/board/chronicler/gpio.inc @@ -0,0 +1,178 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) + +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) + +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) +GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) + +/* HDMI interrupts */ + +/* Power Sequencing Signals */ +GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ +GPIO(EC_PCH_DSW_PWROK, PIN(C, 0), GPIO_OUT_LOW) + +/* Other wake sources */ +/* + * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an + * interrupt handler because it is automatically handled by the PSL. + * + * We need to lock the setting so this gpio can't be reconfigured to overdrive + * the real reset signal. (This is the PSL input pin not the real reset pin). + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | + GPIO_HIB_WAKE_HIGH | + GPIO_LOCKED) + +/* AP/PCH Signals */ +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_RISING, throttle_ap_c10_input_interrupt) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) + +/* USB and USBC Signals */ +GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ +GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ +GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) +GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) +/* There is currently no need to service this interrupt. */ +GPIO(USB_C1_RT_INT_ODL, PIN(F, 3), GPIO_INPUT) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) + +/* Don't have a load switch for retimer */ +UNIMPLEMENTED(USB_C1_LS_EN) + +/* Misc Signals */ +GPIO(EC_H1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) /* H1 Packet Mode */ +/* + * Despite their names, M2_SSD_PLN and M2_SSD_PLA are active-low, and M2_SSD_PLN + * is open-drain. + * TODO(b/138954381): Change these names when they change on the schematic. + */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_ODR_HIGH) /* SSD power-loss notification */ +GPIO(M2_SSD_PLA, PIN(7, 0), GPIO_INPUT) /* SSD power-loss acknowledgment */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(EC_SLP_S0IX, PIN(7, 2), GPIO_INPUT | GPIO_PULL_UP) + +/* LED */ +GPIO(C0_CHARGE_LED_AMBER_L, PIN(C, 3), GPIO_OUT_HIGH) /* Amber C0 port */ +GPIO(C0_CHARGE_LED_WHITE_L, PIN(C, 4), GPIO_OUT_HIGH) /* White C0 port */ +GPIO(C1_CHARGE_LED_AMBER_L, PIN(6, 0), GPIO_OUT_HIGH) /* Amber C1 port */ +GPIO(C1_CHARGE_LED_WHITE_L, PIN(C, 2), GPIO_OUT_HIGH) /* White C1 port */ + +/* Unused signals */ +GPIO(CHARGER_INT_L, PIN(7, 3), GPIO_INPUT) /* Interrupt not used from ISL9241, on board pull-up */ +GPIO(EC_GP_SEL0_ODL, PIN(B, 6), GPIO_OUT_LOW) /* Cannot be configured as input, drive output low, don't rely on the default setting of PxDOUT register */ +GPIO(EN_PP5000_USB_AG, PIN(A, 7), GPIO_INPUT | GPIO_PULL_UP) /* Unconnected power sequencing signal */ +GPIO(UNUSED_GPIO41, PIN(4, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOF2, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO96, PIN(9, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO56, PIN(5, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOD4, PIN(D, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO95, PIN(9, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO81, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO93, PIN(9, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO97, PIN(9, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOB5, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) /* Unused I2C port, Set input only */ +GPIO(UNUSED_GPIOB4, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) /* Unused I2C port, Set input only */ +/* Only connected to test points */ +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_ESPI_ALERT_L, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) + +/* + * eDP backlight - both PCH and EC have enable pins that must be high + * for the backlight to turn on. Default state is high, and can be turned + * off during sleep states. + */ +GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C3_USB_1_MIX_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C3_USB_1_MIX_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C5_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C5_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_PWR_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_PWR_SDA_R, PIN(B, 2), GPIO_INPUT) + +/* Battery signals */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ +ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ + +/* Fan signals */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +ALTERNATE(PIN_MASK(B, BIT(7)), 0, MODULE_PWM, 0) /* FAN_PWM */ +ALTERNATE(PIN_MASK(4, BIT(0)), 0, MODULE_PWM, 0) /* FAN_SPEED_TACH */ + +/* Keyboard pins */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ + +/* UART */ +ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Power Switch Logic (PSL) inputs */ +ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ +ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, + GPIO01 = H1_EC_PWR_BTN_ODL + GPIO02 = EC_RST_ODL */ + +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ diff --git a/board/chronicler/keyboard.c b/board/chronicler/keyboard.c new file mode 100644 index 0000000000..9e04d77ca3 --- /dev/null +++ b/board/chronicler/keyboard.c @@ -0,0 +1,26 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Keyboard config common to ECOS and zephyr */ + +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; diff --git a/board/chronicler/led.c b/board/chronicler/led.c new file mode 100644 index 0000000000..81e2656543 --- /dev/null +++ b/board/chronicler/led.c @@ -0,0 +1,203 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Chronicler + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +#define LED_CYCLE_TIME_MS (2 * 1000) +#define LED_TICKS_PER_CYCLE (LED_CYCLE_TIME_MS / HOOK_TICK_INTERVAL_MS) +#define LED_ON_TIME_MS (1 * 1000) +#define LED_ON_TICKS (LED_ON_TIME_MS / HOOK_TICK_INTERVAL_MS) + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +enum led_port { RIGHT_PORT = 0, LEFT_PORT }; + +static void led_set_color_battery(enum led_port port, enum led_color color) +{ + enum gpio_signal amber_led, white_led; + + amber_led = (port == RIGHT_PORT ? GPIO_C0_CHARGE_LED_AMBER_L : + GPIO_C1_CHARGE_LED_AMBER_L); + white_led = (port == RIGHT_PORT ? GPIO_C0_CHARGE_LED_WHITE_L : + GPIO_C1_CHARGE_LED_WHITE_L); + + switch (color) { + case LED_WHITE: + gpio_set_level(white_led, BAT_LED_ON); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_ON); + break; + case LED_OFF: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + default: + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_RIGHT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + default: + break; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LEFT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LEFT_PORT, LED_AMBER); + else + led_set_color_battery(LEFT_PORT, LED_OFF); + break; + case EC_LED_ID_RIGHT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(RIGHT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(RIGHT_PORT, LED_AMBER); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + break; + default: + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + led_set_color_battery(RIGHT_PORT, + (port == RIGHT_PORT) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, + (port == LEFT_PORT) ? color : LED_OFF); +} + +static void led_set_battery(void) +{ + static int battery_ticks; + static int suspend_ticks; + + battery_ticks++; + + /* + * Override battery LEDs for Chronicler, Chronicler doesn't + * have power LED, blinking both two side battery white + * LEDs to indicate system suspend without charging state. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + suspend_ticks++; + + led_set_color_battery( + RIGHT_PORT, suspend_ticks & 0x4 ? LED_WHITE : LED_OFF); + led_set_color_battery( + LEFT_PORT, suspend_ticks & 0x4 ? LED_WHITE : LED_OFF); + return; + } + + suspend_ticks = 0; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + if (charge_get_percent() < 10) + led_set_color_battery( + RIGHT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, LED_OFF); + break; + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/chronicler/usbc_config.c b/board/chronicler/usbc_config.c new file mode 100644 index 0000000000..55ef253c5b --- /dev/null +++ b/board/chronicler/usbc_config.c @@ -0,0 +1,279 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific USB-C configuration */ +#include "cbi_ec_fw_config.h" +#include "common.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/sn5s330_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/retimer/ps8811.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/rt1715_public.h" +#include "driver/tcpm/tcpci.h" +#include "driver/tcpm/tusb422_public.h" +#include "gpio.h" +#include "hooks.h" +#include "system.h" +#include "timer.h" +#include "usb_mux.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +/* + * USB3 DB mux configuration - the top level mux still needs to be set to the + * virtual_usb_mux_driver so the AP gets notified of mux changes and updates + * the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, +}; + +/******************************************************************************/ +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/******************************************************************************/ +/* PPC support routines */ +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + sn5s330_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +/******************************************************************************/ +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; + +/******************************************************************************/ +/* USBC mux configuration - Tiger Lake includes internal mux */ +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +static void ps8815_reset(void) +{ + int val; + + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 0); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 1); + msleep(PS8815_FW_INIT_DELAY_MS); + + /* + * b/144397088 + * ps8815 firmware 0x01 needs special configuration + */ + + CPRINTS("%s: patching ps8815 registers", __func__); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f was %02x", val); + + if (i2c_write8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f set to 0x31"); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f now %02x", val); +} + +/* + * Adjust USB3 settings to improve signal integrity. + * See b/194985848. + */ +__override void board_ps8xxx_tcpc_init(int port) +{ + int rv; + + CPRINTS("%s", __func__); + + /* TX1 EQ 19db / TX2 EQ 19db */ + rv = tcpc_addr_write(port, PS8XXX_I2C_ADDR1_P1_FLAGS, 0x20, 0x77); + /* RX1 EQ 12db / RX2 EQ 13db */ + rv |= tcpc_addr_write(port, PS8XXX_I2C_ADDR1_P1_FLAGS, 0x22, 0x32); + /* Swing level for upstream port output */ + rv |= tcpc_addr_write(port, PS8XXX_I2C_ADDR1_P1_FLAGS, 0xc4, 0x03); + + if (rv) + CPRINTS("%s fail!", __func__); +} + +/* Called on AP S5 -> S0 transition */ +void board_ps8811_init(void) +{ + int rv; + const int port = I2C_PORT_USB_1_MIX; + const int addr = PS8811_I2C_ADDR_FLAGS0 + PS8811_REG_PAGE1; + + CPRINTS("%s", __func__); + + /* AEQ 12db */ + rv = i2c_write8(port, addr, 0x01, 0x26); + /* ADE 2.1db */ + rv |= i2c_write8(port, addr, 0x02, 0x60); + /* BEQ 10.5db */ + rv |= i2c_write8(port, addr, 0x05, 0x16); + /* BDE 2.1db */ + rv |= i2c_write8(port, addr, 0x06, 0x63); + /* Channel A swing level */ + rv |= i2c_write8(port, addr, 0x66, 0x20); + /* Channel B swing level */ + rv |= i2c_write8(port, addr, 0xa4, 0x03); + /* PS level foe B channel */ + rv |= i2c_write8(port, addr, 0xa5, 0x83); + /* DE level foe B channel */ + rv |= i2c_write8(port, addr, 0xa6, 0x14); + + if (rv) + CPRINTS("%s fail!", __func__); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_ps8811_init, HOOK_PRIO_LAST); + +void board_reset_pd_mcu(void) +{ + /* No reset available for TCPC on port 0 */ + /* Daughterboard specific reset for port 1 */ + ps8815_reset(); + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +/******************************************************************************/ +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/******************************************************************************/ +/* TCPC support routines */ +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +/******************************************************************************/ + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; +} diff --git a/board/chronicler/usbc_config.h b/board/chronicler/usbc_config.h new file mode 100644 index 0000000000..7428d0c436 --- /dev/null +++ b/board/chronicler/usbc_config.h @@ -0,0 +1,16 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* volteer board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +/* Configure the USB3 daughterboard type */ +void config_usb3_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/chronicler/vif_override.xml b/board/chronicler/vif_override.xml new file mode 100644 index 0000000000..29dd5642e3 --- /dev/null +++ b/board/chronicler/vif_override.xml @@ -0,0 +1,114 @@ + + + Volteer RT1715 + 0 + 0 + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 9A1B + + + + 8087 + + + + + + Not TBT3-Compatible + + + + + + + + + NO + + + + + 50 msec + 3600 mA + + + + + + + Gen 3 (40Gb) + + + + + + + + + + HBR3 + 4 Lanes + + + USB 3.2 Gen 2x1 + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + PSD + Alternate Mode Controller (AMC) + + + 18D1 + 0000 + + + + + + 8087 + + + + + + + 00000000 + + + + + + diff --git a/board/coachz/base_detect.c b/board/coachz/base_detect.c index ae485dc5ee..fbae1698de 100644 --- a/board/coachz/base_detect.c +++ b/board/coachz/base_detect.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,7 @@ /* Coachz base detection code */ #include "adc.h" -#include "adc_chip.h" +#include "base_state.h" #include "board.h" #include "chipset.h" #include "common.h" @@ -19,11 +19,12 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) /* Base detection and debouncing */ -#define BASE_DETECT_DEBOUNCE_US (20 * MSEC) +#define BASE_DETECT_EN_DEBOUNCE_US (350 * MSEC) +#define BASE_DETECT_DIS_DEBOUNCE_US (20 * MSEC) /* * If the base status is unclear (i.e. not within expected ranges, read @@ -80,9 +81,9 @@ static void base_detect_change(enum base_status status) if (current_base_status == status) return; - CPRINTS("Base %sconnected", connected ? "" : "not "); gpio_set_level(GPIO_EN_BASE, connected); - tablet_set_mode(!connected); + tablet_set_mode(!connected, TABLET_TRIGGER_BASE); + base_set_state(connected); current_base_status = status; } @@ -92,8 +93,8 @@ static uint32_t pulse_width; static void print_base_detect_value(int v, int tmp_pulse_width) { - CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name, - v, tmp_pulse_width); + CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name, v, + tmp_pulse_width); } static void base_detect_deferred(void) @@ -142,6 +143,12 @@ static inline int detect_pin_connected(enum gpio_signal det_pin) void base_detect_interrupt(enum gpio_signal signal) { uint64_t time_now = get_time().val; + int debounce_us; + + if (detect_pin_connected(signal)) + debounce_us = BASE_DETECT_EN_DEBOUNCE_US; + else + debounce_us = BASE_DETECT_DIS_DEBOUNCE_US; if (base_detect_debounce_time <= time_now) { /* @@ -158,8 +165,7 @@ void base_detect_interrupt(enum gpio_signal signal) } pulse_width = 0; - hook_call_deferred(&base_detect_deferred_data, - BASE_DETECT_DEBOUNCE_US); + hook_call_deferred(&base_detect_deferred_data, debounce_us); } else { if (current_base_status == BASE_CONNECTED && detect_pin_connected(signal) && !pulse_width && @@ -172,7 +178,7 @@ void base_detect_interrupt(enum gpio_signal signal) } } - base_detect_debounce_time = time_now + BASE_DETECT_DEBOUNCE_US; + base_detect_debounce_time = time_now + debounce_us; } static void base_enable(void) @@ -186,9 +192,13 @@ DECLARE_HOOK(HOOK_CHIPSET_STARTUP, base_enable, HOOK_PRIO_DEFAULT); static void base_disable(void) { - /* Disable base detection interrupt and disable power to base. */ + /* + * Disable base detection interrupt and disable power to base. + * Set the state UNKNOWN so the next startup will initialize a + * correct state and notify AP. + */ gpio_disable_interrupt(GPIO_BASE_DET_L); - base_detect_change(BASE_DISCONNECTED); + base_detect_change(BASE_UNKNOWN); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, base_disable, HOOK_PRIO_DEFAULT); @@ -201,15 +211,15 @@ static void base_init(void) if (system_jumped_late() && chipset_in_state(CHIPSET_STATE_ON)) base_enable(); } -DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT+1); +DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT + 1); -void base_force_state(int state) +void base_force_state(enum ec_set_base_state_cmd state) { - if (state == 1) { + if (state == EC_SET_BASE_STATE_ATTACH) { gpio_disable_interrupt(GPIO_BASE_DET_L); base_detect_change(BASE_CONNECTED); CPRINTS("BD forced connected"); - } else if (state == 0) { + } else if (state == EC_SET_BASE_STATE_DETACH) { gpio_disable_interrupt(GPIO_BASE_DET_L); base_detect_change(BASE_DISCONNECTED); CPRINTS("BD forced disconnected"); diff --git a/board/coachz/battery.c b/board/coachz/battery.c index a97395ca73..a89b26f49a 100644 --- a/board/coachz/battery.c +++ b/board/coachz/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -33,6 +33,66 @@ */ const struct board_batt_params board_battery_info[] = { + /* COSMX GH02047XL 333-1C-DA-A */ + [BATTERY_GH02047XL_1C] = { + .fuel_gauge = { + .manuf_name = "333-1C-DA-A", + .device_name = "GH02047XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* COSMX GH02047XL */ + [BATTERY_GH02047XL] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .device_name = "GH02047XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, /* COSMX DS02032XL */ [BATTERY_DS02032XL] = { .fuel_gauge = { @@ -60,6 +120,37 @@ const struct board_batt_params board_battery_info[] = { .charging_max_c = 45, .discharging_min_c = -10, .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* SMP DS02032XL */ + [BATTERY_DS02032XL_1C] = { + .fuel_gauge = { + .manuf_name = "333-1C-13-A", + .device_name = "DS02032XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, }, }, }; diff --git a/board/coachz/board.c b/board/coachz/board.c index 3e9b46655b..d1ab5fb647 100644 --- a/board/coachz/board.c +++ b/board/coachz/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,30 +9,37 @@ #include "button.h" #include "charge_manager.h" #include "charge_state.h" -#include "extpower.h" +#include "common.h" #include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi260.h" #include "driver/accelgyro_bmi_common.h" #include "driver/ppc/sn5s330.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" -#include "keyboard_scan.h" #include "lid_switch.h" +#include "mkbp_input_devices.h" +#include "peripheral_charger.h" #include "pi3usb9201.h" #include "power.h" +#include "power/qcom.h" #include "power_button.h" #include "pwm.h" #include "pwm_chip.h" -#include "system.h" +#include "queue.h" #include "shi_chip.h" #include "switch.h" +#include "system.h" #include "tablet_mode.h" #include "task.h" #include "usbc_ppc.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define KS_DEBOUNCE_US (30 * MSEC) /* Debounce time for kickstand switch */ /* Forward declaration */ static void tcpc_alert_event(enum gpio_signal signal); @@ -40,9 +47,45 @@ static void usb0_evt(enum gpio_signal signal); static void usb1_evt(enum gpio_signal signal); static void ppc_interrupt(enum gpio_signal signal); static void board_connect_c0_sbu(enum gpio_signal s); +static void ks_interrupt(enum gpio_signal s); +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" +/* + * Workaround for b/193223400. This disables the IRQ from CTN730. Fixing this + * here (using a rather awkward way) separates the fix from the common code. + */ +#ifdef SECTION_IS_RW +#define GPIO_PCHG_P0 GPIO_WLC_IRQ_CONN +#else +#define GPIO_PCHG_P0 ARRAY_SIZE(gpio_irq_handlers) +#endif + +extern struct pchg_drv ctn730_drv; + +struct pchg pchgs[] = { + [0] = { + .cfg = &(const struct pchg_config) { + .drv = &ctn730_drv, + .i2c_port = I2C_PORT_WLC, + .irq_pin = GPIO_PCHG_P0, + .full_percent = 96, + .block_size = 128, + }, + .policy = { + [PCHG_CHIPSET_STATE_ON] = &pchg_policy_on, + [PCHG_CHIPSET_STATE_SUSPEND] = &pchg_policy_suspend, + }, + .events = QUEUE_NULL(PCHG_EVENT_QUEUE_SIZE, enum pchg_event), + }, +}; + +int board_get_pchg_count(void) +{ + return ARRAY_SIZE(pchgs); +} + /* GPIO Interrupt Handlers */ static void tcpc_alert_event(enum gpio_signal signal) { @@ -64,12 +107,12 @@ static void tcpc_alert_event(enum gpio_signal signal) static void usb0_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } static void usb1_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); } static void ppc_interrupt(enum gpio_signal signal) @@ -101,20 +144,91 @@ static void board_connect_c0_sbu(enum gpio_signal s) hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); } +static int debounced_ks_attached; +static int debounced_ks_open; + +/** + * Kickstand switch initialization + */ +static void ks_init(void) +{ + debounced_ks_attached = !gpio_get_level(GPIO_KS_ATTACHED_L); + debounced_ks_open = gpio_get_level(GPIO_KS_OPEN); + + /* Enable interrupts, now that we've initialized */ + gpio_enable_interrupt(GPIO_KS_ATTACHED_L); + gpio_enable_interrupt(GPIO_KS_OPEN); +} +DECLARE_HOOK(HOOK_INIT, ks_init, HOOK_PRIO_INIT_SWITCH); + +/** + * Handle debounced kickstand switch changing state. + */ +static void ks_change_deferred(void) +{ + const int ks_attached = !gpio_get_level(GPIO_KS_ATTACHED_L); + const int ks_open = gpio_get_level(GPIO_KS_OPEN); + int proximity_detected; + + /* If the switches haven't changed, nothing to do */ + if (ks_attached == debounced_ks_attached && + ks_open == debounced_ks_open) + return; + + /* + * A heuristic method to use the kickstand position to approach + * the human body proximity. + */ + proximity_detected = !(ks_attached && ks_open); + CPRINTS("ks %s %s -> proximity %s", + ks_attached ? "attached" : "detached", + ks_open ? "open" : "close", proximity_detected ? "on" : "off"); + + debounced_ks_attached = ks_attached; + debounced_ks_open = ks_open; + + body_detect_change_state(proximity_detected, false); +} +DECLARE_DEFERRED(ks_change_deferred); + +static void ks_interrupt(enum gpio_signal s) +{ + /* Reset kickstand debounce time */ + hook_call_deferred(&ks_change_deferred_data, KS_DEBOUNCE_US); +} + /* I2C port map */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_EC_I2C_POWER_SCL, - GPIO_EC_I2C_POWER_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 1000, GPIO_EC_I2C_USB_C0_PD_SCL, - GPIO_EC_I2C_USB_C0_PD_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 1000, GPIO_EC_I2C_USB_C1_PD_SCL, - GPIO_EC_I2C_USB_C1_PD_SDA}, - {"wlc", I2C_PORT_WLC, 1000, GPIO_EC_I2C_WLC_SCL, - GPIO_EC_I2C_WLC_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_EC_I2C_EEPROM_SCL, - GPIO_EC_I2C_EEPROM_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_EC_I2C_SENSOR_SCL, - GPIO_EC_I2C_SENSOR_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "wlc", + .port = I2C_PORT_WLC, + .kbps = 400, + .scl = GPIO_EC_I2C_WLC_SCL, + .sda = GPIO_EC_I2C_WLC_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -122,45 +236,25 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /* ADC channels */ const struct adc_t adc_channels[] = { /* Measure VBUS through a 1/10 voltage divider */ - [ADC_VBUS] = { - "VBUS", - NPCX_ADC_CH1, - ADC_MAX_VOLT * 10, - ADC_READ_MAX + 1, - 0 - }, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* * Adapter current output or battery charging/discharging current (uV) * 18x amplification on charger side. */ - [ADC_AMON_BMON] = { - "AMON_BMON", - NPCX_ADC_CH2, - ADC_MAX_VOLT * 1000 / 18, - ADC_READ_MAX + 1, - 0 - }, + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, /* * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we * only divide by 2 (enough to avoid precision issues). */ - [ADC_PSYS] = { - "PSYS", - NPCX_ADC_CH3, - ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), - 2, - 0 - }, + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, /* Base detection */ - [ADC_BASE_DET] = { - "BASE_DET", - NPCX_ADC_CH5, - ADC_MAX_VOLT, - ADC_READ_MAX + 1, - 0 - }, + [ADC_BASE_DET] = { "BASE_DET", NPCX_ADC_CH5, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -172,16 +266,12 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); /* Power Path Controller */ struct ppc_config_t ppc_chips[] = { - { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, - { - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, }; unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); @@ -191,7 +281,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -199,7 +289,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -212,16 +302,22 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, * the mux misbehaves. */ -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, { - .usb_port = 1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -241,13 +337,14 @@ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { static struct mutex g_lid_mutex; static struct bmi_drv_data_t g_bmi160_data; +static struct bmi_drv_data_t g_bmi260_data; + +bool is_bmi260_present; /* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { /* @@ -257,10 +354,10 @@ struct motion_sensor_t motion_sensors[] = { */ [LID_ACCEL] = { .name = "Lid Accel", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .active_mask = SENSOR_ACTIVE_S0_S3, .chip = MOTIONSENSE_CHIP_BMI160, .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_BASE, + .location = MOTIONSENSE_LOC_LID, .drv = &bmi160_drv, .mutex = &g_lid_mutex, .drv_data = &g_bmi160_data, @@ -278,10 +375,10 @@ struct motion_sensor_t motion_sensors[] = { }, [LID_GYRO] = { .name = "Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .active_mask = SENSOR_ACTIVE_S0_S3, .chip = MOTIONSENSE_CHIP_BMI160, .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_BASE, + .location = MOTIONSENSE_LOC_LID, .drv = &bmi160_drv, .mutex = &g_lid_mutex, .drv_data = &g_bmi160_data, @@ -293,14 +390,102 @@ struct motion_sensor_t motion_sensors[] = { .max_frequency = BMI_GYRO_MAX_FREQ, }, }; + +struct motion_sensor_t motion_sensors_260[] = { + /* + * Note: bmi260: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi260_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [LID_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi260_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +static void board_detect_motionsensor(void) +{ + int val = -1; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + + /* Check base accelgyro chip */ + bmi_read8(motion_sensors[LID_ACCEL].port, + motion_sensors[LID_ACCEL].i2c_spi_addr_flags, BMI260_CHIP_ID, + &val); + if (val == BMI260_CHIP_ID_MAJOR) { + motion_sensors[LID_ACCEL] = motion_sensors_260[LID_ACCEL]; + motion_sensors[LID_GYRO] = motion_sensors_260[LID_GYRO]; + is_bmi260_present = 1; + } else { + is_bmi260_present = 0; + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_DEFAULT + 1); + +void motion_interrupt(enum gpio_signal signal) +{ + if (is_bmi260_present) { + bmi260_interrupt(signal); + } else { + bmi160_interrupt(signal); + } +} + /* Initialize board. */ static void board_init(void) { + /* + * The rev-1 hardware doesn't have the external pull-up fix for the bug + * b/177611071. It requires rework to stuff the resistor. For people who + * has difficulty to do the rework, this is a workaround, which makes + * the GPIO push-pull, instead of open-drain. + */ + if (system_get_board_version() == 1) + gpio_set_flags(GPIO_HIBERNATE_L, GPIO_OUTPUT); + /* Enable BC1.2 interrupts */ gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); /* * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs @@ -314,6 +499,15 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +__overridable uint16_t board_get_ps8xxx_product_id(int port) +{ + /* Coachz board rev 2+ changes TCPC from 8805 to 8755*/ + if (system_get_board_version() < 2) + return PS8805_PRODUCT_ID; + + return PS8755_PRODUCT_ID; +} + void board_tcpc_init(void) { /* Only reset TCPC if not sysjump */ @@ -324,6 +518,7 @@ void board_tcpc_init(void) /* Enable PPC interrupts */ gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); /* Enable TCPC interrupts */ gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); @@ -334,9 +529,36 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_hibernate(void) +{ + int i; + + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + + /* + * Board rev 1+ has the hardware fix. Don't need the following + * workaround. + */ + if (system_get_board_version() >= 1) + return; + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + ppc_vbus_sink_enable(i, 1); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); /* Called on AP S0 -> S3 transition */ static void board_chipset_suspend(void) @@ -416,8 +638,7 @@ void board_overcurrent_event(int port, int is_overcurrented) int board_set_active_charge_port(int port) { - int is_real_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); int i; if (!is_real_port && port != CHARGE_PORT_NONE) @@ -445,7 +666,6 @@ int board_set_active_charge_port(int port) return EC_ERROR_INVAL; } - CPRINTS("New charge port: p%d", port); /* @@ -469,23 +689,20 @@ int board_set_active_charge_port(int port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* * Ignore lower charge ceiling on PD transition if our battery is * critical, as we may brownout. */ - if (supplier == CHARGE_SUPPLIER_PD && - charge_ma < 1500 && + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { CPRINTS("Using max ilim %d", max_ma); charge_ma = max_ma; } - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } uint16_t tcpc_get_alert_status(void) @@ -501,4 +718,3 @@ uint16_t tcpc_get_alert_status(void) return status; } - diff --git a/board/coachz/board.h b/board/coachz/board.h index b85d057604..e0786075df 100644 --- a/board/coachz/board.h +++ b/board/coachz/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,45 +10,80 @@ #include "baseboard.h" -/* TODO(waihong): Remove the following bringup features */ -#define CONFIG_BRINGUP -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands. */ -#define CONFIG_USB_PD_DEBUG_LEVEL 3 -#define CONFIG_CMD_AP_RESET_LOG -#define CONFIG_CMD_GPIO_EXTENDED -#define CONFIG_CMD_POWERINDEBUG -#define CONFIG_I2C_DEBUG +/* On-body detection */ +#define CONFIG_BODY_DETECTION +#define CONFIG_BODY_DETECTION_SENSOR LID_ACCEL +#define CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR 150 /* % */ +#define CONFIG_GESTURE_DETECTION +#define CONFIG_GESTURE_DETECTION_MASK BIT(CONFIG_BODY_DETECTION_SENSOR) +#define CONFIG_GESTURE_HOST_DETECTION + +#define CONFIG_BUTTON_TRIGGERED_RECOVERY /* Internal SPI flash on NPCX7 */ -#define CONFIG_FLASH_SIZE (512 * 1024) /* 512KB internal spi flash */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Save some flash space */ +#define CONFIG_LTO +#define CONFIG_USB_PD_DEBUG_LEVEL 2 +#undef CONFIG_CMD_FLASHINFO +#undef CONFIG_CMD_MMAPINFO +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_ACCEL_FIFO +#undef CONFIG_CMD_ACCEL_INFO +#undef CONFIG_CMD_TASK_RESET +#undef CONFIG_CONSOLE_CMDHELP /* Battery */ -#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_REVIVE_DISCONNECT #define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_VENDOR_PARAM + +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 /* BC 1.2 Charger */ #define CONFIG_BC12_DETECT_PI3USB9201 /* USB */ +#define CONFIG_USB_PD_TCPM_MULTI_PS8XXX +#define CONFIG_USB_PD_TCPM_PS8755 #define CONFIG_USB_PD_TCPM_PS8805 #define CONFIG_USBC_PPC_SN5S330 #define CONFIG_USB_PD_PORT_MAX_COUNT 2 /* BMI160 Lid accel/gyro */ #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) #define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS +#define CONFIG_ACCELGYRO_BMI260 +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) #define CONFIG_TABLET_MODE #define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE +#define CONFIG_FRONT_PROXIMITY_SWITCH + +#define CONFIG_MKBP_INPUT_DEVICES + +#define CONFIG_DETACHABLE_BASE +#define CONFIG_BASE_ATTACHED_SWITCH /* GPIO alias */ #define GPIO_AC_PRESENT GPIO_CHG_ACOK_OD #define GPIO_WP_L GPIO_EC_FLASH_WP_ODL #define GPIO_PMIC_RESIN_L GPIO_PM845_RESIN_L +#define GPIO_TABLET_MODE_L GPIO_LID_360_L +#define GPIO_KS_ATTACHED_L GPIO_LID_INT_N_HALL1 +#define GPIO_KS_OPEN GPIO_LID_INT_N_HALL2 + +/* WLC pins */ +#define CONFIG_PERIPHERAL_CHARGER +#define CONFIG_DEVICE_EVENT +#define CONFIG_CTN730 #ifndef __ASSEMBLER__ @@ -70,30 +105,24 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_DISPLIGHT = 0, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_DISPLIGHT = 0, PWM_CH_COUNT }; /* List of possible batteries */ enum battery_type { + BATTERY_GH02047XL_1C, + BATTERY_GH02047XL, BATTERY_DS02032XL, + BATTERY_DS02032XL_1C, BATTERY_TYPE_COUNT, }; -/* Swithcap functions */ -void board_set_switchcap_power(int enable); -int board_is_switchcap_enabled(void); -int board_is_switchcap_power_good(void); -/* Custom function to indicate if sourcing VBUS */ -int board_is_sourcing_vbus(int port); -/* Enable VBUS sink for a given port */ -int board_vbus_sink_enable(int port, int enable); /* Reset all TCPCs. */ void board_reset_pd_mcu(void); void board_set_tcpc_power_mode(int port, int mode); /* Base detection */ void base_detect_interrupt(enum gpio_signal signal); +/* motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); #endif /* !defined(__ASSEMBLER__) */ diff --git a/board/coachz/build.mk b/board/coachz/build.mk index 5b6ecb0398..01678fc8bb 100644 --- a/board/coachz/build.mk +++ b/board/coachz/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,4 +11,4 @@ CHIP_FAMILY:=npcx7 CHIP_VARIANT:=npcx7m6fc BASEBOARD:=trogdor -board-y=battery.o board.o led.o base_detect.o +board-y=battery.o board.o led.o base_detect.o usbc_config.o diff --git a/board/coachz/ec.tasklist b/board/coachz/ec.tasklist index 49e7fb11c6..ecb6672d32 100644 --- a/board/coachz/ec.tasklist +++ b/board/coachz/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,6 +9,7 @@ #define CONFIG_TASK_LIST \ TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PCHG, pchg_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ diff --git a/board/coachz/gpio.inc b/board/coachz/gpio.inc index d60d49fd77..1bb8e9135b 100644 --- a/board/coachz/gpio.inc +++ b/board/coachz/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,22 +13,25 @@ GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) / GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ -GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING, usb0_evt) /* Interrupt from port-0 BC1.2 */ -GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING, usb1_evt) /* Interrupt from port-1 BC1.2 */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb1_evt) /* Interrupt from port-1 BC1.2 */ /* System interrupts */ -GPIO_INT(CHG_ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) /* AC OK? */ +GPIO_INT(CHG_ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ GPIO_INT(EC_FLASH_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ -GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) /* Lid open? */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ -GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ -GPIO_INT(PMIC_FAULT_L, PIN(A, 3), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) /* Any PMIC fault? */ -GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ + +/* WLC interrupt. GPIO_PULL_DOWN ensures no IRQ when WLC chip is off. */ +GPIO_INT(WLC_IRQ_CONN, PIN(7, 4), GPIO_INT_RISING | GPIO_PULL_DOWN, pchg_irq) + /* * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down * to make it low. Overload the interrupt function chipset_warm_reset_interrupt @@ -42,49 +45,37 @@ GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs GPIO_INT(BASE_DET_L, PIN(3, 7), GPIO_INT_BOTH, base_detect_interrupt) /* Detachable base attached? */ /* Sensor interrupts */ -GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) /* Accelerometer/gyro interrupt */ +GPIO_INT(LID_360_L, PIN(7, 3), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(LID_INT_N_HALL1, PIN(D, 7), GPIO_INT_BOTH, ks_interrupt) /* Kickstand attached (0) or detached (1) */ +GPIO_INT(LID_INT_N_HALL2, PIN(6, 0), GPIO_INT_BOTH, ks_interrupt) /* Kickstand close (0) or open (1) */ +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, motion_interrupt) /* Accelerometer/gyro interrupt */ /* - * EC_RST_ODL acts as a wake source from PSL hibernate mode. However, it does - * not need to be an interrupt for normal EC operations. Thus, configure it as - * GPIO_INT_BOTH with wake on low-to-high edge using GPIO_HIB_WAKE_HIGH so that - * PSL common code can configure PSL_IN correctly. - * - * Use the rising edge to wake EC up. If we chose the falling edge, it would - * still wake EC up, but EC is in an intermediate state until the signal goes - * back to high. + * EC_RST_ODL acts as a wake source from hibernate mode. However, it does not + * need to be an interrupt for normal EC operations. Simply set it an INPUT. */ -GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* Wake source: EC reset */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ /* PMIC/AP 1.8V */ -GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC reset trigger */ -GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC power button */ +GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ GPIO(QSIP_ON, PIN(5, 0), GPIO_OUT_LOW) /* Not used, for non-switchcap testing */ /* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ GPIO(SWITCHCAP_ON, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap; will be configured in the board init */ -/* TODO(waihong): Remove it. The VBOB switch is for backup. */ -GPIO(VBOB_EN, PIN(D, 3), GPIO_OUT_LOW) /* Enable VBOB */ GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ -/* Sensors */ -GPIO(REVERSE_DOCK_EC, PIN(C, 6), GPIO_INPUT) -/* TODO(b/168714440): Implement the hall sensor interrupts */ -GPIO(LID_INT_N_HALL1, PIN(7, 3), GPIO_INPUT) -GPIO(LID_INT_N_HALL2, PIN(6, 0), GPIO_INPUT) -GPIO(LID_INT_N_HALL3, PIN(D, 7), GPIO_INPUT) /* TODO(waihong): Should remove it from hardware */ GPIO(CAM_LED, PIN(3, 0), GPIO_INPUT) -/* Stylus */ -/* TODO(b/168652326): Implement the WLC controls */ -GPIO(WLC_IRQ_CONN, PIN(7, 4), GPIO_INPUT) -GPIO(WLC_NRST_CONN, PIN(C, 5), GPIO_INPUT) +/* Reset line for WLC. External pull-up is expected. */ +GPIO(WLC_NRST_CONN, PIN(C, 5), GPIO_ODR_HIGH) /* Base detection */ GPIO(EN_BASE, PIN(0, 4), GPIO_OUT_LOW) /* Enable power to detachable base */ @@ -92,18 +83,23 @@ GPIO(EN_BASE, PIN(0, 4), GPIO_OUT_LOW) /* Enable power to detach /* USB-C */ GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_ODR_HIGH) /* Port-0 TCPC chip reset, actaully Open-Drain */ GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_ODR_HIGH) /* Port-1 TCPC chip reset, actually Open-Drain */ -GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_OUT_HIGH) /* DP mux enable */ -GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_HIGH) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ -/* USB-A */ -GPIO(EN_USB_A_5V, PIN(8, 6), GPIO_INPUT) /* NC, backup only */ -GPIO(USB_A_CDP_ILIM_EN, PIN(7, 5), GPIO_INPUT) /* NC, backup only */ - /* LEDs */ GPIO(EC_CHG_LED_Y_C0, PIN(C, 3), GPIO_OUT_LOW) GPIO(EC_CHG_LED_W_C0, PIN(C, 4), GPIO_OUT_LOW) +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + /* PWM */ GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ @@ -141,6 +137,54 @@ GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) */ GPIO(DA9313_GPIO0, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. Apply PU for power saving */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(3, 1)) +UNUSED(PIN(2, 7)) +UNUSED(PIN(2, 6)) +UNUSED(PIN(2, 5)) +UNUSED(PIN(2, 4)) +UNUSED(PIN(2, 3)) +UNUSED(PIN(2, 2)) +UNUSED(PIN(2, 1)) +UNUSED(PIN(2, 0)) +UNUSED(PIN(1, 7)) +UNUSED(PIN(1, 6)) +UNUSED(PIN(1, 5)) +UNUSED(PIN(1, 4)) +UNUSED(PIN(1, 3)) +UNUSED(PIN(1, 2)) +UNUSED(PIN(1, 1)) +UNUSED(PIN(1, 0)) +UNUSED(PIN(0, 7)) +UNUSED(PIN(0, 6)) +UNUSED(PIN(0, 5)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 6)) +UNUSED(PIN(C, 0)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(6, 2)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(5, 6)) +UNUSED(PIN(8, 0)) +UNUSED(PIN(D, 3)) +UNUSED(PIN(7, 5)) +UNUSED(PIN(8, 6)) + /* Alternate functions GPIO definitions */ ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ @@ -149,12 +193,7 @@ ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ ALTERNATE(PIN_MASK(D, 0x03), 1, MODULE_I2C, 0) /* I2C3 (GPIOD0/D1) */ -ALTERNATE(PIN_MASK(3, 0x80), 0, MODULE_ADC, 0) /* ADC5 (GPIO37) */ ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ -ALTERNATE(PIN_MASK(D, 0x04), 1, MODULE_PMU, 0) /* PSL_IN1 (GPIOD2) - LID_OPEN_EC */ -ALTERNATE(PIN_MASK(0, 0x01), 1, MODULE_PMU, 0) /* PSL_IN2 (GPIO00) - ACOK_OD */ -ALTERNATE(PIN_MASK(0, 0x02), 1, MODULE_PMU, 0) /* PSL_IN3 (GPIO01) - EC_PWR_BTN_ODL */ -ALTERNATE(PIN_MASK(0, 0x04), 1, MODULE_PMU, 0) /* PSL_IN4 (GPIO02) - EC_RST_ODL */ diff --git a/board/coachz/led.c b/board/coachz/led.c index 8575d8cdaf..06840da74c 100644 --- a/board/coachz/led.c +++ b/board/coachz/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,6 +10,7 @@ #include "charge_state.h" #include "chipset.h" #include "ec_commands.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -18,6 +19,8 @@ #include "util.h" #define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +/* Battery LED blinks every per 400ms */ +#define LED_HALF_ONE_SEC (500 / HOOK_TICK_INTERVAL_MS) #define BAT_LED_ON 1 #define BAT_LED_OFF 0 @@ -32,15 +35,15 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_BLUE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static void led_set_color(enum led_color color) { gpio_set_level(GPIO_EC_CHG_LED_Y_C0, - (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); gpio_set_level(GPIO_EC_CHG_LED_W_C0, - (color == LED_BLUE) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_BLUE) ? BAT_LED_ON : BAT_LED_OFF); } void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) @@ -66,56 +69,83 @@ static void board_led_set_battery(void) static int battery_ticks; int color = LED_OFF; int period = 0; - uint32_t chflags = charge_get_flags(); battery_ticks++; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate amber on when charging. */ color = LED_AMBER; break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { - /* Discharging in S3: Amber 1 sec, off 3 sec */ - period = (1 + 3) * LED_ONE_SEC; + /* Discharging in S3: White 1 sec, off 1 sec */ + period = (1 + 1) * LED_ONE_SEC; battery_ticks = battery_ticks % period; - if (battery_ticks < 1 * LED_ONE_SEC) - color = LED_AMBER; - else + if (battery_ticks < 1 * LED_ONE_SEC) { + if (charge_get_percent() < 10) { + /* Blink amber light (1 sec on, 1 sec + * off) */ + color = LED_AMBER; + } else { + /* Blink white light (1 sec on, 1 sec + * off) */ + color = LED_BLUE; + } + } else { color = LED_OFF; - } else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { - /* Discharging in S5: off */ - color = LED_OFF; - } else if (chipset_in_state(CHIPSET_STATE_ON)) { - /* Discharging in S0: Blue on */ - color = LED_BLUE; + } + } else { + /* Discharging in S5 and S0: off */ + /* Blink amber light (1 sec on, 1 sec off) */ + if (charge_get_percent() < 10) { + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_AMBER; + else + color = LED_OFF; + } else { + /* G3 or S5 or S0: off */ + color = LED_OFF; + } } break; - case PWR_STATE_ERROR: - /* Battery error: Amber 1 sec, off 1 sec */ - period = (1 + 1) * LED_ONE_SEC; + case LED_PWRS_ERROR: + /* Battery error: Amber on 0.5 sec, off 0.5 sec */ + period = (1 + 1) * LED_HALF_ONE_SEC; battery_ticks = battery_ticks % period; - if (battery_ticks < 1 * LED_ONE_SEC) + if (battery_ticks < 1 * LED_HALF_ONE_SEC) color = LED_AMBER; else color = LED_OFF; break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: /* Full Charged: Blue on */ - color = LED_BLUE; - break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) { - /* Factory mode: Blue 2 sec, Amber 2 sec */ - period = (2 + 2) * LED_ONE_SEC; + /* S3: Blink white light (1 sec on, 1 sec off) */ + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + period = (1 + 1) * LED_ONE_SEC; battery_ticks = battery_ticks % period; - if (battery_ticks < 2 * LED_ONE_SEC) + if (battery_ticks < 1 * LED_ONE_SEC) color = LED_BLUE; else - color = LED_AMBER; - } else + color = LED_OFF; + } else { + /* Full charged: White on */ color = LED_BLUE; + } + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_BLUE; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode: Blue 2 sec, Amber 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) + color = LED_BLUE; + else + color = LED_AMBER; break; default: /* Other states don't alter LED behavior */ diff --git a/board/coachz/usbc_config.c b/board/coachz/usbc_config.c new file mode 100644 index 0000000000..704d21722a --- /dev/null +++ b/board/coachz/usbc_config.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor family-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "gpio.h" +#include "usb_pd.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/coachz/vif_override.xml b/board/coachz/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/coachz/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/coffeecake/board.c b/board/coffeecake/board.c index e00c9e7b4b..441f95d21b 100644 --- a/board/coffeecake/board.c +++ b/board/coffeecake/board.c @@ -1,11 +1,10 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Coffeecake dock configuration */ #include "adc.h" -#include "adc_chip.h" #include "charger/sy21612.h" #include "clock.h" #include "common.h" @@ -17,10 +16,10 @@ #include "mcdp28x0.h" #include "registers.h" #include "task.h" +#include "timer.h" #include "usb_bb.h" #include "usb_descriptor.h" #include "usb_pd.h" -#include "timer.h" #include "util.h" static volatile uint64_t hpd_prev_ts; @@ -28,11 +27,16 @@ static volatile int hpd_prev_level; void hpd_event(enum gpio_signal signal); void vbus_event(enum gpio_signal signal); +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"charger", I2C_PORT_SY21612, 400, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, + { .name = "charger", + .port = I2C_PORT_SY21612, + .kbps = 400, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -148,7 +152,7 @@ void board_config_pre_init(void) /* Set 5Vsafe Vdac */ board_set_usb_output_voltage(5000); /* Remap USART DMA to match the USART driver */ - STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10);/* Remap USART1 RX/TX DMA */ + STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10); /* Remap USART1 RX/TX DMA */ } #ifdef CONFIG_SPI_FLASH @@ -192,10 +196,9 @@ static void factory_validation_deferred(void) /* test mcdp via serial to validate function */ if (!mcdp_get_info(&info) && (MCDP_FAMILY(info.family) == 0x0010) && - (MCDP_CHIPID(info.chipid) == 0x2850)) { + (MCDP_CHIPID(info.chipid) == 0x2850)) { pd_log_event(PD_EVENT_VIDEO_CODEC, - PD_LOG_PORT_SIZE(0, sizeof(info)), - 0, &info); + PD_LOG_PORT_SIZE(0, sizeof(info)), 0, &info); } mcdp_disable(); @@ -210,7 +213,8 @@ static void board_post_init(void) * DUT powered - DRP SINK */ pd_set_dual_role(0, gpio_get_level(GPIO_AC_PRESENT_L) ? - PD_DRP_FORCE_SINK : PD_DRP_FORCE_SOURCE); + PD_DRP_FORCE_SINK : + PD_DRP_FORCE_SOURCE); } DECLARE_DEFERRED(board_post_init); @@ -228,10 +232,11 @@ static void board_init(void) gpio_enable_interrupt(GPIO_CHARGER_INT); gpio_enable_interrupt(GPIO_USB_C_VBUS_DET_L); /* Set PD_DISCHARGE initial state */ - gpio_set_level(GPIO_PD_DISCHARGE, gpio_get_level(GPIO_USB_C_VBUS_DET_L)); + gpio_set_level(GPIO_PD_DISCHARGE, + gpio_get_level(GPIO_USB_C_VBUS_DET_L)); /* Delay needed to allow HDMI MCU to boot. */ - hook_call_deferred(&factory_validation_deferred_data, 200*MSEC); + hook_call_deferred(&factory_validation_deferred_data, 200 * MSEC); /* Initialize buck-boost converter */ hook_call_deferred(&board_post_init_data, 0); } @@ -241,16 +246,16 @@ DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); /* ADC channels */ const struct adc_t adc_channels[] = { /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_CH_CC1_PD] = {"USB_C_CC1_PD", 3300, 4096, 0, STM32_AIN(1)}, - [ADC_VBUS_MON] = {"VBUS_MON", 13200, 4096, 0, STM32_AIN(2)}, - [ADC_DAC_REF_TP28] = {"DAC_REF_TP28", 3300, 4096, 0, STM32_AIN(4)}, - [ADC_DAC_VOLT] = {"DAC_VOLT", 3300, 4096, 0, STM32_AIN(5)}, + [ADC_CH_CC1_PD] = { "USB_C_CC1_PD", 3300, 4096, 0, STM32_AIN(1) }, + [ADC_VBUS_MON] = { "VBUS_MON", 13200, 4096, 0, STM32_AIN(2) }, + [ADC_DAC_REF_TP28] = { "DAC_REF_TP28", 3300, 4096, 0, STM32_AIN(4) }, + [ADC_DAC_VOLT] = { "DAC_VOLT", 3300, 4096, 0, STM32_AIN(5) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); -const void * const usb_strings[] = { +const void *const usb_strings[] = { [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), [USB_STR_PRODUCT] = USB_STRING_DESC("Hoho"), [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), [USB_STR_BB_URL] = USB_STRING_DESC(USB_GOOGLE_TYPEC_URL), diff --git a/board/coffeecake/board.h b/board/coffeecake/board.h index f69ebe2f29..9c7a2643d0 100644 --- a/board/coffeecake/board.h +++ b/board/coffeecake/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,9 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H +/* Free up flash space */ +#define CONFIG_LTO + /* 48 MHz SYSCLK clock frequency */ #define CPU_CLOCK 48000000 @@ -15,7 +18,6 @@ #define CONFIG_UART_CONSOLE 1 /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_ADC #define CONFIG_BOARD_PRE_INIT #define CONFIG_CMD_CHARGER @@ -24,15 +26,14 @@ #define CONFIG_CHARGER_SY21612 #define CONFIG_HW_CRC #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_RSA #define CONFIG_RWSIG #define CONFIG_RWSIG_TYPE_USBPD1 #define CONFIG_SHA256 -/* TODO(tbroch) Re-enable once STM spi master can be inhibited at boot so it +/* TODO(tbroch) Re-enable once STM spi controller can be inhibited at boot so it doesn't interfere with HDMI loading its f/w */ #undef CONFIG_SPI_FLASH -#define CONFIG_SPI_MASTER_PORT 2 #define CONFIG_SPI_CS_GPIO GPIO_PD_MCDP_SPI_CS_L #define CONFIG_USB #define CONFIG_USB_BOS @@ -48,7 +49,7 @@ #define CONFIG_USB_PD_IDENTITY_HW_VERS 1 #define CONFIG_USB_PD_IDENTITY_SW_VERS 1 #define CONFIG_USB_PD_LOGGING -#undef CONFIG_EVENT_LOG_SIZE +#undef CONFIG_EVENT_LOG_SIZE #define CONFIG_EVENT_LOG_SIZE 256 #define CONFIG_USB_PD_CUSTOM_PDO #define CONFIG_USB_PD_PORT_MAX_COUNT 1 @@ -78,7 +79,7 @@ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 +#define TIM_ADC 3 #include "gpio_signal.h" @@ -104,21 +105,21 @@ enum usb_strings { }; /* 3.0A Rp */ -#define PD_SRC_VNC PD_SRC_3_0_VNC_MV -#define PD_SRC_RD_THRESHOLD PD_SRC_3_0_RD_THRESH_MV +#define PD_SRC_VNC PD_SRC_3_0_VNC_MV +#define PD_SRC_RD_THRESHOLD PD_SRC_3_0_RD_THRESH_MV /* delay necessary for the voltage transition on the power supply */ /* TODO (code.google.com/p/chrome-os-partner/issues/detail?id=37078) * Need to measure these and adjust for honeybuns. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 1000 -#define PD_MAX_POWER_MW 22500 -#define PD_MAX_CURRENT_MA 2500 -#define PD_MAX_VOLTAGE_MV 9000 +#define PD_MAX_POWER_MW 22500 +#define PD_MAX_CURRENT_MA 2500 +#define PD_MAX_VOLTAGE_MV 9000 /* Board interfaces */ void board_set_usb_output_voltage(int mv); @@ -129,11 +130,11 @@ void board_set_usb_output_voltage(int mv); #define USB_DEV_CLASS USB_CLASS_BILLBOARD /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_COUNT 0 +#define USB_IFACE_COUNT 0 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_COUNT 1 +#define USB_EP_CONTROL 0 +#define USB_EP_COUNT 1 /* I2C ports */ #define I2C_PORT_SY21612 0 diff --git a/board/coffeecake/build.mk b/board/coffeecake/build.mk index fb5a6fccdb..26ddbbd925 100644 --- a/board/coffeecake/build.mk +++ b/board/coffeecake/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -14,4 +14,4 @@ CHIP_VARIANT:=stm32f07x test-list-y= board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_pdo.o diff --git a/board/coffeecake/ec.tasklist b/board/coffeecake/ec.tasklist index d6686d72e9..e02c0620f8 100644 --- a/board/coffeecake/ec.tasklist +++ b/board/coffeecake/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/coffeecake/gpio.inc b/board/coffeecake/gpio.inc index bab62a6bea..9d0a02ea40 100644 --- a/board/coffeecake/gpio.inc +++ b/board/coffeecake/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/coffeecake/usb_pd_config.h b/board/coffeecake/usb_pd_config.h index e2c1dbb2db..728d96bafe 100644 --- a/board/coffeecake/usb_pd_config.h +++ b/board/coffeecake/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -49,7 +49,7 @@ static inline void spi_enable_clock(int port) #define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 #define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 -#define TIM_CCR_CS 1 +#define TIM_CCR_CS 1 #define EXTI_COMP_MASK(p) BIT(21) #define IRQ_COMP STM32_IRQ_COMP /* triggers packet detection on comparator falling edge */ @@ -100,8 +100,8 @@ static inline void pd_select_polarity(int port, int polarity) * use the right comparator : CC1 -> PA1 (COMP1 INP) * use VrefInt / 2 as INM (about 600mV) */ - STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) - | STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12; + STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) | + STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12; } /* Initialize pins used for TX and put them in Hi-Z */ @@ -136,7 +136,7 @@ static inline int pd_adc_read(int port, int cc) * Check HOST_HIGH Rp setting. * Return 3300mV on host mode. */ - if ((STM32_GPIO_MODER(GPIO_B) & (3 << (2*5))) == (1 << (2*5))) + if ((STM32_GPIO_MODER(GPIO_B) & (3 << (2 * 5))) == (1 << (2 * 5))) return 3300; else return 0; diff --git a/board/coffeecake/usb_pd_pdo.c b/board/coffeecake/usb_pd_pdo.c new file mode 100644 index 0000000000..c0d2298706 --- /dev/null +++ b/board/coffeecake/usb_pd_pdo.c @@ -0,0 +1,27 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +#define PDO_FIXED_FLAGS_EXT \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_COMM_CAP | \ + PDO_FIXED_UNCONSTRAINED) + +#define PDO_FIXED_FLAGS \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_COMM_CAP) + +const uint32_t pd_src_pdo[] = { + [PDO_IDX_5V] = PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS_EXT), + [PDO_IDX_9V] = PDO_FIXED(9000, 2500, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +BUILD_ASSERT(ARRAY_SIZE(pd_src_pdo) == PDO_IDX_COUNT); + +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/coffeecake/usb_pd_pdo.h b/board/coffeecake/usb_pd_pdo.h new file mode 100644 index 0000000000..2ec925955d --- /dev/null +++ b/board/coffeecake/usb_pd_pdo.h @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_COFFEECAKE_USB_PD_PDO_H +#define __CROS_EC_BOARD_COFFEECAKE_USB_PD_PDO_H + +#include "stdint.h" + +/* Voltage indexes for the PDOs */ +enum volt_idx { + PDO_IDX_5V = 0, + PDO_IDX_9V = 1, + /* TODO: add PPS support */ + PDO_IDX_COUNT +}; + +extern const uint32_t pd_src_pdo[2]; +extern const int pd_src_pdo_cnt; + +extern const uint32_t pd_snk_pdo[1]; +extern const int pd_snk_pdo_cnt; + +#endif /* __CROS_EC_BOARD_COFFEECAKE_USB_PD_PDO_H */ diff --git a/board/coffeecake/usb_pd_policy.c b/board/coffeecake/usb_pd_policy.c index 6da20a5b37..525d1057e2 100644 --- a/board/coffeecake/usb_pd_policy.c +++ b/board/coffeecake/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #include "charger/sy21612.h" #include "common.h" #include "console.h" +#include "cros_version.h" #include "ec_commands.h" #include "gpio.h" #include "hooks.h" @@ -17,39 +18,12 @@ #include "usb_api.h" #include "usb_bb.h" #include "usb_pd.h" +#include "usb_pd_pdo.h" +#include "usb_pd_tcpm.h" #include "util.h" -#include "version.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define PDO_FIXED_FLAGS_EXT (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP | PDO_FIXED_UNCONSTRAINED) - -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP) - - -/* Voltage indexes for the PDOs */ -enum volt_idx { - PDO_IDX_5V = 0, - PDO_IDX_9V = 1, - /* TODO: add PPS support */ - PDO_IDX_COUNT -}; - -/* PDOs */ -const uint32_t pd_src_pdo[] = { - [PDO_IDX_5V] = PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS_EXT), - [PDO_IDX_9V] = PDO_FIXED(9000, 2500, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); -BUILD_ASSERT(ARRAY_SIZE(pd_src_pdo) == PDO_IDX_COUNT); - -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) /* Holds valid object position (opos) for entered mode */ static int alt_mode[PD_AMODE_COUNT]; @@ -123,31 +97,24 @@ int pd_check_power_swap(int port) return 0; } -int pd_check_data_swap(int port, - enum pd_data_role data_role) +int pd_check_data_swap(int port, enum pd_data_role data_role) { /* We can swap to UFP */ return data_role == PD_ROLE_DFP; } -void pd_execute_data_swap(int port, - enum pd_data_role data_role) +void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* TODO: turn on pp5000, pp3300 */ } -void pd_check_pr_role(int port, - enum pd_power_role pr_role, - int flags) +void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { if (pr_role == PD_ROLE_SINK && !gpio_get_level(GPIO_AC_PRESENT_L)) pd_request_power_swap(port); - } -void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_DFP) pd_request_data_swap(port); @@ -162,8 +129,8 @@ const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, - CONFIG_USB_PD_IDENTITY_SW_VERS, - 0, 0, 0, 0, /* SS[TR][12] */ + CONFIG_USB_PD_IDENTITY_SW_VERS, 0, 0, 0, + 0, /* SS[TR][12] */ 0, /* Vconn power */ 0, /* Vconn power required */ 1, /* Vbus power required */ @@ -189,18 +156,16 @@ static int svdm_response_svids(int port, uint32_t *payload) #define OPOS_DP 1 #define OPOS_GFU 1 -const uint32_t vdo_dp_modes[1] = { - VDO_MODE_DP(0, /* UFP pin cfg supported : none */ +const uint32_t vdo_dp_modes[1] = { + VDO_MODE_DP(0, /* UFP pin cfg supported : none */ MODE_DP_PIN_C, /* DFP pin cfg supported */ - 1, /* no usb2.0 signalling in AMode */ - CABLE_PLUG, /* its a plug */ - MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ - MODE_DP_SNK) /* Its a sink only */ + 1, /* no usb2.0 signalling in AMode */ + CABLE_PLUG, /* its a plug */ + MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ + MODE_DP_SNK) /* Its a sink only */ }; -const uint32_t vdo_goog_modes[1] = { - VDO_MODE_GOOGLE(MODE_GOOGLE_FU) -}; +const uint32_t vdo_goog_modes[1] = { VDO_MODE_GOOGLE(MODE_GOOGLE_FU) }; static int svdm_response_modes(int port, uint32_t *payload) { @@ -222,13 +187,15 @@ static int dp_status(int port, uint32_t *payload) if (opos != OPOS_DP) return 0; /* nak */ - payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ - (hpd == 1), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - 0, /* MF pref */ + payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + (hpd == 1), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ gpio_get_level(GPIO_PD_SBU_ENABLE), - 0, /* power low */ + 0, /* power + low + */ 0x2); return 2; } @@ -266,9 +233,9 @@ static int svdm_enter_mode(int port, uint32_t *payload) return rv; } -int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid) +int pd_alt_mode(int port, enum tcpci_msg_type type, uint16_t svid) { - if (type != TCPC_TX_SOP) + if (type != TCPCI_MSG_SOP) return 0; if (svid == USB_SID_DISPLAYPORT) @@ -307,8 +274,7 @@ const struct svdm_response svdm_rsp = { .exit_mode = &svdm_exit_mode, }; -int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) +int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { int rsize; diff --git a/board/coffeecake/vif_override.xml b/board/coffeecake/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/coffeecake/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/collis/battery.c b/board/collis/battery.c new file mode 100644 index 0000000000..21c7b80901 --- /dev/null +++ b/board/collis/battery.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all Volteer battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + [BATTERY_C490] = { + .fuel_gauge = { + .manuf_name = "AS3GWQd3jB", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x10, 0x10 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000c, + .disconnect_val = 0x000c, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0004, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C490; diff --git a/board/collis/board.c b/board/collis/board.c new file mode 100644 index 0000000000..43b8f8f6d3 --- /dev/null +++ b/board/collis/board.c @@ -0,0 +1,458 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board-specific configuration */ +#include "accelgyro.h" +#include "button.h" +#include "cbi_ec_fw_config.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/ppc/syv682x.h" +#include "driver/sync.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "throttle_ap.h" +#include "uart.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config copano_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &copano_kb; +} + +/******************************************************************************/ +/* + * FW_CONFIG defaults for Terrador if the CBI data is not initialized. + */ +union volteer_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_ACTIVE, +}; + +static void board_init(void) +{ +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C0_SENSOR_SCL, + .sda = GPIO_EC_I2C0_SENSOR_SDA, + }, + { + .name = "usb_c0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C1_USB_C0_SCL, + .sda = GPIO_EC_I2C1_USB_C0_SDA, + }, + { + .name = "usb_c1", + .port = I2C_PORT_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C2_USB_C1_SCL, + .sda = GPIO_EC_I2C2_USB_C1_SDA, + }, + { + .name = "usb_0_mix", + .port = I2C_PORT_USB_0_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C3_USB_0_MIX_SCL, + .sda = GPIO_EC_I2C3_USB_0_MIX_SDA, + }, + { + .name = "usb_1_mix", + .port = I2C_PORT_USB_1_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C4_USB_1_MIX_SCL, + .sda = GPIO_EC_I2C4_USB_1_MIX_SDA, + }, + { + .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C5_POWER_SCL, + .sda = GPIO_EC_I2C5_POWER_SDA, + }, + { + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C7_EEPROM_SCL, + .sda = GPIO_EC_I2C7_EEPROM_SDA, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/******************************************************************************/ +/* PWM configuration */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 10000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/******************************************************************************/ +/* EC thermal management configuration */ + +/* + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +/******************************************************************************/ + +static void kb_backlight_enable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, kb_backlight_enable, HOOK_PRIO_DEFAULT); + +static void kb_backlight_disable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kb_backlight_disable, HOOK_PRIO_DEFAULT); + +/*****************************************************************************/ +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/******************************************************************************/ +/* PPC support routines */ +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +/******************************************************************************/ +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USBC mux configuration - Tiger Lake includes internal mux */ +static const struct usb_mux_chain usbc0_usb3_mb_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, +}; + +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc0_usb3_mb_retimer, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +/******************************************************************************/ +/* TCPC support routines */ +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; +} + +/******************************************************************************/ +/* USB-A charging control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; + +static void ps8815_reset(int port) +{ + int val; + int i2c_port; + enum gpio_signal ps8xxx_rst_odl; + + if (port == USBC_PORT_C0) { + ps8xxx_rst_odl = GPIO_USB_C0_RT_RST_ODL; + i2c_port = I2C_PORT_USB_C0; + } else if (port == USBC_PORT_C1) { + ps8xxx_rst_odl = GPIO_USB_C1_RT_RST_ODL; + i2c_port = I2C_PORT_USB_C1; + } else { + return; + } + + gpio_set_level(ps8xxx_rst_odl, 0); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + gpio_set_level(ps8xxx_rst_odl, 1); + msleep(PS8815_FW_INIT_DELAY_MS); + + CPRINTS("[C%d] %s: patching ps8815 registers", port, __func__); + + if (i2c_read8(i2c_port, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f was %02x", val); + + if (i2c_write8(i2c_port, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, 0x31) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f set to 0x31"); + + if (i2c_read8(i2c_port, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f now %02x", val); +} + +void board_reset_pd_mcu(void) +{ + ps8815_reset(USBC_PORT_C0); + usb_mux_hpd_update(USBC_PORT_C0, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); + ps8815_reset(USBC_PORT_C1); + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} diff --git a/board/collis/board.h b/board/collis/board.h new file mode 100644 index 0000000000..d9e903c6b3 --- /dev/null +++ b/board/collis/board.h @@ -0,0 +1,177 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* + * The RAM and flash size combination on the NPCX797FC dose not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +#define CONFIG_VBOOT_EFS2 + +#define CONFIG_POWER_BUTTON + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Chipset features */ +#define CONFIG_POWER_PP5000_CONTROL + +#undef NPCX_PWM1_SEL +#define NPCX_PWM1_SEL 0 /* GPIO C2 is not used as PWM1 */ + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* Keyboard features */ +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* Sensors */ +/* BMA253 accelerometer in base */ +#define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCEL_KX022 + +/* BMI160 accel/gyro in base */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ + +/* + * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C + * cables only support up to 60W, the limitation of 45W is for the Collis + * board. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +#undef CONFIG_USBC_RETIMER_INTEL_BB +#undef CONFIG_USBC_RETIMER_INTEL_BB_RUNTIME_CONFIG + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USBC PPC*/ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C0/C1 */ + +#undef CONFIG_USB_MUX_RUNTIME_CONFIG +#undef CONFIG_USB_PD_TCPC_RUNTIME_CONFIG +#undef CONFIG_USB_PD_TCPM_RT1715 +#undef CONFIG_USB_PD_TCPM_TUSB422 + +/* BC 1.2 */ + +/* Volume Button feature */ + +/* Fan features */ +#undef CONFIG_FANS + +/* charger defines */ +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_0_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT4_1 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM + +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum battery_type { + BATTERY_C490, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_COUNT }; + +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void board_reset_pd_mcu(void); +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/collis/build.mk b/board/collis/build.mk new file mode 100644 index 0000000000..18397fdec3 --- /dev/null +++ b/board/collis/build.mk @@ -0,0 +1,17 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=volteer + +board-y=board.o +board-y+=battery.o +board-y+=led.o +board-y+=sensors.o diff --git a/board/collis/ec.tasklist b/board/collis/ec.tasklist new file mode 100644 index 0000000000..07a91894ed --- /dev/null +++ b/board/collis/ec.tasklist @@ -0,0 +1,27 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/collis/gpio.inc b/board/collis/gpio.inc new file mode 100644 index 0000000000..51c5f6b144 --- /dev/null +++ b/board/collis/gpio.inc @@ -0,0 +1,176 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) + +/* Sensor Interrupts */ +GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) + +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) + +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) +GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) + +/* HDMI interrupts */ + +/* Volume button interrupts */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) + +/* Power Sequencing Signals */ +GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ +GPIO(EC_PCH_DSW_PWROK, PIN(C, 0), GPIO_OUT_LOW) + +/* Other wake sources */ +/* + * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an + * interrupt handler because it is automatically handled by the PSL. + * + * We need to lock the setting so this gpio can't be reconfigured to overdrive + * the real reset signal. (This is the PSL input pin not the real reset pin). + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | + GPIO_HIB_WAKE_HIGH | + GPIO_LOCKED) + +/* AP/PCH Signals */ +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) + +/* USB and USBC Signals */ +GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ +GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ + +/* + * USB_C1 moved from GPIO32 to GPIO83 on boards with board ID >=1. + * GPIO83/EN_PP1800_A is DNS on board ID 0 and GPIO32 is N/C on board ID >=1 + * so it's safe to define GPIOs compatible with both designs. + * TODO (b/149858568): remove board ID=0 support. + */ +GPIO(USB_C0_RT_RST_ODL, PIN(6, 1), GPIO_ODR_LOW) /* USB_C0 Reset */ +GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset */ +GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) +/* There is currently no need to service this interrupt. */ +GPIO(USB_C0_RT_INT_ODL, PIN(B, 7), GPIO_INPUT) +GPIO(USB_C1_RT_INT_ODL, PIN(4, 0), GPIO_INPUT) +GPIO(USB_C0_FRS_EN, PIN(6, 0), GPIO_OUT_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) + +/* Don't have a load switch for retimer */ +UNIMPLEMENTED(USB_C0_LS_EN) +UNIMPLEMENTED(USB_C1_LS_EN) + +/* Misc Signals */ +GPIO(EC_H1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) /* H1 Packet Mode */ +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) /* Keyboard backlight enable*/ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(M2_SSD_PLA, PIN(7, 0), GPIO_INPUT) /* SSD power-loss acknowledgment */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_ODR_HIGH) /* SSD power-loss notification */ + + +/* LED */ +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) /* Battery Full LED / Power LED: White */ +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) /* Battery Charging LED: Amber */ + +/* + * eDP backlight - both PCH and EC have enable pins that must be high + * for the backlight to turn on. Default state is high, and can be turned + * off during sleep states. + */ +GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C3_USB_0_MIX_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C3_USB_0_MIX_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C4_USB_1_MIX_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C4_USB_1_MIX_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_I2C5_POWER_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C5_POWER_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) + +/* Battery signals */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */ +ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ +ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(F, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ + +/* Keyboard pins */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ + +/* UART */ +ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Power Switch Logic (PSL) inputs */ +ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ +ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, + GPIO01 = H1_EC_PWR_BTN_ODL + GPIO02 = EC_RST_ODL */ + +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ + +/* Unused signals */ +GPIO(UNUSED_GPIOD4, PIN(D, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOC2, PIN(C, 2), GPIO_INPUT | GPIO_PULL_UP) + diff --git a/board/collis/led.c b/board/collis/led.c new file mode 100644 index 0000000000..9220b7a95c --- /dev/null +++ b/board/collis/led.c @@ -0,0 +1,101 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/collis/sensors.c b/board/collis/sensors.c new file mode 100644 index 0000000000..dac94535b3 --- /dev/null +++ b/board/collis/sensors.c @@ -0,0 +1,226 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific sensor configuration */ +#include "accelgyro.h" +#include "cbi_ec_fw_config.h" +#include "cbi_ssfc.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/sync.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "tablet_mode.h" +#include "task.h" +#include "util.h" + +/******************************************************************************/ +/* Sensors */ +static struct mutex g_lid_accel_mutex; +static struct mutex g_base_mutex; + +/* sensor private data */ +static struct accelgyro_saved_data_t g_bma253_data; +static struct kionix_accel_data g_kx022_data; + +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; + +/* Rotation matrix for the lid accelerometer */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t base_standard_ref_icm = { + { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void motion_interrupt(enum gpio_signal signal) +{ + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) + icm426xx_interrupt(signal); + else + bmi160_interrupt(signal); +} + +static void baseboard_sensors_init(void) +{ + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LID_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + ccprints("LID_ACCEL is KX022"); + } else + ccprints("LID_ACCEL is BMA253"); + + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE ACCEL is ICM426XX"); + } else + ccprints("BASE ACCEL IS BMI160"); + + /* Enable interrupt for the accel/gyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); diff --git a/board/collis/vif_override.xml b/board/collis/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/collis/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/constitution/board.c b/board/constitution/board.c new file mode 100644 index 0000000000..3bb1142496 --- /dev/null +++ b/board/constitution/board.c @@ -0,0 +1,544 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "builtin/assert.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/cec/bitbang.h" +#include "driver/tcpm/tcpci.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "peripheral_charger.h" +#include "power.h" +#include "power_button.h" +#include "pse_ltc4291.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +/* + * The LTC4291 is a power over ethernet (PoE) power sourcing equipment (PSE) + * controller. + * + * Port 1: 100W + * Port 2-4: 15W + */ +const int pse_port_hpmd[4] = { + LTC4291_HPMD_MAX, + LTC4291_HPMD_MIN, + LTC4291_HPMD_MIN, + LTC4291_HPMD_MIN, +}; + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + case CHARGE_PORT_TYPEC1: + case CHARGE_PORT_TYPEC2: + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power_s5; +static int32_t base_5v_power_z1; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ + +/* PP5000_S5 loads */ +#define PWR_S5_BASE_LOAD (5 * 1431) +#define PWR_S5_REAR_HIGH (5 * 1737) +#define PWR_S5_REAR_LOW (5 * 1055) +#define PWR_S5_HDMI (5 * 580) +#define PWR_S5_MAX (5 * 10000) +#define REAR_DELTA (PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW) + +/* PP5000_Z1 loads */ +#define PWR_Z1_BASE_LOAD (5 * 5) +#define PWR_Z1_C_HIGH (5 * 3600) +#define PWR_Z1_C_LOW (5 * 2000) +#define PWR_Z1_MAX (5 * 9000) +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int rear_ports = 0; + + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power_s5 = PWR_S5_BASE_LOAD; + if (!gpio_get_level(GPIO_USB_A0_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + /* + * Only 1 rear port can run higher power at a time. + */ + if (rear_ports > 0) + base_5v_power_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + if (!gpio_get_level(GPIO_HDMI_CONN_OC_ODL)) + base_5v_power_s5 += PWR_S5_HDMI; + base_5v_power_z1 = PWR_Z1_BASE_LOAD; + if (usbc_overcurrent) + base_5v_power_z1 += PWR_Z1_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) + ec_bj_power(&pi.voltage, &pi.current); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +static void adp_state_init(void) +{ + ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT); + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +static void board_init(void) +{ + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + gpio_enable_interrupt(GPIO_HDMI_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Check that port number is valid. */ + if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) + return; + usbc_overcurrent = is_overcurrented; + update_5v_usage(); +} +/* + * Power monitoring and management. + * + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * The overall goal is to gracefully manage the power demand so that + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 rear port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 3 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A_REAR BIT(0) +#define THROT_TYPE_C0 BIT(1) +#define THROT_TYPE_C1 BIT(2) +#define THROT_TYPE_C2 BIT(3) +#define THROT_PROCHOT BIT(4) + +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + static uint32_t history[POWER_READINGS]; + static uint8_t index; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v_s5 = PWR_S5_MAX - base_5v_power_s5; + int32_t headroom_5v_z1 = PWR_Z1_MAX - base_5v_power_z1; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + /* + * Clear the first entry of the power table so that + * it is re-initilalised when the CPU starts. + */ + history[0] = 0; + } else { + int32_t charger_mw; + + delay = POWER_DELAY_MS * MSEC; + /* + * Get current charger limit (in mw). + * If not configured yet, skip. + */ + charger_mw = charge_manager_get_power_limit_uw() / 1000; + if (charger_mw != 0) { + int32_t gap, total, max, power; + int i; + + /* + * Read power usage. + */ + power = (adc_read_channel(ADC_VBUS) * + adc_read_channel(ADC_PPVAR_IMON)) / + 1000; + /* Init power table */ + if (history[0] == 0) { + for (i = 0; i < POWER_READINGS; i++) + history[i] = power; + } + /* + * Update the power readings and + * calculate the average and max. + */ + history[index] = power; + index = (index + 1) % POWER_READINGS; + total = 0; + max = history[0]; + for (i = 0; i < POWER_READINGS; i++) { + total += history[i]; + if (history[i] > max) + max = history[i]; + } + /* + * For Type-C power supplies, there is + * less tolerance for exceeding the rating, + * so use the max power that has been measured + * over the measuring period. + * For barrel-jack supplies, the rating can be + * exceeded briefly, so use the average. + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + power = max; + else + power = total / POWER_READINGS; + /* + * Calculate gap, and if negative, power + * demand is exceeding configured power budget, so + * throttling is required to reduce the demand. + */ + gap = charger_mw - power; + /* + * Limiting type-A power rear ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_REAR; + headroom_5v_s5 += REAR_DELTA; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(0) && gap <= 0) { + new_state |= THROT_TYPE_C0; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C0)) + gap += POWER_GAIN_TYPE_C; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(1) && gap <= 0) { + new_state |= THROT_TYPE_C1; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C1)) + gap += POWER_GAIN_TYPE_C; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(2) && gap <= 0) { + new_state |= THROT_TYPE_C2; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C2)) + gap += POWER_GAIN_TYPE_C; + } + /* + * As a last resort, turn on PROCHOT to + * throttle the CPU. + */ + if (gap <= 0) + new_state |= THROT_PROCHOT; + } + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v_z1 < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C0) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + new_state |= THROT_TYPE_C0; + } + /* + * [2] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v_z1 < 0) + new_state |= THROT_TYPE_C0; + } + if (headroom_5v_s5 < 0) { + /* + * If type A rear not already throttled, and power still + * needed, limit type A rear. + */ + if (!(new_state & THROT_TYPE_A_REAR) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + new_state |= THROT_TYPE_A_REAR; + } + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_C0) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C0) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + } + if (diff & THROT_TYPE_C1) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C1) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(1, rp); + tcpm_select_rp_value(1, rp); + pd_update_contract(1); + } + if (diff & THROT_TYPE_C2) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C2) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(2, rp); + tcpm_select_rp_value(2, rp); + pd_update_contract(2); + } + if (diff & THROT_TYPE_A_REAR) { + int typea_bc = (new_state & THROT_TYPE_A_REAR) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR0_OD, typea_bc); + gpio_set_level(GPIO_USB_A_LOW_PWR1_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/constitution/board.h b/board/constitution/board.h new file mode 100644 index 0000000000..a8287f8579 --- /dev/null +++ b/board/constitution/board.h @@ -0,0 +1,199 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brask board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +#define CONFIG_MP2964 + +/* Barrel Jack */ +#define DEDICATED_CHARGE_PORT 3 + +/* HDMI CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMIB_CEC_OUT +#define CEC_GPIO_IN GPIO_HDMIB_CEC_IN +#define CEC_GPIO_PULL_UP GPIO_HDMIB_CEC_PULL_UP + +/* USB Type A Features */ +#define USB_PORT_COUNT 2 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USB_PD_PPC +#define CONFIG_USB_PD_TCPM_RT1715 +#define CONFIG_USBC_RETIMER_INTEL_BB + +#define CONFIG_USBC_PPC_SYV682X +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* The design should support up to 100W. */ +/* TODO(b/197702356): Set the max PD to 60W now and change it + * to 100W after we verify it. + */ +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_OD + +/* I2C Bus Configuration */ +#define I2C_PORT_USB_C0_C2_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_C2_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_C2_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_C2_MUX NPCX_I2C_PORT3_0 + +#define I2C_PORT_PSE NPCX_I2C_PORT5_0 +#define I2C_PORT_ADB NPCX_I2C_PORT6_1 + +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x59 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* ADC */ +#define CONFIG_ADC + +/* PSE */ +#define CONFIG_PSE_LTC4291 + +/* + * TODO(b/197478860): Enable the fan control. We need + * to check the sensor value and adjust the fan speed. + */ +#define CONFIG_FANS FAN_CH_COUNT + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_TYPEC1, + CHARGE_PORT_TYPEC2, + CHARGE_PORT_BARRELJACK, + CHARGE_PORT_ENUM_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1_CPU, + ADC_TEMP_SENSOR_2_CPU_VR, + ADC_TEMP_SENSOR_3_WIFI, + ADC_TEMP_SENSOR_4_DIMM, + ADC_VBUS, + ADC_PPVAR_IMON, /* ADC3 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_CPU, + TEMP_SENSOR_2_CPU_VR, + TEMP_SENSOR_3_WIFI, + TEMP_SENSOR_4_DIMM, + TEMP_SENSOR_COUNT +}; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C2_NCT38XX, IOEX_PORT_COUNT }; + +enum pwm_channel { + PWM_CH_LED_WHITE, /* PWM0 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED_RED, /* PWM2 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +extern void adp_connect_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/constitution/build.mk b/board/constitution/build.mk new file mode 100644 index 0000000000..2301983a1f --- /dev/null +++ b/board/constitution/build.mk @@ -0,0 +1,22 @@ +# -*- makefile -*- +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brask board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brask + +board-y= +board-y+=board.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/constitution/ec.tasklist b/board/constitution/ec.tasklist new file mode 100644 index 0000000000..2d063fe252 --- /dev/null +++ b/board/constitution/ec.tasklist @@ -0,0 +1,28 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P2, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C2, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(2) | BIT(0)), LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/constitution/fans.c b/board/constitution/fans.c new file mode 100644 index 0000000000..ecc93bd330 --- /dev/null +++ b/board/constitution/fans.c @@ -0,0 +1,50 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/197478860): need to update for real fan + * + * Prototype fan spins at about 7200 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2200, + .rpm_start = 2200, + .rpm_max = 7200, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/constitution/fw_config.c b/board/constitution/fw_config.c new file mode 100644 index 0000000000..957a5c8c50 --- /dev/null +++ b/board/constitution/fw_config.c @@ -0,0 +1,65 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union brask_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brask if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union brask_cbi_fw_config fw_config_defaults = { + .audio = DB_NAU88L25B_I2S, + .bj_power = BJ_135W, +}; + +/* + * Barrel-jack power adapter ratings. + */ +static const struct { + int voltage; + int current; +} bj_power[] = { + [BJ_135W] = { /* 0 - 135W (also default) */ + .voltage = 19500, + .current = 6920 + }, + [BJ_230W] = { /* 1 - 230W */ + .voltage = 19500, + .current = 11800 + } +}; + +/**************************************************************************** + * Brask FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +void ec_bj_power(uint32_t *voltage, uint32_t *current) +{ + unsigned int bj; + + bj = fw_config.bj_power; + /* Out of range value defaults to 0 */ + if (bj >= ARRAY_SIZE(bj_power)) + bj = 0; + *voltage = bj_power[bj].voltage; + *current = bj_power[bj].current; +} diff --git a/board/constitution/fw_config.h b/board/constitution/fw_config.h new file mode 100644 index 0000000000..c2afd4c603 --- /dev/null +++ b/board/constitution/fw_config.h @@ -0,0 +1,41 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_BRASK_FW_CONFIG_H_ +#define __BOARD_BRASK_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Brask board. + * + * Source of truth is the project/brask/brask/config.star configuration file. + */ +enum ec_cfg_audio_type { DB_AUDIO_UNKNOWN = 0, DB_NAU88L25B_I2S = 1 }; + +enum ec_cfg_bj_power { BJ_135W = 0, BJ_230W = 1 }; + +union brask_cbi_fw_config { + struct { + uint32_t audio : 3; + uint32_t bj_power : 2; + uint32_t reserved_1 : 27; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union brask_cbi_fw_config get_fw_config(void); + +/** + * Get the barrel-jack power from FW_CONFIG. + */ +void ec_bj_power(uint32_t *voltage, uint32_t *current); + +#endif /* __BOARD_BRASK_FW_CONFIG_H_ */ diff --git a/board/constitution/gpio.inc b/board/constitution/gpio.inc new file mode 100644 index 0000000000..fb2915a3a7 --- /dev/null +++ b/board/constitution/gpio.inc @@ -0,0 +1,182 @@ +/* -*- mode:c -*- + * + * Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTERRUPT GPIOs: */ + +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(A, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C2_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C2_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(2, 3), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(HDMI_CONN_OC_ODL, PIN(5, 0), GPIO_INPUT | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A0_OC_ODL, PIN(3, 1), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) + +/* PSE controller */ +GPIO(EC_PSE_PWM_INT, PIN(9, 6), GPIO_INPUT) +GPIO(EC_RST_LTC4291, PIN(9, 7), GPIO_OUT_HIGH) + +/* TPU */ +GPIO(PP3300_TPU_EN, PIN(2, 6), GPIO_OUT_HIGH) + +/* Wake EC */ +GPIO(WLAN_PCIE_WAKE_EC, PIN(4, 1), GPIO_INPUT) +GPIO(LAN_WAKE_EC, PIN(9, 3), GPIO_INPUT) + +/* ADB Scaler signals */ +GPIO(ADB_WAKEUP_EC, PIN(2, 5), GPIO_INPUT) + +/* CCD */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + +/* Security */ +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Fan */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) + +/* ADC, need to check the usage */ +GPIO(ANALOG_PPVAR_PWR_IN_IMON_EC, PIN(4, 2), GPIO_INPUT) + +/* BarrelJack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 4), GPIO_OUT_LOW) + +/* Chipset PCH */ +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) + +/* Button */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(GSC_EC_RECOVERY_BTN_OD, PIN(2, 2), GPIO_INPUT) + +/* HDMI CEC */ +/* TODO(b/197474873): Enable HDMI CEC */ +GPIO(HDMIA_CEC_IN, PIN(D, 3), GPIO_INPUT) +GPIO(HDMIA_CEC_OUT, PIN(1, 0), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMIA_CEC_PULL_UP, PIN(1, 1), GPIO_OUT_HIGH) +GPIO(HDMIB_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMIB_CEC_OUT, PIN(2, 7), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMIB_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH) + +/* I2C SCL/SDA */ +GPIO(EC_I2C_LTC_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_LTC_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_ADB_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_ADB_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PPC_SDA, PIN(F, 2), GPIO_INPUT) + +/* USBA */ +GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW) +GPIO(USB_A0_STATUS_L, PIN(2, 1), GPIO_INPUT) +GPIO(USB_A1_STATUS_L, PIN(2, 0), GPIO_INPUT) +GPIO(USB_A_LOW_PWR0_OD, PIN(1, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR1_OD, PIN(1, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH) + +/* LED */ +/* TODO(b/197471359): LED implementation */ +GPIO(LED_WHITE_L, PIN(C, 3), GPIO_OUT_LOW) +GPIO(LED_RED_L, PIN(C, 4), GPIO_OUT_LOW) + +/* USBC */ +GPIO(USB_C0_C2_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C2_RT_RST_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 3), GPIO_ODR_HIGH) +IOEX(USB_C2_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C2_FRS_EN, EXPIN(IOEX_C2_NCT38XX, 0, 6), GPIO_LOW) +/* GPIO07_P2 to PU */ + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, 0) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* Unused Pins */ +UNUSED(PIN(D, 4)) /* GPIOD4/CRSIN3 */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */ +UNUSED(PIN(1, 7)) /* KSO2/GPIO17/JTAG_TDI */ +UNUSED(PIN(1, 6)) /* KSO03/GPIO16/JTAG_TDO_SWO */ +UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */ +UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */ +UNUSED(PIN(0, 7)) /* KSO10/GPIO07/P80_CLK */ +UNUSED(PIN(0, 6)) /* KSO11/GPIO06/P80_DAT */ +UNUSED(PIN(0, 5)) /* KSO12/GPIO05 */ +UNUSED(PIN(A, 3)) /* SPIP_MOSI/GPIOA3 */ +UNUSED(PIN(9, 5)) /* SPIP_MISO/GPIO95 */ +UNUSED(PIN(D, 2)) /* PSL_IN1/GPIOD2 */ +UNUSED(PIN(0, 2)) /* GPIO02/PSL_IN4 */ \ No newline at end of file diff --git a/board/constitution/i2c.c b/board/constitution/i2c.c new file mode 100644 index 0000000000..f9ff3524a1 --- /dev/null +++ b/board/constitution/i2c.c @@ -0,0 +1,77 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,2", + .port = I2C_PORT_USB_C0_C2_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,2", + .port = I2C_PORT_USB_C0_C2_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,2", + .port = I2C_PORT_USB_C0_C2_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA, + }, + { + /* I2C4 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_PPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_PPC_SDA, + }, + { + /* I2C5 */ + .name = "pse", + .port = I2C_PORT_PSE, + .kbps = 400, + .scl = GPIO_EC_I2C_LTC_SCL, + .sda = GPIO_EC_I2C_LTC_SDA, + }, + { + /* I2C6 */ + .name = "ADB", + .port = I2C_PORT_ADB, + .kbps = 1000, + .scl = GPIO_EC_I2C_ADB_SCL, + .sda = GPIO_EC_I2C_ADB_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/constitution/led.c b/board/constitution/led.c new file mode 100644 index 0000000000..2d8c167a13 --- /dev/null +++ b/board/constitution/led.c @@ -0,0 +1,260 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Brask. + * Solid white - active power + * White flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_WHITE, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int white = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_WHITE: + white = 1; + break; + case LED_RED: + red = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (white) + pwm_set_duty(PWM_CH_LED_WHITE, duty); + else + pwm_set_duty(PWM_CH_LED_WHITE, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* + * When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_WHITE); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* + * Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_WHITE, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "white")) { + set_color(id, LED_WHITE, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|red|white|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_WHITE]) + return set_color(id, LED_WHITE, brightness[EC_LED_COLOR_WHITE]); + else + return set_color(id, LED_OFF, 0); +} +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Blink alert if insufficient power per system_can_boot_ap(). */ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + led_alert(insufficient_power); +} diff --git a/board/constitution/pwm.c b/board/constitution/pwm.c new file mode 100644 index 0000000000..6558587bf9 --- /dev/null +++ b/board/constitution/pwm.c @@ -0,0 +1,38 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_WHITE] = { .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 2, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * TODO(b/197478860): Turn on the fan at 100% by default + * We need to find tune the fan speed according to the + * thermal sensor value. + */ + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, 100); + + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_WHITE, 1); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/constitution/sensors.c b/board/constitution/sensors.c new file mode 100644 index 0000000000..211faace1c --- /dev/null +++ b/board/constitution/sensors.c @@ -0,0 +1,114 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_CPU] = { + .name = "TEMP_CPU", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CPU_VR] = { + .name = "TEMP_CPU_VR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_WIFI] = { + .name = "TEMP_WIFI", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DIMM] = { + .name = "TEMP_DIMM", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 872.3 mV/A */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT * 1433, + .factor_div = (ADC_READ_MAX + 1) * 1250, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_CPU] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_CPU }, + [TEMP_SENSOR_2_CPU_VR] = { .name = "CPU VR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CPU_VR }, + [TEMP_SENSOR_3_WIFI] = { .name = "WIFI", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_WIFI }, + [TEMP_SENSOR_4_DIMM] = { .name = "DIMM", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DIMM }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/197478860): add the thermal sensor setting + */ +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CPU] = THERMAL_CPU, + [TEMP_SENSOR_2_CPU_VR] = THERMAL_CPU, + [TEMP_SENSOR_3_WIFI] = THERMAL_CPU, + [TEMP_SENSOR_4_DIMM] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/constitution/usbc_config.c b/board/constitution/usbc_config.c new file mode 100644 index 0000000000..cc96a898b1 --- /dev/null +++ b/board/constitution/usbc_config.c @@ -0,0 +1,375 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR1_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C2_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C2] = { + .mux = &(const struct usb_mux){ + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_2_FLAGS, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C2_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = IOEX_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C2) { + rst_signal = IOEX_USB_C2_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +__override int bb_retimer_reset(const struct usb_mux *me) +{ + /* + * TODO(b/193402306, b/195375738): Remove this once transition to + * QS Silicon is complete + */ + bb_retimer_power_enable(me, false); + msleep(5); + bb_retimer_power_enable(me, true); + msleep(25); + + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + enum gpio_signal tcpc_rst; + + tcpc_rst = GPIO_USB_C0_C2_TCPC_RST_ODL; + + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(tcpc_rst, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(tcpc_rst, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void enable_ioex(int ioex) +{ + ioex_init(ioex); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C2 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + enable_ioex(IOEX_C0_NCT38XX); + enable_ioex(IOEX_C2_NCT38XX); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); + + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_2; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C2) + return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C2_BC12_INT_ODL: + usb_charger_task_set_event(2, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + case GPIO_USB_C2_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return true; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/constitution/usbc_config.h b/board/constitution/usbc_config.h new file mode 100644 index 0000000000..778ca51a0d --- /dev/null +++ b/board/constitution/usbc_config.h @@ -0,0 +1,20 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 3 + +enum usbc_port { + USBC_PORT_C0 = 0, + USBC_PORT_C1, + USBC_PORT_C2, + USBC_PORT_COUNT +}; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/constitution/vif_override.xml b/board/constitution/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/constitution/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/copano/battery.c b/board/copano/battery.c new file mode 100644 index 0000000000..85f3d67448 --- /dev/null +++ b/board/copano/battery.c @@ -0,0 +1,66 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all Volteer battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + [BATTERY_C433] = { + .fuel_gauge = { + .manuf_name = "AS1GVPc3KB", + .device_name = "C433-41", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x10, 0x10 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x44, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C433; diff --git a/board/copano/board.c b/board/copano/board.c new file mode 100644 index 0000000000..7608b8cee7 --- /dev/null +++ b/board/copano/board.c @@ -0,0 +1,448 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board-specific configuration */ +#include "accelgyro.h" +#include "button.h" +#include "cbi_ec_fw_config.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/ppc/syv682x.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/sync.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "throttle_ap.h" +#include "uart.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config copano_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &copano_kb; +} + +/******************************************************************************/ +/* + * FW_CONFIG defaults for Terrador if the CBI data is not initialized. + */ +union volteer_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_PASSIVE, +}; + +static void board_init(void) +{ +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C0_SENSOR_SCL, + .sda = GPIO_EC_I2C0_SENSOR_SDA, + }, + { + .name = "usb_c0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C1_USB_C0_SCL, + .sda = GPIO_EC_I2C1_USB_C0_SDA, + }, + { + .name = "usb_c1", + .port = I2C_PORT_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C2_USB_C1_SCL, + .sda = GPIO_EC_I2C2_USB_C1_SDA, + }, + { + .name = "usb_0_mix", + .port = I2C_PORT_USB_0_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C3_USB_0_MIX_SCL, + .sda = GPIO_EC_I2C3_USB_0_MIX_SDA, + }, + { + .name = "usb_1_mix", + .port = I2C_PORT_USB_1_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C4_USB_1_MIX_SCL, + .sda = GPIO_EC_I2C4_USB_1_MIX_SDA, + }, + { + .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C5_POWER_SCL, + .sda = GPIO_EC_I2C5_POWER_SDA, + }, + { + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C7_EEPROM_SCL, + .sda = GPIO_EC_I2C7_EEPROM_SDA, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/******************************************************************************/ +/* PWM configuration */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 10000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/******************************************************************************/ +/* EC thermal management configuration */ + +/* + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +/******************************************************************************/ + +static void kb_backlight_enable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, kb_backlight_enable, HOOK_PRIO_DEFAULT); + +static void kb_backlight_disable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kb_backlight_disable, HOOK_PRIO_DEFAULT); + +void board_reset_pd_mcu(void) +{ + /* TODO(b/159025015): Terrador: check USB PD reset operation */ +} + +/* USBC mux configuration - Tiger Lake includes internal mux */ +struct usb_mux_chain usbc0_usb4_mb_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_0_MIX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, +}; +/***************************************************************************** + * USB-C MUX/Retimer dynamic configuration. + */ +static void setup_mux(void) +{ + CPRINTS("C0 supports bb-retimer"); + /* USB-C port 0 have a retimer */ + usb_muxes[USBC_PORT_C0].next = &usbc0_usb4_mb_retimer; +} + +__override void board_cbi_init(void) +{ + /* + * TODO(b/159025015): Terrador: check FW_CONFIG fields for USB DB type + */ + setup_mux(); + /* Reassign USB_C0_RT_RST_ODL */ + bb_controls[USBC_PORT_C0].usb_ls_en_gpio = GPIO_USB_C0_LS_EN; + bb_controls[USBC_PORT_C0].retimer_rst_gpio = GPIO_USB_C0_RT_RST_ODL; +} + +/******************************************************************************/ +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/******************************************************************************/ +/* PPC support routines */ +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +/******************************************************************************/ +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USBC mux configuration - Tiger Lake includes internal mux */ +struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_1_MIX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +struct bb_usb_control bb_controls[] = { + [USBC_PORT_C0] = { + /* USB-C port 0 doesn't have a retimer */ + }, + [USBC_PORT_C1] = { + .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, + .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +/******************************************************************************/ +/* TCPC support routines */ +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; +} + +/******************************************************************************/ +/* USB-A charging control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; diff --git a/board/copano/board.h b/board/copano/board.h new file mode 100644 index 0000000000..6efd3e88ee --- /dev/null +++ b/board/copano/board.h @@ -0,0 +1,182 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* + * The RAM and flash size combination on the NPCX797FC dose not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +#define CONFIG_VBOOT_EFS2 + +#define CONFIG_POWER_BUTTON + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Chipset features */ +#define CONFIG_POWER_PP5000_CONTROL + +#undef NPCX_PWM1_SEL +#define NPCX_PWM1_SEL 0 /* GPIO C2 is not used as PWM1 */ + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* Keyboard features */ +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* Sensors */ +/* BMA253 accelerometer in base */ +#define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCEL_KX022 + +/* BMI160 accel/gyro in base */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ + +/* + * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C + * cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 15000 + +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x40 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USBC PPC*/ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C0/C1 */ +#define CONFIG_USB_PD_FRS_PPC + +#undef CONFIG_USB_PD_TCPC_RUNTIME_CONFIG +#undef CONFIG_USB_PD_TCPM_TUSB422 + +/* BC 1.2 */ + +/* Volume Button feature */ + +/* Fan features */ +#undef CONFIG_FANS + +/* charger defines */ +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_0_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT4_1 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM + +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum battery_type { + BATTERY_C433, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_COUNT }; + +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void board_reset_pd_mcu(void); +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/copano/build.mk b/board/copano/build.mk new file mode 100644 index 0000000000..c994631759 --- /dev/null +++ b/board/copano/build.mk @@ -0,0 +1,17 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=volteer + +board-y=board.o +board-y+=battery.o +board-y+=led.o +board-y+=sensors.o diff --git a/board/copano/ec.tasklist b/board/copano/ec.tasklist new file mode 100644 index 0000000000..c29125d517 --- /dev/null +++ b/board/copano/ec.tasklist @@ -0,0 +1,27 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/copano/gpio.inc b/board/copano/gpio.inc new file mode 100644 index 0000000000..c6271c20f4 --- /dev/null +++ b/board/copano/gpio.inc @@ -0,0 +1,176 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(EC_LID_OPEN, PIN(9, 5), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) + +/* Sensor Interrupts */ +GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(D, 2), GPIO_INT_BOTH, gmr_tablet_switch_isr) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) + +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) + +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) +GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) + +/* HDMI interrupts */ + +/* Volume button interrupts */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) + +/* Power Sequencing Signals */ +GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ +GPIO(EC_PCH_DSW_PWROK, PIN(C, 0), GPIO_OUT_LOW) + +/* Other wake sources */ +/* + * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an + * interrupt handler because it is automatically handled by the PSL. + * + * We need to lock the setting so this gpio can't be reconfigured to overdrive + * the real reset signal. (This is the PSL input pin not the real reset pin). + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | + GPIO_HIB_WAKE_HIGH | + GPIO_LOCKED) + +/* AP/PCH Signals */ +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) + +/* USB and USBC Signals */ +GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ +GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ + +/* + * USB_C1 moved from GPIO32 to GPIO83 on boards with board ID >=1. + * GPIO83/EN_PP1800_A is DNS on board ID 0 and GPIO32 is N/C on board ID >=1 + * so it's safe to define GPIOs compatible with both designs. + * TODO (b/149858568): remove board ID=0 support. + */ +GPIO(USB_C0_RT_RST_ODL, PIN(6, 1), GPIO_ODR_LOW) /* USB_C0 Reset */ +GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset */ +GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) +/* There is currently no need to service this interrupt. */ +GPIO(USB_C0_RT_INT_ODL, PIN(B, 7), GPIO_INPUT) +GPIO(USB_C1_RT_INT_ODL, PIN(4, 0), GPIO_INPUT) +GPIO(USB_C0_FRS_EN, PIN(6, 0), GPIO_OUT_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) + +/* Don't have a load switch for retimer */ +UNIMPLEMENTED(USB_C0_LS_EN) +UNIMPLEMENTED(USB_C1_LS_EN) + +/* Misc Signals */ +GPIO(EC_H1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) /* H1 Packet Mode */ +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) /* Keyboard backlight enable*/ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(M2_SSD_PLA, PIN(7, 0), GPIO_INPUT) /* SSD power-loss acknowledgment */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_ODR_HIGH) /* SSD power-loss notification */ + + +/* LED */ +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) /* Battery Full LED / Power LED: White */ +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) /* Battery Charging LED: Amber */ + +/* + * eDP backlight - both PCH and EC have enable pins that must be high + * for the backlight to turn on. Default state is high, and can be turned + * off during sleep states. + */ +GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C3_USB_0_MIX_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C3_USB_0_MIX_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C4_USB_1_MIX_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C4_USB_1_MIX_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_I2C5_POWER_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C5_POWER_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) + +/* Battery signals */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */ +ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ +ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(F, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ + +/* Keyboard pins */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ + +/* UART */ +ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Power Switch Logic (PSL) inputs */ +ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ +ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, + GPIO01 = H1_EC_PWR_BTN_ODL + GPIO02 = EC_RST_ODL */ + +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ + +/* Unused signals */ +GPIO(UNUSED_GPIOD4, PIN(D, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOC2, PIN(C, 2), GPIO_INPUT | GPIO_PULL_UP) + diff --git a/board/copano/led.c b/board/copano/led.c new file mode 100644 index 0000000000..15daf7b2b9 --- /dev/null +++ b/board/copano/led.c @@ -0,0 +1,101 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/copano/sensors.c b/board/copano/sensors.c new file mode 100644 index 0000000000..5a37f7ab8b --- /dev/null +++ b/board/copano/sensors.c @@ -0,0 +1,226 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific sensor configuration */ +#include "accelgyro.h" +#include "cbi_ec_fw_config.h" +#include "cbi_ssfc.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/sync.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "tablet_mode.h" +#include "task.h" +#include "util.h" + +/******************************************************************************/ +/* Sensors */ +static struct mutex g_lid_accel_mutex; +static struct mutex g_base_mutex; + +/* sensor private data */ +static struct accelgyro_saved_data_t g_bma253_data; +static struct kionix_accel_data g_kx022_data; + +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; + +/* Rotation matrix for the lid accelerometer */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t base_standard_ref_icm = { + { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void motion_interrupt(enum gpio_signal signal) +{ + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) + icm426xx_interrupt(signal); + else + bmi160_interrupt(signal); +} + +static void baseboard_sensors_init(void) +{ + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LID_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + ccprints("LID_ACCEL is KX022"); + } else + ccprints("LID_ACCEL is BMA253"); + + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE ACCEL is ICM426XX"); + } else + ccprints("BASE ACCEL IS BMI160"); + + /* Enable interrupt for the accel/gyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); diff --git a/board/copano/vif_override.xml b/board/copano/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/copano/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/coral/battery.c b/board/coral/battery.c index ebc8071c0d..3b105c90ca 100644 --- a/board/coral/battery.c +++ b/board/coral/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -19,7 +19,7 @@ #include "i2c.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) /* Number of writes needed to invoke battery cutoff command */ #define SHIP_MODE_WRITES 2 @@ -412,7 +412,8 @@ BUILD_ASSERT(ARRAY_SIZE(info) == BATTERY_TYPE_COUNT); static inline const struct board_batt_params *board_get_batt_params(void) { return &info[board_battery_type == BATTERY_TYPE_COUNT ? - DEFAULT_BATTERY_TYPE : board_battery_type]; + DEFAULT_BATTERY_TYPE : + board_battery_type]; } /* Get type of the battery connected on the board */ @@ -424,14 +425,16 @@ static int board_get_battery_type(void) if (!battery_manufacturer_name(manu_name, sizeof(manu_name))) { for (i = 0; i < BATTERY_TYPE_COUNT; i++) { if (!strcasecmp(manu_name, - info[i].fuel_gauge.manuf_name)) { + info[i].fuel_gauge.manuf_name)) { if (info[i].fuel_gauge.device_name == NULL) { board_battery_type = i; break; - } else if (!battery_device_name(device_name, - sizeof(device_name))) { + } else if (!battery_device_name( + device_name, + sizeof(device_name))) { if (!strcasecmp(device_name, - info[i].fuel_gauge.device_name)) { + info[i].fuel_gauge + .device_name)) { board_battery_type = i; break; } @@ -496,7 +499,7 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) /* Do not discharge on AC if the battery is still waking up */ if (!(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - !(curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.status & STATUS_FULLY_CHARGED)) return 0; /* @@ -513,8 +516,8 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) * and suspend USB charging and DC/DC converter. */ if (!battery_is_cut_off() && - !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - (curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) return 1; /* @@ -548,13 +551,13 @@ enum battery_present battery_hw_present(void) return gpio_get_level(GPIO_EC_BATT_PRES_L) ? BP_NO : BP_YES; } - static int battery_init(void) { int batt_status; - return battery_status(&batt_status) ? 0 : - !!(batt_status & STATUS_INITIALIZED); + return battery_status(&batt_status) ? + 0 : + !!(batt_status & STATUS_INITIALIZED); } /* Allow booting now that the battery has woke up */ @@ -595,12 +598,13 @@ static int battery_check_disconnect(void) /* Read the status of charge/discharge FETs */ if (info[board_battery_type].fuel_gauge.fet.mfgacc_support == 1) { rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); + SB_ALT_MANUFACTURER_ACCESS, data, + sizeof(data)); /* Get the lowest 16bits of the OperationStatus() data */ reg = data[2] | data[3] << 8; } else rv = sb_read(info[board_battery_type].fuel_gauge.fet.reg_addr, - ®); + ®); if (rv) return BATTERY_DISCONNECT_ERROR; @@ -650,7 +654,7 @@ enum battery_present battery_is_present(void) * error due to a failed sb_read. */ battery_report_present_timer_started = 0; - } else if (batt_pres == BP_YES && batt_pres_prev == BP_NO && + } else if (batt_pres == BP_YES && batt_pres_prev == BP_NO && !battery_report_present_timer_started) { /* * Wait 1/2 second before reporting present if it was @@ -674,11 +678,10 @@ int board_battery_initialized(void) return battery_hw_present() == batt_pres_prev; } - /* Customs options controllable by host command. */ #define PARAM_FASTCHARGE (CS_PARAM_CUSTOM_PROFILE_MIN + 0) -#define PARAM_LEARN_MODE 0x10001 -#define PARAM_DISCONNECT_STATE 0x10002 +#define PARAM_LEARN_MODE 0x10001 +#define PARAM_DISCONNECT_STATE 0x10002 enum ec_status charger_profile_override_get_param(uint32_t param, uint32_t *value) @@ -686,10 +689,10 @@ enum ec_status charger_profile_override_get_param(uint32_t param, switch (param) { case PARAM_LEARN_MODE: *value = disch_on_ac; - return EC_SUCCESS; + return EC_RES_SUCCESS; case PARAM_DISCONNECT_STATE: *value = battery_check_disconnect(); - return EC_SUCCESS; + return EC_RES_SUCCESS; default: return EC_RES_INVALID_PARAM; } diff --git a/board/coral/board.c b/board/coral/board.c index 829b057d77..2e42bbc0e0 100644 --- a/board/coral/board.c +++ b/board/coral/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Coral board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_manager.h" #include "charge_ramp.h" @@ -14,10 +13,10 @@ #include "charger.h" #include "chipset.h" #include "console.h" -#include "driver/als_opt3001.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/als_opt3001.h" #include "driver/charger/bd9995x.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" @@ -32,8 +31,9 @@ #include "lid_angle.h" #include "lid_switch.h" #include "math_util.h" -#include "motion_sense.h" #include "motion_lid.h" +#include "motion_sense.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -45,7 +45,7 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "timer.h" #include "uart.h" #include "usb_charge.h" @@ -54,15 +54,15 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define IN_ALL_SYS_PG POWER_SIGNAL_MASK(X86_ALL_SYS_PG) -#define IN_PGOOD_PP3300 POWER_SIGNAL_MASK(X86_PGOOD_PP3300) -#define IN_PGOOD_PP5000 POWER_SIGNAL_MASK(X86_PGOOD_PP5000) +#define IN_ALL_SYS_PG POWER_SIGNAL_MASK(X86_ALL_SYS_PG) +#define IN_PGOOD_PP3300 POWER_SIGNAL_MASK(X86_PGOOD_PP3300) +#define IN_PGOOD_PP5000 POWER_SIGNAL_MASK(X86_PGOOD_PP5000) -#define USB_PD_PORT_ANX74XX 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX74XX 0 +#define USB_PD_PORT_PS8751 1 static int sku_id; @@ -100,7 +100,7 @@ static void anx74xx_cable_det_handler(void) * and if in normal mode, then there is no need to trigger a tcpc reset. */ if (cable_det && !reset_n) - task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); + task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET); } DECLARE_DEFERRED(anx74xx_cable_det_handler); @@ -119,52 +119,62 @@ void anx74xx_cable_det_interrupt(enum gpio_signal signal) static void enable_input_devices(void); DECLARE_DEFERRED(enable_input_devices); -#define LID_DEBOUNCE_US (30 * MSEC) /* Debounce time for lid switch */ void tablet_mode_interrupt(enum gpio_signal signal) { hook_call_deferred(&enable_input_devices_data, LID_DEBOUNCE_US); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* ADC channels */ const struct adc_t adc_channels[] = { /* Vfs = Vref = 2.816V, 10-bit unsigned reading */ - [ADC_TEMP_SENSOR_CHARGER] = { - "CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, - [ADC_TEMP_SENSOR_AMB] = { - "AMBIENT", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, - [ADC_BOARD_ID] = { - "BRD_ID", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, - [ADC_BOARD_SKU_1] = { - "BRD_SKU_1", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, - [ADC_BOARD_SKU_0] = { - "BRD_SKU_0", NPCX_ADC_CH4, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, + [ADC_TEMP_SENSOR_CHARGER] = { "CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_AMB] = { "AMBIENT", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_BOARD_ID] = { "BRD_ID", NPCX_ADC_CH2, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_BOARD_SKU_1] = { "BRD_SKU_1", NPCX_ADC_CH3, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_BOARD_SKU_0] = { "BRD_SKU_0", NPCX_ADC_CH4, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { 4, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_KBLIGHT] = { 4, PWM_CONFIG_DSLEEP, 100 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -const struct i2c_port_t i2c_ports[] = { - {"tcpc0", NPCX_I2C_PORT0_0, 400, - GPIO_EC_I2C_USB_C0_PD_SCL, GPIO_EC_I2C_USB_C0_PD_SDA}, - {"tcpc1", NPCX_I2C_PORT0_1, 400, - GPIO_EC_I2C_USB_C1_PD_SCL, GPIO_EC_I2C_USB_C1_PD_SDA}, - {"accelgyro", I2C_PORT_GYRO, 400, - GPIO_EC_I2C_GYRO_SCL, GPIO_EC_I2C_GYRO_SDA}, - {"sensors", NPCX_I2C_PORT2, 400, - GPIO_EC_I2C_SENSOR_SCL, GPIO_EC_I2C_SENSOR_SDA}, - {"batt", NPCX_I2C_PORT3, 100, - GPIO_EC_I2C_POWER_SCL, GPIO_EC_I2C_POWER_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "tcpc0", + .port = NPCX_I2C_PORT0_0, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = NPCX_I2C_PORT0_1, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "accelgyro", + .port = I2C_PORT_GYRO, + .kbps = 400, + .scl = GPIO_EC_I2C_GYRO_SCL, + .sda = GPIO_EC_I2C_GYRO_SDA }, + { .name = "sensors", + .port = NPCX_I2C_PORT2, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, + { .name = "batt", + .port = NPCX_I2C_PORT3, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -183,7 +193,7 @@ struct i2c_stress_test i2c_stress_tests[] = { #ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC { .port = NPCX_I2C_PORT0_1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, .i2c_test = &ps8xxx_i2c_stress_test_dev, }, #endif @@ -234,7 +244,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = NPCX_I2C_PORT0_1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -280,17 +290,21 @@ static int ps8751_tune_mux(const struct usb_mux *me) return EC_SUCCESS; } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_ANX74XX] = { - .usb_port = USB_PD_PORT_ANX74XX, - .driver = &anx74xx_tcpm_usb_mux_driver, - .hpd_update = &anx74xx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_ANX74XX, + .driver = &anx74xx_tcpm_usb_mux_driver, + .hpd_update = &anx74xx_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_PS8751] = { - .usb_port = USB_PD_PORT_PS8751, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .board_init = &ps8751_tune_mux, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_PS8751, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .board_init = &ps8751_tune_mux, + }, } }; @@ -396,27 +410,28 @@ static void board_tcpc_init(void) gpio_enable_interrupt(GPIO_USB_C0_CABLE_DET); #endif /* - * Initialize HPD to low; after sysjump SOC needs to see - * HPD pulse to enable video path - */ + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_DEFAULT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -456,7 +471,7 @@ static void board_set_tablet_mode(void) if (SKU_IS_CONVERTIBLE(sku_id)) tablet_mode = !gpio_get_level(GPIO_TABLET_MODE_L); - tablet_set_mode(tablet_mode); + tablet_set_mode(tablet_mode, TABLET_TRIGGER_LID); } /* Initialize board. */ @@ -540,8 +555,8 @@ int board_set_active_charge_port(int charge_port) * @param charge_ma Desired charge limit (mA). * @param charge_mv Negotiated charge voltage (mV). */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* Enable charging trigger by BC1.2 detection */ int bc12_enable = (supplier == CHARGE_SUPPLIER_BC12_CDP || @@ -552,9 +567,7 @@ void board_set_charge_limit(int port, int supplier, int charge_ma, if (bd9995x_bc12_enable_charging(port, bc12_enable)) return; - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } /** @@ -585,8 +598,7 @@ static void enable_input_devices(void) } /* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* If the lid is in 360 position, ignore the lid angle, * which might be faulty. Disable keyboard. @@ -595,7 +607,6 @@ void lid_angle_peripheral_enable(int enable) enable = 0; keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif /* Called on AP S5 -> S3 transition */ static void board_chipset_startup(void) @@ -666,17 +677,17 @@ void board_hibernate_late(void) int i; const uint32_t hibernate_pins[][2] = { /* Turn off LEDs in hibernate */ - {GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN}, + { GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN }, /* * BD99956 handles charge input automatically. We'll disable * charge output in hibernate. Charger will assert ACOK_OD * when VBUS or VCC are plugged in. */ - {GPIO_USB_C0_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, - {GPIO_USB_C1_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, + { GPIO_USB_C0_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN }, + { GPIO_USB_C1_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN }, }; /* Change GPIOs' state in hibernate for better power consumption */ @@ -703,17 +714,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -const mat33_fp_t mag_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t mag_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; @@ -823,8 +830,8 @@ static void board_set_motion_sensor_count(uint8_t sku_id) * sensor. If a new SKU id is used that is not in the table, then the * number of motion sensors will remain as ARRAY_SIZE(motion_sensors). */ - motion_sensor_count = SKU_IS_CONVERTIBLE(sku_id) ? - ARRAY_SIZE(motion_sensors) : 0; + motion_sensor_count = + SKU_IS_CONVERTIBLE(sku_id) ? ARRAY_SIZE(motion_sensors) : 0; CPRINTS("Motion Sensor Count = %d", motion_sensor_count); } @@ -835,11 +842,11 @@ struct { } const coral_board_versions[] = { /* Vin = 3.3V, Ideal voltage, R2 values listed below */ /* R1 = 51.1 kOhm */ - { BOARD_VERSION_1, 200 }, /* 124 mV, 2.0 Kohm */ - { BOARD_VERSION_2, 366 }, /* 278 mV, 4.7 Kohm */ - { BOARD_VERSION_3, 550 }, /* 456 mV, 8.2 Kohm */ - { BOARD_VERSION_4, 752 }, /* 644 mV, 12.4 Kohm */ - { BOARD_VERSION_5, 927}, /* 860 mV, 18.0 Kohm */ + { BOARD_VERSION_1, 200 }, /* 124 mV, 2.0 Kohm */ + { BOARD_VERSION_2, 366 }, /* 278 mV, 4.7 Kohm */ + { BOARD_VERSION_3, 550 }, /* 456 mV, 8.2 Kohm */ + { BOARD_VERSION_4, 752 }, /* 644 mV, 12.4 Kohm */ + { BOARD_VERSION_5, 927 }, /* 860 mV, 18.0 Kohm */ { BOARD_VERSION_6, 1073 }, /* 993 mV, 22.0 Kohm */ { BOARD_VERSION_7, 1235 }, /* 1152 mV, 27.4 Kohm */ { BOARD_VERSION_8, 1386 }, /* 1318 mV, 34.0 Kohm */ @@ -892,7 +899,7 @@ int board_get_version(void) return version; } -static void board_get_sku_id(void) +static void sku_id_init(void) { int sku_id_lower; int sku_id_higher; @@ -911,12 +918,12 @@ static void board_get_sku_id(void) CPRINTS("Disable tablet mode interrupt"); gpio_disable_interrupt(GPIO_TABLET_MODE_L); /* Enfore device in laptop mode */ - tablet_set_mode(0); + tablet_set_mode(0, TABLET_TRIGGER_LID); } } } /* This can't run until after the ADC module has been initialized */ -DECLARE_HOOK(HOOK_INIT, board_get_sku_id, HOOK_PRIO_INIT_ADC + 1); +DECLARE_HOOK(HOOK_INIT, sku_id_init, HOOK_PRIO_INIT_ADC + 1); static void print_form_factor_list(int low, int high) { @@ -926,15 +933,15 @@ static void print_form_factor_list(int low, int high) if (high > 255) high = 255; for (id = low; id <= high; id++) { - ccprintf("SKU ID %03d: %s\n", id, SKU_IS_CONVERTIBLE(id) ? - "Convertible" : "Clamshell"); + ccprintf("SKU ID %03d: %s\n", id, + SKU_IS_CONVERTIBLE(id) ? "Convertible" : "Clamshell"); /* Don't print too many lines at once */ if (!(++count % 5)) msleep(20); } } -static int command_sku(int argc, char **argv) +static int command_sku(int argc, const char **argv) { enum adc_channel chan; @@ -977,20 +984,19 @@ static int command_sku(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(sku, command_sku, - "", +DECLARE_CONSOLE_COMMAND(sku, command_sku, "", "Get board id, sku, form factor"); -uint32_t system_get_sku_id(void) +__override uint32_t board_get_sku_id(void) { if (sku_id == BOARD_VERSION_UNKNOWN) - board_get_sku_id(); + sku_id_init(); return (uint32_t)sku_id; } /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * F3 key scan cycle completed but scan input is not * charging to logic high when EC start scan next diff --git a/board/coral/board.h b/board/coral/board.h index 85ddd8e5c2..f5cc6bb706 100644 --- a/board/coral/board.h +++ b/board/coral/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,24 +12,27 @@ * By default, enable all console messages except Events: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_EVENTS)) +#define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_EVENTS)) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD /* EC console commands */ #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_CMD_BATT_MFG_ACCESS #define CONFIG_CMD_CHARGER_ADC_AMON_BMON -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define BD9995X_IOUT_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V + BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V #define CONFIG_CHARGER_PSYS_READ #define BD9995X_PSYS_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW + BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW #define CONFIG_CMD_I2C_STRESS_TEST #define CONFIG_CMD_I2C_STRESS_TEST_ACCEL @@ -43,10 +46,11 @@ #define CONFIG_PORT80_HISTORY_LEN 256 /* Battery */ -#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_HW_PRESENT_CUSTOM -#define CONFIG_BATTERY_LEVEL_NEAR_FULL 94 +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 94 #define CONFIG_BATTERY_PRESENT_CUSTOM #define CONFIG_BATTERY_SMART @@ -58,8 +62,10 @@ #define CONFIG_CHARGER_BD9995X #define CONFIG_CHARGER_BD9995X_CHGEN #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_MAINTAIN_VBAT +#undef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 #define CONFIG_USB_CHARGER #define CONFIG_CHARGER_PROFILE_OVERRIDE @@ -88,7 +94,7 @@ #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PD_VBUS_DETECT_CHARGER #define CONFIG_USB_PD_TCPC_LOW_POWER -#define CONFIG_USB_PD_TCPM_MUX /* for both PS8751 and ANX3429 */ +#define CONFIG_USB_PD_TCPM_MUX /* for both PS8751 and ANX3429 */ #define CONFIG_USB_PD_TCPM_ANX3429 #define CONFIG_USB_PD_TCPM_PS8751 #define CONFIG_USB_PD_TCPM_TCPCI @@ -103,7 +109,7 @@ #define CONFIG_USBC_VCONN_SWAP /* SoC / PCH */ -#define CONFIG_HOSTCMD_LPC +#define CONFIG_HOST_INTERFACE_LPC #define CONFIG_CHIPSET_APOLLOLAKE #define CONFIG_CHIPSET_RESET_HOOK #define CONFIG_POWER_BUTTON @@ -114,17 +120,16 @@ /* EC */ #define CONFIG_ADC -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS -#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_FPU /* Region sizes are not a power of 2 so we can't use MPU */ -#undef CONFIG_MPU +#undef CONFIG_MPU #define CONFIG_HOSTCMD_FLASH_SPI_INFO #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_I2C_CONTROLLER + #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2 @@ -149,7 +154,7 @@ #define CONFIG_WIRELESS #define CONFIG_WIRELESS_SUSPEND EC_WIRELESS_SWITCH_WLAN_POWER #define CONFIG_WLAN_POWER_ACTIVE_LOW -#define WIRELESS_GPIO_WLAN_POWER GPIO_WIRELESS_GPIO_WLAN_POWER +#define WIRELESS_GPIO_WLAN_POWER GPIO_WIRELESS_GPIO_WLAN_POWER #define CONFIG_PWR_STATE_DISCHARGE_FULL /* @@ -165,9 +170,9 @@ #undef CONFIG_MOTION_SENSE_SUSPEND_DELAY_US #define CONFIG_MOTION_SENSE_SUSPEND_DELAY_US (MSEC * 60) -#define CONFIG_FLASH_SIZE 524288 +#define CONFIG_FLASH_SIZE_BYTES 524288 #define CONFIG_SPI_FLASH_REGS -#define CONFIG_SPI_FLASH_W25Q40 /* FIXME: Should be GD25LQ40? */ +#define CONFIG_SPI_FLASH_W25Q40 /* FIXME: Should be GD25LQ40? */ /* * Enable 1 slot of secure temporary storage to support @@ -177,25 +182,24 @@ #define CONFIG_VSTORE_SLOT_COUNT 1 /* Optional feature - used by nuvoton */ -#define NPCX_UART_MODULE2 1 /* 0:GPIO10/11 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ +#define NPCX_UART_MODULE2 1 /* 0:GPIO10/11 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ /* FIXME(dhendrix): these pins are just normal GPIOs on Coral. Do we need * to change some other setting to put them in GPIO mode? */ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ /* I2C ports */ -#define I2C_PORT_GYRO NPCX_I2C_PORT1 -#define I2C_PORT_LID_ACCEL NPCX_I2C_PORT2 -#define I2C_PORT_BATTERY NPCX_I2C_PORT3 -#define I2C_PORT_CHARGER NPCX_I2C_PORT3 +#define I2C_PORT_GYRO NPCX_I2C_PORT1 +#define I2C_PORT_LID_ACCEL NPCX_I2C_PORT2 +#define I2C_PORT_BATTERY NPCX_I2C_PORT3 +#define I2C_PORT_CHARGER NPCX_I2C_PORT3 /* Accelerometer and Gyroscope are the same device. */ -#define I2C_PORT_ACCEL I2C_PORT_GYRO +#define I2C_PORT_ACCEL I2C_PORT_GYRO /* Sensors */ #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_HOST_EVENT #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_MAG_CALIBRATE @@ -213,7 +217,6 @@ /* Depends on how fast the AP boots and typical ODRs */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) - #ifndef __ASSEMBLER__ #include "gpio_signal.h" @@ -221,11 +224,11 @@ /* ADC signal */ enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, /* ADC0 */ - ADC_TEMP_SENSOR_AMB, /* ADC1 */ - ADC_BOARD_ID, /* ADC2 */ - ADC_BOARD_SKU_1, /* ADC3 */ - ADC_BOARD_SKU_0, /* ADC4 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC0 */ + ADC_TEMP_SENSOR_AMB, /* ADC1 */ + ADC_BOARD_ID, /* ADC2 */ + ADC_BOARD_SKU_1, /* ADC3 */ + ADC_BOARD_SKU_0, /* ADC4 */ ADC_CH_COUNT }; @@ -283,17 +286,16 @@ enum coral_board_version { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Reset PD MCU */ void board_reset_pd_mcu(void); diff --git a/board/coral/build.mk b/board/coral/build.mk index 728d027803..470e439b13 100644 --- a/board/coral/build.mk +++ b/board/coral/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/coral/ec.tasklist b/board/coral/ec.tasklist index eeebc0cc59..bc8668a1db 100644 --- a/board/coral/ec.tasklist +++ b/board/coral/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/coral/gpio.inc b/board/coral/gpio.inc index 43a130a140..7f09fe0735 100644 --- a/board/coral/gpio.inc +++ b/board/coral/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -62,7 +62,7 @@ GPIO(EC_I2C_POWER_SCL, PIN(D, 1), GPIO_INPUT) * Pin 57 (SER_IRQ) defaults to LPC mode, but we also have EC_PCH_KB_INT_ODL * (Pin B0) in case it doesn't work (Set CONFIG_KEYBOARD_IRQ_GPIO in this case). * - * See also the NO_LPC_ESPI bit in DEVALT1 and the CONFIG_HOSTCMD_SPS option. + * See also the NO_LPC_ESPI bit in DEVALT1 and the CONFIG_HOST_INTERFACE_SHI option. */ GPIO(PCH_SMI_L, PIN(A, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_SMI_ODL */ @@ -161,7 +161,7 @@ ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* GPIOB5-B4 for EC_I2C_USB_C0_PD ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* GPOPB3-B2 for EC_I2C_USB_C1_PD_SDA/SCL */ ALTERNATE(PIN_MASK(D, 0x03), 1, MODULE_I2C, 0) /* GPIOD1-D0 for EC_I2C_POWER_SDA/SCL */ -ALTERNATE(PIN(B, 6), 3, MODULE_PWM, 0) /* PWM KB Backlight */ +ALTERNATE(PIN_MASK(B, BIT(6)), 3, MODULE_PWM, 0) /* PWM KB Backlight */ /* FIXME: Make UART RX an interrupt? */ ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART from EC to Servo */ diff --git a/board/coral/led.c b/board/coral/led.c index 2a1e39946c..09d944b979 100644 --- a/board/coral/led.c +++ b/board/coral/led.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -28,8 +28,7 @@ #define LED_POWER_ON_TICKS (LED_POWER_BLINK_ON_MSEC / HOOK_TICK_INTERVAL_MS) #define LED_POWER_OFF_TICKS (LED_POWER_BLINK_OFF_MSEC / HOOK_TICK_INTERVAL_MS) -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -37,18 +36,14 @@ const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); #define GPIO_LED_COLOR_2 GPIO_BAT_LED_BLUE #define GPIO_LED_COLOR_3 GPIO_POW_LED -enum led_phase { - LED_PHASE_0, - LED_PHASE_1, - LED_NUM_PHASES -}; +enum led_phase { LED_PHASE_0, LED_PHASE_1, LED_NUM_PHASES }; enum led_color { LED_OFF, LED_COLOR_1, LED_COLOR_2, LED_COLOR_BOTH, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; enum led_states { @@ -85,37 +80,37 @@ struct led_info { /* COLOR_1 = Amber, COLOR_2 = Blue */ static const struct led_descriptor led_default_state_table[][LED_NUM_PHASES] = { - { {LED_COLOR_1, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_2, LED_INDEFINITE}, {LED_COLOR_1, LED_INDEFINITE} }, - { {LED_COLOR_2, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_2, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_1, 1 * LED_ONE_SEC }, {LED_OFF, 3 * LED_ONE_SEC} }, - { {LED_OFF, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_1, 1 * LED_ONE_SEC}, {LED_OFF, 1 * LED_ONE_SEC} }, - { {LED_COLOR_1, 2 * LED_ONE_SEC}, {LED_COLOR_2, 2 * LED_ONE_SEC} }, + { { LED_COLOR_1, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_2, LED_INDEFINITE }, { LED_COLOR_1, LED_INDEFINITE } }, + { { LED_COLOR_2, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_2, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_1, 1 * LED_ONE_SEC }, { LED_OFF, 3 * LED_ONE_SEC } }, + { { LED_OFF, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_1, 1 * LED_ONE_SEC }, { LED_OFF, 1 * LED_ONE_SEC } }, + { { LED_COLOR_1, 2 * LED_ONE_SEC }, { LED_COLOR_2, 2 * LED_ONE_SEC } }, }; /* COLOR_1 = Green, COLOR_2 = Red */ static const struct led_descriptor led_robo_state_table[][LED_NUM_PHASES] = { - { {LED_COLOR_2, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_BOTH, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_1, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_OFF, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_OFF, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_OFF, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_2, 1 * LED_ONE_SEC}, {LED_OFF, 1 * LED_ONE_SEC} }, - { {LED_COLOR_2, 2 * LED_ONE_SEC}, {LED_COLOR_1, 2 * LED_ONE_SEC} }, + { { LED_COLOR_2, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_BOTH, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_1, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_OFF, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_OFF, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_OFF, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_2, 1 * LED_ONE_SEC }, { LED_OFF, 1 * LED_ONE_SEC } }, + { { LED_COLOR_2, 2 * LED_ONE_SEC }, { LED_COLOR_1, 2 * LED_ONE_SEC } }, }; static const struct led_descriptor led_nasher_state_table[][LED_NUM_PHASES] = { - { {LED_COLOR_1, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_2, LED_INDEFINITE}, {LED_COLOR_1, LED_INDEFINITE} }, - { {LED_COLOR_2, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_2, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_2, 1 * LED_ONE_SEC}, {LED_OFF, 1 * LED_ONE_SEC} }, - { {LED_OFF, LED_INDEFINITE}, {LED_OFF, LED_INDEFINITE} }, - { {LED_COLOR_1, 1 * LED_ONE_SEC}, {LED_OFF, 1 * LED_ONE_SEC} }, - { {LED_COLOR_1, 2 * LED_ONE_SEC}, {LED_COLOR_2, 2 * LED_ONE_SEC} }, + { { LED_COLOR_1, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_2, LED_INDEFINITE }, { LED_COLOR_1, LED_INDEFINITE } }, + { { LED_COLOR_2, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_2, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_2, 1 * LED_ONE_SEC }, { LED_OFF, 1 * LED_ONE_SEC } }, + { { LED_OFF, LED_INDEFINITE }, { LED_OFF, LED_INDEFINITE } }, + { { LED_COLOR_1, 1 * LED_ONE_SEC }, { LED_OFF, 1 * LED_ONE_SEC } }, + { { LED_COLOR_1, 2 * LED_ONE_SEC }, { LED_COLOR_2, 2 * LED_ONE_SEC } }, }; static struct led_info led; @@ -176,24 +171,25 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) static enum led_states led_get_state(void) { - int charge_lvl; + int charge_lvl; enum led_states new_state = LED_NUM_STATES; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Get percent charge */ charge_lvl = charge_get_percent(); /* Determine which charge state to use */ new_state = charge_lvl <= led.charge_lvl_1 ? - STATE_CHARGING_LVL_1 : STATE_CHARGING_LVL_2; + STATE_CHARGING_LVL_1 : + STATE_CHARGING_LVL_2; break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { new_state = STATE_CHARGING_LVL_3; break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE /* and PWR_STATE_DISCHARGE_FULL */: + __fallthrough; + case LED_PWRS_DISCHARGE /* and LED_PWRS_DISCHARGE_FULL */: if (chipset_in_state(CHIPSET_STATE_ON)) new_state = STATE_DISCHARGE_S0; else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) @@ -201,17 +197,17 @@ static enum led_states led_get_state(void) else new_state = STATE_DISCHARGE_S5; break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: new_state = STATE_BATTERY_ERROR; break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: new_state = STATE_CHARGING_LVL_3; break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE) - new_state = STATE_FACTORY_TEST; - else - new_state = STATE_DISCHARGE_S0; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + new_state = STATE_DISCHARGE_S0; + break; + case LED_PWRS_FORCED_IDLE: + new_state = STATE_FACTORY_TEST; break; default: /* Other states don't alter LED behavior */ @@ -248,11 +244,13 @@ static void led_update_battery(void) int period; period = led.state_table[led.state][LED_PHASE_0].time + - led.state_table[led.state][LED_PHASE_1].time; + led.state_table[led.state][LED_PHASE_1].time; if (period) - phase = ticks % period < - led.state_table[led.state][LED_PHASE_0].time ? - 0 : 1; + phase = ticks % period < led.state_table[led.state] + [LED_PHASE_0] + .time ? + 0 : + 1; } /* Set the color for the given state and phase */ @@ -278,8 +276,8 @@ static void led_robo_update_power(void) * power LED is off for 600 msec, on for 3 seconds. */ period = LED_POWER_ON_TICKS + LED_POWER_OFF_TICKS; - level = ticks % period < LED_POWER_OFF_TICKS ? - LED_OFF_LVL : LED_ON_LVL; + level = ticks % period < LED_POWER_OFF_TICKS ? LED_OFF_LVL : + LED_ON_LVL; ticks++; } else { level = LED_OFF_LVL; diff --git a/board/coral/sku.h b/board/coral/sku.h index 4588932377..c12777a2f7 100644 --- a/board/coral/sku.h +++ b/board/coral/sku.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,7 +8,7 @@ #ifndef __CROS_EC_SKU_H #define __CROS_EC_SKU_H -#define SKU_CONVERTIBLE(id) (1 << ((id) & 0x7)) +#define SKU_CONVERTIBLE(id) (1 << ((id)&0x7)) /* * There are 256 possible SKUs for Coral. This table is used to map a given SKU @@ -22,7 +22,7 @@ static const uint8_t form_factor[32] = { SKU_CONVERTIBLE(4) | SKU_CONVERTIBLE(5), /* SKU 8 - 15 */ SKU_CONVERTIBLE(8) | SKU_CONVERTIBLE(9) | SKU_CONVERTIBLE(10) | - SKU_CONVERTIBLE(11), + SKU_CONVERTIBLE(11), /* SKU 16 - 23 */ 0x00, /* SKU 24 - 31 */ @@ -61,7 +61,7 @@ static const uint8_t form_factor[32] = { 0x00, /* SKU 160 - 167 */ SKU_CONVERTIBLE(163) | SKU_CONVERTIBLE(164) | SKU_CONVERTIBLE(165) | - SKU_CONVERTIBLE(166), + SKU_CONVERTIBLE(166), /* SKU 168 - 175 */ 0x00, /* SKU 176 - 183 */ @@ -86,6 +86,6 @@ static const uint8_t form_factor[32] = { 0x00, }; -#define SKU_IS_CONVERTIBLE(id) ((form_factor[(id) >> 3] >> ((id) & 0x7)) & 1) +#define SKU_IS_CONVERTIBLE(id) ((form_factor[(id) >> 3] >> ((id)&0x7)) & 1) #endif /* __CROS_EC_SKU_H */ diff --git a/board/coral/usb_pd_policy.c b/board/coral/usb_pd_policy.c index e071f6ae2a..ad6ac613e8 100644 --- a/board/coral/usb_pd_policy.c +++ b/board/coral/usb_pd_policy.c @@ -1,16 +1,16 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/charger/bd9995x.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -18,17 +18,17 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { @@ -39,7 +39,8 @@ static void board_vbus_update_source_current(int port) { enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? - (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP); + (GPIO_INPUT | GPIO_PULL_UP) : + (GPIO_OUTPUT | GPIO_PULL_UP); /* * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance diff --git a/board/coral/vif_override.xml b/board/coral/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/coral/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/corori/battery.c b/board/corori/battery.c new file mode 100644 index 0000000000..f4e126d42e --- /dev/null +++ b/board/corori/battery.c @@ -0,0 +1,71 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "common.h" +#include "gpio.h" +#include "util.h" + +/* + * Battery info for lalala battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* C21N2018 Battery Information + * TODO(b:196506846):Need to be verified on the Proto + */ + [BATTERY_C21N2018] = { + .fuel_gauge = { + .manuf_name = "AS3GXXD3KA", + .device_name = "C110160", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7890, + .voltage_min = 6000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C21N2018; diff --git a/board/corori/board.c b/board/corori/board.c new file mode 100644 index 0000000000..0717b73750 --- /dev/null +++ b/board/corori/board.c @@ -0,0 +1,466 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lalala board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/pi3usb3x532.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_8042.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "stdbool.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "temp_sensor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +#define ADC_VOL_UP_MASK BIT(0) +#define ADC_VOL_DOWN_MASK BIT(1) + +/******************************************************************************/ +/* USB-A Configuration */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, +}; + +static const struct ec_response_keybd_config corori_keybd = { + /* Default Chromeos keyboard config */ + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad, no screenlock key */ +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &corori_keybd; +} + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_b = THERMAL_B; + +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; + +static void setup_thermal(void) +{ + thermal_params[TEMP_SENSOR_1] = thermal_a; + thermal_params[TEMP_SENSOR_2] = thermal_b; +} + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +static void set_5v_gpio(int level) +{ + gpio_set_level(GPIO_EN_PP5000, level); + gpio_set_level(GPIO_EN_USB_A0_VBUS, level); +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC. + */ + set_5v_gpio(!!enable); +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + check_c0_line(); + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + /* Initialize THERMAL */ + setup_thermal(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; +const unsigned int chg_cnt = ARRAY_SIZE(chg_chips); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + }, +}; + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + return status; +} + +static void board_extpower(void) +{ + int extpower_present; + + if (pd_is_connected(0)) + extpower_present = extpower_is_present(); + else + extpower_present = 0; + + gpio_set_level(GPIO_EC_ACOK_OTG, extpower_present); +} +DECLARE_HOOK(HOOK_AC_CHANGE, board_extpower, HOOK_PRIO_DEFAULT); + +const struct i2c_port_t i2c_ports[] = { + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + + { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BATTERY_SCL, + .sda = GPIO_EC_I2C_BATTERY_SDA }, + +#ifdef HAS_TASK_MOTIONSENSE + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +#endif + + { .name = "usbc0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_SCL, + .sda = GPIO_EC_I2C_USB_C0_SDA }, +#if CONFIG_USB_PD_PORT_MAX_COUNT > 1 + { .name = "sub_usbc1", + .port = I2C_PORT_SUB_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C_SUB_USB_C1_SCL, + .sda = GPIO_EC_I2C_SUB_USB_C1_SDA }, +#endif +}; diff --git a/board/corori/board.h b/board/corori/board.h new file mode 100644 index 0000000000..5db8be64cc --- /dev/null +++ b/board/corori/board.h @@ -0,0 +1,114 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lalala board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KEEBY_EC_NPCX797FC +#include "baseboard.h" + +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#undef CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 + +/* LED defines */ +#define CONFIG_LED_COMMON +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 94 +#define GPIO_BAT_LED_AMBER GPIO_LED_Y_ODL +#define GPIO_PWR_LED_WHITE GPIO_LED_W_ODL + +/* PWM */ +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ + +/* Temp sensor */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Common USB-A defines */ +#define USB_PORT_COUNT 1 + +/******************************************************************************/ + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +/* TODO(b:147440290): Need to handle multiple charger ICs */ +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ + +/* Volume Button feature */ +#define CONFIG_VOLUME_BUTTONS +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; + +enum battery_type { + BATTERY_C21N2018, + BATTERY_TYPE_COUNT, +}; + +int board_is_sourcing_vbus(int port); +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/corori/build.mk b/board/corori/build.mk new file mode 100644 index 0000000000..eb422dae93 --- /dev/null +++ b/board/corori/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=keeby + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/corori/cbi_ssfc.c b/board/corori/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/corori/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/corori/cbi_ssfc.h b/board/corori/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/corori/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/corori/ec.tasklist b/board/corori/ec.tasklist new file mode 100644 index 0000000000..386e8625b3 --- /dev/null +++ b/board/corori/ec.tasklist @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/corori/gpio.inc b/board/corori/gpio.inc new file mode 100644 index 0000000000..038c70243f --- /dev/null +++ b/board/corori/gpio.inc @@ -0,0 +1,141 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(A, 2), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Button interrupts */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +GPIO_INT(VOLDN_BTN_ODL, PIN(4, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(7, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) + +/* Extra Sub-board I/O pins */ + +/* Misc Enables */ +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_PEN, PIN(6, 3), GPIO_OUT_LOW) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(EC_CBI_WP, PIN(E, 5), GPIO_OUT_LOW) + +/* LED */ +GPIO(LED_W_ODL, PIN(C, 3), GPIO_OUT_HIGH) /* POWER LED */ +GPIO(LED_Y_ODL, PIN(C, 4), GPIO_OUT_HIGH) /* BATTERY LED */ + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +/* USB pins */ +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(7, 2), GPIO_OUT_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(EN_USB_A0_VBUS, PIN(4, 1), GPIO_OUT_LOW) /* Enable A0 5V Charging */ + +GPIO(EC_ACOK_OTG, PIN(C, 0), GPIO_OUT_LOW) /* OTG-OVP protect enable */ +/* + * Lalala doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(4, 0x30), 0, MODULE_ADC, 0) /* ADC0-1 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO34_NC, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO43_NC, PIN(4, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO60_NC, PIN(6, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO75_NC, PIN(7, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO37_NC, PIN(3, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOF2_NC, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOF3_NC, PIN(F, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO50_NC, PIN(5, 0), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/corori/led.c b/board/corori/led.c new file mode 100644 index 0000000000..6ae0e5f4c9 --- /dev/null +++ b/board/corori/led.c @@ -0,0 +1,225 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for lalala + */ + +#include "battery.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_INDEFINITE UINT8_MAX +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +#define LED_OFF EC_LED_COLOR_COUNT + +struct led_descriptor { + enum ec_led_colors color; + uint8_t time; +}; + +enum led_phase { LED_PHASE_0, LED_PHASE_1, LED_NUM_PHASES }; + +enum led_states { + STATE_CHARGING, + STATE_CHARGING_FULL_CHARGE, + STATE_DISCHARGE_S0, + STATE_DISCHARGE_S0_BAT_LOW, + STATE_BATTERY_S0_ERROR, + STATE_BATTERY_S3_BLINK, + STATE_BATTERY_S5_OFF, + STATE_FACTORY_TEST, + LED_NUM_STATES +}; + +static const struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING] = { { EC_LED_COLOR_AMBER, LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_BATTERY_S0_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_BATTERY_S3_BLINK] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_BATTERY_S5_OFF] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +static int led_get_charge_percent(void) +{ + return DIV_ROUND_NEAREST(charge_get_display_charge(), 10); +} + +void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_BAT_LED_AMBER, LED_ON_LVL); + gpio_set_level(GPIO_PWR_LED_WHITE, LED_OFF_LVL); + break; + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_BAT_LED_AMBER, LED_OFF_LVL); + gpio_set_level(GPIO_PWR_LED_WHITE, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_BAT_LED_AMBER, LED_OFF_LVL); + gpio_set_level(GPIO_PWR_LED_WHITE, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} + +/* Custom led on off states control */ +static enum led_states led_get_state(void) +{ + enum led_states new_state = LED_NUM_STATES; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + new_state = STATE_CHARGING; + break; + case LED_PWRS_DISCHARGE_FULL: + if (extpower_is_present()) { + new_state = STATE_CHARGING_FULL_CHARGE; + break; + } + __fallthrough; + case LED_PWRS_DISCHARGE /* and LED_PWRS_DISCHARGE_FULL */: + if (chipset_in_state(CHIPSET_STATE_ON)) + new_state = (led_get_charge_percent() < 10) ? + STATE_DISCHARGE_S0_BAT_LOW : + STATE_DISCHARGE_S0; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + new_state = STATE_BATTERY_S3_BLINK; + else + new_state = STATE_BATTERY_S5_OFF; + break; + case LED_PWRS_ERROR: + if (chipset_in_state(CHIPSET_STATE_ON)) + new_state = STATE_BATTERY_S0_ERROR; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + new_state = STATE_BATTERY_S3_BLINK; + else + new_state = STATE_BATTERY_S5_OFF; + break; + case LED_PWRS_CHARGE_NEAR_FULL: + new_state = STATE_CHARGING_FULL_CHARGE; + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + new_state = STATE_DISCHARGE_S0; + break; + case LED_PWRS_FORCED_IDLE: + new_state = STATE_FACTORY_TEST; + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + return new_state; +} + +static void led_update_battery(void) +{ + static uint8_t ticks, period; + static int led_state = LED_NUM_STATES; + int phase; + enum led_states desired_state = led_get_state(); + + /* + * We always need to check the current state since the value could + * have been manually overwritten. If we're in a new valid state, + * update our ticks and period info. If our new state isn't defined, + * continue using the previous one. + */ + if (desired_state != led_state && desired_state < LED_NUM_STATES) { + /* State is changing */ + led_state = desired_state; + /* Reset ticks and period when state changes */ + ticks = 0; + + period = led_bat_state_table[led_state][LED_PHASE_0].time + + led_bat_state_table[led_state][LED_PHASE_1].time; + } + + /* If this state is undefined, turn the LED off */ + if (period == 0) { + led_set_color_battery(LED_OFF); + return; + } + + /* + * Determine which phase of the state table to use. The phase is + * determined if it falls within first phase time duration. + */ + phase = ticks < led_bat_state_table[led_state][LED_PHASE_0].time ? 0 : + 1; + ticks = (ticks + 1) % period; + + /* Set the color for the given state and phase */ + led_set_color_battery(led_bat_state_table[led_state][phase].color); +} + +static void led_init(void) +{ + /* If battery LED is enabled, set it to "off" to start with */ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + led_set_color_battery(LED_OFF); +} +DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_DEFAULT); + +/* Called by hook task every hook tick (200 msec) */ +static void led_update(void) +{ + /* + * If battery LED is enabled, set its state based on our power and + * charge + */ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + led_update_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_update, HOOK_PRIO_DEFAULT); diff --git a/board/corori/usb_pd_policy.c b/board/corori/usb_pd_policy.c new file mode 100644 index 0000000000..3410726e87 --- /dev/null +++ b/board/corori/usb_pd_policy.c @@ -0,0 +1,56 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/corori/vif_override.xml b/board/corori/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/corori/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/corori2/battery.c b/board/corori2/battery.c new file mode 100644 index 0000000000..a59663c751 --- /dev/null +++ b/board/corori2/battery.c @@ -0,0 +1,100 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all waddledoo battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* C21N2018 Battery Information*/ + [BATTERY_C21N2018] = { + .fuel_gauge = { + .manuf_name = "AS3GXXD3KA", + .device_name = "C110160", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7890, + .voltage_min = 6000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + /* C21N2018 second Battery Information*/ + [BATTERY_C21N2018_2ND] = { + .fuel_gauge = { + .manuf_name = "AS3FXXD3KA", + .device_name = "C110160", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7890, + .voltage_min = 6000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C21N2018; diff --git a/board/corori2/board.c b/board/corori2/board.c new file mode 100644 index 0000000000..909099c6f8 --- /dev/null +++ b/board/corori2/board.c @@ -0,0 +1,732 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/nb7v904m.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/pi3usb3x532.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "stdbool.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void sub_usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + int hdmi_hpd_odl = gpio_get_level(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, !hdmi_hpd_odl); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SUB_ANALOG] = { + .name = "SUB_ANALOG", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [ADC_TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [ADC_TEMP_SENSOR_2] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_MEMORY \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(95), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_memory = + THERMAL_MEMORY; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(55), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; + +static void setup_thermal(void) +{ + thermal_params[ADC_TEMP_SENSOR_1] = thermal_memory; + thermal_params[ADC_TEMP_SENSOR_2] = thermal_charger; +} + +void board_init(void) +{ + int on; + + /* Enable C0 interrupt and check if it needs processing */ + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + check_c0_line(); + + if (get_cbi_fw_config_db() == DB_1A_HDMI) { + /* Disable i2c on HDMI pins */ + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, + 0); + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, + 0); + + /* Set HDMI and sub-rail enables to output */ + gpio_set_flags(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, + chipset_in_state(CHIPSET_STATE_ON) ? + GPIO_ODR_LOW : + GPIO_ODR_HIGH); + gpio_set_flags(GPIO_SUB_C1_INT_EN_RAILS_ODL, GPIO_ODR_HIGH); + + /* Select HDMI option */ + gpio_set_level(GPIO_HDMI_SEL_L, 0); + + /* Enable interrupt for passing through HPD */ + gpio_enable_interrupt(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + } else { + /* Set SDA as an input */ + gpio_set_flags(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, GPIO_INPUT); + + /* Enable C1 interrupt and check if it needs processing */ + gpio_enable_interrupt(GPIO_SUB_C1_INT_EN_RAILS_ODL); + check_c1_line(); + } + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + /* Initialize THERMAL */ + setup_thermal(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Enable HDMI any time the SoC is on */ +static void hdmi_enable(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + gpio_set_level(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, hdmi_enable, HOOK_PRIO_DEFAULT); + +static void hdmi_disable(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + gpio_set_level(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, hdmi_disable, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +#ifdef BOARD_WADDLEDOO +static void reconfigure_5v_gpio(void) +{ + /* + * b/147257497: On early waddledoo boards, GPIO_EN_PP5000 was swapped + * with GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that + * GPIO instead for those boards. Note that this breaks the volume up + * button functionality. + */ + if (system_get_board_version() < 0) { + CPRINTS("old board - remapping 5V en"); + gpio_set_flags(GPIO_VOLUP_BTN_ODL, GPIO_OUT_LOW); + } +} +DECLARE_HOOK(HOOK_INIT, reconfigure_5v_gpio, HOOK_PRIO_INIT_I2C + 1); +#endif /* BOARD_WADDLEDOO */ + +static void set_5v_gpio(int level) +{ + int version; + enum gpio_signal gpio = GPIO_EN_PP5000; + + /* + * b/147257497: On early waddledoo boards, GPIO_EN_PP5000 was swapped + * with GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that + * GPIO instead for those boards. Note that this breaks the volume up + * button functionality. + */ + if (IS_ENABLED(BOARD_WADDLEDOO)) { + version = system_get_board_version(); + + /* + * If the CBI EEPROM wasn't formatted, assume it's a very early + * board. + */ + gpio = version < 0 ? GPIO_VOLUP_BTN_ODL : GPIO_EN_PP5000; + } + + gpio_set_level(gpio, level); +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC, or send enable signal to HDMI + * DB. + */ + set_5v_gpio(!!enable); + + if (get_cbi_fw_config_db() == DB_1A_HDMI) { + gpio_set_level(GPIO_SUB_C1_INT_EN_RAILS_ODL, !enable); + } else { + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", + enable ? "en" : "dis"); + } +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; + else + return CONFIG_USB_PD_PORT_MAX_COUNT; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + return CHARGER_NUM - 1; + else + return CHARGER_NUM; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +/* Sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static struct accelgyro_saved_data_t g_bma253_data; +static struct bmi_drv_data_t g_bmi160_data; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP, + .freq = 10000, + }, + + [PWM_CH_LED1_AMBER] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq = 2400, + }, + + [PWM_CH_LED2_WHITE] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq = 2400, + } +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, + + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +const struct usb_mux_chain usbc1_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = NB7V904M_I2C_ADDR0, + .driver = &nb7v904m_usb_redriver_drv, + }, +}; +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + .next = &usbc1_retimer, + } +}; + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + if (board_get_usb_pd_port_count() > 1 && + !gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + /* TCPCI spec Rev 1.0 says to ignore bits 14:12. */ + if (!(tcpc_config[1].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} diff --git a/board/corori2/board.h b/board/corori2/board.h new file mode 100644 index 0000000000..5d4d810dd1 --- /dev/null +++ b/board/corori2/board.h @@ -0,0 +1,203 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_DEDEDE_EC_NPCX796FC +#include "baseboard.h" + +/* + * Keep the system unlocked in early development. + * TODO(b/151264302): Make sure to remove this before production! + */ +#define CONFIG_SYSTEM_UNLOCKED + +/* Save some flash space */ +#define CONFIG_CHIP_INIT_ROM_REGION +#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CONSOLE_HISTORY +#define CONFIG_DEBUG_ASSERT_BRIEF +#define CONFIG_USB_PD_DEBUG_LEVEL 0 + +/* EC console commands */ +#define CONFIG_CMD_CHARGER_DUMP + +/* Remove default commands to free flash space */ +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_BATTFAKE +#undef CONFIG_CMD_GETTIME +#undef CONFIG_CMD_I2C_SCAN +#undef CONFIG_CMD_I2C_XFER +#undef CONFIG_CMD_MEM + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +#define CONFIG_OCPC +#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 + +/* + * GPIO for C1 interrupts, for baseboard use + * + * Note this line might already have its pull up disabled for HDMI DBs, but + * it should be fine to set again before z-state. + */ +#define GPIO_USB_C1_INT_ODL GPIO_SUB_C1_INT_EN_RAILS_ODL + +/* Keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* LED */ +#define CONFIG_LED_PWM +#define CONFIG_LED_PWM_COUNT 1 +#undef CONFIG_LED_PWM_NEAR_FULL_COLOR +#undef CONFIG_LED_PWM_SOC_ON_COLOR +#undef CONFIG_LED_PWM_SOC_SUSPEND_COLOR +#undef CONFIG_LED_PWM_LOW_BATT_COLOR +#define CONFIG_LED_PWM_NEAR_FULL_COLOR EC_LED_COLOR_WHITE +#define CONFIG_LED_PWM_SOC_ON_COLOR EC_LED_COLOR_WHITE +#define CONFIG_LED_PWM_SOC_SUSPEND_COLOR EC_LED_COLOR_WHITE +#define CONFIG_LED_PWM_LOW_BATT_COLOR EC_LED_COLOR_AMBER + +/* PWM */ +#define CONFIG_PWM +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ + +/* Temp sensor */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B +#define CONFIG_THROTTLE_AP +#define CONFIG_CHIPSET_CAN_THROTTLE + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 +#define CONFIG_USBC_RETIMER_NB7V904M + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +#undef PD_POWER_SUPPLY_TURN_ON_DELAY +#undef PD_POWER_SUPPLY_TURN_OFF_DELAY +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +/* 20% margin added for these timings */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 13080 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 16080 /* us */ +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +#define CONFIG_USBC_VCONN_SWAP_DELAY_US 787 /* us */ + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +/* TODO(b:147440290): Need to handle multiple charger ICs */ +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ + +/* + * I2C pin names for baseboard + * + * Note: these lines will be set as i2c on start-up, but this should be + * okay since they're ODL. + */ +#define GPIO_EC_I2C_SUB_USB_C1_SCL GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL +#define GPIO_EC_I2C_SUB_USB_C1_SDA GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL + +/* Sensors */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; + +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_LED1_AMBER, + PWM_CH_LED2_WHITE, + PWM_CH_COUNT, +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_C21N2018, + BATTERY_C21N2018_2ND, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/corori2/build.mk b/board/corori2/build.mk new file mode 100644 index 0000000000..1512a49379 --- /dev/null +++ b/board/corori2/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=dedede + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/corori2/cbi_ssfc.c b/board/corori2/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/corori2/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/corori2/cbi_ssfc.h b/board/corori2/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/corori2/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/corori2/ec.tasklist b/board/corori2/ec.tasklist new file mode 100644 index 0000000000..29666dd959 --- /dev/null +++ b/board/corori2/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/corori2/gpio.inc b/board/corori2/gpio.inc new file mode 100644 index 0000000000..63b16a1bc3 --- /dev/null +++ b/board/corori2/gpio.inc @@ -0,0 +1,139 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) +GPIO_INT(SUB_C1_INT_EN_RAILS_ODL, PIN(F, 5), GPIO_INT_FALLING | GPIO_PULL_UP, sub_usb_c1_interrupt) /* C1 interrupt OR 5V power en */ +GPIO_INT(EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, PIN(9, 1), GPIO_INT_BOTH, sub_hdmi_hpd_interrupt) /* C1 I2C SDA OR HDMI_HPD */ + +/* Button interrupts */ +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +GPIO_INT(VOLDN_BTN_ODL, PIN(4, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(7, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) +GPIO_INT(LID_360_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, PIN(9, 2), GPIO_INPUT) /* C1 I2C SCL OR HDMI en */ + +/* Extra Sub-board I/O pins */ +GPIO(EC_SUB_IO_1, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_SUB_IO_2, PIN(3, 4), GPIO_OUT_LOW) + +/* Misc Enables */ +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_PEN, PIN(6, 3), GPIO_OUT_LOW) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_KB_BL, PIN(6, 0), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(IMVP9_PE, PIN(E, 0), GPIO_OUT_LOW) +GPIO(ECH1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) + +GPIO(USB_C0_RST_ODL, PIN(9, 7), GPIO_OUT_HIGH) /* currently unused */ +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(7, 2), GPIO_OUT_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) + +/* + * Waddledoo doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* ADC0-2 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* PWM */ +ALTERNATE(PIN_MASK(C, 0x1C), 0, MODULE_PWM, 0) /* PWM0-2 */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* PWM3 */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO41_NC, PIN(4, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/corori2/led.c b/board/corori2/led.c new file mode 100644 index 0000000000..71a8159a07 --- /dev/null +++ b/board/corori2/led.c @@ -0,0 +1,67 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo specific PWM LED settings. */ + +#include "common.h" +#include "ec_commands.h" +#include "led_pwm.h" +#include "pwm.h" +#include "util.h" + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_POWER_LED, +}; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); +/* + * We only have a white and an amber LED, so setting any other colour results in + * both LEDs being off. + */ +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Amber, White */ + [EC_LED_COLOR_RED] = { 0, 0 }, [EC_LED_COLOR_GREEN] = { 0, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0 }, [EC_LED_COLOR_YELLOW] = { 0, 0 }, + [EC_LED_COLOR_WHITE] = { 0, 100 }, [EC_LED_COLOR_AMBER] = { 100, 0 }, +}; + +/* One logical LED with amber and white channels. */ +struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = { + { + .ch0 = PWM_CH_LED1_AMBER, + .ch1 = PWM_CH_LED2_WHITE, + .ch2 = PWM_LED_NO_CHANNEL, + .enable = &pwm_enable, + .set_duty = &pwm_set_duty, + }, +}; + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + memset(brightness_range, '\0', + sizeof(*brightness_range) * EC_LED_COLOR_COUNT); + brightness_range[EC_LED_COLOR_AMBER] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + enum pwm_led_id pwm_id; + + /* Convert ec_led_id to pwm_led_id. */ + if (led_id == EC_LED_ID_POWER_LED) + pwm_id = PWM_LED0; + else + return EC_ERROR_UNKNOWN; + + if (brightness[EC_LED_COLOR_WHITE]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); + else + /* Otherwise, the "color" is "off". */ + set_pwm_led_color(pwm_id, -1); + + return EC_SUCCESS; +} diff --git a/board/corori2/usb_pd_policy.c b/board/corori2/usb_pd_policy.c new file mode 100644 index 0000000000..83c09bb99e --- /dev/null +++ b/board/corori2/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/corori2/vif_override.xml b/board/corori2/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/corori2/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/flapjack_scp b/board/corsola_scp similarity index 100% rename from board/flapjack_scp rename to board/corsola_scp diff --git a/board/cozmo b/board/cozmo new file mode 120000 index 0000000000..9ed6f26875 --- /dev/null +++ b/board/cozmo @@ -0,0 +1 @@ +icarus \ No newline at end of file diff --git a/board/cret/battery.c b/board/cret/battery.c new file mode 100644 index 0000000000..27bfed5355 --- /dev/null +++ b/board/cret/battery.c @@ -0,0 +1,658 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_state.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all waddledoo battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* BYD Battery Information */ + [BATTERY_BYD_1VX1H] = { + .fuel_gauge = { + .manuf_name = "BYD", + .device_name = "DELL 1VX1H", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* BYD Battery Information */ + [BATTERY_BYD_YT39X] = { + .fuel_gauge = { + .manuf_name = "BYD", + .device_name = "DELL YT39X", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* BYD Battery Information */ + [BATTERY_BYD_X0Y5M] = { + .fuel_gauge = { + .manuf_name = "BYD", + .device_name = "DELL X0Y5M", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x043, + .reg_mask = 0x0001, + .disconnect_val = 0x0000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* LGC Battery Information */ + [BATTERY_LGC_FDRHM] = { + .fuel_gauge = { + .manuf_name = "LGC-LGC3.65", + .device_name = "DELL FDRHM", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11460, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* LGC Battery Information */ + [BATTERY_LGC_8GHCX] = { + .fuel_gauge = { + .manuf_name = "LGC-LGC3.65", + .device_name = "DELL 8GHCX", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11460, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + + /* SWD-ATL Battery Information */ + [BATTERY_SWD_ATL_WJPC4] = { + .fuel_gauge = { + .manuf_name = "SWD-ATL3.618", + .device_name = "DELL WJPC4", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SWD-ATL Battery Information */ + [BATTERY_SWD_ATL_CTGKT] = { + .fuel_gauge = { + .manuf_name = "SWD-ATL3.618", + .device_name = "DELL CTGKT", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SWD-COS Battery Information */ + [BATTERY_SWD_COS_WJPC4] = { + .fuel_gauge = { + .manuf_name = "SWD-COS3.634", + .device_name = "DELL WJPC4", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SWD-COS Battery Information */ + [BATTERY_SWD_COS_CTGKT] = { + .fuel_gauge = { + .manuf_name = "SWD-COS3.634", + .device_name = "DELL CTGKT", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-ATL Battery Information */ + [BATTERY_SMP_ATL_VM732] = { + .fuel_gauge = { + .manuf_name = "SMP-ATL-3.61", + .device_name = "DELL VM732", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-ATL Battery Information */ + [BATTERY_SMP_ATL_26JGK] = { + .fuel_gauge = { + .manuf_name = "SMP-ATL-3.61", + .device_name = "DELL 26JGK", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-ATL Battery Information */ + [BATTERY_SMP_ATL_RF9H3] = { + .fuel_gauge = { + .manuf_name = "SMP-ATL-3.61", + .device_name = "DELL RF9H3", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-COS Battery Information */ + [BATTERY_SMP_COS_VM732] = { + .fuel_gauge = { + .manuf_name = "SMP-COS3.63", + .device_name = "DELL VM732", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-COS Battery Information */ + [BATTERY_SMP_COS_26JGK] = { + .fuel_gauge = { + .manuf_name = "SMP-COS3.63", + .device_name = "DELL 26JGK", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + /* SMP-COS Battery Information */ + [BATTERY_SMP_COS_RF9H3] = { + .fuel_gauge = { + .manuf_name = "SMP-COS3.63", + .device_name = "DELL RF9H3", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* BYD 16DPHYMD Battery Information */ + [BATTERY_BYD16] = { + .fuel_gauge = { + .manuf_name = "BYD-BYD3.685", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x043, + .reg_mask = 0x0001, + .disconnect_val = 0x000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, + + /* LGC Battery Information */ + [BATTERY_LGC3] = { + .fuel_gauge = { + .manuf_name = "LGC-LGC3.553", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, + + /* SIMPLO Battery Information */ + [BATTERY_SIMPLO] = { + .fuel_gauge = { + .manuf_name = "SMP-SDI3.72", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x043, + .reg_mask = 0x0001, + .disconnect_val = 0x000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, + + /* SIMPLO-LISHEN 7T0D3YMD Battery Information */ + [BATTERY_SIMPLO_LS] = { + .fuel_gauge = { + .manuf_name = "SMP-LS3.66", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x043, + .reg_mask = 0x0001, + .disconnect_val = 0x000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_BYD_1VX1H; + +int charger_profile_override(struct charge_state_data *curr) +{ + if (chipset_in_state(CHIPSET_STATE_ON)) { + curr->requested_current = + MIN(curr->requested_current, CHARGING_CURRENT_1100MA); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/cret/board.c b/board/cret/board.c new file mode 100644 index 0000000000..59edd8145a --- /dev/null +++ b/board/cret/board.c @@ -0,0 +1,585 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "driver/accel_lis2dh.h" +#include "driver/accelgyro_lsm6dso.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/pi3usb3x532.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_8042.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "stdbool.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +static void fw_config_tablet_mode(void); +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + int hdmi_hpd_odl = gpio_get_level(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, !hdmi_hpd_odl); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +void board_init(void) +{ + int on; + + /* Enable C0 interrupt and check if it needs processing */ + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + check_c0_line(); + + /* Enable interrupt for passing through HPD */ + gpio_enable_interrupt(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + + fw_config_tablet_mode(); + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Enable HDMI any time the SoC is on */ +static void hdmi_enable(void) +{ + if (get_cbi_fw_config_hdmi() == HDMI_PRESENT) { + gpio_set_level(GPIO_EC_HDMI_EN_ODL, 0); + gpio_set_level(GPIO_HDMI_PP3300_EN, 1); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, hdmi_enable, HOOK_PRIO_DEFAULT); + +static void hdmi_disable(void) +{ + if (get_cbi_fw_config_hdmi() == HDMI_PRESENT) { + gpio_set_level(GPIO_EC_HDMI_EN_ODL, 1); + gpio_set_level(GPIO_HDMI_PP3300_EN, 0); + } +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, hdmi_disable, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +#ifdef BOARD_WADDLEDOO +static void reconfigure_5v_gpio(void) +{ + /* + * b/147257497: On early waddledoo boards, GPIO_EN_PP5000 was swapped + * with GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that + * GPIO instead for those boards. Note that this breaks the volume up + * button functionality. + */ + if (system_get_board_version() < 0) { + CPRINTS("old board - remapping 5V en"); + gpio_set_flags(GPIO_VOLUP_BTN_ODL, GPIO_OUT_LOW); + } +} +DECLARE_HOOK(HOOK_INIT, reconfigure_5v_gpio, HOOK_PRIO_INIT_I2C + 1); +#endif /* BOARD_WADDLEDOO */ + +static void set_5v_gpio(int level) +{ + gpio_set_level(GPIO_EN_PP5000, level); + gpio_set_level(GPIO_EN_USB_A0_VBUS, level); +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC, or send enable signal to HDMI + * DB. + */ + set_5v_gpio(!!enable); +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + return CONFIG_USB_PD_PORT_MAX_COUNT; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + return CHARGER_NUM; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +/* Sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static struct stprivate_data g_lis2dh_data; +static struct lsm6dso_data lsm6dso_data; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DE, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dh_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2dh_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DH_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = LIS2DH_ODR_MIN_VAL, + .max_frequency = LIS2DH_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP, + .freq = 10000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + }, +}; + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + return status; +} + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} + +/* Keyboard scan setting */ +static const struct ec_response_keybd_config cret_keybd = { + /* Default Chromeos keyboard config */ + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad, has screenlock key */ + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &cret_keybd; +} + +static void fw_config_tablet_mode(void) +{ + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_PRESENT) { + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable Base Accel interrupt */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } +} + +static void board_extpower(void) +{ + int extpower_present; + + if (pd_is_connected(0)) + extpower_present = extpower_is_present(); + else + extpower_present = 0; + + gpio_set_level(GPIO_EC_ACOK_OTG, extpower_present); +} +DECLARE_HOOK(HOOK_AC_CHANGE, board_extpower, HOOK_PRIO_DEFAULT); diff --git a/board/cret/board.h b/board/cret/board.h new file mode 100644 index 0000000000..9dc2edb265 --- /dev/null +++ b/board/cret/board.h @@ -0,0 +1,180 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_DEDEDE_EC_NPCX796FC +#include "baseboard.h" + +/* Save some flash space */ +#define CONFIG_CHIP_INIT_ROM_REGION +#define CONFIG_DEBUG_ASSERT_BRIEF + +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_CMD_POWERINDEBUG +#undef CONFIG_I2C_DEBUG + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 +#define CONFIG_CHARGER_PROFILE_OVERRIDE +#define CHARGING_CURRENT_1100MA 1100 + +/* + * GPIO for C1 interrupts, for baseboard use + * + * Note this line might already have its pull up disabled for HDMI DBs, but + * it should be fine to set again before z-state. + */ +#define GPIO_EC_HDMI_EN_ODL GPIO_EC_I2C_SBU_USB_C1_SCL +#define GPIO_HDMI_PP3300_EN GPIO_SUB_USB_C1_INT_ODL + +/* PWM */ +#define CONFIG_PWM +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* LED */ +#define CONFIG_LED_COMMON +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 +#define CONFIG_LED_ONOFF_STATES + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +#undef PD_POWER_SUPPLY_TURN_ON_DELAY +#undef PD_POWER_SUPPLY_TURN_OFF_DELAY +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +/* 20% margin added for these timings */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 13080 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 16080 /* us */ +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +#define CONFIG_USBC_VCONN_SWAP_DELAY_US 787 /* us */ + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +/* TODO(b:147440290): Need to handle multiple charger ICs */ +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ + +/* Sensors */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +#define CONFIG_ACCEL_LIS2DE /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSO /* Base accel */ +#define CONFIG_ACCEL_LSM6DSO_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_BYD_1VX1H, + BATTERY_BYD_YT39X, + BATTERY_BYD_X0Y5M, + BATTERY_LGC_FDRHM, + BATTERY_LGC_8GHCX, + BATTERY_SWD_ATL_WJPC4, + BATTERY_SWD_ATL_CTGKT, + BATTERY_SWD_COS_WJPC4, + BATTERY_SWD_COS_CTGKT, + BATTERY_SMP_ATL_VM732, + BATTERY_SMP_ATL_26JGK, + BATTERY_SMP_ATL_RF9H3, + BATTERY_SMP_COS_VM732, + BATTERY_SMP_COS_26JGK, + BATTERY_SMP_COS_RF9H3, + BATTERY_BYD16, + BATTERY_LGC3, + BATTERY_SIMPLO, + BATTERY_SIMPLO_LS, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/cret/build.mk b/board/cret/build.mk new file mode 100644 index 0000000000..1512a49379 --- /dev/null +++ b/board/cret/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=dedede + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/cret/cbi_ssfc.c b/board/cret/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/cret/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/cret/cbi_ssfc.h b/board/cret/cbi_ssfc.h new file mode 100644 index 0000000000..bef606bc72 --- /dev/null +++ b/board/cret/cbi_ssfc.h @@ -0,0 +1,64 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +/* + * Bits 9-11 + * Cret board uses SSFC bits 9-11 in coreboot for audio codec. + */ + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/cret/ec.tasklist b/board/cret/ec.tasklist new file mode 100644 index 0000000000..a98ca6fd86 --- /dev/null +++ b/board/cret/ec.tasklist @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/cret/gpio.inc b/board/cret/gpio.inc new file mode 100644 index 0000000000..5f39fedc80 --- /dev/null +++ b/board/cret/gpio.inc @@ -0,0 +1,148 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) +GPIO_INT(EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, PIN(9, 1), GPIO_INT_BOTH, sub_hdmi_hpd_interrupt) /* C1 I2C SDA OR HDMI_HPD */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(A, 2), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Button interrupts */ +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +GPIO_INT(VOLDN_BTN_ODL, PIN(4, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(7, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(LID_360_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dso_interrupt) +GPIO(LID_ACCEL_INT_L, PIN(5, 0), GPIO_INPUT | GPIO_SEL_1P8V) + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) + +/* Misc Enables */ +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(IMVP9_PE, PIN(E, 0), GPIO_OUT_LOW) +GPIO(ECH1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(SUB_USB_C1_INT_ODL, PIN(F, 5), GPIO_OUT_LOW) /* 5V power en */ +GPIO(EC_I2C_SBU_USB_C1_SCL, PIN(9, 2), GPIO_ODR_LOW) /* HDMI en */ + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) + +GPIO(USB_C0_RST_ODL, PIN(9, 7), GPIO_OUT_HIGH) /* currently unused */ +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) + +/* USB pins */ +GPIO(USB_A0_CHARGE_EN_L, PIN(6, 3), GPIO_OUT_HIGH) /* Reverse: Enable A0 1.5A Charging */ +GPIO(EN_USB_A0_VBUS, PIN(4, 1), GPIO_OUT_LOW) /* Enable A0 5V Charging */ + +/*LEDs*/ +GPIO(LED_1_PWR_WHITE_L, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(LED_2_CHG_AMBER_L, PIN(C, 4), GPIO_OUT_HIGH) + +/* + * Waddledoo doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(4, 0x30), 0, MODULE_ADC, 0) /* ADC0-1 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* PWM */ +ALTERNATE(PIN_MASK(C, 0x04), 0, MODULE_PWM, 0) /* PWM1 */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, 0x01), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +GPIO(EC_ACOK_OTG, PIN(C, 0), GPIO_OUT_LOW) /* OTG-OVP protect enable */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOF2_NC, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOF3_NC, PIN(F, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO37_NC, PIN(3, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO34_NC, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO43_NC, PIN(4, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO60_NC, PIN(6, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO72_NC, PIN(7, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/cret/led.c b/board/cret/led.c new file mode 100644 index 0000000000..8a7a343fb3 --- /dev/null +++ b/board/cret/led.c @@ -0,0 +1,86 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1 = 10; + +__override const int led_charge_lvl_2 = 100; + +/* Cret: Note there is only LED for charge / power */ +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_1_PWR_WHITE_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_CHG_AMBER_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_1_PWR_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_CHG_AMBER_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_1_PWR_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_CHG_AMBER_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + + return EC_SUCCESS; +} diff --git a/board/cret/usb_pd_policy.c b/board/cret/usb_pd_policy.c new file mode 100644 index 0000000000..83c09bb99e --- /dev/null +++ b/board/cret/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/cret/vif_override.xml b/board/cret/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/cret/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/crota/battery.c b/board/crota/battery.c new file mode 100644 index 0000000000..4738b5910f --- /dev/null +++ b/board/crota/battery.c @@ -0,0 +1,431 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Brya battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* ATL GB-S40-496570-010H Battery Information */ + [BATTERY_ATL] = { + .fuel_gauge = { + .manuf_name = "ATL-ATL3.66", + .device_name = "DELL CFD72", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17600, /* mV */ + .voltage_normal = 15000, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 60, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 60, + }, + }, + /* BYD 13076993-009 Battery Information */ + [BATTERY_BYD_GSL4] = { + .fuel_gauge = { + .manuf_name = "BYD", + .device_name = "DELL WV3K8", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17400, /* mV */ + .voltage_normal = 15000, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 60, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, + /* CosMX B00C496570D0002 Battery Information */ + [BATTERY_COM] = { + .fuel_gauge = { + .manuf_name = "COM", + .device_name = "DELL MVK11", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17600, /* mV */ + .voltage_normal = 15000, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -17, + .discharging_max_c = 70, + }, + }, + /* LGES MPPDELWM4C1N Battery Information */ + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "LGC-LGC3.600", + .device_name = "DELL XPHX8", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17600, /* mV */ + .voltage_normal = 15000, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, + /* SMP 999QA455H Battery Information */ + [BATTERY_SMP_ATL3] = { + .fuel_gauge = { + .manuf_name = "SMP-ATL3.66", + .device_name = "DELL XDY9K", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17600, /* mV */ + .voltage_normal = 15000, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -14, + .discharging_max_c = 70, + }, + }, + /* SMP 999QA454H Battery Information */ + [BATTERY_SMP_COS3] = { + .fuel_gauge = { + .manuf_name = "SMP-COS3.66", + .device_name = "DELL XDY9K", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17600, /* mV */ + .voltage_normal = 15000, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -14, + .discharging_max_c = 70, + }, + }, + /* SWD 1002000008482 Battery Information */ + [BATTERY_SWD_ATL3] = { + .fuel_gauge = { + .manuf_name = "SWD-ATL3.660", + .device_name = "DELL VKYJX", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17600, /* mV */ + .voltage_normal = 15000, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, + /* SWD 1002000008492 Battery Information */ + [BATTERY_SWD_COS3] = { + .fuel_gauge = { + .manuf_name = "SWD-COS3.661", + .device_name = "DELL VKYJX", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17600, /* mV */ + .voltage_normal = 15000, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, + /* SMP 999QA485H Battery Information */ + [BATTERY_SMP_ATL4] = { + .fuel_gauge = { + .manuf_name = "SMP-ATL4.24", + .device_name = "DELL N9XX1", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17800, /* mV */ + .voltage_normal = 15200, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -14, + .discharging_max_c = 70, + }, + }, + /* SMP 999QA486H Battery Information */ + [BATTERY_SMP_COS4] = { + .fuel_gauge = { + .manuf_name = "SMP-COS4.26", + .device_name = "DELL N9XX1", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17800, /* mV */ + .voltage_normal = 15200, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -14, + .discharging_max_c = 70, + }, + }, + /* BYD 13148981-00 Battery Information */ + [BATTERY_BYD_CSL4] = { + .fuel_gauge = { + .manuf_name = "BYD", + .device_name = "DELL JGCCT", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17400, /* mV */ + .voltage_normal = 15000, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 60, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, + /* Sunwoda 1002000009262 Battery Information */ + [BATTERY_SWD_ATL4] = { + .fuel_gauge = { + .manuf_name = "SWD-ATL4.242", + .device_name = "DELL 3RR09", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17800, /* mV */ + .voltage_normal = 15200, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, + /* Sunwoda 1002000009272 Battery Information */ + [BATTERY_SWD_COS4] = { + .fuel_gauge = { + .manuf_name = "SWD-COS4.264", + .device_name = "DELL 3RR09", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 17800, /* mV */ + .voltage_normal = 15200, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_ATL; + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* + * The GPIO is low when the battery is physically present. + * But if battery cell voltage < 2.5V, it will not able to + * pull down EC_BATT_PRES_ODL. So we need to set pre-charge + * current even EC_BATT_PRES_ODL is high. + */ + return gpio_get_level(batt_pres) ? BP_NOT_SURE : BP_YES; +} diff --git a/board/crota/board.c b/board/crota/board.c new file mode 100644 index 0000000000..2e6f851ad5 --- /dev/null +++ b/board/crota/board.c @@ -0,0 +1,69 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi260.h" +#include "driver/accelgyro_lsm6dso.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +bool board_is_convertible(void) +{ + /* + * convertible = 0 + * clamshell = 1 + */ + return !get_fw_config().form_factor; +} + +int board_sensor_at_360(void) +{ + if (board_is_convertible()) + return !gpio_get_level(GPIO_TABLET_MODE_L); + + return 0; +} diff --git a/board/crota/board.h b/board/crota/board.h new file mode 100644 index 0000000000..d652a93ad0 --- /dev/null +++ b/board/crota/board.h @@ -0,0 +1,295 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Crota board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* Sensors */ +#define CONFIG_ACCELGYRO_BMI260 /* Base accel/gyro */ +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_LSM6DSO /* Base accel/gyro */ +#define CONFIG_ACCEL_LSM6DSO_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Lid accel */ +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_ACCEL_LIS2DWL +#define CONFIG_ACCEL_LIS2DW12_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +#define CONFIG_BODY_DETECTION +#define CONFIG_BODY_DETECTION_SENSOR BASE_ACCEL +#define CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR 150 /* % */ +#define CONFIG_GESTURE_DETECTION +#define CONFIG_GESTURE_DETECTION_MASK BIT(CONFIG_BODY_DETECTION_SENSOR) +#define CONFIG_GESTURE_HOST_DETECTION + +#define CONFIG_GMR_TABLET_MODE_CUSTOM +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USBC_RETIMER_INTEL_BB + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +#define CONFIG_USBC_PPC_SYV682X + +#define CONFIG_USB_PD_FRS_PPC + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +#undef CONFIG_CMD_POWERINDEBUG + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +#define GPIO_ID_1_EC_KB_BL_EN GPIO_EC_BATT_PRES_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* Keyboard features */ +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_C1_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_C1_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C1_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C1_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +/* define this to avoid error on CONFIG_ACCELGYRO_BMI_COMM_I2C */ +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 +/* + * see b/174768555#comment22 + */ +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x58 +#define USBC_PORT_C1_SOC_BB_RETIMER_I2C_ADDR 0x54 +/* Type-C connector facing Burnside Bridge retimer */ +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x56 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* Fan features */ +#define CONFIG_CUSTOM_FAN_CONTROL +#define CONFIG_FANS FAN_CH_COUNT +#define CONFIG_FAN_DYNAMIC +#define RPM_DEVIATION 1 + +/* Charger defines */ +#define CONFIG_CHARGER_BQ25720 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 70 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_BQ25710_PSYS_SENSING +#define CONFIG_CHARGER_BQ25710_PP_ACOK + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_SOC, + ADC_TEMP_SENSOR_2_DDR, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_TEMP_SENSOR_4_AMBIENT, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_SOC, + TEMP_SENSOR_2_DDR, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_4_AMBIENT, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { LID_ACCEL = 0, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C1_NCT38XX, IOEX_PORT_COUNT }; + +enum battery_type { + BATTERY_ATL, + BATTERY_BYD_GSL4, + BATTERY_COM, + BATTERY_LGC, + BATTERY_SMP_ATL3, + BATTERY_SMP_COS3, + BATTERY_SWD_ATL3, + BATTERY_SWD_COS3, + BATTERY_SMP_ATL4, + BATTERY_SMP_COS4, + BATTERY_BYD_CSL4, + BATTERY_SWD_ATL4, + BATTERY_SWD_COS4, + BATTERY_TYPE_COUNT +}; + +enum pwm_channel { + PWM_CH_LED2 = 0, /* PWM0 (white charger) */ + PWM_CH_LED1, /* PWM2 (orange charger) */ + PWM_CH_KBLIGHT, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum fan_rpm_table { + RPM_TABLE_CPU, + RPM_TABLE_CPU_TABLET, + RPM_TABLE_DDR, + RPM_TABLE_CHARGER, + RPM_TABLE_AMBIENT, + FAN_RPM_TABLE_COUNT +}; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +struct thermal_policy_config { + uint8_t fan_off_slop1; + uint8_t fan_max_slop1; + uint8_t fan_off_slop2; + uint8_t fan_max_slop2; + uint8_t fan_slop_threshold; + uint8_t ddr_fan_turn_on; + uint8_t ddr_fan_turn_off; + uint8_t rpm_table_cpu; +}; + +enum thermal_cfg_table { LAPTOP_MODE, TABLET_MODE, THERMAL_CFG_TABLE_COUNT }; + +void motion_interrupt(enum gpio_signal signal); + +bool board_is_convertible(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/crota/build.mk b/board/crota/build.mk new file mode 100644 index 0000000000..8b85854cf0 --- /dev/null +++ b/board/crota/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/crota/charger.c b/board/crota/charger.c new file mode 100644 index 0000000000..7b3edd270d --- /dev/null +++ b/board/crota/charger.c @@ -0,0 +1,80 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/crota/ec.tasklist b/board/crota/ec.tasklist new file mode 100644 index 0000000000..17eeb4ae7c --- /dev/null +++ b/board/crota/ec.tasklist @@ -0,0 +1,29 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(1) | BIT(0)), BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/crota/fans.c b/board/crota/fans.c new file mode 100644 index 0000000000..874f04317f --- /dev/null +++ b/board/crota/fans.c @@ -0,0 +1,207 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" +#include "tablet_mode.h" +#include "thermal.h" +#include "timer.h" +#include "util.h" + +#define RECORD_TIME (2 * MINUTE) + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_rpm rpm_table[FAN_RPM_TABLE_COUNT] = { + [RPM_TABLE_CPU] = { + .rpm_min = 0, + .rpm_start = 0, + .rpm_max = 4000, + }, + + [RPM_TABLE_CPU_TABLET] = { + .rpm_min = 0, + .rpm_start = 0, + .rpm_max = 4000, + }, + + [RPM_TABLE_DDR] = { + .rpm_min = 4000, + .rpm_start = 4000, + .rpm_max = 4200, + }, + + [RPM_TABLE_CHARGER] = { + .rpm_min = 4000, + .rpm_start = 4000, + .rpm_max = 4200, + }, + + [RPM_TABLE_AMBIENT] = { + .rpm_min = 4000, + .rpm_start = 4000, + .rpm_max = 4200, + }, +}; + +struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &rpm_table[RPM_TABLE_CPU], + }, +}; + +static const struct thermal_policy_config + thermal_cfg[THERMAL_CFG_TABLE_COUNT] = { + [LAPTOP_MODE] = { + .fan_off_slop1 = 24, + .fan_max_slop1 = 51, + .fan_off_slop2 = 29, + .fan_max_slop2 = 48, + .fan_slop_threshold = 45, + .ddr_fan_turn_off = 38, + .ddr_fan_turn_on = 44, + .rpm_table_cpu = RPM_TABLE_CPU, + }, + + [TABLET_MODE] = { + .fan_off_slop1 = 25, + .fan_max_slop1 = 52, + .fan_off_slop2 = 30, + .fan_max_slop2 = 49, + .fan_slop_threshold = 45, + .ddr_fan_turn_off = 38, + .ddr_fan_turn_on = 44, + .rpm_table_cpu = RPM_TABLE_CPU_TABLET, + }, +}; + +static void fan_get_rpm(int fan) +{ + static timestamp_t deadline; + + /* Record actual RPM every 2 minutes. */ + if (timestamp_expired(deadline, NULL)) { + ccprints("fan actual rpm: %d", fan_get_rpm_actual(FAN_CH(fan))); + deadline.val = get_time().val + RECORD_TIME; + } +} + +static void fan_set_percent(int fan, int pct) +{ + int new_rpm; + + new_rpm = fan_percent_to_rpm(fan, pct); + fan_set_rpm_target(FAN_CH(fan), new_rpm); + fan_get_rpm(fan); +} + +void board_override_fan_control(int fan, int *tmp) +{ + /* + * Crota's fan speed is control by four sensors. + * + * Sensor charger control the speed when system's temperature + * is too high. + * Other sensors control normal loading's speed. + * + * When sensor charger is triggered, the fan speed is only + * control by sensor charger, avoid heat damage to system. + * When other sensors is triggered, the fan is control + * by other sensors. + * + * Sensor SOC has two slopes for fan speed. + * Sensor DDR also become a fan on/off switch. + */ + const struct thermal_policy_config *t; + static int pct; + int i; + int fan_pct[TEMP_SENSOR_COUNT]; + int fan_off; + int fan_max; + + /* Decide is tablet mode or laptop mode. */ + if (tablet_get_mode()) + t = &thermal_cfg[TABLET_MODE]; + else + t = &thermal_cfg[LAPTOP_MODE]; + + /* Decide sensor SOC temperature using which slope. */ + if (tmp[TEMP_SENSOR_1_SOC] <= t->fan_slop_threshold) { + fan_off = t->fan_off_slop1; + fan_max = t->fan_max_slop1; + } else { + fan_off = t->fan_off_slop2; + fan_max = t->fan_max_slop2; + } + thermal_params[TEMP_SENSOR_1_SOC].temp_fan_off = C_TO_K(fan_off); + thermal_params[TEMP_SENSOR_1_SOC].temp_fan_max = C_TO_K(fan_max); + + for (i = 0; i < TEMP_SENSOR_COUNT; i++) { + fan_pct[i] = thermal_fan_percent(thermal_params[i].temp_fan_off, + thermal_params[i].temp_fan_max, + C_TO_K(tmp[i])); + } + + /* + * In Balance mode: + * Sensor DDR turn on when temperature > 44, + * turn off when temperature < 38 + * + * In Tablet mode: + * Sensor DDR turn on when temperature > 44, + * turn off when temperature < 38 + * + * When temperature from high dropping to 38 ~ 44, + * if pct is not 0, keep sensor trigger and choose table. + */ + if (((tmp[TEMP_SENSOR_2_DDR]) <= t->ddr_fan_turn_on && pct == 0) || + ((tmp[TEMP_SENSOR_2_DDR]) < t->ddr_fan_turn_off)) + pct = 0; + else { + /* + * Decide which sensor was triggered and choose table. + * Priority: charger > soc > ddr > ambient + */ + if (fan_pct[TEMP_SENSOR_3_CHARGER]) { + fans[fan].rpm = &rpm_table[RPM_TABLE_CHARGER]; + pct = fan_pct[TEMP_SENSOR_3_CHARGER]; + } else if (fan_pct[TEMP_SENSOR_1_SOC]) { + fans[fan].rpm = &rpm_table[t->rpm_table_cpu]; + pct = fan_pct[TEMP_SENSOR_1_SOC]; + } else if (fan_pct[TEMP_SENSOR_2_DDR]) { + fans[fan].rpm = &rpm_table[RPM_TABLE_DDR]; + pct = fan_pct[TEMP_SENSOR_2_DDR]; + } else { + fans[fan].rpm = &rpm_table[RPM_TABLE_AMBIENT]; + pct = fan_pct[TEMP_SENSOR_4_AMBIENT]; + } + } + + /* Transfer percent to rpm. */ + fan_set_percent(fan, pct); +} diff --git a/board/crota/fw_config.c b/board/crota/fw_config.c new file mode 100644 index 0000000000..c5ee4708c2 --- /dev/null +++ b/board/crota/fw_config.c @@ -0,0 +1,53 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union brya_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brya if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union brya_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Brya FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* + * Early boards have a zero'd out FW_CONFIG, so replace + * it with a sensible default value. If DB_USB_ABSENT2 + * was used as an alternate encoding of DB_USB_ABSENT to + * avoid the zero check, then fix it. + */ + if (fw_config.raw_value == 0) { + CPRINTS("CBI: FW_CONFIG is zero, using board defaults"); + fw_config = fw_config_defaults; + } + } +} + +union brya_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} diff --git a/board/crota/fw_config.h b/board/crota/fw_config.h new file mode 100644 index 0000000000..f2317c7cd7 --- /dev/null +++ b/board/crota/fw_config.h @@ -0,0 +1,42 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_BRYA_FW_CONFIG_H_ +#define __BOARD_BRYA_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Brya board. + * + * Source of truth is the project/brya/brya/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +union brya_cbi_fw_config { + struct { + uint32_t mb_db : 2; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t db_lte : 2; + uint32_t wifi_sar_id : 1; + uint32_t form_factor : 1; + uint32_t reserved_1 : 22; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union brya_cbi_fw_config get_fw_config(void); + +#endif /* __BOARD_BRYA_FW_CONFIG_H_ */ diff --git a/board/crota/gpio.inc b/board/crota/gpio.inc new file mode 100644 index 0000000000..0a3471b5c0 --- /dev/null +++ b/board/crota/gpio.inc @@ -0,0 +1,145 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_ACCEL_INT_R_L, PIN(8, 1), GPIO_SEL_1P8V | GPIO_INT_FALLING, lis2dw12_interrupt) +GPIO_INT(EC_IMU_INT_R_L, PIN(5, 6), GPIO_SEL_1P8V | GPIO_INT_FALLING, motion_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C1_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_C1_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(EC_SENSOR_STRAP, PIN(5, 7), GPIO_INPUT) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(D, 4)) /* GPIOD4/CR_SIN3 */ +UNUSED(PIN(5, 0)) /* GPIO50 */ +UNUSED(PIN(F, 5)) /* GPIOF5/I2C5_SCL1 */ +UNUSED(PIN(A, 2)) /* F_SCLK/GPIOA2 */ +UNUSED(PIN(E, 4)) /* GPIOE4/I2C6_SCL1/I3C_SCL */ +UNUSED(PIN(E, 3)) /* GPIOE3/I2C6_SDA1/I3C_SDA */ +UNUSED(PIN(F, 3)) /* GPIOF3/I2C4_SCL1 */ +UNUSED(PIN(F, 2)) /* GPIOF2/I2C4_SDA1 */ +UNUSED(PIN(9, 4)) /* GPIO94 */ +UNUSED(PIN(9, 6)) /* F_DIO1/GPIO96 */ +UNUSED(PIN(A, 0)) /* F_CS0#/GPIOA0 */ +UNUSED(PIN(0, 2)) /* GPIO02/PSL_IN4#&GPI02 */ +UNUSED(PIN(6, 0)) /* GPIO60/PWM7 */ +UNUSED(PIN(C, 2)) /* GPIOC2/PWM1/I2C6_SCL0 */ + +/* Pre-configured PSL balls: J8 K6 */ + + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C1_RT_RST_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C1_FRS_EN, EXPIN(IOEX_C1_NCT38XX, 0, 6), GPIO_OUT_LOW) diff --git a/board/crota/i2c.c b/board/crota/i2c.c new file mode 100644 index 0000000000..681e600bf2 --- /dev/null +++ b/board/crota/i2c.c @@ -0,0 +1,65 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "hooks.h" +#include "i2c.h" + +#define BOARD_ID_FAST_PLUS_CAPABLE 2 + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,2", + .port = I2C_PORT_USB_C0_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,2", + .port = I2C_PORT_USB_C0_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,2", + .port = I2C_PORT_USB_C0_C1_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_RT_SDA, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/crota/keyboard.c b/board/crota/keyboard.c new file mode 100644 index 0000000000..8911d48b81 --- /dev/null +++ b/board/crota/keyboard.c @@ -0,0 +1,48 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config crota_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &crota_kb; +} diff --git a/board/crota/led.c b/board/crota/led.c new file mode 100644 index 0000000000..ee8b7ad8ea --- /dev/null +++ b/board/crota/led.c @@ -0,0 +1,106 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Crota specific PWM LED settings. */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "compile_time_macros.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "pwm.h" +#include "util.h" + +#include + +#define BAT_LED_ON_LVL 100 +#define BAT_LED_OFF_LVL 0 + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 96; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + /* There are two battery leds, LED1/LED2 are on MB side. + * All leds are OFF by default. + */ + int led1_duty, led2_duty; + + led1_duty = led2_duty = BAT_LED_OFF_LVL; + + switch (color) { + case EC_LED_COLOR_AMBER: + led1_duty = BAT_LED_ON_LVL; + break; + case EC_LED_COLOR_WHITE: + led2_duty = BAT_LED_ON_LVL; + break; + default: /* LED_OFF and other unsupported colors */ + break; + } + + pwm_set_duty(PWM_CH_LED1, led1_duty); + pwm_set_duty(PWM_CH_LED2, led2_duty); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + led_auto_control(led_id, 0); + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else + led_set_color_battery(LED_OFF); + + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + /* Make sure when battery is pre-charging, the LED will blinking. + * Otherwise it will wait 30 seconds then blinking. + */ + if (led_pwr_get_state() == LED_PWRS_IDLE) { + if (charge_get_flags() & CHARGE_FLAG_EXTERNAL_POWER) + desired_state = STATE_BATTERY_ERROR; + } + return desired_state; +} diff --git a/board/crota/pwm.c b/board/crota/pwm.c new file mode 100644 index 0000000000..26da4e4f7d --- /dev/null +++ b/board/crota/pwm.c @@ -0,0 +1,57 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED2] = { + .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_LED1] = { + .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn off all the LEDs. + * Turn on the fan at 100%. + */ + pwm_enable(PWM_CH_LED1, 1); + pwm_set_duty(PWM_CH_LED1, 0); + pwm_enable(PWM_CH_LED2, 1); + pwm_set_duty(PWM_CH_LED2, 0); + + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/crota/sensors.c b/board/crota/sensors.c new file mode 100644 index 0000000000..9121976a40 --- /dev/null +++ b/board/crota/sensors.c @@ -0,0 +1,339 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_lsm6dso.h" +#include "fw_config.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_SOC] = { + .name = "TEMP_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_DDR] = { + .name = "TEMP_DDR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_AMBIENT] = { + .name = "TEMP_AMBIENT", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +static struct stprivate_data g_lis2dw12_data; +static struct lsm6dso_data lsm6dso_data; +static struct bmi_drv_data_t g_bmi260_data; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref_id_1 = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DW12, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_lis2dw12_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DW12_ADDR0, + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t bmi260_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_id_1, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; +struct motion_sensor_t bmi260_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_id_1, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, +}; + +void motion_interrupt(enum gpio_signal signal) +{ + if (get_board_id() > 1) { + if (gpio_get_level(GPIO_EC_SENSOR_STRAP) == 0) + bmi260_interrupt(signal); + else + lsm6dso_interrupt(signal); + } else + lsm6dso_interrupt(signal); +} + +static void board_update_motion_sensor_config(void) +{ + if (get_board_id() > 1 && gpio_get_level(GPIO_EC_SENSOR_STRAP) == 0) { + motion_sensors[BASE_ACCEL] = bmi260_base_accel; + motion_sensors[BASE_GYRO] = bmi260_base_gyro; + ccprints("BASE IMU is BMI260"); + } else { + ccprints("BASE IMU is LSM6DSO"); + } + + if (!board_is_convertible()) { + tablet_set_mode(0, TABLET_TRIGGER_LID); + gmr_tablet_switch_disable(); + /* Make sure tablet mode detection is not trigger by mistake. */ + gpio_set_flags(GPIO_TABLET_MODE_L, GPIO_INPUT | GPIO_PULL_UP); + /* + * Make sure we don't even try to initialize the lid accel, it + * is not present. + */ + motion_sensors[LID_ACCEL].active_mask = 0; + gpio_set_flags(GPIO_EC_ACCEL_INT_R_L, + GPIO_INPUT | GPIO_PULL_UP); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_update_motion_sensor_config, + HOOK_PRIO_INIT_I2C + 1); + +__override int sensor_board_is_lid_angle_available(void) +{ + return board_is_convertible(); +} + +static void baseboard_sensors_init(void) +{ + /* Enable gpio interrupt for lid accel sensor */ + gpio_enable_interrupt(GPIO_EC_ACCEL_INT_R_L); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_R_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_SOC] = { + .name = "SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_SOC, + }, + [TEMP_SENSOR_2_DDR] = { + .name = "DDR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_DDR, + }, + [TEMP_SENSOR_3_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER, + }, + [TEMP_SENSOR_4_AMBIENT] = { + .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_AMBIENT, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(77), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(77), \ + }, \ + .temp_fan_off = C_TO_K(24), \ + .temp_fan_max = C_TO_K(51), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +#define THERMAL_DDR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(78), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + }, \ + .temp_fan_off = C_TO_K(56), \ + .temp_fan_max = C_TO_K(59), \ + } +__maybe_unused static const struct ec_thermal_config thermal_ddr = THERMAL_DDR; + +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(86), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(89), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(86), \ + }, \ + .temp_fan_off = C_TO_K(67), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +#define THERMAL_AMBIENT \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(57), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(60), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(57), \ + }, \ + .temp_fan_off = C_TO_K(38), \ + .temp_fan_max = C_TO_K(45), \ + } +__maybe_unused static const struct ec_thermal_config thermal_ambient = + THERMAL_AMBIENT; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_DDR] = THERMAL_DDR, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, + [TEMP_SENSOR_4_AMBIENT] = THERMAL_AMBIENT, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/crota/usbc_config.c b/board/crota/usbc_config.c new file mode 100644 index 0000000000..f8e3c0704a --- /dev/null +++ b/board/crota/usbc_config.c @@ -0,0 +1,397 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +#ifdef CONFIG_ZEPHYR +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C1_NCT38XX, IOEX_PORT_COUNT }; +#endif /* CONFIG_ZEPHYR */ + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_4_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .frs_en = IOEX_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +struct usb_mux_chain soc_side_bb_retimer_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_SOC_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, +}; +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &soc_side_bb_retimer_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +#ifndef CONFIG_ZEPHYR +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C1 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C1_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_4_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); +#endif /* !CONFIG_ZEPHYR */ + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = IOEX_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C1) { + rst_signal = IOEX_USB_C1_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + enum gpio_signal tcpc_rst; + + tcpc_rst = GPIO_USB_C0_C1_TCPC_RST_ODL; + + gpio_set_level(tcpc_rst, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(tcpc_rst, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C1 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + ioex_init(IOEX_C0_NCT38XX); + ioex_init(IOEX_C1_NCT38XX); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C1_TCPC_INT_ODL); + +#ifndef CONFIG_ZEPHYR + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +#endif /* !CONFIG_ZEPHYR */ +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + if (port == USBC_PORT_C0 || port == USBC_PORT_C1) + return true; + + return false; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/crota/usbc_config.h b/board/crota/usbc_config.h new file mode 100644 index 0000000000..1fa7ad4c7a --- /dev/null +++ b/board/crota/usbc_config.h @@ -0,0 +1,17 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#ifndef CONFIG_ZEPHYR +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#endif + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/crota/vif_override.xml b/board/crota/vif_override.xml new file mode 100644 index 0000000000..db6c426f50 --- /dev/null +++ b/board/crota/vif_override.xml @@ -0,0 +1,225 @@ + + + + 2 + 0 + + + + + + + + + + + + + + TBT3 Compatible + + + 8087 + 8086 + 463E + 8087 + + + + + + + + + + + Not TBT3-Compatible + + + 8087 + 8086 + 463E + 8087 + + + + + + + + + + + + + + Gen 3 (40Gb) + + + + + + + + HBR3 + 4 Lanes + + 22500 mW + Shared + Google + 22500 mW + + USB 3.2 Gen 2x1 + + + + + + USB 3.2 Gen 2x1 + + + + + + + 3A @ 5V + + + + Fixed + 100% IOC + 5000 mV + 3000 mA + 50 msec + 3600 mA + + + + + + + + PDUSB Peripheral + PDUSB Host + + 18D1 + + + + + + + + + 8087 + + + + + + + + + 00000001 + + + + + + 0 + 0 + + + USB 3.2 Gen 2 + + + + + + + + + + + Gen 3 (40Gb) + + + + + + + + HBR3 + 4 Lanes + + 22500 mW + Shared + Google + 22500 mW + + USB 3.2 Gen 2x1 + + + + + + + USB 3.2 Gen 2x1 + + + + + + + 3A @ 5V + + + + Fixed + 100% IOC + 5000 mV + 3000 mA + 50 msec + 3600 mA + + + + + + + + + PDUSB Peripheral + PDUSB Host + + 18D1 + + + + + + + + + 8087 + + + + + + + + + 00000001 + + + + + + 0 + 0 + + + USB 3.2 Gen 2 + + diff --git a/board/dalboz/battery.c b/board/dalboz/battery.c index 5a90a767c8..e5adf3c4b3 100644 --- a/board/dalboz/battery.c +++ b/board/dalboz/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/dalboz/board.c b/board/dalboz/board.c index f0a0e23c2b..20b8a0b9a8 100644 --- a/board/dalboz/board.c +++ b/board/dalboz/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,7 +10,7 @@ #include "driver/accelgyro_lsm6dsm.h" #include "driver/bc12/pi3usb9201.h" #include "driver/ioexpander/pcal6408.h" -#include "driver/ppc/aoz1380.h" +#include "driver/ppc/aoz1380_public.h" #include "driver/ppc/nx20p348x.h" #include "driver/retimer/pi3hdx1204.h" #include "driver/tcpm/nct38xx.h" @@ -36,8 +36,8 @@ #include "usb_pd_tcpm.h" #include "usbc_ppc.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* This I2C moved. Temporarily detect and support the V0 HW. */ int I2C_PORT_BATTERY = I2C_PORT_BATTERY_V1; @@ -73,10 +73,9 @@ void hdmi_hpd_interrupt(enum gpio_signal signal) hook_call_deferred(&hdmi_hpd_handler_data, (2 * MSEC)); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#ifdef HAS_TASK_MOTIONSENSE - /* Motion sensors */ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; @@ -86,11 +85,9 @@ static struct stprivate_data g_lis2dwl_data; static struct lsm6dsm_data g_lsm6dsm_data = LSM6DSM_DATA; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* TODO(gcc >= 5.0) Remove the casts to const pointer at rot_standard_ref */ struct motion_sensor_t motion_sensors[] = { @@ -131,11 +128,9 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .default_range = 4, /* g, enough for laptop */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ .rot_standard_ref = &base_standard_ref, .min_frequency = LSM6DSM_ODR_MIN_VAL, .max_frequency = LSM6DSM_ODR_MAX_VAL, @@ -163,8 +158,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -176,11 +169,9 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#endif /* HAS_TASK_MOTIONSENSE */ - /* These IO expander GPIOs vary with DB option. */ -enum gpio_signal IOEX_USB_A1_RETIMER_EN = IOEX_USB_A1_RETIMER_EN_OPT1; -enum gpio_signal IOEX_USB_A1_CHARGE_EN_DB_L = IOEX_USB_A1_CHARGE_EN_DB_L_OPT1; +enum ioex_signal IOEX_USB_A1_RETIMER_EN = IOEX_USB_A1_RETIMER_EN_OPT1; +enum ioex_signal IOEX_USB_A1_CHARGE_EN_DB_L = IOEX_USB_A1_CHARGE_EN_DB_L_OPT1; static void pcal6408_handler(void) { @@ -196,7 +187,7 @@ void pcal6408_interrupt(enum gpio_signal signal) const struct pi3hdx1204_tuning pi3hdx1204_tuning = { .eq_ch0_ch1_offset = PI3HDX1204_EQ_DB710, .eq_ch2_ch3_offset = PI3HDX1204_EQ_DB710, - .vod_offset = PI3HDX1204_VOD_115_ALL_CHANNELS, + .vod_offset = PI3HDX1204_VOD_130_ALL_CHANNELS, .de_offset = PI3HDX1204_DE_DB_MINUS5, }; @@ -211,9 +202,7 @@ static void board_chipset_resume(void) if (ec_config_has_hdmi_retimer_pi3hdx1204()) { ioex_set_level(IOEX_EN_PWR_HDMI_DB, 1); msleep(PI3HDX1204_POWER_ON_DELAY_MS); - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - 1); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, 1); } } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); @@ -223,16 +212,13 @@ static void board_chipset_suspend(void) ioex_set_level(IOEX_USB_A1_RETIMER_EN, 0); if (ec_config_has_hdmi_retimer_pi3hdx1204()) { - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - 0); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, 0); ioex_set_level(IOEX_EN_PWR_HDMI_DB, 0); } } DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); -static int board_ps8743_mux_set(const struct usb_mux *me, - mux_state_t mux_state) +static int board_ps8743_mux_set(const struct usb_mux *me, mux_state_t mux_state) { if (mux_state & USB_PD_MUX_DP_ENABLED) /* Enable IN_HPD on the DB */ @@ -244,7 +230,6 @@ static int board_ps8743_mux_set(const struct usb_mux *me, return EC_SUCCESS; } - /***************************************************************************** * USB-C */ @@ -254,8 +239,12 @@ static int board_ps8743_mux_set(const struct usb_mux *me, * chip and it need a board specific driver. * Overall, it will use chained mux framework. */ -static int fsusb42umx_set_mux(const struct usb_mux *me, mux_state_t mux_state) +static int fsusb42umx_set_mux(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + if (mux_state & USB_PD_MUX_POLARITY_INVERTED) ioex_set_level(IOEX_USB_C0_SBU_FLIP, 1); else @@ -278,33 +267,45 @@ const struct usb_mux_driver usbc0_sbu_mux_driver = { * Since FSUSB42UMX is not a i2c device, .i2c_port and * .i2c_addr_flags are not required here. */ -const struct usb_mux usbc0_sbu_mux = { - .usb_port = USBC_PORT_C0, - .driver = &usbc0_sbu_mux_driver, +const struct usb_mux_chain usbc0_sbu_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &usbc0_sbu_mux_driver, + }, }; -struct usb_mux usbc1_amd_fp5_usb_mux = { +struct usb_mux usbc1_ps8xxx_mux = { .usb_port = USBC_PORT_C1, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .flags = USB_MUX_FLAG_SET_WITHOUT_FLIP, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PS8743_I2C_ADDR1_FLAG, + .driver = &ps8743_usb_mux_driver, +}; + +struct usb_mux_chain usbc1_amd_fp5_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + .flags = USB_MUX_FLAG_SET_WITHOUT_FLIP, + }, }; -struct usb_mux usb_muxes[] = { +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .next_mux = &usbc0_sbu_mux, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_sbu_mux, }, [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = PS8743_I2C_ADDR1_FLAG, - .driver = &ps8743_usb_mux_driver, - .next_mux = &usbc1_amd_fp5_usb_mux, + .mux = &usbc1_ps8xxx_mux, + .next = &usbc1_amd_fp5_usb_mux, } }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); @@ -347,8 +348,7 @@ void ppc_interrupt(enum gpio_signal signal) int board_set_active_charge_port(int port) { - int is_valid_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); int i; if (port == CHARGE_PORT_NONE) { @@ -369,7 +369,6 @@ int board_set_active_charge_port(int port) return EC_ERROR_INVAL; } - /* Check if the port is sourcing VBUS. */ if (ppc_is_sourcing_vbus(port)) { CPRINTFUSB("Skip enable C%d", port); @@ -451,27 +450,33 @@ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { }; BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); -static void reset_pd_port(int port, enum gpio_signal reset_gpio_l, - int hold_delay, int finish_delay) +static void reset_nct38xx_port(int port) { + enum gpio_signal reset_gpio_l; + + if (port == USBC_PORT_C0) + reset_gpio_l = GPIO_USB_C0_TCPC_RST_L; + else if (port == USBC_PORT_C1) + reset_gpio_l = GPIO_USB_C1_TCPC_RST_L; + else + /* Invalid port: do nothing */ + return; + gpio_set_level(reset_gpio_l, 0); - msleep(hold_delay); + msleep(NCT38XX_RESET_HOLD_DELAY_MS); gpio_set_level(reset_gpio_l, 1); - if (finish_delay) - msleep(finish_delay); + nct38xx_reset_notify(port); + if (NCT3807_RESET_POST_DELAY_MS != 0) + msleep(NCT3807_RESET_POST_DELAY_MS); } void board_reset_pd_mcu(void) { /* Reset TCPC0 */ - reset_pd_port(USBC_PORT_C0, GPIO_USB_C0_TCPC_RST_L, - NCT38XX_RESET_HOLD_DELAY_MS, - NCT38XX_RESET_POST_DELAY_MS); + reset_nct38xx_port(USBC_PORT_C0); /* Reset TCPC1 */ - reset_pd_port(USBC_PORT_C1, GPIO_USB_C1_TCPC_RST_L, - NCT38XX_RESET_HOLD_DELAY_MS, - NCT38XX_RESET_POST_DELAY_MS); + reset_nct38xx_port(USBC_PORT_C1); } uint16_t tcpc_get_alert_status(void) @@ -517,11 +522,11 @@ void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -535,11 +540,9 @@ int board_pd_set_frs_enable(int port, int enable) /* Use the TCPC to enable fast switch when FRS included */ if (port == USBC_PORT_C0) { - rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, - !!enable); + rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, !!enable); } else { - rv = ioex_set_level(IOEX_USB_C1_TCPC_FASTSW_CTL_EN, - !!enable); + rv = ioex_set_level(IOEX_USB_C1_TCPC_FASTSW_CTL_EN, !!enable); } return rv; @@ -549,17 +552,17 @@ static void setup_fw_config(void) { uint32_t board_version = 0; - if (cbi_get_board_version(&board_version) == EC_SUCCESS - && board_version >= 2) { + if (cbi_get_board_version(&board_version) == EC_SUCCESS && + board_version >= 2) { ccprints("PS8743 USB MUX"); - usb_muxes[USBC_PORT_C1].i2c_addr_flags = PS8743_I2C_ADDR1_FLAG; - usb_muxes[USBC_PORT_C1].driver = &ps8743_usb_mux_driver; - usb_muxes[USBC_PORT_C1].board_set = &board_ps8743_mux_set; + usbc1_ps8xxx_mux.i2c_addr_flags = PS8743_I2C_ADDR1_FLAG; + usbc1_ps8xxx_mux.driver = &ps8743_usb_mux_driver; + usbc1_ps8xxx_mux.board_set = &board_ps8743_mux_set; } else { ccprints("PS8740 USB MUX"); - usb_muxes[USBC_PORT_C1].i2c_addr_flags = PS8740_I2C_ADDR0_FLAG; - usb_muxes[USBC_PORT_C1].driver = &ps8740_usb_mux_driver; - usb_muxes[USBC_PORT_C1].board_set = NULL; + usbc1_ps8xxx_mux.i2c_addr_flags = PS8740_I2C_ADDR0_FLAG; + usbc1_ps8xxx_mux.driver = &ps8740_usb_mux_driver; + usbc1_ps8xxx_mux.board_set = NULL; } if (ec_config_get_usb_db() == DALBOZ_DB_D_OPT2_USBA_HDMI) { @@ -604,7 +607,7 @@ static void setup_fw_config(void) } else { motion_sensor_count = 0; /* Device is clamshell only */ - tablet_set_mode(0); + tablet_set_mode(0, TABLET_TRIGGER_LID); /* Gyro is not present, don't allow line to float */ gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); } @@ -626,20 +629,20 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); struct ioexpander_config_t ioex_config[] = { [IOEX_C0_NCT3807] = { .i2c_host_port = I2C_PORT_TCPC0, - .i2c_slave_addr = NCT38XX_I2C_ADDR1_1_FLAGS, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, .drv = &nct38xx_ioexpander_drv, }, [IOEX_C1_NCT3807] = { .i2c_host_port = I2C_PORT_TCPC1, - .i2c_slave_addr = NCT38XX_I2C_ADDR1_1_FLAGS, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, .drv = &nct38xx_ioexpander_drv, - .flags = IOEX_FLAGS_DISABLED, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, }, [IOEX_HDMI_PCAL6408] = { .i2c_host_port = I2C_PORT_TCPC1, - .i2c_slave_addr = PCAL6408_I2C_ADDR0, + .i2c_addr_flags = PCAL6408_I2C_ADDR0, .drv = &pcal6408_ioexpander_drv, - .flags = IOEX_FLAGS_DISABLED, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, }, }; BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); diff --git a/board/dalboz/board.h b/board/dalboz/board.h index 9fa8ac6094..0d77b7be06 100644 --- a/board/dalboz/board.h +++ b/board/dalboz/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,11 +10,11 @@ #define VARIANT_ZORK_DALBOZ -#include #include "baseboard.h" +#include + #define CONFIG_IO_EXPANDER_PCAL6408 -#define CONFIG_MKBP_USE_GPIO #define CONFIG_USBC_PPC_NX20P3483 #define CONFIG_USB_MUX_PS8740 @@ -28,15 +28,11 @@ #define GPIO_USB1_ILIM_SEL IOEX_USB_A0_CHARGE_EN_L #define GPIO_USB2_ILIM_SEL IOEX_USB_A1_CHARGE_EN_DB_L -/* Power LEDs */ -#define CONFIG_LED_POWER_LED - /* Motion sensing drivers */ #define CONFIG_ACCELGYRO_LSM6DSM #define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCEL_LIS2DWL -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_TABLET_MODE @@ -45,42 +41,36 @@ #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL - - /* GPIO mapping from board specific name to EC common name. */ -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL -#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL -#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL -#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L -#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK -#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L -#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL -#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD -#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD -#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE #ifndef __ASSEMBLER__ /* This I2C moved. Temporarily detect and support the V0 HW. */ extern int I2C_PORT_BATTERY; -enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, - ADC_TEMP_SENSOR_SOC, - ADC_CH_COUNT -}; +enum adc_channel { ADC_TEMP_SENSOR_CHARGER, ADC_TEMP_SENSOR_SOC, ADC_CH_COUNT }; enum battery_type { BATTERY_SMP, @@ -89,10 +79,7 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_COUNT }; enum ioex_port { IOEX_C0_NCT3807 = 0, @@ -101,9 +88,7 @@ enum ioex_port { IOEX_PORT_COUNT }; -#define PORT_TO_HPD(port) ((port == 0) \ - ? GPIO_USB3_C0_DP2_HPD \ - : GPIO_DP1_HPD) +#define PORT_TO_HPD(port) ((port == 0) ? GPIO_USB3_C0_DP2_HPD : GPIO_DP1_HPD) enum temp_sensor_id { TEMP_SENSOR_CHARGER = 0, @@ -112,22 +97,13 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum usba_port { - USBA_PORT_A0 = 0, - USBA_PORT_A1, - USBA_PORT_COUNT -}; +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; /***************************************************************************** * CBI EC FW Configuration */ -#include "cbi_ec_fw_config.h" /** * DALBOZ_MB_USBAC @@ -170,36 +146,32 @@ enum ec_cfg_usb_db_type { DALBOZ_DB_D_OPT2_USBA_HDMI = 1, }; -#define HAS_USBC1 \ - (BIT(DALBOZ_DB_D_OPT1_USBAC)) +#include "cbi_ec_fw_config.h" + +#define HAS_USBC1 (BIT(DALBOZ_DB_D_OPT1_USBAC)) static inline bool ec_config_has_usbc1(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1); } -#define HAS_USBC1_RETIMER_PS8740 \ - (BIT(DALBOZ_DB_D_OPT1_USBAC)) +#define HAS_USBC1_RETIMER_PS8740 (BIT(DALBOZ_DB_D_OPT1_USBAC)) static inline bool ec_config_has_usbc1_retimer_ps8740(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8740); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_PS8740); } -#define HAS_HDMI_RETIMER_PI3HDX1204 \ - (BIT(DALBOZ_DB_D_OPT2_USBA_HDMI)) +#define HAS_HDMI_RETIMER_PI3HDX1204 (BIT(DALBOZ_DB_D_OPT2_USBA_HDMI)) static inline bool ec_config_has_hdmi_retimer_pi3hdx1204(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_RETIMER_PI3HDX1204); + return !!(BIT(ec_config_get_usb_db()) & HAS_HDMI_RETIMER_PI3HDX1204); } /* These IO expander GPIOs vary with DB option. */ -extern enum gpio_signal IOEX_USB_A1_RETIMER_EN; -extern enum gpio_signal IOEX_USB_A1_CHARGE_EN_DB_L; +extern enum ioex_signal IOEX_USB_A1_RETIMER_EN; +extern enum ioex_signal IOEX_USB_A1_CHARGE_EN_DB_L; void board_reset_pd_mcu(void); diff --git a/board/dalboz/build.mk b/board/dalboz/build.mk index 4ca0cbd96f..cd58c2b91b 100644 --- a/board/dalboz/build.mk +++ b/board/dalboz/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/dalboz/ec.tasklist b/board/dalboz/ec.tasklist index 41b83cf4f3..4bb60ed55d 100644 --- a/board/dalboz/ec.tasklist +++ b/board/dalboz/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/dalboz/gpio.inc b/board/dalboz/gpio.inc index 74fe019b47..386898f013 100644 --- a/board/dalboz/gpio.inc +++ b/board/dalboz/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/dalboz/led.c b/board/dalboz/led.c index 6ef9c26e8c..d9614539e5 100644 --- a/board/dalboz/led.c +++ b/board/dalboz/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,47 +8,55 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 100; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_RED, 2 * LED_ONE_SEC} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_RED, 2 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_RED, + 2 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_RED, + 2 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + }; BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; BUILD_ASSERT(ARRAY_SIZE(led_pwr_state_table) == PWR_LED_NUM_STATES); -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_LED3_PWM, LED_ON_LVL); @@ -57,7 +65,7 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_LED3_PWM, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_GREEN: diff --git a/board/dalboz/vif_override.xml b/board/dalboz/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/dalboz/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/damu/battery.c b/board/damu/battery.c index c85240a108..2c3b259a23 100644 --- a/board/damu/battery.c +++ b/board/damu/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/damu/board.c b/board/damu/board.c index 280e834c85..3704b019cc 100644 --- a/board/damu/board.c +++ b/board/damu/board.c @@ -1,10 +1,9 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" #include "charge_manager.h" @@ -31,6 +30,7 @@ #include "it8801.h" #include "keyboard_scan.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -40,41 +40,55 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { schedule_deferred_pd_interrupt(0 /* port */); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct i2c_port_t i2c_bitbang_ports[] = { - {"battery", 2, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA, .drv = &bitbang_drv}, + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, }; const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); @@ -82,13 +96,13 @@ const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * TODO(b/133200075): Tune this once we have the final performance * out of the driver and the i2c bus. @@ -107,8 +121,8 @@ struct keyboard_scan_config keyscan_config = { struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { [0] = { - .i2c_host_port = I2C_PORT_IO_EXPANDER_IT8801, - .i2c_slave_addr = IT8801_I2C_ADDR, + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, .drv = &it8801_ioexpander_drv, }, }; @@ -133,15 +147,18 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -static void board_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -149,13 +166,16 @@ static void board_hpd_status(const struct usb_mux *me, host_set_single_event(EC_HOST_EVENT_USB_MUX); } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, }, }; @@ -201,7 +221,7 @@ int board_set_active_charge_port(int charge_port) if (board_vbus_source_enabled(charge_port)) return -1; break; - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -209,22 +229,11 @@ int board_set_active_charge_port(int charge_port) */ charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - int board_discharge_on_ac(int enable) { int ret, port; @@ -254,7 +263,7 @@ int pd_snk_is_vbus_provided(int port) void bc12_interrupt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } #ifndef VARIANT_KUKUI_NO_SENSORS @@ -274,13 +283,12 @@ static void board_spi_enable(void) STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; /* Reinitialize spi peripheral. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); /* Pin mux spi peripheral toward the sensor. */ - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_spi_enable, +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, MOTION_SENSE_HOOK_PRIO - 1); static void board_spi_disable(void) @@ -288,14 +296,13 @@ static void board_spi_disable(void) /* Set pins to a state calming the sensor down. */ gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); - gpio_config_module(MODULE_SPI_MASTER, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); /* Disable spi peripheral and clocks. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_spi_disable, +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, MOTION_SENSE_HOOK_PRIO + 1); #endif /* !VARIANT_KUKUI_NO_SENSORS */ @@ -334,17 +341,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Rotation matrixes */ -static const mat33_fp_t base_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(-1), 0}, - {0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t lid_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(1), 0}, - {0, 0, FLOAT_TO_FP(1) } -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ /* Lid accel private data */ @@ -394,9 +397,10 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = + ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .rot_standard_ref = &base_standard_ref, - .default_range = 2, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, .config = { @@ -422,7 +426,8 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = + ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_GYRO_MIN_FREQ, @@ -452,16 +457,3 @@ int board_get_charger_i2c(void) /* TODO(b:138415463): confirm the bus allocation for future builds */ return board_get_version() == 1 ? 2 : 1; } - -/* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - /* If the lid is in 360 position, ignore the lid angle, - * which might be faulty. Disable keyboard. - */ - if (tablet_get_mode() || chipset_in_state(CHIPSET_STATE_ANY_OFF)) - enable = 0; - keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); -} -#endif diff --git a/board/damu/board.h b/board/damu/board.h index e5de9c205c..64aa8404ec 100644 --- a/board/damu/board.h +++ b/board/damu/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,9 +8,13 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H +/* Save some flash space */ +#undef CONFIG_CHARGE_DEBUG + #define VARIANT_KUKUI_JACUZZI #define VARIANT_KUKUI_BATTERY_SMART #define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32F098 #ifndef SECTION_IS_RW #define VARIANT_KUKUI_NO_SENSORS @@ -18,6 +22,9 @@ #include "baseboard.h" +/* Disable deferred (async) flash protect*/ +#undef CONFIG_FLASH_PROTECT_DEFERRED + #undef CONFIG_CHIPSET_POWER_SEQ_VERSION #define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 @@ -27,6 +34,8 @@ #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_RUNTIME_CONFIG @@ -50,14 +59,12 @@ #define CONFIG_USB_MUX_IT5205 #define CONFIG_LED_ONOFF_STATES -#define CONFIG_LED_POWER_LED #define CONFIG_LED_COMMON /* Motion Sensors */ #ifndef VARIANT_KUKUI_NO_SENSORS -#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ #define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_CMD_ACCEL_INFO @@ -72,25 +79,27 @@ #endif /* VARIANT_KUKUI_NO_SENSORS */ /* I2C ports */ -#define I2C_PORT_BC12 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_BATTERY 2 -#define I2C_PORT_CHARGER board_get_charger_i2c() -#define I2C_PORT_SENSORS 1 -#define I2C_PORT_IO_EXPANDER_IT8801 1 -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_BATTERY 2 +#define I2C_PORT_CHARGER board_get_charger_i2c() +#define I2C_PORT_SENSORS 1 +#define I2C_PORT_KB_DISCRETE 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY + +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -/* Define the MKBP events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* Virutal battery optional MFG function */ +#define CONFIG_SMART_BATTERY_OPTIONAL_MFG_FUNC #ifndef __ASSEMBLER__ @@ -138,7 +147,6 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void bc12_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); /* returns the i2c port number of charger */ int board_get_charger_i2c(void); diff --git a/board/damu/build.mk b/board/damu/build.mk index 0b3565fd84..6a7e557a0e 100644 --- a/board/damu/build.mk +++ b/board/damu/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/damu/ec.tasklist b/board/damu/ec.tasklist index 19d2f34687..30e9967a0a 100644 --- a/board/damu/ec.tasklist +++ b/board/damu/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/damu/gpio.inc b/board/damu/gpio.inc index ba565b4772..9db5b49238 100644 --- a/board/damu/gpio.inc +++ b/board/damu/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -111,5 +111,5 @@ ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) /* EMMC SPI SLAVE: PB13/14/15 */ ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) /* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ -ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_MASTER, 0) -ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/damu/led.c b/board/damu/led.c index a6f27f2200..7fcda9afda 100644 --- a/board/damu/led.c +++ b/board/damu/led.c @@ -1,50 +1,60 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Damu */ #include "common.h" -#include "ioexpander.h" #include "driver/ioexpander/it8801.h" #include "ec_commands.h" +#include "ioexpander.h" #include "led_common.h" #include "led_onoff_states.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: @@ -62,7 +72,7 @@ void led_set_color_battery(enum ec_led_colors color) } } -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: @@ -76,24 +86,24 @@ void led_set_color_power(enum ec_led_colors color) void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) { - if(led_id == EC_LED_ID_BATTERY_LED) { + if (led_id == EC_LED_ID_BATTERY_LED) { brightness_range[EC_LED_COLOR_AMBER] = 1; brightness_range[EC_LED_COLOR_WHITE] = 1; - } else if(led_id == EC_LED_ID_POWER_LED) { + } else if (led_id == EC_LED_ID_POWER_LED) { brightness_range[EC_LED_COLOR_WHITE] = 1; } } int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { - if(led_id == EC_LED_ID_BATTERY_LED) { - if(brightness[EC_LED_COLOR_AMBER] != 0) + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) led_set_color_battery(EC_LED_COLOR_AMBER); - else if(brightness[EC_LED_COLOR_WHITE] != 0) + else if (brightness[EC_LED_COLOR_WHITE] != 0) led_set_color_battery(EC_LED_COLOR_WHITE); else led_set_color_battery(LED_OFF); - } else if(led_id == EC_LED_ID_POWER_LED) { + } else if (led_id == EC_LED_ID_POWER_LED) { if (brightness[EC_LED_COLOR_WHITE] != 0) led_set_color_power(EC_LED_COLOR_WHITE); else diff --git a/board/damu/vif_override.xml b/board/damu/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/damu/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/delbin/battery.c b/board/delbin/battery.c index e907a3574f..6d6ae2afad 100644 --- a/board/delbin/battery.c +++ b/board/delbin/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/delbin/board.c b/board/delbin/board.c index b7a26b683b..0e416e6e2e 100644 --- a/board/delbin/board.c +++ b/board/delbin/board.c @@ -1,19 +1,19 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "common.h" #include "accelgyro.h" +#include "button.h" #include "cbi_ec_fw_config.h" +#include "cbi_ssfc.h" +#include "common.h" #include "driver/accel_bma2x2.h" #include "driver/accelgyro_bmi260.h" #include "driver/bc12/pi3usb9201.h" #include "driver/ppc/syv682x.h" -#include "driver/retimer/bb_retimer.h" +#include "driver/retimer/ps8811.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tusb422.h" @@ -22,6 +22,7 @@ #include "fan_chip.h" #include "gpio.h" #include "hooks.h" +#include "keyboard_customization.h" #include "keyboard_scan.h" #include "lid_switch.h" #include "power.h" @@ -30,23 +31,23 @@ #include "pwm_chip.h" #include "switch.h" #include "system.h" -#include "task.h" #include "tablet_mode.h" +#include "task.h" #include "throttle_ap.h" #include "uart.h" #include "usb_mux.h" #include "usb_pd.h" -#include "usb_pd_tbt.h" #include "usb_pd_tcpm.h" #include "usbc_ppc.h" #include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Increase from 50 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* Other values should be the same as the default configuration. */ @@ -62,6 +63,28 @@ struct keyboard_scan_config keyscan_config = { }, }; +__override struct key { + uint8_t row; + uint8_t col; +} vivaldi_keys[] = { + { .row = 0, .col = 2 }, /* T1 */ + { .row = 3, .col = 2 }, /* T2 */ + { .row = 2, .col = 2 }, /* T3 */ + { .row = 1, .col = 2 }, /* T4 */ + { .row = 3, .col = 4 }, /* T5 */ + { .row = 2, .col = 4 }, /* T6 */ + { .row = 1, .col = 4 }, /* T7 */ + { .row = 2, .col = 9 }, /* T8 */ + { .row = 1, .col = 9 }, /* T9 */ + { .row = 0, .col = 4 }, /* T10 */ + { .row = 0, .col = 1 }, /* T11 */ + { .row = 1, .col = 5 }, /* T12 */ + { .row = 3, .col = 5 }, /* T13 */ + { .row = 0, .col = 9 }, /* T14 */ + { .row = 0, .col = 11 }, /* T15 */ +}; +BUILD_ASSERT(ARRAY_SIZE(vivaldi_keys) == MAX_TOP_ROW_KEYS); + /******************************************************************************/ /* * FW_CONFIG defaults for Delbin if the CBI data is not initialized. @@ -72,56 +95,35 @@ union volteer_cbi_fw_config fw_config_defaults = { static void board_init(void) { -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - if (port == USBC_PORT_C1) { - if (usb_db == DB_USB4_GEN2) { - /* - * Older boards violate 205mm trace length prior - * to connection to the re-timer and only support up - * to GEN2 speeds. - */ - return TBT_SS_U32_GEN1_GEN2; - } else if (usb_db == DB_USB4_GEN3) { - return TBT_SS_TBT_GEN3; - } + key_choose(); + + if (get_cbi_ssfc_keyboard() == SSFC_KEYBOARD_GAMING) { + keyscan_config.actual_key_mask[1] = 0xfa; + keyscan_config.actual_key_mask[4] = 0xfe; + keyscan_config.actual_key_mask[7] = 0x86; + keyscan_config.actual_key_mask[9] = 0xff; + keyscan_config.actual_key_mask[11] = 0xff; + + vivaldi_keys[0].row = 4; + vivaldi_keys[0].col = 2; + vivaldi_keys[4].row = 4; + vivaldi_keys[4].col = 4; + vivaldi_keys[5].row = 3; + vivaldi_keys[5].col = 4; + vivaldi_keys[6].row = 2; + vivaldi_keys[6].col = 4; + vivaldi_keys[9].row = 1; + vivaldi_keys[9].col = 4; } - - /* - * Thunderbolt-compatible mode not supported - * - * TODO (b/147726366): All the USB-C ports need to support same speed. - * Need to fix once USB-C feature set is known for Volteer. - */ - return TBT_SS_RES_0; -} - -__override bool board_is_tbt_usb4_port(int port) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - /* - * Volteer reference design only supports TBT & USB4 on port 1 - * if the USB4 DB is present. - * - * TODO (b/147732807): All the USB-C ports need to support same - * features. Need to fix once USB-C feature set is known for Volteer. - */ - return ((port == USBC_PORT_C1) - && ((usb_db == DB_USB4_GEN2) || (usb_db == DB_USB4_GEN3))); } +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_PRE_DEFAULT); /******************************************************************************/ /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -154,17 +156,22 @@ const struct fan_t fans[FAN_CH_COUNT] = { * 130 C. However, sensor is located next to DDR, so we need to use the lower * DDR temperature limit (85 C) */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(65), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; /* * Inductor limits - used for both charger and PP3300 regulator @@ -177,24 +184,29 @@ const static struct ec_thermal_config thermal_cpu = { * Inductors: limit of 125c * PCB: limit is 80c */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(65), \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -279,61 +291,6 @@ const struct pwm_t pwm_channels[] = { }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -static const struct tcpc_config_t tcpc_config_p0_usb3 = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .flags = TCPC_FLAGS_TCPCI_REV2_0 | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, - .drv = &ps8xxx_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), -}; - -static const struct tcpc_config_t tcpc_config_p1_usb3 = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .flags = TCPC_FLAGS_TCPCI_REV2_0 | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, - .drv = &ps8xxx_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), -}; - -static const struct usb_mux usbc0_usb3_mb_retimer = { - .usb_port = USBC_PORT_C0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .next_mux = NULL, -}; - -static const struct usb_mux mux_config_p0_usb3 = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc0_usb3_mb_retimer, -}; - -static const struct usb_mux usbc1_usb3_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .next_mux = NULL, -}; - -static const struct usb_mux mux_config_p1_usb3 = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb3_db_retimer, -}; - -static const struct bb_usb_control bb_p0_control = { - .usb_ls_en_gpio = GPIO_USB_C0_LS_EN, - .retimer_rst_gpio = GPIO_USB_C0_RT_RST_ODL, -}; - /******************************************************************************/ /* USB-A charging control */ @@ -358,44 +315,33 @@ static void ps8815_reset(int port) } gpio_set_level(ps8xxx_rst_odl, 0); - msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, - PS8815_PWR_H_RST_H_DELAY_MS)); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); gpio_set_level(ps8xxx_rst_odl, 1); msleep(PS8815_FW_INIT_DELAY_MS); CPRINTS("[C%d] %s: patching ps8815 registers", port, __func__); - if (i2c_read8(i2c_port, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) + if (i2c_read8(i2c_port, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) CPRINTS("ps8815: reg 0x0f was %02x", val); - if (i2c_write8(i2c_port, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, 0x31) == EC_SUCCESS) + if (i2c_write8(i2c_port, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, 0x31) == + EC_SUCCESS) CPRINTS("ps8815: reg 0x0f set to 0x31"); - if (i2c_read8(i2c_port, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) + if (i2c_read8(i2c_port, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) CPRINTS("ps8815: reg 0x0f now %02x", val); } void board_reset_pd_mcu(void) { ps8815_reset(USBC_PORT_C0); - usb_mux_hpd_update(USBC_PORT_C0, 0, 0); + usb_mux_hpd_update(USBC_PORT_C0, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); ps8815_reset(USBC_PORT_C1); - usb_mux_hpd_update(USBC_PORT_C1, 0, 0); -} - -__override void board_cbi_init(void) -{ - /* Config MB USB3 */ - tcpc_config[USBC_PORT_C0] = tcpc_config_p0_usb3; - usb_muxes[USBC_PORT_C0] = mux_config_p0_usb3; - bb_controls[USBC_PORT_C0] = bb_p0_control; - - /* Config DB USB3 */ - tcpc_config[USBC_PORT_C1] = tcpc_config_p1_usb3; - usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3; + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } /******************************************************************************/ @@ -425,6 +371,7 @@ void ppc_interrupt(enum gpio_signal signal) break; case GPIO_USB_C1_PPC_INT_ODL: syv682x_interrupt(USBC_PORT_C1); + break; default: break; } @@ -447,12 +394,40 @@ static const struct ec_response_keybd_config delbin_kb = { .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, }; -__override const struct ec_response_keybd_config -*board_vivaldi_keybd_config(void) +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) { return &delbin_kb; } +static void ps8811_init(void) +{ + int rv; + + /* Set Channel A output swing to Level1 */ + rv = i2c_write8(I2C_PORT_USB_1_MIX, + PS8811_I2C_ADDR_FLAGS0 + PS8811_REG_PAGE1, 0x66, 0x10); + /* Set 50 ohm termination adjuct for B channel: -9%*/ + rv |= i2c_write8(I2C_PORT_USB_1_MIX, + PS8811_I2C_ADDR_FLAGS0 + PS8811_REG_PAGE1, 0x73, 0x04); + /* Set Channel B output swing to Level3 */ + rv |= i2c_write8(I2C_PORT_USB_1_MIX, + PS8811_I2C_ADDR_FLAGS0 + PS8811_REG_PAGE1, 0xA4, 0x03); + /* Set PS level for B channel */ + rv |= i2c_write8(I2C_PORT_USB_1_MIX, + PS8811_I2C_ADDR_FLAGS0 + PS8811_REG_PAGE1, 0xA5, 0x84); + /* Set DE level for B channel */ + rv |= i2c_write8(I2C_PORT_USB_1_MIX, + PS8811_I2C_ADDR_FLAGS0 + PS8811_REG_PAGE1, 0xA6, 0x16); +} + +/* Called on AP S5 -> S0ix transition */ +static void board_chipset_startup(void) +{ + ps8811_init(); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + /* Called on AP S0ix -> S0 transition */ static void board_chipset_resume(void) { @@ -483,24 +458,26 @@ BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); /******************************************************************************/ /* USBC TCPC configuration */ -struct tcpc_config_t tcpc_config[] = { +const struct tcpc_config_t tcpc_config[] = { [USBC_PORT_C0] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C0, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, }, [USBC_PORT_C1] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C1, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, }, }; BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); @@ -508,37 +485,45 @@ BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); /******************************************************************************/ /* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, +static const struct usb_mux_chain usbc0_usb3_mb_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, }; -struct usb_mux usb_muxes[] = { - [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, - }, + +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, }; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); -struct bb_usb_control bb_controls[] = { +const struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - /* USB-C port 0 doesn't have a retimer */ + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc0_usb3_mb_retimer, }, [USBC_PORT_C1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, }, }; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); static void board_tcpc_init(void) { diff --git a/board/delbin/board.h b/board/delbin/board.h index 7b94edf039..50759b74d2 100644 --- a/board/delbin/board.h +++ b/board/delbin/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,11 +11,17 @@ /* Baseboard features */ #include "baseboard.h" +/* + * The RAM and flash size combination on the NPCX797FC dose not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + #undef NPCX_PWM1_SEL -#define NPCX_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ /* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ +#undef CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ #define CONFIG_VBOOT_EFS2 @@ -28,72 +34,61 @@ #define CONFIG_POWER_PP5000_CONTROL /* LED defines */ -#define CONFIG_LED_POWER_LED #define CONFIG_LED_ONOFF_STATES /* Keyboard features */ #define CONFIG_KEYBOARD_VIVALDI #define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_CUSTOMIZATION +#define CONFIG_KEYBOARD_MULTIPLE /* Sensors */ /* BMA253 accelerometer in base */ #define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCEL_KX022 /* BMI260 accel/gyro in base */ #define CONFIG_ACCELGYRO_BMI260 #define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL /* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ /* * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C - * cables only support up to 60W. + * cables only support up to 60W, the limitation of 45W is for the delbin + * board. */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 -/* Enabling Thunderbolt-compatible mode */ -#define CONFIG_USB_PD_TBT_COMPAT_MODE - -/* Enabling USB4 mode */ -#define CONFIG_USB_PD_USB4 -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 +#undef CONFIG_USB_PD_TCPC_RUNTIME_CONFIG +#undef CONFIG_USB_MUX_RUNTIME_CONFIG /* USB Type A Features */ -#define USB_PORT_COUNT 1 +#define USB_PORT_COUNT 1 #define CONFIG_USB_PORT_POWER_DUMB /* USBC PPC*/ #define CONFIG_USBC_PPC_SYV682X - /* BC 1.2 */ /* Volume Button feature */ @@ -101,8 +96,12 @@ /* Fan features */ /* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +/* Retimer */ +#undef CONFIG_USBC_RETIMER_INTEL_BB +#undef CONFIG_USBC_RETIMER_INTEL_BB_RUNTIME_CONFIG /* * Macros for GPIO signals used in common code that don't match the @@ -110,46 +109,43 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_UART2_EC_RX -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_UART2_EC_RX +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL /* I2C Bus Configuration */ #define CONFIG_I2C -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM - -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER #ifndef __ASSEMBLER__ @@ -161,11 +157,7 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -enum pwm_channel { - PWM_CH_FAN = 0, - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_FAN = 0, PWM_CH_KBLIGHT, PWM_CH_COUNT }; enum sensor_id { LID_ACCEL = 0, @@ -174,13 +166,10 @@ enum sensor_id { SENSOR_COUNT, }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; void board_reset_pd_mcu(void); +void motion_interrupt(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ diff --git a/board/delbin/build.mk b/board/delbin/build.mk index b78172d3cf..26007095af 100644 --- a/board/delbin/build.mk +++ b/board/delbin/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,10 +8,12 @@ CHIP:=npcx CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc + +CHIP_VARIANT:=npcx7m7fc BASEBOARD:=volteer board-y=board.o board-y+=battery.o board-y+=led.o board-y+=sensors.o +board-$(CONFIG_KEYBOARD_CUSTOMIZATION)+=keyboard_customization.o diff --git a/board/delbin/ec.tasklist b/board/delbin/ec.tasklist index 292de51cdb..c29125d517 100644 --- a/board/delbin/ec.tasklist +++ b/board/delbin/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,6 +16,7 @@ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/delbin/gpio.inc b/board/delbin/gpio.inc index 3ac9d81092..f229e50dcc 100644 --- a/board/delbin/gpio.inc +++ b/board/delbin/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -25,7 +25,7 @@ GPIO_INT(DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) /* Sensor Interrupts */ -GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi260_interrupt) +GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) /* * Lid g-sensor interrupt unused on Delbin, configure as regular input for @@ -173,3 +173,6 @@ ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = GPIO01 = H1_EC_PWR_BTN_ODL GPIO02 = EC_RST_ODL */ +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ diff --git a/board/delbin/keyboard_customization.c b/board/delbin/keyboard_customization.c new file mode 100644 index 0000000000..3ee81cb093 --- /dev/null +++ b/board/delbin/keyboard_customization.c @@ -0,0 +1,169 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "gpio.h" +#include "keyboard_8042_sharedlib.h" +#include "keyboard_config.h" +#include "keyboard_customization.h" +#include "keyboard_protocol.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" + +static uint16_t (*scancode_set2)[KEYBOARD_ROWS]; + +static uint16_t KB2scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 0x0000, 0x0000, 0x0014, 0xe01f, 0xe014, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0076, 0x0000, 0x000e, 0x001c, 0x003a, 0x000d, 0x0016 }, + { 0x006c, 0x000c, 0x0004, 0x0006, 0x0005, 0xe071, 0x0026, 0x002a }, + { 0x0032, 0x0034, 0x002c, 0x002e, 0x002b, 0x0029, 0x0025, 0x002d }, + { 0xe01f, 0x0009, 0x0083, 0x000b, 0x0003, 0x0041, 0x001e, 0x001d }, + { 0x0051, 0x0000, 0x005b, 0x0000, 0x0042, 0x0022, 0x003e, 0x0043 }, + { 0x0031, 0x0033, 0x0035, 0x0036, 0x003b, 0x001b, 0x003d, 0x003c }, + { 0x0000, 0x0012, 0x0061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0059 }, + { 0x0055, 0x0052, 0x0054, 0x004e, 0x004c, 0x0024, 0x0044, 0x004d }, + { 0x0045, 0x0001, 0x000a, 0x002f, 0x004b, 0x0049, 0x0046, 0x001a }, + { 0xe011, 0x0000, 0x006a, 0x0000, 0x005d, 0x0000, 0x0011, 0x0000 }, + { 0xe07a, 0x005d, 0xe075, 0x006b, 0x005a, 0xe072, 0x004a, 0x0066 }, + { 0xe06b, 0xe074, 0xe069, 0x0067, 0xe06c, 0x0064, 0x0015, 0xe07d }, + { 0x0073, 0x007c, 0x007b, 0x0074, 0x0071, 0xe04a, 0x0070, 0x0021 }, + { 0x0023, 0xe05a, 0x0075, 0x0079, 0x007a, 0x0072, 0x007D, 0x0069 }, +}; + +/* The standard Chrome OS keyboard matrix table in scan code set 2. */ +static uint16_t KB1scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 0x0000, 0x0000, 0x0014, 0xe01f, 0xe014, 0xe007, 0x0000, 0x0000 }, + { 0xe01f, 0x0076, 0x000d, 0x000e, 0x001c, 0x001a, 0x0016, 0x0015 }, + { 0x0005, 0x000c, 0x0004, 0x0006, 0x0023, 0x0021, 0x0026, 0x0024 }, + { 0x0032, 0x0034, 0x002c, 0x002e, 0x002b, 0x002a, 0x0025, 0x002d }, + { 0x0009, 0x0083, 0x000b, 0x0003, 0x001b, 0x0022, 0x001e, 0x001d }, + { 0x0051, 0x0000, 0x005b, 0x0000, 0x0042, 0x0041, 0x003e, 0x0043 }, + { 0x0031, 0x0033, 0x0035, 0x0036, 0x003b, 0x003a, 0x003d, 0x003c }, + { 0x0000, 0x0000, 0x0061, 0x0000, 0x0000, 0x0012, 0x0000, 0x0059 }, + { 0x0055, 0x0052, 0x0054, 0x004e, 0x004c, 0x004a, 0x0045, 0x004d }, + { 0x0000, 0x0001, 0x000a, 0x002f, 0x004b, 0x0049, 0x0046, 0x0044 }, + { 0xe011, 0x0000, 0x006a, 0x0000, 0x005d, 0x0000, 0x0011, 0x0000 }, +#ifndef CONFIG_KEYBOARD_KEYPAD + { 0x0000, 0x0066, 0x0000, 0x005d, 0x005a, 0x0029, 0xe072, 0xe075 }, + { 0x0000, 0x0064, 0x0000, 0x0067, 0x0000, 0x0000, 0xe074, 0xe06b }, +#else + { 0x0000, 0x0066, 0xe071, 0x005d, 0x005a, 0x0029, 0xe072, 0xe075 }, + { 0xe06c, 0x0064, 0xe07d, 0x0067, 0xe069, 0xe07a, 0xe074, 0xe06b }, + { 0xe04a, 0x007c, 0x007b, 0x0074, 0x0071, 0x0073, 0x006b, 0x0070 }, + { 0x006c, 0x0075, 0x007d, 0x0079, 0x007a, 0x0072, 0x0069, 0xe05a }, +#endif +}; + +uint16_t get_scancode_set2(uint8_t row, uint8_t col) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) { + return *(*(scancode_set2 + col) + row); + } + return 0; +} + +void set_scancode_set2(uint8_t row, uint8_t col, uint16_t val) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) { + *(*(scancode_set2 + col) + row) = val; + } +} + +void board_keyboard_drive_col(int col) +{ + /* Drive all lines to high */ + if (col == KEYBOARD_COLUMN_NONE) + gpio_set_level(GPIO_KBD_KSO2, 0); + + /* Set KBSOUT to zero to detect key-press */ + else if (col == KEYBOARD_COLUMN_ALL) + gpio_set_level(GPIO_KBD_KSO2, 1); + + /* Drive one line for detection */ + else { + if (col == 2) + gpio_set_level(GPIO_KBD_KSO2, 1); + else + gpio_set_level(GPIO_KBD_KSO2, 0); + } +} + +struct keyboard_type key_typ = { + .col_esc = KEYBOARD_COL_ESC, + .row_esc = KEYBOARD_ROW_ESC, + .col_down = KEYBOARD_COL_DOWN, + .row_down = KEYBOARD_ROW_DOWN, + .col_left_shift = KEYBOARD_COL_LEFT_SHIFT, + .row_left_shift = KEYBOARD_ROW_LEFT_SHIFT, + .col_refresh = KEYBOARD_COL_REFRESH, + .row_refresh = KEYBOARD_ROW_REFRESH, + .col_right_alt = KEYBOARD_COL_RIGHT_ALT, + .row_right_alt = KEYBOARD_ROW_RIGHT_ALT, + .col_left_alt = KEYBOARD_COL_LEFT_ALT, + .row_left_alt = KEYBOARD_ROW_LEFT_ALT, + .col_key_r = KEYBOARD_COL_KEY_R, + .row_key_r = KEYBOARD_ROW_KEY_R, + .col_key_h = KEYBOARD_COL_KEY_H, + .row_key_h = KEYBOARD_ROW_KEY_H, +}; + +int keyboard_choose(void) +{ + if (get_cbi_ssfc_keyboard() == SSFC_KEYBOARD_GAMING) + return 1; + + return 0; +} + +void key_choose(void) +{ + if (keyboard_choose() == 1) { + key_typ.col_esc = KEYBOARD2_COL_ESC; + key_typ.row_esc = KEYBOARD2_ROW_ESC; + key_typ.col_down = KEYBOARD2_COL_DOWN; + key_typ.row_down = KEYBOARD2_ROW_DOWN; + key_typ.col_left_shift = KEYBOARD2_COL_LEFT_SHIFT; + key_typ.row_left_shift = KEYBOARD2_ROW_LEFT_SHIFT; + key_typ.col_refresh = KEYBOARD2_COL_REFRESH; + key_typ.row_refresh = KEYBOARD2_ROW_REFRESH; + key_typ.col_right_alt = KEYBOARD2_COL_RIGHT_ALT; + key_typ.row_right_alt = KEYBOARD2_ROW_RIGHT_ALT; + key_typ.col_left_alt = KEYBOARD2_COL_LEFT_ALT; + key_typ.row_left_alt = KEYBOARD2_ROW_LEFT_ALT; + key_typ.col_key_r = KEYBOARD2_COL_KEY_R; + key_typ.row_key_r = KEYBOARD2_ROW_KEY_R; + key_typ.col_key_h = KEYBOARD2_COL_KEY_H; + key_typ.row_key_h = KEYBOARD2_ROW_KEY_H; + + boot_key_list[0].col = KEYBOARD2_COL_ESC; + boot_key_list[0].row = KEYBOARD2_ROW_ESC; + boot_key_list[1].col = KEYBOARD2_COL_DOWN; + boot_key_list[1].row = KEYBOARD2_ROW_DOWN; + boot_key_list[2].col = KEYBOARD2_COL_LEFT_SHIFT; + boot_key_list[2].row = KEYBOARD2_ROW_LEFT_SHIFT; + + scancode_set2 = KB2scancode_set2; + } else { + key_typ.col_esc = KEYBOARD_COL_ESC; + key_typ.row_esc = KEYBOARD_ROW_ESC; + key_typ.col_down = KEYBOARD_COL_DOWN; + key_typ.row_down = KEYBOARD_ROW_DOWN; + key_typ.col_left_shift = KEYBOARD_COL_LEFT_SHIFT; + key_typ.row_left_shift = KEYBOARD_ROW_LEFT_SHIFT; + key_typ.col_refresh = KEYBOARD_COL_REFRESH; + key_typ.row_refresh = KEYBOARD_ROW_REFRESH; + key_typ.col_right_alt = KEYBOARD_COL_RIGHT_ALT; + key_typ.row_right_alt = KEYBOARD_ROW_RIGHT_ALT; + key_typ.col_left_alt = KEYBOARD_COL_LEFT_ALT; + key_typ.row_left_alt = KEYBOARD_ROW_LEFT_ALT; + key_typ.col_key_r = KEYBOARD_COL_KEY_R; + key_typ.row_key_r = KEYBOARD_ROW_KEY_R; + key_typ.col_key_h = KEYBOARD_COL_KEY_H; + key_typ.row_key_h = KEYBOARD_ROW_KEY_H; + + scancode_set2 = KB1scancode_set2; + } +} diff --git a/board/delbin/keyboard_customization.h b/board/delbin/keyboard_customization.h new file mode 100644 index 0000000000..bfe5c3b584 --- /dev/null +++ b/board/delbin/keyboard_customization.h @@ -0,0 +1,130 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Keyboard configuration */ + +#ifndef __KEYBOARD_CUSTOMIZATION_H +#define __KEYBOARD_CUSTOMIZATION_H + +/* + * KEYBOARD_COLS_MAX has the build time column size. It's used to allocate + * exact spaces for arrays. Actual keyboard scanning is done using + * keyboard_cols, which holds a runtime column size. + */ +#define KEYBOARD_COLS_MAX 16 +#define KEYBOARD_ROWS 8 + +/* + * WARNING: Do not directly modify it. You should call keyboard_raw_set_cols, + * instead. It checks whether you're eligible or not. + */ +extern uint8_t keyboard_cols; + +#define KEYBOARD_ROW_TO_MASK(r) (1 << (r)) + +#define KEYBOARD_COL_DOWN 11 +#define KEYBOARD_ROW_DOWN 6 +#define KEYBOARD_MASK_DOWN KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_DOWN) +#define KEYBOARD_COL_ESC 1 +#define KEYBOARD_ROW_ESC 1 +#define KEYBOARD_MASK_ESC KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_ESC) +#define KEYBOARD_COL_KEY_H 6 +#define KEYBOARD_ROW_KEY_H 1 +#define KEYBOARD_MASK_KEY_H KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_H) +#define KEYBOARD_COL_KEY_R 3 +#define KEYBOARD_ROW_KEY_R 7 +#define KEYBOARD_MASK_KEY_R KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_R) +#define KEYBOARD_COL_LEFT_ALT 10 +#define KEYBOARD_ROW_LEFT_ALT 6 +#define KEYBOARD_MASK_LEFT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_ALT) +#define KEYBOARD_COL_REFRESH 2 +#ifdef CONFIG_KEYBOARD_REFRESH_ROW3 +#define KEYBOARD_ROW_REFRESH 3 +#else +#define KEYBOARD_ROW_REFRESH 2 +#endif +#define KEYBOARD_MASK_REFRESH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_REFRESH) +#define KEYBOARD_COL_RIGHT_ALT 10 +#define KEYBOARD_ROW_RIGHT_ALT 0 +#define KEYBOARD_MASK_RIGHT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_ALT) +#define KEYBOARD_DEFAULT_COL_VOL_UP 4 +#define KEYBOARD_DEFAULT_ROW_VOL_UP 0 +#define KEYBOARD_COL_LEFT_CTRL 0 +#define KEYBOARD_ROW_LEFT_CTRL 2 +#define KEYBOARD_MASK_LEFT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_CTRL) +#define KEYBOARD_COL_RIGHT_CTRL 0 +#define KEYBOARD_ROW_RIGHT_CTRL 4 +#define KEYBOARD_MASK_RIGHT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_CTRL) +#define KEYBOARD_COL_SEARCH 1 +#define KEYBOARD_ROW_SEARCH 0 +#define KEYBOARD_MASK_SEARCH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_SEARCH) +#define KEYBOARD_COL_KEY_0 8 +#define KEYBOARD_ROW_KEY_0 6 +#define KEYBOARD_MASK_KEY_0 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_0) +#define KEYBOARD_COL_KEY_1 1 +#define KEYBOARD_ROW_KEY_1 6 +#define KEYBOARD_MASK_KEY_1 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_1) +#define KEYBOARD_COL_KEY_2 4 +#define KEYBOARD_ROW_KEY_2 6 +#define KEYBOARD_MASK_KEY_2 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_2) +#define KEYBOARD_COL_LEFT_SHIFT 7 +#define KEYBOARD_ROW_LEFT_SHIFT 5 +#define KEYBOARD_MASK_LEFT_SHIFT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_SHIFT) +#ifdef CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2 +#define KEYBOARD_MASK_PWRBTN KEYBOARD_ROW_TO_MASK(2) +#elif defined(CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI3) +#define KEYBOARD_MASK_PWRBTN KEYBOARD_ROW_TO_MASK(3) +#endif + +/* Columns and masks for keys we particularly care about */ +#define KEYBOARD2_COL_DOWN 11 +#define KEYBOARD2_ROW_DOWN 5 +#define KEYBOARD2_MASK_DOWN KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_DOWN) +#define KEYBOARD2_COL_ESC 1 +#define KEYBOARD2_ROW_ESC 1 +#define KEYBOARD2_MASK_ESC KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_ESC) +#define KEYBOARD2_COL_KEY_H 6 +#define KEYBOARD2_ROW_KEY_H 1 +#define KEYBOARD2_MASK_KEY_H KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_KEY_H) +#define KEYBOARD2_COL_KEY_R 3 +#define KEYBOARD2_ROW_KEY_R 7 +#define KEYBOARD2_MASK_KEY_R KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_KEY_R) +#define KEYBOARD2_COL_LEFT_ALT 10 +#define KEYBOARD2_ROW_LEFT_ALT 6 +#define KEYBOARD2_MASK_LEFT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_LEFT_ALT) +#define KEYBOARD2_COL_REFRESH 2 +#define KEYBOARD2_ROW_REFRESH 3 +#define KEYBOARD2_MASK_REFRESH KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_REFRESH) +#define KEYBOARD2_COL_RIGHT_ALT 10 +#define KEYBOARD2_ROW_RIGHT_ALT 0 +#define KEYBOARD2_MASK_RIGHT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_RIGHT_ALT) +#define KEYBOARD2_DEFAULT_COL_VOL_UP 4 +#define KEYBOARD2_DEFAULT_ROW_VOL_UP 1 +#define KEYBOARD2_COL_LEFT_CTRL 0 +#define KEYBOARD2_ROW_LEFT_CTRL 2 +#define KEYBOARD2_MASK_LEFT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_LEFT_CTRL) +#define KEYBOARD2_COL_RIGHT_CTRL 0 +#define KEYBOARD2_ROW_RIGHT_CTRL 4 +#define KEYBOARD2_MASK_RIGHT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_RIGHT_CTRL) +#define KEYBOARD2_COL_SEARCH 4 +#define KEYBOARD2_ROW_SEARCH 0 +#define KEYBOARD2_MASK_SEARCH KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_SEARCH) +#define KEYBOARD2_COL_KEY_0 9 +#define KEYBOARD2_ROW_KEY_0 0 +#define KEYBOARD2_MASK_KEY_0 KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_KEY_0) +#define KEYBOARD2_COL_KEY_1 1 +#define KEYBOARD2_ROW_KEY_1 7 +#define KEYBOARD2_MASK_KEY_1 KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_KEY_1) +#define KEYBOARD2_COL_KEY_2 4 +#define KEYBOARD2_ROW_KEY_2 6 +#define KEYBOARD2_MASK_KEY_2 KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_KEY_2) +#define KEYBOARD2_COL_LEFT_SHIFT 7 +#define KEYBOARD2_ROW_LEFT_SHIFT 1 +#define KEYBOARD2_MASK_LEFT_SHIFT KEYBOARD_ROW_TO_MASK(KEYBOARD2_ROW_LEFT_SHIFT) + +int keyboard_choose(void); +void key_choose(void); + +#endif /* __KEYBOARD_CUSTOMIZATION_H */ diff --git a/board/delbin/led.c b/board/delbin/led.c index fb61d35574..299071818b 100644 --- a/board/delbin/led.c +++ b/board/delbin/led.c @@ -1,44 +1,53 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; - -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_1 = 5; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override const int led_charge_lvl_2 = 95; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, @@ -47,7 +56,7 @@ const enum ec_led_id supported_led_ids[] = { const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -65,7 +74,7 @@ void led_set_color_battery(enum ec_led_colors color) } } -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); @@ -102,4 +111,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/delbin/sensors.c b/board/delbin/sensors.c index d5413769d5..e8d2034015 100644 --- a/board/delbin/sensors.c +++ b/board/delbin/sensors.c @@ -1,19 +1,25 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer family-specific sensor configuration */ -#include "common.h" #include "accelgyro.h" +#include "cbi_ec_fw_config.h" +#include "cbi_ssfc.h" +#include "common.h" #include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi_common.h" +#include "driver/accel_kionix.h" #include "driver/accelgyro_bmi260.h" -#include "keyboard_scan.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "gpio.h" #include "hooks.h" #include "i2c.h" -#include "task.h" +#include "keyboard_scan.h" #include "tablet_mode.h" +#include "task.h" #include "util.h" /******************************************************************************/ @@ -21,23 +27,97 @@ static struct mutex g_lid_accel_mutex; static struct mutex g_base_mutex; -/* BMA253 private data */ +/* sensor private data */ static struct accelgyro_saved_data_t g_bma253_data; - -/* BMI260 private data */ +static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi260_data; +static struct icm_drv_data_t g_icm426xx_data; /* Rotation matrix for the lid accelerometer */ -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t base_standard_ref_icm = { + { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) }, }; -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(1)} +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, }; struct motion_sensor_t motion_sensors[] = { @@ -115,30 +195,30 @@ struct motion_sensor_t motion_sensors[] = { }; unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -static void baseboard_sensors_init(void) +void motion_interrupt(enum gpio_signal signal) { - /* Note - BMA253 interrupt unused by EC */ - - /* Enable interrupt for the BMI260 accel/gyro sensor */ - gpio_enable_interrupt(GPIO_EC_IMU_INT_L); + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) + icm426xx_interrupt(signal); + else + bmi260_interrupt(signal); } -DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +static void baseboard_sensors_init(void) { - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LID_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + ccprints("LID_ACCEL is KX022"); + } else + ccprints("LID_ACCEL is BMA253"); - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE ACCEL is ICM426XX"); + } else + ccprints("BASE ACCEL IS BMI260"); + + /* Enable interrupt for the accel/gyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_L); } -#endif +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); diff --git a/board/delbin/vif_override.xml b/board/delbin/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/delbin/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/dewatt/battery.c b/board/dewatt/battery.c new file mode 100644 index 0000000000..9b3e15cfcf --- /dev/null +++ b/board/dewatt/battery.c @@ -0,0 +1,63 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" + +/* + * Battery info for all Guybrush battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* AP19B8M */ + [BATTERY_AP19B8M] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G024", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 13350, + .voltage_normal = 11610, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AP19B8M; diff --git a/board/dewatt/board.c b/board/dewatt/board.c new file mode 100644 index 0000000000..14b646144f --- /dev/null +++ b/board/dewatt/board.c @@ -0,0 +1,451 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush board-specific configuration */ + +#include "adc.h" +#include "base_fw_config.h" +#include "battery.h" +#include "board_fw_config.h" +#include "builtin/assert.h" +#include "button.h" +#include "charger.h" +#include "common.h" +#include "cros_board_info.h" +#include "driver/accel_bma422.h" +#include "driver/accelgyro_bmi260.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/retimer/ps8811.h" +#include "driver/retimer/ps8818_public.h" +#include "driver/temp_sensor/pct2075.h" +#include "driver/temp_sensor/sb_tsi.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_8042.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "temp_sensor/pct2075.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" +#include "usb_mux.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Motion sensor mutex */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Motion sensor private data */ +static struct bmi_drv_data_t g_bmi_data; +static struct accelgyro_saved_data_t g_bma422_data; + +/* Matrix to rotate accelrator into standard reference frame */ +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +struct motion_sensor_t motion_sensors[] = { + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, + }, + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_PRIMARY, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .default_range = 2, /* g, enough for laptop. */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +__override enum ec_error_list +board_a1_ps8811_retimer_init(const struct usb_mux *me) +{ + /* Set channel A output swing */ + RETURN_ERROR(ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, PS8811_REG1_USB_CHAN_A_SWING, + PS8811_CHAN_A_SWING_MASK, 0x2 << PS8811_CHAN_A_SWING_SHIFT)); + + /* Set channel B output swing */ + RETURN_ERROR(ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, PS8811_REG1_USB_CHAN_B_SWING, + PS8811_CHAN_B_SWING_MASK, 0x2 << PS8811_CHAN_B_SWING_SHIFT)); + + /* Set channel B de-emphasis to -6dB and pre-shoot to 1.5 dB */ + RETURN_ERROR(ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, PS8811_REG1_USB_CHAN_B_DE_PS_LSB, + PS8811_CHAN_B_DE_PS_LSB_MASK, PS8811_CHAN_B_DE_6_PS_1_5_LSB)); + + RETURN_ERROR(ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, PS8811_REG1_USB_CHAN_B_DE_PS_MSB, + PS8811_CHAN_B_DE_PS_MSB_MASK, PS8811_CHAN_B_DE_6_PS_1_5_MSB)); + + return EC_SUCCESS; +} + +__override int board_c1_ps8818_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + /* Set the RX input termination */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_RX_PHY, + PS8818_RX_INPUT_TERM_MASK, + PS8818_RX_INPUT_TERM_112_OHM); + if (rv) + return rv; + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* Boost the DP gain */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_DPEQ_LEVEL, + PS8818_DPEQ_LEVEL_UP_MASK, + PS8818_DPEQ_LEVEL_UP_19DB); + if (rv) + return rv; + + /* Enable HPD on the DB */ + ioex_set_level(IOEX_USB_C1_IN_HPD, 1); + } else { + /* Disable HPD on the DB */ + ioex_set_level(IOEX_USB_C1_IN_HPD, 0); + } + + return rv; +} + +/* + * ANX7491(A1) and ANX7451(C1) are on the same i2c bus. Both default + * to 0x29 for the USB i2c address. This moves ANX7451(C1) USB i2c + * address to 0x2A. ANX7491(A1) will stay at the default 0x29. + */ +uint16_t board_anx7451_get_usb_i2c_addr(const struct usb_mux *me) +{ + ASSERT(me->usb_port == USBC_PORT_C1); + return 0x2a; +} + +/* + * Base Gyro Sensor dynamic configuration + */ +static int base_gyro_config; + +static void board_update_motion_sensor_config(void) +{ + if (board_is_convertible()) { + base_gyro_config = BASE_GYRO_BMI260; + ccprints("BASE GYRO is BMI260"); + + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable Base Accel and Gyro interrupt */ + gpio_enable_interrupt(GPIO_6AXIS_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + } +} + +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_gyro_config) { + case BASE_GYRO_BMI260: + default: + bmi260_interrupt(signal); + break; + } +} + +static void board_init(void) +{ + board_update_motion_sensor_config(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_chipset_startup(void) +{ + if (get_board_version() > 1) + pct2075_init(); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +int board_get_soc_temp_k(int idx, int *temp_k) +{ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + + return pct2075_get_val_k(idx, temp_k); +} + +int board_get_soc_temp_mk(int *temp_mk) +{ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + + return pct2075_get_val_mk(PCT2075_SOC, temp_mk); +} + +int board_get_ambient_temp_mk(int *temp_mk) +{ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + + return pct2075_get_val_mk(PCT2075_AMB, temp_mk); +} + +/* ADC Channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_SOC] = { + .name = "SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_CHARGER] = { + .name = "CHARGER", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_MEMORY] = { + .name = "MEMORY", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_CORE_IMON1] = { + .name = "CORE_I", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SOC_IMON2] = { + .name = "SOC_I", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temp Sensors */ +static int board_get_memory_temp(int, int *); + +const struct pct2075_sensor_t pct2075_sensors[] = { + { I2C_PORT_SENSOR, PCT2075_I2C_ADDR_FLAGS0 }, + { I2C_PORT_SENSOR, PCT2075_I2C_ADDR_FLAGS7 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pct2075_sensors) == PCT2075_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_SOC] = { + .name = "SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = board_get_soc_temp_k, + .idx = PCT2075_SOC, + }, + [TEMP_SENSOR_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER, + }, + [TEMP_SENSOR_MEMORY] = { + .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = board_get_memory_temp, + .idx = ADC_TEMP_SENSOR_MEMORY, + }, + [TEMP_SENSOR_CPU] = { + .name = "CPU", + .type = TEMP_SENSOR_TYPE_CPU, + .read = sb_tsi_get_val, + .idx = 0, + }, + [TEMP_SENSOR_AMBIENT] = { + .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = pct2075_get_val_k, + .idx = PCT2075_AMB, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +static int board_get_memory_temp(int idx, int *temp_k) +{ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + return get_temp_3v3_30k9_47k_4050b(idx, temp_k); +} + +/* keyboard config */ +static const struct ec_response_keybd_config main_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &main_kb; +} + +void board_set_current_limit(void) +{ + const int no_battery_current_limit_override_ma = 6000; + /* + * When there is no battery, override charger current limit to + * prevent brownout during boot. + */ + if (battery_is_present() == BP_NO) { + ccprints("No Battery Found - Override Current Limit to %dmA", + no_battery_current_limit_override_ma); + charger_set_input_current_limit( + CHARGER_SOLO, no_battery_current_limit_override_ma); + } +} +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, board_set_current_limit, + HOOK_PRIO_INIT_EXTPOWER); diff --git a/board/dewatt/board.h b/board/dewatt/board.h new file mode 100644 index 0000000000..58990c97d3 --- /dev/null +++ b/board/dewatt/board.h @@ -0,0 +1,110 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* Motion sensing drivers */ + +/* Keyboard features */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* Tablet Mode Switch */ +#define CONFIG_TABLET_MODE_SWITCH + +/* Sensors */ +#define CONFIG_ACCELGYRO_BMI260 +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCEL_BMA4XX + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +/* EC console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_CMD_BUTTON + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_MUX_ANX7451 +#define CONFIG_USBC_RETIMER_ANX7451 + +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_CURRENT_MA 3250 +#define PD_MAX_VOLTAGE_MV 20000 +/* Max Power = 65 W */ +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) + +/* USB Type A Features */ + +/* BC 1.2 */ + +/* Volume Button feature */ + +/* Fan features */ +#define CONFIG_FAN_RPM_CUSTOM + +/* LED features */ +#define CONFIG_LED_COMMON +#define CONFIG_LED_ONOFF_STATES + +/* Thermal Config */ +#define CONFIG_TEMP_SENSOR_PCT2075 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +/* Motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); + +/* Battery Types */ +enum battery_type { + BATTERY_AP19B8M, + BATTERY_TYPE_COUNT, +}; + +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI260 = 1, +}; + +/* ADC Channels */ +enum adc_channel { + ADC_TEMP_SENSOR_SOC = 0, + ADC_TEMP_SENSOR_CHARGER, + ADC_TEMP_SENSOR_MEMORY, + ADC_CORE_IMON1, + ADC_SOC_IMON2, + ADC_CH_COUNT +}; + +/* Temp Sensors */ +enum temp_sensor_id { + TEMP_SENSOR_SOC = 0, + TEMP_SENSOR_CHARGER, + TEMP_SENSOR_MEMORY, + TEMP_SENSOR_CPU, + TEMP_SENSOR_AMBIENT, + TEMP_SENSOR_COUNT +}; + +/* PCT2075 sensors */ +enum pct2075_sensor { + PCT2075_SOC, + PCT2075_AMB, + PCT2075_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/dewatt/board_fw_config.c b/board/dewatt/board_fw_config.c new file mode 100644 index 0000000000..7128a153ca --- /dev/null +++ b/board/dewatt/board_fw_config.c @@ -0,0 +1,29 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "base_fw_config.h" +#include "board_fw_config.h" + +bool board_is_convertible(void) +{ + return 1; +} + +bool board_has_kblight(void) +{ + return (get_fw_config_field(FW_CONFIG_KBLIGHT_OFFSET, + FW_CONFIG_KBLIGHT_WIDTH) == + FW_CONFIG_KBLIGHT_YES); +} + +enum board_usb_c1_mux board_get_usb_c1_mux(void) +{ + return USB_C1_MUX_PS8818; +}; + +enum board_usb_a1_retimer board_get_usb_a1_retimer(void) +{ + return USB_A1_RETIMER_UNKNOWN; +}; diff --git a/board/dewatt/board_fw_config.h b/board/dewatt/board_fw_config.h new file mode 100644 index 0000000000..4477aca6fd --- /dev/null +++ b/board/dewatt/board_fw_config.h @@ -0,0 +1,37 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _GUYBRUSH_BOARD_FW_CONFIG__H_ +#define _GUYBRUSH_BOARD_FW_CONFIG__H_ + +/**************************************************************************** + * Guybrush CBI FW Configuration + */ + +/* + * USB Daughter Board (2 bits) + */ +#define FW_CONFIG_USB_DB_OFFSET 0 +#define FW_CONFIG_USB_DB_WIDTH 2 +#define FW_CONFIG_USB_DB_A1_PS8811_C1_PS8818 0 +#define FW_CONFIG_USB_DB_A1_ANX7491_C1_ANX7451 1 + +/* + * Form Factor (1 bits) + */ +#define FW_CONFIG_FORM_FACTOR_OFFSET 2 +#define FW_CONFIG_FORM_FACTOR_WIDTH 1 +#define FW_CONFIG_FORM_FACTOR_CLAMSHELL 0 +#define FW_CONFIG_FORM_FACTOR_CONVERTIBLE 1 + +/* + * Keyboard Backlight (1 bit) + */ +#define FW_CONFIG_KBLIGHT_OFFSET 3 +#define FW_CONFIG_KBLIGHT_WIDTH 1 +#define FW_CONFIG_KBLIGHT_NO 0 +#define FW_CONFIG_KBLIGHT_YES 1 + +#endif /* _GUYBRUSH_CBI_FW_CONFIG__H_ */ diff --git a/board/dewatt/build.mk b/board/dewatt/build.mk new file mode 100644 index 0000000000..8a1ce35e1e --- /dev/null +++ b/board/dewatt/build.mk @@ -0,0 +1,12 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +BASEBOARD:=guybrush + +board-y=board.o +board-y+=board_fw_config.o led.o battery.o thermal.o diff --git a/board/dewatt/ec.tasklist b/board/dewatt/ec.tasklist new file mode 100644 index 0000000000..14ecddebc9 --- /dev/null +++ b/board/dewatt/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, VENTI_TASK_STACK_SIZE) diff --git a/board/dewatt/gpio.inc b/board/dewatt/gpio.inc new file mode 100644 index 0000000000..9798239af5 --- /dev/null +++ b/board/dewatt/gpio.inc @@ -0,0 +1,28 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the board GPIOs that we care about. */ + +#include "base_gpio.inc" + +GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, motion_interrupt) /* 6 Axis IMU */ +GPIO_INT(TABLET_MODE, PIN(C, 1), GPIO_INT_BOTH, gmr_tablet_switch_isr) /* 360 Tablet Mode */ + +/* LED Signals */ +ALTERNATE(/*EC_PWM_LED_CHRG_L*/ PIN_MASK(C, BIT(4)), 0, MODULE_PWM, 0) /* Charging LED */ +ALTERNATE(/*EC_PWM_LED_FULL_L*/ PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* Full LED */ + +/* Test Points */ +GPIO(EC_GPIO56, PIN(5, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PS2_CLK, PIN(6, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PS2_DAT, PIN(7, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PS2_RST, PIN(6, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_GPIOB0, PIN(B, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_GPIO81, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_FLPRG2, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PSL_GPO, PIN(D, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PWM7, PIN(6, 0), GPIO_INPUT | GPIO_PULL_UP) \ No newline at end of file diff --git a/board/dewatt/led.c b/board/dewatt/led.c new file mode 100644 index 0000000000..05bc7d88fc --- /dev/null +++ b/board/dewatt/led.c @@ -0,0 +1,124 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Guybrush specific PWM LED settings. + */ + +#include "common.h" +#include "cros_board_info.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "pwm.h" + +/* Note PWM LEDs are active low */ +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +#define CPRINTS(format, args...) cprints(CC_PWM, format, ##args) + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 97; + +static enum pwm_channel pwm_ch_led_blue; +static enum pwm_channel pwm_ch_led_amber; + +static void led_pwm_ch_init(void) +{ + int val; + + pwm_ch_led_blue = PWM_CH_LED_FULL; + pwm_ch_led_amber = PWM_CH_LED_CHRG; + + /* + * Ver1: GPIOC4(PWM2) -> Blue LED + * GPIO80(PWM3) -> Amber LED + */ + if (cbi_get_board_version(&val) == EC_SUCCESS && val <= 1) { + pwm_ch_led_blue = PWM_CH_LED_CHRG; + pwm_ch_led_amber = PWM_CH_LED_FULL; + } +} +DECLARE_HOOK(HOOK_INIT, led_pwm_ch_init, HOOK_PRIO_INIT_PWM - 1); + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_S5] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_BLUE, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + pwm_enable(pwm_ch_led_amber, LED_ON_LVL); + pwm_enable(pwm_ch_led_blue, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + pwm_enable(pwm_ch_led_amber, LED_OFF_LVL); + pwm_enable(pwm_ch_led_blue, LED_ON_LVL); + break; + case LED_OFF: + pwm_enable(pwm_ch_led_amber, LED_OFF_LVL); + pwm_enable(pwm_ch_led_blue, LED_OFF_LVL); + break; + default: /* Unsupported colors */ + CPRINTS("Unsupported LED color: %d", color); + pwm_enable(pwm_ch_led_amber, LED_OFF_LVL); + pwm_enable(pwm_ch_led_blue, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } else { + CPRINTS("Unsupported LED set: %d", led_id); + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} diff --git a/board/dewatt/thermal.c b/board/dewatt/thermal.c new file mode 100644 index 0000000000..bd63fda984 --- /dev/null +++ b/board/dewatt/thermal.c @@ -0,0 +1,144 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush board-specific configuration */ + +#include "console.h" +#include "fan.h" +#include "thermal.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = GPIO_S0_PGOOD, + .enable_gpio = -1, +}; +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 3000, + .rpm_start = 3000, + .rpm_max = 6000, +}; +const struct fan_t fans[] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); + +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT] = { + [TEMP_SENSOR_SOC] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + [EC_TEMP_THRESH_HALT] = C_TO_K(85), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), + }, + .temp_fan_off = C_TO_K(27), + .temp_fan_max = C_TO_K(80), + }, + [TEMP_SENSOR_CHARGER] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + [EC_TEMP_THRESH_HALT] = C_TO_K(85), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), + }, + .temp_fan_off = 0, + .temp_fan_max = 0, + }, + [TEMP_SENSOR_MEMORY] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + [EC_TEMP_THRESH_HALT] = C_TO_K(85), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), + }, + .temp_fan_off = 0, + .temp_fan_max = 0, + }, + [TEMP_SENSOR_CPU] = { + .temp_host = { + [EC_TEMP_THRESH_WARN] = C_TO_K(100), + [EC_TEMP_THRESH_HIGH] = C_TO_K(105), + [EC_TEMP_THRESH_HALT] = C_TO_K(108), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), + }, + .temp_fan_off = 0, + .temp_fan_max = 0, + }, + /* + * Note: Leave ambient entries at 0, both as it does not represent a + * hotspot and as not all boards have this sensor + */ +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +struct fan_step { + int on; + int off; + int rpm; +}; + +static const struct fan_step fan_table[] = { + { .on = 0, .off = 1, .rpm = 0 }, + { .on = 6, .off = 2, .rpm = 3000 }, + { .on = 28, .off = 15, .rpm = 3300 }, + { .on = 34, .off = 26, .rpm = 3700 }, + { .on = 39, .off = 32, .rpm = 4000 }, + { .on = 45, .off = 38, .rpm = 4300 }, + { .on = 51, .off = 43, .rpm = 4700 }, + { .on = 74, .off = 62, .rpm = 5400 }, +}; +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_table) + +int fan_percent_to_rpm(int fan, int pct) +{ + static int current_level; + static int previous_pct; + int i; + + /* + * Compare the pct and previous pct, we have the three paths : + * 1. decreasing path. (check the off point) + * 2. increasing path. (check the on point) + * 3. invariant path. (return the current RPM) + */ + if (pct < previous_pct) { + for (i = current_level; i >= 0; i--) { + if (pct <= fan_table[i].off) + current_level = i - 1; + else + break; + } + } else if (pct > previous_pct) { + for (i = current_level + 1; i < NUM_FAN_LEVELS; i++) { + if (pct >= fan_table[i].on) + current_level = i; + else + break; + } + } + + if (current_level < 0) + current_level = 0; + + previous_pct = pct; + + if (fan_table[current_level].rpm != fan_get_rpm_target(FAN_CH(fan))) + CPRINTS("Setting fan RPM to %d", fan_table[current_level].rpm); + + return fan_table[current_level].rpm; +} diff --git a/board/dewatt/vif_override.xml b/board/dewatt/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/dewatt/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/dibbi/board.c b/board/dibbi/board.c new file mode 100644 index 0000000000..063211c0c4 --- /dev/null +++ b/board/dibbi/board.c @@ -0,0 +1,426 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Dibbi board-specific configuration */ + +#include "adc_chip.h" +#include "board.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "driver/cec/bitbang.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_VBUS] = { .name = "VBUS", /* 113/1113 voltage divider */ + .factor_mul = ADC_MAX_MVOLT * 1113, + .factor_div = (ADC_READ_MAX + 1) * 113, + .shift = 0, + .channel = CHIP_ADC_CH4 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, + [ADC_PPVAR_PWR_IN_IMON] = { .name = "ADC_PPVAR_PWR_IN_IMON", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, + [ADC_SNS_PPVAR_PWR_IN] = { .name = "ADC_SNS_PPVAR_PWR_IN", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH16 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &it83xx_tcpm_drv, + }, +}; + +/* PPCs */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_EC_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, +}; + +/* USB-A ports */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, + GPIO_EN_USB_A1_VBUS, + GPIO_EN_USB_A2_VBUS, + GPIO_EN_USB_A3_VBUS, +}; + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_RED] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_GREEN] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_BLUE] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + } + +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "SoC power", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +void board_init(void) +{ + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT); + + /* Enable PPC interrupt */ + gpio_enable_interrupt(GPIO_USB_C0_FAULT_L); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Nothing to do. 5V should always be enabled while in Z1 or above. + */ +} + +void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma, + int charge_mv) +{ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + /* TODO(b/259467280) blink LED on error */ + (void)insufficient_power; +} + +int board_vbus_source_enabled(int port) +{ + if (port != CHARGE_PORT_TYPEC0) + return 0; + + return ppc_is_sourcing_vbus(port); +} + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* + * We ignore the cc_pin and PPC vconn because polarity and PPC vconn + * should already be set correctly in the PPC driver via the pd + * state machine. + */ +} + +/******************************************************************************/ +/* + * Since dibbi has no battery, it must source all of its power from either + * USB-C or the barrel jack (preferred). Fizz operates in continuous safe + * mode (charge_manager_leave_safe_mode() will never be called), which + * modifies port selection as follows: + * + * - Dual-role / dedicated capability of the port partner is ignored. + * - Charge ceiling on PD voltage transition is ignored. + * - CHARGE_PORT_NONE will never be selected. + */ + +/* List of BJ adapters */ +enum bj_adapter { + BJ_NONE, + BJ_65W_19V, +}; + +/* Barrel-jack power adapter ratings. */ +static const struct charge_port_info bj_adapters[] = { + [BJ_NONE] = { .current = 0, .voltage = 0 }, + [BJ_65W_19V] = { .current = 3420, .voltage = 19000 }, +}; +#define BJ_ADP_RATING_DEFAULT BJ_65W_19V /* BJ power ratings default */ +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ + +/* Debounced connection state of the barrel jack */ +static int8_t bj_adp_connected = -1; +static void adp_connect_deferred(void) +{ + const struct charge_port_info *pi; + int connected = gpio_get_level(GPIO_BJ_ADP_PRESENT); + + /* Debounce */ + if (connected == bj_adp_connected) + return; + + if (connected) { + pi = &bj_adapters[BJ_ADP_RATING_DEFAULT]; + } else { + /* No barrel-jack, zero out this power supply */ + pi = &bj_adapters[BJ_NONE]; + } + /* This will result in a call to board_set_active_charge_port */ + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, pi); + bj_adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +int board_set_active_charge_port(int port) +{ + const int active_port = charge_manager_get_active_charge_port(); + + CPRINTUSB("Requested charge port change to %d", port); + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == active_port) + return EC_SUCCESS; + + /* Don't sink from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_adp_connected != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTUSB("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + ppc_vbus_sink_enable(USBC_PORT_C0, 1); + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_OD, 0); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (!gpio_get_level(GPIO_BJ_ADP_PRESENT)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_OD, 1); + ppc_vbus_sink_enable(USBC_PORT_C0, 1); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static void board_charge_manager_init(void) +{ + enum charge_port port; + + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + port = gpio_get_level(GPIO_BJ_ADP_PRESENT) ? CHARGE_PORT_BARRELJACK : + CHARGE_PORT_TYPEC0; + CPRINTUSB("Power source is p%d (%s)", port, + port == CHARGE_PORT_TYPEC0 ? "USB-C" : "BJ"); + + /* Initialize the power source supplier */ + switch (port) { + case CHARGE_PORT_TYPEC0: + typec_set_input_current_limit(port, 3000, 5000); + break; + case CHARGE_PORT_BARRELJACK: + charge_manager_update_charge( + CHARGE_SUPPLIER_DEDICATED, DEDICATED_CHARGE_PORT, + &bj_adapters[BJ_ADP_RATING_DEFAULT]); + break; + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, board_charge_manager_init, + HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +__override int extpower_is_present(void) +{ + /* + * There's no battery, so running this method implies we have power. + */ + return 1; +} + +void ppc_interrupt(enum gpio_signal signal) +{ + if (signal == GPIO_USB_C0_FAULT_L) + syv682x_interrupt(USBC_PORT_C0); +} + +/* I2C Ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + + { .name = "hdmi2_edid", + .port = I2C_PORT_HDMI2_EDID, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI2_EDID_SCL, + .sda = GPIO_EC_I2C_HDMI2_EDID_SDA }, + + { .name = "usbc0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_SCL, + .sda = GPIO_EC_I2C_USB_C0_SDA }, + + { .name = "hdmi2_src_ddc", + .port = I2C_PORT_HDMI2_SRC_DDC, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI2_SRC_DDC_SCL, + .sda = GPIO_EC_I2C_HDMI2_SRC_DDC_SDA }, + + { .name = "hdmi1_edid", + .port = I2C_PORT_HDMI1_EDID, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI1_EDID_SCL, + .sda = GPIO_EC_I2C_HDMI1_EDID_SDA }, + + { .name = "hdmi1_src_ddc", + .port = I2C_PORT_HDMI1_SRC_DDC, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI1_SRC_DDC_SCL, + .sda = GPIO_EC_I2C_HDMI1_SRC_DDC_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" diff --git a/board/dibbi/board.h b/board/dibbi/board.h new file mode 100644 index 0000000000..0958f754fc --- /dev/null +++ b/board/dibbi/board.h @@ -0,0 +1,176 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Dibbi board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +/* System unlocked in early development */ +#define CONFIG_SYSTEM_UNLOCKED + +#define CONFIG_CMD_CHARGER_DUMP + +/* I2C Bus Configuration */ +#define I2C_PORT_HDMI2_EDID IT83XX_I2C_CH_B +#undef I2C_PORT_USB_C0 +#define I2C_PORT_USB_C0 IT83XX_I2C_CH_C +#define I2C_PORT_HDMI2_SRC_DDC IT83XX_I2C_CH_D +#define I2C_PORT_HDMI1_EDID IT83XX_I2C_CH_E +#define I2C_PORT_HDMI1_SRC_DDC IT83XX_I2C_CH_F + +/* Power */ +#undef CONFIG_CHARGER +#undef CONFIG_CHARGER_DISCHARGE_ON_AC +#undef CONFIG_USB_PD_VBUS_MEASURE_CHARGER +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 16000 +#define PD_MAX_VOLTAGE_MV 20000 +#undef PD_MAX_CURRENT_MA +#define PD_MAX_CURRENT_MA 3250 +#undef PD_MAX_POWER_MW +#define PD_MAX_POWER_MW 65000 +#define CONFIG_USB_PD_VBUS_DETECT_GPIO + +/* Override macro for C0 only */ +#define PORT_TO_HPD(port) (GPIO_USB_C0_DP_HPD) + +/* Power: Dedicated barreljack charger port */ +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 +#define DEDICATED_CHARGE_PORT 1 + +/* USB Type-C */ +#undef CONFIG_USB_CHARGER +#undef CONFIG_USB_MUX_PI3USB31532 + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 + +/* PPC */ +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USBC_PPC +#define CONFIG_USBC_PPC_SYV682X + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C0: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +/* USB Type A Features */ +#define CONFIG_USB_PORT_POWER_DUMB +#define USB_PORT_COUNT 4 /* Type A ports */ + +/* No battery */ +#undef CONFIG_BATTERY_CUT_OFF +#undef CONFIG_BATTERY_PRESENT_GPIO +#undef CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD +#undef CONFIG_BATTERY_REVIVE_DISCONNECT +#undef CONFIG_BATTERY_SMART + +/* LED */ +#define CONFIG_LED_PWM +#define CONFIG_LED_PWM_COUNT 1 + +/* PWM */ +#define CONFIG_PWM + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* Buttons */ +#define CONFIG_DEDICATED_RECOVERY_BUTTON +#define CONFIG_DEDICATED_RECOVERY_BUTTON_2 +#define CONFIG_DEDICATED_RECOVERY_BUTTON_FLAGS BUTTON_FLAG_ACTIVE_HIGH +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_IGNORE_LID +#define CONFIG_POWER_BUTTON_X86 +#define CONFIG_EMULATED_SYSRQ + +/* CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMI2_CEC +#define CEC_GPIO_IN GPIO_HDMI2_CEC_IN +#undef CEC_GPIO_PULL_UP /* Pull-up to PP3300_Z1 */ + +/* No Keyboard */ +#undef CONFIG_KEYBOARD_COL2_INVERTED +#undef CONFIG_KEYBOARD_PROTOCOL_8042 +#undef CONFIG_CMD_KEYBOARD +#undef CONFIG_KEYBOARD_BOOT_KEYS +#undef CONFIG_KEYBOARD_RUNTIME_KEYS + +/* No backlight */ +#undef CONFIG_BACKLIGHT_LID +#undef GPIO_ENABLE_BACKLIGHT + +/* Unused features - Misc */ +#undef CONFIG_HIBERNATE +#undef CONFIG_VOLUME_BUTTONS +#undef CONFIG_LID_SWITCH +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE +#undef GPIO_TABLET_MODE_L + +/* Unused GPIOs */ +#undef GPIO_USB_C1_DP_HPD + +/* Pin renaming */ +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_BARRELJACK, +}; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_COUNT }; + +enum pwm_channel { + PWM_CH_LED_RED, + PWM_CH_LED_GREEN, + PWM_CH_LED_BLUE, + PWM_CH_COUNT, +}; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_VBUS, /* ADC4 */ + ADC_TEMP_SENSOR_3, /* ADC13 */ + ADC_PPVAR_PWR_IN_IMON, /* ADC15 */ + ADC_SNS_PPVAR_PWR_IN, /* ADC16 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/dibbi/build.mk b/board/dibbi/build.mk new file mode 100644 index 0000000000..8336360a6a --- /dev/null +++ b/board/dibbi/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede +BOARD:=dibbi + +board-y=board.o led.o usb_pd_policy.o diff --git a/board/dibbi/ec.tasklist b/board/dibbi/ec.tasklist new file mode 100644 index 0000000000..f3afa44da1 --- /dev/null +++ b/board/dibbi/ec.tasklist @@ -0,0 +1,17 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, TASK_STACK_SIZE) diff --git a/board/dibbi/gpio.inc b/board/dibbi/gpio.inc new file mode 100644 index 0000000000..ccd83d3266 --- /dev/null +++ b/board/dibbi/gpio.inc @@ -0,0 +1,162 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(EC_VSNS_PP3300_S5, PIN(I, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* Other interrupts */ +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +/* Directly connected recovery button */ +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(K, 7), GPIO_INT_BOTH, button_interrupt) +/* Recovery button input from H1 */ +GPIO_INT(H1_EC_RECOVERY_BTN_ODL,PIN(K, 4), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(BJ_ADP_PRESENT, PIN(A, 7), GPIO_INT_BOTH, adp_connect_interrupt) +GPIO_INT(USB_C0_FAULT_L, PIN(K, 0), GPIO_INT_FALLING, ppc_interrupt) +/* CEC interrupt */ +GPIO_INT(HDMI2_CEC_IN, PIN(J, 3), GPIO_INT_BOTH, cec_gpio_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_PSYS, PIN(J, 2), GPIO_OUT_LOW) +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(J, 0), GPIO_INPUT) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_HIGH) +GPIO(PG_PP3300_A, PIN(B, 5), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_PPVAR_BJ_ADP_OD, PIN(E, 3), GPIO_ODR_HIGH) +GPIO(ACK_PPVAR_BJ_ADP_ODL, PIN(A, 0), GPIO_INPUT) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Required for dedede baseboard but not used in dibbi */ +UNIMPLEMENTED(USB_C0_INT_ODL) +UNIMPLEMENTED(EN_SLP_Z) +UNIMPLEMENTED(EC_BATTERY_PRES_ODL) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(F, 6), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(F, 7), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_EDID_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_EDID_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_HDMI2_EDID_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_HDMI2_EDID_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_SRC_DDC_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_SRC_DDC_SDA, PIN(A, 5), GPIO_INPUT) +GPIO(EC_I2C_HDMI2_SRC_DDC_SCL, PIN(H, 1), GPIO_INPUT) +GPIO(EC_I2C_HDMI2_SRC_DDC_SDA, PIN(H, 2), GPIO_INPUT) + +/* USB pins */ +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_A1_VBUS, PIN(C, 6), GPIO_OUT_LOW) +GPIO(EN_USB_A2_VBUS, PIN(C, 4), GPIO_OUT_LOW) +GPIO(EN_USB_A3_VBUS, PIN(J, 5), GPIO_OUT_LOW) +GPIO(EC_USB_C0_FRS_EN, PIN(K, 6), GPIO_OUT_LOW) +GPIO(USB_C0_SBU_MUX_FAULT, PIN(I, 7), GPIO_INPUT) + +/* MKBP event synchronization */ +/* TODO(b/257833880) Check whether this pin is needed */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* HDMI */ +GPIO(HDMI1_CEC, PIN(F, 0), GPIO_OUT_LOW) +GPIO(HDMI2_CEC, PIN(F, 1), GPIO_ODR_HIGH) +GPIO(HDMI1_SRC_HPD, PIN(F, 3), GPIO_INPUT) +GPIO(HDMI2_SRC_HPD, PIN(KSO_L, 3), GPIO_INPUT) +GPIO(EC_HDMI1_SRC_HPD_OUT, PIN(I, 6), GPIO_OUT_LOW) +GPIO(EC_HDMI2_SRC_HPD_OUT, PIN(KSO_L, 4), GPIO_OUT_LOW) +GPIO(HDMI1_EDID_SEL, PIN(J, 1), GPIO_OUT_LOW) +GPIO(HDMI2_EDID_SEL, PIN(KSO_L, 5), GPIO_OUT_LOW) +GPIO(EDID_BTN_ODL, PIN(C, 3), GPIO_INPUT) +GPIO(EC_EN_PP5000_HDMI1, PIN(KSO_L, 6), GPIO_OUT_LOW) +GPIO(EC_EN_PP5000_HDMI2, PIN(KSO_L, 7), GPIO_OUT_LOW) + +/* Misc */ +GPIO(EC_ENTERING_RW, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(ECH1_PACKET_MODE, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EN_RS232_X, PIN(E, 6), GPIO_OUT_LOW) +GPIO(UART0_RX, PIN(B, 1), GPIO_OUT_LOW) /* UART_EC_TX_DBG_RX */ + + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOG0_NC, PIN(G, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOI4_NC, PIN(I, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOK3_NC, PIN(K, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 - EEPROM */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 - HDMI2_EDID */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, 0) /* I2C2 - USB_C0 */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 - HDMI1_EDID */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 - HDMI1_SRC_DDC */ +ALTERNATE(PIN_MASK(H, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C3 - HDMI2_SRC_DDC */ + +/* ADC */ +/* ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2, ADC4: VBUS */ +ALTERNATE(PIN_MASK(I, BIT(2) | BIT(3) | BIT(4)), 0, MODULE_ADC, 0) +/* + * ADC13: TEMP_SENSOR_3 + * ADC15: ANALOG_PPVAR_PWR_IN_IMON + * ADC16: SNS_PPVAR_PWR_IN + */ +ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(1) | BIT(2) | BIT(3)), 0, MODULE_PWM, 0) /* LED_[R,G,B]_ODL */ diff --git a/board/dibbi/led.c b/board/dibbi/led.c new file mode 100644 index 0000000000..fb423877c6 --- /dev/null +++ b/board/dibbi/led.c @@ -0,0 +1,80 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Dibbi specific PWM LED settings. */ + +#include "common.h" +#include "ec_commands.h" +#include "led_pwm.h" +#include "pwm.h" +#include "util.h" + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_POWER_LED, +}; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +/* One physical LED with red, green, and blue. */ +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Red, Green, Blue */ + [EC_LED_COLOR_RED] = { 100, 0, 0 }, + [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, + [EC_LED_COLOR_YELLOW] = { 50, 50, 0 }, + [EC_LED_COLOR_WHITE] = { 50, 50, 50 }, + [EC_LED_COLOR_AMBER] = { 70, 30, 0 }, +}; + +/* One logical LED with red, green, and blue channels. */ +struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = { + { + .ch0 = PWM_CH_LED_RED, + .ch1 = PWM_CH_LED_GREEN, + .ch2 = PWM_CH_LED_BLUE, + .enable = &pwm_enable, + .set_duty = &pwm_set_duty, + }, +}; + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + memset(brightness_range, '\0', + sizeof(*brightness_range) * EC_LED_COLOR_COUNT); + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_GREEN] = 100; + brightness_range[EC_LED_COLOR_BLUE] = 100; + brightness_range[EC_LED_COLOR_YELLOW] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; + brightness_range[EC_LED_COLOR_AMBER] = 100; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + enum pwm_led_id pwm_id; + + /* Convert ec_led_id to pwm_led_id. */ + if (led_id == EC_LED_ID_POWER_LED) + pwm_id = PWM_LED0; + else + return EC_ERROR_UNKNOWN; + + if (brightness[EC_LED_COLOR_RED]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_GREEN]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN); + else if (brightness[EC_LED_COLOR_BLUE]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_YELLOW]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_YELLOW); + else if (brightness[EC_LED_COLOR_WHITE]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); + else + /* Otherwise, the "color" is "off". */ + set_pwm_led_color(pwm_id, -1); + + return EC_SUCCESS; +} diff --git a/board/dibbi/usb_pd_policy.c b/board/dibbi/usb_pd_policy.c new file mode 100644 index 0000000000..b28e1ae7d4 --- /dev/null +++ b/board/dibbi/usb_pd_policy.c @@ -0,0 +1,72 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "usb_pd.h" +#include "usbc_ppc.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return gpio_get_level(GPIO_EN_PP5000_U); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + if (port < 0 || port >= board_get_usb_pd_port_count()) + return; + + prev_en = ppc_is_sourcing_vbus(port); + + /* Disable VBUS source */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Enable VBUS source */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +__override int pd_snk_is_vbus_provided(int port) +{ + if (port != CHARGE_PORT_TYPEC0) + return 0; + + return ppc_is_vbus_present(port); +} diff --git a/board/dibbi/vif_override.xml b/board/dibbi/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/dibbi/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/dingdong/board.c b/board/dingdong/board.c index 0ca41dec45..bc9bb3803a 100644 --- a/board/dingdong/board.c +++ b/board/dingdong/board.c @@ -1,27 +1,27 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Dingdong dongle configuration */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "ec_version.h" #include "gpio.h" #include "hooks.h" #include "registers.h" +#include "task.h" +#include "timer.h" #include "usb_bb.h" #include "usb_descriptor.h" #include "usb_pd.h" -#include "task.h" -#include "timer.h" #include "util.h" static volatile uint64_t hpd_prev_ts; static volatile int hpd_prev_level; void hpd_event(enum gpio_signal signal); +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /** @@ -97,7 +97,7 @@ void board_config_pre_init(void) /* enable SYSCFG clock */ STM32_RCC_APB2ENR |= BIT(0); /* Remap USART DMA to match the USART driver */ - STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10);/* Remap USART1 RX/TX DMA */ + STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10); /* Remap USART1 RX/TX DMA */ } /* Initialize board. */ @@ -116,12 +116,12 @@ DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); /* ADC channels */ const struct adc_t adc_channels[] = { /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_CH_CC1_PD] = {"USB_C_CC1_PD", 3300, 4096, 0, STM32_AIN(1)}, + [ADC_CH_CC1_PD] = { "USB_C_CC1_PD", 3300, 4096, 0, STM32_AIN(1) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); -const void * const usb_strings[] = { +const void *const usb_strings[] = { [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), [USB_STR_PRODUCT] = USB_STRING_DESC("Dingdong"), [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), [USB_STR_BB_URL] = USB_STRING_DESC(USB_GOOGLE_TYPEC_URL), diff --git a/board/dingdong/board.h b/board/dingdong/board.h index 64947960ba..52c3b740e4 100644 --- a/board/dingdong/board.h +++ b/board/dingdong/board.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,7 +15,6 @@ #define CONFIG_UART_CONSOLE 1 /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_ADC #define CONFIG_BOARD_PRE_INIT #define CONFIG_HW_CRC @@ -39,7 +38,7 @@ #define CONFIG_USB_PD_IDENTITY_SW_VERS 1 #define CONFIG_USB_PD_VBUS_DETECT_NONE #define CONFIG_USB_PD_LOGGING -#undef CONFIG_EVENT_LOG_SIZE +#undef CONFIG_EVENT_LOG_SIZE #define CONFIG_EVENT_LOG_SIZE 256 #define CONFIG_USB_PD_PORT_MAX_COUNT 1 #define CONFIG_USB_PD_TCPC @@ -63,7 +62,7 @@ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 +#define TIM_ADC 3 #include "gpio_signal.h" @@ -86,14 +85,14 @@ enum usb_strings { }; /* we are never a source : don't care about power supply */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 0 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 0 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 0 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 1000 -#define PD_MAX_POWER_MW 1500 -#define PD_MAX_CURRENT_MA 300 -#define PD_MAX_VOLTAGE_MV 5000 +#define PD_MAX_POWER_MW 1500 +#define PD_MAX_CURRENT_MA 300 +#define PD_MAX_VOLTAGE_MV 5000 #endif /* !__ASSEMBLER__ */ @@ -101,10 +100,10 @@ enum usb_strings { #define USB_DEV_CLASS USB_CLASS_BILLBOARD /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_COUNT 0 +#define USB_IFACE_COUNT 0 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_COUNT 1 +#define USB_EP_CONTROL 0 +#define USB_EP_COUNT 1 #endif /* __CROS_EC_BOARD_H */ diff --git a/board/dingdong/build.mk b/board/dingdong/build.mk index 18799c3b9f..b6fbbe7a9e 100644 --- a/board/dingdong/build.mk +++ b/board/dingdong/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,4 +11,4 @@ CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f07x board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_pdo.o diff --git a/board/dingdong/ec.tasklist b/board/dingdong/ec.tasklist index 41fc047d6a..5a82344122 100644 --- a/board/dingdong/ec.tasklist +++ b/board/dingdong/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/dingdong/gpio.inc b/board/dingdong/gpio.inc index ec1e9a7fa9..d8ea0dfc8f 100644 --- a/board/dingdong/gpio.inc +++ b/board/dingdong/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/dingdong/usb_pd_config.h b/board/dingdong/usb_pd_config.h index 2f01c275a8..5a7dfd12a6 100644 --- a/board/dingdong/usb_pd_config.h +++ b/board/dingdong/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -49,7 +49,7 @@ static inline void spi_enable_clock(int port) #define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 #define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 -#define TIM_CCR_CS 1 +#define TIM_CCR_CS 1 #define EXTI_COMP_MASK(p) BIT(21) #define IRQ_COMP STM32_IRQ_COMP /* triggers packet detection on comparator falling edge */ @@ -88,9 +88,8 @@ static inline void pd_tx_enable(int port, int polarity) static inline void pd_tx_disable(int port, int polarity) { /* output low on SPI TX (PB4) to disable the FET */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - & ~(3 << (2*4))) - | (1 << (2*4)); + STM32_GPIO_MODER(GPIO_B) = + (STM32_GPIO_MODER(GPIO_B) & ~(3 << (2 * 4))) | (1 << (2 * 4)); /* put the low level reference in Hi-Z */ gpio_set_level(GPIO_PD_CC1_TX_EN, 0); } @@ -101,8 +100,8 @@ static inline void pd_select_polarity(int port, int polarity) * use the right comparator : CC1 -> PA1 (COMP1 INP) * use VrefInt / 2 as INM (about 600mV) */ - STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) - | STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12; + STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) | + STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12; } /* Initialize pins used for TX and put them in Hi-Z */ @@ -111,7 +110,9 @@ static inline void pd_tx_init(void) gpio_config_module(MODULE_USB_PD, 1); } -static inline void pd_set_host_mode(int port, int enable) {} +static inline void pd_set_host_mode(int port, int enable) +{ +} static inline void pd_config_init(int port, uint8_t power_role) { diff --git a/board/dingdong/usb_pd_pdo.c b/board/dingdong/usb_pd_pdo.c new file mode 100644 index 0000000000..7b4ed3e2d8 --- /dev/null +++ b/board/dingdong/usb_pd_pdo.c @@ -0,0 +1,20 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +#define PDO_FIXED_FLAGS PDO_FIXED_COMM_CAP + +/* Source PDOs */ +const uint32_t pd_src_pdo[] = {}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +/* Fake PDOs : we just want our pre-defined voltages */ +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/dingdong/usb_pd_pdo.h b/board/dingdong/usb_pd_pdo.h new file mode 100644 index 0000000000..e1b628c3a8 --- /dev/null +++ b/board/dingdong/usb_pd_pdo.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_DINGDONG_USB_PD_PDO_H +#define __CROS_EC_BOARD_DINGDONG_USB_PD_PDO_H + +#include "stdint.h" + +extern const uint32_t pd_src_pdo[0]; +extern const int pd_src_pdo_cnt; + +extern const uint32_t pd_snk_pdo[1]; +extern const int pd_snk_pdo_cnt; + +#endif /* __CROS_EC_BOARD_DINGDONG_USB_PD_PDO_H */ diff --git a/board/dingdong/usb_pd_policy.c b/board/dingdong/usb_pd_policy.c index f17802c82a..c7e3f0e4a9 100644 --- a/board/dingdong/usb_pd_policy.c +++ b/board/dingdong/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,32 +7,21 @@ #include "board.h" #include "common.h" #include "console.h" +#include "cros_version.h" #include "ec_commands.h" #include "gpio.h" #include "hooks.h" #include "registers.h" #include "task.h" #include "timer.h" -#include "util.h" -#include "usb_bb.h" #include "usb_api.h" +#include "usb_bb.h" #include "usb_pd.h" -#include "version.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define PDO_FIXED_FLAGS PDO_FIXED_COMM_CAP - -/* Source PDOs */ -const uint32_t pd_src_pdo[] = {}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +#include "usb_pd_tcpm.h" +#include "util.h" -/* Fake PDOs : we just want our pre-defined voltages */ -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) /* Holds valid object position (opos) for entered mode */ static int alt_mode[PD_AMODE_COUNT]; @@ -80,28 +69,22 @@ int pd_check_power_swap(int port) return 0; } -int pd_check_data_swap(int port, - enum pd_data_role data_role) +int pd_check_data_swap(int port, enum pd_data_role data_role) { /* Always refuse data swap */ return 0; } -void pd_execute_data_swap(int port, - enum pd_data_role data_role) +void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* Do nothing */ } -void pd_check_pr_role(int port, - enum pd_power_role pr_role, - int flags) +void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { } -void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { } /* ----------------- Vendor Defined Messages ------------------ */ @@ -114,8 +97,8 @@ const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, - CONFIG_USB_PD_IDENTITY_SW_VERS, - 0, 0, 0, 0, /* SS[TR][12] */ + CONFIG_USB_PD_IDENTITY_SW_VERS, 0, 0, 0, + 0, /* SS[TR][12] */ 0, /* Vconn power */ 0, /* Vconn power required */ 1, /* Vbus power required */ @@ -141,18 +124,16 @@ static int svdm_response_svids(int port, uint32_t *payload) #define OPOS_DP 1 #define OPOS_GFU 1 -const uint32_t vdo_dp_modes[1] = { - VDO_MODE_DP(0, /* UFP pin cfg supported : none */ +const uint32_t vdo_dp_modes[1] = { + VDO_MODE_DP(0, /* UFP pin cfg supported : none */ MODE_DP_PIN_E, /* DFP pin cfg supported */ - 1, /* no usb2.0 signalling in AMode */ - CABLE_PLUG, /* its a plug */ - MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ - MODE_DP_SNK) /* Its a sink only */ + 1, /* no usb2.0 signalling in AMode */ + CABLE_PLUG, /* its a plug */ + MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ + MODE_DP_SNK) /* Its a sink only */ }; -const uint32_t vdo_goog_modes[1] = { - VDO_MODE_GOOGLE(MODE_GOOGLE_FU) -}; +const uint32_t vdo_goog_modes[1] = { VDO_MODE_GOOGLE(MODE_GOOGLE_FU) }; static int svdm_response_modes(int port, uint32_t *payload) { @@ -174,13 +155,15 @@ static int dp_status(int port, uint32_t *payload) if (opos != OPOS_DP) return 0; /* nak */ - payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ - (hpd == 1), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - 0, /* MF pref */ + payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + (hpd == 1), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ gpio_get_level(GPIO_PD_SBU_ENABLE), - 0, /* power low */ + 0, /* power + low + */ 0x2); return 2; } @@ -219,9 +202,9 @@ static int svdm_enter_mode(int port, uint32_t *payload) return rv; } -int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid) +int pd_alt_mode(int port, enum tcpci_msg_type type, uint16_t svid) { - if (type != TCPC_TX_SOP) + if (type != TCPCI_MSG_SOP) return 0; if (svid == USB_SID_DISPLAYPORT) @@ -260,8 +243,7 @@ const struct svdm_response svdm_rsp = { .exit_mode = &svdm_exit_mode, }; -int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) +int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { int rsize; diff --git a/board/dingdong/vif_override.xml b/board/dingdong/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/dingdong/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/dirinboz/battery.c b/board/dirinboz/battery.c index f53143aa65..d02d424ba4 100644 --- a/board/dirinboz/battery.c +++ b/board/dirinboz/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -120,7 +120,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack ATL Battery Information */ - [BATTERY_DANAPACK_ATL] = { + [BATTERY_DYNAPACK_ATL] = { .fuel_gauge = { .manuf_name = "333-27-DA-A", .ship_mode = { @@ -149,7 +149,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack Coslight Battery Information */ - [BATTERY_DANAPACK_COS] = { + [BATTERY_DYNAPACK_COS] = { .fuel_gauge = { .manuf_name = "333-2C-DA-A", .ship_mode = { diff --git a/board/dirinboz/board.c b/board/dirinboz/board.c index 7517ee2130..efdcac76ef 100644 --- a/board/dirinboz/board.c +++ b/board/dirinboz/board.c @@ -1,15 +1,14 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "battery_smart.h" #include "button.h" +#include "charge_state.h" #include "cros_board_info.h" -#include "driver/accel_lis2dw12.h" -#include "driver/accelgyro_lsm6dsm.h" #include "driver/bc12/pi3usb9201.h" -#include "driver/ppc/aoz1380.h" +#include "driver/ppc/aoz1380_public.h" #include "driver/ppc/nx20p348x.h" #include "driver/tcpm/nct38xx.h" #include "driver/usb_mux/amd_fp5.h" @@ -20,6 +19,7 @@ #include "gpio.h" #include "hooks.h" #include "ioexpander.h" +#include "keyboard_8042_sharedlib.h" #include "lid_switch.h" #include "power.h" #include "power_button.h" @@ -29,121 +29,21 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" +#include "temp_sensor.h" +#include "thermal.h" #include "usb_charge.h" #include "usb_pd_tcpm.h" #include "usbc_ppc.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* This I2C moved. Temporarily detect and support the V0 HW. */ int I2C_PORT_BATTERY = I2C_PORT_BATTERY_V1; +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#ifdef HAS_TASK_MOTIONSENSE - -/* Motion sensors */ -static struct mutex g_lid_mutex; -static struct mutex g_base_mutex; - -/* sensor private data */ -static struct stprivate_data g_lis2dwl_data; -static struct lsm6dsm_data g_lsm6dsm_data = LSM6DSM_DATA; - -/* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; - -/* TODO(gcc >= 5.0) Remove the casts to const pointer at rot_standard_ref */ -struct motion_sensor_t motion_sensors[] = { - [LID_ACCEL] = { - .name = "Lid Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LIS2DWL, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &lis2dw12_drv, - .mutex = &g_lid_mutex, - .drv_data = &g_lis2dwl_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, - .rot_standard_ref = NULL, - .default_range = 2, /* g, enough for laptop. */ - .min_frequency = LIS2DW12_ODR_MIN_VAL, - .max_frequency = LIS2DW12_ODR_MAX_VAL, - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 12500 | ROUND_UP_FLAG, - }, - /* Sensor on for lid angle detection */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - }, - }, - - [BASE_ACCEL] = { - .name = "Base Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LSM6DSM, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6dsm_drv, - .mutex = &g_base_mutex, - .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, - MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .default_range = 4, /* g, enough for laptop */ - .rot_standard_ref = &base_standard_ref, - .min_frequency = LSM6DSM_ODR_MIN_VAL, - .max_frequency = LSM6DSM_ODR_MAX_VAL, - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 13000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - /* Sensor on for angle detection */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, - }, - - [BASE_GYRO] = { - .name = "Base Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LSM6DSM, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6dsm_drv, - .mutex = &g_base_mutex, - .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, - MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .default_range = 1000 | ROUND_UP_FLAG, /* dps */ - .rot_standard_ref = &base_standard_ref, - .min_frequency = LSM6DSM_ODR_MIN_VAL, - .max_frequency = LSM6DSM_ODR_MAX_VAL, - }, -}; - -unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -#endif /* HAS_TASK_MOTIONSENSE */ - /***************************************************************************** * Retimers */ @@ -171,8 +71,12 @@ DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, retimers_off, HOOK_PRIO_DEFAULT); * chip and it need a board specific driver. * Overall, it will use chained mux framework. */ -static int pi3usb221_set_mux(const struct usb_mux *me, mux_state_t mux_state) +static int pi3usb221_set_mux(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + if (mux_state & USB_PD_MUX_POLARITY_INVERTED) ioex_set_level(IOEX_USB_C0_SBU_FLIP, 1); else @@ -195,33 +99,43 @@ const struct usb_mux_driver usbc0_sbu_mux_driver = { * Since PI3USB221 is not a i2c device, .i2c_port and * .i2c_addr_flags are not required here. */ -const struct usb_mux usbc0_sbu_mux = { - .usb_port = USBC_PORT_C0, - .driver = &usbc0_sbu_mux_driver, +const struct usb_mux_chain usbc0_sbu_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &usbc0_sbu_mux_driver, + }, }; -struct usb_mux usbc1_amd_fp5_usb_mux = { - .usb_port = USBC_PORT_C1, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .flags = USB_MUX_FLAG_SET_WITHOUT_FLIP, +struct usb_mux_chain usbc1_amd_fp5_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + .flags = USB_MUX_FLAG_SET_WITHOUT_FLIP, + }, }; -struct usb_mux usb_muxes[] = { +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .next_mux = &usbc0_sbu_mux, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_sbu_mux, }, [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = PS8743_I2C_ADDR1_FLAG, - .driver = &ps8743_usb_mux_driver, - .next_mux = &usbc1_amd_fp5_usb_mux, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PS8743_I2C_ADDR1_FLAG, + .driver = &ps8743_usb_mux_driver, + }, + .next = &usbc1_amd_fp5_usb_mux, } }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); @@ -264,8 +178,7 @@ void ppc_interrupt(enum gpio_signal signal) int board_set_active_charge_port(int port) { - int is_valid_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); int i; if (port == CHARGE_PORT_NONE) { @@ -286,7 +199,6 @@ int board_set_active_charge_port(int port) return EC_ERROR_INVAL; } - /* Check if the port is sourcing VBUS. */ if (ppc_is_sourcing_vbus(port)) { CPRINTFUSB("Skip enable C%d", port); @@ -368,27 +280,33 @@ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { }; BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); -static void reset_pd_port(int port, enum gpio_signal reset_gpio_l, - int hold_delay, int finish_delay) +static void reset_nct38xx_port(int port) { + enum gpio_signal reset_gpio_l; + + if (port == USBC_PORT_C0) + reset_gpio_l = GPIO_USB_C0_TCPC_RST_L; + else if (port == USBC_PORT_C1) + reset_gpio_l = GPIO_USB_C1_TCPC_RST_L; + else + /* Invalid port: do nothing */ + return; + gpio_set_level(reset_gpio_l, 0); - msleep(hold_delay); + msleep(NCT38XX_RESET_HOLD_DELAY_MS); gpio_set_level(reset_gpio_l, 1); - if (finish_delay) - msleep(finish_delay); + nct38xx_reset_notify(port); + if (NCT3807_RESET_POST_DELAY_MS != 0) + msleep(NCT3807_RESET_POST_DELAY_MS); } void board_reset_pd_mcu(void) { /* Reset TCPC0 */ - reset_pd_port(USBC_PORT_C0, GPIO_USB_C0_TCPC_RST_L, - NCT38XX_RESET_HOLD_DELAY_MS, - NCT38XX_RESET_POST_DELAY_MS); + reset_nct38xx_port(USBC_PORT_C0); /* Reset TCPC1 */ - reset_pd_port(USBC_PORT_C1, GPIO_USB_C1_TCPC_RST_L, - NCT38XX_RESET_HOLD_DELAY_MS, - NCT38XX_RESET_POST_DELAY_MS); + reset_nct38xx_port(USBC_PORT_C1); } uint16_t tcpc_get_alert_status(void) @@ -434,11 +352,11 @@ void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -452,11 +370,9 @@ int board_pd_set_frs_enable(int port, int enable) /* Use the TCPC to enable fast switch when FRS included */ if (port == USBC_PORT_C0) { - rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, - !!enable); + rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, !!enable); } else { - rv = ioex_set_level(IOEX_USB_C1_TCPC_FASTSW_CTL_EN, - !!enable); + rv = ioex_set_level(IOEX_USB_C1_TCPC_FASTSW_CTL_EN, !!enable); } return rv; @@ -480,16 +396,12 @@ static void setup_fw_config(void) ioex_enable_interrupt(IOEX_USB_C0_SBU_FAULT_ODL); ioex_enable_interrupt(IOEX_USB_C1_SBU_FAULT_DB_ODL); - if (ec_config_has_lid_angle_tablet_mode()) { - /* Enable Gyro interrupts */ - gpio_enable_interrupt(GPIO_6AXIS_INT_L); - } else { - motion_sensor_count = 0; - /* Device is clamshell only */ - tablet_set_mode(0); - /* Gyro is not present, don't allow line to float */ - gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); - } + /* + * If keyboard is US2(KB_LAYOUT_1), we need translate right ctrl + * to backslash(\|) key. + */ + if (ec_config_keyboard_layout() == KB_LAYOUT_1) + set_scancode_set2(4, 0, get_scancode_set2(2, 7)); } DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); @@ -505,12 +417,12 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); struct ioexpander_config_t ioex_config[] = { [IOEX_C0_NCT3807] = { .i2c_host_port = I2C_PORT_TCPC0, - .i2c_slave_addr = NCT38XX_I2C_ADDR1_1_FLAGS, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, .drv = &nct38xx_ioexpander_drv, }, [IOEX_C1_NCT3807] = { .i2c_host_port = I2C_PORT_TCPC1, - .i2c_slave_addr = NCT38XX_I2C_ADDR1_1_FLAGS, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, .drv = &nct38xx_ioexpander_drv, }, }; @@ -520,3 +432,117 @@ int usb_port_enable[USBA_PORT_COUNT] = { IOEX_EN_USB_A0_5V, IOEX_EN_USB_A1_5V_DB, }; + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, { 1, 4 }, + { 1, 3 }, { 1, 6 }, { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, + { 2, 6 }, { 2, 7 }, { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, + { 2, 3 }, { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif + +#define CHARGING_CURRENT_500mA 500 + +int charger_profile_override(struct charge_state_data *curr) +{ + static int thermal_sensor_temp; + static int prev_thermal_sensor_temp; + static int limit_charge; + static int limit_usbc_power; + static int limit_usbc_power_backup; + enum tcpc_rp_value rp; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return 0; + + temp_sensor_read(TEMP_SENSOR_CHARGER, &thermal_sensor_temp); + + if (thermal_sensor_temp > prev_thermal_sensor_temp) { + if (thermal_sensor_temp > C_TO_K(63)) + limit_usbc_power = 1; + + if (thermal_sensor_temp > C_TO_K(58)) { + if (curr->state == ST_CHARGE) + limit_charge = 1; + } + } else if (thermal_sensor_temp < prev_thermal_sensor_temp) { + if (thermal_sensor_temp < C_TO_K(62)) + limit_usbc_power = 0; + + if (thermal_sensor_temp < C_TO_K(57)) { + if (curr->state == ST_CHARGE) + limit_charge = 0; + } + } + + if (limit_charge) + curr->requested_current = CHARGING_CURRENT_500mA; + else + curr->requested_current = curr->batt.desired_current; + + if (limit_usbc_power != limit_usbc_power_backup) { + if (limit_usbc_power == 1) + rp = TYPEC_RP_1A5; + else + rp = TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + limit_usbc_power_backup = limit_usbc_power; + } + + prev_thermal_sensor_temp = thermal_sensor_temp; + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +__override struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT] = { + [TEMP_SENSOR_CHARGER] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(63), + [EC_TEMP_THRESH_HALT] = C_TO_K(92), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(62), + } + }, + [TEMP_SENSOR_SOC] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + [EC_TEMP_THRESH_HALT] = C_TO_K(85), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(77), + } + }, + [TEMP_SENSOR_CPU] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), + [EC_TEMP_THRESH_HALT] = C_TO_K(90), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(83), + } + }, +}; diff --git a/board/dirinboz/board.h b/board/dirinboz/board.h index 2538918873..8c77d0665e 100644 --- a/board/dirinboz/board.h +++ b/board/dirinboz/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,20 +10,24 @@ #define VARIANT_ZORK_DALBOZ -#include #include "baseboard.h" -#define CONFIG_IO_EXPANDER_PCAL6408 -#define CONFIG_MKBP_USE_GPIO +#include #define CONFIG_USBC_PPC_NX20P3483 -#define CONFIG_USB_MUX_PS8740 #define CONFIG_USB_MUX_PS8743 #define CONFIG_USB_MUX_RUNTIME_CONFIG #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PORT_ENABLE_DYNAMIC +#undef CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 40000 + +#define CONFIG_CHARGER_PROFILE_OVERRIDE + +#define CONFIG_KEYBOARD_FACTORY_TEST + /* USB-A config */ #define GPIO_USB1_ILIM_SEL IOEX_USB_A0_CHARGE_EN_L #define GPIO_USB2_ILIM_SEL IOEX_USB_A1_CHARGE_EN_DB_L @@ -31,81 +35,52 @@ /* LED */ #undef CONFIG_LED_ONOFF_STATES -/* Motion sensing drivers */ -#define CONFIG_ACCELGYRO_LSM6DSM -#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCEL_LIS2DWL -#define CONFIG_ACCEL_INTERRUPTS -#define CONFIG_CMD_ACCELS -#define CONFIG_CMD_ACCEL_INFO -#define CONFIG_TABLET_MODE -#define CONFIG_LID_ANGLE -#define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL - - - /* GPIO mapping from board specific name to EC common name. */ -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL -#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL -#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL -#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L -#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK -#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L -#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL -#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD -#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD -#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE #ifndef __ASSEMBLER__ /* This I2C moved. Temporarily detect and support the V0 HW. */ extern int I2C_PORT_BATTERY; -enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, - ADC_TEMP_SENSOR_SOC, - ADC_CH_COUNT -}; +enum adc_channel { ADC_TEMP_SENSOR_CHARGER, ADC_TEMP_SENSOR_SOC, ADC_CH_COUNT }; enum battery_type { BATTERY_SIMPLO_COS, BATTERY_SIMPLO_HIGHPOWER, BATTERY_SAMSUNG_SDI, - BATTERY_DANAPACK_ATL, - BATTERY_DANAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_DYNAPACK_COS, BATTERY_COSMX, BATTERY_TYPE_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_COUNT }; -enum ioex_port { - IOEX_C0_NCT3807 = 0, - IOEX_C1_NCT3807, - IOEX_PORT_COUNT -}; +enum ioex_port { IOEX_C0_NCT3807 = 0, IOEX_C1_NCT3807, IOEX_PORT_COUNT }; -#define PORT_TO_HPD(port) ((port == 0) \ - ? GPIO_USB3_C0_DP2_HPD \ - : GPIO_DP1_HPD) +#define PORT_TO_HPD(port) ((port == 0) ? GPIO_USB3_C0_DP2_HPD : GPIO_DP1_HPD) enum temp_sensor_id { TEMP_SENSOR_CHARGER = 0, @@ -114,22 +89,13 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum usba_port { - USBA_PORT_A0 = 0, - USBA_PORT_A1, - USBA_PORT_COUNT -}; +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; /***************************************************************************** * CBI EC FW Configuration */ -#include "cbi_ec_fw_config.h" /** * DALBOZ_MB_USBAC @@ -162,6 +128,8 @@ enum ec_cfg_usb_db_type { DIRINBOZ_DB_OPT1_USBC = 0, }; +#include "cbi_ec_fw_config.h" + static inline bool ec_config_has_hdmi_retimer_pi3hdx1204(void) { return 0; diff --git a/board/dirinboz/build.mk b/board/dirinboz/build.mk index 1c0cbc4f63..45c71f962c 100644 --- a/board/dirinboz/build.mk +++ b/board/dirinboz/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/dirinboz/ec.tasklist b/board/dirinboz/ec.tasklist index d9c1606eb2..779bd4fdd6 100644 --- a/board/dirinboz/ec.tasklist +++ b/board/dirinboz/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,7 +13,6 @@ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, TASK_STACK_SIZE) \ TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/dirinboz/gpio.inc b/board/dirinboz/gpio.inc index 042ae7fe4f..ab1b83c55f 100644 --- a/board/dirinboz/gpio.inc +++ b/board/dirinboz/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -24,12 +24,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_inter GPIO_INT(EC_WP_L, PIN(5, 0), GPIO_INT_BOTH, switch_interrupt) GPIO_INT(VOLDN_BTN_ODL, PIN(A, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) GPIO_INT(VOLUP_BTN_ODL, PIN(9, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, lsm6dsm_interrupt) /* GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an interrupt handler. */ GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) -GPIO(3AXIS_INT_L, PIN(9, 6), GPIO_INPUT | GPIO_PULL_DOWN) /* 3 Axis Accel */ GPIO(CCD_MODE_ODL, PIN(C, 6), GPIO_INPUT) /* Case Closed Debug Mode */ GPIO(PROCHOT_ODL, PIN(D, 5), GPIO_ODR_HIGH) /* PROCHOT to SOC */ GPIO(EC_BATT_PRES_ODL, PIN(4, 1), GPIO_INPUT) /* Battery Present */ diff --git a/board/dirinboz/led.c b/board/dirinboz/led.c index 624277d209..ff9bcd986b 100644 --- a/board/dirinboz/led.c +++ b/board/dirinboz/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,17 +7,12 @@ #include "charge_manager.h" #include "charge_state.h" #include "chipset.h" +#include "cros_board_info.h" #include "ec_commands.h" #include "gpio.h" +#include "hooks.h" #include "host_command.h" #include "led_common.h" -#include "hooks.h" - -#define BAT_LED_ON 0 -#define BAT_LED_OFF 1 - -#define POWER_LED_ON 0 -#define POWER_LED_OFF 1 #define LED_TICKS_PER_CYCLE 10 #define LED_ON_TICKS 5 @@ -33,35 +28,43 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; -enum led_port { - LEFT_PORT = 0, - RIGHT_PORT -}; +enum led_port { LEFT_PORT = 0, RIGHT_PORT }; static void led_set_color_battery(int port, enum led_color color) { - enum gpio_signal amber_led, white_led; + int amber_led, white_led; + uint32_t board_ver = 0; + int led_batt_on_lvl, led_batt_off_lvl; + cbi_get_board_version(&board_ver); amber_led = (port == LEFT_PORT ? GPIO_LED_CHRG_L : - IOEX_C1_CHARGER_LED_AMBER_DB); + IOEX_C1_CHARGER_LED_AMBER_DB); white_led = (port == LEFT_PORT ? GPIO_LED_FULL_L : - IOEX_C1_CHARGER_LED_WHITE_DB); + IOEX_C1_CHARGER_LED_WHITE_DB); + + if ((board_ver >= 3) && (port == RIGHT_PORT)) { + led_batt_on_lvl = 1; + led_batt_off_lvl = 0; + } else { + led_batt_on_lvl = 0; + led_batt_off_lvl = 1; + } switch (color) { case LED_WHITE: - gpio_or_ioex_set_level(white_led, BAT_LED_ON); - gpio_or_ioex_set_level(amber_led, BAT_LED_OFF); + gpio_or_ioex_set_level(white_led, led_batt_on_lvl); + gpio_or_ioex_set_level(amber_led, led_batt_off_lvl); break; case LED_AMBER: - gpio_or_ioex_set_level(white_led, BAT_LED_OFF); - gpio_or_ioex_set_level(amber_led, BAT_LED_ON); + gpio_or_ioex_set_level(white_led, led_batt_off_lvl); + gpio_or_ioex_set_level(amber_led, led_batt_on_lvl); break; case LED_OFF: - gpio_or_ioex_set_level(white_led, BAT_LED_OFF); - gpio_or_ioex_set_level(amber_led, BAT_LED_OFF); + gpio_or_ioex_set_level(white_led, led_batt_off_lvl); + gpio_or_ioex_set_level(amber_led, led_batt_off_lvl); break; default: break; @@ -120,17 +123,16 @@ static void set_active_port_color(enum led_color color) if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) led_set_color_battery(RIGHT_PORT, - (port == RIGHT_PORT) ? color : LED_OFF); + (port == RIGHT_PORT) ? color : LED_OFF); if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) led_set_color_battery(LEFT_PORT, - (port == LEFT_PORT) ? color : LED_OFF); + (port == LEFT_PORT) ? color : LED_OFF); } static void led_set_battery(void) { static int battery_ticks; static int power_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; @@ -139,32 +141,33 @@ static void led_set_battery(void) * design, blinking both two side battery white LEDs to indicate * system suspend with non-charging state. */ - if (chipset_in_state(CHIPSET_STATE_SUSPEND | - CHIPSET_STATE_STANDBY) && - charge_get_state() != PWR_STATE_CHARGE) { - + if (chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_STANDBY) && + led_pwr_get_state() != LED_PWRS_CHARGE) { power_ticks++; - led_set_color_battery(RIGHT_PORT, power_ticks & 0x4 ? - LED_WHITE : LED_OFF); - led_set_color_battery(LEFT_PORT, power_ticks & 0x4 ? - LED_WHITE : LED_OFF); + led_set_color_battery(RIGHT_PORT, + power_ticks & 0x4 ? LED_WHITE : LED_OFF); + led_set_color_battery(LEFT_PORT, + power_ticks & 0x4 ? LED_WHITE : LED_OFF); return; } power_ticks = 0; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate when charging, even in suspend. */ set_active_port_color(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { if (charge_get_percent() < 10) - led_set_color_battery(RIGHT_PORT, - (battery_ticks % LED_TICKS_PER_CYCLE - < LED_ON_TICKS) ? LED_WHITE : LED_OFF); + led_set_color_battery( + RIGHT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); else led_set_color_battery(RIGHT_PORT, LED_OFF); } @@ -172,20 +175,21 @@ static void led_set_battery(void) if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) led_set_color_battery(LEFT_PORT, LED_OFF); break; - case PWR_STATE_ERROR: - set_active_port_color((battery_ticks & 0x2) ? - LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: set_active_port_color(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - set_active_port_color((battery_ticks % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_AMBER : LED_OFF); - else - set_active_port_color(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ diff --git a/board/dirinboz/vif_override.xml b/board/dirinboz/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/dirinboz/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/discovery-stm32f072/board.c b/board/discovery-stm32f072/board.c index b1b9346cd3..1ba70c99d9 100644 --- a/board/discovery-stm32f072/board.c +++ b/board/discovery-stm32f072/board.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,11 +13,11 @@ #include "spi.h" #include "task.h" #include "usart-stm32f0.h" -#include "usart_tx_dma.h" #include "usart_rx_dma.h" +#include "usart_tx_dma.h" +#include "usb-stream.h" #include "usb_gpio.h" #include "usb_spi.h" -#include "usb-stream.h" #include "util.h" /****************************************************************************** @@ -25,34 +25,26 @@ */ void button_event(enum gpio_signal signal); +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" static enum gpio_signal const usb_gpio_list[] = { - GPIO_USER_BUTTON, - GPIO_LED_U, - GPIO_LED_D, - GPIO_LED_L, - GPIO_LED_R, + GPIO_USER_BUTTON, GPIO_LED_U, GPIO_LED_D, GPIO_LED_L, GPIO_LED_R, }; /* * This instantiates struct usb_gpio_config const usb_gpio, plus several other * variables, all named something beginning with usb_gpio_ */ -USB_GPIO_CONFIG(usb_gpio, - usb_gpio_list, - USB_IFACE_GPIO, - USB_EP_GPIO); +USB_GPIO_CONFIG(usb_gpio, usb_gpio_list, USB_IFACE_GPIO, USB_EP_GPIO); /****************************************************************************** * Setup USART1 as a loopback device, it just echo's back anything sent to it. */ static struct usart_config const loopback_usart; -static struct queue const loopback_queue = - QUEUE_DIRECT(64, uint8_t, - loopback_usart.producer, - loopback_usart.consumer); +static struct queue const loopback_queue = QUEUE_DIRECT( + 64, uint8_t, loopback_usart.producer, loopback_usart.consumer); static struct usart_rx_dma const loopback_rx_dma = USART_RX_DMA(STM32_DMAC_CH3, 8); @@ -60,14 +52,9 @@ static struct usart_rx_dma const loopback_rx_dma = static struct usart_tx_dma const loopback_tx_dma = USART_TX_DMA(STM32_DMAC_CH2, 16); -static struct usart_config const loopback_usart = - USART_CONFIG(usart1_hw, - loopback_rx_dma.usart_rx, - loopback_tx_dma.usart_tx, - 115200, - 0, - loopback_queue, - loopback_queue); +static struct usart_config const loopback_usart = USART_CONFIG( + usart1_hw, loopback_rx_dma.usart_rx, loopback_tx_dma.usart_tx, 115200, + 0, loopback_queue, loopback_queue); /****************************************************************************** * Forward USART4 as a simple USB serial interface. @@ -75,36 +62,24 @@ static struct usart_config const loopback_usart = static struct usart_config const forward_usart; struct usb_stream_config const forward_usb; -static struct queue const usart_to_usb = QUEUE_DIRECT(64, uint8_t, - forward_usart.producer, - forward_usb.consumer); -static struct queue const usb_to_usart = QUEUE_DIRECT(64, uint8_t, - forward_usb.producer, - forward_usart.consumer); +static struct queue const usart_to_usb = + QUEUE_DIRECT(64, uint8_t, forward_usart.producer, forward_usb.consumer); +static struct queue const usb_to_usart = + QUEUE_DIRECT(64, uint8_t, forward_usb.producer, forward_usart.consumer); static struct usart_tx_dma const forward_tx_dma = USART_TX_DMA(STM32_DMAC_CH7, 16); static struct usart_config const forward_usart = - USART_CONFIG(usart4_hw, - usart_rx_interrupt, - forward_tx_dma.usart_tx, - 115200, - 0, - usart_to_usb, - usb_to_usart); - -#define USB_STREAM_RX_SIZE 16 -#define USB_STREAM_TX_SIZE 16 - -USB_STREAM_CONFIG(forward_usb, - USB_IFACE_STREAM, - USB_STR_STREAM_NAME, - USB_EP_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart, - usart_to_usb) + USART_CONFIG(usart4_hw, usart_rx_interrupt, forward_tx_dma.usart_tx, + 115200, 0, usart_to_usb, usb_to_usart); + +#define USB_STREAM_RX_SIZE 16 +#define USB_STREAM_TX_SIZE 16 + +USB_STREAM_CONFIG(forward_usb, USB_IFACE_STREAM, USB_STR_STREAM_NAME, + USB_EP_STREAM, USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, + usb_to_usart, usart_to_usb) /****************************************************************************** * Handle button presses by cycling the LEDs on the board. Also run a tick @@ -135,17 +110,17 @@ DECLARE_HOOK(HOOK_TICK, usb_gpio_tick, HOOK_PRIO_DEFAULT); * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("discovery-stm32f072"), - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_STREAM_NAME] = USB_STRING_DESC("Forward"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("discovery-stm32f072"), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_STREAM_NAME] = USB_STRING_DESC("Forward"), [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Shell"), + [USB_STR_SPI_NAME] = USB_STRING_DESC("SPI"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); - /****************************************************************************** * Support SPI bridging over USB, this requires usb_spi_board_enable and * usb_spi_board_disable to be defined to enable and disable the SPI bridge. @@ -153,11 +128,11 @@ BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); /* SPI devices */ const struct spi_device_t spi_devices[] = { - { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS}, + { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS, USB_SPI_ENABLED }, }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); -void usb_spi_board_enable(struct usb_spi_config const *config) +void usb_spi_board_enable(void) { /* Remap SPI2 to DMA channels 6 and 7 */ STM32_SYSCFG_CFGR1 |= BIT(24); @@ -175,12 +150,12 @@ void usb_spi_board_enable(struct usb_spi_config const *config) STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(&spi_devices[0], 1); } -void usb_spi_board_disable(struct usb_spi_config const *config) +void usb_spi_board_disable(void) { - spi_enable(CONFIG_SPI_FLASH_PORT, 0); + spi_enable(&spi_devices[0], 0); /* Disable clocks to SPI2 module */ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; @@ -189,8 +164,6 @@ void usb_spi_board_disable(struct usb_spi_config const *config) gpio_config_module(MODULE_SPI_FLASH, 0); } -USB_SPI_CONFIG(usb_spi, USB_IFACE_SPI, USB_EP_SPI, 0); - /****************************************************************************** * Initialize board. */ @@ -204,6 +177,6 @@ static void board_init(void) usart_init(&loopback_usart); usart_init(&forward_usart); - usb_spi_enable(&usb_spi, 1); + usb_spi_enable(1); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/discovery-stm32f072/board.h b/board/discovery-stm32f072/board.h index ba5894db56..b112f14f9f 100644 --- a/board/discovery-stm32f072/board.h +++ b/board/discovery-stm32f072/board.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -23,7 +23,6 @@ #define CONFIG_UART_CONSOLE 2 /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_HW_CRC /* USB Configuration */ @@ -32,27 +31,26 @@ #define CONFIG_USB_CONSOLE /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_STREAM 0 -#define USB_IFACE_GPIO 1 -#define USB_IFACE_SPI 2 +#define USB_IFACE_STREAM 0 +#define USB_IFACE_GPIO 1 +#define USB_IFACE_SPI 2 #define USB_IFACE_CONSOLE 3 -#define USB_IFACE_COUNT 4 +#define USB_IFACE_COUNT 4 /* USB endpoint indexes (use define rather than enum to expand them) */ #define USB_EP_CONTROL 0 -#define USB_EP_STREAM 1 -#define USB_EP_GPIO 2 -#define USB_EP_SPI 3 +#define USB_EP_STREAM 1 +#define USB_EP_GPIO 2 +#define USB_EP_SPI 3 #define USB_EP_CONSOLE 4 -#define USB_EP_COUNT 5 +#define USB_EP_COUNT 5 /* Enable control of GPIOs over USB */ #define CONFIG_USB_GPIO /* Enable control of SPI over USB */ -#define CONFIG_SPI_MASTER -#define CONFIG_SPI_FLASH_PORT 0 /* First SPI master port */ - +#define CONFIG_SPI_CONTROLLER +#define CONFIG_SPI_FLASH_PORT 0 /* First SPI controller port */ #define CONFIG_USB_SPI @@ -80,6 +78,7 @@ enum usb_strings { USB_STR_VERSION, USB_STR_STREAM_NAME, USB_STR_CONSOLE_NAME, + USB_STR_SPI_NAME, USB_STR_COUNT }; diff --git a/board/discovery-stm32f072/build.mk b/board/discovery-stm32f072/build.mk index c1892335ed..3e87efe412 100644 --- a/board/discovery-stm32f072/build.mk +++ b/board/discovery-stm32f072/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,3 +11,6 @@ CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f07x board-y=board.o + +test-list-y=\ + panic \ diff --git a/board/discovery-stm32f072/ec.tasklist b/board/discovery-stm32f072/ec.tasklist index cc4c2ad42d..2bd7e2f5ce 100644 --- a/board/discovery-stm32f072/ec.tasklist +++ b/board/discovery-stm32f072/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/discovery-stm32f072/gpio.inc b/board/discovery-stm32f072/gpio.inc index 65bdd0179b..25b5f1b0e0 100644 --- a/board/discovery-stm32f072/gpio.inc +++ b/board/discovery-stm32f072/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/discovery-stm32f072/openocd-flash.cfg b/board/discovery-stm32f072/openocd-flash.cfg index ec32416934..05a697acf8 100644 --- a/board/discovery-stm32f072/openocd-flash.cfg +++ b/board/discovery-stm32f072/openocd-flash.cfg @@ -1,4 +1,4 @@ -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/board/discovery/board.c b/board/discovery/board.c index 0d4cde2e7c..7892f1a5e0 100644 --- a/board/discovery/board.c +++ b/board/discovery/board.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,6 +17,7 @@ void button_event(enum gpio_signal signal); +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" void button_event(enum gpio_signal signal) @@ -39,10 +40,8 @@ DECLARE_HOOK(HOOK_TICK, usb_gpio_tick, HOOK_PRIO_DEFAULT); */ static struct usart_config const loopback_usart; -static struct queue const loopback_queue = - QUEUE_DIRECT(64, uint8_t, - loopback_usart.producer, - loopback_usart.consumer); +static struct queue const loopback_queue = QUEUE_DIRECT( + 64, uint8_t, loopback_usart.producer, loopback_usart.consumer); static struct usart_rx_dma const loopback_rx_dma = USART_RX_DMA(STM32_DMAC_CH6, 32); @@ -50,14 +49,9 @@ static struct usart_rx_dma const loopback_rx_dma = static struct usart_tx_dma const loopback_tx_dma = USART_TX_DMA(STM32_DMAC_CH7, 16); -static struct usart_config const loopback_usart = - USART_CONFIG(usart2_hw, - loopback_rx_dma.usart_rx, - loopback_tx_dma.usart_tx, - 115200, - 0, - loopback_queue, - loopback_queue); +static struct usart_config const loopback_usart = USART_CONFIG( + usart2_hw, loopback_rx_dma.usart_rx, loopback_tx_dma.usart_tx, 115200, + 0, loopback_queue, loopback_queue); /****************************************************************************** * Initialize board. diff --git a/board/discovery/board.h b/board/discovery/board.h index ddd2461a56..a722408e81 100644 --- a/board/discovery/board.h +++ b/board/discovery/board.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -25,9 +25,14 @@ #ifndef __ASSEMBLER__ -/* Timer selection */ -#define TIM_CLOCK_MSB 3 -#define TIM_CLOCK_LSB 4 +/* Timer selection + * + * "discovery" is an STM32L152RC, which is a "Category 3" product that + * has the 32-bit timer TIM5. See Section 17 "General-purpose Timers" and + * "Table 3. STM32L15xxx product categories": + * https://www.st.com/resource/en/reference_manual/cd00240193-stm32l100xx-stm32l151xx-stm32l152xx-and-stm32l162xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf + */ +#define TIM_CLOCK32 5 #include "gpio_signal.h" diff --git a/board/discovery/build.mk b/board/discovery/build.mk index 42f9f9a0fc..e07d8af33d 100644 --- a/board/discovery/build.mk +++ b/board/discovery/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. +# Copyright 2013 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/discovery/ec.tasklist b/board/discovery/ec.tasklist index 3822ab3779..e58390c01d 100644 --- a/board/discovery/ec.tasklist +++ b/board/discovery/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/discovery/gpio.inc b/board/discovery/gpio.inc index 821f38ca46..da2742ff7a 100644 --- a/board/discovery/gpio.inc +++ b/board/discovery/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/discovery/openocd-flash.cfg b/board/discovery/openocd-flash.cfg index 6426ad5473..f87c191576 100644 --- a/board/discovery/openocd-flash.cfg +++ b/board/discovery/openocd-flash.cfg @@ -1,4 +1,4 @@ -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/board/dojo/battery.c b/board/dojo/battery.c new file mode 100644 index 0000000000..a766ea3e59 --- /dev/null +++ b/board/dojo/battery.c @@ -0,0 +1,262 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_state.h" +#include "console.h" +#include "gpio.h" +#include "temp_sensor.h" +#include "util.h" + +const struct board_batt_params board_battery_info[] = { + /* DynaPack CosMX Battery Information */ + [BATTERY_DYNAPACK_COS] = { + .fuel_gauge = { + .manuf_name = "333-2C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + + /* DynaPack ATL Battery Information */ + [BATTERY_DYNAPACK_ATL] = { + .fuel_gauge = { + .manuf_name = "333-27-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + + /* Simplo CosMX Battery Information */ + [BATTERY_SIMPLO_COS] = { + .fuel_gauge = { + .manuf_name = "333-1C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + + /* Simplo HIGHPOWER Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-1D-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + + /* CosMX B00C4473A9D0002 Battery Information */ + [BATTERY_COS] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; + +int charger_profile_override(struct charge_state_data *curr) +{ + int chg_temp; + int prev_chg_lvl; + static int chg_lvl; + + if (chipset_in_state(CHIPSET_STATE_ON)) { + temp_sensor_read(TEMP_SENSOR_CHARGER, &chg_temp); + chg_temp = K_TO_C(chg_temp); + + prev_chg_lvl = chg_lvl; + if (chg_temp <= temp_chg_table[chg_lvl].lo_thre && chg_lvl > 0) + chg_lvl--; + else if (chg_temp >= temp_chg_table[chg_lvl].hi_thre && + chg_lvl < CHG_LEVEL_COUNT - 1) + chg_lvl++; + + curr->requested_current = MIN(curr->requested_current, + temp_chg_table[chg_lvl].chg_curr); + + if (chg_lvl != prev_chg_lvl) + ccprints("Override chg curr to %dmA by chg LEVEL_%d", + curr->requested_current, chg_lvl); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +enum battery_present batt_pres_prev = BP_NOT_SURE; + +/* + * Physical detection of battery. + */ +static enum battery_present battery_check_present_status(void) +{ + enum battery_present batt_pres = BP_NOT_SURE; + + /* Get the physical hardware status */ + batt_pres = battery_hw_present(); + + /* + * If the battery is not physically connected, then no need to perform + * any more checks. + */ + if (batt_pres == BP_NO) + return batt_pres; + + /* + * If the battery is present now and was present last time we checked, + * return early. + */ + if (batt_pres == batt_pres_prev) + return batt_pres; + + /* + * Check battery disconnect status. If we are unable to read battery + * disconnect status, then return BP_NOT_SURE. Battery could be in ship + * mode and might require pre-charge current to wake it up. BP_NO is not + * returned here because charger state machine will not provide + * pre-charge current assuming that battery is not present. + */ + if (battery_get_disconnect_state() == BATTERY_DISCONNECT_ERROR) + return BP_NOT_SURE; + + /* Ensure the battery is not in cutoff state */ + if (battery_is_cut_off() != BATTERY_CUTOFF_STATE_NORMAL) + return BP_NO; + + return batt_pres; +} + +enum battery_present battery_is_present(void) +{ + batt_pres_prev = battery_check_present_status(); + return batt_pres_prev; +} + +enum battery_present battery_hw_present(void) +{ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/dojo/board.c b/board/dojo/board.c new file mode 100644 index 0000000000..28788d4641 --- /dev/null +++ b/board/dojo/board.c @@ -0,0 +1,531 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Dojo board configuration */ + +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/accel_kionix.h" +#include "driver/accel_kx022.h" +#include "driver/accelgyro_bmi260_public.h" +#include "driver/accelgyro_bmi_common_public.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/retimer/ps8802.h" +#include "driver/usb_mux/anx3443.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "motion_sense.h" +#include "power.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "system.h" +#include "usb_mux.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +uint32_t board_version; +enum ec_ssfc_base_sensor base_sensor; + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +/* Support keyboard factory test */ +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 30 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { GPIO_KSO_H, 4 }, { GPIO_KSO_H, 0 }, + { GPIO_KSO_H, 1 }, { GPIO_KSO_H, 3 }, { GPIO_KSO_H, 2 }, + { -1, -1 }, { -1, -1 }, { GPIO_KSO_L, 5 }, + { GPIO_KSO_L, 6 }, { -1, -1 }, { GPIO_KSO_L, 3 }, + { GPIO_KSO_L, 2 }, { GPIO_KSI, 0 }, { GPIO_KSO_L, 1 }, + { GPIO_KSO_L, 4 }, { GPIO_KSI, 3 }, { GPIO_KSI, 2 }, + { GPIO_KSO_L, 0 }, { GPIO_KSI, 5 }, { GPIO_KSI, 4 }, + { GPIO_KSO_L, 7 }, { GPIO_KSI, 6 }, { GPIO_KSI, 7 }, + { GPIO_KSI, 1 }, { -1, -1 }, { GPIO_KSO_H, 5 }, + { -1, -1 }, { GPIO_KSO_H, 6 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif + +/* Vol-up key matrix at T13 */ +const struct vol_up_key vol_up_key_matrix_T13 = { + .row = 3, + .col = 5, +}; + +/* Vol-up key matrix at T12 */ +const struct vol_up_key vol_up_key_matrix_T12 = { + .row = 1, + .col = 5, +}; + +/* Vol-up key update */ +static void board_update_vol_up_key(void) +{ + if (board_version >= 2) { + if (get_cbi_fw_config_kblayout() == KB_BL_TOGGLE_KEY_PRESENT) { + /* + * Set vol up key to T13 for KB_BL_TOGGLE_KEY_PRESENT + * and board_version >= 2 + */ + set_vol_up_key(vol_up_key_matrix_T13.row, + vol_up_key_matrix_T13.col); + } else { + /* + * Set vol up key to T12 for KB_BL_TOGGLE_KEY_ABSENT + * and board_version >= 2 + */ + set_vol_up_key(vol_up_key_matrix_T12.row, + vol_up_key_matrix_T12.col); + } + } else { + /* Set vol up key to T13 for board_version < 2 */ + set_vol_up_key(vol_up_key_matrix_T13.row, + vol_up_key_matrix_T13.col); + } +} + +/* Temperature charging table */ +const struct temp_chg_struct temp_chg_table[] = { + [LEVEL_0] = { + .lo_thre = 0, + .hi_thre = 68, + .chg_curr = 3000, + }, + [LEVEL_1] = { + .lo_thre = 63, + .hi_thre = 74, + .chg_curr = 1500, + }, + [LEVEL_2] = { + .lo_thre = 69, + .hi_thre = 100, + .chg_curr = 500, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_chg_table) == CHG_LEVEL_COUNT); + +/* Sensor */ +static struct mutex g_base_mutex; +static struct mutex g_lid_mutex; + +static struct icm_drv_data_t g_icm426xx_data; +static struct icm_drv_data_t g_icm42607_data; +static struct bmi_drv_data_t g_bmi260_data; +static struct kionix_accel_data g_kx022_data; + +/* Matrix to rotate accelrator into standard reference frame */ +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t icm42607_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t icm426xx_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t motion_sensors[] = { + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g, enough for laptop. */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t icm42607_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &icm42607_standard_ref, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm42607_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &icm42607_standard_ref, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs. */ + .rot_standard_ref = &icm426xx_standard_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &icm426xx_standard_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +static void board_update_motion_sensor_config(void) +{ + if (board_version <= 1 || base_sensor == SSFC_SENSOR_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE Accelgyro is ICM426XX"); + } else if (base_sensor == SSFC_SENSOR_ICM42607) { + motion_sensors[BASE_ACCEL] = icm42607_base_accel; + motion_sensors[BASE_GYRO] = icm42607_base_gyro; + ccprints("BASE Accelgyro is ICM42607"); + } else { + ccprints("BASE Accelgyro is BMI260"); + } +} + +void motion_interrupt(enum gpio_signal signal) +{ + if (board_version <= 1 || base_sensor == SSFC_SENSOR_ICM426XX) + icm426xx_interrupt(signal); + else if (base_sensor == SSFC_SENSOR_ICM42607) + icm42607_interrupt(signal); + else + bmi260_interrupt(signal); +} + +/* PWM */ + +/* + * PWM channels. Must be in the exactly same order as in enum pwm_channel. + * There total three 16 bits clock prescaler registers for all pwm channels, + * so use the same frequency and prescaler register setting is required if + * number of pwm channel greater than three. + */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_C1_WHITE] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4, + }, + [PWM_CH_LED_C1_AMBER] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4, + }, + [PWM_CH_LED_PWR] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4, + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .freq_hz = 2400, + .pcfsr_sel = PWM_PRESCALER_C6, + }, + [PWM_CH_LED_C0_WHITE] = { + .channel = 6, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4, + }, + [PWM_CH_LED_C0_AMBER] = { + .channel = 7, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* USB Mux */ + +static int board_ps8762_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + /* Make sure the PS8802 is awake */ + RETURN_ERROR(ps8802_i2c_wake(me)); + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + RETURN_ERROR(ps8802_i2c_field_update16( + me, PS8802_REG_PAGE2, PS8802_REG2_USB_SSEQ_LEVEL, + PS8802_USBEQ_LEVEL_UP_MASK, + PS8802_USBEQ_LEVEL_UP_12DB)); + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* Boost the DP gain */ + RETURN_ERROR(ps8802_i2c_field_update8( + me, PS8802_REG_PAGE2, PS8802_REG2_DPEQ_LEVEL, + PS8802_DPEQ_LEVEL_UP_MASK, PS8802_DPEQ_LEVEL_UP_9DB)); + } + + return EC_SUCCESS; +} + +static int board_ps8762_mux_init(const struct usb_mux *me) +{ + return ps8802_i2c_field_update8(me, PS8802_REG_PAGE1, PS8802_REG_DCIRX, + PS8802_AUTO_DCI_MODE_DISABLE | + PS8802_FORCE_DCI_MODE, + PS8802_AUTO_DCI_MODE_DISABLE); +} + +static int board_anx3443_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + gpio_set_level(GPIO_USB_C1_DP_IN_HPD, + mux_state & USB_PD_MUX_DP_ENABLED); + return EC_SUCCESS; +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX0, + .i2c_addr_flags = PS8802_I2C_ADDR_FLAGS, + .driver = &ps8802_usb_mux_driver, + .board_init = &board_ps8762_mux_init, + .board_set = &board_ps8762_mux_set, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_USB_MUX1, + .i2c_addr_flags = ANX3443_I2C_ADDR0_FLAGS, + .driver = &anx3443_usb_mux_driver, + .board_set = &board_anx3443_mux_set, + }, + }, +}; + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Limit input current lower than 2944 mA for safety */ + charge_ma = MIN(charge_ma, 2944); + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +/* NVME */ +static void nvme_enable(int enable) +{ + gpio_set_level(GPIO_EN_PP3300_SSD, enable); +} + +void suspend_resume_power_signal_interrupt(enum gpio_signal signal) +{ + /* AP resume */ + if (gpio_get_level(signal) == GPIO_SIGNAL_RESUME) + nvme_enable(1); + /* AP suspend */ + else + nvme_enable(0); + + power_signal_interrupt(signal); +} + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable motion sensor interrupt */ + gpio_enable_interrupt(GPIO_BASE_IMU_INT_L); + gpio_enable_interrupt(GPIO_LID_ACCEL_INT_L); + + /* Store board version for use of something */ + cbi_get_board_version(&board_version); + + /* Store base sensor to recognize which base sensor we are using */ + base_sensor = get_cbi_ssfc_base_sensor(); + + /* Make sure that nvme can be enabled/disabled when board init */ + if (gpio_get_level(GPIO_AP_IN_SLEEP_L) == GPIO_SIGNAL_RESUME) + nvme_enable(1); + else + nvme_enable(0); + + board_update_motion_sensor_config(); + board_update_vol_up_key(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_do_chipset_resume(void) +{ + gpio_set_level(GPIO_EN_KB_BL, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_do_chipset_resume, HOOK_PRIO_DEFAULT); + +static void board_do_chipset_suspend(void) +{ + gpio_set_level(GPIO_EN_KB_BL, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_do_chipset_suspend, HOOK_PRIO_DEFAULT); diff --git a/board/dojo/board.h b/board/dojo/board.h new file mode 100644 index 0000000000..43ecd32d7c --- /dev/null +++ b/board/dojo/board.h @@ -0,0 +1,167 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Dojo board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* Optional features */ +#define CONFIG_LTO +#define CONFIG_PRESERVE_LOGS + +/* Watchdog period in ms */ +#undef CONFIG_WATCHDOG_PERIOD_MS +#define CONFIG_WATCHDOG_PERIOD_MS 2500 + +/* + * TODO: Remove this option once the VBAT no longer keeps high when + * system's power isn't presented. + */ +#define CONFIG_IT83XX_RESET_PD_CONTRACT_IN_BRAM + +/* Battery */ +#undef CONFIG_BATTERY_PRESENT_GPIO +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 +#define CONFIG_BATTERY_PRESENT_CUSTOM +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_VENDOR_PARAM + +/* BC12 */ + +/* Charger */ +#define CONFIG_CHARGER_PROFILE_OVERRIDE + +/* Chipset */ +#define CONFIG_CHIPSET_RESUME_INIT_HOOK + +/* PD / USB-C / PPC */ +#undef CONFIG_USB_PD_DEBUG_LEVEL /* default to 1, configurable in ec console \ + */ + +/* Optional console commands */ +#define CONFIG_CMD_FLASH +#define CONFIG_CMD_SCRATCHPAD + +#define CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV 9000 + +/* Keyboard */ +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_FACTORY_TEST +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV + +/* Sensor */ +#define CONFIG_GMR_TABLET_MODE +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_I2C_XFER_LARGE_TRANSFER + +/* ICM426XX Base accel/gyro */ +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* ICM42607 Base accel/gyro*/ +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* BMI260 accel/gyro in base */ +#define CONFIG_ACCELGYRO_BMI260 +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* KX022 Lid accel */ +#define CONFIG_ACCEL_KX022 + +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_UPDATE + +/* SPI / Host Command */ +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + +/* USB-A */ +#define USBA_PORT_COUNT 1 + +/* Temperature */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum battery_type { + BATTERY_DYNAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_SIMPLO_COS, + BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COS, + BATTERY_TYPE_COUNT, +}; + +enum sensor_id { + BASE_ACCEL = 0, + BASE_GYRO, + LID_ACCEL, + SENSOR_COUNT, +}; + +enum pwm_channel { + PWM_CH_LED_C1_WHITE, + PWM_CH_LED_C1_AMBER, + PWM_CH_LED_PWR, + PWM_CH_KBLIGHT, + PWM_CH_LED_C0_WHITE, + PWM_CH_LED_C0_AMBER, + PWM_CH_COUNT, +}; + +/* Temperature charging level */ +enum temp_chg_lvl { + LEVEL_0 = 0, + LEVEL_1, + LEVEL_2, + CHG_LEVEL_COUNT, +}; + +/* Temperature charging struct */ +struct temp_chg_struct { + int lo_thre; + int hi_thre; + int chg_curr; +}; + +/* Forward declaration of temperature charging table */ +extern const struct temp_chg_struct temp_chg_table[]; + +/* Vol-up key matrix struct */ +struct vol_up_key { + uint8_t row; + uint8_t col; +}; + +/* AP in sleep power signal */ +enum ap_in_sleep_l_signal { + GPIO_SIGNAL_SUSPEND = 0, + GPIO_SIGNAL_RESUME, +}; +void suspend_resume_power_signal_interrupt(enum gpio_signal signal); + +int board_accel_force_mode_mask(void); +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/dojo/build.mk b/board/dojo/build.mk new file mode 100644 index 0000000000..740cd30a9d --- /dev/null +++ b/board/dojo/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build + +# the IC is ITE IT8xxx2 +CHIP:=it83xx +CHIP_FAMILY:=it8xxx2 +CHIP_VARIANT:=it81202bx_1024 +BASEBOARD:=cherry + +board-y+=led.o battery.o board.o cbi_fw_config.o cbi_ssfc.o diff --git a/board/dojo/cbi_fw_config.c b/board/dojo/cbi_fw_config.c new file mode 100644 index 0000000000..96e6d9b266 --- /dev/null +++ b/board/dojo/cbi_fw_config.c @@ -0,0 +1,41 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_fw_config.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +/**************************************************************************** + * Dojo CBI FW Configuration + */ + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache FW_CONFIG on init since we don't expect it to change in runtime */ +static uint32_t cached_fw_config; + +static void cbi_fw_config_init(void) +{ + if (cbi_get_fw_config(&cached_fw_config) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_fw_config = 0; + + CPRINTS("FW_CONFIG: 0x%04X", cached_fw_config); +} +DECLARE_HOOK(HOOK_INIT, cbi_fw_config_init, HOOK_PRIO_FIRST); + +enum fw_config_kblight_type get_cbi_fw_config_kblight(void) +{ + return ((cached_fw_config & FW_CONFIG_KB_BL_MASK) >> + FW_CONFIG_KB_BL_OFFSET); +} + +enum fw_config_kblayout_type get_cbi_fw_config_kblayout(void) +{ + return ((cached_fw_config & FW_CONFIG_KB_LAYOUT_MASK) >> + FW_CONFIG_KB_LAYOUT_OFFSET); +} diff --git a/board/dojo/cbi_fw_config.h b/board/dojo/cbi_fw_config.h new file mode 100644 index 0000000000..6ca0e5b9a8 --- /dev/null +++ b/board/dojo/cbi_fw_config.h @@ -0,0 +1,36 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DOJO_CBI_FW_CONFIG__H_ +#define _DOJO_CBI_FW_CONFIG__H_ + +/**************************************************************************** + * Dojo CBI FW Configuration + */ + +/* + * Keyboard backlight (bit 0) + */ +enum fw_config_kblight_type { + KB_BL_ABSENT = 0, + KB_BL_PRESENT = 1, +}; +#define FW_CONFIG_KB_BL_OFFSET 0 +#define FW_CONFIG_KB_BL_MASK GENMASK(0, 0) + +/* + * Keyboard layout (bit 4-5) + */ +enum fw_config_kblayout_type { + KB_BL_TOGGLE_KEY_ABSENT = 0, /* Vol-up key on T12 */ + KB_BL_TOGGLE_KEY_PRESENT = 1, /* Vol-up key on T13 */ +}; +#define FW_CONFIG_KB_LAYOUT_OFFSET 4 +#define FW_CONFIG_KB_LAYOUT_MASK GENMASK(5, 4) + +enum fw_config_kblight_type get_cbi_fw_config_kblight(void); +enum fw_config_kblayout_type get_cbi_fw_config_kblayout(void); + +#endif /* _DOJO_CBI_FW_CONFIG__H_ */ diff --git a/board/dojo/cbi_ssfc.c b/board/dojo/cbi_ssfc.c new file mode 100644 index 0000000000..3b7ed483f5 --- /dev/null +++ b/board/dojo/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dojo_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/dojo/cbi_ssfc.h b/board/dojo/cbi_ssfc.h new file mode 100644 index 0000000000..da37dbaca1 --- /dev/null +++ b/board/dojo/cbi_ssfc.h @@ -0,0 +1,57 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DOJO_CBI_SSFC__H_ +#define _DOJO_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dojo CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_ICM42607 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_BMI260 = 3, +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA422 = 1, + SSFC_SENSOR_KX022 = 2, +}; + +union dojo_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DOJO_CBI_SSFC__H_ */ diff --git a/board/dojo/ec.tasklist b/board/dojo/ec.tasklist new file mode 100644 index 0000000000..5ce0fab583 --- /dev/null +++ b/board/dojo/ec.tasklist @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(DPS, dps_task, NULL, 1280) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, 1024) \ + diff --git a/board/dojo/gpio.inc b/board/dojo/gpio.inc new file mode 100644 index 0000000000..35a0fa0eae --- /dev/null +++ b/board/dojo/gpio.inc @@ -0,0 +1,156 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH | GPIO_PULL_UP | + GPIO_HIB_WAKE_HIGH, power_button_interrupt) /* GSC_EC_PWR_BTN_ODL */ +GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, + lid_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(J, 7), GPIO_INT_BOTH, + gmr_tablet_switch_isr) + +/* Chipset interrupts */ +GPIO_INT(AP_EC_WARM_RST_REQ, PIN(D, 3), GPIO_INT_RISING | GPIO_SEL_1P8V, + chipset_reset_request_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 7), GPIO_INT_BOTH | GPIO_SEL_1P8V, + chipset_watchdog_interrupt) +GPIO_INT(AP_IN_SLEEP_L, PIN(F, 2), + GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + suspend_resume_power_signal_interrupt) +GPIO_INT(PMIC_EC_PWRGD, PIN(F, 3), + GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) + +/* Sensor Interrupts */ +GPIO_INT(BASE_IMU_INT_L, PIN(M, 3), GPIO_INT_FALLING | GPIO_SEL_1P8V, + motion_interrupt) +/* USB-C interrupts */ +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(D, 1), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL,PIN(I, 5), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_INT_ODL, PIN(B, 2), GPIO_INT_FALLING, rt1718s_tcpc_interrupt) +/* TODO: not used in other devices? */ +GPIO(LID_ACCEL_INT_L, PIN(M, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V) + +/* Volume button interrupts */ +GPIO_INT(VOLUME_DOWN_L, PIN(D, 5), GPIO_INT_BOTH | GPIO_PULL_UP, + button_interrupt) /* EC_VOLDN_BTN_ODL */ +GPIO_INT(VOLUME_UP_L, PIN(D, 6), GPIO_INT_BOTH | GPIO_PULL_UP, + button_interrupt) /* EC_VOLUP_BTN_ODL */ + +/* Other interrupts */ +GPIO_INT(AC_PRESENT, PIN(E, 5), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, + extpower_interrupt) /* AC_OK / AC_PRESENT in rev1+ */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, + uart_deepsleep_interrupt) /* UART_DEBUG_TX_EC_RX */ +GPIO_INT(WP, PIN(I, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, + switch_interrupt) /* EC_FLASH_WP_OD */ +GPIO_INT(SPI0_CS, PIN(M, 5), GPIO_INT_FALLING, + spi_event) /* SPI slave Chip Select -- AP_SPI_EC_CS_L */ +GPIO_INT(AP_XHCI_INIT_DONE, PIN(J, 5), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + xhci_init_done_interrupt) + +/* Power Sequencing Signals */ +GPIO(EC_PMIC_EN_ODL, PIN(D, 0), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_PMIC_WATCHDOG_L, PIN(H, 0), GPIO_ODR_LOW | GPIO_SEL_1P8V) +GPIO(EN_PP5000_A, PIN(C, 6), GPIO_OUT_HIGH) +GPIO(PG_MT6315_PROC_B_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(PG_MT6360_ODL, PIN(F, 1), GPIO_INPUT) +GPIO(EN_SLP_Z, PIN(E, 3), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(B, 6), GPIO_ODR_LOW) +GPIO(EC_BL_EN_OD, PIN(B, 5), GPIO_ODR_LOW | GPIO_SEL_1P8V) +GPIO(EN_PP3300_SSD, PIN(H, 1), GPIO_ODR_LOW) /* NVME power sequence control */ + +/* MKBP event synchronization */ +GPIO(EC_INT_L, PIN(E, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_AP_INT_ODL */ + +/* USB and USBC Signals */ +GPIO(DP_PATH_SEL, PIN(G, 0), GPIO_OUT_HIGH) +GPIO(DP_DEMUX_EN, PIN(G, 1), GPIO_OUT_LOW) +GPIO(EC_AP_DP_HPD_ODL, PIN(J, 0), GPIO_ODR_HIGH) +GPIO(EN_PP5000_USB_A0_VBUS_X,PIN(B, 7), GPIO_OUT_LOW) +GPIO(USB_C0_DP_IN_HPD, PIN(H, 4), GPIO_OUT_LOW) +GPIO(USB_C1_DP_IN_HPD, PIN(J, 1), GPIO_OUT_LOW) +GPIO(USB_C0_FRS_EN, PIN(F, 0), GPIO_OUT_LOW) + +/* Misc Signals */ +GPIO(EN_KB_BL, PIN(J, 2), GPIO_OUT_LOW) +GPIO(EC_BATT_PRES_ODL, PIN(C, 0), GPIO_INPUT) +GPIO(EN_EC_ID_ODL, PIN(H, 5), GPIO_ODR_LOW) +GPIO(ENTERING_RW, PIN(C, 5), GPIO_OUT_LOW) /* EC_ENTERING_RW */ +GPIO(EN_5V_USM, PIN(G, 3), GPIO_OUT_LOW) +GPIO(USB_A0_FAULT_ODL, PIN(J, 6), GPIO_INPUT) +GPIO(PACKET_MODE_EN, PIN(D, 4), GPIO_OUT_LOW) /* EC_GSC_PACKET_MODE */ + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) /* I2C_CHG_BATT_SCL */ +GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) /* I2C_CHG_BATT_SDA */ +GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SCL */ +GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SDA */ +GPIO(I2C_C_SCL, PIN(F, 6), GPIO_INPUT) /* I2C_USB_C0_SCL */ +GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) /* I2C_USB_C0_SDA */ +GPIO(I2C_E_SCL, PIN(E, 0), GPIO_INPUT) /* I2C_USB_C1_SCL */ +GPIO(I2C_E_SDA, PIN(E, 7), GPIO_INPUT) /* I2C_USB_C1_SDA */ +GPIO(I2C_F_SCL, PIN(A, 4), GPIO_INPUT) /* Rev 2+ I2C_PROG_SCL */ +GPIO(I2C_F_SDA, PIN(A, 5), GPIO_INPUT) /* Rev 2+ I2C_PROG_SDA */ + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A */ +ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C B */ +ALTERNATE(PIN_MASK(F, 0xC0), 1, MODULE_I2C, 0) /* I2C C */ +ALTERNATE(PIN_MASK(E, 0x81), 1, MODULE_I2C, 0) /* I2C E */ + +/* UART */ +ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, 0) /* EC to Servo */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, 0b11001111), 1, MODULE_PWM, 0) /* PWM 0,1,2,3,6,7 */ + +/* ADC */ +ALTERNATE(PIN_MASK(I, 0b11001001), 0, MODULE_ADC, 0) /* ADC 0,3,6,7 */ + +/* SPI */ +ALTERNATE(PIN_MASK(M, 0x33), 0, MODULE_SPI, 0) /* SPI */ + +/* KEYBOARD */ +ALTERNATE(PIN_MASK(KSI, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSI0-7 */ +ALTERNATE(PIN_MASK(KSO_H, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO8-15 */ +ALTERNATE(PIN_MASK(KSO_L, 0xFB), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO0-1, 3-7 */ +GPIO(EC_KSO_02_INV, PIN(KSO_L, 2), GPIO_OUT_HIGH) /* KSO2 inverted */ + +/* Unimplemented Pins */ +GPIO(PG_PP5000_S5_OD, PIN(D, 2), GPIO_INPUT) +/* *_ODL pin has external pullup so don't pull it down. */ +GPIO(PG_MT6315_GPU_ODL, PIN(H, 6), GPIO_INPUT) +/* reserved for future use */ +GPIO(CCD_MODE_ODL, PIN(C, 4), GPIO_INPUT) + +/* NC pins, enable internal pull-up/down to avoid floating state. */ +GPIO(NC_GPA1, PIN(A, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(EC_NVME_PLN_ODL, PIN(D, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(SPI_CLK_GPG6, PIN(G, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(NC_GPH2, PIN(H, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(PG_NVME_OD, PIN(H, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(EN_PP1200_NVME_X, PIN(J, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPJ4, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPM6, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) +/* + * These pins don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(SPI_MOSI_GPG4, PIN(G, 4), GPIO_OUT_LOW) +GPIO(SPI_MISO_GPG5, PIN(G, 5), GPIO_OUT_LOW) +GPIO(SPI_CS_GPG7, PIN(G, 7), GPIO_OUT_LOW) +GPIO(EC_ID0, PIN(I, 1), GPIO_OUT_LOW) +GPIO(EC_ID1, PIN(I, 2), GPIO_OUT_LOW) + +/* Other unused pins */ +GPIO(NVME_EC_PLA_S3_ODL, PIN(I, 7), GPIO_INPUT) + diff --git a/board/dojo/led.c b/board/dojo/led.c new file mode 100644 index 0000000000..e041ea6a79 --- /dev/null +++ b/board/dojo/led.c @@ -0,0 +1,227 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "pwm.h" +#include "system.h" +#include "util.h" + +/* Times of tick per 1 second */ +#define TIMES_TICK_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +/* Times of tick per half second */ +#define TIMES_TICK_HALF_SEC (500 / HOOK_TICK_INTERVAL_MS) + +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +#define PWR_LED_ON 1 +#define PWR_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_RIGHT_LED, + EC_LED_ID_LEFT_LED, + EC_LED_ID_POWER_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +enum led_port { + RIGHT_PORT = 0, + LEFT_PORT, +}; + +static void battery_led_set_color(enum led_port port, enum led_color color) +{ + pwm_enable(port ? PWM_CH_LED_C1_AMBER : PWM_CH_LED_C0_AMBER, + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + pwm_enable(port ? PWM_CH_LED_C1_WHITE : PWM_CH_LED_C0_WHITE, + (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); +} + +static void power_led_set_color(enum led_color color) +{ + pwm_enable(PWM_CH_LED_PWR, + (color == LED_WHITE) ? PWR_LED_ON : PWR_LED_OFF); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_RIGHT_LED: + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; + break; + case EC_LED_ID_LEFT_LED: + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; + break; + case EC_LED_ID_POWER_LED: + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; + break; + default: + break; + } +} + +static int led_set_color(enum ec_led_id led_id, enum led_color color) +{ + switch (led_id) { + case EC_LED_ID_RIGHT_LED: + battery_led_set_color(RIGHT_PORT, color); + break; + case EC_LED_ID_LEFT_LED: + battery_led_set_color(LEFT_PORT, color); + break; + case EC_LED_ID_POWER_LED: + power_led_set_color(color); + break; + default: + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color(led_id, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color(led_id, LED_AMBER); + else + led_set_color(led_id, LED_OFF); + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + battery_led_set_color(RIGHT_PORT, + (port == RIGHT_PORT) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + battery_led_set_color(LEFT_PORT, + (port == LEFT_PORT) ? color : LED_OFF); +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + int battery_led_blink_cycle; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + if (charge_get_percent() <= 10) { + battery_led_blink_cycle = + battery_ticks % (2 * TIMES_TICK_ONE_SEC); + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + battery_led_set_color(RIGHT_PORT, + (battery_led_blink_cycle < + TIMES_TICK_ONE_SEC) ? + LED_AMBER : + LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + battery_led_set_color(LEFT_PORT, + (battery_led_blink_cycle < + TIMES_TICK_ONE_SEC) ? + LED_AMBER : + LED_OFF); + } else { + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + battery_led_set_color(RIGHT_PORT, LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + battery_led_set_color(LEFT_PORT, LED_OFF); + } + break; + case LED_PWRS_ERROR: + battery_led_blink_cycle = battery_ticks % TIMES_TICK_ONE_SEC; + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + battery_led_set_color(RIGHT_PORT, + (battery_led_blink_cycle < + TIMES_TICK_HALF_SEC) ? + LED_AMBER : + LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + battery_led_set_color(LEFT_PORT, + (battery_led_blink_cycle < + TIMES_TICK_HALF_SEC) ? + LED_AMBER : + LED_OFF); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + battery_led_blink_cycle = + battery_ticks % (2 * TIMES_TICK_ONE_SEC); + set_active_port_color( + (battery_led_blink_cycle < TIMES_TICK_ONE_SEC) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +static void board_led_set_power(void) +{ + static int power_ticks; + int power_led_blink_cycle; + + power_ticks++; + + if (chipset_in_state(CHIPSET_STATE_ON)) { + power_led_set_color(LED_WHITE); + } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + power_led_blink_cycle = power_ticks % (2 * TIMES_TICK_ONE_SEC); + power_led_set_color(power_led_blink_cycle < TIMES_TICK_ONE_SEC ? + LED_WHITE : + LED_OFF); + } else { + power_led_set_color(LED_OFF); + } +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + board_led_set_power(); + + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/dojo/vif_override.xml b/board/dojo/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/dojo/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/don b/board/don new file mode 120000 index 0000000000..7ca3c85ad3 --- /dev/null +++ b/board/don @@ -0,0 +1 @@ +hammer/ \ No newline at end of file diff --git a/board/dood/battery.c b/board/dood/battery.c index e719ea3151..8564eb0926 100644 --- a/board/dood/battery.c +++ b/board/dood/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -277,6 +277,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x43, .reg_mask = 0x0001, .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0, }, }, .batt_info = { diff --git a/board/dood/board.c b/board/dood/board.c index eb87efe87e..9d395d3bfe 100644 --- a/board/dood/board.c +++ b/board/dood/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* dood board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery.h" #include "button.h" #include "charge_manager.h" @@ -38,19 +37,19 @@ #include "switch.h" #include "system.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_charge.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define USB_PD_PORT_ANX7447 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 static uint8_t sku_id; @@ -60,17 +59,16 @@ static uint8_t sku_id; * that we don't have pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {-1, -1}, {-1, -1}, {1, 4}, {1, 3}, - {-1, -1}, {1, 6}, {1, 7}, {3, 1}, {2, 0}, - {1, 5}, {2, 6}, {2, 7}, {2, 1}, {2, 4}, - {2, 5}, {1, 2}, {2, 3}, {2, 2}, {3, 0}, - {-1, -1}, {0, 4}, {-1, -1}, {8, 2}, {-1, -1}, - {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); /* Check PPC ID and board version to decide which one ppc is used. */ static bool support_syv_ppc(void) @@ -88,7 +86,6 @@ static bool support_syv_ppc(void) static void ppc_interrupt(enum gpio_signal signal) { - switch (signal) { case GPIO_USB_PD_C0_INT_ODL: if (support_syv_ppc()) @@ -114,31 +111,31 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, /* Vbus sensing (1/10 voltage divider). */ - [ADC_VBUS_C0] = { - "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, - [ADC_VBUS_C1] = { - "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C0] = { "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + [ADC_VBUS_C1] = { "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -148,11 +145,9 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; @@ -275,17 +270,16 @@ void board_hibernate_late(void) const uint32_t hibernate_pins[][2] = { /* Turn off LEDs before going to hibernate */ - {GPIO_BAT_LED_WHITE_L, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_BAT_LED_AMBER_L, GPIO_INPUT | GPIO_PULL_UP}, + { GPIO_BAT_LED_WHITE_L, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_BAT_LED_AMBER_L, GPIO_INPUT | GPIO_PULL_UP }, }; for (i = 0; i < ARRAY_SIZE(hibernate_pins); ++i) gpio_set_flags(hibernate_pins[i][0], hibernate_pins[i][1]); } -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -297,7 +291,6 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif void board_overcurrent_event(int port, int is_overcurrented) { @@ -310,15 +303,15 @@ void board_overcurrent_event(int port, int is_overcurrented) } const struct ppc_config_t ppc_syv682x_port0 = { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, }; const struct ppc_config_t ppc_syv682x_port1 = { - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, }; static void board_setup_ppc(void) @@ -326,12 +319,10 @@ static void board_setup_ppc(void) if (!support_syv_ppc()) return; - memcpy(&ppc_chips[USB_PD_PORT_TCPC_0], - &ppc_syv682x_port0, - sizeof(struct ppc_config_t)); - memcpy(&ppc_chips[USB_PD_PORT_TCPC_1], - &ppc_syv682x_port1, - sizeof(struct ppc_config_t)); + memcpy(&ppc_chips[USB_PD_PORT_TCPC_0], &ppc_syv682x_port0, + sizeof(struct ppc_config_t)); + memcpy(&ppc_chips[USB_PD_PORT_TCPC_1], &ppc_syv682x_port1, + sizeof(struct ppc_config_t)); gpio_set_flags(GPIO_USB_PD_C0_INT_ODL, GPIO_INT_BOTH); gpio_set_flags(GPIO_USB_PD_C1_INT_ODL, GPIO_INT_BOTH); diff --git a/board/dood/board.h b/board/dood/board.h index 47e5b460da..8c9f225a59 100644 --- a/board/dood/board.h +++ b/board/dood/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,18 +13,16 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" -/* I2C bus configuraiton */ -#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD -/* EC console commands */ -#define CONFIG_CMD_ACCELS -#define CONFIG_CMD_ACCEL_INFO +/* I2C bus configuraiton */ +#define I2C_PORT_ACCEL I2C_PORT_SENSOR #define CONFIG_LED_COMMON /* Sensors */ -#define CONFIG_ACCEL_KX022 /* Lid accel */ -#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ #define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT /* Sensors without hardware FIFO are in forced mode */ @@ -34,8 +32,7 @@ #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE @@ -56,23 +53,25 @@ #define CONFIG_USBC_PPC_DEDICATED_INT #undef CONFIG_SYV682X_HV_ILIM #define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 +/* SYV682 isn't connected to CC, so TCPC must provide VCONN */ +#define CONFIG_USBC_PPC_SYV682X_NO_CC +/* prevent pd reset when battery soc under 2% */ +#define CONFIG_USB_PD_RESET_MIN_BATT_SOC 2 #ifndef __ASSEMBLER__ /* support factory keyboard test */ #define CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; #include "gpio_signal.h" #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ - ADC_VBUS_C0, /* ADC9 */ - ADC_VBUS_C1, /* ADC4 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_VBUS_C0, /* ADC9 */ + ADC_VBUS_C1, /* ADC4 */ ADC_CH_COUNT }; @@ -84,12 +83,7 @@ enum temp_sensor_id { }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { diff --git a/board/dood/build.mk b/board/dood/build.mk index 3d04b75731..998a65a3de 100644 --- a/board/dood/build.mk +++ b/board/dood/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/dood/ec.tasklist b/board/dood/ec.tasklist index d98db145e7..977b8b01be 100644 --- a/board/dood/ec.tasklist +++ b/board/dood/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/dood/gpio.inc b/board/dood/gpio.inc index 961acf8ee0..b10c377ddf 100644 --- a/board/dood/gpio.inc +++ b/board/dood/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/dood/led.c b/board/dood/led.c index c31b2d5316..248dae037f 100644 --- a/board/dood/led.c +++ b/board/dood/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,32 +10,40 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1; +__override const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* Dood: Note there is only LED for charge / power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: @@ -70,4 +78,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/dood/vif_override.xml b/board/dood/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/dood/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/dooly/board.c b/board/dooly/board.c index 8c1c295a66..306fc86ae3 100644 --- a/board/dooly/board.c +++ b/board/dooly/board.c @@ -1,20 +1,23 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Dooly board-specific configuration */ +#include "accelgyro.h" #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "chipset.h" #include "common.h" #include "core/cortex-m/cpu.h" #include "cros_board_info.h" +#include "driver/accel_bma2x2.h" +#include "driver/als_tcs3400.h" #include "driver/ina3221.h" +#include "driver/led/mp3385.h" #include "driver/led/oz554.h" #include "driver/ppc/sn5s330.h" #include "driver/tcpm/anx7447.h" @@ -38,8 +41,8 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_common.h" @@ -47,12 +50,208 @@ #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Sensors */ +static struct mutex g_accel_mutex; +static struct accelgyro_saved_data_t g_bma253_data; + +/* TCS3400 private data */ +static struct als_drv_data_t g_tcs3400_data = { + .als_cal.scale = 1, + .als_cal.uscale = 0, + .als_cal.offset = 0, + .als_cal.channel_scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc */ + .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */ + }, +}; +static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { + /* + * TODO: calculate the actual coefficients and scaling factors + */ + .calibration.rgb_cal[X] = { + .offset = 0, + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + }, + .calibration.rgb_cal[Y] = { + .offset = 0, + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.1), + }, + .calibration.rgb_cal[Z] = { + .offset = 0, + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + }, + .calibration.irt = INT_TO_FP(1), + .saturation.again = TCS_DEFAULT_AGAIN, + .saturation.atime = TCS_DEFAULT_ATIME, +}; + +const mat33_fp_t screen_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t motion_sensors[] = { + [SCREEN_ACCEL] = { + .name = "Screen Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_accel_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR2_FLAGS, + .rot_standard_ref = &screen_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [CLEAR_ALS] = { + .name = "Clear Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT, + .location = MOTIONSENSE_LOC_LID, + .drv = &tcs3400_drv, + .drv_data = &g_tcs3400_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + .min_frequency = TCS3400_LIGHT_MIN_FREQ, + .max_frequency = TCS3400_LIGHT_MAX_FREQ, + .config = { + /* Run ALS sensor in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 1000, + }, + }, + }, + [RGB_ALS] = { + .name = "RGB Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT_RGB, + .location = MOTIONSENSE_LOC_LID, + .drv = &tcs3400_rgb_drv, + .drv_data = &g_tcs3400_rgb_data, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ +const struct motion_sensor_t *motion_als_sensors[] = { + &motion_sensors[CLEAR_ALS], +}; +BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); static void power_monitor(void); DECLARE_DEFERRED(power_monitor); +/* On ECs without an FPU, the fp_t type is backed by a 32-bit fixed precision + * representation that can only store values in the range [-32K, +32K]. Some + * intermediary values produced in tcs3400_translate_to_xyz() do not fit in + * that range, so we define and use a 64-bit fixed representation instead. + */ +typedef int64_t fp64_t; +#define INT_TO_FP64(x) ((int64_t)(x) << 32) +#define FP64_TO_INT(x) ((x) >> 32) +#define FLOAT_TO_FP64(x) ((int64_t)((x) * (float)(1LL << 32))) + +__override void tcs3400_translate_to_xyz(struct motion_sensor_t *s, + int32_t *crgb_data, int32_t *xyz_data) +{ + struct tcs_saturation_t *sat_p = + &(TCS3400_RGB_DRV_DATA(s + 1)->saturation); + + int32_t cur_gain = (1 << (2 * sat_p->again)); + int32_t integration_time_us = + tcs3400_get_integration_time(sat_p->atime); + + fp64_t c_coeff, r_coeff, g_coeff, b_coeff; + fp64_t result; + + /* Use different coefficients based on n_interval = (G+B)/C */ + fp64_t gb_sum = INT_TO_FP64(crgb_data[2]) + INT_TO_FP64(crgb_data[3]); + fp64_t n_interval = gb_sum / MAX(crgb_data[0], 1); + + if (n_interval < FLOAT_TO_FP64(0.692)) { + const float scale = 799.797; + + c_coeff = FLOAT_TO_FP64(0.009 * scale); + r_coeff = FLOAT_TO_FP64(0.056 * scale); + g_coeff = FLOAT_TO_FP64(2.735 * scale); + b_coeff = FLOAT_TO_FP64(-1.903 * scale); + } else if (n_interval < FLOAT_TO_FP64(1.012)) { + const float scale = 801.347; + + c_coeff = FLOAT_TO_FP64(0.202 * scale); + r_coeff = FLOAT_TO_FP64(-1.1 * scale); + g_coeff = FLOAT_TO_FP64(8.692 * scale); + b_coeff = FLOAT_TO_FP64(-7.068 * scale); + } else { + const float scale = 795.574; + + c_coeff = FLOAT_TO_FP64(-0.661 * scale); + r_coeff = FLOAT_TO_FP64(1.334 * scale); + g_coeff = FLOAT_TO_FP64(1.095 * scale); + b_coeff = FLOAT_TO_FP64(-1.821 * scale); + } + + /* Multiply each channel by the coefficient and compute the sum. + * Note: int * fp64_t = fp64_t and fp64_t + fp64_t = fp64_t. + */ + result = crgb_data[0] * c_coeff + crgb_data[1] * r_coeff + + crgb_data[2] * g_coeff + crgb_data[3] * b_coeff; + + /* Adjust for exposure time and sensor gain. + * Note: fp64_t / int = fp64_t. + */ + result /= MAX(integration_time_us * cur_gain / 1000, 1); + + /* Some C/R/G/B coefficients are negative, so the result could also be + * negative and must be clamped at zero. + * + * The value of xyz_data[1] is stored in a 16 bit integer later on, so + * it must be clamped at INT16_MAX. + */ + xyz_data[1] = MIN(MAX(FP64_TO_INT(result), 0), INT16_MAX); +} + static void ppc_interrupt(enum gpio_signal signal) { switch (signal) { @@ -124,8 +323,8 @@ uint16_t tcpc_get_alert_status(void) } /* Called when the charge manager has switched to a new port. */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* Blink alert if insufficient power per system_can_boot_ap(). */ int insufficient_power = @@ -142,12 +341,12 @@ static int32_t base_5v_power; * Power usage for each port as measured or estimated. * Units are milliwatts (5v x ma current) */ -#define PWR_BASE_LOAD (5*1335) -#define PWR_FRONT_HIGH (5*1603) -#define PWR_FRONT_LOW (5*963) -#define PWR_C_HIGH (5*3740) -#define PWR_C_LOW (5*2090) -#define PWR_MAX (5*10000) +#define PWR_BASE_LOAD (5 * 1335) +#define PWR_FRONT_HIGH (5 * 1603) +#define PWR_FRONT_LOW (5 * 963) +#define PWR_C_HIGH (5 * 3740) +#define PWR_C_LOW (5 * 2090) +#define PWR_MAX (5 * 10000) /* * Update the 5V power usage, assuming no throttling, @@ -212,16 +411,14 @@ static const struct { int current; } bj_power[] = { { /* 0 - 65W (also default) */ - .voltage = 19000, - .current = 3420 - }, + .voltage = 19500, + .current = 3200 }, { /* 1 - 90W */ - .voltage = 19000, - .current = 4740 - }, + .voltage = 19500, + .current = 4600 }, }; -#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ /* Debounced connection state of the barrel jack */ static int8_t adp_connected = -1; static void adp_connect_deferred(void) @@ -264,27 +461,29 @@ static void adp_state_init(void) /* Report charge state from the barrel jack. */ adp_connect_deferred(); } -DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_CHARGE_MANAGER_INIT + 1); +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); - -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_FAN] = { .channel = 5, - .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, - [PWM_CH_LED_WHITE] = { .channel = 0, - .flags = PWM_CONFIG_ACTIVE_LOW | - PWM_CONFIG_DSLEEP, - .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_LED_WHITE] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, }; /******************************************************************************/ @@ -309,29 +508,61 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .flags = TCPC_FLAGS_RESET_ACTIVE_HIGH, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, }; /******************************************************************************/ /* I2C port map configuration */ const struct i2c_port_t i2c_ports[] = { - {"ina", I2C_PORT_INA, 400, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"ppc0", I2C_PORT_PPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"ppc1", I2C_PORT_PPC1, 400, GPIO_I2C2_SCL, GPIO_I2C1_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C4_SCL, GPIO_I2C3_SDA}, - {"power", I2C_PORT_POWER, 400, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "ina", + .port = I2C_PORT_INA, + .kbps = 400, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "ppc0", + .port = I2C_PORT_PPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "ppc1", + .port = I2C_PORT_PPC1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA }, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 400, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -372,12 +603,6 @@ const struct adc_t adc_channels[] = { .factor_mul = ADC_MAX_VOLT, .factor_div = ADC_READ_MAX + 1, }, - [ADC_TEMP_SENSOR_2] = { - .name = "TEMP_SENSOR_2", - .input_ch = NPCX_ADC_CH1, - .factor_mul = ADC_MAX_VOLT, - .factor_div = ADC_READ_MAX + 1, - }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -388,26 +613,19 @@ const struct temp_sensor_t temp_sensors[] = { .read = get_temp_3v3_30k9_47k_4050b, .idx = ADC_TEMP_SENSOR_1, }, - [TEMP_SENSOR_2] = { - .name = "PP5000", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2, - }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); /******************************************************************************/ /* Wake up pins */ -const enum gpio_signal hibernate_wake_pins[] = { -}; +const enum gpio_signal hibernate_wake_pins[] = {}; const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /******************************************************************************/ /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = -1, }; @@ -426,30 +644,34 @@ BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /******************************************************************************/ /* Thermal control; drive fan based on temperature sensors. */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(68), - [EC_TEMP_THRESH_HALT] = C_TO_K(78), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(58), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(41), - .temp_fan_max = C_TO_K(72), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(78), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(41), \ + .temp_fan_max = C_TO_K(72), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1] = thermal_a, - [TEMP_SENSOR_2] = thermal_a, + [TEMP_SENSOR_1] = THERMAL_A, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -464,6 +686,7 @@ const unsigned int ina3221_count = ARRAY_SIZE(ina3221); static uint16_t board_version; static uint32_t sku_id; static uint32_t fw_config; +static uint32_t ssfc; static void cbi_init(void) { @@ -481,8 +704,11 @@ static void cbi_init(void) sku_id = val; if (cbi_get_fw_config(&val) == EC_SUCCESS) fw_config = val; - CPRINTS("Board Version: %d, SKU ID: 0x%08x, F/W config: 0x%08x", - board_version, sku_id, fw_config); + if (cbi_get_ssfc(&val) == EC_SUCCESS) + ssfc = val; + CPRINTS("Board Version: %d, SKU ID: 0x%08x, " + "F/W config: 0x%08x, SSFC: 0x%08x ", + board_version, sku_id, fw_config, ssfc); } DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); @@ -510,10 +736,21 @@ static void board_init(void) gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_L); + /* Enable interrupt for the TCS3400 color light sensor */ + gpio_enable_interrupt(GPIO_ALS_GSENSOR_INT_ODL); + /* Always claim AC is online, because we don't have a battery. */ memmap_batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); *memmap_batt_flags |= EC_BATT_FLAG_AC_PRESENT; + /* Initial backlight ic setting by ssfc */ + if (ec_ssfc_get_led_ic() == SSFC_LED_MP3385) + mp3385_board_init(); + else + oz554_board_init(); + gpio_enable_interrupt(GPIO_PANEL_BACKLIGHT_EN); + /* set low to disable EC_PCH_RTCRST */ + gpio_set_level(GPIO_EC_PCH_RTCRST, 0); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -532,22 +769,27 @@ static void board_chipset_startup(void) ppc_vbus_source_enable(USB_PD_PORT_TCPC_0, 1); if (ppc_is_sourcing_vbus(USB_PD_PORT_TCPC_1)) ppc_vbus_source_enable(USB_PD_PORT_TCPC_1, 1); + + /* set high to enable EDID ROM WP */ + gpio_set_level(GPIO_EC_EDID_WP_DISABLE_L, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, - HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +static void board_chipset_shutdown(void) +{ + /* set low to prevent power leakage */ + gpio_set_level(GPIO_EC_EDID_WP_DISABLE_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); /******************************************************************************/ /* USB-C PPC Configuration */ struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { - [USB_PD_PORT_TCPC_0] = { - .i2c_port = I2C_PORT_PPC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, - [USB_PD_PORT_TCPC_1] = { - .i2c_port = I2C_PORT_PPC1, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, + [USB_PD_PORT_TCPC_0] = { .i2c_port = I2C_PORT_PPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + [USB_PD_PORT_TCPC_1] = { .i2c_port = I2C_PORT_PPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, }; unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); @@ -574,7 +816,6 @@ static void board_tcpc_init(void) /* Enable other overcurrent interrupts */ gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); - } /* Make sure this is called after fw_config is initialised */ DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 2); @@ -688,7 +929,7 @@ int extpower_is_present(void) int board_is_c10_gate_enabled(void) { - return 1; + return 0; } void board_enable_s0_rails(int enable) @@ -697,8 +938,8 @@ void board_enable_s0_rails(int enable) unsigned int ec_config_get_bj_power(void) { - unsigned int bj = - (fw_config & EC_CFG_BJ_POWER_MASK) >> EC_CFG_BJ_POWER_L; + unsigned int bj = (fw_config & EC_CFG_BJ_POWER_MASK) >> + EC_CFG_BJ_POWER_L; /* Out of range value defaults to 0 */ if (bj >= ARRAY_SIZE(bj_power)) bj = 0; @@ -710,6 +951,11 @@ unsigned int ec_config_get_thermal_solution(void) return (fw_config & EC_CFG_THERMAL_MASK) >> EC_CFG_THERMAL_L; } +unsigned int ec_ssfc_get_led_ic(void) +{ + return (ssfc & EC_SSFC_LED_MASK) >> EC_SSFC_LED_L; +} + /* * Power monitoring and management. * @@ -748,29 +994,35 @@ unsigned int ec_config_get_thermal_solution(void) * * All measurements are in milliwatts. */ -#define THROT_TYPE_A BIT(0) -#define THROT_TYPE_C BIT(1) -#define THROT_PROCHOT BIT(2) +#define THROT_TYPE_A BIT(0) +#define THROT_TYPE_C BIT(1) +#define THROT_PROCHOT BIT(2) /* * Power gain if front USB A ports are limited. */ -#define POWER_GAIN_TYPE_A 3200 +#define POWER_GAIN_TYPE_A 3200 /* * Power gain if Type C port is limited. */ -#define POWER_GAIN_TYPE_C 8800 +#define POWER_GAIN_TYPE_C 8800 /* * Power is averaged over 10 ms, with a reading every 2 ms. */ -#define POWER_DELAY_MS 2 -#define POWER_READINGS (10/POWER_DELAY_MS) +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +/* PROCHOT_DEFER_OFF is to extend CPU prochot long enough + * to pass safety requirement 30 * 2ms = 60 ms + */ +#define PROCHOT_DEFER_OFF 30 static void power_monitor(void) { static uint32_t current_state; static uint32_t history[POWER_READINGS]; static uint8_t index; + static uint8_t prochot_linger; int32_t delay; uint32_t new_state = 0, diff; int32_t headroom_5v = PWR_MAX - base_5v_power; @@ -779,8 +1031,7 @@ static void power_monitor(void) * If CPU is off or suspended, no need to throttle * or restrict power. */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF | - CHIPSET_STATE_SUSPEND)) { + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { /* * Slow down monitoring, assume no throttling required. */ @@ -808,7 +1059,7 @@ static void power_monitor(void) */ power = (adc_read_channel(ADC_VBUS) * adc_read_channel(ADC_PPVAR_IMON)) / - 1000; + 1000; /* Init power table */ if (history[0] == 0) { for (i = 0; i < POWER_READINGS; i++) @@ -835,8 +1086,7 @@ static void power_monitor(void) * For barrel-jack supplies, the rating can be * exceeded briefly, so use the average. */ - if (charge_manager_get_supplier() == - CHARGE_SUPPLIER_PD) + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) power = max; else power = total / POWER_READINGS; @@ -871,8 +1121,16 @@ static void power_monitor(void) * As a last resort, turn on PROCHOT to * throttle the CPU. */ - if (gap <= 0) + if (gap <= 0) { + prochot_linger = 0; + new_state |= THROT_PROCHOT; + } else if (prochot_linger < PROCHOT_DEFER_OFF) { + /* + * Do not turn off PROCHOT immediately. + */ + prochot_linger++; new_state |= THROT_PROCHOT; + } } } /* @@ -897,8 +1155,8 @@ static void power_monitor(void) * Check whether type C is not throttled, * and is not overcurrent. */ - if (!((new_state & THROT_TYPE_C) || - usbc_0_overcurrent || usbc_1_overcurrent)) { + if (!((new_state & THROT_TYPE_C) || usbc_0_overcurrent || + usbc_1_overcurrent)) { /* * [1] Type C not in overcurrent, throttle it. */ @@ -931,12 +1189,17 @@ static void power_monitor(void) gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); } if (diff & THROT_TYPE_C) { - enum tcpc_rp_value rp = (new_state & THROT_TYPE_C) - ? TYPEC_RP_1A5 : TYPEC_RP_3A0; + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; ppc_set_vbus_source_current_limit(0, rp); tcpm_select_rp_value(0, rp); pd_update_contract(0); + + ppc_set_vbus_source_current_limit(1, rp); + tcpm_select_rp_value(1, rp); + pd_update_contract(1); } if (diff & THROT_TYPE_A) { int typea_bc = (new_state & THROT_TYPE_A) ? 1 : 0; @@ -946,7 +1209,7 @@ static void power_monitor(void) hook_call_deferred(&power_monitor_data, delay); } -__override void oz554_board_init(void) +void oz554_board_init(void) { int pin_status = 0; @@ -957,17 +1220,58 @@ __override void oz554_board_init(void) case 0x00: CPRINTS("PANEL_HAN01.10A"); oz554_set_config(0, 0xF3); + oz554_set_config(2, 0x4C); + oz554_set_config(5, 0xB7); + break; + case 0x02: + CPRINTS("PANEL_WF9_SSA2"); + oz554_set_config(0, 0xF3); oz554_set_config(2, 0x55); oz554_set_config(5, 0x87); break; + default: + CPRINTS("PANEL UNKNOWN"); + break; + } +} + +void mp3385_board_init(void) +{ + int pin_status = 0; + + pin_status |= gpio_get_level(GPIO_PANEL_ID0) << 0; + pin_status |= gpio_get_level(GPIO_PANEL_ID1) << 1; + + switch (pin_status) { + case 0x00: + CPRINTS("PANEL_HAN01.10A"); + mp3385_set_config(0, 0xF1); + mp3385_set_config(2, 0x4C); + mp3385_set_config(5, 0xB7); + break; case 0x02: CPRINTS("PANEL_WF9_SSA2"); - oz554_set_config(0, 0xF3); - oz554_set_config(2, 0x4C); - oz554_set_config(5, 0xB7); + mp3385_set_config(0, 0xF1); + mp3385_set_config(2, 0x55); + mp3385_set_config(5, 0x87); break; default: CPRINTS("PANEL UNKNOWN"); break; } } + +void board_backlight_enable_interrupt(enum gpio_signal signal) +{ + switch (ec_ssfc_get_led_ic()) { + case SSFC_LED_OZ554: + oz554_interrupt(signal); + break; + case SSFC_LED_MP3385: + mp3385_interrupt(signal); + break; + default: + oz554_interrupt(signal); + break; + } +} diff --git a/board/dooly/board.h b/board/dooly/board.h index 3ea5583766..cb9d12f4ff 100644 --- a/board/dooly/board.h +++ b/board/dooly/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,15 +11,52 @@ #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 +/* + * By default, enable all console messages except HC, ACPI and event: + * The sensor stack is generating a lot of activity. + */ +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + /* NPCX7 config */ -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ -#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ /* Internal SPI flash on NPCX796FC is 512 kB */ -#define CONFIG_FLASH_SIZE (512 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ +/* Sensor */ +/* + * Reduce maximal sensor speed: lid accelerometer is not interrupt driven, + * so EC does not timestamp sensor events as accurately as interrupt + * driven ones. + */ +#define CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ 125000 +#define CONFIG_CMD_ACCEL_INFO +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* BMA253 accelerometer */ +#define CONFIG_ACCEL_BMA255 +#define CONFIG_CMD_ACCELS + +/* TCS3400 ALS */ +#define CONFIG_ALS +#define ALS_COUNT 1 +#define CONFIG_ALS_TCS3400 +#define CONFIG_ALS_TCS3400_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(SCREEN_ACCEL) | BIT(CLEAR_ALS)) + /* EC Defines */ #define CONFIG_ADC #define CONFIG_BOARD_HAS_RTC_RESET @@ -27,16 +64,16 @@ #define CONFIG_DEDICATED_RECOVERY_BUTTON #define CONFIG_BOARD_RESET_AFTER_POWER_ON #define CONFIG_CRC8 -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_EMULATED_SYSRQ #undef CONFIG_KEYBOARD_BOOT_KEYS -#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_USE_HOST_EVENT #undef CONFIG_KEYBOARD_RUNTIME_KEYS #undef CONFIG_HIBERNATE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #define CONFIG_LED_COMMON -#undef CONFIG_LID_SWITCH +#undef CONFIG_LID_SWITCH #define CONFIG_LTO #define CONFIG_PWM #define CONFIG_VBOOT_EFS2 @@ -45,9 +82,6 @@ #define CONFIG_VSTORE_SLOT_COUNT 1 #define CONFIG_SHA256 -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY - /* EC Commands */ #define CONFIG_CMD_BUTTON /* Include CLI command needed to support CCD testing. */ @@ -84,7 +118,7 @@ #define CONFIG_CPU_PROCHOT_ACTIVE_LOW /* Dedicated barreljack charger port */ -#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT #define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 #define DEDICATED_CHARGE_PORT 2 @@ -105,21 +139,22 @@ #define CONFIG_INA3221 /* b/143501304 */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 4000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 2000 /* us */ -#define PD_VCONN_SWAP_DELAY 8000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 4000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 2000 /* us */ +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +#define CONFIG_USBC_VCONN_SWAP_DELAY_US 8000 /* us */ -#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON -#define PD_MAX_POWER_MW 100000 -#define PD_MAX_CURRENT_MA 5000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 /* Fan and temp. */ #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 0 #define CONFIG_TEMP_SENSOR -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_ROA_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B #define CONFIG_THROTTLE_AP @@ -136,13 +171,12 @@ #define CONFIG_USB_PD_DECODE_SOP #undef CONFIG_USB_CHARGER #define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PID 0x5040 +#define CONFIG_USB_PID 0x5040 #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_DISCHARGE_PPC #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PD_VBUS_DETECT_PPC #define CONFIG_USBC_PPC_SN5S330 @@ -157,10 +191,10 @@ #define CONFIG_USBC_VCONN #define CONFIG_USBC_VCONN_SWAP -#define USB_PD_PORT_TCPC_0 0 +#define USB_PD_PORT_TCPC_0 0 #define BOARD_TCPC_C0_RESET_HOLD_DELAY ANX74XX_RESET_HOLD_MS #define BOARD_TCPC_C0_RESET_POST_DELAY ANX74XX_RESET_HOLD_MS -#define USB_PD_PORT_TCPC_1 1 +#define USB_PD_PORT_TCPC_1 1 #define BOARD_TCPC_C1_RESET_HOLD_DELAY ANX74XX_RESET_HOLD_MS #define BOARD_TCPC_C1_RESET_POST_DELAY ANX74XX_RESET_HOLD_MS @@ -171,21 +205,23 @@ /* I2C Bus Configuration */ #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define I2C_PORT_INA NPCX_I2C_PORT0_0 -#define I2C_PORT_PPC0 NPCX_I2C_PORT1_0 -#define I2C_PORT_PPC1 NPCX_I2C_PORT2_0 -#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT4_1 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define I2C_PORT_BACKLIGHT NPCX_I2C_PORT7_0 +#define CONFIG_I2C_CONTROLLER +#define I2C_PORT_INA NPCX_I2C_PORT0_0 +#define I2C_PORT_SENSORS NPCX_I2C_PORT0_0 +#define I2C_PORT_PPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_PPC1 NPCX_I2C_PORT2_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT4_1 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_PORT_BACKLIGHT NPCX_I2C_PORT7_0 /* * LED backlight controller */ #define CONFIG_LED_DRIVER_OZ554 +#define CONFIG_LED_DRIVER_MP3385 #define PP5000_PGOOD_POWER_SIGNAL_MASK POWER_SIGNAL_MASK(PP5000_A_PGOOD) @@ -201,18 +237,18 @@ enum charge_port { }; enum adc_channel { - ADC_SNS_PP3300, /* ADC2 */ - ADC_SNS_PP1050, /* ADC7 */ - ADC_VBUS, /* ADC4 */ - ADC_PPVAR_IMON, /* ADC9 */ - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SNS_PP3300, /* ADC2 */ + ADC_SNS_PP1050, /* ADC7 */ + ADC_VBUS, /* ADC4 */ + ADC_PPVAR_IMON, /* ADC9 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ /* Number of ADC channels */ ADC_CH_COUNT }; enum pwm_channel { PWM_CH_FAN, + PWM_CH_LED_RED, PWM_CH_LED_WHITE, /* Number of PWM channels */ PWM_CH_COUNT @@ -230,12 +266,20 @@ enum mft_channel { MFT_CH_COUNT, }; -enum temp_sensor_id { - TEMP_SENSOR_1, - TEMP_SENSOR_2, - TEMP_SENSOR_COUNT +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_COUNT }; + +enum sensor_id { + SCREEN_ACCEL = 0, + CLEAR_ALS, + RGB_ALS, + SENSOR_COUNT, }; +enum ssfc_led_id { + SSFC_LED_OZ554 = 0, + SSFC_LED_MP3385, + SSFC_LED_COUNT, +}; /* Board specific handlers */ void board_reset_pd_mcu(void); @@ -249,52 +293,66 @@ void show_critical_error(void); /* * Barrel-jack power (4 bits). */ -#define EC_CFG_BJ_POWER_L 0 -#define EC_CFG_BJ_POWER_H 3 +#define EC_CFG_BJ_POWER_L 0 +#define EC_CFG_BJ_POWER_H 3 #define EC_CFG_BJ_POWER_MASK GENMASK(EC_CFG_BJ_POWER_H, EC_CFG_BJ_POWER_L) /* * USB Connector 4 not present (1 bit) (not used). */ -#define EC_CFG_NO_USB4_L 4 -#define EC_CFG_NO_USB4_H 4 +#define EC_CFG_NO_USB4_L 4 +#define EC_CFG_NO_USB4_H 4 #define EC_CFG_NO_USB4_MASK GENMASK(EC_CFG_NO_USB4_H, EC_CFG_NO_USB4_L) /* * Thermal solution config (3 bits). */ -#define EC_CFG_THERMAL_L 5 -#define EC_CFG_THERMAL_H 7 +#define EC_CFG_THERMAL_L 5 +#define EC_CFG_THERMAL_H 7 #define EC_CFG_THERMAL_MASK GENMASK(EC_CFG_THERMAL_H, EC_CFG_THERMAL_L) +/* + * Second Source Factory Cache (SSFC) CBI field + */ +/* + * Led driver IC (2 bits). + */ +#define EC_SSFC_LED_L 0 +#define EC_SSFC_LED_H 1 +#define EC_SSFC_LED_MASK GENMASK(EC_SSFC_LED_H, EC_SSFC_LED_L) + unsigned int ec_config_get_bj_power(void); unsigned int ec_config_get_thermal_solution(void); +unsigned int ec_ssfc_get_led_ic(void); + +void board_backlight_enable_interrupt(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ /* Pin renaming */ -#define GPIO_WP_L GPIO_EC_WP_ODL -#define GPIO_PP5000_A_PG_OD GPIO_PG_PP5000_A_OD -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_AC_PRESENT GPIO_BJ_ADP_PRESENT_L +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_PP5000_A_PG_OD GPIO_PG_PP5000_A_OD +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_ROA_RAILS +#define GPIO_AC_PRESENT GPIO_BJ_ADP_PRESENT_L /* * There is no RSMRST input, so alias it to the output. This short-circuits * common_intel_x86_handle_rsmrst. */ -#define GPIO_RSMRST_L_PGOOD GPIO_PCH_RSMRST_L +#define GPIO_PG_EC_RSMRST_ODL GPIO_PCH_RSMRST_L #endif /* __CROS_EC_BOARD_H */ diff --git a/board/dooly/build.mk b/board/dooly/build.mk index 0f55c45f77..f9096c64ff 100644 --- a/board/dooly/build.mk +++ b/board/dooly/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/dooly/ec.tasklist b/board/dooly/ec.tasklist index 5d42008105..cf509f86a2 100644 --- a/board/dooly/ec.tasklist +++ b/board/dooly/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,6 +9,7 @@ #define CONFIG_TASK_LIST \ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 2048) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/dooly/gpio.inc b/board/dooly/gpio.inc index aed8bedd82..d92dedd145 100644 --- a/board/dooly/gpio.inc +++ b/board/dooly/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -25,12 +25,12 @@ GPIO_INT(PG_VPRIM_CORE_A_OD, PIN(2, 3), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PG_PP1050_A_OD, PIN(2, 2), GPIO_INT_BOTH, power_signal_interrupt) /* EC output, but also interrupt so this can be polled as a power signal */ GPIO_INT(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUTPUT | GPIO_INT_F_RISING | GPIO_INT_F_FALLING, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_PP2500_DRAM_U_OD, PIN(2, 0), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PG_PP1200_U_OD, PIN(2, 1), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, slp_s3_interrupt) #endif GPIO_INT(PG_PP950_VCCIO_OD, PIN(1, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -42,7 +42,11 @@ GPIO_INT(USB_C0_TCPPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, ppc_interrupt) GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, tcpc_alert_event) GPIO_INT(USB_C1_TCPPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, ppc_interrupt) GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(E, 4), GPIO_INT_FALLING, tcpc_alert_event) -GPIO_INT(PANEL_BACKLIGHT_EN, PIN(B, 1), GPIO_INT_RISING, backlight_enable_interrupt) +GPIO_INT(PANEL_BACKLIGHT_EN, PIN(B, 1), GPIO_INT_RISING, board_backlight_enable_interrupt) + +/* Sensor Interrupts */ +GPIO_INT(ALS_GSENSOR_INT_ODL, PIN(9, 6), GPIO_INT_FALLING, tcs3400_interrupt) + /* * Directly connected recovery button. */ @@ -58,14 +62,14 @@ GPIO_INT(USB_A0_OC_ODL, PIN(F, 5), GPIO_INT_BOTH, port_ocp_interrupt) GPIO_INT(USB_A1_OC_ODL, PIN(0, 3), GPIO_INT_BOTH, port_ocp_interrupt) /* Volume button interrupts */ -GPIO_INT(EC_VOLDN_BTN_ODL, PIN(C, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) GPIO_INT(EC_VOLUP_BTN_ODL, PIN(8, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* PCH/CPU signals */ GPIO(EC_PCH_PWROK, PIN(0, 5), GPIO_OUT_LOW) GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) -GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) GPIO(EC_PROCHOT_IN_OD, PIN(3, 4), GPIO_INPUT) GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) @@ -130,6 +134,7 @@ ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ ALTERNATE(PIN_MASK(B, 0x0C), 0, MODULE_I2C, 0) /* I2C7 */ /* PWM */ +ALTERNATE(PIN_MASK(C, 0x08), 0, MODULE_PWM, 0) /* PWM0 - Red Led */ ALTERNATE(PIN_MASK(C, 0x10), 0, MODULE_PWM, 0) /* PWM2 - White Led */ ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* PWM5 - Fan 1 */ ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* TA2 - Fan Tachometer */ @@ -146,12 +151,18 @@ ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART from EC GPIO(PANEL_ID0, PIN(0, 2), GPIO_INPUT) GPIO(PANEL_ID1, PIN(C, 6), GPIO_INPUT) +/* + * EDID write protect control + * EDID ROM powered by EN_ROA_RAILS, init low to prevent power leakage + * high to enable EDID ROM WP + * low to disable EDID ROM WP + */ +GPIO(EC_EDID_WP_DISABLE_L, PIN(D, 3), GPIO_OUT_LOW) + /* Unused pins */ -UNUSED(PIN(D, 3)) /* E9 TP55 */ UNUSED(PIN(9, 5)) /* H10 TP54 */ UNUSED(PIN(4, 0)) /* E4 TP56 */ UNUSED(PIN(5, 0)) /* G4 NC */ -UNUSED(PIN(9, 6)) /* M12 TP998 */ UNUSED(PIN(0, 7)) /* E8 TP991 */ UNUSED(PIN(0, 6)) /* B10 TP992 */ UNUSED(PIN(D, 6)) /* F6 */ diff --git a/board/dooly/led.c b/board/dooly/led.c index eeb52b2844..224db77dc0 100644 --- a/board/dooly/led.c +++ b/board/dooly/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -19,42 +19,62 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args) +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) /* * Due to the CSME-Lite processing, upon startup the CPU transitions through * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so * delay turning off the LED during suspend/shutdown. */ -#define LED_CPU_DELAY_MS (2000 * MSEC) +#define LED_CPU_DELAY_MS (2000 * MSEC) -const enum ec_led_id supported_led_ids[] = {EC_LED_ID_POWER_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); enum led_color { LED_OFF = 0, + LED_RED, LED_WHITE, - + LED_AMBER, /* Number of colors, not a color itself */ LED_COLOR_COUNT }; static int set_color_power(enum led_color color, int duty) { + int white = 0; + int red = 0; + if (duty < 0 || 100 < duty) return EC_ERROR_UNKNOWN; switch (color) { case LED_OFF: - pwm_set_duty(PWM_CH_LED_WHITE, 0); break; case LED_WHITE: - pwm_set_duty(PWM_CH_LED_WHITE, duty); + white = 1; + break; + case LED_RED: + red = 1; + break; + case LED_AMBER: + white = 1; + red = 1; break; default: return EC_ERROR_UNKNOWN; } + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (white) + pwm_set_duty(PWM_CH_LED_WHITE, duty); + else + pwm_set_duty(PWM_CH_LED_WHITE, 0); + return EC_SUCCESS; } @@ -68,9 +88,9 @@ static int set_color(enum ec_led_id id, enum led_color color, int duty) } } -#define LED_PULSE_US (2 * SECOND) +#define LED_PULSE_US (2 * SECOND) /* 40 msec for nice and smooth transition. */ -#define LED_PULSE_TICK_US (40 * MSEC) +#define LED_PULSE_TICK_US (40 * MSEC) /* When pulsing is enabled, brightness is incremented by every * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented @@ -165,6 +185,7 @@ DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); static void led_init(void) { pwm_enable(PWM_CH_LED_WHITE, 1); + pwm_enable(PWM_CH_LED_RED, 1); } DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_INIT_PWM + 1); @@ -172,7 +193,7 @@ void led_alert(int enable) { if (enable) { /* Overwrite the current signal */ - config_tick(1 * SECOND, 100, LED_WHITE); + config_tick(1 * SECOND, 100, LED_RED); led_tick(); } else { /* Restore the previous signal */ @@ -189,10 +210,10 @@ void show_critical_error(void) { hook_call_deferred(&led_tick_data, -1); if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) - set_color(EC_LED_ID_POWER_LED, LED_WHITE, 100); + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); } -static int command_led(int argc, char **argv) +static int command_led(int argc, const char **argv) { enum ec_led_id id = EC_LED_ID_POWER_LED; @@ -204,8 +225,12 @@ static int command_led(int argc, char **argv) ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); } else if (!strcasecmp(argv[1], "off")) { set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); } else if (!strcasecmp(argv[1], "white")) { set_color(id, LED_WHITE, 100); + } else if (!strcasecmp(argv[1], "amber")) { + set_color(id, LED_AMBER, 100); } else if (!strcasecmp(argv[1], "alert")) { led_alert(1); } else if (!strcasecmp(argv[1], "crit")) { @@ -216,18 +241,24 @@ static int command_led(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(led, command_led, - "[debug|red|green|amber|off|alert|crit]", + "[debug|red|white|amber|off|alert|crit]", "Turn on/off LED."); void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) { brightness_range[EC_LED_COLOR_WHITE] = 100; + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_AMBER] = 100; } int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) { if (brightness[EC_LED_COLOR_WHITE]) return set_color(id, LED_WHITE, brightness[EC_LED_COLOR_WHITE]); + else if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_AMBER]) + return set_color(id, LED_AMBER, brightness[EC_LED_COLOR_AMBER]); else return set_color(id, LED_OFF, 0); } diff --git a/board/dooly/usb_pd_policy.c b/board/dooly/usb_pd_policy.c index 021b18cae7..71396e8797 100644 --- a/board/dooly/usb_pd_policy.c +++ b/board/dooly/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,16 +12,15 @@ #include "ec_commands.h" #include "gpio.h" #include "system.h" -#include "tcpci.h" -#include "tcpm.h" +#include "tcpm/tcpci.h" +#include "tcpm/tcpm.h" #include "usb_mux.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -42,11 +41,6 @@ void pd_power_supply_reset(int port) if (prev_en) pd_set_vbus_discharge(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -67,11 +61,6 @@ int pd_set_power_supply_ready(int port) if (rv) return rv; -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/board/dooly/vif_override.xml b/board/dooly/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/dooly/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/dragonegg/battery.c b/board/dragonegg/battery.c deleted file mode 100644 index ae583a0d40..0000000000 --- a/board/dragonegg/battery.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery_fuel_gauge.h" -#include "common.h" -#include "util.h" - -/* - * Battery info for all DragonEgg battery types. Note that the fields - * start_charging_min/max and charging_min/max are not used for the charger. - * The effective temperature limits are given by discharging_min/max_c. - * - * Fuel Gauge (FG) parameters which are used for determining if the battery - * is connected, the appropriate ship mode (battery cutoff) command, and the - * charge/discharge FETs status. - * - * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery - * register. For some batteries, the charge/discharge FET bits are set when - * charging/discharging is active, in other types, these bits set mean that - * charging/discharging is disabled. Therefore, in addition to the mask for - * these bits, a disconnect value must be specified. Note that for TI fuel - * gauge, the charge/discharge FET status is found in Operation Status (0x54), - * but a read of Manufacturer Access (0x00) will return the lower 16 bits of - * Operation status which contains the FET status bits. - * - * The assumption for battery types supported is that the charge/discharge FET - * status can be read with a sb_read() command and therefore, only the register - * address, mask, and disconnect value need to be provided. - */ -const struct board_batt_params board_battery_info[] = { - /* Panasonic AP1505L Battery Information */ - [BATTERY_0RD] = { - .fuel_gauge = { - .manuf_name = "SMP-COS5940", - .ship_mode = { - .reg_addr = 0x0, - .reg_data = { 0x10, 0x10 }, - }, - .fet = { - .reg_addr = 0x0, - .reg_mask = 0x2000, - .disconnect_val = 0x2000, - } - }, - .batt_info = { - .voltage_max = 8800, - .voltage_normal = 7700, /* mV */ - .voltage_min = 6000, /* mV */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 60, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = 0, - .discharging_max_c = 60, - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); - -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_0RD; diff --git a/board/dragonegg/board.c b/board/dragonegg/board.c deleted file mode 100644 index 18b4c7c6dc..0000000000 --- a/board/dragonegg/board.c +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* DragonEgg board-specific configuration */ -#include "adc.h" -#include "adc_chip.h" -#include "button.h" -#include "common.h" -#include "charger.h" -#include "console.h" -#include "driver/ppc/nx20p348x.h" -#include "driver/ppc/sn5s330.h" -#include "ec_commands.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "intc.h" -#include "lid_switch.h" -#include "power.h" -#include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "spi.h" -#include "switch.h" -#include "system.h" -#include "uart.h" -#include "usb_pd.h" -#include "util.h" - -static void ppc_interrupt(enum gpio_signal signal) -{ - - switch (signal) { - case GPIO_USB_C0_TCPPC_INT_L: - sn5s330_interrupt(0); - break; - - case GPIO_USB_C2_TCPPC_INT_ODL: - nx20p348x_interrupt(2); - break; - - default: - break; - } -} - -static void tcpc_alert_event(enum gpio_signal signal) -{ - int port = -1; - - /* - * Since C0/C1 TCPC are embedded within EC, we don't need the PDCMD - * tasks.The (embedded) TCPC status since chip driver code will - * handles its own interrupts and forward the correct events to - * the PD_C0/1 task. See it83xx/intc.c - */ - switch (signal) { - case GPIO_USB_C2_TCPC_INT_ODL: - port = 2; - break; - default: - return; - } - - schedule_deferred_pd_interrupt(port); -} - -#include "gpio_list.h" /* Must come after other header files. */ - -/******************************************************************************/ -/* ADC channels */ -const struct adc_t adc_channels[] = { - /* Vbus C0 sensing (7.3x voltage divider). PPVAR_USB_C0_VBUS */ - [ADC_VBUS_C0] = {.name = "VBUS_C0", - .factor_mul = (ADC_MAX_MVOLT * 73) / 10, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH1}, - /* Vbus C1 sensing (7.3x voltage divider). PPVAR_USB_C1_VBUS */ - [ADC_VBUS_C1] = {.name = "VBUS_C1", - .factor_mul = (ADC_MAX_MVOLT * 73) / 10, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH0}, -}; -BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - -/******************************************************************************/ -/* SPI devices */ -/* TODO(b/110880394): Fill out correctly (SPI FLASH) */ -const struct spi_device_t spi_devices[] = { -}; -const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); - -/******************************************************************************/ -/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ -const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 0, .flags = 0, .freq_hz = 100 }, - [PWM_CH_LED_RED] = { .channel = 2, .flags = PWM_CONFIG_DSLEEP | - PWM_CONFIG_ACTIVE_LOW, .freq_hz = 100 }, - [PWM_CH_LED_GREEN] = { .channel = 1, .flags = PWM_CONFIG_DSLEEP | - PWM_CONFIG_ACTIVE_LOW, .freq_hz = 100 }, - [PWM_CH_LED_BLUE] = { .channel = 3, .flags = PWM_CONFIG_DSLEEP | - PWM_CONFIG_ACTIVE_LOW, .freq_hz = 100 }, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -/* GPIO to enable/disable the USB Type-A port. */ -const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { - GPIO_EN_USB_A_5V, -}; - -void board_overcurrent_event(int port) -{ - if (port == 0) { - /* TODO(b/111281797): When does this get set high again? */ - gpio_set_level(GPIO_USB_OC_ODL, 0); - cprints(CC_USBPD, "p%d: overcurrent!", port); - } -} - -static void board_disable_learn_mode(void) -{ - /* Disable learn mode after checking to make sure AC is still present */ - if (extpower_is_present()) - charger_discharge_on_ac(0); -} -DECLARE_DEFERRED(board_disable_learn_mode); - -static void board_extpower(void) -{ - /* - * For the bq25710 charger, we need the switching converter to remain - * disabled until ~130 msec from when VBUS present to allow the - * converter to be biased properly. Otherwise, there will be a reverse - * buck/boost until the converter is biased. The recommendation is to - * exit learn mode 200 msec after external charger is connected. - * - * TODO(b/112372451): When there are updated versions of the bq25710, - * this set of changes can be removed. - */ - if (extpower_is_present()) { - hook_call_deferred(&board_disable_learn_mode_data, 200 * MSEC); - } else { - /* Enable charger learn mode */ - charger_discharge_on_ac(1); - /* Cancel any pending call to disable learn mode */ - hook_call_deferred(&board_disable_learn_mode_data, -1); - } -} -DECLARE_HOOK(HOOK_AC_CHANGE, board_extpower, HOOK_PRIO_DEFAULT); - -/* Initialize board. */ -static void board_init(void) -{ - /* - * On EC reboot, need to always set battery learn mode to the correct - * state based on presence of AC. - */ - board_extpower(); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/dragonegg/board.h b/board/dragonegg/board.h deleted file mode 100644 index daf6f4c255..0000000000 --- a/board/dragonegg/board.h +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* DragonEgg board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Baseboard features */ -#include "baseboard.h" - -/* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ -#define CONFIG_LOW_POWER_IDLE -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 4096 - -/* EC */ -#define CONFIG_BOARD_VERSION_GPIO - -/* Keyboard features */ -#define CONFIG_PWM_KBLIGHT -#define CONFIG_VOLUME_BUTTONS - -/* USB and USBC features */ -#define CONFIG_USB_PORT_POWER_SMART -#undef CONFIG_USB_PORT_POWER_SMART_PORT_COUNT -#define CONFIG_USB_PORT_POWER_SMART_PORT_COUNT 1 -#define CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY -#define GPIO_USB1_ILIM_SEL GPIO_EN_USB_A_HIGH_POWER - -/* LEDs */ -#define CONFIG_LED_COMMON -#define CONFIG_LED_PWM_COUNT 1 -#undef CONFIG_LED_PWM_SOC_ON_COLOR -#define CONFIG_LED_PWM_SOC_ON_COLOR EC_LED_COLOR_BLUE -#undef CONFIG_LED_PWM_SOC_SUSPEND_COLOR -#define CONFIG_LED_PWM_SOC_SUSPEND_COLOR EC_LED_COLOR_WHITE -#define CONFIG_CMD_LEDTEST - -/* - * Macros for GPIO signals used in common code that don't match the - * schematic names. Signal names in gpio.inc match the schematic and are - * then redefined here to so it's more clear which signal is being used for - * which purpose. - */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -enum adc_channel { - ADC_VBUS_C0, - ADC_VBUS_C1, - ADC_CH_COUNT -}; - -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_LED_RED, - PWM_CH_LED_GREEN, - PWM_CH_LED_BLUE, - PWM_CH_COUNT -}; - -/* List of possible batteries */ -enum battery_type { - BATTERY_0RD, - BATTERY_TYPE_COUNT, -}; - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/dragonegg/build.mk b/board/dragonegg/build.mk deleted file mode 100644 index 6da7e2db93..0000000000 --- a/board/dragonegg/build.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -CHIP:=it83xx -CHIP_FAMILY:=it8320 -CHIP_VARIANT:=it8320dx -BASEBOARD:=dragonegg - -board-y=board.o -board-$(CONFIG_BATTERY_SMART)+=battery.o -board-$(CONFIG_LED_COMMON)+=led.o diff --git a/board/dragonegg/ec.tasklist b/board/dragonegg/ec.tasklist deleted file mode 100644 index 7f2b65261f..0000000000 --- a/board/dragonegg/ec.tasklist +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P2, usb_charger_task, 2, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C2, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C2, pd_interrupt_handler_task, 2, TASK_STACK_SIZE) diff --git a/board/dragonegg/gpio.inc b/board/dragonegg/gpio.inc deleted file mode 100644 index ac46ccbd6f..0000000000 --- a/board/dragonegg/gpio.inc +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -/* Wake Source interrupts */ -GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) -GPIO_INT(WP_L, PIN(F, 1), GPIO_INT_BOTH, switch_interrupt) /* EC_WP_ODL */ -GPIO_INT(POWER_BUTTON_L, PIN(E, 2), GPIO_INT_BOTH, power_button_interrupt) /* MECH_PWR_BTN_ODL */ -GPIO_INT(ACOK_OD, PIN(E, 3), GPIO_INT_BOTH, extpower_interrupt) -#ifdef CONFIG_LOW_POWER_IDLE -/* Used to wake up the EC from Deep Doze mode when writing to console */ -GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_SERVO_TX_EC_RX */ -#endif - -/* Power sequencing interrupts */ -GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -GPIO_INT(SLP_S3_L, PIN(I, 4), GPIO_INT_BOTH, power_signal_interrupt) -#endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 -GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) -#endif -GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_RSMRST_ODL,PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_DSW_PWROK, PIN(D, 6), GPIO_INT_BOTH, power_signal_interrupt) - -/* USB-C interrupts */ -GPIO_INT(USB_C0_TCPPC_INT_L, PIN(B, 2), GPIO_INT_FALLING, ppc_interrupt) -GPIO_INT(USB_C2_TCPPC_INT_ODL, PIN(L, 1), GPIO_INT_FALLING, ppc_interrupt) -GPIO_INT(USB_C2_TCPC_INT_ODL, PIN(K, 6), GPIO_INT_FALLING, tcpc_alert_event) - -/* Misc. interrupts */ -GPIO_INT(VOLUME_DOWN_L, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(VOLUME_UP_L, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -/* TODO (b:110947310) Uncomment this when sensor task is added to image */ -/* GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) */ - -#ifdef CONFIG_HOSTCMD_ESPI -/* enable 1.8v input of EC's espi_reset pin, and then this pin takes effect. */ -GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) /* eSPI_reset# */ -#endif - -GPIO(SYS_RESET_L, PIN(D, 1), GPIO_ODR_HIGH) /* SYS_RST_ODL */ -GPIO(PCH_WAKE_L, PIN(D, 5), GPIO_ODR_HIGH) /* EC_PCH_WAKE_ODL */ -GPIO(PCH_PWRBTN_L, PIN(B, 6), GPIO_ODR_HIGH) /* EC_PCH_PWR_BTN_ODL */ - -/* Power Sequencing Signals */ -/* - * Both PP5000 and PP3300_TCPC should be powered up whenever the EC is not in - * hibernate mode. They are enabled by default here and disabled in the - * board_hibernate() callback when the EC goes into hibernate mode. - */ -GPIO(EN_PP5000, PIN(K, 5), GPIO_OUT_HIGH) -GPIO(EN_PP3300_TCPC, PIN(E, 6), GPIO_OUT_HIGH) -GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) -GPIO(EC_PCH_DSW_PWROK, PIN(L, 7), GPIO_OUT_LOW) -GPIO(EC_PCH_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) -GPIO(EC_PROCHOT_ODL, PIN(D, 0), GPIO_ODR_HIGH) -GPIO(PP5000_PG_OD, PIN(F, 0), GPIO_INPUT) - -/* SYS_PWROK generation is done by the Dialog power good IC */ -UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) - -/* USB and USBC Signals */ -GPIO(USB_OC_ODL, PIN(J, 6), GPIO_ODR_HIGH) -GPIO(EN_USB_A_5V, PIN(G, 6), GPIO_OUT_LOW) -GPIO(EN_USB_A_HIGH_POWER, PIN(D, 4), GPIO_OUT_LOW) - -/* BC 1.2 Detection Signals */ -GPIO(USB_C0_BC12_CHG_MAX, PIN(D, 3), GPIO_INPUT) /* C0 BC 1.2 CDP signal */ -GPIO(USB_C1_BC12_CHG_MAX, PIN(B, 7), GPIO_INPUT) /* C1 BC 1.2 CDP signal */ -GPIO(USB_C2_BC12_CHG_MAX, PIN(K, 0), GPIO_INPUT) /* C2 BC 1.2 CDP signal */ -GPIO(USB_C0_BC12_VBUS_ON_ODL, PIN(C, 0), GPIO_ODR_HIGH) /* C0 BC 1.2 enable signal */ -GPIO(USB_C1_BC12_VBUS_ON_ODL, PIN(E, 5), GPIO_ODR_HIGH) /* C1 BC 1.2 enable signal */ -GPIO(USB_C2_BC12_VBUS_ON_ODL, PIN(K, 1), GPIO_ODR_HIGH) /* C2 BC 1.2 enable signal */ - -/* I2C pins - Alternate function below configures I2C module on these pins */ -GPIO(I2C0_SCL, PIN(B, 3), GPIO_INPUT) /* EC_PROG_SCL */ -GPIO(I2C0_SDA, PIN(B, 4), GPIO_INPUT) /* EC_PROG_SDA */ -GPIO(I2C1_SCL, PIN(C, 1), GPIO_INPUT) /* EC_I2C_SENSOR_KB_BL_SCL */ -GPIO(I2C1_SDA, PIN(C, 2), GPIO_INPUT) /* EC_I2C_SENSOR_KB_BL_SDA */ -GPIO(I2C2_SCL, PIN(F, 6), GPIO_INPUT) /* EC_I2C_USB_C1C2_SCL */ -GPIO(I2C2_SDA, PIN(F, 7), GPIO_INPUT) /* EC_I2C_USB_C1C2_SDA */ -GPIO(I2C4_SCL, PIN(E, 0), GPIO_INPUT) /* EC_I2C_USB_C0_SCL */ -GPIO(I2C4_SDA, PIN(E, 7), GPIO_INPUT) /* EC_I2C_USB_C0_SDA */ -GPIO(I2C5_SCL, PIN(A, 4), GPIO_INPUT) /* EC_I2C_POWER_SCL */ -GPIO(I2C5_SDA, PIN(A, 5), GPIO_INPUT) /* EC_I2C_POWER_SDA */ - -GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_INPUT) /* H1 Case Closed Debug */ -GPIO(CHG_VAP_OTG_EN, PIN(C, 3), GPIO_OUT_LOW) /* Charger VAP/OTG Mode_*/ -GPIO(EC_BATT_PRES_ODL, PIN(H, 3), GPIO_INPUT) -GPIO(ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) /* EC_ENTERING_RW */ -GPIO(EDP_BKTLEN_OD, PIN(K, 4), GPIO_ODR_LOW) /* Backlight Disable */ -GPIO(KB_BL_EN, PIN(J, 3), GPIO_OUT_LOW) -/* TODO (b:110947310) Convert this to interrupt when senor support is added */ -GPIO(LID_ACCEL_INT_L, PIN(J, 1), GPIO_INPUT | GPIO_SEL_1P8V) - -/* Board ID */ -GPIO(BOARD_VERSION1, PIN(H, 4), GPIO_INPUT) /* Board ID bit0 */ -GPIO(BOARD_VERSION2, PIN(K, 3), GPIO_INPUT) /* Board ID bit1 */ -GPIO(BOARD_VERSION3, PIN(H, 6), GPIO_INPUT) /* Board ID bit2 */ - -/* Fan Control Pins (connected to TP only, set as inputs) */ -GPIO(EC_FAN_TACH1, PIN(J, 2), GPIO_INPUT) -GPIO(EC_FAN_TACH2, PIN(D, 7), GPIO_INPUT) -GPIO(FAN_PWM1, PIN(A, 6), GPIO_INPUT) -GPIO(FAN_PWM2, PIN(A, 7), GPIO_INPUT) - -/* Alternate functions GPIO definitions */ -ALTERNATE(PIN_MASK(B, 0x03), 0, MODULE_UART, 0) /* UART from EC to Servo */ -ALTERNATE(PIN_MASK(B, 0x18), 0, MODULE_I2C, 0) /* I2C0 */ -ALTERNATE(PIN_MASK(C, 0x06), 0, MODULE_I2C, 0) /* I2C1 */ -ALTERNATE(PIN_MASK(F, 0xC0), 0, MODULE_I2C, 0) /* I2C2 */ -ALTERNATE(PIN_MASK(E, 0x81), 0, MODULE_I2C, 0) /* I2C4 */ -ALTERNATE(PIN_MASK(A, 0x30), 0, MODULE_I2C, 0) /* I2C5 */ -/* Charger_IADP -> ADC15, CHARGER_PSYS -> ADC16 */ -ALTERNATE(PIN_MASK(L, 0x0C), 0, MODULE_ADC, 0) -/* Temp sensors 1 -> ADC2, 2 -> ADC3, 3 -> ADC13 */ -ALTERNATE(PIN_MASK(I, 0x0C), 0, MODULE_ADC, 0) -ALTERNATE(PIN_MASK(L, 0x01), 0, MODULE_ADC, 0) -/* Keyboard Backlight Control */ -ALTERNATE(PIN_MASK(A, 0x01), 0, MODULE_PWM, 0) -/* 3 Color LED Control */ -ALTERNATE(PIN_MASK(A, 0x0E), 0, MODULE_PWM, 0) -ALTERNATE(PIN_MASK(I, 0x03), 0, MODULE_ADC, 0) /* ADC1 & ADC0: ADC_USB_C0_VBUS & ADC_USB_C1_VBUS */ diff --git a/board/dragonegg/led.c b/board/dragonegg/led.c deleted file mode 100644 index 45e944619d..0000000000 --- a/board/dragonegg/led.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Power and battery LED control for DragonEgg - */ - -#include "common.h" -#include "ec_commands.h" -#include "led_pwm.h" -#include "pwm.h" -#include "util.h" - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, -}; -const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); - -struct pwm_led led_color_map[EC_LED_COLOR_COUNT] = { - /* Red, Green, Blue */ - [EC_LED_COLOR_RED] = { 80, 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 65, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, - [EC_LED_COLOR_YELLOW] = { 80, 80, 0 }, - [EC_LED_COLOR_WHITE] = { 80, 65, 100 }, - [EC_LED_COLOR_AMBER] = { 65, 20, 0 }, -}; - -/* - * One tri-color LEDs with red, green, and blue channels. - * - */ -struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = { - [PWM_LED0] = { - /* left port LEDs */ - .ch0 = PWM_CH_LED_RED, - .ch1 = PWM_CH_LED_GREEN, - .ch2 = PWM_CH_LED_BLUE, - .enable = &pwm_enable, - .set_duty = &pwm_set_duty, - }, -}; - -void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) -{ - brightness_range[EC_LED_COLOR_RED] = 100; - brightness_range[EC_LED_COLOR_GREEN] = 100; - brightness_range[EC_LED_COLOR_YELLOW] = 100; - brightness_range[EC_LED_COLOR_AMBER] = 100; - brightness_range[EC_LED_COLOR_BLUE] = 100; - brightness_range[EC_LED_COLOR_WHITE] = 100; -} - -int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) -{ - enum pwm_led_id pwm_id; - - /* Convert ec_led_id to pwm_led_id. */ - if (led_id == EC_LED_ID_POWER_LED) - pwm_id = PWM_LED0; - else - return EC_ERROR_UNKNOWN; - - if (brightness[EC_LED_COLOR_RED]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_RED); - else if (brightness[EC_LED_COLOR_GREEN]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN); - else if (brightness[EC_LED_COLOR_BLUE]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE); - else if (brightness[EC_LED_COLOR_YELLOW]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_YELLOW); - else if (brightness[EC_LED_COLOR_WHITE]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE); - else if (brightness[EC_LED_COLOR_AMBER]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); - else - /* Otherwise, the "color" is "off". */ - set_pwm_led_color(pwm_id, -1); - - return EC_SUCCESS; -} diff --git a/board/drallion_ish/board.c b/board/drallion_ish/board.c index c9a683e36d..8cfee8c19d 100644 --- a/board/drallion_ish/board.c +++ b/board/drallion_ish/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,7 +19,8 @@ #include "tablet_mode.h" #include "task.h" -#include "gpio_list.h" /* has to be included last */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /* I2C port map */ const struct i2c_port_t i2c_ports[] = { @@ -43,11 +44,9 @@ static struct stprivate_data g_lis2dh_data; static struct lis2mdl_private_data lis2mdl_a_data; /* Matrix to rotate base sensor into standard reference frame */ -const mat33_fp_t base_rot_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_rot_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* Drivers */ struct motion_sensor_t motion_sensors[] = { @@ -61,8 +60,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_lid_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_a_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_ACCEL_GYRO_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = NULL, @@ -91,8 +88,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_lid_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_a_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_ACCEL_GYRO_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ diff --git a/board/drallion_ish/board.h b/board/drallion_ish/board.h index fbe4477a39..d87acc48c3 100644 --- a/board/drallion_ish/board.h +++ b/board/drallion_ish/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,10 +19,10 @@ #undef CONFIG_DEBUG_ASSERT #define CONFIG_CLOCK_CRYSTAL /* EC */ -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER /* Base sensor: LNG2DM (uses LIS2DH driver) */ #define CONFIG_ACCEL_LNG2DM @@ -32,7 +32,6 @@ #define CONFIG_MAG_LIS2MDL #define CONFIG_MAG_CALIBRATE -#define CONFIG_ACCEL_INTERRUPTS /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO /* FIFO size is a power of 2. */ @@ -54,13 +53,12 @@ #define CONFIG_TABLET_MODE #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L /* DMA paging between SRAM and DRAM */ #define CONFIG_DMA_PAGING /* Host command over HECI */ -#define CONFIG_HOSTCMD_HECI +#define CONFIG_HOST_INTERFACE_HECI /* I2C ports */ #define I2C_PORT_SENSOR ISH_I2C0 @@ -74,7 +72,7 @@ /* Undefined features */ #undef CONFIG_EXTPOWER #undef CONFIG_KEYBOARD_KSO_BASE -#undef CONFIG_FLASH +#undef CONFIG_FLASH_CROS #undef CONFIG_FMAP #undef CONFIG_SWITCH @@ -96,8 +94,8 @@ #define CONFIG_ISH_PM_D3 #define CONFIG_ISH_PM_RESET_PREP -#define CONFIG_ISH_D0I2_MIN_USEC (15*MSEC) -#define CONFIG_ISH_D0I3_MIN_USEC (100*MSEC) +#define CONFIG_ISH_D0I2_MIN_USEC (15 * MSEC) +#define CONFIG_ISH_D0I3_MIN_USEC (100 * MSEC) #ifndef __ASSEMBLER__ @@ -109,13 +107,7 @@ * Note: Since we aren't using LPC memory map to transmit sensor data, the * order of this enum does not need to be accel, accel, gyro */ -enum sensor_id { - LID_ACCEL, - LID_GYRO, - BASE_ACCEL, - LID_MAG, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, LID_GYRO, BASE_ACCEL, LID_MAG, SENSOR_COUNT }; #endif /* !__ASSEMBLER__ */ diff --git a/board/drallion_ish/build.mk b/board/drallion_ish/build.mk index 51bd96d339..50d4bf1042 100644 --- a/board/drallion_ish/build.mk +++ b/board/drallion_ish/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/drallion_ish/ec.tasklist b/board/drallion_ish/ec.tasklist index a4db486e9a..de7d256324 100644 --- a/board/drallion_ish/ec.tasklist +++ b/board/drallion_ish/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/drallion_ish/gpio.inc b/board/drallion_ish/gpio.inc index 93e6752e2b..b1c585b329 100644 --- a/board/drallion_ish/gpio.inc +++ b/board/drallion_ish/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/dratini/battery.c b/board/dratini/battery.c index dafd0c9425..5cb57e4ba5 100644 --- a/board/dratini/battery.c +++ b/board/dratini/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -96,27 +96,3 @@ const struct board_batt_params board_battery_info[] = { BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO_COS; - -/* Lower our input voltage to 5V in S5/G3 when battery is full. */ -static void reduce_input_voltage_when_full(void) -{ - int max_pd_voltage_mv; - int port; - - if (charge_get_percent() == 100 && - chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) - max_pd_voltage_mv = 5000; - else - max_pd_voltage_mv = PD_MAX_VOLTAGE_MV; - - if (pd_get_max_voltage() != max_pd_voltage_mv) { - for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) - pd_set_external_voltage_limit(port, max_pd_voltage_mv); - } -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); diff --git a/board/dratini/board.c b/board/dratini/board.c index b10c299af1..f109379767 100644 --- a/board/dratini/board.c +++ b/board/dratini/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Hatch board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" @@ -36,16 +35,16 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void check_reboot_deferred(void); DECLARE_DEFERRED(check_reboot_deferred); @@ -113,11 +112,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -125,20 +124,21 @@ static void bc12_interrupt(enum gpio_signal signal) } } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 100 }, - [PWM_CH_FAN] = {.channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 100 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -158,22 +158,48 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +/* Set aux switch to 0xc when CCD enabled on port C0 */ +static int board_anx7447_mux_set_c0(const struct usb_mux *me, + mux_state_t mux_state) +{ + int port = me->usb_port; + int rv = EC_SUCCESS; + + if (port != USB_PD_PORT_TCPC_0) + return rv; + + if (gpio_get_level(GPIO_CCD_MODE_ODL)) + return rv; + + CPRINTS("C%d: set AUX_SW_SEL=0x%x", port, 0xc); + rv = tcpc_write(port, ANX7447_REG_TCPC_AUX_SWITCH, 0xc); + if (rv) + CPRINTS("C%d: Setting AUX_SW_SEL failed", port); + + return rv; +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &anx7447_usb_mux_driver, + .board_set = &board_anx7447_mux_set_c0, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -202,17 +228,13 @@ static struct bmi_drv_data_t g_bmi160_data; static struct accelgyro_saved_data_t g_bma255_data; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -292,7 +314,7 @@ unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -311,68 +333,77 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_5V_REG", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_3] = { - "TEMP_CPU", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_5V_REG", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_3] = { "TEMP_CPU", NPCX_ADC_CH2, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "5V Reg", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, - [TEMP_SENSOR_3] = {.name = "CPU", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_3}, + [TEMP_SENSOR_1] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "5V Reg", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - /* Dratini Temperature sensors */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(73), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(70), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; -const static struct ec_thermal_config thermal_b = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(68), - [EC_TEMP_THRESH_HALT] = C_TO_K(70), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(70), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_b = THERMAL_B; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -395,8 +426,8 @@ bool board_is_convertible(void) * Dratini is not. * Unprovisioned SKU 255. */ - return sku_id == 21 || sku_id == 22 || sku_id == 23 || - sku_id == 24 || sku_id == 255; + return sku_id == 21 || sku_id == 22 || sku_id == 23 || sku_id == 24 || + sku_id == 255; } static void board_update_sensor_config_from_sku(void) @@ -452,7 +483,7 @@ bool board_has_kb_backlight(void) * Unprovisioned: 255 */ return sku_id == 2 || sku_id == 3 || sku_id == 5 || sku_id == 8 || - sku_id == 22 || sku_id == 24 || sku_id == 255; + sku_id == 22 || sku_id == 24 || sku_id == 255; } __override uint32_t board_override_feature_flags0(uint32_t flags0) @@ -470,15 +501,15 @@ __override uint32_t board_override_feature_flags0(uint32_t flags0) * The connector has 24 pins total, and there is no pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {1, 4}, {1, 3}, {1, 6}, {1, 7}, - {3, 1}, {2, 0}, {1, 5}, {2, 6}, {2, 7}, - {2, 1}, {2, 4}, {2, 5}, {1, 2}, {2, 3}, - {2, 2}, {3, 0}, {-1, -1}, {-1, -1}, {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); #endif /* Disable HDMI power while AP is suspended / off */ @@ -507,7 +538,7 @@ __override void board_chipset_forced_shutdown(void) hook_call_deferred(&check_reboot_deferred_data, -1); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_forced_shutdown, - HOOK_PRIO_DEFAULT); + HOOK_PRIO_DEFAULT); static void check_reboot_deferred(void) { diff --git a/board/dratini/board.h b/board/dratini/board.h index bc45b2ca47..8cdbf0947f 100644 --- a/board/dratini/board.h +++ b/board/dratini/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,7 +17,7 @@ #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 2048 @@ -30,12 +30,13 @@ * Dratini's battery takes several seconds to come back out of its disconnect * state (~4 seconds, but give it 6 for margin). */ -#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT #define CONFIG_POWER_BUTTON_INIT_TIMEOUT 6 +#define CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV 5000 + /* Sensors */ /* BMI160 Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) @@ -49,7 +50,6 @@ #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL #define CONFIG_LID_ANGLE_UPDATE #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L /* USB Type C and USB PD defines */ #define CONFIG_USB_PD_COMM_LOCKED @@ -93,7 +93,7 @@ #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 10 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -112,15 +112,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -128,9 +129,9 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_TEMP_SENSOR_3, /* ADC2 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_3, /* ADC2 */ ADC_CH_COUNT }; @@ -141,11 +142,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, @@ -173,11 +170,6 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -#ifdef CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; -#endif - bool board_is_convertible(void); #endif /* !__ASSEMBLER__ */ diff --git a/board/dratini/build.mk b/board/dratini/build.mk index 733912454f..13153c1526 100644 --- a/board/dratini/build.mk +++ b/board/dratini/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/dratini/ec.tasklist b/board/dratini/ec.tasklist index 4a1024a091..829be2b7c8 100644 --- a/board/dratini/ec.tasklist +++ b/board/dratini/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/dratini/gpio.inc b/board/dratini/gpio.inc index 1d83a9813a..bf1a8a431c 100644 --- a/board/dratini/gpio.inc +++ b/board/dratini/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,10 +17,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) @@ -79,6 +79,9 @@ GPIO(USB_C1_TCPC_RST_ODL, PIN(3, 2), GPIO_ODR_HIGH) GPIO(EN_USB_A_5V, PIN(3, 5), GPIO_OUT_LOW) GPIO(EN_USB_A_LOW_PWR_OD, PIN(9, 4), GPIO_OUT_LOW) +/* CCD mode line*/ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + /* Misc Signals */ GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) GPIO(LED_AMBER_C0_L, PIN(C, 4), GPIO_OUT_HIGH) /* Amber C0 port */ diff --git a/board/dratini/led.c b/board/dratini/led.c index 5cc256b2c5..64d5ed3e4d 100644 --- a/board/dratini/led.c +++ b/board/dratini/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,9 +11,9 @@ #include "chipset.h" #include "ec_commands.h" #include "gpio.h" +#include "hooks.h" #include "host_command.h" #include "led_common.h" -#include "hooks.h" #define BAT_LED_ON 0 #define BAT_LED_OFF 1 @@ -24,11 +24,9 @@ #define LED_TICKS_PER_CYCLE 10 #define LED_ON_TICKS 5 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_LEFT_LED, - EC_LED_ID_RIGHT_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -36,7 +34,7 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static void led_set_color_battery(int port, enum led_color color) @@ -64,7 +62,7 @@ static void led_set_color_battery(int port, enum led_color color) } } -void led_set_color_power(enum ec_led_colors color) +void led_set_color_power(enum led_color color) { switch (color) { case LED_OFF: @@ -147,7 +145,6 @@ static void led_set_battery(void) { static int battery_ticks; static int power_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; @@ -158,32 +155,34 @@ static void led_set_battery(void) */ if (!board_is_convertible()) { if (chipset_in_state(CHIPSET_STATE_SUSPEND | - CHIPSET_STATE_STANDBY) && - charge_get_state() != PWR_STATE_CHARGE) { - + CHIPSET_STATE_STANDBY) && + led_pwr_get_state() != LED_PWRS_CHARGE) { power_ticks++; - led_set_color_battery(0, power_ticks & 0x4 ? - LED_WHITE : LED_OFF); - led_set_color_battery(1, power_ticks & 0x4 ? - LED_WHITE : LED_OFF); + led_set_color_battery(0, power_ticks & 0x4 ? LED_WHITE : + LED_OFF); + led_set_color_battery(1, power_ticks & 0x4 ? LED_WHITE : + LED_OFF); return; } } power_ticks = 0; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate when charging, even in suspend. */ set_active_port_color(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { if (charge_get_percent() < 10) - led_set_color_battery(0, (battery_ticks % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_WHITE : LED_OFF); + led_set_color_battery( + 0, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); else led_set_color_battery(0, LED_OFF); } @@ -191,20 +190,21 @@ static void led_set_battery(void) if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) led_set_color_battery(1, LED_OFF); break; - case PWR_STATE_ERROR: - set_active_port_color((battery_ticks & 0x2) ? - LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: set_active_port_color(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - set_active_port_color((battery_ticks % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_AMBER : LED_OFF); - else - set_active_port_color(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ @@ -222,9 +222,10 @@ static void led_set_power(void) led_set_color_power(LED_WHITE); else if (chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_STANDBY)) - led_set_color_power((power_tick % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_WHITE : LED_OFF); + led_set_color_power( + (power_tick % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); else led_set_color_power(LED_OFF); } diff --git a/board/dratini/vif_override.xml b/board/dratini/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/dratini/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/drawcia/battery.c b/board/drawcia/battery.c index 3052f93dcc..acc50ca048 100644 --- a/board/drawcia/battery.c +++ b/board/drawcia/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -33,7 +33,7 @@ */ const struct board_batt_params board_battery_info[] = { /* DynaPack CosMX Battery Information */ - [BATTERY_DANAPACK_COS] = { + [BATTERY_DYNAPACK_COS] = { .fuel_gauge = { .manuf_name = "333-2C-DA-A", .ship_mode = { @@ -45,6 +45,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x0, .reg_mask = 0x0006, .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, }, }, .batt_info = { @@ -62,7 +64,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack ATL Battery Information */ - [BATTERY_DANAPACK_ATL] = { + [BATTERY_DYNAPACK_ATL] = { .fuel_gauge = { .manuf_name = "333-27-DA-A", .ship_mode = { @@ -74,6 +76,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x0, .reg_mask = 0x0006, .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, }, }, .batt_info = { @@ -91,7 +95,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack HIGHPOWER Battery Information */ - [BATTERY_DANAPACK_HIGHPOWER] = { + [BATTERY_DYNAPACK_HIGHPOWER] = { .fuel_gauge = { .manuf_name = "333-2D-0D-A", .ship_mode = { @@ -103,6 +107,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x0, .reg_mask = 0x0006, .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, }, }, .batt_info = { @@ -120,7 +126,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack BYD Battery Information */ - [BATTERY_DANAPACK_BYD] = { + [BATTERY_DYNAPACK_BYD] = { .fuel_gauge = { .manuf_name = "333-2E-0D-A", .ship_mode = { @@ -132,6 +138,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x0, .reg_mask = 0x0006, .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, }, }, .batt_info = { @@ -161,6 +169,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x0, .reg_mask = 0x0006, .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, }, }, .batt_info = { @@ -190,6 +200,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x0, .reg_mask = 0x0006, .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, }, }, .batt_info = { @@ -219,6 +231,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x0, .reg_mask = 0x0006, .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, }, }, .batt_info = { @@ -248,6 +262,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x0, .reg_mask = 0x0006, .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, }, }, .batt_info = { @@ -263,7 +279,71 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 60, }, }, + + /* CosMX B00C4473A9D0002 Battery Information */ + [BATTERY_COS_2] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* ATL GB-S20-4473A9-01H&020H Battery Information + * Gauge IC : RAJ240045 + */ + [BATTERY_ATL] = { + .fuel_gauge = { + .manuf_name = "313-B7-0D-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x43, + .reg_mask = 0x0003, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DANAPACK_COS; +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; diff --git a/board/drawcia/board.c b/board/drawcia/board.c index fe9bb0e940..78459b6ef5 100644 --- a/board/drawcia/board.c +++ b/board/drawcia/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,17 +8,19 @@ #include "adc_chip.h" #include "button.h" #include "cbi_fw_config.h" +#include "cbi_ssfc.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "cros_board_info.h" #include "driver/accel_bma2x2.h" +#include "driver/accel_bma422.h" #include "driver/accelgyro_lsm6dsm.h" #include "driver/bc12/pi3usb9201.h" #include "driver/charger/sm5803.h" -#include "driver/temp_sensor/thermistor.h" #include "driver/tcpm/it83xx_pd.h" #include "driver/tcpm/ps8xxx.h" +#include "driver/temp_sensor/thermistor.h" #include "driver/usb_mux/it5205.h" #include "gpio.h" #include "hooks.h" @@ -33,7 +35,7 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" #include "uart.h" #include "usb_charge.h" @@ -41,7 +43,7 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" -#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) #define INT_RECHECK_US 5000 @@ -52,13 +54,28 @@ const int usb_port_enable[USB_PORT_COUNT] = { GPIO_EN_USB_A_5V, }; +__override void board_process_pd_alert(int port) +{ + /* + * PD_INT task will process this alert, and that task is only needed on + * C1. + */ + if (port != 1) + return; + + if (gpio_get_level(GPIO_USB_C1_INT_ODL)) + return; + + sm5803_handle_interrupt(port); +} + /* C0 interrupt line shared by BC 1.2 and charger */ static void check_c0_line(void); DECLARE_DEFERRED(check_c0_line); static void notify_c0_chips(void) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); sm5803_interrupt(0); } @@ -93,8 +110,7 @@ DECLARE_DEFERRED(check_c1_line); static void notify_c1_chips(void) { schedule_deferred_pd_interrupt(1); - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); - sm5803_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); } static void check_c1_line(void) @@ -121,13 +137,30 @@ static void usb_c1_interrupt(enum gpio_signal s) hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); } +static void board_enable_hdmi_hpd(int enable) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + int hdmi_hpd = gpio_get_level(GPIO_VOLUP_BTN_ODL_HDMI_HPD); + + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) { + /* Check if we can report HDMI_HPD signal to CPU */ + if (enable) + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, hdmi_hpd); + else + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, 0); + } +} + static void button_sub_hdmi_hpd_interrupt(enum gpio_signal s) { + enum fw_config_db db = get_cbi_fw_config_db(); int hdmi_hpd = gpio_get_level(GPIO_VOLUP_BTN_ODL_HDMI_HPD); - if (get_cbi_fw_config_db() == DB_1A_HDMI) - gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, hdmi_hpd); - else + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) { + /* Do not report HDMI_HPD signal to CPU when system off. */ + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, hdmi_hpd); + } else button_interrupt(s); } @@ -149,48 +182,36 @@ static void pen_detect_interrupt(enum gpio_signal s) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_VSNS_PP3300_A] = { - .name = "PP3300_A_PGOOD", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH0 - }, - [ADC_TEMP_SENSOR_1] = { - .name = "TEMP_SENSOR1", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH2 - }, - [ADC_TEMP_SENSOR_2] = { - .name = "TEMP_SENSOR2", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH3 - }, - [ADC_SUB_ANALOG] = { - .name = "SUB_ANALOG", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH13 - }, - [ADC_TEMP_SENSOR_3] = { - .name = "TEMP_SENSOR3", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH15 - }, - [ADC_TEMP_SENSOR_4] = { - .name = "TEMP_SENSOR4", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH16 - }, + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_SUB_ANALOG] = { .name = "SUB_ANALOG", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, + [ADC_TEMP_SENSOR_4] = { .name = "TEMP_SENSOR4", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH16 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -232,26 +253,32 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_SUB_USB_C1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; /* USB Muxes */ -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, }, { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = PS8751_I2C_ADDR1_FLAGS, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, }; @@ -261,20 +288,17 @@ static struct mutex g_base_mutex; /* Sensor Data */ static struct accelgyro_saved_data_t g_bma253_data; +static struct accelgyro_saved_data_t g_bma422_data; static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* Drivers */ struct motion_sensor_t motion_sensors[] = { @@ -312,8 +336,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &base_standard_ref, @@ -341,12 +363,10 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ - .rot_standard_ref = NULL, + .rot_standard_ref = &base_standard_ref, .min_frequency = LSM6DSM_ODR_MIN_VAL, .max_frequency = LSM6DSM_ODR_MAX_VAL, }, @@ -354,11 +374,47 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +struct motion_sensor_t bma422_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_PRIMARY, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, +}; + +static void board_update_motion_sensor_config(void) +{ + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_BMA422) + motion_sensors[LID_ACCEL] = bma422_lid_accel; +} + void board_init(void) { int on; + enum fw_config_db db = get_cbi_fw_config_db(); - if (get_cbi_fw_config_db() == DB_1A_HDMI) { + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) { /* Select HDMI option */ gpio_set_level(GPIO_HDMI_SEL_L, 0); } else { @@ -387,6 +443,8 @@ void board_init(void) motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Enable Base Accel interrupt */ gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + board_update_motion_sensor_config(); } else { motion_sensor_count = 0; gmr_tablet_switch_disable(); @@ -397,6 +455,13 @@ void board_init(void) gpio_enable_interrupt(GPIO_PEN_DET_ODL); + /* Make sure pen detection is triggered or not at sysjump */ + if (!gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_EN_PP5000_PEN, 1); + + /* Make sure HDMI_HPD signal can be reported to CPU at sysjump */ + board_enable_hdmi_hpd(1); + /* Charger on the MB will be outputting PROCHOT_ODL and OD CHG_DET */ sm5803_configure_gpio0(CHARGER_PRIMARY, GPIO0_MODE_PROCHOT, 1); sm5803_configure_chg_det_od(CHARGER_PRIMARY, 1); @@ -407,7 +472,8 @@ void board_init(void) } /* Turn on 5V if the system is on, otherwise turn it off */ - on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND); + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); board_power_5v_enable(on); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -417,6 +483,9 @@ static void board_resume(void) sm5803_disable_low_power_mode(CHARGER_PRIMARY); if (board_get_charger_chip_count() > 1) sm5803_disable_low_power_mode(CHARGER_SECONDARY); + + /* Enable reporting HDMI_HPD to CPU when system resume */ + board_enable_hdmi_hpd(1); } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); @@ -428,6 +497,13 @@ static void board_suspend(void) } DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); +static void board_shutdown(void) +{ + /* Disable reporting HDMI_HPD to CPU at shutdown */ + board_enable_hdmi_hpd(0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_shutdown, HOOK_PRIO_DEFAULT); + void board_hibernate(void) { /* @@ -445,6 +521,21 @@ __override void board_ocpc_init(struct ocpc_data *ocpc) ocpc->chg_flags[CHARGER_SECONDARY] |= OCPC_NO_ISYS_MEAS_CAP; } +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + void board_reset_pd_mcu(void) { /* @@ -463,25 +554,39 @@ __override void board_power_5v_enable(int enable) if (board_get_charger_chip_count() > 1) { if (sm5803_set_gpio0_level(1, !!enable)) - CPRINTUSB("Failed to %sable sub rails!", enable ? - "en" : "dis"); + CPRINTUSB("Failed to %sable sub rails!", + enable ? "en" : "dis"); } } __override uint8_t board_get_usb_pd_port_count(void) { - if (get_cbi_fw_config_db() == DB_1A_HDMI) + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) return CONFIG_USB_PD_PORT_MAX_COUNT - 1; - else + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) return CONFIG_USB_PD_PORT_MAX_COUNT; + + ccprints("Unhandled DB configuration: %d", db); + return 0; } __override uint8_t board_get_charger_chip_count(void) { - if (get_cbi_fw_config_db() == DB_1A_HDMI) + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) return CHARGER_NUM - 1; - else + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) return CHARGER_NUM; + + ccprints("Unhandled DB configuration: %d", db); + return 0; } uint16_t tcpc_get_alert_status(void) @@ -505,19 +610,17 @@ uint16_t tcpc_get_alert_status(void) return status; } -void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma, - int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { - int icl = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); - /* Limit C1 on board version 0 to 2.0 A */ if ((board_version == 0) && (port == 1)) - icl = MIN(icl, 2000); + charge_ma = MIN(charge_ma, 2000); /* * TODO(b/151955431): Characterize the input current limit in case a * scaling needs to be applied here */ - charge_set_input_current_limit(icl, charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } int board_set_active_charge_port(int port) @@ -581,40 +684,53 @@ __override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) charger_set_otg_current_voltage(port, current, 5000); } -/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ -const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { - .channel = 0, - .flags = PWM_CONFIG_DSLEEP, - .freq_hz = 10000, +__override uint16_t board_get_ps8xxx_product_id(int port) +{ + /* Drawcia variant doesn't have ps8xxx product in the port 0 */ + if (port == 0) + return 0; + + switch (get_cbi_ssfc_tcpc_p1()) { + case SSFC_TCPC_P1_PS8805: + return PS8805_PRODUCT_ID; + case SSFC_TCPC_P1_DEFAULT: + case SSFC_TCPC_P1_PS8705: + default: + return PS8705_PRODUCT_ID; } -}; +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 10000, + } }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); /* Thermistors */ const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Memory", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, - [TEMP_SENSOR_3] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_3}, - [TEMP_SENSOR_4] = {.name = "5V regular", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_4}, + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "5V regular", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); @@ -638,18 +754,38 @@ void lid_angle_peripheral_enable(int enable) keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); } } -#endif -__override void ocpc_get_pid_constants(int *kp, int *kp_div, - int *ki, int *ki_div, - int *kd, int *kd_div) +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) { *kp = 3; - *kp_div = 14; + *kp_div = 20; *ki = 3; - *ki_div = 500; + *ki_div = 125; *kd = 4; *kd_div = 40; } + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { GPIO_KSO_H, 4 }, { GPIO_KSO_H, 0 }, + { GPIO_KSO_H, 1 }, { GPIO_KSO_H, 3 }, { GPIO_KSO_H, 2 }, + { GPIO_KSO_L, 5 }, { GPIO_KSO_L, 6 }, { GPIO_KSO_L, 3 }, + { GPIO_KSO_L, 2 }, { GPIO_KSI, 0 }, { GPIO_KSO_L, 1 }, + { GPIO_KSO_L, 4 }, { GPIO_KSI, 3 }, { GPIO_KSI, 2 }, + { GPIO_KSO_L, 0 }, { GPIO_KSI, 5 }, { GPIO_KSI, 4 }, + { GPIO_KSO_L, 7 }, { GPIO_KSI, 6 }, { GPIO_KSI, 7 }, + { GPIO_KSI, 1 }, { -1, -1 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/drawcia/board.h b/board/drawcia/board.h index fb9a5db542..e696ecf7cd 100644 --- a/board/drawcia/board.h +++ b/board/drawcia/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,9 +15,6 @@ #undef GPIO_VOLUME_UP_L #define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL_HDMI_HPD -/* System unlocked in early development */ -#define CONFIG_SYSTEM_UNLOCKED - /* Battery */ #define CONFIG_BATTERY_FUEL_GAUGE @@ -25,24 +22,31 @@ #define CONFIG_BC12_DETECT_PI3USB9201 /* Charger */ -#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 15000 #define CONFIG_USB_PD_VBUS_DETECT_CHARGER #define CONFIG_USB_PD_5V_CHARGER_CTRL #define CONFIG_CHARGER_OTG -#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_CHARGER_SINGLE_CHIP #define CONFIG_OCPC -#define CONFIG_OCPC_DEF_RBATT_MOHMS 21 /* R_DS(on) 10.7mOhm + 10mOhm sns rstr */ +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 21 /* R_DS(on) 10.7mOhm + 10mOhm sns rstr \ + */ /* PWM */ #define CONFIG_PWM /* Sensors */ -#define CONFIG_ACCEL_BMA255 /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCEL_BMA4XX /* 2nd source Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO /* Power of 2 - Too large of a fifo causes too much timestamp jitter */ @@ -64,12 +68,16 @@ #define CONFIG_GMR_TABLET_MODE /* Keyboard */ +#define CONFIG_KEYBOARD_FACTORY_TEST #define CONFIG_PWM_KBLIGHT /* TCPC */ #define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ -#define CONFIG_USB_PD_TCPM_PS8705 /* C1: PS8705 TCPC*/ +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_TCPM_MULTI_PS8XXX +#define CONFIG_USB_PD_TCPM_PS8705 /* C1: PS8705 TCPC */ +#define CONFIG_USB_PD_TCPM_PS8805 /* C1: second source PS8805 TCPC */ +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID #define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE #define CONFIG_USB_PD_TCPC_LOW_POWER @@ -78,11 +86,10 @@ #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_PP3300_A /* USB Mux and Retimer */ -#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ -#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ /* USB Type A Features */ #define USB_PORT_COUNT 1 @@ -105,21 +112,16 @@ enum pwm_channel { }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; /* ADC channels */ enum adc_channel { - ADC_VSNS_PP3300_A, /* ADC0 */ - ADC_TEMP_SENSOR_1, /* ADC2 */ - ADC_TEMP_SENSOR_2, /* ADC3 */ - ADC_SUB_ANALOG, /* ADC13 */ - ADC_TEMP_SENSOR_3, /* ADC15 */ - ADC_TEMP_SENSOR_4, /* ADC16 */ + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_SUB_ANALOG, /* ADC13 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_TEMP_SENSOR_4, /* ADC16 */ ADC_CH_COUNT }; @@ -133,19 +135,19 @@ enum temp_sensor_id { /* List of possible batteries */ enum battery_type { - BATTERY_DANAPACK_COS, - BATTERY_DANAPACK_ATL, - BATTERY_DANAPACK_HIGHPOWER, - BATTERY_DANAPACK_BYD, + BATTERY_DYNAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_DYNAPACK_HIGHPOWER, + BATTERY_DYNAPACK_BYD, BATTERY_SAMSUNG_SDI, BATTERY_SIMPLO_COS, BATTERY_SIMPLO_HIGHPOWER, BATTERY_COS, + BATTERY_COS_2, + BATTERY_ATL, BATTERY_TYPE_COUNT, }; -int board_is_sourcing_vbus(int port); - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/drawcia/build.mk b/board/drawcia/build.mk index 00e4e0bb5d..9b862c7624 100644 --- a/board/drawcia/build.mk +++ b/board/drawcia/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,5 +11,5 @@ CHIP_FAMILY:=it8320 CHIP_VARIANT:=it8320dx BASEBOARD:=dedede -board-y=board.o led.o usb_pd_policy.o +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/drawcia/cbi_ssfc.c b/board/drawcia/cbi_ssfc.c new file mode 100644 index 0000000000..324ceffb63 --- /dev/null +++ b/board/drawcia/cbi_ssfc.c @@ -0,0 +1,41 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} + +enum ec_ssfc_tcpc_p1 get_cbi_ssfc_tcpc_p1(void) +{ + return (enum ec_ssfc_tcpc_p1)cached_ssfc.tcpc_type; +} diff --git a/board/drawcia/cbi_ssfc.h b/board/drawcia/cbi_ssfc.h new file mode 100644 index 0000000000..407efaf3f5 --- /dev/null +++ b/board/drawcia/cbi_ssfc.h @@ -0,0 +1,85 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_BMA422 = 2, +}; + +/* + * TCPC Port 1 (Bits 6-7) + */ +enum ec_ssfc_tcpc_p1 { + SSFC_TCPC_P1_DEFAULT, + SSFC_TCPC_P1_PS8705, + SSFC_TCPC_P1_PS8805, +}; + +/* + * Audio Codec Source(Bit 8-10) + */ +enum ec_ssfc_audio_codec_source { + SSFC_AUDIO_CODEC_DEFAULT = 0, + SSFC_AUDIO_CODEC_VD = 1, + SSFC_ADUIO_CODEC_VS = 2, +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t tcpc_type : 2; + uint32_t audio_codec_source : 3; + uint32_t reserved_2 : 21; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +/** + * Get the TCPC port 1 type from SSFC_CONFIG. + * + * @return the TCPC type. + */ +enum ec_ssfc_tcpc_p1 get_cbi_ssfc_tcpc_p1(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/drawcia/ec.tasklist b/board/drawcia/ec.tasklist index 75181a4531..c3c360febb 100644 --- a/board/drawcia/ec.tasklist +++ b/board/drawcia/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,13 +12,13 @@ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/drawcia/gpio.inc b/board/drawcia/gpio.inc index cfc6b5e867..0c4599911a 100644 --- a/board/drawcia/gpio.inc +++ b/board/drawcia/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -36,8 +36,8 @@ GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_cc /* Other interrupts */ GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) -GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH, button_interrupt) -GPIO_INT(VOLUP_BTN_ODL_HDMI_HPD, PIN(I, 7), GPIO_INT_BOTH, button_sub_hdmi_hpd_interrupt) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL_HDMI_HPD, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_sub_hdmi_hpd_interrupt) GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) GPIO_INT(PEN_DET_ODL, PIN(J, 1), GPIO_INT_BOTH | GPIO_PULL_UP, pen_detect_interrupt) @@ -98,7 +98,8 @@ GPIO(EC_SUB_IO_2_1, PIN(F, 1), GPIO_INPUT) /* Misc */ GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) -GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_INPUT) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) GPIO(EN_KB_BL, PIN(J, 3), GPIO_OUT_LOW) /* Currently unused */ GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) @@ -123,6 +124,12 @@ GPIO(BAT_LED_WHITE_L, PIN(A, 2), GPIO_OUT_HIGH) GPIO(PWR_LED_WHITE_L, PIN(A, 3), GPIO_OUT_HIGH) /* Alternate functions GPIO definitions */ +/* Keyboard */ +ALTERNATE(PIN_MASK(KSI, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSI0-7 */ +ALTERNATE(PIN_MASK(KSO_H, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO8-15 */ +ALTERNATE(PIN_MASK(KSO_L, 0xFB), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO0-1, 3-7 */ +GPIO(EC_KSO_02_INV, PIN(KSO_L, 2), GPIO_OUT_HIGH) /* KSO2 inverted */ + /* UART */ ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ diff --git a/board/drawcia/led.c b/board/drawcia/led.c index 68242180fa..bc4db1d983 100644 --- a/board/drawcia/led.c +++ b/board/drawcia/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #include "cbi_fw_config.h" #include "charge_state.h" #include "extpower.h" +#include "gpio.h" #include "hooks.h" #include "led_common.h" @@ -17,10 +18,8 @@ #define POWER_LED_ON 0 #define POWER_LED_OFF 1 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -28,7 +27,7 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int led_set_color_battery(enum led_color color) @@ -52,7 +51,7 @@ static int led_set_color_battery(enum led_color color) return EC_SUCCESS; } -static int led_set_color_power(enum ec_led_colors color) +static int led_set_color_power(enum led_color color) { switch (color) { case LED_OFF: @@ -115,7 +114,6 @@ static void led_set_battery(void) { static int battery_ticks; static int power_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; @@ -126,26 +124,26 @@ static void led_set_battery(void) */ if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_ABSENT) { if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && - charge_get_state() != PWR_STATE_CHARGE) { - led_set_color_battery(power_ticks++ & 0x2 ? - LED_WHITE : LED_OFF); + led_pwr_get_state() != LED_PWRS_CHARGE) { + led_set_color_battery(power_ticks++ & 0x2 ? LED_WHITE : + LED_OFF); return; } } power_ticks = 0; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: led_set_color_battery(LED_AMBER); break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { led_set_color_battery(LED_WHITE); break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE: + __fallthrough; + case LED_PWRS_DISCHARGE: /* * Blink white light (1 sec on, 1 sec off) * when battery capacity is less than 10% @@ -156,19 +154,19 @@ static void led_set_battery(void) else led_set_color_battery(LED_OFF); break; - case PWR_STATE_ERROR: - led_set_color_battery( - (battery_ticks % 0x2) ? LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + led_set_color_battery((battery_ticks % 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: led_set_color_battery(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - led_set_color_battery( - (battery_ticks & 0x2) ? LED_AMBER : LED_OFF); - else - led_set_color_battery(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + led_set_color_battery(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + led_set_color_battery((battery_ticks & 0x2) ? LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ @@ -185,8 +183,7 @@ static void led_set_power(void) if (chipset_in_state(CHIPSET_STATE_ON)) led_set_color_power(LED_WHITE); else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) - led_set_color_power( - (power_tick & 0x2) ? LED_WHITE : LED_OFF); + led_set_color_power((power_tick & 0x2) ? LED_WHITE : LED_OFF); else led_set_color_power(LED_OFF); } diff --git a/board/drawcia/usb_pd_policy.c b/board/drawcia/usb_pd_policy.c index 9d53f20047..2433b25431 100644 --- a/board/drawcia/usb_pd_policy.c +++ b/board/drawcia/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,8 +13,8 @@ #include "driver/tcpm/tcpci.h" #include "usb_pd.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -38,11 +38,6 @@ void pd_power_supply_reset(int port) if (prev_en) sm5803_set_vbus_disch(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -62,11 +57,6 @@ int pd_set_power_supply_ready(int port) /* Provide Vbus */ charger_enable_otg_power(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -75,18 +65,7 @@ int pd_set_power_supply_ready(int port) __override bool pd_check_vbus_level(int port, enum vbus_level level) { - int vbus_voltage; - - /* If we're unable to speak to the charger, best to guess false */ - if (charger_get_vbus_voltage(port, &vbus_voltage)) - return false; - - if (level == VBUS_SAFE0V) - return vbus_voltage < PD_V_SAFE0V_MAX; - else if (level == VBUS_PRESENT) - return vbus_voltage > PD_V_SAFE5V_MIN; - else - return vbus_voltage < PD_V_SINK_DISCONNECT_MAX; + return sm5803_check_vbus_level(port, level); } int pd_snk_is_vbus_provided(int port) diff --git a/board/drawcia/vif_override.xml b/board/drawcia/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/drawcia/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/drawcia_riscv/battery.c b/board/drawcia_riscv/battery.c new file mode 100644 index 0000000000..074bc78d58 --- /dev/null +++ b/board/drawcia_riscv/battery.c @@ -0,0 +1,349 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all drawcia battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* DynaPack CosMX Battery Information */ + [BATTERY_DYNAPACK_COS] = { + .fuel_gauge = { + .manuf_name = "333-2C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack ATL Battery Information */ + [BATTERY_DYNAPACK_ATL] = { + .fuel_gauge = { + .manuf_name = "333-27-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack HIGHPOWER Battery Information */ + [BATTERY_DYNAPACK_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-2D-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack BYD Battery Information */ + [BATTERY_DYNAPACK_BYD] = { + .fuel_gauge = { + .manuf_name = "333-2E-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Samsung SDI Battery Information */ + [BATTERY_SAMSUNG_SDI] = { + .fuel_gauge = { + .manuf_name = "333-54-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Simplo CosMX Battery Information */ + [BATTERY_SIMPLO_COS] = { + .fuel_gauge = { + .manuf_name = "333-1C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Simplo HIGHPOWER Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-1D-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* CosMX Battery Information */ + [BATTERY_COS] = { + .fuel_gauge = { + .manuf_name = "333-AC-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* CosMX B00C4473A9D0002 Battery Information */ + [BATTERY_COS_2] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* ATL GB-S20-4473A9-01H&020H Battery Information + * Gauge IC : RAJ240045 + */ + [BATTERY_ATL] = { + .fuel_gauge = { + .manuf_name = "313-B7-0D-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x43, + .reg_mask = 0x0003, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; diff --git a/board/drawcia_riscv/board.c b/board/drawcia_riscv/board.c new file mode 100644 index 0000000000..d8d0189635 --- /dev/null +++ b/board/drawcia_riscv/board.c @@ -0,0 +1,707 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Drawcia board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "cros_board_info.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/sm5803.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/it8xxx2_pd_public.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +uint32_t board_version; + +/* GPIO to enable/disable the USB Type-A port. */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +__override void board_process_pd_alert(int port) +{ + /* + * PD_INT task will process this alert, and that task is only needed on + * C1. + */ + if (port != 1) + return; + + if (gpio_get_level(GPIO_USB_C1_INT_ODL)) + return; + + sm5803_handle_interrupt(port); +} + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + sm5803_interrupt(0); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void button_sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + int hdmi_hpd = gpio_get_level(GPIO_VOLUP_BTN_ODL_HDMI_HPD); + + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, hdmi_hpd); + else + button_interrupt(s); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +static void pen_detect_interrupt(enum gpio_signal s) +{ + int pen_detect = !gpio_get_level(GPIO_PEN_DET_ODL); + + gpio_set_level(GPIO_EN_PP5000_PEN, pen_detect); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_SUB_ANALOG] = { .name = "SUB_ANALOG", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, + [ADC_TEMP_SENSOR_4] = { .name = "TEMP_SENSOR4", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH16 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + [CHARGER_PRIMARY] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS, + .drv = &sm5803_drv, + }, + [CHARGER_SECONDARY] = { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS, + .drv = &sm5803_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &it8xxx2_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, +}; + +/* Sensor Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Sensor Data */ +static struct accelgyro_saved_data_t g_bma253_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* Matrix to rotate accelrator into standard reference frame */ +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* Drivers */ +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void board_init(void) +{ + int on; + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) { + /* Select HDMI option */ + gpio_set_level(GPIO_HDMI_SEL_L, 0); + } else { + /* Select AUX option */ + gpio_set_level(GPIO_HDMI_SEL_L, 1); + } + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_INT_ODL); + + /* Store board version for use in determining charge limits */ + cbi_get_board_version(&board_version); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) + hook_call_deferred(&check_c1_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_PRESENT) { + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable Base Accel interrupt */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } + + gpio_enable_interrupt(GPIO_PEN_DET_ODL); + + /* Make sure pen detection is triggered or not at sysjump */ + if (!gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_EN_PP5000_PEN, 1); + + /* Charger on the MB will be outputting PROCHOT_ODL and OD CHG_DET */ + sm5803_configure_gpio0(CHARGER_PRIMARY, GPIO0_MODE_PROCHOT, 1); + sm5803_configure_chg_det_od(CHARGER_PRIMARY, 1); + + if (board_get_charger_chip_count() > 1) { + /* Charger on the sub-board will be a push-pull GPIO */ + sm5803_configure_gpio0(CHARGER_SECONDARY, GPIO0_MODE_OUTPUT, 0); + } + + /* Turn on 5V if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_resume(void) +{ + sm5803_disable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_disable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); + +static void board_suspend(void) +{ + sm5803_enable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_enable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Put all charger ICs present into low power mode before entering + * z-state. + */ + sm5803_hibernate(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_hibernate(CHARGER_SECONDARY); +} + +__override void board_ocpc_init(struct ocpc_data *ocpc) +{ + /* There's no provision to measure Isys */ + ocpc->chg_flags[CHARGER_SECONDARY] |= OCPC_NO_ISYS_MEAS_CAP; +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + + if (board_get_charger_chip_count() > 1) { + if (sm5803_set_gpio0_level(1, !!enable)) + CPRINTUSB("Failed to %sable sub rails!", + enable ? "en" : "dis"); + } +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) + return CONFIG_USB_PD_PORT_MAX_COUNT; + + ccprints("Unhandled DB configuration: %d", db); + return 0; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) + return CHARGER_NUM - 1; + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) + return CHARGER_NUM; + + ccprints("Unhandled DB configuration: %d", db); + return 0; +} + +uint16_t tcpc_get_alert_status(void) +{ + /* + * TCPC 0 is embedded in the EC and processes interrupts in the chip + * code (it83xx/intc.c) + */ + + uint16_t status = 0; + int regval; + + /* Check whether TCPC 1 pulled the shared interrupt line */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Limit C1 on board version 0 to 2.0 A */ + if ((board_version == 0) && (port == 1)) + charge_ma = MIN(charge_ma, 2000); + /* + * TODO(b/151955431): Characterize the input current limit in case a + * scaling needs to be applied here + */ + charge_set_input_current_limit(charge_ma, charge_mv); +} + +int board_set_active_charge_port(int port) +{ + int is_valid_port = (port >= 0 && port < board_get_usb_pd_port_count()); + + if (!is_valid_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTUSB("Disabling all charge ports"); + + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 0); + + if (board_get_charger_chip_count() > 1) + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 0); + + return EC_SUCCESS; + } + + CPRINTUSB("New chg p%d", port); + + /* + * Ensure other port is turned off, then enable new charge port + */ + if (port == 0) { + if (board_get_charger_chip_count() > 1) + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 0); + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 1); + + } else { + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 0); + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 1); + } + + return EC_SUCCESS; +} + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* Vconn control is only for port 0 */ + if (port) + return; + + if (cc_pin == USBPD_CC_PIN_1) + gpio_set_level(GPIO_EN_USB_C0_CC1_VCONN, !!enabled); + else + gpio_set_level(GPIO_EN_USB_C0_CC2_VCONN, !!enabled); +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + int current; + + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + current = (rp == TYPEC_RP_3A0) ? 3000 : 1500; + + charger_set_otg_current_voltage(port, current, 5000); +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 10000, + } }; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "5V regular", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 3; + *kp_div = 20; + + *ki = 3; + *ki_div = 125; + + *kd = 4; + *kd_div = 40; +} + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { GPIO_KSO_H, 4 }, { GPIO_KSO_H, 0 }, + { GPIO_KSO_H, 1 }, { GPIO_KSO_H, 3 }, { GPIO_KSO_H, 2 }, + { GPIO_KSO_L, 5 }, { GPIO_KSO_L, 6 }, { GPIO_KSO_L, 3 }, + { GPIO_KSO_L, 2 }, { GPIO_KSI, 0 }, { GPIO_KSO_L, 1 }, + { GPIO_KSO_L, 4 }, { GPIO_KSI, 3 }, { GPIO_KSI, 2 }, + { GPIO_KSO_L, 0 }, { GPIO_KSI, 5 }, { GPIO_KSI, 4 }, + { GPIO_KSO_L, 7 }, { GPIO_KSI, 6 }, { GPIO_KSI, 7 }, + { GPIO_KSI, 1 }, { -1, -1 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/drawcia_riscv/board.h b/board/drawcia_riscv/board.h new file mode 100644 index 0000000000..2867412cf8 --- /dev/null +++ b/board/drawcia_riscv/board.h @@ -0,0 +1,166 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Drawcia board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ + +/* + * We can use this define since it will work for IT81302 as well, since + * it is mostly used for TCPM config. + */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +#define CONFIG_LTO + +/* + * The workaround can be enabled on a chip variant with 1MB flash. + * (There is relocation truncated to fit error when building this board) + */ +#define CONFIG_RISCV_EXTENSION_M +#undef CONFIG_IT8XXX2_MUL_WORKAROUND + +#undef GPIO_VOLUME_UP_L +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL_HDMI_HPD + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 15000 +#define CONFIG_USB_PD_VBUS_DETECT_CHARGER +#define CONFIG_USB_PD_5V_CHARGER_CTRL +#define CONFIG_CHARGER_OTG +#undef CONFIG_CHARGER_SINGLE_CHIP +#define CONFIG_OCPC +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 21 /* R_DS(on) 10.7mOhm + 10mOhm sns rstr \ + */ + +/* PWM */ +#define CONFIG_PWM + +/* Sensors */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* Power of 2 - Too large of a fifo causes too much timestamp jitter */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* Keyboard */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_PWM_KBLIGHT + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_TCPM_PS8705 /* C1: PS8705 TCPC*/ +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* Reduce flash image footprint */ +#undef CONFIG_CMD_ACCELS + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_SUB_ANALOG, /* ADC13 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_TEMP_SENSOR_4, /* ADC16 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_4, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_DYNAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_DYNAPACK_HIGHPOWER, + BATTERY_DYNAPACK_BYD, + BATTERY_SAMSUNG_SDI, + BATTERY_SIMPLO_COS, + BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COS, + BATTERY_COS_2, + BATTERY_ATL, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/drawcia_riscv/build.mk b/board/drawcia_riscv/build.mk new file mode 100644 index 0000000000..b63b7a58b9 --- /dev/null +++ b/board/drawcia_riscv/build.mk @@ -0,0 +1,17 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# +# Reworked drawcia with it8320 replaced with RISC-V it82302 +# + +CHIP:=it83xx +CHIP_FAMILY:=it8xxx2 +CHIP_VARIANT:=it81302bx_512 +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/drawcia_riscv/cbi_ssfc.c b/board/drawcia_riscv/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/drawcia_riscv/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/drawcia_riscv/cbi_ssfc.h b/board/drawcia_riscv/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/drawcia_riscv/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/drawcia_riscv/ec.tasklist b/board/drawcia_riscv/ec.tasklist new file mode 100644 index 0000000000..c13df44543 --- /dev/null +++ b/board/drawcia_riscv/ec.tasklist @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/drawcia_riscv/gpio.inc b/board/drawcia_riscv/gpio.inc new file mode 100644 index 0000000000..ad20442673 --- /dev/null +++ b/board/drawcia_riscv/gpio.inc @@ -0,0 +1,148 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(USB_C1_INT_ODL, PIN(E, 6), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c1_interrupt) /* TCPC, charger, BC12 */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL_HDMI_HPD, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_sub_hdmi_hpd_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(PEN_DET_ODL, PIN(J, 1), GPIO_INT_BOTH | GPIO_PULL_UP, pen_detect_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EN_USB_A_5V, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC1_VCONN, PIN(H, 4), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC2_VCONN, PIN(H, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(USB_C0_FRS, PIN(C, 4), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_HIGH) + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc pins which will run to the I/O board */ +GPIO(EC_SUB_IO_1_2, PIN(F, 0), GPIO_INPUT) +GPIO(EC_SUB_IO_2_1, PIN(F, 1), GPIO_INPUT) + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(EN_KB_BL, PIN(J, 3), GPIO_OUT_LOW) /* Currently unused */ +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_PEN, PIN(B, 5), GPIO_OUT_LOW) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* LED */ +GPIO(BAT_LED_AMBER_L, PIN(A, 1), GPIO_OUT_HIGH) +GPIO(BAT_LED_WHITE_L, PIN(A, 2), GPIO_OUT_HIGH) +GPIO(PWR_LED_WHITE_L, PIN(A, 3), GPIO_OUT_HIGH) + +/* Alternate functions GPIO definitions */ +/* Keyboard */ +ALTERNATE(PIN_MASK(KSI, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSI0-7 */ +ALTERNATE(PIN_MASK(KSO_H, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO8-15 */ +ALTERNATE(PIN_MASK(KSO_L, 0xFB), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO0-1, 3-7 */ +GPIO(EC_KSO_02_INV, PIN(KSO_L, 2), GPIO_OUT_HIGH) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC13: EC_SUB_ANALOG, ADC15: TEMP_SENSOR_3, ADC16: TEMP_SENSOR_4 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(0)), 0, MODULE_PWM, 0) /* KB_BL_PWM */ diff --git a/board/drawcia_riscv/led.c b/board/drawcia_riscv/led.c new file mode 100644 index 0000000000..926f83d1f6 --- /dev/null +++ b/board/drawcia_riscv/led.c @@ -0,0 +1,200 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Drawcia specific LED settings. */ + +#include "cbi_fw_config.h" +#include "charge_state.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static int led_set_color_battery(enum led_color color) +{ + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_BAT_LED_WHITE_L, BAT_LED_OFF); + gpio_set_level(GPIO_BAT_LED_AMBER_L, BAT_LED_OFF); + break; + case LED_WHITE: + gpio_set_level(GPIO_BAT_LED_WHITE_L, BAT_LED_ON); + gpio_set_level(GPIO_BAT_LED_AMBER_L, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(GPIO_BAT_LED_WHITE_L, BAT_LED_OFF); + gpio_set_level(GPIO_BAT_LED_AMBER_L, BAT_LED_ON); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} + +static int led_set_color_power(enum led_color color) +{ + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_OFF); + break; + case LED_WHITE: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_ON); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_POWER_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + break; + default: + break; + } +} + +static int led_set_color(enum ec_led_id led_id, enum led_color color) +{ + int rv; + + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + rv = led_set_color_battery(color); + break; + case EC_LED_ID_POWER_LED: + rv = led_set_color_power(color); + break; + default: + return EC_ERROR_UNKNOWN; + } + return rv; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color(led_id, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color(led_id, LED_AMBER); + else + led_set_color(led_id, LED_OFF); + + return EC_SUCCESS; +} + +static void led_set_battery(void) +{ + static int battery_ticks; + static int power_ticks; + + battery_ticks++; + + /* + * Override battery LED for Drawlet/Drawman, Drawlet/Drawman + * don't have power LED, blinking battery white LED to indicate + * system suspend without charging. + */ + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_ABSENT) { + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + led_set_color_battery(power_ticks++ & 0x2 ? LED_WHITE : + LED_OFF); + return; + } + } + + power_ticks = 0; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + led_set_color_battery(LED_AMBER); + break; + case LED_PWRS_DISCHARGE_FULL: + if (extpower_is_present()) { + led_set_color_battery(LED_WHITE); + break; + } + __fallthrough; + case LED_PWRS_DISCHARGE: + /* + * Blink white light (1 sec on, 1 sec off) + * when battery capacity is less than 10% + */ + if (charge_get_percent() < 10) + led_set_color_battery( + (battery_ticks & 0x2) ? LED_WHITE : LED_OFF); + else + led_set_color_battery(LED_OFF); + break; + case LED_PWRS_ERROR: + led_set_color_battery((battery_ticks % 0x2) ? LED_WHITE : + LED_OFF); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + led_set_color_battery(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + led_set_color_battery(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + led_set_color_battery((battery_ticks & 0x2) ? LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +static void led_set_power(void) +{ + static int power_tick; + + power_tick++; + + if (chipset_in_state(CHIPSET_STATE_ON)) + led_set_color_power(LED_WHITE); + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + led_set_color_power((power_tick & 0x2) ? LED_WHITE : LED_OFF); + else + led_set_color_power(LED_OFF); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + led_set_power(); + + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/drawcia_riscv/usb_pd_policy.c b/board/drawcia_riscv/usb_pd_policy.c new file mode 100644 index 0000000000..8a2c07c575 --- /dev/null +++ b/board/drawcia_riscv/usb_pd_policy.c @@ -0,0 +1,74 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/sm5803.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + if (port < 0 || port >= board_get_usb_pd_port_count()) + return; + + prev_en = charger_is_sourcing_otg_power(port); + + /* Disable Vbus */ + charger_enable_otg_power(port, 0); + + /* Discharge Vbus if previously enabled */ + if (prev_en) + sm5803_set_vbus_disch(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + enum ec_error_list rv; + + /* Disable sinking */ + rv = sm5803_vbus_sink_enable(port, 0); + if (rv) + return rv; + + /* Disable Vbus discharge */ + sm5803_set_vbus_disch(port, 0); + + /* Provide Vbus */ + charger_enable_otg_power(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +__override bool pd_check_vbus_level(int port, enum vbus_level level) +{ + return sm5803_check_vbus_level(port, level); +} + +int pd_snk_is_vbus_provided(int port) +{ + return sm5803_is_vbus_present(port); +} diff --git a/board/drawcia_riscv/vif_override.xml b/board/drawcia_riscv/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/drawcia_riscv/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/driblee/battery.c b/board/driblee/battery.c new file mode 100644 index 0000000000..d73bc104ac --- /dev/null +++ b/board/driblee/battery.c @@ -0,0 +1,658 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_state.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for lalala battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* BYD Battery Information */ + [BATTERY_BYD_1VX1H] = { + .fuel_gauge = { + .manuf_name = "BYD", + .device_name = "DELL 1VX1H", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* BYD Battery Information */ + [BATTERY_BYD_YT39X] = { + .fuel_gauge = { + .manuf_name = "BYD", + .device_name = "DELL YT39X", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* BYD Battery Information */ + [BATTERY_BYD_X0Y5M] = { + .fuel_gauge = { + .manuf_name = "BYD", + .device_name = "DELL X0Y5M", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x043, + .reg_mask = 0x0001, + .disconnect_val = 0x0000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* LGC Battery Information */ + [BATTERY_LGC_FDRHM] = { + .fuel_gauge = { + .manuf_name = "LGC-LGC3.65", + .device_name = "DELL FDRHM", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11460, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* LGC Battery Information */ + [BATTERY_LGC_8GHCX] = { + .fuel_gauge = { + .manuf_name = "LGC-LGC3.65", + .device_name = "DELL 8GHCX", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11460, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + + /* SWD-ATL Battery Information */ + [BATTERY_SWD_ATL_WJPC4] = { + .fuel_gauge = { + .manuf_name = "SWD-ATL3.618", + .device_name = "DELL WJPC4", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SWD-ATL Battery Information */ + [BATTERY_SWD_ATL_CTGKT] = { + .fuel_gauge = { + .manuf_name = "SWD-ATL3.618", + .device_name = "DELL CTGKT", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SWD-COS Battery Information */ + [BATTERY_SWD_COS_WJPC4] = { + .fuel_gauge = { + .manuf_name = "SWD-COS3.634", + .device_name = "DELL WJPC4", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SWD-COS Battery Information */ + [BATTERY_SWD_COS_CTGKT] = { + .fuel_gauge = { + .manuf_name = "SWD-COS3.634", + .device_name = "DELL CTGKT", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-ATL Battery Information */ + [BATTERY_SMP_ATL_VM732] = { + .fuel_gauge = { + .manuf_name = "SMP-ATL-3.61", + .device_name = "DELL VM732", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-ATL Battery Information */ + [BATTERY_SMP_ATL_26JGK] = { + .fuel_gauge = { + .manuf_name = "SMP-ATL-3.61", + .device_name = "DELL 26JGK", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-ATL Battery Information */ + [BATTERY_SMP_ATL_RF9H3] = { + .fuel_gauge = { + .manuf_name = "SMP-ATL-3.61", + .device_name = "DELL RF9H3", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-COS Battery Information */ + [BATTERY_SMP_COS_VM732] = { + .fuel_gauge = { + .manuf_name = "SMP-COS3.63", + .device_name = "DELL VM732", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* SMP-COS Battery Information */ + [BATTERY_SMP_COS_26JGK] = { + .fuel_gauge = { + .manuf_name = "SMP-COS3.63", + .device_name = "DELL 26JGK", + .ship_mode = { + .wb_support = 1, + .reg_addr = 0x44, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + /* SMP-COS Battery Information */ + [BATTERY_SMP_COS_RF9H3] = { + .fuel_gauge = { + .manuf_name = "SMP-COS3.63", + .device_name = "DELL RF9H3", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = -3, + .start_charging_max_c = 50, + .charging_min_c = -3, + .charging_max_c = 60, + .discharging_min_c = -5, + .discharging_max_c = 70, + }, + }, + + /* BYD 16DPHYMD Battery Information */ + [BATTERY_BYD16] = { + .fuel_gauge = { + .manuf_name = "BYD-BYD3.685", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x043, + .reg_mask = 0x0001, + .disconnect_val = 0x000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, + + /* LGC Battery Information */ + [BATTERY_LGC3] = { + .fuel_gauge = { + .manuf_name = "LGC-LGC3.553", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, + + /* SIMPLO Battery Information */ + [BATTERY_SIMPLO] = { + .fuel_gauge = { + .manuf_name = "SMP-SDI3.72", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x043, + .reg_mask = 0x0001, + .disconnect_val = 0x000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, + + /* SIMPLO-LISHEN 7T0D3YMD Battery Information */ + [BATTERY_SIMPLO_LS] = { + .fuel_gauge = { + .manuf_name = "SMP-LS3.66", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x043, + .reg_mask = 0x0001, + .disconnect_val = 0x000, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = 0, + .discharging_max_c = 70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_BYD_1VX1H; + +int charger_profile_override(struct charge_state_data *curr) +{ + if (chipset_in_state(CHIPSET_STATE_ON)) { + curr->requested_current = + MIN(curr->requested_current, CHARGING_CURRENT_1100MA); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/driblee/board.c b/board/driblee/board.c new file mode 100644 index 0000000000..739be95ce3 --- /dev/null +++ b/board/driblee/board.c @@ -0,0 +1,493 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lalala board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/ps8802.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/pi3usb3x532.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_8042.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "stdbool.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "temp_sensor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +#define ADC_VOL_UP_MASK BIT(0) +#define ADC_VOL_DOWN_MASK BIT(1) + +static uint8_t new_adc_key_state; + +/******************************************************************************/ +/* USB-A Configuration */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, +}; + +/* Keyboard scan setting */ +static const struct ec_response_keybd_config driblee_keybd = { + /* Default Chromeos keyboard config */ + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad, has screenlock key */ + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &driblee_keybd; +} + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + int hdmi_hpd_odl = gpio_get_level(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, !hdmi_hpd_odl); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_b = THERMAL_B; + +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; + +static void setup_thermal(void) +{ + thermal_params[TEMP_SENSOR_1] = thermal_a; + thermal_params[TEMP_SENSOR_2] = thermal_b; +} + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +static void set_5v_gpio(int level) +{ + gpio_set_level(GPIO_EN_PP5000, level); + gpio_set_level(GPIO_EN_USB_A0_VBUS, level); +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC. + */ + set_5v_gpio(!!enable); +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + return CONFIG_USB_PD_PORT_MAX_COUNT; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + return CHARGER_NUM; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + check_c0_line(); + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + /* Initialize THERMAL */ + setup_thermal(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Enable HDMI any time the SoC is on */ +static void hdmi_enable(void) +{ + if (get_cbi_fw_config_hdmi() == HDMI_PRESENT) { + gpio_set_level(GPIO_EC_HDMI_EN_ODL, 0); + gpio_set_level(GPIO_HDMI_PP3300_EN, 1); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, hdmi_enable, HOOK_PRIO_DEFAULT); + +static void hdmi_disable(void) +{ + if (get_cbi_fw_config_hdmi() == HDMI_PRESENT) { + gpio_set_level(GPIO_EC_HDMI_EN_ODL, 1); + gpio_set_level(GPIO_HDMI_PP3300_EN, 0); + } +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, hdmi_disable, HOOK_PRIO_DEFAULT); + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; +const unsigned int chg_cnt = ARRAY_SIZE(chg_chips); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + }, +}; + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + return status; +} + +int adc_to_physical_value(enum gpio_signal gpio) +{ + if (gpio == GPIO_VOLUME_UP_L) + return !!(new_adc_key_state & ADC_VOL_UP_MASK); + else if (gpio == GPIO_VOLUME_DOWN_L) + return !!(new_adc_key_state & ADC_VOL_DOWN_MASK); + + CPRINTS("Not a volume up or down key"); + return 0; +} + +int button_is_adc_detected(enum gpio_signal gpio) +{ + return (gpio == GPIO_VOLUME_DOWN_L) || (gpio == GPIO_VOLUME_UP_L); +} + +static void board_extpower(void) +{ + int extpower_present; + + if (pd_is_connected(0)) + extpower_present = extpower_is_present(); + else + extpower_present = 0; + + gpio_set_level(GPIO_EC_ACOK_OTG, extpower_present); +} +DECLARE_HOOK(HOOK_AC_CHANGE, board_extpower, HOOK_PRIO_DEFAULT); diff --git a/board/driblee/board.h b/board/driblee/board.h new file mode 100644 index 0000000000..e2d51723c0 --- /dev/null +++ b/board/driblee/board.h @@ -0,0 +1,155 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lalala board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KEEBY_EC_NPCX797FC +#include "baseboard.h" + +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#undef CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 +#define CONFIG_MATH_UTIL +#define CONFIG_CHARGER_PROFILE_OVERRIDE +#define CHARGING_CURRENT_1100MA 1100 + +/* + * GPIO for C1 interrupts, for baseboard use + * + * Note this line might already have its pull up disabled for HDMI DBs, but + * it should be fine to set again before z-state. + */ +#define GPIO_EC_HDMI_EN_ODL GPIO_EC_I2C_SBU_USB_C1_SCL +#define GPIO_HDMI_PP3300_EN GPIO_SUB_USB_C1_INT_ODL + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_COMMON +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* PWM */ +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ + +/* Temp sensor */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 +#define CONFIG_USBC_RETIMER_PS8802 + +/* Common USB-A defines */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_SMART +#undef CONFIG_USB_PORT_POWER_SMART_PORT_COUNT +#define CONFIG_USB_PORT_POWER_SMART_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY +#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_CDP +#define CONFIG_USB_PORT_POWER_SMART_INVERTED +#define GPIO_USB1_ILIM_SEL GPIO_USB_A0_CHARGE_EN_L + +/******************************************************************************/ + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +/* TODO(b:147440290): Need to handle multiple charger ICs */ +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ + +/* Volume Button feature */ +#define CONFIG_ADC_BUTTONS +#define CONFIG_VOLUME_BUTTONS +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_BYD_1VX1H, + BATTERY_BYD_YT39X, + BATTERY_BYD_X0Y5M, + BATTERY_LGC_FDRHM, + BATTERY_LGC_8GHCX, + BATTERY_SWD_ATL_WJPC4, + BATTERY_SWD_ATL_CTGKT, + BATTERY_SWD_COS_WJPC4, + BATTERY_SWD_COS_CTGKT, + BATTERY_SMP_ATL_VM732, + BATTERY_SMP_ATL_26JGK, + BATTERY_SMP_ATL_RF9H3, + BATTERY_SMP_COS_VM732, + BATTERY_SMP_COS_26JGK, + BATTERY_SMP_COS_RF9H3, + BATTERY_BYD16, + BATTERY_LGC3, + BATTERY_SIMPLO, + BATTERY_SIMPLO_LS, + BATTERY_TYPE_COUNT, +}; + +int board_is_sourcing_vbus(int port); +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/driblee/build.mk b/board/driblee/build.mk new file mode 100644 index 0000000000..eb422dae93 --- /dev/null +++ b/board/driblee/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=keeby + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/driblee/cbi_ssfc.c b/board/driblee/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/driblee/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/driblee/cbi_ssfc.h b/board/driblee/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/driblee/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/driblee/ec.tasklist b/board/driblee/ec.tasklist new file mode 100644 index 0000000000..386e8625b3 --- /dev/null +++ b/board/driblee/ec.tasklist @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/driblee/gpio.inc b/board/driblee/gpio.inc new file mode 100644 index 0000000000..acd6a33852 --- /dev/null +++ b/board/driblee/gpio.inc @@ -0,0 +1,141 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) +GPIO_INT(EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, PIN(9, 1), GPIO_INT_BOTH, sub_hdmi_hpd_interrupt) /* HDMI_HPD */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(A, 2), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Button interrupts */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) + +/* Misc Enables */ +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(EC_CBI_WP, PIN(E, 5), GPIO_OUT_LOW) +GPIO(SUB_USB_C1_INT_ODL, PIN(F, 5), GPIO_OUT_LOW) /* 5V power en */ +GPIO(EC_I2C_SBU_USB_C1_SCL, PIN(9, 2), GPIO_ODR_LOW) /* HDMI en */ + +/* LED */ +GPIO(LED_1_PWR_WHITE_L, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(LED_2_CHG_AMBER_L, PIN(C, 4), GPIO_OUT_HIGH) + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +/* USB pins */ +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(EN_USB_A0_VBUS, PIN(4, 1), GPIO_OUT_LOW) /* Enable A0 5V Charging */ +GPIO(USB_A0_CHARGE_EN_L, PIN(6, 3), GPIO_OUT_HIGH) /* Reverse: Enable A0 1.5A Charging */ +/* + * Lalala doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) +UNIMPLEMENTED(VOLDN_BTN_ODL) +UNIMPLEMENTED(VOLUP_BTN_ODL) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(4, 0x30), 0, MODULE_ADC, 0) /* ADC0-1 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, 0x01), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +GPIO(EC_ACOK_OTG, PIN(C, 0), GPIO_OUT_LOW) /* OTG-OVP protect enable */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO43_NC, PIN(4, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO40_NC, PIN(4, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO50_NC, PIN(5, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO34_NC, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO37_NC, PIN(3, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOF2_NC, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOF3_NC, PIN(F, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO72_NC, PIN(7, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO73_NC, PIN(7, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO75_NC, PIN(7, 5), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/driblee/led.c b/board/driblee/led.c new file mode 100644 index 0000000000..4eecb2c590 --- /dev/null +++ b/board/driblee/led.c @@ -0,0 +1,88 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for lalala + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 10; + +__override const int led_charge_lvl_2 = 100; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_1_PWR_WHITE_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_CHG_AMBER_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_1_PWR_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_CHG_AMBER_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_1_PWR_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_CHG_AMBER_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + + return EC_SUCCESS; +} diff --git a/board/driblee/usb_pd_policy.c b/board/driblee/usb_pd_policy.c new file mode 100644 index 0000000000..f8a1ee83a2 --- /dev/null +++ b/board/driblee/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/driblee/vif_override.xml b/board/driblee/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/driblee/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/drobit/battery.c b/board/drobit/battery.c new file mode 100644 index 0000000000..0db543a12f --- /dev/null +++ b/board/drobit/battery.c @@ -0,0 +1,65 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all Volteer battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* C490-42 Battery Information */ + [BATTERY_C490] = { + .fuel_gauge = { + .manuf_name = "AS3GWQd3jB", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x10, 0x10 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000c, + .disconnect_val = 0x000c, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C490; diff --git a/board/drobit/board.c b/board/drobit/board.c new file mode 100644 index 0000000000..ab4e98c887 --- /dev/null +++ b/board/drobit/board.c @@ -0,0 +1,478 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board-specific configuration */ +#include "accelgyro.h" +#include "button.h" +#include "cbi_ec_fw_config.h" +#include "charge_state.h" +#include "common.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/ppc/syv682x.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/sync.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "throttle_ap.h" +#include "uart.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config drobit_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &drobit_kb; +} + +/******************************************************************************/ +/* + * FW_CONFIG defaults for Volteer if the CBI data is not initialized. + */ +union volteer_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB4_GEN3, +}; + +/******************************************************************************/ +/* Physical fans. These are logically separate from pwm_channels. */ + +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * Fan specs from datasheet: + * Max speed 5900 rpm (+/- 7%), minimum duty cycle 30%. + * Minimum speed not specified by RPM. Set minimum RPM to max speed (with + * margin) x 30%. + * 5900 x 1.07 x 0.30 = 1894, round up to 1900 + */ +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1900, + .rpm_start = 1900, + .rpm_max = 5900, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +/******************************************************************************/ +/* EC thermal management configuration */ + +/* + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(72), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(75), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(72), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(75), \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +/******************************************************************************/ +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + .name = "usb_c1_mix", + .port = I2C_PORT_USB_C1_MIX, + .kbps = 400, + .scl = GPIO_EC_I2C0_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C0_USB_C1_MIX_SDA, + }, + { + .name = "usb_c0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C1_USB_C0_SCL, + .sda = GPIO_EC_I2C1_USB_C0_SDA, + }, + { + .name = "usb_c1", + .port = I2C_PORT_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C2_USB_C1_SCL, + .sda = GPIO_EC_I2C2_USB_C1_SDA, + }, + { + .name = "usb_1_mix", + .port = I2C_PORT_USB_1_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C3_USB_1_MIX_SCL, + .sda = GPIO_EC_I2C3_USB_1_MIX_SDA, + }, + { + .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C5_BATTERY_SCL, + .sda = GPIO_EC_I2C5_BATTERY_SDA, + }, + { + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C7_EEPROM_PWR_SCL_R, + .sda = GPIO_EC_I2C7_EEPROM_PWR_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/******************************************************************************/ +/* PWM configuration */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 10000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; + +void board_reset_pd_mcu(void) +{ +} + +/******************************************************************************/ +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/******************************************************************************/ +/* PPC support routines */ +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +/* Disable FRS on boards with the SYV682A. FRS only works on the SYV682B. */ +void setup_board_ppc(void) +{ + uint8_t board_id = get_board_id(); + + if (board_id < 2) { + ppc_chips[USBC_PORT_C0].frs_en = 0; + ppc_chips[USBC_PORT_C1].frs_en = 0; + } +} + +__override void board_cbi_init(void) +{ + setup_board_ppc(); +} + +/******************************************************************************/ +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USBC TCPC configuration */ +struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USBC mux configuration - Tiger Lake includes internal mux */ +struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_1_MIX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_1_MIX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +struct bb_usb_control bb_controls[] = { + [USBC_PORT_C0] = { + .usb_ls_en_gpio = GPIO_USB_C0_LS_EN, + .retimer_rst_gpio = GPIO_USB_C0_RT_RST_ODL, + }, + [USBC_PORT_C1] = { + .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, + .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +/******************************************************************************/ +/* TCPC support routines */ +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; +} + +/* Called on AP S0ix -> S0 tranition */ +static void board_chipset_resume(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S0ix transition */ +static void board_chipset_suspend(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); diff --git a/board/drobit/board.h b/board/drobit/board.h new file mode 100644 index 0000000000..c8e51962fa --- /dev/null +++ b/board/drobit/board.h @@ -0,0 +1,161 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* + * The RAM and flash size combination on the NPCX797FC dose not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +#define CONFIG_VBOOT_EFS2 + +#define CONFIG_POWER_BUTTON + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Chipset features */ +#define CONFIG_POWER_PP5000_CONTROL + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* Keyboard features */ +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* Sensors */ +#undef CONFIG_TABLET_MODE +#undef CONFIG_GMR_TABLET_MODE +#undef CONFIG_ACCEL_FIFO +#undef CONFIG_ACCEL_FIFO_SIZE + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* TODO: b/144165680 - measure and check these values on Volteer */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ + +/* + * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C + * cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY +#ifdef BOARD_DROBIT_ECMODEENTRY +#undef CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY +#endif + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 + +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x40 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x41 + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USBC PPC*/ +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USB_PD_FRS_PPC + +/* BC 1.2 */ + +/* Volume Button feature */ +#undef CONFIG_VOLUME_BUTTONS + +/* Fan features */ + +/* charger defines */ +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 2 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define I2C_PORT_USB_C1_MIX NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM + +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum battery_type { + BATTERY_C490, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { PWM_CH_FAN = 0, PWM_CH_KBLIGHT, PWM_CH_COUNT }; + +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void board_reset_pd_mcu(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/drobit/build.mk b/board/drobit/build.mk new file mode 100644 index 0000000000..d590255d2a --- /dev/null +++ b/board/drobit/build.mk @@ -0,0 +1,16 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=volteer + +board-y=board.o +board-y+=battery.o +board-y+=led.o diff --git a/board/drobit/ec.tasklist b/board/drobit/ec.tasklist new file mode 100644 index 0000000000..a1b5d30d93 --- /dev/null +++ b/board/drobit/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/drobit/gpio.inc b/board/drobit/gpio.inc new file mode 100644 index 0000000000..2057cfd27a --- /dev/null +++ b/board/drobit/gpio.inc @@ -0,0 +1,184 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) + +/* Sensor Interrupts */ + +/* + * Lid g-sensor interrupt unused on Volteer, configure as regular input for + * power saving. + */ + +/* USB-C interrupts */ +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) + +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) + +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) +GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) + +/* HDMI interrupts */ + +/* Volume button interrupts */ + +/* Power Sequencing Signals */ +GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ +GPIO(EC_PCH_DSW_PWROK, PIN(C, 0), GPIO_OUT_LOW) + +/* Other wake sources */ +/* + * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an + * interrupt handler because it is automatically handled by the PSL. + * + * We need to lock the setting so this gpio can't be reconfigured to overdrive + * the real reset signal. (This is the PSL input pin not the real reset pin). + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | + GPIO_HIB_WAKE_HIGH | + GPIO_LOCKED) + +/* AP/PCH Signals */ +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) + +/* USB and USBC Signals */ +GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ +GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ +GPIO(USB_C0_RT_RST_ODL, PIN(D, 4), GPIO_ODR_LOW) +GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) +GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) +GPIO(USB_C0_FRS_EN, PIN(6, 0), GPIO_OUT_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +/* There is currently no need to service this interrupt. */ +GPIO(USB_C0_RT_INT_ODL, PIN(F, 2), GPIO_INPUT) +GPIO(USB_C1_RT_INT_ODL, PIN(F, 3), GPIO_INPUT) + +/* Don't have a load switch for retimer */ +UNIMPLEMENTED(USB_C0_LS_EN) +UNIMPLEMENTED(USB_C1_LS_EN) + +/* Misc Signals */ +GPIO(EC_H1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) /* H1 Packet Mode */ +/* + * Despite their names, M2_SSD_PLN and M2_SSD_PLA are active-low, and M2_SSD_PLN + * is open-drain. + * TODO(b/138954381): Change these names when they change on the schematic. + */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_ODR_HIGH) /* SSD power-loss notification */ +GPIO(M2_SSD_PLA, PIN(7, 0), GPIO_INPUT) /* SSD power-loss acknowledgment */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(EC_SLP_S0IX, PIN(7, 2), GPIO_INPUT | GPIO_PULL_UP) + +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(LED_3_L, PIN(C, 2), GPIO_OUT_HIGH) + +/* Unused signals */ +GPIO(UNUSED_GPIO41, PIN(4, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO96, PIN(9, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO56, PIN(5, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO81, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO95, PIN(9, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOC4, PIN(C, 4), GPIO_INPUT | GPIO_PULL_UP) + +/* Only connected to test points */ +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_ESPI_ALERT_L, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) + +/* + * eDP backlight - both PCH and EC have enable pins that must be high + * for the backlight to turn on. Default state is high, and can be turned + * off during sleep states. + */ +GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C0_USB_C1_MIX_SCL, PIN(B, 5), GPIO_INPUT) /* Reserved for USB4 retimer port 1 */ +GPIO(EC_I2C0_USB_C1_MIX_SDA, PIN(B, 4), GPIO_INPUT) /* Reserved for USB4 retimer port 1 */ +GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C3_USB_1_MIX_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C3_USB_1_MIX_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C5_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C5_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_PWR_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_PWR_SDA_R, PIN(B, 2), GPIO_INPUT) + +/* Battery signals */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ +ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ + +/* Fan signals */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +ALTERNATE(PIN_MASK(B, BIT(7)), 0, MODULE_PWM, 0) /* FAN_PWM */ +ALTERNATE(PIN_MASK(4, BIT(0)), 0, MODULE_PWM, 0) /* FAN_SPEED_TACH */ + +/* Keyboard pins */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ + +/* UART */ +ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Power Switch Logic (PSL) inputs */ +ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ +ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, + GPIO01 = H1_EC_PWR_BTN_ODL + GPIO02 = EC_RST_ODL */ + +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ + diff --git a/board/drobit/led.c b/board/drobit/led.c new file mode 100644 index 0000000000..bb712a8fe0 --- /dev/null +++ b/board/drobit/led.c @@ -0,0 +1,101 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_3_L, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_3_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/drobit/vif_override.xml b/board/drobit/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/drobit/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/drobit_ecmodeentry b/board/drobit_ecmodeentry new file mode 120000 index 0000000000..c3ab5c1706 --- /dev/null +++ b/board/drobit_ecmodeentry @@ -0,0 +1 @@ +drobit \ No newline at end of file diff --git a/board/duck b/board/duck new file mode 120000 index 0000000000..7f4a914148 --- /dev/null +++ b/board/duck @@ -0,0 +1 @@ +hammer \ No newline at end of file diff --git a/board/eel b/board/eel new file mode 120000 index 0000000000..7f4a914148 --- /dev/null +++ b/board/eel @@ -0,0 +1 @@ +hammer \ No newline at end of file diff --git a/board/eldrid/battery.c b/board/eldrid/battery.c index 3c9f2b0c21..6f9e6df5af 100644 --- a/board/eldrid/battery.c +++ b/board/eldrid/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -100,7 +100,9 @@ __override bool board_battery_is_initialized(void) bool batt_initialization_state; int batt_status; - batt_initialization_state = (battery_status(&batt_status) ? false : - !!(batt_status & STATUS_INITIALIZED)); + batt_initialization_state = + (battery_status(&batt_status) ? + false : + !!(batt_status & STATUS_INITIALIZED)); return batt_initialization_state; } diff --git a/board/eldrid/board.c b/board/eldrid/board.c index c665e9c9c1..c5a0bb437e 100644 --- a/board/eldrid/board.c +++ b/board/eldrid/board.c @@ -1,14 +1,14 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer board-specific configuration */ -#include "button.h" -#include "common.h" #include "accelgyro.h" +#include "button.h" #include "cbi_ec_fw_config.h" -#include "charge_state_v2.h" +#include "charge_state.h" +#include "common.h" #include "driver/accel_bma2x2.h" #include "driver/accelgyro_bmi160.h" #include "driver/bc12/pi3usb9201.h" @@ -16,6 +16,7 @@ #include "driver/ppc/syv682x.h" #include "driver/sync.h" #include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/rt1715.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tusb422.h" #include "extpower.h" @@ -23,17 +24,19 @@ #include "fan_chip.h" #include "gpio.h" #include "hooks.h" +#include "isl9241.h" +#include "keyboard_8042_sharedlib.h" #include "keyboard_raw.h" -#include "lid_switch.h" #include "keyboard_scan.h" +#include "lid_switch.h" #include "power.h" #include "power_button.h" #include "pwm.h" #include "pwm_chip.h" #include "switch.h" #include "system.h" -#include "task.h" #include "tablet_mode.h" +#include "task.h" #include "throttle_ap.h" #include "uart.h" #include "usb_mux.h" @@ -43,12 +46,13 @@ #include "usbc_ppc.h" #include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Increase from 50 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* Other values should be the same as the default configuration. */ @@ -71,10 +75,58 @@ union volteer_cbi_fw_config fw_config_defaults = { .usb_db = DB_USB3_ACTIVE, }; +static void board_charger_config(void) +{ + /* + * b/166728543, we configured charger setting to throttle CPU + * when the system loading is at battery current limit. + */ + int reg; + + /* + * Set DCProchot# to 5120mA + */ + isl9241_set_dc_prochot(CHARGER_SOLO, 5120); + + /* + * Set Control1 bit<3> = 1, PSYS = 1 + */ + if (i2c_read16(I2C_PORT_CHARGER, ISL9241_ADDR_FLAGS, + ISL9241_REG_CONTROL1, ®) == EC_SUCCESS) { + reg |= ISL9241_CONTROL1_PSYS; + if (i2c_write16(I2C_PORT_CHARGER, ISL9241_ADDR_FLAGS, + ISL9241_REG_CONTROL1, reg)) + CPRINTS("Failed to set isl9241"); + } + + /* + * Set Control2 bit<10:9> = 00, PROCHOT# Debounce = 7us + */ + if (i2c_read16(I2C_PORT_CHARGER, ISL9241_ADDR_FLAGS, + ISL9241_REG_CONTROL2, ®) == EC_SUCCESS) { + reg &= ~ISL9241_CONTROL2_PROCHOT_DEBOUNCE_MASK; + if (i2c_write16(I2C_PORT_CHARGER, ISL9241_ADDR_FLAGS, + ISL9241_REG_CONTROL2, reg)) + CPRINTS("Failed to set isl9241"); + } + + /* + * Set Control4 bit<11> = 1, PSYS Rsense Ratio = 1:1 + */ + if (i2c_read16(I2C_PORT_CHARGER, ISL9241_ADDR_FLAGS, + ISL9241_REG_CONTROL4, ®) == EC_SUCCESS) { + reg |= ISL9241_CONTROL4_PSYS_RSENSE_RATIO; + if (i2c_write16(I2C_PORT_CHARGER, ISL9241_ADDR_FLAGS, + ISL9241_REG_CONTROL4, reg)) + CPRINTS("Failed to set isl9241"); + } +} + static void board_init(void) { pwm_enable(PWM_CH_LED4_SIDESEL, 1); pwm_set_duty(PWM_CH_LED4_SIDESEL, 100); + board_charger_config(); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -115,23 +167,23 @@ __override bool board_is_tbt_usb4_port(int port) * TODO (b/147732807): All the USB-C ports need to support same * features. Need to fix once USB-C feature set is known for Volteer. */ - return ((port == USBC_PORT_C1) - && ((usb_db == DB_USB4_GEN2) || (usb_db == DB_USB4_GEN3))); + return ((port == USBC_PORT_C1) && + ((usb_db == DB_USB4_GEN2) || (usb_db == DB_USB4_GEN3))); } __override void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) + int max_ma, int charge_mv) { /* - * Follow OEM request to limit the input current to - * 90% negotiated limit when S0. + * b/166728543 + * Set different AC_PROCHOT value when using different wattage ADT. */ - if (chipset_in_state(CHIPSET_STATE_ON)) - charge_ma = charge_ma * 90 / 100; + if (max_ma * charge_mv == PD_MAX_POWER_MW * 1000) + isl9241_set_ac_prochot(0, 3840); + else + isl9241_set_ac_prochot(0, 3328); - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } /******************************************************************************/ @@ -139,7 +191,7 @@ __override void board_set_charge_limit(int port, int supplier, int charge_ma, const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -256,11 +308,10 @@ static const struct tcpc_config_t tcpc_config_p1_usb3 = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .flags = TCPC_FLAGS_TCPCI_REV2_0 | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, .drv = &ps8xxx_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), }; /* @@ -268,24 +319,33 @@ static const struct tcpc_config_t tcpc_config_p1_usb3 = { * virtual_usb_mux_driver so the AP gets notified of mux changes and updates * the TCSS configuration on state changes. */ -static const struct usb_mux usbc1_usb3_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .next_mux = NULL, +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, }; -static const struct usb_mux mux_config_p1_usb3_active = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb3_db_retimer, +static const struct usb_mux_chain mux_config_p1_usb3_active = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, }; -static const struct usb_mux mux_config_p1_usb3_passive = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, +static const struct usb_mux_chain mux_config_p1_usb3_passive = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }; /******************************************************************************/ @@ -302,8 +362,7 @@ static void ps8815_reset(void) int val; gpio_set_level(ps8xxx_rst_odl, 0); - msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, - PS8815_PWR_H_RST_H_DELAY_MS)); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); gpio_set_level(ps8xxx_rst_odl, 1); msleep(PS8815_FW_INIT_DELAY_MS); @@ -314,16 +373,16 @@ static void ps8815_reset(void) CPRINTS("%s: patching ps8815 registers", __func__); - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) CPRINTS("ps8815: reg 0x0f was %02x", val); - if (i2c_write8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, 0x31) == EC_SUCCESS) + if (i2c_write8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) CPRINTS("ps8815: reg 0x0f set to 0x31"); - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) CPRINTS("ps8815: reg 0x0f now %02x", val); } @@ -335,7 +394,9 @@ void board_reset_pd_mcu(void) /* Daughterboard specific reset for port 1 */ if (usb_db == DB_USB3_ACTIVE) { ps8815_reset(); - usb_mux_hpd_update(USBC_PORT_C1, 0, 0); + usb_mux_hpd_update(USBC_PORT_C1, + USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } } @@ -365,11 +426,29 @@ static void config_db_usb3_passive(void) usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3_passive; } +static void config_port_discrete_tcpc(int port) +{ + /* + * Support 2 Pin-to-Pin compatible parts: TUSB422 and RT1715, for + * simplicity allow either and decide which we are using. + * Default to TUSB422, and switch to RT1715 after BOARD_ID >=1. + */ + if (get_board_id() >= 1) { + CPRINTS("C%d: RT1715", port); + tcpc_config[port].i2c_info.addr_flags = RT1715_I2C_ADDR_FLAGS; + tcpc_config[port].drv = &rt1715_tcpm_drv; + return; + } + CPRINTS("C%d: Default to TUSB422", port); +} + static const char *db_type_prefix = "USB DB type: "; __override void board_cbi_init(void) { enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); + config_port_discrete_tcpc(0); + switch (usb_db) { case DB_USB_ABSENT: CPRINTS("%sNone", db_type_prefix); @@ -395,6 +474,13 @@ __override void board_cbi_init(void) if ((!IS_ENABLED(TEST_BUILD) && !ec_cfg_has_numeric_pad()) || get_board_id() < 1) keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); + + /* + * If keyboard is US2(KB_LAYOUT_1), we need translate right ctrl + * to backslash(\|) key. + */ + if (ec_cfg_keyboard_layout() == KB_LAYOUT_1) + set_scancode_set2(4, 0, get_scancode_set2(2, 7)); } /******************************************************************************/ @@ -424,6 +510,7 @@ void ppc_interrupt(enum gpio_signal signal) break; case GPIO_USB_C1_PPC_INT_ODL: syv682x_interrupt(USBC_PORT_C1); + break; default: break; } @@ -453,7 +540,6 @@ struct tcpc_config_t tcpc_config[] = { .addr_flags = TUSB422_I2C_ADDR_FLAGS, }, .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), }, [USBC_PORT_C1] = { .bus_type = EC_BUS_TYPE_I2C, @@ -462,7 +548,6 @@ struct tcpc_config_t tcpc_config[] = { .addr_flags = TUSB422_I2C_ADDR_FLAGS, }, .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), }, }; BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); @@ -470,16 +555,20 @@ BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); /******************************************************************************/ /* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usb_muxes[] = { +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }, [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); diff --git a/board/eldrid/board.h b/board/eldrid/board.h index b7b0b62d95..84c04217d8 100644 --- a/board/eldrid/board.h +++ b/board/eldrid/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,16 +11,13 @@ /* Baseboard features */ #include "baseboard.h" -#ifdef BOARD_VOLTEER_TCPMV1 -/* Disable TCPMv2 configuration options */ -#undef CONFIG_USB_PD_TCPMV2 - -/* Enable the required TCPMv1 options */ -#define CONFIG_USB_PD_TCPMV1 -#endif - /* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ +#undef CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION #define CONFIG_VBOOT_EFS2 @@ -33,11 +30,18 @@ #define CONFIG_POWER_PP5000_CONTROL /* LED defines */ -#define CONFIG_LED_POWER_LED #define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 /* Keyboard features */ +/* + * Disable VOL up/down when tablet mode. + * TODO(b/170966461): Re-enable Vivaldi keyboard once + * 8042 and MKBP drivers can coexist. + */ +#undef CONFIG_KEYBOARD_VIVALDI + /* Sensors */ /* BMA253 accelerometer in base */ #define CONFIG_ACCEL_BMA255 @@ -48,52 +52,36 @@ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) /* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - (BIT(LID_ACCEL)) +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(LID_ACCEL)) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL /* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 /* TODO: b/144165680 - measure and check these values on Volteer */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ /* * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C * cables only support up to 60W. */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 - -/* Disabled PD extended message support to save flash space. */ -#undef CONFIG_USB_PD_EXTENDED_MESSAGES +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* USB Type A Features */ -#define USB_PORT_COUNT 1 +#define USB_PORT_COUNT 1 #define CONFIG_USB_PORT_POWER_DUMB /* USBC PPC*/ -#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ +#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ /* BC 1.2 */ @@ -103,8 +91,11 @@ #define CONFIG_CUSTOM_FAN_CONTROL /* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +/* OEM requested 10% derating */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 10 /* Retimer */ #undef CONFIG_USBC_RETIMER_INTEL_BB @@ -116,45 +107,42 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL /* I2C Bus Configuration */ #define CONFIG_I2C -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER #ifndef __ASSEMBLER__ @@ -181,11 +169,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; void board_reset_pd_mcu(void); diff --git a/board/eldrid/build.mk b/board/eldrid/build.mk index 8a5f8f68cd..91041efa43 100644 --- a/board/eldrid/build.mk +++ b/board/eldrid/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,7 +8,8 @@ CHIP:=npcx CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc + +CHIP_VARIANT:=npcx7m7fc BASEBOARD:=volteer board-y=board.o diff --git a/board/eldrid/ec.tasklist b/board/eldrid/ec.tasklist index 292de51cdb..c29125d517 100644 --- a/board/eldrid/ec.tasklist +++ b/board/eldrid/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,6 +16,7 @@ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/eldrid/gpio.inc b/board/eldrid/gpio.inc index 67be3988c0..08d754b366 100644 --- a/board/eldrid/gpio.inc +++ b/board/eldrid/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -177,3 +177,6 @@ ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = GPIO01 = H1_EC_PWR_BTN_ODL GPIO02 = EC_RST_ODL */ +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ diff --git a/board/eldrid/led.c b/board/eldrid/led.c index eecbf9b345..797b6d4bda 100644 --- a/board/eldrid/led.c +++ b/board/eldrid/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,41 +19,47 @@ /* LED_SIDESEL_4_L=1, MB BAT LED open * LED_SIDESEL_4_L=0, DB BAT LED open */ -#define LED_SISESEL_MB_PORT 0 -#define LED_SISESEL_DB_PORT 1 - -const int led_charge_lvl_1 = 5; - -const int led_charge_lvl_2 = 95; - -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = { - {EC_LED_COLOR_WHITE, 0.4 * LED_ONE_SEC}, - {LED_OFF, 0.4 * LED_ONE_SEC} - }, - [STATE_FACTORY_TEST] = { - {EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} - }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = { - {LED_OFF, LED_INDEFINITE} }, -}; - +#define LED_SIDESEL_MB_PORT 0 +#define LED_SIDESEL_DB_PORT 1 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_WHITE, + 0.4 * LED_ONE_SEC }, + { LED_OFF, 0.4 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 6 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, @@ -62,15 +68,31 @@ const enum ec_led_id supported_led_ids[] = { const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { int port; - - port = charge_manager_get_active_charge_port(); - - if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) - pwm_set_duty(PWM_CH_LED4_SIDESEL, - (port == LED_SISESEL_MB_PORT ? 0 : 100)); + int side_select_duty; + + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + port = charge_manager_get_active_charge_port(); + switch (port) { + case LED_SIDESEL_MB_PORT: + side_select_duty = 0; + break; + case LED_SIDESEL_DB_PORT: + side_select_duty = 100; + break; + default: + /* + * We need to turn off led here since curr.ac won't + * update immediately but led will update every 200ms. + */ + side_select_duty = 50; + color = LED_OFF; + } + + pwm_set_duty(PWM_CH_LED4_SIDESEL, side_select_duty); + } switch (color) { case EC_LED_COLOR_AMBER: @@ -88,7 +110,7 @@ void led_set_color_battery(enum ec_led_colors color) } } -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_POWER_LED_GATE, PWR_LED_ON_LVL); @@ -110,6 +132,7 @@ void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { if (led_id == EC_LED_ID_BATTERY_LED) { + led_auto_control(led_id, 0); if (brightness[EC_LED_COLOR_AMBER] != 0) led_set_color_battery(EC_LED_COLOR_AMBER); else if (brightness[EC_LED_COLOR_WHITE] != 0) @@ -125,4 +148,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/eldrid/sensors.c b/board/eldrid/sensors.c index 9a760897bf..9f8996d052 100644 --- a/board/eldrid/sensors.c +++ b/board/eldrid/sensors.c @@ -1,20 +1,21 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer family-specific sensor configuration */ -#include "common.h" #include "accelgyro.h" +#include "common.h" #include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi_common.h" #include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_bmi_common.h" #include "driver/sync.h" -#include "keyboard_scan.h" +#include "gpio.h" #include "hooks.h" #include "i2c.h" -#include "task.h" +#include "keyboard_scan.h" #include "tablet_mode.h" +#include "task.h" #include "util.h" /******************************************************************************/ @@ -29,17 +30,13 @@ static struct accelgyro_saved_data_t g_bma253_data; static struct bmi_drv_data_t g_bmi160_data; /* Rotation matrix for the lid accelerometer */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -124,22 +121,3 @@ static void board_sensors_init(void) gpio_enable_interrupt(GPIO_EC_IMU_INT_L); } DECLARE_HOOK(HOOK_INIT, board_sensors_init, HOOK_PRIO_DEFAULT); - -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); - - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif diff --git a/board/eldrid/thermal.c b/board/eldrid/thermal.c index 2f4210c36c..5ce7b362fc 100644 --- a/board/eldrid/thermal.c +++ b/board/eldrid/thermal.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,8 +15,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_THERMAL, outstr) -#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args) - +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) /******************************************************************************/ /* EC thermal management configuration */ @@ -27,17 +26,20 @@ * TODO(b/170143672): Have different sensor placement. The temperature need to * be changed. */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; /* * Inductor limits - used for both charger and PP3300 regulator @@ -50,23 +52,27 @@ const static struct ec_thermal_config thermal_cpu = { * Inductors: limit of 125c * PCB: limit is 80c */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -95,51 +101,39 @@ struct fan_step { static const struct fan_step fan_table[] = { { /* level 0 */ - .on = {-1, -1, 36, -1}, - .off = {-1, -1, 0, -1}, - .rpm = {0}, + .on = { -1, -1, 44, -1 }, + .off = { -1, -1, 0, -1 }, + .rpm = { 0 }, }, { /* level 1 */ - .on = {-1, -1, 38, -1}, - .off = {-1, -1, 36, -1}, - .rpm = {2000}, + .on = { -1, -1, 46, -1 }, + .off = { -1, -1, 44, -1 }, + .rpm = { 3200 }, }, { /* level 2 */ - .on = {-1, -1, 41, -1}, - .off = {-1, -1, 39, -1}, - .rpm = {2600}, + .on = { -1, -1, 50, -1 }, + .off = { -1, -1, 45, -1 }, + .rpm = { 3600 }, }, { /* level 3 */ - .on = {-1, -1, 44, -1}, - .off = {-1, -1, 42, -1}, - .rpm = {3000}, + .on = { -1, -1, 54, -1 }, + .off = { -1, -1, 49, -1 }, + .rpm = { 4100 }, }, { /* level 4 */ - .on = {-1, -1, 46, -1}, - .off = {-1, -1, 44, -1}, - .rpm = {3300}, + .on = { -1, -1, 58, -1 }, + .off = { -1, -1, 53, -1 }, + .rpm = { 4900 }, }, { /* level 5 */ - .on = {-1, -1, 49, -1}, - .off = {-1, -1, 47, -1}, - .rpm = {3600}, - }, - { - /* level 6 */ - .on = {-1, -1, 51, -1}, - .off = {-1, -1, 49, -1}, - .rpm = {4200}, - }, - { - /* level 7 */ - .on = {-1, -1, 55, -1}, - .off = {-1, -1, 52, -1}, - .rpm = {4700}, + .on = { -1, -1, 60, -1 }, + .off = { -1, -1, 57, -1 }, + .rpm = { 5200 }, }, }; @@ -147,6 +141,9 @@ int fan_table_to_rpm(int fan, int *temp) { /* current fan level */ static int current_level; + /* previous fan level */ + static int prev_current_level; + /* previous sensor temperature */ static int prev_temp[TEMP_SENSOR_COUNT]; const int num_fan_levels = ARRAY_SIZE(fan_table); @@ -161,22 +158,20 @@ int fan_table_to_rpm(int fan, int *temp) * 3. invariant path. (return the current RPM) */ - CPRINTS("temp: %d, prev_temp: %d", temp[TEMP_SENSOR_3_DDR_SOC], - prev_temp[TEMP_SENSOR_3_DDR_SOC]); if (temp[TEMP_SENSOR_3_DDR_SOC] < prev_temp[TEMP_SENSOR_3_DDR_SOC]) { for (i = current_level; i > 0; i--) { if (temp[TEMP_SENSOR_3_DDR_SOC] < - fan_table[i].off[TEMP_SENSOR_3_DDR_SOC]) + fan_table[i].off[TEMP_SENSOR_3_DDR_SOC]) current_level = i - 1; else break; } } else if (temp[TEMP_SENSOR_3_DDR_SOC] > - prev_temp[TEMP_SENSOR_3_DDR_SOC]) { + prev_temp[TEMP_SENSOR_3_DDR_SOC]) { for (i = current_level; i < num_fan_levels; i++) { if (temp[TEMP_SENSOR_3_DDR_SOC] > - fan_table[i].on[TEMP_SENSOR_3_DDR_SOC]) - current_level = i + 1; + fan_table[i].on[TEMP_SENSOR_3_DDR_SOC]) + current_level = i; else break; } @@ -185,10 +180,16 @@ int fan_table_to_rpm(int fan, int *temp) if (current_level < 0) current_level = 0; + if (current_level != prev_current_level) { + CPRINTS("temp: %d, prev_temp: %d", temp[TEMP_SENSOR_3_DDR_SOC], + prev_temp[TEMP_SENSOR_3_DDR_SOC]); + CPRINTS("current_level: %d", current_level); + } + for (i = 0; i < TEMP_SENSOR_COUNT; ++i) prev_temp[i] = temp[i]; - CPRINTS("current_level: %d", current_level); + prev_current_level = current_level; switch (fan) { case FAN_CH_0: @@ -205,8 +206,7 @@ void board_override_fan_control(int fan, int *temp) { if (chipset_in_state(CHIPSET_STATE_ON)) { fan_set_rpm_mode(FAN_CH(fan), 1); - fan_set_rpm_target(FAN_CH(fan), - fan_table_to_rpm(fan, temp)); + fan_set_rpm_target(FAN_CH(fan), fan_table_to_rpm(fan, temp)); } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { /* Stop fan when enter S0ix */ fan_set_rpm_mode(FAN_CH(fan), 1); diff --git a/board/eldrid/vif_override.xml b/board/eldrid/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/eldrid/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/elemi/battery.c b/board/elemi/battery.c index 9b356a8efd..f24c4c6847 100644 --- a/board/elemi/battery.c +++ b/board/elemi/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,7 +10,7 @@ #include "util.h" /* - * Battery info for all Volteer battery types. Note that the fields + * Battery info for all Elemi battery types. Note that the fields * start_charging_min/max and charging_min/max are not used for the charger. * The effective temperature limits are given by discharging_min/max_c. * @@ -32,37 +32,63 @@ * address, mask, and disconnect value need to be provided. */ const struct board_batt_params board_battery_info[] = { - /* LGC\011 L17L3PB0 Battery Information */ - /* - * Battery info provided by ODM on b/143477210, comment #11 - */ - [BATTERY_LGC011] = { + /* SMP 996QA193H Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER] = { .fuel_gauge = { - .manuf_name = "LGC", + .manuf_name = "333-1D-11-A", .ship_mode = { - .reg_addr = 0x00, - .reg_data = { 0x10, 0x10 }, + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, }, .fet = { + .mfgacc_support = 1, .reg_addr = 0x0, - .reg_mask = 0x6000, - .disconnect_val = 0x6000, - } + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + /* Cosmx CA407792G Battery Information */ + [BATTERY_COSMX] = { + .fuel_gauge = { + .manuf_name = "333-AC-11-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, }, .batt_info = { - .voltage_max = TARGET_WITH_MARGIN(13200, 5), - .voltage_normal = 11550, /* mV */ - .voltage_min = 9000, /* mV */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = 0, - .discharging_max_c = 75, + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, }, }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC011; +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO_HIGHPOWER; diff --git a/board/elemi/board.c b/board/elemi/board.c index 1993b241fb..944e585ea4 100644 --- a/board/elemi/board.c +++ b/board/elemi/board.c @@ -1,21 +1,16 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* Volteer board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "common.h" +/* Elemi board-specific configuration */ #include "accelgyro.h" +#include "button.h" #include "cbi_ec_fw_config.h" -#include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi260.h" -#include "driver/als_tcs3400.h" +#include "common.h" #include "driver/bc12/pi3usb9201.h" #include "driver/ppc/sn5s330.h" #include "driver/ppc/syv682x.h" -#include "driver/retimer/bb_retimer.h" #include "driver/sync.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/rt1715.h" @@ -36,7 +31,6 @@ #include "switch.h" #include "system.h" #include "task.h" -#include "tablet_mode.h" #include "throttle_ap.h" #include "uart.h" #include "usb_mux.h" @@ -46,12 +40,13 @@ #include "usbc_ppc.h" #include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Increase from 50 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* Other values should be the same as the default configuration. */ @@ -68,82 +63,25 @@ struct keyboard_scan_config keyscan_config = { /******************************************************************************/ /* - * FW_CONFIG defaults for Volteer if the CBI data is not initialized. + * FW_CONFIG defaults for Elemi if the CBI data is not initialized. */ union volteer_cbi_fw_config fw_config_defaults = { - .usb_db = DB_USB4_GEN2, + .usb_db = DB_USB3_ACTIVE, }; -static void board_init(void) -{ - /* Illuminate motherboard and daughter board LEDs equally to start. */ - pwm_enable(PWM_CH_LED4_SIDESEL, 1); - pwm_set_duty(PWM_CH_LED4_SIDESEL, 50); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - if (port == USBC_PORT_C1) { - if (usb_db == DB_USB4_GEN2) { - /* - * Older boards violate 205mm trace length prior - * to connection to the re-timer and only support up - * to GEN2 speeds. - */ - return TBT_SS_U32_GEN1_GEN2; - } else if (usb_db == DB_USB4_GEN3) { - return TBT_SS_TBT_GEN3; - } - } - - /* - * Thunderbolt-compatible mode not supported - * - * TODO (b/147726366): All the USB-C ports need to support same speed. - * Need to fix once USB-C feature set is known for Volteer. - */ - return TBT_SS_RES_0; -} - -__override bool board_is_tbt_usb4_port(int port) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - /* - * Volteer reference design only supports TBT & USB4 on port 1 - * if the USB4 DB is present. - * - * TODO (b/147732807): All the USB-C ports need to support same - * features. Need to fix once USB-C feature set is known for Volteer. - */ - return ((port == USBC_PORT_C1) - && ((usb_db == DB_USB4_GEN2) || (usb_db == DB_USB4_GEN3))); -} - -/******************************************************************************/ /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; -/* - * Fan specs from datasheet: - * Max speed 5900 rpm (+/- 7%), minimum duty cycle 30%. - * Minimum speed not specified by RPM. Set minimum RPM to max speed (with - * margin) x 30%. - * 5900 x 1.07 x 0.30 = 1894, round up to 1900 - */ const struct fan_rpm fan_rpm_0 = { - .rpm_min = 1900, - .rpm_start = 1900, - .rpm_max = 5900, + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 6500, }; const struct fan_t fans[FAN_CH_COUNT] = { @@ -161,47 +99,64 @@ const struct fan_t fans[FAN_CH_COUNT] = { * 130 C. However, sensor is located next to DDR, so we need to use the lower * DDR temperature limit (85 C) */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(70), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(58), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; /* - * Inductor limits - used for both charger and PP3300 regulator - * - * Need to use the lower of the charger IC, PP3300 regulator, and the inductors - * - * Charger max recommended temperature 100C, max absolute temperature 125C - * PP3300 regulator: operating range -40 C to 145 C - * - * Inductors: limit of 125c - * PCB: limit is 80c + * TODO(b/202062363): Remove when clang is fixed. */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(78), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_REGULATOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(70), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(58), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_regulator = + THERMAL_REGULATOR; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, + [TEMP_SENSOR_1_CHARGER] = THERMAL_CHARGER, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_REGULATOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -219,13 +174,6 @@ BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /******************************************************************************/ /* I2C port map configuration */ const struct i2c_port_t i2c_ports[] = { - { - .name = "sensor", - .port = I2C_PORT_SENSOR, - .kbps = 400, - .scl = GPIO_EC_I2C0_SENSOR_SCL, - .sda = GPIO_EC_I2C0_SENSOR_SDA, - }, { .name = "usb_c0", .port = I2C_PORT_USB_C0, @@ -267,31 +215,6 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /******************************************************************************/ /* PWM configuration */ const struct pwm_t pwm_channels[] = { - [PWM_CH_LED1_BLUE] = { - .channel = 2, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 4800, - }, - [PWM_CH_LED2_GREEN] = { - .channel = 0, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 4800, - }, - [PWM_CH_LED3_RED] = { - .channel = 1, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 4800, - }, - [PWM_CH_LED4_SIDESEL] = { - .channel = 7, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - /* - * If using the side select to run both LEDs at the same time, - * the frequency should be 1/2 of the color channel PWM - * frequency to drive each LED equally. - */ - .freq = 2400, - }, [PWM_CH_FAN] = { .channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, @@ -311,44 +234,39 @@ const struct pwm_t pwm_channels[] = { }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -/******************************************************************************/ -/* Volteer specific USB daughter-board configuration */ +static void kb_backlight_enable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, kb_backlight_enable, HOOK_PRIO_DEFAULT); -/* USBC TCPC configuration for USB3 daughter board */ -static const struct tcpc_config_t tcpc_config_p1_usb3 = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .flags = TCPC_FLAGS_TCPCI_REV2_0 | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, - .drv = &ps8xxx_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), -}; +static void kb_backlight_disable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kb_backlight_disable, HOOK_PRIO_DEFAULT); + +__override void board_ps8xxx_tcpc_init(int port) +{ + /* b/189587527: Set Displayport EQ loss up to 10dB */ + tcpc_addr_write( + port, PS8XXX_I2C_ADDR1_P1_FLAGS, PS8815_REG_DP_EQ_SETTING, + PS8815_DPEQ_LOSS_UP_10DB << PS8815_REG_DP_EQ_COMP_SHIFT); +} /* * USB3 DB mux configuration - the top level mux still needs to be set to the * virtual_usb_mux_driver so the AP gets notified of mux changes and updates * the TCSS configuration on state changes. */ -static const struct usb_mux usbc1_usb3_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .next_mux = NULL, -}; - -static const struct usb_mux mux_config_p1_usb3_active = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb3_db_retimer, -}; - -static const struct usb_mux mux_config_p1_usb3_passive = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, }; /******************************************************************************/ @@ -358,16 +276,13 @@ const int usb_port_enable[USB_PORT_COUNT] = { GPIO_EN_PP5000_USBA, }; -static enum gpio_signal ps8xxx_rst_odl = GPIO_USB_C1_RT_RST_ODL; - static void ps8815_reset(void) { int val; - gpio_set_level(ps8xxx_rst_odl, 0); - msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, - PS8815_PWR_H_RST_H_DELAY_MS)); - gpio_set_level(ps8xxx_rst_odl, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 0); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 1); msleep(PS8815_FW_INIT_DELAY_MS); /* @@ -377,123 +292,30 @@ static void ps8815_reset(void) CPRINTS("%s: patching ps8815 registers", __func__); - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) CPRINTS("ps8815: reg 0x0f was %02x", val); - if (i2c_write8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, 0x31) == EC_SUCCESS) + if (i2c_write8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) CPRINTS("ps8815: reg 0x0f set to 0x31"); - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) CPRINTS("ps8815: reg 0x0f now %02x", val); } void board_reset_pd_mcu(void) { - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - /* No reset available for TCPC on port 0 */ /* Daughterboard specific reset for port 1 */ - if (usb_db == DB_USB3_ACTIVE) { - ps8815_reset(); - usb_mux_hpd_update(USBC_PORT_C1, 0, 0); - } -} - -/* - * Set up support for the USB3 daughterboard: - * Parade PS8815 TCPC (integrated retimer) - * Diodes PI3USB9201 BC 1.2 chip (same as USB4 board) - * Silergy SYV682A PPC (same as USB4 board) - * Virtual mux with stacked retimer - */ -static void config_db_usb3_active(void) -{ - tcpc_config[USBC_PORT_C1] = tcpc_config_p1_usb3; - usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3_active; -} - -/* - * Set up support for the passive USB3 daughterboard: - * TUSB422 TCPC (already the default) - * PI3USB9201 BC 1.2 chip (already the default) - * Silergy SYV682A PPC (already the default) - * Virtual mux without stacked retimer - */ - -static void config_db_usb3_passive(void) -{ - usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3_passive; -} - -static void config_port_discrete_tcpc(int port) -{ - /* - * Support 2 Pin-to-Pin compatible parts: TUSB422 and RT1715, for - * simplicity allow either and decide at runtime which we are using. - * Default to TUSB422, and switch to RT1715 if it is on the I2C bus and - * the VID matches. - */ - - int regval; - - if (i2c_read16(port ? I2C_PORT_USB_C1 : I2C_PORT_USB_C0, - RT1715_I2C_ADDR_FLAGS, TCPC_REG_VENDOR_ID, - ®val) == EC_SUCCESS) { - if (regval == RT1715_VENDOR_ID) { - CPRINTS("C%d: RT1715 detected", port); - tcpc_config[port].i2c_info.addr_flags = - RT1715_I2C_ADDR_FLAGS; - tcpc_config[port].drv = &rt1715_tcpm_drv; - return; - } - } - CPRINTS("C%d: Default to TUSB422", port); + ps8815_reset(); + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -static const char *db_type_prefix = "USB DB type: "; __override void board_cbi_init(void) { - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - /* Reconfigure Volteer GPIOs based on the board ID */ - if (get_board_id() == 0) { - CPRINTS("Configuring GPIOs for board ID 0"); - CPRINTS("VOLUME_UP button disabled"); - - /* Reassign USB_C1_RT_RST_ODL */ - bb_controls[USBC_PORT_C1].retimer_rst_gpio = - GPIO_USB_C1_RT_RST_ODL_BOARDID_0; - ps8xxx_rst_odl = GPIO_USB_C1_RT_RST_ODL_BOARDID_0; - } - config_port_discrete_tcpc(0); - switch (usb_db) { - case DB_USB_ABSENT: - CPRINTS("%sNone", db_type_prefix); - break; - case DB_USB4_GEN2: - config_port_discrete_tcpc(1); - CPRINTS("%sUSB4 Gen1/2", db_type_prefix); - break; - case DB_USB4_GEN3: - config_port_discrete_tcpc(1); - CPRINTS("%sUSB4 Gen3", db_type_prefix); - break; - case DB_USB3_ACTIVE: - config_db_usb3_active(); - CPRINTS("%sUSB3 Active", db_type_prefix); - break; - case DB_USB3_PASSIVE: - config_db_usb3_passive(); - config_port_discrete_tcpc(1); - CPRINTS("%sUSB3 Passive", db_type_prefix); - break; - default: - CPRINTS("%sID %d not supported", db_type_prefix, usb_db); - } - if ((!IS_ENABLED(TEST_BUILD) && !ec_cfg_has_numeric_pad()) || get_board_id() <= 2) keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); @@ -526,6 +348,7 @@ void ppc_interrupt(enum gpio_signal signal) break; case GPIO_USB_C1_PPC_INT_ODL: syv682x_interrupt(USBC_PORT_C1); + break; default: break; } @@ -547,24 +370,24 @@ BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); /******************************************************************************/ /* USBC TCPC configuration */ -struct tcpc_config_t tcpc_config[] = { +const struct tcpc_config_t tcpc_config[] = { [USBC_PORT_C0] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C0, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, + .addr_flags = RT1715_I2C_ADDR_FLAGS, }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), + .drv = &rt1715_tcpm_drv, }, [USBC_PORT_C1] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C1, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, }, }; BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); @@ -572,38 +395,25 @@ BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); /******************************************************************************/ /* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usb_muxes[] = { +const struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }, [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); -struct bb_usb_control bb_controls[] = { - [USBC_PORT_C0] = { - /* USB-C port 0 doesn't have a retimer */ - }, - [USBC_PORT_C1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); - static void board_tcpc_init(void) { /* Don't reset TCPCs after initial reset */ @@ -648,3 +458,21 @@ int ppc_get_alert_status(int port) else return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; } + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/elemi/board.h b/board/elemi/board.h index 0efc83180c..aa6756d0ce 100644 --- a/board/elemi/board.h +++ b/board/elemi/board.h @@ -1,9 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* Volteer board configuration */ +/* Elemi board configuration */ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H @@ -11,24 +11,13 @@ /* Baseboard features */ #include "baseboard.h" -#ifdef BOARD_VOLTEER_TCPMV1 -/* Disable TCPMv2 configuration options */ -#undef CONFIG_USB_PD_TCPMV2 - -/* Enable the required TCPMv1 options */ -#define CONFIG_USB_PD_TCPMV1 - /* - * Because the TPCMv1 stack has considerably smaller flash footprint, disable - * the CONFIG_CHIP_INIT_ROM_REGION for testing of the init_rom API and the - * BMI260 driver. + * The RAM and flash size combination on the NPCX797FC dose not leave + * any unused flash space that can be used to store the .init_rom section. */ #undef CONFIG_CHIP_INIT_ROM_REGION -#endif /* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ - #define CONFIG_VBOOT_EFS2 #define CONFIG_POWER_BUTTON @@ -39,90 +28,61 @@ /* Chipset features */ #define CONFIG_POWER_PP5000_CONTROL -/* LED defines */ -#define CONFIG_LED_PWM -/* Although there are 2 LEDs, they are both controlled by the same lines. */ -#define CONFIG_LED_PWM_COUNT 1 - /* Keyboard features */ /* Sensors */ -/* BMA253 accelerometer in base */ -#define CONFIG_ACCEL_BMA255 - -/* BMI260 accel/gyro in base */ -#define CONFIG_ACCELGYRO_BMI260 -#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) - -/* TCS3400 ALS */ -#define CONFIG_ALS -#define ALS_COUNT 1 -#define CONFIG_ALS_TCS3400 -#define CONFIG_ALS_TCS3400_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) - -/* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) - -#define CONFIG_LID_ANGLE -#define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#undef CONFIG_TABLET_MODE +#undef CONFIG_GMR_TABLET_MODE +#undef CONFIG_ACCEL_FIFO +#undef CONFIG_ACCEL_FIFO_SIZE /* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 /* TODO: b/144165680 - measure and check these values on Volteer */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +/* Experimentally determined. See b/186079130. */ +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +#define CONFIG_USBC_VCONN_SWAP_DELAY_US 10000 /* us */ /* * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C * cables only support up to 60W. */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 - -/* Enabling Thunderbolt-compatible mode */ -#define CONFIG_USB_PD_TBT_COMPAT_MODE - -/* Enabling USB4 mode */ -#define CONFIG_USB_PD_USB4 -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* USB Type A Features */ -#define USB_PORT_COUNT 1 +#define USB_PORT_COUNT 1 #define CONFIG_USB_PORT_POWER_DUMB /* USBC PPC*/ -#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ +#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ +#undef CONFIG_USB_PD_TCPC_RUNTIME_CONFIG +#undef CONFIG_USB_PD_TCPM_TUSB422 +#undef CONFIG_USB_MUX_RUNTIME_CONFIG /* BC 1.2 */ /* Volume Button feature */ +#undef CONFIG_VOLUME_BUTTONS /* Fan features */ /* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +/* Retimer */ +#undef CONFIG_USBC_RETIMER_INTEL_BB +#undef CONFIG_USBC_RETIMER_INTEL_BB_RUNTIME_CONFIG + +/* Keyboard feature */ +#define CONFIG_KEYBOARD_FACTORY_TEST /* * Macros for GPIO signals used in common code that don't match the @@ -130,46 +90,39 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL /* I2C Bus Configuration */ #define CONFIG_I2C -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER #ifndef __ASSEMBLER__ @@ -177,34 +130,14 @@ #include "registers.h" enum battery_type { - BATTERY_LGC011, + BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COSMX, BATTERY_TYPE_COUNT, }; -enum pwm_channel { - PWM_CH_LED1_BLUE = 0, - PWM_CH_LED2_GREEN, - PWM_CH_LED3_RED, - PWM_CH_LED4_SIDESEL, - PWM_CH_FAN, - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; - -enum sensor_id { - LID_ACCEL = 0, - BASE_ACCEL, - BASE_GYRO, - CLEAR_ALS, - RGB_ALS, - SENSOR_COUNT, -}; +enum pwm_channel { PWM_CH_FAN, PWM_CH_KBLIGHT, PWM_CH_COUNT }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; void board_reset_pd_mcu(void); diff --git a/board/elemi/build.mk b/board/elemi/build.mk index b78172d3cf..d590255d2a 100644 --- a/board/elemi/build.mk +++ b/board/elemi/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,10 +8,9 @@ CHIP:=npcx CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc +CHIP_VARIANT:=npcx7m7fc BASEBOARD:=volteer board-y=board.o board-y+=battery.o board-y+=led.o -board-y+=sensors.o diff --git a/board/elemi/ec.tasklist b/board/elemi/ec.tasklist index 292de51cdb..a1b5d30d93 100644 --- a/board/elemi/ec.tasklist +++ b/board/elemi/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,9 +13,9 @@ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/elemi/gpio.inc b/board/elemi/gpio.inc index d0055671ca..3dbf9b35c7 100644 --- a/board/elemi/gpio.inc +++ b/board/elemi/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -24,16 +24,6 @@ GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PG_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) -/* Sensor Interrupts */ -GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi260_interrupt) -GPIO_INT(EC_ALS_RGB_INT_L, PIN(D, 4), GPIO_INT_FALLING, tcs3400_interrupt) -GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) -/* - * Lid g-sensor interrupt unused on Volteer, configure as regular input for - * power saving. - */ -GPIO(EC_ACCEL_INT, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) - /* USB-C interrupts */ GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) @@ -46,10 +36,6 @@ GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) /* HDMI interrupts */ -/* Volume button interrupts */ -GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) - /* Power Sequencing Signals */ GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) @@ -84,15 +70,7 @@ GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) /* USB and USBC Signals */ GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ - -/* - * USB_C1 moved from GPIO32 to GPIO83 on boards with board ID >=1. - * GPIO83/EN_PP1800_A is DNS on board ID 0 and GPIO32 is N/C on board ID >=1 - * so it's safe to define GPIOs compatible with both designs. - * TODO (b/149858568): remove board ID=0 support. - */ -GPIO(USB_C1_RT_RST_ODL_BOARDID_0, PIN(3, 2), GPIO_ODR_LOW) /* USB_C1 Reset on boards without board ID */ -GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset on boards board ID >=1 */ +GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset */ GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) /* There is currently no need to service this interrupt. */ @@ -103,6 +81,7 @@ UNIMPLEMENTED(USB_C1_LS_EN) /* Misc Signals */ GPIO(EC_H1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) /* H1 Packet Mode */ +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) /* Keyboard backlight enable */ /* * Despite their names, M2_SSD_PLN and M2_SSD_PLA are active-low, and M2_SSD_PLN * is open-drain. @@ -112,12 +91,24 @@ GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_ODR_HIGH) /* SSD power-loss notification */ GPIO(M2_SSD_PLA, PIN(7, 0), GPIO_INPUT) /* SSD power-loss acknowledgment */ GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ GPIO(EC_SLP_S0IX, PIN(7, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(C0_CHARGE_LED_AMBER_L, PIN(C, 3), GPIO_OUT_HIGH) /* Amber C0 port */ +GPIO(C0_CHARGE_LED_WHITE_L, PIN(C, 4), GPIO_OUT_HIGH) /* White C0 port */ +GPIO(C1_CHARGE_LED_AMBER_L, PIN(6, 0), GPIO_OUT_HIGH) /* Amber C1 port */ +GPIO(C1_CHARGE_LED_WHITE_L, PIN(C, 2), GPIO_OUT_HIGH) /* White C1 port */ /* Unused signals */ GPIO(UNUSED_GPIO41, PIN(4, 1), GPIO_INPUT | GPIO_PULL_UP) GPIO(UNUSED_GPIOF2, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) GPIO(UNUSED_GPIO96, PIN(9, 6), GPIO_INPUT | GPIO_PULL_UP) GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO56, PIN(5, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOD4, PIN(D, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO95, PIN(9, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO81, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO93, PIN(9, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO97, PIN(9, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOB5, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) /* Unused I2C port, Set input only */ +GPIO(UNUSED_GPIOB4, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) /* Unused I2C port, Set input only */ /* * eDP backlight - both PCH and EC have enable pins that must be high @@ -127,8 +118,6 @@ GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) /* I2C pins - Alternate function below configures I2C module on these pins */ -GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) -GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) @@ -144,19 +133,12 @@ GPIO(EC_I2C7_EEPROM_PWR_SDA_R, PIN(B, 2), GPIO_INPUT) GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) /* Alternate functions GPIO definitions */ -ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */ ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ -/* This selects between an LED module on the motherboard and one on the daughter - * board, to be controlled by LED_{1,2,3}_L. PWM allows driving both modules at - * the same time. */ -ALTERNATE(PIN_MASK(6, BIT(0)), 0, MODULE_PWM, 0) /* LED_SIDESEL_4_L */ -ALTERNATE(PIN_MASK(C, BIT(2) | BIT(3) | BIT(4)), 0, MODULE_PWM, 0) /* LED_{3,2,1}_L */ - /* Fan signals */ GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) ALTERNATE(PIN_MASK(B, BIT(7)), 0, MODULE_PWM, 0) /* FAN_PWM */ @@ -182,3 +164,6 @@ ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = GPIO01 = H1_EC_PWR_BTN_ODL GPIO02 = EC_RST_ODL */ +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ diff --git a/board/elemi/led.c b/board/elemi/led.c index 4486bcb912..f8ac543350 100644 --- a/board/elemi/led.c +++ b/board/elemi/led.c @@ -1,104 +1,203 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * - * Power and battery LED control for Volteer + * Power and battery LED control for Elemi */ +#include "battery.h" #include "charge_manager.h" -#include "common.h" +#include "charge_state.h" +#include "chipset.h" #include "ec_commands.h" +#include "gpio.h" #include "hooks.h" +#include "host_command.h" #include "led_common.h" -#include "led_pwm.h" -#include "pwm.h" + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +#define LED_CYCLE_TIME_MS (2 * 1000) +#define LED_TICKS_PER_CYCLE (LED_CYCLE_TIME_MS / HOOK_TICK_INTERVAL_MS) +#define LED_ON_TIME_MS (1 * 1000) +#define LED_ON_TICKS (LED_ON_TIME_MS / HOOK_TICK_INTERVAL_MS) const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, + EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, }; + const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -struct pwm_led led_color_map[] = { - /* Red, Green, Blue */ - [EC_LED_COLOR_RED] = { 100, 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, - /* The green LED seems to be brighter than the others, so turn down - * green from its natural level for these secondary colors. - */ - [EC_LED_COLOR_YELLOW] = { 100, 70, 0 }, - [EC_LED_COLOR_WHITE] = { 100, 70, 100 }, - [EC_LED_COLOR_AMBER] = { 100, 20, 0 }, +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; -struct pwm_led pwm_leds[] = { - /* 2 RGB diffusers controlled by 1 set of 3 channels. */ - [PWM_LED0] = { - .ch0 = PWM_CH_LED3_RED, - .ch1 = PWM_CH_LED2_GREEN, - .ch2 = PWM_CH_LED1_BLUE, - .enable = &pwm_enable, - .set_duty = &pwm_set_duty, - }, -}; +enum led_port { RIGHT_PORT = 0, LEFT_PORT }; + +static void led_set_color_battery(int port, enum led_color color) +{ + enum gpio_signal amber_led, white_led; + + amber_led = (port == RIGHT_PORT ? GPIO_C0_CHARGE_LED_AMBER_L : + GPIO_C1_CHARGE_LED_AMBER_L); + white_led = (port == RIGHT_PORT ? GPIO_C0_CHARGE_LED_WHITE_L : + GPIO_C1_CHARGE_LED_WHITE_L); + + switch (color) { + case LED_WHITE: + gpio_set_level(white_led, BAT_LED_ON); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_ON); + break; + case LED_OFF: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + default: + break; + } +} void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) { - brightness_range[EC_LED_COLOR_RED] = 255; - brightness_range[EC_LED_COLOR_GREEN] = 255; - brightness_range[EC_LED_COLOR_BLUE] = 255; + switch (led_id) { + case EC_LED_ID_LEFT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_RIGHT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + default: + break; + } } int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { - enum pwm_led_id pwm_id; - - /* Convert ec_led_id to pwm_led_id. */ - if (led_id == EC_LED_ID_POWER_LED) - pwm_id = PWM_LED0; - else - return EC_ERROR_UNKNOWN; - - if (brightness[EC_LED_COLOR_RED]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_RED); - else if (brightness[EC_LED_COLOR_GREEN]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN); - else if (brightness[EC_LED_COLOR_BLUE]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE); - else if (brightness[EC_LED_COLOR_YELLOW]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_YELLOW); - else if (brightness[EC_LED_COLOR_WHITE]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE); - else if (brightness[EC_LED_COLOR_AMBER]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); - else - /* Otherwise, the "color" is "off". */ - set_pwm_led_color(pwm_id, -1); + switch (led_id) { + case EC_LED_ID_LEFT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LEFT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LEFT_PORT, LED_AMBER); + else + led_set_color_battery(LEFT_PORT, LED_OFF); + break; + case EC_LED_ID_RIGHT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(RIGHT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(RIGHT_PORT, LED_AMBER); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + break; + default: + return EC_ERROR_PARAM1; + } return EC_SUCCESS; } -/* Illuminates the LED on the side of the active charging port. If not charging, - * illuminates both LEDs. +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. */ -static void led_set_charge_port_tick(void) +static void set_active_port_color(enum led_color color) { - int port; - int side_select_duty; + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + led_set_color_battery(RIGHT_PORT, + (port == RIGHT_PORT) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, + (port == LEFT_PORT) ? color : LED_OFF); +} + +static void led_set_battery(void) +{ + static int battery_ticks; + static int suspend_ticks; + + battery_ticks++; + + /* + * Override battery LEDs for Elemi, Elemi doesn't have power LED, + * blinking both two side battery white LEDs to indicate + * system suspend without charging state. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + suspend_ticks++; - port = charge_manager_get_active_charge_port(); - switch (port) { - case 0: - side_select_duty = 100; + led_set_color_battery( + RIGHT_PORT, suspend_ticks & 0x4 ? LED_WHITE : LED_OFF); + led_set_color_battery( + LEFT_PORT, suspend_ticks & 0x4 ? LED_WHITE : LED_OFF); + return; + } + + suspend_ticks = 0; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + if (charge_get_percent() < 10) + led_set_color_battery( + RIGHT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, LED_OFF); + break; + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); break; - case 1: - side_select_duty = 0; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); break; default: - side_select_duty = 50; + /* Other states don't alter LED behavior */ + break; } +} - if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) - pwm_set_duty(PWM_CH_LED4_SIDESEL, side_select_duty); +/* Called by hook task every TICK */ +static void led_tick(void) +{ + led_set_battery(); } -DECLARE_HOOK(HOOK_TICK, led_set_charge_port_tick, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/elemi/sensors.c b/board/elemi/sensors.c deleted file mode 100644 index 9e34812131..0000000000 --- a/board/elemi/sensors.c +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer family-specific sensor configuration */ -#include "common.h" -#include "accelgyro.h" -#include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi_common.h" -#include "driver/accelgyro_bmi260.h" -#include "driver/als_tcs3400.h" -#include "driver/sync.h" -#include "keyboard_scan.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "tablet_mode.h" -#include "util.h" - -/******************************************************************************/ -/* Sensors */ -static struct mutex g_lid_accel_mutex; -static struct mutex g_base_mutex; - -/* BMA253 private data */ -static struct accelgyro_saved_data_t g_bma253_data; - -/* BMI260 private data */ -static struct bmi_drv_data_t g_bmi260_data; - -/* TCS3400 private data */ -static struct als_drv_data_t g_tcs3400_data = { - .als_cal.scale = 1, - .als_cal.uscale = 0, - .als_cal.offset = 0, - .als_cal.channel_scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ - .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */ - }, -}; - -/* - * TODO: b/146166425 need to calibrate ALS/RGB sensor. At default settings, - * shining phone flashlight on sensor pegs all readings at 0xFFFF. - */ -static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { - .calibration.rgb_cal[X] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - } - }, - .calibration.rgb_cal[Y] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - }, - }, - .calibration.rgb_cal[Z] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - } - }, - .calibration.irt = INT_TO_FP(1), - .saturation.again = TCS_DEFAULT_AGAIN, - .saturation.atime = TCS_DEFAULT_ATIME, -}; - -/* Rotation matrix for the lid accelerometer */ -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; - -struct motion_sensor_t motion_sensors[] = { - [LID_ACCEL] = { - .name = "Lid Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMA255, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &bma2x2_accel_drv, - .mutex = &g_lid_accel_mutex, - .drv_data = &g_bma253_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .min_frequency = BMA255_ACCEL_MIN_FREQ, - .max_frequency = BMA255_ACCEL_MAX_FREQ, - .default_range = 2, /* g, to support tablet mode */ - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - /* Sensor on in S3 */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - }, - }, - [BASE_ACCEL] = { - .name = "Base Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMI260, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_BASE, - .drv = &bmi260_drv, - .mutex = &g_base_mutex, - .drv_data = &g_bmi260_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, - .rot_standard_ref = &base_standard_ref, - .min_frequency = BMI_ACCEL_MIN_FREQ, - .max_frequency = BMI_ACCEL_MAX_FREQ, - .default_range = 4, /* g */ - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - /* Sensor on in S3 */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, - }, - - [BASE_GYRO] = { - .name = "Base Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMI260, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_BASE, - .drv = &bmi260_drv, - .mutex = &g_base_mutex, - .drv_data = &g_bmi260_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, - .default_range = 1000, /* dps */ - .rot_standard_ref = &base_standard_ref, - .min_frequency = BMI_GYRO_MIN_FREQ, - .max_frequency = BMI_GYRO_MAX_FREQ, - }, - [CLEAR_ALS] = { - .name = "Clear Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT, - .location = MOTIONSENSE_LOC_BASE, - .drv = &tcs3400_drv, - .drv_data = &g_tcs3400_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - .min_frequency = TCS3400_LIGHT_MIN_FREQ, - .max_frequency = TCS3400_LIGHT_MAX_FREQ, - .config = { - /* Run ALS sensor in S0 */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 1000, - }, - }, - }, - - [RGB_ALS] = { - /* - * RGB channels read by CLEAR_ALS and so the i2c port and - * address do not need to be defined for RGB_ALS. - */ - .name = "RGB Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT_RGB, - .location = MOTIONSENSE_LOC_BASE, - .drv = &tcs3400_rgb_drv, - .drv_data = &g_tcs3400_rgb_data, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - }, -}; -unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ -const struct motion_sensor_t *motion_als_sensors[] = { - &motion_sensors[CLEAR_ALS], -}; -BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); - -static void baseboard_sensors_init(void) -{ - /* Note - BMA253 interrupt unused by EC */ - - /* Enable interrupt for the TCS3400 color light sensor */ - gpio_enable_interrupt(GPIO_EC_ALS_RGB_INT_L); - /* Enable interrupt for the BMI260 accel/gyro sensor */ - gpio_enable_interrupt(GPIO_EC_IMU_INT_L); -} -DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); - -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); - - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif diff --git a/board/elemi/vif_override.xml b/board/elemi/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/elemi/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/elm/battery.c b/board/elm/battery.c index de9685a89d..9ef59414a2 100644 --- a/board/elm/battery.c +++ b/board/elm/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,8 +10,8 @@ #include "util.h" /* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHIP_MODE_REG 0x3a -#define SB_SHUTDOWN_DATA 0xC574 +#define SB_SHIP_MODE_REG 0x3a +#define SB_SHUTDOWN_DATA 0xC574 static const struct battery_info info = { .voltage_max = 13200, diff --git a/board/elm/board.c b/board/elm/board.c index a893a57416..15362ee635 100644 --- a/board/elm/board.c +++ b/board/elm/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Oak board configuration */ #include "adc.h" -#include "adc_chip.h" #include "atomic.h" #include "battery.h" #include "charge_manager.h" @@ -50,8 +49,8 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* Dispaly port hardware can connect to port 0, 1 or neither. */ #define PD_PORT_NONE -1 @@ -67,15 +66,16 @@ DECLARE_DEFERRED(deferred_reset_pd_mcu); void usb_evt(enum gpio_signal signal) { if (!gpio_get_level(GPIO_BC12_WAKE_L)) - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_SOC_POWER_GOOD, POWER_SIGNAL_ACTIVE_HIGH, "POWER_GOOD"}, - {GPIO_SUSPEND_L, POWER_SIGNAL_ACTIVE_LOW, "SUSPEND#_ASSERTED"}, + { GPIO_SOC_POWER_GOOD, POWER_SIGNAL_ACTIVE_HIGH, "POWER_GOOD" }, + { GPIO_SUSPEND_L, POWER_SIGNAL_ACTIVE_LOW, "SUSPEND#_ASSERTED" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); @@ -85,18 +85,18 @@ const struct adc_t adc_channels[] = { * PSYS_MONITOR(PA2): ADC_IN2, 1.44 uA/W on 6.05k Ohm * output in mW */ - [ADC_PSYS] = {"PSYS", 379415, 4096, 0, STM32_AIN(2)}, + [ADC_PSYS] = { "PSYS", 379415, 4096, 0, STM32_AIN(2) }, /* AMON_BMON(PC0): ADC_IN10, output in uV */ - [ADC_AMON_BMON] = {"AMON_BMON", 183333, 4096, 0, STM32_AIN(10)}, + [ADC_AMON_BMON] = { "AMON_BMON", 183333, 4096, 0, STM32_AIN(10) }, /* VDC_BOOSTIN_SENSE(PC1): ADC_IN11, output in mV */ - [ADC_VBUS] = {"VBUS", 33000, 4096, 0, STM32_AIN(11)}, + [ADC_VBUS] = { "VBUS", 33000, 4096, 0, STM32_AIN(11) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); int anx7688_passthru_allowed(const struct i2c_port_t *port, const uint16_t addr_flags) { - uint16_t addr = I2C_GET_ADDR(addr_flags); + uint16_t addr = I2C_STRIP_FLAGS(addr_flags); /* Allow access to 0x2c (TCPC) */ if (addr == 0x2c) @@ -108,11 +108,18 @@ int anx7688_passthru_allowed(const struct i2c_port_t *port, } /* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"battery", I2C_PORT_BATTERY, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"pd", I2C_PORT_PD_MCU, 1000, GPIO_I2C1_SCL, GPIO_I2C1_SDA, - anx7688_passthru_allowed} -}; +const struct i2c_port_t i2c_ports[] = { { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "pd", + .port = I2C_PORT_PD_MCU, + .kbps = 1000, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA, + .passthru_allowed = + anx7688_passthru_allowed } }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -151,22 +158,24 @@ BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) == */ const struct temp_sensor_t temp_sensors[] = { #ifdef CONFIG_TEMP_SENSOR_TMP432 - {"TMP432_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_LOCAL}, - {"TMP432_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE1}, - {"TMP432_Sensor_2", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE2}, + { "TMP432_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_LOCAL }, + { "TMP432_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE1 }, + { "TMP432_Sensor_2", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE2 }, #endif - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, - 0}, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &anx7688_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &anx7688_usb_mux_driver, + }, }, }; @@ -196,7 +205,7 @@ void deferred_reset_pd_mcu(void) * and wait for 1ms. */ gpio_set_level(GPIO_USB_C0_PWR_EN_L, 1); - hook_call_deferred(&deferred_reset_pd_mcu_data, 1*MSEC); + hook_call_deferred(&deferred_reset_pd_mcu_data, 1 * MSEC); break; case 1: /* @@ -204,9 +213,9 @@ void deferred_reset_pd_mcu(void) * pull PD reset pin and wait for another 1ms */ gpio_set_level(GPIO_USB_C0_RST, 1); - hook_call_deferred(&deferred_reset_pd_mcu_data, 1*MSEC); + hook_call_deferred(&deferred_reset_pd_mcu_data, 1 * MSEC); /* on PD reset, trigger PD task to reset state */ - task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); + task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET); break; case 3: /* @@ -214,7 +223,7 @@ void deferred_reset_pd_mcu(void) * enable power and wait for 10ms then pull RESET_N */ gpio_set_level(GPIO_USB_C0_PWR_EN_L, 0); - hook_call_deferred(&deferred_reset_pd_mcu_data, 10*MSEC); + hook_call_deferred(&deferred_reset_pd_mcu_data, 10 * MSEC); break; case 2: /* @@ -233,7 +242,7 @@ static void board_power_on_pd_mcu(void) return; gpio_set_level(GPIO_USB_C0_EXTPWR_EN, 1); - hook_call_deferred(&deferred_reset_pd_mcu_data, 1*MSEC); + hook_call_deferred(&deferred_reset_pd_mcu_data, 1 * MSEC); } void board_reset_pd_mcu(void) @@ -242,17 +251,15 @@ void board_reset_pd_mcu(void) anx7688_enable_cable_detection(0); /* wait for 10ms, then start port controller's reset sequence */ - hook_call_deferred(&deferred_reset_pd_mcu_data, 10*MSEC); + hook_call_deferred(&deferred_reset_pd_mcu_data, 10 * MSEC); } -int command_pd_reset(int argc, char **argv) +static int command_pd_reset(int argc, const char **argv) { board_reset_pd_mcu(); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(resetpd, command_pd_reset, - "", - "Reset PD IC"); +DECLARE_CONSOLE_COMMAND(resetpd, command_pd_reset, "", "Reset PD IC"); /** * There is a level shift for AC_OK & LID_OPEN signal between AP & EC, @@ -331,13 +338,10 @@ int board_set_active_charge_port(int charge_port) * @param charge_ma Desired charge limit (mA). * @param charge_mv Negotiated charge voltage (mV). */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { - /* Limit input current 95% ratio on elm board for safety */ - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -388,7 +392,7 @@ static void board_chipset_pre_init(void) board_extpower_buffer_to_soc(); /* Enable SPI for KX022 */ - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); /* Set all four SPI pins to high speed */ /* pins D0/D1/D3/D4 */ @@ -403,7 +407,7 @@ static void board_chipset_pre_init(void) STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); } DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, board_chipset_pre_init, HOOK_PRIO_DEFAULT); @@ -413,12 +417,12 @@ static void board_chipset_shutdown(void) /* Disable level shift to SoC when shutting down */ gpio_set_level(GPIO_LEVEL_SHIFT_EN_L, 1); - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); /* Disable clocks to SPI2 module */ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; - gpio_config_module(MODULE_SPI_MASTER, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); /* * Calling gpio_config_module sets disabled alternate function pins to @@ -448,23 +452,18 @@ static void board_chipset_suspend(void) } DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); -#ifdef HAS_TASK_MOTIONSENSE /* Motion sensors */ /* Mutexes */ static struct mutex g_kx022_mutex[2]; /* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* KX022 private data */ struct kionix_accel_data g_kx022_data[2]; @@ -479,7 +478,7 @@ struct motion_sensor_t motion_sensors[] = { .drv = &kionix_accel_drv, .mutex = &g_kx022_mutex[0], .drv_data = &g_kx022_data[0], - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(0), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(0), .rot_standard_ref = &base_standard_ref, .default_range = 2, /* g, enough for lid angle calculation. */ .min_frequency = KX022_ACCEL_MIN_FREQ, @@ -502,7 +501,7 @@ struct motion_sensor_t motion_sensors[] = { .drv = &kionix_accel_drv, .mutex = &g_kx022_mutex[1], .drv_data = &g_kx022_data[1], - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(1), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(1), .rot_standard_ref = &lid_standard_ref, .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = KX022_ACCEL_MIN_FREQ, @@ -519,17 +518,15 @@ struct motion_sensor_t motion_sensors[] = { const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); /* enable/disable touchpad */ gpio_set_level(GPIO_EN_TP_INT_L, !enable); } -#endif /* defined(HAS_TASK_MOTIONSENSE) */ uint16_t tcpc_get_alert_status(void) { return gpio_get_level(GPIO_PD_MCU_INT) ? PD_STATUS_TCPC_ALERT_0 : 0; } - diff --git a/board/elm/board.h b/board/elm/board.h index a248f6b757..42c8e06c35 100644 --- a/board/elm/board.h +++ b/board/elm/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,17 +14,20 @@ */ #define CONFIG_SYSTEM_UNLOCKED +/* Free up flash space */ +#undef CONFIG_USB_PD_TCPMV1_DEBUG +#define CONFIG_LTO + /* Accelero meter and gyro sensor */ #define CONFIG_ACCEL_KX022 -#define CONFIG_CMD_ACCELS -#define CONFIG_CMD_ACCEL_INFO +#undef CONfFIG_CMD_ACCELSPOOF #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL #define CONFIG_LID_ANGLE_UPDATE #define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG +#undef CONFIG_ADC_WATCHDOG /* AC adaptor, charger, battery */ #define CONFIG_BATTERY_CUT_OFF @@ -34,13 +37,16 @@ #define CONFIG_BATTERY_SMART #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #define CONFIG_CHARGE_RAMP_HW #define CONFIG_CHARGER_ISL9237 #define CONFIG_CHARGER_MAX_INPUT_CURRENT 3000 #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 #define CONFIG_CHARGER_DISCHARGE_ON_AC +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHIPSET_MT817X #define CONFIG_CMD_TYPEC #define CONFIG_EXTPOWER_GPIO @@ -57,7 +63,7 @@ /* Other configs */ #define CONFIG_HOST_COMMAND_STATUS #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_LED_COMMON @@ -69,13 +75,12 @@ #define CONFIG_POWER_COMMON #define CONFIG_USB_CHARGER #define CONFIG_SPI -#define CONFIG_SPI_MASTER -#define CONFIG_STM_HWTIMER32 +#define CONFIG_SPI_CONTROLLER #define CONFIG_VBOOT_HASH -#undef CONFIG_WATCHDOG_HELP +#undef CONFIG_WATCHDOG_HELP #define CONFIG_SWITCH #define CONFIG_BOARD_VERSION_GPIO -#undef CONFIG_UART_CONSOLE +#undef CONFIG_UART_CONSOLE #define CONFIG_UART_CONSOLE 1 #define CONFIG_TEMP_SENSOR #define CONFIG_DPTF @@ -99,7 +104,7 @@ #define CONFIG_USB_PD_TCPM_TCPCI #define CONFIG_USB_PD_TRY_SRC #define CONFIG_USB_PD_VBUS_DETECT_TCPC -#undef CONFIG_TCPC_I2C_BASE_ADDR_FLAGS +#undef CONFIG_TCPC_I2C_BASE_ADDR_FLAGS #define CONFIG_TCPC_I2C_BASE_ADDR_FLAGS 0x2C #define CONFIG_USB_PD_ANX7688 @@ -120,6 +125,8 @@ #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF #define CONFIG_CMD_I2C_PROTECT #define CONFIG_HOSTCMD_PD_CONTROL +/* Disable verbose output in EC pd */ +#define CONFIG_CMD_PD_SRCCAPS_REDUCED_SIZE /* * Flash layout: @@ -139,11 +146,11 @@ #undef CONFIG_EC_WRITABLE_STORAGE_OFF #undef CONFIG_EC_WRITABLE_STORAGE_SIZE #undef CONFIG_WP_STORAGE_SIZE -#define CONFIG_RW_MEM_OFF (128 * 1024) -#define CONFIG_RW_SIZE (128 * 1024) -#define CONFIG_EC_WRITABLE_STORAGE_OFF (128 * 1024) -#define CONFIG_EC_WRITABLE_STORAGE_SIZE (128 * 1024) -#define CONFIG_WP_STORAGE_SIZE (128 * 1024) +#define CONFIG_RW_MEM_OFF (128 * 1024) +#define CONFIG_RW_SIZE (128 * 1024) +#define CONFIG_EC_WRITABLE_STORAGE_OFF (128 * 1024) +#define CONFIG_EC_WRITABLE_STORAGE_SIZE (128 * 1024) +#define CONFIG_WP_STORAGE_SIZE (128 * 1024) /* Drivers */ #ifndef __ASSEMBLER__ @@ -155,30 +162,30 @@ #define KB_OUT_PORT_LIST GPIO_A, GPIO_B, GPIO_C, GPIO_D /* 2 I2C master ports, connect to battery, charger, pd and USB switches */ -#define I2C_PORT_MASTER 0 -#define I2C_PORT_ACCEL 0 +#define I2C_PORT_MASTER 0 +#define I2C_PORT_ACCEL 0 #define I2C_PORT_BATTERY 0 #define I2C_PORT_CHARGER 0 #define I2C_PORT_PERICOM 0 #define I2C_PORT_THERMAL 0 -#define I2C_PORT_PD_MCU 1 +#define I2C_PORT_PD_MCU 1 #define I2C_PORT_USB_MUX 1 -#define I2C_PORT_TCPC 1 +#define I2C_PORT_TCPC 1 /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* First SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* First SPI controller port (SPI2) */ /* Timer selection */ #define TIM_CLOCK32 2 #define TIM_WATCHDOG 4 /* Define the host events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_FASTBOOT)) +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_FASTBOOT)) #include "gpio_signal.h" @@ -196,9 +203,9 @@ enum pwm_channel { }; enum adc_channel { - ADC_PSYS = 0, /* PC1: STM32_AIN(2) */ + ADC_PSYS = 0, /* PC1: STM32_AIN(2) */ ADC_AMON_BMON, /* PC0: STM32_AIN(10) */ - ADC_VBUS, /* PA2: STM32_AIN(11) */ + ADC_VBUS, /* PA2: STM32_AIN(11) */ ADC_CH_COUNT }; @@ -226,17 +233,16 @@ enum sensor_id { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA CONFIG_CHARGER_MAX_INPUT_CURRENT -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA CONFIG_CHARGER_MAX_INPUT_CURRENT +#define PD_MAX_VOLTAGE_MV 20000 /* The lower the input voltage, the higher the power efficiency. */ #define PD_PREFER_LOW_VOLTAGE @@ -246,6 +252,6 @@ void board_reset_pd_mcu(void); /* Set AP reset pin according to parameter */ void board_set_ap_reset(int asserted); -#endif /* !__ASSEMBLER__ */ +#endif /* !__ASSEMBLER__ */ -#endif /* __CROS_EC_BOARD_H */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/elm/build.mk b/board/elm/build.mk index 172a88e843..4d6ba76cae 100644 --- a/board/elm/build.mk +++ b/board/elm/build.mk @@ -1,5 +1,5 @@ #-*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/elm/ec.tasklist b/board/elm/ec.tasklist index 3ea68bf9f8..be745f7487 100644 --- a/board/elm/ec.tasklist +++ b/board/elm/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/elm/gpio.inc b/board/elm/gpio.inc index 246c97edcd..ef77ad732e 100644 --- a/board/elm/gpio.inc +++ b/board/elm/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -110,4 +110,4 @@ ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, GPIO_PULL_UP) /* USART1: PA9/PA10 ALTERNATE(PIN_MASK(B, 0x00c0), 1, MODULE_I2C, 0) /* I2C MASTER:PB6/7 */ ALTERNATE(PIN_MASK(B, 0x6000), 5, MODULE_I2C, 0) /* I2C MASTER:PB13/14 */ ALTERNATE(PIN_MASK(A, 0x00f0), 0, MODULE_SPI, 0) /* SPI SLAVE:PA4/5/6/7 */ -ALTERNATE(PIN_MASK(D, 0x001A), 1, MODULE_SPI_MASTER, 0) /* SPI MASTER:PD1/3/4 */ +ALTERNATE(PIN_MASK(D, 0x001A), 1, MODULE_SPI_CONTROLLER, 0) /* SPI MASTER:PD1/3/4 */ diff --git a/board/elm/led.c b/board/elm/led.c index d73cc05c1b..f420419456 100644 --- a/board/elm/led.c +++ b/board/elm/led.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -12,17 +12,15 @@ #include "hooks.h" #include "host_command.h" #include "led_common.h" -#include "util.h" #include "system.h" +#include "util.h" #define CRITICAL_LOW_BATTERY_PERMILLAGE 71 #define LOW_BATTERY_PERMILLAGE 137 #define FULL_BATTERY_PERMILLAGE 937 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -31,7 +29,7 @@ enum led_color { BAT_LED_ORANGE, PWR_LED_BLUE, PWR_LED_ORANGE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int bat_led_set(enum led_color color, int on) @@ -93,7 +91,7 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) } } -static unsigned blink_second; +static unsigned int blink_second; static void elm_led_set_power(void) { @@ -111,8 +109,7 @@ static void elm_led_set_power(void) bat_led_set(PWR_LED_ORANGE, 0); } else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) { bat_led_set(PWR_LED_BLUE, 0); - bat_led_set(PWR_LED_ORANGE, - (blink_second & 3) ? 0 : 1); + bat_led_set(PWR_LED_ORANGE, (blink_second & 3) ? 0 : 1); } } @@ -135,11 +132,12 @@ static void elm_led_set_battery(void) /* Make the percentage approximate to UI shown */ remaining_capacity = *(int *)host_get_memmap(EC_MEMMAP_BATT_CAP); full_charge_capacity = *(int *)host_get_memmap(EC_MEMMAP_BATT_LFCC); - permillage = !full_charge_capacity ? 0 : - (1000 * remaining_capacity) / full_charge_capacity; + permillage = !full_charge_capacity ? + 0 : + (1000 * remaining_capacity) / full_charge_capacity; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: if (permillage < FULL_BATTERY_PERMILLAGE) { bat_led_set(BAT_LED_BLUE, 0); bat_led_set(BAT_LED_ORANGE, 1); @@ -148,28 +146,26 @@ static void elm_led_set_battery(void) bat_led_set(BAT_LED_ORANGE, 0); } break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: bat_led_set(BAT_LED_BLUE, 1); bat_led_set(BAT_LED_ORANGE, 0); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: bat_led_set(BAT_LED_BLUE, 0); if (!chipset_in_state(CHIPSET_STATE_ANY_OFF) && permillage <= CRITICAL_LOW_BATTERY_PERMILLAGE) - bat_led_set(BAT_LED_ORANGE, - (blink_second & 1) ? 0 : 1); + bat_led_set(BAT_LED_ORANGE, (blink_second & 1) ? 0 : 1); else if (!chipset_in_state(CHIPSET_STATE_ANY_OFF) && permillage <= LOW_BATTERY_PERMILLAGE) - bat_led_set(BAT_LED_ORANGE, - (blink_second & 3) ? 0 : 1); + bat_led_set(BAT_LED_ORANGE, (blink_second & 3) ? 0 : 1); else bat_led_set(BAT_LED_ORANGE, 0); break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: bat_led_set(BAT_LED_BLUE, 0); bat_led_set(BAT_LED_ORANGE, (blink_second & 1) ? 0 : 1); break; - case PWR_STATE_IDLE: /* Ext. power connected in IDLE. */ + case LED_PWRS_IDLE: /* Ext. power connected in IDLE. */ if (charge_flags & CHARGE_FLAG_FORCE_IDLE) { bat_led_set(BAT_LED_BLUE, (blink_second & 2) ? 0 : 1); bat_led_set(BAT_LED_ORANGE, (blink_second & 2) ? 1 : 0); diff --git a/board/elm/usb_pd_policy.c b/board/elm/usb_pd_policy.c index 5cfc60650e..0369d8a15c 100644 --- a/board/elm/usb_pd_policy.c +++ b/board/elm/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,12 +17,12 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_set_power_supply_ready(int port) { @@ -87,7 +87,6 @@ __override int svdm_dp_attention(int port, uint32_t *payload) __override void svdm_exit_dp_mode(int port) { - svdm_safe_dp_mode(port); anx7688_hpd_disable(port); } #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/board/elm/vif_override.xml b/board/elm/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/elm/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/endeavour/board.c b/board/endeavour/board.c index b3d44ec777..10ab236f0f 100644 --- a/board/endeavour/board.c +++ b/board/endeavour/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Endeavour board configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery.h" #include "bd99992gw.h" #include "board_config.h" @@ -39,13 +38,14 @@ #include "uart.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static uint8_t board_version; static uint32_t oem; static uint32_t sku; +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Hibernate wake configuration */ @@ -57,14 +57,15 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* ADC channels */ const struct adc_t adc_channels[] = { /* Vbus sensing (1/10 voltage divider). */ - [ADC_VBUS] = {"VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* TODO: Verify fan control and mft */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_FAN_PWR_EN, }; @@ -81,15 +82,31 @@ const struct fan_t fans[] = { BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); -const struct i2c_port_t i2c_ports[] = { - {"pse", I2C_PORT_PSE, 400, GPIO_I2C0_0_SCL, GPIO_I2C0_0_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_I2C0_1_SCL, GPIO_I2C0_1_SDA}, - {"pmic", I2C_PORT_PMIC, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"thermal", I2C_PORT_THERMAL, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "pse", + .port = I2C_PORT_PSE, + .kbps = 400, + .scl = GPIO_I2C0_0_SCL, + .sda = GPIO_I2C0_0_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_I2C0_1_SCL, + .sda = GPIO_I2C0_1_SDA }, + { .name = "pmic", + .port = I2C_PORT_PMIC, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "thermal", + .port = I2C_PORT_THERMAL, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -108,10 +125,10 @@ const int usb_port_enable[USB_PORT_COUNT] = { * src/mainboard/google/${board}/acpi/dptf.asl */ const struct temp_sensor_t temp_sensors[] = { - {"TMP431_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_LOCAL}, - {"TMP431_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE1}, + { "TMP431_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_LOCAL }, + { "TMP431_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE1 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -119,14 +136,18 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); * Thermal limits for each temp sensor. All temps are in degrees K. Must be in * same order as enum temp_sensor_id. To always ignore any temp, use 0. */ +static const int temp_fan_off = C_TO_K(35); +static const int temp_fan_max = C_TO_K(55); struct ec_thermal_config thermal_params[] = { /* {Twarn, Thigh, Thalt}, * {Twarn, Thigh, X }, * fan_off, fan_max */ - {{0, C_TO_K(81), C_TO_K(82)}, {0, C_TO_K(77), 0}, - C_TO_K(43), C_TO_K(76)}, /* TMP431_Internal */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* TMP431_Sensor_1 */ + { { 0, C_TO_K(81), C_TO_K(82) }, + { 0, C_TO_K(77), 0 }, + temp_fan_off, + temp_fan_max }, /* TMP431_Internal */ + { { 0, 0, 0 }, { 0, 0, 0 }, 0, 0 }, /* TMP431_Sensor_1 */ }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -295,34 +316,38 @@ int64_t get_time_dsw_pwrok(void) } const struct pwm_t pwm_channels[] = { - [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, [PWM_CH_LED_WHITE] = { 5, PWM_CONFIG_DSLEEP, 100 }, - [PWM_CH_FAN] = {4, PWM_CONFIG_OPEN_DRAIN, 25000}, + [PWM_CH_FAN] = { 4, PWM_CONFIG_OPEN_DRAIN, 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -struct fan_step { - int on; - int off; - int rpm; +static const struct fan_step_1_1 fan_table0[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(35), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(41), + .rpm = 2500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .rpm = 2900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .rpm = 3400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .rpm = 3900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .rpm = 4400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(52), + .rpm = 4900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(55), + .rpm = 5400 }, }; - -/* Note: Do not make the fan on/off point equal to 0 or 100 */ -static const struct fan_step fan_table0[] = { - {.on = 0, .off = 3, .rpm = 0}, - {.on = 15, .off = 3, .rpm = 2500}, - {.on = 36, .off = 18, .rpm = 3200}, - {.on = 52, .off = 39, .rpm = 3500}, - {.on = 61, .off = 55, .rpm = 3900}, - {.on = 70, .off = 64, .rpm = 4500}, - {.on = 82, .off = 73, .rpm = 5100}, - {.on = 97, .off = 85, .rpm = 5400}, -}; -/* All fan tables must have the same number of levels */ #define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) -static const struct fan_step *fan_table = fan_table0; - +static const struct fan_step_1_1 *fan_table = fan_table0; static void cbi_init(void) { @@ -347,43 +372,8 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -int fan_percent_to_rpm(int fan, int pct) +int fan_percent_to_rpm(int fan, int temp_ratio) { - static int current_level; - static int previous_pct; - int i; - - /* - * Compare the pct and previous pct, we have the three paths : - * 1. decreasing path. (check the off point) - * 2. increasing path. (check the on point) - * 3. invariant path. (return the current RPM) - */ - if (pct < previous_pct) { - for (i = current_level; i >= 0; i--) { - if (pct <= fan_table[i].off) - current_level = i - 1; - else - break; - } - } else if (pct > previous_pct) { - for (i = current_level + 1; i < NUM_FAN_LEVELS; i++) { - if (pct >= fan_table[i].on) - current_level = i; - else - break; - } - } - - if (current_level < 0) - current_level = 0; - - previous_pct = pct; - - if (fan_table[current_level].rpm != - fan_get_rpm_target(FAN_CH(fan))) - cprints(CC_THERMAL, "Setting fan RPM to %d", - fan_table[current_level].rpm); - - return fan_table[current_level].rpm; + return temp_ratio_to_rpm_hysteresis(fan_table, NUM_FAN_LEVELS, fan, + temp_ratio, NULL); } diff --git a/board/endeavour/board.h b/board/endeavour/board.h index 29ca1316f9..9c0836b0e3 100644 --- a/board/endeavour/board.h +++ b/board/endeavour/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,7 +12,7 @@ * Allow dangerous commands. * TODO: Remove this config before production. */ -#undef CONFIG_SYSTEM_UNLOCKED +#undef CONFIG_SYSTEM_UNLOCKED #define CONFIG_USB_PD_COMM_LOCKED /* EC */ @@ -20,18 +20,18 @@ #define CONFIG_BOARD_VERSION_CBI #define CONFIG_BOARD_HAS_RTC_RESET #define CONFIG_CRC8 -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_DEDICATED_RECOVERY_BUTTON #define CONFIG_EMULATED_SYSRQ #define CONFIG_LED_COMMON -#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_USE_HOST_EVENT #define CONFIG_DPTF -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#undef CONFIG_LID_SWITCH +#define CONFIG_I2C_CONTROLLER +#undef CONFIG_LID_SWITCH #define CONFIG_POWER_BUTTON_IGNORE_LID #define CONFIG_PWM #define CONFIG_LTO @@ -49,8 +49,6 @@ #define CONFIG_THROTTLE_AP #define CONFIG_CHIPSET_CAN_THROTTLE #define CONFIG_PWM -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY /* EC console commands */ #define CONFIG_CMD_BUTTON @@ -60,12 +58,13 @@ #define CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET #define CONFIG_CHIPSET_HAS_PRE_INIT_CALLBACK #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#undef CONFIG_EXTPOWER_DEBOUNCE_MS #define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 @@ -83,18 +82,18 @@ #define USB_PORT_COUNT 4 /* Optional feature to configure npcx chip */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ -#define NPCX_TACH_SEL2 1 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ +#define NPCX_TACH_SEL2 1 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ /* I2C ports */ -#define I2C_PORT_PSE NPCX_I2C_PORT0_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT0_1 -#define I2C_PORT_PMIC NPCX_I2C_PORT2 -#define I2C_PORT_THERMAL NPCX_I2C_PORT3 +#define I2C_PORT_PSE NPCX_I2C_PORT0_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT0_1 +#define I2C_PORT_PMIC NPCX_I2C_PORT2 +#define I2C_PORT_THERMAL NPCX_I2C_PORT3 /* I2C addresses */ -#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_ADDR_EEPROM_FLAGS 0x50 #define CONFIG_VBOOT_HASH #define CONFIG_VSTORE @@ -110,15 +109,12 @@ enum charge_port { }; enum temp_sensor_id { - TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ - TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ + TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ + TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ TEMP_SENSOR_COUNT }; -enum adc_channel { - ADC_VBUS, - ADC_CH_COUNT -}; +enum adc_channel { ADC_VBUS, ADC_CH_COUNT }; enum pwm_channel { PWM_CH_LED_RED, diff --git a/board/endeavour/build.mk b/board/endeavour/build.mk index 20f3f4d02c..2b19f6b43d 100644 --- a/board/endeavour/build.mk +++ b/board/endeavour/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/endeavour/ec.tasklist b/board/endeavour/ec.tasklist index ef58c6267a..9a4435f43e 100644 --- a/board/endeavour/ec.tasklist +++ b/board/endeavour/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/endeavour/gpio.inc b/board/endeavour/gpio.inc index 85904aab0c..e67f88347a 100644 --- a/board/endeavour/gpio.inc +++ b/board/endeavour/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/endeavour/led.c b/board/endeavour/led.c index b75de503e5..91bd6a3410 100644 --- a/board/endeavour/led.c +++ b/board/endeavour/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -15,7 +15,7 @@ #include "timer.h" #include "util.h" -const enum ec_led_id supported_led_ids[] = {EC_LED_ID_POWER_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); enum led_color { @@ -71,9 +71,9 @@ static int set_color(enum ec_led_id id, enum led_color color, int duty) } } -#define LED_PULSE_US (2 * SECOND) +#define LED_PULSE_US (2 * SECOND) /* 40 msec for nice and smooth transition. */ -#define LED_PULSE_TICK_US (40 * MSEC) +#define LED_PULSE_TICK_US (40 * MSEC) /* When pulsing is enabled, brightness is incremented by every * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented @@ -167,7 +167,7 @@ void show_critical_error(void) set_color(EC_LED_ID_POWER_LED, LED_RED, 100); } -static int command_led(int argc, char **argv) +static int command_led(int argc, const char **argv) { enum ec_led_id id = EC_LED_ID_POWER_LED; @@ -190,8 +190,7 @@ static int command_led(int argc, char **argv) } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(led, command_led, - "[debug|red|white|off|crit]", +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|red|white|off|crit]", "Turn on/off LED."); void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) diff --git a/board/endeavour/pse.c b/board/endeavour/pse.c index cce1a104b1..bda7e1994d 100644 --- a/board/endeavour/pse.c +++ b/board/endeavour/pse.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,44 +18,44 @@ #include "timer.h" #include "util.h" -#define LTC4291_I2C_ADDR 0x2C - -#define LTC4291_REG_SUPEVN_COR 0x0B -#define LTC4291_REG_STATPWR 0x10 -#define LTC4291_REG_STATPIN 0x11 -#define LTC4291_REG_OPMD 0x12 -#define LTC4291_REG_DISENA 0x13 -#define LTC4291_REG_DETENA 0x14 -#define LTC4291_REG_DETPB 0x18 -#define LTC4291_REG_PWRPB 0x19 -#define LTC4291_REG_RSTPB 0x1A -#define LTC4291_REG_ID 0x1B -#define LTC4291_REG_DEVID 0x43 -#define LTC4291_REG_HPMD1 0x46 -#define LTC4291_REG_HPMD2 0x4B -#define LTC4291_REG_HPMD3 0x50 -#define LTC4291_REG_HPMD4 0x55 -#define LTC4291_REG_LPWRPB 0x6E - -#define LTC4291_FLD_STATPIN_AUTO BIT(0) -#define LTC4291_FLD_RSTPB_RSTALL BIT(4) - -#define LTC4291_STATPWR_ON_PORT(port) (0x01 << (port)) -#define LTC4291_DETENA_EN_PORT(port) (0x11 << (port)) -#define LTC4291_DETPB_EN_PORT(port) (0x11 << (port)) -#define LTC4291_PWRPB_OFF_PORT(port) (0x10 << (port)) - -#define LTC4291_OPMD_AUTO 0xFF -#define LTC4291_DISENA_ALL 0x0F -#define LTC4291_DETENA_ALL 0xFF -#define LTC4291_ID 0x64 -#define LTC4291_DEVID 0x38 -#define LTC4291_HPMD_MIN 0x00 -#define LTC4291_HPMD_MAX 0xA8 - -#define LTC4291_PORT_MAX 4 - -#define LTC4291_RESET_DELAY_US (20 * MSEC) +#define LTC4291_I2C_ADDR 0x2C + +#define LTC4291_REG_SUPEVN_COR 0x0B +#define LTC4291_REG_STATPWR 0x10 +#define LTC4291_REG_STATPIN 0x11 +#define LTC4291_REG_OPMD 0x12 +#define LTC4291_REG_DISENA 0x13 +#define LTC4291_REG_DETENA 0x14 +#define LTC4291_REG_DETPB 0x18 +#define LTC4291_REG_PWRPB 0x19 +#define LTC4291_REG_RSTPB 0x1A +#define LTC4291_REG_ID 0x1B +#define LTC4291_REG_DEVID 0x43 +#define LTC4291_REG_HPMD1 0x46 +#define LTC4291_REG_HPMD2 0x4B +#define LTC4291_REG_HPMD3 0x50 +#define LTC4291_REG_HPMD4 0x55 +#define LTC4291_REG_LPWRPB 0x6E + +#define LTC4291_FLD_STATPIN_AUTO BIT(0) +#define LTC4291_FLD_RSTPB_RSTALL BIT(4) + +#define LTC4291_STATPWR_ON_PORT(port) (0x01 << (port)) +#define LTC4291_DETENA_EN_PORT(port) (0x11 << (port)) +#define LTC4291_DETPB_EN_PORT(port) (0x11 << (port)) +#define LTC4291_PWRPB_OFF_PORT(port) (0x10 << (port)) + +#define LTC4291_OPMD_AUTO 0xFF +#define LTC4291_DISENA_ALL 0x0F +#define LTC4291_DETENA_ALL 0xFF +#define LTC4291_ID 0x64 +#define LTC4291_DEVID 0x38 +#define LTC4291_HPMD_MIN 0x00 +#define LTC4291_HPMD_MAX 0xA8 + +#define LTC4291_PORT_MAX 4 + +#define LTC4291_RESET_DELAY_US (20 * MSEC) #define I2C_PSE_READ(reg, data) \ i2c_read8(I2C_PORT_PSE, LTC4291_I2C_ADDR, LTC4291_REG_##reg, (data)) @@ -63,7 +63,7 @@ #define I2C_PSE_WRITE(reg, data) \ i2c_write8(I2C_PORT_PSE, LTC4291_I2C_ADDR, LTC4291_REG_##reg, (data)) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) static int pse_write_hpmd(int port, int val) { @@ -170,7 +170,10 @@ static void pse_init(void) } DECLARE_HOOK(HOOK_CHIPSET_RESUME, pse_init, HOOK_PRIO_DEFAULT); -static int command_pse(int argc, char **argv) +/* Also reset the PSE on a reboot to toggle the power. */ +DECLARE_HOOK(HOOK_CHIPSET_RESET, pse_init, HOOK_PRIO_DEFAULT); + +static int command_pse(int argc, const char **argv) { int port; @@ -202,8 +205,7 @@ static int command_pse(int argc, char **argv) else return EC_ERROR_PARAM2; } -DECLARE_CONSOLE_COMMAND(pse, command_pse, - " ", +DECLARE_CONSOLE_COMMAND(pse, command_pse, " ", "Set PSE port power"); static int ec_command_pse_status(int port, uint8_t *status) diff --git a/board/eve/battery.c b/board/eve/battery.c index b5fb949ffe..d1ce1fd74a 100644 --- a/board/eve/battery.c +++ b/board/eve/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -18,10 +18,10 @@ #include "i2c.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) /* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHUTDOWN_DATA 0x0010 +#define SB_SHUTDOWN_DATA 0x0010 /* Vendor CTO command parameter */ #define SB_VENDOR_PARAM_CTO_DISABLE 0 @@ -81,16 +81,16 @@ static int otd_recovery_temp_reg = -1; * limits are given by discharging_min/max_c. */ static const struct battery_info batt_info_lg = { - .voltage_max = TARGET_WITH_MARGIN(8800, 5), /* mV */ - .voltage_normal = 7700, - .voltage_min = 6100, /* Add 100mV for charger accuracy */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 46, - .charging_min_c = 10, - .charging_max_c = 50, - .discharging_min_c = 0, - .discharging_max_c = 60, + .voltage_max = TARGET_WITH_MARGIN(8800, 5), /* mV */ + .voltage_normal = 7700, + .voltage_min = 6100, /* Add 100mV for charger accuracy */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 46, + .charging_min_c = 10, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 60, }; /* @@ -99,16 +99,16 @@ static const struct battery_info batt_info_lg = { * limits are given by discharging_min/max_c. */ static const struct battery_info batt_info_lishen = { - .voltage_max = TARGET_WITH_MARGIN(8800, 5), /* mV */ - .voltage_normal = 7700, - .voltage_min = 6100, /* Add 100mV for charger accuracy */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 46, - .charging_min_c = 10, - .charging_max_c = 50, - .discharging_min_c = 0, - .discharging_max_c = 60, + .voltage_max = TARGET_WITH_MARGIN(8800, 5), /* mV */ + .voltage_normal = 7700, + .voltage_min = 6100, /* Add 100mV for charger accuracy */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 46, + .charging_min_c = 10, + .charging_max_c = 50, + .discharging_min_c = 0, + .discharging_max_c = 60, }; static const struct board_batt_params info[] = { @@ -139,7 +139,7 @@ static int board_get_battery_type(void) if (!battery_manufacturer_name(name, sizeof(name))) { for (i = 0; i < BATTERY_TYPE_COUNT; i++) { if (!strncasecmp(name, info[i].manuf_name, - ARRAY_SIZE(name)-1)) { + ARRAY_SIZE(name) - 1)) { board_battery_type = i; break; } @@ -168,7 +168,9 @@ DECLARE_HOOK(HOOK_INIT, board_init_battery_type, HOOK_PRIO_INIT_I2C + 1); const struct battery_info *battery_get_info(void) { return info[board_battery_type == BATTERY_TYPE_COUNT ? - DEFAULT_BATTERY_TYPE : board_battery_type].batt_info; + DEFAULT_BATTERY_TYPE : + board_battery_type] + .batt_info; } int board_cut_off_battery(void) @@ -192,7 +194,7 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) /* Do not discharge on AC if the battery is still waking up */ if (!(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - !(curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.status & STATUS_FULLY_CHARGED)) return 0; /* @@ -209,8 +211,8 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) * and suspend USB charging and DC/DC converter. */ if (!battery_is_cut_off() && - !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - (curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) return 1; /* @@ -275,8 +277,9 @@ static int battery_init(void) { int batt_status; - return battery_status(&batt_status) ? 0 : - !!(batt_status & STATUS_INITIALIZED); + return battery_status(&batt_status) ? + 0 : + !!(batt_status & STATUS_INITIALIZED); } /* Allow booting now that the battery has woke up */ @@ -305,8 +308,8 @@ static int battery_check_disconnect(void) uint8_t data[6]; /* Check if battery discharging is disabled. */ - rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); + rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, SB_ALT_MANUFACTURER_ACCESS, + data, sizeof(data)); if (rv) return BATTERY_DISCONNECT_ERROR; @@ -384,14 +387,13 @@ static int board_battery_sb_write(uint8_t access, int cmd) buf[1] = cmd & 0xff; buf[2] = (cmd >> 8) & 0xff; - rv = i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - buf, 1 + sizeof(uint16_t), NULL, 0); + rv = i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, buf, + 1 + sizeof(uint16_t), NULL, 0); return rv; } -int board_battery_read_mfgacc(int offset, int access, - uint8_t *buf, int len) +int board_battery_read_mfgacc(int offset, int access, uint8_t *buf, int len) { int rv; uint8_t block_len, reg; @@ -408,7 +410,7 @@ int board_battery_read_mfgacc(int offset, int access, reg = access; rv = i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, ®, 1, - &block_len, 1, I2C_XFER_START); + &block_len, 1, I2C_XFER_START); if (rv) { i2c_lock(I2C_PORT_BATTERY, 0); return rv; @@ -419,7 +421,7 @@ int board_battery_read_mfgacc(int offset, int access, block_len = len; rv = i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, NULL, 0, - buf, block_len, I2C_XFER_STOP); + buf, block_len, I2C_XFER_STOP); i2c_lock(I2C_PORT_BATTERY, 0); return rv; @@ -432,7 +434,8 @@ static int board_battery_unseal(uint32_t param) /* Get Operation Status */ rv = board_battery_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); + SB_ALT_MANUFACTURER_ACCESS, data, + sizeof(data)); if (rv) return EC_ERROR_UNKNOWN; @@ -457,7 +460,8 @@ static int board_battery_unseal(uint32_t param) /* Verify that battery is unsealed */ rv = board_battery_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); + SB_ALT_MANUFACTURER_ACCESS, data, + sizeof(data)); if (rv || ((data[3] & 0x3) != 0x2)) return EC_ERROR_UNKNOWN; } @@ -474,7 +478,7 @@ static int board_battery_seal(void) int rv; i2c_lock(I2C_PORT_BATTERY, 1); - rv = board_battery_sb_write(SB_MANUFACTURER_ACCESS, 0x0030); + rv = board_battery_sb_write(SB_MANUFACTURER_ACCESS, 0x0030); i2c_lock(I2C_PORT_BATTERY, 0); if (rv != EC_SUCCESS) @@ -507,8 +511,7 @@ static int board_battery_write_flash(int addr, uint32_t data, int len) len += 4; i2c_lock(I2C_PORT_BATTERY, 1); - rv = i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, buf, - len, NULL, 0); + rv = i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, buf, len, NULL, 0); i2c_lock(I2C_PORT_BATTERY, 0); return rv; @@ -522,13 +525,13 @@ static int board_battery_read_flash(int block, int len, uint8_t *buf) if (len > 4) len = 4; - rv = board_battery_read_mfgacc(block, - SB_ALT_MANUFACTURER_ACCESS, data, len + 2); + rv = board_battery_read_mfgacc(block, SB_ALT_MANUFACTURER_ACCESS, data, + len + 2); if (rv) return EC_RES_ERROR; for (i = 0; i < len; i++) - buf[i] = data[i+2]; + buf[i] = data[i + 2]; return EC_SUCCESS; } @@ -594,7 +597,7 @@ static int board_battery_fix_otd_recovery_temp(uint32_t value) (uint8_t *)&otd_recovery_temp)) otd_recovery_temp_reg = otd_recovery_temp; } else { - otd_recovery_temp_reg = otd_recovery_temp; + otd_recovery_temp_reg = otd_recovery_temp; } if (board_battery_seal()) { @@ -607,7 +610,7 @@ static int board_battery_fix_otd_recovery_temp(uint32_t value) return EC_SUCCESS; } -int battery_get_vendor_param(uint32_t param, uint32_t *value) +__override int battery_get_vendor_param(uint32_t param, uint32_t *value) { /* * These registers can't be read directly because the flash area @@ -638,7 +641,7 @@ int battery_get_vendor_param(uint32_t param, uint32_t *value) return EC_RES_ERROR; } -int battery_set_vendor_param(uint32_t param, uint32_t value) +__override int battery_set_vendor_param(uint32_t param, uint32_t value) { switch (param) { case SB_VENDOR_PARAM_CTO_DISABLE: diff --git a/board/eve/board.c b/board/eve/board.c index 095b19ef3a..3193451ad1 100644 --- a/board/eve/board.c +++ b/board/eve/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,15 +6,15 @@ /* Eve board-specific configuration */ #include "acpi.h" -#include "adc_chip.h" #include "bd99992gw.h" #include "board_config.h" #include "button.h" #include "charge_manager.h" -#include "charge_state.h" #include "charge_ramp.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" +#include "compiler.h" #include "console.h" #include "device_event.h" #include "driver/accel_kionix.h" @@ -26,19 +26,21 @@ #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" #include "driver/temp_sensor/bd99992gw.h" +#include "espi.h" #include "extpower.h" #include "gesture.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "i2c.h" -#include "keyboard_scan.h" #include "keyboard_8042_sharedlib.h" +#include "keyboard_scan.h" #include "lid_angle.h" #include "lid_switch.h" #include "math_util.h" #include "motion_lid.h" #include "motion_sense.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -56,10 +58,9 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" -#include "espi.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { @@ -86,7 +87,6 @@ static void tcpc_alert_event(enum gpio_signal signal) static void enable_input_devices(void); DECLARE_DEFERRED(enable_input_devices); -#define LID_DEBOUNCE_US (30 * MSEC) void tablet_mode_interrupt(enum gpio_signal signal) { hook_call_deferred(&enable_input_devices_data, LID_DEBOUNCE_US); @@ -120,7 +120,7 @@ static void anx74xx_c0_cable_det_handler(void) * and if in normal mode, then there is no need to trigger a tcpc reset. */ if (cable_det && !reset_n) - task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); + task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET); } DECLARE_DEFERRED(anx74xx_c0_cable_det_handler); @@ -139,7 +139,7 @@ static void anx74xx_c1_cable_det_handler(void) * and if in normal mode, then there is no need to trigger a tcpc reset. */ if (cable_det && !reset_n) - task_set_event(TASK_ID_PD_C1, PD_EVENT_TCPC_RESET, 0); + task_set_event(TASK_ID_PD_C1, PD_EVENT_TCPC_RESET); } DECLARE_DEFERRED(anx74xx_c1_cable_det_handler); @@ -155,10 +155,11 @@ void anx74xx_cable_det_interrupt(enum gpio_signal signal) } #endif +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Keyboard scan. Increase output_settle_us to 80us from default 50us. */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { .output_settle_us = 80, .debounce_down_us = 9 * MSEC, .debounce_up_us = 30 * MSEC, @@ -173,13 +174,13 @@ struct keyboard_scan_config keyscan_config = { /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { 5, 0, 10000 }, - [PWM_CH_LED_L_RED] = { 2, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_KBLIGHT] = { 5, 0, 10000 }, + [PWM_CH_LED_L_RED] = { 2, PWM_CONFIG_DSLEEP, 100 }, [PWM_CH_LED_L_GREEN] = { 3, PWM_CONFIG_DSLEEP, 100 }, - [PWM_CH_LED_L_BLUE] = { 4, PWM_CONFIG_DSLEEP, 100 }, - [PWM_CH_LED_R_RED] = { 1, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_L_BLUE] = { 4, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_R_RED] = { 1, PWM_CONFIG_DSLEEP, 100 }, [PWM_CH_LED_R_GREEN] = { 0, PWM_CONFIG_DSLEEP, 100 }, - [PWM_CH_LED_R_BLUE] = { 6, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_R_BLUE] = { 6, PWM_CONFIG_DSLEEP, 100 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -192,12 +193,32 @@ const enum gpio_signal hibernate_wake_pins[] = { const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* I2C port map */ -const struct i2c_port_t i2c_ports[] = { - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C0_0_SCL, GPIO_I2C0_0_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C0_1_SCL, GPIO_I2C0_1_SDA}, - {"accelgyro", I2C_PORT_GYRO, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"sensors", I2C_PORT_LID_ACCEL, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"batt", I2C_PORT_BATTERY, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C0_0_SCL, + .sda = GPIO_I2C0_0_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C0_1_SCL, + .sda = GPIO_I2C0_1_SDA }, + { .name = "accelgyro", + .port = I2C_PORT_GYRO, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "sensors", + .port = I2C_PORT_LID_ACCEL, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "batt", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -221,16 +242,22 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &anx74xx_tcpm_usb_mux_driver, - .hpd_update = &anx74xx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &anx74xx_tcpm_usb_mux_driver, + .hpd_update = &anx74xx_tcpc_update_hpd_status, + }, }, { - .usb_port = 1, - .driver = &anx74xx_tcpm_usb_mux_driver, - .hpd_update = &anx74xx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &anx74xx_tcpm_usb_mux_driver, + .hpd_update = &anx74xx_tcpc_update_hpd_status, + }, }, }; @@ -331,7 +358,8 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } uint16_t tcpc_get_alert_status(void) @@ -352,18 +380,18 @@ uint16_t tcpc_get_alert_status(void) } const struct temp_sensor_t temp_sensors[] = { - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0}, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0 }, /* These BD99992GW temp sensors are only readable in S0 */ - {"Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM0}, - {"Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM1}, - {"DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM2}, - {"eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM3}, - {"Gyro", TEMP_SENSOR_TYPE_BOARD, bmi160_get_sensor_temp, BASE_GYRO}, + { "Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM0 }, + { "Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM1 }, + { "DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM2 }, + { "eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM3 }, + { "Gyro", TEMP_SENSOR_TYPE_BOARD, bmi160_get_sensor_temp, BASE_GYRO }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -379,8 +407,8 @@ static void board_report_pmic_fault(const char *str) uint32_t info; /* RESETIRQ1 -- Bit 4: VRFAULT */ - if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) - != EC_SUCCESS) + if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) != + EC_SUCCESS) return; if (!(vrfault & BIT(4))) @@ -459,7 +487,7 @@ static void board_set_tablet_mode(void) { int flipped_360_mode = !gpio_get_level(GPIO_TABLET_MODE_L); - tablet_set_mode(flipped_360_mode); + tablet_set_mode(flipped_360_mode, TABLET_TRIGGER_LID); /* Update DPTF profile based on mode */ if (flipped_360_mode) @@ -607,8 +635,8 @@ int board_set_active_charge_port(int charge_port) * @param charge_ma Desired charge limit (mA). * @param charge_mv Negotiated charge voltage (mV). */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* Enable charging trigger by BC1.2 detection */ int bc12_enable = (supplier == CHARGE_SUPPLIER_BC12_CDP || @@ -619,9 +647,7 @@ void board_set_charge_limit(int port, int supplier, int charge_ma, if (bd9995x_bc12_enable_charging(port, bc12_enable)) return; - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } /** @@ -683,15 +709,14 @@ static void enable_input_devices(void) } /* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If suspended and the lid is in 360 position, ignore the lid angle, * which might be faulty. Disable keyboard and trackpad wake. */ if (chipset_in_state(CHIPSET_STATE_ANY_OFF) || - (tablet_get_mode() && chipset_in_state(CHIPSET_STATE_SUSPEND))) + (tablet_get_mode() && chipset_in_state(CHIPSET_STATE_SUSPEND))) enable = 0; keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); @@ -700,7 +725,6 @@ void lid_angle_peripheral_enable(int enable) enable = 0; trackpad_wake_enable(enable); } -#endif /* Called on AP S5 -> S3 transition */ static void board_chipset_startup(void) @@ -824,35 +848,30 @@ static struct mutex g_lid_mutex; static struct kionix_accel_data g_kxcj9_data; static struct bmi_drv_data_t g_bmi160_data; -static struct si114x_drv_data_t g_si114x_data = { - .state = SI114X_NOT_READY, - .covered = 0, - .type_data = { - /* Proximity - unused */ - { - }, - /* light */ - { - .base_data_reg = SI114X_REG_ALSVIS_DATA0, - .irq_flags = SI114X_ALS_INT_FLAG, - .scale = 1, - .offset = -256, - } - } -}; +static struct si114x_drv_data_t + g_si114x_data = { .state = SI114X_NOT_READY, + .covered = 0, + .type_data = { + /* Proximity - unused */ + {}, + /* light */ + { + .base_data_reg = SI114X_ALS_VIS_DATA0, + .irq_flags = + SI114X_IRQ_ENABLE_ALS_IE_INT0 | + SI114X_IRQ_ENABLE_ALS_IE_INT1, + .scale = 1, + .offset = -256, + } } }; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t mag_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t mag_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t lid_standard_ref = { - {FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -947,7 +966,10 @@ struct motion_sensor_t motion_sensors[] = { .default_range = BIT(11), /* 16LSB / uT, fixed */ .rot_standard_ref = &mag_standard_ref, .min_frequency = BMM150_MAG_MIN_FREQ, +/* TODO(b/253292373): Remove when clang is fixed. */ +DISABLE_CLANG_WARNING("-Wshift-count-negative") .max_frequency = BMM150_MAG_MAX_FREQ(SPECIAL), +ENABLE_CLANG_WARNING("-Wshift-count-negative") }, [LID_LIGHT] = { diff --git a/board/eve/board.h b/board/eve/board.h index 1e0431d5cc..f72fd9b523 100644 --- a/board/eve/board.h +++ b/board/eve/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,34 +12,32 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* EC */ #define CONFIG_ADC #define CONFIG_BACKLIGHT_LID -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_BOARD_FORCE_RESET_PIN #define CONFIG_DEVICE_EVENT #define CONFIG_DPTF #define CONFIG_DPTF_MULTI_PROFILE -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU /* 7 day delay before hibernate */ -#undef CONFIG_HIBERNATE_DELAY_SEC +#undef CONFIG_HIBERNATE_DELAY_SEC #define CONFIG_HIBERNATE_DELAY_SEC (3600 * 24 * 7) /* 1 day delay before hibernate if battery is less than 10% */ #define CONFIG_HIBERNATE_BATT_PCT 10 #define CONFIG_HIBERNATE_BATT_SEC (3600 * 24) #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_LED_COMMON #define CONFIG_LID_SWITCH #define CONFIG_LOW_POWER_IDLE #define CONFIG_LTO #define CONFIG_CHIP_PANIC_BACKUP -#define CONFIG_SOFTWARE_PANIC #define CONFIG_PWM #define CONFIG_PWM_KBLIGHT #define CONFIG_SHA256_UNROLLED @@ -56,7 +54,7 @@ #define WIRELESS_GPIO_WLAN GPIO_WLAN_OFF_L #define WIRELESS_GPIO_WLAN_POWER GPIO_PP3300_DX_WLAN #undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 512 +#define CONFIG_UART_TX_BUF_SIZE 256 /* EC console commands */ #define CONFIG_CMD_ACCELS @@ -65,16 +63,21 @@ #define CONFIG_CMD_CHARGER_ADC_AMON_BMON #define CONFIG_HOSTCMD_PD_CONTROL +/* EC console history configuration */ +#undef CONFIG_CONSOLE_HISTORY +#define CONFIG_CONSOLE_HISTORY 1 + /* SOC */ #define CONFIG_CHIPSET_SKYLAKE #define CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + #define CONFIG_KEYBOARD_COL2_INVERTED -#undef CONFIG_KEYBOARD_VIVALDI +#undef CONFIG_KEYBOARD_VIVALDI #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_REFRESH_ROW3 #define CONFIG_TABLET_MODE @@ -83,7 +86,8 @@ #define CONFIG_BATTERY_CRITICAL_SHUTDOWN_CUT_OFF #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" -#define CONFIG_BATTERY_LEVEL_NEAR_FULL 94 +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 94 #define CONFIG_BATTERY_PRESENT_CUSTOM #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_BATTERY_SMART @@ -97,20 +101,22 @@ #define CONFIG_CHARGER_BD9995X #define CONFIG_CHARGER_BD9995X_CHGEN #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_MAINTAIN_VBAT -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 #define CONFIG_CHARGER_PROFILE_OVERRIDE #define CONFIG_CHARGER_PSYS_READ #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 #define BD9995X_IOUT_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V + BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V #define BD9995X_PSYS_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW + BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS -#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 #define CONFIG_POWER_COMMON @@ -132,11 +138,10 @@ #define CONFIG_THERMISTOR_NCP15WB #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_MAG_BMI_BMM150 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCELGYRO_SEC_ADDR_FLAGS BMM150_ADDR0_FLAGS -#define CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT /* Unused */ +#define CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT /* Unused */ #define CONFIG_MAG_CALIBRATE #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_INVALID_CHECK @@ -148,31 +153,34 @@ /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO /* FIFO size is in power of 2. */ -#define CONFIG_ACCEL_FIFO_SIZE 512 +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Depends on how fast the AP boots and typical ODRs */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) /* Enable double tap detection */ #define CONFIG_GESTURE_DETECTION #define CONFIG_GESTURE_HOST_DETECTION -#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP 1 +#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP #define CONFIG_GESTURE_SAMPLING_INTERVAL_MS 5 #define CONFIG_GESTURE_TAP_THRES_MG 100 #define CONFIG_GESTURE_TAP_MAX_INTERSTICE_T 500 -#define CONFIG_GESTURE_DETECTION_MASK \ - BIT(CONFIG_GESTURE_SENSOR_DOUBLE_TAP) +#define CONFIG_GESTURE_DETECTION_MASK BIT(CONFIG_GESTURE_TAP_SENSOR) +#define CONFIG_GESTURE_TAP_SENSOR 1 /* USB */ +#define CONFIG_USB_PID 0x504B + #define CONFIG_USB_CHARGER +#define CONFIG_USB_DRP_ACC_TRYSRC #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_COMM_LOCKED +#define CONFIG_USB_PD_DECODE_SOP #define CONFIG_USB_PD_DISCHARGE_TCPC #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE #define CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT #define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PD_VBUS_DETECT_CHARGER #define CONFIG_USB_PD_TCPC_BOARD_INIT @@ -184,32 +192,32 @@ #undef CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC #define CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC 2 #define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV1 +#define CONFIG_USB_PD_TCPMV2 #define CONFIG_USBC_SS_MUX #define CONFIG_USBC_VCONN #define CONFIG_USBC_VCONN_SWAP /* Optional feature to configure npcx chip */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 as TACH */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 as TACH */ /* I2C ports */ -#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_1 -#define I2C_PORT_GYRO NPCX_I2C_PORT1 -#define I2C_PORT_ACCEL I2C_PORT_GYRO -#define I2C_PORT_LID_ACCEL NPCX_I2C_PORT2 -#define I2C_PORT_ALS NPCX_I2C_PORT2 -#define I2C_PORT_PMIC NPCX_I2C_PORT3 -#define I2C_PORT_BATTERY NPCX_I2C_PORT3 -#define I2C_PORT_CHARGER NPCX_I2C_PORT3 -#define I2C_PORT_THERMAL I2C_PORT_PMIC -#define I2C_PORT_MP2949 NPCX_I2C_PORT3 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_1 +#define I2C_PORT_GYRO NPCX_I2C_PORT1 +#define I2C_PORT_ACCEL I2C_PORT_GYRO +#define I2C_PORT_LID_ACCEL NPCX_I2C_PORT2 +#define I2C_PORT_ALS NPCX_I2C_PORT2 +#define I2C_PORT_PMIC NPCX_I2C_PORT3 +#define I2C_PORT_BATTERY NPCX_I2C_PORT3 +#define I2C_PORT_CHARGER NPCX_I2C_PORT3 +#define I2C_PORT_THERMAL I2C_PORT_PMIC +#define I2C_PORT_MP2949 NPCX_I2C_PORT3 /* I2C addresses */ -#define I2C_ADDR_BD99992_FLAGS 0x30 -#define I2C_ADDR_MP2949_FLAGS 0x20 +#define I2C_ADDR_BD99992_FLAGS 0x30 +#define I2C_ADDR_MP2949_FLAGS 0x20 #ifndef __ASSEMBLER__ @@ -229,11 +237,11 @@ enum board_version_list { }; enum temp_sensor_id { - TEMP_SENSOR_BATTERY, /* BD99956GW TSENSE */ - TEMP_SENSOR_AMBIENT, /* BD99992GW SYSTHERM0 */ - TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ - TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ - TEMP_SENSOR_EMMC, /* BD99992GW SYSTHERM3 */ + TEMP_SENSOR_BATTERY, /* BD99956GW TSENSE */ + TEMP_SENSOR_AMBIENT, /* BD99992GW SYSTHERM0 */ + TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ + TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ + TEMP_SENSOR_EMMC, /* BD99992GW SYSTHERM3 */ TEMP_SENSOR_GYRO, TEMP_SENSOR_COUNT }; @@ -277,25 +285,22 @@ enum sensor_id { SENSOR_COUNT, }; -enum adc_channel { - ADC_CH_COUNT -}; +enum adc_channel { ADC_CH_COUNT }; /* * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Board specific handlers */ int board_get_version(void); diff --git a/board/eve/build.mk b/board/eve/build.mk index f47b5d9caf..0913dd9370 100644 --- a/board/eve/build.mk +++ b/board/eve/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/eve/ec.tasklist b/board/eve/ec.tasklist index 99de365243..75e5f918c5 100644 --- a/board/eve/ec.tasklist +++ b/board/eve/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/eve/gpio.inc b/board/eve/gpio.inc index f9b0c3cfc4..6bf357f0c3 100644 --- a/board/eve/gpio.inc +++ b/board/eve/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/eve/led.c b/board/eve/led.c index 91a7b24a2b..df3f632cf1 100644 --- a/board/eve/led.c +++ b/board/eve/led.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -13,14 +13,14 @@ #include "gpio.h" #include "hooks.h" #include "led_common.h" -#include "pwm.h" #include "math_util.h" +#include "pwm.h" #include "registers.h" #include "task.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_PWM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_PWM, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_PWM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_PWM, format, ##args) #define LED_TICK_TIME (500 * MSEC) #define LED_TICKS_PER_BEAT 1 @@ -37,7 +37,9 @@ * (120, .5, .33). For the transitions of interest only S and I are changed and * they are changed linearly in HSI space. */ -static const uint8_t trans_steps[] = {0, 4, 9, 16, 24, 33, 44, 56, 69, 84, 100}; +static const uint8_t trans_steps[] = { + 0, 4, 9, 16, 24, 33, 44, 56, 69, 84, 100 +}; /* List of LED colors used */ enum led_color { @@ -65,11 +67,7 @@ enum led_pattern { LED_NUM_PATTERNS, }; -enum led_side { - LED_LEFT = 0, - LED_RIGHT, - LED_BOTH -}; +enum led_side { LED_LEFT = 0, LED_RIGHT, LED_BOTH }; struct led_info { /* LED pattern manage variables */ @@ -101,8 +99,8 @@ static int double_tap; static int led_charge_side; static struct led_info led[LED_BOTH]; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_LEFT_LED, EC_LED_ID_RIGHT_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); /* @@ -110,16 +108,18 @@ const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); * particular pattern never changes from the first phase. */ static const struct led_phase pattern[LED_NUM_PATTERNS] = { - { {LED_OFF, LED_OFF}, {0, 0}, DOUBLE_TAP_TICK_LEN }, - { {LED_GREEN, LED_GREEN}, {0, 0}, DOUBLE_TAP_TICK_LEN }, - { {LED_WHITE, LED_GREEN}, {2, 4}, DOUBLE_TAP_TICK_LEN }, - { {LED_WHITE, LED_WHITE}, {0, 0}, DOUBLE_TAP_TICK_LEN }, - { {LED_WHITE, LED_RED}, {2, 4}, DOUBLE_TAP_TICK_LEN }, - { {LED_RED, LED_RED}, {0, 0}, DOUBLE_TAP_TICK_LEN}, - { {LED_RED, LED_RED_HALF}, {4, 4}, DOUBLE_TAP_TICK_LEN * 2 + - DOUBLE_TAP_TICK_LEN / 2}, - { {LED_RED, LED_OFF}, {1, 5}, DOUBLE_TAP_TICK_LEN * 3 + - DOUBLE_TAP_TICK_LEN / 2}, + { { LED_OFF, LED_OFF }, { 0, 0 }, DOUBLE_TAP_TICK_LEN }, + { { LED_GREEN, LED_GREEN }, { 0, 0 }, DOUBLE_TAP_TICK_LEN }, + { { LED_WHITE, LED_GREEN }, { 2, 4 }, DOUBLE_TAP_TICK_LEN }, + { { LED_WHITE, LED_WHITE }, { 0, 0 }, DOUBLE_TAP_TICK_LEN }, + { { LED_WHITE, LED_RED }, { 2, 4 }, DOUBLE_TAP_TICK_LEN }, + { { LED_RED, LED_RED }, { 0, 0 }, DOUBLE_TAP_TICK_LEN }, + { { LED_RED, LED_RED_HALF }, + { 4, 4 }, + DOUBLE_TAP_TICK_LEN * 2 + DOUBLE_TAP_TICK_LEN / 2 }, + { { LED_RED, LED_OFF }, + { 1, 5 }, + DOUBLE_TAP_TICK_LEN * 3 + DOUBLE_TAP_TICK_LEN / 2 }, }; /* @@ -129,12 +129,9 @@ static const struct led_phase pattern[LED_NUM_PATTERNS] = { #define PWM_CHAN_PER_LED 3 static const uint8_t color_brightness[LED_COLOR_COUNT][PWM_CHAN_PER_LED] = { /* {Red, Green, Blue}, */ - [LED_OFF] = {0, 0, 0}, - [LED_RED] = {80, 0, 0}, - [LED_GREEN] = {0, 80, 0}, - [LED_BLUE] = {0, 0, 80}, - [LED_WHITE] = {100, 100, 100}, - [LED_RED_HALF] = {40, 0, 0}, + [LED_OFF] = { 0, 0, 0 }, [LED_RED] = { 80, 0, 0 }, + [LED_GREEN] = { 0, 80, 0 }, [LED_BLUE] = { 0, 0, 80 }, + [LED_WHITE] = { 100, 100, 100 }, [LED_RED_HALF] = { 40, 0, 0 }, }; /* @@ -153,13 +150,13 @@ struct range_map { #error "LED: PULSE_RED battery level <= BLINK_RED level" #endif static const struct range_map pattern_tbl[] = { - {CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC - 1, BLINK_RED}, - {5, PULSE_RED}, - {15, SOLID_RED}, - {25, WHITE_RED}, - {75, SOLID_WHITE}, - {95, WHITE_GREEN}, - {100, SOLID_GREEN}, + { CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC - 1, BLINK_RED }, + { 5, PULSE_RED }, + { 15, SOLID_RED }, + { 25, WHITE_RED }, + { 75, SOLID_WHITE }, + { 95, WHITE_GREEN }, + { 100, SOLID_GREEN }, }; enum led_state_change { @@ -323,18 +320,17 @@ static void led_setup_color_change(int old_idx, int new_idx, enum led_side side) */ total_change = ABS(led[side].rgb_current[rgb_index] - led[side].rgb_target[rgb_index]); - delta_per_step = (total_change << LED_FRAC_BITS) - / (ARRAY_SIZE(trans_steps) - 1); + delta_per_step = (total_change << LED_FRAC_BITS) / + (ARRAY_SIZE(trans_steps) - 1); step_value = 0; for (i = 0; i < ARRAY_SIZE(trans_steps); i++) { - led[side].trans[i] = start_lvl + - ((step_value + - (1 << (LED_FRAC_BITS - 1))) - >> LED_FRAC_BITS); + led[side].trans[i] = + start_lvl + + ((step_value + (1 << (LED_FRAC_BITS - 1))) >> + LED_FRAC_BITS); step_value += delta_per_step; } } - } static void led_adjust_color_step(int side) @@ -397,12 +393,10 @@ static void led_change_color(void) /* Will loop here until the color change is complete. */ while (led[LED_LEFT].state != LED_STATE_DONE || led[LED_RIGHT].state != LED_STATE_DONE) { - for (i = 0; i < LED_BOTH; i++) { if (led[i].state != LED_STATE_DONE) /* Move one step in the transition table */ led_adjust_color_step(i); - } msleep(LED_STEP_MSEC); } @@ -427,14 +421,19 @@ static void led_manage_patterns(enum led_pattern *pattern_desired, int tap) */ if (i == led_charge_side || !led[i].tap_tick_count) { led[i].ticks = 0; - led[i].tap_tick_count = tap ? - pattern[pattern_desired[i]].tap_len : 0; + led[i].tap_tick_count = + tap ? pattern[pattern_desired[i]] + .tap_len : + 0; led[i].pattern_sel = pattern_desired[i]; } } /* Determine pattern phase and color for current phase */ phase = led[i].ticks < LED_TICKS_PER_BEAT * - pattern[led[i].pattern_sel].len[0] ? 0 : 1; + pattern[led[i].pattern_sel] + .len[0] ? + 0 : + 1; color = pattern[led[i].pattern_sel].color[phase]; /* If color is changing, then setup the transition. */ if (led[i].color != color) { @@ -458,9 +457,10 @@ static void led_manage_patterns(enum led_pattern *pattern_desired, int tap) * count. */ if (pattern[led[i].pattern_sel].len[0]) - if (++led[i].ticks == LED_TICKS_PER_BEAT * - (pattern[led[i].pattern_sel].len[0] + - pattern[led[i].pattern_sel].len[1])) + if (++led[i].ticks == + LED_TICKS_PER_BEAT * + (pattern[led[i].pattern_sel].len[0] + + pattern[led[i].pattern_sel].len[1])) led[i].ticks = 0; /* If double tap display is active, decrement its counter */ @@ -486,7 +486,7 @@ static enum led_pattern led_get_double_tap_pattern(int percent_chg) static void led_select_pattern(enum led_pattern *pattern_desired, int tap) { - enum charge_state chg_state = charge_get_state(); + enum led_pwr_state chg_state = led_pwr_get_state(); int side; int percent_chg; enum led_pattern new_pattern; @@ -534,11 +534,11 @@ static void led_select_pattern(enum led_pattern *pattern_desired, int tap) * External charger is connected. First determine pattern for * charging side LED. */ - if (chg_state == PWR_STATE_CHARGE_NEAR_FULL || - ((chg_state == PWR_STATE_DISCHARGE_FULL) - && extpower_is_present())) { + if (chg_state == LED_PWRS_CHARGE_NEAR_FULL || + ((chg_state == LED_PWRS_DISCHARGE_FULL) && + extpower_is_present())) { new_pattern = SOLID_GREEN; - } else if (chg_state == PWR_STATE_CHARGE) { + } else if (chg_state == LED_PWRS_CHARGE) { new_pattern = SOLID_WHITE; } else { new_pattern = OFF; @@ -586,7 +586,6 @@ static void led_init(void) led[i].tap_tick_count = 0; led[i].state = LED_STATE_DONE; } - } void led_task(void *u) @@ -633,7 +632,7 @@ void led_task(void *u) /******************************************************************/ /* Console commands */ -static int command_led(int argc, char **argv) +static int command_led(int argc, const char **argv) { int side = LED_BOTH; char *e; diff --git a/board/eve/usb_pd_policy.c b/board/eve/usb_pd_policy.c index 4d10047d85..969876756e 100644 --- a/board/eve/usb_pd_policy.c +++ b/board/eve/usb_pd_policy.c @@ -1,16 +1,16 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/charger/bd9995x.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -18,17 +18,17 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { @@ -38,9 +38,9 @@ int board_vbus_source_enabled(int port) static void board_vbus_update_source_current(int port) { enum gpio_signal gpio_5v_en = port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN; + GPIO_USB_C0_5V_EN; enum gpio_signal gpio_3a_en = port ? GPIO_EN_USB_C1_3A : - GPIO_EN_USB_C0_3A; + GPIO_EN_USB_C0_3A; int flags; if (system_get_board_version() >= BOARD_VERSION_P1B) { @@ -50,8 +50,8 @@ static void board_vbus_update_source_current(int port) * is controlled by GPIO_USB_C0/1_5V_EN. Both of these signals * can remain outputs. */ - gpio_set_level(gpio_3a_en, vbus_rp[port] == TYPEC_RP_3A0 ? - 1 : 0); + gpio_set_level(gpio_3a_en, + vbus_rp[port] == TYPEC_RP_3A0 ? 1 : 0); gpio_set_level(gpio_5v_en, vbus_en[port]); } else { /* @@ -65,8 +65,8 @@ static void board_vbus_update_source_current(int port) * 1505 mA. */ flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? - (GPIO_INPUT | GPIO_PULL_UP) : - (GPIO_OUTPUT | GPIO_PULL_UP); + (GPIO_INPUT | GPIO_PULL_UP) : + (GPIO_OUTPUT | GPIO_PULL_UP); gpio_set_level(gpio_5v_en, vbus_en[port]); gpio_set_flags(gpio_5v_en, flags); } @@ -85,9 +85,6 @@ int pd_set_power_supply_ready(int port) /* Ensure we're not charging from this port */ bd9995x_select_input_port(port, 0); - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); - pd_set_vbus_discharge(port, 0); /* Provide VBUS */ vbus_en[port] = 1; @@ -113,9 +110,6 @@ void pd_power_supply_reset(int port) if (prev_en) pd_set_vbus_discharge(port, 1); - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); - /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -126,15 +120,13 @@ int pd_check_vconn_swap(int port) return gpio_get_level(GPIO_PMIC_SLP_SUS_L); } -void pd_execute_data_swap(int port, - enum pd_data_role data_role) +void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* Only port 0 supports device mode. */ if (port != 0) return; - gpio_set_level(GPIO_USB2_OTG_ID, - (data_role == PD_ROLE_UFP) ? 1 : 0); + gpio_set_level(GPIO_USB2_OTG_ID, (data_role == PD_ROLE_UFP) ? 1 : 0); gpio_set_level(GPIO_USB2_OTG_VBUSSENSE, - (data_role == PD_ROLE_UFP) ? 1 : 0); + (data_role == PD_ROLE_UFP) ? 1 : 0); } diff --git a/board/eve/vif_override.xml b/board/eve/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/eve/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/ezkinil/battery.c b/board/ezkinil/battery.c index 8c5ec9e1d7..1260b428ae 100644 --- a/board/ezkinil/battery.c +++ b/board/ezkinil/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/ezkinil/board.c b/board/ezkinil/board.c index 17134dd522..d2124188ce 100644 --- a/board/ezkinil/board.c +++ b/board/ezkinil/board.c @@ -1,17 +1,20 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "button.h" -#include "charge_state_v2.h" +#include "cbi_ssfc.h" +#include "charge_state.h" #include "cros_board_info.h" -#include "driver/accelgyro_bmi_common.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" -#include "driver/ppc/aoz1380.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/ppc/aoz1380_public.h" #include "driver/ppc/nx20p348x.h" #include "driver/retimer/pi3hdx1204.h" #include "driver/retimer/tusb544.h" @@ -31,18 +34,34 @@ #include "switch.h" #include "system.h" #include "task.h" -#include "thermistor.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "usb_charge.h" #include "usb_mux.h" #include "usbc_ppc.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#ifdef HAS_TASK_MOTIONSENSE - static int board_ver; +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + /* Motion sensors */ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; @@ -50,18 +69,18 @@ static struct mutex g_base_mutex; /* sensor private data */ static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; -const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +const mat33_fp_t base_standard_ref_1 = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* TODO(gcc >= 5.0) Remove the casts to const pointer at rot_standard_ref */ struct motion_sensor_t motion_sensors[] = { @@ -104,7 +123,7 @@ struct motion_sensor_t motion_sensors[] = { .drv_data = &g_bmi160_data, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .default_range = 2, /* g, enough for laptop */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, @@ -141,7 +160,95 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#endif /* HAS_TASK_MOTIONSENSE */ +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_standard_ref_1, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_1, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t icm42607_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_standard_ref_1, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm42607_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_1, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; const struct power_signal_info power_signal_list[] = { [X86_SLP_S3_N] = { @@ -199,7 +306,7 @@ const int usb_port_enable[USBA_PORT_COUNT] = { const struct pi3hdx1204_tuning pi3hdx1204_tuning = { .eq_ch0_ch1_offset = PI3HDX1204_EQ_DB710, .eq_ch2_ch3_offset = PI3HDX1204_EQ_DB710, - .vod_offset = PI3HDX1204_VOD_115_ALL_CHANNELS, + .vod_offset = PI3HDX1204_VOD_130_ALL_CHANNELS, .de_offset = PI3HDX1204_DE_DB_MINUS5, }; @@ -208,8 +315,12 @@ const struct pi3hdx1204_tuning pi3hdx1204_tuning = { * chip and it need a board specific driver. * Overall, it will use chained mux framework. */ -static int fsusb42umx_set_mux(const struct usb_mux *me, mux_state_t mux_state) +static int fsusb42umx_set_mux(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + if (mux_state & USB_PD_MUX_POLARITY_INVERTED) ioex_set_level(IOEX_USB_C0_SBU_FLIP, 1); else @@ -229,18 +340,80 @@ const struct usb_mux_driver usbc0_sbu_mux_driver = { * Since FSUSB42UMX is not a i2c device, .i2c_port and * .i2c_addr_flags are not required here. */ -const struct usb_mux usbc0_sbu_mux = { - .usb_port = USBC_PORT_C0, - .driver = &usbc0_sbu_mux_driver, +const struct usb_mux_chain usbc0_sbu_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &usbc0_sbu_mux_driver, + }, }; +/***************************************************************************** + * Base Gyro Sensor dynamic configuration + */ + +static enum ec_ssfc_base_gyro_sensor base_gyro_config = SSFC_BASE_GYRO_NONE; + +static void setup_base_gyro_config(void) +{ + base_gyro_config = ec_config_has_base_gyro_sensor(); + + if (base_gyro_config == SSFC_BASE_GYRO_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE GYRO is ICM426XX"); + } else if (base_gyro_config == SSFC_BASE_GYRO_ICM42607) { + motion_sensors[BASE_ACCEL] = icm42607_base_accel; + motion_sensors[BASE_GYRO] = icm42607_base_gyro; + ccprints("BASE GYRO is ICM42607"); + } else if (base_gyro_config == SSFC_BASE_GYRO_BMI160) + ccprints("BASE GYRO is BMI160"); +} + +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_gyro_config) { + case SSFC_BASE_GYRO_ICM426XX: + icm426xx_interrupt(signal); + break; + case SSFC_BASE_GYRO_ICM42607: + icm42607_interrupt(signal); + break; + case SSFC_BASE_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + /***************************************************************************** * USB-C MUX/Retimer dynamic configuration */ +/* Place holder for second mux in USBC1 chain */ +struct usb_mux_chain usbc1_mux1; + +int board_usbc1_retimer_inhpd = IOEX_USB_C1_HPD_IN_DB; + static void setup_mux(void) { - if (ec_config_has_usbc1_retimer_tusb544()) { + enum ec_ssfc_c1_mux mux = get_cbi_ssfc_c1_mux(); + + if (mux == SSFC_C1_MUX_NONE && ec_config_has_usbc1_retimer_tusb544()) + mux = SSFC_C1_MUX_TUSB544; + + if (mux == SSFC_C1_MUX_PS8818) { + ccprints("C1 PS8818 detected"); + /* + * Main MUX is FP5, secondary MUX is PS8818 + * + * Replace usb_muxes[USBC_PORT_C1] with the AMD FP5 + * table entry. + */ + usb_muxes[USBC_PORT_C1].mux = &usbc1_amd_fp5_usb_mux; + /* Set the PS8818 as the secondary MUX */ + usbc1_mux1.mux = &usbc1_ps8818; + } else if (mux == SSFC_C1_MUX_TUSB544) { ccprints("C1 TUSB544 detected"); /* * Main MUX is FP5, secondary MUX is TUSB544 @@ -248,11 +421,9 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the AMD FP5 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_amd_fp5_usb_mux, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_amd_fp5_usb_mux; /* Set the TUSB544 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_tusb544; + usbc1_mux1.mux = &usbc1_tusb544; } else if (ec_config_has_usbc1_retimer_ps8743()) { ccprints("C1 PS8743 detected"); /* @@ -261,32 +432,33 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the PS8743 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_ps8743, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_ps8743; /* Set the AMD FP5 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_amd_fp5_usb_mux; + usbc1_mux1.mux = &usbc1_amd_fp5_usb_mux; /* Don't have the AMD FP5 flip */ usbc1_amd_fp5_usb_mux.flags = USB_MUX_FLAG_SET_WITHOUT_FLIP; } } -struct usb_mux usb_muxes[] = { +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .next_mux = &usbc0_sbu_mux, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_sbu_mux, }, [USBC_PORT_C1] = { /* Filled in dynamically at startup */ + .next = &usbc1_mux1, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); static int board_tusb544_mux_set(const struct usb_mux *me, - mux_state_t mux_state) + mux_state_t mux_state) { if (mux_state & USB_PD_MUX_DP_ENABLED) { /* Enable IN_HPD on the DB */ @@ -298,8 +470,7 @@ static int board_tusb544_mux_set(const struct usb_mux *me, return EC_SUCCESS; } -static int board_ps8743_mux_set(const struct usb_mux *me, - mux_state_t mux_state) +static int board_ps8743_mux_set(const struct usb_mux *me, mux_state_t mux_state) { if (mux_state & USB_PD_MUX_DP_ENABLED) /* Enable IN_HPD on the DB */ @@ -367,15 +538,15 @@ __override void ppc_interrupt(enum gpio_signal signal) } } -__override int board_aoz1380_set_vbus_source_current_limit(int port, - enum tcpc_rp_value rp) +__override int +board_aoz1380_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) { int rv; /* Use the TCPC to set the current limit */ - rv = ioex_set_level(port ? IOEX_USB_C1_PPC_ILIM_3A_EN - : IOEX_USB_C0_PPC_ILIM_3A_EN, - (rp == TYPEC_RP_3A0) ? 1 : 0); + rv = ioex_set_level(port ? IOEX_USB_C1_PPC_ILIM_3A_EN : + IOEX_USB_C0_PPC_ILIM_3A_EN, + (rp == TYPEC_RP_3A0) ? 1 : 0); return rv; } @@ -420,6 +591,8 @@ static void setup_fw_config(void) else gpio_enable_interrupt(GPIO_DP1_HPD_EC_IN); } + + setup_base_gyro_config(); } /* Use HOOK_PRIO_INIT_I2C + 2 to be after ioex_init(). */ DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); @@ -443,10 +616,9 @@ static void hdmi_hpd_handler(void) gpio_set_level(GPIO_DP1_HPD, hpd); ccprints("HDMI HPD %d", hpd); - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON) - && hpd); + pi3hdx1204_enable( + I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, + chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON) && hpd); } DECLARE_DEFERRED(hdmi_hpd_handler); @@ -474,8 +646,7 @@ static void board_chipset_resume(void) if (ec_config_has_hdmi_retimer_pi3hdx1204()) { ioex_set_level(IOEX_HDMI_POWER_EN_DB, 1); msleep(PI3HDX1204_POWER_ON_DELAY_MS); - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, check_hdmi_hpd_status()); } } @@ -486,9 +657,7 @@ static void board_chipset_suspend(void) ioex_set_level(IOEX_USB_A1_RETIMER_EN, 0); if (ec_config_has_hdmi_retimer_pi3hdx1204()) { - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - 0); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, 0); ioex_set_level(IOEX_HDMI_POWER_EN_DB, 0); } @@ -503,13 +672,13 @@ DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = -1, }; const struct fan_rpm fan_rpm_0 = { - .rpm_min = 2800, - .rpm_start = 2800, + .rpm_min = 3200, + .rpm_start = 3200, .rpm_max = 6000, }; const struct fan_t fans[] = { @@ -591,41 +760,40 @@ const struct temp_sensor_t temp_sensors[] = { }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -const static struct ec_thermal_config thermal_thermistor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(85), - [EC_TEMP_THRESH_HALT] = C_TO_K(95), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - }, - .temp_fan_off = 0, - .temp_fan_max = 0, -}; - -const static struct ec_thermal_config thermal_soc = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = 0, - .temp_fan_max = 0, -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_THERMISTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(95), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_thermistor = + THERMAL_THERMISTOR; -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(85), - [EC_TEMP_THRESH_HALT] = C_TO_K(95), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(80), - }, - .temp_fan_off = C_TO_K(37), - .temp_fan_max = C_TO_K(90), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_SOC \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(32), \ + .temp_fan_max = C_TO_K(75), \ + } +__maybe_unused static const struct ec_thermal_config thermal_soc = THERMAL_SOC; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -637,14 +805,14 @@ struct fan_step { /* Note: Do not make the fan on/off point equal to 0 or 100 */ static const struct fan_step fan_table0[] = { - {.on = 0, .off = 2, .rpm = 0}, - {.on = 15, .off = 2, .rpm = 2800}, - {.on = 23, .off = 13, .rpm = 3200}, - {.on = 30, .off = 21, .rpm = 3400}, - {.on = 38, .off = 28, .rpm = 3700}, - {.on = 45, .off = 36, .rpm = 4200}, - {.on = 55, .off = 43, .rpm = 4500}, - {.on = 66, .off = 53, .rpm = 5300}, + { .on = 0, .off = 1, .rpm = 0 }, + { .on = 9, .off = 1, .rpm = 3200 }, + { .on = 21, .off = 7, .rpm = 3500 }, + { .on = 28, .off = 16, .rpm = 3900 }, + { .on = 37, .off = 26, .rpm = 4200 }, + { .on = 47, .off = 35, .rpm = 4600 }, + { .on = 56, .off = 44, .rpm = 5100 }, + { .on = 72, .off = 60, .rpm = 5500 }, }; /* All fan tables must have the same number of levels */ #define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) @@ -655,7 +823,6 @@ static void setup_fans(void) { thermal_params[TEMP_SENSOR_CHARGER] = thermal_thermistor; thermal_params[TEMP_SENSOR_SOC] = thermal_soc; - thermal_params[TEMP_SENSOR_CPU] = thermal_cpu; } DECLARE_HOOK(HOOK_INIT, setup_fans, HOOK_PRIO_DEFAULT); @@ -691,8 +858,7 @@ int fan_percent_to_rpm(int fan, int pct) previous_pct = pct; - if (fan_table[current_level].rpm != - fan_get_rpm_target(FAN_CH(fan))) { + if (fan_table[current_level].rpm != fan_get_rpm_target(FAN_CH(fan))) { cprints(CC_THERMAL, "Setting fan RPM to %d", fan_table[current_level].rpm); board_print_temps(); @@ -700,17 +866,3 @@ int fan_percent_to_rpm(int fan, int pct) return fan_table[current_level].rpm; } - -__override void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* - * Limit the input current to 95% negotiated limit, - * to account for the charger chip margin. - */ - charge_ma = charge_ma * 95 / 100; - - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} diff --git a/board/ezkinil/board.h b/board/ezkinil/board.h index 17a924e99d..66c01a4efb 100644 --- a/board/ezkinil/board.h +++ b/board/ezkinil/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,17 +8,28 @@ #define VARIANT_ZORK_TREMBYLE -#include #include "baseboard.h" -#define CONFIG_MKBP_USE_GPIO +#include + #define CONFIG_FAN_RPM_CUSTOM +#define CONFIG_KEYBOARD_FACTORY_TEST + +/* charger margin */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + /* Motion sensing drivers */ +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCEL_KX022 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -34,38 +45,34 @@ #define TUSB544_I2C_ADDR_FLAGS1 0x0F /* GPIO mapping from board specific name to EC common name. */ -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL -#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL -#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL -#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L -#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK -#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L -#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL -#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD -#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD -#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE -#define GPIO_DP1_HPD GPIO_EC_DP1_HPD -#define IOEX_HDMI_CONN_HPD_3V3_DB IOEX_USB_C1_PPC_ILIM_3A_EN +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_DP1_HPD GPIO_EC_DP1_HPD +#define IOEX_HDMI_CONN_HPD_3V3_DB IOEX_USB_C1_PPC_ILIM_3A_EN #ifndef __ASSEMBLER__ -enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, - ADC_TEMP_SENSOR_SOC, - ADC_CH_COUNT -}; +enum adc_channel { ADC_TEMP_SENSOR_CHARGER, ADC_TEMP_SENSOR_SOC, ADC_CH_COUNT }; enum battery_type { BATTERY_AP19B8M, @@ -79,11 +86,7 @@ enum mft_channel { MFT_CH_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_FAN, PWM_CH_COUNT }; enum temp_sensor_id { TEMP_SENSOR_CHARGER = 0, @@ -92,16 +95,11 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum usba_port { - USBA_PORT_A0 = 0, - USBA_PORT_A1, - USBA_PORT_COUNT -}; +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; /***************************************************************************** * CBI EC FW Configuration */ -#include "cbi_ec_fw_config.h" /** * EZKINIL_MB_USBAC @@ -146,63 +144,55 @@ enum ec_cfg_usb_db_type { EZKINIL_DB_T_OPT2_USBAC = 1, }; +#include "cbi_ec_fw_config.h" -#define HAS_USBA1_RETIMER_TUSB522 \ - (BIT(EZKINIL_DB_T_OPT2_USBAC)) +#define HAS_USBA1_RETIMER_TUSB522 (BIT(EZKINIL_DB_T_OPT2_USBAC)) static inline bool ec_config_has_usba1_retimer_tusb522(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBA1_RETIMER_TUSB522); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBA1_RETIMER_TUSB522); } -#define HAS_USBC1_RETIMER_PS8743 \ - (BIT(EZKINIL_DB_T_OPT2_USBAC)) +#define HAS_USBC1_RETIMER_PS8743 (BIT(EZKINIL_DB_T_OPT2_USBAC)) static inline bool ec_config_has_usbc1_retimer_ps8743(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8743); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_PS8743); } -#define HAS_USBC1_RETIMER_TUSB544 \ - (BIT(EZKINIL_DB_T_OPT1_USBC_HDMI)) +#define HAS_USBC1_RETIMER_TUSB544 (BIT(EZKINIL_DB_T_OPT1_USBC_HDMI)) static inline bool ec_config_has_usbc1_retimer_tusb544(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_TUSB544); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_TUSB544); } -#define HAS_HDMI_RETIMER_PI3HDX1204 \ - (BIT(EZKINIL_DB_T_OPT1_USBC_HDMI)) +#define HAS_HDMI_RETIMER_PI3HDX1204 (BIT(EZKINIL_DB_T_OPT1_USBC_HDMI)) static inline bool ec_config_has_hdmi_retimer_pi3hdx1204(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_RETIMER_PI3HDX1204); + return !!(BIT(ec_config_get_usb_db()) & HAS_HDMI_RETIMER_PI3HDX1204); } -#define HAS_HDMI_CONN_HPD \ - (BIT(EZKINIL_DB_T_OPT1_USBC_HDMI)) +#define HAS_HDMI_CONN_HPD (BIT(EZKINIL_DB_T_OPT1_USBC_HDMI)) static inline bool ec_config_has_hdmi_conn_hpd(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_CONN_HPD); + return !!(BIT(ec_config_get_usb_db()) & HAS_HDMI_CONN_HPD); } /* TODO: Fill in with GPIO values */ -#define PORT_TO_HPD(port) ((port == 0) \ - ? GPIO_USB_C0_HPD \ - : (ec_config_has_usbc1_retimer_ps8743()) \ - ? GPIO_DP1_HPD \ - : GPIO_DP2_HPD) +#define PORT_TO_HPD(port) \ + ((port == 0) ? GPIO_USB_C0_HPD : \ + (ec_config_has_usbc1_retimer_ps8743()) ? GPIO_DP1_HPD : \ + GPIO_DP2_HPD) extern const struct usb_mux usbc1_tusb544; +extern const struct usb_mux usbc1_ps8818; extern const struct usb_mux usbc1_ps8743; extern struct usb_mux usbc1_amd_fp5_usb_mux; +void motion_interrupt(enum gpio_signal signal); void hdmi_hpd_interrupt(enum gpio_signal signal); void hdmi_hpd_interrupt_v2(enum ioex_signal signal); diff --git a/board/ezkinil/build.mk b/board/ezkinil/build.mk index 1c0cbc4f63..45c71f962c 100644 --- a/board/ezkinil/build.mk +++ b/board/ezkinil/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/ezkinil/ec.tasklist b/board/ezkinil/ec.tasklist index d9c1606eb2..abc796f74f 100644 --- a/board/ezkinil/ec.tasklist +++ b/board/ezkinil/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/ezkinil/gpio.inc b/board/ezkinil/gpio.inc index 9a3b022db4..4ea6712424 100644 --- a/board/ezkinil/gpio.inc +++ b/board/ezkinil/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -24,7 +24,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_inter GPIO_INT(EC_WP_L, PIN(5, 0), GPIO_INT_BOTH, switch_interrupt) GPIO_INT(VOLDN_BTN_ODL, PIN(A, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) GPIO_INT(VOLUP_BTN_ODL, PIN(9, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, bmi160_interrupt) +GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, motion_interrupt) GPIO_INT(DP1_HPD_EC_IN, PIN(7, 5), GPIO_INT_BOTH, hdmi_hpd_interrupt) /* GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an interrupt handler. */ diff --git a/board/ezkinil/led.c b/board/ezkinil/led.c index a4eb63b13f..328b47a9e4 100644 --- a/board/ezkinil/led.c +++ b/board/ezkinil/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,32 +8,41 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 100; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{LED_OFF, 1 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_BLUE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { LED_OFF, 1 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + }; BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_BLUE: diff --git a/board/ezkinil/vif_override.xml b/board/ezkinil/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/ezkinil/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/felwinter/battery.c b/board/felwinter/battery.c new file mode 100644 index 0000000000..257d7e8255 --- /dev/null +++ b/board/felwinter/battery.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "compile_time_macros.h" + +/* + * Battery info for all Brya battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + [BATTERY_C536] = { + /* BQ40Z50 Fuel Gauge */ + .fuel_gauge = { + .manuf_name = "AS3GXAE3jB", + .device_name = "C536-49", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x2000, /* XDSG */ + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11800, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C536; diff --git a/board/felwinter/board.c b/board/felwinter/board.c new file mode 100644 index 0000000000..630a8c331a --- /dev/null +++ b/board/felwinter/board.c @@ -0,0 +1,169 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +__override void board_cbi_init(void) +{ + config_usb_db_type(); +} + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S5 -> S3 transition */ +static void board_chipset_startup(void) +{ + pen_config(); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} + +static void board_init(void) +{ + if (ec_cfg_usb_db_type() == DB_USB4_NCT3807) + db_update_usb4_config_from_config(); + + if (ec_cfg_usb_mb_type() == MB_USB4_TBT) + mb_update_usb4_tbt_config_from_config(); + + if (ec_cfg_stylus() == STYLUS_PRSENT) + gpio_enable_interrupt(GPIO_PEN_DET_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/** + * Deferred function to handle pen detect change + */ +static void pendetect_deferred(void) +{ + static int debounced_pen_detect; + int pen_detect = !gpio_get_level(GPIO_PEN_DET_ODL); + + if (pen_detect == debounced_pen_detect) + return; + + debounced_pen_detect = pen_detect; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) + gpio_set_level(GPIO_EN_PP5000_PEN, debounced_pen_detect); +} +DECLARE_DEFERRED(pendetect_deferred); +DECLARE_HOOK(HOOK_INIT, pendetect_deferred, HOOK_PRIO_DEFAULT); + +void pen_detect_interrupt(enum gpio_signal s) +{ + /* Trigger deferred notification of pen detect change */ + hook_call_deferred(&pendetect_deferred_data, 500 * MSEC); +} + +void pen_config(void) +{ + if (ec_cfg_stylus() == STYLUS_PRSENT) { + /* Make sure pen detection is triggered or not at resume */ + if (!gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_EN_PP5000_PEN, 1); + else + gpio_set_level(GPIO_EN_PP5000_PEN, 0); + } +} + +static void board_chipset_shutdown(void) +{ + gpio_set_level(GPIO_EN_PP5000_PEN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); diff --git a/board/felwinter/board.h b/board/felwinter/board.h new file mode 100644 index 0000000000..5327e8fec2 --- /dev/null +++ b/board/felwinter/board.h @@ -0,0 +1,229 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* LED */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 +#define GPIO_PWR_LED_WHITE_L GPIO_LED_1_L +#define GPIO_BAT_LED_AMBER_L GPIO_LED_3_L +#define GPIO_BAT_LED_WHITE_L GPIO_LED_4_L + +/* Sensors */ +#define CONFIG_ACCELGYRO_LSM6DSO /* Base accel */ +#define CONFIG_ACCEL_LSM6DSO_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Lid accel */ +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_ACCEL_LIS2DWL +#define CONFIG_ACCEL_LIS2DW12_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USBC_RETIMER_INTEL_BB + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +/* Disable console commands to help save space */ +#undef CONFIG_CMD_POWERINDEBUG + +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_NX20P3483 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 65000 +#define PD_MAX_CURRENT_MA 3250 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C2_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C2_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C2_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C2_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* + * + */ +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C2_BB_RETIMER_I2C_ADDR 0x58 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 10 + +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_FAN, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_FAN, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { LID_ACCEL = 0, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum ioex_port { IOEX_C2_NCT38XX = 0, IOEX_C1_NCT38XX, IOEX_PORT_COUNT }; + +enum battery_type { BATTERY_C536, BATTERY_TYPE_COUNT }; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +void pen_detect_interrupt(enum gpio_signal s); + +void pen_config(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/felwinter/build.mk b/board/felwinter/build.mk new file mode 100644 index 0000000000..848c76f457 --- /dev/null +++ b/board/felwinter/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger_isl9241.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/felwinter/charger_isl9241.c b/board/felwinter/charger_isl9241.c new file mode 100644 index 0000000000..b86d92965b --- /dev/null +++ b/board/felwinter/charger_isl9241.c @@ -0,0 +1,80 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/felwinter/ec.tasklist b/board/felwinter/ec.tasklist new file mode 100644 index 0000000000..29fd0bf4cb --- /dev/null +++ b/board/felwinter/ec.tasklist @@ -0,0 +1,30 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/felwinter/fans.c b/board/felwinter/fans.c new file mode 100644 index 0000000000..891e8288a9 --- /dev/null +++ b/board/felwinter/fans.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1100, + .rpm_start = 2000, + .rpm_max = 5000, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/181271666): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/felwinter/fw_config.c b/board/felwinter/fw_config.c new file mode 100644 index 0000000000..0a4905bc9d --- /dev/null +++ b/board/felwinter/fw_config.c @@ -0,0 +1,55 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union brya_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brya if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union brya_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_PS8815, + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Brya FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union brya_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void) +{ + return fw_config.usb_db; +} + +enum ec_cfg_usb_mb_type ec_cfg_usb_mb_type(void) +{ + return fw_config.usb_mb; +} + +enum ec_cfg_stylus_type ec_cfg_stylus(void) +{ + return fw_config.stylus; +} diff --git a/board/felwinter/fw_config.h b/board/felwinter/fw_config.h new file mode 100644 index 0000000000..2a8a175efd --- /dev/null +++ b/board/felwinter/fw_config.h @@ -0,0 +1,71 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_BRYA_FW_CONFIG_H_ +#define __BOARD_BRYA_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for felwinter board. + * + * Source of truth is the project/brya/felwinter/config.star configuration file. + */ + +enum ec_cfg_usb_db_type { DB_USB3_PS8815 = 1, DB_USB4_NCT3807 = 2 }; + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_usb_mb_type { MB_USB4_TBT = 0, MB_USB3_NON_TBT = 1 }; + +enum ec_cfg_stylus_type { STYLUS_ABSENT = 0, STYLUS_PRSENT = 1 }; + +union brya_cbi_fw_config { + struct { + enum ec_cfg_usb_db_type usb_db : 3; + uint32_t wifi : 2; + enum ec_cfg_stylus_type stylus : 1; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t thermal : 2; + uint32_t table_mode : 1; + enum ec_cfg_usb_mb_type usb_mb : 3; + uint32_t reserved_1 : 16; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union brya_cbi_fw_config get_fw_config(void); + +/** + * Get the USB daughter board type from FW_CONFIG. + * + * @return the USB daughter board type. + */ +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void); + +/** + * Get the USB main board type from FW_CONFIG. + * + * @return the USB main board type. + */ +enum ec_cfg_usb_mb_type ec_cfg_usb_mb_type(void); + +#endif /* __BOARD_BRYA_FW_CONFIG_H_ */ + +/** + * Get the stylus type from FW_CONFIG. + * + * @return the stylus type. + */ +enum ec_cfg_stylus_type ec_cfg_stylus(void); diff --git a/board/felwinter/gpio.inc b/board/felwinter/gpio.inc new file mode 100644 index 0000000000..df992a18eb --- /dev/null +++ b/board/felwinter/gpio.inc @@ -0,0 +1,154 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_ACCEL_INT_R_L, PIN(8, 1), GPIO_SEL_1P8V | GPIO_INT_FALLING, lis2dw12_interrupt) +GPIO_INT(EC_IMU_INT_R_L, PIN(5, 6), GPIO_SEL_1P8V | GPIO_INT_FALLING, lsm6dso_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(USB_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C2_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C2_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C2_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(PEN_DET_ODL, PIN(D, 4), GPIO_INT_BOTH, pen_detect_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_PP5000_PEN, PIN(E, 1), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_C2_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RST_ODL, PIN(9, 6), GPIO_ODR_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) + +/* LED */ +GPIO(LED_4_L, PIN(6, 0), GPIO_OUT_HIGH) /* battery led white */ +GPIO(LED_3_L, PIN(C, 2), GPIO_OUT_HIGH) /* battery led amber */ +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) /* power led white */ + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(C, 3)) /* GPIOC3 */ +UNUSED(PIN(C, 6)) /* GPIOC6 */ +UNUSED(PIN(6, 2)) /* GPIO62 */ +UNUSED(PIN(B, 1)) /* GPIOB1 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ + +/* Pre-configured PSL balls: J8 K6 */ + + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ + +IOEX(USB_C1_RT_RST_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C1_FRS_EN, EXPIN(IOEX_C1_NCT38XX, 0, 6), GPIO_LOW) + +IOEX(USB_C2_RT_RST_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 7), GPIO_ODR_LOW) +IOEX(USB_C2_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C2_FRS_EN, EXPIN(IOEX_C2_NCT38XX, 0, 6), GPIO_LOW) +/* GPIO07_P2 to PU */ diff --git a/board/felwinter/i2c.c b/board/felwinter/i2c.c new file mode 100644 index 0000000000..81f461a5ba --- /dev/null +++ b/board/felwinter/i2c.c @@ -0,0 +1,78 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc2", + .port = I2C_PORT_USB_C2_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc2", + .port = I2C_PORT_USB_C2_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer2", + .port = I2C_PORT_USB_C2_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/felwinter/keyboard.c b/board/felwinter/keyboard.c new file mode 100644 index 0000000000..cee23af8c3 --- /dev/null +++ b/board/felwinter/keyboard.c @@ -0,0 +1,48 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfe, 0xff, 0xff, 0xff, /* full set */ + }, +}; + +static const struct ec_response_keybd_config felwinter_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &felwinter_kb; +} diff --git a/board/felwinter/led.c b/board/felwinter/led.c new file mode 100644 index 0000000000..2770e7fae8 --- /dev/null +++ b/board/felwinter/led.c @@ -0,0 +1,126 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for felwinter + */ + +#include "chipset.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "system.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_power(enum ec_led_colors color) +{ + if (color == EC_LED_COLOR_WHITE) + gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_ON_LVL); + else + /* LED_OFF and unsupported colors */ + gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_OFF_LVL); +} + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_ON_LVL); + gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_OFF_LVL); + break; + } +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/felwinter/pwm.c b/board/felwinter/pwm.c new file mode 100644 index 0000000000..5023f429cc --- /dev/null +++ b/board/felwinter/pwm.c @@ -0,0 +1,37 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 0); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/felwinter/sensors.c b/board/felwinter/sensors.c new file mode 100644 index 0000000000..4016b12514 --- /dev/null +++ b/board/felwinter/sensors.c @@ -0,0 +1,235 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc_chip.h" +#include "common.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_FAN] = { + .name = "TEMP_FAN", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +static struct stprivate_data g_lis2dw12_data; +static struct lsm6dso_data lsm6dso_data; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +/* TODO(b/184779743): verify orientation matrix */ +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DW12, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_lis2dw12_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DW12_ADDR0, + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void baseboard_sensors_init(void) +{ + /* Enable gpio interrupt for lid accel sensor */ + gpio_enable_interrupt(GPIO_EC_ACCEL_INT_R_L); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_R_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC }, + [TEMP_SENSOR_2_FAN] = { .name = "FAN", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_FAN }, + [TEMP_SENSOR_3_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(60), \ + }, \ + .temp_fan_off = C_TO_K(30), \ + .temp_fan_max = C_TO_K(73), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(60), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(70), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(50), \ + }, \ + .temp_fan_off = C_TO_K(30), \ + .temp_fan_max = C_TO_K(63), \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan = THERMAL_FAN; + +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(60), \ + }, \ + .temp_fan_off = C_TO_K(30), \ + .temp_fan_max = C_TO_K(73), \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_FAN] = THERMAL_FAN, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/felwinter/usbc_config.c b/board/felwinter/usbc_config.c new file mode 100644 index 0000000000..1c93f822c6 --- /dev/null +++ b/board/felwinter/usbc_config.c @@ -0,0 +1,438 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_VCONN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +struct tcpc_config_t tcpc_config_c1 = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, +}; + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM536A0 */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = NX20P3483_ADDR2_FLAGS, + .drv = &nx20p348x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +struct ppc_config_t ppc_chips_c1 = { + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, +}; + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc2_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +/* + * USB3 DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C2] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +static const struct usb_mux_chain usb_muxes_c1 = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, +}; + +static const struct usb_mux_chain usb_muxes_c2 = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C2, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C2_MUX, + .i2c_addr_flags = USBC_PORT_C2_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc2_tcss_usb_mux, +}; + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C1_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C2_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +void config_usb_db_type(void) +{ + enum ec_cfg_usb_db_type db_type = ec_cfg_usb_db_type(); + + /* + * TODO(b/180434685): implement multiple DB types + */ + + CPRINTS("Configured USB DB type number is %d", db_type); +} + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + int rst_signal; + + if (me->usb_port == USBC_PORT_C1) + rst_signal = IOEX_USB_C1_RT_RST_ODL; + else if (me->usb_port == USBC_PORT_C2) + rst_signal = IOEX_USB_C2_RT_RST_ODL; + else + return EC_ERROR_INVAL; + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + gpio_or_ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + gpio_or_ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(GPIO_USB_C0_C2_TCPC_RST_ODL, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + + if (ec_cfg_usb_db_type() == DB_USB4_NCT3807) + gpio_set_level(GPIO_USB_C1_RST_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(GPIO_USB_C0_C2_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + + if (ec_cfg_usb_db_type() == DB_USB4_NCT3807) + gpio_set_level(GPIO_USB_C1_RST_ODL, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void enable_ioex(int ioex) +{ + ioex_init(ioex); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C2 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + if (ec_cfg_usb_db_type() == DB_USB4_NCT3807) + enable_ioex(IOEX_C1_NCT38XX); + enable_ioex(IOEX_C2_NCT38XX); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C2) + return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C2); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C2_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C1_PPC_INT_ODL: + switch (ec_cfg_usb_db_type()) { + case DB_USB3_PS8815: + nx20p348x_interrupt(USBC_PORT_C1); + break; + case DB_USB4_NCT3807: + syv682x_interrupt(USBC_PORT_C1); + break; + } + break; + case GPIO_USB_C2_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C2; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + if (((port == USBC_PORT_C2) && (ec_cfg_usb_mb_type() == MB_USB4_TBT)) || + ((port == USBC_PORT_C1) && + (ec_cfg_usb_db_type() == DB_USB4_NCT3807))) + return true; + + return false; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} + +void db_update_usb4_config_from_config(void) +{ + tcpc_config[USBC_PORT_C1] = tcpc_config_c1; + ppc_chips[USBC_PORT_C1] = ppc_chips_c1; + usb_muxes[USBC_PORT_C1] = usb_muxes_c1; +} + +void mb_update_usb4_tbt_config_from_config(void) +{ + usb_muxes[USBC_PORT_C2] = usb_muxes_c2; +} diff --git a/board/felwinter/usbc_config.h b/board/felwinter/usbc_config.h new file mode 100644 index 0000000000..cab32351f5 --- /dev/null +++ b/board/felwinter/usbc_config.h @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPC_RUNTIME_CONFIG +#define CONFIG_USB_MUX_RUNTIME_CONFIG + +enum usbc_port { USBC_PORT_C2 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void config_usb_db_type(void); +void db_update_usb4_config_from_config(void); +void mb_update_usb4_tbt_config_from_config(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/felwinter/vif_override.xml b/board/felwinter/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/felwinter/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/fennel/battery.c b/board/fennel/battery.c index cfd17a136f..882ff0c5a2 100644 --- a/board/fennel/battery.c +++ b/board/fennel/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/fennel/board.c b/board/fennel/board.c index 799255712d..f650911ba0 100644 --- a/board/fennel/board.c +++ b/board/fennel/board.c @@ -1,10 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" #include "charge_manager.h" @@ -16,6 +15,8 @@ #include "console.h" #include "driver/accel_lis2dw12.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" #include "driver/battery/max17055.h" #include "driver/bc12/pi3usb9201.h" #include "driver/charger/isl923x.h" @@ -29,9 +30,10 @@ #include "i2c.h" #include "i2c_bitbang.h" #include "it8801.h" -#include "keyboard_scan.h" #include "keyboard_backlight.h" +#include "keyboard_scan.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "registers.h" @@ -39,41 +41,55 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { schedule_deferred_pd_interrupt(0 /* port */); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct i2c_port_t i2c_bitbang_ports[] = { - {"battery", 2, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA, .drv = &bitbang_drv}, + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, }; const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); @@ -81,13 +97,13 @@ const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * TODO(b/133200075): Tune this once we have the final performance * out of the driver and the i2c bus. @@ -106,8 +122,8 @@ struct keyboard_scan_config keyscan_config = { struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { [0] = { - .i2c_host_port = I2C_PORT_IO_EXPANDER_IT8801, - .i2c_slave_addr = IT8801_I2C_ADDR, + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, .drv = &it8801_ioexpander_drv, }, }; @@ -132,15 +148,18 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -static void board_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -148,13 +167,16 @@ static void board_hpd_status(const struct usb_mux *me, host_set_single_event(EC_HOST_EVENT_USB_MUX); } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, }, }; @@ -200,7 +222,7 @@ int board_set_active_charge_port(int charge_port) if (board_vbus_source_enabled(charge_port)) return -1; break; - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -208,22 +230,11 @@ int board_set_active_charge_port(int charge_port) */ charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - int board_discharge_on_ac(int enable) { int ret, port; @@ -253,7 +264,7 @@ int pd_snk_is_vbus_provided(int port) void bc12_interrupt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } #ifndef VARIANT_KUKUI_NO_SENSORS @@ -273,13 +284,12 @@ static void board_spi_enable(void) STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; /* Reinitialize spi peripheral. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); /* Pin mux spi peripheral toward the sensor. */ - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_spi_enable, +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, MOTION_SENSE_HOOK_PRIO - 1); static void board_spi_disable(void) @@ -287,14 +297,16 @@ static void board_spi_disable(void) /* Set pins to a state calming the sensor down. */ gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); - gpio_config_module(MODULE_SPI_MASTER, 0); + /* Pull SPI_NSS pin to low to prevent a leakage. */ + gpio_set_flags(GPIO_EC_SENSOR_SPI_NSS, GPIO_OUT_LOW); + gpio_set_level(GPIO_EC_SENSOR_SPI_NSS, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); /* Disable spi peripheral and clocks. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_spi_disable, +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, MOTION_SENSE_HOOK_PRIO + 1); #endif /* !VARIANT_KUKUI_NO_SENSORS */ @@ -333,23 +345,74 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Rotation matrixes */ -static const mat33_fp_t base_standard_ref = { - {0, FLOAT_TO_FP(1), 0}, - {FLOAT_TO_FP(-1), 0, 0}, - {0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -static const mat33_fp_t lid_standard_ref = { - {FLOAT_TO_FP(-1), 0, 0}, - {0, FLOAT_TO_FP(1), 0}, - {0, 0, FLOAT_TO_FP(-1) } -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* sensor private data */ /* Lid accel private data */ static struct stprivate_data g_lis2dwl_data; /* Base accel private data */ static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm42607_data; + +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI160 = 1, + BASE_GYRO_ICM426XX = 2, +}; + +static enum base_accelgyro_type base_accelgyro_config; + +struct motion_sensor_t icm42607_base_accel = { + .name = "Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = NULL, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm42607_base_gyro = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .default_range = 1000, /* dps */ + .rot_standard_ref = NULL, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -393,9 +456,9 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .rot_standard_ref = &base_standard_ref, - .default_range = 2, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, .config = { @@ -421,7 +484,7 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_GYRO_MIN_FREQ, @@ -430,8 +493,54 @@ struct motion_sensor_t motion_sensors[] = { }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +static void board_detect_motionsensor(void) +{ + int ret; + int val; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + if (base_accelgyro_config != BASE_GYRO_NONE) + return; + /* Check base accelgyro chip */ + ret = icm_read8(&icm42607_base_accel, ICM42607_REG_WHO_AM_I, &val); + if (ret) + ccprints("Get ICM fail."); + if (val == ICM42607_CHIP_ICM42607P) { + motion_sensors[BASE_ACCEL] = icm42607_base_accel; + motion_sensors[BASE_GYRO] = icm42607_base_gyro; + } + base_accelgyro_config = (val == ICM42607_CHIP_ICM42607P) ? + BASE_GYRO_ICM426XX : + BASE_GYRO_BMI160; + ccprints("BASE Accelgyro: %s", + (val == ICM42607_CHIP_ICM42607P) ? "ICM42607" : "BMI160"); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); +/* + * board_spi_enable() will be called in the board_init() when sysjump to rw + * the board_init() is DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT) + * the board_detect_motionsensor() reads data via sensor SPI + * so the priority of board_detect_motionsensor should be HOOK_PRIO_DEFAULT+1 + */ +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_DEFAULT + 1); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_accelgyro_config) { + case BASE_GYRO_ICM426XX: + icm42607_interrupt(signal); + break; + case BASE_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + const struct it8801_pwm_t it8801_pwm_channels[] = { - [IT8801_PWM_CH_KBLIGHT] = {.index = 4}, + [IT8801_PWM_CH_KBLIGHT] = { .index = 4 }, }; void board_kblight_init(void) @@ -444,12 +553,41 @@ bool board_has_kb_backlight(void) /* Default enable keyboard backlight */ return true; } +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + +/* Battery functions */ +#define SB_SMARTCHARGE 0x26 +/* Quick charge enable bit */ +#define SMART_QUICK_CHARGE 0x02 +/* Quick charge support bit */ +#define MODE_QUICK_CHARGE_SUPPORT 0x01 + +static void sb_quick_charge_mode(int enable) +{ + int val, rv; + + rv = sb_read(SB_SMARTCHARGE, &val); + if (rv || !(val & MODE_QUICK_CHARGE_SUPPORT)) + return; + + if (enable) + val |= SMART_QUICK_CHARGE; + else + val &= ~SMART_QUICK_CHARGE; + + sb_write(SB_SMARTCHARGE, val); +} /* Called on AP S0iX -> S0 transition */ static void board_chipset_resume(void) { +#ifndef VARIANT_KUKUI_NO_SENSORS if (board_has_kb_backlight()) ioex_set_level(IOEX_KB_BL_EN, 1); +#endif + + /* Normal charge mode */ + sb_quick_charge_mode(0); } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); DECLARE_HOOK(HOOK_INIT, board_chipset_resume, HOOK_PRIO_DEFAULT); @@ -457,13 +595,16 @@ DECLARE_HOOK(HOOK_INIT, board_chipset_resume, HOOK_PRIO_DEFAULT); /* Called on AP S0 -> S0iX transition */ static void board_chipset_suspend(void) { +#ifndef VARIANT_KUKUI_NO_SENSORS if (board_has_kb_backlight()) ioex_set_level(IOEX_KB_BL_EN, 0); +#endif + + /* Quick charge mode */ + sb_quick_charge_mode(1); } DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); -#endif /* !VARIANT_KUKUI_NO_SENSORS */ - /* Called on AP S5 -> S3 transition */ static void board_chipset_startup(void) { @@ -490,8 +631,8 @@ int board_get_battery_i2c(void) } #ifdef SECTION_IS_RW -static int it8801_get_target_channel(enum pwm_channel *channel, - int type, int index) +static int it8801_get_target_channel(enum pwm_channel *channel, int type, + int index) { switch (type) { case EC_PWM_TYPE_GENERIC: @@ -514,14 +655,13 @@ host_command_pwm_set_duty(struct host_cmd_handler_args *args) if (it8801_get_target_channel(&channel, p->pwm_type, p->index)) return EC_RES_INVALID_PARAM; - duty = (uint32_t) p->duty * 255 / 65535; + duty = (uint32_t)p->duty * 255 / 65535; it8801_pwm_set_raw_duty(channel, duty); it8801_pwm_enable(channel, p->duty > 0); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_DUTY, - host_command_pwm_set_duty, +DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_DUTY, host_command_pwm_set_duty, EC_VER_MASK(0)); static enum ec_status @@ -535,12 +675,11 @@ host_command_pwm_get_duty(struct host_cmd_handler_args *args) if (it8801_get_target_channel(&channel, p->pwm_type, p->index)) return EC_RES_INVALID_PARAM; - r->duty = (uint32_t) it8801_pwm_get_raw_duty(channel) * 65535 / 255; + r->duty = (uint32_t)it8801_pwm_get_raw_duty(channel) * 65535 / 255; args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_DUTY, - host_command_pwm_get_duty, +DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_DUTY, host_command_pwm_get_duty, EC_VER_MASK(0)); #endif diff --git a/board/fennel/board.h b/board/fennel/board.h index aaf863206a..e00c37c4e9 100644 --- a/board/fennel/board.h +++ b/board/fennel/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,7 +11,8 @@ #define VARIANT_KUKUI_JACUZZI #define VARIANT_KUKUI_BATTERY_SMART #define VARIANT_KUKUI_CHARGER_ISL9238 - +#define VARIANT_KUKUI_EC_STM32F098 +#undef CONFIG_CMD_MFALLOW #ifndef SECTION_IS_RW #define VARIANT_KUKUI_NO_SENSORS #endif /* SECTION_IS_RW */ @@ -25,6 +26,8 @@ #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_RUNTIME_CONFIG @@ -48,24 +51,24 @@ #define CONFIG_USB_MUX_IT5205 #define CONFIG_LED_ONOFF_STATES -#define CONFIG_LED_POWER_LED /* Motion Sensors */ #ifndef VARIANT_KUKUI_NO_SENSORS -#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ #define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM42607 /* Base accel second source*/ +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) #define CONFIG_ALS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL -#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) - #ifdef SECTION_IS_RW #define CONFIG_IO_EXPANDER_IT8801_PWM #define CONFIG_KEYBOARD_BACKLIGHT @@ -74,25 +77,24 @@ #endif /* VARIANT_KUKUI_NO_SENSORS */ /* I2C ports */ -#define I2C_PORT_BC12 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_CHARGER board_get_charger_i2c() -#define I2C_PORT_SENSORS 1 -#define I2C_PORT_IO_EXPANDER_IT8801 1 -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY -#define I2C_PORT_BATTERY 2 +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_CHARGER board_get_charger_i2c() +#define I2C_PORT_SENSORS 1 +#define I2C_PORT_KB_DISCRETE 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BATTERY 2 + +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -/* Define the MKBP events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) #ifndef __ASSEMBLER__ @@ -146,7 +148,7 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void bc12_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); +void motion_interrupt(enum gpio_signal signal); /* returns the i2c port number of charger/battery */ int board_get_charger_i2c(void); diff --git a/board/fennel/build.mk b/board/fennel/build.mk index a6e1c010d7..f583684804 100644 --- a/board/fennel/build.mk +++ b/board/fennel/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/fennel/ec.tasklist b/board/fennel/ec.tasklist index c1330b86f8..fb131b8eb4 100644 --- a/board/fennel/ec.tasklist +++ b/board/fennel/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/fennel/gpio.inc b/board/fennel/gpio.inc index 3dccd94506..5ebecfac53 100644 --- a/board/fennel/gpio.inc +++ b/board/fennel/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,7 +22,7 @@ GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, chipset_reset_request_interrupt) GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, - bmi160_interrupt) + motion_interrupt) GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, emmc_cmd_interrupt) GPIO_INT(SPI1_NSS, PIN(A, 15), GPIO_INT_BOTH | GPIO_PULL_UP, @@ -117,5 +117,5 @@ ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) /* EMMC SPI SLAVE: PB13/14/15 */ ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) /* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ -ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_MASTER, 0) -ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/fennel/led.c b/board/fennel/led.c index 69b9fcfe97..60fadc3eb0 100644 --- a/board/fennel/led.c +++ b/board/fennel/led.c @@ -1,51 +1,58 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Fennel */ #include "common.h" -#include "ioexpander.h" #include "driver/ioexpander/it8801.h" #include "ec_commands.h" +#include "ioexpander.h" #include "led_common.h" #include "led_onoff_states.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 97; +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 97; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_GREEN: @@ -67,7 +74,7 @@ void led_set_color_battery(enum ec_led_colors color) } } -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: diff --git a/board/fennel/vif_override.xml b/board/fennel/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/fennel/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/fizz/board.c b/board/fizz/board.c index b3627afa7b..5eaa09efec 100644 --- a/board/fizz/board.c +++ b/board/fizz/board.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,26 +6,26 @@ /* Fizz board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "als.h" #include "battery.h" #include "bd99992gw.h" #include "board_config.h" #include "button.h" +#include "cec.h" #include "charge_manager.h" #include "charge_state.h" #include "charger.h" #include "chipset.h" #include "console.h" #include "cros_board_info.h" +#include "driver/cec/bitbang.h" #include "driver/pmic_tps650x30.h" -#include "driver/temp_sensor/tmp432.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" +#include "driver/temp_sensor/tmp432.h" #include "espi.h" #include "extpower.h" -#include "espi.h" #include "fan.h" #include "fan_chip.h" #include "gpio.h" @@ -51,8 +51,8 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static uint16_t board_version; static uint8_t oem; @@ -63,7 +63,7 @@ static void tcpc_alert_event(enum gpio_signal signal) schedule_deferred_pd_interrupt(0 /* port */); } -#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ /* * ADP_IN pin state. It's initialized to 1 (=unplugged) because the IRQ won't * be triggered if BJ is the power source. @@ -115,6 +115,7 @@ void vbus0_evt(enum gpio_signal signal) task_wake(TASK_ID_PD_C0); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Hibernate wake configuration */ @@ -126,7 +127,8 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* ADC channels */ const struct adc_t adc_channels[] = { /* Vbus sensing (1/10 voltage divider). */ - [ADC_VBUS] = {"VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -134,7 +136,7 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_FAN_PWR_EN, }; @@ -159,20 +161,49 @@ BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* I2C port map */ -const struct i2c_port_t i2c_ports[] = { - {"tcpc", NPCX_I2C_PORT0_0, 400, GPIO_I2C0_0_SCL, GPIO_I2C0_0_SDA}, - {"eeprom", NPCX_I2C_PORT0_1, 400, GPIO_I2C0_1_SCL, GPIO_I2C0_1_SDA}, - {"charger", NPCX_I2C_PORT1, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"pmic", NPCX_I2C_PORT2, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"thermal", NPCX_I2C_PORT3, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "tcpc", + .port = NPCX_I2C_PORT0_0, + .kbps = 400, + .scl = GPIO_I2C0_0_SCL, + .sda = GPIO_I2C0_0_SDA }, + { .name = "eeprom", + .port = NPCX_I2C_PORT0_1, + .kbps = 400, + .scl = GPIO_I2C0_1_SCL, + .sda = GPIO_I2C0_1_SDA }, + { .name = "charger", + .port = NPCX_I2C_PORT1, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "pmic", + .port = NPCX_I2C_PORT2, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "thermal", + .port = NPCX_I2C_PORT3, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + /* TCPC mux configuration */ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { { @@ -192,21 +223,19 @@ static int ps8751_tune_mux(const struct usb_mux *me) return EC_SUCCESS; } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .board_init = &ps8751_tune_mux, - } -}; +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .board_init = &ps8751_tune_mux, + }, +} }; const int usb_port_enable[USB_PORT_COUNT] = { - GPIO_USB1_ENABLE, - GPIO_USB2_ENABLE, - GPIO_USB3_ENABLE, - GPIO_USB4_ENABLE, - GPIO_USB5_ENABLE, + GPIO_USB1_ENABLE, GPIO_USB2_ENABLE, GPIO_USB3_ENABLE, + GPIO_USB4_ENABLE, GPIO_USB5_ENABLE, }; void board_reset_pd_mcu(void) @@ -240,9 +269,10 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); uint16_t tcpc_get_alert_status(void) { @@ -264,10 +294,10 @@ uint16_t tcpc_get_alert_status(void) * src/mainboard/google/${board}/acpi/dptf.asl */ const struct temp_sensor_t temp_sensors[] = { - {"TMP431_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_LOCAL}, - {"TMP431_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE1}, + { "TMP431_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_LOCAL }, + { "TMP431_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE1 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -275,14 +305,18 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); * Thermal limits for each temp sensor. All temps are in degrees K. Must be in * same order as enum temp_sensor_id. To always ignore any temp, use 0. */ +static const int temp_fan_off = C_TO_K(25); +static const int temp_fan_max = C_TO_K(50); struct ec_thermal_config thermal_params[] = { /* {Twarn, Thigh, Thalt}, * {Twarn, Thigh, X }, * fan_off, fan_max */ - {{0, C_TO_K(80), C_TO_K(81)}, {0, C_TO_K(78), 0}, - C_TO_K(4), C_TO_K(76)}, /* TMP431_Internal */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* TMP431_Sensor_1 */ + { { 0, C_TO_K(80), C_TO_K(81) }, + { 0, C_TO_K(78), 0 }, + temp_fan_off, + temp_fan_max }, /* TMP431_Internal */ + { { 0, 0, 0 }, { 0, 0, 0 }, 0, 0 }, /* TMP431_Sensor_1 */ }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -491,8 +525,8 @@ static void set_charge_limit(int charge_ma) } } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { int p87w = 0, p65w = 0, p60w = 0; @@ -503,11 +537,11 @@ void board_set_charge_limit(int port, int supplier, int charge_ma, * is called. */ led_alert(charge_ma * charge_mv < - CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); /* * In terms of timing, this should always work because - * HOOK_PRIO_CHARGE_MANAGER_INIT is notified after HOOK_PRIO_INIT_I2C. + * HOOK_PRIO_INIT_CHARGE_MANAGER is notified after HOOK_PRIO_INIT_I2C. * If CBI isn't initialized or contains invalid data, we assume it's * a new board. */ @@ -550,11 +584,11 @@ void board_set_charge_limit(int port, int supplier, int charge_ma, } else { /* * TODO:http://crosbug.com/p/65013352. - * The current monitoring system doesn't support lower - * current. These currents are most likely not enough to - * power the system. However, if they're needed, EC can - * monitor PMON_PSYS and trigger H_PROCHOT by itself. - */ + * The current monitoring system doesn't support lower + * current. These currents are most likely not enough to + * power the system. However, if they're needed, EC can + * monitor PMON_PSYS and trigger H_PROCHOT by itself. + */ p60w = 1; CPRINTS("Current %dmA not supported", charge_ma); } @@ -572,60 +606,105 @@ int64_t get_time_dsw_pwrok(void) } const struct pwm_t pwm_channels[] = { - [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, [PWM_CH_LED_GREEN] = { 5, PWM_CONFIG_DSLEEP, 100 }, - [PWM_CH_FAN] = {4, PWM_CONFIG_OPEN_DRAIN, 25000}, + [PWM_CH_FAN] = { 4, PWM_CONFIG_OPEN_DRAIN, 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -struct fan_step { - int on; - int off; - int rpm; +static const struct fan_step_1_1 *fan_table; + +static const struct fan_step_1_1 fan_table0[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(25), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(34), + .rpm = 2800 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(39), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .rpm = 3200 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .rpm = 3400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .rpm = 4200 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .rpm = 4800 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(45), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(47), + .rpm = 5200 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(47), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .rpm = 5600 }, }; - -static const struct fan_step *fan_table; - -/* Note: Do not make the fan on/off point equal to 0 or 100 */ -static const struct fan_step fan_table0[] = { - {.on = 0, .off = 1, .rpm = 0}, - {.on = 36, .off = 1, .rpm = 2800}, - {.on = 58, .off = 58, .rpm = 3200}, - {.on = 66, .off = 61, .rpm = 3400}, - {.on = 75, .off = 69, .rpm = 4200}, - {.on = 81, .off = 76, .rpm = 4800}, - {.on = 88, .off = 83, .rpm = 5200}, - {.on = 98, .off = 91, .rpm = 5600}, +static const struct fan_step_1_1 fan_table1[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(25), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(34), + .rpm = 2800 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(39), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .rpm = 3200 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .rpm = 3400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .rpm = 4200 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .rpm = 4800 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(45), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(47), + .rpm = 5200 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(47), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .rpm = 5600 }, }; -static const struct fan_step fan_table1[] = { - {.on = 0, .off = 1, .rpm = 0}, - {.on = 36, .off = 1, .rpm = 2800}, - {.on = 62, .off = 58, .rpm = 3200}, - {.on = 68, .off = 63, .rpm = 3400}, - {.on = 75, .off = 69, .rpm = 4200}, - {.on = 81, .off = 76, .rpm = 4800}, - {.on = 88, .off = 83, .rpm = 5200}, - {.on = 98, .off = 91, .rpm = 5600}, +static const struct fan_step_1_1 fan_table2[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(25), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(34), + .rpm = 2200 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(39), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(41), + .rpm = 2900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(41), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(43), + .rpm = 3000 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .rpm = 3300 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .rpm = 3600 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(45), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(47), + .rpm = 3900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(47), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .rpm = 5000 }, }; -static const struct fan_step fan_table2[] = { - {.on = 0, .off = 1, .rpm = 0}, - {.on = 36, .off = 1, .rpm = 2200}, - {.on = 63, .off = 56, .rpm = 2900}, - {.on = 69, .off = 65, .rpm = 3000}, - {.on = 75, .off = 70, .rpm = 3300}, - {.on = 80, .off = 76, .rpm = 3600}, - {.on = 87, .off = 81, .rpm = 3900}, - {.on = 98, .off = 91, .rpm = 5000}, -}; -static const struct fan_step fan_table3[] = { - {.on = 0, .off = 1, .rpm = 0}, - {.on = 36, .off = 22, .rpm = 2500}, - {.on = 54, .off = 49, .rpm = 3200}, - {.on = 61, .off = 56, .rpm = 3500}, - {.on = 68, .off = 63, .rpm = 3900}, - {.on = 75, .off = 69, .rpm = 4500}, - {.on = 82, .off = 76, .rpm = 5100}, - {.on = 92, .off = 85, .rpm = 5400}, +static const struct fan_step_1_1 fan_table3[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(30), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(34), + .rpm = 2500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(37), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(39), + .rpm = 3200 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(39), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .rpm = 3500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .rpm = 3900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .rpm = 4500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .rpm = 5100 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .rpm = 5400 }, }; /* All fan tables must have the same number of levels */ #define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) @@ -718,8 +797,8 @@ static void setup_bj(void) switch (oem) { case OEM_KENCH: - bj = (BJ_ADAPTER_90W_MASK & BIT(sku)) ? - BJ_90W_19P5V : BJ_65W_19P5V; + bj = (BJ_ADAPTER_90W_MASK & BIT(sku)) ? BJ_90W_19P5V : + BJ_65W_19P5V; break; case OEM_TEEMO: case OEM_BLEEMO: @@ -728,15 +807,14 @@ static void setup_bj(void) case OEM_WUKONG_A: case OEM_WUKONG_M: case OEM_EXCELSIOR: - bj = (BJ_ADAPTER_90W_MASK & BIT(sku)) ? - BJ_90W_19V : BJ_65W_19V; + bj = (BJ_ADAPTER_90W_MASK & BIT(sku)) ? BJ_90W_19V : BJ_65W_19V; break; case OEM_JAX: bj = BJ_65W_19V; break; default: - bj = (BJ_ADAPTER_90W_MASK & BIT(sku)) ? - BJ_90W_19P5V : BJ_65W_19P5V; + bj = (BJ_ADAPTER_90W_MASK & BIT(sku)) ? BJ_90W_19P5V : + BJ_65W_19P5V; break; } @@ -765,8 +843,8 @@ static void board_charge_manager_init(void) charge_manager_update_charge(j, i, NULL); } - port = gpio_get_level(GPIO_ADP_IN_L) ? - CHARGE_PORT_TYPEC0 : CHARGE_PORT_BARRELJACK; + port = gpio_get_level(GPIO_ADP_IN_L) ? CHARGE_PORT_TYPEC0 : + CHARGE_PORT_BARRELJACK; CPRINTS("Power source is p%d (%s)", port, port == CHARGE_PORT_TYPEC0 ? "USB-C" : "BJ"); @@ -781,7 +859,7 @@ static void board_charge_manager_init(void) } } DECLARE_HOOK(HOOK_INIT, board_charge_manager_init, - HOOK_PRIO_CHARGE_MANAGER_INIT + 1); + HOOK_PRIO_INIT_CHARGE_MANAGER + 1); static void board_init(void) { @@ -792,43 +870,8 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -int fan_percent_to_rpm(int fan, int pct) +int fan_percent_to_rpm(int fan, int temp_ratio) { - static int current_level; - static int previous_pct; - int i; - - /* - * Compare the pct and previous pct, we have the three paths : - * 1. decreasing path. (check the off point) - * 2. increasing path. (check the on point) - * 3. invariant path. (return the current RPM) - */ - if (pct < previous_pct) { - for (i = current_level; i >= 0; i--) { - if (pct <= fan_table[i].off) - current_level = i - 1; - else - break; - } - } else if (pct > previous_pct) { - for (i = current_level + 1; i < NUM_FAN_LEVELS; i++) { - if (pct >= fan_table[i].on) - current_level = i; - else - break; - } - } - - if (current_level < 0) - current_level = 0; - - previous_pct = pct; - - if (fan_table[current_level].rpm != - fan_get_rpm_target(FAN_CH(fan))) - cprints(CC_THERMAL, "Setting fan RPM to %d", - fan_table[current_level].rpm); - - return fan_table[current_level].rpm; + return temp_ratio_to_rpm_hysteresis(fan_table, NUM_FAN_LEVELS, fan, + temp_ratio, NULL); } diff --git a/board/fizz/board.h b/board/fizz/board.h index 209fe29dfe..b10c7d8407 100644 --- a/board/fizz/board.h +++ b/board/fizz/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,7 +12,7 @@ * Allow dangerous commands. * TODO: Remove this config before production. */ -#undef CONFIG_SYSTEM_UNLOCKED +#undef CONFIG_SYSTEM_UNLOCKED #define CONFIG_USB_PD_COMM_LOCKED /* EC */ @@ -21,18 +21,19 @@ #define CONFIG_BOARD_HAS_RTC_RESET #define CONFIG_CRC8 #define CONFIG_CEC -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CEC_BITBANG +#define CONFIG_CBI_EEPROM #define CONFIG_DEDICATED_RECOVERY_BUTTON #define CONFIG_EMULATED_SYSRQ #define CONFIG_LED_COMMON -#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_USE_HOST_EVENT #define CONFIG_DPTF -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#undef CONFIG_LID_SWITCH +#define CONFIG_I2C_CONTROLLER +#undef CONFIG_LID_SWITCH #define CONFIG_POWER_BUTTON_IGNORE_LID #define CONFIG_PWM #define CONFIG_LTO @@ -47,7 +48,7 @@ #define WIRELESS_GPIO_WLAN_POWER GPIO_PP3300_DX_WLAN #define WIRELESS_GPIO_WWAN GPIO_PP3300_DX_LTE #define CEC_GPIO_OUT GPIO_CEC_OUT -#define CEC_GPIO_IN GPIO_CEC_IN +#define CEC_GPIO_IN GPIO_CEC_IN #define CEC_GPIO_PULL_UP GPIO_CEC_PULL_UP #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED @@ -57,20 +58,23 @@ #define CONFIG_THROTTLE_AP #define CONFIG_CHIPSET_CAN_THROTTLE #define CONFIG_PWM -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY /* EC console commands */ #define CONFIG_CMD_BUTTON +#undef CONFIG_CMD_ADC + +/* Reduce flash space usage */ +#undef CONFIG_CONSOLE_CMDHELP /* SOC */ #define CONFIG_CHIPSET_SKYLAKE #define CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET #define CONFIG_CHIPSET_HAS_PRE_INIT_CALLBACK #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD /* Charger */ #define CONFIG_CHARGE_MANAGER @@ -79,7 +83,7 @@ #define CONFIG_HOSTCMD_PD_CONTROL #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#undef CONFIG_EXTPOWER_DEBOUNCE_MS #define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 @@ -93,7 +97,7 @@ #define CONFIG_TEMP_SENSOR_TMP432 /* USB */ -#undef CONFIG_USB_CHARGER /* dnojiri: verify */ +#undef CONFIG_USB_CHARGER /* dnojiri: verify */ #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_CUSTOM_PDO @@ -116,7 +120,7 @@ #define CONFIG_USBC_VCONN_SWAP /* Charge ports */ -#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT #define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 #define DEDICATED_CHARGE_PORT 1 @@ -125,21 +129,21 @@ #define USB_PORT_COUNT 5 /* Optional feature to configure npcx chip */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ -#define NPCX_TACH_SEL2 1 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ +#define NPCX_TACH_SEL2 1 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ /* I2C ports */ -#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT0_1 -#define I2C_PORT_BATTERY NPCX_I2C_PORT1 -#define I2C_PORT_CHARGER NPCX_I2C_PORT1 -#define I2C_PORT_PMIC NPCX_I2C_PORT2 -#define I2C_PORT_THERMAL NPCX_I2C_PORT3 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT0_1 +#define I2C_PORT_BATTERY NPCX_I2C_PORT1 +#define I2C_PORT_CHARGER NPCX_I2C_PORT1 +#define I2C_PORT_PMIC NPCX_I2C_PORT2 +#define I2C_PORT_THERMAL NPCX_I2C_PORT3 /* I2C addresses */ -#define I2C_ADDR_TCPC0_FLAGS 0x0b -#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_ADDR_TCPC0_FLAGS 0x0b +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* Verify and jump to RW image on boot */ #define CONFIG_VBOOT_EFS @@ -156,18 +160,17 @@ * end of RW_A and RW_B, respectively. */ #define CONFIG_RW_B -#define CONFIG_RW_B_MEM_OFF CONFIG_RO_MEM_OFF -#undef CONFIG_RO_SIZE -#define CONFIG_RO_SIZE (CONFIG_FLASH_SIZE / 4) -#undef CONFIG_RW_SIZE -#define CONFIG_RW_SIZE CONFIG_RO_SIZE -#define CONFIG_RW_A_STORAGE_OFF CONFIG_RW_STORAGE_OFF -#define CONFIG_RW_B_STORAGE_OFF (CONFIG_RW_A_STORAGE_OFF + \ - CONFIG_RW_SIZE) -#define CONFIG_RW_A_SIGN_STORAGE_OFF (CONFIG_RW_A_STORAGE_OFF + \ - CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) -#define CONFIG_RW_B_SIGN_STORAGE_OFF (CONFIG_RW_B_STORAGE_OFF + \ - CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) +#define CONFIG_RW_B_MEM_OFF CONFIG_RO_MEM_OFF +#undef CONFIG_RO_SIZE +#define CONFIG_RO_SIZE (CONFIG_FLASH_SIZE_BYTES / 4) +#undef CONFIG_RW_SIZE +#define CONFIG_RW_SIZE CONFIG_RO_SIZE +#define CONFIG_RW_A_STORAGE_OFF CONFIG_RW_STORAGE_OFF +#define CONFIG_RW_B_STORAGE_OFF (CONFIG_RW_A_STORAGE_OFF + CONFIG_RW_SIZE) +#define CONFIG_RW_A_SIGN_STORAGE_OFF \ + (CONFIG_RW_A_STORAGE_OFF + CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) +#define CONFIG_RW_B_SIGN_STORAGE_OFF \ + (CONFIG_RW_B_STORAGE_OFF + CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) #define CONFIG_RWSIG #define CONFIG_RWSIG_TYPE_RWSIG @@ -193,15 +196,12 @@ enum charge_port { }; enum temp_sensor_id { - TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ - TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ + TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ + TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ TEMP_SENSOR_COUNT }; -enum adc_channel { - ADC_VBUS, - ADC_CH_COUNT -}; +enum adc_channel { ADC_VBUS, ADC_CH_COUNT }; enum pwm_channel { PWM_CH_LED_RED, @@ -223,6 +223,8 @@ enum mft_channel { MFT_CH_COUNT }; +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + enum OEM_ID { OEM_KENCH = 0, OEM_TEEMO = 1, @@ -242,18 +244,17 @@ enum OEM_ID { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power. Since Fizz doesn't have a battery to charge, * we're not interested in any power lower than the AP power-on threshold. */ -#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON -#define PD_MAX_POWER_MW 100000 -#define PD_MAX_CURRENT_MA 5000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 /* Board specific handlers */ void board_reset_pd_mcu(void); diff --git a/board/fizz/build.mk b/board/fizz/build.mk index 74094ac834..b07b1b4cf3 100644 --- a/board/fizz/build.mk +++ b/board/fizz/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,5 +10,5 @@ CHIP:=npcx CHIP_VARIANT:=npcx5m6g board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_pdo.o board-y+=led.o diff --git a/board/fizz/ec.tasklist b/board/fizz/ec.tasklist index 75a09a43df..6212516e6a 100644 --- a/board/fizz/ec.tasklist +++ b/board/fizz/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/fizz/gpio.inc b/board/fizz/gpio.inc index 7da0bfce71..2eee02bfd3 100644 --- a/board/fizz/gpio.inc +++ b/board/fizz/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,10 +13,10 @@ GPIO_INT(AC_PRESENT, PIN(C, 1), GPIO_INT_BOTH, extpower_interrupt) GPIO_INT(POWER_BUTTON_L, PIN(0, 4), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) /* MECH_PWR_BTN_ODL */ GPIO_INT(PCH_SLP_S0_L, PIN(7, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(PCH_SLP_S3_L, PIN(7, 3), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(PCH_SLP_S4_L, PIN(8, 6), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PCH_SLP_SUS_L, PIN(6, 2), GPIO_INT_BOTH, power_signal_interrupt) diff --git a/board/fizz/led.c b/board/fizz/led.c index 9b6942d241..acd0eb5918 100644 --- a/board/fizz/led.c +++ b/board/fizz/led.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -15,7 +15,7 @@ #include "timer.h" #include "util.h" -const enum ec_led_id supported_led_ids[] = {EC_LED_ID_POWER_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); enum led_color { @@ -76,9 +76,9 @@ static int set_color(enum ec_led_id id, enum led_color color, int duty) } } -#define LED_PULSE_US (2 * SECOND) +#define LED_PULSE_US (2 * SECOND) /* 40 msec for nice and smooth transition. */ -#define LED_PULSE_TICK_US (40 * MSEC) +#define LED_PULSE_TICK_US (40 * MSEC) /* When pulsing is enabled, brightness is incremented by every * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented @@ -181,7 +181,7 @@ void led_critical(void) set_color(EC_LED_ID_POWER_LED, LED_RED, 100); } -static int command_led(int argc, char **argv) +static int command_led(int argc, const char **argv) { enum ec_led_id id = EC_LED_ID_POWER_LED; diff --git a/board/fizz/usb_pd_pdo.c b/board/fizz/usb_pd_pdo.c new file mode 100644 index 0000000000..edcc43f15a --- /dev/null +++ b/board/fizz/usb_pd_pdo.c @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +#define PDO_FIXED_FLAGS \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_COMM_CAP) + +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_BATT(4750, 21000, 50000), + PDO_VAR(4750, 21000, 3000), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/fizz/usb_pd_pdo.h b/board/fizz/usb_pd_pdo.h new file mode 100644 index 0000000000..97ee437a3f --- /dev/null +++ b/board/fizz/usb_pd_pdo.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_FIZZ_USB_PD_PDO_H +#define __CROS_EC_BOARD_FIZZ_USB_PD_PDO_H + +#include "stdint.h" + +extern const uint32_t pd_src_pdo[1]; +extern const int pd_src_pdo_cnt; + +extern const uint32_t pd_snk_pdo[3]; +extern const int pd_snk_pdo_cnt; + +#endif /* __CROS_EC_BOARD_FIZZ_USB_PD_PDO_H */ diff --git a/board/fizz/usb_pd_policy.c b/board/fizz/usb_pd_policy.c index 5de57f3c9b..1d96c40a04 100644 --- a/board/fizz/usb_pd_policy.c +++ b/board/fizz/usb_pd_policy.c @@ -1,15 +1,15 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -17,28 +17,14 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_pdo.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP) - -const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); - -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), - PDO_BATT(4750, 21000, 50000), - PDO_VAR(4750, 21000, 3000), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int board_vbus_source_enabled(int port) { @@ -75,19 +61,6 @@ int pd_snk_is_vbus_provided(int port) return !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L); } -__override int pd_check_power_swap(int port) -{ - /* If type-c port is supplying power, we never swap PR (to source) */ - if (port == charge_manager_get_active_charge_port()) - return 0; - /* - * Allow power swap as long as we are acting as a dual role device, - * otherwise assume our role is fixed (not in S0 or console command - * to fix our role). - */ - return pd_get_dual_role(port) == PD_DRP_TOGGLE_ON ? 1 : 0; -} - int pd_check_vconn_swap(int port) { /* in G3, do not allow vconn swap since pp5000_A rail is off */ diff --git a/board/fizz/vif_override.xml b/board/fizz/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/fizz/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/flapjack/battery.c b/board/flapjack/battery.c deleted file mode 100644 index 981edea013..0000000000 --- a/board/flapjack/battery.c +++ /dev/null @@ -1,468 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery.h" -#include "battery_smart.h" -#include "charge_state.h" -#include "console.h" -#include "driver/battery/max17055.h" -#include "driver/charger/rt946x.h" -#include "driver/tcpm/mt6370.h" -#include "ec_commands.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "usb_pd.h" -#include "util.h" -#include "board.h" -#include "adc.h" -#include "adc_chip.h" -#include "math_util.h" -#include "p9221.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -#define BAT_LEVEL_PD_LIMIT 85 - -#define BATTERY_ATL_CHARGE_MIN_TEMP 0 -#define BATTERY_ATL_CHARGE_MAX_TEMP 60 - -#define BATTERY_SUNWODA_CHARGE_MIN_TEMP 0 -#define BATTERY_SUNWODA_CHARGE_MAX_TEMP 60 - -static const uint16_t full_model_ocv_table[][MAX17055_OCV_TABLE_SIZE] = { - [BATTERY_C18_ATL] = { - 0x8fc0, 0xb6c0, 0xb910, 0xbb30, 0xbcb0, 0xbdd0, 0xbef0, 0xc050, - 0xc1a0, 0xc460, 0xc750, 0xca40, 0xcd10, 0xd070, 0xd560, 0xda20, - 0x0060, 0x0f20, 0x0f40, 0x16c0, 0x17f0, 0x15c0, 0x1050, 0x10e0, - 0x09f0, 0x0850, 0x0730, 0x07a0, 0x0730, 0x0700, 0x0710, 0x0710, - 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, - 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, - }, - [BATTERY_C19_ATL] = { - 0xa260, 0xb5d0, 0xb840, 0xb940, 0xbbb0, 0xbcb0, 0xbdb0, 0xbf80, - 0xc0a0, 0xc1e0, 0xc520, 0xc840, 0xcdb0, 0xd150, 0xd590, 0xd9e0, - 0x0030, 0x0cd0, 0x1100, 0x0f30, 0x19e0, 0x19f0, 0x14f0, 0x1160, - 0x0dc0, 0x0980, 0x0850, 0x0780, 0x0730, 0x0700, 0x0710, 0x0710, - 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, - 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, - }, - [BATTERY_C18_SUNWODA] = { - 0x9d70, 0xaf80, 0xb6b0, 0xb830, 0xb990, 0xbc00, 0xbcd0, 0xbea0, - 0xc080, 0xc2e0, 0xc5f0, 0xc890, 0xcb90, 0xcf10, 0xd270, 0xd9e0, - 0x0060, 0x0240, 0x0b20, 0x1210, 0x0f20, 0x2200, 0x1650, 0x14f0, - 0x0980, 0x09c0, 0x07b0, 0x07f0, 0x06f0, 0x07e0, 0x05c0, 0x05c0, - 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, - 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, - }, - [BATTERY_C19_SUNWODA] = { - 0x8590, 0xb1d0, 0xb810, 0xbae0, 0xbc30, 0xbd70, 0xbeb0, 0xbfa0, - 0xc0f0, 0xc330, 0xc640, 0xc890, 0xcb50, 0xce20, 0xd370, 0xd950, - 0x0020, 0x0520, 0x0d80, 0x1860, 0x1910, 0x2040, 0x0be0, 0x0dd0, - 0x0cb0, 0x07b0, 0x08f0, 0x07c0, 0x0790, 0x06e0, 0x0620, 0x0620, - 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, - 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(full_model_ocv_table) == BATTERY_COUNT); - -/* - * TODO: Only precharge_current is different. We should consolidate these - * and apply 294 or 327 at run-time.when we need more rom space later. - */ -static const struct battery_info info[] = { - [BATTERY_C18_ATL] = { - .voltage_max = 4400, - .voltage_normal = 3850, - .voltage_min = 3000, - .precharge_current = 294, - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, - [BATTERY_C19_ATL] = { - .voltage_max = 4400, - .voltage_normal = 3850, - .voltage_min = 3000, - .precharge_current = 327, - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, - [BATTERY_C18_SUNWODA] = { - .voltage_max = 4400, - .voltage_normal = 3850, - .voltage_min = 3000, - .precharge_current = 294, - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, - [BATTERY_C19_SUNWODA] = { - .voltage_max = 4400, - .voltage_normal = 3850, - .voltage_min = 3000, - .precharge_current = 327, - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(info) == BATTERY_COUNT); - -static const struct max17055_batt_profile batt_profile[] = { - [BATTERY_C18_ATL] = { - .is_ez_config = 0, - .design_cap = 0x2e78, /* 5948mAh */ - .ichg_term = 0x03c0, /* 150 mA */ - /* Empty voltage = 3400mV, Recovery voltage = 4000mV */ - .v_empty_detect = 0xaa64, - .learn_cfg = 0x4402, - .dpacc = 0x0c7d, - .rcomp0 = 0x0011, - .tempco = 0x0209, - .qr_table00 = 0x5a00, - .qr_table10 = 0x2980, - .qr_table20 = 0x1100, - .qr_table30 = 0x1000, - .ocv_table = full_model_ocv_table[BATTERY_C18_ATL], - }, - [BATTERY_C19_ATL] = { - .is_ez_config = 0, - .design_cap = 0x3407, /* 6659mAh */ - .ichg_term = 0x03c0, /* 150 mA */ - /* Empty voltage = 3400mV, Recovery voltage = 4000mV */ - .v_empty_detect = 0xaa64, - .learn_cfg = 0x4402, - .dpacc = 0x0c7e, - .rcomp0 = 0x000f, - .tempco = 0x000b, - .qr_table00 = 0x5800, - .qr_table10 = 0x2680, - .qr_table20 = 0x0d00, - .qr_table30 = 0x0b00, - .ocv_table = full_model_ocv_table[BATTERY_C19_ATL], - }, - [BATTERY_C18_SUNWODA] = { - .is_ez_config = 0, - .design_cap = 0x2fcc, /* 6118mAh */ - .ichg_term = 0x03c0, /* 150 mA */ - /* Empty voltage = 3400mV, Recovery voltage = 4000mV */ - .v_empty_detect = 0xaa64, - .learn_cfg = 0x4402, - .dpacc = 0x0c7c, - .rcomp0 = 0x0024, - .tempco = 0x0c1f, - .qr_table00 = 0x9f00, - .qr_table10 = 0x4480, - .qr_table20 = 0x1600, - .qr_table30 = 0x1400, - .ocv_table = full_model_ocv_table[BATTERY_C18_SUNWODA], - }, - [BATTERY_C19_SUNWODA] = { - .is_ez_config = 0, - .design_cap = 0x34b1, /* 6744mAh */ - .ichg_term = 0x03c0, /* 150 mA */ - /* Empty voltage = 3400mV, Recovery voltage = 4000mV */ - .v_empty_detect = 0xaa64, - .learn_cfg = 0x4402, - .dpacc = 0x0c80, - .rcomp0 = 0x001f, - .tempco = 0x051f, - .qr_table00 = 0x9100, - .qr_table10 = 0x3d00, - .qr_table20 = 0x1200, - .qr_table30 = 0x1002, - .ocv_table = full_model_ocv_table[BATTERY_C19_SUNWODA], - }, -}; -BUILD_ASSERT(ARRAY_SIZE(batt_profile) == BATTERY_COUNT); - -static const struct max17055_alert_profile alert_profile[] = { - [BATTERY_C18_ATL] = { - .v_alert_mxmn = VALRT_DISABLE, - .t_alert_mxmn = MAX17055_TALRTTH_REG( - BATTERY_ATL_CHARGE_MAX_TEMP, - BATTERY_ATL_CHARGE_MIN_TEMP), - .s_alert_mxmn = SALRT_DISABLE, - .i_alert_mxmn = IALRT_DISABLE, - }, - [BATTERY_C19_ATL] = { - .v_alert_mxmn = VALRT_DISABLE, - .t_alert_mxmn = MAX17055_TALRTTH_REG( - BATTERY_ATL_CHARGE_MAX_TEMP, - BATTERY_ATL_CHARGE_MIN_TEMP), - .s_alert_mxmn = SALRT_DISABLE, - .i_alert_mxmn = IALRT_DISABLE, - }, - [BATTERY_C18_SUNWODA] = { - .v_alert_mxmn = VALRT_DISABLE, - .t_alert_mxmn = MAX17055_TALRTTH_REG( - BATTERY_SUNWODA_CHARGE_MIN_TEMP, - BATTERY_SUNWODA_CHARGE_MAX_TEMP), - .s_alert_mxmn = SALRT_DISABLE, - .i_alert_mxmn = IALRT_DISABLE, - }, - [BATTERY_C19_SUNWODA] = { - .v_alert_mxmn = VALRT_DISABLE, - .t_alert_mxmn = MAX17055_TALRTTH_REG( - BATTERY_SUNWODA_CHARGE_MIN_TEMP, - BATTERY_SUNWODA_CHARGE_MAX_TEMP), - .s_alert_mxmn = SALRT_DISABLE, - .i_alert_mxmn = IALRT_DISABLE, - }, - -}; -BUILD_ASSERT(ARRAY_SIZE(alert_profile) == BATTERY_COUNT); - -enum temp_zone { - TEMP_ZONE_0, /* t0 <= bat_temp_c < t1 */ - TEMP_ZONE_1, /* t1 <= bat_temp_c < t2 */ - TEMP_ZONE_2, /* t2 <= bat_temp_c < t3 */ - TEMP_ZONE_3, /* t3 <= bat_temp_c < t4 */ - TEMP_ZONE_COUNT, - TEMP_OUT_OF_RANGE = TEMP_ZONE_COUNT, -}; - -/* - * TODO: Many value in temp_zones are pretty similar, we should consolidate - * these and modify the value when we need more rom space later. - */ -static const struct { - int temp_min; /* 0.1 deg C */ - int temp_max; /* 0.1 deg C */ - int desired_current; /* mA */ - int desired_voltage; /* mV */ -} temp_zones[BATTERY_COUNT][TEMP_ZONE_COUNT] = { - [BATTERY_C18_ATL] = { - {BATTERY_ATL_CHARGE_MIN_TEMP * 10, 100, 1170, 4400}, - {100, 200, 1755, 4400}, - {200, 450, 2925, 4400}, - {450, BATTERY_ATL_CHARGE_MAX_TEMP * 10, 2925, 4100}, - }, - [BATTERY_C19_ATL] = { - {BATTERY_ATL_CHARGE_MIN_TEMP * 10, 100, 1300, 4400}, - {100, 200, 1950, 4400}, - {200, 450, 3250, 4400}, - {450, BATTERY_ATL_CHARGE_MAX_TEMP * 10, 3250, 4100}, - }, - [BATTERY_C18_SUNWODA] = { - {BATTERY_SUNWODA_CHARGE_MIN_TEMP * 10, 100, 1170, 4400}, - {100, 200, 1755, 4400}, - {200, 450, 2925, 4400}, - {450, BATTERY_SUNWODA_CHARGE_MAX_TEMP * 10, 2925, 4100}, - }, - [BATTERY_C19_SUNWODA] = { - {BATTERY_SUNWODA_CHARGE_MIN_TEMP * 10, 100, 1300, 4400}, - {100, 200, 1950, 4400}, - {200, 450, 3250, 4400}, - {450, BATTERY_SUNWODA_CHARGE_MAX_TEMP * 10, 3250, 4100}, - }, -}; - -/* BOARD_VERSION < 5: Pull-up = 1800 mV. */ -static const struct mv_to_id batteries0[] = { - { BATTERY_C18_ATL, 900 }, /* 100K ohm */ - { BATTERY_C19_ATL, 576 }, /* 47K ohm */ - { BATTERY_C18_SUNWODA, 1484 }, /* 470K ohm */ - { BATTERY_C19_SUNWODA, 1200 }, /* 200K ohm */ -}; -BUILD_ASSERT(ARRAY_SIZE(batteries0) < BATTERY_COUNT); - -/* BOARD_VERSION >= 5: Pull-up = 3300 mV. */ -static const struct mv_to_id batteries1[] = { - { BATTERY_C18_ATL, 1650 }, /* 100K ohm */ - { BATTERY_C19_ATL, 1055 }, /* 47K ohm */ - { BATTERY_C18_SUNWODA, 2721 }, /* 470K ohm */ - { BATTERY_C19_SUNWODA, 2200 }, /* 200K ohm */ -}; -BUILD_ASSERT(ARRAY_SIZE(batteries1) < BATTERY_COUNT); - -static enum battery_type batt_type = BATTERY_UNKNOWN; - -static void board_get_battery_type(void) -{ - const struct mv_to_id *table = batteries0; - int size = ARRAY_SIZE(batteries0); - int id; - - if (board_version >= 5) { - table = batteries1; - size = ARRAY_SIZE(batteries1); - } - id = board_read_id(ADC_BATT_ID, table, size); - if (id != ADC_READ_ERROR) - batt_type = id; - CPRINTS("Battery Type: %d", batt_type); -} -/* It has to run after BOARD_VERSION is read */ -DECLARE_HOOK(HOOK_INIT, board_get_battery_type, HOOK_PRIO_INIT_I2C + 2); - -const struct battery_info *battery_get_info(void) -{ - return &info[batt_type]; -} - -const struct max17055_batt_profile *max17055_get_batt_profile(void) -{ - return &batt_profile[batt_type]; -} - -const struct max17055_alert_profile *max17055_get_alert_profile(void) -{ - return &alert_profile[batt_type]; -} - -int get_battery_manufacturer_name(char *dest, int size) -{ - static const char * const name[] = { - [BATTERY_UNKNOWN] = "UNKNOWN", - [BATTERY_C18_ATL] = "C18_ATL", - [BATTERY_C19_ATL] = "C19_ATL", - [BATTERY_C18_SUNWODA] = "C18_SWD", - [BATTERY_C19_SUNWODA] = "C19_SWD", - }; - ASSERT(dest); - strzcpy(dest, name[batt_type], size); - return EC_SUCCESS; -} - -int board_cut_off_battery(void) -{ - /* The cut-off procedure is recommended by Richtek. b/116682788 */ - rt946x_por_reset(); - mt6370_vconn_discharge(0); - rt946x_cutoff_battery(); - - return EC_SUCCESS; -} - -enum battery_disconnect_state battery_get_disconnect_state(void) -{ - if (battery_is_present() == BP_YES) - return BATTERY_NOT_DISCONNECTED; - return BATTERY_DISCONNECTED; -} - -int charger_profile_override(struct charge_state_data *curr) -{ - /* battery temp in 0.1 deg C */ - int temp = curr->batt.temperature - 2731; - enum temp_zone zone; - int usb_mv, wpc_mv; - static int previous_usb_mv; - int val; - - if (curr->state != ST_CHARGE) - return 0; - - /* Limit input (=VBUS) to 5V when soc > 85% and charge current < 1A. */ - if (!(curr->batt.flags & BATT_FLAG_BAD_CURRENT) && - charge_get_percent() > BAT_LEVEL_PD_LIMIT && - curr->batt.current < 1000 && - curr->batt.current > 0) { - usb_mv = 5500; - wpc_mv = 5500; - } else { - usb_mv = PD_MAX_VOLTAGE_MV; - wpc_mv = P9221_DC_IVL_EPP_MV; - } - - if (usb_mv != previous_usb_mv) - CPRINTS("VBUS limited to %dmV", usb_mv); - previous_usb_mv = usb_mv; - - /* Pull down USB VBUS */ - if (pd_get_max_voltage() != usb_mv) - pd_set_external_voltage_limit(0, usb_mv); - - /* - * Pull down WPC VBUS. Need to use raw i2c APIs because RO - * doesn't have p9221 driver. If WPC is off, this is a no-op. - */ - if (i2c_read_offset16(I2C_PORT_WPC, P9221_R7_ADDR_FLAGS, - P9221R7_VOUT_SET_REG, &val, 1) == EC_SUCCESS - && val * 100 != wpc_mv) - i2c_write_offset16(I2C_PORT_WPC, P9221_R7_ADDR_FLAGS, - P9221R7_VOUT_SET_REG, wpc_mv / 100, 1); - - if ((curr->batt.flags & BATT_FLAG_BAD_TEMPERATURE) || - (temp < temp_zones[batt_type][TEMP_ZONE_0].temp_min)) { - zone = TEMP_OUT_OF_RANGE; - } else { - for (zone = TEMP_ZONE_0; zone < TEMP_ZONE_COUNT; zone++) { - if (temp < temp_zones[batt_type][zone].temp_max) - break; - } - } - - if (zone == TEMP_OUT_OF_RANGE || zone >= TEMP_ZONE_COUNT) { - curr->requested_current = curr->requested_voltage = 0; - curr->batt.flags &= ~BATT_FLAG_WANT_CHARGE; - curr->state = ST_IDLE; - } else { - curr->requested_current = - temp_zones[batt_type][zone].desired_current; - curr->requested_voltage = - temp_zones[batt_type][zone].desired_voltage; - } - - /* - * When the charger says it's done charging, even if fuel gauge says - * SOC < BATTERY_LEVEL_NEAR_FULL, we'll overwrite SOC with - * BATTERY_LEVEL_NEAR_FULL. So we can ensure both Chrome OS UI - * and battery LED indicate full charge. - */ - if (rt946x_is_charge_done()) { - curr->batt.state_of_charge = MAX(BATTERY_LEVEL_NEAR_FULL, - curr->batt.state_of_charge); - } - - return 0; -} - -static void board_charge_termination(void) -{ - static uint8_t te; - /* Enable charge termination when we are sure battery is present. */ - if (!te && battery_is_present() == BP_YES) { - if (!rt946x_enable_charge_termination(1)) - te = 1; - } -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, - board_charge_termination, - HOOK_PRIO_DEFAULT); - -/* Customs options controllable by host command. */ -#define PARAM_FASTCHARGE (CS_PARAM_CUSTOM_PROFILE_MIN + 0) - -enum ec_status charger_profile_override_get_param(uint32_t param, - uint32_t *value) -{ - return EC_RES_INVALID_PARAM; -} - -enum ec_status charger_profile_override_set_param(uint32_t param, - uint32_t value) -{ - return EC_RES_INVALID_PARAM; -} diff --git a/board/flapjack/board.c b/board/flapjack/board.c deleted file mode 100644 index 065df1edf9..0000000000 --- a/board/flapjack/board.c +++ /dev/null @@ -1,639 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "adc.h" -#include "adc_chip.h" -#include "backlight.h" -#include "board.h" -#include "button.h" -#include "charge_manager.h" -#include "charge_state.h" -#include "charger.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "cros_board_info.h" -#include "driver/accelgyro_bmi_common.h" -#include "driver/als_tcs3400.h" -#include "driver/battery/max17055.h" -#include "driver/charger/rt946x.h" -#include "driver/sync.h" -#include "driver/tcpm/mt6370.h" -#include "driver/temp_sensor/tmp432.h" -#include "driver/wpc/p9221.h" -#include "ec_commands.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "power.h" -#include "power_button.h" -#include "lid_switch.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "registers.h" -#include "spi.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "tcpm.h" -#include "temp_sensor.h" -#include "temp_sensor_chip.h" -#include "thermal.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_mux.h" -#include "usb_pd_tcpm.h" -#include "util.h" - - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -/* LCM_ID is embedded in SKU_ID bit[19-16] */ -#define SKU_ID_TO_LCM_ID(x) (((x) >> PANEL_ID_BIT_POSITION) & 0xf) -#define LCM_ID_TO_SKU_ID(x) (((x) & 0xf) << PANEL_ID_BIT_POSITION) - -/* BOARD_VERSION < 5: Pull-up = 1800 mV. */ -static const struct mv_to_id panels0[] = { - { PANEL_BOE_TV101WUM_NG0, 74 }, /* 2.2 kohm */ - { PANEL_BOE_TV080WUM_NG0, 212 }, /* 6.8 kohm */ - { PANEL_STA_10P, 1191 }, /* 100 kohm */ - { PANEL_STA_08P, 1028 }, /* 68 kohm */ -}; -BUILD_ASSERT(ARRAY_SIZE(panels0) < PANEL_COUNT); - -/* BOARD_VERSION >= 5: Pull-up = 3300 mV. */ -static const struct mv_to_id panels1[] = { - { PANEL_BOE_TV101WUM_NG0, 136 }, /* 2.2 kohm */ - { PANEL_BOE_TV080WUM_NG0, 387 }, /* 6.8 kohm */ - { PANEL_STA_10P, 2184 }, /* 100 kohm */ - { PANEL_STA_08P, 1884 }, /* 68 kohm */ -}; -BUILD_ASSERT(ARRAY_SIZE(panels1) < PANEL_COUNT); - -BUILD_ASSERT(PANEL_COUNT <= PANEL_UNINITIALIZED); - -uint8_t board_version; -uint8_t oem; -uint32_t sku = LCM_ID_TO_SKU_ID(PANEL_UNINITIALIZED); - -static const struct rt946x_init_setting battery_init_setting = { - .eoc_current = 150, - .mivr = 4000, - .ircmp_vclamp = 32, - .ircmp_res = 25, - .boost_voltage = 5050, - .boost_current = 1500, -}; - -int board_read_id(enum adc_channel ch, const struct mv_to_id *table, int size) -{ - int mv = adc_read_channel(ch); - int i; - - if (mv == ADC_READ_ERROR) - mv = adc_read_channel(ch); - - for (i = 0; i < size; i++) { - if (ABS(mv - table[i].median_mv) < ADC_MARGIN_MV) - return table[i].id; - } - - return ADC_READ_ERROR; -} - -const struct rt946x_init_setting *board_rt946x_init_setting(void) -{ - return &battery_init_setting; -} - -static void board_setup_panel(void) -{ - uint8_t channel; - uint8_t dim; - int rv = 0; - - if (board_version >= 3) { - switch (SKU_ID_TO_LCM_ID(sku)) { - case PANEL_BOE_TV080WUM_NG0: - case PANEL_STA_08P: - channel = 0xfa; - dim = 0xc8; - break; - case PANEL_BOE_TV101WUM_NG0: - case PANEL_STA_10P: - channel = 0xfe; - dim = 0xc4; - break; - default: - return; - } - } else { - /* TODO: to be removed once the boards are deprecated. */ - channel = sku & SKU_ID_PANEL_SIZE_MASK ? 0xfe : 0xfa; - dim = sku & SKU_ID_PANEL_SIZE_MASK ? 0xc4 : 0xc8; - } - - rv |= i2c_write8(I2C_PORT_CHARGER, RT946X_ADDR_FLAGS, - MT6370_BACKLIGHT_BLEN, channel); - rv |= i2c_write8(I2C_PORT_CHARGER, RT946X_ADDR_FLAGS, - MT6370_BACKLIGHT_BLDIM, dim); - rv |= i2c_write8(I2C_PORT_CHARGER, RT946X_ADDR_FLAGS, - MT6370_BACKLIGHT_BLPWM, 0xac); - if (rv) - CPRINTS("Board setup panel failed"); -} - -static enum panel_id board_get_panel_id(void) -{ - enum panel_id id; - - if (board_version < 3) { - id = PANEL_DEFAULT; /* No LCM_ID. */ - } else { - const struct mv_to_id *table = panels0; - int size = ARRAY_SIZE(panels0); - if (board_version >= 5) { - table = panels1; - size = ARRAY_SIZE(panels1); - } - id = board_read_id(ADC_LCM_ID, table, size); - if (id < PANEL_DEFAULT || PANEL_COUNT <= id) - id = PANEL_DEFAULT; - } - CPRINTS("LCM ID: %d", id); - return id; -} - -#define CBI_SKU_ID_SIZE 4 - -int cbi_board_override(enum cbi_data_tag tag, uint8_t *buf, uint8_t *size) -{ - switch (tag) { - case CBI_TAG_SKU_ID: - if (*size != CBI_SKU_ID_SIZE) - /* For old boards (board_version < 3) */ - return EC_SUCCESS; - if (SKU_ID_TO_LCM_ID(sku) == PANEL_UNINITIALIZED) - /* Haven't read LCM_ID */ - return EC_ERROR_BUSY; - buf[PANEL_ID_BIT_POSITION / 8] = SKU_ID_TO_LCM_ID(sku); - break; - default: - break; - } - return EC_SUCCESS; -} - -static void cbi_init(void) -{ - uint32_t val; - - if (cbi_get_board_version(&val) == EC_SUCCESS && val <= UINT8_MAX) - board_version = val; - CPRINTS("Board Version: 0x%02x", board_version); - - if (cbi_get_oem_id(&val) == EC_SUCCESS && val <= PROJECT_COUNT) - oem = val; - CPRINTS("OEM: %d", oem); - - sku = LCM_ID_TO_SKU_ID(board_get_panel_id()); - - if (cbi_get_sku_id(&val) == EC_SUCCESS) - sku = val; - - CPRINTS("SKU: 0x%08x", sku); -} -DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); - -static void tcpc_alert_event(enum gpio_signal signal) -{ - schedule_deferred_pd_interrupt(0 /* port */); -} - -static void gauge_interrupt(enum gpio_signal signal) -{ - task_wake(TASK_ID_CHARGER); -} - -#include "gpio_list.h" - -/******************************************************************************/ -/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ -const struct adc_t adc_channels[] = { - [ADC_LCM_ID] = {"LCM_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, - [ADC_BATT_ID] = {"BATT_ID", 3300, 4096, 0, STM32_AIN(7)}, - [ADC_USBC_THERM] = {"USBC_THERM", 3300, 4096, 0, STM32_AIN(14), - STM32_ADC_SMPR_239_5_CY}, -}; -BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - -/******************************************************************************/ -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"charger", I2C_PORT_CHARGER, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"als", I2C_PORT_ALS, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"battery", I2C_PORT_BATTERY, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"accelgyro", I2C_PORT_ACCEL, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/******************************************************************************/ -/* Charger Chips */ -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = RT946X_ADDR_FLAGS, - .drv = &rt946x_drv, - }, -}; - -/* power signal list. Must match order of enum power_signal. */ -const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, -}; -BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); - -#ifdef CONFIG_TEMP_SENSOR_TMP432 -/* Temperature sensors data; must be in same order as enum temp_sensor_id. */ -const struct temp_sensor_t temp_sensors[] = { - {"TMP432_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_LOCAL, 4}, - {"TMP432_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE1, 4}, - {"TMP432_Sensor_2", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE2, 4}, -}; -BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - -/* - * Thermal limits for each temp sensor. All temps are in degrees K. Must be in - * same order as enum temp_sensor_id. To always ignore any temp, use 0. - */ -struct ec_thermal_config thermal_params[] = { - {{0, 0, 0}, 0, 0}, /* TMP432_Internal */ - {{0, 0, 0}, 0, 0}, /* TMP432_Sensor_1 */ - {{0, 0, 0}, 0, 0}, /* TMP432_Sensor_2 */ -}; -BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); -#endif - -/******************************************************************************/ -/* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; -const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); - -/******************************************************************************/ -const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_TCPC0, - .addr_flags = MT6370_TCPC_I2C_ADDR_FLAGS, - }, - .drv = &mt6370_tcpm_drv}, -}; - -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, -}; - -void board_reset_pd_mcu(void) -{ -} - -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_0; - - return status; -} - -int board_set_active_charge_port(int charge_port) -{ - CPRINTS("New chg p%d", charge_port); - - switch (charge_port) { - case 0: - /* Don't charge from a source port except wireless charging*/ -#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7 - if (board_vbus_source_enabled(charge_port) - && !wpc_chip_is_online()) -#else - if (board_vbus_source_enabled(charge_port)) -#endif - return -1; - break; - case CHARGE_PORT_NONE: - /* - * To ensure the fuel gauge (max17055) is always powered - * even when battery is disconnected, keep VBAT rail on but - * set the charging current to minimum. - */ - charger_set_current(CHARGER_SOLO, 0); - break; - default: - panic("Invalid charge port\n"); - break; - } - - return EC_SUCCESS; -} - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - -int extpower_is_present(void) -{ - return tcpm_check_vbus_level(0, VBUS_PRESENT); -} - -int pd_snk_is_vbus_provided(int port) -{ - if (port) - panic("Invalid charge port\n"); - - return rt946x_is_vbus_ready(); -} - -/* - * Threshold to detect USB-C board. If the USB-C board isn't connected, - * USBC_THERM is floating thus the ADC pin should read about the pull-up - * voltage. If it's connected, the voltage is capped by the resistor (429k) - * place in parallel to the thermistor. 3.3V x 429k/(39k + 429k) = 3.025V - */ -#define USBC_THERM_THRESHOLD 3025 - -static void board_init(void) -{ -#ifdef SECTION_IS_RO - /* If USB-C board isn't connected, the device is being assembled. - * We cut off the battery until the assembly is done for better yield. - * Timing is ok because STM32F0 initializes ADC on demand. */ - if (board_version > 0x02) { - int mv = adc_read_channel(ADC_USBC_THERM); - if (mv == ADC_READ_ERROR) - mv = adc_read_channel(ADC_USBC_THERM); - CPRINTS("USBC_THERM=%d", mv); - if (mv > USBC_THERM_THRESHOLD) { - cflush(); - board_cut_off_battery(); - } - } -#endif - /* Set SPI1 PB13/14/15 pins to high speed */ - STM32_GPIO_OSPEEDR(GPIO_B) |= 0xfc000000; - - /* Enable TCPC alert interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); - - /* Enable charger interrupts */ - gpio_enable_interrupt(GPIO_CHARGER_INT_ODL); - -#ifdef SECTION_IS_RW -#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7 - /* Enable Wireless charger interrupts */ - gpio_enable_interrupt(GPIO_P9221_INT_ODL); -#endif - /* Enable interrupts from BMI160 sensor. */ - gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); - - /* Enable interrupt for the TCS3400 color light sensor */ - if (board_version >= 4) - gpio_enable_interrupt(GPIO_TCS3400_INT_ODL); - - /* Enable interrupt for the camera vsync. */ - gpio_enable_interrupt(GPIO_SYNC_INT); -#endif /* SECTION_IS_RW */ - - /* Enable interrupt from PMIC. */ - gpio_enable_interrupt(GPIO_PMIC_EC_RESETB); - - /* Enable gauge interrupt from max17055 */ - gpio_enable_interrupt(GPIO_GAUGE_INT_ODL); - board_setup_panel(); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -#ifdef SECTION_IS_RW -static void usb_pd_connect(void) -{ - /* VBUS from p9221 is already zero as it's disabled by NCP3902 */ - p9221_notify_vbus_change(0); - rt946x_toggle_bc12_detection(); -} -DECLARE_HOOK(HOOK_USB_PD_CONNECT, usb_pd_connect, HOOK_PRIO_DEFAULT); -#endif - -void board_config_pre_init(void) -{ - STM32_RCC_AHBENR |= STM32_RCC_HB_DMA1; - /* - * Remap USART1 and SPI2 DMA: - * - * Ch4: USART1_TX / Ch5: USART1_RX (1000) - * Ch6: SPI2_RX / Ch7: SPI2_TX (0011) - */ - STM32_DMA_CSELR(STM32_DMAC_CH4) = (8 << 12) | (8 << 16) | - (3 << 20) | (3 << 24); -} - -/* Motion sensors */ -/* Mutexes */ -#ifdef SECTION_IS_RW -static struct mutex g_lid_mutex; - -static struct bmi_drv_data_t g_bmi160_data; - -static struct als_drv_data_t g_tcs3400_data = { - .als_cal.scale = 1, - .als_cal.uscale = 0, - .als_cal.offset = 0, - .als_cal.channel_scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ - .cover_scale = ALS_CHANNEL_SCALE(0.9), /* CT */ - }, -}; - -static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { - .calibration.rgb_cal[X] = { - .offset = 15, /* 15.65956688 */ - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(-0.04592318), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0.06756278), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(-0.05885579), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.12021096), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ - .cover_scale = ALS_CHANNEL_SCALE(0.6) - } - }, - .calibration.rgb_cal[Y] = { - .offset = 8, /* 8.75943638 */ - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(-0.07786953), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0.18940035), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(-0.0524428), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.09092403), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - } - }, - .calibration.rgb_cal[Z] = { - .offset = -21, /* -21.92665481 */ - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(-0.18981975), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0.5351057), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(-0.01858507), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(-0.01793189), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ - .cover_scale = ALS_CHANNEL_SCALE(1.5) - } - }, - .calibration.irt = INT_TO_FP(1), - .saturation.again = TCS_DEFAULT_AGAIN, - .saturation.atime = TCS_DEFAULT_ATIME, -}; - -/* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -struct motion_sensor_t motion_sensors[] = { - /* - * Note: bmi160: supports accelerometer and gyro sensor - * Requirement: accelerometer sensor must init before gyro sensor - * DO NOT change the order of the following table. - */ - [LID_ACCEL] = { - .name = "Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMI160, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &bmi160_drv, - .mutex = &g_lid_mutex, - .drv_data = &g_bmi160_data, - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ - .min_frequency = BMI_ACCEL_MIN_FREQ, - .max_frequency = BMI_ACCEL_MAX_FREQ, - .config = { - /* Enable accel in S0 */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, - }, - [LID_GYRO] = { - .name = "Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMI160, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_LID, - .drv = &bmi160_drv, - .mutex = &g_lid_mutex, - .drv_data = &g_bmi160_data, - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .default_range = 1000, /* dps */ - .rot_standard_ref = &lid_standard_ref, - .min_frequency = BMI_GYRO_MIN_FREQ, - .max_frequency = BMI_GYRO_MAX_FREQ, - }, - [CLEAR_ALS] = { - .name = "Clear Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT, - .location = MOTIONSENSE_LOC_LID, - .drv = &tcs3400_drv, - .drv_data = &g_tcs3400_data, - .port = I2C_PORT_ALS, - .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - .min_frequency = TCS3400_LIGHT_MIN_FREQ, - .max_frequency = TCS3400_LIGHT_MAX_FREQ, - .config = { - /* Run ALS sensor in S0 */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 1000, - }, - }, - }, - [RGB_ALS] = { - .name = "RGB Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT_RGB, - .location = MOTIONSENSE_LOC_LID, - .drv = &tcs3400_rgb_drv, - .drv_data = &g_tcs3400_rgb_data, - /*.port=I2C_PORT_ALS,*/ /* Unused. RGB channels read by CLEAR_ALS. */ - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - .min_frequency = 0, /* 0 indicates we should not use sensor directly */ - .max_frequency = 0, /* 0 indicates we should not use sensor directly */ - }, - [VSYNC] = { - .name = "Camera vsync", - .active_mask = SENSOR_ACTIVE_S0, - .chip = MOTIONSENSE_CHIP_GPIO, - .type = MOTIONSENSE_TYPE_SYNC, - .location = MOTIONSENSE_LOC_CAMERA, - .drv = &sync_drv, - .default_range = 0, - .min_frequency = 0, - .max_frequency = 1, - }, -}; -const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -const struct motion_sensor_t *motion_als_sensors[] = { - &motion_sensors[CLEAR_ALS], -}; -BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); -#endif /* SECTION_IS_RW */ - -int board_allow_i2c_passthru(int port) -{ - return (port == I2C_PORT_VIRTUAL_BATTERY); -} - -int board_get_fod(uint8_t **fod) -{ - *fod = NULL; - return 0; -} - -int board_get_epp_fod(uint8_t **fod) -{ - *fod = NULL; - return 0; -} - diff --git a/board/flapjack/board.h b/board/flapjack/board.h deleted file mode 100644 index 370bd1727f..0000000000 --- a/board/flapjack/board.h +++ /dev/null @@ -1,345 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Configuration for Kukui */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Optional modules */ -#define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG -#define CONFIG_BOARD_VERSION_CBI -#define CONFIG_CHIPSET_MT8183 -#define CONFIG_CMD_ACCELS -#define CONFIG_CRC8 -#define CONFIG_CROS_BOARD_INFO -#define CONFIG_EMULATED_SYSRQ -#undef CONFIG_HIBERNATE -#define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_I2C_VIRTUAL_BATTERY -#define CONFIG_I2C_PASSTHRU_RESTRICTED -#define CONFIG_LED_COMMON -#define CONFIG_LOW_POWER_IDLE -#define CONFIG_POWER_COMMON -#define CONFIG_SPI -#define CONFIG_SPI_MASTER -#define CONFIG_STM_HWTIMER32 -#define CONFIG_SWITCH -#define CONFIG_WATCHDOG_HELP - -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */ - -#undef CONFIG_UART_CONSOLE -#define CONFIG_UART_CONSOLE 1 -#define CONFIG_UART_RX_DMA - -/* Bootblock */ -#ifdef SECTION_IS_RO -#define CONFIG_BOOTBLOCK - -#define EMMC_SPI_PORT 2 -#endif - -/* Optional features */ -#define CONFIG_BOARD_PRE_INIT -#define CONFIG_BUTTON_TRIGGERED_RECOVERY -#define CONFIG_CHARGER_ILIM_PIN_DISABLED -#define CONFIG_FORCE_CONSOLE_RESUME -#define CONFIG_HOST_COMMAND_STATUS -#define CONFIG_CMD_AP_RESET_LOG - -/* Required for FAFT */ -#define CONFIG_CMD_BUTTON - -/* By default, set hcdebug to off */ -#undef CONFIG_HOSTCMD_DEBUG_MODE -#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF -#define CONFIG_LTO -#define CONFIG_POWER_BUTTON -#define CONFIG_POWER_BUTTON_IGNORE_LID -#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE -#define CONFIG_SOFTWARE_PANIC -#define CONFIG_VBOOT_HASH -#define CONFIG_VOLUME_BUTTONS - -#define CONFIG_CHARGER -#define CONFIG_CHARGER_MT6370 -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 -#define CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT 2 -#define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 15000 -#define CONFIG_CHARGER_PROFILE_OVERRIDE -#define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_OTG -#define CONFIG_USB_CHARGER -#define CONFIG_USB_MUX_VIRTUAL - -/* Increase tx buffer size, as we'd like to stream EC log to AP. */ -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 4096 - -/* Motion Sensors */ -#ifdef SECTION_IS_RW -#define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS -#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) - -#define CONFIG_ALS -#define ALS_COUNT 1 - -/* TSC3400 ALS */ -#define CONFIG_ALS_TCS3400 -#define CONFIG_ALS_TCS3400_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) -#define CONFIG_TCS_USE_LUX_TABLE - - -/* ALS needs to be polled */ -#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(CLEAR_ALS) - -/* Camera VSYNC */ -#define CONFIG_SYNC -#define CONFIG_SYNC_COMMAND -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) -#endif /* SECTION_IS_RW */ - -/* To be able to indicate the device is in tablet mode. */ -#define CONFIG_TABLET_MODE -#define CONFIG_TABLET_MODE_SWITCH - -/* - * Only include the sensor fifo in the RW section (since the motion task is only - * included there). - */ -#ifdef SECTION_IS_RW -/* Enable sensor fifo, must also define the _SIZE and _THRES */ -#define CONFIG_ACCEL_FIFO -/* FIFO size is in power of 2. */ -#define CONFIG_ACCEL_FIFO_SIZE 256 -/* Depends on how fast the AP boots and typical ODRs. */ -#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) -#endif /* SECTION_IS_RW */ - -/* Wireless Power Charger Config */ -#ifdef SECTION_IS_RW -#define CONFIG_WIRELESS_CHARGER_P9221_R7 -#endif - - -/* USB PD config */ -#define CONFIG_CHARGE_MANAGER -#define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV1 -#define CONFIG_USB_PD_ALT_MODE -#define CONFIG_USB_PD_ALT_MODE_DFP -#define CONFIG_USB_PD_DISCHARGE_TCPC -#define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE -#define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_PORT_MAX_COUNT 1 -#define CONFIG_USB_PD_TCPC_LOW_POWER -#define CONFIG_USB_PD_TCPM_MT6370 -#define CONFIG_USB_PD_TCPM_TCPCI -#define CONFIG_USB_PD_VBUS_DETECT_TCPC -#define CONFIG_USB_PD_5V_CHARGER_CTRL -#define CONFIG_USBC_SS_MUX -#define CONFIG_USBC_VCONN -#define CONFIG_USBC_VCONN_SWAP -#define CONFIG_USB_PD_COMM_LOCKED -#define CONFIG_USB_PD_DP_HPD_GPIO -#define CONFIG_USBC_DISABLE_CHARGE_FROM_RP_DEF -#ifdef SECTION_IS_RO -#define CONFIG_USB_PD_DEBUG_LEVEL 0 -#endif - -#define CONFIG_BATTERY_CUT_OFF -#define CONFIG_BATTERY_PRESENT_CUSTOM -#define CONFIG_BATTERY_REVIVE_DISCONNECT -#define CONFIG_BATTERY_MAX17055 -#define CONFIG_BATTERY_MAX17055_ALERT -#define CONFIG_BATTERY_MAX17055_FULL_MODEL - -/* Battery parameters for max17055 ModelGauge m5 algorithm. */ -#define BATTERY_MAX17055_RSENSE 10 /* m-ohm */ -#define BATTERY_DESIRED_CHARGING_CURRENT 2000 /* mA */ - -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_VOLTAGE_MV 9000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_POWER_MW 18000 - -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - -/* Timer selection */ -#define TIM_CLOCK32 2 -#define TIM_WATCHDOG 7 - -/* 48 MHz SYSCLK clock frequency */ -#define CPU_CLOCK 48000000 - -/* Optional for testing */ -#undef CONFIG_PECI -#undef CONFIG_PSTORE - -/* Modules we want to exclude */ -#undef CONFIG_CMD_ACCELSPOOF -#undef CONFIG_CMD_APTHROTTLE -#undef CONFIG_CMD_BATTFAKE -#undef CONFIG_CMD_DEVICE_EVENT -#undef CONFIG_CMD_FASTCHARGE -#undef CONFIG_CMD_FLASH -#undef CONFIG_CMD_GETTIME -#undef CONFIG_CMD_HASH -#undef CONFIG_CMD_HCDEBUG -#undef CONFIG_CMD_MD -#undef CONFIG_CMD_MEM -#undef CONFIG_CMD_POWERINDEBUG -#undef CONFIG_CMD_TIMERINFO - -#ifdef SECTION_IS_RO -#undef CONFIG_CMD_ADC -#undef CONFIG_CMD_APTHROTTLE -#undef CONFIG_CMD_CBI -#undef CONFIG_CMD_I2C_SCAN -#undef CONFIG_CMD_I2C_XFER -#undef CONFIG_CMD_IDLE_STATS -#undef CONFIG_CMD_INA -#undef CONFIG_CMD_MMAPINFO -#undef CONFIG_CMD_PD -#undef CONFIG_CMD_PWR_AVG -#undef CONFIG_CMD_REGULATOR -#undef CONFIG_CMD_RW -#undef CONFIG_CMD_SHMEM -/* TODO: Consider put these back when FSI is (about to be) done. */ -#undef CONFIG_CMD_SLEEPMASK -#undef CONFIG_CMD_SLEEPMASK_SET -#undef CONFIG_CMD_SYSLOCK -#endif - -#define CONFIG_TASK_PROFILING - -/* I2C ports */ -#define I2C_PORT_CHARGER 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_WPC 0 -#define I2C_PORT_BATTERY 1 -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY -#define I2C_PORT_ACCEL 1 -#define I2C_PORT_ALS 1 -#define I2C_PORT_EEPROM 1 - -/* I2C addresses */ -#define I2C_ADDR_EEPROM_FLAGS 0x50 - -/* Route sbs host requests to virtual battery driver */ -#define VIRTUAL_BATTERY_ADDR_FLAGS 0x0B - -/* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ - -#define CONFIG_KEYBOARD_PROTOCOL_MKBP -#define CONFIG_MKBP_EVENT -#define CONFIG_MKBP_USE_GPIO -/* Define the host events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) - -/* Define panel size mask according to skuid */ -#define SKU_ID_PANEL_SIZE_MASK BIT(1) - -#ifndef __ASSEMBLER__ - -enum oem_id { - PROJECT_FLAPJACK = 0, - PROJECT_COUNT, -}; - -enum adc_channel { - /* Real ADC channels begin here */ - ADC_LCM_ID = 0, - ADC_EC_SKU_ID, - ADC_BATT_ID, - ADC_USBC_THERM, - ADC_CH_COUNT -}; - -/* Panel ID bit position inside sku_id */ -#define PANEL_ID_BIT_POSITION 16 - -/* Refer to coreboot/src/mainboard/google/kukui/display.h */ -enum panel_id { - PANEL_DEFAULT = 0, - PANEL_BOE_TV101WUM_NG0, - PANEL_BOE_TV080WUM_NG0, - PANEL_STA_10P, - PANEL_STA_08P, - PANEL_COUNT, - PANEL_UNINITIALIZED = 0xf, -}; - -/* power signal definitions */ -enum power_signal { - AP_IN_S3_L, - PMIC_PWR_GOOD, - - /* Number of signals */ - POWER_SIGNAL_COUNT, -}; - -/* Motion sensors */ -enum sensor_id { - LID_ACCEL = 0, - LID_GYRO, - CLEAR_ALS, - RGB_ALS, - VSYNC, - SENSOR_COUNT, -}; - -/* Batteries */ -enum battery_type { - BATTERY_UNKNOWN = 0, - BATTERY_C18_ATL, - BATTERY_C19_ATL, - BATTERY_C18_SUNWODA, - BATTERY_C19_SUNWODA, - BATTERY_COUNT, -}; - -#include "gpio_signal.h" -#include "registers.h" - -#ifdef SECTION_IS_RO -/* Interrupt handler for emmc task */ -void emmc_cmd_interrupt(enum gpio_signal signal); -#endif - -void board_reset_pd_mcu(void); - -#define ADC_MARGIN_MV 56 /* Simply assume 1800/16/2 */ - -struct mv_to_id { - int id; - int median_mv; -}; - -int board_read_id(enum adc_channel, const struct mv_to_id *table, int size); - -extern uint8_t board_version; -extern uint8_t oem; -extern uint32_t sku; - -#define PORT_TO_HPD(port) GPIO_USB_C0_HPD_OD - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/flapjack/build.mk b/board/flapjack/build.mk deleted file mode 100644 index a368c187bf..0000000000 --- a/board/flapjack/build.mk +++ /dev/null @@ -1,21 +0,0 @@ -# -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# -# -# STmicro STM32F098VC -CHIP:=stm32 -CHIP_FAMILY:=stm32f0 -CHIP_VARIANT:=stm32f09x - -board-y=battery.o board.o usb_pd_policy.o led.o -board-$(CONFIG_BOOTBLOCK)+=emmc.o -board-$(BOARD_KRANE)+=base_detect_krane.o - -$(out)/RO/board/$(BOARD)/emmc.o: $(out)/bootblock_data.h - -# 21504 bytes plus some extra buffer -DEFAULT_BOOTBLOCK_SIZE:=23000 diff --git a/board/flapjack/ec.tasklist b/board/flapjack/ec.tasklist deleted file mode 100644 index 33e3538139..0000000000 --- a/board/flapjack/ec.tasklist +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/** - * See CONFIG_TASK_LIST in config.h for details. - */ -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG, usb_charger_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS_RW(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS_RO(EMMC, emmc_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS_RW(WPC,wireless_power_charger_task,NULL,LARGER_TASK_STACK_SIZE) - diff --git a/board/flapjack/emmc.c b/board/flapjack/emmc.c deleted file mode 120000 index a97e912173..0000000000 --- a/board/flapjack/emmc.c +++ /dev/null @@ -1 +0,0 @@ -../../baseboard/kukui/emmc.c \ No newline at end of file diff --git a/board/flapjack/gpio.inc b/board/flapjack/gpio.inc deleted file mode 100644 index f349ceb972..0000000000 --- a/board/flapjack/gpio.inc +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. - */ - -/* Interrupts */ -GPIO_INT(USB_C0_PD_INT_ODL, PIN(B, 1), GPIO_INT_FALLING | GPIO_PULL_UP, - tcpc_alert_event) -GPIO_INT(VOLUME_UP_L, PIN(B, 10), GPIO_INT_BOTH | GPIO_PULL_UP, - button_interrupt) /* EC_VOLUP_BTN_ODL */ -GPIO_INT(VOLUME_DOWN_L, PIN(B, 11), GPIO_INT_BOTH | GPIO_PULL_UP, - button_interrupt) /* EC_VOLDN_BTN_ODL */ -GPIO_INT(POWER_BUTTON_L, PIN(A, 0), GPIO_INT_BOTH | GPIO_PULL_UP, - power_button_interrupt) /* EC_PWR_BTN_ODL */ - -GPIO_INT(AP_IN_SLEEP_L, PIN(C, 12), GPIO_INT_BOTH | GPIO_PULL_DOWN, - power_signal_interrupt) -GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, - power_signal_interrupt) -GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, - chipset_reset_request_interrupt) -GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 2), GPIO_INT_FALLING, - chipset_watchdog_interrupt) - -GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | \ - GPIO_PULL_UP, bmi160_interrupt) - -GPIO_INT_RW(TCS3400_INT_ODL, PIN(A, 14), GPIO_INT_FALLING, - tcs3400_interrupt) -GPIO_INT(CHARGER_INT_ODL, PIN(C, 13), GPIO_INT_FALLING | GPIO_PULL_UP, - rt946x_interrupt) -GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, - emmc_cmd_interrupt) -GPIO_INT(SPI1_NSS, PIN(A, 15), GPIO_INT_BOTH | GPIO_PULL_UP, - spi_event) -GPIO_INT_RW(SYNC_INT, PIN(A, 8), GPIO_INT_RISING | GPIO_PULL_DOWN, - sync_interrupt) -GPIO_INT(LID_OPEN, PIN(C, 5), GPIO_INT_BOTH, - lid_interrupt) /* HALL_INT_L */ -GPIO_INT(GAUGE_INT_ODL, PIN(C, 9), GPIO_INT_FALLING | GPIO_PULL_UP, - gauge_interrupt) -GPIO_INT_RW(P9221_INT_ODL, PIN(A, 6), GPIO_INT_FALLING, - p9221_interrupt) - -/* Voltage rails control pins */ - -/* Reset pins */ -GPIO(AP_SYS_RST_L, PIN(C, 11), GPIO_OUT_LOW) -GPIO(PMIC_WATCHDOG_L, PIN(C, 3), GPIO_OUT_LOW) -GPIO(PMIC_EN_ODL, PIN(C, 10), GPIO_ODR_HIGH) -GPIO(PMIC_FORCE_RESET_ODL, PIN(A, 2), GPIO_ODR_HIGH) -GPIO(MT6370_RST_L, PIN(F, 0), GPIO_OUT_LOW) - -/* - * I2C pins should be configured as inputs until I2C module is - * initialized. This will avoid driving the lines unintentionally. - */ -GPIO(I2C1_SCL, PIN(B, 8), GPIO_INPUT) -GPIO(I2C1_SDA, PIN(B, 9), GPIO_INPUT) -GPIO(I2C2_SCL, PIN(A, 11), GPIO_INPUT) -GPIO(I2C2_SDA, PIN(A, 12), GPIO_INPUT) - -/* Analog pins */ -GPIO(BATT_ID, PIN(A, 7), GPIO_ANALOG) -GPIO(LCM_ID, PIN(C, 0), GPIO_ANALOG) -GPIO(EC_SKU_ID, PIN(B, 0), GPIO_ANALOG) -GPIO(USBC_THERM, PIN(C, 4), GPIO_ANALOG) - -/* Other input pins */ -GPIO(WP_L, PIN(C, 8), GPIO_INPUT) /* EC_FLASH_WP_ODL */ -GPIO(BOOT0, PIN(F, 11), GPIO_INPUT) -GPIO(CCD_MODE_ODL, PIN(A, 1), GPIO_INPUT) - -/* Other output pins */ -GPIO(ENTERING_RW, PIN(C, 6), GPIO_ODR_HIGH) /* EC_ENTERING_RW_ODL */ -GPIO(EC_INT_L, PIN(B, 12), GPIO_ODR_HIGH) /* EC_AP_INT_ODL */ -GPIO(USB_C0_DP_POLARITY, PIN(C, 14), GPIO_OUT_LOW) -GPIO(USB_C0_HPD_OD, PIN(F, 1), GPIO_ODR_LOW) -GPIO(BOOTBLOCK_EN_L, PIN(C, 1), GPIO_ODR_HIGH) -GPIO(USB_C0_DP_OE_L, PIN(A, 5), GPIO_OUT_HIGH) -GPIO(EC_SWDIO, PIN(A, 13), GPIO_ODR_HIGH) -GPIO(EN_PP5000_USBC, PIN(D, 2), GPIO_OUT_LOW) -GPIO(BPP_EPP_SEL, PIN(B, 6), GPIO_OUT_LOW) -GPIO(NCP3902_EN_L, PIN(C, 7), GPIO_OUT_LOW) - - -/* USART1: PA9/PA10 */ -ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, 0) -/* I2C MASTER: PB8/9 */ -ALTERNATE(PIN_MASK(B, 0x0300), 1, MODULE_I2C, GPIO_ODR_HIGH ) -/* I2C MASTER: PA11/12 */ -ALTERNATE(PIN_MASK(A, 0x1800), 5, MODULE_I2C, GPIO_ODR_HIGH ) -/* SPI SLAVE: PB3/4/5 */ -ALTERNATE(PIN_MASK(B, 0x0038), 0, MODULE_SPI, 0) -#ifdef SECTION_IS_RO -/* SPI SLAVE: PB13/14/15 */ -ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) -#endif -/* SPI SLAVE CS: PA15 */ -ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) diff --git a/board/flapjack/led.c b/board/flapjack/led.c deleted file mode 100644 index 165d549eb7..0000000000 --- a/board/flapjack/led.c +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery LED control for Flapjack board. - */ - -#include "battery.h" -#include "charge_state.h" -#include "console.h" -#include "driver/charger/rt946x.h" -#include "hooks.h" -#include "led_common.h" -#include "util.h" - -/* Define this to enable led command and debug LED */ -#undef DEBUG_LED - -const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; - -const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); - -#define LED_OFF MT6370_LED_ID_OFF -#define LED_RED MT6370_LED_ID1 -#define LED_GRN MT6370_LED_ID2 -#define LED_BLU MT6370_LED_ID3 - -#define LED_MASK_OFF 0 -#define LED_MASK_RED MT6370_MASK_RGB_ISNK1DIM_EN -#define LED_MASK_GRN MT6370_MASK_RGB_ISNK2DIM_EN -#define LED_MASK_BLU MT6370_MASK_RGB_ISNK3DIM_EN - -static enum charge_state chstate; - -static void led_set_battery(void) -{ - static enum charge_state prev = PWR_STATE_UNCHANGE; - static int battery_second; - int red = 0, grn = 0, blu = 0; - - battery_second++; -#ifndef DEBUG_LED - chstate = charge_get_state(); -#endif - if (chstate == prev) - return; - prev = chstate; - - /* - * Full White - * Charging Amber - * Error Red - */ - switch (chstate) { - case PWR_STATE_CHARGE: - /* RGB(current, duty) = (4mA,10/32) (4mA,1/32) (0mA,) */ - red = 1; - grn = 1; - mt6370_led_set_pwm_dim_duty(LED_RED, 9); - mt6370_led_set_pwm_dim_duty(LED_GRN, 0); - break; - case PWR_STATE_DISCHARGE: - /* RGB(current, duty) = (0mA,) (0mA,) (0mA,) */ - break; - case PWR_STATE_ERROR: - /* RGB(current, duty) = (4mA,8/32) (0mA,) (0mA,) */ - red = 1; - mt6370_led_set_pwm_dim_duty(LED_RED, 7); - break; - case PWR_STATE_CHARGE_NEAR_FULL: - /* RGB(current, duty) = (8mA,2/32) (8mA,1/32) (4mA,1/32) */ - red = 2; - grn = 2; - blu = 1; - mt6370_led_set_pwm_dim_duty(LED_RED, 1); - mt6370_led_set_pwm_dim_duty(LED_GRN, 0); - mt6370_led_set_pwm_dim_duty(LED_BLU, 0); - break; - default: - /* Other states don't alter LED behavior */ - return; - } - - mt6370_led_set_brightness(LED_RED, red); - mt6370_led_set_brightness(LED_GRN, grn); - mt6370_led_set_brightness(LED_BLU, blu); -} - -void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) -{ - /* Current is fixed at 4mA. Brightness is controlled by duty only. */ - const uint8_t max = MT6370_LED_PWM_DIMDUTY_MAX; - if (led_id != EC_LED_ID_BATTERY_LED) - return; - brightness_range[EC_LED_COLOR_GREEN] = max; - brightness_range[EC_LED_COLOR_RED] = max; - brightness_range[EC_LED_COLOR_BLUE] = max; -} - -static void set_current_and_pwm_duty(uint8_t brightness, - enum mt6370_led_index color) -{ - if (brightness) { - /* Current is fixed at 4mA. Brightness is controlled by duty. */ - mt6370_led_set_brightness(color, 1); - mt6370_led_set_pwm_dim_duty(color, brightness); - } else { - /* off */ - mt6370_led_set_brightness(color, 0); - } -} - -int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) -{ - if (led_id != EC_LED_ID_BATTERY_LED) - return EC_ERROR_INVAL; - set_current_and_pwm_duty(brightness[EC_LED_COLOR_RED], LED_RED); - set_current_and_pwm_duty(brightness[EC_LED_COLOR_GREEN], LED_GRN); - set_current_and_pwm_duty(brightness[EC_LED_COLOR_BLUE], LED_BLU); - return EC_SUCCESS; -} - -static void flapjack_led_init(void) -{ - const enum mt6370_led_dim_mode dim = MT6370_LED_DIM_MODE_PWM; - const enum mt6370_led_pwm_freq freq = MT6370_LED_PWM_FREQ1000; - mt6370_led_set_color(LED_MASK_RED | LED_MASK_GRN | LED_MASK_BLU); - mt6370_led_set_dim_mode(LED_RED, dim); - mt6370_led_set_dim_mode(LED_GRN, dim); - mt6370_led_set_dim_mode(LED_BLU, dim); - mt6370_led_set_pwm_frequency(LED_RED, freq); - mt6370_led_set_pwm_frequency(LED_GRN, freq); - mt6370_led_set_pwm_frequency(LED_BLU, freq); -} -DECLARE_HOOK(HOOK_INIT, flapjack_led_init, HOOK_PRIO_DEFAULT); - -/* Called by hook task every 1 sec */ -static void led_second(void) -{ - if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) - led_set_battery(); -} -DECLARE_HOOK(HOOK_SECOND, led_second, HOOK_PRIO_DEFAULT); - -#ifdef DEBUG_LED -static int command_led(int argc, char **argv) -{ - int val; - char *e; - - mt6370_led_set_color(LED_MASK_RED|LED_MASK_GRN|LED_MASK_BLU); - - if (argc == 2) { - val = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - chstate = val; - return EC_SUCCESS; - } - - if (argc < 4) - return EC_ERROR_PARAM_COUNT; - - val = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - mt6370_led_set_brightness(LED_RED, val); - - val = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - mt6370_led_set_brightness(LED_GRN, val); - - val = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - mt6370_led_set_brightness(LED_BLU, val); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(led, command_led, " or ", NULL); -#endif diff --git a/board/flapjack/usb_pd_policy.c b/board/flapjack/usb_pd_policy.c deleted file mode 100644 index 20de95dc3b..0000000000 --- a/board/flapjack/usb_pd_policy.c +++ /dev/null @@ -1,153 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "atomic.h" -#include "charger.h" -#include "charge_manager.h" -#include "common.h" -#include "console.h" -#include "driver/charger/rt946x.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -static uint8_t vbus_en; - -int board_vbus_source_enabled(int port) -{ - return vbus_en; -} - -int pd_check_vconn_swap(int port) -{ - /* - * VCONN is provided directly by the battery (PPVAR_SYS) - * but use the same rules as power swap. - */ - return pd_get_dual_role(port) == PD_DRP_TOGGLE_ON ? 1 : 0; -} - -int pd_set_power_supply_ready(int port) -{ - /* Disable NCP3902 to avoid charging from VBUS */ - gpio_set_level(GPIO_NCP3902_EN_L, 1); - - /* Provide VBUS */ - vbus_en = 1; - gpio_set_level(GPIO_EN_PP5000_USBC, 1); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; /* we are ready */ -} - -void pd_power_supply_reset(int port) -{ - int prev_en; - - prev_en = vbus_en; - /* Disable VBUS */ - vbus_en = 0; - - if (prev_en) { - gpio_set_level(GPIO_EN_PP5000_USBC, 0); - msleep(250); - gpio_set_level(GPIO_NCP3902_EN_L, 0); - } - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -/* ----------------- Vendor Defined Messages ------------------ */ -#ifdef CONFIG_USB_PD_ALT_MODE_DFP -__override void svdm_dp_post_config(int port) -{ - dp_flags[port] |= DP_FLAGS_DP_ON; - if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) - return; - - gpio_set_level(GPIO_USB_C0_HPD_OD, 1); - gpio_set_level(GPIO_USB_C0_DP_OE_L, 0); - gpio_set_level(GPIO_USB_C0_DP_POLARITY, pd_get_polarity(port)); - - /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; - usb_mux_hpd_update(port, 1, 0); -} - -__override int svdm_dp_attention(int port, uint32_t *payload) -{ - int cur_lvl = gpio_get_level(GPIO_USB_C0_HPD_OD); - int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); - int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); - - dp_status[port] = payload[1]; - - /* Its initial DP status message prior to config */ - if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { - if (lvl) - dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; - return 1; - } - - usb_mux_set(port, lvl ? USB_PD_MUX_DP_ENABLED : USB_PD_MUX_NONE, - USB_SWITCH_CONNECT, pd_get_polarity(port)); - - usb_mux_hpd_update(port, lvl, irq); - - if (irq & cur_lvl) { - uint64_t now = get_time().val; - /* wait for the minimum spacing between IRQ_HPD if needed */ - if (now < svdm_hpd_deadline[port]) - usleep(svdm_hpd_deadline[port] - now); - - /* generate IRQ_HPD pulse */ - gpio_set_level(GPIO_USB_C0_HPD_OD, 0); - usleep(HPD_DSTREAM_DEBOUNCE_IRQ); - gpio_set_level(GPIO_USB_C0_HPD_OD, 1); - - gpio_set_level(GPIO_USB_C0_DP_OE_L, 0); - gpio_set_level(GPIO_USB_C0_DP_POLARITY, pd_get_polarity(port)); - - /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + - HPD_USTREAM_DEBOUNCE_LVL; - } else if (irq & !cur_lvl) { - CPRINTF("ERR:HPD:IRQ&LOW\n"); - return 0; /* nak */ - } else { - gpio_set_level(GPIO_USB_C0_HPD_OD, lvl); - gpio_set_level(GPIO_USB_C0_DP_OE_L, !lvl); - gpio_set_level(GPIO_USB_C0_DP_POLARITY, pd_get_polarity(port)); - /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + - HPD_USTREAM_DEBOUNCE_LVL; - } - - /* ack */ - return 1; -} - -__override void svdm_exit_dp_mode(int port) -{ - svdm_safe_dp_mode(port); - gpio_set_level(GPIO_USB_C0_HPD_OD, 0); - gpio_set_level(GPIO_USB_C0_DP_OE_L, 1); - usb_mux_hpd_update(port, 0, 0); -} -#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/board/fleex/battery.c b/board/fleex/battery.c index 57a5246052..e5efb19920 100644 --- a/board/fleex/battery.c +++ b/board/fleex/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/fleex/board.c b/board/fleex/board.c index c487da68f2..c8cecbadd4 100644 --- a/board/fleex/board.c +++ b/board/fleex/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Fleex board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery.h" #include "button.h" #include "charge_manager.h" @@ -18,6 +17,7 @@ #include "driver/accelgyro_lsm6dsm.h" #include "driver/charger/isl923x.h" #include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x.h" #include "driver/tcpm/anx7447.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" @@ -33,32 +33,71 @@ #include "power_button.h" #include "switch.h" #include "system.h" -#include "task.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "task.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define USB_PD_PORT_ANX7447 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 static uint8_t sku_id; +static int is_support_syv_ppc; + +const struct ppc_config_t ppc_syv682x_port0 = { + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, +}; + +const struct ppc_config_t ppc_syv682x_port1 = { + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, +}; + +/* Check PPC_ID pin status to decide which one ppc is used. */ +static int board_is_syv_ppc(void) +{ + return gpio_get_level(GPIO_PPC_ID); +} + +static void board_update_ppc_config_from_board(void) +{ + if (!is_support_syv_ppc) + return; + + memcpy(&ppc_chips[USB_PD_PORT_TCPC_0], &ppc_syv682x_port0, + sizeof(struct ppc_config_t)); + memcpy(&ppc_chips[USB_PD_PORT_TCPC_1], &ppc_syv682x_port1, + sizeof(struct ppc_config_t)); + + gpio_set_flags(GPIO_USB_PD_C0_INT_ODL, GPIO_INT_BOTH); + gpio_set_flags(GPIO_USB_PD_C1_INT_ODL, GPIO_INT_BOTH); +} static void ppc_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_PD_C0_INT_ODL: - nx20p348x_interrupt(0); + if (is_support_syv_ppc) + syv682x_interrupt(0); + else + nx20p348x_interrupt(0); break; case GPIO_USB_PD_C1_INT_ODL: - nx20p348x_interrupt(1); + if (is_support_syv_ppc) + syv682x_interrupt(1); + else + nx20p348x_interrupt(1); break; default: @@ -71,28 +110,30 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_VBUS_C0] = {"VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, - [ADC_VBUS_C1] = {"VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, + [ADC_VBUS_C0] = { "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + [ADC_VBUS_C1] = { "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -102,17 +143,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; - const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} - }; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct stprivate_data g_lis2dh_data; @@ -158,8 +195,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &base_standard_ref, @@ -190,8 +225,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -205,8 +238,8 @@ unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); static int board_is_convertible(void) { - return sku_id == 0x21 || sku_id == 0x22 || sku_id == 0x23 - || sku_id == 0xff; + return sku_id == 0x21 || sku_id == 0x22 || sku_id == 0x23 || + sku_id == 0xff; } static void board_update_sensor_config_from_sku(void) @@ -236,9 +269,8 @@ static void cbi_init(void) } DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -250,7 +282,6 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif void board_overcurrent_event(int port, int is_overcurrented) { @@ -265,9 +296,10 @@ void board_overcurrent_event(int port, int is_overcurrented) static void charger_set_buck_boost_mode(void) { int reg; - /* Reduce Buck-boost mode switching frequency to improve power efficiency. */ + /* Reduce Buck-boost mode switching frequency to improve power + * efficiency. */ if (i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - ISL9238_REG_CONTROL3, ®) == EC_SUCCESS) { + ISL9238_REG_CONTROL3, ®) == EC_SUCCESS) { reg |= ISL9238_C3_BB_SWITCHING_PERIOD; if (i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, ISL9238_REG_CONTROL3, reg)) @@ -278,5 +310,17 @@ static void charger_set_buck_boost_mode(void) static void board_init(void) { charger_set_buck_boost_mode(); + + is_support_syv_ppc = board_is_syv_ppc(); + + board_update_ppc_config_from_board(); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +int ppc_get_alert_status(int port) +{ + if (port == 0) + return gpio_get_level(GPIO_USB_PD_C0_INT_ODL) == 0; + + return gpio_get_level(GPIO_USB_PD_C1_INT_ODL) == 0; +} diff --git a/board/fleex/board.h b/board/fleex/board.h index fe48f4e232..3095fad271 100644 --- a/board/fleex/board.h +++ b/board/fleex/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,6 +13,8 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + /* EC console commands */ #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -31,8 +33,8 @@ #define CONFIG_USB_PD_RESET_MIN_BATT_SOC 2 /* Sensors */ -#define CONFIG_ACCEL_LIS2DE /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LIS2DE /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) #define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT @@ -65,16 +67,23 @@ #define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Additional PPC second source */ +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_DEDICATED_INT +/* SYV682 isn't connected to CC, so TCPC must provide VCONN */ +#define CONFIG_USBC_PPC_SYV682X_NO_CC + #ifndef __ASSEMBLER__ #include "gpio_signal.h" #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ - ADC_VBUS_C0, /* ADC9 */ - ADC_VBUS_C1, /* ADC4 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_VBUS_C0, /* ADC9 */ + ADC_VBUS_C1, /* ADC4 */ ADC_CH_COUNT }; @@ -85,18 +94,10 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { diff --git a/board/fleex/build.mk b/board/fleex/build.mk index 7e806f4667..0eab0adc21 100644 --- a/board/fleex/build.mk +++ b/board/fleex/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/fleex/ec.tasklist b/board/fleex/ec.tasklist index d98db145e7..977b8b01be 100644 --- a/board/fleex/ec.tasklist +++ b/board/fleex/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/fleex/gpio.inc b/board/fleex/gpio.inc index 726f2da951..0b74f8fa76 100644 --- a/board/fleex/gpio.inc +++ b/board/fleex/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -152,11 +152,12 @@ GPIO(EC_GPIO03, PIN(0, 3), GPIO_INPUT) /* TP only */ /* MKBP event synchronization */ GPIO(EC_INT_L, PIN(9, 4), GPIO_ODR_HIGH) /* EC_AP_INT_ODL */ +GPIO(PPC_ID, PIN(9, 7), GPIO_INPUT | GPIO_PULL_DOWN) /* PPC ID Pin */ + /* Unused Pins */ GPIO(CHARGER_PMON, PIN(4, 2), GPIO_INPUT) GPIO(CHARGER_IADP, PIN(4, 3), GPIO_INPUT) GPIO(EC_GPIO57, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) /* TP Only */ -GPIO(EC_GPIO97, PIN(9, 7), GPIO_INPUT | GPIO_PULL_UP) /* TP Only */ GPIO(EC_I2S_SFRM, PIN(A, 5), GPIO_INPUT | GPIO_SEL_1P8V) GPIO(EC_I2S_SCLK, PIN(A, 7), GPIO_INPUT | GPIO_SEL_1P8V) GPIO(EC_I2S_TX_PCH_RX, PIN(B, 0), GPIO_INPUT | GPIO_SEL_1P8V) diff --git a/board/fleex/led.c b/board/fleex/led.c index d502c16797..4ba3c18457 100644 --- a/board/fleex/led.c +++ b/board/fleex/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,38 +10,48 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1 = 10; +__override const int led_charge_lvl_1 = 10; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* Fleex: Note there is only LED for charge / power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0_BAT_LOW] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: @@ -76,4 +86,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/fleex/usb_pd_policy.c b/board/fleex/usb_pd_policy.c index 82922f9a4d..bfcf4484e4 100644 --- a/board/fleex/usb_pd_policy.c +++ b/board/fleex/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/fleex/vif_override.xml b/board/fleex/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/fleex/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/fluffy/board.c b/board/fluffy/board.c index 264ffc4478..b16170148e 100644 --- a/board/fluffy/board.c +++ b/board/fluffy/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,34 +6,34 @@ /* Fluffy configuration */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "console.h" #include "ec_version.h" #include "hooks.h" #include "i2c.h" -#include "usb_descriptor.h" #include "registers.h" #include "timer.h" +#include "usb_descriptor.h" #include "usb_pd.h" #include "util.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("Fluffy"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Fluffy"), /* This gets filled in at runtime. */ - [USB_STR_SERIALNO] = USB_STRING_DESC(""), - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_SERIALNO] = USB_STRING_DESC(""), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Fluffy Shell"), }; @@ -78,7 +78,7 @@ static void print_port_status(void) CPRINTS("USB MUX: %s", gpio_get_level(GPIO_EN_USB_MUX2) ? "ON" : "OFF"); } -static int command_cc_flip(int argc, char *argv[]) +static int command_cc_flip(int argc, const char *argv[]) { int enable; @@ -107,20 +107,19 @@ static int command_cc_flip(int argc, char *argv[]) print_port_status(); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(ccflip, command_cc_flip, - "", +DECLARE_CONSOLE_COMMAND(ccflip, command_cc_flip, "", "enable or disable flipping CC orientation"); /* * Support tca6416 I2C ioexpander. */ -#define GPIOX_I2C_ADDR_FLAGS 0x20 -#define GPIOX_IN_PORT_A 0x0 -#define GPIOX_IN_PORT_B 0x1 -#define GPIOX_OUT_PORT_A 0x2 -#define GPIOX_OUT_PORT_B 0x3 -#define GPIOX_DIR_PORT_A 0x6 -#define GPIOX_DIR_PORT_B 0x7 -#define I2C_PORT_MASTER 1 +#define GPIOX_I2C_ADDR_FLAGS 0x20 +#define GPIOX_IN_PORT_A 0x0 +#define GPIOX_IN_PORT_B 0x1 +#define GPIOX_OUT_PORT_A 0x2 +#define GPIOX_OUT_PORT_B 0x3 +#define GPIOX_DIR_PORT_A 0x6 +#define GPIOX_DIR_PORT_B 0x7 +#define I2C_PORT_MASTER 1 static void i2c_expander_init(void) { @@ -129,12 +128,12 @@ static void i2c_expander_init(void) /* * Setup P00, P02, P04, P10, and P12 on the I/O expander as an output. */ - i2c_write8(I2C_PORT_MASTER, GPIOX_I2C_ADDR_FLAGS, - GPIOX_DIR_PORT_A, 0xea); - i2c_write8(I2C_PORT_MASTER, GPIOX_I2C_ADDR_FLAGS, - GPIOX_DIR_PORT_B, 0xfa); + i2c_write8(I2C_PORT_MASTER, GPIOX_I2C_ADDR_FLAGS, GPIOX_DIR_PORT_A, + 0xea); + i2c_write8(I2C_PORT_MASTER, GPIOX_I2C_ADDR_FLAGS, GPIOX_DIR_PORT_B, + 0xfa); } -DECLARE_HOOK(HOOK_INIT, i2c_expander_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, i2c_expander_init, HOOK_PRIO_INIT_I2C + 1); /* Write to a GPIO register on the tca6416 I2C ioexpander. */ static void write_ioexpander(int bank, int gpio, int reg, int val) @@ -142,15 +141,13 @@ static void write_ioexpander(int bank, int gpio, int reg, int val) int tmp; /* Read output port register */ - i2c_read8(I2C_PORT_MASTER, GPIOX_I2C_ADDR_FLAGS, - reg + bank, &tmp); + i2c_read8(I2C_PORT_MASTER, GPIOX_I2C_ADDR_FLAGS, reg + bank, &tmp); if (val) tmp |= BIT(gpio); else tmp &= ~BIT(gpio); /* Write back modified output port register */ - i2c_write8(I2C_PORT_MASTER, GPIOX_I2C_ADDR_FLAGS, - reg + bank, tmp); + i2c_write8(I2C_PORT_MASTER, GPIOX_I2C_ADDR_FLAGS, reg + bank, tmp); } enum led_ch { @@ -228,7 +225,6 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - enum usb_mux { USB_MUX0 = 0, USB_MUX1, @@ -262,7 +258,7 @@ static void set_mux(enum usb_mux mux, uint8_t val) break; default: - break; + return; } val &= 0x7; @@ -273,7 +269,7 @@ static void set_mux(enum usb_mux mux, uint8_t val) } /* This function assumes only 1 port works at a time. */ -static int command_portctl(int argc, char **argv) +static int command_portctl(int argc, const char **argv) { int port; int enable; @@ -294,7 +290,7 @@ static int command_portctl(int argc, char **argv) gpio_set_level(enabled_port, 0); if (enabled_port != GPIO_EN_C0 + port) - CPRINTS("Port %d: disabled", enabled_port-GPIO_EN_C0); + CPRINTS("Port %d: disabled", enabled_port - GPIO_EN_C0); /* Allow time for an "unplug" to allow VBUS and CC to fall. */ usleep(1 * SECOND); @@ -310,17 +306,17 @@ static int command_portctl(int argc, char **argv) gpio_set_level(enabled_port, 1); if (port < 8) { - set_mux(USB_MUX0, 7-port); + set_mux(USB_MUX0, 7 - port); set_mux(USB_MUX2, 3); } else if (port < 16) { if (port < 14) - set_mux(USB_MUX1, 5-(port-8)); + set_mux(USB_MUX1, 5 - (port - 8)); else - set_mux(USB_MUX1, 7-(port-14)); + set_mux(USB_MUX1, 7 - (port - 14)); set_mux(USB_MUX2, 1); } else { - set_mux(USB_MUX2, 7-(port-16)); + set_mux(USB_MUX2, 7 - (port - 16)); } gpio_set_level(GPIO_EN_USB_MUX2, 1); @@ -338,11 +334,11 @@ DECLARE_CONSOLE_COMMAND(portctl, command_portctl, " ", "enable or disable a port"); -static int command_status(int argc, char **argv) +static int command_status(int argc, const char **argv) { int vbus_mv = adc_read_channel(ADC_PPVAR_VBUS_DUT); - CPRINTS("PPVAR_VBUS_DUT: %dmV (raw: %d)", vbus_mv*7692/1000, + CPRINTS("PPVAR_VBUS_DUT: %dmV (raw: %d)", vbus_mv * 7692 / 1000, vbus_mv); print_port_status(); @@ -389,7 +385,8 @@ void show_output_voltage_on_leds(void) set_led(i, i < max_on_exclusive); act = (vbus_mv * 76667) / 10000; - if ((vbus_mv > prev_vbus_mv+2) || (vbus_mv < prev_vbus_mv-2)) { + if ((vbus_mv > prev_vbus_mv + 2) || + (vbus_mv < prev_vbus_mv - 2)) { CPRINTS("PPVAR_VBUS_DUT: %d mV (raw: %d)", act, vbus_mv); prev_vbus_mv = vbus_mv; @@ -401,6 +398,5 @@ void show_output_voltage_on_leds(void) * a hook with a HOOK_TICK period is to allow the LED sweep sequence * when the board boots up. */ - hook_call_deferred(&show_output_voltage_on_leds_data, - 500 * MSEC); + hook_call_deferred(&show_output_voltage_on_leds_data, 500 * MSEC); } diff --git a/board/fluffy/board.h b/board/fluffy/board.h index 41c01bd8fa..604e67d9b8 100644 --- a/board/fluffy/board.h +++ b/board/fluffy/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -29,26 +29,25 @@ #define DEFAULT_SERIALNO "Uninitialized" /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_CONSOLE 0 -#define USB_IFACE_COUNT 1 +#define USB_IFACE_CONSOLE 0 +#define USB_IFACE_COUNT 1 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_CONSOLE 1 -#define USB_EP_COUNT 2 +#define USB_EP_CONTROL 0 +#define USB_EP_CONSOLE 1 +#define USB_EP_COUNT 2 /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_ADC #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #ifndef __ASSEMBLER__ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 +#define TIM_ADC 3 #include "gpio_signal.h" diff --git a/board/fluffy/build.mk b/board/fluffy/build.mk index b6761a4692..82aa7522d0 100644 --- a/board/fluffy/build.mk +++ b/board/fluffy/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,9 +10,4 @@ CHIP:=stm32 CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f07x -# Use coreboot-sdk -$(call set-option,CROSS_COMPILE_arm,\ - $(CROSS_COMPILE_coreboot_sdk_arm),\ - /opt/coreboot-sdk/bin/arm-eabi-) - board-y=board.o diff --git a/board/fluffy/ec.tasklist b/board/fluffy/ec.tasklist index c732944a23..9c45739414 100644 --- a/board/fluffy/ec.tasklist +++ b/board/fluffy/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/fluffy/gpio.inc b/board/fluffy/gpio.inc index 4c802554f9..532422ae5b 100644 --- a/board/fluffy/gpio.inc +++ b/board/fluffy/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/foob/battery.c b/board/foob/battery.c index 01a6654920..fe5692eec2 100644 --- a/board/foob/battery.c +++ b/board/foob/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/foob/board.c b/board/foob/board.c index 87a5c656de..65fafddd45 100644 --- a/board/foob/board.c +++ b/board/foob/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,7 @@ /* Phaser board-specific configuration */ #include "adc.h" -#include "adc_chip.h" +#include "battery_smart.h" #include "button.h" #include "charge_state.h" #include "common.h" @@ -24,19 +24,18 @@ #include "power.h" #include "power_button.h" #include "switch.h" -#include "task.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "task.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "util.h" -#include "battery_smart.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define USB_PD_PORT_ANX7447 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 static uint8_t sku_id; @@ -61,31 +60,31 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, /* Vbus sensing (1/10 voltage divider). */ - [ADC_VBUS_C0] = { - "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, - [ADC_VBUS_C1] = { - "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C0] = { "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + [ADC_VBUS_C1] = { "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -95,11 +94,9 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate lid and base sensor into standard reference frame */ -const mat33_fp_t standard_rot_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t standard_rot_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct stprivate_data g_lis2dh_data; @@ -145,8 +142,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &standard_rot_ref, @@ -177,8 +172,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -222,9 +215,8 @@ static void cbi_init(void) } DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -237,7 +229,6 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif int board_is_lid_angle_tablet_mode(void) { @@ -245,11 +236,11 @@ int board_is_lid_angle_tablet_mode(void) } /* Battery functions */ -#define SB_OPTIONALMFG_FUNCTION2 0x3e +#define SB_OPTIONALMFG_FUNCTION2 0x3e /* Optional mfg function2 */ -#define SMART_QUICK_CHARGE (1<<12) +#define SMART_QUICK_CHARGE (1 << 12) /* Quick charge support */ -#define MODE_QUICK_CHARGE_SUPPORT (1<<4) +#define MODE_QUICK_CHARGE_SUPPORT (1 << 4) static void sb_quick_charge_mode(int enable) { diff --git a/board/foob/board.h b/board/foob/board.h index 9e1c4d093c..f6d0f20607 100644 --- a/board/foob/board.h +++ b/board/foob/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,12 +13,13 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + #define CONFIG_VOLUME_BUTTONS #define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL #define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL #define CONFIG_LED_COMMON -#define CONFIG_LED_POWER_LED #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_13K7_47K_4050B @@ -29,8 +30,8 @@ #define CONFIG_CMD_ACCEL_INFO /* Sensors */ -#define CONFIG_ACCEL_LIS2DE /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LIS2DE /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) @@ -49,10 +50,10 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ - ADC_VBUS_C0, /* ADC9 */ - ADC_VBUS_C1, /* ADC4 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_VBUS_C0, /* ADC9 */ + ADC_VBUS_C1, /* ADC4 */ ADC_CH_COUNT, }; @@ -63,18 +64,10 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { diff --git a/board/foob/build.mk b/board/foob/build.mk index 137e208b53..fee77e38b5 100644 --- a/board/foob/build.mk +++ b/board/foob/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/foob/ec.tasklist b/board/foob/ec.tasklist index 6eac78a042..6c56976091 100644 --- a/board/foob/ec.tasklist +++ b/board/foob/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/foob/gpio.inc b/board/foob/gpio.inc index ad6773a211..3a553f6e91 100644 --- a/board/foob/gpio.inc +++ b/board/foob/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/foob/led.c b/board/foob/led.c index 0b582e9ca6..a7271f95d3 100644 --- a/board/foob/led.c +++ b/board/foob/led.c @@ -1,53 +1,57 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Phaser */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 97; +__override const int led_charge_lvl_2 = 97; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_ON_LVL); @@ -56,7 +60,7 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_RED: @@ -109,4 +113,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/foob/vif_override.xml b/board/foob/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/foob/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/fusb307bgevb/board.c b/board/fusb307bgevb/board.c index 35dececafb..2b9f4dac2f 100644 --- a/board/fusb307bgevb/board.c +++ b/board/fusb307bgevb/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,15 +17,15 @@ #include "task.h" #include "timer.h" #include "usart-stm32f0.h" -#include "usart_tx_dma.h" #include "usart_rx_dma.h" -#include "usb_gpio.h" +#include "usart_tx_dma.h" #include "usb-stream.h" #include "usb_common.h" +#include "usb_gpio.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { @@ -40,12 +40,13 @@ static int count; static void button_enter_event_deferred(void) { - uint32_t ma, mv; + uint32_t ma, mv, unused; CPRINTS("Button enter event"); if (count >= 0 && count < pd_get_src_cap_cnt(0)) { - pd_extract_pdo_power(pd_get_src_caps(0)[count], &ma, &mv); + pd_extract_pdo_power(pd_get_src_caps(0)[count], &ma, &mv, + &unused); pd_request_source_voltage(0, mv); } else { CPRINTS("ERROR: button counter weird value."); @@ -62,7 +63,7 @@ void button_enter_event(enum gpio_signal signal) static void button_refresh_event_deferred(void) { int i; - uint32_t ma, mv; + uint32_t ma, mv, unused; char c[20]; CPRINTS("Button refresh event"); @@ -71,10 +72,13 @@ static void button_refresh_event_deferred(void) /* Display supply voltage on first page. */ lcd_clear(); for (i = 0; i < MIN(pd_get_src_cap_cnt(0), 4); i++) { - pd_extract_pdo_power(pd_get_src_caps(0)[i], &ma, &mv); - snprintf(c, ARRAY_SIZE(c), "[%d] %dmV %dmA", i, mv, ma); - lcd_set_cursor(0, i); - lcd_print_string(c); + int rv; + pd_extract_pdo_power(pd_get_src_caps(0)[i], &ma, &mv, &unused); + rv = snprintf(c, ARRAY_SIZE(c), "[%d] %dmV %dmA", i, mv, ma); + if (rv > 0) { + lcd_set_cursor(0, i); + lcd_print_string(c); + } } /* Display selector */ @@ -91,7 +95,7 @@ void button_refresh_event(enum gpio_signal signal) static void button_down_event_deferred(void) { int i; - uint32_t ma, mv; + uint32_t ma, mv, unused; char c[20]; CPRINTS("Button down event"); @@ -106,19 +110,29 @@ static void button_down_event_deferred(void) if (count == 0) { lcd_clear(); for (i = 0; i < MIN(pd_get_src_cap_cnt(0), 4); i++) { - pd_extract_pdo_power(pd_get_src_caps(0)[i], &ma, &mv); - snprintf(c, ARRAY_SIZE(c), "[%d] %dmV %dmA", i, mv, ma); - lcd_set_cursor(0, i); - lcd_print_string(c); + int rv; + pd_extract_pdo_power(pd_get_src_caps(0)[i], &ma, &mv, + &unused); + rv = snprintf(c, ARRAY_SIZE(c), "[%d] %dmV %dmA", i, mv, + ma); + if (rv > 0) { + lcd_set_cursor(0, i); + lcd_print_string(c); + } } } if (count == 4) { lcd_clear(); for (i = 4; i < pd_get_src_cap_cnt(0); i++) { - pd_extract_pdo_power(pd_get_src_caps(0)[i], &ma, &mv); - snprintf(c, ARRAY_SIZE(c), "[%d] %dmV %dmA", i, mv, ma); - lcd_set_cursor(0, i - 4); - lcd_print_string(c); + int rv; + pd_extract_pdo_power(pd_get_src_caps(0)[i], &ma, &mv, + &unused); + rv = snprintf(c, ARRAY_SIZE(c), "[%d] %dmV %dmA", i, mv, + ma); + if (rv > 0) { + lcd_set_cursor(0, i - 4); + lcd_print_string(c); + } } } @@ -141,6 +155,7 @@ void button_down_event(enum gpio_signal signal) /****************************************************************************** * Build GPIO tables and expose a subset of the GPIOs over USB. */ +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" static enum gpio_signal const usb_gpio_list[] = { @@ -153,20 +168,15 @@ static enum gpio_signal const usb_gpio_list[] = { * This instantiates struct usb_gpio_config const usb_gpio, plus several other * variables, all named something beginning with usb_gpio_ */ -USB_GPIO_CONFIG(usb_gpio, - usb_gpio_list, - USB_IFACE_GPIO, - USB_EP_GPIO); +USB_GPIO_CONFIG(usb_gpio, usb_gpio_list, USB_IFACE_GPIO, USB_EP_GPIO); /****************************************************************************** * Setup USART1 as a loopback device, it just echo's back anything sent to it. */ static struct usart_config const loopback_usart; -static struct queue const loopback_queue = - QUEUE_DIRECT(64, uint8_t, - loopback_usart.producer, - loopback_usart.consumer); +static struct queue const loopback_queue = QUEUE_DIRECT( + 64, uint8_t, loopback_usart.producer, loopback_usart.consumer); static struct usart_rx_dma const loopback_rx_dma = USART_RX_DMA(STM32_DMAC_CH3, 8); @@ -174,14 +184,9 @@ static struct usart_rx_dma const loopback_rx_dma = static struct usart_tx_dma const loopback_tx_dma = USART_TX_DMA(STM32_DMAC_CH2, 16); -static struct usart_config const loopback_usart = - USART_CONFIG(usart1_hw, - loopback_rx_dma.usart_rx, - loopback_tx_dma.usart_tx, - 115200, - 0, - loopback_queue, - loopback_queue); +static struct usart_config const loopback_usart = USART_CONFIG( + usart1_hw, loopback_rx_dma.usart_rx, loopback_tx_dma.usart_tx, 115200, + 0, loopback_queue, loopback_queue); /****************************************************************************** * Forward USART4 as a simple USB serial interface. @@ -189,46 +194,34 @@ static struct usart_config const loopback_usart = static struct usart_config const forward_usart; struct usb_stream_config const forward_usb; -static struct queue const usart_to_usb = QUEUE_DIRECT(64, uint8_t, - forward_usart.producer, - forward_usb.consumer); -static struct queue const usb_to_usart = QUEUE_DIRECT(64, uint8_t, - forward_usb.producer, - forward_usart.consumer); +static struct queue const usart_to_usb = + QUEUE_DIRECT(64, uint8_t, forward_usart.producer, forward_usb.consumer); +static struct queue const usb_to_usart = + QUEUE_DIRECT(64, uint8_t, forward_usb.producer, forward_usart.consumer); static struct usart_tx_dma const forward_tx_dma = USART_TX_DMA(STM32_DMAC_CH7, 16); static struct usart_config const forward_usart = - USART_CONFIG(usart4_hw, - usart_rx_interrupt, - forward_tx_dma.usart_tx, - 115200, - 0, - usart_to_usb, - usb_to_usart); - -#define USB_STREAM_RX_SIZE 16 -#define USB_STREAM_TX_SIZE 16 - -USB_STREAM_CONFIG(forward_usb, - USB_IFACE_STREAM, - USB_STR_STREAM_NAME, - USB_EP_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart, - usart_to_usb) + USART_CONFIG(usart4_hw, usart_rx_interrupt, forward_tx_dma.usart_tx, + 115200, 0, usart_to_usb, usb_to_usart); + +#define USB_STREAM_RX_SIZE 16 +#define USB_STREAM_TX_SIZE 16 + +USB_STREAM_CONFIG(forward_usb, USB_IFACE_STREAM, USB_STR_STREAM_NAME, + USB_EP_STREAM, USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, + usb_to_usart, usart_to_usb) /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("fusb307bgevb"), - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_STREAM_NAME] = USB_STRING_DESC("Forward"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("fusb307bgevb"), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_STREAM_NAME] = USB_STRING_DESC("Forward"), [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Shell"), }; @@ -237,9 +230,11 @@ BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); /****************************************************************************** * I2C interface. */ -const struct i2c_port_t i2c_ports[] = { - {"tcpc", I2C_PORT_TCPC, 400 /* kHz */, GPIO_I2C2_SCL, GPIO_I2C2_SDA} -}; +const struct i2c_port_t i2c_ports[] = { { .name = "tcpc", + .port = I2C_PORT_TCPC, + .kbps = 400 /* kHz */, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA } }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /****************************************************************************** @@ -250,13 +245,12 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC, - .addr_flags = FUSB307_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB307_I2C_ADDR_FLAGS, }, .drv = &fusb307_tcpm_drv, }, }; - uint16_t tcpc_get_alert_status(void) { uint16_t status = 0; @@ -320,6 +314,5 @@ static void board_init(void) queue_init(&usb_to_usart); usart_init(&loopback_usart); usart_init(&forward_usart); - } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/fusb307bgevb/board.h b/board/fusb307bgevb/board.h index 2497dc7c69..8d2fdfcfed 100644 --- a/board/fusb307bgevb/board.h +++ b/board/fusb307bgevb/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H +#define CONFIG_LTO /* 48 MHz SYSCLK clock frequency */ #define CPU_CLOCK 48000000 @@ -28,10 +29,9 @@ #define CONFIG_UART_CONSOLE 2 /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_HW_CRC #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER /* USB Configuration */ #define CONFIG_USB @@ -52,16 +52,15 @@ #define CONFIG_USB_PD_TCPM_FUSB307 /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define operating power and max power */ #define PD_OPERATING_POWER_MW 15000 #define PD_MAX_VOLTAGE_MV 20000 #define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) /* Degine board specific type-C power constants */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 160000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 160000 /* us */ /* I2C master port connected to the TCPC */ #define I2C_PORT_TCPC 1 @@ -70,23 +69,24 @@ #define LCD_SLAVE_ADDR 0x27 /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_STREAM 0 -#define USB_IFACE_GPIO 1 -#define USB_IFACE_SPI 2 +#define USB_IFACE_STREAM 0 +#define USB_IFACE_GPIO 1 +#define USB_IFACE_SPI 2 #define USB_IFACE_CONSOLE 3 -#define USB_IFACE_COUNT 4 +#define USB_IFACE_COUNT 4 /* USB endpoint indexes (use define rather than enum to expand them) */ #define USB_EP_CONTROL 0 -#define USB_EP_STREAM 1 -#define USB_EP_GPIO 2 -#define USB_EP_SPI 3 +#define USB_EP_STREAM 1 +#define USB_EP_GPIO 2 +#define USB_EP_SPI 3 #define USB_EP_CONSOLE 4 -#define USB_EP_COUNT 5 +#define USB_EP_COUNT 5 /* Enable control of GPIOs over USB */ #define CONFIG_USB_GPIO +#undef CONFIG_CMD_GETTIME #undef CONFIG_WATCHDOG_HELP #undef CONFIG_LID_SWITCH diff --git a/board/fusb307bgevb/build.mk b/board/fusb307bgevb/build.mk index 1372562107..923b144165 100644 --- a/board/fusb307bgevb/build.mk +++ b/board/fusb307bgevb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/fusb307bgevb/ec.tasklist b/board/fusb307bgevb/ec.tasklist index e25b8f7a68..bca2d075be 100644 --- a/board/fusb307bgevb/ec.tasklist +++ b/board/fusb307bgevb/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/fusb307bgevb/gpio.inc b/board/fusb307bgevb/gpio.inc index 16a845576d..ba3b84fb08 100644 --- a/board/fusb307bgevb/gpio.inc +++ b/board/fusb307bgevb/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/fusb307bgevb/lcd.c b/board/fusb307bgevb/lcd.c index 892888329e..f907de7462 100644 --- a/board/fusb307bgevb/lcd.c +++ b/board/fusb307bgevb/lcd.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -26,17 +26,17 @@ static struct lcd_state_info state = { /* write either command or data */ static void expander_write(uint8_t data) { - i2c_write8(I2C_PORT_TCPC, LCD_SLAVE_ADDR, 0x00, data | - state.backlightval); + i2c_write8(I2C_PORT_TCPC, LCD_SLAVE_ADDR, 0x00, + data | state.backlightval); } static void pulse_enable(uint8_t data) { - expander_write(data | LCD_EN);/* En high */ - usleep(1); /* enable pulse must be >450ns */ + expander_write(data | LCD_EN); /* En high */ + usleep(1); /* enable pulse must be >450ns */ - expander_write(data & ~LCD_EN);/* En low */ - usleep(50); /* commands need > 37us to settle */ + expander_write(data & ~LCD_EN); /* En low */ + usleep(50); /* commands need > 37us to settle */ } static void write_4bits(uint8_t value) @@ -63,8 +63,8 @@ static void command(uint8_t value) /********** high level commands, for the user! */ void lcd_clear(void) { - command(LCD_CLEAR_DISPLAY);/* clear display, set cursor to zero */ - usleep(2000); /* this command takes a long time! */ + command(LCD_CLEAR_DISPLAY); /* clear display, set cursor to zero */ + usleep(2000); /* this command takes a long time! */ } void lcd_set_cursor(uint8_t col, uint8_t row) diff --git a/board/fusb307bgevb/lcd.h b/board/fusb307bgevb/lcd.h index 21b0ee9ce9..9ed773d92f 100644 --- a/board/fusb307bgevb/lcd.h +++ b/board/fusb307bgevb/lcd.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,50 +11,50 @@ #include "common.h" /* commands */ -#define LCD_CLEAR_DISPLAY BIT(0) -#define LCD_RETURN_HOME BIT(1) -#define LCD_ENTRYMODE_SET BIT(2) -#define LCD_DISPLAY_CONTROL BIT(3) -#define LCD_CURSOR_SHIFT BIT(4) -#define LCD_FUNCTION_SET BIT(5) -#define LCD_SET_CGRAMADDR BIT(6) -#define LCD_SET_DDRAMADDR BIT(7) +#define LCD_CLEAR_DISPLAY BIT(0) +#define LCD_RETURN_HOME BIT(1) +#define LCD_ENTRYMODE_SET BIT(2) +#define LCD_DISPLAY_CONTROL BIT(3) +#define LCD_CURSOR_SHIFT BIT(4) +#define LCD_FUNCTION_SET BIT(5) +#define LCD_SET_CGRAMADDR BIT(6) +#define LCD_SET_DDRAMADDR BIT(7) /* flags for display entry mode */ -#define LCD_ENTRY_RIGHT 0x00 -#define LCD_ENTRY_LEFT BIT(1) -#define LCD_ENTRY_SHIFT_INCREMENT BIT(0) -#define LCD_ENTRY_SHIFT_DECREMENT 0x00 +#define LCD_ENTRY_RIGHT 0x00 +#define LCD_ENTRY_LEFT BIT(1) +#define LCD_ENTRY_SHIFT_INCREMENT BIT(0) +#define LCD_ENTRY_SHIFT_DECREMENT 0x00 /* flags for display on/off control */ -#define LCD_DISPLAY_ON BIT(2) -#define LCD_DISPLAY_OFF 0x00 -#define LCD_CURSOR_ON BIT(1) -#define LCD_CURSOR_OFF 0x00 -#define LCD_BLINK_ON BIT(0) -#define LCD_BLINK_OFF 0x00 +#define LCD_DISPLAY_ON BIT(2) +#define LCD_DISPLAY_OFF 0x00 +#define LCD_CURSOR_ON BIT(1) +#define LCD_CURSOR_OFF 0x00 +#define LCD_BLINK_ON BIT(0) +#define LCD_BLINK_OFF 0x00 /* flags for display/cursor shift */ -#define LCD_DISPLAY_MOVE BIT(3) -#define LCD_CURSOR_MOVE 0x00 -#define LCD_MOVE_RIGHT BIT(2) -#define LCD_MOVE_LEFT 0x00 +#define LCD_DISPLAY_MOVE BIT(3) +#define LCD_CURSOR_MOVE 0x00 +#define LCD_MOVE_RIGHT BIT(2) +#define LCD_MOVE_LEFT 0x00 /* flags for function set */ -#define LCD_8BITMODE BIT(4) -#define LCD_4BITMODE 0x00 -#define LCD_2LINE BIT(3) -#define LCD_1LINE 0x00 -#define LCD_5X10DOTS BIT(2) -#define LCD_5X8DOTS 0x00 +#define LCD_8BITMODE BIT(4) +#define LCD_4BITMODE 0x00 +#define LCD_2LINE BIT(3) +#define LCD_1LINE 0x00 +#define LCD_5X10DOTS BIT(2) +#define LCD_5X8DOTS 0x00 /* flags for backlight control */ -#define LCD_BACKLIGHT BIT(3) -#define LCD_NO_BACKLIGHT 0x00 +#define LCD_BACKLIGHT BIT(3) +#define LCD_NO_BACKLIGHT 0x00 -#define LCD_EN BIT(2) /* Enable bit */ -#define LCD_RW BIT(1) /* Read/Write bit */ -#define LCD_RS BIT(0) /* Register select bit */ +#define LCD_EN BIT(2) /* Enable bit */ +#define LCD_RW BIT(1) /* Read/Write bit */ +#define LCD_RS BIT(0) /* Register select bit */ void lcd_init(uint8_t cols, uint8_t rows, uint8_t dotsize); void lcd_set_cursor(uint8_t col, uint8_t row); diff --git a/board/fusb307bgevb/vif_override.xml b/board/fusb307bgevb/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/fusb307bgevb/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/gaelin/board.c b/board/gaelin/board.c new file mode 100644 index 0000000000..32ab3e3fdc --- /dev/null +++ b/board/gaelin/board.c @@ -0,0 +1,616 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "assert.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/cec/bitbang.h" +#include "driver/retimer/ps8811.h" +#include "driver/tcpm/tcpci.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ +/* USB-A retimer control */ + +const struct usb_mux usba_ps8811[] = { + [USBA_PORT_A0] = { + .usb_port = USBA_PORT_A0, + .i2c_port = I2C_PORT_USB_A0_A1_MIX, + .i2c_addr_flags = PS8811_I2C_ADDR_FLAGS0, + }, + [USBA_PORT_A1] = { + .usb_port = USBA_PORT_A1, + .i2c_port = I2C_PORT_USB_A0_A1_MIX, + .i2c_addr_flags = PS8811_I2C_ADDR_FLAGS2, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usba_ps8811) == USBA_PORT_COUNT); + +static int usba_retimer_init(int port) +{ + int rv, val; + const struct usb_mux *me = &usba_ps8811[port]; + + rv = ps8811_i2c_read(me, PS8811_REG_PAGE1, PS8811_REG1_USB_BEQ_LEVEL, + &val); + + if (rv) { + CPRINTS("A%d: PS8811 retimer not detected!", port); + } else { + CPRINTS("A%d: PS8811 retimer detected", port); + } + + if (port == USBA_PORT_A1) { + /* Set channel B output swing */ + /* offset 0xA4, Data 0x04 */ + rv |= ps8811_i2c_field_update(me, PS8811_REG_PAGE1, + PS8811_REG1_USB_CHAN_B_SWING, + PS8811_CHAN_B_SWING_MASK, 0x4); + + /* Set channel B output DE level */ + /* offset 0xA6, Data 0x12 */ + rv |= ps8811_i2c_field_update(me, PS8811_REG_PAGE1, + PS8811_REG1_USB_CHAN_B_DE_PS_MSB, + PS8811_CHAN_B_DE_PS_MSB_MASK, + 0x12); + } + + return rv; +} + +void board_chipset_startup(void) +{ + int i; + + for (i = 0; i < USBA_PORT_COUNT; i++) + usba_retimer_init(i); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +/******************************************************************************/ + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + case CHARGE_PORT_TYPEC1: + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power_s5; +static int32_t base_5v_power_z1; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ + +/* PP5000_S5 loads */ +#define PWR_S5_BASE_LOAD (5 * 1431) +#define PWR_S5_FRONT_HIGH (5 * 1737) +#define PWR_S5_FRONT_LOW (5 * 1055) +#define PWR_S5_REAR_HIGH (5 * 1737) +#define PWR_S5_REAR_LOW (5 * 1055) +#define PWR_S5_HDMI (5 * 580) +#define PWR_S5_MAX (5 * 10000) +#define FRONT_DELTA (PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW) +#define REAR_DELTA (PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW) + +/* PP5000_Z1 loads */ +#define PWR_Z1_BASE_LOAD (5 * 5) +#define PWR_Z1_C_HIGH (5 * 3600) +#define PWR_Z1_C_LOW (5 * 2000) +#define PWR_Z1_MAX (5 * 9000) +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int front_ports = 0; + int rear_ports = 0; + + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power_s5 = PWR_S5_BASE_LOAD; + if (!gpio_get_level(GPIO_USB_A0_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + /* + * Only 1 front port can run higher power at a time. + */ + if (front_ports > 0) + base_5v_power_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + + if (!gpio_get_level(GPIO_USB_A2_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + if (!gpio_get_level(GPIO_USB_A3_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + /* + * Only 1 rear port can run higher power at a time. + */ + if (rear_ports > 0) + base_5v_power_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + if (!gpio_get_level(GPIO_HDMI_CONN_OC_ODL)) + base_5v_power_s5 += PWR_S5_HDMI; + base_5v_power_z1 = PWR_Z1_BASE_LOAD; + if (usbc_overcurrent) + base_5v_power_z1 += PWR_Z1_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) + ec_bj_power(&pi.voltage, &pi.current); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +static void adp_state_init(void) +{ + ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT); + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +static void board_init(void) +{ + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + gpio_enable_interrupt(GPIO_HDMI_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A2_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A3_OC_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Check that port number is valid. */ + if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) + return; + usbc_overcurrent = is_overcurrented; + update_5v_usage(); +} + +/* + * Power monitoring and management. + * + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * The overall goal is to gracefully manage the power demand so that + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type A BC1.2 rear port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 3 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A_FRONT BIT(0) +#define THROT_TYPE_A_REAR BIT(1) +#define THROT_TYPE_C0 BIT(2) +#define THROT_TYPE_C1 BIT(3) +#define THROT_PROCHOT BIT(5) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + static uint32_t history[POWER_READINGS]; + static uint8_t index; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v_s5 = PWR_S5_MAX - base_5v_power_s5; + int32_t headroom_5v_z1 = PWR_Z1_MAX - base_5v_power_z1; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + /* + * Clear the first entry of the power table so that + * it is re-initilalised when the CPU starts. + */ + history[0] = 0; + } else { + int32_t charger_mw; + + delay = POWER_DELAY_MS * MSEC; + /* + * Get current charger limit (in mw). + * If not configured yet, skip. + */ + charger_mw = charge_manager_get_power_limit_uw() / 1000; + if (charger_mw != 0) { + int32_t gap, total, max, power; + int i; + + /* + * Read power usage. + */ + power = (adc_read_channel(ADC_VBUS) * + adc_read_channel(ADC_PPVAR_IMON)) / + 1000; + /* Init power table */ + if (history[0] == 0) { + for (i = 0; i < POWER_READINGS; i++) + history[i] = power; + } + /* + * Update the power readings and + * calculate the average and max. + */ + history[index] = power; + index = (index + 1) % POWER_READINGS; + total = 0; + max = history[0]; + for (i = 0; i < POWER_READINGS; i++) { + total += history[i]; + if (history[i] > max) + max = history[i]; + } + /* + * For Type-C power supplies, there is + * less tolerance for exceeding the rating, + * so use the max power that has been measured + * over the measuring period. + * For barrel-jack supplies, the rating can be + * exceeded briefly, so use the average. + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + power = max; + else + power = total / POWER_READINGS; + /* + * Calculate gap, and if negative, power + * demand is exceeding configured power budget, so + * throttling is required to reduce the demand. + */ + gap = charger_mw - power; + /* + * Limiting type-A power rear ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_REAR; + headroom_5v_s5 += REAR_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * Limiting type-A power front ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_FRONT; + headroom_5v_s5 += FRONT_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(0) && gap <= 0) { + new_state |= THROT_TYPE_C0; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C0)) + gap += POWER_GAIN_TYPE_C; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(1) && gap <= 0) { + new_state |= THROT_TYPE_C1; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C1)) + gap += POWER_GAIN_TYPE_C; + } + /* + * As a last resort, turn on PROCHOT to + * throttle the CPU. + */ + if (gap <= 0) + new_state |= THROT_PROCHOT; + } + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v_z1 < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C0) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + new_state |= THROT_TYPE_C0; + } + /* + * [2] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v_z1 < 0) + new_state |= THROT_TYPE_C0; + } + if (headroom_5v_s5 < 0) { + /* + * [1] If type A rear not already throttled, and power still + * needed, limit type A rear. + */ + if (!(new_state & THROT_TYPE_A_REAR) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + new_state |= THROT_TYPE_A_REAR; + } + /* + * [2] If type A front not already throttled, and power still + * needed, limit type A front. + */ + if (!(new_state & THROT_TYPE_A_FRONT) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + new_state |= THROT_TYPE_A_FRONT; + } + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_C0) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C0) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + } + if (diff & THROT_TYPE_C1) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C1) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(1, rp); + tcpm_select_rp_value(1, rp); + pd_update_contract(1); + } + if (diff & THROT_TYPE_A_REAR) { + int typea_bc = (new_state & THROT_TYPE_A_REAR) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR0_OD, typea_bc); + gpio_set_level(GPIO_USB_A_LOW_PWR1_OD, typea_bc); + } + if (diff & THROT_TYPE_A_FRONT) { + int typea_bc = (new_state & THROT_TYPE_A_FRONT) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR2_OD, typea_bc); + gpio_set_level(GPIO_USB_A_LOW_PWR3_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/gaelin/board.h b/board/gaelin/board.h new file mode 100644 index 0000000000..a469deafb3 --- /dev/null +++ b/board/gaelin/board.h @@ -0,0 +1,176 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brask board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +#define CONFIG_MP2964 + +/* Barrel Jack */ +#define DEDICATED_CHARGE_PORT 2 + +/* HDMI CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMI_CEC_OUT +#define CEC_GPIO_IN GPIO_HDMI_CEC_IN +#define CEC_GPIO_PULL_UP GPIO_HDMI_CEC_PULL_UP + +/* USB Type A Features */ +#define USB_PORT_COUNT 4 +#define CONFIG_USB_PORT_POWER_DUMB +#define CONFIG_USBC_RETIMER_PS8811 + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_USB_PD_PPC +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USBC_PPC_NX20P3483 /* Compatible with Silicon Mitus SM5360A */ + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* The design should support up to 100W. */ +/* TODO(b/197702356): Set the max PD to 60W now and change it + * to 100W after we verify it. + */ +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_OD + +/* I2C Bus Configuration */ +#define I2C_PORT_SCALER NPCX_I2C_PORT5_0 + +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT3_0 + +#define I2C_PORT_USB_C0_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT3_0 + +#define I2C_PORT_USB_A0_A1_MIX NPCX_I2C_PORT6_1 + +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +#define I2C_ADDR_SCALER_FLAGS 0x58 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* ADC */ +#define CONFIG_ADC + +/* Fan */ +#define CONFIG_FANS FAN_CH_COUNT +#define RPM_DEVIATION 1 +#define CONFIG_CUSTOM_FAN_CONTROL + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_TYPEC1, + CHARGE_PORT_BARRELJACK, + CHARGE_PORT_ENUM_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1_CPU, + ADC_TEMP_SENSOR_2_CPU_VR, + ADC_TEMP_SENSOR_3_WIFI, + ADC_TEMP_SENSOR_4_DIMM, + ADC_VBUS, + ADC_PPVAR_IMON, /* ADC3 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_CPU, + TEMP_SENSOR_2_CPU_VR, + TEMP_SENSOR_3_WIFI, + TEMP_SENSOR_4_DIMM, + TEMP_SENSOR_COUNT +}; + +enum pwm_channel { + PWM_CH_LED_GREEN, /* PWM0 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED_RED, /* PWM2 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +extern void adp_connect_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/gaelin/build.mk b/board/gaelin/build.mk new file mode 100644 index 0000000000..6961fb3f60 --- /dev/null +++ b/board/gaelin/build.mk @@ -0,0 +1,23 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brask board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brask + +board-y= +board-y+=board.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=thermal.o +board-y+=usbc_config.o diff --git a/board/gaelin/ec.tasklist b/board/gaelin/ec.tasklist new file mode 100644 index 0000000000..4a40f332e8 --- /dev/null +++ b/board/gaelin/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/gaelin/fans.c b/board/gaelin/fans.c new file mode 100644 index 0000000000..c92ae84872 --- /dev/null +++ b/board/gaelin/fans.c @@ -0,0 +1,44 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2350, + .rpm_start = 2350, + .rpm_max = 4100, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/gaelin/fw_config.c b/board/gaelin/fw_config.c new file mode 100644 index 0000000000..3ee71e6a0f --- /dev/null +++ b/board/gaelin/fw_config.c @@ -0,0 +1,65 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union brask_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brask if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union brask_cbi_fw_config fw_config_defaults = { + .audio = DB_NAU88L25B_I2S, + .bj_power = BJ_135W, +}; + +/* + * Barrel-jack power adapter ratings. + */ +static const struct { + int voltage; + int current; +} bj_power[] = { + [BJ_135W] = { /* 0 - 135W (also default) */ + .voltage = 19500, + .current = 6920 + }, + [BJ_230W] = { /* 1 - 230W */ + .voltage = 19500, + .current = 11800 + } +}; + +/**************************************************************************** + * Brask FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +void ec_bj_power(uint32_t *voltage, uint32_t *current) +{ + unsigned int bj; + + bj = fw_config.bj_power; + /* Out of range value defaults to 0 */ + if (bj >= ARRAY_SIZE(bj_power)) + bj = 0; + *voltage = bj_power[bj].voltage; + *current = bj_power[bj].current; +} diff --git a/board/gaelin/fw_config.h b/board/gaelin/fw_config.h new file mode 100644 index 0000000000..95d81f1e05 --- /dev/null +++ b/board/gaelin/fw_config.h @@ -0,0 +1,41 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_BRASK_FW_CONFIG_H_ +#define __BOARD_BRASK_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Brask board. + * + * Source of truth is the project/brask/brask/config.star configuration file. + */ +enum ec_cfg_audio_type { DB_AUDIO_UNKNOWN = 0, DB_NAU88L25B_I2S = 1 }; + +enum ec_cfg_bj_power { BJ_135W = 0, BJ_230W = 1 }; + +union brask_cbi_fw_config { + struct { + uint32_t audio : 3; + uint32_t bj_power : 2; + uint32_t reserved_1 : 27; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union brask_cbi_fw_config get_fw_config(void); + +/** + * Get the barrel-jack power from FW_CONFIG. + */ +void ec_bj_power(uint32_t *voltage, uint32_t *current); + +#endif /* __BOARD_BRASK_FW_CONFIG_H_ */ diff --git a/board/gaelin/gpio.inc b/board/gaelin/gpio.inc new file mode 100644 index 0000000000..3e84f2e692 --- /dev/null +++ b/board/gaelin/gpio.inc @@ -0,0 +1,176 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTERRUPT GPIOs: */ + +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(2, 3), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(HDMI_CONN_OC_ODL, PIN(2, 4), GPIO_INPUT | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A0_OC_ODL, PIN(3, 1), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A2_OC_ODL, PIN(2, 7), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A3_OC_ODL, PIN(2, 6), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) + +/* CCD */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + +/* Security */ +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Fan */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) + +/* ADC, need to check the usage */ +GPIO(ANALOG_PPVAR_PWR_IN_IMON_EC, PIN(4, 2), GPIO_INPUT) + +/* Display */ +GPIO(EC_OVERRIDE_SCLR_EN, PIN(D, 4), GPIO_OUT_HIGH) + +/* TODO(b/260063632): the gpio pin control is wip, setting to level high + to enable the backlight by default */ +GPIO(EC_12VSC_EN, PIN(D, 2), GPIO_OUT_HIGH) + +GPIO(OSD_STS, PIN(4, 1), GPIO_INPUT) +GPIO(DISP_MODE, PIN(A, 0), GPIO_INPUT) +GPIO(PANEL_PWR_STS, PIN(9, 5), GPIO_INPUT) +GPIO(EN_SCLR_RAILS, PIN(0, 4), GPIO_INPUT) +GPIO(HDMI_5V_IN, PIN(9, 3), GPIO_INPUT) +GPIO(HDMI0_CABLE_DET, PIN(9, 6), GPIO_INPUT) +GPIO(WP_EC, PIN(C, 3), GPIO_INPUT) +GPIO(OSD_INT, PIN(0, 5), GPIO_INPUT) + +/* Audio */ +/* TODO(b/260063632): the gpio pin control is wip, setting to level high + to enable the speaker by default */ +GPIO(EC_AMP_SD, PIN(5, 6), GPIO_OUT_HIGH) + +/* BarrelJack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 7), GPIO_OUT_LOW) + +/* Chipset PCH */ +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) + +/* Button */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(GSC_EC_RECOVERY_BTN_OD, PIN(2, 2), GPIO_INPUT) + +/* HDMI CEC */ +/* TODO(b/197474873): Enable HDMI CEC */ +GPIO(HDMI_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CEC_OUT, PIN(D, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMI_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH) + +/* I2C SCL/SDA */ +GPIO(SMSCALER_CLK, PIN(3, 3), GPIO_INPUT) +GPIO(SMSCALER_DATA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PPC_BC_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PPC_BC_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_A1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_A1_MIX_SDA, PIN(E, 3), GPIO_INPUT) + +/* USBA */ +GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW) +GPIO(USB_A0_STATUS_L, PIN(2, 1), GPIO_INPUT) +GPIO(USB_A1_STATUS_L, PIN(2, 0), GPIO_INPUT) +GPIO(USB_A2_STATUS_L, PIN(1, 7), GPIO_INPUT) +GPIO(USB_A3_STATUS_L, PIN(1, 6), GPIO_INPUT) +GPIO(USB_A_LOW_PWR0_OD, PIN(1, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR1_OD, PIN(1, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR2_OD, PIN(1, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR3_OD, PIN(1, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH) + +/* LED */ +/* TODO(b/197471359): LED implementation */ +GPIO(LED_RED_L, PIN(C, 4), GPIO_OUT_LOW) + +/* USBC */ +GPIO(USB_C0_FRS_EN, PIN(9, 7), GPIO_OUT_LOW) +GPIO(USB_C0_RT_RST_L, PIN(A, 7), GPIO_OUT_HIGH) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RT_RST_L, PIN(0, 2), GPIO_OUT_HIGH) + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ +/* GPIO07_P2 to PU */ + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO36/RTS_L/I2C5_SDA0, GPIO33/I2C5_SCL0/CTS_L */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */ +UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */ +UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */ +UNUSED(PIN(0, 6)) /* KSO11/GPIO06/P80_CLK */ +UNUSED(PIN(B, 4)) /* GPIOB4/I2C0_SDA0 */ +UNUSED(PIN(2, 5)) /* KSI4/GPIO25/TRACECLK/GP_SCLK */ +UNUSED(PIN(B, 5)) /* GPIOB5/I2C0_SCL0 */ +UNUSED(PIN(8, 3)) /* KSO15/GPIO83 */ +UNUSED(PIN(B, 1)) /* KSO17/GPIOB1/CR_SIN4 */ +UNUSED(PIN(7, 0)) /* GPIO70/PS2_DAT0 */ +UNUSED(PIN(A, 3)) /* SPIP_MOSI/GPIOA3 */ diff --git a/board/gaelin/i2c.c b/board/gaelin/i2c.c new file mode 100644 index 0000000000..ce285d16b4 --- /dev/null +++ b/board/gaelin/i2c.c @@ -0,0 +1,69 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0", + .port = I2C_PORT_USB_C0_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C1_PPC_BC_SDA, + }, + { + /* I2C4 */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + }, + { + /* I2C5 */ + .name = "scaler", + .port = I2C_PORT_SCALER, + .kbps = 400, + .scl = GPIO_SMSCALER_CLK, + .sda = GPIO_SMSCALER_DATA, + }, + { + /* I2C6 */ + .name = "usba0_retimer,usba1_retimer", + .port = I2C_PORT_USB_A0_A1_MIX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_A0_A1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_A0_A1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/gaelin/led.c b/board/gaelin/led.c new file mode 100644 index 0000000000..a4b9a0d094 --- /dev/null +++ b/board/gaelin/led.c @@ -0,0 +1,260 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Brask. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_GREEN, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int green = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_GREEN: + green = 1; + break; + case LED_RED: + red = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (green) + pwm_set_duty(PWM_CH_LED_GREEN, duty); + else + pwm_set_duty(PWM_CH_LED_GREEN, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* + * When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_GREEN); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* + * Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_GREEN, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "green")) { + set_color(id, LED_GREEN, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|red|green|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_GREEN] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_GREEN]) + return set_color(id, LED_GREEN, brightness[EC_LED_COLOR_GREEN]); + else + return set_color(id, LED_OFF, 0); +} +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Blink alert if insufficient power per system_can_boot_ap(). */ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + led_alert(insufficient_power); +} diff --git a/board/gaelin/pwm.c b/board/gaelin/pwm.c new file mode 100644 index 0000000000..bf90ad5f63 --- /dev/null +++ b/board/gaelin/pwm.c @@ -0,0 +1,39 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_GREEN] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * TODO(b/197478860): Turn on the fan at 100% by default + * We need to find tune the fan speed according to the + * thermal sensor value. + */ + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, 100); + + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_GREEN, 1); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/gaelin/sensors.c b/board/gaelin/sensors.c new file mode 100644 index 0000000000..13948f60d8 --- /dev/null +++ b/board/gaelin/sensors.c @@ -0,0 +1,114 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_CPU] = { + .name = "TEMP_CPU", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CPU_VR] = { + .name = "TEMP_CPU_VR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_WIFI] = { + .name = "TEMP_WIFI", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DIMM] = { + .name = "TEMP_DIMM", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 872.3 mV/A */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT * 1433, + .factor_div = (ADC_READ_MAX + 1) * 1250, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_CPU] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_CPU }, + [TEMP_SENSOR_2_CPU_VR] = { .name = "CPU VR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CPU_VR }, + [TEMP_SENSOR_3_WIFI] = { .name = "WIFI", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_WIFI }, + [TEMP_SENSOR_4_DIMM] = { .name = "DIMM", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DIMM }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/197478860): add the thermal sensor setting + */ +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CPU] = THERMAL_CPU, + [TEMP_SENSOR_2_CPU_VR] = THERMAL_CPU, + [TEMP_SENSOR_3_WIFI] = THERMAL_CPU, + [TEMP_SENSOR_4_DIMM] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/gaelin/thermal.c b/board/gaelin/thermal.c new file mode 100644 index 0000000000..e15e0043e1 --- /dev/null +++ b/board/gaelin/thermal.c @@ -0,0 +1,140 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "fan.h" +#include "hooks.h" +#include "host_command.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +struct fan_step { + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t on[TEMP_SENSOR_COUNT]; + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t off[TEMP_SENSOR_COUNT]; + /* Fan rpm */ + int16_t rpm[FAN_CH_COUNT]; +}; + +static const struct fan_step fan_table[] = { + { + /* level 0 */ + .on = { 65, -1, -1, -1 }, + .off = { 0, -1, -1, -1 }, + .rpm = { 2350 }, + }, + { + /* level 1 */ + .on = { 80, -1, -1, -1 }, + .off = { 60, -1, -1, -1 }, + .rpm = { 2350 }, + }, + { + /* level 2 */ + .on = { 87, -1, -1, -1 }, + .off = { 75, -1, -1, -1 }, + .rpm = { 3250 }, + }, + { + /* level 3 */ + .on = { 91, -1, -1, -1 }, + .off = { 82, -1, -1, -1 }, + .rpm = { 3750 }, + }, + { + /* level 4 */ + .on = { 100, -1, -1, -1 }, + .off = { 86, -1, -1, -1 }, + .rpm = { 4100 }, + }, +}; +const int num_fan_levels = ARRAY_SIZE(fan_table); + +int fan_table_to_rpm(int fan, int *temp, enum temp_sensor_id temp_sensor) +{ + /* current fan level */ + static int current_level; + /* previous fan level */ + static int prev_current_level; + /* previous sensor temperature */ + static int prev_temp[TEMP_SENSOR_COUNT]; + int i; + int new_rpm = 0; + + /* + * Compare the current and previous temperature, we have + * the three paths: + * 1. decreasing path. (check the release point) + * 2. increasing path. (check the trigger point) + * 3. invariant path. (return the current RPM) + */ + if (temp[temp_sensor] < prev_temp[temp_sensor]) { + for (i = current_level; i > 0; i--) { + if (temp[temp_sensor] < fan_table[i].off[temp_sensor]) + current_level = i - 1; + else + break; + } + } else if (temp[temp_sensor] > prev_temp[temp_sensor]) { + for (i = current_level; i < num_fan_levels; i++) { + if (temp[temp_sensor] > fan_table[i].on[temp_sensor]) + current_level = i + 1; + else + break; + } + } + + if (current_level < 0) + current_level = 0; + if (current_level >= num_fan_levels) + current_level = num_fan_levels - 1; + + if (current_level != prev_current_level) { + CPRINTS("temp: %d, prev_temp: %d", temp[temp_sensor], + prev_temp[temp_sensor]); + CPRINTS("current_level: %d", current_level); + } + + prev_temp[temp_sensor] = temp[temp_sensor]; + prev_current_level = current_level; + + switch (fan) { + case FAN_CH_0: + new_rpm = fan_table[current_level].rpm[FAN_CH_0]; + break; + default: + break; + } + + return new_rpm; +} + +void board_override_fan_control(int fan, int *temp) +{ + if (chipset_in_state(CHIPSET_STATE_ON)) { + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), + fan_table_to_rpm(FAN_CH(fan), temp, + TEMP_SENSOR_1_CPU)); + } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* Stop fan when enter S0ix */ + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), 0); + } +} diff --git a/board/gaelin/usbc_config.c b/board/gaelin/usbc_config.c new file mode 100644 index 0000000000..90b9f73d87 --- /dev/null +++ b/board/gaelin/usbc_config.c @@ -0,0 +1,275 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR2_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + /* Compatible with Silicon Mitus SM5360A */ + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = NX20P3483_ADDR2_FLAGS, + .drv = &nx20p348x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM5360A */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = NX20P3483_ADDR3_FLAGS, + .drv = &nx20p348x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_2_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +static void ps8815_reset(int port) +{ + int val; + int i2c_port; + uint16_t i2c_addr_flags; + enum gpio_signal ps8xxx_rst_odl; + + if (port == USBC_PORT_C0) { + ps8xxx_rst_odl = GPIO_USB_C0_RT_RST_L; + i2c_port = I2C_PORT_USB_C0_TCPC; + i2c_addr_flags = PS8XXX_I2C_ADDR1_FLAGS; + } else if (port == USBC_PORT_C1) { + ps8xxx_rst_odl = GPIO_USB_C1_RT_RST_L; + i2c_port = I2C_PORT_USB_C1_TCPC; + i2c_addr_flags = PS8XXX_I2C_ADDR2_FLAGS; + } else { + return; + } + + gpio_set_level(ps8xxx_rst_odl, 0); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + gpio_set_level(ps8xxx_rst_odl, 1); + msleep(PS8815_FW_INIT_DELAY_MS); + + CPRINTS("[C%d] %s: patching ps8815 registers", port, __func__); + + if (i2c_read8(i2c_port, i2c_addr_flags, 0x0f, &val) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f was %02x", val); + else { + CPRINTS("delay 10ms to make sure ps8815 is waken from idle"); + msleep(10); + } + + if (i2c_write8(i2c_port, i2c_addr_flags, 0x0f, 0x31) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f set to 0x31"); + + if (i2c_read8(i2c_port, i2c_addr_flags, 0x0f, &val) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f now %02x", val); +} + +void board_reset_pd_mcu(void) +{ + ps8815_reset(USBC_PORT_C0); + usb_mux_hpd_update(USBC_PORT_C0, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); + ps8815_reset(USBC_PORT_C1); + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + nx20p348x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + nx20p348x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} diff --git a/board/gaelin/usbc_config.h b/board/gaelin/usbc_config.h new file mode 100644 index 0000000000..219ad9a745 --- /dev/null +++ b/board/gaelin/usbc_config.h @@ -0,0 +1,15 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/gaelin/vif_override.xml b/board/gaelin/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/gaelin/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/galtic/battery.c b/board/galtic/battery.c new file mode 100644 index 0000000000..10fc273303 --- /dev/null +++ b/board/galtic/battery.c @@ -0,0 +1,131 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all waddledee battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + [BATTERY_C140254] = { + .fuel_gauge = { + .manuf_name = "AS3GXXE3KA", + .device_name = "C140254", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000C, + .disconnect_val = 0x000C, + } + }, + .batt_info = { + .voltage_max = 8900, /* mV */ + .voltage_normal = 7970, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + [BATTERY_C340184] = { + .fuel_gauge = { + .manuf_name = "AS3GXXH3KD", + .device_name = "C340184", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000C, + .disconnect_val = 0x000C, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0004, + } + }, + .batt_info = { + .voltage_max = 8900, /* mV */ + .voltage_normal = 7960, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + [BATTERY_C140243] = { + .fuel_gauge = { + .manuf_name = "AS3GXXD3KB", + .device_name = "C140243", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000C, + .disconnect_val = 0x000C, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0004, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11880, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C140254; + +__override int board_get_default_battery_type(void) +{ + if (board_get_battery_cell_type() == BATTERY_CELL_TYPE_3S) + return BATTERY_C140243; + else + return DEFAULT_BATTERY_TYPE; +} diff --git a/board/galtic/board.c b/board/galtic/board.c new file mode 100644 index 0000000000..a05c9f470d --- /dev/null +++ b/board/galtic/board.c @@ -0,0 +1,937 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledee board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/tusb544.h" +#include "driver/tcpm/raa489000.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "driver/usb_mux/ps8743_public.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + [CHARGER_PRIMARY] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, + [CHARGER_SECONDARY] = { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +/* USB Retimer */ +enum tusb544_conf { USB_DP = 0, USB_DP_INV, USB, USB_INV, DP, DP_INV }; + +static int board_tusb544_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + enum tusb544_conf usb_mode = 0; + /* USB */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* USB with DP */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? + USB_DP_INV : + USB_DP; + } + /* USB without DP */ + else { + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? + USB_INV : + USB; + } + } + /* DP without USB */ + else if (mux_state & USB_PD_MUX_DP_ENABLED) { + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? DP_INV : + DP; + } + /* Nothing enabled */ + else + return EC_SUCCESS; + /* Write the retimer config byte */ + if (usb_mode == USB_INV) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x15); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0x22); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0x22); + } else if (usb_mode == USB) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x11); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0x22); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0x22); + } else if (usb_mode == USB_DP_INV) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1F); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x99); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0x22); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0x22); + } else if (usb_mode == USB_DP) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1B); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x99); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0x22); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0x22); + } else if (usb_mode == DP_INV) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1E); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x99); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x99); + } else if (usb_mode == DP) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1A); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x99); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x99); + } + + return rv; +} + +static int board_ps8743_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + return ps8743_write(me, PS8743_REG_USB_EQ_RX, PS8743_USB_EQ_RX_16_7_DB); +} + +const struct usb_mux usbc1_retimer = { + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = TUSB544_I2C_ADDR_FLAGS0, + .driver = &tusb544_drv, + .board_set = &board_tusb544_set, +}; + +const struct usb_mux usbc1_virtual_mux_ps8743 = { + .usb_port = 1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, +}; + +struct usb_mux usbc1_mux0_data = { + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, +}; + +struct usb_mux_chain usbc1_mux1 = { + .mux = &usbc1_retimer, +}; + +/* USB Muxes */ +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, + { + .mux = &usbc1_mux0_data, + .next = &usbc1_mux1, + }, +}; + +static const struct ec_response_keybd_config galith_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; + +static const struct ec_response_keybd_config galtic_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (get_cbi_fw_config_numeric_pad() == NUMERIC_PAD_PRESENT) + return &galith_kb; + else + return &galtic_kb; +} + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_INT_ODL); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) + hook_call_deferred(&check_c1_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + /* Enable Base Accel interrupt */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + /* Turn on 5V if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + if (get_cbi_fw_config_numeric_pad() == NUMERIC_PAD_ABSENT) { + /* Disable scanning KSO13 and 14 if keypad isn't present. */ + keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); + } else { + /* Setting scan mask KSO11, KSO12, KSO13 and KSO14 */ + keyscan_config.actual_key_mask[11] = 0xfe; + keyscan_config.actual_key_mask[12] = 0xff; + keyscan_config.actual_key_mask[13] = 0xff; + keyscan_config.actual_key_mask[14] = 0xff; + } +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void setup_mux_config(void) +{ + if (get_cbi_ssfc_mux_redriver() == SSFC_MUX_PS8743) { + usbc1_mux0_data.i2c_addr_flags = PS8743_I2C_ADDR1_FLAG; + usbc1_mux0_data.driver = &ps8743_usb_mux_driver; + usbc1_mux1.mux = &usbc1_virtual_mux_ps8743; + usbc1_mux0_data.board_set = &board_ps8743_mux_set; + } +} +DECLARE_HOOK(HOOK_INIT, setup_mux_config, HOOK_PRIO_INIT_I2C + 2); + +void board_hibernate(void) +{ + /* + * Put all charger ICs present into low power mode before entering + * z-state. + */ + raa489000_hibernate(CHARGER_PRIMARY, true); + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(CHARGER_SECONDARY, true); +} + +__override void board_ocpc_init(struct ocpc_data *ocpc) +{ + /* There's no provision to measure Isys */ + ocpc->chg_flags[CHARGER_SECONDARY] |= OCPC_NO_ISYS_MEAS_CAP; +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + gpio_set_level(GPIO_EN_USB_A0_VBUS, !!enable); + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", enable ? "en" : "dis"); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_0; + } + } + + /* Check whether TCPC 1 pulled the shared interrupt line */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (port == i) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if ((old_port != CHARGE_PORT_NONE) && (old_port != port)) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 10000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Sensor Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Sensor Data */ +static struct accelgyro_saved_data_t g_bma253_data; +static struct kionix_accel_data g_kx022_data; +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; + +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t base_standard_ref_icm = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t base_standard_ref_bmi = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t bma253_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g */ + /* We only use 2g because its resolution is only 8-bits */ + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t bmi160_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_bmi, + .default_range = 4, /* g */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t bmi160_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_bmi, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, +}; + +/* Drivers */ +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g */ + /* We only use 2g because its resolution is only 8-bits */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_icm, + .default_range = 4, /* g */ + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, + }, +}; + +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void motion_interrupt(enum gpio_signal signal) +{ + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BMI160) + bmi160_interrupt(signal); + else + icm426xx_interrupt(signal); +} + +static void board_sensors_init(void) +{ + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_BMA255) { + motion_sensors[LID_ACCEL] = bma253_lid_accel; + ccprints("LID_ACCEL is BMA253"); + } else + ccprints("LID_ACCEL is KX022"); + + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BMI160) { + motion_sensors[BASE_ACCEL] = bmi160_base_accel; + motion_sensors[BASE_GYRO] = bmi160_base_gyro; + ccprints("BASE_ACCEL is BMI160"); + } else + ccprints("BASE_ACCEL is ICM426XX"); +} +DECLARE_HOOK(HOOK_INIT, board_sensors_init, HOOK_PRIO_DEFAULT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Vcore", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(98), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_VCORE \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(50), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_vcore = + THERMAL_VCORE; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_AMBIENT \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(50), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_ambient = + THERMAL_AMBIENT; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1] = THERMAL_CHARGER, + [TEMP_SENSOR_2] = THERMAL_VCORE, + [TEMP_SENSOR_3] = THERMAL_AMBIENT, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This cause Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +enum battery_cell_type battery_cell; + +static void get_battery_cell(void) +{ + int val; + + if (i2c_read16(I2C_PORT_USB_C0, ISL923X_ADDR_FLAGS, ISL9238_REG_INFO2, + &val) == EC_SUCCESS) { + /* PROG resistor read out. Number of battery cells [4:0] */ + val = val & 0x001f; + } + + if (val == 0 || val >= 0x18) + battery_cell = BATTERY_CELL_TYPE_1S; + else if (val >= 0x01 && val <= 0x08) + battery_cell = BATTERY_CELL_TYPE_2S; + else if (val >= 0x09 && val <= 0x10) + battery_cell = BATTERY_CELL_TYPE_3S; + else + battery_cell = BATTERY_CELL_TYPE_4S; + + CPRINTS("Get battery cells: %d", battery_cell); +} +DECLARE_HOOK(HOOK_INIT, get_battery_cell, HOOK_PRIO_INIT_I2C + 1); + +enum battery_cell_type board_get_battery_cell_type(void) +{ + return battery_cell; +} diff --git a/board/galtic/board.h b/board/galtic/board.h new file mode 100644 index 0000000000..cfed23b359 --- /dev/null +++ b/board/galtic/board.h @@ -0,0 +1,160 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledee board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_CMD_CHARGER_DUMP + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#undef CONFIG_CHARGER_SINGLE_CHIP +#define CONFIG_OCPC +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) + +#define GPIO_USB_C1_INT_ODL GPIO_SUB_USB_C1_INT_ODL + +/* LED */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* PWM */ +#define CONFIG_PWM + +/* Sensors */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_BMI_COMM_I2C +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel */ +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM_COMM_I2C + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* Power of 2 - Too large of a fifo causes too much timestamp jitter */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_RAA489000 +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B +#define CONFIG_THROTTLE_AP + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define CONFIG_USB_MUX_PS8743 /* C1: PS8743 Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +#define CONFIG_USBC_RETIMER_TUSB544 /* C1 Redriver: TUSB544 */ +#define CONFIG_USB_MUX_RUNTIME_CONFIG +#define CONFIG_USB_MUX_VIRTUAL + +/* Keyboard */ +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_KEYPAD + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_C140254, + BATTERY_C340184, + BATTERY_C140243, + BATTERY_TYPE_COUNT, +}; + +enum battery_cell_type { + BATTERY_CELL_TYPE_1S = 1, + BATTERY_CELL_TYPE_2S = 2, + BATTERY_CELL_TYPE_3S = 3, + BATTERY_CELL_TYPE_4S = 4, +}; + +void motion_interrupt(enum gpio_signal signal); +enum battery_cell_type board_get_battery_cell_type(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/galtic/build.mk b/board/galtic/build.mk new file mode 100644 index 0000000000..9b862c7624 --- /dev/null +++ b/board/galtic/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/galtic/cbi_ssfc.c b/board/galtic/cbi_ssfc.c new file mode 100644 index 0000000000..7a7ed9f7cf --- /dev/null +++ b/board/galtic/cbi_ssfc.c @@ -0,0 +1,41 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} + +enum ec_ssfc_mux_redriver get_cbi_ssfc_mux_redriver(void) +{ + return (enum ec_ssfc_mux_redriver)cached_ssfc.mux_redriver; +} diff --git a/board/galtic/cbi_ssfc.h b/board/galtic/cbi_ssfc.h new file mode 100644 index 0000000000..84f321977e --- /dev/null +++ b/board/galtic/cbi_ssfc.h @@ -0,0 +1,75 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +/* + * Mux Redriver (Bit 6) + */ +enum ec_ssfc_mux_redriver { + SSFC_MUX_DEFAULT = 0, /* IT5205 + TUSB544 */ + SSFC_MUX_PS8743 = 1, +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t mux_redriver : 1; + uint32_t reserved_2 : 25; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +/** + * Get the MUX and redriver type from SSFC_CONFIG. + * + * @return the MUX and redriver type. + */ +enum ec_ssfc_mux_redriver get_cbi_ssfc_mux_redriver(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/galtic/ec.tasklist b/board/galtic/ec.tasklist new file mode 100644 index 0000000000..bc2fea6148 --- /dev/null +++ b/board/galtic/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/galtic/gpio.inc b/board/galtic/gpio.inc new file mode 100644 index 0000000000..721a193f36 --- /dev/null +++ b/board/galtic/gpio.inc @@ -0,0 +1,145 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(SUB_USB_C1_INT_ODL, PIN(E, 6), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c1_interrupt) +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) /* Board rev 1, NC board rev 0 */ + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc pins which will run to the I/O board */ + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) + +/* LED */ +GPIO(LED_R_ODL, PIN(A, 1), GPIO_OUT_HIGH) +GPIO(LED_G_ODL, PIN(A, 2), GPIO_OUT_HIGH) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOA0_NC, PIN(A, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA3_NC, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOB5_NC, PIN(B, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC4_NC, PIN(C, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC6_NC, PIN(C, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF0_NC, PIN(F, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF1_NC, PIN(F, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF4_NC, PIN(F, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ1_NC, PIN(J, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ3_NC, PIN(J, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL0_NC, PIN(L, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL3_NC, PIN(L, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(2)), 0, MODULE_ADC, 0) /* ADC15: TEMP_SENSOR_3 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + diff --git a/board/galtic/led.c b/board/galtic/led.c new file mode 100644 index 0000000000..1438ccd91a --- /dev/null +++ b/board/galtic/led.c @@ -0,0 +1,106 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { LED_OFF, 2 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_R_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_G_ODL, LED_ON_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_R_ODL, LED_ON_LVL); + gpio_set_level(GPIO_LED_G_ODL, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_R_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_G_ODL, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + /* Battery error LED behavior as below: + * S0: Blinking Amber LED, 1s on/ 1s off + * S3/S5: following S3/S5 behavior + * Add function to let battery error LED follow S3/S5 behavior in S3/S5. + */ + + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/galtic/usb_pd_policy.c b/board/galtic/usb_pd_policy.c new file mode 100644 index 0000000000..23166f7fca --- /dev/null +++ b/board/galtic/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/galtic/vif_override.xml b/board/galtic/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/galtic/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/garg/battery.c b/board/garg/battery.c index 119023877e..5706344191 100644 --- a/board/garg/battery.c +++ b/board/garg/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -89,6 +89,63 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 60, }, }, + + /* Simplo CA475778G 916QA141H battery information */ + [BATTERY_SIMPLO_CA475778G] = { + .fuel_gauge = { + .manuf_name = "SMP-CA475778G", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11430, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + /* Simplo CA475778G_R 916QA152H battery information, BMU RAJ240045 */ + [BATTERY_SIMPLO_CA475778G_R] = { + .fuel_gauge = { + .manuf_name = "SMP-CA475778G_R", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11430, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); diff --git a/board/garg/board.c b/board/garg/board.c index 44cc3b3759..60365a6312 100644 --- a/board/garg/board.c +++ b/board/garg/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,15 +6,19 @@ /* Garg board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery.h" #include "button.h" +#include "cbi_ssfc.h" #include "charge_manager.h" #include "charge_state.h" #include "common.h" #include "cros_board_info.h" #include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_bmi260.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/charger/bd9995x.h" #include "driver/ppc/nx20p348x.h" #include "driver/tcpm/anx7447.h" @@ -33,18 +37,18 @@ #include "switch.h" #include "system.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define USB_PD_PORT_ANX7447 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 static uint8_t sku_id; @@ -54,17 +58,16 @@ static uint8_t sku_id; * that we don't have pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {-1, -1}, {-1, -1}, {1, 4}, {1, 3}, - {-1, -1}, {1, 6}, {1, 7}, {3, 1}, {2, 0}, - {1, 5}, {2, 6}, {2, 7}, {2, 1}, {2, 4}, - {2, 5}, {1, 2}, {2, 3}, {2, 2}, {3, 0}, - {-1, -1}, {0, 4}, {-1, -1}, {8, 2}, {-1, -1}, - {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); static void ppc_interrupt(enum gpio_signal signal) { @@ -87,31 +90,31 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, /* Vbus sensing (1/10 voltage divider). */ - [ADC_VBUS_C0] = { - "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, - [ADC_VBUS_C1] = { - "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C0] = { "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + [ADC_VBUS_C1] = { "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -121,15 +124,23 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_bmi260_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi160_data; +static struct bmi_drv_data_t g_bmi260_data; +static struct icm_drv_data_t g_icm426xx_data; /* Drivers */ struct motion_sensor_t motion_sensors[] = { @@ -207,18 +218,120 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_icm_ref, + .default_range = 4, /* g */ + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t bmi260_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .rot_standard_ref = &base_bmi260_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t bmi260_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_bmi260_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, +}; + static int board_is_convertible(void) { /* - * Garg360: 37, 38 + * Garg360: 37, 38, 39 * Unprovisioned: 255 */ - return sku_id == 37 || sku_id == 38 || sku_id == 255; + return sku_id == 37 || sku_id == 38 || sku_id == 39 || sku_id == 255; } static void board_update_sensor_config_from_sku(void) { if (board_is_convertible()) { + if (get_cbi_ssfc_sensor() == SSFC_SENSOR_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE GYRO is ICM426XX"); + } else if (get_cbi_ssfc_sensor() == SSFC_SENSOR_BMI260) { + motion_sensors[BASE_ACCEL] = bmi260_base_accel; + motion_sensors[BASE_GYRO] = bmi260_base_gyro; + ccprints("BASE GYRO is BMI260"); + } else + ccprints("BASE GYRO is BMI160"); motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Enable Base Accel interrupt */ gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); @@ -231,6 +344,22 @@ static void board_update_sensor_config_from_sku(void) } } +void sensor_interrupt(enum gpio_signal signal) +{ + switch (motion_sensors[BASE_ACCEL].chip) { + case MOTIONSENSE_CHIP_ICM426XX: + icm426xx_interrupt(signal); + break; + case MOTIONSENSE_CHIP_BMI260: + bmi260_interrupt(signal); + break; + case MOTIONSENSE_CHIP_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + /* Read CBI from i2c eeprom and initialize variables for board variants */ static void cbi_init(void) { @@ -245,34 +374,22 @@ static void cbi_init(void) } DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); -__override uint32_t board_override_feature_flags0(uint32_t flags0) -{ - /* - * Remove keyboard backlight feature for devices that don't support it. - */ - if (sku_id == 255) - return flags0; - else - return (flags0 & ~EC_FEATURE_MASK_0(EC_FEATURE_PWM_KEYB)); -} - void board_hibernate_late(void) { int i; const uint32_t hibernate_pins[][2] = { /* Turn off LEDs before going to hibernate */ - {GPIO_BAT_LED_BLUE_L, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_BAT_LED_ORANGE_L, GPIO_INPUT | GPIO_PULL_UP}, + { GPIO_BAT_LED_BLUE_L, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_BAT_LED_ORANGE_L, GPIO_INPUT | GPIO_PULL_UP }, }; for (i = 0; i < ARRAY_SIZE(hibernate_pins); ++i) gpio_set_flags(hibernate_pins[i][0], hibernate_pins[i][1]); } -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -284,7 +401,6 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif void board_overcurrent_event(int port, int is_overcurrented) { diff --git a/board/garg/board.h b/board/garg/board.h index 79871f0af6..90ddb1b217 100644 --- a/board/garg/board.h +++ b/board/garg/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,24 +8,30 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H +/* Free up flash space */ +#define CONFIG_LTO +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_BATTFAKE +#undef CONFIG_CMD_MEM + /* Select Baseboard features */ #define VARIANT_OCTOPUS_EC_NPCX796FB #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" -/* I2C bus configuraiton */ -#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD -/* EC console commands */ -#define CONFIG_CMD_ACCELS -#define CONFIG_CMD_ACCEL_INFO +/* I2C bus configuraiton */ +#define I2C_PORT_ACCEL I2C_PORT_SENSOR #define CONFIG_LED_COMMON /* Sensors */ -#define CONFIG_ACCEL_KX022 /* Lid accel */ -#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_SYNC /* Camera VSYNC */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_BMI260 /* 3rd Base accel */ +#define CONFIG_ACCELGYRO_ICM426XX /* 2nd Base accel */ +#define CONFIG_SYNC /* Camera VSYNC */ #define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT /* Sensors without hardware FIFO are in forced mode */ @@ -34,9 +40,12 @@ /* Motion Sense Task Events */ #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE @@ -52,25 +61,29 @@ #define CONFIG_STEINHART_HART_3V3_13K7_47K_4050B #define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B -/* Keyboard backliht */ -#define CONFIG_PWM -#define CONFIG_PWM_KBLIGHT +/* Free up more flash. */ +#undef CONFIG_CMD_GETTIME +#undef CONFIG_CMD_HCDEBUG +#undef CONFIG_CMD_I2C_SCAN +#undef CONFIG_CMD_I2C_XFER +#undef CONFIG_CONSOLE_VERBOSE +#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CONSOLE_HISTORY +#define CONFIG_USB_PD_DEBUG_LEVEL 0 #ifndef __ASSEMBLER__ /* support factory keyboard test */ #define CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; #include "gpio_signal.h" #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ - ADC_VBUS_C0, /* ADC9 */ - ADC_VBUS_C1, /* ADC4 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_VBUS_C0, /* ADC9 */ + ADC_VBUS_C1, /* ADC4 */ ADC_CH_COUNT }; @@ -81,27 +94,20 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; - /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - VSYNC, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, VSYNC, SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { BATTERY_SIMPLO_SDI, BATTERY_SIMPLO_BYD, + BATTERY_SIMPLO_CA475778G, + BATTERY_SIMPLO_CA475778G_R, BATTERY_TYPE_COUNT, }; +void sensor_interrupt(enum gpio_signal signal); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/garg/build.mk b/board/garg/build.mk index 137e208b53..fee77e38b5 100644 --- a/board/garg/build.mk +++ b/board/garg/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/garg/ec.tasklist b/board/garg/ec.tasklist index 6eac78a042..6c56976091 100644 --- a/board/garg/ec.tasklist +++ b/board/garg/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/garg/gpio.inc b/board/garg/gpio.inc index 2c485e4e2c..57feead408 100644 --- a/board/garg/gpio.inc +++ b/board/garg/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -37,7 +37,7 @@ GPIO_INT(TABLET_MODE_L, PIN(8, 6), GPIO_INT_BOTH, gmr_tablet_switch_isr) GPIO_INT(EC_VOLUP_BTN_ODL, PIN(7, 5), GPIO_INT_BOTH, button_interrupt) GPIO_INT(EC_VOLDN_BTN_ODL, PIN(4, 0), GPIO_INT_BOTH, button_interrupt) -GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, sensor_interrupt) GPIO(LID_ACCEL_INT_L, PIN(5, 0), GPIO_INPUT | GPIO_SEL_1P8V) @@ -136,9 +136,6 @@ GPIO(BAT_LED_ORANGE_L, PIN(C, 3), GPIO_OUT_HIGH) /* LED_1_L */ GPIO(BAT_LED_BLUE_L, PIN(C, 4), GPIO_OUT_HIGH) /* LED_2_L */ GPIO(LED_3_L, PIN(D, 7), GPIO_OUT_HIGH) -/* Keyboard Backlight */ -GPIO(KB_BL_PWR_EN, PIN(6, 2), GPIO_OUT_LOW) - /* MKBP event synchronization */ GPIO(EC_INT_L, PIN(9, 4), GPIO_ODR_HIGH) @@ -158,6 +155,8 @@ GPIO(EC_I2S_SFRM, PIN(A, 5), GPIO_INPUT | GPIO_SEL_1P8V) GPIO(EC_I2S_SCLK, PIN(A, 7), GPIO_INPUT | GPIO_SEL_1P8V) GPIO(EC_I2S_TX_PCH_RX, PIN(B, 0), GPIO_INPUT | GPIO_SEL_1P8V) GPIO(WFCAM_VSYNC, PIN(0, 3), GPIO_INPUT) +GPIO(KB_BL_PWR_EN, PIN(6, 2), GPIO_INPUT) +GPIO(EC_GPIO80, PIN(8, 0), GPIO_INPUT) /* Keyboard pins */ ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT) /* KSI_00-01 */ @@ -181,7 +180,6 @@ ALTERNATE(PIN_MASK(B, 0x0C), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* 1.8 ALTERNATE(PIN_MASK(4, 0x30), 0, MODULE_ADC, 0) /* ADC0-1 */ ALTERNATE(PIN_MASK(4, 0x02), 0, MODULE_ADC, 0) /* ADC4 */ ALTERNATE(PIN_MASK(F, 0x01), 0, MODULE_ADC, 0) /* ADC9 */ -ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* PWM3: KB_BL_PWM */ /* Power Switch Logic (PSL) inputs */ ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, 0) /* GPIOD2 = LID_OPEN */ diff --git a/board/garg/led.c b/board/garg/led.c index f533ed32b6..eff8c1307b 100644 --- a/board/garg/led.c +++ b/board/garg/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,32 +10,39 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1; +__override const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* Garg: Note there is only LED for charge / power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_BLUE: @@ -70,4 +77,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/garg/vif_override.xml b/board/garg/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/garg/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/gelarshie/base_detect.c b/board/gelarshie/base_detect.c new file mode 100644 index 0000000000..9c1a47d2e4 --- /dev/null +++ b/board/gelarshie/base_detect.c @@ -0,0 +1,230 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Gelarshie base detection code */ + +#include "adc.h" +#include "base_state.h" +#include "board.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "system.h" +#include "tablet_mode.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +/* Base detection and debouncing */ +#define BASE_DETECT_EN_DEBOUNCE_US (350 * MSEC) +#define BASE_DETECT_DIS_DEBOUNCE_US (20 * MSEC) + +/* + * If the base status is unclear (i.e. not within expected ranges, read + * the ADC value again every 500ms. + */ +#define BASE_DETECT_RETRY_US (500 * MSEC) + +/* + * Lid has 604K pull-up, base has 30.1K pull-down, so the + * ADC value should be around 30.1/(604+30.1)*3300 = 156 + * + * We add a significant margin on the maximum value, due to noise on the line, + * especially when PWM is active. See b/64193554 for details. + */ +#define BASE_DETECT_MIN_MV 120 +#define BASE_DETECT_MAX_MV 300 + +/* Minimum ADC value to indicate base is disconnected for sure */ +#define BASE_DETECT_DISCONNECT_MIN_MV 1500 + +/* + * Base EC pulses detection pin for 500 us to signal out of band USB wake (that + * can be used to wake system from deep S3). + */ +#define BASE_DETECT_PULSE_MIN_US 400 +#define BASE_DETECT_PULSE_MAX_US 650 + +static uint64_t base_detect_debounce_time; + +static void base_detect_deferred(void); +DECLARE_DEFERRED(base_detect_deferred); + +enum base_status { + BASE_UNKNOWN = 0, + BASE_DISCONNECTED = 1, + BASE_CONNECTED = 2, +}; + +static enum base_status current_base_status; + +/* + * This function is called whenever there is a change in the base detect + * status. Actions taken include: + * 1. Change in power to base + * 2. Indicate mode change to host. + * 3. Indicate tablet mode to host. Current assumption is that if base is + * disconnected then the system is in tablet mode, else if the base is + * connected, then the system is not in tablet mode. + */ +static void base_detect_change(enum base_status status) +{ + int connected = (status == BASE_CONNECTED); + + if (current_base_status == status) + return; + + gpio_set_level(GPIO_EN_BASE, connected); + tablet_set_mode(!connected, TABLET_TRIGGER_BASE); + base_set_state(connected); + current_base_status = status; +} + +/* Measure detection pin pulse duration (used to wake AP from deep S3). */ +static uint64_t pulse_start; +static uint32_t pulse_width; + +static void print_base_detect_value(int v, int tmp_pulse_width) +{ + CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name, v, + tmp_pulse_width); +} + +static void base_detect_deferred(void) +{ + uint64_t time_now = get_time().val; + int v; + uint32_t tmp_pulse_width = pulse_width; + + if (base_detect_debounce_time > time_now) { + hook_call_deferred(&base_detect_deferred_data, + base_detect_debounce_time - time_now); + return; + } + + v = adc_read_channel(ADC_BASE_DET); + if (v == ADC_READ_ERROR) + return; + + print_base_detect_value(v, tmp_pulse_width); + + if (v >= BASE_DETECT_MIN_MV && v <= BASE_DETECT_MAX_MV) { + if (current_base_status != BASE_CONNECTED) { + base_detect_change(BASE_CONNECTED); + } else if (tmp_pulse_width >= BASE_DETECT_PULSE_MIN_US && + tmp_pulse_width <= BASE_DETECT_PULSE_MAX_US) { + CPRINTS("Sending event to AP"); + host_set_single_event(EC_HOST_EVENT_KEY_PRESSED); + } + return; + } + + if (v >= BASE_DETECT_DISCONNECT_MIN_MV) { + base_detect_change(BASE_DISCONNECTED); + return; + } + + /* Unclear base status, schedule again in a while. */ + hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_RETRY_US); +} + +static inline int detect_pin_connected(enum gpio_signal det_pin) +{ + return gpio_get_level(det_pin) == 0; +} + +void base_detect_interrupt(enum gpio_signal signal) +{ + uint64_t time_now = get_time().val; + int debounce_us; + + if (detect_pin_connected(signal)) + debounce_us = BASE_DETECT_EN_DEBOUNCE_US; + else + debounce_us = BASE_DETECT_DIS_DEBOUNCE_US; + + if (base_detect_debounce_time <= time_now) { + /* + * Detect and measure detection pin pulse, when base is + * connected. Only a single pulse is measured over a debounce + * period. If no pulse, or multiple pulses are detected, + * pulse_width is set to 0. + */ + if (current_base_status == BASE_CONNECTED && + !detect_pin_connected(signal)) { + pulse_start = time_now; + } else { + pulse_start = 0; + } + pulse_width = 0; + + hook_call_deferred(&base_detect_deferred_data, debounce_us); + } else { + if (current_base_status == BASE_CONNECTED && + detect_pin_connected(signal) && !pulse_width && + pulse_start) { + /* First pulse within period. */ + pulse_width = time_now - pulse_start; + } else { + pulse_start = 0; + pulse_width = 0; + } + } + + base_detect_debounce_time = time_now + debounce_us; +} + +static void base_enable(void) +{ + /* Enable base detection interrupt. */ + base_detect_debounce_time = get_time().val; + hook_call_deferred(&base_detect_deferred_data, 0); + gpio_enable_interrupt(GPIO_BASE_DET_L); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, base_enable, HOOK_PRIO_DEFAULT); + +static void base_disable(void) +{ + /* + * Disable base detection interrupt and disable power to base. + * Set the state UNKNOWN so the next startup will initialize a + * correct state and notify AP. + */ + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_UNKNOWN); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, base_disable, HOOK_PRIO_DEFAULT); + +static void base_init(void) +{ + /* + * If we jumped to this image and chipset is already in S0, enable + * base. + */ + if (system_jumped_late() && chipset_in_state(CHIPSET_STATE_ON)) + base_enable(); +} +DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT + 1); + +void base_force_state(enum ec_set_base_state_cmd state) +{ + if (state == EC_SET_BASE_STATE_ATTACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_CONNECTED); + CPRINTS("BD forced connected"); + } else if (state == EC_SET_BASE_STATE_DETACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_DISCONNECTED); + CPRINTS("BD forced disconnected"); + } else { + base_enable(); + CPRINTS("BD forced reset"); + } +} diff --git a/board/gelarshie/battery.c b/board/gelarshie/battery.c new file mode 100644 index 0000000000..da96b773f8 --- /dev/null +++ b/board/gelarshie/battery.c @@ -0,0 +1,159 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all gelarshie battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ + +const struct board_batt_params board_battery_info[] = { + /* COSMX GH02047XL 333-1C-DA-A */ + [BATTERY_GH02047XL_1C] = { + .fuel_gauge = { + .manuf_name = "333-1C-DA-A", + .device_name = "GH02047XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* COSMX GH02047XL */ + [BATTERY_GH02047XL] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .device_name = "GH02047XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* COSMX DS02032XL */ + [BATTERY_DS02032XL] = { + .fuel_gauge = { + .manuf_name = "333-AC-13-A", + .device_name = "DS02032XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* SMP DS02032XL */ + [BATTERY_DS02032XL_1C] = { + .fuel_gauge = { + .manuf_name = "333-1C-13-A", + .device_name = "DS02032XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DS02032XL; diff --git a/board/gelarshie/board.c b/board/gelarshie/board.c new file mode 100644 index 0000000000..2899fa9566 --- /dev/null +++ b/board/gelarshie/board.c @@ -0,0 +1,715 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Gelarshie board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi260.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/ln9310.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "lid_switch.h" +#include "mkbp_input_devices.h" +#include "peripheral_charger.h" +#include "pi3usb9201.h" +#include "power.h" +#include "power/qcom.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "queue.h" +#include "shi_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define KS_DEBOUNCE_US (30 * MSEC) /* Debounce time for kickstand switch */ + +/* Forward declaration */ +static void tcpc_alert_event(enum gpio_signal signal); +static void usb0_evt(enum gpio_signal signal); +static void usb1_evt(enum gpio_signal signal); +static void ppc_interrupt(enum gpio_signal signal); +static void board_connect_c0_sbu(enum gpio_signal s); +static void ks_interrupt(enum gpio_signal s); +static void switchcap_interrupt(enum gpio_signal signal); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* GPIO Interrupt Handlers */ +static void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_PD_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +static void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void usb1_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + case GPIO_USB_C1_SWCTL_INT_ODL: + sn5s330_interrupt(1); + break; + default: + break; + } +} + +static void board_connect_c0_sbu_deferred(void) +{ + /* + * If CCD_MODE_ODL asserts, it means there's a debug accessory connected + * and we should enable the SBU FETs. + */ + ppc_set_sbu(0, 1); +} +DECLARE_DEFERRED(board_connect_c0_sbu_deferred); + +static void board_connect_c0_sbu(enum gpio_signal s) +{ + hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); +} + +static int debounced_ks_attached; +static int debounced_ks_open; + +/** + * Kickstand switch initialization + */ +static void ks_init(void) +{ + debounced_ks_attached = !gpio_get_level(GPIO_KS_ATTACHED_L); + debounced_ks_open = gpio_get_level(GPIO_KS_OPEN); + + /* Enable interrupts, now that we've initialized */ + gpio_enable_interrupt(GPIO_KS_ATTACHED_L); + gpio_enable_interrupt(GPIO_KS_OPEN); +} +DECLARE_HOOK(HOOK_INIT, ks_init, HOOK_PRIO_INIT_SWITCH); + +/** + * Handle debounced kickstand switch changing state. + */ +static void ks_change_deferred(void) +{ + const int ks_attached = !gpio_get_level(GPIO_KS_ATTACHED_L); + const int ks_open = gpio_get_level(GPIO_KS_OPEN); + int proximity_detected; + + /* If the switches haven't changed, nothing to do */ + if (ks_attached == debounced_ks_attached && + ks_open == debounced_ks_open) + return; + + /* + * A heuristic method to use the kickstand position to approach + * the human body proximity. + */ + proximity_detected = !(ks_attached && ks_open); + CPRINTS("ks %s %s -> proximity %s", + ks_attached ? "attached" : "detached", + ks_open ? "open" : "close", proximity_detected ? "on" : "off"); + + debounced_ks_attached = ks_attached; + debounced_ks_open = ks_open; + + body_detect_change_state(proximity_detected, false); +} +DECLARE_DEFERRED(ks_change_deferred); + +static void ks_interrupt(enum gpio_signal s) +{ + /* Reset kickstand debounce time */ + hook_call_deferred(&ks_change_deferred_data, KS_DEBOUNCE_US); +} + +static void switchcap_interrupt(enum gpio_signal signal) +{ + ln9310_interrupt(signal); +} + +/* I2C port map */ +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* Measure VBUS through a 1/10 voltage divider */ + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + /* + * Adapter current output or battery charging/discharging current (uV) + * 18x amplification on charger side. + */ + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, + /* + * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read + * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and + * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we + * only divide by 2 (enough to avoid precision issues). + */ + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, + /* Base detection */ + [ADC_BASE_DET] = { "BASE_DET", NPCX_ADC_CH5, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct pwm_t pwm_channels[] = { + /* TODO(waihong): Assign a proper frequency. */ + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 4800 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* LN9310 switchcap */ +const struct ln9310_config_t ln9310_config = { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = LN9310_I2C_ADDR_0_FLAGS, +}; + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + } +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + { + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/* Mutexes */ +static struct mutex g_lid_mutex; + +static struct bmi_drv_data_t g_bmi160_data; +static struct bmi_drv_data_t g_bmi260_data; + +bool is_bmi260_present; + +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t motion_sensors[] = { + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [LID_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +struct motion_sensor_t motion_sensors_260[] = { + /* + * Note: bmi260: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi260_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [LID_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi260_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void board_detect_motionsensor(void) +{ + int val = -1; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + + /* Check base accelgyro chip */ + bmi_read8(motion_sensors[LID_ACCEL].port, + motion_sensors[LID_ACCEL].i2c_spi_addr_flags, BMI260_CHIP_ID, + &val); + if (val == BMI260_CHIP_ID_MAJOR) { + motion_sensors[LID_ACCEL] = motion_sensors_260[LID_ACCEL]; + motion_sensors[LID_GYRO] = motion_sensors_260[LID_GYRO]; + is_bmi260_present = 1; + } else { + is_bmi260_present = 0; + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_DEFAULT + 1); + +void motion_interrupt(enum gpio_signal signal) +{ + if (is_bmi260_present) { + bmi260_interrupt(signal); + } else { + bmi160_interrupt(signal); + } +} + +enum battery_cell_type board_get_battery_cell_type(void) +{ + return BATTERY_CELL_TYPE_2S; +} + +static void board_switchcap_init(void) +{ + CPRINTS("Use switchcap: LN9310"); + + /* Configure and enable interrupt for LN9310 */ + gpio_set_flags(GPIO_SWITCHCAP_PG_INT_L, GPIO_INT_FALLING); + gpio_enable_interrupt(GPIO_SWITCHCAP_PG_INT_L); + + /* Only configure the switchcap if not sysjump */ + if (!system_jumped_late()) { + ln9310_init(); + } +} +/* Initialize board. */ +static void board_init(void) +{ + /* + * The rev-1 hardware doesn't have the external pull-up fix for the bug + * b/177611071. It requires rework to stuff the resistor. For people who + * has difficulty to do the rework, this is a workaround, which makes + * the GPIO push-pull, instead of open-drain. + */ + if (system_get_board_version() == 1) + gpio_set_flags(GPIO_HIBERNATE_L, GPIO_OUTPUT); + + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); + + /* + * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs + * for SBU may be disconnected after DP alt mode is off. Should enable + * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. + */ + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); + + /* Set the backlight duty cycle to 0. AP will override it later. */ + pwm_set_duty(PWM_CH_DISPLIGHT, 0); + + board_switchcap_init(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +__overridable uint16_t board_get_ps8xxx_product_id(int port) +{ + /* Coachz board rev 2+ changes TCPC from 8805 to 8755*/ + if (system_get_board_version() < 2) + return PS8805_PRODUCT_ID; + + return PS8755_PRODUCT_ID; +} + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_hibernate(void) +{ + int i; + + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + + /* + * Board rev 1+ has the hardware fix. Don't need the following + * workaround. + */ + if (system_get_board_version() >= 1) + return; + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + ppc_vbus_sink_enable(i, 1); +} + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* + * Turn off display backlight in S3. AP has its own control. The EC's + * and the AP's will be AND'ed together in hardware. + */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); + pwm_enable(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Turn on display and keyboard backlight in S0. */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); + if (pwm_get_duty(PWM_CH_DISPLIGHT)) + pwm_enable(PWM_CH_DISPLIGHT, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON_L, !enable); + ln9310_software_enable(enable); +} + +int board_is_switchcap_enabled(void) +{ + return !gpio_get_level(GPIO_SWITCHCAP_ON_L); +} + +int board_is_switchcap_power_good(void) +{ + return ln9310_power_good(); +} + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} diff --git a/board/gelarshie/board.h b/board/gelarshie/board.h new file mode 100644 index 0000000000..65016ceb75 --- /dev/null +++ b/board/gelarshie/board.h @@ -0,0 +1,132 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Gelarshie board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* On-body detection */ +#define CONFIG_BODY_DETECTION +#define CONFIG_BODY_DETECTION_SENSOR LID_ACCEL +#define CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR 150 /* % */ +#define CONFIG_GESTURE_DETECTION +#define CONFIG_GESTURE_DETECTION_MASK BIT(CONFIG_BODY_DETECTION_SENSOR) +#define CONFIG_GESTURE_HOST_DETECTION + +#define CONFIG_BUTTON_TRIGGERED_RECOVERY + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Switchcap */ +#define CONFIG_LN9310 + +/* Save some flash space */ +#define CONFIG_LTO +#define CONFIG_USB_PD_DEBUG_LEVEL 2 +#undef CONFIG_CMD_FLASHINFO +#undef CONFIG_CMD_MMAPINFO +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_ACCEL_FIFO +#undef CONFIG_CMD_ACCEL_INFO +#undef CONFIG_CMD_TASK_RESET +#undef CONFIG_CONSOLE_CMDHELP + +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_VENDOR_PARAM + +/* charger margin */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +/* Enable PD3.0 */ +#define CONFIG_USB_PD_REV30 +/* BC 1.2 Charger */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* USB */ +#define CONFIG_USB_PD_TCPM_MULTI_PS8XXX +#define CONFIG_USB_PD_TCPM_PS8755 +#define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* BMI160 Lid accel/gyro */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS +#define CONFIG_ACCELGYRO_BMI260 +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE +#define CONFIG_FRONT_PROXIMITY_SWITCH + +#define CONFIG_MKBP_INPUT_DEVICES + +#define CONFIG_DETACHABLE_BASE +#define CONFIG_BASE_ATTACHED_SWITCH + +/* GPIO alias */ +#define GPIO_AC_PRESENT GPIO_CHG_ACOK_OD +#define GPIO_WP_L GPIO_EC_FLASH_WP_ODL +#define GPIO_PMIC_RESIN_L GPIO_PM845_RESIN_L +#define GPIO_TABLET_MODE_L GPIO_LID_360_L +#define GPIO_KS_ATTACHED_L GPIO_LID_INT_N_HALL1 +#define GPIO_KS_OPEN GPIO_LID_INT_N_HALL2 +#define GPIO_SWITCHCAP_PG_INT_L GPIO_LN9310_INT + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_VBUS, + ADC_AMON_BMON, + ADC_PSYS, + ADC_BASE_DET, + ADC_CH_COUNT +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + LID_GYRO, + SENSOR_COUNT, +}; + +enum pwm_channel { PWM_CH_DISPLIGHT = 0, PWM_CH_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_GH02047XL_1C, + BATTERY_GH02047XL, + BATTERY_DS02032XL, + BATTERY_DS02032XL_1C, + BATTERY_TYPE_COUNT, +}; + +/* Reset all TCPCs. */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); +/* Base detection */ +void base_detect_interrupt(enum gpio_signal signal); +/* motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); + +#endif /* !defined(__ASSEMBLER__) */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/gelarshie/build.mk b/board/gelarshie/build.mk new file mode 100644 index 0000000000..5b0f734fda --- /dev/null +++ b/board/gelarshie/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=trogdor + +board-y=battery.o board.o led.o base_detect.o usbc_config.o diff --git a/board/gelarshie/ec.tasklist b/board/gelarshie/ec.tasklist new file mode 100644 index 0000000000..7d193fecf3 --- /dev/null +++ b/board/gelarshie/ec.tasklist @@ -0,0 +1,22 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/gelarshie/gpio.inc b/board/gelarshie/gpio.inc new file mode 100644 index 0000000000..189a9657a6 --- /dev/null +++ b/board/gelarshie/gpio.inc @@ -0,0 +1,192 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* USB-C interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ +GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ +GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ +GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb1_evt) /* Interrupt from port-1 BC1.2 */ + +/* System interrupts */ +GPIO_INT(CHG_ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ +GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ +GPIO_INT(EC_FLASH_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ +GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ + +/* + * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down + * to make it low. Overload the interrupt function chipset_warm_reset_interrupt + * for not only signalling power_signal_interrupt but also handling the logic + * of WARM_RESET_L which is pulled-up by the same rail of POWER_GOOD. + */ +GPIO_INT(POWER_GOOD, PIN(5, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, chipset_power_good_interrupt) /* SRC_PP1800_S10A from PMIC */ +GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_warm_reset_interrupt) /* AP warm reset */ +GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ + +GPIO_INT(BASE_DET_L, PIN(3, 7), GPIO_INT_BOTH, base_detect_interrupt) /* Detachable base attached? */ + +/* Sensor interrupts */ +GPIO_INT(LID_360_L, PIN(7, 3), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(LID_INT_N_HALL1, PIN(D, 7), GPIO_INT_BOTH, ks_interrupt) /* Kickstand attached (0) or detached (1) */ +GPIO_INT(LID_INT_N_HALL2, PIN(6, 0), GPIO_INT_BOTH, ks_interrupt) /* Kickstand close (0) or open (1) */ +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, motion_interrupt) /* Accelerometer/gyro interrupt */ + +/* Switchcap, for LN9310, it is the interrupt line of LN9310. */ +GPIO_INT(LN9310_INT, PIN(E, 2), GPIO_INT_FALLING, switchcap_interrupt) + +/* + * EC_RST_ODL acts as a wake source from hibernate mode. However, it does not + * need to be an interrupt for normal EC operations. Simply set it an INPUT. + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ +GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ + +/* PMIC/AP 1.8V */ +GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ +GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ +GPIO(QSIP_ON, PIN(5, 0), GPIO_OUT_LOW) /* Not used, for non-switchcap testing */ + +/* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ +GPIO(SWITCHCAP_ON_L, PIN(D, 5), GPIO_ODR_HIGH) /* Enable switch cap */ +GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ +GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ +GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ + +/* TODO(waihong): Should remove it from hardware */ +GPIO(CAM_LED, PIN(3, 0), GPIO_INPUT) + +/* Base detection */ +GPIO(EN_BASE, PIN(0, 4), GPIO_OUT_LOW) /* Enable power to detachable base */ + +/* USB-C */ +GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_ODR_HIGH) /* Port-0 TCPC chip reset, actaully Open-Drain */ +GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_ODR_HIGH) /* Port-1 TCPC chip reset, actually Open-Drain */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ + +/* LEDs */ +GPIO(EC_CHG_LED_Y_C0, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_W_C0, PIN(C, 4), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + +/* PWM */ +GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ + +/* ADC */ +GPIO(PPVAR_BOOSTIN_SENSE, PIN(4, 4), GPIO_INPUT) /* ADC1 */ +GPIO(CHARGER_IADP, PIN(4, 3), GPIO_INPUT) /* ADC2 */ +GPIO(CHARGER_PMON, PIN(4, 2), GPIO_INPUT) /* ADC3 */ + +/* I2C */ +GPIO(EC_I2C_POWER_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Board/SKU IDs */ +GPIO(BRD_ID0, PIN(C, 7), GPIO_INPUT) +GPIO(BRD_ID1, PIN(9, 3), GPIO_INPUT) +GPIO(BRD_ID2, PIN(6, 3), GPIO_INPUT) +GPIO(SKU_ID0, PIN(F, 0), GPIO_INPUT) +GPIO(SKU_ID1, PIN(4, 1), GPIO_INPUT) +GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. Apply PU for power saving */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(3, 1)) +UNUSED(PIN(2, 7)) +UNUSED(PIN(2, 6)) +UNUSED(PIN(2, 5)) +UNUSED(PIN(2, 4)) +UNUSED(PIN(2, 3)) +UNUSED(PIN(2, 2)) +UNUSED(PIN(2, 1)) +UNUSED(PIN(2, 0)) +UNUSED(PIN(1, 7)) +UNUSED(PIN(1, 6)) +UNUSED(PIN(1, 5)) +UNUSED(PIN(1, 4)) +UNUSED(PIN(1, 3)) +UNUSED(PIN(1, 2)) +UNUSED(PIN(1, 1)) +UNUSED(PIN(1, 0)) +UNUSED(PIN(0, 7)) +UNUSED(PIN(0, 6)) +UNUSED(PIN(0, 5)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(C, 6)) +UNUSED(PIN(C, 0)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(6, 2)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(5, 6)) +UNUSED(PIN(8, 0)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(D, 1)) +UNUSED(PIN(D, 3)) +UNUSED(PIN(7, 5)) +UNUSED(PIN(8, 6)) +UNUSED(PIN(7, 4)) +UNUSED(PIN(8, 5)) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ +ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1 SDA (GPIO90), I2C2 (GPIO91/92) */ +ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) */ +ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ +ALTERNATE(PIN_MASK(D, 0x03), 1, MODULE_I2C, 0) /* I2C3 (GPIOD0/D1) */ +ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ +ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ +ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ diff --git a/board/gelarshie/led.c b/board/gelarshie/led.c new file mode 100644 index 0000000000..33dac6bb12 --- /dev/null +++ b/board/gelarshie/led.c @@ -0,0 +1,185 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +/* Battery LED blinks every per 400ms */ +#define LED_HALF_ONE_SEC (500 / HOOK_TICK_INTERVAL_MS) + +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_BLUE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color(enum led_color color) +{ + gpio_set_level(GPIO_EC_CHG_LED_Y_C0, + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(GPIO_EC_CHG_LED_W_C0, + (color == LED_BLUE) ? BAT_LED_ON : BAT_LED_OFF); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color(LED_BLUE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color(LED_AMBER); + else + led_set_color(LED_OFF); + + return EC_SUCCESS; +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + int color = LED_OFF; + int period = 0; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate amber on when charging. */ + color = LED_AMBER; + break; + case LED_PWRS_DISCHARGE: + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* Discharging in S3: White 1 sec, off 1 sec */ + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) { + if (charge_get_percent() < 10) { + /* Blink amber light (1 sec on, 1 sec + * off) */ + color = LED_AMBER; + } else { + /* Blink white light (1 sec on, 1 sec + * off) */ + color = LED_BLUE; + } + } else { + color = LED_OFF; + } + } else { + /* Discharging in S5 and S0: off */ + /* Blink amber light (1 sec on, 1 sec off) */ + if (charge_get_percent() < 10) { + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_AMBER; + else + color = LED_OFF; + } else { + /* G3 or S5 or S0: off */ + color = LED_OFF; + } + } + break; + case LED_PWRS_ERROR: + /* Battery error: Amber on 0.5 sec, off 0.5 sec */ + period = (1 + 1) * LED_HALF_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_HALF_ONE_SEC) + color = LED_AMBER; + else + color = LED_OFF; + break; + case LED_PWRS_CHARGE_NEAR_FULL: + /* Full Charged: Blue on */ + /* S3: Blink white light (1 sec on, 1 sec off) */ + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_BLUE; + else + color = LED_OFF; + } else { + /* Full charged: White on */ + color = LED_BLUE; + } + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_BLUE; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode: Blue 2 sec, Amber 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) + color = LED_BLUE; + else + color = LED_AMBER; + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + led_set_color(color); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_BATTERY_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_BLUE : LED_OFF; + + led_auto_control(EC_LED_ID_BATTERY_LED, 0); + + led_set_color(color); +} diff --git a/board/gelarshie/usbc_config.c b/board/gelarshie/usbc_config.c new file mode 100644 index 0000000000..70c0229793 --- /dev/null +++ b/board/gelarshie/usbc_config.c @@ -0,0 +1,61 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor family-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "gpio.h" +#include "usb_pd.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/gelarshie/vif_override.xml b/board/gelarshie/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/gelarshie/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/gelatin b/board/gelatin new file mode 120000 index 0000000000..7f4a914148 --- /dev/null +++ b/board/gelatin @@ -0,0 +1 @@ +hammer \ No newline at end of file diff --git a/board/genesis/board.c b/board/genesis/board.c new file mode 100644 index 0000000000..3bea8beb63 --- /dev/null +++ b/board/genesis/board.c @@ -0,0 +1,535 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Puff board-specific configuration */ + +#include "adc.h" +#include "button.h" +#include "chipset.h" +#include "common.h" +#include "core/cortex-m/cpu.h" +#include "cros_board_info.h" +#include "driver/ina3221.h" +#include "ec_commands.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "lid_switch.h" +#include "power.h" +#include "power/cometlake-discrete.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "spi.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" +#include "uart.h" +#include "usb_common.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ +#define PWR_BASE_LOAD (5 * 1335) +#define PWR_FRONT_HIGH (5 * 1500) +#define PWR_FRONT_LOW (5 * 900) +#define PWR_REAR (5 * 1500) +#define PWR_HDMI (5 * 562) +#define PWR_C_HIGH (5 * 3740) +#define PWR_C_LOW (5 * 2090) +#define PWR_MAX (5 * 10000) + +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int front_ports = 0; + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power = PWR_BASE_LOAD; + if (!gpio_get_level(GPIO_USB_A2_OC_ODL)) { + front_ports++; + base_5v_power += PWR_FRONT_LOW; + } + if (!gpio_get_level(GPIO_USB_A3_OC_ODL)) { + front_ports++; + base_5v_power += PWR_FRONT_LOW; + } + /* + * Only 1 front port can run higher power at a time. + */ + if (front_ports > 0) + base_5v_power += PWR_FRONT_HIGH - PWR_FRONT_LOW; + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) + base_5v_power += PWR_REAR; + if (!gpio_get_level(GPIO_HDMI_CONN0_OC_ODL)) + base_5v_power += PWR_HDMI; + if (!gpio_get_level(GPIO_HDMI_CONN1_OC_ODL)) + base_5v_power += PWR_HDMI; + if (usbc_overcurrent) + base_5v_power += PWR_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} + +/******************************************************************************/ + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* SPI devices */ +const struct spi_device_t spi_devices[] = {}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +/******************************************************************************/ +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_LED_WHITE] = { .channel = 2, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { .name = "ina", + .port = I2C_PORT_INA, + .kbps = 400, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "ppc0", + .port = I2C_PORT_PPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "pse", + .port = I2C_PORT_PSE, + .kbps = 400, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA }, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 400, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct adc_t adc_channels[] = { + [ADC_SNS_PP3300] = { + /* + * 4700/5631 voltage divider: can take the value out of range + * for 32-bit signed integers, so truncate to 470/563 yielding + * <0.1% error and a maximum intermediate value of 1623457792, + * which comfortably fits in int32. + */ + .name = "SNS_PP3300", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 563, + .factor_div = (ADC_READ_MAX + 1) * 470, + }, + [ADC_SNS_PP1050] = { + .name = "SNS_PP1050", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 500 mV/A */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT * 2, /* Milliamps */ + .factor_div = ADC_READ_MAX + 1, + }, + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR_1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_CORE] = { + .name = "Core", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/******************************************************************************/ +/* Wake up pins */ +const enum gpio_signal hibernate_wake_pins[] = {}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/******************************************************************************/ +/* Physical fans. These are logically separate from pwm_channels. */ +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = -1, +}; + +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 5200, +}; + +const struct fan_t fans[] = { + [FAN_CH_0] = { .conf = &fan_conf_0, .rpm = &fan_rpm_0, }, +}; +BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); + +/******************************************************************************/ +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +/******************************************************************************/ +/* Thermal control; drive fan based on temperature sensors. */ +static const int temp_fan_off = C_TO_K(35); +static const int temp_fan_max = C_TO_K(55); +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_CORE] = { + .temp_host = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(78), + [EC_TEMP_THRESH_HALT] = C_TO_K(85), + }, + .temp_host_release = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), + [EC_TEMP_THRESH_HALT] = 0, + }, + .temp_fan_off = temp_fan_off, + .temp_fan_max = temp_fan_max, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +static const struct fan_step_1_1 fan_table0[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(35), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(41), + .rpm = 2500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .rpm = 2900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .rpm = 3400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .rpm = 3900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .rpm = 4400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(52), + .rpm = 4900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(55), + .rpm = 5200 }, +}; +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) + +static const struct fan_step_1_1 *fan_table = fan_table0; + +int fan_percent_to_rpm(int fan, int temp_ratio) +{ + return temp_ratio_to_rpm_hysteresis(fan_table, NUM_FAN_LEVELS, fan, + temp_ratio, NULL); +} + +/* Power sensors */ +const struct ina3221_t ina3221[] = { + { I2C_PORT_INA, 0x40, { "PP3300_G", "PP5000_A", "PP3300_WLAN" } }, + { I2C_PORT_INA, 0x42, { "PP3300_A", "PP3300_SSD", "PP3300_LAN" } }, + { I2C_PORT_INA, 0x43, { NULL, "PP1200_U", "PP2500_DRAM" } } +}; +const unsigned int ina3221_count = ARRAY_SIZE(ina3221); + +static uint16_t board_version; +static uint32_t sku_id; +static uint32_t fw_config; + +static void cbi_init(void) +{ + /* + * Load board info from CBI to control per-device configuration. + * + * If unset it's safe to treat the board as a proto, just C10 gating + * won't be enabled. + */ + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS && val <= UINT16_MAX) + board_version = val; + if (cbi_get_sku_id(&val) == EC_SUCCESS) + sku_id = val; + if (cbi_get_fw_config(&val) == EC_SUCCESS) + fw_config = val; + CPRINTS("Board Version: %d, SKU ID: 0x%08x, F/W config: 0x%08x", + board_version, sku_id, fw_config); +} +DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); + +static void board_init(void) +{ + uint8_t *memmap_batt_flags; + + /* Override some GPIO interrupt priorities. + * + * These interrupts are timing-critical for AP power sequencing, so we + * increase their NVIC priority from the default of 3. This affects + * whole MIWU groups of 8 GPIOs since they share an IRQ. + * + * Latency at the default priority level can be hundreds of + * microseconds while other equal-priority IRQs are serviced, so GPIOs + * requiring faster response must be higher priority. + */ + /* CPU_C10_GATE_L on GPIO6.7: must be ~instant for ~60us response. */ + cpu_set_interrupt_priority(NPCX_IRQ_WKINTH_1, 1); + /* + * slp_s3_interrupt (GPIOA.5 on WKINTC_0) must respond within 200us + * (tPLT18); less critical than the C10 gate. + */ + cpu_set_interrupt_priority(NPCX_IRQ_WKINTC_0, 2); + + /* Always claim AC is online, because we don't have a battery. */ + memmap_batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); + *memmap_batt_flags |= EC_BATT_FLAG_AC_PRESENT; + /* + * For board version < 2, the directly connected recovery + * button is not available. + */ + if (board_version < 2) + button_disable_gpio(BUTTON_RECOVERY); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/******************************************************************************/ +/* USB-A port control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USB_VBUS, +}; + +int64_t get_time_dsw_pwrok(void) +{ + /* DSW_PWROK is turned on before EC was powered. */ + return -20 * MSEC; +} + +int extpower_is_present(void) +{ + /* genesis: If the EC is running, then there is external power */ + return 1; +} + +int board_is_c10_gate_enabled(void) +{ + return 0; +} + +void board_enable_s0_rails(int enable) +{ +} + +/* + * Power monitoring and management. + * + * The overall goal is to gracefully manage the power demand so that + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 2 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A BIT(0) +#define THROT_TYPE_C BIT(1) +#define THROT_PROCHOT BIT(2) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v = PWR_MAX - base_5v_power; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + } else { + delay = POWER_DELAY_MS * MSEC; + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v += PWR_C_HIGH - PWR_C_LOW; + new_state |= THROT_TYPE_C; + } + /* + * [2] If type A not already throttled, and power still + * needed, limit type A. + */ + if (!(new_state & THROT_TYPE_A) && headroom_5v < 0) { + headroom_5v += PWR_FRONT_HIGH - PWR_FRONT_LOW; + new_state |= THROT_TYPE_A; + } + /* + * [3] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v < 0) + new_state |= THROT_TYPE_C; + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_A) { + int typea_bc = (new_state & THROT_TYPE_A) ? 1 : 0; + + gpio_set_level(GPIO_USB_A3_LOW_PWR_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/genesis/board.h b/board/genesis/board.h new file mode 100644 index 0000000000..603fdb0d02 --- /dev/null +++ b/board/genesis/board.h @@ -0,0 +1,226 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Puff board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* NPCX7 config */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ + +/* Internal SPI flash on NPCX796FC is 512 kB */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) +#define CONFIG_SPI_FLASH_REGS +#define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ + +/* EC Defines */ +#define CONFIG_ADC +#define CONFIG_BOARD_HAS_RTC_RESET +#define CONFIG_BOARD_VERSION_CBI +#define CONFIG_DEDICATED_RECOVERY_BUTTON +#define CONFIG_DEDICATED_RECOVERY_BUTTON_2 +#define CONFIG_BUTTONS_RUNTIME_CONFIG +#define CONFIG_BOARD_RESET_AFTER_POWER_ON +/* TODO: (b/143496253) re-enable CEC */ +/* #define CONFIG_CEC */ +#define CONFIG_CRC8 +#define CONFIG_CBI_EEPROM +#define CONFIG_EMULATED_SYSRQ +#undef CONFIG_KEYBOARD_BOOT_KEYS +#define CONFIG_MKBP_INPUT_DEVICES +#define CONFIG_MKBP_USE_HOST_EVENT +#undef CONFIG_KEYBOARD_RUNTIME_KEYS +#undef CONFIG_HIBERNATE +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_LED_COMMON +#undef CONFIG_LID_SWITCH +#define CONFIG_LTO +#define CONFIG_PWM +#define CONFIG_VBOOT_EFS2 +#define CONFIG_VBOOT_HASH +#define CONFIG_VSTORE +#define CONFIG_VSTORE_SLOT_COUNT 1 +#define CONFIG_SHA256 + +/* EC Commands */ +#define CONFIG_CMD_BUTTON +/* Include CLI command needed to support CCD testing. */ +#define CONFIG_CMD_CHARGEN +#undef CONFIG_CMD_FASTCHARGE +#undef CONFIG_CMD_KEYBOARD +#define CONFIG_HOSTCMD_PD_CONTROL +#undef CONFIG_CMD_PWR_AVG +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_CMD_TCPC_DUMP +#ifdef SECTION_IS_RO +/* Reduce RO size by removing less-relevant commands. */ +#undef CONFIG_CMD_APTHROTTLE +#undef CONFIG_CMD_CHARGEN +#undef CONFIG_CMD_HCDEBUG +#undef CONFIG_CMD_MMAPINFO +#endif + +#undef CONFIG_CONSOLE_CMDHELP + +/* Don't generate host command debug by default */ +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + +/* Enable AP Reset command for TPM with old firmware version to detect it. */ +#define CONFIG_CMD_AP_RESET_LOG +#define CONFIG_HOSTCMD_AP_RESET + +/* Chipset config */ +#define CONFIG_CHIPSET_COMETLAKE_DISCRETE +/* check */ +#define CONFIG_CHIPSET_CAN_THROTTLE +#define CONFIG_CHIPSET_RESET_HOOK +#define CONFIG_CPU_PROCHOT_ACTIVE_LOW + +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_IGNORE_LID +#define CONFIG_POWER_BUTTON_X86 +/* Check: */ +#define CONFIG_POWER_BUTTON_INIT_IDLE +#define CONFIG_POWER_COMMON +#define CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD 30 +#define CONFIG_DELAY_DSW_PWROK_TO_PWRBTN +#define CONFIG_POWER_PP5000_CONTROL +#define CONFIG_POWER_S0IX +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define CONFIG_INA3221 + +/* Fan and temp. */ +#define CONFIG_FANS 1 +#undef CONFIG_FAN_INIT_SPEED +#define CONFIG_FAN_INIT_SPEED 0 +#define CONFIG_FAN_RPM_CUSTOM +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B +#define CONFIG_THROTTLE_AP + +#define CONFIG_USB_PD_PORT_MAX_COUNT 0 + +/* USB Type A Features */ +#define CONFIG_USB_PORT_POWER_DUMB +/* There are five ports, but power enable is ganged across all of them. */ +#define USB_PORT_COUNT 1 + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER +#define I2C_PORT_INA NPCX_I2C_PORT0_0 +#define I2C_PORT_PPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 +#define I2C_PORT_PSE NPCX_I2C_PORT4_1 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define PP5000_PGOOD_POWER_SIGNAL_MASK POWER_SIGNAL_MASK(PP5000_A_PGOOD) + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_SNS_PP3300, /* ADC2 */ + ADC_SNS_PP1050, /* ADC7 */ + ADC_VBUS, /* ADC4 */ + ADC_PPVAR_IMON, /* ADC9 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + /* Number of ADC channels */ + ADC_CH_COUNT +}; + +enum pwm_channel { + PWM_CH_FAN, + PWM_CH_LED_RED, + PWM_CH_LED_WHITE, + /* Number of PWM channels */ + PWM_CH_COUNT +}; + +enum fan_channel { + FAN_CH_0, + /* Number of FAN channels */ + FAN_CH_COUNT +}; + +enum mft_channel { + MFT_CH_0 = 0, + /* Number of MFT channels */ + MFT_CH_COUNT, +}; + +enum temp_sensor_id { TEMP_SENSOR_CORE, TEMP_SENSOR_COUNT }; + +/* Board specific handlers */ +void led_alert(int enable); +void show_critical_error(void); + +/* + * firmware config fields + */ +/* + * Barrel-jack power (4 bits). + */ +#define EC_CFG_BJ_POWER_L 0 +#define EC_CFG_BJ_POWER_H 3 +#define EC_CFG_BJ_POWER_MASK GENMASK(EC_CFG_BJ_POWER_H, EC_CFG_BJ_POWER_L) +/* + * USB Connector 4 not present (1 bit). + */ +#define EC_CFG_NO_USB4_L 4 +#define EC_CFG_NO_USB4_H 4 +#define EC_CFG_NO_USB4_MASK GENMASK(EC_CFG_NO_USB4_H, EC_CFG_NO_USB4_L) +/* + * Thermal solution config (3 bits). + */ +#define EC_CFG_THERMAL_L 5 +#define EC_CFG_THERMAL_H 7 +#define EC_CFG_THERMAL_MASK GENMASK(EC_CFG_THERMAL_H, EC_CFG_THERMAL_L) + +unsigned int ec_config_get_thermal_solution(void); + +#endif /* !__ASSEMBLER__ */ + +/* Pin renaming */ +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_PP5000_A_PG_OD GPIO_PG_PP5000_A_OD +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL +#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_ROA_RAILS +#define GPIO_AC_PRESENT GPIO_BJ_ADP_PRESENT_L + +/* + * There is no RSMRST input, so alias it to the output. This short-circuits + * common_intel_x86_handle_rsmrst. + */ +#define GPIO_PG_EC_RSMRST_ODL GPIO_PCH_RSMRST_L + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/genesis/build.mk b/board/genesis/build.mk new file mode 100644 index 0000000000..50d3763d2b --- /dev/null +++ b/board/genesis/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc + +board-y=board.o +board-y+=led.o +board-y+=pse.o diff --git a/board/genesis/ec.tasklist b/board/genesis/ec.tasklist new file mode 100644 index 0000000000..c43d643410 --- /dev/null +++ b/board/genesis/ec.tasklist @@ -0,0 +1,15 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 2048) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/genesis/gpio.inc b/board/genesis/gpio.inc new file mode 100644 index 0000000000..7d2c33c5a9 --- /dev/null +++ b/board/genesis/gpio.inc @@ -0,0 +1,170 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Pin names follow the schematic, and are aliased to other names if necessary. + * Note: Those with interrupt handlers must be declared first. */ + +/* Latency on this interrupt is extremely critical, so it comes first to ensure + * it gets placed first in gpio_wui_table so gpio_interrupt() needs to do + * minimal scanning. */ +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, c10_gate_interrupt) + +/* Wake Source interrupts */ +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(PG_PP5000_A_OD, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1800_A_OD, PIN(3, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VPRIM_CORE_A_OD, PIN(2, 3), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1050_A_OD, PIN(2, 2), GPIO_INT_BOTH, power_signal_interrupt) +/* EC output, but also interrupt so this can be polled as a power signal */ +GPIO_INT(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUTPUT | GPIO_INT_F_RISING | GPIO_INT_F_FALLING, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(PG_PP2500_DRAM_U_OD, PIN(2, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1200_U_OD, PIN(2, 1), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, slp_s3_interrupt) +#endif +GPIO_INT(PG_PP950_VCCIO_OD, PIN(1, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(IMVP8_VRRDY_OD, PIN(1, 6), GPIO_INT_BOTH, power_signal_interrupt) + +/* + * Directly connected recovery button (not available on some boards). + */ +GPIO_INT(EC_RECOVERY_BTN_ODL, PIN(F, 1), GPIO_INT_BOTH, button_interrupt) +/* + * Recovery button input from H1. + */ +GPIO_INT(H1_EC_RECOVERY_BTN_ODL, PIN(2, 4), GPIO_INT_BOTH, button_interrupt) +GPIO(BJ_ADP_PRESENT_L, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP) + +/* Port power control interrupts */ +GPIO_INT(HDMI_CONN0_OC_ODL, PIN(0, 7), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(HDMI_CONN1_OC_ODL, PIN(0, 6), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(A, 2), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A2_OC_ODL, PIN(F, 5), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A3_OC_ODL, PIN(0, 3), GPIO_INT_BOTH, port_ocp_interrupt) + +/* PCH/CPU signals */ +GPIO(EC_PCH_PWROK, PIN(0, 5), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_IN_OD, PIN(3, 4), GPIO_INPUT) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +/* Power control outputs */ +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PP3300_INA_H1_EC_ODL, PIN(5, 7), GPIO_ODR_HIGH) +GPIO(EN_PP1800_A, PIN(1, 5), GPIO_OUT_LOW) +GPIO(VCCST_PG_OD, PIN(1, 4), GPIO_ODR_LOW) +GPIO(EN_S0_RAILS, PIN(1, 1), GPIO_OUT_LOW) +GPIO(EN_ROA_RAILS, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP950_VCCIO, PIN(1, 0), GPIO_OUT_LOW) +GPIO(EC_IMVP8_PE, PIN(A, 7), GPIO_OUT_LOW) +GPIO(EN_IMVP8_VR, PIN(F, 4), GPIO_OUT_LOW) + +/* Barreljack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 4), GPIO_OUT_LOW) + +/* USB type A */ +GPIO(EN_PP5000_USB_VBUS, PIN(8, 3), GPIO_OUT_LOW) +GPIO(USB_A_LOW_PWR_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(USB_A3_LOW_PWR_OD, PIN(5, 0), GPIO_ODR_LOW) +GPIO(USB_A1_STATUS_L, PIN(6, 1), GPIO_INPUT) +GPIO(USB_A2_STATUS_L, PIN(C, 7), GPIO_INPUT) +GPIO(USB_A3_STATUS_L, PIN(D, 2), GPIO_INPUT) + +/* USB type C */ +GPIO(USB_C0_TCPC_RST, PIN(9, 7), GPIO_OUT_LOW) +GPIO(USB_C0_POL_L, PIN(0, 0), GPIO_INPUT | GPIO_SEL_1P8V) /* USB-C Polarity */ + +/* TPU */ +GPIO(PP3300_TPU_EN, PIN(E, 4), GPIO_OUT_HIGH) + +/* PSE controller */ +GPIO(EC_PSE_PWM_INT, PIN(B, 0), GPIO_INPUT) /* PSE controller interrupt */ +GPIO(EC_RST_LTC4291_L, PIN(9, 6), GPIO_OUT_HIGH) /* PSE controller reset */ + +/* Misc. */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) +GPIO(PACKET_MODE_EN, PIN(7, 5), GPIO_OUT_LOW) + +/* HDMI/CEC */ +GPIO(HDMI_CONN0_CEC_OUT, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(HDMI_CONN0_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CONN1_CEC_OUT, PIN(9, 5), GPIO_ODR_HIGH) +GPIO(HDMI_CONN1_CEC_IN, PIN(D, 3), GPIO_INPUT) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(I2C0_SCL, PIN(B, 5), GPIO_INPUT) /* EC_I2C_INA_SCL */ +GPIO(I2C0_SDA, PIN(B, 4), GPIO_INPUT) /* EC_I2C_INA_SDA */ +GPIO(I2C1_SCL, PIN(9, 0), GPIO_INPUT) /* EC_I2C_USB_C0_TCPPC_SCL */ +GPIO(I2C1_SDA, PIN(8, 7), GPIO_INPUT) /* EC_I2C_USB_C0_TCPPC_SDA */ +GPIO(I2C3_SCL, PIN(D, 1), GPIO_INPUT) /* EC_I2C_USB_C0_TCPC_SCL */ +GPIO(I2C3_SDA, PIN(D, 0), GPIO_INPUT) /* EC_I2C_USB_C0_TCPC_SDA */ +GPIO(I2C4_SCL, PIN(F, 3), GPIO_INPUT) /* EC_I2C_LTC_SCL */ +GPIO(I2C4_SDA, PIN(F, 2), GPIO_INPUT) /* EC_I2C_LTC_SDA */ +GPIO(I2C5_SCL, PIN(3, 3), GPIO_INPUT) /* EC_I2C_IMVP8_SCL */ +GPIO(I2C5_SDA, PIN(3, 6), GPIO_INPUT) /* EC_I2C_IMVP8_SDA */ +GPIO(I2C7_SCL, PIN(B, 3), GPIO_INPUT) /* EC_I2C_EEPROM_SCL */ +GPIO(I2C7_SDA, PIN(B, 2), GPIO_INPUT) /* EC_I2C_EEPROM_SDA */ + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(9, 0x01), 0, MODULE_I2C, 0) /* I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(F, 0x0C), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, 0x0C), 0, MODULE_I2C, 0) /* I2C7 */ + +/* PWM */ +ALTERNATE(PIN_MASK(C, 0x08), 0, MODULE_PWM, 0) /* PWM0 - Red Led */ +ALTERNATE(PIN_MASK(C, 0x10), 0, MODULE_PWM, 0) /* PWM2 - White Led */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* PWM5 - Fan 1 */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* TA2 - Fan Tachometer */ + +/* ADC */ +ALTERNATE(PIN_MASK(4, 0x2A), 0, MODULE_ADC, 0) /* ADC0, ADC2, ADC4 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* ADC7 */ +ALTERNATE(PIN_MASK(F, 0x01), 0, MODULE_ADC, 0) /* ADC9 */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Unused pins */ +UNUSED(PIN(1, 3)) /* EC_GP_SEL1_ODL */ +UNUSED(PIN(C, 0)) /* FAN_PWM_2 */ +UNUSED(PIN(8, 0)) /* LED_BLUE_L */ +UNUSED(PIN(4, 4)) /* ADC1/TEMP_SENSOR_2 */ +UNUSED(PIN(4, 2)) /* ADC3/TEMP_SENSOR_3 */ +UNUSED(PIN(C, 2)) /* A12 NC */ +UNUSED(PIN(9, 2)) /* K8 NC */ +UNUSED(PIN(9, 1)) /* L8 NC */ +UNUSED(PIN(1, 2)) /* C6 NC */ +UNUSED(PIN(6, 6)) /* H4 NC */ +UNUSED(PIN(8, 1)) /* L6 NC */ +UNUSED(PIN(C, 6)) /* B11 NC */ +UNUSED(PIN(E, 2)) /* B8 NC */ +UNUSED(PIN(8, 5)) /* L7 NC */ +UNUSED(PIN(3, 2)) /* E5 NC */ +UNUSED(PIN(D, 6)) /* F6 NC */ +UNUSED(PIN(3, 5)) /* F5 NC */ +UNUSED(PIN(5, 6)) /* M2 NC */ +UNUSED(PIN(8, 6)) /* J8 NC */ +UNUSED(PIN(9, 3)) /* M11 NC */ +UNUSED(PIN(7, 2)) /* H6 NC */ diff --git a/board/genesis/led.c b/board/genesis/led.c new file mode 100644 index 0000000000..9258b6eb6d --- /dev/null +++ b/board/genesis/led.c @@ -0,0 +1,274 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Puff. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_WHITE, + LED_AMBER, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int white = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_WHITE: + white = 1; + break; + case LED_RED: + red = 1; + break; + case LED_AMBER: + red = 1; + white = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (white) + pwm_set_duty(PWM_CH_LED_WHITE, duty); + else + pwm_set_duty(PWM_CH_LED_WHITE, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_WHITE); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_WHITE, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +static void led_init(void) +{ + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_WHITE, 1); + + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + led_suspend(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown(); +} +DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_INIT_PWM + 1); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "white")) { + set_color(id, LED_WHITE, 100); + } else if (!strcasecmp(argv[1], "amber")) { + set_color(id, LED_AMBER, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, + "[debug|red|white|amber|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; + brightness_range[EC_LED_COLOR_AMBER] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_WHITE]) + return set_color(id, LED_WHITE, brightness[EC_LED_COLOR_WHITE]); + else if (brightness[EC_LED_COLOR_AMBER]) + return set_color(id, LED_AMBER, brightness[EC_LED_COLOR_AMBER]); + else + return set_color(id, LED_OFF, 0); +} diff --git a/board/genesis/pse.c b/board/genesis/pse.c new file mode 100644 index 0000000000..bda7e1994d --- /dev/null +++ b/board/genesis/pse.c @@ -0,0 +1,265 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * The LTC4291 is a power over ethernet (PoE) power sourcing equipment (PSE) + * controller. + */ + +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "string.h" +#include "timer.h" +#include "util.h" + +#define LTC4291_I2C_ADDR 0x2C + +#define LTC4291_REG_SUPEVN_COR 0x0B +#define LTC4291_REG_STATPWR 0x10 +#define LTC4291_REG_STATPIN 0x11 +#define LTC4291_REG_OPMD 0x12 +#define LTC4291_REG_DISENA 0x13 +#define LTC4291_REG_DETENA 0x14 +#define LTC4291_REG_DETPB 0x18 +#define LTC4291_REG_PWRPB 0x19 +#define LTC4291_REG_RSTPB 0x1A +#define LTC4291_REG_ID 0x1B +#define LTC4291_REG_DEVID 0x43 +#define LTC4291_REG_HPMD1 0x46 +#define LTC4291_REG_HPMD2 0x4B +#define LTC4291_REG_HPMD3 0x50 +#define LTC4291_REG_HPMD4 0x55 +#define LTC4291_REG_LPWRPB 0x6E + +#define LTC4291_FLD_STATPIN_AUTO BIT(0) +#define LTC4291_FLD_RSTPB_RSTALL BIT(4) + +#define LTC4291_STATPWR_ON_PORT(port) (0x01 << (port)) +#define LTC4291_DETENA_EN_PORT(port) (0x11 << (port)) +#define LTC4291_DETPB_EN_PORT(port) (0x11 << (port)) +#define LTC4291_PWRPB_OFF_PORT(port) (0x10 << (port)) + +#define LTC4291_OPMD_AUTO 0xFF +#define LTC4291_DISENA_ALL 0x0F +#define LTC4291_DETENA_ALL 0xFF +#define LTC4291_ID 0x64 +#define LTC4291_DEVID 0x38 +#define LTC4291_HPMD_MIN 0x00 +#define LTC4291_HPMD_MAX 0xA8 + +#define LTC4291_PORT_MAX 4 + +#define LTC4291_RESET_DELAY_US (20 * MSEC) + +#define I2C_PSE_READ(reg, data) \ + i2c_read8(I2C_PORT_PSE, LTC4291_I2C_ADDR, LTC4291_REG_##reg, (data)) + +#define I2C_PSE_WRITE(reg, data) \ + i2c_write8(I2C_PORT_PSE, LTC4291_I2C_ADDR, LTC4291_REG_##reg, (data)) + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static int pse_write_hpmd(int port, int val) +{ + switch (port) { + case 0: + return I2C_PSE_WRITE(HPMD1, val); + case 1: + return I2C_PSE_WRITE(HPMD2, val); + case 2: + return I2C_PSE_WRITE(HPMD3, val); + case 3: + return I2C_PSE_WRITE(HPMD4, val); + default: + return EC_ERROR_INVAL; + } +} + +/* + * Port 1: 100W + * Port 2-4: 15W + */ +static int pse_port_hpmd[4] = { + LTC4291_HPMD_MAX, + LTC4291_HPMD_MIN, + LTC4291_HPMD_MIN, + LTC4291_HPMD_MIN, +}; + +static int pse_port_enable(int port) +{ + /* Enable detection and classification */ + return I2C_PSE_WRITE(DETPB, LTC4291_DETPB_EN_PORT(port)); +} + +static int pse_port_disable(int port) +{ + /* Request power off (this also disables detection/classification) */ + return I2C_PSE_WRITE(PWRPB, LTC4291_PWRPB_OFF_PORT(port)); +} + +static int pse_init_worker(void) +{ + timestamp_t deadline; + int err, id, devid, statpin, port; + + /* Ignore errors -- may already be resetting */ + I2C_PSE_WRITE(RSTPB, LTC4291_FLD_RSTPB_RSTALL); + + deadline.val = get_time().val + LTC4291_RESET_DELAY_US; + while ((err = I2C_PSE_READ(ID, &id)) != 0) { + if (timestamp_expired(deadline, NULL)) + return err; + } + + err = I2C_PSE_READ(DEVID, &devid); + if (err != 0) + return err; + + if (id != LTC4291_ID || devid != LTC4291_DEVID) + return EC_ERROR_INVAL; + + err = I2C_PSE_READ(STATPIN, &statpin); + if (err != 0) + return err; + + /* + * We don't want to supply power until we've had a chance to set the + * limits. + */ + if (statpin & LTC4291_FLD_STATPIN_AUTO) + CPRINTS("WARN: PSE reset in AUTO mode"); + + err = I2C_PSE_WRITE(OPMD, LTC4291_OPMD_AUTO); + if (err != 0) + return err; + + /* Set maximum power each port is allowed to allocate. */ + for (port = 0; port < LTC4291_PORT_MAX; port++) { + err = pse_write_hpmd(port, pse_port_hpmd[port]); + if (err != 0) + return err; + } + + err = I2C_PSE_WRITE(DISENA, LTC4291_DISENA_ALL); + if (err != 0) + return err; + + err = I2C_PSE_WRITE(DETENA, LTC4291_DETENA_ALL); + if (err != 0) + return err; + + return 0; +} + +static void pse_init(void) +{ + int err; + + err = pse_init_worker(); + if (err != 0) + CPRINTS("PSE init failed: %d", err); + else + CPRINTS("PSE init done"); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, pse_init, HOOK_PRIO_DEFAULT); + +/* Also reset the PSE on a reboot to toggle the power. */ +DECLARE_HOOK(HOOK_CHIPSET_RESET, pse_init, HOOK_PRIO_DEFAULT); + +static int command_pse(int argc, const char **argv) +{ + int port; + + /* + * TODO(b/156399232): endeavour: PSE controller reset by PLTRST + * + * Initialization does not reliably work after reset because the device + * is held in reset by the AP. Running this command after boot finishes + * always succeeds. Remove once the reset signal changes. + */ + if (!strncmp(argv[1], "init", 4)) + return pse_init_worker(); + + if (argc != 3) + return EC_ERROR_PARAM_COUNT; + + port = atoi(argv[1]); + if (port < 0 || port >= LTC4291_PORT_MAX) + return EC_ERROR_PARAM1; + + if (!strncmp(argv[2], "off", 3)) + return pse_port_disable(port); + else if (!strncmp(argv[2], "on", 2)) + return pse_port_enable(port); + else if (!strncmp(argv[2], "min", 3)) + return pse_write_hpmd(port, LTC4291_HPMD_MIN); + else if (!strncmp(argv[2], "max", 3)) + return pse_write_hpmd(port, LTC4291_HPMD_MAX); + else + return EC_ERROR_PARAM2; +} +DECLARE_CONSOLE_COMMAND(pse, command_pse, " ", + "Set PSE port power"); + +static int ec_command_pse_status(int port, uint8_t *status) +{ + int detena, statpwr; + int err; + + err = I2C_PSE_READ(DETENA, &detena); + if (err != 0) + return err; + + err = I2C_PSE_READ(STATPWR, &statpwr); + if (err != 0) + return err; + + if ((detena & LTC4291_DETENA_EN_PORT(port)) == 0) + *status = EC_PSE_STATUS_DISABLED; + else if ((statpwr & LTC4291_STATPWR_ON_PORT(port)) == 0) + *status = EC_PSE_STATUS_ENABLED; + else + *status = EC_PSE_STATUS_POWERED; + + return 0; +} + +static enum ec_status ec_command_pse(struct host_cmd_handler_args *args) +{ + const struct ec_params_pse *p = args->params; + int err = 0; + + if (p->port >= LTC4291_PORT_MAX) + return EC_RES_INVALID_PARAM; + + switch (p->cmd) { + case EC_PSE_STATUS: { + struct ec_response_pse_status *r = args->response; + + args->response_size = sizeof(*r); + err = ec_command_pse_status(p->port, &r->status); + break; + } + case EC_PSE_ENABLE: + err = pse_port_enable(p->port); + break; + case EC_PSE_DISABLE: + err = pse_port_disable(p->port); + break; + default: + return EC_RES_INVALID_PARAM; + } + + if (err) + return EC_RES_ERROR; + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PSE, ec_command_pse, EC_VER_MASK(0)); diff --git a/board/gimble/battery.c b/board/gimble/battery.c new file mode 100644 index 0000000000..89b0ddf1e2 --- /dev/null +++ b/board/gimble/battery.c @@ -0,0 +1,94 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "compile_time_macros.h" + +/* + * Battery info for all Brya battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* SMP 996QA193H Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-1D-11-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + /* Cosmx CA407792G Battery Information */ + [BATTERY_COSMX] = { + .fuel_gauge = { + .manuf_name = "333-AC-11-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO_HIGHPOWER; diff --git a/board/gimble/board.c b/board/gimble/board.c new file mode 100644 index 0000000000..0a04dc5714 --- /dev/null +++ b/board/gimble/board.c @@ -0,0 +1,187 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/accel_bma2x2_public.h" +#include "driver/accel_bma422.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/charger/bq25710.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "keyboard_8042_sharedlib.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "ps8xxx.h" +#include "registers.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +__override void board_cbi_init(void) +{ + config_usb_db_type(); + + /* + * If keyboard is US2(KB_LAYOUT_1), we need translate right ctrl + * to backslash(\|) key. + */ + if (ec_cfg_keyboard_layout() == KB_LAYOUT_1) + set_scancode_set2(4, 0, get_scancode_set2(2, 7)); +} + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + + /* TODO(b/190783131) + * Need to implement specific keyboard backlight control method. + */ +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + + /* TODO(b/190783131) + * Need to implement specific keyboard backlight control method. + */ +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} + +static void board_init(void) +{ + /* The PPVAR_SYS must same as battery voltage(3 cells * 4.4V) */ + if (extpower_is_present() && battery_hw_present()) { + bq25710_set_min_system_voltage(CHARGER_SOLO, 9200); + } else { + bq25710_set_min_system_voltage(CHARGER_SOLO, 13200); + } +} +DECLARE_HOOK(HOOK_SECOND, board_init, HOOK_PRIO_DEFAULT); + +__overridable void board_ps8xxx_tcpc_init(int port) +{ + int val; + + if (i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_P1_FLAGS, + PS8815_REG_APTX_EQ_AT_10G, &val)) + CPRINTS("ps8815: fail to read reg 0x%02x", + PS8815_REG_APTX_EQ_AT_10G); + + /* APTX2 EQ 23dB, APTX1 EQ 23dB */ + if (i2c_write8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_P1_FLAGS, + PS8815_REG_APTX_EQ_AT_10G, 0x99)) + CPRINTS("ps8815: fail to write reg 0x%02x", + PS8815_REG_APTX_EQ_AT_10G); + + if (i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_P1_FLAGS, + PS8815_REG_RX_EQ_AT_10G, &val)) + CPRINTS("ps8815: fail to read reg 0x%02x", + PS8815_REG_RX_EQ_AT_10G); + + /* RX2 EQ 18dB, RX1 EQ 16dB */ + if (i2c_write8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_P1_FLAGS, + PS8815_REG_RX_EQ_AT_10G, 0x64)) + CPRINTS("ps8815: fail to write reg 0x%02x", + PS8815_REG_RX_EQ_AT_10G); + + if (i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_P1_FLAGS, + PS8815_REG_APTX_EQ_AT_5G, &val)) + CPRINTS("ps8815: fail to read reg 0x%02x", + PS8815_REG_APTX_EQ_AT_5G); + + /* APTX2 EQ 16dB, APTX1 EQ 16dB */ + if (i2c_write8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_P1_FLAGS, + PS8815_REG_APTX_EQ_AT_5G, 0x44)) + CPRINTS("ps8815: fail to write reg 0x%02x", + PS8815_REG_APTX_EQ_AT_5G); + + if (i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_P1_FLAGS, + PS8815_REG_RX_EQ_AT_5G, &val)) + CPRINTS("ps8815: fail to read reg 0x%02x", + PS8815_REG_RX_EQ_AT_5G); + + /* RX2 EQ 16dB, RX1 EQ 16dB */ + if (i2c_write8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_P1_FLAGS, + PS8815_REG_RX_EQ_AT_5G, 0x44)) + CPRINTS("ps8815: fail to write reg 0x%02x", + PS8815_REG_RX_EQ_AT_5G); +} diff --git a/board/gimble/board.h b/board/gimble/board.h new file mode 100644 index 0000000000..3fd3adcafa --- /dev/null +++ b/board/gimble/board.h @@ -0,0 +1,266 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* Sensors */ +/* BMA253 accelerometer in lid */ +#define CONFIG_ACCEL_BMA255 + +#define CONFIG_ACCELGYRO_BMI160 /* Base accel/gyro */ +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* BMA422 accelerometer in lid */ +#define CONFIG_ACCEL_BMA4XX + +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel/gyro */ +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +/* Lid accel */ +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 1 + +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID +#undef CONFIG_USBC_RETIMER_INTEL_BB + +#define CONFIG_USBC_PPC_SYV682X +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 +#define CONFIG_USBC_PPC_NX20P3483 + +#define CONFIG_USB_PD_FRS +#define CONFIG_USB_PD_FRS_PPC + +/* measure and check these values on gimble */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* Keyboard features */ +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT4_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +/* define this to aviod error on CONFIG_ACCELGYRO_BMI_COMM_I2C */ +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* Disabling Thunderbolt-compatible mode */ +#undef CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#undef CONFIG_USB_PD_USB4 + +/* Retimer */ +#undef CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_FANS FAN_CH_COUNT +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* + * TODO(b/181271666): no fan control loop until sensors are tuned + */ +/* Fan features */ +#define CONFIG_CUSTOM_FAN_CONTROL + +/* Charger defines */ +#define CONFIG_CHARGER_BQ25720 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 70 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_BQ25710_PSYS_SENSING +/* OEM requested 10% derating */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 10 + +/* PROCHOT defines */ +#define BATT_MAX_CONTINUE_DISCHARGE_WATT 45 + +/* Prochot assertion/deassertion ratios*/ +#define PROCHOT_ADAPTER_WATT_RATIO 97 +#define PROCHOT_ASSERTION_BATTERY_RATIO 95 +#define PROCHOT_DEASSERTION_BATTERY_RATIO 85 +#define PROCHOT_ASSERTION_PD_RATIO 104 +#define PROCHOT_DEASSERTION_PD_RATIO 94 +#define PROCHOT_DEASSERTION_PD_BATTERY_RATIO 95 +#define PROCHOT_ASSERTION_ADAPTER_RATIO 102 +#define PROCHOT_DEASSERTION_ADAPTER_RATIO 100 +#define PROCHOT_DEASSERTION_ADAPTER_BATT_RATIO 90 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_FAN, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_IADPT, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_FAN, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { LID_ACCEL = 0, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_PORT_COUNT }; + +enum battery_type { + BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COSMX, + BATTERY_TYPE_COUNT +}; + +enum pwm_channel { + PWM_CH_LED2 = 0, /* PWM0 (white charger) */ + PWM_CH_LED3, /* PWM1 (orange on DB) */ + PWM_CH_LED1, /* PWM2 (orange charger) */ + PWM_CH_KBLIGHT, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED4, /* PWM7 (white on DB) */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/gimble/build.mk b/board/gimble/build.mk new file mode 100644 index 0000000000..cad0da2a4e --- /dev/null +++ b/board/gimble/build.mk @@ -0,0 +1,26 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=thermal.o +board-y+=usbc_config.o diff --git a/board/gimble/charger.c b/board/gimble/charger.c new file mode 100644 index 0000000000..827152e115 --- /dev/null +++ b/board/gimble/charger.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/gimble/ec.tasklist b/board/gimble/ec.tasklist new file mode 100644 index 0000000000..27ab9a6e63 --- /dev/null +++ b/board/gimble/ec.tasklist @@ -0,0 +1,31 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_NOTEST(PROCHOT, prochot_task, NULL, VENTI_TASK_STACK_SIZE) diff --git a/board/gimble/fans.c b/board/gimble/fans.c new file mode 100644 index 0000000000..69d7542f37 --- /dev/null +++ b/board/gimble/fans.c @@ -0,0 +1,88 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/180681346): need to update for real fan + * + * Prototype fan spins at about 7200 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2200, + .rpm_start = 2200, + .rpm_max = 7200, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/181271666): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/gimble/fw_config.c b/board/gimble/fw_config.c new file mode 100644 index 0000000000..8698145efd --- /dev/null +++ b/board/gimble/fw_config.c @@ -0,0 +1,65 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union brya_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brya if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union brya_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_PS8815, + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Brya FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* + * Early boards have a zero'd out FW_CONFIG, so replace + * it with a sensible default value. If DB_USB_ABSENT2 + * was used as an alternate encoding of DB_USB_ABSENT to + * avoid the zero check, then fix it. + */ + if (fw_config.raw_value == 0) { + CPRINTS("CBI: FW_CONFIG is zero, using board defaults"); + fw_config = fw_config_defaults; + } else if (fw_config.usb_db == DB_USB_ABSENT2) { + fw_config.usb_db = DB_USB_ABSENT; + } + } +} + +union brya_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +enum ec_cfg_keyboard_layout ec_cfg_keyboard_layout(void) +{ + return fw_config.kb_layout; +} + +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void) +{ + return fw_config.usb_db; +} diff --git a/board/gimble/fw_config.h b/board/gimble/fw_config.h new file mode 100644 index 0000000000..fcf24b4094 --- /dev/null +++ b/board/gimble/fw_config.h @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_BRYA_FW_CONFIG_H_ +#define __BOARD_BRYA_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Brya board. + * + * Source of truth is the project/brya/brya/config.star configuration file. + */ + +enum ec_cfg_usb_db_type { + DB_USB_ABSENT = 0, + DB_USB3_PS8815 = 1, + DB_USB_ABSENT2 = 15 +}; + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_keyboard_layout { KB_LAYOUT_DEFAULT = 0, KB_LAYOUT_1 = 1 }; + +union brya_cbi_fw_config { + struct { + enum ec_cfg_usb_db_type usb_db : 4; + uint32_t sd_db : 2; + uint32_t reserved_0 : 1; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t cellular_db : 2; + uint32_t wifi_sar_id : 1; + enum ec_cfg_keyboard_layout kb_layout : 2; + uint32_t reserved_1 : 16; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union brya_cbi_fw_config get_fw_config(void); + +/** + * Get keyboard type from FW_CONFIG. + * + * @return the keyboard type. + */ +enum ec_cfg_keyboard_layout ec_cfg_keyboard_layout(void); + +/** + * Get the USB daughter board type from FW_CONFIG. + * + * @return the USB daughter board type. + */ +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void); + +#endif /* __BOARD_BRYA_FW_CONFIG_H_ */ diff --git a/board/gimble/gpio.inc b/board/gimble/gpio.inc new file mode 100644 index 0000000000..1961f1bcb4 --- /dev/null +++ b/board/gimble/gpio.inc @@ -0,0 +1,142 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_IMU_INT_R_L, PIN(5, 6), GPIO_SEL_1P8V | GPIO_INT_FALLING, motion_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_LOCK, PIN(0, 4), GPIO_INPUT) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(E, 1), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(POWER_LED_GATE, PIN(B, 6), GPIO_OUT_LOW) /* Power LED: White */ +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(6, 0x01), 0, MODULE_PWM, 0) /* GPIO60/PWM7 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x1c), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0, GPIOC2/PWM1/I2C6_SCL0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPO66/ARM_L_x86 */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */ +UNUSED(PIN(D, 4)) /* GPIOD4/CR_SIN3 */ +UNUSED(PIN(D, 1)) /* GPIOD1/I2C3_SCL0 */ +UNUSED(PIN(D, 0)) /* GPIOD0/I2C3_SDA0 */ +UNUSED(PIN(8, 3)) /* KSO15/GPIO83 */ +UNUSED(PIN(B, 1)) /* KSO17/GPIOB1/CR_SIN4 */ +UNUSED(PIN(4, 1)) /* GPIO41/ADC4 */ +UNUSED(PIN(A, 0)) /* F_CS0_L/GPIOA0 */ +UNUSED(PIN(9, 6)) /* F_DIO1/GPIO96 */ +UNUSED(PIN(7, 0)) /* GPIO70/PS2_DAT0 */ +UNUSED(PIN(8, 1)) /* PECI DATA/GPIO81 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ +UNUSED(PIN(8, 2)) /* KSO14/GPIO82 */ + +/* Pre-configured PSL balls: J8 K6 */ + + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) diff --git a/board/gimble/i2c.c b/board/gimble/i2c.c new file mode 100644 index 0000000000..621e7bf3f0 --- /dev/null +++ b/board/gimble/i2c.c @@ -0,0 +1,62 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0", + .port = I2C_PORT_USB_C0_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/gimble/keyboard.c b/board/gimble/keyboard.c new file mode 100644 index 0000000000..e1b0ca8a21 --- /dev/null +++ b/board/gimble/keyboard.c @@ -0,0 +1,51 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config gimble_kb = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_KBD_BKLIGHT_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &gimble_kb; +} diff --git a/board/gimble/led.c b/board/gimble/led.c new file mode 100644 index 0000000000..b56ccbbdca --- /dev/null +++ b/board/gimble/led.c @@ -0,0 +1,173 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "common.h" +#include "compile_time_macros.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "pwm.h" +#include "util.h" + +#include + +#define BAT_LED_ON_LVL 100 +#define BAT_LED_OFF_LVL 0 + +#define PWR_LED_ON_LVL 1 +#define PWR_LED_OFF_LVL 0 + +#define LED_SIDESEL_MB_PORT 0 +#define LED_SIDESEL_DB_PORT 1 + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + int port; + + /* There are four battery leds, LED1/LED2 are on MB side and + * LED3/LED4 are on DB side. All leds are OFF by default. + */ + int led1_duty, led2_duty, led3_duty, led4_duty; + + led1_duty = led2_duty = led3_duty = led4_duty = BAT_LED_OFF_LVL; + + /* Check which port is the charging port, + * and turn on the corresponding led. + */ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + port = charge_manager_get_active_charge_port(); + switch (port) { + case LED_SIDESEL_MB_PORT: + switch (color) { + case EC_LED_COLOR_AMBER: + led1_duty = BAT_LED_ON_LVL; + break; + case EC_LED_COLOR_WHITE: + led2_duty = BAT_LED_ON_LVL; + break; + default: /* LED_OFF and other unsupported colors */ + break; + } + break; + case LED_SIDESEL_DB_PORT: + switch (color) { + case EC_LED_COLOR_AMBER: + led3_duty = BAT_LED_ON_LVL; + break; + case EC_LED_COLOR_WHITE: + led4_duty = BAT_LED_ON_LVL; + break; + default: /* LED_OFF and other unsupported colors */ + break; + } + break; + default: /* Unknown charging port */ + break; + } + } else { + switch (color) { + case EC_LED_COLOR_AMBER: + led1_duty = BAT_LED_ON_LVL; + led3_duty = BAT_LED_ON_LVL; + break; + case EC_LED_COLOR_WHITE: + led2_duty = BAT_LED_ON_LVL; + led4_duty = BAT_LED_ON_LVL; + break; + default: /* LED_OFF and other unsupported colors */ + break; + } + } + + pwm_set_duty(PWM_CH_LED1, led1_duty); + pwm_set_duty(PWM_CH_LED2, led2_duty); + pwm_set_duty(PWM_CH_LED3, led3_duty); + pwm_set_duty(PWM_CH_LED4, led4_duty); +} + +__override void led_set_color_power(enum ec_led_colors color) +{ + if (color == EC_LED_COLOR_WHITE) + gpio_set_level(GPIO_POWER_LED_GATE, PWR_LED_ON_LVL); + else + /* LED_OFF and unsupported colors */ + gpio_set_level(GPIO_POWER_LED_GATE, PWR_LED_OFF_LVL); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + led_auto_control(led_id, 0); + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[LED_OFF] != 0) + led_set_color_battery(LED_OFF); + else { + led_auto_control(led_id, 1); + led_set_color_battery(LED_OFF); + } + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/gimble/pwm.c b/board/gimble/pwm.c new file mode 100644 index 0000000000..9f9a8ed94f --- /dev/null +++ b/board/gimble/pwm.c @@ -0,0 +1,70 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED2] = { + .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_LED3] = { + .channel = 1, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_LED1] = { + .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, + [PWM_CH_LED4] = { + .channel = 7, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* Turn off LED1 to LED4 */ + pwm_enable(PWM_CH_LED1, 1); + pwm_set_duty(PWM_CH_LED1, 0); + pwm_enable(PWM_CH_LED2, 1); + pwm_set_duty(PWM_CH_LED2, 0); + pwm_enable(PWM_CH_LED3, 1); + pwm_set_duty(PWM_CH_LED3, 0); + pwm_enable(PWM_CH_LED4, 1); + pwm_set_duty(PWM_CH_LED4, 0); + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + /* Turn on KB LED at 50%. */ + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/gimble/sensors.c b/board/gimble/sensors.c new file mode 100644 index 0000000000..0f415f168f --- /dev/null +++ b/board/gimble/sensors.c @@ -0,0 +1,387 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc_chip.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_bma2x2_public.h" +#include "driver/accel_bma422.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_FAN] = { + .name = "TEMP_FAN", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_IADPT] = { + .name = "CHARGER_IADPT", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +/* BMA253 private data */ +static struct accelgyro_saved_data_t g_bma253_data; + +/* BMI160 private data */ +static struct bmi_drv_data_t g_bmi160_data; + +/* LSM6DSM private data */ +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* BMA422 private data */ +static struct accelgyro_saved_data_t g_bma422_data; + +/* TODO(b/192477578): calibrate the orientation matrix on later board stage */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref_id_1 = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* TODO(b/192477578): calibrate the orientation matrix on later board stage */ +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_standard_ref_id_1 = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR2_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t bma422_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_SECONDARY, + .rot_standard_ref = &lid_standard_ref_id_1, + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .default_range = 2, /* g, enough for laptop. */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, +}; + +struct motion_sensor_t lsm6dsm_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_id_1, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t lsm6dsm_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref_id_1, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +void motion_interrupt(enum gpio_signal signal) +{ + if (get_board_id() >= 1) + lsm6dsm_interrupt(signal); + else + bmi160_interrupt(signal); +} + +static void update_sensor_array(void) +{ + if (get_board_id() >= 1) { + motion_sensors[LID_ACCEL] = bma422_lid_accel; + motion_sensors[BASE_ACCEL] = lsm6dsm_base_accel; + motion_sensors[BASE_GYRO] = lsm6dsm_base_gyro; + ccprints("LID ACCEL is BMA422"); + ccprints("BASE IMU is LSM6DSM"); + } else { + ccprints("LID ACCEL is BMA253"); + ccprints("BASE IMU is BMI160"); + } +} +DECLARE_HOOK(HOOK_INIT, update_sensor_array, HOOK_PRIO_INIT_I2C); + +static void baseboard_sensors_init(void) +{ + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_R_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC }, + [TEMP_SENSOR_2_FAN] = { .name = "Fan", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_FAN }, + [TEMP_SENSOR_3_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/194318801): confirm thermal limits setting for gimble + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/194318801): confirm thermal limits setting for gimble + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; + +#define THERMAL_FAN_MISSING \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan_missing = + THERMAL_FAN_MISSING; + +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + /* TODO(b/194318801): confirm thermal limits setting for gimble */ + [TEMP_SENSOR_2_FAN] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_CHARGER] = THERMAL_INDUCTOR, +}; + +struct ec_thermal_config temp_sensor_2_fan_set[] = { + [TEMP_SENSOR_2_FAN] = THERMAL_FAN_MISSING, +}; + +static void config_thermal_params(void) +{ + int rv, val; + + rv = tcpc_addr_read16_no_lpm_exit(USBC_PORT_C1, PS8XXX_I2C_ADDR1_FLAGS, + TCPC_REG_VENDOR_ID, &val); + + if (rv != 0) { + thermal_params[TEMP_SENSOR_2_FAN] = + temp_sensor_2_fan_set[TEMP_SENSOR_2_FAN]; + } +} +DECLARE_HOOK(HOOK_INIT, config_thermal_params, HOOK_PRIO_INIT_I2C + 1); + +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/gimble/thermal.c b/board/gimble/thermal.c new file mode 100644 index 0000000000..37184f92f2 --- /dev/null +++ b/board/gimble/thermal.c @@ -0,0 +1,156 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "fan.h" +#include "hooks.h" +#include "host_command.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +struct fan_step { + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t on[TEMP_SENSOR_COUNT]; + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t off[TEMP_SENSOR_COUNT]; + /* Fan rpm */ + uint16_t rpm[FAN_CH_COUNT]; + /* Fan rpm for tablet mode */ + uint16_t rpm_tablet[FAN_CH_COUNT]; +}; +/* + * TODO(b/167931578) Only monitor sensor3 for now. + * Will add more sensors support if needed. + */ +static const struct fan_step fan_table[] = { + { + /* level 0 */ + .on = { 43, -1, -1 }, + .off = { 0, -1, -1 }, + .rpm = { 0 }, + .rpm_tablet = { 0 }, + }, + { + /* level 1 */ + .on = { 45, -1, -1 }, + .off = { 43, -1, -1 }, + .rpm = { 3400 }, + .rpm_tablet = { 3400 }, + }, + { + /* level 2 */ + .on = { 46, -1, -1 }, + .off = { 44, -1, -1 }, + .rpm = { 3800 }, + .rpm_tablet = { 3700 }, + }, + { + /* level 3 */ + .on = { 48, -1, -1 }, + .off = { 45, -1, -1 }, + .rpm = { 4200 }, + .rpm_tablet = { 4100 }, + }, + { + /* level 4 */ + .on = { 50, -1, -1 }, + .off = { 47, -1, -1 }, + .rpm = { 4800 }, + .rpm_tablet = { 4800 }, + }, + { + /* level 5 */ + .on = { 52, -1, -1 }, + .off = { 49, -1, -1 }, + .rpm = { 5400 }, + .rpm_tablet = { 5200 }, + }, +}; +const int num_fan_levels = ARRAY_SIZE(fan_table); + +int fan_table_to_rpm(int fan, int *temp, enum temp_sensor_id temp_sensor) +{ + /* current fan level */ + static int current_level; + /* previous fan level */ + static int prev_current_level; + + /* previous sensor temperature */ + static int prev_temp[TEMP_SENSOR_COUNT]; + int i; + int new_rpm = 0; + + /* + * Compare the current and previous temperature, we have + * the three paths : + * 1. decreasing path. (check the release point) + * 2. increasing path. (check the trigger point) + * 3. invariant path. (return the current RPM) + */ + if (temp[temp_sensor] < prev_temp[temp_sensor]) { + for (i = current_level; i > 0; i--) { + if (temp[temp_sensor] < fan_table[i].off[temp_sensor]) + current_level = i - 1; + else + break; + } + } else if (temp[temp_sensor] > prev_temp[temp_sensor]) { + for (i = current_level; i < num_fan_levels; i++) { + if (temp[temp_sensor] >= fan_table[i].on[temp_sensor]) + current_level = i; + else + break; + } + } + if (current_level < 0) + current_level = 0; + + if (current_level != prev_current_level) { + CPRINTS("temp: %d, prev_temp: %d", temp[temp_sensor], + prev_temp[temp_sensor]); + CPRINTS("current_level: %d", current_level); + } + + prev_temp[temp_sensor] = temp[temp_sensor]; + prev_current_level = current_level; + + switch (fan) { + case FAN_CH_0: + if (tablet_get_mode()) + new_rpm = fan_table[current_level].rpm_tablet[FAN_CH_0]; + else + new_rpm = fan_table[current_level].rpm[FAN_CH_0]; + break; + default: + break; + } + return new_rpm; +} +void board_override_fan_control(int fan, int *temp) +{ + if (chipset_in_state(CHIPSET_STATE_ON)) { + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), + fan_table_to_rpm(FAN_CH(fan), temp, + TEMP_SENSOR_1_DDR_SOC)); + } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* Stop fan when enter S0ix */ + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), 0); + } +} diff --git a/board/gimble/usbc_config.c b/board/gimble/usbc_config.c new file mode 100644 index 0000000000..c566cbdcf6 --- /dev/null +++ b/board/gimble/usbc_config.c @@ -0,0 +1,279 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_VCONN | + TCPC_FLAGS_CONTROL_FRS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM536A0 */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = NX20P3483_ADDR2_FLAGS, + .drv = &nx20p348x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* + * USB3 DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, +}; + +/* USBC mux configuration - Alder Lake includes internal mux */ +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +void config_usb_db_type(void) +{ + enum ec_cfg_usb_db_type db_type = ec_cfg_usb_db_type(); + + /* + * TODO(b/180434685): implement multiple DB types + */ + + CPRINTS("Configured USB DB type number is %d", db_type); +} + +void board_reset_pd_mcu(void) +{ + /* Port0 */ + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 0); + + if (battery_hw_present()) + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + + /* wait for chips to come up */ + msleep(PS8815_FW_INIT_DELAY_MS); +} + +static void board_tcpc_init(void) +{ + int i; + + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + for (i = 0; i < CONFIG_IO_EXPANDER_PORT_COUNT; ++i) + ioex_init(i); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + nx20p348x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} diff --git a/board/gimble/usbc_config.h b/board/gimble/usbc_config.h new file mode 100644 index 0000000000..ab2dabc1e9 --- /dev/null +++ b/board/gimble/usbc_config.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void config_usb_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/gimble/vif_override.xml b/board/gimble/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/gimble/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/gingerbread/board.c b/board/gingerbread/board.c index 00e7eedc2e..62f871b55a 100644 --- a/board/gingerbread/board.c +++ b/board/gingerbread/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,15 +6,95 @@ /* Gingerbread board-specific configuration */ #include "common.h" +#include "cros_board_info.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/stm32gx.h" +#include "driver/tcpm/tcpci.h" +#include "driver/usb_mux/tusb1064.h" +#include "ec_version.h" #include "gpio.h" #include "hooks.h" +#include "mp4245.h" #include "switch.h" #include "system.h" #include "task.h" +#include "timer.h" #include "uart.h" +#include "usb_descriptor.h" +#include "usb_pd.h" +#include "usb_pd_dp_ufp.h" +#include "usb_pe_sm.h" +#include "usb_prl_sm.h" +#include "usb_tc_sm.h" +#include "usbc_ppc.h" #include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +#define QUICHE_PD_DEBUG_LVL 1 + +#ifdef SECTION_IS_RW +#define CROS_EC_SECTION "RW" +#else +#define CROS_EC_SECTION "RO" +#endif + +#ifdef SECTION_IS_RW +/* + * C1 port on gingerbread does not have a PPC. However, C0 port does have a PPC + * and therefore PPC related config options are defined. Defining a null driver + * here so that functions from usbc_ppc.c will correctly dereference to a NULL + * function pointer. + */ +const struct ppc_drv board_ppc_null_drv = {}; + +static int pd_dual_role_init[CONFIG_USB_PD_PORT_MAX_COUNT] = { + PD_DRP_TOGGLE_ON, + PD_DRP_FORCE_SOURCE, +}; + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_HOST_USBC_PPC_INT_ODL: + sn5s330_interrupt(USB_PD_PORT_HOST); + break; + + default: + break; + } +} + +static void tcpc_alert_event(enum gpio_signal s) +{ + int port = -1; + + switch (s) { + case GPIO_USBC_DP_MUX_ALERT_ODL: + port = USB_PD_PORT_DP; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +void hpd_interrupt(enum gpio_signal signal) +{ + usb_pd_hpd_edge_event(signal); +} + +static void board_pwr_btn_interrupt(enum gpio_signal signal) +{ + baseboard_power_button_evt(gpio_get_level(signal)); +} +#endif /* SECTION_IS_RW */ + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /* * Table GPIO signals control both power rails and reset lines to various chips @@ -22,35 +102,300 @@ * signals is driven by USB/MST hub power sequencing requirements. */ const struct power_seq board_power_seq[] = { - {GPIO_EN_AC_JACK, 1, 20}, - {GPIO_EN_PP5000_A, 1, 31}, - {GPIO_EN_PP3300_A, 1, 35}, - {GPIO_STATUS_LED1, 0, 100}, - {GPIO_EN_BB, 1, 30}, - {GPIO_EN_PP1100_A, 1, 30}, - {GPIO_EN_PP1000_A, 1, 20}, - {GPIO_EN_PP1050_A, 1, 30}, - {GPIO_EN_PP1200_A, 1, 20}, - {GPIO_EN_PP5000_HSPORT, 1, 31}, - {GPIO_EN_DP_SINK, 1, 80}, - {GPIO_MST_LP_CTL_L, 1, 80}, - {GPIO_MST_RST_L, 1, 41}, - {GPIO_EC_HUB1_RESET_L, 1, 41}, - {GPIO_EC_HUB2_RESET_L, 1, 33}, - {GPIO_USBC_DP_PD_RST_L, 1, 100}, - {GPIO_USBC_UF_RESET_L, 1, 33}, - {GPIO_DEMUX_DUAL_DP_PD_N, 1, 100}, - {GPIO_DEMUX_DUAL_DP_RESET_N, 1, 100}, - {GPIO_DEMUX_DP_HDMI_PD_N, 1, 10}, - {GPIO_DEMUX_DUAL_DP_MODE, 1, 10}, - {GPIO_DEMUX_DP_HDMI_MODE, 1, 1}, - {GPIO_STATUS_LED2, 0, 100}, + { GPIO_EN_AC_JACK, 1, 20 }, + { GPIO_EN_PP5000_A, 1, 31 }, + { GPIO_EN_PP3300_A, 1, 135 }, + { GPIO_EN_BB, 1, 30 }, + { GPIO_EN_PP1100_A, 1, 30 }, + { GPIO_EN_PP1000_A, 1, 20 }, + { GPIO_EN_PP1050_A, 1, 30 }, + { GPIO_EN_PP1200_A, 1, 20 }, + { GPIO_EN_PP5000_HSPORT, 1, 31 }, + { GPIO_EN_DP_SINK, 1, 80 }, + { GPIO_MST_LP_CTL_L, 1, 80 }, + { GPIO_MST_RST_L, 1, 41 }, + { GPIO_EC_HUB1_RESET_L, 1, 41 }, + { GPIO_EC_HUB2_RESET_L, 1, 33 }, + { GPIO_USBC_DP_PD_RST_L, 1, 100 }, + { GPIO_USBC_UF_RESET_L, 1, 33 }, + { GPIO_DEMUX_DUAL_DP_PD_N, 1, 100 }, + { GPIO_DEMUX_DUAL_DP_RESET_N, 1, 100 }, + { GPIO_DEMUX_DP_HDMI_PD_N, 1, 10 }, + { GPIO_DEMUX_DUAL_DP_MODE, 1, 10 }, + { GPIO_DEMUX_DP_HDMI_MODE, 1, 1 }, }; const size_t board_power_seq_count = ARRAY_SIZE(board_power_seq); +/* + * Define the strings used in our USB descriptors. + */ +const void *const usb_strings[] = { + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Gingerbread"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = + USB_STRING_DESC(CROS_EC_SECTION ":" CROS_EC_VERSION32), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), +}; +BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); + +#ifndef SECTION_IS_RW +/* USB-C PPC Configuration */ +struct ppc_config_t ppc_chips[] = { + [USB_PD_PORT_HOST] = { + .i2c_port = I2C_PORT_I2C3, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + }, +}; +#endif + +#ifdef SECTION_IS_RW + +/* TUSB1064 set mux board tuning for DP Rx path */ +static int board_tusb1064_dp_rx_eq_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) + rv = tusb1064_set_dp_rx_eq(me, TUSB1064_DP_EQ_RX_8_9_DB); + + return rv; +} + +/* + * TCPCs: 2 USBC/PD ports + * port 0 -> host port -> STM32G4 UCPD + * port 1 -> user data/display port -> PS8805 + */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &stm32gx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_I2C3, + .addr_flags = PS8XXX_I2C_ADDR2_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_HOST, + .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = TUSB1064_I2C_ADDR0_FLAGS, + .driver = &tusb1064_usb_mux_driver, + .board_set = &board_tusb1064_dp_rx_eq_set, + }, + }, + [USB_PD_PORT_DP] = { + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_DP, + .i2c_port = I2C_PORT_I2C3, + .i2c_addr_flags = PS8XXX_I2C_ADDR2_FLAGS, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, +}; + +/* USB-C PPC Configuration */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { .i2c_port = I2C_PORT_I2C3, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + [USB_PD_PORT_DP] = { .drv = &board_ppc_null_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +const struct hpd_to_pd_config_t hpd_config = { + .port = USB_PD_PORT_HOST, + .signal = GPIO_DDI_MST_IN_HPD, +}; + +void board_reset_pd_mcu(void) +{ + cprints(CC_SYSTEM, "Resetting TCPCs..."); + cflush(); + /* + * Reset all TCPCs. + * C0 -> ucpd (on chip TCPC) + * C1 -> PS8805 TCPC -> USBC_DP_PD_RST_L + * C2 -> PS8803 TCPC -> USBC_UF_RESET_L + */ + gpio_set_level(GPIO_USBC_DP_PD_RST_L, 0); + gpio_set_level(GPIO_USBC_UF_RESET_L, 0); + msleep(PS8805_FW_INIT_DELAY_MS); + gpio_set_level(GPIO_USBC_DP_PD_RST_L, 1); + gpio_set_level(GPIO_USBC_UF_RESET_L, 1); + msleep(PS8805_FW_INIT_DELAY_MS); +} + +/* Power Delivery and charging functions */ +void board_enable_usbc_interrupts(void) +{ + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_HOST_USBC_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USBC_DP_MUX_ALERT_ODL); + + /* Enable HPD interrupt */ + gpio_enable_interrupt(GPIO_DDI_MST_IN_HPD); +} + +/* Power Delivery and charging functions */ +void board_disable_usbc_interrupts(void) +{ + /* Disable PPC interrupts. */ + gpio_disable_interrupt(GPIO_HOST_USBC_PPC_INT_ODL); + + /* Disable TCPC interrupts. */ + gpio_disable_interrupt(GPIO_USBC_DP_MUX_ALERT_ODL); + + /* Disable HPD interrupt */ + gpio_disable_interrupt(GPIO_DDI_MST_IN_HPD); +} + +void board_tcpc_init(void) +{ + board_reset_pd_mcu(); + + /* Enable board usbc interrupts */ + board_enable_usbc_interrupts(); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 2); + +enum pd_dual_role_states board_tc_get_initial_drp_mode(int port) +{ + return pd_dual_role_init[port]; +} + +int ppc_get_alert_status(int port) +{ + if (port == USB_PD_PORT_HOST) + return gpio_get_level(GPIO_HOST_USBC_PPC_INT_ODL) == 0; + + return 0; +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USBC_DP_MUX_ALERT_ODL) && + gpio_get_level(GPIO_USBC_DP_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO: b/ - check correct operation for honeybuns */ +} + +int dock_get_mf_preference(void) +{ + int rv; + uint32_t fw_config; + int mf = MF_OFF; + + /* + * MF (multi function) preferece is indicated by bit 0 of the fw_config + * data field. If this data field does not exist, then default to 4 lane + * mode. + */ + rv = cbi_get_fw_config(&fw_config); + if (!rv) + mf = CBI_FW_MF_PREFERENCE(fw_config); + + return mf; +} + +static void board_usb_tc_connect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* + * The EC needs to keep the USB hubs in reset until the host port is + * attached so that the USB-EP can be properly enumerated. + */ + if (port == USB_PD_PORT_HOST) { + gpio_set_level(GPIO_EC_HUB1_RESET_L, 1); + gpio_set_level(GPIO_EC_HUB2_RESET_L, 1); + } +} +DECLARE_HOOK(HOOK_USB_PD_CONNECT, board_usb_tc_connect, HOOK_PRIO_DEFAULT); + +static void board_usb_tc_disconnect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* Only the host port disconnect is relevant */ + if (port == USB_PD_PORT_HOST) { + gpio_set_level(GPIO_EC_HUB1_RESET_L, 0); + gpio_set_level(GPIO_EC_HUB2_RESET_L, 0); + } +} +DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, board_usb_tc_disconnect, + HOOK_PRIO_DEFAULT); + +#endif /* SECTION_IS_RW */ + static void board_init(void) { - /* TODO */ +#ifdef SECTION_IS_RW + /* + * Set current limit for USB 3.1 Gen 2 ports to 1.5 A. Note, this is + * also done in gpio.inc, but needs to be in RW for platforms which + * shipped with RO that set these 2 lines to the 900 mA level. + */ + gpio_set_level(GPIO_USB3_P3_CDP_EN, 1); + gpio_set_level(GPIO_USB3_P4_CDP_EN, 1); +#endif } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_debug_gpio_1_pulse(void) +{ + gpio_set_level(GPIO_TRIGGER_1, 0); +} +DECLARE_DEFERRED(board_debug_gpio_1_pulse); + +static void board_debug_gpio_2_pulse(void) +{ + gpio_set_level(GPIO_TRIGGER_2, 0); +} +DECLARE_DEFERRED(board_debug_gpio_2_pulse); + +void board_debug_gpio(enum debug_gpio trigger, int level, int pulse_usec) +{ + switch (trigger) { + case TRIGGER_1: + gpio_set_level(GPIO_TRIGGER_1, level); + if (pulse_usec) + hook_call_deferred(&board_debug_gpio_1_pulse_data, + pulse_usec); + break; + case TRIGGER_2: + gpio_set_level(GPIO_TRIGGER_2, level); + if (pulse_usec) + hook_call_deferred(&board_debug_gpio_2_pulse_data, + pulse_usec); + break; + default: + CPRINTS("bad debug gpio selection"); + break; + } +} diff --git a/board/gingerbread/board.h b/board/gingerbread/board.h index c3052f3f59..09e9e0b7fe 100644 --- a/board/gingerbread/board.h +++ b/board/gingerbread/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,24 +12,44 @@ #include "baseboard.h" /* Optional features */ +/* + * For MP release, CONFIG_SYSTEM_UNLOCKED must be undefined, and + * CONFIG_FLASH_PSTATE_LOCKED must be defined in order to enable write protect + * using option bytes WRP registers. + */ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ +#undef CONFIG_FLASH_PSTATE_LOCKED -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 4096 - -/* Keyboard features */ +#define CONFIG_WP_ACTIVE_HIGH -/* Sensors */ +/* Console */ +#define CONFIG_UART_CONSOLE 3 +#define CONFIG_UART_TX_DMA_CH STM32_DMAC_USART3_TX +#define CONFIG_UART_TX_DMA_PH DMAMUX_REQ_USART3_TX /* USB Type C and USB PD defines */ - -/* USB Type A Features */ - -/* BC 1.2 */ - -/* Volume Button feature */ - -/* Fan features */ +#define USB_PD_PORT_HOST 0 +#define USB_PD_PORT_DP 1 + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_MUX_TUSB1064 +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define BOARD_C1_NO_PPC +#define BOARD_C1_1A5_LIMIT + +#define CONFIG_USB_PID 0x5049 +#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ +#define CONFIG_USB_PD_IDENTITY_HW_VERS 1 +#define CONFIG_USB_PD_IDENTITY_SW_VERS 1 + +/* I2C port names */ +#define I2C_PORT_I2C1 0 +#define I2C_PORT_I2C2 1 +#define I2C_PORT_I2C3 2 +/* Required symbolic I2C port names */ +#define I2C_PORT_MP4245 I2C_PORT_I2C3 +#define I2C_PORT_EEPROM I2C_PORT_I2C1 +#define MP4245_I2C_ADDR_FLAGS MP4245_I2C_ADDR_0_FLAGS /* * Macros for GPIO signals used in common code that don't match the @@ -37,16 +57,52 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_WP_L GPIO_EC_WP_L - +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_WP GPIO_EC_WP_L +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL #ifndef __ASSEMBLER__ -#include "gpio_signal.h" #include "registers.h" +#define GPIO_DP_HPD GPIO_DDI_MST_IN_HPD +#define GPIO_BPWR_DET GPIO_TP71 +#define GPIO_PWR_BUTTON_RED GPIO_EC_STATUS_LED1 +#define GPIO_PWR_BUTTON_GREEN GPIO_EC_STATUS_LED2 + +#define BUTTON_PRESSED_LEVEL 0 +#define BUTTON_RELEASED_LEVEL 1 + +#define GPIO_TRIGGER_1 GPIO_USB3_A1_CDP_EN +#define GPIO_TRIGGER_2 GPIO_USB3_A2_CDP_EN + +enum debug_gpio { + TRIGGER_1 = 0, + TRIGGER_2, +}; + +/* + * Function used to control GPIO signals as a timing marker. This is intended to + * be used for development/debugging purposes. + * + * @param trigger GPIO debug signal selection + * @param level desired level of the debug gpio signal + * @param pulse_usec pulse width if non-zero + */ +void board_debug_gpio(enum debug_gpio trigger, int level, int pulse_usec); + +/* + * Function called in power on case to enable usbc related interrupts + */ +void board_enable_usbc_interrupts(void); + +/* + * Function called in power off case to disable usbc related interrupts + */ +void board_disable_usbc_interrupts(void); #endif /* !__ASSEMBLER__ */ diff --git a/board/gingerbread/build.mk b/board/gingerbread/build.mk index bd3691f95a..d7ca7b35b5 100644 --- a/board/gingerbread/build.mk +++ b/board/gingerbread/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -12,7 +12,7 @@ CHIP:=stm32 # codebase. Currently, using a variant of the F family so the project will # build properly. CHIP_FAMILY:=stm32g4 -CHIP_VARIANT:=stm32g431xb +CHIP_VARIANT:=stm32g473xc BASEBOARD:=honeybuns board-y=board.o diff --git a/board/gingerbread/dev_key.pem b/board/gingerbread/dev_key.pem new file mode 100644 index 0000000000..7b1df5d805 --- /dev/null +++ b/board/gingerbread/dev_key.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5AIBAAKCAYEA2hyGIDxIS/jWNh3Nhg7V4/5Ce8KT4CIb1XaLd0mR2gWCkYdZ +iRWSjAjMsMCLSLM0gUDnFU5xJgbUdg1GeafXdPlRQojG2ztZ/z+JBNgQvsWtdJhR +m9dMm1cbq3rajU5NoVu1hiLIWpayYo91w1qMnf3LRFAgrVDvEUt8elCpTB60uZiS +QL3PSCJhZiGyK2QGix+vNKxri+GnM+SxXggi3IrLMI2gqpCTiTZl4t8Ecnsn4QMC +OvgRzDj2TnYJhhAdFeg7SuQ9TKCXAyw0LAR9AcuQ8tbf3ox04umLdbAj518ScXZB +ef2xrnXIBkXcA5UXZ2J6+YP7tvm6XCEnwdhEq5gi65Mjc1i8vihzABXbXrKhFdKt +ACLdQ8V6eM2nTK4NwNIeHdF0KRBvln5APxapNfjQh9Fz67ytvxt7TaBQWOheWB1V +8NL7AzfcEPUH5blCjdWNfLcUXNqZa6+Jxk5Zug5dPazo1y1R5XoLFKpZ76c33fPr +ngV8jwkTNaXVU84jAgEDAoIBgQCRaFlq0trdUI7OvokECePtVCxSgbfqwWfjpFz6 +MQvmrlcLr5EGDmGysIh11bIwd3hWK0S43vYZWeL5Xi77xTpN+4uBsISSJ5FU1QYD +OrXUg8j4ZYu9OjMSOhJyUecI3t5rknkEFzA8ZHbsX6PXkbMT/oeC4BXI4J9g3P2m +4HDdac3REGGAfoowFuuZa8wc7VmyFR94cvJdQRoimHY+sBc9sdzLCRXHCw0GJEPs +lK2hp2/rV1bR+raIJfmJpAZZYBIn4W8yHD2LX6/ofgnTIxw9jAL1eheBviKwpYw8 +QOr46FlX3SZs8cupHbCf+DiPbcwZce3viPPMXSF+XW4wmiXgQeJnAh7sStcu4WjF +TWxppqto6mr/5D5uI+NWjm13puJVL6OsPkJrhEZ1gSW6u3pPxAotkj4sppIg2qUJ +pmxohz4D8gChOyedxtg1DRBqMY9VDnfRN5DMuPiF9t77KkOuHfZI3tUwWIeZeRKV +tJEldJjnTBZfqZirjznlIBq1oasCgcEA/9RLDoX70KACdkki4o8MOrqHvmU3fgtZ +MWIxrbjFoR9JhjFIZm41Ak8/sMhbs0dOskS4FmNaeKgkhsalZR997HvZXDxAsB7X +tWkYcqKI1XaB48rIB5g5rxFmnxh/vVrchlUh80YQS/jvetD+fmjzXHeyrC2OCAgR +2cfrl0ZwbXDbvoWoUcAl9C8YuUWUYurJsyqnwNLg6uiGB5anjBITNVGOXYD8hdcv +2RoOOSnuGwTHRtytphO1WJiUqn9yOV5jAoHBANpByXEz5SrxDLAmAozAxmq/BMQ6 +hR3j56iPB22V/dDjQud5P3Akyy55/2WJK3kpFo7y3fvTM4vF45fOXRPRje65dfTT +tGDJokJtPWV/L+rCHhSoRHi0Re9+Ptffg1vY3bq1hqguADvRFmtriSiUfmHbDpdI +iKC6wLQLmCfgPU6spZOsrK06GaJefwgb2uOEIdsVMgIQ2j7cnpsmk8F84P+P3XLd +rIjRVqYqYPrxkhxzizwlHGhzYjUZp7N2Own9QQKBwQCqjYdfA/01wAGkMMHsX118 +fFp+7iT+sjt2QXZz0IPAv4ZZdjBESXisNNUghZJ3hN8hgyVkQjxQcBhZ2cOYv6lI +UpDoKCsgFI/ORhBMbFs4+avtMdqvutEfYO8Uuv/TkehZjhaiLrWH+0pR4Kmpm0zo +T8xyyQlasAvmhUe6LvWeSz0prnA2gBlNdLsmLmLsnIZ3ccUrN0CcmwQFDxpdYWIj +i7Q+Vf2uj3U7ZrQmG/QSAy+Ekx5ut847EGMcVPbQ6ZcCgcEAkYEw9iKYx0tdysQB +sysu8dSt2CcDaUKacF9aSQ6pNezXRPt/oBiHdFFU7ltyUMYPCfc+p+IiXS6XuomT +Youz9Huj+I0i6zEW1vN+Q6of8da+uHAtpc2D9P7Uj+pXkpCT0c5ZxXQAJ+C5nPJb +cGL+6+dfD4WwaycrIrJlb+rTichuYnMdyNFmbD7/Wr08l61r52N2rAs8KehpvMRi +gP3rVQqToekdsIuPGXGV/KEMEveyKBi9mveWzhEad6QnW/4rAoHBAM1TgJVVYCKl +tmUf8XcC8+bNQ+dlqPdBQa3cAPFlQdRZUzDIYU+ZHa66GWUWb2uuD2hFCDDEpC1l +Ke34tNROiruDfj9lfD6UmJv8vw/wPG3m52Qb5iWdA+B1512MK8p7KZg9YQJot/Yj +B2rNxv1O+IjWPxxtUEVsFpx/XGoEemc85iS+icjNXvtOwyEGdNliRFiQtVkh2mtX +7uKbkUAL2HKzxfnJ/LbWZwDlW45x/qDQtncp93sTcM3k8FVE+MtLbw== +-----END RSA PRIVATE KEY----- diff --git a/board/gingerbread/ec.tasklist b/board/gingerbread/ec.tasklist index c272906fc7..ffd4a604c9 100644 --- a/board/gingerbread/ec.tasklist +++ b/board/gingerbread/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,5 +8,11 @@ */ #define CONFIG_TASK_LIST \ + TASK_ALWAYS_RO(RWSIG, rwsig_task, NULL, 1280) \ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(POWER_BUTTON, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PD_INT_C1, pd_interrupt_handler_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(UCPD, ucpd_task, 0, LARGER_TASK_STACK_SIZE) diff --git a/board/gingerbread/gpio.inc b/board/gingerbread/gpio.inc index 052124289c..4da3c973c1 100644 --- a/board/gingerbread/gpio.inc +++ b/board/gingerbread/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,8 +8,14 @@ /* Declare symbolic names for all the GPIOs that we care about. * Note: Those with interrupt handlers must be declared first. */ -/* Power sequencing interrupts */ -GPIO(PWR_BTN, PIN(A, 0), GPIO_INPUT) +#ifdef SECTION_IS_RW +GPIO_INT(HOST_USBC_PPC_INT_ODL, PIN(C, 1), GPIO_INT_FALLING | GPIO_PULL_UP, ppc_interrupt) +GPIO_INT(USBC_DP_MUX_ALERT_ODL, PIN(C, 12), GPIO_INT_FALLING | GPIO_PULL_UP, tcpc_alert_event) +GPIO_INT(DDI_MST_IN_HPD, PIN(C, 14), GPIO_INT_BOTH, hpd_interrupt) +GPIO_INT(PWR_BTN, PIN(A, 0), GPIO_INT_BOTH, board_pwr_btn_interrupt) +#endif + +/* Power sequencing signals */ GPIO(EN_AC_JACK, PIN(A, 1), GPIO_OUT_LOW) GPIO(EN_BB, PIN(C, 0), GPIO_OUT_LOW) GPIO(EN_PP3300_A, PIN(C, 10), GPIO_OUT_LOW) @@ -19,12 +25,13 @@ GPIO(EN_PP1100_A, PIN(C, 4), GPIO_OUT_LOW) GPIO(EN_PP1000_A, PIN(C, 5), GPIO_OUT_LOW) GPIO(EN_PP1050_A, PIN(C, 6), GPIO_OUT_LOW) GPIO(EN_PP5000_HSPORT, PIN(C, 7), GPIO_OUT_LOW) -GPIO(STATUS_LED1, PIN(A, 2), GPIO_OUT_HIGH) -GPIO(STATUS_LED2, PIN(B, 12), GPIO_OUT_HIGH) +GPIO(EC_STATUS_LED1, PIN(A, 2), GPIO_OUT_HIGH) +GPIO(EC_STATUS_LED2, PIN(B, 12), GPIO_OUT_HIGH) /* MST Hub signals */ -GPIO(MST_LP_CTL_L, PIN(B, 9), GPIO_ODR_LOW) +GPIO(MST_LP_CTL_L, PIN(B, 9), GPIO_OUT_LOW) GPIO(MST_RST_L, PIN(B, 3), GPIO_ODR_LOW) +GPIO(MST_HUB_LANE_SWITCH, PIN(C, 15), GPIO_OUT_HIGH) /* Display Demux signals */ GPIO(DEMUX_DUAL_DP_MODE, PIN(D, 8), GPIO_OUT_LOW) @@ -43,7 +50,30 @@ GPIO(USBC_UF_RESET_L, PIN(C, 11), GPIO_ODR_LOW) GPIO(EC_HUB1_RESET_L, PIN(E, 13), GPIO_ODR_LOW) GPIO(EC_HUB2_RESET_L, PIN(E, 14), GPIO_ODR_LOW) -/* Misc Signals */ +/* DEBUG signals */ +GPIO(DEBUG_GPIO1, PIN(B, 13), GPIO_OUT_LOW) + +/* Configure as output to enable @1.5A on USBA Ports +* USB CDP enables. */ +GPIO(USB3_A1_CDP_EN, PIN(E, 7), GPIO_OUT_LOW) +GPIO(USB3_A2_CDP_EN, PIN(E, 8), GPIO_OUT_LOW) +GPIO(USB3_P3_CDP_EN, PIN(D, 1), GPIO_OUT_HIGH) +GPIO(USB3_P4_CDP_EN, PIN(E, 12), GPIO_OUT_HIGH) + +/* Write protect */ +GPIO(EC_FLASH_WP_ODL, PIN(A, 3), GPIO_ODR_HIGH) +GPIO(EC_WP_L, PIN(E, 11), GPIO_INT_BOTH) + + +/* SPI Bus */ +GPIO(FLASH_SPI1_NSS, PIN(A, 4), GPIO_INT_FALLING) +GPIO(FLASH_SPI1_SCK, PIN(A, 5), GPIO_INT_BOTH) +GPIO(FLASH_SPI1_MISO, PIN(A, 6), GPIO_INT_BOTH) +GPIO(FLASH_SPI1_MOSI, PIN(A, 7), GPIO_INT_BOTH) + +/* misc signals */ +GPIO(EC_DFU_MUX_CTRL, PIN(A, 8), GPIO_OUT_HIGH) +GPIO(TP71, PIN(B, 0), GPIO_OUT_LOW) /* * I2C SCL/SDA pins. These will normally be under control of the peripheral from @@ -52,16 +82,13 @@ GPIO(EC_HUB2_RESET_L, PIN(E, 14), GPIO_ODR_LOW) */ GPIO(EC_I2C1_SCL, PIN(A, 15), GPIO_ODR_HIGH) GPIO(EC_I2C1_SDA, PIN(B, 7), GPIO_ODR_HIGH) -GPIO(EC_I2C2_SDA, PIN(A, 8), GPIO_ODR_HIGH) -GPIO(EC_I2C2_SCL, PIN(A, 9), GPIO_ODR_HIGH) GPIO(EC_I2C3_SCL, PIN(C, 8), GPIO_ODR_HIGH) GPIO(EC_I2C3_SDA, PIN(C, 9), GPIO_ODR_HIGH) UNIMPLEMENTED(EC_ENTERING_RW) -UNIMPLEMENTED(EC_WP_L) - -/* UART */ +ALTERNATE(PIN_MASK(B, 0x0C00), GPIO_ALT_USART, MODULE_UART, GPIO_PULL_UP) /* GPIOB 10-11:USART3_TX/RX */ +ALTERNATE(PIN_MASK(A, 0x00F0), 5, MODULE_SPI, 0) /* GPIOA4-7: SPI Signals */ /* I2C Ports * I2C1: SDA/SCL -> PB7/PA15 * I2C2: SDA/SCL -> PA8/PA9 @@ -69,5 +96,4 @@ UNIMPLEMENTED(EC_WP_L) */ ALTERNATE(PIN_MASK(B, 0x0080), 4, MODULE_I2C, GPIO_OPEN_DRAIN) ALTERNATE(PIN_MASK(A, 0X8000), 4, MODULE_I2C, GPIO_OPEN_DRAIN) -ALTERNATE(PIN_MASK(A, 0x0300), 4, MODULE_I2C, GPIO_OPEN_DRAIN) ALTERNATE(PIN_MASK(C, 0x0300), 8, MODULE_I2C, GPIO_OPEN_DRAIN) diff --git a/board/gladios/board.c b/board/gladios/board.c new file mode 100644 index 0000000000..898d85a9d0 --- /dev/null +++ b/board/gladios/board.c @@ -0,0 +1,534 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "builtin/assert.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/cec/bitbang.h" +#include "driver/tcpm/tcpci.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power_s5; +static int32_t base_5v_power_z1; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ + +/* PP5000_S5 loads */ +#define PWR_S5_BASE_LOAD (5 * 1431) +#define PWR_S5_FRONT_HIGH (5 * 1737) +#define PWR_S5_FRONT_LOW (5 * 1055) +#define PWR_S5_REAR_HIGH (5 * 1737) +#define PWR_S5_REAR_LOW (5 * 1055) +#define PWR_S5_HDMI (5 * 580) +#define PWR_S5_MAX (5 * 10000) +#define FRONT_DELTA (PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW) +#define REAR_DELTA (PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW) + +/* PP5000_Z1 loads */ +#define PWR_Z1_BASE_LOAD (5 * 5) +#define PWR_Z1_C_HIGH (5 * 3600) +#define PWR_Z1_C_LOW (5 * 2000) +#define PWR_Z1_MAX (5 * 9000) +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int front_ports = 0; + int rear_ports = 0; + + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power_s5 = PWR_S5_BASE_LOAD; + if (!gpio_get_level(GPIO_USB_A0_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + /* + * Only 1 front port can run higher power at a time. + */ + if (front_ports > 0) + base_5v_power_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + + if (!gpio_get_level(GPIO_USB_A2_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + if (!gpio_get_level(GPIO_USB_A3_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + /* + * Only 1 rear port can run higher power at a time. + */ + if (rear_ports > 0) + base_5v_power_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + if (!gpio_get_level(GPIO_HDMIA_CONN_OC_ODL)) + base_5v_power_s5 += PWR_S5_HDMI; + if (!gpio_get_level(GPIO_HDMIB_CONN_OC_ODL)) + base_5v_power_s5 += PWR_S5_HDMI; + base_5v_power_z1 = PWR_Z1_BASE_LOAD; + if (usbc_overcurrent) + base_5v_power_z1 += PWR_Z1_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) + ec_bj_power(&pi.voltage, &pi.current); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +static void adp_state_init(void) +{ + ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT); + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +static void board_init(void) +{ + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + gpio_enable_interrupt(GPIO_HDMIA_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_HDMIB_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A2_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A3_OC_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Check that port number is valid. */ + if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) + return; + usbc_overcurrent = is_overcurrented; + update_5v_usage(); +} +/* + * Power monitoring and management. + * + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * The overall goal is to gracefully manage the power demand so that + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type A BC1.2 rear port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 3 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A_FRONT BIT(0) +#define THROT_TYPE_A_REAR BIT(1) +#define THROT_TYPE_C0 BIT(2) +#define THROT_PROCHOT BIT(5) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + static uint32_t history[POWER_READINGS]; + static uint8_t index; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v_s5 = PWR_S5_MAX - base_5v_power_s5; + int32_t headroom_5v_z1 = PWR_Z1_MAX - base_5v_power_z1; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + /* + * Clear the first entry of the power table so that + * it is re-initilalised when the CPU starts. + */ + history[0] = 0; + } else { + int32_t charger_mw; + + delay = POWER_DELAY_MS * MSEC; + /* + * Get current charger limit (in mw). + * If not configured yet, skip. + */ + charger_mw = charge_manager_get_power_limit_uw() / 1000; + if (charger_mw != 0) { + int32_t gap, total, max, power; + int i; + + /* + * Read power usage. + */ + power = (adc_read_channel(ADC_VBUS) * + adc_read_channel(ADC_PPVAR_IMON)) / + 1000; + /* Init power table */ + if (history[0] == 0) { + for (i = 0; i < POWER_READINGS; i++) + history[i] = power; + } + /* + * Update the power readings and + * calculate the average and max. + */ + history[index] = power; + index = (index + 1) % POWER_READINGS; + total = 0; + max = history[0]; + for (i = 0; i < POWER_READINGS; i++) { + total += history[i]; + if (history[i] > max) + max = history[i]; + } + /* + * For Type-C power supplies, there is + * less tolerance for exceeding the rating, + * so use the max power that has been measured + * over the measuring period. + * For barrel-jack supplies, the rating can be + * exceeded briefly, so use the average. + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + power = max; + else + power = total / POWER_READINGS; + /* + * Calculate gap, and if negative, power + * demand is exceeding configured power budget, so + * throttling is required to reduce the demand. + */ + gap = charger_mw - power; + /* + * Limiting type-A power rear ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_REAR; + headroom_5v_s5 += REAR_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * Limiting type-A power front ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_FRONT; + headroom_5v_s5 += FRONT_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(0) && gap <= 0) { + new_state |= THROT_TYPE_C0; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C0)) + gap += POWER_GAIN_TYPE_C; + } + /* + * As a last resort, turn on PROCHOT to + * throttle the CPU. + */ + if (gap <= 0) + new_state |= THROT_PROCHOT; + } + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v_z1 < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C0) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + new_state |= THROT_TYPE_C0; + } + /* + * [2] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v_z1 < 0) + new_state |= THROT_TYPE_C0; + } + if (headroom_5v_s5 < 0) { + /* + * [1] If type A rear not already throttled, and power still + * needed, limit type A rear. + */ + if (!(new_state & THROT_TYPE_A_REAR) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + new_state |= THROT_TYPE_A_REAR; + } + /* + * [2] If type A front not already throttled, and power still + * needed, limit type A front. + */ + if (!(new_state & THROT_TYPE_A_FRONT) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + new_state |= THROT_TYPE_A_FRONT; + } + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_C0) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C0) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + } + if (diff & THROT_TYPE_A_REAR) { + int typea_bc = (new_state & THROT_TYPE_A_REAR) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR0_OD, typea_bc); + gpio_set_level(GPIO_USB_A_LOW_PWR1_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/gladios/board.h b/board/gladios/board.h new file mode 100644 index 0000000000..fd2db92a46 --- /dev/null +++ b/board/gladios/board.h @@ -0,0 +1,163 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Gladios board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* Barrel Jack */ +#define DEDICATED_CHARGE_PORT 1 + +/* HDMI CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMIB_CEC_OUT +#define CEC_GPIO_IN GPIO_HDMIB_CEC_IN +#define CEC_GPIO_PULL_UP GPIO_HDMIB_CEC_PULL_UP + +/* USB Type A Features */ +#define USB_PORT_COUNT 4 +#define CONFIG_USB_PORT_POWER_DUMB +#define CONFIG_USBC_RETIMER_PS8811 + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_PPC +#define CONFIG_USB_PD_TCPM_RT1715 +#define CONFIG_USBC_RETIMER_PS8818 +#define CONFIG_USBC_PPC_SYV682X +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* The design should support up to 100W. */ +/* TODO(b/197702356): Set the max PD to 60W now and change it + * to 100W after we verify it. + */ +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_OD + +/* I2C Bus Configuration */ +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 + +#define I2C_PORT_USB_C0_PPC_BC12 NPCX_I2C_PORT2_0 + +#define I2C_PORT_USB_C0_MUX NPCX_I2C_PORT3_0 + +#define I2C_PORT_USB_A2_A3_RT NPCX_I2C_PORT6_1 + +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* ADC */ +#define CONFIG_ADC + +/* + * TODO(b/197478860): Enable the fan control. We need + * to check the sensor value and adjust the fan speed. + */ +#define CONFIG_FANS FAN_CH_COUNT + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_BARRELJACK, + CHARGE_PORT_ENUM_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1_CPU, + ADC_TEMP_SENSOR_2_CPU_VR, + ADC_TEMP_SENSOR_3_WIFI, + ADC_TEMP_SENSOR_4_DIMM, + ADC_VBUS, + ADC_PPVAR_IMON, /* ADC3 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_CPU, + TEMP_SENSOR_2_CPU_VR, + TEMP_SENSOR_3_WIFI, + TEMP_SENSOR_4_DIMM, + TEMP_SENSOR_COUNT +}; + +enum pwm_channel { + PWM_CH_LED_GREEN, /* PWM0 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED_RED, /* PWM2 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +extern void adp_connect_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/gladios/build.mk b/board/gladios/build.mk new file mode 100644 index 0000000000..637cdc2c22 --- /dev/null +++ b/board/gladios/build.mk @@ -0,0 +1,22 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Gladios board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brask + +board-y= +board-y+=board.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/gladios/ec.tasklist b/board/gladios/ec.tasklist new file mode 100644 index 0000000000..072252f0cd --- /dev/null +++ b/board/gladios/ec.tasklist @@ -0,0 +1,23 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/gladios/fans.c b/board/gladios/fans.c new file mode 100644 index 0000000000..02172cd3e1 --- /dev/null +++ b/board/gladios/fans.c @@ -0,0 +1,48 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * Fan spins at about 4100 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2000, + .rpm_start = 2000, + .rpm_max = 4700, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/gladios/fw_config.c b/board/gladios/fw_config.c new file mode 100644 index 0000000000..ed2b8b32ce --- /dev/null +++ b/board/gladios/fw_config.c @@ -0,0 +1,66 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union gladios_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for gladios if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union gladios_cbi_fw_config fw_config_defaults = { + .bj_power = BJ_65W, + .storage = EMMC, + .fvm_support = FVM_NO, +}; + +/* + * Barrel-jack power adapter ratings. + */ +static const struct { + int voltage; + int current; +} bj_power[] = { + [BJ_65W] = { /* 0 - 65W (also default) */ + .voltage = 19000, + .current = 3420 + }, + [BJ_90W] = { /* 1 - 90W */ + .voltage = 19000, + .current = 4740 + } +}; + +/**************************************************************************** + * Gladios FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +void ec_bj_power(uint32_t *voltage, uint32_t *current) +{ + unsigned int bj; + + bj = fw_config.bj_power; + /* Out of range value defaults to 0 */ + if (bj >= ARRAY_SIZE(bj_power)) + bj = 0; + *voltage = bj_power[bj].voltage; + *current = bj_power[bj].current; +} diff --git a/board/gladios/fw_config.h b/board/gladios/fw_config.h new file mode 100644 index 0000000000..ba0bd65047 --- /dev/null +++ b/board/gladios/fw_config.h @@ -0,0 +1,44 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_GLADIOS_FW_CONFIG_H_ +#define __BOARD_GLADIOS_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Gladios board. + * + * Source of truth is the project/brask/gladios/config.star configuration file. + */ +enum ec_cfg_bj_power { BJ_65W = 0, BJ_90W = 1 }; + +enum ec_cfg_storage { EMMC = 0, SSD = 1 }; + +enum ec_cfg_fvm_support { FVM_NO = 0, FVM_YES = 1 }; + +union gladios_cbi_fw_config { + struct { + uint32_t bj_power : 1; + uint32_t storage : 1; + uint32_t fvm_support : 1; + uint32_t reserved_1 : 29; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union gladios_cbi_fw_config get_fw_config(void); + +/** + * Get the barrel-jack power from FW_CONFIG. + */ +void ec_bj_power(uint32_t *voltage, uint32_t *current); + +#endif /* __BOARD_GLADIOS_FW_CONFIG_H_ */ diff --git a/board/gladios/gpio.inc b/board/gladios/gpio.inc new file mode 100644 index 0000000000..958b36c619 --- /dev/null +++ b/board/gladios/gpio.inc @@ -0,0 +1,162 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTERRUPT GPIOs: */ + +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(2, 3), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(HDMIA_CONN_OC_ODL, PIN(5, 0), GPIO_INPUT | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(HDMIB_CONN_OC_ODL, PIN(2, 4), GPIO_INPUT | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A0_OC_ODL, PIN(3, 1), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A2_OC_ODL, PIN(2, 7), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A3_OC_ODL, PIN(2, 6), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) + +/* CCD */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + +/* Security */ +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Fan */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) + +/* ADC, need to check the usage */ +GPIO(ANALOG_PPVAR_PWR_IN_IMON_EC, PIN(4, 2), GPIO_INPUT) + +/* BarrelJack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 7), GPIO_OUT_LOW) + +/* Chipset PCH */ +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) + +/* Button */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(GSC_EC_RECOVERY_BTN_OD, PIN(2, 2), GPIO_INPUT) + +/* HDMI CEC */ +/* TODO(b/197474873): Enable HDMI CEC */ +GPIO(HDMIB_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMIB_CEC_OUT, PIN(D, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMIB_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH) +GPIO(HDMIA_CEC_IN, PIN(A, 7), GPIO_INPUT) +GPIO(HDMIA_CEC_OUT, PIN(F, 2), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMIA_CEC_PULL_UP, PIN(F, 3), GPIO_OUT_HIGH) + +/* I2C SCL/SDA */ +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_A2_A3_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_A2_A3_SDA, PIN(E, 3), GPIO_INPUT) + +/* USBA */ +GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW) +GPIO(USB_A0_STATUS_L, PIN(2, 1), GPIO_INPUT) +GPIO(USB_A1_STATUS_L, PIN(2, 0), GPIO_INPUT) +GPIO(USB_A_LOW_PWR0_OD, PIN(1, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR1_OD, PIN(1, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH) + +/* LED */ +/* TODO(b/197471359): LED implementation */ +GPIO(LED_GREEN_L, PIN(C, 3), GPIO_OUT_LOW) +GPIO(LED_RED_L, PIN(C, 4), GPIO_OUT_LOW) + +/* USBC */ +GPIO(USB_C0_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C0_HPD, PIN(0, 4), GPIO_OUT_LOW) +GPIO(USB_C0_OC_ODL, PIN(7, 0), GPIO_OUT_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIO02_NC, PIN(0, 2), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */ +UNUSED(PIN(9, 7)) /* GPIO97 */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */ +UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */ +UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */ +UNUSED(PIN(0, 6)) /* KSO11/GPIO06/P80_CLK */ +UNUSED(PIN(A, 0)) +UNUSED(PIN(A, 2)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(B, 5)) +UNUSED(PIN(B, 4)) +UNUSED(PIN(D, 2)) +UNUSED(PIN(D, 4)) +UNUSED(PIN(F, 5)) +UNUSED(PIN(0, 5)) +UNUSED(PIN(1, 1)) +UNUSED(PIN(1, 0)) +UNUSED(PIN(1, 7)) +UNUSED(PIN(1, 6)) +UNUSED(PIN(2, 5)) +UNUSED(PIN(3, 3)) +UNUSED(PIN(3, 6)) +UNUSED(PIN(4, 1)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(9, 3)) +UNUSED(PIN(9, 5)) +UNUSED(PIN(9, 6)) diff --git a/board/gladios/i2c.c b/board/gladios/i2c.c new file mode 100644 index 0000000000..a58f75bfa7 --- /dev/null +++ b/board/gladios/i2c.c @@ -0,0 +1,53 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc, bc1.2 c0", + .port = I2C_PORT_USB_C0_PPC_BC12, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0", + .port = I2C_PORT_USB_C0_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA, + }, + { + /* I2C6 */ + .name = "usba2_retimer, usba3_retimer", + .port = I2C_PORT_USB_A2_A3_RT, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_A2_A3_SCL, + .sda = GPIO_EC_I2C_USB_A2_A3_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/gladios/led.c b/board/gladios/led.c new file mode 100644 index 0000000000..e6248774a6 --- /dev/null +++ b/board/gladios/led.c @@ -0,0 +1,266 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Gladios. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_GREEN, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int green = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_GREEN: + green = 1; + break; + case LED_RED: + red = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (green) + pwm_set_duty(PWM_CH_LED_GREEN, duty); + else + pwm_set_duty(PWM_CH_LED_GREEN, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (1500 * MSEC) +#define LED_OFF_TIME_US (1500 * MSEC) +/* 30 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (30 * MSEC) + +/* + * When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. Stay 0 for . + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + uint32_t off_time; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color), \ + (LED_OFF_TIME_US)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color, + uint32_t off_time) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.off_time = off_time; + led_pulse.duty = 0; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) { + set_color(EC_LED_ID_POWER_LED, led_pulse.color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) { + led_pulse.duty_inc = led_pulse.duty_inc * -1; + } else if (led_pulse.duty + led_pulse.duty_inc < 0) { + led_pulse.duty_inc = led_pulse.duty_inc * -1; + next = led_pulse.off_time; + } + led_pulse.duty += led_pulse.duty_inc; + } + + if (next == 0) + next = led_pulse.interval; + elapsed = get_time().le.lo - start; + next = next > elapsed ? next - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_GREEN); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* + * Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_GREEN, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED, 0); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "green")) { + set_color(id, LED_GREEN, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|red|green|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_GREEN] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_GREEN]) + return set_color(id, LED_GREEN, brightness[EC_LED_COLOR_GREEN]); + else + return set_color(id, LED_OFF, 0); +} +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Blink alert if insufficient power per system_can_boot_ap(). */ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + led_alert(insufficient_power); +} diff --git a/board/gladios/pwm.c b/board/gladios/pwm.c new file mode 100644 index 0000000000..db85952f41 --- /dev/null +++ b/board/gladios/pwm.c @@ -0,0 +1,33 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_GREEN] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN | PWM_CONFIG_DSLEEP, + .freq = 1000 }, + [PWM_CH_LED_RED] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + pwm_enable(PWM_CH_FAN, 1); + + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_GREEN, 1); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/gladios/sensors.c b/board/gladios/sensors.c new file mode 100644 index 0000000000..99bc0a4304 --- /dev/null +++ b/board/gladios/sensors.c @@ -0,0 +1,114 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_CPU] = { + .name = "TEMP_CPU", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CPU_VR] = { + .name = "TEMP_CPU_VR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_WIFI] = { + .name = "TEMP_WIFI", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DIMM] = { + .name = "TEMP_DIMM", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 872.3 mV/A */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT * 1433, + .factor_div = (ADC_READ_MAX + 1) * 1250, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_CPU] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_CPU }, + [TEMP_SENSOR_2_CPU_VR] = { .name = "CPU VR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CPU_VR }, + [TEMP_SENSOR_3_WIFI] = { .name = "WIFI", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_WIFI }, + [TEMP_SENSOR_4_DIMM] = { .name = "DIMM", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DIMM }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(80), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/197478860): add the thermal sensor setting + */ +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CPU] = THERMAL_CPU, + [TEMP_SENSOR_2_CPU_VR] = THERMAL_CPU, + [TEMP_SENSOR_3_WIFI] = THERMAL_CPU, + [TEMP_SENSOR_4_DIMM] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/gladios/usbc_config.c b/board/gladios/usbc_config.c new file mode 100644 index 0000000000..c010eb1333 --- /dev/null +++ b/board/gladios/usbc_config.c @@ -0,0 +1,162 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/ps8818_public.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC_BC12, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +static int board_c0_ps8818_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + if (mux_state & USB_PD_MUX_DP_ENABLED) + gpio_set_level(GPIO_USB_C0_HPD, 1); + else + gpio_set_level(GPIO_USB_C0_HPD, 0); + + return 0; +} + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &ps8818_usb_retimer_driver, + .i2c_port = I2C_PORT_USB_C0_MUX, + .i2c_addr_flags = PS8818_I2C_ADDR3_FLAGS, + .board_set = &board_c0_ps8818_mux_set, + }, + .next = &usbc0_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +void board_reset_pd_mcu(void) +{ + /* Using RT1716, no reset available for TCPC */ +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + schedule_deferred_pd_interrupt(USBC_PORT_C0); +} + +void bc12_interrupt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +void ppc_interrupt(enum gpio_signal signal) +{ + syv682x_interrupt(USBC_PORT_C0); +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} diff --git a/board/gladios/usbc_config.h b/board/gladios/usbc_config.h new file mode 100644 index 0000000000..4c3f7ee4d8 --- /dev/null +++ b/board/gladios/usbc_config.h @@ -0,0 +1,15 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Gladios board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/gladios/vif_override.xml b/board/gladios/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/gladios/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/glkrvp/battery.c b/board/glkrvp/battery.c deleted file mode 100644 index cccf3c1016..0000000000 --- a/board/glkrvp/battery.c +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery.h" -#include "charger_profile_override.h" -#include "console.h" -#include "pca9555.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -#define I2C_PORT_PCA555_BATT_PRESENT_GPIO NPCX_I2C_PORT0_0 -#define I2C_ADDR_PCA555_BATT_PRESENT_GPIO_FLAGS 0x21 -#define PCA555_BATT_PRESENT_GPIO_READ(reg, data) \ - pca9555_read(I2C_PORT_PCA555_BATT_PRESENT_GPIO, \ - I2C_ADDR_PCA555_BATT_PRESENT_GPIO_FLAGS, (reg), (data)) - -/* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHUTDOWN_DATA 0x0010 - -enum fast_chg_voltage_ranges { - VOLTAGE_RANGE_0, - VOLTAGE_RANGE_1, - VOLTAGE_RANGE_2, -}; - -enum temp_range { - TEMP_RANGE_0, - TEMP_RANGE_1, - TEMP_RANGE_2, - TEMP_RANGE_3, - TEMP_RANGE_4, - TEMP_RANGE_5, -}; - -/* keep track of previous charge profile info */ -static const struct fast_charge_profile *prev_chg_profile_info; - -/* SMP-CA-445 battery & BQ30Z554 fuel gauge */ -static const struct battery_info batt_info_smp_ca445 = { - .voltage_max = 8700, /* mV */ - .voltage_normal = 7600, - - /* - * Actual value 6000mV, added 100mV for charger accuracy so that - * unwanted low VSYS_Prochot# assertion can be avoided. - */ - .voltage_min = 6100, - .precharge_current = 150, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 45, - .discharging_min_c = -20, - .discharging_max_c = 60, -}; - -const struct battery_info *battery_get_info(void) -{ - static struct battery_info batt_info; - - if (battery_is_present() == BP_YES) - return &batt_info_smp_ca445; - - /* - * In no battery condition, to avoid voltage drop on VBATA set - * the battery minimum voltage to the battery maximum voltage. - */ - - batt_info = batt_info_smp_ca445; - batt_info.voltage_min = batt_info.voltage_max; - - return &batt_info; -} - -static const struct fast_charge_profile fast_charge_smp_ca445_info[] = { - /* < 0C */ - [TEMP_RANGE_0] = { - .temp_c = TEMPC_TENTHS_OF_DEG(-1), - .current_mA = { - [VOLTAGE_RANGE_0] = 0, - [VOLTAGE_RANGE_1] = 0, - [VOLTAGE_RANGE_2] = 0, - }, - }, - - /* 0C >= && <=15C */ - [TEMP_RANGE_1] = { - .temp_c = TEMPC_TENTHS_OF_DEG(15), - .current_mA = { - [VOLTAGE_RANGE_0] = 890, - [VOLTAGE_RANGE_1] = 445, - [VOLTAGE_RANGE_2] = 445, - }, - }, - - /* 15C > && <=20C */ - [TEMP_RANGE_2] = { - .temp_c = TEMPC_TENTHS_OF_DEG(20), - .current_mA = { - [VOLTAGE_RANGE_0] = 1335, - [VOLTAGE_RANGE_1] = 1335, - [VOLTAGE_RANGE_2] = 1335, - }, - }, - - /* 20C > && <=45C */ - [TEMP_RANGE_3] = { - .temp_c = TEMPC_TENTHS_OF_DEG(45), - .current_mA = { - [VOLTAGE_RANGE_0] = 2225, - [VOLTAGE_RANGE_1] = 2225, - [VOLTAGE_RANGE_2] = 2225, - }, - }, - - /* 45C > && <=55C */ - [TEMP_RANGE_4] = { - .temp_c = TEMPC_TENTHS_OF_DEG(55), - .current_mA = { - [VOLTAGE_RANGE_0] = 1335, - [VOLTAGE_RANGE_1] = 1335, - [VOLTAGE_RANGE_2] = 0, - }, - }, - - /* > 55C */ - [TEMP_RANGE_5] = { - .temp_c = TEMPC_TENTHS_OF_DEG(CHARGER_PROF_TEMP_C_LAST_RANGE), - .current_mA = { - [VOLTAGE_RANGE_0] = 0, - [VOLTAGE_RANGE_1] = 0, - [VOLTAGE_RANGE_2] = 0, - }, - }, -}; - -static const struct fast_charge_params fast_chg_params_smp_ca445 = { - .total_temp_ranges = ARRAY_SIZE(fast_charge_smp_ca445_info), - .default_temp_range_profile = TEMP_RANGE_3, - .voltage_mV = { - [VOLTAGE_RANGE_0] = 8000, - [VOLTAGE_RANGE_1] = 8200, - [VOLTAGE_RANGE_2] = CHARGER_PROF_VOLTAGE_MV_LAST_RANGE, - }, - .chg_profile_info = &fast_charge_smp_ca445_info[0], -}; - -/* - * This can override the smart battery's charging profile. To make a change, - * modify one or more of requested_voltage, requested_current, or state. - * Leave everything else unchanged. - * - * Return the next poll period in usec, or zero to use the default (which is - * state dependent). - */ -int charger_profile_override(struct charge_state_data *curr) -{ - /* - * If battery present and not in cut off and almost full - * then if it does not want charge then discharge on AC - */ - if ((battery_is_present() == BP_YES) && - !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - (curr->batt.status & STATUS_FULLY_CHARGED)) { - charger_discharge_on_ac(1); - curr->state = ST_DISCHARGE; - return 0; - } - - charger_discharge_on_ac(0); - - return charger_profile_override_common(curr, - &fast_chg_params_smp_ca445, - &prev_chg_profile_info, - batt_info_smp_ca445.voltage_max); -} - -int board_cut_off_battery(void) -{ - int rv; - - /* Ship mode command must be sent twice to take effect */ - rv = sb_write(SB_MANUFACTURER_ACCESS, SB_SHUTDOWN_DATA); - if (rv != EC_SUCCESS) - return rv; - - return sb_write(SB_MANUFACTURER_ACCESS, SB_SHUTDOWN_DATA); -} - -static inline int batt_smp_cos4870_is_initialized(void) -{ - int batt_status; - - return battery_status(&batt_status) ? 0 : - batt_status & STATUS_INITIALIZED; -} - -enum battery_present battery_hw_present(void) -{ - int data; - int rv; - - rv = PCA555_BATT_PRESENT_GPIO_READ(PCA9555_CMD_INPUT_PORT_0, &data); - - /* GPIO is low when the battery is physically present */ - return rv || (data & PCA9555_IO_5) ? BP_NO : BP_YES; -} - -/* - * Physical detection of battery. - */ -enum battery_present battery_is_present(void) -{ - static enum battery_present batt_pres_prev = BP_NOT_SURE; - enum battery_present batt_pres; - - /* Get the physical hardware status */ - batt_pres = battery_hw_present(); - - /* - * Make sure battery status is implemented, I2C transactions are - * success & the battery status is Initialized to find out if it - * is a working battery and it is not in the cut-off mode. - * - * FETs are turned off after Power Shutdown time. - * The device will wake up when a voltage is applied to PACK. - * Battery status will be inactive until it is initialized. - */ - if (batt_pres == BP_YES && batt_pres_prev != batt_pres && - !battery_is_cut_off() && !batt_smp_cos4870_is_initialized()) - batt_pres = BP_NO; - - batt_pres_prev = batt_pres; - - return batt_pres; -} diff --git a/board/glkrvp/board.c b/board/glkrvp/board.c deleted file mode 100644 index c4b3ce6e38..0000000000 --- a/board/glkrvp/board.c +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel GLK-RVP board-specific configuration */ - -#include "button.h" -#include "charger.h" -#include "chipset.h" -#include "console.h" -#include "driver/charger/isl923x.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "keyboard_scan.h" -#include "lid_switch.h" -#include "pca9555.h" -#include "power.h" -#include "power_button.h" -#include "spi.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "uart.h" -#include "util.h" - -#include "gpio_list.h" - -#define I2C_PORT_PCA555_PMIC_GPIO NPCX_I2C_PORT0_0 -#define I2C_ADDR_PCA555_PMIC_GPIO_FLAGS 0x21 -#define PCA555_PMIC_GPIO_WRITE(reg, data) \ - pca9555_write(I2C_PORT_PCA555_PMIC_GPIO, \ - I2C_ADDR_PCA555_PMIC_GPIO_FLAGS, (reg), (data)) -#define PCA555_PMIC_GPIO_READ(reg, data) \ - pca9555_read(I2C_PORT_PCA555_PMIC_GPIO, \ - I2C_ADDR_PCA555_PMIC_GPIO_FLAGS, (reg), (data)) - -#define I2C_PORT_PCA555_BOARD_ID_GPIO NPCX_I2C_PORT0_0 -#define I2C_ADDR_PCA555_BOARD_ID_GPIO_FLAGS 0x20 -#define PCA555_BOARD_ID_GPIO_READ(reg, data) \ - pca9555_read(I2C_PORT_PCA555_BOARD_ID_GPIO, \ - I2C_ADDR_PCA555_BOARD_ID_GPIO_FLAGS, (reg), (data)) - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"pmic", NPCX_I2C_PORT0_0, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"typec", NPCX_I2C_PORT7_0, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, - {"master1", NPCX_I2C_PORT1_0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"master2", NPCX_I2C_PORT2_0, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"charger", NPCX_I2C_PORT3_0, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/* Charger chips */ -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = ISL923X_ADDR_FLAGS, - .drv = &isl923x_drv, - }, -}; - -/* Wake-up pins for hibernate */ -const enum gpio_signal hibernate_wake_pins[] = { - GPIO_AC_PRESENT, - GPIO_LID_OPEN, - GPIO_POWER_BUTTON_L, -}; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); - -/* Called by APL power state machine when transitioning from G3 to S5 */ -void chipset_pre_init_callback(void) -{ - int data; - - if (PCA555_PMIC_GPIO_READ(PCA9555_CMD_OUTPUT_PORT_0, &data)) - return; - - /* - * No need to re-init PMIC since settings are sticky across sysjump. - * However, be sure to check that PMIC is already enabled. If it is - * then there's no need to re-sequence the PMIC. - */ - if (system_jumped_to_this_image() && (data & PCA9555_IO_0)) - return; - - /* Enable SOC_3P3_EN_L: Set the Output port O0.1 to low level */ - data &= ~PCA9555_IO_1; - PCA555_PMIC_GPIO_WRITE(PCA9555_CMD_OUTPUT_PORT_0, data); - - /* TODO: Find out from the spec */ - msleep(10); - - /* Enable PMIC_EN: Set the Output port O0.0 to high level */ - PCA555_PMIC_GPIO_WRITE(PCA9555_CMD_OUTPUT_PORT_0, data | PCA9555_IO_0); -} - -/* Initialize board. */ -static void board_init(void) -{ -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_FIRST); - -/* Called on AP S5 -> S3 transition */ -static void board_chipset_startup(void) -{ -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); - -/* Called on AP S3 -> S5 transition */ -static void board_chipset_shutdown(void) -{ -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); - -void chipset_do_shutdown(void) -{ - int data; - - if (PCA555_PMIC_GPIO_READ(PCA9555_CMD_OUTPUT_PORT_0, &data)) - return; - - /* Disable SOC_3P3_EN_L: Set the Output port O0.1 to high level */ - data |= PCA9555_IO_1; - PCA555_PMIC_GPIO_WRITE(PCA9555_CMD_OUTPUT_PORT_0, data); - - /* TODO: Find out from the spec */ - msleep(10); - - /* Disable PMIC_EN: Set the Output port O0.0 to low level */ - PCA555_PMIC_GPIO_WRITE(PCA9555_CMD_OUTPUT_PORT_0, data & ~PCA9555_IO_0); -} - -void board_hibernate_late(void) -{ -} - -void board_hibernate(void) -{ - /* - * To support hibernate called from console commands, ectool commands - * and key sequence, shutdown the AP before hibernating. - */ - chipset_do_shutdown(); - - /* Added delay to allow AP to settle down */ - msleep(100); -} - -int board_get_version(void) -{ - int data; - - if (PCA555_BOARD_ID_GPIO_READ(PCA9555_CMD_INPUT_PORT_1, &data)) - return -1; - - return data & 0x0f; -} - -static void pmic_init(void) -{ - /* No need to re-init PMIC since settings are sticky across sysjump. */ - if (system_jumped_late()) - return; - - /* - * PMIC INIT - * Configure Port O0.0 as Output port - PMIC_EN - * Configure Port O0.1 as Output port - SOC_3P3_EN_L - */ - PCA555_PMIC_GPIO_WRITE(PCA9555_CMD_CONFIGURATION_PORT_0, 0xfc); - - /* - * Set the Output port O0.0 to low level - PMIC_EN - * Set the Output port O0.1 to high level - SOC_3P3_EN_L - * - * POR of PCA9555 port is input with high impedance hence explicitly - * configure the SOC_3P3_EN_L to high level. - */ - PCA555_PMIC_GPIO_WRITE(PCA9555_CMD_OUTPUT_PORT_0, 0xfe); -} -DECLARE_HOOK(HOOK_INIT, pmic_init, HOOK_PRIO_INIT_I2C + 1); diff --git a/board/glkrvp/board.h b/board/glkrvp/board.h deleted file mode 100644 index 138aa478bf..0000000000 --- a/board/glkrvp/board.h +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel GLK-RVP board-specific configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* - * Allow dangerous commands. - * TODO: Remove this config before production. - */ -#define CONFIG_SYSTEM_UNLOCKED - -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) -#undef CONFIG_HOSTCMD_DEBUG_MODE - -/* - * By default, enable all console messages excepted HC, ACPI and event: - * The sensor stack is generating a lot of activity. - */ -#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF - -/* EC console commands */ - -/* Battery */ -#define CONFIG_BATTERY_CUT_OFF -#define CONFIG_BATTERY_PRESENT_CUSTOM -#define CONFIG_BATTERY_SMART - -/* Charger */ -#define CONFIG_CHARGE_MANAGER -#define CONFIG_CHARGER -#define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_ISL9238 -#define CONFIG_CHARGER_PROFILE_OVERRIDE -#define CONFIG_CHARGER_PROFILE_OVERRIDE_COMMON -#undef CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES -#define CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES 3 -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 -#undef CONFIG_EXTPOWER_DEBOUNCE_MS -#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 -#define CONFIG_EXTPOWER_GPIO - -/* DC Jack charge ports */ -#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT -#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 -#define DEDICATED_CHARGE_PORT 2 - -/* Keyboard */ -#define CONFIG_KEYBOARD_PROTOCOL_8042 - -/* UART */ -#define NPCX_UART_MODULE2 1 /* 0:GPIO10/11 1:GPIO64/65 as UART */ -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ - -/* USB-A config */ - -/* USB PD config */ -#define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define CONFIG_USB_PD_TCPM_TCPCI -#define CONFIG_USB_PD_TRY_SRC -#define CONFIG_USB_PD_VBUS_DETECT_TCPC -#define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV1 - -/* USB MUX */ -#define CONFIG_USBC_SS_MUX -#define CONFIG_USB_MUX_PS8743 - -/* SoC / PCH */ -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_CHIPSET_GEMINILAKE -#define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_POWER_BUTTON -#define CONFIG_POWER_BUTTON_X86 -#define CONFIG_POWER_COMMON -#define CONFIG_POWER_S0IX -#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE - -/* EC */ -#define CONFIG_BOARD_VERSION_CUSTOM -#define CONFIG_VOLUME_BUTTONS -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define CONFIG_WP_ALWAYS -#define CONFIG_FLASH_READOUT_PROTECTION -#define CONFIG_I2C -#define CONFIG_I2C_MASTER - -#define CONFIG_LID_SWITCH -#define CONFIG_LTO - -#define CONFIG_LOW_POWER_IDLE - -#define CONFIG_FLASH_SIZE 524288 -#define CONFIG_SPI_FLASH_REGS -#define CONFIG_SPI_FLASH_W25Q40 - -/* Verified boot */ -#define CONFIG_SHA256_UNROLLED -#define CONFIG_VBOOT_HASH -/* - * Enable 1 slot of secure temporary storage to support - * suspend/resume with read/write memory training. - */ -#define CONFIG_VSTORE -#define CONFIG_VSTORE_SLOT_COUNT 1 - -/* Optional feature - used by nuvoton */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/A4 1:GPIO93/D3 as TACH */ - -/* I2C ports */ -#define I2C_PORT_CHARGER NPCX_I2C_PORT3_0 -#define I2C_PORT_BATTERY NPCX_I2C_PORT3_0 -#define I2C_PORT_USB_MUX NPCX_I2C_PORT7_0 - -/* EC exclude modules */ -#undef CONFIG_ADC - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -enum adc_channel { - ADC_VBUS, - ADC_CH_COUNT, -}; - -int board_get_version(void); - -/* TODO: Verify the numbers below. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ - -/* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 -#define DC_JACK_MAX_VOLTAGE_MV 19000 - -/* Reset PD MCU */ -void board_reset_pd_mcu(void); -void tcpc_alert_event(enum gpio_signal signal); -void board_charging_enable(int port, int enable); -void board_vbus_enable(int port, int enable); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/glkrvp/build.mk b/board/glkrvp/build.mk deleted file mode 100644 index 235514e22b..0000000000 --- a/board/glkrvp/build.mk +++ /dev/null @@ -1,15 +0,0 @@ -# -*- makefile -*- -# Copyright 2017 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -CHIP:=npcx -CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6g - -board-y=board.o -board-$(CONFIG_BATTERY_SMART)+=battery.o -board-$(CONFIG_USB_POWER_DELIVERY)+=chg_usb_pd.o usb_pd_policy.o diff --git a/board/glkrvp/chg_usb_pd.c b/board/glkrvp/chg_usb_pd.c deleted file mode 100644 index f8e8520b72..0000000000 --- a/board/glkrvp/chg_usb_pd.c +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "charge_manager.h" -#include "charge_state_v2.h" -#include "console.h" -#include "hooks.h" -#include "task.h" -#include "tcpci.h" -#include "system.h" -#include "usb_mux.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define PTN5110_EXT_GPIO_CONFIG 0x92 -#define PTN5110_EXT_GPIO_CONTROL 0x93 - -#define PTN5110_EXT_GPIO_FRS_EN BIT(6) -#define PTN5110_EXT_GPIO_EN_SRC BIT(5) -#define PTN5110_EXT_GPIO_EN_SNK1 BIT(4) -#define PTN5110_EXT_GPIO_IILIM_5V_VBUS_L BIT(3) - -enum glkrvp_charge_ports { - TYPE_C_PORT_0, - TYPE_C_PORT_1, - DC_JACK_PORT_0 = DEDICATED_CHARGE_PORT, -}; - -const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = NPCX_I2C_PORT7_0, - .addr_flags = 0x50, - }, - .drv = &tcpci_tcpm_drv, - }, - { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = NPCX_I2C_PORT7_0, - .addr_flags = 0x52, - }, - .drv = &tcpci_tcpm_drv, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == CONFIG_USB_PD_PORT_MAX_COUNT); - -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = 0x10, - .driver = &ps8743_usb_mux_driver, - }, - { - .usb_port = 1, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = 0x11, - .driver = &ps8743_usb_mux_driver, - }, -}; - -static int board_charger_port_is_sourcing_vbus(int port) -{ - int reg; - - if (tcpc_read(port, PTN5110_EXT_GPIO_CONTROL, ®)) - return 0; - - return !!(reg & PTN5110_EXT_GPIO_EN_SRC); -} - -static int ptn5110_ext_gpio_enable(int port, int enable, int gpio) -{ - int reg; - int rv; - - rv = tcpc_read(port, PTN5110_EXT_GPIO_CONTROL, ®); - if (rv) - return rv; - - if (enable) - reg |= gpio; - else - reg &= ~gpio; - - return tcpc_write(port, PTN5110_EXT_GPIO_CONTROL, reg); -} - -void board_charging_enable(int port, int enable) -{ - ptn5110_ext_gpio_enable(port, enable, PTN5110_EXT_GPIO_EN_SNK1); -} - -void board_vbus_enable(int port, int enable) -{ - ptn5110_ext_gpio_enable(port, enable, PTN5110_EXT_GPIO_EN_SRC); -} - -void tcpc_alert_event(enum gpio_signal signal) -{ - int port = -1; - - switch (signal) { - case GPIO_USB_C0_PD_INT_ODL: - port = 0; - break; - case GPIO_USB_C1_PD_INT_ODL: - port = 1; - break; - default: - return; - } - - schedule_deferred_pd_interrupt(port); -} - -void board_tcpc_init(void) -{ - /* Only reset TCPC if not sysjump */ - if (!system_jumped_late()) - board_reset_pd_mcu(); - - /* Enable TCPC0/1 interrupt */ - gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); - -int board_tcpc_post_init(int port) -{ - int reg; - int rv; - - rv = tcpc_read(port, PTN5110_EXT_GPIO_CONFIG, ®); - if (rv) - return rv; - - /* Configure PTN5110 External GPIOs as output */ - reg |= PTN5110_EXT_GPIO_EN_SRC | PTN5110_EXT_GPIO_EN_SNK1 | - PTN5110_EXT_GPIO_IILIM_5V_VBUS_L; - rv = tcpc_write(port, PTN5110_EXT_GPIO_CONFIG, reg); - if (rv) - return rv; - - return ptn5110_ext_gpio_enable(port, 1, - PTN5110_EXT_GPIO_IILIM_5V_VBUS_L); -} - -/* Reset PD MCU */ -void board_reset_pd_mcu(void) -{ - /* TODO: Add reset logic */ -} - -static inline int board_dc_jack_present(void) -{ - return !gpio_get_level(GPIO_DC_JACK_PRESENT_L); -} - -static void board_dc_jack_handle(void) -{ - struct charge_port_info charge_dc_jack; - - /* System is booted from DC Jack */ - if (board_dc_jack_present()) { - charge_dc_jack.current = (PD_MAX_POWER_MW * 1000) / - DC_JACK_MAX_VOLTAGE_MV; - charge_dc_jack.voltage = DC_JACK_MAX_VOLTAGE_MV; - } else { - charge_dc_jack.current = 0; - charge_dc_jack.voltage = USB_CHARGER_VOLTAGE_MV; - } - - charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, - DC_JACK_PORT_0, &charge_dc_jack); -} -DECLARE_HOOK(HOOK_AC_CHANGE, board_dc_jack_handle, HOOK_PRIO_FIRST); - -static void board_charge_init(void) -{ - int port, supplier; - - /* Initialize all charge suppliers to seed the charge manager */ - for (port = 0; port < CHARGE_PORT_COUNT; port++) { - for (supplier = 0; supplier < CHARGE_SUPPLIER_COUNT; supplier++) - charge_manager_update_charge(supplier, port, NULL); - } - - board_dc_jack_handle(); -} -DECLARE_HOOK(HOOK_INIT, board_charge_init, HOOK_PRIO_DEFAULT); - -int board_set_active_charge_port(int port) -{ - /* if it's a PD port and sourcing VBUS, don't enable */ - if (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT) - if (board_charger_port_is_sourcing_vbus(port)) { - CPRINTS("Skip enable p%d", port); - return EC_ERROR_INVAL; - } - - /* - * Do not enable Type-C port if the DC Jack is present. - * When the Type-C is active port, hardware circuit will - * block DC jack from enabling +VADP_OUT. - */ - if (port != DC_JACK_PORT_0 && board_dc_jack_present()) { - CPRINTS("DC Jack present, Skip enable p%d", port); - return EC_ERROR_INVAL; - } - - /* Make sure non-charging port is disabled */ - switch (port) { - case TYPE_C_PORT_0: - board_charging_enable(TYPE_C_PORT_1, 0); - board_charging_enable(TYPE_C_PORT_0, 1); - break; - case TYPE_C_PORT_1: - board_charging_enable(TYPE_C_PORT_0, 0); - board_charging_enable(TYPE_C_PORT_1, 1); - break; - case DC_JACK_PORT_0: - case CHARGE_PORT_NONE: - default: - /* Disable both Type-C ports */ - board_charging_enable(TYPE_C_PORT_0, 0); - board_charging_enable(TYPE_C_PORT_1, 0); - break; - } - - return EC_SUCCESS; -} - -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_0; - - if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - -int adc_read_channel(enum adc_channel ch) -{ - return 0; -} diff --git a/board/glkrvp/ec.tasklist b/board/glkrvp/ec.tasklist deleted file mode 100644 index 8fecf61480..0000000000 --- a/board/glkrvp/ec.tasklist +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel RVP board-specific configuration */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/glkrvp/gpio.inc b/board/glkrvp/gpio.inc deleted file mode 100644 index a173ba6333..0000000000 --- a/board/glkrvp/gpio.inc +++ /dev/null @@ -1,180 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel GLK-RVP board-specific configuration */ - -/* - * Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. - */ - -/* Power sequencing interrupts */ -GPIO_INT(SUSPWRDNACK, PIN(0, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(RSMRST_L_PGOOD,PIN(3, 6), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(ALL_SYS_PGOOD, PIN(7, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PCH_SLP_S0_L, PIN(8, 1), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PCH_SLP_S3_L, PIN(8, 5), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PCH_SLP_S4_L, PIN(8, 6), GPIO_INT_BOTH, power_signal_interrupt) - -/* Button interrupts */ -GPIO_INT(LID_OPEN, PIN(0, 3), GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) -GPIO_INT(EC_VOLUP_BTN_ODL, PIN(3, 4), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(EC_VOLDN_BTN_ODL, PIN(3, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(POWER_BUTTON_L, PIN(A, 6), GPIO_INT_BOTH, power_button_interrupt) - -/* Type-C interrupts */ -GPIO_INT(USB_C0_PD_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, tcpc_alert_event) -GPIO_INT(USB_C1_PD_INT_ODL, PIN(6, 3), GPIO_INT_FALLING, tcpc_alert_event) - -GPIO_INT(AC_PRESENT, PIN(D, 2), GPIO_INT_BOTH, extpower_interrupt) -GPIO_INT(WP_L, PIN(9, 3), GPIO_INT_BOTH | GPIO_SEL_1P8V, switch_interrupt) - -UNIMPLEMENTED(PP3300_PG) -UNIMPLEMENTED(PP5000_PG) - -/* Power sequencing GPIOs */ -GPIO(SYS_RESET_L, PIN(0, 0), GPIO_ODR_HIGH) -GPIO(PCH_RSMRST_L, PIN(0, 1), GPIO_OUT_LOW) -GPIO(SMC_SHUTDOWN, PIN(3, 3), GPIO_OUT_LOW | GPIO_PULL_DOWN) -GPIO(PCH_SYS_PWROK, PIN(3, 5), GPIO_OUT_LOW) -GPIO(PCH_PWRBTN_L, PIN(7, 5), GPIO_ODR_HIGH) -/* - * PCH_PROCHOT_ODL is primarily for monitoring the PROCHOT# signal which is - * normally driven by the PMIC. The EC can also drive this signal in the event - * that the ambient or charger temperature sensors exceeds their thresholds. - */ -GPIO(CPU_PROCHOT, PIN(A, 3), GPIO_INPUT) /* PCH_PROCHOT_ODL */ - -/* Host communication GPIOs */ -GPIO(PCH_WAKE_L, PIN(C, 1), GPIO_ODR_HIGH) - -GPIO(DC_JACK_PRESENT_L, PIN(7, 0), GPIO_INPUT) /* DC Jack presence coming from +V3P3_A_KBC */ -GPIO(USBC_LDO_ENABLE, PIN(7, 1), GPIO_OUT_HIGH) /* USB TCPC to enable LDO in dead battery */ -GPIO(ENABLE_BACKLIGHT, PIN(9, 7), GPIO_ODR_HIGH) -GPIO(ENTERING_RW, PIN(A, 7), GPIO_OUTPUT) /* EC_ENTERING_RW */ - -/* - * I2C pins should be configured as inputs until I2C module is - * initialized. This will avoid driving the lines unintentionally. - */ -GPIO(I2C0_SCL, PIN(B, 5), GPIO_ODR_HIGH) -GPIO(I2C0_SDA, PIN(B, 4), GPIO_ODR_HIGH) -GPIO(I2C1_SCL, PIN(9, 0), GPIO_ODR_HIGH) -GPIO(I2C1_SDA, PIN(8, 7), GPIO_ODR_HIGH) -GPIO(I2C2_SCL, PIN(9, 2), GPIO_ODR_HIGH) -GPIO(I2C2_SDA, PIN(9, 1), GPIO_ODR_HIGH) -GPIO(I2C3_SCL, PIN(D, 1), GPIO_ODR_HIGH) -GPIO(I2C3_SDA, PIN(D, 0), GPIO_ODR_HIGH) -GPIO(I2C7_SCL, PIN(B, 3), GPIO_ODR_HIGH) -GPIO(I2C7_SDA, PIN(B, 2), GPIO_ODR_HIGH) - -/* LPC / eSPI signals */ -#if 0 -GPIO(LAD0_eSPI_IO0, PIN(4, 6), GPIO_INPUT) /* LAD0 / eSPI_IO0 */ -GPIO(LAD1_eSPI_IO1, PIN(4, 7), GPIO_INPUT) /* LAD1 / eSPI_IO1 */ -GPIO(LAD2_eSPI_IO2, PIN(5, 1), GPIO_INPUT) /* LAD2 / eSPI_IO2 */ -GPIO(LAD3_eSPI_IO3, PIN(5, 2), GPIO_INPUT) /* LAD3 / eSPI_IO3 */ -GPIO(LFRAME_eSPI_CS, PIN(5, 3), GPIO_INPUT) /* LFRAME / eSPI_CS */ -GPIO(LRESET_eSPI_RST, PIN(5, 4), GPIO_INPUT) /* LRESET / eSPI_RST */ -GPIO(PCI_CLK_eSPI_CLK, PIN(5, 5), GPIO_INPUT) /* PCI_CLK / eSPI_CLK */ -GPIO(CLKRUN, PIN(5, 6), GPIO_INPUT) /* CLKRUN */ -GPIO(SER_IRQ_eSPI_ALERT,PIN(5, 7), GPIO_INPUT) /* SER_IRQ / eSPI_ALERT */ -#endif - -/* Unused pins 3.3V & Interruptable */ -GPIO(NC_04, PIN(0, 4), GPIO_INPUT | GPIO_PULL_UP) - -GPIO(NC_40, PIN(4, 0), GPIO_INPUT) /* TA1_TACH1 */ -GPIO(NC_41, PIN(4, 1), GPIO_INPUT | GPIO_PULL_UP) /* ADC4 */ -GPIO(NC_42, PIN(4, 2), GPIO_INPUT | GPIO_PULL_UP) /* ADC3 */ -GPIO(NC_43, PIN(4, 3), GPIO_INPUT | GPIO_PULL_UP) /* ADC2 */ -GPIO(NC_44, PIN(4, 4), GPIO_INPUT | GPIO_PULL_UP) /* ADC1 */ -GPIO(NC_45, PIN(4, 5), GPIO_INPUT | GPIO_PULL_UP) /* ADC5 */ - -GPIO(NC_60, PIN(6, 0), GPIO_INPUT) /* PWM7 */ -GPIO(NC_61, PIN(6, 1), GPIO_INPUT | GPIO_PULL_UP) -GPIO(NC_67, PIN(6, 7), GPIO_INPUT) /* Wake-up button */ - -GPIO(NC_73, PIN(7, 3), GPIO_INPUT | GPIO_PULL_UP) -GPIO(NC_74, PIN(7, 4), GPIO_INPUT | GPIO_PULL_UP) -GPIO(NC_76, PIN(7, 6), GPIO_INPUT | GPIO_PULL_UP) /* SCI */ - -GPIO(NC_80, PIN(8, 0), GPIO_INPUT) /* PWM3 */ -GPIO(NC_82, PIN(8, 2), GPIO_INPUT | GPIO_PULL_UP) -GPIO(NC_83, PIN(8, 3), GPIO_INPUT | GPIO_PULL_UP) -GPIO(NC_84, PIN(8, 4), GPIO_INPUT | GPIO_PULL_UP) - -GPIO(NC_B1, PIN(B, 1), GPIO_INPUT | GPIO_PULL_UP) -GPIO(NC_B7, PIN(B, 7), GPIO_INPUT) /* PWM5 */ - -GPIO(NC_C0, PIN(C, 0), GPIO_INPUT) /* PWM6 */ -GPIO(NC_C2, PIN(C, 2), GPIO_INPUT) /* PWM1 */ -GPIO(NC_C3, PIN(C, 3), GPIO_INPUT) /* PWM0 */ -GPIO(NC_C4, PIN(C, 4), GPIO_INPUT) /* PWM2 */ -GPIO(NC_C5, PIN(C, 5), GPIO_INPUT | GPIO_PULL_UP) -GPIO(NC_C7, PIN(C, 7), GPIO_INPUT | GPIO_PULL_UP) - -GPIO(NC_C6, PIN(C, 6), GPIO_INPUT | GPIO_PULL_UP) /* SMI */ - -GPIO(NC_D3, PIN(D, 3), GPIO_INPUT) /* TB1 */ - -GPIO(NC_E7, PIN(E, 7), GPIO_INPUT) /* 32K_CLKIN */ - -/* Unused pins: VSPI 3.3V or 1.8V & Interruptable */ -GPIO(NC_94, PIN(9, 4), GPIO_INPUT | GPIO_PULL_UP) -GPIO(NC_95, PIN(9, 5), GPIO_INPUT | GPIO_PULL_UP) - -GPIO(NC_A1, PIN(A, 1), GPIO_INPUT | GPIO_PULL_UP) -GPIO(NC_A5, PIN(A, 5), GPIO_INPUT | GPIO_PULL_UP) - -GPIO(NC_B0, PIN(B, 0), GPIO_INPUT | GPIO_PULL_UP) - -/* Unused pins 3.3V & Non-Interruptable */ -GPIO(NC_32, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) - -GPIO(NC_66, PIN(6, 6), GPIO_INPUT | GPIO_PULL_UP) - -GPIO(NC_B6, PIN(B, 6), GPIO_INPUT) /* PWM4 */ - -/* eSPI: VHIF Unused pins 1.8V & Interruptable */ -GPIO(NC_50, PIN(5, 0), GPIO_INPUT | GPIO_PULL_UP) - -/* Alternate pins for UART */ -ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, 0) /* GPIO64/65 */ - -/* Alternate pins for I2C */ -ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1:SDA GPIO87 */ -ALTERNATE(PIN_MASK(9, 0x01), 1, MODULE_I2C, 0) /* I2C1:SCL GPIO90 */ -ALTERNATE(PIN_MASK(9, 0x06), 1, MODULE_I2C, 0) /* I2C2:SDA/SCL GPIO91/92 */ -ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* I2C7:SDA/SCL GPIOB2/B3 */ -ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0:SDA/SCL GPIOB4/B5 */ -ALTERNATE(PIN_MASK(D, 0x03), 1, MODULE_I2C, 0) /* I2C3:SDA/SCL GPIOD0/D1 */ - -/* Keyboard pins */ -#define GPIO_KB_INPUT (GPIO_INPUT) -#define GPIO_KB_OUTPUT (GPIO_ODR_HIGH) - -/* Keyboard Columns */ -/* GPIO05/06/07 */ -ALTERNATE(PIN_MASK(0, 0xE0), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) -/* GPIO10/11/12/13/14/15/16/17 */ -ALTERNATE(PIN_MASK(1, 0xFF), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) -/* GPIO20/21 */ -ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) - -/* Keyboard Rows */ -/* GPIO22/23/24/25/26/27 */ -ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) -/* GPIO30/31 */ -ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) - -/* EC SPI chip */ -#if 0 -GPIO(F_CS0_EC_L, PIN(A, 0), GPIO_OUT_HIGH | GPIO_PULL_UP) -ALTERNATE(PIN_MASK(A, 0x14), 1, MODULE_SPI, 0) /* SPI:MOSI/SCLK GPIOA4/A2 */ -ALTERNATE(PIN_MASK(9, 0x40), 1, MODULE_SPI, 0) /* SPI:MISO GPIO96 */ -#endif diff --git a/board/glkrvp/usb_pd_policy.c b/board/glkrvp/usb_pd_policy.c deleted file mode 100644 index 19572f7063..0000000000 --- a/board/glkrvp/usb_pd_policy.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "charge_manager.h" -#include "compile_time_macros.h" -#include "console.h" -#include "gpio.h" -#include "stddef.h" -#include "system.h" -#include "usb_mux.h" -#include "usb_pd_tcpm.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -int pd_set_power_supply_ready(int port) -{ - /* Disable charging */ - board_charging_enable(port, 0); - - /* Provide VBUS */ - board_vbus_enable(port, 1); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; /* we are ready */ -} - -void pd_power_supply_reset(int port) -{ - /* Disable VBUS */ - board_vbus_enable(port, 0); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -int pd_check_vconn_swap(int port) -{ - /* in G3, do not allow vconn swap since pp5000_A rail is off */ - /* TODO: return gpio_get_level(GPIO_PMIC_EN); */ - return 1; -} - -/* ----------------- Vendor Defined Messages ------------------ */ -#ifdef CONFIG_USB_PD_ALT_MODE_DFP -static void svdm_dp_post_config(int port) -{ - dp_flags[port] |= DP_FLAGS_DP_ON; - if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) - return; - /* TODO: Update HPD to host */ -} - -static int svdm_dp_attention(int port, uint32_t *payload) -{ - int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); - - /* TODO: Read HPD IRQ */ - - dp_status[port] = payload[1]; - if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { - if (lvl) - dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; - return 1; - } - /* TODO: Update HPD to host */ - - /* ack */ - return 1; -} -#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/board/glkrvp_ite/battery.c b/board/glkrvp_ite/battery.c deleted file mode 100644 index b2dc6a11c8..0000000000 --- a/board/glkrvp_ite/battery.c +++ /dev/null @@ -1,237 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery.h" -#include "charger_profile_override.h" -#include "console.h" -#include "pca9555.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -/* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHUTDOWN_DATA 0x0010 - -enum fast_chg_voltage_ranges { - VOLTAGE_RANGE_0, - VOLTAGE_RANGE_1, - VOLTAGE_RANGE_2, -}; - -enum temp_range { - TEMP_RANGE_0, - TEMP_RANGE_1, - TEMP_RANGE_2, - TEMP_RANGE_3, - TEMP_RANGE_4, - TEMP_RANGE_5, -}; - -/* keep track of previous charge profile info */ -static const struct fast_charge_profile *prev_chg_profile_info; - -/* SMP-CA-445 battery & BQ30Z554 fuel gauge */ -static const struct battery_info batt_info_smp_ca445 = { - .voltage_max = 8700, /* mV */ - .voltage_normal = 7600, - - /* - * Actual value 6000mV, added 100mV for charger accuracy so that - * unwanted low VSYS_Prochot# assertion can be avoided. - */ - .voltage_min = 6100, - .precharge_current = 150, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 45, - .discharging_min_c = -20, - .discharging_max_c = 60, -}; - -const struct battery_info *battery_get_info(void) -{ - static struct battery_info batt_info; - - if (battery_is_present() == BP_YES) - return &batt_info_smp_ca445; - - /* - * In no battery condition, to avoid voltage drop on VBATA set - * the battery minimum voltage to the battery maximum voltage. - */ - - batt_info = batt_info_smp_ca445; - batt_info.voltage_min = batt_info.voltage_max; - - return &batt_info; -} - -static const struct fast_charge_profile fast_charge_smp_ca445_info[] = { - /* < 0C */ - [TEMP_RANGE_0] = { - .temp_c = TEMPC_TENTHS_OF_DEG(-1), - .current_mA = { - [VOLTAGE_RANGE_0] = 0, - [VOLTAGE_RANGE_1] = 0, - [VOLTAGE_RANGE_2] = 0, - }, - }, - - /* 0C >= && <=15C */ - [TEMP_RANGE_1] = { - .temp_c = TEMPC_TENTHS_OF_DEG(15), - .current_mA = { - [VOLTAGE_RANGE_0] = 890, - [VOLTAGE_RANGE_1] = 445, - [VOLTAGE_RANGE_2] = 445, - }, - }, - - /* 15C > && <=20C */ - [TEMP_RANGE_2] = { - .temp_c = TEMPC_TENTHS_OF_DEG(20), - .current_mA = { - [VOLTAGE_RANGE_0] = 1335, - [VOLTAGE_RANGE_1] = 1335, - [VOLTAGE_RANGE_2] = 1335, - }, - }, - - /* 20C > && <=45C */ - [TEMP_RANGE_3] = { - .temp_c = TEMPC_TENTHS_OF_DEG(45), - .current_mA = { - [VOLTAGE_RANGE_0] = 2225, - [VOLTAGE_RANGE_1] = 2225, - [VOLTAGE_RANGE_2] = 2225, - }, - }, - - /* 45C > && <=55C */ - [TEMP_RANGE_4] = { - .temp_c = TEMPC_TENTHS_OF_DEG(55), - .current_mA = { - [VOLTAGE_RANGE_0] = 1335, - [VOLTAGE_RANGE_1] = 1335, - [VOLTAGE_RANGE_2] = 0, - }, - }, - - /* > 55C */ - [TEMP_RANGE_5] = { - .temp_c = TEMPC_TENTHS_OF_DEG(CHARGER_PROF_TEMP_C_LAST_RANGE), - .current_mA = { - [VOLTAGE_RANGE_0] = 0, - [VOLTAGE_RANGE_1] = 0, - [VOLTAGE_RANGE_2] = 0, - }, - }, -}; - -static const struct fast_charge_params fast_chg_params_smp_ca445 = { - .total_temp_ranges = ARRAY_SIZE(fast_charge_smp_ca445_info), - .default_temp_range_profile = TEMP_RANGE_3, - .voltage_mV = { - [VOLTAGE_RANGE_0] = 8000, - [VOLTAGE_RANGE_1] = 8200, - [VOLTAGE_RANGE_2] = CHARGER_PROF_VOLTAGE_MV_LAST_RANGE, - }, - .chg_profile_info = &fast_charge_smp_ca445_info[0], -}; - -/* - * This can override the smart battery's charging profile. To make a change, - * modify one or more of requested_voltage, requested_current, or state. - * Leave everything else unchanged. - * - * Return the next poll period in usec, or zero to use the default (which is - * state dependent). - */ -int charger_profile_override(struct charge_state_data *curr) -{ - /* - * If battery present and not in cut off and almost full - * then if it does not want charge then discharge on AC - */ - if ((battery_is_present() == BP_YES) && - !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - (curr->batt.status & STATUS_FULLY_CHARGED)) { - charger_discharge_on_ac(1); - curr->state = ST_DISCHARGE; - return 0; - } - - charger_discharge_on_ac(0); - - return charger_profile_override_common(curr, - &fast_chg_params_smp_ca445, - &prev_chg_profile_info, - batt_info_smp_ca445.voltage_max); -} - -int board_cut_off_battery(void) -{ - int rv; - - /* Ship mode command must be sent twice to take effect */ - rv = sb_write(SB_MANUFACTURER_ACCESS, SB_SHUTDOWN_DATA); - if (rv != EC_SUCCESS) - return rv; - - return sb_write(SB_MANUFACTURER_ACCESS, SB_SHUTDOWN_DATA); -} - -static inline int batt_smp_cos4870_is_initialized(void) -{ - int batt_status; - - return battery_status(&batt_status) ? 0 : - batt_status & STATUS_INITIALIZED; -} - -enum battery_present battery_hw_present(void) -{ - int data; - int rv; - - rv = pca9555_read(I2C_PORT_PCA555_PMIC_BATT_GPIO, - I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS, - PCA9555_CMD_INPUT_PORT_0, &data); - - /* GPIO is low when the battery is physically present */ - return rv || (data & PCA9555_IO_5) ? BP_NO : BP_YES; -} - -/* - * Physical detection of battery. - */ -enum battery_present battery_is_present(void) -{ - static enum battery_present batt_pres_prev = BP_NOT_SURE; - enum battery_present batt_pres; - - /* Get the physical hardware status */ - batt_pres = battery_hw_present(); - - /* - * Make sure battery status is implemented, I2C transactions are - * success & the battery status is Initialized to find out if it - * is a working battery and it is not in the cut-off mode. - * - * FETs are turned off after Power Shutdown time. - * The device will wake up when a voltage is applied to PACK. - * Battery status will be inactive until it is initialized. - */ - if (batt_pres == BP_YES && batt_pres_prev != batt_pres && - !battery_is_cut_off() && !batt_smp_cos4870_is_initialized()) - batt_pres = BP_NO; - - batt_pres_prev = batt_pres; - - return batt_pres; -} diff --git a/board/glkrvp_ite/board.c b/board/glkrvp_ite/board.c deleted file mode 100644 index b1102092b0..0000000000 --- a/board/glkrvp_ite/board.c +++ /dev/null @@ -1,209 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel GLK-RVP-ITE board-specific configuration */ - -#include "button.h" -#include "chipset.h" -#include "charger.h" -#include "console.h" -#include "driver/charger/isl923x.h" -#include "ec2i_chip.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "intc.h" -#include "keyboard_scan.h" -#include "lid_switch.h" -#include "pca9555.h" -#include "power.h" -#include "power_button.h" -#include "spi.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "uart.h" -#include "util.h" - -#include "gpio_list.h" - -#define I2C_PORT_PCA555_BOARD_ID_GPIO IT83XX_I2C_CH_C -#define I2C_ADDR_PCA555_BOARD_ID_GPIO_FLAGS 0x20 - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"charger", IT83XX_I2C_CH_A, 100, GPIO_I2C_A_SCL, GPIO_I2C_A_SDA}, - {"typec", IT83XX_I2C_CH_B, 400, GPIO_I2C_B_SCL, GPIO_I2C_B_SDA}, - {"pmic", IT83XX_I2C_CH_C, 100, GPIO_I2C_C_SCL, GPIO_I2C_C_SDA}, - {"ext_io", IT83XX_I2C_CH_E, 400, GPIO_I2C_E_SCL, GPIO_I2C_E_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/* Charger Chips */ -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = ISL923X_ADDR_FLAGS, - .drv = &isl923x_drv, - }, -}; - -/* Wake-up pins for hibernate */ -const enum gpio_signal hibernate_wake_pins[] = { - GPIO_AC_PRESENT, - GPIO_LID_OPEN, - GPIO_POWER_BUTTON_L, -}; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); - -/* Called by APL power state machine when transitioning from G3 to S5 */ -void chipset_pre_init_callback(void) -{ - int data; - - if (pca9555_read(I2C_PORT_PCA555_PMIC_BATT_GPIO, - I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS, - PCA9555_CMD_OUTPUT_PORT_0, &data)) - return; - - /* - * No need to re-init PMIC since settings are sticky across sysjump. - * However, be sure to check that PMIC is already enabled. If it is - * then there's no need to re-sequence the PMIC. - */ - if (system_jumped_to_this_image() && (data & PCA9555_IO_0)) - return; - - /* Enable SOC_3P3_EN_L: Set the Output port O0.1 to low level */ - data &= ~PCA9555_IO_1; - pca9555_write(I2C_PORT_PCA555_PMIC_BATT_GPIO, - I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS, - PCA9555_CMD_OUTPUT_PORT_0, data); - - /* TODO: Find out from the spec */ - msleep(10); - - /* Enable PMIC_EN: Set the Output port O0.0 to high level */ - pca9555_write(I2C_PORT_PCA555_PMIC_BATT_GPIO, - I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS, - PCA9555_CMD_OUTPUT_PORT_0, - data | PCA9555_IO_0); -} - -/* Initialize board. */ -static void board_init(void) -{ -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_FIRST); - -/* Called on AP S5 -> S3 transition */ -static void board_chipset_startup(void) -{ -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); - -/* Called on AP S3 -> S5 transition */ -static void board_chipset_shutdown(void) -{ -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); - -void chipset_do_shutdown(void) -{ - int data; - - if (pca9555_read(I2C_PORT_PCA555_PMIC_BATT_GPIO, - I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS, - PCA9555_CMD_OUTPUT_PORT_0, &data)) - return; - - /* Disable SOC_3P3_EN_L: Set the Output port O0.1 to high level */ - data |= PCA9555_IO_1; - pca9555_write(I2C_PORT_PCA555_PMIC_BATT_GPIO, - I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS, - PCA9555_CMD_OUTPUT_PORT_0, data); - - /* TODO: Find out from the spec */ - msleep(10); - - /* Disable PMIC_EN: Set the Output port O0.0 to low level */ - pca9555_write(I2C_PORT_PCA555_PMIC_BATT_GPIO, - I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS, - PCA9555_CMD_OUTPUT_PORT_0, - data & ~PCA9555_IO_0); -} - -void board_hibernate_late(void) -{ -} - -void board_hibernate(void) -{ - /* - * To support hibernate called from console commands, ectool commands - * and key sequence, shutdown the AP before hibernating. - */ - chipset_do_shutdown(); - - /* Added delay to allow AP to settle down */ - msleep(100); -} - -int board_get_version(void) -{ - int data; - - if (pca9555_read(I2C_PORT_PCA555_BOARD_ID_GPIO, - I2C_ADDR_PCA555_BOARD_ID_GPIO_FLAGS, - PCA9555_CMD_INPUT_PORT_1, &data)) - return -1; - - return data & 0x0f; -} - -static void pmic_init(void) -{ - /* No need to re-init PMIC since settings are sticky across sysjump. */ - if (system_jumped_late()) - return; - - /* - * PMIC INIT - * Configure Port O0.0 as Output port - PMIC_EN - * Configure Port O0.1 as Output port - SOC_3P3_EN_L - */ - pca9555_write(I2C_PORT_PCA555_PMIC_BATT_GPIO, - I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS, - PCA9555_CMD_CONFIGURATION_PORT_0, 0xfc); - - /* - * Set the Output port O0.0 to low level - PMIC_EN - * Set the Output port O0.1 to high level - SOC_3P3_EN_L - * - * POR of PCA9555 port is input with high impedance hence explicitly - * configure the SOC_3P3_EN_L to high level. - */ - pca9555_write(I2C_PORT_PCA555_PMIC_BATT_GPIO, - I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS, - PCA9555_CMD_OUTPUT_PORT_0, 0xfe); -} -DECLARE_HOOK(HOOK_INIT, pmic_init, HOOK_PRIO_INIT_I2C + 1); - -/* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { - .output_settle_us = 35, - .debounce_down_us = 5 * MSEC, - .debounce_up_us = 40 * MSEC, - .scan_period_us = 3 * MSEC, - .min_post_scan_delay_us = 1000, - .poll_timeout_us = 100 * MSEC, - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ - }, -}; diff --git a/board/glkrvp_ite/board.h b/board/glkrvp_ite/board.h deleted file mode 100644 index b131ac42c4..0000000000 --- a/board/glkrvp_ite/board.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel GLK-RVP-ITE board-specific configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* - * Allow dangerous commands. - * TODO: Remove this config before production. - */ -#define CONFIG_SYSTEM_UNLOCKED - -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) -#undef CONFIG_HOSTCMD_DEBUG_MODE - -/* - * By default, enable all console messages excepted HC, ACPI and event: - * The sensor stack is generating a lot of activity. - */ -#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF - -/* EC console commands */ - -/* Battery */ -#define CONFIG_BATTERY_CUT_OFF -#define CONFIG_BATTERY_PRESENT_CUSTOM -#define CONFIG_BATTERY_SMART - -/* Charger */ -#define CONFIG_CHARGE_MANAGER -#define CONFIG_CHARGER -#define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_ISL9238 -#define CONFIG_CHARGER_PROFILE_OVERRIDE -#define CONFIG_CHARGER_PROFILE_OVERRIDE_COMMON -#undef CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES -#define CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES 3 -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 -#undef CONFIG_EXTPOWER_DEBOUNCE_MS -#define CONFIG_EXTPOWER_DEBOUNCE_MS 200 -#define CONFIG_EXTPOWER_GPIO - -/* DC Jack charge ports */ -#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT -#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 -#define DEDICATED_CHARGE_PORT 2 - -/* Keyboard */ -#define CONFIG_KEYBOARD_BOARD_CONFIG -#define CONFIG_KEYBOARD_PROTOCOL_8042 - -/* UART */ -#define CONFIG_LOW_POWER_IDLE - -/* USB-A config */ - -/* USB PD config */ -#define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define CONFIG_USB_PD_TCPM_TCPCI -#define CONFIG_USB_PD_TRY_SRC -#define CONFIG_USB_PD_VBUS_DETECT_TCPC -#define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV1 - -/* USB MUX */ -#define CONFIG_USBC_SS_MUX -#define CONFIG_USB_MUX_PS8743 - -/* SoC / PCH */ -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_CHIPSET_GEMINILAKE -#define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_POWER_BUTTON -#define CONFIG_POWER_BUTTON_X86 -#define CONFIG_POWER_COMMON -#define CONFIG_POWER_S0IX -#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE - -/* EC */ -#define CONFIG_BOARD_VERSION_CUSTOM -#define CONFIG_VOLUME_BUTTONS -#define CONFIG_LID_SWITCH -#define CONFIG_WP_ALWAYS -#define CONFIG_FLASH_READOUT_PROTECTION - -/* Verified boot */ -#define CONFIG_SHA256_UNROLLED -#define CONFIG_VBOOT_HASH -/* - * Enable 1 slot of secure temporary storage to support - * suspend/resume with read/write memory training. - */ -#define CONFIG_VSTORE -#define CONFIG_VSTORE_SLOT_COUNT 1 - -/* Optional feature - used by ITE */ -#define CONFIG_IT83XX_ENABLE_MOUSE_DEVICE -#define CONFIG_IT83XX_FLASH_CLOCK_48MHZ - -/* I2C ports */ -#define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_IT83XX_SMCLK2_ON_GPC7 - -#define I2C_PORT_CHARGER IT83XX_I2C_CH_A -#define I2C_PORT_BATTERY IT83XX_I2C_CH_A -#define I2C_PORT_USB_MUX IT83XX_I2C_CH_B - -#define I2C_PORT_PCA555_PMIC_BATT_GPIO IT83XX_I2C_CH_C -#define I2C_ADDR_PCA555_PMIC_BATT_GPIO_FLAGS 0x21 - -/* EC exclude modules */ -#undef CONFIG_ADC -#undef CONFIG_WATCHDOG - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -enum adc_channel { - ADC_VBUS, - ADC_CH_COUNT, -}; - -int board_get_version(void); - -/* TODO: Verify the numbers below. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ - -/* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 -#define DC_JACK_MAX_VOLTAGE_MV 19000 - -/* Reset PD MCU */ -void board_reset_pd_mcu(void); -void tcpc_alert_event(enum gpio_signal signal); -void board_charging_enable(int port, int enable); -void board_vbus_enable(int port, int enable); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/glkrvp_ite/build.mk b/board/glkrvp_ite/build.mk deleted file mode 100644 index b2e416c00b..0000000000 --- a/board/glkrvp_ite/build.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -#it8320 -CHIP:=it83xx -CHIP_FAMILY:=it8320 -CHIP_VARIANT:=it8320bx - -board-y=board.o -board-$(CONFIG_BATTERY_SMART)+=battery.o -board-$(CONFIG_USB_POWER_DELIVERY)+=chg_usb_pd.o usb_pd_policy.o diff --git a/board/glkrvp_ite/chg_usb_pd.c b/board/glkrvp_ite/chg_usb_pd.c deleted file mode 100644 index 7bc60fd5c8..0000000000 --- a/board/glkrvp_ite/chg_usb_pd.c +++ /dev/null @@ -1,261 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "charge_manager.h" -#include "charge_state_v2.h" -#include "console.h" -#include "hooks.h" -#include "task.h" -#include "tcpci.h" -#include "system.h" -#include "usb_mux.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define PTN5110_EXT_GPIO_CONFIG 0x92 -#define PTN5110_EXT_GPIO_CONTROL 0x93 - -#define PTN5110_EXT_GPIO_FRS_EN BIT(6) -#define PTN5110_EXT_GPIO_EN_SRC BIT(5) -#define PTN5110_EXT_GPIO_EN_SNK1 BIT(4) -#define PTN5110_EXT_GPIO_IILIM_5V_VBUS_L BIT(3) - -enum glkrvp_charge_ports { - TYPE_C_PORT_0, - TYPE_C_PORT_1, - DC_JACK_PORT_0 = DEDICATED_CHARGE_PORT, -}; - -const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = IT83XX_I2C_CH_B, - .addr_flags = 0x50, - }, - .drv = &tcpci_tcpm_drv, - }, - { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = IT83XX_I2C_CH_B, - .addr_flags = 0x52, - }, - .drv = &tcpci_tcpm_drv, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == CONFIG_USB_PD_PORT_MAX_COUNT); - -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = 0x10, - .driver = &ps8743_usb_mux_driver, - }, - { - .usb_port = 1, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = 0x11, - .driver = &ps8743_usb_mux_driver, - }, -}; - -static int board_charger_port_is_sourcing_vbus(int port) -{ - int reg; - - /* DC Jack can't source VBUS */ - if (port == DC_JACK_PORT_0) - return 0; - - if (tcpc_read(port, PTN5110_EXT_GPIO_CONTROL, ®)) - return 0; - - return !!(reg & PTN5110_EXT_GPIO_EN_SRC); -} - -static int ptn5110_ext_gpio_enable(int port, int enable, int gpio) -{ - int reg; - int rv; - - rv = tcpc_read(port, PTN5110_EXT_GPIO_CONTROL, ®); - if (rv) - return rv; - - if (enable) - reg |= gpio; - else - reg &= ~gpio; - - return tcpc_write(port, PTN5110_EXT_GPIO_CONTROL, reg); -} - -void board_charging_enable(int port, int enable) -{ - ptn5110_ext_gpio_enable(port, enable, PTN5110_EXT_GPIO_EN_SNK1); -} - -void board_vbus_enable(int port, int enable) -{ - ptn5110_ext_gpio_enable(port, enable, PTN5110_EXT_GPIO_EN_SRC); -} - -void tcpc_alert_event(enum gpio_signal signal) -{ -#ifdef HAS_TASK_PDCMD - /* Exchange status with TCPCs */ - host_command_pd_send_status(PD_CHARGE_NO_CHANGE); -#endif -} - -void board_tcpc_init(void) -{ - /* Only reset TCPC if not sysjump */ - if (!system_jumped_late()) - board_reset_pd_mcu(); - - /* Enable TCPC0/1 interrupt */ - gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); - -int board_tcpc_post_init(int port) -{ - int reg; - int rv; - - rv = tcpc_read(port, PTN5110_EXT_GPIO_CONFIG, ®); - if (rv) - return rv; - - /* Configure PTN5110 External GPIOs as output */ - reg |= PTN5110_EXT_GPIO_EN_SRC | PTN5110_EXT_GPIO_EN_SNK1 | - PTN5110_EXT_GPIO_IILIM_5V_VBUS_L; - rv = tcpc_write(port, PTN5110_EXT_GPIO_CONFIG, reg); - if (rv) - return rv; - - return ptn5110_ext_gpio_enable(port, 1, - PTN5110_EXT_GPIO_IILIM_5V_VBUS_L); -} - -/* Reset PD MCU */ -void board_reset_pd_mcu(void) -{ - /* TODO: Add reset logic */ -} - -static inline int board_dc_jack_present(void) -{ - return !gpio_get_level(GPIO_DC_JACK_PRESENT_L); -} - -static void board_dc_jack_handle(void) -{ - struct charge_port_info charge_dc_jack; - - /* System is booted from DC Jack */ - if (board_dc_jack_present()) { - charge_dc_jack.current = (PD_MAX_POWER_MW * 1000) / - DC_JACK_MAX_VOLTAGE_MV; - charge_dc_jack.voltage = DC_JACK_MAX_VOLTAGE_MV; - } else { - charge_dc_jack.current = 0; - charge_dc_jack.voltage = USB_CHARGER_VOLTAGE_MV; - } - - charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, - DC_JACK_PORT_0, &charge_dc_jack); -} -DECLARE_HOOK(HOOK_AC_CHANGE, board_dc_jack_handle, HOOK_PRIO_FIRST); - -static void board_charge_init(void) -{ - int port, supplier; - - /* Initialize all charge suppliers to seed the charge manager */ - for (port = 0; port < CHARGE_PORT_COUNT; port++) { - for (supplier = 0; supplier < CHARGE_SUPPLIER_COUNT; supplier++) - charge_manager_update_charge(supplier, port, NULL); - } - - board_dc_jack_handle(); -} -DECLARE_HOOK(HOOK_INIT, board_charge_init, HOOK_PRIO_DEFAULT); - -int board_set_active_charge_port(int port) -{ - /* charge port is a realy physical port */ - int is_real_port = (port >= 0 && - port < CHARGE_PORT_COUNT); - /* check if we are source vbus on that port */ - int source = board_charger_port_is_sourcing_vbus(port); - - if (is_real_port && source) { - CPRINTS("Skip enable p%d", port); - return EC_ERROR_INVAL; - } - - /* - * Do not enable Type-C port if the DC Jack is present. - * When the Type-C is active port, hardware circuit will - * block DC jack from enabling +VADP_OUT. - */ - if (port != DC_JACK_PORT_0 && board_dc_jack_present()) { - CPRINTS("DC Jack present, Skip enable p%d", port); - return EC_ERROR_INVAL; - } - - /* Make sure non-charging port is disabled */ - switch (port) { - case TYPE_C_PORT_0: - board_charging_enable(TYPE_C_PORT_1, 0); - board_charging_enable(TYPE_C_PORT_0, 1); - break; - case TYPE_C_PORT_1: - board_charging_enable(TYPE_C_PORT_0, 0); - board_charging_enable(TYPE_C_PORT_1, 1); - break; - case DC_JACK_PORT_0: - case CHARGE_PORT_NONE: - default: - /* Disable both Type-C ports */ - board_charging_enable(TYPE_C_PORT_0, 0); - board_charging_enable(TYPE_C_PORT_1, 0); - break; - } - - return EC_SUCCESS; -} - -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_0; - - if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - -int adc_read_channel(enum adc_channel ch) -{ - return 0; -} diff --git a/board/glkrvp_ite/ec.tasklist b/board/glkrvp_ite/ec.tasklist deleted file mode 100644 index 086a352bcb..0000000000 --- a/board/glkrvp_ite/ec.tasklist +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel GLK-RVP-ITE board-specific configuration */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(PDCMD, pd_command_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/glkrvp_ite/gpio.inc b/board/glkrvp_ite/gpio.inc deleted file mode 100644 index a4f21a64f4..0000000000 --- a/board/glkrvp_ite/gpio.inc +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel GLK-RVP-ITE board-specific configuration */ - -/* - * Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. - */ - -/* Power sequencing interrupts */ -GPIO_INT(SUSPWRDNACK, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PCH_SLP_S0_L, PIN(F, 0), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PCH_SLP_S3_L, PIN(F, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PCH_SLP_S4_L, PIN(F, 3), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(RSMRST_L_PGOOD,PIN(G, 6), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(ALL_SYS_PGOOD, PIN(I, 7), GPIO_INT_BOTH, power_signal_interrupt) - -/* Button interrupts */ -GPIO_INT(VOLUME_UP_L, PIN(D, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(VOLUME_DOWN_L, PIN(D, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) -GPIO_INT(POWER_BUTTON_L,PIN(E, 4), GPIO_INT_BOTH, power_button_interrupt) - -GPIO_INT(AC_PRESENT, PIN(A, 6), GPIO_INT_BOTH, extpower_interrupt) - -GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, uart_deepsleep_interrupt) /* UART1 RX input */ -#ifdef CONFIG_HOSTCMD_ESPI -/* enable 1.8v input of EC's espi_reset pin, and then this pin takes effect. */ -GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) /* eSPI_reset# */ -#endif - -/* Type-C interrupts */ -UNIMPLEMENTED(USB_C0_PD_INT_ODL) -UNIMPLEMENTED(USB_C1_PD_INT_ODL) - -UNIMPLEMENTED(WP_L) -UNIMPLEMENTED(PP3300_PG) -UNIMPLEMENTED(PP5000_PG) - -/* Power sequencing GPIOs */ -UNIMPLEMENTED(SYS_RESET_L) -GPIO(PCH_RSMRST_L, PIN(C, 6), GPIO_OUT_LOW) -GPIO(PCH_PWRBTN_L, PIN(D, 0), GPIO_ODR_HIGH) -GPIO(PCH_SYS_PWROK, PIN(K, 4), GPIO_OUT_LOW) -GPIO(SMC_SHUTDOWN, PIN(K, 5), GPIO_OUT_LOW | GPIO_PULL_DOWN) -/* - * PCH_PROCHOT_ODL is primarily for monitoring the PROCHOT# signal which is - * normally driven by the PMIC. The EC can also drive this signal in the event - * that the ambient or charger temperature sensors exceeds their thresholds. - */ -GPIO(CPU_PROCHOT, PIN(E, 5), GPIO_INPUT) /* PCH_PROCHOT_ODL */ - -/* Host communication GPIOs */ -GPIO(PCH_WAKE_L, PIN(L, 0), GPIO_ODR_HIGH) -GPIO(PCH_PLTRST_L, PIN(E, 3), GPIO_INPUT | GPIO_PULL_UP) - -GPIO(DC_JACK_PRESENT_L, PIN(C, 0), GPIO_INPUT) /* DC Jack presence coming from +V3P3_A_KBC */ -GPIO(USBC_LDO_ENABLE, PIN(K, 0), GPIO_OUT_HIGH) /* USB TCPC to enable LDO in dead battery */ -UNIMPLEMENTED(ENABLE_BACKLIGHT) -GPIO(ENTERING_RW, PIN(C, 5), GPIO_OUTPUT) /* EC_ENTERING_RW */ - -/* - * I2C pins should be configured as inputs until I2C module is - * initialized. This will avoid driving the lines unintentionally. - */ -GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) -GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) -GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT) -GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT) -#ifdef CONFIG_IT83XX_SMCLK2_ON_GPC7 -GPIO(I2C_C_SCL, PIN(C, 7), GPIO_INPUT) -#else -GPIO(I2C_C_SCL, PIN(F, 6), GPIO_INPUT) -#endif -GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) -GPIO(I2C_E_SCL, PIN(E, 0), GPIO_INPUT) -GPIO(I2C_E_SDA, PIN(E, 7), GPIO_INPUT) - -/* LPC / eSPI signals */ -#if 0 -GPIO(LPC_ESPI_RST, PIN(D, 2), GPIO_INPUT) -GPIO(LAD_EIO_0, PIN(M, 0), GPIO_INPUT) -GPIO(LAD_EIO_1, PIN(M, 1), GPIO_INPUT) -GPIO(LAD_EIO_2, PIN(M, 2), GPIO_INPUT) -GPIO(LAD_EIO_3, PIN(M, 3), GPIO_INPUT) -GPIO(LPC_ESPI_CLK, PIN(M, 4), GPIO_INPUT) -GPIO(LFRAME_ESPI_CS, PIN(M, 5), GPIO_INPUT) -GPIO(SERIRQ_ALERT, PIN(M, 6), GPIO_INPUT) -#endif - -/* Unused pins 3.3V & Interruptable */ - -/* Unused pins: VSPI 3.3V or 1.8V & Interruptable */ - -/* Unused pins 3.3V & Non-Interruptable */ - -/* eSPI: VHIF Unused pins 1.8V & Interruptable */ - -/* eSPI: VHIF Unused pins 1.8V & Non-Interruptable */ - -/* Alternate pins for UART */ -ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, GPIO_PULL_UP) /* UART1 */ - -/* Alternate pins for I2C */ -ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A SCL/SDA B3/B4 */ -ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, 0) /* I2C B SCL/SDA C1/C2 */ -#ifdef CONFIG_IT83XX_SMCLK2_ON_GPC7 -ALTERNATE(PIN_MASK(C, 0x80), 1, MODULE_I2C, 0) /* I2C C SCL C7 */ -#else -ALTERNATE(PIN_MASK(F, 0x40), 1, MODULE_I2C, 0) /* I2C C SCL F6 */ -#endif -ALTERNATE(PIN_MASK(F, 0x80), 1, MODULE_I2C, 0) /* I2C C SDA F7 */ -ALTERNATE(PIN_MASK(E, 0x81), 1, MODULE_I2C, 0) /* I2C E SCL/SDA E0/E7 */ diff --git a/board/glkrvp_ite/usb_pd_policy.c b/board/glkrvp_ite/usb_pd_policy.c deleted file mode 100644 index bfb395baf4..0000000000 --- a/board/glkrvp_ite/usb_pd_policy.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "charge_manager.h" -#include "compile_time_macros.h" -#include "console.h" -#include "gpio.h" -#include "stddef.h" -#include "system.h" -#include "usb_mux.h" -#include "usb_pd_tcpm.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -int pd_set_power_supply_ready(int port) -{ - /* Disable charging */ - board_charging_enable(port, 0); - - /* Provide VBUS */ - board_vbus_enable(port, 1); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; /* we are ready */ -} - -void pd_power_supply_reset(int port) -{ - /* Disable VBUS */ - board_vbus_enable(port, 0); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -int pd_check_vconn_swap(int port) -{ - /* in G3, do not allow vconn swap since pp5000_A rail is off */ - /* TODO: return gpio_get_level(GPIO_PMIC_EN); */ - return 1; -} - -void pd_execute_data_swap(int port, - enum pd_data_role data_role) -{ - /* Do nothing */ -} diff --git a/board/gooey/battery.c b/board/gooey/battery.c new file mode 100644 index 0000000000..e8cec5af5f --- /dev/null +++ b/board/gooey/battery.c @@ -0,0 +1,121 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all gooey battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* SMP L18D3PG1 Battery Information */ + [BATTERY_SMP] = { + .fuel_gauge = { + .manuf_name = "SMP", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11250, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* LGC L17L3PB0 Battery Information */ + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "LGC", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 73, + }, + }, + + /* Sunwoda L17M3PB0 Battery Information */ + [BATTERY_SUNWODA] = { + .fuel_gauge = { + .manuf_name = "SUNWODA", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11250, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 186, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP; diff --git a/board/gooey/board.c b/board/gooey/board.c new file mode 100644 index 0000000000..0160832c04 --- /dev/null +++ b/board/gooey/board.c @@ -0,0 +1,490 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Gooey board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_8042.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void hdmi_hpd_interrupt(enum gpio_signal s) +{ + gpio_set_level(GPIO_USB_C1_DP_HPD, !gpio_get_level(s)); +} + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/** + * Deferred function to handle pen detect change + */ +static void pendetect_deferred(void) +{ + static int debounced_pen_detect; + int pen_detect = !gpio_get_level(GPIO_PEN_DET_ODL); + + if (pen_detect == debounced_pen_detect) + return; + + debounced_pen_detect = pen_detect; + + gpio_set_level(GPIO_EN_PP5000_PEN, debounced_pen_detect); + gpio_set_level(GPIO_PEN_DET_PCH, !debounced_pen_detect); +} +DECLARE_DEFERRED(pendetect_deferred); + +void pen_detect_interrupt(enum gpio_signal s) +{ + /* Trigger deferred notification of pen detect change */ + hook_call_deferred(&pendetect_deferred_data, 500 * MSEC); +} + +void board_hibernate(void) +{ + /* + * Charger IC need to be put into their "low power mode" before + * entering the Z-state. + */ + raa489000_hibernate(0, false); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, +}; + +/* USB-A charging control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, +}; + +void board_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + gpio_enable_interrupt(GPIO_HDMI_HPD_SUB_ODL); + /* Enable gpio interrupt for pen detect */ + gpio_enable_interrupt(GPIO_PEN_DET_ODL); + + /* Make sure pen detection is triggered or not at sysjump */ + if (!gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_EN_PP5000_PEN, 1); + if (gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_PEN_DET_PCH, 1); + + /* Set LEDs luminance */ + pwm_set_duty(PWM_CH_LED_RED, 70); + pwm_set_duty(PWM_CH_LED_GREEN, 70); + pwm_set_duty(PWM_CH_LED_WHITE, 70); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + return status; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + if (port != 0 && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + CPRINTUSB("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + tcpc_write(0, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(0, false); + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTUSB("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(0, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTUSB("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 10000, + }, + + [PWM_CH_LED_RED] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_GREEN] = { + .channel = 2, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + }, + + [PWM_CH_LED_WHITE] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP | PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 2400, + } + +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Sensor Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +/* Sensor Data */ +static struct stprivate_data g_lis2dwl_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* Drivers */ +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DWL, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2dwl_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, +}; + +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} + +static const struct ec_response_keybd_config gooey_keybd = { + /* Default Chromeos keyboard config */ + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad, has screenlock key */ + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &gooey_keybd; +} diff --git a/board/gooey/board.h b/board/gooey/board.h new file mode 100644 index 0000000000..82aca107af --- /dev/null +++ b/board/gooey/board.h @@ -0,0 +1,145 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Gooey board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_KEEBY_EC_IT8320 +#include "baseboard.h" + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 +#define CONFIG_HOSTCMD_BATTERY_V2 + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 + +/* DAC for PSYS */ +#define CONFIG_DAC + +/* LED */ +#define CONFIG_LED_ONOFF_STATES + +/* PWM */ +#define CONFIG_PWM + +/* Sensors */ +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* Power of 2 - Too large of a fifo causes too much timestamp jitter */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux */ +#define CONFIG_USB_MUX_IT5205 + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* Keyboard features */ +#define CONFIG_KEYBOARD_VIVALDI + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_LED_RED, + PWM_CH_LED_GREEN, + PWM_CH_LED_WHITE, + PWM_CH_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_SMP, + BATTERY_LGC, + BATTERY_SUNWODA, + BATTERY_TYPE_COUNT, +}; + +void pen_detect_interrupt(enum gpio_signal s); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/gooey/build.mk b/board/gooey/build.mk new file mode 100644 index 0000000000..f65b5e8f0c --- /dev/null +++ b/board/gooey/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=keeby + +board-y=board.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/gooey/ec.tasklist b/board/gooey/ec.tasklist new file mode 100644 index 0000000000..8ccdfc81b2 --- /dev/null +++ b/board/gooey/ec.tasklist @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/gooey/gpio.inc b/board/gooey/gpio.inc new file mode 100644 index 0000000000..8eb1f5ef22 --- /dev/null +++ b/board/gooey/gpio.inc @@ -0,0 +1,146 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(HDMI_HPD_SUB_ODL, PIN(E, 7), GPIO_INT_BOTH, hdmi_hpd_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Used by baseboard z-state enable, but not present on gooey */ +UNIMPLEMENTED(USB_C1_INT_ODL) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_A1_VBUS, PIN(E, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_LOW) + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc pins which will run to the I/O board */ + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(C, 7), GPIO_OUT_LOW) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO_INT(PEN_DET_ODL, PIN(J, 1), GPIO_INT_BOTH | GPIO_PULL_UP, pen_detect_interrupt) +GPIO(EN_PP5000_PEN, PIN(B, 5), GPIO_OUT_LOW) +GPIO(PEN_DET_PCH, PIN(F, 1), GPIO_OUT_LOW) +GPIO(EN_KB_BL, PIN(J, 3), GPIO_OUT_LOW) /* Currently unused */ +GPIO(EC_CBI_WP, PIN(H, 5), GPIO_OUT_LOW) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC4_NC, PIN(C, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF0_NC, PIN(F, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF4_NC, PIN(F, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG0_NC, PIN(G, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH1_NC, PIN(H, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL0_NC, PIN(L, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL2_NC, PIN(L, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL3_NC, PIN(L, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + +/* DAC */ +ALTERNATE(PIN_MASK(J, BIT(2)), 0, MODULE_DAC, 0) /* DAC2: EC_AP_PSYS */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(0) | BIT(1) | BIT(2) | BIT(3)), 0, MODULE_PWM, 0) /* KB_BL_PWM, LED_[R,G,B]_ODL */ diff --git a/board/gooey/led.c b/board/gooey/led.c new file mode 100644 index 0000000000..751ffa30bf --- /dev/null +++ b/board/gooey/led.c @@ -0,0 +1,117 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Gooey specific PWM LED settings. + */ + +#include "common.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "pwm.h" + +#define LED_OFF_LVL 0 +#define LED_ON_LVL 1 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, + 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_power(enum ec_led_colors color) +{ + if (color == EC_LED_COLOR_WHITE) + pwm_enable(PWM_CH_LED_WHITE, LED_ON_LVL); + else + pwm_enable(PWM_CH_LED_WHITE, LED_OFF_LVL); +} + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_RED: + pwm_enable(PWM_CH_LED_RED, LED_ON_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + pwm_enable(PWM_CH_LED_RED, LED_ON_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_ON_LVL); + break; + case EC_LED_COLOR_GREEN: + pwm_enable(PWM_CH_LED_RED, LED_OFF_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + pwm_enable(PWM_CH_LED_RED, LED_OFF_LVL); + pwm_enable(PWM_CH_LED_GREEN, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_battery(EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/gooey/usb_pd_policy.c b/board/gooey/usb_pd_policy.c new file mode 100644 index 0000000000..a7633b73ac --- /dev/null +++ b/board/gooey/usb_pd_policy.c @@ -0,0 +1,71 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + if (port != 0) + return; + + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port != 0) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} diff --git a/board/gooey/vif_override.xml b/board/gooey/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/gooey/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/goroh/battery.c b/board/goroh/battery.c new file mode 100644 index 0000000000..4da7b255e0 --- /dev/null +++ b/board/goroh/battery.c @@ -0,0 +1,48 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_manager.h" +#include "chipset.h" +#include "gpio.h" +#include "hooks.h" +#include "system.h" +#include "usb_pd.h" + +const struct board_batt_params board_battery_info[] = { + [BATTERY_LGC_AP18C8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G020", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC_AP18C8K; diff --git a/board/goroh/board.c b/board/goroh/board.c new file mode 100644 index 0000000000..d13c7cfb1b --- /dev/null +++ b/board/goroh/board.c @@ -0,0 +1,98 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Goroh board configuration */ + +#include "adc.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/als_tcs3400.h" +#include "driver/charger/isl923x.h" +#include "driver/ppc/syv682x.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/temp_sensor/thermistor.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "spi.h" +#include "switch.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "timer.h" +#include "uart.h" +#include "usb_mux.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable motion sensor interrupt */ + gpio_enable_interrupt(GPIO_BASE_IMU_INT_L); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + { "BOARD_ID", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH1 }, + { "TEMP_CPU", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH2 }, + { "TEMP_GPU", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH3 }, + { "TEMP_CHARGER", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH5 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* PWM channels. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_GREEN] = { .channel = PWM_HW_CH_DCR0, + .flags = PWM_CONFIG_DSLEEP | + PWM_CONFIG_OPEN_DRAIN | + PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4 }, + [PWM_CH_LED_RED] = { .channel = PWM_HW_CH_DCR1, + .flags = PWM_CONFIG_DSLEEP | + PWM_CONFIG_OPEN_DRAIN | + PWM_CONFIG_ACTIVE_LOW, + .freq_hz = 324, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4 }, + [PWM_CH_FAN] = { .channel = PWM_HW_CH_DCR2, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq_hz = 25000, /* maximum supported frequency */ + .pcfsr_sel = PWM_PRESCALER_C4 }, + [PWM_CH_KBLIGHT] = { .channel = PWM_HW_CH_DCR3, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 25000, + .pcfsr_sel = PWM_PRESCALER_C4 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_suspend(void) +{ +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + +static void board_resume(void) +{ +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); diff --git a/board/goroh/board.h b/board/goroh/board.h new file mode 100644 index 0000000000..d0f3733053 --- /dev/null +++ b/board/goroh/board.h @@ -0,0 +1,130 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Goroh board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* Chipset config */ +#define CONFIG_BRINGUP + +/* Optional features */ +#define CONFIG_LTO + +/* + * TODO: Remove this option once the VBAT no longer keeps high when + * system's power isn't presented. + */ +#define CONFIG_IT83XX_RESET_PD_CONTRACT_IN_BRAM + +/* LED */ +#define CONFIG_LED_PWM_COUNT 1 +#define CONFIG_LED_PWM +#define CONFIG_LED_POWER_LED +#undef CONFIG_LED_PWM_NEAR_FULL_COLOR +#undef CONFIG_LED_PWM_CHARGE_COLOR +#undef CONFIG_LED_PWM_CHARGE_ERROR_COLOR +#undef CONFIG_LED_PWM_LOW_BATT_COLOR +#undef CONFIG_LED_PWM_SOC_ON_COLOR +#undef CONFIG_LED_PWM_SOC_SUSPEND_COLOR +#define CONFIG_LED_PWM_NEAR_FULL_COLOR EC_LED_COLOR_GREEN +#define CONFIG_LED_PWM_CHARGE_COLOR EC_LED_COLOR_GREEN +#define CONFIG_LED_PWM_CHARGE_ERROR_COLOR EC_LED_COLOR_RED +#define CONFIG_LED_PWM_LOW_BATT_COLOR EC_LED_COLOR_RED +#define CONFIG_LED_PWM_SOC_ON_COLOR EC_LED_COLOR_COUNT /* OFF */ +#define CONFIG_LED_PWM_SOC_SUSPEND_COLOR EC_LED_COLOR_COUNT /* OFF */ + +/* PD / USB-C / PPC */ +#define CONFIG_USB_PD_DEBUG_LEVEL 3 + +/* Optional console commands */ +#define CONFIG_CMD_FLASH +#define CONFIG_CMD_SCRATCHPAD + +#define CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV 9000 + +/* Sensor */ +#define CONFIG_GMR_TABLET_MODE +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH + +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_UPDATE + +#define CONFIG_ACCEL_BMA255 /* Lid accel BMA253 */ + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK \ + (BIT(LID_ACCEL) | BIT(BASE_GYRO) | BIT(BASE_ACCEL)) + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* SPI / Host Command */ +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + +/* USB-A */ +#define USBA_PORT_COUNT 1 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum battery_type { + BATTERY_LGC_AP18C8K, + BATTERY_TYPE_COUNT, +}; + +enum sensor_id { + BASE_ACCEL = 0, + BASE_GYRO, + LID_ACCEL, + + SENSOR_COUNT, +}; + +enum adc_channel { + ADC_BOARD_ID, /* ADC 1 */ + ADC_TEMP_SENSOR_CPU, /* ADC 2 */ + ADC_TEMP_SENSOR_GPU, /* ADC 3 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC 5 */ + + /* Number of ADC channels */ + ADC_CH_COUNT, +}; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +enum pwm_channel { + PWM_CH_LED_GREEN, + PWM_CH_LED_RED, + PWM_CH_FAN, + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +enum fan_channel { FAN_CH_0, FAN_CH_COUNT }; + +enum temp_sensor_id { + TEMP_SENSOR_CPU, + TEMP_SENSOR_GPU, + TEMP_SENSOR_CHARGER, + TEMP_SENSOR_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/goroh/build.mk b/board/goroh/build.mk new file mode 100644 index 0000000000..5f2dea191a --- /dev/null +++ b/board/goroh/build.mk @@ -0,0 +1,18 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build + +# the IC is ITE IT8xxx2 +CHIP:=it83xx +CHIP_FAMILY:=it8xxx2 +CHIP_VARIANT:=it81202bx_1024 +BASEBOARD:=goroh + +board-y+=battery.o +board-y+=board.o +board-y+=fans.o +board-y+=led.o +board-y+=sensors.o diff --git a/board/goroh/ec.tasklist b/board/goroh/ec.tasklist new file mode 100644 index 0000000000..148b7679ae --- /dev/null +++ b/board/goroh/ec.tasklist @@ -0,0 +1,20 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(PDCMD, pd_command_task, NULL, 1024) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, 1280) \ + diff --git a/board/goroh/fans.c b/board/goroh/fans.c new file mode 100644 index 0000000000..1ac9a79acb --- /dev/null +++ b/board/goroh/fans.c @@ -0,0 +1,91 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = PWM_CH_FAN, + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN_X, +}; + +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2400, + .rpm_start = 2400, + .rpm_max = 5700, +}; + +const struct fan_t fans[] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(fans) == CONFIG_FANS); +/* + * PWM HW channelx binding tachometer channelx for fan control. + * Four tachometer input pins but two tachometer modules only, + * so always binding [TACH_CH_TACH0A | TACH_CH_TACH0B] and/or + * [TACH_CH_TACH1A | TACH_CH_TACH1B] + */ +const struct fan_tach_t fan_tach[] = { + [PWM_HW_CH_DCR0] = { + .ch_tach = TACH_CH_NULL, + .fan_p = -1, + .rpm_re = -1, + .s_duty = -1, + }, + [PWM_HW_CH_DCR1] = { + .ch_tach = TACH_CH_NULL, + .fan_p = -1, + .rpm_re = -1, + .s_duty = -1, + }, + [PWM_HW_CH_DCR2] = { + .ch_tach = TACH_CH_TACH0A, + .fan_p = 2, + .rpm_re = 50, + .s_duty = 30, + }, + [PWM_HW_CH_DCR3] = { + .ch_tach = TACH_CH_NULL, + .fan_p = -1, + .rpm_re = -1, + .s_duty = -1, + }, + [PWM_HW_CH_DCR4] = { + .ch_tach = TACH_CH_NULL, + .fan_p = -1, + .rpm_re = -1, + .s_duty = -1, + }, + [PWM_HW_CH_DCR5] = { + .ch_tach = TACH_CH_NULL, + .fan_p = -1, + .rpm_re = -1, + .s_duty = -1, + }, + [PWM_HW_CH_DCR6] = { + .ch_tach = TACH_CH_NULL, + .fan_p = -1, + .rpm_re = -1, + .s_duty = -1, + }, + [PWM_HW_CH_DCR7] = { + .ch_tach = TACH_CH_NULL, + .fan_p = -1, + .rpm_re = -1, + .s_duty = -1, + }, +}; diff --git a/board/goroh/gpio.inc b/board/goroh/gpio.inc new file mode 100644 index 0000000000..5d534044fe --- /dev/null +++ b/board/goroh/gpio.inc @@ -0,0 +1,156 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, + power_button_interrupt) /* H1_EC_PWR_BTN_ODL */ +GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, + lid_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(J, 7), GPIO_INT_BOTH, + gmr_tablet_switch_isr) + +/* Power sequencing interrupts */ +GPIO_INT(AP_EC_WARM_RST_REQ, PIN(D, 3), GPIO_INT_RISING | GPIO_SEL_1P8V, + chipset_reset_request_interrupt) +GPIO_INT(AP_EC_SHUTDOWN_REQ_L, PIN(F, 2), + GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + chipset_reset_request_interrupt) +GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 7), GPIO_INT_BOTH | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(PG_S5_PWR_OD, PIN(A, 6), GPIO_INT_BOTH, + power_signal_interrupt) +GPIO_INT(PG_VDD1_VDD2_OD, PIN(M, 6), GPIO_INT_BOTH | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(PG_VDD_MEDIA_ML_OD, PIN(J, 3), GPIO_INT_BOTH, + power_signal_interrupt) +GPIO_INT(PG_VDD_SOC_OD, PIN(J, 4), GPIO_INT_BOTH, + power_signal_interrupt) +GPIO_INT(PG_VDD_DDR_OD, PIN(J, 5), GPIO_INT_BOTH, + power_signal_interrupt) + +/* Sensor Interrupts */ +GPIO_INT(BASE_IMU_INT_L, PIN(M, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, + bmi160_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_FAULT_ODL, PIN(D, 1), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USB_C1_FAULT_ODL, PIN(B, 2), GPIO_INT_BOTH, ppc_interrupt) + +/* Volume button interrupts */ +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(D, 5), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(H, 6), GPIO_INT_BOTH, button_interrupt) + +/* Other interrupts */ +GPIO_INT(ACOK_OD, PIN(E, 5), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, + extpower_interrupt) /* AC_OK / AC_PRESENT in rev1+ */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, + uart_deepsleep_interrupt) /* UART_DEBUG_TX_EC_RX */ +GPIO_INT(WP, PIN(I, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, + switch_interrupt) /* EC_FLASH_WP_OD */ +GPIO_INT(SPI0_CS, PIN(M, 5), GPIO_INT_FALLING, + spi_event) /* SPI slave Chip Select -- AP_SPI_EC_CS_L */ + +/* Power Sequencing Signals */ +GPIO(EN_PP1800_S5, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EN_PP5000_S5, PIN(C, 6), GPIO_OUT_HIGH) /* default high for PPC init on start up. */ +GPIO(EN_VDD_SOC, PIN(E, 1), GPIO_OUT_LOW) +GPIO(EN_VDD_MEDIA_ML, PIN(F, 1), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(B, 6), GPIO_ODR_LOW) +GPIO(EC_BL_EN_OD, PIN(B, 5), GPIO_ODR_LOW | GPIO_SEL_1P8V) +GPIO(EN_VDDQ_VR_D, PIN(M, 3), GPIO_OUT_LOW) +GPIO(EN_PP1820A_IO_X, PIN(D, 4), GPIO_OUT_LOW) +GPIO(EN_PP1800_VDD33_PMC_X, PIN(D, 0), GPIO_OUT_LOW) +GPIO(EN_PP0800_VDD_PMC_X, PIN(D, 2), GPIO_OUT_LOW) +GPIO(EN_VDD1_VDD2_VR, PIN(A, 7), GPIO_OUT_LOW) +GPIO(EN_PP3300A_IO_X, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_VDD_DDR, PIN(I, 0), GPIO_OUT_LOW) +GPIO(EN_VDD_CPU, PIN(F, 3), GPIO_OUT_LOW) +GPIO(EN_PP1800_S3, PIN(G, 2), GPIO_OUT_LOW) +GPIO(EN_PP3300_S3, PIN(G, 3), GPIO_OUT_LOW) +GPIO(EN_VDD_GPU, PIN(G, 1), GPIO_OUT_LOW) +GPIO(EN_PP1800_VDDIO_PMC_X, PIN(B, 7), GPIO_OUT_LOW) + +/* MKBP event synchronization */ +GPIO(EC_INT_L, PIN(E, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_AP_INT_ODL */ + +/* USB and USBC Signals */ +GPIO(USB_C1_HPD_3V3, PIN(J, 0), GPIO_OUT_LOW) +GPIO(USB_C0_HPD_3V3, PIN(J, 1), GPIO_OUT_LOW) +GPIO(USB_C1_HPD_IN, PIN(J, 2), GPIO_OUT_LOW) +GPIO(EN_USB_C1_MUX_PWR, PIN(F, 0), GPIO_OUT_LOW) +GPIO(USB_C0_SBU1_DC, PIN(H, 4), GPIO_OUT_LOW) +GPIO(USB_C0_SBU2_DC, PIN(H, 5), GPIO_OUT_LOW) + +/* Misc Signals */ +GPIO(EC_BATT_PRES_ODL, PIN(C, 0), GPIO_INPUT) +GPIO(ENTERING_RW, PIN(C, 5), GPIO_OUT_LOW) /* EC_ENTERING_RW */ +GPIO(EN_EC_ID_ODL, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_FAN_X, PIN(E, 3), GPIO_OUT_LOW) +GPIO(EN_PPVAR_KB_BL_X, PIN(H, 3), GPIO_OUT_LOW) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) /* I2C_CHG_BATT_SCL */ +GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) /* I2C_CHG_BATT_SDA */ +GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SCL */ +GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SDA */ +GPIO(I2C_C_SCL, PIN(F, 6), GPIO_INPUT) /* I2C_USB_C0_SCL */ +GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) /* I2C_USB_C0_SCL */ +GPIO(I2C_E_SCL, PIN(E, 0), GPIO_INPUT) /* I2C_USB_C1_SCL */ +GPIO(I2C_E_SDA, PIN(E, 7), GPIO_INPUT) /* I2C_USB_C1_SDA */ + +/* SPI pins - Alternate function below configures SPI module on these pins */ + +/* NC / TP */ + +/* Keyboard pins */ + +/* CLOCK */ +GPIO(CLK_32_EC, PIN(J, 6), GPIO_INPUT) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A */ +ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C B */ +ALTERNATE(PIN_MASK(F, 0xC0), 1, MODULE_I2C, 0) /* I2C C */ +ALTERNATE(PIN_MASK(E, 0x81), 1, MODULE_I2C, 0) /* I2C E */ + +/* UART */ +ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, 0) /* EC to Servo */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, 0x0F), 1, MODULE_PWM, 0) /* PWM 0~3 */ +ALTERNATE(PIN_MASK(D, 0x40), 3, MODULE_PWM, GPIO_PULL_UP) /* TACH0A for FAN1 */ + +/* ADC */ +ALTERNATE(PIN_MASK(I, 0x2E), 0, MODULE_ADC, 0) /* ADC 1,2,3,5 */ + +/* SPI */ +ALTERNATE(PIN_MASK(M, 0x33), 0, MODULE_SPI, 0) /* SPI */ + +/* unused, configure as input pin */ +GPIO(LID_ACCEL_INT_L, PIN(G, 0), GPIO_INPUT | GPIO_SEL_1P8V) + +/* *_ODL pin has external pullup so don't pull it down. */ + +/* reserved for future use */ +GPIO(CCD_MODE_ODL, PIN(C, 4), GPIO_INPUT) +/* + * ADC pins don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(NC_GPI7, PIN(I, 7), GPIO_OUT_LOW) +/* NC pins, enable internal pull-up/down to avoid floating state. */ +GPIO(SPI_CLK_GPG6, PIN(G, 6), GPIO_INPUT | GPIO_PULL_UP) +/* + * These 3 pins don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(SPI_MOSI_GPG4, PIN(G, 4), GPIO_OUT_LOW) +GPIO(SPI_MISO_GPG5, PIN(G, 5), GPIO_OUT_LOW) +GPIO(SPI_CS_GPG7, PIN(G, 7), GPIO_OUT_LOW) diff --git a/board/goroh/led.c b/board/goroh/led.c new file mode 100644 index 0000000000..7ed155acc0 --- /dev/null +++ b/board/goroh/led.c @@ -0,0 +1,63 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "ec_commands.h" +#include "led_common.h" +#include "led_pwm.h" +#include "pwm.h" + +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Green, Red */ + [EC_LED_COLOR_RED] = { 0, 100 }, [EC_LED_COLOR_GREEN] = { 100, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0 }, [EC_LED_COLOR_YELLOW] = { 0, 0 }, + [EC_LED_COLOR_WHITE] = { 0, 0 }, [EC_LED_COLOR_AMBER] = { 0, 0 }, +}; + +struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = { + [PWM_LED0] = { + /* left port LEDs */ + .ch0 = PWM_CH_LED_GREEN, + .ch1 = PWM_CH_LED_RED, + .ch2 = PWM_LED_NO_CHANNEL, + .enable = &pwm_enable, + .set_duty = &pwm_set_duty, + }, +}; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) + brightness_range[EC_LED_COLOR_RED] = 100; + else if (led_id == EC_LED_ID_POWER_LED) + brightness_range[EC_LED_COLOR_GREEN] = 100; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + enum pwm_led_id pwm_id; + + /* Convert ec_led_id to pwm_led_id. */ + if (led_id == EC_LED_ID_POWER_LED || led_id == EC_LED_ID_BATTERY_LED) + pwm_id = PWM_LED0; + else + return EC_ERROR_UNKNOWN; + + if (brightness[EC_LED_COLOR_RED]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_GREEN]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN); + else + /* Otherwise, the "color" is "off". */ + set_pwm_led_color(pwm_id, -1); + + return EC_SUCCESS; +} diff --git a/board/goroh/sensors.c b/board/goroh/sensors.c new file mode 100644 index 0000000000..8236627e47 --- /dev/null +++ b/board/goroh/sensors.c @@ -0,0 +1,124 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Goroh sensors configuration */ + +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/als_tcs3400.h" +#include "driver/temp_sensor/thermistor.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "spi.h" +#include "temp_sensor.h" +#include "thermal.h" + +static struct mutex g_base_mutex; +static struct mutex g_lid_mutex; + +static struct bmi_drv_data_t g_bmi160_data; +static struct accelgyro_saved_data_t g_bma253_data; + +struct motion_sensor_t motion_sensors[] = { + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = NULL, /* identity matrix */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = NULL, /* identity matrix */ + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = NULL, /* identity matrix */ + .min_frequency = BMI_GYRO_MIN_FREQ, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_CPU] = { + .name = "CPU", + .type = TEMP_SENSOR_TYPE_CPU, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_CPU, + }, + [TEMP_SENSOR_GPU] = { + .name = "GPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_GPU, + }, + [TEMP_SENSOR_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); diff --git a/board/goroh/usbc_confg.c b/board/goroh/usbc_confg.c new file mode 100644 index 0000000000..a2d268877f --- /dev/null +++ b/board/goroh/usbc_confg.c @@ -0,0 +1,33 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" + +#include +#include + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_FAULT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_FAULT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); diff --git a/board/goroh/vif_override.xml b/board/goroh/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/goroh/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/grunt/battery.c b/board/grunt/battery.c index 359ec9785b..7c7ec44c56 100644 --- a/board/grunt/battery.c +++ b/board/grunt/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/grunt/board.c b/board/grunt/board.c index 45aa4f4421..96b8f986b7 100644 --- a/board/grunt/board.c +++ b/board/grunt/board.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,6 +18,7 @@ #include "pwm_chip.h" #include "switch.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" const enum gpio_signal hibernate_wake_pins[] = { @@ -25,16 +26,40 @@ const enum gpio_signal hibernate_wake_pins[] = { GPIO_AC_PRESENT, GPIO_POWER_BUTTON_L, }; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* I2C port map. */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"thermal", I2C_PORT_THERMAL_AP, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"kblight", I2C_PORT_KBLIGHT, 100, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "thermal", + .port = I2C_PORT_THERMAL_AP, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "kblight", + .port = I2C_PORT_KBLIGHT, + .kbps = 100, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/grunt/board.h b/board/grunt/board.h index 2585db17fd..b8cb063dee 100644 --- a/board/grunt/board.h +++ b/board/grunt/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF @@ -51,7 +51,6 @@ #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCEL_KX022 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -63,7 +62,7 @@ /* * Slew rate on the PP1800_SENSOR load switch requires a short delay on startup. */ -#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US +#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US #define CONFIG_MOTION_SENSE_RESUME_DELAY_US (10 * MSEC) #ifndef __ASSEMBLER__ diff --git a/board/grunt/build.mk b/board/grunt/build.mk index c808e65aed..d24127ddae 100644 --- a/board/grunt/build.mk +++ b/board/grunt/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/grunt/ec.tasklist b/board/grunt/ec.tasklist index dc898c4502..9572d61c8f 100644 --- a/board/grunt/ec.tasklist +++ b/board/grunt/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/grunt/gpio.inc b/board/grunt/gpio.inc index 97f5afabfd..8c75686f47 100644 --- a/board/grunt/gpio.inc +++ b/board/grunt/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/grunt/led.c b/board/grunt/led.c index 9cd1122665..0a7a794bfd 100644 --- a/board/grunt/led.c +++ b/board/grunt/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,14 +18,11 @@ const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); * We only have a blue and an amber LED, so setting any other colour results in * both LEDs being off. */ -struct pwm_led led_color_map[EC_LED_COLOR_COUNT] = { - /* Amber, Blue */ - [EC_LED_COLOR_RED] = { 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 100 }, - [EC_LED_COLOR_YELLOW] = { 0, 0 }, - [EC_LED_COLOR_WHITE] = { 0, 0 }, - [EC_LED_COLOR_AMBER] = { 100, 0 }, +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Amber, Blue */ + [EC_LED_COLOR_RED] = { 0, 0 }, [EC_LED_COLOR_GREEN] = { 0, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 100 }, [EC_LED_COLOR_YELLOW] = { 0, 0 }, + [EC_LED_COLOR_WHITE] = { 0, 0 }, [EC_LED_COLOR_AMBER] = { 100, 0 }, }; /* One logical LED with amber and blue channels. */ diff --git a/board/grunt/vif_override.xml b/board/grunt/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/grunt/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/gumboz/analyzestack.yaml b/board/gumboz/analyzestack.yaml new file mode 100644 index 0000000000..7ff5f39644 --- /dev/null +++ b/board/gumboz/analyzestack.yaml @@ -0,0 +1,2 @@ +remove: +- panic_assert_fail diff --git a/board/gumboz/battery.c b/board/gumboz/battery.c new file mode 100644 index 0000000000..8b9b3ddf96 --- /dev/null +++ b/board/gumboz/battery.c @@ -0,0 +1,211 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all Gumboz battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* Simplo Coslight Battery Information */ + [BATTERY_SIMPLO_COS] = { + .fuel_gauge = { + .manuf_name = "333-1C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Simplo HIGHPOWER Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-1D-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Samsung SDI Battery Information */ + [BATTERY_SAMSUNG_SDI] = { + .fuel_gauge = { + .manuf_name = "333-54-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack ATL Battery Information */ + [BATTERY_DYNAPACK_ATL] = { + .fuel_gauge = { + .manuf_name = "333-27-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack Cosmx Battery Information */ + [BATTERY_DYNAPACK_COS] = { + .fuel_gauge = { + .manuf_name = "333-2C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Cosmx Battery Information */ + [BATTERY_COSMX] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO_COS; diff --git a/board/gumboz/board.c b/board/gumboz/board.c new file mode 100644 index 0000000000..b6388983d7 --- /dev/null +++ b/board/gumboz/board.c @@ -0,0 +1,647 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "button.h" +#include "charge_state.h" +#include "cros_board_info.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/ppc/aoz1380_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/usb_mux/amd_fp5.h" +#include "driver/usb_mux/ps8743.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "ioexpander.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "usb_charge.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* This I2C moved. Temporarily detect and support the V0 HW. */ +int I2C_PORT_BATTERY = I2C_PORT_BATTERY_V1; + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Motion sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* sensor private data */ +static struct kionix_accel_data g_kx022_data; +static struct lsm6dsm_data g_lsm6dsm_data = LSM6DSM_DATA; + +/* Matrix to rotate accelrator into standard reference frame */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +/* TODO(gcc >= 5.0) Remove the casts to const pointer at rot_standard_ref */ +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g */ + /* We only use 2g because its resolution is only 8-bits */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/***************************************************************************** + * Retimers + */ + +static void retimers_on(void) +{ + /* usba retimer power on */ + ioex_set_level(IOEX_USB_A1_RETIMER_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, retimers_on, HOOK_PRIO_DEFAULT); + +static void retimers_off(void) +{ + /* usba retimer power off */ + ioex_set_level(IOEX_USB_A1_RETIMER_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, retimers_off, HOOK_PRIO_DEFAULT); + +/***************************************************************************** + * USB-C + */ + +/* + * USB C0 port SBU mux use standalone PI3USB221 + * chip and it need a board specific driver. + * Overall, it will use chained mux framework. + */ +static int pi3usb221_set_mux(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) +{ + /* This driver does not use host command ACKs */ + *ack_required = false; + + if (mux_state & USB_PD_MUX_POLARITY_INVERTED) + ioex_set_level(IOEX_USB_C0_SBU_FLIP, 1); + else + ioex_set_level(IOEX_USB_C0_SBU_FLIP, 0); + + return EC_SUCCESS; +} + +/* + * .init is not necessary here because it has nothing + * to do. Primary mux will handle mux state so .get is + * not needed as well. usb_mux.c can handle the situation + * properly. + */ +const struct usb_mux_driver usbc0_sbu_mux_driver = { + .set = pi3usb221_set_mux, +}; + +/* + * Since PI3USB221 is not a i2c device, .i2c_port and + * .i2c_addr_flags are not required here. + */ +const struct usb_mux_chain usbc0_sbu_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &usbc0_sbu_mux_driver, + }, +}; + +struct usb_mux_chain usbc1_amd_fp5_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + .flags = USB_MUX_FLAG_SET_WITHOUT_FLIP, + }, +}; + +struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_sbu_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PS8743_I2C_ADDR1_FLAG, + .driver = &ps8743_usb_mux_driver, + }, + .next = &usbc1_amd_fp5_usb_mux, + } +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + /* Device does not talk I2C */ + .drv = &aoz1380_drv + }, + + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = NX20P3483_ADDR1_FLAGS, + .drv = &nx20p348x_drv + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_FAULT_ODL: + aoz1380_interrupt(USBC_PORT_C0); + break; + + case GPIO_USB_C1_PPC_INT_ODL: + /* + * Sensitive only to falling edges; GPIO is configured for both + * because this input may be used for HDMI HPD instead. + */ + if (!gpio_get_level(signal)) + nx20p348x_interrupt(USBC_PORT_C1); + break; + + default: + break; + } +} + +int board_set_active_charge_port(int port) +{ + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + switch (port) { + case USBC_PORT_C0: + ioex_set_level(IOEX_USB_C0_FAULT_ODL, !is_overcurrented); + break; + + case USBC_PORT_C1: + ioex_set_level(IOEX_USB_C1_FAULT_ODL, !is_overcurrented); + break; + + default: + break; + } +} + +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +static void reset_nct38xx_port(int port) +{ + enum gpio_signal reset_gpio_l; + + if (port == USBC_PORT_C0) + reset_gpio_l = GPIO_USB_C0_TCPC_RST_L; + else if (port == USBC_PORT_C1) + reset_gpio_l = GPIO_USB_C1_TCPC_RST_L; + else + /* Invalid port: do nothing */ + return; + + gpio_set_level(reset_gpio_l, 0); + msleep(NCT38XX_RESET_HOLD_DELAY_MS); + gpio_set_level(reset_gpio_l, 1); + nct38xx_reset_notify(port); + if (NCT3807_RESET_POST_DELAY_MS != 0) + msleep(NCT3807_RESET_POST_DELAY_MS); +} + +void board_reset_pd_mcu(void) +{ + /* Reset TCPC0 */ + reset_nct38xx_port(USBC_PORT_C0); + + /* Reset TCPC1 */ + reset_nct38xx_port(USBC_PORT_C1); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set and ignore if that TCPC has + * its reset line active. + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) { + if (gpio_get_level(GPIO_USB_C0_TCPC_RST_L) != 0) + status |= PD_STATUS_TCPC_ALERT_0; + } + + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) { + if (gpio_get_level(GPIO_USB_C1_TCPC_RST_L) != 0) + status |= PD_STATUS_TCPC_ALERT_1; + } + + return status; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_TCPC_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + + default: + break; + } +} + +int board_pd_set_frs_enable(int port, int enable) +{ + int rv = EC_SUCCESS; + + /* Use the TCPC to enable fast switch when FRS included */ + if (port == USBC_PORT_C0) { + rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, !!enable); + } else { + rv = ioex_set_level(IOEX_USB_C1_TCPC_FASTSW_CTL_EN, !!enable); + } + + return rv; +} + +static void setup_fw_config(void) +{ + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_FAULT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC 1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); + + /* Enable SBU fault interrupts */ + ioex_enable_interrupt(IOEX_USB_C0_SBU_FAULT_ODL); + ioex_enable_interrupt(IOEX_USB_C1_SBU_FAULT_DB_ODL); + + if (ec_config_has_lid_angle_tablet_mode()) { + /* Enable Gyro interrupts */ + gpio_enable_interrupt(GPIO_6AXIS_INT_L); + } else { + motion_sensor_count = 0; + /* Device is clamshell only */ + tablet_set_mode(0, TABLET_TRIGGER_LID); + /* Gyro is not present, don't allow line to float */ + gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + } +} +DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP, + .freq = 100, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT3807] = { + .i2c_host_port = I2C_PORT_TCPC0, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + }, + [IOEX_C1_NCT3807] = { + .i2c_host_port = I2C_PORT_TCPC1, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +int usb_port_enable[USBA_PORT_COUNT] = { + IOEX_EN_USB_A0_5V, + IOEX_EN_USB_A1_5V_DB, +}; + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, { 1, 4 }, + { 1, 3 }, { 1, 6 }, { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, + { 2, 6 }, { 2, 7 }, { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, + { 2, 3 }, { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif + +#define CHARGING_CURRENT_500MA 500 + +int charger_profile_override(struct charge_state_data *curr) +{ + int rv; + static int thermal_sensor_temp; + static int prev_thermal_sensor_temp; + static int limit_charge; + static int limit_usbc_power; + static int limit_usbc_power_backup; + enum tcpc_rp_value rp; + + rv = temp_sensor_read(TEMP_SENSOR_CHARGER, &thermal_sensor_temp); + + if (rv != EC_SUCCESS) + return 0; + + if (thermal_sensor_temp > prev_thermal_sensor_temp) { + if (thermal_sensor_temp > C_TO_K(63)) + limit_usbc_power = 1; + + else if (thermal_sensor_temp > C_TO_K(58)) { + if (curr->state == ST_CHARGE) + limit_charge = 1; + } + } else if (thermal_sensor_temp < prev_thermal_sensor_temp) { + if (thermal_sensor_temp < C_TO_K(57)) { + if (curr->state == ST_CHARGE) + limit_charge = 0; + + } else if (thermal_sensor_temp < C_TO_K(62)) + limit_usbc_power = 0; + } + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return 0; + + curr->requested_current = (limit_charge) ? CHARGING_CURRENT_500MA : + curr->batt.desired_current; + + if (limit_usbc_power != limit_usbc_power_backup) { + rp = (limit_usbc_power) ? TYPEC_RP_1A5 : TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + limit_usbc_power_backup = limit_usbc_power; + } + + prev_thermal_sensor_temp = thermal_sensor_temp; + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +__override struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT] = { + [TEMP_SENSOR_CHARGER] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(63), + [EC_TEMP_THRESH_HALT] = C_TO_K(92), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(62), + } + }, + [TEMP_SENSOR_SOC] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + [EC_TEMP_THRESH_HALT] = C_TO_K(85), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(77), + } + }, + [TEMP_SENSOR_CPU] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), + [EC_TEMP_THRESH_HALT] = C_TO_K(90), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(83), + } + }, +}; diff --git a/board/gumboz/board.h b/board/gumboz/board.h new file mode 100644 index 0000000000..abf8280f74 --- /dev/null +++ b/board/gumboz/board.h @@ -0,0 +1,161 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trembyle board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_ZORK_DALBOZ + +#include "baseboard.h" + +#include + +#define CONFIG_USBC_PPC_NX20P3483 +#define CONFIG_USB_MUX_PS8743 +#define CONFIG_USB_MUX_RUNTIME_CONFIG + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PORT_ENABLE_DYNAMIC + +#undef CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 40000 + +#define CONFIG_CHARGER_PROFILE_OVERRIDE + +#define CONFIG_KEYBOARD_FACTORY_TEST + +/* USB-A config */ +#define GPIO_USB1_ILIM_SEL IOEX_USB_A0_CHARGE_EN_L +#define GPIO_USB2_ILIM_SEL IOEX_USB_A1_CHARGE_EN_DB_L + +/* LED */ +#undef CONFIG_LED_ONOFF_STATES + +/* Motion sensing drivers */ +#define CONFIG_ACCELGYRO_LSM6DSM +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_TABLET_MODE +#define CONFIG_GMR_TABLET_MODE +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +/* GPIO mapping from board specific name to EC common name. */ +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE + +#ifndef __ASSEMBLER__ + +/* This I2C moved. Temporarily detect and support the V0 HW. */ +extern int I2C_PORT_BATTERY; + +enum adc_channel { ADC_TEMP_SENSOR_CHARGER, ADC_TEMP_SENSOR_SOC, ADC_CH_COUNT }; + +enum battery_type { + BATTERY_SIMPLO_COS, + BATTERY_SIMPLO_HIGHPOWER, + BATTERY_SAMSUNG_SDI, + BATTERY_DYNAPACK_ATL, + BATTERY_DYNAPACK_COS, + BATTERY_COSMX, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_COUNT }; + +enum ioex_port { IOEX_C0_NCT3807 = 0, IOEX_C1_NCT3807, IOEX_PORT_COUNT }; + +#define PORT_TO_HPD(port) ((port == 0) ? GPIO_USB3_C0_DP2_HPD : GPIO_DP1_HPD) + +enum temp_sensor_id { + TEMP_SENSOR_CHARGER = 0, + TEMP_SENSOR_SOC, + TEMP_SENSOR_CPU, + TEMP_SENSOR_COUNT +}; + +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +/***************************************************************************** + * CBI EC FW Configuration + */ + +/** + * DALBOZ_MB_USBAC + * USB-A0 Speed: 5 Gbps + * Retimer: none + * USB-C0 Speed: 5 Gbps + * Retimer: none + * TCPC: NCT3807 + * PPC: AOZ1380 + * IOEX: TCPC + */ +enum ec_cfg_usb_mb_type { + DALBOZ_MB_USBAC = 0, +}; + +/** + * GUMBOZ_DB_OPT1_USBC + * USB-A1 Speed: 5 Gbps + * Retimer: PS8719 + * USB-C1 Speed: 5 Gbps + * Retimer: PS8743 + * TCPC: NCT3807 + * PPC: NX20P3483 + * IOEX: TCPC + * HDMI Exists: no + * Retimer: none + * MST Hub: none + */ +enum ec_cfg_usb_db_type { + GUMBOZ_DB_OPT1_USBC = 0, +}; + +#include "cbi_ec_fw_config.h" + +static inline bool ec_config_has_hdmi_retimer_pi3hdx1204(void) +{ + return 0; +} + +void board_reset_pd_mcu(void); + +/* Common definition for the USB PD interrupt handlers. */ +void tcpc_alert_event(enum gpio_signal signal); +void bc12_interrupt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/gumboz/build.mk b/board/gumboz/build.mk new file mode 100644 index 0000000000..45c71f962c --- /dev/null +++ b/board/gumboz/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7wc +BASEBOARD:=zork + +board-y=board.o led.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/gumboz/ec.tasklist b/board/gumboz/ec.tasklist new file mode 100644 index 0000000000..abc796f74f --- /dev/null +++ b/board/gumboz/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/gumboz/gpio.inc b/board/gumboz/gpio.inc new file mode 100644 index 0000000000..2e7e4b78a9 --- /dev/null +++ b/board/gumboz/gpio.inc @@ -0,0 +1,138 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(3, 4), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(F, 1), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_FAULT_ODL, PIN(6, 3), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(D, 4), GPIO_INT_BOTH | GPIO_PULL_UP, ppc_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(9, 3), GPIO_INT_FALLING | GPIO_PULL_UP, bc12_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_PULL_UP, bc12_interrupt) +GPIO_INT(SLP_S3_L, PIN(7, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S5_L, PIN(E, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(S0_PWROK_OD, PIN(5, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(EC_PWROK_OD, PIN(3, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(4, 4), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_WP_L, PIN(5, 0), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(VOLDN_BTN_ODL, PIN(A, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(9, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, lsm6dsm_interrupt) + +/* GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an interrupt handler. */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) + +GPIO(3AXIS_INT_L, PIN(9, 6), GPIO_INPUT | GPIO_PULL_DOWN) /* 3 Axis Accel */ +GPIO(CCD_MODE_ODL, PIN(C, 6), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(PROCHOT_ODL, PIN(D, 5), GPIO_ODR_HIGH) /* PROCHOT to SOC */ +GPIO(EC_BATT_PRES_ODL, PIN(4, 1), GPIO_INPUT) /* Battery Present */ +GPIO(EC_AP_INT_ODL, PIN(A, 3), GPIO_ODR_HIGH) /* Sensor MKBP event to SOC */ +GPIO(EN_PWR_A, PIN(B, 7), GPIO_OUT_LOW) /* Enable Power */ +GPIO(EC_EDP_BL_DISABLE, PIN(A, 2), GPIO_OUT_HIGH) /* Enable Backlight */ +GPIO(EC_ENTERING_RW, PIN(E, 5), GPIO_OUT_LOW) /* EC Entering RW */ +GPIO(EC_FCH_PWR_BTN_L, PIN(6, 7), GPIO_OUT_HIGH) /* Power Button to SOC */ +GPIO(EC_FCH_RSMRST_L, PIN(A, 1), GPIO_OUT_LOW) /* RSMRST# to SOC */ +GPIO(EC_FCH_PWROK, PIN(7, 0), GPIO_OUT_LOW) /* Power OK to SOC */ +GPIO(EC_FCH_WAKE_L, PIN(0, 3), GPIO_OUT_HIGH) /* Wake SOC */ +GPIO(EC_FCH_SCI_ODL, PIN(7, 6), GPIO_ODR_HIGH) /* SCI to SOC */ +GPIO(EC_SYS_RST_L, PIN(C, 7), GPIO_ODR_HIGH) /* Cold Reset to SOC */ +GPIO(USB_C0_TCPC_RST_L, PIN(E, 1), GPIO_OUT_HIGH) /* C0 TCPC Reset */ +GPIO(USB_C1_TCPC_RST_L, PIN(F, 0), GPIO_OUT_HIGH) /* C1 TCPC Reset */ +GPIO(USB3_C0_DP2_HPD, PIN(F, 5), GPIO_OUT_LOW) /* C0 DP Hotplug Detect */ +GPIO(DP1_HPD, PIN(F, 4), GPIO_OUT_LOW) /* C1 DP Hotplug Detect */ +GPIO(EC_H1_PACKET_MODE, PIN(8, 6), GPIO_OUT_LOW) /* H1 Packet Mode */ + +UNIMPLEMENTED(PCH_SMI_L) + +GPIO(LED_FULL_L, PIN(6, 0), GPIO_OUT_HIGH) +GPIO(LED_CHRG_L, PIN(C, 0), GPIO_OUT_HIGH) +GPIO(PWR_LED_WHITE_L, PIN(C, 3), GPIO_OUT_HIGH) + +/* + * Gumboz has 1 DB options. + * IOEX_C1_NCT3807 is the DB (USB-C1). + */ + +IOEX_INT(USB_C0_SBU_FAULT_ODL, EXPIN(IOEX_C0_NCT3807, 1, 2), GPIO_INT_FALLING, sbu_fault_interrupt) +IOEX_INT(USB_C1_SBU_FAULT_DB_ODL, EXPIN(IOEX_C1_NCT3807, 1, 2), GPIO_INT_FALLING, sbu_fault_interrupt) + +IOEX(USB_C0_FAULT_ODL, EXPIN(IOEX_C0_NCT3807, 0, 3), GPIO_ODR_HIGH) /* C0 Fault to SOC */ +IOEX(USB_C0_TCPC_FASTSW_CTL_EN, EXPIN(IOEX_C0_NCT3807, 0, 4), GPIO_OUT_LOW) /* C0 FastSwitch Control */ +IOEX(USB_C1_FAULT_ODL, EXPIN(IOEX_C0_NCT3807, 1, 0), GPIO_ODR_HIGH) /* C1 Fault to SOC */ +IOEX(USB_C0_PPC_ILIM_3A_EN, EXPIN(IOEX_C0_NCT3807, 1, 1), GPIO_OUT_LOW) /* C0 3A Current Limit Enable */ +IOEX(KB_BL_EN, EXPIN(IOEX_C0_NCT3807, 1, 3), GPIO_OUT_LOW) /* KB Backlight Enable */ +IOEX(EN_USB_A0_5V, EXPIN(IOEX_C0_NCT3807, 1, 5), GPIO_OUT_LOW) /* A0 5V Source Enable */ +IOEX(USB_A0_CHARGE_EN_L, EXPIN(IOEX_C0_NCT3807, 1, 6), GPIO_OUT_HIGH) /* A0 5V High Current Enable */ +IOEX(USB_C0_SBU_FLIP, EXPIN(IOEX_C0_NCT3807, 1, 7), GPIO_OUT_LOW) /* C0 SBU Flip */ + +IOEX(USB_A1_RETIMER_EN, EXPIN(IOEX_C1_NCT3807, 0, 0), GPIO_OUT_LOW) /* A1 Retimer Enable */ +IOEX(USB_C1_HPD_IN_DB, EXPIN(IOEX_C1_NCT3807, 0, 2), GPIO_OUT_LOW) /* C1 HPD */ +IOEX(USB_C1_TCPC_FASTSW_CTL_EN, EXPIN(IOEX_C1_NCT3807, 0, 4), GPIO_OUT_LOW) /* C1 FastSwitch Control */ +IOEX(USB_C1_PPC_EN_L, EXPIN(IOEX_C1_NCT3807, 1, 3), GPIO_OUT_LOW) /* C1 PPC Enable */ +IOEX(USB_C1_DATA_EN, EXPIN(IOEX_C1_NCT3807, 1, 5), GPIO_OUT_HIGH) /* C1 Retimer Enable */ +IOEX(EN_USB_A1_5V_DB, EXPIN(IOEX_C1_NCT3807, 1, 6), GPIO_OUT_LOW) /* A1 5V Source Enable */ +IOEX(USB_A1_CHARGE_EN_DB_L,EXPIN(IOEX_C1_NCT3807, 1, 7), GPIO_OUT_HIGH) /* A1 5V High Current Enable */ +IOEX(C1_CHARGER_LED_WHITE_DB,EXPIN(IOEX_C1_NCT3807, 1, 0), GPIO_OUT_HIGH) /* C1 Charge LED White */ +IOEX(C1_CHARGER_LED_AMBER_DB,EXPIN(IOEX_C1_NCT3807, 1, 4), GPIO_OUT_HIGH) /* C1 Charge LED Amber */ + + +/* + * The NPCX LPC driver configures and controls SCI, so PCH_SCI_ODL [PIN(7, 6)] + * is not defined here as GPIO. + */ + +/* I2C pins - these will be reconfigured for alternate function below */ +GPIO(EC_I2C_USB_A0_C0_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_C0_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_A1_C1_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_A1_C1_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_POWER_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USBC_AP_MUX_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USBC_AP_MUX_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(FCH_SIC, PIN(F, 3), GPIO_INPUT) +GPIO(FCH_SID, PIN(F, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_CBI_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_CBI_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(I2C_AUDIO_USB_HUB_SCL, PIN(E, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(I2C_AUDIO_USB_HUB_SDA, PIN(E, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_BATT_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_BATT_SDA, PIN(B, 2), GPIO_INPUT) + +ALTERNATE(PIN_MASK(6, BIT(4) | BIT(5)), 0, MODULE_UART, 0) /* Cr50 requires no pullups. */ + +ALTERNATE(PIN_MASK(B, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(9, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ +ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, BIT(0) | BIT(1)), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(F, BIT(2) | BIT(3)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(E, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C6 */ +ALTERNATE(PIN_MASK(B, BIT(2) | BIT(3)), 0, MODULE_I2C, 0) /* I2C7 */ + +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC2, ADC3 Temp Sensors */ + +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* PWM3 KB Backlight */ + +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT) /* KSI_00-01 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT) /* KSI_02-07 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 inverted */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ +ALTERNATE(PIN_MASK(0, 0xE0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-12 */ + +/* Power Switch Logic (PSL) inputs */ +ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* AC_PRESENT, POWER_BUTTON_L, EC_RST_ODL */ +ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* LID_OPEN */ + +ALTERNATE(PIN_MASK(A, 0xA0), 1, MODULE_WOV, 0) /* I2S_SYNC/I2S_SCLK GPIOA5/A7 */ +ALTERNATE(PIN_MASK(B, 0x01), 1, MODULE_WOV, 0) /* I2S_SDAT GPIOB0 */ +ALTERNATE(PIN_MASK(9, 0x90), 1, MODULE_WOV, 0) /* DMIC_CLK/DMIC_IN GPIO94/97 */ diff --git a/board/gumboz/led.c b/board/gumboz/led.c new file mode 100644 index 0000000000..9fa8c9bfb9 --- /dev/null +++ b/board/gumboz/led.c @@ -0,0 +1,234 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "cros_board_info.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +#define LED_TICKS_PER_CYCLE 10 +#define LED_ON_TICKS 5 + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +enum led_port { LEFT_PORT = 0, RIGHT_PORT }; + +static void led_set_color_battery(int port, enum led_color color) +{ + int amber_led, white_led; + uint32_t board_ver = 0; + int led_batt_on_lvl, led_batt_off_lvl; + + cbi_get_board_version(&board_ver); + amber_led = (port == LEFT_PORT ? GPIO_LED_CHRG_L : + IOEX_C1_CHARGER_LED_AMBER_DB); + white_led = (port == LEFT_PORT ? GPIO_LED_FULL_L : + IOEX_C1_CHARGER_LED_WHITE_DB); + + if ((board_ver >= 2) && (port == RIGHT_PORT)) { + led_batt_on_lvl = 1; + led_batt_off_lvl = 0; + } else { + led_batt_on_lvl = 0; + led_batt_off_lvl = 1; + } + + switch (color) { + case LED_WHITE: + gpio_or_ioex_set_level(white_led, led_batt_on_lvl); + gpio_or_ioex_set_level(amber_led, led_batt_off_lvl); + break; + case LED_AMBER: + gpio_or_ioex_set_level(white_led, led_batt_off_lvl); + gpio_or_ioex_set_level(amber_led, led_batt_on_lvl); + break; + case LED_OFF: + gpio_or_ioex_set_level(white_led, led_batt_off_lvl); + gpio_or_ioex_set_level(amber_led, led_batt_off_lvl); + break; + default: + break; + } +} + +void led_set_color_power(enum led_color color) +{ + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_OFF); + break; + case LED_WHITE: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_ON); + break; + default: + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_RIGHT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_POWER_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + break; + default: + break; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LEFT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LEFT_PORT, LED_AMBER); + else + led_set_color_battery(LEFT_PORT, LED_OFF); + break; + case EC_LED_ID_RIGHT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(RIGHT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(RIGHT_PORT, LED_AMBER); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + break; + case EC_LED_ID_POWER_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(LED_WHITE); + else + led_set_color_power(LED_OFF); + break; + default: + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + led_set_color_battery(RIGHT_PORT, + (port == RIGHT_PORT) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, + (port == LEFT_PORT) ? color : LED_OFF); +} + +static void led_set_battery(void) +{ + static int battery_ticks; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + if (charge_get_percent() < 10) + led_set_color_battery( + RIGHT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, LED_OFF); + break; + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +static void led_set_power(void) +{ + static int power_tick; + + power_tick++; + + if (chipset_in_state(CHIPSET_STATE_ON)) + led_set_color_power(LED_WHITE); + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + led_set_color_power( + (power_tick % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); + else + led_set_color_power(LED_OFF); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + led_set_power(); + + led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/gumboz/vif_override.xml b/board/gumboz/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/gumboz/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/guybrush/battery.c b/board/guybrush/battery.c new file mode 100644 index 0000000000..e7163c8a11 --- /dev/null +++ b/board/guybrush/battery.c @@ -0,0 +1,127 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" + +/* + * Battery info for all Guybrush battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* AEC 5477109 */ + [BATTERY_AEC] = { + .fuel_gauge = { + .manuf_name = "AEC", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .sleep_mode = { + .sleep_supported = true, + .reg_addr = 0x00, + .reg_data = 0x0011, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 8700, /* mV */ + .voltage_normal = 7600, + .voltage_min = 6000, + .precharge_current = 100, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + /* AP18F4M / LIS4163ACPC */ + [BATTERY_AP18F4M] = { + .fuel_gauge = { + .manuf_name = "Murata KT00404001", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 8700, /* mV */ + .voltage_normal = 7600, + .voltage_min = 5500, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* POW-TECH Battery Information */ + [BATTERY_POWER_TECH] = { + .fuel_gauge = { + .manuf_name = "POW-TECH", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x10, 0x10 }, + }, + .sleep_mode = { + .sleep_supported = true, + .reg_addr = 0x00, + .reg_data = 0x0011, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 88, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AP18F4M; diff --git a/board/guybrush/board.c b/board/guybrush/board.c new file mode 100644 index 0000000000..cbe1049d98 --- /dev/null +++ b/board/guybrush/board.c @@ -0,0 +1,535 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush board-specific configuration */ + +#include "adc.h" +#include "base_fw_config.h" +#include "board_fw_config.h" +#include "builtin/assert.h" +#include "button.h" +#include "common.h" +#include "cros_board_info.h" +#include "driver/accel_bma422.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_bmi323.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/retimer/ps8811.h" +#include "driver/retimer/ps8818_public.h" +#include "driver/temp_sensor/sb_tsi.h" +#include "driver/temp_sensor/tmp112.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "temp_sensor/tmp112.h" +#include "thermal.h" +#include "usb_mux.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Motion sensor mutex */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Motion sensor private data */ +static struct bmi_drv_data_t g_bmi_data; +static struct accelgyro_saved_data_t g_bma422_data; + +/* Matrix to rotate accelrator into standard reference frame */ +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_PRIMARY, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .default_range = 2, /* g, enough for laptop. */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI323, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi3xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI3_ADDR_I2C_PRIM, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI323, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi3xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI3_ADDR_I2C_PRIM, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t bmi160_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, +}; + +struct motion_sensor_t bmi160_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, +}; + +__override enum ec_error_list +board_a1_ps8811_retimer_init(const struct usb_mux *me) +{ + /* Set channel A output swing */ + RETURN_ERROR(ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, PS8811_REG1_USB_CHAN_A_SWING, + PS8811_CHAN_A_SWING_MASK, 0x2 << PS8811_CHAN_A_SWING_SHIFT)); + + /* Set channel B output swing */ + RETURN_ERROR(ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, PS8811_REG1_USB_CHAN_B_SWING, + PS8811_CHAN_B_SWING_MASK, 0x2 << PS8811_CHAN_B_SWING_SHIFT)); + + /* Set channel B de-emphasis to -6dB and pre-shoot to 1.5 dB */ + RETURN_ERROR(ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, PS8811_REG1_USB_CHAN_B_DE_PS_LSB, + PS8811_CHAN_B_DE_PS_LSB_MASK, PS8811_CHAN_B_DE_6_PS_1_5_LSB)); + + RETURN_ERROR(ps8811_i2c_field_update( + me, PS8811_REG_PAGE1, PS8811_REG1_USB_CHAN_B_DE_PS_MSB, + PS8811_CHAN_B_DE_PS_MSB_MASK, PS8811_CHAN_B_DE_6_PS_1_5_MSB)); + + return EC_SUCCESS; +} + +__override int board_c1_ps8818_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + /* Set the RX input termination */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_RX_PHY, + PS8818_RX_INPUT_TERM_MASK, + PS8818_RX_INPUT_TERM_112_OHM); + if (rv) + return rv; + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* Boost the DP gain */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_DPEQ_LEVEL, + PS8818_DPEQ_LEVEL_UP_MASK, + PS8818_DPEQ_LEVEL_UP_19DB); + if (rv) + return rv; + + /* Enable HPD on the DB */ + ioex_set_level(IOEX_USB_C1_IN_HPD, 1); + } else { + /* Disable HPD on the DB */ + ioex_set_level(IOEX_USB_C1_IN_HPD, 0); + } + + return rv; +} + +/* + * ANX7491(A1) and ANX7451(C1) are on the same i2c bus. Both default + * to 0x29 for the USB i2c address. This moves ANX7451(C1) USB i2c + * address to 0x2A. ANX7491(A1) will stay at the default 0x29. + */ +uint16_t board_anx7451_get_usb_i2c_addr(const struct usb_mux *me) +{ + ASSERT(me->usb_port == USBC_PORT_C1); + return 0x2a; +} + +/* + * Base Gyro Sensor dynamic configuration + */ +static int base_gyro_config; + +static void board_update_motion_sensor_config(void) +{ + if (board_is_convertible()) { + if (get_board_version() == 1) { + motion_sensors[BASE_ACCEL] = bmi160_base_accel; + motion_sensors[BASE_GYRO] = bmi160_base_gyro; + base_gyro_config = BASE_GYRO_BMI160; + ccprints("BASE GYRO is BMI160"); + } else { + base_gyro_config = BASE_GYRO_BMI323; + ccprints("BASE GYRO is BMI323"); + } + + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable Base Accel and Gyro interrupt */ + gpio_enable_interrupt(GPIO_6AXIS_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + } +} + +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_gyro_config) { + case BASE_GYRO_BMI160: + bmi160_interrupt(signal); + break; + case BASE_GYRO_BMI323: + default: + bmi3xx_interrupt(signal); + break; + } +} + +static void board_init(void) +{ + board_update_motion_sensor_config(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_chipset_startup(void) +{ + if (get_board_version() > 1) + tmp112_init(); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +int board_get_soc_temp_k(int idx, int *temp_k) +{ + uint32_t board_version = get_board_version(); + + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + + if (board_version == 1) + return get_temp_3v3_30k9_47k_4050b(ADC_TEMP_SENSOR_SOC, temp_k); + + return tmp112_get_val_k(idx, temp_k); +} + +int board_get_soc_temp_mk(int *temp_mk) +{ + uint32_t board_version = get_board_version(); + + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + + if (board_version == 1) + return EC_ERROR_UNIMPLEMENTED; + + return tmp112_get_val_mk(TMP112_SOC, temp_mk); +} + +int board_get_ambient_temp_mk(int *temp_mk) +{ + uint32_t board_version = get_board_version(); + + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + + if (board_version == 1) + return EC_ERROR_UNIMPLEMENTED; + + return tmp112_get_val_mk(TMP112_AMB, temp_mk); +} + +/* ADC Channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_SOC] = { + .name = "SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_CHARGER] = { + .name = "CHARGER", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_MEMORY] = { + .name = "MEMORY", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_CORE_IMON1] = { + .name = "CORE_I", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SOC_IMON2] = { + .name = "SOC_I", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temp Sensors */ +static int board_get_memory_temp(int, int *); + +const struct tmp112_sensor_t tmp112_sensors[] = { + { I2C_PORT_SENSOR, TMP112_I2C_ADDR_FLAGS0 }, + { I2C_PORT_SENSOR, TMP112_I2C_ADDR_FLAGS1 }, +}; +BUILD_ASSERT(ARRAY_SIZE(tmp112_sensors) == TMP112_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_SOC] = { + .name = "SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = board_get_soc_temp_k, + .idx = TMP112_SOC, + }, + [TEMP_SENSOR_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER, + }, + [TEMP_SENSOR_MEMORY] = { + .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = board_get_memory_temp, + .idx = ADC_TEMP_SENSOR_MEMORY, + }, + [TEMP_SENSOR_CPU] = { + .name = "CPU", + .type = TEMP_SENSOR_TYPE_CPU, + .read = sb_tsi_get_val, + .idx = 0, + }, + [TEMP_SENSOR_AMBIENT] = { + .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = tmp112_get_val_k, + .idx = TMP112_AMB, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT] = { + [TEMP_SENSOR_SOC] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(100), + [EC_TEMP_THRESH_HALT] = C_TO_K(105), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + }, + .temp_fan_off = C_TO_K(25), + .temp_fan_max = C_TO_K(70), + }, + [TEMP_SENSOR_CHARGER] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(100), + [EC_TEMP_THRESH_HALT] = C_TO_K(105), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + }, + .temp_fan_off = 0, + .temp_fan_max = 0, + }, + [TEMP_SENSOR_MEMORY] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(100), + [EC_TEMP_THRESH_HALT] = C_TO_K(105), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + }, + .temp_fan_off = 0, + .temp_fan_max = 0, + }, + [TEMP_SENSOR_CPU] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(100), + [EC_TEMP_THRESH_HALT] = C_TO_K(105), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + }, + /* + * CPU temp sensor fan thresholds are high because they are a + * backup for the SOC temp sensor fan thresholds. + */ + .temp_fan_off = C_TO_K(60), + .temp_fan_max = C_TO_K(90), + }, + /* + * Note: Leave ambient entries at 0, both as it does not represent a + * hotspot and as not all boards have this sensor + */ +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +static int board_get_memory_temp(int idx, int *temp_k) +{ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + return get_temp_3v3_30k9_47k_4050b(idx, temp_k); +} diff --git a/board/guybrush/board.h b/board/guybrush/board.h new file mode 100644 index 0000000000..094b98f23e --- /dev/null +++ b/board/guybrush/board.h @@ -0,0 +1,104 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* Motion sensing drivers */ + +/* Keyboard features */ +#define CONFIG_KEYBOARD_FACTORY_TEST + +/* Sensors */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_BMI3XX +#define CONFIG_ACCELGYRO_BMI3XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCEL_BMA4XX + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +/* EC console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_CMD_BUTTON + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_MUX_ANX7451 +#define CONFIG_USBC_RETIMER_ANX7451 + +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 +/* Max Power = 100 W */ +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) + +/* USB Type A Features */ + +/* BC 1.2 */ + +/* Volume Button feature */ + +/* Fan features */ + +/* LED features */ +#define CONFIG_LED_COMMON +#define CONFIG_LED_ONOFF_STATES + +/* Thermal Config */ +#define CONFIG_TEMP_SENSOR_TMP112 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +/* Motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); + +/* Battery Types */ +enum battery_type { + BATTERY_AEC, + BATTERY_AP18F4M, + BATTERY_POWER_TECH, + BATTERY_TYPE_COUNT, +}; + +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI160 = 1, + BASE_GYRO_BMI323 = 2, +}; + +/* ADC Channels */ +enum adc_channel { + ADC_TEMP_SENSOR_SOC = 0, + ADC_TEMP_SENSOR_CHARGER, + ADC_TEMP_SENSOR_MEMORY, + ADC_CORE_IMON1, + ADC_SOC_IMON2, + ADC_CH_COUNT +}; + +/* Temp Sensors */ +enum temp_sensor_id { + TEMP_SENSOR_SOC = 0, + TEMP_SENSOR_CHARGER, + TEMP_SENSOR_MEMORY, + TEMP_SENSOR_CPU, + TEMP_SENSOR_AMBIENT, + TEMP_SENSOR_COUNT +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/guybrush/board_fw_config.c b/board/guybrush/board_fw_config.c new file mode 100644 index 0000000000..0484b82461 --- /dev/null +++ b/board/guybrush/board_fw_config.c @@ -0,0 +1,43 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "base_fw_config.h" +#include "board_fw_config.h" + +bool board_is_convertible(void) +{ + return (get_fw_config_field(FW_CONFIG_FORM_FACTOR_OFFSET, + FW_CONFIG_FORM_FACTOR_WIDTH) == + FW_CONFIG_FORM_FACTOR_CONVERTIBLE); +} + +bool board_has_kblight(void) +{ + return (get_fw_config_field(FW_CONFIG_KBLIGHT_OFFSET, + FW_CONFIG_KBLIGHT_WIDTH) == + FW_CONFIG_KBLIGHT_YES); +} + +enum board_usb_c1_mux board_get_usb_c1_mux(void) +{ + int usb_db = get_fw_config_field(FW_CONFIG_USB_DB_OFFSET, + FW_CONFIG_USB_DB_WIDTH); + if (usb_db == FW_CONFIG_USB_DB_A1_PS8811_C1_PS8818) + return USB_C1_MUX_PS8818; + if (usb_db == FW_CONFIG_USB_DB_A1_ANX7491_C1_ANX7451) + return USB_C1_MUX_ANX7451; + return USB_C1_MUX_UNKNOWN; +}; + +enum board_usb_a1_retimer board_get_usb_a1_retimer(void) +{ + int usb_db = get_fw_config_field(FW_CONFIG_USB_DB_OFFSET, + FW_CONFIG_USB_DB_WIDTH); + if (usb_db == FW_CONFIG_USB_DB_A1_PS8811_C1_PS8818) + return USB_A1_RETIMER_PS8811; + if (usb_db == FW_CONFIG_USB_DB_A1_ANX7491_C1_ANX7451) + return USB_A1_RETIMER_ANX7491; + return USB_A1_RETIMER_UNKNOWN; +}; diff --git a/board/guybrush/board_fw_config.h b/board/guybrush/board_fw_config.h new file mode 100644 index 0000000000..4477aca6fd --- /dev/null +++ b/board/guybrush/board_fw_config.h @@ -0,0 +1,37 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _GUYBRUSH_BOARD_FW_CONFIG__H_ +#define _GUYBRUSH_BOARD_FW_CONFIG__H_ + +/**************************************************************************** + * Guybrush CBI FW Configuration + */ + +/* + * USB Daughter Board (2 bits) + */ +#define FW_CONFIG_USB_DB_OFFSET 0 +#define FW_CONFIG_USB_DB_WIDTH 2 +#define FW_CONFIG_USB_DB_A1_PS8811_C1_PS8818 0 +#define FW_CONFIG_USB_DB_A1_ANX7491_C1_ANX7451 1 + +/* + * Form Factor (1 bits) + */ +#define FW_CONFIG_FORM_FACTOR_OFFSET 2 +#define FW_CONFIG_FORM_FACTOR_WIDTH 1 +#define FW_CONFIG_FORM_FACTOR_CLAMSHELL 0 +#define FW_CONFIG_FORM_FACTOR_CONVERTIBLE 1 + +/* + * Keyboard Backlight (1 bit) + */ +#define FW_CONFIG_KBLIGHT_OFFSET 3 +#define FW_CONFIG_KBLIGHT_WIDTH 1 +#define FW_CONFIG_KBLIGHT_NO 0 +#define FW_CONFIG_KBLIGHT_YES 1 + +#endif /* _GUYBRUSH_CBI_FW_CONFIG__H_ */ diff --git a/board/guybrush/build.mk b/board/guybrush/build.mk new file mode 100644 index 0000000000..806e8988a2 --- /dev/null +++ b/board/guybrush/build.mk @@ -0,0 +1,12 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +BASEBOARD:=guybrush + +board-y=board.o +board-y+=board_fw_config.o led.o battery.o thermal.o diff --git a/board/guybrush/ec.tasklist b/board/guybrush/ec.tasklist new file mode 100644 index 0000000000..7a64850dfb --- /dev/null +++ b/board/guybrush/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, VENTI_TASK_STACK_SIZE) diff --git a/board/guybrush/gpio.inc b/board/guybrush/gpio.inc new file mode 100644 index 0000000000..ffc567b261 --- /dev/null +++ b/board/guybrush/gpio.inc @@ -0,0 +1,28 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the board GPIOs that we care about. */ + +#include "base_gpio.inc" + +GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, motion_interrupt) /* 6 Axis IMU */ +GPIO_INT(TABLET_MODE, PIN(C, 1), GPIO_INT_BOTH, gmr_tablet_switch_isr) /* 360 Tablet Mode */ + +/* LED Signals */ +ALTERNATE(/*EC_PWM_LED_CHRG_L*/ PIN_MASK(C, BIT(4)), 0, MODULE_PWM, 0) /* Charging LED */ +ALTERNATE(/*EC_PWM_LED_FULL_L*/ PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* Full LED */ + +/* Test Points */ +GPIO(EC_GPIO56, PIN(5, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PS2_CLK, PIN(6, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PS2_DAT, PIN(7, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PS2_RST, PIN(6, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_GPIOB0, PIN(B, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_GPIO81, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_FLPRG2, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PSL_GPO, PIN(D, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PWM7, PIN(6, 0), GPIO_INPUT | GPIO_PULL_UP) \ No newline at end of file diff --git a/board/guybrush/led.c b/board/guybrush/led.c new file mode 100644 index 0000000000..c61886de15 --- /dev/null +++ b/board/guybrush/led.c @@ -0,0 +1,99 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Guybrush specific PWM LED settings. + */ + +#include "common.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "pwm.h" + +/* Note PWM LEDs are active low */ +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +#define CPRINTS(format, args...) cprints(CC_PWM, format, ##args) + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + pwm_enable(PWM_CH_LED_CHRG, LED_ON_LVL); + pwm_enable(PWM_CH_LED_FULL, LED_OFF_LVL); + break; + case EC_LED_COLOR_WHITE: + pwm_enable(PWM_CH_LED_CHRG, LED_OFF_LVL); + pwm_enable(PWM_CH_LED_FULL, LED_ON_LVL); + break; + case LED_OFF: + pwm_enable(PWM_CH_LED_CHRG, LED_OFF_LVL); + pwm_enable(PWM_CH_LED_FULL, LED_OFF_LVL); + break; + default: /* Unsupported colors */ + CPRINTS("Unsupported LED color: %d", color); + pwm_enable(PWM_CH_LED_CHRG, LED_OFF_LVL); + pwm_enable(PWM_CH_LED_FULL, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } else { + CPRINTS("Unsupported LED set: %d", led_id); + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} diff --git a/board/guybrush/thermal.c b/board/guybrush/thermal.c new file mode 100644 index 0000000000..5bb1295f84 --- /dev/null +++ b/board/guybrush/thermal.c @@ -0,0 +1,34 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush board-specific configuration */ + +#include "console.h" +#include "fan.h" +#include "thermal.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = GPIO_S0_PGOOD, + .enable_gpio = -1, +}; +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1000, + .rpm_start = 1000, + .rpm_max = 6500, +}; +const struct fan_t fans[] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); diff --git a/board/guybrush/vif_override.xml b/board/guybrush/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/guybrush/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/haboki/battery.c b/board/haboki/battery.c new file mode 100644 index 0000000000..72ad9ad6cb --- /dev/null +++ b/board/haboki/battery.c @@ -0,0 +1,349 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all haboki battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* DynaPack CosMX Battery Information */ + [BATTERY_DYNAPACK_COS] = { + .fuel_gauge = { + .manuf_name = "333-2C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack ATL Battery Information */ + [BATTERY_DYNAPACK_ATL] = { + .fuel_gauge = { + .manuf_name = "333-27-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack HIGHPOWER Battery Information */ + [BATTERY_DYNAPACK_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-2D-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack BYD Battery Information */ + [BATTERY_DYNAPACK_BYD] = { + .fuel_gauge = { + .manuf_name = "333-2E-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Samsung SDI Battery Information */ + [BATTERY_SAMSUNG_SDI] = { + .fuel_gauge = { + .manuf_name = "333-54-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Simplo CosMX Battery Information */ + [BATTERY_SIMPLO_COS] = { + .fuel_gauge = { + .manuf_name = "333-1C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Simplo HIGHPOWER Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-1D-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* CosMX Battery Information */ + [BATTERY_COS] = { + .fuel_gauge = { + .manuf_name = "333-AC-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* CosMX B00C4473A9D0002 Battery Information */ + [BATTERY_COS_2] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* ATL GB-S20-4473A9-01H&020H Battery Information + * Gauge IC : RAJ240045 + */ + [BATTERY_ATL] = { + .fuel_gauge = { + .manuf_name = "313-B7-0D-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x43, + .reg_mask = 0x0003, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; diff --git a/board/haboki/board.c b/board/haboki/board.c new file mode 100644 index 0000000000..74cf39483b --- /dev/null +++ b/board/haboki/board.c @@ -0,0 +1,691 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Haboki board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "cros_board_info.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/sm5803.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +uint32_t board_version; + +/* GPIO to enable/disable the USB Type-A port. */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +__override void board_process_pd_alert(int port) +{ + /* + * PD_INT task will process this alert, and that task is only needed on + * C1. + */ + if (port != 1) + return; + + if (gpio_get_level(GPIO_USB_C1_INT_ODL)) + return; + + sm5803_handle_interrupt(port); +} + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + sm5803_interrupt(0); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void button_sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + int hdmi_hpd = gpio_get_level(GPIO_VOLUP_BTN_ODL_HDMI_HPD); + + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, hdmi_hpd); + else + button_interrupt(s); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +static void pen_detect_interrupt(enum gpio_signal s) +{ + int pen_detect = !gpio_get_level(GPIO_PEN_DET_ODL); + + gpio_set_level(GPIO_EN_PP5000_PEN, pen_detect); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_SUB_ANALOG] = { .name = "SUB_ANALOG", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, + [ADC_TEMP_SENSOR_4] = { .name = "TEMP_SENSOR4", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH16 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + [CHARGER_PRIMARY] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS, + .drv = &sm5803_drv, + }, + [CHARGER_SECONDARY] = { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS, + .drv = &sm5803_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &it83xx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, +}; + +/* Sensor Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Sensor Data */ +static struct accelgyro_saved_data_t g_bma253_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* Matrix to rotate accelrator into standard reference frame */ +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* Drivers */ +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void board_init(void) +{ + int on; + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) { + /* Select HDMI option */ + gpio_set_level(GPIO_HDMI_SEL_L, 0); + } else { + /* Select AUX option */ + gpio_set_level(GPIO_HDMI_SEL_L, 1); + } + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_INT_ODL); + + /* Store board version for use in determining charge limits */ + cbi_get_board_version(&board_version); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) + hook_call_deferred(&check_c1_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_PRESENT) { + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable Base Accel interrupt */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } + + gpio_enable_interrupt(GPIO_PEN_DET_ODL); + + /* Make sure pen detection is triggered or not at sysjump */ + if (!gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_EN_PP5000_PEN, 1); + + /* Charger on the MB will be outputting PROCHOT_ODL and OD CHG_DET */ + sm5803_configure_gpio0(CHARGER_PRIMARY, GPIO0_MODE_PROCHOT, 1); + sm5803_configure_chg_det_od(CHARGER_PRIMARY, 1); + + if (board_get_charger_chip_count() > 1) { + /* Charger on the sub-board will be a push-pull GPIO */ + sm5803_configure_gpio0(CHARGER_SECONDARY, GPIO0_MODE_OUTPUT, 0); + } + + /* Turn on 5V if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_resume(void) +{ + sm5803_disable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_disable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); + +static void board_suspend(void) +{ + sm5803_enable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_enable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Put all charger ICs present into low power mode before entering + * z-state. + */ + sm5803_hibernate(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_hibernate(CHARGER_SECONDARY); +} + +__override void board_ocpc_init(struct ocpc_data *ocpc) +{ + /* There's no provision to measure Isys */ + ocpc->chg_flags[CHARGER_SECONDARY] |= OCPC_NO_ISYS_MEAS_CAP; +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + + if (board_get_charger_chip_count() > 1) { + if (sm5803_set_gpio0_level(1, !!enable)) + CPRINTUSB("Failed to %sable sub rails!", + enable ? "en" : "dis"); + } +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) + return CONFIG_USB_PD_PORT_MAX_COUNT; + + ccprints("Unhandled DB configuration: %d", db); + return 0; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) + return CHARGER_NUM - 1; + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) + return CHARGER_NUM; + + ccprints("Unhandled DB configuration: %d", db); + return 0; +} + +uint16_t tcpc_get_alert_status(void) +{ + /* + * TCPC 0 is embedded in the EC and processes interrupts in the chip + * code (it83xx/intc.c) + */ + + uint16_t status = 0; + int regval; + + /* Check whether TCPC 1 pulled the shared interrupt line */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Limit C1 on board version 0 to 2.0 A */ + if ((board_version == 0) && (port == 1)) + charge_ma = MIN(charge_ma, 2000); + /* + * TODO(b/151955431): Characterize the input current limit in case a + * scaling needs to be applied here + */ + charge_set_input_current_limit(charge_ma, charge_mv); +} + +int board_set_active_charge_port(int port) +{ + int is_valid_port = (port >= 0 && port < board_get_usb_pd_port_count()); + + if (!is_valid_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTUSB("Disabling all charge ports"); + + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 0); + + if (board_get_charger_chip_count() > 1) + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 0); + + return EC_SUCCESS; + } + + CPRINTUSB("New chg p%d", port); + + /* + * Ensure other port is turned off, then enable new charge port + */ + if (port == 0) { + if (board_get_charger_chip_count() > 1) + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 0); + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 1); + + } else { + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 0); + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 1); + } + + return EC_SUCCESS; +} + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* Vconn control is only for port 0 */ + if (port) + return; + + if (cc_pin == USBPD_CC_PIN_1) + gpio_set_level(GPIO_EN_USB_C0_CC1_VCONN, !!enabled); + else + gpio_set_level(GPIO_EN_USB_C0_CC2_VCONN, !!enabled); +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + int current; + + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + current = (rp == TYPEC_RP_3A0) ? 3000 : 1500; + + charger_set_otg_current_voltage(port, current, 5000); +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 10000, + } }; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "5V regular", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 3; + *kp_div = 20; + + *ki = 3; + *ki_div = 125; + + *kd = 4; + *kd_div = 40; +} + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { GPIO_KSO_H, 4 }, { GPIO_KSO_H, 0 }, + { GPIO_KSO_H, 1 }, { GPIO_KSO_H, 3 }, { GPIO_KSO_H, 2 }, + { GPIO_KSO_L, 5 }, { GPIO_KSO_L, 6 }, { GPIO_KSO_L, 3 }, + { GPIO_KSO_L, 2 }, { GPIO_KSI, 0 }, { GPIO_KSO_L, 1 }, + { GPIO_KSO_L, 4 }, { GPIO_KSI, 3 }, { GPIO_KSI, 2 }, + { GPIO_KSO_L, 0 }, { GPIO_KSI, 5 }, { GPIO_KSI, 4 }, + { GPIO_KSO_L, 7 }, { GPIO_KSI, 6 }, { GPIO_KSI, 7 }, + { GPIO_KSI, 1 }, { -1, -1 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/haboki/board.h b/board/haboki/board.h new file mode 100644 index 0000000000..0365d094ea --- /dev/null +++ b/board/haboki/board.h @@ -0,0 +1,149 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Haboki board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_KEEBY_EC_IT8320 +#include "baseboard.h" + +#undef GPIO_VOLUME_UP_L +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL_HDMI_HPD + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 15000 +#define CONFIG_USB_PD_VBUS_DETECT_CHARGER +#define CONFIG_USB_PD_5V_CHARGER_CTRL +#define CONFIG_CHARGER_OTG +#undef CONFIG_CHARGER_SINGLE_CHIP +#define CONFIG_OCPC +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 21 /* R_DS(on) 10.7mOhm + 10mOhm sns rstr \ + */ + +/* PWM */ +#define CONFIG_PWM + +/* Sensors */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* Power of 2 - Too large of a fifo causes too much timestamp jitter */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* Keyboard */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_PWM_KBLIGHT + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_TCPM_PS8705 /* C1: PS8705 TCPC*/ +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_SUB_ANALOG, /* ADC13 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_TEMP_SENSOR_4, /* ADC16 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_4, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_DYNAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_DYNAPACK_HIGHPOWER, + BATTERY_DYNAPACK_BYD, + BATTERY_SAMSUNG_SDI, + BATTERY_SIMPLO_COS, + BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COS, + BATTERY_COS_2, + BATTERY_ATL, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/haboki/build.mk b/board/haboki/build.mk new file mode 100644 index 0000000000..4362df50a4 --- /dev/null +++ b/board/haboki/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=keeby + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/haboki/cbi_ssfc.c b/board/haboki/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/haboki/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/haboki/cbi_ssfc.h b/board/haboki/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/haboki/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/haboki/ec.tasklist b/board/haboki/ec.tasklist new file mode 100644 index 0000000000..c13df44543 --- /dev/null +++ b/board/haboki/ec.tasklist @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/haboki/gpio.inc b/board/haboki/gpio.inc new file mode 100644 index 0000000000..8ecc458a19 --- /dev/null +++ b/board/haboki/gpio.inc @@ -0,0 +1,148 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(USB_C1_INT_ODL, PIN(E, 6), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c1_interrupt) /* TCPC, charger, BC12 */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL_HDMI_HPD, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_sub_hdmi_hpd_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(PEN_DET_ODL, PIN(J, 1), GPIO_INT_BOTH | GPIO_PULL_UP, pen_detect_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EN_USB_A_5V, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC1_VCONN, PIN(H, 4), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC2_VCONN, PIN(H, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(USB_C0_FRS, PIN(C, 4), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_HIGH) + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc pins which will run to the I/O board */ +GPIO(EC_SUB_IO_1_2, PIN(F, 0), GPIO_INPUT) +GPIO(EC_SUB_IO_2_1, PIN(F, 1), GPIO_INPUT) + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(C, 7), GPIO_OUT_LOW) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(EN_KB_BL, PIN(J, 3), GPIO_OUT_LOW) /* Currently unused */ +GPIO(EN_PP5000_PEN, PIN(B, 5), GPIO_OUT_LOW) +GPIO(EC_CBI_WP, PIN(H, 5), GPIO_OUT_LOW) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG0_NC, PIN(G, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH1_NC, PIN(H, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* LED */ +GPIO(BAT_LED_AMBER_L, PIN(A, 1), GPIO_OUT_HIGH) +GPIO(BAT_LED_WHITE_L, PIN(A, 2), GPIO_OUT_HIGH) +GPIO(PWR_LED_WHITE_L, PIN(A, 3), GPIO_OUT_HIGH) + +/* Alternate functions GPIO definitions */ +/* Keyboard */ +ALTERNATE(PIN_MASK(KSI, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSI0-7 */ +ALTERNATE(PIN_MASK(KSO_H, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO8-15 */ +ALTERNATE(PIN_MASK(KSO_L, 0xFB), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO0-1, 3-7 */ +GPIO(EC_KSO_02_INV, PIN(KSO_L, 2), GPIO_OUT_HIGH) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC13: EC_SUB_ANALOG, ADC15: TEMP_SENSOR_3, ADC16: TEMP_SENSOR_4 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(0)), 0, MODULE_PWM, 0) /* KB_BL_PWM */ diff --git a/board/haboki/led.c b/board/haboki/led.c new file mode 100644 index 0000000000..e353ba6f77 --- /dev/null +++ b/board/haboki/led.c @@ -0,0 +1,200 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Haboki specific LED settings. */ + +#include "cbi_fw_config.h" +#include "charge_state.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static int led_set_color_battery(enum led_color color) +{ + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_BAT_LED_WHITE_L, BAT_LED_OFF); + gpio_set_level(GPIO_BAT_LED_AMBER_L, BAT_LED_OFF); + break; + case LED_WHITE: + gpio_set_level(GPIO_BAT_LED_WHITE_L, BAT_LED_ON); + gpio_set_level(GPIO_BAT_LED_AMBER_L, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(GPIO_BAT_LED_WHITE_L, BAT_LED_OFF); + gpio_set_level(GPIO_BAT_LED_AMBER_L, BAT_LED_ON); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} + +static int led_set_color_power(enum led_color color) +{ + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_OFF); + break; + case LED_WHITE: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_ON); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_POWER_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + break; + default: + break; + } +} + +static int led_set_color(enum ec_led_id led_id, enum led_color color) +{ + int rv; + + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + rv = led_set_color_battery(color); + break; + case EC_LED_ID_POWER_LED: + rv = led_set_color_power(color); + break; + default: + return EC_ERROR_UNKNOWN; + } + return rv; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color(led_id, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color(led_id, LED_AMBER); + else + led_set_color(led_id, LED_OFF); + + return EC_SUCCESS; +} + +static void led_set_battery(void) +{ + static int battery_ticks; + static int power_ticks; + + battery_ticks++; + + /* + * Override battery LED for Drawlet/Drawman, Drawlet/Drawman + * don't have power LED, blinking battery white LED to indicate + * system suspend without charging. + */ + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_ABSENT) { + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + led_set_color_battery(power_ticks++ & 0x2 ? LED_WHITE : + LED_OFF); + return; + } + } + + power_ticks = 0; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + led_set_color_battery(LED_AMBER); + break; + case LED_PWRS_DISCHARGE_FULL: + if (extpower_is_present()) { + led_set_color_battery(LED_WHITE); + break; + } + __fallthrough; + case LED_PWRS_DISCHARGE: + /* + * Blink white light (1 sec on, 1 sec off) + * when battery capacity is less than 10% + */ + if (charge_get_percent() < 10) + led_set_color_battery( + (battery_ticks & 0x2) ? LED_WHITE : LED_OFF); + else + led_set_color_battery(LED_OFF); + break; + case LED_PWRS_ERROR: + led_set_color_battery((battery_ticks % 0x2) ? LED_WHITE : + LED_OFF); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + led_set_color_battery(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + led_set_color_battery(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + led_set_color_battery((battery_ticks & 0x2) ? LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +static void led_set_power(void) +{ + static int power_tick; + + power_tick++; + + if (chipset_in_state(CHIPSET_STATE_ON)) + led_set_color_power(LED_WHITE); + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + led_set_color_power((power_tick & 0x2) ? LED_WHITE : LED_OFF); + else + led_set_color_power(LED_OFF); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + led_set_power(); + + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/haboki/usb_pd_policy.c b/board/haboki/usb_pd_policy.c new file mode 100644 index 0000000000..8a2c07c575 --- /dev/null +++ b/board/haboki/usb_pd_policy.c @@ -0,0 +1,74 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/sm5803.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + if (port < 0 || port >= board_get_usb_pd_port_count()) + return; + + prev_en = charger_is_sourcing_otg_power(port); + + /* Disable Vbus */ + charger_enable_otg_power(port, 0); + + /* Discharge Vbus if previously enabled */ + if (prev_en) + sm5803_set_vbus_disch(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + enum ec_error_list rv; + + /* Disable sinking */ + rv = sm5803_vbus_sink_enable(port, 0); + if (rv) + return rv; + + /* Disable Vbus discharge */ + sm5803_set_vbus_disch(port, 0); + + /* Provide Vbus */ + charger_enable_otg_power(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +__override bool pd_check_vbus_level(int port, enum vbus_level level) +{ + return sm5803_check_vbus_level(port, level); +} + +int pd_snk_is_vbus_provided(int port) +{ + return sm5803_is_vbus_present(port); +} diff --git a/board/haboki/vif_override.xml b/board/haboki/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/haboki/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/hades/battery.c b/board/hades/battery.c new file mode 100644 index 0000000000..29f73d76c4 --- /dev/null +++ b/board/hades/battery.c @@ -0,0 +1,80 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Hades battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* LGC AP21A8T Battery Information */ + [BATTERY_LGC_AP21A8T] = { + /* RAJ240045 Fuel Gauge */ + .fuel_gauge = { + .manuf_name = "LGES KT0040G014", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 17600, + .voltage_normal = 15400, /* mV */ + .voltage_min = 12000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC_AP21A8T; + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} diff --git a/board/hades/board.c b/board/hades/board.c new file mode 100644 index 0000000000..c4baf00f79 --- /dev/null +++ b/board/hades/board.c @@ -0,0 +1,106 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "anx7406.h" +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/nvidia_gpu.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "system.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static int block_sequence; + +struct d_notify_policy d_notify_policies[] = { + [D_NOTIFY_1] = AC_ATLEAST_W(100), + [D_NOTIFY_2] = AC_ATLEAST_W(65), + [D_NOTIFY_3] = AC_DC, + [D_NOTIFY_4] = DC_ATMOST_SOC(20), + [D_NOTIFY_5] = DC_ATMOST_SOC(5), +}; +BUILD_ASSERT(ARRAY_SIZE(d_notify_policies) == D_NOTIFY_COUNT); + +__override void board_cbi_init(void) +{ +} + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + gpio_set_level(GPIO_EN_EC_KB_BL_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + gpio_set_level(GPIO_EN_EC_KB_BL_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +static void board_init(void) +{ + const uint16_t i2c_sequencer_addr_flag = 0x10; + /* 0xaf: glitch filter reg address */ + const uint8_t out[2] = { 0xaf, 0x01 }; + + int rv; + + if ((system_get_reset_flags() & EC_RESET_FLAG_AP_OFF) || + (keyboard_scan_get_boot_keys() & BOOT_KEY_DOWN_ARROW)) { + CPRINTS("PG_PP3300_S5_OD block is enabled"); + block_sequence = 1; + } + + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + + nvidia_gpu_init_policy(d_notify_policies); + + /* Adjust glitch filtering on PPVAR_SYS (b/282181312) */ + rv = i2c_xfer(I2C_PORT_MISC, i2c_sequencer_addr_flag, out, sizeof(out), + NULL, 0); + if (rv) + CPRINTS("Failed to adjust sequencer timing (%d)", rv); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void gpu_overt_interrupt(enum gpio_signal signal) +{ + nvidia_gpu_over_temp(gpio_get_level(signal)); +} + +int board_anx7406_init(int port) +{ + /* Unblock USB_C1_PPC_SNK_EN */ + if (port == USBC_PORT_C1) + return anx7406_set_gpio(USBC_PORT_C1, 0, 1); + + return EC_SUCCESS; +} diff --git a/board/hades/board.h b/board/hades/board.h new file mode 100644 index 0000000000..c5e435f9a7 --- /dev/null +++ b/board/hades/board.h @@ -0,0 +1,232 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Hades board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +#define CONFIG_SYSTEM_UNLOCKED + +/* + * Nvidia GPU + */ +#define CONFIG_GPU_NVIDIA + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +/* + * Hades blocks PG_PP3300_S5_OD instead to control AP power-on. + */ +#undef CONFIG_CHIPSET_X86_RSMRST_AFTER_S5 + +/* Sensors */ +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE + +/* Buttons */ +#undef CONFIG_VOLUME_BUTTONS + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB-C0 */ +#define CONFIG_USB_PD_TCPM_NCT38XX +#define CONFIG_USBC_PPC_TCPCI +#define CONFIG_USBC_RETIMER_PI3DPX1207 + +/* USB-C1 */ +#define CONFIG_USB_PD_TCPM_ANX7406 +#define CONFIG_USBC_PPC_TCPCI +#define CONFIG_USBC_RETIMER_PS8818 + +/* USB-C Common */ +#define CONFIG_USB_PD_FRS_TCPC + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 500 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PCH_DSW_PWROK GPIO_PCH_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* + * I2C Bus Configuration + */ +/* 0: Unused */ +/* 1: USB-C0 */ +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C0_BC12 NPCX_I2C_PORT1_0 +/* 2: USB-C1 */ +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT2_0 +/* 3: Reserved for Accels */ +/* 4: Unused */ +/* 5: Battery */ +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +/* 6: Unused */ +/* 7: Charger, EEPROM, IMVP9 VR, MONITOR, Power sequencer */ +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MISC NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS 500 +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_BYPASS_MODE +#define CONFIG_CHARGER_RAA489110 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 +/* Round down 7700 max current to multiple of 128mA for ISL9241 AC prochot. */ +#define HADES_AC_PROCHOT_CURRENT_MA 7680 + +/* Barrel jack adapter settings */ +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 +/* This is the next available port # after USB-C ports. */ +#define DEDICATED_CHARGE_PORT 2 + +/* + * Older boards have a different ADC assignment. + */ + +#define CONFIG_ADC_CHANNELS_RUNTIME_CONFIG + +/* Give SEQ_EC_DSW_PWROK IRQ higher priority to reduce latency for PCH_PWROK. */ +#define NPCX_MIWU0_GROUP_F 1 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_FAN, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_TEMP_SENSOR_4_GPU_FBVDD, + ADC_CHARGER_IADP, + ADC_ADP_TYP, + ADC_USB_C1_VBUSM, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_GPU, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_4_GPU_FBVDD, + TEMP_SENSOR_COUNT +}; + +enum battery_type { + BATTERY_LGC_AP21A8T, + + BATTERY_TYPE_COUNT +}; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_FAN2, /* PWM4 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_1, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_1, MFT_CH_COUNT }; + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_TYPEC1, + CHARGE_PORT_BARRELJACK, +}; + +/** + * Interrupt handler for PG_PP3300_S5_OD changes. + * + * @param signal Signal which triggered the interrupt. + */ +void board_power_interrupt(enum gpio_signal signal); + +/* IRQ for BJ plug/unplug. */ +void bj_present_interrupt(enum gpio_signal signal); + +/* IRQ for over temperature. */ +void gpu_overt_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/hades/build.mk b/board/hades/build.mk new file mode 100644 index 0000000000..e72f79992f --- /dev/null +++ b/board/hades/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Hades board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger_isl9241.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/hades/charger_isl9241.c b/board/hades/charger_isl9241.c new file mode 100644 index 0000000000..ad59c5f139 --- /dev/null +++ b/board/hades/charger_isl9241.c @@ -0,0 +1,275 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * + * We need to deal with plug / unplug of AC chargers: + * + * +---------+ +USB +---------+ + * | BATTERY |------------>| BATTERY | + * | |<------------| +USB | + * +---------+ -USB +---------+ + * | ^ | ^ + * +BJ | | -BJ +BJ | | -BJ + * v | v | + * +---------+ +USB +---------+ + * | BATTERY |------------>| BATTERY | + * | +BJ |<------------| +BJ+USB | + * +---------+ -USB +---------+ + * + * Depending on available battery charge, power rating of the new charger, and + * the system power state, transition/throttling may or may not occur but + * switching chargers is handled as follows: + * + * 1. Detects a new charger or removal of an existing charger. + * 2. charge_manager_update_charge is called with new charger's info. + * 3. board_set_active_charge_port is called. + * 3.1 It triggers hard & soft throttling for AP & GPU. + * 3.2 It disable active port then enables the new port. + * 4. HOOK_POWER_SUPPLY_CHANGE is called. We disables hard throttling. + * 5. charger task wakes up on HOOK_POWER_SUPPLY_CHANGE, enables (or disables) + * bypass mode. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "gpio.h" +#include "hooks.h" +#include "stdbool.h" +#include "throttle_ap.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +static int board_enable_bj_port(bool enable) +{ + if (enable) { + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + } else { + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + } + + CPRINTS("BJ power is %sabled", enable ? "en" : "dis"); + + return EC_SUCCESS; +} + +static void board_throttle_ap_gpu(void) +{ + throttle_ap(THROTTLE_ON, THROTTLE_HARD, THROTTLE_SRC_AC); + throttle_gpu(THROTTLE_ON, THROTTLE_HARD, THROTTLE_SRC_AC); +} + +/* Disable all VBUS sink ports except . = -1 disables all ports. */ +static int board_disable_other_vbus_sink(int except_port) +{ + int i, r, rv = EC_SUCCESS; + + for (i = 0; i < ppc_cnt; i++) { + if (i == except_port) + continue; + /* + * Do not return early if one fails otherwise we can get into a + * boot loop assertion failure. + */ + r = ppc_vbus_sink_enable(i, 0); + if (r) + CPRINTS("Failed to disable sink path C%d (%d)", i, r); + rv |= r; + } + + return rv; +} + +/* Minimum battery SoC required for switching source port. */ +#define MIN_BATT_FOR_SWITCHING_SOURCE_PORT 1 + +/* + * TODO: Recover from incomplete execution: + */ +int board_set_active_charge_port(int port) +{ + enum charge_supplier active_supplier = charge_manager_get_supplier(); + int active_port = charge_manager_get_active_charge_port(); + + CPRINTS("Switching charger from P%d (supplier=%d) to P%d", active_port, + active_supplier, port); + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charger ports"); + + board_enable_bj_port(false); + board_disable_other_vbus_sink(-1); + + return EC_SUCCESS; + } + + /* Return on invalid or no-op call. */ + if (port < 0 || CHARGE_PORT_COUNT <= port) { + return EC_ERROR_INVAL; + } else if (port == active_port) { + return EC_SUCCESS; + } else if (board_vbus_source_enabled(port)) { + /* Don't charge from a USBC source port */ + CPRINTS("Don't enable P%d. It's sourcing.", port); + return EC_ERROR_INVAL; + } + + /* + * If we're in S0, throttle AP and GPU. They'll be unthrottled when + * a port/supply switch completes (via HOOK_POWER_SUPPLY_CHANGE). + * + * If we're running currently on a battery (active_supplier == NONE), we + * don't need to throttle because we're not disabling any port. + */ + if (chipset_in_state(CHIPSET_STATE_ON) && + active_supplier != CHARGE_SUPPLIER_NONE) + board_throttle_ap_gpu(); + + /* + * We're here for the two cases: + * 1. A new charger was connected. + * 2. One charger was disconnected and we're switching to another. + */ + + /* + * We need to check the battery if we're switching a source port. If + * we're just starting up or no AC was previously plugged, we shouldn't + * check the battery. Both cases can be caught by supplier == NONE. + */ + if (active_supplier != CHARGE_SUPPLIER_NONE) { + if (charge_get_percent() < MIN_BATT_FOR_SWITCHING_SOURCE_PORT) + return EC_ERROR_NOT_POWERED; + } + + /* Turn off other ports' sink paths before enabling requested port. */ + if (is_pd_port(port)) { + /* + * BJ port is enabled on start-up. So, we need to turn it off + * even if we were not previously on BJ. + */ + board_enable_bj_port(false); + if (board_disable_other_vbus_sink(port)) + return EC_ERROR_UNCHANGED; + + /* Enable requested USBC charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTS("Failed to enable sink path for C%d", port); + return EC_ERROR_UNKNOWN; + } + } else if (port == CHARGE_PORT_BARRELJACK) { + /* + * We can't proceed unless both ports are successfully + * disconnected as sources. + */ + if (board_disable_other_vbus_sink(-1)) + return EC_ERROR_UNKNOWN; + board_enable_bj_port(true); + } + + CPRINTS("New charger P%d", port); + + return EC_SUCCESS; +} + +static const struct charge_port_info bj_power = { + /* 150W (also default) */ + .voltage = 19500, + .current = 7700, +}; + +/* Debounce time for BJ plug/unplug */ +#define BJ_DEBOUNCE_MS CONFIG_EXTPOWER_DEBOUNCE_MS + +int board_should_charger_bypass(void) +{ + return charge_manager_get_active_charge_port() == DEDICATED_CHARGE_PORT; +} + +static void bj_connect(void) +{ + static int8_t bj_connected = -1; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == bj_connected) + return; + + bj_connected = connected; + CPRINTS("BJ %sconnected", connected ? "" : "dis"); + + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, + connected ? &bj_power : NULL); +} +DECLARE_DEFERRED(bj_connect); + +/* This handler shouldn't be needed if ACOK from isl9241 is working. */ +void bj_present_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&bj_connect_data, BJ_DEBOUNCE_MS * MSEC); +} + +void ac_change(void) +{ + /* + * Serialize. We don't handle USB-C here because we'll get a + * notification from TCPC. + */ + hook_call_deferred(&bj_connect_data, 0); +} +DECLARE_HOOK(HOOK_AC_CHANGE, ac_change, HOOK_PRIO_DEFAULT); + +static void power_supply_changed(void) +{ + /* + * We've switched to a new charge port (or no port). Hardware throttles + * can be removed now. Software throttles may stay enabled and change + * as the situation changes. + */ + throttle_ap(THROTTLE_OFF, THROTTLE_HARD, THROTTLE_SRC_AC); + /* + * Unthrottling GPU is done through a deferred call scheduled when it + * was throttled. + */ +} +DECLARE_HOOK(HOOK_POWER_SUPPLY_CHANGE, power_supply_changed, HOOK_PRIO_DEFAULT); + +static void bj_state_init(void) +{ + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + bj_connect(); + + isl9241_set_ac_prochot(CHARGER_SOLO, HADES_AC_PROCHOT_CURRENT_MA); +} +DECLARE_HOOK(HOOK_INIT, bj_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); diff --git a/board/hades/ec.tasklist b/board/hades/ec.tasklist new file mode 100644 index 0000000000..905a3cceca --- /dev/null +++ b/board/hades/ec.tasklist @@ -0,0 +1,29 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(LED, led_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/hades/fans.c b/board/hades/fans.c new file mode 100644 index 0000000000..337ac21418 --- /dev/null +++ b/board/hades/fans.c @@ -0,0 +1,66 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, + [MFT_CH_1] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN2, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_conf fan_conf_1 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_1, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP12000_FAN_X, +}; + +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 4300, +}; + +static const struct fan_rpm fan_rpm_1 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 4300, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, + [FAN_CH_1] = { + .conf = &fan_conf_1, + .rpm = &fan_rpm_1, + }, +}; diff --git a/board/hades/fw_config.c b/board/hades/fw_config.c new file mode 100644 index 0000000000..a49079a9f1 --- /dev/null +++ b/board/hades/fw_config.c @@ -0,0 +1,40 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union hades_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for hades if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union hades_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Hades FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union hades_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} diff --git a/board/hades/fw_config.h b/board/hades/fw_config.h new file mode 100644 index 0000000000..5f7758bb2a --- /dev/null +++ b/board/hades/fw_config.h @@ -0,0 +1,38 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_HADES_FW_CONFIG_H_ +#define __BOARD_HADES_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Hades board. + * + * Source of truth is the project/draco/agah/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +union hades_cbi_fw_config { + struct { + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t reserved_1 : 21; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union hades_cbi_fw_config get_fw_config(void); + +#endif /* __BOARD_HADES_FW_CONFIG_H_ */ diff --git a/board/hades/gpio.inc b/board/hades/gpio.inc new file mode 100644 index 0000000000..1fac87c82f --- /dev/null +++ b/board/hades/gpio.inc @@ -0,0 +1,143 @@ +/* -*- mode:c -*- + * + * Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, intel_x86_pwrok_signal_interrupt) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(A, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_PULL_UP | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(A, 7), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(9, 5), GPIO_INT_BOTH | GPIO_PULL_UP, bj_present_interrupt) +GPIO_INT(GPU_OVERT_ODL, PIN(5, 0), GPIO_INT_BOTH, gpu_overt_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_ODR_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EN_EC_KB_BL_L, PIN(8, 6), GPIO_ODR_HIGH) +GPIO(IMVP91_PE_EC, PIN(E, 3), GPIO_OUT_LOW) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +GPIO(EN_PP12000_FAN_X, PIN(F, 5), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(9, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(EC_USB_PCH_C0_OC_ODL, PIN(9, 4), GPIO_ODR_HIGH) +GPIO(EC_USB_PCH_C1_OC_ODL, PIN(9, 7), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(EN_USB_A_LOW_POWER, PIN(9, 3), GPIO_OUT_LOW) +GPIO(EN_USB_C1_28V, PIN(B, 5), GPIO_OUT_LOW) +GPIO(USB_C0_TCPC_RST_ODL, PIN(D, 4), GPIO_OUT_HIGH) +GPIO(NVIDIA_GPU_ACOFF_ODL, PIN(5, 6), GPIO_ODR_HIGH) +GPIO(LED_4_L, PIN(6, 0), GPIO_OUT_HIGH) +GPIO(LED_3_L, PIN(C, 2), GPIO_OUT_HIGH) +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) +GPIO(USB_C0_PPC_HI_ILIM, PIN(F, 2), GPIO_OUT_HIGH) +GPIO(USB_C1_PPC_HI_ILIM, PIN(F, 3), GPIO_OUT_HIGH) +GPIO(USB_C0_IN_HPD, PIN(6, 2), GPIO_OUT_LOW) +/* Block AP power sequencing (b/279214842) */ +GPIO(PG_PP3300_S5_OD, PIN(B, 4), GPIO_ODR_HIGH) + +/* + * Barrel-jack adapter enable switch. When starting up on a depleted battery, + * we'll be powered by either BJ or USB-C but not both. The EC will detect BJ + * or USBC and disable the other ports. + */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(A, 2), GPIO_OUT_LOW) + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 EC_FAN1_TACH */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 EC_FAN2_TACH */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 EC_KB_BL_PWM */ +ALTERNATE(PIN_MASK(B, 0xC0), 0, MODULE_PWM, 0) /* GPIOB7/PWM5=FAN1_PWM, + GPIOB6/PWM4=FAN2_PWM */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6=TEMP_SENSOR_3 */ +ALTERNATE(PIN_MASK(4, 0x36), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L=CHARGER_IADP_R, + GPIO45/ADC0=TEMP_SENSOR_1, + GPIO44/ADC1=TEMP_SENSOR_2, + GPIO41/ADC4=ADP_TYP. */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7=TEMP_SENSOR_4 */ +ALTERNATE(PIN_MASK(F, 0x01), 0, MODULE_ADC, 0) /* GPIOF0/ADC9=USB_C1_VBUSM */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(D, 0)) +UNUSED(PIN(D, 1)) +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 1)) /* GPIO81 */ +UNUSED(PIN(E, 1)) /* GPIOE1 */ +UNUSED(PIN(E, 4)) +UNUSED(PIN(0, 2)) /* USB_C1_TCPC_RST_ODL. Not connected because R564 is + DNS. */ diff --git a/board/hades/i2c.c b/board/hades/i2c.c new file mode 100644 index 0000000000..a09be51cd3 --- /dev/null +++ b/board/hades/i2c.c @@ -0,0 +1,48 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "i2c.h" + +#define BOARD_ID_FAST_PLUS_CAPABLE 2 + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_SCL, + .sda = GPIO_EC_I2C_USB_C0_SDA, + }, + { + /* I2C2 */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_SCL, + .sda = GPIO_EC_I2C_USB_C1_SDA, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 400, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C7 */ + .name = "misc", + .port = I2C_PORT_MISC, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/hades/keyboard.c b/board/hades/keyboard.c new file mode 100644 index 0000000000..a420ec8a4a --- /dev/null +++ b/board/hades/keyboard.c @@ -0,0 +1,65 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xf6, 0x55, 0xfe, 0xff, 0xff, 0xff, /* full set */ + }, +}; + +static const struct ec_response_keybd_config keybd = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* There's no screen lock key on hades */ + .capabilities = KEYBD_CAP_NUMERIC_KEYPAD, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &keybd; +} + +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); diff --git a/board/hades/led.c b/board/hades/led.c new file mode 100644 index 0000000000..1e34229a47 --- /dev/null +++ b/board/hades/led.c @@ -0,0 +1,200 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery LED control for Hades + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "host_command.h" +#include "led_common.h" +#include "task.h" + +#include + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define BATT_LOW_BCT 10 + +#define LED_TICK_INTERVAL_MS (500 * MSEC) +#define LED_CYCLE_TIME_MS (2000 * MSEC) +#define LED_TICKS_PER_CYCLE (LED_CYCLE_TIME_MS / LED_TICK_INTERVAL_MS) +#define LED_ON_TIME_MS (1000 * MSEC) +#define LED_ON_TICKS (LED_ON_TIME_MS / LED_TICK_INTERVAL_MS) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color_battery(enum led_color color) +{ + enum gpio_signal amber_led1, white_led1, amber_led2, white_led2; + + amber_led1 = GPIO_LED_1_L; + white_led1 = GPIO_LED_2_L; + amber_led2 = GPIO_LED_3_L; + white_led2 = GPIO_LED_4_L; + + switch (color) { + case LED_WHITE: + gpio_set_level(white_led1, BAT_LED_ON); + gpio_set_level(amber_led1, BAT_LED_OFF); + gpio_set_level(white_led2, BAT_LED_ON); + gpio_set_level(amber_led2, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(white_led1, BAT_LED_OFF); + gpio_set_level(amber_led1, BAT_LED_ON); + gpio_set_level(white_led2, BAT_LED_OFF); + gpio_set_level(amber_led2, BAT_LED_ON); + break; + case LED_OFF: + gpio_set_level(white_led1, BAT_LED_OFF); + gpio_set_level(amber_led1, BAT_LED_OFF); + gpio_set_level(white_led2, BAT_LED_OFF); + gpio_set_level(amber_led2, BAT_LED_OFF); + break; + default: + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + default: + break; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LED_AMBER); + else + led_set_color_battery(LED_OFF); + break; + default: + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + led_set_color_battery(color); +} + +static void led_set_battery(void) +{ + static unsigned int battery_ticks; + static unsigned int suspend_ticks; + + battery_ticks++; + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + suspend_ticks++; + + led_set_color_battery( + (suspend_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); + + return; + } + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + /* + * Blinking amber LEDs slowly if battery is lower 10 + * percentage. + */ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + if (charge_get_percent() < BATT_LOW_BCT) + led_set_color_battery( + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(LED_OFF); + } + + break; + case LED_PWRS_ERROR: + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + led_set_color_battery( + (battery_ticks & 0x1) ? LED_AMBER : LED_OFF); + } + + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +void led_task(void *u) +{ + uint32_t start_time; + uint32_t task_duration; + + while (1) { + start_time = get_time().le.lo; + + led_set_battery(); + + /* Compute time for this iteration */ + task_duration = get_time().le.lo - start_time; + /* + * Compute wait time required to for next desired LED tick. If + * the duration exceeds the tick time, then don't sleep. + */ + if (task_duration < LED_TICK_INTERVAL_MS) + usleep(LED_TICK_INTERVAL_MS - task_duration); + } +} diff --git a/board/hades/pwm.c b/board/hades/pwm.c new file mode 100644 index 0000000000..22c01fc6d9 --- /dev/null +++ b/board/hades/pwm.c @@ -0,0 +1,47 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, + [PWM_CH_FAN2] = { + .channel = 4, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn off all the LEDs. + * Turn on the fan at 100%. + */ + + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/hades/sensors.c b/board/hades/sensors.c new file mode 100644 index 0000000000..87d1e2a625 --- /dev/null +++ b/board/hades/sensors.c @@ -0,0 +1,156 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_FAN] = { + .name = "TEMP_FAN", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_GPU_FBVDD] = { + .name = "TEMP_GPU_FBVDD", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_CHARGER_IADP] = { + .name = "CHARGER_IADP", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_ADP_TYP] = { + .name = "ADP_TYP", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_USB_C1_VBUSM] = { + .name = "USB_C1_VBUSM", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { + .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC, + }, + [TEMP_SENSOR_2_GPU] = { + .name = "GPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_FAN, + }, + [TEMP_SENSOR_3_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER, + }, + [TEMP_SENSOR_4_GPU_FBVDD] = { + .name = "GPU FBVDD", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_GPU_FBVDD, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +#define THERMAL_GPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_gpu = THERMAL_GPU; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 125C, max absolute temperature 150C + * PP3300 regulator: operating range -40 C to 125 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(105), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(120), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(65), \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_GPU] = THERMAL_GPU, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, + [TEMP_SENSOR_4_GPU_FBVDD] = THERMAL_GPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/hades/usbc_config.c b/board/hades/usbc_config.c new file mode 100644 index 0000000000..d8df38c6b6 --- /dev/null +++ b/board/hades/usbc_config.c @@ -0,0 +1,422 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/tcpci_ppc.h" +#include "driver/retimer/pi3dpx1207.h" +#include "driver/retimer/ps8818_public.h" +#include "driver/tcpm/anx7406.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + /* Circuit 1 (p1 = 0x70, p2 = 0x74) */ + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = ANX7406_TCPC0_I2C_ADDR_FLAGS, + }, + .drv = &anx7406_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &tcpci_ppc_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = ANX7406_TCPC0_I2C_ADDR_FLAGS, + .drv = &tcpci_ppc_drv, + }, +}; + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +const static struct ps8818_reg_val equalizer_default_table[] = { + { + .reg = PS8818_REG1_APTX1EQ_10G_LEVEL, + .mask = PS8818_EQ_LEVEL_UP_MASK, + .val = PS8818_EQ_LEVEL_UP_19DB, + }, + { + .reg = PS8818_REG1_APTX2EQ_10G_LEVEL, + .mask = PS8818_EQ_LEVEL_UP_MASK, + .val = PS8818_EQ_LEVEL_UP_19DB, + }, + { + .reg = PS8818_REG1_APTX1EQ_5G_LEVEL, + .mask = PS8818_EQ_LEVEL_UP_MASK, + .val = PS8818_EQ_LEVEL_UP_19DB, + }, + { + .reg = PS8818_REG1_APTX2EQ_5G_LEVEL, + .mask = PS8818_EQ_LEVEL_UP_MASK, + .val = PS8818_EQ_LEVEL_UP_19DB, + }, + { + .reg = PS8818_REG1_RX_PHY, + .mask = PS8818_RX_INPUT_TERM_MASK, + .val = PS8818_RX_INPUT_TERM_112_OHM, + }, +}; + +#define NUM_EQ_DEFAULT_ARRAY ARRAY_SIZE(equalizer_default_table) + +int board_ps8818_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + int i; + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + for (i = 0; i < NUM_EQ_DEFAULT_ARRAY; i++) + rv |= ps8818_i2c_field_update8( + me, PS8818_REG_PAGE1, + equalizer_default_table[i].reg, + equalizer_default_table[i].mask, + equalizer_default_table[i].val); + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* Boost the DP gain */ + rv |= ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_DPEQ_LEVEL, + PS8818_DPEQ_LEVEL_UP_MASK, + PS8818_DPEQ_LEVEL_UP_19DB); + } + + return rv; +} + +const static struct usb_mux_chain usbc2_ps8818 = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_USB_C1_TCPC, + .i2c_addr_flags = PS8818_I2C_ADDR0_FLAGS, + .driver = &ps8818_usb_retimer_driver, + .board_set = &board_ps8818_mux_set, + }, +}; + +const struct pi3dpx1207_usb_control pi3dpx1207_controls[] = { + [USBC_PORT_C0] = { + .dp_enable_gpio = GPIO_USB_C0_IN_HPD, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3dpx1207_controls) == 1); + +const struct usb_mux_chain usbc0_pi3dpx1207_usb_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_C0_TCPC, + .i2c_addr_flags = PI3DPX1207_I2C_ADDR_FLAGS, + .driver = &pi3dpx1207_usb_retimer, + }, +}; + +/* USBC mux configuration - Alder Lake includes internal mux */ +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc0_pi3dpx1207_usb_retimer, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc2_ps8818, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +void board_reset_pd_mcu(void) +{ + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + msleep(NCT38XX_RESET_HOLD_DELAY_MS); + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 1); + + nct38xx_reset_notify(USBC_PORT_C0); + + /* wait for chips to come up */ + if (NCT3808_RESET_POST_DELAY_MS != 0) + msleep(NCT3808_RESET_POST_DELAY_MS); +} + +int board_tcpc_post_init(int port) +{ + int rv; + + if (port != USBC_PORT_C0) + return EC_SUCCESS; + + /* Disable P2 on C0 */ + rv = i2c_write16(tcpc_config[port].i2c_info.port, + NCT38XX_I2C_ADDR2_1_FLAGS, TCPC_REG_ALERT_MASK, + TCPC_REG_ALERT_NONE); + rv |= i2c_write16(tcpc_config[port].i2c_info.port, + NCT38XX_I2C_ADDR2_1_FLAGS, TCPC_REG_RX_DETECT, + TCPC_REG_RX_DETECT_NONE); + rv |= i2c_write16(tcpc_config[port].i2c_info.port, + NCT38XX_I2C_ADDR2_1_FLAGS, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_DISABLE_VBUS_DETECT); + if (rv) + CPRINTS("C0: Failed to disable P2 (0x%x)", rv); + + return rv; +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + board_tcpc_post_init(USBC_PORT_C0); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + + if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +static void ppc_handle_interrupt(int port) +{ + /* + * Ignore false positives (which may happen when we're already + * disconnected). + */ + if (!ppc_chips[port].drv->is_sourcing_vbus(port)) + return; + + /* + * If this is triggered by AOZ15333, it's either over current, short + * circuit, or over temperature. If this is triggered by AOZ13937, it's + * either over temperature, over voltage, or reverse current. + */ + ppc_prints("C%d: Vbus OC/OT/SC/OV/RC", port); + pd_handle_overcurrent(port); +} + +static atomic_t irq_pending; /* Bitmask of ports signaling an interrupt. */ + +static void ppc_irq_deferred(void) +{ + uint32_t pending = atomic_clear(&irq_pending); + + for (int i = 0; i < board_get_usb_pd_port_count(); i++) + if (pending & BIT(i)) + ppc_handle_interrupt(i); +} +DECLARE_DEFERRED(ppc_irq_deferred); + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + atomic_or(&irq_pending, BIT(0)); + break; + case GPIO_USB_C1_PPC_INT_ODL: + atomic_or(&irq_pending, BIT(1)); + break; + default: + break; + } + hook_call_deferred(&ppc_irq_deferred_data, 0); +} + +void retimer_interrupt(enum gpio_signal signal) +{ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return false; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/hades/usbc_config.h b/board/hades/usbc_config.h new file mode 100644 index 0000000000..fa3c5d241b --- /dev/null +++ b/board/hades/usbc_config.h @@ -0,0 +1,21 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Hades board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +struct ps8818_reg_val { + uint8_t reg; + uint8_t mask; + uint16_t val; +}; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/hades/vif_override.xml b/board/hades/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/hades/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/hadoken/board.c b/board/hadoken/board.c deleted file mode 100644 index d9c8ed322f..0000000000 --- a/board/hadoken/board.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "gpio.h" -#include "registers.h" -#include "util.h" - - -/* To define the gpio_list[] instance. */ -#include "gpio_list.h" - diff --git a/board/hadoken/board.h b/board/hadoken/board.h deleted file mode 100644 index e8d71b7ee8..0000000000 --- a/board/hadoken/board.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Hadoken board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -#ifndef __ASSEMBLER__ - -#undef CONFIG_FLASH /* TODO: implement me */ -#undef CONFIG_FLASH_PHYSICAL /* TODO: implement me */ -#undef CONFIG_FMAP /* TODO: implement me */ -#undef CONFIG_WATCHDOG -#undef CONFIG_LID_SWITCH - -/* - * nRF51 board specific configuration. - */ -#define NRF51_UART_TX_PIN 24 -#define NRF51_UART_RX_PIN 28 - -#define BATTERY_VOLTAGE_MAX 4425 /* mV */ -#define BATTERY_VOLTAGE_NORMAL 3800 /* mV */ -#define BATTERY_VOLTAGE_MIN 3000 /* mV */ - -#define CONFIG_BLUETOOTH_LE -#define CONFIG_BLUETOOTH_LE_STACK -#define CONFIG_BLUETOOTH_LE_RADIO_TEST -#define CONFIG_BLUETOOTH_LL_DEBUG -#define CONFIG_BLUETOOTH_HCI_DEBUG - -#include "gpio_signal.h" - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ - diff --git a/board/hadoken/build.mk b/board/hadoken/build.mk deleted file mode 100644 index b2fee56f23..0000000000 --- a/board/hadoken/build.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build - -# the IC is Nordic nRF51822 -CHIP:=nrf51 -CHIP_FAMILY:=nrf51x22 -CHIP_VARIANT:=nrf51822 - -# Hadoken does not support scratchpad -test-list-y= - -board-y=board.o diff --git a/board/hadoken/ec.tasklist b/board/hadoken/ec.tasklist deleted file mode 100644 index 0bb461ecb8..0000000000 --- a/board/hadoken/ec.tasklist +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/** - * See CONFIG_TASK_LIST in config.h for details. - */ -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(BLE_LL, bluetooth_ll_task, NULL, TASK_STACK_SIZE) - diff --git a/board/hadoken/gpio.inc b/board/hadoken/gpio.inc deleted file mode 100644 index ac4127992c..0000000000 --- a/board/hadoken/gpio.inc +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH) -#define GPIO_KB_OUTPUT GPIO_ODR_HIGH - -/* Keyboard inputs */ -/* - * TODO(yjlou): call keyboard_raw_gpio_interrupt() in chip/nrf51/keyboard_raw.c - */ -GPIO(KB_IN00, PIN(0, 6), GPIO_KB_INPUT) -GPIO(KB_IN01, PIN(0, 23), GPIO_KB_INPUT) -GPIO(KB_IN02, PIN(0, 1), GPIO_KB_INPUT) -GPIO(KB_IN03, PIN(0, 4), GPIO_KB_INPUT) -GPIO(KB_IN04, PIN(0, 0), GPIO_KB_INPUT) -GPIO(KB_IN05, PIN(0, 29), GPIO_KB_INPUT) -GPIO(KB_IN06, PIN(0, 22), GPIO_KB_INPUT) -GPIO(KB_IN07, PIN(0, 25), GPIO_KB_INPUT) - -/* Other inputs */ -GPIO(LID_PRESENT_L, PIN(0, 30), GPIO_INPUT) /* Hall sensor */ - -/* Useful for test software */ -GPIO(IND_CHRG_DISABLE, PIN(0, 20), GPIO_INPUT) - -/* Outputs */ -GPIO(KB_OUT00, PIN(0, 2), GPIO_KB_OUTPUT) -GPIO(KB_OUT01, PIN(0, 10), GPIO_KB_OUTPUT) -GPIO(KB_OUT02, PIN(0, 7), GPIO_KB_OUTPUT) -GPIO(KB_OUT03, PIN(0, 5), GPIO_KB_OUTPUT) -GPIO(KB_OUT04, PIN(0, 3), GPIO_KB_OUTPUT) -GPIO(KB_OUT05, PIN(0, 9), GPIO_KB_OUTPUT) -GPIO(KB_OUT06, PIN(0, 8), GPIO_KB_OUTPUT) -GPIO(KB_OUT07, PIN(0, 27), GPIO_KB_OUTPUT) -GPIO(KB_OUT08, PIN(0, 18), GPIO_KB_OUTPUT) -GPIO(KB_OUT09, PIN(0, 16), GPIO_KB_OUTPUT) -GPIO(KB_OUT10, PIN(0, 12), GPIO_KB_OUTPUT) -GPIO(KB_OUT11, PIN(0, 15), GPIO_KB_OUTPUT) -GPIO(KB_OUT12, PIN(0, 11), GPIO_KB_OUTPUT) - -/* SPI */ -GPIO(MCU_SPI_MOSI, PIN(0, 13), GPIO_OUTPUT) -GPIO(MCU_SPI_MISO, PIN(0, 14), GPIO_INPUT) -GPIO(MCU_SPI_SCLK, PIN(0, 17), GPIO_OUTPUT) -GPIO(MCU_SPI_CS_L, PIN(0, 19), GPIO_OUT_HIGH) - -/* VBATT_SENSE */ -GPIO(VBATT_SENSE, PIN(0, 26), GPIO_ANALOG) -GPIO(VBATT_SENSE_EN, PIN(0, 21), GPIO_OUT_LOW) - -/* Unimplemented */ -UNIMPLEMENTED(ENTERING_RW) diff --git a/board/halvor/battery.c b/board/halvor/battery.c deleted file mode 100644 index 828220fd49..0000000000 --- a/board/halvor/battery.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery_fuel_gauge.h" -#include "common.h" -#include "util.h" - -/* - * Battery info for all Volteer battery types. Note that the fields - * start_charging_min/max and charging_min/max are not used for the charger. - * The effective temperature limits are given by discharging_min/max_c. - * - * Fuel Gauge (FG) parameters which are used for determining if the battery - * is connected, the appropriate ship mode (battery cutoff) command, and the - * charge/discharge FETs status. - * - * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery - * register. For some batteries, the charge/discharge FET bits are set when - * charging/discharging is active, in other types, these bits set mean that - * charging/discharging is disabled. Therefore, in addition to the mask for - * these bits, a disconnect value must be specified. Note that for TI fuel - * gauge, the charge/discharge FET status is found in Operation Status (0x54), - * but a read of Manufacturer Access (0x00) will return the lower 16 bits of - * Operation status which contains the FET status bits. - * - * The assumption for battery types supported is that the charge/discharge FET - * status can be read with a sb_read() command and therefore, only the register - * address, mask, and disconnect value need to be provided. - */ -const struct board_batt_params board_battery_info[] = { - /* AEC AEC335181 Battery Information */ - /* - * Battery info provided by ODM on b/162908664, comment #4 - */ - [BATTERY_AEC] = { - .fuel_gauge = { - .manuf_name = "AEC", - .ship_mode = { - .reg_addr = 0x00, - .reg_data = { 0x0010, 0x0010 }, - }, - .fet = { - .mfgacc_support = 1, - .reg_addr = 0x0, - .reg_mask = 0x2000, - .disconnect_val = 0x2000, - } - }, - .batt_info = { - .voltage_max = 8700, /* mV */ - .voltage_normal = 7600, /* mV */ - .voltage_min = 6000, /* mV */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 50, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); - -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AEC; diff --git a/board/halvor/board.c b/board/halvor/board.c deleted file mode 100644 index fc12ccfb85..0000000000 --- a/board/halvor/board.c +++ /dev/null @@ -1,528 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer board-specific configuration */ -#include "accelgyro.h" -#include "assert.h" -#include "bb_retimer.h" -#include "button.h" -#include "common.h" -#include "cbi_ec_fw_config.h" -#include "driver/accel_bma2x2.h" -#include "driver/als_tcs3400.h" -#include "driver/bc12/pi3usb9201.h" -#include "driver/ppc/syv682x.h" -#include "driver/sync.h" -#include "driver/tcpm/tcpci.h" -#include "driver/tcpm/tusb422.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "keyboard_scan.h" -#include "lid_switch.h" -#include "power.h" -#include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "tablet_mode.h" -#include "uart.h" -#include "usb_pd_tbt.h" -#include "usbc_ppc.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "usb_mux.h" -#include "util.h" - -#include "gpio_list.h" /* Must come after other header files. */ - -/* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { - /* Increase from 50 us, because KSO_02 passes through the H1. */ - .output_settle_us = 80, - /* Other values should be the same as the default configuration. */ - .debounce_down_us = 9 * MSEC, - .debounce_up_us = 30 * MSEC, - .scan_period_us = 3 * MSEC, - .min_post_scan_delay_us = 1000, - .poll_timeout_us = 100 * MSEC, - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xff, - 0xa0, 0xff, 0xfe, 0x41, 0xfa, 0xc0, 0x02, - 0x08, /* full set */ - }, -}; - -/******************************************************************************/ -static const struct ec_response_keybd_config halvor_kb = { - .num_top_row_keys = 10, - .action_keys = { - TK_BACK, /* T1 */ - TK_REFRESH, /* T2 */ - TK_FULLSCREEN, /* T3 */ - TK_OVERVIEW, /* T4 */ - TK_BRIGHTNESS_DOWN, /* T5 */ - TK_BRIGHTNESS_UP, /* T6 */ - TK_PLAY_PAUSE, /* T7 */ - TK_VOL_MUTE, /* T8 */ - TK_VOL_DOWN, /* T9 */ - TK_VOL_UP, /* T10 */ - }, - .capabilities = KEYBD_CAP_SCRNLOCK_KEY, -}; - -__override const struct ec_response_keybd_config -*board_vivaldi_keybd_config(void) -{ - return &halvor_kb; -} - -/* - * FW_CONFIG defaults for Halvor if the CBI data is not initialized. - */ -union volteer_cbi_fw_config fw_config_defaults = { - /* Set all FW_CONFIG fields default to 0 */ - .raw_value = 0, -}; - -static void board_init(void) -{ - /* Illuminate motherboard and daughter board LEDs equally to start. */ - pwm_enable(PWM_CH_LED4_SIDESEL, 1); - pwm_set_duty(PWM_CH_LED4_SIDESEL, 50); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) -{ - /* Routing length exceeds 205mm prior to connection to re-timer */ - if (port == USBC_PORT_C1) - return TBT_SS_U32_GEN1_GEN2; - - /* - * Thunderbolt-compatible mode not supported - * - * TODO (b/153995632): All the USB-C ports need to support same speed. - * Need to fix once USB-C feature set is known for Halvor. - */ - return TBT_SS_RES_0; -} - -__override bool board_is_tbt_usb4_port(int port) -{ - /* - * On the volteer reference board 1 only port 1 supports TBT & USB4 - * - * TODO (b/153995632): All the USB-C ports need to support same - * features. Need to fix once USB-C feature set is known for Halvor. - */ - return port == USBC_PORT_C1; -} - -/******************************************************************************/ -/* I2C port map configuration */ -const struct i2c_port_t i2c_ports[] = { - { - .name = "sensor", - .port = I2C_PORT_SENSOR, - .kbps = 400, - .scl = GPIO_EC_I2C_0_SCL, - .sda = GPIO_EC_I2C_0_SDA, - }, - { - .name = "usb_c0", - .port = I2C_PORT_USB_C0, - .kbps = 1000, - .scl = GPIO_EC_I2C_1_SCL, - .sda = GPIO_EC_I2C_1_SDA, - }, - { - .name = "usb_c1", - .port = I2C_PORT_USB_C1, - .kbps = 1000, - .scl = GPIO_EC_I2C_2_SCL, - .sda = GPIO_EC_I2C_2_SDA, - }, - { - .name = "usb_bb_retimer", - .port = I2C_PORT_USB_BB_RETIMER, - .kbps = 100, - .scl = GPIO_EC_I2C_3_SCL, - .sda = GPIO_EC_I2C_3_SDA, - }, - { - .name = "usb_c2", - .port = I2C_PORT_USB_C2, - .kbps = 1000, - .scl = GPIO_EC_I2C_4_SCL, - .sda = GPIO_EC_I2C_4_SDA, - }, - { - .name = "power", - .port = I2C_PORT_POWER, - .kbps = 100, - .scl = GPIO_EC_I2C_5_SCL, - .sda = GPIO_EC_I2C_5_SDA, - }, - { - .name = "eeprom", - .port = I2C_PORT_EEPROM, - .kbps = 400, - .scl = GPIO_EC_I2C_7_SCL, - .sda = GPIO_EC_I2C_7_SDA, - }, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/* PWM configuration */ -const struct pwm_t pwm_channels[] = { - [PWM_CH_LED1_BLUE] = { - .channel = 2, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 2400, - }, - [PWM_CH_LED2_GREEN] = { - .channel = 0, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 2400, - }, - [PWM_CH_LED3_RED] = { - .channel = 1, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 2400, - }, - [PWM_CH_LED4_SIDESEL] = { - .channel = 7, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - /* Run at a higher frequency than the color PWM signals to avoid - * timing-based color shifts. - */ - .freq = 4800, - }, - [PWM_CH_FAN] = { - .channel = 5, - .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000 - }, - [PWM_CH_KBLIGHT] = { - .channel = 3, - .flags = 0, - /* - * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent - * flicker. Higher frequencies consume similar average power to - * lower PWM frequencies, but higher frequencies record a much - * lower maximum power. - */ - .freq = 2400, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -/******************************************************************************/ -/* EC thermal management configuration */ - -/* - * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at - * 130 C. However, sensor is located next to DDR, so we need to use the lower - * DDR temperature limit (85 C) - */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; - -/* - * Inductor limits - used for both charger and PP3300 regulator - * - * Need to use the lower of the charger IC, PP3300 regulator, and the inductors - * - * Charger max recommended temperature 100C, max absolute temperature 125C - * PP3300 regulator: operating range -40 C to 145 C - * - * Inductors: limit of 125c - * PCB: limit is 80c - */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - - -struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, -}; -BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); - -/******************************************************************************/ -void halvor_tcpc_alert_event(enum gpio_signal signal) -{ - int port = -1; - - switch (signal) { - case GPIO_USB_C0_TCPC_INT_ODL: - port = USBC_PORT_C0; - break; - case GPIO_USB_C1_TCPC_INT_ODL: - port = USBC_PORT_C1; - break; - case GPIO_USB_C2_TCPC_INT_ODL: - port = USBC_PORT_C2; - break; - default: - return; - } - - ASSERT(port != -1); - schedule_deferred_pd_interrupt(port); -} - -void halvor_ppc_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_PPC_INT_ODL: - syv682x_interrupt(USBC_PORT_C0); - break; - case GPIO_USB_C1_PPC_INT_ODL: - syv682x_interrupt(USBC_PORT_C1); - break; - case GPIO_USB_C2_PPC_INT_ODL: - syv682x_interrupt(USBC_PORT_C2); - break; - default: - break; - } -} - -void halvor_bc12_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); - break; - case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); - break; - case GPIO_USB_C2_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P2, USB_CHG_EVENT_BC12, 0); - break; - - default: - break; - } -} - -void board_reset_pd_mcu(void) -{ - /* TODO (b/153705222): Need to implement three USB-C function */ -} - -__override void board_cbi_init(void) -{ - /* TODO (b/153705222): Check FW_CONFIG for USB DB options */ -} - -/******************************************************************************/ -/* USBC PPC configuration */ -struct ppc_config_t ppc_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - }, - [USBC_PORT_C2] = { - .i2c_port = I2C_PORT_USB_C2, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -/******************************************************************************/ -/* BC1.2 charger detect configuration */ -const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, - [USBC_PORT_C2] = { - .i2c_port = I2C_PORT_USB_C2, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC TCPC configuration */ -struct tcpc_config_t tcpc_config[] = { - [USBC_PORT_C0] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C0, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), - }, - [USBC_PORT_C1] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), - }, - [USBC_PORT_C2] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C2, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_2_USB2_NUM | (USBC_PORT_2_USB3_NUM << 4), - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); -BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc0_usb4_db_retimer = { - .usb_port = USBC_PORT_C0, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usbc2_usb4_db_retimer = { - .usb_port = USBC_PORT_C2, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C2_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usb_muxes[] = { - [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc0_usb4_db_retimer, - }, - [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, - }, - [USBC_PORT_C2] = { - .usb_port = USBC_PORT_C2, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc2_usb4_db_retimer, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); - -struct bb_usb_control bb_controls[] = { - [USBC_PORT_C0] = { - .usb_ls_en_gpio = GPIO_USB_C0_LS_EN, - .retimer_rst_gpio = GPIO_USB_C0_RT_RST_ODL, - }, - [USBC_PORT_C1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, - }, - [USBC_PORT_C2] = { - .usb_ls_en_gpio = GPIO_USB_C2_LS_EN, - .retimer_rst_gpio = GPIO_USB_C2_RT_RST_ODL, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); - -static void board_usb_chip_init(void) -{ - /* Don't reset TCPCs after initial reset */ - if (!system_jumped_late()) - board_reset_pd_mcu(); - - /* Enable PPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); - - /* Enable TCPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C2_TCPC_INT_ODL); - - /* Enable BC1.2 interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C2_BC12_INT_ODL); -} -DECLARE_HOOK(HOOK_INIT, board_usb_chip_init, HOOK_PRIO_INIT_CHIPSET); - -/******************************************************************************/ -/* TCPC support routines */ -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - /* - * Check which port has the ALERT line set - */ - if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - if (!gpio_get_level(GPIO_USB_C2_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_2; - - return status; -} - -int ppc_get_alert_status(int port) -{ - if (port == USBC_PORT_C0) - return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; - else if (port == USBC_PORT_C1) - return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; - else - return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; -} - diff --git a/board/halvor/board.h b/board/halvor/board.h deleted file mode 100644 index b1db5627fa..0000000000 --- a/board/halvor/board.h +++ /dev/null @@ -1,191 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Baseboard features */ -#include "baseboard.h" - -/* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ - -#define CONFIG_POWER_BUTTON - -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 4096 - -/* LED defines */ -#define CONFIG_LED_POWER_LED -#define CONFIG_LED_ONOFF_STATES -#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 - -/* Keyboard features */ - -/* Sensors */ -/* BMA253 accelerometer in base */ -#define CONFIG_ACCEL_BMA255 - -/* TCS3400 ALS */ -#define CONFIG_ALS -#define ALS_COUNT 1 -#define CONFIG_ALS_TCS3400 -#define CONFIG_ALS_TCS3400_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) - -/* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) - -/* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 3 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 2 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 -#define USBC_PORT_2_USB2_NUM 6 -#define USBC_PORT_2_USB3_NUM 3 - -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - -/* - * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C - * cables only support up to 60W. - */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 65000 -#define PD_MAX_CURRENT_MA 3250 -#define PD_MAX_VOLTAGE_MV 20000 - -/* Enabling Thunderbolt-compatible mode */ -#define CONFIG_USB_PD_TBT_COMPAT_MODE - -/* Enabling USB4 mode */ -#define CONFIG_USB_PD_USB4 -#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x40 -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x41 -#define USBC_PORT_C2_BB_RETIMER_I2C_ADDR 0x42 - -/* USB Type A Features */ - -/* USBC PPC*/ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C0 C1 C2 */ - -/* BC 1.2 */ - -/* Volume Button feature */ - -/* Fan features */ - -/* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 5 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 - -/* - * Macros for GPIO signals used in common code that don't match the - * schematic names. Signal names in gpio.inc match the schematic and are - * then redefined here to so it's more clear which signal is being used for - * which purpose. - */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_USB_C0_BC12_INT_ODL GPIO_USB_C0_MIX_INT_ODL -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_USB_C2_BC12_INT_ODL GPIO_USB_C2_MIX_INT_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L - -#undef CONFIG_FANS -#undef CONFIG_VOLUME_BUTTONS - -/* I2C Bus Configuration */ -#define CONFIG_I2C -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_BB_RETIMER NPCX_I2C_PORT3_0 -#define I2C_PORT_USB_C2 NPCX_I2C_PORT4_1 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM -#define I2C_PORT_USB_1_MIX I2C_PORT_USB_BB_RETIMER - -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER - - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -enum battery_type { - BATTERY_AEC, - BATTERY_TYPE_COUNT, -}; - -enum pwm_channel { - PWM_CH_LED1_BLUE = 0, - PWM_CH_LED2_GREEN, - PWM_CH_LED3_RED, - PWM_CH_LED4_SIDESEL, - PWM_CH_FAN, - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; - -enum sensor_id { - LID_ACCEL = 0, - CLEAR_ALS, - RGB_ALS, - SENSOR_COUNT, -}; - -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_C2, - USBC_PORT_COUNT -}; - -/* Definition for Halvor USB PD interrupt handlers. */ -void halvor_tcpc_alert_event(enum gpio_signal signal); -void halvor_ppc_interrupt(enum gpio_signal signal); -void halvor_bc12_interrupt(enum gpio_signal signal); - -void board_reset_pd_mcu(void); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/halvor/build.mk b/board/halvor/build.mk deleted file mode 100644 index b78172d3cf..0000000000 --- a/board/halvor/build.mk +++ /dev/null @@ -1,17 +0,0 @@ -# -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -CHIP:=npcx -CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc -BASEBOARD:=volteer - -board-y=board.o -board-y+=battery.o -board-y+=led.o -board-y+=sensors.o diff --git a/board/halvor/ec.tasklist b/board/halvor/ec.tasklist deleted file mode 100644 index 936a4276e6..0000000000 --- a/board/halvor/ec.tasklist +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P2, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C2, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C2, pd_interrupt_handler_task, 2, TASK_STACK_SIZE) diff --git a/board/halvor/gpio.inc b/board/halvor/gpio.inc deleted file mode 100644 index 7631415318..0000000000 --- a/board/halvor/gpio.inc +++ /dev/null @@ -1,180 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -/* Wake Source interrupts */ -GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) -GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) -GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) -GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) - -/* Power sequencing interrupts */ -GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) -#endif -GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) - -/* Sensor Interrupts */ -GPIO_INT(EC_ALS_RGB_INT_L, PIN(D, 4), GPIO_INT_FALLING, tcs3400_interrupt) -GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) - -/* USB-C interrupts */ -GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, halvor_tcpc_alert_event) -GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, halvor_tcpc_alert_event) -GPIO_INT(USB_C2_TCPC_INT_ODL, PIN(A, 0), GPIO_INT_BOTH, halvor_tcpc_alert_event) - -GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, halvor_ppc_interrupt) -GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, halvor_ppc_interrupt) -GPIO_INT(USB_C2_PPC_INT_ODL, PIN(A, 4), GPIO_INT_BOTH, halvor_ppc_interrupt) - -GPIO_INT(USB_C0_MIX_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, halvor_bc12_interrupt) -GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, halvor_bc12_interrupt) -GPIO_INT(USB_C2_MIX_INT_ODL, PIN(6, 1), GPIO_INT_BOTH, halvor_bc12_interrupt) - -/* HDMI interrupts */ - -/* Volume button interrupts */ - -/* Unused signals */ -GPIO(EN_PP1050_STG, PIN(C, 0), GPIO_INPUT | GPIO_PULL_UP) -GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT | GPIO_PULL_UP) -GPIO(EN_PP1050_ST_S0, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) -/* Power Sequencing Signals */ -GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) -GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) -GPIO(EN_PP5000_USB_AG, PIN(A, 7), GPIO_OUT_HIGH) - -/* The EC does not buffer this signal on Halvor. */ -UNIMPLEMENTED(PCH_DSW_PWROK) -UNIMPLEMENTED(EN_PP5000_A) - -/* Other wake sources */ -/* - * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an - * interrupt handler because it is automatically handled by the PSL. - * - * We need to lock the setting so this gpio can't be reconfigured to overdrive - * the real reset signal. (This is the PSL input pin not the real reset pin). - */ -GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | - GPIO_HIB_WAKE_HIGH | - GPIO_LOCKED) - -/* AP/PCH Signals */ -GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) -GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ -GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) -GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) -GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) -GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) -GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) -GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) - -GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) - -/* USB and USBC Signals */ -GPIO(USB_C0_RT_RST_ODL, PIN(6, 6), GPIO_ODR_LOW) -GPIO(USB_C1_RT_RST_ODL, PIN(8, 6), GPIO_ODR_LOW) -GPIO(USB_C2_RT_RST_ODL, PIN(9, 6), GPIO_ODR_LOW) - -GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) -GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) -GPIO(USB_C2_OC_ODL, PIN(3, 2), GPIO_ODR_HIGH) - - - -/* Don't have a load switch for retimer */ -UNIMPLEMENTED(USB_C0_LS_EN) -UNIMPLEMENTED(USB_C1_LS_EN) -UNIMPLEMENTED(USB_C2_LS_EN) -UNIMPLEMENTED(USB_C0_BC12_INT_ODL) -UNIMPLEMENTED(USB_C1_BC12_INT_ODL) - -/* Other input pins */ -GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) -GPIO(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INPUT) -GPIO(CHARGER_INT_L, PIN(7, 3), GPIO_INPUT) - -/* Other output pins */ -GPIO(EC_PPEXT_EN1, PIN(C, 2), GPIO_OUT_HIGH) -GPIO(EC_I2CBUFFER_EN, PIN(9, 3), GPIO_OUT_LOW) -GPIO(UART2_EC_RX, PIN(7, 5), GPIO_OUT_LOW) - -/* LED Signals */ -GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_LOW) -GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_LOW) - -/* Misc Signals */ - -/* - * eDP backlight - both PCH and EC have enable pins that must be high - * for the backlight to turn on. Default state is high, and can be turned - * off during sleep states. - */ -GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) - -/* I2C pins - Alternate function below configures I2C module on these pins */ -GPIO(EC_I2C_0_SCL, PIN(B, 5), GPIO_INPUT) -GPIO(EC_I2C_0_SDA, PIN(B, 4), GPIO_INPUT) -GPIO(EC_I2C_1_SCL, PIN(9, 0), GPIO_INPUT) -GPIO(EC_I2C_1_SDA, PIN(8, 7), GPIO_INPUT) -GPIO(EC_I2C_2_SCL, PIN(9, 2), GPIO_INPUT) -GPIO(EC_I2C_2_SDA, PIN(9, 1), GPIO_INPUT) -GPIO(EC_I2C_3_SCL, PIN(D, 1), GPIO_INPUT) -GPIO(EC_I2C_3_SDA, PIN(D, 0), GPIO_INPUT) -GPIO(EC_I2C_4_SCL, PIN(F, 3), GPIO_INPUT) -GPIO(EC_I2C_4_SDA, PIN(F, 2), GPIO_INPUT) -GPIO(EC_I2C_5_SCL, PIN(3, 3), GPIO_INPUT) -GPIO(EC_I2C_5_SDA, PIN(3, 6), GPIO_INPUT) -GPIO(EC_I2C_7_SCL, PIN(B, 3), GPIO_INPUT) -GPIO(EC_I2C_7_SDA, PIN(B, 2), GPIO_INPUT) - -/* Battery signals */ -GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) - -/* Physical HPD pins are not needed on EC as these are configured by PMC */ -GPIO(USB_C0_DP_HPD, PIN(C, 6), GPIO_INPUT) -GPIO(USB_C1_DP_HPD, PIN(7, 0), GPIO_INPUT) -GPIO(USB_C2_DP_HPD, PIN(B, 7), GPIO_INPUT) - -/* Alternate functions GPIO definitions */ -ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ -ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ -ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ -ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ -ALTERNATE(PIN_MASK(F, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C4 */ -ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ -ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ - -/* Fan signals */ - -/* Keyboard pins */ -#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) -ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ -ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ -ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ -GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ -ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ -ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ -ALTERNATE(PIN_MASK(8, 0x0C), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14-15 */ -ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ - -/* UART */ -ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ - -/* Power Switch Logic (PSL) inputs */ -ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ -ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, - GPIO01 = H1_EC_PWR_BTN_ODL - GPIO02 = EC_RST_ODL */ - diff --git a/board/halvor/led.c b/board/halvor/led.c deleted file mode 100644 index 47753899bf..0000000000 --- a/board/halvor/led.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Power and battery LED control for Halvor - */ - -#include "ec_commands.h" -#include "gpio.h" -#include "led_common.h" -#include "led_onoff_states.h" -#include "chipset.h" - -#define LED_ON_LVL 1 -#define LED_OFF_LVL 0 - -const int led_charge_lvl_1 = 10; - -const int led_charge_lvl_2 = 100; - -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0_BAT_LOW] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC}, - {LED_OFF, 2 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED, -}; -const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); - -void led_set_color_battery(enum ec_led_colors color) -{ - gpio_set_level(GPIO_LED_2_L, - (color == EC_LED_COLOR_AMBER) ? LED_ON_LVL : LED_OFF_LVL); -} - -void led_set_color_power(enum ec_led_colors color) -{ - gpio_set_level(GPIO_LED_1_L, - (color == EC_LED_COLOR_WHITE) ? LED_ON_LVL : LED_OFF_LVL); -} - -void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) -{ - if (led_id == EC_LED_ID_BATTERY_LED) - brightness_range[EC_LED_COLOR_AMBER] = 1; - else if (led_id == EC_LED_ID_POWER_LED) - brightness_range[EC_LED_COLOR_WHITE] = 1; - -} - -int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) -{ - if (led_id == EC_LED_ID_BATTERY_LED) { - if (brightness[EC_LED_COLOR_AMBER] != 0) - led_set_color_battery(EC_LED_COLOR_AMBER); - else - led_set_color_battery(LED_OFF); - } else if (led_id == EC_LED_ID_POWER_LED) { - if (brightness[EC_LED_COLOR_WHITE] != 0) - led_set_color_power(EC_LED_COLOR_WHITE); - else - led_set_color_power(LED_OFF); - } - - return EC_SUCCESS; -} diff --git a/board/halvor/sensors.c b/board/halvor/sensors.c deleted file mode 100644 index b2795ee904..0000000000 --- a/board/halvor/sensors.c +++ /dev/null @@ -1,170 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer family-specific sensor configuration */ -#include "common.h" -#include "accelgyro.h" -#include "driver/accel_bma2x2.h" -#include "driver/als_tcs3400.h" -#include "driver/sync.h" -#include "keyboard_scan.h" -#include "hooks.h" -#include "task.h" -#include "util.h" - -/******************************************************************************/ -/* Sensors */ -static struct mutex g_lid_accel_mutex; - -/* BMA253 private data */ -static struct accelgyro_saved_data_t g_bma253_data; - -/* TCS3400 private data */ -static struct als_drv_data_t g_tcs3400_data = { - .als_cal.scale = 1, - .als_cal.uscale = 0, - .als_cal.offset = 0, - .als_cal.channel_scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ - .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */ - }, -}; - -/* - * TODO: b/146166425 need to calibrate ALS/RGB sensor. At default settings, - * shining phone flashlight on sensor pegs all readings at 0xFFFF. - */ -static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { - .calibration.rgb_cal[X] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - } - }, - .calibration.rgb_cal[Y] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - }, - }, - .calibration.rgb_cal[Z] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - } - }, - .calibration.irt = INT_TO_FP(1), - .saturation.again = TCS_DEFAULT_AGAIN, - .saturation.atime = TCS_DEFAULT_ATIME, -}; - -/* Rotation matrix for the lid accelerometer */ -/* TODO: b/146144170 - the accelerometer is on the motherboard for proto1 - * for testing. Once the sensor moves to the lid, the rotation matrix needs - * to be updated for correct behavior. - */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -struct motion_sensor_t motion_sensors[] = { - [LID_ACCEL] = { - .name = "Lid Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMA255, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &bma2x2_accel_drv, - .mutex = &g_lid_accel_mutex, - .drv_data = &g_bma253_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .min_frequency = BMA255_ACCEL_MIN_FREQ, - .max_frequency = BMA255_ACCEL_MAX_FREQ, - .default_range = 2, /* g, to support tablet mode */ - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - /* Sensor on in S3 */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - }, - }, - - [CLEAR_ALS] = { - .name = "Clear Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT, - .location = MOTIONSENSE_LOC_BASE, - .drv = &tcs3400_drv, - .drv_data = &g_tcs3400_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - .min_frequency = TCS3400_LIGHT_MIN_FREQ, - .max_frequency = TCS3400_LIGHT_MAX_FREQ, - .config = { - /* Run ALS sensor in S0 */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 1000, - }, - }, - }, - - [RGB_ALS] = { - /* - * RGB channels read by CLEAR_ALS and so the i2c port and - * address do not need to be defined for RGB_ALS. - */ - .name = "RGB Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT_RGB, - .location = MOTIONSENSE_LOC_BASE, - .drv = &tcs3400_rgb_drv, - .drv_data = &g_tcs3400_rgb_data, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - }, -}; -unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ -const struct motion_sensor_t *motion_als_sensors[] = { - &motion_sensors[CLEAR_ALS], -}; -BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); - -static void baseboard_sensors_init(void) -{ - /* Note - BMA253 interrupt unused by EC */ - - /* Enable interrupt for the TCS3400 color light sensor */ - gpio_enable_interrupt(GPIO_EC_ALS_RGB_INT_L); -} -DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); diff --git a/board/hammer/battery.c b/board/hammer/battery.c index 4025a08b14..df6a716cd7 100644 --- a/board/hammer/battery.c +++ b/board/hammer/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,8 +13,8 @@ #include "util.h" /* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS -#define SB_SHUTDOWN_DATA 0x0010 +#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS +#define SB_SHUTDOWN_DATA 0x0010 static const struct battery_info info = { .voltage_max = 8800, diff --git a/board/hammer/board.c b/board/hammer/board.c index c6149a678c..2e46a636f3 100644 --- a/board/hammer/board.c +++ b/board/hammer/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,8 +9,8 @@ #include "common.h" #include "driver/charger/isl923x.h" #include "driver/led/lm3630a.h" +#include "ec_ec_comm_server.h" #include "ec_version.h" -#include "ec_ec_comm_slave.h" #include "gpio.h" #include "hooks.h" #include "hwtimer.h" @@ -28,18 +28,19 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "touchpad.h" #include "timer.h" +#include "touchpad.h" #include "update_fw.h" #include "usart-stm32f0.h" -#include "usart_tx_dma.h" #include "usart_rx_dma.h" +#include "usart_tx_dma.h" #include "usb_api.h" #include "usb_descriptor.h" #include "usb_i2c.h" #include "usb_spi.h" #include "util.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" #ifdef SECTION_IS_RW @@ -48,20 +49,21 @@ #define CROS_EC_SECTION "RO" #endif -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("Hammer"), - [USB_STR_SERIALNO] = 0, - [USB_STR_VERSION] = - USB_STRING_DESC(CROS_EC_SECTION ":" CROS_EC_VERSION32), - [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), - [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Hammer"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = + USB_STRING_DESC(CROS_EC_SECTION ":" CROS_EC_VERSION32), + [USB_STR_SPI_NAME] = USB_STRING_DESC("SPI"), + [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), #ifdef CONFIG_USB_ISOCHRONOUS [USB_STR_HEATMAP_NAME] = USB_STRING_DESC("Heatmap"), #endif @@ -77,24 +79,34 @@ BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); #ifdef HAS_SPI_TOUCHPAD /* SPI devices */ const struct spi_device_t spi_devices[] = { - [SPI_ST_TP_DEVICE_ID] = { CONFIG_SPI_TOUCHPAD_PORT, 2, GPIO_SPI1_NSS }, + [SPI_ST_TP_DEVICE_ID] = { CONFIG_SPI_TOUCHPAD_PORT, 2, GPIO_SPI1_NSS, + USB_SPI_ENABLED }, }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); -USB_SPI_CONFIG(usb_spi, USB_IFACE_I2C_SPI, USB_EP_I2C_SPI, 0); /* SPI interface is always enabled, no need to do anything. */ -void usb_spi_board_enable(struct usb_spi_config const *config) {} -void usb_spi_board_disable(struct usb_spi_config const *config) {} -#endif /* !HAS_SPI_TOUCHPAD */ +void usb_spi_board_enable(void) +{ +} +void usb_spi_board_disable(void) +{ +} +#endif /* !HAS_SPI_TOUCHPAD */ #ifdef CONFIG_I2C /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 400, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + { .name = "master", + .port = I2C_PORT_MASTER, + .kbps = 400, + .scl = GPIO_MASTER_I2C_SCL, + .sda = GPIO_MASTER_I2C_SDA }, #ifdef BOARD_WAND - {"charger", I2C_PORT_CHARGER, 100, - GPIO_CHARGER_I2C_SCL, GPIO_CHARGER_I2C_SDA}, + { .name = "charger", + .port = I2C_PORT_CHARGER, + .kbps = 100, + .scl = GPIO_CHARGER_I2C_SCL, + .sda = GPIO_CHARGER_I2C_SDA }, #endif }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -114,7 +126,7 @@ const struct charger_config_t chg_chips[] = { #ifdef HAS_BACKLIGHT /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - {STM32_TIM(TIM_KBLIGHT), STM32_TIM_CH(1), 0, KBLIGHT_PWM_FREQ}, + { STM32_TIM(TIM_KBLIGHT), STM32_TIM_CH(1), 0, KBLIGHT_PWM_FREQ }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); #endif /* HAS_BACKLIGHT */ @@ -125,8 +137,7 @@ int usb_i2c_board_is_enabled(void) return !system_is_locked(); } -#ifdef CONFIG_KEYBOARD_BOARD_CONFIG -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { .output_settle_us = 50, .debounce_down_us = 9 * MSEC, .debounce_up_us = 30 * MSEC, @@ -139,32 +150,27 @@ struct keyboard_scan_config keyscan_config = { }, }; #endif -#endif #if defined(BOARD_WAND) && defined(SECTION_IS_RW) struct consumer const ec_ec_usart_consumer; static struct usart_config const ec_ec_usart; -struct queue const ec_ec_comm_slave_input = QUEUE_DIRECT(64, uint8_t, - ec_ec_usart.producer, ec_ec_usart_consumer); -struct queue const ec_ec_comm_slave_output = QUEUE_DIRECT(64, uint8_t, - null_producer, ec_ec_usart.consumer); +struct queue const ec_ec_comm_server_input = + QUEUE_DIRECT(64, uint8_t, ec_ec_usart.producer, ec_ec_usart_consumer); +struct queue const ec_ec_comm_server_output = + QUEUE_DIRECT(64, uint8_t, null_producer, ec_ec_usart.consumer); struct consumer const ec_ec_usart_consumer = { - .queue = &ec_ec_comm_slave_input, - .ops = &((struct consumer_ops const) { - .written = ec_ec_comm_slave_written, + .queue = &ec_ec_comm_server_input, + .ops = &((struct consumer_ops const){ + .written = ec_ec_comm_server_written, }), }; static struct usart_config const ec_ec_usart = - USART_CONFIG(EC_EC_UART, - usart_rx_interrupt, - usart_tx_interrupt, - 115200, - USART_CONFIG_FLAG_HDSEL, - ec_ec_comm_slave_input, - ec_ec_comm_slave_output); + USART_CONFIG(EC_EC_UART, usart_rx_interrupt, usart_tx_interrupt, 115200, + USART_CONFIG_FLAG_HDSEL, ec_ec_comm_server_input, + ec_ec_comm_server_output); #endif /* BOARD_WAND && SECTION_IS_RW */ /****************************************************************************** @@ -184,8 +190,8 @@ static void board_init(void) #ifdef BOARD_WAND /* USB to serial queues */ - queue_init(&ec_ec_comm_slave_input); - queue_init(&ec_ec_comm_slave_output); + queue_init(&ec_ec_comm_server_input); + queue_init(&ec_ec_comm_server_output); /* UART init */ usart_init(&ec_ec_usart); @@ -196,10 +202,10 @@ static void board_init(void) #endif #ifdef HAS_SPI_TOUCHPAD - spi_enable(CONFIG_SPI_TOUCHPAD_PORT, 0); + spi_enable(&spi_devices[SPI_ST_TP_DEVICE_ID], 0); /* Disable SPI passthrough when the system is locked */ - usb_spi_enable(&usb_spi, system_is_locked()); + usb_spi_enable(system_is_locked()); /* Set all four SPI pins to high speed */ /* pins B3/5, A15 */ @@ -214,8 +220,8 @@ static void board_init(void) clock_wait_bus_cycles(BUS_APB, 1); /* Enable SPI for touchpad */ - gpio_config_module(MODULE_SPI_MASTER, 1); - spi_enable(CONFIG_SPI_TOUCHPAD_PORT, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); + spi_enable(&spi_devices[SPI_ST_TP_DEVICE_ID], 1); #endif /* HAS_SPI_TOUCHPAD */ } /* This needs to happen before PWM is initialized. */ @@ -271,9 +277,9 @@ static void board_tablet_mode_change(void) keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); } DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, board_tablet_mode_change, - HOOK_PRIO_DEFAULT); + HOOK_PRIO_DEFAULT); /* Run after tablet_mode_init. */ -DECLARE_HOOK(HOOK_INIT, board_tablet_mode_change, HOOK_PRIO_DEFAULT+1); +DECLARE_HOOK(HOOK_INIT, board_tablet_mode_change, HOOK_PRIO_DEFAULT + 1); #endif /* @@ -286,7 +292,7 @@ int board_get_entropy(void *buffer, int len) uint8_t *data = buffer; uint32_t start; /* We expect one SOF per ms, so wait at most 2ms. */ - const uint32_t timeout = 2*MSEC; + const uint32_t timeout = 2 * MSEC; for (i = 0; i < len; i++) { STM32_CRS_ICR |= STM32_CRS_ICR_SYNCOKC; @@ -317,8 +323,9 @@ __override const char *board_read_serial(void) int i; for (i = 0; i < idlen && pos < sizeof(str); i++, pos += 2) { - snprintf(&str[pos], sizeof(str)-pos, - "%02x", id[i]); + if (snprintf(&str[pos], sizeof(str) - pos, "%02x", + id[i]) < 0) + return NULL; } } @@ -329,3 +336,68 @@ __override int board_write_serial(const char *serialno) { return 0; } + +static const struct ec_response_keybd_config zed_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, + TK_REFRESH, + TK_FULLSCREEN, + TK_OVERVIEW, + TK_SNAPSHOT, + TK_BRIGHTNESS_DOWN, + TK_BRIGHTNESS_UP, + TK_VOL_MUTE, + TK_VOL_DOWN, + TK_VOL_UP, + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config bland_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, + TK_REFRESH, + TK_FULLSCREEN, + TK_OVERVIEW, + TK_BRIGHTNESS_DOWN, + TK_BRIGHTNESS_UP, + TK_MICMUTE, + TK_VOL_MUTE, + TK_VOL_DOWN, + TK_VOL_UP, + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config duck_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, + TK_FORWARD, + TK_REFRESH, + TK_FULLSCREEN, + TK_OVERVIEW, + TK_BRIGHTNESS_DOWN, + TK_BRIGHTNESS_UP, + TK_VOL_MUTE, + TK_VOL_DOWN, + TK_VOL_UP, + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (IS_ENABLED(BOARD_ZED) || IS_ENABLED(BOARD_STAR) || + IS_ENABLED(BOARD_GELATIN)) + return &zed_kb; + if (IS_ENABLED(BOARD_BLAND) || IS_ENABLED(BOARD_EEL)) + return &bland_kb; + if (IS_ENABLED(BOARD_DUCK)) + return &duck_kb; + + return NULL; +} diff --git a/board/hammer/board.h b/board/hammer/board.h index d1a7af0bfe..d5ab4699ac 100644 --- a/board/hammer/board.h +++ b/board/hammer/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -46,28 +46,27 @@ /* Do not use a dedicated PSTATE bank */ #undef CONFIG_FLASH_PSTATE_BANK -#define CONFIG_SHAREDLIB_SIZE 0 +#define CONFIG_SHAREDLIB_SIZE 0 -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RO_SIZE (44*1024) +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (44 * 1024) /* EC rollback protection block */ #define CONFIG_ROLLBACK_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) #define CONFIG_ROLLBACK_SIZE CONFIG_FLASH_BANK_SIZE -#define CONFIG_RW_MEM_OFF (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) -#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE - \ - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) +#define CONFIG_RW_MEM_OFF (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE_BYTES - CONFIG_RW_MEM_OFF) -#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE +#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* The UART console is on USART1 (PA9/PA10) */ #undef CONFIG_UART_CONSOLE @@ -83,7 +82,7 @@ #endif #define CONFIG_LTO #define CONFIG_FORCE_CONSOLE_RESUME -#define CONFIG_STM_HWTIMER32 +#define CONFIG_MATH_UTIL /* USB Configuration */ #define CONFIG_USB @@ -91,8 +90,8 @@ #define CONFIG_USB_UPDATE #undef CONFIG_UPDATE_PDU_SIZE -#ifdef BOARD_WAND -/* Wand does not have enough space to fit 4k PDU. */ +#if defined(BOARD_WAND) || defined(VARIANT_HAMMER_TP_LARGE_PAGE) +/* Wand/Zed does not have enough space to fit 4k PDU. */ #define CONFIG_UPDATE_PDU_SIZE 2048 #else #define CONFIG_UPDATE_PDU_SIZE 4096 @@ -110,48 +109,48 @@ /* USB interface indexes (use define rather than enum to expand them) */ #ifdef SECTION_IS_RW -#define USB_IFACE_HID_KEYBOARD 0 -#define USB_IFACE_UPDATE 1 +#define USB_IFACE_HID_KEYBOARD 0 +#define USB_IFACE_UPDATE 1 #ifdef HAS_NO_TOUCHPAD -#define USB_IFACE_COUNT 2 +#define USB_IFACE_COUNT 2 #else /* !HAS_NO_TOUCHPAD */ -#define USB_IFACE_HID_TOUCHPAD 2 +#define USB_IFACE_HID_TOUCHPAD 2 /* Can be either I2C or SPI passthrough, depending on the board. */ -#define USB_IFACE_I2C_SPI 3 +#define USB_IFACE_I2C_SPI 3 #if defined(CONFIG_USB_ISOCHRONOUS) -#define USB_IFACE_ST_TOUCHPAD 4 -#define USB_IFACE_COUNT 5 -#else /* !CONFIG_USB_ISOCHRONOUS */ -#define USB_IFACE_COUNT 4 -#endif /* CONFIG_USB_ISOCHRONOUS */ +#define USB_IFACE_ST_TOUCHPAD 4 +#define USB_IFACE_COUNT 5 +#else /* !CONFIG_USB_ISOCHRONOUS */ +#define USB_IFACE_COUNT 4 +#endif /* CONFIG_USB_ISOCHRONOUS */ #endif /* !HAS_NO_TOUCHPAD */ -#else /* !SECTION_IS_RW */ -#define USB_IFACE_UPDATE 0 -#define USB_IFACE_COUNT 1 -#endif /* SECTION_IS_RW */ +#else /* !SECTION_IS_RW */ +#define USB_IFACE_UPDATE 0 +#define USB_IFACE_COUNT 1 +#endif /* SECTION_IS_RW */ /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_UPDATE 1 +#define USB_EP_CONTROL 0 +#define USB_EP_UPDATE 1 #ifdef SECTION_IS_RW -#define USB_EP_HID_KEYBOARD 2 +#define USB_EP_HID_KEYBOARD 2 #ifdef HAS_NO_TOUCHPAD -#define USB_EP_COUNT 3 +#define USB_EP_COUNT 3 #else /* !HAS_NO_TOUCHPAD */ -#define USB_EP_HID_TOUCHPAD 3 +#define USB_EP_HID_TOUCHPAD 3 /* Can be either I2C or SPI passthrough, depending on the board. */ -#define USB_EP_I2C_SPI 4 +#define USB_EP_I2C_SPI 4 #if defined(CONFIG_USB_ISOCHRONOUS) -#define USB_EP_ST_TOUCHPAD 5 -#define USB_EP_ST_TOUCHPAD_INT 6 -#define USB_EP_COUNT 7 +#define USB_EP_ST_TOUCHPAD 5 +#define USB_EP_ST_TOUCHPAD_INT 6 +#define USB_EP_COUNT 7 #else /* !CONFIG_USB_ISOCHRONOUS */ -#define USB_EP_COUNT 5 +#define USB_EP_COUNT 5 #endif /* CONFIG_USB_ISOCHRONOUS */ #endif /* !HAS_NO_TOUCHPAD */ -#else /* !SECTION_IS_RW */ -#define USB_EP_COUNT 2 -#endif /* SECTION_IS_RW */ +#else /* !SECTION_IS_RW */ +#define USB_EP_COUNT 2 +#endif /* SECTION_IS_RW */ /* Optional features */ #define CONFIG_BOARD_PRE_INIT @@ -175,12 +174,23 @@ * buffer size have to be power of two. */ #undef CONFIG_USB_I2C_MAX_WRITE_COUNT -#define CONFIG_USB_I2C_MAX_WRITE_COUNT (128 - 4) /* 4 is maximum header size */ +#ifdef VARIANT_HAMMER_TP_LARGE_PAGE +/* Zed requires 516 byte per packet for touchpad update */ +#define CONFIG_USB_I2C_MAX_WRITE_COUNT \ + (1024 - 4) /* 4 is maximum header size \ + */ +#else +#define CONFIG_USB_I2C_MAX_WRITE_COUNT \ + (128 - 4) /* 4 is maximum header size \ + */ +#endif #undef CONFIG_USB_I2C_MAX_READ_COUNT -#define CONFIG_USB_I2C_MAX_READ_COUNT (1024 - 6) /* 6 is maximum header size */ +#define CONFIG_USB_I2C_MAX_READ_COUNT \ + (1024 - 6) /* 6 is maximum header size \ + */ -#define CONFIG_I2C_XFER_LARGE_READ +#define CONFIG_I2C_XFER_LARGE_TRANSFER /* No lid switch */ #undef CONFIG_LID_SWITCH @@ -196,7 +206,7 @@ #define CONFIG_USB_HID_TOUCHPAD /* Virtual address for touchpad FW in USB updater. */ -#define CONFIG_TOUCHPAD_VIRTUAL_OFF 0x80000000 +#define CONFIG_TOUCHPAD_VIRTUAL_OFF 0x80000000 /* Include touchpad FW hashes in image */ #define CONFIG_TOUCHPAD_HASH_FW @@ -210,7 +220,7 @@ #if defined(HAS_I2C_TOUCHPAD) || defined(CONFIG_LED_DRIVER_LM3630A) #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define I2C_PORT_MASTER 0 #define I2C_PORT_KBLIGHT 0 #define I2C_PORT_CHARGER 1 @@ -223,19 +233,20 @@ #ifdef CONFIG_GMR_TABLET_MODE #define CONFIG_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L #define CONFIG_KEYBOARD_TABLET_MODE_SWITCH #endif #ifdef HAS_SPI_TOUCHPAD /* Enable control of SPI over USB */ #define CONFIG_USB_SPI -#define CONFIG_SPI_MASTER +#define USB_IFACE_SPI USB_IFACE_I2C_SPI +#define USB_EP_SPI USB_EP_I2C_SPI +#define CONFIG_SPI_CONTROLLER #define CONFIG_SPI_HALFDUPLEX -#define CONFIG_STM32_SPI1_MASTER +#define CONFIG_STM32_SPI1_CONTROLLER #define CONFIG_SPI_TOUCHPAD_PORT 0 #define SPI_ST_TP_DEVICE_ID 0 -/* Enable SPI master xfer command */ +/* Enable SPI controller xfer command */ #define CONFIG_CMD_SPI_XFER #define CONFIG_TOUCHPAD #define CONFIG_TOUCHPAD_ST @@ -260,7 +271,7 @@ #ifdef BOARD_WAND /* Battery and charger options. */ #define CONFIG_CHARGER -#define CONFIG_CHARGER_INPUT_CURRENT 128 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 128 #define CONFIG_CHARGER_ISL9238 #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 @@ -278,7 +289,7 @@ #define CONFIG_STREAM_USART2 #define CONFIG_STREAM_USART -#define CONFIG_EC_EC_COMM_SLAVE +#define CONFIG_EC_EC_COMM_SERVER #define CONFIG_EC_EC_COMM_BATTERY #define CONFIG_CRC8 #endif /* BOARD_WAND */ @@ -302,6 +313,7 @@ /* * Add rollback protection, and independent RW region protection. */ +#define CONFIG_LIBCRYPTOC #define CONFIG_ROLLBACK #define CONFIG_ROLLBACK_SECRET_SIZE 32 #define CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE 32 @@ -311,10 +323,10 @@ #endif /* Maximum current to draw. */ -#define MAX_CURRENT_MA 2000 +#define MAX_CURRENT_MA 2000 /* Maximum current/voltage to provide over OTG. */ -#define MAX_OTG_CURRENT_MA 2000 -#define MAX_OTG_VOLTAGE_MV 20000 +#define MAX_OTG_CURRENT_MA 2000 +#define MAX_OTG_VOLTAGE_MV 20000 #ifndef __ASSEMBLER__ @@ -332,6 +344,7 @@ enum usb_strings { USB_STR_PRODUCT, USB_STR_SERIALNO, USB_STR_VERSION, + USB_STR_SPI_NAME, USB_STR_I2C_NAME, USB_STR_UPDATE_NAME, #ifdef CONFIG_USB_ISOCHRONOUS diff --git a/board/hammer/build.mk b/board/hammer/build.mk index b32a6b768a..d41aed0d84 100644 --- a/board/hammer/build.mk +++ b/board/hammer/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/hammer/ec.tasklist b/board/hammer/ec.tasklist index ecdb6db120..e528d20cd8 100644 --- a/board/hammer/ec.tasklist +++ b/board/hammer/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,7 +13,7 @@ TASK_ALWAYS_RW(TOUCHPAD, touchpad_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS_RW(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS (CONSOLE, console_task, NULL, 1024) \ - TASK_ALWAYS_RW(ECCOMM, ec_ec_comm_slave_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(ECCOMM, ec_ec_comm_server_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST_RW(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) #elif defined(CONFIG_USB_ISOCHRONOUS) #define CONFIG_TASK_LIST \ diff --git a/board/hammer/gpio.inc b/board/hammer/gpio.inc index a94c0aa7e4..d79895564d 100644 --- a/board/hammer/gpio.inc +++ b/board/hammer/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -126,7 +126,7 @@ ALTERNATE(PIN_MASK(B, 0x0c00), 1, MODULE_I2C, 0) /* I2C CHARGER: PB10/11 GPIO_O #endif #ifdef HAS_SPI_TOUCHPAD -ALTERNATE(PIN_MASK(B, 0x0038), 0, MODULE_SPI_MASTER, 0) /* SPI MASTER:PB3/4/5 */ +ALTERNATE(PIN_MASK(B, 0x0038), 0, MODULE_SPI_CONTROLLER, 0) /* SPI MASTER:PB3/4/5 */ #endif #ifdef CONFIG_I2C diff --git a/board/hammer/variants.h b/board/hammer/variants.h index 7829e3a34a..12b955dc43 100644 --- a/board/hammer/variants.h +++ b/board/hammer/variants.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,6 +15,18 @@ /* USB ID */ #ifdef BOARD_HAMMER #define CONFIG_USB_PID 0x5022 +#elif defined(BOARD_BLAND) +#define CONFIG_USB_PID 0x5056 +#elif defined(BOARD_DON) +#define CONFIG_USB_PID 0x5050 +#elif defined(BOARD_DUCK) +#define CONFIG_USB_PID 0x505b +#elif defined(BOARD_EEL) +#define CONFIG_USB_PID 0x5057 +#elif defined(BOARD_GELATIN) +#define CONFIG_USB_PID 0x505D +#elif defined(BOARD_JEWEL) +#define CONFIG_USB_PID 0x5061 #elif defined(BOARD_MAGNEMITE) #define CONFIG_USB_PID 0x503d #elif defined(BOARD_MASTERBALL) @@ -23,13 +35,14 @@ #define CONFIG_USB_PID 0x5044 #elif defined(BOARD_STAFF) #define CONFIG_USB_PID 0x502b +#elif defined(BOARD_STAR) +#define CONFIG_USB_PID 0x5052 #elif defined(BOARD_WAND) #define CONFIG_USB_PID 0x502d #elif defined(BOARD_WHISKERS) #define CONFIG_USB_PID 0x5030 #elif defined(BOARD_ZED) -/* TODO: update PID */ -#define CONFIG_USB_PID 0x5022 +#define CONFIG_USB_PID 0x504c #else #error "Invalid board" #endif @@ -44,7 +57,64 @@ #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 #define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 1018 /* tenth of mm */ #define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 566 /* tenth of mm */ -#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (48*1024) +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (48 * 1024) +#elif defined(BOARD_BLAND) +#define CONFIG_USB_HID_KEYBOARD_VIVALDI +#define CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS 10 +#define HAS_I2C_TOUCHPAD +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 2644 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1440 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 839 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 457 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (64 * 1024) +#elif defined(BOARD_DON) +#define HAS_I2C_TOUCHPAD +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 2925 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1440 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 929 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 457 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (56 * 1024) +#elif defined(BOARD_DUCK) +#define CONFIG_USB_HID_KEYBOARD_VIVALDI +#define CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS 10 +#define HAS_I2C_TOUCHPAD +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 2644 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1440 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 839 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 457 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (64 * 1024) +#elif defined(BOARD_EEL) +#define CONFIG_USB_HID_KEYBOARD_VIVALDI +#define CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS 10 +#define HAS_I2C_TOUCHPAD +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 2644 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1440 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 839 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 457 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (64 * 1024) +#elif defined(BOARD_GELATIN) +#define CONFIG_USB_HID_KEYBOARD_VIVALDI +#define CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS 10 +#define HAS_I2C_TOUCHPAD +/* TODO: update correct parameters */ +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 3340 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1811 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 1060 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 575 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (64 * 1024) +#elif defined(BOARD_JEWEL) +#define HAS_I2C_TOUCHPAD +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 2925 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1440 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 929 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 457 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (56 * 1024) #elif defined(BOARD_MAGNEMITE) #define HAS_NO_TOUCHPAD #elif defined(BOARD_MASTERBALL) @@ -54,56 +124,69 @@ #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 #define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 839 /* tenth of mm */ #define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 457 /* tenth of mm */ -#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (64*1024) +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (64 * 1024) #elif defined(BOARD_MOONBALL) #define HAS_I2C_TOUCHPAD -#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 2926 -#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1441 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 2925 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1440 #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 -#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 950 /* tenth of mm */ -#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 480 /* tenth of mm */ -#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (56*1024) +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 929 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 457 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (56 * 1024) #elif defined(BOARD_STAFF) #define HAS_I2C_TOUCHPAD #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 3206 #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1832 #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 -#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 1017 /* tenth of mm */ -#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 581 /* tenth of mm */ -#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (56*1024) +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 1018 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 582 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (56 * 1024) +#elif defined(BOARD_STAR) +#define CONFIG_USB_HID_KEYBOARD_VIVALDI +#define CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS 10 +#define HAS_I2C_TOUCHPAD +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 3282 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1793 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 1042 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 569 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (64 * 1024) #elif defined(BOARD_WHISKERS) #define HAS_SPI_TOUCHPAD #define HAS_EN_PP3300_TP_ACTIVE_HIGH #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 2160 #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1573 #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 255 -#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 1030 /* tenth of mm */ -#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 750 /* tenth of mm */ -#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (CONFIG_UPDATE_PDU_SIZE + 128*1024) +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 1031 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 751 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (CONFIG_UPDATE_PDU_SIZE + 128 * 1024) /* Enable to send heatmap to AP */ #define CONFIG_USB_ISOCHRONOUS #elif defined(BOARD_ZED) +#define CONFIG_USB_HID_KEYBOARD_VIVALDI +#define CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS 10 + /* TODO: update correct parameters */ #define HAS_I2C_TOUCHPAD -#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 3207 -#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1783 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X 3340 +#define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y 1811 #define CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE 511 -#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 1018 /* tenth of mm */ -#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 566 /* tenth of mm */ -#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (48*1024) +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X 1060 /* tenth of mm */ +#define CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y 575 /* tenth of mm */ +#define CONFIG_TOUCHPAD_VIRTUAL_SIZE (64 * 1024) #else #error "No touchpad information for board." #endif /* Assistant key */ #if defined(BOARD_HAMMER) || defined(BOARD_WAND) || defined(BOARD_WHISKERS) -#define CONFIG_KEYBOARD_BOARD_CONFIG + #define CONFIG_KEYBOARD_ASSISTANT_KEY #endif /* Backlight */ -#if defined(BOARD_HAMMER) || defined(BOARD_STAFF) || \ - defined(BOARD_WAND) || defined(BOARD_WHISKERS) +#if defined(BOARD_HAMMER) || defined(BOARD_STAFF) || defined(BOARD_WAND) || \ + defined(BOARD_WHISKERS) /* * Even with this option, we detect the backlight presence using a PU/PD on the * PWM pin. Not defining this totally disables support. @@ -123,11 +206,17 @@ #endif /* BOARD_HAMMER/WAND/WHISKERS */ /* GMR sensor for tablet mode detection */ -#if defined(BOARD_MASTERBALL) || defined(BOARD_MOONBALL) || \ - defined(BOARD_WHISKERS) +#if defined(BOARD_DON) || defined(BOARD_MASTERBALL) || \ + defined(BOARD_MOONBALL) || defined(BOARD_WHISKERS) || \ + defined(BOARD_EEL) || defined(BOARD_JEWEL) #define CONFIG_GMR_TABLET_MODE #endif #endif /* SECTION_IS_RW */ +/* Enable if the touchpad has >= 128 bytes per page */ +#if defined(BOARD_ZED) || defined(BOARD_DUCK) +#define VARIANT_HAMMER_TP_LARGE_PAGE +#endif + #endif /* __CROS_EC_VARIANTS_H */ diff --git a/board/hatch/battery.c b/board/hatch/battery.c index b81fa795b9..444262b353 100644 --- a/board/hatch/battery.c +++ b/board/hatch/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/hatch/board.c b/board/hatch/board.c index 69da3f5328..373afcaea6 100644 --- a/board/hatch/board.c +++ b/board/hatch/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Hatch board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" @@ -35,16 +34,16 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* GPIO to enable/disable the USB Type-A port. */ const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { @@ -94,11 +93,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -106,20 +105,21 @@ static void bc12_interrupt(enum gpio_signal signal) } } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, - [PWM_CH_FAN] = {.channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -139,22 +139,26 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -221,22 +225,18 @@ static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { }; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* * TODO(b/124337208): P0 boards don't have this sensor mounted so the rotation * matrix can't be tested properly. This needs to be revisited after EVT to make * sure the rotaiton matrix for the lid sensor is correct. */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -360,7 +360,7 @@ BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -379,52 +379,56 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Temp1", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Temp2", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, + [TEMP_SENSOR_1] = { .name = "Temp1", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Temp2", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - /* Hatch Temperature sensors */ /* * TODO(b/124316213): These setting need to be reviewed and set appropriately * for Hatch. They matter when the EC is controlling the fan as opposed to DPTF * control. */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -465,7 +469,6 @@ static void board_gpio_set_pp5000(void) } else if (board_id >= 1) { reset_gpio_flags(GPIO_EN_PP5000_A_V1, GPIO_OUT_LOW); } - } static void board_init(void) diff --git a/board/hatch/board.h b/board/hatch/board.h index 057475cb55..0de9a4828f 100644 --- a/board/hatch/board.h +++ b/board/hatch/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -26,7 +26,6 @@ /* Sensors */ /* BMI160 Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) @@ -44,7 +43,7 @@ #define CONFIG_ALS_TCS3400 #define CONFIG_ALS_TCS3400_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) -#define I2C_PORT_ALS I2C_PORT_SENSOR +#define I2C_PORT_ALS I2C_PORT_SENSOR /* USB Type C and USB PD defines */ #define CONFIG_USB_PD_COMM_LOCKED @@ -89,7 +88,7 @@ #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 50 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -108,15 +107,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -128,8 +128,8 @@ extern enum gpio_signal gpio_en_pp5000_a; enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ ADC_CH_COUNT }; @@ -142,11 +142,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, @@ -160,11 +156,7 @@ enum mft_channel { MFT_CH_COUNT, }; -enum temp_sensor_id { - TEMP_SENSOR_1, - TEMP_SENSOR_2, - TEMP_SENSOR_COUNT -}; +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { diff --git a/board/hatch/build.mk b/board/hatch/build.mk index 733912454f..13153c1526 100644 --- a/board/hatch/build.mk +++ b/board/hatch/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/hatch/ec.tasklist b/board/hatch/ec.tasklist index 4a1024a091..829be2b7c8 100644 --- a/board/hatch/ec.tasklist +++ b/board/hatch/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/hatch/gpio.inc b/board/hatch/gpio.inc index cd241f15f5..22cda73feb 100644 --- a/board/hatch/gpio.inc +++ b/board/hatch/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,10 +16,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) diff --git a/board/hatch/led.c b/board/hatch/led.c index d6da1d098f..92332d5978 100644 --- a/board/hatch/led.c +++ b/board/hatch/led.c @@ -1,43 +1,48 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Hatch */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -76,4 +81,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/hatch/vif_override.xml b/board/hatch/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/hatch/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/hatch_fp/board.c b/board/hatch_fp/board.c index e42f576ad8..b213d1ab9e 100644 --- a/board/hatch_fp/board.c +++ b/board/hatch_fp/board.c @@ -1,8 +1,7 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* Meowth Fingerprint MCU configuration */ #include "common.h" #include "console.h" @@ -14,7 +13,6 @@ #include "system.h" #include "task.h" #include "usart_host_command.h" -#include "util.h" /** * Disable restricted commands when the system is locked. @@ -26,22 +24,31 @@ int console_is_restricted(void) return system_is_locked(); } -#ifndef HAS_TASK_FPSENSOR -void fps_event(enum gpio_signal signal) -{ -} -#endif +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* + * Some platforms have a broken SLP_S0_L signal (stuck to 0 in S0) + * if set, ignore it and only uses SLP_S3_L for the AP state. + */ +static bool broken_slp; static void ap_deferred(void) { /* - * in S3: SLP_S3_L is 0 and SLP_S0_L is X. - * in S0ix: SLP_S3_L is X and SLP_S0_L is 0. - * in S0: SLP_S3_L is 1 and SLP_S0_L is 1. + * Behavior: + * AP Active (ex. Intel S0): SLP_L is 1 + * AP Suspend (ex. Intel S0ix): SLP_L is 0 + * The alternative SLP_ALT_L should be pulled high at all the times. + * + * Legacy Intel behavior: + * in S3: SLP_ALT_L is 0 and SLP_L is X. + * in S0ix: SLP_ALT_L is 1 and SLP_L is 0. + * in S0: SLP_ALT_L is 1 and SLP_L is 1. * in S5/G3, the FP MCU should not be running. */ - int running = gpio_get_level(GPIO_PCH_SLP_S3_L) - && gpio_get_level(GPIO_PCH_SLP_S0_L); + int running = gpio_get_level(GPIO_SLP_ALT_L) && + (gpio_get_level(GPIO_SLP_L) || broken_slp); if (running) { /* S0 */ disable_sleep(SLEEP_MASK_AP_RUN); @@ -59,44 +66,24 @@ void slp_event(enum gpio_signal signal) hook_call_deferred(&ap_deferred_data, 0); } -#include "gpio_list.h" - -/* SPI devices */ -const struct spi_device_t spi_devices[] = { - /* Fingerprint sensor (SCLK at 4Mhz) */ - { .port = CONFIG_SPI_FP_PORT, .div = 3, .gpio_cs = GPIO_SPI2_NSS } -}; -const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); - -static void configure_fp_sensor_spi(void) -{ - /* Configure SPI GPIOs */ - gpio_config_module(MODULE_SPI_MASTER, 1); - - /* Set all SPI master signal pins to very high speed: B12/13/14/15 */ - STM32_GPIO_OSPEEDR(GPIO_B) |= 0xff000000; - - /* Enable clocks to SPI2 module (master) */ - STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; - - spi_enable(CONFIG_SPI_FP_PORT, 1); -} - -/* Initialize board. */ -static void board_init(void) +static void board_init_transport(void) { enum fp_transport_type ret_transport = get_fp_transport_type(); - /* Configure and enable SPI as master for FP sensor */ - configure_fp_sensor_spi(); - - ccprints("TRANSPORT_SEL: %s", - fp_transport_type_to_str(ret_transport)); + ccprints("TRANSPORT_SEL: %s", fp_transport_type_to_str(ret_transport)); /* Initialize transport based on bootstrap */ switch (ret_transport) { - case FP_TRANSPORT_TYPE_UART: + /* + * The Zork variants currently have a broken SLP_S0_L signal + * (stuck to 0 in S0). For now, unconditionally ignore it here + * as they are the only UART users and the AP has no S0ix state. + * TODO(b/174695987) once the RW AP firmware has been updated + * on all those machines, remove this workaround. + */ + broken_slp = true; + /* Check if CONFIG_USART_HOST_COMMAND is enabled. */ if (IS_ENABLED(CONFIG_USART_HOST_COMMAND)) usart_host_command_init(); @@ -117,13 +104,29 @@ static void board_init(void) } ccprints("TRANSPORT_SEL: %s", - fp_transport_type_to_str(get_fp_transport_type())); + fp_transport_type_to_str(get_fp_transport_type())); +} + +/* Initialize board. */ +static void board_init(void) +{ + /* Run until the first S3 entry */ + disable_sleep(SLEEP_MASK_AP_RUN); + + board_init_transport(); /* Enable interrupt on PCH power signals */ - gpio_enable_interrupt(GPIO_PCH_SLP_S3_L); - gpio_enable_interrupt(GPIO_PCH_SLP_S0_L); + gpio_enable_interrupt(GPIO_SLP_ALT_L); + gpio_enable_interrupt(GPIO_SLP_L); - /* enable the SPI slave interface if the PCH is up */ - hook_call_deferred(&ap_deferred_data, 0); + if (IS_ENABLED(SECTION_IS_RW)) + board_init_rw(); + + /* + * Enable the SPI slave interface if the PCH is up. + * Do not use hook_call_deferred(), because ap_deferred() will be + * called after tasks with priority higher than HOOK task (very late). + */ + ap_deferred(); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/hatch_fp/board.h b/board/hatch_fp/board.h index 001f437b86..721d216a44 100644 --- a/board/hatch_fp/board.h +++ b/board/hatch_fp/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -59,28 +59,28 @@ #define CONFIG_FLASH_WRITE_SIZE STM32_FLASH_WRITE_SIZE_3300 -#define CONFIG_SHAREDLIB_SIZE 0 +#define CONFIG_SHAREDLIB_SIZE 0 -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RO_SIZE (128 * 1024) +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (128 * 1024) /* EC rollback protection block */ #define CONFIG_ROLLBACK_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) #define CONFIG_ROLLBACK_SIZE (128 * 1024 * 2) /* 2 blocks of 128KB each */ -#define CONFIG_RW_MEM_OFF (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) -#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE - \ - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) +#define CONFIG_RW_MEM_OFF (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) -#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE +#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* * We want to prevent flash readout, and use it as indicator of protection @@ -124,10 +124,10 @@ *-------------------------------------------------------------------------*/ #define CONFIG_CMD_FLASH -#define CONFIG_CMD_SPI_XFER #define CONFIG_CMD_IDLE_STATS #ifdef SECTION_IS_RW +#define CONFIG_CMD_SPI_XFER /* TODO(b/130249462): remove for release */ #define CONFIG_CMD_FPSENSOR_DEBUG #endif @@ -188,8 +188,9 @@ *-------------------------------------------------------------------------*/ /* SPI configuration for the fingerprint sensor */ -#define CONFIG_SPI_MASTER -#define CONFIG_SPI_FP_PORT 0 /* SPI2: first master config */ +#define CONFIG_SPI_CONTROLLER +#define CONFIG_SPI_FP_PORT 0 /* SPI2: first master config */ +#define CONFIG_FINGERPRINT_MCU #ifdef SECTION_IS_RW #define CONFIG_FP_SENSOR_FPC1025 /* @@ -221,36 +222,41 @@ * Other *-------------------------------------------------------------------------*/ -#define CONFIG_AES -#define CONFIG_AES_GCM -#define CONFIG_DMA -/*FIXME*/ -/*#define CONFIG_FORCE_CONSOLE_RESUME*/ +#define CONFIG_BORINGSSL_CRYPTO +#define CONFIG_DMA_CROS #define CONFIG_FPU +#define CONFIG_FPU_WARNINGS #define CONFIG_HOST_COMMAND_STATUS -/*FIXME*/ -/*#define CONFIG_LOW_POWER_IDLE*/ #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -#define CONFIG_PRINTF_LEGACY_LI_FORMAT +#define CONFIG_PRINTF_LONG_IS_32BITS #define CONFIG_RNG #define CONFIG_SHA256 #define CONFIG_SHA256_UNROLLED #define CONFIG_SPI -#define CONFIG_STM_HWTIMER32 -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY #define CONFIG_WP_ACTIVE_HIGH +#define CONFIG_PANIC_STRIP_GPR + +/* + * Bloonchipper FPMCU RO has RV32I core panic data structure in their panic + * data structure, so expected size of the structure is 144 bytes. + */ +#define CONFIG_RO_PANIC_DATA_SIZE 144 + +#ifdef SECTION_IS_RW +#define CONFIG_LOW_POWER_IDLE +#endif /* SECTION_IS_RW */ #ifndef __ASSEMBLER__ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_WATCHDOG 16 +#define TIM_WATCHDOG 9 +#include "board_rw.h" #include "gpio_signal.h" -void fps_event(enum gpio_signal signal); +void slp_event(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ diff --git a/board/hatch_fp/board_rw.c b/board/hatch_fp/board_rw.c new file mode 100644 index 0000000000..58a0d62386 --- /dev/null +++ b/board/hatch_fp/board_rw.c @@ -0,0 +1,62 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "console.h" +#include "fpsensor_detect.h" +#include "gpio.h" +#include "registers.h" +#include "spi.h" +#include "task.h" +#include "usart_host_command.h" +#include "util.h" + +#ifndef SECTION_IS_RW +#error "This file should only be built for RW." +#endif + +/* SPI devices */ +const struct spi_device_t spi_devices[] = { + /* Fingerprint sensor (SCLK at 4Mhz) */ + { .port = CONFIG_SPI_FP_PORT, .div = 3, .gpio_cs = GPIO_SPI2_NSS } +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +static void configure_fp_sensor_spi(void) +{ + /* The dragonclaw development board needs this enabled to enable the + * AND gate (U10) to CS. Production boards could disable this to save + * power since it's only needed for initial detection on those boards. + */ + gpio_set_level(GPIO_DIVIDER_HIGHSIDE, 1); + + /* Configure SPI GPIOs */ + gpio_config_module(MODULE_SPI_CONTROLLER, 1); + + /* Set all SPI controller signal pins to very high speed: + * B12/13/14/15 + */ + STM32_GPIO_OSPEEDR(GPIO_B) |= 0xff000000; + + /* Enable clocks to SPI2 module (master) */ + STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; + + spi_enable(&spi_devices[0], 1); +} + +void board_init_rw(void) +{ + /* + * FP_RST_ODL pin is defined in gpio_rw.inc (with GPIO_OUT_HIGH + * flag) but not in gpio.inc, so RO leaves this pin set to 0 (reset + * default), but RW doesn't initialize this pin to 1 because sysjump + * to RW is a warm reset (see gpio_pre_init() in chip/stm32/gpio.c). + * Explicitly reset FP_RST_ODL pin to default value. + */ + gpio_reset(GPIO_FP_RST_ODL); + + /* Configure and enable SPI as master for FP sensor */ + configure_fp_sensor_spi(); +} diff --git a/board/hatch_fp/board_rw.h b/board/hatch_fp/board_rw.h new file mode 100644 index 0000000000..22495ec6d4 --- /dev/null +++ b/board/hatch_fp/board_rw.h @@ -0,0 +1,15 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_HATCH_FP_BOARD_RW_H +#define __CROS_EC_BOARD_HATCH_FP_BOARD_RW_H + +#include "gpio_signal.h" + +void fps_event(enum gpio_signal signal); + +void board_init_rw(void); + +#endif /* __CROS_EC_BOARD_HATCH_FP_BOARD_RW_H */ diff --git a/board/hatch_fp/build.mk b/board/hatch_fp/build.mk index 2e40d585fc..eb45551e41 100644 --- a/board/hatch_fp/build.mk +++ b/board/hatch_fp/build.mk @@ -1,4 +1,4 @@ -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -9,24 +9,74 @@ CHIP:=stm32 CHIP_FAMILY:=stm32f4 CHIP_VARIANT:=stm32f412 -board-y=board.o fpsensor_detect.o +# Don't forget that the board build.mk is included more than once to allow +# conditional variables to be realized. This means that we need to redefine all +# variable or the "+=" lines will compound. +board-rw=board_rw.o +board-y=board.o +# If we're mocking the sensor detection for testing (so we can test +# sensor/transport permutations in the unit tests), don't build the real sensor +# detection. +ifeq ($(HAS_MOCK_FPSENSOR_DETECT),) + board-y+=fpsensor_detect.o + board-rw+=fpsensor_detect_rw.o +endif + +# Do not build rsa test because this board uses RSA exponent 3 and the rsa test +# will fail on device. test-list-y=\ + abort \ aes \ + always_memset \ + benchmark \ + boringssl_crypto \ compile_time_macros \ - crc32 \ + cortexm_fpu \ + crc \ + debug \ + exception \ flash_physical \ flash_write_protect \ + fpsensor \ + fpsensor_auth_crypto_stateless \ + fpsensor_hw \ + ftrapv \ + global_initialization \ + libc_printf \ + libcxx \ + malloc \ mpu \ mutex \ + panic \ + panic_data \ pingpong \ + printf \ + queue \ + rng_benchmark \ rollback \ rollback_entropy \ - rsa \ rsa3 \ rtc \ + sbrk \ scratchpad \ sha256 \ sha256_unrolled \ + static_if \ + stdlib \ + std_vector \ stm32f_rtc \ + system_is_locked \ + timer \ + timer_dos \ + tpm_seed_clear \ utils \ + utils_str \ + + # TODO(b/274162810): Re-enable test on bloonchipper when LTO is + # re-enabled. + #fpsensor_auth_crypto_stateful \ + +# Note that this variable includes the trailing "/" +_hatch_fp_cur_dir:=$(dir $(lastword $(MAKEFILE_LIST))) +-include $(_hatch_fp_cur_dir)../../private/board/hatch_fp/build.mk diff --git a/board/hatch_fp/ec.tasklist b/board/hatch_fp/ec.tasklist index ed1e6ed294..79b8531751 100644 --- a/board/hatch_fp/ec.tasklist +++ b/board/hatch_fp/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,5 +10,5 @@ TASK_ALWAYS_RO(RWSIG, rwsig_task, NULL, 1280) \ TASK_ALWAYS(HOOKS, hook_task, NULL, 1024) \ TASK_ALWAYS_RW(FPSENSOR, fp_task, NULL, 4096) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 4096) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 6144) \ TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) diff --git a/board/hatch_fp/fpsensor_detect.c b/board/hatch_fp/fpsensor_detect.c index e737052b77..7e3b99cac7 100644 --- a/board/hatch_fp/fpsensor_detect.c +++ b/board/hatch_fp/fpsensor_detect.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,27 +7,6 @@ #include "gpio.h" #include "timer.h" -enum fp_sensor_type get_fp_sensor_type(void) -{ - enum fp_sensor_type ret; - - gpio_set_level(GPIO_DIVIDER_HIGHSIDE, 1); - usleep(1); - switch (gpio_get_level(GPIO_FP_SENSOR_SEL)) { - case 0: - ret = FP_SENSOR_TYPE_ELAN; - break; - case 1: - ret = FP_SENSOR_TYPE_FPC; - break; - default: - ret = FP_SENSOR_TYPE_UNKNOWN; - break; - } - gpio_set_level(GPIO_DIVIDER_HIGHSIDE, 0); - return ret; -} - enum fp_transport_type get_fp_transport_type(void) { enum fp_transport_type ret; diff --git a/board/hatch_fp/fpsensor_detect_rw.c b/board/hatch_fp/fpsensor_detect_rw.c new file mode 100644 index 0000000000..e69f0e0000 --- /dev/null +++ b/board/hatch_fp/fpsensor_detect_rw.c @@ -0,0 +1,38 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "fpsensor_detect.h" +#include "gpio.h" +#include "timer.h" + +enum fp_sensor_type fpsensor_detect_get_type(void) +{ + enum fp_sensor_type ret; + + gpio_set_level(GPIO_DIVIDER_HIGHSIDE, 1); + usleep(1); + switch (gpio_get_level(GPIO_FP_SENSOR_SEL)) { + case 0: + ret = FP_SENSOR_TYPE_ELAN; + break; + case 1: + ret = FP_SENSOR_TYPE_FPC; + break; + default: + ret = FP_SENSOR_TYPE_UNKNOWN; + break; + } + /* We leave GPIO_DIVIDER_HIGHSIDE enabled, since the dragonclaw + * development board use it to enable the AND gate (U10) to CS. + * Production boards could disable this to save power since it's + * only needed for initial detection on those boards. + */ + return ret; +} + +enum fp_sensor_spi_select fpsensor_detect_get_spi_select(void) +{ + return FP_SENSOR_SPI_SELECT_PRODUCTION; +} diff --git a/board/hatch_fp/gpio.inc b/board/hatch_fp/gpio.inc index 3f00642b69..dc185751bc 100644 --- a/board/hatch_fp/gpio.inc +++ b/board/hatch_fp/gpio.inc @@ -1,26 +1,21 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Interrupts */ -GPIO_INT(FPS_INT, PIN(A, 0), GPIO_INT_RISING, fps_event) -GPIO_INT(PCH_SLP_S0_L, PIN(A, 8), GPIO_INT_BOTH, slp_event) +GPIO_INT(SLP_L, PIN(A, 8), GPIO_INT_BOTH, slp_event) +GPIO_INT(SLP_ALT_L, PIN(B, 6), GPIO_INT_BOTH, slp_event) GPIO_INT(SPI1_NSS, PIN(A, 4), GPIO_INPUT, spi_event) -GPIO_INT(PCH_SLP_S3_L, PIN(B, 6), GPIO_INT_BOTH, slp_event) /* Inputs */ -GPIO(FP_SENSOR_SEL, PIN(B, 0), GPIO_INPUT) GPIO(TRANSPORT_SEL, PIN(B, 1), GPIO_INPUT) GPIO(WP, PIN(B, 7), GPIO_INPUT) /* Outputs */ GPIO(EC_INT_L, PIN(A, 1), GPIO_OUT_HIGH) -GPIO(FP_RST_ODL, PIN(B,10), GPIO_OUT_HIGH) -GPIO(SPI2_NSS, PIN(B,12), GPIO_OUT_HIGH) GPIO(DIVIDER_HIGHSIDE, PIN(B, 8), GPIO_OUT_LOW) -GPIO(USER_PRES_L, PIN(B, 9), GPIO_ODR_HIGH) /* * Unused pins. @@ -38,16 +33,13 @@ UNUSED(PIN(H, 1)) UNIMPLEMENTED(ENTERING_RW) -/* USART1: PA9/PA10 (TX/RX) to AP*/ +/* USART1: PA9/PA10 (TX/RX) to AP */ ALTERNATE(PIN_MASK(A, 0x0600), GPIO_ALT_USART, MODULE_UART, GPIO_PULL_UP) -/* USART2: PA2/PA3 (TX/RX) to servo*/ +/* USART2: PA2/PA3 (TX/RX) to servo */ ALTERNATE(PIN_MASK(A, 0x000C), GPIO_ALT_USART, MODULE_UART, GPIO_PULL_UP) /* SPI1 slave from the AP: PA4/5/6/7 (CS/CLK/MISO/MOSI) */ ALTERNATE(PIN_MASK(A, 0x00f0), GPIO_ALT_SPI, MODULE_SPI, 0) -/* - * SPI2 master to sensor: PB13/14/15 (CLK/MISO/MOSI) - * Note that we're not configuring NSS (PB12) here because we have already - * configured it as a GPIO above and the SPI_MASTER module expects to use it - * in software NSS management mode, not hardware management mode. - */ -ALTERNATE(PIN_MASK(B, 0xE000), GPIO_ALT_SPI, MODULE_SPI_MASTER, GPIO_PULL_DOWN) + +#ifdef SECTION_IS_RW +#include "gpio_rw.inc" +#endif diff --git a/board/hatch_fp/gpio_rw.inc b/board/hatch_fp/gpio_rw.inc new file mode 100644 index 0000000000..dc82cd984a --- /dev/null +++ b/board/hatch_fp/gpio_rw.inc @@ -0,0 +1,28 @@ +/* + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SECTION_IS_RW +#error "This file should only be included in RW." +#endif + +/* Interrupts */ +GPIO_INT(FPS_INT, PIN(A, 0), GPIO_INT_RISING, fps_event) + +/* Inputs */ +GPIO(FP_SENSOR_SEL, PIN(B, 0), GPIO_INPUT) + +/* Outputs */ +GPIO(FP_RST_ODL, PIN(B,10), GPIO_OUT_HIGH) +GPIO(SPI2_NSS, PIN(B,12), GPIO_OUT_HIGH) +GPIO(USER_PRES_L, PIN(B, 9), GPIO_ODR_HIGH) + +/* + * SPI2 master to sensor: PB13/14/15 (CLK/MISO/MOSI) + * Note that we're not configuring NSS (PB12) here because we have already + * configured it as a GPIO above and the SPI_MASTER module expects to use it + * in software NSS management mode, not hardware management mode. + */ +ALTERNATE(PIN_MASK(B, 0xE000), GPIO_ALT_SPI, MODULE_SPI_CONTROLLER, GPIO_PULL_DOWN) diff --git a/board/helios/battery.c b/board/helios/battery.c index c7168caf8a..dcc9503244 100644 --- a/board/helios/battery.c +++ b/board/helios/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/helios/board.c b/board/helios/board.c index 87b2b89702..1cc7de762c 100644 --- a/board/helios/board.c +++ b/board/helios/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,12 +6,13 @@ /* Helios board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" #include "driver/accel_bma2x2.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/als_opt3001.h" #include "driver/bc12/pi3usb9201.h" #include "driver/ppc/sn5s330.h" @@ -35,16 +36,16 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void ppc_interrupt(enum gpio_signal signal) { @@ -84,11 +85,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -129,20 +130,21 @@ static void board_gmr_tablet_switch_isr(enum gpio_signal signal) gmr_tablet_switch_isr(signal); } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, - [PWM_CH_FAN] = {.channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -153,7 +155,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -161,22 +163,26 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -200,21 +206,77 @@ static struct mutex g_lid_mutex; /* Base accel private data */ static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; /* BMA255 private data */ static struct accelgyro_saved_data_t g_bma255_data; +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI160 = 1, + BASE_GYRO_ICM426XX = 2, +}; + +static enum base_accelgyro_type base_accelgyro_config; + /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref_icm = { + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs. */ + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, }; -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, }; struct motion_sensor_t motion_sensors[] = { @@ -290,12 +352,43 @@ struct motion_sensor_t motion_sensors[] = { }; unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +void motion_interrupt(enum gpio_signal signal) +{ + if (base_accelgyro_config == BASE_GYRO_ICM426XX) + icm426xx_interrupt(signal); + else + bmi160_interrupt(signal); +} + +static void board_detect_motionsense(void) +{ + int val; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + if (base_accelgyro_config != BASE_GYRO_NONE) + return; + + icm_read8(&icm426xx_base_accel, ICM426XX_REG_WHO_AM_I, &val); + if (val == ICM426XX_CHIP_ICM40608) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + base_accelgyro_config = BASE_GYRO_ICM426XX; + ccprints("Base Accelgyro: ICM40608"); + } else { + base_accelgyro_config = BASE_GYRO_BMI160; + ccprints("Base Accelgyro: BMI160"); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsense, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsense, HOOK_PRIO_INIT_I2C + 1); + /******************************************************************************/ /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -314,58 +407,63 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_5V_REG", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_3] = { - "TEMP_AMB", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_4] = { - "TEMP_CPU", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_5V_REG", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_3] = { "TEMP_AMB", NPCX_ADC_CH3, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_4] = { "TEMP_CPU", NPCX_ADC_CH2, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Temp1", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Temp2", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, - [TEMP_SENSOR_3] = {.name = "Temp3", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_3}, - [TEMP_SENSOR_4] = {.name = "Temp4", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_4}, + [TEMP_SENSOR_1] = { .name = "Temp1", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Temp2", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Temp3", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "Temp4", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); /* Helios temperature control thresholds */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = C_TO_K(90), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(60), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(65), - .temp_fan_max = C_TO_K(80), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(60), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(65), \ + .temp_fan_max = C_TO_K(80), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -402,8 +500,8 @@ int board_tcpc_post_init(int port) /* Set MUX_DP_EQ to 3.6dB (0x98) */ rv = tcpc_write(port, PS8XXX_REG_MUX_DP_EQ_CONFIGURATION, 0x98); else if (port == USB_PD_PORT_TCPC_1) - rv = tcpc_write(port, - PS8XXX_REG_MUX_USB_C2SS_HS_THRESHOLD, 0x80); + rv = tcpc_write(port, PS8XXX_REG_MUX_USB_C2SS_HS_THRESHOLD, + 0x80); return rv; } diff --git a/board/helios/board.h b/board/helios/board.h index 17e719abb0..83ffd2b4b7 100644 --- a/board/helios/board.h +++ b/board/helios/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,10 +14,9 @@ #define CONFIG_POWER_BUTTON #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_LED_COMMON -#define CONFIG_LED_POWER_LED #define CONFIG_LOW_POWER_IDLE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -27,10 +26,12 @@ /* Sensors */ /* BMI160 Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT /* BMA253 Lid accel */ #define CONFIG_ACCEL_BMA255 @@ -40,7 +41,6 @@ #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL #define CONFIG_LID_ANGLE_UPDATE #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L /* USB Type C and USB PD defines */ #define CONFIG_USB_PD_COMM_LOCKED @@ -56,7 +56,7 @@ * Helios' battery takes several seconds to come back out of its disconnect * state (~4.2 seconds on the unit I have, so give it a little more for margin). */ -#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT #define CONFIG_POWER_BUTTON_INIT_TIMEOUT 6 /* BC 1.2 */ @@ -71,7 +71,7 @@ #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 50 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -85,15 +85,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -101,10 +102,10 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_TEMP_SENSOR_3, /* ADC3 */ - ADC_TEMP_SENSOR_4, /* ADC2 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_3, /* ADC3 */ + ADC_TEMP_SENSOR_4, /* ADC2 */ ADC_CH_COUNT }; @@ -116,11 +117,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, @@ -149,6 +146,8 @@ enum battery_type { BATTERY_TYPE_COUNT, }; +void motion_interrupt(enum gpio_signal signal); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/helios/build.mk b/board/helios/build.mk index 733912454f..13153c1526 100644 --- a/board/helios/build.mk +++ b/board/helios/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/helios/ec.tasklist b/board/helios/ec.tasklist index 63d366a33b..7fb3e38b63 100644 --- a/board/helios/ec.tasklist +++ b/board/helios/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/helios/gpio.inc b/board/helios/gpio.inc index ab8d9f4388..65fc10f761 100644 --- a/board/helios/gpio.inc +++ b/board/helios/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,10 +17,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) @@ -28,7 +28,7 @@ GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PP5000_A_PG_OD, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Sensor Interrupts */ -GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING, bmi160_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING, motion_interrupt) /* USB-C interrupts */ GPIO_INT(USB_C0_PPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, ppc_interrupt) diff --git a/board/helios/led.c b/board/helios/led.c index 2c064fb1ea..262f6a055a 100644 --- a/board/helios/led.c +++ b/board/helios/led.c @@ -1,46 +1,55 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Helios */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; - -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_1 = 5; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override const int led_charge_lvl_2 = 95; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, @@ -49,7 +58,7 @@ const enum ec_led_id supported_led_ids[] = { const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -67,7 +76,7 @@ void led_set_color_battery(enum ec_led_colors color) } } -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); @@ -104,4 +113,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/helios/vif_override.xml b/board/helios/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/helios/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/helipilot/board.c b/board/helipilot/board.c new file mode 100644 index 0000000000..abaec801da --- /dev/null +++ b/board/helipilot/board.c @@ -0,0 +1,143 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "fpsensor_detect.h" +#include "gpio.h" +#include "hooks.h" +#include "registers.h" +#include "shi_chip.h" +#include "spi.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "uart.h" +#include "uartn.h" + +/* TODO(b/279096907): Investigate de-duping with other FPMCU boards*/ + +/** + * Disable restricted commands when the system is locked. + * + * @see console.h system.c + */ +int console_is_restricted(void) +{ + return system_is_locked(); +} + +/* Must come after other header files. */ +#include "gpio_list.h" + +/* + * Some platforms have a broken SLP_S0_L signal (stuck to 0 in S0) + * if set, ignore it and only uses SLP_S3_L for the AP state. + */ +static bool broken_slp; + +static void ap_deferred(void) +{ + /* + * Behavior: + * AP Active (ex. Intel S0): SLP_L is 1 + * AP Suspend (ex. Intel S0ix): SLP_L is 0 + * The alternative SLP_ALT_L should be pulled high at all the times. + * + * Legacy Intel behavior: + * in S3: SLP_ALT_L is 0 and SLP_L is X. + * in S0ix: SLP_ALT_L is 1 and SLP_L is 0. + * in S0: SLP_ALT_L is 1 and SLP_L is 1. + * in S5/G3, the FP MCU should not be running. + */ + int running = gpio_get_level(GPIO_SLP_ALT_L) && + (gpio_get_level(GPIO_SLP_L) || broken_slp); + + if (running) { /* S0 */ + disable_sleep(SLEEP_MASK_AP_RUN); + hook_notify(HOOK_CHIPSET_RESUME); + } else { /* S0ix/S3 */ + hook_notify(HOOK_CHIPSET_SUSPEND); + enable_sleep(SLEEP_MASK_AP_RUN); + } +} +DECLARE_DEFERRED(ap_deferred); + +static void board_init_transport(void) +{ + enum fp_transport_type ret_transport = get_fp_transport_type(); + + ccprints("TRANSPORT_SEL: %s", fp_transport_type_to_str(ret_transport)); + + /* Initialize transport based on bootstrap */ + switch (ret_transport) { + case FP_TRANSPORT_TYPE_UART: + /* + * The Zork variants currently have a broken SLP_S0_L signal + * (stuck to 0 in S0). For now, unconditionally ignore it here + * as they are the only UART users and the AP has no S0ix state. + * TODO(b/174695987) once the RW AP firmware has been updated + * on all those machines, remove this workaround. + */ + broken_slp = true; + + /* Check if CONFIG_USART_HOST_COMMAND is enabled. */ + if (IS_ENABLED(CONFIG_USART_HOST_COMMAND)) + /*TODO (b/279035335): implement protocol */ + ccprints("TODO: CONFIG_USART_HOST_COMMAND protocol not " + "yet implemented on helipilot"); + else + ccprints("ERROR: UART not supported in fw build."); + + /* Disable SPI interrupt to disable SPI transport layer */ + gpio_disable_interrupt(GPIO_SHI_CS_L); + break; + + case FP_TRANSPORT_TYPE_SPI: + /* SPI transport is enabled. */ + break; + default: + ccprints("ERROR: Selected transport is not valid."); + } + + ccprints("TRANSPORT_SEL: %s", + fp_transport_type_to_str(get_fp_transport_type())); +} + +static void board_init(void) +{ + /* Run until the first S3 entry */ + disable_sleep(SLEEP_MASK_AP_RUN); + + board_init_transport(); + + /* Enable interrupt on PCH power signals */ + gpio_enable_interrupt(GPIO_SLP_ALT_L); + gpio_enable_interrupt(GPIO_SLP_L); + + if (IS_ENABLED(SECTION_IS_RW)) { + board_init_rw(); + } + + /* + * Enable the SPI slave interface if the PCH is up. + * Do not use hook_call_deferred(), because ap_deferred() will be + * called after tasks with priority higher than HOOK task (very late). + */ + ap_deferred(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* PCH power state changes */ +void slp_event(enum gpio_signal signal) +{ + hook_call_deferred(&ap_deferred_data, 0); +} +#ifndef HAS_TASK_FPSENSOR +void fps_event(enum gpio_signal signal) +{ +} +#endif diff --git a/board/helipilot/board.h b/board/helipilot/board.h new file mode 100644 index 0000000000..1c55017082 --- /dev/null +++ b/board/helipilot/board.h @@ -0,0 +1,303 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Helipilot board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +#undef CONFIG_SYSTEM_UNLOCKED + +#define CONFIG_LTO + +/*-------------------------------------------------------------------------* + * Flash layout: + * + * +++++++++++++ + * | RO | + * | ......... | + * | Rollback | (two sectors) + * +-----------+ + * | RW | + * | | + * | | + * | | + * | | + * +++++++++++++ + * + * We adjust the following macros to accommodate for a rollback, RO, + * and RW region of different sizes. + * + *-------------------------------------------------------------------------* + */ + +#undef _IMAGE_SIZE +#undef CONFIG_ROLLBACK_OFF +#undef CONFIG_ROLLBACK_SIZE +#undef CONFIG_FLASH_PSTATE +#undef CONFIG_FW_PSTATE_SIZE +#undef CONFIG_FW_PSTATE_OFF +#undef CONFIG_SHAREDLIB_SIZE +#undef CONFIG_RO_MEM_OFF +#undef CONFIG_RO_STORAGE_OFF +#undef CONFIG_RO_SIZE +#undef CONFIG_RW_MEM_OFF +#undef CONFIG_RW_STORAGE_OFF +#undef CONFIG_RW_SIZE +#undef CONFIG_EC_PROTECTED_STORAGE_OFF +#undef CONFIG_EC_PROTECTED_STORAGE_SIZE +#undef CONFIG_EC_WRITABLE_STORAGE_OFF +#undef CONFIG_EC_WRITABLE_STORAGE_SIZE +#undef CONFIG_WP_STORAGE_OFF +#undef CONFIG_WP_STORAGE_SIZE + +/*-------------------------------------------------------------------------* + * Patch for reducing program memory size to increase data RAM + *-------------------------------------------------------------------------* + */ +#undef NPCX_PROGRAM_MEMORY_SIZE +/* 384 KB program RAM */ +#define NPCX_PROGRAM_MEMORY_SIZE ((416 - 32) * 1024) + +#undef CONFIG_PROGRAM_MEMORY_BASE +#define CONFIG_PROGRAM_MEMORY_BASE 0x10058000 + +#undef CONFIG_RAM_BASE +/* + * Adjust the base address of the Data RAM + * 0x200C0000 - 32K (0x8000) memory address of Data RAM + */ +#define CONFIG_RAM_BASE 0x200B8000 + +#undef CONFIG_DATA_RAM_SIZE +/* + * Define Data RAM size = 128KB - 4KB (Reserved for booter). + */ +#define CONFIG_DATA_RAM_SIZE ((96 + 32) * 1024 - 0x1000) +/*-------------------------------------------------------------------------*/ + +#define CONFIG_SHAREDLIB_SIZE 0 + +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (128 * 1024) + +#define CONFIG_RO_PUBKEY_READ_ADDR \ + (CONFIG_MAPPED_STORAGE_BASE + CONFIG_EC_PROTECTED_STORAGE_OFF + \ + CONFIG_RO_PUBKEY_STORAGE_OFF) + +#define CONFIG_RWSIG_READ_ADDR \ + ((CONFIG_MAPPED_STORAGE_BASE + CONFIG_EC_WRITABLE_STORAGE_OFF + \ + CONFIG_RW_STORAGE_OFF + RW_SIG_OFFSET)) +/* + * Since NPCX9 executes out of SRAM and only one image (RO/RW) is loaded + * from flash at a time, we don't apply an offset to program memory + */ +#define CONFIG_RW_MEM_OFF 0 +#define CONFIG_RW_STORAGE_OFF 0 + +/* + * The remaining flash size (CONFIG_FLASH_SIZE_BYTES - + * (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF) exceeds available program memory, + * can only execute a program as big as the available program SRAM + */ +#define CONFIG_RW_SIZE \ + ((NPCX_PROGRAM_MEMORY_SIZE / CONFIG_FLASH_ERASE_SIZE) * \ + CONFIG_FLASH_ERASE_SIZE) + +#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_OFF \ + (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) + +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE + +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE + +/* + * We want to prevent flash readout, and use it as indicator of protection + * status. + */ +#define CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE + +/*-------------------------------------------------------------------------* + * Console Defines + *-------------------------------------------------------------------------* + */ + +/* Select which UART Controller is the Console UART */ +#undef CONFIG_CONSOLE_UART +#define CONFIG_CONSOLE_UART 0 /* 0:UART1 1:UART2 */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART1 */ + +#undef CONSOLE_TASK_STACK_SIZE +#define CONSOLE_TASK_STACK_SIZE 4096 + +/*-------------------------------------------------------------------------* + * Disable Features + *-------------------------------------------------------------------------* + */ +#undef CONFIG_ADC +#undef CONFIG_CMD_ADC +#undef CONFIG_CMD_POWER_AP +#undef CONFIG_HIBERNATE +#undef CONFIG_LID_SWITCH +#undef CONFIG_SWITCH +#undef CONFIG_TEMP_SENSOR +#undef CONFIG_I2C +#undef CONFIG_TASK_PROFILING + +/*-------------------------------------------------------------------------* + * Enable Features + *-------------------------------------------------------------------------* + */ +#define CONFIG_BORINGSSL_CRYPTO +#define CONFIG_CMD_FLASH +#define CONFIG_CMD_IDLE_STATS +#define CONFIG_FPU +#define CONFIG_FPU_WARNINGS +#define CONFIG_HOST_INTERFACE_SHI +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_USE_GPIO +#define CONFIG_PRINTF_LONG_IS_32BITS +#define CONFIG_RNG +#define CONFIG_SHA256 +#define CONFIG_SHA256_UNROLLED +#ifdef SECTION_IS_RW +#define CONFIG_SPI +#define CONFIG_CMD_SPI_XFER +/* TODO(b/130249462): remove for release */ +#define CONFIG_CMD_FPSENSOR_DEBUG +#endif + +/*-------------------------------------------------------------------------* + * Watchdog + *-------------------------------------------------------------------------* + */ + +/* + * RW does slow compute, RO does slow flash erase. + */ +#undef CONFIG_WATCHDOG_PERIOD_MS +#define CONFIG_WATCHDOG_PERIOD_MS 10000 +#define CONFIG_WATCHDOG_HELP + +/*-------------------------------------------------------------------------* + * Fingerprint Specific + *-------------------------------------------------------------------------* + */ + +/* SPI configuration for the fingerprint sensor */ +#define CONFIG_SPI_CONTROLLER +#define CONFIG_SPI_FP_PORT 0 /* SPI0: only one SPIP (SPI Peripheral) */ +#define CONFIG_FINGERPRINT_MCU +#ifdef SECTION_IS_RW +#define CONFIG_FP_SENSOR_FPC1025 +/* + * Use the malloc code only in the RW section (for the private library), + * we cannot enable it in RO since it is not compatible with the RW + * verification (shared_mem_init done too late). + */ +#define CONFIG_MALLOC +/* + * FP buffers are allocated in regular SRAM + * TODO(b/124773209): Instead of defining to empty, #undef once all CLs that + * depend on FP_*_SECTION have landed. Also rename the variables to CONFIG_*. + */ +#define FP_FRAME_SECTION +#define FP_TEMPLATE_SECTION +#endif /* SECTION_IS_RW */ + +/* + * These allow console commands to be flagged as restricted. + * Restricted commands will only be permitted to run when + * console_is_restricted() returns false. + * See console_is_restricted's definition in board.c. + */ +#define CONFIG_CONSOLE_COMMAND_FLAGS +#define CONFIG_RESTRICTED_CONSOLE_COMMANDS + +/*-------------------------------------------------------------------------* + * Rollback Block + *-------------------------------------------------------------------------* + */ + +#define CONFIG_ROLLBACK +#define CONFIG_ROLLBACK_SECRET_SIZE 32 +#define CONFIG_MPU +#define CONFIG_ROLLBACK_MPU_PROTECT + +/* + * We do not use any "locally" generated entropy: this is normally used + * to add local entropy when the main source of entropy is remote. + */ +#undef CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE +#ifdef SECTION_IS_RW +#undef CONFIG_ROLLBACK_UPDATE +#endif + +/* EC rollback protection block */ +#define CONFIG_ROLLBACK_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) +#define CONFIG_ROLLBACK_SIZE (128 * 1024 * 2) /* 2 blocks of 128KB each */ + +/*-------------------------------------------------------------------------* + * RW Signature Verification + *-------------------------------------------------------------------------* + */ + +#ifdef SECTION_IS_RO +/* RO verifies the RW partition signature */ +#define CONFIG_RSA +#define CONFIG_RWSIG +#endif /* SECTION_IS_RO */ +#define CONFIG_RSA_KEY_SIZE 3072 +#define CONFIG_RSA_EXPONENT_3 +#define CONFIG_RWSIG_TYPE_RWSIG + +/*-------------------------------------------------------------------------* + * Chip Specific + *-------------------------------------------------------------------------* + */ + +/* + * TODO (b/281751547): Remove once Quincy brought up + * Board should be set to CONFIG_HW_MRIDER or CONFIG_HW_QUINCY, only needed + * until Quincy stable, re-assigns WP GPIO + */ +#undef CONFIG_HW_MRIDER +#define CONFIG_HW_QUINCY + +/* + * TODO (b/279032946): should eventually be removed, required to avoid + * chip_pre_init disabling JTAG internally + */ +#define CONFIG_ENABLE_JTAG_SELECTION + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_WP_L GPIO_HOST_MCU_WP_OD +#define GPIO_SHI_CS_L GPIO_SPI_HOST_CS_MCU_ODL +#define GPIO_FPS_INT GPIO_FP_MCU_INT_L +#define GPIO_EC_INT_L GPIO_MCU_PLATFORM_INT_L +#define GPIO_SLP_ALT_L GPIO_SLP_L + +#ifndef __ASSEMBLER__ + +#include "board_rw.h" +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" + +void slp_event(enum gpio_signal signal); +void fps_event(enum gpio_signal signal); +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/helipilot/board_rw.c b/board/helipilot/board_rw.c new file mode 100644 index 0000000000..2c6a8b8a0a --- /dev/null +++ b/board/helipilot/board_rw.c @@ -0,0 +1,44 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "console.h" +#include "fpsensor_detect.h" +#include "gpio.h" +#include "registers.h" +#include "spi.h" +#include "task.h" +/*#include "usart_host_command.h"*/ +#include "util.h" + +#ifndef SECTION_IS_RW +#error "This file should only be built for RW." +#endif + +/* TODO(b/279096907): Investigate de-duping with other FPMCU boards*/ + +/* create alias to fit spi_devices declaration in 80 chars */ +#define FP_SPI_CS GPIO_SPI_MCU_CS_FP_L + +/* SPI devices */ +const struct spi_device_t spi_devices[] = { + /* Fingerprint sensor (SCLK at 4Mhz) */ + { .port = CONFIG_SPI_FP_PORT, .div = 3, .gpio_cs = FP_SPI_CS } +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +static void configure_fp_sensor_spi(void) +{ + /* Configure SPI GPIOs */ + gpio_config_module(MODULE_SPI_CONTROLLER, 1); + + spi_enable(&spi_devices[0], 1); +} + +void board_init_rw(void) +{ + /* Configure and enable SPI as master for FP sensor */ + configure_fp_sensor_spi(); +} diff --git a/board/helipilot/board_rw.h b/board/helipilot/board_rw.h new file mode 120000 index 0000000000..909a66e760 --- /dev/null +++ b/board/helipilot/board_rw.h @@ -0,0 +1 @@ +../hatch_fp/board_rw.h \ No newline at end of file diff --git a/board/helipilot/build.mk b/board/helipilot/build.mk new file mode 100644 index 0000000000..0d1e722289 --- /dev/null +++ b/board/helipilot/build.mk @@ -0,0 +1,78 @@ +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Helipilot board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m8s + +board-y= +board-y+=board.o +board-rw=board_rw.o + +# If we're mocking the sensor detection for testing (so we can test +# sensor/transport permutations in the unit tests), don't build the real sensor +# detection. +ifeq ($(HAS_MOCK_FPSENSOR_DETECT),) + board-y+=fpsensor_detect.o + board-rw+=fpsensor_detect_rw.o +endif + +# Do not build rsa test because this board uses RSA exponent 3 and the rsa test +# will fail on device. +test-list-y=\ + abort \ + aes \ + always_memset \ + benchmark \ + boringssl_crypto \ + compile_time_macros \ + cortexm_fpu \ + crc \ + debug \ + exception \ + flash_physical \ + flash_write_protect \ + fpsensor \ + fpsensor_auth_crypto_stateful \ + fpsensor_auth_crypto_stateless \ + fpsensor_hw \ + ftrapv \ + global_initialization \ + libc_printf \ + libcxx \ + malloc \ + mpu \ + mutex \ + panic \ + panic_data \ + pingpong \ + printf \ + queue \ + rng_benchmark \ + rollback \ + rollback_entropy \ + rsa3 \ + rtc \ + sbrk \ + scratchpad \ + sha256 \ + sha256_unrolled \ + static_if \ + stdlib \ + std_vector \ + stm32f_rtc \ + system_is_locked \ + timer \ + timer_dos \ + tpm_seed_clear \ + unaligned_access \ + utils \ + utils_str \ + +# Note that this variable includes the trailing "/" +_hatch_fp_cur_dir:=$(dir $(lastword $(MAKEFILE_LIST))) +-include $(_hatch_fp_cur_dir)../../private/board/hatch_fp/build.mk diff --git a/board/helipilot/dev_key.pem b/board/helipilot/dev_key.pem new file mode 100644 index 0000000000..1319b85136 --- /dev/null +++ b/board/helipilot/dev_key.pem @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/AIBADANBgkqhkiG9w0BAQEFAASCBuYwggbiAgEAAoIBgQCeXIneAYNlR6mp +cqkaQrGwfOTwZaz6i1jgra6Uj0RcNzr6qNzkz228vcjRtkFW/ZpJf79Kw6RlOc+M +U2dRh7JThK+M0glzR6PtXtfCoH1qcRWIRjwm1F5FrlyTT+wqOolkgZ++tN5iUK/A +eSo7Mt4FOigCXAmKeVVgk0l0VuedTe6sezeV5eL6jY1ot6F/oOhtpNUP9Hn731Cx +1EdwAvOZQROx6i2MUUMvqY38kc7t6s71JHG1Y7boytIr/IR+9cLzzahV9Z5nqyti +YO+PPtCeSRCCcpYsOh/mZ1WItXc5AaD3licq7bzsBc0TXZy20dTs6DsyvrVbp1N+ +wL0U9/Gc3NC+YdId3LfL9q05jY0gJsChC85ZshP87/q97grzLytQ1vCBSdHIyUfq +eipzs+vLz/YG3FFigto/7nOSOp6wZrcQSa6gkhc+5QhkopmuijxmLjHIyPYemVX5 +OVOcdLTDLorVceO03shVGe88j8Rbk/RrhjlUVYb3141fzk28WDsCAQMCggGAaZMG +lAECQ4UbxkxwvCx2daiYoEPIpweQlckfDbTYPXonUcXomIpJKH6F4SQrj1O8MP/U +3IJtmNE1CDeaNlp24lh1CIwGTNptSOnlLGr+RvYOWtl9bzg+2R7oYjVIHCcGQwEV +Kc3pluB1KvtxfMyUA3warD1bsaY46wzbouSaaN6fHad6Y+6XUbOzmyUWVRXwSRiO +CqL7/T+LITgvoAH3u4C3y/FzsuDXdRuz/baJ8/HfThhLzkJ58Ic2x/2tqfkrlfgP +V6VkEg8955Ox/cbu7JV7d8GZW6pCcygAAT/Nrg4V+urcZOg1z9YSYW8SThyDIVyO +U3MAAlPUibEG8P0J8Ym5daD1NPytKzPX42DNijmFWekA8fD/TC8BiIvAXwANt4Iu +nInKb0+INACkxZZzQiFqqzHga0w5n/w1vlJDce4roKv8Ygau8RHIs/vt27e2uzAj +vYRU8n7OxKC0y3G9qscdfzdgWhOy6odOvAbBM22B1dFEsUNWdontKO486Ai7AoHB +AM8I0bmKYb0v9ROty6wa25aVaY2X2ZRIQq/mYrtVnlCx0Kcf4IV0ZSirSFt0fGka +POuPlqCJnkSqSnIJjCkTzy3V/9GrA8GwvoX40NrTYhKCmJXi441WFGRcQfzrU0/I +Ex2ze0Bwz3Pmt4ReO3kLVcExpalAi7gPBUtJXZY7ywkdBnver0mo1QWHmA1V/5V+ +/uYZPcKrodmSLXf8XJY4YRt1Nc5NN00D59Patgdrf6BjzDvyZH39NNe8qKPJTJ1T +DwKBwQDD0L+Y8yaPZFlzVZjmeY6k023BOFaOcnmJxPLLgCRjOq9YFfwOHQcLmWkl +woTYjNNPTc8VCJcTf0o+LaaCaJOEuDq8RV6MsPWFMBiJqPa+TeAES2lhcoCmTTZ0 +MRcU5wOf4C9WClKt60QYGvfSRuknbDBc0PUJgX6EqsVeg258ZG8jaQTD3zvPwsNJ +UrVPd6tnTL5p1tTZSPJaS+fVEbcnjqjIUZvgvVQhdEMbGiLuC+Vu2e3Mc1BuTAD+ +n6XC+BUCgcEAigXhJlxBKMqjYnPdHWc9Dw5GXmU7uDAsdURB0jkUNcvgb2qVrk2Y +xceFkk2oRhF98l+5wFu+2HGG9rEIG2KKHo6qi8dX1nXUWVCLPIzsDFcQY+yXs464 +Qugr/fI3ioViE8z81aCKTUR6WD7SULI5K3ZucNWyerSuMjDpDtKHW2iu/T8fhnCO +A6+6s46qY6n/RBDT1x0WkQweT/2TDtBAvPjOiYjPiK1FN+ckBPJVFZfdfUxC/qjN +5ShwbTDdvjdfAoHBAIKLKmX3bwpC5kzju0RRCcM3noDQObRMUQaDTIeqwuzRyjq5 +UrQTWge7m26BreWzN4oz32NbD2JU3ClzxFbwYlh60dLY6bMgo64gEFvF+dQz6q2H +m5ZMVcQzeaLLZLiaAmqVdOQG4clHgrq8pTbZ8MTyyuiLTgZWVFhx2Oms9FLtn2zw +rdfqJ9/XLNuMeN+lHO+IfvE54zuF9ubdRTi2ehpfGzA2Z+so4sD4LLy8F0ldQ587 +892iNZ7dVf8VGSylYwKBwEnwpTIwvAlMEEhritgi1qUCwUBp0amNw25vWOEWTMdG +4EGW4UJtuLmHjaiibbDrqD0bq7bg9J8cgNSJWUpJje/tCC5XxMasx2VndD27zy30 +pWqt7tl7lrvEUhsfB/ZFbM/IepDuzyqGD/VzK0uGzzXW1/OwFCI8Yya1jn8ah61p +wOyt6Sc1U03ROsHS6K5v0D38U5r1707DkNfZrFFe9QnQceAtbNsGvUyQIht17dj9 +XnknJc8icroJS5SPuZs32g== +-----END PRIVATE KEY----- diff --git a/board/helipilot/ec.tasklist b/board/helipilot/ec.tasklist new file mode 100644 index 0000000000..3fac320eec --- /dev/null +++ b/board/helipilot/ec.tasklist @@ -0,0 +1,17 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ +#undef HOOKS_TASK_STACK_SIZE +#define HOOKS_TASK_STACK_SIZE 2048 + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 6144) \ + TASK_ALWAYS_RO(RWSIG, rwsig_task, NULL, 1280) \ + TASK_ALWAYS_RW(FPSENSOR, fp_task, NULL, 4096) diff --git a/board/helipilot/fpsensor_detect.c b/board/helipilot/fpsensor_detect.c new file mode 120000 index 0000000000..141c5a5af9 --- /dev/null +++ b/board/helipilot/fpsensor_detect.c @@ -0,0 +1 @@ +../hatch_fp/fpsensor_detect.c \ No newline at end of file diff --git a/board/helipilot/fpsensor_detect_rw.c b/board/helipilot/fpsensor_detect_rw.c new file mode 120000 index 0000000000..b33a47500d --- /dev/null +++ b/board/helipilot/fpsensor_detect_rw.c @@ -0,0 +1 @@ +../hatch_fp/fpsensor_detect_rw.c \ No newline at end of file diff --git a/board/helipilot/gpio.inc b/board/helipilot/gpio.inc new file mode 100644 index 0000000000..275d3764a3 --- /dev/null +++ b/board/helipilot/gpio.inc @@ -0,0 +1,58 @@ +/* + * Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Interrupts */ +GPIO_INT(FP_MCU_INT_L, PIN(B, 0), GPIO_INT_RISING, fps_event) + +/* A4 is the assignment on QUINCY, need to use 45 on MRIDER to set pin */ +#ifdef CONFIG_HW_QUINCY +GPIO_INT(HOST_MCU_WP_OD, PIN(A, 4), GPIO_INT_BOTH, switch_interrupt) +#elif defined(CONFIG_HW_MRIDER) +GPIO_INT(HOST_MCU_WP_OD, PIN(4, 5), GPIO_INT_BOTH, switch_interrupt) +#else +#error "No hardware configured (CONFIG_HW_QUINCY, CONFIG_HW_MRIDER)" +#endif + +/* SHI CS Ready, Low Active. */ +GPIO_INT(SPI_HOST_CS_MCU_ODL, PIN(5, 3), GPIO_INT_FALLING,shi_cs_event) +GPIO_INT(SLP_L, PIN(A, 0), GPIO_INT_BOTH, slp_event) + +/* Inputs */ +GPIO(TRANSPORT_SEL, PIN(4, 3), GPIO_INPUT) +GPIO(FP_SENSOR_SEL, PIN(4, 4), GPIO_INPUT) +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(SPI_HOST_DO_MCU_DI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(SPI_HOST_DI_MCU_DO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(SPI_HOST_CLK_MCU, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(MCU_PLATFORM_INT_L, PIN(A, 7), GPIO_ODR_HIGH) + +/* Outputs */ +GPIO(FP_RST_ODL, PIN(9, 6), GPIO_OUT_HIGH) +GPIO(SPI_MCU_CS_FP_L, PIN(A, 6), GPIO_OUT_HIGH) +GPIO(DIVIDER_HIGHSIDE, PIN(9, 3), GPIO_OUT_LOW) + +/* UART1 Tx/Rx */ +#if NPCX_UART_MODULE2 +ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO64/65 */ +#else +ALTERNATE(PIN_MASK(1, 0x03), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO10/11 */ +#endif + +/* UART2 Tx/Rx */ +ALTERNATE(PIN_MASK(7, 0x20), 1, MODULE_UART, 0) /* CR_SIN2 GPIO75 */ +ALTERNATE(PIN_MASK(8, 0x40), 1, MODULE_UART, 0) /* CR_SOUT2 GPIO86 */ + +/* SPIP - to FPC Sensor */ +/* SPIP_MOSI/SPIP_SCLK GPIOA3/A1 */ +ALTERNATE(PIN_MASK(A, 0x0A), 1, MODULE_SPI, 0) +/* SPIP_MISO GPIO95 */ +ALTERNATE(PIN_MASK(9, 0x20), 1, MODULE_SPI, 0) + +UNIMPLEMENTED(ENTERING_RW) \ No newline at end of file diff --git a/board/herobrine/battery.c b/board/herobrine/battery.c new file mode 100644 index 0000000000..84c43cc263 --- /dev/null +++ b/board/herobrine/battery.c @@ -0,0 +1,68 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all herobrine battery types. Note that the fields start + * charging_min/max and charging_min/max are not used for the charger. The + * effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ + +const struct board_batt_params board_battery_info[] = { + /* AP16L5J */ + [BATTERY_AP16L5J] = { + .fuel_gauge = { + .manuf_name = "PANASONIC", + .device_name = "AP16L5J", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x0, + .reg_mask = 0x4000, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AP16L5J; diff --git a/board/herobrine/board.c b/board/herobrine/board.c new file mode 100644 index 0000000000..37c88818b0 --- /dev/null +++ b/board/herobrine/board.c @@ -0,0 +1,271 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Herobrine board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "shi_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +static uint8_t sku_id; + +/* Wake-up pins for hibernate */ +const enum gpio_signal hibernate_wake_pins[] = { + GPIO_LID_OPEN, + GPIO_AC_PRESENT, + GPIO_POWER_BUTTON_L, + GPIO_RTC_EC_WAKE_ODL, +}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Use 80 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* + * Unmask 0x08 in [0] (KSO_00/KSI_03, the new location of Search key); + * as it still uses the legacy location (KSO_01/KSI_00). + */ + .actual_key_mask = { 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xa4, + 0xff, 0xfe, 0x55, 0xfa, 0xca }, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, +}; + +/* I2C port map */ +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "rtc", + .port = I2C_PORT_RTC, + .kbps = 400, + .scl = GPIO_EC_I2C_RTC_SCL, + .sda = GPIO_EC_I2C_RTC_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* Measure VBUS through a 1/10 voltage divider */ + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + /* + * Adapter current output or battery charging/discharging current (uV) + * 18x amplification on charger side. + */ + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, + /* + * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read + * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and + * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we + * only divide by 2 (enough to avoid precision issues). + */ + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + /* TODO(waihong): Assign a proper frequency. */ + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 4800 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Read SKU ID from GPIO and initialize variables for board variants */ +static void sku_id_init(void) +{ + int bits[3]; + + bits[0] = gpio_get_ternary(GPIO_SKU_ID0); + bits[1] = gpio_get_ternary(GPIO_SKU_ID1); + bits[2] = gpio_get_ternary(GPIO_SKU_ID2); + + sku_id = binary_first_base3_from_bits(bits, ARRAY_SIZE(bits)); + CPRINTS("SKU ID: %u", sku_id); +} +DECLARE_HOOK(HOOK_INIT, sku_id_init, HOOK_PRIO_INIT_I2C + 1); + +__override uint32_t board_get_sku_id(void) +{ + return sku_id; +} + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable interrupt for BMI260 sensor */ + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); + + /* Set the backlight duty cycle to 0. AP will override it later. */ + pwm_set_duty(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* + * Turn off display backlight in S3. AP has its own control. The EC's + * and the AP's will be AND'ed together in hardware. + */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); + pwm_enable(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Turn on display and keyboard backlight in S0. */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); + if (pwm_get_duty(PWM_CH_DISPLIGHT)) + pwm_enable(PWM_CH_DISPLIGHT, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Mutexes */ +static struct mutex g_base_mutex; +static struct mutex g_lid_mutex; + +static struct bmi_drv_data_t g_bmi260_data; +static struct accelgyro_saved_data_t g_bma255_data; + +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma255_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g, to support lid angle calculation. */ + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + /* + * Note: BMI260: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); diff --git a/board/herobrine/board.h b/board/herobrine/board.h new file mode 100644 index 0000000000..59580826f5 --- /dev/null +++ b/board/herobrine/board.h @@ -0,0 +1,103 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Herobrine board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* TODO(waihong): Remove the following bringup features */ +#define CONFIG_BRINGUP +#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands. */ +#define CONFIG_USB_PD_DEBUG_LEVEL 3 +#define CONFIG_CMD_GPIO_EXTENDED +#define CONFIG_CMD_POWERINDEBUG +#define CONFIG_I2C_DEBUG + +/* Keyboard */ +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +#define CONFIG_PWM_KBLIGHT + +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_FUEL_GAUGE + +/* BC 1.2 Charger */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* USB */ +#define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* USB-A */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* Sensors */ +/* BMI260 Base accel/gyro */ +#define CONFIG_ACCELGYRO_BMI260 +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS + +/* BMA253 lid accel */ +#define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_UPDATE + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* GPIO alias */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_SWITCHCAP_PG GPIO_SRC_VPH_PWR_PG +#define GPIO_ACOK_OD GPIO_CHG_ACOK_OD +#define GPIO_EN_PP5000 GPIO_EN_PP5000_S5 +#define GPIO_POWER_GOOD GPIO_MB_POWER_GOOD +#define GPIO_EC_INT_L GPIO_AP_EC_INT_L +#define GPIO_DP_HOT_PLUG_DET GPIO_DP_HOT_PLUG_DET_R + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { ADC_VBUS, ADC_AMON_BMON, ADC_PSYS, ADC_CH_COUNT }; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_DISPLIGHT, PWM_CH_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_AP16L5J, + BATTERY_TYPE_COUNT, +}; + +/* Reset all TCPCs. */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); + +#endif /* !defined(__ASSEMBLER__) */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/herobrine/build.mk b/board/herobrine/build.mk new file mode 100644 index 0000000000..6827780a6c --- /dev/null +++ b/board/herobrine/build.mk @@ -0,0 +1,18 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=herobrine + +board-y+=battery.o +board-y+=board.o +board-y+=led.o +board-y+=switchcap.o +board-y+=usbc_config.o diff --git a/board/herobrine/ec.tasklist b/board/herobrine/ec.tasklist new file mode 100644 index 0000000000..228828af3c --- /dev/null +++ b/board/herobrine/ec.tasklist @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/herobrine/gpio.inc b/board/herobrine/gpio.inc new file mode 100644 index 0000000000..9628684737 --- /dev/null +++ b/board/herobrine/gpio.inc @@ -0,0 +1,177 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* USB interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ +GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ +GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ +GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb1_evt) /* Interrupt from port-1 BC1.2 */ +GPIO_INT(USB_A0_OC_ODL, PIN(F, 4), GPIO_INT_BOTH | GPIO_PULL_UP, usba_oc_interrupt) + +/* System interrupts */ +GPIO_INT(CHG_ACOK_OD, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) /* ACOK */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 0), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(6, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ +GPIO_INT(EC_WP_ODL, PIN(D, 3), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ +GPIO_INT(LID_OPEN_EC, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) /* Lid open */ +GPIO_INT(AP_RST_L, PIN(5, 1), GPIO_INT_BOTH, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ +GPIO_INT(PS_HOLD, PIN(A, 6), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ +/* + * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down + * to make it low. + */ +GPIO_INT(MB_POWER_GOOD, PIN(3, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* PP1800_L18B from PMIC */ +GPIO_INT(WARM_RESET_L, PIN(B, 0), GPIO_INT_BOTH, power_signal_interrupt) /* AP warm reset */ +GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ + +/* Sensor interrupts */ +GPIO_INT(TABLET_MODE_L, PIN(C, 6), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 3), GPIO_INT_FALLING, bmi260_interrupt) /* Accelerometer/gyro interrupt */ + +GPIO(RTC_EC_WAKE_ODL , PIN(0, 2), GPIO_INPUT) /* RTC interrupt */ +GPIO(EC_ENTERING_RW, PIN(7, 2), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(CCD_MODE_ODL, PIN(6, 3), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ +GPIO(EC_GSC_PACKET_MODE, PIN(8, 3), GPIO_OUT_LOW) /* GSC Packet Mode */ + +/* PMIC/AP 1.8V */ +GPIO(PMIC_RESIN_L, PIN(A, 0), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(A, 2), GPIO_ODR_HIGH) /* PMIC power button */ +GPIO(AP_EC_INT_L, PIN(5, 6), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ + +/* Power enables */ +GPIO(SWITCHCAP_ON, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap */ +GPIO(EN_PP5000_S5, PIN(7, 3), GPIO_OUT_HIGH) /* Enable PP5000 */ +GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ + +/* Sensors */ +GPIO(LID_ACCEL_INT_L, PIN(A, 1), GPIO_INPUT) /* Lid accel sensor interrupt */ +/* Control the gate for trackpad IRQ. High closes the gate. + * This is always set low so that the OS can manage the trackpad. */ +GPIO(TP_INT_GATE, PIN(7, 4), GPIO_OUT_LOW) + +/* USB-C */ +GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_OUT_HIGH) /* Port-0 TCPC chip reset */ +GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_OUT_HIGH) /* Port-1 TCPC chip reset */ +GPIO(DP_MUX_OE_L, PIN(B, 1), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_HOT_PLUG_DET_R, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ + +/* USB-A */ +GPIO(EN_USB_A_5V, PIN(F, 0), GPIO_OUT_LOW) +GPIO(USB_A_CDP_ILIM_EN_L, PIN(7, 5), GPIO_OUT_HIGH) /* H:CDP, L:SDP. Only one USB-A port, always CDP */ + +/* LEDs */ +GPIO(EC_CHG_LED_Y_C0, PIN(6, 0), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_W_C0, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_Y_C1, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_W_C1, PIN(C, 4), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + +/* I2C */ +GPIO(EC_I2C_POWER_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_RTC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_RTC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Board/SKU IDs */ +GPIO(BRD_ID0, PIN(9, 4), GPIO_INPUT) +GPIO(BRD_ID1, PIN(9, 7), GPIO_INPUT) +GPIO(BRD_ID2, PIN(A, 5), GPIO_INPUT) +GPIO(SKU_ID0, PIN(6, 7), GPIO_INPUT) +GPIO(SKU_ID1, PIN(7, 0), GPIO_INPUT) +GPIO(SKU_ID2, PIN(E, 1), GPIO_INPUT) + +/* Switchcap */ +/* + * GPIO0 is configured as PVC_PG. When the chip in power down mode, it outputs + * high-Z. Set pull-down to avoid floating. + */ +GPIO(SRC_VPH_PWR_PG, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. */ +UNUSED(PIN(5, 2)) +UNUSED(PIN(5, 4)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(D, 1)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(E, 3)) +UNUSED(PIN(C, 1)) +UNUSED(PIN(0, 4)) +UNUSED(PIN(D, 6)) +UNUSED(PIN(3, 2)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(8, 6)) +UNUSED(PIN(D, 4)) +UNUSED(PIN(4, 1)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 7)) +UNUSED(PIN(A, 4)) +UNUSED(PIN(9, 6)) +UNUSED(PIN(9, 3)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(5, 0)) +UNUSED(PIN(8, 1)) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ +ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1 SDA (GPIO90), I2C2 (GPIO91/92) */ +ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) */ +ALTERNATE(PIN_MASK(F, 0x0C), 1, MODULE_I2C, 0) /* I2C4 (GPIOF2/F3) */ +ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ +ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ +ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ +ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* PWM3 (GPIO80) - KB_BL_PWM */ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ +ALTERNATE(PIN_MASK(D, 0x04), 1, MODULE_PMU, 0) /* PSL_IN1 (GPIOD2) - ACOK_OD */ +ALTERNATE(PIN_MASK(0, 0x01), 1, MODULE_PMU, 0) /* PSL_IN2 (GPIO00) - EC_PWR_BTN_ODL */ +ALTERNATE(PIN_MASK(0, 0x02), 1, MODULE_PMU, 0) /* PSL_IN3 (GPIO01) - LID_OPEN_EC */ +ALTERNATE(PIN_MASK(0, 0x04), 1, MODULE_PMU, 0) /* PSL_IN4 (GPIO02) - RTC_EC_WAKE_ODL */ + +/* Keyboard */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +#define GPIO_KB_OUTPUT (GPIO_ODR_HIGH) +#define GPIO_KB_OUTPUT_COL2 (GPIO_OUT_LOW) + +/* Keyboard alternate functions */ +ALTERNATE(PIN_MASK(0, 0xE0), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO10 (GPIO07), KSO11 (GPIO06), KSO12 (GPIO05) */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO03 (GPIO16), KSO04 (GPIO15), KSO05 (GPIO14), KSO06 (GPIO13), KSO07 (GPIO12), KSO08 (GPIO11), KSO09 (GPIO10) */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO00 (GPIO21), KSO01 (GPIO20) */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI2 (GPIO27), KSI3 (GPIO26), KSI4 (GPIO25), KSI5 (GPIO24), KSI6 (GPIO23), KSI7 (GPIO22) */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI0 (GPIO31), KSI1 (GPIO30) */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_KB_OUTPUT_COL2) /* KSO02 (GPIO17) */ diff --git a/board/herobrine/led.c b/board/herobrine/led.c new file mode 100644 index 0000000000..27205e0257 --- /dev/null +++ b/board/herobrine/led.c @@ -0,0 +1,163 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_RIGHT_LED, + EC_LED_ID_LEFT_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void side_led_set_color(int port, enum led_color color) +{ + gpio_set_level(port ? GPIO_EC_CHG_LED_Y_C1 : GPIO_EC_CHG_LED_Y_C0, + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(port ? GPIO_EC_CHG_LED_W_C1 : GPIO_EC_CHG_LED_W_C0, + (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + int port; + + switch (led_id) { + case EC_LED_ID_RIGHT_LED: + port = 0; + break; + case EC_LED_ID_LEFT_LED: + port = 1; + break; + default: + return EC_ERROR_PARAM1; + } + + if (brightness[EC_LED_COLOR_WHITE] != 0) + side_led_set_color(port, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + side_led_set_color(port, LED_AMBER); + else + side_led_set_color(port, LED_OFF); + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + side_led_set_color(0, (port == 0) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + side_led_set_color(1, (port == 1) ? color : LED_OFF); +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + if (charge_get_percent() <= 10) + side_led_set_color(0, (battery_ticks & 0x4) ? + LED_WHITE : + LED_OFF); + else + side_led_set_color(0, LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + side_led_set_color(1, LED_OFF); + break; + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color((battery_ticks & 0x4) ? LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_LEFT_LED, 1); + led_auto_control(EC_LED_ID_RIGHT_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_WHITE : LED_OFF; + + led_auto_control(EC_LED_ID_LEFT_LED, 0); + led_auto_control(EC_LED_ID_RIGHT_LED, 0); + + side_led_set_color(0, color); + side_led_set_color(1, color); +} diff --git a/board/herobrine/switchcap.c b/board/herobrine/switchcap.c new file mode 100644 index 0000000000..5173e27f75 --- /dev/null +++ b/board/herobrine/switchcap.c @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gpio.h" +#include "power/qcom.h" + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON, enable); +} + +int board_is_switchcap_enabled(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_ON); +} + +int board_is_switchcap_power_good(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_PG); +} diff --git a/board/herobrine/usbc_config.c b/board/herobrine/usbc_config.c new file mode 100644 index 0000000000..7709a3ba25 --- /dev/null +++ b/board/herobrine/usbc_config.c @@ -0,0 +1,317 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Herobrine board-specific USB-C configuration */ + +#include "bc12/pi3usb9201_public.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "config.h" +#include "gpio.h" +#include "hooks.h" +#include "ppc/sn5s330_public.h" +#include "system.h" +#include "tcpm/ps8xxx_public.h" +#include "tcpm/tcpci.h" +#include "timer.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_config.h" +#include "usbc_ocp.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* GPIO Interrupt Handlers */ +void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_PD_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +void usb1_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void usba_oc_deferred(void) +{ + /* Use next number after all USB-C ports to indicate the USB-A port */ + board_overcurrent_event(CONFIG_USB_PD_PORT_MAX_COUNT, + !gpio_get_level(GPIO_USB_A0_OC_ODL)); +} +DECLARE_DEFERRED(usba_oc_deferred); + +void usba_oc_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&usba_oc_deferred_data, 0); +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + case GPIO_USB_C1_SWCTL_INT_ODL: + sn5s330_interrupt(1); + break; + default: + break; + } +} + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + } +}; + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + { + .i2c_port = I2C_PORT_EEPROM, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/* Initialize board USC-C things */ +static void board_init_usbc(void) +{ + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + + /* Enable USB-A overcurrent interrupt */ + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init_usbc, HOOK_PRIO_DEFAULT); + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); + msleep(PS8805_FW_INIT_DELAY_MS); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} diff --git a/board/herobrine/usbc_config.h b/board/herobrine/usbc_config.h new file mode 100644 index 0000000000..da19a67d2d --- /dev/null +++ b/board/herobrine/usbc_config.h @@ -0,0 +1,19 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Herobrine board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#include "gpio.h" + +void tcpc_alert_event(enum gpio_signal signal); +void usb0_evt(enum gpio_signal signal); +void usb1_evt(enum gpio_signal signal); +void usba_oc_interrupt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/herobrine/vif_override.xml b/board/herobrine/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/herobrine/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/hoho/board.c b/board/hoho/board.c index fe2bcf1476..a671ef707d 100644 --- a/board/hoho/board.c +++ b/board/hoho/board.c @@ -1,11 +1,10 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Hoho dongle configuration */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "ec_commands.h" #include "ec_version.h" @@ -14,16 +13,17 @@ #include "mcdp28x0.h" #include "registers.h" #include "task.h" +#include "timer.h" #include "usb_bb.h" #include "usb_descriptor.h" #include "usb_pd.h" -#include "timer.h" #include "util.h" static volatile uint64_t hpd_prev_ts; static volatile int hpd_prev_level; void hpd_event(enum gpio_signal signal); +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /** @@ -99,7 +99,7 @@ void board_config_pre_init(void) /* enable SYSCFG clock */ STM32_RCC_APB2ENR |= BIT(0); /* Remap USART DMA to match the USART driver */ - STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10);/* Remap USART1 RX/TX DMA */ + STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10); /* Remap USART1 RX/TX DMA */ } #ifdef CONFIG_SPI_FLASH @@ -143,11 +143,10 @@ static void factory_validation_deferred(void) /* test mcdp via serial to validate function */ if (!mcdp_get_info(&info) && (MCDP_FAMILY(info.family) == 0x0010) && - (MCDP_CHIPID(info.chipid) == 0x2850)) { + (MCDP_CHIPID(info.chipid) == 0x2850)) { gpio_set_level(GPIO_MCDP_READY, 1); pd_log_event(PD_EVENT_VIDEO_CODEC, - PD_LOG_PORT_SIZE(0, sizeof(info)), - 0, &info); + PD_LOG_PORT_SIZE(0, sizeof(info)), 0, &info); } mcdp_disable(); @@ -168,7 +167,7 @@ static void board_init(void) gpio_set_level(GPIO_STM_READY, 1); /* factory test only */ /* Delay needed to allow HDMI MCU to boot. */ - hook_call_deferred(&factory_validation_deferred_data, 200*MSEC); + hook_call_deferred(&factory_validation_deferred_data, 200 * MSEC); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -176,13 +175,13 @@ DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); /* ADC channels */ const struct adc_t adc_channels[] = { /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_CH_CC1_PD] = {"USB_C_CC1_PD", 3300, 4096, 0, STM32_AIN(1)}, + [ADC_CH_CC1_PD] = { "USB_C_CC1_PD", 3300, 4096, 0, STM32_AIN(1) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); -const void * const usb_strings[] = { +const void *const usb_strings[] = { [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), [USB_STR_PRODUCT] = USB_STRING_DESC("Hoho"), [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), [USB_STR_BB_URL] = USB_STRING_DESC(USB_GOOGLE_TYPEC_URL), diff --git a/board/hoho/board.h b/board/hoho/board.h index 21fb536a6f..f6421fdaf0 100644 --- a/board/hoho/board.h +++ b/board/hoho/board.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,7 +15,6 @@ #define CONFIG_UART_CONSOLE 1 /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_ADC #define CONFIG_BOARD_PRE_INIT #define CONFIG_CMD_SPI_FLASH @@ -24,10 +23,9 @@ #define CONFIG_RWSIG #define CONFIG_RWSIG_TYPE_USBPD1 #define CONFIG_SHA256 -/* TODO(tbroch) Re-enable once STM spi master can be inhibited at boot so it +/* TODO(tbroch) Re-enable once STM spi controller can be inhibited at boot so it doesn't interfere with HDMI loading its f/w */ #undef CONFIG_SPI_FLASH -#define CONFIG_SPI_MASTER_PORT 2 #define CONFIG_SPI_CS_GPIO GPIO_PD_MCDP_SPI_CS_L #define CONFIG_USB #define CONFIG_USB_BOS @@ -44,7 +42,7 @@ #define CONFIG_USB_PD_IDENTITY_HW_VERS 1 #define CONFIG_USB_PD_IDENTITY_SW_VERS 1 #define CONFIG_USB_PD_LOGGING -#undef CONFIG_EVENT_LOG_SIZE +#undef CONFIG_EVENT_LOG_SIZE #define CONFIG_EVENT_LOG_SIZE 256 #define CONFIG_USB_PD_PORT_MAX_COUNT 1 #define CONFIG_USB_PD_TCPC @@ -73,7 +71,7 @@ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 +#define TIM_ADC 3 #include "gpio_signal.h" @@ -96,14 +94,14 @@ enum usb_strings { }; /* we are never a source : don't care about power supply */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 0 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 0 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 0 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 1000 -#define PD_MAX_POWER_MW 1500 -#define PD_MAX_CURRENT_MA 300 -#define PD_MAX_VOLTAGE_MV 5000 +#define PD_MAX_POWER_MW 1500 +#define PD_MAX_CURRENT_MA 300 +#define PD_MAX_VOLTAGE_MV 5000 #endif /* !__ASSEMBLER__ */ @@ -111,10 +109,10 @@ enum usb_strings { #define USB_DEV_CLASS USB_CLASS_BILLBOARD /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_COUNT 0 +#define USB_IFACE_COUNT 0 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_COUNT 1 +#define USB_EP_CONTROL 0 +#define USB_EP_COUNT 1 #endif /* __CROS_EC_BOARD_H */ diff --git a/board/hoho/build.mk b/board/hoho/build.mk index 18799c3b9f..b6fbbe7a9e 100644 --- a/board/hoho/build.mk +++ b/board/hoho/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,4 +11,4 @@ CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f07x board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_pdo.o diff --git a/board/hoho/ec.tasklist b/board/hoho/ec.tasklist index 41fc047d6a..5a82344122 100644 --- a/board/hoho/ec.tasklist +++ b/board/hoho/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/hoho/gpio.inc b/board/hoho/gpio.inc index 6d0701ded1..56a4f8808e 100644 --- a/board/hoho/gpio.inc +++ b/board/hoho/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/hoho/usb_pd_config.h b/board/hoho/usb_pd_config.h index 2f01c275a8..5a7dfd12a6 100644 --- a/board/hoho/usb_pd_config.h +++ b/board/hoho/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -49,7 +49,7 @@ static inline void spi_enable_clock(int port) #define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 #define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 -#define TIM_CCR_CS 1 +#define TIM_CCR_CS 1 #define EXTI_COMP_MASK(p) BIT(21) #define IRQ_COMP STM32_IRQ_COMP /* triggers packet detection on comparator falling edge */ @@ -88,9 +88,8 @@ static inline void pd_tx_enable(int port, int polarity) static inline void pd_tx_disable(int port, int polarity) { /* output low on SPI TX (PB4) to disable the FET */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - & ~(3 << (2*4))) - | (1 << (2*4)); + STM32_GPIO_MODER(GPIO_B) = + (STM32_GPIO_MODER(GPIO_B) & ~(3 << (2 * 4))) | (1 << (2 * 4)); /* put the low level reference in Hi-Z */ gpio_set_level(GPIO_PD_CC1_TX_EN, 0); } @@ -101,8 +100,8 @@ static inline void pd_select_polarity(int port, int polarity) * use the right comparator : CC1 -> PA1 (COMP1 INP) * use VrefInt / 2 as INM (about 600mV) */ - STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) - | STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12; + STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) | + STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12; } /* Initialize pins used for TX and put them in Hi-Z */ @@ -111,7 +110,9 @@ static inline void pd_tx_init(void) gpio_config_module(MODULE_USB_PD, 1); } -static inline void pd_set_host_mode(int port, int enable) {} +static inline void pd_set_host_mode(int port, int enable) +{ +} static inline void pd_config_init(int port, uint8_t power_role) { diff --git a/board/hoho/usb_pd_pdo.c b/board/hoho/usb_pd_pdo.c new file mode 100644 index 0000000000..c52179acfc --- /dev/null +++ b/board/hoho/usb_pd_pdo.c @@ -0,0 +1,18 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +/* Source PDOs */ +const uint32_t pd_src_pdo[] = {}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +/* Fake PDOs : we just want our pre-defined voltages */ +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_COMM_CAP), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/hoho/usb_pd_pdo.h b/board/hoho/usb_pd_pdo.h new file mode 100644 index 0000000000..e04c3aa677 --- /dev/null +++ b/board/hoho/usb_pd_pdo.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_HOHO_USB_PD_PDO_H +#define __CROS_EC_BOARD_HOHO_USB_PD_PDO_H + +#include "stdint.h" + +extern const uint32_t pd_src_pdo[0]; +extern const int pd_src_pdo_cnt; + +extern const uint32_t pd_snk_pdo[1]; +extern const int pd_snk_pdo_cnt; + +#endif /* __CROS_EC_BOARD_HOHO_USB_PD_PDO_H */ diff --git a/board/hoho/usb_pd_policy.c b/board/hoho/usb_pd_policy.c index 4fe82320e8..baf05d0e71 100644 --- a/board/hoho/usb_pd_policy.c +++ b/board/hoho/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,6 +7,7 @@ #include "board.h" #include "common.h" #include "console.h" +#include "cros_version.h" #include "ec_commands.h" #include "gpio.h" #include "hooks.h" @@ -16,21 +17,12 @@ #include "usb_api.h" #include "usb_bb.h" #include "usb_pd.h" +#include "usb_pd_pdo.h" +#include "usb_pd_tcpm.h" #include "util.h" -#include "version.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -/* Source PDOs */ -const uint32_t pd_src_pdo[] = {}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); - -/* Fake PDOs : we just want our pre-defined voltages */ -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_COMM_CAP), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) /* Holds valid object position (opos) for entered mode */ static int alt_mode[PD_AMODE_COUNT]; @@ -62,22 +54,18 @@ __override int pd_check_power_swap(int port) return 0; } -__override int pd_check_data_swap(int port, - enum pd_data_role data_role) +__override int pd_check_data_swap(int port, enum pd_data_role data_role) { /* Always refuse data swap */ return 0; } -__override void pd_check_pr_role(int port, - enum pd_power_role pr_role, +__override void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { } -__override void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +__override void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { } /* ----------------- Vendor Defined Messages ------------------ */ @@ -90,8 +78,8 @@ const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, - CONFIG_USB_PD_IDENTITY_SW_VERS, - 0, 0, 0, 0, /* SS[TR][12] */ + CONFIG_USB_PD_IDENTITY_SW_VERS, 0, 0, 0, + 0, /* SS[TR][12] */ 0, /* Vconn power */ 0, /* Vconn power required */ 1, /* Vbus power required */ @@ -117,18 +105,16 @@ static int svdm_response_svids(int port, uint32_t *payload) #define OPOS_DP 1 #define OPOS_GFU 1 -const uint32_t vdo_dp_modes[1] = { - VDO_MODE_DP(0, /* UFP pin cfg supported : none */ +const uint32_t vdo_dp_modes[1] = { + VDO_MODE_DP(0, /* UFP pin cfg supported : none */ MODE_DP_PIN_C, /* DFP pin cfg supported */ - 1, /* no usb2.0 signalling in AMode */ - CABLE_PLUG, /* its a plug */ - MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ - MODE_DP_SNK) /* Its a sink only */ + 1, /* no usb2.0 signalling in AMode */ + CABLE_PLUG, /* its a plug */ + MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ + MODE_DP_SNK) /* Its a sink only */ }; -const uint32_t vdo_goog_modes[1] = { - VDO_MODE_GOOGLE(MODE_GOOGLE_FU) -}; +const uint32_t vdo_goog_modes[1] = { VDO_MODE_GOOGLE(MODE_GOOGLE_FU) }; static int svdm_response_modes(int port, uint32_t *payload) { @@ -150,13 +136,15 @@ static int dp_status(int port, uint32_t *payload) if (opos != OPOS_DP) return 0; /* nak */ - payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ - (hpd == 1), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - 0, /* MF pref */ + payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + (hpd == 1), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ gpio_get_level(GPIO_PD_SBU_ENABLE), - 0, /* power low */ + 0, /* power + low + */ 0x2); return 2; } @@ -194,9 +182,9 @@ static int svdm_enter_mode(int port, uint32_t *payload) return rv; } -int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid) +int pd_alt_mode(int port, enum tcpci_msg_type type, uint16_t svid) { - if (type != TCPC_TX_SOP) + if (type != TCPCI_MSG_SOP) return 0; if (svid == USB_SID_DISPLAYPORT) @@ -235,8 +223,7 @@ const struct svdm_response svdm_rsp = { .exit_mode = &svdm_exit_mode, }; -int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) +int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { int rsize; diff --git a/board/hoho/vif_override.xml b/board/hoho/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/hoho/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/homestar/base_detect.c b/board/homestar/base_detect.c new file mode 100644 index 0000000000..7625db02d7 --- /dev/null +++ b/board/homestar/base_detect.c @@ -0,0 +1,233 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Homestar base detection code */ + +#include "adc.h" +#include "base_state.h" +#include "board.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "system.h" +#include "tablet_mode.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +/* Make sure POGO VBUS starts later then PP3300_HUB when power on */ +#define BASE_DETECT_EN_LATER_US (600 * MSEC) + +/* Base detection and debouncing */ +#define BASE_DETECT_EN_DEBOUNCE_US (350 * MSEC) +#define BASE_DETECT_DIS_DEBOUNCE_US (20 * MSEC) + +/* + * If the base status is unclear (i.e. not within expected ranges, read + * the ADC value again every 500ms. + */ +#define BASE_DETECT_RETRY_US (500 * MSEC) + +/* + * Lid has 604K pull-up, base has 30.1K pull-down, so the + * ADC value should be around 30.1/(604+30.1)*3300 = 156 + * + * We add a significant margin on the maximum value, due to noise on the line, + * especially when PWM is active. See b/64193554 for details. + */ +#define BASE_DETECT_MIN_MV 120 +#define BASE_DETECT_MAX_MV 300 + +/* Minimum ADC value to indicate base is disconnected for sure */ +#define BASE_DETECT_DISCONNECT_MIN_MV 1500 + +/* + * Base EC pulses detection pin for 500 us to signal out of band USB wake (that + * can be used to wake system from deep S3). + */ +#define BASE_DETECT_PULSE_MIN_US 400 +#define BASE_DETECT_PULSE_MAX_US 650 + +static uint64_t base_detect_debounce_time; + +static void base_detect_deferred(void); +DECLARE_DEFERRED(base_detect_deferred); + +enum base_status { + BASE_UNKNOWN = 0, + BASE_DISCONNECTED = 1, + BASE_CONNECTED = 2, +}; + +static enum base_status current_base_status; + +/* + * This function is called whenever there is a change in the base detect + * status. Actions taken include: + * 1. Change in power to base + * 2. Indicate mode change to host. + * 3. Indicate tablet mode to host. Current assumption is that if base is + * disconnected then the system is in tablet mode, else if the base is + * connected, then the system is not in tablet mode. + */ +static void base_detect_change(enum base_status status) +{ + int connected = (status == BASE_CONNECTED); + + if (current_base_status == status) + return; + + gpio_set_level(GPIO_EN_BASE, connected); + tablet_set_mode(!connected, TABLET_TRIGGER_BASE); + base_set_state(connected); + current_base_status = status; +} + +/* Measure detection pin pulse duration (used to wake AP from deep S3). */ +static uint64_t pulse_start; +static uint32_t pulse_width; + +static void print_base_detect_value(int v, int tmp_pulse_width) +{ + CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name, v, + tmp_pulse_width); +} + +static void base_detect_deferred(void) +{ + uint64_t time_now = get_time().val; + int v; + uint32_t tmp_pulse_width = pulse_width; + + if (base_detect_debounce_time > time_now) { + hook_call_deferred(&base_detect_deferred_data, + base_detect_debounce_time - time_now); + return; + } + + v = adc_read_channel(ADC_BASE_DET); + if (v == ADC_READ_ERROR) + return; + + print_base_detect_value(v, tmp_pulse_width); + + if (v >= BASE_DETECT_MIN_MV && v <= BASE_DETECT_MAX_MV) { + if (current_base_status != BASE_CONNECTED) { + base_detect_change(BASE_CONNECTED); + } else if (tmp_pulse_width >= BASE_DETECT_PULSE_MIN_US && + tmp_pulse_width <= BASE_DETECT_PULSE_MAX_US) { + CPRINTS("Sending event to AP"); + host_set_single_event(EC_HOST_EVENT_KEY_PRESSED); + } + return; + } + + if (v >= BASE_DETECT_DISCONNECT_MIN_MV) { + base_detect_change(BASE_DISCONNECTED); + return; + } + + /* Unclear base status, schedule again in a while. */ + hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_RETRY_US); +} + +static inline int detect_pin_connected(enum gpio_signal det_pin) +{ + return gpio_get_level(det_pin) == 0; +} + +void base_detect_interrupt(enum gpio_signal signal) +{ + uint64_t time_now = get_time().val; + int debounce_us; + + if (detect_pin_connected(signal)) + debounce_us = BASE_DETECT_EN_DEBOUNCE_US; + else + debounce_us = BASE_DETECT_DIS_DEBOUNCE_US; + + if (base_detect_debounce_time <= time_now) { + /* + * Detect and measure detection pin pulse, when base is + * connected. Only a single pulse is measured over a debounce + * period. If no pulse, or multiple pulses are detected, + * pulse_width is set to 0. + */ + if (current_base_status == BASE_CONNECTED && + !detect_pin_connected(signal)) { + pulse_start = time_now; + } else { + pulse_start = 0; + } + pulse_width = 0; + + hook_call_deferred(&base_detect_deferred_data, debounce_us); + } else { + if (current_base_status == BASE_CONNECTED && + detect_pin_connected(signal) && !pulse_width && + pulse_start) { + /* First pulse within period. */ + pulse_width = time_now - pulse_start; + } else { + pulse_start = 0; + pulse_width = 0; + } + } + + base_detect_debounce_time = time_now + debounce_us; +} + +static void base_enable(void) +{ + /* Enable base detection interrupt. */ + base_detect_debounce_time = get_time().val; + hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_EN_LATER_US); + gpio_enable_interrupt(GPIO_BASE_DET_L); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, base_enable, HOOK_PRIO_DEFAULT); + +static void base_disable(void) +{ + /* + * Disable base detection interrupt and disable power to base. + * Set the state UNKNOWN so the next startup will initialize a + * correct state and notify AP. + */ + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_UNKNOWN); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, base_disable, HOOK_PRIO_DEFAULT); + +static void base_init(void) +{ + /* + * If we jumped to this image and chipset is already in S0, enable + * base. + */ + if (system_jumped_late() && chipset_in_state(CHIPSET_STATE_ON)) + base_enable(); +} +DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT + 1); + +void base_force_state(enum ec_set_base_state_cmd state) +{ + if (state == EC_SET_BASE_STATE_ATTACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_CONNECTED); + CPRINTS("BD forced connected"); + } else if (state == EC_SET_BASE_STATE_DETACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_DISCONNECTED); + CPRINTS("BD forced disconnected"); + } else { + base_enable(); + CPRINTS("BD forced reset"); + } +} diff --git a/board/homestar/battery.c b/board/homestar/battery.c new file mode 100644 index 0000000000..01fdb29f6a --- /dev/null +++ b/board/homestar/battery.c @@ -0,0 +1,219 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all homestar battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ + +const struct board_batt_params board_battery_info[] = { + /* COSMX GH02047XL 333-1C-DA-A */ + [BATTERY_GH02047XL_1C] = { + .fuel_gauge = { + .manuf_name = "333-1C-DA-A", + .device_name = "GH02047XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* COSMX GH02047XL */ + [BATTERY_GH02047XL] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .device_name = "GH02047XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* COSMX DS02032XL */ + [BATTERY_DS02032XL] = { + .fuel_gauge = { + .manuf_name = "333-AC-13-A", + .device_name = "DS02032XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* SMP DS02032XL */ + [BATTERY_DS02032XL_1C] = { + .fuel_gauge = { + .manuf_name = "333-1C-13-A", + .device_name = "DS02032XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* Sunwoda L21D4PG0 */ + [BATTERY_L21D4PG0] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "L21D4PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8900, /* mV */ + .voltage_normal = 7720, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 274, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + .vendor_param_start = 0x2f, + }, + }, + /* SMP L21M4PG0 */ + [BATTERY_L21M4PG0] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L21M4PG0", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8900, /* mV */ + .voltage_normal = 7720, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 274, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + .vendor_param_start = 0x2f, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_L21D4PG0; diff --git a/board/homestar/board.c b/board/homestar/board.c new file mode 100644 index 0000000000..306fd7c2a3 --- /dev/null +++ b/board/homestar/board.c @@ -0,0 +1,663 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Homestar board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/ln9310.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_mkbp.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "peripheral_charger.h" +#include "pi3usb9201.h" +#include "power.h" +#include "power/qcom.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "queue.h" +#include "shi_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define KS_DEBOUNCE_US (30 * MSEC) /* Debounce time for kickstand switch */ + +/* Forward declaration */ +static void tcpc_alert_event(enum gpio_signal signal); +static void usb0_evt(enum gpio_signal signal); +static void usb1_evt(enum gpio_signal signal); +static void ppc_interrupt(enum gpio_signal signal); +static void board_connect_c0_sbu(enum gpio_signal s); +static void switchcap_interrupt(enum gpio_signal signal); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* GPIO Interrupt Handlers */ +static void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_PD_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +static void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void usb1_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + case GPIO_USB_C1_SWCTL_INT_ODL: + sn5s330_interrupt(1); + break; + default: + break; + } +} + +static void board_connect_c0_sbu_deferred(void) +{ + /* + * If CCD_MODE_ODL asserts, it means there's a debug accessory connected + * and we should enable the SBU FETs. + */ + ppc_set_sbu(0, 1); +} +DECLARE_DEFERRED(board_connect_c0_sbu_deferred); + +static void board_connect_c0_sbu(enum gpio_signal s) +{ + hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); +} + +static void switchcap_interrupt(enum gpio_signal signal) +{ + ln9310_interrupt(signal); +} + +/* I2C port map */ +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* Measure VBUS through a 1/10 voltage divider */ + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + /* + * Adapter current output or battery charging/discharging current (uV) + * 18x amplification on charger side. + */ + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, + /* + * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read + * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and + * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we + * only divide by 2 (enough to avoid precision issues). + */ + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, + /* Base detection */ + [ADC_BASE_DET] = { "BASE_DET", NPCX_ADC_CH5, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct pwm_t pwm_channels[] = { + /* TODO(waihong): Assign a proper frequency. */ + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 4800 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* LN9310 switchcap */ +const struct ln9310_config_t ln9310_config = { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = LN9310_I2C_ADDR_0_FLAGS, +}; + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + } +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + { + .i2c_port = I2C_PORT_EEPROM, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/* Mutexes */ +static struct mutex g_lid_mutex; + +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm42607_data; + +enum lid_accelgyro_type { + LID_GYRO_NONE = 0, + LID_GYRO_BMI160 = 1, + LID_GYRO_ICM42607 = 2, +}; + +static enum lid_accelgyro_type lid_accelgyro_config; + +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t lid_standard_ref_icm42607 = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t icm42607_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref_icm42607, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm42607_lid_gyro = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref_icm42607, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t motion_sensors[] = { + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [LID_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void board_detect_motionsensor(void) +{ + int val = -1; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + if (lid_accelgyro_config != LID_GYRO_NONE) + return; + + /* Check base accelgyro chip */ + icm_read8(&icm42607_lid_accel, ICM42607_REG_WHO_AM_I, &val); + if (val == ICM42607_CHIP_ICM42607P) { + motion_sensors[LID_ACCEL] = icm42607_lid_accel; + motion_sensors[LID_GYRO] = icm42607_lid_gyro; + lid_accelgyro_config = LID_GYRO_ICM42607; + CPRINTS("LID Accelgyro: ICM42607"); + } else { + lid_accelgyro_config = LID_GYRO_BMI160; + CPRINTS("LID Accelgyro: BMI160"); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_DEFAULT + 1); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (lid_accelgyro_config) { + case LID_GYRO_ICM42607: + icm42607_interrupt(signal); + break; + case LID_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +enum battery_cell_type board_get_battery_cell_type(void) +{ + return BATTERY_CELL_TYPE_2S; +} + +static void board_switchcap_init(void) +{ + CPRINTS("Use switchcap: LN9310"); + + /* Configure and enable interrupt for LN9310 */ + gpio_set_flags(GPIO_SWITCHCAP_PG_INT_L, GPIO_INT_FALLING); + gpio_enable_interrupt(GPIO_SWITCHCAP_PG_INT_L); + + /* Only configure the switchcap if not sysjump */ + if (!system_jumped_late()) { + ln9310_init(); + } +} + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); + + /* + * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs + * for SBU may be disconnected after DP alt mode is off. Should enable + * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. + */ + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); + + /* Set the backlight duty cycle to 0. AP will override it later. */ + pwm_set_duty(PWM_CH_DISPLIGHT, 0); + + board_switchcap_init(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +__overridable uint16_t board_get_ps8xxx_product_id(int port) +{ + if (check_ps8755_chip(port)) + return PS8755_PRODUCT_ID; + + return PS8805_PRODUCT_ID; +} + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_hibernate(void) +{ + int i; + + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + + /* + * Board rev 1+ has the hardware fix. Don't need the following + * workaround. + */ + if (system_get_board_version() >= 1) + return; + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + ppc_vbus_sink_enable(i, 1); +} + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* + * Turn off display backlight in S3. AP has its own control. The EC's + * and the AP's will be AND'ed together in hardware. + */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); + pwm_enable(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Turn on display and keyboard backlight in S0. */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); + if (pwm_get_duty(PWM_CH_DISPLIGHT)) + pwm_enable(PWM_CH_DISPLIGHT, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON_L, !enable); + ln9310_software_enable(enable); +} + +int board_is_switchcap_enabled(void) +{ + return !gpio_get_level(GPIO_SWITCHCAP_ON_L); +} + +int board_is_switchcap_power_good(void) +{ + return ln9310_power_good(); +} + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} diff --git a/board/homestar/board.h b/board/homestar/board.h new file mode 100644 index 0000000000..fff7ad7f77 --- /dev/null +++ b/board/homestar/board.h @@ -0,0 +1,123 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Homestar board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* Free up flash space */ +#undef CONFIG_CONSOLE_CMDHELP + +#define CONFIG_BUTTON_TRIGGERED_RECOVERY + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Switchcap */ +#define CONFIG_LN9310 + +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_VENDOR_PARAM + +/* charger margin */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +/* Enable PD3.0 */ +#define CONFIG_USB_PD_REV30 + +/* BC 1.2 Charger */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* USB */ +#define CONFIG_USB_PD_TCPM_MULTI_PS8XXX +#define CONFIG_USB_PD_TCPM_PS8755 +#define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* Lid accel/gyro */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_FRONT_PROXIMITY_SWITCH + +#define CONFIG_DETACHABLE_BASE +#define CONFIG_BASE_ATTACHED_SWITCH + +/* + * Oled panel need to setup both vcc and backlight, AP will ctrl them. + * BL_DISABLE does not need to be controlled by ec. + */ +#ifdef CONFIG_BACKLIGHT_LID +#undef CONFIG_BACKLIGHT_LID +#endif + +/* GPIO alias */ +#define GPIO_AC_PRESENT GPIO_CHG_ACOK_OD +#define GPIO_WP_L GPIO_EC_FLASH_WP_ODL +#define GPIO_PMIC_RESIN_L GPIO_PM845_RESIN_L +#define GPIO_SWITCHCAP_PG_INT_L GPIO_LN9310_INT + +#define CONFIG_MKBP_INPUT_DEVICES + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_VBUS, + ADC_AMON_BMON, + ADC_PSYS, + ADC_BASE_DET, + ADC_CH_COUNT +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + LID_GYRO, + SENSOR_COUNT, +}; + +enum pwm_channel { PWM_CH_DISPLIGHT = 0, PWM_CH_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_GH02047XL_1C, + BATTERY_GH02047XL, + BATTERY_DS02032XL, + BATTERY_DS02032XL_1C, + BATTERY_L21D4PG0, + BATTERY_L21M4PG0, + BATTERY_TYPE_COUNT, +}; + +/* Reset all TCPCs. */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); +/* Base detection */ +void base_detect_interrupt(enum gpio_signal signal); + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !defined(__ASSEMBLER__) */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/homestar/build.mk b/board/homestar/build.mk new file mode 100644 index 0000000000..363ef59a16 --- /dev/null +++ b/board/homestar/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=trogdor + +board-y=battery.o board.o led.o base_detect.o usbc_config.o diff --git a/board/homestar/ec.tasklist b/board/homestar/ec.tasklist new file mode 100644 index 0000000000..8fc8115afc --- /dev/null +++ b/board/homestar/ec.tasklist @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/homestar/gpio.inc b/board/homestar/gpio.inc new file mode 100644 index 0000000000..37e71977ac --- /dev/null +++ b/board/homestar/gpio.inc @@ -0,0 +1,196 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* USB-C interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ +GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ +GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ +GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb1_evt) /* Interrupt from port-1 BC1.2 */ + +/* System interrupts */ +GPIO_INT(CHG_ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ +GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ +GPIO_INT(EC_FLASH_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ +GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ + +/* + * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down + * to make it low. Overload the interrupt function chipset_warm_reset_interrupt + * for not only signalling power_signal_interrupt but also handling the logic + * of WARM_RESET_L which is pulled-up by the same rail of POWER_GOOD. + */ +GPIO_INT(POWER_GOOD, PIN(5, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, chipset_power_good_interrupt) /* SRC_PP1800_S10A from PMIC */ +GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_warm_reset_interrupt) /* AP warm reset */ +GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ + +GPIO_INT(BASE_DET_L, PIN(3, 7), GPIO_INT_BOTH, base_detect_interrupt) /* Detachable base attached? */ + +/* Sensor interrupts */ +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, motion_interrupt) /* Accelerometer/gyro interrupt */ + +/* Switchcap, for LN9310, it is the interrupt line of LN9310. */ +GPIO_INT(LN9310_INT, PIN(E, 2), GPIO_INT_FALLING, switchcap_interrupt) + +/* + * EC_RST_ODL acts as a wake source from hibernate mode. However, it does not + * need to be an interrupt for normal EC operations. Simply set it an INPUT. + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ +GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ + +/* PMIC/AP 1.8V */ +GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ +GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ +GPIO(QSIP_ON, PIN(5, 0), GPIO_OUT_LOW) /* Not used, for non-switchcap testing */ + +/* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ +GPIO(SWITCHCAP_ON_L, PIN(D, 5), GPIO_ODR_HIGH) /* Enable switch cap */ +GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ +GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ +GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ + +/* Base detection */ +GPIO(EN_BASE, PIN(0, 4), GPIO_OUT_LOW) /* Enable power to detachable base */ + +/* POGO */ +GPIO(POGO_VBUS_PRESENT, PIN(6, 2), GPIO_INPUT) /* POGO PIN */ + +/* USB-C */ +GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_ODR_HIGH) /* Port-0 TCPC chip reset, actaully Open-Drain */ +GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_ODR_HIGH) /* Port-1 TCPC chip reset, actually Open-Drain */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ + +/* LEDs */ +GPIO(EC_CHG_LED_R_C0, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_G_C0, PIN(C, 4), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + +/* PWM */ +GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ +GPIO(WCAM_EC_VSYNC, PIN(C, 0), GPIO_INPUT) /* PWM6 */ +GPIO(FCAM_EC_VSYNC, PIN(6, 0), GPIO_INPUT) /* PWM7 */ + +/* ADC */ +GPIO(PPVAR_BOOSTIN_SENSE, PIN(4, 4), GPIO_INPUT) /* ADC1 */ +GPIO(CHARGER_IADP, PIN(4, 3), GPIO_INPUT) /* ADC2 */ +GPIO(CHARGER_PMON, PIN(4, 2), GPIO_INPUT) /* ADC3 */ + +/* I2C */ +GPIO(EC_I2C_POWER_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Board/SKU IDs */ +GPIO(BRD_ID0, PIN(C, 7), GPIO_INPUT) +GPIO(BRD_ID1, PIN(9, 3), GPIO_INPUT) +GPIO(BRD_ID2, PIN(6, 3), GPIO_INPUT) +GPIO(SKU_ID0, PIN(F, 0), GPIO_INPUT) +GPIO(SKU_ID1, PIN(4, 1), GPIO_INPUT) +GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. Apply PU for power saving */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(3, 1)) +UNUSED(PIN(3, 0)) +UNUSED(PIN(2, 7)) +UNUSED(PIN(2, 6)) +UNUSED(PIN(2, 5)) +UNUSED(PIN(2, 4)) +UNUSED(PIN(2, 3)) +UNUSED(PIN(2, 2)) +UNUSED(PIN(2, 1)) +UNUSED(PIN(2, 0)) +UNUSED(PIN(1, 7)) +UNUSED(PIN(1, 6)) +UNUSED(PIN(1, 5)) +UNUSED(PIN(1, 4)) +UNUSED(PIN(1, 3)) +UNUSED(PIN(1, 2)) +UNUSED(PIN(1, 1)) +UNUSED(PIN(1, 0)) +UNUSED(PIN(0, 7)) +UNUSED(PIN(0, 6)) +UNUSED(PIN(0, 5)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(C, 6)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(5, 6)) +UNUSED(PIN(8, 0)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(D, 1)) +UNUSED(PIN(D, 3)) +UNUSED(PIN(7, 5)) +UNUSED(PIN(8, 6)) +UNUSED(PIN(7, 3)) +UNUSED(PIN(7, 4)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(8, 5)) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ +ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1 SDA (GPIO90), I2C2 (GPIO91/92) */ +ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) */ +ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ +ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ +ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ +ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ +/* TODO(Camera?) should have a poper config for this, PWM or not */ +ALTERNATE(PIN_MASK(C, 0x01), 1, MODULE_PWM, 0) /* PWM6 (GPIOC0) - WCAM_EC_VSYNC */ +ALTERNATE(PIN_MASK(6, 0x01), 1, MODULE_PWM, 0) /* PWM7 (GPIO60) - FCAM_EC_VSYNC */ + + diff --git a/board/homestar/led.c b/board/homestar/led.c new file mode 100644 index 0000000000..0b6f177b5a --- /dev/null +++ b/board/homestar/led.c @@ -0,0 +1,163 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +/* Battery LED blinks every per 400ms */ +#define LED_HALF_ONE_SEC (500 / HOOK_TICK_INTERVAL_MS) + +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_GREEN, + LED_AMBER, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color(enum led_color color) +{ + gpio_set_level(GPIO_EC_CHG_LED_R_C0, + (color == LED_RED) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(GPIO_EC_CHG_LED_G_C0, + (color == LED_GREEN) ? BAT_LED_ON : BAT_LED_OFF); + if (color == LED_AMBER) { + gpio_set_level(GPIO_EC_CHG_LED_R_C0, BAT_LED_ON); + gpio_set_level(GPIO_EC_CHG_LED_G_C0, BAT_LED_ON); + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color(LED_RED); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color(LED_GREEN); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color(LED_AMBER); + else + led_set_color(LED_OFF); + + return EC_SUCCESS; +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + int color = LED_OFF; + int period = 0; + int percent = DIV_ROUND_NEAREST(charge_get_display_charge(), 10); + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + case LED_PWRS_CHARGE_NEAR_FULL: + if (chipset_in_state(CHIPSET_STATE_ON | + CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_ANY_OFF)) { + if (percent <= BATTERY_LEVEL_CRITICAL) { + /* battery capa <= 5%, Red */ + color = LED_RED; + } else if (percent > BATTERY_LEVEL_CRITICAL && + percent < CONFIG_BATT_HOST_FULL_FACTOR) { + /* 5% < battery capa < 97%, Orange */ + color = LED_AMBER; + } else { + /* battery capa >= 97%, Green */ + color = LED_GREEN; + } + } + break; + case LED_PWRS_DISCHARGE: + /* Always indicate off on when discharging */ + color = LED_OFF; + break; + case LED_PWRS_ERROR: + /* Battery error, Red on 1sec off 1sec */ + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_OFF; + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_RED; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode, Red 2 sec, green 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_GREEN; + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + led_set_color(color); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_BATTERY_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_RED : LED_OFF; + + led_auto_control(EC_LED_ID_BATTERY_LED, 0); + + led_set_color(color); +} diff --git a/board/homestar/usbc_config.c b/board/homestar/usbc_config.c new file mode 100644 index 0000000000..28f6b7a1c9 --- /dev/null +++ b/board/homestar/usbc_config.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor family-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "console.h" +#include "usb_pd.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/homestar/vif_override.xml b/board/homestar/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/homestar/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/host/battery.c b/board/host/battery.c index 1228485ab7..ff87a118b7 100644 --- a/board/host/battery.c +++ b/board/host/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,6 +6,7 @@ */ #include "battery.h" +#include "battery_fuel_gauge.h" #include "battery_smart.h" #include "common.h" #include "console.h" @@ -14,16 +15,15 @@ static uint16_t mock_smart_battery[SB_MANUFACTURER_DATA + 1]; -int sb_i2c_xfer(int port, uint16_t slave_addr_flags, - const uint8_t *out, int out_size, +int sb_i2c_xfer(int port, uint16_t addr_flags, const uint8_t *out, int out_size, uint8_t *in, int in_size, int flags) { if (out_size == 0) return EC_SUCCESS; - if (port != I2C_PORT_BATTERY || slave_addr_flags != BATTERY_ADDR_FLAGS) + if (port != I2C_PORT_BATTERY || addr_flags != BATTERY_ADDR_FLAGS) return EC_ERROR_INVAL; - if (out[0] >= ARRAY_SIZE(mock_smart_battery)) + if (out[0] >= ARRAY_SIZE(mock_smart_battery)) return EC_ERROR_UNIMPLEMENTED; if (out_size == 1) { /* Read */ @@ -56,12 +56,12 @@ static const struct battery_info bat_info = { * normal = 7.4V * min = 6.0V */ - .voltage_max = 8400, + .voltage_max = 8400, .voltage_normal = 7400, - .voltage_min = 6000, + .voltage_min = 6000, /* Pre-charge current: I <= 0.01C */ - .precharge_current = 64, /* mA */ + .precharge_current = 64, /* mA */ /* * Operational temperature range @@ -70,10 +70,10 @@ static const struct battery_info bat_info = { */ .start_charging_min_c = 0, .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 50, - .discharging_min_c = -20, - .discharging_max_c = 60, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -20, + .discharging_max_c = 60, }; const struct battery_info *battery_get_info(void) diff --git a/board/host/board.c b/board/host/board.c index 25abd9a0ad..00367a5a54 100644 --- a/board/host/board.c +++ b/board/host/board.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,13 +13,15 @@ #include "i2c.h" #include "inductive_charging.h" #include "lid_switch.h" -#include "motion_sense.h" #include "motion_lid.h" +#include "motion_sense.h" #include "power_button.h" #include "spi.h" +#include "tablet_mode.h" #include "temp_sensor.h" #include "test_util.h" #include "timer.h" +#include "usb_pd_tcpm.h" #include "util.h" /* @@ -27,10 +29,15 @@ * GPIO ports. This maps back to 0, which is then ignored by the host GPIO mock * code. */ -#define GPIO_0 0 +#define GPIO_0 0 +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" +test_mockable const struct tcpc_config_t tcpc_config[] = { + [0] = {}, +}; + test_mockable enum battery_present battery_is_present(void) { return BP_YES; @@ -43,10 +50,10 @@ test_mockable_static int mock_temp_get_val(int idx, int *temp_ptr) } const struct temp_sensor_t temp_sensors[] = { - {"CPU", TEMP_SENSOR_TYPE_CPU, mock_temp_get_val, 0}, - {"Board", TEMP_SENSOR_TYPE_BOARD, mock_temp_get_val, 1}, - {"Case", TEMP_SENSOR_TYPE_CASE, mock_temp_get_val, 2}, - {"Battery", TEMP_SENSOR_TYPE_BOARD, mock_temp_get_val, 3}, + { "CPU", TEMP_SENSOR_TYPE_CPU, mock_temp_get_val, 0 }, + { "Board", TEMP_SENSOR_TYPE_BOARD, mock_temp_get_val, 1 }, + { "Case", TEMP_SENSOR_TYPE_CASE, mock_temp_get_val, 2 }, + { "Battery", TEMP_SENSOR_TYPE_BOARD, mock_temp_get_val, 3 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -58,24 +65,46 @@ test_mockable void fps_event(enum gpio_signal signal) { } +test_mockable void gmr_tablet_switch_isr(enum gpio_signal signal) +{ +} + #ifdef CONFIG_I2C /* I2C ports */ const struct i2c_port_t i2c_ports[] = { #ifdef I2C_PORT_BATTERY - {"battery", I2C_PORT_BATTERY, 100, 0, 0}, + { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = 0, + .sda = 0 }, #elif defined I2C_PORT_LIGHTBAR - {"lightbar", I2C_PORT_LIGHTBAR, 100, 0, 0}, + { .name = "lightbar", + .port = I2C_PORT_LIGHTBAR, + .kbps = 100, + .scl = 0, + .sda = 0 }, #elif defined I2C_PORT_HOST_TCPC - {"tcpc", I2C_PORT_HOST_TCPC, 100, 0, 0}, + { .name = "tcpc", + .port = I2C_PORT_HOST_TCPC, + .kbps = 100, + .scl = 0, + .sda = 0 }, #elif defined I2C_PORT_EEPROM - {"eeprom", I2C_PORT_EEPROM, 100, 0, 0}, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 100, + .scl = 0, + .sda = 0 }, +#elif defined I2C_PORT_WLC + { .name = "wlc", .port = I2C_PORT_WLC, .kbps = 100, .scl = 0, .sda = 0 }, #endif }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); #endif -#ifdef CONFIG_SPI_MASTER +#ifdef CONFIG_SPI_CONTROLLER /* SPI devices */ const struct spi_device_t spi_devices[] = { /* Fingerprint sensor (SCLK at 4Mhz) */ @@ -102,11 +131,10 @@ int board_get_entropy(void *buffer, int len) } #endif -static uint8_t eeprom[CBI_EEPROM_SIZE]; +static uint8_t eeprom[CBI_IMAGE_SIZE]; -int eeprom_i2c_xfer(int port, uint16_t addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) +int eeprom_i2c_xfer(int port, uint16_t addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size, int flags) { static int offset; diff --git a/board/host/board.h b/board/host/board.h index 0eafedc2bc..eb6eecb14e 100644 --- a/board/host/board.h +++ b/board/host/board.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,7 +12,7 @@ /* Default-yes, override to no by including fake_battery module. */ #define CONFIG_BATTERY_PRESENT_CUSTOM #undef CONFIG_CMD_PD -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_EXTPOWER_GPIO #undef CONFIG_FMAP #define CONFIG_POWER_BUTTON @@ -30,6 +30,8 @@ #define CONFIG_USB_PD_CUSTOM_PDO #define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_CMD_AP_RESET_LOG + #include "gpio_signal.h" enum temp_sensor_id { @@ -44,10 +46,13 @@ enum temp_sensor_id { enum adc_channel { ADC_CH_CHARGER_CURRENT, ADC_AC_ADAPTER_ID_VOLTAGE, + ADC_VBUS, ADC_CH_COUNT }; +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + /* Fake test charge suppliers */ enum { CHARGE_SUPPLIER_TEST1, @@ -64,25 +69,25 @@ enum { }; /* Standard-current Rp */ -#define PD_SRC_VNC PD_SRC_DEF_VNC_MV -#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV +#define PD_SRC_VNC PD_SRC_DEF_VNC_MV +#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV /* delay necessary for the voltage transition on the power supply */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 20000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 20000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 20000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 -#define PD_MIN_CURRENT_MA 500 -#define PD_MIN_POWER_MW 7500 +#define PD_MIN_CURRENT_MA 500 +#define PD_MIN_POWER_MW 7500 /* Configuration for fake Fingerprint Sensor */ -#define CONFIG_SPI_MASTER -#define CONFIG_SPI_FP_PORT 1 /* SPI1: third master config */ +#define CONFIG_SPI_CONTROLLER +#define CONFIG_SPI_FP_PORT 1 /* SPI1: third master config */ #define CONFIG_RNG void fps_event(enum gpio_signal signal); @@ -90,8 +95,8 @@ void fps_event(enum gpio_signal signal); #define CONFIG_CRC8 #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define I2C_PORT_EEPROM 0 -#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER +#define I2C_PORT_EEPROM 0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 #endif /* __CROS_EC_BOARD_H */ diff --git a/board/host/build.mk b/board/host/build.mk index 241f197342..c17ed65d95 100644 --- a/board/host/build.mk +++ b/board/host/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. +# Copyright 2013 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -12,4 +12,5 @@ board-y=board.o board-$(HAS_TASK_CHIPSET)+=chipset.o board-$(CONFIG_BATTERY_MOCK)+=battery.o charger.o board-$(CONFIG_FANS)+=fan.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_config.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_config.o usb_pd_pdo.o +board-$(CONFIG_CEC)+=cec.o diff --git a/board/host/cec.c b/board/host/cec.c new file mode 100644 index 0000000000..f0a86a591e --- /dev/null +++ b/board/host/cec.c @@ -0,0 +1,62 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Mock CEC driver. + */ + +#include "cec.h" +#include "util.h" + +static int mock_cec_send(int port, const uint8_t *msg, uint8_t len) +{ + return EC_SUCCESS; +} + +static int mock_cec_get_received_message(int port, uint8_t **msg, uint8_t *len) +{ + return EC_SUCCESS; +} + +static int mock_cec_get_enable(int port, uint8_t *enable) +{ + return EC_SUCCESS; +} + +static int mock_cec_set_enable(int port, uint8_t enable) +{ + return EC_SUCCESS; +} + +static int mock_cec_get_logical_addr(int port, uint8_t *logical_addr) +{ + return EC_SUCCESS; +} + +static int mock_cec_set_logical_addr(int port, uint8_t logical_addr) +{ + return EC_SUCCESS; +} + +static int mock_cec_init(int port) +{ + return EC_SUCCESS; +} + +static const struct cec_drv mock_cec_drv = { + .init = &mock_cec_init, + .get_enable = &mock_cec_get_enable, + .set_enable = &mock_cec_set_enable, + .get_logical_addr = &mock_cec_get_logical_addr, + .set_logical_addr = &mock_cec_set_logical_addr, + .send = &mock_cec_send, + .get_received_message = &mock_cec_get_received_message, +}; + +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &mock_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); diff --git a/board/host/charger.c b/board/host/charger.c index 01f29571d0..7fa9b78dd1 100644 --- a/board/host/charger.c +++ b/board/host/charger.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -7,20 +7,20 @@ #include "battery_smart.h" #include "charger.h" -#include "console.h" #include "common.h" +#include "console.h" #include "util.h" static const struct charger_info mock_charger_info = { - .name = "MockCharger", - .voltage_max = 19200, - .voltage_min = 1024, + .name = "MockCharger", + .voltage_max = 19200, + .voltage_min = 1024, .voltage_step = 16, - .current_max = 8192, - .current_min = 128, + .current_max = 8192, + .current_min = 128, .current_step = 128, - .input_current_max = 8064, - .input_current_min = 128, + .input_current_max = 8064, + .input_current_min = 128, .input_current_step = 128, }; @@ -37,7 +37,6 @@ static const struct charger_info *mock_get_info(int chgnum) return &mock_charger_info; } - static enum ec_error_list mock_get_status(int chgnum, int *status) { *status = CHARGER_LEVEL_2; @@ -47,7 +46,6 @@ static enum ec_error_list mock_get_status(int chgnum, int *status) return EC_SUCCESS; } - static enum ec_error_list mock_set_mode(int chgnum, int mode) { if (mode & CHARGE_FLAG_INHIBIT_CHARGE) @@ -57,14 +55,12 @@ static enum ec_error_list mock_set_mode(int chgnum, int mode) return EC_SUCCESS; } - static enum ec_error_list mock_get_current(int chgnum, int *current) { *current = mock_current; return EC_SUCCESS; } - static enum ec_error_list mock_set_current(int chgnum, int current) { const struct charger_info *info = mock_get_info(chgnum); @@ -86,7 +82,6 @@ static enum ec_error_list mock_get_voltage(int chgnum, int *voltage) return EC_SUCCESS; } - static enum ec_error_list mock_set_voltage(int chgnum, int voltage) { mock_voltage = voltage; @@ -94,41 +89,36 @@ static enum ec_error_list mock_set_voltage(int chgnum, int voltage) return EC_SUCCESS; } - static enum ec_error_list mock_get_option(int chgnum, int *option) { *option = mock_option; return EC_SUCCESS; } - static enum ec_error_list mock_set_option(int chgnum, int option) { mock_option = option; return EC_SUCCESS; } - static enum ec_error_list mock_manufacturer_id(int chgnum, int *id) { return EC_SUCCESS; } - static enum ec_error_list mock_device_id(int chgnum, int *id) { return EC_SUCCESS; } - -static enum ec_error_list mock_get_input_current(int chgnum, int *input_current) +static enum ec_error_list mock_get_input_current_limit(int chgnum, + int *input_current) { *input_current = mock_input_current; return EC_SUCCESS; } - -static enum ec_error_list mock_set_input_current(int chgnum, int current) +static enum ec_error_list mock_set_input_current_limit(int chgnum, int current) { const struct charger_info *info = mock_get_info(chgnum); @@ -144,10 +134,10 @@ static enum ec_error_list mock_set_input_current(int chgnum, int current) return EC_SUCCESS; } - static enum ec_error_list mock_post_init(int chgnum) { - mock_current = mock_input_current = CONFIG_CHARGER_INPUT_CURRENT; + mock_current = mock_input_current = + CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT; return EC_SUCCESS; } @@ -160,8 +150,8 @@ const struct charger_drv mock_drv = { .set_current = &mock_set_current, .get_voltage = &mock_get_voltage, .set_voltage = &mock_set_voltage, - .set_input_current = &mock_set_input_current, - .get_input_current = &mock_get_input_current, + .set_input_current_limit = &mock_set_input_current_limit, + .get_input_current_limit = &mock_get_input_current_limit, .manufacturer_id = &mock_manufacturer_id, .device_id = &mock_device_id, .get_option = &mock_get_option, diff --git a/board/host/chipset.c b/board/host/chipset.c index 3cb859eb29..ece97dc4fd 100644 --- a/board/host/chipset.c +++ b/board/host/chipset.c @@ -1,22 +1,26 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Chipset module for emulator */ -#include +/* Does not run a chipset task, but does emulate an AP chipset */ +#define CONFIG_AP_POWER_CONTROL + #include "chipset.h" #include "common.h" #include "hooks.h" #include "task.h" #include "test_util.h" +#include + static int chipset_state = CHIPSET_STATE_SOFT_OFF; static int power_on_req; static int power_off_req; -test_mockable void chipset_reset(enum chipset_reset_reason reason) +test_mockable void chipset_reset(enum chipset_shutdown_reason reason) { fprintf(stderr, "Chipset reset: %d!\n", reason); } diff --git a/board/host/ec.tasklist b/board/host/ec.tasklist index c056c51e8a..0195800932 100644 --- a/board/host/ec.tasklist +++ b/board/host/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/host/fan.c b/board/host/fan.c index 1e1001f1cd..de335afa06 100644 --- a/board/host/fan.c +++ b/board/host/fan.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,7 +22,10 @@ const struct fan_rpm fan_rpm_0 = { }; const struct fan_t fans[CONFIG_FANS] = { - { .conf = &fan_conf_0, .rpm = &fan_rpm_0, }, + { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, }; static int mock_enabled; diff --git a/board/host/gpio.inc b/board/host/gpio.inc index c567aa0277..e9855b686f 100644 --- a/board/host/gpio.inc +++ b/board/host/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,6 +14,7 @@ GPIO_INT(AC_PRESENT, PIN(0, 2), GPIO_INT_BOTH, extpower_interrupt) GPIO_INT(VOLUME_DOWN_L, PIN(0, 3), GPIO_INT_BOTH, button_interrupt) GPIO_INT(VOLUME_UP_L, PIN(0, 4), GPIO_INT_BOTH, button_interrupt) GPIO_INT(CHARGE_DONE, PIN(0, 5), GPIO_INT_BOTH, inductive_charging_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(0, 19), GPIO_INT_BOTH, gmr_tablet_switch_isr) /* Fingerprint */ GPIO_INT(FPS_INT, PIN(0, 14), GPIO_INT_RISING, fps_event) @@ -34,3 +35,5 @@ GPIO(USB_C0_DISCHARGE, PIN(0, 15), 0) GPIO(I2C_SCL, PIN(0, 16), GPIO_INPUT) GPIO(I2C_SDA, PIN(0, 17), GPIO_INPUT) + +GPIO(EC_CBI_WP, PIN(0, 18), GPIO_OUT_LOW) diff --git a/board/host/usb_pd_config.c b/board/host/usb_pd_config.c index 91c30d1755..10ed9536fa 100644 --- a/board/host/usb_pd_config.c +++ b/board/host/usb_pd_config.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -32,4 +32,3 @@ test_mockable int pd_adc_read(int port, int cc) /* Not implemented */ return 0; } - diff --git a/board/host/usb_pd_config.h b/board/host/usb_pd_config.h index fb12b2ce7d..0fff2af019 100644 --- a/board/host/usb_pd_config.h +++ b/board/host/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/host/usb_pd_pdo.c b/board/host/usb_pd_pdo.c new file mode 100644 index 0000000000..a352148ecb --- /dev/null +++ b/board/host/usb_pd_pdo.c @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP) + +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 900, PDO_FIXED_FLAGS), + PDO_FIXED(12000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_BATT(4750, 21000, 15000), + PDO_VAR(4750, 21000, 3000), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/host/usb_pd_pdo.h b/board/host/usb_pd_pdo.h new file mode 100644 index 0000000000..4f1a64dced --- /dev/null +++ b/board/host/usb_pd_pdo.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_HOST_USB_PD_PDO_H +#define __CROS_EC_BOARD_HOST_USB_PD_PDO_H + +#include "stdint.h" + +extern const uint32_t pd_src_pdo[2]; +extern const int pd_src_pdo_cnt; + +extern const uint32_t pd_snk_pdo[3]; +extern const int pd_snk_pdo_cnt; + +#endif /* __CROS_EC_BOARD_HOST_USB_PD_PDO_H */ diff --git a/board/host/usb_pd_policy.c b/board/host/usb_pd_policy.c index 1ea28dcbe9..dc965ca192 100644 --- a/board/host/usb_pd_policy.c +++ b/board/host/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,39 +6,25 @@ #include "common.h" #include "console.h" #include "usb_pd.h" +#include "usb_pd_pdo.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP) - -const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 900, PDO_FIXED_FLAGS), - PDO_FIXED(12000, 3000, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); - -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), - PDO_BATT(4750, 21000, 15000), - PDO_VAR(4750, 21000, 3000), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); - -int pd_set_power_supply_ready(int port) +test_mockable int pd_set_power_supply_ready(int port) { /* Not implemented */ return EC_SUCCESS; } -void pd_power_supply_reset(int port) +test_mockable void pd_power_supply_reset(int port) { /* Not implemented */ } -void pd_set_input_current_limit(int port, uint32_t max_ma, - uint32_t supply_voltage) +__overridable void pd_set_input_current_limit(int port, uint32_t max_ma, + uint32_t supply_voltage) { /* Not implemented */ } @@ -55,22 +41,18 @@ __override int pd_check_power_swap(int port) return 1; } -__override int pd_check_data_swap(int port, - enum pd_data_role data_role) +__override int pd_check_data_swap(int port, enum pd_data_role data_role) { /* Always allow data swap */ return 1; } -__override void pd_check_pr_role(int port, - enum pd_power_role pr_role, +__override void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { } -__override void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +__override void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { } diff --git a/board/host/vif_override.xml b/board/host/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/host/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/hyperdebug/board.c b/board/hyperdebug/board.c new file mode 100644 index 0000000000..50d7855b1e --- /dev/null +++ b/board/hyperdebug/board.c @@ -0,0 +1,287 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* HyperDebug board configuration */ + +#include "adc.h" +#include "common.h" +#include "ec_version.h" +#include "queue_policies.h" +#include "registers.h" +#include "spi.h" +#include "stm32-dma.h" +#include "timer.h" +#include "usart-stm32l5.h" +#include "usb-stream.h" +#include "usb_spi.h" + +#include + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +void board_config_pre_init(void) +{ + /* enable SYSCFG clock */ + STM32_RCC_APB2ENR |= STM32_RCC_SYSCFGEN; +} + +/****************************************************************************** + * Forward UARTs as a USB serial interface. + */ + +#define USB_STREAM_RX_SIZE 16 +#define USB_STREAM_TX_SIZE 16 + +/****************************************************************************** + * Forward USART2 as a simple USB serial interface. + */ + +static struct usart_config const usart2; +struct usb_stream_config const usart2_usb; + +static struct queue const usart2_to_usb = + QUEUE_DIRECT(64, uint8_t, usart2.producer, usart2_usb.consumer); +static struct queue const usb_to_usart2 = + QUEUE_DIRECT(64, uint8_t, usart2_usb.producer, usart2.consumer); + +static struct usart_config const usart2 = + USART_CONFIG(usart2_hw, usart_rx_interrupt, usart_tx_interrupt, 115200, + 0, usart2_to_usb, usb_to_usart2); + +USB_STREAM_CONFIG(usart2_usb, USB_IFACE_USART2_STREAM, + USB_STR_USART2_STREAM_NAME, USB_EP_USART2_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, usb_to_usart2, + usart2_to_usb) + +/****************************************************************************** + * Forward USART3 as a simple USB serial interface. + */ + +static struct usart_config const usart3; +struct usb_stream_config const usart3_usb; + +static struct queue const usart3_to_usb = + QUEUE_DIRECT(64, uint8_t, usart3.producer, usart3_usb.consumer); +static struct queue const usb_to_usart3 = + QUEUE_DIRECT(64, uint8_t, usart3_usb.producer, usart3.consumer); + +static struct usart_config const usart3 = + USART_CONFIG(usart3_hw, usart_rx_interrupt, usart_tx_interrupt, 115200, + 0, usart3_to_usb, usb_to_usart3); + +USB_STREAM_CONFIG(usart3_usb, USB_IFACE_USART3_STREAM, + USB_STR_USART3_STREAM_NAME, USB_EP_USART3_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, usb_to_usart3, + usart3_to_usb) + +/****************************************************************************** + * Forward USART4 as a simple USB serial interface. + */ + +static struct usart_config const usart4; +struct usb_stream_config const usart4_usb; + +static struct queue const usart4_to_usb = + QUEUE_DIRECT(64, uint8_t, usart4.producer, usart4_usb.consumer); +static struct queue const usb_to_usart4 = + QUEUE_DIRECT(64, uint8_t, usart4_usb.producer, usart4.consumer); + +static struct usart_config const usart4 = + USART_CONFIG(usart4_hw, usart_rx_interrupt, usart_tx_interrupt, 115200, + 0, usart4_to_usb, usb_to_usart4); + +USB_STREAM_CONFIG(usart4_usb, USB_IFACE_USART4_STREAM, + USB_STR_USART4_STREAM_NAME, USB_EP_USART4_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, usb_to_usart4, + usart4_to_usb) + +/****************************************************************************** + * Forward USART5 as a simple USB serial interface. + */ + +static struct usart_config const usart5; +struct usb_stream_config const usart5_usb; + +static struct queue const usart5_to_usb = + QUEUE_DIRECT(64, uint8_t, usart5.producer, usart5_usb.consumer); +static struct queue const usb_to_usart5 = + QUEUE_DIRECT(64, uint8_t, usart5_usb.producer, usart5.consumer); + +static struct usart_config const usart5 = + USART_CONFIG(usart5_hw, usart_rx_interrupt, usart_tx_interrupt, 115200, + 0, usart5_to_usb, usb_to_usart5); + +USB_STREAM_CONFIG(usart5_usb, USB_IFACE_USART5_STREAM, + USB_STR_USART5_STREAM_NAME, USB_EP_USART5_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, usb_to_usart5, + usart5_to_usb) + +/****************************************************************************** + * Define the strings used in our USB descriptors. + */ + +const void *const usb_strings[] = { + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("HyperDebug"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("HyperDebug Shell"), + [USB_STR_SPI_NAME] = USB_STRING_DESC("SPI"), + [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), + [USB_STR_USART2_STREAM_NAME] = USB_STRING_DESC("UART2"), + [USB_STR_USART3_STREAM_NAME] = USB_STRING_DESC("UART3"), + [USB_STR_USART4_STREAM_NAME] = USB_STRING_DESC("UART4"), + [USB_STR_USART5_STREAM_NAME] = USB_STRING_DESC("UART5"), + [USB_STR_DFU_NAME] = USB_STRING_DESC("DFU"), +}; + +BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); + +/****************************************************************************** + * Set up USB PD + */ + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* + * All available ADC signals, converted to mV (3300mV/4096). Every one + * is declared with same name as the GPIO signal on the same pin, that + * is how opentitantool identifies the signal. + * + * Technically, the Nucleo-L552ZE-Q board can run at either 1v8 or 3v3 + * supply, but we use HyperDebug only on 3v3 setting. If in the future + * we want to detect actual voltage, Vrefint could be used. This would + * also serve as calibration as the supply voltage may not be 3300mV + * exactly. + */ + [ADC_CN9_11] = { "CN9_11", 3300, 4096, 0, STM32_AIN(1) }, + [ADC_CN9_9] = { "CN9_9", 3300, 4096, 0, STM32_AIN(2) }, + /*[ADC_CN10_9] = { "CN10_9", 3300, 4096, 0, STM32_AIN(3) },*/ + [ADC_CN9_5] = { "CN9_5", 3300, 4096, 0, STM32_AIN(4) }, + [ADC_CN10_29] = { "CN10_29", 3300, 4096, 0, STM32_AIN(5) }, + [ADC_CN10_11] = { "CN10_11", 3300, 4096, 0, STM32_AIN(6) }, + [ADC_CN9_3] = { "CN9_3", 3300, 4096, 0, STM32_AIN(7) }, + [ADC_CN9_1] = { "CN9_1", 3300, 4096, 0, STM32_AIN(8) }, + [ADC_CN7_9] = { "CN7_9", 3300, 4096, 0, STM32_AIN(9) }, + [ADC_CN7_10] = { "CN7_10", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_CN7_12] = { "CN7_12", 3300, 4096, 0, STM32_AIN(11) }, + [ADC_CN7_14] = { "CN7_14", 3300, 4096, 0, STM32_AIN(12) }, + [ADC_CN9_7] = { "CN9_7", 3300, 4096, 0, STM32_AIN(15) }, + [ADC_CN10_7] = { "CN10_7", 3300, 4096, 0, STM32_AIN(16) }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/****************************************************************************** + * Initialize board. + */ + +static void board_init(void) +{ + timestamp_t deadline; + + STM32_GPIO_BSRR(STM32_GPIOE_BASE) |= 0x0000FF00; + + /* We know VDDIO2 is present, enable the GPIO circuit. */ + STM32_PWR_CR2 |= STM32_PWR_CR2_IOSV; + + /* USB to serial queues */ + queue_init(&usart2_to_usb); + queue_init(&usb_to_usart2); + queue_init(&usart3_to_usb); + queue_init(&usb_to_usart3); + queue_init(&usart4_to_usb); + queue_init(&usb_to_usart4); + queue_init(&usart5_to_usb); + queue_init(&usb_to_usart5); + + /* UART init */ + usart_init(&usart2); + usart_init(&usart3); + usart_init(&usart4); + usart_init(&usart5); + + /* Structured endpoints */ + usb_spi_enable(1); + + /* Configure SPI GPIOs */ + gpio_config_module(MODULE_SPI, 1); + + /* Enable ADC */ + STM32_RCC_AHB2ENR |= STM32_RCC_AHB2ENR_ADCEN; + /* Initialize the ADC by performing a fake reading */ + adc_read_channel(ADC_CN9_11); + + /* Enable DAC */ + STM32_RCC_APB1ENR |= STM32_RCC_APB1ENR1_DAC1EN; + + /* + * Enable SPI2. + */ + + /* Enable clocks to SPI2 module */ + STM32_RCC_APB1ENR1 |= STM32_RCC_APB1ENR1_SPI2EN; + + /* Reset SPI2 */ + STM32_RCC_APB1RSTR1 |= STM32_RCC_APB1RSTR1_SPI2RST; + STM32_RCC_APB1RSTR1 &= ~STM32_RCC_APB1RSTR1_SPI2RST; + + spi_enable(&spi_devices[0], 1); + + /* + * Enable OCTOSPI, no driver for this in chip/stm32. + */ + deadline.val = get_time().val + OCTOSPI_INIT_TIMEOUT_US; + + STM32_RCC_AHB3ENR |= STM32_RCC_AHB3ENR_QSPIEN; + while (STM32_OCTOSPI_SR & STM32_OCTOSPI_SR_BUSY) { + timestamp_t now = get_time(); + if (timestamp_expired(deadline, &now)) { + /* + * Ideally, the USB host would have a way of + * discovering our failure to initialize OctoSPI. But + * for now, log and move on, this would happen only on + * code bug or hardware failure. + */ + cprints(CC_SPI, "Initialization of OctoSPI failed"); + break; + } + } + + /* + * Declare that a "Standard" SPI flash device, maximum size is connected + * to OCTOSPI. This allows the controller to send arbitrary 32-bit + * addresses, which is needed as we use the instruction and address + * bytes as arbitrary data to send via SPI. + */ + STM32_OCTOSPI_DCR1 = STM32_OCTOSPI_DCR1_MTYP_STANDARD | + STM32_OCTOSPI_DCR1_DEVSIZE_MSK; + /* Clock prescaler (max value 255) */ + STM32_OCTOSPI_DCR2 = spi_devices[1].div; + + /* Select DMA channel */ + dma_select_channel(STM32_DMAC_CH13, DMAMUX_REQ_OCTOSPI1); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +const char *board_read_serial(void) +{ + const uint32_t *stm32_unique_id = + (const uint32_t *)STM32_UNIQUE_ID_BASE; + static char serial[13]; + + // Compute 12 hex digits from three factory programmed 32-bit "Unique + // ID" words in a manner that has been observed to be consistent with + // how the STM DFU ROM bootloader presents its serial number. This + // means that the serial number of any particular HyperDebug board will + // remain the same as it enters and leaves DFU mode for software + // upgrade. + int rc = snprintf(serial, sizeof(serial), "%08X%04X", + stm32_unique_id[0] + stm32_unique_id[2], + stm32_unique_id[1] >> 16); + if (12 != rc) + return NULL; + return serial; +} diff --git a/board/hyperdebug/board.h b/board/hyperdebug/board.h new file mode 100644 index 0000000000..a0b533b758 --- /dev/null +++ b/board/hyperdebug/board.h @@ -0,0 +1,243 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* HyperDebug configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define CONFIG_LTO + +/* Disable deferred (async) flash protect*/ +#undef CONFIG_FLASH_PROTECT_DEFERRED + +/* Configure the flash */ +#undef CONFIG_RO_SIZE +#undef CONFIG_FW_PSTATE_OFF +#undef CONFIG_FW_PSTATE_SIZE +#undef CONFIG_RW_MEM_OFF +#undef CONFIG_RW_SIZE + +#define CONFIG_RO_SIZE (4 * 1024) +#define CONFIG_RW_MEM_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) +#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE_BYTES - CONFIG_RW_MEM_OFF) +#undef CONFIG_IMAGE_PADDING + +#ifdef SECTION_IS_RO + +/* Configure the Boot Manager. */ +#define CONFIG_MALLOC +#define CONFIG_DFU_BOOTMANAGER_MAIN +#define CONFIG_DFU_BOOTMANAGER_SHARED +#undef CONFIG_COMMON_RUNTIME +#undef CONFIG_COMMON_PANIC_OUTPUT +#undef CONFIG_COMMON_GPIO +#undef CONFIG_COMMON_TIMER +#undef CONFIG_WATCHDOG + +#else /* !SECTION_IS_RO */ + +/* + * PLL configuration. Freq = STM32_HSE_CLOCK or HSI (16MHz) * N / M / R. + * + * In our case, 16MHz * 13 / 1 / 2 = 104MHz. + */ + +#undef STM32_PLLM +#undef STM32_PLLN +#undef STM32_PLLR +#define STM32_PLLM 1 +#define STM32_PLLN 13 +#define STM32_PLLR 2 + +#define STM32_USE_PLL +#define CPU_CLOCK 104000000 + +#define CONFIG_ADC +#define CONFIG_ADC_SAMPLE_TIME STM32_ADC_SMPR_247_5_CY +#undef CONFIG_ADC_WATCHDOG +#define CONFIG_BOARD_PRE_INIT + +#define CONFIG_ROM_BASE 0x0 +#define CONFIG_ROM_SIZE (CONFIG_RAM_BASE - CONFIG_ROM_BASE) + +/* DFU Firmware Update */ +#define CONFIG_DFU_RUNTIME +#define CONFIG_DFU_BOOTMANAGER_SHARED + +/* Enable USB forwarding on UART 2, 3, 4, and 5. */ +#define CONFIG_STREAM_USART +#undef CONFIG_STREAM_USART1 +#define CONFIG_STREAM_USART2 +#define CONFIG_STREAM_USART3 +#define CONFIG_STREAM_USART4 +#define CONFIG_STREAM_USART5 +#undef CONFIG_STREAM_USART9 +#define CONFIG_STREAM_USB +#define CONFIG_CMD_USART_INFO + +/* The UART console is on LPUART (UART9), connected to st-link debugger. */ +#undef CONFIG_UART_CONSOLE +#define CONFIG_UART_CONSOLE 9 +#undef CONFIG_UART_TX_DMA +#undef CONFIG_UART_RX_DMA + +/* Optional features */ +#define CONFIG_HW_CRC +#undef CONFIG_PVD + +/* + * See 'Programmable voltage detector characteristics' in the + * STM32F072x8 Datasheet. PVD Threshold 1 corresponds to a falling + * voltage threshold of min:2.09V, max:2.27V. + */ +#define PVD_THRESHOLD (1) + +/* USB Configuration */ + +#define CONFIG_USB +#define CONFIG_USB_PID 0x520e +#define CONFIG_USB_CONSOLE + +/* + * Enabling USB updating would exceed the number of USB endpoints + * supported by the hardware. We will have to rely on the built-in + * DFU support of STM32 chips. + */ +#undef CONFIG_USB_UPDATE + +#undef CONFIG_USB_MAXPOWER_MA +#define CONFIG_USB_MAXPOWER_MA 100 + +#define CONFIG_USB_SERIALNO +#define DEFAULT_SERIALNO "Uninitialized" + +/* USB interface indexes (use define rather than enum to expand them) */ +#define USB_IFACE_CONSOLE 0 +#define USB_IFACE_SPI 1 +#define USB_IFACE_I2C 2 +#define USB_IFACE_USART2_STREAM 3 +#define USB_IFACE_USART3_STREAM 4 +#define USB_IFACE_USART4_STREAM 5 +#define USB_IFACE_USART5_STREAM 6 +#define USB_IFACE_DFU 7 +#define USB_IFACE_COUNT 8 + +/* USB endpoint indexes (use define rather than enum to expand them) */ +#define USB_EP_CONTROL 0 +#define USB_EP_CONSOLE 1 +#define USB_EP_SPI 2 +#define USB_EP_I2C 3 +#define USB_EP_USART2_STREAM 4 +#define USB_EP_USART3_STREAM 5 +#define USB_EP_USART4_STREAM 6 +#define USB_EP_USART5_STREAM 7 +#define USB_EP_COUNT 8 + +/* + * Do not enable the common EC command gpioset for recasting of GPIO + * type. Instead, board specific commands are used for implementing + * the OpenTitan tool requirements. + */ +#undef CONFIG_CMD_GPIO_EXTENDED +#define CONFIG_GPIO_GET_EXTENDED + +/* Enable control of SPI over USB */ +#define CONFIG_USB_SPI +#define CONFIG_USB_SPI_BUFFER_SIZE 2048 +#define CONFIG_USB_SPI_FLASH_EXTENSIONS +#define CONFIG_SPI_CONTROLLER +#define CONFIG_STM32_SPI1_CONTROLLER +#define CONFIG_SPI_MUTABLE_DEVICE_LIST + +/* Enable control of I2C over USB */ +#define CONFIG_USB_I2C +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER + +/* See i2c_ite_flash_support.c for more information about these values */ +/*#define CONFIG_ITE_FLASH_SUPPORT */ +/*#define CONFIG_I2C_XFER_LARGE_TRANSFER */ +#undef CONFIG_USB_I2C_MAX_WRITE_COUNT +#undef CONFIG_USB_I2C_MAX_READ_COUNT +#define CONFIG_USB_I2C_MAX_WRITE_COUNT ((1 << 9) - 4) +#define CONFIG_USB_I2C_MAX_READ_COUNT ((1 << 9) - 6) + +#endif /* SECTION_IS_RO */ + +/* This is not actually an EC so disable some features. */ +#undef CONFIG_WATCHDOG_HELP +#undef CONFIG_LID_SWITCH +#undef CONFIG_FLASH_PSTATE + +/* + * Allow dangerous commands all the time, since we don't have a write protect + * switch. + */ +#define CONFIG_SYSTEM_UNLOCKED + +#ifndef __ASSEMBLER__ + +/* Timer selection */ +#define TIM_CLOCK32 2 + +#include "gpio_signal.h" + +/* USB string indexes */ +enum usb_strings { + USB_STR_DESC = 0, + USB_STR_VENDOR, + USB_STR_PRODUCT, + USB_STR_SERIALNO, + USB_STR_VERSION, + USB_STR_CONSOLE_NAME, + USB_STR_SPI_NAME, + USB_STR_I2C_NAME, + USB_STR_USART2_STREAM_NAME, + USB_STR_USART3_STREAM_NAME, + USB_STR_USART4_STREAM_NAME, + USB_STR_USART5_STREAM_NAME, + USB_STR_DFU_NAME, + + USB_STR_COUNT +}; + +/* ADC signal */ +enum adc_channel { + ADC_CN9_11, /* ADC12_IN1 */ + ADC_CN9_9, /* ADC12_IN2 */ + /* ADC_CN10_9, */ /* ADC12_IN3, Nucleo USB VBUS sense */ + ADC_CN9_5, /* ADC12_IN4 */ + ADC_CN10_29, /* ADC12_IN5 */ + ADC_CN10_11, /* ADC12_IN6 */ + ADC_CN9_3, /* ADC12_IN7 */ + ADC_CN9_1, /* ADC12_IN8 */ + ADC_CN7_9, /* ADC12_IN9 */ + ADC_CN7_10, /* ADC12_IN10 */ + ADC_CN7_12, /* ADC12_IN11 */ + ADC_CN7_14, /* ADC12_IN12 */ + /* PC4, not on connectors */ /* ADC12_IN13 */ + /* PC5, not on connectors */ /* ADC12_IN14 */ + ADC_CN9_7, /* ADC12_IN15 */ + ADC_CN10_7, /* ADC12_IN16 */ + /* Number of ADC channels */ + ADC_CH_COUNT +}; + +/* Timeout for initializing the OctoSPI controller. */ +#define OCTOSPI_INIT_TIMEOUT_US (100 * MSEC) + +/* + * Timeout for a complete SPI transaction. Users can potentially set the clock + * down to 62.5 kHz and transfer up to 2048 bytes, which would take 262ms + * assuming no FIFO stalls. + */ +#define OCTOSPI_TRANSACTION_TIMEOUT_US (500 * MSEC) + +/* Interrupt handler, called by common/gpio.c. */ +void gpio_edge(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/hyperdebug/build.mk b/board/hyperdebug/build.mk new file mode 100644 index 0000000000..2d8291043c --- /dev/null +++ b/board/hyperdebug/build.mk @@ -0,0 +1,16 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build + +# the IC is STmicro STM32F302R8 +CHIP:=stm32 +CHIP_FAMILY:=stm32l5 +CHIP_VARIANT:=stm32l552xe + +# These files are compiled into RO +chip-ro=bkpdata.o system.o + +board-rw=board.o gpio.o spi.o i2c.o diff --git a/board/hyperdebug/ec.tasklist b/board/hyperdebug/ec.tasklist new file mode 100644 index 0000000000..731007e9fe --- /dev/null +++ b/board/hyperdebug/ec.tasklist @@ -0,0 +1,11 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS_RW(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) diff --git a/board/hyperdebug/gpio.c b/board/hyperdebug/gpio.c new file mode 100644 index 0000000000..dbffa7fefb --- /dev/null +++ b/board/hyperdebug/gpio.c @@ -0,0 +1,972 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* HyperDebug GPIO logic and console commands */ + +#include "atomic.h" +#include "builtin/assert.h" +#include "common.h" +#include "console.h" +#include "cpu.h" +#include "gpio.h" +#include "hooks.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +struct dac_t { + uint32_t enable_mask; + volatile uint32_t *data_register; +}; + +/* Sparse array of DAC capabilities for GPIO pins. */ +const struct dac_t dac_channels[GPIO_COUNT] = { + [GPIO_CN7_9] = { STM32_DAC_CR_EN1, &STM32_DAC_DHR12R1 }, + [GPIO_CN7_10] = { STM32_DAC_CR_EN2, &STM32_DAC_DHR12R2 }, +}; + +/* + * GPIO structure for keeping extra flags such as GPIO_OPEN_DRAIN, to be applied + * whenever the pin is switched into "alternate" mode. + */ +struct gpio_alt_flags { + /* Port base address */ + uint32_t port; + + /* Bitmask on that port (multiple bits allowed) */ + uint32_t mask; + + /* Flags (GPIO_*; see above). */ + uint32_t flags; +}; + +/* + * Construct the gpio_alt_flags array, this really is just a subset of the + * columns in the gpio_alt_funcs array in common/gpio.c (which is not accessible + * from here). This array is used by extra_alternate_flags(). + */ +#define ALTERNATE(pinmask, function, module, flagz) \ + { GPIO_##pinmask, .flags = (flagz) }, + +static __const_data const struct gpio_alt_flags gpio_alt_flags[] = { +#include "gpio.wrap" +}; +#undef ALTERNATE + +/* + * A cyclic buffer is used to record events (edges) of one or more GPIO + * signals. Each event records the time since the previous event, and the + * signal that changed (the direction of change is not explicitly recorded). + * + * So conceptually the buffer entries are pairs of (diff: u64, signal_no: u8). + * These entries are encoded as bytes in the following way: First the timestamp + * diff is shifted left by signal_bits, and the signal_no value put into the + * lower bits freed up this way. Now we have a single u64, which often will be + * a small value (or at least, when the edges happen rapidly, and the need to + * store many of them the highest, then the u64 will be a small value). This + * u64 is then stored 7 bits at a time in successive bytes, with the most + * significant bit indicating whether more bytes belong to the same entry. + * + * The chain of relative timestamps are resolved by keeping two absolute + * timestamps: head_time is the time of the most recently inserted event, and is + * accessed and updated only by the interrupt handler. tail_time is the past + * timestamp on which the diff of the oldest record in the buffer is based (the + * timestamp of the last record to be removed from the buffer), it is accessed + * and updated only from the non-interrupt code that removes records from the + * buffer. + * + * In a similar fashion, the signal level is recorded "at both ends" in for each + * monitored signal by head_level and tail_level, the former only accessed from + * the interrupt handler, and the latter only accessed from non-interrupt code. + */ +struct cyclic_buffer_header_t { + /* Number of signals being monitored in this buffer. */ + uint8_t num_signals; + /* The number of bits required to represent 0..num_signals-1. */ + uint8_t signal_bits; + /* Sticky bit recording if overflow occurred. */ + volatile uint8_t overflow; + /* Time of the most recent event, updated from interrupt context. */ + volatile timestamp_t head_time; + /* Time base that the oldest event is relative to. */ + timestamp_t tail_time; + /* Index at which new records are placed, updated from interrupt. */ + volatile uint32_t head; + /* Index af oldest record. */ + uint32_t tail; + /* + * Size of cyclic byte buffer, determined at runtime, not necessarily + * power of two. Head and tail wrap to zero here. + */ + uint32_t size; + /* Data contents */ + uint8_t data[]; +}; + +/* + * The STM32L5 has 16 edge detection circuits. Each pin can only be used with + * one of them. That is, detector 0 can take its input from one of pins A0, + * B0, C0, ..., while detector 1 can choose between A1, B1, etc. + * + * Information about the current use of each detection circuit is stored in 16 + * "slots" below. + */ +struct monitoring_slot_t { + /* Link to buffer recording edges of this signal. */ + struct cyclic_buffer_header_t *buffer; + /* EC enum id of the signal used by this detection slot. */ + int gpio_signal; + /* The index of the signal as used in the recording buffer. */ + uint8_t signal_no; + /* Most recently recorded level of the signal. */ + volatile uint8_t head_level; + /* Level as of the current oldest end (tail) of the recording. */ + uint8_t tail_level; +}; +struct monitoring_slot_t monitoring_slots[16]; + +/* + * Memory area used for allocation of cyclic buffers. (Currently the + * implementation supports only a single allocation.) + */ +uint8_t buffer_area[sizeof(struct cyclic_buffer_header_t) + 8192]; +bool buffer_area_in_use = false; + +static struct cyclic_buffer_header_t *allocate_cyclic_buffer(size_t size) +{ + struct cyclic_buffer_header_t *res = + (struct cyclic_buffer_header_t *)buffer_area; + if (buffer_area_in_use) { + /* No support for multiple smaller allocations, yet. */ + return 0; + } + if (sizeof(struct cyclic_buffer_header_t) + size > + sizeof(buffer_area)) { + /* Requested size exceeds the capacity of the area. */ + return 0; + } + buffer_area_in_use = true; + res->size = size; + return res; +} + +static void free_cyclic_buffer(struct cyclic_buffer_header_t *buf) +{ + buffer_area_in_use = false; +} + +/* + * Counts unacknowledged buffer overflows. Whenever non-zero, the red LED + * will flash. + */ +atomic_t num_cur_error_conditions; + +/* + * Counts the number of cyclic buffers currently in existence, the green LED + * will flash whenever this is non-zero, indicating the monitoring activity. + */ +int num_cur_monitoring = 0; + +static __attribute__((noinline)) void overflow(struct monitoring_slot_t *slot) +{ + struct cyclic_buffer_header_t *buffer_header = slot->buffer; + gpio_disable_interrupt(slot->gpio_signal); + buffer_header->overflow = 1; + atomic_add(&num_cur_error_conditions, 1); +} + +void gpio_edge(enum gpio_signal signal) +{ + /* + * Hardware has detected one or more edges since last time. We + * process by looking at the current level of the signal. If opposite + * the most recent level, we record one edge, if the same as most + * recent level, we record two edges, that is, a zero-width pulse. + * This is useful for tests trying to verify e.g. that there are no + * glitches on a particular signal, and want to know about any pulses, + * however narrow. + */ + timestamp_t now = get_time(); + int gpio_num = GPIO_MASK_TO_NUM(gpio_list[signal].mask); + struct monitoring_slot_t *slot = monitoring_slots + gpio_num; + int current_level = gpio_get_level(signal); + struct cyclic_buffer_header_t *buffer_header = slot->buffer; + uint8_t *buffer_data = buffer_header->data; + uint32_t tail = buffer_header->tail, head = buffer_header->head, + size = buffer_header->size; + uint64_t diff = now.val - buffer_header->head_time.val; + + uint8_t signal_bits = buffer_header->signal_bits; + + /* + * Race condition here! If three or more edges happen in + * rapid succession, we may fail to record some of them, but + * we should never over-report edges. + * + * Since the edge interrupts pending bit has been cleared before the + * "current_level" was polled, if an edge happened between the two, then + * an interrupt is currently pending, and when handled after this method + * returns, the logic below would wrongly conclude that the signal must + * have seen two transitions, in order to end up at the same level as + * before. In order to avoid such over-reporting, we clear "pending" + * interrupt bit below, but only for the direction that goes "towards" + * the level measured above. + */ + if (current_level) + STM32_EXTI_RPR = BIT(gpio_num); + else + STM32_EXTI_FPR = BIT(gpio_num); + + /* + * Insert an entry recording the time since last event, and which + * signal changed (the direction of the edge is not explicitly + * recorded, as it can be inferred from the initial level). + * + * The time difference and pin index are encoded in `diff`, which will + * be a small integer if the event arrive rapidly. 7 bits of this + * integer is then put into one byte at a time, using the high bit of + * each byte to indicate if more are to come. This encoding will use + * only one byte per event, in the best case, allowing tens of + * thousands of events to be buffered. + */ + diff <<= signal_bits; + diff |= slot->signal_no; + do { + buffer_data[head++] = ((diff >= 0x80) ? 0x80 : 0x00) | + (diff & 0x7F); + diff >>= 7; + if (head == size) + head = 0; + if (head == tail) { + /* + * The new head will not be persisted, maintaining the + * invatiant that head and tail are equal only when the + * buffer is empty. + */ + return overflow(slot); + } + } while (diff); + + /* + * If current level equals the previous level, then record an + * additional edge 0ms after the previous. + */ + if (!!current_level == !!slot->head_level) { + /* + * Add a record with zero diff, and the same signal no. (Will + * always fit in one byte, as signal_no never uses more than 7 + * bits.) + */ + buffer_data[head++] = slot->signal_no; + if (head == size) + head = 0; + if (head == tail) { + /* + * The new head will not be persisted, maintaining the + * invatiant that head and tail are equal only when the + * buffer is empty. + */ + return overflow(slot); + } + } else { + slot->head_level = current_level; + } + buffer_header->head = head; + buffer_header->head_time = now; +} + +static void board_gpio_init(void) +{ + /* Mark every slot as unused. */ + for (int i = 0; i < ARRAY_SIZE(monitoring_slots); i++) + monitoring_slots[i].gpio_signal = GPIO_COUNT; +} +DECLARE_HOOK(HOOK_INIT, board_gpio_init, HOOK_PRIO_DEFAULT); + +static void stop_all_gpio_monitoring(void) +{ + struct monitoring_slot_t *slot; + struct cyclic_buffer_header_t *buffer_header; + for (int i = 0; i < ARRAY_SIZE(monitoring_slots); i++) { + slot = monitoring_slots + i; + if (!slot->buffer) + continue; + + /* Disable interrupts for all signals feeding into the same + * cyclic buffer. */ + buffer_header = slot->buffer; + for (int j = i; j < ARRAY_SIZE(monitoring_slots); j++) { + slot = monitoring_slots + i; + if (slot->buffer != buffer_header) + continue; + gpio_disable_interrupt(slot->gpio_signal); + slot->gpio_signal = GPIO_COUNT; + } + /* Deallocate this one cyclic buffer. */ + num_cur_monitoring--; + if (buffer_header->overflow) + atomic_sub(&num_cur_error_conditions, 1); + free_cyclic_buffer(buffer_header); + } +} + +/* + * Return GPIO_OPEN_DRAIN or any other special flags to apply when the given + * signal is in "alternate" mode. + */ +static uint32_t extra_alternate_flags(enum gpio_signal signal) +{ + const struct gpio_info *g = gpio_list + signal; + const struct gpio_alt_flags *af; + + /* Find the first ALTERNATE() declaration for the given pin. */ + for (af = gpio_alt_flags; + af < gpio_alt_flags + ARRAY_SIZE(gpio_alt_flags); af++) { + if (af->port != g->port) + continue; + + if (af->mask & g->mask) { + return af->flags; + } + } + + /* No ALTERNATE() declaration mention the given pin. */ + return 0; +} + +/** + * Find a GPIO signal by name. + * + * This is copied from gpio.c unfortunately, as it is static over there. + * + * @param name Signal name to find + * + * @return the signal index, or GPIO_COUNT if no match. + */ +static enum gpio_signal find_signal_by_name(const char *name) +{ + int i; + + if (!name || !*name) + return GPIO_COUNT; + + for (i = 0; i < GPIO_COUNT; i++) + if (gpio_is_implemented(i) && + !strcasecmp(name, gpio_get_name(i))) + return i; + + return GPIO_COUNT; +} + +/* + * Set the mode of a GPIO pin: input/opendrain/pushpull/alternate. + */ +static int command_gpio_mode(int argc, const char **argv) +{ + int gpio; + int flags; + uint32_t dac_enable_value = STM32_DAC_CR; + + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + + gpio = find_signal_by_name(argv[1]); + if (gpio == GPIO_COUNT) + return EC_ERROR_PARAM1; + flags = gpio_get_flags(gpio); + + flags &= ~(GPIO_INPUT | GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_ANALOG); + dac_enable_value &= ~dac_channels[gpio].enable_mask; + if (strcasecmp(argv[2], "input") == 0) + flags |= GPIO_INPUT; + else if (strcasecmp(argv[2], "opendrain") == 0) + flags |= GPIO_OUTPUT | GPIO_OPEN_DRAIN; + else if (strcasecmp(argv[2], "pushpull") == 0) + flags |= GPIO_OUTPUT; + else if (strcasecmp(argv[2], "adc") == 0) + flags |= GPIO_ANALOG; + else if (strcasecmp(argv[2], "dac") == 0) { + if (dac_channels[gpio].enable_mask == 0) { + ccprintf("Error: Pin does not support dac\n"); + return EC_ERROR_PARAM2; + } + dac_enable_value |= dac_channels[gpio].enable_mask; + /* Disable digital output, when DAC is overriding. */ + flags |= GPIO_INPUT; + } else if (strcasecmp(argv[2], "alternate") == 0) + flags |= GPIO_ALTERNATE | extra_alternate_flags(gpio); + else + return EC_ERROR_PARAM2; + + /* Update GPIO flags. */ + gpio_set_flags(gpio, flags); + STM32_DAC_CR = dac_enable_value; + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND_FLAGS( + gpiomode, command_gpio_mode, + "name ", + "Set a GPIO mode", CMD_FLAG_RESTRICTED); + +/* + * Set the weak pulling of a GPIO pin: up/down/none. + */ +static int command_gpio_pull_mode(int argc, const char **argv) +{ + int gpio; + int flags; + + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + + gpio = find_signal_by_name(argv[1]); + if (gpio == GPIO_COUNT) + return EC_ERROR_PARAM1; + flags = gpio_get_flags(gpio); + + flags = flags & ~(GPIO_PULL_UP | GPIO_PULL_DOWN); + if (strcasecmp(argv[2], "none") == 0) + ; + else if (strcasecmp(argv[2], "up") == 0) + flags |= GPIO_PULL_UP; + else if (strcasecmp(argv[2], "down") == 0) + flags |= GPIO_PULL_DOWN; + else + return EC_ERROR_PARAM2; + + /* Update GPIO flags. */ + gpio_set_flags(gpio, flags); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND_FLAGS(gpiopullmode, command_gpio_pull_mode, + "name ", + "Set a GPIO weak pull mode", CMD_FLAG_RESTRICTED); + +static int set_dac(int gpio, const char *value) +{ + int milli_volts; + char *e; + if (dac_channels[gpio].enable_mask == 0) { + ccprintf("Error: Pin does not support dac\n"); + return EC_ERROR_PARAM6; + } + + milli_volts = strtoi(value, &e, 0); + if (*e) + return EC_ERROR_PARAM6; + + if (milli_volts <= 0) + *dac_channels[gpio].data_register = 0; + else if (milli_volts >= 3300) + *dac_channels[gpio].data_register = 4095; + else + *dac_channels[gpio].data_register = milli_volts * 4096 / 3300; + + return EC_SUCCESS; +} + +/* + * Set the value in millivolts for driving the DAC of a given pin. + */ +static int command_gpio_analog_set(int argc, const char **argv) +{ + int gpio; + + if (argc < 4) + return EC_ERROR_PARAM_COUNT; + + gpio = find_signal_by_name(argv[2]); + if (gpio == GPIO_COUNT) + return EC_ERROR_PARAM2; + + if (set_dac(gpio, argv[3]) != EC_SUCCESS) + return EC_ERROR_PARAM3; + return EC_SUCCESS; +} + +/* + * Set multiple aspects of a GPIO pin simultaneously, that is, can switch output + * level, opendrain/pushpull, and pullup simultaneously, eliminating the risk of + * glitches. + */ +static int command_gpio_multiset(int argc, const char **argv) +{ + int gpio; + int flags; + uint32_t dac_enable_value = STM32_DAC_CR; + + if (argc < 4) + return EC_ERROR_PARAM_COUNT; + + gpio = find_signal_by_name(argv[2]); + if (gpio == GPIO_COUNT) + return EC_ERROR_PARAM2; + flags = gpio_get_flags(gpio); + + if (argc > 3 && strcasecmp(argv[3], "-") != 0) { + flags = flags & ~(GPIO_LOW | GPIO_HIGH); + if (strcasecmp(argv[3], "0") == 0) + flags |= GPIO_LOW; + else if (strcasecmp(argv[3], "1") == 0) + flags |= GPIO_HIGH; + else + return EC_ERROR_PARAM3; + } + + if (argc > 4 && strcasecmp(argv[4], "-") != 0) { + flags &= ~(GPIO_INPUT | GPIO_OUTPUT | GPIO_OPEN_DRAIN | + GPIO_ANALOG); + dac_enable_value &= ~dac_channels[gpio].enable_mask; + if (strcasecmp(argv[4], "input") == 0) + flags |= GPIO_INPUT; + else if (strcasecmp(argv[4], "opendrain") == 0) + flags |= GPIO_OUTPUT | GPIO_OPEN_DRAIN; + else if (strcasecmp(argv[4], "pushpull") == 0) + flags |= GPIO_OUTPUT; + else if (strcasecmp(argv[4], "adc") == 0) + flags |= GPIO_ANALOG; + else if (strcasecmp(argv[4], "dac") == 0) { + if (dac_channels[gpio].enable_mask == 0) { + ccprintf("Error: Pin does not support dac\n"); + return EC_ERROR_PARAM2; + } + dac_enable_value |= dac_channels[gpio].enable_mask; + /* Disable digital output, when DAC is overriding. */ + flags |= GPIO_INPUT; + } else if (strcasecmp(argv[4], "alternate") == 0) + flags |= GPIO_ALTERNATE | extra_alternate_flags(gpio); + else + return EC_ERROR_PARAM4; + } + + if (argc > 5 && strcasecmp(argv[5], "-") != 0) { + flags = flags & ~(GPIO_PULL_UP | GPIO_PULL_DOWN); + if (strcasecmp(argv[5], "none") == 0) + ; + else if (strcasecmp(argv[5], "up") == 0) + flags |= GPIO_PULL_UP; + else if (strcasecmp(argv[5], "down") == 0) + flags |= GPIO_PULL_DOWN; + else + return EC_ERROR_PARAM5; + } + + if (argc > 6 && strcasecmp(argv[6], "-") != 0) { + if (set_dac(gpio, argv[6]) != EC_SUCCESS) + return EC_ERROR_PARAM6; + } + + /* Update GPIO flags. */ + gpio_set_flags(gpio, flags); + STM32_DAC_CR = dac_enable_value; + return EC_SUCCESS; +} + +static int command_gpio_monitoring_start(int argc, const char **argv) +{ + BUILD_ASSERT(STM32_IRQ_EXTI15 < 32); + int gpios[16]; + int gpio_num = argc - 3; + int i; + timestamp_t now; + int rv; + uint32_t nvic_mask; + size_t cyclic_buffer_size = 8192; /* Maybe configurable by parameter */ + struct cyclic_buffer_header_t *buf; + struct monitoring_slot_t *slot; + + if (gpio_num <= 0 || gpio_num > 16) + return EC_ERROR_PARAM_COUNT; + + for (i = 0; i < gpio_num; i++) { + gpios[i] = find_signal_by_name(argv[3 + i]); + if (gpios[i] == GPIO_COUNT) { + rv = EC_ERROR_PARAM3 + i; + goto out_partial_cleanup; + } + slot = monitoring_slots + + GPIO_MASK_TO_NUM(gpio_list[gpios[i]].mask); + if (slot->gpio_signal != GPIO_COUNT) { + ccprintf("Error: Monitoring of %s conflicts with %s\n", + argv[3 + i], + gpio_list[slot->gpio_signal].name); + rv = EC_ERROR_PARAM3 + i; + goto out_partial_cleanup; + } + slot->gpio_signal = gpios[i]; + } + + /* + * All the requested signals were available for monitoring, and their + * slots have been marked as reserved for the respective signal. + */ + buf = allocate_cyclic_buffer(cyclic_buffer_size); + if (!buf) { + rv = EC_ERROR_BUSY; + goto out_cleanup; + } + + buf->head = buf->tail = 0; + buf->overflow = 0; + buf->num_signals = gpio_num; + buf->signal_bits = 0; + /* Compute how many bits are required to represent 0..gpio_num-1. */ + while ((gpio_num - 1) >> buf->signal_bits) + buf->signal_bits++; + + for (i = 0; i < gpio_num; i++) { + slot = monitoring_slots + + GPIO_MASK_TO_NUM(gpio_list[gpios[i]].mask); + slot->buffer = buf; + slot->signal_no = i; + } + + /* + * The code relies on all EXTIn interrupts belonging to the same 32-bit + * NVIC register, so that multiple interrupts can be "unleashed" + * simultaneously. + */ + nvic_mask = 0; + + /* + * Disable interrupts in GPIO/EXTI detection circuits (should be + * disabled already, but disabled and clear pending bit to be on the + * safe side). + */ + for (i = 0; i < gpio_num; i++) { + int gpio_num = GPIO_MASK_TO_NUM(gpio_list[gpios[i]].mask); + gpio_disable_interrupt(gpios[i]); + gpio_clear_pending_interrupt(gpios[i]); + nvic_mask |= BIT(STM32_IRQ_EXTI0 + gpio_num); + } + /* Also disable interrupts at NVIC (interrupt controller) level. */ + CPU_NVIC_UNPEND(0) = nvic_mask; + CPU_NVIC_DIS(0) = nvic_mask; + + for (i = 0; i < gpio_num; i++) { + int gpio_num = GPIO_MASK_TO_NUM(gpio_list[gpios[i]].mask); + slot = monitoring_slots + gpio_num; + /* + * Tell the GPIO block to start detecting rising and falling + * edges, and latch them in STM32_EXTI_RPR and STM32_EXTI_FPR + * respectively. Interrupts are still disabled in the NVIC, + * meaning that the execution will not be interrupted, yet, even + * if the GPIO block requests interrupt. + */ + gpio_enable_interrupt(gpios[i]); + slot->tail_level = slot->head_level = gpio_get_level(gpios[i]); + /* + * Race condition here! If three or more edges happen in + * rapid succession, we may fail to record some of them, but + * we should never over-report edges. + * + * Since edge detection was enabled before the "head_level" + * was polled, if an edge happened between the two, then an + * interrupt is currently pending, and when handled after this + * loop, the logic in the gpio_edge interrupt handler would + * wrongly conclude that the signal must have seen two + * transitions, in order to end up at the same level as before. + * In order to avoid such over-reporting, we clear "pending" + * interrupt bit below, but only for the direction that goes + * "towards" the level measured above. + */ + if (slot->head_level) + STM32_EXTI_RPR = BIT(gpio_num); + else + STM32_EXTI_FPR = BIT(gpio_num); + } + /* + * Now enable the handling of the set of interrupts. + */ + now = get_time(); + buf->head_time = now; + CPU_NVIC_EN(0) = nvic_mask; + + buf->tail_time = now; + num_cur_monitoring++; + ccprintf(" @%lld\n", buf->tail_time.val); + + /* + * Dump the initial level of each input, for the convenience of the + * caller. (Allow makes monitoring useful, even if a signal has no + * transitions during the monitoring period. + */ + for (i = 0; i < gpio_num; i++) { + slot = monitoring_slots + + GPIO_MASK_TO_NUM(gpio_list[gpios[i]].mask); + ccprintf(" %d %s %d\n", i, gpio_list[gpios[i]].name, + slot->tail_level); + } + + return EC_SUCCESS; + +out_cleanup: + i = gpio_num; +out_partial_cleanup: + while (i-- > 0) { + monitoring_slots[GPIO_MASK_TO_NUM(gpio_list[gpios[i]].mask)] + .gpio_signal = GPIO_COUNT; + } + return rv; +} + +static int command_gpio_monitoring_read(int argc, const char **argv) +{ + int gpios[16]; + int gpio_num = argc - 3; + int i; + struct cyclic_buffer_header_t *buf = NULL; + struct monitoring_slot_t *slot; + int gpio_signals_by_no[16]; + uint8_t signal_bits; + uint32_t tail, head; + timestamp_t tail_time, now; + + if (gpio_num <= 0 || gpio_num > 16) + return EC_ERROR_PARAM_COUNT; + + for (i = 0; i < gpio_num; i++) { + gpios[i] = find_signal_by_name(argv[3 + i]); + if (gpios[i] == GPIO_COUNT) + return EC_ERROR_PARAM3 + i; /* May overflow */ + slot = monitoring_slots + + GPIO_MASK_TO_NUM(gpio_list[gpios[i]].mask); + if (slot->gpio_signal != gpios[i]) { + ccprintf("Error: Not monitoring %s\n", + gpio_list[gpios[i]].name); + return EC_ERROR_PARAM3 + i; + } + if (slot->signal_no != i) { + ccprintf("Error: Inconsistent order at %s\n", + gpio_list[gpios[i]].name); + return EC_ERROR_PARAM3 + i; + } + if (buf == NULL) { + buf = slot->buffer; + } else if (buf != slot->buffer) { + ccprintf( + "Error: Not monitoring %s as part of same groups as %s\n", + gpio_list[gpios[i]].name, + gpio_list[gpios[0]].name); + return EC_ERROR_PARAM3 + i; + } + gpio_signals_by_no[slot->signal_no] = gpios[i]; + } + if (gpio_num != buf->num_signals) { + ccprintf("Error: Not full set of signals monitored\n"); + return EC_ERROR_INVAL; + } + + /* + * We read current time, before taking a snapshot of the head pointer as + * set by the interrupt handler. This way, we can guarantee that the + * transcript will include any edge happening at or before the `now` + * timestamp. If an interrupt happens between the two lines below, + * causing our head pointer to include an event that happened after + * "now", then it will be skipped in the loop below, and kept for the + * next invocation of `gpio monitoring read`. + */ + now = get_time(); + head = buf->head; + + ccprintf(" @%lld\n", now.val); + signal_bits = buf->signal_bits; + tail = buf->tail; + tail_time = buf->tail_time; + while (tail != head) { + uint8_t *buffer = buf->data; + timestamp_t diff; + uint8_t byte; + uint8_t signal_no; + int shift = 0; + uint32_t tentative_tail = tail; + struct monitoring_slot_t *slot; + diff.val = 0; + do { + byte = buffer[tentative_tail++]; + if (tentative_tail == buf->size) + tentative_tail = 0; + diff.val |= (byte & 0x7F) << shift; + shift += 7; + } while (byte & 0x80); + signal_no = diff.val & (0xFF >> (8 - signal_bits)); + diff.val >>= signal_bits; + if (tail_time.val + diff.val > now.val) { + /* + * Do not consume this or subsequent records, which + * apparently happened after our "now" timestamp from + * earlier in the execution of this method. + */ + break; + } + tail = tentative_tail; + tail_time.val += diff.val; + slot = monitoring_slots + + GPIO_MASK_TO_NUM( + gpio_list[gpio_signals_by_no[signal_no]].mask); + /* To conserve bandwidth, timestamps are relative to `now`. */ + ccprintf(" %d %lld %s\n", signal_no, tail_time.val - now.val, + slot->tail_level ? "F" : "R"); + /* Flush console to avoid truncating output */ + cflush(); + slot->tail_level = !slot->tail_level; + } + buf->tail = tail; + buf->tail_time = tail_time; + if (buf->overflow) { + ccprintf("Error: Buffer overflow\n"); + } + + return EC_SUCCESS; +} + +static int command_gpio_monitoring_stop(int argc, const char **argv) +{ + int gpios[16]; + int gpio_num = argc - 3; + int i; + struct cyclic_buffer_header_t *buf = NULL; + struct monitoring_slot_t *slot; + + if (gpio_num <= 0 || gpio_num > 16) + return EC_ERROR_PARAM_COUNT; + + for (i = 0; i < gpio_num; i++) { + gpios[i] = find_signal_by_name(argv[3 + i]); + if (gpios[i] == GPIO_COUNT) + return EC_ERROR_PARAM3 + i; /* May overflow */ + slot = monitoring_slots + + GPIO_MASK_TO_NUM(gpio_list[gpios[i]].mask); + if (slot->gpio_signal != gpios[i]) { + ccprintf("Error: Not monitoring %s\n", + gpio_list[gpios[i]].name); + return EC_ERROR_PARAM3 + i; + } + if (buf == NULL) { + buf = slot->buffer; + } else if (buf != slot->buffer) { + ccprintf( + "Error: Not monitoring %s as part of same groups as %s\n", + gpio_list[gpios[i]].name, + gpio_list[gpios[0]].name); + return EC_ERROR_PARAM3 + i; + } + } + if (gpio_num != buf->num_signals) { + ccprintf("Error: Not full set of signals monitored\n"); + return EC_ERROR_INVAL; + } + + for (i = 0; i < gpio_num; i++) { + gpio_disable_interrupt(gpios[i]); + } + + /* + * With no more interrupts modifying the buffer, it can be deallocated. + */ + num_cur_monitoring--; + for (i = 0; i < gpio_num; i++) { + slot = monitoring_slots + + GPIO_MASK_TO_NUM(gpio_list[gpios[i]].mask); + slot->gpio_signal = GPIO_COUNT; + slot->buffer = NULL; + } + + if (buf->overflow) + atomic_sub(&num_cur_error_conditions, 1); + + free_cyclic_buffer(buf); + return EC_SUCCESS; +} + +static int command_gpio_monitoring(int argc, const char **argv) +{ + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + if (!strcasecmp(argv[2], "start")) + return command_gpio_monitoring_start(argc, argv); + if (!strcasecmp(argv[2], "read")) + return command_gpio_monitoring_read(argc, argv); + if (!strcasecmp(argv[2], "stop")) + return command_gpio_monitoring_stop(argc, argv); + return EC_ERROR_PARAM2; +} + +static int command_gpio(int argc, const char **argv) +{ + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + if (!strcasecmp(argv[1], "analog-set")) + return command_gpio_analog_set(argc, argv); + if (!strcasecmp(argv[1], "monitoring")) + return command_gpio_monitoring(argc, argv); + if (!strcasecmp(argv[1], "multiset")) + return command_gpio_multiset(argc, argv); + return EC_ERROR_PARAM1; +} +DECLARE_CONSOLE_COMMAND_FLAGS( + gpio, command_gpio, + "multiset name [level] [mode] [pullmode] [milli_volts]" + "\nanalog-set name milli_volts" + "\nmonitoring start name..." + "\nmonitoring read name..." + "\nmonitoring stop name...", + "GPIO manipulation", CMD_FLAG_RESTRICTED); + +static int command_reinit(int argc, const char **argv) +{ + const struct gpio_info *g = gpio_list; + int i; + + stop_all_gpio_monitoring(); + + /* Set all GPIOs to defaults */ + for (i = 0; i < GPIO_COUNT; i++, g++) { + int flags = g->flags; + + if (flags & GPIO_DEFAULT) + continue; + + if (flags & GPIO_ALTERNATE) + flags |= extra_alternate_flags(i); + + /* Set up GPIO based on flags */ + gpio_set_flags_by_mask(g->port, g->mask, flags); + } + + /* Disable any DAC (which would override GPIO function of pins) */ + STM32_DAC_CR = 0; + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND_FLAGS(reinit, command_reinit, "", + "Stop any ongoing operation", + CMD_FLAG_RESTRICTED); + +static void led_tick(void) +{ + /* Indicate ongoing GPIO monitoring by flashing the green LED. */ + if (num_cur_monitoring) + gpio_set_level(GPIO_NUCLEO_LED1, + !gpio_get_level(GPIO_NUCLEO_LED1)); + else { + /* + * If not flashing, leave the green LED on, to indicate that + * HyperDebug firmware is running and ready. + */ + gpio_set_level(GPIO_NUCLEO_LED1, 1); + } + /* Indicate error conditions by flashing red LED. */ + if (atomic_add(&num_cur_error_conditions, 0)) + gpio_set_level(GPIO_NUCLEO_LED3, + !gpio_get_level(GPIO_NUCLEO_LED3)); + else { + /* + * If not flashing, leave the red LED off. + */ + gpio_set_level(GPIO_NUCLEO_LED3, 0); + } +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/hyperdebug/gpio.inc b/board/hyperdebug/gpio.inc new file mode 100644 index 0000000000..f02c55b793 --- /dev/null +++ b/board/hyperdebug/gpio.inc @@ -0,0 +1,161 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * List of all GPIO pins available for Host computer to manipulate. + * The are named based on their location on the two 70-pin DIL + * connectors on either side of the HyperDebug board. Pins with + * special functions are commented out, and declared with relevant + * symbolic name further below. + */ + +/* + * The common define GPIO_INT_BOTH includes GPIO_INPUT, which interferes with + * GPIO_ALTERNATE. Instead we want to declare the intent to detect either + * rising or falling edges, making it conditional on the pins possibly later + * being re-configured as GPIO inputs. + */ +#define ANY_EDGE (GPIO_INT_F_RISING | GPIO_INT_F_FALLING) + +GPIO_INT(CN7_1, PIN(C, 6), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN7_2, PIN(B, 8), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* I2C1 SCL */ +GPIO_INT(CN7_3, PIN(D, 11), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN7_4, PIN(B, 9), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* I2C1 SDA */ +GPIO_INT(CN7_5, PIN(B, 13), GPIO_INPUT | ANY_EDGE, gpio_edge) +/* CN7_6 is VREFP */ +GPIO_INT(CN7_7, PIN(D, 12), GPIO_INPUT | ANY_EDGE, gpio_edge) +/* CN7_8 is GND */ +GPIO_INT(CN7_9, PIN(A, 4), GPIO_INPUT | ANY_EDGE, gpio_edge) /* DAC0, ADC12_IN9 */ +GPIO_INT(CN7_10, PIN(A, 5), GPIO_INPUT | ANY_EDGE, gpio_edge) /* DAC1, ADC12_IN10 */ +GPIO_INT(CN7_11, PIN(B, 4), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN7_12, PIN(A, 6), GPIO_INPUT | ANY_EDGE, gpio_edge) /* ADC12_IN11 */ +/*GPIO_INT(CN7_13, PIN(B, 5), GPIO_INPUT | ANY_EDGE, gpio_edge) Nucleo USB-C */ +GPIO_INT(CN7_14, PIN(A, 7), GPIO_INPUT | ANY_EDGE, gpio_edge) /* ADC12_IN12 */ +GPIO_INT(CN7_15, PIN(B, 3), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN7_16, PIN(D, 14), GPIO_INPUT | ANY_EDGE, gpio_edge) +/*GPIO_INT(CN7_17, PIN(A, 4), GPIO_INPUT | ANY_EDGE, gpio_edge)*/ +GPIO_INT(CN7_18, PIN(D, 15), GPIO_INPUT | ANY_EDGE, gpio_edge) +/*GPIO_INT(CN7_19, PIN(B, 4), GPIO_INPUT | ANY_EDGE, gpio_edge)*/ +GPIO_INT(CN7_20, PIN(F, 12), GPIO_INPUT | ANY_EDGE, gpio_edge) + +/* CN8_1 is NC */ +GPIO_INT(CN8_2, PIN(C, 8), GPIO_INPUT | ANY_EDGE, gpio_edge) +/* CN8_3 is IOREF */ +GPIO_INT(CN8_4, PIN(C, 9), GPIO_INPUT | ANY_EDGE, gpio_edge) +/* CN8_5 is NRST */ +GPIO_INT(CN8_6, PIN(C, 10), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* UART4 TX */ +/* CN8_7 is 3V3 */ +GPIO_INT(CN8_8, PIN(C, 11), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* UART4 RX */ +/* CN8_9 is 5V */ +GPIO_INT(CN8_10, PIN(C, 12), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* UART5 TX */ +/* CN8_11 is GND */ +GPIO_INT(CN8_12, PIN(D, 2), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* UART5 RX */ +/* CN8_13 is GND */ +GPIO_INT(CN8_14, PIN(F, 3), GPIO_INPUT | ANY_EDGE, gpio_edge) +/* CN8_15 is VIN */ +GPIO_INT(CN8_16, PIN(F, 5), GPIO_INPUT | ANY_EDGE, gpio_edge) + +GPIO_INT(CN9_1, PIN(A, 3), GPIO_INPUT | ANY_EDGE, gpio_edge) /* ADC12_IN8 */ +GPIO_INT(CN9_2, PIN(D, 7), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_3, PIN(A, 2), GPIO_INPUT | ANY_EDGE, gpio_edge) /* ADC12_IN7 */ +GPIO_INT(CN9_4, PIN(D, 6), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* UART2 RX */ +GPIO_INT(CN9_5, PIN(C, 3), GPIO_INPUT | ANY_EDGE, gpio_edge) /* ADC12_IN4 */ +GPIO_INT(CN9_6, PIN(D, 5), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* UART2 TX */ +GPIO_INT(CN9_7, PIN(B, 0), GPIO_INPUT | ANY_EDGE, gpio_edge) /* ADC12_IN15 */ +GPIO_INT(CN9_8, PIN(D, 4), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* SPI2 CODI */ +GPIO_INT(CN9_9, PIN(C, 1), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* I2C3 SDA, ADC12_IN2 */ +GPIO_INT(CN9_10, PIN(D, 3), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* SPI2 CIDO */ +GPIO_INT(CN9_11, PIN(C, 0), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* I2C3 SCL, ADC12_IN1 */ +/* CN9_12 is GND */ +GPIO_INT(CN9_13, PIN(B, 2), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_14, PIN(E, 2), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_15, PIN(B, 6), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_16, PIN(E, 4), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_17, PIN(F, 2), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_18, PIN(E, 5), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_19, PIN(F, 1), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* I2C2 SCL */ +GPIO_INT(CN9_20, PIN(E, 6), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_21, PIN(F, 0), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* I2C2 SDA */ +GPIO_INT(CN9_22, PIN(E, 3), GPIO_INPUT | ANY_EDGE, gpio_edge) +/* CN9_23 is GND */ +GPIO_INT(CN9_24, PIN(F, 8), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_25, PIN(D, 0), GPIO_OUT_HIGH | ANY_EDGE, gpio_edge) /* SPI2 CS */ +GPIO_INT(CN9_26, PIN(F, 7), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_27, PIN(D, 1), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* SPI2 CLK */ +GPIO_INT(CN9_28, PIN(F, 9), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_29, PIN(G, 0), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN9_30, PIN(G, 1), GPIO_INPUT | ANY_EDGE, gpio_edge) + +/* CN10_1 is AVDD */ +GPIO_INT(CN10_2, PIN(F, 13), GPIO_INPUT | ANY_EDGE, gpio_edge) +/* CN10_3 is AGND */ +GPIO_INT(CN10_4, PIN(E, 9), GPIO_INPUT | ANY_EDGE, gpio_edge) +/* CN10_5 is GND */ +GPIO_INT(CN10_6, PIN(E, 11), GPIO_OUT_HIGH | ANY_EDGE, gpio_edge) /* QSPI CS */ +GPIO_INT(CN10_7, PIN(B, 1), GPIO_INPUT | ANY_EDGE, gpio_edge) /* ADC12_IN16 */ +GPIO_INT(CN10_8, PIN(F, 14), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* I2C4 SCL */ +/*GPIO_INT(CN10_9, PIN(C, 2), GPIO_INPUT | ANY_EDGE, gpio_edge) Nucleo USB VBUS sense, ADC12_IN3 */ +GPIO_INT(CN10_10, PIN(E, 13), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* QSPI D1 */ +GPIO_INT(CN10_11, PIN(A, 1), GPIO_INPUT | ANY_EDGE, gpio_edge) /* ADC12_IN6 */ +GPIO_INT(CN10_12, PIN(F, 15), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* I2C4 SDA */ +/*GPIO_INT(CN10_13, PIN(A, 2), GPIO_INPUT | ANY_EDGE, gpio_edge)*/ +GPIO_INT(CN10_14, PIN(D, 8), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* UART3 TX */ +GPIO_INT(CN10_15, PIN(B, 10), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN10_16, PIN(D, 9), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* UART3 RX */ +/* CN10_17 is GND */ +GPIO_INT(CN10_18, PIN(E, 8), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN10_19, PIN(E, 15), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* QSPI D3 */ +GPIO_INT(CN10_20, PIN(E, 7), GPIO_INPUT | ANY_EDGE, gpio_edge) +/*GPIO_INT(CN10_21, PIN(B, 0), GPIO_INPUT | ANY_EDGE, gpio_edge)*/ +/* CN10_22 is GND */ +GPIO_INT(CN10_23, PIN(E, 12), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* QSPI D0 */ +GPIO_INT(CN10_24, PIN(E, 10), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* QSPI CLK */ +GPIO_INT(CN10_25, PIN(E, 14), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) /* QSPI D2 */ +/*GPIO_INT(CN10_26, PIN(E, 12), GPIO_INPUT | ANY_EDGE, gpio_edge) QSPI */ +/* CN10_27 is GND */ +/*GPIO_INT(CN10_28, PIN(E, 14), GPIO_INPUT | ANY_EDGE, gpio_edge) QSPI */ +GPIO_INT(CN10_29, PIN(A, 0), GPIO_INPUT | ANY_EDGE, gpio_edge) /* ADC12_IN5 */ +/*GPIO_INT(CN10_30, PIN(E, 15), GPIO_INPUT | ANY_EDGE, gpio_edge) QSPI */ +GPIO_INT(CN10_31, PIN(A, 8), GPIO_INPUT | ANY_EDGE, gpio_edge) +/*GPIO_INT(CN10_32, PIN(B, 10), GPIO_INPUT | ANY_EDGE, gpio_edge)*/ +GPIO_INT(CN10_33, PIN(E, 0), GPIO_INPUT | ANY_EDGE, gpio_edge) +GPIO_INT(CN10_34, PIN(B, 11), GPIO_INPUT | ANY_EDGE, gpio_edge) + +/* These pins are used for USART and are set to alternate mode below */ +GPIO_INT(HYPER_CONSOLE_TX, PIN(G, 7), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) +GPIO_INT(HYPER_CONSOLE_RX, PIN(G, 8), GPIO_ALTERNATE | ANY_EDGE, gpio_edge) + +/* USB pins */ +GPIO(USB_FS_DM, PIN(A, 11), GPIO_ALTERNATE) +GPIO(USB_FS_DP, PIN(A, 12), GPIO_ALTERNATE) + +/* Signals for hardware on the Nucleo board itself */ +GPIO_INT(NUCLEO_LED1, PIN(C, 7), GPIO_OUT_HIGH | ANY_EDGE, gpio_edge) /* Green */ +GPIO_INT(NUCLEO_LED2, PIN(B, 7), GPIO_OUT_LOW | ANY_EDGE, gpio_edge) /* Blue */ +GPIO_INT(NUCLEO_LED3, PIN(A, 9), GPIO_OUT_LOW | ANY_EDGE, gpio_edge) /* Red */ +GPIO_INT(NUCLEO_USER_BTN, PIN(C, 13), GPIO_INPUT | ANY_EDGE, gpio_edge) /* User button */ + +/* Unimplemented signals since we are not an EC */ +UNIMPLEMENTED(ENTERING_RW) +UNIMPLEMENTED(WP_L) + + +ALTERNATE(PIN_MASK(A, 0x1800), 10, MODULE_USB, 0) /* USB: PA11/12 */ + +ALTERNATE(PIN_MASK(D, 0x0060), 7, MODULE_UART, 0) /* USART2: PD5/PD6 - OT UART */ +ALTERNATE(PIN_MASK(C, 0x0C00), 8, MODULE_UART, 0) /* USART4: PC10/PC11 - AP UART */ +ALTERNATE(PIN_MASK(D, 0x0300), 7, MODULE_UART, 0) /* USART3: PD8/PD9 - EC UART */ +ALTERNATE(PIN_MASK(C, 0x1000), 8, MODULE_UART, 0) /* USART5: PC12 - FP MCU UART */ +ALTERNATE(PIN_MASK(D, 0x0004), 8, MODULE_UART, 0) /* USART5: PD2 - FP MCU UART */ +ALTERNATE(PIN_MASK(G, 0x0180), 8, MODULE_UART, 0) /* LPUART1: PG7/PG8 - HyperDebug console */ + +ALTERNATE(PIN_MASK(F, 0x0003), 4, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C2: PF0/PF1 */ +ALTERNATE(PIN_MASK(B, 0x0300), 4, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C1: PB8/PB9 */ +ALTERNATE(PIN_MASK(C, 0x0003), 4, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C3: PC0/PC1 */ +ALTERNATE(PIN_MASK(F, 0xC000), 4, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C4: PF14/PF15 */ +ALTERNATE(PIN_MASK(E, 0xF400), 10, MODULE_SPI, 0) /* QSPI: PE10/PE12-15 */ +ALTERNATE(PIN_MASK(D, 0x001A), 5, MODULE_SPI, 0) /* SPI2: PD1/PD3/PD4 SCK/CIDO/CODI */ diff --git a/board/hyperdebug/i2c.c b/board/hyperdebug/i2c.c new file mode 100644 index 0000000000..bbb86d0d6b --- /dev/null +++ b/board/hyperdebug/i2c.c @@ -0,0 +1,155 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* HyperDebug I2C logic and console commands */ + +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "i2c.h" +#include "util.h" + +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "I2C1", + .port = 0, + .kbps = 100, + .scl = GPIO_CN7_2, + .sda = GPIO_CN7_4, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED }, + { .name = "I2C2", + .port = 1, + .kbps = 100, + .scl = GPIO_CN9_19, + .sda = GPIO_CN9_21, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED }, + { .name = "I2C3", + .port = 2, + .kbps = 100, + .scl = GPIO_CN9_11, + .sda = GPIO_CN9_9, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED }, + { .name = "I2C4", + .port = 3, + .kbps = 100, + .scl = GPIO_CN10_8, + .sda = GPIO_CN10_12, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +int usb_i2c_board_is_enabled(void) +{ + return 1; +} + +/* + * Find i2c port by name or by number. Returns an index into i2c_ports[], or on + * error a negative value. + */ +static int find_i2c_by_name(const char *name) +{ + int i; + char *e; + i = strtoi(name, &e, 0); + + if (!*e && i < i2c_ports_used) + return i; + + for (i = 0; i < i2c_ports_used; i++) { + if (!strcasecmp(name, i2c_ports[i].name)) + return i; + } + + /* I2C device not found */ + return -1; +} + +static void print_i2c_info(int index) +{ + uint32_t bits_per_second = 1000 * i2c_freq_to_khz(i2c_get_freq(index)); + + ccprintf(" %d %s %d bps\n", index, i2c_ports[index].name, + bits_per_second); + + /* Flush console to avoid truncating output */ + cflush(); +} + +/* + * Get information about one or all I2C ports. + */ +static int command_i2c_info(int argc, const char **argv) +{ + int i; + + /* If a I2C port is specified, print only that one */ + if (argc == 3) { + int index = find_i2c_by_name(argv[2]); + if (index < 0) { + ccprintf("I2C port not found\n"); + return EC_ERROR_PARAM2; + } + + print_i2c_info(index); + return EC_SUCCESS; + } + + /* Otherwise print them all */ + for (i = 0; i < i2c_ports_used; i++) { + print_i2c_info(i); + } + + return EC_SUCCESS; +} + +static int command_i2c_set_speed(int argc, const char **argv) +{ + int index; + uint32_t desired_speed; + char *e; + if (argc < 5) + return EC_ERROR_PARAM_COUNT; + + index = find_i2c_by_name(argv[3]); + if (index < 0) + return EC_ERROR_PARAM3; + + desired_speed = strtoi(argv[4], &e, 0); + if (*e) + return EC_ERROR_PARAM4; + + if (desired_speed >= 1000000) { + i2c_set_freq(index, I2C_FREQ_1000KHZ); + } else if (desired_speed >= 400000) { + i2c_set_freq(index, I2C_FREQ_400KHZ); + } else { + i2c_set_freq(index, I2C_FREQ_100KHZ); + } + return EC_SUCCESS; +} + +static int command_i2c_set(int argc, const char **argv) +{ + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + if (!strcasecmp(argv[2], "speed")) + return command_i2c_set_speed(argc, argv); + return EC_ERROR_PARAM2; +} + +static int command_i2c(int argc, const char **argv) +{ + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + if (!strcasecmp(argv[1], "info")) + return command_i2c_info(argc, argv); + if (!strcasecmp(argv[1], "set")) + return command_i2c_set(argc, argv); + return EC_ERROR_PARAM1; +} +DECLARE_CONSOLE_COMMAND_FLAGS(i2c, command_i2c, + "info [PORT]" + "\nset speed PORT BPS", + "I2C bus manipulation", CMD_FLAG_RESTRICTED); diff --git a/board/hyperdebug/spi.c b/board/hyperdebug/spi.c new file mode 100644 index 0000000000..eee1626281 --- /dev/null +++ b/board/hyperdebug/spi.c @@ -0,0 +1,479 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* HyperDebug SPI logic and console commands */ + +#include "common.h" +#include "console.h" +#include "dma.h" +#include "gpio.h" +#include "registers.h" +#include "spi.h" +#include "stm32-dma.h" +#include "timer.h" +#include "usb_spi.h" +#include "util.h" + +#define OCTOSPI_CLOCK (CPU_CLOCK) +#define SPI_CLOCK (CPU_CLOCK) + +/* SPI devices, default to 406 kb/s for all. */ +struct spi_device_t spi_devices[] = { + { .name = "SPI2", + .port = 1, + .div = 7, + .gpio_cs = GPIO_CN9_25, + .usb_flags = USB_SPI_ENABLED }, + { .name = "QSPI", + .port = -1 /* OCTOSPI */, + .div = 255, + .gpio_cs = GPIO_CN10_6, + .usb_flags = USB_SPI_ENABLED | USB_SPI_CUSTOM_SPI_DEVICE | + USB_SPI_FLASH_DUAL_SUPPORT | USB_SPI_FLASH_QUAD_SUPPORT | + USB_SPI_FLASH_DTR_SUPPORT }, +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +/* + * Find spi device by name or by number. Returns an index into spi_devices[], + * or on error a negative value. + */ +static int find_spi_by_name(const char *name) +{ + int i; + char *e; + i = strtoi(name, &e, 0); + + if (!*e && i < spi_devices_used) + return i; + + for (i = 0; i < spi_devices_used; i++) { + if (!strcasecmp(name, spi_devices[i].name)) + return i; + } + + /* SPI device not found */ + return -1; +} + +static void print_spi_info(int index) +{ + uint32_t bits_per_second; + + if (spi_devices[index].usb_flags & USB_SPI_CUSTOM_SPI_DEVICE) { + // OCTOSPI as 8 bit prescaler, dividing clock by 1..256. + bits_per_second = OCTOSPI_CLOCK / (spi_devices[index].div + 1); + } else { + // Other SPIs have prescaler by power of two 2, 4, 8, ..., 256. + bits_per_second = SPI_CLOCK / (2 << spi_devices[index].div); + } + + ccprintf(" %d %s %d bps\n", index, spi_devices[index].name, + bits_per_second); + + /* Flush console to avoid truncating output */ + cflush(); +} + +/* + * Get information about one or all SPI ports. + */ +static int command_spi_info(int argc, const char **argv) +{ + int i; + + /* If a SPI target is specified, print only that one */ + if (argc == 3) { + int index = find_spi_by_name(argv[2]); + if (index < 0) { + ccprintf("SPI device not found\n"); + return EC_ERROR_PARAM2; + } + + print_spi_info(index); + return EC_SUCCESS; + } + + /* Otherwise print them all */ + for (i = 0; i < spi_devices_used; i++) { + print_spi_info(i); + } + + return EC_SUCCESS; +} + +static int command_spi_set_speed(int argc, const char **argv) +{ + int index; + uint32_t desired_speed; + char *e; + if (argc < 5) + return EC_ERROR_PARAM_COUNT; + + index = find_spi_by_name(argv[3]); + if (index < 0) + return EC_ERROR_PARAM3; + + desired_speed = strtoi(argv[4], &e, 0); + if (*e) + return EC_ERROR_PARAM4; + + if (spi_devices[index].usb_flags & USB_SPI_CUSTOM_SPI_DEVICE) { + /* + * Find prescaler value by division, rounding up in order to get + * slightly slower speed than requested, if it cannot be matched + * exactly. + */ + int divisor = + (OCTOSPI_CLOCK + desired_speed - 1) / desired_speed - 1; + if (divisor >= 256) + divisor = 255; + STM32_OCTOSPI_DCR2 = spi_devices[index].div = divisor; + } else { + int divisor = 7; + /* + * Find the smallest divisor that result in a speed not faster + * than what was requested. + */ + while (divisor > 0) { + if (SPI_CLOCK / (2 << (divisor - 1)) > desired_speed) { + /* One step further would make the clock too + * fast, stop here. */ + break; + } + divisor--; + } + + /* + * Re-initialize spi controller to apply the new clock divisor. + */ + spi_enable(&spi_devices[index], 0); + spi_devices[index].div = divisor; + spi_enable(&spi_devices[index], 1); + } + + return EC_SUCCESS; +} + +static int command_spi_set(int argc, const char **argv) +{ + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + if (!strcasecmp(argv[2], "speed")) + return command_spi_set_speed(argc, argv); + return EC_ERROR_PARAM2; +} + +static int command_spi(int argc, const char **argv) +{ + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + if (!strcasecmp(argv[1], "info")) + return command_spi_info(argc, argv); + if (!strcasecmp(argv[1], "set")) + return command_spi_set(argc, argv); + return EC_ERROR_PARAM1; +} +DECLARE_CONSOLE_COMMAND_FLAGS(spi, command_spi, + "info [PORT]" + "\nset speed PORT BPS", + "SPI bus manipulation", CMD_FLAG_RESTRICTED); + +/****************************************************************************** + * OCTOSPI driver. + */ + +/* + * Wait for a certain set of status bits to all be asserted. + */ +static int octospi_wait_for(uint32_t flags, timestamp_t deadline) +{ + while ((STM32_OCTOSPI_SR & flags) != flags) { + timestamp_t now = get_time(); + if (timestamp_expired(deadline, &now)) + return EC_ERROR_TIMEOUT; + } + return EC_SUCCESS; +} + +/* + * Board-specific SPI driver entry point, called by usb_spi.c. + */ +void usb_spi_board_enable(void) +{ + /* All initialization already done in board_init(). */ +} + +void usb_spi_board_disable(void) +{ +} + +static const struct dma_option dma_octospi_option = { + .channel = STM32_DMAC_CH13, + .periph = (void *)&STM32_OCTOSPI_DR, + .flags = STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT, +}; + +static bool previous_cs; +static timestamp_t deadline; + +/* + * Board-specific SPI driver entry point, called by usb_spi.c. On this board, + * the only spi device declared as requiring board specific driver is OCTOSPI. + * + * Actually, there is nothing board-specific in the code below, as it merely + * implements the serial flash USB protocol extensions on the OctoSPI hardware + * found on STM32L5 chips (and probably others). For now, however, HyperDebug + * is the only board that uses a chip with such an OctoSPI controller, so until + * we have seen this code being generally useful, it will live in + * board/hyperdebug. + */ +int usb_spi_board_transaction_async(const struct spi_device_t *spi_device, + uint32_t flash_flags, const uint8_t *txdata, + int txlen, uint8_t *rxdata, int rxlen) +{ + uint32_t opcode = 0, address = 0; + const uint32_t mode = flash_flags & FLASH_FLAG_MODE_MSK; + const uint8_t width = (flash_flags & FLASH_FLAG_WIDTH_MSK) >> + FLASH_FLAG_WIDTH_POS; + uint8_t opcode_len = (flash_flags & FLASH_FLAG_OPCODE_LEN_MSK) >> + FLASH_FLAG_OPCODE_LEN_POS; + uint8_t addr_len = (flash_flags & FLASH_FLAG_ADDR_LEN_MSK) >> + FLASH_FLAG_ADDR_LEN_POS; + const uint8_t dummy_cycles = + (flash_flags & FLASH_FLAG_DUMMY_CYCLES_MSK) >> + FLASH_FLAG_DUMMY_CYCLES_POS; + uint32_t data_len; + uint32_t control_value = 0; + + if (!flash_flags) { + /* + * This is a request does not use the extended format with SPI + * flash flags, but is for doing plain write-then-read of single + * lane (COPI/CIPO) SPI data. + */ + if (rxlen == SPI_READBACK_ALL) { + cprints(CC_SPI, + "Full duplex not supported by OctoSPI hardware"); + return EC_ERROR_UNIMPLEMENTED; + } else if (!rxlen && !txlen) { + /* No operation requested, done. */ + return EC_SUCCESS; + } else if (!rxlen) { + /* + * Transmit-only transaction. This is implemented by + * not using any of the up to 12 bytes of instructions, + * but as all "data". + */ + flash_flags |= FLASH_FLAG_READ_WRITE_WRITE; + } else if (txlen <= 12) { + /* + * Sending of up to 12 bytes, followed by reading a + * possibly large number of bytes. This is implemented + * by a "read" transaction using the instruction and + * address feature of OctoSPI. + */ + if (txlen <= 4) { + opcode_len = txlen; + } else { + opcode_len = 4; + addr_len = txlen - 4; + } + } else { + /* + * Sending many bytes, followed by reading. This would + * have to be implemented as two separate OctoSPI + * transactions. + */ + cprints(CC_SPI, + "General write-then-read not supported by OctoSPI hardware"); + return EC_ERROR_UNIMPLEMENTED; + } + } + + previous_cs = gpio_get_level(spi_device->gpio_cs); + + /* Drive chip select low */ + gpio_set_level(spi_device->gpio_cs, 0); + + /* Deadline on the entire SPI transaction. */ + deadline.val = get_time().val + OCTOSPI_TRANSACTION_TIMEOUT_US; + + if ((flash_flags & FLASH_FLAG_READ_WRITE_MSK) == + FLASH_FLAG_READ_WRITE_WRITE) { + data_len = txlen - opcode_len - addr_len; + /* Enable OCTOSPI, indirect write mode. */ + STM32_OCTOSPI_CR = STM32_OCTOSPI_CR_FMODE_IND_WRITE | + STM32_OCTOSPI_CR_DMAEN | STM32_OCTOSPI_CR_EN; + } else { + data_len = rxlen; + /* Enable OCTOSPI, indirect read mode. */ + STM32_OCTOSPI_CR = STM32_OCTOSPI_CR_FMODE_IND_READ | + STM32_OCTOSPI_CR_DMAEN | STM32_OCTOSPI_CR_EN; + } + + /* Clear completion flag from last transaction. */ + STM32_OCTOSPI_FCR = STM32_OCTOSPI_FCR_CTCF; + + /* Data length. */ + STM32_OCTOSPI_DLR = data_len - 1; + + /* + * Set up the number of bytes and data width of each of the opcode, + * address, and "alternate" stages of the initial command bytes. + */ + if (opcode_len == 0) { + control_value |= STM32_OCTOSPI_CCR_IMODE_NONE; + } else { + control_value |= (opcode_len - 1) + << STM32_OCTOSPI_CCR_ISIZE_POS; + if (mode < FLASH_FLAG_MODE_NNN) { + // Opcode phase is single-lane + control_value |= 1 << STM32_OCTOSPI_CCR_IMODE_POS; + } else { + // Opcode phase is multi-lane + control_value |= (width + 1) + << STM32_OCTOSPI_CCR_IMODE_POS; + if (flash_flags & FLASH_FLAG_DTR) + control_value |= STM32_OCTOSPI_CCR_IDTR; + } + for (int i = 0; i < opcode_len; i++) { + opcode <<= 8; + opcode |= *txdata++; + txlen--; + } + } + if (addr_len == 0) { + control_value |= STM32_OCTOSPI_CCR_ADMODE_NONE; + control_value |= STM32_OCTOSPI_CCR_ABMODE_NONE; + } else if (addr_len <= 4) { + control_value |= (addr_len - 1) << STM32_OCTOSPI_CCR_ADSIZE_POS; + if (mode < FLASH_FLAG_MODE_1NN) { + // Address phase is single-lane + control_value |= 1 << STM32_OCTOSPI_CCR_ADMODE_POS; + } else { + // Address phase is multi-lane + control_value |= (width + 1) + << STM32_OCTOSPI_CCR_ADMODE_POS; + if (flash_flags & FLASH_FLAG_DTR) + control_value |= STM32_OCTOSPI_CCR_ADDTR; + } + for (int i = 0; i < addr_len; i++) { + address <<= 8; + address |= *txdata++; + txlen--; + } + control_value |= STM32_OCTOSPI_CCR_ABMODE_NONE; + } else { + uint32_t alternate = 0; + control_value |= 3 << STM32_OCTOSPI_CCR_ADSIZE_POS; + control_value |= (addr_len - 5) << STM32_OCTOSPI_CCR_ABSIZE_POS; + if (mode < FLASH_FLAG_MODE_1NN) { + // Address phase is single-lane + control_value |= 1 << STM32_OCTOSPI_CCR_ADMODE_POS; + control_value |= 1 << STM32_OCTOSPI_CCR_ABMODE_POS; + } else { + // Address phase is multi-lane + control_value |= (width + 1) + << STM32_OCTOSPI_CCR_ADMODE_POS; + control_value |= (width + 1) + << STM32_OCTOSPI_CCR_ABMODE_POS; + if (flash_flags & FLASH_FLAG_DTR) + control_value |= STM32_OCTOSPI_CCR_ADDTR | + STM32_OCTOSPI_CCR_ABDTR; + } + for (int i = 0; i < 4; i++) { + address <<= 8; + address |= *txdata++; + txlen--; + } + for (int i = 0; i < addr_len - 4; i++) { + alternate <<= 8; + alternate |= *txdata++; + txlen--; + } + STM32_OCTOSPI_ABR = alternate; + } + /* Set up how many bytes to read/write after the initial command. */ + if (data_len == 0) { + control_value |= STM32_OCTOSPI_CCR_DMODE_NONE; + } else { + if (mode < FLASH_FLAG_MODE_11N) { + // Data phase is single-lane + control_value |= 1 << STM32_OCTOSPI_CCR_DMODE_POS; + } else { + // Data phase is multi-lane + control_value |= (width + 1) + << STM32_OCTOSPI_CCR_DMODE_POS; + if (flash_flags & FLASH_FLAG_DTR) + control_value |= STM32_OCTOSPI_CCR_DDTR; + } + } + + /* Dummy cycles. */ + STM32_OCTOSPI_TCR = dummy_cycles << STM32_OCTOSPI_TCR_DCYC_POS; + + STM32_OCTOSPI_CCR = control_value; + + /* Set instruction and address registers, triggering the start of the + * write+read transaction. */ + STM32_OCTOSPI_IR = opcode; + STM32_OCTOSPI_AR = address; + + if ((flash_flags & FLASH_FLAG_READ_WRITE_MSK) == + FLASH_FLAG_READ_WRITE_WRITE) { + if (txlen > 0) { + dma_chan_t *txdma = dma_get_channel(STM32_DMAC_CH13); + dma_prepare_tx(&dma_octospi_option, txlen, txdata); + dma_go(txdma); + } + } else { + if (rxlen > 0) { + dma_start_rx(&dma_octospi_option, rxlen, rxdata); + } + } + + return EC_SUCCESS; +} + +int usb_spi_board_transaction_is_complete(const struct spi_device_t *spi_device) +{ + /* Query the "transaction complete flag" of the status register. */ + return STM32_OCTOSPI_SR & STM32_OCTOSPI_SR_TCF; +} + +int usb_spi_board_transaction_flush(const struct spi_device_t *spi_device) +{ + /* + * Wait until DMA transfer is complete (no-op if DMA not started because + * of zero-length transfer). + */ + int rv = dma_wait(STM32_DMAC_CH13); + dma_disable(STM32_DMAC_CH13); + if (rv != EC_SUCCESS) + return rv; + + /* + * Ensure that all bits of the last byte has been shifted onto the SPI + * bus. + */ + rv = octospi_wait_for(STM32_OCTOSPI_SR_TCF, deadline); + + /* Return chip select to previous level. */ + gpio_set_level(spi_device->gpio_cs, previous_cs); + + return rv; +} + +int usb_spi_board_transaction(const struct spi_device_t *spi_device, + uint32_t flash_flags, const uint8_t *txdata, + int txlen, uint8_t *rxdata, int rxlen) +{ + int rv = usb_spi_board_transaction_async(spi_device, flash_flags, + txdata, txlen, rxdata, rxlen); + if (rv == EC_SUCCESS) { + rv = usb_spi_board_transaction_flush(spi_device); + } + return rv; +} diff --git a/board/icarus/battery.c b/board/icarus/battery.c new file mode 100644 index 0000000000..5e1671f5f3 --- /dev/null +++ b/board/icarus/battery.c @@ -0,0 +1,189 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "gpio.h" + +const struct board_batt_params board_battery_info[] = { + /* LGC AP18C8K Battery Information */ + [BATTERY_LGC_AP18C8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G020", + .device_name = "AP18C8K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* Murata AP18C4K Battery Information */ + [BATTERY_MURATA_AP18C4K] = { + .fuel_gauge = { + .manuf_name = "Murata KT00304012", + .device_name = "AP18C4K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* Panasonic AP19B5K Battery Information */ + [BATTERY_PANASONIC_AP19B5K_KT00305011] = { + .fuel_gauge = { + .manuf_name = "PANASONIC KT00305011", + .device_name = "AP19B5K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x4000, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* LGC AP19B8K Battery Information */ + [BATTERY_LGC_AP19B8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G022", + .device_name = "AP19B8K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* COSMX AP20CBL Battery Information */ + [BATTERY_COSMX_AP20CBL] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B002", + .device_name = "AP20CBL", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* SMP AP18C7K Battery Information */ + [BATTERY_SMP_AP18C7K] = { + .fuel_gauge = { + .manuf_name = "SMP KT00307010", + .device_name = "AP18C7K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC_AP18C8K; + +enum battery_present battery_hw_present(void) +{ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/icarus/board.c b/board/icarus/board.c new file mode 100644 index 0000000000..33b2d7768c --- /dev/null +++ b/board/icarus/board.c @@ -0,0 +1,286 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "backlight.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/battery/max17055.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/usb_mux/it5205.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "panic.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "spi.h" +#include "system.h" +#include "task.h" +#include "tcpm/tcpm.h" +#include "timer.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { GPIO_KSO_H, 4 }, { GPIO_KSO_H, 0 }, + { GPIO_KSO_H, 1 }, { GPIO_KSO_H, 3 }, { GPIO_KSO_H, 2 }, + { -1, -1 }, { -1, -1 }, { GPIO_KSO_L, 5 }, + { GPIO_KSO_L, 6 }, { -1, -1 }, { GPIO_KSO_L, 3 }, + { GPIO_KSO_L, 2 }, { GPIO_KSI, 0 }, { GPIO_KSO_L, 1 }, + { GPIO_KSO_L, 4 }, { GPIO_KSI, 3 }, { GPIO_KSI, 2 }, + { GPIO_KSO_L, 0 }, { GPIO_KSI, 5 }, { GPIO_KSI, 4 }, + { GPIO_KSO_L, 7 }, { GPIO_KSI, 6 }, { GPIO_KSI, 7 }, + { GPIO_KSI, 1 }, { -1, -1 }, { GPIO_KSO_H, 5 }, + { -1, -1 }, { GPIO_KSO_H, 6 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +/* Wake-up pins for hibernate */ +const enum gpio_signal hibernate_wake_pins[] = { + GPIO_AC_PRESENT, + GPIO_LID_OPEN, + GPIO_POWER_BUTTON_L, +}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/******************************************************************************/ +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + [ADC_BOARD_ID] = { "BOARD_ID", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH1 }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH2 }, + [ADC_VBUS] = { "VBUS", ADC_MAX_MVOLT * 10, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "typec", + .port = IT83XX_I2C_CH_C, + .kbps = 400, + .scl = GPIO_I2C_C_SCL, + .sda = GPIO_I2C_C_SDA }, + { .name = "other", + .port = IT83XX_I2C_CH_B, + .kbps = 100, + .scl = GPIO_I2C_B_SCL, + .sda = GPIO_I2C_B_SDA }, + { .name = "battery", + .port = IT83XX_I2C_CH_A, + .kbps = 100, + .scl = GPIO_I2C_A_SCL, + .sda = GPIO_I2C_A_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +#define BC12_I2C_ADDR PI3USB9201_I2C_ADDR_3 + +/* power signal list. Must match order of enum power_signal. */ +const struct power_signal_info power_signal_list[] = { + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, +}; +BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); + +/******************************************************************************/ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/******************************************************************************/ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + /* TCPC is embedded within EC so no i2c config needed */ + .drv = &it8xxx2_tcpm_drv, + /* Alert is active-low, push-pull */ + .flags = 0, + }, +}; + +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) +{ + /* This driver does not use host command ACKs */ + *ack_required = false; + + /* + * svdm_dp_attention() did most of the work, we only need to notify + * host here. + */ + host_set_single_event(EC_HOST_EVENT_USB_MUX); +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, + }, +}; + +/* Charger config. Start i2c address at 1, update during runtime */ +struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +static int force_discharge; + +int board_set_active_charge_port(int charge_port) +{ + CPRINTS("New chg p%d", charge_port); + + /* ignore all request when discharge mode is on */ + if (force_discharge && charge_port != CHARGE_PORT_NONE) + return EC_SUCCESS; + + switch (charge_port) { + case CHARGE_PORT_USB_C: + /* Don't charge from a source port */ + if (board_vbus_source_enabled(charge_port)) + return -1; + break; + default: + /* + * To ensure the fuel gauge (max17055) is always powered + * even when battery is disconnected, keep VBAT rail on but + * set the charging current to minimum. + */ + charger_set_current(CHARGER_SOLO, 0); + break; + } + + return EC_SUCCESS; +} + +int board_discharge_on_ac(int enable) +{ + int ret, port; + + if (enable) { + port = CHARGE_PORT_NONE; + } else { + /* restore the charge port state */ + port = charge_manager_get_override(); + if (port == OVERRIDE_OFF) + port = charge_manager_get_active_charge_port(); + } + + ret = charger_discharge_on_ac(enable); + if (ret) + return ret; + + force_discharge = enable; + return board_set_active_charge_port(port); +} + +#define VBUS_THRESHOLD_MV 4200 +int pd_snk_is_vbus_provided(int port) +{ + /* This board has only one port. */ + if (!port) + return adc_read_channel(ADC_VBUS) > VBUS_THRESHOLD_MV ? 1 : 0; + else + return 0; +} + +void bc12_interrupt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void board_init(void) +{ + /* If the reset cause is external, pulse PMIC force reset. */ + if (system_get_reset_flags() == EC_RESET_FLAG_RESET_PIN) { + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 0); + msleep(100); + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 1); + } + + /* Enable interrupts from BMI160 sensor. */ + gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); + + /* Enable interrupt from PMIC. */ + gpio_enable_interrupt(GPIO_PMIC_EC_RESETB); + + /* Enable BC12 interrupt */ + gpio_enable_interrupt(GPIO_BC12_EC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* Vconn control is only for port 0 */ + if (port) + return; + + if (cc_pin == USBPD_CC_PIN_1) + gpio_set_level(GPIO_EN_USB_C0_CC1_VCONN, !!enabled); + else + gpio_set_level(GPIO_EN_USB_C0_CC2_VCONN, !!enabled); +} + +/* Called on AP S5 -> S3 transition */ +static void board_chipset_startup(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S5 transition */ +static void board_chipset_shutdown(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); diff --git a/board/icarus/board.h b/board/icarus/board.h new file mode 100644 index 0000000000..5fa752c518 --- /dev/null +++ b/board/icarus/board.h @@ -0,0 +1,139 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Configuration for Kukui */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KUKUI_JACUZZI +#define VARIANT_KUKUI_BATTERY_SMART +#define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_IT81202 + +#include "baseboard.h" + +/* TODO: remove me once we fix IT83XX_ILM_BLOCK_SIZE out of space issue */ +#undef CONFIG_LTO + +#undef CONFIG_CHIPSET_POWER_SEQ_VERSION +#define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 + +#define CONFIG_BATTERY_HW_PRESENT_CUSTOM + +#define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +#define CONFIG_CHARGER_RUNTIME_CONFIG + +#define CONFIG_BC12_DETECT_PI3USB9201 + +#define CONFIG_EXTPOWER_GPIO +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 200 + +#undef CONFIG_I2C_NACK_RETRY_COUNT +#define CONFIG_I2C_NACK_RETRY_COUNT 10 +#define CONFIG_SMBUS_PEC + +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP +#define CONFIG_USB_PD_DISCHARGE_GPIO +#define CONFIG_USB_PD_TCPC_LOW_POWER + +#define CONFIG_USB_MUX_IT5205 + +#undef CONFIG_ACCEL_FIFO +#undef CONFIG_ACCEL_FIFO_SIZE +#undef CONFIG_ACCEL_FIFO_THRES + +/* I2C ports */ +#define I2C_PORT_BC12 IT83XX_I2C_CH_C +#define I2C_PORT_TCPC0 IT83XX_I2C_CH_C +#define I2C_PORT_USB_MUX IT83XX_I2C_CH_C +#define I2C_PORT_CHARGER IT83XX_I2C_CH_A +#define I2C_PORT_SENSORS IT83XX_I2C_CH_B +#define I2C_PORT_ACCEL I2C_PORT_SENSORS +#define I2C_PORT_BATTERY IT83XX_I2C_CH_A +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY + +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_USE_GPIO + +#define CONFIG_LED_ONOFF_STATES + +#undef CONFIG_GMR_TABLET_MODE +#undef GPIO_TABLET_MODE_L +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH + +#ifndef __ASSEMBLER__ + +enum adc_channel { + /* Real ADC channels begin here */ + ADC_BOARD_ID = 0, + ADC_EC_SKU_ID, + ADC_VBUS, + ADC_CH_COUNT +}; + +/* power signal definitions */ +enum power_signal { + AP_IN_S3_L, + PMIC_PWR_GOOD, + + /* Number of signals */ + POWER_SIGNAL_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum charge_port { + CHARGE_PORT_USB_C, +}; + +enum battery_type { + BATTERY_LGC_AP18C8K, + BATTERY_MURATA_AP18C4K, + BATTERY_PANASONIC_AP19B5K_KT00305011, + BATTERY_LGC_AP19B8K, + BATTERY_COSMX_AP20CBL, + BATTERY_SMP_AP18C7K, + BATTERY_TYPE_COUNT, +}; + +#include "gpio_signal.h" +#include "registers.h" + +/* support factory keyboard test */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV + +#ifdef SECTION_IS_RO +/* Interrupt handler for AP jump to BL */ +void emmc_ap_jump_to_bl(enum gpio_signal signal); +#endif + +void bc12_interrupt(enum gpio_signal signal); +void board_reset_pd_mcu(void); +int board_get_version(void); + +/* returns the i2c port number of charger/battery */ +int board_get_charger_i2c(void); +int board_get_battery_i2c(void); + +/* Motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/icarus/build.mk b/board/icarus/build.mk new file mode 100644 index 0000000000..a1ca27116e --- /dev/null +++ b/board/icarus/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# +# +# IC is ITE IT81202 +CHIP:=it83xx +CHIP_FAMILY:=it8xxx2 +CHIP_VARIANT:=it81202bx_1024 +BASEBOARD:=kukui + +board-y=battery.o board.o led.o diff --git a/board/icarus/ec.tasklist b/board/icarus/ec.tasklist new file mode 100644 index 0000000000..9b6e29ea07 --- /dev/null +++ b/board/icarus/ec.tasklist @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) diff --git a/board/icarus/gpio.inc b/board/icarus/gpio.inc new file mode 100644 index 0000000000..1ec4c9cc41 --- /dev/null +++ b/board/icarus/gpio.inc @@ -0,0 +1,148 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Interrupts */ +GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH, + power_button_interrupt) /* EC_PWR_BTN_ODL */ +GPIO_INT(AP_IN_SLEEP_L, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(PMIC_EC_RESETB, PIN(F, 3), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(WARM_RESET_REQ, PIN(D, 3), GPIO_INT_RISING | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + chipset_reset_request_interrupt) +GPIO_INT_RO(BOOTBLOCK_EN_L, PIN(J, 1), GPIO_INT_RISING | GPIO_SEL_1P8V, + emmc_ap_jump_to_bl) +GPIO_INT(SPI0_CS, PIN(M, 5), GPIO_INT_FALLING, + spi_event) /* SPI slave Chip Select -- AP_SPI_EC_CS_L */ +GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH, + lid_interrupt) +GPIO_INT(AC_PRESENT, PIN(E, 5), GPIO_INT_BOTH, + extpower_interrupt) /* ACOK_OD */ +GPIO_INT(BC12_EC_INT_ODL, PIN(J, 6), GPIO_INT_FALLING, + bc12_interrupt) +GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 7), GPIO_INT_FALLING | GPIO_SEL_1P8V, + chipset_watchdog_interrupt) +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, + uart_deepsleep_interrupt) /* UART_DEBUG_TX_EC_RX */ +/* Unimplemented interrupts */ +GPIO(ACCEL_INT_ODL, PIN(J, 2), GPIO_INPUT) +GPIO(TABLET_MODE_L, PIN(J, 7), GPIO_INPUT) +GPIO(VOLUME_DOWN_L, PIN(D, 5), GPIO_INPUT) +GPIO(VOLUME_UP_L, PIN(D, 6), GPIO_INPUT) +GPIO(ALS_RGB_INT_ODL, PIN(F, 0), GPIO_INPUT) +GPIO(LID_ACCEL_INT_ODL, PIN(J, 3), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Reset pins */ +GPIO(AP_SYS_RST_L, PIN(B, 6), GPIO_OUT_LOW) +/* 1.8V PP or 1.8V OD output with external 10K PU */ +GPIO(PMIC_WATCHDOG_L, PIN(H, 0), GPIO_ODR_LOW | GPIO_SEL_1P8V) +/* OD output with 5VT (there is 5V internal PU on PWRKEY of MT6358) */ +GPIO(PMIC_EN_ODL, PIN(E, 1), GPIO_ODR_HIGH) + +/* + * I2C pins should be configured as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +/* EC programming */ +GPIO(I2C_E_SCL, PIN(A, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(I2C_E_SDA, PIN(A, 5), GPIO_INPUT | GPIO_SEL_1P8V) +/* battery and charger */ +GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) +/* sensor */ +GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT | GPIO_SEL_1P8V) +/* typec */ +GPIO(I2C_C_SCL, PIN(F, 6), GPIO_INPUT) +GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) + +/* Other input pins */ +/* TODO(WP_L): change to interrupt pin ? */ +GPIO(WP_L, PIN(I, 4), GPIO_INPUT | GPIO_SEL_1P8V) /* EC_FLASH_WP_ODL */ +GPIO(CCD_MODE_ODL, PIN(C, 4), GPIO_INPUT) + +/* Other output pins */ +GPIO(EC_BATT_PRES_ODL, PIN(C, 0), GPIO_INPUT) +GPIO(EC_BL_EN_OD, PIN(B, 5), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EN_USBA_5V, PIN(B, 7), GPIO_OUT_LOW) +GPIO(ENTERING_RW, PIN(C, 5), GPIO_ODR_HIGH) /* EC_ENTERING_RW_ODL */ +GPIO(EC_INT_L, PIN(E, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_AP_INT_ODL */ +GPIO(EC_BOARD_ID_EN_L, PIN(H, 5), GPIO_ODR_HIGH) /* EC_BOARD_ID_EN_ODL */ +GPIO(USB_C0_HPD_OD, PIN(J, 0), GPIO_ODR_LOW) +GPIO(USB_C0_DISCHARGE, PIN(H, 3), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC1_VCONN, PIN(H, 1), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC2_VCONN, PIN(H, 2), GPIO_OUT_LOW) + +/* LEDs */ +GPIO(LED_BLUE, PIN(A, 2), GPIO_OUT_HIGH) +GPIO(LED_GREEN, PIN(A, 1), GPIO_OUT_HIGH) +GPIO(LED_ORANGE, PIN(A, 0), GPIO_OUT_HIGH) +GPIO(EN_PP1800_S5_L, PIN(D, 0), GPIO_OUT_LOW) + +/* Unimplemented Pins */ +GPIO(PG_PP5000_A_OD, PIN(A, 6), GPIO_INPUT) +GPIO(USB_A0_OC_ODL, PIN(A, 7), GPIO_INPUT) +GPIO(EC_PROCHOT_ODL, PIN(C, 3), GPIO_INPUT) +GPIO(PMIC_FORCE_RESET_ODL, PIN(C, 6), GPIO_INPUT) +GPIO(USB_C0_PD_INT_ODL, PIN(D, 1), GPIO_INPUT) /* no used on this board */ +GPIO(EN_PP5000A_USM, PIN(D, 7), GPIO_INPUT) +GPIO(EN_USBC_CHARGE_L, PIN(F, 1), GPIO_INPUT) +GPIO(EN_PP5000_USBC, PIN(H, 4), GPIO_INPUT) +GPIO(PP1800_H1_PG, PIN(H, 6), GPIO_INPUT) + +/* NC pins, ensure they aren't in floating state. */ +GPIO(NC_GPA3, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPB2, PIN(B, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPD2, PIN(D, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPD4, PIN(D, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPE0, PIN(E, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPE3, PIN(E, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPE7, PIN(E, 7), GPIO_INPUT | GPIO_PULL_DOWN) +/* + * ADC pins don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(NC_GPI5, PIN(I, 5), GPIO_OUT_LOW) +GPIO(NC_GPI7, PIN(I, 7), GPIO_OUT_LOW) + +GPIO(NC_GPJ4, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPJ5, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +/* + * GPG3,4,5,7 don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(NC_GPG0, PIN(G, 0), GPIO_INPUT | GPIO_PULL_DOWN) +/* Don't touch GPG1 and GPG2 */ +GPIO(NC_GPG3, PIN(G, 3), GPIO_OUT_LOW) +GPIO(EC_SPI_FLASH_MOSI, PIN(G, 4), GPIO_OUT_LOW) +GPIO(EC_SPI_FLASH_MISO, PIN(G, 5), GPIO_OUT_LOW) +GPIO(EC_SPI_FLASH_CLK, PIN(G, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_SPI_FLASH_CS_L, PIN(G, 7), GPIO_OUT_LOW) + +/* Alternate functions GPIO definitions */ +/* Keyboard */ +ALTERNATE(PIN_MASK(KSI, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSI0-7 */ +ALTERNATE(PIN_MASK(KSO_H, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO8-15 */ +ALTERNATE(PIN_MASK(KSO_L, 0xFB), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO0-1, 3-7 */ +GPIO(EC_KSO_02_INV, PIN(KSO_L, 2), GPIO_OUT_LOW) /* KSO2 inverted */ +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A */ +ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C B */ +ALTERNATE(PIN_MASK(F, 0xC0), 1, MODULE_I2C, 0) /* I2C C */ +/* ADC */ +ALTERNATE(PIN_MASK(I, 0x4F), 0, MODULE_ADC, 0) /* ADC 0,1,2,3,6 */ +/* UART */ +ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, 0) /* EC to Servo */ +/* EMMC SPI SLAVE M2:CLK, M3:CMD, M6:DATA0 */ +ALTERNATE(PIN_MASK(M, 0x4C), 0, MODULE_SPI_FLASH, 0) +/* SPI */ +ALTERNATE(PIN_MASK(M, 0x33), 0, MODULE_SPI, 0) /* SPI for communication */ diff --git a/board/icarus/led.c b/board/icarus/led.c new file mode 100644 index 0000000000..bbbad7ceb8 --- /dev/null +++ b/board/icarus/led.c @@ -0,0 +1,85 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Jacuzzi + */ +#include "common.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_ORANGE, LED_ON_LVL); + gpio_set_level(GPIO_LED_BLUE, LED_OFF_LVL); + gpio_set_level(GPIO_LED_GREEN, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_LED_BLUE, LED_ON_LVL); + gpio_set_level(GPIO_LED_ORANGE, LED_OFF_LVL); + gpio_set_level(GPIO_LED_GREEN, LED_OFF_LVL); + break; + case EC_LED_COLOR_GREEN: + gpio_set_level(GPIO_LED_GREEN, LED_ON_LVL); + gpio_set_level(GPIO_LED_BLUE, LED_OFF_LVL); + gpio_set_level(GPIO_LED_ORANGE, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_GREEN, LED_OFF_LVL); + gpio_set_level(GPIO_LED_BLUE, LED_OFF_LVL); + gpio_set_level(GPIO_LED_ORANGE, LED_OFF_LVL); + break; + } +} +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + } +} +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} diff --git a/board/icarus/vif_override.xml b/board/icarus/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/icarus/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/it83xx_evb/board.c b/board/it83xx_evb/board.c index a18b8b3b70..37ee2f48ed 100644 --- a/board/it83xx_evb/board.c +++ b/board/it83xx_evb/board.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/it83xx_evb/board.h b/board/it83xx_evb/board.h index 754474174c..d3eec7f09e 100644 --- a/board/it83xx_evb/board.h +++ b/board/it83xx_evb/board.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/it83xx_evb/build.mk b/board/it83xx_evb/build.mk index e4c8c01b89..9a78775633 100644 --- a/board/it83xx_evb/build.mk +++ b/board/it83xx_evb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. +# Copyright 2013 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/it83xx_evb/ec.tasklist b/board/it83xx_evb/ec.tasklist index 3ca78d55db..e5d2d246df 100644 --- a/board/it83xx_evb/ec.tasklist +++ b/board/it83xx_evb/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/it83xx_evb/gpio.inc b/board/it83xx_evb/gpio.inc index 9f96b5f325..e3014814d7 100644 --- a/board/it83xx_evb/gpio.inc +++ b/board/it83xx_evb/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,7 +9,7 @@ * Note: Those with interrupt handlers must be declared first. */ GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI GPIO_INT(PCH_PLTRST_L, PIN(E, 3), GPIO_INT_BOTH | GPIO_PULL_UP, lpcrst_interrupt) #endif GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN, lid_interrupt) @@ -56,10 +56,10 @@ ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, GPIO_PULL_UP) /* UART1 */ #ifdef CONFIG_UART_HOST ALTERNATE(PIN_MASK(H, 0x06), 1, MODULE_UART, 0) /* UART2 */ #endif -ALTERNATE(PIN_MASK(A, 0x40), 3, MODULE_SPI_MASTER, 0) /* SSCK of SPI */ -ALTERNATE(PIN_MASK(C, 0x28), 3, MODULE_SPI_MASTER, 0) /* SMOSI/SMISO of SPI */ -ALTERNATE(PIN_MASK(G, 0x01), 3, MODULE_SPI_MASTER, 0) /* SSCE1# of SPI */ -ALTERNATE(PIN_MASK(G, 0x04), 3, MODULE_SPI_MASTER, 0) /* SSCE0# of SPI */ +ALTERNATE(PIN_MASK(A, 0x40), 3, MODULE_SPI_CONTROLLER, 0) /* SSCK of SPI */ +ALTERNATE(PIN_MASK(C, 0x28), 3, MODULE_SPI_CONTROLLER, 0) /* SMOSI/SMISO of SPI */ +ALTERNATE(PIN_MASK(G, 0x01), 3, MODULE_SPI_CONTROLLER, 0) /* SSCE1# of SPI */ +ALTERNATE(PIN_MASK(G, 0x04), 3, MODULE_SPI_CONTROLLER, 0) /* SSCE0# of SPI */ ALTERNATE(PIN_MASK(A, 0x80), 1, MODULE_PWM, 0) /* PWM7 for FAN1 */ ALTERNATE(PIN_MASK(D, 0x40), 3, MODULE_PWM, 0) /* TACH0A for FAN1 */ ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A SCL/SDA */ diff --git a/board/it8xxx2_evb/board.c b/board/it8xxx2_evb/board.c index 0daa3d48cd..404a575e42 100644 --- a/board/it8xxx2_evb/board.c +++ b/board/it8xxx2_evb/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/it8xxx2_evb/board.h b/board/it8xxx2_evb/board.h index 1369e43496..766f0fab4f 100644 --- a/board/it8xxx2_evb/board.h +++ b/board/it8xxx2_evb/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/it8xxx2_evb/build.mk b/board/it8xxx2_evb/build.mk index b54a2fcbb6..6fefa1fc6c 100644 --- a/board/it8xxx2_evb/build.mk +++ b/board/it8xxx2_evb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/it8xxx2_evb/ec.tasklist b/board/it8xxx2_evb/ec.tasklist index ff184489e3..a25dab19eb 100644 --- a/board/it8xxx2_evb/ec.tasklist +++ b/board/it8xxx2_evb/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/it8xxx2_evb/gpio.inc b/board/it8xxx2_evb/gpio.inc index 008034cfb3..32d9de4a05 100644 --- a/board/it8xxx2_evb/gpio.inc +++ b/board/it8xxx2_evb/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,7 +9,7 @@ * Note: Those with interrupt handlers must be declared first. */ GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI GPIO_INT(PCH_PLTRST_L, PIN(E, 3), GPIO_INT_BOTH | GPIO_PULL_UP, lpcrst_interrupt) #endif GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) @@ -56,10 +56,10 @@ ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, GPIO_PULL_UP) /* UART1 */ #ifdef CONFIG_UART_HOST ALTERNATE(PIN_MASK(H, 0x06), 1, MODULE_UART, 0) /* UART2 */ #endif -ALTERNATE(PIN_MASK(A, 0x40), 3, MODULE_SPI_MASTER, 0) /* SSCK of SPI */ -ALTERNATE(PIN_MASK(C, 0x28), 3, MODULE_SPI_MASTER, 0) /* SMOSI/SMISO of SPI */ -ALTERNATE(PIN_MASK(G, 0x01), 3, MODULE_SPI_MASTER, 0) /* SSCE1# of SPI */ -ALTERNATE(PIN_MASK(G, 0x04), 3, MODULE_SPI_MASTER, 0) /* SSCE0# of SPI */ +ALTERNATE(PIN_MASK(A, 0x40), 3, MODULE_SPI_CONTROLLER, 0) /* SSCK of SPI */ +ALTERNATE(PIN_MASK(C, 0x28), 3, MODULE_SPI_CONTROLLER, 0) /* SMOSI/SMISO of SPI */ +ALTERNATE(PIN_MASK(G, 0x01), 3, MODULE_SPI_CONTROLLER, 0) /* SSCE1# of SPI */ +ALTERNATE(PIN_MASK(G, 0x04), 3, MODULE_SPI_CONTROLLER, 0) /* SSCE0# of SPI */ ALTERNATE(PIN_MASK(A, 0x80), 1, MODULE_PWM, 0) /* PWM7 for FAN1 */ ALTERNATE(PIN_MASK(D, 0x40), 3, MODULE_PWM, 0) /* TACH0A for FAN1 */ ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A SCL/SDA */ diff --git a/board/it8xxx2_pdevb/board.c b/board/it8xxx2_pdevb/board.c index 22f204258b..2bcc58a58c 100644 --- a/board/it8xxx2_pdevb/board.c +++ b/board/it8xxx2_pdevb/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,18 +7,19 @@ #include "adc_chip.h" #include "battery.h" #include "console.h" +#include "gpio.h" #include "it83xx_pd.h" #include "pwm.h" #include "pwm_chip.h" #include "timer.h" #include "usb_pd_tcpm.h" -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) -#define USB_PD_PORT_ITE_0 0 -#define USB_PD_PORT_ITE_1 1 -#define USB_PD_PORT_ITE_2 2 -#define RESISTIVE_DIVIDER 11 +#define USB_PD_PORT_ITE_0 0 +#define USB_PD_PORT_ITE_1 1 +#define USB_PD_PORT_ITE_2 2 +#define RESISTIVE_DIVIDER 11 int board_get_battery_soc(void) { @@ -36,14 +37,14 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_ITE_0] = { .bus_type = EC_BUS_TYPE_EMBEDDED, /* TCPC is embedded within EC so needn't i2c config */ - .drv = &it83xx_tcpm_drv, + .drv = &it8xxx2_tcpm_drv, /* Alert is active-low, push-pull */ .flags = 0, }, [USB_PD_PORT_ITE_1] = { .bus_type = EC_BUS_TYPE_EMBEDDED, /* TCPC is embedded within EC so needn't i2c config */ - .drv = &it83xx_tcpm_drv, + .drv = &it8xxx2_tcpm_drv, /* Alert is active-low, push-pull */ .flags = 0, }, @@ -82,7 +83,7 @@ void board_pd_vbus_ctrl(int port, int enabled) gpio_set_level(GPIO_USBPD_PORTA_VBUS_OUTPUT, enabled); if (!enabled) { gpio_set_level(GPIO_USBPD_PORTA_VBUS_DROP, 1); - udelay(10*MSEC); /* 10ms is a try and error value */ + udelay(10 * MSEC); /* 10ms is a try and error value */ } gpio_set_level(GPIO_USBPD_PORTA_VBUS_DROP, 0); } else if (port == USBPD_PORT_B) { @@ -90,7 +91,7 @@ void board_pd_vbus_ctrl(int port, int enabled) gpio_set_level(GPIO_USBPD_PORTB_VBUS_OUTPUT, enabled); if (!enabled) { gpio_set_level(GPIO_USBPD_PORTB_VBUS_DROP, 1); - udelay(10*MSEC); /* 10ms is a try and error value */ + udelay(10 * MSEC); /* 10ms is a try and error value */ } gpio_set_level(GPIO_USBPD_PORTB_VBUS_DROP, 0); } else if (port == USBPD_PORT_C) { @@ -98,13 +99,13 @@ void board_pd_vbus_ctrl(int port, int enabled) gpio_set_level(GPIO_USBPD_PORTC_VBUS_OUTPUT, enabled); if (!enabled) { gpio_set_level(GPIO_USBPD_PORTC_VBUS_DROP, 1); - udelay(10*MSEC); /* 10ms is a try and error value */ + udelay(10 * MSEC); /* 10ms is a try and error value */ } gpio_set_level(GPIO_USBPD_PORTC_VBUS_DROP, 0); } if (enabled) - udelay(10*MSEC); /* 10ms is a try and error value */ + udelay(10 * MSEC); /* 10ms is a try and error value */ } void pd_set_input_current_limit(int port, uint32_t max_ma, @@ -119,8 +120,7 @@ void pd_set_input_current_limit(int port, uint32_t max_ma, * so use the same frequency and prescaler register setting is required if * number of pwm channel greater than three. */ -const struct pwm_t pwm_channels[] = { -}; +const struct pwm_t pwm_channels[] = {}; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ diff --git a/board/it8xxx2_pdevb/board.h b/board/it8xxx2_pdevb/board.h index 7c40a1ffc7..e617a015bd 100644 --- a/board/it8xxx2_pdevb/board.h +++ b/board/it8xxx2_pdevb/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,17 +22,16 @@ #undef CONFIG_FANS #undef CONFIG_IT83XX_ENABLE_MOUSE_DEVICE #undef CONFIG_IT83XX_SMCLK2_ON_GPC7 -#undef CONFIG_KEYBOARD_BOARD_CONFIG #undef CONFIG_KEYBOARD_PROTOCOL_8042 #undef CONFIG_PECI #undef CONFIG_PECI_COMMON #undef CONFIG_PECI_TJMAX #undef CONFIG_POWER_BUTTON #undef CONFIG_PWM -#undef CONFIG_SPI_MASTER +#undef CONFIG_SPI_CONTROLLER #undef CONFIG_SPI_FLASH_PORT #undef CONFIG_UART_HOST -#undef CONFIG_HOSTCMD_LPC +#undef CONFIG_HOST_INTERFACE_LPC #undef CONFIG_CMD_MMAPINFO #undef CONFIG_SWITCH @@ -41,13 +40,14 @@ #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED #define CONFIG_USB_PD_CUSTOM_PDO +#define CONFIG_USB_PD_3A_PORTS 0 #define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 #define CONFIG_USB_PD_TCPMV2 #define CONFIG_USB_DRP_ACC_TRYSRC #define CONFIG_USB_PD_REV30 -#define CONFIG_USB_PID 0x1234 /* Invalid PID for development board */ +#define CONFIG_USB_PID 0x1234 /* Invalid PID for development board */ #define CONFIG_USB_PD_DEBUG_LEVEL 2 #define CONFIG_USB_PD_TCPM_ITE_ON_CHIP #define CONFIG_USB_PD_TRY_SRC @@ -82,20 +82,19 @@ enum adc_channel { /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 /* Try to negotiate to 20V since i2c noise problems should be fixed. */ -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_VOLTAGE_MV 20000 /* TODO: determine the following board specific type-C power constants */ /* * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ void board_pd_vbus_ctrl(int port, int enabled); diff --git a/board/it8xxx2_pdevb/build.mk b/board/it8xxx2_pdevb/build.mk index b54a2fcbb6..6fefa1fc6c 100644 --- a/board/it8xxx2_pdevb/build.mk +++ b/board/it8xxx2_pdevb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/it8xxx2_pdevb/ec.tasklist b/board/it8xxx2_pdevb/ec.tasklist index 41fc733526..ef1195fe7e 100644 --- a/board/it8xxx2_pdevb/ec.tasklist +++ b/board/it8xxx2_pdevb/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/it8xxx2_pdevb/gpio.inc b/board/it8xxx2_pdevb/gpio.inc index afc83a82c3..a03509507b 100644 --- a/board/it8xxx2_pdevb/gpio.inc +++ b/board/it8xxx2_pdevb/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/it8xxx2_pdevb/vif_override.xml b/board/it8xxx2_pdevb/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/it8xxx2_pdevb/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/jacuzzi/battery.c b/board/jacuzzi/battery.c index 443bf1e98a..1caeb7e3c5 100644 --- a/board/jacuzzi/battery.c +++ b/board/jacuzzi/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -120,7 +120,8 @@ const struct board_batt_params board_battery_info[] = { }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_PANASONIC_AC16L5J_KT00205009; +const enum battery_type DEFAULT_BATTERY_TYPE = + BATTERY_PANASONIC_AC16L5J_KT00205009; enum battery_present battery_hw_present(void) { diff --git a/board/jacuzzi/board.c b/board/jacuzzi/board.c index 8b6478c26a..c19c41d6c2 100644 --- a/board/jacuzzi/board.c +++ b/board/jacuzzi/board.c @@ -1,10 +1,9 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" #include "charge_manager.h" @@ -16,6 +15,8 @@ #include "console.h" #include "driver/accel_kionix.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/battery/max17055.h" #include "driver/bc12/pi3usb9201.h" #include "driver/charger/isl923x.h" @@ -31,6 +32,7 @@ #include "it8801.h" #include "keyboard_scan.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "registers.h" @@ -38,45 +40,63 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { schedule_deferred_pd_interrupt(0 /* port */); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, #ifdef BOARD_JACUZZI - {"other", 1, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "other", + .port = 1, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, #else /* Juniper */ - {"other", 1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "other", + .port = 1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, #endif }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct i2c_port_t i2c_bitbang_ports[] = { - {"battery", 2, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA, .drv = &bitbang_drv}, + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, }; const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); @@ -84,13 +104,13 @@ const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * TODO(b/133200075): Tune this once we have the final performance * out of the driver and the i2c bus. @@ -109,8 +129,8 @@ struct keyboard_scan_config keyscan_config = { struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { [0] = { - .i2c_host_port = I2C_PORT_IO_EXPANDER_IT8801, - .i2c_slave_addr = IT8801_I2C_ADDR, + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, .drv = &it8801_ioexpander_drv, }, }; @@ -135,15 +155,18 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -static void board_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -151,13 +174,16 @@ static void board_hpd_status(const struct usb_mux *me, host_set_single_event(EC_HOST_EVENT_USB_MUX); } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, }, }; @@ -203,7 +229,7 @@ int board_set_active_charge_port(int charge_port) if (board_vbus_source_enabled(charge_port)) return -1; break; - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -211,22 +237,11 @@ int board_set_active_charge_port(int charge_port) */ charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - int board_discharge_on_ac(int enable) { int ret, port; @@ -256,7 +271,7 @@ int pd_snk_is_vbus_provided(int port) void bc12_interrupt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } #ifndef VARIANT_KUKUI_NO_SENSORS @@ -276,13 +291,12 @@ static void board_spi_enable(void) STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; /* Reinitialize spi peripheral. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); /* Pin mux spi peripheral toward the sensor. */ - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_spi_enable, +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, MOTION_SENSE_HOOK_PRIO - 1); static void board_spi_disable(void) @@ -290,19 +304,23 @@ static void board_spi_disable(void) /* Set pins to a state calming the sensor down. */ gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); - gpio_config_module(MODULE_SPI_MASTER, 0); + /* Pull SPI_NSS pin to low to prevent a leakage. */ + gpio_set_flags(GPIO_EC_SENSOR_SPI_NSS, GPIO_OUT_LOW); + gpio_set_level(GPIO_EC_SENSOR_SPI_NSS, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); /* Disable spi peripheral and clocks. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_spi_disable, +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, MOTION_SENSE_HOOK_PRIO + 1); #endif /* !VARIANT_KUKUI_NO_SENSORS */ static void board_init(void) { + int board_version; + /* If the reset cause is external, pulse PMIC force reset. */ if (system_get_reset_flags() == EC_RESET_FLAG_RESET_PIN) { gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 0); @@ -326,6 +344,20 @@ static void board_init(void) /* Enable BC12 interrupt */ gpio_enable_interrupt(GPIO_BC12_EC_INT_ODL); + + board_version = board_get_version(); + if (board_version == 8 || board_version == 9) { + /* Disable motion sense. */ +#ifndef VARIANT_KUKUI_NO_SENSORS + motion_sensor_count = 0; + gpio_disable_interrupt(GPIO_ACCEL_INT_ODL); + gpio_set_flags(GPIO_ACCEL_INT_ODL, GPIO_INPUT | GPIO_PULL_DOWN); +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + /* Disable tablet mode. */ + tablet_set_mode(0, TABLET_TRIGGER_LID); + gmr_tablet_switch_disable(); + gpio_set_flags(GPIO_TABLET_MODE_L, GPIO_INPUT | GPIO_PULL_UP); + } } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -336,15 +368,24 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Rotation matrixes */ -static const mat33_fp_t base_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(1), 0}, - {0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_bmi160_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_icm426xx_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; + +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI160 = 1, + BASE_GYRO_ICM426XX = 2, +}; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -359,7 +400,7 @@ struct motion_sensor_t motion_sensors[] = { .port = I2C_PORT_SENSORS, .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, .rot_standard_ref = NULL, /* Identity matrix. */ - .default_range = 2, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .default_range = 2, /* g, enough to calculate lid angle. */ .config = { /* EC use accel for angle detection */ [SENSOR_CONFIG_EC_S0] = { @@ -386,9 +427,9 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), - .rot_standard_ref = &base_standard_ref, - .default_range = 2, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .rot_standard_ref = &base_bmi160_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, .config = { @@ -414,15 +455,104 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ - .rot_standard_ref = &base_standard_ref, + .rot_standard_ref = &base_bmi160_ref, .min_frequency = BMI_GYRO_MIN_FREQ, .max_frequency = BMI_GYRO_MAX_FREQ, }, }; -const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_icm426xx_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm426xx_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; +static int base_accelgyro_config; + +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_accelgyro_config) { + case BASE_GYRO_ICM426XX: + icm426xx_interrupt(signal); + break; + case BASE_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +static void board_detect_motionsensor(void) +{ + int val; + /* Check base accelgyro chip */ + if (base_accelgyro_config != BASE_GYRO_NONE) + return; + + icm_read8(&icm426xx_base_accel, ICM426XX_REG_WHO_AM_I, &val); + if (val == ICM426XX_CHIP_ICM40608) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + } + base_accelgyro_config = (val == ICM426XX_CHIP_ICM40608) ? + BASE_GYRO_ICM426XX : + BASE_GYRO_BMI160; + CPRINTS("Base Accelgyro: %s", + (val == ICM426XX_CHIP_ICM40608) ? "ICM40608" : "BMI160"); +} +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_DEFAULT); + +int board_sensor_at_360(void) +{ + int board_version; + + board_version = board_get_version(); + if (board_version == 8 || board_version == 9) + return 0; + else + return !gpio_get_level(GPIO_TABLET_MODE_L); +} #endif /* !VARIANT_KUKUI_NO_SENSORS */ /* Called on AP S5 -> S3 transition */ diff --git a/board/jacuzzi/board.h b/board/jacuzzi/board.h index 0303d87433..3d50b41297 100644 --- a/board/jacuzzi/board.h +++ b/board/jacuzzi/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,6 +11,12 @@ #define VARIANT_KUKUI_JACUZZI #define VARIANT_KUKUI_BATTERY_SMART #define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32F098 +#undef CONFIG_CMD_MFALLOW + +/* Free up flash space */ +#define CONFIG_DEBUG_ASSERT_BRIEF +#define CONFIG_USB_PD_DEBUG_LEVEL 2 #ifndef SECTION_IS_RW #define VARIANT_KUKUI_NO_SENSORS @@ -28,6 +34,8 @@ #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_RUNTIME_CONFIG @@ -51,46 +59,54 @@ /* Motion Sensors */ #ifndef VARIANT_KUKUI_NO_SENSORS -#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT +#define CONFIG_ACCEL_KX022 /* Lid accel */ #define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* ICM426XX Base accel/gyro */ +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + #define CONFIG_ALS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_GMR_TABLET_MODE_CUSTOM + #endif /* VARIANT_KUKUI_NO_SENSORS */ /* I2C ports */ -#define I2C_PORT_BC12 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_CHARGER board_get_charger_i2c() -#define I2C_PORT_SENSORS 1 -#define I2C_PORT_IO_EXPANDER_IT8801 1 -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_CHARGER board_get_charger_i2c() +#define I2C_PORT_SENSORS 1 +#define I2C_PORT_KB_DISCRETE 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY #ifdef BOARD_JACUZZI -#define I2C_PORT_BATTERY 1 +#define I2C_PORT_BATTERY 1 #else /* Juniper */ -#define I2C_PORT_BATTERY 2 +#define I2C_PORT_BATTERY 2 #endif +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 + /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -/* Define the MKBP events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) #define CONFIG_LED_ONOFF_STATES @@ -143,12 +159,14 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void bc12_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); /* returns the i2c port number of charger/battery */ int board_get_charger_i2c(void); int board_get_battery_i2c(void); +/* Motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/jacuzzi/build.mk b/board/jacuzzi/build.mk index e449fce9fc..80c34a4e46 100644 --- a/board/jacuzzi/build.mk +++ b/board/jacuzzi/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/jacuzzi/ec.tasklist b/board/jacuzzi/ec.tasklist index b695d05a71..dd3b853c27 100644 --- a/board/jacuzzi/ec.tasklist +++ b/board/jacuzzi/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/jacuzzi/gpio.inc b/board/jacuzzi/gpio.inc index b0f5f25645..b534ad2ea1 100644 --- a/board/jacuzzi/gpio.inc +++ b/board/jacuzzi/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,7 +22,7 @@ GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, chipset_reset_request_interrupt) GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, - bmi160_interrupt) + motion_interrupt) GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, emmc_cmd_interrupt) GPIO_INT(SPI1_NSS, PIN(A, 15), GPIO_INT_BOTH | GPIO_PULL_UP, @@ -122,5 +122,5 @@ ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) /* EMMC SPI SLAVE: PB13/14/15 */ ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) /* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ -ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_MASTER, 0) -ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/jacuzzi/led.c b/board/jacuzzi/led.c index d0039cbfae..ee4df43121 100644 --- a/board/jacuzzi/led.c +++ b/board/jacuzzi/led.c @@ -1,37 +1,43 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Jacuzzi */ #include "common.h" -#include "ioexpander.h" #include "driver/ioexpander/it8801.h" #include "ec_commands.h" +#include "ioexpander.h" #include "led_common.h" #include "led_onoff_states.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED -}; +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -77,4 +83,4 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) led_set_color_battery(LED_OFF); } return EC_SUCCESS; -} \ No newline at end of file +} diff --git a/board/jacuzzi/vif_override.xml b/board/jacuzzi/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/jacuzzi/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/jerry/battery.c b/board/jerry/battery.c deleted file mode 100644 index 4f127c9458..0000000000 --- a/board/jerry/battery.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery.h" -#include "battery_smart.h" -#include "console.h" -#include "gpio.h" -#include "host_command.h" -#include "util.h" - -/* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHUTDOWN_DATA 0x0010 - -static const struct battery_info info = { - .voltage_max = 8400, /* mV */ - .voltage_normal = 7400, - .voltage_min = 6000, - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 45, - .discharging_min_c = 0, - .discharging_max_c = 60, -}; - -const struct battery_info *battery_get_info(void) -{ - return &info; -} - -static int cutoff(void) -{ - int rv; - - /* Ship mode command must be sent twice to take effect */ - rv = sb_write(SB_MANUFACTURER_ACCESS, SB_SHUTDOWN_DATA); - - if (rv != EC_SUCCESS) - return rv; - - return sb_write(SB_MANUFACTURER_ACCESS, SB_SHUTDOWN_DATA); -} - - -int board_cut_off_battery(void) -{ - return cutoff(); -} - diff --git a/board/jerry/board.c b/board/jerry/board.c deleted file mode 100644 index 9583f7ef41..0000000000 --- a/board/jerry/board.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -/* Veyron board-specific configuration */ - -#include "battery.h" -#include "battery_smart.h" -#include "chipset.h" -#include "common.h" -#include "driver/charger/bq24715.h" -#include "extpower.h" -#include "gpio.h" -#include "i2c.h" -#include "keyboard_raw.h" -#include "lid_switch.h" -#include "power.h" -#include "power_button.h" -#include "power.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "registers.h" -#include "spi.h" -#include "task.h" -#include "util.h" -#include "timer.h" -#include "charger.h" -#include "gpio_list.h" - -/* power signal list. Must match order of enum power_signal. */ -const struct power_signal_info power_signal_list[] = { - {GPIO_SOC_POWER_GOOD, POWER_SIGNAL_ACTIVE_HIGH, "POWER_GOOD"}, - {GPIO_SUSPEND_L, POWER_SIGNAL_ACTIVE_HIGH, "SUSPEND#_ASSERTED"}, -}; -BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ -const struct pwm_t pwm_channels[] = { - {STM32_TIM(2), STM32_TIM_CH(3), - PWM_CONFIG_ACTIVE_LOW}, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -/* Charger chips */ -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = CHARGER_ADDR_FLAGS, - .drv = &bq24715_drv, - }, -}; - -void board_config_pre_init(void) -{ - /* enable SYSCFG clock */ - STM32_RCC_APB2ENR |= BIT(0); - - /* Remap USART DMA to match the USART driver */ - /* - * the DMA mapping is : - * Chan 2 : TIM1_CH1 - * Chan 3 : SPI1_TX - * Chan 4 : USART1_TX - * Chan 5 : USART1_RX - */ - STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10); /* Remap USART1 RX/TX DMA */ -} diff --git a/board/jerry/board.h b/board/jerry/board.h deleted file mode 100644 index 2671e20fbb..0000000000 --- a/board/jerry/board.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Veyron board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Increase size of UART TX buffer. */ -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 1024 - -/* Optional features */ -#define CONFIG_AP_HANG_DETECT -#define CONFIG_BATTERY_CUT_OFF -#define CONFIG_BATTERY_SMART -#define CONFIG_BOARD_PRE_INIT -#define CONFIG_CHARGER -#define CONFIG_CHARGER_BQ24715 -#define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHIPSET_RK3288 -#define CONFIG_EXTPOWER_GPIO -#define CONFIG_FORCE_CONSOLE_RESUME -#define CONFIG_HOST_COMMAND_STATUS -#define CONFIG_HOSTCMD_VBNV_CONTEXT -#define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_I2C_VIRTUAL_BATTERY -#define CONFIG_KEYBOARD_COL2_INVERTED -#define CONFIG_KEYBOARD_PROTOCOL_MKBP -#define CONFIG_LED_COMMON -#define CONFIG_LED_POLICY_STD -#define CONFIG_LED_BAT_ACTIVE_LOW -#define CONFIG_LED_POWER_ACTIVE_LOW -#define CONFIG_LOW_POWER_IDLE -#define CONFIG_LOW_POWER_S0 -#define CONFIG_MKBP_USE_GPIO -#define CONFIG_POWER_BUTTON -#define CONFIG_POWER_BUTTON_FLAGS BUTTON_FLAG_ACTIVE_HIGH -#define CONFIG_POWER_COMMON -#define CONFIG_PWM -#define CONFIG_SPI -#define CONFIG_STM_HWTIMER32 -#define CONFIG_UART_RX_DMA -#define CONFIG_VBOOT_HASH - -#define CONFIG_HOSTCMD_ALIGNED - -#define CONFIG_LTO - -#undef CONFIG_CONSOLE_CMDHELP -#undef CONFIG_CONSOLE_HISTORY -#undef CONFIG_SOFTWARE_PANIC -#undef CONFIG_WATCHDOG_HELP -#undef CONFIG_CMD_KEYBOARD - -/* Not enough RO flash space */ -#undef CONFIG_HOSTCMD_GET_UPTIME_INFO - -#define CONFIG_HIBERNATE_WAKEUP_PINS (STM32_PWR_CSR_EWUP1 | STM32_PWR_CSR_EWUP6) - -#ifndef __ASSEMBLER__ - -/* 48 MHz SYSCLK clock frequency */ -#define CPU_CLOCK 48000000 - -/* Keyboard output port list */ -#define KB_OUT_PORT_LIST GPIO_A, GPIO_B, GPIO_C - -/* Single I2C port, where the EC is the master. */ -#define I2C_PORT_MASTER 0 -#define I2C_PORT_BATTERY I2C_PORT_MASTER -#define I2C_PORT_CHARGER I2C_PORT_MASTER -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_MASTER - -/* Timer selection */ -#define TIM_CLOCK32 2 -#define TIM_WATCHDOG 4 - -#include "gpio_signal.h" - -enum power_signal { - RK_POWER_GOOD = 0, - RK_SUSPEND_ASSERTED, - /* Number of power signals */ - POWER_SIGNAL_COUNT -}; - -enum pwm_channel { - PWM_CH_POWER_LED = 0, - /* Number of PWM channels */ - PWM_CH_COUNT -}; - -/* Charger module */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 /* Charge sense resistor, mOhm */ -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 /* Input sensor resistor, mOhm */ -/* Input current limit for 45W AC adapter: - * 45W/19V*85%=2013mA, choose the closest charger setting = 2048mA - */ -#define CONFIG_CHARGER_INPUT_CURRENT 2048 /* mA, based on Link HW design */ -#define CONFIG_CHARGER_CURRENT_LIMIT 3000 /* PL102 inductor 3.0A(3.8A) */ - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/jerry/build.mk b/board/jerry/build.mk deleted file mode 100644 index 05f23ede25..0000000000 --- a/board/jerry/build.mk +++ /dev/null @@ -1,13 +0,0 @@ -# -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build - -# the IC is STmicro STM32F071RB -CHIP:=stm32 -CHIP_FAMILY:=stm32f0 -CHIP_VARIANT:=stm32f07x - -board-y=board.o battery.o diff --git a/board/jerry/ec.tasklist b/board/jerry/ec.tasklist deleted file mode 100644 index 672a633bcd..0000000000 --- a/board/jerry/ec.tasklist +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/** - * See CONFIG_TASK_LIST in config.h for details. - */ -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) diff --git a/board/jerry/gpio.inc b/board/jerry/gpio.inc deleted file mode 100644 index 8dfaa6417b..0000000000 --- a/board/jerry/gpio.inc +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -GPIO_INT(POWER_BUTTON_L, PIN(B, 5), GPIO_INT_BOTH, power_button_interrupt) /* wk6 */ /* active high, the name is for compatibility with existing code */ -GPIO_INT(SOC_POWER_GOOD, PIN(A, 3), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(LID_OPEN, PIN(C, 13), GPIO_INT_BOTH, lid_interrupt) -GPIO_INT(SUSPEND_L, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(SPI1_NSS, PIN(A, 4), GPIO_INT_BOTH, spi_event) -GPIO_INT(AC_PRESENT, PIN(C, 6), GPIO_INT_BOTH | GPIO_PULL_UP, extpower_interrupt) - -/* Keyboard inputs */ -#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH) -#define GPIO_KB_OUTPUT GPIO_ODR_HIGH - -GPIO_INT(KB_IN00, PIN(C, 8), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) -GPIO_INT(KB_IN01, PIN(C, 9), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) -GPIO_INT(KB_IN02, PIN(C, 10), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) -GPIO_INT(KB_IN03, PIN(C, 11), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) -GPIO_INT(KB_IN04, PIN(C, 12), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) -GPIO_INT(KB_IN05, PIN(C, 14), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) -GPIO_INT(KB_IN06, PIN(C, 15), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) -GPIO_INT(KB_IN07, PIN(D, 2), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) - -/* Other inputs */ -GPIO(EC_WAKE, PIN(A, 0), GPIO_INPUT | GPIO_PULL_DOWN) /* wk1 */ -GPIO(WP_L, PIN(B, 4), GPIO_INPUT) - -/* Outputs */ -GPIO(BAT_LED_RED, PIN(B, 11), GPIO_OUT_HIGH) -GPIO(BAT_LED_GREEN, PIN(A, 11), GPIO_OUT_HIGH) -GPIO(EC_BL_OVERRIDE, PIN(F, 1), GPIO_OUT_LOW) -GPIO(EC_INT_L, PIN(B, 9), GPIO_OUT_LOW) -GPIO(ENTERING_RW, PIN(F, 0), GPIO_OUT_LOW) -GPIO(I2C1_SCL, PIN(B, 6), GPIO_ODR_HIGH) -GPIO(I2C1_SDA, PIN(B, 7), GPIO_ODR_HIGH) -GPIO(KB_OUT00, PIN(B, 0), GPIO_KB_OUTPUT) -GPIO(KB_OUT01, PIN(B, 8), GPIO_KB_OUTPUT) -GPIO(KB_OUT02, PIN(B, 12), GPIO_OUT_LOW) /* Inverted from silegro */ -GPIO(KB_OUT03, PIN(B, 13), GPIO_KB_OUTPUT) -GPIO(KB_OUT04, PIN(B, 14), GPIO_KB_OUTPUT) -GPIO(KB_OUT05, PIN(B, 15), GPIO_KB_OUTPUT) -GPIO(KB_OUT06, PIN(C, 0), GPIO_KB_OUTPUT) -GPIO(KB_OUT07, PIN(C, 1), GPIO_KB_OUTPUT) -GPIO(KB_OUT08, PIN(C, 2), GPIO_KB_OUTPUT) -GPIO(KB_OUT09, PIN(B, 1), GPIO_KB_OUTPUT) -GPIO(KB_OUT10, PIN(C, 5), GPIO_KB_OUTPUT) -GPIO(KB_OUT11, PIN(C, 4), GPIO_KB_OUTPUT) -GPIO(KB_OUT12, PIN(A, 13), GPIO_KB_OUTPUT) -GPIO(POWER_LED, PIN(A, 2), GPIO_OUT_HIGH) -GPIO(PMIC_PWRON, PIN(A, 12), GPIO_OUT_LOW) -GPIO(PMIC_RESET, PIN(B, 3), GPIO_OUT_LOW) -GPIO(PMIC_SOURCE_PWREN, PIN(B, 10), GPIO_OUT_LOW) -GPIO(PMIC_WARM_RESET_L, PIN(C, 3), GPIO_ODR_HIGH) - -ALTERNATE(PIN_MASK(A, 0x00f0), 0, MODULE_SPI, 0) -ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, 0) -ALTERNATE(PIN_MASK(B, 0x00c0), 1, MODULE_I2C, 0) diff --git a/board/jewel b/board/jewel new file mode 120000 index 0000000000..7f4a914148 --- /dev/null +++ b/board/jewel @@ -0,0 +1 @@ +hammer \ No newline at end of file diff --git a/board/jinlon/battery.c b/board/jinlon/battery.c index cf3941221c..9cf4c15458 100644 --- a/board/jinlon/battery.c +++ b/board/jinlon/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -36,7 +36,7 @@ */ const struct board_batt_params board_battery_info[] = { /* DynaPack CosMX Battery Information */ - [BATTERY_DANAPACK_COS] = { + [BATTERY_DYNAPACK_COS] = { .fuel_gauge = { .manuf_name = "333-2C-14-A", .ship_mode = { @@ -66,28 +66,4 @@ const struct board_batt_params board_battery_info[] = { }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DANAPACK_COS; - -/* Lower our input voltage to 5V in S5/G3 when battery is full. */ -static void reduce_input_voltage_when_full(void) -{ - int max_pd_voltage_mv; - int port; - - if (charge_get_percent() == 100 && - chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) - max_pd_voltage_mv = 5000; - else - max_pd_voltage_mv = PD_MAX_VOLTAGE_MV; - - if (pd_get_max_voltage() != max_pd_voltage_mv) { - for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) - pd_set_external_voltage_limit(port, max_pd_voltage_mv); - } -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; diff --git a/board/jinlon/board.c b/board/jinlon/board.c index f789b15590..290fa19000 100644 --- a/board/jinlon/board.c +++ b/board/jinlon/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Hatch board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" @@ -37,16 +36,16 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void check_reboot_deferred(void); DECLARE_DEFERRED(check_reboot_deferred); @@ -99,11 +98,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -111,22 +110,24 @@ static void bc12_interrupt(enum gpio_signal signal) } } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 100 }, - [PWM_CH_FAN] = {.channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, - [PWM_CH_FAN2] = {.channel = 6, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 100 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_FAN2] = { .channel = 6, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -137,7 +138,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -145,22 +146,26 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -189,17 +194,13 @@ static struct bmi_drv_data_t g_bmi160_data; static struct accelgyro_saved_data_t g_bma255_data; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -279,14 +280,14 @@ unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; const struct fan_conf fan_conf_1 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_1, /* Use MFT id to control fan */ + .ch = MFT_CH_1, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN2, }; @@ -312,71 +313,76 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, - [MFT_CH_1] = {NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN2}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, + [MFT_CH_1] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN2 }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_5V_REG", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_3] = { - "TEMP_CPU", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_5V_REG", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_3] = { "TEMP_CPU", NPCX_ADC_CH2, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "5v Reg", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, - [TEMP_SENSOR_3] = {.name = "CPU", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_3}, - [TEMP_SENSOR_4] = {.name = "IR Sensor", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = oti502_get_val, - .idx = OTI502_IDX_OBJECT}, + [TEMP_SENSOR_1] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "5v Reg", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "IR Sensor", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = oti502_get_val, + .idx = OTI502_IDX_OBJECT }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - /* Dratini Temperature sensors */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(70), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; -const static struct ec_thermal_config thermal_b = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(86), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(86), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_b = THERMAL_B; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -433,8 +439,8 @@ static const struct ec_response_keybd_config keybd2 = { .capabilities = KEYBD_CAP_SCRNLOCK_KEY, }; -__override const struct ec_response_keybd_config -*board_vivaldi_keybd_config(void) +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) { /* * Future boards should use fw_config instead of SKU ID @@ -482,15 +488,15 @@ void board_overcurrent_event(int port, int is_overcurrented) * The connector has 24 pins total, and there is no pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {1, 4}, {1, 3}, {1, 6}, {1, 7}, - {3, 1}, {2, 0}, {1, 5}, {2, 6}, {2, 7}, - {2, 1}, {2, 4}, {2, 5}, {1, 2}, {2, 3}, - {2, 2}, {3, 0}, {-1, -1}, {-1, -1}, {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); #endif bool board_is_convertible(void) @@ -498,10 +504,9 @@ bool board_is_convertible(void) const uint8_t sku = get_board_sku(); return (sku == 255) || (sku == 1) || (sku == 2) || (sku == 21) || - (sku == 22); + (sku == 22); } - void all_sys_pgood_check_reboot(void) { hook_call_deferred(&check_reboot_deferred_data, 3000 * MSEC); @@ -512,7 +517,7 @@ __override void board_chipset_forced_shutdown(void) hook_call_deferred(&check_reboot_deferred_data, -1); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_forced_shutdown, - HOOK_PRIO_DEFAULT); + HOOK_PRIO_DEFAULT); static void check_reboot_deferred(void) { diff --git a/board/jinlon/board.h b/board/jinlon/board.h index f898b90c9a..350376dd63 100644 --- a/board/jinlon/board.h +++ b/board/jinlon/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,7 +19,7 @@ #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -32,12 +32,13 @@ * Jinlon's battery takes several seconds to come back out of its disconnect * state (~4 seconds, but give it 6 for margin). */ -#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT #define CONFIG_POWER_BUTTON_INIT_TIMEOUT 6 +#define CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV 5000 + /* Sensors */ /* BMI160 Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) @@ -50,7 +51,6 @@ #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL #define CONFIG_LID_ANGLE_UPDATE #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L /* USB Type C and USB PD defines */ #define CONFIG_USB_PD_COMM_LOCKED @@ -98,7 +98,7 @@ #define CONFIG_FAN_INIT_SPEED 50 #define RPM_DEVIATION 1 #define CONFIG_TEMP_SENSOR_OTI502 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -117,15 +117,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -133,9 +134,9 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_TEMP_SENSOR_3, /* ADC2 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_3, /* ADC2 */ ADC_CH_COUNT }; @@ -146,12 +147,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_FAN2, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_FAN2, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, @@ -177,15 +173,10 @@ enum temp_sensor_id { /* List of possible batteries */ enum battery_type { - BATTERY_DANAPACK_COS, + BATTERY_DYNAPACK_COS, BATTERY_TYPE_COUNT, }; -#ifdef CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; -#endif - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/jinlon/build.mk b/board/jinlon/build.mk index 2d6118ea70..4e42a0616e 100644 --- a/board/jinlon/build.mk +++ b/board/jinlon/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/jinlon/ec.tasklist b/board/jinlon/ec.tasklist index 4a1024a091..829be2b7c8 100644 --- a/board/jinlon/ec.tasklist +++ b/board/jinlon/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/jinlon/gpio.inc b/board/jinlon/gpio.inc index f57a331436..91002dacc1 100644 --- a/board/jinlon/gpio.inc +++ b/board/jinlon/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,10 +17,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) diff --git a/board/jinlon/led.c b/board/jinlon/led.c index 18dfb67f78..f9441fd78e 100644 --- a/board/jinlon/led.c +++ b/board/jinlon/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,9 +11,9 @@ #include "chipset.h" #include "ec_commands.h" #include "gpio.h" +#include "hooks.h" #include "host_command.h" #include "led_common.h" -#include "hooks.h" #define BAT_LED_ON 0 #define BAT_LED_OFF 1 @@ -25,11 +25,9 @@ #define LED_ON_TICKS 5 #define POWER_LED_ON_TICKS 2 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_LEFT_LED, - EC_LED_ID_RIGHT_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -37,7 +35,7 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static void led_set_color_battery(int port, enum led_color color) @@ -65,7 +63,7 @@ static void led_set_color_battery(int port, enum led_color color) } } -void led_set_color_power(enum ec_led_colors color) +void led_set_color_power(enum led_color color) { switch (color) { case LED_OFF: @@ -147,21 +145,23 @@ static void set_active_port_color(enum led_color color) static void led_set_battery(void) { static int battery_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate when charging, even in suspend. */ set_active_port_color(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { if (charge_get_percent() < 10) - led_set_color_battery(0, (battery_ticks % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_WHITE : LED_OFF); + led_set_color_battery( + 0, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); else led_set_color_battery(0, LED_OFF); } @@ -169,20 +169,21 @@ static void led_set_battery(void) if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) led_set_color_battery(1, LED_OFF); break; - case PWR_STATE_ERROR: - set_active_port_color((battery_ticks & 0x2) ? - LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: set_active_port_color(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - set_active_port_color((battery_ticks % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? - LED_AMBER : LED_OFF); - else - set_active_port_color(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ @@ -200,9 +201,10 @@ static void led_set_power(void) led_set_color_power(LED_WHITE); else if (chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_STANDBY)) - led_set_color_power((power_tick % - LED_TICKS_PER_CYCLE < POWER_LED_ON_TICKS) ? - LED_WHITE : LED_OFF); + led_set_color_power((power_tick % LED_TICKS_PER_CYCLE < + POWER_LED_ON_TICKS) ? + LED_WHITE : + LED_OFF); else led_set_color_power(LED_OFF); } diff --git a/board/jinlon/thermal.c b/board/jinlon/thermal.c index 4d75f70738..6a18861af3 100644 --- a/board/jinlon/thermal.c +++ b/board/jinlon/thermal.c @@ -1,8 +1,9 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "chipset.h" #include "common.h" #include "console.h" @@ -16,7 +17,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_THERMAL, outstr) -#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) struct fan_step { /* @@ -40,109 +41,108 @@ static const struct fan_step *fan_step_table; static const struct fan_step fan_table_clamshell[] = { { /* level 0 */ - .on = {0, -1, 54, 34}, - .off = {99, -1, 99, 99}, - .rpm = {0, 0}, + .on = { 0, -1, 54, 41 }, + .off = { 99, -1, 99, 99 }, + .rpm = { 0, 0 }, }, { /* level 1 */ - .on = {0, -1, 57, 35}, - .off = {99, -1, 54, 34}, - .rpm = {3950, 3850}, + .on = { 0, -1, 57, 42 }, + .off = { 99, -1, 54, 41 }, + .rpm = { 3950, 3850 }, }, { /* level 2 */ - .on = {0, -1, 58, 36}, - .off = {99, -1, 57, 35}, - .rpm = {4200, 4100}, + .on = { 0, -1, 58, 43 }, + .off = { 99, -1, 57, 42 }, + .rpm = { 4200, 4100 }, }, { /* level 3 */ - .on = {0, -1, 59, 37}, - .off = {99, -1, 58, 36}, - .rpm = {4550, 4450}, + .on = { 0, -1, 59, 44 }, + .off = { 99, -1, 58, 43 }, + .rpm = { 4550, 4450 }, }, { /* level 4 */ - .on = {60, -1, 60, 38}, - .off = {58, -1, 59, 37}, - .rpm = {4900, 4800}, + .on = { 62, -1, 60, 45 }, + .off = { 58, -1, 59, 44 }, + .rpm = { 4900, 4800 }, }, { /* level 5 */ - .on = {62, -1, 61, 39}, - .off = {60, -1, 60, 38}, - .rpm = {5250, 5150}, + .on = { 64, -1, 61, 46 }, + .off = { 62, -1, 60, 45 }, + .rpm = { 5250, 5150 }, }, { /* level 6 */ - .on = {65, -1, 64, 40}, - .off = {62, -1, 61, 39}, - .rpm = {5400, 5300}, + .on = { 65, -1, 64, 47 }, + .off = { 63, -1, 61, 46 }, + .rpm = { 5400, 5300 }, }, { /* level 7 */ - .on = {100, -1, 100, 100}, - .off = {65, -1, 62, 40}, - .rpm = {6000, 6150}, + .on = { 100, -1, 100, 100 }, + .off = { 65, -1, 62, 47 }, + .rpm = { 6000, 5900 }, }, }; static const struct fan_step fan_table_tablet[] = { { /* level 0 */ - .on = {0, -1, 55, 39}, - .off = {99, -1, 99, 99}, - .rpm = {0, 0}, + .on = { 0, -1, 55, 41 }, + .off = { 99, -1, 99, 99 }, + .rpm = { 0, 0 }, }, { /* level 1 */ - .on = {0, -1, 56, 40}, - .off = {99, -1, 55, 39}, - .rpm = {0, 0}, + .on = { 0, -1, 56, 42 }, + .off = { 99, -1, 55, 41 }, + .rpm = { 0, 0 }, }, { /* level 2 */ - .on = {0, -1, 57, 41}, - .off = {99, -1, 56, 40}, - .rpm = {4000, 3350}, + .on = { 0, -1, 57, 43 }, + .off = { 99, -1, 56, 42 }, + .rpm = { 4000, 3350 }, }, { /* level 3 */ - .on = {0, -1, 58, 42}, - .off = {99, -1, 57, 41}, - .rpm = {4200, 3400}, + .on = { 0, -1, 58, 44 }, + .off = { 99, -1, 57, 43 }, + .rpm = { 4200, 3400 }, }, { /* level 4 */ - .on = {60, -1, 59, 43}, - .off = {58, -1, 58, 42}, - .rpm = {4400, 3500}, + .on = { 60, -1, 59, 45 }, + .off = { 58, -1, 58, 44 }, + .rpm = { 4400, 3500 }, }, { /* level 5 */ - .on = {62, -1, 60, 44}, - .off = {60, -1, 59, 43}, - .rpm = {4800, 4350}, + .on = { 62, -1, 60, 46 }, + .off = { 60, -1, 59, 45 }, + .rpm = { 4800, 4350 }, }, { /* level 6 */ - .on = {65, -1, 61, 45}, - .off = {62, -1, 60, 44}, - .rpm = {5000, 4500}, + .on = { 65, -1, 61, 47 }, + .off = { 62, -1, 60, 46 }, + .rpm = { 5000, 4500 }, }, { /* level 7 */ - .on = {100, -1, 100, 100}, - .off = {65, -1, 61, 45}, - .rpm = {5200, 5100}, + .on = { 100, -1, 100, 100 }, + .off = { 65, -1, 61, 47 }, + .rpm = { 5200, 5100 }, }, }; #define NUM_FAN_LEVELS ARRAY_SIZE(fan_table_clamshell) -BUILD_ASSERT(ARRAY_SIZE(fan_table_clamshell) == - ARRAY_SIZE(fan_table_tablet)); +BUILD_ASSERT(ARRAY_SIZE(fan_table_clamshell) == ARRAY_SIZE(fan_table_tablet)); int fan_table_to_rpm(int fan, int *temp) { @@ -165,12 +165,15 @@ int fan_table_to_rpm(int fan, int *temp) */ if (temp[TEMP_SENSOR_1] < prev_tmp[TEMP_SENSOR_1] || - temp[TEMP_SENSOR_3] < prev_tmp[TEMP_SENSOR_3] || - temp[TEMP_SENSOR_4] < prev_tmp[TEMP_SENSOR_4]) { + temp[TEMP_SENSOR_3] < prev_tmp[TEMP_SENSOR_3] || + temp[TEMP_SENSOR_4] < prev_tmp[TEMP_SENSOR_4]) { for (i = current_level; i > 0; i--) { - if (temp[TEMP_SENSOR_1] < fan_step_table[i].off[TEMP_SENSOR_1] && - temp[TEMP_SENSOR_4] < fan_step_table[i].off[TEMP_SENSOR_4] && - temp[TEMP_SENSOR_3] < fan_step_table[i].off[TEMP_SENSOR_3]) + if (temp[TEMP_SENSOR_1] < + fan_step_table[i].off[TEMP_SENSOR_1] && + temp[TEMP_SENSOR_4] < + fan_step_table[i].off[TEMP_SENSOR_4] && + temp[TEMP_SENSOR_3] < + fan_step_table[i].off[TEMP_SENSOR_3]) current_level = i - 1; else break; @@ -179,9 +182,12 @@ int fan_table_to_rpm(int fan, int *temp) temp[TEMP_SENSOR_3] > prev_tmp[TEMP_SENSOR_3] || temp[TEMP_SENSOR_4] > prev_tmp[TEMP_SENSOR_4]) { for (i = current_level; i < NUM_FAN_LEVELS; i++) { - if ((temp[TEMP_SENSOR_1] > fan_step_table[i].on[TEMP_SENSOR_1] && - temp[TEMP_SENSOR_4] > fan_step_table[i].on[TEMP_SENSOR_4]) || - temp[TEMP_SENSOR_3] > fan_step_table[i].on[TEMP_SENSOR_3]) + if ((temp[TEMP_SENSOR_1] > + fan_step_table[i].on[TEMP_SENSOR_1] && + temp[TEMP_SENSOR_4] > + fan_step_table[i].on[TEMP_SENSOR_4]) || + temp[TEMP_SENSOR_3] > + fan_step_table[i].on[TEMP_SENSOR_3]) current_level = i + 1; else break; @@ -212,10 +218,8 @@ int fan_table_to_rpm(int fan, int *temp) void board_override_fan_control(int fan, int *tmp) { - if (chipset_in_state(CHIPSET_STATE_ON | - CHIPSET_STATE_ANY_SUSPEND)) { + if (chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND)) { fan_set_rpm_mode(FAN_CH(fan), 1); - fan_set_rpm_target(FAN_CH(fan), - fan_table_to_rpm(fan, tmp)); + fan_set_rpm_target(FAN_CH(fan), fan_table_to_rpm(fan, tmp)); } } diff --git a/board/jinlon/vif_override.xml b/board/jinlon/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/jinlon/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/jslrvp_ite/board.c b/board/jslrvp_ite/board.c deleted file mode 100644 index 6a8cc3972b..0000000000 --- a/board/jslrvp_ite/board.c +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel Jasperlake RVP with ITE EC board specific configuration */ - -#include "button.h" -#include "charger.h" -#include "driver/charger/isl923x.h" -#include "extpower.h" -#include "i2c.h" -#include "icelake.h" -#include "intc.h" -#include "lid_switch.h" -#include "power.h" -#include "power_button.h" -#include "switch.h" -#include "system.h" -#include "tablet_mode.h" -#include "uart.h" - -#include "gpio_list.h" - -#define CPRINTS(format, args...) cprints(CC_COMMAND, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_COMMAND, format, ## args) - -/* TCPC gpios */ -const struct tcpc_gpio_config_t tcpc_gpios[] = { - [TYPE_C_PORT_0] = { - .vbus = { - .pin = GPIO_USB_C0_VBUS_INT, - .pin_pol = 1, - }, - .src = { - .pin = GPIO_USB_C0_SRC_EN, - .pin_pol = 1, - }, - .snk = { - .pin = GPIO_USB_C0_SNK_EN_L, - .pin_pol = 0, - }, - }, - [TYPE_C_PORT_1] = { - .vbus = { - .pin = GPIO_USB_C1_VBUS_INT, - .pin_pol = 1, - }, - .src = { - .pin = GPIO_USB_C1_SRC_EN, - .pin_pol = 1, - }, - .snk = { - .pin = GPIO_USB_C1_SNK_EN_L, - .pin_pol = 0, - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_gpios) == CONFIG_USB_PD_PORT_MAX_COUNT); - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - /* Flash EC */ - [I2C_CHAN_FLASH] = { - .name = "chan-A", - .port = IT83XX_I2C_CH_A, - .kbps = 100, - .scl = GPIO_I2C_A_SCL, - .sda = GPIO_I2C_A_SDA, - }, - /* - * Port-80 Display, Charger, Battery, IO-expanders, EEPROM, - * IMVP9, AUX-rail, power-monitor. - */ - [I2C_CHAN_BATT_CHG] = { - .name = "batt_chg", - .port = IT83XX_I2C_CH_B, - .kbps = 100, - .scl = GPIO_I2C_B_SCL, - .sda = GPIO_I2C_B_SDA, - }, - /* Retimers, PDs */ - [I2C_CHAN_RETIMER] = { - .name = "retimer", - .port = IT83XX_I2C_CH_E, - .kbps = 100, - .scl = GPIO_I2C_E_SCL, - .sda = GPIO_I2C_E_SDA, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(i2c_ports) == I2C_CHAN_COUNT); -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/* Charger Chips */ -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = ISL923X_ADDR_FLAGS, - .drv = &isl923x_drv, - }, -}; - -/******************************************************************************/ -/* PWROK signal configuration */ -/* - * On JSLRVP the ALL_SYS_PWRGD, VCCST_PWRGD, PCH_PWROK, and SYS_PWROK - * signals are handled by the board. No EC control needed. - */ -const struct intel_x86_pwrok_signal pwrok_signal_assert_list[] = {}; -const int pwrok_signal_assert_count = ARRAY_SIZE(pwrok_signal_assert_list); - -const struct intel_x86_pwrok_signal pwrok_signal_deassert_list[] = {}; -const int pwrok_signal_deassert_count = ARRAY_SIZE(pwrok_signal_assert_list); - -/* - * Returns board information (board id[7:0] and Fab id[15:8]) on success - * -1 on error. - */ -int board_get_version(void) -{ - int fab_id; - int board_id; - int bom_id; - - if (ioexpander_read_intelrvp_version(&fab_id, &board_id)) - return -1; - /* - * Port0: bit 1:0 - FAB ID(1:0) + 1 - * Port1: bit 7:5 - BOM ID(2:0) - * bit 4:0 - BOARD ID(4:0) - */ - fab_id = (fab_id & 0x03) + 1; - bom_id = ((board_id & 0xE0) >> 5); - board_id &= 0x1F; - - CPRINTS("BID:0x%x, FID:0x%x, BOM:0x%x", board_id, fab_id, bom_id); - - return board_id | (fab_id << 8); -} diff --git a/board/jslrvp_ite/board.h b/board/jslrvp_ite/board.h deleted file mode 100644 index 2ac8afa8d9..0000000000 --- a/board/jslrvp_ite/board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel Jasperlake RVP with ITE EC board specific configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -#define CONFIG_CHIPSET_JASPERLAKE -#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD -#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK -#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_ALL_SYS_PWRGD - -/* Fan features */ -#define CONFIG_FANS 1 -#define BOARD_FAN_MIN_RPM 3000 -#define BOARD_FAN_MAX_RPM 10000 - -/* Temperature sensor */ -#define CONFIG_TEMP_SENSOR - -#include "baseboard.h" - -/* Charger */ -#define CONFIG_CHARGER_ISL9238 - -/* DC Jack charge ports */ -#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT -#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 - -/* USB ports */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define DEDICATED_CHARGE_PORT 2 - -/* USB MUX */ -#define CONFIG_USB_MUX_ANX7440 - -/* USB HPD */ -#define CONFIG_USB_PD_DP_HPD_GPIO - -/* Thermal configs */ - -/* I2C ports */ -#define CONFIG_IT83XX_SMCLK2_ON_GPC7 - -#define I2C_PORT_CHARGER IT83XX_I2C_CH_B -#define I2C_PORT_BATTERY IT83XX_I2C_CH_B -#define I2C_PORT_PCA9555_BOARD_ID_GPIO IT83XX_I2C_CH_B -#define I2C_PORT_PORT80 IT83XX_I2C_CH_B -#define I2C_PORT_USB_MUX IT83XX_I2C_CH_E - -#define I2C_ADDR_PCA9555_BOARD_ID_GPIO 0x22 -#define PORT80_I2C_ADDR MAX695X_I2C_ADDR1_FLAGS - -#ifndef __ASSEMBLER__ - -enum jslrvp_charge_ports { - TYPE_C_PORT_0, - TYPE_C_PORT_1, -}; - -enum jslrvp_i2c_channel { - I2C_CHAN_FLASH, - I2C_CHAN_BATT_CHG, - I2C_CHAN_RETIMER, - I2C_CHAN_COUNT, -}; - -/* Define max power */ -#define PD_MAX_POWER_MW 45000 - -int board_get_version(void); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/jslrvp_ite/build.mk b/board/jslrvp_ite/build.mk deleted file mode 100644 index 31f33208ba..0000000000 --- a/board/jslrvp_ite/build.mk +++ /dev/null @@ -1,15 +0,0 @@ -# -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Intel Jasperlake RVP with ITE EC board specific configuration -# - -#it8320 -CHIP:=it83xx -CHIP_FAMILY:=it8320 -CHIP_VARIANT:=it8320dx -BASEBOARD:=intelrvp - -board-y=board.o diff --git a/board/jslrvp_ite/ec.tasklist b/board/jslrvp_ite/ec.tasklist deleted file mode 100644 index 768211c95f..0000000000 --- a/board/jslrvp_ite/ec.tasklist +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel Jasperlake RVP with ITE EC board specific configuration. - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/jslrvp_ite/gpio.inc b/board/jslrvp_ite/gpio.inc deleted file mode 100644 index 5c0219263e..0000000000 --- a/board/jslrvp_ite/gpio.inc +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel Jasperlake RVP with ITE EC board specific configuration */ - -/* - * Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. - */ - -/* Power sequencing interrupts */ -GPIO_INT(PG_EC_DSW_PWROK, PIN(C, 0), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(SLP_SUS_L, PIN(K, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(ALL_SYS_PWRGD, PIN(F, 0), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(RSMRST_L_PGOOD,PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PCH_SLP_S0_L, PIN(G, 6), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -GPIO_INT(PCH_SLP_S3_L, PIN(F, 2), GPIO_INT_BOTH, power_signal_interrupt) -#endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 -GPIO_INT(PCH_SLP_S4_L, PIN(F, 3), GPIO_INT_BOTH, power_signal_interrupt) -#endif - -/* Button interrupts */ -GPIO_INT(VOLUME_UP_L, PIN(D, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(VOLUME_DOWN_L, PIN(D, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) -GPIO_INT(POWER_BUTTON_L,PIN(L, 3), GPIO_INT_BOTH, power_button_interrupt) - -GPIO_INT(AC_PRESENT, PIN(A, 7), GPIO_INT_BOTH, extpower_interrupt) - -GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, uart_deepsleep_interrupt) /* UART1 RX input */ - -GPIO_INT(WP_L, PIN(I, 4), GPIO_INT_BOTH, switch_interrupt) /* EC_WP_ODL */ - -#ifdef CONFIG_HOSTCMD_ESPI -/* enable 1.8v input of EC's espi_reset pin, and then this pin takes effect. */ -GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) /* eSPI_reset# */ -#endif - -GPIO_INT(TABLET_MODE_L, PIN(K, 1), GPIO_INT_BOTH, gmr_tablet_switch_isr) - -/* DC Jack presence coming from +VADP_OUT */ -GPIO_INT(DC_JACK_PRESENT, PIN(J, 2), GPIO_INT_BOTH, board_dc_jack_interrupt) - -/* Type-C interrupts */ -GPIO_INT(USB_C0_VBUS_INT, PIN(L, 5), GPIO_INT_BOTH, tcpc_alert_event) -GPIO_INT(USB_C1_VBUS_INT, PIN(D, 4), GPIO_INT_BOTH, tcpc_alert_event) - -/* Power sequencing GPIOs */ -GPIO(CPU_PROCHOT, PIN(B, 2), GPIO_INPUT) -GPIO(SYS_RESET_L, PIN(B, 6), GPIO_ODR_HIGH) -GPIO(PCH_RSMRST_L, PIN(C, 6), GPIO_OUT_LOW) -GPIO(PCH_PWRBTN_L, PIN(D, 0), GPIO_ODR_HIGH) -GPIO(EC_SPI_OE_N, PIN(I, 2), GPIO_OUT_LOW) -/* - * PCH_SYS_PWROK is an input, driven by the Silego chip. The common x86 - * power sequencing expects that PCH_SYS_PWROK is an output and will drive - * this signal if GPIO_PCH_SYS_PWROK is configured. Map this pin as no-connect - * so that state can be monitored using the console. - */ -GPIO(NC_PCH_SYS_PWROK, PIN(K, 4), GPIO_INPUT) -GPIO(EN_PP5000, PIN(L, 4), GPIO_OUT_LOW) -GPIO(EN_PP3300_A, PIN(C, 3), GPIO_OUT_LOW) -GPIO(EC_PCH_DSW_PWROK, PIN(L, 6), GPIO_OUT_LOW) - -UNIMPLEMENTED(EN_VCCIO_EXT) - -/* Host communication GPIOs */ -GPIO(PCH_WAKE_L, PIN(J, 0), GPIO_ODR_HIGH) -#ifndef CONFIG_HOSTCMD_ESPI -GPIO(PCH_PLTRST_L, PIN(E, 3), GPIO_INPUT | GPIO_PULL_UP) -#endif - -/* Battery present */ -GPIO(EC_BATT_PRES_L, PIN(K, 0), GPIO_INPUT) - -/* Type-C GPIOs */ -GPIO(USB_C0_SRC_EN, PIN(L, 1), GPIO_OUT_LOW) -GPIO(USB_C0_SNK_EN_L, PIN(H, 6), GPIO_ODR_LOW) -GPIO(USB_C0_SRC_HI_ILIM, PIN(M, 6), GPIO_OUT_LOW) -GPIO(USB_C0_DP_HPD, PIN(E, 6), GPIO_OUT_LOW) -GPIO(USB_C0_FRS_EN, PIN(L, 7), GPIO_INPUT) - -GPIO(USB_C1_SRC_EN, PIN(G, 1), GPIO_OUT_LOW) -GPIO(USB_C1_SNK_EN_L, PIN(I, 5), GPIO_ODR_LOW) -GPIO(USB_C1_SRC_HI_ILIM, PIN(A, 0), GPIO_OUT_LOW) -GPIO(USB_C1_DP_HPD, PIN(D, 3), GPIO_OUT_LOW) -GPIO(USB_C1_FRS_EN, PIN(K, 5), GPIO_INPUT) - -/* - * Type-C USB MUX GPIOs - * TODO(b/146683781): drive initial level to low and - * handle the low power mode - */ -GPIO(USB_C0_LS_EN, PIN(J, 1), GPIO_OUT_HIGH) -GPIO(USB_C1_LS_EN, PIN(C, 4), GPIO_OUT_HIGH) - -/* Type-C BC1.2 GPIOs */ -GPIO(USB_C0_BC12_CHG_DET_L, PIN(A, 1), GPIO_INPUT) -GPIO(USB_C0_BC12_VBUS_ON_ODL, PIN(H, 4), GPIO_ODR_HIGH) - -GPIO(USB_C1_BC12_CHG_DET_L, PIN(B, 7), GPIO_INPUT) -GPIO(USB_C1_BC12_VBUS_ON_ODL, PIN(J, 6), GPIO_ODR_HIGH) - -/* USB-A GPIOs */ -GPIO(USB_A_5V_EN, PIN(K, 3), GPIO_INPUT) - -/* LED */ -GPIO(BAT_LED_GREEN_L, PIN(A, 6), GPIO_OUT_HIGH) /* LED_2_L */ -GPIO(AC_LED_GREEN_L, PIN(A, 3), GPIO_OUT_HIGH) /* LED_1_L */ - -/* FAN control pins */ -GPIO(FAN_POWER_EN, PIN(K, 6), GPIO_OUT_LOW) - -/* H1 pins */ -GPIO(CCD_MODE_ODL, PIN(B, 5), GPIO_INPUT) -GPIO(ENTERING_RW, PIN(C, 5), GPIO_OUT_LOW) - -/* Used if Type-A ports have BC1.2 */ -GPIO(NC_USB_A_CHG_EN, PIN(D, 1), GPIO_INPUT) - -/* Used if dead battery LDO present */ -GPIO(NC_USBC_LDO_ENABLE, PIN(G, 2), GPIO_INPUT) - -/* Used with Discreate TBT and or with PD on RVP */ -GPIO(NC_TBT_C0_RESET_N, PIN(KSO_H, 7), GPIO_INPUT) -GPIO(NC_TBT_C1_RESET_N, PIN(K, 7), GPIO_INPUT) -GPIO(NC_USB_C0_RETIMER_ALRT, PIN(I, 7), GPIO_INPUT) -GPIO(NC_USB_C1_RETIMER_ALRT, PIN(G, 0), GPIO_INPUT) - -/* Used if PMIC is used */ -GPIO(NC_PMIC_EN, PIN(H, 3), GPIO_INPUT) - -/* Used if Base EC is present */ -GPIO(NC_EC_BASE_DET, PIN(I, 3), GPIO_INPUT) - -#ifndef CONFIG_HOSTCMD_ESPI -GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INPUT) -#endif - -/* Unused pins */ -GPIO(NC_SUSWARN, PIN(E, 1), GPIO_INPUT) -GPIO(NC_SD_CARD_DETECT, PIN(E, 5), GPIO_INPUT) -GPIO(NC_BATT_DISABLE, PIN(H, 0), GPIO_INPUT) -GPIO(NC_SLP_S0_CS_N, PIN(I, 0), GPIO_INPUT) - -/* - * I2C pins should be configure as inputs until I2C module is - * initialized. This will avoid driving the lines unintentionally. - */ -GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) -GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) -GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT) -GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT) -GPIO(I2C_C_SCL, PIN(C, 7), GPIO_INPUT) -GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) -GPIO(I2C_E_SCL, PIN(E, 0), GPIO_INPUT) -GPIO(I2C_E_SDA, PIN(E, 7), GPIO_INPUT) -GPIO(I2C_F_SCL, PIN(A, 4), GPIO_INPUT) -GPIO(I2C_F_SDA, PIN(A, 5), GPIO_INPUT) - -/* Alternate pins for I2C */ -ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C F SCL/SDA A4/A5 */ -ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C A SCL/SDA B3/B4 */ -ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C B SCL/SDA C1/C2 */ -ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C E SCL/SDA E0/E7 */ -ALTERNATE(PIN_MASK(C, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C C SCL C7 */ -ALTERNATE(PIN_MASK(F, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C C SDA F7 */ - -/* Alternate pins for UART */ -ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), GPIO_ALT_FUNC_DEFAULT, MODULE_UART, GPIO_PULL_UP) /* UART1 B0/B1 */ - -/* Alternate pins for ADC */ -ALTERNATE(PIN_MASK(I, BIT(1) | BIT(6)), GPIO_ALT_FUNC_DEFAULT, MODULE_ADC, GPIO_FLAG_NONE) /* ADC 1,6 -> I1,I6 */ -ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_ADC, GPIO_FLAG_NONE) /* ADC 13,15 -> L0,L2 */ - -/* Alternate pins for FAN */ -ALTERNATE(PIN_MASK(A, BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_PWM, GPIO_FLAG_NONE) /* PWM2 A2 */ -ALTERNATE(PIN_MASK(D, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_PWM, GPIO_FLAG_NONE) /* TACH1A D7 */ diff --git a/board/kakadu/board.c b/board/kakadu/board.c index 47cf5ee3be..fa7ff1c09e 100644 --- a/board/kakadu/board.c +++ b/board/kakadu/board.c @@ -1,10 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_manager.h" #include "charge_ramp.h" @@ -14,7 +13,9 @@ #include "chipset.h" #include "common.h" #include "console.h" -#include "driver/accelgyro_lsm6dsm.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" #include "driver/charger/rt946x.h" #include "driver/sync.h" #include "driver/tcpm/mt6370.h" @@ -26,6 +27,7 @@ #include "host_command.h" #include "i2c.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -34,7 +36,7 @@ #include "spi.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" @@ -42,8 +44,8 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { @@ -55,37 +57,46 @@ static void gauge_interrupt(enum gpio_signal signal) task_wake(TASK_ID_CHARGER); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, - [ADC_BATT_ID] = {"BATT_ID", 3300, 4096, 0, STM32_AIN(7)}, - [ADC_POGO_ADC_INT_L] = {"POGO_ADC_INT_L", 3300, 4096, 0, STM32_AIN(6)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, + [ADC_BATT_ID] = { "BATT_ID", 3300, 4096, 0, STM32_AIN(7) }, + [ADC_POGO_ADC_INT_L] = { "POGO_ADC_INT_L", 3300, 4096, 0, + STM32_AIN(6) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ @@ -101,13 +112,16 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }; struct mt6370_thermal_bound thermal_bound = { - .target = 90, + .target = 80, .err = 4, }; -static void board_hpd_update(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_update(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -118,7 +132,7 @@ static void board_hpd_update(const struct usb_mux *me, __override const struct rt946x_init_setting *board_rt946x_init_setting(void) { static const struct rt946x_init_setting battery_init_setting = { - .eoc_current = 500, + .eoc_current = 140, .mivr = 4000, .ircmp_vclamp = 32, .ircmp_res = 25, @@ -129,13 +143,16 @@ __override const struct rt946x_init_setting *board_rt946x_init_setting(void) return &battery_init_setting; } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_update, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_update, + }, }, }; @@ -173,7 +190,7 @@ int board_set_active_charge_port(int charge_port) gpio_set_level(GPIO_EN_POGO_CHARGE_L, 0); break; #endif - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -183,9 +200,6 @@ int board_set_active_charge_port(int charge_port) gpio_set_level(GPIO_EN_USBC_CHARGE_L, 1); charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; @@ -226,9 +240,8 @@ int extpower_is_present(void) if (board_vbus_source_enabled(CHARGE_PORT_USB_C)) usb_c_extpower_present = 0; else - usb_c_extpower_present = tcpm_check_vbus_level( - CHARGE_PORT_USB_C, - VBUS_PRESENT); + usb_c_extpower_present = + tcpm_check_vbus_level(CHARGE_PORT_USB_C, VBUS_PRESENT); return usb_c_extpower_present; } @@ -241,20 +254,8 @@ int pd_snk_is_vbus_provided(int port) return rt946x_is_vbus_ready(); } - -#define CHARGER_I2C_ADDR_FLAGS RT946X_ADDR_FLAGS - static void board_init(void) { - -#ifdef SECTION_IS_RW - int val; - i2c_read8(I2C_PORT_CHARGER, CHARGER_I2C_ADDR_FLAGS, - RT946X_REG_CHGCTRL1, &val); - val &= RT946X_MASK_OPA_MODE; - i2c_write8(I2C_PORT_CHARGER, CHARGER_I2C_ADDR_FLAGS, - RT946X_REG_CHGCTRL1, (val | RT946X_MASK_STAT_EN)); -#endif /* If the reset cause is external, pulse PMIC force reset. */ if (system_get_reset_flags() == EC_RESET_FLAG_RESET_PIN) { gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 0); @@ -269,7 +270,7 @@ static void board_init(void) gpio_enable_interrupt(GPIO_CHARGER_INT_ODL); #ifdef SECTION_IS_RW - /* Enable interrupts from LSM6DS3TR sensor. */ + /* Enable interrupts from BMI160 sensor. */ gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); /* Enable interrupt for the camera vsync. */ @@ -300,18 +301,9 @@ static void board_rev_init(void) * Keep this pin defaults to P1 setting since that eMMC enabled with * High-Z stat. */ - /* TODO */ /* Put initial code here for different EC board reversion */ - - /* Display bias settings. */ - mt6370_db_set_voltages(6000, 5800, 5800); - - /* - * Enable MT6370 DB_POSVOUT/DB_NEGVOUT (controlled by _EN pins). - */ - mt6370_db_external_control(1); - + return; } DECLARE_HOOK(HOOK_INIT, board_rev_init, HOOK_PRIO_INIT_ADC + 1); @@ -325,13 +317,64 @@ void sensor_board_proc_double_tap(void) #ifndef VARIANT_KUKUI_NO_SENSORS static struct mutex g_lid_mutex; -static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm42607_data; + +enum lid_accelgyro_type { + LID_GYRO_NONE = 0, + LID_GYRO_BMI160 = 1, + LID_GYRO_ICM426XX = 2, +}; + +static enum lid_accelgyro_type lid_accelgyro_config; /* Matrix to rotate accelerometer into standard reference frame */ -static const mat33_fp_t lid_standard_ref = { - {0, FLOAT_TO_FP(1), 0}, - {FLOAT_TO_FP(-1), 0, 0}, - {0, 0, FLOAT_TO_FP(1)} +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t lid_standard_ref_icm42607 = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; +struct motion_sensor_t icm42607_lid_accel = { + .name = "Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &lid_standard_ref_icm42607, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* Enable accel in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm42607_lid_gyro = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref_icm42607, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, }; struct motion_sensor_t motion_sensors[] = { @@ -341,61 +384,103 @@ struct motion_sensor_t motion_sensors[] = { * DO NOT change the order of the following table. */ [LID_ACCEL] = { - .name = "Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LSM6DSM, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &lsm6dsm_drv, - .mutex = &g_lid_mutex, - .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, - MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_ACCEL_INT_ODL, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ - .min_frequency = LSM6DSM_ODR_MIN_VAL, - .max_frequency = LSM6DSM_ODR_MAX_VAL, - .config = { - /* Enable accel in S0 */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 13000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, + .name = "Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + /* Enable accel in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = TAP_ODR, + .ec_rate = 100 * MSEC, + }, + /* For double tap detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = TAP_ODR, + .ec_rate = 100 * MSEC, + }, + }, }, [LID_GYRO] = { - .name = "Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LSM6DSM, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_LID, - .drv = &lsm6dsm_drv, - .mutex = &g_lid_mutex, - .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, - MOTIONSENSE_TYPE_GYRO), - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .default_range = 1000 | ROUND_UP_FLAG, /* dps */ - .rot_standard_ref = &lid_standard_ref, - .min_frequency = LSM6DSM_ODR_MIN_VAL, - .max_frequency = LSM6DSM_ODR_MAX_VAL, + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, }, [VSYNC] = { - .name = "Camera vsync", - .active_mask = SENSOR_ACTIVE_S0, - .chip = MOTIONSENSE_CHIP_GPIO, - .type = MOTIONSENSE_TYPE_SYNC, - .location = MOTIONSENSE_LOC_CAMERA, - .drv = &sync_drv, - .default_range = 0, - .min_frequency = 0, - .max_frequency = 1, + .name = "Camera vsync", + .active_mask = SENSOR_ACTIVE_S0, + .chip = MOTIONSENSE_CHIP_GPIO, + .type = MOTIONSENSE_TYPE_SYNC, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &sync_drv, + .default_range = 0, + .min_frequency = 0, + .max_frequency = 1, }, }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void board_detect_motionsensor(void) +{ + int ret; + int val; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + if (lid_accelgyro_config != LID_GYRO_NONE) + return; + /* Check base accelgyro chip */ + ret = icm_read8(&icm42607_lid_accel, ICM42607_REG_WHO_AM_I, &val); + if (ret) + ccprints("Get ICM fail."); + if (val == ICM42607_CHIP_ICM42607P) { + motion_sensors[LID_ACCEL] = icm42607_lid_accel; + motion_sensors[LID_GYRO] = icm42607_lid_gyro; + } + lid_accelgyro_config = (val == ICM42607_CHIP_ICM42607P) ? + LID_GYRO_ICM426XX : + LID_GYRO_BMI160; + ccprints("LID Accelgyro: %s", + (val == ICM42607_CHIP_ICM42607P) ? "ICM42607" : "BMI160"); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_INIT_ADC + 2); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (lid_accelgyro_config) { + case LID_GYRO_ICM426XX: + icm42607_interrupt(signal); + break; + case LID_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + #endif /* VARIANT_KUKUI_NO_SENSORS */ /* @@ -431,9 +516,8 @@ __override int board_charge_port_is_connected(int port) return gpio_get_level(GPIO_POGO_VBUS_PRESENT); } -__override -void board_fill_source_power_info(int port, - struct ec_response_usb_pd_power_info *r) +__override void +board_fill_source_power_info(int port, struct ec_response_usb_pd_power_info *r) { r->meas.voltage_now = 3300; r->meas.voltage_max = 3300; @@ -442,3 +526,14 @@ void board_fill_source_power_info(int port, r->max_power = r->meas.voltage_now * r->meas.current_max; } +/* b/207456334: bugged reserved bits causes device not charging */ +static void mt6370_reg_fix(void) +{ + i2c_update8(chg_chips[CHARGER_SOLO].i2c_port, + chg_chips[CHARGER_SOLO].i2c_addr_flags, RT946X_REG_CHGCTRL1, + BIT(3) | BIT(5), MASK_CLR); + i2c_update8(chg_chips[CHARGER_SOLO].i2c_port, + chg_chips[CHARGER_SOLO].i2c_addr_flags, RT946X_REG_CHGCTRL2, + BIT(5) | BIT(RT946X_SHIFT_BATDET_DIS_DLY), MASK_CLR); +} +DECLARE_HOOK(HOOK_INIT, mt6370_reg_fix, HOOK_PRIO_DEFAULT); diff --git a/board/kakadu/board.h b/board/kakadu/board.h index 5bb59705fb..5d64af2f6b 100644 --- a/board/kakadu/board.h +++ b/board/kakadu/board.h @@ -1,16 +1,19 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* Configuration for kakadu */ +/* Configuration for Kakadu */ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H -#define VARIANT_KUKUI_BATTERY_MAX17055 -#define VARIANT_KUKUI_CHARGER_MT6370 +#define BQ27541_ADDR 0x55 +#define VARIANT_KUKUI_BATTERY_BQ27541 #define VARIANT_KUKUI_POGO_KEYBOARD + +#define VARIANT_KUKUI_CHARGER_MT6370 +#define VARIANT_KUKUI_EC_STM32F098 #define VARIANT_KUKUI_TABLET_PWRBTN #ifndef SECTION_IS_RW @@ -21,50 +24,42 @@ #define CONFIG_USB_MUX_IT5205 #define CONFIG_VOLUME_BUTTONS +#define CONFIG_USB_MUX_RUNTIME_CONFIG /* Battery */ -#define BATTERY_DESIRED_CHARGING_CURRENT 3500 /* mA */ +#define BATTERY_DESIRED_CHARGING_CURRENT 3500 /* mA */ #define CONFIG_CHARGER_MT6370_BACKLIGHT -#ifdef BOARD_KAKADU -#define CHARGER_LIMIT_TIMEOUT_HOURS 48 -#define CHARGER_LIMIT_TIMEOUT_HOURS_TEMP 2 -#endif /* Motion Sensors */ #ifdef SECTION_IS_RW -#define CONFIG_ACCELGYRO_LSM6DSM -#define CONFIG_ACCEL_INTERRUPTS -#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) +#define CONFIG_ACCELGYRO_ICM42607 /* Base accel second source*/ +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) /* Camera VSYNC */ #define CONFIG_SYNC #define CONFIG_SYNC_COMMAND -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) #endif /* SECTION_IS_RW */ /* I2C ports */ -#define I2C_PORT_CHARGER 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_BATTERY 1 +#define I2C_PORT_CHARGER 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_BATTERY 1 #define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY -#define I2C_PORT_ACCEL 1 -#define I2C_PORT_BC12 1 -#define I2C_PORT_ALS 1 +#define I2C_PORT_ACCEL 1 +#define I2C_PORT_BC12 1 /* Route sbs host requests to virtual battery driver */ #define VIRTUAL_BATTERY_ADDR_FLAGS 0x0B -/* Define the host events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE)) - /* MKBP */ +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_EVENT_WAKEUP_MASK \ (BIT(EC_MKBP_EVENT_SENSOR_FIFO) | BIT(EC_MKBP_EVENT_HOST_EVENT)) @@ -113,10 +108,19 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); void pogo_adc_interrupt(enum gpio_signal signal); int board_discharge_on_ac(int enable); - +void motion_interrupt(enum gpio_signal signal); + +/* Enable double tap detection */ +#define CONFIG_GESTURE_DETECTION +#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP +#define CONFIG_GESTURE_TAP_SENSOR 0 +#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP_FOR_HOST +#define CONFIG_GESTURE_SAMPLING_INTERVAL_MS 5 +#define CONFIG_GESTURE_TAP_THRES_MG 100 +#define CONFIG_GESTURE_TAP_MAX_INTERSTICE_T 500 +#define CONFIG_GESTURE_DETECTION_MASK BIT(CONFIG_GESTURE_TAP_SENSOR) #endif /* !__ASSEMBLER__ */ diff --git a/board/kakadu/build.mk b/board/kakadu/build.mk index 7a3953b8bb..52ee1b3354 100644 --- a/board/kakadu/build.mk +++ b/board/kakadu/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/kakadu/ec.tasklist b/board/kakadu/ec.tasklist index fc26f445b2..8be28c373d 100644 --- a/board/kakadu/ec.tasklist +++ b/board/kakadu/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/kakadu/gpio.inc b/board/kakadu/gpio.inc index 308520ceda..6f494a9388 100644 --- a/board/kakadu/gpio.inc +++ b/board/kakadu/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -30,7 +30,7 @@ GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 2), GPIO_INT_FALLING, chipset_watchdog_interrupt) GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, - lsm6dsm_interrupt) + motion_interrupt) GPIO_INT(CHARGER_INT_ODL, PIN(C, 13), GPIO_INT_FALLING | GPIO_PULL_UP, rt946x_interrupt) GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, @@ -48,8 +48,10 @@ GPIO_INT(POGO_ADC_INT_L, PIN(A, 6), GPIO_INT_BOTH, /* unused */ GPIO(POGO_VBUS_PRESENT, PIN(A, 14), GPIO_INPUT) -/* To support Apple dongle b/155242849 */ -GPIO(USB_C0_VCONN_EN_OD, PIN(C, 14), GPIO_ODR_HIGH) +/* unused after board rev 5 */ +GPIO(USB_C0_DP_POLARITY, PIN(C, 14), GPIO_INPUT) +GPIO(USB_C0_DP_OE_L, PIN(A, 5), GPIO_INPUT) + /* Reset pins */ GPIO(AP_SYS_RST_L, PIN(C, 11), GPIO_OUT_LOW) diff --git a/board/kakadu/led.c b/board/kakadu/led.c index 3931c392e7..d652563378 100644 --- a/board/kakadu/led.c +++ b/board/kakadu/led.c @@ -1,8 +1,8 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * - * Battery LED control for kakadu board. + * Battery LED control for Kakadu board. */ #include "battery.h" @@ -10,62 +10,123 @@ #include "driver/charger/rt946x.h" #include "hooks.h" #include "led_common.h" +#include "power.h" const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -static enum charge_state prv_chstate = PWR_STATE_INIT; +#define LED_OFF MT6370_LED_ID_OFF +#define LED_AMBER MT6370_LED_ID1 +#define LED_WHITE MT6370_LED_ID2 -#define LED_OFF MT6370_LED_ID_OFF -#define LED_RED MT6370_LED_ID1 -#define LED_GREEN MT6370_LED_ID2 - -#define LED_MASK_OFF 0 -#define LED_MASK_RED MT6370_MASK_RGB_ISNK1DIM_EN -#define LED_MASK_GREEN MT6370_MASK_RGB_ISNK2DIM_EN +#define LED_MASK_OFF 0 +#define LED_MASK_AMBER MT6370_MASK_RGB_ISNK1DIM_EN +#define LED_MASK_WHITE MT6370_MASK_RGB_ISNK2DIM_EN static void kakadu_led_set_battery(void) { - enum charge_state chstate; - static uint8_t prv_r, prv_g; + enum led_pwr_state chstate; + enum power_state powerstate; + static uint8_t prv_white, prv_amber; + static uint8_t time_cnt; uint8_t br[EC_LED_COLOR_COUNT] = { 0 }; - chstate = charge_get_state(); - - if (prv_chstate == chstate && - chstate != PWR_STATE_DISCHARGE) - return; - - prv_chstate = chstate; + chstate = led_pwr_get_state(); + powerstate = power_get_state(); switch (chstate) { - case PWR_STATE_CHARGE: - br[EC_LED_COLOR_GREEN] = 255; - br[EC_LED_COLOR_RED] = 255; - break; - case PWR_STATE_DISCHARGE: - /* real battery SoC 5%*/ - if (charge_get_percent() <= 5) - br[EC_LED_COLOR_RED] = 255; + case LED_PWRS_CHARGE: + case LED_PWRS_CHARGE_NEAR_FULL: + if (charge_get_percent() < 94) { + br[EC_LED_COLOR_AMBER] = 1; + br[EC_LED_COLOR_WHITE] = 0; + break; + } + br[EC_LED_COLOR_WHITE] = 1; + br[EC_LED_COLOR_AMBER] = 0; break; - case PWR_STATE_CHARGE_NEAR_FULL: - br[EC_LED_COLOR_GREEN] = 255; + case LED_PWRS_DISCHARGE: + if (powerstate == POWER_S0) { + /* display SoC 10% = real battery SoC 13%*/ + if (charge_get_percent() < 14) { + if (time_cnt < 1) { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 1; + } else { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + if (time_cnt > 3) + time_cnt = 0; + } + break; + } + br[EC_LED_COLOR_WHITE] = 1; + br[EC_LED_COLOR_AMBER] = 0; + break; + } else if (powerstate == POWER_S3) { + if (time_cnt < 2) { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 1; + br[EC_LED_COLOR_AMBER] = 0; + } else { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + if (time_cnt > 3) + time_cnt = 0; + } + break; + } else if (powerstate == POWER_S5 || powerstate == POWER_G3) { + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + } break; - case PWR_STATE_ERROR: - br[EC_LED_COLOR_RED] = 255; + case LED_PWRS_ERROR: + if (powerstate == POWER_S0) { + if (time_cnt < 1) { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 1; + } else { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + if (time_cnt > 1) + time_cnt = 0; + } + break; + } else if (powerstate == POWER_S3) { + if (time_cnt < 2) { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 1; + br[EC_LED_COLOR_AMBER] = 0; + } else { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + if (time_cnt > 3) + time_cnt = 0; + } + break; + } else if (powerstate == POWER_S5 || powerstate == POWER_G3) { + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + } break; default: /* Other states don't alter LED behavior */ return; } - if (prv_r == br[EC_LED_COLOR_RED] && - prv_g == br[EC_LED_COLOR_GREEN]) + if (prv_white == br[EC_LED_COLOR_WHITE] && + prv_amber == br[EC_LED_COLOR_AMBER]) return; - prv_r = br[EC_LED_COLOR_RED]; - prv_g = br[EC_LED_COLOR_GREEN]; + prv_white = br[EC_LED_COLOR_WHITE]; + prv_amber = br[EC_LED_COLOR_AMBER]; led_set_brightness(EC_LED_ID_BATTERY_LED, br); } @@ -74,50 +135,40 @@ void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) if (led_id != EC_LED_ID_BATTERY_LED) return; - brightness_range[EC_LED_COLOR_RED] = MT6370_LED_BRIGHTNESS_MAX; - brightness_range[EC_LED_COLOR_GREEN] = MT6370_LED_BRIGHTNESS_MAX; + brightness_range[EC_LED_COLOR_WHITE] = MT6370_LED_BRIGHTNESS_MAX; + brightness_range[EC_LED_COLOR_AMBER] = MT6370_LED_BRIGHTNESS_MAX; } int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { - uint8_t red, green; + uint8_t white, amber; if (led_id != EC_LED_ID_BATTERY_LED) return EC_ERROR_INVAL; - red = brightness[EC_LED_COLOR_RED]; - green = brightness[EC_LED_COLOR_GREEN]; + white = brightness[EC_LED_COLOR_WHITE]; + amber = brightness[EC_LED_COLOR_AMBER]; - mt6370_led_set_brightness(LED_RED, red); - mt6370_led_set_brightness(LED_GREEN, green); + mt6370_led_set_brightness(LED_WHITE, white); + mt6370_led_set_brightness(LED_AMBER, amber); /* Enables LED sink power if necessary. */ - mt6370_led_set_color((red ? LED_MASK_RED : 0) | - (green ? LED_MASK_GREEN : 0)); + mt6370_led_set_color((white ? LED_MASK_WHITE : 0) | + (amber ? LED_MASK_AMBER : 0)); return EC_SUCCESS; } -/* - * Reset prv_chstate so that led can be updated immediately once - * auto-controlled. - */ -static void led_reset_auto_control(void) -{ - prv_chstate = PWR_STATE_INIT; -} - static void kakadu_led_init(void) { const enum mt6370_led_dim_mode dim = MT6370_LED_DIM_MODE_PWM; const enum mt6370_led_pwm_freq freq = MT6370_LED_PWM_FREQ1000; - mt6370_led_set_color(0); - mt6370_led_set_dim_mode(LED_RED, dim); - mt6370_led_set_dim_mode(LED_GREEN, dim); - mt6370_led_set_pwm_frequency(LED_RED, freq); - mt6370_led_set_pwm_frequency(LED_GREEN, freq); - mt6370_led_set_pwm_dim_duty(LED_RED, 12); - mt6370_led_set_pwm_dim_duty(LED_GREEN, 31); + mt6370_led_set_dim_mode(LED_WHITE, dim); + mt6370_led_set_dim_mode(LED_AMBER, dim); + mt6370_led_set_pwm_frequency(LED_WHITE, freq); + mt6370_led_set_pwm_frequency(LED_AMBER, freq); + mt6370_led_set_pwm_dim_duty(LED_WHITE, 255); + mt6370_led_set_pwm_dim_duty(LED_AMBER, 255); } DECLARE_HOOK(HOOK_INIT, kakadu_led_init, HOOK_PRIO_DEFAULT); @@ -126,8 +177,6 @@ static void led_second(void) { if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) kakadu_led_set_battery(); - else - led_reset_auto_control(); } DECLARE_HOOK(HOOK_SECOND, led_second, HOOK_PRIO_DEFAULT); @@ -140,13 +189,12 @@ __override void led_control(enum ec_led_id led_id, enum ec_led_state state) return; if (state == LED_STATE_RESET) { - led_reset_auto_control(); led_auto_control(EC_LED_ID_BATTERY_LED, 1); return; } if (state) - br[EC_LED_COLOR_GREEN] = 1; + br[EC_LED_COLOR_WHITE] = 1; led_auto_control(EC_LED_ID_BATTERY_LED, 0); led_set_brightness(EC_LED_ID_BATTERY_LED, br); diff --git a/board/kakadu/vif_override.xml b/board/kakadu/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kakadu/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kano/battery.c b/board/kano/battery.c new file mode 100644 index 0000000000..0b1d956173 --- /dev/null +++ b/board/kano/battery.c @@ -0,0 +1,67 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "compile_time_macros.h" + +/* + * Battery info for all Kano battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* LGC AP19B8M Battery Information */ + [BATTERY_AP19B8M] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G024", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13350, + .voltage_normal = 11610, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AP19B8M; diff --git a/board/kano/board.c b/board/kano/board.c new file mode 100644 index 0000000000..0d40a655bb --- /dev/null +++ b/board/kano/board.c @@ -0,0 +1,121 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} + +/* keyboard factory test */ +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/kano/board.h b/board/kano/board.h new file mode 100644 index 0000000000..156df67af0 --- /dev/null +++ b/board/kano/board.h @@ -0,0 +1,227 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Kano board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* LED */ +#define CONFIG_LED_ONOFF_STATES + +/* Sensors */ +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel */ +#define CONFIG_ACCELGYRO_ICM_COMM_I2C +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_BMI260 +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +/* Lid accel */ +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_ACCEL_KX022 +#define CONFIG_ACCEL_BMA4XX + +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* Keyboard */ +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_FACTORY_TEST + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_USBC_RETIMER_INTEL_BB + +#define CONFIG_USBC_PPC_SYV682X + +#undef CONFIG_USB_PD_TCPM_NCT38XX +#define CONFIG_USB_PD_TCPM_RT1715 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_ACCEL NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_C2_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_C2_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* + * see b/174768555#comment22 + */ +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x54 +/* SOC facing Burnside Bridge retimer */ +#define USBC_PORT_C1_SOC_BB_RETIMER_I2C_ADDR 0x55 +/* Type-C connector facing Burnside Bridge retimer */ +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x56 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_FAN, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_FAN, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { LID_ACCEL = 0, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum battery_type { BATTERY_AP19B8M, BATTERY_TYPE_COUNT }; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +void motion_interrupt(enum gpio_signal signal); + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +extern const int keyboard_factory_scan_pins[][2]; +extern const int keyboard_factory_scan_pins_used; +#endif + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/kano/build.mk b/board/kano/build.mk new file mode 100644 index 0000000000..0393829e6e --- /dev/null +++ b/board/kano/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/kano/charger.c b/board/kano/charger.c new file mode 100644 index 0000000000..b86d92965b --- /dev/null +++ b/board/kano/charger.c @@ -0,0 +1,80 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/kano/ec.tasklist b/board/kano/ec.tasklist new file mode 100644 index 0000000000..64edf7bf2e --- /dev/null +++ b/board/kano/ec.tasklist @@ -0,0 +1,30 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(2) | BIT(0)), BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/kano/fans.c b/board/kano/fans.c new file mode 100644 index 0000000000..4ae6edf1c3 --- /dev/null +++ b/board/kano/fans.c @@ -0,0 +1,50 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/180681346): need to update for real fan + * + * Prototype fan spins at about 7200 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2400, + .rpm_start = 2400, + .rpm_max = 6000, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/kano/fw_config.c b/board/kano/fw_config.c new file mode 100644 index 0000000000..f04fd0063b --- /dev/null +++ b/board/kano/fw_config.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union kano_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for kano if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union kano_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, + .thermal_solution = THERMAL_SOLUTION_15W, +}; + +/**************************************************************************** + * Kano FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* + * Early boards have a zero'd out FW_CONFIG, so replace + * it with a sensible default value. + */ + if (fw_config.raw_value == 0) { + CPRINTS("CBI: FW_CONFIG is zero, using board defaults"); + fw_config = fw_config_defaults; + } + } +} + +union kano_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +bool ec_cfg_has_kblight(void) +{ + return (fw_config.kb_bl == KEYBOARD_BACKLIGHT_ENABLED); +} + +enum ec_cfg_thermal_solution_type ec_cfg_thermal_solution(void) +{ + return fw_config.thermal_solution; +} diff --git a/board/kano/fw_config.h b/board/kano/fw_config.h new file mode 100644 index 0000000000..9f0c1c3373 --- /dev/null +++ b/board/kano/fw_config.h @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_KANO_FW_CONFIG_H_ +#define __BOARD_KANO_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Kano board. + * + * Source of truth is the project/brya/kano/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_thermal_solution_type { + THERMAL_SOLUTION_15W = 0, + THERMAL_SOLUTION_28W = 1 +}; + +union kano_cbi_fw_config { + struct { + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t ufc : 2; + uint32_t stylus : 1; + enum ec_cfg_thermal_solution_type thermal_solution : 1; + uint32_t reserved_1 : 24; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union kano_cbi_fw_config get_fw_config(void); + +/** + * Check if the FW_CONFIG has enabled keyboard backlight. + * + * @return true if board supports keyboard backlight, false if the board + * doesn't support it. + */ +bool ec_cfg_has_kblight(void); + +/** + * Read the thermal solution config. + * + * @return thermal solution config. + */ +enum ec_cfg_thermal_solution_type ec_cfg_thermal_solution(void); + +#endif /* __BOARD_KANO_FW_CONFIG_H_ */ diff --git a/board/kano/gpio.inc b/board/kano/gpio.inc new file mode 100644 index 0000000000..2ace5cbbca --- /dev/null +++ b/board/kano/gpio.inc @@ -0,0 +1,135 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_IMU_INT_R_L, PIN(5, 6), GPIO_SEL_1P8V | GPIO_INT_FALLING, motion_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ + +/* Pre-configured PSL balls: J8 K6 */ + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +GPIO(USB_C0_OC_ODL, PIN(D, 4), GPIO_ODR_HIGH) +GPIO(USB_C0_FRS_EN, PIN(6, 0), GPIO_LOW) +GPIO(USB_C0_RT_RST_ODL, PIN(C, 2), GPIO_ODR_LOW) + +GPIO(USB_C1_OC_ODL, PIN(E, 1), GPIO_ODR_HIGH) diff --git a/board/kano/i2c.c b/board/kano/i2c.c new file mode 100644 index 0000000000..70ca87f1b0 --- /dev/null +++ b/board/kano/i2c.c @@ -0,0 +1,77 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_ACCEL, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,2", + .port = I2C_PORT_USB_C0_C2_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,2", + .port = I2C_PORT_USB_C0_C2_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,2", + .port = I2C_PORT_USB_C0_C2_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/kano/keyboard.c b/board/kano/keyboard.c new file mode 100644 index 0000000000..3a15831adc --- /dev/null +++ b/board/kano/keyboard.c @@ -0,0 +1,47 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config kano_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &kano_kb; +} diff --git a/board/kano/led.c b/board/kano/led.c new file mode 100644 index 0000000000..6539ec3819 --- /dev/null +++ b/board/kano/led.c @@ -0,0 +1,84 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * Power and battery LED control for kano + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/kano/pwm.c b/board/kano/pwm.c new file mode 100644 index 0000000000..3286e37631 --- /dev/null +++ b/board/kano/pwm.c @@ -0,0 +1,40 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 25000, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn on the fan at 50%. + */ + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/kano/sensors.c b/board/kano/sensors.c new file mode 100644 index 0000000000..cce5adcef9 --- /dev/null +++ b/board/kano/sensors.c @@ -0,0 +1,413 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc_chip.h" +#include "common.h" +#include "driver/accel_bma422.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi260.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "fw_config.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_FAN] = { + .name = "TEMP_FAN", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +static struct kionix_accel_data g_kx022_data; +static struct icm_drv_data_t g_icm426xx_data; +static struct bmi_drv_data_t g_bmi260_data; +static struct accelgyro_saved_data_t g_bma422_data; + +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI260 = 1, + BASE_GYRO_ICM426XX = 2, +}; + +static enum base_accelgyro_type base_accelgyro_config; + +/* + * TODO:(b/197200940): Verify lid and base orientation + * matrix on proto board. + */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t lid_bma422_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +static const mat33_fp_t base_bmi260_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static struct motion_sensor_t bmi260_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .rot_standard_ref = &base_bmi260_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +static struct motion_sensor_t bmi260_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_bmi260_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, +}; + +static struct motion_sensor_t bma422_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_SECONDARY, + .rot_standard_ref = &lid_bma422_standard_ref, + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .default_range = 2, /* g, enough for laptop. */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void baseboard_sensors_detect(void) +{ + int ret, val; + + if (base_accelgyro_config != BASE_GYRO_NONE) + return; + + ret = i2c_read8(I2C_PORT_ACCEL, BMA4_I2C_ADDR_SECONDARY, + BMA4_CHIP_ID_ADDR, &val); + if (ret == 0 && val == BMA422_CHIP_ID) { + motion_sensors[LID_ACCEL] = bma422_lid_accel; + ccprints("LID_ACCEL is BMA422"); + } else + ccprints("LID_ACCEL is KX022"); + + ret = bmi_read8(I2C_PORT_ACCEL, BMI260_ADDR0_FLAGS, BMI260_CHIP_ID, + &val); + if (ret == 0 && val == BMI260_CHIP_ID_MAJOR) { + motion_sensors[BASE_ACCEL] = bmi260_base_accel; + motion_sensors[BASE_GYRO] = bmi260_base_gyro; + base_accelgyro_config = BASE_GYRO_BMI260; + ccprints("BASE ACCEL is BMI260"); + } else { + base_accelgyro_config = BASE_GYRO_ICM426XX; + ccprints("BASE ACCEL IS ICM426XX"); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, baseboard_sensors_detect, HOOK_PRIO_DEFAULT); + +static void baseboard_sensors_init(void) +{ + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_R_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +void motion_interrupt(enum gpio_signal signal) +{ + if (base_accelgyro_config == BASE_GYRO_NONE) + return; + if (base_accelgyro_config == BASE_GYRO_BMI260) + bmi260_interrupt(signal); + else + icm426xx_interrupt(signal); +} + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC }, + [TEMP_SENSOR_2_FAN] = { .name = "FAN", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_FAN }, + [TEMP_SENSOR_3_CHARGER] = { .name = "CHARGER", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + }, \ + .temp_fan_off = C_TO_K(37), \ + .temp_fan_max = C_TO_K(90), \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan = THERMAL_FAN; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_FAN_28W \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + }, \ + .temp_fan_off = C_TO_K(37), \ + .temp_fan_max = C_TO_K(62), \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan_28w = + THERMAL_FAN_28W; + +/* + * Set value to zero to disable charger thermal control. + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_FAN] = THERMAL_FAN, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +static void setup_thermal(void) +{ + unsigned int table = ec_cfg_thermal_solution(); + /* Configure Fan */ + switch (table) { + /* 28w CPU fan table */ + case THERMAL_SOLUTION_28W: + cprints(CC_THERMAL, "Fan table set to 28w CPU scheme"); + thermal_params[TEMP_SENSOR_2_FAN] = thermal_fan_28w; + break; + /* Default fan table */ + case THERMAL_SOLUTION_15W: + default: + cprints(CC_THERMAL, "Fan table set to 15w CPU scheme"); + break; + } +} +/* setup_thermal should be called before HOOK_INIT/HOOK_PRIO_DEFAULT */ +DECLARE_HOOK(HOOK_INIT, setup_thermal, HOOK_PRIO_DEFAULT - 1); diff --git a/board/kano/usbc_config.c b/board/kano/usbc_config.c new file mode 100644 index 0000000000..d725ab91d2 --- /dev/null +++ b/board/kano/usbc_config.c @@ -0,0 +1,304 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM536A0 */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +struct usb_mux_chain soc_side_bb_retimer_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_SOC_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C2_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &soc_side_bb_retimer_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_2_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum gpio_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = GPIO_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C1) { + rst_signal = GPIO_USB_C1_RT_RST_R_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + gpio_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + gpio_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(GPIO_USB_C0_RT_RST_ODL, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(GPIO_USB_C0_RT_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_2; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} diff --git a/board/kano/usbc_config.h b/board/kano/usbc_config.h new file mode 100644 index 0000000000..72e26c31c1 --- /dev/null +++ b/board/kano/usbc_config.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Kano board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void config_usb_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/kano/vif_override.xml b/board/kano/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kano/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kappa/battery.c b/board/kappa/battery.c index c09ac72730..bd8f05b418 100644 --- a/board/kappa/battery.c +++ b/board/kappa/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,7 +9,7 @@ const struct board_batt_params board_battery_info[] = { /* Dynapack HIGHPOWER DAK124960-W110703HT Battery Information */ - [BATTERY_DANAPACK_HIGHPOWER] = { + [BATTERY_DYNAPACK_HIGHPOWER] = { .fuel_gauge = { .manuf_name = "333-2D-14-A", .ship_mode = { @@ -34,10 +34,11 @@ const struct board_batt_params board_battery_info[] = { .charging_max_c = 45, .discharging_min_c = -10, .discharging_max_c = 60, + .vendor_param_start = 0x70, }, }, /* Dynapack CosMX DAK124960-W0P0707HT Battery Information */ - [BATTERY_DANAPACK_COS] = { + [BATTERY_DYNAPACK_COS] = { .fuel_gauge = { .manuf_name = "333-2C-14-A", .ship_mode = { @@ -62,12 +63,42 @@ const struct board_batt_params board_battery_info[] = { .charging_max_c = 45, .discharging_min_c = -10, .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* LGC MPPHPPFO021C Battery Information, BMU RAJ240045 */ + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "313-42-14-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x43, + .reg_mask = 0x0003, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8700, /* mV */ + .voltage_normal = 7520, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, }, }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DANAPACK_HIGHPOWER; +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_HIGHPOWER; enum battery_present battery_hw_present(void) { diff --git a/board/kappa/board.c b/board/kappa/board.c index 89dd4648c6..4a6b2d282e 100644 --- a/board/kappa/board.c +++ b/board/kappa/board.c @@ -1,10 +1,9 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" #include "charge_manager.h" @@ -31,6 +30,7 @@ #include "it8801.h" #include "keyboard_scan.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "registers.h" @@ -38,41 +38,55 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { schedule_deferred_pd_interrupt(0 /* port */); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct i2c_port_t i2c_bitbang_ports[] = { - {"battery", 2, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA, .drv = &bitbang_drv}, + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, }; const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); @@ -80,13 +94,13 @@ const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * TODO(b/133200075): Tune this once we have the final performance * out of the driver and the i2c bus. @@ -105,8 +119,8 @@ struct keyboard_scan_config keyscan_config = { struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { [0] = { - .i2c_host_port = I2C_PORT_IO_EXPANDER_IT8801, - .i2c_slave_addr = IT8801_I2C_ADDR, + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, .drv = &it8801_ioexpander_drv, }, }; @@ -114,8 +128,7 @@ struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { /******************************************************************************/ /* SPI devices */ /* TODO: to be added once sensors land via CL:1714436 */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { @@ -131,15 +144,18 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -static void board_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -147,13 +163,16 @@ static void board_hpd_status(const struct usb_mux *me, host_set_single_event(EC_HOST_EVENT_USB_MUX); } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, }, }; @@ -183,7 +202,7 @@ int board_set_active_charge_port(int charge_port) if (board_vbus_source_enabled(charge_port)) return -1; break; - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -191,22 +210,11 @@ int board_set_active_charge_port(int charge_port) */ charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - int board_discharge_on_ac(int enable) { int ret, port; @@ -236,7 +244,7 @@ int pd_snk_is_vbus_provided(int port) void bc12_interrupt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } static void board_init(void) @@ -251,11 +259,6 @@ static void board_init(void) /* Enable TCPC alert interrupts */ gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); -#ifdef SECTION_IS_RW - /* Enable interrupts from BMI160 sensor. */ - gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); -#endif /* SECTION_IS_RW */ - /* Enable interrupt from PMIC. */ gpio_enable_interrupt(GPIO_PMIC_EC_RESETB); @@ -264,16 +267,6 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -/* Motion sensors */ -/* Mutexes */ -#ifdef SECTION_IS_RW -/* TODO: to be added once sensors land via CL:1714436 */ -struct motion_sensor_t motion_sensors[] = { -}; -const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -#endif /* SECTION_IS_RW */ - /* Called on AP S5 -> S3 transition */ static void board_chipset_startup(void) { @@ -287,25 +280,3 @@ static void board_chipset_shutdown(void) gpio_set_level(GPIO_EN_USBA_5V, 0); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); - -int battery_get_vendor_param(uint32_t param, uint32_t *value) -{ - int rv; - uint8_t data[16] = {}; - - /* only allow reading 0x70~0x7F, 16 byte data */ - if (param < 0x70 || param >= 0x80) - return EC_ERROR_ACCESS_DENIED; - - rv = sb_read_string(0x70, data, sizeof(data)); - if (rv) - return rv; - - *value = data[param - 0x70]; - return EC_SUCCESS; -} - -int battery_set_vendor_param(uint32_t param, uint32_t value) -{ - return EC_ERROR_UNIMPLEMENTED; -} diff --git a/board/kappa/board.h b/board/kappa/board.h index 81ac819cf9..0911d50951 100644 --- a/board/kappa/board.h +++ b/board/kappa/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,10 +11,9 @@ #define VARIANT_KUKUI_JACUZZI #define VARIANT_KUKUI_BATTERY_SMART #define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32F098 -#ifndef SECTION_IS_RW #define VARIANT_KUKUI_NO_SENSORS -#endif /* SECTION_IS_RW */ #include "baseboard.h" @@ -23,8 +22,12 @@ #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_BATTERY_VENDOR_PARAM +#define CONFIG_BATTERY_V2 +#define CONFIG_BATTERY_COUNT 1 #define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_BC12_DETECT_PI3USB9201 @@ -44,45 +47,25 @@ #define CONFIG_USB_MUX_IT5205 -/* Motion Sensors */ -#ifdef SECTION_IS_RW -#define CONFIG_MAG_BMI_BMM150 -#define CONFIG_ACCELGYRO_SEC_ADDR_FLAGS BMM150_ADDR0_FLAGS -#define CONFIG_MAG_CALIBRATE -#define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS -#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) -#define CONFIG_ALS - -#define ALS_COUNT 1 -#define CONFIG_ALS_TCS3400 -#define CONFIG_ALS_TCS3400_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) -#define CONFIG_ALS_TCS3400_EMULATED_IRQ_EVENT -#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(CLEAR_ALS) - -#endif /* SECTION_IS_RW */ +#undef CONFIG_GMR_TABLET_MODE +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH /* I2C ports */ -#define I2C_PORT_BC12 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_BATTERY 2 -#define I2C_PORT_CHARGER 1 -#define I2C_PORT_IO_EXPANDER_IT8801 1 -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_BATTERY 2 +#define I2C_PORT_CHARGER 1 +#define I2C_PORT_KB_DISCRETE 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY -/* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -/* Define the MKBP events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) #ifndef __ASSEMBLER__ @@ -118,8 +101,9 @@ enum charge_port { }; enum battery_type { - BATTERY_DANAPACK_HIGHPOWER, - BATTERY_DANAPACK_COS, + BATTERY_DYNAPACK_HIGHPOWER, + BATTERY_DYNAPACK_COS, + BATTERY_LGC, BATTERY_TYPE_COUNT, }; @@ -134,7 +118,6 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void bc12_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); /* returns the i2c port number of charger */ int board_get_charger_i2c(void); diff --git a/board/kappa/build.mk b/board/kappa/build.mk index e449fce9fc..80c34a4e46 100644 --- a/board/kappa/build.mk +++ b/board/kappa/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/kappa/ec.tasklist b/board/kappa/ec.tasklist index b695d05a71..3705823bac 100644 --- a/board/kappa/ec.tasklist +++ b/board/kappa/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,7 +11,6 @@ TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS_RW(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/kappa/gpio.inc b/board/kappa/gpio.inc index 1f3bd6cd9d..d7d6c5267b 100644 --- a/board/kappa/gpio.inc +++ b/board/kappa/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -21,8 +21,6 @@ GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, chipset_reset_request_interrupt) -GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, - bmi160_interrupt) GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, emmc_cmd_interrupt) GPIO_INT(SPI1_NSS, PIN(A, 15), GPIO_INT_BOTH | GPIO_PULL_UP, @@ -37,8 +35,6 @@ GPIO_INT(IT8801_SMB_INT, PIN(A, 8), GPIO_INT_FALLING | GPIO_PULL_UP, io_expander_it8801_interrupt) /* KB_INT_ODL */ GPIO_INT(AP_EC_WATCHDOG_L, PIN(D, 2), GPIO_INT_FALLING, chipset_watchdog_interrupt) -GPIO_INT(TABLET_MODE_L, PIN(B, 11), GPIO_INT_BOTH, - gmr_tablet_switch_isr) /* Unimplemented interrupts */ GPIO(ALS_RGB_INT_ODL, PIN(C, 10), GPIO_INPUT) diff --git a/board/kappa/led.c b/board/kappa/led.c index 5b65d7b948..e17657d421 100644 --- a/board/kappa/led.c +++ b/board/kappa/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -14,7 +14,7 @@ #define BAT_LED_ON 0 #define BAT_LED_OFF 1 -const enum ec_led_id supported_led_ids[] = {EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -22,7 +22,7 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int led_set_color_battery(enum led_color color) @@ -82,32 +82,30 @@ static void led_set_battery(void) { static int battery_ticks; static int power_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; /* override battery led for system suspend */ - if (chipset_in_state(CHIPSET_STATE_SUSPEND | - CHIPSET_STATE_STANDBY) && - charge_get_state() != PWR_STATE_CHARGE) { - led_set_color_battery(power_ticks++ & 0x2 ? - LED_WHITE : LED_OFF); + if (chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_STANDBY) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + led_set_color_battery(power_ticks++ & 0x2 ? LED_WHITE : + LED_OFF); return; } power_ticks = 0; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: led_set_color_battery(LED_AMBER); break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { led_set_color_battery(LED_WHITE); break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE: + __fallthrough; + case LED_PWRS_DISCHARGE: /* * Blink white light (1 sec on, 1 sec off) * when battery capacity is less than 10% @@ -118,19 +116,19 @@ static void led_set_battery(void) else led_set_color_battery(LED_OFF); break; - case PWR_STATE_ERROR: - led_set_color_battery( - (battery_ticks % 0x2) ? LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + led_set_color_battery((battery_ticks % 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: led_set_color_battery(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - led_set_color_battery( - (battery_ticks & 0x2) ? LED_AMBER : LED_OFF); - else - led_set_color_battery(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + led_set_color_battery(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + led_set_color_battery((battery_ticks & 0x2) ? LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ diff --git a/board/kappa/vif_override.xml b/board/kappa/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kappa/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/karma/board.c b/board/karma/board.c index 7bac35bd64..df053ad782 100644 --- a/board/karma/board.c +++ b/board/karma/board.c @@ -1,16 +1,17 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "console.h" #include "gpio.h" +#include "hooks.h" #include "oz554.h" -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) -__override void oz554_board_init(void) +void oz554_board_init(void) { int pin_status = 0; @@ -40,3 +41,10 @@ __override void oz554_board_init(void) break; } } + +static void init_oz554(void) +{ + oz554_board_init(); + gpio_enable_interrupt(GPIO_PANEL_BACKLIGHT_EN); +} +DECLARE_HOOK(HOOK_INIT, init_oz554, HOOK_PRIO_DEFAULT); diff --git a/board/karma/board.h b/board/karma/board.h index 372b18509b..c3b6cd074a 100644 --- a/board/karma/board.h +++ b/board/karma/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/karma/build.mk b/board/karma/build.mk index 2554425920..bee5d9f886 100644 --- a/board/karma/build.mk +++ b/board/karma/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/karma/ec.tasklist b/board/karma/ec.tasklist index ca4e3b5ee6..829c9f19bc 100644 --- a/board/karma/ec.tasklist +++ b/board/karma/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/karma/gpio.inc b/board/karma/gpio.inc index 1b265ed6ca..2f0fef053e 100644 --- a/board/karma/gpio.inc +++ b/board/karma/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,7 +11,7 @@ GPIO_INT(USB_C0_PD_INT_ODL, PIN(3, 7), GPIO_INT_FALLING | GPIO_PULL_UP, tcpc_alert_event) GPIO_INT(AC_PRESENT, PIN(C, 1), GPIO_INT_BOTH, extpower_interrupt) GPIO_INT(POWER_BUTTON_L, PIN(0, 4), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) /* MECH_PWR_BTN_ODL */ -GPIO_INT(PANEL_BACKLIGHT_EN, PIN(4, 4), GPIO_INT_RISING, backlight_enable_interrupt) +GPIO_INT(PANEL_BACKLIGHT_EN, PIN(4, 4), GPIO_INT_RISING, oz554_interrupt) GPIO_INT(PCH_SLP_S0_L, PIN(7, 5), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PCH_SLP_SUS_L, PIN(6, 2), GPIO_INT_BOTH, power_signal_interrupt) diff --git a/board/karma/vif_override.xml b/board/karma/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/karma/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/katsu/board.c b/board/katsu/board.c new file mode 100644 index 0000000000..a7f7347814 --- /dev/null +++ b/board/katsu/board.c @@ -0,0 +1,452 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "charger_mt6370.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/charger/rt946x.h" +#include "driver/sync.h" +#include "driver/tcpm/mt6370.h" +#include "driver/usb_mux/it5205.h" +#include "extpower.h" +#include "gesture.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "lid_switch.h" +#include "panic.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "registers.h" +#include "spi.h" +#include "system.h" +#include "task.h" +#include "tcpm/tcpm.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd_policy.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +static void tcpc_alert_event(enum gpio_signal signal) +{ + schedule_deferred_pd_interrupt(0 /* port */); +} + +static void gauge_interrupt(enum gpio_signal signal) +{ + task_wake(TASK_ID_CHARGER); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, + [ADC_BATT_ID] = { "BATT_ID", 3300, 4096, 0, STM32_AIN(7) }, + [ADC_POGO_ADC_INT_L] = { "POGO_ADC_INT_L", 3300, 4096, 0, + STM32_AIN(6) }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* power signal list. Must match order of enum power_signal. */ +const struct power_signal_info power_signal_list[] = { + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, +}; +BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); + +/******************************************************************************/ +/* SPI devices */ +const struct spi_device_t spi_devices[] = {}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +/******************************************************************************/ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = MT6370_TCPC_I2C_ADDR_FLAGS, + }, + .drv = &mt6370_tcpm_drv, + }, +}; + +struct mt6370_thermal_bound thermal_bound = { + .target = 80, + .err = 4, +}; + +static void board_hpd_update(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) +{ + /* This driver does not use host command ACKs */ + *ack_required = false; + + /* + * svdm_dp_attention() did most of the work, we only need to notify + * host here. + */ + host_set_single_event(EC_HOST_EVENT_USB_MUX); +} + +__override const struct rt946x_init_setting *board_rt946x_init_setting(void) +{ + static const struct rt946x_init_setting battery_init_setting = { + .eoc_current = 140, + .mivr = 4000, + .ircmp_vclamp = 32, + .ircmp_res = 25, + .boost_voltage = 5050, + .boost_current = 1500, + }; + + return &battery_init_setting; +} + +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_update, + }, + }, +}; + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} + +static int force_discharge; + +int board_set_active_charge_port(int charge_port) +{ + CPRINTS("New chg p%d", charge_port); + + /* ignore all request when discharge mode is on */ + if (force_discharge && charge_port != CHARGE_PORT_NONE) + return EC_SUCCESS; + + switch (charge_port) { + case CHARGE_PORT_USB_C: + /* Don't charge from a source port */ + if (board_vbus_source_enabled(charge_port)) + return -1; + gpio_set_level(GPIO_EN_POGO_CHARGE_L, 1); + gpio_set_level(GPIO_EN_USBC_CHARGE_L, 0); + break; +#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 + case CHARGE_PORT_POGO: + gpio_set_level(GPIO_EN_USBC_CHARGE_L, 1); + gpio_set_level(GPIO_EN_POGO_CHARGE_L, 0); + break; +#endif + default: + /* + * To ensure the fuel gauge (max17055) is always powered + * even when battery is disconnected, keep VBAT rail on but + * set the charging current to minimum. + */ + gpio_set_level(GPIO_EN_POGO_CHARGE_L, 1); + gpio_set_level(GPIO_EN_USBC_CHARGE_L, 1); + charger_set_current(CHARGER_SOLO, 0); + break; + } + + return EC_SUCCESS; +} + +int board_discharge_on_ac(int enable) +{ + int ret, port; + + if (enable) { + port = CHARGE_PORT_NONE; + } else { + /* restore the charge port state */ + port = charge_manager_get_override(); + if (port == OVERRIDE_OFF) + port = charge_manager_get_active_charge_port(); + } + + ret = charger_discharge_on_ac(enable); + if (ret) + return ret; + + if (force_discharge && !enable) + rt946x_toggle_bc12_detection(); + + force_discharge = enable; + return board_set_active_charge_port(port); +} + +int extpower_is_present(void) +{ + /* + * The charger will indicate VBUS presence if we're sourcing 5V, + * so exclude such ports. + */ + int usb_c_extpower_present; + static int prev_usb_c_extpower_present; + + if (board_vbus_source_enabled(CHARGE_PORT_USB_C)) + usb_c_extpower_present = 0; + else + usb_c_extpower_present = + tcpm_check_vbus_level(CHARGE_PORT_USB_C, VBUS_PRESENT); + + if (prev_usb_c_extpower_present != usb_c_extpower_present) { + if (usb_c_extpower_present) + host_set_single_event(EC_HOST_EVENT_AC_CONNECTED); + else + host_set_single_event(EC_HOST_EVENT_AC_DISCONNECTED); + prev_usb_c_extpower_present = usb_c_extpower_present; + } + + return usb_c_extpower_present; +} + +int pd_snk_is_vbus_provided(int port) +{ + if (port) + panic("Invalid charge port\n"); + + return rt946x_is_vbus_ready(); +} + +static void board_init(void) +{ + /* If the reset cause is external, pulse PMIC force reset. */ + if (system_get_reset_flags() == EC_RESET_FLAG_RESET_PIN) { + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 0); + msleep(100); + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 1); + } + + /* Enable TCPC alert interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + + /* Enable charger interrupts */ + gpio_enable_interrupt(GPIO_CHARGER_INT_ODL); + +#ifdef SECTION_IS_RW + /* Enable interrupts from ICM40608 sensor. */ + gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); + + /* Enable interrupt for the camera vsync. */ + gpio_enable_interrupt(GPIO_SYNC_INT); +#endif /* SECTION_IS_RW */ + + /* Enable interrupt from PMIC. */ + gpio_enable_interrupt(GPIO_PMIC_EC_RESETB); + + /* Enable gauge interrupt from max17055 */ + gpio_enable_interrupt(GPIO_GAUGE_INT_ODL); + + /* + * Fix backlight led maximum current: + * tolerance 120mA * 0.75 = 90mA. + * (b/133655155) + */ + mt6370_backlight_set_dim(MT6370_BLDIM_DEFAULT * 3 / 4); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_rev_init(void) +{ + /* Board revision specific configs. */ + + /* + * It's a P1 pin BOOTBLOCK_MUX_OE, also a P2 pin BC12_DET_EN. + * Keep this pin defaults to P1 setting since that eMMC enabled with + * High-Z stat. + */ + /* TODO */ + /* Put initial code here for different EC board reversion */ +} +DECLARE_HOOK(HOOK_INIT, board_rev_init, HOOK_PRIO_INIT_ADC + 1); + +void sensor_board_proc_double_tap(void) +{ + CPRINTS("Detect double tap"); +} + +/* Motion sensors */ +/* Mutexes */ +#ifndef VARIANT_KUKUI_NO_SENSORS +static struct mutex g_lid_mutex; + +static struct icm_drv_data_t g_icm426xx_data; + +/* Matrix to rotate accelerometer into standard reference frame */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t motion_sensors[] = { + /* + * Note: ICM40608: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [LID_ACCEL] = { + .name = "Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm426xx_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* Enable accel in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = TAP_ODR, + .ec_rate = 100 * MSEC, + }, + /* For double tap detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = TAP_ODR, + .ec_rate = 100 * MSEC, + }, + }, + }, + [LID_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm426xx_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, + }, + [VSYNC] = { + .name = "Camera vsync", + .active_mask = SENSOR_ACTIVE_S0, + .chip = MOTIONSENSE_CHIP_GPIO, + .type = MOTIONSENSE_TYPE_SYNC, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &sync_drv, + .default_range = 0, + .min_frequency = 0, + .max_frequency = 1, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +#endif /* VARIANT_KUKUI_NO_SENSORS */ + +/* + * Return if VBUS is sagging too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + /* + * Though we have a more tolerant range (3.9V~13.4V), setting 4400 to + * prevent from a bad charger crashed. + * + * TODO(b:131284131): mt6370 VBUS reading is not accurate currently. + * Vendor will provide a workaround solution to fix the gap between ADC + * reading and actual voltage. After the workaround applied, we could + * try to raise this value to 4600. (when it says it read 4400, it is + * actually close to 4600) + */ + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + return voltage < 4400; +} + +__override int board_charge_port_is_sink(int port) +{ + /* TODO(b:128386458): Check POGO_ADC_INT_L */ + return 1; +} + +__override int board_charge_port_is_connected(int port) +{ + return gpio_get_level(GPIO_POGO_VBUS_PRESENT); +} + +__override void +board_fill_source_power_info(int port, struct ec_response_usb_pd_power_info *r) +{ + r->meas.voltage_now = 3300; + r->meas.voltage_max = 3300; + r->meas.current_max = 1500; + r->meas.current_lim = 1500; + r->max_power = r->meas.voltage_now * r->meas.current_max; +} + +/* b/207456334: bugged reserved bits causes device not charging */ +static void mt6370_reg_fix(void) +{ + i2c_update8(chg_chips[CHARGER_SOLO].i2c_port, + chg_chips[CHARGER_SOLO].i2c_addr_flags, RT946X_REG_CHGCTRL1, + BIT(3) | BIT(5), MASK_CLR); + i2c_update8(chg_chips[CHARGER_SOLO].i2c_port, + chg_chips[CHARGER_SOLO].i2c_addr_flags, RT946X_REG_CHGCTRL2, + BIT(5) | BIT(RT946X_SHIFT_BATDET_DIS_DLY), MASK_CLR); +} +DECLARE_HOOK(HOOK_INIT, mt6370_reg_fix, HOOK_PRIO_DEFAULT); diff --git a/board/katsu/board.h b/board/katsu/board.h new file mode 100644 index 0000000000..6f53801ffc --- /dev/null +++ b/board/katsu/board.h @@ -0,0 +1,130 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Configuration for Katsu */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define BQ27541_ADDR 0x55 +#define VARIANT_KUKUI_BATTERY_BQ27541 +#define VARIANT_KUKUI_POGO_KEYBOARD + +#define VARIANT_KUKUI_CHARGER_MT6370 +#define VARIANT_KUKUI_EC_STM32F098 +#define VARIANT_KUKUI_TABLET_PWRBTN + +#ifndef SECTION_IS_RW +#define VARIANT_KUKUI_NO_SENSORS +#endif /* SECTION_IS_RW */ + +#include "baseboard.h" + +#define CONFIG_USB_MUX_IT5205 +#define CONFIG_VOLUME_BUTTONS +#define CONFIG_USB_MUX_RUNTIME_CONFIG + +/* Battery */ +#define BATTERY_DESIRED_CHARGING_CURRENT 3500 /* mA */ + +#define CONFIG_CHARGER_MT6370_BACKLIGHT + +/* Motion Sensors */ +#ifdef SECTION_IS_RW +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +/* Camera VSYNC */ +#define CONFIG_SYNC +#define CONFIG_SYNC_COMMAND +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#endif /* SECTION_IS_RW */ + +/* I2C ports */ +#define I2C_PORT_CHARGER 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_BATTERY 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_ACCEL 1 +#define I2C_PORT_BC12 1 + +/* Route sbs host requests to virtual battery driver */ +#define VIRTUAL_BATTERY_ADDR_FLAGS 0x0B + +/* MKBP */ +#define CONFIG_MKBP_INPUT_DEVICES +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_EVENT_WAKEUP_MASK \ + (BIT(EC_MKBP_EVENT_SENSOR_FIFO) | BIT(EC_MKBP_EVENT_HOST_EVENT)) +#undef CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE)) + +#define PD_OPERATING_POWER_MW 15000 + +#ifndef __ASSEMBLER__ + +enum adc_channel { + /* Real ADC channels begin here */ + ADC_BOARD_ID = 0, + ADC_EC_SKU_ID, + ADC_BATT_ID, + ADC_POGO_ADC_INT_L, + ADC_CH_COUNT +}; + +/* power signal definitions */ +enum power_signal { + AP_IN_S3_L, + PMIC_PWR_GOOD, + + /* Number of signals */ + POWER_SIGNAL_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + LID_GYRO, + VSYNC, + SENSOR_COUNT, +}; + +enum charge_port { + CHARGE_PORT_USB_C, +}; + +#include "gpio_signal.h" +#include "registers.h" + +#ifdef SECTION_IS_RO +/* Interrupt handler for emmc task */ +void emmc_cmd_interrupt(enum gpio_signal signal); +#endif + +void board_reset_pd_mcu(void); +int board_get_version(void); +void pogo_adc_interrupt(enum gpio_signal signal); +int board_discharge_on_ac(int enable); + +/* Enable double tap detection */ +#define CONFIG_GESTURE_DETECTION +#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP +#define CONFIG_GESTURE_TAP_SENSOR 0 +#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP_FOR_HOST +#define CONFIG_GESTURE_SAMPLING_INTERVAL_MS 5 +#define CONFIG_GESTURE_TAP_THRES_MG 100 +#define CONFIG_GESTURE_TAP_MAX_INTERSTICE_T 500 +#define CONFIG_GESTURE_DETECTION_MASK BIT(CONFIG_GESTURE_TAP_SENSOR) + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/katsu/build.mk b/board/katsu/build.mk new file mode 100644 index 0000000000..52ee1b3354 --- /dev/null +++ b/board/katsu/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# +# +# STmicro STM32F098VC +CHIP:=stm32 +CHIP_FAMILY:=stm32f0 +CHIP_VARIANT:=stm32f09x +BASEBOARD:=kukui + +board-y=board.o led.o diff --git a/board/katsu/ec.tasklist b/board/katsu/ec.tasklist new file mode 100644 index 0000000000..8be28c373d --- /dev/null +++ b/board/katsu/ec.tasklist @@ -0,0 +1,20 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG, usb_charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, 1024) \ + TASK_ALWAYS_RO(EMMC, emmc_task, NULL, LARGER_TASK_STACK_SIZE) + diff --git a/board/katsu/gpio.inc b/board/katsu/gpio.inc new file mode 100644 index 0000000000..82f7ddb3af --- /dev/null +++ b/board/katsu/gpio.inc @@ -0,0 +1,107 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(B, 1), GPIO_INT_FALLING | GPIO_PULL_UP, + tcpc_alert_event) +GPIO_INT(VOLUME_UP_L, PIN(B, 10), GPIO_INT_BOTH | GPIO_PULL_UP, + button_interrupt) /* EC_VOLUP_BTN_ODL */ +GPIO_INT(VOLUME_DOWN_L, PIN(B, 11), GPIO_INT_BOTH | GPIO_PULL_UP, + button_interrupt) /* EC_VOLDN_BTN_ODL */ +GPIO_INT(POWER_BUTTON_L, PIN(A, 0), GPIO_INT_BOTH | GPIO_PULL_UP, + power_button_interrupt) /* EC_PWR_BTN_ODL */ + +GPIO_INT(AP_IN_SLEEP_L, PIN(C, 12), GPIO_INT_BOTH | GPIO_PULL_DOWN, + power_signal_interrupt) +GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, + power_signal_interrupt) +GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, + chipset_reset_request_interrupt) +GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 2), GPIO_INT_FALLING, + chipset_watchdog_interrupt) + +GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, + icm426xx_interrupt) +GPIO_INT(CHARGER_INT_ODL, PIN(C, 13), GPIO_INT_FALLING | GPIO_PULL_UP, + rt946x_interrupt) +GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, + emmc_cmd_interrupt) +GPIO_INT(SPI1_NSS, PIN(A, 15), GPIO_INT_BOTH | GPIO_PULL_UP, + spi_event) +GPIO_INT_RW(SYNC_INT, PIN(A, 8), GPIO_INT_RISING | GPIO_PULL_DOWN, + sync_interrupt) +GPIO_INT(HALL_INT_L, PIN(C, 5), GPIO_INT_BOTH, + lid_interrupt) +GPIO_INT(GAUGE_INT_ODL, PIN(C, 9), GPIO_INT_FALLING | GPIO_PULL_UP, + gauge_interrupt) +GPIO_INT(POGO_ADC_INT_L, PIN(A, 6), GPIO_INT_BOTH, + pogo_adc_interrupt) + +/* unused */ +GPIO(POGO_VBUS_PRESENT, PIN(A, 14), GPIO_INPUT) +/* unused after board rev 5 */ +GPIO(USB_C0_DP_POLARITY, PIN(C, 14), GPIO_INPUT) +GPIO(USB_C0_DP_OE_L, PIN(A, 5), GPIO_INPUT) + + +/* Reset pins */ +GPIO(AP_SYS_RST_L, PIN(C, 11), GPIO_OUT_LOW) +GPIO(PMIC_WATCHDOG_L, PIN(C, 3), GPIO_OUT_LOW) +GPIO(PMIC_EN_ODL, PIN(C, 10), GPIO_ODR_HIGH) +GPIO(PMIC_FORCE_RESET_ODL, PIN(A, 2), GPIO_ODR_HIGH) +GPIO(MT6370_RST_L, PIN(F, 0), GPIO_OUT_LOW) + +/* + * I2C pins should be configured as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(I2C1_SCL, PIN(B, 8), GPIO_INPUT) +GPIO(I2C1_SDA, PIN(B, 9), GPIO_INPUT) +GPIO(I2C2_SCL, PIN(A, 11), GPIO_INPUT) +GPIO(I2C2_SDA, PIN(A, 12), GPIO_INPUT) + +/* Analog pins */ +GPIO(BATT_ID, PIN(A, 7), GPIO_ANALOG) +GPIO(BOARD_ID, PIN(C, 0), GPIO_ANALOG) +GPIO(EC_SKU_ID, PIN(B, 0), GPIO_ANALOG) + +/* Other input pins */ +GPIO(WP_L, PIN(C, 8), GPIO_INPUT) /* EC_FLASH_WP_ODL */ +GPIO(BOOT0, PIN(F, 11), GPIO_INPUT) +GPIO(CCD_MODE_ODL, PIN(A, 1), GPIO_INPUT) + +/* Other output pins */ +GPIO(ENTERING_RW, PIN(C, 6), GPIO_ODR_HIGH) /* EC_ENTERING_RW_ODL */ +GPIO(EC_INT_L, PIN(B, 12), GPIO_ODR_HIGH) /* EC_AP_INT_ODL */ +GPIO(EC_BOARD_ID_EN_L, PIN(C, 15), GPIO_ODR_HIGH) /* EC_BOARD_ID_EN_ODL */ +GPIO(USB_C0_HPD_OD, PIN(F, 1), GPIO_ODR_LOW) +GPIO(BOOTBLOCK_EN_L, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EN_PP3300_POGO, PIN(A, 13), GPIO_OUT_LOW) +GPIO(EN_POGO_CHARGE_L, PIN(B, 6), GPIO_OUT_HIGH) +GPIO(EN_USBC_CHARGE_L, PIN(C, 7), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBC, PIN(D, 2), GPIO_OUT_LOW) +GPIO(BC12_DET_EN, PIN(C, 4), GPIO_OUT_LOW) + +/* USART1: PA9/PA10 */ +ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, 0) +/* I2C MASTER: PB8/9 */ +ALTERNATE(PIN_MASK(B, 0x0300), 1, MODULE_I2C, GPIO_ODR_HIGH ) +/* I2C MASTER: PA11/12 */ +ALTERNATE(PIN_MASK(A, 0x1800), 5, MODULE_I2C, GPIO_ODR_HIGH ) +/* SPI SLAVE: PB3/4/5 */ +ALTERNATE(PIN_MASK(B, 0x0038), 0, MODULE_SPI, 0) +#ifdef SECTION_IS_RO +/* SPI SLAVE: PB13/14/15 */ +ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) +#endif +/* SPI SLAVE CS: PA15 */ +ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) diff --git a/board/katsu/led.c b/board/katsu/led.c new file mode 100644 index 0000000000..64f0982e20 --- /dev/null +++ b/board/katsu/led.c @@ -0,0 +1,202 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery LED control for Katsu board. + */ + +#include "battery.h" +#include "charge_state.h" +#include "driver/charger/rt946x.h" +#include "hooks.h" +#include "led_common.h" +#include "power.h" + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +#define LED_OFF MT6370_LED_ID_OFF +#define LED_AMBER MT6370_LED_ID1 +#define LED_WHITE MT6370_LED_ID2 + +#define LED_MASK_OFF 0 +#define LED_MASK_AMBER MT6370_MASK_RGB_ISNK1DIM_EN +#define LED_MASK_WHITE MT6370_MASK_RGB_ISNK2DIM_EN + +static void katsu_led_set_battery(void) +{ + enum led_pwr_state chstate; + enum power_state powerstate; + static uint8_t prv_white, prv_amber; + static uint8_t time_cnt; + uint8_t br[EC_LED_COLOR_COUNT] = { 0 }; + + chstate = led_pwr_get_state(); + powerstate = power_get_state(); + + switch (chstate) { + case LED_PWRS_CHARGE: + case LED_PWRS_CHARGE_NEAR_FULL: + if (charge_get_percent() < 94) { + br[EC_LED_COLOR_AMBER] = 1; + br[EC_LED_COLOR_WHITE] = 0; + break; + } + br[EC_LED_COLOR_WHITE] = 1; + br[EC_LED_COLOR_AMBER] = 0; + break; + case LED_PWRS_DISCHARGE: + if (powerstate == POWER_S0) { + /* display SoC 10% = real battery SoC 13%*/ + if (charge_get_percent() < 14) { + if (time_cnt < 1) { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 1; + } else { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + if (time_cnt > 3) + time_cnt = 0; + } + break; + } + br[EC_LED_COLOR_WHITE] = 1; + br[EC_LED_COLOR_AMBER] = 0; + break; + } else if (powerstate == POWER_S3) { + if (time_cnt < 2) { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 1; + br[EC_LED_COLOR_AMBER] = 0; + } else { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + if (time_cnt > 3) + time_cnt = 0; + } + break; + } else if (powerstate == POWER_S5 || powerstate == POWER_G3) { + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + } + break; + case LED_PWRS_ERROR: + if (powerstate == POWER_S0) { + if (time_cnt < 1) { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 1; + } else { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + if (time_cnt > 1) + time_cnt = 0; + } + break; + } else if (powerstate == POWER_S3) { + if (time_cnt < 2) { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 1; + br[EC_LED_COLOR_AMBER] = 0; + } else { + time_cnt++; + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + if (time_cnt > 3) + time_cnt = 0; + } + break; + } else if (powerstate == POWER_S5 || powerstate == POWER_G3) { + br[EC_LED_COLOR_WHITE] = 0; + br[EC_LED_COLOR_AMBER] = 0; + } + break; + default: + /* Other states don't alter LED behavior */ + return; + } + + if (prv_white == br[EC_LED_COLOR_WHITE] && + prv_amber == br[EC_LED_COLOR_AMBER]) + return; + + prv_white = br[EC_LED_COLOR_WHITE]; + prv_amber = br[EC_LED_COLOR_AMBER]; + led_set_brightness(EC_LED_ID_BATTERY_LED, br); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id != EC_LED_ID_BATTERY_LED) + return; + + brightness_range[EC_LED_COLOR_WHITE] = MT6370_LED_BRIGHTNESS_MAX; + brightness_range[EC_LED_COLOR_AMBER] = MT6370_LED_BRIGHTNESS_MAX; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + uint8_t white, amber; + + if (led_id != EC_LED_ID_BATTERY_LED) + return EC_ERROR_INVAL; + + white = brightness[EC_LED_COLOR_WHITE]; + amber = brightness[EC_LED_COLOR_AMBER]; + + mt6370_led_set_brightness(LED_WHITE, white); + mt6370_led_set_brightness(LED_AMBER, amber); + + /* Enables LED sink power if necessary. */ + mt6370_led_set_color((white ? LED_MASK_WHITE : 0) | + (amber ? LED_MASK_AMBER : 0)); + return EC_SUCCESS; +} + +static void katsu_led_init(void) +{ + const enum mt6370_led_dim_mode dim = MT6370_LED_DIM_MODE_PWM; + const enum mt6370_led_pwm_freq freq = MT6370_LED_PWM_FREQ1000; + + mt6370_led_set_color(0); + mt6370_led_set_dim_mode(LED_WHITE, dim); + mt6370_led_set_dim_mode(LED_AMBER, dim); + mt6370_led_set_pwm_frequency(LED_WHITE, freq); + mt6370_led_set_pwm_frequency(LED_AMBER, freq); + mt6370_led_set_pwm_dim_duty(LED_WHITE, 255); + mt6370_led_set_pwm_dim_duty(LED_AMBER, 255); +} +DECLARE_HOOK(HOOK_INIT, katsu_led_init, HOOK_PRIO_DEFAULT); + +/* Called by hook task every 1 sec */ +static void led_second(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + katsu_led_set_battery(); +} +DECLARE_HOOK(HOOK_SECOND, led_second, HOOK_PRIO_DEFAULT); + +__override void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + uint8_t br[EC_LED_COLOR_COUNT] = { 0 }; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_BATTERY_LED, 1); + return; + } + + if (state) + br[EC_LED_COLOR_WHITE] = 1; + + led_auto_control(EC_LED_ID_BATTERY_LED, 0); + led_set_brightness(EC_LED_ID_BATTERY_LED, br); +} diff --git a/board/katsu/vif_override.xml b/board/katsu/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/katsu/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kindred/battery.c b/board/kindred/battery.c index 9db25ac059..a087d0a85f 100644 --- a/board/kindred/battery.c +++ b/board/kindred/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/kindred/board.c b/board/kindred/board.c index 0ee52f7095..3358b86583 100644 --- a/board/kindred/board.c +++ b/board/kindred/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,12 +6,14 @@ /* Hatch board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" #include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/bc12/pi3usb9201.h" #include "driver/ppc/sn5s330.h" #include "driver/tcpm/anx7447.h" @@ -29,23 +31,26 @@ #include "power_button.h" #include "pwm.h" #include "pwm_chip.h" -#include "stdbool.h" #include "spi.h" +#include "stdbool.h" #include "switch.h" #include "system.h" #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +static int lid_device_id; +static int base_device_id; static void check_reboot_deferred(void); DECLARE_DEFERRED(check_reboot_deferred); @@ -61,17 +66,16 @@ const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { * that we don't have pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {-1, -1}, {-1, -1}, {1, 4}, {1, 3}, - {-1, -1}, {1, 6}, {1, 7}, {3, 1}, {2, 0}, - {1, 5}, {2, 6}, {2, 7}, {2, 1}, {2, 4}, - {2, 5}, {1, 2}, {2, 3}, {2, 2}, {3, 0}, - {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, - {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, + { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); static void ppc_interrupt(enum gpio_signal signal) { @@ -116,11 +120,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -128,20 +132,21 @@ static void bc12_interrupt(enum gpio_signal signal) } } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, - [PWM_CH_FAN] = {.channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -161,23 +166,51 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, .flags = 0, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +static int board_anx7447_mux_set_c0(const struct usb_mux *me, + mux_state_t mux_state) +{ + int port = me->usb_port; + int rv = EC_SUCCESS; + + if (port != USB_PD_PORT_TCPC_0) + return rv; + + if (gpio_get_level(GPIO_CCD_MODE_ODL)) + return rv; + + /* + * Expect to set AUX_SWITCH to 0, but 0xc isolates the DP_AUX + * signal from SBU. + */ + CPRINTS("C%d: AUX_SW_SEL=0x%x", port, 0xc); + if (tcpc_write(port, ANX7447_REG_TCPC_AUX_SWITCH, 0xc)) + CPRINTS("C%d: Setting AUX_SW_SEL failed", port); + + return rv; +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &anx7447_usb_mux_driver, + .board_set = &board_anx7447_mux_set_c0, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -201,21 +234,94 @@ static struct mutex g_lid_mutex; /* Base accel private data */ static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; /* BMA255 private data */ static struct accelgyro_saved_data_t g_bma255_data; +static struct kionix_accel_data g_kx022_data; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_icm_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 2, /* g, enough for laptop */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, }; -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, }; struct motion_sensor_t motion_sensors[] = { @@ -264,6 +370,7 @@ struct motion_sensor_t motion_sensors[] = { .config = { [SENSOR_CONFIG_EC_S0] = { .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, }, /* Sensor on in S3 */ [SENSOR_CONFIG_EC_S3] = { @@ -296,7 +403,7 @@ unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -315,58 +422,62 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_3] = { - "TEMP_WIFI", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_3] = { "TEMP_WIFI", NPCX_ADC_CH3, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Temp1", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Temp2", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, - [TEMP_SENSOR_3] = {.name = "Temp3", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_3}, + [TEMP_SENSOR_1] = { .name = "Temp1", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Temp2", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Temp3", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - /* Hatch Temperature sensors */ /* * TODO(b/124316213): These setting need to be reviewed and set appropriately * for Hatch. They matter when the EC is controlling the fan as opposed to DPTF * control. */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = C_TO_K(75), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(55), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(55), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(75), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(55), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -407,7 +518,6 @@ static void board_gpio_set_pp5000(void) } else if (board_id >= 1) { reset_gpio_flags(GPIO_EN_PP5000_A_V1, GPIO_OUT_LOW); } - } bool board_is_convertible(void) @@ -455,6 +565,55 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +static void determine_accel_devices(void) +{ + static uint8_t read_time; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + + if (read_time == 0 && board_is_convertible()) { + /* Read g sensor chip id*/ + i2c_read8(I2C_PORT_ACCEL, KX022_ADDR0_FLAGS, KX022_WHOAMI, + &lid_device_id); + /* Read gyro sensor id*/ + i2c_read8(I2C_PORT_ACCEL, ICM426XX_ADDR0_FLAGS, + ICM426XX_REG_WHO_AM_I, &base_device_id); + + CPRINTS("Motion Sensor Base id = %d Lid id =%d", base_device_id, + lid_device_id); + + if (lid_device_id == KX022_WHO_AM_I_VAL) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + ccprints("Lid Accel is KX022"); + } else + ccprints("Lid Accel is BMA255"); + + if (base_device_id == ICM426XX_CHIP_ICM40608) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE Accel is ICM426XX"); + } else + ccprints("BASE Accel is BMI160"); + + read_time++; + } +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, determine_accel_devices, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, determine_accel_devices, HOOK_PRIO_INIT_ADC + 2); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_device_id) { + case ICM426XX_CHIP_ICM40608: + icm426xx_interrupt(signal); + break; + default: + bmi160_interrupt(signal); + break; + } +} + void board_overcurrent_event(int port, int is_overcurrented) { /* Check that port number is valid. */ @@ -489,7 +648,8 @@ __override void board_chipset_forced_shutdown(void) { hook_call_deferred(&check_reboot_deferred_data, -1); } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_forced_shutdown, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_forced_shutdown, + HOOK_PRIO_DEFAULT); static void check_reboot_deferred(void) { diff --git a/board/kindred/board.h b/board/kindred/board.h index 54c2d173d7..1372887446 100644 --- a/board/kindred/board.h +++ b/board/kindred/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,13 +12,13 @@ #include "baseboard.h" #define CONFIG_POWER_BUTTON -#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT #define CONFIG_POWER_BUTTON_INIT_TIMEOUT 2 #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -31,13 +31,19 @@ /* Sensors */ /* BMI160 Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS + #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + #define CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT /* BMA253 Lid accel */ #define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCEL_KX022 #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL @@ -86,7 +92,7 @@ #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 50 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -105,15 +111,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ #include "gpio_signal.h" @@ -124,9 +131,9 @@ extern enum gpio_signal gpio_en_pp5000_a; enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_TEMP_SENSOR_3, /* ADC3 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_3, /* ADC3 */ ADC_CH_COUNT }; @@ -137,11 +144,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, @@ -172,8 +175,9 @@ enum battery_type { /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK (1 << LID_ACCEL) -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; +void motion_interrupt(enum gpio_signal signal); + +void ccd_mode_isr(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ diff --git a/board/kindred/build.mk b/board/kindred/build.mk index 733912454f..13153c1526 100644 --- a/board/kindred/build.mk +++ b/board/kindred/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/kindred/ec.tasklist b/board/kindred/ec.tasklist index 4a1024a091..829be2b7c8 100644 --- a/board/kindred/ec.tasklist +++ b/board/kindred/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/kindred/gpio.inc b/board/kindred/gpio.inc index 91b41a4730..cde4305f16 100644 --- a/board/kindred/gpio.inc +++ b/board/kindred/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,10 +16,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) @@ -27,7 +27,7 @@ GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PP5000_A_PG_OD, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Sensor Interrupts */ -GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING, bmi160_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING, motion_interrupt) /* USB-C interrupts */ GPIO_INT(USB_C0_PPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, ppc_interrupt) @@ -37,6 +37,9 @@ GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) GPIO_INT(USB_C0_BC12_INT_ODL, PIN(9, 5), GPIO_INT_FALLING, bc12_interrupt) GPIO_INT(USB_C1_BC12_INT_ODL, PIN(E, 4), GPIO_INT_FALLING, bc12_interrupt) +/* CCD mode line*/ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + GPIO_INT(HDMI_CONN_HPD, PIN(7, 2), GPIO_INT_BOTH, hdmi_hpd_interrupt) /* Volume button interrupts */ diff --git a/board/kindred/led.c b/board/kindred/led.c index f47ee7e101..21be931889 100644 --- a/board/kindred/led.c +++ b/board/kindred/led.c @@ -1,44 +1,50 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Hatch */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -77,4 +83,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/kindred/vif_override.xml b/board/kindred/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kindred/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kingoftown/battery.c b/board/kingoftown/battery.c new file mode 100644 index 0000000000..3a74f99907 --- /dev/null +++ b/board/kingoftown/battery.c @@ -0,0 +1,160 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all kingoftown battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ + +const struct board_batt_params board_battery_info[] = { + /* DynaPack HIGHPOWER Battery Information */ + [BATTERY_DYNAPACK_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-2D-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + + /* DynaPack BYD Battery Information */ + [BATTERY_DYNAPACK_BYD] = { + .fuel_gauge = { + .manuf_name = "333-2E-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + + /* CosMX Battery Information */ + [BATTERY_COS] = { + .fuel_gauge = { + .manuf_name = "333-AC-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + + /* ATL GB-S20-4473A9-01H&020H Battery Information + * Gauge IC : RAJ240045 + */ + [BATTERY_ATL] = { + .fuel_gauge = { + .manuf_name = "313-B7-0D-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x43, + .reg_mask = 0x0003, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_HIGHPOWER; diff --git a/board/kingoftown/board.c b/board/kingoftown/board.c new file mode 100644 index 0000000000..b8bbd08d2e --- /dev/null +++ b/board/kingoftown/board.c @@ -0,0 +1,251 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Kingoftown board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "shi_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Use 80 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* + * Unmask 0x08 in [0] (KSO_00/KSI_03, the new location of Search key); + * as it still uses the legacy location (KSO_01/KSI_00). + */ + .actual_key_mask = { 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xa4, + 0xff, 0xfe, 0x55, 0xfa, 0xca }, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, +}; + +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +/* I2C port map */ +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* Measure VBUS through a 1/10 voltage divider */ + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + /* + * Adapter current output or battery charging/discharging current (uV) + * 18x amplification on charger side. + */ + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, + /* + * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read + * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and + * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we + * only divide by 2 (enough to avoid precision issues). + */ + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + /* TODO(waihong): Assign a proper frequency. */ + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 4800 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable interrupt for BMI160 sensor */ + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); + + /* Set the backlight duty cycle to 0. AP will override it later. */ + pwm_set_duty(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* + * Turn off display backlight in S3. AP has its own control. The EC's + * and the AP's will be AND'ed together in hardware. + */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); + pwm_enable(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Turn on display and keyboard backlight in S0. */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); + if (pwm_get_duty(PWM_CH_DISPLIGHT)) + pwm_enable(PWM_CH_DISPLIGHT, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Mutexes */ +static struct mutex g_base_mutex; +static struct mutex g_lid_mutex; + +static struct bmi_drv_data_t g_bmi160_data; +static struct accelgyro_saved_data_t g_bma255_data; + +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma255_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g, to support lid angle calculation. */ + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); diff --git a/board/kingoftown/board.h b/board/kingoftown/board.h new file mode 100644 index 0000000000..6b553f65fa --- /dev/null +++ b/board/kingoftown/board.h @@ -0,0 +1,103 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Kingoftown board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Keyboard */ +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +#define CONFIG_PWM_KBLIGHT + +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_VENDOR_PARAM + +/* BC 1.2 Charger */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* USB */ +#define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* USB-A */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* No side volume button */ +#undef CONFIG_VOLUME_BUTTONS + +/* Sensors */ +/* BMI160 Base accel/gyro */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS + +/* BMA253 lid accel */ +#define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_UPDATE + +/* GPIO alias */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_SWITCHCAP_PG GPIO_SWITCHCAP_GPIO_1 +#define GPIO_ACOK_OD GPIO_CHG_ACOK_OD + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { ADC_VBUS, ADC_AMON_BMON, ADC_PSYS, ADC_CH_COUNT }; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_DISPLIGHT, PWM_CH_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_DYNAPACK_HIGHPOWER, + BATTERY_DYNAPACK_BYD, + BATTERY_COS, + BATTERY_ATL, + BATTERY_TYPE_COUNT, +}; + +/* Reset all TCPCs. */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); + +/* support factory keyboard test */ +#define CONFIG_KEYBOARD_FACTORY_TEST +extern const int keyboard_factory_scan_pins[][2]; +extern const int keyboard_factory_scan_pins_used; + +#endif /* !defined(__ASSEMBLER__) */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/kingoftown/build.mk b/board/kingoftown/build.mk new file mode 100644 index 0000000000..2c5eb4ae2e --- /dev/null +++ b/board/kingoftown/build.mk @@ -0,0 +1,19 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=trogdor + +board-y+=battery.o +board-y+=board.o +board-y+=hibernate.o +board-y+=led.o +board-y+=switchcap.o +board-y+=usbc_config.o diff --git a/board/kingoftown/ec.tasklist b/board/kingoftown/ec.tasklist new file mode 100644 index 0000000000..228828af3c --- /dev/null +++ b/board/kingoftown/ec.tasklist @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/kingoftown/gpio.inc b/board/kingoftown/gpio.inc new file mode 100644 index 0000000000..7147869ea3 --- /dev/null +++ b/board/kingoftown/gpio.inc @@ -0,0 +1,187 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* USB interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ +GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ +GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ +GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb1_evt) /* Interrupt from port-1 BC1.2 */ +GPIO_INT(USB_A0_OC_ODL, PIN(D, 1), GPIO_INT_BOTH | GPIO_PULL_UP, usba_oc_interrupt) + +/* System interrupts */ +GPIO_INT(CHG_ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ +GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ +/* + * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down + * to make it low. Overload the interrupt function chipset_warm_reset_interrupt + * for not only signalling power_signal_interrupt but also handling the logic + * of WARM_RESET_L which is pulled-up by the same rail of POWER_GOOD. + */ +GPIO_INT(POWER_GOOD, PIN(5, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, chipset_power_good_interrupt) /* SRC_PP1800_S10A from PMIC */ +GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_warm_reset_interrupt) /* AP warm reset */ +GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ + +/* Sensor interrupts */ +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, bmi160_interrupt) /* Accelerometer/gyro interrupt */ + +/* + * EC_RST_ODL used to be a wake source from PSL mode. However, we disabled + * the PSL mode. This GPIO does nothing now. Simply set it an INPUT. + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ +GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(CCD_MODE_ODL, PIN(E, 3), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ + +/* PMIC/AP 1.8V */ +GPIO(PMIC_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ +GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ + +/* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ +GPIO(SWITCHCAP_ON, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap */ +GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ +GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ +GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ + +/* Sensors */ +GPIO(LID_ACCEL_INT_L, PIN(5, 6), GPIO_INPUT) /* Lid accel sensor interrupt */ +/* Control the gate for trackpad IRQ. High closes the gate. + * This is always set low so that the OS can manage the trackpad. */ +GPIO(TRACKPAD_INT_GATE, PIN(7, 4), GPIO_OUT_LOW) + +/* USB-C */ +GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_OUT_HIGH) /* Port-0 TCPC chip reset */ +GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_OUT_HIGH) /* Port-1 TCPC chip reset */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ + +/* USB-A */ +GPIO(EN_USB_A_5V, PIN(8, 6), GPIO_OUT_LOW) +GPIO(USB_A_CDP_ILIM_EN_L, PIN(7, 5), GPIO_OUT_HIGH) /* H:CDP, L:SDP. Only one USB-A port, always CDP */ + +/* LEDs */ +GPIO(EC_CHG_LED_Y_C0, PIN(6, 0), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_W_C0, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_Y_C1, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_W_C1, PIN(C, 4), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + +/* PWM */ +GPIO(KB_BL_PWM, PIN(8, 0), GPIO_INPUT) /* PWM3 */ +GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ + +/* ADC */ +GPIO(PPVAR_BOOSTIN_SENSE, PIN(4, 4), GPIO_INPUT) /* ADC1 */ +GPIO(CHARGER_IADP, PIN(4, 3), GPIO_INPUT) /* ADC2 */ +GPIO(CHARGER_PMON, PIN(4, 2), GPIO_INPUT) /* ADC3 */ + +/* I2C */ +GPIO(EC_I2C_POWER_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Board/SKU IDs */ +GPIO(BRD_ID0, PIN(C, 7), GPIO_INPUT) +GPIO(BRD_ID1, PIN(9, 3), GPIO_INPUT) +GPIO(BRD_ID2, PIN(6, 3), GPIO_INPUT) +GPIO(SKU_ID0, PIN(F, 0), GPIO_INPUT) +GPIO(SKU_ID1, PIN(4, 1), GPIO_INPUT) +GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) + +/* Switchcap */ +/* + * GPIO0 is configured as PVC_PG. When the chip in power down mode, it outputs + * high-Z. Set pull-down to avoid floating. + */ +GPIO(SWITCHCAP_GPIO_1, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(3, 7)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(7, 3)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(6, 2)) +UNUSED(PIN(0, 4)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(5, 0)) +UNUSED(PIN(D, 3)) +UNUSED(PIN(C, 6)) +UNUSED(PIN(7, 0)) +UNUSED(PIN(F, 2)) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ +ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1 SDA (GPIO90), I2C2 (GPIO91/92) */ +ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) */ +ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ +ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ +ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ +ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* PWM3 (GPIO80) - KB_BL_PWM */ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ + +/* Keyboard */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +#define GPIO_KB_OUTPUT (GPIO_ODR_HIGH) +#define GPIO_KB_OUTPUT_COL2 (GPIO_OUT_LOW) + +/* Keyboard alternate functions */ +ALTERNATE(PIN_MASK(0, 0xE0), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO10 (GPIO07), KSO11 (GPIO06), KSO12 (GPIO05) */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO03 (GPIO16), KSO04 (GPIO15), KSO05 (GPIO14), KSO06 (GPIO13), KSO07 (GPIO12), KSO08 (GPIO11), KSO09 (GPIO10) */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO00 (GPIO21), KSO01 (GPIO20) */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI2 (GPIO27), KSI3 (GPIO26), KSI4 (GPIO25), KSI5 (GPIO24), KSI6 (GPIO23), KSI7 (GPIO22) */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI0 (GPIO31), KSI1 (GPIO30) */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_KB_OUTPUT_COL2) /* KSO02 (GPIO17) */ diff --git a/board/kingoftown/hibernate.c b/board/kingoftown/hibernate.c new file mode 100644 index 0000000000..9b64e85053 --- /dev/null +++ b/board/kingoftown/hibernate.c @@ -0,0 +1,16 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gpio.h" + +void board_hibernate(void) +{ + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_LID_ACCEL_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); +} diff --git a/board/kingoftown/led.c b/board/kingoftown/led.c new file mode 100644 index 0000000000..1a7f503cb7 --- /dev/null +++ b/board/kingoftown/led.c @@ -0,0 +1,210 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +/* Times of tick per 1 second */ +#define TIMES_TICK_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +/* Times of tick per half second */ +#define TIMES_TICK_HALF_SEC (500 / HOOK_TICK_INTERVAL_MS) + +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void side_led_set_color(int port, enum led_color color) +{ + gpio_set_level(port ? GPIO_EC_CHG_LED_Y_C1 : GPIO_EC_CHG_LED_Y_C0, + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(port ? GPIO_EC_CHG_LED_W_C1 : GPIO_EC_CHG_LED_W_C0, + (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + int port; + + switch (led_id) { + case EC_LED_ID_LEFT_LED: + port = 0; + break; + case EC_LED_ID_RIGHT_LED: + port = 1; + break; + default: + return EC_ERROR_PARAM1; + } + + if (brightness[EC_LED_COLOR_WHITE] != 0) + side_led_set_color(port, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + side_led_set_color(port, LED_AMBER); + else + side_led_set_color(port, LED_OFF); + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + side_led_set_color(0, (port == 0) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + side_led_set_color(1, (port == 1) ? color : LED_OFF); +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + static int power_ticks; + int led_blink_cycle; + + battery_ticks++; + + /* + * Override battery LED for kingoftown which doesn't have power LED, + * blinking battery white LED to indicate system suspend without + * charging. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + power_ticks++; + led_blink_cycle = power_ticks % (2 * TIMES_TICK_ONE_SEC); + + side_led_set_color(0, (led_blink_cycle < TIMES_TICK_ONE_SEC) ? + LED_WHITE : + LED_OFF); + side_led_set_color(1, (led_blink_cycle < TIMES_TICK_ONE_SEC) ? + LED_WHITE : + LED_OFF); + return; + } + + power_ticks = 0; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + if (charge_get_percent() <= 10) { + led_blink_cycle = + battery_ticks % (2 * TIMES_TICK_ONE_SEC); + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + side_led_set_color(1, (led_blink_cycle < + TIMES_TICK_ONE_SEC) ? + LED_AMBER : + LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + side_led_set_color(0, (led_blink_cycle < + TIMES_TICK_ONE_SEC) ? + LED_AMBER : + LED_OFF); + } else { + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + side_led_set_color(1, LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + side_led_set_color(0, LED_OFF); + } + break; + case LED_PWRS_ERROR: + led_blink_cycle = battery_ticks % TIMES_TICK_ONE_SEC; + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + side_led_set_color(1, (led_blink_cycle < + TIMES_TICK_HALF_SEC) ? + LED_AMBER : + LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + side_led_set_color(0, (led_blink_cycle < + TIMES_TICK_HALF_SEC) ? + LED_AMBER : + LED_OFF); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + led_blink_cycle = battery_ticks % (2 * TIMES_TICK_ONE_SEC); + set_active_port_color((led_blink_cycle < TIMES_TICK_ONE_SEC) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_LEFT_LED, 1); + led_auto_control(EC_LED_ID_RIGHT_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_WHITE : LED_OFF; + + led_auto_control(EC_LED_ID_LEFT_LED, 0); + led_auto_control(EC_LED_ID_RIGHT_LED, 0); + + side_led_set_color(0, color); + side_led_set_color(1, color); +} diff --git a/board/kingoftown/switchcap.c b/board/kingoftown/switchcap.c new file mode 100644 index 0000000000..5173e27f75 --- /dev/null +++ b/board/kingoftown/switchcap.c @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gpio.h" +#include "power/qcom.h" + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON, enable); +} + +int board_is_switchcap_enabled(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_ON); +} + +int board_is_switchcap_power_good(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_PG); +} diff --git a/board/kingoftown/usbc_config.c b/board/kingoftown/usbc_config.c new file mode 100644 index 0000000000..b18b43ed37 --- /dev/null +++ b/board/kingoftown/usbc_config.c @@ -0,0 +1,365 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Kingoftown board-specific USB-C configuration */ + +#include "bc12/pi3usb9201_public.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "common.h" +#include "config.h" +#include "gpio.h" +#include "hooks.h" +#include "ppc/sn5s330_public.h" +#include "system.h" +#include "tcpm/ps8xxx_public.h" +#include "tcpm/tcpci.h" +#include "timer.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_config.h" +#include "usbc_ocp.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +/* GPIO Interrupt Handlers */ +void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_PD_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +void usb1_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void usba_oc_deferred(void) +{ + /* Use next number after all USB-C ports to indicate the USB-A port */ + board_overcurrent_event(CONFIG_USB_PD_PORT_MAX_COUNT, + !gpio_get_level(GPIO_USB_A0_OC_ODL)); +} +DECLARE_DEFERRED(usba_oc_deferred); + +void usba_oc_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&usba_oc_deferred_data, 0); +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + case GPIO_USB_C1_SWCTL_INT_ODL: + sn5s330_interrupt(1); + break; + default: + break; + } +} + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + } +}; + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + { + .i2c_port = I2C_PORT_EEPROM, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/* Initialize board USC-C things */ +static void board_init_usbc(void) +{ + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + + /* Enable USB-A overcurrent interrupt */ + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init_usbc, HOOK_PRIO_DEFAULT); + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); + msleep(PS8805_FW_INIT_DELAY_MS); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} diff --git a/board/kingoftown/usbc_config.h b/board/kingoftown/usbc_config.h new file mode 100644 index 0000000000..7718aea74c --- /dev/null +++ b/board/kingoftown/usbc_config.h @@ -0,0 +1,19 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Kingoftown board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#include "gpio.h" + +void tcpc_alert_event(enum gpio_signal signal); +void usb0_evt(enum gpio_signal signal); +void usb1_evt(enum gpio_signal signal); +void usba_oc_interrupt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/kingoftown/vif_override.xml b/board/kingoftown/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kingoftown/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kinox/board.c b/board/kinox/board.c new file mode 100644 index 0000000000..af36a3bbc7 --- /dev/null +++ b/board/kinox/board.c @@ -0,0 +1,138 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "builtin/assert.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/cec/bitbang.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + ppc_vbus_sink_enable(0, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ +} + +static void adp_state_init(void) +{ + ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT); + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +static void board_init(void) +{ + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/kinox/board.h b/board/kinox/board.h new file mode 100644 index 0000000000..a1179167a8 --- /dev/null +++ b/board/kinox/board.h @@ -0,0 +1,178 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Kinox board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* Barrel Jack */ +#define DEDICATED_CHARGE_PORT 1 + +/* HDMI CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMI_CEC_OUT +#define CEC_GPIO_IN GPIO_HDMI_CEC_IN +#define CEC_GPIO_PULL_UP GPIO_HDMI_CEC_PULL_UP + +/* USB Type A Features */ +#define USB_PORT_COUNT 4 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_PPC +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID +#undef CONFIG_USB_PD_TCPM_NCT38XX + +#define CONFIG_USBC_PPC_SYV682X +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* The design should support up to 100W. */ +/* TODO(b/197702356): Set the max PD to 60W now and change it + * to 100W after we verify it. + */ +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_OD + +/* I2C Bus Configuration */ +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT4_1 +#define I2C_PORT_USB_C0_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* ADC */ +#define CONFIG_ADC + +/* + * TODO(b/197478860): Enable the fan control. We need + * to check the sensor value and adjust the fan speed. + */ +#define CONFIG_FANS FAN_CH_COUNT + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adp_id { UNKNOWN, TINY, TIO1, TIO2, TYPEC }; + +struct adpater_id_params { + int min_voltage; + int max_voltage; + int charge_voltage; + int charge_current; + int watt; + int obp95; + int obp85; +}; + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_BARRELJACK, + CHARGE_PORT_ENUM_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1_CPU, + ADC_TEMP_SENSOR_2_CPU_VR, + ADC_TEMP_SENSOR_3_WIFI, + ADC_TEMP_SENSOR_4_DIMM, + ADC_PWR_IN_IMON, + ADC_VBUS, + ADC_ADP_ID, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_CPU, + TEMP_SENSOR_2_CPU_VR, + TEMP_SENSOR_3_WIFI, + TEMP_SENSOR_4_DIMM, + TEMP_SENSOR_COUNT +}; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_PORT_COUNT }; + +enum pwm_channel { + PWM_CH_LED_GREEN, /* PWM0 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED_RED, /* PWM2 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +extern void adp_connect_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/kinox/build.mk b/board/kinox/build.mk new file mode 100644 index 0000000000..3eb2d2b2d5 --- /dev/null +++ b/board/kinox/build.mk @@ -0,0 +1,23 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brask board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brask + +board-y= +board-y+=board.o +board-y+=power_detection.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/kinox/ec.tasklist b/board/kinox/ec.tasklist new file mode 100644 index 0000000000..6524d9c2b0 --- /dev/null +++ b/board/kinox/ec.tasklist @@ -0,0 +1,23 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, BIT(0), LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/kinox/fans.c b/board/kinox/fans.c new file mode 100644 index 0000000000..e5724e345a --- /dev/null +++ b/board/kinox/fans.c @@ -0,0 +1,50 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP12000_FAN, +}; + +/* + * TOOD(b/197478860): need to update for real fan + * + * Prototype fan spins at about 7200 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1000, + .rpm_start = 1000, + .rpm_max = 4200, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/kinox/fw_config.c b/board/kinox/fw_config.c new file mode 100644 index 0000000000..9736de1110 --- /dev/null +++ b/board/kinox/fw_config.c @@ -0,0 +1,35 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union kinox_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for kinox if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union kinox_cbi_fw_config fw_config_defaults = { + .dp_display = ABSENT, +}; + +/**************************************************************************** + * Kinox FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} diff --git a/board/kinox/fw_config.h b/board/kinox/fw_config.h new file mode 100644 index 0000000000..a3efa7bfe9 --- /dev/null +++ b/board/kinox/fw_config.h @@ -0,0 +1,34 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_KINOX_FW_CONFIG_H_ +#define __BOARD_KINOX_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for kinox board. + * + * Source of truth is the project/brask/kinox/config.star configuration file. + */ + +enum ec_cfg_dp_display { ABSENT = 0, DB_HDMI = 1, DB_DP = 2 }; + +union kinox_cbi_fw_config { + struct { + uint32_t dp_display : 4; + uint32_t reserved_1 : 28; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union kinox_cbi_fw_config get_fw_config(void); + +#endif /* __BOARD_KINOX_FW_CONFIG_H_ */ diff --git a/board/kinox/gpio.inc b/board/kinox/gpio.inc new file mode 100644 index 0000000000..f3d94ebf07 --- /dev/null +++ b/board/kinox/gpio.inc @@ -0,0 +1,163 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(2, 3), GPIO_INT_BOTH, button_interrupt) + +/* CCD */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + +/* Security */ +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Fan */ +GPIO(EN_PP12000_FAN, PIN(6, 1), GPIO_OUT_LOW) + +/* Display */ +GPIO(DP_CONN_OC_ODL, PIN(2, 5), GPIO_INPUT) +GPIO(HDMI_CONN_OC_ODL, PIN(2, 4), GPIO_INPUT) + +/* BarrelJack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 7), GPIO_OUT_LOW) + +/* Chipset PCH */ +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) + +/* Button */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(GSC_EC_RECOVERY_BTN_OD, PIN(2, 2), GPIO_INPUT) + +GPIO(SIO_LEGO_EN_L, PIN(9, 6), GPIO_OUT_LOW) + +/* HDMI CEC */ +/* TODO(b/197474873): Enable HDMI CEC */ +GPIO(HDMI_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CEC_OUT, PIN(D, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMI_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH) + +/* I2C SCL/SDA */ +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SDA, PIN(F, 2), GPIO_INPUT) + +/* USBA */ +GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW) +GPIO(USB_A0_OC_ODL, PIN(3, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(USB_A2_OC_ODL, PIN(2, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(USB_HUB_A1_OC_ODL, PIN(2, 6), GPIO_INPUT) +GPIO(USB_HUB_A2_OC_ODL, PIN(2, 1), GPIO_INPUT) +GPIO(USB_HUB_A3_OC_ODL, PIN(2, 0), GPIO_INPUT) +GPIO(BTB1_USB_DET_L, PIN(1, 5), GPIO_INPUT) +GPIO(BTB1_DP_DET_L, PIN(1, 4), GPIO_INPUT) +GPIO(BTB1_COM_DET_L, PIN(1, 1), GPIO_INPUT) +GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH) + +/* LED */ +/* TODO(b/197471359): LED implementation */ +GPIO(LED_PWR_L, PIN(C, 3), GPIO_OUT_LOW) +GPIO(LED_HDD_L, PIN(C, 4), GPIO_OUT_LOW) + +/* USBC */ +GPIO(USB_C0_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C0_RT_RST_R_ODL, PIN(0, 2), GPIO_OUT_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, 0) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ +ALTERNATE(PIN_MASK(4, 0x02), 0, MODULE_ADC, 0) /* GPIO41/ADC4 */ +ALTERNATE(PIN_MASK(4, 0x04), 0, MODULE_ADC, 0) /* GPIO42/ADC3 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */ +UNUSED(PIN(9, 7)) /* GPIO97 */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */ +UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */ +UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */ +UNUSED(PIN(0, 6)) /* KSO11/GPIO06/P80_CLK */ +UNUSED(PIN(0, 4)) /* KSO13/GPIO04 */ +UNUSED(PIN(0, 5)) /* KSO12/GPIO05 */ +UNUSED(PIN(1, 0)) /* KSO09/GPIO10 */ +UNUSED(PIN(1, 6)) /* KSO03/GPIO16 */ +UNUSED(PIN(1, 7)) /* KSO02/GPIO17 */ +UNUSED(PIN(3, 3)) /* GPIO33 */ +UNUSED(PIN(3, 6)) /* GPIO36 */ +UNUSED(PIN(E, 0)) /* GPIOE0/ADC10 */ +UNUSED(PIN(5, 0)) /* GPIO50 */ +UNUSED(PIN(6, 2)) /* GPIO62/PS2_CLK1 */ +UNUSED(PIN(7, 0)) /* GPIO70/PS2_DAT0 */ +UNUSED(PIN(8, 3)) /* KSO15/GPIO83 */ +UNUSED(PIN(8, 7)) /* GPIO87/I2C1_SDA0 */ +UNUSED(PIN(9, 0)) /* GPIO90/I2C1_SCL0 */ +UNUSED(PIN(9, 3)) /* GPIO93 */ +UNUSED(PIN(9, 5)) /* GPIO95/SPIP_MISO */ +UNUSED(PIN(A, 0)) /* F_CS0#/GPIOA0 */ +UNUSED(PIN(A, 3)) /* GPIOA3/SPIP_MOSI */ +UNUSED(PIN(A, 7)) /* GPIOA7/PS2_DAT3 */ +UNUSED(PIN(B, 1)) /* KSO17/GPIOB1 */ +UNUSED(PIN(B, 4)) /* GPIOB4/I2C0_SDA0 */ +UNUSED(PIN(B, 5)) /* GPIOB5/I2C0_SCL0 */ +UNUSED(PIN(D, 0)) /* GPIOD0/I2C3_SDA0 */ +UNUSED(PIN(D, 1)) /* GPIOD1/I2C3_SCL0 */ +UNUSED(PIN(D, 2)) /* PSL_IN1#/GPIOD2 */ +UNUSED(PIN(D, 4)) /* GPIOD4/CR_SIN3 */ \ No newline at end of file diff --git a/board/kinox/i2c.c b/board/kinox/i2c.c new file mode 100644 index 0000000000..0412640a19 --- /dev/null +++ b/board/kinox/i2c.c @@ -0,0 +1,46 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C2 C0 PPC*/ + .name = "ppc C0", + .port = I2C_PORT_USB_C0_PPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_SDA, + }, + { + /* I2C4 C0 TCPC */ + .name = "tcpc C0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C6 C0 BC1.2 */ + .name = "bc12 C0", + .port = I2C_PORT_USB_C0_BC12, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C0_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/kinox/led.c b/board/kinox/led.c new file mode 100644 index 0000000000..d2a9a599cf --- /dev/null +++ b/board/kinox/led.c @@ -0,0 +1,262 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Brask. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_GREEN, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int green = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_GREEN: + green = 1; + break; + case LED_RED: + red = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (green) + pwm_set_duty(PWM_CH_LED_GREEN, duty); + else + pwm_set_duty(PWM_CH_LED_GREEN, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* + * When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_GREEN); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* + * Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_GREEN, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +void board_led_auto_control(void) +{ + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); +} + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "green")) { + set_color(id, LED_GREEN, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|red|green|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_GREEN] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_GREEN]) + return set_color(id, LED_GREEN, brightness[EC_LED_COLOR_GREEN]); + else + return set_color(id, LED_OFF, 0); +} diff --git a/board/kinox/power_detection.c b/board/kinox/power_detection.c new file mode 100644 index 0000000000..3fece05749 --- /dev/null +++ b/board/kinox/power_detection.c @@ -0,0 +1,438 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "power.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/******************************************************************************/ + +static const char *const adp_id_names[] = { + "unknown", "tiny", "tio1", "tio2", "typec", +}; + +/* ADP_ID control */ +struct adpater_id_params tio1_power[] = { + { + .min_voltage = 2816, + .max_voltage = 2816, + .charge_voltage = 20000, + .charge_current = 6000, + .watt = 120, + .obp95 = 1990, + .obp85 = 1780, + }, +}; + +struct adpater_id_params tio2_power[] = { + { + .min_voltage = 0, + .max_voltage = 68, + .charge_voltage = 20000, + .charge_current = 8500, + .watt = 170, + .obp95 = 2816, + .obp85 = 2520, + }, + { + .min_voltage = 68, + .max_voltage = 142, + .charge_voltage = 20000, + .charge_current = 2250, + .watt = 45, + .obp95 = 750, + .obp85 = 670, + }, + { + .min_voltage = 200, + .max_voltage = 288, + .charge_voltage = 20000, + .charge_current = 3250, + .watt = 65, + .obp95 = 1080, + .obp85 = 960, + }, + { + .min_voltage = 384, + .max_voltage = 480, + .charge_voltage = 20000, + .charge_current = 7500, + .watt = 150, + .obp95 = 2490, + .obp85 = 2220, + }, + { + .min_voltage = 531, + .max_voltage = 607, + .charge_voltage = 20000, + .charge_current = 6000, + .watt = 120, + .obp95 = 1990, + .obp85 = 1780, + }, + { + .min_voltage = 1062, + .max_voltage = 1126, + .charge_voltage = 20000, + .charge_current = 8500, + .watt = 170, + .obp95 = 2816, + .obp85 = 2520, + }, + { + .min_voltage = 2816, + .max_voltage = 2816, + .charge_voltage = 20000, + .charge_current = 6000, + .watt = 120, + .obp95 = 1990, + .obp85 = 1780, + }, +}; + +struct adpater_id_params tiny_power[] = { + { + .min_voltage = 68, + .max_voltage = 142, + .charge_voltage = 20000, + .charge_current = 2250, + .watt = 45, + .obp95 = 750, + .obp85 = 670, + }, + { + .min_voltage = 200, + .max_voltage = 288, + .charge_voltage = 20000, + .charge_current = 3250, + .watt = 65, + .obp95 = 1080, + .obp85 = 960, + }, + { + .min_voltage = 384, + .max_voltage = 480, + .charge_voltage = 20000, + .charge_current = 4500, + .watt = 90, + .obp95 = 1490, + .obp85 = 1330, + }, + { + .min_voltage = 531, + .max_voltage = 607, + .charge_voltage = 20000, + .charge_current = 6000, + .watt = 120, + .obp95 = 1990, + .obp85 = 1780, + }, + { + .min_voltage = 653, + .max_voltage = 783, + .charge_voltage = 20000, + .charge_current = 6750, + .watt = 135, + .obp95 = 2240, + .obp85 = 2000, + }, + { + .min_voltage = 851, + .max_voltage = 997, + .charge_voltage = 20000, + .charge_current = 7500, + .watt = 150, + .obp95 = 2490, + .obp85 = 2220, + }, + { + .min_voltage = 1063, + .max_voltage = 1226, + .charge_voltage = 20000, + .charge_current = 8500, + .watt = 170, + .obp95 = 2816, + .obp85 = 2520, + }, + { + .min_voltage = 1749, + .max_voltage = 1968, + .charge_voltage = 20000, + .charge_current = 11500, + .watt = 230, + .obp95 = 2816, + .obp85 = 2815, + }, +}; + +struct adpater_id_params typec_power[] = { + { + .charge_voltage = 20000, + .charge_current = 1500, + .watt = 30, + .obp95 = 500, + .obp85 = 440, + }, + { + .charge_voltage = 15000, + .charge_current = 2000, + .watt = 30, + .obp95 = 660, + .obp85 = 590, + }, + { + .charge_voltage = 20000, + .charge_current = 2250, + .watt = 45, + .obp95 = 750, + .obp85 = 670, + }, + { + .charge_voltage = 15000, + .charge_current = 3000, + .watt = 45, + .obp95 = 990, + .obp85 = 890, + }, + { + .charge_voltage = 20000, + .charge_current = 3250, + .watt = 65, + .obp95 = 1080, + .obp85 = 960, + }, + { + .charge_voltage = 20000, + .charge_current = 5000, + .watt = 100, + .obp95 = 1660, + .obp85 = 1480, + }, +}; + +struct adpater_id_params power_type[8]; +static int adp_id_value_debounce; + +void obp_point_95(void) +{ + /* Disable this interrupt while it's asserted. */ + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 0); + /* Enable the voltage low interrupt. */ + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 1); + + /* Trigger the PROCHOT */ + gpio_set_level(GPIO_EC_PROCHOT_ODL, 0); + CPRINTS("Adapter voltage over 95%% trigger prochot."); +} + +void obp_point_85(void) +{ + /* Disable this interrupt while it's asserted. */ + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 0); + /* Enable the voltage high interrupt. */ + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 1); + + /* Release the PROCHOT */ + gpio_set_level(GPIO_EC_PROCHOT_ODL, 1); + CPRINTS("Adapter voltage lower than 85%% release prochot."); +} + +struct npcx_adc_thresh_t adc_obp_point_95 = { + .adc_ch = ADC_PWR_IN_IMON, + .adc_thresh_cb = obp_point_95, + .thresh_assert = 3300, /* Default */ +}; + +struct npcx_adc_thresh_t adc_obp_point_85 = { + .adc_ch = ADC_PWR_IN_IMON, + .adc_thresh_cb = obp_point_85, + .lower_or_higher = 1, + .thresh_assert = 0, /* Default */ +}; + +static void set_up_adc_irqs(void) +{ + /* Set interrupt thresholds for the ADC. */ + CPRINTS("%s", __func__); + npcx_adc_register_thresh_irq(NPCX_ADC_THRESH1, &adc_obp_point_95); + npcx_adc_register_thresh_irq(NPCX_ADC_THRESH2, &adc_obp_point_85); + npcx_set_adc_repetitive(adc_channels[ADC_PWR_IN_IMON].input_ch, 1); + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 1); + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 1); +} + +void set_the_obp(int power_type_index, int adp_type) +{ + struct charge_port_info pi = { 0 }; + + adc_obp_point_95.thresh_assert = power_type[power_type_index].obp95; + adc_obp_point_85.thresh_assert = power_type[power_type_index].obp85; + set_up_adc_irqs(); + if (adp_type != TYPEC) { + /* Only the TIO and Tiny need to update */ + pi.voltage = power_type[power_type_index].charge_voltage; + pi.current = power_type[power_type_index].charge_current; + + switch (adp_type) { + case TIO1: + case TIO2: + gpio_set_level(GPIO_SIO_LEGO_EN_L, 0); + charge_manager_update_charge( + CHARGE_SUPPLIER_PROPRIETARY, + DEDICATED_CHARGE_PORT, &pi); + break; + case TINY: + gpio_set_level(GPIO_SIO_LEGO_EN_L, 1); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, + &pi); + break; + } + } + + CPRINTS("Power type %s, %dW", adp_id_names[adp_type], + power_type[power_type_index].watt); +} + +/* + * Scalar change to Scalar change to + * downgrade voltage 3.3V voltage + * | | + * | SIO collect | SIO collect + * | 1st adapter | 2nd adapter + * | information | information + * | | | | | | | | | | + * ------------------------------------------------------- + * | | | + * |---220 ms---|-----400 ms-----| + * + * Tiny: Twice adapter ADC values are less than 2.816v. + * TIO1: Twice adapter ADC values are 2.816v. + * TIO2: First adapter ADC value less than 2.816v. + * Second adpater ADC value is 2.816v. + */ +static void adp_id_deferred(void); +DECLARE_DEFERRED(adp_id_deferred); +void adp_id_deferred(void) +{ + int i = 0; + int adp_type = 0; + int adp_id_value; + int adp_finial_adc_value; + int power_type_len = 0; + + adp_id_value = adc_read_channel(ADC_ADP_ID); + + if (!adp_id_value_debounce) { + adp_id_value_debounce = adp_id_value; + /* for delay the 400ms to get the next APD_ID value */ + hook_call_deferred(&adp_id_deferred_data, 400 * MSEC); + } else if (adp_id_value_debounce == ADC_MAX_VOLT && + adp_id_value == ADC_MAX_VOLT) { + adp_finial_adc_value = adp_id_value; + adp_type = TIO1; + } else if (adp_id_value_debounce < ADC_MAX_VOLT && + adp_id_value == ADC_MAX_VOLT) { + adp_finial_adc_value = adp_id_value_debounce; + adp_type = TIO2; + } else if (adp_id_value_debounce < ADC_MAX_VOLT && + adp_id_value < ADC_MAX_VOLT) { + adp_finial_adc_value = adp_id_value; + adp_type = TINY; + } else { + CPRINTS("ADP_ID mismatch anything!"); + /* Set the default TINY 45w adapter */ + adp_finial_adc_value = 142; + adp_type = TINY; + } + + switch (adp_type) { + case TIO1: + power_type_len = + sizeof(tio1_power) / sizeof(struct adpater_id_params); + memcpy(&power_type, &tio1_power, sizeof(tio1_power)); + break; + case TIO2: + power_type_len = + sizeof(tio2_power) / sizeof(struct adpater_id_params); + memcpy(&power_type, &tio2_power, sizeof(tio2_power)); + break; + case TINY: + power_type_len = + sizeof(tiny_power) / sizeof(struct adpater_id_params); + memcpy(&power_type, &tiny_power, sizeof(tiny_power)); + break; + } + + for (i = 0; (i < power_type_len) && adp_type; i++) { + if (adp_finial_adc_value <= power_type[i].max_voltage) { + set_the_obp(i, adp_type); + break; + } + } +} + +static void barrel_jack_setting(void) +{ + struct charge_port_info pi = { 0 }; + /* Check ADP_ID when barrel jack is present */ + if (!gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) { + /* Set the default TINY 45w adapter */ + pi.voltage = 20000; + pi.current = 2250; + + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + + /* Delay 220ms to get the first ADP_ID value */ + hook_call_deferred(&adp_id_deferred_data, 220 * MSEC); + } +} +DECLARE_HOOK(HOOK_INIT, barrel_jack_setting, HOOK_PRIO_DEFAULT); + +static void typec_adapter_setting(void) +{ + int i = 0; + int adp_type = TYPEC; + int adapter_current_ma; + int power_type_len; + + /* Check the barrel jack is not present */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) { + adapter_current_ma = charge_manager_get_charger_current(); + power_type_len = + sizeof(typec_power) / sizeof(struct adpater_id_params); + + memcpy(&power_type, &typec_power, sizeof(typec_power)); + for (i = (power_type_len - 1); i >= 0; i--) { + if (adapter_current_ma >= + power_type[i].charge_current) { + set_the_obp(i, adp_type); + break; + } + } + } +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, typec_adapter_setting, HOOK_PRIO_DEFAULT); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + hook_call_deferred(&adp_id_deferred_data, 0); +} diff --git a/board/kinox/pwm.c b/board/kinox/pwm.c new file mode 100644 index 0000000000..cee2bfd59c --- /dev/null +++ b/board/kinox/pwm.c @@ -0,0 +1,33 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_GREEN] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP | + PWM_CONFIG_OPEN_DRAIN, + .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + pwm_enable(PWM_CH_FAN, 1); + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_GREEN, 1); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/kinox/sensors.c b/board/kinox/sensors.c new file mode 100644 index 0000000000..ea193ddc53 --- /dev/null +++ b/board/kinox/sensors.c @@ -0,0 +1,122 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_CPU] = { + .name = "TEMP_CPU", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CPU_VR] = { + .name = "TEMP_CPU_VR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_WIFI] = { + .name = "TEMP_WIFI", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DIMM] = { + .name = "TEMP_DIMM", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PWR_IN_IMON] = { + .name = "PWR_IN_IMON", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX, + }, + [ADC_ADP_ID] = { + .name = "ADP_ID", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_CPU] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_CPU }, + [TEMP_SENSOR_2_CPU_VR] = { .name = "CPU VR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CPU_VR }, + [TEMP_SENSOR_3_WIFI] = { .name = "WIFI", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_WIFI }, + [TEMP_SENSOR_4_DIMM] = { .name = "DIMM", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DIMM }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(95), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(75), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/197478860): add the thermal sensor setting + */ +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CPU] = THERMAL_CPU, + [TEMP_SENSOR_2_CPU_VR] = THERMAL_CPU, + [TEMP_SENSOR_3_WIFI] = THERMAL_CPU, + [TEMP_SENSOR_4_DIMM] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/kinox/usbc_config.c b/board/kinox/usbc_config.c new file mode 100644 index 0000000000..381f82be44 --- /dev/null +++ b/board/kinox/usbc_config.c @@ -0,0 +1,183 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_VCONN | + TCPC_FLAGS_CONTROL_FRS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_usb3_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + /* PS8815 */ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc0_usb3_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(GPIO_USB_C0_RT_RST_R_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + msleep(20); + + gpio_set_level(GPIO_USB_C0_RT_RST_R_ODL, 1); + + /* wait for chips to come up */ + msleep(50); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} diff --git a/board/kinox/usbc_config.h b/board/kinox/usbc_config.h new file mode 100644 index 0000000000..7a212f8fb6 --- /dev/null +++ b/board/kinox/usbc_config.h @@ -0,0 +1,15 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/kinox/vif_override.xml b/board/kinox/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kinox/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kodama/battery.c b/board/kodama/battery.c index 1dbff92a00..1c6737bd3a 100644 --- a/board/kodama/battery.c +++ b/board/kodama/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,7 +14,7 @@ #include "usb_pd.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) const struct board_batt_params board_battery_info[] = { [BATTERY_SIMPLO] = { @@ -95,9 +95,9 @@ int charger_profile_override(struct charge_state_data *curr) * When smart battery temperature is more than 45 deg C, the max * charging voltage is 4100mV. */ - if (curr->state == ST_CHARGE && bat_temp_c >= 450 - && !(curr->batt.flags & BATT_FLAG_BAD_TEMPERATURE)) - curr->requested_voltage = 4100; + if (curr->state == ST_CHARGE && bat_temp_c >= 450 && + !(curr->batt.flags & BATT_FLAG_BAD_TEMPERATURE)) + curr->requested_voltage = 4100; else curr->requested_voltage = batt_info->voltage_max; diff --git a/board/kodama/board.c b/board/kodama/board.c index 2fab43d3ac..d378410639 100644 --- a/board/kodama/board.c +++ b/board/kodama/board.c @@ -1,10 +1,9 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_manager.h" #include "charge_ramp.h" @@ -26,6 +25,7 @@ #include "i2c.h" #include "i2c_bitbang.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -34,57 +34,71 @@ #include "spi.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { schedule_deferred_pd_interrupt(0 /* port */); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, - [ADC_POGO_ADC_INT_L] = {"POGO_ADC_INT_L", 3300, 4096, 0, STM32_AIN(6)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, + [ADC_POGO_ADC_INT_L] = { "POGO_ADC_INT_L", 3300, 4096, 0, + STM32_AIN(6) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA, - .flags = I2C_PORT_FLAG_DYNAMIC_SPEED}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct i2c_port_t i2c_bitbang_ports[] = { - {"battery", 2, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA, .drv = &bitbang_drv}, + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, }; const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ @@ -104,9 +118,12 @@ struct mt6370_thermal_bound thermal_bound = { .err = 4, }; -static void board_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -114,7 +131,6 @@ static void board_hpd_status(const struct usb_mux *me, host_set_single_event(EC_HOST_EVENT_USB_MUX); } - __override const struct rt946x_init_setting *board_rt946x_init_setting(void) { static const struct rt946x_init_setting battery_init_setting = { @@ -129,13 +145,16 @@ __override const struct rt946x_init_setting *board_rt946x_init_setting(void) return &battery_init_setting; } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, }, }; @@ -165,7 +184,7 @@ int board_set_active_charge_port(int charge_port) if (board_vbus_source_enabled(charge_port)) return -1; break; - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -173,9 +192,6 @@ int board_set_active_charge_port(int charge_port) */ charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; @@ -216,9 +232,8 @@ int extpower_is_present(void) if (board_vbus_source_enabled(CHARGE_PORT_USB_C)) usb_c_extpower_present = 0; else - usb_c_extpower_present = tcpm_check_vbus_level( - CHARGE_PORT_USB_C, - VBUS_PRESENT); + usb_c_extpower_present = + tcpm_check_vbus_level(CHARGE_PORT_USB_C, VBUS_PRESENT); return usb_c_extpower_present; } @@ -238,11 +253,11 @@ static void board_init(void) #ifdef SECTION_IS_RW int val; - i2c_read8(I2C_PORT_CHARGER, CHARGER_I2C_ADDR_FLAGS, - RT946X_REG_CHGCTRL1, &val); + i2c_read8(I2C_PORT_CHARGER, CHARGER_I2C_ADDR_FLAGS, RT946X_REG_CHGCTRL1, + &val); val &= RT946X_MASK_OPA_MODE; i2c_write8(I2C_PORT_CHARGER, CHARGER_I2C_ADDR_FLAGS, - RT946X_REG_CHGCTRL1, (val | RT946X_MASK_STAT_EN)); + RT946X_REG_CHGCTRL1, (val | RT946X_MASK_STAT_EN)); #endif /* If the reset cause is external, pulse PMIC force reset. */ @@ -295,7 +310,7 @@ DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); static void board_i2c_init(void) { if (board_get_version() < 2) - i2c_set_freq(1, I2C_FREQ_100KHZ); + i2c_set_freq(1, I2C_FREQ_100KHZ); } DECLARE_HOOK(HOOK_INIT, board_i2c_init, HOOK_PRIO_INIT_I2C); @@ -307,11 +322,9 @@ static struct mutex g_lid_mutex; static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; /* Matrix to rotate accelerometer into standard reference frame */ -static const mat33_fp_t lid_standard_ref = { - {0, FLOAT_TO_FP(1), 0}, - {FLOAT_TO_FP(-1), 0, 0}, - {0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -323,8 +336,6 @@ struct motion_sensor_t motion_sensors[] = { .drv = &lsm6dsm_drv, .mutex = &g_lid_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_ACCEL_INT_ODL, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_ACCEL, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &lid_standard_ref, diff --git a/board/kodama/board.h b/board/kodama/board.h index cf71fe5dd2..b22ab2153f 100644 --- a/board/kodama/board.h +++ b/board/kodama/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,8 +10,10 @@ #define VARIANT_KUKUI_BATTERY_SMART #define VARIANT_KUKUI_CHARGER_MT6370 +#define VARIANT_KUKUI_EC_STM32F098 #define VARIANT_KUKUI_POGO_KEYBOARD #define VARIANT_KUKUI_TABLET_PWRBTN +#undef CONFIG_CMD_MFALLOW #ifndef SECTION_IS_RW #define VARIANT_KUKUI_NO_SENSORS @@ -19,12 +21,13 @@ #include "baseboard.h" +#define CONFIG_DEBUG_ASSERT_BRIEF + #define CONFIG_VOLUME_BUTTONS #define CONFIG_USB_MUX_IT5205 #define CONFIG_LED_ONOFF_STATES -#define CONFIG_LED_POWER_LED #define CONFIG_BATTERY_HW_PRESENT_CUSTOM @@ -35,7 +38,7 @@ #define CONFIG_SMBUS_PEC /* Battery */ -#define BATTERY_DESIRED_CHARGING_CURRENT 2000 /* mA */ +#define BATTERY_DESIRED_CHARGING_CURRENT 2000 /* mA */ #define CONFIG_CHARGER_MT6370_BACKLIGHT #define CONFIG_CHARGER_MAINTAIN_VBAT @@ -43,32 +46,37 @@ /* Motion Sensors */ #ifdef SECTION_IS_RW #define CONFIG_ACCELGYRO_LSM6DSM -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) /* Camera VSYNC */ #define CONFIG_SYNC #define CONFIG_SYNC_COMMAND -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) #endif /* SECTION_IS_RW */ +/* Disable verbose output in EC pd */ +#define CONFIG_CMD_PD_SRCCAPS_REDUCED_SIZE + /* I2C ports */ -#define I2C_PORT_CHARGER 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_ACCEL 1 -#define I2C_PORT_BATTERY board_get_battery_i2c() +#define I2C_PORT_CHARGER 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_ACCEL 1 +#define I2C_PORT_BATTERY board_get_battery_i2c() #define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY /* Define the host events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) +#define CONFIG_MKBP_INPUT_DEVICES #define PD_OPERATING_POWER_MW 15000 +/* Free up flash in RO. */ +#ifdef SECTION_IS_RO +#undef CONFIG_USB_PD_HOST_CMD +#undef CONFIG_USB_PD_CONSOLE_CMD +#endif + #ifndef __ASSEMBLER__ enum adc_channel { @@ -116,7 +124,6 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); void pogo_adc_interrupt(enum gpio_signal signal); int board_discharge_on_ac(int enable); /* returns the i2c port number of battery */ diff --git a/board/kodama/build.mk b/board/kodama/build.mk index 0b3565fd84..6a7e557a0e 100644 --- a/board/kodama/build.mk +++ b/board/kodama/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/kodama/ec.tasklist b/board/kodama/ec.tasklist index f71a208dd6..e66c52616b 100644 --- a/board/kodama/ec.tasklist +++ b/board/kodama/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/kodama/gpio.inc b/board/kodama/gpio.inc index 75a3db7d20..d72532ff70 100644 --- a/board/kodama/gpio.inc +++ b/board/kodama/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/kodama/led.c b/board/kodama/led.c index 61d29f9d16..8ea6f2e308 100644 --- a/board/kodama/led.c +++ b/board/kodama/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,49 +6,53 @@ */ #include "charge_state.h" #include "driver/charger/rt946x.h" +#include "ec_commands.h" #include "hooks.h" #include "led_common.h" #include "led_onoff_states.h" -#include "ec_commands.h" -#define LED_RED MT6370_LED_ID1 -#define LED_GREEN MT6370_LED_ID2 -#define LED_WHITE MT6370_LED_ID3 - -#define LED_MASK_OFF 0 -#define LED_MASK_RED MT6370_MASK_RGB_ISNK1DIM_EN -#define LED_MASK_GREEN MT6370_MASK_RGB_ISNK2DIM_EN -#define LED_MASK_WHITE MT6370_MASK_RGB_ISNK3DIM_EN - -const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 97; - -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, LED_ONE_SEC / 2} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED -}; +#define LED_RED MT6370_LED_ID1 +#define LED_GREEN MT6370_LED_ID2 +#define LED_WHITE MT6370_LED_ID3 + +#define LED_MASK_OFF 0 +#define LED_MASK_RED MT6370_MASK_RGB_ISNK1DIM_EN +#define LED_MASK_GREEN MT6370_MASK_RGB_ISNK2DIM_EN +#define LED_MASK_WHITE MT6370_MASK_RGB_ISNK3DIM_EN + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, LED_ONE_SEC / 2 } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -66,7 +70,7 @@ static void led_set_color(int mask) mt6370_led_set_color(led_mask); } -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) led_mask |= LED_MASK_WHITE; @@ -75,7 +79,7 @@ void led_set_color_power(enum ec_led_colors color) led_set_color(led_mask); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_RED: diff --git a/board/kodama/vif_override.xml b/board/kodama/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kodama/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kohaku/battery.c b/board/kohaku/battery.c index 1d311d69f1..693c5b5221 100644 --- a/board/kohaku/battery.c +++ b/board/kohaku/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,6 +6,7 @@ */ #include "battery_fuel_gauge.h" +#include "charge_state.h" #include "common.h" #include "system.h" #include "util.h" @@ -32,6 +33,10 @@ * status can be read with a sb_read() command and therefore, only the register * address, mask, and disconnect value need to be provided. */ + +/* charging current is limited to 0.45C */ +#define CHARGING_CURRENT_45C 2804 + const struct board_batt_params board_battery_info[] = { /* Dyna Battery Information */ [BATTERY_DYNA] = { @@ -106,3 +111,29 @@ enum battery_present variant_battery_present(void) */ return BP_YES; } + +int charger_profile_override(struct charge_state_data *curr) +{ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return 0; + + if (curr->requested_current > CHARGING_CURRENT_45C) + curr->requested_current = CHARGING_CURRENT_45C; + + return 0; +} + +/* Customs options controllable by host command. */ +#define PARAM_FASTCHARGE (CS_PARAM_CUSTOM_PROFILE_MIN + 0) + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/kohaku/board.c b/board/kohaku/board.c index 8f261dff23..fc7f77b369 100644 --- a/board/kohaku/board.c +++ b/board/kohaku/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Kohaku board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" @@ -14,8 +13,8 @@ #include "driver/accelgyro_bmi_common.h" #include "driver/als_bh1730.h" #include "driver/als_tcs3400.h" -#include "driver/ppc/sn5s330.h" #include "driver/bc12/max14637.h" +#include "driver/ppc/sn5s330.h" #include "driver/sync.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" @@ -34,16 +33,16 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void ppc_interrupt(enum gpio_signal signal) { @@ -83,11 +82,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -95,18 +94,18 @@ static void bc12_interrupt(enum gpio_signal signal) } } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -117,7 +116,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -125,22 +124,26 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -224,11 +227,9 @@ static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { }; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -313,12 +314,11 @@ struct motion_sensor_t motion_sensors[] = { .i2c_spi_addr_flags = BH1730_I2C_ADDR_FLAGS, .rot_standard_ref = NULL, .default_range = 65535, - .min_frequency = 10, - .max_frequency = 10, + .min_frequency = BH1730_MIN_FREQ, + .max_frequency = BH1730_MAX_FREQ, .config = { [SENSOR_CONFIG_EC_S0] = { - .odr = 100000, - .ec_rate = 0, + .odr = BH1730_10000_MHZ, }, }, }, @@ -385,34 +385,34 @@ BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); /**********************************************************************/ /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_AMB", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_3] = { - "TEMP_GT", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_4] = { - "TEMP_IA", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_AMB", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_3] = { "TEMP_GT", NPCX_ADC_CH2, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_4] = { "TEMP_IA", NPCX_ADC_CH3, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, - [TEMP_SENSOR_3] = {.name = "GT", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_3}, - [TEMP_SENSOR_4] = {.name = "IA", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_4}, + [TEMP_SENSOR_1] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "GT", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "IA", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -422,26 +422,31 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); * for Kohaku. They matter when the EC is controlling the fan as opposed to DPTF * control. */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(90), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1] = thermal_a, - [TEMP_SENSOR_2] = thermal_a, - [TEMP_SENSOR_3] = thermal_a, - [TEMP_SENSOR_4] = thermal_a, + [TEMP_SENSOR_1] = THERMAL_A, + [TEMP_SENSOR_2] = THERMAL_A, + [TEMP_SENSOR_3] = THERMAL_A, + [TEMP_SENSOR_4] = THERMAL_A, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/kohaku/board.h b/board/kohaku/board.h index 196365b9da..d120e308aa 100644 --- a/board/kohaku/board.h +++ b/board/kohaku/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,9 +18,8 @@ #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE -#define CONFIG_LED_POWER_LED -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -30,15 +29,13 @@ /* Sensors */ /* BMI160 Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT /* Camera VSYNC */ #define CONFIG_SYNC -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) /* BMA253 Lid accel */ #define CONFIG_ACCEL_BMA255 #define CONFIG_LID_ANGLE @@ -48,7 +45,7 @@ /* BH1730 and TCS3400 ALS */ #define CONFIG_ALS #define ALS_COUNT 2 -#define I2C_PORT_ALS I2C_PORT_SENSOR +#define I2C_PORT_ALS I2C_PORT_SENSOR #define CONFIG_ALS_BH1730 #define CONFIG_ALS_TCS3400 #define CONFIG_ALS_TCS3400_INT_EVENT \ @@ -72,18 +69,18 @@ * Kohaku will not use both BH1730_LUXTH3_1K condition * and BH1730_LUXTH4_1K condition. */ -#define BH1730_LUXTH1_1K 270 -#define BH1730_LUXTH1_D0_1K 19200 -#define BH1730_LUXTH1_D1_1K 30528 -#define BH1730_LUXTH2_1K 655360000 -#define BH1730_LUXTH2_D0_1K 11008 -#define BH1730_LUXTH2_D1_1K 10752 -#define BH1730_LUXTH3_1K 1030 -#define BH1730_LUXTH3_D0_1K 11008 -#define BH1730_LUXTH3_D1_1K 10752 -#define BH1730_LUXTH4_1K 3670 -#define BH1730_LUXTH4_D0_1K 11008 -#define BH1730_LUXTH4_D1_1K 10752 +#define BH1730_LUXTH1_1K 270 +#define BH1730_LUXTH1_D0_1K 19200 +#define BH1730_LUXTH1_D1_1K 30528 +#define BH1730_LUXTH2_1K 655360000 +#define BH1730_LUXTH2_D0_1K 11008 +#define BH1730_LUXTH2_D1_1K 10752 +#define BH1730_LUXTH3_1K 1030 +#define BH1730_LUXTH3_D0_1K 11008 +#define BH1730_LUXTH3_D1_1K 10752 +#define BH1730_LUXTH4_1K 3670 +#define BH1730_LUXTH4_D0_1K 11008 +#define BH1730_LUXTH4_D1_1K 10752 /* USB Type C and USB PD defines */ #define CONFIG_USB_PD_COMM_LOCKED @@ -113,6 +110,7 @@ */ #define CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA 6144 #define CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS +#define CONFIG_CHARGER_PROFILE_OVERRIDE /* Volume Button feature */ #define CONFIG_VOLUME_BUTTONS @@ -120,7 +118,7 @@ #define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL /* Thermal features */ -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -131,15 +129,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -150,10 +149,10 @@ extern enum gpio_signal gpio_en_pp5000_a; enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_TEMP_SENSOR_3, /* ADC2 */ - ADC_TEMP_SENSOR_4, /* ADC3 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_3, /* ADC2 */ + ADC_TEMP_SENSOR_4, /* ADC3 */ ADC_CH_COUNT }; @@ -168,10 +167,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; enum temp_sensor_id { TEMP_SENSOR_1, diff --git a/board/kohaku/build.mk b/board/kohaku/build.mk index 733912454f..13153c1526 100644 --- a/board/kohaku/build.mk +++ b/board/kohaku/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/kohaku/ec.tasklist b/board/kohaku/ec.tasklist index 63d366a33b..7fb3e38b63 100644 --- a/board/kohaku/ec.tasklist +++ b/board/kohaku/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/kohaku/gpio.inc b/board/kohaku/gpio.inc index 742a570cf8..eaddb14e2b 100644 --- a/board/kohaku/gpio.inc +++ b/board/kohaku/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,10 +16,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) diff --git a/board/kohaku/led.c b/board/kohaku/led.c index 58cdf6f175..2fbf2da3a5 100644 --- a/board/kohaku/led.c +++ b/board/kohaku/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -12,53 +12,56 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1 = 0; +__override const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* Kohaku : There are 3 leds for AC, Battery and Power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0_BAT_LOW] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 0.5 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_BLUE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { /* Don't set led if led_auto_control is disabled. */ if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || - !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { return; } - if (color == EC_LED_COLOR_BLUE) - { + if (color == EC_LED_COLOR_BLUE) { gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_ON_LVL); @@ -68,19 +71,18 @@ void led_set_color_power(enum ec_led_colors color) } } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { /* Don't set led if led_auto_control is disabled. */ if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || - !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { return; } /* Battery leds must be turn off when blue led is on * because kohaku has 3-in-1 led. */ - if(!gpio_get_level(GPIO_PWR_LED_BLUE_L)) - { + if (!gpio_get_level(GPIO_PWR_LED_BLUE_L)) { gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); return; @@ -116,10 +118,13 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { if (led_id == EC_LED_ID_BATTERY_LED) { gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); - gpio_set_level(GPIO_BAT_LED_GREEN_L, !brightness[EC_LED_COLOR_GREEN]); - gpio_set_level(GPIO_BAT_LED_RED_L, !brightness[EC_LED_COLOR_RED]); + gpio_set_level(GPIO_BAT_LED_GREEN_L, + !brightness[EC_LED_COLOR_GREEN]); + gpio_set_level(GPIO_BAT_LED_RED_L, + !brightness[EC_LED_COLOR_RED]); } else if (led_id == EC_LED_ID_POWER_LED) { - gpio_set_level(GPIO_PWR_LED_BLUE_L, !brightness[EC_LED_COLOR_BLUE]); + gpio_set_level(GPIO_PWR_LED_BLUE_L, + !brightness[EC_LED_COLOR_BLUE]); gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); } diff --git a/board/kohaku/vif_override.xml b/board/kohaku/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kohaku/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kracko/battery.c b/board/kracko/battery.c new file mode 100644 index 0000000000..4b8bbb7351 --- /dev/null +++ b/board/kracko/battery.c @@ -0,0 +1,99 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all kracko battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* Simplo Battery Information */ + [BATTERY_SIMPLO] = { + .fuel_gauge = { + .manuf_name = "SMP-4473A9PU", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* CosMX Battery Information */ + [BATTERY_COS] = { + .fuel_gauge = { + .manuf_name = "333-AC-0D-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO; diff --git a/board/kracko/board.c b/board/kracko/board.c new file mode 100644 index 0000000000..2f69f43632 --- /dev/null +++ b/board/kracko/board.c @@ -0,0 +1,763 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Kracko board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "cros_board_info.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/sm5803.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +uint32_t board_version; + +/* GPIO to enable/disable the USB Type-A port. */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +__override void board_process_pd_alert(int port) +{ + /* + * PD_INT task will process this alert, and that task is only needed on + * C1. + */ + if (port != 1) + return; + + if (gpio_get_level(GPIO_USB_C1_INT_ODL)) + return; + + sm5803_handle_interrupt(port); +} + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + sm5803_interrupt(0); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void button_sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + int hdmi_hpd = gpio_get_level(GPIO_VOLUP_BTN_ODL_HDMI_HPD); + + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, hdmi_hpd); + else + button_interrupt(s); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +static void pen_detect_interrupt(enum gpio_signal s) +{ + int pen_detect = !gpio_get_level(GPIO_PEN_DET_ODL); + + gpio_set_level(GPIO_EN_PP5000_PEN, pen_detect); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_SUB_ANALOG] = { .name = "SUB_ANALOG", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, + [ADC_TEMP_SENSOR_4] = { .name = "TEMP_SENSOR4", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH16 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + [CHARGER_PRIMARY] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS, + .drv = &sm5803_drv, + }, + [CHARGER_SECONDARY] = { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS, + .drv = &sm5803_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &it83xx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, +}; + +/* Sensor Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Sensor Data */ +static struct accelgyro_saved_data_t g_bma253_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; +static struct kionix_accel_data g_kx022_data; + +/* Matrix to rotate accelrator into standard reference frame */ +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_kx022_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* Drivers */ +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_kx022_ref, + .default_range = 2, /* g, enough for laptop. */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void board_init(void) +{ + int on; + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) { + /* Select HDMI option */ + gpio_set_level(GPIO_HDMI_SEL_L, 0); + } else { + /* Select AUX option */ + gpio_set_level(GPIO_HDMI_SEL_L, 1); + } + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_INT_ODL); + + /* Store board version for use in determining charge limits */ + cbi_get_board_version(&board_version); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) + hook_call_deferred(&check_c1_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_PRESENT) { + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Second source LID ACCEL */ + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + ccprints("LID ACCEL is KX022"); + } else + ccprints("LID ACCEL is BMA253"); + /* Enable Base Accel interrupt */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } + + gpio_enable_interrupt(GPIO_PEN_DET_ODL); + + /* Make sure pen detection is triggered or not at sysjump */ + if (!gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_EN_PP5000_PEN, 1); + + /* Charger on the MB will be outputting PROCHOT_ODL and OD CHG_DET */ + sm5803_configure_gpio0(CHARGER_PRIMARY, GPIO0_MODE_PROCHOT, 1); + sm5803_configure_chg_det_od(CHARGER_PRIMARY, 1); + + if (board_get_charger_chip_count() > 1) { + /* Charger on the sub-board will be a push-pull GPIO */ + sm5803_configure_gpio0(CHARGER_SECONDARY, GPIO0_MODE_OUTPUT, 0); + } + + /* Turn on 5V if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_resume(void) +{ + sm5803_disable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_disable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); + +static void board_suspend(void) +{ + sm5803_enable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_enable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Put all charger ICs present into low power mode before entering + * z-state. + */ + sm5803_hibernate(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_hibernate(CHARGER_SECONDARY); +} + +__override void board_ocpc_init(struct ocpc_data *ocpc) +{ + /* There's no provision to measure Isys */ + ocpc->chg_flags[CHARGER_SECONDARY] |= OCPC_NO_ISYS_MEAS_CAP; +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + + if (board_get_charger_chip_count() > 1) { + if (sm5803_set_gpio0_level(1, !!enable)) + CPRINTUSB("Failed to %sable sub rails!", + enable ? "en" : "dis"); + } +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) + return CONFIG_USB_PD_PORT_MAX_COUNT; + + ccprints("Unhandled DB configuration: %d", db); + return 0; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) + return CHARGER_NUM - 1; + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) + return CHARGER_NUM; + + ccprints("Unhandled DB configuration: %d", db); + return 0; +} + +uint16_t tcpc_get_alert_status(void) +{ + /* + * TCPC 0 is embedded in the EC and processes interrupts in the chip + * code (it83xx/intc.c) + */ + + uint16_t status = 0; + int regval; + + /* Check whether TCPC 1 pulled the shared interrupt line */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Limit C1 on board version 0 to 2.0 A */ + if ((board_version == 0) && (port == 1)) + charge_ma = MIN(charge_ma, 2000); + /* + * TODO(b/151955431): Characterize the input current limit in case a + * scaling needs to be applied here + */ + charge_set_input_current_limit(charge_ma, charge_mv); +} + +int board_set_active_charge_port(int port) +{ + int is_valid_port = (port >= 0 && port < board_get_usb_pd_port_count()); + + if (!is_valid_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTUSB("Disabling all charge ports"); + + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 0); + + if (board_get_charger_chip_count() > 1) + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 0); + + return EC_SUCCESS; + } + + CPRINTUSB("New chg p%d", port); + + /* + * Ensure other port is turned off, then enable new charge port + */ + if (port == 0) { + if (board_get_charger_chip_count() > 1) + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 0); + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 1); + + } else { + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 0); + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 1); + } + + return EC_SUCCESS; +} + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* Vconn control is only for port 0 */ + if (port) + return; + + if (cc_pin == USBPD_CC_PIN_1) + gpio_set_level(GPIO_EN_USB_C0_CC1_VCONN, !!enabled); + else + gpio_set_level(GPIO_EN_USB_C0_CC2_VCONN, !!enabled); +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + int current; + + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + current = (rp == TYPEC_RP_3A0) ? 3000 : 1500; + + charger_set_otg_current_voltage(port, current, 5000); +} + +__override uint16_t board_get_ps8xxx_product_id(int port) +{ + /* Kracko variant doesn't have ps8xxx product in the port 0 */ + if (port == 0) + return 0; + + switch (get_cbi_ssfc_tcpc_p1()) { + case SSFC_TCPC_P1_PS8805: + return PS8805_PRODUCT_ID; + case SSFC_TCPC_P1_DEFAULT: + case SSFC_TCPC_P1_PS8705: + default: + return PS8705_PRODUCT_ID; + } +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 10000, + } }; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "5V regular", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 3; + *kp_div = 20; + + *ki = 3; + *ki_div = 125; + + *kd = 4; + *kd_div = 40; +} + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { GPIO_KSO_H, 4 }, { GPIO_KSO_H, 0 }, + { GPIO_KSO_H, 1 }, { GPIO_KSO_H, 3 }, { GPIO_KSO_H, 2 }, + { GPIO_KSO_L, 5 }, { GPIO_KSO_L, 6 }, { GPIO_KSO_L, 3 }, + { GPIO_KSO_L, 2 }, { GPIO_KSI, 0 }, { GPIO_KSO_L, 1 }, + { GPIO_KSO_L, 4 }, { GPIO_KSI, 3 }, { GPIO_KSI, 2 }, + { GPIO_KSO_L, 0 }, { GPIO_KSI, 5 }, { GPIO_KSI, 4 }, + { GPIO_KSO_L, 7 }, { GPIO_KSI, 6 }, { GPIO_KSI, 7 }, + { GPIO_KSI, 1 }, { -1, -1 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/kracko/board.h b/board/kracko/board.h new file mode 100644 index 0000000000..387680203c --- /dev/null +++ b/board/kracko/board.h @@ -0,0 +1,148 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Kracko board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +#undef GPIO_VOLUME_UP_L +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL_HDMI_HPD + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 15000 +#define CONFIG_USB_PD_VBUS_DETECT_CHARGER +#define CONFIG_USB_PD_5V_CHARGER_CTRL +#define CONFIG_CHARGER_OTG +#undef CONFIG_CHARGER_SINGLE_CHIP +#define CONFIG_OCPC +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 21 /* R_DS(on) 10.7mOhm + 10mOhm sns rstr \ + */ + +/* PWM */ +#define CONFIG_PWM + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES + +/* Sensors */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* Power of 2 - Too large of a fifo causes too much timestamp jitter */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* Keyboard */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_PWM_KBLIGHT + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_TCPM_MULTI_PS8XXX +#define CONFIG_USB_PD_TCPM_PS8705 /* C1: PS8705 TCPC */ +#define CONFIG_USB_PD_TCPM_PS8805 /* C1: second source PS8805 TCPC */ +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_SUB_ANALOG, /* ADC13 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_TEMP_SENSOR_4, /* ADC16 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_4, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_SIMPLO, + BATTERY_COS, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/kracko/build.mk b/board/kracko/build.mk new file mode 100644 index 0000000000..01b890bf29 --- /dev/null +++ b/board/kracko/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/kracko/cbi_ssfc.c b/board/kracko/cbi_ssfc.c new file mode 100644 index 0000000000..324ceffb63 --- /dev/null +++ b/board/kracko/cbi_ssfc.c @@ -0,0 +1,41 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} + +enum ec_ssfc_tcpc_p1 get_cbi_ssfc_tcpc_p1(void) +{ + return (enum ec_ssfc_tcpc_p1)cached_ssfc.tcpc_type; +} diff --git a/board/kracko/cbi_ssfc.h b/board/kracko/cbi_ssfc.h new file mode 100644 index 0000000000..ad35b1a139 --- /dev/null +++ b/board/kracko/cbi_ssfc.h @@ -0,0 +1,86 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +/* + * TCPC Port 1 (Bits 6-7) + */ +enum ec_ssfc_tcpc_p1 { + SSFC_TCPC_P1_DEFAULT, + SSFC_TCPC_P1_PS8705, + SSFC_TCPC_P1_PS8805, +}; + +/* + * Audio Codec Source(Bit 8-10) + */ +enum ec_ssfc_audio_codec_source { + SSFC_AUDIO_CODEC_DEFAULT = 0, + SSFC_AUDIO_CODEC_VD = 1, + SSFC_ADUIO_CODEC_VS = 2, +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t tcpc_type : 2; + uint32_t audio_codec_source : 3; + uint32_t reserved_2 : 21; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +/** + * Get the TCPC port 1 type from SSFC_CONFIG. + * + * @return the TCPC type. + */ +enum ec_ssfc_tcpc_p1 get_cbi_ssfc_tcpc_p1(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/kracko/ec.tasklist b/board/kracko/ec.tasklist new file mode 100644 index 0000000000..c13df44543 --- /dev/null +++ b/board/kracko/ec.tasklist @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/kracko/gpio.inc b/board/kracko/gpio.inc new file mode 100644 index 0000000000..a138a925f3 --- /dev/null +++ b/board/kracko/gpio.inc @@ -0,0 +1,148 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(USB_C1_INT_ODL, PIN(E, 6), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c1_interrupt) /* TCPC, charger, BC12 */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL_HDMI_HPD, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_sub_hdmi_hpd_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(PEN_DET_ODL, PIN(J, 1), GPIO_INT_BOTH | GPIO_PULL_UP, pen_detect_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EN_USB_A_5V, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC1_VCONN, PIN(H, 4), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC2_VCONN, PIN(H, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(USB_C0_FRS, PIN(C, 4), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_HIGH) + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc pins which will run to the I/O board */ +GPIO(EC_SUB_IO_1_2, PIN(F, 0), GPIO_INPUT) +GPIO(EC_SUB_IO_2_1, PIN(F, 1), GPIO_INPUT) + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(EN_KB_BL, PIN(J, 3), GPIO_OUT_LOW) /* Currently unused */ +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_PEN, PIN(B, 5), GPIO_OUT_LOW) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOA3_NC, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* LED */ +GPIO(BAT_LED_ORANGE_L, PIN(A, 1), GPIO_OUT_HIGH) /* LED_1_L */ +GPIO(BAT_LED_BLUE_L, PIN(A, 2), GPIO_OUT_HIGH) /* LED_2_L */ + +/* Alternate functions GPIO definitions */ +/* Keyboard */ +ALTERNATE(PIN_MASK(KSI, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSI0-7 */ +ALTERNATE(PIN_MASK(KSO_H, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO8-15 */ +ALTERNATE(PIN_MASK(KSO_L, 0xFB), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO0-1, 3-7 */ +GPIO(EC_KSO_02_INV, PIN(KSO_L, 2), GPIO_OUT_HIGH) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC13: EC_SUB_ANALOG, ADC15: TEMP_SENSOR_3, ADC16: TEMP_SENSOR_4 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(0)), 0, MODULE_PWM, 0) /* KB_BL_PWM */ diff --git a/board/kracko/led.c b/board/kracko/led.c new file mode 100644 index 0000000000..22a906807b --- /dev/null +++ b/board/kracko/led.c @@ -0,0 +1,79 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Power and battery LED control for Kracko. */ + +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; + +__override const int led_charge_lvl_2 = 100; + +/* Kracko: Note there is only LED for charge / power */ +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_BAT_LED_BLUE_L, LED_ON_LVL); + gpio_set_level(GPIO_BAT_LED_ORANGE_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_BAT_LED_BLUE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_ORANGE_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_BAT_LED_BLUE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_ORANGE_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_BLUE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + + return EC_SUCCESS; +} diff --git a/board/kracko/usb_pd_policy.c b/board/kracko/usb_pd_policy.c new file mode 100644 index 0000000000..8a2c07c575 --- /dev/null +++ b/board/kracko/usb_pd_policy.c @@ -0,0 +1,74 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/sm5803.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + if (port < 0 || port >= board_get_usb_pd_port_count()) + return; + + prev_en = charger_is_sourcing_otg_power(port); + + /* Disable Vbus */ + charger_enable_otg_power(port, 0); + + /* Discharge Vbus if previously enabled */ + if (prev_en) + sm5803_set_vbus_disch(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + enum ec_error_list rv; + + /* Disable sinking */ + rv = sm5803_vbus_sink_enable(port, 0); + if (rv) + return rv; + + /* Disable Vbus discharge */ + sm5803_set_vbus_disch(port, 0); + + /* Provide Vbus */ + charger_enable_otg_power(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +__override bool pd_check_vbus_level(int port, enum vbus_level level) +{ + return sm5803_check_vbus_level(port, level); +} + +int pd_snk_is_vbus_provided(int port) +{ + return sm5803_is_vbus_present(port); +} diff --git a/board/kracko/vif_override.xml b/board/kracko/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kracko/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kukui/board.c b/board/kukui/board.c index 0f6107ceaa..c76768f7d8 100644 --- a/board/kukui/board.c +++ b/board/kukui/board.c @@ -1,10 +1,9 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_manager.h" #include "charge_ramp.h" @@ -28,6 +27,7 @@ #include "host_command.h" #include "i2c.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -36,7 +36,7 @@ #include "spi.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" @@ -44,8 +44,8 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { @@ -57,23 +57,37 @@ static void gauge_interrupt(enum gpio_signal signal) task_wake(TASK_ID_CHARGER); } +#ifdef SECTION_IS_RW +static void motion_interrupt(enum gpio_signal signal); +#endif /* SECTION_IS_RW */ + +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, - [ADC_BATT_ID] = {"BATT_ID", 3300, 4096, 0, STM32_AIN(7)}, - [ADC_POGO_ADC_INT_L] = {"POGO_ADC_INT_L", 3300, 4096, 0, STM32_AIN(6)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, + [ADC_BATT_ID] = { "BATT_ID", 3300, 4096, 0, STM32_AIN(7) }, + [ADC_POGO_ADC_INT_L] = { "POGO_ADC_INT_L", 3300, 4096, 0, + STM32_AIN(6) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -81,15 +95,14 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ @@ -119,9 +132,12 @@ void board_set_dp_mux_control(int output_enable, int polarity) gpio_set_level(GPIO_USB_C0_DP_POLARITY, polarity); } -static void board_hpd_update(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_update(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -143,13 +159,17 @@ __override const struct rt946x_init_setting *board_rt946x_init_setting(void) return &battery_init_setting; } -struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +struct usb_mux usbc0_mux0 = { + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_update, +}; + +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_update, + .mux = &usbc0_mux0, }, }; @@ -187,7 +207,7 @@ int board_set_active_charge_port(int charge_port) gpio_set_level(GPIO_EN_POGO_CHARGE_L, 0); break; #endif - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -197,9 +217,6 @@ int board_set_active_charge_port(int charge_port) gpio_set_level(GPIO_EN_USBC_CHARGE_L, 1); charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; @@ -247,9 +264,8 @@ int extpower_is_present(void) if (board_vbus_source_enabled(CHARGE_PORT_USB_C)) usb_c_extpower_present = 0; else - usb_c_extpower_present = tcpm_check_vbus_level( - CHARGE_PORT_USB_C, - VBUS_PRESENT); + usb_c_extpower_present = + tcpm_check_vbus_level(CHARGE_PORT_USB_C, VBUS_PRESENT); return usb_c_extpower_present || kukui_pogo_extpower_present(); } @@ -338,15 +354,15 @@ static void board_rev_init(void) /* configure PI3USB9201 to USB Path ON Mode */ i2c_write8(I2C_PORT_BC12, BC12_I2C_ADDR_FLAGS, PI3USB9201_REG_CTRL_1, - (PI3USB9201_USB_PATH_ON << - PI3USB9201_REG_CTRL_1_MODE_SHIFT)); + (PI3USB9201_USB_PATH_ON + << PI3USB9201_REG_CTRL_1_MODE_SHIFT)); } if (board_get_version() < 5) { gpio_set_flags(GPIO_USB_C0_DP_OE_L, GPIO_OUT_HIGH); gpio_set_flags(GPIO_USB_C0_DP_POLARITY, GPIO_OUT_LOW); - usb_muxes[0].driver = &virtual_usb_mux_driver; - usb_muxes[0].hpd_update = &virtual_hpd_update; + usbc0_mux0.driver = &virtual_usb_mux_driver; + usbc0_mux0.hpd_update = &virtual_hpd_update; } } DECLARE_HOOK(HOOK_INIT, board_rev_init, HOOK_PRIO_INIT_ADC + 1); @@ -419,26 +435,20 @@ static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { /* Matrix to rotate accelerometer into standard reference frame */ #ifdef BOARD_KUKUI -static const mat33_fp_t lid_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(1), 0}, - {0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; #else -static const mat33_fp_t lid_standard_ref = { - {FLOAT_TO_FP(-1), 0, 0}, - {0, FLOAT_TO_FP(-1), 0}, - {0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; #endif /* BOARD_KUKUI */ #ifdef CONFIG_MAG_BMI_BMM150 /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t mag_standard_ref = { - {0, FLOAT_TO_FP(-1), 0}, - {FLOAT_TO_FP(-1), 0, 0}, - {0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t mag_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; #endif /* CONFIG_MAG_BMI_BMM150 */ struct motion_sensor_t motion_sensors[] = { @@ -506,7 +516,10 @@ struct motion_sensor_t motion_sensors[] = { .default_range = BIT(11), /* 16LSB / uT, fixed */ .rot_standard_ref = &mag_standard_ref, .min_frequency = BMM150_MAG_MIN_FREQ, +/* TODO(b/253292373): Remove when clang is fixed. */ +DISABLE_CLANG_WARNING("-Wshift-count-negative") .max_frequency = BMM150_MAG_MAX_FREQ(SPECIAL), +ENABLE_CLANG_WARNING("-Wshift-count-negative") }, #endif /* CONFIG_MAG_BMI_BMM150 */ [CLEAR_ALS] = { @@ -560,8 +573,62 @@ const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); const struct motion_sensor_t *motion_als_sensors[] = { &motion_sensors[CLEAR_ALS], }; + +#ifdef BOARD_KRANE + +static bool is_bmi220_present; + +static void board_detect_bmi220(void) +{ + int id = -1; + struct motion_sensor_t *s; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + + /* Detect accelgyro chip */ + bmi_read8(I2C_PORT_ACCEL, BMI260_ADDR0_FLAGS, BMI260_CHIP_ID, &id); + if (id == BMI220_CHIP_ID_MAJOR) { + is_bmi220_present = true; + /* Lid Accel*/ + s = &motion_sensors[LID_ACCEL]; + s->chip = MOTIONSENSE_CHIP_BMI220; + s->drv = &bmi260_drv; + s->i2c_spi_addr_flags = BMI260_ADDR0_FLAGS; + /* Lid Gyro */ + s = &motion_sensors[LID_GYRO]; + s->chip = MOTIONSENSE_CHIP_BMI220; + s->drv = &bmi260_drv; + s->i2c_spi_addr_flags = BMI260_ADDR0_FLAGS; +#ifdef CONFIG_MAG_BMI_BMM150 + /* Lid Mag */ + s = &motion_sensors[LID_MAG]; + s->chip = MOTIONSENSE_CHIP_BMI220; + s->drv = &bmi260_drv; + s->i2c_spi_addr_flags = BMI260_ADDR0_FLAGS; +#endif /* CONFIG_MAG_BMI_BMM150 */ + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_bmi220, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_bmi220, HOOK_PRIO_DEFAULT + 1); +#endif /* BOARD_KRANE */ + #endif /* VARIANT_KUKUI_NO_SENSORS */ +#ifdef SECTION_IS_RW +static void motion_interrupt(enum gpio_signal signal) +{ +#if defined(BOARD_KRANE) + if (is_bmi220_present) + bmi260_interrupt(signal); + else + bmi160_interrupt(signal); +#elif !defined(VARIANT_KUKUI_NO_SENSORS) + bmi160_interrupt(signal); +#endif /* BOARD_KRANE, !VARIANT_KUKUI_NO_SENSORS */ +} +#endif /* SECTION_IS_RW */ + /* * Return if VBUS is sagging too low */ @@ -595,9 +662,8 @@ __override int board_charge_port_is_connected(int port) return gpio_get_level(GPIO_POGO_VBUS_PRESENT); } -__override -void board_fill_source_power_info(int port, - struct ec_response_usb_pd_power_info *r) +__override void +board_fill_source_power_info(int port, struct ec_response_usb_pd_power_info *r) { r->meas.voltage_now = 3300; r->meas.voltage_max = 3300; diff --git a/board/kukui/board.h b/board/kukui/board.h index 3320a53472..94c05a1209 100644 --- a/board/kukui/board.h +++ b/board/kukui/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,6 +16,7 @@ #endif #define VARIANT_KUKUI_CHARGER_MT6370 +#define VARIANT_KUKUI_EC_STM32F098 #define VARIANT_KUKUI_DP_MUX_GPIO #define VARIANT_KUKUI_TABLET_PWRBTN @@ -30,11 +31,15 @@ #define CONFIG_VOLUME_BUTTONS #define CONFIG_USB_MUX_RUNTIME_CONFIG +#ifdef SECTION_IS_RO +#define CONFIG_CMD_PD_SRCCAPS_REDUCED_SIZE +#endif /* SECTION_IS_RO */ + /* Battery */ #ifdef BOARD_KRANE -#define BATTERY_DESIRED_CHARGING_CURRENT 3500 /* mA */ +#define BATTERY_DESIRED_CHARGING_CURRENT 3500 /* mA */ #else -#define BATTERY_DESIRED_CHARGING_CURRENT 2000 /* mA */ +#define BATTERY_DESIRED_CHARGING_CURRENT 2000 /* mA */ #endif /* BOARD_KRANE */ #ifdef BOARD_KRANE @@ -54,9 +59,14 @@ #define CONFIG_MAG_CALIBRATE #endif /* !BOARD_KRANE */ #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) +#ifdef BOARD_KRANE +#define CONFIG_I2C_XFER_LARGE_TRANSFER +#define CONFIG_ACCELGYRO_BMI220 +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) +#endif /* BOARD_KRANE */ #define CONFIG_ALS #define ALS_COUNT 1 @@ -69,30 +79,24 @@ /* Camera VSYNC */ #define CONFIG_SYNC #define CONFIG_SYNC_COMMAND -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) #endif /* SECTION_IS_RW */ /* I2C ports */ -#define I2C_PORT_CHARGER 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_BATTERY 1 +#define I2C_PORT_CHARGER 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_BATTERY 1 #define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY -#define I2C_PORT_ACCEL 1 -#define I2C_PORT_BC12 1 -#define I2C_PORT_ALS 1 +#define I2C_PORT_ACCEL 1 +#define I2C_PORT_BC12 1 +#define I2C_PORT_ALS 1 /* Route sbs host requests to virtual battery driver */ #define VIRTUAL_BATTERY_ADDR_FLAGS 0x0B -/* Define the host events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE)) - /* MKBP */ +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_EVENT_WAKEUP_MASK \ (BIT(EC_MKBP_EVENT_SENSOR_FIFO) | BIT(EC_MKBP_EVENT_HOST_EVENT)) @@ -149,20 +153,19 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); void pogo_adc_interrupt(enum gpio_signal signal); int board_discharge_on_ac(int enable); /* Enable double tap detection */ #define CONFIG_GESTURE_DETECTION #define CONFIG_GESTURE_HOST_DETECTION -#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP 0 -#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP_FOR_HOST +#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP +#define CONFIG_GESTURE_TAP_FOR_HOST #define CONFIG_GESTURE_SAMPLING_INTERVAL_MS 5 #define CONFIG_GESTURE_TAP_THRES_MG 100 #define CONFIG_GESTURE_TAP_MAX_INTERSTICE_T 500 -#define CONFIG_GESTURE_DETECTION_MASK \ - BIT(CONFIG_GESTURE_SENSOR_DOUBLE_TAP) +#define CONFIG_GESTURE_TAP_SENSOR 0 +#define CONFIG_GESTURE_DETECTION_MASK BIT(CONFIG_GESTURE_TAP_SENSOR) #endif /* !__ASSEMBLER__ */ diff --git a/board/kukui/build.mk b/board/kukui/build.mk index 694879cee6..b60b9cf091 100644 --- a/board/kukui/build.mk +++ b/board/kukui/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/kukui/ec.tasklist b/board/kukui/ec.tasklist index 9ba564ce52..2551038b66 100644 --- a/board/kukui/ec.tasklist +++ b/board/kukui/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/kukui/gpio.inc b/board/kukui/gpio.inc index 1f17a24bcd..efac70d681 100644 --- a/board/kukui/gpio.inc +++ b/board/kukui/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -30,7 +30,7 @@ GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 2), GPIO_INT_FALLING, chipset_watchdog_interrupt) GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, - bmi160_interrupt) + motion_interrupt) GPIO_INT(CHARGER_INT_ODL, PIN(C, 13), GPIO_INT_FALLING | GPIO_PULL_UP, rt946x_interrupt) GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, diff --git a/board/kukui/led.c b/board/kukui/led.c index 59f7681754..b6836f49fb 100644 --- a/board/kukui/led.c +++ b/board/kukui/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -15,46 +15,45 @@ const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -static enum charge_state prv_chstate = PWR_STATE_INIT; +static enum led_pwr_state prv_chstate = LED_PWRS_INIT; -#define LED_OFF MT6370_LED_ID_OFF -#define LED_RED MT6370_LED_ID1 -#define LED_GREEN MT6370_LED_ID2 -#define LED_BLUE MT6370_LED_ID3 +#define LED_OFF MT6370_LED_ID_OFF +#define LED_RED MT6370_LED_ID1 +#define LED_GREEN MT6370_LED_ID2 +#define LED_BLUE MT6370_LED_ID3 -#define LED_MASK_OFF 0 -#define LED_MASK_RED MT6370_MASK_RGB_ISNK1DIM_EN -#define LED_MASK_GREEN MT6370_MASK_RGB_ISNK2DIM_EN -#define LED_MASK_BLUE MT6370_MASK_RGB_ISNK3DIM_EN +#define LED_MASK_OFF 0 +#define LED_MASK_RED MT6370_MASK_RGB_ISNK1DIM_EN +#define LED_MASK_GREEN MT6370_MASK_RGB_ISNK2DIM_EN +#define LED_MASK_BLUE MT6370_MASK_RGB_ISNK3DIM_EN static void kukui_led_set_battery(void) { - enum charge_state chstate; + enum led_pwr_state chstate; static uint8_t prv_r, prv_g, prv_b; uint8_t br[EC_LED_COLOR_COUNT] = { 0 }; - chstate = charge_get_state(); + chstate = led_pwr_get_state(); - if (prv_chstate == chstate && - chstate != PWR_STATE_DISCHARGE) + if (prv_chstate == chstate && chstate != LED_PWRS_DISCHARGE) return; prv_chstate = chstate; switch (chstate) { - case PWR_STATE_CHARGE: + case LED_PWRS_CHARGE: /* RGB(current, duty) = (4mA,1/32)*/ br[EC_LED_COLOR_BLUE] = 1; break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: /* display SoC 10% = real battery SoC 13%*/ if (charge_get_percent() <= 13) br[EC_LED_COLOR_RED] = 1; break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: br[EC_LED_COLOR_GREEN] = 1; break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: br[EC_LED_COLOR_RED] = 1; break; default: @@ -62,8 +61,7 @@ static void kukui_led_set_battery(void) return; } - if (prv_r == br[EC_LED_COLOR_RED] && - prv_g == br[EC_LED_COLOR_GREEN] && + if (prv_r == br[EC_LED_COLOR_RED] && prv_g == br[EC_LED_COLOR_GREEN] && prv_b == br[EC_LED_COLOR_BLUE]) return; @@ -111,7 +109,7 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) */ static void led_reset_auto_control(void) { - prv_chstate = PWR_STATE_INIT; + prv_chstate = LED_PWRS_INIT; } static void krane_led_init(void) diff --git a/board/kukui/vif_override.xml b/board/kukui/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kukui/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/kukui_scp/board.c b/board/kukui_scp/board.c index e5c4f0c760..e961b91a94 100644 --- a/board/kukui_scp/board.c +++ b/board/kukui_scp/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,6 +16,5 @@ #include "timer.h" #include "util.h" -/* Build GPIO tables */ +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" - diff --git a/board/kukui_scp/board.h b/board/kukui_scp/board.h index fcd9fb6399..fb074c59e0 100644 --- a/board/kukui_scp/board.h +++ b/board/kukui_scp/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,9 +10,14 @@ #define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_HOSTCMD) | CC_MASK(CC_IPI))) -#define CONFIG_FLASH_SIZE 0x58000 /* Image file size: 256KB */ -#undef CONFIG_LID_SWITCH -#undef CONFIG_FW_INCLUDE_RO +#ifdef CHIP_VARIANT_MT8186 +#define CONFIG_FLASH_SIZE_BYTES 0x2C000 /* SRAM Size: 256KB */ +#else +#define CONFIG_FLASH_SIZE_BYTES 0x58000 /* Image file size: 256KB */ +#endif + +#undef CONFIG_LID_SWITCH +#undef CONFIG_FW_INCLUDE_RO #define CONFIG_MKBP_EVENT /* Sent MKBP event via IPI. */ #define CONFIG_MKBP_USE_CUSTOM @@ -22,10 +27,12 @@ #define CONFIG_HOSTCMD_ALIGNED /* + * mt8183: + * * RW only, no flash * +-------------------- 0x0 * | ROM vectortable, .text, .rodata, .data LMA - * +-------------------- 0x10000 + * +-------------------- 0x58000 * | RAM .bss, .data * +-------------------- 0x7BDB0 * | IPI shared buffer with AP (288 + 8) * 2 @@ -35,9 +42,38 @@ * | 8KB D-CACHE * +-------------------- 0x80000 */ -#define ICACHE_BASE 0x7C000 + +/* + * mt8186: + * + * RW only, no flash + * +-------------------- 0x0 + * | ROM vectortable, .text, .rodata, .data LMA + * +-------------------- 0x2C000 + * | RAM .bss, .data + * +-------------------- 0x3BDB0 + * | IPI shared buffer with AP (288 + 8) * 2 => 0x250 + * +-------------------- 0x3C000 + * | 8KB I-CACHE + * +-------------------- 0x3E000 + * | 8KB D-CACHE + * +-------------------- 0x40000 + */ + #define CONFIG_ROM_BASE 0x0 + +#ifdef CHIP_VARIANT_MT8186 +#define CONFIG_RAM_BASE 0x2C000 +#else #define CONFIG_RAM_BASE 0x58000 +#endif + +#ifdef CHIP_VARIANT_MT8186 +#define ICACHE_BASE 0x3C000 +#else +#define ICACHE_BASE 0x7C000 +#endif + #define CONFIG_ROM_SIZE (CONFIG_RAM_BASE - CONFIG_ROM_BASE) #define CONFIG_RAM_SIZE (CONFIG_IPC_SHARED_OBJ_ADDR - CONFIG_RAM_BASE) #define CONFIG_CODE_RAM_SIZE CONFIG_RAM_BASE @@ -48,12 +84,19 @@ #define CONFIG_DRAM_BASE 0x10000000 /* Shared memory address in AP physical address space. */ #define CONFIG_DRAM_BASE_LOAD 0x50000000 + +#ifdef CHIP_VARIANT_MT8186 +#define CONFIG_DRAM_SIZE 0x010a0000 /* 16 MB */ +#define CACHE_TRANS_AP_SIZE 0x010a0000 +#else #define CONFIG_DRAM_SIZE 0x01400000 /* 20 MB */ +#define CACHE_TRANS_AP_SIZE 0x00400000 +#endif /* IPI configs */ #define CONFIG_IPC_SHARED_OBJ_BUF_SIZE 288 -#define CONFIG_IPC_SHARED_OBJ_ADDR \ - (ICACHE_BASE - \ +#define CONFIG_IPC_SHARED_OBJ_ADDR \ + (ICACHE_BASE - \ (CONFIG_IPC_SHARED_OBJ_BUF_SIZE + 2 * 4 /* int32_t */) * 2) #define CONFIG_IPI #define CONFIG_RPMSG_NAME_SERVICE @@ -75,28 +118,30 @@ #define IPI_ISP_FRAME 11 #define IPI_FD_CMD 12 #define IPI_HOST_COMMAND 13 -#define IPI_COUNT 14 +#define SCP_IPI_VDEC_LAT 14 +#define SCP_IPI_VDEC_CORE 15 +#define IPI_COUNT 16 #define IPI_NS_SERVICE 0xFF -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ - #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 8192 -#undef CONFIG_UART_CONSOLE +#undef CONFIG_UART_CONSOLE /* * CONFIG_UART_CONSOLE * 0 - SCP UART0 * 1 - SCP UART1 * 2 - share with AP UART0 */ +#ifdef CHIP_VARIANT_MT8186 +#define CONFIG_UART_CONSOLE 1 +#else #define CONFIG_UART_CONSOLE 0 - +#endif /* We let AP setup the correct pinmux. */ -#undef UART0_PINMUX_11_12 -#undef UART0_PINMUX_110_112 +#undef UART0_PINMUX_11_12 +#undef UART0_PINMUX_110_112 /* Track AP power state */ #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE diff --git a/board/kukui_scp/build.mk b/board/kukui_scp/build.mk index 19355b5af5..f04d506057 100644 --- a/board/kukui_scp/build.mk +++ b/board/kukui_scp/build.mk @@ -1,12 +1,17 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Board specific files build # CHIP:=mt_scp + +ifeq ($(BOARD), corsola_scp) +CHIP_VARIANT:=mt8186 +else CHIP_VARIANT:=mt8183 +endif board-y=board.o board-$(HAS_TASK_VDEC_SERVICE)+=vdec.o diff --git a/board/kukui_scp/ec.tasklist b/board/kukui_scp/ec.tasklist index 935d409b00..179e1b7c7f 100644 --- a/board/kukui_scp/ec.tasklist +++ b/board/kukui_scp/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,13 +14,24 @@ #define UART_TASK #endif +#ifdef HAVE_PRIVATE_MT8183 #define S3_SUSPEND_TASK_LIST \ TASK_ALWAYS(VDEC_SERVICE, vdec_service_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(VENC_SERVICE, venc_service_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(FD_SERVICE, fd_service_task, NULL, 760) \ TASK_ALWAYS(DIP_SERVICE, dip_service_task, NULL, 6400) \ + TASK_ALWAYS(ISP_SERVICE, isp_service_task, NULL, 880) \ TASK_ALWAYS(MDP_SERVICE, mdp_service_task, NULL, 1800) \ - TASK_ALWAYS(ISP_SERVICE, isp_service_task, NULL, 880) + TASK_ALWAYS(VENC_SERVICE, venc_service_task, NULL, LARGER_TASK_STACK_SIZE) +#else +#define S3_SUSPEND_TASK_LIST \ + TASK_ALWAYS(VDEC_SERVICE, vdec_service_task, NULL, 4096) \ + TASK_ALWAYS(VDEC_CORE_SERVICE, vdec_core_service_task, NULL, 4096) \ + TASK_ALWAYS(MDP_SERVICE, mdp_service_task, NULL, 1800) \ + TASK_ALWAYS(FD_SERVICE, fd_service_task, NULL, 760) \ + TASK_ALWAYS(DIP_SERVICE, dip_service_task, NULL, 6400) \ + TASK_ALWAYS(ISP_SERVICE, isp_service_task, NULL, 880) \ + TASK_ALWAYS(VENC_SERVICE, venc_service_task, NULL, LARGER_TASK_STACK_SIZE) +#endif #define CONFIG_TASK_LIST \ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/kukui_scp/fd.c b/board/kukui_scp/fd.c index 11f27cf945..be0bdeab57 100644 --- a/board/kukui_scp/fd.c +++ b/board/kukui_scp/fd.c @@ -1,17 +1,17 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "chip/mt_scp/ipi_chip.h" -#include "chip/mt_scp/registers.h" #include "console.h" -#include "hooks.h" -#include "task.h" -#include "util.h" #include "fd.h" +#include "hooks.h" +#include "ipi_chip.h" #include "queue.h" #include "queue_policies.h" +#include "registers.h" +#include "task.h" +#include "util.h" #define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) #define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) @@ -20,12 +20,11 @@ static struct consumer const event_fd_consumer; static void event_fd_written(struct consumer const *consumer, size_t count); -static struct queue const fd_queue = QUEUE_DIRECT(4, struct fd_msg, - null_producer, - event_fd_consumer); +static struct queue const fd_queue = + QUEUE_DIRECT(4, struct fd_msg, null_producer, event_fd_consumer); static struct consumer const event_fd_consumer = { .queue = &fd_queue, - .ops = &((struct consumer_ops const) { + .ops = &((struct consumer_ops const){ .written = event_fd_written, }), }; @@ -33,7 +32,9 @@ static struct consumer const event_fd_consumer = { /* Stub functions only provided by private overlays. */ // Jerry TODO implement private part and remove this #ifndef HAVE_PRIVATE_MT8183 -void fd_ipi_msg_handler(void *data) {} +void fd_ipi_msg_handler(void *data) +{ +} #endif static void event_fd_written(struct consumer const *consumer, size_t count) diff --git a/board/kukui_scp/fd.h b/board/kukui_scp/fd.h index 07554f7e15..cea5817942 100644 --- a/board/kukui_scp/fd.h +++ b/board/kukui_scp/fd.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,9 +6,9 @@ #ifndef __CROS_EC_SCP_FD_H #define __CROS_EC_SCP_FD_H -#include "chip/mt_scp/registers.h" -#include "queue.h" #include "compile_time_macros.h" +#include "queue.h" +#include "registers.h" enum fd_msg_type { FD_IPI_MSG, diff --git a/board/kukui_scp/gpio.inc b/board/kukui_scp/gpio.inc index b186904aad..6cc2e0495e 100644 --- a/board/kukui_scp/gpio.inc +++ b/board/kukui_scp/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/kukui_scp/isp_p1_srv.c b/board/kukui_scp/isp_p1_srv.c index 92048f98c1..40dd37ff90 100644 --- a/board/kukui_scp/isp_p1_srv.c +++ b/board/kukui_scp/isp_p1_srv.c @@ -1,17 +1,17 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "chip/mt_scp/ipi_chip.h" -#include "chip/mt_scp/registers.h" #include "console.h" #include "dma.h" #include "hooks.h" +#include "ipi_chip.h" #include "isp_p1_srv.h" -#include "task.h" #include "queue.h" #include "queue_policies.h" +#include "registers.h" +#include "task.h" #include "util.h" #define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) @@ -20,19 +20,21 @@ static struct consumer const event_isp_consumer; static void event_isp_written(struct consumer const *consumer, size_t count); -static struct queue const event_isp_queue = QUEUE_DIRECT(8, - struct isp_msg, null_producer, event_isp_consumer); +static struct queue const event_isp_queue = + QUEUE_DIRECT(8, struct isp_msg, null_producer, event_isp_consumer); static struct consumer const event_isp_consumer = { .queue = &event_isp_queue, - .ops = &((struct consumer_ops const) { + .ops = &((struct consumer_ops const){ .written = event_isp_written, }), }; /* Stub functions only provided by private overlays. */ #ifndef HAVE_PRIVATE_MT8183 -void isp_msg_handler(void *data) {} +void isp_msg_handler(void *data) +{ +} #endif static void event_isp_written(struct consumer const *consumer, size_t count) diff --git a/board/kukui_scp/isp_p1_srv.h b/board/kukui_scp/isp_p1_srv.h index 6e262b55e4..e0abe9e4c8 100644 --- a/board/kukui_scp/isp_p1_srv.h +++ b/board/kukui_scp/isp_p1_srv.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,14 +6,15 @@ #ifndef __CROS_EC_ISP_P1_SRV_H #define __CROS_EC_ISP_P1_SRV_H -#include "chip/mt_scp/ipi_chip.h" +#include "ipi_chip.h" struct isp_msg { unsigned char id; unsigned char msg[140]; }; -BUILD_ASSERT(member_size(struct isp_msg, msg) <= CONFIG_IPC_SHARED_OBJ_BUF_SIZE); +BUILD_ASSERT(member_size(struct isp_msg, msg) <= + CONFIG_IPC_SHARED_OBJ_BUF_SIZE); /* Functions provided by private overlay. */ void isp_msg_handler(void *data); diff --git a/board/kukui_scp/isp_p2_srv.c b/board/kukui_scp/isp_p2_srv.c old mode 100755 new mode 100644 index 5acb81ae0f..f38d4401ff --- a/board/kukui_scp/isp_p2_srv.c +++ b/board/kukui_scp/isp_p2_srv.c @@ -1,17 +1,17 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "isp_p2_srv.h" -#include "chip/mt_scp/ipi_chip.h" -#include "chip/mt_scp/registers.h" -#include "queue_policies.h" #include "console.h" #include "hooks.h" +#include "ipi_chip.h" +#include "isp_p2_srv.h" +#include "queue.h" +#include "queue_policies.h" +#include "registers.h" #include "task.h" #include "util.h" -#include "queue.h" #define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) @@ -19,19 +19,21 @@ static struct consumer const event_dip_consumer; static void event_dip_written(struct consumer const *consumer, size_t count); -static struct queue const event_dip_queue = QUEUE_DIRECT(4, - struct dip_msg_service, null_producer, event_dip_consumer); +static struct queue const event_dip_queue = QUEUE_DIRECT( + 4, struct dip_msg_service, null_producer, event_dip_consumer); static struct consumer const event_dip_consumer = { .queue = &event_dip_queue, - .ops = &((struct consumer_ops const) { + .ops = &((struct consumer_ops const){ .written = event_dip_written, }), }; /* Stub functions only provided by private overlays. */ #ifndef HAVE_PRIVATE_MT8183 -void dip_msg_handler(void *data) {} +void dip_msg_handler(void *data) +{ +} #endif static void event_dip_written(struct consumer const *consumer, size_t count) diff --git a/board/kukui_scp/isp_p2_srv.h b/board/kukui_scp/isp_p2_srv.h index 196de3e092..3c1ba50f1c 100644 --- a/board/kukui_scp/isp_p2_srv.h +++ b/board/kukui_scp/isp_p2_srv.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,14 +6,15 @@ #ifndef __CROS_EC_ISP_P2_SRV_H #define __CROS_EC_ISP_P2_SRV_H -#include "chip/mt_scp/ipi_chip.h" +#include "ipi_chip.h" struct dip_msg_service { unsigned char id; unsigned char msg[288]; }; -BUILD_ASSERT(member_size(struct dip_msg_service, msg) <= CONFIG_IPC_SHARED_OBJ_BUF_SIZE); +BUILD_ASSERT(member_size(struct dip_msg_service, msg) <= + CONFIG_IPC_SHARED_OBJ_BUF_SIZE); /* Functions provided by private overlay. */ void dip_msg_handler(void *data); diff --git a/board/kukui_scp/mdp_ipi_message.c b/board/kukui_scp/mdp_ipi_message.c index a33048821f..fd6da65a07 100644 --- a/board/kukui_scp/mdp_ipi_message.c +++ b/board/kukui_scp/mdp_ipi_message.c @@ -1,17 +1,16 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "console.h" +#include "ipi_chip.h" +#include "mdp_ipi_message.h" #include "queue_policies.h" +#include "registers.h" #include "task.h" #include "util.h" -#include "chip/mt_scp/ipi_chip.h" -#include "chip/mt_scp/registers.h" -#include "mdp_ipi_message.h" - #define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) #define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) @@ -19,19 +18,25 @@ static struct consumer const event_mdp_consumer; static void event_mdp_written(struct consumer const *consumer, size_t count); -static struct queue const event_mdp_queue = QUEUE_DIRECT(4, - struct mdp_msg_service, null_producer, event_mdp_consumer); +static struct queue const event_mdp_queue = QUEUE_DIRECT( + 4, struct mdp_msg_service, null_producer, event_mdp_consumer); static struct consumer const event_mdp_consumer = { .queue = &event_mdp_queue, - .ops = &((struct consumer_ops const) { + .ops = &((struct consumer_ops const){ .written = event_mdp_written, }), }; /* Stub functions only provided by private overlays. */ #ifndef HAVE_PRIVATE_MT8183 -void mdp_common_init(void) {} -void mdp_ipi_task_handler(void *pvParameters) {} +#ifndef HAVE_PRIVATE_MT8186 +void mdp_common_init(void) +{ +} +void mdp_ipi_task_handler(void *pvParameters) +{ +} +#endif #endif static void event_mdp_written(struct consumer const *consumer, size_t count) diff --git a/board/kukui_scp/mdp_ipi_message.h b/board/kukui_scp/mdp_ipi_message.h index bcedb58504..0e46b947b2 100644 --- a/board/kukui_scp/mdp_ipi_message.h +++ b/board/kukui_scp/mdp_ipi_message.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,9 +11,10 @@ struct mdp_msg_service { unsigned char msg[20]; }; -BUILD_ASSERT(member_size(struct mdp_msg_service, msg) <= CONFIG_IPC_SHARED_OBJ_BUF_SIZE); +BUILD_ASSERT(member_size(struct mdp_msg_service, msg) <= + CONFIG_IPC_SHARED_OBJ_BUF_SIZE); void mdp_common_init(void); void mdp_ipi_task_handler(void *pvParameters); -#endif // _MDP_IPI_MESSAGE_H +#endif // _MDP_IPI_MESSAGE_H diff --git a/board/kukui_scp/update_scp b/board/kukui_scp/update_scp index 846095a7f9..67aaacdcdc 100755 --- a/board/kukui_scp/update_scp +++ b/board/kukui_scp/update_scp @@ -1,12 +1,12 @@ #!/bin/bash -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2022 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. usage() { - echo "Usage: $0 [IP] [bin/elf]" >&2 + echo "Usage: $0 [kukui_scp/corsola_scp] [IP] [bin/elf]" >&2 echo >&2 - echo "Deploy kukui_scp image to DUT, and restart the remoteproc driver" >&2 + echo "Deploy kukui_scp/corsola_scp image to DUT, and restart the remoteproc driver" >&2 exit 2 } @@ -14,25 +14,31 @@ if [[ -z "$1" ]]; then usage fi -KUKUI_IP="$1" -INFILE="build/kukui_scp/ec.bin" +if [ "$1" = "kukui_scp" ] || [ "$1" = "corsola_scp" ]; then + BOARD="$1" +else + usage +fi + +DUT_IP="$2" +INFILE="build/$BOARD/ec.bin" -case "$2" in +case "$3" in bin) ;; elf|"") # Default # ec.obj is an elf file that has the right memory layout to be loaded # from the AP/kernel. - INFILE="build/kukui_scp/ec.obj" + INFILE="build/$BOARD/ec.obj" ;; *) usage ;; esac -scp "$INFILE" "$KUKUI_IP":/lib/firmware/scp.img +scp "$INFILE" "$DUT_IP":/lib/firmware/scp.img -ssh "$KUKUI_IP" sh -x -c "' +ssh "$DUT_IP" sh -x -c "' sync; echo stop > /sys/class/remoteproc/remoteproc0/state; echo start > /sys/class/remoteproc/remoteproc0/state'" diff --git a/board/kukui_scp/vdec.c b/board/kukui_scp/vdec.c index 6ab257b08e..fcc327d764 100644 --- a/board/kukui_scp/vdec.c +++ b/board/kukui_scp/vdec.c @@ -1,55 +1,89 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2022 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "chip/mt_scp/ipi_chip.h" -#include "chip/mt_scp/registers.h" #include "console.h" -#include "hooks.h" +#include "ipi_chip.h" +#include "queue_policies.h" +#include "registers.h" #include "task.h" #include "util.h" #include "vdec.h" +#ifdef HAVE_PRIVATE_MT8183 +#include "hooks.h" #include "queue.h" -#include "queue_policies.h" +#else +#include "link_defs.h" +#endif #define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) #define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) -/* Forwad declaration. */ +static void event_vdec_written(struct consumer const *consumer, size_t count) +{ + task_wake(TASK_ID_VDEC_SERVICE); +} static struct consumer const event_vdec_consumer; -static void event_vdec_written(struct consumer const *consumer, size_t count); - -static struct queue const event_vdec_queue = QUEUE_DIRECT(8, - struct vdec_msg, null_producer, event_vdec_consumer); +static struct queue const event_vdec_queue = + QUEUE_DIRECT(8, struct vdec_msg, null_producer, event_vdec_consumer); static struct consumer const event_vdec_consumer = { .queue = &event_vdec_queue, - .ops = &((struct consumer_ops const) { + .ops = &((struct consumer_ops const){ .written = event_vdec_written, }), }; -/* Stub functions only provided by private overlays. */ +/* + * Only need to separate 8183 and others. + * 8183's architecture is different with other platforms. + * 8186 and future platform's architecture is the same, won't change anymore. + */ #ifndef HAVE_PRIVATE_MT8183 -void vdec_h264_service_init(void) {} -void vdec_h264_msg_handler(void *data) {} -#endif - +static void event_vdec_core_written(struct consumer const *consumer, + size_t count) +{ + task_wake(TASK_ID_VDEC_CORE_SERVICE); +} +static struct consumer const event_vdec_core_consumer; +static struct queue const event_vdec_core_queue = QUEUE_DIRECT( + 8, struct vdec_msg, null_producer, event_vdec_core_consumer); +static struct consumer const event_vdec_core_consumer = { + .queue = &event_vdec_core_queue, + .ops = &((struct consumer_ops const){ + .written = event_vdec_core_written, + }), +}; +#else static vdec_msg_handler mtk_vdec_msg_handle[VDEC_MAX]; +#endif -static void event_vdec_written(struct consumer const *consumer, size_t count) +/* Stub functions only provided by private overlays. */ +#ifndef HAVE_PRIVATE_MT8183 +#ifndef HAVE_PRIVATE_MT8186 +void vdec_msg_handler(void *data) +{ +} +void vdec_core_msg_handler(void *data) { - task_wake(TASK_ID_VDEC_SERVICE); } +#endif +#endif static void vdec_h264_ipi_handler(int id, void *data, uint32_t len) { struct vdec_msg rsv_msg; - if (!len) + if (!len) { + CPRINTS("len is zero."); return; + } +#ifdef HAVE_PRIVATE_MT8183 rsv_msg.type = VDEC_H264; +#else + rsv_msg.type = VDEC_LAT; +#endif memcpy(rsv_msg.msg, data, MIN(len, sizeof(rsv_msg.msg))); /* @@ -59,17 +93,21 @@ static void vdec_h264_ipi_handler(int id, void *data, uint32_t len) if (!queue_add_unit(&event_vdec_queue, &rsv_msg)) CPRINTS("Could not send vdec %d to the queue.", rsv_msg.type); } +#ifdef HAVE_PRIVATE_MT8183 DECLARE_IPI(IPI_VDEC_H264, vdec_h264_ipi_handler, 0); +#else +DECLARE_IPI(SCP_IPI_VDEC_LAT, vdec_h264_ipi_handler, 0); +#endif -/* This function renames from vdec_service_entry. */ void vdec_service_task(void *u) { struct vdec_msg rsv_msg; size_t size; +#ifdef HAVE_PRIVATE_MT8183 vdec_h264_service_init(); mtk_vdec_msg_handle[VDEC_H264] = vdec_h264_msg_handler; - +#endif while (1) { /* * Queue unit is added in IPI handler, which is in ISR context. @@ -79,11 +117,62 @@ void vdec_service_task(void *u) size = queue_remove_unit(&event_vdec_queue, &rsv_msg); ipi_enable_irq(SCP_IRQ_IPC0); - if (!size) + if (!size) { task_wait_event(-1); - else if (mtk_vdec_msg_handle[rsv_msg.type]) + continue; + } +#ifndef HAVE_PRIVATE_MT8183 + vdec_msg_handler(rsv_msg.msg); +#else + if (mtk_vdec_msg_handle[rsv_msg.type]) vdec_h264_msg_handler(rsv_msg.msg); else CPRINTS("vdec handler %d not exists.", rsv_msg.type); +#endif } } + +#ifndef HAVE_PRIVATE_MT8183 +static void vdec_h264_ipi_core_handler(int id, void *data, uint32_t len) +{ + struct vdec_msg rsv_msg; + + if (!len) { + CPRINTS("len is zero."); + return; + } + + rsv_msg.type = VDEC_CORE; + memcpy(rsv_msg.msg, data, MIN(len, sizeof(rsv_msg.msg))); + + /* + * If there is no other IPI handler touch this queue, we don't need to + * interrupt_disable() or task_disable_irq(). + */ + if (!queue_add_unit(&event_vdec_core_queue, &rsv_msg)) + CPRINTS("Could not send vdec %d to core queue.", rsv_msg.type); +} +DECLARE_IPI(SCP_IPI_VDEC_CORE, vdec_h264_ipi_core_handler, 0); + +void vdec_core_service_task(void *u) +{ + struct vdec_msg rsv_msg; + size_t size; + + while (1) { + /* + * Queue unit is added in IPI handler, which is in ISR context. + * Disable IRQ to prevent a clobbered queue. + */ + ipi_disable_irq(SCP_IRQ_IPC0); + size = queue_remove_unit(&event_vdec_core_queue, &rsv_msg); + ipi_enable_irq(SCP_IRQ_IPC0); + + if (!size) { + task_wait_event(-1); + continue; + } + vdec_core_msg_handler(rsv_msg.msg); + } +} +#endif diff --git a/board/kukui_scp/vdec.h b/board/kukui_scp/vdec.h index 6e4c9b40e7..411c1cbd15 100644 --- a/board/kukui_scp/vdec.h +++ b/board/kukui_scp/vdec.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2022 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,9 +6,11 @@ #ifndef __CROS_EC_SCP_VDEC_H #define __CROS_EC_SCP_VDEC_H -#include "chip/mt_scp/registers.h" #include "compile_time_macros.h" + +#ifdef HAVE_PRIVATE_MT8183 #include "queue.h" +#include "registers.h" enum vdec_type { VDEC_H264, @@ -18,16 +20,29 @@ enum vdec_type { }; typedef void (*vdec_msg_handler)(void *msg); +#else +enum vdec_type { + VDEC_LAT, + VDEC_CORE, + VDEC_MAX, +}; +#endif struct vdec_msg { enum vdec_type type; unsigned char msg[48]; }; -BUILD_ASSERT(member_size(struct vdec_msg, msg) <= CONFIG_IPC_SHARED_OBJ_BUF_SIZE); +BUILD_ASSERT(member_size(struct vdec_msg, msg) <= + CONFIG_IPC_SHARED_OBJ_BUF_SIZE); /* Functions provided by private overlay. */ +#ifdef HAVE_PRIVATE_MT8183 void vdec_h264_service_init(void); void vdec_h264_msg_handler(void *data); +#else +void vdec_core_msg_handler(void *msg); +void vdec_msg_handler(void *msg); +#endif #endif /* __CROS_EC_SCP_VDEC_H */ diff --git a/board/kukui_scp/venc.c b/board/kukui_scp/venc.c index ef1df894a0..ca5fc08429 100644 --- a/board/kukui_scp/venc.c +++ b/board/kukui_scp/venc.c @@ -1,17 +1,17 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "chip/mt_scp/ipi_chip.h" -#include "chip/mt_scp/registers.h" #include "console.h" #include "hooks.h" +#include "ipi_chip.h" +#include "queue.h" +#include "queue_policies.h" +#include "registers.h" #include "task.h" #include "util.h" #include "venc.h" -#include "queue.h" -#include "queue_policies.h" #define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) #define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) @@ -20,11 +20,11 @@ static struct consumer const event_venc_consumer; static void event_venc_written(struct consumer const *consumer, size_t count); -static struct queue const event_venc_queue = QUEUE_DIRECT(8, - struct venc_msg, null_producer, event_venc_consumer); +static struct queue const event_venc_queue = + QUEUE_DIRECT(8, struct venc_msg, null_producer, event_venc_consumer); static struct consumer const event_venc_consumer = { .queue = &event_venc_queue, - .ops = &((struct consumer_ops const) { + .ops = &((struct consumer_ops const){ .written = event_venc_written, }), }; @@ -33,7 +33,11 @@ static venc_msg_handler mtk_venc_msg_handle[VENC_MAX]; /* Stub functions only provided by private overlays. */ #ifndef HAVE_PRIVATE_MT8183 -void venc_h264_msg_handler(void *data) {} +#ifndef HAVE_PRIVATE_MT8186 +void venc_h264_msg_handler(void *data) +{ +} +#endif #endif static void event_venc_written(struct consumer const *consumer, size_t count) diff --git a/board/kukui_scp/venc.h b/board/kukui_scp/venc.h index 1172efd1b1..dcb74dbd87 100644 --- a/board/kukui_scp/venc.h +++ b/board/kukui_scp/venc.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,9 +6,13 @@ #ifndef __CROS_EC_SCP_VENC_H #define __CROS_EC_SCP_VENC_H -#include "chip/mt_scp/registers.h" #include "compile_time_macros.h" #include "queue.h" +#include "registers.h" + +#ifdef HAVE_PRIVATE_MT8186 +#include "venc_h264_srv.h" +#endif enum venc_type { VENC_H264, @@ -22,7 +26,8 @@ struct venc_msg { unsigned char msg[288]; }; -BUILD_ASSERT(member_size(struct venc_msg, msg) <= CONFIG_IPC_SHARED_OBJ_BUF_SIZE); +BUILD_ASSERT(member_size(struct venc_msg, msg) <= + CONFIG_IPC_SHARED_OBJ_BUF_SIZE); /* Functions provided by private overlay. */ void venc_h264_msg_handler(void *data); diff --git a/board/kuldax/board.c b/board/kuldax/board.c new file mode 100644 index 0000000000..37c2a6920c --- /dev/null +++ b/board/kuldax/board.c @@ -0,0 +1,607 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "builtin/assert.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/cec/bitbang.h" +#include "driver/tcpm/tcpci.h" +#include "driver/wpc/cps8100.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "peripheral_charger.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +struct pchg pchgs[] = { + [0] = { + .cfg = &(const struct pchg_config) { + .drv = &cps8200_drv, + .i2c_port = I2C_PORT_QI, + .irq_pin = GPIO_QI_INT_ODL, + .full_percent = 96, + .block_size = 128, + .flags = PCHG_CFG_FW_UPDATE_SYNC, + }, + .policy = { + [PCHG_CHIPSET_STATE_ON] = &pchg_policy_on, + [PCHG_CHIPSET_STATE_SUSPEND] = &pchg_policy_suspend, + }, + .events = QUEUE_NULL(PCHG_EVENT_QUEUE_SIZE, enum pchg_event), + }, +}; + +__override void board_pchg_power_on(int port, bool on) +{ + if (port == 0) + gpio_set_level(GPIO_EC_QI_PWR, on); + else + CPRINTS("%s: Invalid port=%d", __func__, port); +} + +int board_get_pchg_count(void) +{ + if (ec_cfg_has_peripheral_charger()) { + return ARRAY_SIZE(pchgs); + } else { + return 0; + } +} + +/******************************************************************************/ + +/* Power on Kuldax through CEC */ +struct cec_offline_policy kuldax_cec_policy[] = { + { + .command = CEC_MSG_REPORT_PHYSICAL_ADDRESS, + .action = CEC_ACTION_POWER_BUTTON, + }, + { + .command = CEC_MSG_DEVICE_VENDOR_ID, + .action = CEC_ACTION_POWER_BUTTON, + }, + /* Terminator */ + { 0 }, +}; + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = kuldax_cec_policy, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power_s5; +static int32_t base_5v_power_z1; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ + +/* PP5000_S5 loads */ +#define PWR_S5_BASE_LOAD (5 * 1431) +#define PWR_S5_FRONT_HIGH (5 * 1737) +#define PWR_S5_FRONT_LOW (5 * 1055) +#define PWR_S5_REAR_HIGH (5 * 1737) +#define PWR_S5_REAR_LOW (5 * 1055) +#define PWR_S5_HDMI (5 * 580) +#define PWR_S5_MAX (5 * 10000) +#define FRONT_DELTA (PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW) +#define REAR_DELTA (PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW) + +/* PP5000_Z1 loads */ +#define PWR_Z1_BASE_LOAD (5 * 5) +#define PWR_Z1_C_HIGH (5 * 3600) +#define PWR_Z1_C_LOW (5 * 2000) +#define PWR_Z1_MAX (5 * 9000) +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int front_ports = 0; + int rear_ports = 0; + + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power_s5 = PWR_S5_BASE_LOAD; + if (!gpio_get_level(GPIO_USB_A0_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + /* + * Only 1 front port can run higher power at a time. + */ + if (front_ports > 0) + base_5v_power_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + + if (!gpio_get_level(GPIO_USB_A2_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + if (!gpio_get_level(GPIO_USB_A3_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + /* + * Only 1 rear port can run higher power at a time. + */ + if (rear_ports > 0) + base_5v_power_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + if (!gpio_get_level(GPIO_HDMI_CONN_OC_ODL)) + base_5v_power_s5 += PWR_S5_HDMI; + base_5v_power_z1 = PWR_Z1_BASE_LOAD; + if (usbc_overcurrent) + base_5v_power_z1 += PWR_Z1_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) + ec_bj_power(&pi.voltage, &pi.current); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +static void adp_state_init(void) +{ + ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT); + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +static void board_init(void) +{ + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + gpio_enable_interrupt(GPIO_HDMI_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A2_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A3_OC_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Check that port number is valid. */ + if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) + return; + usbc_overcurrent = is_overcurrented; + update_5v_usage(); +} +/* + * Power monitoring and management. + * + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * The overall goal is to gracefully manage the power demand so that + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type A BC1.2 rear port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 3 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A_FRONT BIT(0) +#define THROT_TYPE_A_REAR BIT(1) +#define THROT_TYPE_C0 BIT(2) +#define THROT_TYPE_C1 BIT(3) +#define THROT_TYPE_C2 BIT(4) +#define THROT_PROCHOT BIT(5) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + static uint32_t history[POWER_READINGS]; + static uint8_t index; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v_s5 = PWR_S5_MAX - base_5v_power_s5; + int32_t headroom_5v_z1 = PWR_Z1_MAX - base_5v_power_z1; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + /* + * Clear the first entry of the power table so that + * it is re-initilalised when the CPU starts. + */ + history[0] = 0; + } else { + int32_t charger_mw; + + delay = POWER_DELAY_MS * MSEC; + /* + * Get current charger limit (in mw). + * If not configured yet, skip. + */ + charger_mw = charge_manager_get_power_limit_uw() / 1000; + if (charger_mw != 0) { + int32_t gap, total, max, power; + int i; + + /* + * Read power usage. + */ + power = (adc_read_channel(ADC_VBUS) * + adc_read_channel(ADC_PPVAR_IMON)) / + 1000; + /* Init power table */ + if (history[0] == 0) { + for (i = 0; i < POWER_READINGS; i++) + history[i] = power; + } + /* + * Update the power readings and + * calculate the average and max. + */ + history[index] = power; + index = (index + 1) % POWER_READINGS; + total = 0; + max = history[0]; + for (i = 0; i < POWER_READINGS; i++) { + total += history[i]; + if (history[i] > max) + max = history[i]; + } + /* + * For Type-C power supplies, there is + * less tolerance for exceeding the rating, + * so use the max power that has been measured + * over the measuring period. + * For barrel-jack supplies, the rating can be + * exceeded briefly, so use the average. + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + power = max; + else + power = total / POWER_READINGS; + /* + * Calculate gap, and if negative, power + * demand is exceeding configured power budget, so + * throttling is required to reduce the demand. + */ + gap = charger_mw - power; + /* + * Limiting type-A power rear ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_REAR; + headroom_5v_s5 += REAR_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * Limiting type-A power front ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_FRONT; + headroom_5v_s5 += FRONT_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(0) && gap <= 0) { + new_state |= THROT_TYPE_C0; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C0)) + gap += POWER_GAIN_TYPE_C; + } + /* + * As a last resort, turn on PROCHOT to + * throttle the CPU. + */ + if (gap <= 0) + new_state |= THROT_PROCHOT; + } + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v_z1 < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C0) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + new_state |= THROT_TYPE_C0; + } + /* + * [2] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v_z1 < 0) + new_state |= THROT_TYPE_C0; + } + if (headroom_5v_s5 < 0) { + /* + * [1] If type A rear not already throttled, and power still + * needed, limit type A rear. + */ + if (!(new_state & THROT_TYPE_A_REAR) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + new_state |= THROT_TYPE_A_REAR; + } + /* + * [2] If type A front not already throttled, and power still + * needed, limit type A front. + */ + if (!(new_state & THROT_TYPE_A_FRONT) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + new_state |= THROT_TYPE_A_FRONT; + } + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_C0) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C0) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + } + if (diff & THROT_TYPE_C1) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C1) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(1, rp); + tcpm_select_rp_value(1, rp); + pd_update_contract(1); + } + if (diff & THROT_TYPE_C2) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C2) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(2, rp); + tcpm_select_rp_value(2, rp); + pd_update_contract(2); + } + if (diff & THROT_TYPE_A_REAR) { + int typea_bc = (new_state & THROT_TYPE_A_REAR) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR0_OD, typea_bc); + gpio_set_level(GPIO_USB_A_LOW_PWR1_OD, typea_bc); + } + if (diff & THROT_TYPE_A_FRONT) { + int typea_bc = (new_state & THROT_TYPE_A_FRONT) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR2_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/kuldax/board.h b/board/kuldax/board.h new file mode 100644 index 0000000000..1665815114 --- /dev/null +++ b/board/kuldax/board.h @@ -0,0 +1,199 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brask board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* Disable console commands to help save space */ +#undef CONFIG_CMD_POWERINDEBUG + +#define CONFIG_MP2964 + +/* Barrel Jack */ +#define DEDICATED_CHARGE_PORT 1 + +/* HDMI CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMI_CEC_OUT +#define CEC_GPIO_IN GPIO_HDMI_CEC_IN +#define CEC_GPIO_PULL_UP GPIO_HDMI_CEC_PULL_UP + +/* USB Type A Features */ +#define USB_PORT_COUNT 4 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_USB_PD_PPC +#define CONFIG_USB_PD_TCPM_RT1715 +#define CONFIG_USBC_RETIMER_INTEL_BB + +#define CONFIG_USBC_PPC_SYV682X +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* The design should support up to 100W. */ +/* TODO(b/197702356): Set the max PD to 60W now and change it + * to 100W after we verify it. + */ +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_OD + +/* I2C Bus Configuration */ + +#define I2C_PORT_DP_REDRIVER NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0_C2_TCPC NPCX_I2C_PORT1_0 + +#define I2C_PORT_USB_C0_C2_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_QI NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x58 +#define USBC_PORT_C2_BB_RETIMER_I2C_ADDR 0x59 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* ADC */ +#define CONFIG_ADC + +/* + * TODO(b/197478860): Enable the fan control. We need + * to check the sensor value and adjust the fan speed. + */ +#define CONFIG_FANS FAN_CH_COUNT + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +/* WPC/Qi charger */ +#ifdef SECTION_IS_RW +#define CONFIG_PERIPHERAL_CHARGER +#define CONFIG_CPS8100 +#define CONFIG_SW_CRC +#endif + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_BARRELJACK, + CHARGE_PORT_ENUM_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1_CPU, + ADC_TEMP_SENSOR_2_CPU_VR, + ADC_TEMP_SENSOR_3_WIFI, + ADC_TEMP_SENSOR_4_DIMM, + ADC_VBUS, + ADC_PPVAR_IMON, /* ADC3 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_CPU, + TEMP_SENSOR_2_CPU_VR, + TEMP_SENSOR_3_WIFI, + TEMP_SENSOR_4_DIMM, + TEMP_SENSOR_COUNT +}; + +enum pwm_channel { + PWM_CH_LED_WHITE, /* PWM0 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED_RED, /* PWM2 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +extern void adp_connect_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/kuldax/build.mk b/board/kuldax/build.mk new file mode 100644 index 0000000000..3de758d1bd --- /dev/null +++ b/board/kuldax/build.mk @@ -0,0 +1,22 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brask board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brask + +board-y= +board-y+=board.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/kuldax/ec.tasklist b/board/kuldax/ec.tasklist new file mode 100644 index 0000000000..23218133a8 --- /dev/null +++ b/board/kuldax/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PCHG, pchg_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P2, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/kuldax/fans.c b/board/kuldax/fans.c new file mode 100644 index 0000000000..6e3740a894 --- /dev/null +++ b/board/kuldax/fans.c @@ -0,0 +1,50 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/197478860): need to update for real fan + * + * Prototype fan spins at about 7200 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2400, + .rpm_start = 2400, + .rpm_max = 4500, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/kuldax/fw_config.c b/board/kuldax/fw_config.c new file mode 100644 index 0000000000..7f0204f667 --- /dev/null +++ b/board/kuldax/fw_config.c @@ -0,0 +1,78 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union brask_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brask if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union brask_cbi_fw_config fw_config_defaults = { + .audio = DB_NAU88L25B_I2S, + .bj_power = BJ_135W, +}; + +/* + * Barrel-jack power adapter ratings. + */ +static const struct { + int voltage; + int current; +} bj_power[] = { + [BJ_150W] = { /* 0 - 150W (also default)*/ + .voltage = 20000, + .current = 7500 + }, + [BJ_230W] = { /* 1 - 230W */ + .voltage = 19500, + .current = 11800 + }, + [BJ_65W] = { /* 2 - 65W */ + .voltage = 19000, + .current = 3420 + }, + [BJ_135W] = { /* 4 - 135W */ + .voltage = 19500, + .current = 6920 + } +}; + +/**************************************************************************** + * Brask FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +void ec_bj_power(uint32_t *voltage, uint32_t *current) +{ + unsigned int bj; + + bj = fw_config.bj_power; + /* Out of range value defaults to 0 */ + if (bj >= ARRAY_SIZE(bj_power)) + bj = 0; + *voltage = bj_power[bj].voltage; + *current = bj_power[bj].current; +} + +bool ec_cfg_has_peripheral_charger(void) +{ + return (fw_config.peripheral_charger == PERIPHERAL_CHARGER_ENABLE); +} diff --git a/board/kuldax/fw_config.h b/board/kuldax/fw_config.h new file mode 100644 index 0000000000..cdba1b16d7 --- /dev/null +++ b/board/kuldax/fw_config.h @@ -0,0 +1,55 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_BRASK_FW_CONFIG_H_ +#define __BOARD_BRASK_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Brask board. + * + * Source of truth is the project/brask/brask/config.star configuration file. + */ +enum ec_cfg_audio_type { DB_AUDIO_UNKNOWN = 0, DB_NAU88L25B_I2S = 1 }; + +enum ec_cfg_bj_power { BJ_150W = 0, BJ_230W = 1, BJ_65W = 2, BJ_135W = 3 }; + +/* + * Peripheral charger (Bits 5) + */ +enum ec_cfg_peripheral_charger { + PERIPHERAL_CHARGER_ENABLE = 0, + PERIPHERAL_CHARGER_DISABLE = 1 +}; + +union brask_cbi_fw_config { + struct { + uint32_t audio : 3; + uint32_t bj_power : 2; + uint32_t peripheral_charger : 1; + uint32_t reserved_1 : 26; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union brask_cbi_fw_config get_fw_config(void); + +/** + * Get the barrel-jack power from FW_CONFIG. + */ +void ec_bj_power(uint32_t *voltage, uint32_t *current); + +/** + * SWITCH the peripheral charger function enable/disable from FW_CONFIG. + */ +bool ec_cfg_has_peripheral_charger(void); + +#endif /* __BOARD_BRASK_FW_CONFIG_H_ */ diff --git a/board/kuldax/gpio.inc b/board/kuldax/gpio.inc new file mode 100644 index 0000000000..253d9b7fc3 --- /dev/null +++ b/board/kuldax/gpio.inc @@ -0,0 +1,172 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTERRUPT GPIOs: */ + +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(2, 3), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(HDMI_CONN_OC_ODL, PIN(2, 4), GPIO_INPUT | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A0_OC_ODL, PIN(3, 1), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A2_OC_ODL, PIN(2, 7), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A3_OC_ODL, PIN(2, 6), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +#ifdef SECTION_IS_RW +GPIO_INT(QI_INT_ODL, PIN(9, 6), GPIO_INT_FALLING, pchg_irq) +#else +UNIMPLEMENTED(QI_INT_ODL) +#endif + +/* CCD */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + +/* Security */ +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Fan */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) + +/* ADC, need to check the usage */ +GPIO(ANALOG_PPVAR_PWR_IN_IMON_EC, PIN(4, 2), GPIO_INPUT) + +/* Display */ +GPIO(DP_CONN_OC_ODL, PIN(2, 5), GPIO_INPUT) + + +/* BarrelJack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 7), GPIO_OUT_LOW) + +/* Chipset PCH */ +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) + +/* Button */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(GSC_EC_RECOVERY_BTN_OD, PIN(2, 2), GPIO_INPUT) + +/* Wireless Charger */ +GPIO(EC_QI_PWR, PIN(D, 2), GPIO_OUT_LOW) +GPIO(QI_RESET_L, PIN(9, 3), GPIO_OUT_HIGH) + +/* HDMI CEC */ +/* TODO(b/197474873): Enable HDMI CEC */ +GPIO(HDMI_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CEC_OUT, PIN(D, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMI_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH) + +/* I2C SCL/SDA */ +GPIO(EC_I2C_QI_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_QI_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_DP_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_DP_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) + +/* USBA */ +GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW) +GPIO(USB_A0_STATUS_L, PIN(2, 1), GPIO_INPUT) +GPIO(USB_A1_STATUS_L, PIN(2, 0), GPIO_INPUT) +GPIO(USB_A_LOW_PWR0_OD, PIN(1, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR1_OD, PIN(1, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR2_OD, PIN(1, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH) + +/* LED */ +/* TODO(b/197471359): LED implementation */ +GPIO(LED_GREEN_L, PIN(C, 3), GPIO_OUT_LOW) +GPIO(LED_RED_L, PIN(C, 4), GPIO_OUT_LOW) + +/* USBC */ +GPIO(USB_C0_FRS_EN, PIN(A, 3), GPIO_OUT_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C0_RT_RST_ODL, PIN(9, 5), GPIO_ODR_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, 0) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* Unused Pins */ +UNUSED(PIN(0, 2)) /* GPIO02/PSL_IN4 */ +UNUSED(PIN(0, 4)) /* KSO13/GPIO04 */ +UNUSED(PIN(0, 5)) /* KSO13/GPIO05 */ +UNUSED(PIN(0, 6)) /* KSO11/GPIO06/P80_CLK */ +UNUSED(PIN(1, 0)) /* KSO9/GPIO10/CR_SIN1 */ +UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */ +UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */ +UNUSED(PIN(1, 6)) /* KSO3/GPIO16 */ +UNUSED(PIN(1, 7)) /* KSO2/GPIO17/JTAG_TDI */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(4, 1)) /* GPIO41/ADC4 */ +UNUSED(PIN(5, 0)) /* GPIO50 */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(7, 0)) /* GPIO70/PS2_DAT0*/ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(8, 3)) /* KSO15/GPIO83 */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */ +UNUSED(PIN(9, 7)) /* GPIO97 */ +UNUSED(PIN(9, 4)) /* GPIO94*/ +UNUSED(PIN(A, 2)) /* F_SCLK/GPIOA2 */ +UNUSED(PIN(A, 7)) /* GPIOA7 */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(D, 4)) /* GPIOD4/CR_SIN3 */ +UNUSED(PIN(F, 2)) /* GPIOF2/I2C4_SDA1*/ +UNUSED(PIN(F, 3)) /* GPIOF3/I2C4_SCL1*/ +UNUSED(PIN(F, 5)) /* GPIOF5/I2C5_SCL1*/ diff --git a/board/kuldax/i2c.c b/board/kuldax/i2c.c new file mode 100644 index 0000000000..e7868b4b08 --- /dev/null +++ b/board/kuldax/i2c.c @@ -0,0 +1,69 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "dp_redriver", + .port = I2C_PORT_DP_REDRIVER, + .kbps = 400, + .scl = GPIO_EC_I2C_DP_SCL, + .sda = GPIO_EC_I2C_DP_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,2", + .port = I2C_PORT_USB_C0_C2_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,2", + .port = I2C_PORT_USB_C0_C2_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,2", + .port = I2C_PORT_USB_C0_C2_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA, + }, + { + /* I2C5 */ + .name = "wireless_charger", + .port = I2C_PORT_QI, + .kbps = 400, + .scl = GPIO_EC_I2C_QI_SCL, + .sda = GPIO_EC_I2C_QI_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/kuldax/led.c b/board/kuldax/led.c new file mode 100644 index 0000000000..2fabc26a9a --- /dev/null +++ b/board/kuldax/led.c @@ -0,0 +1,270 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Brask. + * Solid white - active power + * White flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_WHITE, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int white = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_WHITE: + white = 1; + break; + case LED_RED: + red = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (white) + pwm_set_duty(PWM_CH_LED_WHITE, duty); + else + pwm_set_duty(PWM_CH_LED_WHITE, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* + * When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_WHITE); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* + * Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_WHITE, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +void board_led_auto_control(void) +{ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); +} + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "white")) { + set_color(id, LED_WHITE, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|red|white|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_WHITE]) + return set_color(id, LED_WHITE, brightness[EC_LED_COLOR_WHITE]); + else + return set_color(id, LED_OFF, 0); +} +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Blink alert if insufficient power per system_can_boot_ap(). */ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + led_alert(insufficient_power); +} diff --git a/board/kuldax/pwm.c b/board/kuldax/pwm.c new file mode 100644 index 0000000000..52cc1c2886 --- /dev/null +++ b/board/kuldax/pwm.c @@ -0,0 +1,40 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_WHITE] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP | PWM_CONFIG_OPEN_DRAIN, + .freq = 2000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * TODO(b/197478860): Turn on the fan at 100% by default + * We need to find tune the fan speed according to the + * thermal sensor value. + */ + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, 100); + + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_WHITE, 1); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/kuldax/sensors.c b/board/kuldax/sensors.c new file mode 100644 index 0000000000..687bfe3851 --- /dev/null +++ b/board/kuldax/sensors.c @@ -0,0 +1,117 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_CPU] = { + .name = "TEMP_CPU", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CPU_VR] = { + .name = "TEMP_CPU_VR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_WIFI] = { + .name = "TEMP_WIFI", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DIMM] = { + .name = "TEMP_DIMM", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 20/(20+8.66)*50/200 */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT * 143, + .factor_div = (ADC_READ_MAX + 1) * 25, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_CPU] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_CPU }, + [TEMP_SENSOR_2_CPU_VR] = { .name = "CPU VR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CPU_VR }, + [TEMP_SENSOR_3_WIFI] = { .name = "WIFI", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_WIFI }, + [TEMP_SENSOR_4_DIMM] = { .name = "DIMM", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DIMM }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/238260272): add the thermal sensor setting + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HALT] = C_TO_K(70), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(89), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +#define THERMAL_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan = THERMAL_FAN; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CPU] = THERMAL_CPU, + [TEMP_SENSOR_2_CPU_VR] = THERMAL_FAN, + [TEMP_SENSOR_3_WIFI] = THERMAL_FAN, + [TEMP_SENSOR_4_DIMM] = THERMAL_FAN, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/kuldax/usbc_config.c b/board/kuldax/usbc_config.c new file mode 100644 index 0000000000..a485dfb326 --- /dev/null +++ b/board/kuldax/usbc_config.c @@ -0,0 +1,235 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/retimer/kb800x.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, +}; + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, +}; + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C2_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, +}; + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t + pi3usb9201_bc12_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum gpio_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = GPIO_USB_C0_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + gpio_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + gpio_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +__override int bb_retimer_reset(const struct usb_mux *me) +{ + /* + * TODO(b/193402306, b/195375738): Remove this once transition to + * QS Silicon is complete + */ + bb_retimer_power_enable(me, false); + msleep(5); + bb_retimer_power_enable(me, true); + msleep(25); + + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/179648104): figure out correct timing + */ +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_2; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return true; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/kuldax/usbc_config.h b/board/kuldax/usbc_config.h new file mode 100644 index 0000000000..7a212f8fb6 --- /dev/null +++ b/board/kuldax/usbc_config.h @@ -0,0 +1,15 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/kuldax/vif_override.xml b/board/kuldax/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/kuldax/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/lalala/battery.c b/board/lalala/battery.c new file mode 100644 index 0000000000..4edf5fa864 --- /dev/null +++ b/board/lalala/battery.c @@ -0,0 +1,128 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "common.h" +#include "gpio.h" +#include "util.h" + +/* + * Battery info for lalala battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* LGC AP18C8K Battery Information */ + [BATTERY_LGC_AP18C8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G020", + .device_name = "AP18C8K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* Murata AP18C4K Battery Information */ + [BATTERY_MURATA_AP18C4K] = { + .fuel_gauge = { + .manuf_name = "Murata KT00304012", + .device_name = "AP18C4K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* AP19B8M */ + [BATTERY_AP19B8M] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G024", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13350, + .voltage_normal = 11610, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC_AP18C8K; diff --git a/board/lalala/board.c b/board/lalala/board.c new file mode 100644 index 0000000000..2d9c004f20 --- /dev/null +++ b/board/lalala/board.c @@ -0,0 +1,843 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lalala board-specific configuration */ + +#include "adc.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/ps8802.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/pi3usb3x532.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_config.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "stdbool.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +#define ADC_VOL_UP_MASK BIT(0) +#define ADC_VOL_DOWN_MASK BIT(1) + +static uint8_t new_adc_key_state; + +static void ps8762_chaddr_deferred(void); +DECLARE_DEFERRED(ps8762_chaddr_deferred); + +/******************************************************************************/ +/* USB-A Configuration */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, + GPIO_EN_USB_A1_VBUS, +}; + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* + * F3 key scan cycle completed but scan input is not + * charging to logic high when EC start scan next + * column for "T" key, so we set .output_settle_us + * to 80us from 50us. + */ + .output_settle_us = 80, + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfe, 0xff, 0xff, 0xff, /* full set */ + }, +}; + +static const struct ec_response_keybd_config lalala_keybd = { + /* Default Chromeos keyboard config */ + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad, has screenlock key */ + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &lalala_keybd; +} + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_SUB_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void sub_usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SUB_ANALOG] = { + .name = "SUB_ANALOG", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_b = THERMAL_B; + +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; + +static void setup_thermal(void) +{ + thermal_params[TEMP_SENSOR_1] = thermal_a; + thermal_params[TEMP_SENSOR_2] = thermal_b; +} + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +static void ps8762_chaddr_deferred(void) +{ + /* Switch PS8762 I2C Address to 0x50*/ + if (ps8802_chg_i2c_addr(I2C_PORT_SUB_USB_C1) == EC_SUCCESS) + CPRINTS("Switch PS8762 address to 0x50 success"); + else + CPRINTS("Switch PS8762 address to 0x50 failed"); +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", enable ? "en" : "dis"); + + if (!enable) + return; + /* + * Port C1 the PP3300_USB_C1 assert, delay 15ms + * colud be accessed PS8762 by I2C. + */ + hook_call_deferred(&ps8762_chaddr_deferred_data, 15 * MSEC); +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +/* Sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* BMA253 private data */ +static struct accelgyro_saved_data_t g_bma253_data; + +/* BMI160 private data */ +static struct bmi_drv_data_t g_bmi160_data; + +static const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* ICM426 private data */ +static struct icm_drv_data_t g_icm426xx_data; +/* KX022 private data */ +static struct kionix_accel_data g_kx022_data; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_SUB_USB_C1_INT_ODL); + check_c0_line(); + check_c1_line(); + + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + if (get_cbi_fw_config_tablet_mode()) { + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + cprints(CC_SYSTEM, "BASE GYRO is ICM426XX"); + } else + cprints(CC_SYSTEM, "BASE GYRO is BMI160"); + + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + cprints(CC_SYSTEM, "LID_ACCEL is KX022"); + } else + cprints(CC_SYSTEM, "LID_ACCEL is BMA253"); + + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + /* Initialize THERMAL */ + setup_thermal(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (get_cbi_ssfc_base_sensor()) { + case SSFC_SENSOR_ICM426XX: + icm426xx_interrupt(signal); + break; + case SSFC_SENSOR_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; +const unsigned int chg_cnt = ARRAY_SIZE(chg_chips); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP, + .freq = 10000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, + + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8802_I2C_ADDR_FLAGS_CUSTOM, + .driver = &ps8802_usb_mux_driver, + }, + } +}; + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + if (!gpio_get_level(GPIO_SUB_USB_C1_INT_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + /* TCPCI spec Rev 1.0 says to ignore bits 14:12. */ + if (!(tcpc_config[1].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +int adc_to_physical_value(enum gpio_signal gpio) +{ + if (gpio == GPIO_VOLUME_UP_L) + return !!(new_adc_key_state & ADC_VOL_UP_MASK); + else if (gpio == GPIO_VOLUME_DOWN_L) + return !!(new_adc_key_state & ADC_VOL_DOWN_MASK); + + CPRINTS("Not a volume up or down key"); + return 0; +} + +int button_is_adc_detected(enum gpio_signal gpio) +{ + return (gpio == GPIO_VOLUME_DOWN_L) || (gpio == GPIO_VOLUME_UP_L); +} + +static void adc_vol_key_press_check(void) +{ + int volt = adc_read_channel(ADC_SUB_ANALOG); + static uint8_t old_adc_key_state; + uint8_t adc_key_state_change; + + if (volt > 2400 && volt < 2490) { + /* volume-up is pressed */ + new_adc_key_state = ADC_VOL_UP_MASK; + } else if (volt > 2600 && volt < 2690) { + /* volume-down is pressed */ + new_adc_key_state = ADC_VOL_DOWN_MASK; + } else if (volt < 2290) { + /* both volumn-up and volume-down are pressed */ + new_adc_key_state = ADC_VOL_UP_MASK | ADC_VOL_DOWN_MASK; + } else if (volt > 2700) { + /* both volumn-up and volume-down are released */ + new_adc_key_state = 0; + } + if (new_adc_key_state != old_adc_key_state) { + adc_key_state_change = old_adc_key_state ^ new_adc_key_state; + if (adc_key_state_change & ADC_VOL_UP_MASK) + button_interrupt(GPIO_VOLUME_UP_L); + if (adc_key_state_change & ADC_VOL_DOWN_MASK) + button_interrupt(GPIO_VOLUME_DOWN_L); + + old_adc_key_state = new_adc_key_state; + } +} +DECLARE_HOOK(HOOK_TICK, adc_vol_key_press_check, HOOK_PRIO_DEFAULT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} diff --git a/board/lalala/board.h b/board/lalala/board.h new file mode 100644 index 0000000000..f9aa2482b0 --- /dev/null +++ b/board/lalala/board.h @@ -0,0 +1,181 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lalala board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KEEBY_EC_NPCX797FC +#include "baseboard.h" + +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +#define CONFIG_OCPC +#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 + +/* GPIO for C1 interrupts, for baseboard use */ +#define GPIO_USB_C1_INT_ODL GPIO_SUB_USB_C1_INT_ODL + +/* Keyboard */ + +#define CONFIG_KEYBOARD_KEYPAD +#define CONFIG_PWM_KBLIGHT + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES + +/* PWM */ +#define CONFIG_PWM +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ + +/* Temp sensor */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THROTTLE_AP +#define CONFIG_THERMISTOR_NCP15WB +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 +#define CONFIG_USBC_RETIMER_PS8802 + +/* Common USB-A defines */ +#define USB_PORT_COUNT 2 +#define CONFIG_USB_PORT_POWER_SMART +#define CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY +#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_CDP +#define CONFIG_USB_PORT_POWER_SMART_INVERTED +#define GPIO_USB1_ILIM_SEL GPIO_USB_A0_CHARGE_EN_L +#define GPIO_USB2_ILIM_SEL GPIO_USB_A1_CHARGE_EN_L + +/******************************************************************************/ + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +/* TODO(b:147440290): Need to handle multiple charger ICs */ +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ + +/* Sensors */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel second source*/ + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* Volume Button feature */ +#define CONFIG_ADC_BUTTONS +#define CONFIG_VOLUME_BUTTONS +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; + +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +enum battery_type { + BATTERY_AP19B8M, + BATTERY_LGC_AP18C8K, + BATTERY_MURATA_AP18C4K, + BATTERY_TYPE_COUNT, +}; + +int board_is_sourcing_vbus(int port); +void motion_interrupt(enum gpio_signal signal); +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/lalala/build.mk b/board/lalala/build.mk new file mode 100644 index 0000000000..eb422dae93 --- /dev/null +++ b/board/lalala/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=keeby + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/lalala/cbi_ssfc.c b/board/lalala/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/lalala/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/lalala/cbi_ssfc.h b/board/lalala/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/lalala/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/lalala/ec.tasklist b/board/lalala/ec.tasklist new file mode 100644 index 0000000000..29666dd959 --- /dev/null +++ b/board/lalala/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/lalala/gpio.inc b/board/lalala/gpio.inc new file mode 100644 index 0000000000..8d37079ca4 --- /dev/null +++ b/board/lalala/gpio.inc @@ -0,0 +1,145 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) +GPIO_INT(SUB_USB_C1_INT_ODL, PIN(F, 5), GPIO_INT_FALLING | GPIO_PULL_UP, sub_usb_c1_interrupt) + +/* Button interrupts */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(LID_360_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) + +/* Extra Sub-board I/O pins */ + +GPIO(EC_SUB_IO_2, PIN(3, 4), GPIO_OUT_LOW) + +/* Misc Enables */ +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_PEN, PIN(6, 3), GPIO_OUT_LOW) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_KB_BL, PIN(6, 0), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(EC_CBI_WP, PIN(E, 5), GPIO_OUT_LOW) + +/* LED */ +GPIO(LED_B_ODL, PIN(C, 2), GPIO_OUT_HIGH) /* PWM_CH_LED2_BLUE */ +GPIO(LED_G_ODL, PIN(C, 3), GPIO_OUT_HIGH) /* PWM_CH_LED1_GREEN */ +GPIO(LED_R_ODL, PIN(C, 4), GPIO_OUT_HIGH) /* PWM_CH_LED2_ORANGE */ + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +/* USB pins */ +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(7, 2), GPIO_OUT_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(USB_A0_CHARGE_EN_L, PIN(3, 7), GPIO_OUT_HIGH) /* Enable A0 1.5A Charging */ +GPIO(USB_A1_CHARGE_EN_L, PIN(F, 3), GPIO_OUT_HIGH) /* Enable A1 1.5A Charging */ +GPIO(EN_USB_A0_VBUS, PIN(4, 1), GPIO_OUT_LOW) /* Enable A1 5V Charging */ +GPIO(EN_USB_A1_VBUS, PIN(F, 2), GPIO_OUT_LOW) /* Enable A1 5V Charging */ +/* + * Lalala doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) +UNIMPLEMENTED(VOLDN_BTN_ODL) +UNIMPLEMENTED(VOLUP_BTN_ODL) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* ADC0-2 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* PWM */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* PWM3 */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO40_NC, PIN(4, 0), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/lalala/led.c b/board/lalala/led.c new file mode 100644 index 0000000000..94e55a8597 --- /dev/null +++ b/board/lalala/led.c @@ -0,0 +1,84 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for lalala + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_R_ODL, LED_ON_LVL); + gpio_set_level(GPIO_LED_B_ODL, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_LED_R_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_B_ODL, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_R_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_B_ODL, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} diff --git a/board/lalala/usb_pd_policy.c b/board/lalala/usb_pd_policy.c new file mode 100644 index 0000000000..3410726e87 --- /dev/null +++ b/board/lalala/usb_pd_policy.c @@ -0,0 +1,56 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/lalala/vif_override.xml b/board/lalala/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/lalala/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/lantis/battery.c b/board/lantis/battery.c new file mode 100644 index 0000000000..6dfb91ef50 --- /dev/null +++ b/board/lantis/battery.c @@ -0,0 +1,285 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all lantis battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* DynaPack CosMX Battery Information */ + [BATTERY_DYNAPACK_COS] = { + .fuel_gauge = { + .manuf_name = "333-2C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack ATL Battery Information */ + [BATTERY_DYNAPACK_ATL] = { + .fuel_gauge = { + .manuf_name = "333-27-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Simplo CosMX Battery Information */ + [BATTERY_SIMPLO_COS] = { + .fuel_gauge = { + .manuf_name = "333-1C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Simplo HIGHPOWER Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-1D-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* CosMX B00C4473A9D0002 Battery Information */ + [BATTERY_COS] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack CosMX DAK125720-W0P0701HT Battery Information */ + [BATTERY_DYNAPACK_COS_44WH] = { + .fuel_gauge = { + .manuf_name = "333-2C-DB-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* DynaPack ATL DAK125720-W0G0701HT Battery Information */ + [BATTERY_DYNAPACK_ATL_44WH] = { + .fuel_gauge = { + .manuf_name = "333-27-DB-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + + /* Simplo HIGHPOWER 996Q4242H Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER_44WH] = { + .fuel_gauge = { + .manuf_name = "333-1D-DB-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; diff --git a/board/lantis/board.c b/board/lantis/board.c new file mode 100644 index 0000000000..600f141639 --- /dev/null +++ b/board/lantis/board.c @@ -0,0 +1,887 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lantis board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "cros_board_info.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_bma422.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/sm5803.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_8042.h" +#include "keyboard_8042_sharedlib.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +uint32_t board_version; + +/* GPIO to enable/disable the USB Type-A port. */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + .output_settle_us = 80, + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfe, 0xff, 0xff, 0xff, /* full set */ + }, +}; + +__override void board_process_pd_alert(int port) +{ + /* + * PD_INT task will process this alert, and that task is only needed on + * C1. + */ + if (port != 1) + return; + + if (gpio_get_level(GPIO_USB_C1_INT_ODL)) + return; + + sm5803_handle_interrupt(port); +} + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + sm5803_interrupt(0); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void button_sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + int hdmi_hpd = gpio_get_level(GPIO_VOLUP_BTN_ODL_HDMI_HPD); + + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, hdmi_hpd); + else + button_interrupt(s); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +static void pen_detect_interrupt(enum gpio_signal s) +{ + int pen_detect = !gpio_get_level(GPIO_PEN_DET_ODL); + + gpio_set_level(GPIO_EN_PP5000_PEN, pen_detect); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_SUB_ANALOG] = { .name = "SUB_ANALOG", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, + [ADC_TEMP_SENSOR_4] = { .name = "TEMP_SENSOR4", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH16 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + [CHARGER_PRIMARY] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS, + .drv = &sm5803_drv, + }, + [CHARGER_SECONDARY] = { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS, + .drv = &sm5803_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &it83xx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, +}; + +/* Sensor Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Sensor Data */ +static struct accelgyro_saved_data_t g_bma253_data; +static struct accelgyro_saved_data_t g_bma422_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* Matrix to rotate accelrator into standard reference frame */ +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +/* Drivers */ +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t bma422_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_PRIMARY, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, +}; + +static void board_update_motion_sensor_config(void) +{ + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_BMA422) + motion_sensors[LID_ACCEL] = bma422_lid_accel; +} + +static const struct ec_response_keybd_config lantis_keybd_backlight = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad and no screenlock key */ +}; + +static const struct ec_response_keybd_config landia_keybd = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, + /* No function keys and no numeric keypad */ +}; + +static const struct ec_response_keybd_config landrid_keybd_backlight = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_KBD_BKLIGHT_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_NUMERIC_KEYPAD, + /* No function keys and no screenlock key */ +}; + +static const struct ec_response_keybd_config landrid_keybd = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PLAY_PAUSE, /* T8 */ + TK_MICMUTE, /* T9 */ + TK_VOL_MUTE, /* T10 */ + TK_VOL_DOWN, /* T11 */ + TK_VOL_UP, /* T12 */ + TK_MENU, /* T13 */ + }, + .capabilities = KEYBD_CAP_NUMERIC_KEYPAD, + /* No function keys and no screenlock key */ +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (get_cbi_fw_config_numeric_pad()) { + if (get_cbi_fw_config_kblight()) + return &landrid_keybd_backlight; + else + return &landrid_keybd; + } else { + if (get_cbi_fw_config_tablet_mode()) + return &landia_keybd; + else + return &lantis_keybd_backlight; + } +} + +__override uint8_t board_keyboard_row_refresh(void) +{ + if (gpio_get_level(GPIO_EC_VIVALDIKEYBOARD_ID)) + return 3; + else + return 2; +} + +static void board_update_no_keypad_by_fwconfig(void) +{ + if (!get_cbi_fw_config_numeric_pad()) { + /* Disable scanning KSO13 & 14 if keypad isn't present. */ + keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); + keyscan_config.actual_key_mask[11] = 0xfa; + keyscan_config.actual_key_mask[12] = 0xca; + } +} + +static void board_update_keyboard_layout(void) +{ + if (get_cbi_fw_config_keyboard() == KB_LAYOUT_1) { + /* + * If keyboard is UK(KB_LAYOUT_1), we need translate right ctrl + * to backslash(\|) key. + */ + set_scancode_set2(4, 0, get_scancode_set2(2, 7)); + } +} + +void board_init(void) +{ + int on; + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_LTE_HDMI || db == DB_1A_HDMI_LTE) { + /* Select HDMI option */ + gpio_set_level(GPIO_HDMI_SEL_L, 0); + } else { + /* Select AUX option */ + gpio_set_level(GPIO_HDMI_SEL_L, 1); + } + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_INT_ODL); + + /* Store board version for use in determining charge limits */ + cbi_get_board_version(&board_version); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) + hook_call_deferred(&check_c1_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_PRESENT) { + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable Base Accel interrupt */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + board_update_motion_sensor_config(); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } + + gpio_enable_interrupt(GPIO_PEN_DET_ODL); + + /* Charger on the MB will be outputting PROCHOT_ODL and OD CHG_DET */ + sm5803_configure_gpio0(CHARGER_PRIMARY, GPIO0_MODE_PROCHOT, 1); + sm5803_configure_chg_det_od(CHARGER_PRIMARY, 1); + + if (board_get_charger_chip_count() > 1) { + /* Charger on the sub-board will be a push-pull GPIO */ + sm5803_configure_gpio0(CHARGER_SECONDARY, GPIO0_MODE_OUTPUT, 0); + } + + /* Turn on 5V if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + board_update_no_keypad_by_fwconfig(); + board_update_keyboard_layout(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_resume(void) +{ + sm5803_disable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_disable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); + +static void board_suspend(void) +{ + sm5803_enable_low_power_mode(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_enable_low_power_mode(CHARGER_SECONDARY); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Put all charger ICs present into low power mode before entering + * z-state. + */ + sm5803_hibernate(CHARGER_PRIMARY); + if (board_get_charger_chip_count() > 1) + sm5803_hibernate(CHARGER_SECONDARY); +} + +__override void board_ocpc_init(struct ocpc_data *ocpc) +{ + /* There's no provision to measure Isys */ + ocpc->chg_flags[CHARGER_SECONDARY] |= OCPC_NO_ISYS_MEAS_CAP; +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + + if (board_get_charger_chip_count() > 1) { + if (sm5803_set_gpio0_level(1, !!enable)) + CPRINTUSB("Failed to %sable sub rails!", + enable ? "en" : "dis"); + } +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) + return CONFIG_USB_PD_PORT_MAX_COUNT; + + ccprints("Unhandled DB configuration: %d", db); + return 0; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + enum fw_config_db db = get_cbi_fw_config_db(); + + if (db == DB_1A_HDMI || db == DB_NONE || db == DB_LTE_HDMI || + db == DB_1A_HDMI_LTE) + return CHARGER_NUM - 1; + else if (db == DB_1C || db == DB_1C_LTE || db == DB_1C_1A || + db == DB_1C_1A_LTE) + return CHARGER_NUM; + + ccprints("Unhandled DB configuration: %d", db); + return 0; +} + +uint16_t tcpc_get_alert_status(void) +{ + /* + * TCPC 0 is embedded in the EC and processes interrupts in the chip + * code (it83xx/intc.c) + */ + + uint16_t status = 0; + int regval; + + /* Check whether TCPC 1 pulled the shared interrupt line */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +int board_set_active_charge_port(int port) +{ + int is_valid_port = (port >= 0 && port < board_get_usb_pd_port_count()); + + if (!is_valid_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTUSB("Disabling all charge ports"); + + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 0); + + if (board_get_charger_chip_count() > 1) + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 0); + + return EC_SUCCESS; + } + + CPRINTUSB("New chg p%d", port); + + /* + * Ensure other port is turned off, then enable new charge port + */ + if (port == 0) { + if (board_get_charger_chip_count() > 1) + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 0); + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 1); + + } else { + sm5803_vbus_sink_enable(CHARGER_PRIMARY, 0); + sm5803_vbus_sink_enable(CHARGER_SECONDARY, 1); + } + + return EC_SUCCESS; +} + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* Vconn control is only for port 0 */ + if (port) + return; + + if (cc_pin == USBPD_CC_PIN_1) + gpio_set_level(GPIO_EN_USB_C0_CC1_VCONN, !!enabled); + else + gpio_set_level(GPIO_EN_USB_C0_CC2_VCONN, !!enabled); +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + int current; + + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + current = (rp == TYPEC_RP_3A0) ? 3000 : 1500; + + charger_set_otg_current_voltage(port, current, 5000); +} + +__override uint16_t board_get_ps8xxx_product_id(int port) +{ + /* Lantis variant doesn't have ps8xxx product in the port 0 */ + if (port == 0) + return 0; + + switch (get_cbi_ssfc_tcpc_p1()) { + case SSFC_TCPC_P1_PS8805: + return PS8805_PRODUCT_ID; + case SSFC_TCPC_P1_DEFAULT: + case SSFC_TCPC_P1_PS8705: + default: + return PS8705_PRODUCT_ID; + } +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 100, + } }; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "5V regular", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 3; + *kp_div = 20; + + *ki = 3; + *ki_div = 125; + + *kd = 4; + *kd_div = 40; +} + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { GPIO_KSO_H, 4 }, { GPIO_KSO_H, 0 }, + { GPIO_KSO_H, 1 }, { GPIO_KSO_H, 3 }, { GPIO_KSO_H, 2 }, + { GPIO_KSO_L, 5 }, { GPIO_KSO_L, 6 }, { GPIO_KSO_L, 3 }, + { GPIO_KSO_L, 2 }, { GPIO_KSI, 0 }, { GPIO_KSO_L, 1 }, + { GPIO_KSO_L, 4 }, { GPIO_KSI, 3 }, { GPIO_KSI, 2 }, + { GPIO_KSO_L, 0 }, { GPIO_KSI, 5 }, { GPIO_KSI, 4 }, + { GPIO_KSO_L, 7 }, { GPIO_KSI, 6 }, { GPIO_KSI, 7 }, + { GPIO_KSI, 1 }, { -1, -1 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/lantis/board.h b/board/lantis/board.h new file mode 100644 index 0000000000..7447dcbf31 --- /dev/null +++ b/board/lantis/board.h @@ -0,0 +1,151 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lantis board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +#undef GPIO_VOLUME_UP_L +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL_HDMI_HPD + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 15000 +#define CONFIG_USB_PD_VBUS_DETECT_CHARGER +#define CONFIG_USB_PD_5V_CHARGER_CTRL +#define CONFIG_CHARGER_OTG +#undef CONFIG_CHARGER_SINGLE_CHIP +#define CONFIG_OCPC +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 21 /* R_DS(on) 10.7mOhm + 10mOhm sns rstr \ + */ + +/* PWM */ +#define CONFIG_PWM + +/* Sensors */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCEL_BMA4XX /* 2nd source Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* Power of 2 - Too large of a fifo causes too much timestamp jitter */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* Keyboard */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_PWM_KBLIGHT +#define CONFIG_KEYBOARD_KEYPAD + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_TCPM_MULTI_PS8XXX +#define CONFIG_USB_PD_TCPM_PS8705 /* C1: PS8705 TCPC */ +#define CONFIG_USB_PD_TCPM_PS8805 /* C1: second source PS8805 TCPC */ +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_SUB_ANALOG, /* ADC13 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_TEMP_SENSOR_4, /* ADC16 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_4, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_DYNAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_SIMPLO_COS, + BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COS, + BATTERY_DYNAPACK_COS_44WH, + BATTERY_DYNAPACK_ATL_44WH, + BATTERY_SIMPLO_HIGHPOWER_44WH, + BATTERY_TYPE_COUNT, +}; + +enum ec_cfg_keyboard_layout { KB_LAYOUT_DEFAULT = 0, KB_LAYOUT_1 = 1 }; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/lantis/build.mk b/board/lantis/build.mk new file mode 100644 index 0000000000..9b862c7624 --- /dev/null +++ b/board/lantis/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/lantis/cbi_ssfc.c b/board/lantis/cbi_ssfc.c new file mode 100644 index 0000000000..324ceffb63 --- /dev/null +++ b/board/lantis/cbi_ssfc.c @@ -0,0 +1,41 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} + +enum ec_ssfc_tcpc_p1 get_cbi_ssfc_tcpc_p1(void) +{ + return (enum ec_ssfc_tcpc_p1)cached_ssfc.tcpc_type; +} diff --git a/board/lantis/cbi_ssfc.h b/board/lantis/cbi_ssfc.h new file mode 100644 index 0000000000..626fe62498 --- /dev/null +++ b/board/lantis/cbi_ssfc.h @@ -0,0 +1,95 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_BMA422 = 2, +}; + +/* + * TCPC Port 1 (Bits 6-7) + */ +enum ec_ssfc_tcpc_p1 { + SSFC_TCPC_P1_DEFAULT, + SSFC_TCPC_P1_PS8705, + SSFC_TCPC_P1_PS8805, +}; + +/* + * Audio Codec Source(Bit 8-10) + */ +enum ec_ssfc_audio_codec_source { + SSFC_AUDIO_CODEC_DEFAULT = 0, + SSFC_AUDIO_CODEC_VD = 1, + SSFC_ADUIO_CODEC_VS = 2, +}; + +/* + * Touchscreen Driver Source(Bit 11-13) + */ +enum ec_ssfc_ts_driver_source { + SSFC_TS_DRIVER_DEFAULT = 0, + SSFC_TS_DRIVER_GENERIC = 1, + SSFC_TS_DRIVER_HID = 2, +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t tcpc_type : 2; + uint32_t audio_codec_source : 3; + uint32_t ts_driver_source : 3; + uint32_t reserved_2 : 18; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +/** + * Get the TCPC port 1 type from SSFC_CONFIG. + * + * @return the TCPC type. + */ +enum ec_ssfc_tcpc_p1 get_cbi_ssfc_tcpc_p1(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/lantis/ec.tasklist b/board/lantis/ec.tasklist new file mode 100644 index 0000000000..c3c360febb --- /dev/null +++ b/board/lantis/ec.tasklist @@ -0,0 +1,24 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/lantis/gpio.inc b/board/lantis/gpio.inc new file mode 100644 index 0000000000..6afb9ccc4b --- /dev/null +++ b/board/lantis/gpio.inc @@ -0,0 +1,146 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(USB_C1_INT_ODL, PIN(E, 6), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c1_interrupt) /* TCPC, charger, BC12 */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL_HDMI_HPD, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_sub_hdmi_hpd_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(PEN_DET_ODL, PIN(J, 1), GPIO_INT_BOTH | GPIO_PULL_UP, pen_detect_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EN_USB_A_5V, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC1_VCONN, PIN(H, 4), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC2_VCONN, PIN(H, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(USB_C0_FRS, PIN(C, 4), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_HIGH) + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(EN_KB_BL, PIN(J, 3), GPIO_OUT_LOW) /* Currently unused */ +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_PEN, PIN(B, 5), GPIO_OUT_LOW) +GPIO(EC_VIVALDIKEYBOARD_ID, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) /* keyboard ID */ + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* LED */ +GPIO(BAT_LED_AMBER_C0, PIN(A, 1), GPIO_OUT_HIGH) +GPIO(BAT_LED_WHITE_C0, PIN(A, 2), GPIO_OUT_HIGH) +GPIO(BAT_LED_AMBER_C1, PIN(F, 1), GPIO_OUT_HIGH) +GPIO(BAT_LED_WHITE_C1, PIN(F, 0), GPIO_OUT_HIGH) +GPIO(PWR_LED_WHITE_L, PIN(A, 3), GPIO_OUT_HIGH) + +/* Alternate functions GPIO definitions */ +/* Keyboard */ +ALTERNATE(PIN_MASK(KSI, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSI0-7 */ +ALTERNATE(PIN_MASK(KSO_H, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO8-15 */ +ALTERNATE(PIN_MASK(KSO_L, 0xFB), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO0-1, 3-7 */ +GPIO(EC_KSO_02_INV, PIN(KSO_L, 2), GPIO_OUT_HIGH) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC13: EC_SUB_ANALOG, ADC15: TEMP_SENSOR_3, ADC16: TEMP_SENSOR_4 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + +/* PWM */ +ALTERNATE(PIN_MASK(A, BIT(0)), 0, MODULE_PWM, 0) /* KB_BL_PWM */ diff --git a/board/lantis/led.c b/board/lantis/led.c new file mode 100644 index 0000000000..cef6f57a5e --- /dev/null +++ b/board/lantis/led.c @@ -0,0 +1,280 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lantis specific LED settings. */ + +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +enum led_port { LEFT_PORT = 0, RIGHT_PORT }; + +static int led_set_color_battery(int port, enum led_color color) +{ + enum gpio_signal amber_led, white_led; + + amber_led = (port == RIGHT_PORT ? GPIO_BAT_LED_AMBER_C1 : + GPIO_BAT_LED_AMBER_C0); + white_led = (port == RIGHT_PORT ? GPIO_BAT_LED_WHITE_C1 : + GPIO_BAT_LED_WHITE_C0); + + switch (color) { + case LED_OFF: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + case LED_WHITE: + gpio_set_level(white_led, BAT_LED_ON); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_ON); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} + +static int led_set_color_power(enum led_color color) +{ + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_OFF); + break; + case LED_WHITE: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_ON); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_RIGHT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_POWER_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + break; + default: + break; + } +} + +static int led_set_color(enum ec_led_id led_id, enum led_color color) +{ + int rv; + + switch (led_id) { + case EC_LED_ID_RIGHT_LED: + rv = led_set_color_battery(RIGHT_PORT, color); + break; + case EC_LED_ID_LEFT_LED: + rv = led_set_color_battery(LEFT_PORT, color); + break; + case EC_LED_ID_POWER_LED: + rv = led_set_color_power(color); + break; + default: + return EC_ERROR_UNKNOWN; + } + return rv; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color(led_id, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color(led_id, LED_AMBER); + else + led_set_color(led_id, LED_OFF); + + return EC_SUCCESS; +} + +/* + * lantis use old led policy. + * Use cbi fw_config to distinguish lantis from other boards. + * numeric_pad tablet mode + * lantis N N + * landrid Y N + * landia N Y + */ +static bool is_led_old_policy(void) +{ + if (get_cbi_fw_config_numeric_pad() == NUMERIC_PAD_ABSENT && + get_cbi_fw_config_tablet_mode() == TABLET_MODE_ABSENT) + return 1; + else + return 0; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + led_set_color_battery(RIGHT_PORT, + (port == RIGHT_PORT) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, + (port == LEFT_PORT) ? color : LED_OFF); +} + +static void led_set_battery(void) +{ + static int battery_ticks; + static int power_ticks; + + battery_ticks++; + + /* + * Override battery LED for clamshell SKU, which doesn't have power + * LED, blinking battery white LED to indicate system suspend without + * charging. + */ + if (get_cbi_fw_config_tablet_mode() == TABLET_MODE_ABSENT) { + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + power_ticks++; + + led_set_color_battery(RIGHT_PORT, power_ticks & 0x2 ? + LED_WHITE : + LED_OFF); + led_set_color_battery(LEFT_PORT, power_ticks & 0x2 ? + LED_WHITE : + LED_OFF); + return; + } + } + + power_ticks = 0; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE_FULL: + if (extpower_is_present()) { + set_active_port_color(LED_WHITE); + break; + } + __fallthrough; + case LED_PWRS_DISCHARGE: + /* + * Blink white/amber light (1 sec on, 1 sec off) + * when battery capacity is less than 10% + */ + if (charge_get_percent() < 10) { + if (is_led_old_policy()) { + led_set_color_battery(RIGHT_PORT, + (battery_ticks & 0x2) ? + LED_WHITE : + LED_OFF); + } else { + if (led_auto_control_is_enabled( + EC_LED_ID_RIGHT_LED)) + led_set_color_battery( + RIGHT_PORT, + (battery_ticks & 0x2) ? + LED_AMBER : + LED_OFF); + if (led_auto_control_is_enabled( + EC_LED_ID_LEFT_LED)) + led_set_color_battery( + LEFT_PORT, + (battery_ticks & 0x2) ? + LED_AMBER : + LED_OFF); + } + } else { + set_active_port_color(LED_OFF); + } + break; + case LED_PWRS_ERROR: + if (is_led_old_policy()) + set_active_port_color( + (battery_ticks % 0x2) ? LED_WHITE : LED_OFF); + else + set_active_port_color( + (battery_ticks % 0x2) ? LED_AMBER : LED_OFF); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color((battery_ticks & 0x2) ? LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +static void led_set_power(void) +{ + static int power_tick; + + power_tick++; + + if (chipset_in_state(CHIPSET_STATE_ON)) + led_set_color_power(LED_WHITE); + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + led_set_color_power((power_tick & 0x2) ? LED_WHITE : LED_OFF); + else + led_set_color_power(LED_OFF); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + led_set_power(); + + led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/lantis/usb_pd_policy.c b/board/lantis/usb_pd_policy.c new file mode 100644 index 0000000000..2433b25431 --- /dev/null +++ b/board/lantis/usb_pd_policy.c @@ -0,0 +1,74 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/sm5803.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + if (port < 0 || port >= board_get_usb_pd_port_count()) + return; + + prev_en = charger_is_sourcing_otg_power(port); + + /* Disable Vbus */ + charger_enable_otg_power(port, 0); + + /* Discharge Vbus if previously enabled */ + if (prev_en) + sm5803_set_vbus_disch(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + enum ec_error_list rv; + + /* Disable sinking */ + rv = sm5803_vbus_sink_enable(port, 0); + if (rv) + return rv; + + /* Disable Vbus discharge */ + sm5803_set_vbus_disch(port, 0); + + /* Provide Vbus */ + charger_enable_otg_power(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +__override bool pd_check_vbus_level(int port, enum vbus_level level) +{ + return sm5803_check_vbus_level(port, level); +} + +int pd_snk_is_vbus_provided(int port) +{ + return sm5803_is_vbus_present(port); +} diff --git a/board/lantis/vif_override.xml b/board/lantis/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/lantis/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/lazor/battery.c b/board/lazor/battery.c index 6cad716e2c..61de35da12 100644 --- a/board/lazor/battery.c +++ b/board/lazor/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/lazor/board.c b/board/lazor/board.c index 6ef3e2c0f9..ecfa4ace6b 100644 --- a/board/lazor/board.c +++ b/board/lazor/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,121 +7,49 @@ #include "adc_chip.h" #include "button.h" -#include "charge_manager.h" -#include "charge_state.h" -#include "extpower.h" #include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accel_kx022.h" #include "driver/accelgyro_bmi_common.h" -#include "driver/ppc/sn5s330.h" -#include "driver/tcpm/ps8xxx.h" -#include "driver/tcpm/tcpci.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/ln9310.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "keyboard_scan.h" #include "lid_switch.h" -#include "ln9310.h" -#include "pi3usb9201.h" +#include "mkbp_info.h" #include "power.h" #include "power_button.h" #include "pwm.h" #include "pwm_chip.h" -#include "system.h" #include "shi_chip.h" +#include "sku.h" #include "switch.h" +#include "system.h" #include "tablet_mode.h" #include "task.h" +#include "usbc_config.h" #include "usbc_ppc.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -/* Forward declaration */ -static void tcpc_alert_event(enum gpio_signal signal); -static void usb0_evt(enum gpio_signal signal); -static void usb1_evt(enum gpio_signal signal); -static void ppc_interrupt(enum gpio_signal signal); -static void board_connect_c0_sbu(enum gpio_signal s); -static void switchcap_interrupt(enum gpio_signal signal); +/* Disable debug messages to free flash space */ +#define CPRINTS(format, args...) +#define CPRINTF(format, args...) +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -static uint8_t sku_id; - -/* GPIO Interrupt Handlers */ -static void tcpc_alert_event(enum gpio_signal signal) -{ - int port = -1; - - switch (signal) { - case GPIO_USB_C0_PD_INT_ODL: - port = 0; - break; - case GPIO_USB_C1_PD_INT_ODL: - port = 1; - break; - default: - return; - } - - schedule_deferred_pd_interrupt(port); -} - -static void usb0_evt(enum gpio_signal signal) -{ - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); -} - -static void usb1_evt(enum gpio_signal signal) -{ - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); -} - -static void ppc_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_SWCTL_INT_ODL: - sn5s330_interrupt(0); - break; - case GPIO_USB_C1_SWCTL_INT_ODL: - sn5s330_interrupt(1); - break; - default: - break; - } -} - -static void board_connect_c0_sbu_deferred(void) -{ - /* - * If CCD_MODE_ODL asserts, it means there's a debug accessory connected - * and we should enable the SBU FETs. - */ - ppc_set_sbu(0, 1); -} -DECLARE_DEFERRED(board_connect_c0_sbu_deferred); - -static void board_connect_c0_sbu(enum gpio_signal s) -{ - hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); -} - -static void switchcap_interrupt(enum gpio_signal signal) -{ - ln9310_interrupt(signal); -} - /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Use 80 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* * Unmask 0x08 in [0] (KSO_00/KSI_03, the new location of Search key); * as it still uses the legacy location (KSO_01/KSI_00). */ - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca - }, + .actual_key_mask = { 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xa4, + 0xff, 0xfe, 0x55, 0xfa, 0xca }, /* Other values should be the same as the default configuration. */ .debounce_down_us = 9 * MSEC, .debounce_up_us = 30 * MSEC, @@ -130,18 +58,50 @@ struct keyboard_scan_config keyscan_config = { .poll_timeout_us = 100 * MSEC, }; +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + /* I2C port map */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_EC_I2C_POWER_SCL, - GPIO_EC_I2C_POWER_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 1000, GPIO_EC_I2C_USB_C0_PD_SCL, - GPIO_EC_I2C_USB_C0_PD_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 1000, GPIO_EC_I2C_USB_C1_PD_SCL, - GPIO_EC_I2C_USB_C1_PD_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_EC_I2C_EEPROM_SCL, - GPIO_EC_I2C_EEPROM_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_EC_I2C_SENSOR_SCL, - GPIO_EC_I2C_SENSOR_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -149,37 +109,22 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /* ADC channels */ const struct adc_t adc_channels[] = { /* Measure VBUS through a 1/10 voltage divider */ - [ADC_VBUS] = { - "VBUS", - NPCX_ADC_CH1, - ADC_MAX_VOLT * 10, - ADC_READ_MAX + 1, - 0 - }, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* * Adapter current output or battery charging/discharging current (uV) * 18x amplification on charger side. */ - [ADC_AMON_BMON] = { - "AMON_BMON", - NPCX_ADC_CH2, - ADC_MAX_VOLT * 1000 / 18, - ADC_READ_MAX + 1, - 0 - }, + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, /* * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we * only divide by 2 (enough to avoid precision issues). */ - [ADC_PSYS] = { - "PSYS", - NPCX_ADC_CH3, - ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), - 2, - 0 - }, + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -190,107 +135,42 @@ const struct pwm_t pwm_channels[] = { }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -/* LN9310 switchcap */ -const struct ln9310_config_t ln9310_config = { - .i2c_port = I2C_PORT_POWER, - .i2c_addr_flags = LN9310_I2C_ADDR_0_FLAGS, -}; - -/* Power Path Controller */ -struct ppc_config_t ppc_chips[] = { - { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, - { - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, -}; -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -/* TCPC mux configuration */ -const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .drv = &ps8xxx_tcpm_drv, - }, - { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .drv = &ps8xxx_tcpm_drv, - }, -}; - -/* - * Port-0/1 USB mux driver. - * - * The USB mux is handled by TCPC chip and the HPD update is through a GPIO - * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, - * the mux misbehaves. - */ -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - }, - { - .usb_port = 1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - } -}; - -const int usb_port_enable[USB_PORT_COUNT] = { - GPIO_EN_USB_A_5V, -}; - -/* BC1.2 */ -const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { - { - .i2c_port = I2C_PORT_POWER, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, - { - .i2c_port = I2C_PORT_EEPROM, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, -}; - /* Mutexes */ static struct mutex g_base_mutex; static struct mutex g_lid_mutex; +static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; static struct accelgyro_saved_data_t g_bma255_data; -/* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI160 = 1, + BASE_GYRO_ICM426XX = 2, }; -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t base_standard_ref_bmi160 = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t base_standard_ref_icm426xx = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref_bma255 = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t lid_standard_ref_kx022 = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { .name = "Lid Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, + .active_mask = SENSOR_ACTIVE_S0_S3_S5, .chip = MOTIONSENSE_CHIP_BMA255, .type = MOTIONSENSE_TYPE_ACCEL, .location = MOTIONSENSE_LOC_LID, @@ -299,7 +179,7 @@ struct motion_sensor_t motion_sensors[] = { .drv_data = &g_bma255_data, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, - .rot_standard_ref = &lid_standard_ref, + .rot_standard_ref = &lid_standard_ref_bma255, .default_range = 2, /* g, to support lid angle calculation. */ .min_frequency = BMA255_ACCEL_MIN_FREQ, .max_frequency = BMA255_ACCEL_MAX_FREQ, @@ -330,14 +210,19 @@ struct motion_sensor_t motion_sensors[] = { .drv_data = &g_bmi160_data, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .rot_standard_ref = &base_standard_ref, + .rot_standard_ref = &base_standard_ref_bmi160, .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, .config = { - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, }, }, [BASE_GYRO] = { @@ -352,46 +237,124 @@ struct motion_sensor_t motion_sensors[] = { .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, .default_range = 1000, /* dps */ - .rot_standard_ref = &base_standard_ref, + .rot_standard_ref = &base_standard_ref_bmi160, .min_frequency = BMI_GYRO_MIN_FREQ, .max_frequency = BMI_GYRO_MAX_FREQ, }, }; unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#ifndef TEST_BUILD -/* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) -{ - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref_kx022, + .default_range = 2, /* g, enough for laptop. */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_standard_ref_icm426xx, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm426xx, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; -static int board_is_clamshell(void) +static int base_accelgyro_config; + +void motion_interrupt(enum gpio_signal signal) { - /* SKU ID of Limozeen: 4, 5 */ - return sku_id == 4 || sku_id == 5; + switch (base_accelgyro_config) { + case BASE_GYRO_ICM426XX: + icm426xx_interrupt(signal); + break; + case BASE_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } } -enum battery_cell_type board_get_battery_cell_type(void) +static void board_detect_motionsensor(void) { - /* SKU ID of Limozeen: 4, 5 -> 3S battery */ - if (sku_id == 4 || sku_id == 5) - return BATTERY_CELL_TYPE_3S; + int ret; + int val; + + /* Check lid accel chip */ + ret = i2c_read8(I2C_PORT_SENSOR, BMA2x2_I2C_ADDR1_FLAGS, + BMA2x2_CHIP_ID_ADDR, &val); + if (ret) + motion_sensors[LID_ACCEL] = kx022_lid_accel; + + CPRINTS("Lid Accel: %s", ret ? "KX022" : "BMA255"); + + /* Check base accelgyro chip */ + ret = icm_read8(&icm426xx_base_accel, ICM426XX_REG_WHO_AM_I, &val); + if (val == ICM426XX_CHIP_ICM40608) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + } - return BATTERY_CELL_TYPE_UNKNOWN; + base_accelgyro_config = (val == ICM426XX_CHIP_ICM40608) ? + BASE_GYRO_ICM426XX : + BASE_GYRO_BMI160; + CPRINTS("Base Accelgyro: %s", + (val == ICM426XX_CHIP_ICM40608) ? "ICM40608" : "BMI160"); } static void board_update_sensor_config_from_sku(void) @@ -399,175 +362,29 @@ static void board_update_sensor_config_from_sku(void) if (board_is_clamshell()) { motion_sensor_count = 0; gmr_tablet_switch_disable(); - /* The base accel is not stuffed; don't allow line to float */ + /* The sensors are not stuffed; don't allow lines to float */ gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_LID_ACCEL_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); } else { + board_detect_motionsensor(); motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Enable interrupt for the base accel sensor */ gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); } } - -/* Read SKU ID from GPIO and initialize variables for board variants */ -static void sku_init(void) -{ - uint8_t val = 0; - - if (gpio_get_level(GPIO_SKU_ID0)) - val |= 0x01; - if (gpio_get_level(GPIO_SKU_ID1)) - val |= 0x02; - if (gpio_get_level(GPIO_SKU_ID2)) - val |= 0x04; - - sku_id = val; - CPRINTS("SKU: %u", sku_id); - - board_update_sensor_config_from_sku(); -} -DECLARE_HOOK(HOOK_INIT, sku_init, HOOK_PRIO_INIT_I2C + 1); - -static int board_has_ln9310(void) -{ - static int ln9310_present = -1; - int status, val; - - /* Cache the status of LN9310 present or not */ - if (ln9310_present == -1) { - status = i2c_read8(ln9310_config.i2c_port, - ln9310_config.i2c_addr_flags, - LN9310_REG_CHIP_ID, - &val); - - /* - * Any error reading LN9310 CHIP_ID over I2C means the chip - * not present. Fallback to use DA9313 switchcap. - */ - ln9310_present = !status && val == LN9310_CHIP_ID; - } - - return ln9310_present; -} - -static void board_switchcap_init(void) -{ - if (board_has_ln9310()) { - CPRINTS("Use switchcap: LN9310"); - - /* Configure and enable interrupt for LN9310 */ - gpio_set_flags(GPIO_SWITCHCAP_PG_INT_L, GPIO_INT_FALLING); - gpio_enable_interrupt(GPIO_SWITCHCAP_PG_INT_L); - - /* - * Configure LN9310 enable, open-drain output. Don't set the - * level here; otherwise, it will override its value and - * shutdown the switchcap when sysjump to RW. - * - * Note that the gpio.inc configures it GPIO_OUT_LOW. When - * sysjump to RW, will output push-pull a short period of - * time. As it outputs LOW, should be fine. - * - * This GPIO changes like: - * (1) EC boots from RO -> high-Z - * (2) GPIO init according to gpio.inc -> push-pull LOW - * (3) This function configures it -> open-drain HIGH - * (4) Power sequence turns on the switchcap -> open-drain LOW - * (5) EC sysjumps to RW - * (6) GPIO init according to gpio.inc -> push-pull LOW - * (7) This function configures it -> open-drain LOW - */ - gpio_set_flags(GPIO_SWITCHCAP_ON_L, - GPIO_OUTPUT | GPIO_OPEN_DRAIN); - - /* Only configure the switchcap if not sysjump */ - if (!system_jumped_late()) { - /* - * Deassert the enable pin (set it HIGH), so the - * switchcap won't be enabled after the switchcap is - * configured from standby mode to switching mode. - */ - gpio_set_level(GPIO_SWITCHCAP_ON_L, 1); - ln9310_init(); - } - } else { - CPRINTS("Use switchcap: DA9313"); - - /* - * When the chip in power down mode, it outputs high-Z. - * Set pull-down to avoid floating. - */ - gpio_set_flags(GPIO_DA9313_GPIO0, GPIO_INPUT | GPIO_PULL_DOWN); - - /* - * Configure DA9313 enable, push-pull output. Don't set the - * level here; otherwise, it will override its value and - * shutdown the switchcap when sysjump to RW. - */ - gpio_set_flags(GPIO_SWITCHCAP_ON, GPIO_OUTPUT); - } -} +DECLARE_HOOK(HOOK_INIT, board_update_sensor_config_from_sku, + HOOK_PRIO_INIT_I2C + 2); /* Initialize board. */ static void board_init(void) { - /* Enable BC1.2 interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); - - /* - * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs - * for SBU may be disconnected after DP alt mode is off. Should enable - * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. - */ - gpio_enable_interrupt(GPIO_CCD_MODE_ODL); - /* Set the backlight duty cycle to 0. AP will override it later. */ pwm_set_duty(PWM_CH_DISPLIGHT, 0); - - board_switchcap_init(); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -__override uint16_t board_get_ps8xxx_product_id(int port) -{ - /* - * Lazor (SKU_ID: 0, 1, 2, 3) rev 3+ changes TCPC from PS8751 to - * PS8805. - * - * Limozeen (SKU_ID: 4, 5) all-rev uses PS8805. - */ - if ((sku_id == 0 || sku_id == 1 || sku_id == 2 || sku_id == 3) && - system_get_board_version() < 3) - return PS8751_PRODUCT_ID; - - return PS8805_PRODUCT_ID; -} - -void board_tcpc_init(void) -{ - /* Only reset TCPC if not sysjump */ - if (!system_jumped_late()) { - /* TODO(crosbug.com/p/61098): How long do we need to wait? */ - board_reset_pd_mcu(); - } - - /* Enable PPC interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); - - /* Enable TCPC interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); - - /* - * Initialize HPD to low; after sysjump SOC needs to see - * HPD pulse to enable video path - */ - for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); - /* Called on AP S0 -> S3 transition */ static void board_chipset_suspend(void) { @@ -590,154 +407,23 @@ static void board_chipset_resume(void) } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); -void board_set_switchcap_power(int enable) -{ - if (board_has_ln9310()) - gpio_set_level(GPIO_SWITCHCAP_ON_L, !enable); - else - gpio_set_level(GPIO_SWITCHCAP_ON, enable); -} - -int board_is_switchcap_enabled(void) -{ - if (board_has_ln9310()) - return !gpio_get_level(GPIO_SWITCHCAP_ON_L); - else - return gpio_get_level(GPIO_SWITCHCAP_ON); -} - -int board_is_switchcap_power_good(void) -{ - if (board_has_ln9310()) - return ln9310_power_good(); - else - return gpio_get_level(GPIO_DA9313_GPIO0); -} - -void board_reset_pd_mcu(void) -{ - cprints(CC_USB, "Resetting TCPCs..."); - cflush(); - - gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); - gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); - msleep(PS8XXX_RESET_DELAY_MS); - gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); - gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); -} - -void board_set_tcpc_power_mode(int port, int mode) -{ - /* Ignore the "mode" to turn the chip on. We can only do a reset. */ - if (mode) - return; - - board_reset_pd_mcu(); -} - -int board_vbus_sink_enable(int port, int enable) -{ - /* Both ports are controlled by PPC SN5S330 */ - return ppc_vbus_sink_enable(port, enable); -} - -int board_is_sourcing_vbus(int port) +__override uint32_t board_get_sku_id(void) { - /* Both ports are controlled by PPC SN5S330 */ - return ppc_is_sourcing_vbus(port); -} - -void board_overcurrent_event(int port, int is_overcurrented) -{ - /* TODO(b/120231371): Notify AP */ - CPRINTS("p%d: overcurrent!", port); -} - -int board_set_active_charge_port(int port) -{ - int is_real_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); - int i; - - if (!is_real_port && port != CHARGE_PORT_NONE) - return EC_ERROR_INVAL; - - if (port == CHARGE_PORT_NONE) { - CPRINTS("Disabling all charging port"); - - /* Disable all ports. */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - /* - * Do not return early if one fails otherwise we can - * get into a boot loop assertion failure. - */ - if (board_vbus_sink_enable(i, 0)) - CPRINTS("Disabling p%d sink path failed.", i); - } - - return EC_SUCCESS; - } + static int sku_id = -1; - /* Check if the port is sourcing VBUS. */ - if (board_is_sourcing_vbus(port)) { - CPRINTS("Skip enable p%d", port); - return EC_ERROR_INVAL; - } - - - CPRINTS("New charge port: p%d", port); - - /* - * Turn off the other ports' sink path FETs, before enabling the - * requested charge port. - */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - if (i == port) - continue; + if (sku_id == -1) { + int bits[3]; - if (board_vbus_sink_enable(i, 0)) - CPRINTS("p%d: sink path disable failed.", i); + bits[0] = gpio_get_ternary(GPIO_SKU_ID0); + bits[1] = gpio_get_ternary(GPIO_SKU_ID1); + bits[2] = gpio_get_ternary(GPIO_SKU_ID2); + sku_id = binary_first_base3_from_bits(bits, ARRAY_SIZE(bits)); } - /* Enable requested charge port. */ - if (board_vbus_sink_enable(port, 1)) { - CPRINTS("p%d: sink path enable failed.", port); - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* - * Ignore lower charge ceiling on PD transition if our battery is - * critical, as we may brownout. - */ - if (supplier == CHARGE_SUPPLIER_PD && - charge_ma < 1500 && - charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { - CPRINTS("Using max ilim %d", max_ma); - charge_ma = max_ma; - } - - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); + return (uint32_t)sku_id; } -uint16_t tcpc_get_alert_status(void) +__override int mkbp_support_volume_buttons(void) { - uint16_t status = 0; - - if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) - if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) - if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; + return board_has_side_volume_buttons(); } - diff --git a/board/lazor/board.h b/board/lazor/board.h index 162e03b08e..427db5e82e 100644 --- a/board/lazor/board.h +++ b/board/lazor/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,27 +10,23 @@ #include "baseboard.h" -/* TODO(waihong): Remove the following bringup features */ -#define CONFIG_BRINGUP -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands. */ -#define CONFIG_USB_PD_DEBUG_LEVEL 3 -#define CONFIG_CMD_AP_RESET_LOG -#define CONFIG_CMD_GPIO_EXTENDED -#define CONFIG_CMD_POWERINDEBUG -#define CONFIG_I2C_DEBUG - /* Internal SPI flash on NPCX7 */ -#define CONFIG_FLASH_SIZE (512 * 1024) /* 512KB internal spi flash */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Reduce flash usage */ +#define CONFIG_LTO +#define CONFIG_USB_PD_DEBUG_LEVEL 2 /* Switchcap */ #define CONFIG_LN9310 /* Keyboard */ -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_KEYBOARD_PROTOCOL_MKBP + #define CONFIG_PWM_KBLIGHT /* Battery */ -#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_REVIVE_DISCONNECT #define CONFIG_BATTERY_FUEL_GAUGE @@ -41,6 +37,7 @@ #define CONFIG_USB_PD_TCPM_MULTI_PS8XXX #define CONFIG_USB_PD_TCPM_PS8751 #define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID #define CONFIG_USBC_PPC_SN5S330 #define CONFIG_USB_PD_PORT_MAX_COUNT 2 @@ -53,11 +50,18 @@ /* BMI160 Base accel/gyro */ #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS +/* ICM426XX Base accel/gyro */ +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* KX022 lid accel */ +#define CONFIG_ACCEL_KX022 + /* BMA253 lid accel */ #define CONFIG_ACCEL_BMA255 #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) @@ -70,7 +74,6 @@ #define CONFIG_TABLET_MODE #define CONFIG_TABLET_MODE_SWITCH #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L /* GPIO alias */ #define GPIO_AC_PRESENT GPIO_ACOK_OD @@ -79,17 +82,17 @@ #define GPIO_SWITCHCAP_PG_INT_L GPIO_DA9313_GPIO0 #define GPIO_SWITCHCAP_ON_L GPIO_SWITCHCAP_ON +/* Disable console commands to help save space */ +#undef CONFIG_CMD_BATTFAKE +#undef CONFIG_CMD_CHARGE_SUPPLIER_INFO + #ifndef __ASSEMBLER__ #include "gpio_signal.h" #include "registers.h" +#include "sku.h" -enum adc_channel { - ADC_VBUS, - ADC_AMON_BMON, - ADC_PSYS, - ADC_CH_COUNT -}; +enum adc_channel { ADC_VBUS, ADC_AMON_BMON, ADC_PSYS, ADC_CH_COUNT }; /* Motion sensors */ enum sensor_id { @@ -99,11 +102,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_DISPLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_DISPLIGHT, PWM_CH_COUNT }; /* List of possible batteries */ enum battery_type { @@ -115,18 +114,14 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -/* Swithcap functions */ -void board_set_switchcap_power(int enable); -int board_is_switchcap_enabled(void); -int board_is_switchcap_power_good(void); -enum battery_cell_type board_get_battery_cell_type(void); -/* Custom function to indicate if sourcing VBUS */ -int board_is_sourcing_vbus(int port); -/* Enable VBUS sink for a given port */ -int board_vbus_sink_enable(int port, int enable); +/* support factory keyboard test */ +#define CONFIG_KEYBOARD_FACTORY_TEST + /* Reset all TCPCs. */ void board_reset_pd_mcu(void); void board_set_tcpc_power_mode(int port, int mode); +/* Motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); #endif /* !defined(__ASSEMBLER__) */ diff --git a/board/lazor/build.mk b/board/lazor/build.mk index a044fa58cb..c17ab5e40c 100644 --- a/board/lazor/build.mk +++ b/board/lazor/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,4 +11,10 @@ CHIP_FAMILY:=npcx7 CHIP_VARIANT:=npcx7m6fc BASEBOARD:=trogdor -board-y=battery.o board.o led.o +board-y+=battery.o +board-y+=board.o +board-y+=hibernate.o +board-y+=led.o +board-y+=sku.o +board-y+=switchcap.o +board-y+=usbc_config.o diff --git a/board/lazor/ec.tasklist b/board/lazor/ec.tasklist index 2b55c26c20..92d5a1dde1 100644 --- a/board/lazor/ec.tasklist +++ b/board/lazor/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/lazor/gpio.inc b/board/lazor/gpio.inc index 744cfd96fa..c7af05eb3b 100644 --- a/board/lazor/gpio.inc +++ b/board/lazor/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,26 +8,26 @@ /* Declare symbolic names for all the GPIOs that we care about. * Note: Those with interrupt handlers must be declared first. */ -/* USB-C interrupts */ +/* USB interrupts */ GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ -GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING, usb0_evt) /* Interrupt from port-0 BC1.2 */ -GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING, usb1_evt) /* Interrupt from port-1 BC1.2 */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb1_evt) /* Interrupt from port-1 BC1.2 */ +GPIO_INT(USB_A0_OC_ODL, PIN(D, 1), GPIO_INT_BOTH | GPIO_PULL_UP, usba_oc_interrupt) /* System interrupts */ -GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) /* AC OK? */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ -GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) /* Lid open? */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ -GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ -GPIO_INT(PMIC_FAULT_L, PIN(A, 3), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) /* Any PMIC fault? */ -GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ /* * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down @@ -41,36 +41,31 @@ GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs /* Sensor interrupts */ GPIO_INT(TABLET_MODE_L, PIN(C, 6), GPIO_INT_BOTH, gmr_tablet_switch_isr) -GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) /* Accelerometer/gyro interrupt */ +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, motion_interrupt) /* Accelerometer/gyro interrupt */ /* Switchcap * * For DA9313 SKUs, it is GPIO0 of DA9313. The GPIO0 is configured as PVC_PG. * For LN9310 SKUs, it is the interrupt line of LN9310. */ -GPIO_INT(DA9313_GPIO0, PIN(E, 2), GPIO_INT_FALLING, switchcap_interrupt) +GPIO_INT(DA9313_GPIO0, PIN(E, 2), GPIO_INT_FALLING, ln9310_interrupt) /* - * EC_RST_ODL acts as a wake source from PSL hibernate mode. However, it does - * not need to be an interrupt for normal EC operations. Thus, configure it as - * GPIO_INT_BOTH with wake on low-to-high edge using GPIO_HIB_WAKE_HIGH so that - * PSL common code can configure PSL_IN correctly. - * - * Use the rising edge to wake EC up. If we chose the falling edge, it would - * still wake EC up, but EC is in an intermediate state until the signal goes - * back to high. + * EC_RST_ODL used to be a wake source from PSL mode. However, we disabled + * the PSL mode. This GPIO does nothing now. Simply set it an INPUT. */ -GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* Wake source: EC reset */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ /* PMIC/AP 1.8V */ -GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC reset trigger */ -GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC power button */ +GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ GPIO(QSIP_ON, PIN(5, 0), GPIO_OUT_LOW) /* Not used, for non-switchcap testing */ /* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ GPIO(SWITCHCAP_ON, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap; will be configured in the board init */ /* TODO(waihong): Remove it. The VBOB switch is for backup. */ GPIO(VBOB_EN, PIN(D, 3), GPIO_OUT_LOW) /* Enable VBOB */ @@ -87,23 +82,27 @@ GPIO(TRACKPAD_INT_GATE, PIN(7, 4), GPIO_OUT_LOW) /* USB-C */ GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_ODR_HIGH) /* Port-0 TCPC chip reset, actaully Open-Drain */ GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_ODR_HIGH) /* Port-1 TCPC chip reset, actually Open-Drain */ -GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_OUT_HIGH) /* DP mux enable */ -GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_HIGH) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ -/* TODO(waihong): Remove it from schematic. No use. */ -GPIO(USBC_MUX_CONF0, PIN(5, 1), GPIO_INPUT) -GPIO(USB_C0_VBUS_DET_L, PIN(6, 2), GPIO_INPUT) /* Deprecated BC1.2 VBUS detection on port-0 */ -GPIO(USB_C1_VBUS_DET_L, PIN(8, 3), GPIO_INPUT) /* Deprecated BC1.2 VBUS detection on port-1 */ /* USB-A */ GPIO(EN_USB_A_5V, PIN(8, 6), GPIO_OUT_LOW) GPIO(USB_A_CDP_ILIM_EN, PIN(7, 5), GPIO_OUT_HIGH) /* H: CDP, L:SDP. Only one USB-A port, always CDP */ -GPIO(USB_A0_OC_ODL, PIN(D, 1), GPIO_ODR_HIGH) /* LEDs */ GPIO(EC_CHG_LED_Y_C1, PIN(C, 3), GPIO_OUT_LOW) GPIO(EC_CHG_LED_B_C1, PIN(C, 4), GPIO_OUT_LOW) +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + /* PWM */ GPIO(KB_BL_PWM, PIN(8, 0), GPIO_INPUT) /* PWM3 */ GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ @@ -133,6 +132,35 @@ GPIO(SKU_ID0, PIN(F, 0), GPIO_INPUT) GPIO(SKU_ID1, PIN(4, 1), GPIO_INPUT) GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(0, 4)) +UNUSED(PIN(C, 0)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(3, 7)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(7, 3)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(6, 2)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(6, 0)) +UNUSED(PIN(7, 2)) + /* Alternate functions GPIO definitions */ ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ @@ -145,10 +173,6 @@ ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* PWM3 (GPIO80) - KB_BL_PWM */ ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ -ALTERNATE(PIN_MASK(D, 0x04), 1, MODULE_PMU, 0) /* PSL_IN1 (GPIOD2) - LID_OPEN_EC */ -ALTERNATE(PIN_MASK(0, 0x01), 1, MODULE_PMU, 0) /* PSL_IN2 (GPIO00) - ACOK_OD */ -ALTERNATE(PIN_MASK(0, 0x02), 1, MODULE_PMU, 0) /* PSL_IN3 (GPIO01) - EC_PWR_BTN_ODL */ -ALTERNATE(PIN_MASK(0, 0x04), 1, MODULE_PMU, 0) /* PSL_IN4 (GPIO02) - EC_RST_ODL */ /* Keyboard */ #define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/lazor/hibernate.c b/board/lazor/hibernate.c new file mode 100644 index 0000000000..67d9b30791 --- /dev/null +++ b/board/lazor/hibernate.c @@ -0,0 +1,41 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "gpio.h" +#include "sku.h" +#include "system.h" +#include "usbc_ppc.h" + +void board_hibernate(void) +{ + int i; + + if (!board_is_clamshell()) { + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_LID_ACCEL_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } + + /* + * Board rev 5+ has the hardware fix. Don't need the following + * workaround. + */ + if (system_get_board_version() >= 5) + return; + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + ppc_vbus_sink_enable(i, 1); +} diff --git a/board/lazor/led.c b/board/lazor/led.c index f9c91c1c6a..bb41dfb8f7 100644 --- a/board/lazor/led.c +++ b/board/lazor/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -32,15 +32,15 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_BLUE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static void led_set_color(enum led_color color) { gpio_set_level(GPIO_EC_CHG_LED_Y_C1, - (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); gpio_set_level(GPIO_EC_CHG_LED_B_C1, - (color == LED_BLUE) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_BLUE) ? BAT_LED_ON : BAT_LED_OFF); } void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) @@ -66,16 +66,15 @@ static void board_led_set_battery(void) static int battery_ticks; int color = LED_OFF; int period = 0; - uint32_t chflags = charge_get_flags(); battery_ticks++; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate amber on when charging. */ color = LED_AMBER; break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { /* Discharging in S3: Amber 1 sec, off 3 sec */ period = (1 + 3) * LED_ONE_SEC; @@ -92,7 +91,7 @@ static void board_led_set_battery(void) color = LED_BLUE; } break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: /* Battery error: Amber 1 sec, off 1 sec */ period = (1 + 1) * LED_ONE_SEC; battery_ticks = battery_ticks % period; @@ -101,21 +100,21 @@ static void board_led_set_battery(void) else color = LED_OFF; break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: /* Full Charged: Blue on */ color = LED_BLUE; break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) { - /* Factory mode: Blue 2 sec, Amber 2 sec */ - period = (2 + 2) * LED_ONE_SEC; - battery_ticks = battery_ticks % period; - if (battery_ticks < 2 * LED_ONE_SEC) - color = LED_BLUE; - else - color = LED_AMBER; - } else + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_BLUE; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode: Blue 2 sec, Amber 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) color = LED_BLUE; + else + color = LED_AMBER; break; default: /* Other states don't alter LED behavior */ diff --git a/board/lazor/sku.c b/board/lazor/sku.c new file mode 100644 index 0000000000..0b622046a7 --- /dev/null +++ b/board/lazor/sku.c @@ -0,0 +1,98 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "config.h" +#include "console.h" +#include "driver/ln9310.h" +#include "gpio.h" +#include "hooks.h" +#include "sku.h" +#include "system.h" +#include "tcpm/ps8xxx_public.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +static uint8_t sku_id; + +enum board_model { + LAZOR, + LIMOZEEN, + UNKNOWN, +}; + +static const char *const model_name[] = { + "LAZOR", + "LIMOZEEN", + "UNKNOWN", +}; + +static enum board_model get_model(void) +{ + if (sku_id == 0 || sku_id == 1 || sku_id == 2 || sku_id == 3) + return LAZOR; + if (sku_id == 4 || sku_id == 5 || sku_id == 6) + return LIMOZEEN; + return UNKNOWN; +} + +/* Read SKU ID from GPIO and initialize variables for board variants */ +static void sku_init(void) +{ + sku_id = system_get_sku_id(); + CPRINTS("SKU: %u (%s)", sku_id, model_name[get_model()]); +} +DECLARE_HOOK(HOOK_INIT, sku_init, HOOK_PRIO_INIT_I2C + 1); + +enum battery_cell_type board_get_battery_cell_type(void) +{ + switch (get_model()) { + case LIMOZEEN: + return BATTERY_CELL_TYPE_3S; + default: + return BATTERY_CELL_TYPE_UNKNOWN; + } +} + +int board_is_clamshell(void) +{ + return get_model() == LIMOZEEN; +} + +__override uint16_t board_get_ps8xxx_product_id(int port) +{ + /* + * Lazor (SKU_ID: 0, 1, 2, 3) rev 3+ changes TCPC from PS8751 to + * PS8805. + * + * Limozeen (SKU_ID: 4, 5, 6) all-rev uses PS8805. + */ + if (get_model() == LAZOR && system_get_board_version() < 3) + return PS8751_PRODUCT_ID; + + return PS8805_PRODUCT_ID; +} + +int board_has_da9313(void) +{ + return get_model() == LAZOR; +} + +int board_has_buck_ic(void) +{ + return get_model() == LIMOZEEN && system_get_board_version() >= 8; +} + +int board_has_ln9310(void) +{ + return get_model() == LIMOZEEN && system_get_board_version() < 8; +} + +int board_has_side_volume_buttons(void) +{ + return get_model() == LAZOR; +} diff --git a/board/lazor/sku.h b/board/lazor/sku.h new file mode 100644 index 0000000000..3ba687939d --- /dev/null +++ b/board/lazor/sku.h @@ -0,0 +1,18 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lazor board-specific SKU configuration */ + +#ifndef __CROS_EC_SKU_H +#define __CROS_EC_SKU_H + +int board_get_version(void); +int board_is_clamshell(void); +int board_has_da9313(void); +int board_has_ln9310(void); +int board_has_buck_ic(void); +int board_has_side_volume_buttons(void); + +#endif /* __CROS_EC_SKU_H */ diff --git a/board/lazor/switchcap.c b/board/lazor/switchcap.c new file mode 100644 index 0000000000..fc9dce3ada --- /dev/null +++ b/board/lazor/switchcap.c @@ -0,0 +1,121 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "config.h" +#include "console.h" +#include "driver/ln9310.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "power/qcom.h" +#include "sku.h" +#include "system.h" + +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) + +/* LN9310 switchcap */ +const struct ln9310_config_t ln9310_config = { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = LN9310_I2C_ADDR_0_FLAGS, +}; + +static void switchcap_init(void) +{ + if (board_has_da9313()) { + CPRINTS("Use switchcap: DA9313"); + + /* + * When the chip in power down mode, it outputs high-Z. + * Set pull-down to avoid floating. + */ + gpio_set_flags(GPIO_DA9313_GPIO0, GPIO_INPUT | GPIO_PULL_DOWN); + + /* + * Configure DA9313 enable, push-pull output. Don't set the + * level here; otherwise, it will override its value and + * shutdown the switchcap when sysjump to RW. + */ + gpio_set_flags(GPIO_SWITCHCAP_ON, GPIO_OUTPUT); + } else if (board_has_ln9310()) { + CPRINTS("Use switchcap: LN9310"); + + /* Configure and enable interrupt for LN9310 */ + gpio_set_flags(GPIO_SWITCHCAP_PG_INT_L, GPIO_INT_FALLING); + gpio_enable_interrupt(GPIO_SWITCHCAP_PG_INT_L); + + /* + * Configure LN9310 enable, open-drain output. Don't set the + * level here; otherwise, it will override its value and + * shutdown the switchcap when sysjump to RW. + * + * Note that the gpio.inc configures it GPIO_OUT_LOW. When + * sysjump to RW, will output push-pull a short period of + * time. As it outputs LOW, should be fine. + * + * This GPIO changes like: + * (1) EC boots from RO -> high-Z + * (2) GPIO init according to gpio.inc -> push-pull LOW + * (3) This function configures it -> open-drain HIGH + * (4) Power sequence turns on the switchcap -> open-drain LOW + * (5) EC sysjumps to RW + * (6) GPIO init according to gpio.inc -> push-pull LOW + * (7) This function configures it -> open-drain LOW + */ + gpio_set_flags(GPIO_SWITCHCAP_ON_L, + GPIO_OUTPUT | GPIO_OPEN_DRAIN); + + /* Only configure the switchcap if not sysjump */ + if (!system_jumped_late()) { + /* + * Deassert the enable pin (set it HIGH), so the + * switchcap won't be enabled after the switchcap is + * configured from standby mode to switching mode. + */ + gpio_set_level(GPIO_SWITCHCAP_ON_L, 1); + ln9310_init(); + } + } else if (board_has_buck_ic()) { + CPRINTS("Use Buck IC"); + } else { + CPRINTS("ERROR: No switchcap solution"); + } +} +DECLARE_HOOK(HOOK_INIT, switchcap_init, HOOK_PRIO_DEFAULT); + +void board_set_switchcap_power(int enable) +{ + if (board_has_da9313()) { + gpio_set_level(GPIO_SWITCHCAP_ON, enable); + } else if (board_has_ln9310()) { + gpio_set_level(GPIO_SWITCHCAP_ON_L, !enable); + ln9310_software_enable(enable); + } else if (board_has_buck_ic()) { + gpio_set_level(GPIO_VBOB_EN, enable); + } +} + +int board_is_switchcap_enabled(void) +{ + if (board_has_da9313()) + return gpio_get_level(GPIO_SWITCHCAP_ON); + else if (board_has_ln9310()) + return !gpio_get_level(GPIO_SWITCHCAP_ON_L); + + /* Board has buck ic*/ + return gpio_get_level(GPIO_VBOB_EN); +} + +int board_is_switchcap_power_good(void) +{ + if (board_has_da9313()) + return gpio_get_level(GPIO_DA9313_GPIO0); + else if (board_has_ln9310()) + return ln9310_power_good(); + + /* Board has buck ic no way to check POWER GOOD */ + return 1; +} diff --git a/board/lazor/usbc_config.c b/board/lazor/usbc_config.c new file mode 100644 index 0000000000..410d0c19d1 --- /dev/null +++ b/board/lazor/usbc_config.c @@ -0,0 +1,402 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lazor board-specific USB-C configuration */ + +#include "battery_fuel_gauge.h" +#include "bc12/pi3usb9201_public.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "common.h" +#include "config.h" +#include "driver/ln9310.h" +#include "gpio.h" +#include "hooks.h" +#include "ppc/sn5s330_public.h" +#include "system.h" +#include "tcpm/ps8xxx_public.h" +#include "tcpm/tcpci.h" +#include "timer.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_config.h" +#include "usbc_ocp.h" +#include "usbc_ppc.h" + +/* Disable debug messages to free flash space */ +#define CPRINTS(format, args...) +#define CPRINTF(format, args...) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +void usb1_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void usba_oc_deferred(void) +{ + /* Use next number after all USB-C ports to indicate the USB-A port */ + board_overcurrent_event(CONFIG_USB_PD_PORT_MAX_COUNT, + !gpio_get_level(GPIO_USB_A0_OC_ODL)); +} +DECLARE_DEFERRED(usba_oc_deferred); + +void usba_oc_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&usba_oc_deferred_data, 0); +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + case GPIO_USB_C1_SWCTL_INT_ODL: + sn5s330_interrupt(1); + break; + default: + break; + } +} + +static void board_connect_c0_sbu_deferred(void) +{ + /* + * If CCD_MODE_ODL asserts, it means there's a debug accessory connected + * and we should enable the SBU FETs. + */ + ppc_set_sbu(0, 1); +} +DECLARE_DEFERRED(board_connect_c0_sbu_deferred); + +void board_connect_c0_sbu(enum gpio_signal s) +{ + hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); +} + +/* GPIO Interrupt Handlers */ +void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_PD_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + } +}; + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + { + .i2c_port = I2C_PORT_EEPROM, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +__override int board_get_default_battery_type(void) +{ + /* + * A 2S battery is set as default. If the board is configured to use + * a 3S battery, according to its SKU_ID, return a 3S battery as + * default. It helps to configure the charger to output a correct + * voltage in case the battery is not attached. + */ + if (board_get_battery_cell_type() == BATTERY_CELL_TYPE_3S) + return BATTERY_LGC_AP18C8K; + + return DEFAULT_BATTERY_TYPE; +} + +/* Initialize board USC-C things */ +static void board_init_usbc(void) +{ + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + + /* Enable USB-A overcurrent interrupt */ + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + /* + * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs + * for SBU may be disconnected after DP alt mode is off. Should enable + * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. + */ + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init_usbc, HOOK_PRIO_DEFAULT); + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} diff --git a/board/lazor/usbc_config.h b/board/lazor/usbc_config.h new file mode 100644 index 0000000000..53d6df3983 --- /dev/null +++ b/board/lazor/usbc_config.h @@ -0,0 +1,20 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* lazor board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#include "gpio.h" + +void tcpc_alert_event(enum gpio_signal signal); +void usb0_evt(enum gpio_signal signal); +void usb1_evt(enum gpio_signal signal); +void usba_oc_interrupt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); +void board_connect_c0_sbu(enum gpio_signal s); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/lazor/vif_override.xml b/board/lazor/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/lazor/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/liara/battery.c b/board/liara/battery.c index 25df841018..291925cd06 100644 --- a/board/liara/battery.c +++ b/board/liara/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -165,27 +165,3 @@ const struct board_batt_params board_battery_info[] = { BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_PANASONIC; - -/* Lower our input voltage to 5V in S5/G3 when battery is full. */ -static void reduce_input_voltage_when_full(void) -{ - int max_pd_voltage_mv; - int port; - - if (charge_get_percent() == 100 && - chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) - max_pd_voltage_mv = 5000; - else - max_pd_voltage_mv = PD_MAX_VOLTAGE_MV; - - if (pd_get_max_voltage() != max_pd_voltage_mv) { - for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) - pd_set_external_voltage_limit(port, max_pd_voltage_mv); - } -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, reduce_input_voltage_when_full, - HOOK_PRIO_DEFAULT); diff --git a/board/liara/board.c b/board/liara/board.c index 4f8b552d1f..e919cdb4e7 100644 --- a/board/liara/board.c +++ b/board/liara/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,6 +17,7 @@ #include "pwm_chip.h" #include "switch.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" const enum gpio_signal hibernate_wake_pins[] = { @@ -25,16 +26,40 @@ const enum gpio_signal hibernate_wake_pins[] = { GPIO_POWER_BUTTON_L, GPIO_EC_RST_ODL, }; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* I2C port map. */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"thermal", I2C_PORT_THERMAL_AP, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"kblight", I2C_PORT_KBLIGHT, 100, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "thermal", + .port = I2C_PORT_THERMAL_AP, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "kblight", + .port = I2C_PORT_KBLIGHT, + .kbps = 100, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/liara/board.h b/board/liara/board.h index b869f9f8c1..4ef9a11793 100644 --- a/board/liara/board.h +++ b/board/liara/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,12 +17,14 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF #define CONFIG_MKBP_USE_HOST_EVENT +#define CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV 5000 + /* Power and battery LEDs */ #define CONFIG_LED_COMMON #define CONFIG_LED_PWM_CHARGE_STATE_ONLY diff --git a/board/liara/build.mk b/board/liara/build.mk index c808e65aed..d24127ddae 100644 --- a/board/liara/build.mk +++ b/board/liara/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/liara/ec.tasklist b/board/liara/ec.tasklist index b562761311..24300fe7da 100644 --- a/board/liara/ec.tasklist +++ b/board/liara/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/liara/gpio.inc b/board/liara/gpio.inc index 343c50f503..a1c3e1a25f 100644 --- a/board/liara/gpio.inc +++ b/board/liara/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/liara/led.c b/board/liara/led.c index 8efb6150fc..45cc43edc8 100644 --- a/board/liara/led.c +++ b/board/liara/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,14 +18,11 @@ const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); * We only have a blue and an amber LED, so setting any other colour results in * both LEDs being off. */ -struct pwm_led led_color_map[EC_LED_COLOR_COUNT] = { - /* White, Amber */ - [EC_LED_COLOR_RED] = { 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0 }, - [EC_LED_COLOR_YELLOW] = { 0, 0 }, - [EC_LED_COLOR_WHITE] = { 100, 0 }, - [EC_LED_COLOR_AMBER] = { 0, 100 }, +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* White, Amber */ + [EC_LED_COLOR_RED] = { 0, 0 }, [EC_LED_COLOR_GREEN] = { 0, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0 }, [EC_LED_COLOR_YELLOW] = { 0, 0 }, + [EC_LED_COLOR_WHITE] = { 100, 0 }, [EC_LED_COLOR_AMBER] = { 0, 100 }, }; /* One logical LED with amber and blue channels. */ diff --git a/board/liara/vif_override.xml b/board/liara/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/liara/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/lick/battery.c b/board/lick/battery.c index fa746a8c9f..01ab23dd3b 100644 --- a/board/lick/battery.c +++ b/board/lick/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/lick/board.c b/board/lick/board.c index 71512249be..2aea264d69 100644 --- a/board/lick/board.c +++ b/board/lick/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,7 @@ /* Lick board-specific configuration */ #include "adc.h" -#include "adc_chip.h" +#include "battery_smart.h" #include "button.h" #include "charge_state.h" #include "common.h" @@ -24,19 +24,18 @@ #include "power.h" #include "power_button.h" #include "switch.h" -#include "task.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "task.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "util.h" -#include "battery_smart.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define USB_PD_PORT_ANX7447 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 static uint8_t sku_id; @@ -61,31 +60,31 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, /* Vbus sensing (1/10 voltage divider). */ - [ADC_VBUS_C0] = { - "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, - [ADC_VBUS_C1] = { - "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C0] = { "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + [ADC_VBUS_C1] = { "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -95,11 +94,9 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate lid and base sensor into standard reference frame */ -const mat33_fp_t standard_rot_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t standard_rot_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct stprivate_data g_lis2dh_data; @@ -145,8 +142,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &standard_rot_ref, @@ -177,8 +172,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -197,11 +190,10 @@ static int board_is_convertible(void) static void board_update_sensor_config_from_sku(void) { - motion_sensor_count = 0; - gmr_tablet_switch_disable(); - /* Base accel is not stuffed, don't allow line to float */ - gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, - GPIO_INPUT | GPIO_PULL_DOWN); + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); } static void cbi_init(void) @@ -216,9 +208,8 @@ static void cbi_init(void) } DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -231,7 +222,6 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif int board_is_lid_angle_tablet_mode(void) { @@ -239,11 +229,11 @@ int board_is_lid_angle_tablet_mode(void) } /* Battery functions */ -#define SB_OPTIONALMFG_FUNCTION2 0x3e +#define SB_OPTIONALMFG_FUNCTION2 0x3e /* Optional mfg function2 */ -#define SMART_QUICK_CHARGE (1<<12) +#define SMART_QUICK_CHARGE (1 << 12) /* Quick charge support */ -#define MODE_QUICK_CHARGE_SUPPORT (1<<4) +#define MODE_QUICK_CHARGE_SUPPORT (1 << 4) static void sb_quick_charge_mode(int enable) { diff --git a/board/lick/board.h b/board/lick/board.h index cf3a7c013a..05f24f141d 100644 --- a/board/lick/board.h +++ b/board/lick/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,12 +13,13 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + #define CONFIG_VOLUME_BUTTONS #define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL #define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL #define CONFIG_LED_COMMON -#define CONFIG_LED_POWER_LED #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_13K7_47K_4050B @@ -29,8 +30,8 @@ #define CONFIG_CMD_ACCEL_INFO /* Sensors */ -#define CONFIG_ACCEL_LIS2DE /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LIS2DE /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) @@ -49,10 +50,10 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ - ADC_VBUS_C0, /* ADC9 */ - ADC_VBUS_C1, /* ADC4 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_VBUS_C0, /* ADC9 */ + ADC_VBUS_C1, /* ADC4 */ ADC_CH_COUNT, }; @@ -63,18 +64,10 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { diff --git a/board/lick/build.mk b/board/lick/build.mk index 137e208b53..fee77e38b5 100644 --- a/board/lick/build.mk +++ b/board/lick/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/lick/ec.tasklist b/board/lick/ec.tasklist index 6eac78a042..6c56976091 100644 --- a/board/lick/ec.tasklist +++ b/board/lick/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/lick/gpio.inc b/board/lick/gpio.inc index ad6773a211..3a553f6e91 100644 --- a/board/lick/gpio.inc +++ b/board/lick/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/lick/led.c b/board/lick/led.c index 3985c519f3..1d5bd17c0d 100644 --- a/board/lick/led.c +++ b/board/lick/led.c @@ -1,53 +1,57 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Lick */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 97; +__override const int led_charge_lvl_2 = 97; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_ON_LVL); @@ -56,7 +60,7 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_RED: @@ -109,4 +113,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/lick/vif_override.xml b/board/lick/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/lick/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/lindar/battery.c b/board/lindar/battery.c index 7f37c6fe10..e206a5c6aa 100644 --- a/board/lindar/battery.c +++ b/board/lindar/battery.c @@ -1,11 +1,13 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Battery pack vendor provided charging profile */ +#include "battery.h" #include "battery_fuel_gauge.h" +#include "battery_smart.h" #include "common.h" #include "util.h" @@ -121,3 +123,15 @@ const struct board_batt_params board_battery_info[] = { BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP; + +__override bool board_battery_is_initialized(void) +{ + bool batt_initialization_state; + int batt_status; + + batt_initialization_state = + (battery_status(&batt_status) ? + false : + !!(batt_status & STATUS_INITIALIZED)); + return batt_initialization_state; +} diff --git a/board/lindar/board.c b/board/lindar/board.c index ce30e301c9..49d90502ba 100644 --- a/board/lindar/board.c +++ b/board/lindar/board.c @@ -1,10 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* Malefor board-specific configuration */ -#include "bb_retimer.h" +/* lindar board-specific configuration */ #include "button.h" #include "cbi_ec_fw_config.h" #include "common.h" @@ -15,6 +14,7 @@ #include "driver/ppc/syv682x.h" #include "driver/sync.h" #include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/rt1715.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tusb422.h" #include "extpower.h" @@ -30,8 +30,8 @@ #include "pwm_chip.h" #include "switch.h" #include "system.h" -#include "task.h" #include "tablet_mode.h" +#include "task.h" #include "uart.h" #include "usb_mux.h" #include "usb_pd.h" @@ -39,13 +39,14 @@ #include "usbc_ppc.h" #include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ##args) /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Increase from 50 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* Other values should be the same as the default configuration. */ @@ -76,7 +77,7 @@ static void board_init(void) } else { motion_sensor_count = 0; /* Device is clamshell only */ - tablet_set_mode(0); + tablet_set_mode(0, TABLET_TRIGGER_LID); /* Gyro is not present, don't allow line to float */ gpio_set_flags(GPIO_EC_IMU_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); } @@ -91,23 +92,33 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +int board_is_i2c_port_powered(int port) +{ + if (port != I2C_PORT_LIGHTBAR) + return 1; + + /* + * Lightbar rails are off in S5/G3 + * Refer CL-2739008. + */ + return chipset_in_state(CHIPSET_STATE_ANY_OFF) ? 0 : 1; +} + int board_is_lid_angle_tablet_mode(void) { return ec_cfg_has_tabletmode(); } /* Enable or disable input devices, based on tablet mode or chipset state */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { if (ec_cfg_has_tabletmode()) { if (chipset_in_state(CHIPSET_STATE_ANY_OFF) || - tablet_get_mode()) + tablet_get_mode()) enable = 0; keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } } -#endif /******************************************************************************/ /* Sensors */ @@ -120,17 +131,13 @@ static struct stprivate_data g_lis2dh_data; static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; /* Matrix to rotate lid and base sensor into standard reference frame */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -170,8 +177,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_EC_IMU_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &base_standard_ref, @@ -202,8 +207,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_EC_IMU_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -219,7 +222,7 @@ unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -250,19 +253,24 @@ const struct fan_t fans[FAN_CH_COUNT] = { /* * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at * 130 C. However, sensor is located next to DDR, so we need to use the lower - * DDR temperature limit (85 C) + * DDR temperature limit (100 C) */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + }, \ + .temp_fan_off = C_TO_K(30), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; /* * Inductor limits - used for both charger and PP3300 regulator @@ -273,26 +281,31 @@ const static struct ec_thermal_config thermal_cpu = { * PP3300 regulator: operating range -40 C to 145 C * * Inductors: limit of 125c - * PCB: limit is 80c + * PCB: limit is 100c */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + }, \ + .temp_fan_off = C_TO_K(30), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -385,42 +398,59 @@ const struct pwm_t pwm_channels[] = { }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -/* USBC TCPC configuration for port 1 on USB3 board */ -static const struct tcpc_config_t tcpc_config_p1_usb3 = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .flags = TCPC_FLAGS_TCPCI_REV2_0 | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, - .drv = &ps8xxx_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), -}; +static void kb_backlight_enable(void) +{ + if (ec_cfg_has_keyboard_backlight() == 1) + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, kb_backlight_enable, HOOK_PRIO_DEFAULT); -static const struct usb_mux usbc1_usb3_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .next_mux = NULL, -}; +static void kb_backlight_disable(void) +{ + if (ec_cfg_has_keyboard_backlight() == 1) + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kb_backlight_disable, HOOK_PRIO_DEFAULT); -static const struct usb_mux mux_config_p1_usb3 = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb3_db_retimer, +/* USB-A charging control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, }; -void board_reset_pd_mcu(void) +static void ps8815_reset(void) { - /* TODO(b/159024035): Malefor: check USB PD reset operation */ + int val; + + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 0); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 1); + msleep(PS8815_FW_INIT_DELAY_MS); + + /* + * b/144397088 + * ps8815 firmware 0x01 needs special configuration + */ + + CPRINTS("%s: patching ps8815 registers", __func__); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f was %02x", val); + + if (i2c_write8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f set to 0x31"); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f now %02x", val); } -__override void board_cbi_init(void) +void board_reset_pd_mcu(void) { - /* Config DB USB3 */ - tcpc_config[USBC_PORT_C1] = tcpc_config_p1_usb3; - usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3; + ps8815_reset(); + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } /******************************************************************************/ @@ -450,6 +480,7 @@ void ppc_interrupt(enum gpio_signal signal) break; case GPIO_USB_C1_PPC_INT_ODL: syv682x_interrupt(USBC_PORT_C1); + break; default: break; } @@ -476,19 +507,19 @@ struct tcpc_config_t tcpc_config[] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C0, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, + .addr_flags = RT1715_I2C_ADDR_FLAGS, }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), + .drv = &rt1715_tcpm_drv, }, [USBC_PORT_C1] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C1, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), + .flags = TCPC_FLAGS_TCPCI_REV2_0 + | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, }, }; BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); @@ -496,37 +527,35 @@ BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); /******************************************************************************/ /* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usb_muxes[] = { - [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, - }, +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, }; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); -struct bb_usb_control bb_controls[] = { +const struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - /* USB-C port 0 doesn't have a retimer */ + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = NULL, }, [USBC_PORT_C1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, }, }; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); static void board_tcpc_init(void) { @@ -545,6 +574,13 @@ static void board_tcpc_init(void) /* Enable BC1.2 interrupts. */ gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); + + if (get_board_id() <= 1) { + tcpc_config[USBC_PORT_C0].i2c_info.addr_flags = + TUSB422_I2C_ADDR_FLAGS; + tcpc_config[USBC_PORT_C0].drv = &tusb422_tcpm_drv; + tcpc_config[USBC_PORT_C0].flags = 0; + } } DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); diff --git a/board/lindar/board.h b/board/lindar/board.h index bacac9d015..7c407d05a7 100644 --- a/board/lindar/board.h +++ b/board/lindar/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,8 +11,9 @@ /* Baseboard features */ #include "baseboard.h" -/* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +#define CONFIG_VBOOT_EFS2 #define CONFIG_POWER_BUTTON @@ -20,19 +21,17 @@ #define CONFIG_UART_TX_BUF_SIZE 4096 /* LED defines */ -#define CONFIG_LED_POWER_LED #define CONFIG_LED_ONOFF_STATES /* Keyboard features */ /* Sensors */ #define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT -#define CONFIG_ACCEL_LIS2DE /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LIS2DE /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - BIT(LID_ACCEL) +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE @@ -43,39 +42,29 @@ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) /* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ /* * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C * cables only support up to 60W. */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 -/* Enabling USB4 mode */ -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +#undef CONFIG_USB_MUX_RUNTIME_CONFIG /* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB /* USBC PPC*/ -#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ +#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ /* BC 1.2 */ @@ -84,8 +73,15 @@ /* Fan features */ /* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +/* Retimer */ +#undef CONFIG_USBC_RETIMER_INTEL_BB +#undef CONFIG_USBC_RETIMER_INTEL_BB_RUNTIME_CONFIG + +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP /* * Macros for GPIO signals used in common code that don't match the @@ -93,45 +89,43 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_MUTE_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_MUTE_BTN_ODL /* I2C Bus Configuration */ #define CONFIG_I2C -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_LIGHTBAR NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_COUNT +#define CONFIG_I2C_BUS_MAY_BE_UNPOWERED +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_LIGHTBAR NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER #ifndef __ASSEMBLER__ @@ -159,11 +153,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; void board_reset_pd_mcu(void); diff --git a/board/lindar/build.mk b/board/lindar/build.mk index 279b2e559e..d590255d2a 100644 --- a/board/lindar/build.mk +++ b/board/lindar/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,7 +8,7 @@ CHIP:=npcx CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc +CHIP_VARIANT:=npcx7m7fc BASEBOARD:=volteer board-y=board.o diff --git a/board/lindar/ec.tasklist b/board/lindar/ec.tasklist index 292de51cdb..c29125d517 100644 --- a/board/lindar/ec.tasklist +++ b/board/lindar/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,6 +16,7 @@ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/lindar/gpio.inc b/board/lindar/gpio.inc index 611512a7b6..f8c036b96c 100644 --- a/board/lindar/gpio.inc +++ b/board/lindar/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -83,6 +83,9 @@ GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) /* USB and USBC Signals */ +GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ +GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ + GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset on boards board ID >=1 */ GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) @@ -92,12 +95,13 @@ UNIMPLEMENTED(USB_C1_LS_EN) /* Misc Signals */ GPIO(EC_H1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) /* H1 Packet Mode */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ /* - * Determine the polarity of these SSD signals and whether - * they are open-drain. + * Despite their names, M2_SSD_PLN and M2_SSD_PLA are active-low, and M2_SSD_PLN + * is open-drain. */ -GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_OUT_HIGH) /* SSD power-loss notification */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_ODR_HIGH) /* SSD power-loss notification */ GPIO(M2_SSD_PLA, PIN(7, 0), GPIO_INPUT) /* SSD power-loss acknoledgement */ /* @@ -144,6 +148,7 @@ ALTERNATE(PIN_MASK(4, BIT(0)), 0, MODULE_PWM, 0) /* FAN_SPEED_TACH */ /* Keyboard pins */ #define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) /* Keyboard backlight */ ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ @@ -162,6 +167,10 @@ ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = GPIO01 = H1_EC_PWR_BTN_ODL GPIO02 = EC_RST_ODL */ +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ + /* Unused signals */ GPIO(UNUSED_GPIO60, PIN(6, 0), GPIO_INPUT | GPIO_PULL_UP) GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/lindar/ktd20xx.h b/board/lindar/ktd20xx.h new file mode 100644 index 0000000000..63e3bfb363 --- /dev/null +++ b/board/lindar/ktd20xx.h @@ -0,0 +1,141 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Public header for Kinetic 36-Channel RGB LED Drivers with I2C control, + * including KTD2061/58/59/60. + */ + +#ifndef __CROS_EC_DRIVER_RGB_LED_DRIVER_KTD20XX_PUBLIC_H +#define __CROS_EC_DRIVER_RGB_LED_DRIVER_KTD20XX_PUBLIC_H + +/* + * KTD20xx Register Definition + * + * Reg0x00: ID Data Register + * skip... + * Reg0x01: MONITOR Status Register + * skip... + * Reg0x02: CONTROL Configuration Register + * BIT7:6 is EN_MODE[1:0] + * 00 = global off, 01 = Night mode, + * 10 = Normal mode, 11 = reset as default + * BIT5 is BrightExtendTM Enable + * 0 = disable/1 = enable + * BIT4:3 is CoolExtendTM Temperature Setting + * 00 = 135°C rising, 01 = 120°C + * 10 = 105°C, 11 = 90°C + * BIT2:0 is Fade Rate Exponential Time-Constant Setting + * 000 = 31ms, 001 = 63ms, 010 = 125ms, 011 = 250ms + * 100 = 500ms, 101 = 1s, 110 = 2s, 111 = 4s + * + * Reg0x03: IRED0 Color Configuration Register + * IRED_SET0[7:0] Red Current Setting 0 + * 0000 0000 = 0μA + * 0000 0001 = 125μA + * ... + * 0010 1000 = 5mA + * ... + * 1100 0000 = 24mA + * 1100 0001 = 24mA (reads back as 1100 0000) + * ... + * 1111 1111 = 24mA (reads back as 1100 0000) + * Reg0x04: IGRN0 Color Configuration Register + * IGRN_SET0[7:0] Green Current Setting 0 + * Reg0x05: IBLU0 Color Configuration Register + * IBLU_SET0[7:0] Blue Current Setting 0 + * Reg0x06: IRED1 Color Configuration Register + * IRED_SET1[7:0] Red Current Setting 1 + * Reg0x07: IGRN1 Color Configuration Register + * IGRN_SET1[7:0] Green Current Setting 1 + * Reg0x08: IBLU1 Color Configuration Register + * IBLU_SET1[7:0] Blue Current Setting 1 + * + * Reg0x09: ISELA12 Selection Configuration Register + * BIT7 is ENA1, Enable RGB with anode connected to LEDA1 pin + * 0 = use 0μA for these LEDs (includes fade to 0μA) + * 1 = use the settings selected by RGBA1_SEL[2:0] + * BIT6:4 is RGBA1_SEL[2:0] + * Current Selection for RGB with anode connected to LEDA1 pin + * 0XX = I LEDA3 selects IRED_SET0[7:0] + * 1XX = I LEDA3 selects IRED_SET1[7:0] + * X0X = I LEDA2 selects IGRN_SET0[7:0] + * X1X = I LEDA2 selects IGRN_SET1[7:0] + * XX0 = I LEDA4 selects IBLU_SET0[7:0] + * XX1 = I LEDA4 selects IBLU_SET1[7:0] + * BIT3 IS ENA2 + * 0 = use 0μA for these LEDs (includes fade to 0μA) + * 1 = use the settings selected by RGBA2_SEL[2:0] + * BIT2:0 is RGBA2_SEL[2:0] + * Current Selection for RGB with anode connected to LEDA2 pin + * 0XX = I LEDA4 selects IRED_SET0[7:0] + * 1XX = I LEDA4 selects IRED_SET1[7:0] + * X0X = I LEDA3 selects IGRN_SET0[7:0] + * X1X = I LEDA3 selects IGRN_SET1[7:0] + * XX0 = I LEDA1 selects IBLU_SET0[7:0] + * XX1 = I LEDA1 selects IBLU_SET1[7:0] + * Reg0x0A: ISELA34 Selection Configuration Register + * BIT7 is ENA3, Enable RGB with anode connected to LEDA3 pin + * 0 = use 0μA for these LEDs (includes fade to 0μA) + * 1 = use the settings selected by RGBA3_SEL[2:0] + * BIT6:4 is RGBA3_SEL[2:0] + * Current Selection for RGB with anode connected to LEDA3 pin + * 0XX = I LEDA1 selects IRED_SET0[7:0] + * 1XX = I LEDA1 selects IRED_SET1[7:0] + * X0X = I LEDA4 selects IGRN_SET0[7:0] + * X1X = I LEDA4 selects IGRN_SET1[7:0] + * XX0 = I LEDA2 selects IBLU_SET0[7:0] + * XX1 = I LEDA2 selects IBLU_SET1[7:0] + * BIT3 IS ENA4 + * 0 = use 0μA for these LEDs (includes fade to 0μA) + * 1 = use the settings selected by RGBA4_SEL[2:0] + * BIT2:0 is RGBA4_SEL[2:0] + * Current Selection for RGB with anode connected to LEDA4 pin + * 0XX = I LEDA2 selects IRED_SET0[7:0] + * 1XX = I LEDA2 selects IRED_SET1[7:0] + * X0X = I LEDA1 selects IGRN_SET0[7:0] + * X1X = I LEDA1 selects IGRN_SET1[7:0] + * XX0 = I LEDA3 selects IBLU_SET0[7:0] + * XX1 = I LEDA3 selects IBLU_SET1[7:0] + * Reg0x0B: ISELB12 Selection Configuration Register + * BIT7 is ENB1, Enable RGB with anode connected to LEDB1 pin + * 0 = use 0μA for these LEDs (includes fade to 0μA) + * 1 = use the settings selected by RGB1_SEL[2:0] + * BIT6:4 is RGBB1_SEL[2:0] + * Current Selection for RGB with anode connected to LEDB1 pin + * 0XX = I LEDB3 selects IRED_SET0[7:0] + * 1XX = I LEDB3 selects IRED_SET1[7:0] + * X0X = I LEDB2 selects IGRN_SET0[7:0] + * X1X = I LEDB2 selects IGRN_SET1[7:0] + * XX0 = I LEDB4 selects IBLU_SET0[7:0] + * XX1 = I LEDB4 selects IBLU_SET1[7:0] + * BIT3 IS ENB2 + * ... + * Reg0x0C: ISELB34 Selection Configuration Register + * ... + * Reg0x0D: ISELC12 Selection Configuration Register + * ... + * Reg0x0E: ISELC34 Selection Configuration Register + * ... + */ + +enum ktd20xx_register { + KTD20XX_ID_DATA = 0x00, + KTD20XX_STATUS_REG = 0x01, + KTD20XX_CTRL_CFG = 0x02, + KTD20XX_IRED_SET0 = 0x03, + KTD20XX_IGRN_SET0 = 0x04, + KTD20XX_IBLU_SET0 = 0x05, + KTD20XX_IRED_SET1 = 0x06, + KTD20XX_IGRN_SET1 = 0x07, + KTD20XX_IBLU_SET1 = 0x08, + KTD20XX_ISEL_A12 = 0x09, + KTD20XX_ISEL_A34 = 0x0A, + KTD20XX_ISEL_B12 = 0x0B, + KTD20XX_ISEL_B34 = 0x0C, + KTD20XX_ISEL_C12 = 0x0D, + KTD20XX_ISEL_C34 = 0x0E, + KTD20XX_TOTOAL_REG +}; + +#endif /* __CROS_EC_DRIVER_RGB_LED_DRIVER_KTD20XX_PUBLIC_H */ diff --git a/board/lindar/led.c b/board/lindar/led.c index 6f4e781404..9ad7b48fb2 100644 --- a/board/lindar/led.c +++ b/board/lindar/led.c @@ -1,52 +1,75 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Malefor */ +#include "cbi_ssfc.h" +#include "charge_state.h" #include "common.h" -#include "led_onoff_states.h" -#include "led_common.h" +#include "cros_board_info.h" +#include "extpower.h" #include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "ktd20xx.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "lid_switch.h" +#include "stdbool.h" +#include "task.h" +#include "timer.h" +#include "util.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) -const int led_charge_lvl_1 = 5; +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_2 = 97; +__override const int led_charge_lvl_1 = 5; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; +__override const int led_charge_lvl_2 = 97; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); @@ -55,17 +78,17 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_LED_3_L, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { - case EC_LED_COLOR_RED: - gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); - gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); - break; case EC_LED_COLOR_AMBER: gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); break; + case EC_LED_COLOR_RED: + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + break; case EC_LED_COLOR_GREEN: gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); @@ -108,3 +131,631 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } + +static const uint16_t ktd2061_i2c_addr = 0x68; +static void controller_write(uint8_t reg, uint8_t val) +{ + uint8_t buf[2]; + + buf[0] = reg; + buf[1] = val; + + i2c_xfer_unlocked(I2C_PORT_LIGHTBAR, ktd2061_i2c_addr, buf, 2, 0, 0, + I2C_XFER_SINGLE); +} + +enum lightbar_states { + LB_STATE_OFF, + LB_STATE_LID_CLOSE, + LB_STATE_SLEEP_AC_ONLY, + LB_STATE_SLEEP_AC_BAT_LOW, + LB_STATE_SLEEP_AC_BAT_LV1, + LB_STATE_SLEEP_AC_BAT_LV2, + LB_STATE_SLEEP_AC_BAT_LV3, + LB_STATE_SLEEP_AC_BAT_LV4, + LB_STATE_SLEEP_BAT_LOW, + LB_STATE_SLEEP_BAT_ONLY, + LB_STATE_S0_AC_ONLY, + LB_STATE_S0_BAT_LOW, + LB_STATE_S0_BAT_LV1, + LB_STATE_S0_BAT_LV2, + LB_STATE_S0_BAT_LV3, + LB_STATE_S0_BAT_LV4, + LB_NUM_STATES +}; + +/* + * All lightbar states should have one phase defined, + * and an additional phase can be defined for blinking + */ +enum lightbar_phase { + LIGHTBAR_PHASE_0 = 0, + LIGHTBAR_PHASE_1 = 1, + LIGHTBAR_NUM_PHASES +}; + +enum ec_lightbar_colors { + BAR_RESET, + BAR_OFF, + BAR_COLOR_ORG_20_PERCENT, + BAR_COLOR_GRN_40_PERCENT, + BAR_COLOR_GRN_60_PERCENT, + BAR_COLOR_GRN_80_PERCENT, + BAR_COLOR_GRN_FULL, + BAR_COLOR_ORG_FULL, + LIGHTBAR_COLOR_TOTAL +}; + +struct lightbar_descriptor { + enum ec_lightbar_colors color; + uint8_t ticks; +}; + +#define BAR_INFINITE UINT8_MAX +#define LIGHTBAR_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +#define LIGHTBAR_COUNT_FOR_RESUME_FROM_SLEEP (3 * LIGHTBAR_ONE_SEC) +int lightbar_resume_tick; + +const struct lightbar_descriptor lb_table[LB_NUM_STATES][LIGHTBAR_NUM_PHASES] = { + [LB_STATE_OFF] = { { BAR_OFF, BAR_INFINITE } }, + [LB_STATE_LID_CLOSE] = { { BAR_OFF, BAR_INFINITE } }, + [LB_STATE_SLEEP_AC_ONLY] = { { BAR_OFF, BAR_INFINITE } }, + [LB_STATE_SLEEP_AC_BAT_LOW] = { { BAR_COLOR_ORG_20_PERCENT, + BAR_INFINITE } }, + [LB_STATE_SLEEP_AC_BAT_LV1] = { { BAR_COLOR_GRN_40_PERCENT, + BAR_INFINITE } }, + [LB_STATE_SLEEP_AC_BAT_LV2] = { { BAR_COLOR_GRN_60_PERCENT, + BAR_INFINITE } }, + [LB_STATE_SLEEP_AC_BAT_LV3] = { { BAR_COLOR_GRN_80_PERCENT, + BAR_INFINITE } }, + [LB_STATE_SLEEP_AC_BAT_LV4] = { { BAR_COLOR_GRN_FULL, BAR_INFINITE } }, + [LB_STATE_SLEEP_BAT_LOW] = { { BAR_OFF, 5 * LIGHTBAR_ONE_SEC }, + { BAR_COLOR_ORG_FULL, LIGHTBAR_ONE_SEC } }, + [LB_STATE_SLEEP_BAT_ONLY] = { { BAR_OFF, BAR_INFINITE } }, + [LB_STATE_S0_AC_ONLY] = { { BAR_OFF, BAR_INFINITE } }, + [LB_STATE_S0_BAT_LOW] = { { BAR_COLOR_ORG_20_PERCENT, BAR_INFINITE } }, + [LB_STATE_S0_BAT_LV1] = { { BAR_COLOR_GRN_40_PERCENT, BAR_INFINITE } }, + [LB_STATE_S0_BAT_LV2] = { { BAR_COLOR_GRN_60_PERCENT, BAR_INFINITE } }, + [LB_STATE_S0_BAT_LV3] = { { BAR_COLOR_GRN_80_PERCENT, BAR_INFINITE } }, + [LB_STATE_S0_BAT_LV4] = { { BAR_COLOR_GRN_FULL, BAR_INFINITE } }, +}; + +#define DISABLE_LIGHTBAR 0x00 +#define ENABLE_LIGHTBAR 0x80 +#define I_OFF 0x00 +#define GRN_I_ON 0x1E +#define ORG_I_ON 0x28 +#define SEL_OFF 0x00 +#define SEL_1ST_LED BIT(7) +#define SEL_2ND_LED BIT(3) +#define SEL_BOTH (SEL_1ST_LED | SEL_2ND_LED) +#define SKU_ID_NONE 0x00 +#define SKU_ID_INVALID 0x01 +#define LB_SUPPORTED_SKUID_LOWER 458700 +#define LB_SUPPORTED_SKUID_UPPER 458800 + +static bool lightbar_is_supported(void) +{ + static uint32_t skuid = SKU_ID_NONE; + bool result; + + /* lindar add SSFC tag to cbi image from "board_id = 3". */ + if (get_board_id() >= 3) { + if (get_cbi_ssfc_lightbar() == SSFC_LIGHTBAR_NONE) + return false; + return true; + } + + if (skuid == SKU_ID_NONE) { + if (cbi_get_sku_id(&skuid)) { + CPRINTS("Cannot get skuid for lightbar supported"); + skuid = SKU_ID_INVALID; + } + } + + /* + * If board_id = 1 or 2, it needs to check sku_id to know + * if system support lightbar or not. + */ + if (skuid >= LB_SUPPORTED_SKUID_LOWER && + skuid <= LB_SUPPORTED_SKUID_UPPER) + result = true; + else + result = false; + + return result; +} + +/* + * lightbar_enter_s0ix_s3: + * This flag is used to know if system ever enter S0ix/S3. + * Lightbar V9 SPEC define lightbar resuming behavior, "S0ix/S3 -> S0", + * but not include "G3/S5/S4 -> S0". "G3/S5/S4 -> S0" need to keep off. + */ +static bool lightbar_enter_s0ix_s3; + +/* + * lightbar_auto_control: + * We need some command for testing lightbar in factory. + * So, create this flag to stop regular action in lightbar_update(). + * + * lightbar_demo_state: + * It's used for testing lightbar via executing command under + * console. + */ +static bool lightbar_auto_control; +static enum lightbar_states lightbar_demo_state; + +static void lightbar_set_auto_control(bool state) +{ + lightbar_auto_control = state; +} + +static bool lightbar_is_auto_control(void) +{ + return lightbar_auto_control; +} + +static void lightbar_set_demo_state(enum lightbar_states tmp_state) +{ + if (tmp_state >= LB_NUM_STATES || tmp_state < LB_STATE_OFF) { + lightbar_demo_state = LB_NUM_STATES; + lightbar_resume_tick = 0; + } else { + lightbar_demo_state = tmp_state; + + if (lightbar_demo_state >= LB_STATE_S0_AC_ONLY) + lightbar_resume_tick = + LIGHTBAR_COUNT_FOR_RESUME_FROM_SLEEP; + } + ccprintf("lightbar_demo_state = %d; lightbar_resume_tick %d.\n", + lightbar_demo_state, lightbar_resume_tick); +} + +static enum lightbar_states lightbar_get_demo_state(void) +{ + /* + * Once tick count to zero, it needs to return LB_STATE_OFF to + * simulate lightbar off. + */ + if ((lightbar_demo_state != LB_NUM_STATES) && + (lightbar_demo_state >= LB_STATE_S0_AC_ONLY) && + (lightbar_resume_tick == 0)) + return LB_STATE_OFF; + + return lightbar_demo_state; +} + +static bool lightbar_is_enabled(void) +{ + if (!lightbar_is_supported()) + return false; + + /* + * Lightbar's I2C is powered by PP3300_A, and its power will be turn + * when system enter S4/S5. It may get I2C error if EC keep polling + * lightbar. We should stop it when EC doesn't turn on PP330_A. + */ + if (!board_is_i2c_port_powered(I2C_PORT_LIGHTBAR)) + return false; + + return true; +} + +/* + * From "board_id = 3", HW change lightbar circuit, and it only support + * two colors, orange (amber) and green. It connects KTD20xx's red-channel + * green color led, and green-channel to orange color led. + * Blue-channel is unused. + * + * The configuration format of lightbar_xx_led_cfg's is as below. + * ID_DAT, STATUS_REG, CTRL_CFG + * IRED_SET0, IGRN_SET0, IBLU_SET0, IRED_SET1, IGRN_SET1, IBLU_SET1 + * ISEL_A12, ISEL_A34, ISEL_B12, ISEL_B34, ISEL_C12, ISEL_C34 + */ +const uint8_t lightbar_10_led_cfg[LIGHTBAR_COLOR_TOTAL][KTD20XX_TOTOAL_REG] = { + [BAR_RESET] = { 0x00, 0x00, DISABLE_LIGHTBAR, I_OFF, I_OFF, I_OFF, + I_OFF, I_OFF, I_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, + SEL_OFF, SEL_OFF }, + [BAR_OFF] = { 0x00, 0x00, DISABLE_LIGHTBAR, I_OFF, I_OFF, I_OFF, I_OFF, + I_OFF, I_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, + SEL_OFF }, + [BAR_COLOR_ORG_20_PERCENT] = { 0x00, 0x00, ENABLE_LIGHTBAR, I_OFF, + ORG_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, + SEL_OFF, SEL_BOTH, SEL_OFF, SEL_OFF, + SEL_OFF, SEL_OFF }, + [BAR_COLOR_GRN_40_PERCENT] = { 0x00, 0x00, ENABLE_LIGHTBAR, GRN_I_ON, + I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, + SEL_BOTH, SEL_BOTH, SEL_OFF, SEL_OFF, + SEL_OFF, SEL_OFF }, + [BAR_COLOR_GRN_60_PERCENT] = { 0x00, 0x00, ENABLE_LIGHTBAR, GRN_I_ON, + I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, + SEL_BOTH, SEL_BOTH, SEL_OFF, SEL_BOTH, + SEL_OFF, SEL_OFF }, + [BAR_COLOR_GRN_80_PERCENT] = { 0x00, 0x00, ENABLE_LIGHTBAR, GRN_I_ON, + I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, + SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, + SEL_OFF, SEL_OFF }, + [BAR_COLOR_GRN_FULL] = { 0x00, 0x00, ENABLE_LIGHTBAR, GRN_I_ON, I_OFF, + I_OFF, I_OFF, I_OFF, I_OFF, SEL_BOTH, SEL_BOTH, + SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_OFF }, + [BAR_COLOR_ORG_FULL] = { 0x00, 0x00, ENABLE_LIGHTBAR, I_OFF, ORG_I_ON, + I_OFF, I_OFF, I_OFF, I_OFF, SEL_BOTH, SEL_BOTH, + SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_OFF } +}; + +const uint8_t lightbar_12_led_cfg[LIGHTBAR_COLOR_TOTAL][KTD20XX_TOTOAL_REG] = { + [BAR_RESET] = { 0x00, 0x00, DISABLE_LIGHTBAR, I_OFF, I_OFF, I_OFF, + I_OFF, I_OFF, I_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, + SEL_OFF, SEL_OFF }, + [BAR_OFF] = { 0x00, 0x00, DISABLE_LIGHTBAR, I_OFF, I_OFF, I_OFF, I_OFF, + I_OFF, I_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, + SEL_OFF }, + [BAR_COLOR_ORG_20_PERCENT] = { 0x00, 0x00, ENABLE_LIGHTBAR, I_OFF, + ORG_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, + SEL_2ND_LED, SEL_BOTH, SEL_OFF, SEL_OFF, + SEL_OFF, SEL_OFF }, + [BAR_COLOR_GRN_40_PERCENT] = { 0x00, 0x00, ENABLE_LIGHTBAR, GRN_I_ON, + I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, + SEL_BOTH, SEL_BOTH, SEL_OFF, SEL_2ND_LED, + SEL_OFF, SEL_OFF }, + [BAR_COLOR_GRN_60_PERCENT] = { 0x00, 0x00, ENABLE_LIGHTBAR, GRN_I_ON, + I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, + SEL_BOTH, SEL_BOTH, SEL_2ND_LED, + SEL_BOTH, SEL_OFF, SEL_OFF }, + [BAR_COLOR_GRN_80_PERCENT] = { 0x00, 0x00, ENABLE_LIGHTBAR, GRN_I_ON, + I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, + SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, + SEL_OFF, SEL_2ND_LED }, + [BAR_COLOR_GRN_FULL] = { 0x00, 0x00, ENABLE_LIGHTBAR, GRN_I_ON, I_OFF, + I_OFF, I_OFF, I_OFF, I_OFF, SEL_BOTH, SEL_BOTH, + SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH }, + [BAR_COLOR_ORG_FULL] = { 0x00, 0x00, ENABLE_LIGHTBAR, I_OFF, ORG_I_ON, + I_OFF, I_OFF, I_OFF, I_OFF, SEL_BOTH, SEL_BOTH, + SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH } +}; + +/* + * lightbar_ctrl is a pointer to 2-dimension lightbar configuration. It's used + * to base on DUT type to load different cfg. + * Default is lightbar_10_led_cfg. + */ +const uint8_t (*lightbar_ctrl)[KTD20XX_TOTOAL_REG] = lightbar_10_led_cfg; + +static void lightbar_set_color(enum ec_lightbar_colors color) +{ + enum ktd20xx_register i; + + if (color >= LIGHTBAR_COLOR_TOTAL) { + CPRINTS("Lightbar Error! Incorrect lightbard color %d", color); + color = BAR_RESET; + } + + i2c_lock(I2C_PORT_LIGHTBAR, 1); + for (i = KTD20XX_IRED_SET0; i <= KTD20XX_ISEL_C34; i++) + controller_write(i, lightbar_ctrl[color][i]); + + controller_write(KTD20XX_CTRL_CFG, + lightbar_ctrl[color][KTD20XX_CTRL_CFG]); + + i2c_lock(I2C_PORT_LIGHTBAR, 0); +} + +static void lightbar_init(void) +{ + if (!lightbar_is_enabled()) + return; + + if (get_cbi_ssfc_lightbar() == SSFC_LIGHTBAR_12_LED) + lightbar_ctrl = lightbar_12_led_cfg; + else + lightbar_ctrl = lightbar_10_led_cfg; + + /* Clear this flag if system doesn't enter S0ix/S3 */ + lightbar_enter_s0ix_s3 = false; + lightbar_resume_tick = 0; + + lightbar_set_color(BAR_RESET); +} + +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, lightbar_init, HOOK_PRIO_DEFAULT); + +static void lightbar_sleep_entry(void) +{ + if (!lightbar_is_enabled()) + return; + + lightbar_set_auto_control(true); + /* + * Set this flag, then EC'll base on it to set resume tick after + * S0ix/S3 exit. + */ + lightbar_enter_s0ix_s3 = true; + lightbar_resume_tick = 0; + + lightbar_set_color(BAR_RESET); +} + +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, lightbar_sleep_entry, HOOK_PRIO_DEFAULT); + +static void lightbar_sleep_exit(void) +{ + if (!lightbar_is_enabled()) + return; + + lightbar_set_auto_control(true); + if (lightbar_enter_s0ix_s3) + lightbar_resume_tick = LIGHTBAR_COUNT_FOR_RESUME_FROM_SLEEP; + else + lightbar_resume_tick = 0; + lightbar_enter_s0ix_s3 = false; +} + +DECLARE_HOOK(HOOK_CHIPSET_RESUME, lightbar_sleep_exit, HOOK_PRIO_DEFAULT); + +#define LB_BAT_THRESHOLD_1 16 +#define LB_BAT_THRESHOLD_2 40 +#define LB_BAT_THRESHOLD_3 60 +#define LB_BAT_THRESHOLD_4 80 + +static enum lightbar_states lightbar_get_state(void) +{ + enum lightbar_states new_state = LB_NUM_STATES; + int cur_bat_percent; + + cur_bat_percent = charge_get_percent(); + + if (!lid_is_open()) + return LB_STATE_LID_CLOSE; + + if (lightbar_resume_tick) { + if ((battery_is_present() == BP_YES) && + charge_get_display_charge()) { + if (cur_bat_percent < LB_BAT_THRESHOLD_1) + new_state = LB_STATE_S0_BAT_LOW; + else if (cur_bat_percent < LB_BAT_THRESHOLD_2) + new_state = LB_STATE_S0_BAT_LV1; + else if (cur_bat_percent < LB_BAT_THRESHOLD_3) + new_state = LB_STATE_S0_BAT_LV2; + else if (cur_bat_percent < LB_BAT_THRESHOLD_4) + new_state = LB_STATE_S0_BAT_LV3; + else + new_state = LB_STATE_S0_BAT_LV4; + } else + new_state = LB_STATE_S0_AC_ONLY; + return new_state; + } + + if (!chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return LB_STATE_OFF; + + if (extpower_is_present()) { + if ((battery_is_present() == BP_YES) && + charge_get_display_charge()) { + if (cur_bat_percent < LB_BAT_THRESHOLD_1) + new_state = LB_STATE_SLEEP_AC_BAT_LOW; + else if (cur_bat_percent < LB_BAT_THRESHOLD_2) + new_state = LB_STATE_SLEEP_AC_BAT_LV1; + else if (cur_bat_percent < LB_BAT_THRESHOLD_3) + new_state = LB_STATE_SLEEP_AC_BAT_LV2; + else if (cur_bat_percent < LB_BAT_THRESHOLD_4) + new_state = LB_STATE_SLEEP_AC_BAT_LV3; + else + new_state = LB_STATE_SLEEP_AC_BAT_LV4; + } else + new_state = LB_STATE_SLEEP_AC_ONLY; + } else { + if (cur_bat_percent < LB_BAT_THRESHOLD_1) + new_state = LB_STATE_SLEEP_BAT_LOW; + else + new_state = LB_STATE_SLEEP_BAT_ONLY; + } + + return new_state; +} + +#define LIGHTBAR_DEBOUNCE_TICKS 1 +static void lightbar_update(void) +{ + static uint8_t ticks, period; + static enum lightbar_states lb_cur_state = LB_NUM_STATES; + static int debounce_lightbar_state_update; + enum lightbar_states desired_state; + int phase; + + if (!lightbar_is_enabled()) + return; + + if (lightbar_is_auto_control()) + desired_state = lightbar_get_state(); + else { + desired_state = lightbar_get_demo_state(); + /* + * Stop to update lb_cur_state if desired_state is equal to + * LB_NUM_STATES. + */ + if (desired_state == LB_NUM_STATES) + return; + } + + if (lightbar_resume_tick) + lightbar_resume_tick--; + + if (desired_state != lb_cur_state && desired_state < LB_NUM_STATES) { + /* State is changing */ + lb_cur_state = desired_state; + /* Reset ticks and period when state changes */ + ticks = 0; + + period = lb_table[lb_cur_state][LIGHTBAR_PHASE_0].ticks + + lb_table[lb_cur_state][LIGHTBAR_PHASE_1].ticks; + + /* + * System will be waken up when AC status change in S0ix. Due to + * EC may be late to update chipset state and cause lightbar + * flash a while when system transfer to S0. We add to debounce + * for any lightbar status change. + * It can make sure lightbar state is ready to to update. + */ + debounce_lightbar_state_update = LIGHTBAR_DEBOUNCE_TICKS; + } + + /* If this state is undefined, turn lightbar off */ + if (period == 0) { + CPRINTS("Undefined lightbar behavior for lightbar state %d," + "turning off lightbar", + lb_cur_state); + lightbar_set_color(BAR_OFF); + return; + } + + if (debounce_lightbar_state_update != 0) { + debounce_lightbar_state_update--; + return; + } + + /* + * Determine which phase of the state table to use. The phase is + * determined if it falls within first phase time duration. + */ + phase = ticks < lb_table[lb_cur_state][LIGHTBAR_PHASE_0].ticks ? 0 : 1; + ticks = (ticks + 1) % period; + + /* Set the color for the given state and phase */ + lightbar_set_color(lb_table[lb_cur_state][phase].color); +} + +DECLARE_HOOK(HOOK_TICK, lightbar_update, HOOK_PRIO_DEFAULT); + +/****************************************************************************/ +/* EC console commands for lightbar */ +/****************************************************************************/ +static void lightbar_dump_status(void) +{ + uint32_t cbi_bid, cbi_skuid; + int cbi_ssfc_lightbar; + + ccprintf("lightbar is %ssupported, %sabled, auto_control: %sabled\n", + lightbar_is_supported() ? "" : "un-", + lightbar_is_enabled() ? "en" : "dis", + lightbar_is_auto_control() ? "en" : "dis"); + + cbi_bid = get_board_id(); + cbi_get_sku_id(&cbi_skuid); + cbi_ssfc_lightbar = get_cbi_ssfc_lightbar(); + ccprintf("board id = %d, skuid = %d, ssfc_lightbar = %d\n", cbi_bid, + cbi_skuid, cbi_ssfc_lightbar); +} + +#ifdef CONFIG_CONSOLE_CMDHELP +static int help(const char *cmd) +{ + ccprintf("Usage:\n"); + ccprintf(" %s - dump lightbar status\n", cmd); + ccprintf(" %s on - set on lightbar auto control\n", + cmd); + ccprintf(" %s off - set off lightbar auto control\n", + cmd); + ccprintf(" %s demo [%x - %x] - demo lightbar state\n", cmd, + LB_STATE_OFF, (LB_NUM_STATES - 1)); + return EC_SUCCESS; +} +#endif + +static int command_lightbar(int argc, const char **argv) +{ + /* no args = dump lightbar status */ + if (argc == 1) { + lightbar_dump_status(); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[1], "help")) { +#ifdef CONFIG_CONSOLE_CMDHELP + help(argv[0]); +#endif + return EC_SUCCESS; + } + + if (!lightbar_is_enabled()) { + lightbar_dump_status(); + return EC_ERROR_UNIMPLEMENTED; + } + + if (!strcasecmp(argv[1], "on")) { + lightbar_set_auto_control(true); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[1], "off")) { + lightbar_set_auto_control(false); + lightbar_set_demo_state(LB_NUM_STATES); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[1], "demo")) { + int lb_demo_state; + char *e; + + /* Need to disable auto_control before demo */ + if (lightbar_is_auto_control()) { + ccprintf("Please set off auto control before demo.\n"); + return EC_ERROR_ACCESS_DENIED; + } + + lb_demo_state = 0xff & strtoi(argv[2], &e, 16); + lightbar_set_demo_state(lb_demo_state); + return EC_SUCCESS; + } + +#ifdef CONFIG_CONSOLE_CMDHELP + help(argv[0]); +#endif + + return EC_ERROR_INVAL; +} + +DECLARE_CONSOLE_COMMAND(lightbar, command_lightbar, "[help | on | off | demo]", + "get/set lightbar status"); + +/****************************************************************************/ +/* EC host commands (ectool) for lightbar */ +/****************************************************************************/ +static enum ec_status lpc_cmd_lightbar(struct host_cmd_handler_args *args) +{ + const struct ec_params_lightbar *in = args->params; + int lb_demo_state; + + /* + * HOST_CMD is binded with ectool. From ectool.c, it already define + * command format. + * We only base on "off", "on", and "seq" to do what we can do + * now. + * Originally, I expect to use "demo", but it limit "in->demo.num" + * within 0~1. So, adopt "seq" command for basic testing. + */ + switch (in->cmd) { + case LIGHTBAR_CMD_OFF: + lightbar_set_auto_control(false); + lightbar_set_demo_state(LB_NUM_STATES); + break; + case LIGHTBAR_CMD_ON: + lightbar_set_auto_control(true); + break; + case LIGHTBAR_CMD_SEQ: + lb_demo_state = in->seq.num; + if (lightbar_is_auto_control()) { + CPRINTS("Please set off auto control before demo."); + return EC_RES_ACCESS_DENIED; + } + lightbar_set_demo_state(lb_demo_state); + break; + default: + CPRINTS("LB bad cmd 0x%x", in->cmd); + return EC_RES_INVALID_PARAM; + } + + return EC_RES_SUCCESS; +} + +DECLARE_HOST_COMMAND(EC_CMD_LIGHTBAR_CMD, lpc_cmd_lightbar, EC_VER_MASK(0)); diff --git a/board/lindar/vif_override.xml b/board/lindar/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/lindar/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/lingcod/battery.c b/board/lingcod/battery.c deleted file mode 100644 index 7f37c6fe10..0000000000 --- a/board/lingcod/battery.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery_fuel_gauge.h" -#include "common.h" -#include "util.h" - -/* - * Battery info for all Volteer battery types. Note that the fields - * start_charging_min/max and charging_min/max are not used for the charger. - * The effective temperature limits are given by discharging_min/max_c. - * - * Fuel Gauge (FG) parameters which are used for determining if the battery - * is connected, the appropriate ship mode (battery cutoff) command, and the - * charge/discharge FETs status. - * - * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery - * register. For some batteries, the charge/discharge FET bits are set when - * charging/discharging is active, in other types, these bits set mean that - * charging/discharging is disabled. Therefore, in addition to the mask for - * these bits, a disconnect value must be specified. Note that for TI fuel - * gauge, the charge/discharge FET status is found in Operation Status (0x54), - * but a read of Manufacturer Access (0x00) will return the lower 16 bits of - * Operation status which contains the FET status bits. - * - * The assumption for battery types supported is that the charge/discharge FET - * status can be read with a sb_read() command and therefore, only the register - * address, mask, and disconnect value need to be provided. - */ -const struct board_batt_params board_battery_info[] = { - [BATTERY_SMP] = { - .fuel_gauge = { - .manuf_name = "SMP", - .device_name = "L19M4PG2", - .ship_mode = { - .reg_addr = 0x34, - .reg_data = { 0x0000, 0x1000 }, - }, - .fet = { - .reg_addr = 0x34, - .reg_mask = 0x0100, - .disconnect_val = 0x0100, - } - }, - .batt_info = { - .voltage_max = 8800, /* mV */ - .voltage_normal = 7680, /* mV */ - .voltage_min = 6000, /* mV */ - .precharge_current = 332, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, - }, - [BATTERY_LGC] = { - .fuel_gauge = { - .manuf_name = "LGC", - .device_name = "L19L4PG2", - .ship_mode = { - .reg_addr = 0x34, - .reg_data = { 0x0000, 0x1000 }, - }, - .fet = { - .reg_addr = 0x34, - .reg_mask = 0x0100, - .disconnect_val = 0x0100, - } - }, - .batt_info = { - .voltage_max = 8800, /* mV */ - .voltage_normal = 7700, /* mV */ - /* - * voltage min value and precharge current value are - * specified by LGC directly and not shown in the SPEC. - */ - .voltage_min = 6000, /* mV */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 73, - }, - }, - [BATTERY_SUNWODA] = { - .fuel_gauge = { - .manuf_name = "SUNWODA", - .device_name = "L19D4PG2", - .ship_mode = { - .reg_addr = 0x34, - .reg_data = { 0x0000, 0x1000 }, - }, - .fet = { - .reg_addr = 0x34, - .reg_mask = 0x0100, - .disconnect_val = 0x0100, - } - }, - .batt_info = { - .voltage_max = 8800, /* mV */ - .voltage_normal = 7680, /* mV */ - .voltage_min = 6000, /* mV */ - .precharge_current = 333, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); - -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP; diff --git a/board/lingcod/board.c b/board/lingcod/board.c deleted file mode 100644 index 28edcce5ae..0000000000 --- a/board/lingcod/board.c +++ /dev/null @@ -1,545 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Malefor board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "cbi_ec_fw_config.h" -#include "common.h" -#include "driver/accel_lis2dh.h" -#include "driver/accelgyro_lsm6dsm.h" -#include "driver/bc12/pi3usb9201.h" -#include "driver/ppc/sn5s330.h" -#include "driver/ppc/syv682x.h" -#include "driver/tcpm/tcpci.h" -#include "driver/tcpm/tusb422.h" -#include "driver/sync.h" -#include "extpower.h" -#include "fan.h" -#include "fan_chip.h" -#include "gpio.h" -#include "hooks.h" -#include "keyboard_scan.h" -#include "lid_switch.h" -#include "power.h" -#include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "tablet_mode.h" -#include "uart.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "usbc_ppc.h" -#include "util.h" - -#include "gpio_list.h" /* Must come after other header files. */ - -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { - /* Increase from 50 us, because KSO_02 passes through the H1. */ - .output_settle_us = 80, - /* Other values should be the same as the default configuration. */ - .debounce_down_us = 9 * MSEC, - .debounce_up_us = 30 * MSEC, - .scan_period_us = 3 * MSEC, - .min_post_scan_delay_us = 1000, - .poll_timeout_us = 100 * MSEC, - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ - }, -}; - -/******************************************************************************/ -/* - * FW_CONFIG defaults for Malefor if the CBI data is not initialized. - */ -union volteer_cbi_fw_config fw_config_defaults = { - .usb_db = DB_USB3_NO_A, -}; - -static void board_init(void) -{ - if (ec_cfg_has_tabletmode()) { - /* Enable gpio interrupt for base accelgyro sensor */ - gpio_enable_interrupt(GPIO_EC_IMU_INT_L); - } else { - motion_sensor_count = 0; - /* Device is clamshell only */ - tablet_set_mode(0); - /* Gyro is not present, don't allow line to float */ - gpio_set_flags(GPIO_EC_IMU_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); - } - - /* - * TODO: b/154447182 - Malefor will control power LED and battery LED - * independently, and keep the max brightness of power LED and battery - * LED as 50%. - */ - pwm_enable(PWM_CH_LED4_SIDESEL, 1); - pwm_set_duty(PWM_CH_LED4_SIDESEL, 50); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -int board_is_lid_angle_tablet_mode(void) -{ - return ec_cfg_has_tabletmode(); -} - -/* Enable or disable input devices, based on tablet mode or chipset state */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - if (ec_cfg_has_tabletmode()) { - if (chipset_in_state(CHIPSET_STATE_ANY_OFF) || - tablet_get_mode()) - enable = 0; - keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif - -/******************************************************************************/ -/* Sensors */ -/* Lid and base Sensor mutex */ -static struct mutex g_lid_accel_mutex; -static struct mutex g_base_mutex; - -/* Lid and base accel private data */ -static struct stprivate_data g_lis2dh_data; -static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; - -/* Matrix to rotate lid and base sensor into standard reference frame */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -struct motion_sensor_t motion_sensors[] = { - [LID_ACCEL] = { - .name = "Lid Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LIS2DE, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &lis2dh_drv, - .mutex = &g_lid_accel_mutex, - .drv_data = &g_lis2dh_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = LIS2DH_ADDR1_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .min_frequency = LIS2DH_ODR_MIN_VAL, - .max_frequency = LIS2DH_ODR_MAX_VAL, - .default_range = 2, /* g, to support tablet mode */ - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - /* Sensor on in S3 */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - }, - }, - - [BASE_ACCEL] = { - .name = "Base Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LSM6DSM, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6dsm_drv, - .mutex = &g_base_mutex, - .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, - MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_EC_IMU_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .rot_standard_ref = &base_standard_ref, - .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ - .min_frequency = LSM6DSM_ODR_MIN_VAL, - .max_frequency = LSM6DSM_ODR_MAX_VAL, - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 13000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - /* Sensor on for angle detection */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, - }, - - [BASE_GYRO] = { - .name = "Base Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LSM6DSM, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6dsm_drv, - .mutex = &g_base_mutex, - .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, - MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_EC_IMU_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .default_range = 1000 | ROUND_UP_FLAG, /* dps */ - .rot_standard_ref = &base_standard_ref, - .min_frequency = LSM6DSM_ODR_MIN_VAL, - .max_frequency = LSM6DSM_ODR_MAX_VAL, - }, -}; -unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -/******************************************************************************/ -/* Physical fans. These are logically separate from pwm_channels. */ - -const struct fan_conf fan_conf_0 = { - .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ - .pgood_gpio = -1, - .enable_gpio = GPIO_EN_PP5000_FAN, -}; - -/* - * Fan specs from datasheet: - * Max speed 5900 rpm (+/- 7%), minimum duty cycle 30%. - * Minimum speed not specified by RPM. Set minimum RPM to max speed (with - * margin) x 30%. - * 5900 x 1.07 x 0.30 = 1894, round up to 1900 - */ -const struct fan_rpm fan_rpm_0 = { - .rpm_min = 1900, - .rpm_start = 1900, - .rpm_max = 5900, -}; - -const struct fan_t fans[FAN_CH_COUNT] = { - [FAN_CH_0] = { - .conf = &fan_conf_0, - .rpm = &fan_rpm_0, - }, -}; - -/******************************************************************************/ -/* EC thermal management configuration */ - -/* - * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at - * 130 C. However, sensor is located next to DDR, so we need to use the lower - * DDR temperature limit (85 C) - */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; - -/* - * Inductor limits - used for both charger and PP3300 regulator - * - * Need to use the lower of the charger IC, PP3300 regulator, and the inductors - * - * Charger max recommended temperature 100C, max absolute temperature 125C - * PP3300 regulator: operating range -40 C to 145 C - * - * Inductors: limit of 125c - * PCB: limit is 80c - */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - - -struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, -}; -BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); - -/******************************************************************************/ -/* MFT channels. These are logically separate from pwm_channels. */ -const struct mft_t mft_channels[] = { - [MFT_CH_0] = { - .module = NPCX_MFT_MODULE_1, - .clk_src = TCKC_LFCLK, - .pwm_id = PWM_CH_FAN, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); - -/******************************************************************************/ -/* I2C port map configuration */ -const struct i2c_port_t i2c_ports[] = { - { - .name = "sensor", - .port = I2C_PORT_SENSOR, - .kbps = 400, - .scl = GPIO_EC_I2C0_SENSOR_SCL, - .sda = GPIO_EC_I2C0_SENSOR_SDA, - }, - { - .name = "usb_c0", - .port = I2C_PORT_USB_C0, - .kbps = 1000, - .scl = GPIO_EC_I2C1_USB_C0_SCL, - .sda = GPIO_EC_I2C1_USB_C0_SDA, - }, - { - .name = "usb_c1", - .port = I2C_PORT_USB_C1, - .kbps = 1000, - .scl = GPIO_EC_I2C2_USB_C1_SCL, - .sda = GPIO_EC_I2C2_USB_C1_SDA, - }, - { - .name = "usb_1_mix", - .port = I2C_PORT_USB_1_MIX, - .kbps = 100, - .scl = GPIO_EC_I2C3_USB_1_MIX_SCL, - .sda = GPIO_EC_I2C3_USB_1_MIX_SDA, - }, - { - .name = "power", - .port = I2C_PORT_POWER, - .kbps = 100, - .scl = GPIO_EC_I2C5_POWER_SCL, - .sda = GPIO_EC_I2C5_POWER_SDA, - }, - { - .name = "eeprom", - .port = I2C_PORT_EEPROM, - .kbps = 400, - .scl = GPIO_EC_I2C7_EEPROM_SCL, - .sda = GPIO_EC_I2C7_EEPROM_SDA, - }, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/******************************************************************************/ -/* PWM configuration */ -const struct pwm_t pwm_channels[] = { - [PWM_CH_LED4_SIDESEL] = { - .channel = 7, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - /* Run at a higher frequency than the color PWM signals to avoid - * timing-based color shifts. - */ - .freq = 4800, - }, - [PWM_CH_FAN] = { - .channel = 5, - .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000 - }, - [PWM_CH_KBLIGHT] = { - .channel = 3, - .flags = 0, - /* - * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent - * flicker. Higher frequencies consume similar average power to - * lower PWM frequencies, but higher frequencies record a much - * lower maximum power. - */ - .freq = 2400, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -void board_reset_pd_mcu(void) -{ - /* TODO(b/159024035): Malefor: check USB PD reset operation */ -} - -__override void board_cbi_init(void) -{ - /* TODO(b/159024035): Malefor: check FW_CONFIG fields for USB DB type */ -} - -/******************************************************************************/ -/* USBC PPC configuration */ -struct ppc_config_t ppc_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -/******************************************************************************/ -/* PPC support routines */ -void ppc_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_PPC_INT_ODL: - sn5s330_interrupt(USBC_PORT_C0); - break; - case GPIO_USB_C1_PPC_INT_ODL: - syv682x_interrupt(USBC_PORT_C1); - default: - break; - } -} - -/******************************************************************************/ -/* BC1.2 charger detect configuration */ -const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC TCPC configuration */ -struct tcpc_config_t tcpc_config[] = { - [USBC_PORT_C0] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C0, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), - }, - [USBC_PORT_C1] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); -BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usb_muxes[] = { - [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); - -struct bb_usb_control bb_controls[] = { - [USBC_PORT_C0] = { - /* USB-C port 0 doesn't have a retimer */ - }, - [USBC_PORT_C1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); - -static void board_tcpc_init(void) -{ - /* Don't reset TCPCs after initial reset */ - if (!system_jumped_late()) - board_reset_pd_mcu(); - - /* Enable PPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); - - /* Enable TCPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); - - /* Enable BC1.2 interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); - -/******************************************************************************/ -/* TCPC support routines */ -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - /* - * Check which port has the ALERT line set - */ - if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} - -int ppc_get_alert_status(int port) -{ - if (port == USBC_PORT_C0) - return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; - else - return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; -} diff --git a/board/lingcod/board.h b/board/lingcod/board.h deleted file mode 100644 index 230b40fd84..0000000000 --- a/board/lingcod/board.h +++ /dev/null @@ -1,171 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Baseboard features */ -#include "baseboard.h" - -/* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ - -#define CONFIG_POWER_BUTTON - -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 4096 - -/* LED defines */ -#define CONFIG_LED_POWER_LED -#define CONFIG_LED_ONOFF_STATES - -/* Keyboard features */ - -/* Sensors */ -#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT -#define CONFIG_ACCEL_LIS2DE /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ - -/* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - BIT(LID_ACCEL) - -#define CONFIG_LID_ANGLE -#define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL - -#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) - -/* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 - -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - -/* - * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C - * cables only support up to 60W. - */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 -/* Enabling USB4 mode */ -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 - -/* USB Type A Features */ - -/* USBC PPC*/ -#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ - -/* BC 1.2 */ - -/* Volume Button feature */ - -/* Fan features */ - -/* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 - -/* - * Macros for GPIO signals used in common code that don't match the - * schematic names. Signal names in gpio.inc match the schematic and are - * then redefined here to so it's more clear which signal is being used for - * which purpose. - */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L - -/* I2C Bus Configuration */ -#define CONFIG_I2C -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM - -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -enum battery_type { - BATTERY_SMP, - BATTERY_LGC, - BATTERY_SUNWODA, - BATTERY_TYPE_COUNT, -}; - -enum pwm_channel { - PWM_CH_LED4_SIDESEL = 0, - PWM_CH_FAN, - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; - -enum sensor_id { - LID_ACCEL = 0, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT, -}; - -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; - -void board_reset_pd_mcu(void); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/lingcod/build.mk b/board/lingcod/build.mk deleted file mode 100644 index 279b2e559e..0000000000 --- a/board/lingcod/build.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -CHIP:=npcx -CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc -BASEBOARD:=volteer - -board-y=board.o -board-y+=battery.o -board-y+=led.o diff --git a/board/lingcod/ec.tasklist b/board/lingcod/ec.tasklist deleted file mode 100644 index 292de51cdb..0000000000 --- a/board/lingcod/ec.tasklist +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/lingcod/gpio.inc b/board/lingcod/gpio.inc deleted file mode 100644 index 6144bba66f..0000000000 --- a/board/lingcod/gpio.inc +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -/* Wake Source interrupts */ -GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) -GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) -GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) -GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) - -/* Power sequencing interrupts */ -GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) -#endif -GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) - -/* Sensor Interrupts */ -GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) -GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) - -/* USB-C interrupts */ -GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) -GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) - -GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) -GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) - -GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) -GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) - -/* HDMI interrupts */ - -/* Volume button interrupts */ -GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) - -/* Power Sequencing Signals */ -GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) -GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) -GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ -/* The EC does not buffer this signal on Volteer. */ -UNIMPLEMENTED(PCH_DSW_PWROK) - -/* Other wake sources */ -/* - * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an - * interrupt handler because it is automatically handled by the PSL. - * - * We need to lock the setting so this gpio can't be reconfigured to overdrive - * the real reset signal. (This is the PSL input pin not the real reset pin). - */ -GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | - GPIO_HIB_WAKE_HIGH | - GPIO_LOCKED) - -/* AP/PCH Signals */ -GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) -GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ -GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) -GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) -GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) -GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) -GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) -UNIMPLEMENTED(EC_PROCHOT_IN_L) -GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) - -GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) - -/* USB and USBC Signals */ -GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset on boards board ID >=1 */ -GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) -GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) - -/* Don't have a load switch for retimer */ -UNIMPLEMENTED(USB_C1_LS_EN) - -/* Misc Signals */ - -/* - * eDP backlight - both PCH and EC have enable pins that must be high - * for the backlight to turn on. Default state is high, and can be turned - * off during sleep states. - */ -GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) - -/* I2C pins - Alternate function below configures I2C module on these pins */ -GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) -GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) -GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) -GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) -GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) -GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) -GPIO(EC_I2C3_USB_1_MIX_SCL, PIN(D, 1), GPIO_INPUT) -GPIO(EC_I2C3_USB_1_MIX_SDA, PIN(D, 0), GPIO_INPUT) -GPIO(EC_I2C5_POWER_SCL, PIN(3, 3), GPIO_INPUT) -GPIO(EC_I2C5_POWER_SDA, PIN(3, 6), GPIO_INPUT) -GPIO(EC_I2C7_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) -GPIO(EC_I2C7_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) - -/* Battery signals */ -GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) - -/* Physical HPD pins are not needed on EC as these are configured by PMC */ -GPIO(USB_C0_DP_HPD, PIN(F, 3), GPIO_INPUT) -GPIO(USB_C1_DP_HPD, PIN(7, 0), GPIO_INPUT) - -/* LED */ -GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) /* Battery - Green LED */ -GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) /* Battery - Red LED */ -GPIO(LED_3_L, PIN(C, 2), GPIO_OUT_HIGH) /* Power - White LED */ - -/* Alternate functions GPIO definitions */ -ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */ -ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ -ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ -ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ -ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ -ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ - -/* This selects between an LED module on the motherboard and one on the daughter - * board, to be controlled by LED_{1,2,3}_L. PWM allows driving both modules at - * the same time. */ -ALTERNATE(PIN_MASK(6, BIT(0)), 0, MODULE_PWM, 0) /* LED_SIDESEL_4_L */ - -/* Fan signals */ -GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) -ALTERNATE(PIN_MASK(B, BIT(7)), 0, MODULE_PWM, 0) /* FAN_PWM */ -ALTERNATE(PIN_MASK(4, BIT(0)), 0, MODULE_PWM, 0) /* FAN_SPEED_TACH */ - -/* Keyboard pins */ -#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) -ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ -ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ -ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ -GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ -ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ -ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ -ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ -ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ - -/* UART */ -ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ - -/* Power Switch Logic (PSL) inputs */ -ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ -ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, - GPIO01 = H1_EC_PWR_BTN_ODL - GPIO02 = EC_RST_ODL */ - diff --git a/board/lingcod/led.c b/board/lingcod/led.c deleted file mode 100644 index 6f4e781404..0000000000 --- a/board/lingcod/led.c +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Power and battery LED control for Malefor - */ - -#include "common.h" -#include "led_onoff_states.h" -#include "led_common.h" -#include "gpio.h" - -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 - -const int led_charge_lvl_1 = 5; - -const int led_charge_lvl_2 = 97; - -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; - -const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); - -void led_set_color_power(enum ec_led_colors color) -{ - if (color == EC_LED_COLOR_WHITE) - gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); - else - /* LED_OFF and unsupported colors */ - gpio_set_level(GPIO_LED_3_L, LED_OFF_LVL); -} - -void led_set_color_battery(enum ec_led_colors color) -{ - switch (color) { - case EC_LED_COLOR_RED: - gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); - gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); - break; - case EC_LED_COLOR_AMBER: - gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); - gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); - break; - case EC_LED_COLOR_GREEN: - gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); - gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); - break; - default: /* LED_OFF and other unsupported colors */ - gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); - gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); - break; - } -} - -void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) -{ - if (led_id == EC_LED_ID_BATTERY_LED) { - brightness_range[EC_LED_COLOR_RED] = 1; - brightness_range[EC_LED_COLOR_AMBER] = 1; - brightness_range[EC_LED_COLOR_GREEN] = 1; - } else if (led_id == EC_LED_ID_POWER_LED) { - brightness_range[EC_LED_COLOR_WHITE] = 1; - } -} - -int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) -{ - if (led_id == EC_LED_ID_BATTERY_LED) { - if (brightness[EC_LED_COLOR_RED] != 0) - led_set_color_battery(EC_LED_COLOR_RED); - else if (brightness[EC_LED_COLOR_AMBER] != 0) - led_set_color_battery(EC_LED_COLOR_AMBER); - else if (brightness[EC_LED_COLOR_GREEN] != 0) - led_set_color_battery(EC_LED_COLOR_GREEN); - else - led_set_color_battery(LED_OFF); - } else if (led_id == EC_LED_ID_POWER_LED) { - if (brightness[EC_LED_COLOR_WHITE] != 0) - led_set_color_power(EC_LED_COLOR_WHITE); - else - led_set_color_power(LED_OFF); - } - - return EC_SUCCESS; -} diff --git a/board/lisbon/board.c b/board/lisbon/board.c new file mode 100644 index 0000000000..898d85a9d0 --- /dev/null +++ b/board/lisbon/board.c @@ -0,0 +1,534 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "adc.h" +#include "builtin/assert.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/cec/bitbang.h" +#include "driver/tcpm/tcpci.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power_s5; +static int32_t base_5v_power_z1; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ + +/* PP5000_S5 loads */ +#define PWR_S5_BASE_LOAD (5 * 1431) +#define PWR_S5_FRONT_HIGH (5 * 1737) +#define PWR_S5_FRONT_LOW (5 * 1055) +#define PWR_S5_REAR_HIGH (5 * 1737) +#define PWR_S5_REAR_LOW (5 * 1055) +#define PWR_S5_HDMI (5 * 580) +#define PWR_S5_MAX (5 * 10000) +#define FRONT_DELTA (PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW) +#define REAR_DELTA (PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW) + +/* PP5000_Z1 loads */ +#define PWR_Z1_BASE_LOAD (5 * 5) +#define PWR_Z1_C_HIGH (5 * 3600) +#define PWR_Z1_C_LOW (5 * 2000) +#define PWR_Z1_MAX (5 * 9000) +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int front_ports = 0; + int rear_ports = 0; + + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power_s5 = PWR_S5_BASE_LOAD; + if (!gpio_get_level(GPIO_USB_A0_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) { + front_ports++; + base_5v_power_s5 += PWR_S5_FRONT_LOW; + } + /* + * Only 1 front port can run higher power at a time. + */ + if (front_ports > 0) + base_5v_power_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + + if (!gpio_get_level(GPIO_USB_A2_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + if (!gpio_get_level(GPIO_USB_A3_OC_ODL)) { + rear_ports++; + base_5v_power_s5 += PWR_S5_REAR_LOW; + } + /* + * Only 1 rear port can run higher power at a time. + */ + if (rear_ports > 0) + base_5v_power_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + if (!gpio_get_level(GPIO_HDMIA_CONN_OC_ODL)) + base_5v_power_s5 += PWR_S5_HDMI; + if (!gpio_get_level(GPIO_HDMIB_CONN_OC_ODL)) + base_5v_power_s5 += PWR_S5_HDMI; + base_5v_power_z1 = PWR_Z1_BASE_LOAD; + if (usbc_overcurrent) + base_5v_power_z1 += PWR_Z1_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) + ec_bj_power(&pi.voltage, &pi.current); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +static void adp_state_init(void) +{ + ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT); + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +static void board_init(void) +{ + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + gpio_enable_interrupt(GPIO_HDMIA_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_HDMIB_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A2_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A3_OC_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Check that port number is valid. */ + if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) + return; + usbc_overcurrent = is_overcurrented; + update_5v_usage(); +} +/* + * Power monitoring and management. + * + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * The overall goal is to gracefully manage the power demand so that + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type A BC1.2 rear port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 3 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A_FRONT BIT(0) +#define THROT_TYPE_A_REAR BIT(1) +#define THROT_TYPE_C0 BIT(2) +#define THROT_PROCHOT BIT(5) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + static uint32_t history[POWER_READINGS]; + static uint8_t index; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v_s5 = PWR_S5_MAX - base_5v_power_s5; + int32_t headroom_5v_z1 = PWR_Z1_MAX - base_5v_power_z1; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + /* + * Clear the first entry of the power table so that + * it is re-initilalised when the CPU starts. + */ + history[0] = 0; + } else { + int32_t charger_mw; + + delay = POWER_DELAY_MS * MSEC; + /* + * Get current charger limit (in mw). + * If not configured yet, skip. + */ + charger_mw = charge_manager_get_power_limit_uw() / 1000; + if (charger_mw != 0) { + int32_t gap, total, max, power; + int i; + + /* + * Read power usage. + */ + power = (adc_read_channel(ADC_VBUS) * + adc_read_channel(ADC_PPVAR_IMON)) / + 1000; + /* Init power table */ + if (history[0] == 0) { + for (i = 0; i < POWER_READINGS; i++) + history[i] = power; + } + /* + * Update the power readings and + * calculate the average and max. + */ + history[index] = power; + index = (index + 1) % POWER_READINGS; + total = 0; + max = history[0]; + for (i = 0; i < POWER_READINGS; i++) { + total += history[i]; + if (history[i] > max) + max = history[i]; + } + /* + * For Type-C power supplies, there is + * less tolerance for exceeding the rating, + * so use the max power that has been measured + * over the measuring period. + * For barrel-jack supplies, the rating can be + * exceeded briefly, so use the average. + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + power = max; + else + power = total / POWER_READINGS; + /* + * Calculate gap, and if negative, power + * demand is exceeding configured power budget, so + * throttling is required to reduce the demand. + */ + gap = charger_mw - power; + /* + * Limiting type-A power rear ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_REAR; + headroom_5v_s5 += REAR_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * Limiting type-A power front ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_FRONT; + headroom_5v_s5 += FRONT_DELTA; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(0) && gap <= 0) { + new_state |= THROT_TYPE_C0; + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + if (!(current_state & THROT_TYPE_C0)) + gap += POWER_GAIN_TYPE_C; + } + /* + * As a last resort, turn on PROCHOT to + * throttle the CPU. + */ + if (gap <= 0) + new_state |= THROT_PROCHOT; + } + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v_z1 < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C0) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v_z1 += PWR_Z1_C_HIGH - PWR_Z1_C_LOW; + new_state |= THROT_TYPE_C0; + } + /* + * [2] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v_z1 < 0) + new_state |= THROT_TYPE_C0; + } + if (headroom_5v_s5 < 0) { + /* + * [1] If type A rear not already throttled, and power still + * needed, limit type A rear. + */ + if (!(new_state & THROT_TYPE_A_REAR) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_REAR_HIGH - PWR_S5_REAR_LOW; + new_state |= THROT_TYPE_A_REAR; + } + /* + * [2] If type A front not already throttled, and power still + * needed, limit type A front. + */ + if (!(new_state & THROT_TYPE_A_FRONT) && headroom_5v_s5 < 0) { + headroom_5v_s5 += PWR_S5_FRONT_HIGH - PWR_S5_FRONT_LOW; + new_state |= THROT_TYPE_A_FRONT; + } + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_C0) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C0) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + } + if (diff & THROT_TYPE_A_REAR) { + int typea_bc = (new_state & THROT_TYPE_A_REAR) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR0_OD, typea_bc); + gpio_set_level(GPIO_USB_A_LOW_PWR1_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/lisbon/board.h b/board/lisbon/board.h new file mode 100644 index 0000000000..804a3a4ce7 --- /dev/null +++ b/board/lisbon/board.h @@ -0,0 +1,163 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lisbon board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* Barrel Jack */ +#define DEDICATED_CHARGE_PORT 1 + +/* HDMI CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMIB_CEC_OUT +#define CEC_GPIO_IN GPIO_HDMIB_CEC_IN +#define CEC_GPIO_PULL_UP GPIO_HDMIB_CEC_PULL_UP + +/* USB Type A Features */ +#define USB_PORT_COUNT 4 +#define CONFIG_USB_PORT_POWER_DUMB +#define CONFIG_USBC_RETIMER_PS8811 + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_PPC +#define CONFIG_USB_PD_TCPM_RT1715 +#define CONFIG_USBC_RETIMER_PS8818 +#define CONFIG_USBC_PPC_SYV682X +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* The design should support up to 100W. */ +/* TODO(b/197702356): Set the max PD to 60W now and change it + * to 100W after we verify it. + */ +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_OD + +/* I2C Bus Configuration */ +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 + +#define I2C_PORT_USB_C0_PPC_BC12 NPCX_I2C_PORT2_0 + +#define I2C_PORT_USB_C0_MUX NPCX_I2C_PORT3_0 + +#define I2C_PORT_USB_A2_A3_RT NPCX_I2C_PORT6_1 + +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* ADC */ +#define CONFIG_ADC + +/* + * TODO(b/197478860): Enable the fan control. We need + * to check the sensor value and adjust the fan speed. + */ +#define CONFIG_FANS FAN_CH_COUNT + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_BARRELJACK, + CHARGE_PORT_ENUM_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1_CPU, + ADC_TEMP_SENSOR_2_CPU_VR, + ADC_TEMP_SENSOR_3_WIFI, + ADC_TEMP_SENSOR_4_DIMM, + ADC_VBUS, + ADC_PPVAR_IMON, /* ADC3 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_CPU, + TEMP_SENSOR_2_CPU_VR, + TEMP_SENSOR_3_WIFI, + TEMP_SENSOR_4_DIMM, + TEMP_SENSOR_COUNT +}; + +enum pwm_channel { + PWM_CH_LED_GREEN, /* PWM0 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED_RED, /* PWM2 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +extern void adp_connect_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/lisbon/build.mk b/board/lisbon/build.mk new file mode 100644 index 0000000000..ef82fc1347 --- /dev/null +++ b/board/lisbon/build.mk @@ -0,0 +1,22 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Lisbon board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brask + +board-y= +board-y+=board.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/lisbon/ec.tasklist b/board/lisbon/ec.tasklist new file mode 100644 index 0000000000..072252f0cd --- /dev/null +++ b/board/lisbon/ec.tasklist @@ -0,0 +1,23 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/lisbon/fans.c b/board/lisbon/fans.c new file mode 100644 index 0000000000..2bf4c43912 --- /dev/null +++ b/board/lisbon/fans.c @@ -0,0 +1,50 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/197478860): need to update for real fan + * + * Prototype fan spins at about 7200 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2000, + .rpm_start = 2000, + .rpm_max = 4700, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/lisbon/fw_config.c b/board/lisbon/fw_config.c new file mode 100644 index 0000000000..0de818c18f --- /dev/null +++ b/board/lisbon/fw_config.c @@ -0,0 +1,66 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union lisbon_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for lisbon if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union lisbon_cbi_fw_config fw_config_defaults = { + .bj_power = BJ_65W, + .storage = EMMC, + .fvm_support = FVM_NO, +}; + +/* + * Barrel-jack power adapter ratings. + */ +static const struct { + int voltage; + int current; +} bj_power[] = { + [BJ_65W] = { /* 0 - 65W (also default) */ + .voltage = 19000, + .current = 3420 + }, + [BJ_90W] = { /* 1 - 90W */ + .voltage = 19000, + .current = 4740 + } +}; + +/**************************************************************************** + * Lisbon FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +void ec_bj_power(uint32_t *voltage, uint32_t *current) +{ + unsigned int bj; + + bj = fw_config.bj_power; + /* Out of range value defaults to 0 */ + if (bj >= ARRAY_SIZE(bj_power)) + bj = 0; + *voltage = bj_power[bj].voltage; + *current = bj_power[bj].current; +} diff --git a/board/lisbon/fw_config.h b/board/lisbon/fw_config.h new file mode 100644 index 0000000000..e9cd6bd338 --- /dev/null +++ b/board/lisbon/fw_config.h @@ -0,0 +1,44 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_LISBON_FW_CONFIG_H_ +#define __BOARD_LISBON_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Lisbon board. + * + * Source of truth is the project/brask/lisbon/config.star configuration file. + */ +enum ec_cfg_bj_power { BJ_65W = 0, BJ_90W = 1 }; + +enum ec_cfg_storage { EMMC = 0, SSD = 1 }; + +enum ec_cfg_fvm_support { FVM_NO = 0, FVM_YES = 1 }; + +union lisbon_cbi_fw_config { + struct { + uint32_t bj_power : 1; + uint32_t storage : 1; + uint32_t fvm_support : 1; + uint32_t reserved_1 : 29; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union lisbon_cbi_fw_config get_fw_config(void); + +/** + * Get the barrel-jack power from FW_CONFIG. + */ +void ec_bj_power(uint32_t *voltage, uint32_t *current); + +#endif /* __BOARD_LISBON_FW_CONFIG_H_ */ diff --git a/board/lisbon/gpio.inc b/board/lisbon/gpio.inc new file mode 100644 index 0000000000..958b36c619 --- /dev/null +++ b/board/lisbon/gpio.inc @@ -0,0 +1,162 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTERRUPT GPIOs: */ + +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(2, 3), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(HDMIA_CONN_OC_ODL, PIN(5, 0), GPIO_INPUT | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(HDMIB_CONN_OC_ODL, PIN(2, 4), GPIO_INPUT | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A0_OC_ODL, PIN(3, 1), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A2_OC_ODL, PIN(2, 7), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A3_OC_ODL, PIN(2, 6), GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH, port_ocp_interrupt) + +/* CCD */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + +/* Security */ +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Fan */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) + +/* ADC, need to check the usage */ +GPIO(ANALOG_PPVAR_PWR_IN_IMON_EC, PIN(4, 2), GPIO_INPUT) + +/* BarrelJack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 7), GPIO_OUT_LOW) + +/* Chipset PCH */ +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) + +/* Button */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(GSC_EC_RECOVERY_BTN_OD, PIN(2, 2), GPIO_INPUT) + +/* HDMI CEC */ +/* TODO(b/197474873): Enable HDMI CEC */ +GPIO(HDMIB_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMIB_CEC_OUT, PIN(D, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMIB_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH) +GPIO(HDMIA_CEC_IN, PIN(A, 7), GPIO_INPUT) +GPIO(HDMIA_CEC_OUT, PIN(F, 2), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMIA_CEC_PULL_UP, PIN(F, 3), GPIO_OUT_HIGH) + +/* I2C SCL/SDA */ +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_A2_A3_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_A2_A3_SDA, PIN(E, 3), GPIO_INPUT) + +/* USBA */ +GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW) +GPIO(USB_A0_STATUS_L, PIN(2, 1), GPIO_INPUT) +GPIO(USB_A1_STATUS_L, PIN(2, 0), GPIO_INPUT) +GPIO(USB_A_LOW_PWR0_OD, PIN(1, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_LOW_PWR1_OD, PIN(1, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH) + +/* LED */ +/* TODO(b/197471359): LED implementation */ +GPIO(LED_GREEN_L, PIN(C, 3), GPIO_OUT_LOW) +GPIO(LED_RED_L, PIN(C, 4), GPIO_OUT_LOW) + +/* USBC */ +GPIO(USB_C0_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C0_HPD, PIN(0, 4), GPIO_OUT_LOW) +GPIO(USB_C0_OC_ODL, PIN(7, 0), GPIO_OUT_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIO02_NC, PIN(0, 2), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */ +UNUSED(PIN(9, 7)) /* GPIO97 */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */ +UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */ +UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */ +UNUSED(PIN(0, 6)) /* KSO11/GPIO06/P80_CLK */ +UNUSED(PIN(A, 0)) +UNUSED(PIN(A, 2)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(B, 5)) +UNUSED(PIN(B, 4)) +UNUSED(PIN(D, 2)) +UNUSED(PIN(D, 4)) +UNUSED(PIN(F, 5)) +UNUSED(PIN(0, 5)) +UNUSED(PIN(1, 1)) +UNUSED(PIN(1, 0)) +UNUSED(PIN(1, 7)) +UNUSED(PIN(1, 6)) +UNUSED(PIN(2, 5)) +UNUSED(PIN(3, 3)) +UNUSED(PIN(3, 6)) +UNUSED(PIN(4, 1)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(9, 3)) +UNUSED(PIN(9, 5)) +UNUSED(PIN(9, 6)) diff --git a/board/lisbon/i2c.c b/board/lisbon/i2c.c new file mode 100644 index 0000000000..a58f75bfa7 --- /dev/null +++ b/board/lisbon/i2c.c @@ -0,0 +1,53 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc, bc1.2 c0", + .port = I2C_PORT_USB_C0_PPC_BC12, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0", + .port = I2C_PORT_USB_C0_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA, + }, + { + /* I2C6 */ + .name = "usba2_retimer, usba3_retimer", + .port = I2C_PORT_USB_A2_A3_RT, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_A2_A3_SCL, + .sda = GPIO_EC_I2C_USB_A2_A3_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/lisbon/led.c b/board/lisbon/led.c new file mode 100644 index 0000000000..711b914660 --- /dev/null +++ b/board/lisbon/led.c @@ -0,0 +1,260 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Lisbon. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_GREEN, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int green = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_GREEN: + green = 1; + break; + case LED_RED: + red = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (green) + pwm_set_duty(PWM_CH_LED_GREEN, duty); + else + pwm_set_duty(PWM_CH_LED_GREEN, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* + * When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_GREEN); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* + * Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_GREEN, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "green")) { + set_color(id, LED_GREEN, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|red|green|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_GREEN] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_GREEN]) + return set_color(id, LED_GREEN, brightness[EC_LED_COLOR_GREEN]); + else + return set_color(id, LED_OFF, 0); +} +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Blink alert if insufficient power per system_can_boot_ap(). */ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + led_alert(insufficient_power); +} diff --git a/board/lisbon/pwm.c b/board/lisbon/pwm.c new file mode 100644 index 0000000000..db85952f41 --- /dev/null +++ b/board/lisbon/pwm.c @@ -0,0 +1,33 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_GREEN] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN | PWM_CONFIG_DSLEEP, + .freq = 1000 }, + [PWM_CH_LED_RED] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + pwm_enable(PWM_CH_FAN, 1); + + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_GREEN, 1); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/lisbon/sensors.c b/board/lisbon/sensors.c new file mode 100644 index 0000000000..99bc0a4304 --- /dev/null +++ b/board/lisbon/sensors.c @@ -0,0 +1,114 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_CPU] = { + .name = "TEMP_CPU", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CPU_VR] = { + .name = "TEMP_CPU_VR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_WIFI] = { + .name = "TEMP_WIFI", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DIMM] = { + .name = "TEMP_DIMM", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 872.3 mV/A */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT * 1433, + .factor_div = (ADC_READ_MAX + 1) * 1250, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_CPU] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_CPU }, + [TEMP_SENSOR_2_CPU_VR] = { .name = "CPU VR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CPU_VR }, + [TEMP_SENSOR_3_WIFI] = { .name = "WIFI", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_WIFI }, + [TEMP_SENSOR_4_DIMM] = { .name = "DIMM", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DIMM }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(80), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/197478860): add the thermal sensor setting + */ +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CPU] = THERMAL_CPU, + [TEMP_SENSOR_2_CPU_VR] = THERMAL_CPU, + [TEMP_SENSOR_3_WIFI] = THERMAL_CPU, + [TEMP_SENSOR_4_DIMM] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/lisbon/usbc_config.c b/board/lisbon/usbc_config.c new file mode 100644 index 0000000000..c010eb1333 --- /dev/null +++ b/board/lisbon/usbc_config.c @@ -0,0 +1,162 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/ps8818_public.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC_BC12, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +static int board_c0_ps8818_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + if (mux_state & USB_PD_MUX_DP_ENABLED) + gpio_set_level(GPIO_USB_C0_HPD, 1); + else + gpio_set_level(GPIO_USB_C0_HPD, 0); + + return 0; +} + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &ps8818_usb_retimer_driver, + .i2c_port = I2C_PORT_USB_C0_MUX, + .i2c_addr_flags = PS8818_I2C_ADDR3_FLAGS, + .board_set = &board_c0_ps8818_mux_set, + }, + .next = &usbc0_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +void board_reset_pd_mcu(void) +{ + /* Using RT1716, no reset available for TCPC */ +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + schedule_deferred_pd_interrupt(USBC_PORT_C0); +} + +void bc12_interrupt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +void ppc_interrupt(enum gpio_signal signal) +{ + syv682x_interrupt(USBC_PORT_C0); +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} diff --git a/board/lisbon/usbc_config.h b/board/lisbon/usbc_config.h new file mode 100644 index 0000000000..9e7f05a676 --- /dev/null +++ b/board/lisbon/usbc_config.h @@ -0,0 +1,15 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Lisbon board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/lisbon/vif_override.xml b/board/lisbon/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/lisbon/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/madoo/battery.c b/board/madoo/battery.c index 9d17d9b0fd..b37cb463dd 100644 --- a/board/madoo/battery.c +++ b/board/madoo/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -12,7 +12,7 @@ #include "extpower.h" /* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHUTDOWN_DATA 0x0010 +#define SB_SHUTDOWN_DATA 0x0010 const struct board_batt_params board_battery_info[] = { [BATTERY_SIMPLO_HIGHPOWER] = { @@ -123,7 +123,7 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 60, }, }, - [BATTERY_DynaPack_COS] = { + [BATTERY_DYNAPACK_COS] = { .fuel_gauge = { .manuf_name = "333-2C-DA-A", .ship_mode = { @@ -150,7 +150,7 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 60, }, }, - [BATTERY_DANAPACK_ATL] = { + [BATTERY_DYNAPACK_ATL] = { .fuel_gauge = { .manuf_name = "333-27-DA-A", .ship_mode = { diff --git a/board/madoo/board.c b/board/madoo/board.c index 9ced2a0ecb..bb031c3acf 100644 --- a/board/madoo/board.c +++ b/board/madoo/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,7 +9,7 @@ #include "button.h" #include "cbi_fw_config.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" #include "common.h" @@ -28,8 +28,8 @@ #include "gpio.h" #include "hooks.h" #include "i2c.h" -#include "keyboard_scan.h" #include "keyboard_8042_sharedlib.h" +#include "keyboard_scan.h" #include "lid_switch.h" #include "motion_sense.h" #include "power.h" @@ -46,34 +46,81 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) -static void tcpc_alert_event(enum gpio_signal s) -{ - int port = (s == GPIO_USB_C0_INT_ODL) ? 0 : 1; +#define INT_RECHECK_US 5000 - schedule_deferred_pd_interrupt(port); -} +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); -static void usb_c0_interrupt(enum gpio_signal s) +static void notify_c0_chips(void) { /* * The interrupt line is shared between the TCPC and BC 1.2 detection * chip. Therefore we'll need to check both ICs. */ - tcpc_alert_event(s); - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } -static void sub_usb_c1_interrupt(enum gpio_signal s) +static void check_c0_line(void) { /* - * The interrupt line is shared between the TCPC and BC 1.2 detection - * chip. Therefore we'll need to check both ICs. + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. */ - tcpc_alert_event(s); - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void sub_usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); } static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) @@ -82,6 +129,7 @@ static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) pd_handle_cc_overvoltage(0); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* ADC channels */ @@ -128,8 +176,18 @@ void board_init(void) /* Enable gpio interrupt for base accelgyro sensor */ gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) + hook_call_deferred(&check_c1_line_data, 0); + /* Turn on 5V if the system is on, otherwise turn it off. */ - on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND); + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); board_power_5v_enable(on); if (get_cbi_fw_config_keyboard() == CUST_UK2_KB) { /* @@ -151,8 +209,8 @@ void board_hibernate(void) * Both charger ICs need to be put into their "low power mode" before * entering the Z-state. */ - raa489000_hibernate(1); - raa489000_hibernate(0); + raa489000_hibernate(1, true); + raa489000_hibernate(0, false); } void board_reset_pd_mcu(void) @@ -163,40 +221,9 @@ void board_reset_pd_mcu(void) */ } -static void reconfigure_5v_gpio(void) -{ - /* - * b/147257497: On early boards, GPIO_EN_PP5000 was swapped with - * GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that GPIO - * instead for those boards. Note that this breaks the volume up button - * functionality. - */ - if (system_get_board_version() < 0) { - CPRINTS("old board - remapping 5V en"); - gpio_set_flags(GPIO_VOLUP_BTN_ODL, GPIO_OUT_LOW); - } -} -DECLARE_HOOK(HOOK_INIT, reconfigure_5v_gpio, HOOK_PRIO_INIT_I2C+1); - static void set_5v_gpio(int level) { - int version; - enum gpio_signal gpio; - - /* - * b/147257497: On early boards, GPIO_EN_PP5000 was swapped with - * GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that GPIO - * instead for those boards. Note that this breaks the volume up button - * functionality. - */ - version = system_get_board_version(); - - /* - * If the CBI EEPROM wasn't formatted, assume it's a very early board. - */ - gpio = version < 0 ? GPIO_VOLUP_BTN_ODL : GPIO_EN_PP5000; - - gpio_set_level(gpio, level); + gpio_set_level(GPIO_EN_PP5000, level); } __override void board_power_5v_enable(int enable) @@ -209,8 +236,7 @@ __override void board_power_5v_enable(int enable) set_5v_gpio(!!enable); if (isl923x_set_comparator_inversion(1, !!enable)) - CPRINTS("Failed to %sable sub rails!", enable ? - "en" : "dis"); + CPRINTS("Failed to %sable sub rails!", enable ? "en" : "dis"); } int board_is_sourcing_vbus(int port) @@ -219,13 +245,11 @@ int board_is_sourcing_vbus(int port) tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); - } int board_set_active_charge_port(int port) { - int is_real_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); int i; int old_port; @@ -238,9 +262,11 @@ int board_set_active_charge_port(int port) /* Disable all ports. */ if (port == CHARGE_PORT_NONE) { - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { tcpc_write(i, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } return EC_SUCCESS; } @@ -262,6 +288,7 @@ int board_set_active_charge_port(int port) if (tcpc_write(i, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW)) CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); } /* @@ -272,7 +299,8 @@ int board_set_active_charge_port(int port) charger_discharge_on_ac(1); /* Enable requested charge port. */ - if (tcpc_write(port, TCPC_REG_COMMAND, + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { CPRINTS("p%d: sink path enable failed.", port); charger_discharge_on_ac(0); @@ -285,16 +313,12 @@ int board_set_active_charge_port(int port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) { - int icl = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); + if (port < 0 || port > board_get_usb_pd_port_count()) + return; - /* - * TODO(b:147463641): Characterize the input current limit in case that - * a scaling needs to be applied here. - */ - charge_set_input_current_limit(icl, charge_mv); + raa489000_set_output_current(port, rp); } /* Sensors */ @@ -302,17 +326,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrices to rotate accelerometers into the standard reference. */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; static struct accelgyro_saved_data_t g_bma253_data; static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; @@ -352,8 +372,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &base_standard_ref, @@ -381,8 +399,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -396,40 +412,26 @@ const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Thermistors */ const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Memory", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -__override void ocpc_get_pid_constants(int *kp, int *kp_div, - int *ki, int *ki_div, - int *kd, int *kd_div) +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) { - /* - * Early boards need different constants due to a change in charger IC - * silicon revision. - */ - if (system_get_board_version() >= 0) { - *kp = 1; - *kp_div = 128; - *ki = 1; - *ki_div = 1024; - *kd = 0; - *kd_div = 1; - } else { - *kp = 1; - *kp_div = 4; - *ki = 1; - *ki_div = 15; - *kd = 1; - *kd_div = 10; - } + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; } int pd_snk_is_vbus_provided(int port) @@ -497,31 +499,43 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }, }; -const struct usb_mux usbc0_retimer = { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = NB7V904M_I2C_ADDR0, - .driver = &nb7v904m_usb_redriver_drv, +const struct usb_mux_chain usbc0_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = NB7V904M_I2C_ADDR0, + .driver = &nb7v904m_usb_redriver_drv, + }, }; -const struct usb_mux usbc1_retimer = { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = NB7V904M_I2C_ADDR0, - .driver = &nb7v904m_usb_redriver_drv, +const struct usb_mux_chain usbc1_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = NB7V904M_I2C_ADDR0, + .driver = &nb7v904m_usb_redriver_drv, + }, }; -struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, - .driver = &pi3usb3x532_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, }, { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, - .driver = &pi3usb3x532_usb_mux_driver, - .next_mux = &usbc1_retimer, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + .next = &usbc1_retimer, } }; @@ -529,10 +543,10 @@ static void reconfigure_usbmux(void) { if (system_get_board_version() < 2) { CPRINTS("add redriver at usbc0"); - usb_muxes[0].next_mux = &usbc0_retimer; + usb_muxes[0].next = &usbc0_retimer; } } -DECLARE_HOOK(HOOK_INIT, reconfigure_usbmux, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, reconfigure_usbmux, HOOK_PRIO_INIT_I2C + 1); uint16_t tcpc_get_alert_status(void) { @@ -569,9 +583,8 @@ uint16_t tcpc_get_alert_status(void) return status; } -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); @@ -595,4 +608,3 @@ void lid_angle_peripheral_enable(int enable) keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); } } -#endif diff --git a/board/madoo/board.h b/board/madoo/board.h index 100e39e842..1e7118ba28 100644 --- a/board/madoo/board.h +++ b/board/madoo/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,19 +11,22 @@ #define VARIANT_DEDEDE_EC_NPCX796FC #include "baseboard.h" -/* - * Keep the system unlocked in early development. - * TODO(b/151264302): Make sure to remove this before production! - */ -#define CONFIG_SYSTEM_UNLOCKED - /* Charger */ #define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 #define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_OCPC_DEF_RBATT_MOHMS 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr */ +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 #define CONFIG_OCPC -#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_CHARGER_SINGLE_CHIP /* EC console commands */ #define CONFIG_CMD_TCPC_DUMP @@ -37,7 +40,7 @@ /* PWM */ #define CONFIG_PWM -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ /* USB */ #define CONFIG_BC12_DETECT_PI3USB9201 @@ -45,12 +48,14 @@ /* LED */ #define CONFIG_LED_COMMON -#define CONFIG_LED_POWER_LED #define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 /* USB PD */ #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PD_TCPM_RAA489000 +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) /* USB defines specific to external TCPCs */ #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE @@ -62,16 +67,16 @@ #define CONFIG_USB_PD_5V_EN_CUSTOM /* I2C configuration */ -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 #define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* TODO(b:147440290): Need to handle multiple charger ICs */ -#define I2C_PORT_CHARGER I2C_PORT_USB_C0 +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 -#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_ACCEL I2C_PORT_SENSOR #define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ @@ -79,17 +84,15 @@ #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO -#define CONFIG_ACCEL_BMA255 /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Lid operates in forced mode, base in FIFO */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) #define CONFIG_ACCEL_FIFO -#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) -#define CONFIG_ACCEL_INTERRUPTS - #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL @@ -102,9 +105,6 @@ #define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_MKBP_EVENT -#define CONFIG_MKBP_USE_GPIO - #define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_FUEL_GAUGE @@ -114,7 +114,6 @@ #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_PP3300_A #ifndef __ASSEMBLER__ @@ -128,25 +127,16 @@ enum chg_id { }; enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_SUB_ANALOG, /* ADC2 */ - ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_VSNS_PP3300_A, /* ADC9 */ ADC_CH_COUNT }; -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; -enum temp_sensor_id { - TEMP_SENSOR_1, - TEMP_SENSOR_2, - TEMP_SENSOR_COUNT -}; +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; enum pwm_channel { PWM_CH_KBLIGHT, @@ -158,8 +148,8 @@ enum battery_type { BATTERY_SIMPLO_COS, BATTERY_CosMX, BATTERY_SAMSUNG_SDI, - BATTERY_DynaPack_COS, - BATTERY_DANAPACK_ATL, + BATTERY_DYNAPACK_COS, + BATTERY_DYNAPACK_ATL, BATTERY_TYPE_COUNT, }; @@ -169,7 +159,5 @@ enum fw_config_keyboard_type { CUST_UK2_KB = 1, }; -int board_is_sourcing_vbus(int port); - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/madoo/build.mk b/board/madoo/build.mk index e262a6aabc..1531d1f3ae 100644 --- a/board/madoo/build.mk +++ b/board/madoo/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,4 +11,4 @@ CHIP_FAMILY:=npcx7 CHIP_VARIANT:=npcx7m7fc BASEBOARD:=dedede -board-y=board.o battery.o led.o usb_pd_policy.o +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/madoo/cbi_ssfc.c b/board/madoo/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/madoo/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/madoo/cbi_ssfc.h b/board/madoo/cbi_ssfc.h new file mode 100644 index 0000000000..13800bcc85 --- /dev/null +++ b/board/madoo/cbi_ssfc.h @@ -0,0 +1,60 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t usb_ss_mux : 3; + uint32_t reserved_2 : 23; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/madoo/ec.tasklist b/board/madoo/ec.tasklist index 0aba1fabeb..ba5855412d 100644 --- a/board/madoo/ec.tasklist +++ b/board/madoo/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/madoo/gpio.inc b/board/madoo/gpio.inc index 53dece4e13..d3eb97ed11 100644 --- a/board/madoo/gpio.inc +++ b/board/madoo/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -52,10 +52,6 @@ GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) -/* Extra Sub-board I/O pins */ -GPIO(EC_SUB_IO_1, PIN(3, 7), GPIO_OUT_LOW) -GPIO(EC_SUB_IO_2, PIN(3, 4), GPIO_OUT_LOW) - /* Misc Enables */ GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) /* TODO(b:149775160) - Modify if needed if we ever use this signal. */ @@ -84,7 +80,7 @@ GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) -GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) GPIO(USB_C0_RST_ODL, PIN(9, 7), GPIO_OUT_HIGH) /* currently unused */ GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) @@ -96,6 +92,8 @@ GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) GPIO(BAT_LED_AMBER_L, PIN(C, 4), GPIO_OUT_HIGH) GPIO(BAT_LED_WHITE_L, PIN(C, 3), GPIO_OUT_HIGH) GPIO(PWR_LED_WHITE_L, PIN(C, 2), GPIO_OUT_HIGH) +GPIO(EC_CHG_LED_R_Y, PIN(F, 2), GPIO_OUT_HIGH) +GPIO(EC_CHG_LED_R_W, PIN(F, 3), GPIO_OUT_HIGH) /* * Waddledoo doesn't have these physical pins coming to the EC but uses other @@ -130,3 +128,18 @@ ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO00_NC, PIN(0, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO34_NC, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO37_NC, PIN(3, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO41_NC, PIN(4, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/madoo/led.c b/board/madoo/led.c index e22f9cff42..3aabcb171c 100644 --- a/board/madoo/led.c +++ b/board/madoo/led.c @@ -1,56 +1,66 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for madoo */ +#include "charge_state.h" +#include "driver/tcpm/tcpci.h" #include "ec_commands.h" #include "gpio.h" +#include "hooks.h" #include "led_common.h" #include "led_onoff_states.h" -#include "hooks.h" +#include "system.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1; +__override const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* madoo: Note there is only LED for charge / power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0_BAT_LOW] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - /* STATE_DISCHARGE_S3 will changed if sku is clamshells */ - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 0.5 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + /* STATE_DISCHARGE_S3 will changed if sku is clamshells */ + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 1 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_ON_LVL); @@ -59,20 +69,90 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +/* + * Turn off battery LED, if AC is present but battery is not charging. + * It could be caused by battery's protection like OTP. + */ +int battery_safety_check(void) +{ + uint8_t data[6]; + int rv; + + /* ignore battery in error state because it has other behavior */ + if (led_pwr_get_state() == LED_PWRS_ERROR) + return false; + + /* turn off LED due to a safety fault */ + rv = sb_read_mfgacc(PARAM_SAFETY_STATUS, SB_ALT_MANUFACTURER_ACCESS, + data, sizeof(data)); + if (rv) + return false; + /* + * Each bit represents for one safey status, and normally they should + * all be 0. Data reads from LSB to MSB. + * data[2] - BIT 7-0 + * AOLDL, AOLD, OCD2, OCD1, OCC2, OCC1, COV, CUV + * + * data[3] - BIT 15-8 + * RSVD, CUVC, OTD, OTC, ASCDL, ASCD, ASCCL, ASCC + * + * data[4] - BIT 23-16 + * CHGC, OC, RSVD, CTO, RSVD, PTO, RSVD, OTF + * + * data[5] - BIT 31-24 + * RSVD, RSVD, OCDL, COVL, UTD, UTC, PCHGC, CHGV + */ + if (data[2] || data[3] || data[4] || data[5]) + return true; + + return false; +} + +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: - gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_ON_LVL); - gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_OFF_LVL); + /* Ports are controlled by different GPIO */ + if (battery_safety_check()) { + gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_EC_CHG_LED_R_W, LED_OFF_LVL); + } else if (charge_manager_get_active_charge_port() == 1 || + system_get_board_version() < 3) { + gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_ON_LVL); + gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_OFF_LVL); + } else if (charge_manager_get_active_charge_port() == 0) { + gpio_set_level(GPIO_EC_CHG_LED_R_W, LED_ON_LVL); + gpio_set_level(GPIO_EC_CHG_LED_R_Y, LED_OFF_LVL); + } break; case EC_LED_COLOR_AMBER: - gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_OFF_LVL); - gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_ON_LVL); + /* Ports are controlled by different GPIO */ + if (battery_safety_check()) { + gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_OFF_LVL); + gpio_set_level(GPIO_EC_CHG_LED_R_Y, LED_OFF_LVL); + } else if (led_pwr_get_state() == LED_PWRS_ERROR && + system_get_board_version() >= 3) { + gpio_set_level(GPIO_EC_CHG_LED_R_W, LED_OFF_LVL); + gpio_set_level(GPIO_EC_CHG_LED_R_Y, LED_ON_LVL); + } else if (charge_manager_get_active_charge_port() == 1 || + system_get_board_version() < 3) { + gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_ON_LVL); + gpio_set_level(GPIO_EC_CHG_LED_R_Y, LED_OFF_LVL); + } else if (charge_manager_get_active_charge_port() == 0) { + gpio_set_level(GPIO_EC_CHG_LED_R_W, LED_OFF_LVL); + gpio_set_level(GPIO_EC_CHG_LED_R_Y, LED_ON_LVL); + } else if (charge_get_percent() < + CONFIG_LED_ONOFF_STATES_BAT_LOW) { + gpio_set_level(GPIO_EC_CHG_LED_R_W, LED_OFF_LVL); + gpio_set_level(GPIO_EC_CHG_LED_R_Y, LED_ON_LVL); + } break; default: /* LED_OFF and other unsupported colors */ gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_OFF_LVL); gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_OFF_LVL); + gpio_set_level(GPIO_EC_CHG_LED_R_W, LED_OFF_LVL); + gpio_set_level(GPIO_EC_CHG_LED_R_Y, LED_OFF_LVL); break; } } @@ -105,4 +185,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/madoo/usb_pd_policy.c b/board/madoo/usb_pd_policy.c index bcdf8300c5..2bad4d6931 100644 --- a/board/madoo/usb_pd_policy.c +++ b/board/madoo/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,11 +7,12 @@ #include "chipset.h" #include "common.h" #include "console.h" +#include "driver/charger/isl923x_public.h" #include "driver/tcpm/tcpci.h" #include "usb_pd.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -24,11 +25,6 @@ void pd_power_supply_reset(int port) /* Disable VBUS */ tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -54,10 +50,9 @@ int pd_set_power_supply_ready(int port) if (rv) return rv; -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/board/madoo/vif_override.xml b/board/madoo/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/madoo/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/magolor/battery.c b/board/magolor/battery.c index e7572946b2..748c079890 100644 --- a/board/magolor/battery.c +++ b/board/magolor/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -93,6 +93,127 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 75, }, }, + /* AP19B8M */ + [BATTERY_AP19B8M] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G024", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13350, + .voltage_normal = 11610, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* AP18C7M */ + [BATTERY_AP18C7M] = { + .fuel_gauge = { + .manuf_name = "SMP KT00407008", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + } + }, + .batt_info = { + .voltage_max = 17600, + .voltage_normal = 15400, + .voltage_min = 12000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, + /* COSMX AP20CBL Battery Information */ + [BATTERY_COSMX_AP20CBL] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B002", + .device_name = "AP20CBL", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* COSMX AP20CBL Battery Information (new firmware ver) */ + [BATTERY_COSMX_AP20CBL_004] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B004", + .device_name = "AP20CBL", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); diff --git a/board/magolor/board.c b/board/magolor/board.c index d173c25716..92505e1928 100644 --- a/board/magolor/board.c +++ b/board/magolor/board.c @@ -1,33 +1,40 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Waddledoo board-specific configuration */ -#include "adc_chip.h" +#include "adc.h" +#include "battery_fuel_gauge.h" #include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" #include "common.h" #include "compile_time_macros.h" #include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" #include "driver/accelgyro_bmi_common.h" -#include "driver/temp_sensor/thermistor.h" -#include "temp_sensor.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/bc12/pi3usb9201.h" #include "driver/charger/isl923x.h" -#include "driver/retimer/nb7v904m.h" +#include "driver/retimer/ps8802.h" #include "driver/tcpm/raa489000.h" #include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" #include "driver/usb_mux/pi3usb3x532.h" -#include "driver/retimer/ps8802.h" +#include "driver/usb_mux/ps8743.h" #include "extpower.h" #include "gpio.h" #include "hooks.h" #include "i2c.h" +#include "keyboard_config.h" +#include "keyboard_raw.h" #include "keyboard_scan.h" #include "lid_switch.h" #include "motion_sense.h" @@ -40,18 +47,24 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" +#include "temp_sensor.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 -#define ADC_VOL_UP_MASK BIT(0) -#define ADC_VOL_DOWN_MASK BIT(1) +#define ADC_VOL_UP_MASK BIT(0) +#define ADC_VOL_DOWN_MASK BIT(1) static uint8_t new_adc_key_state; +static void ps8762_chaddr_deferred(void); +DECLARE_DEFERRED(ps8762_chaddr_deferred); + /******************************************************************************/ /* USB-A Configuration */ const int usb_port_enable[USB_PORT_COUNT] = { @@ -59,33 +72,220 @@ const int usb_port_enable[USB_PORT_COUNT] = { GPIO_EN_USB_A1_VBUS, }; -static void tcpc_alert_event(enum gpio_signal s) +#ifdef BOARD_MAGOLOR +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* + * F3 key scan cycle completed but scan input is not + * charging to logic high when EC start scan next + * column for "T" key, so we set .output_settle_us + * to 80us from 50us. + */ + .output_settle_us = 80, + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfe, 0xff, 0xff, 0xff, /* full set */ + }, +}; + +static const struct ec_response_keybd_config magolor_keybd = { + /* Default Chromeos keyboard config */ + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad, has screenlock key */ + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config magister_keybd = { + /* Default Chromeos keyboard config */ + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad, has screenlock key */ + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config magpie_keybd = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; + +static const struct ec_response_keybd_config magma_keybd = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; + +__override uint8_t board_keyboard_row_refresh(void) { - int port = (s == GPIO_USB_C0_INT_ODL) ? 0 : 1; + if (gpio_get_level(GPIO_EC_VIVALDIKEYBOARD_ID)) + return 3; + else + return 2; +} - schedule_deferred_pd_interrupt(port); +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (get_cbi_fw_config_numeric_pad()) { + if (gpio_get_level(GPIO_EC_VIVALDIKEYBOARD_ID)) + return &magma_keybd; + else + return &magpie_keybd; + } else { + if (gpio_get_level(GPIO_EC_VIVALDIKEYBOARD_ID)) + return &magister_keybd; + else + return &magolor_keybd; + } } +#endif -static void usb_c0_interrupt(enum gpio_signal s) +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) { /* * The interrupt line is shared between the TCPC and BC 1.2 detection * chip. Therefore we'll need to check both ICs. */ - tcpc_alert_event(s); - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } -static void sub_usb_c1_interrupt(enum gpio_signal s) +static void check_c0_line(void) { /* - * The interrupt line is shared between the TCPC and BC 1.2 detection - * chip. Therefore we'll need to check both ICs. + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. */ - tcpc_alert_event(s); - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + if (!gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void sub_usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + int hdmi_hpd_odl = gpio_get_level(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, !hdmi_hpd_odl); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* ADC channels */ @@ -123,56 +323,89 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* Thermistors */ const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Memory", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(73), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_b = THERMAL_B; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; static void setup_thermal(void) { thermal_params[TEMP_SENSOR_1] = thermal_a; - thermal_params[TEMP_SENSOR_2] = thermal_a; + thermal_params[TEMP_SENSOR_2] = thermal_b; } -void board_init(void) +#ifdef BOARD_MAGOLOR +static void board_update_no_keypad_by_fwconfig(void) { - int on; - - gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); - gpio_enable_interrupt(GPIO_SUB_USB_C1_INT_ODL); - /* Enable gpio interrupt for base accelgyro sensor */ - gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + if (!get_cbi_fw_config_numeric_pad()) { +#ifndef TEST_BUILD + /* Disable scanning KSO13 & 14 if keypad isn't present. */ + keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); + keyscan_config.actual_key_mask[11] = 0xfa; + keyscan_config.actual_key_mask[12] = 0xca; +#endif + } +} +#endif - /* Turn on 5V if the system is on, otherwise turn it off. */ - on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND); - board_power_5v_enable(on); +/* Enable HDMI any time the SoC is on */ +static void hdmi_enable(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + gpio_set_level(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, hdmi_enable, HOOK_PRIO_DEFAULT); - /* Initialize THERMAL */ - setup_thermal(); +static void hdmi_disable(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + gpio_set_level(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, 1); } -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, hdmi_disable, HOOK_PRIO_DEFAULT); void board_hibernate(void) { @@ -180,8 +413,11 @@ void board_hibernate(void) * Both charger ICs need to be put into their "low power mode" before * entering the Z-state. */ - raa489000_hibernate(1); - raa489000_hibernate(0); + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); + + msleep(1000); /* Wait for charger to enter low power mode */ } void board_reset_pd_mcu(void) @@ -192,42 +428,56 @@ void board_reset_pd_mcu(void) */ } +#ifdef BOARD_WADDLEDOO static void reconfigure_5v_gpio(void) { /* - * b/147257497: On early boards, GPIO_EN_PP5000 was swapped with - * GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that GPIO - * instead for those boards. Note that this breaks the volume up button - * functionality. + * b/147257497: On early waddledoo boards, GPIO_EN_PP5000 was swapped + * with GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that + * GPIO instead for those boards. Note that this breaks the volume up + * button functionality. */ if (system_get_board_version() < 0) { CPRINTS("old board - remapping 5V en"); gpio_set_flags(GPIO_VOLUP_BTN_ODL, GPIO_OUT_LOW); } } -DECLARE_HOOK(HOOK_INIT, reconfigure_5v_gpio, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, reconfigure_5v_gpio, HOOK_PRIO_INIT_I2C + 1); +#endif /* BOARD_WADDLEDOO */ static void set_5v_gpio(int level) { int version; - enum gpio_signal gpio; + enum gpio_signal gpio = GPIO_EN_PP5000; /* - * b/147257497: On early boards, GPIO_EN_PP5000 was swapped with - * GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that GPIO - * instead for those boards. Note that this breaks the volume up button - * functionality. + * b/147257497: On early waddledoo boards, GPIO_EN_PP5000 was swapped + * with GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that + * GPIO instead for those boards. Note that this breaks the volume up + * button functionality. */ - version = system_get_board_version(); + if (IS_ENABLED(BOARD_WADDLEDOO)) { + version = system_get_board_version(); - /* - * If the CBI EEPROM wasn't formatted, assume it's a very early board. - */ - gpio = version < 0 ? GPIO_VOLUP_BTN_ODL : GPIO_EN_PP5000; + /* + * If the CBI EEPROM wasn't formatted, assume it's a very early + * board. + */ + gpio = version < 0 ? GPIO_VOLUP_BTN_ODL : GPIO_EN_PP5000; + } gpio_set_level(gpio, level); } +static void ps8762_chaddr_deferred(void) +{ + /* Switch PS8762 I2C Address to 0x50*/ + if (ps8802_chg_i2c_addr(I2C_PORT_SUB_USB_C1) == EC_SUCCESS) + CPRINTS("Switch PS8762 address to 0x50 success"); + else + CPRINTS("Switch PS8762 address to 0x50 failed"); +} + __override void board_power_5v_enable(int enable) { /* @@ -236,9 +486,40 @@ __override void board_power_5v_enable(int enable) * polarity on the sub board charger IC. */ set_5v_gpio(!!enable); - if (isl923x_set_comparator_inversion(1, !!enable)) - CPRINTS("Failed to %sable sub rails!", enable ? "en" : "dis"); + if (get_cbi_fw_config_db() == DB_1A_HDMI) { + gpio_set_level(GPIO_SUB_C1_INT_EN_RAILS_ODL, !enable); + } else { + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", + enable ? "en" : "dis"); + + if (!enable) + return; + /* + * Port C1 the PP3300_USB_C1 assert, delay 15ms + * colud be accessed PS8762 by I2C. + */ + if (get_cbi_ssfc_usb_mux() == SSFC_USBMUX_PS8762) + hook_call_deferred(&ps8762_chaddr_deferred_data, + 15 * MSEC); + } +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; + else + return CONFIG_USB_PD_PORT_MAX_COUNT; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + return CHARGER_NUM - 1; + else + return CHARGER_NUM; } int board_is_sourcing_vbus(int port) @@ -247,13 +528,11 @@ int board_is_sourcing_vbus(int port) tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); - } int board_set_active_charge_port(int port) { - int is_real_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); int i; int old_port; @@ -266,9 +545,11 @@ int board_set_active_charge_port(int port) /* Disable all ports. */ if (port == CHARGE_PORT_NONE) { - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + for (i = 0; i < board_get_usb_pd_port_count(); i++) { tcpc_write(i, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } return EC_SUCCESS; } @@ -283,13 +564,14 @@ int board_set_active_charge_port(int port) * Turn off the other ports' sink path FETs, before enabling the * requested charge port. */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { if (i == port) continue; if (tcpc_write(i, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW)) CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); } /* @@ -300,7 +582,8 @@ int board_set_active_charge_port(int port) charger_discharge_on_ac(1); /* Enable requested charge port. */ - if (tcpc_write(port, TCPC_REG_COMMAND, + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { CPRINTS("p%d: sink path enable failed.", port); charger_discharge_on_ac(0); @@ -313,16 +596,12 @@ int board_set_active_charge_port(int port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) { - int icl = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); + if (port < 0 || port > board_get_usb_pd_port_count()) + return; - /* - * TODO(b:147463641): Characterize the input current limit in case that - * a scaling needs to be applied here. - */ - charge_set_input_current_limit(icl, charge_mv); + raa489000_set_output_current(port, rp); } /* Sensors */ @@ -330,21 +609,109 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrices to rotate accelerometers into the standard reference. */ -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +/* Matrices to rotate accelerometers into the magister reference. */ +static const mat33_fp_t lid_magister_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +/* BMA253 private data */ static struct accelgyro_saved_data_t g_bma253_data; + +/* BMI160 private data */ static struct bmi_drv_data_t g_bmi160_data; +#ifdef BOARD_MAGOLOR +static const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* ICM426 private data */ +static struct icm_drv_data_t g_icm426xx_data; +/* KX022 private data */ +static struct kionix_accel_data g_kx022_data; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; +#endif + struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { .name = "Lid Accel", @@ -414,31 +781,180 @@ struct motion_sensor_t motion_sensors[] = { }, }; -const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -__override void ocpc_get_pid_constants(int *kp, int *kp_div, - int *ki, int *ki_div, - int *kd, int *kd_div) +/** + * Handle debounced pen input changing state. + */ +static void pendetect_deferred(void) { - /* - * Early boards need different constants due to a change in charger IC - * silicon revision. - */ - if (system_get_board_version() >= 0) { - *kp = 1; - *kp_div = 128; - *ki = 1; - *ki_div = 1024; - *kd = 0; - *kd_div = 1; + int pen_charge_enable = !gpio_get_level(GPIO_PEN_DET_ODL) && + !chipset_in_state(CHIPSET_STATE_ANY_OFF); + + if (pen_charge_enable) + gpio_set_level(GPIO_EN_PP5000_PEN, 1); + else + gpio_set_level(GPIO_EN_PP5000_PEN, 0); + + CPRINTS("Pen charge %sable", pen_charge_enable ? "en" : "dis"); +} +DECLARE_DEFERRED(pendetect_deferred); + +void pen_detect_interrupt(enum gpio_signal signal) +{ + /* pen input debounce time */ + hook_call_deferred(&pendetect_deferred_data, (100 * MSEC)); +} + +static void pen_charge_check(void) +{ + if (get_cbi_fw_config_stylus() == STYLUS_PRESENT) + hook_call_deferred(&pendetect_deferred_data, (100 * MSEC)); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pen_charge_check, HOOK_PRIO_LAST); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pen_charge_check, HOOK_PRIO_LAST); + +/***************************************************************************** + * USB-C MUX/Retimer dynamic configuration + */ +struct usb_mux usbc1_mux0 = { + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8802_I2C_ADDR_FLAGS_CUSTOM, + .driver = &ps8802_usb_mux_driver, +}; + +static void setup_mux(void) +{ + if (get_cbi_ssfc_usb_mux() == SSFC_USBMUX_PS8743) { + usbc1_mux0.i2c_addr_flags = PS8743_I2C_ADDR0_FLAG; + usbc1_mux0.driver = &ps8743_usb_mux_driver; + ccprints("PS8743 USB MUX"); + } else + ccprints("PS8762 USB MUX"); +} + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + check_c0_line(); + + if (get_cbi_fw_config_db() == DB_1A_HDMI) { + /* Disable i2c on HDMI pins */ + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, + 0); + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, + 0); + + /* Set HDMI and sub-rail enables to output */ + gpio_set_flags(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, + chipset_in_state(CHIPSET_STATE_ON) ? + GPIO_ODR_LOW : + GPIO_ODR_HIGH); + gpio_set_flags(GPIO_SUB_C1_INT_EN_RAILS_ODL, GPIO_ODR_HIGH); + + /* Select HDMI option */ + gpio_set_level(GPIO_HDMI_SEL_L, 0); + + /* Enable interrupt for passing through HPD */ + gpio_enable_interrupt(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + + } else { + /* Set SDA as an input */ + gpio_set_flags(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, GPIO_INPUT); + + /* Enable C1 interrupt and check if it needs processing */ + gpio_enable_interrupt(GPIO_SUB_C1_INT_EN_RAILS_ODL); + check_c1_line(); + } + + setup_mux(); + + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + if (get_cbi_fw_config_tablet_mode()) { +#ifdef BOARD_MAGOLOR + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE GYRO is ICM426XX"); + } else + ccprints("BASE GYRO is BMI160"); + + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + ccprints("LID_ACCEL is KX022"); + } else { + if (system_get_board_version() >= 5) { + motion_sensors[LID_ACCEL].rot_standard_ref = + &lid_magister_ref; + } + ccprints("LID_ACCEL is BMA253"); + } +#endif + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } + + if (get_cbi_fw_config_stylus() == STYLUS_PRESENT) { + gpio_enable_interrupt(GPIO_PEN_DET_ODL); + /* Make sure pen detection is triggered or not at sysjump */ + pen_charge_check(); } else { - *kp = 1; - *kp_div = 4; - *ki = 1; - *ki_div = 15; - *kd = 1; - *kd_div = 10; + gpio_disable_interrupt(GPIO_PEN_DET_ODL); + gpio_set_flags(GPIO_PEN_DET_ODL, GPIO_INPUT | GPIO_PULL_DOWN); } + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + /* Initialize THERMAL */ + setup_thermal(); + +#ifdef BOARD_MAGOLOR + /* Support Keyboard Pad */ + board_update_no_keypad_by_fwconfig(); +#endif +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void motion_interrupt(enum gpio_signal signal) +{ +#ifdef BOARD_MAGOLOR + switch (get_cbi_ssfc_base_sensor()) { + case SSFC_SENSOR_ICM426XX: + icm426xx_interrupt(signal); + break; + case SSFC_SENSOR_BMI160: + default: + bmi160_interrupt(signal); + break; + } +#else + bmi160_interrupt(signal); +#endif +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; } int pd_snk_is_vbus_provided(int port) @@ -507,25 +1023,17 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }, }; -const struct usb_mux usbc1_retimer = { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = NB7V904M_I2C_ADDR0, - .driver = &nb7v904m_usb_redriver_drv, -}; - -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, - .driver = &pi3usb3x532_usb_mux_driver, +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, }, - { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = PS8802_I2C_ADDR_FLAGS, - .driver = &ps8802_usb_mux_driver, + [USBC_PORT_C1] = { + .mux = &usbc1_mux0, } }; @@ -550,7 +1058,8 @@ uint16_t tcpc_get_alert_status(void) } } - if (!gpio_get_level(GPIO_SUB_USB_C1_INT_ODL)) { + if (board_get_usb_pd_port_count() > 1 && + !gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { /* TCPCI spec Rev 1.0 says to ignore bits 14:12. */ if (!(tcpc_config[1].flags & TCPC_FLAGS_TCPCI_REV2_0)) @@ -586,24 +1095,24 @@ static void adc_vol_key_press_check(void) static uint8_t old_adc_key_state; uint8_t adc_key_state_change; - if (volt > 2400 && volt < 2490) { + if (volt > 2400 && volt < 2540) { /* volume-up is pressed */ new_adc_key_state = ADC_VOL_UP_MASK; - } else if (volt > 2600 && volt < 2690) { + } else if (volt > 2600 && volt < 2740) { /* volume-down is pressed */ new_adc_key_state = ADC_VOL_DOWN_MASK; - } else if (volt < 2290) { + } else if (volt < 2300) { /* both volumn-up and volume-down are pressed */ new_adc_key_state = ADC_VOL_UP_MASK | ADC_VOL_DOWN_MASK; - } else if (volt > 2700) { + } else if (volt > 2780) { /* both volumn-up and volume-down are released */ new_adc_key_state = 0; } if (new_adc_key_state != old_adc_key_state) { adc_key_state_change = old_adc_key_state ^ new_adc_key_state; - if (adc_key_state_change && ADC_VOL_UP_MASK) + if (adc_key_state_change & ADC_VOL_UP_MASK) button_interrupt(GPIO_VOLUME_UP_L); - if (adc_key_state_change && ADC_VOL_DOWN_MASK) + if (adc_key_state_change & ADC_VOL_DOWN_MASK) button_interrupt(GPIO_VOLUME_DOWN_L); old_adc_key_state = new_adc_key_state; @@ -611,9 +1120,8 @@ static void adc_vol_key_press_check(void) } DECLARE_HOOK(HOOK_TICK, adc_vol_key_press_check, HOOK_PRIO_DEFAULT); -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); @@ -637,4 +1145,16 @@ void lid_angle_peripheral_enable(int enable) keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); } } -#endif + +__override int board_get_leave_safe_mode_delay_ms(void) +{ + const struct fuel_gauge_info *const fuel_gauge = + &get_batt_params()->fuel_gauge; + + /* If it's COSMX battery, there's need more delay time. */ + if (!strcasecmp(fuel_gauge->manuf_name, "COSMX KT0030B002") || + !strcasecmp(fuel_gauge->manuf_name, "COSMX KT0030B004")) + return 2000; + else + return 500; +} diff --git a/board/magolor/board.h b/board/magolor/board.h index 2fb9f30908..07ddf79744 100644 --- a/board/magolor/board.h +++ b/board/magolor/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,31 +12,55 @@ #include "baseboard.h" #define CONFIG_USB_PD_DEBUG_LEVEL 2 + +#ifdef BOARD_MAGOLOR_LEGACY /* this change saves 1656 bytes of RW flash space */ #define CONFIG_CHIP_INIT_ROM_REGION - +#define CONFIG_DEBUG_ASSERT_BRIEF +#else /* - * Keep the system unlocked in early development. - * TODO(b/151264302): Make sure to remove this before production! + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. */ -#define CONFIG_SYSTEM_UNLOCKED +#undef CONFIG_CHIP_INIT_ROM_REGION +#endif + +/* Remove default commands to free flash space */ +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_BATTFAKE /* Battery */ #define CONFIG_BATTERY_FUEL_GAUGE /* Charger */ #define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 #define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_OCPC_DEF_RBATT_MOHMS 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr */ +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ #define CONFIG_OCPC -#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_CHARGER_SINGLE_CHIP #undef CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 /* GPIO for C1 interrupts, for baseboard use */ -#define GPIO_USB_C1_INT_ODL GPIO_SUB_USB_C1_INT_ODL +#define GPIO_USB_C1_INT_ODL GPIO_SUB_C1_INT_EN_RAILS_ODL /* Keyboard */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#ifdef BOARD_MAGOLOR + +#define CONFIG_KEYBOARD_KEYPAD +#endif #define CONFIG_PWM_KBLIGHT /* LED defines */ @@ -44,7 +68,7 @@ /* PWM */ #define CONFIG_PWM -#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ /* Temp sensor */ #define CONFIG_TEMP_SENSOR @@ -54,8 +78,9 @@ /* USB */ #define CONFIG_BC12_DETECT_PI3USB9201 -#define CONFIG_USBC_RETIMER_NB7V904M #define CONFIG_USBC_RETIMER_PS8802 +#define CONFIG_USB_MUX_PS8743 +#define CONFIG_USB_MUX_RUNTIME_CONFIG /* Common USB-A defines */ #define USB_PORT_COUNT 2 @@ -82,36 +107,55 @@ #define CONFIG_USB_PD_5V_EN_CUSTOM /* I2C configuration */ -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 #define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* TODO(b:147440290): Need to handle multiple charger ICs */ -#define I2C_PORT_CHARGER I2C_PORT_USB_C0 +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 -#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_ACCEL I2C_PORT_SENSOR #define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ +/* + * I2C pin names for baseboard + * + * Note: these lines will be set as i2c on start-up, but this should be + * okay since they're ODL. + */ +#define GPIO_EC_I2C_SUB_USB_C1_SCL GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL +#define GPIO_EC_I2C_SUB_USB_C1_SDA GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL + /* Sensors */ #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_ACCEL_BMA255 /* Lid accel */ -#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#ifdef BOARD_MAGOLOR +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel second source*/ +#endif /* Lid operates in forced mode, base in FIFO */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) #define CONFIG_ACCEL_FIFO -#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#ifdef BOARD_MAGOLOR +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#endif + #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL @@ -121,9 +165,6 @@ #define CONFIG_TABLET_MODE_SWITCH #define CONFIG_GMR_TABLET_MODE -#define CONFIG_MKBP_EVENT -#define CONFIG_MKBP_USE_GPIO - /* Volume Button feature */ #define CONFIG_ADC_BUTTONS #define CONFIG_VOLUME_BUTTONS @@ -142,25 +183,16 @@ enum chg_id { }; enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_SUB_ANALOG, /* ADC2 */ - ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_VSNS_PP3300_A, /* ADC9 */ ADC_CH_COUNT }; -enum temp_sensor_id { - TEMP_SENSOR_1, - TEMP_SENSOR_2, - TEMP_SENSOR_COUNT -}; +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; enum pwm_channel { PWM_CH_KBLIGHT, @@ -168,11 +200,18 @@ enum pwm_channel { }; enum battery_type { + BATTERY_AP19B8M, + BATTERY_AP18C7M, BATTERY_LGC_AP18C8K, BATTERY_MURATA_AP18C4K, + BATTERY_COSMX_AP20CBL, + BATTERY_COSMX_AP20CBL_004, BATTERY_TYPE_COUNT, }; -int board_is_sourcing_vbus(int port); +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void motion_interrupt(enum gpio_signal signal); +void pen_detect_interrupt(enum gpio_signal s); #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/magolor/build.mk b/board/magolor/build.mk index 3cbadc55d7..c69e903608 100644 --- a/board/magolor/build.mk +++ b/board/magolor/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,7 +8,13 @@ CHIP:=npcx CHIP_FAMILY:=npcx7 +# A limited Magolor_legacy boards are reworked with NPCX796FC variant. +# Set the modify the variant type to match. +ifeq ($(BOARD),magolor_legacy) CHIP_VARIANT:=npcx7m6fc +else +CHIP_VARIANT:=npcx7m7fc +endif BASEBOARD:=dedede -board-y=board.o battery.o led.o usb_pd_policy.o +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/magolor/cbi_ssfc.c b/board/magolor/cbi_ssfc.c new file mode 100644 index 0000000000..155ecae6bf --- /dev/null +++ b/board/magolor/cbi_ssfc.c @@ -0,0 +1,41 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} + +enum ec_ssfc_usb_mux get_cbi_ssfc_usb_mux(void) +{ + return (enum ec_ssfc_usb_mux)cached_ssfc.usb_mux; +} diff --git a/board/magolor/cbi_ssfc.h b/board/magolor/cbi_ssfc.h new file mode 100644 index 0000000000..78e32f5810 --- /dev/null +++ b/board/magolor/cbi_ssfc.h @@ -0,0 +1,80 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +/* + * Usb Mux (Bits 20-21) + */ +enum ec_ssfc_usb_mux { + SSFC_USBMUX_PS8762 = 0, + SSFC_USBMUX_PS8743 = 1, +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t cam_wfc : 3; + uint32_t cam_ufc : 2; + uint32_t cam_vcm : 2; + uint32_t TS_Source : 4; + uint32_t AUDIO_CODEC_SOURCE : 3; + uint32_t usb_mux : 2; + uint32_t reserved_2 : 10; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +/** + * Get the Usb Mux type from SSFC_CONFIG. + * + * @return the Usb Mux board type. + */ +enum ec_ssfc_usb_mux get_cbi_ssfc_usb_mux(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/magolor/ec.tasklist b/board/magolor/ec.tasklist index 0aba1fabeb..ba5855412d 100644 --- a/board/magolor/ec.tasklist +++ b/board/magolor/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/magolor/gpio.inc b/board/magolor/gpio.inc index 68861fa7f7..77cf523de1 100644 --- a/board/magolor/gpio.inc +++ b/board/magolor/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -26,7 +26,8 @@ GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) /* USB-C interrupts */ GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) -GPIO_INT(SUB_USB_C1_INT_ODL, PIN(F, 5), GPIO_INT_FALLING | GPIO_PULL_UP, sub_usb_c1_interrupt) +GPIO_INT(SUB_C1_INT_EN_RAILS_ODL, PIN(F, 5), GPIO_INT_FALLING | GPIO_PULL_UP, sub_usb_c1_interrupt) /* C1 interrupt OR 5V power en */ +GPIO_INT(EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, PIN(9, 1), GPIO_INT_BOTH, sub_hdmi_hpd_interrupt) /* C1 I2C SDA OR HDMI_HPD */ /* Button interrupts */ GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) @@ -34,8 +35,9 @@ GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_butt /* Other interrupts */ GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) -GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) GPIO_INT(LID_360_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(PEN_DET_ODL, PIN(5, 0), GPIO_INT_BOTH, pen_detect_interrupt) /* I2C Ports */ GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) @@ -46,8 +48,7 @@ GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT) GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT) GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) -GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) -GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, PIN(9, 2), GPIO_INPUT) /* C1 I2C SCL OR HDMI en */ /* Extra Sub-board I/O pins */ @@ -57,14 +58,14 @@ GPIO(EC_SUB_IO_2, PIN(3, 4), GPIO_OUT_LOW) GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) /* TODO(b:149775160) - Modify if needed if we ever use this signal. */ GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) -GPIO(EN_PP3300_PEN, PIN(6, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_PEN, PIN(6, 3), GPIO_OUT_LOW) GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) GPIO(EN_KB_BL, PIN(6, 0), GPIO_OUT_LOW) GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) -GPIO(IMVP9_PE, PIN(E, 0), GPIO_OUT_LOW) GPIO(ECH1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_VIVALDIKEYBOARD_ID, PIN(4, 0), GPIO_INPUT + GPIO_PULL_DOWN) /* keyboard ID */ /* LED */ GPIO(LED_B_ODL, PIN(C, 2), GPIO_OUT_HIGH) /* PWM_CH_LED2_BLUE */ @@ -86,7 +87,7 @@ GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) -GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) /* USB pins */ GPIO(USB_C0_RST_ODL, PIN(9, 7), GPIO_OUT_HIGH) /* currently unused */ @@ -133,3 +134,15 @@ ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/magolor/led.c b/board/magolor/led.c index e682e5fd48..2076532142 100644 --- a/board/magolor/led.c +++ b/board/magolor/led.c @@ -1,44 +1,50 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Magolor */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: diff --git a/board/magolor/usb_pd_policy.c b/board/magolor/usb_pd_policy.c index bcdf8300c5..2bad4d6931 100644 --- a/board/magolor/usb_pd_policy.c +++ b/board/magolor/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,11 +7,12 @@ #include "chipset.h" #include "common.h" #include "console.h" +#include "driver/charger/isl923x_public.h" #include "driver/tcpm/tcpci.h" #include "usb_pd.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -24,11 +25,6 @@ void pd_power_supply_reset(int port) /* Disable VBUS */ tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -54,10 +50,9 @@ int pd_set_power_supply_ready(int port) if (rv) return rv; -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/board/magolor/vif_override.xml b/board/magolor/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/magolor/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/makomo/battery.c b/board/makomo/battery.c new file mode 100644 index 0000000000..1f5be3dbe3 --- /dev/null +++ b/board/makomo/battery.c @@ -0,0 +1,104 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "gpio.h" + +const struct board_batt_params board_battery_info[] = { + /* LGC L20L3PG2, Gauge IC: RAJ240047A20DNP. */ + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "LGC", + .device_name = "L20L3PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 73, + }, + }, + /* Sunwoda L20D3PG2, Gauge IC: BQ40Z697A. */ + [BATTERY_SUNWODA] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "L20D3PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11250, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* SIMPLO L20M3PG2, Gauge IC: BQ40Z697A. */ + [BATTERY_SMP] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L20M3PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + }, + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11250, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -40, + .discharging_max_c = 73, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC; + +enum battery_present battery_hw_present(void) +{ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/makomo/board.c b/board/makomo/board.c new file mode 100644 index 0000000000..ff6a8c19d5 --- /dev/null +++ b/board/makomo/board.c @@ -0,0 +1,579 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "backlight.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/battery/max17055.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/fusb302.h" +#include "driver/usb_mux/it5205.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "i2c_bitbang.h" +#include "it8801.h" +#include "keyboard_backlight.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "panic.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "spi.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpm.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +static void tcpc_alert_event(enum gpio_signal signal) +{ + schedule_deferred_pd_interrupt(0 /* port */); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct i2c_port_t i2c_bitbang_ports[] = { + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, +}; +const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); + +#define BC12_I2C_ADDR PI3USB9201_I2C_ADDR_3 + +/* power signal list. Must match order of enum power_signal. */ +const struct power_signal_info power_signal_list[] = { + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, +}; +BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* + * TODO(b/133200075): Tune this once we have the final performance + * out of the driver and the i2c bus. + */ + .output_settle_us = 35, + .debounce_down_us = 5 * MSEC, + .debounce_up_us = 40 * MSEC, + .scan_period_us = 10 * MSEC, + .min_post_scan_delay_us = 10 * MSEC, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { + [0] = { + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, + .drv = &it8801_ioexpander_drv, + }, +}; + +/******************************************************************************/ +/* SPI devices */ +const struct spi_device_t spi_devices[] = { + { CONFIG_SPI_ACCEL_PORT, 2, GPIO_EC_SENSOR_SPI_NSS }, +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/******************************************************************************/ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, + }, + .drv = &fusb302_tcpm_drv, + }, +}; + +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) +{ + /* This driver does not use host command ACKs */ + *ack_required = false; + + /* + * svdm_dp_attention() did most of the work, we only need to notify + * host here. + */ + host_set_single_event(EC_HOST_EVENT_USB_MUX); +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, + }, +}; + +/* Charger config. Start i2c address at 1, update during runtime */ +struct charger_config_t chg_chips[] = { + { + .i2c_port = 1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* Board version depends on ADCs, so init i2c port after ADC */ +static void charger_config_complete(void) +{ + chg_chips[0].i2c_port = board_get_charger_i2c(); +} +DECLARE_HOOK(HOOK_INIT, charger_config_complete, HOOK_PRIO_INIT_ADC + 1); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} + +static int force_discharge; + +int board_set_active_charge_port(int charge_port) +{ + CPRINTS("New chg p%d", charge_port); + + /* ignore all request when discharge mode is on */ + if (force_discharge && charge_port != CHARGE_PORT_NONE) + return EC_SUCCESS; + + switch (charge_port) { + case CHARGE_PORT_USB_C: + /* Don't charge from a source port */ + if (board_vbus_source_enabled(charge_port)) + return -1; + break; + default: + /* + * To ensure the fuel gauge (max17055) is always powered + * even when battery is disconnected, keep VBAT rail on but + * set the charging current to minimum. + */ + charger_set_current(CHARGER_SOLO, 0); + break; + } + + return EC_SUCCESS; +} + +int board_discharge_on_ac(int enable) +{ + int ret, port; + + if (enable) { + port = CHARGE_PORT_NONE; + } else { + /* restore the charge port state */ + port = charge_manager_get_override(); + if (port == OVERRIDE_OFF) + port = charge_manager_get_active_charge_port(); + } + + ret = charger_discharge_on_ac(enable); + if (ret) + return ret; + + force_discharge = enable; + return board_set_active_charge_port(port); +} + +int pd_snk_is_vbus_provided(int port) +{ + /* TODO(b:138352732): read IT8801 GPIO EN_USBC_CHARGE_L */ + return EC_ERROR_UNIMPLEMENTED; +} + +void bc12_interrupt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +#ifndef VARIANT_KUKUI_NO_SENSORS +static void board_spi_enable(void) +{ + /* + * Pin mux spi peripheral away from emmc, since RO might have + * left them there. + */ + gpio_config_module(MODULE_SPI_FLASH, 0); + + /* Enable clocks to SPI2 module. */ + STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; + + /* Reset SPI2 to clear state left over from the emmc slave. */ + STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; + STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; + + /* Reinitialize spi peripheral. */ + spi_enable(&spi_devices[0], 1); + + /* Pin mux spi peripheral toward the sensor. */ + gpio_config_module(MODULE_SPI_CONTROLLER, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, + MOTION_SENSE_HOOK_PRIO - 1); + +static void board_spi_disable(void) +{ + /* Set pins to a state calming the sensor down. */ + gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); + gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); + + /* Disable spi peripheral and clocks. */ + spi_enable(&spi_devices[0], 0); + STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, + MOTION_SENSE_HOOK_PRIO + 1); +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + +static void board_init(void) +{ + /* If the reset cause is external, pulse PMIC force reset. */ + if (system_get_reset_flags() == EC_RESET_FLAG_RESET_PIN) { + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 0); + msleep(100); + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 1); + } + + /* Enable TCPC alert interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + +#ifndef VARIANT_KUKUI_NO_SENSORS + /* Enable interrupts from BMI160 sensor. */ + gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); + + /* For some reason we have to do this again in case of sysjump */ + board_spi_enable(); +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + + /* Enable interrupt from PMIC. */ + gpio_enable_interrupt(GPIO_PMIC_EC_RESETB); + + /* Enable BC12 interrupt */ + gpio_enable_interrupt(GPIO_BC12_EC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +#ifndef VARIANT_KUKUI_NO_SENSORS +/* Motion sensors */ +/* Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Rotation matrixes */ +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* sensor private data */ +/* Lid accel private data */ +static struct stprivate_data g_lis2dwl_data; +/* Base accel private data */ +static struct bmi_drv_data_t g_bmi160_data; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DWL, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2dwl_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +const struct it8801_pwm_t it8801_pwm_channels[] = { + [IT8801_PWM_CH_KBLIGHT] = { .index = 4 }, +}; + +void board_kblight_init(void) +{ + kblight_register(&kblight_it8801); +} + +bool board_has_kb_backlight(void) +{ + /* Default enable keyboard backlight */ + return true; +} +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + +/* Battery functions */ +#define SB_SMARTCHARGE 0x26 +/* Quick charge enable bit */ +#define SMART_QUICK_CHARGE 0x02 +/* Quick charge support bit */ +#define MODE_QUICK_CHARGE_SUPPORT 0x01 + +static void sb_quick_charge_mode(int enable) +{ + int val, rv; + + rv = sb_read(SB_SMARTCHARGE, &val); + if (rv || !(val & MODE_QUICK_CHARGE_SUPPORT)) + return; + + if (enable) + val |= SMART_QUICK_CHARGE; + else + val &= ~SMART_QUICK_CHARGE; + + sb_write(SB_SMARTCHARGE, val); +} + +/* Called on AP S0iX -> S0 transition */ +static void board_chipset_resume(void) +{ +#ifndef VARIANT_KUKUI_NO_SENSORS + if (board_has_kb_backlight()) + ioex_set_level(IOEX_KB_BL_EN, 1); +#endif + + /* Normal charge mode */ + sb_quick_charge_mode(0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S0iX transition */ +static void board_chipset_suspend(void) +{ +#ifndef VARIANT_KUKUI_NO_SENSORS + if (board_has_kb_backlight()) + ioex_set_level(IOEX_KB_BL_EN, 0); +#endif + + /* Quick charge mode */ + sb_quick_charge_mode(1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S5 -> S3 transition */ +static void board_chipset_startup(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S5 transition */ +static void board_chipset_shutdown(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); + +int board_get_charger_i2c(void) +{ + /* TODO(b:138415463): confirm the bus allocation for future builds */ + return board_get_version() == 1 ? 2 : 1; +} + +int board_get_battery_i2c(void) +{ + return board_get_version() >= 1 ? 2 : 1; +} + +#ifdef SECTION_IS_RW +static int it8801_get_target_channel(enum pwm_channel *channel, int type, + int index) +{ + switch (type) { + case EC_PWM_TYPE_GENERIC: + *channel = index; + break; + default: + return -1; + } + + return *channel >= 1; +} + +static enum ec_status +host_command_pwm_set_duty(struct host_cmd_handler_args *args) +{ + const struct ec_params_pwm_set_duty *p = args->params; + enum pwm_channel channel; + uint16_t duty; + + if (it8801_get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + duty = (uint32_t)p->duty * 255 / 65535; + it8801_pwm_set_raw_duty(channel, duty); + it8801_pwm_enable(channel, p->duty > 0); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_DUTY, host_command_pwm_set_duty, + EC_VER_MASK(0)); + +static enum ec_status +host_command_pwm_get_duty(struct host_cmd_handler_args *args) +{ + const struct ec_params_pwm_get_duty *p = args->params; + struct ec_response_pwm_get_duty *r = args->response; + + enum pwm_channel channel; + + if (it8801_get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + r->duty = (uint32_t)it8801_pwm_get_raw_duty(channel) * 65535 / 255; + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_DUTY, host_command_pwm_get_duty, + EC_VER_MASK(0)); +#endif diff --git a/board/makomo/board.h b/board/makomo/board.h new file mode 100644 index 0000000000..e05e15c13d --- /dev/null +++ b/board/makomo/board.h @@ -0,0 +1,158 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Configuration for Makomo */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KUKUI_JACUZZI +#define VARIANT_KUKUI_BATTERY_SMART +#define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32F098 + +#ifndef SECTION_IS_RW +#define VARIANT_KUKUI_NO_SENSORS +#undef CONFIG_CMD_MFALLOW +#endif /* SECTION_IS_RW */ + +#include "baseboard.h" + +#undef CONFIG_CHIPSET_POWER_SEQ_VERSION +#define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 +#undef CONFIG_SYSTEM_UNLOCKED + +#define CONFIG_BATTERY_HW_PRESENT_CUSTOM + +#define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +#define CONFIG_CHARGER_RUNTIME_CONFIG + +#define CONFIG_BC12_DETECT_PI3USB9201 + +#define CONFIG_EXTPOWER_GPIO +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 200 + +#define CONFIG_I2C_BITBANG +#undef I2C_BITBANG_PORT_COUNT +#define I2C_BITBANG_PORT_COUNT 1 +#undef CONFIG_I2C_NACK_RETRY_COUNT +#define CONFIG_I2C_NACK_RETRY_COUNT 10 +#define CONFIG_SMBUS_PEC + +#define CONFIG_USB_PD_TCPM_FUSB302 +#define CONFIG_USB_PD_DISCHARGE_GPIO +#define CONFIG_USB_PD_TCPC_LOW_POWER + +#define CONFIG_USB_MUX_IT5205 + +#define CONFIG_LED_ONOFF_STATES + +/* Motion Sensors */ +#ifndef VARIANT_KUKUI_NO_SENSORS +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ALS +#define CONFIG_CMD_ACCEL_INFO + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#ifdef SECTION_IS_RW +#define CONFIG_IO_EXPANDER_IT8801_PWM +#define CONFIG_KEYBOARD_BACKLIGHT +#endif + +#endif /* VARIANT_KUKUI_NO_SENSORS */ + +/* I2C ports */ +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_CHARGER board_get_charger_i2c() +#define I2C_PORT_SENSORS 1 +#define I2C_PORT_KB_DISCRETE 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BATTERY 2 + +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 + +/* Enable Accel over SPI */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ + +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_USE_GPIO + +#ifndef __ASSEMBLER__ + +enum adc_channel { + /* Real ADC channels begin here */ + ADC_BOARD_ID = 0, + ADC_EC_SKU_ID, + ADC_CH_COUNT +}; + +/* power signal definitions */ +enum power_signal { + AP_IN_S3_L, + PMIC_PWR_GOOD, + + /* Number of signals */ + POWER_SIGNAL_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum charge_port { + CHARGE_PORT_USB_C, +}; + +enum battery_type { + BATTERY_LGC, + BATTERY_SUNWODA, + BATTERY_SMP, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { + IT8801_PWM_CH_KBLIGHT = 0, +}; + +#include "gpio_signal.h" +#include "registers.h" + +#ifdef SECTION_IS_RO +/* Interrupt handler for emmc task */ +void emmc_cmd_interrupt(enum gpio_signal signal); +#endif + +void bc12_interrupt(enum gpio_signal signal); +void board_reset_pd_mcu(void); +int board_get_version(void); + +/* returns the i2c port number of charger/battery */ +int board_get_charger_i2c(void); +int board_get_battery_i2c(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/makomo/build.mk b/board/makomo/build.mk new file mode 100644 index 0000000000..5b31bc2d67 --- /dev/null +++ b/board/makomo/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# +# +# STmicro STM32F098VC +CHIP:=stm32 +CHIP_FAMILY:=stm32f0 +CHIP_VARIANT:=stm32f09x +BASEBOARD:=kukui + +board-y=battery.o board.o led.o diff --git a/board/makomo/ec.tasklist b/board/makomo/ec.tasklist new file mode 100644 index 0000000000..23b568cb28 --- /dev/null +++ b/board/makomo/ec.tasklist @@ -0,0 +1,20 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, 1024) \ + TASK_ALWAYS_RO(EMMC, emmc_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/makomo/gpio.inc b/board/makomo/gpio.inc new file mode 100644 index 0000000000..8cbdef529e --- /dev/null +++ b/board/makomo/gpio.inc @@ -0,0 +1,121 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(B, 1), GPIO_INT_FALLING | GPIO_PULL_UP, + tcpc_alert_event) +GPIO_INT(POWER_BUTTON_L, PIN(A, 0), GPIO_INT_BOTH | GPIO_PULL_UP, + power_button_interrupt) /* EC_PWR_BTN_ODL */ +GPIO_INT(AP_IN_SLEEP_L, PIN(C, 12), GPIO_INT_BOTH | GPIO_PULL_DOWN, + power_signal_interrupt) +GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, + power_signal_interrupt) +GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, + chipset_reset_request_interrupt) +GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, + bmi160_interrupt) +GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, + emmc_cmd_interrupt) +GPIO_INT(SPI1_NSS, PIN(A, 15), GPIO_INT_BOTH | GPIO_PULL_UP, + spi_event) /* SPI_AP_EC_CS_L */ +GPIO_INT(LID_OPEN, PIN(C, 5), GPIO_INT_BOTH, + lid_interrupt) +GPIO_INT(AC_PRESENT, PIN(A, 6), GPIO_INT_BOTH, + extpower_interrupt) /* ACOK_OD */ +GPIO_INT(BC12_EC_INT_ODL, PIN(C, 9), GPIO_INT_FALLING, + bc12_interrupt) +GPIO_INT(IT8801_SMB_INT, PIN(A, 8), GPIO_INT_FALLING | GPIO_PULL_UP, + io_expander_it8801_interrupt) /* KB_INT_ODL */ +GPIO_INT(AP_EC_WATCHDOG_L, PIN(D, 2), GPIO_INT_FALLING, + chipset_watchdog_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(B, 11), GPIO_INT_BOTH, + gmr_tablet_switch_isr) + +/* Unimplemented interrupts */ +GPIO(ALS_RGB_INT_ODL, PIN(C, 10), GPIO_INPUT) + +/* Reset pins */ +GPIO(AP_SYS_RST_L, PIN(C, 11), GPIO_OUT_LOW) +GPIO(PMIC_WATCHDOG_L, PIN(A, 2), GPIO_OUT_LOW) +GPIO(PMIC_EN_ODL, PIN(F, 0), GPIO_ODR_HIGH) + +/* + * I2C pins should be configured as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(I2C1_SCL, PIN(B, 8), GPIO_INPUT) +GPIO(I2C1_SDA, PIN(B, 9), GPIO_INPUT) +GPIO(I2C2_SCL, PIN(A, 11), GPIO_INPUT) +GPIO(I2C2_SDA, PIN(A, 12), GPIO_INPUT) +GPIO(I2C3_SCL, PIN(A, 5), GPIO_ODR_HIGH) +GPIO(I2C3_SDA, PIN(C, 4), GPIO_ODR_HIGH) + +/* Analog pins */ +GPIO(BOARD_ID, PIN(C, 0), GPIO_ANALOG) +GPIO(EC_SKU_ID, PIN(B, 0), GPIO_ANALOG) + +/* Other input pins */ +GPIO(WP_L, PIN(C, 8), GPIO_INPUT) /* EC_FLASH_WP_ODL */ +GPIO(BOOT0, PIN(F, 11), GPIO_INPUT) +GPIO(CCD_MODE_ODL, PIN(A, 1), GPIO_INPUT) + +/* Other output pins */ +GPIO(EC_BATT_PRES_ODL, PIN(A, 7), GPIO_INPUT) +GPIO(EC_BL_EN_OD, PIN(A, 13), GPIO_ODR_HIGH) +GPIO(EN_USBA_5V, PIN(C, 14), GPIO_OUT_LOW) +GPIO(EC_SENSOR_SPI_MISO, PIN(C, 2), GPIO_INPUT) +GPIO(EC_SENSOR_SPI_MOSI, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_SENSOR_SPI_NSS, PIN(B, 12), GPIO_OUT_HIGH) +GPIO(EC_SENSOR_SPI_CK, PIN(B, 10), GPIO_OUT_LOW) +GPIO(ENTERING_RW, PIN(C, 6), GPIO_ODR_HIGH) /* EC_ENTERING_RW_ODL */ +GPIO(EC_INT_L, PIN(C, 7), GPIO_ODR_HIGH) /* EC_AP_INT_ODL */ +GPIO(EC_BOARD_ID_EN_L, PIN(C, 15), GPIO_ODR_HIGH) /* EC_BOARD_ID_EN_ODL */ +GPIO(USB_C0_HPD_OD, PIN(F, 1), GPIO_ODR_LOW) +GPIO(BOOTBLOCK_EN_L, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EN_PP1800_S5_L, PIN(A, 14), GPIO_OUT_LOW) +GPIO(USB_C0_DISCHARGE, PIN(B, 6), GPIO_OUT_LOW) + +IOEX(PWR_LED_WHITE_L, EXPIN(0, 1, 4), GPIO_OUT_HIGH) +IOEX(BAT_LED_GREEN_FULL_L, EXPIN(0, 1, 3), GPIO_OUT_HIGH) +IOEX(BAT_LED_RED_L, EXPIN(0, 1, 2), GPIO_OUT_HIGH) +IOEX(KB_BL_EN, EXPIN(0, 0, 7), GPIO_OUT_LOW) + +/* + * TODO(b:138352732): On IT88801 expander, To be readded once IT8801 driver and + * gpio expander framework has landed. + */ +UNIMPLEMENTED(EN_PP5000_USBC) +UNIMPLEMENTED(PMIC_FORCE_RESET_ODL) +UNIMPLEMENTED(EN_USBC_CHARGE_L) + +/* USART1: PA9/PA10 */ +ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, 0) +/* I2C MASTER: PB8/9 */ +ALTERNATE(PIN_MASK(B, 0x0300), 1, MODULE_I2C, GPIO_ODR_HIGH ) +/* I2C MASTER: PA11/12 */ +ALTERNATE(PIN_MASK(A, 0x1800), 5, MODULE_I2C, GPIO_ODR_HIGH ) + + +/* SPI1 */ +/* SPI SLAVE: PB3/4/5 */ +ALTERNATE(PIN_MASK(B, 0x0038), 0, MODULE_SPI, 0) +/* SPI SLAVE CS: PA15 */ +ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) + +/* SPI2 */ +/* Shared between slave for emmc and master for bmi160 */ +/* They're mutually exclusive with gpio_config_module. */ +/* EMMC SPI SLAVE: PB13/14/15 */ +ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) +/* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/makomo/led.c b/board/makomo/led.c new file mode 100644 index 0000000000..d0a7f7165c --- /dev/null +++ b/board/makomo/led.c @@ -0,0 +1,120 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Makomo + */ +#include "common.h" +#include "driver/ioexpander/it8801.h" +#include "ec_commands.h" +#include "ioexpander.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_GREEN: + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_ON_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_ON_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_ON_LVL); + break; + case EC_LED_COLOR_RED: + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_OFF_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_OFF_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_OFF_LVL); + break; + } +} + +__override void led_set_color_power(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + ioex_set_level(IOEX_PWR_LED_WHITE_L, LED_ON_LVL); + break; + default: + ioex_set_level(IOEX_PWR_LED_WHITE_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_RED] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_battery(EC_LED_COLOR_RED); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } else { + return EC_ERROR_INVAL; + } + return EC_SUCCESS; +} diff --git a/board/makomo/vif_override.xml b/board/makomo/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/makomo/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/malefor/battery.c b/board/malefor/battery.c deleted file mode 100644 index 7f37c6fe10..0000000000 --- a/board/malefor/battery.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery_fuel_gauge.h" -#include "common.h" -#include "util.h" - -/* - * Battery info for all Volteer battery types. Note that the fields - * start_charging_min/max and charging_min/max are not used for the charger. - * The effective temperature limits are given by discharging_min/max_c. - * - * Fuel Gauge (FG) parameters which are used for determining if the battery - * is connected, the appropriate ship mode (battery cutoff) command, and the - * charge/discharge FETs status. - * - * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery - * register. For some batteries, the charge/discharge FET bits are set when - * charging/discharging is active, in other types, these bits set mean that - * charging/discharging is disabled. Therefore, in addition to the mask for - * these bits, a disconnect value must be specified. Note that for TI fuel - * gauge, the charge/discharge FET status is found in Operation Status (0x54), - * but a read of Manufacturer Access (0x00) will return the lower 16 bits of - * Operation status which contains the FET status bits. - * - * The assumption for battery types supported is that the charge/discharge FET - * status can be read with a sb_read() command and therefore, only the register - * address, mask, and disconnect value need to be provided. - */ -const struct board_batt_params board_battery_info[] = { - [BATTERY_SMP] = { - .fuel_gauge = { - .manuf_name = "SMP", - .device_name = "L19M4PG2", - .ship_mode = { - .reg_addr = 0x34, - .reg_data = { 0x0000, 0x1000 }, - }, - .fet = { - .reg_addr = 0x34, - .reg_mask = 0x0100, - .disconnect_val = 0x0100, - } - }, - .batt_info = { - .voltage_max = 8800, /* mV */ - .voltage_normal = 7680, /* mV */ - .voltage_min = 6000, /* mV */ - .precharge_current = 332, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, - }, - [BATTERY_LGC] = { - .fuel_gauge = { - .manuf_name = "LGC", - .device_name = "L19L4PG2", - .ship_mode = { - .reg_addr = 0x34, - .reg_data = { 0x0000, 0x1000 }, - }, - .fet = { - .reg_addr = 0x34, - .reg_mask = 0x0100, - .disconnect_val = 0x0100, - } - }, - .batt_info = { - .voltage_max = 8800, /* mV */ - .voltage_normal = 7700, /* mV */ - /* - * voltage min value and precharge current value are - * specified by LGC directly and not shown in the SPEC. - */ - .voltage_min = 6000, /* mV */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 73, - }, - }, - [BATTERY_SUNWODA] = { - .fuel_gauge = { - .manuf_name = "SUNWODA", - .device_name = "L19D4PG2", - .ship_mode = { - .reg_addr = 0x34, - .reg_data = { 0x0000, 0x1000 }, - }, - .fet = { - .reg_addr = 0x34, - .reg_mask = 0x0100, - .disconnect_val = 0x0100, - } - }, - .batt_info = { - .voltage_max = 8800, /* mV */ - .voltage_normal = 7680, /* mV */ - .voltage_min = 6000, /* mV */ - .precharge_current = 333, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 60, - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); - -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP; diff --git a/board/malefor/board.c b/board/malefor/board.c deleted file mode 100644 index 2532369dc8..0000000000 --- a/board/malefor/board.c +++ /dev/null @@ -1,599 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Malefor board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "cbi_ec_fw_config.h" -#include "common.h" -#include "driver/accel_lis2dh.h" -#include "driver/accelgyro_lsm6dsm.h" -#include "driver/bc12/pi3usb9201.h" -#include "driver/ppc/sn5s330.h" -#include "driver/ppc/syv682x.h" -#include "driver/sync.h" -#include "driver/tcpm/ps8xxx.h" -#include "driver/tcpm/tcpci.h" -#include "driver/tcpm/tusb422.h" -#include "extpower.h" -#include "fan.h" -#include "fan_chip.h" -#include "gpio.h" -#include "hooks.h" -#include "keyboard_scan.h" -#include "lid_switch.h" -#include "power.h" -#include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "tablet_mode.h" -#include "uart.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "usbc_ppc.h" -#include "util.h" - -#include "gpio_list.h" /* Must come after other header files. */ - -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { - /* Increase from 50 us, because KSO_02 passes through the H1. */ - .output_settle_us = 80, - /* Other values should be the same as the default configuration. */ - .debounce_down_us = 9 * MSEC, - .debounce_up_us = 30 * MSEC, - .scan_period_us = 3 * MSEC, - .min_post_scan_delay_us = 1000, - .poll_timeout_us = 100 * MSEC, - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ - }, -}; - -/******************************************************************************/ -/* - * FW_CONFIG defaults for Malefor if the CBI data is not initialized. - */ -union volteer_cbi_fw_config fw_config_defaults = { - .usb_db = DB_USB3_NO_A, -}; - -static void board_init(void) -{ - if (ec_cfg_has_tabletmode()) { - /* Enable gpio interrupt for base accelgyro sensor */ - gpio_enable_interrupt(GPIO_EC_IMU_INT_L); - } else { - motion_sensor_count = 0; - /* Device is clamshell only */ - tablet_set_mode(0); - /* Gyro is not present, don't allow line to float */ - gpio_set_flags(GPIO_EC_IMU_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); - } - - /* - * TODO: b/154447182 - Malefor will control power LED and battery LED - * independently, and keep the max brightness of power LED and battery - * LED as 50%. - */ - pwm_enable(PWM_CH_LED4_SIDESEL, 1); - pwm_set_duty(PWM_CH_LED4_SIDESEL, 50); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -int board_is_lid_angle_tablet_mode(void) -{ - return ec_cfg_has_tabletmode(); -} - -/* Enable or disable input devices, based on tablet mode or chipset state */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - if (ec_cfg_has_tabletmode()) { - if (chipset_in_state(CHIPSET_STATE_ANY_OFF) || - tablet_get_mode()) - enable = 0; - keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif - -/******************************************************************************/ -/* Sensors */ -/* Lid and base Sensor mutex */ -static struct mutex g_lid_accel_mutex; -static struct mutex g_base_mutex; - -/* Lid and base accel private data */ -static struct stprivate_data g_lis2dh_data; -static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; - -/* Matrix to rotate lid and base sensor into standard reference frame */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -struct motion_sensor_t motion_sensors[] = { - [LID_ACCEL] = { - .name = "Lid Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LIS2DE, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &lis2dh_drv, - .mutex = &g_lid_accel_mutex, - .drv_data = &g_lis2dh_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = LIS2DH_ADDR1_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .min_frequency = LIS2DH_ODR_MIN_VAL, - .max_frequency = LIS2DH_ODR_MAX_VAL, - .default_range = 2, /* g, to support tablet mode */ - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - /* Sensor on in S3 */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - }, - }, - - [BASE_ACCEL] = { - .name = "Base Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LSM6DSM, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6dsm_drv, - .mutex = &g_base_mutex, - .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, - MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_EC_IMU_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .rot_standard_ref = &base_standard_ref, - .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ - .min_frequency = LSM6DSM_ODR_MIN_VAL, - .max_frequency = LSM6DSM_ODR_MAX_VAL, - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 13000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - /* Sensor on for angle detection */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, - }, - - [BASE_GYRO] = { - .name = "Base Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_LSM6DSM, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6dsm_drv, - .mutex = &g_base_mutex, - .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, - MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_EC_IMU_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .default_range = 1000 | ROUND_UP_FLAG, /* dps */ - .rot_standard_ref = &base_standard_ref, - .min_frequency = LSM6DSM_ODR_MIN_VAL, - .max_frequency = LSM6DSM_ODR_MAX_VAL, - }, -}; -unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -/******************************************************************************/ -/* Physical fans. These are logically separate from pwm_channels. */ - -const struct fan_conf fan_conf_0 = { - .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ - .pgood_gpio = -1, - .enable_gpio = GPIO_EN_PP5000_FAN, -}; - -/* - * Fan specs from datasheet: - * Max speed 5900 rpm (+/- 7%), minimum duty cycle 30%. - * Minimum speed not specified by RPM. Set minimum RPM to max speed (with - * margin) x 30%. - * 5900 x 1.07 x 0.30 = 1894, round up to 1900 - */ -const struct fan_rpm fan_rpm_0 = { - .rpm_min = 1900, - .rpm_start = 1900, - .rpm_max = 5900, -}; - -const struct fan_t fans[FAN_CH_COUNT] = { - [FAN_CH_0] = { - .conf = &fan_conf_0, - .rpm = &fan_rpm_0, - }, -}; - -/******************************************************************************/ -/* EC thermal management configuration */ - -/* - * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at - * 130 C. However, sensor is located next to DDR, so we need to use the lower - * DDR temperature limit (85 C) - */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; - -/* - * Inductor limits - used for both charger and PP3300 regulator - * - * Need to use the lower of the charger IC, PP3300 regulator, and the inductors - * - * Charger max recommended temperature 100C, max absolute temperature 125C - * PP3300 regulator: operating range -40 C to 145 C - * - * Inductors: limit of 125c - * PCB: limit is 80c - */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - - -struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, -}; -BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); - -/******************************************************************************/ -/* MFT channels. These are logically separate from pwm_channels. */ -const struct mft_t mft_channels[] = { - [MFT_CH_0] = { - .module = NPCX_MFT_MODULE_1, - .clk_src = TCKC_LFCLK, - .pwm_id = PWM_CH_FAN, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); - -/******************************************************************************/ -/* I2C port map configuration */ -const struct i2c_port_t i2c_ports[] = { - { - .name = "sensor", - .port = I2C_PORT_SENSOR, - .kbps = 400, - .scl = GPIO_EC_I2C0_SENSOR_SCL, - .sda = GPIO_EC_I2C0_SENSOR_SDA, - }, - { - .name = "usb_c0", - .port = I2C_PORT_USB_C0, - .kbps = 1000, - .scl = GPIO_EC_I2C1_USB_C0_SCL, - .sda = GPIO_EC_I2C1_USB_C0_SDA, - }, - { - .name = "usb_c1", - .port = I2C_PORT_USB_C1, - .kbps = 1000, - .scl = GPIO_EC_I2C2_USB_C1_SCL, - .sda = GPIO_EC_I2C2_USB_C1_SDA, - }, - { - .name = "usb_1_mix", - .port = I2C_PORT_USB_1_MIX, - .kbps = 100, - .scl = GPIO_EC_I2C3_USB_1_MIX_SCL, - .sda = GPIO_EC_I2C3_USB_1_MIX_SDA, - }, - { - .name = "power", - .port = I2C_PORT_POWER, - .kbps = 100, - .scl = GPIO_EC_I2C5_POWER_SCL, - .sda = GPIO_EC_I2C5_POWER_SDA, - }, - { - .name = "eeprom", - .port = I2C_PORT_EEPROM, - .kbps = 400, - .scl = GPIO_EC_I2C7_EEPROM_SCL, - .sda = GPIO_EC_I2C7_EEPROM_SDA, - }, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/******************************************************************************/ -/* PWM configuration */ -const struct pwm_t pwm_channels[] = { - [PWM_CH_LED4_SIDESEL] = { - .channel = 7, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - /* Run at a higher frequency than the color PWM signals to avoid - * timing-based color shifts. - */ - .freq = 4800, - }, - [PWM_CH_FAN] = { - .channel = 5, - .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000 - }, - [PWM_CH_KBLIGHT] = { - .channel = 3, - .flags = 0, - /* - * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent - * flicker. Higher frequencies consume similar average power to - * lower PWM frequencies, but higher frequencies record a much - * lower maximum power. - */ - .freq = 2400, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -/* USBC TCPC configuration for port 1 on USB3 board */ -static const struct tcpc_config_t tcpc_config_p1_usb3 = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .flags = TCPC_FLAGS_TCPCI_REV2_0 | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, - .drv = &ps8xxx_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), -}; - -static const struct usb_mux usbc1_usb3_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .next_mux = NULL, -}; - -static const struct usb_mux mux_config_p1_usb3 = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb3_db_retimer, -}; - -void board_reset_pd_mcu(void) -{ - int val; - - gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 0); - msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, - PS8815_PWR_H_RST_H_DELAY_MS)); - gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 1); - msleep(PS8815_FW_INIT_DELAY_MS); - - /* - * b/144397088 - * ps8815 firmware 0x01 needs special configuration - */ - - CPRINTS("%s: patching ps8815 registers", __func__); - - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) - CPRINTS("ps8815: reg 0x0f was %02x", val); - - if (i2c_write8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, 0x31) == EC_SUCCESS) - CPRINTS("ps8815: reg 0x0f set to 0x31"); - - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) - CPRINTS("ps8815: reg 0x0f now %02x", val); -} - -__override void board_cbi_init(void) -{ - /* Config DB USB3 */ - tcpc_config[USBC_PORT_C1] = tcpc_config_p1_usb3; - usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3; -} - -/******************************************************************************/ -/* USBC PPC configuration */ -struct ppc_config_t ppc_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -/******************************************************************************/ -/* PPC support routines */ -void ppc_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_PPC_INT_ODL: - sn5s330_interrupt(USBC_PORT_C0); - break; - case GPIO_USB_C1_PPC_INT_ODL: - syv682x_interrupt(USBC_PORT_C1); - default: - break; - } -} - -/******************************************************************************/ -/* BC1.2 charger detect configuration */ -const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC TCPC configuration */ -struct tcpc_config_t tcpc_config[] = { - [USBC_PORT_C0] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C0, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), - }, - [USBC_PORT_C1] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); -BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usb_muxes[] = { - [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); - -struct bb_usb_control bb_controls[] = { - [USBC_PORT_C0] = { - /* USB-C port 0 doesn't have a retimer */ - }, - [USBC_PORT_C1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); - -static void board_tcpc_init(void) -{ - /* Don't reset TCPCs after initial reset */ - if (!system_jumped_late()) - board_reset_pd_mcu(); - - /* Enable PPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); - - /* Enable TCPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); - - /* Enable BC1.2 interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); - -/******************************************************************************/ -/* TCPC support routines */ -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - /* - * Check which port has the ALERT line set - */ - if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} - -int ppc_get_alert_status(int port) -{ - if (port == USBC_PORT_C0) - return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; - else - return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; -} diff --git a/board/malefor/board.h b/board/malefor/board.h deleted file mode 100644 index 321fbc130f..0000000000 --- a/board/malefor/board.h +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Baseboard features */ -#include "baseboard.h" - -/* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ - -#define CONFIG_POWER_BUTTON - -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 4096 - -/* LED defines */ -#define CONFIG_LED_POWER_LED -#define CONFIG_LED_ONOFF_STATES - -/* Keyboard features */ - -/* Sensors */ -#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT -#define CONFIG_ACCEL_LIS2DE /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ - -/* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - BIT(LID_ACCEL) - -#define CONFIG_LID_ANGLE -#define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL - -#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) - -/* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 - -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - -/* - * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C - * cables only support up to 60W. - */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 -/* Enabling USB4 mode */ -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 - -/* USB Type A Features */ - -/* USBC PPC*/ -#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ - -/* BC 1.2 */ - -/* Volume Button feature */ - -/* Fan features */ - -/* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 - -/* - * Macros for GPIO signals used in common code that don't match the - * schematic names. Signal names in gpio.inc match the schematic and are - * then redefined here to so it's more clear which signal is being used for - * which purpose. - */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L - -/* I2C Bus Configuration */ -#define CONFIG_I2C -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM - -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER - - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -enum battery_type { - BATTERY_SMP, - BATTERY_LGC, - BATTERY_SUNWODA, - BATTERY_TYPE_COUNT, -}; - -enum pwm_channel { - PWM_CH_LED4_SIDESEL = 0, - PWM_CH_FAN, - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; - -enum sensor_id { - LID_ACCEL = 0, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT, -}; - -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; - -void board_reset_pd_mcu(void); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/malefor/build.mk b/board/malefor/build.mk deleted file mode 100644 index 279b2e559e..0000000000 --- a/board/malefor/build.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -CHIP:=npcx -CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc -BASEBOARD:=volteer - -board-y=board.o -board-y+=battery.o -board-y+=led.o diff --git a/board/malefor/ec.tasklist b/board/malefor/ec.tasklist deleted file mode 100644 index 292de51cdb..0000000000 --- a/board/malefor/ec.tasklist +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/malefor/gpio.inc b/board/malefor/gpio.inc deleted file mode 100644 index 6144bba66f..0000000000 --- a/board/malefor/gpio.inc +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -/* Wake Source interrupts */ -GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) -GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) -GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) -GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) - -/* Power sequencing interrupts */ -GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) -#endif -GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) - -/* Sensor Interrupts */ -GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) -GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) - -/* USB-C interrupts */ -GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) -GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) - -GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) -GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) - -GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) -GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) - -/* HDMI interrupts */ - -/* Volume button interrupts */ -GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) - -/* Power Sequencing Signals */ -GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) -GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) -GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ -/* The EC does not buffer this signal on Volteer. */ -UNIMPLEMENTED(PCH_DSW_PWROK) - -/* Other wake sources */ -/* - * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an - * interrupt handler because it is automatically handled by the PSL. - * - * We need to lock the setting so this gpio can't be reconfigured to overdrive - * the real reset signal. (This is the PSL input pin not the real reset pin). - */ -GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | - GPIO_HIB_WAKE_HIGH | - GPIO_LOCKED) - -/* AP/PCH Signals */ -GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) -GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ -GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) -GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) -GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) -GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) -GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) -UNIMPLEMENTED(EC_PROCHOT_IN_L) -GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) - -GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) - -/* USB and USBC Signals */ -GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset on boards board ID >=1 */ -GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) -GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) - -/* Don't have a load switch for retimer */ -UNIMPLEMENTED(USB_C1_LS_EN) - -/* Misc Signals */ - -/* - * eDP backlight - both PCH and EC have enable pins that must be high - * for the backlight to turn on. Default state is high, and can be turned - * off during sleep states. - */ -GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) - -/* I2C pins - Alternate function below configures I2C module on these pins */ -GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) -GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) -GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) -GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) -GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) -GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) -GPIO(EC_I2C3_USB_1_MIX_SCL, PIN(D, 1), GPIO_INPUT) -GPIO(EC_I2C3_USB_1_MIX_SDA, PIN(D, 0), GPIO_INPUT) -GPIO(EC_I2C5_POWER_SCL, PIN(3, 3), GPIO_INPUT) -GPIO(EC_I2C5_POWER_SDA, PIN(3, 6), GPIO_INPUT) -GPIO(EC_I2C7_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) -GPIO(EC_I2C7_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) - -/* Battery signals */ -GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) - -/* Physical HPD pins are not needed on EC as these are configured by PMC */ -GPIO(USB_C0_DP_HPD, PIN(F, 3), GPIO_INPUT) -GPIO(USB_C1_DP_HPD, PIN(7, 0), GPIO_INPUT) - -/* LED */ -GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) /* Battery - Green LED */ -GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) /* Battery - Red LED */ -GPIO(LED_3_L, PIN(C, 2), GPIO_OUT_HIGH) /* Power - White LED */ - -/* Alternate functions GPIO definitions */ -ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */ -ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ -ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ -ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ -ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ -ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ - -/* This selects between an LED module on the motherboard and one on the daughter - * board, to be controlled by LED_{1,2,3}_L. PWM allows driving both modules at - * the same time. */ -ALTERNATE(PIN_MASK(6, BIT(0)), 0, MODULE_PWM, 0) /* LED_SIDESEL_4_L */ - -/* Fan signals */ -GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) -ALTERNATE(PIN_MASK(B, BIT(7)), 0, MODULE_PWM, 0) /* FAN_PWM */ -ALTERNATE(PIN_MASK(4, BIT(0)), 0, MODULE_PWM, 0) /* FAN_SPEED_TACH */ - -/* Keyboard pins */ -#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) -ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ -ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ -ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ -GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ -ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ -ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ -ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ -ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ - -/* UART */ -ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ - -/* Power Switch Logic (PSL) inputs */ -ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ -ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, - GPIO01 = H1_EC_PWR_BTN_ODL - GPIO02 = EC_RST_ODL */ - diff --git a/board/malefor/led.c b/board/malefor/led.c deleted file mode 100644 index 6f4e781404..0000000000 --- a/board/malefor/led.c +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Power and battery LED control for Malefor - */ - -#include "common.h" -#include "led_onoff_states.h" -#include "led_common.h" -#include "gpio.h" - -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 - -const int led_charge_lvl_1 = 5; - -const int led_charge_lvl_2 = 97; - -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; - -const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); - -void led_set_color_power(enum ec_led_colors color) -{ - if (color == EC_LED_COLOR_WHITE) - gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); - else - /* LED_OFF and unsupported colors */ - gpio_set_level(GPIO_LED_3_L, LED_OFF_LVL); -} - -void led_set_color_battery(enum ec_led_colors color) -{ - switch (color) { - case EC_LED_COLOR_RED: - gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); - gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); - break; - case EC_LED_COLOR_AMBER: - gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); - gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); - break; - case EC_LED_COLOR_GREEN: - gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); - gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); - break; - default: /* LED_OFF and other unsupported colors */ - gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); - gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); - break; - } -} - -void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) -{ - if (led_id == EC_LED_ID_BATTERY_LED) { - brightness_range[EC_LED_COLOR_RED] = 1; - brightness_range[EC_LED_COLOR_AMBER] = 1; - brightness_range[EC_LED_COLOR_GREEN] = 1; - } else if (led_id == EC_LED_ID_POWER_LED) { - brightness_range[EC_LED_COLOR_WHITE] = 1; - } -} - -int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) -{ - if (led_id == EC_LED_ID_BATTERY_LED) { - if (brightness[EC_LED_COLOR_RED] != 0) - led_set_color_battery(EC_LED_COLOR_RED); - else if (brightness[EC_LED_COLOR_AMBER] != 0) - led_set_color_battery(EC_LED_COLOR_AMBER); - else if (brightness[EC_LED_COLOR_GREEN] != 0) - led_set_color_battery(EC_LED_COLOR_GREEN); - else - led_set_color_battery(LED_OFF); - } else if (led_id == EC_LED_ID_POWER_LED) { - if (brightness[EC_LED_COLOR_WHITE] != 0) - led_set_color_power(EC_LED_COLOR_WHITE); - else - led_set_color_power(LED_OFF); - } - - return EC_SUCCESS; -} diff --git a/board/marasov/battery.c b/board/marasov/battery.c new file mode 100644 index 0000000000..b974930d5b --- /dev/null +++ b/board/marasov/battery.c @@ -0,0 +1,77 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Brya battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* C490-42 Battery Information */ + [BATTERY_C490] = { + .fuel_gauge = { + .manuf_name = "AS3GWQd3jB", + .device_name = "C490-42", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000c, + .disconnect_val = 0x000c, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11880, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C490; + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} diff --git a/board/marasov/board.c b/board/marasov/board.c new file mode 100644 index 0000000000..94ef52a8c4 --- /dev/null +++ b/board/marasov/board.c @@ -0,0 +1,64 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "button.h" +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "driver/als_tcs3400.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + + if (ec_cfg_kb_bl_type()) + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + + if (ec_cfg_kb_bl_type()) + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +__override uint32_t board_override_feature_flags0(uint32_t flags0) +{ + /* + * Remove keyboard backlight feature for devices that don't support it. + */ + if (!ec_cfg_kb_bl_type()) + return (flags0 & ~EC_FEATURE_MASK_0(EC_FEATURE_PWM_KEYB)); + else + return flags0; +} diff --git a/board/marasov/board.h b/board/marasov/board.h new file mode 100644 index 0000000000..b34e69224b --- /dev/null +++ b/board/marasov/board.h @@ -0,0 +1,192 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* LED */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE +#undef CONFIG_VOLUME_BUTTONS + +/* USB Type A Features */ +#define USB_PORT_COUNT 2 +#define CONFIG_USB_PORT_POWER_DUMB + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 1 + +#define CONFIG_USB_PD_FRS_PPC +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#undef CONFIG_USB_PD_VBUS_DETECT_TCPC + +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID +#undef CONFIG_BC12_DETECT_PI3USB9201 +#undef CONFIG_USB_CHARGER + +/* Battery Configuration */ +#define CONFIG_SMBUS_PEC +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 99 + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +#define CONFIG_USBC_PPC_SYV682X + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_BQ25720 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 70 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_BQ25710_PSYS_SENSING + +/* + * Older boards have a different ADC assignment. + */ + +#define CONFIG_ADC_CHANNELS_RUNTIME_CONFIG + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_AMBIENT, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_TEMP_SENSOR_4_WWAN, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_AMBIENT, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_4_WWAN, + TEMP_SENSOR_COUNT +}; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_PORT_COUNT }; + +enum battery_type { BATTERY_C490, BATTERY_TYPE_COUNT }; + +enum pwm_channel { + PWM_CH_KBLIGHT, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/marasov/build.mk b/board/marasov/build.mk new file mode 100644 index 0000000000..8b85854cf0 --- /dev/null +++ b/board/marasov/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/marasov/charger.c b/board/marasov/charger.c new file mode 100644 index 0000000000..d78c345f94 --- /dev/null +++ b/board/marasov/charger.c @@ -0,0 +1,82 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/marasov/ec.tasklist b/board/marasov/ec.tasklist new file mode 100644 index 0000000000..a4039fc94f --- /dev/null +++ b/board/marasov/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/marasov/fans.c b/board/marasov/fans.c new file mode 100644 index 0000000000..d9b4d0d99a --- /dev/null +++ b/board/marasov/fans.c @@ -0,0 +1,89 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/181271666): thermistor placement and calibration + * + * Prototype fan spins at about 4200 RPM at 100% PWM, this + * is specific to board ID 2 and might also apears in later + * boards as well. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2200, + .rpm_start = 2200, + .rpm_max = 4200, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/181271666): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/marasov/fw_config.c b/board/marasov/fw_config.c new file mode 100644 index 0000000000..39c5488331 --- /dev/null +++ b/board/marasov/fw_config.c @@ -0,0 +1,45 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union marasov_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for brya if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union marasov_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Brya FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union marasov_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +enum ec_cfg_keyboard_backlight_type ec_cfg_kb_bl_type(void) +{ + return fw_config.kb_bl; +} diff --git a/board/marasov/fw_config.h b/board/marasov/fw_config.h new file mode 100644 index 0000000000..e208e80ca0 --- /dev/null +++ b/board/marasov/fw_config.h @@ -0,0 +1,47 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_MARASOV_FW_CONFIG_H_ +#define __BOARD_MARASOV_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for marasov board. + * + * Source of truth is the project/brya/marasov/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +union marasov_cbi_fw_config { + struct { + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t ufc : 1; + uint32_t reserved_1 : 25; + uint32_t storage : 2; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union marasov_cbi_fw_config get_fw_config(void); + +/** + * Get the keyboard backlight type from FW_CONFIG. + * + * @return the keyboard backlight type. + */ +enum ec_cfg_keyboard_backlight_type ec_cfg_kb_bl_type(void); + +#endif /* __BOARD_MARASOV_FW_CONFIG_H_ */ diff --git a/board/marasov/generated-gpio.inc b/board/marasov/generated-gpio.inc new file mode 100644 index 0000000000..e3a76ab142 --- /dev/null +++ b/board/marasov/generated-gpio.inc @@ -0,0 +1,126 @@ +/* + * This file was auto-generated. + */ + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_OC_ODL, PIN(9, 6), GPIO_ODR_HIGH) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(PWR_LED_W_ODL, PIN(6, 0), GPIO_OUT_HIGH) +GPIO(PWR_LED_A_ODL, PIN(C, 2), GPIO_OUT_HIGH) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ +UNUSED(PIN(9, 5)) /* GPIO95 */ +UNUSED(PIN(8, 1)) /* GPIO81 */ +UNUSED(PIN(5, 6)) /* GPIO56 */ +UNUSED(PIN(D, 4)) /* GPIOD4 */ +UNUSED(PIN(9, 3)) /* GPIO93 */ +UNUSED(PIN(9, 7)) /* GPIO97 */ +UNUSED(PIN(C, 3)) /* GPIOC3 */ +UNUSED(PIN(C, 4)) /* GPIOC4 */ +UNUSED(PIN(C, 6)) /* GPIOC6 */ +UNUSED(PIN(5, 0)) /* GPIO50 */ +UNUSED(PIN(8, 3)) /* GPIO83 */ +UNUSED(PIN(7, 0)) /* GPIO70 */ +UNUSED(PIN(4, 1)) /* GPIO41 */ +UNUSED(PIN(B, 1)) /* GPIOB1 */ +UNUSED(PIN(D, 0)) /* GPIOD0 */ +UNUSED(PIN(D, 1)) /* GPIOD1 */ + +/* Pre-configured PSL balls: J8 K6 */ diff --git a/board/marasov/gpio.inc b/board/marasov/gpio.inc new file mode 100644 index 0000000000..d4a2ff2d67 --- /dev/null +++ b/board/marasov/gpio.inc @@ -0,0 +1,38 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* + * Generated-gpio.inc is produced using a Brya specific tool that + * parses the GPIO definitions derived from the board schematics and + * EC pinout descriptions derived form the chip datasheets to generate + * the Chrome EC GPIO pinout definitions. Due to the confidential + * nature of schematics and datasheets, they are not provided here. + * + * Variants that do not auto-generate their GPIO definitions should + * combine the Brya gpio.inc and generated-gpio.inc into their + * gpio.inc and customize as appropriate. + */ + +#include "generated-gpio.inc" + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* IO expander configuration */ + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) +/* GPIO07_P2 to PU */ diff --git a/board/marasov/i2c.c b/board/marasov/i2c.c new file mode 100644 index 0000000000..846be8947a --- /dev/null +++ b/board/marasov/i2c.c @@ -0,0 +1,73 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "hooks.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,2", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,2", + .port = I2C_PORT_USB_C0_PPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_PPC_BC_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/marasov/keyboard.c b/board/marasov/keyboard.c new file mode 100644 index 0000000000..e75af0b516 --- /dev/null +++ b/board/marasov/keyboard.c @@ -0,0 +1,48 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config marasov_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &marasov_kb; +} diff --git a/board/marasov/led.c b/board/marasov/led.c new file mode 100644 index 0000000000..74005005cb --- /dev/null +++ b/board/marasov/led.c @@ -0,0 +1,101 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_PWR_LED_A_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_PWR_LED_W_ODL, LED_ON_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_PWR_LED_A_ODL, LED_ON_LVL); + gpio_set_level(GPIO_PWR_LED_W_ODL, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_PWR_LED_W_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_PWR_LED_A_ODL, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/marasov/pwm.c b/board/marasov/pwm.c new file mode 100644 index 0000000000..a1ffcbef30 --- /dev/null +++ b/board/marasov/pwm.c @@ -0,0 +1,37 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 12000, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/marasov/sensors.c b/board/marasov/sensors.c new file mode 100644 index 0000000000..090377419d --- /dev/null +++ b/board/marasov/sensors.c @@ -0,0 +1,141 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "common.h" +#include "gpio.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_AMBIENT] = { + .name = "TEMP_AMBIENT", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_WWAN] = { + .name = "TEMP_WWAN", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { + .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC, + }, + [TEMP_SENSOR_2_AMBIENT] = { + .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_AMBIENT, + }, + [TEMP_SENSOR_3_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER, + }, + [TEMP_SENSOR_4_WWAN] = { + .name = "WWAN", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_WWAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(92), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(80), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +#define THERMAL_AMBIENT \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(92), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(80), \ + } +__maybe_unused static const struct ec_thermal_config thermal_ambient = + THERMAL_AMBIENT; + +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(92), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(80), \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +#define THERMAL_WWAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(65), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(92), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(80), \ + } +__maybe_unused static const struct ec_thermal_config thermal_wwan = + THERMAL_WWAN; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_AMBIENT] = THERMAL_AMBIENT, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, + [TEMP_SENSOR_4_WWAN] = THERMAL_WWAN, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/marasov/usbc_config.c b/board/marasov/usbc_config.c new file mode 100644 index 0000000000..2fa5efea5f --- /dev/null +++ b/board/marasov/usbc_config.c @@ -0,0 +1,327 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +#ifdef CONFIG_ZEPHYR +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_PORT_COUNT }; +#endif /* CONFIG_ZEPHYR */ + +#ifndef CONFIG_ZEPHYR +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_FRS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); +#endif /* !CONFIG_ZEPHYR */ + +/******************************************************************************/ +/* USB-A charging control */ + +#ifndef CONFIG_ZEPHYR +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +#endif +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +#ifndef CONFIG_ZEPHYR +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM5360A */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +/* + * USB3 DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* + * USB C0 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); +#endif /* !CONFIG_ZEPHYR */ + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { +/* TODO: explore how to handle board id in zephyr*/ +#ifndef CONFIG_ZEPHYR + rst_signal = IOEX_USB_C0_RT_RST_ODL; +#else + /* On Zephyr use bb_controls generated from DTS */ + rst_signal = bb_controls[me->usb_port].retimer_rst_gpio; +#endif /* !CONFIG_ZEPHYR */ + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + enum gpio_signal tcpc_rst; + +#ifndef CONFIG_ZEPHYR + tcpc_rst = GPIO_USB_C0_TCPC_RST_ODL; +#else + tcpc_rst = GPIO_UNIMPLEMENTED; +#endif /* !CONFIG_ZEPHYR */ + + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(tcpc_rst, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(tcpc_rst, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ +#ifndef CONFIG_ZEPHYR + ioex_init(IOEX_C0_NCT38XX); +#else + gpio_reset_port(DEVICE_DT_GET(DT_NODELABEL(ioex_port1))); +#endif + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC +int pd_snk_is_vbus_provided(int port) +{ + return ppc_is_vbus_present(port); +} +#endif diff --git a/board/marasov/usbc_config.h b/board/marasov/usbc_config.h new file mode 100644 index 0000000000..1fa7ad4c7a --- /dev/null +++ b/board/marasov/usbc_config.h @@ -0,0 +1,17 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#ifndef CONFIG_ZEPHYR +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#endif + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/marasov/vif_override.xml b/board/marasov/vif_override.xml new file mode 100644 index 0000000000..6ade5d2f92 --- /dev/null +++ b/board/marasov/vif_override.xml @@ -0,0 +1,148 @@ + + + 2 + 0 + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 9A1B + + + + + + Gen 3 (40Gb) + + + + USB 3.2 Gen 2x2 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + + + + + + USB 3.2 Gen 2x1 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PSD + PDUSB Host + + + + + Gen 3 (40Gb) + + USB 3.2 Gen 2x2 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + diff --git a/board/marzipan/battery.c b/board/marzipan/battery.c new file mode 100644 index 0000000000..fa3a4ec189 --- /dev/null +++ b/board/marzipan/battery.c @@ -0,0 +1,97 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all marzipan battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ + +const struct board_batt_params board_battery_info[] = { + /* COSMX DM02032XL 333-AC-13-A */ + [BATTERY_COSMX] = { + .fuel_gauge = { + .manuf_name = "333-AC-13-A", + .device_name = "DM02032XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, + /* Simplo DM02032XL 333-AC-13-A */ + [BATTERY_SIMPLO] = { + .fuel_gauge = { + .manuf_name = "333-1D-13-A", + .device_name = "DM02032XL", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_COSMX; diff --git a/board/marzipan/board.c b/board/marzipan/board.c new file mode 100644 index 0000000000..b2f7ade2ba --- /dev/null +++ b/board/marzipan/board.c @@ -0,0 +1,658 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Marzipan board-specific configuration */ + +#include "adc_chip.h" +#include "battery_fuel_gauge.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accel_kx022.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "pi3usb9201.h" +#include "power.h" +#include "power/qcom.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "shi_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "usbc_config.h" +#include "usbc_ocp.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +void usb1_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + case GPIO_USB_C1_SWCTL_INT_ODL: + sn5s330_interrupt(1); + break; + default: + break; + } +} + +static void board_connect_c0_sbu_deferred(void) +{ + /* + * If CCD_MODE_ODL asserts, it means there's a debug accessory connected + * and we should enable the SBU FETs. + */ + ppc_set_sbu(0, 1); +} +DECLARE_DEFERRED(board_connect_c0_sbu_deferred); + +void board_connect_c0_sbu(enum gpio_signal s) +{ + hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); +} + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Use 80 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* + * Unmask 0x08 in [0] (KSO_00/KSI_03, the new location of Search key); + * as it still uses the legacy location (KSO_01/KSI_00). + */ + .actual_key_mask = { 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xa4, + 0xff, 0xfe, 0x55, 0xfa, 0xca }, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, +}; + +/* I2C port map */ +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* Measure VBUS through a 1/10 voltage divider */ + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + /* + * Adapter current output or battery charging/discharging current (uV) + * 18x amplification on charger side. + */ + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, + /* + * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read + * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and + * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we + * only divide by 2 (enough to avoid precision issues). + */ + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + /* TODO(waihong): Assign a proper frequency. */ + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 4800 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + } +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + { + .i2c_port = I2C_PORT_EEPROM, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/* Mutexes */ +static struct mutex g_base_mutex; +static struct mutex g_lid_mutex; + +static struct kionix_accel_data g_kx022_data; +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; +static struct accelgyro_saved_data_t g_bma255_data; + +enum base_accelgyro_type { + BASE_GYRO_NONE = 0, + BASE_GYRO_BMI160 = 1, + BASE_GYRO_ICM426XX = 2, +}; + +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t base_standard_ref_bmi160 = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t base_standard_ref_icm426xx = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref_bma255 = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t lid_standard_ref_kx022 = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma255_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref_bma255, + .default_range = 2, /* g, to support lid angle calculation. */ + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_bmi160, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_bmi160, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref_kx022, + .default_range = 2, /* g, enough for laptop. */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_standard_ref_icm426xx, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm426xx, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +static int base_accelgyro_config; + +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_accelgyro_config) { + case BASE_GYRO_ICM426XX: + icm426xx_interrupt(signal); + break; + case BASE_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +static void board_detect_motionsensor(void) +{ + int ret; + int val; + + /* Check lid accel chip */ + ret = i2c_read8(I2C_PORT_SENSOR, BMA2x2_I2C_ADDR1_FLAGS, + BMA2x2_CHIP_ID_ADDR, &val); + if (ret) + motion_sensors[LID_ACCEL] = kx022_lid_accel; + + CPRINTS("Lid Accel: %s", ret ? "KX022" : "BMA255"); + + /* Check base accelgyro chip */ + ret = icm_read8(&icm426xx_base_accel, ICM426XX_REG_WHO_AM_I, &val); + if (val == ICM426XX_CHIP_ICM40608) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + } + + base_accelgyro_config = (val == ICM426XX_CHIP_ICM40608) ? + BASE_GYRO_ICM426XX : + BASE_GYRO_BMI160; + CPRINTS("Base Accelgyro: %s", + (val == ICM426XX_CHIP_ICM40608) ? "ICM40608" : "BMI160"); +} + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + + /* + * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs + * for SBU may be disconnected after DP alt mode is off. Should enable + * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. + */ + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); + + /* Set the backlight duty cycle to 0. AP will override it later. */ + pwm_set_duty(PWM_CH_DISPLIGHT, 0); + + board_detect_motionsensor(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + int i; + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + ppc_vbus_sink_enable(i, 1); +} + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* + * Turn off display backlight in S3. AP has its own control. The EC's + * and the AP's will be AND'ed together in hardware. + */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); + pwm_enable(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Turn on display and keyboard backlight in S0. */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); + if (pwm_get_duty(PWM_CH_DISPLIGHT)) + pwm_enable(PWM_CH_DISPLIGHT, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} diff --git a/board/marzipan/board.h b/board/marzipan/board.h new file mode 100644 index 0000000000..c651e55965 --- /dev/null +++ b/board/marzipan/board.h @@ -0,0 +1,101 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Marzipan board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Keyboard */ +#define CONFIG_KEYBOARD_PROTOCOL_MKBP + +#define CONFIG_PWM_KBLIGHT + +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_FUEL_GAUGE + +/* BC 1.2 Charger */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* USB */ +#define CONFIG_USB_PD_TCPM_PS8755 +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* Sensors */ +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +/* BMI160 Base accel/gyro */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS + +/* ICM426XX Base accel/gyro */ +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* KX022 lid accel */ +#define CONFIG_ACCEL_KX022 + +/* BMA253 lid accel */ +#define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_UPDATE + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* GPIO alias */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_PMIC_RESIN_L GPIO_PM845_RESIN_L + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { ADC_VBUS, ADC_AMON_BMON, ADC_PSYS, ADC_CH_COUNT }; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_DISPLIGHT, PWM_CH_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_COSMX, + BATTERY_SIMPLO, + BATTERY_TYPE_COUNT, +}; + +/* Reset all TCPCs. */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); +/* Motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); + +#endif /* !defined(__ASSEMBLER__) */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/marzipan/build.mk b/board/marzipan/build.mk new file mode 100644 index 0000000000..048f0787f7 --- /dev/null +++ b/board/marzipan/build.mk @@ -0,0 +1,18 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=trogdor + +board-y+=battery.o +board-y+=board.o +board-y+=led.o +board-y+=switchcap.o +board-y+=usbc_config.o diff --git a/board/marzipan/ec.tasklist b/board/marzipan/ec.tasklist new file mode 100644 index 0000000000..228828af3c --- /dev/null +++ b/board/marzipan/ec.tasklist @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/marzipan/gpio.inc b/board/marzipan/gpio.inc new file mode 100644 index 0000000000..633f689c66 --- /dev/null +++ b/board/marzipan/gpio.inc @@ -0,0 +1,185 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* USB interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ +GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ +GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ +GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb1_evt) /* Interrupt from port-1 BC1.2 */ + +/* System interrupts */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ +GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ +GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ +/* + * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down + * to make it low. Overload the interrupt function chipset_warm_reset_interrupt + * for not only signalling power_signal_interrupt but also handling the logic + * of WARM_RESET_L which is pulled-up by the same rail of POWER_GOOD. + */ +GPIO_INT(POWER_GOOD, PIN(5, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, chipset_power_good_interrupt) /* SRC_PP1800_S10A from PMIC */ +GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_warm_reset_interrupt) /* AP warm reset */ +GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ + +/* Sensor interrupts */ +GPIO_INT(TABLET_MODE_L, PIN(C, 6), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, motion_interrupt) /* Accelerometer/gyro interrupt */ + +/* + * EC_RST_ODL used to be a wake source from PSL mode. However, we disabled + * the PSL mode. This GPIO does nothing now. Simply set it an INPUT. + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ +GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ + +/* PMIC/AP 1.8V */ +GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ +GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ +GPIO(QSIP_ON, PIN(5, 0), GPIO_OUT_LOW) /* Not used, for non-switchcap testing */ + +/* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ +GPIO(SWITCHCAP_ON, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap; will be configured in the board init */ +GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ +GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ +GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ + +/* Sensors */ +GPIO(LID_ACCEL_INT_L, PIN(5, 6), GPIO_INPUT) /* Lid accel sensor interrupt */ +/* Control the gate for trackpad IRQ. High closes the gate. + * This is always set low so that the OS can manage the trackpad. */ +GPIO(TRACKPAD_INT_GATE, PIN(7, 4), GPIO_OUT_LOW) + +/* USB-C */ +GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_ODR_HIGH) /* Port-0 TCPC chip reset, actaully Open-Drain */ +GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_ODR_HIGH) /* Port-1 TCPC chip reset, actually Open-Drain */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ + +/* LEDs */ +GPIO(EC_CHG_LED_Y_C1, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_B_C1, PIN(C, 4), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + +/* PWM */ +GPIO(KB_BL_PWM, PIN(8, 0), GPIO_INPUT) /* PWM3 */ +GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ + +/* ADC */ +GPIO(PPVAR_BOOSTIN_SENSE, PIN(4, 4), GPIO_INPUT) /* ADC1 */ +GPIO(CHARGER_IADP, PIN(4, 3), GPIO_INPUT) /* ADC2 */ +GPIO(CHARGER_PMON, PIN(4, 2), GPIO_INPUT) /* ADC3 */ + +/* I2C */ +GPIO(EC_I2C_POWER_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Board/SKU IDs */ +GPIO(BRD_ID0, PIN(C, 7), GPIO_INPUT) +GPIO(BRD_ID1, PIN(9, 3), GPIO_INPUT) +GPIO(BRD_ID2, PIN(6, 3), GPIO_INPUT) +GPIO(SKU_ID0, PIN(F, 0), GPIO_INPUT) +GPIO(SKU_ID1, PIN(4, 1), GPIO_INPUT) +GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) + +/* Switchcap */ +/* + * GPIO0 is configured as PVC_PG. When the chip in power down mode, it outputs + * high-Z. Set pull-down to avoid floating. + */ +GPIO(DA9313_GPIO0, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(0, 4)) +UNUSED(PIN(C, 0)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(3, 7)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(7, 3)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(6, 2)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(6, 0)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(D, 3)) +UNUSED(PIN(8, 6)) +UNUSED(PIN(7, 5)) +UNUSED(PIN(D, 1)) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ +ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1 SDA (GPIO90), I2C2 (GPIO91/92) */ +ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) */ +ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ +ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ +ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ +ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* PWM3 (GPIO80) - KB_BL_PWM */ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ + +/* Keyboard */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +#define GPIO_KB_OUTPUT (GPIO_ODR_HIGH) +#define GPIO_KB_OUTPUT_COL2 (GPIO_OUT_LOW) + +/* Keyboard alternate functions */ +ALTERNATE(PIN_MASK(0, 0xE0), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO10 (GPIO07), KSO11 (GPIO06), KSO12 (GPIO05) */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO03 (GPIO16), KSO04 (GPIO15), KSO05 (GPIO14), KSO06 (GPIO13), KSO07 (GPIO12), KSO08 (GPIO11), KSO09 (GPIO10) */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO00 (GPIO21), KSO01 (GPIO20) */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI2 (GPIO27), KSI3 (GPIO26), KSI4 (GPIO25), KSI5 (GPIO24), KSI6 (GPIO23), KSI7 (GPIO22) */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI0 (GPIO31), KSI1 (GPIO30) */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_KB_OUTPUT_COL2) /* KSO02 (GPIO17) */ diff --git a/board/marzipan/led.c b/board/marzipan/led.c new file mode 100644 index 0000000000..b2fc45abe1 --- /dev/null +++ b/board/marzipan/led.c @@ -0,0 +1,154 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) + +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_BLUE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color(enum led_color color) +{ + gpio_set_level(GPIO_EC_CHG_LED_Y_C1, + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(GPIO_EC_CHG_LED_B_C1, + (color == LED_BLUE) ? BAT_LED_ON : BAT_LED_OFF); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color(LED_BLUE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color(LED_AMBER); + else + led_set_color(LED_OFF); + + return EC_SUCCESS; +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + int color = LED_OFF; + int period = 0; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate amber on when charging. */ + color = LED_AMBER; + break; + case LED_PWRS_DISCHARGE: + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* Discharging in S3: Amber 1 sec, off 3 sec */ + period = (1 + 3) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_AMBER; + else + color = LED_OFF; + } else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + /* Discharging in S5: off */ + color = LED_OFF; + } else if (chipset_in_state(CHIPSET_STATE_ON)) { + /* Discharging in S0: Blue on */ + color = LED_BLUE; + } + break; + case LED_PWRS_ERROR: + /* Battery error: Amber 1 sec, off 1 sec */ + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_AMBER; + else + color = LED_OFF; + break; + case LED_PWRS_CHARGE_NEAR_FULL: + /* Full Charged: Blue on */ + color = LED_BLUE; + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_BLUE; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode: Blue 2 sec, Amber 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) + color = LED_BLUE; + else + color = LED_AMBER; + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + led_set_color(color); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_BATTERY_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_BLUE : LED_OFF; + + led_auto_control(EC_LED_ID_BATTERY_LED, 0); + + led_set_color(color); +} diff --git a/board/marzipan/switchcap.c b/board/marzipan/switchcap.c new file mode 100644 index 0000000000..853f677f27 --- /dev/null +++ b/board/marzipan/switchcap.c @@ -0,0 +1,31 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "config.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "power/qcom.h" +#include "system.h" + +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON, enable); +} + +int board_is_switchcap_enabled(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_ON); +} + +int board_is_switchcap_power_good(void) +{ + return gpio_get_level(GPIO_DA9313_GPIO0); +} diff --git a/board/marzipan/usbc_config.c b/board/marzipan/usbc_config.c new file mode 100644 index 0000000000..f7e9bd6220 --- /dev/null +++ b/board/marzipan/usbc_config.c @@ -0,0 +1,80 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Marzipan board-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "usb_pd.h" +#include "usbc_config.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +/* GPIO Interrupt Handlers */ +void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_PD_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} diff --git a/board/marzipan/usbc_config.h b/board/marzipan/usbc_config.h new file mode 100644 index 0000000000..56cdb155ea --- /dev/null +++ b/board/marzipan/usbc_config.h @@ -0,0 +1,19 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Marzipan board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#include "gpio.h" + +void tcpc_alert_event(enum gpio_signal signal); +void usb0_evt(enum gpio_signal signal); +void usb1_evt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); +void board_connect_c0_sbu(enum gpio_signal s); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/marzipan/vif_override.xml b/board/marzipan/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/marzipan/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/max32660-eval/board.c b/board/max32660-eval/board.c index 15a856ab4e..442469ba27 100644 --- a/board/max32660-eval/board.c +++ b/board/max32660-eval/board.c @@ -1,19 +1,21 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* MAX32660 EvalKit Board Specific Configuration */ -#include "i2c.h" -#include "board.h" +#include "config.h" #include "console.h" #include "ec_commands.h" #include "gpio.h" #include "hooks.h" -#include "timer.h" +#include "i2c.h" #include "registers.h" +#include "timer.h" #include "util.h" + +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" #define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) diff --git a/board/max32660-eval/board.h b/board/max32660-eval/board.h index 87a4b65fa1..9061b0b958 100644 --- a/board/max32660-eval/board.h +++ b/board/max32660-eval/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,7 +11,7 @@ /* Optional features */ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands */ #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_FPU @@ -24,8 +24,8 @@ #undef CONFIG_HOSTCMD_EVENTS #define CONFIG_I2C -#define CONFIG_I2C_SLAVE -#define CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS (0x51) /* 7 bit right-aligned, bits 6 to 0 */ +#define CONFIG_I2C_PERIPHERAL +#define CONFIG_HOSTCMD_I2C_ADDR_FLAGS (0x51) /* 7 bit right-aligned */ /* Slave I2C port configuration */ #define I2C_PORT_SLAVE 1 diff --git a/board/max32660-eval/build.mk b/board/max32660-eval/build.mk index a613922cd2..3e50dd9a00 100644 --- a/board/max32660-eval/build.mk +++ b/board/max32660-eval/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/max32660-eval/ec.tasklist b/board/max32660-eval/ec.tasklist index 5e58b9dea8..c92b25295b 100644 --- a/board/max32660-eval/ec.tasklist +++ b/board/max32660-eval/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/max32660-eval/gpio.inc b/board/max32660-eval/gpio.inc index 3ced37a77f..e7397e11a4 100644 --- a/board/max32660-eval/gpio.inc +++ b/board/max32660-eval/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/mchpevb1/battery.c b/board/mchpevb1/battery.c index fcc09994bf..d8f7496fa0 100644 --- a/board/mchpevb1/battery.c +++ b/board/mchpevb1/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -14,15 +14,15 @@ #include "util.h" /* Shutdown mode parameter to write to manufacturer access register */ -#define PARAM_CUT_OFF_LOW 0x10 +#define PARAM_CUT_OFF_LOW 0x10 #define PARAM_CUT_OFF_HIGH 0x00 /* Battery info for BQ40Z55 */ static const struct battery_info info = { - .voltage_max = 8700, /* mV */ + .voltage_max = 8700, /* mV */ .voltage_normal = 7600, .voltage_min = 6000, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 46, .charging_min_c = 0, @@ -47,10 +47,10 @@ int board_cut_off_battery(void) buf[2] = PARAM_CUT_OFF_HIGH; i2c_lock(I2C_PORT_BATTERY, 1); - rv = i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - buf, 3, NULL, 0, I2C_XFER_SINGLE); - rv |= i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - buf, 3, NULL, 0, I2C_XFER_SINGLE); + rv = i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, buf, 3, + NULL, 0, I2C_XFER_SINGLE); + rv |= i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, buf, 3, + NULL, 0, I2C_XFER_SINGLE); i2c_lock(I2C_PORT_BATTERY, 0); return rv; @@ -214,7 +214,7 @@ enum ec_status charger_profile_override_set_param(uint32_t param, return EC_RES_INVALID_PARAM; } -static int command_fastcharge(int argc, char **argv) +static int command_fastcharge(int argc, const char **argv) { if (argc > 1 && !parse_bool(argv[1], &fast_charging_allowed)) return EC_ERROR_PARAM1; @@ -223,8 +223,7 @@ static int command_fastcharge(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(fastcharge, command_fastcharge, - "[on|off]", +DECLARE_CONSOLE_COMMAND(fastcharge, command_fastcharge, "[on|off]", "Get or set fast charging profile"); -#endif /* CONFIG_CHARGER_PROFILE_OVERRIDE */ +#endif /* CONFIG_CHARGER_PROFILE_OVERRIDE */ diff --git a/board/mchpevb1/board.c b/board/mchpevb1/board.c index 79f104ff55..c10520276b 100644 --- a/board/mchpevb1/board.c +++ b/board/mchpevb1/board.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,8 +11,8 @@ */ #include "adc.h" -#include "adc_chip.h" #include "als.h" +#include "battery_smart.h" #include "bd99992gw.h" #include "button.h" #include "charge_manager.h" @@ -20,24 +20,24 @@ #include "charger.h" #include "chipset.h" #include "console.h" -#include "driver/als_opt3001.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/als_opt3001.h" #include "driver/tcpm/tcpci.h" +#include "espi.h" #include "extpower.h" -#include "gpio_chip.h" #include "gpio.h" +#include "gpio_chip.h" #include "hooks.h" #include "host_command.h" #include "i2c.h" -#include "espi.h" -#include "lpc_chip.h" #include "keyboard_scan.h" #include "lid_switch.h" +#include "lpc_chip.h" #include "math_util.h" -#include "motion_sense.h" #include "motion_lid.h" +#include "motion_sense.h" #include "pi3usb9281.h" #include "power.h" #include "power_button.h" @@ -54,31 +54,28 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" -#include "espi.h" -#include "battery_smart.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* NOTE: MEC17xx EVB + SKL RVP3 does not use BD99992 PMIC. * RVP3 PMIC controlled by RVP3 logic. */ -#define I2C_ADDR_BD99992_FLAGS 0x30 +#define I2C_ADDR_BD99992_FLAGS 0x30 /* * Maxim DS1624 I2C temperature sensor used for testing I2C. * DS1624 contains one internal temperature sensor * and EEPROM. It has no external temperature inputs. */ -#define DS1624_I2C_ADDR_FLAGS (0x48 | I2C_FLAG_BIG_ENDIAN) -#define DS1624_IDX_LOCAL 0 -#define DS1624_READ_TEMP16 0xAA /* read 16-bit temperature */ -#define DS1624_ACCESS_CFG 0xAC /* read/write 8-bit config */ -#define DS1624_CMD_START 0xEE -#define DS1624_CMD_STOP 0x22 +#define DS1624_I2C_ADDR_FLAGS (0x48 | I2C_FLAG_BIG_ENDIAN) +#define DS1624_IDX_LOCAL 0 +#define DS1624_READ_TEMP16 0xAA /* read 16-bit temperature */ +#define DS1624_ACCESS_CFG 0xAC /* read/write 8-bit config */ +#define DS1624_CMD_START 0xEE +#define DS1624_CMD_STOP 0x22 /* * static global and routine to return smart battery @@ -88,10 +85,8 @@ static int smart_batt_temp; static int ds1624_temp; static int sb_temp(int idx, int *temp_ptr); static int ds1624_get_val(int idx, int *temp_ptr); -#ifdef HAS_TASK_MOTIONSENSE static void board_spi_enable(void); static void board_spi_disable(void); -#endif #ifdef CONFIG_BOARD_PRE_INIT /* @@ -119,7 +114,6 @@ void board_config_pre_init(void) } #endif /* #ifdef CONFIG_BOARD_PRE_INIT */ - /* * Use EC to handle ALL_SYS_PWRGD signal. * MEC17xx connected to SKL/KBL RVP3 reference board @@ -138,8 +132,8 @@ static void board_all_sys_pwrgd(void) CPRINTS("ALL_SYS_PWRGD=%d SYS_RESET_L=%d", allsys_in, allsys_out); - trace2(0, BRD, 0, "ALL_SYS_PWRGD=%d SYS_RESET_L=%d", - allsys_in, allsys_out); + trace2(0, BRD, 0, "ALL_SYS_PWRGD=%d SYS_RESET_L=%d", allsys_in, + allsys_out); /* * Wait at least 10 ms between power signals going high @@ -164,14 +158,12 @@ void all_sys_pwrgd_interrupt(enum gpio_signal signal) } #endif /* #ifdef CONFIG_BOARD_HAS_ALL_SYS_PWRGD */ - #ifdef HAS_TASK_PDCMD /* Exchange status with PD MCU. */ static void pd_mcu_interrupt(enum gpio_signal signal) { /* Exchange status with PD MCU to determine interrupt cause */ host_command_pd_send_status(0); - } #endif @@ -192,12 +184,12 @@ void vbus1_evt(enum gpio_signal signal) void usb0_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } void usb1_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); } #endif @@ -213,6 +205,7 @@ void tablet_mode_interrupt(enum gpio_signal signal) hook_call_deferred(&enable_input_devices_data, 0); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* ADC channels @@ -220,21 +213,29 @@ void tablet_mode_interrupt(enum gpio_signal signal) */ const struct adc_t adc_channels[] = { /* Vbus sensing. Converted to mV, full ADC is equivalent to 30V. */ - [ADC_VBUS] = {"VBUS", 30000, 1024, 0, 1}, + [ADC_VBUS] = { "VBUS", 30000, 1024, 0, 1 }, /* Adapter current output or battery discharging current */ - [ADC_AMON_BMON] = {"AMON_BMON", 25000, 3072, 0, 3}, + [ADC_AMON_BMON] = { "AMON_BMON", 25000, 3072, 0, 3 }, /* System current consumption */ - [ADC_PSYS] = {"PSYS", 1, 1, 0, 4}, - [ADC_CASE] = {"CASE", 1, 1, 0, 7}, + [ADC_PSYS] = { "PSYS", 1, 1, 0, 4 }, + [ADC_CASE] = { "CASE", 1, 1, 0, 7 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* * MCHP EVB connected to KBL RVP3 */ -const struct i2c_port_t i2c_ports[] = { - {"sensors", MCHP_I2C_PORT4, 100, GPIO_SMB04_SCL, GPIO_SMB04_SDA}, - {"batt", MCHP_I2C_PORT5, 100, GPIO_SMB05_SCL, GPIO_SMB05_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "sensors", + .port = MCHP_I2C_PORT4, + .kbps = 100, + .scl = GPIO_SMB04_SCL, + .sda = GPIO_SMB04_SDA }, + { .name = "batt", + .port = MCHP_I2C_PORT5, + .kbps = 100, + .scl = GPIO_SMB05_SCL, + .sda = GPIO_SMB05_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -264,53 +265,15 @@ int board_i2c_p2c(int port) #ifdef CONFIG_USB_POWER_DELIVERY const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - {I2C_PORT_TCPC, - CONFIG_TCPC_I2C_BASE_ADDR_FLAGS, - &tcpci_tcpm_drv}, + { I2C_PORT_TCPC, CONFIG_TCPC_I2C_BASE_ADDR_FLAGS, &tcpci_tcpm_drv }, - {I2C_PORT_TCPC, - CONFIG_TCPC_I2C_BASE_ADDR_FLAGS + 1, - &tcpci_tcpm_drv}, + { I2C_PORT_TCPC, CONFIG_TCPC_I2C_BASE_ADDR_FLAGS + 1, &tcpci_tcpm_drv }, }; #endif -const uint32_t i2c_ctrl_slave_addrs[I2C_CONTROLLER_COUNT] = { -#ifdef CONFIG_BOARD_MCHP_I2C0_SLAVE_ADDRS - (MCHP_I2C_CTRL0 + (CONFIG_BOARD_MCHP_I2C0_SLAVE_ADDRS << 16)), -#else - (MCHP_I2C_CTRL0 + (CONFIG_MCHP_I2C0_SLAVE_ADDRS << 16)), -#endif -#ifdef CONFIG_BOARD_MCHP_I2C1_SLAVE_ADDRS - (MCHP_I2C_CTRL1 + (CONFIG_BOARD_MCHP_I2C1_SLAVE_ADDRS << 16)), -#else - (MCHP_I2C_CTRL1 + (CONFIG_MCHP_I2C1_SLAVE_ADDRS << 16)), -#endif -}; - -/* Return the two slave addresses the specified - * controller will respond to when controller - * is acting as a slave. - * b[6:0] = b[7:1] of I2C address 1 - * b[14:8] = b[7:1] of I2C address 2 - * When not using I2C controllers as slaves we can use - * the same value for all controllers. The address should - * not be 0x00 as this is the general call address. - */ -uint16_t board_i2c_slave_addrs(int controller) -{ - int i; - - for (i = 0; i < I2C_CONTROLLER_COUNT; i++) - if ((i2c_ctrl_slave_addrs[i] & 0xffff) == controller) - return (i2c_ctrl_slave_addrs[i] >> 16); - - return CONFIG_MCHP_I2C0_SLAVE_ADDRS; -} - - /* SPI devices */ const struct spi_device_t spi_devices[] = { - { QMSPI0_PORT, 4, GPIO_QMSPI_CS0}, + { QMSPI0_PORT, 4, GPIO_QMSPI_CS0 }, #if defined(CONFIG_SPI_ACCEL_PORT) { GPSPI0_PORT, 2, GPIO_SPI0_CS0 }, #endif @@ -324,7 +287,6 @@ const enum gpio_signal hibernate_wake_pins[] = { }; const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); - /* * Deep sleep support, called by chip level. */ @@ -340,7 +302,7 @@ void board_prepare_for_deep_sleep(void) #if defined(CONFIG_GPIO_POWER_DOWN) && \ defined(CONFIG_MCHP_DEEP_SLP_GPIO_PWR_DOWN) gpio_power_down_module(MODULE_SPI_FLASH); - gpio_power_down_module(MODULE_SPI_MASTER); + gpio_power_down_module(MODULE_SPI_CONTROLLER); gpio_power_down_module(MODULE_I2C); /* powering down keyscan is causing an issue with keyscan task * probably due to spurious interrupts on keyscan pins. @@ -367,7 +329,7 @@ void board_resume_from_deep_sleep(void) #endif /* gpio_config_module(MODULE_KEYBOARD_SCAN, 1); */ gpio_config_module(MODULE_SPI_FLASH, 1); - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); gpio_config_module(MODULE_I2C, 1); #endif } @@ -387,18 +349,24 @@ struct pi3usb9281_config pi3usb9281_chips[] = { BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) == CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT); -struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, - .driver = &pi3usb3x532_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, }, { - .usb_port = 1, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = 0x10, - .driver = &ps8740_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = 0x10, + .driver = &ps8740_usb_mux_driver, + }, } }; #endif @@ -454,9 +422,9 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); * a static global in this module. */ const struct temp_sensor_t temp_sensors[] = { - {"Battery", TEMP_SENSOR_TYPE_BATTERY, sb_temp, 0}, - {"Ambient", TEMP_SENSOR_TYPE_BOARD, ds1624_get_val, 0}, - {"Case", TEMP_SENSOR_TYPE_CASE, therm_get_val, (int)ADC_CASE}, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, sb_temp, 0 }, + { "Ambient", TEMP_SENSOR_TYPE_BOARD, ds1624_get_val, 0 }, + { "Case", TEMP_SENSOR_TYPE_CASE, therm_get_val, (int)ADC_CASE }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); #endif @@ -465,16 +433,16 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); #ifdef CONFIG_ALS /* ALS instances. Must be in same order as enum als_id. */ struct als_t als[] = { - {"TI", opt3001_init, opt3001_read_lux, 5}, + { "TI", opt3001_init, opt3001_read_lux, 5 }, }; BUILD_ASSERT(ARRAY_SIZE(als) == ALS_COUNT); #endif const struct button_config buttons[CONFIG_BUTTON_COUNT] = { - {"Volume Down", KEYBOARD_BUTTON_VOLUME_DOWN, GPIO_VOLUME_DOWN_L, - 30 * MSEC, 0}, - {"Volume Up", KEYBOARD_BUTTON_VOLUME_UP, GPIO_VOLUME_UP_L, - 30 * MSEC, 0}, + { "Volume Down", KEYBOARD_BUTTON_VOLUME_DOWN, GPIO_VOLUME_DOWN_L, + 30 * MSEC, 0 }, + { "Volume Up", KEYBOARD_BUTTON_VOLUME_UP, GPIO_VOLUME_UP_L, 30 * MSEC, + 0 }, }; /* MCHP mec1701_evb connected to Intel SKL RVP3 with Kabylake @@ -515,8 +483,7 @@ static void board_pmic_init(void) cfg = 0x66; rv = i2c_read8(I2C_PORT_THERMAL, DS1624_I2C_ADDR_FLAGS, DS1624_ACCESS_CFG, &cfg); - trace2(0, BRD, 0, "Read DS1624 Config rv = %d cfg = 0x%02X", - rv, cfg); + trace2(0, BRD, 0, "Read DS1624 Config rv = %d cfg = 0x%02X", rv, cfg); if ((rv == EC_SUCCESS) && (cfg & (1u << 0))) { /* one-shot mode switch to continuous */ @@ -561,18 +528,13 @@ static void board_init(void) /* Provide AC status to the PCH */ gpio_set_level(GPIO_PCH_ACOK, extpower_is_present()); -#ifdef HAS_TASK_MOTIONSENSE - if (system_jumped_late() && - chipset_in_state(CHIPSET_STATE_ON)) { + if (system_jumped_late() && chipset_in_state(CHIPSET_STATE_ON)) { trace0(0, BRD, 0, "board_init: S0 call board_spi_enable"); board_spi_enable(); } -#endif - } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - /** * Buffer the AC present GPIO to the PCH. */ @@ -604,8 +566,7 @@ int board_set_active_charge_port(int charge_port) if (is_real_port && source) { CPRINTS("MEC1701 Skip enable p%d", charge_port); - trace1(0, BOARD, 0, "Skip enable charge port %d", - charge_port); + trace1(0, BOARD, 0, "Skip enable charge port %d", charge_port); return EC_ERROR_INVAL; } @@ -619,45 +580,16 @@ int board_set_active_charge_port(int charge_port) } else { /* Make sure non-charging port is disabled */ gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_EN_L : - GPIO_USB_C1_CHARGE_EN_L, 1); + GPIO_USB_C1_CHARGE_EN_L, + 1); /* Enable charging port */ gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_EN_L : - GPIO_USB_C0_CHARGE_EN_L, 0); + GPIO_USB_C0_CHARGE_EN_L, + 0); } return EC_SUCCESS; } - -/** - * Set the charge limit based upon desired maximum. - * - * @param port Port number. - * @param supplier Charge supplier type. - * @param charge_ma Desired charge limit (mA). - * @param charge_mv Negotiated charge voltage (mV). - */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} -#else -/* - * TODO HACK providing functions from common/charge_state_v2.c - * which is not compiled in when no charger - */ -int charge_want_shutdown(void) -{ - return 0; -} - -int charge_prevent_power_on(int power_button_pressed) -{ - return 0; -} - - #endif /* @@ -689,23 +621,18 @@ static void board_chipset_startup(void) gpio_set_level(GPIO_USB2_ENABLE, 1); hook_call_deferred(&enable_input_devices_data, 0); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_chipset_startup, - HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); /* Called on AP S3 -> S5 transition */ static void board_chipset_shutdown(void) { CPRINTS("MEC1701 HOOK_CHIPSET_SHUTDOWN board_chipset_shutdown"); - trace0(0, HOOK, 0, - "HOOK_CHIPSET_SHUTDOWN board_chipset_shutdown"); + trace0(0, HOOK, 0, "HOOK_CHIPSET_SHUTDOWN board_chipset_shutdown"); gpio_set_level(GPIO_USB1_ENABLE, 0); gpio_set_level(GPIO_USB2_ENABLE, 0); hook_call_deferred(&enable_input_devices_data, 0); } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_chipset_shutdown, - HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); /* Called on AP S3 -> S0 transition */ static void board_chipset_resume(void) @@ -717,10 +644,9 @@ static void board_chipset_resume(void) gpio_set_level(GPIO_PP1800_DX_AUDIO_EN, 1); gpio_set_level(GPIO_PP1800_DX_SENSOR_EN, 1); #endif - } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, - MOTION_SENSE_HOOK_PRIO-1); + MOTION_SENSE_HOOK_PRIO - 1); /* Called on AP S0 -> S3 transition */ static void board_chipset_suspend(void) @@ -733,9 +659,7 @@ static void board_chipset_suspend(void) gpio_set_level(GPIO_PP1800_DX_SENSOR_EN, 0); #endif } -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, - board_chipset_suspend, - HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); void board_hibernate_late(void) { @@ -812,7 +736,6 @@ static void board_handle_reboot(void) } DECLARE_HOOK(HOOK_INIT, board_handle_reboot, HOOK_PRIO_FIRST); - static int sb_temp(int idx, int *temp_ptr) { if (idx != 0) @@ -849,8 +772,8 @@ static void sb_update(void) rv = sb_read(SB_TEMPERATURE, &smart_batt_temp); smart_batt_temp = smart_batt_temp / 10; - trace12(0, BRD, 0, "sb_read temperature rv=%d temp=%d K", - rv, smart_batt_temp); + trace12(0, BRD, 0, "sb_read temperature rv=%d temp=%d K", rv, + smart_batt_temp); } /* @@ -906,7 +829,6 @@ static void board_one_sec(void) } DECLARE_HOOK(HOOK_SECOND, board_one_sec, HOOK_PRIO_DEFAULT); -#ifdef HAS_TASK_MOTIONSENSE /* Motion sensors */ static struct mutex g_base_mutex; @@ -935,7 +857,7 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS( + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS( CONFIG_SPI_ACCEL_PORT), .rot_standard_ref = NULL, /* Identity matrix. */ .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ @@ -960,7 +882,7 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS( + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS( CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ .rot_standard_ref = NULL, /* Identity Matrix. */ @@ -999,7 +921,7 @@ static void board_spi_enable(void) { trace0(0, BRD, 0, "HOOK_CHIPSET_STARTUP - board_spi_enable"); - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[1], 1); /* Toggle SPI chip select to switch BMI160 from I2C mode * to SPI mode @@ -1014,14 +936,13 @@ DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, static void board_spi_disable(void) { trace0(0, BRD, 0, "HOOK_CHIPSET_SHUTDOWN - board_spi_disable"); - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[1], 0); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, MOTION_SENSE_HOOK_PRIO + 1); -#endif /* defined(HAS_TASK_MOTIONSENSE) */ #ifdef MEC1701_EVB_TACH_TEST /* PWM/TACH test */ -void tach0_isr(void) +static void tach0_isr(void) { MCHP_INT_DISABLE(MCHP_TACH_GIRQ) = MCHP_TACH_GIRQ_BIT(0); MCHP_INT_SOURCE(MCHP_TACH_GIRQ) = MCHP_TACH_GIRQ_BIT(0); diff --git a/board/mchpevb1/board.h b/board/mchpevb1/board.h index e46a1dced4..dd7c87fd6f 100644 --- a/board/mchpevb1/board.h +++ b/board/mchpevb1/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -39,6 +39,10 @@ * #define CONFIG_MCHP_LFW_DEBUG */ +/* + * EC UART console on UART 0 or 1 + */ +#define CONFIG_UART_CONSOLE 0 /* * Override Boot-ROM JTAG mode @@ -84,7 +88,6 @@ * #define EVB_NO_ESPI_TEST_MODE */ - /* * DEBUG * Disable ARM Cortex-M4 write buffer so @@ -93,24 +96,24 @@ * #define CONFIG_DEBUG_DISABLE_WRITE_BUFFER */ -/* New eSPI slave configuration items */ +/* New eSPI configuration items */ /* - * Maximum clock frequence eSPI EC slave advertises + * Maximum clock frequence eSPI EC advertises * Values in MHz are 20, 25, 33, 50, and 66 */ /* KBL + EVB fly-wire hook up only supports 20MHz */ -#define CONFIG_HOSTCMD_ESPI_EC_MAX_FREQ 20 +#define CONFIG_HOST_INTERFACE_ESPI_EC_MAX_FREQ MCHP_ESPI_CAP1_MAX_FREQ_20M /* - * EC eSPI slave advertises IO lanes + * EC eSPI advertises IO lanes * 0 = Single * 1 = Single and Dual * 2 = Single and Quad * 3 = Single, Dual, and Quad */ /* KBL + EVB fly-wire hook up only support Single mode */ -#define CONFIG_HOSTCMD_ESPI_EC_MODE 0 +#define CONFIG_HOST_INTERFACE_ESPI_EC_MODE MCHP_ESPI_CAP1_SINGLE_MODE /* * Bit map of eSPI channels EC advertises @@ -119,7 +122,7 @@ * bit[2] = 1 OOB channel * bit[3] = 1 Flash channel */ -#define CONFIG_HOSTCMD_ESPI_EC_CHAN_BITMAP 0x0F +#define CONFIG_HOST_INTERFACE_ESPI_EC_CHAN_BITMAP MCHP_ESPI_CAP0_ALL_CHAN_SUPP #define CONFIG_MCHP_ESPI_VW_SAVE_ON_SLEEP @@ -142,18 +145,13 @@ /* #define CONFIG_CHARGE_MANAGER */ /* #define CONFIG_CHARGE_RAMP_SW */ - /* #define CONFIG_CHARGER */ /* #define CONFIG_CHARGER_DISCHARGE_ON_AC */ /* #define CONFIG_CHARGER_ISL9237 */ /* #define CONFIG_CHARGER_ILIM_PIN_DISABLED */ -/* #define CONFIG_CHARGER_INPUT_CURRENT 512 */ - -/* - * MCHP disable this for Kabylake eSPI bring up - * #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 - */ +/* #define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 */ +/* #define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 */ /* #define CONFIG_CHARGER_NARROW_VDC */ /* #define CONFIG_CHARGER_PROFILE_OVERRIDE */ @@ -164,16 +162,17 @@ #define CONFIG_CHIPSET_SKYLAKE #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD #define CONFIG_CLOCK_CRYSTAL #define CONFIG_EXTPOWER_GPIO /* #define CONFIG_HOSTCMD_PD */ /* #define CONFIG_HOSTCMD_PD_PANIC */ #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_LED_COMMON @@ -190,7 +189,6 @@ * #define CONFIG_LOW_POWER_IDLE */ - /* #define CONFIG_GPIO_POWER_DOWN */ /* @@ -270,10 +268,10 @@ * Configure for smaller flash is OK for testing except * for SPI flash lock bit. */ - #define CONFIG_FLASH_SIZE 524288 - #define CONFIG_SPI_FLASH_W25X40 +#define CONFIG_FLASH_SIZE_BYTES 524288 +#define CONFIG_SPI_FLASH_W25X40 /* - * #define CONFIG_FLASH_SIZE 0x1000000 + * #define CONFIG_FLASH_SIZE_BYTES 0x1000000 * #define CONFIG_SPI_FLASH_W25Q128 */ @@ -321,7 +319,7 @@ * Make sure to not include GPSPI in little-firmware(LFW) */ #ifndef LFW -#define CONFIG_MCHP_GPSPI 0x01 +#define CONFIG_MCHP_GPSPI 0x01 #endif /* SPI Accelerometer @@ -360,9 +358,8 @@ #define GPIO_BAT_LED_GREEN GPIO_CHARGE_LED_2 /* I2C ports */ -#define I2C_CONTROLLER_COUNT 2 -#define I2C_PORT_COUNT 2 - +#define I2C_CONTROLLER_COUNT 2 +#define I2C_PORT_COUNT 2 /* * Map I2C Ports to Controllers for this board. @@ -377,26 +374,26 @@ * All other ports set to 0xff (not used) */ -#define I2C_PORT_PMIC MCHP_I2C_PORT10 -#define I2C_PORT_USB_CHARGER_1 MCHP_I2C_PORT2 -#define I2C_PORT_USB_MUX MCHP_I2C_PORT2 -#define I2C_PORT_USB_CHARGER_2 MCHP_I2C_PORT2 -#define I2C_PORT_PD_MCU MCHP_I2C_PORT3 -#define I2C_PORT_TCPC MCHP_I2C_PORT3 -#define I2C_PORT_ALS MCHP_I2C_PORT4 -#define I2C_PORT_ACCEL MCHP_I2C_PORT4 -#define I2C_PORT_BATTERY MCHP_I2C_PORT5 -#define I2C_PORT_CHARGER MCHP_I2C_PORT5 +#define I2C_PORT_PMIC MCHP_I2C_PORT10 +#define I2C_PORT_USB_CHARGER_1 MCHP_I2C_PORT2 +#define I2C_PORT_USB_MUX MCHP_I2C_PORT2 +#define I2C_PORT_USB_CHARGER_2 MCHP_I2C_PORT2 +#define I2C_PORT_PD_MCU MCHP_I2C_PORT3 +#define I2C_PORT_TCPC MCHP_I2C_PORT3 +#define I2C_PORT_ALS MCHP_I2C_PORT4 +#define I2C_PORT_ACCEL MCHP_I2C_PORT4 +#define I2C_PORT_BATTERY MCHP_I2C_PORT5 +#define I2C_PORT_CHARGER MCHP_I2C_PORT5 /* Thermal sensors read through PMIC ADC interface */ #if 0 -#define I2C_PORT_THERMAL I2C_PORT_PMIC +#define I2C_PORT_THERMAL I2C_PORT_PMIC #else -#define I2C_PORT_THERMAL MCHP_I2C_PORT4 +#define I2C_PORT_THERMAL MCHP_I2C_PORT4 #endif /* Ambient Light Sensor address */ -#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS /* Modules we want to exclude */ #undef CONFIG_CMD_HASH @@ -425,9 +422,9 @@ enum temp_sensor_id { /* These temp sensors are only readable in S0 */ TEMP_SENSOR_AMBIENT, TEMP_SENSOR_CASE, -/* TEMP_SENSOR_CHARGER, */ -/* TEMP_SENSOR_DRAM, */ -/* TEMP_SENSOR_WIFI, */ + /* TEMP_SENSOR_CHARGER, */ + /* TEMP_SENSOR_DRAM, */ + /* TEMP_SENSOR_WIFI, */ TEMP_SENSOR_COUNT }; @@ -453,37 +450,27 @@ enum als_id { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 /* Try to negotiate to 20V since i2c noise problems should be fixed. */ -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_VOLTAGE_MV 20000 /* * include TFDP macros from mchp chip level */ #include "tfdp_chip.h" - /* Map I2C port to controller */ int board_i2c_p2c(int port); -/* Return the two slave addresses the specified - * controller will respond to when controller - * is acting as a slave. - * b[6:0] = b[7:1] of I2C address 1 - * b[14:8] = b[7:1] of I2C address 2 - */ -uint16_t board_i2c_slave_addrs(int controller); - /* Reset PD MCU */ void board_reset_pd_mcu(void); diff --git a/board/mchpevb1/build.mk b/board/mchpevb1/build.mk index ffac227688..c92a045646 100644 --- a/board/mchpevb1/build.mk +++ b/board/mchpevb1/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,8 +10,8 @@ # external SPI is 512KB # external clock is crystal CHIP:=mchp -CHIP_FAMILY:=mec17xx -CHIP_VARIANT:=mec17xx_2E00 +CHIP_FAMILY:=mec170x +CHIP_VARIANT:=mec1701 CHIP_SPI_SIZE_KB:=512 board-y=board.o led.o diff --git a/board/mchpevb1/ec.tasklist b/board/mchpevb1/ec.tasklist index cdfdd45163..f187bb914a 100644 --- a/board/mchpevb1/ec.tasklist +++ b/board/mchpevb1/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,10 +9,10 @@ #define CONFIG_TASK_LIST \ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) diff --git a/board/mchpevb1/gpio.inc b/board/mchpevb1/gpio.inc index f3341b959a..b3aa29941e 100644 --- a/board/mchpevb1/gpio.inc +++ b/board/mchpevb1/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,10 +22,13 @@ * GPIO_0150 is JTAG_TMS */ +/* include common gpio.inc under chip/mchp/lfw/... */ +#include "chip/mchp/lfw/gpio.inc" + #define GPIO_BOTH_EDGES_PU (GPIO_INT_BOTH | GPIO_PULL_UP) -/* Only needed if CONFIG_HOSTCMD_ESPI is not set, using LPC interface to PCH */ -#ifndef CONFIG_HOSTCMD_ESPI +/* Only needed if CONFIG_HOST_INTERFACE_ESPI is not set, using LPC interface to PCH */ +#ifndef CONFIG_HOST_INTERFACE_ESPI GPIO_INT(PCH_PLTRST_L, PIN(064), GPIO_BOTH_EDGES_PU, lpcrst_interrupt) #endif @@ -294,23 +297,6 @@ GPIO(BOARD_VERSION1, PIN(0114), GPIO_INPUT) GPIO(BOARD_VERSION2, PIN(0207), GPIO_INPUT) GPIO(BOARD_VERSION3, PIN(0011), GPIO_INPUT) - -/* SPI - * Chip select must be open drain and driven high before SPI controller - * configuration. - */ -/* - * MEC1701H - * GPIO_0055/PWM2/SHD_CS0#/RSMRST# - * GPIO_0124/GPTP-OUT6/PVT_CS#/KSO11 - * QMSPI controller drives chip select, must be - * configured to alternative function. See below. - * Always use the name QMSPI_CS0 for chip select. - * Actual GPIO could be GPIO_0055 QMSPI shared chip select or - * GPIO_0124 private chip select. - */ -GPIO(QMSPI_CS0, PIN(055), GPIO_ODR_HIGH) - /* * MEC1701H GP-SPI0 chip select is GPIO_0003 * It is used as GPIO output. GPSPI chip level @@ -341,14 +327,6 @@ GPIO(TFDP_DATA, PIN(0171), GPIO_INPUT) #define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) #define GPIO_KB_OUTPUT (GPIO_ODR_HIGH) - -/* - * GPIO_0104(UART0_TX) Func1 - * GPIO_0105(UART0_RX) Func1 - * Bank 2 bits[4:5] - */ -ALTERNATE(PIN_MASK(2, 0x30), 1, MODULE_UART, 0) - /* KB pins */ /* * MEC1704H (144 pin package) @@ -413,25 +391,6 @@ ALTERNATE(PIN_MASK(1, 0xf000000), 2, MODULE_LPC, 0) * Function 1, Bank 1 bit[20] */ ALTERNATE(PIN_MASK(1, 0x100000), 1, MODULE_LPC, GPIO_PULL_UP) -/* MECC card SPI flash is connected to QMSPI Shared Port - * Also, MEC1701H Private SPI Port (Port 1) has pins multiplexed - * with KSO pins used in key scan! - * QMSPI Shared SPI Port (Port 0) - * NOTE: QMSPI Shared SPI Port pins are on VTR2 - */ -/* - * MEC1701H SHD SPI is connected to QMSPI controller. - * QMSPI drives chip select. SHD_CS0#(GPIO_0055) must be set - * to alternate function 2 and GPIO_ODR_HIGH. - * GPIO_0055 Function 2, Bank 1 bit[13] - */ -ALTERNATE(PIN_MASK(1, 0x2000), 2, MODULE_SPI_FLASH, GPIO_ODR_HIGH) -/* SHD_CLK - GPIO_0056 Function 2, Bank 1 bit[14] */ -ALTERNATE(PIN_MASK(1, 0x4000), 2, MODULE_SPI_FLASH, 0) -/* MOSI(SHD_IO0) - GPIO_0223 Function 2, Bank 4 bit[19] */ -/* MISO(SHD_IO1) - GPIO_0224 Function 2, Bank 4 bit[20] */ -ALTERNATE(PIN_MASK(4, 0x180000), 2, MODULE_SPI_FLASH, 0) - /* * MEC1701H GP-SPI0 Master * SPI0_CS# = GPIO_0003 Func 0(GPIO) Bank 0, bit 3 @@ -439,8 +398,8 @@ ALTERNATE(PIN_MASK(4, 0x180000), 2, MODULE_SPI_FLASH, 0) * SPI0_MISO = GPIO_0036 Func 2 Bank 0, bit 30 * SPI0_MOSI = GPIO_0004 Func 2 Bank 0, bit 4 */ -ALTERNATE(PIN_MASK(0, 0x00000008), 0, MODULE_SPI_MASTER, GPIO_ODR_HIGH) -ALTERNATE(PIN_MASK(0, 0x50000010), 2, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(0, 0x00000008), 0, MODULE_SPI_CONTROLLER, GPIO_ODR_HIGH) +ALTERNATE(PIN_MASK(0, 0x50000010), 2, MODULE_SPI_CONTROLLER, 0) /* I2C pins */ /* Using SMB00 as function 2 GP-SPI0 diff --git a/board/mchpevb1/led.c b/board/mchpevb1/led.c index 7b9f7646cb..6400b0a466 100644 --- a/board/mchpevb1/led.c +++ b/board/mchpevb1/led.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -30,8 +30,7 @@ * NOTE: GPIO_BAT_LED_xxx defined in board.h */ -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -40,7 +39,7 @@ enum led_color { LED_RED, LED_AMBER, LED_GREEN, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int bat_led_set_color(enum led_color color) @@ -68,8 +67,7 @@ static int bat_led_set_color(enum led_color color) return EC_SUCCESS; } -void led_get_brightness_range(enum ec_led_id led_id, - uint8_t *brightness_range) +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) { brightness_range[EC_LED_COLOR_RED] = 1; brightness_range[EC_LED_COLOR_GREEN] = 1; @@ -114,7 +112,6 @@ static void board_led_set_battery(void) { #ifdef CONFIG_CHARGER static int battery_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; @@ -122,41 +119,49 @@ static void board_led_set_battery(void) * Same as the chromeos spec * Green/Amber for CHARGE_FLAG_FORCE_IDLE */ - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: board_led_set_color_battery(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: /* Less than 3%, blink one second every two second */ if (!chipset_in_state(CHIPSET_STATE_ANY_OFF) && - charge_get_percent() < CRITICAL_LOW_BATTERY_PERCENTAGE) + charge_get_percent() < CRITICAL_LOW_BATTERY_PERCENTAGE) board_led_set_color_battery( (battery_ticks % LED_TOTAL_2SECS_TICKS < - LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); + LED_ON_1SEC_TICKS) ? + LED_AMBER : + LED_OFF); /* Less than 10%, blink one second every four seconds */ else if (!chipset_in_state(CHIPSET_STATE_ANY_OFF) && - charge_get_percent() < LOW_BATTERY_PERCENTAGE) + charge_get_percent() < LOW_BATTERY_PERCENTAGE) board_led_set_color_battery( (battery_ticks % LED_TOTAL_4SECS_TICKS < - LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); + LED_ON_1SEC_TICKS) ? + LED_AMBER : + LED_OFF); else board_led_set_color_battery(LED_OFF); break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: board_led_set_color_battery( (battery_ticks % LED_TOTAL_2SECS_TICKS < - LED_ON_1SEC_TICKS) ? LED_RED : LED_OFF); + LED_ON_1SEC_TICKS) ? + LED_RED : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: board_led_set_color_battery(LED_GREEN); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - board_led_set_color_battery( - (battery_ticks % LED_TOTAL_4SECS_TICKS < - LED_ON_2SECS_TICKS) ? LED_GREEN : LED_AMBER); - else - board_led_set_color_battery(LED_GREEN); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + board_led_set_color_battery(LED_GREEN); + break; + case LED_PWRS_FORCED_IDLE: + board_led_set_color_battery( + (battery_ticks % LED_TOTAL_4SECS_TICKS < + LED_ON_2SECS_TICKS) ? + LED_GREEN : + LED_AMBER); break; default: /* Other states don't alter LED behavior */ @@ -165,7 +170,6 @@ static void board_led_set_battery(void) #endif } - static void led_second(void) { if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) diff --git a/board/mchpevb1/lfw/gpio.inc b/board/mchpevb1/lfw/gpio.inc deleted file mode 100644 index f4142d3c29..0000000000 --- a/board/mchpevb1/lfw/gpio.inc +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Minimal set of GPIOs needed for LFW loader - */ - -/* - * MEC1701H GPIO_0055/PWM2/SHD_CS0#/RSMRST# - * MEC1701H QMSPI controller drives chip select, must be - * configured to alternative function. See below. - * GPIO_SHD_CS0 is used in board level spi_devices[] table - */ -GPIO(QMSPI_CS0, PIN(055), GPIO_ODR_HIGH) - - -/* Alternate functions GPIO definition */ - -/* - * UART - * GPIO_0104(UART0_TX) Func1 - * GPIO_0105(UART0_RX) Func1 - * Bank 2 bits[4:5] -*/ -ALTERNATE(PIN_MASK(2, 0x30), 1, MODULE_UART, 0) - -/* SPI pins */ -/* - * MEC1701H SHD SPI is connected to QMSPI controller. - * QMSPI drives chip select. SHD_CS0#(GPIO_0055) must be set - * to alternate function 2 and GPIO_ODR_HIGH. - * GPIO_0055 Function 2, Bank 1 bit[13] - */ -ALTERNATE(PIN_MASK(1, 0x2000), 2, MODULE_SPI_FLASH, GPIO_ODR_HIGH) -/* SHD_CLK - GPIO_0056 Function 2, Bank 1 bit[14] */ -ALTERNATE(PIN_MASK(1, 0x4000), 2, MODULE_SPI_FLASH, 0) -/* MOSI(SHD_IO0) - GPIO_0223 Function 2, Bank 4 bit[19] */ -/* MISO(SHD_IO1) - GPIO_0224 Function 2, Bank 4 bit[20] */ -ALTERNATE(PIN_MASK(4, 0x180000), 2, MODULE_SPI_FLASH, 0) - - diff --git a/board/mchpevb1/lfw/vif_override.xml b/board/mchpevb1/lfw/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/mchpevb1/lfw/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/mchpevb1/usb_pd_policy.c b/board/mchpevb1/usb_pd_policy.c index 690f8b8a3c..107b5029cf 100644 --- a/board/mchpevb1/usb_pd_policy.c +++ b/board/mchpevb1/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,23 +14,20 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_set_power_supply_ready(int port) { /* Disable charging */ - gpio_set_level(port ? GPIO_USB_C1_CHARGE_EN_L : - GPIO_USB_C0_CHARGE_EN_L, 1); + gpio_set_level(port ? GPIO_USB_C1_CHARGE_EN_L : GPIO_USB_C0_CHARGE_EN_L, + 1); /* Provide VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN, 1); + gpio_set_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN, 1); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -41,8 +38,7 @@ int pd_set_power_supply_ready(int port) void pd_power_supply_reset(int port) { /* Disable VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN, 0); + gpio_set_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN, 0); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/board/meep/battery.c b/board/meep/battery.c index eced940973..56434d98da 100644 --- a/board/meep/battery.c +++ b/board/meep/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -33,7 +33,7 @@ */ const struct board_batt_params board_battery_info[] = { /* DynaPack Coslight Battery Information */ - [BATTERY_DANAPACK_COS] = { + [BATTERY_DYNAPACK_COS] = { .fuel_gauge = { .manuf_name = "333-2C-DA-A", .ship_mode = { @@ -62,7 +62,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack ATL Battery Information */ - [BATTERY_DANAPACK_ATL] = { + [BATTERY_DYNAPACK_ATL] = { .fuel_gauge = { .manuf_name = "333-27-DA-A", .ship_mode = { @@ -91,7 +91,7 @@ const struct board_batt_params board_battery_info[] = { }, /* DynaPack SDI Battery Information */ - [BATTERY_DANAPACK_SDI] = { + [BATTERY_DYNAPACK_SDI] = { .fuel_gauge = { .manuf_name = "333-24-DA-A", .ship_mode = { @@ -234,7 +234,36 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 60, }, }, + + /* CosMX B00C4473A9D0002 Battery Information */ + [BATTERY_COS] = { + .fuel_gauge = { + .manuf_name = "333-AC-DA-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DANAPACK_COS; +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; diff --git a/board/meep/board.c b/board/meep/board.c index 0577671755..62e4881b1b 100644 --- a/board/meep/board.c +++ b/board/meep/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Meep/Mimrock board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery.h" #include "button.h" #include "cbi_ssfc.h" @@ -36,20 +35,20 @@ #include "switch.h" #include "system.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) -#define USB_PD_PORT_ANX7447 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 #ifdef CONFIG_KEYBOARD_KEYPAD #error "KSO_14 was repurposed to PPC_ID pin so CONFIG_KEYBOARD_KEYPAD \ @@ -87,32 +86,32 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, /* Vbus C0 sensing (10x voltage divider). PPVAR_USB_C0_VBUS */ - [ADC_VBUS_C0] = { - "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C0] = { "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* Vbus C1 sensing (10x voltage divider). PPVAR_USB_C1_VBUS */ - [ADC_VBUS_C1] = { - "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C1] = { "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -122,17 +121,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t lid_standrd_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t lid_standrd_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* sensor private data */ static struct kionix_accel_data kx022_data; @@ -177,8 +172,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &base_standard_ref, @@ -209,8 +202,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -233,9 +224,9 @@ int board_is_convertible(void) * Vortininja: 49, 50, 51, 52 * Unprovisioned: 255 */ - return sku_id == 1 || sku_id == 2 || sku_id == 3 || - sku_id == 4 || sku_id == 49 || sku_id == 50 || - sku_id == 51 || sku_id == 52 || sku_id == 255; + return sku_id == 1 || sku_id == 2 || sku_id == 3 || sku_id == 4 || + sku_id == 49 || sku_id == 50 || sku_id == 51 || sku_id == 52 || + sku_id == 255; } static void board_update_sensor_config_from_sku(void) @@ -311,17 +302,16 @@ void board_hibernate_late(void) const uint32_t hibernate_pins[][2] = { /* Turn off LEDs before going to hibernate */ - {GPIO_BAT_LED_WHITE_L, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_BAT_LED_AMBER_L, GPIO_INPUT | GPIO_PULL_UP}, + { GPIO_BAT_LED_WHITE_L, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_BAT_LED_AMBER_L, GPIO_INPUT | GPIO_PULL_UP }, }; for (i = 0; i < ARRAY_SIZE(hibernate_pins); ++i) gpio_set_flags(hibernate_pins[i][0], hibernate_pins[i][1]); } -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -334,7 +324,6 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif #ifdef CONFIG_KEYBOARD_FACTORY_TEST /* @@ -343,15 +332,15 @@ void lid_angle_peripheral_enable(int enable) * The connector has 24 pins total, and there is no pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {1, 4}, {1, 3}, {1, 6}, {1, 7}, - {3, 1}, {2, 0}, {1, 5}, {2, 6}, {2, 7}, - {2, 1}, {2, 4}, {2, 5}, {1, 2}, {2, 3}, - {2, 2}, {3, 0}, {-1, -1}, {-1, -1}, {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); #endif void board_overcurrent_event(int port, int is_overcurrented) @@ -396,31 +385,29 @@ __override uint16_t board_get_ps8xxx_product_id(int port) } static const struct ppc_config_t ppc_syv682x_port0 = { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, }; static const struct ppc_config_t ppc_syv682x_port1 = { - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, }; static void board_setup_ppc(void) { if (c0_port_ppc == PPC_SYV682X) { - memcpy(&ppc_chips[USB_PD_PORT_TCPC_0], - &ppc_syv682x_port0, - sizeof(struct ppc_config_t)); + memcpy(&ppc_chips[USB_PD_PORT_TCPC_0], &ppc_syv682x_port0, + sizeof(struct ppc_config_t)); gpio_set_flags(GPIO_USB_PD_C0_INT_ODL, GPIO_INT_BOTH); } if (c1_port_ppc == PPC_SYV682X) { - memcpy(&ppc_chips[USB_PD_PORT_TCPC_1], - &ppc_syv682x_port1, - sizeof(struct ppc_config_t)); + memcpy(&ppc_chips[USB_PD_PORT_TCPC_1], &ppc_syv682x_port1, + sizeof(struct ppc_config_t)); gpio_set_flags(GPIO_USB_PD_C1_INT_ODL, GPIO_INT_BOTH); } diff --git a/board/meep/board.h b/board/meep/board.h index 570cbd5f7c..6f437fb852 100644 --- a/board/meep/board.h +++ b/board/meep/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,20 +13,17 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + #define CONFIG_VOLUME_BUTTONS #define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL #define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -/* EC console commands */ -#define CONFIG_CMD_ACCELS -#define CONFIG_CMD_ACCEL_INFO - #define CONFIG_LED_COMMON -#define CONFIG_LED_POWER_LED /* Sensors */ -#define CONFIG_ACCEL_KX022 /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) @@ -56,6 +53,8 @@ #define CONFIG_USBC_PPC_DEDICATED_INT #undef CONFIG_SYV682X_HV_ILIM #define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 +/* SYV682 isn't connected to CC, so TCPC must provide VCONN */ +#define CONFIG_USBC_PPC_SYV682X_NO_CC /* Additional TCPC second source in Port 1 */ #define CONFIG_USB_PD_TCPM_MULTI_PS8XXX @@ -67,10 +66,10 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ - ADC_VBUS_C0, /* ADC9 */ - ADC_VBUS_C1, /* ADC4 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_VBUS_C0, /* ADC9 */ + ADC_VBUS_C1, /* ADC4 */ ADC_CH_COUNT }; @@ -81,27 +80,20 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; enum battery_type { - BATTERY_DANAPACK_COS, - BATTERY_DANAPACK_ATL, - BATTERY_DANAPACK_SDI, + BATTERY_DYNAPACK_COS, + BATTERY_DYNAPACK_ATL, + BATTERY_DYNAPACK_SDI, BATTERY_SAMSUNG_SDI, BATTERY_SIMPLO_COS, BATTERY_SIMPLO_ATL, BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COS, BATTERY_TYPE_COUNT, }; @@ -111,11 +103,6 @@ enum ppc_type { PPC_TYPE_COUNT, }; -#ifdef CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; -#endif - int board_is_convertible(void); #endif /* !__ASSEMBLER__ */ diff --git a/board/meep/build.mk b/board/meep/build.mk index 3d04b75731..998a65a3de 100644 --- a/board/meep/build.mk +++ b/board/meep/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/meep/ec.tasklist b/board/meep/ec.tasklist index d98db145e7..977b8b01be 100644 --- a/board/meep/ec.tasklist +++ b/board/meep/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/meep/gpio.inc b/board/meep/gpio.inc index ebb69bdf53..aeb659624a 100644 --- a/board/meep/gpio.inc +++ b/board/meep/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/meep/led.c b/board/meep/led.c index 7baedca253..dab78ccad4 100644 --- a/board/meep/led.c +++ b/board/meep/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -7,48 +7,56 @@ #include "ec_commands.h" #include "gpio.h" +#include "hooks.h" #include "led_common.h" #include "led_onoff_states.h" -#include "hooks.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1; +__override const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* Meep: Note there is only LED for charge / power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0_BAT_LOW] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - /* STATE_DISCHARGE_S3 will changed if sku is clamshells */ - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_WHITE, 0.5 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + /* STATE_DISCHARGE_S3 will changed if sku is clamshells */ + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_WHITE, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 1 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; static void s3_led_init(void) { @@ -68,7 +76,7 @@ DECLARE_HOOK(HOOK_INIT, s3_led_init, HOOK_PRIO_DEFAULT); const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_ON_LVL); @@ -77,7 +85,7 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: @@ -123,4 +131,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/meep/vif_override.xml b/board/meep/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/meep/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/metaknight/battery.c b/board/metaknight/battery.c new file mode 100644 index 0000000000..cff274ae4f --- /dev/null +++ b/board/metaknight/battery.c @@ -0,0 +1,68 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all metaknight battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* Simplo PC-VP-BP44 Battery Information */ + [BATTERY_SMP_PCVPBP144] = { + .fuel_gauge = { + .manuf_name = "SIMPLO", + .device_name = "PC-VP-BP144", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x10, + .disconnect_val = 0x00, + .cfet_mask = 0x08, + .cfet_off_val = 0x00, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 128, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP_PCVPBP144; diff --git a/board/metaknight/board.c b/board/metaknight/board.c new file mode 100644 index 0000000000..7675c7c8f5 --- /dev/null +++ b/board/metaknight/board.c @@ -0,0 +1,880 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* metaknight board-specific configuration */ + +#include "adc.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/nb7v904m.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/pi3usb3x532.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "stdbool.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +#define ADC_VOL_UP_MASK BIT(0) +#define ADC_VOL_DOWN_MASK BIT(1) + +static uint8_t new_adc_key_state; + +/* USB-A Configuration */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, + GPIO_EN_USB_A1_VBUS, +}; + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + int hdmi_hpd_odl = gpio_get_level(GPIO_HDMI_HPD_SUB_ODL); + + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, !hdmi_hpd_odl); + + cprints(CC_SYSTEM, "HDMI plug-%s", !hdmi_hpd_odl ? "in" : "out"); +} + +/** + * Handle debounced pen input changing state. + */ +static void pen_input_deferred(void) +{ + int pen_charge_enable = !gpio_get_level(GPIO_PEN_DET_ODL) && + !chipset_in_state(CHIPSET_STATE_ANY_OFF); + + if (pen_charge_enable) + gpio_set_level(GPIO_EN_PP3300_PEN, 1); + else + gpio_set_level(GPIO_EN_PP3300_PEN, 0); + + CPRINTS("Pen charge %sable", pen_charge_enable ? "en" : "dis"); +} +DECLARE_DEFERRED(pen_input_deferred); + +void pen_input_interrupt(enum gpio_signal signal) +{ + /* pen input debounce time */ + hook_call_deferred(&pen_input_deferred_data, (100 * MSEC)); +} + +static void pen_charge_check(void) +{ + hook_call_deferred(&pen_input_deferred_data, (100 * MSEC)); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pen_charge_check, HOOK_PRIO_LAST); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pen_charge_check, HOOK_PRIO_LAST); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SUB_ANALOG] = { + .name = "SUB_ANALOG", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + + [TEMP_SENSOR_MEMORY] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_CPU] = { .name = "CPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_MEMORY \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_memory = + THERMAL_MEMORY; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; + +static void setup_thermal(void) +{ + thermal_params[TEMP_SENSOR_MEMORY] = thermal_memory; + thermal_params[TEMP_SENSOR_CPU] = thermal_cpu; +} + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +#ifdef BOARD_WADDLEDOO +static void reconfigure_5v_gpio(void) +{ + /* + * b/147257497: On early waddledoo boards, GPIO_EN_PP5000 was swapped + * with GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that + * GPIO instead for those boards. Note that this breaks the volume up + * button functionality. + */ + if (system_get_board_version() < 0) { + CPRINTS("old board - remapping 5V en"); + gpio_set_flags(GPIO_VOLUP_BTN_ODL, GPIO_OUT_LOW); + } +} +DECLARE_HOOK(HOOK_INIT, reconfigure_5v_gpio, HOOK_PRIO_INIT_I2C + 1); +#endif /* BOARD_WADDLEDOO */ + +static void set_5v_gpio(int level) +{ + int version; + enum gpio_signal gpio = GPIO_EN_PP5000; + + /* + * b/147257497: On early waddledoo boards, GPIO_EN_PP5000 was swapped + * with GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that + * GPIO instead for those boards. Note that this breaks the volume up + * button functionality. + */ + if (IS_ENABLED(BOARD_WADDLEDOO)) { + version = system_get_board_version(); + + /* + * If the CBI EEPROM wasn't formatted, assume it's a very early + * board. + */ + gpio = version < 0 ? GPIO_VOLUP_BTN_ODL : GPIO_EN_PP5000; + } + + gpio_set_level(gpio, level); +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC, or send enable signal to HDMI + * DB. + */ + set_5v_gpio(!!enable); + + if (get_cbi_fw_config_db() == DB_1A_HDMI || + get_cbi_fw_config_db() == DB_LTE_HDMI) { + gpio_set_level(GPIO_SUB_C1_INT_EN_RAILS_ODL, !enable); + } +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + return CONFIG_USB_PD_PORT_MAX_COUNT; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + return CHARGER_NUM; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +/* Sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_lsm6dsm_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static struct accelgyro_saved_data_t g_bma253_data; +static struct bmi_drv_data_t g_bmi160_data; +static struct kionix_accel_data g_kx022_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; +static struct icm_drv_data_t g_icm426xx_data; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t lsm6dsm_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DS3, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_lsm6dsm_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t lsm6dsm_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DS3, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_lsm6dsm_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, enough for laptop */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +static int base_gyro_config; + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + check_c0_line(); + + if (get_cbi_fw_config_db() == DB_1A_HDMI || + get_cbi_fw_config_db() == DB_LTE_HDMI) { + /* Disable i2c on HDMI pins */ + gpio_config_pin(MODULE_I2C, GPIO_HDMI_HPD_SUB_ODL, 0); + gpio_config_pin(MODULE_I2C, GPIO_GPIO92_NC, 0); + + gpio_set_flags(GPIO_SUB_C1_INT_EN_RAILS_ODL, GPIO_ODR_HIGH); + + /* Select HDMI option */ + gpio_set_level(GPIO_HDMI_SEL_L, 0); + + /* Enable interrupt for passing through HPD */ + gpio_enable_interrupt(GPIO_HDMI_HPD_SUB_ODL); + } else { + /* Set SDA as an input */ + gpio_set_flags(GPIO_HDMI_HPD_SUB_ODL, GPIO_INPUT); + } + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + /* Enable gpio interrupt for pen detect */ + gpio_enable_interrupt(GPIO_PEN_DET_ODL); + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + /* Initialize g-sensor */ + base_gyro_config = get_cbi_ssfc_base_sensor(); + + if (base_gyro_config == SSFC_SENSOR_LSM6DSM) { + motion_sensors[BASE_ACCEL] = lsm6dsm_base_accel; + motion_sensors[BASE_GYRO] = lsm6dsm_base_gyro; + cprints(CC_SYSTEM, "SSFC: BASE GYRO is LSM6DSM"); + } else if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + cprints(CC_SYSTEM, "SSFC: BASE GYRO is ICM426XX"); + } else + cprints(CC_SYSTEM, "SSFC: BASE GYRO is BMI160"); + + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + cprints(CC_SYSTEM, "SSFC: LID ACCEL is KX022"); + } else + cprints(CC_SYSTEM, "SSFC: LID ACCEL is BMA253"); + + /* Initial thermal */ + setup_thermal(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + .alert_signal = GPIO_USB_C0_INT_ODL, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + }, +}; + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + int p; + + /* + * The interrupt line is shared between the TCPC and BC1.2 + * detector IC. Therefore, go out and actually read the alert + * registers to report the alert status. + */ + for (p = 0; p < board_get_usb_pd_port_count(); p++) { + if (gpio_get_level(tcpc_config[p].alert_signal) || + tcpc_read16(p, TCPC_REG_ALERT, ®val)) + continue; + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[p].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~(BIT(14) | BIT(13) | BIT(12)); + if (regval) + status |= (PD_STATUS_TCPC_ALERT_0 << p); + } + + return status; +} + +int adc_to_physical_value(enum gpio_signal gpio) +{ + if (gpio == GPIO_VOLUME_UP_L) + return !!(new_adc_key_state & ADC_VOL_UP_MASK); + else if (gpio == GPIO_VOLUME_DOWN_L) + return !!(new_adc_key_state & ADC_VOL_DOWN_MASK); + + CPRINTS("Not a volume up or down key"); + return 0; +} + +int button_is_adc_detected(enum gpio_signal gpio) +{ + return (gpio == GPIO_VOLUME_DOWN_L) || (gpio == GPIO_VOLUME_UP_L); +} + +static void adc_vol_key_press_check(void) +{ + int volt = adc_read_channel(ADC_SUB_ANALOG); + static uint8_t old_adc_key_state; + uint8_t adc_key_state_change; + + if (volt > 2400 && volt < 2540) { + /* volume-up is pressed */ + new_adc_key_state = ADC_VOL_UP_MASK; + } else if (volt > 2600 && volt < 2740) { + /* volume-down is pressed */ + new_adc_key_state = ADC_VOL_DOWN_MASK; + } else if (volt < 2300) { + /* both volumn-up and volume-down are pressed */ + new_adc_key_state = ADC_VOL_UP_MASK | ADC_VOL_DOWN_MASK; + } else if (volt > 2780) { + /* both volumn-up and volume-down are released */ + new_adc_key_state = 0; + } + if (new_adc_key_state != old_adc_key_state) { + adc_key_state_change = old_adc_key_state ^ new_adc_key_state; + if (adc_key_state_change & ADC_VOL_UP_MASK) + button_interrupt(GPIO_VOLUME_UP_L); + if (adc_key_state_change & ADC_VOL_DOWN_MASK) + button_interrupt(GPIO_VOLUME_DOWN_L); + + old_adc_key_state = new_adc_key_state; + } +} +DECLARE_HOOK(HOOK_TICK, adc_vol_key_press_check, HOOK_PRIO_DEFAULT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} + +#ifndef TEST_BUILD +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_gyro_config) { + case SSFC_SENSOR_LSM6DSM: + lsm6dsm_interrupt(signal); + break; + case SSFC_SENSOR_ICM426XX: + icm426xx_interrupt(signal); + break; + case SSFC_SENSOR_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +const struct i2c_port_t i2c_ports[] = { + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + + { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BATTERY_SCL, + .sda = GPIO_EC_I2C_BATTERY_SDA }, + + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, + + { .name = "usbc0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_SCL, + .sda = GPIO_EC_I2C_USB_C0_SDA }, +#if CONFIG_USB_PD_PORT_MAX_COUNT > 1 + { .name = "sub_usbc1", + .port = I2C_PORT_SUB_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C_SUB_USB_C1_SCL, + .sda = GPIO_EC_I2C_SUB_USB_C1_SDA }, +#endif +}; + +#endif diff --git a/board/metaknight/board.h b/board/metaknight/board.h new file mode 100644 index 0000000000..cab1501256 --- /dev/null +++ b/board/metaknight/board.h @@ -0,0 +1,186 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* metaknight board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_DEDEDE_EC_NPCX796FC +#include "baseboard.h" + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 + +/* + * GPIO for C1 interrupts, for baseboard use + * + * Note this line might already have its pull up disabled for HDMI DBs, but + * it should be fine to set again before z-state. + */ +#define GPIO_USB_C1_INT_ODL GPIO_SUB_C1_INT_EN_RAILS_ODL + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES + +/* PWM */ +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ + +/* Temp sensor */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THROTTLE_AP +#define CONFIG_THERMISTOR_NCP15WB +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 +#define CONFIG_USBC_RETIMER_NB7V904M + +/* Common USB-A defines */ +#define USB_PORT_COUNT 2 +#define CONFIG_USB_PORT_POWER_SMART +#define CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY +#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_CDP +#define CONFIG_USB_PORT_POWER_SMART_INVERTED +#define GPIO_USB1_ILIM_SEL GPIO_USB_A0_CHARGE_EN_L +#define GPIO_USB2_ILIM_SEL GPIO_USB_A1_CHARGE_EN_L + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +/* TODO(b:147440290): Need to handle multiple charger ICs */ +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ + +/* + * I2C pin names for baseboard + * + * Note: these lines will be set as i2c on start-up, but this should be + * okay since they're ODL. + */ +#define GPIO_EC_I2C_SUB_USB_C1_SCL GPIO_GPIO92_NC +#define GPIO_EC_I2C_SUB_USB_C1_SDA GPIO_HDMI_HPD_SUB_ODL + +/* Sensors */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel second source */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel second source */ +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel second source */ + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* Volume Button feature */ +#define CONFIG_ADC_BUTTONS +#define CONFIG_VOLUME_BUTTONS +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL + +#ifdef BOARD_METAKNIGHT_LEGACY +/* this change saves 1656 bytes of RW flash space */ +#define CONFIG_CHIP_INIT_ROM_REGION +#define CONFIG_DEBUG_ASSERT_BRIEF +#else +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION +#endif + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_NUM, +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { TEMP_SENSOR_MEMORY, TEMP_SENSOR_CPU, TEMP_SENSOR_COUNT }; + +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum pwm_channel { + PWM_CH_COUNT, +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_SMP_PCVPBP144, + BATTERY_TYPE_COUNT, +}; + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/metaknight/build.mk b/board/metaknight/build.mk new file mode 100644 index 0000000000..1531d1f3ae --- /dev/null +++ b/board/metaknight/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=dedede + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/metaknight/cbi_ssfc.c b/board/metaknight/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/metaknight/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/metaknight/cbi_ssfc.h b/board/metaknight/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/metaknight/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/metaknight/ec.tasklist b/board/metaknight/ec.tasklist new file mode 100644 index 0000000000..6316569c9a --- /dev/null +++ b/board/metaknight/ec.tasklist @@ -0,0 +1,22 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/metaknight/gpio.inc b/board/metaknight/gpio.inc new file mode 100644 index 0000000000..4d68595d65 --- /dev/null +++ b/board/metaknight/gpio.inc @@ -0,0 +1,152 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) + + +/* Button interrupts */ +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(LID_360_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(PEN_DET_ODL, PIN(5, 0), GPIO_INT_BOTH, pen_input_interrupt) +GPIO_INT(HDMI_HPD_SUB_ODL, PIN(9, 1), GPIO_INT_BOTH, sub_hdmi_hpd_interrupt) /* HDMI_HPD */ + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) + +/* Extra Sub-board I/O pins */ +GPIO(EC_SUB_IO_2, PIN(3, 4), GPIO_OUT_LOW) + +/* Misc Enables */ +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_PEN, PIN(6, 3), GPIO_OUT_LOW) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(ECH1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(SUB_C1_INT_EN_RAILS_ODL, PIN(F, 5), GPIO_ODR_LOW)/* 5V power en */ + +/* LED */ +GPIO(LED_W_ODL, PIN(C, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) /* LED White */ +GPIO(LED_Y_ODL, PIN(C, 4), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) /* LED Amber */ + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) + +/* USB pins */ +GPIO(USB_C0_RST_ODL, PIN(9, 7), GPIO_OUT_HIGH) /* currently unused */ +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(7, 2), GPIO_OUT_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(USB_A0_CHARGE_EN_L, PIN(3, 7), GPIO_OUT_HIGH) /* Enable A0 1.5A Charging */ +GPIO(USB_A1_CHARGE_EN_L, PIN(F, 3), GPIO_OUT_HIGH) /* Enable A1 1.5A Charging */ +GPIO(EN_USB_A0_VBUS, PIN(4, 1), GPIO_OUT_LOW) /* Enable A1 5V Charging */ +GPIO(EN_USB_A1_VBUS, PIN(F, 2), GPIO_OUT_LOW) /* Enable A1 5V Charging */ + +/* + * metaknight doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) +UNIMPLEMENTED(VOLDN_BTN_ODL) +UNIMPLEMENTED(VOLUP_BTN_ODL) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* ADC0-2 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* PWM */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* PWM3 */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO00_NC, PIN(0, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO40_NC, PIN(4, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO60_NC, PIN(6, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO73_NC, PIN(7, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO80_NC, PIN(8, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO92_NC, PIN(9, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOC2_NC, PIN(C, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/metaknight/led.c b/board/metaknight/led.c new file mode 100644 index 0000000000..f117146f48 --- /dev/null +++ b/board/metaknight/led.c @@ -0,0 +1,86 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Metaknight + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1; + +__override const int led_charge_lvl_2 = 100; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_W_ODL, LED_ON_LVL); + gpio_set_level(GPIO_LED_Y_ODL, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_W_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_Y_ODL, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_W_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_Y_ODL, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} diff --git a/board/metaknight/usb_pd_policy.c b/board/metaknight/usb_pd_policy.c new file mode 100644 index 0000000000..23166f7fca --- /dev/null +++ b/board/metaknight/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/metaknight/vif_override.xml b/board/metaknight/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/metaknight/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/mithrax/battery.c b/board/mithrax/battery.c new file mode 100644 index 0000000000..16840d5b3d --- /dev/null +++ b/board/mithrax/battery.c @@ -0,0 +1,122 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "compile_time_macros.h" + +/* + * Battery info for all Mithrax battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + [BATTERY_C536] = { + /* BQ40Z50 Fuel Gauge */ + .fuel_gauge = { + .manuf_name = "AS3GXAE3jB", + .device_name = "C536-49", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x2000, /* XDSG */ + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11800, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + [BATTERY_C490] = { + .fuel_gauge = { + .manuf_name = "AS3GWQd3jB", + .device_name = "C490-42", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x2000, /* XDSG */ + .disconnect_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11800, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + [BATTERY_C340] = { + .fuel_gauge = { + .manuf_name = "AS3FXXD3KB", + .device_name = "C340152", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000C, + .disconnect_val = 0x000C, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0004, + } + }, + .batt_info = { + .voltage_max = 13350, + .voltage_normal = 11985, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_C536; diff --git a/board/mithrax/board.c b/board/mithrax/board.c new file mode 100644 index 0000000000..49d2849ab1 --- /dev/null +++ b/board/mithrax/board.c @@ -0,0 +1,184 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "keyboard_backlight.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "rgb_keyboard.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void rgb_backlight_config(void); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +__override void board_cbi_init(void) +{ + config_usb_db_type(); +} + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S5 -> S3 transition */ +static void board_chipset_startup(void) +{ + pen_config(); + rgb_backlight_config(); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} + +static void board_init(void) +{ + if (ec_cfg_stylus() == STYLUS_PRSENT) + gpio_enable_interrupt(GPIO_PEN_DET_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/** + * Deferred function to handle pen detect change + */ +static void pendetect_deferred(void) +{ + static int debounced_pen_detect; + int pen_detect = !gpio_get_level(GPIO_PEN_DET_ODL); + + if (pen_detect == debounced_pen_detect) + return; + + debounced_pen_detect = pen_detect; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) + gpio_set_level(GPIO_EN_PP5000_PEN, debounced_pen_detect); +} +DECLARE_DEFERRED(pendetect_deferred); +DECLARE_HOOK(HOOK_INIT, pendetect_deferred, HOOK_PRIO_DEFAULT); + +void pen_detect_interrupt(enum gpio_signal s) +{ + /* Trigger deferred notification of pen detect change */ + hook_call_deferred(&pendetect_deferred_data, 500 * MSEC); +} + +void pen_config(void) +{ + if (ec_cfg_stylus() == STYLUS_PRSENT) { + /* Make sure pen detection is triggered or not at resume */ + if (!gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_EN_PP5000_PEN, 1); + else + gpio_set_level(GPIO_EN_PP5000_PEN, 0); + } +} + +static void board_chipset_shutdown(void) +{ + gpio_set_level(GPIO_EN_PP5000_PEN, 0); + gpio_set_level(GPIO_EN_PP5000_LED, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); + +static void rgb_backlight_config(void) +{ + if (ec_cfg_kb_backlight() == RGB) + gpio_set_level(GPIO_EN_PP5000_LED, 1); + else + gpio_set_level(GPIO_EN_PP5000_LED, 0); +} + +void board_kblight_init(void) +{ + if ((IS_ENABLED(CONFIG_PWM_KBLIGHT)) && + (ec_cfg_kb_backlight() == SOLID_COLOR)) { + kblight_register(&kblight_pwm); + rgbkbd_type = EC_RGBKBD_TYPE_UNKNOWN; + } else if ((IS_ENABLED(CONFIG_RGB_KEYBOARD)) && + (ec_cfg_kb_backlight() == RGB)) { + kblight_register(&kblight_rgbkbd); + rgbkbd_type = EC_RGBKBD_TYPE_FOUR_ZONES_4_LEDS; + } +} diff --git a/board/mithrax/board.h b/board/mithrax/board.h new file mode 100644 index 0000000000..22878a936d --- /dev/null +++ b/board/mithrax/board.h @@ -0,0 +1,240 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Mithrax board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* KEYBOARD */ +#define CONFIG_KEYBOARD_CUSTOMIZATION +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* LED */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 +#define GPIO_BAT_LED_AMBER_L GPIO_LED_3_L +#define GPIO_BAT_LED_WHITE_L GPIO_LED_4_L + +/* Sensors */ +#define CONFIG_ACCELGYRO_LSM6DSO /* Base accel */ +#define CONFIG_ACCEL_LSM6DSO_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +/* Lid accel */ +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_ACCEL_LIS2DWL +#define CONFIG_ACCEL_LIS2DW_AS_BASE +#define CONFIG_ACCEL_LIS2DW12_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USB_PD_TCPM_PS8815 + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +/* Disable console commands to help save space */ +#undef CONFIG_CMD_POWERINDEBUG + +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_NX20P3483 + +/* TODO: b/177608416 - measure and check these values on mithrax */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 65000 +#define PD_MAX_CURRENT_MA 3250 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_KEYBOARD_BACKLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C2_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C2_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C2_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C2_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 +#define I2C_PORT_KBMCU NPCX_I2C_PORT3_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* + * + */ + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 10 + +/* RGB Keyboard */ +#ifdef SECTION_IS_RW +#define CONFIG_RGB_KEYBOARD +#define CONFIG_LED_DRIVER_TLC59116F /* TLC59116F on I2C */ +#define TLC59116F_I2C_ADDR_FLAG TLC59116F_ADDR3_FLAG +#endif /* SECTION_IS_RW */ +#define RGB_GRID0_COL 4 +#define RGB_GRID0_ROW 1 + +#define CONFIG_PWM_KBLIGHT + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_FAN, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_FAN, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { LID_ACCEL = 0, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum ioex_port { IOEX_C2_NCT38XX = 0, IOEX_C1_NCT38XX, IOEX_PORT_COUNT }; + +enum battery_type { + BATTERY_C536, + BATTERY_C490, + BATTERY_C340, + BATTERY_TYPE_COUNT +}; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +void pen_detect_interrupt(enum gpio_signal s); + +void pen_config(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/mithrax/build.mk b/board/mithrax/build.mk new file mode 100644 index 0000000000..ca2d2e6c70 --- /dev/null +++ b/board/mithrax/build.mk @@ -0,0 +1,26 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Mithrax board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger_isl9241.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o +board-y+=keyboard_customization.o diff --git a/board/mithrax/charger_isl9241.c b/board/mithrax/charger_isl9241.c new file mode 100644 index 0000000000..76e2712181 --- /dev/null +++ b/board/mithrax/charger_isl9241.c @@ -0,0 +1,80 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/mithrax/ec.tasklist b/board/mithrax/ec.tasklist new file mode 100644 index 0000000000..8949bb98e7 --- /dev/null +++ b/board/mithrax/ec.tasklist @@ -0,0 +1,31 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(RGBKBD, rgbkbd_task, NULL, BASEBOARD_RGBKBD_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/mithrax/fans.c b/board/mithrax/fans.c new file mode 100644 index 0000000000..9dbc34589e --- /dev/null +++ b/board/mithrax/fans.c @@ -0,0 +1,82 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1100, + .rpm_start = 2000, + .rpm_max = 5000, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/181271666): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/mithrax/fw_config.c b/board/mithrax/fw_config.c new file mode 100644 index 0000000000..17b623371f --- /dev/null +++ b/board/mithrax/fw_config.c @@ -0,0 +1,60 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union mithrax_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for mithrax if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union mithrax_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_PS8815, + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Mithrax FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union mithrax_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void) +{ + return fw_config.usb_db; +} + +enum ec_cfg_usb_mb_type ec_cfg_usb_mb_type(void) +{ + return fw_config.usb_mb; +} + +enum ec_cfg_stylus_type ec_cfg_stylus(void) +{ + return fw_config.stylus; +} + +enum ec_cfg_kb_backlight_type ec_cfg_kb_backlight(void) +{ + return fw_config.rgb; +} diff --git a/board/mithrax/fw_config.h b/board/mithrax/fw_config.h new file mode 100644 index 0000000000..c7053c0da4 --- /dev/null +++ b/board/mithrax/fw_config.h @@ -0,0 +1,81 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_MITHRAX_FW_CONFIG_H_ +#define __BOARD_MITHRAX_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for mithrax board. + * + * Source of truth is the project/brya/mithrax/config.star configuration file. + */ + +enum ec_cfg_usb_db_type { DB_USB_ABSENT = 0, DB_USB3_PS8815 = 1 }; + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_usb_mb_type { NA = 0, MB_USB3_NON_TBT = 1 }; + +enum ec_cfg_stylus_type { STYLUS_ABSENT = 0, STYLUS_PRSENT = 1 }; + +enum ec_cfg_kb_backlight_type { SOLID_COLOR = 0, RGB = 1 }; + +union mithrax_cbi_fw_config { + struct { + enum ec_cfg_usb_db_type usb_db : 3; + uint32_t wifi : 1; + enum ec_cfg_kb_backlight_type rgb : 1; + enum ec_cfg_stylus_type stylus : 1; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t thermal : 2; + uint32_t table_mode : 1; + enum ec_cfg_usb_mb_type usb_mb : 3; + uint32_t reserved_1 : 16; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union mithrax_cbi_fw_config get_fw_config(void); + +/** + * Get the USB daughter board type from FW_CONFIG. + * + * @return the USB daughter board type. + */ +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void); + +/** + * Get the USB main board type from FW_CONFIG. + * + * @return the USB main board type. + */ +enum ec_cfg_usb_mb_type ec_cfg_usb_mb_type(void); + +#endif /* __BOARD_MITHRAX_FW_CONFIG_H_ */ + +/** + * Get the stylus type from FW_CONFIG. + * + * @return the stylus type. + */ +enum ec_cfg_stylus_type ec_cfg_stylus(void); + +/** + * Get the rgb type from FW_CONFIG. + * + * @return the rgb type. + */ +enum ec_cfg_kb_backlight_type ec_cfg_kb_backlight(void); diff --git a/board/mithrax/gpio.inc b/board/mithrax/gpio.inc new file mode 100644 index 0000000000..1ee2ae40f0 --- /dev/null +++ b/board/mithrax/gpio.inc @@ -0,0 +1,154 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_ACCEL_INT_R_L, PIN(8, 1), GPIO_SEL_1P8V | GPIO_INT_FALLING, lis2dw12_interrupt) +GPIO_INT(EC_IMU_INT_R_L, PIN(5, 6), GPIO_SEL_1P8V | GPIO_INT_FALLING, lsm6dso_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(USB_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C2_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C2_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C2_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(PEN_DET_ODL, PIN(D, 4), GPIO_INT_BOTH, pen_detect_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_PP5000_LED, PIN(C, 6), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_PP5000_PEN, PIN(E, 1), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_C2_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RST_ODL, PIN(9, 6), GPIO_ODR_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) + +/* LED */ +GPIO(LED_4_L, PIN(6, 0), GPIO_OUT_HIGH) /* battery led white */ +GPIO(LED_3_L, PIN(C, 2), GPIO_OUT_HIGH) /* battery led amber */ + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(C, 3)) /* GPIOC3 */ +UNUSED(PIN(C, 4)) /* GPIOC4 */ +UNUSED(PIN(6, 2)) /* GPIO62 */ +UNUSED(PIN(B, 1)) /* GPIOB1 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ + +/* Pre-configured PSL balls: J8 K6 */ + + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ + +IOEX(USB_C1_RT_RST_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C1_FRS_EN, EXPIN(IOEX_C1_NCT38XX, 0, 6), GPIO_LOW) + +IOEX(USB_C2_RT_RST_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C2_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C2_FRS_EN, EXPIN(IOEX_C2_NCT38XX, 0, 6), GPIO_LOW) +/* GPIO07_P2 to PU */ diff --git a/board/mithrax/i2c.c b/board/mithrax/i2c.c new file mode 100644 index 0000000000..1a5d348c30 --- /dev/null +++ b/board/mithrax/i2c.c @@ -0,0 +1,78 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc2", + .port = I2C_PORT_USB_C2_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc2", + .port = I2C_PORT_USB_C2_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer2", + .port = I2C_PORT_USB_C2_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_RT_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/mithrax/keyboard.c b/board/mithrax/keyboard.c new file mode 100644 index 0000000000..36830958f5 --- /dev/null +++ b/board/mithrax/keyboard.c @@ -0,0 +1,107 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "rgb_keyboard.h" +#include "timer.h" +#include "tlc59116f.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x86, 0xff, 0xff, 0x55, 0xff, 0xff, 0xff, 0xff, /* full set */ + }, +}; + +static const struct ec_response_keybd_config mithrax_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static struct rgb_s grid0[RGB_GRID0_COL * RGB_GRID0_ROW]; + +struct rgbkbd rgbkbds[] = { + [0] = { + .cfg = &(const struct rgbkbd_cfg) { + .drv = &tlc59116f_drv, + .i2c = I2C_PORT_KBMCU, + .col_len = RGB_GRID0_COL, + .row_len = RGB_GRID0_ROW, + }, + .buf = grid0, + }, +}; +const uint8_t rgbkbd_count = ARRAY_SIZE(rgbkbds); + +const uint8_t rgbkbd_hsize = RGB_GRID0_COL; +const uint8_t rgbkbd_vsize = RGB_GRID0_ROW; + +enum ec_rgbkbd_type rgbkbd_type; +#define LED(x, y) RGBKBD_COORD((x), (y)) +#define DELM RGBKBD_DELM + +const uint8_t rgbkbd_map[] = { + DELM, LED(0, 0), DELM, LED(1, 0), DELM, + LED(2, 0), DELM, LED(3, 0), DELM, DELM, +}; +#undef LED +#undef DELM +const size_t rgbkbd_map_size = ARRAY_SIZE(rgbkbd_map); + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &mithrax_kb; +} + +/* + * Row Column info for Top row keys T1 - T15. + * on mithrax_kb keyboard Row Column is customization + * need define row col to mapping matrix layout. + */ +__override const struct key { + uint8_t row; + uint8_t col; +} vivaldi_keys[] = { + { .row = 4, .col = 2 }, /* T1 */ + { .row = 3, .col = 2 }, /* T2 */ + { .row = 2, .col = 2 }, /* T3 */ + { .row = 1, .col = 2 }, /* T4 */ + { .row = 4, .col = 4 }, /* T5 */ + { .row = 3, .col = 4 }, /* T6 */ + { .row = 2, .col = 4 }, /* T7 */ + { .row = 2, .col = 9 }, /* T8 */ + { .row = 1, .col = 9 }, /* T9 */ + { .row = 1, .col = 4 }, /* T10 */ + { .row = 0, .col = 4 }, /* T11 */ + { .row = 1, .col = 5 }, /* T12 */ + { .row = 3, .col = 5 }, /* T13 */ + { .row = 2, .col = 1 }, /* T14 */ + { .row = 0, .col = 1 }, /* T15 */ +}; +BUILD_ASSERT(ARRAY_SIZE(vivaldi_keys) == MAX_TOP_ROW_KEYS); diff --git a/board/mithrax/keyboard_customization.c b/board/mithrax/keyboard_customization.c new file mode 100644 index 0000000000..f9b2dd27ce --- /dev/null +++ b/board/mithrax/keyboard_customization.c @@ -0,0 +1,104 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "gpio.h" +#include "keyboard_8042_sharedlib.h" +#include "keyboard_config.h" +#include "keyboard_customization.h" +#include "keyboard_protocol.h" +#include "keyboard_raw.h" + +static uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 0x0000, 0x0000, 0x0014, 0xe01f, 0xe014, 0x0000, 0x0000, 0x0000 }, + { 0x001f, 0x0076, 0x0017, 0x000e, 0x001c, 0x003a, 0x000d, 0x0016 }, + { 0x006c, 0xe024, 0xe01d, 0xe020, 0xe038, 0xe071, 0x0026, 0x002a }, + { 0x0032, 0x0034, 0x002c, 0x002e, 0x002b, 0x0029, 0x0025, 0x002d }, + { 0x0078, 0xe032, 0xe035, 0xe02c, 0xe02d, 0x0041, 0x001e, 0x001d }, + { 0x0051, 0x0007, 0x005b, 0x000f, 0x0042, 0x0022, 0x003e, 0x0043 }, + { 0x0031, 0x0033, 0x0035, 0x0036, 0x003b, 0x001b, 0x003d, 0x003c }, + { 0x0000, 0x0012, 0x0061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0059 }, + { 0x0055, 0x0052, 0x0054, 0x004e, 0x004c, 0x0024, 0x0044, 0x004d }, + { 0x0045, 0xe021, 0xe023, 0x002f, 0x004b, 0x0049, 0x0046, 0x001a }, + { 0xe011, 0x0000, 0x006a, 0x0000, 0x005d, 0x0000, 0x0011, 0x0000 }, + { 0xe07a, 0x005d, 0xe075, 0x006b, 0x005a, 0xe072, 0x004a, 0x0066 }, + { 0xe06b, 0xe074, 0xe069, 0x0067, 0xe06c, 0x0064, 0x0015, 0xe07d }, + { 0x0073, 0x007c, 0x007b, 0x0074, 0x0071, 0xe04a, 0x0070, 0x0021 }, + { 0x0023, 0xe05a, 0x0075, 0x0079, 0x007a, 0x0072, 0x007d, 0x0069 }, +}; + +uint16_t get_scancode_set2(uint8_t row, uint8_t col) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + return scancode_set2[col][row]; + return 0; +} + +void set_scancode_set2(uint8_t row, uint8_t col, uint16_t val) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + scancode_set2[col][row] = val; +} + +void board_keyboard_drive_col(int col) +{ + /* Drive all lines to high */ + if (col == KEYBOARD_COLUMN_NONE) + gpio_set_level(GPIO_KBD_KSO2, 0); + + /* Set KBSOUT to zero to detect key-press */ + else if (col == KEYBOARD_COLUMN_ALL) + gpio_set_level(GPIO_KBD_KSO2, 1); + + /* Drive one line for detection */ + else { + if (col == 2) + gpio_set_level(GPIO_KBD_KSO2, 1); + else + gpio_set_level(GPIO_KBD_KSO2, 0); + } +} + +#ifdef CONFIG_KEYBOARD_DEBUG +static uint8_t keycap_label[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 'c', KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { 'q', KLLI_UNKNO, KLLI_UNKNO, KLLI_TAB, '`', '1', KLLI_UNKNO, 'a' }, + { KLLI_R_ALT, KLLI_L_ALT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_UNKNO, KLLI_SPACE, 'e', KLLI_F4, KLLI_SEARC, '3', KLLI_F3, + KLLI_UNKNO }, + { 'x', 'z', KLLI_F2, KLLI_F1, 's', '2', 'w', KLLI_ESC }, + { 'v', 'b', 'g', 't', '5', '4', 'r', 'f' }, + { 'm', 'n', 'h', 'y', '6', '7', 'u', 'j' }, + { '.', KLLI_DOWN, '\\', 'o', KLLI_F10, '9', KLLI_UNKNO, 'l' }, + { KLLI_R_SHT, KLLI_L_SHT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { ',', KLLI_UNKNO, KLLI_F7, KLLI_F6, KLLI_F5, '8', 'i', 'k' }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_F9, KLLI_UNKNO, KLLI_UNKNO, + KLLI_LEFT, KLLI_UNKNO }, + { KLLI_R_CTR, KLLI_L_CTR, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { '/', KLLI_UP, '-', KLLI_UNKNO, '0', 'p', '[', ';' }, + { '\'', KLLI_ENTER, KLLI_UNKNO, KLLI_UNKNO, '=', KLLI_B_SPC, ']', 'd' }, + { KLLI_UNKNO, KLLI_F8, KLLI_RIGHT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO }, +}; + +uint8_t get_keycap_label(uint8_t row, uint8_t col) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + return keycap_label[col][row]; + return KLLI_UNKNO; +} + +void set_keycap_label(uint8_t row, uint8_t col, uint8_t val) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + keycap_label[col][row] = val; +} +#endif diff --git a/board/mithrax/keyboard_customization.h b/board/mithrax/keyboard_customization.h new file mode 100644 index 0000000000..1d0e6ec483 --- /dev/null +++ b/board/mithrax/keyboard_customization.h @@ -0,0 +1,73 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Keyboard configuration */ + +#ifndef __KEYBOARD_CUSTOMIZATION_H +#define __KEYBOARD_CUSTOMIZATION_H + +/* + * KEYBOARD_COLS_MAX has the build time column size. It's used to allocate + * exact spaces for arrays. Actual keyboard scanning is done using + * keyboard_cols, which holds a runtime column size. + */ +#define KEYBOARD_COLS_MAX 15 +#define KEYBOARD_ROWS 8 + +/* + * WARNING: Do not directly modify it. You should call keyboard_raw_set_cols, + * instead. It checks whether you're eligible or not. + */ +extern uint8_t keyboard_cols; + +#define KEYBOARD_ROW_TO_MASK(r) (1 << (r)) + +/* Columns and masks for keys we particularly care about */ +#define KEYBOARD_COL_DOWN 11 +#define KEYBOARD_ROW_DOWN 5 +#define KEYBOARD_MASK_DOWN KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_DOWN) +#define KEYBOARD_COL_ESC 1 +#define KEYBOARD_ROW_ESC 1 +#define KEYBOARD_MASK_ESC KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_ESC) +#define KEYBOARD_COL_KEY_H 6 +#define KEYBOARD_ROW_KEY_H 1 +#define KEYBOARD_MASK_KEY_H KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_H) +#define KEYBOARD_COL_KEY_R 3 +#define KEYBOARD_ROW_KEY_R 7 +#define KEYBOARD_MASK_KEY_R KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_R) +#define KEYBOARD_COL_LEFT_ALT 10 +#define KEYBOARD_ROW_LEFT_ALT 6 +#define KEYBOARD_MASK_LEFT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_ALT) +#define KEYBOARD_COL_REFRESH 2 +#define KEYBOARD_ROW_REFRESH 3 +#define KEYBOARD_MASK_REFRESH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_REFRESH) +#define KEYBOARD_COL_RIGHT_ALT 10 +#define KEYBOARD_ROW_RIGHT_ALT 0 +#define KEYBOARD_MASK_RIGHT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_ALT) +#define KEYBOARD_DEFAULT_COL_VOL_UP 4 +#define KEYBOARD_DEFAULT_ROW_VOL_UP 1 +#define KEYBOARD_COL_LEFT_CTRL 0 +#define KEYBOARD_ROW_LEFT_CTRL 2 +#define KEYBOARD_MASK_LEFT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_CTRL) +#define KEYBOARD_COL_RIGHT_CTRL 0 +#define KEYBOARD_ROW_RIGHT_CTRL 4 +#define KEYBOARD_MASK_RIGHT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_CTRL) +#define KEYBOARD_COL_SEARCH 0 +#define KEYBOARD_ROW_SEARCH 3 +#define KEYBOARD_MASK_SEARCH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_SEARCH) +#define KEYBOARD_COL_KEY_0 9 +#define KEYBOARD_ROW_KEY_0 0 +#define KEYBOARD_MASK_KEY_0 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_0) +#define KEYBOARD_COL_KEY_1 1 +#define KEYBOARD_ROW_KEY_1 7 +#define KEYBOARD_MASK_KEY_1 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_1) +#define KEYBOARD_COL_KEY_2 4 +#define KEYBOARD_ROW_KEY_2 6 +#define KEYBOARD_MASK_KEY_2 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_2) +#define KEYBOARD_COL_LEFT_SHIFT 7 +#define KEYBOARD_ROW_LEFT_SHIFT 1 +#define KEYBOARD_MASK_LEFT_SHIFT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_SHIFT) + +#endif /* __KEYBOARD_CUSTOMIZATION_H */ diff --git a/board/mithrax/led.c b/board/mithrax/led.c new file mode 100644 index 0000000000..660fc8ce2d --- /dev/null +++ b/board/mithrax/led.c @@ -0,0 +1,99 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for mithrax + */ + +#include "chipset.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#include "system.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_ON_LVL); + gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_BAT_LED_WHITE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_AMBER_L, LED_OFF_LVL); + break; + } +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/mithrax/pwm.c b/board/mithrax/pwm.c new file mode 100644 index 0000000000..c889b1d70e --- /dev/null +++ b/board/mithrax/pwm.c @@ -0,0 +1,37 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 0); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/mithrax/sensors.c b/board/mithrax/sensors.c new file mode 100644 index 0000000000..215b0cd2c5 --- /dev/null +++ b/board/mithrax/sensors.c @@ -0,0 +1,235 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc_chip.h" +#include "common.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_FAN] = { + .name = "TEMP_FAN", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +static struct stprivate_data g_lis2dw12_data; +static struct lsm6dso_data lsm6dso_data; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +/* TODO(b/184779743): verify orientation matrix */ +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DW12, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_lis2dw12_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DW12_ADDR0, + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void baseboard_sensors_init(void) +{ + /* Enable gpio interrupt for lid accel sensor */ + gpio_enable_interrupt(GPIO_EC_ACCEL_INT_R_L); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_R_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC }, + [TEMP_SENSOR_2_FAN] = { .name = "FAN", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_FAN }, + [TEMP_SENSOR_3_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/mithrax + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(60), \ + }, \ + .temp_fan_off = C_TO_K(30), \ + .temp_fan_max = C_TO_K(73), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/180681346): update for Alder Lake/mithrax + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(60), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(70), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(50), \ + }, \ + .temp_fan_off = C_TO_K(30), \ + .temp_fan_max = C_TO_K(63), \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan = THERMAL_FAN; + +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(60), \ + }, \ + .temp_fan_off = C_TO_K(30), \ + .temp_fan_max = C_TO_K(73), \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_FAN] = THERMAL_FAN, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/mithrax/usbc_config.c b/board/mithrax/usbc_config.c new file mode 100644 index 0000000000..8557da622f --- /dev/null +++ b/board/mithrax/usbc_config.c @@ -0,0 +1,346 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C2_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_VCONN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM536A0 */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = NX20P3483_ADDR2_FLAGS, + .drv = &nx20p348x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* + * USB3 DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C2] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C1_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C2_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C2_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +void config_usb_db_type(void) +{ + enum ec_cfg_usb_db_type db_type = ec_cfg_usb_db_type(); + + /* + * TODO(b/180434685): implement multiple DB types + */ + + CPRINTS("Configured USB DB type number is %d", db_type); +} + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + int rst_signal; + + if (me->usb_port == USBC_PORT_C1) + rst_signal = IOEX_USB_C1_RT_RST_ODL; + else if (me->usb_port == USBC_PORT_C2) + rst_signal = IOEX_USB_C2_RT_RST_ODL; + else + return EC_ERROR_INVAL; + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + gpio_or_ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + gpio_or_ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(GPIO_USB_C0_C2_TCPC_RST_ODL, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(GPIO_USB_C0_C2_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void enable_ioex(int ioex) +{ + ioex_init(ioex); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C2 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + enable_ioex(IOEX_C2_NCT38XX); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C2) + return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C2); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C2_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C1_PPC_INT_ODL: + nx20p348x_interrupt(USBC_PORT_C1); + break; + case GPIO_USB_C2_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C2; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return false; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/mithrax/usbc_config.h b/board/mithrax/usbc_config.h new file mode 100644 index 0000000000..22242d7c5b --- /dev/null +++ b/board/mithrax/usbc_config.h @@ -0,0 +1,19 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Mithrax board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPC_RUNTIME_CONFIG +#define CONFIG_USB_MUX_RUNTIME_CONFIG + +enum usbc_port { USBC_PORT_C2 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void config_usb_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/mithrax/vif_override.xml b/board/mithrax/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/mithrax/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/moli/board.c b/board/moli/board.c new file mode 100644 index 0000000000..61f8580af2 --- /dev/null +++ b/board/moli/board.c @@ -0,0 +1,529 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "builtin/assert.h" +#include "button.h" +#include "cec.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "driver/cec/bitbang.h" +#include "driver/tcpm/tcpci.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +/******************************************************************************/ +/* Power on by HDMI/ DP monitor */ +struct monitor_config { + enum gpio_signal gpio; + uint8_t state; +}; + +static struct monitor_config monitors[MONITOR_COUNT] = { + [HDMI1_MONITOR] = { + .gpio = GPIO_HDMI1_MONITOR_ON, + .state = MONITOR_OFF, + }, + + [HDMI2_MONITOR] = { + .gpio = GPIO_HDMI2_MONITOR_ON, + .state = MONITOR_OFF, + }, + + [OPTION_MONITOR] = { + .gpio = GPIO_OPTION_MONITOR_ON, + .state = MONITOR_OFF, + }, +}; + +/******************************************************************************/ + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* CEC ports */ +const struct cec_config_t cec_config[] = { + [CEC_PORT_0] = { + .drv = &bitbang_cec_drv, + .offline_policy = NULL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(cec_config) == CEC_PORT_COUNT); + +int board_set_active_charge_port(int port) +{ + CPRINTS("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + case CHARGE_PORT_TYPEC1: + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static uint8_t usbc_overcurrent; + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_ODL); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) + ec_bj_power(&pi.voltage, &pi.current); + + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +static void adp_state_init(void) +{ + ASSERT(CHARGE_PORT_ENUM_COUNT == CHARGE_PORT_COUNT); + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +static void board_init(void) +{ + int i; + + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_ODL); + gpio_enable_interrupt(GPIO_HDMI_CONN_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A1_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A2_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A3_OC_ODL); + gpio_enable_interrupt(GPIO_USB_A4_OC_ODL); + + if (ec_cfg_power_on_monitor() == POWER_ON_MONITOR_ENABLE) { + /* + * Only enable interrupt when fw_config set it as enable. + */ + gpio_enable_interrupt(GPIO_HDMI1_MONITOR_ON); + gpio_enable_interrupt(GPIO_HDMI2_MONITOR_ON); + gpio_enable_interrupt(GPIO_OPTION_MONITOR_ON); + + /* + * Initialize the monitor state to corresponding gpio state. + */ + for (i = 0; i < MONITOR_COUNT; i++) + monitors[i].state = gpio_get_level(monitors[i].gpio); + } +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Check that port number is valid. */ + if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) + return; + usbc_overcurrent = is_overcurrented; +} +/* + * Power monitoring and management. + * + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * The overall goal is to gracefully manage the power demand so that + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type A BC1.2 rear port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 3 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A_FRONT BIT(0) +#define THROT_TYPE_A_REAR BIT(1) +#define THROT_TYPE_C0 BIT(2) +#define THROT_TYPE_C1 BIT(3) +#define THROT_PROCHOT BIT(5) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +static void power_monitor(void) +{ + static uint32_t current_state; + static uint32_t history[POWER_READINGS]; + static uint8_t index; + int32_t delay; + uint32_t new_state = 0, diff; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + /* + * Clear the first entry of the power table so that + * it is re-initilalised when the CPU starts. + */ + history[0] = 0; + } else { + int32_t charger_mw; + + delay = POWER_DELAY_MS * MSEC; + /* + * Get current charger limit (in mw). + * If not configured yet, skip. + */ + charger_mw = charge_manager_get_power_limit_uw() / 1000; + if (charger_mw != 0) { + int32_t gap, total, max, power; + int i; + + /* + * Read power usage. + */ + power = (adc_read_channel(ADC_VBUS) * + adc_read_channel(ADC_PPVAR_IMON)) / + 1000; + /* Init power table */ + if (history[0] == 0) { + for (i = 0; i < POWER_READINGS; i++) + history[i] = power; + } + /* + * Update the power readings and + * calculate the average and max. + */ + history[index] = power; + index = (index + 1) % POWER_READINGS; + total = 0; + max = history[0]; + for (i = 0; i < POWER_READINGS; i++) { + total += history[i]; + if (history[i] > max) + max = history[i]; + } + /* + * For Type-C power supplies, there is + * less tolerance for exceeding the rating, + * so use the max power that has been measured + * over the measuring period. + * For barrel-jack supplies, the rating can be + * exceeded briefly, so use the average. + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + power = max; + else + power = total / POWER_READINGS; + /* + * Calculate gap, and if negative, power + * demand is exceeding configured power budget, so + * throttling is required to reduce the demand. + */ + gap = charger_mw - power; + /* + * Limiting type-A power rear ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_REAR; + if (!(current_state & THROT_TYPE_A_REAR)) + gap += POWER_GAIN_TYPE_A; + } + /* + * Limiting type-A power front ports. + */ + if (gap <= 0) { + new_state |= THROT_TYPE_A_FRONT; + if (!(current_state & THROT_TYPE_A_FRONT)) + gap += POWER_GAIN_TYPE_A; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(0) && gap <= 0) { + new_state |= THROT_TYPE_C0; + if (!(current_state & THROT_TYPE_C0)) + gap += POWER_GAIN_TYPE_C; + } + /* + * If the type-C port is sourcing power, + * check whether it should be throttled. + */ + if (ppc_is_sourcing_vbus(1) && gap <= 0) { + new_state |= THROT_TYPE_C1; + if (!(current_state & THROT_TYPE_C1)) + gap += POWER_GAIN_TYPE_C; + } + /* + * As a last resort, turn on PROCHOT to + * throttle the CPU. + */ + if (gap <= 0) + new_state |= THROT_PROCHOT; + } + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_C0) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C0) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(0, rp); + tcpm_select_rp_value(0, rp); + pd_update_contract(0); + } + if (diff & THROT_TYPE_C1) { + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C1) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; + + ppc_set_vbus_source_current_limit(1, rp); + tcpm_select_rp_value(1, rp); + pd_update_contract(1); + } + if (diff & THROT_TYPE_A_REAR) { + int typea_bc = (new_state & THROT_TYPE_A_REAR) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR1_OD, typea_bc); + } + if (diff & THROT_TYPE_A_FRONT) { + int typea_bc = (new_state & THROT_TYPE_A_FRONT) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR2_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, power_monitor, HOOK_PRIO_INIT_ADC + 1); + +/******************************************************************************/ +/* + * System power on and wake up by monitor power button. + * + * After pressing power button of monitor for power on, monitor will send power + * on signal with 3.3V / 200ms to DT. If DT detect that pulse, there are three + * DT behavior: + * + * - Do nothing in state S0. + * - Wake up from state S0ix. + * - Power on from state S5 and G3. + */ + +/* Debounce time for HDMI power button press */ +#define MONITOR_DEBOUNCE_MS 100 + +static void monitor_irq_deferred(void); +DECLARE_DEFERRED(monitor_irq_deferred); + +static void monitor_irq_deferred(void) +{ + int i; + + for (i = 0; i < MONITOR_COUNT; i++) { + if (monitors[i].state && gpio_get_level(monitors[i].gpio)) { + /* + * System power on from state S5 and G3. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + chipset_power_on(); + /* + * System wake up from state S0ix. + */ + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + power_button_simulate_press(200); + } + monitors[i].state = MONITOR_OFF; + } +} + +/* Power on by HDMI/ DP monitor. */ +void monitor_interrupt(enum gpio_signal signal) +{ + /* + * Power on by HDMI/ DP monitor only works + * when system is not in S0. + */ + if (chipset_in_state(CHIPSET_STATE_ON)) + return; + + if (ec_cfg_power_on_monitor() == POWER_ON_MONITOR_ENABLE) { + switch (signal) { + case GPIO_HDMI1_MONITOR_ON: + monitors[HDMI1_MONITOR].state = MONITOR_ON; + break; + case GPIO_HDMI2_MONITOR_ON: + monitors[HDMI2_MONITOR].state = MONITOR_ON; + break; + case GPIO_OPTION_MONITOR_ON: + monitors[OPTION_MONITOR].state = MONITOR_ON; + break; + default: + break; + } + hook_call_deferred(&monitor_irq_deferred_data, + MONITOR_DEBOUNCE_MS * MSEC); + } +} diff --git a/board/moli/board.h b/board/moli/board.h new file mode 100644 index 0000000000..9f4003ccfe --- /dev/null +++ b/board/moli/board.h @@ -0,0 +1,201 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brask board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +#define CONFIG_MP2964 + +/* Barrel Jack */ +#define DEDICATED_CHARGE_PORT 2 + +/* HDMI CEC */ +#define CONFIG_CEC +#define CONFIG_CEC_BITBANG +#define CEC_GPIO_OUT GPIO_HDMI_CEC_OUT +#define CEC_GPIO_IN GPIO_HDMI_CEC_IN +#define CEC_GPIO_PULL_UP GPIO_HDMI_CEC_PULL_UP + +/* USB Type A Features */ +#define USB_PORT_COUNT 4 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USB_PD_PPC +#define CONFIG_USBC_RETIMER_INTEL_BB + +#undef CONFIG_CMD_POWERINDEBUG + +#define CONFIG_USBC_PPC_SYV682X +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* The design should support up to 100W. */ +/* TODO(b/197702356): Set the max PD to 60W now and change it + * to 100W after we verify it. + */ +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL +#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_ODL + +/* I2C Bus Configuration */ + +#define I2C_PORT_USB_C0_C1_TCPC NPCX_I2C_PORT1_0 + +#define I2C_PORT_USB_C0_C1_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_A0_A1_MIX NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C1_BC12 NPCX_I2C_PORT2_0 + +#define I2C_PORT_USB_C0_C1_MUX NPCX_I2C_PORT3_0 + +#define I2C_PORT_QI NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x57 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* ADC */ +#define CONFIG_ADC + +/* Fan */ +#define CONFIG_FANS FAN_CH_COUNT +#define RPM_DEVIATION 1 +#define CONFIG_CUSTOM_FAN_CONTROL + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_TYPEC1, + CHARGE_PORT_BARRELJACK, + CHARGE_PORT_ENUM_COUNT +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1_SSD, + ADC_TEMP_SENSOR_2_CPU_VR, + ADC_TEMP_SENSOR_4_DIMM, + ADC_VBUS, + ADC_PPVAR_IMON, /* ADC3 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_SSD, + TEMP_SENSOR_2_CPU_VR, + TEMP_SENSOR_4_DIMM, + TEMP_SENSOR_COUNT +}; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C1_NCT38XX, IOEX_PORT_COUNT }; + +enum pwm_channel { + PWM_CH_LED_AMBER, /* PWM0 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED_BLUE, /* PWM2 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +enum monitor_port { + HDMI1_MONITOR, + HDMI2_MONITOR, + OPTION_MONITOR, + MONITOR_COUNT +}; + +enum monitor_state { MONITOR_OFF, MONITOR_ON }; + +enum cec_port { CEC_PORT_0, CEC_PORT_COUNT }; + +extern void adp_connect_interrupt(enum gpio_signal signal); +extern void monitor_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/moli/build.mk b/board/moli/build.mk new file mode 100644 index 0000000000..4ddfaaf181 --- /dev/null +++ b/board/moli/build.mk @@ -0,0 +1,23 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brask board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brask + +board-y= +board-y+=board.o +board-y+=fans.o +board-y+=i2c.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=thermal.o +board-y+=usbc_config.o +board-y+=fw_config.o diff --git a/board/moli/ec.tasklist b/board/moli/ec.tasklist new file mode 100644 index 0000000000..2fda1cfb5e --- /dev/null +++ b/board/moli/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(1) | BIT(0)), LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CEC, cec_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/moli/fans.c b/board/moli/fans.c new file mode 100644 index 0000000000..88eb45935e --- /dev/null +++ b/board/moli/fans.c @@ -0,0 +1,44 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1500, + .rpm_start = 1500, + .rpm_max = 5200, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/moli/fw_config.c b/board/moli/fw_config.c new file mode 100644 index 0000000000..5807ee9111 --- /dev/null +++ b/board/moli/fw_config.c @@ -0,0 +1,73 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union moli_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for moli if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union moli_cbi_fw_config fw_config_defaults = { + .bj_power = BJ_90W, + .po_mon = POWER_ON_MONITOR_ENABLE, +}; + +/* + * Barrel-jack power adapter ratings. + */ +static const struct { + int voltage; + int current; +} bj_power[] = { + [BJ_90W] = { /* 0 - 90W (also default) */ + .voltage = 19000, + .current = 4740 }, + [BJ_135W] = { /* 1 - 135W */ + .voltage = 19500, + .current = 6920 }, +}; + +/**************************************************************************** + * Moli FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union moli_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +void ec_bj_power(uint32_t *voltage, uint32_t *current) +{ + unsigned int bj; + + bj = fw_config.bj_power; + /* Out of range value defaults to 0 */ + if (bj >= ARRAY_SIZE(bj_power)) + bj = 0; + *voltage = bj_power[bj].voltage; + *current = bj_power[bj].current; +} + +enum ec_cfg_power_on_monitor ec_cfg_power_on_monitor(void) +{ + return fw_config.po_mon; +} diff --git a/board/moli/fw_config.h b/board/moli/fw_config.h new file mode 100644 index 0000000000..ee3dcd274d --- /dev/null +++ b/board/moli/fw_config.h @@ -0,0 +1,53 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_MOLI_FW_CONFIG_H_ +#define __BOARD_MOLI_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Moli board. + * + * Source of truth is the project/brask/moli/config.star configuration file. + */ + +enum ec_cfg_bj_power { BJ_90W = 0, BJ_135W = 1 }; + +enum ec_cfg_power_on_monitor { + POWER_ON_MONITOR_ENABLE = 0, + POWER_ON_MONITOR_DISABLE = 1 +}; + +union moli_cbi_fw_config { + struct { + uint32_t bj_power : 2; + uint32_t mlb_usb_tbt : 2; + uint32_t storage : 2; + uint32_t audio : 1; + enum ec_cfg_power_on_monitor po_mon : 1; + uint32_t reserved_1 : 24; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union moli_cbi_fw_config get_fw_config(void); + +/** + * Get the barrel-jack power from FW_CONFIG. + */ +void ec_bj_power(uint32_t *voltage, uint32_t *current); + +/** + * Get enable/disable power on by monitor from FW_CONFIG. + */ +enum ec_cfg_power_on_monitor ec_cfg_power_on_monitor(void); + +#endif /* __BOARD_MOLI_FW_CONFIG_H_ */ diff --git a/board/moli/gpio.inc b/board/moli/gpio.inc new file mode 100644 index 0000000000..e8473f8c95 --- /dev/null +++ b/board/moli/gpio.inc @@ -0,0 +1,177 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C1_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(BJ_ADP_PRESENT_ODL, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(EC_RECOVERY_BTN_ODL, PIN(2, 3), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(USB_C1_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(HDMI1_MONITOR_ON, PIN(B, 4), GPIO_INT_RISING, monitor_interrupt) +GPIO_INT(HDMI2_MONITOR_ON, PIN(B, 5), GPIO_INT_RISING, monitor_interrupt) +GPIO_INT(OPTION_MONITOR_ON, PIN(1, 0), GPIO_INT_RISING, monitor_interrupt) + +/* CCD */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) + +/* Security */ +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) + +/* Fan */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) + +/* ADC, need to check the usage */ +GPIO(ANALOG_PPVAR_PWR_IN_IMON_EC, PIN(4, 2), GPIO_INPUT) + +/* BarrelJack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 7), GPIO_OUT_LOW) + +/* Chipset PCH */ +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(6, 0), GPIO_INPUT) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) + +/* Button */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(GSC_EC_RECOVERY_BTN_ODL, PIN(2, 2), GPIO_INPUT) + +/* NFC */ +/* TODO(b/194068530): Enable NFC */ +GPIO(NFC_COIL_ACT_L, PIN(D, 4), GPIO_INPUT) +GPIO(NFC_LOW_POWER_MODE, PIN(9, 5), GPIO_OUT_HIGH) +GPIO(NFC_CARD_DET_L, PIN(A, 3), GPIO_INPUT) +GPIO(EN_NFC_BUZZER, PIN(0, 5), GPIO_OUT_LOW) + +/* Wireless Charger */ +/* TODO(b/191418683): Implement Qi Driver */ +GPIO(EC_QI_PWR, PIN(D, 2), GPIO_OUT_HIGH) +GPIO(EC_I2C_QI_RESET_L, PIN(9, 3), GPIO_OUT_HIGH) +GPIO(EC_I2C_QI_INT_ODL, PIN(9, 6), GPIO_INPUT) + +/* HDMI */ +GPIO(HDMI_CONN_OC_ODL, PIN(2, 4), GPIO_INPUT) + +/* HDMI CEC */ +/* TODO(b/197474873): Enable HDMI CEC */ +GPIO(HDMI_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CEC_OUT, PIN(D, 3), GPIO_OUT_HIGH | GPIO_OPEN_DRAIN) +GPIO(HDMI_CEC_PULL_UP, PIN(C, 2), GPIO_OUT_HIGH) + +/* I2C SCL/SDA */ +GPIO(EC_I2C_QI_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_QI_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_A1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_A1_MIX_SDA, PIN(E, 3), GPIO_INPUT) + +/* USBA */ +GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW) +GPIO(USB_A1_STATUS_L, PIN(2, 0), GPIO_INPUT) +GPIO(USB_A2_STATUS_L, PIN(1, 7), GPIO_INPUT) +GPIO(USB_A_LOW_PWR1_OD, PIN(1, 4), GPIO_OUT_LOW) +GPIO(USB_A_LOW_PWR2_OD, PIN(1, 1), GPIO_OUT_LOW) +GPIO(USB_A_OC_SOC_L, PIN(8, 0), GPIO_OUT_HIGH) +GPIO(USB_A1_OC_ODL, PIN(3, 0), GPIO_INPUT) +GPIO(USB_A2_OC_ODL, PIN(2, 7), GPIO_INPUT) +GPIO(USB_A3_OC_ODL, PIN(2, 6), GPIO_INPUT) +GPIO(USB_A4_OC_ODL, PIN(0, 6), GPIO_INPUT) + +/* USBC */ +GPIO(USB_C0_C1_TCPC_RST_ODL, PIN(F, 5), GPIO_ODR_LOW) + +/* LAN */ +GPIO(LAN_PWR_GOOD, PIN(0, 2), GPIO_INPUT) + +/* LED */ +GPIO(LED_ORANGE_CONTROL, PIN(3, 1), GPIO_ODR_LOW) +GPIO(LED_BLUE_CONTROL, PIN(2, 5), GPIO_ODR_LOW) + +/* Option Board */ +GPIO(HDMI1_MONON_SIO, PIN(1, 6), GPIO_INPUT) +GPIO(HDMI2_MONON_SIO, PIN(1, 5), GPIO_INPUT) +GPIO(OPTION_MONON_SIO, PIN(2, 1), GPIO_INPUT) + +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C1_RT_RST_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 2), GPIO_ODR_LOW) +IOEX(USB_C1_FRS_EN, EXPIN(IOEX_C1_NCT38XX, 0, 6), GPIO_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x18), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */ +UNUSED(PIN(9, 7)) /* GPIO97 */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2/FLPRG2_L */ +UNUSED(PIN(1, 3)) /* KSO06/GPO13/GP_SEL# */ +UNUSED(PIN(1, 2)) /* KSO07/GPO12/JEN# */ +UNUSED(PIN(0, 4)) /* KSO13/GPIO04 */ +UNUSED(PIN(A, 2)) /* F_SCLK/GPIOA2 */ +UNUSED(PIN(5, 0)) /* GPIO50 */ +UNUSED(PIN(9, 4)) /* GPIO94 */ +UNUSED(PIN(A, 0)) /* F_CS0_L/GPIOA0 */ +UNUSED(PIN(3, 4)) /* GPIO34/PS2_DAT2/ADC6 */ +UNUSED(PIN(F, 3)) /* GPIOF3/I2C4_SCL1 */ +UNUSED(PIN(F, 2)) /* GPIOF2/I2C4_SDA1 */ +UNUSED(PIN(A, 7)) /* GPIOA7/PS2_DAT3/TB2/F_DIO3 */ diff --git a/board/moli/i2c.c b/board/moli/i2c.c new file mode 100644 index 0000000000..472eb35424 --- /dev/null +++ b/board/moli/i2c.c @@ -0,0 +1,61 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C1 */ + .name = "tcpc0,1", + .port = I2C_PORT_USB_C0_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,1", + .port = I2C_PORT_USB_C0_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,1", + .port = I2C_PORT_USB_C0_C1_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_RT_SDA, + }, + { + /* I2C5 */ + .name = "wireless_charger", + .port = I2C_PORT_QI, + .kbps = 400, + .scl = GPIO_EC_I2C_QI_SCL, + .sda = GPIO_EC_I2C_QI_SDA, + }, + { + /* I2C6 */ + .name = "usba_mix0,1", + .port = I2C_PORT_USB_A0_A1_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C_USB_A0_A1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_A0_A1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL, + .sda = GPIO_EC_I2C_MISC_SDA, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/moli/led.c b/board/moli/led.c new file mode 100644 index 0000000000..edb429e530 --- /dev/null +++ b/board/moli/led.c @@ -0,0 +1,281 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Brask. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_BLUE, + LED_AMBER, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int amber = 0; + int blue = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_AMBER: + amber = 1; + break; + case LED_BLUE: + blue = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (blue && duty) { + gpio_set_level(GPIO_LED_BLUE_CONTROL, 1); + pwm_set_duty(PWM_CH_LED_BLUE, duty); + } else { + gpio_set_level(GPIO_LED_BLUE_CONTROL, 0); + pwm_set_duty(PWM_CH_LED_BLUE, 0); + } + + if (amber && duty) { + gpio_set_level(GPIO_LED_ORANGE_CONTROL, 1); + pwm_set_duty(PWM_CH_LED_AMBER, duty); + } else { + gpio_set_level(GPIO_LED_ORANGE_CONTROL, 0); + pwm_set_duty(PWM_CH_LED_AMBER, 0); + } + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PERIOD (4 * SECOND) +#define LED_DUTY_CYCLE (25) +#define LED_PULSE_US (LED_PERIOD * LED_DUTY_CYCLE / 100 / 2) +/* 10 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (10 * MSEC) + +/* + * When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; + uint32_t time_off; +} led_pulse; + +/* + * LED_PERIOD = time_on + time_off; + * time_on = LED_PULSE_US * 2; + * time_off = LED_PERIOD - LED_PULSE_US * 2; + */ +#define CONFIG_TICK(interval, period, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), \ + LED_PERIOD - LED_PULSE_US * 2, (color)) + +static void config_tick(uint32_t interval, int duty_inc, int time_off, + enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; + led_pulse.time_off = time_off; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + next = (led_pulse.duty - led_pulse.duty_inc) ? + next : + next + led_pulse.time_off; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_PERIOD, LED_BLUE); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* + * Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_BLUE, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, 0, LED_AMBER); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_AMBER, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "blue")) { + set_color(id, LED_BLUE, 100); + } else if (!strcasecmp(argv[1], "amber")) { + set_color(id, LED_AMBER, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|blue|amber|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_AMBER] = 100; + brightness_range[EC_LED_COLOR_BLUE] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_BLUE]) + return set_color(id, LED_BLUE, brightness[EC_LED_COLOR_BLUE]); + else if (brightness[EC_LED_COLOR_AMBER]) + return set_color(id, LED_AMBER, brightness[EC_LED_COLOR_AMBER]); + else + return set_color(id, LED_OFF, 0); +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* Blink alert if insufficient power per system_can_boot_ap(). */ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + led_alert(insufficient_power); +} diff --git a/board/moli/pwm.c b/board/moli/pwm.c new file mode 100644 index 0000000000..405dcddcae --- /dev/null +++ b/board/moli/pwm.c @@ -0,0 +1,33 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_AMBER] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_BLUE] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + pwm_enable(PWM_CH_FAN, 1); + pwm_enable(PWM_CH_LED_BLUE, 1); + pwm_enable(PWM_CH_LED_AMBER, 1); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/moli/sensors.c b/board/moli/sensors.c new file mode 100644 index 0000000000..2ad327617e --- /dev/null +++ b/board/moli/sensors.c @@ -0,0 +1,102 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_SSD] = { + .name = "TEMP_SSD", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CPU_VR] = { + .name = "TEMP_CPU_VR", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DIMM] = { + .name = "TEMP_DIMM", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 20/(20+8.66)*50/200 current divider */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT * 1433, + .factor_div = (ADC_READ_MAX + 1) * 250, + }, + +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_SSD] = { .name = "SSD", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_SSD }, + [TEMP_SENSOR_2_CPU_VR] = { .name = "CPU VR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CPU_VR }, + [TEMP_SENSOR_4_DIMM] = { .name = "DIMM", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DIMM }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +#define THERMAL_SSD \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HALT] = C_TO_K(64), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_ssd = THERMAL_SSD; + +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +#define THERMAL_DIMM \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HALT] = C_TO_K(67), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_dimm = + THERMAL_DIMM; +/* + * TODO(b/197478860): add the thermal sensor setting + */ +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_SSD] = THERMAL_SSD, + [TEMP_SENSOR_2_CPU_VR] = THERMAL_CPU, + [TEMP_SENSOR_4_DIMM] = THERMAL_DIMM, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/moli/thermal.c b/board/moli/thermal.c new file mode 100644 index 0000000000..16aaa5c069 --- /dev/null +++ b/board/moli/thermal.c @@ -0,0 +1,143 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "fan.h" +#include "hooks.h" +#include "host_command.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +struct fan_step { + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t on[TEMP_SENSOR_COUNT]; + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t off[TEMP_SENSOR_COUNT]; + /* Fan rpm */ + uint16_t rpm[FAN_CH_COUNT]; +}; + +static const struct fan_step fan_table[] = { + { + /* level 0 */ + .on = { -1, 47, -1 }, + .off = { -1, 0, -1 }, + .rpm = { 1900 }, + }, + { + /* level 1 */ + .on = { -1, 50, -1 }, + .off = { -1, 47, -1 }, + .rpm = { 2400 }, + }, + { + /* level 2 */ + .on = { -1, 60, -1 }, + .off = { -1, 57, -1 }, + .rpm = { 3000 }, + }, + { + /* level 3 */ + .on = { -1, 64, -1 }, + .off = { -1, 61, -1 }, + .rpm = { 3700 }, + }, + { + /* level 4 */ + .on = { -1, 67, -1 }, + .off = { -1, 64, -1 }, + .rpm = { 4400 }, + }, + { + /* level 5 */ + .on = { -1, 70, -1 }, + .off = { -1, 67, -1 }, + .rpm = { 5000 }, + }, +}; +const int num_fan_levels = ARRAY_SIZE(fan_table); + +int fan_table_to_rpm(int fan, int *temp, enum temp_sensor_id temp_sensor) +{ + /* current fan level */ + static int current_level; + /* previous fan level */ + static int prev_current_level; + /* previous sensor temperature */ + static int prev_temp[TEMP_SENSOR_COUNT]; + int i; + int new_rpm = 0; + + /* + * Compare the current and previous temperature, we have + * the three paths : + * 1. decreasing path. (check the release point) + * 2. increasing path. (check the trigger point) + * 3. invariant path. (return the current RPM) + */ + if (temp[temp_sensor] < prev_temp[temp_sensor]) { + for (i = current_level; i > 0; i--) { + if (temp[temp_sensor] < fan_table[i].off[temp_sensor]) + current_level = i - 1; + else + break; + } + } else if (temp[temp_sensor] > prev_temp[temp_sensor]) { + for (i = current_level; i < num_fan_levels; i++) { + if (temp[temp_sensor] >= fan_table[i].on[temp_sensor]) + current_level = i; + else + break; + } + } + if (current_level < 0) + current_level = 0; + if (current_level >= num_fan_levels) + current_level = num_fan_levels - 1; + + if (current_level != prev_current_level) { + CPRINTS("temp: %d, prev_temp: %d", temp[temp_sensor], + prev_temp[temp_sensor]); + CPRINTS("current_level: %d", current_level); + } + + prev_temp[temp_sensor] = temp[temp_sensor]; + prev_current_level = current_level; + + switch (fan) { + case FAN_CH_0: + new_rpm = fan_table[current_level].rpm[FAN_CH_0]; + break; + default: + break; + } + return new_rpm; +} + +void board_override_fan_control(int fan, int *temp) +{ + if (chipset_in_state(CHIPSET_STATE_ON)) { + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), + fan_table_to_rpm(FAN_CH(fan), temp, + TEMP_SENSOR_2_CPU_VR)); + } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* Stop fan when enter S0ix */ + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), 0); + } +} diff --git a/board/moli/usbc_config.c b/board/moli/usbc_config.c new file mode 100644 index 0000000000..1c2f7eccf8 --- /dev/null +++ b/board/moli/usbc_config.c @@ -0,0 +1,345 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C1_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = IOEX_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C1) { + rst_signal = IOEX_USB_C1_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +__override int bb_retimer_reset(const struct usb_mux *me) +{ + /* + * TODO(b/193402306, b/195375738): Remove this once transition to + * QS Silicon is complete + */ + bb_retimer_power_enable(me, false); + msleep(5); + bb_retimer_power_enable(me, true); + msleep(25); + + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + enum gpio_signal tcpc_rst; + + tcpc_rst = GPIO_USB_C0_C1_TCPC_RST_ODL; + + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(tcpc_rst, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(tcpc_rst, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void enable_ioex(int ioex) +{ + ioex_init(ioex); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C1 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + enable_ioex(IOEX_C0_NCT38XX); + enable_ioex(IOEX_C1_NCT38XX); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C1_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return true; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/moli/usbc_config.h b/board/moli/usbc_config.h new file mode 100644 index 0000000000..219ad9a745 --- /dev/null +++ b/board/moli/usbc_config.h @@ -0,0 +1,15 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/moli/vif_override.xml b/board/moli/vif_override.xml new file mode 100644 index 0000000000..9fc397cd40 --- /dev/null +++ b/board/moli/vif_override.xml @@ -0,0 +1,129 @@ + + + + + 2 + 0 + + + + + + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 463E + + + + + + + + + + Gen 3 (40Gb) + + + + + + + + HBR3 + 4 Lanes + + + + USB 3.2 Gen 2x1 + + + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + + + + + PSD + PDUSB Host + + + + + + + + Gen 3 (40Gb) + + + + + + + + HBR3 + 4 Lanes + + + + USB 3.2 Gen 2x1 + + + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + + + + + PSD + PDUSB Host + + diff --git a/board/moonbuggy/board.c b/board/moonbuggy/board.c new file mode 100644 index 0000000000..9ee309d2fe --- /dev/null +++ b/board/moonbuggy/board.c @@ -0,0 +1,561 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Puff board-specific configuration */ + +#include "adc.h" +#include "button.h" +#include "chipset.h" +#include "common.h" +#include "core/cortex-m/cpu.h" +#include "cros_board_info.h" +#include "driver/ina3221.h" +#include "ec_commands.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "lid_switch.h" +#include "power.h" +#include "power/cometlake-discrete.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "spi.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" +#include "uart.h" +#include "usb_common.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ +#define PWR_BASE_LOAD (5 * 1335) +#define PWR_FRONT_HIGH (5 * 1500) +#define PWR_FRONT_LOW (5 * 900) +#define PWR_REAR (5 * 1500) +#define PWR_HDMI (5 * 562) +#define PWR_C_HIGH (5 * 3740) +#define PWR_C_LOW (5 * 2090) +#define PWR_MAX (5 * 10000) + +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int front_ports = 0; + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power = PWR_BASE_LOAD; + /* + * Only 1 front port can run higher power at a time. + */ + if (front_ports > 0) + base_5v_power += PWR_FRONT_HIGH - PWR_FRONT_LOW; + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) + base_5v_power += PWR_REAR; + if (!gpio_get_level(GPIO_HDMI_CONN0_OC_ODL)) + base_5v_power += PWR_HDMI; + if (!gpio_get_level(GPIO_HDMI_CONN1_OC_ODL)) + base_5v_power += PWR_HDMI; + if (!gpio_get_level(GPIO_HDMI_CONN2_OC_ODL)) + base_5v_power += PWR_HDMI; + if (usbc_overcurrent) + base_5v_power += PWR_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} + +/* + * Reverse current protection: + * When the board asserts +5Vs_V2_ADP_PRESENT_L active low, the EC needs + * to turn off the jack charger by setting EN_AC_JACK_CHARGER_EC_L high. + * + * When the board asserts BJ_ADP_PRESENT_L active low, the EC needs to + * enable the jack charger by setting EN_AC_JACK_CHARGER_EC_L low. + */ +static void ads_5v_deferred(void) +{ + int ads_5v_enable = !gpio_get_level(GPIO_ADS_5VS_V2_ADP_PRESENT_L); + + if (ads_5v_enable) + gpio_set_level(GPIO_EN_AC_JACK_CHARGER_EC_L, 1); +} +DECLARE_DEFERRED(ads_5v_deferred); + +void ads_5v_interrupt(enum gpio_signal signal) +{ + /* ADS 5v control time*/ + hook_call_deferred(&ads_5v_deferred_data, (5 * MSEC)); +} + +/** + * Handle debounced ADS 12v handler. + */ +static void ads_12v_deferred(void) +{ + int ads_12v_enable = !gpio_get_level(GPIO_BJ_ADP_PRESENT_L); + + if (ads_12v_enable) + gpio_set_level(GPIO_EN_AC_JACK_CHARGER_EC_L, 0); +} +DECLARE_DEFERRED(ads_12v_deferred); + +void ads_12v_interrupt(enum gpio_signal signal) +{ + /* ADS 12v control time */ + hook_call_deferred(&ads_12v_deferred_data, (5 * MSEC)); +} + +/******************************************************************************/ + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* SPI devices */ +const struct spi_device_t spi_devices[] = {}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +/******************************************************************************/ +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_LED_WHITE] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { .name = "ina", + .port = I2C_PORT_INA, + .kbps = 400, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "pse", + .port = I2C_PORT_PSE, + .kbps = 400, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA }, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 400, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct adc_t adc_channels[] = { + [ADC_SNS_PP3300] = { + /* + * 4700/5631 voltage divider: can take the value out of range + * for 32-bit signed integers, so truncate to 470/563 yielding + * <0.1% error and a maximum intermediate value of 1623457792, + * which comfortably fits in int32. + */ + .name = "SNS_PP3300", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 563, + .factor_div = (ADC_READ_MAX + 1) * 470, + }, + [ADC_SNS_PP1050] = { + .name = "SNS_PP1050", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 500 mV/A */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT * 2, /* Milliamps */ + .factor_div = ADC_READ_MAX + 1, + }, + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR_1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_CORE] = { + .name = "Core", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/******************************************************************************/ +/* Wake up pins */ +const enum gpio_signal hibernate_wake_pins[] = {}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/******************************************************************************/ +/* Physical fans. These are logically separate from pwm_channels. */ +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = -1, +}; + +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 5300, +}; + +const struct fan_t fans[] = { + [FAN_CH_0] = { .conf = &fan_conf_0, .rpm = &fan_rpm_0, }, +}; +BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); + +/******************************************************************************/ +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +/******************************************************************************/ +/* Thermal control; drive fan based on temperature sensors. */ +static const int temp_fan_off = C_TO_K(35); +static const int temp_fan_max = C_TO_K(55); +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_CORE] = { + .temp_host = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), + [EC_TEMP_THRESH_HALT] = C_TO_K(90), + }, + .temp_host_release = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(78), + [EC_TEMP_THRESH_HALT] = 0, + }, + .temp_fan_off = temp_fan_off, + .temp_fan_max = temp_fan_max, + }, +}; + +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +static const struct fan_step_1_1 fan_table0[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(35), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(41), + .rpm = 2500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .rpm = 2900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .rpm = 3400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .rpm = 3900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .rpm = 4400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(52), + .rpm = 4900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(55), + .rpm = 5300 }, +}; +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) + +static const struct fan_step_1_1 *fan_table = fan_table0; + +int fan_percent_to_rpm(int fan, int temp_ratio) +{ + return temp_ratio_to_rpm_hysteresis(fan_table, NUM_FAN_LEVELS, fan, + temp_ratio, NULL); +} + +/* Power sensors */ +const struct ina3221_t ina3221[] = { + { I2C_PORT_INA, 0x40, { "PP3300_G", "PP5000_A", "PP3300_WLAN" } }, + { I2C_PORT_INA, 0x42, { "PP3300_A", "PP3300_SSD", "PP3300_LAN" } }, + { I2C_PORT_INA, 0x43, { NULL, "PP1200_U", "PP2500_DRAM" } } +}; +const unsigned int ina3221_count = ARRAY_SIZE(ina3221); + +static uint16_t board_version; +static uint32_t sku_id; +static uint32_t fw_config; + +static void cbi_init(void) +{ + /* + * Load board info from CBI to control per-device configuration. + * + * If unset it's safe to treat the board as a proto, just C10 gating + * won't be enabled. + */ + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS && val <= UINT16_MAX) + board_version = val; + if (cbi_get_sku_id(&val) == EC_SUCCESS) + sku_id = val; + if (cbi_get_fw_config(&val) == EC_SUCCESS) + fw_config = val; + CPRINTS("Board Version: %d, SKU ID: 0x%08x, F/W config: 0x%08x", + board_version, sku_id, fw_config); +} +DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); + +static void board_init(void) +{ + uint8_t *memmap_batt_flags; + + /* Override some GPIO interrupt priorities. + * + * These interrupts are timing-critical for AP power sequencing, so we + * increase their NVIC priority from the default of 3. This affects + * whole MIWU groups of 8 GPIOs since they share an IRQ. + * + * Latency at the default priority level can be hundreds of + * microseconds while other equal-priority IRQs are serviced, so GPIOs + * requiring faster response must be higher priority. + */ + /* CPU_C10_GATE_L on GPIO6.7: must be ~instant for ~60us response. */ + cpu_set_interrupt_priority(NPCX_IRQ_WKINTH_1, 1); + /* + * slp_s3_interrupt (GPIOA.5 on WKINTC_0) must respond within 200us + * (tPLT18); less critical than the C10 gate. + */ + cpu_set_interrupt_priority(NPCX_IRQ_WKINTC_0, 2); + + /* Always claim AC is online, because we don't have a battery. */ + memmap_batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); + *memmap_batt_flags |= EC_BATT_FLAG_AC_PRESENT; + /* + * For board version < 2, the directly connected recovery + * button is not available. + */ + if (board_version < 2) + button_disable_gpio(BUTTON_RECOVERY); + + /* ADS GPIO interrupt enable*/ + gpio_enable_interrupt(GPIO_ADS_5VS_V2_ADP_PRESENT_L); + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_L); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/******************************************************************************/ +/* USB-A port control */ +const int usb_port_enable[USB_PORT_COUNT] = {}; + +int64_t get_time_dsw_pwrok(void) +{ + /* DSW_PWROK is turned on before EC was powered. */ + return -20 * MSEC; +} + +int extpower_is_present(void) +{ + /* genesis: If the EC is running, then there is external power */ + return 1; +} + +int board_is_c10_gate_enabled(void) +{ + return 0; +} + +void board_enable_s0_rails(int enable) +{ +} + +/* + * Power monitoring and management. + * + * The overall goal is to gracefully manage the power demand so that + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 2 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A BIT(0) +#define THROT_TYPE_C BIT(1) +#define THROT_PROCHOT BIT(2) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v = PWR_MAX - base_5v_power; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + } else { + delay = POWER_DELAY_MS * MSEC; + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v += PWR_C_HIGH - PWR_C_LOW; + new_state |= THROT_TYPE_C; + } + /* + * [2] If type A not already throttled, and power still + * needed, limit type A. + */ + /* No front USB A ports on moonbuggy. */ + /* + * [3] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v < 0) + new_state |= THROT_TYPE_C; + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/moonbuggy/board.h b/board/moonbuggy/board.h new file mode 100644 index 0000000000..96e1e60e6e --- /dev/null +++ b/board/moonbuggy/board.h @@ -0,0 +1,230 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Puff board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* NPCX7 config */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ + +/* Internal SPI flash on NPCX796FC is 512 kB */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) +#define CONFIG_SPI_FLASH_REGS +#define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ + +/* EC Defines */ +#define CONFIG_ADC +#define CONFIG_BOARD_HAS_RTC_RESET +#define CONFIG_BOARD_VERSION_CBI +#define CONFIG_DEDICATED_RECOVERY_BUTTON +#define CONFIG_DEDICATED_RECOVERY_BUTTON_2 +#define CONFIG_BUTTONS_RUNTIME_CONFIG +#define CONFIG_BOARD_RESET_AFTER_POWER_ON +/* TODO: (b/143496253) re-enable CEC */ +/* #define CONFIG_CEC */ +#define CONFIG_CRC8 +#define CONFIG_CBI_EEPROM +#define CONFIG_EMULATED_SYSRQ +#undef CONFIG_KEYBOARD_BOOT_KEYS +#define CONFIG_MKBP_INPUT_DEVICES +#define CONFIG_MKBP_USE_HOST_EVENT +#undef CONFIG_KEYBOARD_RUNTIME_KEYS +#undef CONFIG_HIBERNATE +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_LED_COMMON +#undef CONFIG_LID_SWITCH +#define CONFIG_LTO +#define CONFIG_PWM +#define CONFIG_VBOOT_EFS2 +#define CONFIG_VBOOT_HASH +#define CONFIG_VSTORE +#define CONFIG_VSTORE_SLOT_COUNT 1 +#define CONFIG_SHA256 + +/* EC Commands */ +#define CONFIG_CMD_BUTTON +/* Include CLI command needed to support CCD testing. */ +#define CONFIG_CMD_CHARGEN +#undef CONFIG_CMD_FASTCHARGE +#undef CONFIG_CMD_KEYBOARD +#define CONFIG_HOSTCMD_PD_CONTROL +#undef CONFIG_CMD_PWR_AVG +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_CMD_TCPC_DUMP +#ifdef SECTION_IS_RO +/* Reduce RO size by removing less-relevant commands. */ +#undef CONFIG_CMD_APTHROTTLE +#undef CONFIG_CMD_CHARGEN +#undef CONFIG_CMD_HCDEBUG +#undef CONFIG_CMD_MMAPINFO +#endif + +#undef CONFIG_CONSOLE_CMDHELP + +/* Don't generate host command debug by default */ +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + +/* Enable AP Reset command for TPM with old firmware version to detect it. */ +#define CONFIG_CMD_AP_RESET_LOG +#define CONFIG_HOSTCMD_AP_RESET + +/* Chipset config */ +#define CONFIG_CHIPSET_COMETLAKE_DISCRETE +/* check */ +#define CONFIG_CHIPSET_CAN_THROTTLE +#define CONFIG_CHIPSET_RESET_HOOK +#define CONFIG_CPU_PROCHOT_ACTIVE_LOW + +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_IGNORE_LID +#define CONFIG_POWER_BUTTON_X86 +/* Check: */ +#define CONFIG_POWER_BUTTON_INIT_IDLE +#define CONFIG_POWER_COMMON +#define CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD 30 +#define CONFIG_DELAY_DSW_PWROK_TO_PWRBTN +#define CONFIG_POWER_PP5000_CONTROL +#define CONFIG_POWER_S0IX +#define CONFIG_POWER_S0IX_FAILURE_DETECTION +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define CONFIG_INA3221 + +/* Fan and temp. */ +#define CONFIG_FANS 1 +#undef CONFIG_FAN_INIT_SPEED +#define CONFIG_FAN_INIT_SPEED 0 +#define CONFIG_FAN_RPM_CUSTOM +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B +#define CONFIG_THROTTLE_AP + +#define CONFIG_USB_PD_PORT_MAX_COUNT 0 + +/* USB Type A Features */ +#define CONFIG_USB_PORT_POWER_DUMB +/* There are five ports, but power enable is ganged across all of them. */ +#define USB_PORT_COUNT 0 + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER +#define I2C_PORT_INA NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 +#define I2C_PORT_PSE NPCX_I2C_PORT4_1 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define PP5000_PGOOD_POWER_SIGNAL_MASK POWER_SIGNAL_MASK(PP5000_A_PGOOD) + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_SNS_PP3300, /* ADC2 */ + ADC_SNS_PP1050, /* ADC7 */ + ADC_VBUS, /* ADC4 */ + ADC_PPVAR_IMON, /* ADC9 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + /* Number of ADC channels */ + ADC_CH_COUNT +}; + +enum pwm_channel { + PWM_CH_FAN, + PWM_CH_LED_RED, + PWM_CH_LED_WHITE, + /* Number of PWM channels */ + PWM_CH_COUNT +}; + +enum fan_channel { + FAN_CH_0, + /* Number of FAN channels */ + FAN_CH_COUNT +}; + +enum mft_channel { + MFT_CH_0 = 0, + /* Number of MFT channels */ + MFT_CH_COUNT, +}; + +enum temp_sensor_id { TEMP_SENSOR_CORE, TEMP_SENSOR_COUNT }; + +/* Board specific handlers */ +void led_alert(int enable); +void show_critical_error(void); + +/* Board ADS control handlers */ +void ads_5v_interrupt(enum gpio_signal signal); +void ads_12v_interrupt(enum gpio_signal signal); + +/* + * firmware config fields + */ +/* + * Barrel-jack power (4 bits). + */ +#define EC_CFG_BJ_POWER_L 0 +#define EC_CFG_BJ_POWER_H 3 +#define EC_CFG_BJ_POWER_MASK GENMASK(EC_CFG_BJ_POWER_H, EC_CFG_BJ_POWER_L) +/* + * USB Connector 4 not present (1 bit). + */ +#define EC_CFG_NO_USB4_L 4 +#define EC_CFG_NO_USB4_H 4 +#define EC_CFG_NO_USB4_MASK GENMASK(EC_CFG_NO_USB4_H, EC_CFG_NO_USB4_L) +/* + * Thermal solution config (3 bits). + */ +#define EC_CFG_THERMAL_L 5 +#define EC_CFG_THERMAL_H 7 +#define EC_CFG_THERMAL_MASK GENMASK(EC_CFG_THERMAL_H, EC_CFG_THERMAL_L) + +unsigned int ec_config_get_thermal_solution(void); + +#endif /* !__ASSEMBLER__ */ + +/* Pin renaming */ +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_PP5000_A_PG_OD GPIO_PG_PP5000_A_OD +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL +#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_ROA_RAILS +#define GPIO_AC_PRESENT GPIO_BJ_ADP_PRESENT_L + +/* + * There is no RSMRST input, so alias it to the output. This short-circuits + * common_intel_x86_handle_rsmrst. + */ +#define GPIO_PG_EC_RSMRST_ODL GPIO_PCH_RSMRST_L + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/moonbuggy/build.mk b/board/moonbuggy/build.mk new file mode 100644 index 0000000000..aca2a91e5c --- /dev/null +++ b/board/moonbuggy/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc + +board-y=board.o +board-y+=led.o +board-y+=pse.o diff --git a/board/moonbuggy/ec.tasklist b/board/moonbuggy/ec.tasklist new file mode 100644 index 0000000000..c43d643410 --- /dev/null +++ b/board/moonbuggy/ec.tasklist @@ -0,0 +1,15 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 2048) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/moonbuggy/gpio.inc b/board/moonbuggy/gpio.inc new file mode 100644 index 0000000000..bb914d2254 --- /dev/null +++ b/board/moonbuggy/gpio.inc @@ -0,0 +1,176 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Pin names follow the schematic, and are aliased to other names if necessary. + * Note: Those with interrupt handlers must be declared first. */ + +/* Latency on this interrupt is extremely critical, so it comes first to ensure + * it gets placed first in gpio_wui_table so gpio_interrupt() needs to do + * minimal scanning. */ +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, c10_gate_interrupt) + +/* Wake Source interrupts */ +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(PG_PP5000_A_OD, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1800_A_OD, PIN(3, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VPRIM_CORE_A_OD, PIN(2, 3), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1050_A_OD, PIN(2, 2), GPIO_INT_BOTH, power_signal_interrupt) +/* EC output, but also interrupt so this can be polled as a power signal */ +GPIO_INT(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUTPUT | GPIO_INT_F_RISING | GPIO_INT_F_FALLING, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(PG_PP2500_DRAM_U_OD, PIN(2, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1200_U_OD, PIN(2, 1), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, slp_s3_interrupt) +#endif +GPIO_INT(PG_PP950_VCCIO_OD, PIN(1, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(IMVP8_VRRDY_OD, PIN(1, 6), GPIO_INT_BOTH, power_signal_interrupt) + +/* + * Directly connected recovery button (not available on some boards). + */ +GPIO_INT(EC_RECOVERY_BTN_ODL, PIN(F, 1), GPIO_INT_BOTH, button_interrupt) +/* + * Recovery button input from H1. + */ +GPIO_INT(H1_EC_RECOVERY_BTN_ODL, PIN(2, 4), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(BJ_ADP_PRESENT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, +ads_12v_interrupt) + +/* Port power control interrupts */ +GPIO_INT(HDMI_CONN0_OC_ODL, PIN(0, 7), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(HDMI_CONN1_OC_ODL, PIN(0, 6), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(HDMI_CONN2_OC_ODL, PIN(8, 3), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(A, 2), GPIO_INT_BOTH, port_ocp_interrupt) + +/* PCH/CPU signals */ +GPIO(EC_PCH_PWROK, PIN(0, 5), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_IN_OD, PIN(3, 4), GPIO_INPUT) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +/* ADB Scaler signals */ +GPIO(ADB_WAKEUP_EC, PIN(B, 1), GPIO_INPUT) + +/* Power control outputs */ +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PP3300_INA_H1_EC_ODL, PIN(5, 7), GPIO_ODR_HIGH) +GPIO(EN_PP1800_A, PIN(1, 5), GPIO_OUT_LOW) +GPIO(VCCST_PG_OD, PIN(1, 4), GPIO_ODR_LOW) +GPIO(EN_S0_RAILS, PIN(1, 1), GPIO_OUT_LOW) +GPIO(EN_ROA_RAILS, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP950_VCCIO, PIN(1, 0), GPIO_OUT_LOW) +GPIO(EC_IMVP8_PE, PIN(A, 7), GPIO_OUT_LOW) +GPIO(EN_IMVP8_VR, PIN(F, 4), GPIO_OUT_LOW) + +/* Barreljack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 4), GPIO_OUT_LOW) + +/* USB type A */ +GPIO(USB_A_LOW_PWR_OD, PIN(9, 4), GPIO_ODR_LOW) + +/* USB type C */ +GPIO(USB_C0_POL_L, PIN(0, 0), GPIO_INPUT | GPIO_SEL_1P8V) /* USB-C Polarity */ +UNUSED(PIN(7, 2)) /* EN_USB_C0_5V_OUT only works if set unused */ +GPIO(SBU_C0_FAULT_ODL, PIN(5, 6), GPIO_INPUT) + +/* TPU */ +GPIO(PP3300_TPU_EN, PIN(E, 4), GPIO_OUT_HIGH) + +/* PSE controller */ +GPIO(EC_PSE_PWM_INT, PIN(B, 0), GPIO_INPUT) /* PSE controller interrupt */ +GPIO(EC_RST_LTC4291_L, PIN(9, 6), GPIO_OUT_HIGH) /* PSE controller reset */ + +/* Misc. */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) +GPIO(PACKET_MODE_EN, PIN(7, 5), GPIO_OUT_LOW) +GPIO_INT(ADS_5VS_V2_ADP_PRESENT_L, PIN(0, 3), GPIO_INT_FALLING | GPIO_PULL_UP, +ads_5v_interrupt) +GPIO(EN_AC_JACK_CHARGER_EC_L, PIN(C, 0), GPIO_OUT_LOW) +GPIO(LAN_WAKE_ODL_EC, PIN(8, 0), GPIO_INPUT) /* LAN_WAKE */ + +/* HDMI/CEC */ +GPIO(HDMI_CONN0_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CONN1_CEC_OUT, PIN(9, 5), GPIO_ODR_HIGH) +GPIO(HDMI_CONN1_CEC_IN, PIN(D, 3), GPIO_INPUT) +GPIO(HDMI_DATA_EN_DB, PIN(6, 1), GPIO_OUT_HIGH) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(I2C0_SCL, PIN(B, 5), GPIO_INPUT) /* EC_I2C_INA_SCL */ +GPIO(I2C0_SDA, PIN(B, 4), GPIO_INPUT) /* EC_I2C_INA_SDA */ +GPIO(I2C3_SCL, PIN(D, 1), GPIO_INPUT) /* EC_I2C_ADB_SCL */ +GPIO(I2C3_SDA, PIN(D, 0), GPIO_INPUT) /* EC_I2C_ADB_SDA */ +GPIO(I2C4_SCL, PIN(F, 3), GPIO_INPUT) /* EC_I2C_LTC_SCL */ +GPIO(I2C4_SDA, PIN(F, 2), GPIO_INPUT) /* EC_I2C_LTC_SDA */ +GPIO(I2C5_SCL, PIN(3, 3), GPIO_INPUT) /* EC_I2C_IMVP8_SCL */ +GPIO(I2C5_SDA, PIN(3, 6), GPIO_INPUT) /* EC_I2C_IMVP8_SDA */ +GPIO(I2C7_SCL, PIN(B, 3), GPIO_INPUT) /* EC_I2C_EEPROM_SCL */ +GPIO(I2C7_SDA, PIN(B, 2), GPIO_INPUT) /* EC_I2C_EEPROM_SDA */ + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(9, 0x01), 0, MODULE_I2C, 0) /* I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(F, 0x0C), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, 0x0C), 0, MODULE_I2C, 0) /* I2C7 */ + +/* PWM */ +ALTERNATE(PIN_MASK(C, 0x08), 0, MODULE_PWM, 0) /* PWM0 - Red Led */ +ALTERNATE(PIN_MASK(C, 0x10), 0, MODULE_PWM, 0) /* PWM2 - White Led */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* PWM5 - Fan 1 */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* TA2 - Fan Tachometer */ + +/* ADC */ +ALTERNATE(PIN_MASK(4, 0x2A), 0, MODULE_ADC, 0) /* ADC0, ADC2, ADC4 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* ADC7 */ +ALTERNATE(PIN_MASK(F, 0x01), 0, MODULE_ADC, 0) /* ADC9 */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Unused pins */ +UNUSED(PIN(1, 3)) /* EC_GP_SEL1_ODL */ +UNUSED(PIN(4, 4)) /* ADC1/TEMP_SENSOR_2 */ +UNUSED(PIN(4, 2)) /* ADC3/TEMP_SENSOR_3 */ +UNUSED(PIN(9, 2)) /* K8 NC */ +UNUSED(PIN(9, 1)) /* L8 NC */ +UNUSED(PIN(1, 2)) /* C6 NC */ +UNUSED(PIN(6, 6)) /* H4 NC */ +UNUSED(PIN(8, 1)) /* L6 NC */ +UNUSED(PIN(C, 6)) /* B11 NC */ +UNUSED(PIN(E, 2)) /* B8 NC */ +UNUSED(PIN(8, 5)) /* L7 NC */ +UNUSED(PIN(3, 2)) /* E5 NC */ +UNUSED(PIN(D, 6)) /* F6 NC */ +UNUSED(PIN(3, 5)) /* F5 NC */ +UNUSED(PIN(8, 6)) /* J8 NC */ +UNUSED(PIN(9, 3)) /* M11 NC */ +UNUSED(PIN(C, 7)) /* B9 NC */ +UNUSED(PIN(D, 2)) /* C11 NC */ +UNUSED(PIN(F, 5)) /* E7 NC */ +UNUSED(PIN(5, 0)) /* G4 NC */ +UNUSED(PIN(9, 0)) /* J10 NC */ +UNUSED(PIN(8, 7)) /* M7 NC */ +UNUSED(PIN(6, 2)) /* J2 NC */ +UNUSED(PIN(9, 7)) /* J9 NC */ +UNUSED(PIN(0, 2)) /* D10 NC */ +UNUSED(PIN(C, 2)) /* A12 NC */ diff --git a/board/moonbuggy/led.c b/board/moonbuggy/led.c new file mode 100644 index 0000000000..cc76c36dce --- /dev/null +++ b/board/moonbuggy/led.c @@ -0,0 +1,263 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Puff. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_WHITE, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int white = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_WHITE: + white = 1; + break; + case LED_RED: + red = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (white) + pwm_set_duty(PWM_CH_LED_WHITE, duty); + else + pwm_set_duty(PWM_CH_LED_WHITE, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_WHITE); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_WHITE, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +static void led_init(void) +{ + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_WHITE, 1); + + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + led_suspend(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown(); +} +DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_INIT_PWM + 1); + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "white")) { + set_color(id, LED_WHITE, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|red|white|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_WHITE]) + return set_color(id, LED_WHITE, brightness[EC_LED_COLOR_WHITE]); + else + return set_color(id, LED_OFF, 0); +} diff --git a/board/moonbuggy/pse.c b/board/moonbuggy/pse.c new file mode 100644 index 0000000000..c309db887a --- /dev/null +++ b/board/moonbuggy/pse.c @@ -0,0 +1,264 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * The LTC4291 is a power over ethernet (PoE) power sourcing equipment (PSE) + * controller. + */ + +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "string.h" +#include "timer.h" +#include "util.h" + +#define LTC4291_I2C_ADDR 0x2C + +#define LTC4291_REG_SUPEVN_COR 0x0B +#define LTC4291_REG_STATPWR 0x10 +#define LTC4291_REG_STATPIN 0x11 +#define LTC4291_REG_OPMD 0x12 +#define LTC4291_REG_DISENA 0x13 +#define LTC4291_REG_DETENA 0x14 +#define LTC4291_REG_DETPB 0x18 +#define LTC4291_REG_PWRPB 0x19 +#define LTC4291_REG_RSTPB 0x1A +#define LTC4291_REG_ID 0x1B +#define LTC4291_REG_DEVID 0x43 +#define LTC4291_REG_HPMD1 0x46 +#define LTC4291_REG_HPMD2 0x4B +#define LTC4291_REG_HPMD3 0x50 +#define LTC4291_REG_HPMD4 0x55 +#define LTC4291_REG_LPWRPB 0x6E + +#define LTC4291_FLD_STATPIN_AUTO BIT(0) +#define LTC4291_FLD_RSTPB_RSTALL BIT(4) + +#define LTC4291_STATPWR_ON_PORT(port) (0x01 << (port)) +#define LTC4291_DETENA_EN_PORT(port) (0x11 << (port)) +#define LTC4291_DETPB_EN_PORT(port) (0x11 << (port)) +#define LTC4291_PWRPB_OFF_PORT(port) (0x10 << (port)) + +#define LTC4291_OPMD_AUTO 0xFF +#define LTC4291_DISENA_ALL 0x0F +#define LTC4291_DETENA_ALL 0xFF +#define LTC4291_ID 0x64 +#define LTC4291_DEVID 0x38 +#define LTC4291_HPMD_MIN 0x00 +#define LTC4291_HPMD_MAX 0xA8 + +#define LTC4291_PORT_MAX 4 + +#define LTC4291_RESET_DELAY_US (20 * MSEC) + +#define I2C_PSE_READ(reg, data) \ + i2c_read8(I2C_PORT_PSE, LTC4291_I2C_ADDR, LTC4291_REG_##reg, (data)) + +#define I2C_PSE_WRITE(reg, data) \ + i2c_write8(I2C_PORT_PSE, LTC4291_I2C_ADDR, LTC4291_REG_##reg, (data)) + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static int pse_write_hpmd(int port, int val) +{ + switch (port) { + case 0: + return I2C_PSE_WRITE(HPMD1, val); + case 1: + return I2C_PSE_WRITE(HPMD2, val); + case 2: + return I2C_PSE_WRITE(HPMD3, val); + case 3: + return I2C_PSE_WRITE(HPMD4, val); + default: + return EC_ERROR_INVAL; + } +} + +/* + * Port 1-4: 15W + */ +static int pse_port_hpmd[LTC4291_PORT_MAX] = { + LTC4291_HPMD_MIN, + LTC4291_HPMD_MIN, + LTC4291_HPMD_MIN, + LTC4291_HPMD_MIN, +}; + +static int pse_port_enable(int port) +{ + /* Enable detection and classification */ + return I2C_PSE_WRITE(DETPB, LTC4291_DETPB_EN_PORT(port)); +} + +static int pse_port_disable(int port) +{ + /* Request power off (this also disables detection/classification) */ + return I2C_PSE_WRITE(PWRPB, LTC4291_PWRPB_OFF_PORT(port)); +} + +static int pse_init_worker(void) +{ + timestamp_t deadline; + int err, id, devid, statpin, port; + + /* Ignore errors -- may already be resetting */ + I2C_PSE_WRITE(RSTPB, LTC4291_FLD_RSTPB_RSTALL); + + deadline.val = get_time().val + LTC4291_RESET_DELAY_US; + while ((err = I2C_PSE_READ(ID, &id)) != 0) { + if (timestamp_expired(deadline, NULL)) + return err; + } + + err = I2C_PSE_READ(DEVID, &devid); + if (err != 0) + return err; + + if (id != LTC4291_ID || devid != LTC4291_DEVID) + return EC_ERROR_INVAL; + + err = I2C_PSE_READ(STATPIN, &statpin); + if (err != 0) + return err; + + /* + * We don't want to supply power until we've had a chance to set the + * limits. + */ + if (statpin & LTC4291_FLD_STATPIN_AUTO) + CPRINTS("WARN: PSE reset in AUTO mode"); + + err = I2C_PSE_WRITE(OPMD, LTC4291_OPMD_AUTO); + if (err != 0) + return err; + + /* Set maximum power each port is allowed to allocate. */ + for (port = 0; port < LTC4291_PORT_MAX; port++) { + err = pse_write_hpmd(port, pse_port_hpmd[port]); + if (err != 0) + return err; + } + + err = I2C_PSE_WRITE(DISENA, LTC4291_DISENA_ALL); + if (err != 0) + return err; + + err = I2C_PSE_WRITE(DETENA, LTC4291_DETENA_ALL); + if (err != 0) + return err; + + return 0; +} + +static void pse_init(void) +{ + int err; + + err = pse_init_worker(); + if (err != 0) + CPRINTS("PSE init failed: %d", err); + else + CPRINTS("PSE init done"); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, pse_init, HOOK_PRIO_DEFAULT); + +/* Also reset the PSE on a reboot to toggle the power. */ +DECLARE_HOOK(HOOK_CHIPSET_RESET, pse_init, HOOK_PRIO_DEFAULT); + +static int command_pse(int argc, const char **argv) +{ + int port; + + /* + * TODO(b/156399232): endeavour: PSE controller reset by PLTRST + * + * Initialization does not reliably work after reset because the device + * is held in reset by the AP. Running this command after boot finishes + * always succeeds. Remove once the reset signal changes. + */ + if (!strncmp(argv[1], "init", 4)) + return pse_init_worker(); + + if (argc != 3) + return EC_ERROR_PARAM_COUNT; + + port = atoi(argv[1]); + if (port < 0 || port >= LTC4291_PORT_MAX) + return EC_ERROR_PARAM1; + + if (!strncmp(argv[2], "off", 3)) + return pse_port_disable(port); + else if (!strncmp(argv[2], "on", 2)) + return pse_port_enable(port); + else if (!strncmp(argv[2], "min", 3)) + return pse_write_hpmd(port, LTC4291_HPMD_MIN); + else if (!strncmp(argv[2], "max", 3)) + return pse_write_hpmd(port, LTC4291_HPMD_MAX); + else + return EC_ERROR_PARAM2; +} +DECLARE_CONSOLE_COMMAND(pse, command_pse, " ", + "Set PSE port power"); + +static int ec_command_pse_status(int port, uint8_t *status) +{ + int detena, statpwr; + int err; + + err = I2C_PSE_READ(DETENA, &detena); + if (err != 0) + return err; + + err = I2C_PSE_READ(STATPWR, &statpwr); + if (err != 0) + return err; + + if ((detena & LTC4291_DETENA_EN_PORT(port)) == 0) + *status = EC_PSE_STATUS_DISABLED; + else if ((statpwr & LTC4291_STATPWR_ON_PORT(port)) == 0) + *status = EC_PSE_STATUS_ENABLED; + else + *status = EC_PSE_STATUS_POWERED; + + return 0; +} + +static enum ec_status ec_command_pse(struct host_cmd_handler_args *args) +{ + const struct ec_params_pse *p = args->params; + int err = 0; + + if (p->port >= LTC4291_PORT_MAX) + return EC_RES_INVALID_PARAM; + + switch (p->cmd) { + case EC_PSE_STATUS: { + struct ec_response_pse_status *r = args->response; + + args->response_size = sizeof(*r); + err = ec_command_pse_status(p->port, &r->status); + break; + } + case EC_PSE_ENABLE: + err = pse_port_enable(p->port); + break; + case EC_PSE_DISABLE: + err = pse_port_disable(p->port); + break; + default: + return EC_RES_INVALID_PARAM; + } + + if (err) + return EC_RES_ERROR; + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PSE, ec_command_pse, EC_VER_MASK(0)); diff --git a/board/morphius/battery.c b/board/morphius/battery.c index 6d8a8190b2..6867bcd8bd 100644 --- a/board/morphius/battery.c +++ b/board/morphius/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/morphius/board.c b/board/morphius/board.c index 8dca1c99ed..03a141e98b 100644 --- a/board/morphius/board.c +++ b/board/morphius/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,15 +6,17 @@ /* Morphius board configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery_smart.h" #include "button.h" +#include "cbi_ssfc.h" #include "charger.h" #include "cros_board_info.h" -#include "driver/accelgyro_bmi_common.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" -#include "driver/ppc/aoz1380.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/ppc/aoz1380_public.h" #include "driver/ppc/nx20p348x.h" #include "driver/retimer/pi3dpx1207.h" #include "driver/retimer/pi3hdx1204.h" @@ -22,12 +24,13 @@ #include "driver/temp_sensor/tmp432.h" #include "driver/usb_mux/amd_fp5.h" #include "extpower.h" -#include "gpio.h" #include "fan.h" #include "fan_chip.h" +#include "gpio.h" #include "hooks.h" #include "keyboard_8042.h" #include "lid_switch.h" +#include "mkbp_event.h" #include "power.h" #include "power_button.h" #include "ps2_chip.h" @@ -38,39 +41,39 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" -#include "thermistor.h" -#include "usb_mux.h" +#include "temp_sensor/thermistor.h" #include "usb_charge.h" +#include "usb_mux.h" #include "usbc_ppc.h" static void hdmi_hpd_interrupt_v2(enum ioex_signal signal); static void hdmi_hpd_interrupt_v3(enum gpio_signal signal); static void board_gmr_tablet_switch_isr(enum gpio_signal signal); +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" static bool support_aoz_ppc; - -#ifdef HAS_TASK_MOTIONSENSE +static bool ignore_c1_dp; /* Motion sensors */ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; -mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; -mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +const mat33_fp_t base_standard_ref_1 = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; /* TODO(gcc >= 5.0) Remove the casts to const pointer at rot_standard_ref */ struct motion_sensor_t motion_sensors[] = { @@ -113,7 +116,7 @@ struct motion_sensor_t motion_sensors[] = { .drv_data = &g_bmi160_data, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .default_range = 2, /* g, enough for laptop */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ .rot_standard_ref = (const mat33_fp_t *)&base_standard_ref, .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, @@ -150,7 +153,49 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#endif /* HAS_TASK_MOTIONSENSE */ +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_standard_ref_1, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_1, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { @@ -189,13 +234,64 @@ const int usb_port_enable[USBA_PORT_COUNT] = { const struct pi3hdx1204_tuning pi3hdx1204_tuning = { .eq_ch0_ch1_offset = PI3HDX1204_EQ_DB710, .eq_ch2_ch3_offset = PI3HDX1204_EQ_DB710, - .vod_offset = PI3HDX1204_VOD_115_ALL_CHANNELS, + .vod_offset = PI3HDX1204_VOD_130_ALL_CHANNELS, .de_offset = PI3HDX1204_DE_DB_MINUS7, }; +/***************************************************************************** + * Base Gyro Sensor dynamic configuration + */ +static enum ec_ssfc_base_gyro_sensor base_gyro_config = SSFC_BASE_GYRO_NONE; + +enum ec_ssfc_base_gyro_sensor get_base_gyro_sensor(void) +{ + switch (get_cbi_ssfc_base_sensor()) { + case SSFC_BASE_GYRO_NONE: + return ec_config_has_base_gyro_sensor(); + default: + return get_cbi_ssfc_base_sensor(); + } +} + +static void setup_base_gyro_config(void) +{ + base_gyro_config = get_base_gyro_sensor(); + + switch (base_gyro_config) { + case SSFC_BASE_GYRO_BMI160: + ccprints("BASE GYRO is BMI160"); + break; + case SSFC_BASE_GYRO_ICM426XX: + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE GYRO is ICM426XX"); + break; + default: + break; + } +} + +void motion_interrupt(enum gpio_signal signal) +{ + switch (base_gyro_config) { + case SSFC_BASE_GYRO_BMI160: + bmi160_interrupt(signal); + break; + case SSFC_BASE_GYRO_ICM426XX: + icm426xx_interrupt(signal); + break; + default: + break; + } +} + /***************************************************************************** * USB-C MUX/Retimer dynamic configuration */ + +/* Place holder for second mux in USBC1 chain */ +struct usb_mux_chain usbc1_mux1; + static void setup_mux(void) { if (ec_config_has_usbc1_retimer_ps8802()) { @@ -207,12 +303,10 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the PS8802 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_ps8802, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_ps8802; /* Set the AMD FP5 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_amd_fp5_usb_mux; + usbc1_mux1.mux = &usbc1_amd_fp5_usb_mux; /* Don't have the AMD FP5 flip */ usbc1_amd_fp5_usb_mux.flags = USB_MUX_FLAG_SET_WITHOUT_FLIP; @@ -226,12 +320,10 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the AMD FP5 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_amd_fp5_usb_mux, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_amd_fp5_usb_mux; /* Set the PS8818 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_ps8818; + usbc1_mux1.mux = &usbc1_ps8818; } } @@ -245,23 +337,29 @@ const struct pi3dpx1207_usb_control pi3dpx1207_controls[] = { }; BUILD_ASSERT(ARRAY_SIZE(pi3dpx1207_controls) == USBC_PORT_COUNT); -const struct usb_mux usbc0_pi3dpx1207_usb_retimer = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = PI3DPX1207_I2C_ADDR_FLAGS, - .driver = &pi3dpx1207_usb_retimer, +const struct usb_mux_chain usbc0_pi3dpx1207_usb_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = PI3DPX1207_I2C_ADDR_FLAGS, + .driver = &pi3dpx1207_usb_retimer, + }, }; -struct usb_mux usb_muxes[] = { +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .next_mux = &usbc0_pi3dpx1207_usb_retimer, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_pi3dpx1207_usb_retimer, }, [USBC_PORT_C1] = { /* Filled in dynamically at startup */ + .next = &usbc1_mux1, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); @@ -286,7 +384,7 @@ static void setup_v0_charger(void) */ DECLARE_HOOK(HOOK_INIT, setup_v0_charger, HOOK_PRIO_INIT_I2C); -enum gpio_signal board_usbc_port_to_hpd_gpio(int port) +int board_usbc_port_to_hpd_gpio_or_ioex(int port) { /* USB-C0 always uses USB_C0_HPD (= DP3_HPD). */ if (port == 0) @@ -303,11 +401,9 @@ enum gpio_signal board_usbc_port_to_hpd_gpio(int port) * this will be removed when version_2 hardware is retired. */ else if (ec_config_has_mst_hub_rtd2141b()) - return (board_ver >= 4) - ? GPIO_USB_C1_HPD_IN_DB_V1 - : (board_ver == 3) - ? IOEX_USB_C1_HPD_IN_DB - : GPIO_EC_DP1_HPD; + return (board_ver >= 4) ? GPIO_USB_C1_HPD_IN_DB_V1 : + (board_ver == 3) ? IOEX_USB_C1_HPD_IN_DB : + GPIO_EC_DP1_HPD; /* USB-C1 OPT1 DB uses DP2_HPD. */ return GPIO_DP2_HPD; @@ -376,6 +472,8 @@ static void setup_fw_config(void) setup_mux(); board_remap_gpio(); + + setup_base_gyro_config(); } /* Use HOOK_PRIO_INIT_I2C + 2 to be after ioex_init(). */ DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); @@ -387,7 +485,7 @@ DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = -1, }; @@ -482,17 +580,20 @@ const struct temp_sensor_t temp_sensors[] = { }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(90), - [EC_TEMP_THRESH_HALT] = C_TO_K(105), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(80), - }, - .temp_fan_off = C_TO_K(98), - .temp_fan_max = C_TO_K(99), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(105), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -503,11 +604,11 @@ static void setup_fans(void) DECLARE_HOOK(HOOK_INIT, setup_fans, HOOK_PRIO_DEFAULT); /* Battery functions */ -#define SB_OPTIONALMFG_FUNCTION2 0x26 -#define SMART_CHARGE_SUPPORT 0x01 -#define SMART_CHARGE_ENABLE 0x02 -#define SB_SMART_CHARGE_ENABLE 1 -#define SB_SMART_CHARGE_DISABLE 0 +#define SB_OPTIONALMFG_FUNCTION2 0x26 +#define SMART_CHARGE_SUPPORT 0x01 +#define SMART_CHARGE_ENABLE 0x02 +#define SB_SMART_CHARGE_ENABLE 1 +#define SB_SMART_CHARGE_DISABLE 0 static void sb_smart_charge_mode(int enable) { @@ -549,18 +650,18 @@ __override void ppc_interrupt(enum gpio_signal signal) * the attached NCT3807 to control a GPIO to indicate 1A5 or 3A0 * current limits. */ -__override int board_aoz1380_set_vbus_source_current_limit(int port, - enum tcpc_rp_value rp) +__override int +board_aoz1380_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) { int rv; /* Use the TCPC to set the current limit */ if (port == 0) { rv = ioex_set_level(IOEX_USB_C0_PPC_ILIM_3A_EN, - (rp == TYPEC_RP_3A0) ? 1 : 0); + (rp == TYPEC_RP_3A0) ? 1 : 0); } else if (board_ver >= 3) { rv = ioex_set_level(IOEX_USB_C1_PPC_ILIM_3A_EN, - (rp == TYPEC_RP_3A0) ? 1 : 0); + (rp == TYPEC_RP_3A0) ? 1 : 0); } else { rv = 1; } @@ -614,26 +715,37 @@ static void board_chipset_resume(void) ioex_set_level(IOEX_HDMI_POWER_EN_DB, 1); msleep(PI3HDX1204_POWER_ON_DELAY_MS); } - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, check_hdmi_hpd_status()); } } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); +static void board_chipset_suspend_delay(void) +{ + ignore_c1_dp = false; +} +DECLARE_DEFERRED(board_chipset_suspend_delay); + static void board_chipset_suspend(void) { /* SMART charge current */ sb_smart_charge_mode(SB_SMART_CHARGE_ENABLE); if (ec_config_has_hdmi_retimer_pi3hdx1204()) { - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - 0); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, 0); if (board_ver >= 3) ioex_set_level(IOEX_HDMI_POWER_EN_DB, 0); } + /* Wait 500ms before allowing DP event to cause resume. */ + if (ec_config_has_mst_hub_rtd2141b() && + (dp_flags[USBC_PORT_C1] & DP_FLAGS_DP_ON)) { + ignore_c1_dp = true; + hook_call_deferred(&board_chipset_suspend_delay_data, + 500 * MSEC); + } + ioex_set_level(IOEX_HDMI_DATA_EN_DB, 0); } DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); @@ -673,15 +785,14 @@ BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); * The connector has 24 pins total, and there is no pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {3, 0}, {2, 2}, {2, 3}, {1, 2}, {2, 5}, - {2, 4}, {2, 1}, {2, 7}, {2, 6}, {1, 5}, - {2, 0}, {3, 1}, {1, 7}, {1, 6}, {-1, -1}, - {1, 3}, {1, 4}, {-1, -1}, {-1, -1}, {0, 7}, - {0, 6}, {1, 0}, {1, 1}, {0, 5}, + { 3, 0 }, { 2, 2 }, { 2, 3 }, { 1, 2 }, { 2, 5 }, { 2, 4 }, + { 2, 1 }, { 2, 7 }, { 2, 6 }, { 1, 5 }, { 2, 0 }, { 3, 1 }, + { 1, 7 }, { 1, 6 }, { -1, -1 }, { 1, 3 }, { 1, 4 }, { -1, -1 }, + { -1, -1 }, { 0, 7 }, { 0, 6 }, { 1, 0 }, { 1, 1 }, { 0, 5 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); #endif /***************************************************************************** @@ -724,10 +835,9 @@ static void hdmi_hpd_handler(void) gpio_set_level(GPIO_EC_DP1_HPD, hpd); ccprints("HDMI HPD %d", hpd); - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON) - && hpd); + pi3hdx1204_enable( + I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, + chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON) && hpd); } DECLARE_DEFERRED(hdmi_hpd_handler); @@ -758,7 +868,20 @@ int board_sensor_at_360(void) * mode. */ if (board_ver >= 3) - return !gpio_get_level(GMR_TABLET_MODE_GPIO_L); + return !gpio_get_level(GPIO_TABLET_MODE_L); return 0; } + +/* + * b/167949458: Suppress setting the host event for 500ms after entering S3. + * Otherwise turning off the MST hub in S3 (via IOEX_HDMI_DATA_EN_DB) causes + * a VDM:Attention that immediately wakes us back up from S3. + */ +__override void pd_notify_dp_alt_mode_entry(int port) +{ + if (port == USBC_PORT_C1 && ignore_c1_dp) + return; + cprints(CC_USBPD, "Notifying AP of DP Alt Mode Entry..."); + mkbp_send_event(EC_MKBP_EVENT_DP_ALT_MODE_ENTERED); +} diff --git a/board/morphius/board.h b/board/morphius/board.h index 2375a186c0..ca3ecf4f03 100644 --- a/board/morphius/board.h +++ b/board/morphius/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,25 +10,32 @@ #define VARIANT_ZORK_TREMBYLE -#include #include "baseboard.h" +#include + #define CONFIG_USBC_RETIMER_PI3DPX1207 -#define CONFIG_MKBP_USE_GPIO #define CONFIG_8042_AUX #define CONFIG_PS2 #define CONFIG_CMD_PS2 #define CONFIG_KEYBOARD_FACTORY_TEST #define CONFIG_DEVICE_EVENT +#define CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT #undef CONFIG_LED_ONOFF_STATES -#define CONFIG_BATTERY_LEVEL_NEAR_FULL 91 +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 91 + +#undef ZORK_PS8818_RX_INPUT_TERM +#define ZORK_PS8818_RX_INPUT_TERM PS8818_RX_INPUT_TERM_85_OHM /* Motion sensing drivers */ +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCEL_KX022 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -36,46 +43,46 @@ #define CONFIG_TABLET_MODE #define CONFIG_TEMP_SENSOR #define CONFIG_TEMP_SENSOR_TMP432 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_PWR_A +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL #define CONFIG_GMR_TABLET_MODE #define CONFIG_GMR_TABLET_MODE_CUSTOM -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE +#define GPIO_TABLET_MODE_L GPIO_TABLET_MODE #define RPM_DEVIATION 1 /* GPIO mapping from board specific name to EC common name. */ -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL -#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL -#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL -#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L -#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK -#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L -#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL -#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD -#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD -#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_PWR_A +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE /* I2C mapping from board specific function*/ -#define I2C_PORT_THERMAL I2C_PORT_AP_HDMI +#define I2C_PORT_THERMAL I2C_PORT_AP_HDMI #ifndef __ASSEMBLER__ - void ps2_pwr_en_interrupt(enum gpio_signal signal); enum adc_channel { @@ -112,16 +119,11 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum usba_port { - USBA_PORT_A0 = 0, - USBA_PORT_A1, - USBA_PORT_COUNT -}; +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; /***************************************************************************** * CBI EC FW Configuration */ -#include "cbi_ec_fw_config.h" /** * MORPHIUS_MB_USBAC @@ -165,57 +167,52 @@ enum ec_cfg_usb_db_type { MORPHIUS_DB_T_OPT3_USBC_HDMI_MSTHUB = 1, }; +#include "cbi_ec_fw_config.h" -#define HAS_USBC1_RETIMER_PS8802 \ - (BIT(MORPHIUS_DB_T_OPT3_USBC_HDMI_MSTHUB)) +#define HAS_USBC1_RETIMER_PS8802 (BIT(MORPHIUS_DB_T_OPT3_USBC_HDMI_MSTHUB)) static inline bool ec_config_has_usbc1_retimer_ps8802(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8802); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_PS8802); } -#define HAS_USBC1_RETIMER_PS8818 \ - (BIT(MORPHIUS_DB_T_OPT1_USBC_HDMI)) +#define HAS_USBC1_RETIMER_PS8818 (BIT(MORPHIUS_DB_T_OPT1_USBC_HDMI)) static inline bool ec_config_has_usbc1_retimer_ps8818(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8818); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_PS8818); } -#define HAS_HDMI_RETIMER_PI3HDX1204 \ - (BIT(MORPHIUS_DB_T_OPT1_USBC_HDMI)) +#define HAS_HDMI_RETIMER_PI3HDX1204 (BIT(MORPHIUS_DB_T_OPT1_USBC_HDMI)) static inline bool ec_config_has_hdmi_retimer_pi3hdx1204(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_RETIMER_PI3HDX1204); + return !!(BIT(ec_config_get_usb_db()) & HAS_HDMI_RETIMER_PI3HDX1204); } -#define HAS_MST_HUB_RTD2141B \ - (BIT(MORPHIUS_DB_T_OPT3_USBC_HDMI_MSTHUB)) +#define HAS_MST_HUB_RTD2141B (BIT(MORPHIUS_DB_T_OPT3_USBC_HDMI_MSTHUB)) static inline bool ec_config_has_mst_hub_rtd2141b(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_MST_HUB_RTD2141B); + return !!(BIT(ec_config_get_usb_db()) & HAS_MST_HUB_RTD2141B); } -enum gpio_signal board_usbc_port_to_hpd_gpio(int port); -#define PORT_TO_HPD(port) board_usbc_port_to_hpd_gpio(port) +void motion_interrupt(enum gpio_signal signal); -extern const struct usb_mux usbc0_pi3dpx1207_usb_retimer; -extern const struct usb_mux usbc1_ps8802; +/** + * @warning Callers must use gpio_or_ioex_set_level to handle the return result + * since either type of signal can be returned. + * + * @return GPIO (gpio_signal) or IOEX (ioex_signal) + */ +int board_usbc_port_to_hpd_gpio_or_ioex(int port); +#define PORT_TO_HPD(port) board_usbc_port_to_hpd_gpio_or_ioex(port) + +extern const struct usb_mux_chain usbc0_pi3dpx1207_usb_retimer; extern const struct usb_mux usbc1_ps8818; +extern struct usb_mux usbc1_ps8802; extern struct usb_mux usbc1_amd_fp5_usb_mux; -#ifdef CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; -#endif - #endif /* !__ASSEMBLER__ */ - #endif /* __CROS_EC_BOARD_H */ diff --git a/board/morphius/build.mk b/board/morphius/build.mk index 4c2a6c5546..d6a15192ec 100644 --- a/board/morphius/build.mk +++ b/board/morphius/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/morphius/ec.tasklist b/board/morphius/ec.tasklist index 41b83cf4f3..4bb60ed55d 100644 --- a/board/morphius/ec.tasklist +++ b/board/morphius/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/morphius/gpio.inc b/board/morphius/gpio.inc index 5ec5875a3a..0597419c63 100644 --- a/board/morphius/gpio.inc +++ b/board/morphius/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -25,7 +25,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_inter GPIO_INT(EC_WP_L, PIN(5, 0), GPIO_INT_BOTH, switch_interrupt) GPIO_INT(VOLDN_BTN_ODL, PIN(A, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) GPIO_INT(VOLUP_BTN_ODL, PIN(9, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, bmi160_interrupt) +GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, motion_interrupt) GPIO_INT(EN_PWR_TOUCHPAD_PS2, PIN(C, 2), GPIO_INT_RISING, ps2_pwr_en_interrupt) GPIO_INT(DP1_HPD_EC_IN, PIN(7, 5), GPIO_INT_BOTH, hdmi_hpd_interrupt_v3) @@ -33,7 +33,7 @@ GPIO_INT(DP1_HPD_EC_IN, PIN(7, 5), GPIO_INT_BOTH, hdmi_hpd_interrupt_v3) GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) GPIO(3AXIS_INT_L, PIN(9, 6), GPIO_INPUT | GPIO_PULL_DOWN) /* 3 Axis Accel */ -GPIO(CCD_MODE_ODL, PIN(C, 6), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(CCD_MODE_ODL, PIN(C, 6), GPIO_ODR_HIGH) /* Case Closed Debug Mode */ GPIO(PROCHOT_ODL, PIN(D, 5), GPIO_ODR_HIGH) /* PROCHOT to SOC */ GPIO(EC_BATT_PRES_ODL, PIN(4, 1), GPIO_INPUT) /* Battery Present */ GPIO(EC_AP_INT_ODL, PIN(A, 3), GPIO_ODR_HIGH) /* Sensor MKBP event to SOC */ @@ -55,7 +55,7 @@ GPIO(DP2_HPD, PIN(C, 1), GPIO_OUT_LOW) /* C1 DP Hotplug Detect */ GPIO(EC_PS2_RESET_V0, PIN(3, 2), GPIO_OUT_LOW) /* Trackpoint reset pin V0*/ GPIO(EC_PS2_RESET_V1, PIN(4, 5), GPIO_OUT_LOW) /* Trackpoint reset pin V1 */ GPIO(EC_H1_PACKET_MODE, PIN(8, 6), GPIO_OUT_LOW) /* H1 Packet Mode */ -GPIO(FAN_ID, PIN(8, 2), GPIO_INPUT) /* Fan ID*/ +GPIO(FAN_ID, PIN(8, 2), GPIO_INPUT | GPIO_PULL_UP) /* Fan ID*/ GPIO(USB_C1_HPD_IN_DB_V1, PIN(B, 1), GPIO_OUT_LOW) /* C1 HPD V1 */ UNIMPLEMENTED(NO_HPD) diff --git a/board/morphius/led.c b/board/morphius/led.c index fc57b46d6b..55d29f1b2d 100644 --- a/board/morphius/led.c +++ b/board/morphius/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,8 +17,8 @@ #include "timer.h" #include "util.h" -#define LED_BAT_OFF_LVL 0 -#define LED_BAT_ON_LVL 1 +#define LED_BAT_OFF_LVL 0 +#define LED_BAT_ON_LVL 1 #define LED_BAT_S3_OFF_TIME_MS 3000 #define LED_BAT_S3_PWM_RESCALE 5 #define LED_BAT_S3_TICK_MS 50 @@ -34,10 +34,8 @@ static int ticks; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -45,21 +43,21 @@ enum led_color { LED_OFF = 0, LED_WHITE, LED_AMBER, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; /* PWM brightness vs. color, in the order of off, white */ static const uint8_t color_brightness[2] = { - [LED_OFF] = 0, - [LED_WHITE] = 100, + [LED_OFF] = 0, + [LED_WHITE] = 100, }; -void led_set_color_power(enum ec_led_colors color) +void led_set_color_power(enum led_color color) { pwm_set_duty(PWM_CH_POWER_LED, color_brightness[color]); } -void led_set_color_battery(enum ec_led_colors color) +void led_set_color_battery(enum led_color color) { uint32_t board_ver = 0; int led_batt_on_lvl, led_batt_off_lvl; @@ -111,10 +109,10 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) } else if (led_id == EC_LED_ID_POWER_LED) { if (brightness[EC_LED_COLOR_WHITE] != 0) pwm_set_duty(PWM_CH_POWER_LED, - color_brightness[LED_WHITE]); + color_brightness[LED_WHITE]); else pwm_set_duty(PWM_CH_POWER_LED, - color_brightness[LED_OFF]); + color_brightness[LED_OFF]); } return EC_SUCCESS; @@ -133,8 +131,8 @@ static void suspend_led_update_deferred(void) if (ticks <= TICKS_STEP2_DIMMER) { pwm_set_duty(PWM_CH_POWER_LED, ticks * LED_BAT_S3_PWM_RESCALE); } else if (ticks <= TICKS_STEP3_OFF) { - pwm_set_duty(PWM_CH_POWER_LED, - (TICKS_STEP3_OFF - ticks) * LED_BAT_S3_PWM_RESCALE); + pwm_set_duty(PWM_CH_POWER_LED, (TICKS_STEP3_OFF - ticks) * + LED_BAT_S3_PWM_RESCALE); } else { ticks = TICKS_STEP1_BRIGHTER; delay = LED_BAT_S3_OFF_TIME_MS * MSEC; @@ -161,27 +159,26 @@ DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, suspend_led_deinit, HOOK_PRIO_DEFAULT); static void led_set_battery(void) { static int battery_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate when charging, even in suspend. */ led_set_color_battery(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: led_set_color_battery(LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: led_set_color_battery(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - led_set_color_battery( - (battery_ticks & 0x4) ? LED_AMBER : LED_OFF); - else - led_set_color_battery(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + led_set_color_battery(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + led_set_color_battery((battery_ticks & 0x4) ? LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ @@ -204,9 +201,10 @@ static void led_set_power(void) power_ticks = 0; while (blink_ticks < LED_PWR_TICKS_PER_CYCLE) { - led_set_color_power( - (power_ticks % LED_TOTAL_TICKS) < LED_ON_TICKS ? - LED_WHITE : LED_OFF); + led_set_color_power((power_ticks % LED_TOTAL_TICKS) < + LED_ON_TICKS ? + LED_WHITE : + LED_OFF); previous_state_suspend = 1; return; diff --git a/board/morphius/thermal.c b/board/morphius/thermal.c index 019e377aca..2ffc2d105b 100644 --- a/board/morphius/thermal.c +++ b/board/morphius/thermal.c @@ -1,13 +1,15 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "chipset.h" #include "common.h" #include "console.h" #include "extpower.h" #include "fan.h" +#include "gpio.h" #include "hooks.h" #include "host_command.h" #include "lid_switch.h" @@ -19,7 +21,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_THERMAL, outstr) -#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) struct fan_step { /* @@ -43,316 +45,315 @@ static const struct fan_step *fan_step_table; static const struct fan_step fan1_table_clamshell[] = { { /* level 0 */ - .on = {-1, -1, -1, -1}, - .off = {-1, -1, -1, -1}, - .rpm = {0}, + .on = { -1, -1, -1, -1 }, + .off = { -1, -1, -1, -1 }, + .rpm = { 0 }, }, { /* level 1 */ - .on = {-1, -1, 40, -1}, - .off = {-1, -1, 31, -1}, - .rpm = {1900}, + .on = { -1, -1, 40, -1 }, + .off = { -1, -1, 31, -1 }, + .rpm = { 1900 }, }, { /* level 2 */ - .on = {-1, -1, 45, -1}, - .off = {-1, -1, 43, -1}, - .rpm = {2900}, + .on = { -1, -1, 45, -1 }, + .off = { -1, -1, 43, -1 }, + .rpm = { 2900 }, }, { /* level 3 */ - .on = {-1, -1, 48, -1}, - .off = {-1, -1, 46, -1}, - .rpm = {3200}, + .on = { -1, -1, 48, -1 }, + .off = { -1, -1, 46, -1 }, + .rpm = { 3200 }, }, { /* level 4 */ - .on = {-1, -1, 51, -1}, - .off = {-1, -1, 49, -1}, - .rpm = {3550}, + .on = { -1, -1, 51, -1 }, + .off = { -1, -1, 49, -1 }, + .rpm = { 3550 }, }, { /* level 5 */ - .on = {-1, -1, 54, -1}, - .off = {-1, -1, 52, -1}, - .rpm = {3950}, + .on = { -1, -1, 54, -1 }, + .off = { -1, -1, 52, -1 }, + .rpm = { 3950 }, }, { /* level 6 */ - .on = {-1, -1, 57, -1}, - .off = {-1, -1, 55, -1}, - .rpm = {4250}, + .on = { -1, -1, 57, -1 }, + .off = { -1, -1, 55, -1 }, + .rpm = { 4250 }, }, { /* level 7 */ - .on = {-1, -1, 60, -1}, - .off = {-1, -1, 58, -1}, - .rpm = {4650}, + .on = { -1, -1, 60, -1 }, + .off = { -1, -1, 58, -1 }, + .rpm = { 4650 }, }, }; static const struct fan_step fan1_table_tablet[] = { { /* level 0 */ - .on = {-1, -1, -1, -1}, - .off = {-1, -1, -1, -1}, - .rpm = {0}, + .on = { -1, -1, -1, -1 }, + .off = { -1, -1, -1, -1 }, + .rpm = { 0 }, }, { /* level 1 */ - .on = {-1, -1, 41, -1}, - .off = {-1, -1, 31, -1}, - .rpm = {2100}, + .on = { -1, -1, 41, -1 }, + .off = { -1, -1, 31, -1 }, + .rpm = { 2100 }, }, { /* level 2 */ - .on = {-1, -1, 50, -1}, - .off = {-1, -1, 48, -1}, - .rpm = {2600}, + .on = { -1, -1, 50, -1 }, + .off = { -1, -1, 48, -1 }, + .rpm = { 2600 }, }, { /* level 3 */ - .on = {-1, -1, 54, -1}, - .off = {-1, -1, 52, -1}, - .rpm = {2800}, + .on = { -1, -1, 54, -1 }, + .off = { -1, -1, 52, -1 }, + .rpm = { 2800 }, }, { /* level 4 */ - .on = {-1, -1, 57, -1}, - .off = {-1, -1, 55, -1}, - .rpm = {3300}, + .on = { -1, -1, 57, -1 }, + .off = { -1, -1, 55, -1 }, + .rpm = { 3300 }, }, { /* level 5 */ - .on = {-1, -1, 60, -1}, - .off = {-1, -1, 58, -1}, - .rpm = {3800}, + .on = { -1, -1, 60, -1 }, + .off = { -1, -1, 58, -1 }, + .rpm = { 3800 }, }, { /* level 6 */ - .on = {-1, -1, 72, -1}, - .off = {-1, -1, 69, -1}, - .rpm = {4000}, + .on = { -1, -1, 72, -1 }, + .off = { -1, -1, 69, -1 }, + .rpm = { 4000 }, }, { /* level 7 */ - .on = {-1, -1, 74, -1}, - .off = {-1, -1, 73, -1}, - .rpm = {4300}, + .on = { -1, -1, 74, -1 }, + .off = { -1, -1, 73, -1 }, + .rpm = { 4300 }, }, }; static const struct fan_step fan1_table_stand[] = { { /* level 0 */ - .on = {-1, -1, -1, -1}, - .off = {-1, -1, -1, -1}, - .rpm = {0}, + .on = { -1, -1, -1, -1 }, + .off = { -1, -1, -1, -1 }, + .rpm = { 0 }, }, { /* level 1 */ - .on = {-1, -1, 34, -1}, - .off = {-1, -1, 31, -1}, - .rpm = {1850}, + .on = { -1, -1, 34, -1 }, + .off = { -1, -1, 31, -1 }, + .rpm = { 1850 }, }, { /* level 2 */ - .on = {-1, -1, 42, -1}, - .off = {-1, -1, 39, -1}, - .rpm = {2550}, + .on = { -1, -1, 42, -1 }, + .off = { -1, -1, 39, -1 }, + .rpm = { 2550 }, }, { /* level 3 */ - .on = {-1, -1, 49, -1}, - .off = {-1, -1, 48, -1}, - .rpm = {2900}, + .on = { -1, -1, 49, -1 }, + .off = { -1, -1, 48, -1 }, + .rpm = { 2900 }, }, { /* level 4 */ - .on = {-1, -1, 51, -1}, - .off = {-1, -1, 50, -1}, - .rpm = {3350}, + .on = { -1, -1, 51, -1 }, + .off = { -1, -1, 50, -1 }, + .rpm = { 3350 }, }, { /* level 5 */ - .on = {-1, -1, 53, -1}, - .off = {-1, -1, 52, -1}, - .rpm = {3700}, + .on = { -1, -1, 53, -1 }, + .off = { -1, -1, 52, -1 }, + .rpm = { 3700 }, }, { /* level 6 */ - .on = {-1, -1, 55, -1}, - .off = {-1, -1, 54, -1}, - .rpm = {3900}, + .on = { -1, -1, 55, -1 }, + .off = { -1, -1, 54, -1 }, + .rpm = { 3900 }, }, { /* level 7 */ - .on = {-1, -1, 57, -1}, - .off = {-1, -1, 56, -1}, - .rpm = {4250}, + .on = { -1, -1, 57, -1 }, + .off = { -1, -1, 56, -1 }, + .rpm = { 4250 }, }, }; static const struct fan_step fan0_table_clamshell[] = { { /* level 0 */ - .on = {-1, -1, -1, -1}, - .off = {-1, -1, -1, -1}, - .rpm = {0}, + .on = { -1, -1, -1, -1 }, + .off = { -1, -1, -1, -1 }, + .rpm = { 0 }, }, { /* level 1 */ - .on = {-1, -1, 41, -1}, - .off = {-1, -1, 31, -1}, - .rpm = {2350}, + .on = { -1, -1, 41, -1 }, + .off = { -1, -1, 31, -1 }, + .rpm = { 2350 }, }, { /* level 2 */ - .on = {-1, -1, 44, -1}, - .off = {-1, -1, 42, -1}, - .rpm = {3300}, + .on = { -1, -1, 44, -1 }, + .off = { -1, -1, 42, -1 }, + .rpm = { 3300 }, }, { /* level 3 */ - .on = {-1, -1, 47, -1}, - .off = {-1, -1, 45, -1}, - .rpm = {3600}, + .on = { -1, -1, 47, -1 }, + .off = { -1, -1, 45, -1 }, + .rpm = { 3600 }, }, { /* level 4 */ - .on = {-1, -1, 50, -1}, - .off = {-1, -1, 48, -1}, - .rpm = {4050}, + .on = { -1, -1, 50, -1 }, + .off = { -1, -1, 48, -1 }, + .rpm = { 4050 }, }, { /* level 5 */ - .on = {-1, -1, 53, -1}, - .off = {-1, -1, 51, -1}, - .rpm = {4450}, + .on = { -1, -1, 53, -1 }, + .off = { -1, -1, 51, -1 }, + .rpm = { 4450 }, }, { /* level 6 */ - .on = {-1, -1, 56, -1}, - .off = {-1, -1, 54, -1}, - .rpm = {4750}, + .on = { -1, -1, 56, -1 }, + .off = { -1, -1, 54, -1 }, + .rpm = { 4750 }, }, { /* level 7 */ - .on = {-1, -1, 59, -1}, - .off = {-1, -1, 57, -1}, - .rpm = {5150}, + .on = { -1, -1, 59, -1 }, + .off = { -1, -1, 57, -1 }, + .rpm = { 5150 }, }, }; static const struct fan_step fan0_table_tablet[] = { { /* level 0 */ - .on = {-1, -1, -1, -1}, - .off = {-1, -1, -1, -1}, - .rpm = {0}, + .on = { -1, -1, -1, -1 }, + .off = { -1, -1, -1, -1 }, + .rpm = { 0 }, }, { /* level 1 */ - .on = {-1, -1, 41, -1}, - .off = {-1, -1, 31, -1}, - .rpm = {2250}, + .on = { -1, -1, 41, -1 }, + .off = { -1, -1, 31, -1 }, + .rpm = { 2250 }, }, { /* level 2 */ - .on = {-1, -1, 50, -1}, - .off = {-1, -1, 48, -1}, - .rpm = {2850}, + .on = { -1, -1, 50, -1 }, + .off = { -1, -1, 48, -1 }, + .rpm = { 2850 }, }, { /* level 3 */ - .on = {-1, -1, 54, -1}, - .off = {-1, -1, 51, -1}, - .rpm = {3100}, + .on = { -1, -1, 54, -1 }, + .off = { -1, -1, 51, -1 }, + .rpm = { 3100 }, }, { /* level 4 */ - .on = {-1, -1, 57, -1}, - .off = {-1, -1, 55, -1}, - .rpm = {3500}, + .on = { -1, -1, 57, -1 }, + .off = { -1, -1, 55, -1 }, + .rpm = { 3500 }, }, { /* level 5 */ - .on = {-1, -1, 60, -1}, - .off = {-1, -1, 58, -1}, - .rpm = {3900}, + .on = { -1, -1, 60, -1 }, + .off = { -1, -1, 58, -1 }, + .rpm = { 3900 }, }, { /* level 6 */ - .on = {-1, -1, 72, -1}, - .off = {-1, -1, 69, -1}, - .rpm = {4150}, + .on = { -1, -1, 72, -1 }, + .off = { -1, -1, 69, -1 }, + .rpm = { 4150 }, }, { /* level 7 */ - .on = {-1, -1, 74, -1}, - .off = {-1, -1, 73, -1}, - .rpm = {4400}, + .on = { -1, -1, 74, -1 }, + .off = { -1, -1, 73, -1 }, + .rpm = { 4400 }, }, }; static const struct fan_step fan0_table_stand[] = { { /* level 0 */ - .on = {-1, -1, -1, -1}, - .off = {-1, -1, -1, -1}, - .rpm = {0}, + .on = { -1, -1, -1, -1 }, + .off = { -1, -1, -1, -1 }, + .rpm = { 0 }, }, { /* level 1 */ - .on = {-1, -1, 34, -1}, - .off = {-1, -1, 31, -1}, - .rpm = {2250}, + .on = { -1, -1, 34, -1 }, + .off = { -1, -1, 31, -1 }, + .rpm = { 2250 }, }, { /* level 2 */ - .on = {-1, -1, 42, -1}, - .off = {-1, -1, 39, -1}, - .rpm = {2800}, + .on = { -1, -1, 42, -1 }, + .off = { -1, -1, 39, -1 }, + .rpm = { 2800 }, }, { /* level 3 */ - .on = {-1, -1, 49, -1}, - .off = {-1, -1, 48, -1}, - .rpm = {3150}, + .on = { -1, -1, 49, -1 }, + .off = { -1, -1, 48, -1 }, + .rpm = { 3150 }, }, { /* level 4 */ - .on = {-1, -1, 51, -1}, - .off = {-1, -1, 50, -1}, - .rpm = {3550}, + .on = { -1, -1, 51, -1 }, + .off = { -1, -1, 50, -1 }, + .rpm = { 3550 }, }, { /* level 5 */ - .on = {-1, -1, 53, -1}, - .off = {-1, -1, 52, -1}, - .rpm = {3900}, + .on = { -1, -1, 53, -1 }, + .off = { -1, -1, 52, -1 }, + .rpm = { 3900 }, }, { /* level 6 */ - .on = {-1, -1, 55, -1}, - .off = {-1, -1, 54, -1}, - .rpm = {4150}, + .on = { -1, -1, 55, -1 }, + .off = { -1, -1, 54, -1 }, + .rpm = { 4150 }, }, { /* level 7 */ - .on = {-1, -1, 57, -1}, - .off = {-1, -1, 56, -1}, - .rpm = {4400}, + .on = { -1, -1, 57, -1 }, + .off = { -1, -1, 56, -1 }, + .rpm = { 4400 }, }, }; #define NUM_FAN_LEVELS ARRAY_SIZE(fan1_table_clamshell) -#define lid_angle_tablet 340 +#define lid_angle_tablet 340 static int throttle_on; -BUILD_ASSERT(ARRAY_SIZE(fan1_table_clamshell) == - ARRAY_SIZE(fan1_table_tablet)); +BUILD_ASSERT(ARRAY_SIZE(fan1_table_clamshell) == ARRAY_SIZE(fan1_table_tablet)); #define average_time 60 int fan_table_to_rpm(int fan, int *temp) @@ -403,7 +404,7 @@ int fan_table_to_rpm(int fan, int *temp) for (j = 0; j < average_time; j++) avg_sum = avg_sum + avg_calc_tmp[TEMP_SENSOR_CPU][j]; - avg_tmp[TEMP_SENSOR_CPU] = avg_sum/average_time; + avg_tmp[TEMP_SENSOR_CPU] = avg_sum / average_time; /* * Compare the current and previous temperature, we have @@ -415,10 +416,10 @@ int fan_table_to_rpm(int fan, int *temp) if (avg_tmp[TEMP_SENSOR_CPU] < prev_tmp[TEMP_SENSOR_CPU]) { for (i = current_level; i >= 0; i--) { if (avg_tmp[TEMP_SENSOR_CPU] < - fan_step_table[i].off[TEMP_SENSOR_CPU]) { - /* - * fan step down debounce - */ + fan_step_table[i].off[TEMP_SENSOR_CPU]) { + /* + * fan step down debounce + */ if (fan_down_count < 10) { fan_down_count++; fan_up_count = 0; @@ -433,12 +434,12 @@ int fan_table_to_rpm(int fan, int *temp) break; } } else if (avg_tmp[TEMP_SENSOR_CPU] > prev_tmp[TEMP_SENSOR_CPU]) { - for (i = current_level+1; i < NUM_FAN_LEVELS; i++) { + for (i = current_level + 1; i < NUM_FAN_LEVELS; i++) { if ((avg_tmp[TEMP_SENSOR_CPU] > - fan_step_table[i].on[TEMP_SENSOR_CPU])) { - /* - * fan step up debounce - */ + fan_step_table[i].on[TEMP_SENSOR_CPU])) { + /* + * fan step up debounce + */ if (fan_up_count < 10) { fan_up_count++; fan_down_count = 0; @@ -495,21 +496,33 @@ void board_override_fan_control(int fan, int *tmp) void thermal_protect(void) { + int rv1, rv2; int thermal_sensor1, thermal_sensor2; - temp_sensor_read(TEMP_SENSOR_5V_REGULATOR, &thermal_sensor1); - temp_sensor_read(TEMP_SENSOR_CPU, &thermal_sensor2); - - if ((!lid_is_open()) && (!extpower_is_present())) { - if (thermal_sensor2 > C_TO_K(70)) { - chipset_throttle_cpu(1); - throttle_on = 1; - } else if (thermal_sensor2 < C_TO_K(60) && throttle_on) { - chipset_throttle_cpu(0); - throttle_on = 0; + rv1 = temp_sensor_read(TEMP_SENSOR_5V_REGULATOR, &thermal_sensor1); + rv2 = temp_sensor_read(TEMP_SENSOR_CPU, &thermal_sensor2); + + if (rv2 == EC_SUCCESS) { + if ((!lid_is_open()) && (!extpower_is_present())) { + if (thermal_sensor2 > C_TO_K(70)) { + chipset_throttle_cpu(1); + throttle_on = 1; + } else if (thermal_sensor2 < C_TO_K(60) && + throttle_on) { + chipset_throttle_cpu(0); + throttle_on = 0; + } + } else { + if (throttle_on == 1) { + chipset_throttle_cpu(0); + throttle_on = 0; + } } + } - if (thermal_sensor1 > C_TO_K(51)) + if (rv1 == EC_SUCCESS) { + if ((!lid_is_open()) && (!extpower_is_present()) && + thermal_sensor1 > C_TO_K(51)) chipset_force_shutdown(CHIPSET_SHUTDOWN_THERMAL); } } diff --git a/board/morphius/vif_override.xml b/board/morphius/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/morphius/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/mrbland/base_detect.c b/board/mrbland/base_detect.c new file mode 100644 index 0000000000..82326ab456 --- /dev/null +++ b/board/mrbland/base_detect.c @@ -0,0 +1,246 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Mrbland base detection code */ + +#include "adc.h" +#include "base_state.h" +#include "board.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "lid_switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +/* Make sure POGO VBUS starts later then PP3300_HUB when power on */ +#define BASE_DETECT_EN_LATER_US (600 * MSEC) + +/* Base detection and debouncing */ +#define BASE_DETECT_EN_DEBOUNCE_US (350 * MSEC) +#define BASE_DETECT_DIS_DEBOUNCE_US (20 * MSEC) + +/* + * If the base status is unclear (i.e. not within expected ranges, read + * the ADC value again every 500ms. + */ +#define BASE_DETECT_RETRY_US (500 * MSEC) + +/* + * Lid has 604K pull-up, base has 30.1K pull-down, so the + * ADC value should be around 30.1/(604+30.1)*3300 = 156 + * + * We add a significant margin on the maximum value, due to noise on the line, + * especially when PWM is active. See b/64193554 for details. + */ +#define BASE_DETECT_MIN_MV 120 +#define BASE_DETECT_MAX_MV 300 + +/* Minimum ADC value to indicate base is disconnected for sure */ +#define BASE_DETECT_DISCONNECT_MIN_MV 1500 + +/* + * Base EC pulses detection pin for 500 us to signal out of band USB wake (that + * can be used to wake system from deep S3). + */ +#define BASE_DETECT_PULSE_MIN_US 400 +#define BASE_DETECT_PULSE_MAX_US 650 + +static uint64_t base_detect_debounce_time; + +static void base_detect_deferred(void); +DECLARE_DEFERRED(base_detect_deferred); + +enum base_status { + BASE_UNKNOWN = 0, + BASE_DISCONNECTED = 1, + BASE_CONNECTED = 2, +}; + +static enum base_status current_base_status; +static bool current_base_enable_allow; + +/* + * This function is called whenever there is a change in the base detect + * status. Actions taken include: + * 1. Change in power to base after chipset startup, and disable the base + * power at chipset shutdown. + * 2. Indicate mode change to host. + * 3. Indicate tablet mode to host. Current assumption is that if base is + * disconnected then the system is in tablet mode, else if the base is + * connected, then the system is not in tablet mode. + * 4. Change lid dectect according to base status. + */ +static void base_detect_change(enum base_status status) +{ + int connected = (status == BASE_CONNECTED); + bool base_enable_allow = + !chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF); + + if ((current_base_status == status) && + (current_base_enable_allow == base_enable_allow)) + return; + + if (base_enable_allow) + gpio_set_level(GPIO_EN_BASE, connected); + else + gpio_set_level(GPIO_EN_BASE, 0); + + tablet_set_mode(!connected, TABLET_TRIGGER_BASE); + base_set_state(connected); + current_base_status = status; + current_base_enable_allow = base_enable_allow; + enable_lid_detect(connected); +} + +/* Measure detection pin pulse duration (used to wake AP from deep S3). */ +static uint64_t pulse_start; +static uint32_t pulse_width; + +static void print_base_detect_value(int v, int tmp_pulse_width) +{ + CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name, v, + tmp_pulse_width); +} + +static void base_detect_deferred(void) +{ + uint64_t time_now = get_time().val; + int v; + uint32_t tmp_pulse_width = pulse_width; + + if (base_detect_debounce_time > time_now) { + hook_call_deferred(&base_detect_deferred_data, + base_detect_debounce_time - time_now); + return; + } + + v = adc_read_channel(ADC_BASE_DET); + if (v == ADC_READ_ERROR) + return; + + print_base_detect_value(v, tmp_pulse_width); + + if (v >= BASE_DETECT_MIN_MV && v <= BASE_DETECT_MAX_MV) { + if ((current_base_status != BASE_CONNECTED) || + (current_base_enable_allow != true)) { + base_detect_change(BASE_CONNECTED); + } else if (tmp_pulse_width >= BASE_DETECT_PULSE_MIN_US && + tmp_pulse_width <= BASE_DETECT_PULSE_MAX_US) { + CPRINTS("Sending event to AP"); + host_set_single_event(EC_HOST_EVENT_KEY_PRESSED); + } + return; + } + + if (v >= BASE_DETECT_DISCONNECT_MIN_MV) { + base_detect_change(BASE_DISCONNECTED); + return; + } + + /* Unclear base status, schedule again in a while. */ + hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_RETRY_US); +} + +static inline int detect_pin_connected(enum gpio_signal det_pin) +{ + return gpio_get_level(det_pin) == 0; +} + +void base_detect_interrupt(enum gpio_signal signal) +{ + uint64_t time_now = get_time().val; + int debounce_us; + + if (detect_pin_connected(signal)) + debounce_us = BASE_DETECT_EN_DEBOUNCE_US; + else + debounce_us = BASE_DETECT_DIS_DEBOUNCE_US; + + if (base_detect_debounce_time <= time_now) { + /* + * Detect and measure detection pin pulse, when base is + * connected. Only a single pulse is measured over a debounce + * period. If no pulse, or multiple pulses are detected, + * pulse_width is set to 0. + */ + if (current_base_status == BASE_CONNECTED && + !detect_pin_connected(signal)) { + pulse_start = time_now; + } else { + pulse_start = 0; + } + pulse_width = 0; + + hook_call_deferred(&base_detect_deferred_data, debounce_us); + } else { + if (current_base_status == BASE_CONNECTED && + detect_pin_connected(signal) && !pulse_width && + pulse_start) { + /* First pulse within period. */ + pulse_width = time_now - pulse_start; + } else { + pulse_start = 0; + pulse_width = 0; + } + } + + base_detect_debounce_time = time_now + debounce_us; +} + +static void base_enable(void) +{ + /* Enable base detection interrupt. */ + base_detect_debounce_time = get_time().val; + hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_EN_LATER_US); + gpio_enable_interrupt(GPIO_BASE_DET_L); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, base_enable, HOOK_PRIO_DEFAULT); + +static void base_disable(void) +{ + /* + * Disable power to base and update the base dectect status, + * so the next startup will initialize a correct state + * and notify AP. + */ + base_detect_change(current_base_status); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, base_disable, HOOK_PRIO_DEFAULT); + +static void base_init(void) +{ + /* + * If we jumped to this image and chipset is already in S0, enable + * base. + */ + if (system_jumped_late() && chipset_in_state(CHIPSET_STATE_ON)) + base_enable(); +} +DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT + 1); + +void base_force_state(enum ec_set_base_state_cmd state) +{ + if (state == EC_SET_BASE_STATE_ATTACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_CONNECTED); + CPRINTS("BD forced connected"); + } else if (state == EC_SET_BASE_STATE_DETACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_DISCONNECTED); + CPRINTS("BD forced disconnected"); + } else { + base_enable(); + CPRINTS("BD forced reset"); + } +} diff --git a/board/mrbland/battery.c b/board/mrbland/battery.c new file mode 100644 index 0000000000..d6dda523be --- /dev/null +++ b/board/mrbland/battery.c @@ -0,0 +1,129 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all mrbland battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ + +const struct board_batt_params board_battery_info[] = { + /* Celxpert L21C2PG1 */ + [BATTERY_L21C2PG1] = { + .fuel_gauge = { + .manuf_name = "Celxpert", + .device_name = "LNV-5B11F38374", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7680, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 384, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, + /* Sunwoda L21D2PG1 */ + [BATTERY_L21D2PG1] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "LNV-5B11F38370", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7680, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 63, + .discharging_min_c = -20, + .discharging_max_c = 63, + .vendor_param_start = 0x70, + }, + }, + /* SMP L21M2PG1 */ + [BATTERY_L21M2PG1] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "LNV-5B11F38381", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7680, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 128, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_L21D2PG1; diff --git a/board/mrbland/board.c b/board/mrbland/board.c new file mode 100644 index 0000000000..c078d29ef7 --- /dev/null +++ b/board/mrbland/board.c @@ -0,0 +1,614 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Mrbland board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/ln9310.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_mkbp.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "peripheral_charger.h" +#include "pi3usb9201.h" +#include "power.h" +#include "power/qcom.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "queue.h" +#include "shi_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define KS_DEBOUNCE_US (30 * MSEC) /* Debounce time for kickstand switch */ + +/* Forward declaration */ +static void tcpc_alert_event(enum gpio_signal signal); +static void usb0_evt(enum gpio_signal signal); +static void ppc_interrupt(enum gpio_signal signal); +static void board_connect_c0_sbu(enum gpio_signal s); +static void switchcap_interrupt(enum gpio_signal signal); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* GPIO Interrupt Handlers */ +static void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +static void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + default: + break; + } +} + +static void board_connect_c0_sbu_deferred(void) +{ + /* + * If CCD_MODE_ODL asserts, it means there's a debug accessory connected + * and we should enable the SBU FETs. + */ + ppc_set_sbu(0, 1); +} +DECLARE_DEFERRED(board_connect_c0_sbu_deferred); + +static void board_connect_c0_sbu(enum gpio_signal s) +{ + hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); +} + +static void switchcap_interrupt(enum gpio_signal signal) +{ + ln9310_interrupt(signal); +} + +/* I2C port map */ +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* Measure VBUS through a 1/10 voltage divider */ + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + /* + * Adapter current output or battery charging/discharging current (uV) + * 18x amplification on charger side. + */ + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, + /* + * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read + * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and + * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we + * only divide by 2 (enough to avoid precision issues). + */ + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, + /* Base detection */ + [ADC_BASE_DET] = { "BASE_DET", NPCX_ADC_CH5, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct pwm_t pwm_channels[] = { + /* TODO(waihong): Assign a proper frequency. */ + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 4800 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* LN9310 switchcap */ +const struct ln9310_config_t ln9310_config = { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = LN9310_I2C_ADDR_0_FLAGS, +}; + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_EEPROM, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/* Mutexes */ +static struct mutex g_lid_mutex; + +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm42607_data; + +enum lid_accelgyro_type { + LID_GYRO_NONE = 0, + LID_GYRO_BMI160 = 1, + LID_GYRO_ICM42607 = 2, +}; + +static enum lid_accelgyro_type lid_accelgyro_config; + +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t lid_standard_ref_icm42607 = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t icm42607_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref_icm42607, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm42607_lid_gyro = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref_icm42607, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t motion_sensors[] = { + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [LID_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void board_detect_motionsensor(void) +{ + int val = -1; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + if (lid_accelgyro_config != LID_GYRO_NONE) + return; + + /* Check base accelgyro chip */ + icm_read8(&icm42607_lid_accel, ICM42607_REG_WHO_AM_I, &val); + if (val == ICM42607_CHIP_ICM42607P) { + motion_sensors[LID_ACCEL] = icm42607_lid_accel; + motion_sensors[LID_GYRO] = icm42607_lid_gyro; + lid_accelgyro_config = LID_GYRO_ICM42607; + CPRINTS("LID Accelgyro: ICM42607"); + } else { + lid_accelgyro_config = LID_GYRO_BMI160; + CPRINTS("LID Accelgyro: BMI160"); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_DEFAULT + 1); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (lid_accelgyro_config) { + case LID_GYRO_ICM42607: + icm42607_interrupt(signal); + break; + case LID_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +enum battery_cell_type board_get_battery_cell_type(void) +{ + return BATTERY_CELL_TYPE_2S; +} + +static void board_switchcap_init(void) +{ + CPRINTS("Use switchcap: LN9310"); + + /* Configure and enable interrupt for LN9310 */ + gpio_set_flags(GPIO_SWITCHCAP_PG_INT_L, GPIO_INT_FALLING); + gpio_enable_interrupt(GPIO_SWITCHCAP_PG_INT_L); + + /* Only configure the switchcap if not sysjump */ + if (!system_jumped_late()) + ln9310_init(); +} + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); + + /* + * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs + * for SBU may be disconnected after DP alt mode is off. Should enable + * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. + */ + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); + + /* Set the backlight duty cycle to 0. AP will override it later. */ + pwm_set_duty(PWM_CH_DISPLIGHT, 0); + + board_switchcap_init(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +__overridable uint16_t board_get_ps8xxx_product_id(int port) +{ + if (check_ps8755_chip(port)) + return PS8755_PRODUCT_ID; + + return PS8805_PRODUCT_ID; +} + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_hibernate(void) +{ + int i; + + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + + /* + * Board rev 1+ has the hardware fix. Don't need the following + * workaround. + */ + if (system_get_board_version() >= 1) + return; + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + ppc_vbus_sink_enable(i, 1); +} + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* + * Turn off display backlight in S3. AP has its own control. The EC's + * and the AP's will be AND'ed together in hardware. + */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); + pwm_enable(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Turn on display and keyboard backlight in S0. */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); + if (pwm_get_duty(PWM_CH_DISPLIGHT)) + pwm_enable(PWM_CH_DISPLIGHT, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON_L, !enable); + ln9310_software_enable(enable); +} + +int board_is_switchcap_enabled(void) +{ + return !gpio_get_level(GPIO_SWITCHCAP_ON_L); +} + +int board_is_switchcap_power_good(void) +{ + return ln9310_power_good(); +} + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} diff --git a/board/mrbland/board.h b/board/mrbland/board.h new file mode 100644 index 0000000000..25b1805e2a --- /dev/null +++ b/board/mrbland/board.h @@ -0,0 +1,112 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Mrbland board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +#define CONFIG_BUTTON_TRIGGERED_RECOVERY + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Switchcap */ +#define CONFIG_LN9310 + +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_VENDOR_PARAM + +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +/* Enable PD3.0 */ +#define CONFIG_USB_PD_REV30 + +/* BC 1.2 Charger */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* USB */ +#define CONFIG_USB_PD_TCPM_MULTI_PS8XXX +#define CONFIG_USB_PD_TCPM_PS8755 +#define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 + +/* I2C */ +#undef I2C_PORT_TCPC0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT2_0 + +/* Lid accel/gyro */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_FRONT_PROXIMITY_SWITCH + +#define CONFIG_DETACHABLE_BASE +#define CONFIG_BASE_ATTACHED_SWITCH + +/* GPIO alias */ +#define GPIO_AC_PRESENT GPIO_CHG_ACOK_OD +#define GPIO_WP_L GPIO_EC_FLASH_WP_ODL +#define GPIO_PMIC_RESIN_L GPIO_PM845_RESIN_L +#define GPIO_SWITCHCAP_PG_INT_L GPIO_LN9310_INT + +#define CONFIG_MKBP_INPUT_DEVICES + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_VBUS, + ADC_AMON_BMON, + ADC_PSYS, + ADC_BASE_DET, + ADC_CH_COUNT +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + LID_GYRO, + SENSOR_COUNT, +}; + +enum pwm_channel { PWM_CH_DISPLIGHT = 0, PWM_CH_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_L21C2PG1, + BATTERY_L21D2PG1, + BATTERY_L21M2PG1, + BATTERY_TYPE_COUNT, +}; + +/* Reset all TCPCs. */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); +/* Base detection */ +void base_detect_interrupt(enum gpio_signal signal); + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !defined(__ASSEMBLER__) */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/mrbland/build.mk b/board/mrbland/build.mk new file mode 100644 index 0000000000..363ef59a16 --- /dev/null +++ b/board/mrbland/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=trogdor + +board-y=battery.o board.o led.o base_detect.o usbc_config.o diff --git a/board/mrbland/ec.tasklist b/board/mrbland/ec.tasklist new file mode 100644 index 0000000000..fc40a8b684 --- /dev/null +++ b/board/mrbland/ec.tasklist @@ -0,0 +1,19 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/mrbland/gpio.inc b/board/mrbland/gpio.inc new file mode 100644 index 0000000000..b5ff32f0b8 --- /dev/null +++ b/board/mrbland/gpio.inc @@ -0,0 +1,195 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* USB-C interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ +GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ + +/* System interrupts */ +GPIO_INT(CHG_ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ +GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ +GPIO_INT(EC_FLASH_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ +GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ + +/* + * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down + * to make it low. Overload the interrupt function chipset_warm_reset_interrupt + * for not only signalling power_signal_interrupt but also handling the logic + * of WARM_RESET_L which is pulled-up by the same rail of POWER_GOOD. + */ +GPIO_INT(POWER_GOOD, PIN(5, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, chipset_power_good_interrupt) /* SRC_PP1800_S10A from PMIC */ +GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_warm_reset_interrupt) /* AP warm reset */ +GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ + +GPIO_INT(BASE_DET_L, PIN(3, 7), GPIO_INT_BOTH, base_detect_interrupt) /* Detachable base attached? */ + +/* Sensor interrupts */ +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, motion_interrupt) /* Accelerometer/gyro interrupt */ + +/* Switchcap, for LN9310, it is the interrupt line of LN9310. */ +GPIO_INT(LN9310_INT, PIN(E, 2), GPIO_INT_FALLING, switchcap_interrupt) + +/* + * EC_RST_ODL acts as a wake source from hibernate mode. However, it does not + * need to be an interrupt for normal EC operations. Simply set it an INPUT. + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ +GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ + +/* PMIC/AP 1.8V */ +GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ +GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ +GPIO(QSIP_ON, PIN(5, 0), GPIO_OUT_LOW) /* Not used, for non-switchcap testing */ + +/* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ +GPIO(SWITCHCAP_ON_L, PIN(D, 5), GPIO_ODR_HIGH) /* Enable switch cap */ +GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ +GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ +GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ + +/* Base detection */ +GPIO(EN_BASE, PIN(0, 4), GPIO_OUT_LOW) /* Enable power to detachable base */ + +/* POGO */ +GPIO(POGO_VBUS_PRESENT, PIN(6, 2), GPIO_INPUT) /* POGO PIN */ + +/* USB-C */ +GPIO(USB_C0_PD_RST_L, PIN(E, 4), GPIO_ODR_HIGH) /* Port-0 TCPC chip reset, actually Open-Drain */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ + +/* LEDs */ +GPIO(EC_CHG_LED_R_C0, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_G_C0, PIN(C, 4), GPIO_OUT_LOW) +GPIO(EC_PWRBTN_LED, PIN(7, 3), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + +/* PWM */ +GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ +GPIO(WCAM_EC_VSYNC, PIN(C, 0), GPIO_INPUT) /* PWM6 */ +GPIO(FCAM_EC_VSYNC, PIN(6, 0), GPIO_INPUT) /* PWM7 */ + +/* ADC */ +GPIO(PPVAR_BOOSTIN_SENSE, PIN(4, 4), GPIO_INPUT) /* ADC1 */ +GPIO(CHARGER_IADP, PIN(4, 3), GPIO_INPUT) /* ADC2 */ +GPIO(CHARGER_PMON, PIN(4, 2), GPIO_INPUT) /* ADC3 */ + +/* I2C */ +GPIO(EC_I2C_POWER_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Board/SKU IDs */ +GPIO(BRD_ID0, PIN(C, 7), GPIO_INPUT) +GPIO(BRD_ID1, PIN(9, 3), GPIO_INPUT) +GPIO(BRD_ID2, PIN(6, 3), GPIO_INPUT) +GPIO(SKU_ID0, PIN(F, 0), GPIO_INPUT) +GPIO(SKU_ID1, PIN(4, 1), GPIO_INPUT) +GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. Apply PU for power saving */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(3, 1)) +UNUSED(PIN(3, 0)) +UNUSED(PIN(2, 7)) +UNUSED(PIN(2, 6)) +UNUSED(PIN(2, 5)) +UNUSED(PIN(2, 4)) +UNUSED(PIN(2, 3)) +UNUSED(PIN(2, 2)) +UNUSED(PIN(2, 1)) +UNUSED(PIN(2, 0)) +UNUSED(PIN(1, 7)) +UNUSED(PIN(1, 6)) +UNUSED(PIN(1, 5)) +UNUSED(PIN(1, 4)) +UNUSED(PIN(1, 3)) +UNUSED(PIN(1, 2)) +UNUSED(PIN(1, 1)) +UNUSED(PIN(1, 0)) +UNUSED(PIN(0, 7)) +UNUSED(PIN(0, 6)) +UNUSED(PIN(0, 5)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(C, 6)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(5, 6)) +UNUSED(PIN(8, 0)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(D, 1)) +UNUSED(PIN(D, 3)) +UNUSED(PIN(7, 5)) +UNUSED(PIN(8, 6)) +UNUSED(PIN(7, 4)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(8, 5)) +UNUSED(PIN(E, 0)) +UNUSED(PIN(0, 3)) +UNUSED(PIN(6, 1)) +UNUSED(PIN(F, 1)) +UNUSED(PIN(9, 0)) +UNUSED(PIN(8, 7)) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ +ALTERNATE(PIN_MASK(9, 0x06), 1, MODULE_I2C, 0) /* I2C2 (GPIO91/92) */ +ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ +ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ +ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ +ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ +/* TODO(Camera?) should have a poper config for this, PWM or not */ +ALTERNATE(PIN_MASK(C, 0x01), 1, MODULE_PWM, 0) /* PWM6 (GPIOC0) - WCAM_EC_VSYNC */ +ALTERNATE(PIN_MASK(6, 0x01), 1, MODULE_PWM, 0) /* PWM7 (GPIO60) - FCAM_EC_VSYNC */ + + diff --git a/board/mrbland/led.c b/board/mrbland/led.c new file mode 100644 index 0000000000..3eb236e162 --- /dev/null +++ b/board/mrbland/led.c @@ -0,0 +1,219 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +/* Battery LED blinks every per 400ms */ +#define LED_HALF_ONE_SEC (500 / HOOK_TICK_INTERVAL_MS) + +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_GREEN, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color_battery(enum led_color color) +{ + gpio_set_level(GPIO_EC_CHG_LED_R_C0, + (color == LED_RED) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(GPIO_EC_CHG_LED_G_C0, + (color == LED_GREEN) ? BAT_LED_ON : BAT_LED_OFF); + if (color == LED_AMBER) { + gpio_set_level(GPIO_EC_CHG_LED_R_C0, BAT_LED_ON); + gpio_set_level(GPIO_EC_CHG_LED_G_C0, BAT_LED_ON); + } +} + +static void led_set_color_power(enum led_color color) +{ + gpio_set_level(GPIO_EC_PWRBTN_LED, + (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_battery(LED_RED); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(LED_GREEN); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LED_AMBER); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(LED_WHITE); + else + led_set_color_power(LED_OFF); + } + + return EC_SUCCESS; +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + int color = LED_OFF; + int period = 0; + int percent = DIV_ROUND_NEAREST(charge_get_display_charge(), 10); + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + case LED_PWRS_CHARGE_NEAR_FULL: + if (chipset_in_state(CHIPSET_STATE_ON | + CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_ANY_OFF)) { + if (percent <= BATTERY_LEVEL_CRITICAL) { + /* battery capa <= 5%, Red */ + color = LED_RED; + } else if (percent > BATTERY_LEVEL_CRITICAL && + percent < CONFIG_BATT_HOST_FULL_FACTOR) { + /* 5% < battery capa < 97%, Orange */ + color = LED_AMBER; + } else { + /* battery capa >= 97%, Green */ + color = LED_GREEN; + } + } + break; + case LED_PWRS_DISCHARGE: + color = LED_OFF; + break; + case LED_PWRS_ERROR: + /* Battery error, Red on 1sec off 1sec */ + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_OFF; + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_RED; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode, Red 2 sec, green 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_GREEN; + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + led_set_color_battery(color); +} + +static void board_led_set_power(void) +{ + static int power_ticks; + int color = LED_OFF; + int period = 0; + + power_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + case LED_PWRS_CHARGE_NEAR_FULL: + case LED_PWRS_DISCHARGE: + if (chipset_in_state(CHIPSET_STATE_ON)) { + /* S0, White (soild on) */ + color = LED_WHITE; + } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* S3, white (3s on 500ms off) */ + period = 1 * LED_HALF_ONE_SEC + 3 * LED_ONE_SEC; + power_ticks = power_ticks % period; + if (power_ticks < 3 * LED_ONE_SEC) + color = LED_WHITE; + else + color = LED_OFF; + } else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + /* S5, off */ + color = LED_OFF; + } + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + led_set_color_power(color); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + board_led_set_battery(); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + board_led_set_power(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_BATTERY_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_RED : LED_OFF; + + led_auto_control(EC_LED_ID_BATTERY_LED, 0); + + led_set_color_battery(color); +} diff --git a/board/mrbland/usbc_config.c b/board/mrbland/usbc_config.c new file mode 100644 index 0000000000..28f6b7a1c9 --- /dev/null +++ b/board/mrbland/usbc_config.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor family-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "console.h" +#include "usb_pd.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/mrbland/vif_override.xml b/board/mrbland/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/mrbland/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/munna/battery.c b/board/munna/battery.c new file mode 100644 index 0000000000..1f5be3dbe3 --- /dev/null +++ b/board/munna/battery.c @@ -0,0 +1,104 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "gpio.h" + +const struct board_batt_params board_battery_info[] = { + /* LGC L20L3PG2, Gauge IC: RAJ240047A20DNP. */ + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "LGC", + .device_name = "L20L3PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11400, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 73, + }, + }, + /* Sunwoda L20D3PG2, Gauge IC: BQ40Z697A. */ + [BATTERY_SUNWODA] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "L20D3PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + } + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11250, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* SIMPLO L20M3PG2, Gauge IC: BQ40Z697A. */ + [BATTERY_SMP] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L20M3PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + }, + }, + .batt_info = { + .voltage_max = 13050, /* mV */ + .voltage_normal = 11250, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -40, + .discharging_max_c = 73, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC; + +enum battery_present battery_hw_present(void) +{ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/munna/board.c b/board/munna/board.c new file mode 100644 index 0000000000..9830869476 --- /dev/null +++ b/board/munna/board.c @@ -0,0 +1,595 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "backlight.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/battery/max17055.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/fusb302.h" +#include "driver/usb_mux/it5205.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "i2c_bitbang.h" +#include "it8801.h" +#include "keyboard_backlight.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "panic.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "spi.h" +#include "system.h" +#include "task.h" +#include "tcpm/tcpm.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +static void tcpc_alert_event(enum gpio_signal signal) +{ + schedule_deferred_pd_interrupt(0 /* port */); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(5) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(15) }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 2, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct i2c_port_t i2c_bitbang_ports[] = { + { .name = "battery", + .port = 3, + .kbps = 100, + .scl = GPIO_I2C4_SCL, + .sda = GPIO_I2C4_SDA, + .drv = &bitbang_drv }, +}; +const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); + +#define BC12_I2C_ADDR PI3USB9201_I2C_ADDR_3 + +/* power signal list. Must match order of enum power_signal. */ +const struct power_signal_info power_signal_list[] = { + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, +}; +BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* + * TODO(b/133200075): Tune this once we have the final performance + * out of the driver and the i2c bus. + */ + .output_settle_us = 35, + .debounce_down_us = 5 * MSEC, + .debounce_up_us = 40 * MSEC, + .scan_period_us = 10 * MSEC, + .min_post_scan_delay_us = 10 * MSEC, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { + [0] = { + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, + .drv = &it8801_ioexpander_drv, + }, +}; + +/******************************************************************************/ +/* SPI devices */ +const struct spi_device_t spi_devices[] = { + { CONFIG_SPI_ACCEL_PORT, 2, GPIO_EC_SENSOR_SPI_NSS }, +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/******************************************************************************/ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, + }, + .drv = &fusb302_tcpm_drv, + }, +}; + +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) +{ + /* This driver does not use host command ACKs */ + *ack_required = false; + + /* + * svdm_dp_attention() did most of the work, we only need to notify + * host here. + */ + host_set_single_event(EC_HOST_EVENT_USB_MUX); +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, + }, +}; + +/* Charger config. Start i2c address at 1, update during runtime */ +struct charger_config_t chg_chips[] = { + { + .i2c_port = 2, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* Board version depends on ADCs, so init i2c port after ADC */ +static void charger_config_complete(void) +{ + chg_chips[0].i2c_port = board_get_charger_i2c(); +} +DECLARE_HOOK(HOOK_INIT, charger_config_complete, HOOK_PRIO_INIT_ADC + 1); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} + +static int force_discharge; + +int board_set_active_charge_port(int charge_port) +{ + CPRINTS("New chg p%d", charge_port); + + /* ignore all request when discharge mode is on */ + if (force_discharge && charge_port != CHARGE_PORT_NONE) + return EC_SUCCESS; + + switch (charge_port) { + case CHARGE_PORT_USB_C: + /* Don't charge from a source port */ + if (board_vbus_source_enabled(charge_port)) + return -1; + break; + default: + /* + * To ensure the fuel gauge (max17055) is always powered + * even when battery is disconnected, keep VBAT rail on but + * set the charging current to minimum. + */ + charger_set_current(CHARGER_SOLO, 0); + break; + } + + return EC_SUCCESS; +} + +int board_discharge_on_ac(int enable) +{ + int ret, port; + + if (enable) { + port = CHARGE_PORT_NONE; + } else { + /* restore the charge port state */ + port = charge_manager_get_override(); + if (port == OVERRIDE_OFF) + port = charge_manager_get_active_charge_port(); + } + + ret = charger_discharge_on_ac(enable); + if (ret) + return ret; + + force_discharge = enable; + return board_set_active_charge_port(port); +} + +int pd_snk_is_vbus_provided(int port) +{ + /* TODO(b:138352732): read IT8801 GPIO EN_USBC_CHARGE_L */ + return EC_ERROR_UNIMPLEMENTED; +} + +void bc12_interrupt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +#ifndef VARIANT_KUKUI_NO_SENSORS +static void board_spi_enable(void) +{ + /* + * Pin mux spi peripheral away from emmc, since RO might have + * left them there. + */ + gpio_config_module(MODULE_SPI_FLASH, 0); +#ifdef CHIP_FAMILY_STM32L4 + /* Set I/O speed before AF configured */ + /* EMMC SPI SLAVE: PB13/14/15 */ + /* SENSORS SPI controller: PB10, PB12, PC2, PC3 */ + STM32_GPIO_OSPEEDR(GPIO_B) |= 0xFF300000; + STM32_GPIO_OSPEEDR(GPIO_C) |= 0x000000F0; + + /* Enable clocks to SPI2 module. */ + STM32_RCC_APB1ENR1 |= STM32_RCC_PB1_SPI2; + + /* Reset SPI2 to clear state left over from the emmc slave. */ + STM32_RCC_APB1RSTR1 |= STM32_RCC_PB1_SPI2; + STM32_RCC_APB1RSTR1 &= ~STM32_RCC_PB1_SPI2; +#else + /* Enable clocks to SPI2 module. */ + STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; + + /* Reset SPI2 to clear state left over from the emmc slave. */ + STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; + STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; +#endif + /* Reinitialize spi peripheral. */ + spi_enable(&spi_devices[0], 1); + + /* Pin mux spi peripheral toward the sensor. */ + gpio_config_module(MODULE_SPI_CONTROLLER, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, + MOTION_SENSE_HOOK_PRIO - 1); + +static void board_spi_disable(void) +{ + /* Set pins to a state calming the sensor down. */ + gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); + gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); + + /* Disable spi peripheral and clocks. */ + spi_enable(&spi_devices[0], 0); +#ifdef CHIP_FAMILY_STM32L4 + STM32_RCC_APB1ENR1 &= ~STM32_RCC_PB1_SPI2; +#else + STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; +#endif +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, + MOTION_SENSE_HOOK_PRIO + 1); +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + +static void board_init(void) +{ + /* If the reset cause is external, pulse PMIC force reset. */ + if (system_get_reset_flags() == EC_RESET_FLAG_RESET_PIN) { + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 0); + msleep(100); + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 1); + } + + /* Enable TCPC alert interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + +#ifndef VARIANT_KUKUI_NO_SENSORS + /* Enable interrupts from BMI160 sensor. */ + gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); + + /* For some reason we have to do this again in case of sysjump */ + board_spi_enable(); +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + + /* Enable interrupt from PMIC. */ + gpio_enable_interrupt(GPIO_PMIC_EC_RESETB); + + /* Enable BC12 interrupt */ + gpio_enable_interrupt(GPIO_BC12_EC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +#ifndef VARIANT_KUKUI_NO_SENSORS +/* Motion sensors */ +/* Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Rotation matrixes */ +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* sensor private data */ +/* Lid accel private data */ +static struct stprivate_data g_lis2dwl_data; +/* Base accel private data */ +static struct bmi_drv_data_t g_bmi160_data; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DWL, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2dwl_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = CONFIG_SPI_ACCEL_PORT, + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +const struct it8801_pwm_t it8801_pwm_channels[] = { + [IT8801_PWM_CH_KBLIGHT] = { .index = 4 }, +}; + +void board_kblight_init(void) +{ + kblight_register(&kblight_it8801); +} + +bool board_has_kb_backlight(void) +{ + /* Default enable keyboard backlight */ + return true; +} +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + +/* Battery functions */ +#define SB_SMARTCHARGE 0x26 +/* Quick charge enable bit */ +#define SMART_QUICK_CHARGE 0x02 +/* Quick charge support bit */ +#define MODE_QUICK_CHARGE_SUPPORT 0x01 + +static void sb_quick_charge_mode(int enable) +{ + int val, rv; + + rv = sb_read(SB_SMARTCHARGE, &val); + if (rv || !(val & MODE_QUICK_CHARGE_SUPPORT)) + return; + + if (enable) + val |= SMART_QUICK_CHARGE; + else + val &= ~SMART_QUICK_CHARGE; + + sb_write(SB_SMARTCHARGE, val); +} + +/* Called on AP S0iX -> S0 transition */ +static void board_chipset_resume(void) +{ +#ifndef VARIANT_KUKUI_NO_SENSORS + if (board_has_kb_backlight()) + ioex_set_level(IOEX_KB_BL_EN, 1); +#endif + + /* Normal charge mode */ + sb_quick_charge_mode(0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S0iX transition */ +static void board_chipset_suspend(void) +{ +#ifndef VARIANT_KUKUI_NO_SENSORS + if (board_has_kb_backlight()) + ioex_set_level(IOEX_KB_BL_EN, 0); +#endif + + /* Quick charge mode */ + sb_quick_charge_mode(1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S5 -> S3 transition */ +static void board_chipset_startup(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S5 transition */ +static void board_chipset_shutdown(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); + +int board_get_charger_i2c(void) +{ + /* TODO(b:138415463): confirm the bus allocation for future builds */ + return I2C_PORT_CHARGER; +} + +int board_get_battery_i2c(void) +{ + return I2C_PORT_BATTERY; +} + +#ifdef SECTION_IS_RW +static int it8801_get_target_channel(enum pwm_channel *channel, int type, + int index) +{ + switch (type) { + case EC_PWM_TYPE_GENERIC: + *channel = index; + break; + default: + return -1; + } + + return *channel >= 1; +} + +static enum ec_status +host_command_pwm_set_duty(struct host_cmd_handler_args *args) +{ + const struct ec_params_pwm_set_duty *p = args->params; + enum pwm_channel channel; + uint16_t duty; + + if (it8801_get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + duty = (uint32_t)p->duty * 255 / 65535; + it8801_pwm_set_raw_duty(channel, duty); + it8801_pwm_enable(channel, p->duty > 0); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_DUTY, host_command_pwm_set_duty, + EC_VER_MASK(0)); + +static enum ec_status +host_command_pwm_get_duty(struct host_cmd_handler_args *args) +{ + const struct ec_params_pwm_get_duty *p = args->params; + struct ec_response_pwm_get_duty *r = args->response; + + enum pwm_channel channel; + + if (it8801_get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + r->duty = (uint32_t)it8801_pwm_get_raw_duty(channel) * 65535 / 255; + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_DUTY, host_command_pwm_get_duty, + EC_VER_MASK(0)); +#endif diff --git a/board/munna/board.h b/board/munna/board.h new file mode 100644 index 0000000000..286f80aa38 --- /dev/null +++ b/board/munna/board.h @@ -0,0 +1,190 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Configuration for Munna */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KUKUI_JACUZZI +#define VARIANT_KUKUI_BATTERY_SMART +#define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32L431 + +#ifndef SECTION_IS_RW +#define VARIANT_KUKUI_NO_SENSORS +#endif /* SECTION_IS_RW */ + +#include "baseboard.h" + +#undef CONFIG_CHIPSET_POWER_SEQ_VERSION +#define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 +#undef CONFIG_SYSTEM_UNLOCKED + +/* PLL configuration. Freq = STM32_HSE_CLOCK or HSI (16MHz) * n/m/r */ +#undef STM32_PLLM +#undef STM32_PLLN +#undef STM32_PLLR +#define STM32_PLLM 1 +#ifdef STM32_HSE_CLOCK +#define STM32_PLLN 12 +#else +#define STM32_PLLN 10 +#endif +#define STM32_PLLR 2 + +#define STM32_USE_PLL + +#define CONFIG_BATTERY_HW_PRESENT_CUSTOM + +#define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +#define CONFIG_CHARGER_RUNTIME_CONFIG + +#define CONFIG_BC12_DETECT_PI3USB9201 + +#define CONFIG_EXTPOWER_GPIO +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 200 + +#define CONFIG_I2C_BITBANG +#undef I2C_BITBANG_PORT_COUNT +#define I2C_BITBANG_PORT_COUNT 1 +#undef CONFIG_I2C_NACK_RETRY_COUNT +#define CONFIG_I2C_NACK_RETRY_COUNT 10 +#define CONFIG_SMBUS_PEC + +#define CONFIG_USB_PD_TCPM_FUSB302 +#define CONFIG_USB_PD_DISCHARGE_GPIO +#define CONFIG_USB_PD_TCPC_LOW_POWER + +#define CONFIG_USB_MUX_IT5205 + +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_POWER_LED + +#undef CONFIG_WATCHDOG_PERIOD_MS +#define CONFIG_WATCHDOG_PERIOD_MS 4000 + +/* Motion Sensors */ +#ifndef VARIANT_KUKUI_NO_SENSORS +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ALS +#define CONFIG_CMD_ACCEL_INFO + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#ifdef SECTION_IS_RW +#define CONFIG_IO_EXPANDER_IT8801_PWM +#define CONFIG_KEYBOARD_BACKLIGHT +#endif + +#endif /* VARIANT_KUKUI_NO_SENSORS */ + +/* I2C ports */ +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_CHARGER 2 +#define I2C_PORT_SENSORS 2 +#define I2C_PORT_KB_DISCRETE 2 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BATTERY 3 +#define I2C_PORT_TCPC0 0 + +#undef I2C_CONTROLLER_COUNT +#undef I2C_PORT_COUNT +#define I2C_CONTROLLER_COUNT 3 +#define I2C_PORT_COUNT 3 + +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 + +/* Enable Accel over SPI */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ + +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_USE_GPIO +/* Define the MKBP events which are allowed to wakeup AP in S3. */ +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +#undef CONFIG_GMR_TABLET_MODE +#undef GPIO_TABLET_MODE_L +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH + +#ifndef __ASSEMBLER__ + +enum adc_channel { + /* Real ADC channels begin here */ + ADC_BOARD_ID = 0, + ADC_EC_SKU_ID, + ADC_CH_COUNT +}; + +/* power signal definitions */ +enum power_signal { + AP_IN_S3_L, + PMIC_PWR_GOOD, + + /* Number of signals */ + POWER_SIGNAL_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum charge_port { + CHARGE_PORT_USB_C, +}; + +enum battery_type { + BATTERY_LGC, + BATTERY_SUNWODA, + BATTERY_SMP, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { + IT8801_PWM_CH_KBLIGHT = 0, +}; + +#include "gpio_signal.h" +#include "registers.h" + +#ifdef SECTION_IS_RO +/* Interrupt handler for emmc task */ +void emmc_cmd_interrupt(enum gpio_signal signal); +#endif + +void bc12_interrupt(enum gpio_signal signal); +void board_reset_pd_mcu(void); +int board_get_version(void); + +/* returns the i2c port number of charger/battery */ +int board_get_charger_i2c(void); +int board_get_battery_i2c(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/munna/build.mk b/board/munna/build.mk new file mode 100644 index 0000000000..aab7974af2 --- /dev/null +++ b/board/munna/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# +# +# STmicro STM32L431RCI +CHIP:=stm32 +CHIP_FAMILY:=stm32l4 +CHIP_VARIANT:=stm32l431x +BASEBOARD:=kukui + +board-y=battery.o board.o led.o diff --git a/board/munna/ec.tasklist b/board/munna/ec.tasklist new file mode 100644 index 0000000000..1e7e61108b --- /dev/null +++ b/board/munna/ec.tasklist @@ -0,0 +1,20 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, 1024) \ + TASK_ALWAYS_RO(EMMC, emmc_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/munna/gpio.inc b/board/munna/gpio.inc new file mode 100644 index 0000000000..72de7677dc --- /dev/null +++ b/board/munna/gpio.inc @@ -0,0 +1,120 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(B, 1), GPIO_INT_FALLING | GPIO_PULL_UP, + tcpc_alert_event) +GPIO_INT(POWER_BUTTON_L, PIN(A, 11), GPIO_INT_BOTH | GPIO_PULL_UP, + power_button_interrupt) /* EC_PWR_BTN_ODL */ +GPIO_INT(AP_IN_SLEEP_L, PIN(C, 12), GPIO_INT_BOTH | GPIO_PULL_DOWN, + power_signal_interrupt) +GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, + power_signal_interrupt) +GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, + chipset_reset_request_interrupt) +GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, + bmi160_interrupt) +GPIO_INT_RO(EMMC_CMD, PIN(B, 15), GPIO_INT_FALLING, + emmc_cmd_interrupt) +GPIO_INT(SPI1_NSS, PIN(A, 15), GPIO_INT_BOTH | GPIO_PULL_UP, + spi_event) /* SPI_AP_EC_CS_L */ +GPIO_INT(LID_OPEN, PIN(C, 5), GPIO_INT_BOTH, + lid_interrupt) +GPIO_INT(AC_PRESENT, PIN(A, 6), GPIO_INT_BOTH, + extpower_interrupt) /* ACOK_OD */ +GPIO_INT(BC12_EC_INT_ODL, PIN(C, 9), GPIO_INT_FALLING, + bc12_interrupt) +GPIO_INT(IT8801_SMB_INT, PIN(A, 8), GPIO_INT_FALLING | GPIO_PULL_UP, + io_expander_it8801_interrupt) /* KB_INT_ODL */ +GPIO_INT(AP_EC_WATCHDOG_L, PIN(D, 2), GPIO_INT_FALLING, + chipset_watchdog_interrupt) + +/* Unimplemented interrupts */ +GPIO(ALS_RGB_INT_ODL, PIN(C, 10), GPIO_INPUT) +GPIO(TABLET_MODE_L, PIN(B, 11), GPIO_INPUT) + +/* Reset pins */ +GPIO(AP_SYS_RST_L, PIN(C, 11), GPIO_OUT_LOW) +GPIO(PMIC_WATCHDOG_L, PIN(A, 2), GPIO_OUT_LOW) +GPIO(PMIC_EN_ODL, PIN(H, 0), GPIO_ODR_HIGH) + +/* + * I2C pins should be configured as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(I2C1_SCL, PIN(B, 8), GPIO_INPUT) +GPIO(I2C1_SDA, PIN(B, 9), GPIO_INPUT) +GPIO(I2C3_SCL, PIN(C, 0), GPIO_INPUT) +GPIO(I2C3_SDA, PIN(C, 1), GPIO_INPUT) +GPIO(I2C4_SCL, PIN(A, 5), GPIO_ODR_HIGH) +GPIO(I2C4_SDA, PIN(C, 4), GPIO_ODR_HIGH) + +/* Analog pins */ +GPIO(BOARD_ID, PIN(A, 0), GPIO_ANALOG) +GPIO(EC_SKU_ID, PIN(B, 0), GPIO_ANALOG) + +/* Other input pins */ +GPIO(WP_L, PIN(C, 8), GPIO_INPUT) /* EC_FLASH_WP_ODL */ +GPIO(BOOT0, PIN(H, 3), GPIO_INPUT) +GPIO(CCD_MODE_ODL, PIN(A, 1), GPIO_INPUT) + +/* Other output pins */ +GPIO(EC_BATT_PRES_ODL, PIN(A, 7), GPIO_INPUT) +GPIO(EC_BL_EN_OD, PIN(A, 13), GPIO_ODR_HIGH) +GPIO(EN_USBA_5V, PIN(C, 14), GPIO_OUT_LOW) +GPIO(EC_SENSOR_SPI_MISO, PIN(C, 2), GPIO_INPUT) +GPIO(EC_SENSOR_SPI_MOSI, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_SENSOR_SPI_NSS, PIN(B, 12), GPIO_OUT_HIGH) +GPIO(EC_SENSOR_SPI_CK, PIN(B, 10), GPIO_OUT_LOW) +GPIO(ENTERING_RW, PIN(C, 6), GPIO_ODR_HIGH) /* EC_ENTERING_RW_ODL */ +GPIO(EC_INT_L, PIN(C, 7), GPIO_ODR_HIGH) /* EC_AP_INT_ODL */ +GPIO(EC_BOARD_ID_EN_L, PIN(C, 15), GPIO_ODR_HIGH) /* EC_BOARD_ID_EN_ODL */ +GPIO(USB_C0_HPD_OD, PIN(H, 1), GPIO_ODR_LOW) +GPIO(BOOTBLOCK_EN_L, PIN(A, 12), GPIO_ODR_HIGH) +GPIO(EN_PP1800_S5_L, PIN(A, 14), GPIO_OUT_LOW) +GPIO(USB_C0_DISCHARGE, PIN(B, 6), GPIO_OUT_LOW) + +IOEX(PWR_LED_WHITE_L, EXPIN(0, 1, 4), GPIO_OUT_HIGH) +IOEX(BAT_LED_GREEN_FULL_L, EXPIN(0, 1, 3), GPIO_OUT_HIGH) +IOEX(BAT_LED_RED_L, EXPIN(0, 1, 2), GPIO_OUT_HIGH) +IOEX(KB_BL_EN, EXPIN(0, 0, 7), GPIO_OUT_LOW) + +/* + * TODO(b:138352732): On IT88801 expander, To be readded once IT8801 driver and + * gpio expander framework has landed. + */ +UNIMPLEMENTED(EN_PP5000_USBC) +UNIMPLEMENTED(PMIC_FORCE_RESET_ODL) +UNIMPLEMENTED(EN_USBC_CHARGE_L) + +/* USART1: PA9/PA10 */ +ALTERNATE(PIN_MASK(A, 0x0600), 7, MODULE_UART, 0) +/* I2C MASTER: PB8/9 */ +ALTERNATE(PIN_MASK(B, 0x0300), 4, MODULE_I2C, GPIO_ODR_HIGH ) +/* I2C MASTER: PC0/C1 */ +ALTERNATE(PIN_MASK(C, 0x0003), 4, MODULE_I2C, GPIO_ODR_HIGH ) + + +/* SPI1 */ +/* SPI SLAVE: PB3/4/5 */ +ALTERNATE(PIN_MASK(B, 0x0038), 5, MODULE_SPI, 0) +/* SPI SLAVE CS: PA15 */ +ALTERNATE(PIN_MASK(A, 0x8000), 5, MODULE_SPI, 0) + +/* SPI2 */ +/* Shared between slave for emmc and master for bmi160 */ +/* They're mutually exclusive with gpio_config_module. */ +/* EMMC SPI SLAVE: PB13/14/15 */ +ALTERNATE(PIN_MASK(B, 0xE000), 5, MODULE_SPI_FLASH, 0) +/* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 5, MODULE_SPI_CONTROLLER, 0) diff --git a/board/munna/led.c b/board/munna/led.c new file mode 100644 index 0000000000..e537863e80 --- /dev/null +++ b/board/munna/led.c @@ -0,0 +1,120 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Munna + */ +#include "common.h" +#include "driver/ioexpander/it8801.h" +#include "ec_commands.h" +#include "ioexpander.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_GREEN: + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_ON_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_ON_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_ON_LVL); + break; + case EC_LED_COLOR_RED: + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_OFF_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + ioex_set_level(IOEX_BAT_LED_GREEN_FULL_L, LED_OFF_LVL); + ioex_set_level(IOEX_BAT_LED_RED_L, LED_OFF_LVL); + break; + } +} + +__override void led_set_color_power(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + ioex_set_level(IOEX_PWR_LED_WHITE_L, LED_ON_LVL); + break; + default: + ioex_set_level(IOEX_PWR_LED_WHITE_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_RED] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_battery(EC_LED_COLOR_RED); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } else { + return EC_ERROR_INVAL; + } + return EC_SUCCESS; +} diff --git a/board/munna/vif_override.xml b/board/munna/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/munna/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/mushu/battery.c b/board/mushu/battery.c index 7e48dfdc19..d523d918f7 100644 --- a/board/mushu/battery.c +++ b/board/mushu/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/mushu/board.c b/board/mushu/board.c index dd407091c5..35c1972dce 100644 --- a/board/mushu/board.c +++ b/board/mushu/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Mushu board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" @@ -19,7 +18,6 @@ #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/temp_sensor/amd_r19me4070.h" -#include "driver/temp_sensor/f75303.h" #include "ec_commands.h" #include "extpower.h" #include "fan.h" @@ -37,16 +35,17 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/f75303.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* GPIO to enable/disable the USB Type-A port. */ const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { @@ -96,11 +95,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -108,22 +107,24 @@ static void bc12_interrupt(enum gpio_signal signal) } } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, - [PWM_CH_FAN] = {.channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, - [PWM_CH_FAN2] = {.channel = 6, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_FAN2] = { .channel = 6, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -143,22 +144,26 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -225,22 +230,18 @@ static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { }; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* * TODO(b/124337208): P0 boards don't have this sensor mounted so the rotation * matrix can't be tested properly. This needs to be revisited after EVT to make * sure the rotation matrix for the lid sensor is correct. */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -284,7 +285,7 @@ struct motion_sensor_t motion_sensors[] = { .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, - .default_range = 2, /* g, to support tablet mode */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ .config = { [SENSOR_CONFIG_EC_S0] = { .odr = 10000 | ROUND_UP_FLAG, @@ -364,14 +365,14 @@ BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; const struct fan_conf fan_conf_1 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_1, /* Use MFT id to control fan */ + .ch = MFT_CH_1, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -395,97 +396,93 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, - [MFT_CH_1] = {NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN2}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, + [MFT_CH_1] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN2 }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_5V", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_5V", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_CHARGER] = { - .name = "CHARGER", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1 - }, - [TEMP_5V] = { - .name = "5V", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2 - }, - [TEMP_GPU] = { - .name = "GPU", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_R19ME4070, - .idx = R19ME4070_LOCAL - }, - [TEMP_F75303_LOCAL] = { - .name = "F75303_Local", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = f75303_get_val, - .idx = F75303_IDX_LOCAL - }, - [TEMP_F75303_GPU] = { - .name = "F75303_GPU", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = f75303_get_val, - .idx = F75303_IDX_REMOTE1 - }, - [TEMP_F75303_GPU_POWER] = { - .name = "F75303_GPU_Power", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = f75303_get_val, - .idx = F75303_IDX_REMOTE2 - }, + [TEMP_CHARGER] = { .name = "CHARGER", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_5V] = { .name = "5V", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_GPU] = { .name = "GPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_R19ME4070, + .idx = R19ME4070_LOCAL }, + [TEMP_F75303_LOCAL] = { .name = "F75303_Local", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = f75303_get_val, + .idx = F75303_IDX_LOCAL }, + [TEMP_F75303_GPU] = { .name = "F75303_GPU", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = f75303_get_val, + .idx = F75303_IDX_REMOTE1 }, + [TEMP_F75303_GPU_POWER] = { .name = "F75303_GPU_Power", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = f75303_get_val, + .idx = F75303_IDX_REMOTE2 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - /* Hatch Temperature sensors */ /* * TODO(b/124316213): These setting need to be reviewed and set appropriately * for Hatch. They matter when the EC is controlling the fan as opposed to DPTF * control. */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(0), - .temp_fan_max = C_TO_K(70), -}; - -const static struct ec_thermal_config thermal_b = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(0), - .temp_fan_max = C_TO_K(70), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(0), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(0), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_b = THERMAL_B; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -527,7 +524,6 @@ static void board_gpio_set_pp5000(void) } else if (board_id >= 1) { reset_gpio_flags(GPIO_EN_PP5000_A_V1, GPIO_OUT_LOW); } - } static void board_init(void) diff --git a/board/mushu/board.h b/board/mushu/board.h index 40c4046350..c3cafaac93 100644 --- a/board/mushu/board.h +++ b/board/mushu/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,12 +11,31 @@ /* Baseboard features */ #include "baseboard.h" +/* Reduce flash usage */ +#undef CONFIG_ACCEL_SPOOF_MODE +#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CONSOLE_HISTORY +#define CONFIG_USB_PD_DEBUG_LEVEL 0 +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_ACCELS +#undef CONFIG_CMD_APTHROTTLE +#undef CONFIG_CMD_BATTFAKE +#undef CONFIG_CMD_CHARGE_SUPPLIER_INFO +#undef CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_CMD_HCDEBUG +#undef CONFIG_CMD_I2C_SCAN +#undef CONFIG_CMD_I2C_XFER +#undef CONFIG_CMD_PPC_DUMP +#undef CONFIG_CMD_SYSLOCK +#undef CONFIG_CMD_TIMERINFO + #define CONFIG_POWER_BUTTON #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI +#undef CONFIG_CMD_MFALLOW #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -24,10 +43,8 @@ /* Keyboard features */ #define CONFIG_PWM_KBLIGHT - /* Sensors */ /* BMI160 Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) @@ -45,7 +62,7 @@ #define CONFIG_ALS_TCS3400 #define CONFIG_ALS_TCS3400_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) -#define I2C_PORT_ALS I2C_PORT_SENSOR +#define I2C_PORT_ALS I2C_PORT_SENSOR #define CONFIG_TEMP_SENSOR /* AMD SMBUS Temp sensors */ #define CONFIG_TEMP_SENSOR_AMD_R19ME4070 @@ -56,7 +73,7 @@ #define I2C_PORT_THERMAL I2C_PORT_SENSOR /* GPU features */ -#define I2C_PORT_GPU NPCX_I2C_PORT4_1 +#define I2C_PORT_GPU NPCX_I2C_PORT4_1 /* USB Type C and USB PD defines */ #undef CONFIG_USB_PD_TCPMV1 @@ -65,6 +82,7 @@ * parade PS8751 TCPC */ #define CONFIG_USB_PD_TCPMV2 +#undef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT #define CONFIG_USB_PID 0x5047 #define CONFIG_USB_PD_DECODE_SOP #define CONFIG_USB_PD_TRY_SRC @@ -111,7 +129,7 @@ #define CONFIG_CUSTOM_FAN_CONTROL #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 50 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -130,15 +148,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -150,8 +169,8 @@ extern enum gpio_signal gpio_en_pp5000_a; enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ ADC_CH_COUNT }; @@ -164,12 +183,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_FAN2, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_FAN2, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, @@ -202,15 +216,14 @@ enum battery_type { BATTERY_TYPE_COUNT, }; - #undef PD_OPERATING_POWER_MW -#define PD_OPERATING_POWER_MW 15000 +#define PD_OPERATING_POWER_MW 15000 #undef PD_MAX_POWER_MW -#define PD_MAX_POWER_MW 100000 +#define PD_MAX_POWER_MW 100000 #undef PD_MAX_CURRENT_MA -#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_CURRENT_MA 5000 #undef PD_MAX_VOLTAGE_MV -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_VOLTAGE_MV 20000 #endif /* !__ASSEMBLER__ */ diff --git a/board/mushu/build.mk b/board/mushu/build.mk index 2d6118ea70..4e42a0616e 100644 --- a/board/mushu/build.mk +++ b/board/mushu/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/mushu/ec.tasklist b/board/mushu/ec.tasklist index 4a1024a091..829be2b7c8 100644 --- a/board/mushu/ec.tasklist +++ b/board/mushu/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/mushu/gpio.inc b/board/mushu/gpio.inc index cc8c7a0154..e1711a87e1 100644 --- a/board/mushu/gpio.inc +++ b/board/mushu/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,10 +16,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) diff --git a/board/mushu/led.c b/board/mushu/led.c index 4e0c721c1b..1ec2075586 100644 --- a/board/mushu/led.c +++ b/board/mushu/led.c @@ -1,43 +1,48 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Mushu */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -76,4 +81,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/mushu/thermal.c b/board/mushu/thermal.c index b61f36ab8a..da8f29de08 100644 --- a/board/mushu/thermal.c +++ b/board/mushu/thermal.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -23,8 +23,7 @@ void fan_set_percent(int fan, int pct) new_rpm = fan_percent_to_rpm(fan, pct); actual_rpm = fan_get_rpm_actual(FAN_CH(fan)); - if (new_rpm && - actual_rpm < min_rpm && + if (new_rpm && actual_rpm < min_rpm && new_rpm < fans[fan].rpm->rpm_start) new_rpm = fans[fan].rpm->rpm_start; diff --git a/board/mushu/vif_override.xml b/board/mushu/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/mushu/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/nami/battery.c b/board/nami/battery.c index 149272c8c1..18f03fc9de 100644 --- a/board/nami/battery.c +++ b/board/nami/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -16,8 +16,8 @@ #include "hooks.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) /* Default, Nami, Vayne */ static const struct battery_info info_0 = { @@ -243,8 +243,9 @@ static int battery_init(void) if (batt_status & STATUS_INITIALIZED) return 1; - return battery_status(&batt_status) ? 0 : - !!(batt_status & STATUS_INITIALIZED); + return battery_status(&batt_status) ? + 0 : + !!(batt_status & STATUS_INITIALIZED); } enum battery_disconnect_grace_period { @@ -278,13 +279,13 @@ static int battery_check_disconnect_ti_bq40z50(void) uint8_t data[6]; /* Check if battery charging + discharging is disabled. */ - rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); + rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, SB_ALT_MANUFACTURER_ACCESS, + data, sizeof(data)); if (rv) return BATTERY_DISCONNECT_ERROR; - if ((data[3] & (BATTERY_DISCHARGING_DISABLED | - BATTERY_CHARGING_DISABLED)) == + if ((data[3] & + (BATTERY_DISCHARGING_DISABLED | BATTERY_CHARGING_DISABLED)) == (BATTERY_DISCHARGING_DISABLED | BATTERY_CHARGING_DISABLED)) { if (oem != PROJECT_SONA) return BATTERY_DISCONNECTED; @@ -298,10 +299,10 @@ static int battery_check_disconnect_ti_bq40z50(void) * stop charging and avoid damaging the battery. */ if (disconnect_grace_period == - BATTERY_DISCONNECT_GRACE_PERIOD_OVER) + BATTERY_DISCONNECT_GRACE_PERIOD_OVER) return BATTERY_DISCONNECTED; if (disconnect_grace_period == - BATTERY_DISCONNECT_GRACE_PERIOD_OFF) + BATTERY_DISCONNECT_GRACE_PERIOD_OFF) hook_call_deferred(&battery_disconnect_timer_data, 5 * SECOND); ccprintf("Battery disconnect grace period\n"); diff --git a/board/nami/board.c b/board/nami/board.c index 3ffed42ae0..c90fdb66dc 100644 --- a/board/nami/board.c +++ b/board/nami/board.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,30 +6,31 @@ /* Poppy board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "anx7447.h" #include "battery.h" #include "board_config.h" #include "button.h" #include "charge_manager.h" -#include "charge_state.h" #include "charge_ramp.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" #include "console.h" #include "cros_board_info.h" -#include "driver/pmic_tps650x30.h" -#include "driver/accelgyro_bmi_common.h" #include "driver/accel_bma2x2.h" #include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi_common.h" #include "driver/baro_bmp280.h" #include "driver/charger/isl923x.h" #include "driver/led/lm3509.h" +#include "driver/pmic_tps650x30.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" -#include "driver/temp_sensor/f75303.h" +#include "espi.h" #include "extpower.h" +#include "fan.h" +#include "fan_chip.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -55,6 +56,7 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/f75303.h" #include "timer.h" #include "uart.h" #include "usb_charge.h" @@ -62,15 +64,12 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" -#include "espi.h" -#include "fan.h" -#include "fan_chip.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define USB_PD_PORT_PS8751 0 -#define USB_PD_PORT_ANX7447 1 +#define USB_PD_PORT_PS8751 0 +#define USB_PD_PORT_ANX7447 1 uint16_t board_version; uint8_t oem = PROJECT_NAMI; @@ -83,17 +82,16 @@ uint8_t model; * that we don't have pin 0. */ const int keyboard_factory_scan_pins[][2] = { - {-1, -1}, {0, 5}, {1, 1}, {1, 0}, {0, 6}, - {0, 7}, {-1, -1}, {-1, -1}, {1, 4}, {1, 3}, - {-1, -1}, {1, 6}, {1, 7}, {3, 1}, {2, 0}, - {1, 5}, {2, 6}, {2, 7}, {2, 1}, {2, 4}, - {2, 5}, {1, 2}, {2, 3}, {2, 2}, {3, 0}, - {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, - {-1, -1}, + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, + { -1, -1 }, }; const int keyboard_factory_scan_pins_used = - ARRAY_SIZE(keyboard_factory_scan_pins); + ARRAY_SIZE(keyboard_factory_scan_pins); static void tcpc_alert_event(enum gpio_signal signal) { @@ -139,26 +137,28 @@ void vbus1_evt(enum gpio_signal signal) void usb0_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } void usb1_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* ADC channels */ const struct adc_t adc_channels[] = { /* Vbus sensing (10x voltage divider). PPVAR_BOOSTIN_SENSE */ - [ADC_VBUS] = {"VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* * Adapter current output or battery charging/discharging current (uV) * 18x amplification on charger side. */ - [ADC_AMON_BMON] = {"AMON_BMON", NPCX_ADC_CH1, ADC_MAX_VOLT*1000/18, - ADC_READ_MAX+1, 0}, + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH1, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -167,7 +167,7 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = -1, }; @@ -213,18 +213,42 @@ struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* I2C port map */ -const struct i2c_port_t i2c_ports[] = { - {"tcpc0", NPCX_I2C_PORT0_0, 400, GPIO_I2C0_0_SCL, GPIO_I2C0_0_SDA}, - {"tcpc1", NPCX_I2C_PORT0_1, 400, GPIO_I2C0_1_SCL, GPIO_I2C0_1_SDA}, - {"battery", NPCX_I2C_PORT1, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"charger", NPCX_I2C_PORT2, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"pmic", NPCX_I2C_PORT2, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"accelgyro", NPCX_I2C_PORT3, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "tcpc0", + .port = NPCX_I2C_PORT0_0, + .kbps = 400, + .scl = GPIO_I2C0_0_SCL, + .sda = GPIO_I2C0_0_SDA }, + { .name = "tcpc1", + .port = NPCX_I2C_PORT0_1, + .kbps = 400, + .scl = GPIO_I2C0_1_SCL, + .sda = GPIO_I2C0_1_SDA }, + { .name = "battery", + .port = NPCX_I2C_PORT1, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "charger", + .port = NPCX_I2C_PORT2, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "pmic", + .port = NPCX_I2C_PORT2, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "accelgyro", + .port = NPCX_I2C_PORT3, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -234,7 +258,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = NPCX_I2C_PORT0_0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, /* Alert is active-low, push-pull */ @@ -259,16 +283,22 @@ static int ps8751_tune_mux(const struct usb_mux *me) return EC_SUCCESS; } -struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +struct usb_mux usb_mux_ps8751 = { + .usb_port = USB_PD_PORT_PS8751, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, +}; + +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_PS8751] = { - .usb_port = USB_PD_PORT_PS8751, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &usb_mux_ps8751, }, [USB_PD_PORT_ANX7447] = { - .usb_port = USB_PD_PORT_ANX7447, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_ANX7447, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, } }; @@ -298,7 +328,6 @@ void board_reset_pd_mcu(void) if (oem == PROJECT_AKALI && board_version < 0x0200) { if (anx7447_flash_erase(USB_PD_PORT_ANX7447)) CPRINTS("Failed to erase OCM flash"); - } /* Assert reset */ @@ -323,14 +352,15 @@ void board_tcpc_init(void) gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); if (oem == PROJECT_SONA && model != MODEL_SYNDRA) - usb_muxes[USB_PD_PORT_PS8751].board_init = ps8751_tune_mux; + usb_mux_ps8751.board_init = ps8751_tune_mux; /* * Initialize HPD to low; after sysjump SOC needs to see * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 2); @@ -355,150 +385,188 @@ uint16_t tcpc_get_alert_status(void) * F75303_Remote1 is near CPU, and F75303_Remote2 is near 5V power IC. */ const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT] = { - {"F75303_Local", TEMP_SENSOR_TYPE_BOARD, f75303_get_val, - F75303_IDX_LOCAL}, - {"F75303_Remote1", TEMP_SENSOR_TYPE_CPU, f75303_get_val, - F75303_IDX_REMOTE1}, - {"F75303_Remote2", TEMP_SENSOR_TYPE_BOARD, f75303_get_val, - F75303_IDX_REMOTE2}, + { "F75303_Local", TEMP_SENSOR_TYPE_BOARD, f75303_get_val, + F75303_IDX_LOCAL }, + { "F75303_Remote1", TEMP_SENSOR_TYPE_CPU, f75303_get_val, + F75303_IDX_REMOTE1 }, + { "F75303_Remote2", TEMP_SENSOR_TYPE_BOARD, f75303_get_val, + F75303_IDX_REMOTE2 }, }; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; /* Nami/Vayne Remote 1, 2 */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(39), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(39), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; /* Sona Remote 1 */ -const static struct ec_thermal_config thermal_b1 = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(82), - [EC_TEMP_THRESH_HALT] = C_TO_K(89), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(72), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(38), - .temp_fan_max = C_TO_K(58), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B1 \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(82), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(89), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(72), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(38), \ + .temp_fan_max = C_TO_K(58), \ + } +__maybe_unused static const struct ec_thermal_config thermal_b1 = THERMAL_B1; /* Sona Remote 2 */ -const static struct ec_thermal_config thermal_b2 = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(84), - [EC_TEMP_THRESH_HALT] = C_TO_K(91), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(74), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(60), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B2 \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(84), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(91), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(74), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(60), \ + } +__maybe_unused static const struct ec_thermal_config thermal_b2 = THERMAL_B2; /* Pantheon Remote 1 */ -const static struct ec_thermal_config thermal_c1 = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(66), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(56), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(38), - .temp_fan_max = C_TO_K(61), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_C1 \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(66), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(56), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(38), \ + .temp_fan_max = C_TO_K(61), \ + } +__maybe_unused static const struct ec_thermal_config thermal_c1 = THERMAL_C1; /* Pantheon Remote 2 */ -const static struct ec_thermal_config thermal_c2 = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(74), - [EC_TEMP_THRESH_HALT] = C_TO_K(82), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(64), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(38), - .temp_fan_max = C_TO_K(61), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_C2 \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(74), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(82), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(64), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(38), \ + .temp_fan_max = C_TO_K(61), \ + } +__maybe_unused static const struct ec_thermal_config thermal_c2 = THERMAL_C2; /* Akali Local */ -const static struct ec_thermal_config thermal_d0 = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = C_TO_K(79), - [EC_TEMP_THRESH_HIGH] = 0, - [EC_TEMP_THRESH_HALT] = C_TO_K(81), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = C_TO_K(80), - [EC_TEMP_THRESH_HIGH] = 0, - [EC_TEMP_THRESH_HALT] = C_TO_K(82), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(70), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_D0 \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(79), \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = C_TO_K(81), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(80), \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = C_TO_K(82), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_d0 = THERMAL_D0; /* Akali Remote 1 */ -const static struct ec_thermal_config thermal_d1 = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = C_TO_K(59), - [EC_TEMP_THRESH_HIGH] = 0, - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = C_TO_K(60), - [EC_TEMP_THRESH_HIGH] = 0, - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = 0, - .temp_fan_max = 0, -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_D1 \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(59), \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(60), \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_d1 = THERMAL_D1; /* Akali Remote 2 */ -const static struct ec_thermal_config thermal_d2 = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = C_TO_K(59), - [EC_TEMP_THRESH_HIGH] = 0, - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = C_TO_K(60), - [EC_TEMP_THRESH_HIGH] = 0, - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = 0, - .temp_fan_max = 0, -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_D2 \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(59), \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(60), \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_d2 = THERMAL_D2; #define I2C_PMIC_READ(reg, data) \ - i2c_read8(I2C_PORT_PMIC, TPS650X30_I2C_ADDR1_FLAGS,\ - (reg), (data)) + i2c_read8(I2C_PORT_PMIC, TPS650X30_I2C_ADDR1_FLAGS, (reg), (data)) #define I2C_PMIC_WRITE(reg, data) \ - i2c_write8(I2C_PORT_PMIC, TPS650X30_I2C_ADDR1_FLAGS,\ - (reg), (data)) + i2c_write8(I2C_PORT_PMIC, TPS650X30_I2C_ADDR1_FLAGS, (reg), (data)) static void board_pmic_init(void) { @@ -650,8 +718,8 @@ int board_set_active_charge_port(int charge_port) charge_port < CONFIG_USB_PD_PORT_MAX_COUNT); /* check if we are sourcing VBUS on the port */ /* dnojiri: revisit */ - int is_source = gpio_get_level(charge_port == 0 ? - GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN); + int is_source = gpio_get_level(charge_port == 0 ? GPIO_USB_C0_5V_EN : + GPIO_USB_C1_5V_EN); if (is_real_port && is_source) { CPRINTF("No charging on source port p%d is ", charge_port); @@ -669,17 +737,19 @@ int board_set_active_charge_port(int charge_port) /* dnojiri: revisit. there is always this assumption that * battery is present. If not, this may cause brownout. */ gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_L : - GPIO_USB_C1_CHARGE_L, 1); + GPIO_USB_C1_CHARGE_L, + 1); /* Enable charging port */ gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_L : - GPIO_USB_C0_CHARGE_L, 0); + GPIO_USB_C0_CHARGE_L, + 0); } return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* * Limit the input current to 96% negotiated limit, @@ -688,12 +758,10 @@ void board_set_charge_limit(int port, int supplier, int charge_ma, int factor = 96; if (oem == PROJECT_AKALI && - (model == MODEL_EKKO || model == MODEL_BARD)) + (model == MODEL_EKKO || model == MODEL_BARD)) factor = 95; charge_ma = charge_ma * factor / 100; - charge_set_input_current_limit( - MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } void board_hibernate(void) @@ -706,9 +774,9 @@ void board_hibernate(void) } const struct pwm_t pwm_channels[] = { - [PWM_CH_LED1] = { 3, PWM_CONFIG_DSLEEP, 1200 }, + [PWM_CH_LED1] = { 3, PWM_CONFIG_DSLEEP, 1200 }, [PWM_CH_LED2] = { 5, PWM_CONFIG_DSLEEP, 1200 }, - [PWM_CH_FAN] = {4, PWM_CONFIG_OPEN_DRAIN, 25000}, + [PWM_CH_FAN] = { 4, PWM_CONFIG_OPEN_DRAIN, 25000 }, /* * 1.2kHz is a multiple of both 50 and 60. So a video recorder * (generally designed to ignore either 50 or 60 Hz flicker) will not @@ -730,23 +798,17 @@ static struct kionix_accel_data g_kx022_data; static struct accelgyro_saved_data_t g_bma255_data; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t rotation_x180_z90 = { - { 0, FLOAT_TO_FP(-1), 0 }, - { FLOAT_TO_FP(-1), 0, 0 }, - { 0, 0, FLOAT_TO_FP(-1) } -}; +const mat33_fp_t rotation_x180_z90 = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; const struct motion_sensor_t lid_accel_1 = { .name = "Lid Accel", @@ -852,8 +914,7 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* If the lid is in 360 position, ignore the lid angle, * which might be faulty. Disable keyboard. @@ -862,7 +923,6 @@ void lid_angle_peripheral_enable(int enable) enable = 0; keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif /* Called on AP S3 -> S0 transition */ static void board_chipset_resume(void) @@ -963,7 +1023,7 @@ static void cbi_init(void) DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * F3 key scan cycle completed but scan input is not * charging to logic high when EC start scan next @@ -982,6 +1042,26 @@ struct keyboard_scan_config keyscan_config = { }, }; +static void anx7447_set_aux_switch(void) +{ + const int port = USB_PD_PORT_ANX7447; + + /* Debounce */ + if (gpio_get_level(GPIO_CCD_MODE_ODL)) + return; + + CPRINTS("C%d: AUX_SW_SEL=0x%x", port, 0xc); + if (tcpc_write(port, ANX7447_REG_TCPC_AUX_SWITCH, 0xc)) + CPRINTS("C%d: Setting AUX_SW_SEL failed", port); +} +DECLARE_DEFERRED(anx7447_set_aux_switch); + +void ccd_mode_isr(enum gpio_signal signal) +{ + /* Wait 2 seconds until all mux setting is done by PD task */ + hook_call_deferred(&anx7447_set_aux_switch_data, 2 * SECOND); +} + static void board_init(void) { int reg; @@ -1002,7 +1082,7 @@ static void board_init(void) ISL9238_REG_CONTROL3, ®) == EC_SUCCESS) { reg |= ISL9238_C3_BB_SWITCHING_PERIOD; if (i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - ISL9238_REG_CONTROL3, reg)) + ISL9238_REG_CONTROL3, reg)) CPRINTF("Failed to set isl9238\n"); } @@ -1014,6 +1094,10 @@ static void board_init(void) gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + /* Trigger once to set mux in case CCD cable is already connected. */ + ccd_mode_isr(GPIO_CCD_MODE_ODL); + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); + /* Enable Accel/Gyro interrupt for convertibles. */ if (sku & SKU_ID_MASK_CONVERTIBLE) gpio_enable_interrupt(GPIO_ACCELGYRO3_INT_L); @@ -1090,14 +1174,13 @@ void board_kblight_init(void) } } -enum critical_shutdown board_critical_shutdown_check( - struct charge_state_data *curr) +enum critical_shutdown +board_critical_shutdown_check(struct charge_state_data *curr) { if (oem == PROJECT_VAYNE) return CRITICAL_SHUTDOWN_CUTOFF; else return CRITICAL_SHUTDOWN_HIBERNATE; - } uint8_t board_set_battery_level_shutdown(void) diff --git a/board/nami/board.h b/board/nami/board.h index b12d8133bd..652db4826d 100644 --- a/board/nami/board.h +++ b/board/nami/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,7 +12,7 @@ * By default, enable all console messages except ACPI and host event because * the sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) /* EC */ #define CONFIG_ADC @@ -21,14 +21,14 @@ #define CONFIG_BOARD_VERSION_CBI #define CONFIG_BOARD_FORCE_RESET_PIN #define CONFIG_CRC8 -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_CASE_CLOSED_DEBUG_EXTERNAL #define CONFIG_DPTF -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_I2C_CONTROLLER + #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_KEYPAD @@ -38,7 +38,6 @@ #define CONFIG_LTO #define CONFIG_CHIP_PANIC_BACKUP #define CONFIG_PWM -#define CONFIG_SOFTWARE_PANIC #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25X40 #define CONFIG_VBOOT_HASH @@ -58,9 +57,6 @@ #define CONFIG_FAN_DYNAMIC #define CONFIG_THROTTLE_AP #define CONFIG_PWM_KBLIGHT -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY, \ - EC_CMD_MOTION_SENSE_CMD /* EC console commands */ #define CONFIG_CMD_ACCELS @@ -76,10 +72,11 @@ #define CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET #define CONFIG_CHIPSET_HAS_PRE_INIT_CALLBACK #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 #define CONFIG_HOSTCMD_FLASH_SPI_INFO +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD /* Battery */ #define CONFIG_BATTERY_CUT_OFF @@ -89,8 +86,8 @@ #define CONFIG_BATTERY_SMART #define CONFIG_PWR_STATE_DISCHARGE_FULL #define CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD -#undef CONFIG_BATT_HOST_FULL_FACTOR -#define CONFIG_BATT_HOST_FULL_FACTOR 100 +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 100 /* Charger */ #define CONFIG_CHARGE_MANAGER @@ -99,12 +96,10 @@ #define CONFIG_CHARGER #define CONFIG_CHARGER_ISL9238 #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 -/* EC's thresholds. 3%: boot, 2%: no boot. Required for soft sync. */ -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 3 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC 1 -#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 27000 -#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 27000 +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000 /* AP's thresholds. */ #define CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT 3 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 27000 @@ -115,11 +110,11 @@ #define CONFIG_CMD_CHARGER_ADC_AMON_BMON #define CONFIG_HOSTCMD_PD_CONTROL #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#undef CONFIG_EXTPOWER_DEBOUNCE_MS #define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 -#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT #define CONFIG_POWER_BUTTON_INIT_TIMEOUT 6 #define CONFIG_POWER_COMMON #define CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD 30 @@ -138,7 +133,6 @@ #define CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT #define CONFIG_ACCEL_BMA255 #define CONFIG_ACCEL_KX022 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL @@ -158,7 +152,6 @@ #define CONFIG_TABLET_MODE #define CONFIG_TABLET_MODE_SWITCH #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L /* USB */ #define CONFIG_USB_CHARGER @@ -187,41 +180,38 @@ #define CONFIG_USBC_VCONN_SWAP #define CONFIG_USB_MUX_RUNTIME_CONFIG - /* BC 1.2 charger */ #define CONFIG_BC12_DETECT_PI3USB9281 #define CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT 2 /* Optional feature to configure npcx chip */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ -#define NPCX_TACH_SEL2 1 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ +#define NPCX_TACH_SEL2 1 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ /* I2C ports */ -#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_1 -#define I2C_PORT_USB_CHARGER_0 NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_CHARGER_1 NPCX_I2C_PORT0_1 -#define I2C_PORT_EEPROM NPCX_I2C_PORT0_0 -#define I2C_PORT_BATTERY NPCX_I2C_PORT1 -#define I2C_PORT_CHARGER NPCX_I2C_PORT1 -#define I2C_PORT_PMIC NPCX_I2C_PORT2 -#define I2C_PORT_KBLIGHT NPCX_I2C_PORT2 -#define I2C_PORT_GYRO NPCX_I2C_PORT3 -#define I2C_PORT_ACCEL NPCX_I2C_PORT3 -#define I2C_PORT_THERMAL NPCX_I2C_PORT3 -#define I2C_PORT_ALS NPCX_I2C_PORT3 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_1 +#define I2C_PORT_USB_CHARGER_0 NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_CHARGER_1 NPCX_I2C_PORT0_1 +#define I2C_PORT_EEPROM NPCX_I2C_PORT0_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT1 +#define I2C_PORT_CHARGER NPCX_I2C_PORT1 +#define I2C_PORT_PMIC NPCX_I2C_PORT2 +#define I2C_PORT_KBLIGHT NPCX_I2C_PORT2 +#define I2C_PORT_GYRO NPCX_I2C_PORT3 +#define I2C_PORT_ACCEL NPCX_I2C_PORT3 +#define I2C_PORT_THERMAL NPCX_I2C_PORT3 +#define I2C_PORT_ALS NPCX_I2C_PORT3 /* I2C addresses */ -#define I2C_ADDR_MP2949_FLAGS 0x20 -#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_ADDR_MP2949_FLAGS 0x20 +#define I2C_ADDR_EEPROM_FLAGS 0x50 #ifndef __ASSEMBLER__ /* support factory keyboard test */ #define CONFIG_KEYBOARD_FACTORY_TEST -extern const int keyboard_factory_scan_pins[][2]; -extern const int keyboard_factory_scan_pins_used; #include "gpio_signal.h" #include "registers.h" @@ -293,27 +283,26 @@ enum model_id { MODEL_BARD = 2, }; -#define SKU_ID_MASK_KBLIGHT BIT(0) -#define SKU_ID_MASK_CONVERTIBLE BIT(9) -#define SKU_ID_MASK_KEYPAD BIT(15) -#define SKU_ID_MASK_UK2 BIT(18) +#define SKU_ID_MASK_KBLIGHT BIT(0) +#define SKU_ID_MASK_CONVERTIBLE BIT(9) +#define SKU_ID_MASK_KEYPAD BIT(15) +#define SKU_ID_MASK_UK2 BIT(18) /* TODO(crosbug.com/p/61098): Verify the numbers below. */ /* * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 70000 -#define PD_MAX_CURRENT_MA 3500 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 70000 +#define PD_MAX_CURRENT_MA 3500 +#define PD_MAX_VOLTAGE_MV 20000 /* Board specific handlers */ void board_reset_pd_mcu(void); @@ -329,7 +318,9 @@ extern uint32_t sku; extern uint8_t model; /* SKU_ID[24:31] are dedicated to OEM customization */ -#define CBI_SKU_CUSTOM_FIELD(val) ((val) >> 24) +#define CBI_SKU_CUSTOM_FIELD(val) ((val) >> 24) + +void ccd_mode_isr(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ diff --git a/board/nami/build.mk b/board/nami/build.mk index f4bf21113d..8f3a138f56 100644 --- a/board/nami/build.mk +++ b/board/nami/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/nami/ec.tasklist b/board/nami/ec.tasklist index 93fcda9f91..99d0f15b70 100644 --- a/board/nami/ec.tasklist +++ b/board/nami/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nami/gpio.inc b/board/nami/gpio.inc index 7bc922edaa..124af79f49 100644 --- a/board/nami/gpio.inc +++ b/board/nami/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -35,6 +35,7 @@ GPIO_INT(USB_C0_BC12_INT_L, PIN(D, 2), GPIO_INT_FALLING, usb0_evt) GPIO_INT(USB_C1_BC12_INT_L, PIN(D, 3), GPIO_INT_FALLING, usb1_evt) GPIO_INT(ACCELGYRO3_INT_L, PIN(3, 6), GPIO_INT_FALLING | GPIO_PULL_UP, bmi160_interrupt) GPIO_INT(TABLET_MODE_L, PIN(7, 2), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(CCD_MODE_ODL, PIN(6, 3), GPIO_INT_FALLING, ccd_mode_isr) GPIO(ENABLE_BACKLIGHT_L, PIN(6, 7), GPIO_OUT_LOW) /* LCD backlight */ GPIO(PP3300_DX_WLAN, PIN(B, 1), GPIO_OUT_LOW) /* Enable WLAN 3.3V Power */ @@ -47,7 +48,6 @@ GPIO(EC_PLATFORM_RST, PIN(4, 5), GPIO_OUT_LOW) /* EC Reset to LDO_EN */ GPIO(SYS_RESET_L, PIN(6, 1), GPIO_ODR_HIGH) /* Cold Reset to SOC */ GPIO(PMIC_SLP_SUS_L, PIN(8, 5), GPIO_OUT_LOW) /* SLP_SUS# to PMIC */ GPIO(BATTERY_PRESENT_L, PIN(3, 4), GPIO_INPUT) /* Battery Present */ -GPIO(CCD_MODE_ODL, PIN(6, 3), GPIO_INPUT) /* Case Closed Debug Mode */ GPIO(ENTERING_RW, PIN(7, 6), GPIO_OUTPUT) /* EC Entering RW */ GPIO(PMIC_INT_L, PIN(6, 0), GPIO_INPUT) /* PMIC interrupt */ #ifndef CONFIG_POWER_S0IX diff --git a/board/nami/led.c b/board/nami/led.c index 17af4d5f82..cf5c864045 100644 --- a/board/nami/led.c +++ b/board/nami/led.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -25,10 +25,10 @@ * connected to a regular GPIO pin. */ -#include "cros_board_info.h" #include "charge_state.h" #include "chipset.h" #include "console.h" +#include "cros_board_info.h" #include "ec_commands.h" #include "gpio.h" #include "hooks.h" @@ -38,8 +38,8 @@ #include "timer.h" #include "util.h" -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, EC_LED_ID_POWER_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); enum led_color { @@ -79,19 +79,19 @@ struct led_pattern { uint8_t pulse; }; -#define PULSE_NO 0 -#define PULSE(interval) (BIT(7) | (interval)) -#define BLINK(interval) (interval) -#define ALTERNATE(interval) (BIT(6) | (interval)) -#define IS_PULSING(pulse) ((pulse) & 0x80) -#define IS_ALTERNATE(pulse) ((pulse) & 0x40) -#define PULSE_INTERVAL(pulse) (((pulse) & 0x3f) * 100 * MSEC) +#define PULSE_NO 0 +#define PULSE(interval) (BIT(7) | (interval)) +#define BLINK(interval) (interval) +#define ALTERNATE(interval) (BIT(6) | (interval)) +#define IS_PULSING(pulse) ((pulse)&0x80) +#define IS_ALTERNATE(pulse) ((pulse)&0x40) +#define PULSE_INTERVAL(pulse) (((pulse)&0x3f) * 100 * MSEC) /* 40 msec for nice and smooth transition. */ -#define LED_PULSE_TICK_US (40 * MSEC) +#define LED_PULSE_TICK_US (40 * MSEC) typedef struct led_pattern led_patterns[LED_CHARGE_STATE_COUNT] - [LED_POWER_STATE_COUNT]; + [LED_POWER_STATE_COUNT]; /* * Nami/Vayne - One dual color LED: @@ -105,11 +105,17 @@ typedef struct led_pattern led_patterns[LED_CHARGE_STATE_COUNT] */ const static led_patterns battery_pattern_0 = { /* discharging: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE(10)}, {LED_OFF, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE(10) }, + { LED_OFF, PULSE_NO } }, /* charging: s0, s3, s5 */ - {{LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}}, + { { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO } }, /* full: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO } }, }; /* @@ -117,11 +123,15 @@ const static led_patterns battery_pattern_0 = { */ const static led_patterns battery_pattern_1 = { /* discharging: s0, s3, s5 */ - {{LED_OFF, PULSE_NO}, {LED_OFF, PULSE_NO}, {LED_OFF, PULSE_NO}}, + { { LED_OFF, PULSE_NO }, { LED_OFF, PULSE_NO }, { LED_OFF, PULSE_NO } }, /* charging: s0, s3, s5 */ - {{LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}}, + { { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO } }, /* full: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO } }, }; /* @@ -132,11 +142,15 @@ const static led_patterns battery_pattern_1 = { */ const static led_patterns battery_pattern_2 = { /* discharging: s0, s3, s5 */ - {{LED_OFF, PULSE_NO}, {LED_OFF, PULSE_NO}, {LED_OFF, PULSE_NO}}, + { { LED_OFF, PULSE_NO }, { LED_OFF, PULSE_NO }, { LED_OFF, PULSE_NO } }, /* charging: s0, s3, s5 */ - {{LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}}, + { { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO } }, /* full: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO } }, }; /* @@ -144,11 +158,17 @@ const static led_patterns battery_pattern_2 = { */ const static led_patterns power_pattern_1 = { /* discharging: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, BLINK(10)}, {LED_OFF, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, BLINK(10) }, + { LED_OFF, PULSE_NO } }, /* charging: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, BLINK(10)}, {LED_OFF, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, BLINK(10) }, + { LED_OFF, PULSE_NO } }, /* full: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, BLINK(10)}, {LED_OFF, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, BLINK(10) }, + { LED_OFF, PULSE_NO } }, }; /* @@ -159,11 +179,17 @@ const static led_patterns power_pattern_1 = { */ const static led_patterns power_pattern_2 = { /* discharging: s0, s3, s5 */ - {{LED_WHITE, 0}, {LED_WHITE, ALTERNATE(BLINK(10))}, {LED_OFF, 0}}, + { { LED_WHITE, 0 }, + { LED_WHITE, ALTERNATE(BLINK(10)) }, + { LED_OFF, 0 } }, /* charging: s0, s3, s5 */ - {{LED_WHITE, 0}, {LED_WHITE, ALTERNATE(BLINK(10))}, {LED_OFF, 0}}, + { { LED_WHITE, 0 }, + { LED_WHITE, ALTERNATE(BLINK(10)) }, + { LED_OFF, 0 } }, /* full: s0, s3, s5 */ - {{LED_WHITE, 0}, {LED_WHITE, ALTERNATE(BLINK(10))}, {LED_OFF, 0}}, + { { LED_WHITE, 0 }, + { LED_WHITE, ALTERNATE(BLINK(10)) }, + { LED_OFF, 0 } }, }; /* @@ -178,30 +204,42 @@ const static led_patterns power_pattern_2 = { */ const static led_patterns battery_pattern_3 = { /* discharging: s0, s3, s5 */ - {{LED_WHITE, 0}, {LED_AMBER, ALTERNATE(BLINK(10))}, {LED_OFF, 0}}, + { { LED_WHITE, 0 }, + { LED_AMBER, ALTERNATE(BLINK(10)) }, + { LED_OFF, 0 } }, /* charging: s0, s3, s5 */ - {{LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}}, + { { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO } }, /* full: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO } }, }; const static led_patterns battery_pattern_4 = { /* discharging: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, BLINK(10)}, {LED_OFF, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, BLINK(10) }, + { LED_OFF, PULSE_NO } }, /* charging: s0, s3, s5 */ - {{LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}, {LED_AMBER, PULSE_NO}}, + { { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO }, + { LED_AMBER, PULSE_NO } }, /* full: s0, s3, s5 */ - {{LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}, {LED_WHITE, PULSE_NO}}, + { { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO }, + { LED_WHITE, PULSE_NO } }, }; /* Patterns for battery LED and power LED. Initialized at run-time. */ static led_patterns const *patterns[2]; /* Pattern for battery error. Only blinking battery LED is supported. */ -static struct led_pattern battery_error = {LED_AMBER, BLINK(10)}; +static struct led_pattern battery_error = { LED_AMBER, BLINK(10) }; /* Pattern for low state of charge. Only battery LED is supported. */ -static struct led_pattern low_battery = {LED_WHITE, BLINK(10)}; +static struct led_pattern low_battery = { LED_WHITE, BLINK(10) }; /* Pattern for factory mode. Blinking 2-color battery LED. */ -static struct led_pattern battery_factory = {LED_FACTORY, BLINK(20)}; +static struct led_pattern battery_factory = { LED_FACTORY, BLINK(20) }; static int low_battery_soc; static void led_charge_hook(void); static enum led_power_state power_state; @@ -222,7 +260,7 @@ static void led_init(void) patterns[1] = &power_pattern_1; } battery_error.pulse = BLINK(5); - low_battery_soc = 100; /* 10.0% */ + low_battery_soc = 100; /* 10.0% */ break; case PROJECT_PANTHEON: patterns[0] = &battery_pattern_2; @@ -452,7 +490,7 @@ void config_led(enum ec_led_id id, enum led_charge_state charge) pattern = patterns[id]; if (!pattern) - return; /* This LED isn't present */ + return; /* This LED isn't present */ start_tick(id, &(*pattern)[charge][power_state]); } @@ -466,47 +504,48 @@ void config_leds(enum led_charge_state charge) static void call_handler(void) { int soc; - enum charge_state cs; + enum led_pwr_state cs; if (!led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) return; - cs = charge_get_state(); + cs = led_pwr_get_state(); soc = charge_get_display_charge(); if (soc < 0) - cs = PWR_STATE_ERROR; + cs = LED_PWRS_ERROR; switch (cs) { - case PWR_STATE_DISCHARGE: - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE: + case LED_PWRS_DISCHARGE_FULL: if (soc < low_battery_soc) start_tick(EC_LED_ID_BATTERY_LED, &low_battery); else config_led(EC_LED_ID_BATTERY_LED, LED_STATE_DISCHARGE); config_led(EC_LED_ID_POWER_LED, LED_STATE_DISCHARGE); break; - case PWR_STATE_CHARGE_NEAR_FULL: - case PWR_STATE_CHARGE: + case LED_PWRS_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE: if (soc >= 1000) config_leds(LED_STATE_FULL); else config_leds(LED_STATE_CHARGE); break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: /* It doesn't matter what 'charge' state we pass because power * LED (if it exists) is orthogonal to battery state. */ config_led(EC_LED_ID_POWER_LED, 0); led_alert(1); break; - case PWR_STATE_IDLE: - /* External power connected in IDLE. This is also used to show - * factory mode when 'ectool chargecontrol idle' is run during - * factory process. */ - if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE) - led_factory(1); + case LED_PWRS_IDLE: + /* External power connected in IDLE. */ break; - default: - ; + case LED_PWRS_FORCED_IDLE: + /* This is used to show factory mode when + * 'ectool chargecontrol idle' is run during factory process. + */ + led_factory(1); + break; + default:; } } @@ -548,7 +587,7 @@ static void print_config(enum ec_led_id id) ccprintf(" Interval:%d\n", tick[id].interval); } -static int command_led(int argc, char **argv) +static int command_led(int argc, const char **argv) { enum ec_led_id id = EC_LED_ID_BATTERY_LED; static int alert = 0; @@ -587,9 +626,10 @@ static int command_led(int argc, char **argv) } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(led, command_led, - "[debug|red|green|amber|off|alert|s0|s3|s5|conf|factory]", - "Turn on/off LED."); +DECLARE_CONSOLE_COMMAND( + led, command_led, + "[debug|red|green|amber|off|alert|s0|s3|s5|conf|factory]", + "Turn on/off LED."); void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) { diff --git a/board/nami/usb_pd_policy.c b/board/nami/usb_pd_policy.c index c1d5591d7c..e8111e7cbd 100644 --- a/board/nami/usb_pd_policy.c +++ b/board/nami/usb_pd_policy.c @@ -1,15 +1,15 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "chipset.h" #include "common.h" #include "console.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -17,17 +17,17 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { return vbus_en[port]; @@ -52,8 +52,7 @@ __override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) int pd_set_power_supply_ready(int port) { /* Disable charging */ - gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : - GPIO_USB_C0_CHARGE_L, 1); + gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : GPIO_USB_C0_CHARGE_L, 1); /* Ensure we advertise the proper available current quota */ charge_manager_source_port(port, 1); @@ -103,8 +102,7 @@ int pd_check_vconn_swap(int port) return gpio_get_level(GPIO_PMIC_SLP_SUS_L); } -__override void pd_execute_data_swap(int port, - enum pd_data_role data_role) +__override void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* Only port 0 supports device mode. */ if (port != 0) diff --git a/board/nami/vif_override.xml b/board/nami/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/nami/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/nautilus/battery.c b/board/nautilus/battery.c index 642497cdfe..8f0c4baa4e 100644 --- a/board/nautilus/battery.c +++ b/board/nautilus/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -17,22 +17,24 @@ static enum battery_present batt_pres_prev = BP_NOT_SURE; /* Shutdown mode parameters to write to manufacturer access register */ -#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS -#define SB_SHUTDOWN_DATA 0x0010 +#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS +#define SB_SHUTDOWN_DATA 0x0010 /* * Unlike other smart batteries, Nautilus battery uses different bit fields * in manufacturer access register for the conditions of the CHG/DSG FETs. */ -#define BATFETS_SHIFT (14) -#define BATFETS_MASK (0x3) -#define BATFETS_DISABLED (0x2) +#define BATFETS_SHIFT (14) +#define BATFETS_MASK (0x3) +#define BATFETS_DISABLED (0x2) -#define CHARGING_VOLTAGE_MV_SAFE 8400 -#define CHARGING_CURRENT_MA_SAFE 1500 +#define CHARGING_VOLTAGE_MV_SAFE 8400 +#define CHARGING_CURRENT_MA_SAFE 1500 +#define CHARGING_VOLTAGE_MV_ADJUST 8600 +#define CHARGING_CURRENT_MA_ADJUST 3200 static const struct battery_info info = { - .voltage_max = 8700, + .voltage_max = 8600, .voltage_normal = 7700, .voltage_min = 6000, /* Pre-charge values. */ @@ -88,7 +90,11 @@ int charger_profile_override(struct charge_state_data *curr) } temp_zone; current = curr->requested_current; + if (current > CHARGING_CURRENT_MA_ADJUST) + current = CHARGING_CURRENT_MA_ADJUST; voltage = curr->requested_voltage; + if (voltage > CHARGING_VOLTAGE_MV_ADJUST) + voltage = CHARGING_VOLTAGE_MV_ADJUST; bat_temp_c = curr->batt.temperature - 2731; /* @@ -160,8 +166,9 @@ static int battery_init(void) { int batt_status; - return battery_status(&batt_status) ? 0 : - !!(batt_status & STATUS_INITIALIZED); + return battery_status(&batt_status) ? + 0 : + !!(batt_status & STATUS_INITIALIZED); } /* @@ -185,8 +192,7 @@ static int battery_check_disconnect(void) if (rv) return BATTERY_DISCONNECT_ERROR; - if (((batt_mfgacc >> BATFETS_SHIFT) & BATFETS_MASK) == - BATFETS_DISABLED) + if (((batt_mfgacc >> BATFETS_SHIFT) & BATFETS_MASK) == BATFETS_DISABLED) return BATTERY_DISCONNECTED; return BATTERY_NOT_DISCONNECTED; @@ -221,4 +227,3 @@ enum battery_present battery_is_present(void) batt_pres_prev = batt_pres; return batt_pres; } - diff --git a/board/nautilus/board.c b/board/nautilus/board.c index e538010814..c3569ce56b 100644 --- a/board/nautilus/board.c +++ b/board/nautilus/board.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,25 +6,25 @@ /* Poppy board-specific configuration */ #include "adc.h" -#include "adc_chip.h" +#include "battery_smart.h" #include "bd99992gw.h" #include "board_config.h" -#include "battery_smart.h" #include "button.h" #include "charge_manager.h" -#include "charge_state.h" #include "charge_ramp.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" #include "console.h" -#include "driver/accelgyro_bmi_common.h" #include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" #include "driver/baro_bmp280.h" #include "driver/charger/isl923x.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" #include "driver/temp_sensor/bd99992gw.h" +#include "espi.h" #include "extpower.h" #include "gpio.h" #include "hooks.h" @@ -35,6 +35,7 @@ #include "math_util.h" #include "motion_lid.h" #include "motion_sense.h" +#include "panic.h" #include "pi3usb9281.h" #include "power.h" #include "power_button.h" @@ -51,10 +52,9 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" -#include "espi.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { @@ -76,9 +76,9 @@ static void vbus_discharge_handler(void) { if (system_get_board_version() >= 2) { pd_set_vbus_discharge(0, - gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L)); + gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L)); pd_set_vbus_discharge(1, - gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L)); + gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L)); } } DECLARE_DEFERRED(vbus_discharge_handler); @@ -103,14 +103,15 @@ void vbus1_evt(enum gpio_signal signal) void usb0_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } void usb1_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Hibernate wake configuration */ @@ -123,26 +124,47 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* ADC channels */ const struct adc_t adc_channels[] = { /* Base detection */ - [ADC_BASE_DET] = {"BASE_DET", NPCX_ADC_CH0, - ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_BASE_DET] = { "BASE_DET", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, /* Vbus sensing (10x voltage divider). */ - [ADC_VBUS] = {"VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* * Adapter current output or battery charging/discharging current (uV) * 18x amplification on charger side. */ - [ADC_AMON_BMON] = {"AMON_BMON", NPCX_ADC_CH1, ADC_MAX_VOLT*1000/18, - ADC_READ_MAX+1, 0}, + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH1, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* I2C port map */ -const struct i2c_port_t i2c_ports[] = { - {"tcpc0", NPCX_I2C_PORT0_0, 400, GPIO_I2C0_0_SCL, GPIO_I2C0_0_SDA}, - {"tcpc1", NPCX_I2C_PORT0_1, 400, GPIO_I2C0_1_SCL, GPIO_I2C0_1_SDA}, - {"charger", NPCX_I2C_PORT1, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"pmic", NPCX_I2C_PORT2, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"accelgyro", NPCX_I2C_PORT3, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "tcpc0", + .port = NPCX_I2C_PORT0_0, + .kbps = 400, + .scl = GPIO_I2C0_0_SCL, + .sda = GPIO_I2C0_0_SDA }, + { .name = "tcpc1", + .port = NPCX_I2C_PORT0_1, + .kbps = 400, + .scl = GPIO_I2C0_1_SCL, + .sda = GPIO_I2C0_1_SDA }, + { .name = "charger", + .port = NPCX_I2C_PORT1, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "pmic", + .port = NPCX_I2C_PORT2, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "accelgyro", + .port = NPCX_I2C_PORT3, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -152,7 +174,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = NPCX_I2C_PORT0_0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -160,22 +182,28 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = NPCX_I2C_PORT0_1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, { - .usb_port = 1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -193,7 +221,7 @@ BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) == CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT); const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { - GPIO_USB1_ENABLE, + GPIO_USB1_ENABLE, }; const struct charger_config_t chg_chips[] = { @@ -230,9 +258,10 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); uint16_t tcpc_get_alert_status(void) { @@ -252,13 +281,13 @@ uint16_t tcpc_get_alert_status(void) } const struct temp_sensor_t temp_sensors[] = { - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0}, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0 }, /* These BD99992GW temp sensors are only readable in S0 */ - {"Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM1}, - {"DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM2}, + { "Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM1 }, + { "DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM2 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -274,8 +303,8 @@ static void board_report_pmic_fault(const char *str) uint32_t info; /* RESETIRQ1 -- Bit 4: VRFAULT */ - if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) - != EC_SUCCESS) + if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) != + EC_SUCCESS) return; if (!(vrfault & BIT(4))) @@ -384,8 +413,7 @@ static void board_pmic_enable_slp_s0_vr_decay(void) i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x38, 0x7a); } -__override void power_board_handle_host_sleep_event( - enum host_sleep_event state) +__override void power_board_handle_host_sleep_event(enum host_sleep_event state) { if (state == HOST_SLEEP_EVENT_S0IX_SUSPEND) board_pmic_enable_slp_s0_vr_decay(); @@ -433,13 +461,13 @@ static void board_init(void) gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); /* Level of sensor's I2C and interrupt are 3.3V on proto board */ - if(system_get_board_version() < 2) { + if (system_get_board_version() < 2) { /* ACCELGYRO3_INT_L */ gpio_set_flags(GPIO_ACCELGYRO3_INT_L, GPIO_INT_FALLING); /* I2C3_SCL / I2C3_SDA */ gpio_set_flags(GPIO_I2C3_SCL, GPIO_INPUT); gpio_set_flags(GPIO_I2C3_SDA, GPIO_INPUT); - } + } /* Enable Gyro interrupts */ gpio_enable_interrupt(GPIO_ACCELGYRO3_INT_L); @@ -489,35 +517,17 @@ int board_set_active_charge_port(int charge_port) } else { /* Make sure non-charging port is disabled */ gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_L : - GPIO_USB_C1_CHARGE_L, 1); + GPIO_USB_C1_CHARGE_L, + 1); /* Enable charging port */ gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_L : - GPIO_USB_C0_CHARGE_L, 0); + GPIO_USB_C0_CHARGE_L, + 0); } return EC_SUCCESS; } -/** - * Set the charge limit based upon desired maximum. - * - * @param port Port number. - * @param supplier Charge supplier type. - * @param charge_ma Desired charge limit (mA). - * @param charge_mv Negotiated charge voltage (mV). - */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* - * Limit the input current to 96% negotiated limit, - * to account for the charger chip margin. - */ - charge_ma = charge_ma * 96 / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - /** * Return the maximum allowed input current */ @@ -541,7 +551,7 @@ void board_hibernate(void) CPRINTS("Triggering PMIC shutdown."); uart_flush_output(); - /* Trigger PMIC shutdown. */ + /* Trigger PMIC shutdown. */ if (i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x49, 0x01)) { /* * If we can't tell the PMIC to shutdown, instead reset @@ -595,17 +605,13 @@ static struct bmi_drv_data_t g_bmi160_data; static struct accelgyro_saved_data_t g_bma255_data; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0 }, - { 0, FLOAT_TO_FP(1), 0 }, - { 0, 0, FLOAT_TO_FP(-1) } -}; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0 }, - { 0, FLOAT_TO_FP(1), 0 }, - { 0, 0, FLOAT_TO_FP(-1) } -}; +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -681,8 +687,7 @@ struct motion_sensor_t motion_sensors[] = { const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* If the lid is in 360 position, ignore the lid angle, * which might be faulty. Disable keyboard. @@ -691,7 +696,6 @@ void lid_angle_peripheral_enable(int enable) enable = 0; keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif static void board_chipset_reset(void) { @@ -751,20 +755,19 @@ int board_has_working_reset_flags(void) * I2C callbacks to ensure bus free time for battery I2C transactions is at * least 5ms. */ -#define BATTERY_FREE_MIN_DELTA_US (5 * MSEC) +#define BATTERY_FREE_MIN_DELTA_US (5 * MSEC) static timestamp_t battery_last_i2c_time; -static int is_battery_i2c(const int port, const uint16_t slave_addr_flags) +static int is_battery_i2c(const int port, const uint16_t addr_flags) { - return (port == I2C_PORT_BATTERY) - && (slave_addr_flags == BATTERY_ADDR_FLAGS); + return (port == I2C_PORT_BATTERY) && (addr_flags == BATTERY_ADDR_FLAGS); } -void i2c_start_xfer_notify(const int port, const uint16_t slave_addr_flags) +void i2c_start_xfer_notify(const int port, const uint16_t addr_flags) { unsigned int time_delta_us; - if (!is_battery_i2c(port, slave_addr_flags)) + if (!is_battery_i2c(port, addr_flags)) return; time_delta_us = time_since32(battery_last_i2c_time); @@ -774,9 +777,9 @@ void i2c_start_xfer_notify(const int port, const uint16_t slave_addr_flags) usleep(BATTERY_FREE_MIN_DELTA_US - time_delta_us); } -void i2c_end_xfer_notify(const int port, const uint16_t slave_addr_flags) +void i2c_end_xfer_notify(const int port, const uint16_t addr_flags) { - if (!is_battery_i2c(port, slave_addr_flags)) + if (!is_battery_i2c(port, addr_flags)) return; battery_last_i2c_time = get_time(); diff --git a/board/nautilus/board.h b/board/nautilus/board.h index 958e3d202c..e3a136c261 100644 --- a/board/nautilus/board.h +++ b/board/nautilus/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,16 +17,15 @@ /* EC */ #define CONFIG_ADC #define CONFIG_BACKLIGHT_LID -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_BOARD_FORCE_RESET_PIN #define CONFIG_CASE_CLOSED_DEBUG_EXTERNAL #define CONFIG_DPTF #define CONFIG_DPTF_MOTION_LID_NO_GMR_SENSOR #define CONFIG_DPTF_MULTI_PROFILE -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_I2C_XFER_BOARD_CALLBACK #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PROTOCOL_8042 @@ -35,7 +34,6 @@ #define CONFIG_LOW_POWER_IDLE #define CONFIG_LTO #define CONFIG_CHIP_PANIC_BACKUP -#define CONFIG_SOFTWARE_PANIC #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25X40 #define CONFIG_VBOOT_HASH @@ -63,9 +61,10 @@ #define CONFIG_CHIPSET_SKYLAKE #define CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD /* Battery */ #define CONFIG_BATTERY_CUT_OFF @@ -80,17 +79,19 @@ #define CONFIG_CHARGER #define CONFIG_CHARGER_ISL9238 #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_PROFILE_OVERRIDE #define CONFIG_CHARGER_PSYS #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 /* margining */ #define CONFIG_CMD_CHARGER_ADC_AMON_BMON #define CONFIG_HOSTCMD_PD_CONTROL #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS -#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 #define CONFIG_POWER_COMMON @@ -117,7 +118,6 @@ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT #define CONFIG_ACCEL_BMA255 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL @@ -130,7 +130,7 @@ /* Depends on how fast the AP boots and typical ODRs */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) -#undef CONFIG_UART_TX_BUF_SIZE +#undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 2048 #define CONFIG_TABLET_MODE @@ -164,27 +164,27 @@ #define CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT 2 /* Optional feature to configure npcx chip */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 as TACH */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 as TACH */ /* I2C ports */ -#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_1 -#define I2C_PORT_USB_CHARGER_1 NPCX_I2C_PORT0_1 -#define I2C_PORT_USB_CHARGER_0 NPCX_I2C_PORT1 -#define I2C_PORT_CHARGER NPCX_I2C_PORT1 -#define I2C_PORT_BATTERY NPCX_I2C_PORT1 -#define I2C_PORT_PMIC NPCX_I2C_PORT2 -#define I2C_PORT_MP2949 NPCX_I2C_PORT2 -#define I2C_PORT_GYRO NPCX_I2C_PORT3 -#define I2C_PORT_BARO NPCX_I2C_PORT3 -#define I2C_PORT_ACCEL I2C_PORT_GYRO -#define I2C_PORT_THERMAL I2C_PORT_PMIC +#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_1 +#define I2C_PORT_USB_CHARGER_1 NPCX_I2C_PORT0_1 +#define I2C_PORT_USB_CHARGER_0 NPCX_I2C_PORT1 +#define I2C_PORT_CHARGER NPCX_I2C_PORT1 +#define I2C_PORT_BATTERY NPCX_I2C_PORT1 +#define I2C_PORT_PMIC NPCX_I2C_PORT2 +#define I2C_PORT_MP2949 NPCX_I2C_PORT2 +#define I2C_PORT_GYRO NPCX_I2C_PORT3 +#define I2C_PORT_BARO NPCX_I2C_PORT3 +#define I2C_PORT_ACCEL I2C_PORT_GYRO +#define I2C_PORT_THERMAL I2C_PORT_PMIC /* I2C addresses */ -#define I2C_ADDR_BD99992_FLAGS 0x30 -#define I2C_ADDR_MP2949_FLAGS 0x20 +#define I2C_ADDR_BD99992_FLAGS 0x30 +#define I2C_ADDR_MP2949_FLAGS 0x20 #ifndef __ASSEMBLER__ @@ -193,9 +193,9 @@ /* Nautilus doesn't have systherm0 and systherm3 */ enum temp_sensor_id { - TEMP_SENSOR_BATTERY, /* BD99956GW TSENSE */ - TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ - TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ + TEMP_SENSOR_BATTERY, /* BD99956GW TSENSE */ + TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ + TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ TEMP_SENSOR_COUNT }; @@ -213,29 +213,23 @@ enum sensor_id { SENSOR_COUNT, }; -enum adc_channel { - ADC_BASE_DET, - ADC_VBUS, - ADC_AMON_BMON, - ADC_CH_COUNT -}; +enum adc_channel { ADC_BASE_DET, ADC_VBUS, ADC_AMON_BMON, ADC_CH_COUNT }; /* TODO(crosbug.com/p/61098): Verify the numbers below. */ /* * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Board specific handlers */ int board_get_version(void); diff --git a/board/nautilus/build.mk b/board/nautilus/build.mk index f4bf21113d..8f3a138f56 100644 --- a/board/nautilus/build.mk +++ b/board/nautilus/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/nautilus/ec.tasklist b/board/nautilus/ec.tasklist index 8257734572..bcc5fc37e5 100644 --- a/board/nautilus/ec.tasklist +++ b/board/nautilus/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nautilus/gpio.inc b/board/nautilus/gpio.inc index 9cfc1e0bfd..13305d50fb 100644 --- a/board/nautilus/gpio.inc +++ b/board/nautilus/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,10 +14,10 @@ GPIO_INT(USB_C1_PD_INT_ODL, PIN(C, 5), GPIO_INT_FALLING, tcpc_alert_event) GPIO_INT(PCH_SLP_S0_L, PIN(7, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif /* Use VW signals instead of GPIOs */ -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(PCH_SLP_S3_L, PIN(7, 3), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(PCH_SLP_S4_L, PIN(8, 6), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PCH_SLP_SUS_L, PIN(6, 2), GPIO_INT_BOTH, power_signal_interrupt) diff --git a/board/nautilus/led.c b/board/nautilus/led.c index 86567701f0..96b9334a5c 100644 --- a/board/nautilus/led.c +++ b/board/nautilus/led.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -23,9 +23,8 @@ #define LED_TOTAL_TICKS 16 #define LED_ON_TICKS 8 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -67,12 +66,11 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - static void nautilus_led_set_power_battery(void) { static unsigned int power_ticks; enum led_color cur_led_color = LED_RED; - enum charge_state chg_state = charge_get_state(); + enum led_pwr_state chg_state = led_pwr_get_state(); int charge_percent = charge_get_percent(); if (chipset_in_state(CHIPSET_STATE_ON)) { @@ -82,34 +80,37 @@ static void nautilus_led_set_power_battery(void) /* Flash red on critical battery, which usually inhibits AP power-on. */ if (battery_is_present() != BP_YES || - charge_percent < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { - set_color(((power_ticks++ % LED_TOTAL_TICKS) < LED_ON_TICKS) ? - LED_RED : LED_OFF); + charge_percent < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + set_color(((power_ticks++ % LED_TOTAL_TICKS) < LED_ON_TICKS) ? + LED_RED : + LED_OFF); return; } /* CHIPSET_STATE_OFF */ switch (chg_state) { - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if ((charge_get_flags() & CHARGE_FLAG_EXTERNAL_POWER) && - charge_percent >= BATTERY_LEVEL_NEAR_FULL) + charge_percent >= CONFIG_BATT_HOST_FULL_FACTOR) cur_led_color = LED_GREEN; else cur_led_color = LED_OFF; break; - case PWR_STATE_CHARGE: + case LED_PWRS_CHARGE: cur_led_color = LED_RED; break; - case PWR_STATE_ERROR: - cur_led_color = ((power_ticks++ % LED_TOTAL_TICKS) - < LED_ON_TICKS) ? LED_RED : LED_GREEN; + case LED_PWRS_ERROR: + cur_led_color = + ((power_ticks++ % LED_TOTAL_TICKS) < LED_ON_TICKS) ? + LED_RED : + LED_GREEN; break; - case PWR_STATE_CHARGE_NEAR_FULL: - case PWR_STATE_IDLE: - if(charge_get_flags() & CHARGE_FLAG_EXTERNAL_POWER) - cur_led_color = LED_GREEN; - else - cur_led_color = LED_OFF; + case LED_PWRS_CHARGE_NEAR_FULL: + case LED_PWRS_IDLE: + cur_led_color = LED_OFF; + break; + case LED_PWRS_FORCED_IDLE: + cur_led_color = LED_GREEN; break; default: cur_led_color = LED_RED; @@ -118,7 +119,7 @@ static void nautilus_led_set_power_battery(void) set_color(cur_led_color); - if (chg_state != PWR_STATE_ERROR) + if (chg_state != LED_PWRS_ERROR) power_ticks = 0; } @@ -128,8 +129,8 @@ static void nautilus_led_set_power_battery(void) static void led_tick(void) { if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED) && - led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { - nautilus_led_set_power_battery(); + led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + nautilus_led_set_power_battery(); } } diff --git a/board/nautilus/usb_pd_policy.c b/board/nautilus/usb_pd_policy.c index be4716b860..050eae9a64 100644 --- a/board/nautilus/usb_pd_policy.c +++ b/board/nautilus/usb_pd_policy.c @@ -1,14 +1,14 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -16,17 +16,17 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { @@ -47,8 +47,8 @@ static void board_vbus_update_source_current(int port) * is controlled by GPIO_USB_C0/1_5V_EN. Both of these signals * can remain outputs. */ - gpio_set_level(gpio_3a_en, vbus_rp[port] == TYPEC_RP_3A0 ? - 1 : 0); + gpio_set_level(gpio_3a_en, + vbus_rp[port] == TYPEC_RP_3A0 ? 1 : 0); gpio_set_level(gpio_5v_en, vbus_en[port]); } else { /* @@ -60,8 +60,8 @@ static void board_vbus_update_source_current(int port) * 1505 mA. */ int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? - (GPIO_INPUT | GPIO_PULL_UP) : - (GPIO_OUTPUT | GPIO_PULL_UP); + (GPIO_INPUT | GPIO_PULL_UP) : + (GPIO_OUTPUT | GPIO_PULL_UP); gpio_set_level(gpio_5v_en, vbus_en[port]); gpio_set_flags(gpio_5v_en, flags); } @@ -78,8 +78,7 @@ __override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) int pd_set_power_supply_ready(int port) { /* Disable charging */ - gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : - GPIO_USB_C0_CHARGE_L, 1); + gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : GPIO_USB_C0_CHARGE_L, 1); /* Ensure we advertise the proper available current quota */ charge_manager_source_port(port, 1); @@ -124,22 +123,19 @@ int pd_snk_is_vbus_provided(int port) GPIO_USB_C0_VBUS_WAKE_L); } - int pd_check_vconn_swap(int port) { /* in G3, do not allow vconn swap since pp5000_A rail is off */ return gpio_get_level(GPIO_PMIC_SLP_SUS_L); } -__override void pd_execute_data_swap(int port, - enum pd_data_role data_role) +__override void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* Only port 0 supports device mode. */ if (port != 0) return; - gpio_set_level(GPIO_USB2_OTG_ID, - (data_role == PD_ROLE_UFP) ? 1 : 0); + gpio_set_level(GPIO_USB2_OTG_ID, (data_role == PD_ROLE_UFP) ? 1 : 0); gpio_set_level(GPIO_USB2_OTG_VBUSSENSE, - (data_role == PD_ROLE_UFP) ? 1 : 0); + (data_role == PD_ROLE_UFP) ? 1 : 0); } diff --git a/board/nautilus/vif_override.xml b/board/nautilus/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/nautilus/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/nightfury/battery.c b/board/nightfury/battery.c index a3b251229b..9e9b9baa74 100644 --- a/board/nightfury/battery.c +++ b/board/nightfury/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -111,10 +111,10 @@ enum battery_present variant_battery_present(void) int charger_profile_override(struct charge_state_data *curr) { - if(chipset_in_state(CHIPSET_STATE_ANY_OFF)) + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) return 0; - if(curr->requested_current > CHARGING_CURRENT_45C) + if (curr->requested_current > CHARGING_CURRENT_45C) curr->requested_current = CHARGING_CURRENT_45C; return 0; @@ -124,13 +124,13 @@ int charger_profile_override(struct charge_state_data *curr) #define PARAM_FASTCHARGE (CS_PARAM_CUSTOM_PROFILE_MIN + 0) enum ec_status charger_profile_override_get_param(uint32_t param, - uint32_t *value) + uint32_t *value) { - return EC_RES_INVALID_PARAM; + return EC_RES_INVALID_PARAM; } enum ec_status charger_profile_override_set_param(uint32_t param, - uint32_t value) + uint32_t value) { - return EC_RES_INVALID_PARAM; + return EC_RES_INVALID_PARAM; } diff --git a/board/nightfury/board.c b/board/nightfury/board.c index 0dcee3a1cf..bc1c26de12 100644 --- a/board/nightfury/board.c +++ b/board/nightfury/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Nightfury board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" @@ -14,8 +13,8 @@ #include "driver/accelgyro_bmi_common.h" #include "driver/als_opt3001.h" #include "driver/als_tcs3400.h" -#include "driver/ppc/sn5s330.h" #include "driver/bc12/pi3usb9201.h" +#include "driver/ppc/sn5s330.h" #include "driver/sync.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" @@ -26,6 +25,7 @@ #include "gpio.h" #include "hooks.h" #include "host_command.h" +#include "keyboard_scan.h" #include "lid_switch.h" #include "power.h" #include "power_button.h" @@ -36,16 +36,16 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void ppc_interrupt(enum gpio_signal signal) { @@ -85,11 +85,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -97,27 +97,21 @@ static void bc12_interrupt(enum gpio_signal signal) } } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { - .channel = 3, - .flags = 0, - .freq = 10000 - }, - [PWM_CH_FAN] = { - .channel = 5, - .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000 - }, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -128,7 +122,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -136,20 +130,24 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -186,22 +184,18 @@ static struct opt3001_drv_data_t g_opt3001_data = { static struct stprivate_data g_lis2ds_data; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* * TODO(b/124337208): P0 boards don't have this sensor mounted so the rotation * matrix can't be tested properly. This needs to be revisited after EVT to make * sure the rotation matrix for the lid sensor is correct. */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -304,6 +298,19 @@ const struct motion_sensor_t *motion_als_sensors[] = { }; BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); +__override struct keyboard_scan_config keyscan_config = { + .output_settle_us = 80, + .debounce_down_us = 30 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + /******************************************************************************/ /* Physical fans. These are logically separate from pwm_channels. */ @@ -328,63 +335,68 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /**********************************************************************/ /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_IA", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_3] = { - "TEMP_GT", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_IA", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_3] = { "TEMP_GT", NPCX_ADC_CH3, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "IA", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, - [TEMP_SENSOR_3] = {.name = "GT", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_3}, + [TEMP_SENSOR_1] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "IA", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "GT", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); /* Nightfury Temperature sensors */ /* * TODO(b/138578073): These setting need to be reviewed and set appropriately - * for Nightfury. They matter when the EC is controlling the fan as opposed to DPTF - * control. + * for Nightfury. They matter when the EC is controlling the fan as opposed to + * DPTF control. */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(90), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1] = thermal_a, - [TEMP_SENSOR_2] = thermal_a, - [TEMP_SENSOR_3] = thermal_a, + [TEMP_SENSOR_1] = THERMAL_A, + [TEMP_SENSOR_2] = THERMAL_A, + [TEMP_SENSOR_3] = THERMAL_A, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -424,5 +436,5 @@ bool board_is_convertible(void) { const uint8_t sku = get_board_sku(); - return (sku == 255) || (sku == 1); + return (sku == 255) || (sku == 1) || (sku == 2); } diff --git a/board/nightfury/board.h b/board/nightfury/board.h index 7f06cd2ae2..9831741d5a 100644 --- a/board/nightfury/board.h +++ b/board/nightfury/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,11 +16,11 @@ #define CONFIG_POWER_BUTTON #define CONFIG_KEYBOARD_PROTOCOL_8042 + #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE -#define CONFIG_LED_POWER_LED -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -30,7 +30,6 @@ /* Sensors */ /* BMI160 Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) @@ -46,7 +45,7 @@ /* BH1730 and TCS3400 ALS */ #define CONFIG_ALS #define ALS_COUNT 1 -#define I2C_PORT_ALS I2C_PORT_SENSOR +#define I2C_PORT_ALS I2C_PORT_SENSOR #define CONFIG_ALS_OPT3001 #define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS @@ -67,18 +66,18 @@ * Nightfury will not use both BH1730_LUXTH3_1K condition * and BH1730_LUXTH4_1K condition. */ -#define BH1730_LUXTH1_1K 270 -#define BH1730_LUXTH1_D0_1K 19200 -#define BH1730_LUXTH1_D1_1K 30528 -#define BH1730_LUXTH2_1K 655360000 -#define BH1730_LUXTH2_D0_1K 11008 -#define BH1730_LUXTH2_D1_1K 10752 -#define BH1730_LUXTH3_1K 1030 -#define BH1730_LUXTH3_D0_1K 11008 -#define BH1730_LUXTH3_D1_1K 10752 -#define BH1730_LUXTH4_1K 3670 -#define BH1730_LUXTH4_D0_1K 11008 -#define BH1730_LUXTH4_D1_1K 10752 +#define BH1730_LUXTH1_1K 270 +#define BH1730_LUXTH1_D0_1K 19200 +#define BH1730_LUXTH1_D1_1K 30528 +#define BH1730_LUXTH2_1K 655360000 +#define BH1730_LUXTH2_D0_1K 11008 +#define BH1730_LUXTH2_D1_1K 10752 +#define BH1730_LUXTH3_1K 1030 +#define BH1730_LUXTH3_D0_1K 11008 +#define BH1730_LUXTH3_D1_1K 10752 +#define BH1730_LUXTH4_1K 3670 +#define BH1730_LUXTH4_D0_1K 11008 +#define BH1730_LUXTH4_D1_1K 10752 /* USB Type C and USB PD defines */ #define CONFIG_USB_MUX_RUNTIME_CONFIG @@ -117,7 +116,7 @@ #define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL /* Thermal features */ -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -133,15 +132,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -152,9 +152,9 @@ extern enum gpio_signal gpio_en_pp5000_a; enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_TEMP_SENSOR_3, /* ADC3 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_3, /* ADC3 */ ADC_CH_COUNT }; @@ -166,11 +166,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, diff --git a/board/nightfury/build.mk b/board/nightfury/build.mk index e91262fd43..169668e64c 100644 --- a/board/nightfury/build.mk +++ b/board/nightfury/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/nightfury/ec.tasklist b/board/nightfury/ec.tasklist index 101713dc6e..507845b304 100644 --- a/board/nightfury/ec.tasklist +++ b/board/nightfury/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nightfury/gpio.inc b/board/nightfury/gpio.inc index 68d847fe92..710bf07c17 100644 --- a/board/nightfury/gpio.inc +++ b/board/nightfury/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,10 +16,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) diff --git a/board/nightfury/led.c b/board/nightfury/led.c index b20dbbd6f0..9d2c367ab5 100644 --- a/board/nightfury/led.c +++ b/board/nightfury/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -12,54 +12,57 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1 = 1; +__override const int led_charge_lvl_1 = 1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* Nightfury : There are 3 leds for AC, Battery and Power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, 0.5 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0_BAT_LOW] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 0.5 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, -}; - -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_BLUE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { /* Don't set led if led_auto_control is disabled. */ if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || - !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { return; } - if (color == EC_LED_COLOR_BLUE) - { + if (color == EC_LED_COLOR_BLUE) { gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_ON_LVL); @@ -69,19 +72,18 @@ void led_set_color_power(enum ec_led_colors color) } } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { /* Don't set led if led_auto_control is disabled. */ if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || - !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { return; } /* Battery leds must be turn off when blue led is on * because Nightfury has 3-in-1 led. */ - if(!gpio_get_level(GPIO_PWR_LED_BLUE_L)) - { + if (!gpio_get_level(GPIO_PWR_LED_BLUE_L)) { gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); return; @@ -117,10 +119,13 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { if (led_id == EC_LED_ID_BATTERY_LED) { gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); - gpio_set_level(GPIO_BAT_LED_GREEN_L, !brightness[EC_LED_COLOR_GREEN]); - gpio_set_level(GPIO_BAT_LED_RED_L, !brightness[EC_LED_COLOR_RED]); + gpio_set_level(GPIO_BAT_LED_GREEN_L, + !brightness[EC_LED_COLOR_GREEN]); + gpio_set_level(GPIO_BAT_LED_RED_L, + !brightness[EC_LED_COLOR_RED]); } else if (led_id == EC_LED_ID_POWER_LED) { - gpio_set_level(GPIO_PWR_LED_BLUE_L, !brightness[EC_LED_COLOR_BLUE]); + gpio_set_level(GPIO_PWR_LED_BLUE_L, + !brightness[EC_LED_COLOR_BLUE]); gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); } diff --git a/board/nightfury/vif_override.xml b/board/nightfury/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/nightfury/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/nipperkin/battery.c b/board/nipperkin/battery.c new file mode 100644 index 0000000000..b8bedb535e --- /dev/null +++ b/board/nipperkin/battery.c @@ -0,0 +1,92 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" + +/* + * Battery info for all Guybrush battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* SMP 996QA193H Battery Information */ + [BATTERY_SIMPLO_HIGHPOWER] = { + .fuel_gauge = { + .manuf_name = "333-1D-11-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +/* Cosmx CA407792G Battery Information */ + [BATTERY_COSMX] = { + .fuel_gauge = { + .manuf_name = "333-AC-11-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO_HIGHPOWER; diff --git a/board/nipperkin/board.c b/board/nipperkin/board.c new file mode 100644 index 0000000000..0111f9c04e --- /dev/null +++ b/board/nipperkin/board.c @@ -0,0 +1,531 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Nipperkin board-specific configuration */ + +#include "adc.h" +#include "base_fw_config.h" +#include "battery.h" +#include "board_fw_config.h" +#include "button.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "cros_board_info.h" +#include "driver/charger/isl9241.h" +#include "driver/retimer/pi3hdx1204.h" +#include "driver/retimer/ps8811.h" +#include "driver/retimer/ps8818_public.h" +#include "driver/temp_sensor/pct2075.h" +#include "driver/temp_sensor/sb_tsi.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" +#include "timer.h" +#include "usb_mux.h" + +static void hdmi_hpd_interrupt(enum gpio_signal signal); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +__override enum ec_error_list +board_a1_ps8811_retimer_init(const struct usb_mux *me) +{ + return EC_SUCCESS; +} + +__override int board_c1_ps8818_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + /* Set the RX input termination */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_RX_PHY, + PS8818_RX_INPUT_TERM_MASK, + PS8818_RX_INPUT_TERM_112_OHM); + if (rv) + return rv; + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* Boost the DP gain */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_DPEQ_LEVEL, + PS8818_DPEQ_LEVEL_UP_MASK, + PS8818_DPEQ_LEVEL_UP_19DB); + if (rv) + return rv; + + /* Enable HPD on the DB */ + ioex_set_level(IOEX_USB_C1_IN_HPD, 1); + } else { + /* Disable HPD on the DB */ + ioex_set_level(IOEX_USB_C1_IN_HPD, 0); + } + + return rv; +} + +static void board_init(void) +{ + if (get_board_version() > 1) + gpio_enable_interrupt(GPIO_HPD_EC_IN); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_chipset_startup(void) +{ + if (get_board_version() > 1) + pct2075_init(); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +int board_get_soc_temp_k(int idx, int *temp_k) +{ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + + return pct2075_get_val_k(idx, temp_k); +} + +int board_get_soc_temp_mk(int *temp_mk) +{ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + + return pct2075_get_val_mk(PCT2075_SOC, temp_mk); +} + +int board_get_ambient_temp_mk(int *temp_mk) +{ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + + return pct2075_get_val_mk(PCT2075_AMB, temp_mk); +} + +/* ADC Channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_MEMORY] = { + .name = "MEMORY", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_CHARGER] = { + .name = "CHARGER", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_5V_REGULATOR] = { + .name = "5V_REGULATOR", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_CORE_IMON1] = { + .name = "CORE_I", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SOC_IMON2] = { + .name = "SOC_I", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temp Sensors */ +static int board_get_temp(int, int *); + +const struct pct2075_sensor_t pct2075_sensors[] = { + { I2C_PORT_SENSOR, PCT2075_I2C_ADDR_FLAGS0 }, + { I2C_PORT_SENSOR, PCT2075_I2C_ADDR_FLAGS7 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pct2075_sensors) == PCT2075_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_SOC] = { + .name = "SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = board_get_soc_temp_k, + .idx = PCT2075_SOC, + }, + [TEMP_SENSOR_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER, + }, + [TEMP_SENSOR_MEMORY] = { + .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = board_get_temp, + .idx = ADC_TEMP_SENSOR_MEMORY, + }, + [TEMP_SENSOR_5V_REGULATOR] = { + .name = "5V_REGULATOR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = board_get_temp, + .idx = ADC_TEMP_SENSOR_5V_REGULATOR, + }, + [TEMP_SENSOR_CPU] = { + .name = "CPU", + .type = TEMP_SENSOR_TYPE_CPU, + .read = sb_tsi_get_val, + .idx = 0, + }, + [TEMP_SENSOR_AMBIENT] = { + .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = pct2075_get_val_k, + .idx = PCT2075_AMB, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT] = { + [TEMP_SENSOR_SOC] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + [EC_TEMP_THRESH_HALT] = C_TO_K(83), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), + }, + }, + [TEMP_SENSOR_CHARGER] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(77), + [EC_TEMP_THRESH_HALT] = C_TO_K(81), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(72), + }, + }, + [TEMP_SENSOR_MEMORY] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + [EC_TEMP_THRESH_HALT] = C_TO_K(83), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), + }, + }, + [TEMP_SENSOR_5V_REGULATOR] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(55), + [EC_TEMP_THRESH_HALT] = C_TO_K(58), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(47), + }, + }, + [TEMP_SENSOR_CPU] = { + .temp_host = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(100), + [EC_TEMP_THRESH_HALT] = C_TO_K(105), + }, + .temp_host_release = { + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), + }, + }, + /* + * Note: Leave ambient entries at 0, both as it does not represent a + * hotspot and as not all boards have this sensor + */ +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +static int board_get_temp(int idx, int *temp_k) +{ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + return EC_ERROR_NOT_POWERED; + return get_temp_3v3_30k9_47k_4050b(idx, temp_k); +} + +static int check_hdmi_hpd_status(void) +{ + if (get_board_version() > 1) + return gpio_get_level(GPIO_HPD_EC_IN); + else + return true; +} + +/* Called on AP resume to S0 */ +static void board_chipset_resume(void) +{ + ioex_set_level(IOEX_USB_A1_PD_R_L, 1); + ioex_set_level(IOEX_EN_PWR_HDMI, 1); + ioex_set_level(IOEX_HDMI_DATA_EN, 1); + msleep(PI3HDX1204_POWER_ON_DELAY_MS); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, + check_hdmi_hpd_status()); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP suspend */ +static void board_chipset_suspend(void) +{ + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, 0); + ioex_set_level(IOEX_HDMI_DATA_EN, 0); + ioex_set_level(IOEX_EN_PWR_HDMI, 0); + ioex_set_level(IOEX_USB_A1_PD_R_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* + * With privacy screen, with keyboard backlight + */ +static const struct ec_response_keybd_config + keybd_w_privacy_w_kblight = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PRIVACY_SCRN_TOGGLE, /* T8 */ + TK_KBD_BKLIGHT_TOGGLE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +/* + * Without privacy screen, with keyboard backlight + */ +static const struct ec_response_keybd_config + keybd_wo_privacy_w_kblight = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_KBD_BKLIGHT_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +/* + * With privacy screen, without keyboard backlight + */ +static const struct ec_response_keybd_config + keybd_w_privacy_wo_kblight = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PRIVACY_SCRN_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +/* + * Without privacy screen, without keyboard backlight + */ +static const struct ec_response_keybd_config + keybd_wo_privacy_wo_kblight_V0 = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PREV_TRACK, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config + keybd_wo_privacy_wo_kblight_V1 = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PLAY_PAUSE, /* T8 */ + TK_MICMUTE, /* T9 */ + TK_VOL_MUTE, /* T10 */ + TK_VOL_DOWN, /* T11 */ + TK_VOL_UP, /* T12 */ + TK_MENU, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (board_has_privacy_panel() && board_has_kblight()) + return &keybd_w_privacy_w_kblight; + else if (!board_has_privacy_panel() && board_has_kblight()) + return &keybd_wo_privacy_w_kblight; + else if (board_has_privacy_panel() && !board_has_kblight()) + return &keybd_w_privacy_wo_kblight; + else { + if (get_board_version() <= 3) + return &keybd_wo_privacy_wo_kblight_V0; + else + return &keybd_wo_privacy_wo_kblight_V1; + } +} + +const struct pi3hdx1204_tuning pi3hdx1204_tuning = { + .eq_ch0_ch1_offset = PI3HDX1204_EQ_DB710, + .eq_ch2_ch3_offset = PI3HDX1204_EQ_DB710, + .vod_offset = PI3HDX1204_VOD_115_ALL_CHANNELS, + .de_offset = PI3HDX1204_DE_DB_MINUS5, +}; + +static void hdmi_hpd_handler(void) +{ + int hpd = check_hdmi_hpd_status(); + + ccprints("HDMI HPD %d", hpd); + pi3hdx1204_enable( + I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, + chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON) && hpd); +} +DECLARE_DEFERRED(hdmi_hpd_handler); + +static void hdmi_hpd_interrupt(enum gpio_signal signal) +{ + /* Debounce for 2 msec */ + hook_call_deferred(&hdmi_hpd_handler_data, (2 * MSEC)); +} + +void board_set_current_limit(void) +{ + const int no_battery_current_limit_override_ma = 6000; + /* + * When there is no battery, override charger current limit to + * prevent brownout during boot. + */ + if (battery_is_present() == BP_NO) { + ccprints("No Battery Found - Override Current Limit to %dmA", + no_battery_current_limit_override_ma); + charger_set_input_current_limit( + CHARGER_SOLO, no_battery_current_limit_override_ma); + } +} +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, board_set_current_limit, + HOOK_PRIO_INIT_EXTPOWER); + +/* Set the DCPROCHOT base on battery over discharging current 5.888A */ +static void set_dc_prochot(void) +{ + /* + * Only bits 13:8 are usable for this register, any other bits will be + * truncated. Valid values are 256 mA to 16128 mA at 256 mA intervals. + */ + isl9241_set_dc_prochot(CHARGER_SOLO, 5888); +} +DECLARE_HOOK(HOOK_INIT, set_dc_prochot, HOOK_PRIO_DEFAULT); diff --git a/board/nipperkin/board.h b/board/nipperkin/board.h new file mode 100644 index 0000000000..af684e1f49 --- /dev/null +++ b/board/nipperkin/board.h @@ -0,0 +1,91 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Guybrush board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* Motion sensing drivers */ + +/* Keyboard features */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* EC console commands */ +#define CONFIG_CMD_BUTTON + +/* USB Type C and USB PD defines */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 +/* Max Power = 100 W */ +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) + +#define CONFIG_CHARGER_PROFILE_OVERRIDE + +/* USB Type A Features */ + +/* BC 1.2 */ + +/* Volume Button feature */ + +/* Fan features */ +#define CONFIG_CUSTOM_FAN_CONTROL +#define RPM_DEVIATION 1 + +/* LED features */ +#define CONFIG_LED_COMMON +#define CONFIG_LED_ONOFF_STATES + +/* Thermal Config */ +#define CONFIG_TEMP_SENSOR_PCT2075 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +/* Battery Types */ +enum battery_type { + BATTERY_SIMPLO_HIGHPOWER, + BATTERY_COSMX, + BATTERY_TYPE_COUNT, +}; + +/* ADC Channels */ +enum adc_channel { + ADC_TEMP_SENSOR_MEMORY = 0, + ADC_TEMP_SENSOR_CHARGER, + ADC_TEMP_SENSOR_5V_REGULATOR, + ADC_CORE_IMON1, + ADC_SOC_IMON2, + ADC_CH_COUNT +}; + +/* Temp Sensors */ +enum temp_sensor_id { + TEMP_SENSOR_SOC = 0, + TEMP_SENSOR_CHARGER, + TEMP_SENSOR_MEMORY, + TEMP_SENSOR_5V_REGULATOR, + TEMP_SENSOR_CPU, + TEMP_SENSOR_AMBIENT, + TEMP_SENSOR_COUNT +}; + +/* PCT2075 sensors */ +enum pct2075_sensor { + PCT2075_SOC, + PCT2075_AMB, + PCT2075_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/nipperkin/board_fw_config.c b/board/nipperkin/board_fw_config.c new file mode 100644 index 0000000000..e21e42689f --- /dev/null +++ b/board/nipperkin/board_fw_config.c @@ -0,0 +1,31 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "base_fw_config.h" +#include "board_fw_config.h" + +bool board_has_kblight(void) +{ + return (get_fw_config_field(FW_CONFIG_KBLIGHT_OFFSET, + FW_CONFIG_KBLIGHT_WIDTH) == + FW_CONFIG_KBLIGHT_YES); +} + +enum board_usb_c1_mux board_get_usb_c1_mux(void) +{ + return USB_C1_MUX_PS8818; +}; + +enum board_usb_a1_retimer board_get_usb_a1_retimer(void) +{ + return USB_A1_RETIMER_PS8811; +}; + +bool board_has_privacy_panel(void) +{ + return (get_fw_config_field(FW_CONFIG_KEYBOARD_OFFSET, + FW_CONFIG_KEYBOARD_WIDTH) == + FW_CONFIG_KEYBOARD_PRIVACY_YES); +} diff --git a/board/nipperkin/board_fw_config.h b/board/nipperkin/board_fw_config.h new file mode 100644 index 0000000000..f4673f732e --- /dev/null +++ b/board/nipperkin/board_fw_config.h @@ -0,0 +1,35 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _NIPPERKIN_BOARD_FW_CONFIG__H_ +#define _NIPPERKIN_BOARD_FW_CONFIG__H_ + +/**************************************************************************** + * Nipperkin CBI FW Configuration + */ + +/* + * Keyboard Backlight (1 bit) + */ +#define FW_CONFIG_KBLIGHT_OFFSET 0 +#define FW_CONFIG_KBLIGHT_WIDTH 1 +#define FW_CONFIG_KBLIGHT_NO 0 +#define FW_CONFIG_KBLIGHT_YES 1 + +/* + * Bit 1 ~ 6 not related to EC function + */ + +/* + * Keyboard (1 bit) + */ +#define FW_CONFIG_KEYBOARD_OFFSET 7 +#define FW_CONFIG_KEYBOARD_WIDTH 1 +#define FW_CONFIG_KEYBOARD_PRIVACY_YES 0 +#define FW_CONFIG_KEYBOARD_PRIVACY_NO 1 + +bool board_has_privacy_panel(void); + +#endif /* _NIPPERKIN_BOARD_FW_CONFIG__H_ */ diff --git a/board/nipperkin/build.mk b/board/nipperkin/build.mk new file mode 100644 index 0000000000..aad8b2ae09 --- /dev/null +++ b/board/nipperkin/build.mk @@ -0,0 +1,13 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +BASEBOARD:=guybrush + +board-y=board.o +board-y+=board_fw_config.o led.o battery.o +board-y+=thermal.o diff --git a/board/nipperkin/ec.tasklist b/board/nipperkin/ec.tasklist new file mode 100644 index 0000000000..a127b13eba --- /dev/null +++ b/board/nipperkin/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, VENTI_TASK_STACK_SIZE) diff --git a/board/nipperkin/gpio.inc b/board/nipperkin/gpio.inc new file mode 100644 index 0000000000..0a8c6d9a65 --- /dev/null +++ b/board/nipperkin/gpio.inc @@ -0,0 +1,32 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the board GPIOs that we care about. */ + +#include "base_gpio.inc" + +/* LED Signals */ +GPIO(C0_CHARGE_LED_AMBER_L, PIN(C, 4), GPIO_OUT_HIGH) +GPIO(C0_CHARGE_LED_WHITE_L, PIN(8, 0), GPIO_OUT_HIGH) +GPIO(C1_CHARGE_LED_AMBER_L, PIN(6, 7), GPIO_OUT_HIGH) +GPIO(C1_CHARGE_LED_WHITE_L, PIN(7, 0), GPIO_OUT_HIGH) + +/* HDMI */ +IOEX(EN_PWR_HDMI, EXPIN(USBC_PORT_C0, 0, 3), GPIO_OUT_LOW) +IOEX(HDMI_DATA_EN, EXPIN(USBC_PORT_C0, 1, 4), GPIO_OUT_LOW) +GPIO_INT(HPD_EC_IN, PIN(6, 2), GPIO_INT_BOTH, hdmi_hpd_interrupt) + +/* Power Signals */ +IOEX(USB_A1_PD_R_L, EXPIN(USBC_PORT_C1, 1, 7), GPIO_OUT_LOW) + +/* Test Points */ +GPIO(EC_GPIO56, PIN(5, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_GPIOB0, PIN(B, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_GPIO81, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_FLPRG2, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PSL_GPO, PIN(D, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_PWM7, PIN(6, 0), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/nipperkin/led.c b/board/nipperkin/led.c new file mode 100644 index 0000000000..72598f8a21 --- /dev/null +++ b/board/nipperkin/led.c @@ -0,0 +1,228 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +#define LED_TICKS_PER_CYCLE 10 +#define LED_TICKS_PER_CYCLE_S3 10 +#define LED_ON_TICKS 5 +#define POWER_LED_ON_S3_TICKS 5 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +enum led_port { LED_LEFT_PORT = 0, LED_RIGHT_PORT }; + +static void led_set_color_battery(enum led_port port, enum led_color color) +{ + enum gpio_signal amber_led, white_led; + + amber_led = (port == LED_LEFT_PORT ? GPIO_C0_CHARGE_LED_AMBER_L : + GPIO_C1_CHARGE_LED_AMBER_L); + white_led = (port == LED_LEFT_PORT ? GPIO_C0_CHARGE_LED_WHITE_L : + GPIO_C1_CHARGE_LED_WHITE_L); + + switch (color) { + case LED_WHITE: + gpio_set_level(white_led, BAT_LED_ON); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_ON); + break; + case LED_OFF: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + default: + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_RIGHT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + default: + break; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LED_LEFT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LED_LEFT_PORT, LED_AMBER); + else + led_set_color_battery(LED_LEFT_PORT, LED_OFF); + break; + case EC_LED_ID_RIGHT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LED_RIGHT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LED_RIGHT_PORT, LED_AMBER); + else + led_set_color_battery(LED_RIGHT_PORT, LED_OFF); + break; + default: + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + led_set_color_battery(LED_RIGHT_PORT, (port == LED_RIGHT_PORT) ? + color : + LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LED_LEFT_PORT, (port == LED_LEFT_PORT) ? + color : + LED_OFF); +} + +static void led_set_battery(void) +{ + static int battery_ticks; + static int power_ticks; + + battery_ticks++; + + /* + * Override battery LEDs for Nipperkin, Nipperkin is non-power LED + * design, blinking both two side battery white LEDs to indicate + * system suspend with non-charging state. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + led_pwr_get_state() != LED_PWRS_CHARGE) { + power_ticks++; + + led_set_color_battery(LED_RIGHT_PORT, + power_ticks % LED_TICKS_PER_CYCLE_S3 < + POWER_LED_ON_S3_TICKS ? + LED_WHITE : + LED_OFF); + led_set_color_battery(LED_LEFT_PORT, + power_ticks % LED_TICKS_PER_CYCLE_S3 < + POWER_LED_ON_S3_TICKS ? + LED_WHITE : + LED_OFF); + return; + } + + power_ticks = 0; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + if (charge_get_percent() < 10) + led_set_color_battery( + LED_RIGHT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(LED_RIGHT_PORT, LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) { + if (charge_get_percent() < 10) + led_set_color_battery( + LED_LEFT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(LED_LEFT_PORT, LED_OFF); + } + break; + case LED_PWRS_ERROR: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + led_set_color_battery( + LED_RIGHT_PORT, + (battery_ticks & 0x1) ? LED_AMBER : LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) { + led_set_color_battery( + LED_LEFT_PORT, + (battery_ticks & 0x1) ? LED_AMBER : LED_OFF); + } + break; + + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/nipperkin/thermal.c b/board/nipperkin/thermal.c new file mode 100644 index 0000000000..117a6d08fa --- /dev/null +++ b/board/nipperkin/thermal.c @@ -0,0 +1,239 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_state.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "fan.h" +#include "hooks.h" +#include "host_command.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = GPIO_S0_PGOOD, + .enable_gpio = -1, +}; +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1000, + .rpm_start = 1000, + .rpm_max = 6500, +}; +const struct fan_t fans[] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); + +struct fan_step { + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t on[TEMP_SENSOR_COUNT]; + + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t off[TEMP_SENSOR_COUNT]; + + /* Fan 1~2 rpm */ + uint16_t rpm[FAN_CH_COUNT]; +}; + +static const struct fan_step fan_step_table[] = { + { + /* level 0 */ + .on = { 51, 0, 44, -1, -1, -1 }, + .off = { 99, 99, 99, -1, -1, -1 }, + .rpm = { 0 }, + }, + { + /* level 1 */ + .on = { 52, 0, 47, -1, -1, -1 }, + .off = { 50, 99, 43, -1, -1, -1 }, + .rpm = { 3000 }, + }, + { + /* level 2 */ + .on = { 53, 0, 49, -1, -1, -1 }, + .off = { 51, 99, 45, -1, -1, -1 }, + .rpm = { 3400 }, + }, + { + /* level 3 */ + .on = { 54, 0, 51, -1, -1, -1 }, + .off = { 52, 99, 47, -1, -1, -1 }, + .rpm = { 3800 }, + }, + { + /* level 4 */ + .on = { 56, 50, 53, -1, -1, -1 }, + .off = { 53, 47, 49, -1, -1, -1 }, + .rpm = { 4100 }, + }, + { + /* level 5 */ + .on = { 57, 52, 55, -1, -1, -1 }, + .off = { 55, 49, 51, -1, -1, -1 }, + .rpm = { 4400 }, + }, + { + /* level 6 */ + .on = { 100, 100, 100, -1, -1, -1 }, + .off = { 56, 51, 53, -1, -1, -1 }, + .rpm = { 4900 }, + }, +}; + +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_step_table) + +BUILD_ASSERT(ARRAY_SIZE(fan_step_table) == ARRAY_SIZE(fan_step_table)); + +int fan_table_to_rpm(int fan, int *temp) +{ + static int current_level; + static int prev_tmp[TEMP_SENSOR_COUNT]; + int new_rpm = 0; + int i; + + /* + * Compare the current and previous temperature, we have + * the three paths : + * 1. decreasing path. (check the release point) + * 2. increasing path. (check the trigger point) + * 3. invariant path. (return the current RPM) + */ + if (temp[TEMP_SENSOR_CHARGER] < prev_tmp[TEMP_SENSOR_CHARGER] || + temp[TEMP_SENSOR_MEMORY] < prev_tmp[TEMP_SENSOR_MEMORY] || + temp[TEMP_SENSOR_SOC] < prev_tmp[TEMP_SENSOR_SOC]) { + for (i = current_level; i > 0; i--) { + if (temp[TEMP_SENSOR_CHARGER] < + fan_step_table[i].off[TEMP_SENSOR_CHARGER] && + temp[TEMP_SENSOR_MEMORY] < + fan_step_table[i].off[TEMP_SENSOR_MEMORY] && + temp[TEMP_SENSOR_SOC] < + fan_step_table[i].off[TEMP_SENSOR_SOC]) { + current_level = i - 1; + } else + break; + } + } else if (temp[TEMP_SENSOR_CHARGER] > prev_tmp[TEMP_SENSOR_CHARGER] || + temp[TEMP_SENSOR_MEMORY] > prev_tmp[TEMP_SENSOR_MEMORY] || + temp[TEMP_SENSOR_SOC] > prev_tmp[TEMP_SENSOR_SOC]) { + for (i = current_level; i < NUM_FAN_LEVELS; i++) { + if ((temp[TEMP_SENSOR_CHARGER] > + fan_step_table[i].on[TEMP_SENSOR_CHARGER] && + temp[TEMP_SENSOR_MEMORY] > + fan_step_table[i].on[TEMP_SENSOR_MEMORY]) || + temp[TEMP_SENSOR_SOC] > + fan_step_table[i].on[TEMP_SENSOR_SOC]) { + current_level = i + 1; + } else + break; + } + } + + if (current_level < 0) + current_level = 0; + + if (current_level >= NUM_FAN_LEVELS) + current_level = NUM_FAN_LEVELS - 1; + + for (i = 0; i < TEMP_SENSOR_COUNT; ++i) + prev_tmp[i] = temp[i]; + + new_rpm = fan_step_table[current_level].rpm[FAN_CH_0]; + + return new_rpm; +} + +void board_override_fan_control(int fan, int *tmp) +{ + if (chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND)) { + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), fan_table_to_rpm(fan, tmp)); + } +} + +struct chg_curr_step { + int on; + int off; + int curr_ma; +}; + +static const struct chg_curr_step chg_curr_table[] = { + { .on = 0, .off = 0, .curr_ma = 3566 }, + { .on = 66, .off = 65, .curr_ma = 2500 }, + { .on = 70, .off = 69, .curr_ma = 1500 }, +}; + +#define NUM_CHG_CURRENT_LEVELS ARRAY_SIZE(chg_curr_table) + +int charger_profile_override(struct charge_state_data *curr) +{ + int rv; + int chg_temp_c; + int current; + int thermal_sensor_chrg; + static int current_level; + static int prev_tmp; + + if (!(curr->batt.flags & BATT_FLAG_RESPONSIVE)) + return 0; + + current = curr->requested_current; + + rv = temp_sensor_read(TEMP_SENSOR_CHARGER, &thermal_sensor_chrg); + chg_temp_c = K_TO_C(thermal_sensor_chrg); + + if (rv != EC_SUCCESS) + return rv; + + if (chipset_in_state(CHIPSET_STATE_ON)) { + if (chg_temp_c < prev_tmp) { + if ((chg_temp_c <= chg_curr_table[current_level].off) && + (current_level > 0)) + current_level -= 1; + } else if (chg_temp_c > prev_tmp) { + if ((chg_temp_c >= + chg_curr_table[current_level + 1].on) && + (current_level < NUM_CHG_CURRENT_LEVELS - 1)) + current_level += 1; + } + + prev_tmp = chg_temp_c; + current = chg_curr_table[current_level].curr_ma; + + curr->requested_current = MIN(curr->requested_current, current); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/nipperkin/vif_override.xml b/board/nipperkin/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/nipperkin/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/nocturne/base_detect.c b/board/nocturne/base_detect.c index 3735080c49..807aa3e14a 100644 --- a/board/nocturne/base_detect.c +++ b/board/nocturne/base_detect.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -26,8 +26,8 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) #define DEFAULT_POLL_TIMEOUT_US (250 * MSEC) #define DEBOUNCE_TIMEOUT_US (20 * MSEC) @@ -62,7 +62,6 @@ */ #define WINDOW_SIZE 5 - enum base_detect_state { BASE_DETACHED = 0, BASE_ATTACHED_DEBOUNCE, @@ -82,7 +81,7 @@ static timestamp_t detached_decision_deadline; static void enable_base_interrupts(int enable) { int (*fn)(enum gpio_signal) = enable ? gpio_enable_interrupt : - gpio_disable_interrupt; + gpio_disable_interrupt; /* This pin is present on boards newer than rev 0. */ if (board_get_version() > 0) @@ -141,28 +140,26 @@ static void base_detect_changed(void) static int base_seems_attached(int attach_pin_mv, int detach_pin_mv) { /* We can't tell if we don't have good readings. */ - if (attach_pin_mv == ADC_READ_ERROR || - detach_pin_mv == ADC_READ_ERROR) + if (attach_pin_mv == ADC_READ_ERROR || detach_pin_mv == ADC_READ_ERROR) return 0; if (gpio_get_level(GPIO_BASE_PWR_EN)) return (attach_pin_mv >= PWREN_ATTACH_MIN_MV) && - (detach_pin_mv >= DETACH_MIN_MV); + (detach_pin_mv >= DETACH_MIN_MV); else return (attach_pin_mv <= ATTACH_MAX_MV) && - (attach_pin_mv >= ATTACH_MIN_MV) && - (detach_pin_mv <= DETACH_MIN_MV); + (attach_pin_mv >= ATTACH_MIN_MV) && + (detach_pin_mv <= DETACH_MIN_MV); } static int base_seems_detached(int attach_pin_mv, int detach_pin_mv) { /* We can't tell if we don't have good readings. */ - if (attach_pin_mv == ADC_READ_ERROR || - detach_pin_mv == ADC_READ_ERROR) + if (attach_pin_mv == ADC_READ_ERROR || detach_pin_mv == ADC_READ_ERROR) return 0; return (attach_pin_mv >= PWREN_ATTACH_MIN_MV) && - (detach_pin_mv <= DETACH_MIN_MV); + (detach_pin_mv <= DETACH_MIN_MV); } static void set_state(enum base_detect_state new_state) @@ -194,9 +191,9 @@ static void base_detect_deferred(void) if (forced_state != BASE_NO_FORCED_STATE) { if (state != forced_state) { - CPRINTS("BD forced %s", - forced_state == BASE_ATTACHED ? - "attached" : "detached"); + CPRINTS("BD forced %s", forced_state == BASE_ATTACHED ? + "attached" : + "detached"); set_state(forced_state); base_detect_changed(); } @@ -212,8 +209,7 @@ static void base_detect_deferred(void) if (debug) { int i; - CPRINTS("BD st%d: att: %dmV det: %dmV", state, - attach_reading, + CPRINTS("BD st%d: att: %dmV det: %dmV", state, attach_reading, detach_reading); CPRINTF("det readings = ["); for (i = 0; i < WINDOW_SIZE; i++) @@ -341,7 +337,6 @@ static void check_and_reapply_base_power_deferred(void) hook_call_deferred(&clear_base_power_on_attempts_deferred_data, SECOND); } - } DECLARE_DEFERRED(check_and_reapply_base_power_deferred); @@ -366,25 +361,24 @@ void base_pwr_fault_interrupt(enum gpio_signal s) } } -static int command_basedetectdebug(int argc, char **argv) +static int command_basedetectdebug(int argc, const char **argv) { if ((argc > 1) && !parse_bool(argv[1], &debug)) return EC_ERROR_PARAM1; - CPRINTS("BD: %sst%d", forced_state != BASE_NO_FORCED_STATE ? - "forced " : "", state); + CPRINTS("BD: %sst%d", + forced_state != BASE_NO_FORCED_STATE ? "forced " : "", state); return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(basedebug, command_basedetectdebug, "[ena|dis]", "En/Disable base detection debug"); - -void base_force_state(int state) +void base_force_state(enum ec_set_base_state_cmd state) { - if (state == 1) + if (state == EC_SET_BASE_STATE_ATTACH) forced_state = BASE_ATTACHED; - else if (state == 0) + else if (state == EC_SET_BASE_STATE_DETACH) forced_state = BASE_DETACHED; else forced_state = BASE_NO_FORCED_STATE; diff --git a/board/nocturne/battery.c b/board/nocturne/battery.c index 67c5346063..4914f89b2e 100644 --- a/board/nocturne/battery.c +++ b/board/nocturne/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,38 +8,39 @@ #include "battery.h" #include "battery_smart.h" #include "charge_manager.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" -#include "charge_state_v2.h" #include "common.h" #include "console.h" #include "ec_commands.h" #include "extpower.h" +#include "gpio.h" #include "hooks.h" #include "temp_sensor.h" #include "usb_pd.h" /* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHUTDOWN_DATA 0x0010 +#define SB_SHUTDOWN_DATA 0x0010 /* * We need to stop charging the battery when the DRAM temperature sensor gets * over 47 C (320 K), and resume charging once it cools back down. */ -#define DRAM_STOPCHARGE_TEMP_K 320 +#define DRAM_STOPCHARGE_TEMP_K 320 /* Battery info */ static const struct battery_info info = { - .voltage_max = 8880, - .voltage_normal = 7700, - .voltage_min = 6000, - .precharge_current = 160, - .start_charging_min_c = 10, - .start_charging_max_c = 50, - .charging_min_c = 10, - .charging_max_c = 50, - .discharging_min_c = -20, - .discharging_max_c = 60, + .voltage_max = 8880, + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 160, + .start_charging_min_c = 10, + .start_charging_max_c = 50, + .charging_min_c = 10, + .charging_max_c = 50, + .discharging_min_c = -20, + .discharging_max_c = 60, }; int board_cut_off_battery(void) @@ -77,8 +78,8 @@ enum battery_disconnect_state battery_get_disconnect_state(void) return BATTERY_NOT_DISCONNECTED; /* Check if battery discharge FET is disabled. */ - rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); + rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, SB_ALT_MANUFACTURER_ACCESS, + data, sizeof(data)); if (rv) return BATTERY_DISCONNECT_ERROR; if (~data[3] & (BATTERY_DISCHARGING_DISABLED)) { @@ -90,8 +91,8 @@ enum battery_disconnect_state battery_get_disconnect_state(void) * Battery discharge FET is disabled. Verify that we didn't enter this * state due to a safety fault. */ - rv = sb_read_mfgacc(PARAM_SAFETY_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); + rv = sb_read_mfgacc(PARAM_SAFETY_STATUS, SB_ALT_MANUFACTURER_ACCESS, + data, sizeof(data)); if (rv || data[2] || data[3] || data[4] || data[5]) return BATTERY_DISCONNECT_ERROR; @@ -99,32 +100,6 @@ enum battery_disconnect_state battery_get_disconnect_state(void) return BATTERY_DISCONNECTED; } -static void reduce_input_voltage_when_full(void) -{ - struct batt_params batt; - int max_pd_voltage_mv; - int active_chg_port; - - active_chg_port = charge_manager_get_active_charge_port(); - if (active_chg_port == CHARGE_PORT_NONE) - return; - - battery_get_params(&batt); - if (!(batt.flags & BATT_FLAG_BAD_STATUS)) { - /* Lower our input voltage to 9V when battery is full. */ - if ((batt.status & STATUS_FULLY_CHARGED) && - chipset_in_state(CHIPSET_STATE_ANY_OFF)) - max_pd_voltage_mv = 9000; - else - max_pd_voltage_mv = PD_MAX_VOLTAGE_MV; - - if (pd_get_max_voltage() != max_pd_voltage_mv) - pd_set_external_voltage_limit(active_chg_port, - max_pd_voltage_mv); - } -} -DECLARE_HOOK(HOOK_SECOND, reduce_input_voltage_when_full, HOOK_PRIO_DEFAULT); - enum ec_status charger_profile_override_get_param(uint32_t param, uint32_t *value) { diff --git a/board/nocturne/board.c b/board/nocturne/board.c index 6a45cabf4c..de7671163b 100644 --- a/board/nocturne/board.c +++ b/board/nocturne/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,11 +9,10 @@ #include "button.h" #include "charge_manager.h" #include "charge_state.h" -#include "charge_state_v2.h" #include "chipset.h" #include "common.h" -#include "console.h" #include "compile_time_macros.h" +#include "console.h" #include "driver/accelgyro_bmi_common.h" #include "driver/als_opt3001.h" #include "driver/charger/isl923x.h" @@ -30,24 +29,25 @@ #include "lpc.h" #include "mkbp_event.h" #include "motion_sense.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" #include "pwm_chip.h" #include "registers.h" +#include "switch.h" #include "system.h" #include "system_chip.h" -#include "switch.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal s) { @@ -94,6 +94,7 @@ static void board_connect_c0_sbu(enum gpio_signal s) hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" const enum gpio_signal hibernate_wake_pins[] = { @@ -101,63 +102,67 @@ const enum gpio_signal hibernate_wake_pins[] = { GPIO_AC_PRESENT, GPIO_POWER_BUTTON_L, }; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); const struct adc_t adc_channels[] = { - [ADC_BASE_ATTACH] = { - "BASE ATTACH", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, + [ADC_BASE_ATTACH] = { "BASE ATTACH", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, - [ADC_BASE_DETACH] = { - "BASE DETACH", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, + [ADC_BASE_DETACH] = { "BASE DETACH", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_DB0_LED_RED] = { 3, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - 986 }, + [PWM_CH_DB0_LED_RED] = { 3, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 986 }, [PWM_CH_DB0_LED_GREEN] = { 0, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, 986 }, - [PWM_CH_DB0_LED_BLUE] = { 2, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - 986 }, - [PWM_CH_DB1_LED_RED] = { 7, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - 986 }, + [PWM_CH_DB0_LED_BLUE] = { 2, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 986 }, + [PWM_CH_DB1_LED_RED] = { 7, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 986 }, [PWM_CH_DB1_LED_GREEN] = { 5, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, 986 }, - [PWM_CH_DB1_LED_BLUE] = { 6, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - 986 }, + [PWM_CH_DB1_LED_BLUE] = { 6, PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + 986 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); /* I2C port map */ const struct i2c_port_t i2c_ports[] = { - { - "battery", I2C_PORT_BATTERY, 100, GPIO_EC_I2C4_BATTERY_SCL, - GPIO_EC_I2C4_BATTERY_SDA - }, - - { - "power", I2C_PORT_POWER, 100, GPIO_EC_I2C0_POWER_SCL, - GPIO_EC_I2C0_POWER_SDA - }, - - { - "als_gyro", I2C_PORT_ALS_GYRO, 400, GPIO_EC_I2C5_ALS_GYRO_SCL, - GPIO_EC_I2C5_ALS_GYRO_SDA - }, - - { - "usbc0", I2C_PORT_USB_C0, 100, GPIO_USB_C0_SCL, GPIO_USB_C0_SDA - }, - - { - "usbc1", I2C_PORT_USB_C1, 100, GPIO_USB_C1_SCL, GPIO_USB_C1_SDA - }, + { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C4_BATTERY_SCL, + .sda = GPIO_EC_I2C4_BATTERY_SDA }, + + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C0_POWER_SCL, + .sda = GPIO_EC_I2C0_POWER_SDA }, + + { .name = "als_gyro", + .port = I2C_PORT_ALS_GYRO, + .kbps = 400, + .scl = GPIO_EC_I2C5_ALS_GYRO_SCL, + .sda = GPIO_EC_I2C5_ALS_GYRO_SDA }, + + { .name = "usbc0", + .port = I2C_PORT_USB_C0, + .kbps = 100, + .scl = GPIO_USB_C0_SCL, + .sda = GPIO_USB_C0_SDA }, + + { .name = "usbc1", + .port = I2C_PORT_USB_C1, + .kbps = 100, + .scl = GPIO_USB_C1_SCL, + .sda = GPIO_USB_C1_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - /* * Motion Sense */ @@ -174,11 +179,9 @@ static struct opt3001_drv_data_t g_opt3001_data = { }; /* Matrix to rotate accel/gyro into standard reference frame. */ -const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -286,11 +289,9 @@ static void enable_sensor_irqs(void) DECLARE_HOOK(HOOK_CHIPSET_RESUME, enable_sensor_irqs, HOOK_PRIO_DEFAULT); struct ppc_config_t ppc_chips[] = { - { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, + { .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, { .i2c_port = I2C_PORT_USB_C1, .i2c_addr_flags = SN5S330_ADDR0_FLAGS, @@ -304,7 +305,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -312,23 +313,29 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_USB_C1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, { - .usb_port = 1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, }; @@ -349,8 +356,7 @@ DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); static void imvp8_tune_deferred(void) { /* For the IMVP8, reduce the steps during decay from 3 to 1. */ - if (i2c_write16(I2C_PORT_POWER, I2C_ADDR_MP2949_FLAGS, - 0xFA, 0x0AC5)) + if (i2c_write16(I2C_PORT_POWER, I2C_ADDR_MP2949_FLAGS, 0xFA, 0x0AC5)) CPRINTS("Failed to change step decay!"); } DECLARE_DEFERRED(imvp8_tune_deferred); @@ -505,8 +511,7 @@ static void board_pmic_enable_slp_s0_vr_decay(void) i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x38, 0x6a); } -__override void power_board_handle_host_sleep_event( - enum host_sleep_event state) +__override void power_board_handle_host_sleep_event(enum host_sleep_event state) { if (state == HOST_SLEEP_EVENT_S0IX_SUSPEND) board_pmic_enable_slp_s0_vr_decay(); @@ -519,8 +524,7 @@ static void board_pmic_init(void) int pgmask1; /* Mask V5A_DS3_PG from PMIC PGMASK1. */ - if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, - 0x18, &pgmask1)) + if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x18, &pgmask1)) return; pgmask1 |= BIT(2); i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x18, pgmask1); @@ -594,19 +598,19 @@ static int read_gyro_sensor_temp(int idx, int *temp_ptr) } const struct temp_sensor_t temp_sensors[] = { - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0}, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0 }, /* These BD99992GW temp sensors are only readable in S0 */ - {"Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM0}, - {"Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM1}, - {"DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM2}, - {"eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM3}, + { "Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM0 }, + { "Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM1 }, + { "DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM2 }, + { "eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM3 }, /* The Gyro temperature sensor is only readable in S0. */ - {"Gyro", TEMP_SENSOR_TYPE_BOARD, read_gyro_sensor_temp, LID_GYRO} + { "Gyro", TEMP_SENSOR_TYPE_BOARD, read_gyro_sensor_temp, LID_GYRO } }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -616,16 +620,15 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); */ struct ec_thermal_config thermal_params[] = { /* {Twarn, Thigh, Thalt}, fan_off, fan_max */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Battery */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Ambient */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Charger */ - {{0, C_TO_K(52), 0}, {0, 0, 0}, 0, 0}, /* DRAM */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* eMMC */ - {{0, 0, 0}, {0, 0, 0}, 0, 0} /* Gyro */ + { { 0, 0, 0 }, { 0, 0, 0 }, 0, 0 }, /* Battery */ + { { 0, 0, 0 }, { 0, 0, 0 }, 0, 0 }, /* Ambient */ + { { 0, 0, 0 }, { 0, 0, 0 }, 0, 0 }, /* Charger */ + { { 0, C_TO_K(52), 0 }, { 0, 0, 0 }, 0, 0 }, /* DRAM */ + { { 0, 0, 0 }, { 0, 0, 0 }, 0, 0 }, /* eMMC */ + { { 0, 0, 0 }, { 0, 0, 0 }, 0, 0 } /* Gyro */ }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); - /* * Check if PMIC fault registers indicate VR fault. If yes, print out fault * register info to console. Additionally, set panic reason so that the OS can @@ -638,8 +641,8 @@ static void board_report_pmic_fault(const char *str) uint32_t info; /* RESETIRQ1 -- Bit 4: VRFAULT */ - if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) - != EC_SUCCESS) + if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) != + EC_SUCCESS) return; if (!(vrfault & BIT(4))) @@ -692,8 +695,7 @@ void board_set_tcpc_power_mode(int port, int mode) int board_set_active_charge_port(int port) { - int is_real_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); int i; int rv; int old_port; @@ -758,19 +760,6 @@ int board_set_active_charge_port(int port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - int icl = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); - - /* - * Nocturne seems to overdraw its set input current limit by about 5%. - * Request at most 95% of what's desired. - */ - icl = icl * 95 / 100; - charge_set_input_current_limit(icl, charge_mv); -} - static void board_chipset_reset(void) { board_report_pmic_fault("CHIPSET RESET"); diff --git a/board/nocturne/board.h b/board/nocturne/board.h index a97b242978..6c46a2949b 100644 --- a/board/nocturne/board.h +++ b/board/nocturne/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,36 +8,35 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H +#define CONFIG_LTO + /* * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY - /* NPCX7 config */ -#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ -#define NPCX_TACH_SEL2 0 /* No tach. */ -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX_TACH_SEL2 0 /* No tach. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ #define CONFIG_HIBERNATE_PSL /* Internal SPI flash on NPCX7 */ -#define CONFIG_FLASH_SIZE (512 * 1024) /* It's really 1MB. */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* It's really 1MB. */ #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ /* EC modules */ #define CONFIG_ADC #define CONFIG_BACKLIGHT_LID -#define CONFIG_BOARD_VERSION_CUSTOM -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_FPU #define CONFIG_I2C #define CONFIG_I2C_BUS_MAY_BE_UNPOWERED -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_LOW_POWER_IDLE #define CONFIG_PWM #define CONFIG_THROTTLE_AP @@ -60,6 +59,7 @@ #define CONFIG_BATTERY_SMART #define CONFIG_BATTERY_REVIVE_DISCONNECT #define CONFIG_BATTERY_PRESENT_GPIO GPIO_BAT_PRESENT_L +#define CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV 9000 /* Buttons / Switches */ #define CONFIG_BASE_ATTACHED_SWITCH @@ -70,8 +70,16 @@ #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 128 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 128 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 128 #define CONFIG_CHARGER_ISL9238 +/* + * Nocturne seems to overdraw its set input current limit by about 5%. + * Request at most 95% of what's desired. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 +#undef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 #define CONFIG_CHARGER_PROFILE_OVERRIDE #define CONFIG_CHARGER_SENSE_RESISTOR 10 @@ -87,8 +95,8 @@ /* MKBP */ #define CONFIG_MKBP_EVENT -#define CONFIG_MKBP_EVENT_WAKEUP_MASK (1< diff --git a/board/nocturne_fp/board.c b/board/nocturne_fp/board.c deleted file mode 100644 index c12003577f..0000000000 --- a/board/nocturne_fp/board.c +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -/* Meowth Fingerprint MCU configuration */ - -#include "common.h" -#include "console.h" -#include "fpsensor_detect.h" -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "spi.h" -#include "system.h" -#include "task.h" -#include "util.h" - -/** - * Disable restricted commands when the system is locked. - * - * @see console.h system.c - */ -int console_is_restricted(void) -{ - return system_is_locked(); -} - -#ifndef HAS_TASK_FPSENSOR -void fps_event(enum gpio_signal signal) -{ -} -#endif - -static void ap_deferred(void) -{ - /* - * in S3: SLP_S3_L is 0 and SLP_S0_L is X. - * in S0ix: SLP_S3_L is X and SLP_S0_L is 0. - * in S0: SLP_S3_L is 1 and SLP_S0_L is 1. - * in S5/G3, the FP MCU should not be running. - */ - int running = gpio_get_level(GPIO_PCH_SLP_S3_L) - && gpio_get_level(GPIO_PCH_SLP_S0_L); - - if (running) { /* S0 */ - disable_sleep(SLEEP_MASK_AP_RUN); - hook_notify(HOOK_CHIPSET_RESUME); - } else { /* S0ix/S3 */ - hook_notify(HOOK_CHIPSET_SUSPEND); - enable_sleep(SLEEP_MASK_AP_RUN); - } -} -DECLARE_DEFERRED(ap_deferred); - -/* PCH power state changes */ -void slp_event(enum gpio_signal signal) -{ - hook_call_deferred(&ap_deferred_data, 0); -} - -#include "gpio_list.h" - -/* SPI devices */ -const struct spi_device_t spi_devices[] = { - /* Fingerprint sensor (SCLK at 4Mhz) */ - { .port = CONFIG_SPI_FP_PORT, .div = 3, .gpio_cs = GPIO_SPI4_NSS } -}; -const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); - -static void spi_configure(void) -{ - /* Configure SPI GPIOs */ - gpio_config_module(MODULE_SPI_MASTER, 1); - /* Set all SPI master signal pins to very high speed: pins E2/4/5/6 */ - STM32_GPIO_OSPEEDR(GPIO_E) |= 0x00003f30; - /* Enable clocks to SPI4 module (master) */ - STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI4; - - spi_enable(CONFIG_SPI_FP_PORT, 1); -} - -/* Initialize board. */ -static void board_init(void) -{ - spi_configure(); - - ccprints("TRANSPORT_SEL: %s", - fp_transport_type_to_str(get_fp_transport_type())); - - /* Enable interrupt on PCH power signals */ - gpio_enable_interrupt(GPIO_PCH_SLP_S3_L); - gpio_enable_interrupt(GPIO_PCH_SLP_S0_L); - /* enable the SPI slave interface if the PCH is up */ - hook_call_deferred(&ap_deferred_data, 0); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/nocturne_fp/board.h b/board/nocturne_fp/board.h index 1774e8483f..1a34c05ed8 100644 --- a/board/nocturne_fp/board.h +++ b/board/nocturne_fp/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -51,28 +51,28 @@ #undef CONFIG_WP_STORAGE_OFF #undef CONFIG_WP_STORAGE_SIZE -#define CONFIG_SHAREDLIB_SIZE 0 +#define CONFIG_SHAREDLIB_SIZE 0 -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RO_SIZE (768*1024) +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (768 * 1024) /* EC rollback protection block */ #define CONFIG_ROLLBACK_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) #define CONFIG_ROLLBACK_SIZE (CONFIG_FLASH_BANK_SIZE * 2) -#define CONFIG_RW_MEM_OFF (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) -#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE - \ - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) +#define CONFIG_RW_MEM_OFF (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) -#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE +#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* * We want to prevent flash readout, and use it as indicator of protection @@ -91,30 +91,73 @@ /* Optional features */ #undef CONFIG_ADC #define CONFIG_CMD_IDLE_STATS -#define CONFIG_DMA +#define CONFIG_DMA_CROS #define CONFIG_FORCE_CONSOLE_RESUME #define CONFIG_FPU +/* + * Don't enable FPU warnings on STM32H7, because FPU interrupt is not triggered + * (see, errata ES0392 Rev 8, 2.1.2 Cortex-M7 FPU interrupt not present on NVIC + * line 81). + */ +#undef CONFIG_FPU_WARNINGS #undef CONFIG_HIBERNATE #define CONFIG_HOST_COMMAND_STATUS #undef CONFIG_I2C #undef CONFIG_LID_SWITCH -#define CONFIG_LOW_POWER_IDLE #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -#define CONFIG_PRINTF_LEGACY_LI_FORMAT +#define CONFIG_PRINTF_LONG_IS_32BITS #define CONFIG_SHA256 #define CONFIG_SHA256_UNROLLED #define CONFIG_SPI -#define CONFIG_STM_HWTIMER32 -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY #undef CONFIG_TASK_PROFILING #define CONFIG_WATCHDOG_HELP #define CONFIG_WP_ACTIVE_HIGH +#define CONFIG_PANIC_STRIP_GPR + +#if defined(BOARD_NOCTURNE_FP) || defined(BOARD_NAMI_FP) +/* + * FPMCU RO for nocturne (nocturne_fp_v2.2.64-58cf5974e) and + * FPMCU RO for nami (nami_fp_v2.2.144-7a08e07eb) + * don't have the RV32I core panic data in their panic data structure. + * As a consequence the size of panic data structure is different between RO + * and RW (RO panic data structure is smaller). This results in overwriting RW + * panic data (if it exists) by RO when jumping to RW. Another problem is that + * RW can't find the jump data, because owerwritten panic data structure created + * by RW still contains RW panic data structure size (bigger than RO's), so + * calculated jump data address is wrong. + * + * The problem is fixed by excluding RV32I core panic data from RW, only when + * compiling firmware for nami_fp and nocturne_fp. Expected size of the + * structure is 116 bytes. + */ +#define CONFIG_DO_NOT_INCLUDE_RV32I_PANIC_DATA +#define CONFIG_RO_PANIC_DATA_SIZE 116 + +/* + * FPMCU RO for nocturne and nami don't support extended reset flags in backup + * RAM. RO interprets the register as saved panic reason, so it tries to restore + * panic data when value in the register is different than 0. Another problem is + * that panic data saved in backup RAM on hard reset is restored incorrectly. + * + * CL:1295890 is the change which introduced extended reset flags. + */ +#undef CONFIG_STM32_EXTENDED_RESET_FLAGS +#else +/* + * Dartmonkey FPMCU RO (dartmonkey_v2.0.2887-311310808) has RV32I core panic + * data structure in their panic data structure, so expected size of the + * structure is 144 bytes. + */ +#define CONFIG_RO_PANIC_DATA_SIZE 144 +#endif /* defined(BOARD_NOCTURNE_FP) || defined(BOARD_NAMI_FP) */ /* SPI configuration for the fingerprint sensor */ -#define CONFIG_SPI_MASTER -#define CONFIG_SPI_FP_PORT 2 /* SPI4: third master config */ +#define CONFIG_SPI_CONTROLLER +#define CONFIG_SPI_FP_PORT 2 /* SPI4: third master config */ +#define CONFIG_SPI_MUTABLE_DEVICE_LIST + +#define CONFIG_FINGERPRINT_MCU #ifdef SECTION_IS_RW #define CONFIG_FP_SENSOR_FPC1145 #define CONFIG_CMD_FPSENSOR_DEBUG @@ -125,7 +168,7 @@ */ #define CONFIG_MALLOC /* Special memory regions to store large arrays */ -#define FP_FRAME_SECTION __SECTION(ahb4) +#define FP_FRAME_SECTION __SECTION(ahb4) #define FP_TEMPLATE_SECTION __SECTION(ahb) #else /* SECTION_IS_RO */ @@ -159,13 +202,16 @@ #undef CONFIG_ROLLBACK_UPDATE #endif -#define CONFIG_AES -#define CONFIG_AES_GCM +#define CONFIG_BORINGSSL_CRYPTO #define CONFIG_RNG #define CONFIG_CMD_FLASH + +#ifdef SECTION_IS_RW +#define CONFIG_LOW_POWER_IDLE #define CONFIG_CMD_SPI_XFER +#endif #ifdef SECTION_IS_RW /* @@ -180,12 +226,10 @@ #define TIM_CLOCK32 2 #define TIM_WATCHDOG 16 +#include "board_rw.h" #include "gpio_signal.h" -void fps_event(enum gpio_signal signal); - -/* Defined in ro_workarounds.c */ -void wp_event(enum gpio_signal signal); +void slp_event(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ diff --git a/board/nocturne_fp/board_ro.c b/board/nocturne_fp/board_ro.c new file mode 100644 index 0000000000..7350e5bded --- /dev/null +++ b/board/nocturne_fp/board_ro.c @@ -0,0 +1,77 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Meowth Fingerprint MCU configuration */ + +#include "common.h" +#include "hooks.h" +#include "registers.h" +#include "spi.h" +#include "system.h" +#include "task.h" + +#ifndef SECTION_IS_RO +#error "This file should only be built for RO." +#endif + +/** + * Disable restricted commands when the system is locked. + * + * @see console.h system.c + */ +int console_is_restricted(void) +{ + return system_is_locked(); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +static void ap_deferred(void) +{ + /* + * Behavior: + * AP Active (ex. Intel S0): SLP_L is 1 + * AP Suspend (ex. Intel S0ix): SLP_L is 0 + * The alternative SLP_ALT_L should be pulled high at all the times. + * + * Legacy Intel behavior: + * in S3: SLP_ALT_L is 0 and SLP_L is X. + * in S0ix: SLP_ALT_L is X and SLP_L is 0. + * in S0: SLP_ALT_L is 1 and SLP_L is 1. + * in S5/G3, the FP MCU should not be running. + */ + int running = gpio_get_level(GPIO_SLP_ALT_L) && + gpio_get_level(GPIO_SLP_L); + + if (running) { /* AP is S0 */ + disable_sleep(SLEEP_MASK_AP_RUN); + hook_notify(HOOK_CHIPSET_RESUME); + } else { /* AP is suspend/S0ix/S3 */ + hook_notify(HOOK_CHIPSET_SUSPEND); + enable_sleep(SLEEP_MASK_AP_RUN); + } +} +DECLARE_DEFERRED(ap_deferred); + +/* PCH power state changes */ +void slp_event(enum gpio_signal signal) +{ + hook_call_deferred(&ap_deferred_data, 0); +} + +void board_init(void) +{ + /* Enable interrupt on PCH power signals */ + gpio_enable_interrupt(GPIO_SLP_ALT_L); + gpio_enable_interrupt(GPIO_SLP_L); + + /* + * Enable the SPI slave interface if the PCH is up. + * Do not use hook_call_deferred(), because ap_deferred() will be + * called after tasks with priority higher than HOOK task (very late). + */ + ap_deferred(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/nocturne_fp/board_rw.c b/board/nocturne_fp/board_rw.c new file mode 100644 index 0000000000..c8bc225aa7 --- /dev/null +++ b/board/nocturne_fp/board_rw.c @@ -0,0 +1,137 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "board_rw.h" +#include "common.h" +#include "console.h" +#include "fpsensor_detect.h" +#include "gpio.h" +#include "hooks.h" +#include "registers.h" +#include "spi.h" +#include "system.h" +#include "task.h" +#include "util.h" + +#ifndef SECTION_IS_RW +#error "This file should only be built for RW." +#endif + +/** + * Disable restricted commands when the system is locked. + * + * @see console.h system.c + */ +int console_is_restricted(void) +{ + return system_is_locked(); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* SPI devices */ +struct spi_device_t spi_devices[] = { + /* Fingerprint sensor (SCLK at 4Mhz) */ + { .port = CONFIG_SPI_FP_PORT, .div = 3, .gpio_cs = GPIO_SPI4_NSS } +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +/* Allow changing the signal used for alt sleep depending on the board being + * used: http://b/179946521. + */ +static int gpio_slp_alt_l = GPIO_SLP_ALT_L; + +static void ap_deferred(void) +{ + /* + * Behavior: + * AP Active (ex. Intel S0): SLP_L is 1 + * AP Suspend (ex. Intel S0ix): SLP_L is 0 + * The alternative SLP_ALT_L should be pulled high at all the times. + * + * Legacy Intel behavior: + * in S3: SLP_ALT_L is 0 and SLP_L is X. + * in S0ix: SLP_ALT_L is X and SLP_L is 0. + * in S0: SLP_ALT_L is 1 and SLP_L is 1. + * in S5/G3, the FP MCU should not be running. + */ + int running = gpio_get_level(gpio_slp_alt_l) && + gpio_get_level(GPIO_SLP_L); + + if (running) { /* AP is S0 */ + disable_sleep(SLEEP_MASK_AP_RUN); + hook_notify(HOOK_CHIPSET_RESUME); + } else { /* AP is suspend/S0ix/S3 */ + hook_notify(HOOK_CHIPSET_SUSPEND); + enable_sleep(SLEEP_MASK_AP_RUN); + } +} +DECLARE_DEFERRED(ap_deferred); + +/* PCH power state changes */ +void slp_event(enum gpio_signal signal) +{ + hook_call_deferred(&ap_deferred_data, 0); +} + +static void spi_configure(enum fp_sensor_spi_select spi_select) +{ + if (spi_select == FP_SENSOR_SPI_SELECT_DEVELOPMENT) { + /* SPI4 master to sensor: PE12/13/14 (CLK/MISO/MOSI) */ + gpio_set_flags_by_mask(GPIO_E, 0x7000, 0); + gpio_set_alternate_function(GPIO_E, 0x7000, GPIO_ALT_SPI); + } else { + gpio_config_module(MODULE_SPI_CONTROLLER, 1); + } + + /* Set all SPI controller signal pins to very high speed: + * pins E2/4/5/6 + */ + STM32_GPIO_OSPEEDR(GPIO_E) |= 0x00003f30; + /* Enable clocks to SPI4 module (master) */ + STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI4; + + if (spi_select == FP_SENSOR_SPI_SELECT_DEVELOPMENT) + spi_devices[0].gpio_cs = GPIO_SPI4_ALT_NSS; + spi_enable(&spi_devices[0], 1); +} + +void board_init(void) +{ + enum fp_sensor_spi_select spi_select = fpsensor_detect_get_spi_select(); + + /* + * FP_RST_ODL pin is defined in gpio_rw.inc (with GPIO_OUT_HIGH + * flag) but not in gpio.inc, so RO leaves this pin set to 0 (reset + * default), but RW doesn't initialize this pin to 1 because sysjump + * to RW is a warm reset (see gpio_pre_init() in chip/stm32/gpio.c). + * Explicitly reset FP_RST_ODL pin to default value. + */ + gpio_reset(GPIO_FP_RST_ODL); + + ccprints("FP_SPI_SEL: %s", fp_sensor_spi_select_to_str(spi_select)); + + spi_configure(spi_select); + + ccprints("TRANSPORT_SEL: %s", + fp_transport_type_to_str(get_fp_transport_type())); + + /* Use SPI select as a proxy for running on the icetower dev board. */ + if (spi_select == FP_SENSOR_SPI_SELECT_DEVELOPMENT) + gpio_slp_alt_l = GPIO_SLP_ALT_DEV_L; + + /* Enable interrupt on PCH power signals */ + gpio_enable_interrupt(gpio_slp_alt_l); + gpio_enable_interrupt(GPIO_SLP_L); + + /* + * Enable the SPI peripheral interface if the PCH is up. + * Do not use hook_call_deferred(), because ap_deferred() will be + * called after tasks with priority higher than HOOK task (very late). + */ + ap_deferred(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/nocturne_fp/board_rw.h b/board/nocturne_fp/board_rw.h new file mode 100644 index 0000000000..ebb0892829 --- /dev/null +++ b/board/nocturne_fp/board_rw.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_NOCTURNE_FP_BOARD_RW_H +#define __CROS_EC_BOARD_NOCTURNE_FP_BOARD_RW_H + +#include "config.h" +#include "gpio_signal.h" + +void fps_event(enum gpio_signal signal); + +/* Defined in ro_workarounds.c */ +void wp_event(enum gpio_signal signal); + +#endif /* __CROS_EC_BOARD_NOCTURNE_FP_BOARD_RW_H */ diff --git a/board/nocturne_fp/build.mk b/board/nocturne_fp/build.mk index fca1dc62e3..9116581442 100644 --- a/board/nocturne_fp/build.mk +++ b/board/nocturne_fp/build.mk @@ -1,4 +1,4 @@ -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -9,25 +9,70 @@ CHIP:=stm32 CHIP_FAMILY:=stm32h7 CHIP_VARIANT:=stm32h7x3 -board-rw=ro_workarounds.o -board-y=board.o fpsensor_detect.o +# Don't forget that the board build.mk is included more than once to allow +# conditional variables to be realized. This means that we need to redefine all +# variable or the "+=" lines will compound. +board-y= +board-rw=ro_workarounds.o board_rw.o +board-ro=board_ro.o +# If we're mocking the sensor detection for testing (so we can test +# sensor/transport permutations in the unit tests), don't build the real sensor +# detection. +ifeq ($(HAS_MOCK_FPSENSOR_DETECT),) + board-rw+=fpsensor_detect_rw.o + board-y+=fpsensor_detect.o +endif +# Do not build rsa test because this board uses RSA exponent 3 and the rsa test +# will fail on device. test-list-y=\ + abort \ aes \ + always_memset \ + benchmark \ + boringssl_crypto \ compile_time_macros \ - crc32 \ + cortexm_fpu \ + crc \ + debug \ + exception \ flash_physical \ flash_write_protect \ + fpsensor \ + fpsensor_auth_crypto_stateful \ + fpsensor_auth_crypto_stateless \ + fpsensor_hw \ + ftrapv \ + global_initialization \ + libc_printf \ + libcxx \ + malloc \ mpu \ mutex \ + panic \ + panic_data \ pingpong \ + printf \ + queue \ + rng_benchmark \ rollback \ rollback_entropy \ - rsa \ rsa3 \ rtc \ + sbrk \ scratchpad \ sha256 \ sha256_unrolled \ - stm32f_rtc \ + static_if \ + stdlib \ + std_vector \ + system_is_locked \ + timer \ + timer_dos \ + tpm_seed_clear \ utils \ + utils_str \ + +# Note that this variable includes the trailing "/" +_nocturne_fp_cur_dir:=$(dir $(lastword $(MAKEFILE_LIST))) +-include $(_nocturne_fp_cur_dir)../../private/board/nocturne_fp/build.mk diff --git a/board/nocturne_fp/ec.tasklist b/board/nocturne_fp/ec.tasklist index ed1e6ed294..79b8531751 100644 --- a/board/nocturne_fp/ec.tasklist +++ b/board/nocturne_fp/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,5 +10,5 @@ TASK_ALWAYS_RO(RWSIG, rwsig_task, NULL, 1280) \ TASK_ALWAYS(HOOKS, hook_task, NULL, 1024) \ TASK_ALWAYS_RW(FPSENSOR, fp_task, NULL, 4096) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 4096) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 6144) \ TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) diff --git a/board/nocturne_fp/fpsensor_detect.c b/board/nocturne_fp/fpsensor_detect.c index 72b9b89e11..2541aa3c68 100644 --- a/board/nocturne_fp/fpsensor_detect.c +++ b/board/nocturne_fp/fpsensor_detect.c @@ -1,15 +1,10 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "fpsensor_detect.h" -enum fp_sensor_type get_fp_sensor_type(void) -{ - return FP_SENSOR_TYPE_FPC; -} - enum fp_transport_type get_fp_transport_type(void) { return FP_TRANSPORT_TYPE_SPI; diff --git a/board/nocturne_fp/fpsensor_detect_rw.c b/board/nocturne_fp/fpsensor_detect_rw.c new file mode 100644 index 0000000000..adc2690998 --- /dev/null +++ b/board/nocturne_fp/fpsensor_detect_rw.c @@ -0,0 +1,34 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "fpsensor_detect.h" +#include "gpio.h" +#include "timer.h" + +enum fp_sensor_type fpsensor_detect_get_type(void) +{ + return FP_SENSOR_TYPE_FPC; +} + +enum fp_sensor_spi_select fpsensor_detect_get_spi_select(void) +{ + enum fp_sensor_spi_select ret; + + gpio_set_level(GPIO_DIVIDER_HIGHSIDE, 1); + usleep(1); + switch (gpio_get_level(GPIO_FP_SPI_SEL)) { + case 0: + ret = FP_SENSOR_SPI_SELECT_DEVELOPMENT; + break; + case 1: + ret = FP_SENSOR_SPI_SELECT_PRODUCTION; + break; + default: + ret = FP_SENSOR_SPI_SELECT_UNKNOWN; + break; + } + gpio_set_level(GPIO_DIVIDER_HIGHSIDE, 0); + return ret; +} diff --git a/board/nocturne_fp/gpio.inc b/board/nocturne_fp/gpio.inc index 48a15209ba..b0e1c3a80b 100644 --- a/board/nocturne_fp/gpio.inc +++ b/board/nocturne_fp/gpio.inc @@ -1,29 +1,21 @@ /* - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Interrupts */ -GPIO_INT(FPS_INT, PIN(A, 0), GPIO_INT_RISING, fps_event) +GPIO_INT(SLP_L, PIN(D,13), GPIO_INT_BOTH, slp_event) +GPIO_INT(SLP_ALT_L, PIN(A,11), GPIO_INT_BOTH, slp_event) GPIO_INT(SPI1_NSS, PIN(A, 4), GPIO_INPUT, spi_event) -GPIO_INT(PCH_SLP_S0_L, PIN(D,13), GPIO_INT_BOTH, slp_event) -GPIO_INT(PCH_SLP_S3_L, PIN(A,11), GPIO_INT_BOTH, slp_event) - -GPIO(PCH_SLP_S4_L, PIN(D, 8), GPIO_INPUT) -GPIO(PCH_SLP_SUS_L, PIN(D, 3), GPIO_INPUT) -#if defined(APPLY_RESET_LOOP_FIX) && defined(SECTION_IS_RW) -GPIO_INT(WP, PIN(B, 7), GPIO_INT_BOTH, wp_event) -#else +/* Inputs */ +#ifndef APPLY_RESET_LOOP_FIX GPIO(WP, PIN(B, 7), GPIO_INPUT) #endif /* Outputs */ GPIO(EC_INT_L, PIN(A, 1), GPIO_OUT_HIGH) -GPIO(FP_RST_ODL, PIN(E, 0), GPIO_OUT_HIGH) -GPIO(SPI4_NSS, PIN(E, 4), GPIO_OUT_HIGH) -GPIO(USER_PRES_L, PIN(C, 5), GPIO_ODR_HIGH) UNIMPLEMENTED(ENTERING_RW) @@ -31,5 +23,7 @@ UNIMPLEMENTED(ENTERING_RW) ALTERNATE(PIN_MASK(A, 0x0600), GPIO_ALT_USART, MODULE_UART, GPIO_PULL_UP) /* SPI1 slave from the AP: PA4/5/6/7 (CS/CLK/MISO/MOSI) */ ALTERNATE(PIN_MASK(A, 0x00f0), GPIO_ALT_SPI, MODULE_SPI, 0) -/* SPI4 master to sensor: PE2/5/6 (CLK/MISO/MOSI) */ -ALTERNATE(PIN_MASK(E, 0x0064), GPIO_ALT_SPI, MODULE_SPI_MASTER, 0) + +#ifdef SECTION_IS_RW +#include "gpio_rw.inc" +#endif diff --git a/board/nocturne_fp/gpio_rw.inc b/board/nocturne_fp/gpio_rw.inc new file mode 100644 index 0000000000..9ee3af139f --- /dev/null +++ b/board/nocturne_fp/gpio_rw.inc @@ -0,0 +1,45 @@ +/* + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SECTION_IS_RW +#error "This file should only be included in RW." +#endif + +/* Interrupts */ +GPIO_INT(FPS_INT, PIN(A, 0), GPIO_INT_RISING, fps_event) + +#ifdef APPLY_RESET_LOOP_FIX +GPIO_INT(WP, PIN(B, 7), GPIO_INT_BOTH, wp_event) +#endif + +/* Inputs */ +GPIO_INT(SLP_ALT_DEV_L, PIN(D,14), GPIO_INT_BOTH, slp_event) +/* + * The S4 and SUS sleep lines are unused in code, but are maintained in this + * gpio list to ensure that they are not repurposed. This is because these + * inputs are driven on nocturne. + */ +GPIO(PCH_SLP_S4_L, PIN(D, 8), GPIO_INPUT) +GPIO(PCH_SLP_SUS_L, PIN(D, 3), GPIO_INPUT) +/* TODO(b/178808871): Only enable pull up when doing detection. */ +GPIO(FP_SPI_SEL, PIN(E, 1), GPIO_INPUT | GPIO_PULL_UP) + +/* Outputs */ +GPIO(DIVIDER_HIGHSIDE, PIN(B, 8), GPIO_OUT_LOW) +GPIO(FP_RST_ODL, PIN(E, 0), GPIO_OUT_HIGH) +GPIO(SPI4_NSS, PIN(E, 4), GPIO_OUT_HIGH) +GPIO(SPI4_ALT_NSS, PIN(E, 11), GPIO_OUT_HIGH) +GPIO(USER_PRES_L, PIN(C, 5), GPIO_ODR_HIGH) + +/* Default SPI4 master to sensor: PE2/5/6 (CLK/MISO/MOSI) */ +ALTERNATE(PIN_MASK(E, 0x0064), GPIO_ALT_SPI, MODULE_SPI_CONTROLLER, 0) + +/* See board_rw.c for the alternate configuration that we use on + * development boards, which overrides the UNUSED values below. + */ +UNUSED(PIN(E, 12)) /* Alternate SPI4 master to sensor CLK */ +UNUSED(PIN(E, 13)) /* Alternate SPI4 master to sensor MISO */ +UNUSED(PIN(E, 14)) /* Alternate SPI4 master to sensor MOSI */ diff --git a/board/nocturne_fp/ro_workarounds.c b/board/nocturne_fp/ro_workarounds.c index 333f1ed9da..92f7dacd28 100644 --- a/board/nocturne_fp/ro_workarounds.c +++ b/board/nocturne_fp/ro_workarounds.c @@ -1,13 +1,10 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* A place to organize workarounds for legacy RO */ -#include -#include - #include "bkpdata.h" #include "common.h" #include "console.h" @@ -18,8 +15,11 @@ #include "task.h" #include "watchdog.h" +#include +#include + /* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /* * We only patch RW to ensure that future ROs have correct behavior. @@ -30,7 +30,7 @@ * Add in ap-off flag to be able to detect on next boot. * No other code in this build uses this ap-off reset flag. */ -#define FORGE_PORFLAG_FLAGS (EC_RESET_FLAG_POWER_ON|EC_RESET_FLAG_AP_OFF) +#define FORGE_PORFLAG_FLAGS (EC_RESET_FLAG_POWER_ON | EC_RESET_FLAG_AP_OFF) static void wp_change_deferred(void) { @@ -75,20 +75,15 @@ void wp_event(enum gpio_signal signal) * This function is also called from system_reset to set the final save * reset flags, before an actual planned reset. */ -__override -void bkpdata_write_reset_flags(uint32_t save_flags) +__override void bkpdata_write_reset_flags(uint32_t save_flags) { /* Preserve flags in case a reset pulse occurs */ if (!gpio_get_level(GPIO_WP)) save_flags |= FORGE_PORFLAG_FLAGS; -#ifdef CONFIG_STM32_RESET_FLAGS_EXTENDED bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS, save_flags & 0xffff); +#ifdef CONFIG_STM32_EXTENDED_RESET_FLAGS bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS_2, save_flags >> 16); -#else - /* Reset flags are 32-bits, but BBRAM entry is only 16 bits. */ - ASSERT(!(save_flags >> 16)); - bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS, save_flags); #endif } diff --git a/board/npcx7_evb/board.c b/board/npcx7_evb/board.c index 5fa421d917..250f963b88 100644 --- a/board/npcx7_evb/board.c +++ b/board/npcx7_evb/board.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Nuvoton M4 EB board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "chipset.h" #include "common.h" @@ -28,27 +27,33 @@ #include "switch.h" #include "temp_sensor.h" #include "temp_sensor_chip.h" -#include "timer.h" #include "thermal.h" +#include "timer.h" #include "util.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_CH_0] = {"ADC0", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_1] = {"ADC1", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_2] = {"ADC2", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_3] = {"ADC3", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_4] = {"ADC4", NPCX_ADC_CH4, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_CH_0] = { "ADC0", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_1] = { "ADC1", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_2] = { "ADC2", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_3] = { "ADC3", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_4] = { "ADC4", NPCX_ADC_CH4, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_FAN] = { 0, PWM_CONFIG_OPEN_DRAIN, 25000}, + [PWM_CH_FAN] = { 0, PWM_CONFIG_OPEN_DRAIN, 25000 }, [PWM_CH_KBLIGHT] = { 2, 0, 10000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -57,7 +62,7 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = 0, /* Use MFT id to control fan */ + .ch = 0, /* Use MFT id to control fan */ .pgood_gpio = GPIO_PGOOD_FAN, .enable_gpio = -1, }; @@ -76,25 +81,45 @@ BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master0-0", NPCX_I2C_PORT0_0, 100, GPIO_I2C0_SCL0, GPIO_I2C0_SDA0}, - {"master1-0", NPCX_I2C_PORT1_0, 100, GPIO_I2C1_SCL0, GPIO_I2C1_SDA0}, - {"master2-0", NPCX_I2C_PORT2_0, 100, GPIO_I2C2_SCL0, GPIO_I2C2_SDA0}, - {"master3-0", NPCX_I2C_PORT3_0, 100, GPIO_I2C3_SCL0, GPIO_I2C3_SDA0}, - {"master7-0", NPCX_I2C_PORT7_0, 100, GPIO_I2C7_SCL0, GPIO_I2C7_SDA0}, + { .name = "master0-0", + .port = NPCX_I2C_PORT0_0, + .kbps = 100, + .scl = GPIO_I2C0_SCL0, + .sda = GPIO_I2C0_SDA0 }, + { .name = "master1-0", + .port = NPCX_I2C_PORT1_0, + .kbps = 100, + .scl = GPIO_I2C1_SCL0, + .sda = GPIO_I2C1_SDA0 }, + { .name = "master2-0", + .port = NPCX_I2C_PORT2_0, + .kbps = 100, + .scl = GPIO_I2C2_SCL0, + .sda = GPIO_I2C2_SDA0 }, + { .name = "master3-0", + .port = NPCX_I2C_PORT3_0, + .kbps = 100, + .scl = GPIO_I2C3_SCL0, + .sda = GPIO_I2C3_SDA0 }, + { .name = "master7-0", + .port = NPCX_I2C_PORT7_0, + .kbps = 100, + .scl = GPIO_I2C7_SCL0, + .sda = GPIO_I2C7_SDA0 }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /******************************************************************************/ /* SPI devices */ const struct spi_device_t spi_devices[] = { - { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS_L}, + { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS_L }, }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); @@ -109,7 +134,7 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /******************************************************************************/ /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { .output_settle_us = 40, .debounce_down_us = 6 * MSEC, .debounce_up_us = 30 * MSEC, diff --git a/board/npcx7_evb/board.h b/board/npcx7_evb/board.h index 6d36f901b0..ae3392ab16 100644 --- a/board/npcx7_evb/board.h +++ b/board/npcx7_evb/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,11 +15,11 @@ * npcx7m6f/npcx7m6fb/npcx7m6fc/npcx7m7fc/npcx7m7wb/npcx7m7wc */ #if defined(CHIP_VARIANT_NPCX7M6G) -#define BOARD_VERSION 1 -#elif defined(CHIP_VARIANT_NPCX7M6F) || defined(CHIP_VARIANT_NPCX7M6FB) || \ +#define BOARD_VERSION 1 +#elif defined(CHIP_VARIANT_NPCX7M6F) || defined(CHIP_VARIANT_NPCX7M6FB) || \ defined(CHIP_VARIANT_NPCX7M6FC) || defined(CHIP_VARIANT_NPCX7M7FC) || \ defined(CHIP_VARIANT_NPCX7M7WB) || defined(CHIP_VARIANT_NPCX7M7WC) -#define BOARD_VERSION 2 +#define BOARD_VERSION 2 #endif /* EC modules */ @@ -28,27 +28,26 @@ #define CONFIG_SPI #define CONFIG_I2C /* Features of eSPI */ -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 /* Optional features */ #define CONFIG_ENABLE_JTAG_SELECTION #define CONFIG_BOARD_VERSION_GPIO #define CONFIG_EXTPOWER_GPIO -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_I2C_CONTROLLER + #define CONFIG_KEYBOARD_PROTOCOL_8042 -#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ +#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ #define CONFIG_POWER_BUTTON -#undef CONFIG_PSTORE +#undef CONFIG_PSTORE #define CONFIG_PWM_KBLIGHT #define CONFIG_VBOOT_HASH #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands */ /* EC console commands */ #define CONFIG_CMD_TASKREADY -#define CONFIG_CMD_STACKOVERFLOW #define CONFIG_CMD_JUMPTAGS #define CONFIG_CMD_FLASH #define CONFIG_CMD_SPI_FLASH @@ -57,7 +56,7 @@ /* I2C port for CONFIG_CMD_I2CWEDGE */ #define I2C_PORT_MASTER NPCX_I2C_PORT0_0 -#define I2C_PORT_HOST 0 +#define I2C_PORT_HOST 0 /* Fans for testing */ #define CONFIG_FANS 1 @@ -69,10 +68,10 @@ #if defined(CHIP_VARIANT_NPCX7M6FC) || defined(CHIP_VARIANT_NPCX7M7FC) || \ defined(CHIP_VARIANT_NPCX7M7WC) #define CONFIG_SPI_FLASH_W25Q40 /* Internal spi flash type */ -#define CONFIG_FLASH_SIZE 0x00080000 /* 512 KB internal spi flash */ +#define CONFIG_FLASH_SIZE_BYTES 0x00080000 /* 512 KB internal spi flash */ #else #define CONFIG_SPI_FLASH_W25Q80 /* Internal spi flash type */ -#define CONFIG_FLASH_SIZE 0x00100000 /* 1 MB internal spi flash */ +#define CONFIG_FLASH_SIZE_BYTES 0x00100000 /* 1 MB internal spi flash */ #endif /* New features on npcx7 ec */ @@ -86,7 +85,6 @@ #define CONFIG_AUDIO_CODEC_I2S_RX /* Use Audio front-end for Wake-on-Voice */ #endif #undef CONFIG_FANS /* Remove fan application */ -#define CONFIG_FANS 0 #else #undef CONFIG_HIBERNATE_PSL /* Use PSL (Power Switch Logic) for hibernate */ #undef CONFIG_CLOCK_SRC_EXTERNAL /* Use external 32kHz OSC as LFCLK source */ @@ -96,20 +94,20 @@ /* Select which UART Controller is the Console UART */ #undef CONFIG_CONSOLE_UART -#define CONFIG_CONSOLE_UART 0 /* 0:UART1 1:UART2 */ +#define CONFIG_CONSOLE_UART 0 /* 0:UART1 1:UART2 */ /* * This definition below actually doesn't define which UART controller to be * used. Instead, it defines which pinouts (GPIO10/11 or GPIO64/65) are * connected to "UART1" controller. */ #if (BOARD_VERSION == 2) -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART1 */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART1 */ #else -#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 as UART1 */ +#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 as UART1 */ #endif -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG */ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ -#define NPCX7_PWM1_SEL 0 /* 0:GPIOC2 as I2CSCL0 1:as PWM1 (only in npcx7) */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG */ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX7_PWM1_SEL 0 /* 0:GPIOC2 as I2CSCL0 1:as PWM1 (only in npcx7) */ #ifndef __ASSEMBLER__ diff --git a/board/npcx7_evb/build.mk b/board/npcx7_evb/build.mk index 4bd829202c..e51c3bdc5c 100644 --- a/board/npcx7_evb/build.mk +++ b/board/npcx7_evb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/npcx7_evb/ec.tasklist b/board/npcx7_evb/ec.tasklist index 88b5ffaa62..24e3b42d7c 100644 --- a/board/npcx7_evb/ec.tasklist +++ b/board/npcx7_evb/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/npcx7_evb/gpio.inc b/board/npcx7_evb/gpio.inc index 145a48de85..b8cfa1d8d5 100644 --- a/board/npcx7_evb/gpio.inc +++ b/board/npcx7_evb/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/npcx9_evb/board.c b/board/npcx9_evb/board.c index 892c0d1031..27b1651a0c 100644 --- a/board/npcx9_evb/board.c +++ b/board/npcx9_evb/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,10 +6,10 @@ /* Nuvoton M4 EB board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "chipset.h" #include "common.h" +#include "driver/temp_sensor/tmp112.h" #include "extpower.h" #include "fan.h" #include "fan_chip.h" @@ -27,34 +27,47 @@ #include "switch.h" #include "temp_sensor.h" #include "temp_sensor_chip.h" -#include "timer.h" #include "thermal.h" +#include "timer.h" #include "util.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_CH_0] = {"ADC0", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_1] = {"ADC1", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_2] = {"ADC2", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_3] = {"ADC3", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_4] = {"ADC4", NPCX_ADC_CH4, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_5] = {"ADC5", NPCX_ADC_CH5, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_6] = {"ADC6", NPCX_ADC_CH6, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_7] = {"ADC7", NPCX_ADC_CH7, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_8] = {"ADC8", NPCX_ADC_CH8, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_9] = {"ADC9", NPCX_ADC_CH9, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_10] = {"ADC10", NPCX_ADC_CH10, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_11] = {"ADC11", NPCX_ADC_CH11, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_CH_0] = { "ADC0", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_1] = { "ADC1", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_2] = { "ADC2", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_3] = { "ADC3", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_4] = { "ADC4", NPCX_ADC_CH4, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_5] = { "ADC5", NPCX_ADC_CH5, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_6] = { "ADC6", NPCX_ADC_CH6, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_7] = { "ADC7", NPCX_ADC_CH7, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_8] = { "ADC8", NPCX_ADC_CH8, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_9] = { "ADC9", NPCX_ADC_CH9, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_10] = { "ADC10", NPCX_ADC_CH10, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_11] = { "ADC11", NPCX_ADC_CH11, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_FAN] = { 0, PWM_CONFIG_OPEN_DRAIN, 25000}, + [PWM_CH_FAN] = { 0, PWM_CONFIG_OPEN_DRAIN, 25000 }, [PWM_CH_KBLIGHT] = { 2, 0, 10000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -63,7 +76,7 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = 0, /* Use MFT id to control fan */ + .ch = 0, /* Use MFT id to control fan */ .pgood_gpio = GPIO_PGOOD_FAN, .enable_gpio = -1, }; @@ -79,31 +92,58 @@ const struct fan_t fans[] = { }; BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); +/******************************************************************************/ +/* TMP112 sensors. Must be in the exactly same order as in enum tmp112_sensor */ +const struct tmp112_sensor_t tmp112_sensors[] = { + { I2C_PORT_THERMAL, TMP112_I2C_ADDR_FLAGS0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(tmp112_sensors) == TMP112_COUNT); + +/******************************************************************************/ +/* Temperature sensor. */ +const struct temp_sensor_t temp_sensors[] = { + { "System", TEMP_SENSOR_TYPE_BOARD, tmp112_get_val_k, TMP112_0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master0-0", NPCX_I2C_PORT0_0, 100, GPIO_I2C0_SCL0, GPIO_I2C0_SDA0}, - {"master1-0", NPCX_I2C_PORT1_0, 100, GPIO_I2C1_SCL0, GPIO_I2C1_SDA0}, - {"master2-0", NPCX_I2C_PORT2_0, 100, GPIO_I2C2_SCL0, GPIO_I2C2_SDA0}, - {"master3-0", NPCX_I2C_PORT3_0, 100, GPIO_I2C3_SCL0, GPIO_I2C3_SDA0}, - {"master7-0", NPCX_I2C_PORT7_0, 100, GPIO_I2C7_SCL0, GPIO_I2C7_SDA0}, + { .name = "master0-0", + .port = NPCX_I2C_PORT0_0, + .kbps = 100, + .scl = GPIO_I2C0_SCL0, + .sda = GPIO_I2C0_SDA0 }, + { .name = "master1-0", + .port = NPCX_I2C_PORT1_0, + .kbps = 100, + .scl = GPIO_I2C1_SCL0, + .sda = GPIO_I2C1_SDA0 }, + { .name = "master2-0", + .port = NPCX_I2C_PORT2_0, + .kbps = 100, + .scl = GPIO_I2C2_SCL0, + .sda = GPIO_I2C2_SDA0 }, + { .name = "master3-0", + .port = NPCX_I2C_PORT3_0, + .kbps = 100, + .scl = GPIO_I2C3_SCL0, + .sda = GPIO_I2C3_SDA0 }, + { .name = "master7-0", + .port = NPCX_I2C_PORT7_0, + .kbps = 100, + .scl = GPIO_I2C7_SCL0, + .sda = GPIO_I2C7_SDA0 }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -/******************************************************************************/ -/* SPI devices */ -const struct spi_device_t spi_devices[] = { - { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS_L}, -}; -const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); - /******************************************************************************/ /* Wake-up pins for hibernate */ const enum gpio_signal hibernate_wake_pins[] = { @@ -115,7 +155,7 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /******************************************************************************/ /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { .output_settle_us = 40, .debounce_down_us = 6 * MSEC, .debounce_up_us = 30 * MSEC, diff --git a/board/npcx9_evb/board.h b/board/npcx9_evb/board.h index cac7ea99be..a613a712f5 100644 --- a/board/npcx9_evb/board.h +++ b/board/npcx9_evb/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,43 +11,46 @@ /* EC modules */ #define CONFIG_ADC #define CONFIG_PWM -#define CONFIG_SPI #define CONFIG_I2C /* Features of eSPI */ -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 /* Optional features */ #define CONFIG_ENABLE_JTAG_SELECTION #define CONFIG_BOARD_VERSION_GPIO #define CONFIG_EXTPOWER_GPIO -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_HIBERNATE_PSL_COMPENSATE_RTC +#define CONFIG_I2C_CONTROLLER + #define CONFIG_KEYBOARD_PROTOCOL_8042 -#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ +#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ #define CONFIG_POWER_BUTTON -#undef CONFIG_PSTORE +#undef CONFIG_PSTORE #define CONFIG_PWM_KBLIGHT #define CONFIG_VBOOT_HASH #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands */ /* EC console commands */ #define CONFIG_CMD_TASKREADY -#define CONFIG_CMD_STACKOVERFLOW #define CONFIG_CMD_JUMPTAGS #define CONFIG_CMD_FLASH -#define CONFIG_CMD_SPI_FLASH +#define CONFIG_CMD_RTC #define CONFIG_CMD_SCRATCHPAD #define CONFIG_CMD_I2CWEDGE /* I2C port for CONFIG_CMD_I2CWEDGE */ #define I2C_PORT_MASTER NPCX_I2C_PORT0_0 -#define I2C_PORT_HOST 0 +#define I2C_PORT_HOST 0 /* Fans for testing */ #define CONFIG_FANS 1 +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_TMP112 +#define I2C_PORT_THERMAL NPCX_I2C_PORT2_0 + #define CONFIG_KEYBOARD_KSO_HIGH_DRIVE /* Quasi-bidirectional buf for KSOs */ #define CONFIG_HIBERNATE_PSL /* Use PSL (Power Switch Logic) for hibernate */ #undef CONFIG_CLOCK_SRC_EXTERNAL /* Use external 32kHz OSC as LFCLK source */ @@ -56,15 +59,15 @@ /* Select which UART Controller is the Console UART */ #undef CONFIG_CONSOLE_UART -#define CONFIG_CONSOLE_UART 0 /* 0:UART1 1:UART2 */ +#define CONFIG_CONSOLE_UART 0 /* 0:UART1 1:UART2 */ /* * This definition below actually doesn't define which UART controller to be * used. Instead, it defines which pinouts (GPIO10/11 or GPIO64/65) are * connected to "UART1" controller. */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART1 */ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ -#define NPCX9_PWM1_SEL 0 /* 0:GPIOC2 as I2CSCL0 1:as PWM1 */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART1 */ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX9_PWM1_SEL 0 /* 0:GPIOC2 as I2CSCL0 1:as PWM1 */ #ifndef __ASSEMBLER__ @@ -84,6 +87,16 @@ enum adc_channel { ADC_CH_COUNT }; +enum tmp112_sensor { + TMP112_0, + TMP112_COUNT, +}; + +enum temp_sensor_id { + TEMP_SENSOR_SYSTHERM0, /* TMP100 */ + TEMP_SENSOR_COUNT +}; + enum pwm_channel { PWM_CH_FAN, PWM_CH_KBLIGHT, @@ -104,6 +117,7 @@ enum mft_channel { }; #include "gpio_signal.h" +#include "registers.h" #endif /* !__ASSEMBLER__ */ diff --git a/board/npcx9_evb/build.mk b/board/npcx9_evb/build.mk index 92bcc84144..d2526afb1b 100644 --- a/board/npcx9_evb/build.mk +++ b/board/npcx9_evb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/npcx9_evb/ec.tasklist b/board/npcx9_evb/ec.tasklist index 9560b43561..d41f0ade2f 100644 --- a/board/npcx9_evb/ec.tasklist +++ b/board/npcx9_evb/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/npcx9_evb/gpio.inc b/board/npcx9_evb/gpio.inc index ec57c1afc5..28dbbba93a 100644 --- a/board/npcx9_evb/gpio.inc +++ b/board/npcx9_evb/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/npcx_evb/board.c b/board/npcx_evb/board.c index cee9acfeef..dab80f8531 100644 --- a/board/npcx_evb/board.c +++ b/board/npcx_evb/board.c @@ -1,11 +1,10 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* EC for Nuvoton M4 EB configuration */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "chipset.h" #include "common.h" @@ -27,25 +26,29 @@ #include "switch.h" #include "temp_sensor.h" #include "temp_sensor_chip.h" -#include "timer.h" #include "thermal.h" +#include "timer.h" #include "util.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_CH_0] = {"ADC0", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_1] = {"ADC1", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_2] = {"ADC2", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_CH_0] = { "ADC0", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_1] = { "ADC1", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_2] = { "ADC2", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_FAN] = { 0, PWM_CONFIG_OPEN_DRAIN, 25000}, + [PWM_CH_FAN] = { 0, PWM_CONFIG_OPEN_DRAIN, 25000 }, #if (CONFIG_FANS == 2) [PWM_CH_FAN2] = { 2, 0, 25000 }, #endif @@ -57,14 +60,14 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = 0, /* Use MFT id to control fan */ + .ch = 0, /* Use MFT id to control fan */ .pgood_gpio = GPIO_PGOOD_FAN, .enable_gpio = -1, }; const struct fan_conf fan_conf_1 = { .flags = FAN_USE_RPM_MODE, - .ch = 1, /* Use MFT id to control fan */ + .ch = 1, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = -1, }; @@ -92,9 +95,9 @@ BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, #if (CONFIG_FANS == 2) - [MFT_CH_1] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN2}, + [MFT_CH_1] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN2 }, #endif }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); @@ -102,18 +105,38 @@ BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master0-0", NPCX_I2C_PORT0_0, 100, GPIO_I2C0_SCL0, GPIO_I2C0_SDA0}, - {"master0-1", NPCX_I2C_PORT0_1, 100, GPIO_I2C0_SCL1, GPIO_I2C0_SDA1}, - {"master1", NPCX_I2C_PORT1, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"master2", NPCX_I2C_PORT2, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"master3", NPCX_I2C_PORT3, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, + { .name = "master0-0", + .port = NPCX_I2C_PORT0_0, + .kbps = 100, + .scl = GPIO_I2C0_SCL0, + .sda = GPIO_I2C0_SDA0 }, + { .name = "master0-1", + .port = NPCX_I2C_PORT0_1, + .kbps = 100, + .scl = GPIO_I2C0_SCL1, + .sda = GPIO_I2C0_SDA1 }, + { .name = "master1", + .port = NPCX_I2C_PORT1, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "master2", + .port = NPCX_I2C_PORT2, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "master3", + .port = NPCX_I2C_PORT3, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /******************************************************************************/ /* SPI devices */ const struct spi_device_t spi_devices[] = { - { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS_L}, + { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS_L }, }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); @@ -126,7 +149,7 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /******************************************************************************/ /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { .output_settle_us = 40, .debounce_down_us = 6 * MSEC, .debounce_up_us = 30 * MSEC, diff --git a/board/npcx_evb/board.h b/board/npcx_evb/board.h index d7b7b6162a..08cf1176d3 100644 --- a/board/npcx_evb/board.h +++ b/board/npcx_evb/board.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,19 +12,19 @@ #define CONFIG_ADC #define CONFIG_PWM #define CONFIG_SPI -#define CONFIG_HOSTCMD_LPC +#define CONFIG_HOST_INTERFACE_LPC #define CONFIG_PECI /* Optional features */ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */ #define CONFIG_SPI_FLASH_PORT 0 #define CONFIG_SPI_FLASH -#define CONFIG_FLASH_SIZE 0x00800000 /* 8MB spi flash */ +#define CONFIG_FLASH_SIZE_BYTES 0x00800000 /* 8MB spi flash */ #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q64 #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_I2C_CONTROLLER + #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_POWER_BUTTON #define CONFIG_VBOOT_HASH @@ -34,36 +34,30 @@ /* Optional features for test commands */ #define CONFIG_CMD_TASKREADY -#define CONFIG_CMD_STACKOVERFLOW #define CONFIG_CMD_JUMPTAGS #define CONFIG_CMD_FLASH #define CONFIG_CMD_SPI_FLASH #define CONFIG_CMD_SCRATCHPAD #define CONFIG_CMD_I2CWEDGE -#define CONFIG_FANS 1 +#define CONFIG_FANS 1 /* Optional feature - used by nuvoton */ -#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ /* Optional for testing */ -#undef CONFIG_PSTORE -#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ +#undef CONFIG_PSTORE +#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ /* Single I2C port, where the EC is the master. */ -#define I2C_PORT_MASTER NPCX_I2C_PORT0_0 -#define I2C_PORT_HOST 0 +#define I2C_PORT_MASTER NPCX_I2C_PORT0_0 +#define I2C_PORT_HOST 0 #ifndef __ASSEMBLER__ -enum adc_channel { - ADC_CH_0 = 0, - ADC_CH_1, - ADC_CH_2, - ADC_CH_COUNT -}; +enum adc_channel { ADC_CH_0 = 0, ADC_CH_1, ADC_CH_2, ADC_CH_COUNT }; enum pwm_channel { PWM_CH_FAN, diff --git a/board/npcx_evb/build.mk b/board/npcx_evb/build.mk index 7dfc4544f2..c86457489f 100644 --- a/board/npcx_evb/build.mk +++ b/board/npcx_evb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/npcx_evb/ec.tasklist b/board/npcx_evb/ec.tasklist index b0d584174e..82d4d031a2 100644 --- a/board/npcx_evb/ec.tasklist +++ b/board/npcx_evb/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/npcx_evb/gpio.inc b/board/npcx_evb/gpio.inc index c4e673fd25..584cbfd9b2 100644 --- a/board/npcx_evb/gpio.inc +++ b/board/npcx_evb/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/npcx_evb_arm/board.c b/board/npcx_evb_arm/board.c index f99ab2e0f6..28b72d5f3c 100644 --- a/board/npcx_evb_arm/board.c +++ b/board/npcx_evb_arm/board.c @@ -1,11 +1,10 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* EC for Nuvoton M4 EB configuration */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "chipset.h" #include "common.h" @@ -23,29 +22,33 @@ #include "pwm.h" #include "pwm_chip.h" #include "registers.h" +#include "shi_chip.h" #include "switch.h" #include "temp_sensor.h" #include "temp_sensor_chip.h" -#include "timer.h" #include "thermal.h" +#include "timer.h" #include "util.h" -#include "shi_chip.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_CH_0] = {"ADC0", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_1] = {"ADC1", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_CH_2] = {"ADC2", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_CH_0] = { "ADC0", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_1] = { "ADC1", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, + [ADC_CH_2] = { "ADC2", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX + 1, + 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_FAN] = { 0, PWM_CONFIG_OPEN_DRAIN, 25000}, + [PWM_CH_FAN] = { 0, PWM_CONFIG_OPEN_DRAIN, 25000 }, [PWM_CH_KBLIGHT] = { 1, 0, 10000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -54,7 +57,7 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = 0, /* Use MFT id to control fan */ + .ch = 0, /* Use MFT id to control fan */ .pgood_gpio = GPIO_PGOOD_FAN, .enable_gpio = -1, }; @@ -73,18 +76,38 @@ BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master0-0", NPCX_I2C_PORT0_0, 100, GPIO_I2C0_SCL0, GPIO_I2C0_SDA0}, - {"master0-1", NPCX_I2C_PORT0_1, 100, GPIO_I2C0_SCL1, GPIO_I2C0_SDA1}, - {"master1", NPCX_I2C_PORT1, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"master2", NPCX_I2C_PORT2, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"master3", NPCX_I2C_PORT3, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, + { .name = "master0-0", + .port = NPCX_I2C_PORT0_0, + .kbps = 100, + .scl = GPIO_I2C0_SCL0, + .sda = GPIO_I2C0_SDA0 }, + { .name = "master0-1", + .port = NPCX_I2C_PORT0_1, + .kbps = 100, + .scl = GPIO_I2C0_SCL1, + .sda = GPIO_I2C0_SDA1 }, + { .name = "master1", + .port = NPCX_I2C_PORT1, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "master2", + .port = NPCX_I2C_PORT2, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "master3", + .port = NPCX_I2C_PORT3, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -97,7 +120,7 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /******************************************************************************/ /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { .output_settle_us = 40, .debounce_down_us = 6 * MSEC, .debounce_up_us = 30 * MSEC, diff --git a/board/npcx_evb_arm/board.h b/board/npcx_evb_arm/board.h index 5128bffd0a..a3cbacdc6d 100644 --- a/board/npcx_evb_arm/board.h +++ b/board/npcx_evb_arm/board.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,17 +11,18 @@ /* Optional modules */ #define CONFIG_ADC #define CONFIG_PWM -#define CONFIG_HOSTCMD_SPS /* Used in ARM-based platform for host interface */ +#define CONFIG_HOST_INTERFACE_SHI /* ARM-based platform for host interface */ /* Optional features */ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */ -#define CONFIG_FLASH_SIZE 0x00800000 /* 8MB spi flash */ +#define CONFIG_FLASH_SIZE_BYTES 0x00800000 /* 8MB spi flash */ #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q64 #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG -#define CONFIG_KEYBOARD_PROTOCOL_MKBP /* Instead of 8042 protocol of keyboard */ +#define CONFIG_I2C_CONTROLLER + +#define CONFIG_KEYBOARD_PROTOCOL_MKBP /* Instead of 8042 protocol of keyboard \ + */ #define CONFIG_MKBP_USE_GPIO #define CONFIG_POWER_BUTTON #define CONFIG_VBOOT_HASH @@ -31,41 +32,35 @@ /* Optional features for test commands */ #define CONFIG_CMD_TASKREADY -#define CONFIG_CMD_STACKOVERFLOW #define CONFIG_CMD_JUMPTAGS #define CONFIG_CMD_FLASH #define CONFIG_CMD_SPI_FLASH #define CONFIG_CMD_SCRATCHPAD #define CONFIG_CMD_I2CWEDGE -#define CONFIG_UART_HOST 0 -#define CONFIG_FANS 1 +#define CONFIG_UART_HOST 0 +#define CONFIG_FANS 1 /* Optional feature - used by nuvoton */ -#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ /* Enable SHI PU on transition to S0. Disable the PU otherwise for leakage. */ #define NPCX_SHI_CS_PU /* Enable bypass since shi outputs invalid data when across 256B boundary */ #define NPCX_SHI_BYPASS_OVER_256B /* Optional for testing */ -#undef CONFIG_PSTORE -#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ +#undef CONFIG_PSTORE +#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ /* Single I2C port, where the EC is the master. */ -#define I2C_PORT_MASTER NPCX_I2C_PORT0_0 -#define I2C_PORT_HOST 0 +#define I2C_PORT_MASTER NPCX_I2C_PORT0_0 +#define I2C_PORT_HOST 0 #ifndef __ASSEMBLER__ -enum adc_channel { - ADC_CH_0 = 0, - ADC_CH_1, - ADC_CH_2, - ADC_CH_COUNT -}; +enum adc_channel { ADC_CH_0 = 0, ADC_CH_1, ADC_CH_2, ADC_CH_COUNT }; enum pwm_channel { PWM_CH_FAN, diff --git a/board/npcx_evb_arm/build.mk b/board/npcx_evb_arm/build.mk index 48116c5454..e1a3762504 100644 --- a/board/npcx_evb_arm/build.mk +++ b/board/npcx_evb_arm/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/npcx_evb_arm/ec.tasklist b/board/npcx_evb_arm/ec.tasklist index a014b86350..078059e9d8 100644 --- a/board/npcx_evb_arm/ec.tasklist +++ b/board/npcx_evb_arm/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/npcx_evb_arm/gpio.inc b/board/npcx_evb_arm/gpio.inc index 1cdda98300..dc94a8ac7b 100644 --- a/board/npcx_evb_arm/gpio.inc +++ b/board/npcx_evb_arm/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-dartmonkey/board.c b/board/nucleo-dartmonkey/board.c index ea5a921aa7..9b8ba6c42c 100644 --- a/board/nucleo-dartmonkey/board.c +++ b/board/nucleo-dartmonkey/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -27,13 +27,19 @@ int console_is_restricted(void) static void ap_deferred(void) { /* - * in S3: SLP_S3_L is 0 and SLP_S0_L is X. - * in S0ix: SLP_S3_L is X and SLP_S0_L is 0. - * in S0: SLP_S3_L is 1 and SLP_S0_L is 1. + * Behavior: + * AP Active (ex. Intel S0): SLP_L is 1 + * AP Suspend (ex. Intel S0ix): SLP_L is 0 + * The alternative SLP_ALT_L should be pulled high at all the times. + * + * Legacy Intel behavior: + * in S3: SLP_ALT_L is 0 and SLP_L is X. + * in S0ix: SLP_ALT_L is X and SLP_L is 0. + * in S0: SLP_ALT_L is 1 and SLP_L is 1. * in S5/G3, the FP MCU should not be running. */ - int running = gpio_get_level(GPIO_PCH_SLP_S3_L) - && gpio_get_level(GPIO_PCH_SLP_S0_L); + int running = gpio_get_level(GPIO_SLP_ALT_L) && + gpio_get_level(GPIO_SLP_L); if (running) { /* S0 */ disable_sleep(SLEEP_MASK_AP_RUN); @@ -57,6 +63,7 @@ void fps_event(enum gpio_signal signal) } #endif +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* SPI devices */ @@ -69,13 +76,15 @@ const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); static void spi_configure(void) { /* Configure SPI GPIOs */ - gpio_config_module(MODULE_SPI_MASTER, 1); - /* Set all SPI master signal pins to very high speed: pins E2/4/5/6 */ + gpio_config_module(MODULE_SPI_CONTROLLER, 1); + /* Set all SPI controller signal pins to very high speed: + * pins E2/4/5/6 + */ STM32_GPIO_OSPEEDR(GPIO_E) |= 0x00003f30; /* Enable clocks to SPI4 module (master) */ STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI4; - spi_enable(CONFIG_SPI_FP_PORT, 1); + spi_enable(&spi_devices[0], 1); } /* Initialize board. */ @@ -84,12 +93,17 @@ static void board_init(void) spi_configure(); ccprints("TRANSPORT_SEL: %s", - fp_transport_type_to_str(get_fp_transport_type())); + fp_transport_type_to_str(get_fp_transport_type())); /* Enable interrupt on PCH power signals */ - gpio_enable_interrupt(GPIO_PCH_SLP_S3_L); - gpio_enable_interrupt(GPIO_PCH_SLP_S0_L); - /* enable the SPI slave interface if the PCH is up */ - hook_call_deferred(&ap_deferred_data, 0); + gpio_enable_interrupt(GPIO_SLP_ALT_L); + gpio_enable_interrupt(GPIO_SLP_L); + + /* + * Enable the SPI peripheral interface if the PCH is up. + * Do not use hook_call_deferred(), because ap_deferred() will be + * called after tasks with priority higher than HOOK task (very late). + */ + ap_deferred(); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/nucleo-dartmonkey/board.h b/board/nucleo-dartmonkey/board.h index 00ef075129..4e070bf91b 100644 --- a/board/nucleo-dartmonkey/board.h +++ b/board/nucleo-dartmonkey/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -31,27 +31,31 @@ /* Fingerprint needs to store a secrect in the anti-rollback block */ #define CONFIG_ROLLBACK_SECRET_SIZE 32 +#define CONFIG_BORINGSSL_CRYPTO + /* SPI configuration for the fingerprint sensor */ -#define CONFIG_SPI_MASTER -#define CONFIG_SPI_FP_PORT 2 /* SPI4: third master config */ +#define CONFIG_SPI_CONTROLLER +#define CONFIG_SPI_FP_PORT 2 /* SPI4: third master config */ + +#define CONFIG_FINGERPRINT_MCU #ifdef SECTION_IS_RW - /* Select fingerprint sensor */ -# define CONFIG_FP_SENSOR_FPC1145 -# define CONFIG_CMD_FPSENSOR_DEBUG - /* Special memory regions to store large arrays */ -# define FP_FRAME_SECTION __SECTION(ahb4) -# define FP_TEMPLATE_SECTION __SECTION(ahb) - /* - * Use the malloc code only in the RW section (for the private library), - * we cannot enable it in RO since it is not compatible with the RW - * verification (shared_mem_init done too late). - */ -# define CONFIG_MALLOC +/* Select fingerprint sensor */ +#define CONFIG_FP_SENSOR_FPC1145 +#define CONFIG_CMD_FPSENSOR_DEBUG +/* Special memory regions to store large arrays */ +#define FP_FRAME_SECTION __SECTION(ahb4) +#define FP_TEMPLATE_SECTION __SECTION(ahb) +/* + * Use the malloc code only in the RW section (for the private library), + * we cannot enable it in RO since it is not compatible with the RW + * verification (shared_mem_init done too late). + */ +#define CONFIG_MALLOC #endif /* SECTION_IS_RW */ #ifndef __ASSEMBLER__ - void fps_event(enum gpio_signal signal); +void fps_event(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ #endif /* __BOARD_H */ diff --git a/board/nucleo-dartmonkey/build.mk b/board/nucleo-dartmonkey/build.mk index 4d39121edc..c56a08af10 100644 --- a/board/nucleo-dartmonkey/build.mk +++ b/board/nucleo-dartmonkey/build.mk @@ -1,4 +1,4 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,15 +11,36 @@ board-y+=fpsensor_detect.o # Enable on device tests test-list-y=\ + abort \ aes \ + boringssl_crypto \ compile_time_macros \ - crc32 \ + crc \ + debug \ + exception \ + flash_physical \ + flash_write_protect \ + fpsensor \ + fpsensor_auth_crypto_stateful \ + fpsensor_auth_crypto_stateless \ + fpsensor_hw \ + libc_printf \ + mpu \ mutex \ pingpong \ - rsa \ + printf \ + queue \ + rng_benchmark \ + rollback \ + rollback_entropy \ rsa3 \ rtc \ + sbrk \ + scratchpad \ sha256 \ sha256_unrolled \ - stm32f_rtc \ + static_if \ + stdlib \ + timer_dos \ utils \ + utils_str \ diff --git a/board/nucleo-dartmonkey/ec.tasklist b/board/nucleo-dartmonkey/ec.tasklist index 80e226637b..7f35361949 100644 --- a/board/nucleo-dartmonkey/ec.tasklist +++ b/board/nucleo-dartmonkey/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-dartmonkey/fpsensor_detect.c b/board/nucleo-dartmonkey/fpsensor_detect.c index 72b9b89e11..07dee3d0cb 100644 --- a/board/nucleo-dartmonkey/fpsensor_detect.c +++ b/board/nucleo-dartmonkey/fpsensor_detect.c @@ -1,11 +1,11 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "fpsensor_detect.h" -enum fp_sensor_type get_fp_sensor_type(void) +enum fp_sensor_type fpsensor_detect_get_type(void) { return FP_SENSOR_TYPE_FPC; } diff --git a/board/nucleo-dartmonkey/gpio.inc b/board/nucleo-dartmonkey/gpio.inc index e20027a8ff..a9e5101855 100644 --- a/board/nucleo-dartmonkey/gpio.inc +++ b/board/nucleo-dartmonkey/gpio.inc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,8 +14,8 @@ #include "base-gpio.inc" /* Interrupts */ -GPIO_INT(PCH_SLP_S0_L, PIN(D, 13), GPIO_INT_BOTH, slp_event) -GPIO_INT(PCH_SLP_S3_L, PIN(A, 11), GPIO_INT_BOTH, slp_event) +GPIO_INT(SLP_L, PIN(D, 13), GPIO_INT_BOTH, slp_event) +GPIO_INT(SLP_ALT_L, PIN(A, 11), GPIO_INT_BOTH, slp_event) /* Output for User Presence */ GPIO(USER_PRES_L, PIN(C, 5), GPIO_ODR_HIGH) @@ -25,4 +25,4 @@ GPIO_INT(FPS_INT, PIN(A, 0), GPIO_INT_RISING, fps_event) GPIO(FP_RST_ODL, PIN(E, 0), GPIO_OUT_HIGH) GPIO(SPI4_NSS, PIN(E, 4), GPIO_OUT_HIGH) /* SPI4 master to sensor: PE2/5/6 (CLK/MISO/MOSI) */ -ALTERNATE(PIN_MASK(E, 0x0064), GPIO_ALT_SPI, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(E, 0x0064), GPIO_ALT_SPI, MODULE_SPI_CONTROLLER, 0) diff --git a/board/nucleo-f072rb/board.c b/board/nucleo-f072rb/board.c index 66e8960ce7..8d75379f97 100644 --- a/board/nucleo-f072rb/board.c +++ b/board/nucleo-f072rb/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,9 +6,9 @@ #include "common.h" #include "gpio.h" #include "hooks.h" +#include "i2c.h" #include "registers.h" #include "task.h" -#include "i2c.h" #include "timer.h" void button_event(enum gpio_signal signal) @@ -21,10 +21,15 @@ void button_event(enum gpio_signal signal) * Mock interrupt handler. It's supposed to be overwritten by each suite * if needed. */ -__attribute__((weak)) void cts_irq1(enum gpio_signal signal) {} -__attribute__((weak)) void cts_irq2(enum gpio_signal signal) {} +__attribute__((weak)) void cts_irq1(enum gpio_signal signal) +{ +} +__attribute__((weak)) void cts_irq2(enum gpio_signal signal) +{ +} #endif +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" void tick_event(void) @@ -38,8 +43,12 @@ void tick_event(void) DECLARE_HOOK(HOOK_TICK, tick_event, HOOK_PRIO_DEFAULT); #ifdef CTS_MODULE_I2C -const struct i2c_port_t i2c_ports[] = { - {"test", STM32_I2C1_PORT, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "test", + .port = STM32_I2C1_PORT, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -51,6 +60,5 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); static void board_init(void) { gpio_enable_interrupt(GPIO_USER_BUTTON); - } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/nucleo-f072rb/board.h b/board/nucleo-f072rb/board.h index 9cc2fc2d0b..bd957d35db 100644 --- a/board/nucleo-f072rb/board.h +++ b/board/nucleo-f072rb/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,14 +16,13 @@ #define CONFIG_UART_CONSOLE 2 /* Optional features */ -#define CONFIG_STM_HWTIMER32 #ifdef CTS_MODULE #undef STM32_IRQ_EXT2_3_PRIORITY -#define STM32_IRQ_EXT2_3_PRIORITY 2 +#define STM32_IRQ_EXT2_3_PRIORITY 2 #ifdef CTS_MODULE_I2C #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #endif #endif diff --git a/board/nucleo-f072rb/build.mk b/board/nucleo-f072rb/build.mk index 0e069a31ad..7ac70706fc 100644 --- a/board/nucleo-f072rb/build.mk +++ b/board/nucleo-f072rb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/nucleo-f072rb/ec.tasklist b/board/nucleo-f072rb/ec.tasklist index a6385530b5..3ddec80f41 100644 --- a/board/nucleo-f072rb/ec.tasklist +++ b/board/nucleo-f072rb/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-f072rb/gpio.inc b/board/nucleo-f072rb/gpio.inc index 6f3b592845..a14c7a5470 100644 --- a/board/nucleo-f072rb/gpio.inc +++ b/board/nucleo-f072rb/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-f072rb/openocd-flash.cfg b/board/nucleo-f072rb/openocd-flash.cfg index 91e3805c74..f06b3c22a2 100644 --- a/board/nucleo-f072rb/openocd-flash.cfg +++ b/board/nucleo-f072rb/openocd-flash.cfg @@ -1,4 +1,4 @@ -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/board/nucleo-f411re/board.c b/board/nucleo-f411re/board.c index 97f5a8a8d3..8fce43c988 100644 --- a/board/nucleo-f411re/board.c +++ b/board/nucleo-f411re/board.c @@ -1,11 +1,10 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* nucleo-f411re development board configuration */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "console.h" #include "driver/accelgyro_bmi_common.h" @@ -14,8 +13,6 @@ #include "hooks.h" #include "i2c.h" #include "motion_sense.h" - -#include "gpio.h" #include "registers.h" #include "task.h" #include "util.h" @@ -25,6 +22,7 @@ void user_button_evt(enum gpio_signal signal) ccprintf("Button %d, %d!\n", signal, gpio_get_level(signal)); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Initialize board. */ @@ -44,17 +42,20 @@ DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); /* ADC channels */ const struct adc_t adc_channels[] = { /* Arduino connectors analog pins */ - [ADC1_0] = {"ADC1_0", 3000, 4096, 0, STM32_AIN(0)}, - [ADC1_1] = {"ADC1_1", 3000, 4096, 0, STM32_AIN(1)}, - [ADC1_4] = {"ADC1_4", 3000, 4096, 0, STM32_AIN(4)}, - [ADC1_8] = {"ADC1_8", 3000, 4096, 0, STM32_AIN(8)}, + [ADC1_0] = { "ADC1_0", 3000, 4096, 0, STM32_AIN(0) }, + [ADC1_1] = { "ADC1_1", 3000, 4096, 0, STM32_AIN(1) }, + [ADC1_4] = { "ADC1_4", 3000, 4096, 0, STM32_AIN(4) }, + [ADC1_8] = { "ADC1_8", 3000, 4096, 0, STM32_AIN(8) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + { .name = "master", + .port = I2C_PORT_MASTER, + .kbps = 100, + .scl = GPIO_MASTER_I2C_SCL, + .sda = GPIO_MASTER_I2C_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -113,13 +114,12 @@ const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); #ifdef CONFIG_DMA_HELP #include "dma.h" -int command_dma_help(int argc, char **argv) +static int command_dma_help(int argc, const char **argv) { dma_dump(STM32_DMA2_STREAM0); dma_test(STM32_DMA2_STREAM0); dma_dump(STM32_DMA2_STREAM0); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(dmahelp, command_dma_help, - NULL, "Run DMA test"); +DECLARE_CONSOLE_COMMAND(dmahelp, command_dma_help, NULL, "Run DMA test"); #endif diff --git a/board/nucleo-f411re/board.h b/board/nucleo-f411re/board.h index 069e1367f2..3b7d5f1bf1 100644 --- a/board/nucleo-f411re/board.h +++ b/board/nucleo-f411re/board.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,7 +12,6 @@ #define CPU_CLOCK 84000000 #define CONFIG_FLASH_WRITE_SIZE STM32_FLASH_WRITE_SIZE_3300 - /* the UART console is on USART2 (PA2/PA3) */ #undef CONFIG_UART_CONSOLE #define CONFIG_UART_CONSOLE 2 @@ -20,7 +19,6 @@ /* Optional features */ #undef CONFIG_LID_SWITCH #undef CONFIG_HIBERNATE -#define CONFIG_STM_HWTIMER32 #define CONFIG_WATCHDOG_HELP #define CONFIG_TASK_PROFILING @@ -40,10 +38,10 @@ #define CONFIG_CMD_FLASH /* I2C ports configuration */ -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_I2C_DEBUG #define I2C_PORT_MASTER 1 -#define I2C_PORT_SLAVE 0 /* needed for DMAC macros (ugh) */ +#define I2C_PORT_SLAVE 0 /* needed for DMAC macros (ugh) */ #define I2C_PORT_ACCEL I2C_PORT_MASTER #ifndef __ASSEMBLER__ diff --git a/board/nucleo-f411re/build.mk b/board/nucleo-f411re/build.mk index 3a5fc28558..93a0a02ecc 100644 --- a/board/nucleo-f411re/build.mk +++ b/board/nucleo-f411re/build.mk @@ -1,4 +1,4 @@ -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/nucleo-f411re/ec.tasklist b/board/nucleo-f411re/ec.tasklist index b5e3cb82b2..a9566a92aa 100644 --- a/board/nucleo-f411re/ec.tasklist +++ b/board/nucleo-f411re/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-f411re/gpio.inc b/board/nucleo-f411re/gpio.inc index 83a9e51a08..2fd98f2a4a 100644 --- a/board/nucleo-f411re/gpio.inc +++ b/board/nucleo-f411re/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-f411re/openocd-flash.cfg b/board/nucleo-f411re/openocd-flash.cfg index 7a6ea6316c..23da86c6ba 100644 --- a/board/nucleo-f411re/openocd-flash.cfg +++ b/board/nucleo-f411re/openocd-flash.cfg @@ -1,4 +1,4 @@ -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/board/nucleo-f412zg/README.md b/board/nucleo-f412zg/README.md index fcdd5e40df..f2fa682e6f 100644 --- a/board/nucleo-f412zg/README.md +++ b/board/nucleo-f412zg/README.md @@ -1,22 +1,19 @@ # Nucleo F412ZG -This is a simpler EC example for the ST Nucleo F412ZG -development board. +This is a simpler EC example for the ST Nucleo F412ZG development board. # Quick Start -The Nucleo dev boards have lots of developer friendly features, -like an in-circuit debugger/programmer/UART-bridge, programmable -LEDs, and a button, to name a few. +The Nucleo dev boards have lots of developer friendly features, like an +in-circuit debugger/programmer/UART-bridge, programmable LEDs, and a button, to +name a few. -The built-in debugger can be connected to using a Micro USB cable. -It provides three great interfaces to the host. -1. Mass storage interface for drag-drop programming -2. Full ST-Link in-circuit debugger -3. UART bridge for logs/consoles +The built-in debugger can be connected to using a Micro USB cable. It provides +three great interfaces to the host. 1. Mass storage interface for drag-drop +programming 2. Full ST-Link in-circuit debugger 3. UART bridge for logs/consoles -We will use a few of these interfaces below to program and interact -with out Nucleo dev board. +We will use a few of these interfaces below to program and interact with out +Nucleo dev board. ## Build @@ -26,17 +23,17 @@ make BOARD=nucleo-f412zg -j ## Program -The easiest way to flash the Nucleo board is to Copy-Paste/Drag-Drop -the firmware image onto the exposed mass storage drive. +The easiest way to flash the Nucleo board is to Copy-Paste/Drag-Drop the +firmware image onto the exposed mass storage drive. -Open a file browser and `Copy` the file in `build/nucleo-f412zg/ec.bin`. -Now, find the removable storage that the Nucleo device has presented, -and `Paste` the file into the directory. +Open a file browser and `Copy` the file in `build/nucleo-f412zg/ec.bin`. Now, +find the removable storage that the Nucleo device has presented, and `Paste` the +file into the directory. ## Interact -After the Nucelo finishes programming, you can open the EC console. -On GNU/Linux, this is mapped to `/dev/ttyACM0`. +After the Nucleo finishes programming, you can open the EC console. On +GNU/Linux, this is mapped to `/dev/ttyACM0`. Install `minicom` and issue the following command: @@ -48,9 +45,9 @@ minicom -D/dev/ttyACM0 A fun EC feature is that unit tests can be run on-device. -This is made possible by an alternative build rule that generates a -test image per unit test. These test images use a unit test specific taskset -and console command to trigger them. +This is made possible by an alternative build rule that generates a test image +per unit test. These test images use a unit test specific taskset and console +command to trigger them. ## Create @@ -67,19 +64,20 @@ To build all unit test images for this board, run the following command: make BOARD=nucleo-f412zg tests ``` -You can build a specific unit test image by changing `tests` to `test-aes`, -for the `aes` unit test. +You can build a specific unit test image by changing `tests` to `test-aes`, for +the `aes` unit test. ## Flash -Copy/paste the `build/nucleo-f412zg/${TEST}/${TEST}.bin` file to the -Nucleo's mass storage drive, where `${TEST}` is the name of the unit test, -like `aes`. +Copy/paste the `build/nucleo-f412zg/${TEST}/${TEST}.bin` file to the Nucleo's +mass storage drive, where `${TEST}` is the name of the unit test, like `aes`. ## Run -1. Connect to UART console - ```bash - minicom -D/dev/ttyACM0 - ``` -2. Run the `runtest` command \ No newline at end of file +1. Connect to UART console + +```bash +minicom -D/dev/ttyACM0 +``` + +1. Run the `runtest` command diff --git a/board/nucleo-f412zg/board.c b/board/nucleo-f412zg/board.c index e06408c404..39110cd82b 100644 --- a/board/nucleo-f412zg/board.c +++ b/board/nucleo-f412zg/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -31,8 +31,8 @@ static void ap_deferred(void) * in S0: SLP_S3_L is 1 and SLP_S0_L is 1. * in S5/G3, the FP MCU should not be running. */ - int running = gpio_get_level(GPIO_PCH_SLP_S3_L) - && gpio_get_level(GPIO_PCH_SLP_S0_L); + int running = gpio_get_level(GPIO_PCH_SLP_S3_L) && + gpio_get_level(GPIO_PCH_SLP_S0_L); if (running) { /* S0 */ disable_sleep(SLEEP_MASK_AP_RUN); @@ -50,6 +50,7 @@ static void slp_event(enum gpio_signal signal) hook_call_deferred(&ap_deferred_data, 0); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Initialize board. */ @@ -58,7 +59,12 @@ static void board_init(void) /* Enable interrupt on PCH power signals */ gpio_enable_interrupt(GPIO_PCH_SLP_S3_L); gpio_enable_interrupt(GPIO_PCH_SLP_S0_L); - /* enable the SPI slave interface if the PCH is up */ - hook_call_deferred(&ap_deferred_data, 0); + + /* + * Enable the SPI peripheral interface if the PCH is up. + * Do not use hook_call_deferred(), because ap_deferred() will be + * called after tasks with priority higher than HOOK task (very late). + */ + ap_deferred(); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/nucleo-f412zg/board.h b/board/nucleo-f412zg/board.h index 331fa29578..7e3c8d976d 100644 --- a/board/nucleo-f412zg/board.h +++ b/board/nucleo-f412zg/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,4 +22,10 @@ #define CONFIG_CONSOLE_COMMAND_FLAGS #define CONFIG_RESTRICTED_CONSOLE_COMMANDS +/* + * Enable the blink example that exercises the LEDs. + */ +#define CONFIG_BLINK +#define CONFIG_BLINK_LEDS GPIO_LED1, GPIO_LED2, GPIO_LED3 + #endif /* __BOARD_H */ diff --git a/board/nucleo-f412zg/build.mk b/board/nucleo-f412zg/build.mk index 4dbe987b39..02b2222d93 100644 --- a/board/nucleo-f412zg/build.mk +++ b/board/nucleo-f412zg/build.mk @@ -1,4 +1,4 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,21 +10,33 @@ board-y=board.o # Enable on device tests test-list-y=\ + abort \ aes \ + boringssl_crypto \ compile_time_macros \ - crc32 \ + crc \ + debug \ + exception \ flash_physical \ flash_write_protect \ + libc_printf \ mpu \ mutex \ pingpong \ + printf \ + queue \ + rng_benchmark \ rollback \ rollback_entropy \ - rsa \ rsa3 \ rtc \ + sbrk \ scratchpad \ sha256 \ sha256_unrolled \ + static_if \ + stdlib \ stm32f_rtc \ + timer_dos \ utils \ + utils_str \ diff --git a/board/nucleo-f412zg/ec.tasklist b/board/nucleo-f412zg/ec.tasklist index 896eb2fdb3..04e21000f9 100644 --- a/board/nucleo-f412zg/ec.tasklist +++ b/board/nucleo-f412zg/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-f412zg/gpio.inc b/board/nucleo-f412zg/gpio.inc index 57f78203ba..6cc09a20df 100644 --- a/board/nucleo-f412zg/gpio.inc +++ b/board/nucleo-f412zg/gpio.inc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-g431rb/board.c b/board/nucleo-g431rb/board.c index 01f8a55629..5a6a0a6f5c 100644 --- a/board/nucleo-g431rb/board.c +++ b/board/nucleo-g431rb/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,8 +9,8 @@ #include "gpio.h" #include "hooks.h" -#include "gpio_list.h" /* Must come after other header files. */ - +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" static void board_init(void) { @@ -31,4 +31,3 @@ static void led_second(void) gpio_set_level(GPIO_LED1, count++ & 0x1); } DECLARE_HOOK(HOOK_SECOND, led_second, HOOK_PRIO_DEFAULT); - diff --git a/board/nucleo-g431rb/board.h b/board/nucleo-g431rb/board.h index a65daa4364..e2df8d2547 100644 --- a/board/nucleo-g431rb/board.h +++ b/board/nucleo-g431rb/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,16 +12,14 @@ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ #define CPU_CLOCK 48000000 -#define CONFIG_STM_HWTIMER32 #define TIM_CLOCK32 2 -#define TIM_CLOCK_MSB 3 +#define TIM_CLOCK_MSB 3 #define TIM_CLOCK_LSB 15 #define TIM_WATCHDOG 7 /* Nucelo platform does not have a lid switch */ #undef CONFIG_LID_SWITCH - /* Setup UART console */ /* * The STM32G431 Nucleo-64 has two UARTs which can be connected to the virtual @@ -49,24 +47,20 @@ #define CONFIG_UART_TX_DMA_PH DMAMUX_REQ_USART1_TX #endif - /* * Macros for GPIO signals used in common code that don't match the * schematic names. Signal names in gpio.inc match the schematic and are * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_WP_L GPIO_EC_WP_L - - +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_WP_L GPIO_EC_WP_L #ifndef __ASSEMBLER__ #include "gpio_signal.h" #include "registers.h" - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/nucleo-g431rb/build.mk b/board/nucleo-g431rb/build.mk index 8140048cdd..a5a00675ee 100644 --- a/board/nucleo-g431rb/build.mk +++ b/board/nucleo-g431rb/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/nucleo-g431rb/ec.tasklist b/board/nucleo-g431rb/ec.tasklist index c272906fc7..682e6d8290 100644 --- a/board/nucleo-g431rb/ec.tasklist +++ b/board/nucleo-g431rb/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-g431rb/gpio.inc b/board/nucleo-g431rb/gpio.inc index 4dd4a6d966..4c7507eff9 100644 --- a/board/nucleo-g431rb/gpio.inc +++ b/board/nucleo-g431rb/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-h743zi/README.md b/board/nucleo-h743zi/README.md index 58d47219da..7ba8a143a3 100644 --- a/board/nucleo-h743zi/README.md +++ b/board/nucleo-h743zi/README.md @@ -1,22 +1,19 @@ # Nucleo H743ZI -This is a simpler EC example for the ST Nucleo H743ZI -development board. +This is a simpler EC example for the ST Nucleo H743ZI development board. # Quick Start -The Nucleo dev boards have lots of developer friendly features, -like an in-circuit debugger/programmer/UART-bridge, programmable -LEDs, and a button, to name a few. +The Nucleo dev boards have lots of developer friendly features, like an +in-circuit debugger/programmer/UART-bridge, programmable LEDs, and a button, to +name a few. -The built-in debugger can be connected to using a Micro USB cable. -It provides three great interfaces to the host. -1. Mass storage interface for drag-drop programming -2. Full ST-Link in-circuit debugger -3. UART bridge for logs/consoles +The built-in debugger can be connected to using a Micro USB cable. It provides +three great interfaces to the host. 1. Mass storage interface for drag-drop +programming 2. Full ST-Link in-circuit debugger 3. UART bridge for logs/consoles -We will use a few of these interfaces below to program and interact -with out Nucleo dev board. +We will use a few of these interfaces below to program and interact with out +Nucleo dev board. ## Build @@ -26,17 +23,17 @@ make BOARD=nucleo-h743zi -j ## Program -The easiest way to flash the Nucleo board is to Copy-Paste/Drag-Drop -the firmware image onto the exposed mass storage drive. +The easiest way to flash the Nucleo board is to Copy-Paste/Drag-Drop the +firmware image onto the exposed mass storage drive. -Open a file browser and `Copy` the file in `build/nucleo-h743zi/ec.bin`. -Now, find the removable storage that the Nucleo device has presented, -and `Paste` the file into the directory. +Open a file browser and `Copy` the file in `build/nucleo-h743zi/ec.bin`. Now, +find the removable storage that the Nucleo device has presented, and `Paste` the +file into the directory. ## Interact -After the Nucelo finishes programming, you can open the EC console. -On GNU/Linux, this is mapped to `/dev/ttyACM0`. +After the Nucleo finishes programming, you can open the EC console. On +GNU/Linux, this is mapped to `/dev/ttyACM0`. Install `minicom` and issue the following command: @@ -48,9 +45,9 @@ minicom -D/dev/ttyACM0 A fun EC feature is that unit tests can be run on-device. -This is made possible by an alternative build rule that generates a -test image per unit test. These test images use a unit test specific taskset -and console command to trigger them. +This is made possible by an alternative build rule that generates a test image +per unit test. These test images use a unit test specific taskset and console +command to trigger them. ## Create @@ -67,19 +64,20 @@ To build all unit test images for this board, run the following command: make BOARD=nucleo-h743zi tests ``` -You can build a specific unit test image by changing `tests` to `test-aes`, -for the `aes` unit test. +You can build a specific unit test image by changing `tests` to `test-aes`, for +the `aes` unit test. ## Flash -Copy/paste the `build/nucleo-h743zi/${TEST}/${TEST}.bin` file to the -Nucleo's mass storage drive, where `${TEST}` is the name of the unit test, -like `aes`. +Copy/paste the `build/nucleo-h743zi/${TEST}/${TEST}.bin` file to the Nucleo's +mass storage drive, where `${TEST}` is the name of the unit test, like `aes`. ## Run -1. Connect to UART console - ```bash - minicom -D/dev/ttyACM0 - ``` -2. Run the `runtest` command \ No newline at end of file +1. Connect to UART console + +```bash +minicom -D/dev/ttyACM0 +``` + +1. Run the `runtest` command diff --git a/board/nucleo-h743zi/board.c b/board/nucleo-h743zi/board.c index c4c7e764c8..0752b02f0c 100644 --- a/board/nucleo-h743zi/board.c +++ b/board/nucleo-h743zi/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -31,8 +31,8 @@ static void ap_deferred(void) * in S0: SLP_S3_L is 1 and SLP_S0_L is 1. * in S5/G3, the FP MCU should not be running. */ - int running = gpio_get_level(GPIO_PCH_SLP_S3_L) - && gpio_get_level(GPIO_PCH_SLP_S0_L); + int running = gpio_get_level(GPIO_PCH_SLP_S3_L) && + gpio_get_level(GPIO_PCH_SLP_S0_L); if (running) { /* S0 */ disable_sleep(SLEEP_MASK_AP_RUN); @@ -50,6 +50,7 @@ static void slp_event(enum gpio_signal signal) hook_call_deferred(&ap_deferred_data, 0); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Initialize board. */ @@ -58,7 +59,12 @@ static void board_init(void) /* Enable interrupt on PCH power signals */ gpio_enable_interrupt(GPIO_PCH_SLP_S3_L); gpio_enable_interrupt(GPIO_PCH_SLP_S0_L); - /* enable the SPI slave interface if the PCH is up */ - hook_call_deferred(&ap_deferred_data, 0); + + /* + * Enable the SPI peripheral interface if the PCH is up. + * Do not use hook_call_deferred(), because ap_deferred() will be + * called after tasks with priority higher than HOOK task (very late). + */ + ap_deferred(); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/nucleo-h743zi/board.h b/board/nucleo-h743zi/board.h index 966f2a8c94..81cdd60fc9 100644 --- a/board/nucleo-h743zi/board.h +++ b/board/nucleo-h743zi/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -28,6 +28,6 @@ * Enable the blink example that exercises the LEDs. */ #define CONFIG_BLINK -#define CONFIG_BLINK_LEDS GPIO_LED1, GPIO_LED2, GPIO_LED3 +#define CONFIG_BLINK_LEDS GPIO_LED1, GPIO_LED2, GPIO_LED3 #endif /* __BOARD_H */ diff --git a/board/nucleo-h743zi/build.mk b/board/nucleo-h743zi/build.mk index ebb8d6b18f..2785b30d30 100644 --- a/board/nucleo-h743zi/build.mk +++ b/board/nucleo-h743zi/build.mk @@ -1,4 +1,4 @@ -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,20 +10,32 @@ board-y=board.o # Enable on device tests test-list-y=\ + abort \ aes \ + boringssl \ compile_time_macros \ - crc32 \ + crc \ + debug \ + exception \ flash_physical \ flash_write_protect \ + libc_printf \ mpu \ mutex \ pingpong \ + printf \ + queue \ + rng_benchmark \ rollback \ rollback_entropy \ - rsa \ rsa3 \ rtc \ + sbrk \ scratchpad \ sha256 \ sha256_unrolled \ + static_if \ + stdlib \ + timer_dos \ utils \ + utils_str \ diff --git a/board/nucleo-h743zi/ec.tasklist b/board/nucleo-h743zi/ec.tasklist index 9c37e0b58b..ed124cd672 100644 --- a/board/nucleo-h743zi/ec.tasklist +++ b/board/nucleo-h743zi/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nucleo-h743zi/gpio.inc b/board/nucleo-h743zi/gpio.inc index 0f2bb32d75..a93133abd7 100644 --- a/board/nucleo-h743zi/gpio.inc +++ b/board/nucleo-h743zi/gpio.inc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nuwani/battery.c b/board/nuwani/battery.c index 5cbbeb5123..e24b442049 100644 --- a/board/nuwani/battery.c +++ b/board/nuwani/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/nuwani/board.c b/board/nuwani/board.c index 3b64396976..de2506d0a1 100644 --- a/board/nuwani/board.c +++ b/board/nuwani/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,16 +10,18 @@ #include "driver/accelgyro_bmi_common.h" #include "driver/accelgyro_lsm6dsm.h" #include "extpower.h" +#include "gpio.h" #include "i2c.h" #include "lid_switch.h" #include "power.h" #include "power_button.h" #include "pwm.h" -#include "system.h" #include "switch.h" +#include "system.h" #include "tablet_mode.h" #include "task.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" const enum gpio_signal hibernate_wake_pins[] = { @@ -28,20 +30,38 @@ const enum gpio_signal hibernate_wake_pins[] = { GPIO_POWER_BUTTON_L, GPIO_EC_RST_ODL, }; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* I2C port map. */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"thermal", I2C_PORT_THERMAL_AP, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "thermal", + .port = I2C_PORT_THERMAL_AP, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -#ifdef HAS_TASK_MOTIONSENSE - /* Motion sensors */ static struct mutex g_lid_mutex_1; static struct mutex g_base_mutex_1; @@ -51,19 +71,15 @@ static struct stprivate_data g_lis2dwl_data; /* Base accel private data */ static struct lsm6dsm_data g_lsm6dsm_data = LSM6DSM_DATA; - /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t lsm6dsm_base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t lsm6dsm_base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, + FLOAT_TO_FP(1) } }; -static const mat33_fp_t treeya_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t treeya_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t lid_accel_1 = { .name = "Lid Accel", @@ -102,8 +118,6 @@ struct motion_sensor_t base_accel_1 = { .mutex = &g_base_mutex_1, .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_ACCEL, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &lsm6dsm_base_standard_ref, @@ -132,10 +146,7 @@ struct motion_sensor_t base_gyro_1 = { .location = MOTIONSENSE_LOC_BASE, .drv = &lsm6dsm_drv, .mutex = &g_base_mutex_1, - .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, - MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, + .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), .port = I2C_PORT_ACCEL, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -163,10 +174,12 @@ void board_update_sensor_config_from_sku(void) motion_sensors[LID_ACCEL] = lid_accel_1; motion_sensors[BASE_ACCEL] = base_accel_1; motion_sensors[BASE_GYRO] = base_gyro_1; - } else{ + } else { /*Need to change matrix for treeya*/ - motion_sensors[BASE_ACCEL].rot_standard_ref = &treeya_standard_ref; - motion_sensors[BASE_GYRO].rot_standard_ref = &treeya_standard_ref; + motion_sensors[BASE_ACCEL].rot_standard_ref = + &treeya_standard_ref; + motion_sensors[BASE_GYRO].rot_standard_ref = + &treeya_standard_ref; } /* Enable Gyro interrupts */ @@ -174,10 +187,9 @@ void board_update_sensor_config_from_sku(void) } else { motion_sensor_count = 0; /* Device is clamshell only */ - tablet_set_mode(0); + tablet_set_mode(0, TABLET_TRIGGER_LID); /* Gyro is not present, don't allow line to float */ - gpio_set_flags(GPIO_6AXIS_INT_L, - GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); } } @@ -189,5 +201,3 @@ void board_bmi160_lsm6dsm_interrupt(enum gpio_signal signal) else bmi160_interrupt(signal); } - -#endif diff --git a/board/nuwani/board.h b/board/nuwani/board.h index 17d16110a5..b58102efe7 100644 --- a/board/nuwani/board.h +++ b/board/nuwani/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,14 +16,13 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* Power and battery LEDs */ #define CONFIG_LED_COMMON #define CONFIG_CMD_LEDTEST -#define CONFIG_LED_POWER_LED #define CONFIG_LED_ONOFF_STATES @@ -37,7 +36,6 @@ #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCEL_KX022 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -49,7 +47,7 @@ /* * Slew rate on the PP1800_SENSOR load switch requires a short delay on startup. */ -#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US +#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US #define CONFIG_MOTION_SENSE_RESUME_DELAY_US (10 * MSEC) /* Second set of sensor drivers */ @@ -60,7 +58,6 @@ #ifndef __ASSEMBLER__ - enum battery_type { BATTERY_SMP, BATTERY_LGC, diff --git a/board/nuwani/build.mk b/board/nuwani/build.mk index 85b141b15d..c754c96237 100644 --- a/board/nuwani/build.mk +++ b/board/nuwani/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/nuwani/ec.tasklist b/board/nuwani/ec.tasklist index 2874dff927..c5db864fe5 100644 --- a/board/nuwani/ec.tasklist +++ b/board/nuwani/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nuwani/gpio.inc b/board/nuwani/gpio.inc index 18c72c8125..e01af85e34 100644 --- a/board/nuwani/gpio.inc +++ b/board/nuwani/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/nuwani/led.c b/board/nuwani/led.c index 9298075157..f04a422592 100644 --- a/board/nuwani/led.c +++ b/board/nuwani/led.c @@ -1,51 +1,54 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" -#include "led_onoff_states.h" -#include "led_common.h" #include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 97; +__override const int led_charge_lvl_2 = 97; -struct led_descriptor - led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_POWER_LED_3_L, LED_ON_LVL); @@ -54,7 +57,7 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_POWER_LED_3_L, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_RED: diff --git a/board/nuwani/vif_override.xml b/board/nuwani/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/nuwani/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/oak/battery.c b/board/oak/battery.c index fffd2f7763..b9b410932d 100644 --- a/board/oak/battery.c +++ b/board/oak/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,7 +11,7 @@ #include "util.h" /* Shutdown mode parameter to write to manufacturer access register */ -#define PARAM_CUT_OFF_LOW 0x10 +#define PARAM_CUT_OFF_LOW 0x10 #define PARAM_CUT_OFF_HIGH 0x00 static const struct battery_info info = { @@ -21,7 +21,7 @@ static const struct battery_info info = { /* * TODO(crosbug.com/p/44428): * In order to compatible with 2S battery, set min voltage as 6V rather - * than 9V. Should set voltage_min to 9V, when 2S battery + * than 9V. Should set voltage_min to 9V, when 2S battery * phased out. */ .voltage_min = 6000, @@ -57,10 +57,10 @@ static int cutoff(void) buf[2] = PARAM_CUT_OFF_HIGH; i2c_lock(I2C_PORT_BATTERY, 1); - rv = i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - buf, 3, NULL, 0, I2C_XFER_SINGLE); - rv |= i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - buf, 3, NULL, 0, I2C_XFER_SINGLE); + rv = i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, buf, 3, + NULL, 0, I2C_XFER_SINGLE); + rv |= i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, buf, 3, + NULL, 0, I2C_XFER_SINGLE); i2c_lock(I2C_PORT_BATTERY, 0); return rv; diff --git a/board/oak/board.c b/board/oak/board.c index eb16c03ab1..f53d61cd9d 100644 --- a/board/oak/board.c +++ b/board/oak/board.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Oak board configuration */ #include "adc.h" -#include "adc_chip.h" #include "als.h" #include "atomic.h" #include "battery.h" @@ -53,34 +52,33 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* Dispaly port hardware can connect to port 0, 1 or neither. */ #define PD_PORT_NONE -1 void pd_mcu_interrupt(enum gpio_signal signal) { -#ifdef HAS_TASK_PDCMD /* Exchange status with PD MCU to determine interrupt cause */ host_command_pd_send_status(0); -#endif } #if BOARD_REV >= OAK_REV4 void usb_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_INTR, 0); - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_INTR, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_INTR); + usb_charger_task_set_event(1, USB_CHG_EVENT_INTR); } #endif /* BOARD_REV >= OAK_REV4 */ +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_SOC_POWER_GOOD, POWER_SIGNAL_ACTIVE_HIGH, "POWER_GOOD"}, - {GPIO_SUSPEND_L, POWER_SIGNAL_ACTIVE_LOW, "SUSPEND#_ASSERTED"}, + { GPIO_SOC_POWER_GOOD, POWER_SIGNAL_ACTIVE_HIGH, "POWER_GOOD" }, + { GPIO_SUSPEND_L, POWER_SIGNAL_ACTIVE_LOW, "SUSPEND#_ASSERTED" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); @@ -90,27 +88,32 @@ const struct adc_t adc_channels[] = { * PSYS_MONITOR(PA2): ADC_IN2, 1.44 uA/W on 6.05k Ohm * output in mW */ - [ADC_PSYS] = {"PSYS", 379415, 4096, 0, STM32_AIN(2)}, + [ADC_PSYS] = { "PSYS", 379415, 4096, 0, STM32_AIN(2) }, /* AMON_BMON(PC0): ADC_IN10, output in uV */ - [ADC_AMON_BMON] = {"AMON_BMON", 183333, 4096, 0, STM32_AIN(10)}, + [ADC_AMON_BMON] = { "AMON_BMON", 183333, 4096, 0, STM32_AIN(10) }, /* VDC_BOOSTIN_SENSE(PC1): ADC_IN11, output in mV */ - [ADC_VBUS] = {"VBUS", 33000, 4096, 0, STM32_AIN(11)}, + [ADC_VBUS] = { "VBUS", 33000, 4096, 0, STM32_AIN(11) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"battery", I2C_PORT_BATTERY, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"pd", I2C_PORT_PD_MCU, 1000, GPIO_I2C1_SCL, GPIO_I2C1_SDA} -}; +const struct i2c_port_t i2c_ports[] = { { .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "pd", + .port = I2C_PORT_PD_MCU, + .kbps = 1000, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA } }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); #ifdef CONFIG_ACCELGYRO_BMI160 /* SPI devices */ -const struct spi_device_t spi_devices[] = { - { CONFIG_SPI_ACCEL_PORT, 1, GPIO_SPI2_NSS } -}; +const struct spi_device_t spi_devices[] = { { CONFIG_SPI_ACCEL_PORT, 1, + GPIO_SPI2_NSS } }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); #endif @@ -175,42 +178,47 @@ const struct charger_config_t chg_chips[] = { * src/mainboard/google/${board}/acpi/dptf.asl */ const struct temp_sensor_t temp_sensors[] = { - {"TMP432_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_LOCAL}, - {"TMP432_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE1}, - {"TMP432_Sensor_2", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE2}, - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, - 0}, + { "TMP432_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_LOCAL }, + { "TMP432_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE1 }, + { "TMP432_Sensor_2", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE2 }, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); #ifdef HAS_TASK_ALS /* ALS instances. Must be in same order as enum als_id. */ struct als_t als[] = { - {"TI", opt3001_init, opt3001_read_lux, 5}, + { "TI", opt3001_init, opt3001_read_lux, 5 }, }; BUILD_ASSERT(ARRAY_SIZE(als) == ALS_COUNT); #endif -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, - .driver = &pi3usb3x532_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, }, { - .usb_port = 1, - .i2c_port = I2C_PORT_USB_MUX, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_USB_MUX, #if (BOARD_REV <= OAK_REV4) - .i2c_addr_flags = PI3USB3X532_I2C_ADDR1, - .driver = &pi3usb3x532_usb_mux_driver, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR1, + .driver = &pi3usb3x532_usb_mux_driver, #else - .i2c_addr_flags = 0x10, - .driver = &ps8740_usb_mux_driver, + .i2c_addr_flags = 0x10, + .driver = &ps8740_usb_mux_driver, #endif + }, }, }; @@ -281,7 +289,7 @@ static void board_init(void) STM32_DMA_CSELR(STM32_DMAC_CH6) |= (3 << 20) | (3 << 24); /* Enable SPI for BMI160 */ - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); /* Set all four SPI pins to high speed */ /* pins D0/D1/D3/D4 */ @@ -294,7 +302,7 @@ static void board_init(void) STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); CPRINTS("Board using SPI sensors"); #endif } @@ -331,10 +339,12 @@ int board_set_active_charge_port(int charge_port) } else { /* Make sure non-charging port is disabled */ gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_L : - GPIO_USB_C1_CHARGE_L, 1); + GPIO_USB_C1_CHARGE_L, + 1); /* Enable charging port */ gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_L : - GPIO_USB_C0_CHARGE_L, 0); + GPIO_USB_C0_CHARGE_L, + 0); } return EC_SUCCESS; @@ -348,11 +358,10 @@ int board_set_active_charge_port(int charge_port) * @param charge_ma Desired charge limit (mA). * @param charge_mv Negotiated charge voltage (mV). */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -543,9 +552,8 @@ void vbus_task(void *u) } if (wake) - task_set_event(port ? TASK_ID_USB_CHG_P1 : - TASK_ID_USB_CHG_P0, - USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(port, + USB_CHG_EVENT_BC12); } task_wait_event(-1); } @@ -561,15 +569,15 @@ void vbus_task(void *u) #ifdef CONFIG_TEMP_SENSOR_TMP432 static void tmp432_set_power_deferred(void) { - /* Shut tmp432 down if not in S0 && no external power */ - if (!extpower_is_present() && !chipset_in_state(CHIPSET_STATE_ON)) { - if (EC_SUCCESS != tmp432_set_power(TMP432_POWER_OFF)) + /* Shut tmp432 down if not in S0 && no external power */ + if (!extpower_is_present() && !chipset_in_state(CHIPSET_STATE_ON)) { + if (EC_SUCCESS != tmp432_set_power(TMP432_POWER_OFF)) CPRINTS("ERROR: Can't shutdown TMP432."); - return; - } + return; + } - /* else, turn it on. */ - if (EC_SUCCESS != tmp432_set_power(TMP432_POWER_ON)) + /* else, turn it on. */ + if (EC_SUCCESS != tmp432_set_power(TMP432_POWER_ON)) CPRINTS("ERROR: Can't turn on TMP432."); } DECLARE_DEFERRED(tmp432_set_power_deferred); @@ -594,7 +602,7 @@ static void board_chipset_pre_init(void) board_extpower_buffer_to_soc(); #if BOARD_REV >= OAK_REV5 /* Enable DP muxer */ - gpio_set_level(GPIO_DP_MUX_EN_L , 0); + gpio_set_level(GPIO_DP_MUX_EN_L, 0); gpio_set_level(GPIO_PARADE_MUX_EN, 1); #endif } @@ -607,13 +615,12 @@ static void board_chipset_shutdown(void) gpio_set_level(GPIO_LEVEL_SHIFT_EN_L, 1); #if BOARD_REV >= OAK_REV5 /* Disable DP muxer */ - gpio_set_level(GPIO_DP_MUX_EN_L , 1); + gpio_set_level(GPIO_DP_MUX_EN_L, 1); gpio_set_level(GPIO_PARADE_MUX_EN, 0); #endif } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); - /* Called on AP S3 -> S0 transition */ static void board_chipset_resume(void) { @@ -642,11 +649,9 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; #endif static struct kionix_accel_data g_kx022_data; @@ -669,7 +674,7 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(0), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(0), .rot_standard_ref = &base_standard_ref, .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, @@ -693,7 +698,7 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(0), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(0), .default_range = 1000, /* dps */ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_GYRO_MIN_FREQ, @@ -728,7 +733,7 @@ struct motion_sensor_t motion_sensors[] = { }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } diff --git a/board/oak/board.h b/board/oak/board.h index d959763853..c429a655c5 100644 --- a/board/oak/board.h +++ b/board/oak/board.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,17 +11,20 @@ /* board revision */ #include "board_revs.h" +/* Free up some flash space */ +#define CONFIG_DEBUG_ASSERT_BRIEF +#define CONFIG_USB_PD_DEBUG_LEVEL 0 +#undef CONFIG_CONSOLE_CMDHELP + #define CONFIG_LTO #if BOARD_REV >= OAK_REV5 #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCEL_KX022 -#define CONFIG_CMD_ACCELS -#define CONFIG_CMD_ACCEL_INFO #endif #define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG +#undef CONFIG_ADC_WATCHDOG #if BOARD_REV >= OAK_REV5 /* Add for Ambient Light Sensor */ @@ -37,7 +40,8 @@ #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #if BOARD_REV == OAK_REV1 #define CONFIG_CHARGER_BQ24773 @@ -57,7 +61,6 @@ #define CONFIG_CMD_TYPEC #define CONFIG_EXTPOWER_GPIO #define CONFIG_FORCE_CONSOLE_RESUME -#define CONFIG_CMD_CHARGER_ADC_AMON_BMON /* * EC_WAKE: PA0 - WKUP1 @@ -77,7 +80,7 @@ #define CONFIG_HOSTCMD_PD #define CONFIG_HOSTCMD_PD_PANIC #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_LED_COMMON @@ -103,13 +106,12 @@ #define CONFIG_USB_PD_TRY_SRC #define CONFIG_USB_PD_VBUS_DETECT_TCPC #define CONFIG_SPI -#define CONFIG_SPI_MASTER -#define CONFIG_STM_HWTIMER32 +#define CONFIG_SPI_CONTROLLER #define CONFIG_VBOOT_HASH -#undef CONFIG_WATCHDOG_HELP +#undef CONFIG_WATCHDOG_HELP #define CONFIG_SWITCH #define CONFIG_BOARD_VERSION_GPIO -#undef CONFIG_UART_CONSOLE +#undef CONFIG_UART_CONSOLE #define CONFIG_UART_CONSOLE 1 #define CONFIG_TEMP_SENSOR #define CONFIG_TEMP_SENSOR_TMP432 @@ -127,6 +129,7 @@ /* Optional features */ #define CONFIG_CMD_HOSTCMD +#undef CONFIG_CMD_MFALLOW /* Drivers */ /* USB Mux */ @@ -147,19 +150,19 @@ #define KB_OUT_PORT_LIST GPIO_A, GPIO_B, GPIO_C, GPIO_D /* 2 I2C master ports, connect to battery, charger, pd and USB switches */ -#define I2C_PORT_MASTER 0 -#define I2C_PORT_ACCEL 0 -#define I2C_PORT_ALS 0 +#define I2C_PORT_MASTER 0 +#define I2C_PORT_ACCEL 0 +#define I2C_PORT_ALS 0 #define I2C_PORT_BATTERY 0 #define I2C_PORT_CHARGER 0 #define I2C_PORT_PERICOM 0 #define I2C_PORT_THERMAL 0 -#define I2C_PORT_PD_MCU 1 +#define I2C_PORT_PD_MCU 1 #define I2C_PORT_USB_MUX 1 -#define I2C_PORT_TCPC 1 +#define I2C_PORT_TCPC 1 /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* First SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* First SPI controller port (SPI2) */ /* Ambient Light Sensor address */ #define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS @@ -169,12 +172,12 @@ #define TIM_WATCHDOG 4 /* Define the host events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_FASTBOOT)) +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_FASTBOOT)) #include "gpio_signal.h" @@ -192,9 +195,9 @@ enum pwm_channel { }; enum adc_channel { - ADC_PSYS = 0, /* PC1: STM32_AIN(2) */ + ADC_PSYS = 0, /* PC1: STM32_AIN(2) */ ADC_AMON_BMON, /* PC0: STM32_AIN(10) */ - ADC_VBUS, /* PA2: STM32_AIN(11) */ + ADC_VBUS, /* PA2: STM32_AIN(11) */ ADC_CH_COUNT }; @@ -233,17 +236,16 @@ enum als_id { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA CONFIG_CHARGER_MAX_INPUT_CURRENT -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA CONFIG_CHARGER_MAX_INPUT_CURRENT +#define PD_MAX_VOLTAGE_MV 20000 /* Reset PD MCU */ void board_reset_pd_mcu(void); @@ -255,6 +257,6 @@ void board_typec_dp_on(int port); void board_typec_dp_off(int port, int *dp_flags); void board_typec_dp_set(int port, int level); -#endif /* !__ASSEMBLER__ */ +#endif /* !__ASSEMBLER__ */ -#endif /* __CROS_EC_BOARD_H */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/oak/board_revs.h b/board/oak/board_revs.h index 34fc4bfc88..6220a05fb0 100644 --- a/board/oak/board_revs.h +++ b/board/oak/board_revs.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,7 +12,7 @@ #define OAK_REV3 3 #define OAK_REV4 4 #define OAK_REV5 5 -#define OAK_REV_LAST OAK_REV5 +#define OAK_REV_LAST OAK_REV5 #define OAK_REV_DEFAULT OAK_REV5 #if !defined(BOARD_REV) diff --git a/board/oak/build.mk b/board/oak/build.mk index dc21970df0..1cbbb2ac63 100644 --- a/board/oak/build.mk +++ b/board/oak/build.mk @@ -1,5 +1,5 @@ #-*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/oak/ec.tasklist b/board/oak/ec.tasklist index 2af7da77eb..80c39f2617 100644 --- a/board/oak/ec.tasklist +++ b/board/oak/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/oak/gpio.inc b/board/oak/gpio.inc index 70bb3a7bba..b2ce008363 100644 --- a/board/oak/gpio.inc +++ b/board/oak/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -210,5 +210,5 @@ ALTERNATE(PIN_MASK(B, 0x00c0), 1, MODULE_I2C, 0) /* I2C MASTER:PB6/7 */ ALTERNATE(PIN_MASK(B, 0x6000), 5, MODULE_I2C, 0) /* I2C MASTER:PB13/14 */ ALTERNATE(PIN_MASK(A, 0x00f0), 0, MODULE_SPI, 0) /* SPI SLAVE:PA4/5/6/7 */ #if BOARD_REV >= OAK_REV5 -ALTERNATE(PIN_MASK(D, 0x001A), 1, MODULE_SPI_MASTER, 0) /* SPI MASTER:PD1/3/4 */ +ALTERNATE(PIN_MASK(D, 0x001A), 1, MODULE_SPI_CONTROLLER, 0) /* SPI MASTER:PD1/3/4 */ #endif diff --git a/board/oak/led.c b/board/oak/led.c index 877f115a12..ac7d78118b 100644 --- a/board/oak/led.c +++ b/board/oak/led.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,12 +11,10 @@ #include "gpio.h" #include "hooks.h" #include "led_common.h" -#include "util.h" #include "system.h" +#include "util.h" -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -27,7 +25,7 @@ enum led_color { BAT_LED_AMBER, PWR_LED_GREEN, PWR_LED_ORANGE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int bat_led_set(enum led_color color, int on) @@ -113,7 +111,7 @@ static void oak_led_set_power(int board_version) power_second++; - switch(board_version) { + switch (board_version) { case OAK_REV3: case OAK_REV4: /* @@ -131,8 +129,7 @@ static void oak_led_set_power(int board_version) bat_led_set(PWR_LED_ORANGE, 0); } else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) { bat_led_set(PWR_LED_GREEN, 0); - bat_led_set(PWR_LED_ORANGE, - (power_second & 3) ? 0 : 1); + bat_led_set(PWR_LED_ORANGE, (power_second & 3) ? 0 : 1); } break; default: @@ -146,7 +143,7 @@ static void oak_led_set_battery(int board_version) battery_second++; - switch(board_version) { + switch (board_version) { case OAK_REV3: case OAK_REV4: /* @@ -157,29 +154,29 @@ static void oak_led_set_battery(int board_version) * - Battery discharging capacity<10%, red blink * - Battery error: Red ON */ - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: bat_led_set(BAT_LED_AMBER, 1); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: bat_led_set(BAT_LED_GREEN, 1); bat_led_set(BAT_LED_RED, 0); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: bat_led_set(BAT_LED_GREEN, 0); if (charge_get_percent() < 3) bat_led_set(BAT_LED_RED, - (battery_second & 1) ? 0 : 1); + (battery_second & 1) ? 0 : 1); else if (charge_get_percent() < 10) bat_led_set(BAT_LED_RED, - (battery_second & 3) ? 0 : 1); + (battery_second & 3) ? 0 : 1); else bat_led_set(BAT_LED_RED, 0); break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: bat_led_set(BAT_LED_RED, 1); break; - case PWR_STATE_IDLE: /* Ext. power connected in IDLE. */ + case LED_PWRS_IDLE: /* Ext. power connected in IDLE. */ bat_led_set(BAT_LED_GREEN, 1); bat_led_set(BAT_LED_RED, 0); break; @@ -191,7 +188,8 @@ static void oak_led_set_battery(int board_version) default: /* * Put power control here since we are using the "battery" LED. - * This allows LED autocontrol to be turned off by cmd during factory test. + * This allows LED autocontrol to be turned off by cmd during + * factory test. * * PWR LED behavior: * Power on: Green @@ -205,8 +203,8 @@ static void oak_led_set_battery(int board_version) else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) { int cycle_time = 4; /* Oak rev5 with GlaDOS ID has a extremely power - * comsuming LED. Increase LED blink cycle time to reduce - * S3 power comsuption. */ + * comsuming LED. Increase LED blink cycle time to + * reduce S3 power comsuption. */ if (board_version >= OAK_REV5) cycle_time = 10; bat_led_set(BAT_LED_GREEN, @@ -221,28 +219,28 @@ static void oak_led_set_battery(int board_version) * situation: Orange in blinking mode (1s on, 1s off) * Using battery or not connected to AC power: OFF */ - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: bat_led_set(BAT_LED_ORANGE, 1); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: bat_led_set(BAT_LED_ORANGE, 1); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (charge_get_percent() < 3) bat_led_set(BAT_LED_ORANGE, - (battery_second & 1) ? 0 : 1); + (battery_second & 1) ? 0 : 1); else if (charge_get_percent() < 10) bat_led_set(BAT_LED_ORANGE, - (battery_second & 3) ? 0 : 1); + (battery_second & 3) ? 0 : 1); else bat_led_set(BAT_LED_ORANGE, 0); break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: bat_led_set(BAT_LED_ORANGE, (battery_second & 1) ? 0 : 1); break; - case PWR_STATE_IDLE: /* Ext. power connected in IDLE. */ + case LED_PWRS_IDLE: /* Ext. power connected in IDLE. */ bat_led_set(BAT_LED_ORANGE, 0); break; default: diff --git a/board/oak/usb_pd_policy.c b/board/oak/usb_pd_policy.c index bf2fca3f49..2419927c17 100644 --- a/board/oak/usb_pd_policy.c +++ b/board/oak/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,21 +14,19 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_set_power_supply_ready(int port) { /* Disable charging */ - gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : - GPIO_USB_C0_CHARGE_L, 1); + gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : GPIO_USB_C0_CHARGE_L, 1); /* Provide VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN, 1); + gpio_set_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN, 1); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -39,8 +37,7 @@ int pd_set_power_supply_ready(int port) void pd_power_supply_reset(int port) { /* Disable VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN, 0); + gpio_set_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN, 0); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -101,7 +98,6 @@ __override int svdm_dp_attention(int port, uint32_t *payload) __override void svdm_exit_dp_mode(int port) { - svdm_safe_dp_mode(port); board_typec_dp_off(port, dp_flags); } #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/board/oak/vif_override.xml b/board/oak/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/oak/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/omnigul/battery.c b/board/omnigul/battery.c new file mode 100644 index 0000000000..0fae9dbe56 --- /dev/null +++ b/board/omnigul/battery.c @@ -0,0 +1,111 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Brya battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* LGC AP19B8M Battery Information */ + /* + * Battery info provided by ODM on b/263691095, comment #2 + */ + [BATTERY_AP19B8M] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G024", + .device_name = "AP19B8M", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0003, /* D-FET C-FET */ + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13350, + .voltage_normal = 11610, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* COSMX AP20CBL Battery Information */ + /* + * Battery info provided by ODM on b/263691095, comment #2 + */ + [BATTERY_AP20CBL] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B004", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, /* D-FET C-FET */ + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AP19B8M; + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} diff --git a/board/omnigul/board.c b/board/omnigul/board.c new file mode 100644 index 0000000000..0c963416f2 --- /dev/null +++ b/board/omnigul/board.c @@ -0,0 +1,50 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "button.h" +#include "charger.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + + if (IS_ENABLED(CONFIG_PWM_KBLIGHT)) + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + + if (IS_ENABLED(CONFIG_PWM_KBLIGHT)) + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); diff --git a/board/omnigul/board.h b/board/omnigul/board.h new file mode 100644 index 0000000000..f9d6f841a9 --- /dev/null +++ b/board/omnigul/board.h @@ -0,0 +1,255 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* + * Early brya boards are not set up for vivaldi + */ +#undef CONFIG_KEYBOARD_VIVALDI + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* LED */ +#define CONFIG_LED_PWM +#define CONFIG_LED_PWM_COUNT 1 +#undef CONFIG_LED_PWM_NEAR_FULL_COLOR +#undef CONFIG_LED_PWM_SOC_ON_COLOR +#undef CONFIG_LED_PWM_SOC_SUSPEND_COLOR +#undef CONFIG_LED_PWM_LOW_BATT_COLOR +#undef CONFIG_LED_PWM_CHARGE_ERROR_COLOR +#undef LED_CHARGER_ERROR_ON_TIME +#undef LED_CHARGER_ERROR_PERIOD +#define CONFIG_LED_PWM_NEAR_FULL_COLOR EC_LED_COLOR_BLUE +#define CONFIG_LED_PWM_SOC_ON_COLOR EC_LED_COLOR_BLUE +#define CONFIG_LED_PWM_SOC_SUSPEND_COLOR EC_LED_COLOR_AMBER +#define CONFIG_LED_PWM_LOW_BATT_COLOR EC_LED_COLOR_AMBER +#define CONFIG_LED_PWM_CHARGE_ERROR_COLOR EC_LED_COLOR_AMBER +#define LED_CHARGER_ERROR_ON_TIME 5 +#define LED_CHARGER_ERROR_PERIOD 10 + +/* Sensors */ +#define CONFIG_ACCELGYRO_LSM6DSO /* Base accel */ +#define CONFIG_ACCEL_LSM6DSO_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Lid accel */ +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_ACCEL_LIS2DWL +#define CONFIG_ACCEL_LIS2DW12_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 1 + +#define CONFIG_USB_PD_FRS_PPC + +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID +#undef CONFIG_USB_CHARGER +#undef CONFIG_BC12_DETECT_PI3USB9201 + +#define CONFIG_USB_PD_COMM_LOCKED + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_NX20P3483 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 65W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 65000 +#define PD_MAX_CURRENT_MA 3250 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Because of b:279526032, modify monitor Vbus from Charger to TCPC. + */ +#undef CONFIG_USB_PD_VBUS_MEASURE_CHARGER +#define CONFIG_USB_PD_VBUS_MEASURE_TCPC + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* + * see b/174768555#comment22 + */ +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C2_BB_RETIMER_I2C_ADDR 0x57 + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT +#define RPM_DEVIATION 2 + +/* Charger defines */ +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 10 + +/* KEYBOARD */ +#define CONFIG_KEYBOARD_CUSTOMIZATION +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* DISABLE POWERINDEBUG */ +#undef CONFIG_CMD_POWERINDEBUG + +/* + * Older boards have a different ADC assignment. + */ + +#define CONFIG_ADC_CHANNELS_RUNTIME_CONFIG + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_AMBIENT, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_AMBIENT, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { LID_ACCEL = 0, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C2_NCT38XX, IOEX_PORT_COUNT }; + +enum battery_type { BATTERY_AP19B8M, BATTERY_AP20CBL, BATTERY_TYPE_COUNT }; + +enum pwm_channel { + PWM_CH_LED2 = 0, /* PWM0 (white charger) */ + PWM_CH_LED1, /* PWM2 (orange charger) */ + PWM_CH_KBLIGHT, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/omnigul/build.mk b/board/omnigul/build.mk new file mode 100644 index 0000000000..d8488c6b9d --- /dev/null +++ b/board/omnigul/build.mk @@ -0,0 +1,26 @@ +# -*- makefile -*- +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o +board-y+=keyboard_customization.o diff --git a/board/omnigul/charger.c b/board/omnigul/charger.c new file mode 100644 index 0000000000..b3ca8dc104 --- /dev/null +++ b/board/omnigul/charger.c @@ -0,0 +1,82 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/omnigul/ec.tasklist b/board/omnigul/ec.tasklist new file mode 100644 index 0000000000..c2ef5f48cc --- /dev/null +++ b/board/omnigul/ec.tasklist @@ -0,0 +1,27 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(2) | BIT(0)), BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/omnigul/fans.c b/board/omnigul/fans.c new file mode 100644 index 0000000000..714449696f --- /dev/null +++ b/board/omnigul/fans.c @@ -0,0 +1,89 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/181271666): thermistor placement and calibration + * + * Prototype fan spins at about 4200 RPM at 100% PWM, this + * is specific to board ID 2 and might also apears in later + * boards as well. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2100, + .rpm_start = 2400, + .rpm_max = 4464, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/181271666): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/omnigul/fw_config.c b/board/omnigul/fw_config.c new file mode 100644 index 0000000000..34b460dad1 --- /dev/null +++ b/board/omnigul/fw_config.c @@ -0,0 +1,48 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union omnigul_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for Omnigul if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union omnigul_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, + .tab_mode = TABLETMODE_DISABLED, + .aud = AUDIO_ALC5682I_ALC1019, + .sar_id = SAR_ID_0, +}; + +/**************************************************************************** + * Omnigul FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union omnigul_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +bool ec_cfg_has_tabletmode(void) +{ + return (fw_config.tab_mode == TABLETMODE_ENABLED); +} diff --git a/board/omnigul/fw_config.h b/board/omnigul/fw_config.h new file mode 100644 index 0000000000..d0facef0da --- /dev/null +++ b/board/omnigul/fw_config.h @@ -0,0 +1,58 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_OMNIGUL_FW_CONFIG_H_ +#define __BOARD_OMNIGUL_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Omnigul board. + * + * Source of truth is the project/brya/brya/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_tabletmode_type { TABLETMODE_DISABLED = 0, TABLETMODE_ENABLED = 1 }; + +enum ec_cfg_storage_type { + STORAGE_UNPROVISION = 0, + STORAGE_UFS = 1, + STORAGE_NVMe = 2 +}; + +enum ec_cfg_audio_type { + AUDIO_ALC5682I_ALC1019 = 0, + AUDIO_ALC5682I_ALC1019_3MIC = 1 +}; + +enum ec_cfg_sar_id { SAR_ID_0 = 0, SAR_ID_1 = 1 }; + +union omnigul_cbi_fw_config { + struct { + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + enum ec_cfg_tabletmode_type tab_mode : 1; + enum ec_cfg_storage_type stg : 2; + enum ec_cfg_audio_type aud : 1; + enum ec_cfg_sar_id sar_id : 1; + uint32_t reserved_1 : 26; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union omnigul_cbi_fw_config get_fw_config(void); + +bool ec_cfg_has_tabletmode(void); + +#endif /* __BOARD_OMNIGUL_FW_CONFIG_H_ */ diff --git a/board/omnigul/generated-gpio.inc b/board/omnigul/generated-gpio.inc new file mode 100644 index 0000000000..8fec026b96 --- /dev/null +++ b/board/omnigul/generated-gpio.inc @@ -0,0 +1,125 @@ +/* + * This file was auto-generated. + */ + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_ACCEL_INT_R_L, PIN(8, 1), GPIO_SEL_1P8V | GPIO_INT_FALLING, lis2dw12_interrupt) +GPIO_INT(EC_IMU_INT_R_L, PIN(5, 6), GPIO_SEL_1P8V | GPIO_INT_FALLING, lsm6dso_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_ODR_HIGH) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(6, 0x01), 0, MODULE_PWM, 0) /* GPIO60/PWM7 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x1c), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0, GPIOC2/PWM1/I2C6_SCL0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ +UNUSED(PIN(4, 1)) /* GPIO41/ADC4 */ +UNUSED(PIN(7, 0)) /* GPIO70/PS2_DAT0 */ +UNUSED(PIN(8, 3)) /* GPIO83/KSO15 */ +UNUSED(PIN(9, 6)) /* GPIO96/F_DIO1 */ +UNUSED(PIN(B, 1)) /* GPIOB1/KSO17/CR_SIN4 */ +UNUSED(PIN(D, 0)) /* GPIOD0/I2C3_SDA0 */ +UNUSED(PIN(D, 1)) /* GPIOD1/I2C3_SCL0 */ +UNUSED(PIN(D, 4)) /* GPIOD4/CR_SIN3 */ +UNUSED(PIN(C, 6)) /* GPIOC6/SMI */ + +/* Pre-configured PSL balls: J8 K6 */ diff --git a/board/omnigul/gpio.inc b/board/omnigul/gpio.inc new file mode 100644 index 0000000000..0bb243eefe --- /dev/null +++ b/board/omnigul/gpio.inc @@ -0,0 +1,38 @@ +/* -*- mode:c -*- + * + * Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* + * Generated-gpio.inc is produced using a Brya specific tool that + * parses the GPIO definitions derived from the board schematics and + * EC pinout descriptions derived form the chip datasheets to generate + * the Chrome EC GPIO pinout definitions. Due to the confidential + * nature of schematics and datasheets, they are not provided here. + * + * Variants that do not auto-generate their GPIO definitions should + * combine the Brya gpio.inc and generated-gpio.inc into their + * gpio.inc and customize as appropriate. + */ + +#include "generated-gpio.inc" + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* IO expander configuration */ + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) +/* GPIO07_P2 to PU */ diff --git a/board/omnigul/i2c.c b/board/omnigul/i2c.c new file mode 100644 index 0000000000..1dfad89ee4 --- /dev/null +++ b/board/omnigul/i2c.c @@ -0,0 +1,73 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "hooks.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0", + .port = I2C_PORT_USB_C0_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_PPC_BC_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/omnigul/keyboard.c b/board/omnigul/keyboard.c new file mode 100644 index 0000000000..8e26876a73 --- /dev/null +++ b/board/omnigul/keyboard.c @@ -0,0 +1,75 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xa4, 0xff, 0xf7, 0x55, 0xfb, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config omnigul_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &omnigul_kb; +} + +/* + * Row Column info for Top row keys T1 - T15. + * on mithrax_kb keyboard Row Column is customization + * need define row col to mapping matrix layout. + */ +__override const struct key { + uint8_t row; + uint8_t col; +} vivaldi_keys[] = { + { .row = 0, .col = 2 }, /* T1 */ + { .row = 3, .col = 2 }, /* T2 */ + { .row = 2, .col = 2 }, /* T3 */ + { .row = 1, .col = 2 }, /* T4 */ + { .row = 3, .col = 4 }, /* T5 */ + { .row = 2, .col = 4 }, /* T6 */ + { .row = 1, .col = 4 }, /* T7 */ + { .row = 2, .col = 9 }, /* T8 */ + { .row = 1, .col = 9 }, /* T9 */ + { .row = 0, .col = 4 }, /* T10 */ + { .row = 3, .col = 0 }, /* T11 */ + { .row = 1, .col = 5 }, /* T12 */ + { .row = 3, .col = 5 }, /* T13 */ + { .row = 0, .col = 9 }, /* T14 */ + { .row = 0, .col = 11 }, /* T15 */ +}; +BUILD_ASSERT(ARRAY_SIZE(vivaldi_keys) == MAX_TOP_ROW_KEYS); diff --git a/board/omnigul/keyboard_customization.c b/board/omnigul/keyboard_customization.c new file mode 100644 index 0000000000..51d9e2d898 --- /dev/null +++ b/board/omnigul/keyboard_customization.c @@ -0,0 +1,102 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "gpio.h" +#include "keyboard_8042_sharedlib.h" +#include "keyboard_config.h" +#include "keyboard_customization.h" +#include "keyboard_protocol.h" +#include "keyboard_raw.h" + +static uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 0x0000, 0x0000, 0x0014, 0x0000, 0xe014, 0x0000, 0x0000, 0x0000 }, + { 0xe01f, 0x0076, 0x000d, 0x000e, 0x001c, 0x001a, 0x0016, 0x0015 }, + { 0x0005, 0x000c, 0x0004, 0x0006, 0x0023, 0x0021, 0x0026, 0x0024 }, + { 0x0032, 0x0034, 0x002c, 0x002e, 0x002b, 0x002a, 0x0025, 0x002d }, + { 0x000a, 0x0083, 0x000b, 0x0003, 0x001b, 0x0022, 0x001e, 0x001d }, + { 0x0051, 0x0000, 0x005b, 0x0000, 0x0042, 0x0041, 0x003e, 0x0043 }, + { 0x0031, 0x0033, 0x0035, 0x0036, 0x003b, 0x003a, 0x003d, 0x003c }, + { 0x0000, 0x0000, 0x0061, 0x0000, 0x0000, 0x0012, 0x0000, 0x0059 }, + { 0x0055, 0x0052, 0x0054, 0x004e, 0x004c, 0x004a, 0x0045, 0x004d }, + { 0x0000, 0x0078, 0x0009, 0x0000, 0x004b, 0x0049, 0x0046, 0x0044 }, + { 0xe011, 0x0000, 0x006a, 0x0000, 0x005d, 0x0000, 0x0011, 0x0000 }, + { 0x0000, 0x0066, 0x0000, 0x005d, 0x005a, 0x0029, 0xe072, 0xe075 }, + { 0x0000, 0xe064, 0x0000, 0x0067, 0x0000, 0x0000, 0xe074, 0xe06b }, +}; + +uint16_t get_scancode_set2(uint8_t row, uint8_t col) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + return scancode_set2[col][row]; + return 0; +} + +void set_scancode_set2(uint8_t row, uint8_t col, uint16_t val) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + scancode_set2[col][row] = val; +} + +void board_keyboard_drive_col(int col) +{ + /* Drive all lines to high */ + if (col == KEYBOARD_COLUMN_NONE) + gpio_set_level(GPIO_KBD_KSO2, 0); + + /* Set KBSOUT to zero to detect key-press */ + else if (col == KEYBOARD_COLUMN_ALL) + gpio_set_level(GPIO_KBD_KSO2, 1); + + /* Drive one line for detection */ + else { + if (col == 2) + gpio_set_level(GPIO_KBD_KSO2, 1); + else + gpio_set_level(GPIO_KBD_KSO2, 0); + } +} + +#ifdef CONFIG_KEYBOARD_DEBUG +static uint8_t keycap_label[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 'c', KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { 'q', KLLI_UNKNO, KLLI_UNKNO, KLLI_TAB, '`', '1', KLLI_UNKNO, 'a' }, + { KLLI_R_ALT, KLLI_L_ALT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_UNKNO, KLLI_SPACE, 'e', KLLI_F4, KLLI_SEARC, '3', KLLI_F3, + KLLI_UNKNO }, + { 'x', 'z', KLLI_F2, KLLI_F1, 's', '2', 'w', KLLI_ESC }, + { 'v', 'b', 'g', 't', '5', '4', 'r', 'f' }, + { 'm', 'n', 'h', 'y', '6', '7', 'u', 'j' }, + { '.', KLLI_DOWN, '\\', 'o', KLLI_F10, '9', KLLI_UNKNO, 'l' }, + { KLLI_R_SHT, KLLI_L_SHT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { ',', KLLI_UNKNO, KLLI_F7, KLLI_F6, KLLI_F5, '8', 'i', 'k' }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_F9, KLLI_UNKNO, KLLI_UNKNO, + KLLI_LEFT, KLLI_UNKNO }, + { KLLI_R_CTR, KLLI_L_CTR, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { '/', KLLI_UP, '-', KLLI_UNKNO, '0', 'p', '[', ';' }, + { '\'', KLLI_ENTER, KLLI_UNKNO, KLLI_UNKNO, '=', KLLI_B_SPC, ']', 'd' }, + { KLLI_UNKNO, KLLI_F8, KLLI_RIGHT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO }, +}; + +uint8_t get_keycap_label(uint8_t row, uint8_t col) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + return keycap_label[col][row]; + return KLLI_UNKNO; +} + +void set_keycap_label(uint8_t row, uint8_t col, uint8_t val) +{ + if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) + keycap_label[col][row] = val; +} +#endif diff --git a/board/omnigul/keyboard_customization.h b/board/omnigul/keyboard_customization.h new file mode 100644 index 0000000000..8e7e3ee2c1 --- /dev/null +++ b/board/omnigul/keyboard_customization.h @@ -0,0 +1,80 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Keyboard configuration */ + +#ifndef __KEYBOARD_CUSTOMIZATION_H +#define __KEYBOARD_CUSTOMIZATION_H + +#define KEYBOARD_MASK_PWRBTN KEYBOARD_ROW_TO_MASK(3) + +/* + * KEYBOARD_COLS_MAX has the build time column size. It's used to allocate + * exact spaces for arrays. Actual keyboard scanning is done using + * keyboard_cols, which holds a runtime column size. + */ +#ifdef CONFIG_KEYBOARD_CUSTOMIZATION +#undef KEYBOARD_COLS_MAX +#undef KEYBOARD_ROWS + +#define KEYBOARD_COLS_MAX 13 +#define KEYBOARD_ROWS 8 +#endif + +/* + * WARNING: Do not directly modify it. You should call keyboard_raw_set_cols, + * instead. It checks whether you're eligible or not. + */ +extern uint8_t keyboard_cols; + +#define KEYBOARD_ROW_TO_MASK(r) (1 << (r)) + +/* Columns and masks for keys we particularly care about */ +#define KEYBOARD_COL_DOWN 11 +#define KEYBOARD_ROW_DOWN 6 +#define KEYBOARD_MASK_DOWN KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_DOWN) +#define KEYBOARD_COL_ESC 1 +#define KEYBOARD_ROW_ESC 1 +#define KEYBOARD_MASK_ESC KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_ESC) +#define KEYBOARD_COL_KEY_H 6 +#define KEYBOARD_ROW_KEY_H 1 +#define KEYBOARD_MASK_KEY_H KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_H) +#define KEYBOARD_COL_KEY_R 3 +#define KEYBOARD_ROW_KEY_R 7 +#define KEYBOARD_MASK_KEY_R KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_R) +#define KEYBOARD_COL_LEFT_ALT 10 +#define KEYBOARD_ROW_LEFT_ALT 6 +#define KEYBOARD_MASK_LEFT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_ALT) +#define KEYBOARD_COL_REFRESH 2 +#define KEYBOARD_ROW_REFRESH 3 +#define KEYBOARD_MASK_REFRESH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_REFRESH) +#define KEYBOARD_COL_RIGHT_ALT 10 +#define KEYBOARD_ROW_RIGHT_ALT 0 +#define KEYBOARD_MASK_RIGHT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_ALT) +#define KEYBOARD_DEFAULT_COL_VOL_UP 4 +#define KEYBOARD_DEFAULT_ROW_VOL_UP 0 +#define KEYBOARD_COL_LEFT_CTRL 0 +#define KEYBOARD_ROW_LEFT_CTRL 2 +#define KEYBOARD_MASK_LEFT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_CTRL) +#define KEYBOARD_COL_RIGHT_CTRL 0 +#define KEYBOARD_ROW_RIGHT_CTRL 4 +#define KEYBOARD_MASK_RIGHT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_CTRL) +#define KEYBOARD_COL_SEARCH 1 +#define KEYBOARD_ROW_SEARCH 0 +#define KEYBOARD_MASK_SEARCH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_SEARCH) +#define KEYBOARD_COL_KEY_0 8 +#define KEYBOARD_ROW_KEY_0 6 +#define KEYBOARD_MASK_KEY_0 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_0) +#define KEYBOARD_COL_KEY_1 1 +#define KEYBOARD_ROW_KEY_1 6 +#define KEYBOARD_MASK_KEY_1 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_1) +#define KEYBOARD_COL_KEY_2 4 +#define KEYBOARD_ROW_KEY_2 6 +#define KEYBOARD_MASK_KEY_2 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_2) +#define KEYBOARD_COL_LEFT_SHIFT 7 +#define KEYBOARD_ROW_LEFT_SHIFT 5 +#define KEYBOARD_MASK_LEFT_SHIFT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_SHIFT) + +#endif /* __KEYBOARD_CUSTOMIZATION_H */ diff --git a/board/omnigul/led.c b/board/omnigul/led.c new file mode 100644 index 0000000000..8437e7d554 --- /dev/null +++ b/board/omnigul/led.c @@ -0,0 +1,79 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya specific PWM LED settings: there are 2 LEDs on each side of the board, + * each one can be controlled separately. The LED colors are blue or amber, + * and the default behavior is tied to the charging process: both sides are + * amber while charging the battery and blue when the battery is charged. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "ec_commands.h" +#include "led_pwm.h" +#include "pwm.h" +#include "util.h" + +#include + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_LEFT_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +/* + * We only have a blue and an amber LED, so setting any other color results in + * both LEDs being off. Cap at 50% to save power. + */ +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Amber, Blue */ + [EC_LED_COLOR_RED] = { 0, 0 }, [EC_LED_COLOR_GREEN] = { 0, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 50 }, [EC_LED_COLOR_YELLOW] = { 0, 0 }, + [EC_LED_COLOR_WHITE] = { 0, 0 }, [EC_LED_COLOR_AMBER] = { 50, 0 }, +}; + +/* Two logical LEDs with amber and blue channels. */ +struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = { + { + .ch0 = PWM_CH_LED2, + .ch1 = PWM_CH_LED1, + .ch2 = PWM_LED_NO_CHANNEL, + .enable = &pwm_enable, + .set_duty = &pwm_set_duty, + }, +}; + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + memset(brightness_range, '\0', + sizeof(*brightness_range) * EC_LED_COLOR_COUNT); + brightness_range[EC_LED_COLOR_AMBER] = 100; + brightness_range[EC_LED_COLOR_BLUE] = 100; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + enum pwm_led_id pwm_id; + + /* Convert ec_led_id to pwm_led_id. */ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + pwm_id = PWM_LED0; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (brightness[EC_LED_COLOR_BLUE]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_AMBER]) + set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); + else + /* Otherwise, the "color" is "off". */ + set_pwm_led_color(pwm_id, -1); + + return EC_SUCCESS; +} diff --git a/board/omnigul/pwm.c b/board/omnigul/pwm.c new file mode 100644 index 0000000000..23046bac73 --- /dev/null +++ b/board/omnigul/pwm.c @@ -0,0 +1,56 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED2] = { + .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_LED1] = { + .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 12000, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn off all the LEDs. + * Turn on the fan at 100%. + */ + pwm_enable(PWM_CH_LED1, 1); + pwm_set_duty(PWM_CH_LED1, 0); + pwm_enable(PWM_CH_LED2, 1); + pwm_set_duty(PWM_CH_LED2, 0); + + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/omnigul/sensors.c b/board/omnigul/sensors.c new file mode 100644 index 0000000000..a2d08bd045 --- /dev/null +++ b/board/omnigul/sensors.c @@ -0,0 +1,270 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc.h" +#include "common.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "fw_config.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_AMBIENT] = { + .name = "TEMP_AMBIENT", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +static struct stprivate_data g_lis2dw12_data; +static struct lsm6dso_data lsm6dso_data; + +/* TODO(b/184779333): calibrate the orientation matrix on later board stage */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* TODO(b/184779743): verify orientation matrix */ +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DW12, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_lis2dw12_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DW12_ADDR0, + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSO_ST_DATA(lsm6dso_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void baseboard_sensors_init(void) +{ + if (ec_cfg_has_tabletmode()) { + /* Enable gpio interrupt for lid accel sensor */ + gpio_enable_interrupt(GPIO_EC_ACCEL_INT_R_L); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_R_L); + } else { + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_EC_ACCEL_INT_R_L, + GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_EC_IMU_INT_R_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { + .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC, + }, + [TEMP_SENSOR_2_AMBIENT] = { + .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_AMBIENT, + }, + [TEMP_SENSOR_3_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Alder Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_AMBIENT \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(70), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = C_TO_K(69), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(70), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(65), \ + } +__maybe_unused static const struct ec_thermal_config thermal_ambient = + THERMAL_AMBIENT; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 125C, max absolute temperature 150C + * PP3300 regulator: operating range -40 C to 125 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_AMBIENT] = THERMAL_AMBIENT, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/omnigul/usbc_config.c b/board/omnigul/usbc_config.c new file mode 100644 index 0000000000..307d4fccca --- /dev/null +++ b/board/omnigul/usbc_config.c @@ -0,0 +1,242 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_NO_DEBUG_ACC_CONTROL, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_VCONN | + TCPC_FLAGS_CONTROL_FRS | + TCPC_FLAGS_VBUS_MONITOR, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM5360A */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = NX20P3483_ADDR2_FLAGS, + .drv = &nx20p348x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* + * USB3 DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C2 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + + ioex_init(IOEX_C0_NCT38XX); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_2; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + nx20p348x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} diff --git a/board/omnigul/usbc_config.h b/board/omnigul/usbc_config.h new file mode 100644 index 0000000000..cd4e387406 --- /dev/null +++ b/board/omnigul/usbc_config.h @@ -0,0 +1,17 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Brya board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#ifndef CONFIG_ZEPHYR +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#endif + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/omnigul/vif_override.xml b/board/omnigul/vif_override.xml new file mode 100644 index 0000000000..6ade5d2f92 --- /dev/null +++ b/board/omnigul/vif_override.xml @@ -0,0 +1,148 @@ + + + 2 + 0 + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 9A1B + + + + + + Gen 3 (40Gb) + + + + USB 3.2 Gen 2x2 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + + + + + + USB 3.2 Gen 2x1 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PSD + PDUSB Host + + + + + Gen 3 (40Gb) + + USB 3.2 Gen 2x2 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + diff --git a/board/osiris/battery.c b/board/osiris/battery.c new file mode 100644 index 0000000000..669b592b1b --- /dev/null +++ b/board/osiris/battery.c @@ -0,0 +1,150 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger_profile_override.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Osiris battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* COSMX AP22ABN Battery Information */ + [BATTERY_COSMX_AP22ABN] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B003", + .device_name = "AP22ABN", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x8000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 13440, + .voltage_normal = 11670, + .voltage_min = 9000, + .precharge_current = 567, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_COSMX_AP22ABN; + +enum battery_present battery_hw_present(void) +{ + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} + +static int charger_should_discharge_on_ac(struct charge_state_data *curr) +{ + /* can not discharge on AC without battery */ + if (curr->batt.is_present != BP_YES) + return 0; + + /* Do not discharge when battery disconnect */ + if (battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED) + return 0; + + /* Do not discharge on AC if the battery is still waking up */ + if ((curr->batt.flags & BATT_FLAG_BAD_STATUS) || + (!(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + !(curr->batt.status & STATUS_FULLY_CHARGED))) + return 0; + + /* + * In heavy load (>3A being withdrawn from VSYS) the DCDC of the + * charger operates on hybrid mode. This causes a slight voltage + * ripple on VSYS that falls in the audible noise frequency (single + * digit kHz range). This small ripple generates audible noise in + * the output ceramic capacitors (caps on VSYS and any input of + * DCDC under VSYS). + * + * To overcome this issue, force battery discharging when battery + * full, So the battery MOS of NVDC charger will turn on always, + * it make the Vsys same as Vbat and the noise has been improved. + */ + if (!battery_is_cut_off() && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + return 1; + + return 0; +} + +/* + * This can override the smart battery's charging profile. To make a change, + * modify one or more of requested_voltage, requested_current, or state. + * Leave everything else unchanged. + * + * Return the next poll period in usec, or zero to use the default (which is + * state dependent). + */ +int charger_profile_override(struct charge_state_data *curr) +{ + int disch_on_ac = charger_should_discharge_on_ac(curr); + + charger_discharge_on_ac(disch_on_ac); + + if (disch_on_ac) { + curr->state = ST_DISCHARGE; + return 0; + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/osiris/board.c b/board/osiris/board.c new file mode 100644 index 0000000000..20c1ae0993 --- /dev/null +++ b/board/osiris/board.c @@ -0,0 +1,78 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + gpio_set_level(GPIO_AMP_PWR_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + gpio_set_level(GPIO_AMP_PWR_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +__override void board_kblight_shutdown(void) +{ + /* turn off keyboard backlight power */ + gpio_set_level(GPIO_KYBL_EN, 0); +} + +__override void board_kblight_init(void) +{ + /* turn on keyboard backlight power */ + gpio_set_level(GPIO_KYBL_EN, 1); + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); + msleep(10); +} + +/* keyboard factory test */ +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/osiris/board.h b/board/osiris/board.h new file mode 100644 index 0000000000..0c6cf2397e --- /dev/null +++ b/board/osiris/board.h @@ -0,0 +1,202 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Osiris board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* Tablet mode is not supported */ +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_LID_ANGLE + +/* LED */ +#define CONFIG_LED_ONOFF_STATES + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +#undef CONFIG_USB_PD_TCPM_NCT38XX +#define CONFIG_USB_PD_TCPM_PS8815 /* C0 and C1 */ + +#define CONFIG_USB_PD_FRS_PPC + +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID + +/* Retimer */ +#undef CONFIG_USBC_RETIMER_INTEL_BB + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +#define CONFIG_USBC_PPC_SYV682X + +/* TODO: b/177608416 - measure and check these values on osiris */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +#define CONFIG_CHARGER_PROFILE_OVERRIDE +#define CONFIG_PWR_STATE_DISCHARGE_FULL + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* I2C Bus Configuration */ + +#define I2C_PORT_RGBKB NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_C2_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_C2_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT +#define CONFIG_FAN_RPM_CUSTOM + +/* Charger defines */ +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +/* shutdown if soc <= 3%, default is 4% */ +#undef CONFIG_BATT_HOST_SHUTDOWN_PERCENTAGE +#define CONFIG_BATT_HOST_SHUTDOWN_PERCENTAGE 3 + +#undef CONFIG_VOLUME_BUTTONS + +/* RGB Keyboard */ +#define CONFIG_KEYBOARD_BACKLIGHT +#define GPIO_RGBKBD_SDB_L GPIO_EC_KB_BL_EN_L +#ifdef SECTION_IS_RW +#define CONFIG_RGB_KEYBOARD +#define CONFIG_LED_DRIVER_IS31FL3733B /* is31fl3733b on I2C */ +#endif +#define RGB_GRID0_COL 12 +#define RGB_GRID0_ROW 1 +#define I2C_PORT_KBMCU I2C_PORT_RGBKB + +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +#define CONFIG_KEYBOARD_FACTORY_TEST + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_AMBIENT, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_AMBIENT, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_COUNT +}; + +enum battery_type { BATTERY_COSMX_AP22ABN, BATTERY_TYPE_COUNT }; + +enum pwm_channel { + PWM_CH_FAN = 0, /* PWM5 */ + PWM_CH_FAN2, /* PWM3 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_1, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_1, MFT_CH_COUNT }; + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +extern const int keyboard_factory_scan_pins[][2]; +extern const int keyboard_factory_scan_pins_used; +#endif + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/osiris/build.mk b/board/osiris/build.mk new file mode 100644 index 0000000000..fc29a4bb0e --- /dev/null +++ b/board/osiris/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Osiris board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/osiris/charger.c b/board/osiris/charger.c new file mode 100644 index 0000000000..76e2712181 --- /dev/null +++ b/board/osiris/charger.c @@ -0,0 +1,80 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/osiris/ec.tasklist b/board/osiris/ec.tasklist new file mode 100644 index 0000000000..1b6c9cb361 --- /dev/null +++ b/board/osiris/ec.tasklist @@ -0,0 +1,30 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(RGBKBD, rgbkbd_task, NULL, BASEBOARD_RGBKBD_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(2) | BIT(0)), BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/osiris/fans.c b/board/osiris/fans.c new file mode 100644 index 0000000000..af7bc1e17f --- /dev/null +++ b/board/osiris/fans.c @@ -0,0 +1,220 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" +#include "util.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, + [MFT_CH_1] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN2, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_conf fan_conf_1 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_1, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN2, +}; + +/* + * TODO(b/234545460): thermistor placement and calibration + * + * Prototype fan spins at about 4200 RPM at 100% PWM, this + * is specific to board ID 2 and might also apears in later + * boards as well. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 6000, +}; + +static const struct fan_rpm fan_rpm_1 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 6000, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, + [FAN_CH_1] = { + .conf = &fan_conf_1, + .rpm = &fan_rpm_1, + }, +}; + +/* fan control */ + +struct fan_step { + int on; + int off; + int rpm; +}; + +struct fan_table_config { + /* number of control_table */ + uint8_t step; + /* fan control table */ + const struct fan_step *control_table; +}; + +const struct fan_step fan_table0[] = { + { .on = 25, .off = 0, .rpm = 0 }, + { .on = 37, .off = 34, .rpm = 2500 }, + { .on = 42, .off = 39, .rpm = 2800 }, + { .on = 46, .off = 43, .rpm = 3000 }, + { .on = 51, .off = 48, .rpm = 3200 }, + { .on = 55, .off = 52, .rpm = 3600 }, + { .on = 59, .off = 56, .rpm = 4000 }, + { .on = 66, .off = 63, .rpm = 4600 }, + { .on = 72, .off = 69, .rpm = 5000 }, + { .on = 74, .off = 71, .rpm = 5500 }, +}; +const int fan_table0_count = ARRAY_SIZE(fan_table0); + +const struct fan_step fan_table1[] = { + { .on = 25, .off = 0, .rpm = 0 }, + { .on = 51, .off = 48, .rpm = 3200 }, + { .on = 55, .off = 52, .rpm = 3600 }, + { .on = 59, .off = 56, .rpm = 4000 }, + { .on = 66, .off = 63, .rpm = 4600 }, + { .on = 72, .off = 69, .rpm = 5000 }, + { .on = 74, .off = 71, .rpm = 5500 }, +}; +const int fan_table1_count = ARRAY_SIZE(fan_table1); + +/* Fan control configuration */ +static struct fan_table_config fan_tables[] = { + [FAN_CH_0] = { + .step = fan_table0_count, + .control_table = (const struct fan_step *) &fan_table0, + }, + [FAN_CH_1] = { + .step = fan_table1_count, + .control_table = (const struct fan_step *) &fan_table1, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(fan_tables) == FAN_CH_COUNT); + +static int current_level[] = { 0, 0 }; +BUILD_ASSERT(ARRAY_SIZE(current_level) == FAN_CH_COUNT); + +static int previous_level[] = { 0, 0 }; +BUILD_ASSERT(ARRAY_SIZE(previous_level) == FAN_CH_COUNT); + +#undef BOARD_FAN_TEST + +#ifdef BOARD_FAN_TEST +static int manual_temp = -1; +#endif + +int fan_percent_to_rpm(int fan, int pct) +{ + static struct fan_table_config *fan_table; + static int previous_pct; + int i; + + fan_table = &fan_tables[fan]; + +#ifdef BOARD_FAN_TEST + if (manual_temp != -1) + pct = manual_temp; +#endif + + /* + * Compare the pct and previous pct, we have the three paths : + * 1. decreasing path. (check the off point) + * 2. increasing path. (check the on point) + * 3. invariant path. (return the current RPM) + */ + if (pct < previous_pct) { + for (i = current_level[fan]; i >= 0; i--) { + if (pct <= fan_table->control_table[i].off) + current_level[fan] = i - 1; + else + break; + } + } else if (pct > previous_pct) { + for (i = current_level[fan] + 1; i < fan_table->step; i++) { + if (pct >= fan_table->control_table[i].on) + current_level[fan] = i; + else + break; + } + } + + if (current_level[fan] < 0) + current_level[fan] = 0; + + if (current_level[fan] != previous_level[fan]) + cprints(CC_THERMAL, "Fan %d: Set fan RPM to %d", fan, + fan_table->control_table[current_level[fan]].rpm); + + if (fan == (FAN_CH_COUNT - 1)) + previous_pct = pct; + +#ifdef BOARD_FAN_TEST + if (manual_temp != -1) + ccprints("Fan%d: temps:%d curr:%d prev:%d rpm:%d", fan, pct, + current_level[fan], previous_level[fan], + fan_table->control_table[current_level[fan]].rpm); +#endif + + previous_level[fan] = current_level[fan]; + + return fan_table->control_table[current_level[fan]].rpm; +} + +#ifdef BOARD_FAN_TEST +static int command_fan_test(int argc, const char **argv) +{ + char *e; + int t; + + if (argc > 1) { + t = strtoi(argv[1], &e, 0); + if (*e) { + ccprints("Invalid test temp"); + return EC_ERROR_INVAL; + } + manual_temp = t; + ccprints("manual temp is %d", manual_temp); + return EC_SUCCESS; + } + manual_temp = -1; + ccprints("manual temp reset"); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(fan_test, command_fan_test, "[temperature]", + "set manual temperature for fan test"); +#endif diff --git a/board/osiris/fw_config.c b/board/osiris/fw_config.c new file mode 100644 index 0000000000..1fb085fe6e --- /dev/null +++ b/board/osiris/fw_config.c @@ -0,0 +1,40 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +static union osiris_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for osiris if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union osiris_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Osiris FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} + +union osiris_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} diff --git a/board/osiris/fw_config.h b/board/osiris/fw_config.h new file mode 100644 index 0000000000..fb776dc5a4 --- /dev/null +++ b/board/osiris/fw_config.h @@ -0,0 +1,39 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_OSIRIS_FW_CONFIG_H_ +#define __BOARD_OSIRIS_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Osiris board. + * + * Source of truth is the project/brya/osiris/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +union osiris_cbi_fw_config { + struct { + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t reserved_1 : 1; + uint32_t audio : 2; + uint32_t reserved_2 : 28; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union osiris_cbi_fw_config get_fw_config(void); + +#endif /* __BOARD_OSIRIS_FW_CONFIG_H_ */ diff --git a/board/osiris/gpio.inc b/board/osiris/gpio.inc new file mode 100644 index 0000000000..ea196571f8 --- /dev/null +++ b/board/osiris/gpio.inc @@ -0,0 +1,142 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(4, 1), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_LOW) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_FAN2, PIN(9, 7), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RST_ODL, PIN(9, 6), GPIO_ODR_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(KYBL_EN, PIN(A, 7), GPIO_OUT_LOW) +GPIO(AMP_PWR_EN, PIN(5, 7), GPIO_OUT_LOW) +GPIO(RGB_KB_INT, PIN(5, 6), GPIO_INPUT) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 4)) /* GPIO34 */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(8, 3)) /* GPIO83 */ +UNUSED(PIN(7, 0)) /* GPIO70 */ +UNUSED(PIN(8, 1)) /* GPIO81 */ +UNUSED(PIN(9, 3)) /* GPIO93 */ +UNUSED(PIN(D, 0)) /* GPIOD0/I2C3_SDA0 */ +UNUSED(PIN(D, 1)) /* GPIOD1/I2C3_SCL0 */ +UNUSED(PIN(9, 5)) /* GPIO95 */ + +/* Pre-configured PSL balls: J8 K6 */ + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +GPIO(USB_C0_OC_ODL, PIN(D, 4), GPIO_ODR_HIGH) +GPIO(USB_C0_FRS_EN, PIN(6, 0), GPIO_LOW) +GPIO(USB_C0_RT_RST_ODL, PIN(C, 2), GPIO_ODR_LOW) + +GPIO(USB_C1_OC_ODL, PIN(E, 1), GPIO_ODR_HIGH) \ No newline at end of file diff --git a/board/osiris/i2c.c b/board/osiris/i2c.c new file mode 100644 index 0000000000..2d0656c484 --- /dev/null +++ b/board/osiris/i2c.c @@ -0,0 +1,91 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "hooks.h" +#include "i2c.h" + +#define BOARD_ID_FAST_PLUS_CAPABLE 2 + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "rgbkb", + .port = I2C_PORT_RGBKB, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,2", + .port = I2C_PORT_USB_C0_C2_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,2", + .port = I2C_PORT_USB_C0_C2_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* + * I2C controllers are initialized in main.c. This sets the speed much + * later, but before I2C peripherals are initialized. + */ +static void set_board_legacy_i2c_speeds(void) +{ + if (get_board_id() >= BOARD_ID_FAST_PLUS_CAPABLE) + return; + + ccprints("setting USB DB I2C buses to 400 kHz\n"); + + i2c_set_freq(I2C_PORT_USB_C1_TCPC, I2C_FREQ_400KHZ); + i2c_set_freq(I2C_PORT_USB_C1_PPC, I2C_FREQ_400KHZ); +} +DECLARE_HOOK(HOOK_INIT, set_board_legacy_i2c_speeds, HOOK_PRIO_INIT_I2C - 1); diff --git a/board/osiris/keyboard.c b/board/osiris/keyboard.c new file mode 100644 index 0000000000..cd557760eb --- /dev/null +++ b/board/osiris/keyboard.c @@ -0,0 +1,140 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "hooks.h" +#include "keyboard_8042_sharedlib.h" +#include "keyboard_scan.h" +#include "rgb_keyboard.h" +#include "timer.h" + +#define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ##args) + +const struct key { + uint8_t row; + uint8_t col; +} vivaldi_keys[] = { + { .row = 4, .col = 2 }, /* T1 */ + { .row = 3, .col = 2 }, /* T2 */ + { .row = 2, .col = 2 }, /* T3 */ + { .row = 1, .col = 2 }, /* T4 */ + { .row = 4, .col = 4 }, /* T5 */ + { .row = 3, .col = 4 }, /* T6 */ + { .row = 2, .col = 4 }, /* T7 */ + { .row = 2, .col = 9 }, /* T8 */ + { .row = 1, .col = 9 }, /* T9 */ + { .row = 1, .col = 4 }, /* T10 */ + { .row = 0, .col = 4 }, /* T11 */ + { .row = 1, .col = 5 }, /* T12 */ + { .row = 3, .col = 5 }, /* T13 */ + { .row = 2, .col = 1 }, /* T14 */ + { .row = 0, .col = 1 }, /* T15 */ +}; +BUILD_ASSERT(ARRAY_SIZE(vivaldi_keys) == MAX_TOP_ROW_KEYS); + +static const struct ec_response_keybd_config osiris_vivaldi_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &osiris_vivaldi_kb; +} + +extern struct rgbkbd_drv is31fl3733b_drv; + +static struct rgb_s grid0[RGB_GRID0_COL * RGB_GRID0_ROW]; + +struct rgbkbd rgbkbds[] = { + [0] = { + .cfg = &(const struct rgbkbd_cfg) { + .drv = &is31fl3733b_drv, + .i2c = I2C_PORT_KBMCU, + .col_len = RGB_GRID0_COL, + .row_len = RGB_GRID0_ROW, + }, + .buf = grid0, + }, +}; +const uint8_t rgbkbd_count = ARRAY_SIZE(rgbkbds); + +const uint8_t rgbkbd_hsize = RGB_GRID0_COL; +const uint8_t rgbkbd_vsize = RGB_GRID0_ROW; + +enum ec_rgbkbd_type rgbkbd_type = EC_RGBKBD_TYPE_FOUR_ZONES_12_LEDS; + +#define LED(x, y) RGBKBD_COORD((x), (y)) +#define DELM RGBKBD_DELM + +const uint8_t rgbkbd_map[] = { + DELM, LED(0, 0), DELM, LED(1, 0), DELM, LED(2, 0), DELM, LED(3, 0), + DELM, LED(4, 0), DELM, LED(5, 0), DELM, LED(6, 0), DELM, LED(7, 0), + DELM, LED(8, 0), DELM, LED(9, 0), DELM, LED(10, 0), DELM, LED(11, 0), + DELM, DELM, +}; +#undef LED +#undef DELM +const size_t rgbkbd_map_size = ARRAY_SIZE(rgbkbd_map); + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x86, 0xff, 0xff, 0x55, 0xff, 0xff, 0xff, + 0xff /* full set */ + }, +}; + +static uint16_t scancode_set2_rgb[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 0x0000, 0x0000, 0x0014, 0xe01f, 0xe014, 0xe007, 0x0000, 0x0000 }, + { 0x001f, 0x0076, 0x0017, 0x000e, 0x001c, 0x003a, 0x000d, 0x0016 }, + { 0x006c, 0x000c, 0x0004, 0x0006, 0x0005, 0xe071, 0x0026, 0x002a }, + { 0x0032, 0x0034, 0x002c, 0x002e, 0x002b, 0x0029, 0x0025, 0x002d }, + { 0x0078, 0x0009, 0x0083, 0x000b, 0x0003, 0x0041, 0x001e, 0x001d }, + { 0x0051, 0x0007, 0x005b, 0x0000, 0x0042, 0x0022, 0x003e, 0x0043 }, + { 0x0031, 0x0033, 0x0035, 0x0036, 0x003b, 0x001b, 0x003d, 0x003c }, + { 0x0000, 0x0012, 0x0061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0059 }, + { 0x0055, 0x0052, 0x0054, 0x004e, 0x004c, 0x0024, 0x0044, 0x004d }, + { 0x0045, 0x0001, 0x000a, 0x002f, 0x004b, 0x0049, 0x0046, 0x001A }, + { 0xe011, 0x0000, 0x006a, 0x0000, 0x005d, 0x0000, 0x0011, 0x0000 }, + { 0xe07a, 0x005d, 0xe075, 0x006b, 0x005a, 0xe072, 0x004a, 0x0066 }, + { 0xe06b, 0xe074, 0xe069, 0x0067, 0xe0c6, 0x0064, 0x0015, 0xe07d }, + { 0x0073, 0x0066, 0xe071, 0x005d, 0x005a, 0xe04a, 0x0070, 0x0021 }, + { 0x0023, 0xe05a, 0x0075, 0x0067, 0xe069, 0xe07a, 0x007d, 0x0069 }, +}; + +static void keyboard_matrix_init(void) +{ + CPRINTS("%s", __func__); + + register_scancode_set2((uint16_t *)&scancode_set2_rgb, + sizeof(scancode_set2_rgb)); +} +DECLARE_HOOK(HOOK_INIT, keyboard_matrix_init, HOOK_PRIO_PRE_DEFAULT); diff --git a/board/osiris/led.c b/board/osiris/led.c new file mode 100644 index 0000000000..f06cc17f8f --- /dev/null +++ b/board/osiris/led.c @@ -0,0 +1,87 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * Power and battery LED control for osiris + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +#define GPIO_LED_BLUE_L GPIO_LED_1_L +#define GPIO_LED_AMBER_L GPIO_LED_2_L + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_AMBER_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_BLUE_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_LED_BLUE_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_AMBER_L, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_BLUE_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_AMBER_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/osiris/pwm.c b/board/osiris/pwm.c new file mode 100644 index 0000000000..cc093a208f --- /dev/null +++ b/board/osiris/pwm.c @@ -0,0 +1,20 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_FAN2] = { .channel = 3, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/board/osiris/sensors.c b/board/osiris/sensors.c new file mode 100644 index 0000000000..4232a1a3fa --- /dev/null +++ b/board/osiris/sensors.c @@ -0,0 +1,107 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc.h" +#include "common.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_AMBIENT] = { + .name = "TEMP_AMBIENT", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { + .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC, + }, + [TEMP_SENSOR_2_AMBIENT] = { + .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_AMBIENT, + }, + [TEMP_SENSOR_3_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * Temperature limit, See thermal table in b/234545460#comment16 + * For real temperature in fan control table, set temp_fan_off + * and temp_fan_max to 0 and 99. + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(78), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + }, \ + .temp_fan_off = C_TO_K(0), \ + .temp_fan_max = C_TO_K(99), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +#define THERMAL_UNUSED \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_unused = + THERMAL_UNUSED; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_AMBIENT] = THERMAL_UNUSED, + [TEMP_SENSOR_3_CHARGER] = THERMAL_UNUSED, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/osiris/usbc_config.c b/board/osiris/usbc_config.c new file mode 100644 index 0000000000..85d73b63cf --- /dev/null +++ b/board/osiris/usbc_config.c @@ -0,0 +1,319 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_FRS, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_FRS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +#ifndef CONFIG_ZEPHYR +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +#endif +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* + * USB3 MB/DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ + +static const struct usb_mux_chain usbc0_usb3_mb_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + /* PS8815 MB */ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc0_usb3_mb_retimer, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/179648104): figure out correct timing + */ + gpio_set_level(GPIO_USB_C1_RST_ODL, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + gpio_set_level(GPIO_USB_C0_RT_RST_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(GPIO_USB_C1_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + gpio_set_level(GPIO_USB_C0_RT_RST_ODL, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + return false; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (!board_is_tbt_usb4_port(port)) + return TBT_SS_RES_0; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/osiris/usbc_config.h b/board/osiris/usbc_config.h new file mode 100644 index 0000000000..dac4177f0c --- /dev/null +++ b/board/osiris/usbc_config.h @@ -0,0 +1,19 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Osiris board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#ifndef CONFIG_ZEPHYR +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#endif + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void config_usb_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/osiris/vif_override.xml b/board/osiris/vif_override.xml new file mode 100644 index 0000000000..6ade5d2f92 --- /dev/null +++ b/board/osiris/vif_override.xml @@ -0,0 +1,148 @@ + + + 2 + 0 + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 9A1B + + + + + + Gen 3 (40Gb) + + + + USB 3.2 Gen 2x2 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + + + + + + USB 3.2 Gen 2x1 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PSD + PDUSB Host + + + + + Gen 3 (40Gb) + + USB 3.2 Gen 2x2 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + diff --git a/board/palkia/battery.c b/board/palkia/battery.c index 76e58aa618..ed7efdb423 100644 --- a/board/palkia/battery.c +++ b/board/palkia/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/palkia/board.c b/board/palkia/board.c index 939447fc17..342d3e05e9 100644 --- a/board/palkia/board.c +++ b/board/palkia/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Palkia board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" @@ -32,21 +31,20 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static const uint8_t actual_key_mask[KEYBOARD_COLS_MAX] = { - 0x01, 0x68, 0xbd, 0x03, 0x7e, 0xff, 0xff, - 0xff, 0xff, 0x03, 0xfd, 0x48, 0x03, 0xff, - 0xf7, 0x16 /* full set */ + 0x01, 0x68, 0xbd, 0x03, 0x7e, 0xff, 0xff, 0xff, + 0xff, 0x03, 0xfd, 0x48, 0x03, 0xff, 0xf7, 0x16 /* full set */ }; /* GPIO to enable/disable the USB Type-A port. */ @@ -94,7 +92,7 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; default: @@ -116,20 +114,21 @@ static void board_lid_interrupt(enum gpio_signal signal) lid_interrupt(signal); } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, - [PWM_CH_FAN] = {.channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -140,17 +139,19 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, } }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, }; @@ -166,7 +167,7 @@ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -185,58 +186,63 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_5V_REG", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_3] = { - "TEMP_AMB", NPCX_ADC_CH3, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_4] = { - "TEMP_CPU", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_5V_REG", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_3] = { "TEMP_AMB", NPCX_ADC_CH3, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_4] = { "TEMP_CPU", NPCX_ADC_CH2, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Temp1", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Temp2", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, - [TEMP_SENSOR_3] = {.name = "Temp3", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_3}, - [TEMP_SENSOR_4] = {.name = "Temp4", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_4}, + [TEMP_SENSOR_1] = { .name = "Temp1", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Temp2", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Temp3", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "Temp4", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); /* Palkia temperature control thresholds */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = C_TO_K(90), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(60), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(65), - .temp_fan_max = C_TO_K(80), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(60), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(65), \ + .temp_fan_max = C_TO_K(80), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; diff --git a/board/palkia/board.h b/board/palkia/board.h index 6164e872c1..d4de1aca39 100644 --- a/board/palkia/board.h +++ b/board/palkia/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,10 +14,9 @@ #define CONFIG_POWER_BUTTON #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_LED_COMMON -#define CONFIG_LED_POWER_LED #define CONFIG_LOW_POWER_IDLE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -47,7 +46,7 @@ * Palkia' battery takes several seconds to come back out of its disconnect * state (~4.2 seconds on the unit I have, so give it a little more for margin). */ -#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT #define CONFIG_POWER_BUTTON_INIT_TIMEOUT 6 /* BC 1.2 */ @@ -57,7 +56,7 @@ #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 50 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -71,15 +70,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -87,18 +87,14 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_TEMP_SENSOR_3, /* ADC3 */ - ADC_TEMP_SENSOR_4, /* ADC2 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_3, /* ADC3 */ + ADC_TEMP_SENSOR_4, /* ADC2 */ ADC_CH_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, diff --git a/board/palkia/build.mk b/board/palkia/build.mk index cf0939b776..3ad9efe889 100644 --- a/board/palkia/build.mk +++ b/board/palkia/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/palkia/ec.tasklist b/board/palkia/ec.tasklist index be39ae64a2..2a0d89d14e 100644 --- a/board/palkia/ec.tasklist +++ b/board/palkia/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/palkia/gpio.inc b/board/palkia/gpio.inc index ec7ce25538..dfe92f8a81 100644 --- a/board/palkia/gpio.inc +++ b/board/palkia/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,10 +16,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) diff --git a/board/palkia/keyboard_customization.c b/board/palkia/keyboard_customization.c index 706ad18a4e..9356b5f152 100644 --- a/board/palkia/keyboard_customization.c +++ b/board/palkia/keyboard_customization.c @@ -1,32 +1,33 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" -#include "keyboard_customization.h" +#include "gpio.h" #include "keyboard_8042_sharedlib.h" #include "keyboard_config.h" +#include "keyboard_customization.h" #include "keyboard_protocol.h" #include "keyboard_raw.h" static uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { - {0x0021, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0x0000, 0x0000, 0x0000, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000}, - {0x0015, 0x0000, 0x0014, 0x000d, 0x000e, 0x0016, 0x0000, 0x001c}, - {0xe011, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0x0000, 0x0029, 0x0024, 0x000c, 0xe01f, 0x0026, 0x0004, 0x0000}, - {0x0022, 0x001a, 0x0006, 0x0005, 0x001b, 0x001e, 0x001d, 0x0076}, - {0x002a, 0x0032, 0x0034, 0x002c, 0x002e, 0x0025, 0x002d, 0x002b}, - {0x003a, 0x0031, 0x0033, 0x0035, 0x0036, 0x003d, 0x003c, 0x003b}, - {0x0049, 0xe072, 0x005d, 0x0044, 0x0009, 0x0046, 0x0000, 0x004b}, - {0x0059, 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0x0041, 0x0000, 0x0083, 0x000b, 0x0003, 0x003e, 0x0043, 0x0042}, - {0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0xe06b, 0x0000}, - {0xe014, 0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0x004a, 0xe075, 0x004e, 0x0000, 0x0045, 0x004d, 0x0054, 0x004c}, - {0x0052, 0x005a, 0x0000, 0x0000, 0x0055, 0x0066, 0x005b, 0x0023}, - {0x0000, 0x000a, 0xe074, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + { 0x0021, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x0000, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0015, 0x0000, 0x0014, 0x000d, 0x000e, 0x0016, 0x0000, 0x001c }, + { 0xe011, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0029, 0x0024, 0x000c, 0xe01f, 0x0026, 0x0004, 0x0000 }, + { 0x0022, 0x001a, 0x0006, 0x0005, 0x001b, 0x001e, 0x001d, 0x0076 }, + { 0x002a, 0x0032, 0x0034, 0x002c, 0x002e, 0x0025, 0x002d, 0x002b }, + { 0x003a, 0x0031, 0x0033, 0x0035, 0x0036, 0x003d, 0x003c, 0x003b }, + { 0x0049, 0xe072, 0x005d, 0x0044, 0x0009, 0x0046, 0x0000, 0x004b }, + { 0x0059, 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0041, 0x0000, 0x0083, 0x000b, 0x0003, 0x003e, 0x0043, 0x0042 }, + { 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0xe06b, 0x0000 }, + { 0xe014, 0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x004a, 0xe075, 0x004e, 0x0000, 0x0045, 0x004d, 0x0054, 0x004c }, + { 0x0052, 0x005a, 0x0000, 0x0000, 0x0055, 0x0066, 0x005b, 0x0023 }, + { 0x0000, 0x000a, 0xe074, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, }; uint16_t get_scancode_set2(uint8_t row, uint8_t col) @@ -62,49 +63,41 @@ void board_keyboard_drive_col(int col) } #ifdef CONFIG_KEYBOARD_DEBUG -static char keycap_label[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { - {'c', KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO}, - {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO}, - {'q', KLLI_UNKNO, KLLI_UNKNO, KLLI_TAB, '`', - '1', KLLI_UNKNO, 'a'}, - {KLLI_R_ALT, KLLI_L_ALT, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO}, - {KLLI_UNKNO, KLLI_SPACE, 'e', KLLI_F4, - KLLI_SEARC, '3', KLLI_F3, KLLI_UNKNO}, - {'x', 'z', KLLI_F2, KLLI_F1, - 's', '2', 'w', KLLI_ESC}, - {'v', 'b', 'g', 't', - '5', '4', 'r', 'f'}, - {'m', 'n', 'h', 'y', - '6', '7', 'u', 'j'}, - {'.', KLLI_DOWN, '\\', 'o', - KLLI_F10, '9', KLLI_UNKNO, 'l'}, - {KLLI_R_SHT, KLLI_L_SHT, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO}, - {',', KLLI_UNKNO, KLLI_F7, KLLI_F6, - KLLI_F5, '8', 'i', 'k'}, - {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_F9, - KLLI_UNKNO, KLLI_UNKNO, KLLI_LEFT, KLLI_UNKNO}, - {KLLI_R_CTR, KLLI_L_CTR, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO}, - {'/', KLLI_UP, '-', KLLI_UNKNO, - '0', 'p', '[', ';'}, - {'\'', KLLI_ENTER, KLLI_UNKNO, KLLI_UNKNO, - '=', KLLI_B_SPC, ']', 'd'}, - {KLLI_UNKNO, KLLI_F8, KLLI_RIGHT, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO}, +static uint8_t keycap_label[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { 'c', KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { 'q', KLLI_UNKNO, KLLI_UNKNO, KLLI_TAB, '`', '1', KLLI_UNKNO, 'a' }, + { KLLI_R_ALT, KLLI_L_ALT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_UNKNO, KLLI_SPACE, 'e', KLLI_F4, KLLI_SEARC, '3', KLLI_F3, + KLLI_UNKNO }, + { 'x', 'z', KLLI_F2, KLLI_F1, 's', '2', 'w', KLLI_ESC }, + { 'v', 'b', 'g', 't', '5', '4', 'r', 'f' }, + { 'm', 'n', 'h', 'y', '6', '7', 'u', 'j' }, + { '.', KLLI_DOWN, '\\', 'o', KLLI_F10, '9', KLLI_UNKNO, 'l' }, + { KLLI_R_SHT, KLLI_L_SHT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { ',', KLLI_UNKNO, KLLI_F7, KLLI_F6, KLLI_F5, '8', 'i', 'k' }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_F9, KLLI_UNKNO, KLLI_UNKNO, + KLLI_LEFT, KLLI_UNKNO }, + { KLLI_R_CTR, KLLI_L_CTR, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { '/', KLLI_UP, '-', KLLI_UNKNO, '0', 'p', '[', ';' }, + { '\'', KLLI_ENTER, KLLI_UNKNO, KLLI_UNKNO, '=', KLLI_B_SPC, ']', 'd' }, + { KLLI_UNKNO, KLLI_F8, KLLI_RIGHT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO }, }; -char get_keycap_label(uint8_t row, uint8_t col) +uint8_t get_keycap_label(uint8_t row, uint8_t col) { if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) return keycap_label[col][row]; return KLLI_UNKNO; } -void set_keycap_label(uint8_t row, uint8_t col, char val) +void set_keycap_label(uint8_t row, uint8_t col, uint8_t val) { if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) keycap_label[col][row] = val; diff --git a/board/palkia/keyboard_customization.h b/board/palkia/keyboard_customization.h index 37ce1cf61f..fc97ffd728 100644 --- a/board/palkia/keyboard_customization.h +++ b/board/palkia/keyboard_customization.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -25,47 +25,47 @@ extern uint8_t keyboard_cols; #define KEYBOARD_ROW_TO_MASK(r) (1 << (r)) /* Columns and masks for keys we particularly care about */ -#define KEYBOARD_COL_DOWN 8 -#define KEYBOARD_ROW_DOWN 1 -#define KEYBOARD_MASK_DOWN KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_DOWN) -#define KEYBOARD_COL_ESC 5 -#define KEYBOARD_ROW_ESC 7 -#define KEYBOARD_MASK_ESC KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_ESC) -#define KEYBOARD_COL_KEY_H 7 -#define KEYBOARD_ROW_KEY_H 2 -#define KEYBOARD_MASK_KEY_H KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_H) -#define KEYBOARD_COL_KEY_R 6 -#define KEYBOARD_ROW_KEY_R 6 -#define KEYBOARD_MASK_KEY_R KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_R) -#define KEYBOARD_COL_LEFT_ALT 3 -#define KEYBOARD_ROW_LEFT_ALT 1 -#define KEYBOARD_MASK_LEFT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_ALT) -#define KEYBOARD_COL_REFRESH 4 -#define KEYBOARD_ROW_REFRESH 6 -#define KEYBOARD_MASK_REFRESH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_REFRESH) -#define KEYBOARD_COL_RIGHT_ALT 3 -#define KEYBOARD_ROW_RIGHT_ALT 0 -#define KEYBOARD_MASK_RIGHT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_ALT) -#define KEYBOARD_DEFAULT_COL_VOL_UP 8 -#define KEYBOARD_DEFAULT_ROW_VOL_UP 4 -#define KEYBOARD_COL_LEFT_CTRL 12 -#define KEYBOARD_ROW_LEFT_CTRL 1 +#define KEYBOARD_COL_DOWN 8 +#define KEYBOARD_ROW_DOWN 1 +#define KEYBOARD_MASK_DOWN KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_DOWN) +#define KEYBOARD_COL_ESC 5 +#define KEYBOARD_ROW_ESC 7 +#define KEYBOARD_MASK_ESC KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_ESC) +#define KEYBOARD_COL_KEY_H 7 +#define KEYBOARD_ROW_KEY_H 2 +#define KEYBOARD_MASK_KEY_H KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_H) +#define KEYBOARD_COL_KEY_R 6 +#define KEYBOARD_ROW_KEY_R 6 +#define KEYBOARD_MASK_KEY_R KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_R) +#define KEYBOARD_COL_LEFT_ALT 3 +#define KEYBOARD_ROW_LEFT_ALT 1 +#define KEYBOARD_MASK_LEFT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_ALT) +#define KEYBOARD_COL_REFRESH 4 +#define KEYBOARD_ROW_REFRESH 6 +#define KEYBOARD_MASK_REFRESH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_REFRESH) +#define KEYBOARD_COL_RIGHT_ALT 3 +#define KEYBOARD_ROW_RIGHT_ALT 0 +#define KEYBOARD_MASK_RIGHT_ALT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_ALT) +#define KEYBOARD_DEFAULT_COL_VOL_UP 8 +#define KEYBOARD_DEFAULT_ROW_VOL_UP 4 +#define KEYBOARD_COL_LEFT_CTRL 12 +#define KEYBOARD_ROW_LEFT_CTRL 1 #define KEYBOARD_MASK_LEFT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_CTRL) #define KEYBOARD_COL_RIGHT_CTRL 12 #define KEYBOARD_ROW_RIGHT_CTRL 0 #define KEYBOARD_MASK_RIGHT_CTRL KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_RIGHT_CTRL) -#define KEYBOARD_COL_SEARCH 2 -#define KEYBOARD_ROW_SEARCH 3 -#define KEYBOARD_MASK_SEARCH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_SEARCH) -#define KEYBOARD_COL_KEY_0 13 -#define KEYBOARD_ROW_KEY_0 4 -#define KEYBOARD_MASK_KEY_0 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_0) -#define KEYBOARD_COL_KEY_1 2 -#define KEYBOARD_ROW_KEY_1 5 -#define KEYBOARD_MASK_KEY_1 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_1) -#define KEYBOARD_COL_KEY_2 5 -#define KEYBOARD_ROW_KEY_2 5 -#define KEYBOARD_MASK_KEY_2 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_2) +#define KEYBOARD_COL_SEARCH 2 +#define KEYBOARD_ROW_SEARCH 3 +#define KEYBOARD_MASK_SEARCH KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_SEARCH) +#define KEYBOARD_COL_KEY_0 13 +#define KEYBOARD_ROW_KEY_0 4 +#define KEYBOARD_MASK_KEY_0 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_0) +#define KEYBOARD_COL_KEY_1 2 +#define KEYBOARD_ROW_KEY_1 5 +#define KEYBOARD_MASK_KEY_1 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_1) +#define KEYBOARD_COL_KEY_2 5 +#define KEYBOARD_ROW_KEY_2 5 +#define KEYBOARD_MASK_KEY_2 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_2) #define KEYBOARD_COL_LEFT_SHIFT 9 #define KEYBOARD_ROW_LEFT_SHIFT 1 #define KEYBOARD_MASK_LEFT_SHIFT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_SHIFT) diff --git a/board/palkia/led.c b/board/palkia/led.c index 1fa9295c80..a8ac1bcb44 100644 --- a/board/palkia/led.c +++ b/board/palkia/led.c @@ -1,46 +1,55 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Palkia */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; - -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_1 = 5; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override const int led_charge_lvl_2 = 95; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, @@ -49,7 +58,7 @@ const enum ec_led_id supported_led_ids[] = { const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -67,7 +76,7 @@ void led_set_color_battery(enum ec_led_colors color) } } -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); @@ -104,4 +113,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/palkia/vif_override.xml b/board/palkia/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/palkia/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/panqueque/board.c b/board/panqueque/board.c new file mode 100644 index 0000000000..42df0896cb --- /dev/null +++ b/board/panqueque/board.c @@ -0,0 +1,356 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Panqueque board-specific configuration */ + +#include "common.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/stm32gx.h" +#include "driver/tcpm/tcpci.h" +#include "driver/usb_mux/ps8822.h" +#include "ec_version.h" +#include "gpio.h" +#include "hooks.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "uart.h" +#include "usb_descriptor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_dp_ufp.h" +#include "usb_pe_sm.h" +#include "usb_prl_sm.h" +#include "usb_tc_sm.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +#define QUICHE_PD_DEBUG_LVL 1 + +#ifdef SECTION_IS_RW +#define CROS_EC_SECTION "RW" +#else +#define CROS_EC_SECTION "RO" +#endif + +#ifdef SECTION_IS_RW +static int pd_dual_role_init[CONFIG_USB_PD_PORT_MAX_COUNT] = { + PD_DRP_TOGGLE_ON, +}; + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_HOST_USBC_PPC_INT_ODL: + sn5s330_interrupt(USB_PD_PORT_HOST); + break; + default: + break; + } +} + +void hpd_interrupt(enum gpio_signal signal) +{ + usb_pd_hpd_edge_event(signal); +} + +static void board_uf_manage_vbus_interrupt(enum gpio_signal signal) +{ + baseboard_usb3_check_state(); +} + +static void board_pwr_btn_interrupt(enum gpio_signal signal) +{ + baseboard_power_button_evt(gpio_get_level(signal)); +} + +static void board_usbc_usb3_interrupt(enum gpio_signal signal) +{ + baseboard_usbc_usb3_irq(); +} +#endif /* SECTION_IS_RW */ + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* + * Table GPIO signals control both power rails and reset lines to various chips + * on the board. The order the signals are changed and the delay between GPIO + * signals is driven by USB/MST hub power sequencing requirements. + */ +const struct power_seq board_power_seq[] = { + { GPIO_EN_AC_JACK, 1, 20 }, + { GPIO_EC_DFU_MUX_CTRL, 0, 0 }, + { GPIO_EN_PP5000_A, 1, 31 }, + { GPIO_MST_LP_CTL_L, 1, 0 }, + { GPIO_EN_PP3300_B, 1, 1 }, + { GPIO_EN_PP1100_A, 1, 100 + 30 }, + { GPIO_EN_BB, 1, 30 }, + { GPIO_EN_PP1050_A, 1, 30 }, + { GPIO_EN_PP1200_A, 1, 20 }, + { GPIO_EN_PP5000_C, 1, 20 }, + { GPIO_EN_PP5000_HSPORT, 1, 31 }, + { GPIO_EN_DP_SINK, 1, 80 }, + { GPIO_MST_RST_L, 1, 61 }, + { GPIO_EC_HUB2_RESET_L, 1, 41 }, + { GPIO_EC_HUB3_RESET_L, 1, 33 }, + { GPIO_DP_SINK_RESET, 1, 100 }, + { GPIO_USBC_UF_RESET_L, 1, 33 }, + { GPIO_DEMUX_DP_HDMI_PD_N, 1, 10 }, + { GPIO_DEMUX_DP_HDMI_MODE, 1, 5 }, +}; +const size_t board_power_seq_count = ARRAY_SIZE(board_power_seq); + +/* + * Define the strings used in our USB descriptors. + */ +const void *const usb_strings[] = { + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Plugable"), + [USB_STR_PRODUCT] = USB_STRING_DESC("UC-MSTHDC"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = + USB_STRING_DESC(CROS_EC_SECTION ":" CROS_EC_VERSION32), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), +}; +BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); + +#ifndef SECTION_IS_RW +/* USB-C PPC Configuration */ +struct ppc_config_t ppc_chips[] = { + [USB_PD_PORT_HOST] = { + .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + }, +}; +#endif + +#ifdef SECTION_IS_RW +/* + * PS8802 set mux board tuning. + * Adds in board specific gain and DP lane count configuration + */ +static int board_ps8822_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) + rv = ps8822_set_dp_rx_eq(me, PS8822_DPEQ_LEVEL_UP_20DB); + + return rv; +} + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &stm32gx_tcpm_drv, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_HOST, + .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = PS8822_I2C_ADDR3_FLAG, + .driver = &ps8822_usb_mux_driver, + .board_set = &board_ps8822_mux_set, + }, + }, +}; + +/* USB-C PPC Configuration */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + [USB_PD_PORT_USB3] = { .i2c_port = I2C_PORT_I2C3, + .i2c_addr_flags = SN5S330_ADDR1_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +const struct hpd_to_pd_config_t hpd_config = { + .port = USB_PD_PORT_HOST, + .signal = GPIO_DDI_MST_IN_HPD, +}; + +void board_reset_pd_mcu(void) +{ + cprints(CC_SYSTEM, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USBC_UF_RESET_L, 0); + msleep(PS8805_FW_INIT_DELAY_MS); + gpio_set_level(GPIO_USBC_UF_RESET_L, 1); + msleep(PS8805_FW_INIT_DELAY_MS); +} + +void board_enable_usbc_interrupts(void) +{ + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_HOST_USBC_PPC_INT_ODL); + /* Enable HPD interrupt */ + gpio_enable_interrupt(GPIO_DDI_MST_IN_HPD); + /* Enable VBUS control interrupt for C1 */ + gpio_enable_interrupt(GPIO_USBC_UF_MUX_VBUS_EN); +} + +void board_disable_usbc_interrupts(void) +{ + /* Disable PPC interrupts. */ + gpio_disable_interrupt(GPIO_HOST_USBC_PPC_INT_ODL); + /* Disable HPD interrupt */ + gpio_disable_interrupt(GPIO_DDI_MST_IN_HPD); + /* Disable VBUS control interrupt for C1 */ + gpio_disable_interrupt(GPIO_USBC_UF_MUX_VBUS_EN); +} + +void board_tcpc_init(void) +{ + board_reset_pd_mcu(); + + /* Enable board usbc interrupts */ + board_enable_usbc_interrupts(); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 2); + +enum pd_dual_role_states board_tc_get_initial_drp_mode(int port) +{ + return pd_dual_role_init[port]; +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + /* + * CONFIG_USB_PD_PORT_MAX_COUNT must be defined to account for C0 + * and C1, but TCPMv2 only knows about C0, as C1 is a type-c only + * port that is managed directly by the PS8803 TCPC. + */ + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; +} + +int ppc_get_alert_status(int port) +{ + if (port == USB_PD_PORT_HOST) + return gpio_get_level(GPIO_HOST_USBC_PPC_INT_ODL) == 0; + + return 0; +} + +uint16_t tcpc_get_alert_status(void) +{ + return 0; +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/174825406): check correct operation for honeybuns */ +} + +int dock_get_mf_preference(void) +{ + return MF_ON; +} + +static void board_usb_tc_connect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* + * The EC needs to indicate to the MST hub when the host port is + * attached. GPIO_UFP_PLUG_DET is used for this purpose. + */ + if (port == USB_PD_PORT_HOST) + gpio_set_level(GPIO_UFP_PLUG_DET, 0); +} +DECLARE_HOOK(HOOK_USB_PD_CONNECT, board_usb_tc_connect, HOOK_PRIO_DEFAULT); + +static void board_usb_tc_disconnect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* Only the host port disconnect is relevant */ + if (port == USB_PD_PORT_HOST) + gpio_set_level(GPIO_UFP_PLUG_DET, 1); +} +DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, board_usb_tc_disconnect, + HOOK_PRIO_DEFAULT); + +#endif /* SECTION_IS_RW */ + +static void board_init(void) +{ +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_debug_gpio_1_pulse(void) +{ + gpio_set_level(GPIO_TRIGGER_1, 0); +} +DECLARE_DEFERRED(board_debug_gpio_1_pulse); + +static void board_debug_gpio_2_pulse(void) +{ + gpio_set_level(GPIO_TRIGGER_2, 0); +} +DECLARE_DEFERRED(board_debug_gpio_2_pulse); + +void board_debug_gpio(enum debug_gpio trigger, int level, int pulse_usec) +{ + switch (trigger) { + case TRIGGER_1: + gpio_set_level(GPIO_TRIGGER_1, level); + if (pulse_usec) + hook_call_deferred(&board_debug_gpio_1_pulse_data, + pulse_usec); + break; + case TRIGGER_2: + gpio_set_level(GPIO_TRIGGER_2, level); + if (pulse_usec) + hook_call_deferred(&board_debug_gpio_2_pulse_data, + pulse_usec); + break; + default: + CPRINTS("bad debug gpio selection"); + break; + } +} + +static int command_dplane(int argc, const char **argv) +{ + char *e; + int lane; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + lane = strtoi(argv[1], &e, 10); + + if ((lane != 2) && (lane != 4)) + return EC_ERROR_PARAM1; + + /* put MST into reset */ + gpio_set_level(GPIO_MST_RST_L, 0); + msleep(1); + /* Set lane control to requested level */ + gpio_set_level(GPIO_MST_HUB_LANE_SWITCH, lane == 2 ? 1 : 0); + msleep(1); + /* Take MST out of reset */ + gpio_set_level(GPIO_MST_RST_L, 1); + + ccprintf("MST lane set: %s, lane_ctrl = %d\n", + lane == 2 ? "2 lane" : "4 lane", + gpio_get_level(GPIO_MST_HUB_LANE_SWITCH)); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(dplane, command_dplane, "<2 | 4>", "MST lane control."); diff --git a/board/panqueque/board.h b/board/panqueque/board.h new file mode 100644 index 0000000000..24eeebabe5 --- /dev/null +++ b/board/panqueque/board.h @@ -0,0 +1,98 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Panqueque board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* Optional features */ +/* + * For MP release, CONFIG_SYSTEM_UNLOCKED must be undefined, and + * CONFIG_FLASH_PSTATE_LOCKED must be defined in order to enable write protect + * using option bytes WRP registers. + */ +#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ +#undef CONFIG_FLASH_PSTATE_LOCKED + +/* USB Type C and USB PD defines */ +#define USB_PD_PORT_HOST 0 +#define USB_PD_PORT_USB3 1 + +/* + * Only the host and display usbc ports are usb-pd capable. There is a 2nd usbc + * port, but this is type-c capable only. Only the PPC for this port needs to be + * controlled by FW. + */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_MUX_PS8822 + +#undef CONFIG_USB_VID +#define CONFIG_USB_VID 0x2230 +#define CONFIG_USB_PID 0x2018 +#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ +#define CONFIG_USB_PD_IDENTITY_HW_VERS 1 +#define CONFIG_USB_PD_IDENTITY_SW_VERS 1 + +/* I2C port names */ +#define I2C_PORT_I2C1 0 +#define I2C_PORT_I2C2 1 +#define I2C_PORT_I2C3 2 + +/* Required symbolic I2C port names */ +#define I2C_PORT_MP4245 I2C_PORT_I2C3 +#define I2C_PORT_EEPROM I2C_PORT_I2C3 +#define MP4245_I2C_ADDR_FLAGS MP4245_I2C_ADDR_0_FLAGS + +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + +#ifndef __ASSEMBLER__ + +#include "registers.h" + +#define GPIO_DP_HPD GPIO_DDI_MST_IN_HPD +#define GPIO_USBC_UF_ATTACHED_SRC GPIO_USBC_UF_MUX_VBUS_EN +#define GPIO_BPWR_DET GPIO_HUB_BPWRDET +#define GPIO_USB_HUB_OCP_NOTIFY GPIO_USBC_DATA_OCP_NOTIFY +#define GPIO_UFP_PLUG_DET GPIO_MST_UFP_PLUG_DET + +#define BUTTON_PRESSED_LEVEL 1 +#define BUTTON_RELEASED_LEVEL 0 + +#define GPIO_TRIGGER_1 GPIO_USB3_A5_CDP_EN +#define GPIO_TRIGGER_2 GPIO_USB3_A6_CDP_EN + +enum debug_gpio { + TRIGGER_1 = 0, + TRIGGER_2, +}; + +/* + * Function used to control GPIO signals as a timing marker. This is intended to + * be used for development/debugging purposes. + * + * @param trigger GPIO debug signal selection + * @param level desired level of the debug gpio signal + * @param pulse_usec pulse width if non-zero + */ +void board_debug_gpio(enum debug_gpio trigger, int level, int pulse_usec); + +/* + * Function called in power on case to enable usbc related interrupts + */ +void board_enable_usbc_interrupts(void); + +/* + * Function called in power off case to disable usbc related interrupts + */ +void board_disable_usbc_interrupts(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/panqueque/build.mk b/board/panqueque/build.mk new file mode 100644 index 0000000000..8f9795eca9 --- /dev/null +++ b/board/panqueque/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=stm32 +CHIP_FAMILY:=stm32g4 +CHIP_VARIANT:=stm32g473xc +BASEBOARD:=honeybuns + +board-y=board.o diff --git a/board/panqueque/dev_key.pem b/board/panqueque/dev_key.pem new file mode 100644 index 0000000000..4897ceb44e --- /dev/null +++ b/board/panqueque/dev_key.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEAyiT9PsD2wW3mhfuxMtihnLDKC+PY9l6j+j405G5Wd3BBtLLl +2uEoSD8cFQfnVTeFH7wggVf+SMAP3Y2aTnXIfdTX3N0skAdq/kYNUlQAK0xsa3Z7 +bRZ8puvzu+XNqsSS/tvsdYbNE5WC5sXtt7Wkm3mKn7PAti7oQrKbW1beFD0FgdAq +JoweIdpkuOwDYtFBcF92LWWGziDcEXlc2v5Xj3qvixMLnhy+Ny1Byr2ApVaYZ56H +JfjHKxbirNj4IrgmhdzfBIKxDf4mGibG0K1aC1io+SixtRV1cS6JRB0D+GS4QIcq +y9bCMkBeVQLHhSo1UYZqbB7Qef0blQ2sxsXklo8Q5EIQOd6yiXiTelApOWDn3zTi +uTkUo+99SPDLw/S3sR3uESxt+OYO2Yt6BWe2JSYBhHWB0Xc0PGItq7DUpm2cEWke +vS91I/lBfqhOxQOvnEx5NM97/RBQMa3jJ5Jv/72X5oU6OcGmaliBJy3Tv0CSiI06 +qgRgWxMym/XA0ui/AgEDAoIBgQCGw1N/K08rnpmup8t3OxZoddwH7TtO6cKm1CNC +9Dmk9YEjIe6R63AwKhK4r++OJQNqfWsA5VQwgAqTs7w0ToWpOI/ok3MKr5yphAjh +jVVyMvLyTvzzZFMZ8qJ9Q95x2GH/PUhOWd4NDldEg/PPzm28+7G/zSskH0WBzGeS +Oeli01kBNXFvCBQWkZh7SAJB4NZK6k7I7lnewJK2UOiR/uUKUcpct10UEyl6Hivc +flXDjxBFFFoZUITHZJcd5frB0Bh+EiqJ3CnkSIjD4sTnZs/TP8CKhmYriabfBHdH +j6ffcr5y8VhqDJK/ISSmWQO1c/rSziJLhx/ZrWvWp1FAbRg+kdh+RmV8hYIdEOq8 +PYOiERihd+eHVhtzsc74+cRGxPbaFJ2rpuJt+xk1Zp7IfGyyPWDmvXFKZgX+vo2s +vJL6q9pPR57uUHL0xsxDrMH3HFxkl1ta5PsiBGXs+zG0EUzNKGtoRTCi176xUWyo +NG+eWiL9ddeZVBzWeKfJGfwQ53sCgcEA+JE2E5kjvVCasSqERfDfIkSeOKoqWdZ2 +sAvTHibq6+vMBkRubNA0glHcUrMEBblDg3ds2z1A9YvwjwEUq9UFpVH3qfX9vaTX +lLYFRZjcA3PkCJvFAt5eIlVXp+vgaEo6OcodLjDiqkYKzbMC13k5uM1wsEEwo2vI +38vhHQlH1PHVTd8pt2Y7mOpDgxOOJLrvwuew7Lj9QSBRZ0EJxqv+1QA4EQ1cPr1H +hGqggtL0ChLRV7KBHiLz9ggS5vHTEkFNAoHBANAwaSIfTnpAvkMoGy+iQyw0afC0 +7hnwhHKcAzqenT1Mzo3Yt7/zsZE8ywjKPe9C+ZHZyh+W373tCUQRnjpNOpNiVHzi +ekFxl8kpLhpbB8LTXuRlQmtZjVQPbyuORPGDCzA05GGBN6mnXju+iQEz2WD8f3oY +Jz5yYl54eAuMsFl5/0yehqBQjRvky5YRna2eNUKBvz+/BgjpZeb0DtLMffcAvrkQ +FQbAwNvzvagMOEemjLSp9iXjQSNWJAdc86dMOwKBwQCltiQNEMJ+Nbx2HFguoJTB +gxQlxsbmjvnKsoy+xJydR91ZgvRIis2sNpLhzK1ZJi0CT53nfitOXUsKALhyjgPD +i/pxTqkpGI+4eVjZEJKs9+1bEoNXPulsOOUanUBFhtF73BN0IJccLrHed1c6UNEl +3ksgK3XCR9s/3UC+Bi/jS+OJP3Ek7tJl8YJXYl7DJ0qB78tIe1OAwDZE1gaEcqnj +VXq2COgp04UC8cBXN01cDIuPzFYUF01OsAyZ9oy21jMCgcEAisrwwWo0UYB+13AS +H8GCHXhGoHieu/Wtob1XfGm+KN3fCTslKqJ2YNMyBdwpSiymYTvcFQ8/0/NbgrZp +fDN8YkGNqJb8K6EP23DJZudageI/Qu4sR5EI4rT0x7Qt9ldcys3tllYlG8TpfSmw +q3fmQKhU/BAaKaGW6aWlXQh1kPv/iGmvFYsIvUMyZAu+c77OLFZ/f9SusJuZRKK0 +jIhT+gB/Jgq4rysrPU0pGrLQL8RdzcakGUIrbOQYBOiib4gnAoHAVrvbmZGxyeeA +oDE2QlXXmd1higPaQe3u+7vmh6itVpJ71n9wmu9xei7IiTOtGDYjHLXa8Qg0y37/ +FVCUiFxhOz05hpnB1ts70tuIWUJbWttMnhZPTpKa1dzZFB6qrlk2o/ONaSfNzpOZ +FgKxBURFVzNMTlIh7QOZGoOeRg5BkFG5z21g8egYQ/1cY61BhaxJTz93HGKb0jYn +QnC0WfVF9amWNGwocKATkwjoSVC7rQRsB2FMbY/WCqgE92lXsU9W +-----END RSA PRIVATE KEY----- diff --git a/board/panqueque/ec.tasklist b/board/panqueque/ec.tasklist new file mode 100644 index 0000000000..7bd8acaa5f --- /dev/null +++ b/board/panqueque/ec.tasklist @@ -0,0 +1,16 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS_RO(RWSIG, rwsig_task, NULL, 1280) \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(POWER_BUTTON, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(UCPD, ucpd_task, 0, LARGER_TASK_STACK_SIZE) diff --git a/board/panqueque/gpio.inc b/board/panqueque/gpio.inc new file mode 100644 index 0000000000..4fd80ec754 --- /dev/null +++ b/board/panqueque/gpio.inc @@ -0,0 +1,93 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +#ifdef SECTION_IS_RW +GPIO_INT(HOST_USBC_PPC_INT_ODL, PIN(D, 9), GPIO_INT_FALLING | GPIO_PULL_UP, ppc_interrupt) +GPIO_INT(DDI_MST_IN_HPD, PIN(C, 14), GPIO_INT_BOTH, hpd_interrupt) +GPIO_INT(USBC_UF_MUX_VBUS_EN, PIN(C, 12), GPIO_INT_BOTH, board_uf_manage_vbus_interrupt) +GPIO_INT(PWR_BTN, PIN(A, 0), GPIO_INT_BOTH, board_pwr_btn_interrupt) +GPIO_INT(USBC_UF_PPC_INT_ODL, PIN(B, 5), GPIO_INT_FALLING | GPIO_PULL_UP, board_usbc_usb3_interrupt) +#endif + +/* Power sequencing signals */ +GPIO(EN_AC_JACK, PIN(A, 1), GPIO_OUT_LOW) +GPIO(EN_BB, PIN(A, 8), GPIO_OUT_LOW) +GPIO(EN_PP3300_B, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EN_PP5000_A, PIN(C, 6), GPIO_OUT_LOW) +GPIO(EN_PP1200_A, PIN(E, 8), GPIO_OUT_LOW) +GPIO(EN_PP1100_A, PIN(C, 7), GPIO_OUT_LOW) +GPIO(EN_PP1050_A, PIN(A, 2), GPIO_OUT_LOW) +GPIO(EN_PP5000_C, PIN(D, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_HSPORT, PIN(D, 0), GPIO_OUT_LOW) + +/* MST Hub signals */ +GPIO(MST_LP_CTL_L, PIN(D, 10), GPIO_ODR_LOW) +GPIO(MST_RST_L, PIN(E, 14), GPIO_ODR_LOW) +GPIO(MST_HUB_LANE_SWITCH, PIN(C, 15), GPIO_OUT_HIGH) +GPIO(MST_UFP_PLUG_DET, PIN(B, 12), GPIO_OUT_HIGH) + +/* Display Demux signals */ +GPIO(DEMUX_DP_HDMI_MODE, PIN(E, 15), GPIO_OUT_LOW) +GPIO(DEMUX_DP_HDMI_PD_N, PIN(B, 13), GPIO_ODR_LOW) + +/* USBC Mux and Demux Signals */ +GPIO(EN_DP_SINK, PIN(B, 14), GPIO_OUT_LOW) +GPIO(DP_SINK_RESET, PIN(B, 15), GPIO_OUT_LOW) +GPIO(USBC_UF_RESET_L, PIN(D, 2), GPIO_ODR_LOW) + +/* USB Hubs signals */ +GPIO(EC_HUB2_RESET_L, PIN(C, 5), GPIO_ODR_LOW) +GPIO(EC_HUB3_RESET_L, PIN(B, 10), GPIO_ODR_LOW) +GPIO(USBC_DATA_OCP_NOTIFY, PIN(C, 2), GPIO_OUT_HIGH) +GPIO(HUB_BPWRDET, PIN(C, 1), GPIO_OUT_LOW) + +/* USB-A Current limit switches, set default to 1.5A */ +GPIO(GBE_RESET_EC, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EC_DFU_MUX_CTRL, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(USB3_A5_CDP_EN, PIN(B, 9), GPIO_OUT_LOW) +GPIO(USB3_A6_CDP_EN, PIN(C, 13), GPIO_OUT_LOW) + + +/* Write protect */ +GPIO(EC_FLASH_WP_ODL, PIN(A, 3), GPIO_ODR_HIGH) +GPIO(EC_WP_L, PIN(E, 11), GPIO_INT_BOTH) + +/* UART Bus */ +GPIO(EC_UART_TX, PIN(C, 10), GPIO_INT_BOTH) +GPIO(EC_UART_RX, PIN(C, 11), GPIO_INT_BOTH) + +/* + * I2C SCL/SDA pins. These will normally be under control of the peripheral from + * alt function setting below. But if a port gets wedged, the unwedge code uses + * these signals as regular GPIOs. + */ +GPIO(EC_I2C1_SCL, PIN(A, 15), GPIO_ODR_HIGH) +GPIO(EC_I2C1_SDA, PIN(B, 7), GPIO_ODR_HIGH) +GPIO(EC_I2C3_SCL, PIN(C, 8), GPIO_ODR_HIGH) +GPIO(EC_I2C3_SDA, PIN(C, 9), GPIO_ODR_HIGH) + +/* misc signals */ +GPIO(BOOT0, PIN(B, 8), GPIO_INPUT) + +/* Unimplemented signals since we are not an EC */ +UNIMPLEMENTED(ENTERING_RW) + +/* USART3_TX/RX GPIOC 10-11*/ +ALTERNATE(PIN_MASK(C, 0x0C00), 7, MODULE_UART, GPIO_PULL_UP) +/* I2C Ports + * I2C1: SDA/SCL -> PB7/PA15 + * I2C2: SDA/SCL -> PA8/PA9 + * I2C3: SDA/SCL -> PC8/PC9 + */ +ALTERNATE(PIN_MASK(B, 0x0080), 4, MODULE_I2C, GPIO_OPEN_DRAIN) +ALTERNATE(PIN_MASK(A, 0X8000), 4, MODULE_I2C, GPIO_OPEN_DRAIN) +ALTERNATE(PIN_MASK(C, 0x0300), 8, MODULE_I2C, GPIO_OPEN_DRAIN) +/* GPIOA4-7: SPI Signals */ +ALTERNATE(PIN_MASK(A, 0x00F0), 5, MODULE_SPI, 0) diff --git a/board/pazquel/battery.c b/board/pazquel/battery.c new file mode 100644 index 0000000000..bd600aed5b --- /dev/null +++ b/board/pazquel/battery.c @@ -0,0 +1,72 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" + +const struct board_batt_params board_battery_info[] = { + /* GanFeng SG20 Battery Information */ + [BATTERY_GANFENG] = { + .fuel_gauge = { + .manuf_name = "Ganfeng", + .device_name = "SG20", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0003, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 8700, /* mV */ + .voltage_normal = 7600, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + /* Pow-Tech SG20QT1C-2S4000-P1P1 Battery Information */ + [BATTERY_POWTECH_SG20QT1C] = { + .fuel_gauge = { + .manuf_name = "POW-TECH", + .device_name = "SG20QT1C", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x54, + .reg_mask = 0x0006, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 8700, /* mV */ + .voltage_normal = 7600, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 53, + .discharging_min_c = -23, + .discharging_max_c = 63, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_GANFENG; diff --git a/board/pazquel/board.c b/board/pazquel/board.c new file mode 100644 index 0000000000..7502d18b4d --- /dev/null +++ b/board/pazquel/board.c @@ -0,0 +1,725 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi323.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "pi3usb9201.h" +#include "power.h" +#include "power/qcom.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "shi_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "usbc_ocp.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Forward declaration */ +static void tcpc_alert_event(enum gpio_signal signal); +static void usb0_evt(enum gpio_signal signal); +static void usb1_evt(enum gpio_signal signal); +static void usba_oc_interrupt(enum gpio_signal signal); +static void ppc_interrupt(enum gpio_signal signal); +static void board_connect_c0_sbu(enum gpio_signal s); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* GPIO Interrupt Handlers */ +static void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_PD_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +static void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void usb1_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void usba_oc_deferred(void) +{ + /* Use next number after all USB-C ports to indicate the USB-A port */ + board_overcurrent_event(CONFIG_USB_PD_PORT_MAX_COUNT, + !gpio_get_level(GPIO_USB_A0_OC_ODL)); +} +DECLARE_DEFERRED(usba_oc_deferred); + +static void usba_oc_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&usba_oc_deferred_data, 0); +} + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + case GPIO_USB_C1_SWCTL_INT_ODL: + sn5s330_interrupt(1); + break; + default: + break; + } +} + +static void board_connect_c0_sbu_deferred(void) +{ + /* + * If CCD_MODE_ODL asserts, it means there's a debug accessory connected + * and we should enable the SBU FETs. + */ + ppc_set_sbu(0, 1); +} +DECLARE_DEFERRED(board_connect_c0_sbu_deferred); + +static void board_connect_c0_sbu(enum gpio_signal s) +{ + hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); +} + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Use 80 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* + * 1. launcher key mapped to (KSI_3, KSO_0): + * change actual_key_mask[0] = 0x14 to 0x1c + * 2. T11 key not in keyboard (KSI_0,KSO_1): + * change actual_key_mask[1] from 0xff to 0xfe + */ + .actual_key_mask = { 0x1c, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xa4, + 0xff, 0xfe, 0x55, 0xfa, 0xca }, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, +}; + +/* I2C port map */ +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* Measure VBUS through a 1/10 voltage divider */ + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + /* + * Adapter current output or battery charging/discharging current (uV) + * 18x amplification on charger side. + */ + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, + /* + * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read + * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and + * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we + * only divide by 2 (enough to avoid precision issues). + */ + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 20000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + } +}; + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + { + .i2c_port = I2C_PORT_EEPROM, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +/* Initialize board. */ +static void board_init(void) +{ + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + + /* Enable USB-A overcurrent interrupt */ + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + + /* Enable interrupt for BMI160 sensor */ + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); + + /* + * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs + * for SBU may be disconnected after DP alt mode is off. Should enable + * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. + */ + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); + + /* Set the backlight duty cycle to 0. AP will override it later. */ + pwm_set_duty(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); + /* + * Pazquel/pazquel360 share the same firmware ,only pazquel360 has + * volume keys. So disable volume keys for pazquel board + */ + if (!board_has_side_volume_buttons()) { + button_disable_gpio(BUTTON_VOLUME_UP); + button_disable_gpio(BUTTON_VOLUME_DOWN); + gpio_set_flags(GPIO_VOLUME_DOWN_L, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_VOLUME_UP_L, GPIO_INPUT | GPIO_PULL_DOWN); + } +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +static void da9313_pvc_mode_ctrl(int enable) +{ + /* + * On enable, PVC operates in automatic frequency mode. + * On disable, PVC operates in fixed frequency mode. + */ + if (enable) + i2c_update8(I2C_PORT_POWER, DA9313_I2C_ADDR_FLAGS, + DA9313_REG_PVC_CTRL, DA9313_PVC_CTRL_PVC_MODE, + MASK_SET); + else + i2c_update8(I2C_PORT_POWER, DA9313_I2C_ADDR_FLAGS, + DA9313_REG_PVC_CTRL, DA9313_PVC_CTRL_PVC_MODE, + MASK_CLR); +} + +void da9313_init(void) +{ + /* PVC operates in fixed frequency mode in S0. */ + da9313_pvc_mode_ctrl(0); +} +DECLARE_HOOK(HOOK_INIT, da9313_init, HOOK_PRIO_DEFAULT + 1); + +void board_hibernate(void) +{ + int i; + + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_LID_ACCEL_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + ppc_vbus_sink_enable(i, 1); +} + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* + * Turn off display backlight in S3. AP has its own control. The EC's + * and the AP's will be AND'ed together in hardware. + */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); + + /* PVC operates in automatic frequency mode in S3. */ + da9313_pvc_mode_ctrl(1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* PVC operates in fixed frequency mode in S0. */ + da9313_pvc_mode_ctrl(0); + /* Turn on display and keyboard backlight in S0. */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); + if (pwm_get_duty(PWM_CH_DISPLIGHT)) + pwm_enable(PWM_CH_DISPLIGHT, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on S3 -> S5 transition */ +static void board_shutdown_complete(void) +{ + if (pwm_get_duty(PWM_CH_DISPLIGHT)) { + pwm_set_duty(PWM_CH_DISPLIGHT, 0); + } +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN_COMPLETE, board_shutdown_complete, + HOOK_PRIO_DEFAULT); + +__override uint32_t board_get_sku_id(void) +{ + static int sku_id = -1; + + if (sku_id == -1) { + int bits[3]; + + bits[0] = gpio_get_ternary(GPIO_SKU_ID0); + bits[1] = gpio_get_ternary(GPIO_SKU_ID1); + bits[2] = gpio_get_ternary(GPIO_SKU_ID2); + sku_id = binary_first_base3_from_bits(bits, ARRAY_SIZE(bits)); + } + + return (uint32_t)sku_id; +} + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON, enable); +} + +int board_is_switchcap_enabled(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_ON); +} + +int board_is_switchcap_power_good(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_PG); +} + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); + msleep(PS8805_FW_INIT_DELAY_MS); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +/* Mutexes */ +static struct mutex g_base_mutex; +static struct mutex g_lid_mutex; + +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static struct kionix_accel_data g_kx022_data; + +static const mat33_fp_t lid_standard_ref_kx022 = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static struct bmi_drv_data_t g_bmi_data; +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref_kx022, + .default_range = 2, /* g */ + /* We only use 2g because its resolution is only 8-bits */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + /* + * Note: bmi232: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI323, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi3xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI3_ADDR_I2C_PRIM, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI323, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi3xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI3_ADDR_I2C_PRIM, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void board_update_sensor_config_from_sku(void) +{ + if (board_is_clamshell()) { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* The sensors are not stuffed; don't allow lines to float */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_LID_ACCEL_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } else { + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable interrupt for the base accel sensor */ + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); + } +} +DECLARE_HOOK(HOOK_INIT, board_update_sensor_config_from_sku, + HOOK_PRIO_INIT_I2C + 2); + +static uint8_t sku_id; + +enum board_model { + PAZQUEL, + PAZQUEL360, + UNKNOWN, +}; + +static const char *const model_name[] = { + "PAZQUEL", + "PAZQUEL360", + "UNKNOWN", +}; + +static enum board_model get_model(void) +{ + if (sku_id == 0 || sku_id == 1 || sku_id == 2 || sku_id == 3 || + sku_id == 4 || sku_id == 5 || sku_id == 6) + return PAZQUEL; + if (sku_id >= 8) + return PAZQUEL360; + return UNKNOWN; +} + +int board_is_clamshell(void) +{ + return get_model() == PAZQUEL; +} + +/* Read SKU ID from GPIO and initialize variables for board variants */ +static void sku_init(void) +{ + sku_id = system_get_sku_id(); + CPRINTS("SKU: %u (%s)", sku_id, model_name[get_model()]); +} +DECLARE_HOOK(HOOK_INIT, sku_init, HOOK_PRIO_INIT_I2C + 1); + +int board_has_side_volume_buttons(void) +{ + return get_model() == PAZQUEL360; +} +__override int mkbp_support_volume_buttons(void) +{ + return board_has_side_volume_buttons(); +} diff --git a/board/pazquel/board.h b/board/pazquel/board.h new file mode 100644 index 0000000000..414c8ab7dd --- /dev/null +++ b/board/pazquel/board.h @@ -0,0 +1,104 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Keyboard */ +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_PWM_KBLIGHT + +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_LOW_VOLTAGE_PROTECTION + +/* BC 1.2 Charger */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* USB */ +#define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* USB-A */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* Sensors */ +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT +/* BMI323 Base accel/gyro */ +#define CONFIG_ACCELGYRO_BMI3XX +#define CONFIG_ACCELGYRO_BMI3XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS + +/* KX022 lid accel */ +#define CONFIG_ACCEL_KX022 +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_UPDATE + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* GPIO alias */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_SWITCHCAP_PG GPIO_SWITCHCAP_GPIO_1 +#define GPIO_ACOK_OD GPIO_CHG_ACOK_OD +/* Da9313 */ +#define DA9313_I2C_ADDR_FLAGS 0x68 +#define DA9313_REG_PVC_CTRL 0x04 +#define DA9313_PVC_CTRL_PVC_MODE BIT(1) +#define DA9313_PVC_CTRL_PVC_EN BIT(0) + +/* Button Config*/ +#define CONFIG_BUTTONS_RUNTIME_CONFIG +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { ADC_VBUS, ADC_AMON_BMON, ADC_PSYS, ADC_CH_COUNT }; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_DISPLIGHT, PWM_CH_COUNT }; + +enum battery_type { + BATTERY_GANFENG, + BATTERY_POWTECH_SG20QT1C, + BATTERY_TYPE_COUNT, +}; +/* Reset all TCPCs. */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); +int board_is_clamshell(void); +int board_has_side_volume_buttons(void); + +#endif /* !defined(__ASSEMBLER__) */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/pazquel/build.mk b/board/pazquel/build.mk new file mode 100644 index 0000000000..3bc07db568 --- /dev/null +++ b/board/pazquel/build.mk @@ -0,0 +1,17 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=trogdor + +board-y+=battery.o +board-y+=board.o +board-y+=led.o +board-y+=usbc_config.o diff --git a/board/pazquel/ec.tasklist b/board/pazquel/ec.tasklist new file mode 100644 index 0000000000..228828af3c --- /dev/null +++ b/board/pazquel/ec.tasklist @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/pazquel/gpio.inc b/board/pazquel/gpio.inc new file mode 100644 index 0000000000..8d9a2827bc --- /dev/null +++ b/board/pazquel/gpio.inc @@ -0,0 +1,187 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* USB interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ +GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ +GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ +GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING, usb1_evt) /* Interrupt from port-1 BC1.2 */ +GPIO_INT(USB_A0_OC_ODL, PIN(D, 1), GPIO_INT_BOTH | GPIO_PULL_UP, usba_oc_interrupt) + +/* System interrupts */ +GPIO_INT(CHG_ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ +GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ +GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ +/* + * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down + * to make it low. Overload the interrupt function chipset_warm_reset_interrupt + * for not only signalling power_signal_interrupt but also handling the logic + * of WARM_RESET_L which is pulled-up by the same rail of POWER_GOOD. + */ +GPIO_INT(POWER_GOOD, PIN(5, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, chipset_power_good_interrupt) /* SRC_PP1800_S10A from PMIC */ +GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_warm_reset_interrupt) /* AP warm reset */ +GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ + +/* Sensor interrupts */ +GPIO_INT(TABLET_MODE_L, PIN(C, 6), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, bmi3xx_interrupt) /* Accelerometer/gyro interrupt */ + +/* + * EC_RST_ODL used to be a wake source from PSL mode. However, we disabled + * the PSL mode. This GPIO does nothing now. Simply set it an INPUT. + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ +GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ + +/* PMIC/AP 1.8V */ +GPIO(PMIC_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ +GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ + +/* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_OUT_HIGH) /* EC hibernate */ +GPIO(SWITCHCAP_ON, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap */ +GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ +GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ +GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ + +/* Sensors */ +GPIO(LID_ACCEL_INT_L, PIN(5, 6), GPIO_INPUT) /* Lid accel sensor interrupt */ +/* Control the gate for trackpad IRQ. High closes the gate. + * This is always set low so that the OS can manage the trackpad. */ +GPIO(TRACKPAD_INT_GATE, PIN(7, 4), GPIO_OUT_LOW) + +/* USB-C */ +GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_OUT_HIGH) /* Port-0 TCPC chip reset */ +GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_OUT_HIGH) /* Port-1 TCPC chip reset */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ + +/* USB-A */ +GPIO(EN_USB_A_5V, PIN(8, 6), GPIO_OUT_LOW) +GPIO(USB_A_CDP_ILIM_EN_L, PIN(7, 5), GPIO_OUT_HIGH) /* H:CDP, L:SDP. Only one USB-A port, always CDP */ + +/* LEDs */ +GPIO(EC_CHG_LED_Y_C0, PIN(6, 0), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_W_C0, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_Y_C1, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_W_C1, PIN(C, 4), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + +/* PWM */ +GPIO(KB_BL_PWM, PIN(8, 0), GPIO_INPUT) /* PWM3 */ +GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ + +/* ADC */ +GPIO(PPVAR_BOOSTIN_SENSE, PIN(4, 4), GPIO_INPUT) /* ADC1 */ +GPIO(CHARGER_IADP, PIN(4, 3), GPIO_INPUT) /* ADC2 */ +GPIO(CHARGER_PMON, PIN(4, 2), GPIO_INPUT) /* ADC3 */ + +/* I2C */ +GPIO(EC_I2C_POWER_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Board/SKU IDs */ +GPIO(BRD_ID0, PIN(C, 7), GPIO_INPUT) +GPIO(BRD_ID1, PIN(9, 3), GPIO_INPUT) +GPIO(BRD_ID2, PIN(6, 3), GPIO_INPUT) +GPIO(SKU_ID0, PIN(F, 0), GPIO_INPUT) +GPIO(SKU_ID1, PIN(4, 1), GPIO_INPUT) +GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) + +/* Switchcap */ +/* + * GPIO0 is configured as PVC_PG. When the chip in power down mode, it outputs + * high-Z. Set pull-down to avoid floating. + */ +GPIO(SWITCHCAP_GPIO_1, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(3, 7)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(7, 3)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(6, 2)) +UNUSED(PIN(0, 4)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(5, 0)) +UNUSED(PIN(D, 3)) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ +ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1 SDA (GPIO90), I2C2 (GPIO91/92) */ +ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) */ +ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ +ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ +ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ +ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* PWM3 (GPIO80) - KB_BL_PWM */ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ + +/* Keyboard */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +#define GPIO_KB_OUTPUT (GPIO_ODR_HIGH) +#define GPIO_KB_OUTPUT_COL2 (GPIO_OUT_LOW) + +/* Keyboard alternate functions */ +ALTERNATE(PIN_MASK(0, 0xE0), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO10 (GPIO07), KSO11 (GPIO06), KSO12 (GPIO05) */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO03 (GPIO16), KSO04 (GPIO15), KSO05 (GPIO14), KSO06 (GPIO13), KSO07 (GPIO12), KSO08 (GPIO11), KSO09 (GPIO10) */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) /* KSO00 (GPIO21), KSO01 (GPIO20) */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI2 (GPIO27), KSI3 (GPIO26), KSI4 (GPIO25), KSI5 (GPIO24), KSI6 (GPIO23), KSI7 (GPIO22) */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI0 (GPIO31), KSI1 (GPIO30) */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_KB_OUTPUT_COL2) /* KSO02 (GPIO17) */ diff --git a/board/pazquel/led.c b/board/pazquel/led.c new file mode 100644 index 0000000000..f9e1371a66 --- /dev/null +++ b/board/pazquel/led.c @@ -0,0 +1,153 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_BLUE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color(enum led_color color) +{ + gpio_set_level(GPIO_EC_CHG_LED_Y_C1, + (color == LED_RED) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(GPIO_EC_CHG_LED_W_C1, + (color == LED_BLUE) ? BAT_LED_ON : BAT_LED_OFF); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color(LED_BLUE); + else if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color(LED_RED); + else + led_set_color(LED_OFF); + + return EC_SUCCESS; +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + enum led_color color = LED_OFF; + int period = 0; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate amber on when charging. */ + color = LED_RED; + break; + case LED_PWRS_DISCHARGE: + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* Discharging in S3: Red 1 sec, off 3 sec */ + period = (1 + 3) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_OFF; + } else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + /* Discharging in S5: off */ + color = LED_OFF; + } else if (chipset_in_state(CHIPSET_STATE_ON)) { + /* Discharging in S0: Blue on */ + color = LED_BLUE; + } + break; + case LED_PWRS_ERROR: + /* Battery error: Red 1 sec, off 1 sec */ + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_OFF; + break; + case LED_PWRS_CHARGE_NEAR_FULL: + /* Full Charged: Blue on */ + color = LED_BLUE; + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_BLUE; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode: Blue 2 sec, Red 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) + color = LED_BLUE; + else + color = LED_RED; + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + led_set_color(color); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_BATTERY_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_BLUE : LED_OFF; + + led_auto_control(EC_LED_ID_BATTERY_LED, 0); + + led_set_color(color); +} diff --git a/board/pazquel/usbc_config.c b/board/pazquel/usbc_config.c new file mode 100644 index 0000000000..28f6b7a1c9 --- /dev/null +++ b/board/pazquel/usbc_config.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor family-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "console.h" +#include "usb_pd.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/pazquel/vif_override.xml b/board/pazquel/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/pazquel/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/pdeval-stm32f072/PD_evaluation.md b/board/pdeval-stm32f072/PD_evaluation.md index 95e31996fc..fd4763a849 100644 --- a/board/pdeval-stm32f072/PD_evaluation.md +++ b/board/pdeval-stm32f072/PD_evaluation.md @@ -1,17 +1,17 @@ -USB PD chip evaluation configuration -==================================== +# USB PD chip evaluation configuration -This board configuration implements a USB Power Delivery TCPM -in order to evaluate various TCPC chips. -The code tries to follow the preliminary USB PD interface standard but for TCPC chip implementing proprietary I2C protocol, a new TCPM file can be implemented as explained in the [Updating the code](#Updating-the-code) section below. +This board configuration implements a USB Power Delivery TCPM in order to +evaluate various TCPC chips. The code tries to follow the preliminary USB PD +interface standard but for TCPC chip implementing proprietary I2C protocol, a +new TCPM file can be implemented as explained in the +[Updating the code](#Updating-the-code) section below. -Building --------- +## Building -### ChromiumOS chroot +### Chromium OS chroot -All the following instructions have been verified in a ChromiumOS chroot. -You can find how to set one up on the Chromium development wiki: +All the following instructions have been verified in a ChromiumOS chroot. You +can find how to set one up on the Chromium development: [http://dev.chromium.org/chromium-os/quick-start-guide](http://dev.chromium.org/chromium-os/quick-start-guide) ### Build the TCPM code @@ -20,34 +20,52 @@ You can find how to set one up on the Chromium development wiki: `make BOARD=pdeval-stm32f072` - -Updating the code ------------------ +## Updating the code ### TCPC Communication code -Please duplicate [driver/tcpm/tcpci.c](../../driver/tcpm/tcpci.c) into **driver/tcpm/##chip#name##.c**. -Then update the control logic through I2C there. +Please duplicate [driver/tcpm/tcpci.c](../../driver/tcpm/tcpci.c) into +**driver/tcpm/##chip#name##.c**. Then update the control logic through I2C +there. -In order for your new code to compile, you need to update [driver/build.mk](../../driver/build.mk) with the new file : -`driver-$(CONFIG_USB_PD_TCPM_##CHIP#NAME##)+=tcpm/##chip#name##.o` -then document the new `CONFIG_USB_PD_TCPM_` variable in the [include/config.h](../../include/config.h) file and define it in the board configuration in [board/pdeval-stm32f072/board.h](board.h). +In order for your new code to compile, you need to update +[driver/build.mk](../../driver/build.mk) with the new file : +`driver-$(CONFIG_USB_PD_TCPM_##CHIP#NAME##)+=tcpm/##chip#name##.o` then document +the new `CONFIG_USB_PD_TCPM_` variable in the +[include/config.h](../../include/config.h) file and define it in the board +configuration in [board/pdeval-stm32f072/board.h](board.h). ### Board configuration -In [board/pdeval-stm32f072/board.h](board.h), you can update `CONFIG_USB_PD_PORT_MAX_COUNT` to the actual number of ports on your board. -You also need to create/delete the corresponding `PD_Cx` tasks in [board/pdeval-stm32f072/ec.tasklist](ec.tasklist). - -By default, the firmware is using I2C1 with SCL/SDA on pins PB6 and PB7, running with a 100kHz clock, and tries to talk to TCPCs at i2c slave addresses 0x9c and 0x9e. -To change the pins or speed, you need to edit `i2c_ports` in [board/pdeval-stm32f072/board.c](board.c), update `I2C_PORT_TCPC` in [board/pdeval-stm32f072/board.h](board.h) with the right controller number, and change the pin mux in [board/pdeval-stm32f072/gpio.inc](gpio.inc). To change TCPC i2c slave addresses, update `TCPC1_I2C_ADDR` and `TCPC2_I2C_ADDR` in [board/pdeval-stm32f072/board.h](board.h). - -The I2C bus needs pull-up resistors on SCL/SDA. If your setup doesn't have external pull-ups on those lines, you can activate the chip internal pull-ups (but they are a bit weak for I2C) by editing [board/pdeval-stm32f072/gpio.inc](gpio.inc) and updating the alternate mode configuration flags with `GPIO_PULL_UP` e.g. : -`ALTERNATE(PIN_MASK(B, 0x00c0), 1, MODULE_I2C, GPIO_PULL_UP) /* I2C MASTER:PB6/7 */` - -An interrupt line, PA1, is configured to be used for the TCPC to get the attention of the TCPM. The GPIO is configured to trigger an interrupt on the falling edge and will call `tcpc_alert()`, which must be implemented in **driver/tcpm/.c**, and should determine the cause of the interrupt and take action. The GPIO can be changed in [board/pdeval-stm32f072/gpio.inc](gpio.inc). - -Flashing and Running --------------------- +In [board/pdeval-stm32f072/board.h](board.h), you can update +`CONFIG_USB_PD_PORT_MAX_COUNT` to the actual number of ports on your board. You +also need to create/delete the corresponding `PD_Cx` tasks in +[board/pdeval-stm32f072/ec.tasklist](ec.tasklist). + +By default, the firmware is using I2C1 with SCL/SDA on pins PB6 and PB7, running +with a 100kHz clock, and tries to talk to TCPCs at i2c target addresses 0x9c and +0x9e. To change the pins or speed, you need to edit `i2c_ports` in +[board/pdeval-stm32f072/board.c](board.c), update `I2C_PORT_TCPC` in +[board/pdeval-stm32f072/board.h](board.h) with the right controller number, and +change the pin mux in [board/pdeval-stm32f072/gpio.inc](gpio.inc). To change +TCPC i2c target addresses, update `TCPC1_I2C_ADDR` and `TCPC2_I2C_ADDR` in +[board/pdeval-stm32f072/board.h](board.h). + +The I2C bus needs pull-up resistors on SCL/SDA. If your setup doesn't have +external pull-ups on those lines, you can activate the chip internal pull-ups +(but they are a bit weak for I2C) by editing +[board/pdeval-stm32f072/gpio.inc](gpio.inc) and updating the alternate mode +configuration flags with `GPIO_PULL_UP` e.g. : `ALTERNATE(PIN_MASK(B, 0x00c0), +1, MODULE_I2C, GPIO_PULL_UP) /* I2C MASTER:PB6/7 */` + +An interrupt line, PA1, is configured to be used for the TCPC to get the +attention of the TCPM. The GPIO is configured to trigger an interrupt on the +falling edge and will call `tcpc_alert()`, which must be implemented in +**driver/tcpm/.c**, and should determine the cause of the interrupt and +take action. The GPIO can be changed in +[board/pdeval-stm32f072/gpio.inc](gpio.inc). + +## Flashing and Running ### Flashing the firmware binary @@ -55,37 +73,46 @@ To flash through JTAG with OpenOCD, you can just run: `sudo make flash BOARD=pdeval-stm32f072` -Note: you need to do that with your USB mini-B cable is connected to the **USB ST-LINK** plug on the discovery board. +Note: you need to do that with your USB mini-B cable is connected to the **USB +ST-LINK** plug on the discovery board. ### Connecting to the firmware console -Connect a USB cable to the **USB USER** mini-B receptacle on the board. -`lsusb` should show you a device with the following ID : 18d1:500f +Connect a USB cable to the **USB USER** mini-B receptacle on the board. `lsusb` +should show you a device with the following ID : 18d1:500f -You can get a console over USB by issuing the following command on a Linux computer: +You can get a console over USB by issuing the following command on a Linux +computer: `echo '18d1 500f' | sudo tee /sys/bus/usb-serial/drivers/generic/new_id` -Testing -------- +## Testing -Currently, the TCPM is expecting to have a GPIO to detect VBUS, but to minimize the HW setup with the discovery board the alternative is to fake VBUS detection using either the **USER** button on the discovery board, or the `vbus` console command, both of which toggle the state of VBUS detected. For example, to make get a PD contract with a power adapter, plug in the adapter and then toggle VBUS on. When a PD contract above 6V is made, LED5 on the discovery board will light. To disconnect, toggle VBUS off. +Currently, the TCPM is expecting to have a GPIO to detect VBUS, but to minimize +the HW setup with the discovery board the alternative is to fake VBUS detection +using either the **USER** button on the discovery board, or the `vbus` console +command, both of which toggle the state of VBUS detected. For example, to make +get a PD contract with a power adapter, plug in the adapter and then toggle VBUS +on. When a PD contract above 6V is made, LED5 on the discovery board will light. +To disconnect, toggle VBUS off. EC command line commands -- `help` List all available EC console commands -- `vbus` Toggle VBUS on/off -- `pd state` Print PD protocol state information -- `pd swap data` Request data role swap on port -- `pd swap power` Request power role swap on port -- `i2cscan` Scan i2c bus for any responsive devices -- `i2cxfer` Perform an i2c transaction - -On the console, you will the PD state machine transitioning through its states with traces like `C0 st5`. -You can always the human readable name of the current state by doing `pd 0 state` returning something like : -`Port C0 CC1, Ena - Role: SNK-UFP State: SNK_DISCOVERY, Flags: 0x0608` -else the numbering of the state is defined in [include/usb_pd.h](../../include/us_pd.h) by the `PD_STATE_` constants. -It should be by default : +- `help` List all available EC console commands +- `vbus` Toggle VBUS on/off +- `pd state` Print PD protocol state information +- `pd swap data` Request data role swap on port +- `pd swap power` Request power role swap on port +- `i2cscan` Scan i2c bus for any responsive devices +- `i2cxfer` Perform an i2c transaction + +On the console, you will the PD state machine transitioning through its states +with traces like `C0 st5`. You can always the human readable name of the current +state by doing `pd 0 state` returning something like : `Port C0 CC1, Ena - Role: +SNK-UFP State: SNK_DISCOVERY, Flags: 0x0608` else the numbering of the state is +defined in [include/usb_pd.h](../../include/us_pd.h) by the `PD_STATE_` +constants. It should be by default : + ``` [0] DISABLED [1] SUSPENDED @@ -125,27 +152,26 @@ It should be by default : [35] BIST_TX ``` -Known Issues ------------- - -1. This doc is not finished yet ... +## Known Issues -2. You might need a ChromeOS chroot ... +1. This doc is not finished yet ... -Troubleshooting ---------------- +2. You might need a ChromeOS chroot ... -1. OpenOCD is not finding the device. +## Troubleshooting - 1. Check that your USB mini-B cable is connected to the **USB ST-LINK** plug on the discovery board. - 2. What color is the LD1 LED on the board ? +1. OpenOCD is not finding the device. -1. On the I2C bus, SDA/SCL lines are staying always low + 1. Check that your USB mini-B cable is connected to the **USB ST-LINK** + plug on the discovery board. + 2. What color is the LD1 LED on the board ? - 1. You might be missing some pull-up resistors on the bus. - 1. Check the [Board configuration](#Board-configuration) section if you cannot add external pull-ups. +1. On the I2C bus, SDA/SCL lines are staying always low -1. You got black smoke + 1. You might be missing some pull-up resistors on the bus. + 1. Check the [Board configuration](#Board-configuration) section if you + cannot add external pull-ups. - 1. Time to buy a new one. +1. You got black smoke + 1. Time to buy a new one. diff --git a/board/pdeval-stm32f072/board.c b/board/pdeval-stm32f072/board.c index 93f3f87082..f170319cc6 100644 --- a/board/pdeval-stm32f072/board.c +++ b/board/pdeval-stm32f072/board.c @@ -1,11 +1,11 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* STM32F072-discovery board based USB PD evaluation configuration */ -#include "common.h" #include "anx7447.h" +#include "common.h" #include "ec_version.h" #include "gpio.h" #include "hooks.h" @@ -13,7 +13,7 @@ #include "i2c.h" #include "registers.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "usb_descriptor.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" @@ -27,13 +27,14 @@ void alert_event(enum gpio_signal signal) host_command_pd_send_status(PD_CHARGE_NO_CHANGE); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("PDeval-stm32f072"), - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("PDeval-stm32f072"), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Shell"), }; @@ -52,9 +53,11 @@ void board_reset_pd_mcu(void) } /* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"tcpc", I2C_PORT_TCPC, 400 /* kHz */, GPIO_I2C0_SCL, GPIO_I2C0_SDA} -}; +const struct i2c_port_t i2c_ports[] = { { .name = "tcpc", + .port = I2C_PORT_TCPC, + .kbps = 400 /* kHz */, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA } }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { diff --git a/board/pdeval-stm32f072/board.h b/board/pdeval-stm32f072/board.h index 6da1c7c1f0..6ba7923b8e 100644 --- a/board/pdeval-stm32f072/board.h +++ b/board/pdeval-stm32f072/board.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,11 +15,12 @@ #undef CONFIG_UART_CONSOLE #define CONFIG_UART_CONSOLE 2 +#define CONFIG_LTO + /* Optional features */ #define CONFIG_HW_CRC #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_STM_HWTIMER32 +#define CONFIG_I2C_CONTROLLER /* USB Power Delivery configuration */ #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_TCPMV1 @@ -32,6 +33,7 @@ #define CONFIG_USB_PD_VBUS_DETECT_TCPC #define CONFIG_USB_PD_TCPM_ANX7447 #define CONFIG_USB_PD_TCPM_MUX +#define CONFIG_USBC_SS_MUX #undef CONFIG_USB_PD_INITIAL_DRP_STATE #define CONFIG_USB_PD_INITIAL_DRP_STATE PD_DRP_TOGGLE_ON @@ -40,14 +42,14 @@ #define CONFIG_USB_PD_PULLUP TYPEC_RP_USB /* fake board specific type-C power constants */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 650000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* I2C master port connected to the TCPC */ #define I2C_PORT_TCPC 0 @@ -58,7 +60,6 @@ #define CONFIG_USBC_VCONN #define CONFIG_USBC_VCONN_SWAP /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* USB Configuration */ #define CONFIG_USB @@ -67,15 +68,19 @@ /* USB interface indexes (use define rather than enum to expand them) */ #define USB_IFACE_CONSOLE 0 -#define USB_IFACE_COUNT 1 +#define USB_IFACE_COUNT 1 /* USB endpoint indexes (use define rather than enum to expand them) */ #define USB_EP_CONTROL 0 #define USB_EP_CONSOLE 1 -#define USB_EP_COUNT 2 +#define USB_EP_COUNT 2 +/* Remove console commands / features for flash / RAM savings */ #undef CONFIG_WATCHDOG_HELP #undef CONFIG_LID_SWITCH +#undef CONFIG_CONSOLE_HISTORY +#undef CONFIG_HIBERNATE +#undef CONFIG_CMD_CRASH /* * Allow dangerous commands all the time, since we don't have a write protect diff --git a/board/pdeval-stm32f072/build.mk b/board/pdeval-stm32f072/build.mk index ef1346d534..2238f8f59a 100644 --- a/board/pdeval-stm32f072/build.mk +++ b/board/pdeval-stm32f072/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,4 +10,4 @@ CHIP:=stm32 CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f07x -board-y=board.o usb_pd_policy.o +board-y=board.o usb_pd_policy.o usb_pd_pdo.o diff --git a/board/pdeval-stm32f072/ec.tasklist b/board/pdeval-stm32f072/ec.tasklist index 5003fc7ba1..e897969a55 100644 --- a/board/pdeval-stm32f072/ec.tasklist +++ b/board/pdeval-stm32f072/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/pdeval-stm32f072/gpio.inc b/board/pdeval-stm32f072/gpio.inc index 5409077c34..fb8537ffbe 100644 --- a/board/pdeval-stm32f072/gpio.inc +++ b/board/pdeval-stm32f072/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/pdeval-stm32f072/openocd-flash.cfg b/board/pdeval-stm32f072/openocd-flash.cfg index ec32416934..05a697acf8 100644 --- a/board/pdeval-stm32f072/openocd-flash.cfg +++ b/board/pdeval-stm32f072/openocd-flash.cfg @@ -1,4 +1,4 @@ -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/board/pdeval-stm32f072/usb_pd_pdo.c b/board/pdeval-stm32f072/usb_pd_pdo.c new file mode 100644 index 0000000000..31d84f9785 --- /dev/null +++ b/board/pdeval-stm32f072/usb_pd_pdo.c @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP) + +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 900, PDO_FIXED_FLAGS), + PDO_BATT(5000, 21000, 30000), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/pdeval-stm32f072/usb_pd_pdo.h b/board/pdeval-stm32f072/usb_pd_pdo.h new file mode 100644 index 0000000000..13640a7471 --- /dev/null +++ b/board/pdeval-stm32f072/usb_pd_pdo.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_PDEVAL_STM32F072_USB_PD_PDO_H +#define __CROS_EC_BOARD_PDEVAL_STM32F072_USB_PD_PDO_H + +#include "stdint.h" + +extern const uint32_t pd_src_pdo[1]; +extern const int pd_src_pdo_cnt; + +extern const uint32_t pd_snk_pdo[2]; +extern const int pd_snk_pdo_cnt; + +#endif /* __CROS_EC_BOARD_PDEVAL_STM32F072_USB_PD_PDO_H */ diff --git a/board/pdeval-stm32f072/usb_pd_policy.c b/board/pdeval-stm32f072/usb_pd_policy.c index 78026c9e7b..eb9a8ef9d5 100644 --- a/board/pdeval-stm32f072/usb_pd_policy.c +++ b/board/pdeval-stm32f072/usb_pd_policy.c @@ -1,10 +1,10 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "common.h" #include "anx7447.h" +#include "common.h" #include "console.h" #include "gpio.h" #include "hooks.h" @@ -12,34 +12,26 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_pdo.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) /* Used to fake VBUS presence since no GPIO is available to read VBUS */ static int vbus_present; -const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); - -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 900, PDO_FIXED_FLAGS), - PDO_BATT(5000, 21000, 30000), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); - #if defined(CONFIG_USB_PD_TCPM_MUX) && defined(CONFIG_USB_PD_TCPM_ANX7447) -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &anx7447_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, }; #endif @@ -48,11 +40,11 @@ const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { int pd_set_power_supply_ready(int port) { /* Disable charging */ - anx7447_board_charging_enable(port, 0); + tcpm_set_snk_ctrl(port, 0); /* Provide VBUS */ gpio_set_level(GPIO_VBUS_PMIC_CTRL, 1); - anx7447_set_power_supply_ready(port); + tcpm_set_src_ctrl(port, 1); /* notify host of power info change */ @@ -64,12 +56,12 @@ int pd_set_power_supply_ready(int port) void pd_power_supply_reset(int port) { /* Disable VBUS */ - anx7447_power_supply_reset(port); + tcpm_set_src_ctrl(port, 0); gpio_set_level(GPIO_VBUS_PMIC_CTRL, 0); CPRINTS("Disable VBUS, port%d", port); /* Enable charging */ - anx7447_board_charging_enable(port, 1); + tcpm_set_snk_ctrl(port, 1); } #else int pd_set_power_supply_ready(int port) @@ -92,8 +84,8 @@ void pd_power_supply_reset(int port) void pd_set_input_current_limit(int port, uint32_t max_ma, uint32_t supply_voltage) { - CPRINTS("USBPD current limit port %d max %d mA %d mV", - port, max_ma, supply_voltage); + CPRINTS("USBPD current limit port %d max %d mA %d mV", port, max_ma, + supply_voltage); /* do some LED coding of the power we can sink */ if (max_ma) { if (supply_voltage > 6500) @@ -109,8 +101,8 @@ void pd_set_input_current_limit(int port, uint32_t max_ma, __override void typec_set_input_current_limit(int port, uint32_t max_ma, uint32_t supply_voltage) { - CPRINTS("TYPEC current limit port %d max %d mA %d mV", - port, max_ma, supply_voltage); + CPRINTS("TYPEC current limit port %d max %d mA %d mV", port, max_ma, + supply_voltage); gpio_set_level(GPIO_LED_R, !!max_ma); } @@ -120,24 +112,21 @@ void button_event(enum gpio_signal signal) CPRINTS("VBUS %d", vbus_present); } -static int command_vbus_toggle(int argc, char **argv) +static int command_vbus_toggle(int argc, const char **argv) { vbus_present = !vbus_present; CPRINTS("VBUS %d", vbus_present); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(vbus, command_vbus_toggle, - "", - "Toggle VBUS detected"); +DECLARE_CONSOLE_COMMAND(vbus, command_vbus_toggle, "", "Toggle VBUS detected"); int pd_snk_is_vbus_provided(int port) { return vbus_present; } -__override int pd_check_data_swap(int port, - enum pd_data_role data_role) +__override int pd_check_data_swap(int port, enum pd_data_role data_role) { /* Always allow data swap */ return 1; @@ -155,22 +144,18 @@ int pd_check_vconn_swap(int port) } #endif -__override void pd_check_pr_role(int port, - enum pd_power_role pr_role, +__override void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { } -__override void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +__override void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { } /* ----------------- Vendor Defined Messages ------------------ */ const uint32_t vdo_idh = VDO_IDH(1, /* data caps as USB host */ 0, /* data caps as USB device */ - IDH_PTYPE_PERIPH, - 0, /* supports alt modes */ + IDH_PTYPE_PERIPH, 0, /* supports alt modes */ 0x0000); const uint32_t vdo_product = VDO_PRODUCT(0x0000, 0x0000); @@ -194,78 +179,72 @@ __override void svdm_safe_dp_mode(int port) { /* make DP interface safe until configure */ dp_flags[port] = 0; - /* board_set_usb_mux(port, USB_PD_MUX_NONE, pd_get_polarity(port)); */ + /* + * board_set_usb_mux(port, USB_PD_MUX_NONE, + * polarity_rm_dts(pd_get_polarity(port))); + */ } __override int svdm_dp_config(int port, uint32_t *payload) { - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]); -#if defined(CONFIG_USB_PD_TCPM_MUX) && defined(CONFIG_USB_PD_TCPM_ANX7447) - const struct usb_mux *mux = &usb_muxes[port]; -#endif - -#ifdef CONFIG_USB_PD_TCPM_ANX7447 mux_state_t mux_state = USB_PD_MUX_NONE; - if (pd_get_polarity(port)) - mux_state |= USB_PD_MUX_POLARITY_INVERTED; -#endif CPRINTS("pin_mode = %d", pin_mode); if (!pin_mode) return 0; -#if defined(CONFIG_USB_PD_TCPM_MUX) && defined(CONFIG_USB_PD_TCPM_ANX7447) switch (pin_mode) { case MODE_DP_PIN_A: case MODE_DP_PIN_C: case MODE_DP_PIN_E: mux_state |= USB_PD_MUX_DP_ENABLED; - mux->driver->set(mux, mux_state); break; case MODE_DP_PIN_B: case MODE_DP_PIN_D: case MODE_DP_PIN_F: mux_state |= USB_PD_MUX_DOCK; - mux->driver->set(mux, mux_state); break; } -#endif + usb_mux_set(port, mux_state, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); /* * board_set_usb_mux(port, USB_PD_MUX_DP_ENABLED, - * pd_get_polarity(port)); + * polarity_rm_dts(pd_get_polarity(port))); */ - payload[0] = VDO(USB_SID_DISPLAYPORT, 1, - CMD_DP_CONFIG | VDO_OPOS(opos)); + payload[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ - 1, /* DPv1.3 signaling */ - 2); /* UFP connected */ + 1, /* DPv1.3 signaling */ + 2); /* UFP connected */ return 2; } __override void svdm_dp_post_config(int port) { - const struct usb_mux *mux = &usb_muxes[port]; - dp_flags[port] |= DP_FLAGS_DP_ON; if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) return; - if (IS_ENABLED(CONFIG_USB_PD_TCPM_ANX7447)) - anx7447_tcpc_update_hpd_status(mux, 1, 0); + usb_mux_hpd_update(port, + USB_PD_MUX_HPD_LVL | USB_PD_MUX_HPD_IRQ_DEASSERTED); } __override int svdm_dp_attention(int port, uint32_t *payload) { -#ifdef CONFIG_USB_PD_TCPM_ANX7447 int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); - const struct usb_mux *mux = &usb_muxes[port]; + mux_state_t mux_state = + (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | + (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); + + /* Note: Usage is deprecated, use usb_mux_hpd_update instead */ CPRINTS("Attention: 0x%x", payload[1]); - anx7447_tcpc_update_hpd_status(mux, lvl, irq); -#endif + usb_mux_hpd_update(port, mux_state); + dp_status[port] = payload[1]; /* ack */ @@ -274,9 +253,7 @@ __override int svdm_dp_attention(int port, uint32_t *payload) __override void svdm_exit_dp_mode(int port) { - svdm_safe_dp_mode(port); -#ifdef CONFIG_USB_PD_TCPM_ANX7447 - anx7447_tcpc_clear_hpd_status(port); -#endif + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/board/pdeval-stm32f072/vif_override.xml b/board/pdeval-stm32f072/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/pdeval-stm32f072/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/phaser/battery.c b/board/phaser/battery.c index 2e1f77d552..25a0fbce92 100644 --- a/board/phaser/battery.c +++ b/board/phaser/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/phaser/board.c b/board/phaser/board.c index 219f5ad1b1..803cb18dd2 100644 --- a/board/phaser/board.c +++ b/board/phaser/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,8 @@ /* Phaser board-specific configuration */ #include "adc.h" -#include "adc_chip.h" +#include "battery_smart.h" +#include "builtin/stdnoreturn.h" #include "button.h" #include "charge_state.h" #include "common.h" @@ -25,23 +26,24 @@ #include "power.h" #include "power_button.h" #include "switch.h" -#include "task.h" +#include "system_chip.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "task.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usbc_ppc.h" #include "util.h" -#include "battery_smart.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define USB_PD_PORT_ANX7447 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 static uint8_t sku_id; static bool support_syv_ppc; +static uint8_t is_psl_hibernate; /* Check PPC ID and board version to decide which one ppc is used. */ static bool board_is_support_syv_ppc(void) @@ -84,31 +86,31 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, /* Vbus sensing (1/10 voltage divider). */ - [ADC_VBUS_C0] = { - "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, - [ADC_VBUS_C1] = { - "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS_C0] = { "VBUS_C0", NPCX_ADC_CH9, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + [ADC_VBUS_C1] = { "VBUS_C1", NPCX_ADC_CH4, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -118,11 +120,9 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate lid and base sensor into standard reference frame */ -const mat33_fp_t standard_rot_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t standard_rot_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct stprivate_data g_lis2dh_data; @@ -168,8 +168,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &standard_rot_ref, @@ -200,8 +198,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -215,8 +211,8 @@ unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); static int board_is_convertible(void) { - return sku_id == 2 || sku_id == 3 || sku_id == 4 || sku_id == 5 || \ - sku_id == 255; + return sku_id == 2 || sku_id == 3 || sku_id == 4 || sku_id == 5 || + sku_id == 255; } static void board_update_sensor_config_from_sku(void) @@ -245,12 +241,103 @@ static void cbi_init(void) board_update_sensor_config_from_sku(); support_syv_ppc = board_is_support_syv_ppc(); + + /* Please correct the SKU ID checking if it is not right */ + if (sku_id == 1 || sku_id == 2 || sku_id == 3 || sku_id == 4) + is_psl_hibernate = 0; + else + is_psl_hibernate = 1; } DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); -#ifndef TEST_BUILD +static void system_psl_type_sel(int psl_no, uint32_t flags) +{ + /* Set PSL input events' type as level or edge trigger */ + if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) + CLEAR_BIT(NPCX_GLUE_PSL_CTS, psl_no + 4); + else if ((flags & GPIO_INT_F_RISING) || (flags & GPIO_INT_F_FALLING)) + SET_BIT(NPCX_GLUE_PSL_CTS, psl_no + 4); + + /* + * Set PSL input events' polarity is low (high-to-low) active or + * high (low-to-high) active + */ + if (flags & GPIO_HIB_WAKE_HIGH) + SET_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_no); + else + CLEAR_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_no); +} + +int system_config_psl_mode(enum gpio_signal signal) +{ + int psl_no; + const struct gpio_info *g = gpio_list + signal; + + if (g->port == GPIO_PORT_D && g->mask == MASK_PIN2) /* GPIOD2 */ + psl_no = 0; + else if (g->port == GPIO_PORT_0 && (g->mask & 0x07)) /* GPIO00/01/02 */ + psl_no = GPIO_MASK_TO_NUM(g->mask) + 1; + else + return 0; + + system_psl_type_sel(psl_no, g->flags); + return 1; +} + +void system_enter_psl_mode(void) +{ + /* Configure pins from GPIOs to PSL which rely on VSBY power rail. */ + gpio_config_module(MODULE_PMU, 1); + + /* + * Only PSL_IN events can pull PSL_OUT to high and reboot ec. + * We should treat it as wake-up pin reset. + */ + NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_PIN; + + /* + * Pull PSL_OUT (GPIO85) to low to cut off ec's VCC power rail by + * setting bit 5 of PDOUT(8). + */ + SET_BIT(NPCX_PDOUT(GPIO_PORT_8), 5); +} + +/* Hibernate function implemented by PSL (Power Switch Logic) mode. */ +noreturn void __keep __enter_hibernate_in_psl(void) +{ + system_enter_psl_mode(); + /* Spin and wait for PSL cuts power; should never return */ + while (1) + ; +} +void board_hibernate_late(void) +{ + int i; + + /* + * If the SKU cannot use PSL hibernate, immediately return to go the + * non-PSL hibernate flow. + */ + if (!is_psl_hibernate) { + NPCX_KBSINPU = 0x0A; + return; + } + + for (i = 0; i < hibernate_wake_pins_used; i++) { + /* Config PSL pins setting for wake-up inputs */ + if (!system_config_psl_mode(hibernate_wake_pins[i])) + ccprintf("Invalid PSL setting in wake-up pin %d\n", i); + } + + /* Clear all pending IRQ otherwise wfi will have no affect */ + for (i = NPCX_IRQ_0; i < NPCX_IRQ_COUNT; i++) + task_clear_pending_irq(i); + + __enter_hibernate_in_psl(); +} + /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* * If the lid is in tablet position via other sensors, @@ -263,7 +350,6 @@ void lid_angle_peripheral_enable(int enable) if (board_is_convertible()) keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif int board_is_lid_angle_tablet_mode(void) { @@ -271,11 +357,11 @@ int board_is_lid_angle_tablet_mode(void) } /* Battery functions */ -#define SB_OPTIONALMFG_FUNCTION2 0x3e +#define SB_OPTIONALMFG_FUNCTION2 0x3e /* Optional mfg function2 */ -#define SMART_QUICK_CHARGE (1<<12) +#define SMART_QUICK_CHARGE (1 << 12) /* Quick charge support */ -#define MODE_QUICK_CHARGE_SUPPORT (1<<4) +#define MODE_QUICK_CHARGE_SUPPORT (1 << 4) static void sb_quick_charge_mode(int enable) { @@ -324,15 +410,15 @@ void board_overcurrent_event(int port, int is_overcurrented) } static const struct ppc_config_t ppc_syv682x_port0 = { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, }; static const struct ppc_config_t ppc_syv682x_port1 = { - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, }; static void board_setup_ppc(void) @@ -340,12 +426,10 @@ static void board_setup_ppc(void) if (!support_syv_ppc) return; - memcpy(&ppc_chips[USB_PD_PORT_TCPC_0], - &ppc_syv682x_port0, - sizeof(struct ppc_config_t)); - memcpy(&ppc_chips[USB_PD_PORT_TCPC_1], - &ppc_syv682x_port1, - sizeof(struct ppc_config_t)); + memcpy(&ppc_chips[USB_PD_PORT_TCPC_0], &ppc_syv682x_port0, + sizeof(struct ppc_config_t)); + memcpy(&ppc_chips[USB_PD_PORT_TCPC_1], &ppc_syv682x_port1, + sizeof(struct ppc_config_t)); gpio_set_flags(GPIO_USB_PD_C0_INT_ODL, GPIO_INT_BOTH); gpio_set_flags(GPIO_USB_PD_C1_INT_ODL, GPIO_INT_BOTH); diff --git a/board/phaser/board.h b/board/phaser/board.h index e230c98efc..54f3cf3b32 100644 --- a/board/phaser/board.h +++ b/board/phaser/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,12 +13,27 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" +/* b/203442963 + * It's workaround to reduce keyboard's "Silver Migration". + * From keyboard vendor's feedback, there are two factors to cause + * "Silver Migration". + * 1. A voltage potential between trace. + * 2. The presence of an electrolyte , such as moisture. + * The reason cause voltage potential between KSIxx trace is EC enter ec + * hibernate PSL and turn EC's VCC1 power off. Besides KSI2, the other + * KSIxx will be turn off. KSI2 is powered by H1. + * To avoid voltage potential is keep KSIxx on. That means not to enter + * ec hibernate PSL. + */ +#undef CONFIG_HIBERNATE_PSL + +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + #define CONFIG_VOLUME_BUTTONS #define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL #define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL #define CONFIG_LED_COMMON -#define CONFIG_LED_POWER_LED #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_13K7_47K_4050B @@ -29,8 +44,8 @@ #define CONFIG_CMD_ACCEL_INFO /* Sensors */ -#define CONFIG_ACCEL_LIS2DE /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LIS2DE /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) @@ -45,9 +60,11 @@ /* Additional PPC second source */ #define CONFIG_USBC_PPC_SYV682X -#define CONFIG_USBC_PPC_DEDICATED_INT -#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_USBC_PPC_DEDICATED_INT +#undef CONFIG_SYV682X_HV_ILIM #define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 +/* SYV682 isn't connected to CC, so TCPC must provide VCONN */ +#define CONFIG_USBC_PPC_SYV682X_NO_CC #ifndef __ASSEMBLER__ @@ -55,10 +72,10 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ - ADC_VBUS_C0, /* ADC9 */ - ADC_VBUS_C1, /* ADC4 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_VBUS_C0, /* ADC9 */ + ADC_VBUS_C1, /* ADC4 */ ADC_CH_COUNT, }; @@ -69,18 +86,10 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { diff --git a/board/phaser/build.mk b/board/phaser/build.mk index 3d04b75731..998a65a3de 100644 --- a/board/phaser/build.mk +++ b/board/phaser/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/phaser/ec.tasklist b/board/phaser/ec.tasklist index d98db145e7..977b8b01be 100644 --- a/board/phaser/ec.tasklist +++ b/board/phaser/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/phaser/gpio.inc b/board/phaser/gpio.inc index 639ed914b6..c6d2be7fc6 100644 --- a/board/phaser/gpio.inc +++ b/board/phaser/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/phaser/led.c b/board/phaser/led.c index 115832e3b6..16f68b28f9 100644 --- a/board/phaser/led.c +++ b/board/phaser/led.c @@ -1,53 +1,57 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Phaser */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 97; +__override const int led_charge_lvl_2 = 97; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_ON_LVL); @@ -56,7 +60,7 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_RED: @@ -109,4 +113,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/phaser/vif_override.xml b/board/phaser/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/phaser/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/pico/battery.c b/board/pico/battery.c new file mode 100644 index 0000000000..5e1671f5f3 --- /dev/null +++ b/board/pico/battery.c @@ -0,0 +1,189 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "gpio.h" + +const struct board_batt_params board_battery_info[] = { + /* LGC AP18C8K Battery Information */ + [BATTERY_LGC_AP18C8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G020", + .device_name = "AP18C8K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* Murata AP18C4K Battery Information */ + [BATTERY_MURATA_AP18C4K] = { + .fuel_gauge = { + .manuf_name = "Murata KT00304012", + .device_name = "AP18C4K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* Panasonic AP19B5K Battery Information */ + [BATTERY_PANASONIC_AP19B5K_KT00305011] = { + .fuel_gauge = { + .manuf_name = "PANASONIC KT00305011", + .device_name = "AP19B5K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x4000, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* LGC AP19B8K Battery Information */ + [BATTERY_LGC_AP19B8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G022", + .device_name = "AP19B8K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* COSMX AP20CBL Battery Information */ + [BATTERY_COSMX_AP20CBL] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B002", + .device_name = "AP20CBL", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* SMP AP18C7K Battery Information */ + [BATTERY_SMP_AP18C7K] = { + .fuel_gauge = { + .manuf_name = "SMP KT00307010", + .device_name = "AP18C7K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0002, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC_AP18C8K; + +enum battery_present battery_hw_present(void) +{ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/pico/board.c b/board/pico/board.c new file mode 100644 index 0000000000..30708c3adc --- /dev/null +++ b/board/pico/board.c @@ -0,0 +1,421 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "backlight.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/battery/max17055.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/usb_mux/it5205.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "panic.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "spi.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpm.h" +#include "timer.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#ifndef VARIANT_KUKUI_NO_SENSORS +/* Motion sensors */ +/* Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Rotation matrixes */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +/* sensor private data */ +static struct kionix_accel_data g_kx022_data; +static struct bmi_drv_data_t g_bmi160_data; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, enough to calculate lid angle. */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [BASE_ACCEL] = { + .name = "Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static bool board_is_convertible(void) +{ + int sku = system_get_sku_id(); + + return sku == 1 || sku == 2; +} + +int board_sensor_at_360(void) +{ + if (board_is_convertible()) + return !gpio_get_level(GPIO_TABLET_MODE_L); + + return 0; +} +#endif /* !VARIANT_KUKUI_NO_SENSORS */ +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { GPIO_KSO_H, 4 }, { GPIO_KSO_H, 0 }, + { GPIO_KSO_H, 1 }, { GPIO_KSO_H, 3 }, { GPIO_KSO_H, 2 }, + { -1, -1 }, { -1, -1 }, { GPIO_KSO_L, 5 }, + { GPIO_KSO_L, 6 }, { -1, -1 }, { GPIO_KSO_L, 3 }, + { GPIO_KSO_L, 2 }, { GPIO_KSI, 0 }, { GPIO_KSO_L, 1 }, + { GPIO_KSO_L, 4 }, { GPIO_KSI, 3 }, { GPIO_KSI, 2 }, + { GPIO_KSO_L, 0 }, { GPIO_KSI, 5 }, { GPIO_KSI, 4 }, + { GPIO_KSO_L, 7 }, { GPIO_KSI, 6 }, { GPIO_KSI, 7 }, + { GPIO_KSI, 1 }, { -1, -1 }, { GPIO_KSO_H, 5 }, + { -1, -1 }, { GPIO_KSO_H, 6 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +/* Wake-up pins for hibernate */ +const enum gpio_signal hibernate_wake_pins[] = { + GPIO_AC_PRESENT, + GPIO_LID_OPEN, + GPIO_POWER_BUTTON_L, +}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/******************************************************************************/ +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + [ADC_BOARD_ID] = { "BOARD_ID", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH1 }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH2 }, + [ADC_VBUS] = { "VBUS", ADC_MAX_MVOLT * 10, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/******************************************************************************/ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "typec", + .port = IT83XX_I2C_CH_C, + .kbps = 400, + .scl = GPIO_I2C_C_SCL, + .sda = GPIO_I2C_C_SDA }, + { .name = "sensor", + .port = IT83XX_I2C_CH_B, + .kbps = 400, + .scl = GPIO_I2C_B_SCL, + .sda = GPIO_I2C_B_SDA }, + { .name = "battery", + .port = IT83XX_I2C_CH_A, + .kbps = 100, + .scl = GPIO_I2C_A_SCL, + .sda = GPIO_I2C_A_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +#define BC12_I2C_ADDR PI3USB9201_I2C_ADDR_3 + +/* power signal list. Must match order of enum power_signal. */ +const struct power_signal_info power_signal_list[] = { + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, +}; +BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); + +/******************************************************************************/ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/******************************************************************************/ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + /* TCPC is embedded within EC so no i2c config needed */ + .drv = &it8xxx2_tcpm_drv, + /* Alert is active-low, push-pull */ + .flags = 0, + }, +}; + +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) +{ + /* This driver does not use host command ACKs */ + *ack_required = false; + + /* + * svdm_dp_attention() did most of the work, we only need to notify + * host here. + */ + host_set_single_event(EC_HOST_EVENT_USB_MUX); +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, + }, +}; + +/* Charger config. Start i2c address at 1, update during runtime */ +struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +static int force_discharge; + +int board_set_active_charge_port(int charge_port) +{ + CPRINTS("New chg p%d", charge_port); + + /* ignore all request when discharge mode is on */ + if (force_discharge && charge_port != CHARGE_PORT_NONE) + return EC_SUCCESS; + + switch (charge_port) { + case CHARGE_PORT_USB_C: + /* Don't charge from a source port */ + if (board_vbus_source_enabled(charge_port)) + return -1; + break; + default: + /* + * To ensure the fuel gauge (max17055) is always powered + * even when battery is disconnected, keep VBAT rail on but + * set the charging current to minimum. + */ + charger_set_current(CHARGER_SOLO, 0); + break; + } + + return EC_SUCCESS; +} + +int board_discharge_on_ac(int enable) +{ + int ret, port; + + if (enable) { + port = CHARGE_PORT_NONE; + } else { + /* restore the charge port state */ + port = charge_manager_get_override(); + if (port == OVERRIDE_OFF) + port = charge_manager_get_active_charge_port(); + } + + ret = charger_discharge_on_ac(enable); + if (ret) + return ret; + + force_discharge = enable; + return board_set_active_charge_port(port); +} + +#define VBUS_THRESHOLD_MV 4200 +int pd_snk_is_vbus_provided(int port) +{ + /* This board has only one port. */ + if (!port) + return adc_read_channel(ADC_VBUS) > VBUS_THRESHOLD_MV ? 1 : 0; + else + return 0; +} + +void bc12_interrupt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void board_init(void) +{ + /* If the reset cause is external, pulse PMIC force reset. */ + if (system_get_reset_flags() == EC_RESET_FLAG_RESET_PIN) { + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 0); + msleep(100); + gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 1); + } + +#ifndef VARIANT_KUKUI_NO_SENSORS + /* Enable interrupts from BMI160 sensor. */ + gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); +#endif /* VARIANT_KUKUI_NO_SENSORS */ + + /* Enable interrupt from PMIC. */ + gpio_enable_interrupt(GPIO_PMIC_EC_RESETB); + + /* Enable BC12 interrupt */ + gpio_enable_interrupt(GPIO_BC12_EC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +#ifndef VARIANT_KUKUI_NO_SENSORS +static void board_motion_init(void) +{ + if (!board_is_convertible()) { + /* Disable motion sense. */ + motion_sensor_count = 0; + gpio_disable_interrupt(GPIO_ACCEL_INT_ODL); + gpio_set_flags(GPIO_ACCEL_INT_ODL, GPIO_INPUT); + /* Disable tablet mode. */ + tablet_set_mode(0, TABLET_TRIGGER_LID); + gmr_tablet_switch_disable(); + gpio_set_flags(GPIO_TABLET_MODE_L, GPIO_INPUT | GPIO_PULL_UP); + } +} +DECLARE_HOOK(HOOK_INIT, board_motion_init, HOOK_PRIO_DEFAULT + 1); +#endif /* VARIANT_KUKUI_NO_SENSORS */ + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* Vconn control is only for port 0 */ + if (port) + return; + + if (cc_pin == USBPD_CC_PIN_1) + gpio_set_level(GPIO_EN_USB_C0_CC1_VCONN, !!enabled); + else + gpio_set_level(GPIO_EN_USB_C0_CC2_VCONN, !!enabled); +} + +/* Called on AP S5 -> S3 transition */ +static void board_chipset_startup(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S5 transition */ +static void board_chipset_shutdown(void) +{ + gpio_set_level(GPIO_EN_USBA_5V, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); diff --git a/board/pico/board.h b/board/pico/board.h new file mode 100644 index 0000000000..1cfed1eba1 --- /dev/null +++ b/board/pico/board.h @@ -0,0 +1,156 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Configuration for Kukui */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KUKUI_JACUZZI +#define VARIANT_KUKUI_BATTERY_SMART +#define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_IT81202 + +#ifndef SECTION_IS_RW +#define VARIANT_KUKUI_NO_SENSORS +#endif /* SECTION_IS_RW */ + +#include "baseboard.h" + +/* TODO: remove me once we fix IT83XX_ILM_BLOCK_SIZE out of space issue */ +#undef CONFIG_LTO + +#undef CONFIG_CHIPSET_POWER_SEQ_VERSION +#define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 + +#define CONFIG_BATTERY_HW_PRESENT_CUSTOM + +#define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +#define CONFIG_CHARGER_RUNTIME_CONFIG + +#define CONFIG_BC12_DETECT_PI3USB9201 + +#define CONFIG_EXTPOWER_GPIO +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 200 + +#undef CONFIG_I2C_NACK_RETRY_COUNT +#define CONFIG_I2C_NACK_RETRY_COUNT 10 +#define CONFIG_SMBUS_PEC + +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP +#define CONFIG_USB_PD_DISCHARGE_GPIO +#define CONFIG_USB_PD_TCPC_LOW_POWER + +#define CONFIG_USB_MUX_IT5205 + +/* Motion Sensors */ +#ifndef VARIANT_KUKUI_NO_SENSORS +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ALS +#define CONFIG_CMD_ACCEL_INFO + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_GMR_TABLET_MODE_CUSTOM +#endif /* !VARIANT_KUKUI_NO_SENSORS */ + +/* I2C ports */ +#define I2C_PORT_BC12 IT83XX_I2C_CH_C +#define I2C_PORT_TCPC0 IT83XX_I2C_CH_C +#define I2C_PORT_USB_MUX IT83XX_I2C_CH_C +#define I2C_PORT_CHARGER IT83XX_I2C_CH_A +#define I2C_PORT_SENSORS IT83XX_I2C_CH_B +#define I2C_PORT_ACCEL I2C_PORT_SENSORS +#define I2C_PORT_BATTERY IT83XX_I2C_CH_A +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY + +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_EVENT +#define CONFIG_MKBP_USE_GPIO + +#define CONFIG_LED_ONOFF_STATES + +#ifndef __ASSEMBLER__ + +enum adc_channel { + /* Real ADC channels begin here */ + ADC_BOARD_ID = 0, + ADC_EC_SKU_ID, + ADC_VBUS, + ADC_CH_COUNT +}; + +/* power signal definitions */ +enum power_signal { + AP_IN_S3_L, + PMIC_PWR_GOOD, + + /* Number of signals */ + POWER_SIGNAL_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum charge_port { + CHARGE_PORT_USB_C, +}; + +enum battery_type { + BATTERY_LGC_AP18C8K, + BATTERY_MURATA_AP18C4K, + BATTERY_PANASONIC_AP19B5K_KT00305011, + BATTERY_LGC_AP19B8K, + BATTERY_COSMX_AP20CBL, + BATTERY_SMP_AP18C7K, + BATTERY_TYPE_COUNT, +}; + +#include "gpio_signal.h" +#include "registers.h" + +/* support factory keyboard test */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +extern const int keyboard_factory_scan_pins[][2]; +extern const int keyboard_factory_scan_pins_used; + +#ifdef SECTION_IS_RO +/* Interrupt handler for AP jump to BL */ +void emmc_ap_jump_to_bl(enum gpio_signal signal); +#endif + +void bc12_interrupt(enum gpio_signal signal); +void board_reset_pd_mcu(void); +int board_get_version(void); + +/* returns the i2c port number of charger/battery */ +int board_get_charger_i2c(void); +int board_get_battery_i2c(void); + +/* Motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/pico/build.mk b/board/pico/build.mk new file mode 100644 index 0000000000..a1ca27116e --- /dev/null +++ b/board/pico/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# +# +# IC is ITE IT81202 +CHIP:=it83xx +CHIP_FAMILY:=it8xxx2 +CHIP_VARIANT:=it81202bx_1024 +BASEBOARD:=kukui + +board-y=battery.o board.o led.o diff --git a/board/pico/ec.tasklist b/board/pico/ec.tasklist new file mode 100644 index 0000000000..883033408a --- /dev/null +++ b/board/pico/ec.tasklist @@ -0,0 +1,18 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) diff --git a/board/pico/gpio.inc b/board/pico/gpio.inc new file mode 100644 index 0000000000..359e25451e --- /dev/null +++ b/board/pico/gpio.inc @@ -0,0 +1,150 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Interrupts */ +GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH, + power_button_interrupt) /* EC_PWR_BTN_ODL */ +GPIO_INT(AP_IN_SLEEP_L, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(PMIC_EC_RESETB, PIN(F, 3), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(WARM_RESET_REQ, PIN(D, 3), GPIO_INT_RISING | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + chipset_reset_request_interrupt) +GPIO_INT_RW(ACCEL_INT_ODL, PIN(J, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, + bmi160_interrupt) +GPIO_INT_RO(BOOTBLOCK_EN_L, PIN(J, 1), GPIO_INT_RISING | GPIO_SEL_1P8V, + emmc_ap_jump_to_bl) +GPIO_INT(SPI0_CS, PIN(M, 5), GPIO_INT_FALLING, + spi_event) /* SPI slave Chip Select -- AP_SPI_EC_CS_L */ +GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH, + lid_interrupt) +GPIO_INT(AC_PRESENT, PIN(E, 5), GPIO_INT_BOTH, + extpower_interrupt) /* ACOK_OD */ +GPIO_INT(BC12_EC_INT_ODL, PIN(J, 6), GPIO_INT_FALLING, + bc12_interrupt) +GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 7), GPIO_INT_FALLING | GPIO_SEL_1P8V, + chipset_watchdog_interrupt) +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, + uart_deepsleep_interrupt) /* UART_DEBUG_TX_EC_RX */ +GPIO_INT(TABLET_MODE_L, PIN(J, 7), GPIO_INT_BOTH, + gmr_tablet_switch_isr) +/* Unimplemented interrupts */ +GPIO(VOLUME_DOWN_L, PIN(D, 5), GPIO_INPUT) +GPIO(VOLUME_UP_L, PIN(D, 6), GPIO_INPUT) +GPIO(ALS_RGB_INT_ODL, PIN(F, 0), GPIO_INPUT) +GPIO(LID_ACCEL_INT_ODL, PIN(J, 3), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Reset pins */ +GPIO(AP_SYS_RST_L, PIN(B, 6), GPIO_OUT_LOW) +/* 1.8V PP or 1.8V OD output with external 10K PU */ +GPIO(PMIC_WATCHDOG_L, PIN(H, 0), GPIO_ODR_LOW | GPIO_SEL_1P8V) +/* OD output with 5VT (there is 5V internal PU on PWRKEY of MT6358) */ +GPIO(PMIC_EN_ODL, PIN(E, 1), GPIO_ODR_HIGH) + +/* + * I2C pins should be configured as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +/* EC programming */ +GPIO(I2C_E_SCL, PIN(A, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(I2C_E_SDA, PIN(A, 5), GPIO_INPUT | GPIO_SEL_1P8V) +/* battery and charger */ +GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) +/* sensor */ +GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT | GPIO_SEL_1P8V) +/* typec */ +GPIO(I2C_C_SCL, PIN(F, 6), GPIO_INPUT) +GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) + +/* Other input pins */ +/* TODO(WP_L): change to interrupt pin ? */ +GPIO(WP_L, PIN(I, 4), GPIO_INPUT | GPIO_SEL_1P8V) /* EC_FLASH_WP_ODL */ +GPIO(CCD_MODE_ODL, PIN(C, 4), GPIO_INPUT) + +/* Other output pins */ +GPIO(EC_BATT_PRES_ODL, PIN(C, 0), GPIO_INPUT) +GPIO(EC_BL_EN_OD, PIN(B, 5), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EN_USBA_5V, PIN(B, 7), GPIO_OUT_LOW) +GPIO(ENTERING_RW, PIN(C, 5), GPIO_ODR_HIGH) /* EC_ENTERING_RW_ODL */ +GPIO(EC_INT_L, PIN(E, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_AP_INT_ODL */ +GPIO(EC_BOARD_ID_EN_L, PIN(H, 5), GPIO_ODR_HIGH) /* EC_BOARD_ID_EN_ODL */ +GPIO(USB_C0_HPD_OD, PIN(J, 0), GPIO_ODR_LOW) +GPIO(USB_C0_DISCHARGE, PIN(H, 3), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC1_VCONN, PIN(H, 1), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC2_VCONN, PIN(H, 2), GPIO_OUT_LOW) + +/* LEDs */ +GPIO(LED_BLUE, PIN(A, 2), GPIO_OUT_HIGH) +GPIO(LED_GREEN, PIN(A, 1), GPIO_OUT_HIGH) +GPIO(LED_ORANGE, PIN(A, 0), GPIO_OUT_HIGH) +GPIO(EN_PP1800_S5_L, PIN(D, 0), GPIO_OUT_LOW) + +/* Unimplemented Pins */ +GPIO(PG_PP5000_A_OD, PIN(A, 6), GPIO_INPUT) +GPIO(USB_A0_OC_ODL, PIN(A, 7), GPIO_INPUT) +GPIO(EC_PROCHOT_ODL, PIN(C, 3), GPIO_INPUT) +GPIO(PMIC_FORCE_RESET_ODL, PIN(C, 6), GPIO_INPUT) +GPIO(USB_C0_PD_INT_ODL, PIN(D, 1), GPIO_INPUT) /* no used on this board */ +GPIO(EN_PP5000A_USM, PIN(D, 7), GPIO_INPUT) +GPIO(EN_USBC_CHARGE_L, PIN(F, 1), GPIO_INPUT) +GPIO(EN_PP5000_USBC, PIN(H, 4), GPIO_INPUT) +GPIO(PP1800_H1_PG, PIN(H, 6), GPIO_INPUT) + +/* NC pins, ensure they aren't in floating state. */ +GPIO(NC_GPA3, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPB2, PIN(B, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPD2, PIN(D, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPD4, PIN(D, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPE0, PIN(E, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPE3, PIN(E, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPE7, PIN(E, 7), GPIO_INPUT | GPIO_PULL_DOWN) +/* + * ADC pins don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(NC_GPI5, PIN(I, 5), GPIO_OUT_LOW) +GPIO(NC_GPI7, PIN(I, 7), GPIO_OUT_LOW) + +GPIO(NC_GPJ4, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPJ5, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +/* + * GPG3,4,5,7 don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(NC_GPG0, PIN(G, 0), GPIO_INPUT | GPIO_PULL_DOWN) +/* Don't touch GPG1 and GPG2 */ +GPIO(NC_GPG3, PIN(G, 3), GPIO_OUT_LOW) +GPIO(EC_SPI_FLASH_MOSI, PIN(G, 4), GPIO_OUT_LOW) +GPIO(EC_SPI_FLASH_MISO, PIN(G, 5), GPIO_OUT_LOW) +GPIO(EC_SPI_FLASH_CLK, PIN(G, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_SPI_FLASH_CS_L, PIN(G, 7), GPIO_OUT_LOW) + +/* Alternate functions GPIO definitions */ +/* Keyboard */ +ALTERNATE(PIN_MASK(KSI, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSI0-7 */ +ALTERNATE(PIN_MASK(KSO_H, 0xFF), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO8-15 */ +ALTERNATE(PIN_MASK(KSO_L, 0xFB), 0, MODULE_KEYBOARD_SCAN, 0) /* KSO0-1, 3-7 */ +GPIO(EC_KSO_02_INV, PIN(KSO_L, 2), GPIO_OUT_LOW) /* KSO2 inverted */ +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A */ +ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C B */ +ALTERNATE(PIN_MASK(F, 0xC0), 1, MODULE_I2C, 0) /* I2C C */ +/* ADC */ +ALTERNATE(PIN_MASK(I, 0x4F), 0, MODULE_ADC, 0) /* ADC 0,1,2,3,6 */ +/* UART */ +ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, 0) /* EC to Servo */ +/* EMMC SPI SLAVE M2:CLK, M3:CMD, M6:DATA0 */ +ALTERNATE(PIN_MASK(M, 0x4C), 0, MODULE_SPI_FLASH, 0) +/* SPI */ +ALTERNATE(PIN_MASK(M, 0x33), 0, MODULE_SPI, 0) /* SPI for communication */ diff --git a/board/pico/led.c b/board/pico/led.c new file mode 100644 index 0000000000..bbbad7ceb8 --- /dev/null +++ b/board/pico/led.c @@ -0,0 +1,85 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Jacuzzi + */ +#include "common.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_ORANGE, LED_ON_LVL); + gpio_set_level(GPIO_LED_BLUE, LED_OFF_LVL); + gpio_set_level(GPIO_LED_GREEN, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_LED_BLUE, LED_ON_LVL); + gpio_set_level(GPIO_LED_ORANGE, LED_OFF_LVL); + gpio_set_level(GPIO_LED_GREEN, LED_OFF_LVL); + break; + case EC_LED_COLOR_GREEN: + gpio_set_level(GPIO_LED_GREEN, LED_ON_LVL); + gpio_set_level(GPIO_LED_BLUE, LED_OFF_LVL); + gpio_set_level(GPIO_LED_ORANGE, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_GREEN, LED_OFF_LVL); + gpio_set_level(GPIO_LED_BLUE, LED_OFF_LVL); + gpio_set_level(GPIO_LED_ORANGE, LED_OFF_LVL); + break; + } +} +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + } +} +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} diff --git a/board/pico/vif_override.xml b/board/pico/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/pico/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/pirika/battery.c b/board/pirika/battery.c new file mode 100644 index 0000000000..f753eba554 --- /dev/null +++ b/board/pirika/battery.c @@ -0,0 +1,94 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all waddledee battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /*COSMX CA14J43 Battery Information */ + [BATTERY_CA14J43] = { + .fuel_gauge = { + .manuf_name = "PG01LJ3353", + .device_name = "CA14J43", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + /*COSMX CA11J58 Battery Information */ + [BATTERY_CA11J58] = { + .fuel_gauge = { + .manuf_name = "PG01NL3353", + .device_name = "CA11J58", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_CA14J43; diff --git a/board/pirika/board.c b/board/pirika/board.c new file mode 100644 index 0000000000..d1baae03f2 --- /dev/null +++ b/board/pirika/board.c @@ -0,0 +1,789 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledee board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/tusb544.h" +#include "driver/tcpm/raa489000.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +/* Use default keyboard scan config, because board didn't supply one */ +__override struct keyboard_scan_config keyscan_config = { + /* + * CONFIG_KEYBOARD_COL2_INVERTED is defined for passing the column 2 + * to H1 which inverts the signal. The signal passing through H1 + * adds more delay. Need a larger delay value. Otherwise, pressing + * Refresh key will also trigger T key, which is in the next scanning + * column line. See http://b/156007029. + */ + .output_settle_us = 80, + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xf6, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config pirika_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config pasara_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (get_cbi_fw_config_numeric_pad() == NUMERIC_PAD_ABSENT) + return &pirika_kb; + else + return &pasara_kb; +} + +static void notify_c0_chips(void) +{ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + [CHARGER_PRIMARY] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, + [CHARGER_SECONDARY] = { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +/* USB Retimer */ +enum tusb544_conf { USB_DP = 0, USB_DP_INV, USB, USB_INV, DP, DP_INV }; + +static int board_tusb544_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + enum tusb544_conf usb_mode = 0; + /* USB */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* USB with DP */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? + USB_DP_INV : + USB_DP; + } + /* USB without DP */ + else { + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? + USB_INV : + USB; + } + } + /* DP without USB */ + else if (mux_state & USB_PD_MUX_DP_ENABLED) { + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? DP_INV : + DP; + } + /* Nothing enabled */ + else + return EC_SUCCESS; + /* Write the retimer config byte */ + if (usb_mode == USB_INV) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x15); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0x22); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0x22); + } else if (usb_mode == USB) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x11); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0x22); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0x22); + } else if (usb_mode == USB_DP_INV) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1F); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x99); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0x22); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0x22); + } else if (usb_mode == USB_DP) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1B); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x99); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x33); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0x22); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0x22); + } else if (usb_mode == DP_INV) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1E); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x99); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x99); + } else if (usb_mode == DP) { + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1A); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x99); + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x99); + } + + return rv; +} + +const struct usb_mux_chain usbc1_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = TUSB544_I2C_ADDR_FLAGS0, + .driver = &tusb544_drv, + .board_set = &board_tusb544_set, + }, +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + .next = &usbc1_retimer, + }, +}; + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_INT_ODL); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) + hook_call_deferred(&check_c1_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + /* Enable Base Accel interrupt */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + + /* Turn on 5V if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + if (get_cbi_fw_config_numeric_pad() == NUMERIC_PAD_ABSENT) { + keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); + } else { + /* Setting scan mask KSO11, KSO12, KSO13 and KSO14 */ + keyscan_config.actual_key_mask[11] = 0xfe; + keyscan_config.actual_key_mask[12] = 0xff; + keyscan_config.actual_key_mask[13] = 0xff; + keyscan_config.actual_key_mask[14] = 0xff; + } +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Put all charger ICs present into low power mode before entering + * z-state. + */ + raa489000_hibernate(CHARGER_PRIMARY, true); + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(CHARGER_SECONDARY, true); +} + +__override void board_ocpc_init(struct ocpc_data *ocpc) +{ + /* There's no provision to measure Isys */ + ocpc->chg_flags[CHARGER_SECONDARY] |= OCPC_NO_ISYS_MEAS_CAP; +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + gpio_set_level(GPIO_EN_USB_A0_VBUS, !!enable); + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", enable ? "en" : "dis"); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_0; + } + } + + /* Check whether TCPC 1 pulled the shared interrupt line */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (port == i) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (!board_is_usb_pd_port_present(port)) + return; + + raa489000_set_output_current(port, rp); +} + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq_hz = 10000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Sensor Mutexes */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Sensor Data */ +static struct kionix_accel_data g_kx022_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* Drivers */ +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = NULL, + .default_range = 2, /* g */ + /* We only use 2g because its resolution is only 8-bits */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = NULL, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = NULL, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, +}; + +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Vcore", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(50), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_VCORE \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(53), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_vcore = + THERMAL_VCORE; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_AMBIENT \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(50), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_ambient = + THERMAL_AMBIENT; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1] = THERMAL_CHARGER, + [TEMP_SENSOR_2] = THERMAL_VCORE, + [TEMP_SENSOR_3] = THERMAL_AMBIENT, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This cause Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} diff --git a/board/pirika/board.h b/board/pirika/board.h new file mode 100644 index 0000000000..c8e2f3eb35 --- /dev/null +++ b/board/pirika/board.h @@ -0,0 +1,143 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledee board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +/* System unlocked in early development */ +#undef CONFIG_SYSTEM_UNLOCKED + +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_CMD_CHARGER_DUMP + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#undef CONFIG_CHARGER_SINGLE_CHIP +#define CONFIG_OCPC +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) + +#define GPIO_USB_C1_INT_ODL GPIO_SUB_USB_C1_INT_ODL + +/* LED */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* PWM */ +#define CONFIG_PWM + +/* Sensors */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* Power of 2 - Too large of a fifo causes too much timestamp jitter */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_RAA489000 +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B +#define CONFIG_THROTTLE_AP +#define CONFIG_CHIPSET_CAN_THROTTLE + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +#define CONFIG_USBC_RETIMER_TUSB544 /* C1 Redriver: TUSB544 */ + +/* Keyboard */ +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_KEYPAD + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_CA14J43, + BATTERY_CA11J58, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/pirika/build.mk b/board/pirika/build.mk new file mode 100644 index 0000000000..01b890bf29 --- /dev/null +++ b/board/pirika/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/pirika/cbi_ssfc.c b/board/pirika/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/pirika/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/pirika/cbi_ssfc.h b/board/pirika/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/pirika/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/pirika/ec.tasklist b/board/pirika/ec.tasklist new file mode 100644 index 0000000000..f7c32f66bf --- /dev/null +++ b/board/pirika/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/pirika/gpio.inc b/board/pirika/gpio.inc new file mode 100644 index 0000000000..5ec1003a70 --- /dev/null +++ b/board/pirika/gpio.inc @@ -0,0 +1,145 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(SUB_USB_C1_INT_ODL, PIN(E, 6), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c1_interrupt) +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) /* Board rev 1, NC board rev 0 */ + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc pins which will run to the I/O board */ + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) + +/* LED */ +GPIO(LED_R_ODL, PIN(A, 1), GPIO_OUT_HIGH) +GPIO(LED_G_ODL, PIN(A, 2), GPIO_OUT_HIGH) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOA0_NC, PIN(A, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA3_NC, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOB5_NC, PIN(B, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC4_NC, PIN(C, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC6_NC, PIN(C, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF0_NC, PIN(F, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF1_NC, PIN(F, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF4_NC, PIN(F, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ1_NC, PIN(J, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ3_NC, PIN(J, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL0_NC, PIN(L, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL3_NC, PIN(L, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(2)), 0, MODULE_ADC, 0) /* ADC15: TEMP_SENSOR_3 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ + diff --git a/board/pirika/led.c b/board/pirika/led.c new file mode 100644 index 0000000000..916f691dd6 --- /dev/null +++ b/board/pirika/led.c @@ -0,0 +1,106 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { LED_OFF, 2 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_R_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_G_ODL, LED_ON_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_R_ODL, LED_ON_LVL); + gpio_set_level(GPIO_LED_G_ODL, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_R_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_G_ODL, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + /* Battery error LED behavior as below: + * S0: Blinking Amber LED, 1s on/ 1s off + * S3/S5: following S3/S5 behavior + * Add function to let battery error LED follow S3/S5 behavior in S3/S5. + */ + + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/pirika/usb_pd_policy.c b/board/pirika/usb_pd_policy.c new file mode 100644 index 0000000000..83c09bb99e --- /dev/null +++ b/board/pirika/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/pirika/vif_override.xml b/board/pirika/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/pirika/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/plankton/board.c b/board/plankton/board.c index 551642fae0..160192e7ff 100644 --- a/board/plankton/board.c +++ b/board/plankton/board.c @@ -1,11 +1,10 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Plankton board configuration */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "console.h" #include "gpio.h" @@ -23,6 +22,7 @@ void button_event(enum gpio_signal signal); void hpd_event(enum gpio_signal signal); void vbus_event(enum gpio_signal signal); +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" static volatile uint64_t hpd_prev_ts; @@ -79,14 +79,12 @@ void hpd_lvl_deferred(void) /* Configure redriver's back side */ if (level) sn75dp130_dpcd_init(); - } /* Send queued IRQ if the cable is attached */ if (hpd_possible_irq && level && dp_mode) pd_send_hpd(0, hpd_irq); hpd_possible_irq = 0; - } DECLARE_DEFERRED(hpd_lvl_deferred); @@ -104,8 +102,7 @@ void hpd_event(enum gpio_signal signal) hpd_prev_ts = now.val; /* All previous hpd level events need to be re-triggered */ - hook_call_deferred(&hpd_lvl_deferred_data, - HPD_USTREAM_DEBOUNCE_LVL); + hook_call_deferred(&hpd_lvl_deferred_data, HPD_USTREAM_DEBOUNCE_LVL); } /* Debounce time for voltage buttons */ @@ -135,8 +132,7 @@ enum usbc_action { USBC_ACT_COUNT }; -enum board_src_cap src_cap_mapping[USBC_ACT_COUNT] = -{ +enum board_src_cap src_cap_mapping[USBC_ACT_COUNT] = { [USBC_ACT_5V_TO_DUT] = SRC_CAP_5V, [USBC_ACT_12V_TO_DUT] = SRC_CAP_12V, [USBC_ACT_20V_TO_DUT] = SRC_CAP_20V, @@ -156,21 +152,21 @@ static void set_active_cc(int cc) * disabled then only set the active CC line. */ /* Pull-up on CC2 */ - gpio_set_flags(GPIO_USBC_CC2_HOST, - ((cc || drp_enable) && host_mode) ? - GPIO_OUT_HIGH : GPIO_INPUT); + gpio_set_flags(GPIO_USBC_CC2_HOST, ((cc || drp_enable) && host_mode) ? + GPIO_OUT_HIGH : + GPIO_INPUT); /* Pull-down on CC2 */ gpio_set_flags(GPIO_USBC_CC2_DEVICE_ODL, - ((cc || drp_enable) && !host_mode) ? - GPIO_OUT_LOW : GPIO_INPUT); + ((cc || drp_enable) && !host_mode) ? GPIO_OUT_LOW : + GPIO_INPUT); /* Pull-up on CC1 */ - gpio_set_flags(GPIO_USBC_CC1_HOST, - ((!cc || drp_enable) && host_mode) ? - GPIO_OUT_HIGH : GPIO_INPUT); + gpio_set_flags(GPIO_USBC_CC1_HOST, ((!cc || drp_enable) && host_mode) ? + GPIO_OUT_HIGH : + GPIO_INPUT); /* Pull-down on CC1 */ gpio_set_flags(GPIO_USBC_CC1_DEVICE_ODL, - ((!cc || drp_enable) && !host_mode) ? - GPIO_OUT_LOW : GPIO_INPUT); + ((!cc || drp_enable) && !host_mode) ? GPIO_OUT_LOW : + GPIO_INPUT); } /** @@ -222,7 +218,7 @@ static void fake_disconnect_end(void) board_pd_set_host_mode(fake_pd_host_mode); /* Restart CC cable detection */ - hook_call_deferred(&detect_cc_cable_data, 500*MSEC); + hook_call_deferred(&detect_cc_cable_data, 500 * MSEC); } DECLARE_DEFERRED(fake_disconnect_end); @@ -362,10 +358,10 @@ static void set_usbc_action(enum usbc_action act) gpio_set_level(GPIO_CASE_CLOSE_EN, 1); gpio_set_level(GPIO_CASE_CLOSE_DFU_L, 1); break; - case USBC_ACT_DRP_TOGGLE: + case USBC_ACT_DRP_TOGGLE: /* Toggle dualrole mode setting. */ - update_usbc_dual_role(drp_enable ? - PD_DRP_TOGGLE_OFF : PD_DRP_TOGGLE_ON); + update_usbc_dual_role(drp_enable ? PD_DRP_TOGGLE_OFF : + PD_DRP_TOGGLE_ON); break; default: break; @@ -425,8 +421,8 @@ static void button_deferred(void) break; } - ccprintf("Button %d = %d\n", - button_pressed, gpio_get_level(button_pressed)); + ccprintf("Button %d = %d\n", button_pressed, + gpio_get_level(button_pressed)); } DECLARE_DEFERRED(button_deferred); @@ -454,15 +450,18 @@ void vbus_event(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_CH_CC1_PD] = {"CC1_PD", 3300, 4096, 0, STM32_AIN(0)}, - [ADC_CH_CC2_PD] = {"CC2_PD", 3300, 4096, 0, STM32_AIN(4)}, + [ADC_CH_CC1_PD] = { "CC1_PD", 3300, 4096, 0, STM32_AIN(0) }, + [ADC_CH_CC2_PD] = { "CC2_PD", 3300, 4096, 0, STM32_AIN(4) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + { .name = "master", + .port = I2C_PORT_MASTER, + .kbps = 100, + .scl = GPIO_MASTER_I2C_SCL, + .sda = GPIO_MASTER_I2C_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -472,12 +471,12 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); * Pin number for active-high reset from PCA9534 to CMOS pull-down to * SN75DP130's RSTN (active-low) */ -#define REDRIVER_RST_PIN 0x1 +#define REDRIVER_RST_PIN 0x1 static int sn75dp130_i2c_write(uint8_t index, uint8_t value) { - return i2c_write8(I2C_PORT_MASTER, SN75DP130_I2C_ADDR_FLAGS, - index, value); + return i2c_write8(I2C_PORT_MASTER, SN75DP130_I2C_ADDR_FLAGS, index, + value); } /** @@ -490,17 +489,15 @@ static int sn75dp130_reset(void) { int rv; - rv = pca9534_config_pin(I2C_PORT_MASTER, 0x20, - REDRIVER_RST_PIN, PCA9534_OUTPUT); + rv = pca9534_config_pin(I2C_PORT_MASTER, 0x20, REDRIVER_RST_PIN, + PCA9534_OUTPUT); /* Assert (its active high) */ - rv |= pca9534_set_level(I2C_PORT_MASTER, 0x20, - REDRIVER_RST_PIN, 1); + rv |= pca9534_set_level(I2C_PORT_MASTER, 0x20, REDRIVER_RST_PIN, 1); /* datasheet recommends > 100usec */ usleep(200); /* De-assert */ - rv |= pca9534_set_level(I2C_PORT_MASTER, 0x20, - REDRIVER_RST_PIN, 0); + rv |= pca9534_set_level(I2C_PORT_MASTER, 0x20, REDRIVER_RST_PIN, 0); /* datasheet recommends > 400msec */ usleep(450 * MSEC); return rv; @@ -551,7 +548,7 @@ static int sn75dp130_redriver_init(void) return rv; } -static int cmd_usbc_action(int argc, char *argv[]) +static int cmd_usbc_action(int argc, const char *argv[]) { enum usbc_action act; @@ -596,12 +593,10 @@ int board_in_hub_mode(void) int ret; int level; - ret = pca9534_config_pin(I2C_PORT_MASTER, 0x20, - 6, PCA9534_INPUT); + ret = pca9534_config_pin(I2C_PORT_MASTER, 0x20, 6, PCA9534_INPUT); if (ret) return -1; - ret = pca9534_get_level(I2C_PORT_MASTER, 0x20, - 6, &level); + ret = pca9534_get_level(I2C_PORT_MASTER, 0x20, 6, &level); if (ret) return -1; return level; @@ -611,17 +606,14 @@ static int board_usb_hub_reset(void) { int ret; - ret = pca9534_config_pin(I2C_PORT_MASTER, 0x20, - 7, PCA9534_OUTPUT); + ret = pca9534_config_pin(I2C_PORT_MASTER, 0x20, 7, PCA9534_OUTPUT); if (ret) return ret; - ret = pca9534_set_level(I2C_PORT_MASTER, 0x20, - 7, 0); + ret = pca9534_set_level(I2C_PORT_MASTER, 0x20, 7, 0); if (ret) return ret; usleep(100 * MSEC); - return pca9534_set_level(I2C_PORT_MASTER, 0x20, - 7, 1); + return pca9534_set_level(I2C_PORT_MASTER, 0x20, 7, 1); } void board_maybe_reset_usb_hub(void) @@ -630,12 +622,11 @@ void board_maybe_reset_usb_hub(void) board_usb_hub_reset(); } -static int cmd_usb_hub_reset(int argc, char *argv[]) +static int cmd_usb_hub_reset(int argc, const char *argv[]) { return board_usb_hub_reset(); } -DECLARE_CONSOLE_COMMAND(hub_reset, cmd_usb_hub_reset, - NULL, "Reset USB hub"); +DECLARE_CONSOLE_COMMAND(hub_reset, cmd_usb_hub_reset, NULL, "Reset USB hub"); static void board_usb_hub_reset_no_return(void) { @@ -664,7 +655,7 @@ int board_fake_pd_adc_read(int cc) * on other CC line. */ if (active_cc == cc) return adc_read_channel(cc ? ADC_CH_CC2_PD : - ADC_CH_CC1_PD); + ADC_CH_CC1_PD); else return host_mode ? 3000 : 0; } @@ -750,7 +741,7 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -static int cmd_fake_disconnect(int argc, char *argv[]) +static int cmd_fake_disconnect(int argc, const char *argv[]) { int delay_ms, duration_ms; char *e; @@ -772,8 +763,8 @@ static int cmd_fake_disconnect(int argc, char *argv[]) fake_pd_disconnect_duration_us = duration_ms * MSEC; hook_call_deferred(&fake_disconnect_start_data, delay_ms * MSEC); - ccprintf("Fake disconnect for %d ms starting in %d ms.\n", - duration_ms, delay_ms); + ccprintf("Fake disconnect for %d ms starting in %d ms.\n", duration_ms, + delay_ms); return EC_SUCCESS; } @@ -787,7 +778,7 @@ static void trigger_dfu_release(void) } DECLARE_DEFERRED(trigger_dfu_release); -static int cmd_trigger_dfu(int argc, char *argv[]) +static int cmd_trigger_dfu(int argc, const char *argv[]) { gpio_set_level(GPIO_CASE_CLOSE_DFU_L, 0); ccprintf("Asserting CASE_CLOSE_DFU_L.\n"); diff --git a/board/plankton/board.h b/board/plankton/board.h index 5e2f5f28a0..a17bd30c3c 100644 --- a/board/plankton/board.h +++ b/board/plankton/board.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,6 @@ #define CONFIG_UART_CONSOLE 2 /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_TCPMV1 #define CONFIG_USB_PD_ALT_MODE @@ -34,7 +33,7 @@ #define CONFIG_ADC #define CONFIG_HW_CRC #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_INA219 #define CONFIG_IO_EXPANDER_PCA9534 #undef CONFIG_WATCHDOG_HELP @@ -58,7 +57,7 @@ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 +#define TIM_ADC 3 #include "gpio_signal.h" @@ -77,18 +76,18 @@ enum board_src_cap { }; /* 3.0A Rp */ -#define PD_SRC_VNC PD_SRC_3_0_VNC_MV -#define PD_SNK_RD_THRESHOLD PD_SRC_3_0_RD_THRESH_MV +#define PD_SRC_VNC PD_SRC_3_0_VNC_MV +#define PD_SNK_RD_THRESHOLD PD_SRC_3_0_RD_THRESH_MV /* delay necessary for the voltage transition on the power supply */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 5000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Set USB PD source capability */ void board_set_source_cap(enum board_src_cap cap); diff --git a/board/plankton/build.mk b/board/plankton/build.mk index 89a01e629b..0e597a478f 100644 --- a/board/plankton/build.mk +++ b/board/plankton/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,4 +11,4 @@ CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f07x board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_pdo.o diff --git a/board/plankton/ec.tasklist b/board/plankton/ec.tasklist index 41fc047d6a..5a82344122 100644 --- a/board/plankton/ec.tasklist +++ b/board/plankton/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/plankton/gpio.inc b/board/plankton/gpio.inc index 9c618dbaa6..edccec814c 100644 --- a/board/plankton/gpio.inc +++ b/board/plankton/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/plankton/usb_pd_config.h b/board/plankton/usb_pd_config.h index fca6484069..47614c3fce 100644 --- a/board/plankton/usb_pd_config.h +++ b/board/plankton/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -50,7 +50,7 @@ static inline void spi_enable_clock(int port) #define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 #define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 -#define TIM_CCR_CS 1 +#define TIM_CCR_CS 1 #define EXTI_COMP_MASK(p) BIT(21) #define IRQ_COMP STM32_IRQ_COMP /* triggers packet detection on comparator falling edge */ @@ -92,9 +92,8 @@ static inline void pd_tx_disable(int port, int polarity) { /* output low on SPI TX to disable the FET */ /* PA6 is SPI1_MISO */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - & ~(3 << (2*6))) - | (1 << (2*6)); + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) & ~(3 << (2 * 6))) | (1 << (2 * 6)); /* put the low level reference in Hi-Z */ gpio_set_level(GPIO_USBC_CC1_TX_EN, 0); gpio_set_level(GPIO_USBC_CC2_TX_EN, 0); @@ -104,11 +103,10 @@ static inline void pd_tx_disable(int port, int polarity) static inline void pd_select_polarity(int port, int polarity) { /* use the right comparator non inverted input for COMP1 */ - STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) - | STM32_COMP_CMP1EN - | (polarity ? - STM32_COMP_CMP1INSEL_INM4 : - STM32_COMP_CMP1INSEL_INM6); + STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) | + STM32_COMP_CMP1EN | + (polarity ? STM32_COMP_CMP1INSEL_INM4 : + STM32_COMP_CMP1INSEL_INM6); gpio_set_level(GPIO_USBC_POLARITY, polarity); } diff --git a/board/plankton/usb_pd_pdo.c b/board/plankton/usb_pd_pdo.c new file mode 100644 index 0000000000..52dcc11352 --- /dev/null +++ b/board/plankton/usb_pd_pdo.c @@ -0,0 +1,45 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +#define PDO_FIXED_FLAGS \ + (PDO_FIXED_DATA_SWAP | PDO_FIXED_UNCONSTRAINED | PDO_FIXED_COMM_CAP) + +/* Source PDOs */ +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), + PDO_FIXED(12000, 3000, PDO_FIXED_FLAGS), + PDO_FIXED(20000, 3000, PDO_FIXED_FLAGS), +}; + +/* Fake PDOs : we just want our pre-defined voltages */ +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_FIXED(12000, 500, PDO_FIXED_FLAGS), + PDO_FIXED(20000, 500, PDO_FIXED_FLAGS), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); + +static const int pd_src_pdo_cnts[] = { + [SRC_CAP_5V] = 1, + [SRC_CAP_12V] = 2, + [SRC_CAP_20V] = 3, +}; + +static int pd_src_pdo_idx; + +void board_set_source_cap(enum board_src_cap cap) +{ + pd_src_pdo_idx = cap; +} + +int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) +{ + *src_pdo = pd_src_pdo; + return pd_src_pdo_cnts[pd_src_pdo_idx]; +} diff --git a/board/plankton/usb_pd_pdo.h b/board/plankton/usb_pd_pdo.h new file mode 100644 index 0000000000..030dab9287 --- /dev/null +++ b/board/plankton/usb_pd_pdo.h @@ -0,0 +1,19 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_PLANKTON_USB_PD_PDO_H +#define __CROS_EC_BOARD_PLANKTON_USB_PD_PDO_H + +#include "stdint.h" + +extern const uint32_t pd_src_pdo[3]; + +extern const uint32_t pd_snk_pdo[3]; +extern const int pd_snk_pdo_cnt; + +void board_set_source_cap(enum board_src_cap cap); +int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port); + +#endif /* __CROS_EC_BOARD_PLANKTON_USB_PD_PDO_H */ diff --git a/board/plankton/usb_pd_policy.c b/board/plankton/usb_pd_policy.c index f6701ab65e..622489c744 100644 --- a/board/plankton/usb_pd_policy.c +++ b/board/plankton/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,60 +7,26 @@ #include "board.h" #include "common.h" #include "console.h" +#include "cros_version.h" #include "gpio.h" #include "hooks.h" #include "registers.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_pd.h" -#include "version.h" +#include "usb_pd_pdo.h" +#include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) /* Acceptable margin between requested VBUS and measured value */ #define MARGIN_MV 400 /* mV */ -#define PDO_FIXED_FLAGS (PDO_FIXED_DATA_SWAP | PDO_FIXED_UNCONSTRAINED |\ - PDO_FIXED_COMM_CAP) - -/* Source PDOs */ -const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), - PDO_FIXED(12000, 3000, PDO_FIXED_FLAGS), - PDO_FIXED(20000, 3000, PDO_FIXED_FLAGS), -}; -static const int pd_src_pdo_cnts[] = { - [SRC_CAP_5V] = 1, - [SRC_CAP_12V] = 2, - [SRC_CAP_20V] = 3, -}; - -static int pd_src_pdo_idx; - -/* Fake PDOs : we just want our pre-defined voltages */ -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), - PDO_FIXED(12000, 500, PDO_FIXED_FLAGS), - PDO_FIXED(20000, 500, PDO_FIXED_FLAGS), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); - /* Whether alternate mode has been entered or not */ static int alt_mode; -void board_set_source_cap(enum board_src_cap cap) -{ - pd_src_pdo_idx = cap; -} - -int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) -{ - *src_pdo = pd_src_pdo; - return pd_src_pdo_cnts[pd_src_pdo_idx]; -} - void pd_set_input_current_limit(int port, uint32_t max_ma, uint32_t supply_voltage) { @@ -110,22 +76,18 @@ __override int pd_check_power_swap(int port) return 1; } -__override int pd_check_data_swap(int port, - enum pd_data_role data_role) +__override int pd_check_data_swap(int port, enum pd_data_role data_role) { /* Always allow data swap */ return 1; } -__override void pd_check_pr_role(int port, - enum pd_power_role pr_role, +__override void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { } -__override void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +__override void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { /* If Plankton is in USB hub mode, always act as UFP */ if (board_in_hub_mode() && dr_role == PD_ROLE_DFP && @@ -143,8 +105,8 @@ const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, - CONFIG_USB_PD_IDENTITY_SW_VERS, - 0, 0, 0, 0, /* SS[TR][12] */ + CONFIG_USB_PD_IDENTITY_SW_VERS, 0, 0, 0, + 0, /* SS[TR][12] */ 0, /* Vconn power */ 0, /* Vconn power required */ 1, /* Vbus power required */ @@ -172,13 +134,13 @@ static int svdm_response_svids(int port, uint32_t *payload) #define MODE_CNT 1 #define OPOS 1 -const uint32_t vdo_dp_mode[MODE_CNT] = { - VDO_MODE_DP(0, /* UFP pin cfg supported : none */ +const uint32_t vdo_dp_mode[MODE_CNT] = { + VDO_MODE_DP(0, /* UFP pin cfg supported : none */ MODE_DP_PIN_E, /* DFP pin cfg supported */ - 1, /* no usb2.0 signalling in AMode */ - CABLE_PLUG, /* its a plug */ - MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ - MODE_DP_SNK) /* Its a sink only */ + 1, /* no usb2.0 signalling in AMode */ + CABLE_PLUG, /* its a plug */ + MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ + MODE_DP_SNK) /* Its a sink only */ }; static int svdm_response_modes(int port, uint32_t *payload) @@ -200,13 +162,13 @@ static int dp_status(int port, uint32_t *payload) if (opos != OPOS) return 0; /* nak */ - payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ - (hpd == 1), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - 0, /* MF pref */ + payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + (hpd == 1), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ !gpio_get_level(GPIO_USBC_SS_USB_MODE), - 0, /* power low */ + 0, /* power low */ 0x2); return 2; } @@ -236,7 +198,7 @@ int svdm_enter_mode(int port, uint32_t *payload) return 1; } -int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid) +int pd_alt_mode(int port, enum tcpci_msg_type type, uint16_t svid) { return alt_mode; } diff --git a/board/plankton/vif_override.xml b/board/plankton/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/plankton/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/polyberry/board.c b/board/polyberry/board.c index 5bb811f82c..52d27e5a37 100644 --- a/board/polyberry/board.c +++ b/board/polyberry/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,29 +8,31 @@ #include "dma.h" #include "ec_version.h" #include "gpio.h" -#include "gpio_list.h" #include "hooks.h" #include "registers.h" #include "stm32-dma.h" #include "task.h" #include "update_fw.h" #include "usb_descriptor.h" -#include "util.h" #include "usb_dwc_console.h" #include "usb_dwc_update.h" #include "usb_hw.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("Polyberry"), - [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Polyberry EC Shell"), - [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Polyberry"), + [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Polyberry EC Shell"), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); @@ -47,15 +49,15 @@ struct dwc_usb usb_ctl = { .irq = STM32_IRQ_OTG_HS, }; -#define GPIO_SET_HS(bank, number) \ - (STM32_GPIO_OSPEEDR(GPIO_##bank) |= (0x3 << ((number) * 2))) +#define GPIO_SET_HS(bank, number) \ + (STM32_GPIO_OSPEEDR(GPIO_##bank) |= (0x3 << ((number)*2))) void board_config_post_gpio_init(void) { /* We use MCO2 clock passthrough to provide a clock to USB HS */ gpio_config_module(MODULE_MCO, 1); /* GPIO PC9 to high speed */ - GPIO_SET_HS(C, 9); + GPIO_SET_HS(C, 9); if (usb_ctl.phy_type == USB_PHY_ULPI) gpio_set_level(GPIO_USB_MUX_SEL, 0); @@ -66,19 +68,19 @@ void board_config_post_gpio_init(void) GPIO_SET_HS(A, 11); GPIO_SET_HS(A, 12); - GPIO_SET_HS(C, 3); - GPIO_SET_HS(C, 2); - GPIO_SET_HS(C, 0); - GPIO_SET_HS(A, 5); + GPIO_SET_HS(C, 3); + GPIO_SET_HS(C, 2); + GPIO_SET_HS(C, 0); + GPIO_SET_HS(A, 5); - GPIO_SET_HS(B, 5); + GPIO_SET_HS(B, 5); GPIO_SET_HS(B, 13); GPIO_SET_HS(B, 12); - GPIO_SET_HS(B, 2); + GPIO_SET_HS(B, 2); GPIO_SET_HS(B, 10); - GPIO_SET_HS(B, 1); - GPIO_SET_HS(B, 0); - GPIO_SET_HS(A, 3); + GPIO_SET_HS(B, 1); + GPIO_SET_HS(B, 0); + GPIO_SET_HS(A, 3); } static void board_init(void) diff --git a/board/polyberry/board.h b/board/polyberry/board.h index 8e55967bf5..1390bb996c 100644 --- a/board/polyberry/board.h +++ b/board/polyberry/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -44,15 +44,15 @@ #define DEFAULT_SERIALNO "Uninitialized" /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_CONSOLE 0 -#define USB_IFACE_UPDATE 1 -#define USB_IFACE_COUNT 2 +#define USB_IFACE_CONSOLE 0 +#define USB_IFACE_UPDATE 1 +#define USB_IFACE_COUNT 2 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_CONSOLE 1 -#define USB_EP_UPDATE 2 -#define USB_EP_COUNT 3 +#define USB_EP_CONTROL 0 +#define USB_EP_CONSOLE 1 +#define USB_EP_UPDATE 2 +#define USB_EP_COUNT 3 /* This is not actually a Chromium EC so disable some features. */ #undef CONFIG_WATCHDOG_HELP @@ -60,7 +60,6 @@ #undef CONFIG_WATCHDOG /* Optional features */ -#define CONFIG_STM_HWTIMER32 /* * Allow dangerous commands all the time, since we don't have a write protect diff --git a/board/polyberry/build.mk b/board/polyberry/build.mk index 6b06f2bb8f..61e4b79d47 100644 --- a/board/polyberry/build.mk +++ b/board/polyberry/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/polyberry/ec.tasklist b/board/polyberry/ec.tasklist index c1fb169118..c45a1e89a7 100644 --- a/board/polyberry/ec.tasklist +++ b/board/polyberry/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/polyberry/gpio.inc b/board/polyberry/gpio.inc index 536dccc5ff..d862155c4d 100644 --- a/board/polyberry/gpio.inc +++ b/board/polyberry/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/pompom/battery.c b/board/pompom/battery.c index 7ce8eec202..2566813651 100644 --- a/board/pompom/battery.c +++ b/board/pompom/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/pompom/board.c b/board/pompom/board.c index 041993b01b..9f0b9e484a 100644 --- a/board/pompom/board.c +++ b/board/pompom/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,37 +9,42 @@ #include "button.h" #include "charge_manager.h" #include "charge_state.h" -#include "extpower.h" #include "driver/accel_bma2x2.h" +#include "driver/accel_lis2dw12.h" #include "driver/accelgyro_bmi_common.h" #include "driver/ppc/sn5s330.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "keyboard_scan.h" #include "lid_switch.h" #include "pi3usb9201.h" #include "power.h" +#include "power/qcom.h" #include "power_button.h" #include "pwm.h" #include "pwm_chip.h" -#include "system.h" #include "shi_chip.h" #include "switch.h" +#include "system.h" #include "tablet_mode.h" #include "task.h" +#include "usbc_ocp.h" #include "usbc_ppc.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* Forward declaration */ static void tcpc_alert_event(enum gpio_signal signal); static void usb0_evt(enum gpio_signal signal); +static void usba_oc_interrupt(enum gpio_signal signal); static void ppc_interrupt(enum gpio_signal signal); static void board_connect_c0_sbu(enum gpio_signal s); +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* GPIO Interrupt Handlers */ @@ -60,7 +65,20 @@ static void tcpc_alert_event(enum gpio_signal signal) static void usb0_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void usba_oc_deferred(void) +{ + /* Use next number after all USB-C ports to indicate the USB-A port */ + board_overcurrent_event(CONFIG_USB_PD_PORT_MAX_COUNT, + !gpio_get_level(GPIO_USB_A0_OC_ODL)); +} +DECLARE_DEFERRED(usba_oc_deferred); + +static void usba_oc_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&usba_oc_deferred_data, 0); } static void ppc_interrupt(enum gpio_signal signal) @@ -90,7 +108,7 @@ static void board_connect_c0_sbu(enum gpio_signal s) } /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Use 80 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* @@ -98,10 +116,8 @@ struct keyboard_scan_config keyscan_config = { * as it uses the new location (KSO_00/KSI_03). And T11 key, which maps * to KSO_01/KSI_00, is not there. */ - .actual_key_mask = { - 0x1c, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca - }, + .actual_key_mask = { 0x1c, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xa4, + 0xff, 0xfe, 0x55, 0xfa, 0xca }, /* Other values should be the same as the default configuration. */ .debounce_down_us = 9 * MSEC, .debounce_up_us = 30 * MSEC, @@ -112,14 +128,26 @@ struct keyboard_scan_config keyscan_config = { /* I2C port map */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_EC_I2C_POWER_SCL, - GPIO_EC_I2C_POWER_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 1000, GPIO_EC_I2C_USB_C0_PD_SCL, - GPIO_EC_I2C_USB_C0_PD_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_EC_I2C_EEPROM_SCL, - GPIO_EC_I2C_EEPROM_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_EC_I2C_SENSOR_SCL, - GPIO_EC_I2C_SENSOR_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -127,54 +155,37 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /* ADC channels */ const struct adc_t adc_channels[] = { /* Measure VBUS through a 1/10 voltage divider */ - [ADC_VBUS] = { - "VBUS", - NPCX_ADC_CH1, - ADC_MAX_VOLT * 10, - ADC_READ_MAX + 1, - 0 - }, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* * Adapter current output or battery charging/discharging current (uV) * 18x amplification on charger side. */ - [ADC_AMON_BMON] = { - "AMON_BMON", - NPCX_ADC_CH2, - ADC_MAX_VOLT * 1000 / 18, - ADC_READ_MAX + 1, - 0 - }, + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, /* * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we * only divide by 2 (enough to avoid precision issues). */ - [ADC_PSYS] = { - "PSYS", - NPCX_ADC_CH3, - ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), - 2, - 0 - }, + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, /* TODO(waihong): Assign a proper frequency. */ - [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 4800 }, + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 20000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); /* Power Path Controller */ struct ppc_config_t ppc_chips[] = { - { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, }; unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); @@ -184,7 +195,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -197,11 +208,14 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, * the mux misbehaves. */ -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, }; @@ -224,9 +238,21 @@ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { /* Initialize board. */ static void board_init(void) { + /* + * The rev-2 hardware doesn't have the external pull-up fix for the bug + * b/164256614. It requires rework to stuff the resistor. For people who + * has difficulty to do the rework, this is a workaround, which makes + * the GPIO push-pull, instead of open-drain. + */ + if (system_get_board_version() == 2) + gpio_set_flags(GPIO_HIBERNATE_L, GPIO_OUTPUT); + /* Enable BC1.2 interrupts */ gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + /* Enable USB-A overcurrent interrupt */ + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); + /* Enable interrupt for BMI160 sensor */ gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); @@ -242,13 +268,39 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +void board_hibernate(void) +{ + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_LID_ACCEL_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + + /* + * Board rev 2+ has the hardware fix. Don't need the following + * workaround. + */ + if (system_get_board_version() >= 2) + return; + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + ppc_vbus_sink_enable(USB_PD_PORT_C0, 1); +} + __override uint16_t board_get_ps8xxx_product_id(int port) { - /* Pompom rev 1+ changes TCPC from PS8751 to PS8805 */ + /* Pompom rev 2+ changes TCPC from PS8805 to PS8755 */ if (system_get_board_version() == 0) return PS8751_PRODUCT_ID; + else if (system_get_board_version() == 1) + return PS8805_PRODUCT_ID; - return PS8805_PRODUCT_ID; + return PS8755_PRODUCT_ID; } void board_tcpc_init(void) @@ -269,10 +321,11 @@ void board_tcpc_init(void) * Initialize HPD to low; after sysjump SOC needs to see * HPD pulse to enable video path */ - for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(USB_PD_PORT_C0, + USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); /* Called on AP S0 -> S3 transition */ static void board_chipset_suspend(void) @@ -350,25 +403,20 @@ void board_overcurrent_event(int port, int is_overcurrented) int board_set_active_charge_port(int port) { - int is_real_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); - int i; + int is_real_port = (port == USB_PD_PORT_C0); if (!is_real_port && port != CHARGE_PORT_NONE) return EC_ERROR_INVAL; if (port == CHARGE_PORT_NONE) { CPRINTS("Disabling all charging port"); - - /* Disable all ports. */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - /* - * Do not return early if one fails otherwise we can - * get into a boot loop assertion failure. - */ - if (board_vbus_sink_enable(i, 0)) - CPRINTS("Disabling p%d sink path failed.", i); - } + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(USB_PD_PORT_C0, 0)) + CPRINTS("Disabling p%d sink path failed.", + USB_PD_PORT_C0); return EC_SUCCESS; } @@ -379,21 +427,8 @@ int board_set_active_charge_port(int port) return EC_ERROR_INVAL; } - CPRINTS("New charge port: p%d", port); - /* - * Turn off the other ports' sink path FETs, before enabling the - * requested charge port. - */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - if (i == port) - continue; - - if (board_vbus_sink_enable(i, 0)) - CPRINTS("p%d: sink path disable failed.", i); - } - /* Enable requested charge port. */ if (board_vbus_sink_enable(port, 1)) { CPRINTS("p%d: sink path enable failed.", port); @@ -403,23 +438,20 @@ int board_set_active_charge_port(int port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* * Ignore lower charge ceiling on PD transition if our battery is * critical, as we may brownout. */ - if (supplier == CHARGE_SUPPLIER_PD && - charge_ma < 1500 && + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { CPRINTS("Using max ilim %d", max_ma); charge_ma = max_ma; } - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } uint16_t tcpc_get_alert_status(void) @@ -439,19 +471,16 @@ static struct mutex g_lid_mutex; static struct bmi_drv_data_t g_bmi160_data; static struct accelgyro_saved_data_t g_bma255_data; +static struct stprivate_data g_lis2dwl_data; /* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -487,7 +516,7 @@ struct motion_sensor_t motion_sensors[] = { */ [BASE_ACCEL] = { .name = "Base Accel", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .active_mask = SENSOR_ACTIVE_S0_S3, .chip = MOTIONSENSE_CHIP_BMI160, .type = MOTIONSENSE_TYPE_ACCEL, .location = MOTIONSENSE_LOC_BASE, @@ -512,7 +541,7 @@ struct motion_sensor_t motion_sensors[] = { }, [BASE_GYRO] = { .name = "Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .active_mask = SENSOR_ACTIVE_S0_S3, .chip = MOTIONSENSE_CHIP_BMI160, .type = MOTIONSENSE_TYPE_GYRO, .location = MOTIONSENSE_LOC_BASE, @@ -529,22 +558,53 @@ struct motion_sensor_t motion_sensors[] = { }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#ifndef TEST_BUILD -/* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +struct motion_sensor_t lis2dwl_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DWL, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2dwl_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = LIS2DWL_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +static void board_detect_motionsensor(void) { - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + int val = 0; - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + /* + * BMA253 and LIS2DWL have same target address, so we check the + * LIS2DWL WHO AM I register to check the lid accel type + */ + i2c_read8(I2C_PORT_SENSOR, LIS2DWL_ADDR0_FLAGS, LIS2DW12_WHO_AM_I_REG, + &val); + + if (val == LIS2DW12_WHO_AM_I) { + motion_sensors[LID_ACCEL] = lis2dwl_lid_accel; + CPRINTS("Lid Accel: LIS2DWL"); } } -#endif + +static void board_update_sensor_config_from_sku(void) +{ + board_detect_motionsensor(); +} +DECLARE_HOOK(HOOK_INIT, board_update_sensor_config_from_sku, + HOOK_PRIO_INIT_I2C + 2); diff --git a/board/pompom/board.h b/board/pompom/board.h index 11d48a5d40..de7fd92a75 100644 --- a/board/pompom/board.h +++ b/board/pompom/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,31 +11,29 @@ #include "baseboard.h" #include "board_revs.h" -/* TODO(waihong): Remove the following bringup features */ -#define CONFIG_BRINGUP -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands. */ -#define CONFIG_USB_PD_DEBUG_LEVEL 3 -#define CONFIG_CMD_AP_RESET_LOG -#define CONFIG_CMD_GPIO_EXTENDED -#define CONFIG_CMD_POWERINDEBUG -#define CONFIG_I2C_DEBUG - /* Internal SPI flash on NPCX7 */ -#define CONFIG_FLASH_SIZE (512 * 1024) /* 512KB internal spi flash */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ /* Keyboard */ -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_KEYBOARD_PROTOCOL_MKBP + +#define CONFIG_KEYBOARD_REFRESH_ROW3 #define CONFIG_PWM_KBLIGHT /* BC 1.2 Charger */ #define CONFIG_BC12_DETECT_PI3USB9201 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + /* USB */ #define CONFIG_USB_PD_TCPM_MULTI_PS8XXX #define CONFIG_USB_PD_TCPM_PS8751 +#define CONFIG_USB_PD_TCPM_PS8755 #define CONFIG_USB_PD_TCPM_PS8805 #define CONFIG_USBC_PPC_SN5S330 #define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define USB_PD_PORT_C0 0 /* USB-A */ #define USB_PORT_COUNT 1 @@ -44,13 +42,13 @@ /* Sensors */ /* BMI160 Base accel/gyro */ #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS /* BMA253 lid accel */ #define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCEL_LIS2DWL #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) #define CONFIG_LID_ANGLE @@ -61,7 +59,7 @@ #define CONFIG_TABLET_MODE #define CONFIG_TABLET_MODE_SWITCH #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_LID_360_L +#define GPIO_TABLET_MODE_L GPIO_LID_360_L /* GPIO alias */ #define GPIO_AC_PRESENT GPIO_ACOK_OD @@ -78,12 +76,7 @@ #include "gpio_signal.h" #include "registers.h" -enum adc_channel { - ADC_VBUS, - ADC_AMON_BMON, - ADC_PSYS, - ADC_CH_COUNT -}; +enum adc_channel { ADC_VBUS, ADC_AMON_BMON, ADC_PSYS, ADC_CH_COUNT }; /* Motion sensors */ enum sensor_id { @@ -93,25 +86,13 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_DISPLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_DISPLIGHT, PWM_CH_COUNT }; enum battery_type { BATTERY_BYD, BATTERY_TYPE_COUNT, }; -/* Swithcap functions */ -void board_set_switchcap_power(int enable); -int board_is_switchcap_enabled(void); -int board_is_switchcap_power_good(void); -/* Custom function to indicate if sourcing VBUS */ -int board_is_sourcing_vbus(int port); -/* Enable VBUS sink for a given port */ -int board_vbus_sink_enable(int port, int enable); /* Reset all TCPCs. */ void board_reset_pd_mcu(void); void board_set_tcpc_power_mode(int port, int mode); diff --git a/board/pompom/board_revs.h b/board/pompom/board_revs.h index 1ac5ee1337..8edc249df0 100644 --- a/board/pompom/board_revs.h +++ b/board/pompom/board_revs.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,7 +8,7 @@ #define POMPOM_REV0 0 #define POMPOM_REV1 1 -#define POMPOM_REV_LAST POMPOM_REV1 +#define POMPOM_REV_LAST POMPOM_REV1 #define POMPOM_REV_DEFAULT POMPOM_REV1 #if !defined(BOARD_REV) @@ -19,5 +19,4 @@ #error "Board revision out of range" #endif - #endif /* __CROS_EC_BOARD_REVS_H */ diff --git a/board/pompom/build.mk b/board/pompom/build.mk index a044fa58cb..8d302988f4 100644 --- a/board/pompom/build.mk +++ b/board/pompom/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,4 +11,4 @@ CHIP_FAMILY:=npcx7 CHIP_VARIANT:=npcx7m6fc BASEBOARD:=trogdor -board-y=battery.o board.o led.o +board-y=battery.o board.o led.o usbc_config.o diff --git a/board/pompom/ec.tasklist b/board/pompom/ec.tasklist index 7ec8b46059..9145e6dd84 100644 --- a/board/pompom/ec.tasklist +++ b/board/pompom/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/pompom/gpio.inc b/board/pompom/gpio.inc index 70d210b670..3016f8b9d5 100644 --- a/board/pompom/gpio.inc +++ b/board/pompom/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,23 +8,23 @@ /* Declare symbolic names for all the GPIOs that we care about. * Note: Those with interrupt handlers must be declared first. */ -/* USB-C interrupts */ +/* USB interrupts */ GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ -GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_A0_OC_ODL, PIN(D, 1), GPIO_INT_BOTH | GPIO_PULL_UP, usba_oc_interrupt) /* System interrupts */ -GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) /* AC OK? */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ -GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) /* Lid open? */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ -GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ -GPIO_INT(PMIC_FAULT_L, PIN(A, 3), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) /* Any PMIC fault? */ -GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ /* * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down @@ -38,32 +38,25 @@ GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs /* Sensor interrupts */ GPIO_INT(LID_360_L, PIN(7, 2), GPIO_INT_BOTH, gmr_tablet_switch_isr) -GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) /* Accelerometer/gyro interrupt */ +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, bmi160_interrupt) /* Accelerometer/gyro interrupt */ /* - * EC_RST_ODL acts as a wake source from PSL hibernate mode. However, it does - * not need to be an interrupt for normal EC operations. Thus, configure it as - * GPIO_INT_BOTH with wake on low-to-high edge using GPIO_HIB_WAKE_HIGH so that - * PSL common code can configure PSL_IN correctly. - * - * Use the rising edge to wake EC up. If we chose the falling edge, it would - * still wake EC up, but EC is in an intermediate state until the signal goes - * back to high. + * EC_RST_ODL acts as a wake source from hibernate mode. However, it does not + * need to be an interrupt for normal EC operations. Simply set it an INPUT. */ -GPIO(EC_RST_ODL_GPIO02, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* Wake source: EC reset */ +GPIO(EC_RST_ODL_GPIO02, PIN(0, 2), GPIO_INPUT) /* EC reset */ GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ /* PMIC/AP 1.8V */ -GPIO(PM7180_RESIN_D_L, PIN(3, 2), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC reset trigger */ -GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC power button */ +GPIO(PM7180_RESIN_D_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ GPIO(QSIP_ON, PIN(5, 0), GPIO_OUT_LOW) /* Not used, for non-switchcap testing */ /* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ GPIO(SWITCHCAP_ON, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap */ -/* TODO(waihong): Remove it. The VBOB switch is for backup. */ -GPIO(VBOB_EN, PIN(D, 3), GPIO_OUT_LOW) /* Enable VBOB */ GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ @@ -76,24 +69,28 @@ GPIO(TRACKPAD_INT_GATE, PIN(7, 4), GPIO_OUT_LOW) /* USB-C */ GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_OUT_HIGH) /* Port-0 TCPC chip reset */ -GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_OUT_HIGH) /* DP mux enable */ -GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_HIGH) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ -/* TODO(waihong): Remove it from schematic. No use. */ -GPIO(USBC_MUX_CONF0, PIN(5, 1), GPIO_INPUT) -GPIO(USB_C0_VBUS_DET_L, PIN(6, 2), GPIO_INPUT) /* Deprecated BC1.2 VBUS detection on port-0 */ - /* USB-A */ GPIO(EN_USB_A_5V, PIN(8, 6), GPIO_OUT_LOW) GPIO(USB_A_CDP_ILIM_EN, PIN(7, 5), GPIO_OUT_HIGH) /* H: CDP, L:SDP. Only one USB-A port, always CDP */ -GPIO(USB_A0_OC_ODL, PIN(D, 1), GPIO_ODR_HIGH) /* LEDs */ GPIO(EC_CHG_LED_Y_C0, PIN(C, 3), GPIO_OUT_LOW) GPIO(EC_CHG_LED_W_C0, PIN(C, 4), GPIO_OUT_LOW) GPIO(EC_PWR_LED_W, PIN(6, 0), GPIO_OUT_LOW) +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + /* PWM */ GPIO(KB_BL_PWM, PIN(8, 0), GPIO_INPUT) /* PWM3 */ GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ @@ -128,6 +125,37 @@ GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) */ GPIO(DA9313_GPIO0, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(0, 4)) +UNUSED(PIN(C, 0)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(3, 7)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(C, 6)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(7, 3)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(6, 2)) +UNUSED(PIN(E, 4)) +UNUSED(PIN(F, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(D, 3)) + /* Alternate functions GPIO definitions */ ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ @@ -140,10 +168,6 @@ ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* PWM3 (GPIO80) - KB_BL_PWM */ ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ -ALTERNATE(PIN_MASK(D, 0x04), 1, MODULE_PMU, 0) /* PSL_IN1 (GPIOD2) - LID_OPEN_EC */ -ALTERNATE(PIN_MASK(0, 0x01), 1, MODULE_PMU, 0) /* PSL_IN2 (GPIO00) - ACOK_OD */ -ALTERNATE(PIN_MASK(0, 0x02), 1, MODULE_PMU, 0) /* PSL_IN3 (GPIO01) - EC_PWR_BTN_ODL */ -ALTERNATE(PIN_MASK(0, 0x04), 1, MODULE_PMU, 0) /* PSL_IN4 (GPIO02) - EC_RST_ODL */ /* Keyboard */ #define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/pompom/led.c b/board/pompom/led.c index db571a067c..fffd367cc5 100644 --- a/board/pompom/led.c +++ b/board/pompom/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -31,21 +31,21 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static void led_set_color_battery(enum led_color color) { gpio_set_level(GPIO_EC_CHG_LED_Y_C0, - (color == LED_AMBER) ? LED_ON_LVL : LED_OFF_LVL); + (color == LED_AMBER) ? LED_ON_LVL : LED_OFF_LVL); gpio_set_level(GPIO_EC_CHG_LED_W_C0, - (color == LED_WHITE) ? LED_ON_LVL : LED_OFF_LVL); + (color == LED_WHITE) ? LED_ON_LVL : LED_OFF_LVL); } void led_set_color_power(enum led_color color) { gpio_set_level(GPIO_EC_PWR_LED_W, - (color == LED_WHITE) ? LED_ON_LVL : LED_OFF_LVL); + (color == LED_WHITE) ? LED_ON_LVL : LED_OFF_LVL); } void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) @@ -82,20 +82,19 @@ static void board_led_set_battery(void) static int battery_ticks; int color = LED_OFF; int period = 0; - uint32_t chflags = charge_get_flags(); battery_ticks++; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate amber on when charging. */ color = LED_AMBER; break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: /* Discharging : off */ color = LED_OFF; break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: /* Battery error: Amber 1 sec, off 1 sec */ period = (1 + 1); battery_ticks = battery_ticks % period; @@ -104,21 +103,21 @@ static void board_led_set_battery(void) else color = LED_OFF; break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: /* Full Charged: White on */ color = LED_WHITE; break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) { - /* Factory mode: White 2 sec, Amber 2 sec */ - period = (2 + 2); - battery_ticks = battery_ticks % period; - if (battery_ticks < 2) - color = LED_WHITE; - else - color = LED_AMBER; - } else + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_WHITE; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode: White 2 sec, Amber 2 sec */ + period = (2 + 2); + battery_ticks = battery_ticks % period; + if (battery_ticks < 2) color = LED_WHITE; + else + color = LED_AMBER; break; default: /* Other states don't alter LED behavior */ diff --git a/board/pompom/usbc_config.c b/board/pompom/usbc_config.c new file mode 100644 index 0000000000..28f6b7a1c9 --- /dev/null +++ b/board/pompom/usbc_config.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor family-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "console.h" +#include "usb_pd.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/pompom/vif_override.xml b/board/pompom/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/pompom/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/poppy/base_detect_lux.c b/board/poppy/base_detect_lux.c index 155243af0e..8b799a3dbd 100644 --- a/board/poppy/base_detect_lux.c +++ b/board/poppy/base_detect_lux.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Lux base detection code */ #include "adc.h" -#include "adc_chip.h" #include "board.h" #include "chipset.h" #include "common.h" @@ -21,8 +20,8 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) /* Base detection and debouncing */ #define BASE_DETECT_DEBOUNCE_US (20 * MSEC) @@ -45,7 +44,7 @@ #define BASE_DISCONNECTED_CONNECT_MAX_MV 600 #define BASE_DISCONNECTED_MIN_MV 2800 -#define BASE_DISCONNECTED_MAX_MV (ADC_MAX_VOLT+1) +#define BASE_DISCONNECTED_MAX_MV (ADC_MAX_VOLT + 1) /* * When base is connected, then gets disconnected: @@ -94,7 +93,7 @@ int board_is_base_connected(void) void board_enable_base_power(int enable) { gpio_set_level(GPIO_PPVAR_VAR_BASE, - enable && current_base_status == BASE_CONNECTED); + enable && current_base_status == BASE_CONNECTED); } /* @@ -128,7 +127,7 @@ static void base_detect_change(enum base_status status) */ task_wake(TASK_ID_CHARGER); - tablet_set_mode(!connected); + tablet_set_mode(!connected, TABLET_TRIGGER_BASE); } static void print_base_detect_value(const char *str, int v) @@ -182,8 +181,7 @@ static void base_detect_deferred(void) retry: print_base_detect_value("status unclear", v); /* Unclear base status, schedule again in a while. */ - hook_call_deferred(&base_detect_deferred_data, - BASE_DETECT_RETRY_US); + hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_RETRY_US); } void base_detect_interrupt(enum gpio_signal signal) @@ -217,21 +215,21 @@ static void base_init(void) hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_DEBOUNCE_US); gpio_enable_interrupt(GPIO_BASE_DET_A); } -DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT+1); +DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT + 1); -void base_force_state(int state) +void base_force_state(enum ec_set_base_state_cmd state) { - if (state == 1) { + if (state == EC_SET_BASE_STATE_ATTACH) { gpio_disable_interrupt(GPIO_BASE_DET_A); base_detect_change(BASE_CONNECTED); CPRINTS("BD forced connected"); - } else if (state == 0) { + } else if (state == EC_SET_BASE_STATE_DETACH) { gpio_disable_interrupt(GPIO_BASE_DET_A); base_detect_change(BASE_DISCONNECTED); CPRINTS("BD forced disconnected"); } else { hook_call_deferred(&base_detect_deferred_data, - BASE_DETECT_DEBOUNCE_US); + BASE_DETECT_DEBOUNCE_US); gpio_enable_interrupt(GPIO_BASE_DET_A); CPRINTS("BD forced reset"); } diff --git a/board/poppy/base_detect_poppy.c b/board/poppy/base_detect_poppy.c index 358461896e..e6ac6e8da7 100644 --- a/board/poppy/base_detect_poppy.c +++ b/board/poppy/base_detect_poppy.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,7 +7,6 @@ #include "acpi.h" #include "adc.h" -#include "adc_chip.h" #include "board.h" #include "chipset.h" #include "common.h" @@ -20,8 +19,8 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) /* Base detection and debouncing */ #define BASE_DETECT_DEBOUNCE_US (20 * MSEC) @@ -95,14 +94,13 @@ static void base_detect_change(enum base_status status) CPRINTS("Base %sconnected", connected ? "" : "not "); gpio_set_level(GPIO_PP3300_DX_BASE, connected); - tablet_set_mode(!connected); + tablet_set_mode(!connected, TABLET_TRIGGER_BASE); current_base_status = status; if (connected) acpi_dptf_set_profile_num(DPTF_PROFILE_BASE_ATTACHED); else acpi_dptf_set_profile_num(DPTF_PROFILE_BASE_DETACHED); - } /* Measure detection pin pulse duration (used to wake AP from deep S3). */ @@ -111,8 +109,8 @@ static uint32_t pulse_width; static void print_base_detect_value(int v, int tmp_pulse_width) { - CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name, - v, tmp_pulse_width); + CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name, v, + tmp_pulse_width); } static void base_detect_deferred(void) @@ -244,15 +242,15 @@ static void base_init(void) if (system_jumped_late() && chipset_in_state(CHIPSET_STATE_ON)) base_enable(); } -DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT+1); +DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT + 1); -void base_force_state(int state) +void base_force_state(enum ec_set_base_state_cmd state) { - if (state == 1) { + if (state == EC_SET_BASE_STATE_ATTACH) { gpio_disable_interrupt(GPIO_BASE_DET_A); base_detect_change(BASE_CONNECTED); CPRINTS("BD forced connected"); - } else if (state == 0) { + } else if (state == EC_SET_BASE_STATE_DETACH) { gpio_disable_interrupt(GPIO_BASE_DET_A); base_detect_change(BASE_DISCONNECTED); CPRINTS("BD forced disconnected"); diff --git a/board/poppy/battery.c b/board/poppy/battery.c index 3f6c4e273d..5006edf123 100644 --- a/board/poppy/battery.c +++ b/board/poppy/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -14,14 +14,14 @@ #include "gpio.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) static enum battery_present batt_pres_prev = BP_NOT_SURE; /* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS -#define SB_SHUTDOWN_DATA 0x0010 -#define SB_REVIVE_DATA 0x23a7 +#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS +#define SB_SHUTDOWN_DATA 0x0010 +#define SB_REVIVE_DATA 0x23a7 #if defined(BOARD_SORAKA) || defined(BOARD_LUX) static const struct battery_info info = { @@ -86,8 +86,9 @@ static int battery_init(void) { int batt_status; - return battery_status(&batt_status) ? 0 : - !!(batt_status & STATUS_INITIALIZED); + return battery_status(&batt_status) ? + 0 : + !!(batt_status & STATUS_INITIALIZED); } /* @@ -108,13 +109,13 @@ static int battery_check_disconnect(void) uint8_t data[6]; /* Check if battery charging + discharging is disabled. */ - rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); + rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, SB_ALT_MANUFACTURER_ACCESS, + data, sizeof(data)); if (rv) return BATTERY_DISCONNECT_ERROR; - if ((data[3] & (BATTERY_DISCHARGING_DISABLED | - BATTERY_CHARGING_DISABLED)) == + if ((data[3] & + (BATTERY_DISCHARGING_DISABLED | BATTERY_CHARGING_DISABLED)) == (BATTERY_DISCHARGING_DISABLED | BATTERY_CHARGING_DISABLED)) return BATTERY_DISCONNECTED; @@ -223,4 +224,3 @@ enum battery_present battery_is_present(void) batt_pres_prev = battery_check_present_status(); return batt_pres_prev; } - diff --git a/board/poppy/board.c b/board/poppy/board.c index e01446b316..a757515aa4 100644 --- a/board/poppy/board.c +++ b/board/poppy/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,14 +6,13 @@ /* Poppy board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "als.h" #include "bd99992gw.h" #include "board_config.h" #include "button.h" #include "charge_manager.h" -#include "charge_state.h" #include "charge_ramp.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" #include "console.h" @@ -26,6 +25,7 @@ #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" #include "driver/temp_sensor/bd99992gw.h" +#include "espi.h" #include "extpower.h" #include "gpio.h" #include "hooks.h" @@ -35,6 +35,7 @@ #include "math_util.h" #include "motion_lid.h" #include "motion_sense.h" +#include "panic.h" #include "pi3usb9281.h" #include "power.h" #include "power_button.h" @@ -51,15 +52,11 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" -#include "espi.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define USB_PD_PORT_ANX74XX 0 - -/* Minimum input current limit. */ -#define ILIM_MIN_MA 472 +#define USB_PD_PORT_ANX74XX 0 static void tcpc_alert_event(enum gpio_signal signal) { @@ -81,9 +78,9 @@ static void vbus_discharge_handler(void) { if (system_get_board_version() >= 2) { pd_set_vbus_discharge(0, - gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L)); + gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L)); pd_set_vbus_discharge(1, - gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L)); + gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L)); } } DECLARE_DEFERRED(vbus_discharge_handler); @@ -108,12 +105,12 @@ void vbus1_evt(enum gpio_signal signal) void usb0_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } void usb1_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); } #ifdef CONFIG_USB_PD_TCPC_LOW_POWER @@ -132,7 +129,7 @@ static void anx74xx_cable_det_handler(void) * and if in normal mode, then there is no need to trigger a tcpc reset. */ if (cable_det && !reset_n) - task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); + task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET); } DECLARE_DEFERRED(anx74xx_cable_det_handler); @@ -143,6 +140,7 @@ void anx74xx_cable_det_interrupt(enum gpio_signal signal) } #endif +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Hibernate wake configuration */ @@ -155,16 +153,17 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* ADC channels */ const struct adc_t adc_channels[] = { /* Base detection */ - [ADC_BASE_DET] = {"BASE_DET", NPCX_ADC_CH0, - ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_BASE_DET] = { "BASE_DET", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, /* Vbus sensing (10x voltage divider). */ - [ADC_VBUS] = {"VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* * Adapter current output or battery charging/discharging current (uV) * 18x amplification on charger side. */ - [ADC_AMON_BMON] = {"AMON_BMON", NPCX_ADC_CH1, ADC_MAX_VOLT*1000/18, - ADC_READ_MAX+1, 0}, + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH1, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, #ifdef BOARD_LUX /* * ISL9238 PSYS output is 1.44 uA/W over 12.4K resistor, to read @@ -172,19 +171,39 @@ const struct adc_t adc_channels[] = { * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we * only divide by 2 (enough to avoid precision issues). */ - [ADC_PSYS] = {"PSYS", NPCX_ADC_CH3, - ADC_MAX_VOLT*56250*2/(ADC_READ_MAX+1), 2, 0}, + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 56250 * 2 / (ADC_READ_MAX + 1), 2, 0 }, #endif }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* I2C port map */ -const struct i2c_port_t i2c_ports[] = { - {"tcpc", NPCX_I2C_PORT0_0, 400, GPIO_I2C0_0_SCL, GPIO_I2C0_0_SDA}, - {"als", NPCX_I2C_PORT0_1, 400, GPIO_I2C0_1_SCL, GPIO_I2C0_1_SDA}, - {"charger", NPCX_I2C_PORT1, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"pmic", NPCX_I2C_PORT2, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"accelgyro", NPCX_I2C_PORT3, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "tcpc", + .port = NPCX_I2C_PORT0_0, + .kbps = 400, + .scl = GPIO_I2C0_0_SCL, + .sda = GPIO_I2C0_0_SDA }, + { .name = "als", + .port = NPCX_I2C_PORT0_1, + .kbps = 400, + .scl = GPIO_I2C0_1_SCL, + .sda = GPIO_I2C0_1_SDA }, + { .name = "charger", + .port = NPCX_I2C_PORT1, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "pmic", + .port = NPCX_I2C_PORT2, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "accelgyro", + .port = NPCX_I2C_PORT3, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -202,22 +221,28 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = NPCX_I2C_PORT0_0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &anx74xx_tcpm_usb_mux_driver, - .hpd_update = &anx74xx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &anx74xx_tcpm_usb_mux_driver, + .hpd_update = &anx74xx_tcpc_update_hpd_status, + }, }, { - .usb_port = 1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -242,7 +267,6 @@ const struct charger_config_t chg_chips[] = { }, }; - /** * Power on (or off) a single TCPC. * minimum on/off delays are included. @@ -319,9 +343,10 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); uint16_t tcpc_get_alert_status(void) { @@ -341,17 +366,17 @@ uint16_t tcpc_get_alert_status(void) } const struct temp_sensor_t temp_sensors[] = { - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0}, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0 }, /* These BD99992GW temp sensors are only readable in S0 */ - {"Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM0}, - {"Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM1}, - {"DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM2}, - {"eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM3}, + { "Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM0 }, + { "Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM1 }, + { "DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM2 }, + { "eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM3 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -367,8 +392,8 @@ static void board_report_pmic_fault(const char *str) uint32_t info; /* RESETIRQ1 -- Bit 4: VRFAULT */ - if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) - != EC_SUCCESS) + if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) != + EC_SUCCESS) return; if (!(vrfault & BIT(4))) @@ -477,8 +502,7 @@ static void board_pmic_enable_slp_s0_vr_decay(void) i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x38, 0x7a); } -__override void power_board_handle_host_sleep_event( - enum host_sleep_event state) +__override void power_board_handle_host_sleep_event(enum host_sleep_event state) { if (state == HOST_SLEEP_EVENT_S0IX_SUSPEND) board_pmic_enable_slp_s0_vr_decay(); @@ -531,9 +555,9 @@ static void board_init(void) * force detection on both ports. */ gpio_set_flags(GPIO_USB_C0_VBUS_WAKE_L, - GPIO_INPUT | GPIO_PULL_DOWN); + GPIO_INPUT | GPIO_PULL_DOWN); gpio_set_flags(GPIO_USB_C1_VBUS_WAKE_L, - GPIO_INPUT | GPIO_PULL_DOWN); + GPIO_INPUT | GPIO_PULL_DOWN); vbus0_evt(GPIO_USB_C0_VBUS_WAKE_L); vbus1_evt(GPIO_USB_C1_VBUS_WAKE_L); @@ -552,10 +576,9 @@ static void board_init(void) */ if (system_get_board_version() >= 5) gpio_set_flags(GPIO_LED_YELLOW_C0_OLD, - GPIO_INPUT | GPIO_PULL_UP); + GPIO_INPUT | GPIO_PULL_UP); else - gpio_set_flags(GPIO_LED_YELLOW_C0, - GPIO_INPUT | GPIO_PULL_UP); + gpio_set_flags(GPIO_LED_YELLOW_C0, GPIO_INPUT | GPIO_PULL_UP); #ifdef BOARD_SORAKA /* @@ -564,21 +587,25 @@ static void board_init(void) * for better S0ix/S3 power */ if (system_get_board_version() >= 4) { - gpio_set_flags(GPIO_WLAN_PE_RST, - GPIO_INPUT | GPIO_PULL_UP); - gpio_set_flags(GPIO_PP3300_DX_LTE, - GPIO_INPUT | GPIO_PULL_UP); - gpio_set_flags(GPIO_LTE_GPS_OFF_L, - GPIO_INPUT | GPIO_PULL_UP); - gpio_set_flags(GPIO_LTE_BODY_SAR_L, - GPIO_INPUT | GPIO_PULL_UP); - gpio_set_flags(GPIO_LTE_WAKE_L, - GPIO_INPUT | GPIO_PULL_UP); - gpio_set_flags(GPIO_LTE_OFF_ODL, - GPIO_INPUT | GPIO_PULL_UP); + gpio_set_flags(GPIO_WLAN_PE_RST, GPIO_INPUT | GPIO_PULL_UP); + gpio_set_flags(GPIO_PP3300_DX_LTE, GPIO_INPUT | GPIO_PULL_UP); + gpio_set_flags(GPIO_LTE_GPS_OFF_L, GPIO_INPUT | GPIO_PULL_UP); + gpio_set_flags(GPIO_LTE_BODY_SAR_L, GPIO_INPUT | GPIO_PULL_UP); + gpio_set_flags(GPIO_LTE_WAKE_L, GPIO_INPUT | GPIO_PULL_UP); + gpio_set_flags(GPIO_LTE_OFF_ODL, GPIO_INPUT | GPIO_PULL_UP); } #endif +#ifndef BOARD_LUX + /* + * see (b/111215677): setting the internal PU/PD of the unused pin + * GPIO10 affects the ball K10 when it is selected to CR_SIN. + * Disabing the WKINEN bit of GPIO10 insteading setting its PU/PD to + * bypass this issue. + */ + NPCX_WKINEN(MIWU_TABLE_1, MIWU_GROUP_2) &= 0xFE; +#endif + /* Enable Gyro interrupts */ gpio_enable_interrupt(GPIO_ACCELGYRO3_INT_L); @@ -631,10 +658,12 @@ int board_set_active_charge_port(int charge_port) #endif /* Make sure non-charging port is disabled */ gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_L : - GPIO_USB_C1_CHARGE_L, 1); + GPIO_USB_C1_CHARGE_L, + 1); /* Enable charging port */ gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_L : - GPIO_USB_C0_CHARGE_L, 0); + GPIO_USB_C0_CHARGE_L, + 0); } return EC_SUCCESS; @@ -648,8 +677,8 @@ int board_set_active_charge_port(int charge_port) * @param charge_ma Desired charge limit (mA). * @param charge_mv Negotiated charge voltage (mV). */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* Adjust ILIM according to measurements to eliminate overshoot. */ charge_ma = (charge_ma - 500) * 31 / 32 + 472; @@ -657,7 +686,7 @@ void board_set_charge_limit(int port, int supplier, int charge_ma, if (charge_mv > 5000) charge_ma -= 52; - charge_set_input_current_limit(MAX(charge_ma, ILIM_MIN_MA), charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } void board_hibernate(void) @@ -666,8 +695,7 @@ void board_hibernate(void) uart_flush_output(); /* Trigger PMIC shutdown. */ - if (i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, - 0x49, 0x01)) { + if (i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x49, 0x01)) { /* * If we can't tell the PMIC to shutdown, instead reset * and don't start the AP. Hopefully we'll be able to @@ -723,31 +751,23 @@ static struct opt3001_drv_data_t g_opt3001_data = { }; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t mag_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t mag_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; #ifdef BOARD_SORAKA -const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - {FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* For rev3 and older */ -const mat33_fp_t lid_standard_ref_old = { - {FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t lid_standard_ref_old = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; #else -const mat33_fp_t lid_standard_ref = { - {FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; #endif struct motion_sensor_t motion_sensors[] = { @@ -806,7 +826,10 @@ struct motion_sensor_t motion_sensors[] = { .default_range = BIT(11), /* 16LSB / uT, fixed */ .rot_standard_ref = &mag_standard_ref, .min_frequency = BMM150_MAG_MIN_FREQ, +/* TODO(b/253292373): Remove when clang is fixed. */ +DISABLE_CLANG_WARNING("-Wshift-count-negative") .max_frequency = BMM150_MAG_MAX_FREQ(SPECIAL), +ENABLE_CLANG_WARNING("-Wshift-count-negative") }, [LID_ALS] = { .name = "Light", diff --git a/board/poppy/board.h b/board/poppy/board.h index 00effffe56..5242c1d3a8 100644 --- a/board/poppy/board.h +++ b/board/poppy/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,7 +17,6 @@ /* EC */ #define CONFIG_ADC #define CONFIG_BACKLIGHT_LID -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_BOARD_FORCE_RESET_PIN #define CONFIG_BUTTON_TRIGGERED_RECOVERY #define CONFIG_DETACHABLE_BASE @@ -26,16 +25,15 @@ #define CONFIG_DPTF_MULTI_PROFILE #endif #define CONFIG_EMULATED_SYSRQ -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_LED_COMMON #define CONFIG_LID_SWITCH #define CONFIG_LOW_POWER_IDLE #define CONFIG_LTO #define CONFIG_CHIP_PANIC_BACKUP -#define CONFIG_SOFTWARE_PANIC #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25X40 #define CONFIG_VBOOT_HASH @@ -64,9 +62,10 @@ #define CONFIG_CHIPSET_SKYLAKE #define CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD /* Battery */ #define CONFIG_BATTERY_CUT_OFF @@ -78,7 +77,7 @@ #ifdef BOARD_LUX #define CONFIG_UART_PAD_SWITCH -#define CONFIG_EC_EC_COMM_MASTER +#define CONFIG_EC_EC_COMM_CLIENT #define CONFIG_EC_EC_COMM_BATTERY #define CONFIG_CRC8 #endif @@ -90,8 +89,8 @@ #define CONFIG_CHARGER #define CONFIG_CHARGER_ISL9238 #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 472 #define CONFIG_CHARGER_PSYS #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 @@ -102,8 +101,8 @@ #define CONFIG_CMD_CHARGER_ADC_AMON_BMON #define CONFIG_HOSTCMD_PD_CONTROL #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS -#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 #define CONFIG_POWER_COMMON @@ -120,12 +119,11 @@ #define CONFIG_TEMP_SENSOR_BD99992GW #define CONFIG_THERMISTOR_NCP15WB -#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_HOST_EVENT #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_MAG_BMI_BMM150 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) #define CONFIG_ACCELGYRO_SEC_ADDR_FLAGS BMM150_ADDR0_FLAGS @@ -143,7 +141,7 @@ #define CONFIG_TABLET_MODE #define CONFIG_TABLET_MODE_SWITCH -#undef CONFIG_UART_TX_BUF_SIZE +#undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 2048 /* USB */ @@ -174,28 +172,28 @@ #define CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT 2 /* Optional feature to configure npcx chip */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 as TACH */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 as TACH */ /* I2C ports */ -#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_0 -#define I2C_PORT_ALS NPCX_I2C_PORT0_1 -#define I2C_PORT_USB_CHARGER_1 NPCX_I2C_PORT0_1 -#define I2C_PORT_USB_CHARGER_0 NPCX_I2C_PORT1 -#define I2C_PORT_CHARGER NPCX_I2C_PORT1 -#define I2C_PORT_BATTERY NPCX_I2C_PORT1 -#define I2C_PORT_PMIC NPCX_I2C_PORT2 -#define I2C_PORT_MP2949 NPCX_I2C_PORT2 -#define I2C_PORT_GYRO NPCX_I2C_PORT3 -#define I2C_PORT_BARO NPCX_I2C_PORT3 -#define I2C_PORT_ACCEL I2C_PORT_GYRO -#define I2C_PORT_THERMAL I2C_PORT_PMIC +#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_0 +#define I2C_PORT_ALS NPCX_I2C_PORT0_1 +#define I2C_PORT_USB_CHARGER_1 NPCX_I2C_PORT0_1 +#define I2C_PORT_USB_CHARGER_0 NPCX_I2C_PORT1 +#define I2C_PORT_CHARGER NPCX_I2C_PORT1 +#define I2C_PORT_BATTERY NPCX_I2C_PORT1 +#define I2C_PORT_PMIC NPCX_I2C_PORT2 +#define I2C_PORT_MP2949 NPCX_I2C_PORT2 +#define I2C_PORT_GYRO NPCX_I2C_PORT3 +#define I2C_PORT_BARO NPCX_I2C_PORT3 +#define I2C_PORT_ACCEL I2C_PORT_GYRO +#define I2C_PORT_THERMAL I2C_PORT_PMIC /* I2C addresses */ -#define I2C_ADDR_BD99992_FLAGS 0x30 -#define I2C_ADDR_MP2949_FLAGS 0x20 +#define I2C_ADDR_BD99992_FLAGS 0x30 +#define I2C_ADDR_MP2949_FLAGS 0x20 #ifndef __ASSEMBLER__ @@ -203,11 +201,11 @@ #include "registers.h" enum temp_sensor_id { - TEMP_SENSOR_BATTERY, /* BD99956GW TSENSE */ - TEMP_SENSOR_AMBIENT, /* BD99992GW SYSTHERM0 */ - TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ - TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ - TEMP_SENSOR_EMMC, /* BD99992GW SYSTHERM3 */ + TEMP_SENSOR_BATTERY, /* BD99956GW TSENSE */ + TEMP_SENSOR_AMBIENT, /* BD99992GW SYSTHERM0 */ + TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ + TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ + TEMP_SENSOR_EMMC, /* BD99992GW SYSTHERM3 */ TEMP_SENSOR_COUNT }; @@ -240,17 +238,16 @@ enum adc_channel { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Board specific handlers */ int board_get_version(void); diff --git a/board/poppy/build.mk b/board/poppy/build.mk index df32a7ca8f..36c55d3048 100644 --- a/board/poppy/build.mk +++ b/board/poppy/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/poppy/ec.tasklist b/board/poppy/ec.tasklist index 7591137bc9..4ee0b53a32 100644 --- a/board/poppy/ec.tasklist +++ b/board/poppy/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/poppy/gpio.inc b/board/poppy/gpio.inc index 940d498a19..63a8d3ce99 100644 --- a/board/poppy/gpio.inc +++ b/board/poppy/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,14 +13,14 @@ GPIO_INT(USB_C1_PD_INT_ODL, PIN(C, 5), GPIO_INT_FALLING, tcpc_alert_event) #ifdef CONFIG_POWER_S0IX GPIO_INT(PCH_SLP_S0_L, PIN(7, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 #ifdef BOARD_LUX GPIO_INT(PCH_SLP_S3_L, PIN(2, 2), GPIO_INT_BOTH, power_signal_interrupt) #else GPIO_INT(PCH_SLP_S3_L, PIN(7, 3), GPIO_INT_BOTH, power_signal_interrupt) #endif -#endif /* CONFIG_HOSTCMD_ESPI_VW_SLP_S3 */ -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#endif /* CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 */ +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(PCH_SLP_S4_L, PIN(8, 6), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PCH_SLP_SUS_L, PIN(6, 2), GPIO_INT_BOTH, power_signal_interrupt) @@ -117,7 +117,7 @@ GPIO(PPVAR_VAR_BASE, PIN(1, 2), GPIO_OUT_LOW) #else GPIO(PP3300_DX_BASE, PIN(1, 1), GPIO_OUT_LOW) GPIO(TP_EC_GPIO_07, PIN(0, 7), GPIO_INPUT | GPIO_PULL_UP) -GPIO(TP_EC_GPIO_10, PIN(1, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(TP_EC_GPIO_10, PIN(1, 0), GPIO_INPUT) GPIO(TP_EC_GPIO_15, PIN(1, 5), GPIO_INPUT | GPIO_PULL_UP) #endif diff --git a/board/poppy/led.c b/board/poppy/led.c index 0c2d7f1832..ea82bda490 100644 --- a/board/poppy/led.c +++ b/board/poppy/led.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -31,17 +31,18 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static void side_led_set_color(int port, enum led_color color) { int yellow_c0 = (system_get_board_version() >= 5) ? - GPIO_LED_YELLOW_C0 : GPIO_LED_YELLOW_C0_OLD; + GPIO_LED_YELLOW_C0 : + GPIO_LED_YELLOW_C0_OLD; gpio_set_level(port ? GPIO_LED_YELLOW_C1 : yellow_c0, - (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); gpio_set_level(port ? GPIO_LED_WHITE_C1 : GPIO_LED_WHITE_C0, - (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); } void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) @@ -92,20 +93,20 @@ static void set_active_port_color(enum led_color color) static void board_led_set_battery(void) { static int battery_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate when charging, even in suspend. */ set_active_port_color(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) { if (charge_get_percent() <= 10) - side_led_set_color(0, - (battery_ticks & 0x4) ? LED_WHITE : LED_OFF); + side_led_set_color(0, (battery_ticks & 0x4) ? + LED_WHITE : + LED_OFF); else side_led_set_color(0, LED_OFF); } @@ -113,19 +114,19 @@ static void board_led_set_battery(void) if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) side_led_set_color(1, LED_OFF); break; - case PWR_STATE_ERROR: - set_active_port_color((battery_ticks & 0x2) ? - LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: set_active_port_color(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - set_active_port_color((battery_ticks & 0x4) ? - LED_AMBER : LED_OFF); - else - set_active_port_color(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color((battery_ticks & 0x4) ? LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ diff --git a/board/poppy/usb_pd_policy.c b/board/poppy/usb_pd_policy.c index a32b77bbe7..96e13aa73b 100644 --- a/board/poppy/usb_pd_policy.c +++ b/board/poppy/usb_pd_policy.c @@ -1,15 +1,15 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -17,17 +17,17 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { @@ -48,8 +48,8 @@ static void board_vbus_update_source_current(int port) * is controlled by GPIO_USB_C0/1_5V_EN. Both of these signals * can remain outputs. */ - gpio_set_level(gpio_3a_en, vbus_rp[port] == TYPEC_RP_3A0 ? - 1 : 0); + gpio_set_level(gpio_3a_en, + vbus_rp[port] == TYPEC_RP_3A0 ? 1 : 0); gpio_set_level(gpio_5v_en, vbus_en[port]); } else { /* @@ -61,8 +61,8 @@ static void board_vbus_update_source_current(int port) * 1505 mA. */ int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? - (GPIO_INPUT | GPIO_PULL_UP) : - (GPIO_OUTPUT | GPIO_PULL_UP); + (GPIO_INPUT | GPIO_PULL_UP) : + (GPIO_OUTPUT | GPIO_PULL_UP); gpio_set_level(gpio_5v_en, vbus_en[port]); gpio_set_flags(gpio_5v_en, flags); } @@ -79,8 +79,7 @@ void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) int pd_set_power_supply_ready(int port) { /* Disable charging */ - gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : - GPIO_USB_C0_CHARGE_L, 1); + gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : GPIO_USB_C0_CHARGE_L, 1); /* Ensure we advertise the proper available current quota */ charge_manager_source_port(port, 1); @@ -131,15 +130,13 @@ int pd_check_vconn_swap(int port) return gpio_get_level(GPIO_PMIC_SLP_SUS_L); } -__override void pd_execute_data_swap(int port, - enum pd_data_role data_role) +__override void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* Only port 0 supports device mode. */ if (port != 0) return; - gpio_set_level(GPIO_USB2_OTG_ID, - (data_role == PD_ROLE_UFP) ? 1 : 0); + gpio_set_level(GPIO_USB2_OTG_ID, (data_role == PD_ROLE_UFP) ? 1 : 0); gpio_set_level(GPIO_USB2_OTG_VBUSSENSE, - (data_role == PD_ROLE_UFP) ? 1 : 0); + (data_role == PD_ROLE_UFP) ? 1 : 0); } diff --git a/board/poppy/vif_override.xml b/board/poppy/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/poppy/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/primus/battery.c b/board/primus/battery.c new file mode 100644 index 0000000000..1b0d74bed3 --- /dev/null +++ b/board/primus/battery.c @@ -0,0 +1,211 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "compile_time_macros.h" + +/* + * Battery info for all Primus battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + [BATTERY_SUNWODA_5B11F21946] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "LNV-5B11F21946", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0000, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 251, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + [BATTERY_SUNWODA_5B11H56342] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "LNV-5B11H56342", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0000, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 251, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + [BATTERY_SMP_5B11F21953] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "LNV-5B11F21953", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0000, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 250, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 60, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + [BATTERY_SMP_5B11H56344] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "LNV-5B11H56344", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0000, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 250, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 60, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + [BATTERY_CELXPERT_5B11F21941] = { + .fuel_gauge = { + .manuf_name = "Celxpert", + .device_name = "LNV-5B11F21941", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0000, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 487, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, + + [BATTERY_CELXPERT_5B11H56343] = { + .fuel_gauge = { + .manuf_name = "Celxpert", + .device_name = "LNV-5B11H56343", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0000, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 487, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SUNWODA_5B11F21946; diff --git a/board/primus/board.c b/board/primus/board.c new file mode 100644 index 0000000000..f42e83c509 --- /dev/null +++ b/board/primus/board.c @@ -0,0 +1,167 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "keyboard_8042_sharedlib.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "registers.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +#define KBLIGHT_LED_ON_LVL 100 +#define KBLIGHT_LED_OFF_LVL 0 + +#define PD_MAX_SUSPEND_CURRENT_MA 3000 + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +__override void board_cbi_init(void) +{ + config_usb_db_type(); +} + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + pwm_set_duty(PWM_CH_KBLIGHT, KBLIGHT_LED_ON_LVL); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + pwm_set_duty(PWM_CH_KBLIGHT, KBLIGHT_LED_OFF_LVL); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +enum battery_present battery_hw_present(void) +{ + enum gpio_signal batt_pres; + + batt_pres = GPIO_EC_BATT_PRES_ODL; + + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(batt_pres) ? BP_NO : BP_YES; +} + +static void keyboard_init(void) +{ + /* + * Set T15(KSI0/KSO11) to Lock key(KSI3/KSO9) + */ + set_scancode_set2(0, 11, get_scancode_set2(3, 9)); +} +DECLARE_HOOK(HOOK_INIT, keyboard_init, HOOK_PRIO_DEFAULT); + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Need to set different input current limit depend on system state. + * Guard adapter plug/ un-plug here. + */ + + if (((max_ma == PD_MAX_CURRENT_MA) && + chipset_in_state(CHIPSET_STATE_ANY_OFF)) || + (max_ma != PD_MAX_CURRENT_MA)) + charge_ma = charge_ma * 97 / 100; + else + charge_ma = charge_ma * 93 / 100; + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +static void configure_input_current_limit(void) +{ + /* + * If adapter == 3250mA, we need system be charged at 3150mA in S5. + * And system be charged at 3000mA in S0. + */ + int adapter_current_ma; + int adapter_current_mv; + /* Get adapter voltage/ current */ + adapter_current_mv = charge_manager_get_charger_voltage(); + adapter_current_ma = charge_manager_get_charger_current(); + + if ((adapter_current_ma == PD_MAX_CURRENT_MA) && + chipset_in_or_transitioning_to_state(CHIPSET_STATE_SUSPEND)) + adapter_current_ma = PD_MAX_SUSPEND_CURRENT_MA; + else + adapter_current_ma = adapter_current_ma * 97 / 100; + + charge_set_input_current_limit(adapter_current_ma, adapter_current_mv); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, configure_input_current_limit, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN_COMPLETE, configure_input_current_limit, + HOOK_PRIO_DEFAULT); diff --git a/board/primus/board.h b/board/primus/board.h new file mode 100644 index 0000000000..3fb8b868c6 --- /dev/null +++ b/board/primus/board.h @@ -0,0 +1,230 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Primus board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* Sensors */ +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE + +/* No side buttons */ +#undef CONFIG_MKBP_INPUT_DEVICES +#undef CONFIG_VOLUME_BUTTONS + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#undef CONFIG_USB_PD_TCPM_NCT38XX +#define CONFIG_USB_PD_TCPM_RT1715 +#define CONFIG_USBC_RETIMER_INTEL_BB + +#define CONFIG_USBC_PPC_SYV682X + +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 65000 +#define PD_MAX_CURRENT_MA 3250 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +#define GPIO_ID_1_EC_KB_BL_EN GPIO_EC_BATT_PRES_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* Keyboard features */ +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* I2C Bus Configuration */ + +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 +#define I2C_PORT_USB_C0_C1_PPC_BC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C0_C1_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C0_C1_RT NPCX_I2C_PORT3_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_USB_A0_A1_MIX NPCX_I2C_PORT6_1 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x57 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* LED */ +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 91 + +/* Fan features */ +#define CONFIG_CUSTOM_FAN_CONTROL +#define CONFIG_FANS FAN_CH_COUNT +#define RPM_DEVIATION 1 + +/* Charger defines */ +#define CONFIG_CHARGER_BQ25720 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 70 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 + +/* PROCHOT defines */ +#define BATT_MAX_CONTINUE_DISCHARGE_WATT 66 + +/* Prochot assertion/deassertion ratios*/ +#define PROCHOT_ADAPTER_WATT_RATIO 97 +#define PROCHOT_ASSERTION_BATTERY_RATIO 95 +#define PROCHOT_DEASSERTION_BATTERY_RATIO 85 +#define PROCHOT_ASSERTION_PD_RATIO 105 +#define PROCHOT_DEASSERTION_PD_RATIO 100 +#define PROCHOT_DEASSERTION_PD_BATTERY_RATIO 95 +#define PROCHOT_ASSERTION_ADAPTER_RATIO 105 +#define PROCHOT_DEASSERTION_ADAPTER_RATIO 100 +#define PROCHOT_DEASSERTION_ADAPTER_BATT_RATIO 90 + +/* PS2 defines */ +#define CONFIG_8042_AUX +#define CONFIG_PS2 +#define CONFIG_CMD_PS2 +#define PRIMUS_PS2_CH NPCX_PS2_CH1 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_SSD, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_TEMP_SENSOR_4_MEMORY, + ADC_TEMP_SENSOR_5_USBC, + ADC_IADPT, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_SSD, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_4_MEMORY, + TEMP_SENSOR_5_USBC, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + CLEAR_ALS, + RGB_ALS, + SENSOR_COUNT +}; + +enum battery_type { + BATTERY_SUNWODA_5B11F21946, + BATTERY_SUNWODA_5B11H56342, + BATTERY_SMP_5B11F21953, + BATTERY_SMP_5B11H56344, + BATTERY_CELXPERT_5B11F21941, + BATTERY_CELXPERT_5B11H56343, + BATTERY_TYPE_COUNT +}; + +enum pwm_channel { + PWM_CH_LED2_WHITE = 0, /* PWM0 (white charger) */ + PWM_CH_TKP_A_LED_N, /* PWM1 (LOGO led on A cover) */ + PWM_CH_LED1_AMBER, /* PWM2 (orange charger) */ + PWM_CH_KBLIGHT, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_LED4, /* PWM7 (power) */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/primus/build.mk b/board/primus/build.mk new file mode 100644 index 0000000000..409a9dd45e --- /dev/null +++ b/board/primus/build.mk @@ -0,0 +1,28 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Primus board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=cbi_ssfc.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=ps2.o +board-y+=sensors.o +board-y+=thermal.o +board-y+=usbc_config.o diff --git a/board/primus/cbi_ssfc.c b/board/primus/cbi_ssfc.c new file mode 100644 index 0000000000..45afa622ab --- /dev/null +++ b/board/primus/cbi_ssfc.c @@ -0,0 +1,30 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union primus_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +void board_init_ssfc(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} + +enum ec_ssfc_trackpoint get_cbi_ssfc_trackpoint(void) +{ + return cached_ssfc.trackpoint; +} diff --git a/board/primus/cbi_ssfc.h b/board/primus/cbi_ssfc.h new file mode 100644 index 0000000000..fe4c2fb4e5 --- /dev/null +++ b/board/primus/cbi_ssfc.h @@ -0,0 +1,31 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef _PRIMUS_CBI_SSFC_H_ +#define _PRIMUS_CBI_SSFC_H_ +#include "stdint.h" +/**************************************************************************** + * Primus CBI Second Source Factory Cache + */ +/* + * Trackpoint (Bit 0) + */ +enum ec_ssfc_trackpoint { + SSFC_SENSOR_TRACKPOINT_ELAN = 0, + SSFC_SENSOR_TRACKPOINT_SYNAPTICS = 1, +}; +union primus_cbi_ssfc { + struct { + enum ec_ssfc_trackpoint trackpoint : 2; + uint32_t reserved_1 : 30; + }; + uint32_t raw_value; +}; +/** + * Get the trackpoint type from SSFC_CONFIG. + * + * @return the Trackpoint board type. + */ +enum ec_ssfc_trackpoint get_cbi_ssfc_trackpoint(void); +#endif /* _PRIMUS_CBI_SSFC_H_ */ diff --git a/board/primus/charger.c b/board/primus/charger.c new file mode 100644 index 0000000000..827152e115 --- /dev/null +++ b/board/primus/charger.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/primus/ec.tasklist b/board/primus/ec.tasklist new file mode 100644 index 0000000000..3afcca805e --- /dev/null +++ b/board/primus/ec.tasklist @@ -0,0 +1,31 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_NOTEST(PROCHOT, prochot_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(LOGOLED, logoled_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/primus/fans.c b/board/primus/fans.c new file mode 100644 index 0000000000..b109fcf5da --- /dev/null +++ b/board/primus/fans.c @@ -0,0 +1,85 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * Set maximum rpm at 4800/ minimum rpm at 1800. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1800, + .rpm_start = 1800, + .rpm_max = 4800, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/181271666): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/primus/fw_config.c b/board/primus/fw_config.c new file mode 100644 index 0000000000..82ba396901 --- /dev/null +++ b/board/primus/fw_config.c @@ -0,0 +1,65 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union primus_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for primus if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union primus_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_PS8815, + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Primus FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* + * Early boards have a zero'd out FW_CONFIG, so replace + * it with a sensible default value. If DB_USB_ABSENT2 + * was used as an alternate encoding of DB_USB_ABSENT to + * avoid the zero check, then fix it. + */ + if (fw_config.raw_value == 0) { + CPRINTS("CBI: FW_CONFIG is zero, using board defaults"); + fw_config = fw_config_defaults; + } else if (fw_config.usb_db == DB_USB_ABSENT2) { + fw_config.usb_db = DB_USB_ABSENT; + } + } +} + +union primus_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +enum ec_cfg_mlb_usb ec_cfg_mlb_usb(void) +{ + return fw_config.mlb_usb; +} + +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void) +{ + return fw_config.usb_db; +} diff --git a/board/primus/fw_config.h b/board/primus/fw_config.h new file mode 100644 index 0000000000..81fa5481f8 --- /dev/null +++ b/board/primus/fw_config.h @@ -0,0 +1,65 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_PRIMUS_FW_CONFIG_H_ +#define __BOARD_PRIMUS_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Primus board. + * + * Source of truth is the project/brya/primus/config.star configuration file. + */ + +enum ec_cfg_usb_db_type { + DB_USB_ABSENT = 0, + DB_USB3_PS8815 = 1, + DB_USB_ABSENT2 = 15 +}; + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_mlb_usb { MLB_USB_TBT = 0, MLB_USB_USB4 = 1 }; + +union primus_cbi_fw_config { + struct { + enum ec_cfg_usb_db_type usb_db : 4; + uint32_t sd_db : 2; + uint32_t reserved_0 : 1; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t cellular_db : 2; + enum ec_cfg_mlb_usb mlb_usb : 1; + uint32_t reserved_1 : 18; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union primus_cbi_fw_config get_fw_config(void); + +/** + * Get MLB USB type from FW_CONFIG. + * + * @return the MLB USB type. + */ +enum ec_cfg_mlb_usb ec_cfg_mlb_usb(void); + +/** + * Get the USB daughter board type from FW_CONFIG. + * + * @return the USB daughter board type. + */ +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void); + +#endif /* __BOARD_PRIMUS_FW_CONFIG_H_ */ diff --git a/board/primus/gpio.inc b/board/primus/gpio.inc new file mode 100644 index 0000000000..9928eb0cc5 --- /dev/null +++ b/board/primus/gpio.inc @@ -0,0 +1,136 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(A, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +/* USB C1 gpio pins are mapped to schematic USB C2 */ +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(0, 2), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_RT_INT_ODL, PIN(9, 7), GPIO_INT_FALLING, retimer_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(KBD_BL_DTCT_N, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_A1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_A1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(5, 7), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(9, 5), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_RT_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(PDEV_STP_N, PIN(9, 6), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(USB_C1_RT_RST_ODL, PIN(5, 0), GPIO_ODR_LOW) +GPIO(USB_C0_FRS_EN, PIN(8, 3), GPIO_OUT_LOW) +GPIO(USB_A_LOW_PWR_OD, PIN(B, 5), GPIO_ODR_LOW) +GPIO(TBT_PWR_EN, PIN(D, 4), GPIO_OUT_LOW) +GPIO(TP4_RESET, PIN(9, 3), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(FAN_ID, PIN(4, 1), GPIO_INPUT) +GPIO(USB_C0_OC_ODL, PIN(5, 6), GPIO_ODR_HIGH) +GPIO(USB_C1_OC_ODL, PIN(B, 4), GPIO_ODR_HIGH) +GPIO(EC_PS2_SCL_TPAD, PIN(6, 2), GPIO_ODR_LOW) +GPIO(EC_PS2_SDA_TPAD, PIN(6, 3), GPIO_ODR_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(6, 0x01), 0, MODULE_PWM, 0) /* GPIO60/PWM7 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ +ALTERNATE(PIN_MASK(C, 0x1c), 0, MODULE_PWM, 0) /* GPIOC4/PWM2, GPIOC3/PWM0, GPIOC2/PWM1/I2C6_SCL0 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x3C), 0, MODULE_ADC, 0) /* GPIO45/ADC0, GPIO44/ADC1, GPIO43/ADC2, GPIO42/ADC3/RI_L */ +ALTERNATE(PIN_MASK(F, 0x01), 0, MODULE_ADC, 0) /* GPIOF0/ADC9 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(8, 1)) /* GPIO81/PECI_DATA */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS# */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST# */ +UNUSED(PIN(6, 6)) /* GPO66/ARM#_X86 */ +UNUSED(PIN(8, 6)) /* GPIO86/TXD/CR_SOUT2 */ +/* Pre-configured PSL balls: J8 K6 */ + + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) diff --git a/board/primus/i2c.c b/board/primus/i2c.c new file mode 100644 index 0000000000..02892af19d --- /dev/null +++ b/board/primus/i2c.c @@ -0,0 +1,75 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C1 + * TODO(b/191178381) Need to check the signals with a scope + * before raising to 1MHz. + */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,1", + .port = I2C_PORT_USB_C0_C1_PPC_BC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,2", + .port = I2C_PORT_USB_C0_C1_RT, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_RT_SDA, + }, + { + /* I2C4 + * TODO(b/191178381) Need to check the signals with a scope + * before raising to 1MHz. + */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "usb_mix0,1", + .port = I2C_PORT_USB_A0_A1_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C_USB_A0_A1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_A0_A1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/primus/keyboard.c b/board/primus/keyboard.c new file mode 100644 index 0000000000..9c9a37e9fc --- /dev/null +++ b/board/primus/keyboard.c @@ -0,0 +1,52 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfb, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config primus_kb = { + .num_top_row_keys = 14, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PREV_TRACK, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_NEXT_TRACK, /* T10 */ + TK_MICMUTE, /* T11 */ + TK_VOL_MUTE, /* T12 */ + TK_VOL_DOWN, /* T13 */ + TK_VOL_UP, /* T14 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &primus_kb; +} diff --git a/board/primus/led.c b/board/primus/led.c new file mode 100644 index 0000000000..8d4083558f --- /dev/null +++ b/board/primus/led.c @@ -0,0 +1,236 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Primus specific PWM LED settings. */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "ec_commands.h" +#include "extpower.h" +#include "hooks.h" +#include "led_common.h" +#include "power.h" +#include "pwm.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#include +#define CPRINTS(format, args...) cprints(CC_LOGOLED, format, ##args) + +#define LED_ON_LVL 100 +#define LED_OFF_LVL 0 +#define LED_BAT_S3_OFF_TIME_MS 3000 +#define LED_BAT_S3_TICK_MS 50 +#define LED_BAT_S3_PWM_RESCALE 5 +#define LED_TOTAL_TICKS 6 +#define TICKS_STEP1_BRIGHTER 0 +#define TICKS_STEP2_DIMMER (1000 / LED_BAT_S3_TICK_MS) +#define TICKS_STEP3_OFF (2 * TICKS_STEP2_DIMMER) +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +#define LED_LOGO_TICK_SEC (LED_ONE_SEC / 4) +/* Total on/off duration in a period */ +#define PERIOD (LED_LOGO_TICK_SEC * 2) +#define LED_ON 1 +#define LED_OFF EC_LED_COLOR_COUNT +#define LED_EVENT_SUSPEND TASK_EVENT_CUSTOM_BIT(0) +#define LED_EVENT_200MS_TICK TASK_EVENT_CUSTOM_BIT(1) + +static int tick; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +static void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + pwm_set_duty(PWM_CH_LED1_AMBER, LED_ON_LVL); + pwm_set_duty(PWM_CH_LED2_WHITE, LED_OFF_LVL); + break; + case EC_LED_COLOR_WHITE: + pwm_set_duty(PWM_CH_LED2_WHITE, LED_ON_LVL); + pwm_set_duty(PWM_CH_LED1_AMBER, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + pwm_set_duty(PWM_CH_LED1_AMBER, LED_OFF_LVL); + pwm_set_duty(PWM_CH_LED2_WHITE, LED_OFF_LVL); + break; + } +} + +static void led_set_battery(void) +{ + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + led_set_color_battery(EC_LED_COLOR_AMBER); + break; + case LED_PWRS_DISCHARGE: + led_set_color_battery(LED_OFF); + break; + case LED_PWRS_CHARGE_NEAR_FULL: + led_set_color_battery(EC_LED_COLOR_WHITE); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +void led_set_color_power(int onoff_status) +{ + /* primus logo led and power led have same behavior. */ + if (onoff_status == LED_ON) { + pwm_set_duty(PWM_CH_TKP_A_LED_N, LED_ON_LVL); + pwm_set_duty(PWM_CH_LED4, LED_ON_LVL); + } else { + /* LED_OFF and unsupported colors */ + pwm_set_duty(PWM_CH_TKP_A_LED_N, LED_OFF_LVL); + pwm_set_duty(PWM_CH_LED4, LED_OFF_LVL); + } +} + +#define AC_DISCONNECTED (-1) + +static void led_set_power(void) +{ + static int plug_ac_countdown; + static int ticks; + + if (plug_ac_countdown > 0) { + ticks = (ticks + 1) % PERIOD; + plug_ac_countdown--; + if (ticks < LED_LOGO_TICK_SEC) + led_set_color_power(LED_OFF); + else + led_set_color_power(LED_ON); + } else if (chipset_in_state(CHIPSET_STATE_ON)) + led_set_color_power(LED_ON); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_set_color_power(LED_OFF); + + /* Check AC_PRESENT */ + if (!extpower_is_present()) + plug_ac_countdown = AC_DISCONNECTED; + else if (plug_ac_countdown == AC_DISCONNECTED) + /* AC power was plugged in (previous state was "disconnected"), + * set plug_ac_countdown for amount of ticks left + */ + plug_ac_countdown = LED_TOTAL_TICKS; +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_WHITE] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_RED] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_power(LED_ON); + else + led_set_color_power(LED_OFF); + } + + return EC_SUCCESS; +} + +/* Called by hook task every 200 ms */ +static void led_tick(void) +{ + task_set_event(TASK_ID_LOGOLED, LED_EVENT_200MS_TICK); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +static void suspend_led_update(void) +{ + while (1) { + tick++; + + /* HOOK_CHIPSET_SUSPEND will be called when POWER_S0S0ix, + * if we are not transitioning to suspend, we should break here. + */ + if (!chipset_in_or_transitioning_to_state( + CHIPSET_STATE_ANY_SUSPEND)) + break; + + /* 1s gradual on, 1s gradual off, 3s off */ + if (tick <= TICKS_STEP2_DIMMER) { + /* increase 5 duty every 50ms until PWM=100 + * enter here 20 times, total duartion is 1sec + * A-cover and power button led are shared same + * behavior. + */ + pwm_set_duty(PWM_CH_TKP_A_LED_N, + tick * LED_BAT_S3_PWM_RESCALE); + pwm_set_duty(PWM_CH_LED4, + tick * LED_BAT_S3_PWM_RESCALE); + msleep(LED_BAT_S3_TICK_MS); + } else if (tick <= TICKS_STEP3_OFF) { + /* decrease 5 duty every 50ms until PWM=0 + * enter here 20 times, total duartion is 1sec + * A-cover and power button led are shared same + * behavior. + */ + pwm_set_duty(PWM_CH_TKP_A_LED_N, + (TICKS_STEP3_OFF - tick) * + LED_BAT_S3_PWM_RESCALE); + pwm_set_duty(PWM_CH_LED4, + (TICKS_STEP3_OFF - tick) * + LED_BAT_S3_PWM_RESCALE); + msleep(LED_BAT_S3_TICK_MS); + } else { + tick = TICKS_STEP1_BRIGHTER; + msleep(LED_BAT_S3_OFF_TIME_MS); + } + } +} + +static void suspend_led_init(void) +{ + task_set_event(TASK_ID_LOGOLED, LED_EVENT_SUSPEND); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, suspend_led_init, HOOK_PRIO_DEFAULT); + +void logoled_task(void *u) +{ + uint32_t evt; + + while (1) { + evt = task_wait_event(-1); + + if (evt & LED_EVENT_SUSPEND) { + tick = TICKS_STEP2_DIMMER; + suspend_led_update(); + } + + if (evt & LED_EVENT_200MS_TICK) { + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + led_set_power(); + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + led_set_battery(); + } + } +} diff --git a/board/primus/ps2.c b/board/primus/ps2.c new file mode 100644 index 0000000000..685c036fc2 --- /dev/null +++ b/board/primus/ps2.c @@ -0,0 +1,163 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_8042.h" +#include "ps2.h" +#include "ps2_chip.h" +#include "registers.h" +#include "time.h" + +#include +#include + +#define PS2_TRANSMIT_DELAY_MS 10 + +static uint8_t queue_data[3]; +static int data_count; + +void send_aux_data_to_device(uint8_t data) +{ + ps2_transmit_byte(PRIMUS_PS2_CH, data); +} + +static void board_init(void) +{ + ps2_enable_channel(PRIMUS_PS2_CH, 1, send_aux_data_to_host_interrupt); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* + * Goodix touchpad AVDD need to pull low to 0V when poweroff. + * Setting PS2 module in GPIO.inc will let AVDD have 0.9V offset. + * So we need to enable PS2 module later than PLTRST# to avoid the 0.9V + * offset. + */ +static void enable_ps2(void) +{ + gpio_set_alternate_function(GPIO_PORT_6, BIT(2) | BIT(3), + GPIO_ALT_FUNC_DEFAULT); +} +DECLARE_DEFERRED(enable_ps2); + +static void disable_ps2(void) +{ + gpio_set_flags(GPIO_EC_PS2_SCL_TPAD, GPIO_ODR_LOW); + gpio_set_flags(GPIO_EC_PS2_SDA_TPAD, GPIO_ODR_LOW); + gpio_set_alternate_function(GPIO_PORT_6, BIT(2) | BIT(3), + GPIO_ALT_FUNC_NONE); + /* make sure PLTRST# goes high and re-enable PS2.*/ + hook_call_deferred(&enable_ps2_data, 2 * SECOND); +} +DECLARE_HOOK(HOOK_CHIPSET_RESET, disable_ps2, HOOK_PRIO_DEFAULT); + +static void ps2_transmit(uint8_t cmd) +{ + ps2_transmit_byte(PRIMUS_PS2_CH, cmd); + msleep(PS2_TRANSMIT_DELAY_MS); +} + +/* Process the PS2 data at here */ +void get_ps2_data(uint8_t data) +{ + /* receive the PS2 data and save in PS2 queue */ + queue_data[data_count++] = data; +} + +static void send_command_to_trackpoint(uint8_t command1, uint8_t command2) +{ + /* + * Send command to trackpoint and wait, + * this will make sure EC get ACK from PS2 device + * and send the next command. + */ + + ps2_transmit(TP_COMMAND); + ps2_transmit(TP_TOGGLE); + ps2_transmit(command1); + ps2_transmit(command2); +} + +uint8_t get_trackpoint_id(void) +{ + /* + * Three data will be received when asking PS2 + * device id. + */ + ps2_transmit(TP_READ_ID); + + /* + * When EC send TP_READ_ID, trackpoint will return ACK(0xFA), + * and then return device ID. So return the second data. + * Also make sure only return the trackpoint device ID. + */ + if (queue_data[1] == TP_VARIANT_ELAN || + queue_data[1] == TP_VARIANT_SYNAPTICS) + return queue_data[1]; + else + return 0; +} + +/* Called on AP S0 -> S0ix transition */ +static void ps2_suspend(void) +{ + uint8_t trackpoint_id; + /* + * When EC send PS2 command to PS2 device, + * PS2 device will return ACK(0xFA). + * EC will send it to host and cause host wake from suspend. + * So disable EC send data to host to avoid it. + * + * In order to receive the PS2 data and also not to wake host, + * use get_ps2_data to process PS2 data. + */ + ps2_enable_channel(PRIMUS_PS2_CH, 1, get_ps2_data); + trackpoint_id = get_trackpoint_id(); + /* + * Don't need to read any data from PS2 device now, + * so disable it. + */ + ps2_enable_channel(PRIMUS_PS2_CH, 1, NULL); + + /* + * Send suspend mode to trackpoint + * Those commands was provide by Elan and Synaptics + */ + if (trackpoint_id == TP_VARIANT_ELAN) + send_command_to_trackpoint(TP_TOGGLE_BURST, + TP_TOGGLE_ELAN_SLEEP); + else if (trackpoint_id == TP_VARIANT_SYNAPTICS) + send_command_to_trackpoint(TP_TOGGLE_SOURCE_TAG, + TP_TOGGLE_SNAPTICS_SLEEP); + + /* Clear the data in queue and the counter */ + memset(queue_data, 0, ARRAY_SIZE(queue_data)); + data_count = 0; +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, ps2_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S0ix -> S0 transition */ +static void ps2_resume(void) +{ + uint8_t trackpoint_id; + + ps2_enable_channel(PRIMUS_PS2_CH, 1, get_ps2_data); + trackpoint_id = get_trackpoint_id(); + ps2_enable_channel(PRIMUS_PS2_CH, 1, send_aux_data_to_host_interrupt); + /* + * For Synaptics trackpoint, EC need to send command to it again. + * For Elan trackpoint, we just need to touch trackpoint and it wake. + */ + if (trackpoint_id == TP_VARIANT_SYNAPTICS) + send_command_to_trackpoint(TP_TOGGLE_SOURCE_TAG, + TP_TOGGLE_SNAPTICS_SLEEP); + + /* Clear the data in queue and the counter */ + memset(queue_data, 0, ARRAY_SIZE(queue_data)); + data_count = 0; +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, ps2_resume, HOOK_PRIO_DEFAULT); diff --git a/board/primus/ps2.h b/board/primus/ps2.h new file mode 100644 index 0000000000..a82d6d566a --- /dev/null +++ b/board/primus/ps2.h @@ -0,0 +1,31 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_PRIMUS_PS2_H +#define __CROS_EC_PRIMUS_PS2_H + +/* Primus board-specific PS2 configuration */ +/* + * Valid first byte responses to the "Read Secondary ID" (0xE1) command. + * 0x01 was the original IBM trackpoint, others implement very limited + * subset of trackpoint features. + */ +#define TP_READ_ID 0xE1 /* Sent for device identification */ + +#define TP_COMMAND 0xE2 /* Commands start with this */ + +/* + * Toggling Flag bits + */ +#define TP_TOGGLE 0x47 /* Toggle command */ + +#define TP_VARIANT_ELAN 0x03 +#define TP_VARIANT_SYNAPTICS 0x06 +#define TP_TOGGLE_SOURCE_TAG 0x20 +#define TP_TOGGLE_BURST 0x28 +#define TP_TOGGLE_SNAPTICS_SLEEP 0x10 +#define TP_TOGGLE_ELAN_SLEEP 0x8 + +#endif /* __CROS_EC_PRIMUS_PS2_H */ diff --git a/board/primus/pwm.c b/board/primus/pwm.c new file mode 100644 index 0000000000..f2889c2b8e --- /dev/null +++ b/board/primus/pwm.c @@ -0,0 +1,74 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED2_WHITE] = { + .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_TKP_A_LED_N] = { + .channel = 1, + .flags = PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_LED1_AMBER] = { + .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, + [PWM_CH_LED4] = { + .channel = 7, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 4800, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn off LOGO/power/battery led + */ + pwm_enable(PWM_CH_LED1_AMBER, 1); + pwm_set_duty(PWM_CH_LED1_AMBER, 0); + pwm_enable(PWM_CH_LED2_WHITE, 1); + pwm_set_duty(PWM_CH_LED2_WHITE, 0); + pwm_enable(PWM_CH_TKP_A_LED_N, 1); + pwm_set_duty(PWM_CH_TKP_A_LED_N, 0); + pwm_enable(PWM_CH_LED4, 1); + pwm_set_duty(PWM_CH_LED4, 0); + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + pwm_enable(PWM_CH_KBLIGHT, 1); + /* TODO(b/190518315) + * Check if need to turn to 100% after with chassis. + */ + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/primus/sensors.c b/board/primus/sensors.c new file mode 100644 index 0000000000..67ec6c6310 --- /dev/null +++ b/board/primus/sensors.c @@ -0,0 +1,167 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc_chip.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_SSD] = { + .name = "TEMP_SSD", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_MEMORY] = { + .name = "TEMP_MEMORY", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_5_USBC] = { + .name = "TEMP_USBC", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_IADPT] = { + .name = "CHARGER_IADPT", + .input_ch = NPCX_ADC_CH3, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC }, + [TEMP_SENSOR_2_SSD] = { .name = "SSD", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_SSD }, + [TEMP_SENSOR_3_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER }, + [TEMP_SENSOR_4_MEMORY] = { .name = "MEMORY", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_MEMORY }, + [TEMP_SENSOR_5_USBC] = { .name = "USBC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_5_USBC }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/195901486): update for Alder Lake/primus + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_SSD \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(92), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_ssd = THERMAL_SSD; + +/* + * TODO(b/195901486): update for Alder Lake/primus + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; + +/* + * TODO(b/195901486): Thermal table need to be fine tuned. + */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_SSD] = THERMAL_SSD, + [TEMP_SENSOR_3_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_4_MEMORY] = THERMAL_INDUCTOR, + [TEMP_SENSOR_5_USBC] = THERMAL_INDUCTOR, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/primus/thermal.c b/board/primus/thermal.c new file mode 100644 index 0000000000..00e2dddf98 --- /dev/null +++ b/board/primus/thermal.c @@ -0,0 +1,153 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "fan.h" +#include "hooks.h" +#include "host_command.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +struct fan_step { + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t on[TEMP_SENSOR_COUNT]; + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t off[TEMP_SENSOR_COUNT]; + /* Fan rpm */ + uint16_t rpm[FAN_CH_COUNT]; +}; + +static const struct fan_step fan_table[] = { + { + /* level 0 */ + .on = { 40, -1, -1, -1, -1 }, + .off = { 0, -1, -1, -1, -1 }, + .rpm = { 0 }, + }, + { + /* level 1 */ + .on = { 42, -1, -1, -1, -1 }, + .off = { 40, -1, -1, -1, -1 }, + .rpm = { 1800 }, + }, + { + /* level 2 */ + .on = { 43, -1, -1, -1, -1 }, + .off = { 42, -1, -1, -1, -1 }, + .rpm = { 2000 }, + }, + { + /* level 3 */ + .on = { 44, -1, -1, -1, -1 }, + .off = { 43, -1, -1, -1, -1 }, + .rpm = { 2200 }, + }, + { + /* level 4 */ + .on = { 45, -1, -1, -1, -1 }, + .off = { 44, -1, -1, -1, -1 }, + .rpm = { 2500 }, + }, + { + /* level 5 */ + .on = { 46, -1, -1, -1, -1 }, + .off = { 45, -1, -1, -1, -1 }, + .rpm = { 2800 }, + }, + { + /* level 6 */ + .on = { 47, -1, -1, -1, -1 }, + .off = { 46, -1, -1, -1, -1 }, + .rpm = { 3000 }, + }, + { + /* level 7 */ + .on = { 75, -1, -1, -1, -1 }, + .off = { 72, -1, -1, -1, -1 }, + .rpm = { 3200 }, + }, +}; +const int num_fan_levels = ARRAY_SIZE(fan_table); + +int fan_table_to_rpm(int fan, int *temp, enum temp_sensor_id temp_sensor) +{ + /* current fan level */ + static int current_level; + /* previous fan level */ + static int prev_current_level; + + /* previous sensor temperature */ + static int prev_temp[TEMP_SENSOR_COUNT]; + int i; + int new_rpm = 0; + + /* + * Compare the current and previous temperature, we have + * the three paths : + * 1. decreasing path. (check the release point) + * 2. increasing path. (check the trigger point) + * 3. invariant path. (return the current RPM) + */ + if (temp[temp_sensor] < prev_temp[temp_sensor]) { + for (i = current_level; i > 0; i--) { + if (temp[temp_sensor] < fan_table[i].off[temp_sensor]) + current_level = i - 1; + else + break; + } + } else if (temp[temp_sensor] > prev_temp[temp_sensor]) { + for (i = current_level; i < num_fan_levels; i++) { + if (temp[temp_sensor] > fan_table[i].on[temp_sensor]) + current_level = i + 1; + else + break; + } + } + if (current_level < 0) + current_level = 0; + + if (current_level != prev_current_level) { + CPRINTS("temp: %d, prev_temp: %d", temp[temp_sensor], + prev_temp[temp_sensor]); + CPRINTS("current_level: %d", current_level); + } + + prev_temp[temp_sensor] = temp[temp_sensor]; + prev_current_level = current_level; + + switch (fan) { + case FAN_CH_0: + new_rpm = fan_table[current_level].rpm[FAN_CH_0]; + break; + default: + break; + } + return new_rpm; +} +void board_override_fan_control(int fan, int *temp) +{ + if (chipset_in_state(CHIPSET_STATE_ON)) { + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), + fan_table_to_rpm(FAN_CH(fan), temp, + TEMP_SENSOR_1_DDR_SOC)); + } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* Stop fan when enter S0ix */ + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), 0); + } +} diff --git a/board/primus/usbc_config.c b/board/primus/usbc_config.c new file mode 100644 index 0000000000..aca27e9c8e --- /dev/null +++ b/board/primus/usbc_config.c @@ -0,0 +1,291 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC_BC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC_BC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_RT, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_RT, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC_BC, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC_BC, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +void config_usb_db_type(void) +{ + enum ec_cfg_usb_db_type db_type = ec_cfg_usb_db_type(); + + /* + * TODO(b/180434685): implement multiple DB types + */ + + CPRINTS("Configured USB DB type number is %d", db_type); +} + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum gpio_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = GPIO_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C1) { + rst_signal = GPIO_USB_C1_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + gpio_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + + /* This will allow power saving on BB retimer */ + gpio_set_level(GPIO_TBT_PWR_EN, 1); + } else { + gpio_set_level(rst_signal, 0); + msleep(1); + gpio_set_level(GPIO_TBT_PWR_EN, 0); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + /* Using RT1716, no reset available for TCPC on port 0/ port 2 */ +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + if (ec_cfg_mlb_usb()) + return TBT_SS_U32_GEN1_GEN2; + + return TBT_SS_TBT_GEN3; +} diff --git a/board/primus/usbc_config.h b/board/primus/usbc_config.h new file mode 100644 index 0000000000..1e087f083c --- /dev/null +++ b/board/primus/usbc_config.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Primus board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void config_usb_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/primus/vif_override.xml b/board/primus/vif_override.xml new file mode 100644 index 0000000000..5f9cb6eed1 --- /dev/null +++ b/board/primus/vif_override.xml @@ -0,0 +1,117 @@ + + + 2 + 0 + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 463E + + + + + + Gen 3 (40Gb) + + + + USB 3.2 Gen 2x1 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + + + Gen 3 (40Gb) + + + USB 3.2 Gen 2x1 + + + + + + + + + + + + + 3A @ 5V + + + + 50 msec + 3600 mA + + + + + PDUSB Peripheral + PDUSB Host + + + + + + + + + + + HBR3 + 4 Lanes + + + diff --git a/board/prism/board.c b/board/prism/board.c new file mode 100644 index 0000000000..efdc4f5cd1 --- /dev/null +++ b/board/prism/board.c @@ -0,0 +1,366 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "clock.h" +#include "common.h" +#include "ec_commands.h" +#include "ec_version.h" +#include "gpio.h" +#include "hooks.h" +#include "hwtimer.h" +#include "i2c.h" +#include "printf.h" +#include "registers.h" +#include "rgb_keyboard.h" +#include "rollback.h" +#include "spi.h" +#include "system.h" +#include "task.h" +#include "timer.h" +#include "update_fw.h" +#include "usart-stm32f0.h" +#include "usart_rx_dma.h" +#include "usart_tx_dma.h" +#include "usb_api.h" +#include "usb_descriptor.h" +#include "util.h" + +#include + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#ifdef SECTION_IS_RW +#define CROS_EC_SECTION "RW" +#else +#define CROS_EC_SECTION "RO" +#endif + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/****************************************************************************** + * Define the strings used in our USB descriptors. + */ +const void *const usb_strings[] = { + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Prism"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = + USB_STRING_DESC(CROS_EC_SECTION ":" CROS_EC_VERSION32), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), + [USB_STR_HOSTCMD_NAME] = USB_STRING_DESC("Host command"), +}; + +BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); + +/****************************************************************************** + * Support I2C bridging over USB. + */ + +#ifdef SECTION_IS_RW +const struct spi_device_t spi_devices[] = { + [SPI_RGB0_DEVICE_ID] = { CONFIG_SPI_RGB_PORT, 2, /* 2: Fpclk/8 = 48Mhz/8 + = 6Mhz */ + GPIO_SPI1_CS1_L }, + [SPI_RGB1_DEVICE_ID] = { CONFIG_SPI_RGB_PORT, 2, GPIO_SPI1_CS2_L }, +}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +/* + * RGB Keyboard config & data + */ +BUILD_ASSERT(RGB_GRID0_ROW == RGB_GRID1_ROW); + +extern struct rgbkbd_drv is31fl3743b_drv; + +static struct rgb_s grid0[RGB_GRID0_COL * RGB_GRID0_ROW]; +static struct rgb_s grid1[RGB_GRID1_COL * RGB_GRID1_ROW]; + +struct rgbkbd rgbkbds[] = { + [0] = { + .cfg = &(const struct rgbkbd_cfg) { + .drv = &is31fl3743b_drv, + .spi = SPI_RGB0_DEVICE_ID, + .col_len = RGB_GRID0_COL, + .row_len = RGB_GRID0_ROW, + }, + .buf = grid0, + }, + [1] = { + .cfg = &(const struct rgbkbd_cfg) { + .drv = &is31fl3743b_drv, + .spi = SPI_RGB1_DEVICE_ID, + .col_len = RGB_GRID1_COL, + .row_len = RGB_GRID1_ROW, + }, + .buf = grid1, + }, +}; +const uint8_t rgbkbd_count = ARRAY_SIZE(rgbkbds); +const uint8_t rgbkbd_hsize = RGB_GRID0_COL + RGB_GRID1_COL; +const uint8_t rgbkbd_vsize = RGB_GRID0_ROW; + +enum ec_rgbkbd_type rgbkbd_type = EC_RGBKBD_TYPE_PER_KEY; + +#define LED(x, y) RGBKBD_COORD((x), (y)) +#define DELM RGBKBD_DELM + +const uint8_t rgbkbd_map[] = { + DELM, /* 0: (null) */ + LED(0, 1), LED(0, 2), DELM, /* 1: ~ ` */ + LED(1, 1), LED(1, 2), DELM, /* 2: ! 1 */ + LED(2, 1), LED(2, 2), DELM, /* 3: @ 2 */ + LED(3, 1), LED(3, 2), DELM, /* 4: # 3 */ + LED(4, 1), LED(4, 2), DELM, /* 5: $ 4 */ + LED(5, 1), LED(5, 2), DELM, /* 6: % 5 */ + LED(6, 1), LED(6, 2), DELM, /* 7: ^ 6 */ + LED(7, 1), LED(7, 2), DELM, /* 8: & 7 */ + LED(8, 1), LED(8, 2), DELM, /* 9: * 8 */ + LED(9, 1), LED(9, 2), DELM, /* 10: ( 9 */ + LED(10, 1), LED(10, 2), DELM, /* 11: ) 0 */ + LED(11, 1), LED(11, 2), DELM, /* 12: _ - */ + LED(12, 1), LED(12, 2), DELM, /* 13: + = */ + DELM, /* 14: (null) */ + LED(13, 1), LED(13, 2), DELM, /* 15: backspace */ + LED(0, 3), LED(15, 2), DELM, /* 16: tab */ + LED(1, 3), DELM, /* 17: q */ + LED(2, 3), DELM, /* 18: w */ + LED(3, 3), DELM, /* 19: e */ + LED(4, 3), DELM, /* 20: r */ + LED(5, 3), DELM, /* 21: t */ + LED(6, 3), DELM, /* 22: y */ + LED(7, 3), DELM, /* 23: u */ + LED(8, 3), DELM, /* 24: i */ + LED(9, 3), DELM, /* 25: o */ + LED(10, 3), DELM, /* 26: p */ + LED(11, 3), LED(12, 3), DELM, /* 27: [ { */ + LED(13, 3), LED(14, 3), DELM, /* 28: ] } */ + LED(15, 3), LED(16, 3), DELM, /* 29: \ | */ + LED(0, 4), LED(1, 4), DELM, /* 30: caps lock */ + LED(2, 4), DELM, /* 31: a */ + LED(3, 4), DELM, /* 32: s */ + LED(4, 4), DELM, /* 33: d */ + LED(5, 4), DELM, /* 34: f */ + LED(6, 4), DELM, /* 35: g */ + LED(7, 4), DELM, /* 36: h */ + LED(8, 4), DELM, /* 37: j */ + LED(9, 4), DELM, /* 38: k */ + LED(10, 4), DELM, /* 39: l */ + LED(11, 4), LED(12, 4), DELM, /* 40: ; : */ + LED(13, 4), LED(14, 4), DELM, /* 41: " ' */ + DELM, /* 42: (null) */ + LED(15, 4), LED(16, 4), DELM, /* 43: enter */ + LED(0, 5), LED(1, 5), LED(2, 5), DELM, /* 44: L-shift */ + DELM, /* 45: (null) */ + LED(3, 5), DELM, /* 46: z */ + LED(4, 5), DELM, /* 47: x */ + LED(5, 5), DELM, /* 48: c */ + LED(6, 5), DELM, /* 49: v */ + LED(7, 5), DELM, /* 50: b */ + LED(8, 5), DELM, /* 51: n */ + LED(9, 5), DELM, /* 52: m */ + LED(10, 5), LED(11, 5), DELM, /* 53: , < */ + LED(12, 5), LED(13, 5), DELM, /* 54: . > */ + LED(14, 5), LED(15, 5), DELM, /* 55: / ? */ + DELM, /* 56: (null) */ + LED(16, 5), LED(17, 5), LED(18, 5), DELM, /* 57: R-shift */ + LED(17, 4), LED(18, 4), LED(19, 4), DELM, /* 58: L-ctrl */ + LED(15, 0), DELM, /* 59: power */ + LED(17, 2), LED(18, 2), LED(19, 2), DELM, /* 60: L-alt */ + LED(17, 3), LED(18, 3), LED(19, 3), LED(20, 3), + LED(21, 3), LED(16, 2), DELM, /* 61: space */ + LED(20, 2), DELM, /* 62: R-alt */ + DELM, /* 63: (null) */ + LED(21, 2), DELM, /* 64: R-ctrl */ + DELM, /* 65: (null) */ + DELM, /* 66: (null) */ + DELM, /* 67: (null) */ + DELM, /* 68: (null) */ + DELM, /* 69: (null) */ + DELM, /* 70: (null) */ + DELM, /* 71: (null) */ + DELM, /* 72: (null) */ + DELM, /* 73: (null) */ + DELM, /* 74: (null) */ + DELM, /* 75: (null) */ + DELM, /* 76: (null) */ + DELM, /* 77: (null) */ + DELM, /* 78: (null) */ + LED(19, 5), DELM, /* 79: left */ + DELM, /* 80: (null) */ + DELM, /* 81: (null) */ + DELM, /* 82: (null) */ + LED(20, 4), DELM, /* 83: up */ + LED(20, 5), DELM, /* 84: down */ + DELM, /* 85: (null) */ + DELM, /* 86: (null) */ + DELM, /* 87: (null) */ + DELM, /* 88: (null) */ + LED(21, 5), DELM, /* 89: right */ + DELM, /* 90: (null) */ + DELM, /* 91: (null) */ + DELM, /* 92: (null) */ + DELM, /* 93: (null) */ + DELM, /* 94: (null) */ + DELM, /* 95: (null) */ + DELM, /* 96: (null) */ + DELM, /* 97: (null) */ + DELM, /* 98: (null) */ + DELM, /* 99: (null) */ + DELM, /* 100: (null) */ + DELM, /* 101: (null) */ + DELM, /* 102: (null) */ + DELM, /* 103: (null) */ + DELM, /* 104: (null) */ + DELM, /* 105: (null) */ + DELM, /* 106: (null) */ + DELM, /* 107: (null) */ + DELM, /* 108: (null) */ + DELM, /* 109: (null) */ + LED(0, 0), DELM, /* 110: esc */ + LED(1, 0), DELM, /* T1: previous page */ + LED(2, 0), DELM, /* T2: refresh */ + LED(3, 0), DELM, /* T3: full screen */ + LED(4, 0), DELM, /* T4: windows */ + LED(5, 0), DELM, /* T5: screenshot */ + LED(6, 0), DELM, /* T6: brightness down */ + LED(7, 0), DELM, /* T7: brightness up */ + LED(8, 0), DELM, /* T8: KB backlight off */ + LED(9, 0), DELM, /* T9: play/pause */ + LED(10, 0), DELM, /* T10: mute microphone */ + LED(11, 0), DELM, /* T11: mute speakers */ + LED(12, 0), DELM, /* T12: volume down */ + LED(13, 0), DELM, /* T13: volume up */ + DELM, /* T14: (null) */ + DELM, /* T15: (null) */ + DELM, /* 126: (null) */ + DELM, /* 127: (null) */ +}; +#undef LED +#undef DELM +const size_t rgbkbd_map_size = ARRAY_SIZE(rgbkbd_map); + +__override void board_kblight_shutdown(void) +{ + gpio_set_level(GPIO_RGBKBD_POWER, 0); +} + +__override void board_kblight_init(void) +{ + /* + * Keep hardware stand-by always on since it doesn't allow scale and PWM + * registers to be written. We use software stand-by for enable/disable. + */ + gpio_set_level(GPIO_RGBKBD_SDB_L, 1); + gpio_set_level(GPIO_RGBKBD_POWER, 1); + msleep(10); +} + +#endif + +/****************************************************************************** + * Initialize board. + */ +static int has_keyboard_backlight; + +#ifdef SECTION_IS_RW +static void board_init(void) +{ + spi_enable(&spi_devices[SPI_RGB0_DEVICE_ID], 0); + spi_enable(&spi_devices[SPI_RGB1_DEVICE_ID], 0); + + /* Set all SPI pins to high speed */ + /* pins A1, 2, 5, 6, 7 */ + STM32_GPIO_OSPEEDR(GPIO_A) |= 0x0000fc3c; + + /* Reset SPI1 */ + STM32_RCC_APB2RSTR |= STM32_RCC_PB2_SPI1; + STM32_RCC_APB2RSTR &= ~STM32_RCC_PB2_SPI1; + /* Enable clocks to SPI1 module */ + STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI1; + + clock_wait_bus_cycles(BUS_APB, 1); + /* Enable SPI for RGB matrix. */ + gpio_config_module(MODULE_SPI_CONTROLLER, 1); + spi_enable(&spi_devices[SPI_RGB0_DEVICE_ID], 1); + spi_enable(&spi_devices[SPI_RGB1_DEVICE_ID], 1); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_INIT_SPI - 1); +#endif /* SECTION_IS_RW */ + +void board_config_pre_init(void) +{ + /* enable SYSCFG clock */ + STM32_RCC_APB2ENR |= BIT(0); + + /* Remap USART DMA to match the USART driver */ + /* + * the DMA mapping is : + * Chan 4 : USART1_TX + * Chan 5 : USART1_RX + */ + STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10); /* Remap USART1 RX/TX DMA */ +} + +int board_has_keyboard_backlight(void) +{ + return has_keyboard_backlight; +} + +/* + * Get entropy based on Clock Recovery System, which is enabled on hammer to + * synchronize USB SOF with internal oscillator. + */ +int board_get_entropy(void *buffer, int len) +{ + int i = 0; + uint8_t *data = buffer; + uint32_t start; + /* We expect one SOF per ms, so wait at most 2ms. */ + const uint32_t timeout = 2 * MSEC; + + for (i = 0; i < len; i++) { + STM32_CRS_ICR |= STM32_CRS_ICR_SYNCOKC; + start = __hw_clock_source_read(); + while (!(STM32_CRS_ISR & STM32_CRS_ISR_SYNCOKF)) { + if ((__hw_clock_source_read() - start) > timeout) + return 0; + usleep(500); + } + /* Pick 8 bits, including FEDIR and 7 LSB of FECAP. */ + data[i] = STM32_CRS_ISR >> 15; + } + + return 1; +} + +/* + * Generate a USB serial number from unique chip ID. + */ +__override const char *board_read_serial(void) +{ + static char str[CONFIG_SERIALNO_LEN]; + + if (str[0] == '\0') { + uint8_t *id; + int pos = 0; + int idlen = system_get_chip_unique_id(&id); + int i; + + for (i = 0; i < idlen && pos < sizeof(str); i++, pos += 2) { + if (snprintf(&str[pos], sizeof(str) - pos, "%02x", + id[i]) < 0) + return NULL; + } + } + + return str; +} + +__override int board_write_serial(const char *serialno) +{ + return 0; +} diff --git a/board/prism/board.h b/board/prism/board.h new file mode 100644 index 0000000000..c4bf4de58e --- /dev/null +++ b/board/prism/board.h @@ -0,0 +1,223 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Prism configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Prism doesn't use WP GPIO, set WP enabled */ +#ifdef SECTION_IS_RO +#define CONFIG_WP_ALWAYS +#endif + +/* TODO: May define FLASH_PSTATE_LOCKED prior to building MP FW. */ +#undef CONFIG_FLASH_PSTATE_LOCKED + +/* USB ID for Prism */ +#define CONFIG_USB_PID 0x5022 + +/* 48 MHz SYSCLK clock frequency */ +#define CPU_CLOCK 48000000 + +/* For RGB keyboard control */ +#ifdef SECTION_IS_RW +#define CONFIG_KEYBOARD_BACKLIGHT +#define CONFIG_RGB_KEYBOARD +#define GPIO_RGBKBD_SDB_L GPIO_SDB_L +#define GPIO_RGBKBD_POWER GPIO_L_POWER +#define CONFIG_LED_DRIVER_IS31FL3743B +#define SPI_RGB0_DEVICE_ID 0 +#define SPI_RGB1_DEVICE_ID 1 +#define RGB_GRID0_COL 11 +#define RGB_GRID0_ROW 6 +#define RGB_GRID1_COL 11 +#define RGB_GRID1_ROW 6 + +/* Enable control of SPI over USB */ +#define CONFIG_SPI_CONTROLLER +#define CONFIG_STM32_SPI1_CONTROLLER +/* Enable SPI controller xfer command */ +#define CONFIG_CMD_SPI_XFER + +#define CONFIG_SPI_RGB_PORT 0 + +#define CONFIG_IS31FL3743B_LATE_INIT + +#endif /* SECTION_IS_RW */ + +/* + * Flash layout: we redefine the sections offsets and sizes as we want to + * include a rollback region, and will use RO/RW regions of different sizes. + */ +#undef _IMAGE_SIZE +#undef CONFIG_ROLLBACK_OFF +#undef CONFIG_ROLLBACK_SIZE +#undef CONFIG_FLASH_PSTATE +#undef CONFIG_FW_PSTATE_SIZE +#undef CONFIG_FW_PSTATE_OFF +#undef CONFIG_SHAREDLIB_SIZE +#undef CONFIG_RO_MEM_OFF +#undef CONFIG_RO_STORAGE_OFF +#undef CONFIG_RO_SIZE +#undef CONFIG_RW_MEM_OFF +#undef CONFIG_RW_STORAGE_OFF +#undef CONFIG_RW_SIZE +#undef CONFIG_EC_PROTECTED_STORAGE_OFF +#undef CONFIG_EC_PROTECTED_STORAGE_SIZE +#undef CONFIG_EC_WRITABLE_STORAGE_OFF +#undef CONFIG_EC_WRITABLE_STORAGE_SIZE +#undef CONFIG_WP_STORAGE_OFF +#undef CONFIG_WP_STORAGE_SIZE + +#define CONFIG_FLASH_PSTATE +/* Do not use a dedicated PSTATE bank */ +#undef CONFIG_FLASH_PSTATE_BANK + +#define CONFIG_SHAREDLIB_SIZE 0 + +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (44 * 1024) + +/* EC rollback protection block */ +#define CONFIG_ROLLBACK_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) +#define CONFIG_ROLLBACK_SIZE CONFIG_FLASH_BANK_SIZE + +#define CONFIG_RW_MEM_OFF (CONFIG_ROLLBACK_OFF + CONFIG_ROLLBACK_SIZE) +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE_BYTES - CONFIG_RW_MEM_OFF) + +#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE + +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE + +/* The UART console is on USART1 (PA9/PA10) */ +#undef CONFIG_UART_CONSOLE +#define CONFIG_UART_CONSOLE 1 + +#undef CONFIG_UART_TX_BUF_SIZE +/* Has to be power of two */ +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Optional features */ +#define CONFIG_LOW_POWER_IDLE +#define CONFIG_LTO +#define CONFIG_FORCE_CONSOLE_RESUME +#define CONFIG_MATH_UTIL + +/* USB Configuration */ +#define CONFIG_USB +#define CONFIG_STREAM_USB +#define CONFIG_USB_UPDATE + +#undef CONFIG_USB_MAXPOWER_MA +#define CONFIG_USB_MAXPOWER_MA 100 + +#define CONFIG_USB_REMOTE_WAKEUP +#define CONFIG_USB_SUSPEND + +#define CONFIG_USB_SERIALNO +/* Replaced at runtime (board_read_serial) by chip unique-id-based number. */ +#define DEFAULT_SERIALNO "Uninitialized" + +/* USB interface indexes (use define rather than enum to expand them) */ +#undef CONFIG_HOSTCMD_EVENTS +#define USB_IFACE_UPDATE 0 +#define CONFIG_HOST_INTERFACE_USB +#define USB_IFACE_HOSTCMD 1 +#define USB_IFACE_COUNT 2 + +/* USB endpoint indexes (use define rather than enum to expand them) */ +#define USB_EP_CONTROL 0 +#define USB_EP_UPDATE 1 +#define USB_EP_HOSTCMD 2 +#define USB_EP_COUNT 3 + +/* Optional features */ +#define CONFIG_BOARD_PRE_INIT +#define CONFIG_WATCHDOG_HELP + +/* No need to hibernate, remove console commands that are not very useful. */ +#undef CONFIG_HIBERNATE +#undef CONFIG_CONSOLE_CHANNEL +#undef CONFIG_CONSOLE_HISTORY +#undef CONFIG_CMD_GETTIME +#undef CONFIG_CMD_MD +#undef CONFIG_CMD_RW +#undef CONFIG_CMD_SHMEM +#undef CONFIG_CMD_TIMERINFO +#undef CONFIG_CMD_WAITMS + +#undef CONFIG_LID_SWITCH + +#define CONFIG_USB_CONSOLE_READ + +#ifdef SECTION_IS_RW + +#define CONFIG_CURVE25519 + +#define CONFIG_USB_PAIRING + +#else /* SECTION_IS_RO */ +/* Sign and switch to RW partition on boot. */ +#define CONFIG_RWSIG +#define CONFIG_RSA +#endif + +#define CONFIG_RSA_KEY_SIZE 3072 +#define CONFIG_RSA_EXPONENT_3 + +#define CONFIG_SHA256 +#ifdef SECTION_IS_RO +#define CONFIG_SHA256_UNROLLED +#endif + +#define CONFIG_RWSIG_TYPE_RWSIG + +/* + * Add rollback protection, and independent RW region protection. + */ +#define CONFIG_LIBCRYPTOC +#define CONFIG_ROLLBACK +#define CONFIG_ROLLBACK_SECRET_SIZE 32 +#define CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE 32 +#define CONFIG_FLASH_PROTECT_RW +#ifdef SECTION_IS_RW +#undef CONFIG_ROLLBACK_UPDATE +#endif + +/* Maximum current to draw. */ +#define MAX_CURRENT_MA 2000 +/* Maximum current/voltage to provide over OTG. */ +#define MAX_OTG_CURRENT_MA 2000 +#define MAX_OTG_VOLTAGE_MV 20000 + +#ifndef __ASSEMBLER__ + +/* Timer selection */ +#define TIM_CLOCK32 2 +#define TIM_WATCHDOG 16 + +#include "gpio_signal.h" + +/* USB string indexes */ +enum usb_strings { + USB_STR_DESC = 0, + USB_STR_VENDOR, + USB_STR_PRODUCT, + USB_STR_SERIALNO, + USB_STR_VERSION, + USB_STR_UPDATE_NAME, + USB_STR_HOSTCMD_NAME, + USB_STR_COUNT +}; + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/prism/build.mk b/board/prism/build.mk new file mode 100644 index 0000000000..7e37df6f7a --- /dev/null +++ b/board/prism/build.mk @@ -0,0 +1,13 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +CHIP:=stm32 +CHIP_FAMILY:=stm32f0 +CHIP_VARIANT:=stm32f07x + +# Build tests that we care about for Prism. +test-list-y=entropy rsa3 sha256 sha256_unrolled x25519 + +board-y=board.o diff --git a/board/prism/dev_key.pem b/board/prism/dev_key.pem new file mode 100644 index 0000000000..b72c787613 --- /dev/null +++ b/board/prism/dev_key.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAseZZZlXXDP+KrjqV+XhP0ZgPlU5mX4GCm27yzTqcKiFWLlHZ +3f8seGG0lKNiL7WvHim8uSEDaPbp2us4uaJ6nTHEpbSGi2QVp90tE3aJG34HyKlg +jcaE1r/0n6ynG/bf0Xx4O63Plp3Czi3TBYW49vT6+T/Jyfl2JpGQ9KNcD0umafsv +uaEmdrLGrzjN8w1mFZfwscFkfVDh0cdiFNJ+UkTSpO9/yPapXbo4/lOMwdO9xILF +cEZV9I7K7lBSvQ5Uep+w0SqNPTh2cGhoeEeDyH+Ce0LA8H7ZwbVnwLe1RswF9Wek +uzqp9lMSNkkwMtTkumTuJLLGJX9rc0MVQTKgNV8wIzizf5lkCCBCJLf7aRBaeWCJ +cXjKiavSPOZXDcnqCWqRJT3jN4ibAsU1GQtqLa8pTAi2wkE0fjuvAWK3NYuvpukg +qNq2LI+BJkF4+dCZoeB1PDNyFNzdOFvkxj2+ImS3DLlPYVng4vHsTK1HRUUpL5Ag +jjfMhMs4NC7HMOCTAgEDAoIBgHaZkO7j5LNVBx7RuVD63+EQCmOJmZUBAbz0od4n +EsbA5B7hO+lUyFBBIw3CQXUjyhQb0yYWAkX58Tyc0HvBpxN2gxkjBFztY8U+Hgz5 +sLz+r9sblbPZreR/+GpzGhKklTZS+tJz37m+gd7JN1kD0KSjUft/29v7pBm2YKMX +krTdGZv8ynvAxE8h2col3qII7rkP9cvWQv416+EvlriMVDbYjG30/9tPG5PRe1Q3 +syvifoMB2PWEOU20h0mK4dNe4d7E96s1Q+RTmTUtyipxUp6d4PIufAjMtM8yfkb0 +/0z81IsWQ0NOhefrMAi8TEcDkbyNSBPqHqbqH2FosFWo2cU3r6TXv2LdvFzc5BA+ +U6c+fXz7BDjv+NT3Bh98whKvTdJYcIgSg6vqzW7ZWJWWllZQtpJnQccIq4sPaL4S +osFg8jd1kcbjVakCN0wYtfvMa/+WBZNNsZLUHoeIJvO7qnT7VKzhceoKHCJCMxNR +Ypu5eELxCwebTXiImDqmFsKIawKBwQDpDjff6eatHbjmGV1elTyV5MLi95Tc0T7P +FZHC1KLXkA/mEuXjAGfoZuLB5a3WmrA8r8fWNZoKV+0RBKIs3at1JFxZn9YiA0Hy +5qmnYkXjMaY4p5AyO3eJsc2kbsh9r0cy2cb5GdwFDApeoVICoQh+dW9FpvIS+9AF +0DVc2/Rg//cuXLlCMonF+PZVmDxRNhjBvwvRjxeowiu2ntI4sa83nHMhXI/RfvV4 +xcSng8gSIvabUmunDcPKvqO3rnpHzVECgcEAw2oFcHDAuZ1Xuopb2ghLRK3uLQVy +BnqLu9QYk3OTe8C3PrNZ80R5MgtnZ0kP8bTZ4uE6MJ3+IMhPUCFqk9euGGdMUlU+ +SUmHie5CZPg4CwD4BUBy6dVdwId7aTxrdBOuGwwhYAhBsJxcfd3eNgiALcCoKsbi +BLhjJ9Rch2rOsnpNJVwMvFMr6RM33oQrrufe4MBhDa/QD9yDtnDYH/KPO09E6AqU +sMvBNsjbCC9rSYv+L9QkW8EUhT+wJIcqxUajAoHBAJtez+qb7x4T0JlmPj8OKGPt +10H6Yz3g1IoOYSyNweUKtUQMmUIARUWZ7IFDyTm8dX3KhTl5EVw6ngtYbB3pHPjC +6Du/5Bas1qHvG8TsLpd2btBvtXbST7EhM8L0hakfhMyRL1C76ANdXD8WNqxrWv74 +9NkZ9rdSiq6Kzj3n+ECqpMmTJiwhsS6l+Y5lfYt5ZdZ/XTZfZRssHSRp4XshH3po +TMDoX+D/TlCD2G+tMAwXTxI28m9egocpwnp0UYUziwKBwQCCRq5K9dXRE4/RsZKR +WtzYc/QeA6FZpwfSjWW3omJSgHopzOaiLaYhXO+aMLVLzeaXQNF1vqlrMDTgFkcN +OnQQRN2MONQw26+xSYGYpXqyAKVY1aHxOOkrBPzw0vJNYnQSCBZABYEgaD2pPpQk +BarJKxrHL0FYeuzFOD2vnInMUYjDkrMoN3KbYiU/AsfJ7+nrKutedTVf6FfO9eVq +obTSNNiasbh13St52zywH5zbsql1OBg9K2MDf8rDBMcuLxcCgcBfM9FWZivdG2tJ +5REvL0vPAQfcjVi4HUHvnaCuwMYEuF5T2Xf9P8d8ZflfWHaGlkl/qPvE897fns2l +PZvvhRnr9GlHKt940ZOTI2v+hjlwcHGAAQc+p7BcKeUYLChwhVK/cZ9f6ZCotZNh +543ecG4KZiJaqBZ/mDRaW7Py0w6lbOAzprrHF3ChvQ6VAllajoWx4CeINRcxX2vP +bAPZxvt0gwpoHtUAsZo/bKEF0sM5qM/fK43gH5KhJeunq/xHO7E= +-----END RSA PRIVATE KEY----- diff --git a/board/prism/ec.tasklist b/board/prism/ec.tasklist new file mode 100644 index 0000000000..810ef8489b --- /dev/null +++ b/board/prism/ec.tasklist @@ -0,0 +1,14 @@ +/* Copyright 2016 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS_RO(RWSIG, rwsig_task, NULL, 1280) \ + TASK_ALWAYS (HOOKS, hook_task, NULL, 1024) \ + TASK_ALWAYS_RW(RGBKBD, rgbkbd_task, NULL, 2048) \ + TASK_ALWAYS (HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS (CONSOLE, console_task, NULL, 1024) diff --git a/board/prism/gpio.inc b/board/prism/gpio.inc new file mode 100644 index 0000000000..2b8f2ee9b8 --- /dev/null +++ b/board/prism/gpio.inc @@ -0,0 +1,25 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifdef SECTION_IS_RW + +GPIO(SDB_L, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SPI1_CS1_L, PIN(A, 1), GPIO_OUT_HIGH) +GPIO(SPI1_CS2_L, PIN(A, 2), GPIO_OUT_HIGH) +GPIO(L_POWER, PIN(A, 3), GPIO_OUT_LOW) + +/* SPI Controller: PA5, 6, 7 */ +ALTERNATE(PIN_MASK(A, 0x00e0), 0, MODULE_SPI_CONTROLLER, GPIO_PULL_UP) + + +#endif /* SECTION_IS_RW */ + +/* USART1: PA09/PA10 - Servo stm32 console UART */ +ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, GPIO_PULL_UP) + +UNIMPLEMENTED(ENTERING_RW) +UNIMPLEMENTED(WP_L) diff --git a/board/puff/board.c b/board/puff/board.c index c034e06e45..7e5c2ad8e6 100644 --- a/board/puff/board.c +++ b/board/puff/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,10 +6,9 @@ /* Puff board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "chipset.h" #include "common.h" #include "core/cortex-m/cpu.h" @@ -37,8 +36,8 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_common.h" @@ -46,8 +45,8 @@ #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void power_monitor(void); DECLARE_DEFERRED(power_monitor); @@ -89,8 +88,8 @@ uint16_t tcpc_get_alert_status(void) } /* Called when the charge manager has switched to a new port. */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* Blink alert if insufficient power per system_can_boot_ap(). */ int insufficient_power = @@ -106,14 +105,14 @@ static int32_t base_5v_power; * Power usage for each port as measured or estimated. * Units are milliwatts (5v x ma current) */ -#define PWR_BASE_LOAD (5*1335) -#define PWR_FRONT_HIGH (5*1603) -#define PWR_FRONT_LOW (5*963) -#define PWR_REAR (5*1075) -#define PWR_HDMI (5*562) -#define PWR_C_HIGH (5*3740) -#define PWR_C_LOW (5*2090) -#define PWR_MAX (5*10000) +#define PWR_BASE_LOAD (5 * 1335) +#define PWR_FRONT_HIGH (5 * 1603) +#define PWR_FRONT_LOW (5 * 963) +#define PWR_REAR (5 * 1075) +#define PWR_HDMI (5 * 562) +#define PWR_C_HIGH (5 * 3740) +#define PWR_C_LOW (5 * 2090) +#define PWR_MAX (5 * 10000) /* * Update the 5V power usage, assuming no throttling, @@ -186,16 +185,14 @@ static const struct { int current; } bj_power[] = { { /* 0 - 65W (also default) */ - .voltage = 19000, - .current = 3420 - }, + .voltage = 19000, + .current = 3420 }, { /* 1 - 90W */ - .voltage = 19000, - .current = 4740 - }, + .voltage = 19000, + .current = 4740 }, }; -#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ /* Debounced connection state of the barrel jack */ static int8_t adp_connected = -1; static void adp_connect_deferred(void) @@ -238,31 +235,29 @@ static void adp_state_init(void) /* Report charge state from the barrel jack. */ adp_connect_deferred(); } -DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_CHARGE_MANAGER_INIT + 1); - +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_FAN] = { .channel = 5, - .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, - [PWM_CH_LED_RED] = { .channel = 0, - .flags = PWM_CONFIG_ACTIVE_LOW | - PWM_CONFIG_DSLEEP, - .freq = 2000 }, - [PWM_CH_LED_GREEN] = { .channel = 2, - .flags = PWM_CONFIG_ACTIVE_LOW | - PWM_CONFIG_DSLEEP, - .freq = 2000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 0, + .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_LED_GREEN] = { .channel = 2, + .flags = PWM_CONFIG_ACTIVE_LOW | + PWM_CONFIG_DSLEEP, + .freq = 2000 }, }; /******************************************************************************/ @@ -278,22 +273,44 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .flags = TCPC_FLAGS_RESET_ACTIVE_HIGH, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, }; /******************************************************************************/ /* I2C port map configuration */ const struct i2c_port_t i2c_ports[] = { - {"ina", I2C_PORT_INA, 400, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"ppc0", I2C_PORT_PPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"power", I2C_PORT_POWER, 400, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "ina", + .port = I2C_PORT_INA, + .kbps = 400, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "ppc0", + .port = I2C_PORT_PPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 400, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -349,15 +366,14 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); /******************************************************************************/ /* Wake up pins */ -const enum gpio_signal hibernate_wake_pins[] = { -}; +const enum gpio_signal hibernate_wake_pins[] = {}; const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /******************************************************************************/ /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = -1, }; @@ -376,42 +392,52 @@ BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /******************************************************************************/ /* Thermal control; drive fan based on temperature sensors. */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(68), - [EC_TEMP_THRESH_HALT] = C_TO_K(78), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(58), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(41), - .temp_fan_max = C_TO_K(72), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(78), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(58), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(41), \ + .temp_fan_max = C_TO_K(72), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; -const static struct ec_thermal_config thermal_b = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(78), - [EC_TEMP_THRESH_HALT] = C_TO_K(85), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = 0, - }, -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(78), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_b = THERMAL_B; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_CORE] = thermal_a, + [TEMP_SENSOR_CORE] = THERMAL_A, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -480,7 +506,7 @@ static void board_init(void) * button is not available. */ if (board_version < 2) - button_disable_gpio(GPIO_EC_RECOVERY_BTN_ODL); + button_disable_gpio(BUTTON_RECOVERY); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -498,16 +524,13 @@ static void board_chipset_startup(void) if (ppc_is_sourcing_vbus(0)) ppc_vbus_source_enable(0, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, - HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); /******************************************************************************/ /* USB-C PPC Configuration */ struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { - [USB_PD_PORT_TCPC_0] = { - .i2c_port = I2C_PORT_PPC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, + [USB_PD_PORT_TCPC_0] = { .i2c_port = I2C_PORT_PPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, }; unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); @@ -540,14 +563,12 @@ static void board_tcpc_init(void) /* * By default configured as output low. */ - gpio_set_flags(GPIO_USB_A4_OC_ODL, - GPIO_INPUT | GPIO_INT_BOTH); + gpio_set_flags(GPIO_USB_A4_OC_ODL, GPIO_INPUT | GPIO_INT_BOTH); gpio_enable_interrupt(GPIO_USB_A4_OC_ODL); } else { /* Ensure no interrupts from pin */ gpio_disable_interrupt(GPIO_USB_A4_OC_ODL); } - } /* Make sure this is called after fw_config is initialised */ DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 2); @@ -666,8 +687,8 @@ void board_enable_s0_rails(int enable) unsigned int ec_config_get_bj_power(void) { - unsigned int bj = - (fw_config & EC_CFG_BJ_POWER_MASK) >> EC_CFG_BJ_POWER_L; + unsigned int bj = (fw_config & EC_CFG_BJ_POWER_MASK) >> + EC_CFG_BJ_POWER_L; /* Out of range value defaults to 0 */ if (bj >= ARRAY_SIZE(bj_power)) bj = 0; @@ -742,23 +763,23 @@ DECLARE_HOOK(HOOK_INIT, setup_thermal, HOOK_PRIO_DEFAULT - 1); * * All measurements are in milliwatts. */ -#define THROT_TYPE_A BIT(0) -#define THROT_TYPE_C BIT(1) -#define THROT_PROCHOT BIT(2) +#define THROT_TYPE_A BIT(0) +#define THROT_TYPE_C BIT(1) +#define THROT_PROCHOT BIT(2) /* * Power gain if front USB A ports are limited. */ -#define POWER_GAIN_TYPE_A 3200 +#define POWER_GAIN_TYPE_A 3200 /* * Power gain if Type C port is limited. */ -#define POWER_GAIN_TYPE_C 8800 +#define POWER_GAIN_TYPE_C 8800 /* * Power is averaged over 10 ms, with a reading every 2 ms. */ -#define POWER_DELAY_MS 2 -#define POWER_READINGS (10/POWER_DELAY_MS) +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) static void power_monitor(void) { @@ -773,8 +794,7 @@ static void power_monitor(void) * If CPU is off or suspended, no need to throttle * or restrict power. */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF | - CHIPSET_STATE_SUSPEND)) { + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { /* * Slow down monitoring, assume no throttling required. */ @@ -802,7 +822,7 @@ static void power_monitor(void) */ power = (adc_read_channel(ADC_VBUS) * adc_read_channel(ADC_PPVAR_IMON)) / - 1000; + 1000; /* Init power table */ if (history[0] == 0) { for (i = 0; i < POWER_READINGS; i++) @@ -829,8 +849,7 @@ static void power_monitor(void) * For barrel-jack supplies, the rating can be * exceeded briefly, so use the average. */ - if (charge_manager_get_supplier() == - CHARGE_SUPPLIER_PD) + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) power = max; else power = total / POWER_READINGS; @@ -922,8 +941,9 @@ static void power_monitor(void) gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); } if (diff & THROT_TYPE_C) { - enum tcpc_rp_value rp = (new_state & THROT_TYPE_C) - ? TYPEC_RP_1A5 : TYPEC_RP_3A0; + enum tcpc_rp_value rp = (new_state & THROT_TYPE_C) ? + TYPEC_RP_1A5 : + TYPEC_RP_3A0; ppc_set_vbus_source_current_limit(0, rp); tcpm_select_rp_value(0, rp); diff --git a/board/puff/board.h b/board/puff/board.h index 57284761fa..59c177c604 100644 --- a/board/puff/board.h +++ b/board/puff/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,11 +12,11 @@ #define CONFIG_UART_TX_BUF_SIZE 4096 /* NPCX7 config */ -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ -#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ /* Internal SPI flash on NPCX796FC is 512 kB */ -#define CONFIG_FLASH_SIZE (512 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ @@ -31,16 +31,16 @@ /* TODO: (b/143496253) re-enable CEC */ /* #define CONFIG_CEC */ #define CONFIG_CRC8 -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_EMULATED_SYSRQ #undef CONFIG_KEYBOARD_BOOT_KEYS -#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_USE_HOST_EVENT #undef CONFIG_KEYBOARD_RUNTIME_KEYS #undef CONFIG_HIBERNATE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #define CONFIG_LED_COMMON -#undef CONFIG_LID_SWITCH +#undef CONFIG_LID_SWITCH #define CONFIG_LTO #define CONFIG_PWM #define CONFIG_VBOOT_EFS2 @@ -49,9 +49,6 @@ #define CONFIG_VSTORE_SLOT_COUNT 1 #define CONFIG_SHA256 -#define CONFIG_SUPPRESSED_HOST_COMMANDS \ - EC_CMD_CONSOLE_SNAPSHOT, EC_CMD_CONSOLE_READ, EC_CMD_PD_GET_LOG_ENTRY - /* EC Commands */ #define CONFIG_CMD_BUTTON /* Include CLI command needed to support CCD testing. */ @@ -88,7 +85,7 @@ #define CONFIG_CPU_PROCHOT_ACTIVE_LOW /* Dedicated barreljack charger port */ -#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT #define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 #define DEDICATED_CHARGE_PORT 1 @@ -107,21 +104,22 @@ #define CONFIG_INA3221 /* b/143501304 */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 4000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 2000 /* us */ -#define PD_VCONN_SWAP_DELAY 8000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 4000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 2000 /* us */ +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +#define CONFIG_USBC_VCONN_SWAP_DELAY_US 8000 /* us */ -#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON -#define PD_MAX_POWER_MW 100000 -#define PD_MAX_CURRENT_MA 5000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 /* Fan and temp. */ #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 0 #define CONFIG_TEMP_SENSOR -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_ROA_RAILS +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B #define CONFIG_THROTTLE_AP @@ -138,13 +136,12 @@ #define CONFIG_USB_PD_DECODE_SOP #undef CONFIG_USB_CHARGER #define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PID 0x5040 +#define CONFIG_USB_PID 0x5040 #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_DISCHARGE_PPC #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_PORT_MAX_COUNT 1 #define CONFIG_USB_PD_VBUS_DETECT_PPC #define CONFIG_USBC_PPC_SN5S330 @@ -159,7 +156,7 @@ #define CONFIG_USBC_VCONN #define CONFIG_USBC_VCONN_SWAP -#define USB_PD_PORT_TCPC_0 0 +#define USB_PD_PORT_TCPC_0 0 #define BOARD_TCPC_C0_RESET_HOLD_DELAY ANX74XX_RESET_HOLD_MS #define BOARD_TCPC_C0_RESET_POST_DELAY ANX74XX_RESET_HOLD_MS @@ -170,16 +167,19 @@ /* I2C Bus Configuration */ #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define I2C_PORT_INA NPCX_I2C_PORT0_0 -#define I2C_PORT_PPC0 NPCX_I2C_PORT1_0 -#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER +#define I2C_PORT_INA NPCX_I2C_PORT0_0 +#define I2C_PORT_PPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 #define PP5000_PGOOD_POWER_SIGNAL_MASK POWER_SIGNAL_MASK(PP5000_A_PGOOD) +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL + #ifndef __ASSEMBLER__ #include "gpio_signal.h" @@ -191,11 +191,11 @@ enum charge_port { }; enum adc_channel { - ADC_SNS_PP3300, /* ADC2 */ - ADC_SNS_PP1050, /* ADC7 */ - ADC_VBUS, /* ADC4 */ - ADC_PPVAR_IMON, /* ADC9 */ - ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_SNS_PP3300, /* ADC2 */ + ADC_SNS_PP1050, /* ADC7 */ + ADC_VBUS, /* ADC4 */ + ADC_PPVAR_IMON, /* ADC9 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ /* Number of ADC channels */ ADC_CH_COUNT }; @@ -220,11 +220,7 @@ enum mft_channel { MFT_CH_COUNT, }; -enum temp_sensor_id { - TEMP_SENSOR_CORE, - TEMP_SENSOR_COUNT -}; - +enum temp_sensor_id { TEMP_SENSOR_CORE, TEMP_SENSOR_COUNT }; /* Board specific handlers */ void board_reset_pd_mcu(void); @@ -238,20 +234,20 @@ void show_critical_error(void); /* * Barrel-jack power (4 bits). */ -#define EC_CFG_BJ_POWER_L 0 -#define EC_CFG_BJ_POWER_H 3 +#define EC_CFG_BJ_POWER_L 0 +#define EC_CFG_BJ_POWER_H 3 #define EC_CFG_BJ_POWER_MASK GENMASK(EC_CFG_BJ_POWER_H, EC_CFG_BJ_POWER_L) /* * USB Connector 4 not present (1 bit). */ -#define EC_CFG_NO_USB4_L 4 -#define EC_CFG_NO_USB4_H 4 +#define EC_CFG_NO_USB4_L 4 +#define EC_CFG_NO_USB4_H 4 #define EC_CFG_NO_USB4_MASK GENMASK(EC_CFG_NO_USB4_H, EC_CFG_NO_USB4_L) /* * Thermal solution config (3 bits). */ -#define EC_CFG_THERMAL_L 5 -#define EC_CFG_THERMAL_H 7 +#define EC_CFG_THERMAL_L 5 +#define EC_CFG_THERMAL_H 7 #define EC_CFG_THERMAL_MASK GENMASK(EC_CFG_THERMAL_H, EC_CFG_THERMAL_L) unsigned int ec_config_get_bj_power(void); @@ -261,29 +257,30 @@ unsigned int ec_config_get_thermal_solution(void); #endif /* !__ASSEMBLER__ */ /* Pin renaming */ -#define GPIO_WP_L GPIO_EC_WP_ODL -#define GPIO_PP5000_A_PG_OD GPIO_PG_PP5000_A_OD -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL -#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_AC_PRESENT GPIO_BJ_ADP_PRESENT_L +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_PP5000_A_PG_OD GPIO_PG_PP5000_A_OD +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL +#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_ROA_RAILS +#define GPIO_AC_PRESENT GPIO_BJ_ADP_PRESENT_L /* * There is no RSMRST input, so alias it to the output. This short-circuits * common_intel_x86_handle_rsmrst. */ -#define GPIO_RSMRST_L_PGOOD GPIO_PCH_RSMRST_L +#define GPIO_PG_EC_RSMRST_ODL GPIO_PCH_RSMRST_L #endif /* __CROS_EC_BOARD_H */ diff --git a/board/puff/build.mk b/board/puff/build.mk index e9968d5710..3edfc84c2f 100644 --- a/board/puff/build.mk +++ b/board/puff/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/puff/ec.tasklist b/board/puff/ec.tasklist index ae10417dff..d579f65fd9 100644 --- a/board/puff/ec.tasklist +++ b/board/puff/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/puff/gpio.inc b/board/puff/gpio.inc index 7e62488cee..5f7650a682 100644 --- a/board/puff/gpio.inc +++ b/board/puff/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -25,12 +25,12 @@ GPIO_INT(PG_VPRIM_CORE_A_OD, PIN(2, 3), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PG_PP1050_A_OD, PIN(2, 2), GPIO_INT_BOTH, power_signal_interrupt) /* EC output, but also interrupt so this can be polled as a power signal */ GPIO_INT(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUTPUT | GPIO_INT_F_RISING | GPIO_INT_F_FALLING, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_PP2500_DRAM_U_OD, PIN(2, 0), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PG_PP1200_U_OD, PIN(2, 1), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, slp_s3_interrupt) #endif GPIO_INT(PG_PP950_VCCIO_OD, PIN(1, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -64,7 +64,7 @@ GPIO_INT(USB_A4_OC_ODL, PIN(B, 0), GPIO_OUT_LOW | GPIO_INT_BOTH, port_ocp GPIO(EC_PCH_PWROK, PIN(0, 5), GPIO_OUT_LOW) GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) -GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) GPIO(EC_PROCHOT_IN_OD, PIN(3, 4), GPIO_INPUT) GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) diff --git a/board/puff/led.c b/board/puff/led.c index ba87f05460..9cca110467 100644 --- a/board/puff/led.c +++ b/board/puff/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -19,16 +19,16 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args) +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) /* * Due to the CSME-Lite processing, upon startup the CPU transitions through * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so * delay turning off the LED during suspend/shutdown. */ -#define LED_CPU_DELAY_MS (2000 * MSEC) +#define LED_CPU_DELAY_MS (2000 * MSEC) -const enum ec_led_id supported_led_ids[] = {EC_LED_ID_POWER_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); enum led_color { @@ -89,9 +89,9 @@ static int set_color(enum ec_led_id id, enum led_color color, int duty) } } -#define LED_PULSE_US (2 * SECOND) +#define LED_PULSE_US (2 * SECOND) /* 40 msec for nice and smooth transition. */ -#define LED_PULSE_TICK_US (40 * MSEC) +#define LED_PULSE_TICK_US (40 * MSEC) /* When pulsing is enabled, brightness is incremented by every * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented @@ -214,7 +214,7 @@ void show_critical_error(void) set_color(EC_LED_ID_POWER_LED, LED_RED, 100); } -static int command_led(int argc, char **argv) +static int command_led(int argc, const char **argv) { enum ec_led_id id = EC_LED_ID_POWER_LED; diff --git a/board/puff/usb_pd_policy.c b/board/puff/usb_pd_policy.c index f3b9146b0b..e3fc86c8ca 100644 --- a/board/puff/usb_pd_policy.c +++ b/board/puff/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,16 +12,15 @@ #include "ec_commands.h" #include "gpio.h" #include "system.h" -#include "tcpci.h" -#include "tcpm.h" +#include "tcpm/tcpci.h" +#include "tcpm/tcpm.h" #include "usb_mux.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -42,11 +41,6 @@ void pd_power_supply_reset(int port) if (prev_en) pd_set_vbus_discharge(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -67,11 +61,6 @@ int pd_set_power_supply_ready(int port) if (rv) return rv; -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/board/puff/vif_override.xml b/board/puff/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/puff/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/quackingstick/base_detect.c b/board/quackingstick/base_detect.c new file mode 100644 index 0000000000..f3045897d6 --- /dev/null +++ b/board/quackingstick/base_detect.c @@ -0,0 +1,230 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Coachz base detection code */ + +#include "adc.h" +#include "base_state.h" +#include "board.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "system.h" +#include "tablet_mode.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +/* Base detection and debouncing */ +#define BASE_DETECT_EN_DEBOUNCE_US (350 * MSEC) +#define BASE_DETECT_DIS_DEBOUNCE_US (20 * MSEC) + +/* + * If the base status is unclear (i.e. not within expected ranges, read + * the ADC value again every 500ms. + */ +#define BASE_DETECT_RETRY_US (500 * MSEC) + +/* + * Lid has 604K pull-up, base has 30.1K pull-down, so the + * ADC value should be around 30.1/(604+30.1)*3300 = 156 + * + * We add a significant margin on the maximum value, due to noise on the line, + * especially when PWM is active. See b/64193554 for details. + */ +#define BASE_DETECT_MIN_MV 120 +#define BASE_DETECT_MAX_MV 300 + +/* Minimum ADC value to indicate base is disconnected for sure */ +#define BASE_DETECT_DISCONNECT_MIN_MV 1500 + +/* + * Base EC pulses detection pin for 500 us to signal out of band USB wake (that + * can be used to wake system from deep S3). + */ +#define BASE_DETECT_PULSE_MIN_US 400 +#define BASE_DETECT_PULSE_MAX_US 650 + +static uint64_t base_detect_debounce_time; + +static void base_detect_deferred(void); +DECLARE_DEFERRED(base_detect_deferred); + +enum base_status { + BASE_UNKNOWN = 0, + BASE_DISCONNECTED = 1, + BASE_CONNECTED = 2, +}; + +static enum base_status current_base_status; + +/* + * This function is called whenever there is a change in the base detect + * status. Actions taken include: + * 1. Change in power to base + * 2. Indicate mode change to host. + * 3. Indicate tablet mode to host. Current assumption is that if base is + * disconnected then the system is in tablet mode, else if the base is + * connected, then the system is not in tablet mode. + */ +static void base_detect_change(enum base_status status) +{ + int connected = (status == BASE_CONNECTED); + + if (current_base_status == status) + return; + + gpio_set_level(GPIO_EN_BASE, connected); + tablet_set_mode(!connected, TABLET_TRIGGER_BASE); + base_set_state(connected); + current_base_status = status; +} + +/* Measure detection pin pulse duration (used to wake AP from deep S3). */ +static uint64_t pulse_start; +static uint32_t pulse_width; + +static void print_base_detect_value(int v, int tmp_pulse_width) +{ + CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name, v, + tmp_pulse_width); +} + +static void base_detect_deferred(void) +{ + uint64_t time_now = get_time().val; + int v; + uint32_t tmp_pulse_width = pulse_width; + + if (base_detect_debounce_time > time_now) { + hook_call_deferred(&base_detect_deferred_data, + base_detect_debounce_time - time_now); + return; + } + + v = adc_read_channel(ADC_BASE_DET); + if (v == ADC_READ_ERROR) + return; + + print_base_detect_value(v, tmp_pulse_width); + + if (v >= BASE_DETECT_MIN_MV && v <= BASE_DETECT_MAX_MV) { + if (current_base_status != BASE_CONNECTED) { + base_detect_change(BASE_CONNECTED); + } else if (tmp_pulse_width >= BASE_DETECT_PULSE_MIN_US && + tmp_pulse_width <= BASE_DETECT_PULSE_MAX_US) { + CPRINTS("Sending event to AP"); + host_set_single_event(EC_HOST_EVENT_KEY_PRESSED); + } + return; + } + + if (v >= BASE_DETECT_DISCONNECT_MIN_MV) { + base_detect_change(BASE_DISCONNECTED); + return; + } + + /* Unclear base status, schedule again in a while. */ + hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_RETRY_US); +} + +static inline int detect_pin_connected(enum gpio_signal det_pin) +{ + return gpio_get_level(det_pin) == 0; +} + +void base_detect_interrupt(enum gpio_signal signal) +{ + uint64_t time_now = get_time().val; + int debounce_us; + + if (detect_pin_connected(signal)) + debounce_us = BASE_DETECT_EN_DEBOUNCE_US; + else + debounce_us = BASE_DETECT_DIS_DEBOUNCE_US; + + if (base_detect_debounce_time <= time_now) { + /* + * Detect and measure detection pin pulse, when base is + * connected. Only a single pulse is measured over a debounce + * period. If no pulse, or multiple pulses are detected, + * pulse_width is set to 0. + */ + if (current_base_status == BASE_CONNECTED && + !detect_pin_connected(signal)) { + pulse_start = time_now; + } else { + pulse_start = 0; + } + pulse_width = 0; + + hook_call_deferred(&base_detect_deferred_data, debounce_us); + } else { + if (current_base_status == BASE_CONNECTED && + detect_pin_connected(signal) && !pulse_width && + pulse_start) { + /* First pulse within period. */ + pulse_width = time_now - pulse_start; + } else { + pulse_start = 0; + pulse_width = 0; + } + } + + base_detect_debounce_time = time_now + debounce_us; +} + +static void base_enable(void) +{ + /* Enable base detection interrupt. */ + base_detect_debounce_time = get_time().val; + hook_call_deferred(&base_detect_deferred_data, 0); + gpio_enable_interrupt(GPIO_BASE_DET_L); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, base_enable, HOOK_PRIO_DEFAULT); + +static void base_disable(void) +{ + /* + * Disable base detection interrupt and disable power to base. + * Set the state UNKNOWN so the next startup will initialize a + * correct state and notify AP. + */ + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_UNKNOWN); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, base_disable, HOOK_PRIO_DEFAULT); + +static void base_init(void) +{ + /* + * If we jumped to this image and chipset is already in S0, enable + * base. + */ + if (system_jumped_late() && chipset_in_state(CHIPSET_STATE_ON)) + base_enable(); +} +DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT + 1); + +void base_force_state(enum ec_set_base_state_cmd state) +{ + if (state == EC_SET_BASE_STATE_ATTACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_CONNECTED); + CPRINTS("BD forced connected"); + } else if (state == EC_SET_BASE_STATE_DETACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_DISCONNECTED); + CPRINTS("BD forced disconnected"); + } else { + base_enable(); + CPRINTS("BD forced reset"); + } +} diff --git a/board/quackingstick/battery.c b/board/quackingstick/battery.c new file mode 100644 index 0000000000..5376e74dc5 --- /dev/null +++ b/board/quackingstick/battery.c @@ -0,0 +1,97 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all quackingstick battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ + +const struct board_batt_params board_battery_info[] = { + /* COSMX AP21CBI Battery information */ + [BATTERY_AP21CBI] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0020B001", + .device_name = "AP21CBI", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + .vendor_param_start = 0x70, + }, + }, + /* COSMX AP21CBI Battery information */ + [BATTERY_AP21CBI_VER0] = { + .fuel_gauge = { + .manuf_name = "AP21CBI", + .device_name = "COSMX KT0020B001", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x8000, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + .vendor_param_start = 0x70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AP21CBI; diff --git a/board/quackingstick/board.c b/board/quackingstick/board.c new file mode 100644 index 0000000000..2cb1ac37e5 --- /dev/null +++ b/board/quackingstick/board.c @@ -0,0 +1,668 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Coachz board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "lid_switch.h" +#include "mkbp_input_devices.h" +#include "peripheral_charger.h" +#include "pi3usb9201.h" +#include "power.h" +#include "power/qcom.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "queue.h" +#include "shi_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define KS_DEBOUNCE_US (30 * MSEC) /* Debounce time for kickstand switch */ + +/* Forward declaration */ +static void tcpc_alert_event(enum gpio_signal signal); +static void usb0_evt(enum gpio_signal signal); +static void ppc_interrupt(enum gpio_signal signal); +static void board_connect_c0_sbu(enum gpio_signal s); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* GPIO Interrupt Handlers */ +static void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +static void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + default: + break; + } +} + +static void board_connect_c0_sbu_deferred(void) +{ + /* + * If CCD_MODE_ODL asserts, it means there's a debug accessory connected + * and we should enable the SBU FETs. + */ + ppc_set_sbu(0, 1); +} +DECLARE_DEFERRED(board_connect_c0_sbu_deferred); + +static void board_connect_c0_sbu(enum gpio_signal s) +{ + hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); +} + +/* I2C port map */ +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* Measure VBUS through a 1/10 voltage divider */ + [ADC_VBUS] = { + "VBUS", + NPCX_ADC_CH1, + ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, + 0 + }, + /* + * Adapter current output or battery charging/discharging current (uV) + * 18x amplification on charger side. + */ + [ADC_AMON_BMON] = { + "AMON_BMON", + NPCX_ADC_CH2, + ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, + 0 + }, + /* + * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read + * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and + * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we + * only divide by 2 (enough to avoid precision issues). + */ + [ADC_PSYS] = { + "PSYS", + NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), + 2, + 0 + }, + /* Base detection */ + [ADC_BASE_DET] = { + "BASE_DET", + NPCX_ADC_CH5, + ADC_MAX_VOLT, + ADC_READ_MAX + 1, + 0 + }, + [ADC_SYSTHERM2] = { + "SYSTHERM2", + NPCX_ADC_CH6, + ADC_MAX_VOLT, + ADC_READ_MAX + 1, + 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_SYS2] = { + .name = "SYSTEMP2", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_SYSTHERM2, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +const struct pwm_t pwm_channels[] = { + /* TODO(waihong): Assign a proper frequency. */ + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 4800 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/* Mutexes */ +static struct mutex g_lid_mutex; + +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm42607_data; + +enum lid_accelgyro_type { + LID_GYRO_NONE = 0, + LID_GYRO_BMI160 = 1, + LID_GYRO_ICM42607 = 2, +}; + +static enum lid_accelgyro_type lid_accelgyro_config; + +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t motion_sensors[] = { + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [LID_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +struct motion_sensor_t motion_sensors_icm[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .rot_standard_ref = NULL, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [LID_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = NULL, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, + }, +}; + +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void board_detect_motionsensor(void) +{ + int val = -1; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + if (lid_accelgyro_config != LID_GYRO_NONE) + return; + + /* Check base accelgyro chip */ + icm_read8(&motion_sensors_icm[LID_ACCEL], ICM42607_REG_WHO_AM_I, &val); + if (val == ICM42607_CHIP_ICM42607P) { + motion_sensors[LID_ACCEL] = motion_sensors_icm[LID_ACCEL]; + motion_sensors[LID_GYRO] = motion_sensors_icm[LID_GYRO]; + lid_accelgyro_config = LID_GYRO_ICM42607; + CPRINTS("LID Accelgyro: ICM42607"); + } else { + lid_accelgyro_config = LID_GYRO_BMI160; + CPRINTS("LID Accelgyro: BMI160"); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_DEFAULT + 1); + +void motion_interrupt(enum gpio_signal signal) +{ + if (lid_accelgyro_config == LID_GYRO_ICM42607) + icm42607_interrupt(signal); + else + bmi160_interrupt(signal); +} + +/* Initialize board. */ +static void board_init(void) +{ + /* + * The rev-1 hardware use PP1800_SENSORS as the power of the hall IC, + * it cause the LID_OPEN_EC wake EC immediately when EC enter hibernate. + */ + if (system_get_board_version() <= 1) { + hibernate_wake_pins[0] = GPIO_AC_PRESENT; + hibernate_wake_pins[1] = GPIO_POWER_BUTTON_L; + hibernate_wake_pins[2] = GPIO_EC_RST_ODL; + hibernate_wake_pins_used = 3; + } + + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); + + /* + * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs + * for SBU may be disconnected after DP alt mode is off. Should enable + * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. + */ + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); + + /* Enable pen input detect interrupt */ + if (system_get_board_version() >= 2) + gpio_enable_interrupt(GPIO_EC_PEN_PDCT_L); + + /* Set the backlight duty cycle to 0. AP will override it later. */ + pwm_set_duty(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +enum battery_present battery_is_present(void) +{ + static int first_check_done; + + /* + * b/231911921: It's found that the D-FET status is incorrect + * when the battery resume from cut off. The battery needs + * about 2s to ready to discharge so delay 2s before charge + * manager init. + */ + if (!first_check_done) { + if (battery_get_disconnect_state() == + BATTERY_NOT_DISCONNECTED) { + CPRINTS("Delay 2s on the first power on."); + sleep(2); + } + first_check_done = 1; + } + + return gpio_get_level(GPIO_BATT_PRES_ODL) ? BP_NO : BP_YES; +} + +void board_hibernate(void) +{ + int i; + + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + + /* + * Board rev 1+ has the hardware fix. Don't need the following + * workaround. + */ + if (system_get_board_version() > 1) + return; + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + ppc_vbus_sink_enable(i, 1); +} + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* + * Turn off display backlight in S3. AP has its own control. The EC's + * and the AP's will be AND'ed together in hardware. + */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); + pwm_enable(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Turn on display and keyboard backlight in S0. */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); + if (pwm_get_duty(PWM_CH_DISPLIGHT)) + pwm_enable(PWM_CH_DISPLIGHT, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON, enable); +} + +int board_is_switchcap_enabled(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_ON); +} + +int board_is_switchcap_power_good(void) +{ + return gpio_get_level(GPIO_DA9313_GPIO0); +} + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +/** + * Handle debounced pen input changing state. + */ +static void pen_input_deferred(void) +{ + bool pen_charge_enable = !gpio_get_level(GPIO_EC_PEN_PDCT_L) && + !chipset_in_state(CHIPSET_STATE_ANY_OFF); + + gpio_set_level(GPIO_PEN_PWR_EN, pen_charge_enable); + + CPRINTS("Pen charge %sable", pen_charge_enable ? "en" : "dis"); +} +DECLARE_DEFERRED(pen_input_deferred); + +void pen_input_interrupt(enum gpio_signal signal) +{ + /* pen input debounce time */ + hook_call_deferred(&pen_input_deferred_data, (100 * MSEC)); +} + +static void pen_charge_check(void) +{ + hook_call_deferred(&pen_input_deferred_data, (100 * MSEC)); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pen_charge_check, HOOK_PRIO_LAST); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pen_charge_check, HOOK_PRIO_LAST); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} diff --git a/board/quackingstick/board.h b/board/quackingstick/board.h new file mode 100644 index 0000000000..3cc4ab2b12 --- /dev/null +++ b/board/quackingstick/board.h @@ -0,0 +1,118 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Coachz board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +#define CONFIG_BUTTON_TRIGGERED_RECOVERY + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Save some flash space */ +#define CONFIG_LTO +#define CONFIG_USB_PD_DEBUG_LEVEL 2 +#undef CONFIG_CMD_FLASHINFO +#undef CONFIG_CMD_MMAPINFO +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_ACCEL_FIFO +#undef CONFIG_CMD_ACCEL_INFO +#undef CONFIG_CMD_TASK_RESET + +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#undef CONFIG_BATTERY_PRESENT_GPIO +#define CONFIG_BATTERY_PRESENT_CUSTOM +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_VENDOR_PARAM + +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +/* BC 1.2 Charger */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* USB */ +#define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 + +/* Lid accel/gyro */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_FRONT_PROXIMITY_SWITCH + +#define CONFIG_MKBP_INPUT_DEVICES + +#define CONFIG_DETACHABLE_BASE +#define CONFIG_BASE_ATTACHED_SWITCH + +/* GPIO alias */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_WP_L GPIO_EC_FLASH_WP_ODL +#define GPIO_PMIC_RESIN_L GPIO_PM845_RESIN_L + +/* temp */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_VBUS, + ADC_AMON_BMON, + ADC_PSYS, + ADC_BASE_DET, + ADC_SYSTHERM2, + ADC_CH_COUNT +}; + +enum temp_sensor_id { TEMP_SENSOR_SYS2, TEMP_SENSOR_COUNT }; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + LID_GYRO, + SENSOR_COUNT, +}; + +enum pwm_channel { PWM_CH_DISPLIGHT = 0, PWM_CH_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_AP21CBI, + BATTERY_AP21CBI_VER0, + BATTERY_TYPE_COUNT, +}; + +/* Reset all TCPCs. */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); +/* Base detection */ +void base_detect_interrupt(enum gpio_signal signal); +/* motion sensor interrupt */ +void motion_interrupt(enum gpio_signal signal); +void pen_input_interrupt(enum gpio_signal signal); + +#endif /* !defined(__ASSEMBLER__) */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/quackingstick/build.mk b/board/quackingstick/build.mk new file mode 100644 index 0000000000..363ef59a16 --- /dev/null +++ b/board/quackingstick/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=trogdor + +board-y=battery.o board.o led.o base_detect.o usbc_config.o diff --git a/board/quackingstick/ec.tasklist b/board/quackingstick/ec.tasklist new file mode 100644 index 0000000000..6cc550374d --- /dev/null +++ b/board/quackingstick/ec.tasklist @@ -0,0 +1,19 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/quackingstick/gpio.inc b/board/quackingstick/gpio.inc new file mode 100644 index 0000000000..ee3cedf704 --- /dev/null +++ b/board/quackingstick/gpio.inc @@ -0,0 +1,193 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* USB-C interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ +GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ + +/* System interrupts */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ +GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ +GPIO_INT(EC_FLASH_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ +GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ + +/* + * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down + * to make it low. Overload the interrupt function chipset_warm_reset_interrupt + * for not only signalling power_signal_interrupt but also handling the logic + * of WARM_RESET_L which is pulled-up by the same rail of POWER_GOOD. + */ +GPIO_INT(POWER_GOOD, PIN(5, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, chipset_power_good_interrupt) /* SRC_PP1800_S10A from PMIC */ +GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_warm_reset_interrupt) /* AP warm reset */ +GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ +GPIO_INT(BASE_DET_L, PIN(3, 7), GPIO_INT_BOTH, base_detect_interrupt) /* Detachable base attached? */ + +/* Sensor interrupts */ +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, motion_interrupt) /* Accelerometer/gyro interrupt */ +GPIO_INT(EC_PEN_PDCT_L, PIN(5, 0), GPIO_INT_BOTH, pen_input_interrupt) /* Pen input detect */ + +/* + * EC_RST_ODL acts as a wake source from hibernate mode. However, it does not + * need to be an interrupt for normal EC operations. Simply set it an INPUT. + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ +GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ + +/* PMIC/AP 1.8V */ +GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ +GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ + +/* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ +GPIO(SWITCHCAP_ON, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap; will be configured in the board init */ +GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ +GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ +GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ + +/* Base detection */ +GPIO(EN_BASE, PIN(0, 4), GPIO_OUT_LOW) /* Enable power to detachable base */ +GPIO(PEN_PWR_EN, PIN(8, 2), GPIO_OUT_LOW) /* Pen input charge */ + +/* USB-C */ +GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_ODR_HIGH) /* Port-0 TCPC chip reset, actaully Open-Drain */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ + +/* LEDs */ +GPIO(LED_ORANGE, PIN(C, 3), GPIO_OUT_LOW) +GPIO(LED_BLUE, PIN(C, 4), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + +/* PWM */ +GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ + +/* ADC */ +GPIO(PPVAR_BOOSTIN_SENSE, PIN(4, 4), GPIO_INPUT) /* ADC1 */ +GPIO(CHARGER_IADP, PIN(4, 3), GPIO_INPUT) /* ADC2 */ +GPIO(CHARGER_PMON, PIN(4, 2), GPIO_INPUT) /* ADC3 */ +GPIO(SYSTHERM2_CHARGER, PIN(3, 4), GPIO_INPUT) /* ADC6 */ + +/* I2C */ +GPIO(EC_I2C_POWER_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Board/SKU IDs */ +GPIO(BRD_ID0, PIN(C, 7), GPIO_INPUT) +GPIO(BRD_ID1, PIN(9, 3), GPIO_INPUT) +GPIO(BRD_ID2, PIN(6, 3), GPIO_INPUT) +GPIO(SKU_ID0, PIN(F, 0), GPIO_INPUT) +GPIO(SKU_ID1, PIN(4, 1), GPIO_INPUT) +GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) + +/* Switchcap */ +/* + * GPIO0 is configured as PVC_PG. When the chip in power down mode, it outputs + * high-Z. Set pull-down to avoid floating. + */ +GPIO(DA9313_GPIO0, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. Apply PU for power saving */ +UNUSED(PIN(F, 5)) +UNUSED(PIN(4, 0)) +UNUSED(PIN(7, 4)) +UNUSED(PIN(7, 3)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(6, 0)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(3, 0)) +UNUSED(PIN(E, 4)) +UNUSED(PIN(9, 2)) +UNUSED(PIN(9, 1)) +UNUSED(PIN(D, 1)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(5, 1)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(3, 1)) +UNUSED(PIN(2, 7)) +UNUSED(PIN(2, 6)) +UNUSED(PIN(2, 5)) +UNUSED(PIN(2, 4)) +UNUSED(PIN(2, 3)) +UNUSED(PIN(2, 2)) +UNUSED(PIN(2, 1)) +UNUSED(PIN(2, 0)) +UNUSED(PIN(1, 7)) +UNUSED(PIN(1, 6)) +UNUSED(PIN(1, 5)) +UNUSED(PIN(1, 4)) +UNUSED(PIN(1, 3)) +UNUSED(PIN(1, 2)) +UNUSED(PIN(1, 1)) +UNUSED(PIN(1, 0)) +UNUSED(PIN(0, 7)) +UNUSED(PIN(0, 6)) +UNUSED(PIN(0, 5)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(C, 6)) +UNUSED(PIN(C, 0)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(6, 2)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(5, 6)) +UNUSED(PIN(8, 0)) +UNUSED(PIN(D, 3)) +UNUSED(PIN(7, 5)) +UNUSED(PIN(8, 6)) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ +ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1 SDA (GPIO90), I2C2 (GPIO91/92) */ +ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) */ +ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ +ALTERNATE(PIN_MASK(D, 0x03), 1, MODULE_I2C, 0) /* I2C3 (GPIOD0/D1) */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* ADC6 (GPIO34) */ +ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ +ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ +ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ diff --git a/board/quackingstick/led.c b/board/quackingstick/led.c new file mode 100644 index 0000000000..b45ea32ec0 --- /dev/null +++ b/board/quackingstick/led.c @@ -0,0 +1,159 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +/* Battery LED blinks every per 400ms */ +#define LED_HALF_ONE_SEC (500 / HOOK_TICK_INTERVAL_MS) + +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_BLUE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color(enum led_color color) +{ + gpio_set_level(GPIO_LED_ORANGE, + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(GPIO_LED_BLUE, + (color == LED_BLUE) ? BAT_LED_ON : BAT_LED_OFF); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color(LED_BLUE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color(LED_AMBER); + else + led_set_color(LED_OFF); + + return EC_SUCCESS; +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + int color = LED_OFF; + int period = 0; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate amber on when charging. */ + color = LED_AMBER; + break; + case LED_PWRS_DISCHARGE: + if (chipset_in_or_transitioning_to_state( + CHIPSET_STATE_ANY_SUSPEND)) { + /* Discharging in S3: Amber 1 sec, off 3 sec */ + period = (1 + 3) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_AMBER; + else + color = LED_OFF; + } else if (chipset_in_or_transitioning_to_state( + CHIPSET_STATE_ANY_OFF)) { + /* Discharging in S5: off */ + color = LED_OFF; + } else { + /* Discharging in S0: Blue on */ + color = LED_BLUE; + } + break; + case LED_PWRS_ERROR: + /* Battery error: Amber on 1 sec, off 1 sec */ + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_AMBER; + else + color = LED_OFF; + break; + case LED_PWRS_CHARGE_NEAR_FULL: + /* Full Charged: Blue on */ + color = LED_BLUE; + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_BLUE; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode: Blue 2 sec, Amber 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) + color = LED_BLUE; + else + color = LED_AMBER; + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + led_set_color(color); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_BATTERY_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_BLUE : LED_OFF; + + led_auto_control(EC_LED_ID_BATTERY_LED, 0); + + led_set_color(color); +} diff --git a/board/quackingstick/usbc_config.c b/board/quackingstick/usbc_config.c new file mode 100644 index 0000000000..073c394de2 --- /dev/null +++ b/board/quackingstick/usbc_config.c @@ -0,0 +1,100 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor family-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "console.h" +#include "temp_sensor.h" +#include "usb_pd.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +struct temp_chg_step { + int low; /* temp thershold ('C) to lower level*/ + int high; /* temp thershold ('C) to higher level */ + int current; /* charging limitation (mA) */ +}; + +static const struct temp_chg_step temp_chg_table[] = { + { .low = 0, .high = 50, .current = 3000 }, /* Lv0: normal charge */ + { .low = 48, .high = 53, .current = 1500 }, + { .low = 51, .high = 56, .current = 1000 }, + { .low = 54, .high = 100, .current = 800 }, +}; +#define NUM_TEMP_CHG_LEVELS ARRAY_SIZE(temp_chg_table) + +int charger_profile_override(struct charge_state_data *curr) +{ + static int current_level; + int charger_temp, charger_temp_c; + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* charge current control depends on temp if the system is on */ + if (chipset_in_state(CHIPSET_STATE_ON)) { + temp_sensor_read(TEMP_SENSOR_SYS2, &charger_temp); + charger_temp_c = K_TO_C(charger_temp); + + if (charger_temp_c <= temp_chg_table[current_level].low) + current_level--; + else if (charger_temp_c >= temp_chg_table[current_level].high) + current_level++; + + if (current_level < 0) + current_level = 0; + + if (current_level >= NUM_TEMP_CHG_LEVELS) + current_level = NUM_TEMP_CHG_LEVELS - 1; + + curr->requested_current = + MIN(curr->requested_current, + temp_chg_table[current_level].current); + } + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/quackingstick/vif_override.xml b/board/quackingstick/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/quackingstick/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/quiche/board.c b/board/quiche/board.c index 46a19f4b5e..afe177efe8 100644 --- a/board/quiche/board.c +++ b/board/quiche/board.c @@ -1,14 +1,103 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Quiche board-specific configuration */ +#include "common.h" +#include "cros_board_info.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/stm32gx.h" +#include "driver/tcpm/tcpci.h" +#include "driver/usb_mux/ps8822.h" +#include "ec_version.h" +#include "gpio.h" #include "hooks.h" #include "switch.h" +#include "system.h" +#include "task.h" +#include "uart.h" +#include "usb_descriptor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_dp_ufp.h" +#include "usb_pe_sm.h" +#include "usb_prl_sm.h" +#include "usb_tc_sm.h" +#include "usbc_ppc.h" +#include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +#define QUICHE_PD_DEBUG_LVL 1 + +#ifdef SECTION_IS_RW +#define CROS_EC_SECTION "RW" +#else +#define CROS_EC_SECTION "RO" +#endif + +#ifdef SECTION_IS_RW +static int pd_dual_role_init[CONFIG_USB_PD_PORT_MAX_COUNT] = { + PD_DRP_TOGGLE_ON, + PD_DRP_FORCE_SOURCE, +}; + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_HOST_USBC_PPC_INT_ODL: + sn5s330_interrupt(USB_PD_PORT_HOST); + break; + case GPIO_USBC_DP_PPC_INT_ODL: + sn5s330_interrupt(USB_PD_PORT_DP); + break; + + default: + break; + } +} + +static void tcpc_alert_event(enum gpio_signal s) +{ + int port = -1; + + switch (s) { + case GPIO_USBC_DP_MUX_ALERT_ODL: + port = USB_PD_PORT_DP; + break; + default: + return; + } + schedule_deferred_pd_interrupt(port); +} + +void hpd_interrupt(enum gpio_signal signal) +{ + usb_pd_hpd_edge_event(signal); +} + +static void board_uf_manage_vbus_interrupt(enum gpio_signal signal) +{ + baseboard_usb3_check_state(); +} + +static void board_pwr_btn_interrupt(enum gpio_signal signal) +{ + baseboard_power_button_evt(gpio_get_level(signal)); +} + +static void board_usbc_usb3_interrupt(enum gpio_signal signal) +{ + baseboard_usbc_usb3_irq(); +} +#endif /* SECTION_IS_RW */ + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /* * Table GPIO signals control both power rails and reset lines to various chips @@ -16,34 +105,334 @@ * signals is driven by USB/MST hub power sequencing requirements. */ const struct power_seq board_power_seq[] = { - {GPIO_EN_AC_JACK, 1, 20}, - {GPIO_EN_PP5000_A, 1, 31}, - {GPIO_EN_PP3300_B, 1, 100}, - {GPIO_EN_BB, 1, 30}, - {GPIO_EN_PP1100_A, 1, 30}, - {GPIO_EN_PP1050_A, 1, 30}, - {GPIO_EN_PP1200_A, 1, 20}, - {GPIO_EN_PP5000_C, 1, 20}, - {GPIO_EN_PP5000_HSPORT, 1, 31}, - {GPIO_EN_DP_SINK, 1, 80}, - {GPIO_MST_RST_L, 1, 20}, - {GPIO_MST_LP_CTL_L, 1, 41}, - {GPIO_EC_HUB2_RESET_L, 1, 41}, - {GPIO_EC_HUB3_RESET_L, 1, 33}, - {GPIO_DP_SINK_RESET, 1, 100}, - {GPIO_USBC_DP_PD_RST_L, 1, 100}, - {GPIO_USBC_UF_RESET_L, 1, 33}, - {GPIO_DEMUX_DUAL_DP_PD_N, 1, 100}, - {GPIO_DEMUX_DUAL_DP_RESET_N, 1, 100}, - {GPIO_DEMUX_DP_HDMI_PD_N, 1, 10}, - {GPIO_DEMUX_DUAL_DP_MODE, 1, 10}, - {GPIO_DEMUX_DP_HDMI_MODE, 1, 1}, + { GPIO_EN_AC_JACK, 1, 20 }, + { GPIO_EC_DFU_MUX_CTRL, 0, 0 }, + { GPIO_EN_PP5000_A, 1, 31 }, + { GPIO_MST_LP_CTL_L, 1, 0 }, + { GPIO_EN_PP3300_B, 1, 1 }, + { GPIO_EN_PP1100_A, 1, 100 + 30 }, + { GPIO_EN_BB, 1, 30 }, + { GPIO_EN_PP1050_A, 1, 30 }, + { GPIO_EN_PP1200_A, 1, 20 }, + { GPIO_EN_PP5000_C, 1, 20 }, + { GPIO_EN_PP5000_HSPORT, 1, 31 }, + { GPIO_EN_DP_SINK, 1, 80 }, + { GPIO_MST_RST_L, 1, 61 }, + { GPIO_EC_HUB2_RESET_L, 1, 41 }, + { GPIO_EC_HUB3_RESET_L, 1, 33 }, + { GPIO_DP_SINK_RESET, 1, 100 }, + { GPIO_USBC_DP_PD_RST_L, 1, 100 }, + { GPIO_USBC_UF_RESET_L, 1, 33 }, + { GPIO_DEMUX_DUAL_DP_PD_N, 1, 100 }, + { GPIO_DEMUX_DUAL_DP_RESET_N, 1, 100 }, + { GPIO_DEMUX_DP_HDMI_PD_N, 1, 10 }, + { GPIO_DEMUX_DUAL_DP_MODE, 1, 10 }, + { GPIO_DEMUX_DP_HDMI_MODE, 1, 5 }, }; - const size_t board_power_seq_count = ARRAY_SIZE(board_power_seq); +/* + * Define the strings used in our USB descriptors. + */ +const void *const usb_strings[] = { + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Quiche"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = + USB_STRING_DESC(CROS_EC_SECTION ":" CROS_EC_VERSION32), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), +}; +BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); + +#ifndef SECTION_IS_RW +/* USB-C PPC Configuration */ +struct ppc_config_t ppc_chips[] = { + [USB_PD_PORT_HOST] = { + .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + }, +}; +#endif + +#ifdef SECTION_IS_RW +/* + * PS8802 set mux board tuning. + * Adds in board specific gain and DP lane count configuration + */ +static int board_ps8822_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) + rv = ps8822_set_dp_rx_eq(me, PS8822_DPEQ_LEVEL_UP_20DB); + + return rv; +} + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &stm32gx_tcpm_drv, + }, + [USB_PD_PORT_DP] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_I2C1, + .addr_flags = PS8XXX_I2C_ADDR2_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_HOST, + .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = PS8822_I2C_ADDR3_FLAG, + .driver = &ps8822_usb_mux_driver, + .board_set = &board_ps8822_mux_set, + }, + }, + [USB_PD_PORT_DP] = { + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_DP, + .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = PS8XXX_I2C_ADDR2_FLAGS, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, +}; + +/* USB-C PPC Configuration */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [USB_PD_PORT_HOST] = { .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + [USB_PD_PORT_DP] = { .i2c_port = I2C_PORT_I2C1, + .i2c_addr_flags = SN5S330_ADDR2_FLAGS, + .drv = &sn5s330_drv }, + [USB_PD_PORT_USB3] = { .i2c_port = I2C_PORT_I2C3, + .i2c_addr_flags = SN5S330_ADDR1_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +const struct hpd_to_pd_config_t hpd_config = { + .port = USB_PD_PORT_HOST, + .signal = GPIO_DDI_MST_IN_HPD, +}; + +void board_reset_pd_mcu(void) +{ + cprints(CC_SYSTEM, "Resetting TCPCs..."); + cflush(); + gpio_set_level(GPIO_USBC_DP_PD_RST_L, 0); + gpio_set_level(GPIO_USBC_UF_RESET_L, 0); + msleep(PS8805_FW_INIT_DELAY_MS); + gpio_set_level(GPIO_USBC_DP_PD_RST_L, 1); + gpio_set_level(GPIO_USBC_UF_RESET_L, 1); + msleep(PS8805_FW_INIT_DELAY_MS); +} + +void board_enable_usbc_interrupts(void) +{ + /* Enable C0 PPC interrupt */ + gpio_enable_interrupt(GPIO_HOST_USBC_PPC_INT_ODL); + /* Enable C1 PPC interrupt */ + gpio_enable_interrupt(GPIO_USBC_DP_PPC_INT_ODL); + /* Enable C0 HPD interrupt */ + gpio_enable_interrupt(GPIO_DDI_MST_IN_HPD); + /* Enable C1 TCPC interrupt */ + gpio_enable_interrupt(GPIO_USBC_DP_MUX_ALERT_ODL); +} + +void board_disable_usbc_interrupts(void) +{ + /* Disable C0 PPC interrupt */ + gpio_disable_interrupt(GPIO_HOST_USBC_PPC_INT_ODL); + /* Disable C1 PPC interrupt */ + gpio_disable_interrupt(GPIO_USBC_DP_PPC_INT_ODL); + /* Disable C0 HPD interrupt */ + gpio_disable_interrupt(GPIO_DDI_MST_IN_HPD); + /* Disable C1 TCPC interrupt */ + gpio_disable_interrupt(GPIO_USBC_DP_MUX_ALERT_ODL); + /* Disable VBUS control interrupt for C2 */ + gpio_disable_interrupt(GPIO_USBC_UF_MUX_VBUS_EN); +} + +void board_tcpc_init(void) +{ + board_reset_pd_mcu(); + + /* Enable board usbc interrupts */ + board_enable_usbc_interrupts(); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 2); + +enum pd_dual_role_states board_tc_get_initial_drp_mode(int port) +{ + return pd_dual_role_init[port]; +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + /* + * CONFIG_USB_PD_PORT_MAX_COUNT must be defined to account for C0, C1, + * and C2, but TCPMv2 only knows about C0 and C1, as C2 is a type-c only + * port that is managed directly by the PS8803 TCPC. + */ + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; +} + +int ppc_get_alert_status(int port) +{ + if (port == USB_PD_PORT_HOST) + return gpio_get_level(GPIO_HOST_USBC_PPC_INT_ODL) == 0; + else if (port == USB_PD_PORT_DP) + return gpio_get_level(GPIO_USBC_DP_PPC_INT_ODL) == 0; + + return 0; +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USBC_DP_MUX_ALERT_ODL) && + gpio_get_level(GPIO_USBC_DP_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +static void board_usb_pd_dp_ocp_reset(void) +{ + gpio_set_level(GPIO_USBC_ALTMODE_OCP_NOTIFY, 1); +} +DECLARE_DEFERRED(board_usb_pd_dp_ocp_reset); + +void board_overcurrent_event(int port, int is_overcurrented) +{ + if (port == USB_PD_PORT_DP) { + gpio_set_level(GPIO_USBC_ALTMODE_OCP_NOTIFY, !is_overcurrented); + hook_call_deferred(&board_usb_pd_dp_ocp_reset_data, + USB_HUB_OCP_RESET_MSEC); + } +} + +int dock_get_mf_preference(void) +{ + int rv; + uint32_t fw_config; + int mf = MF_OFF; + + /* + * MF (multi function) preferece is indicated by bit 0 of the fw_config + * data field. If this data field does not exist, then default to 4 lane + * mode. + */ + rv = cbi_get_fw_config(&fw_config); + if (!rv) + mf = CBI_FW_MF_PREFERENCE(fw_config); + + return mf; +} + +static void board_usb_tc_connect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* + * The EC needs to indicate to the MST hub when the host port is + * attached. GPIO_UFP_PLUG_DET is used for this purpose. + */ + if (port == USB_PD_PORT_HOST) + gpio_set_level(GPIO_UFP_PLUG_DET, 0); +} +DECLARE_HOOK(HOOK_USB_PD_CONNECT, board_usb_tc_connect, HOOK_PRIO_DEFAULT); + +static void board_usb_tc_disconnect(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + + /* Only the host port disconnect is relevant */ + if (port == USB_PD_PORT_HOST) + gpio_set_level(GPIO_UFP_PLUG_DET, 1); +} +DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, board_usb_tc_disconnect, + HOOK_PRIO_DEFAULT); + +#endif /* SECTION_IS_RW */ + static void board_init(void) { - /* TODO */ } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_debug_gpio_1_pulse(void) +{ + gpio_set_level(GPIO_TRIGGER_1, 0); +} +DECLARE_DEFERRED(board_debug_gpio_1_pulse); + +static void board_debug_gpio_2_pulse(void) +{ + gpio_set_level(GPIO_TRIGGER_2, 0); +} +DECLARE_DEFERRED(board_debug_gpio_2_pulse); + +void board_debug_gpio(enum debug_gpio trigger, int level, int pulse_usec) +{ + switch (trigger) { + case TRIGGER_1: + gpio_set_level(GPIO_TRIGGER_1, level); + if (pulse_usec) + hook_call_deferred(&board_debug_gpio_1_pulse_data, + pulse_usec); + break; + case TRIGGER_2: + gpio_set_level(GPIO_TRIGGER_2, level); + if (pulse_usec) + hook_call_deferred(&board_debug_gpio_2_pulse_data, + pulse_usec); + break; + default: + CPRINTS("bad debug gpio selection"); + break; + } +} + +static int command_dplane(int argc, const char **argv) +{ + char *e; + int lane; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + lane = strtoi(argv[1], &e, 10); + + if ((lane != 2) && (lane != 4)) + return EC_ERROR_PARAM1; + + /* put MST into reset */ + gpio_set_level(GPIO_MST_RST_L, 0); + msleep(1); + /* Set lane control to requested level */ + gpio_set_level(GPIO_MST_HUB_LANE_SWITCH, lane == 2 ? 1 : 0); + msleep(1); + /* Take MST out of reset */ + gpio_set_level(GPIO_MST_RST_L, 1); + + ccprintf("MST lane set: %s, lane_ctrl = %d\n", + lane == 2 ? "2 lane" : "4 lane", + gpio_get_level(GPIO_MST_HUB_LANE_SWITCH)); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(dplane, command_dplane, "<2 | 4>", "MST lane control."); diff --git a/board/quiche/board.h b/board/quiche/board.h index 48422e7a50..b1ba0c5eba 100644 --- a/board/quiche/board.h +++ b/board/quiche/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,19 +12,89 @@ #include "baseboard.h" /* Optional features */ +/* + * For MP release, CONFIG_SYSTEM_UNLOCKED must be undefined, and + * CONFIG_FLASH_PSTATE_LOCKED must be defined in order to enable write protect + * using option bytes WRP registers. + */ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ +#undef CONFIG_FLASH_PSTATE_LOCKED /* USB Type C and USB PD defines */ +#define USB_PD_PORT_HOST 0 +#define USB_PD_PORT_DP 1 +#define USB_PD_PORT_USB3 2 + +/* + * The host (C0) and display (C1) usbc ports are usb-pd capable. There is + * also a type-c only port (C2). C2 must be accounted for in PORT_MAX_COUNT so + * the PPC config table is correctly sized and the PPC driver can be used to + * control VBUS on/off. + */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 3 +#define CONFIG_USB_MUX_PS8822 + +#define CONFIG_USB_PID 0x5048 +#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ +#define CONFIG_USB_PD_IDENTITY_HW_VERS 1 +#define CONFIG_USB_PD_IDENTITY_SW_VERS 1 -/* USB Type A Features */ +/* I2C port names */ +#define I2C_PORT_I2C1 0 +#define I2C_PORT_I2C2 1 +#define I2C_PORT_I2C3 2 -/* BC 1.2 */ +/* Required symbolic I2C port names */ +#define I2C_PORT_MP4245 I2C_PORT_I2C3 +#define I2C_PORT_EEPROM I2C_PORT_I2C3 +#define MP4245_I2C_ADDR_FLAGS MP4245_I2C_ADDR_0_FLAGS +/* Include math_util for bitmask_uint64 used in pd_timers */ +#define CONFIG_MATH_UTIL #ifndef __ASSEMBLER__ #include "registers.h" +#define GPIO_DP_HPD GPIO_DDI_MST_IN_HPD +#define GPIO_USBC_UF_ATTACHED_SRC GPIO_USBC_UF_MUX_VBUS_EN +#define GPIO_BPWR_DET GPIO_TP73 +#define GPIO_USB_HUB_OCP_NOTIFY GPIO_USBC_DATA_OCP_NOTIFY +#define GPIO_UFP_PLUG_DET GPIO_MST_UFP_PLUG_DET +#define GPIO_PWR_BUTTON_RED GPIO_EC_STATUS_LED1 +#define GPIO_PWR_BUTTON_GREEN GPIO_EC_STATUS_LED2 + +#define BUTTON_PRESSED_LEVEL 1 +#define BUTTON_RELEASED_LEVEL 0 + +#define GPIO_TRIGGER_1 GPIO_EC_STATUS_LED1 +#define GPIO_TRIGGER_2 GPIO_EC_STATUS_LED2 + +enum debug_gpio { + TRIGGER_1 = 0, + TRIGGER_2, +}; + +/* + * Function used to control GPIO signals as a timing marker. This is intended to + * be used for development/debugging purposes. + * + * @param trigger GPIO debug signal selection + * @param level desired level of the debug gpio signal + * @param pulse_usec pulse width if non-zero + */ +void board_debug_gpio(enum debug_gpio trigger, int level, int pulse_usec); + +/* + * Function called in power on case to enable usbc related interrupts + */ +void board_enable_usbc_interrupts(void); + +/* + * Function called in power off case to disable usbc related interrupts + */ +void board_disable_usbc_interrupts(void); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/quiche/build.mk b/board/quiche/build.mk index 3c17e2e83b..76a59e502a 100644 --- a/board/quiche/build.mk +++ b/board/quiche/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,7 +8,7 @@ CHIP:=stm32 CHIP_FAMILY:=stm32g4 -CHIP_VARIANT:=stm32g431xb +CHIP_VARIANT:=stm32g473xc BASEBOARD:=honeybuns board-y=board.o diff --git a/board/quiche/dev_key.pem b/board/quiche/dev_key.pem new file mode 100644 index 0000000000..4897ceb44e --- /dev/null +++ b/board/quiche/dev_key.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEAyiT9PsD2wW3mhfuxMtihnLDKC+PY9l6j+j405G5Wd3BBtLLl +2uEoSD8cFQfnVTeFH7wggVf+SMAP3Y2aTnXIfdTX3N0skAdq/kYNUlQAK0xsa3Z7 +bRZ8puvzu+XNqsSS/tvsdYbNE5WC5sXtt7Wkm3mKn7PAti7oQrKbW1beFD0FgdAq +JoweIdpkuOwDYtFBcF92LWWGziDcEXlc2v5Xj3qvixMLnhy+Ny1Byr2ApVaYZ56H +JfjHKxbirNj4IrgmhdzfBIKxDf4mGibG0K1aC1io+SixtRV1cS6JRB0D+GS4QIcq +y9bCMkBeVQLHhSo1UYZqbB7Qef0blQ2sxsXklo8Q5EIQOd6yiXiTelApOWDn3zTi +uTkUo+99SPDLw/S3sR3uESxt+OYO2Yt6BWe2JSYBhHWB0Xc0PGItq7DUpm2cEWke +vS91I/lBfqhOxQOvnEx5NM97/RBQMa3jJ5Jv/72X5oU6OcGmaliBJy3Tv0CSiI06 +qgRgWxMym/XA0ui/AgEDAoIBgQCGw1N/K08rnpmup8t3OxZoddwH7TtO6cKm1CNC +9Dmk9YEjIe6R63AwKhK4r++OJQNqfWsA5VQwgAqTs7w0ToWpOI/ok3MKr5yphAjh +jVVyMvLyTvzzZFMZ8qJ9Q95x2GH/PUhOWd4NDldEg/PPzm28+7G/zSskH0WBzGeS +Oeli01kBNXFvCBQWkZh7SAJB4NZK6k7I7lnewJK2UOiR/uUKUcpct10UEyl6Hivc +flXDjxBFFFoZUITHZJcd5frB0Bh+EiqJ3CnkSIjD4sTnZs/TP8CKhmYriabfBHdH +j6ffcr5y8VhqDJK/ISSmWQO1c/rSziJLhx/ZrWvWp1FAbRg+kdh+RmV8hYIdEOq8 +PYOiERihd+eHVhtzsc74+cRGxPbaFJ2rpuJt+xk1Zp7IfGyyPWDmvXFKZgX+vo2s +vJL6q9pPR57uUHL0xsxDrMH3HFxkl1ta5PsiBGXs+zG0EUzNKGtoRTCi176xUWyo +NG+eWiL9ddeZVBzWeKfJGfwQ53sCgcEA+JE2E5kjvVCasSqERfDfIkSeOKoqWdZ2 +sAvTHibq6+vMBkRubNA0glHcUrMEBblDg3ds2z1A9YvwjwEUq9UFpVH3qfX9vaTX +lLYFRZjcA3PkCJvFAt5eIlVXp+vgaEo6OcodLjDiqkYKzbMC13k5uM1wsEEwo2vI +38vhHQlH1PHVTd8pt2Y7mOpDgxOOJLrvwuew7Lj9QSBRZ0EJxqv+1QA4EQ1cPr1H +hGqggtL0ChLRV7KBHiLz9ggS5vHTEkFNAoHBANAwaSIfTnpAvkMoGy+iQyw0afC0 +7hnwhHKcAzqenT1Mzo3Yt7/zsZE8ywjKPe9C+ZHZyh+W373tCUQRnjpNOpNiVHzi +ekFxl8kpLhpbB8LTXuRlQmtZjVQPbyuORPGDCzA05GGBN6mnXju+iQEz2WD8f3oY +Jz5yYl54eAuMsFl5/0yehqBQjRvky5YRna2eNUKBvz+/BgjpZeb0DtLMffcAvrkQ +FQbAwNvzvagMOEemjLSp9iXjQSNWJAdc86dMOwKBwQCltiQNEMJ+Nbx2HFguoJTB +gxQlxsbmjvnKsoy+xJydR91ZgvRIis2sNpLhzK1ZJi0CT53nfitOXUsKALhyjgPD +i/pxTqkpGI+4eVjZEJKs9+1bEoNXPulsOOUanUBFhtF73BN0IJccLrHed1c6UNEl +3ksgK3XCR9s/3UC+Bi/jS+OJP3Ek7tJl8YJXYl7DJ0qB78tIe1OAwDZE1gaEcqnj +VXq2COgp04UC8cBXN01cDIuPzFYUF01OsAyZ9oy21jMCgcEAisrwwWo0UYB+13AS +H8GCHXhGoHieu/Wtob1XfGm+KN3fCTslKqJ2YNMyBdwpSiymYTvcFQ8/0/NbgrZp +fDN8YkGNqJb8K6EP23DJZudageI/Qu4sR5EI4rT0x7Qt9ldcys3tllYlG8TpfSmw +q3fmQKhU/BAaKaGW6aWlXQh1kPv/iGmvFYsIvUMyZAu+c77OLFZ/f9SusJuZRKK0 +jIhT+gB/Jgq4rysrPU0pGrLQL8RdzcakGUIrbOQYBOiib4gnAoHAVrvbmZGxyeeA +oDE2QlXXmd1higPaQe3u+7vmh6itVpJ71n9wmu9xei7IiTOtGDYjHLXa8Qg0y37/ +FVCUiFxhOz05hpnB1ts70tuIWUJbWttMnhZPTpKa1dzZFB6qrlk2o/ONaSfNzpOZ +FgKxBURFVzNMTlIh7QOZGoOeRg5BkFG5z21g8egYQ/1cY61BhaxJTz93HGKb0jYn +QnC0WfVF9amWNGwocKATkwjoSVC7rQRsB2FMbY/WCqgE92lXsU9W +-----END RSA PRIVATE KEY----- diff --git a/board/quiche/ec.tasklist b/board/quiche/ec.tasklist index c272906fc7..ffd4a604c9 100644 --- a/board/quiche/ec.tasklist +++ b/board/quiche/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,5 +8,11 @@ */ #define CONFIG_TASK_LIST \ + TASK_ALWAYS_RO(RWSIG, rwsig_task, NULL, 1280) \ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(POWER_BUTTON, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PD_INT_C1, pd_interrupt_handler_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(UCPD, ucpd_task, 0, LARGER_TASK_STACK_SIZE) diff --git a/board/quiche/gpio.inc b/board/quiche/gpio.inc index e6264c741e..afd18e5bb6 100644 --- a/board/quiche/gpio.inc +++ b/board/quiche/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,10 +8,19 @@ /* Declare symbolic names for all the GPIOs that we care about. * Note: Those with interrupt handlers must be declared first. */ +#ifdef SECTION_IS_RW +GPIO_INT(HOST_USBC_PPC_INT_ODL, PIN(D, 9), GPIO_INT_FALLING | GPIO_PULL_UP, ppc_interrupt) +GPIO_INT(USBC_DP_MUX_ALERT_ODL, PIN(B, 1), GPIO_INT_FALLING | GPIO_PULL_UP, tcpc_alert_event) +GPIO_INT(USBC_DP_PPC_INT_ODL, PIN(E, 7), GPIO_INT_FALLING | GPIO_PULL_UP, ppc_interrupt) +GPIO_INT(DDI_MST_IN_HPD, PIN(C, 14), GPIO_INT_BOTH, hpd_interrupt) +GPIO_INT(USBC_UF_MUX_VBUS_EN, PIN(C, 12), GPIO_INT_BOTH, board_uf_manage_vbus_interrupt) +GPIO_INT(PWR_BTN, PIN(A, 0), GPIO_INT_BOTH, board_pwr_btn_interrupt) +GPIO_INT(USBC_UF_PPC_INT_ODL, PIN(B, 5), GPIO_INT_FALLING | GPIO_PULL_UP, board_usbc_usb3_interrupt) +#endif + /* Power sequencing signals */ -GPIO(PWR_BTN, PIN(A, 0), GPIO_INPUT) GPIO(EN_AC_JACK, PIN(A, 1), GPIO_OUT_LOW) -GPIO(EN_BB, PIN(A, 10), GPIO_OUT_LOW) +GPIO(EN_BB, PIN(A, 8), GPIO_OUT_LOW) GPIO(EN_PP3300_B, PIN(B, 2), GPIO_OUT_LOW) GPIO(EN_PP5000_A, PIN(C, 6), GPIO_OUT_LOW) GPIO(EN_PP1200_A, PIN(E, 8), GPIO_OUT_LOW) @@ -23,6 +32,8 @@ GPIO(EN_PP5000_HSPORT, PIN(D, 0), GPIO_OUT_LOW) /* MST Hub signals */ GPIO(MST_LP_CTL_L, PIN(D, 10), GPIO_ODR_LOW) GPIO(MST_RST_L, PIN(E, 14), GPIO_ODR_LOW) +GPIO(MST_HUB_LANE_SWITCH, PIN(C, 15), GPIO_OUT_HIGH) +GPIO(MST_UFP_PLUG_DET, PIN(B, 12), GPIO_OUT_HIGH) /* Display Demux signals */ GPIO(DEMUX_DUAL_DP_MODE, PIN(B, 0), GPIO_OUT_LOW) @@ -39,12 +50,26 @@ GPIO(USBC_UF_RESET_L, PIN(D, 2), GPIO_ODR_LOW) /* USB Hubs signals */ GPIO(EC_HUB2_RESET_L, PIN(C, 5), GPIO_ODR_LOW) -GPIO(EC_HUB3_RESET_L, PIN(C, 10), GPIO_ODR_LOW) +GPIO(EC_HUB3_RESET_L, PIN(B, 10), GPIO_ODR_LOW) +GPIO(USBC_ALTMODE_OCP_NOTIFY, PIN(F, 0), GPIO_OUT_HIGH) +GPIO(USBC_DATA_OCP_NOTIFY, PIN(F, 1), GPIO_OUT_HIGH) + +/* USB-A Current limit switches, set default to 1.5A */ +GPIO(TP73, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EC_DFU_MUX_CTRL, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(EC_STATUS_LED1, PIN(C, 1), GPIO_OUT_HIGH) +GPIO(EC_STATUS_LED2, PIN(C, 2), GPIO_OUT_HIGH) +GPIO(USB3_A5_CDP_EN, PIN(B, 9), GPIO_OUT_LOW) +GPIO(USB3_A6_CDP_EN, PIN(C, 13), GPIO_OUT_LOW) /* Write protect */ GPIO(EC_FLASH_WP_ODL, PIN(A, 3), GPIO_ODR_HIGH) GPIO(EC_WP_L, PIN(E, 11), GPIO_INT_BOTH) +/* UART Bus */ +GPIO(EC_UART_TX, PIN(C, 10), GPIO_INT_BOTH) +GPIO(EC_UART_RX, PIN(C, 11), GPIO_INT_BOTH) + /* * I2C SCL/SDA pins. These will normally be under control of the peripheral from * alt fucntion setting below. But if a port gets wedged, the unwedge code uses @@ -52,11 +77,12 @@ GPIO(EC_WP_L, PIN(E, 11), GPIO_INT_BOTH) */ GPIO(EC_I2C1_SCL, PIN(A, 15), GPIO_ODR_HIGH) GPIO(EC_I2C1_SDA, PIN(B, 7), GPIO_ODR_HIGH) -GPIO(EC_I2C2_SDA, PIN(A, 8), GPIO_ODR_HIGH) -GPIO(EC_I2C2_SCL, PIN(A, 9), GPIO_ODR_HIGH) GPIO(EC_I2C3_SCL, PIN(C, 8), GPIO_ODR_HIGH) GPIO(EC_I2C3_SDA, PIN(C, 9), GPIO_ODR_HIGH) +/* misc signals */ +GPIO(BOOT0, PIN(B, 8), GPIO_INPUT) + /* Unimplemented signals since we are not an EC */ UNIMPLEMENTED(ENTERING_RW) @@ -69,7 +95,6 @@ ALTERNATE(PIN_MASK(C, 0x0C00), 7, MODULE_UART, GPIO_PULL_UP) */ ALTERNATE(PIN_MASK(B, 0x0080), 4, MODULE_I2C, GPIO_OPEN_DRAIN) ALTERNATE(PIN_MASK(A, 0X8000), 4, MODULE_I2C, GPIO_OPEN_DRAIN) -ALTERNATE(PIN_MASK(A, 0x0300), 4, MODULE_I2C, GPIO_OPEN_DRAIN) ALTERNATE(PIN_MASK(C, 0x0300), 8, MODULE_I2C, GPIO_OPEN_DRAIN) /* GPIOA4-7: SPI Signals */ ALTERNATE(PIN_MASK(A, 0x00F0), 5, MODULE_SPI, 0) diff --git a/board/rainier/board.c b/board/rainier/board.c index fa852a5a90..1844688947 100644 --- a/board/rainier/board.c +++ b/board/rainier/board.c @@ -1,22 +1,21 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" -#include "chipset.h" #include "charge_manager.h" #include "charge_state.h" +#include "chipset.h" #include "common.h" #include "console.h" -#include "ec_commands.h" #include "driver/accelgyro_bmi_common.h" #include "driver/baro_bmp280.h" #include "driver/tcpm/fusb302.h" #include "driver/temp_sensor/tmp432.h" +#include "ec_commands.h" #include "extpower.h" #include "gpio.h" #include "hooks.h" @@ -31,18 +30,18 @@ #include "switch.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "temp_sensor.h" #include "temp_sensor_chip.h" -#include "timer.h" #include "thermal.h" +#include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { @@ -61,40 +60,45 @@ static void warm_reset_request_interrupt(enum gpio_signal signal) chipset_reset(CHIPSET_RESET_AP_REQ); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 16, 4096, 0, STM32_AIN(10)}, + [ADC_BOARD_ID] = { "BOARD_ID", 16, 4096, 0, STM32_AIN(10) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"tcpc0", I2C_PORT_TCPC0, 1000, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_PP1250_S3_PG, POWER_SIGNAL_ACTIVE_HIGH, "PP1250_S3_PWR_GOOD"}, - {GPIO_PP900_S0_PG, POWER_SIGNAL_ACTIVE_HIGH, "PP900_S0_PWR_GOOD"}, - {GPIO_AP_CORE_PG, POWER_SIGNAL_ACTIVE_HIGH, "AP_PWR_GOOD"}, - {GPIO_AP_EC_S3_S0_L, POWER_SIGNAL_ACTIVE_LOW, "SUSPEND_DEASSERTED"}, + { GPIO_PP1250_S3_PG, POWER_SIGNAL_ACTIVE_HIGH, "PP1250_S3_PWR_GOOD" }, + { GPIO_PP900_S0_PG, POWER_SIGNAL_ACTIVE_HIGH, "PP900_S0_PWR_GOOD" }, + { GPIO_AP_CORE_PG, POWER_SIGNAL_ACTIVE_HIGH, "AP_PWR_GOOD" }, + { GPIO_AP_EC_S3_S0_L, POWER_SIGNAL_ACTIVE_LOW, "SUSPEND_DEASSERTED" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); #ifdef CONFIG_TEMP_SENSOR_TMP432 /* Temperature sensors data; must be in same order as enum temp_sensor_id. */ const struct temp_sensor_t temp_sensors[] = { - {"TMP432_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_LOCAL, 4}, - {"TMP432_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE1, 4}, - {"TMP432_Sensor_2", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE2, 4}, + { "TMP432_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_LOCAL, 4 }, + { "TMP432_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE1, 4 }, + { "TMP432_Sensor_2", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE2, 4 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -103,9 +107,9 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); * same order as enum temp_sensor_id. To always ignore any temp, use 0. */ struct ec_thermal_config thermal_params[] = { - {{0, 0, 0}, 0, 0}, /* TMP432_Internal */ - {{0, 0, 0}, 0, 0}, /* TMP432_Sensor_1 */ - {{0, 0, 0}, 0, 0}, /* TMP432_Sensor_2 */ + { { 0, 0, 0 }, 0, 0 }, /* TMP432_Internal */ + { { 0, 0, 0 }, 0, 0 }, /* TMP432_Sensor_1 */ + { { 0, 0, 0 }, 0, 0 }, /* TMP432_Sensor_2 */ }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); #endif @@ -120,9 +124,8 @@ const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* Wake-up pins for hibernate */ -const enum gpio_signal hibernate_wake_pins[] = { - GPIO_POWER_BUTTON_L, GPIO_CHARGER_INT_L -}; +const enum gpio_signal hibernate_wake_pins[] = { GPIO_POWER_BUTTON_L, + GPIO_CHARGER_INT_L }; const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /******************************************************************************/ @@ -131,17 +134,20 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }, }; @@ -168,8 +174,8 @@ int board_set_active_charge_port(int charge_port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* * NOP because there is no internal power therefore no charging. @@ -185,13 +191,13 @@ int extpower_is_present(void) int pd_snk_is_vbus_provided(int port) { - /* Must be, if we're at a stage where this function is called. */ + /* Must be, if we're at a stage where this function is called. */ return 1; } static void board_spi_enable(void) { - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); /* Enable clocks to SPI2 module */ STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; @@ -200,24 +206,22 @@ static void board_spi_enable(void) STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_spi_enable, +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, MOTION_SENSE_HOOK_PRIO - 1); static void board_spi_disable(void) { - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); /* Disable clocks to SPI2 module */ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; - gpio_config_module(MODULE_SPI_MASTER, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_spi_disable, - MOTION_SENSE_HOOK_PRIO + 1); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, + MOTION_SENSE_HOOK_PRIO + 1); static void board_init(void) { @@ -250,8 +254,8 @@ void board_config_pre_init(void) * Ch4: USART1_TX / Ch5: USART1_RX (1000) * Ch6: SPI2_RX / Ch7: SPI2_TX (0011) */ - STM32_DMA_CSELR(STM32_DMAC_CH4) = (8 << 12) | (8 << 16) | - (3 << 20) | (3 << 24); + STM32_DMA_CSELR(STM32_DMAC_CH4) = (8 << 12) | (8 << 16) | (3 << 20) | + (3 << 24); } void board_hibernate(void) @@ -296,16 +300,16 @@ struct { enum rainier_board_version version; int expect_mv; } const rainier_boards[] = { - { BOARD_VERSION_REV0, 109 }, /* 51.1K , 2.2K(gru 3.3K) ohm */ - { BOARD_VERSION_REV1, 211 }, /* 51.1k , 6.8K ohm */ - { BOARD_VERSION_REV2, 319 }, /* 51.1K , 11K ohm */ - { BOARD_VERSION_REV3, 427 }, /* 56K , 17.4K ohm */ - { BOARD_VERSION_REV4, 542 }, /* 51.1K , 22K ohm */ - { BOARD_VERSION_REV5, 666 }, /* 51.1K , 30K ohm */ - { BOARD_VERSION_REV6, 781 }, /* 51.1K , 39.2K ohm */ - { BOARD_VERSION_REV7, 900 }, /* 56K , 56K ohm */ - { BOARD_VERSION_REV8, 1023 }, /* 47K , 61.9K ohm */ - { BOARD_VERSION_REV9, 1137 }, /* 47K , 80.6K ohm */ + { BOARD_VERSION_REV0, 109 }, /* 51.1K , 2.2K(gru 3.3K) ohm */ + { BOARD_VERSION_REV1, 211 }, /* 51.1k , 6.8K ohm */ + { BOARD_VERSION_REV2, 319 }, /* 51.1K , 11K ohm */ + { BOARD_VERSION_REV3, 427 }, /* 56K , 17.4K ohm */ + { BOARD_VERSION_REV4, 542 }, /* 51.1K , 22K ohm */ + { BOARD_VERSION_REV5, 666 }, /* 51.1K , 30K ohm */ + { BOARD_VERSION_REV6, 781 }, /* 51.1K , 39.2K ohm */ + { BOARD_VERSION_REV7, 900 }, /* 56K , 56K ohm */ + { BOARD_VERSION_REV8, 1023 }, /* 47K , 61.9K ohm */ + { BOARD_VERSION_REV9, 1137 }, /* 47K , 80.6K ohm */ { BOARD_VERSION_REV10, 1240 }, /* 56K , 124K ohm */ { BOARD_VERSION_REV11, 1343 }, /* 51.1K , 150K ohm */ { BOARD_VERSION_REV12, 1457 }, /* 47K , 200K ohm */ @@ -347,18 +351,15 @@ int board_get_version(void) } /* Motion sensors */ -#ifdef HAS_TASK_MOTIONSENSE /* Mutexes */ static struct mutex g_base_mutex; static struct bmi_drv_data_t g_bmi160_data; /* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; static struct bmp280_drv_data_t bmp280_drv_data; @@ -378,7 +379,7 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .rot_standard_ref = &base_standard_ref, .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, @@ -401,18 +402,11 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_GYRO_MIN_FREQ, .max_frequency = BMI_GYRO_MAX_FREQ, - .config = { - /* Enable gyro in S0 */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, }, [LID_BARO] = { .name = "Baro", @@ -423,16 +417,15 @@ struct motion_sensor_t motion_sensors[] = { .drv = &bmp280_drv, .drv_data = &bmp280_drv_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = BIT(18), /* 1bit = 4 Pa, 16bit ~= 2600 hPa */ .min_frequency = BMP280_BARO_MIN_FREQ, .max_frequency = BMP280_BARO_MAX_FREQ, }, }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#endif /* defined(HAS_TASK_MOTIONSENSE) */ -int board_allow_i2c_passthru(int port) +int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc) { /* * Battery port is the only port passthru is allowed on and this board @@ -440,18 +433,3 @@ int board_allow_i2c_passthru(int port) */ return 0; } - -int charge_want_shutdown(void) -{ - /* - * power/rk3399.c assumes there is internal power. Therefore this stub - * returns false to prevent arbitrary shutdown. - */ - return 0; -} - -int charge_prevent_power_on(int power_button_pressed) -{ - /* Assume there is always sufficient power from charger to power on. */ - return 0; -} diff --git a/board/rainier/board.h b/board/rainier/board.h index 7ff319e0ea..745ebeaca8 100644 --- a/board/rainier/board.h +++ b/board/rainier/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,19 +10,18 @@ /* Optional modules */ #define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG +#undef CONFIG_ADC_WATCHDOG #define CONFIG_CHIPSET_RK3399 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_RTC #define CONFIG_HOSTCMD_RTC #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_I2C_PASSTHRU_RESTRICTED #define CONFIG_LOW_POWER_IDLE #define CONFIG_POWER_COMMON #define CONFIG_SPI -#define CONFIG_SPI_MASTER -#define CONFIG_STM_HWTIMER32 +#define CONFIG_SPI_CONTROLLER /* Source RTCCLK from external 32.768kHz source on PC15/OSC32_IN. */ #define CONFIG_STM32_CLOCK_LSE #define CONFIG_SWITCH @@ -30,11 +29,11 @@ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */ -#undef CONFIG_UART_CONSOLE +#undef CONFIG_UART_CONSOLE #define CONFIG_UART_CONSOLE 1 /* Region sizes are no longer a power of 2 so we can't enable MPU */ -#undef CONFIG_MPU +#undef CONFIG_MPU /* Enable a different power-on sequence than the one on gru */ #undef CONFIG_CHIPSET_POWER_SEQ_VERSION @@ -42,7 +41,6 @@ /* Optional features */ #define CONFIG_BOARD_PRE_INIT -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_BUTTON_TRIGGERED_RECOVERY #define CONFIG_CHARGER_ILIM_PIN_DISABLED #define CONFIG_FORCE_CONSOLE_RESUME @@ -56,7 +54,6 @@ #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_IGNORE_LID #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE -#define CONFIG_SOFTWARE_PANIC #define CONFIG_VBOOT_HASH #define CONFIG_VOLUME_BUTTONS @@ -68,7 +65,6 @@ /* Motion Sensors */ #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) #define CONFIG_BARO_BMP280 @@ -106,39 +102,38 @@ #define CONFIG_USB_PD_COMM_LOCKED #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 12850 +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 12850 -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ /* Timer selection */ -#define TIM_CLOCK32 2 +#define TIM_CLOCK32 2 #define TIM_WATCHDOG 7 /* 48 MHz SYSCLK clock frequency */ #define CPU_CLOCK 48000000 /* Optional for testing */ -#undef CONFIG_PECI -#undef CONFIG_PSTORE +#undef CONFIG_PECI +#undef CONFIG_PSTORE #define CONFIG_TASK_PROFILING #define I2C_PORT_TCPC0 1 /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ -#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO /* Define the host events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) #ifndef __ASSEMBLER__ diff --git a/board/rainier/build.mk b/board/rainier/build.mk index b77a900d56..b95d9dc46e 100644 --- a/board/rainier/build.mk +++ b/board/rainier/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/rainier/ec.tasklist b/board/rainier/ec.tasklist index ed574a1d6a..5008495942 100644 --- a/board/rainier/ec.tasklist +++ b/board/rainier/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/rainier/gpio.inc b/board/rainier/gpio.inc index 65bbfe1d6f..1cf1080e05 100644 --- a/board/rainier/gpio.inc +++ b/board/rainier/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -90,4 +90,4 @@ ALTERNATE(PIN_MASK(B, 0x0038), 0, MODULE_SPI, 0) /* SPI SLAVE CS: PA15 */ ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) /* SPI MASTER: PD1/3/4 */ -ALTERNATE(PIN_MASK(D, 0x001a), 1, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(D, 0x001a), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/rainier/usb_pd_policy.c b/board/rainier/usb_pd_policy.c index 6de1dc9271..b6c78d5e95 100644 --- a/board/rainier/usb_pd_policy.c +++ b/board/rainier/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,13 +13,13 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en; diff --git a/board/rainier/vif_override.xml b/board/rainier/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/rainier/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/rammus/battery.c b/board/rammus/battery.c index 916aac5fd3..9a538cc5e6 100644 --- a/board/rammus/battery.c +++ b/board/rammus/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -17,8 +17,8 @@ static enum battery_present batt_pres_prev = BP_NOT_SURE; /* Shutdown mode parameters to write to manufacturer access register */ -#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS -#define SB_SHUTDOWN_DATA 0x0010 +#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS +#define SB_SHUTDOWN_DATA 0x0010 static const struct battery_info info = { .voltage_max = 13200, @@ -63,8 +63,9 @@ static int battery_init(void) { int batt_status; - return battery_status(&batt_status) ? 0 : - !!(batt_status & STATUS_INITIALIZED); + return battery_status(&batt_status) ? + 0 : + !!(batt_status & STATUS_INITIALIZED); } /* @@ -85,13 +86,13 @@ static int battery_check_disconnect(void) uint8_t data[6]; /* Check if battery charging + discharging is disabled. */ - rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); + rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, SB_ALT_MANUFACTURER_ACCESS, + data, sizeof(data)); if (rv) return BATTERY_DISCONNECT_ERROR; - if ((data[3] & (BATTERY_DISCHARGING_DISABLED | - BATTERY_CHARGING_DISABLED)) == + if ((data[3] & + (BATTERY_DISCHARGING_DISABLED | BATTERY_CHARGING_DISABLED)) == (BATTERY_DISCHARGING_DISABLED | BATTERY_CHARGING_DISABLED)) return BATTERY_DISCONNECTED; @@ -127,4 +128,3 @@ enum battery_present battery_is_present(void) batt_pres_prev = batt_pres; return batt_pres; } - diff --git a/board/rammus/board.c b/board/rammus/board.c index 06210b2134..86bd039102 100644 --- a/board/rammus/board.c +++ b/board/rammus/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,25 +6,30 @@ /* Rammus board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "anx7447.h" #include "bd99992gw.h" #include "board_config.h" #include "button.h" +#include "cbi_ssfc.h" #include "charge_manager.h" -#include "charge_state.h" #include "charge_ramp.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" #include "console.h" #include "cros_board_info.h" -#include "driver/accelgyro_bmi_common.h" #include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accel_kx022.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/charger/isl923x.h" #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" #include "driver/temp_sensor/bd99992gw.h" +#include "espi.h" #include "extpower.h" #include "gpio.h" #include "hooks.h" @@ -35,6 +40,7 @@ #include "math_util.h" #include "motion_lid.h" #include "motion_sense.h" +#include "panic.h" #include "pi3usb9281.h" #include "power.h" #include "power_button.h" @@ -53,13 +59,12 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" -#include "espi.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) -#define USB_PD_PORT_PS8751 1 -#define USB_PD_PORT_ANX7447 0 +#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX7447 0 static void tcpc_alert_event(enum gpio_signal signal) { @@ -105,14 +110,15 @@ void vbus1_evt(enum gpio_signal signal) void usb0_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } void usb1_evt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Hibernate wake configuration */ @@ -126,23 +132,44 @@ const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* ADC channels */ const struct adc_t adc_channels[] = { /* Vbus sensing (10x voltage divider). */ - [ADC_VBUS] = {"VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT*10, ADC_READ_MAX+1, 0}, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH2, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* * Adapter current output or battery charging/discharging current (uV) * 18x amplification on charger side. */ - [ADC_AMON_BMON] = {"AMON_BMON", NPCX_ADC_CH1, ADC_MAX_VOLT*1000/18, - ADC_READ_MAX+1, 0}, + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH1, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* I2C port map */ -const struct i2c_port_t i2c_ports[] = { - {"i2c_0_0", NPCX_I2C_PORT0_0, 400, GPIO_I2C0_0_SCL, GPIO_I2C0_0_SDA}, - {"i2c_0_1", NPCX_I2C_PORT0_1, 400, GPIO_I2C0_1_SCL, GPIO_I2C0_1_SDA}, - {"i2c_1", NPCX_I2C_PORT1, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"i2c_2", NPCX_I2C_PORT2, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"i2c_3", NPCX_I2C_PORT3, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "i2c_0_0", + .port = NPCX_I2C_PORT0_0, + .kbps = 400, + .scl = GPIO_I2C0_0_SCL, + .sda = GPIO_I2C0_0_SDA }, + { .name = "i2c_0_1", + .port = NPCX_I2C_PORT0_1, + .kbps = 400, + .scl = GPIO_I2C0_1_SCL, + .sda = GPIO_I2C0_1_SDA }, + { .name = "i2c_1", + .port = NPCX_I2C_PORT1, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "i2c_2", + .port = NPCX_I2C_PORT2, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "i2c_3", + .port = NPCX_I2C_PORT3, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -161,7 +188,7 @@ struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -176,16 +203,20 @@ struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_PS8751] = { - .usb_port = USB_PD_PORT_PS8751, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_PS8751, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_ANX7447] = { - .usb_port = USB_PD_PORT_ANX7447, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_ANX7447, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, } }; @@ -228,7 +259,7 @@ static void ps8751_i2c_remap(void) uint32_t board_version; if (cbi_get_board_version(&board_version) != EC_SUCCESS || - board_version > 1) + board_version > 1) return; /* * Due to b/118063849, we separate the ps8751 and anx3447 to @@ -258,9 +289,10 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); uint16_t tcpc_get_alert_status(void) { @@ -280,17 +312,17 @@ uint16_t tcpc_get_alert_status(void) } const struct temp_sensor_t temp_sensors[] = { - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0}, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0 }, /* These BD99992GW temp sensors are only readable in S0 */ - {"Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM0}, - {"Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM1}, - {"DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM2}, - {"eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, - BD99992GW_ADC_CHANNEL_SYSTHERM3}, + { "Ambient", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM0 }, + { "Charger", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM1 }, + { "DRAM", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM2 }, + { "eMMC", TEMP_SENSOR_TYPE_BOARD, bd99992gw_get_val, + BD99992GW_ADC_CHANNEL_SYSTHERM3 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -306,8 +338,8 @@ static void board_report_pmic_fault(const char *str) uint32_t info; /* RESETIRQ1 -- Bit 4: VRFAULT */ - if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) - != EC_SUCCESS) + if (i2c_read8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x8, &vrfault) != + EC_SUCCESS) return; if (!(vrfault & BIT(4))) @@ -398,8 +430,7 @@ static void board_pmic_enable_slp_s0_vr_decay(void) i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992_FLAGS, 0x38, 0x7a); } -__override void power_board_handle_host_sleep_event( - enum host_sleep_event state) +__override void power_board_handle_host_sleep_event(enum host_sleep_event state) { if (state == HOST_SLEEP_EVENT_S0IX_SUSPEND) board_pmic_enable_slp_s0_vr_decay(); @@ -473,7 +504,7 @@ static void usb_charge_mode_init(void) * inhibit_charging_in_suspend. */ usb_charge_set_mode(0, CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE, - USB_DISALLOW_SUSPEND_CHARGE); + USB_DISALLOW_SUSPEND_CHARGE); } DECLARE_HOOK(HOOK_INIT, usb_charge_mode_init, HOOK_PRIO_DEFAULT + 1); @@ -517,36 +548,17 @@ int board_set_active_charge_port(int charge_port) } else { /* Make sure non-charging port is disabled */ gpio_set_level(charge_port ? GPIO_EN_USB_C0_CHARGE_EC_L : - GPIO_EN_USB_C1_CHARGE_EC_L, 1); + GPIO_EN_USB_C1_CHARGE_EC_L, + 1); /* Enable charging port */ gpio_set_level(charge_port ? GPIO_EN_USB_C1_CHARGE_EC_L : - GPIO_EN_USB_C0_CHARGE_EC_L, 0); + GPIO_EN_USB_C0_CHARGE_EC_L, + 0); } return EC_SUCCESS; } -/** - * Set the charge limit based upon desired maximum. - * - * @param port Port number. - * @param supplier Charge supplier type. - * @param charge_ma Desired charge limit (mA). - * @param charge_mv Negotiated charge voltage (mV). - */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* - * Limit the input current to 96% negotiated limit, - * to account for the charger chip margin. - */ - charge_ma = charge_ma * 96 / 100; - charge_set_input_current_limit( - MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} - void board_hibernate(void) { CPRINTS("Triggering PMIC shutdown."); @@ -583,21 +595,98 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; -/* BMA255 private data */ +/* private data */ static struct accelgyro_saved_data_t g_bma255_data; +static struct kionix_accel_data g_kx022_data; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0 }, - { 0, FLOAT_TO_FP(-1), 0 }, - { 0, 0, FLOAT_TO_FP(-1) } +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t base_standard_ref_icm = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t base_accel_icm = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, }; -const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0 }, - { 0, FLOAT_TO_FP(1), 0 }, - { 0, 0, FLOAT_TO_FP(-1) } +struct motion_sensor_t base_gyro_icm = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t lid_accel_kx022 = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support lid angle calculation. */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, }; struct motion_sensor_t motion_sensors[] = { @@ -676,9 +765,33 @@ struct motion_sensor_t motion_sensors[] = { }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +void motion_interrupt(enum gpio_signal signal) +{ + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) + icm426xx_interrupt(signal); + else + bmi160_interrupt(signal); +} + +static void board_detect_motionsense(void) +{ + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LID_KX022) { + motion_sensors[LID_ACCEL] = lid_accel_kx022; + ccprints("LID_ACCEL is KX022"); + } else + ccprints("LID_ACCEL is BMA253"); + + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) { + motion_sensors[BASE_ACCEL] = base_accel_icm; + motion_sensors[BASE_GYRO] = base_gyro_icm; + ccprints("BASE_ACCEL is ICM426XX"); + } else + ccprints("BASE_ACCEL is BMI160"); +} +DECLARE_HOOK(HOOK_INIT, board_detect_motionsense, HOOK_PRIO_DEFAULT); + /* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* If the lid is in 360 position, ignore the lid angle, * which might be faulty. Disable keyboard. @@ -687,7 +800,6 @@ void lid_angle_peripheral_enable(int enable) enable = 0; keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif static void board_chipset_reset(void) { diff --git a/board/rammus/board.h b/board/rammus/board.h index 7a569392a5..bfe8f75e53 100644 --- a/board/rammus/board.h +++ b/board/rammus/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,20 +8,28 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H +/* + * By default, enable all console messages excepted HC, ACPI and event: + * The sensor stack is generating a lot of activity. + */ +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + /* EC */ #define CONFIG_ADC #define CONFIG_BACKLIGHT_LID #define CONFIG_BOARD_VERSION_CBI #define CONFIG_BOARD_FORCE_RESET_PIN #define CONFIG_CRC8 -#define CONFIG_CROS_BOARD_INFO +#define CONFIG_CBI_EEPROM #define CONFIG_DPTF -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_KEYBOARD_COL2_INVERTED -#undef CONFIG_KEYBOARD_VIVALDI +#undef CONFIG_KEYBOARD_VIVALDI #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_LED_COMMON #define CONFIG_LID_SWITCH @@ -30,7 +38,6 @@ #define CONFIG_CHIP_PANIC_BACKUP #define CONFIG_PWM #define CONFIG_PWM_KBLIGHT -#define CONFIG_SOFTWARE_PANIC #define CONFIG_SPI_FLASH_REGS #define CONFIG_SPI_FLASH_W25X40 #define CONFIG_VBOOT_HASH @@ -58,9 +65,9 @@ #define CONFIG_CHIPSET_SKYLAKE #define CONFIG_CHIPSET_HAS_PLATFORM_PMIC_RESET #define CONFIG_CHIPSET_RESET_HOOK -#define CONFIG_HOSTCMD_ESPI -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -#define CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +#define CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 #define CONFIG_HOSTCMD_FLASH_SPI_INFO /* Battery */ @@ -68,7 +75,8 @@ #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_SMART -#define CONFIG_BATTERY_LEVEL_NEAR_FULL 94 +#undef CONFIG_BATT_HOST_FULL_FACTOR +#define CONFIG_BATT_HOST_FULL_FACTOR 94 /* Charger */ #define CONFIG_CHARGE_MANAGER @@ -77,16 +85,18 @@ #define CONFIG_CHARGER #define CONFIG_CHARGER_ISL9238 #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_PSYS #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 /* charger margin */ #define CONFIG_CMD_CHARGER_ADC_AMON_BMON #define CONFIG_HOSTCMD_PD_CONTROL #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS -#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 #define CONFIG_POWER_COMMON @@ -113,9 +123,12 @@ #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT #define CONFIG_ACCEL_BMA255 -#define CONFIG_ACCEL_INTERRUPTS +#define CONFIG_ACCEL_KX022 #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL @@ -130,13 +143,13 @@ /* Depends on how fast the AP boots and typical ODRs */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) -#undef CONFIG_UART_TX_BUF_SIZE +#undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 1024 #define CONFIG_TABLET_MODE #define CONFIG_TABLET_MODE_SWITCH #define CONFIG_GMR_TABLET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE +#define GPIO_TABLET_MODE_L GPIO_TABLET_MODE /* USB */ #define CONFIG_USB_CHARGER @@ -171,45 +184,45 @@ #define CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT 2 /* Optional feature to configure npcx chip */ -#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 as TACH */ +#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 as JTAG */ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 as TACH */ /* I2C ports */ -#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 -#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_1 -#define I2C_PORT_USB_CHARGER_1 NPCX_I2C_PORT0_1 -#define I2C_PORT_USB_CHARGER_0 NPCX_I2C_PORT1 -#define I2C_PORT_CHARGER NPCX_I2C_PORT1 -#define I2C_PORT_EEPROM NPCX_I2C_PORT0_0 -#define I2C_PORT_BATTERY NPCX_I2C_PORT1 -#define I2C_PORT_PMIC NPCX_I2C_PORT2 -#define I2C_PORT_MP2949 NPCX_I2C_PORT2 -#define I2C_PORT_GYRO NPCX_I2C_PORT3 -#define I2C_PORT_ACCEL I2C_PORT_GYRO -#define I2C_PORT_THERMAL I2C_PORT_PMIC +#define I2C_PORT_TCPC0 NPCX_I2C_PORT0_0 +#define I2C_PORT_TCPC1 NPCX_I2C_PORT0_1 +#define I2C_PORT_USB_CHARGER_1 NPCX_I2C_PORT0_1 +#define I2C_PORT_USB_CHARGER_0 NPCX_I2C_PORT1 +#define I2C_PORT_CHARGER NPCX_I2C_PORT1 +#define I2C_PORT_EEPROM NPCX_I2C_PORT0_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT1 +#define I2C_PORT_PMIC NPCX_I2C_PORT2 +#define I2C_PORT_MP2949 NPCX_I2C_PORT2 +#define I2C_PORT_GYRO NPCX_I2C_PORT3 +#define I2C_PORT_ACCEL I2C_PORT_GYRO +#define I2C_PORT_THERMAL I2C_PORT_PMIC /* I2C addresses */ -#define I2C_ADDR_BD99992_FLAGS 0x30 -#define I2C_ADDR_MP2949_FLAGS 0x20 -#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define I2C_ADDR_BD99992_FLAGS 0x30 +#define I2C_ADDR_MP2949_FLAGS 0x20 +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* Rename GPIOs */ -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_SUS_L GPIO_SLP_SUS_L_PCH -#define GPIO_RSMRST_L_PGOOD GPIO_ROP_EC_RSMRST_L -#define GPIO_PMIC_DPWROK GPIO_ROP_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_PWR_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN -#define GPIO_AC_PRESENT GPIO_ROP_EC_ACOK -#define GPIO_ENABLE_BACKLIGHT GPIO_BL_DISABLE_L -#define GPIO_CPU_PROCHOT GPIO_PCH_PROCHOT -#define GPIO_PCH_PWRBTN_L GPIO_PCH_PWR_BTN_L -#define GPIO_EC_PLATFORM_RST GPIO_PLATFORM_RST -#define GPIO_PMIC_SLP_SUS_L GPIO_SLP_SUS_L_PMIC -#define GPIO_USB_C0_5V_EN GPIO_EN_USB_C0_5V_OUT -#define GPIO_USB_C1_5V_EN GPIO_EN_USB_C1_5V_OUT +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_SUS_L GPIO_SLP_SUS_L_PCH +#define GPIO_PG_EC_RSMRST_ODL GPIO_ROP_EC_RSMRST_L +#define GPIO_PMIC_DPWROK GPIO_ROP_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_PWR_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN +#define GPIO_AC_PRESENT GPIO_ROP_EC_ACOK +#define GPIO_ENABLE_BACKLIGHT GPIO_BL_DISABLE_L +#define GPIO_CPU_PROCHOT GPIO_PCH_PROCHOT +#define GPIO_PCH_PWRBTN_L GPIO_PCH_PWR_BTN_L +#define GPIO_EC_PLATFORM_RST GPIO_PLATFORM_RST +#define GPIO_PMIC_SLP_SUS_L GPIO_SLP_SUS_L_PMIC +#define GPIO_USB_C0_5V_EN GPIO_EN_USB_C0_5V_OUT +#define GPIO_USB_C1_5V_EN GPIO_EN_USB_C1_5V_OUT #ifndef __ASSEMBLER__ @@ -217,11 +230,11 @@ #include "registers.h" enum temp_sensor_id { - TEMP_SENSOR_BATTERY, /* Smart Battery Temperature */ - TEMP_SENSOR_AMBIENT, /* BD99992GW SYSTHERM0 */ - TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ - TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ - TEMP_SENSOR_EMMC, /* BD99992GW SYSTHERM3 */ + TEMP_SENSOR_BATTERY, /* Smart Battery Temperature */ + TEMP_SENSOR_AMBIENT, /* BD99992GW SYSTHERM0 */ + TEMP_SENSOR_CHARGER, /* BD99992GW SYSTHERM1 */ + TEMP_SENSOR_DRAM, /* BD99992GW SYSTHERM2 */ + TEMP_SENSOR_EMMC, /* BD99992GW SYSTHERM3 */ TEMP_SENSOR_COUNT }; @@ -238,11 +251,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum adc_channel { - ADC_VBUS, - ADC_AMON_BMON, - ADC_CH_COUNT -}; +enum adc_channel { ADC_VBUS, ADC_AMON_BMON, ADC_CH_COUNT }; enum pwm_channel { PWM_CH_KBLIGHT, @@ -255,21 +264,21 @@ enum pwm_channel { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Board specific handlers */ void board_reset_pd_mcu(void); void board_set_tcpc_power_mode(int port, int mode); +void motion_interrupt(enum gpio_signal signal); /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) diff --git a/board/rammus/build.mk b/board/rammus/build.mk index 21f6e4c99e..9bc5e8a822 100644 --- a/board/rammus/build.mk +++ b/board/rammus/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -9,7 +9,7 @@ CHIP:=npcx CHIP_VARIANT:=npcx5m6g -board-y=board.o +board-y=board.o cbi_ssfc.o board-$(CONFIG_BATTERY_SMART)+=battery.o board-$(CONFIG_LED_COMMON)+=led.o board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o diff --git a/board/rammus/cbi_ssfc.c b/board/rammus/cbi_ssfc.c new file mode 100644 index 0000000000..99c303eac5 --- /dev/null +++ b/board/rammus/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union rammus_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_INIT_I2C + 1); + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return cached_ssfc.lid_sensor; +} + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return cached_ssfc.base_sensor; +} diff --git a/board/rammus/cbi_ssfc.h b/board/rammus/cbi_ssfc.h new file mode 100644 index 0000000000..e6351db03f --- /dev/null +++ b/board/rammus/cbi_ssfc.h @@ -0,0 +1,56 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _RAMMUS_CBI_SSFC__H_ +#define _RAMMUS_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Rammus CBI Second Source Factory Cache + */ + +/* + * Lid Sensor (Bits 2-0) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_LID_BMA255 = 1, + SSFC_SENSOR_LID_KX022 = 2 +}; + +/* + * Base Sensor (Bits 5-3) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BASE_BMI160 = 1, + SSFC_SENSOR_BASE_ICM426XX = 2, +}; + +union rammus_cbi_ssfc { + struct { + enum ec_ssfc_lid_sensor lid_sensor : 3; + enum ec_ssfc_base_sensor base_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +/** + * Get the base sensor type form SSFC_CONFIG. + * + * @return the base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +#endif /* _RAMMUS_CBI_SSFC__H_ */ diff --git a/board/rammus/ec.tasklist b/board/rammus/ec.tasklist index f708a41386..c2738d28b5 100644 --- a/board/rammus/ec.tasklist +++ b/board/rammus/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/rammus/gpio.inc b/board/rammus/gpio.inc index b55fe6b47c..df12930ccd 100644 --- a/board/rammus/gpio.inc +++ b/board/rammus/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -26,7 +26,7 @@ GPIO_INT(USB_C0_VBUS_DET_L, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, vbus0_ GPIO_INT(USB_C1_VBUS_DET_L, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, vbus1_evt) GPIO_INT(USB_C0_BC12_INT_L, PIN(D, 3), GPIO_INT_FALLING, usb0_evt) GPIO_INT(USB_C1_BC12_INT_L, PIN(3, 3), GPIO_INT_FALLING, usb1_evt) -GPIO_INT(BASE_SIXAXIS_INT_L, PIN(7, 3), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(7, 3), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) GPIO_INT(TABLET_MODE, PIN(C, 6), GPIO_INT_BOTH, gmr_tablet_switch_isr) GPIO(EN_PP3300_TRACKPAD, PIN(4, 5), GPIO_OUT_LOW) /* Enable TouchPad */ diff --git a/board/rammus/led.c b/board/rammus/led.c index a86e11e3a0..d40c39c649 100644 --- a/board/rammus/led.c +++ b/board/rammus/led.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -23,9 +23,8 @@ #define LED_CHARGE_PULSE 10 #define LED_POWER_PULSE 15 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -47,24 +46,20 @@ enum led_power_state { }; static const struct { - uint8_t led1:1; - uint8_t led2:1; -} led_chg_state_table[] = { - [LED_STATE_DISCHARGE] = {LED_OFF, LED_OFF}, - [LED_STATE_CHARGE] = {LED_OFF, LED_ON}, - [LED_STATE_FULL] = {LED_ON, LED_OFF}, - [LED_STATE_ERROR_PHASE0] = {LED_OFF, LED_OFF}, - [LED_STATE_ERROR_PHASE1] = {LED_OFF, LED_ON} -}; + uint8_t led1 : 1; + uint8_t led2 : 1; +} led_chg_state_table[] = { [LED_STATE_DISCHARGE] = { LED_OFF, LED_OFF }, + [LED_STATE_CHARGE] = { LED_OFF, LED_ON }, + [LED_STATE_FULL] = { LED_ON, LED_OFF }, + [LED_STATE_ERROR_PHASE0] = { LED_OFF, LED_OFF }, + [LED_STATE_ERROR_PHASE1] = { LED_OFF, LED_ON } }; static const struct { - uint8_t led:1; -} led_pwr_state_table[] = { - [LED_STATE_S0] = {LED_ON}, - [LED_STATE_S3_PHASE0] = {LED_OFF}, - [LED_STATE_S3_PHASE1] = {LED_ON}, - [LED_STATE_S5] = {LED_OFF} -}; + uint8_t led : 1; +} led_pwr_state_table[] = { [LED_STATE_S0] = { LED_ON }, + [LED_STATE_S3_PHASE0] = { LED_OFF }, + [LED_STATE_S3_PHASE1] = { LED_ON }, + [LED_STATE_S5] = { LED_OFF } }; void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) { @@ -100,7 +95,7 @@ static void rammus_led_set_power(void) chipset_state = chipset_in_state(CHIPSET_STATE_HARD_OFF) | (chipset_in_state(CHIPSET_STATE_SOFT_OFF) << 1) | - (chipset_in_state(CHIPSET_STATE_SUSPEND) << 2) | + (chipset_in_state(CHIPSET_STATE_SUSPEND) << 2) | (chipset_in_state(CHIPSET_STATE_ON) << 3) | (chipset_in_state(CHIPSET_STATE_STANDBY) << 4); @@ -128,36 +123,37 @@ static void rammus_led_set_power(void) static void rammus_led_set_battery(void) { - enum charge_state chg_state = charge_get_state(); + enum led_pwr_state chg_state = led_pwr_get_state(); int charge_percent = charge_get_percent(); static unsigned int charge_ticks; /* CHIPSET_STATE_OFF */ switch (chg_state) { - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if ((charge_get_flags() & CHARGE_FLAG_EXTERNAL_POWER) && - charge_percent >= BATTERY_LEVEL_NEAR_FULL) + charge_percent >= CONFIG_BATT_HOST_FULL_FACTOR) config_battery_led(LED_STATE_FULL); else config_battery_led(LED_STATE_DISCHARGE); charge_ticks = 0; break; - case PWR_STATE_CHARGE: + case LED_PWRS_CHARGE: config_battery_led(LED_STATE_CHARGE); charge_ticks = 0; break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: if ((charge_ticks++ % LED_TOTAL_TICKS) < LED_CHARGE_PULSE) config_battery_led(LED_STATE_ERROR_PHASE0); else config_battery_led(LED_STATE_ERROR_PHASE1); break; - case PWR_STATE_CHARGE_NEAR_FULL: - case PWR_STATE_IDLE: - if(charge_get_flags() & CHARGE_FLAG_EXTERNAL_POWER) - config_battery_led(LED_STATE_FULL); - else - config_battery_led(LED_STATE_OFF); + case LED_PWRS_CHARGE_NEAR_FULL: + case LED_PWRS_IDLE: + config_battery_led(LED_STATE_DISCHARGE); + charge_ticks = 0; + break; + case LED_PWRS_FORCED_IDLE: + config_battery_led(LED_STATE_FULL); charge_ticks = 0; break; default: diff --git a/board/rammus/usb_pd_policy.c b/board/rammus/usb_pd_policy.c index 652c9bb259..f048fc5738 100644 --- a/board/rammus/usb_pd_policy.c +++ b/board/rammus/usb_pd_policy.c @@ -1,14 +1,14 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -16,17 +16,17 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { @@ -53,7 +53,8 @@ int pd_set_power_supply_ready(int port) { /* Disable charging */ gpio_set_level(port ? GPIO_EN_USB_C1_CHARGE_EC_L : - GPIO_EN_USB_C0_CHARGE_EC_L, 1); + GPIO_EN_USB_C0_CHARGE_EC_L, + 1); /* Ensure we advertise the proper available current quota */ charge_manager_source_port(port, 1); @@ -103,13 +104,11 @@ int pd_check_vconn_swap(int port) return gpio_get_level(GPIO_SLP_SUS_L_PMIC); } -__override void pd_execute_data_swap(int port, - enum pd_data_role data_role) +__override void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* Only port 0 supports device mode. */ if (port != 0) return; - gpio_set_level(GPIO_USB2_ID2, - (data_role == PD_ROLE_UFP) ? 1 : 0); + gpio_set_level(GPIO_USB2_ID2, (data_role == PD_ROLE_UFP) ? 1 : 0); } diff --git a/board/rammus/vif_override.xml b/board/rammus/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/rammus/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/redrix/battery.c b/board/redrix/battery.c new file mode 100644 index 0000000000..c5c144113b --- /dev/null +++ b/board/redrix/battery.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "compile_time_macros.h" + +/* + * Battery info for all Redrix battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* DynaPack CosMX Battery Information */ + [BATTERY_DYNAPACK_COS] = { + .fuel_gauge = { + .manuf_name = "333-2C-14-A", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_DYNAPACK_COS; diff --git a/board/redrix/board.c b/board/redrix/board.c new file mode 100644 index 0000000000..84d4520e70 --- /dev/null +++ b/board/redrix/board.c @@ -0,0 +1,123 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/als_tcs3400.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "peripheral_charger.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* Battery discharging over-current limit is 8A */ +#define BATT_OC_LIMIT -8000 + +/* PCHG control */ +#ifdef SECTION_IS_RW +extern struct pchg_drv ctn730_drv; + +struct pchg pchgs[] = { + [0] = { + .cfg = &(const struct pchg_config) { + .drv = &ctn730_drv, + .i2c_port = I2C_PORT_WLC, + .irq_pin = GPIO_PEN_INT_ODL, + .full_percent = 96, + .block_size = 128, + /* A stylus needs about 700ms to complete recovery */ + .rf_charge_msec = 1000, + }, + .policy = { + [PCHG_CHIPSET_STATE_ON] = &pchg_policy_on, + [PCHG_CHIPSET_STATE_SUSPEND] = &pchg_policy_suspend, + }, + .events = QUEUE_NULL(PCHG_EVENT_QUEUE_SIZE, enum pchg_event), + }, +}; + +int board_get_pchg_count(void) +{ + return ARRAY_SIZE(pchgs); +} +#endif + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +enum battery_present battery_hw_present(void) +{ + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} + +int charger_profile_override(struct charge_state_data *curr) +{ + /* Turn off haptic pad LRA if battery discharing current over 8A */ + if (!(curr->batt.flags & BATT_FLAG_BAD_CURRENT) && + curr->batt.current < BATT_OC_LIMIT) + gpio_set_level(GPIO_LRA_DIS_ODL, 0); + else + gpio_set_level(GPIO_LRA_DIS_ODL, 1); + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/redrix/board.h b/board/redrix/board.h new file mode 100644 index 0000000000..65f63dc0bb --- /dev/null +++ b/board/redrix/board.h @@ -0,0 +1,267 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Redrix board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* Increase tx buffer size. */ +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 8192 + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +/* Chipset */ +#define CONFIG_CHIPSET_RESUME_INIT_HOOK + +/* Sensors */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCEL_BMA4XX /* 2nd source Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +/* TCS3400 ALS */ +#define CONFIG_ALS +#define ALS_COUNT 1 +#define CONFIG_ALS_TCS3400 +#define CONFIG_ALS_TCS3400_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) + +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* WLC pins */ +#ifdef SECTION_IS_RW +#define CONFIG_PERIPHERAL_CHARGER +#define CONFIG_DEVICE_EVENT +#define CONFIG_CTN730 +#define CONFIG_MKBP_EVENT_WAKEUP_MASK (BIT(EC_MKBP_EVENT_PCHG)) +#endif + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 6 + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 + +#define CONFIG_USB_PD_FRS_PPC + +#define CONFIG_USBC_RETIMER_INTEL_BB + +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_NX20P3483 + +/* TODO: b/193452481 - measure and check these values on redrix */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +#define GPIO_WLC_NRST_CONN GPIO_PEN_RST_L + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_WLC NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* + * see b/174768555#comment22 + */ +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x58 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* Fan features */ +#define CONFIG_FANS FAN_CH_COUNT +#define CONFIG_CUSTOM_FAN_CONTROL +#define RPM_DEVIATION 1 + +/* Charger defines */ +#define CONFIG_CHARGER_BQ25720 +/* + * b/202915015: The IDCHG current limit is set in 512 mA steps. + * The value set here is somewhat specific to the battery pack being + * currently used. The limit here was set based on the battery's + * discharge current limit and what was tested to prevent the AP + * rebooting with low charge level batteries. + */ +#define CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA 8192 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 70 +#define CONFIG_CHARGE_RAMP_HW +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_PROFILE_OVERRIDE + +/* Keyboard features */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR, + ADC_TEMP_SENSOR_2_SOC, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_TEMP_SENSOR_4_REGULATOR, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR, + TEMP_SENSOR_2_SOC, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_4_REGULATOR, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + CLEAR_ALS, + RGB_ALS, + SENSOR_COUNT +}; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_C1_NCT38XX, IOEX_PORT_COUNT }; + +enum battery_type { BATTERY_DYNAPACK_COS, BATTERY_TYPE_COUNT }; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_FAN2, /* PWM7 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_1, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_1, MFT_CH_COUNT }; + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +extern const int keyboard_factory_scan_pins[][2]; +extern const int keyboard_factory_scan_pins_used; +#endif + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/redrix/build.mk b/board/redrix/build.mk new file mode 100644 index 0000000000..e021ebc4f4 --- /dev/null +++ b/board/redrix/build.mk @@ -0,0 +1,27 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Redrix board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=cbi_ssfc.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=thermal.o +board-y+=usbc_config.o diff --git a/board/redrix/cbi_ssfc.c b/board/redrix/cbi_ssfc.c new file mode 100644 index 0000000000..e0e954a7a6 --- /dev/null +++ b/board/redrix/cbi_ssfc.c @@ -0,0 +1,30 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union redrix_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +void board_init_ssfc(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return cached_ssfc.lid_sensor; +} diff --git a/board/redrix/cbi_ssfc.h b/board/redrix/cbi_ssfc.h new file mode 100644 index 0000000000..724daa3782 --- /dev/null +++ b/board/redrix/cbi_ssfc.h @@ -0,0 +1,39 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _REDRIX_CBI_SSFC_H_ +#define _REDRIX_CBI_SSFC_H_ + +#include "stdint.h" + +/**************************************************************************** + * Redrix CBI Second Source Factory Cache + */ + +/* + * Lid Sensor (Bits 0-1) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_LID_BMA253 = 1, + SSFC_SENSOR_LID_BMA422 = 2 +}; + +union redrix_cbi_ssfc { + struct { + enum ec_ssfc_lid_sensor lid_sensor : 2; + uint32_t reserved_1 : 30; + }; + uint32_t raw_value; +}; + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _REDRIX_CBI_SSFC_H_ */ diff --git a/board/redrix/charger.c b/board/redrix/charger.c new file mode 100644 index 0000000000..827152e115 --- /dev/null +++ b/board/redrix/charger.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/redrix/ec.tasklist b/board/redrix/ec.tasklist new file mode 100644 index 0000000000..f755b40858 --- /dev/null +++ b/board/redrix/ec.tasklist @@ -0,0 +1,31 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(LED, led_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS_RW(PCHG, pchg_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/redrix/fans.c b/board/redrix/fans.c new file mode 100644 index 0000000000..905e5b8ad7 --- /dev/null +++ b/board/redrix/fans.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, + [MFT_CH_1] = { + .module = NPCX_MFT_MODULE_2, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN2, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_conf fan_conf_1 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_1, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN2, +}; + +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 1900, + .rpm_start = 2900, + .rpm_max = 7300, +}; + +static const struct fan_rpm fan_rpm_1 = { + .rpm_min = 1900, + .rpm_start = 2900, + .rpm_max = 7300, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, + [FAN_CH_1] = { + .conf = &fan_conf_1, + .rpm = &fan_rpm_1, + }, +}; diff --git a/board/redrix/fw_config.c b/board/redrix/fw_config.c new file mode 100644 index 0000000000..cfbf46291c --- /dev/null +++ b/board/redrix/fw_config.c @@ -0,0 +1,55 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union redrix_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for redrix if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union redrix_cbi_fw_config fw_config_defaults = { + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Redrix FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* + * Early boards have a zero'd out FW_CONFIG, so replace + * it with a sensible default value. + */ + if (fw_config.raw_value == 0) { + CPRINTS("CBI: FW_CONFIG is zero, using board defaults"); + fw_config = fw_config_defaults; + } + } +} + +union redrix_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +bool ec_cfg_has_eps(void) +{ + return (fw_config.eps == EPS_ENABLED); +} diff --git a/board/redrix/fw_config.h b/board/redrix/fw_config.h new file mode 100644 index 0000000000..02157bf23e --- /dev/null +++ b/board/redrix/fw_config.h @@ -0,0 +1,52 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_REDRIX_FW_CONFIG_H_ +#define __BOARD_REDRIX_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Redrix board. + * + * Source of truth is the project/brya/redrix/config.star configuration file. + */ + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_eps_type { EPS_DISABLED = 0, EPS_ENABLED = 1 }; + +union redrix_cbi_fw_config { + struct { + uint32_t sd_db : 2; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t lte_db : 2; + uint32_t ufc : 2; + enum ec_cfg_eps_type eps : 1; + uint32_t reserved_1 : 21; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union redrix_cbi_fw_config get_fw_config(void); + +/** + * Check if the FW_CONFIG has enabled privacy screen. + * + * @return true if board supports privacy screen, false if the board + * doesn't support it. + */ +bool ec_cfg_has_eps(void); + +#endif /* __BOARD_REDRIX_FW_CONFIG_H_ */ diff --git a/board/redrix/gpio.inc b/board/redrix/gpio.inc new file mode 100644 index 0000000000..0f39efe33b --- /dev/null +++ b/board/redrix/gpio.inc @@ -0,0 +1,153 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_ALS_RGB_INT_R_L, PIN(D, 4), GPIO_INT_FALLING, tcs3400_interrupt) +GPIO_INT(EC_IMU_INT_R_L, PIN(5, 6), GPIO_SEL_1P8V | GPIO_INT_FALLING, lsm6dsm_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_RT_INT_ODL, PIN(4, 1), GPIO_INT_FALLING, retimer_interrupt) + +/* WLC interrupt. GPIO_PULL_DOWN ensures no IRQ when WLC chip is off. */ +#ifdef SECTION_IS_RW +GPIO_INT(PEN_INT_ODL, PIN(F, 5), GPIO_INT_RISING | GPIO_PULL_DOWN, pchg_irq) +#endif + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(9, 6), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_FAN2, PIN(5, 0), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_TCPC_RST_ODL, PIN(A, 0), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(PEN_RST_L, PIN(0, 2), GPIO_ODR_HIGH) +GPIO(LRA_DIS_ODL, PIN(0, 4), GPIO_ODR_HIGH) /* Disable haptic pad LRA */ + +/* LED */ +GPIO(C0_CHARGE_LED_AMBER_L, PIN(C, 4), GPIO_OUT_HIGH) /* Amber C0 port */ +GPIO(C0_CHARGE_LED_WHITE_L, PIN(C, 3), GPIO_OUT_HIGH) /* White C0 port */ +GPIO(C1_CHARGE_LED_AMBER_L, PIN(5, 7), GPIO_OUT_HIGH) /* Amber C1 port */ +GPIO(C1_CHARGE_LED_WHITE_L, PIN(9, 4), GPIO_OUT_HIGH) /* White C1 port */ +GPIO(PWR_LED_WHITE_L, PIN(C, 2), GPIO_OUT_HIGH) /* Power LED */ + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* GPIO73/TA2 */ +ALTERNATE(PIN_MASK(6, 0x01), 0, MODULE_PWM, 0) /* GPIO60/PWM7 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xe0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPO66/ARM_L_x86 */ +UNUSED(PIN(8, 2)) /* KSO14/GPIO82 */ + +/* Pre-configured PSL balls: J8 K6 */ + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C1_FRS_EN, EXPIN(IOEX_C1_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C1_RT_RST_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 7), GPIO_ODR_LOW) diff --git a/board/redrix/i2c.c b/board/redrix/i2c.c new file mode 100644 index 0000000000..c1a0c31b40 --- /dev/null +++ b/board/redrix/i2c.c @@ -0,0 +1,77 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0", + .port = I2C_PORT_USB_C0_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0", + .port = I2C_PORT_USB_C0_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_RT_SCL, + .sda = GPIO_EC_I2C_USB_C0_RT_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1,retimer1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "charger,eeprom,wlc", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/redrix/keyboard.c b/board/redrix/keyboard.c new file mode 100644 index 0000000000..11cfaaa02d --- /dev/null +++ b/board/redrix/keyboard.c @@ -0,0 +1,93 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config keybd1 = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_KBD_BKLIGHT_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config keybd2 = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_PRIVACY_SCRN_TOGGLE, /* T8 */ + TK_KBD_BKLIGHT_TOGGLE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (ec_cfg_has_eps() == 0) + return &keybd1; + else + return &keybd2; +} + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/redrix/led.c b/board/redrix/led.c new file mode 100644 index 0000000000..66170766c2 --- /dev/null +++ b/board/redrix/led.c @@ -0,0 +1,252 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Redrix + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "host_command.h" +#include "led_common.h" +#include "task.h" + +#include + +#define BAT_LED_ON 0 +#define BAT_LED_OFF 1 + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +#define LED_TICK_INTERVAL_MS (500 * MSEC) +#define LED_CYCLE_TIME_MS (2000 * MSEC) +#define LED_TICKS_PER_CYCLE (LED_CYCLE_TIME_MS / LED_TICK_INTERVAL_MS) +#define LED_ON_TIME_MS (1000 * MSEC) +#define LED_ON_TICKS (LED_ON_TIME_MS / LED_TICK_INTERVAL_MS) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +enum led_port { LEFT_PORT = 0, RIGHT_PORT }; + +static void led_set_color_battery(int port, enum led_color color) +{ + enum gpio_signal amber_led, white_led; + + amber_led = (port == RIGHT_PORT ? GPIO_C1_CHARGE_LED_AMBER_L : + GPIO_C0_CHARGE_LED_AMBER_L); + white_led = (port == RIGHT_PORT ? GPIO_C1_CHARGE_LED_WHITE_L : + GPIO_C0_CHARGE_LED_WHITE_L); + + switch (color) { + case LED_WHITE: + gpio_set_level(white_led, BAT_LED_ON); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + case LED_AMBER: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_ON); + break; + case LED_OFF: + gpio_set_level(white_led, BAT_LED_OFF); + gpio_set_level(amber_led, BAT_LED_OFF); + break; + default: + break; + } +} + +void led_set_color_power(enum led_color color) +{ + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_OFF); + break; + case LED_WHITE: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_ON); + break; + default: + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_RIGHT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_POWER_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + break; + default: + break; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LEFT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LEFT_PORT, LED_AMBER); + else + led_set_color_battery(LEFT_PORT, LED_OFF); + break; + case EC_LED_ID_RIGHT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(RIGHT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(RIGHT_PORT, LED_AMBER); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + break; + case EC_LED_ID_POWER_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(LED_WHITE); + else + led_set_color_power(LED_OFF); + break; + default: + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int port = charge_manager_get_active_charge_port(); + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + led_set_color_battery(RIGHT_PORT, + (port == RIGHT_PORT) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, + (port == LEFT_PORT) ? color : LED_OFF); +} + +static void led_set_battery(void) +{ + static unsigned int battery_ticks; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + if (charge_get_percent() < 10) + led_set_color_battery( + RIGHT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) { + if (charge_get_percent() < 10) + led_set_color_battery( + LEFT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(LEFT_PORT, LED_OFF); + } + break; + case LED_PWRS_ERROR: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + led_set_color_battery( + RIGHT_PORT, + (battery_ticks & 0x1) ? LED_AMBER : LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) { + led_set_color_battery(LEFT_PORT, (battery_ticks & 0x1) ? + LED_AMBER : + LED_OFF); + } + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +static void led_set_power(void) +{ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_set_color_power(LED_WHITE); + else + led_set_color_power(LED_OFF); +} + +void led_task(void *u) +{ + uint32_t start_time; + uint32_t task_duration; + + while (1) { + start_time = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + led_set_power(); + + led_set_battery(); + + /* Compute time for this iteration */ + task_duration = get_time().le.lo - start_time; + /* + * Compute wait time required to for next desired LED tick. If + * the duration exceeds the tick time, then don't sleep. + */ + if (task_duration < LED_TICK_INTERVAL_MS) + usleep(LED_TICK_INTERVAL_MS - task_duration); + } +} diff --git a/board/redrix/pwm.c b/board/redrix/pwm.c new file mode 100644 index 0000000000..12f8d7ed9f --- /dev/null +++ b/board/redrix/pwm.c @@ -0,0 +1,35 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, + [PWM_CH_FAN2] = { + .channel = 7, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/board/redrix/sensors.c b/board/redrix/sensors.c new file mode 100644 index 0000000000..fa7a9ea670 --- /dev/null +++ b/board/redrix/sensors.c @@ -0,0 +1,383 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc_chip.h" +#include "cbi_ssfc.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_bma422.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/als_tcs3400_public.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR] = { + .name = "TEMP_DDR", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_SOC] = { + .name = "TEMP_SOC", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_REGULATOR] = { + .name = "TEMP_REGULATOR", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +static struct accelgyro_saved_data_t g_bma253_data; +static struct accelgyro_saved_data_t g_bma422_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* TCS3400 private data */ +static struct als_drv_data_t g_tcs3400_data = { + .als_cal.scale = 1, + .als_cal.uscale = 0, + .als_cal.offset = 0, + .als_cal.channel_scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ + .cover_scale = ALS_CHANNEL_SCALE(0.98), /* CT */ + }, +}; + +/* + * TODO: b/184702900 need to calibrate ALS/RGB sensor. At default settings, + * shining phone flashlight on sensor pegs all readings at 0xFFFF. + */ +static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { + .calibration.rgb_cal[X] = { + .offset = 66, /* 66.47729532 */ + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0.00222243), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0.51877192), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(-0.28664117), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.0586877), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ + .cover_scale = ALS_CHANNEL_SCALE(0.61) + } + }, + .calibration.rgb_cal[Y] = { + .offset = 41, /* 40.95355984 */ + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(-0.15384715), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0.40454969), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(-0.237452), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.13102168), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + }, + .calibration.rgb_cal[Z] = { + .offset = 5, /* 5.08596128 */ + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(-0.79005309), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(-0.35553576), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0.13997097), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.40223911), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ + .cover_scale = ALS_CHANNEL_SCALE(1.6) + } + }, + .calibration.irt = FLOAT_TO_FP(0.41), + .saturation.again = TCS_DEFAULT_AGAIN, + .saturation.atime = TCS_DEFAULT_ATIME, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + }, + + [CLEAR_ALS] = { + .name = "Clear Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &tcs3400_drv, + .drv_data = &g_tcs3400_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + .min_frequency = TCS3400_LIGHT_MIN_FREQ, + .max_frequency = TCS3400_LIGHT_MAX_FREQ, + .config = { + /* Run ALS sensor in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 1000, + }, + }, + }, + + [RGB_ALS] = { + /* + * RGB channels read by CLEAR_ALS and so the i2c port and + * address do not need to be defined for RGB_ALS. + */ + .name = "RGB Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT_RGB, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &tcs3400_rgb_drv, + .drv_data = &g_tcs3400_rgb_data, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t bma422_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_PRIMARY, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g, enough for laptop. */ + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, +}; + +static void board_update_motion_sensor_config(void) +{ + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LID_BMA422) + motion_sensors[LID_ACCEL] = bma422_lid_accel; +} + +/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ +const struct motion_sensor_t *motion_als_sensors[] = { + &motion_sensors[CLEAR_ALS], +}; +BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); + +static void board_sensors_init(void) +{ + /* Enable interrupt for the TCS3400 color light sensor */ + gpio_enable_interrupt(GPIO_EC_ALS_RGB_INT_R_L); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_R_L); + + board_update_motion_sensor_config(); +} +DECLARE_HOOK(HOOK_INIT, board_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR] = { .name = "DDR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR }, + [TEMP_SENSOR_2_SOC] = { .name = "SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_SOC }, + [TEMP_SENSOR_3_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER }, + [TEMP_SENSOR_4_REGULATOR] = { .name = "Regulator", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_REGULATOR }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_DDR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_ddr = THERMAL_DDR; + +/* + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to SOC, so we need to use the lower + * SOC temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_REGULATOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_regulator = + THERMAL_REGULATOR; + +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR] = THERMAL_DDR, + [TEMP_SENSOR_2_SOC] = THERMAL_CPU, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, + [TEMP_SENSOR_4_REGULATOR] = THERMAL_REGULATOR, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/redrix/thermal.c b/board/redrix/thermal.c new file mode 100644 index 0000000000..e192157943 --- /dev/null +++ b/board/redrix/thermal.c @@ -0,0 +1,215 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "builtin/assert.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "fan.h" +#include "hooks.h" +#include "host_command.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +struct fan_step { + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t on[TEMP_SENSOR_COUNT]; + + /* + * Sensor 1~4 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t off[TEMP_SENSOR_COUNT]; + + /* Fan 1~2 rpm */ + uint16_t rpm[FAN_CH_COUNT]; +}; + +static const struct fan_step *fan_step_table; + +static const struct fan_step fan_table_clamshell[] = { + { + /* level 0 */ + .on = { 53, 53, 0, -1 }, + .off = { 99, 99, 99, -1 }, + .rpm = { 0, 0 }, + }, + { + /* level 1 */ + .on = { 54, 54, 0, -1 }, + .off = { 53, 53, 99, -1 }, + .rpm = { 3900, 4300 }, + }, + { + /* level 2 */ + .on = { 55, 55, 0, -1 }, + .off = { 54, 54, 99, -1 }, + .rpm = { 4800, 5200 }, + }, + { + /* level 3 */ + .on = { 56, 56, 0, -1 }, + .off = { 54, 55, 99, -1 }, + .rpm = { 5000, 5500 }, + }, + { + /* level 4 */ + .on = { 57, 57, 61, -1 }, + .off = { 56, 56, 59, -1 }, + .rpm = { 5200, 5700 }, + }, + { + /* level 5 */ + .on = { 58, 58, 63, -1 }, + .off = { 57, 57, 61, -1 }, + .rpm = { 5700, 6200 }, + }, + { + /* level 6 */ + .on = { 100, 100, 100, -1 }, + .off = { 58, 58, 63, -1 }, + .rpm = { 6200, 6400 }, + }, +}; + +static const struct fan_step fan_table_tablet[] = { + { + /* level 0 */ + .on = { 52, 55, 0, -1 }, + .off = { 99, 99, 99, -1 }, + .rpm = { 0, 0 }, + }, + { + /* level 1 */ + .on = { 53, 56, 0, -1 }, + .off = { 52, 55, 99, -1 }, + .rpm = { 4100, 4200 }, + }, + { + /* level 2 */ + .on = { 54, 57, 0, -1 }, + .off = { 53, 56, 99, -1 }, + .rpm = { 4500, 4800 }, + }, + { + /* level 3 */ + .on = { 55, 58, 0, -1 }, + .off = { 54, 57, 99, -1 }, + .rpm = { 4800, 5200 }, + }, + { + /* level 4 */ + .on = { 56, 59, 61, -1 }, + .off = { 55, 58, 59, -1 }, + .rpm = { 5100, 5400 }, + }, + { + /* level 5 */ + .on = { 57, 60, 63, -1 }, + .off = { 56, 59, 61, -1 }, + .rpm = { 5500, 5800 }, + }, + { + /* level 6 */ + .on = { 100, 100, 100, -1 }, + .off = { 57, 60, 63, -1 }, + .rpm = { 6000, 6200 }, + }, +}; + +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_table_clamshell) + +BUILD_ASSERT(ARRAY_SIZE(fan_table_clamshell) == ARRAY_SIZE(fan_table_tablet)); + +int fan_table_to_rpm(int fan, int *temp) +{ + static int current_level; + static int prev_tmp[TEMP_SENSOR_COUNT]; + int new_rpm = 0; + int i; + + if (tablet_get_mode()) + fan_step_table = fan_table_tablet; + else + fan_step_table = fan_table_clamshell; + + /* + * Compare the current and previous temperature, we have + * the three paths : + * 1. decreasing path. (check the release point) + * 2. increasing path. (check the trigger point) + * 3. invariant path. (return the current RPM) + */ + if (temp[TEMP_SENSOR_1_DDR] < prev_tmp[TEMP_SENSOR_1_DDR] || + temp[TEMP_SENSOR_2_SOC] < prev_tmp[TEMP_SENSOR_2_SOC] || + temp[TEMP_SENSOR_3_CHARGER] < prev_tmp[TEMP_SENSOR_3_CHARGER]) { + for (i = current_level; i > 0; i--) { + if (temp[TEMP_SENSOR_1_DDR] < + fan_step_table[i].off[TEMP_SENSOR_1_DDR] && + temp[TEMP_SENSOR_3_CHARGER] < + fan_step_table[i] + .off[TEMP_SENSOR_3_CHARGER] && + temp[TEMP_SENSOR_2_SOC] < + fan_step_table[i].off[TEMP_SENSOR_2_SOC]) + current_level = i - 1; + else + break; + } + } else if (temp[TEMP_SENSOR_1_DDR] > prev_tmp[TEMP_SENSOR_1_DDR] || + temp[TEMP_SENSOR_2_SOC] > prev_tmp[TEMP_SENSOR_2_SOC] || + temp[TEMP_SENSOR_3_CHARGER] > + prev_tmp[TEMP_SENSOR_3_CHARGER]) { + for (i = current_level; i < NUM_FAN_LEVELS; i++) { + if ((temp[TEMP_SENSOR_1_DDR] > + fan_step_table[i].on[TEMP_SENSOR_1_DDR] && + temp[TEMP_SENSOR_3_CHARGER] > + fan_step_table[i] + .on[TEMP_SENSOR_3_CHARGER]) || + temp[TEMP_SENSOR_2_SOC] > + fan_step_table[i].on[TEMP_SENSOR_2_SOC]) + current_level = i + 1; + else + break; + } + } + + if (current_level < 0) + current_level = 0; + + for (i = 0; i < TEMP_SENSOR_COUNT; ++i) + prev_tmp[i] = temp[i]; + + ASSERT(current_level < NUM_FAN_LEVELS); + + switch (fan) { + case FAN_CH_0: + new_rpm = fan_step_table[current_level].rpm[FAN_CH_0]; + break; + case FAN_CH_1: + new_rpm = fan_step_table[current_level].rpm[FAN_CH_1]; + break; + default: + break; + } + + return new_rpm; +} + +void board_override_fan_control(int fan, int *tmp) +{ + if (chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND)) { + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), fan_table_to_rpm(fan, tmp)); + } +} diff --git a/board/redrix/usbc_config.c b/board/redrix/usbc_config.c new file mode 100644 index 0000000000..70e9a7dfd4 --- /dev/null +++ b/board/redrix/usbc_config.c @@ -0,0 +1,321 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_4_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .frs_en = IOEX_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + /* + * A USB-A adapter plugged into Type-C port + * would increase BBR power consumption, so + * clear USB3_Connection bit in S0ix and + * re-enable in S0 + */ + .flags = USB_MUX_FLAG_CAN_IDLE, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .flags = USB_MUX_FLAG_CAN_IDLE, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C1 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C1_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_4_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) { + rst_signal = IOEX_USB_C0_RT_RST_ODL; + } else if (me->usb_port == USBC_PORT_C1) { + rst_signal = IOEX_USB_C1_RT_RST_ODL; + } else { + return EC_ERROR_INVAL; + } + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 0); + gpio_set_level(GPIO_USB_C1_TCPC_RST_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + msleep(NCT38XX_RESET_HOLD_DELAY_MS); + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_TCPC_RST_ODL, 1); + + nct38xx_reset_notify(USBC_PORT_C0); + nct38xx_reset_notify(USBC_PORT_C1); + + /* wait for chips to come up */ + if (NCT3807_RESET_POST_DELAY_MS != 0) + msleep(NCT3807_RESET_POST_DELAY_MS); +} + +static void board_tcpc_init(void) +{ + int i; + + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C1 TCPCs, so they must be set up after the TCPCs has + * been taken out of reset. + */ + for (i = 0; i < CONFIG_IO_EXPANDER_PORT_COUNT; ++i) + ioex_init(i); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} diff --git a/board/redrix/usbc_config.h b/board/redrix/usbc_config.h new file mode 100644 index 0000000000..248e697572 --- /dev/null +++ b/board/redrix/usbc_config.h @@ -0,0 +1,15 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Redrix board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/redrix/vif_override.xml b/board/redrix/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/redrix/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/reef/battery.c b/board/reef/battery.c index 83a3679b26..52ec2a0471 100644 --- a/board/reef/battery.c +++ b/board/reef/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -20,7 +20,7 @@ #include "i2c.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) enum battery_type { BATTERY_SONY_CORP, @@ -135,7 +135,7 @@ const struct battery_info batt_info_smp_cos4870 = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 46, .charging_min_c = 0, @@ -183,7 +183,7 @@ const struct battery_info batt_info_sonycorp = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 50, .charging_min_c = 0, @@ -240,7 +240,7 @@ const struct battery_info batt_info_panasoic = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 50, .charging_min_c = 0, @@ -384,7 +384,7 @@ const struct battery_info batt_info_c22n1626 = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 45, .charging_min_c = 0, @@ -398,7 +398,7 @@ static int batt_smp_cos4870_init(void) int batt_status; return battery_status(&batt_status) ? 0 : - batt_status & STATUS_INITIALIZED; + batt_status & STATUS_INITIALIZED; } static int batt_sony_corp_init(void) @@ -411,8 +411,9 @@ static int batt_sony_corp_init(void) * : 0b - Allowed to Discharge * : 1b - Not Allowed to Discharge */ - return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? 0 : - !(batt_status & SONY_DISCHARGE_DISABLE_FET_BIT); + return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? + 0 : + !(batt_status & SONY_DISCHARGE_DISABLE_FET_BIT); } static int batt_panasonic_init(void) @@ -425,8 +426,9 @@ static int batt_panasonic_init(void) * : 0b - Not Allowed to Discharge * : 1b - Allowed to Discharge */ - return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? 0 : - !!(batt_status & PANASONIC_DISCHARGE_ENABLE_FET_BIT); + return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? + 0 : + !!(batt_status & PANASONIC_DISCHARGE_ENABLE_FET_BIT); } static int batt_c22n1626_init(void) @@ -439,8 +441,9 @@ static int batt_c22n1626_init(void) * : 0b - Not Allowed to Discharge * : 1b - Allowed to Discharge */ - return sb_read(SB_PACK_STATUS, &batt_status) ? 0 : - !!(batt_status & C22N1626_DISCHARGE_ENABLE_FET_BIT); + return sb_read(SB_PACK_STATUS, &batt_status) ? + 0 : + !!(batt_status & C22N1626_DISCHARGE_ENABLE_FET_BIT); } static const struct ship_mode_info ship_mode_info_smp_cos4870 = { @@ -461,7 +464,7 @@ static const struct ship_mode_info ship_mode_info_panasonic = { .batt_init = batt_panasonic_init, }; -static const struct ship_mode_info ship_mode_info_c22n1626= { +static const struct ship_mode_info ship_mode_info_c22n1626 = { .ship_mode_reg = 0x00, .ship_mode_data = 0x0010, .batt_init = batt_c22n1626_init, @@ -513,7 +516,8 @@ BUILD_ASSERT(ARRAY_SIZE(info) == BATTERY_TYPE_COUNT); static inline const struct board_batt_params *board_get_batt_params(void) { return &info[board_battery_type == BATTERY_TYPE_COUNT ? - DEFAULT_BATTERY_TYPE : board_battery_type]; + DEFAULT_BATTERY_TYPE : + board_battery_type]; } enum battery_present battery_hw_present(void) @@ -540,8 +544,9 @@ static int board_get_battery_type(void) /* Initialize fast charging parameters */ chg_params = board_get_batt_params()->fast_chg_params; - prev_chg_profile_info = &chg_params->chg_profile_info[ - chg_params->default_temp_range_profile]; + prev_chg_profile_info = + &chg_params->chg_profile_info + [chg_params->default_temp_range_profile]; return board_battery_type; } @@ -571,11 +576,11 @@ int board_cut_off_battery(void) { int rv; const struct ship_mode_info *ship_mode_inf = - board_get_batt_params()->ship_mode_inf; + board_get_batt_params()->ship_mode_inf; /* Ship mode command must be sent twice to take effect */ rv = sb_write(ship_mode_inf->ship_mode_reg, - ship_mode_inf->ship_mode_data); + ship_mode_inf->ship_mode_data); if (rv != EC_SUCCESS) return rv; @@ -591,7 +596,7 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) /* Do not discharge on AC if the battery is still waking up */ if (!(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - !(curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.status & STATUS_FULLY_CHARGED)) return 0; /* @@ -608,8 +613,8 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) * and suspend USB charging and DC/DC converter. */ if (!battery_is_cut_off() && - !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - (curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) return 1; /* @@ -642,10 +647,10 @@ int charger_profile_override(struct charge_state_data *curr) return 0; } - return charger_profile_override_common(curr, - board_get_batt_params()->fast_chg_params, - &prev_chg_profile_info, - board_get_batt_params()->batt_info->voltage_max); + return charger_profile_override_common( + curr, board_get_batt_params()->fast_chg_params, + &prev_chg_profile_info, + board_get_batt_params()->batt_info->voltage_max); } /* @@ -671,7 +676,7 @@ enum battery_present battery_is_present(void) * Battery status will be inactive until it is initialized. */ if (batt_pres == BP_YES && batt_pres_prev != batt_pres && - !battery_is_cut_off()) { + !battery_is_cut_off()) { /* Re-init board battery if battery presence status changes */ if (board_get_battery_type() == BATTERY_TYPE_COUNT) { if (bd9995x_get_battery_voltage() >= diff --git a/board/reef/board.c b/board/reef/board.c index e6856f3f55..71dadb6507 100644 --- a/board/reef/board.c +++ b/board/reef/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Reef board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_manager.h" #include "charge_ramp.h" @@ -14,10 +13,10 @@ #include "charger.h" #include "chipset.h" #include "console.h" -#include "driver/als_opt3001.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/als_opt3001.h" #include "driver/baro_bmp280.h" #include "driver/charger/bd9995x.h" #include "driver/tcpm/anx74xx.h" @@ -33,8 +32,9 @@ #include "lid_angle.h" #include "lid_switch.h" #include "math_util.h" -#include "motion_sense.h" #include "motion_lid.h" +#include "motion_sense.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -45,7 +45,7 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "timer.h" #include "uart.h" #include "usb_charge.h" @@ -54,15 +54,15 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define IN_ALL_SYS_PG POWER_SIGNAL_MASK(X86_ALL_SYS_PG) -#define IN_PGOOD_PP3300 POWER_SIGNAL_MASK(X86_PGOOD_PP3300) -#define IN_PGOOD_PP5000 POWER_SIGNAL_MASK(X86_PGOOD_PP5000) +#define IN_ALL_SYS_PG POWER_SIGNAL_MASK(X86_ALL_SYS_PG) +#define IN_PGOOD_PP3300 POWER_SIGNAL_MASK(X86_PGOOD_PP3300) +#define IN_PGOOD_PP5000 POWER_SIGNAL_MASK(X86_PGOOD_PP5000) -#define USB_PD_PORT_ANX74XX 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX74XX 0 +#define USB_PD_PORT_PS8751 1 static void tcpc_alert_event(enum gpio_signal signal) { @@ -98,7 +98,7 @@ static void anx74xx_cable_det_handler(void) * and if in normal mode, then there is no need to trigger a tcpc reset. */ if (cable_det && !reset_n) - task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); + task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET); } DECLARE_DEFERRED(anx74xx_cable_det_handler); @@ -117,47 +117,59 @@ void anx74xx_cable_det_interrupt(enum gpio_signal signal) static void enable_input_devices(void); DECLARE_DEFERRED(enable_input_devices); -#define LID_DEBOUNCE_US (30 * MSEC) /* Debounce time for lid switch */ void tablet_mode_interrupt(enum gpio_signal signal) { hook_call_deferred(&enable_input_devices_data, LID_DEBOUNCE_US); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* ADC channels */ const struct adc_t adc_channels[] = { /* Vfs = Vref = 2.816V, 10-bit unsigned reading */ - [ADC_TEMP_SENSOR_CHARGER] = { - "CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, - [ADC_TEMP_SENSOR_AMB] = { - "AMBIENT", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, - [ADC_BOARD_ID] = { - "BRD_ID", NPCX_ADC_CH2, ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 - }, + [ADC_TEMP_SENSOR_CHARGER] = { "CHARGER", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_AMB] = { "AMBIENT", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_BOARD_ID] = { "BRD_ID", NPCX_ADC_CH2, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { [PWM_CH_LED_GREEN] = { 2, PWM_CONFIG_DSLEEP, 100 }, - [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -const struct i2c_port_t i2c_ports[] = { - {"tcpc0", NPCX_I2C_PORT0_0, 400, - GPIO_EC_I2C_USB_C0_PD_SCL, GPIO_EC_I2C_USB_C0_PD_SDA}, - {"tcpc1", NPCX_I2C_PORT0_1, 400, - GPIO_EC_I2C_USB_C1_PD_SCL, GPIO_EC_I2C_USB_C1_PD_SDA}, - {"accelgyro", I2C_PORT_GYRO, 400, - GPIO_EC_I2C_GYRO_SCL, GPIO_EC_I2C_GYRO_SDA}, - {"sensors", NPCX_I2C_PORT2, 400, - GPIO_EC_I2C_SENSOR_SCL, GPIO_EC_I2C_SENSOR_SDA}, - {"batt", NPCX_I2C_PORT3, 100, - GPIO_EC_I2C_POWER_SCL, GPIO_EC_I2C_POWER_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "tcpc0", + .port = NPCX_I2C_PORT0_0, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = NPCX_I2C_PORT0_1, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "accelgyro", + .port = I2C_PORT_GYRO, + .kbps = 400, + .scl = GPIO_EC_I2C_GYRO_SCL, + .sda = GPIO_EC_I2C_GYRO_SDA }, + { .name = "sensors", + .port = NPCX_I2C_PORT2, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, + { .name = "batt", + .port = NPCX_I2C_PORT3, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -176,7 +188,7 @@ struct i2c_stress_test i2c_stress_tests[] = { #ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC { .port = NPCX_I2C_PORT0_1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, .i2c_test = &ps8xxx_i2c_stress_test_dev, }, #endif @@ -239,7 +251,7 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = NPCX_I2C_PORT0_1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, @@ -285,17 +297,21 @@ static int ps8751_tune_mux(const struct usb_mux *me) return EC_SUCCESS; } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_ANX74XX] = { - .usb_port = USB_PD_PORT_ANX74XX, - .driver = &anx74xx_tcpm_usb_mux_driver, - .hpd_update = &anx74xx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_ANX74XX, + .driver = &anx74xx_tcpm_usb_mux_driver, + .hpd_update = &anx74xx_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_PS8751] = { - .usb_port = USB_PD_PORT_PS8751, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .board_init = &ps8751_tune_mux, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_PS8751, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .board_init = &ps8751_tune_mux, + }, } }; @@ -390,27 +406,28 @@ void board_tcpc_init(void) gpio_enable_interrupt(GPIO_USB_C0_CABLE_DET); #endif /* - * Initialize HPD to low; after sysjump SOC needs to see - * HPD pulse to enable video path - */ + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -445,7 +462,8 @@ void chipset_pre_init_callback(void) static void board_set_tablet_mode(void) { - tablet_set_mode(!gpio_get_level(GPIO_TABLET_MODE_L)); + tablet_set_mode(!gpio_get_level(GPIO_TABLET_MODE_L), + TABLET_TRIGGER_LID); } /* Initialize board. */ @@ -526,8 +544,8 @@ int board_set_active_charge_port(int charge_port) * @param charge_ma Desired charge limit (mA). * @param charge_mv Negotiated charge voltage (mV). */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* Enable charging trigger by BC1.2 detection */ int bc12_enable = (supplier == CHARGE_SUPPLIER_BC12_CDP || @@ -538,9 +556,7 @@ void board_set_charge_limit(int port, int supplier, int charge_ma, if (bd9995x_bc12_enable_charging(port, bc12_enable)) return; - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } /** @@ -571,8 +587,7 @@ static void enable_input_devices(void) } /* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* If the lid is in 360 position, ignore the lid angle, * which might be faulty. Disable keyboard. @@ -581,7 +596,6 @@ void lid_angle_peripheral_enable(int enable) enable = 0; keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif /* Called on AP S5 -> S3 transition */ static void board_chipset_startup(void) @@ -652,17 +666,17 @@ void board_hibernate_late(void) int i; const uint32_t hibernate_pins[][2] = { /* Turn off LEDs in hibernate */ - {GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN}, + { GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN }, /* * BD99956 handles charge input automatically. We'll disable * charge output in hibernate. Charger will assert ACOK_OD * when VBUS or VCC are plugged in. */ - {GPIO_USB_C0_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, - {GPIO_USB_C1_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, + { GPIO_USB_C0_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN }, + { GPIO_USB_C1_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN }, }; /* Change GPIOs' state in hibernate for better power consumption */ @@ -689,17 +703,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -const mat33_fp_t mag_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t mag_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; @@ -799,7 +809,10 @@ struct motion_sensor_t motion_sensors[] = { .default_range = BIT(11), /* 16LSB / uT, fixed */ .rot_standard_ref = &mag_standard_ref, .min_frequency = BMM150_MAG_MIN_FREQ, +/* TODO(b/253292373): Remove when clang is fixed. */ +DISABLE_CLANG_WARNING("-Wshift-count-negative") .max_frequency = BMM150_MAG_MAX_FREQ(SPECIAL), +ENABLE_CLANG_WARNING("-Wshift-count-negative") }, [BASE_BARO] = { .name = "Base Baro", @@ -867,8 +880,8 @@ struct { int thresh_mv; } const reef_board_versions[] = { /* Vin = 3.3V, R1 = 46.4K, R2 values listed below */ - { BOARD_VERSION_1, 328 * 1.03 }, /* 5.11 Kohm */ - { BOARD_VERSION_2, 670 * 1.03 }, /* 11.8 Kohm */ + { BOARD_VERSION_1, 328 * 1.03 }, /* 5.11 Kohm */ + { BOARD_VERSION_2, 670 * 1.03 }, /* 11.8 Kohm */ { BOARD_VERSION_3, 1012 * 1.03 }, /* 20.5 Kohm */ { BOARD_VERSION_4, 1357 * 1.03 }, /* 32.4 Kohm */ { BOARD_VERSION_5, 1690 * 1.03 }, /* 48.7 Kohm */ @@ -913,7 +926,7 @@ int board_get_version(void) } /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * F3 key scan cycle completed but scan input is not * charging to logic high when EC start scan next diff --git a/board/reef/board.h b/board/reef/board.h index 8b38811024..b5bdd574a8 100644 --- a/board/reef/board.h +++ b/board/reef/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,24 +12,23 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF - /* EC console commands */ #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_CMD_BATT_MFG_ACCESS #define CONFIG_CMD_CHARGER_ADC_AMON_BMON -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 #define BD9995X_IOUT_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V + BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V #define CONFIG_CHARGER_PSYS_READ #define BD9995X_PSYS_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW + BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW #define CONFIG_CMD_I2C_STRESS_TEST #define CONFIG_CMD_I2C_STRESS_TEST_ACCEL @@ -39,7 +38,7 @@ #define CONFIG_CMD_I2C_STRESS_TEST_TCPC /* Battery */ -#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_PRESENT_CUSTOM #define CONFIG_BATTERY_SMART @@ -51,15 +50,19 @@ #define CONFIG_CHARGER_BD9995X #define CONFIG_CHARGER_BD9995X_CHGEN #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT 1 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 18000 #define CONFIG_CHARGER_MAINTAIN_VBAT +#undef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 #define CONFIG_USB_CHARGER #define CONFIG_CHARGER_PROFILE_OVERRIDE #define CONFIG_CHARGER_PROFILE_OVERRIDE_COMMON -#undef CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES +#undef CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES #define CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES 3 #define CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT @@ -86,7 +89,7 @@ #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PD_VBUS_DETECT_CHARGER #define CONFIG_USB_PD_TCPC_LOW_POWER -#define CONFIG_USB_PD_TCPM_MUX /* for both PS8751 and ANX3429 */ +#define CONFIG_USB_PD_TCPM_MUX /* for both PS8751 and ANX3429 */ #define CONFIG_USB_PD_TCPM_ANX3429 #define CONFIG_USB_PD_TCPM_PS8751 #define CONFIG_USB_PD_TCPM_TCPCI @@ -101,7 +104,7 @@ #define CONFIG_USBC_VCONN_SWAP /* SoC / PCH */ -#define CONFIG_HOSTCMD_LPC +#define CONFIG_HOST_INTERFACE_LPC #define CONFIG_CHIPSET_APOLLOLAKE #define CONFIG_CHIPSET_RESET_HOOK #define CONFIG_POWER_BUTTON @@ -109,18 +112,18 @@ #define CONFIG_POWER_COMMON #define CONFIG_POWER_S0IX #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD /* EC */ #define CONFIG_ADC -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS -#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_FPU #define CONFIG_HOSTCMD_FLASH_SPI_INFO #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_I2C_CONTROLLER + #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2 @@ -144,7 +147,7 @@ #define CONFIG_WIRELESS #define CONFIG_WIRELESS_SUSPEND EC_WIRELESS_SWITCH_WLAN_POWER #define CONFIG_WLAN_POWER_ACTIVE_LOW -#define WIRELESS_GPIO_WLAN_POWER GPIO_WIRELESS_GPIO_WLAN_POWER +#define WIRELESS_GPIO_WLAN_POWER GPIO_WIRELESS_GPIO_WLAN_POWER #define CONFIG_PWR_STATE_DISCHARGE_FULL #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 512 @@ -162,9 +165,9 @@ #undef CONFIG_MOTION_SENSE_SUSPEND_DELAY_US #define CONFIG_MOTION_SENSE_SUSPEND_DELAY_US (MSEC * 60) -#define CONFIG_FLASH_SIZE 524288 +#define CONFIG_FLASH_SIZE_BYTES 524288 #define CONFIG_SPI_FLASH_REGS -#define CONFIG_SPI_FLASH_W25Q40 /* FIXME: Should be GD25LQ40? */ +#define CONFIG_SPI_FLASH_W25Q40 /* FIXME: Should be GD25LQ40? */ /* * Enable 1 slot of secure temporary storage to support @@ -174,27 +177,26 @@ #define CONFIG_VSTORE_SLOT_COUNT 1 /* Optional feature - used by nuvoton */ -#define NPCX_UART_MODULE2 1 /* 0:GPIO10/11 1:GPIO64/65 as UART */ -#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ +#define NPCX_UART_MODULE2 1 /* 0:GPIO10/11 1:GPIO64/65 as UART */ +#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ /* FIXME(dhendrix): these pins are just normal GPIOs on Reef. Do we need * to change some other setting to put them in GPIO mode? */ -#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ +#define NPCX_TACH_SEL2 0 /* 0:GPIO40/73 1:GPIO93/A6 as TACH */ /* I2C ports */ -#define I2C_PORT_GYRO NPCX_I2C_PORT1 -#define I2C_PORT_LID_ACCEL NPCX_I2C_PORT2 -#define I2C_PORT_ALS NPCX_I2C_PORT2 -#define I2C_PORT_BARO NPCX_I2C_PORT2 -#define I2C_PORT_BATTERY NPCX_I2C_PORT3 -#define I2C_PORT_CHARGER NPCX_I2C_PORT3 +#define I2C_PORT_GYRO NPCX_I2C_PORT1 +#define I2C_PORT_LID_ACCEL NPCX_I2C_PORT2 +#define I2C_PORT_ALS NPCX_I2C_PORT2 +#define I2C_PORT_BARO NPCX_I2C_PORT2 +#define I2C_PORT_BATTERY NPCX_I2C_PORT3 +#define I2C_PORT_CHARGER NPCX_I2C_PORT3 /* Accelerometer and Gyroscope are the same device. */ -#define I2C_PORT_ACCEL I2C_PORT_GYRO +#define I2C_PORT_ACCEL I2C_PORT_GYRO /* Sensors */ #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_HOST_EVENT #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_MAG_BMI_BMM150 @@ -215,7 +217,6 @@ /* Depends on how fast the AP boots and typical ODRs */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) - #ifndef __ASSEMBLER__ #include "gpio_signal.h" @@ -223,9 +224,9 @@ /* ADC signal */ enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, /* ADC0 */ - ADC_TEMP_SENSOR_AMB, /* ADC1 */ - ADC_BOARD_ID, /* ADC2 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC0 */ + ADC_TEMP_SENSOR_AMB, /* ADC1 */ + ADC_BOARD_ID, /* ADC2 */ ADC_CH_COUNT }; @@ -286,17 +287,16 @@ enum reef_board_version { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Reset PD MCU */ void board_reset_pd_mcu(void); diff --git a/board/reef/build.mk b/board/reef/build.mk index 728d027803..470e439b13 100644 --- a/board/reef/build.mk +++ b/board/reef/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Copyright 2015 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/reef/ec.tasklist b/board/reef/ec.tasklist index eeebc0cc59..bc8668a1db 100644 --- a/board/reef/ec.tasklist +++ b/board/reef/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/reef/gpio.inc b/board/reef/gpio.inc index 2b6a5342f4..3f66a9903a 100644 --- a/board/reef/gpio.inc +++ b/board/reef/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -67,7 +67,8 @@ GPIO(EC_I2C_POWER_SCL, PIN(D, 1), GPIO_INPUT) * Pin 57 (SER_IRQ) defaults to LPC mode, but we also have EC_PCH_KB_INT_ODL * (Pin B0) in case it doesn't work (Set CONFIG_KEYBOARD_IRQ_GPIO in this case). * - * See also the NO_LPC_ESPI bit in DEVALT1 and the CONFIG_HOSTCMD_SPS option. + * See also the NO_LPC_ESPI bit in DEVALT1 and the + * CONFIG_HOST_INTERFACE_SHI option. */ GPIO(PCH_SMI_L, PIN(A, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_SMI_ODL */ @@ -163,8 +164,8 @@ ALTERNATE(PIN_MASK(0, 0xe0), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_OUTPUT) GPIO(KBD_KSO2, PIN(1, 7), GPIO_KB_OUTPUT_COL2) -ALTERNATE(PIN(4, 4), 6, MODULE_ADC, 0) /* TEMP_SENSOR_AMB (FIXME: alt function 6?) */ -ALTERNATE(PIN(4, 5), 6, MODULE_ADC, 0) /* TEMP_SENSOR_CHARGER (FIXME: alt function?) */ +/* GPIO44 for TEMP_SENSOR_AMB and GPIO45 for TEMP_SENSOR_CHARGER */ +ALTERNATE(PIN_MASK(4, 0x30), 0, MODULE_ADC, 0) ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* GPIO87 for EC_I2C_GYRO_SDA */ ALTERNATE(PIN_MASK(9, 0x01), 1, MODULE_I2C, 0) /* GPIO90 for EC_I2C_GYRO_SCL */ diff --git a/board/reef/led.c b/board/reef/led.c index 807b1c109c..0f9685c15c 100644 --- a/board/reef/led.c +++ b/board/reef/led.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -27,8 +27,7 @@ #define LED_ON_1SEC_TICKS 1 #define LED_ON_2SECS_TICKS 2 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -36,7 +35,7 @@ enum led_color { LED_OFF = 0, LED_BLUE, LED_AMBER, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int led_set_color_battery(enum led_color color) @@ -96,43 +95,47 @@ static void led_set_battery(void) static int battery_ticks; static int suspend_ticks; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: led_set_color_battery(LED_AMBER); break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { led_set_color_battery(LED_BLUE); break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE /* and PWR_STATE_DISCHARGE_FULL */: + __fallthrough; + case LED_PWRS_DISCHARGE /* and LED_PWRS_DISCHARGE_FULL */: if (chipset_in_state(CHIPSET_STATE_ON)) { led_set_color_battery(LED_BLUE); } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { /* Blink once every four seconds. */ led_set_color_battery( - (suspend_ticks % LED_TOTAL_4SECS_TICKS) - < LED_ON_1SEC_TICKS ? LED_AMBER : LED_OFF); + (suspend_ticks % LED_TOTAL_4SECS_TICKS) < + LED_ON_1SEC_TICKS ? + LED_AMBER : + LED_OFF); } else { led_set_color_battery(LED_OFF); } break; - case PWR_STATE_ERROR: - led_set_color_battery( - (battery_ticks % LED_TOTAL_2SECS_TICKS < - LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); + case LED_PWRS_ERROR: + led_set_color_battery((battery_ticks % LED_TOTAL_2SECS_TICKS < + LED_ON_1SEC_TICKS) ? + LED_AMBER : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: led_set_color_battery(LED_BLUE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE) - led_set_color_battery( - (battery_ticks % LED_TOTAL_4SECS_TICKS < - LED_ON_2SECS_TICKS) ? LED_AMBER : LED_BLUE); - else - led_set_color_battery(LED_BLUE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + led_set_color_battery(LED_BLUE); + break; + case LED_PWRS_FORCED_IDLE: + led_set_color_battery((battery_ticks % LED_TOTAL_4SECS_TICKS < + LED_ON_2SECS_TICKS) ? + LED_AMBER : + LED_BLUE); break; default: /* Other states don't alter LED behavior */ diff --git a/board/reef/usb_pd_policy.c b/board/reef/usb_pd_policy.c index 2d2ef416b2..5990dd9e75 100644 --- a/board/reef/usb_pd_policy.c +++ b/board/reef/usb_pd_policy.c @@ -1,16 +1,16 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/charger/bd9995x.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -18,17 +18,17 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { @@ -39,7 +39,8 @@ static void board_vbus_update_source_current(int port) { enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? - (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP); + (GPIO_INPUT | GPIO_PULL_UP) : + (GPIO_OUTPUT | GPIO_PULL_UP); /* * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance diff --git a/board/reef/vif_override.xml b/board/reef/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/reef/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/reef_it8320/battery.c b/board/reef_it8320/battery.c index 1b16a672b2..f03000f3c7 100644 --- a/board/reef_it8320/battery.c +++ b/board/reef_it8320/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -20,7 +20,7 @@ #include "i2c.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) enum battery_type { BATTERY_SONY_CORP, @@ -135,7 +135,7 @@ const struct battery_info batt_info_smp_cos4870 = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 46, .charging_min_c = 0, @@ -183,7 +183,7 @@ const struct battery_info batt_info_sonycorp = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 50, .charging_min_c = 0, @@ -240,7 +240,7 @@ const struct battery_info batt_info_panasoic = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 50, .charging_min_c = 0, @@ -384,7 +384,7 @@ const struct battery_info batt_info_c22n1626 = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 45, .charging_min_c = 0, @@ -398,7 +398,7 @@ static int batt_smp_cos4870_init(void) int batt_status; return battery_status(&batt_status) ? 0 : - batt_status & STATUS_INITIALIZED; + batt_status & STATUS_INITIALIZED; } static int batt_sony_corp_init(void) @@ -411,8 +411,9 @@ static int batt_sony_corp_init(void) * : 0b - Allowed to Discharge * : 1b - Not Allowed to Discharge */ - return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? 0 : - !(batt_status & SONY_DISCHARGE_DISABLE_FET_BIT); + return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? + 0 : + !(batt_status & SONY_DISCHARGE_DISABLE_FET_BIT); } static int batt_panasonic_init(void) @@ -425,8 +426,9 @@ static int batt_panasonic_init(void) * : 0b - Not Allowed to Discharge * : 1b - Allowed to Discharge */ - return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? 0 : - !!(batt_status & PANASONIC_DISCHARGE_ENABLE_FET_BIT); + return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? + 0 : + !!(batt_status & PANASONIC_DISCHARGE_ENABLE_FET_BIT); } static int batt_c22n1626_init(void) @@ -439,8 +441,9 @@ static int batt_c22n1626_init(void) * : 0b - Not Allowed to Discharge * : 1b - Allowed to Discharge */ - return sb_read(SB_PACK_STATUS, &batt_status) ? 0 : - !!(batt_status & C22N1626_DISCHARGE_ENABLE_FET_BIT); + return sb_read(SB_PACK_STATUS, &batt_status) ? + 0 : + !!(batt_status & C22N1626_DISCHARGE_ENABLE_FET_BIT); } static const struct ship_mode_info ship_mode_info_smp_cos4870 = { @@ -513,7 +516,8 @@ BUILD_ASSERT(ARRAY_SIZE(info) == BATTERY_TYPE_COUNT); static inline const struct board_batt_params *board_get_batt_params(void) { return &info[board_battery_type == BATTERY_TYPE_COUNT ? - DEFAULT_BATTERY_TYPE : board_battery_type]; + DEFAULT_BATTERY_TYPE : + board_battery_type]; } enum battery_present battery_hw_present(void) @@ -540,8 +544,9 @@ static int board_get_battery_type(void) /* Initialize fast charging parameters */ chg_params = board_get_batt_params()->fast_chg_params; - prev_chg_profile_info = &chg_params->chg_profile_info[ - chg_params->default_temp_range_profile]; + prev_chg_profile_info = + &chg_params->chg_profile_info + [chg_params->default_temp_range_profile]; return board_battery_type; } @@ -571,11 +576,11 @@ int board_cut_off_battery(void) { int rv; const struct ship_mode_info *ship_mode_inf = - board_get_batt_params()->ship_mode_inf; + board_get_batt_params()->ship_mode_inf; /* Ship mode command must be sent twice to take effect */ rv = sb_write(ship_mode_inf->ship_mode_reg, - ship_mode_inf->ship_mode_data); + ship_mode_inf->ship_mode_data); if (rv != EC_SUCCESS) return rv; @@ -591,7 +596,7 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) /* Do not discharge on AC if the battery is still waking up */ if (!(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - !(curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.status & STATUS_FULLY_CHARGED)) return 0; /* @@ -608,8 +613,8 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) * and suspend USB charging and DC/DC converter. */ if (!battery_is_cut_off() && - !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - (curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) return 1; /* @@ -642,10 +647,10 @@ int charger_profile_override(struct charge_state_data *curr) return 0; } - return charger_profile_override_common(curr, - board_get_batt_params()->fast_chg_params, - &prev_chg_profile_info, - board_get_batt_params()->batt_info->voltage_max); + return charger_profile_override_common( + curr, board_get_batt_params()->fast_chg_params, + &prev_chg_profile_info, + board_get_batt_params()->batt_info->voltage_max); } /* @@ -671,7 +676,7 @@ enum battery_present battery_is_present(void) * Battery status will be inactive until it is initialized. */ if (batt_pres == BP_YES && batt_pres_prev != batt_pres && - !battery_is_cut_off()) { + !battery_is_cut_off()) { /* Re-init board battery if battery presence status changes */ if (board_get_battery_type() == BATTERY_TYPE_COUNT) { if (bd9995x_get_battery_voltage() >= diff --git a/board/reef_it8320/board.c b/board/reef_it8320/board.c index e45174e9e1..5901c1a821 100644 --- a/board/reef_it8320/board.c +++ b/board/reef_it8320/board.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* reef_it8320 board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "charge_manager.h" #include "charge_ramp.h" @@ -28,8 +27,9 @@ #include "lid_angle.h" #include "lid_switch.h" #include "math_util.h" -#include "motion_sense.h" #include "motion_lid.h" +#include "motion_sense.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -40,7 +40,7 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "timer.h" #include "uart.h" #include "usb_charge.h" @@ -49,40 +49,41 @@ #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define IN_ALL_SYS_PG POWER_SIGNAL_MASK(X86_ALL_SYS_PG) -#define IN_PGOOD_PP3300 POWER_SIGNAL_MASK(X86_PGOOD_PP3300) -#define IN_PGOOD_PP5000 POWER_SIGNAL_MASK(X86_PGOOD_PP5000) +#define IN_ALL_SYS_PG POWER_SIGNAL_MASK(X86_ALL_SYS_PG) +#define IN_PGOOD_PP3300 POWER_SIGNAL_MASK(X86_PGOOD_PP3300) +#define IN_PGOOD_PP5000 POWER_SIGNAL_MASK(X86_PGOOD_PP5000) +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" const struct adc_t adc_channels[] = { /* Convert to mV (3000mV/1024). */ - {"CHARGER", 3000, 1024, 0, CHIP_ADC_CH1}, /* GPI1 */ - {"AMBIENT", 3000, 1024, 0, CHIP_ADC_CH2}, /* GPI2 */ - {"BRD_ID", 3000, 1024, 0, CHIP_ADC_CH3}, /* GPI3 */ + { "CHARGER", 3000, 1024, 0, CHIP_ADC_CH1 }, /* GPI1 */ + { "AMBIENT", 3000, 1024, 0, CHIP_ADC_CH2 }, /* GPI2 */ + { "BRD_ID", 3000, 1024, 0, CHIP_ADC_CH3 }, /* GPI3 */ }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); -const struct i2c_port_t i2c_ports[] = { - {"mux", IT83XX_I2C_CH_C, 400, - GPIO_EC_I2C_C_SCL, GPIO_EC_I2C_C_SDA}, - {"batt", IT83XX_I2C_CH_E, 100, - GPIO_EC_I2C_E_SCL, GPIO_EC_I2C_E_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "mux", + .port = IT83XX_I2C_CH_C, + .kbps = 400, + .scl = GPIO_EC_I2C_C_SCL, + .sda = GPIO_EC_I2C_C_SDA }, + { .name = "batt", + .port = IT83XX_I2C_CH_E, + .kbps = 100, + .scl = GPIO_EC_I2C_E_SCL, + .sda = GPIO_EC_I2C_E_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .bus_type = EC_BUS_TYPE_EMBEDDED, - .drv = &it83xx_tcpm_drv - }, - { - .bus_type = EC_BUS_TYPE_EMBEDDED, - .drv = &it83xx_tcpm_drv - }, + { .bus_type = EC_BUS_TYPE_EMBEDDED, .drv = &it83xx_tcpm_drv }, + { .bus_type = EC_BUS_TYPE_EMBEDDED, .drv = &it83xx_tcpm_drv }, }; void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) @@ -112,11 +113,16 @@ const enum gpio_signal hibernate_wake_pins[] = { const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); static void it83xx_tcpc_update_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) + mux_state_t mux_state, + bool *ack_required) { - enum gpio_signal gpio = - me->usb_port ? GPIO_USB_C1_HPD_1P8_ODL - : GPIO_USB_C0_HPD_1P8_ODL; + int hpd_lvl = (mux_state & USB_PD_MUX_HPD_LVL) ? 1 : 0; + int hpd_irq = (mux_state & USB_PD_MUX_HPD_IRQ) ? 1 : 0; + enum gpio_signal gpio = me->usb_port ? GPIO_USB_C1_HPD_1P8_ODL : + GPIO_USB_C0_HPD_1P8_ODL; + + /* This driver does not use host command ACKs */ + *ack_required = false; hpd_lvl = !hpd_lvl; @@ -128,20 +134,26 @@ static void it83xx_tcpc_update_hpd_status(const struct usb_mux *me, } } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, - .driver = &pi3usb3x532_usb_mux_driver, - .hpd_update = &it83xx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + .hpd_update = &it83xx_tcpc_update_hpd_status, + }, }, { - .usb_port = 1, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = 0x10, - .driver = &ps8740_usb_mux_driver, - .hpd_update = &it83xx_tcpc_update_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = 0x10, + .driver = &ps8740_usb_mux_driver, + .hpd_update = &it83xx_tcpc_update_hpd_status, + }, }, }; @@ -150,18 +162,18 @@ const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { }; const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -208,7 +220,7 @@ static void board_set_tablet_mode(void) * Always report device isn't in tablet mode because * our id is clamshell and no TABLET_MODE_L pin */ - tablet_set_mode(0); + tablet_set_mode(0, TABLET_TRIGGER_LID); } /* Initialize board. */ @@ -219,11 +231,12 @@ static void board_init(void) gpio_enable_interrupt(GPIO_CHARGER_INT_L); /* - * Initialize HPD to low; after sysjump SOC needs to see - * HPD pulse to enable video path - */ + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_INIT_I2C + 1); @@ -287,8 +300,8 @@ int board_set_active_charge_port(int charge_port) * @param charge_ma Desired charge limit (mA). * @param charge_mv Negotiated charge voltage (mV). */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* Enable charging trigger by BC1.2 detection */ int bc12_enable = (supplier == CHARGE_SUPPLIER_BC12_CDP || @@ -299,9 +312,7 @@ void board_set_charge_limit(int port, int supplier, int charge_ma, if (bd9995x_bc12_enable_charging(port, bc12_enable)) return; - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } /** @@ -380,22 +391,27 @@ void chipset_do_shutdown(void) ; } +void board_reset_pd_mcu(void) +{ + /* do nothing */ +} + void board_hibernate_late(void) { int i; const uint32_t hibernate_pins[][2] = { /* Turn off LEDs in hibernate */ - {GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN}, + { GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN }, /* * BD99956 handles charge input automatically. We'll disable * charge output in hibernate. Charger will assert ACOK_OD * when VBUS or VCC are plugged in. */ - {GPIO_USB_C0_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, - {GPIO_USB_C1_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, + { GPIO_USB_C0_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN }, + { GPIO_USB_C1_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN }, }; /* Change GPIOs' state in hibernate for better power consumption */ @@ -426,8 +442,8 @@ struct { int thresh_mv; } const reef_it8320_board_versions[] = { /* Vin = 3.3V, R1 = 46.4K, R2 values listed below */ - { BOARD_VERSION_1, 328 * 1.03 }, /* 5.11 Kohm */ - { BOARD_VERSION_2, 670 * 1.03 }, /* 11.8 Kohm */ + { BOARD_VERSION_1, 328 * 1.03 }, /* 5.11 Kohm */ + { BOARD_VERSION_2, 670 * 1.03 }, /* 11.8 Kohm */ { BOARD_VERSION_3, 1012 * 1.03 }, /* 20.5 Kohm */ { BOARD_VERSION_4, 1357 * 1.03 }, /* 32.4 Kohm */ { BOARD_VERSION_5, 1690 * 1.03 }, /* 48.7 Kohm */ @@ -472,7 +488,7 @@ int board_get_version(void) } /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * F3 key scan cycle completed but scan input is not * charging to logic high when EC start scan next diff --git a/board/reef_it8320/board.h b/board/reef_it8320/board.h index fb26e2ff57..87767e5c23 100644 --- a/board/reef_it8320/board.h +++ b/board/reef_it8320/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,24 +19,24 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* EC console commands */ #define CONFIG_CMD_BATT_MFG_ACCESS #define CONFIG_CMD_CHARGER_ADC_AMON_BMON -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 #define BD9995X_IOUT_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V + BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V #define CONFIG_CHARGER_PSYS_READ #define BD9995X_PSYS_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW + BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW /* Battery */ -#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_PRESENT_CUSTOM #define CONFIG_BATTERY_SMART @@ -48,15 +48,19 @@ #define CONFIG_CHARGER_BD9995X #define CONFIG_CHARGER_BD9995X_CHGEN #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT 1 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 18000 #define CONFIG_CHARGER_MAINTAIN_VBAT +#undef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 #define CONFIG_USB_CHARGER #define CONFIG_CHARGER_PROFILE_OVERRIDE #define CONFIG_CHARGER_PROFILE_OVERRIDE_COMMON -#undef CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES +#undef CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES #define CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES 3 #define CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT @@ -78,7 +82,6 @@ #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_DISCHARGE_GPIO #define CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 #define CONFIG_USB_PD_VBUS_DETECT_CHARGER @@ -89,7 +92,7 @@ #define CONFIG_USB_PD_TCPMV2 #define CONFIG_USB_DRP_ACC_TRYSRC #define CONFIG_USB_PD_REV30 -#define CONFIG_USB_PID 0x1234 /* Invalid PID for development board */ +#define CONFIG_USB_PID 0x1234 /* Invalid PID for development board */ #define CONFIG_USB_PD_DECODE_SOP #define CONFIG_USB_PD_DEBUG_LEVEL 2 #define CONFIG_USB_PD_COMM_LOCKED @@ -99,7 +102,7 @@ #define CONFIG_USBC_VCONN_SWAP /* SoC / PCH */ -#define CONFIG_HOSTCMD_LPC +#define CONFIG_HOST_INTERFACE_LPC #define CONFIG_CHIPSET_APOLLOLAKE #define CONFIG_CHIPSET_RESET_HOOK #define CONFIG_POWER_BUTTON @@ -107,16 +110,17 @@ #define CONFIG_POWER_COMMON #define CONFIG_POWER_S0IX #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD /* EC */ #define CONFIG_ADC -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#undef CONFIG_EXTPOWER_DEBOUNCE_MS #define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_I2C_CONTROLLER +#define CONFIG_IT83XX_VCC_3P3V + #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_LED_COMMON @@ -161,15 +165,15 @@ #include "registers.h" /* I2C ports */ -#define I2C_PORT_USB_MUX IT83XX_I2C_CH_C -#define I2C_PORT_BATTERY IT83XX_I2C_CH_E -#define I2C_PORT_CHARGER IT83XX_I2C_CH_E +#define I2C_PORT_USB_MUX IT83XX_I2C_CH_C +#define I2C_PORT_BATTERY IT83XX_I2C_CH_E +#define I2C_PORT_CHARGER IT83XX_I2C_CH_E /* ADC signal */ enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, /* ADC CH1 */ - ADC_TEMP_SENSOR_AMB, /* ADC CH2 */ - ADC_BOARD_ID, /* ADC CH3 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC CH1 */ + ADC_TEMP_SENSOR_AMB, /* ADC CH2 */ + ADC_BOARD_ID, /* ADC CH3 */ ADC_CH_COUNT }; @@ -199,17 +203,16 @@ enum reef_it8320_board_version { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Reset PD MCU */ void board_reset_pd_mcu(void); diff --git a/board/reef_it8320/build.mk b/board/reef_it8320/build.mk index e5c12f9090..0c2fcec14f 100644 --- a/board/reef_it8320/build.mk +++ b/board/reef_it8320/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/reef_it8320/ec.tasklist b/board/reef_it8320/ec.tasklist index fdaf792a17..7faf124d53 100644 --- a/board/reef_it8320/ec.tasklist +++ b/board/reef_it8320/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/reef_it8320/gpio.inc b/board/reef_it8320/gpio.inc index 9882065d50..54528d3818 100644 --- a/board/reef_it8320/gpio.inc +++ b/board/reef_it8320/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -20,7 +20,7 @@ GPIO_INT(PCH_SLP_S0_L, PIN(B, 7), GPIO_INT_BOTH, power_signal_interrupt) /* #endif GPIO_INT(SUSPWRDNACK, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) /* SUSPWRNACK */ GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH, lid_interrupt) /* LID_OPEN */ -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI GPIO_INT(PCH_PLTRST_L, PIN(E, 3), GPIO_INT_BOTH | GPIO_PULL_UP, lpcrst_interrupt) /* PLT_RST_L */ #endif GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH, power_button_interrupt) /* MECH_PWR_BTN_ODL */ diff --git a/board/reef_it8320/led.c b/board/reef_it8320/led.c index a1ea5964a8..6f250c83e3 100644 --- a/board/reef_it8320/led.c +++ b/board/reef_it8320/led.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -27,8 +27,7 @@ #define LED_ON_1SEC_TICKS 1 #define LED_ON_2SECS_TICKS 2 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -36,7 +35,7 @@ enum led_color { LED_OFF = 0, LED_BLUE, LED_AMBER, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int led_set_color_battery(enum led_color color) @@ -97,43 +96,47 @@ static void led_set_battery(void) static int battery_ticks; static int suspend_ticks; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: led_set_color_battery(LED_AMBER); break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { led_set_color_battery(LED_BLUE); break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE /* and PWR_STATE_DISCHARGE_FULL */: + __fallthrough; + case LED_PWRS_DISCHARGE /* and LED_PWRS_DISCHARGE_FULL */: if (chipset_in_state(CHIPSET_STATE_ON)) { led_set_color_battery(LED_BLUE); } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { /* Blink once every four seconds. */ led_set_color_battery( - (suspend_ticks % LED_TOTAL_4SECS_TICKS) - < LED_ON_1SEC_TICKS ? LED_AMBER : LED_OFF); + (suspend_ticks % LED_TOTAL_4SECS_TICKS) < + LED_ON_1SEC_TICKS ? + LED_AMBER : + LED_OFF); } else { led_set_color_battery(LED_OFF); } break; - case PWR_STATE_ERROR: - led_set_color_battery( - (battery_ticks % LED_TOTAL_2SECS_TICKS < - LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); + case LED_PWRS_ERROR: + led_set_color_battery((battery_ticks % LED_TOTAL_2SECS_TICKS < + LED_ON_1SEC_TICKS) ? + LED_AMBER : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: led_set_color_battery(LED_BLUE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE) - led_set_color_battery( - (battery_ticks % LED_TOTAL_4SECS_TICKS < - LED_ON_2SECS_TICKS) ? LED_AMBER : LED_BLUE); - else - led_set_color_battery(LED_BLUE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + led_set_color_battery(LED_BLUE); + break; + case LED_PWRS_FORCED_IDLE: + led_set_color_battery((battery_ticks % LED_TOTAL_4SECS_TICKS < + LED_ON_2SECS_TICKS) ? + LED_AMBER : + LED_BLUE); break; default: /* Other states don't alter LED behavior */ diff --git a/board/reef_it8320/usb_pd_policy.c b/board/reef_it8320/usb_pd_policy.c index 87b9c8d42e..bf29197906 100644 --- a/board/reef_it8320/usb_pd_policy.c +++ b/board/reef_it8320/usb_pd_policy.c @@ -1,16 +1,16 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/charger/bd9995x.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -18,17 +18,17 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { @@ -39,7 +39,7 @@ static void board_vbus_update_source_current(int port) { enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; enum gpio_signal gpio_3a_en = port ? GPIO_EN_USB_C1_3A : - GPIO_EN_USB_C0_3A; + GPIO_EN_USB_C0_3A; gpio_set_level(gpio_3a_en, vbus_rp[port] == TYPEC_RP_3A0 ? 1 : 0); gpio_set_level(gpio, vbus_en[port]); @@ -58,9 +58,6 @@ int pd_set_power_supply_ready(int port) /* Ensure we're not charging from this port */ bd9995x_select_input_port(port, 0); - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); - pd_set_vbus_discharge(port, 0); /* Provide VBUS */ vbus_en[port] = 1; @@ -86,9 +83,6 @@ void pd_power_supply_reset(int port) if (prev_en) pd_set_vbus_discharge(port, 1); - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); - /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } diff --git a/board/reef_it8320/vif_override.xml b/board/reef_it8320/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/reef_it8320/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/reef_mchp/battery.c b/board/reef_mchp/battery.c index c557533c9d..d4a8aa7546 100644 --- a/board/reef_mchp/battery.c +++ b/board/reef_mchp/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -18,11 +18,11 @@ #include "gpio.h" #include "hooks.h" #include "i2c.h" -#include "util.h" #include "tfdp_chip.h" +#include "util.h" #define CPUTS(outstr) cputs(CC_CHARGER, outstr) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) enum battery_type { BATTERY_SONY_CORP, @@ -137,7 +137,7 @@ const struct battery_info batt_info_smp_cos4870 = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 46, .charging_min_c = 0, @@ -185,7 +185,7 @@ const struct battery_info batt_info_sonycorp = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 50, .charging_min_c = 0, @@ -242,7 +242,7 @@ const struct battery_info batt_info_panasoic = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 50, .charging_min_c = 0, @@ -386,7 +386,7 @@ const struct battery_info batt_info_c22n1626 = { * unwanted low VSYS_Prochot# assertion can be avoided. */ .voltage_min = 6100, - .precharge_current = 256, /* mA */ + .precharge_current = 256, /* mA */ .start_charging_min_c = 0, .start_charging_max_c = 45, .charging_min_c = 0, @@ -400,7 +400,7 @@ static int batt_smp_cos4870_init(void) int batt_status; return battery_status(&batt_status) ? 0 : - batt_status & STATUS_INITIALIZED; + batt_status & STATUS_INITIALIZED; } static int batt_sony_corp_init(void) @@ -413,8 +413,9 @@ static int batt_sony_corp_init(void) * : 0b - Allowed to Discharge * : 1b - Not Allowed to Discharge */ - return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? 0 : - !(batt_status & SONY_DISCHARGE_DISABLE_FET_BIT); + return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? + 0 : + !(batt_status & SONY_DISCHARGE_DISABLE_FET_BIT); } static int batt_panasonic_init(void) @@ -427,8 +428,9 @@ static int batt_panasonic_init(void) * : 0b - Not Allowed to Discharge * : 1b - Allowed to Discharge */ - return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? 0 : - !!(batt_status & PANASONIC_DISCHARGE_ENABLE_FET_BIT); + return sb_read(SB_MANUFACTURER_ACCESS, &batt_status) ? + 0 : + !!(batt_status & PANASONIC_DISCHARGE_ENABLE_FET_BIT); } static int batt_c22n1626_init(void) @@ -441,8 +443,9 @@ static int batt_c22n1626_init(void) * : 0b - Not Allowed to Discharge * : 1b - Allowed to Discharge */ - return sb_read(SB_PACK_STATUS, &batt_status) ? 0 : - !!(batt_status & C22N1626_DISCHARGE_ENABLE_FET_BIT); + return sb_read(SB_PACK_STATUS, &batt_status) ? + 0 : + !!(batt_status & C22N1626_DISCHARGE_ENABLE_FET_BIT); } static const struct ship_mode_info ship_mode_info_smp_cos4870 = { @@ -515,7 +518,8 @@ BUILD_ASSERT(ARRAY_SIZE(info) == BATTERY_TYPE_COUNT); static inline const struct board_batt_params *board_get_batt_params(void) { return &info[board_battery_type == BATTERY_TYPE_COUNT ? - DEFAULT_BATTERY_TYPE : board_battery_type]; + DEFAULT_BATTERY_TYPE : + board_battery_type]; } enum battery_present battery_hw_present(void) @@ -545,8 +549,9 @@ static int board_get_battery_type(void) /* Initialize fast charging parameters */ chg_params = board_get_batt_params()->fast_chg_params; - prev_chg_profile_info = &chg_params->chg_profile_info[ - chg_params->default_temp_range_profile]; + prev_chg_profile_info = + &chg_params->chg_profile_info + [chg_params->default_temp_range_profile]; return board_battery_type; } @@ -561,8 +566,7 @@ static int board_get_battery_type(void) static void board_init_battery_type(void) { if (board_get_battery_type() != BATTERY_TYPE_COUNT) - CPRINTS("found batt:%s", - info[board_battery_type].manuf_name); + CPRINTS("found batt:%s", info[board_battery_type].manuf_name); else CPUTS("battery not found"); } @@ -577,16 +581,16 @@ int board_cut_off_battery(void) { int rv; const struct ship_mode_info *ship_mode_inf = - board_get_batt_params()->ship_mode_inf; + board_get_batt_params()->ship_mode_inf; /* Ship mode command must be sent twice to take effect */ rv = sb_write(ship_mode_inf->ship_mode_reg, - ship_mode_inf->ship_mode_data); + ship_mode_inf->ship_mode_data); if (rv != EC_SUCCESS) return rv; rv = sb_write(ship_mode_inf->ship_mode_reg, - ship_mode_inf->ship_mode_data); + ship_mode_inf->ship_mode_data); return rv; } @@ -599,7 +603,7 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) /* Do not discharge on AC if the battery is still waking up */ if (!(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - !(curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.status & STATUS_FULLY_CHARGED)) return 0; /* @@ -616,8 +620,8 @@ static int charger_should_discharge_on_ac(struct charge_state_data *curr) * and suspend USB charging and DC/DC converter. */ if (!battery_is_cut_off() && - !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - (curr->batt.status & STATUS_FULLY_CHARGED)) + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) return 1; /* @@ -650,10 +654,10 @@ int charger_profile_override(struct charge_state_data *curr) return 0; } - return charger_profile_override_common(curr, - board_get_batt_params()->fast_chg_params, - &prev_chg_profile_info, - board_get_batt_params()->batt_info->voltage_max); + return charger_profile_override_common( + curr, board_get_batt_params()->fast_chg_params, + &prev_chg_profile_info, + board_get_batt_params()->batt_info->voltage_max); } /* @@ -679,7 +683,7 @@ enum battery_present battery_is_present(void) * Battery status will be inactive until it is initialized. */ if (batt_pres == BP_YES && batt_pres_prev != batt_pres && - !battery_is_cut_off()) { + !battery_is_cut_off()) { /* Re-init board battery if battery presence status changes */ if (board_get_battery_type() == BATTERY_TYPE_COUNT) { if (bd9995x_get_battery_voltage() >= diff --git a/board/reef_mchp/board.c b/board/reef_mchp/board.c index 621f6c484b..70b75d4b72 100644 --- a/board/reef_mchp/board.c +++ b/board/reef_mchp/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Reef board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "als.h" #include "button.h" #include "charge_manager.h" @@ -15,10 +14,10 @@ #include "charger.h" #include "chipset.h" #include "console.h" -#include "driver/als_opt3001.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" #include "driver/accelgyro_bmi_common.h" +#include "driver/als_opt3001.h" #include "driver/baro_bmp280.h" #include "driver/charger/bd9995x.h" #include "driver/tcpm/anx74xx.h" @@ -33,14 +32,15 @@ #include "keyboard_scan.h" #include "lid_angle.h" #include "lid_switch.h" +#include "lpc_chip.h" #include "math_util.h" -#include "motion_sense.h" #include "motion_lid.h" +#include "motion_sense.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" #include "pwm_chip.h" -#include "lpc_chip.h" #include "spi.h" #include "spi_chip.h" #include "switch.h" @@ -48,8 +48,8 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "tfdp_chip.h" -#include "thermistor.h" #include "timer.h" #include "uart.h" #include "usb_charge.h" @@ -58,17 +58,16 @@ #include "usb_pd_tcpm.h" #include "util.h" - #define CPUTS(outstr) cputs(CC_USBCHARGE, outstr) -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define IN_ALL_SYS_PG POWER_SIGNAL_MASK(X86_ALL_SYS_PG) -#define IN_PGOOD_PP3300 POWER_SIGNAL_MASK(X86_PGOOD_PP3300) -#define IN_PGOOD_PP5000 POWER_SIGNAL_MASK(X86_PGOOD_PP5000) +#define IN_ALL_SYS_PG POWER_SIGNAL_MASK(X86_ALL_SYS_PG) +#define IN_PGOOD_PP3300 POWER_SIGNAL_MASK(X86_PGOOD_PP3300) +#define IN_PGOOD_PP5000 POWER_SIGNAL_MASK(X86_PGOOD_PP5000) -#define USB_PD_PORT_ANX74XX 0 -#define USB_PD_PORT_PS8751 1 +#define USB_PD_PORT_ANX74XX 0 +#define USB_PD_PORT_PS8751 1 #ifdef CONFIG_BOARD_PRE_INIT /* @@ -132,7 +131,7 @@ static void anx74xx_cable_det_handler(void) * and if in normal mode, then there is no need to trigger a tcpc reset. */ if (cable_det && !reset_n) - task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); + task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET); } DECLARE_DEFERRED(anx74xx_cable_det_handler); /* from firmware-reef-9042.B */ @@ -153,17 +152,17 @@ void anx74xx_cable_det_interrupt(enum gpio_signal signal) static void enable_input_devices(void); DECLARE_DEFERRED(enable_input_devices); -#define LID_DEBOUNCE_US (30 * MSEC) /* Debounce time for lid switch */ void tablet_mode_interrupt(enum gpio_signal signal) { hook_call_deferred(&enable_input_devices_data, LID_DEBOUNCE_US); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* SPI devices */ const struct spi_device_t spi_devices[] = { - { QMSPI0_PORT, 4, GPIO_QMSPI_CS0}, + { QMSPI0_PORT, 4, GPIO_QMSPI_CS0 }, #if defined(CONFIG_SPI_ACCEL_PORT) { GPSPI0_PORT, 2, GPIO_SPI0_CS0 }, #endif @@ -177,15 +176,9 @@ const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); */ const struct adc_t adc_channels[] = { /* Vref = 3.000V, 10-bit unsigned reading */ - [ADC_TEMP_SENSOR_CHARGER] = { - "CHARGER", 3000, 1024, 0, 0 - }, - [ADC_TEMP_SENSOR_AMB] = { - "AMBIENT", 3000, 1024, 0, 1 - }, - [ADC_BOARD_ID] = { - "BRD_ID", 3000, 1024, 0, 2 - }, + [ADC_TEMP_SENSOR_CHARGER] = { "CHARGER", 3000, 1024, 0, 0 }, + [ADC_TEMP_SENSOR_AMB] = { "AMBIENT", 3000, 1024, 0, 1 }, + [ADC_BOARD_ID] = { "BRD_ID", 3000, 1024, 0, 2 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -194,7 +187,7 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct pwm_t pwm_channels[] = { /* channel, flags */ [PWM_CH_LED_GREEN] = { 4, PWM_CONFIG_DSLEEP }, - [PWM_CH_LED_RED] = { 5, PWM_CONFIG_DSLEEP }, + [PWM_CH_LED_RED] = { 5, PWM_CONFIG_DSLEEP }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); #endif /* #ifdef CONFIG_PWM */ @@ -205,17 +198,32 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); * Due to added RC of interposer board temporarily reduce * 400 to 100 kHz. */ -const struct i2c_port_t i2c_ports[] = { - {"tcpc0", MCHP_I2C_PORT0, 400, - GPIO_EC_I2C_USB_C0_PD_SCL, GPIO_EC_I2C_USB_C0_PD_SDA}, - {"tcpc1", MCHP_I2C_PORT2, 400, - GPIO_EC_I2C_USB_C1_PD_SCL, GPIO_EC_I2C_USB_C1_PD_SDA}, - {"accelgyro", I2C_PORT_GYRO, 400, - GPIO_EC_I2C_GYRO_SCL, GPIO_EC_I2C_GYRO_SDA}, - {"sensors", MCHP_I2C_PORT7, 400, - GPIO_EC_I2C_SENSOR_SCL, GPIO_EC_I2C_SENSOR_SDA}, - {"batt", MCHP_I2C_PORT3, 100, - GPIO_EC_I2C_POWER_SCL, GPIO_EC_I2C_POWER_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "tcpc0", + .port = MCHP_I2C_PORT0, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = MCHP_I2C_PORT2, + .kbps = 400, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "accelgyro", + .port = I2C_PORT_GYRO, + .kbps = 400, + .scl = GPIO_EC_I2C_GYRO_SCL, + .sda = GPIO_EC_I2C_GYRO_SDA }, + { .name = "sensors", + .port = MCHP_I2C_PORT7, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, + { .name = "batt", + .port = MCHP_I2C_PORT3, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -232,16 +240,6 @@ const uint16_t i2c_port_to_ctrl[I2C_PORT_COUNT] = { (MCHP_I2C_CTRL3 << 8) + MCHP_I2C_PORT7, }; -/* - * Used by chip level I2C controller initialization. - * Board level can specify two unused I2C addresses - * for each controller. Current chip level disables - * controller response to address 0(general call). - */ -const uint32_t i2c_ctrl_slave_addrs[I2C_CONTROLLER_COUNT] = { - 0, 0, 0, 0, -}; - const struct charger_config_t chg_chips[] = { { .i2c_port = I2C_PORT_CHARGER, @@ -250,26 +248,6 @@ const struct charger_config_t chg_chips[] = { }, }; -/* Return the two slave addresses the specified - * controller will respond to when controller - * is acting as a slave. - * b[6:0] = b[7:1] of I2C address 1 - * b[14:8] = b[7:1] of I2C address 2 - * When not using I2C controllers as slaves we can use - * the same value for all controllers. The address should - * not be 0x00 as this is the general call address. - */ -uint16_t board_i2c_slave_addrs(int controller) -{ - int i; - - for (i = 0; i < I2C_CONTROLLER_COUNT; i++) - if ((i2c_ctrl_slave_addrs[i] & 0xffff) == controller) - return (i2c_ctrl_slave_addrs[i] >> 16); - - return 0; /* general call address */ -} - /* * default to I2C0 because callers may not check * return value if we returned an error code. @@ -420,19 +398,23 @@ static int ps8751_tune_mux(const struct usb_mux *me) /* * USB_PD_PORT_ANX74XX and USB_PD_PORT_PS8751 are zero based indices into * tcpc_config array. The tcpc_config array contains the actual EC I2C - * port, device slave address, and a function pointer into the driver code. + * port, device address, and a function pointer into the driver code. */ -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_ANX74XX] = { - .usb_port = USB_PD_PORT_ANX74XX, - .driver = &anx74xx_tcpm_usb_mux_driver, - .hpd_update = &anx74xx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_ANX74XX, + .driver = &anx74xx_tcpm_usb_mux_driver, + .hpd_update = &anx74xx_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_PS8751] = { - .usb_port = USB_PD_PORT_PS8751, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .board_init = &ps8751_tune_mux, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_PS8751, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .board_init = &ps8751_tune_mux, + }, } }; @@ -540,9 +522,10 @@ void board_tcpc_init(void) * HPD pulse to enable video path */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); } -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); /* * Data derived from Seinhart-Hart equation in a resistor divider circuit with @@ -579,8 +562,7 @@ int board_get_charger_temp(int idx, int *temp_ptr) if (mv < 0) return -1; - *temp_ptr = thermistor_linear_interpolate(mv, - &charger_thermistor_info); + *temp_ptr = thermistor_linear_interpolate(mv, &charger_thermistor_info); *temp_ptr = C_TO_K(*temp_ptr); return 0; } @@ -620,8 +602,7 @@ int board_get_ambient_temp(int idx, int *temp_ptr) if (mv < 0) return -1; - *temp_ptr = thermistor_linear_interpolate(mv, - &amb_thermistor_info); + *temp_ptr = thermistor_linear_interpolate(mv, &amb_thermistor_info); *temp_ptr = C_TO_K(*temp_ptr); return 0; } @@ -632,9 +613,9 @@ int board_get_ambient_temp(int idx, int *temp_ptr) * delay from read to taking action */ const struct temp_sensor_t temp_sensors[] = { - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0}, - {"Ambient", TEMP_SENSOR_TYPE_BOARD, board_get_ambient_temp, 0}, - {"Charger", TEMP_SENSOR_TYPE_BOARD, board_get_charger_temp, 1}, + { "Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0 }, + { "Ambient", TEMP_SENSOR_TYPE_BOARD, board_get_ambient_temp, 0 }, + { "Charger", TEMP_SENSOR_TYPE_BOARD, board_get_charger_temp, 1 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -669,7 +650,8 @@ void chipset_pre_init_callback(void) static void board_set_tablet_mode(void) { - tablet_set_mode(!gpio_get_level(GPIO_TABLET_MODE_L)); + tablet_set_mode(!gpio_get_level(GPIO_TABLET_MODE_L), + TABLET_TRIGGER_LID); } /* Initialize board. */ @@ -755,8 +737,8 @@ int board_set_active_charge_port(int charge_port) * @param charge_ma Desired charge limit (mA). * @param charge_mv Negotiated charge voltage (mV). */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { /* Enable charging trigger by BC1.2 detection */ int bc12_enable = (supplier == CHARGE_SUPPLIER_BC12_CDP || @@ -767,9 +749,7 @@ void board_set_charge_limit(int port, int supplier, int charge_ma, if (bd9995x_bc12_enable_charging(port, bc12_enable)) return; - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); + charge_set_input_current_limit(charge_ma, charge_mv); } /** @@ -811,8 +791,7 @@ static void enable_input_devices(void) } /* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { /* If the lid is in 360 position, ignore the lid angle, * which might be faulty. Disable keyboard. @@ -821,7 +800,6 @@ void lid_angle_peripheral_enable(int enable) enable = 0; keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); } -#endif /* Called on AP S5 -> S3 transition */ static void board_chipset_startup(void) @@ -897,17 +875,17 @@ void board_hibernate_late(void) int i; const uint32_t hibernate_pins[][2] = { /* Turn off LEDs in hibernate */ - {GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN}, + { GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN }, /* * BD99956 handles charge input automatically. We'll disable * charge output in hibernate. Charger will assert ACOK_OD * when VBUS or VCC are plugged in. */ - {GPIO_USB_C0_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, - {GPIO_USB_C1_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, + { GPIO_USB_C0_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN }, + { GPIO_USB_C1_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN }, }; /* Change GPIOs' state in hibernate for better power consumption */ @@ -934,17 +912,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -const mat33_fp_t mag_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t mag_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; @@ -1048,7 +1022,10 @@ struct motion_sensor_t motion_sensors[] = { .default_range = BIT(11), /* 16LSB / uT, fixed */ .rot_standard_ref = &mag_standard_ref, .min_frequency = BMM150_MAG_MIN_FREQ, +/* TODO(b/253292373): Remove when clang is fixed. */ +DISABLE_CLANG_WARNING("-Wshift-count-negative") .max_frequency = BMM150_MAG_MAX_FREQ(SPECIAL), +ENABLE_CLANG_WARNING("-Wshift-count-negative") }, [BASE_BARO] = { .name = "Base Baro", @@ -1120,8 +1097,8 @@ struct { int thresh_mv; } const reef_board_versions[] = { /* Vin = 3.3V, R1 = 46.4K, R2 values listed below */ - { BOARD_VERSION_1, 328 * 1.03 }, /* 5.11 Kohm */ - { BOARD_VERSION_2, 670 * 1.03 }, /* 11.8 Kohm */ + { BOARD_VERSION_1, 328 * 1.03 }, /* 5.11 Kohm */ + { BOARD_VERSION_2, 670 * 1.03 }, /* 11.8 Kohm */ { BOARD_VERSION_3, 1012 * 1.03 }, /* 20.5 Kohm */ { BOARD_VERSION_4, 1357 * 1.03 }, /* 32.4 Kohm */ { BOARD_VERSION_5, 1690 * 1.03 }, /* 48.7 Kohm */ @@ -1183,7 +1160,7 @@ int board_get_version(void) } /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * F3 key scan cycle completed but scan input is not * charging to logic high when EC start scan next diff --git a/board/reef_mchp/board.h b/board/reef_mchp/board.h index 0e630e15fb..f9db14a01e 100644 --- a/board/reef_mchp/board.h +++ b/board/reef_mchp/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,24 +12,26 @@ * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF +/* EC console on UART 0 */ +#define CONFIG_UART_CONSOLE 0 /* EC console commands */ #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_CMD_BATT_MFG_ACCESS #define CONFIG_CMD_CHARGER_ADC_AMON_BMON -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 #define BD9995X_IOUT_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V + BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V #define CONFIG_CHARGER_PSYS_READ #define BD9995X_PSYS_GAIN_SELECT \ - BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW + BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW #define CONFIG_CMD_I2C_STRESS_TEST #define CONFIG_CMD_I2C_STRESS_TEST_ACCEL @@ -39,7 +41,7 @@ #define CONFIG_CMD_I2C_STRESS_TEST_TCPC /* Battery */ -#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_PRESENT_CUSTOM #define CONFIG_BATTERY_SMART @@ -51,15 +53,19 @@ #define CONFIG_CHARGER_BD9995X #define CONFIG_CHARGER_BD9995X_CHGEN #define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT 1 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 18000 #define CONFIG_CHARGER_MAINTAIN_VBAT +#undef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 #define CONFIG_USB_CHARGER #define CONFIG_CHARGER_PROFILE_OVERRIDE #define CONFIG_CHARGER_PROFILE_OVERRIDE_COMMON -#undef CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES +#undef CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES #define CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES 3 #define CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT @@ -86,7 +92,7 @@ #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PD_VBUS_DETECT_CHARGER #define CONFIG_USB_PD_TCPC_LOW_POWER -#define CONFIG_USB_PD_TCPM_MUX /* for both PS8751 and ANX3429 */ +#define CONFIG_USB_PD_TCPM_MUX /* for both PS8751 and ANX3429 */ #define CONFIG_USB_PD_TCPM_ANX3429 /* Silicon on Reef is ANX3429 */ #define CONFIG_USB_PD_TCPM_PS8751 #define CONFIG_USB_PD_TCPM_TCPCI @@ -101,7 +107,7 @@ #define CONFIG_USBC_VCONN_SWAP /* SoC / PCH */ -#define CONFIG_HOSTCMD_LPC +#define CONFIG_HOST_INTERFACE_LPC #define CONFIG_CHIPSET_APOLLOLAKE #define CONFIG_CHIPSET_RESET_HOOK #define CONFIG_POWER_BUTTON @@ -109,18 +115,18 @@ #define CONFIG_POWER_COMMON #define CONFIG_POWER_S0IX #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD /* EC */ #define CONFIG_ADC -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_EXTPOWER_GPIO -#undef CONFIG_EXTPOWER_DEBOUNCE_MS -#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 +#undef CONFIG_EXTPOWER_DEBOUNCE_MS +#define CONFIG_EXTPOWER_DEBOUNCE_MS 1000 #define CONFIG_FPU #define CONFIG_HOSTCMD_FLASH_SPI_INFO #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_I2C_CONTROLLER + #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_COL2_INVERTED #define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2 @@ -142,7 +148,7 @@ #define CONFIG_WIRELESS #define CONFIG_WIRELESS_SUSPEND EC_WIRELESS_SWITCH_WLAN_POWER #define CONFIG_WLAN_POWER_ACTIVE_LOW -#define WIRELESS_GPIO_WLAN_POWER GPIO_WIRELESS_GPIO_WLAN_POWER +#define WIRELESS_GPIO_WLAN_POWER GPIO_WIRELESS_GPIO_WLAN_POWER #define CONFIG_PWR_STATE_DISCHARGE_FULL /* @@ -166,9 +172,9 @@ #define CONFIG_SPI_FLASH_PORT 0 #define CONFIG_SPI_FLASH -#define CONFIG_FLASH_SIZE 524288 +#define CONFIG_FLASH_SIZE_BYTES 524288 #define CONFIG_SPI_FLASH_REGS -#define CONFIG_SPI_FLASH_W25Q40 /* FIXME: Should be GD25LQ40? */ +#define CONFIG_SPI_FLASH_W25Q40 /* FIXME: Should be GD25LQ40? */ /* * Enable 1 slot of secure temporary storage to support @@ -183,23 +189,22 @@ #define CONFIG_BOARD_PRE_INIT /* I2C ports */ -#define I2C_CONTROLLER_COUNT 4 -#define I2C_PORT_COUNT 5 - -#define I2C_PORT_GYRO MCHP_I2C_PORT6 -#define I2C_PORT_LID_ACCEL MCHP_I2C_PORT7 -#define I2C_PORT_ALS MCHP_I2C_PORT7 -#define I2C_PORT_BARO MCHP_I2C_PORT7 -#define I2C_PORT_BATTERY MCHP_I2C_PORT3 -#define I2C_PORT_CHARGER MCHP_I2C_PORT3 +#define I2C_CONTROLLER_COUNT 4 +#define I2C_PORT_COUNT 5 + +#define I2C_PORT_GYRO MCHP_I2C_PORT6 +#define I2C_PORT_LID_ACCEL MCHP_I2C_PORT7 +#define I2C_PORT_ALS MCHP_I2C_PORT7 +#define I2C_PORT_BARO MCHP_I2C_PORT7 +#define I2C_PORT_BATTERY MCHP_I2C_PORT3 +#define I2C_PORT_CHARGER MCHP_I2C_PORT3 /* Accelerometer and Gyroscope are the same device. */ -#define I2C_PORT_ACCEL I2C_PORT_GYRO +#define I2C_PORT_ACCEL I2C_PORT_GYRO /* Sensors */ #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_HOST_EVENT #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_MAG_BMI_BMM150 @@ -220,7 +225,6 @@ /* Depends on how fast the AP boots and typical ODRs */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) - #ifndef __ASSEMBLER__ #include "gpio_signal.h" @@ -228,9 +232,9 @@ /* ADC signal */ enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, /* ADC0 */ - ADC_TEMP_SENSOR_AMB, /* ADC1 */ - ADC_BOARD_ID, /* ADC2 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC0 */ + ADC_TEMP_SENSOR_AMB, /* ADC1 */ + ADC_BOARD_ID, /* ADC2 */ ADC_CH_COUNT }; @@ -269,7 +273,7 @@ enum sensor_id { BASE_GYRO, BASE_MAG, BASE_BARO, - LID_ALS, /* firmware-reef-9042.B doesn't have this */ + LID_ALS, /* firmware-reef-9042.B doesn't have this */ SENSOR_COUNT, }; @@ -292,17 +296,16 @@ enum reef_board_version { * delay to turn on the power supply max is ~16ms. * delay to turn off the power supply max is about ~180ms. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ /* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 45000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Reset PD MCU */ void board_reset_pd_mcu(void); @@ -315,14 +318,6 @@ void board_print_tcpc_fw_version(int port); /* Map I2C port to controller */ int board_i2c_p2c(int port); -/* Return the two slave addresses the specified - * controller will respond to when controller - * is acting as a slave. - * b[6:0] = b[7:1] of I2C address 1 - * b[14:8] = b[7:1] of I2C address 2 - */ -uint16_t board_i2c_slave_addrs(int controller); - /* MCHP - firwmare-reef-9042.B does have LID_ALS bit * because its using TASK_ALS ? */ diff --git a/board/reef_mchp/build.mk b/board/reef_mchp/build.mk index 303eae4be4..afc530837e 100644 --- a/board/reef_mchp/build.mk +++ b/board/reef_mchp/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -7,8 +7,8 @@ # CHIP:=mchp -CHIP_FAMILY:=mec17xx -CHIP_VARIANT:=mec1701h +CHIP_FAMILY:=mec170x +CHIP_VARIANT:=mec1701 CHIP_SPI_SIZE_KB:=512 board-y=board.o led.o diff --git a/board/reef_mchp/ec.tasklist b/board/reef_mchp/ec.tasklist index adf63fae62..8611d09301 100644 --- a/board/reef_mchp/ec.tasklist +++ b/board/reef_mchp/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/reef_mchp/gpio.inc b/board/reef_mchp/gpio.inc index baaf36330e..9783649e25 100644 --- a/board/reef_mchp/gpio.inc +++ b/board/reef_mchp/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,9 @@ /* Declare symbolic names for all the GPIOs that we care about. * Note: Those with interrupt handlers must be declared first. */ +/* include common gpio.inc under chip/mchp/lfw/... */ +#include "chip/mchp/lfw/gpio.inc" + /* MEC1701H GPIO_0105/UART0_RX OK */ GPIO_INT(UART0_RX, PIN(0105), GPIO_INT_BOTH_DSLEEP | GPIO_PULL_UP, \ uart_deepsleep_interrupt) @@ -81,7 +84,8 @@ GPIO(EC_I2C_POWER_SCL, PIN(010), GPIO_INPUT) * Pin 57 (SER_IRQ) defaults to LPC mode, but we also have EC_PCH_KB_INT_ODL * (Pin B0) in case it doesn't work (Set CONFIG_KEYBOARD_IRQ_GPIO in this case). * - * See also the NO_LPC_ESPI bit in DEVALT1 and the CONFIG_HOSTCMD_SPS option. + * See also the NO_LPC_ESPI bit in DEVALT1 and the + * CONFIG_HOST_INTERFACE_SHI option. */ GPIO(PCH_SMI_L, PIN(0227), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_SMI_ODL */ @@ -167,35 +171,10 @@ GPIO(USB_C1_5V_EN, PIN(061), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C1_5V_OUT, GPIO(BAT_LED_BLUE, PIN(0153), GPIO_OUT_HIGH) GPIO(BAT_LED_AMBER, PIN(0226), GPIO_OUT_HIGH) -/* - * MEC1701H - * GPIO_0055/PWM2/SHD_CS0#/RSMRST# - * GPIO_0124/GPTP-OUT6/PVT_CS#/KSO11 - * QMSPI controller drives chip select, must be - * configured to alternative function. See below. - * Always use the name QMSPI_CS0 for chip select. - * Actual GPIO could be GPIO_0055 QMSPI shared chip select or - * GPIO_0124 private chip select. - */ -GPIO(QMSPI_CS0, PIN(055), GPIO_ODR_HIGH) - /* * Alternate function pins */ -/* - * MEC1701H SHD SPI is connected to QMSPI controller. - * QMSPI drives chip select. SHD_CS0#(GPIO_0055) must be set - * to alternate function 2 and GPIO_ODR_HIGH. - * GPIO_0055 Function 2, Bank 1 bit[13] - */ -ALTERNATE(PIN_MASK(1, 0x2000), 2, MODULE_SPI_FLASH, GPIO_ODR_HIGH) -/* SHD_CLK - GPIO_0056 Function 2, Bank 1 bit[14] */ -ALTERNATE(PIN_MASK(1, 0x4000), 2, MODULE_SPI_FLASH, 0) -/* MOSI(SHD_IO0) - GPIO_0223 Function 2, Bank 4 bit[19] */ -/* MISO(SHD_IO1) - GPIO_0224 Function 2, Bank 4 bit[20] */ -ALTERNATE(PIN_MASK(4, 0x180000), 2, MODULE_SPI_FLASH, 0) - /* MEC1701H LPC all alternate function 1 * bank bit * GPIO061 LPCPD# 1 17 @@ -290,13 +269,6 @@ ALTERNATE(PIN_MASK(3, 0x00003001), 1, MODULE_I2C, 0) /* reefmchp board note: not PWM in reef or reedmchp boards design?? */ //ALTERNATE(PIN_MASK(0, 0x00000006), 1, MODULE_PWM, 0) -/* - * GPIO_0104(UART0_TX) Func1 - * GPIO_0105(UART0_RX) Func1 - * Bank 2 bits[4:5] - */ -ALTERNATE(PIN_MASK(2, 0x30), 1, MODULE_UART, 0) - /* * MCHP TFDP alternate function configuration * GPIO 0170 = clock, 0171 = data both function 1 diff --git a/board/reef_mchp/led.c b/board/reef_mchp/led.c index ca49fe4ed5..ad06133890 100644 --- a/board/reef_mchp/led.c +++ b/board/reef_mchp/led.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -27,8 +27,7 @@ #define LED_ON_1SEC_TICKS 1 #define LED_ON_2SECS_TICKS 2 -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -36,7 +35,7 @@ enum led_color { LED_OFF = 0, LED_BLUE, LED_AMBER, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int led_set_color_battery(enum led_color color) @@ -97,41 +96,46 @@ static void led_set_battery(void) static int battery_ticks; static int suspend_ticks; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: led_set_color_battery(LED_AMBER); break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { led_set_color_battery(LED_BLUE); break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE /* and PWR_STATE_DISCHARGE_FULL */: + __fallthrough; + case LED_PWRS_DISCHARGE /* and LED_PWRS_DISCHARGE_FULL */: if (chipset_in_state(CHIPSET_STATE_ON)) { led_set_color_battery(LED_BLUE); } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { /* Blink once every four seconds. */ led_set_color_battery( - (suspend_ticks % LED_TOTAL_4SECS_TICKS) - < LED_ON_1SEC_TICKS ? LED_AMBER : LED_OFF); + (suspend_ticks % LED_TOTAL_4SECS_TICKS) < + LED_ON_1SEC_TICKS ? + LED_AMBER : + LED_OFF); } else { led_set_color_battery(LED_OFF); } break; - case PWR_STATE_ERROR: - led_set_color_battery( - (battery_ticks % LED_TOTAL_2SECS_TICKS < - LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); + case LED_PWRS_ERROR: + led_set_color_battery((battery_ticks % LED_TOTAL_2SECS_TICKS < + LED_ON_1SEC_TICKS) ? + LED_AMBER : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: led_set_color_battery(LED_BLUE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ + case LED_PWRS_IDLE: /* External power connected in IDLE */ if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE) led_set_color_battery( (battery_ticks % LED_TOTAL_4SECS_TICKS < - LED_ON_2SECS_TICKS) ? LED_AMBER : LED_BLUE); + LED_ON_2SECS_TICKS) ? + LED_AMBER : + LED_BLUE); else led_set_color_battery(LED_BLUE); break; diff --git a/board/reef_mchp/lfw/gpio.inc b/board/reef_mchp/lfw/gpio.inc deleted file mode 100644 index f4142d3c29..0000000000 --- a/board/reef_mchp/lfw/gpio.inc +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Minimal set of GPIOs needed for LFW loader - */ - -/* - * MEC1701H GPIO_0055/PWM2/SHD_CS0#/RSMRST# - * MEC1701H QMSPI controller drives chip select, must be - * configured to alternative function. See below. - * GPIO_SHD_CS0 is used in board level spi_devices[] table - */ -GPIO(QMSPI_CS0, PIN(055), GPIO_ODR_HIGH) - - -/* Alternate functions GPIO definition */ - -/* - * UART - * GPIO_0104(UART0_TX) Func1 - * GPIO_0105(UART0_RX) Func1 - * Bank 2 bits[4:5] -*/ -ALTERNATE(PIN_MASK(2, 0x30), 1, MODULE_UART, 0) - -/* SPI pins */ -/* - * MEC1701H SHD SPI is connected to QMSPI controller. - * QMSPI drives chip select. SHD_CS0#(GPIO_0055) must be set - * to alternate function 2 and GPIO_ODR_HIGH. - * GPIO_0055 Function 2, Bank 1 bit[13] - */ -ALTERNATE(PIN_MASK(1, 0x2000), 2, MODULE_SPI_FLASH, GPIO_ODR_HIGH) -/* SHD_CLK - GPIO_0056 Function 2, Bank 1 bit[14] */ -ALTERNATE(PIN_MASK(1, 0x4000), 2, MODULE_SPI_FLASH, 0) -/* MOSI(SHD_IO0) - GPIO_0223 Function 2, Bank 4 bit[19] */ -/* MISO(SHD_IO1) - GPIO_0224 Function 2, Bank 4 bit[20] */ -ALTERNATE(PIN_MASK(4, 0x180000), 2, MODULE_SPI_FLASH, 0) - - diff --git a/board/reef_mchp/lfw/vif_override.xml b/board/reef_mchp/lfw/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/reef_mchp/lfw/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/reef_mchp/usb_pd_policy.c b/board/reef_mchp/usb_pd_policy.c index 90f44f8580..060d53a58a 100644 --- a/board/reef_mchp/usb_pd_policy.c +++ b/board/reef_mchp/usb_pd_policy.c @@ -1,36 +1,35 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/charger/bd9995x.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "registers.h" #include "system.h" #include "task.h" +#include "tfdp_chip.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#include "tfdp_chip.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = {TYPEC_RP_1A5, - TYPEC_RP_1A5}; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, + TYPEC_RP_1A5 }; int board_vbus_source_enabled(int port) { @@ -41,7 +40,8 @@ static void board_vbus_update_source_current(int port) { enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? - (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP); + (GPIO_INPUT | GPIO_PULL_UP) : + (GPIO_OUTPUT | GPIO_PULL_UP); /* * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance diff --git a/board/reef_mchp/vif_override.xml b/board/reef_mchp/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/reef_mchp/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/samus/battery.c b/board/samus/battery.c deleted file mode 100644 index bc73cbc1c3..0000000000 --- a/board/samus/battery.c +++ /dev/null @@ -1,301 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery_smart.h" -#include "charge_state.h" -#include "console.h" -#include "ec_commands.h" -#include "extpower.h" -#include "i2c.h" -#include "util.h" - -static const struct battery_info info = { - /* - * Design voltage - * max = 8.4V - * normal = 7.4V - * min = 6.0V - */ - .voltage_max = 8700, - .voltage_normal = 7400, - .voltage_min = 6000, - - /* Pre-charge current: I <= 0.01C */ - .precharge_current = 64, /* mA */ - - /* - * Operational temperature range - * 0 <= T_charge <= 50 deg C - * -20 <= T_discharge <= 60 deg C - */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 50, - .discharging_min_c = -20, - .discharging_max_c = 60, -}; - -const struct battery_info *battery_get_info(void) -{ - return &info; -} - -#ifdef CONFIG_CHARGER_PROFILE_OVERRIDE - -static int fast_charging_allowed = 1; - -/* - * This can override the smart battery's charging profile. To make a change, - * modify one or more of requested_voltage, requested_current, or state. - * Leave everything else unchanged. - * - * Return the next poll period in usec, or zero to use the default (which is - * state dependent). - */ -int charger_profile_override(struct charge_state_data *curr) -{ - /* temp in 0.1 deg C */ - int temp_c; - const struct charger_info *info; - - /* keep track of last temperature range for hysteresis */ - static enum { - TEMP_LOW, - TEMP_NORMAL, - TEMP_HIGH - } temp_range = TEMP_NORMAL, prev_temp_range = TEMP_NORMAL; - - /* charging voltage to use at high temp */ - static int high_temp_charging_voltage; - - /* custom profile phase at normal temp */ - static int normal_temp_phase; - - /* battery voltage and current and previous voltage and current */ - int batt_voltage, batt_current; - static int prev_batt_voltage, prev_batt_current; - - /* - * Determine temperature range: - * Low: Battery is <15C - * Normal: Battery is 15-45C - * High: Battery is >45C - * - * Add 0.2 degrees of hysteresis. - * If temp reading was bad use last range. - */ - if (!(curr->batt.flags & BATT_FLAG_BAD_TEMPERATURE)) { - temp_c = curr->batt.temperature - 2731; - if (temp_c < 149) - temp_range = TEMP_LOW; - else if (temp_c > 151 && temp_c < 449) - temp_range = TEMP_NORMAL; - else if (temp_c > 451) - temp_range = TEMP_HIGH; - } - - /* - * Treat voltage and current as a pair, if either is bad fall back to - * previous reading. - */ - if (curr->batt.flags & - (BATT_FLAG_BAD_VOLTAGE | BATT_FLAG_BAD_CURRENT)) { - batt_voltage = prev_batt_voltage; - batt_current = prev_batt_current; - } else { - batt_voltage = prev_batt_voltage = curr->batt.voltage; - batt_current = prev_batt_current = curr->batt.current; - } - - /* - * If we are not charging or we aren't using fast charging profiles, - * then do not override desired current and voltage and reset some - * fast charging profile static variables. - */ - if (curr->state != ST_CHARGE || !fast_charging_allowed) { - prev_temp_range = TEMP_NORMAL; - normal_temp_phase = 0; - return 0; - } - - /* - * Okay, impose our custom will: - * Normal temp: - * Phase 0: CC at 9515mA @ 8.3V - * CV at 8.3V until current drops to 4759mA - * Phase 1: CC at 4759mA @ 8.7V - * CV at 8.7V - * - * Low temp: - * CC at 2854mA @ 8.7V - * CV at 8.7V - * - * High temp: - * If battery voltage < 8.3V then: - * CC at 6660mA @ 8.3V - * CV at 8.3V (when battery is hot we don't go to fully charged) - * else: - * CV at just above battery voltage which will essentially - * terminate the charge and allow battery to cool. - * Note that if we ever request a voltage below the present battery - * voltage, then we will stop the BQ switching, which will power off - * the INA and we won't be able to charge again until AC is - * disconnected. see crbug.com/p/35491. - */ - switch (temp_range) { - case TEMP_LOW: - curr->requested_current = 2854; - curr->requested_voltage = 8700; - break; - case TEMP_NORMAL: - if (normal_temp_phase == 0) { - curr->requested_current = 9515; - curr->requested_voltage = 8300; - if (batt_current <= 4759 && batt_voltage >= 8200) - normal_temp_phase = 1; - } - if (normal_temp_phase == 1) { - curr->requested_current = 4759; - curr->requested_voltage = 8700; - } - break; - case TEMP_HIGH: - /* - * First time TEMP_HIGH is used, get the closest voltage - * just above the battery voltage. If it is above 8.3V, we - * will use that as the target, otherwise we will use 8.3V. - */ - if (prev_temp_range != TEMP_HIGH) { - info = charger_get_info(); - high_temp_charging_voltage = MAX(8300, - charger_closest_voltage(batt_voltage + - info->voltage_step)); - } - curr->requested_current = 6660; - curr->requested_voltage = high_temp_charging_voltage; - break; - } - prev_temp_range = temp_range; - - return 0; -} - -/* Customs options controllable by host command. */ -#define PARAM_FASTCHARGE (CS_PARAM_CUSTOM_PROFILE_MIN + 0) - -enum ec_status charger_profile_override_get_param(uint32_t param, - uint32_t *value) -{ - if (param == PARAM_FASTCHARGE) { - *value = fast_charging_allowed; - return EC_RES_SUCCESS; - } - return EC_RES_INVALID_PARAM; -} - -enum ec_status charger_profile_override_set_param(uint32_t param, - uint32_t value) -{ - if (param == PARAM_FASTCHARGE) { - fast_charging_allowed = value; - return EC_RES_SUCCESS; - } - return EC_RES_INVALID_PARAM; -} - -#ifdef CONFIG_CMD_FASTCHARGE -static int command_fastcharge(int argc, char **argv) -{ - if (argc > 1 && !parse_bool(argv[1], &fast_charging_allowed)) - return EC_ERROR_PARAM1; - - ccprintf("fastcharge %s\n", fast_charging_allowed ? "on" : "off"); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(fastcharge, command_fastcharge, - "[on|off]", - "Get or set fast charging profile"); -#endif /* CONFIG_CMD_FASTCHARGE */ - -#endif /* CONFIG_CHARGER_PROFILE_OVERRIDE */ - -#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT -/* - * Check if battery is in disconnect state, a state entered by pulling - * BATT_DISCONN_N low, and clear that state if we have external power plugged - * and no battery faults are detected. Disconnect state resembles battery - * shutdown mode, but extra steps must be taken to get the battery out of this - * mode. - */ -enum battery_disconnect_state battery_get_disconnect_state(void) -{ - uint8_t data[6]; - int rv; - /* - * Take note if we find that the battery isn't in disconnect state, - * and always return NOT_DISCONNECTED without probing the battery. - * This assumes the battery will not go to disconnect state during - * runtime. - */ - static int not_disconnected; - - if (not_disconnected) - return BATTERY_NOT_DISCONNECTED; - - if (extpower_is_present()) { - /* Check if battery charging + discharging is disabled. */ - rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); - if (rv) - return BATTERY_DISCONNECT_ERROR; - if (~data[3] & (BATTERY_DISCHARGING_DISABLED | - BATTERY_CHARGING_DISABLED)) { - not_disconnected = 1; - return BATTERY_NOT_DISCONNECTED; - } - - /* - * Battery is neither charging nor discharging. Verify that - * we didn't enter this state due to a safety fault. - */ - rv = sb_read_mfgacc(PARAM_SAFETY_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); - if (rv || data[2] || data[3] || data[4] || data[5]) - return BATTERY_DISCONNECT_ERROR; - else - /* No safety fault -- clear disconnect state. */ - return BATTERY_DISCONNECTED; - } - not_disconnected = 1; - return BATTERY_NOT_DISCONNECTED; -} -#endif /* CONFIG_BATTERY_REVIVE_DISCONNECT */ - -#define PARAM_CUT_OFF_LOW 0x10 -#define PARAM_CUT_OFF_HIGH 0x00 - -int board_cut_off_battery(void) -{ - int rv; - uint8_t buf[3]; - - buf[0] = SB_MANUFACTURER_ACCESS & 0xff; - buf[1] = PARAM_CUT_OFF_LOW; - buf[2] = PARAM_CUT_OFF_HIGH; - - i2c_lock(I2C_PORT_BATTERY, 1); - rv = i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - buf, 3, NULL, 0, I2C_XFER_SINGLE); - rv |= i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - buf, 3, NULL, 0, I2C_XFER_SINGLE); - i2c_lock(I2C_PORT_BATTERY, 0); - - return rv; -} - diff --git a/board/samus/board.c b/board/samus/board.c deleted file mode 100644 index 211d000e86..0000000000 --- a/board/samus/board.c +++ /dev/null @@ -1,500 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -/* EC for Samus board configuration */ - -#include "als.h" -#include "adc.h" -#include "adc_chip.h" -#include "backlight.h" -#include "battery.h" -#include "capsense.h" -#include "charger.h" -#include "charge_state.h" -#include "common.h" -#include "console.h" -#include "driver/accel_kionix.h" -#include "driver/accel_kxcj9.h" -#include "driver/accelgyro_lsm6ds0.h" -#include "driver/als_isl29035.h" -#include "driver/charger/bq24773.h" -#include "driver/temp_sensor/tmp006.h" -#include "extpower.h" -#include "fan.h" -#include "gesture.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "keyboard_scan.h" -#include "keyboard_8042.h" -#include "keyboard_8042_sharedlib.h" -#include "lid_switch.h" -#include "lightbar.h" -#include "motion_sense.h" -#include "motion_lid.h" -#include "peci.h" -#include "power.h" -#include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "registers.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "temp_sensor.h" -#include "temp_sensor_chip.h" -#include "timer.h" -#include "thermal.h" -#include "uart.h" -#include "util.h" - -static void pd_mcu_interrupt(enum gpio_signal signal) -{ - /* Exchange status with PD MCU. */ - host_command_pd_send_status(PD_CHARGE_NO_CHANGE); -} - -#include "gpio_list.h" - -/* power signal list. Must match order of enum power_signal. */ -const struct power_signal_info power_signal_list[] = { - {GPIO_PP1050_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "PGOOD_PP1050"}, - {GPIO_PP1200_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "PGOOD_PP1200"}, - {GPIO_PP1800_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "PGOOD_PP1800"}, - {GPIO_VCORE_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "PGOOD_VCORE"}, - {GPIO_PCH_SLP_S0_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S0_DEASSERTED"}, - {GPIO_PCH_SLP_S3_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S3_DEASSERTED"}, - {GPIO_PCH_SLP_S5_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S5_DEASSERTED"}, - {GPIO_PCH_SLP_SUS_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_SUS_DEASSERTED"}, - {GPIO_PCH_SUSWARN_L, POWER_SIGNAL_ACTIVE_HIGH, "SUSWARN_DEASSERTED"}, -}; -BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); - -/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ -const struct adc_t adc_channels[] = { - /* - * EC internal temperature is calculated by - * 273 + (295 - 450 * ADC_VALUE / ADC_READ_MAX) / 2 - * = -225 * ADC_VALUE / ADC_READ_MAX + 420.5 - */ - {"ECTemp", LM4_ADC_SEQ0, -225, ADC_READ_MAX, 420, - LM4_AIN_NONE, 0x0e /* TS0 | IE0 | END0 */, 0, 0}, - /* - * TODO(crosbug.com/p/23827): We don't know what to expect here, but - * it's an analog input that's pulled high. We're using it as a battery - * presence indicator for now. We'll return just 0 - ADC_READ_MAX for - * now. - */ - {"BatteryTemp", LM4_ADC_SEQ2, 1, 1, 0, - LM4_AIN(10), 0x06 /* IE0 | END0 */, LM4_GPIO_B, BIT(4)}, -}; -BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - -/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ -const struct pwm_t pwm_channels[] = { - {4, 0}, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -/* Physical fans. These are logically separate from pwm_channels. */ -const struct fan_conf fan_conf_0 = { - .flags = FAN_USE_RPM_MODE, - .ch = 2, /* Use MFT id to control fan */ - .pgood_gpio = -1, - .enable_gpio = -1, -}; - -const struct fan_conf fan_conf_1 = { - .flags = FAN_USE_RPM_MODE, - .ch = 3, /* Use MFT id to control fan */ - .pgood_gpio = -1, - .enable_gpio = -1, -}; - -const struct fan_rpm fan_rpm_0 = { - .rpm_min = 1000, - .rpm_start = 1000, - .rpm_max = 6350, -}; - -const struct fan_t fans[] = { - { .conf = &fan_conf_0, .rpm = &fan_rpm_0, }, - { .conf = &fan_conf_1, .rpm = &fan_rpm_0, }, -}; -BUILD_ASSERT(ARRAY_SIZE(fans) == CONFIG_FANS); - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"batt_chg", 0, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"lightbar", 1, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"thermal", 5, 100, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/* Charger chips */ -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = I2C_ADDR_CHARGER_FLAGS, - .drv = &bq2477x_drv, - }, -}; - -#define TEMP_U40_REG_ADDR_FLAGS (0x40 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U41_REG_ADDR_FLAGS (0x44 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U42_REG_ADDR_FLAGS (0x41 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U43_REG_ADDR_FLAGS (0x45 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U115_REG_ADDR_FLAGS (0x42 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U116_REG_ADDR_FLAGS (0x43 | I2C_FLAG_BIG_ENDIAN) - -#define TEMP_U40_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U40_REG_ADDR_FLAGS) -#define TEMP_U41_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U41_REG_ADDR_FLAGS) -#define TEMP_U42_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U42_REG_ADDR_FLAGS) -#define TEMP_U43_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U43_REG_ADDR_FLAGS) -#define TEMP_U115_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U115_REG_ADDR_FLAGS) -#define TEMP_U116_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U116_REG_ADDR_FLAGS) - -const struct tmp006_t tmp006_sensors[TMP006_COUNT] = { - {"Charger", TEMP_U40_ADDR_FLAGS}, - {"CPU", TEMP_U41_ADDR_FLAGS}, - {"Left C", TEMP_U42_ADDR_FLAGS}, - {"Right C", TEMP_U43_ADDR_FLAGS}, - {"Right D", TEMP_U115_ADDR_FLAGS}, - {"Left D", TEMP_U116_ADDR_FLAGS}, -}; -BUILD_ASSERT(ARRAY_SIZE(tmp006_sensors) == TMP006_COUNT); - -/* Temperature sensors data; must be in same order as enum temp_sensor_id. */ -const struct temp_sensor_t temp_sensors[] = { - {"PECI", TEMP_SENSOR_TYPE_CPU, peci_temp_sensor_get_val, 0}, - {"ECInternal", TEMP_SENSOR_TYPE_BOARD, chip_temp_sensor_get_val, 0}, - {"I2C-Charger-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 0}, - {"I2C-Charger-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 1}, - {"I2C-CPU-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 2}, - {"I2C-CPU-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 3}, - {"I2C-Left C-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 4}, - {"I2C-Left C-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 5}, - {"I2C-Right C-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 6}, - {"I2C-Right C-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 7}, - {"I2C-Right D-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 8}, - {"I2C-Right D-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 9}, - {"I2C-Left D-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 10}, - {"I2C-Left D-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 11}, - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0}, -}; -BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - -/* ALS instances. Must be in same order as enum als_id. */ -struct als_t als[] = { - {"ISL", isl29035_init, isl29035_read_lux, 5}, -}; -BUILD_ASSERT(ARRAY_SIZE(als) == ALS_COUNT); - - -/* Thermal limits for each temp sensor. All temps are in degrees K. Must be in - * same order as enum temp_sensor_id. To always ignore any temp, use 0. - */ -struct ec_thermal_config thermal_params[] = { - /* {Twarn, Thigh, Thalt}, fan_off, fan_max */ - {{C_TO_K(95), C_TO_K(101), C_TO_K(104)}, - {0, 0, 0}, C_TO_K(55), C_TO_K(90)}, /* PECI */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* EC */ - {{0, 0, 0}, {0, 0, 0}, C_TO_K(41), C_TO_K(55)}, /* Charger die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, C_TO_K(35), C_TO_K(49)}, /* CPU die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Left C die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Right C die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Right D die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, C_TO_K(43), C_TO_K(54)}, /* Left D die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Battery */ -}; -BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); - -struct keyboard_scan_config keyscan_config = { - .output_settle_us = 40, - .debounce_down_us = 6 * MSEC, - .debounce_up_us = 30 * MSEC, - .scan_period_us = 1500, - .min_post_scan_delay_us = 1000, - .poll_timeout_us = SECOND, - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xf6, 0x55, 0xfa, 0xc8 /* full set */ - }, -}; - -/* Initialize board. */ -static void board_init(void) -{ - gpio_enable_interrupt(GPIO_PD_MCU_INT); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -#ifdef CONFIG_BATTERY_PRESENT_CUSTOM -/** - * Physical check of battery presence. - */ -enum battery_present battery_is_present(void) -{ - /* - * This pin has a pullup, so if it's not completely pegged there's - * something attached. Probably a battery. - */ - int analog_val = adc_read_channel(ADC_CH_BAT_TEMP); - return analog_val < (9 * ADC_READ_MAX / 10) ? BP_YES : BP_NO; -} -#endif - -static int discharging_on_ac; - -/** - * Discharge battery when on AC power for factory test. - */ -int board_discharge_on_ac(int enable) -{ - int rv = charger_discharge_on_ac(enable); - - if (rv == EC_SUCCESS) - discharging_on_ac = enable; - - return rv; -} - -/** - * Check if we are discharging while connected to AC - */ -int board_is_discharging_on_ac(void) -{ - return discharging_on_ac; -} - -/** - * Reset PD MCU - */ -void board_reset_pd_mcu(void) -{ - gpio_set_level(GPIO_USB_MCU_RST, 1); - usleep(100); - gpio_set_level(GPIO_USB_MCU_RST, 0); -} - -void sensor_board_proc_double_tap(void) -{ - lightbar_sequence(LIGHTBAR_TAP); -} - -const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { - GPIO_USB1_ENABLE, - GPIO_USB2_ENABLE, -}; - -/* Base Sensor mutex */ -static struct mutex g_base_mutex; - -/* Lid Sensor mutex */ -static struct mutex g_lid_mutex; - -/* kxcj9 local/private data */ -struct kionix_accel_data g_kxcj9_data; - -/* lsm6ds0 local sensor data (per-sensor) */ -struct lsm6ds0_data g_saved_data[2]; - -/* Four Motion sensors */ -/* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - {FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - {FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -struct motion_sensor_t motion_sensors[] = { - /* - * Note: lsm6ds0: supports accelerometer and gyro sensor - * Requirement: accelerometer sensor must init before gyro sensor - * DO NOT change the order of the following table. - */ - {.name = "Base", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, - .chip = MOTIONSENSE_CHIP_LSM6DS0, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6ds0_drv, - .mutex = &g_base_mutex, - .drv_data = &g_saved_data[0], - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = LSM6DS0_ADDR1_FLAGS, - .rot_standard_ref = &base_standard_ref, - .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ - .min_frequency = LSM6DS0_ACCEL_MIN_FREQ, - .max_frequency = LSM6DS0_ACCEL_MAX_FREQ, - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 119000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - /* Used for double tap */ - [SENSOR_CONFIG_EC_S3] = { - .odr = TAP_ODR_LSM6DS0 | ROUND_UP_FLAG, - .ec_rate = CONFIG_GESTURE_SAMPLING_INTERVAL_MS * MSEC, - }, - [SENSOR_CONFIG_EC_S5] = { - .odr = TAP_ODR_LSM6DS0 | ROUND_UP_FLAG, - .ec_rate = CONFIG_GESTURE_SAMPLING_INTERVAL_MS * MSEC, - }, - }, - }, - - {.name = "Lid", - .active_mask = SENSOR_ACTIVE_S0, - .chip = MOTIONSENSE_CHIP_KXCJ9, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &kionix_accel_drv, - .mutex = &g_lid_mutex, - .drv_data = &g_kxcj9_data, - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = KXCJ9_ADDR0_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .default_range = 2, /* g, to support lid angle calculation. */ - .min_frequency = KXCJ9_ACCEL_MIN_FREQ, - .max_frequency = KXCJ9_ACCEL_MAX_FREQ, - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 100000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, - }, - - {.name = "Base Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, - .chip = MOTIONSENSE_CHIP_LSM6DS0, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6ds0_drv, - .mutex = &g_base_mutex, - .drv_data = &g_saved_data[1], - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = LSM6DS0_ADDR1_FLAGS, - .rot_standard_ref = NULL, - .default_range = 2000, /* dps, enough for laptop. */ - .min_frequency = LSM6DS0_GYRO_MIN_FREQ, - .max_frequency = LSM6DS0_GYRO_MAX_FREQ, - }, - -}; -const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -#ifdef CONFIG_LOW_POWER_IDLE -void jtag_interrupt(enum gpio_signal signal) -{ - /* - * This interrupt is the first sign someone is trying to use - * the JTAG. Disable slow speed sleep so that the JTAG action - * can take place. - */ - disable_sleep(SLEEP_MASK_JTAG); - - /* - * Once we get this interrupt, disable it from occurring again - * to avoid repeated interrupts when debugging via JTAG. - */ - gpio_disable_interrupt(GPIO_JTAG_TCK); -} -#endif /* CONFIG_LOW_POWER_IDLE */ - - -enum ec_error_list keyboard_scancode_callback(uint16_t *make_code, - int8_t pressed) -{ - const uint16_t k = *make_code; - static uint8_t s; - static const uint16_t a[] = { - SCANCODE_UP, SCANCODE_UP, SCANCODE_DOWN, SCANCODE_DOWN, - SCANCODE_LEFT, SCANCODE_RIGHT, SCANCODE_LEFT, SCANCODE_RIGHT, - SCANCODE_B, SCANCODE_A}; - - if (!pressed) - return EC_SUCCESS; - - /* Lightbar demo mode: keyboard can fake the battery state */ - switch (k) { - case SCANCODE_UP: - demo_battery_level(1); - break; - case SCANCODE_DOWN: - demo_battery_level(-1); - break; - case SCANCODE_LEFT: - demo_is_charging(0); - break; - case SCANCODE_RIGHT: - demo_is_charging(1); - break; - case SCANCODE_F6: /* dim */ - demo_brightness(-1); - break; - case SCANCODE_F7: /* bright */ - demo_brightness(1); - break; - case SCANCODE_T: - demo_tap(); - break; - } - - if (k == a[s]) - s++; - else if (k != a[0]) - s = 0; - else if (s != 2) - s = 1; - - if (s == ARRAY_SIZE(a)) { - s = 0; - lightbar_sequence(LIGHTBAR_KONAMI); - } - return EC_SUCCESS; -} - -/* - * Use to define going in to hibernate early if low on battery. - * HIBERNATE_BATT_PCT specifies the low battery threshold - * for going into hibernate early, and HIBERNATE_BATT_SEC defines - * the minimum amount of time to stay in G3 before checking for low - * battery hibernate. - */ -#define HIBERNATE_BATT_PCT 10 -#define HIBERNATE_BATT_SEC (3600 * 24) - -__override enum critical_shutdown board_system_is_idle( - uint64_t last_shutdown_time, uint64_t *target, uint64_t now) -{ - if (charge_get_percent() <= HIBERNATE_BATT_PCT) { - uint64_t t = last_shutdown_time + HIBERNATE_BATT_SEC * SEC_UL; - *target = MIN(*target, t); - } - return now > *target ? - CRITICAL_SHUTDOWN_HIBERNATE : CRITICAL_SHUTDOWN_IGNORE; -} diff --git a/board/samus/board.h b/board/samus/board.h deleted file mode 100644 index 1e3154c2e3..0000000000 --- a/board/samus/board.h +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Configuration for Samus mainboard */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Debug features */ -#define CONFIG_CONSOLE_CMDHELP -#define CONFIG_TASK_PROFILING - -#undef HEY_USE_BUILTIN_CLKRUN - -/* Optional features */ -#define CONFIG_ACCELGYRO_LSM6DS0 -#define CONFIG_ACCEL_KXCJ9 -#define CONFIG_ACCEL_STD_REF_FRAME_OLD -#define CONFIG_ALS_ISL29035 -#define CONFIG_BOARD_VERSION_GPIO -#define CONFIG_CMD_ACCELS -#define CONFIG_CMD_ACCEL_INFO -#undef CONFIG_BATTERY_CRITICAL_SHUTDOWN_TIMEOUT -#define CONFIG_BATTERY_CRITICAL_SHUTDOWN_TIMEOUT 60 -#define CONFIG_BATTERY_CUT_OFF -#define CONFIG_POWER_COMMON -#define CONFIG_POWER_SHUTDOWN_PAUSE_IN_S5 -#define CONFIG_CHIPSET_CAN_THROTTLE -#define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG -#define CONFIG_KEYBOARD_PROTOCOL_8042 -#define CONFIG_KEYBOARD_COL2_INVERTED -#define CONFIG_KEYBOARD_SCANCODE_CALLBACK -#define CONFIG_LID_ANGLE -#define CONFIG_LIGHTBAR_POWER_RAILS -#define CONFIG_LOW_POWER_IDLE -#define CONFIG_POWER_BUTTON -#define CONFIG_POWER_BUTTON_X86 -/* Note: not CONFIG_BACKLIGHT_LID. It's handled specially for Samus. */ -#define CONFIG_BACKLIGHT_REQ_GPIO GPIO_PCH_BL_EN -/* TODO(crosbug.com/p/29467): remove this workaround when possible. */ -#define CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD -#define CONFIG_CHARGER_PROFILE_OVERRIDE -#define CONFIG_BATTERY_SMART -#define CONFIG_BATTERY_REVIVE_DISCONNECT -#define CONFIG_CHARGER -#define CONFIG_CHARGER_BQ24773 -#define CONFIG_CHARGER_ILIM_PIN_DISABLED -#define CONFIG_CHARGER_SENSE_RESISTOR 5 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 -#define CONFIG_CHARGER_INPUT_CURRENT 320 -#define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_DISCHARGE_ON_AC_CUSTOM -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 -#define CONFIG_FANS 2 -#define CONFIG_FAN_UPDATE_PERIOD 10 -#define CONFIG_FPU -#define CONFIG_GESTURE_DETECTION -#define CONFIG_GESTURE_SW_DETECTION -#define CONFIG_GESTURE_SAMPLING_INTERVAL_MS 5 -#undef CONFIG_HIBERNATE_DELAY_SEC -#define CONFIG_HIBERNATE_DELAY_SEC (3600 * 24 * 7) -#define CONFIG_HOSTCMD_PD -#define CONFIG_HOSTCMD_PD_CHG_CTRL -#define CONFIG_HOSTCMD_PD_PANIC -#define CONFIG_PECI_TJMAX 105 -#define CONFIG_PWM -#define CONFIG_PWM_KBLIGHT -#define CONFIG_TEMP_SENSOR -#define CONFIG_TEMP_SENSOR_TMP006 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_PP3300_DSW_GATED_EN -#define CONFIG_THROTTLE_AP -#define CONFIG_UART_HOST 2 -#define CONFIG_USB_PORT_POWER_SMART -#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_CDP -#define CONFIG_USB_PORT_POWER_SMART_INVERTED -#define GPIO_USB1_ILIM_SEL GPIO_USB1_ILIM_SEL_L -#define GPIO_USB2_ILIM_SEL GPIO_USB2_ILIM_SEL_L -#define CONFIG_VBOOT_HASH -#define CONFIG_WIRELESS -#define CONFIG_WIRELESS_SUSPEND \ - (EC_WIRELESS_SWITCH_WLAN | EC_WIRELESS_SWITCH_WLAN_POWER) -/* Do we want EC_WIRELESS_SWITCH_WWAN as well? */ - -#ifndef __ASSEMBLER__ - -/* I2C ports */ -#define I2C_PORT_BACKLIGHT 0 -#define I2C_PORT_BATTERY 0 -#define I2C_PORT_CHARGER 0 -#define I2C_PORT_PD_MCU 0 -#define I2C_PORT_ALS 1 -#define I2C_PORT_ACCEL 1 -#define I2C_PORT_LIGHTBAR 1 -#define I2C_PORT_THERMAL 5 - -/* 13x8 keyboard scanner uses an entire GPIO bank for row inputs */ -#define KB_SCAN_ROW_IRQ LM4_IRQ_GPIOK -#define KB_SCAN_ROW_GPIO LM4_GPIO_K - -/* Host connects to keyboard controller module via LPC */ -#define HOST_KB_BUS_LPC - -/* USB ports managed by the EC */ -#define USB_PORT_COUNT 2 - -#include "gpio_signal.h" - -/* x86 signal definitions */ -enum x86_signal { - X86_PGOOD_PP1050 = 0, - X86_PGOOD_PP1200, - X86_PGOOD_PP1800, - X86_PGOOD_VCORE, - - X86_SLP_S0_DEASSERTED, - X86_SLP_S3_DEASSERTED, - X86_SLP_S5_DEASSERTED, - X86_SLP_SUS_DEASSERTED, - X86_SUSWARN_DEASSERTED, - - /* Number of X86 signals */ - POWER_SIGNAL_COUNT -}; - -enum adc_channel { - /* EC internal die temperature in degrees K. */ - ADC_CH_EC_TEMP = 0, - /* BAT_TEMP */ - ADC_CH_BAT_TEMP, - - ADC_CH_COUNT -}; - -enum pwm_channel { - PWM_CH_KBLIGHT, - - /* Number of PWM channels */ - PWM_CH_COUNT -}; - -enum temp_sensor_id { - /* CPU die temperature via PECI */ - TEMP_SENSOR_CPU_PECI, - /* EC internal temperature sensor */ - TEMP_SENSOR_EC_INTERNAL, - /* TMP006 U40, die/object temperature near battery charger */ - TEMP_SENSOR_I2C_U40_DIE, - TEMP_SENSOR_I2C_U40_OBJECT, - /* TMP006 U41, die/object temperature near CPU */ - TEMP_SENSOR_I2C_U41_DIE, - TEMP_SENSOR_I2C_U41_OBJECT, - /* TMP006 U42, die/object temperature left side of C-case */ - TEMP_SENSOR_I2C_U42_DIE, - TEMP_SENSOR_I2C_U42_OBJECT, - /* TMP006 U43, die/object temperature right side of C-case */ - TEMP_SENSOR_I2C_U43_DIE, - TEMP_SENSOR_I2C_U43_OBJECT, - /* TMP006 U115, die/object temperature right side of D-case */ - TEMP_SENSOR_I2C_U115_DIE, - TEMP_SENSOR_I2C_U115_OBJECT, - /* TMP006 U116, die/object temperature left side of D-case */ - TEMP_SENSOR_I2C_U116_DIE, - TEMP_SENSOR_I2C_U116_OBJECT, - - /* Battery temperature sensor */ - TEMP_SENSOR_BATTERY, - - TEMP_SENSOR_COUNT -}; - -enum sensor_id { - BASE_ACCEL, - LID_ACCEL, - BASE_GYRO, - SENSOR_COUNT, -}; - -/* The number of TMP006 sensor chips on the board. */ -#define TMP006_COUNT 6 - -/* Light sensors attached to the EC. */ -enum als_id { - ALS_ISL29035 = 0, - - ALS_COUNT, -}; - -/* Wireless signals */ -#define WIRELESS_GPIO_WLAN GPIO_WLAN_OFF_L -#define WIRELESS_GPIO_WLAN_POWER GPIO_PP3300_WLAN_EN - -/* Discharge battery when on AC power for factory test. */ -int board_is_discharging_on_ac(void); - -/* Reset PD MCU */ -void board_reset_pd_mcu(void); - -/* Backboost detected interrupt */ -void bkboost_det_interrupt(enum gpio_signal signal); - -/* Interrupt handler for JTAG clock */ -void jtag_interrupt(enum gpio_signal signal); - -/* Bit masks for turning on PP5000 rail in G3 */ -#define PP5000_IN_G3_AC BIT(0) -#define PP5000_IN_G3_LIGHTBAR BIT(1) - -/* Enable/disable PP5000 rail mask in G3 */ -void set_pp5000_in_g3(int mask, int enable); - -/* Define for sensor tasks */ -#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP 0 -#define CONFIG_GESTURE_TAP_OUTER_WINDOW_T 200 -#define CONFIG_GESTURE_TAP_INNER_WINDOW_T 30 -#define CONFIG_GESTURE_TAP_MIN_INTERSTICE_T 120 -#define CONFIG_GESTURE_TAP_MAX_INTERSTICE_T 500 - -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/samus/build.mk b/board/samus/build.mk deleted file mode 100644 index 183605fc62..0000000000 --- a/board/samus/build.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -# the IC is TI Stellaris LM4 -CHIP:=lm4 - -# Samus has board-specific chipset code, and the tests don't -# compile with it. Disable them for now. -test-list-y= - -board-y=battery.o board.o power_sequence.o panel.o extpower.o diff --git a/board/samus/ec.tasklist b/board/samus/ec.tasklist deleted file mode 100644 index 345892a64b..0000000000 --- a/board/samus/ec.tasklist +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/** - * See CONFIG_TASK_LIST in config.h for details. - */ -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(ALS, als_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(LIGHTBAR, lightbar_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(EXTPOWER, extpower_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(MOTIONSENSE, motion_sense_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(PDCMD, pd_command_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) diff --git a/board/samus/extpower.c b/board/samus/extpower.c deleted file mode 100644 index c6a7424fca..0000000000 --- a/board/samus/extpower.c +++ /dev/null @@ -1,433 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * Pure GPIO-based external power detection, buffered to PCH. - * Drive high in S5-S0 when AC_PRESENT is high, otherwise drive low. - */ - -#include "bq24773.h" -#include "charge_state.h" -#include "charger.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "system.h" -#include "task.h" -#include "util.h" - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) - -/* Max number of attempts to enable/disable NVDC charger */ -#define CHARGER_MODE_ATTEMPTS 3 - -/* Backboost has been detected */ -static int bkboost_detected; - -/* Charging is disabled */ -static int charge_is_disabled; - -/* Extpower task has been initialized */ -static int extpower_task_initialized; - -/* - * Charge circuit occasionally gets wedged and doesn't charge. - * This variable keeps track of the state of the circuit. - */ -static enum { - CHARGE_CIRCUIT_OK, - CHARGE_CIRCUIT_WEDGED, -} charge_circuit_state = CHARGE_CIRCUIT_OK; - -int extpower_is_present(void) -{ - return gpio_get_level(GPIO_AC_PRESENT); -} - -static void extpower_buffer_to_pch(void) -{ - if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) { - /* Drive low in G3 state */ - gpio_set_level(GPIO_PCH_ACOK, 0); - } else { - /* Buffer from extpower in S5+ (where 3.3DSW enabled) */ - gpio_set_level(GPIO_PCH_ACOK, extpower_is_present()); - } -} -DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, extpower_buffer_to_pch, HOOK_PRIO_DEFAULT); - -static void extpower_shutdown(void) -{ - /* Drive ACOK buffer to PCH low when shutting down */ - gpio_set_level(GPIO_PCH_ACOK, 0); -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, extpower_shutdown, HOOK_PRIO_DEFAULT); - -void extpower_interrupt(enum gpio_signal signal) -{ - /* Trigger notification of external power change */ - extpower_buffer_to_pch(); - - /* Wake extpower task only if task has been initialized */ - if (extpower_task_initialized) - task_wake(TASK_ID_EXTPOWER); -} - -static void extpower_init(void) -{ - extpower_buffer_to_pch(); - - /* Enable interrupts, now that we've initialized */ - gpio_enable_interrupt(GPIO_AC_PRESENT); -} -DECLARE_HOOK(HOOK_INIT, extpower_init, HOOK_PRIO_DEFAULT); - -/* - * Save power in S3/S5/G3 by disabling charging when the battery is - * full. Restore charging when battery is not full anymore. This saves - * power because our input AC path is inefficient. - */ - -static void check_charging_cutoff(void) -{ - /* If battery is full disable charging */ - if (charge_get_percent() == 100) { - charge_is_disabled = 1; - host_command_pd_send_status(PD_CHARGE_NONE); - } -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, check_charging_cutoff, HOOK_PRIO_DEFAULT); - -static void cancel_charging_cutoff(void) -{ - /* If charging is disabled, enable it */ - if (charge_is_disabled) { - charge_is_disabled = 0; - host_command_pd_send_status(PD_CHARGE_5V); - } -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, cancel_charging_cutoff, HOOK_PRIO_DEFAULT); - -static void batt_soc_change(void) -{ - /* If in S0, leave charging alone */ - if (chipset_in_state(CHIPSET_STATE_ON)) { - host_command_pd_send_status(PD_CHARGE_NO_CHANGE); - return; - } - - /* Check to disable or enable charging based on batt state of charge */ - if (!charge_is_disabled && charge_get_percent() == 100) { - host_command_pd_send_status(PD_CHARGE_NONE); - charge_is_disabled = 1; - } else if (charge_is_disabled && charge_get_percent() < 100) { - charge_is_disabled = 0; - host_command_pd_send_status(PD_CHARGE_5V); - } else { - /* Leave charging alone, but update battery SOC */ - host_command_pd_send_status(PD_CHARGE_NO_CHANGE); - } -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, batt_soc_change, HOOK_PRIO_DEFAULT); - -/** - * Enable/disable NVDC charger to control AC to system and battery. - */ -static void charger_disable(int disable) -{ - int i, rv; - - for (i = 0; i < CHARGER_MODE_ATTEMPTS; i++) { - rv = charger_discharge_on_ac(disable); - if (rv == EC_SUCCESS) - return; - } - - CPRINTS("Setting learn mode %d failed!", disable); -} - -static void allow_max_request(void) -{ - int prochot_status; - if (charge_circuit_state == CHARGE_CIRCUIT_WEDGED) { - /* Read PROCHOT status register to clear it */ - i2c_read8(I2C_PORT_CHARGER, BQ24773_ADDR_FLAGS, - BQ24773_PROCHOT_STATUS, &prochot_status); - charge_circuit_state = CHARGE_CIRCUIT_OK; - } - host_command_pd_send_status(PD_CHARGE_MAX); -} -DECLARE_DEFERRED(allow_max_request); - -static void allow_min_charging(void) -{ - if (!charge_is_disabled && charge_circuit_state == CHARGE_CIRCUIT_OK) - host_command_pd_send_status(PD_CHARGE_5V); -} -DECLARE_DEFERRED(allow_min_charging); - -static void extpower_board_hacks(int extpower, int extpower_prev) -{ - /* Cancel deferred attempt to enable max charge request */ - hook_call_deferred(&allow_max_request_data, -1); - - /* - * When AC is detected, delay briefly before allowing PD - * to negotiate up to the max voltage to give charge circuit - * time to settle down. When AC goes away, disable charging - * for a brief time, allowing charge state machine time to - * see AC has gone away, and then set PD to only allow - * 5V charging for the next time AC is connected. - * - * Use NVDC charger learn mode (charger_disable()) when AC - * is not present to avoid backboosting when AC is plugged in. - * - * When in G3, PP5000 needs to be enabled to accurately sense - * CC voltage when AC is attached. When AC is disconnceted - * it needs to be off to save power. - */ - if (extpower && !extpower_prev) { - /* AC connected */ - charger_disable(0); - hook_call_deferred(&allow_max_request_data, 500*MSEC); - set_pp5000_in_g3(PP5000_IN_G3_AC, 1); - } else if (extpower && extpower_prev) { - /* - * Glitch on AC_PRESENT, attempt to recover from - * backboost - */ - host_command_pd_send_status(PD_CHARGE_NONE); - } else { - /* AC disconnected */ - if (!charge_is_disabled && - charge_circuit_state == CHARGE_CIRCUIT_OK) - host_command_pd_send_status(PD_CHARGE_NONE); - - charger_disable(1); - - hook_call_deferred(&allow_min_charging_data, 100*MSEC); - set_pp5000_in_g3(PP5000_IN_G3_AC, 0); - } - extpower_prev = extpower; -} - -/* Return boostin_voltage or negative if error */ -static int get_boostin_voltage(void) -{ - /* Static structs to save stack space */ - static struct ec_response_usb_pd_power_info pd_power_ret; - static struct ec_params_usb_pd_power_info pd_power_args; - int ret; - int err; - - /* Boost-in voltage is maximum of voltage now on each port */ - pd_power_args.port = 0; - err = pd_host_command(EC_CMD_USB_PD_POWER_INFO, 0, - &pd_power_args, - sizeof(struct ec_params_usb_pd_power_info), - &pd_power_ret, - sizeof(struct ec_response_usb_pd_power_info)); - if (err < 0) - return err; - ret = pd_power_ret.meas.voltage_now; - - pd_power_args.port = 1; - err = pd_host_command(EC_CMD_USB_PD_POWER_INFO, 0, - &pd_power_args, - sizeof(struct ec_params_usb_pd_power_info), - &pd_power_ret, - sizeof(struct ec_response_usb_pd_power_info)); - if (err < 0) - return err; - - /* Get max of two measuremente */ - if (pd_power_ret.meas.voltage_now > ret) - ret = pd_power_ret.meas.voltage_now; - - return ret; -} - -/* - * Send command to PD to write a custom persistent log entry indicating that - * charging was wedged. Returns pd_host_command success status. - */ -static int log_charge_wedged(void) -{ - static struct ec_params_pd_write_log_entry log_args; - - log_args.type = PD_EVENT_MCU_BOARD_CUSTOM; - log_args.port = 0; - - return pd_host_command(EC_CMD_PD_WRITE_LOG_ENTRY, 0, - &log_args, - sizeof(struct ec_params_pd_write_log_entry), - NULL, 0); -} - -/* Time interval between checking if charge circuit is wedged */ -#define CHARGE_WEDGE_CHECK_INTERVAL (2*SECOND) - -/* - * Number of iterations through check_charge_wedged() with charging stalled - * before attempting unwedge. - */ -#define CHARGE_STALLED_COUNT 5 -/* - * Number of iterations through check_charge_wedged() with charging stalled - * after we already just tried unwedging the circuit, before we try again. - */ -#define CHARGE_STALLED_REPEATEDLY_COUNT 60 - -/* - * Minimum number of iterations through check_charge_wedged() between - * unwedge attempts. - */ -#define MIN_COUNTS_BETWEEN_UNWEDGES 3 - -static void check_charge_wedged(void) -{ - int rv, prochot_status, batt_discharging_on_ac, boostin_voltage = 0; - static int counts_since_wedged; - static int charge_stalled_count = CHARGE_STALLED_COUNT; - uint8_t *batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); - - if (charge_circuit_state == CHARGE_CIRCUIT_OK) { - /* Check PROCHOT warning */ - rv = i2c_read8(I2C_PORT_CHARGER, BQ24773_ADDR_FLAGS, - BQ24773_PROCHOT_STATUS, &prochot_status); - if (rv) - prochot_status = 0; - - batt_discharging_on_ac = - (*batt_flags & EC_BATT_FLAG_AC_PRESENT) && - (*batt_flags & EC_BATT_FLAG_DISCHARGING); - - /* - * If PROCHOT is set or we are discharging on AC, then we - * need to know boostin_voltage. - */ - if (prochot_status || batt_discharging_on_ac) - boostin_voltage = get_boostin_voltage(); - - /* - * If AC is present, and battery is discharging, and - * boostin voltage is above 5V, then we might be wedged. - */ - if (batt_discharging_on_ac) { - if (boostin_voltage > 6000) - charge_stalled_count--; - else if (boostin_voltage >= 0) - charge_stalled_count = CHARGE_STALLED_COUNT; - /* If boostin_voltage < 0, don't change stalled count */ - } else { - charge_stalled_count = CHARGE_STALLED_COUNT; - } - - /* - * If we were recently wedged, then give ourselves a free pass - * here. This gives an opportunity for reading the PROCHOT - * status to clear it if the error has gone away. - */ - if (counts_since_wedged < MIN_COUNTS_BETWEEN_UNWEDGES) - counts_since_wedged++; - - /* - * If PROCHOT is asserted AND boost_in voltage is above 5V, - * then charge circuit is wedged. If charging has been stalled - * long enough, then also consider the circuit wedged. - * - * To unwedge the charge circuit turn on learn mode and notify - * PD to disable charging on all ports. - * Note: learn mode is critical here because when in this state - * backboosting causes >20V on boostin even after PD disables - * CHARGE_EN lines. - */ - if ((prochot_status && boostin_voltage > 6000 && - counts_since_wedged >= MIN_COUNTS_BETWEEN_UNWEDGES) || - charge_stalled_count <= 0) { - counts_since_wedged = 0; - host_command_pd_send_status(PD_CHARGE_NONE); - charger_disable(1); - charge_circuit_state = CHARGE_CIRCUIT_WEDGED; - log_charge_wedged(); - CPRINTS("Charge wedged! PROCHOT %02x, Stalled: %d", - prochot_status, charge_stalled_count); - - /* - * If this doesn't clear the problem, then start - * the stall counter higher so that we don't retry - * unwedging for a while. Note, if we do start charging - * properly, then stall counter will be set to - * default, so that we will trigger faster the first - * time it stalls out. - */ - charge_stalled_count = CHARGE_STALLED_REPEATEDLY_COUNT; - } - } else { - /* - * Charge circuit is wedged and we already disabled charging, - * Now start to recover from wedged state by allowing 5V. - */ - host_command_pd_send_status(PD_CHARGE_5V); - } -} - -/** - * Task to handle external power change - */ -void extpower_task(void) -{ - int extpower = extpower_is_present(); - int extpower_prev = 0; - - extpower_board_hacks(extpower, extpower_prev); - extpower_prev = extpower; - extpower_task_initialized = 1; - - /* Enable backboost detection interrupt */ - gpio_enable_interrupt(GPIO_BKBOOST_DET); - - while (1) { - if (task_wait_event(CHARGE_WEDGE_CHECK_INTERVAL) == - TASK_EVENT_TIMER) { - /* - * If we are NOT purposely discharging on AC, then - * periodically check if charge circuit is wedged. - */ - if (!board_is_discharging_on_ac()) - check_charge_wedged(); - } else { - /* Must have received power change interrupt */ - extpower = extpower_is_present(); - - /* Various board hacks to run on extpower change */ - extpower_board_hacks(extpower, extpower_prev); - extpower_prev = extpower; - - extpower_handle_update(extpower); - } - } -} - -void bkboost_det_interrupt(enum gpio_signal signal) -{ - /* Backboost has been detected, save it, and disable interrupt */ - bkboost_detected = 1; - gpio_disable_interrupt(GPIO_BKBOOST_DET); -} - -static int command_backboost_det(int argc, char **argv) -{ - ccprintf("Backboost detected: %d\n", bkboost_detected); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(bkboost, command_backboost_det, NULL, - "Read backboost detection"); diff --git a/board/samus/gpio.inc b/board/samus/gpio.inc deleted file mode 100644 index 1b49c58bd0..0000000000 --- a/board/samus/gpio.inc +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -GPIO_INT(POWER_BUTTON_L, PIN(A, 2), GPIO_INT_BOTH_DSLEEP, power_button_interrupt) /* Power button */ -GPIO_INT(LID_OPEN, PIN(A, 3), GPIO_INT_BOTH_DSLEEP, lid_interrupt) /* Lid switch */ -GPIO_INT(AC_PRESENT, PIN(H, 3), GPIO_INT_BOTH_DSLEEP, extpower_interrupt) /* AC power present */ -GPIO_INT(PCH_SLP_S0_L, PIN(G, 6), GPIO_INT_BOTH, power_signal_interrupt) /* SLP_S0# signal from PCH */ -GPIO_INT(PCH_SLP_S3_L, PIN(G, 7), GPIO_INT_BOTH_DSLEEP, power_signal_interrupt) /* SLP_S3# signal from PCH */ -GPIO_INT(PCH_SLP_S5_L, PIN(H, 1), GPIO_INT_BOTH_DSLEEP, power_signal_interrupt) /* SLP_S5# signal from PCH */ -GPIO_INT(PCH_SLP_SUS_L, PIN(G, 3), GPIO_INT_BOTH, power_signal_interrupt) /* SLP_SUS# signal from PCH */ -GPIO_INT(PCH_SUSWARN_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) /* SUSWARN# signal from PCH */ -GPIO_INT(PP1050_PGOOD, PIN(H, 4), GPIO_INT_BOTH, power_signal_interrupt) /* Power good on 1.05V */ -GPIO_INT(PP1200_PGOOD, PIN(H, 6), GPIO_INT_BOTH, power_signal_interrupt) /* Power good on 1.2V (DRAM) */ -GPIO_INT(PP1800_PGOOD, PIN(L, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Power good on 1.8V (DRAM) */ -GPIO_INT(VCORE_PGOOD, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) /* Power good on core VR */ -GPIO_INT(WP_L, PIN(A, 4), GPIO_INT_BOTH, switch_interrupt) /* Write protect input */ -GPIO_INT(PCH_BL_EN, PIN(M, 3), GPIO_INT_RISING, backlight_interrupt) /* PCH backlight input */ -GPIO_INT(JTAG_TCK, PIN(C, 0), GPIO_DEFAULT, jtag_interrupt) /* JTAG clock input */ -GPIO_INT(UART0_RX, PIN(A, 0), GPIO_PULL_UP | GPIO_INT_BOTH_DSLEEP, uart_deepsleep_interrupt) /* UART0 RX input */ -GPIO_INT(BKBOOST_DET, PIN(B, 5), GPIO_INT_RISING, bkboost_det_interrupt) /* Backboost detect */ - -/* Interrupt signal from PD MCU, external pull-down */ -GPIO_INT(PD_MCU_INT, PIN(J, 5), GPIO_INT_RISING | GPIO_INT_DSLEEP, pd_mcu_interrupt) - -/* - * Combined accelerometer input. This will become an interrupt, once we have - * support for it. - */ -GPIO(ACCEL_INT, PIN(F, 7), GPIO_INPUT) - -/* - * Ambient Light Sensor input. This could become an interrupt once supported. - */ -GPIO(ALS_INT_L, PIN(N, 0), GPIO_INPUT) - -/* Other inputs */ -GPIO(BOARD_VERSION1, PIN(Q, 7), GPIO_INPUT) /* Board version stuffing resistor 1 */ -GPIO(BOARD_VERSION2, PIN(Q, 6), GPIO_INPUT) /* Board version stuffing resistor 2 */ -GPIO(BOARD_VERSION3, PIN(Q, 5), GPIO_INPUT) /* Board version stuffing resistor 3 */ -GPIO(USB1_OC_L, PIN(E, 7), GPIO_INPUT) /* USB port overcurrent warning */ -GPIO(USB1_STATUS_L, PIN(E, 6), GPIO_INPUT) /* USB charger port 1 status output */ -GPIO(USB2_OC_L, PIN(E, 0), GPIO_INPUT) /* USB port overcurrent warning */ -GPIO(USB2_STATUS_L, PIN(D, 7), GPIO_INPUT) /* USB charger port 2 status output */ -GPIO(PD_IN_RW, PIN(A, 5), GPIO_INPUT) /* PD is in RW */ -GPIO(PCH_HDA_SDO_L, PIN(G, 1), GPIO_INPUT) /* HDA_SDO signal to PCH to disable ME */ - -/* Outputs; all unasserted by default except for reset signals */ -GPIO(CPU_PROCHOT, PIN(B, 1), GPIO_OUT_LOW) /* Force CPU to think it's overheated */ -GPIO(PP1200_EN, PIN(H, 5), GPIO_OUT_LOW) /* Enable 1.20V supply */ -GPIO(PP3300_DSW_EN, PIN(F, 6), GPIO_OUT_LOW) /* Enable 3.3V DSW rail */ -GPIO(PP3300_DSW_GATED_EN, PIN(J, 3), GPIO_OUT_LOW) /* Enable 3.3V Gated DSW and core VDD */ -GPIO(PP3300_LTE_EN, PIN(D, 2), GPIO_OUT_LOW) /* Enable LTE radio */ -GPIO(PP3300_WLAN_EN, PIN(J, 0), GPIO_OUT_LOW) /* Enable WiFi power */ -GPIO(PP1050_EN, PIN(C, 7), GPIO_OUT_LOW) /* Enable 1.05V regulator */ -GPIO(PP5000_USB_EN, PIN(C, 5), GPIO_OUT_LOW) /* Enable USB power */ -GPIO(PP5000_EN, PIN(H, 7), GPIO_OUT_LOW) /* Enable 5V supply */ -GPIO(PP1800_EN, PIN(L, 6), GPIO_OUT_LOW) /* Enable 1.8V supply */ -GPIO(SYS_PWROK, PIN(H, 2), GPIO_OUT_LOW) /* EC thinks everything is up and ready */ -GPIO(WLAN_OFF_L, PIN(J, 4), GPIO_OUT_LOW) /* Disable WiFi radio */ -GPIO(USB_MCU_RST, PIN(B, 0), GPIO_OUT_LOW) /* USB PD MCU reset */ -GPIO(ENABLE_BACKLIGHT, PIN(M, 7), GPIO_OUT_LOW) /* Enable backlight power */ -GPIO(ENABLE_TOUCHPAD, PIN(N, 1), GPIO_OUT_LOW) /* Enable touchpad power */ -GPIO(ENTERING_RW, PIN(D, 3), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ -GPIO(LIGHTBAR_RESET_L, PIN(J, 2), GPIO_ODR_LOW) /* Reset lightbar controllers */ -GPIO(PCH_DPWROK, PIN(G, 0), GPIO_OUT_LOW) /* Indicate when VccDSW is good */ -GPIO(PCH_RSMRST_L, PIN(C, 4), GPIO_OUT_LOW) /* Reset PCH resume power plane logic */ -GPIO(PCH_RTCRST_L, PIN(J, 1), GPIO_ODR_HIGH) /* Reset PCH RTC well */ -GPIO(PCH_WAKE_L, PIN(F, 0), GPIO_ODR_HIGH) /* Wake signal from EC to PCH */ -GPIO(PCH_NMI_L, PIN(F, 2), GPIO_ODR_HIGH) /* Non-maskable interrupt pin to PCH */ -GPIO(PCH_PWRBTN_L, PIN(H, 0), GPIO_ODR_HIGH) /* Power button output to PCH */ -GPIO(PCH_PWROK, PIN(F, 5), GPIO_OUT_LOW) /* PWROK / APWROK signals to PCH */ -GPIO(PCH_RCIN_L, PIN(F, 3), GPIO_ODR_HIGH) /* RCIN# line to PCH (for 8042 emulation) */ -GPIO(PCH_SYS_RST_L, PIN(F, 1), GPIO_ODR_HIGH) /* Reset PCH resume power plane logic */ -GPIO(PCH_SMI_L, PIN(F, 4), GPIO_ODR_HIGH) /* System management interrupt to PCH */ -GPIO(TOUCHSCREEN_RESET_L, PIN(N, 7), GPIO_ODR_LOW) /* Reset touch screen */ -GPIO(PCH_ACOK, PIN(M, 6), GPIO_OUT_LOW) /* AC present signal buffered to PCH */ -#ifndef HEY_USE_BUILTIN_CLKRUN -GPIO(LPC_CLKRUN_L, PIN(M, 2), GPIO_ODR_HIGH) /* Dunno. Probably important, though. */ -#endif -GPIO(USB1_CTL1, PIN(E, 1), GPIO_OUT_LOW) /* USB charger port 1 CTL1 output */ -GPIO(USB1_CTL2, PIN(E, 2), GPIO_OUT_HIGH) /* USB charger port 1 CTL2 output */ -GPIO(USB1_CTL3, PIN(E, 3), GPIO_OUT_LOW) /* USB charger port 1 CTL3 output */ -GPIO(USB1_ENABLE, PIN(E, 4), GPIO_OUT_HIGH) /* USB charger port 1 enable */ -GPIO(USB1_ILIM_SEL_L, PIN(E, 5), GPIO_OUT_HIGH) /* USB charger port 1 ILIM_SEL output */ -GPIO(USB2_CTL1, PIN(D, 0), GPIO_OUT_LOW) /* USB charger port 2 CTL1 output */ -GPIO(USB2_CTL2, PIN(D, 1), GPIO_OUT_HIGH) /* USB charger port 2 CTL2 output */ -GPIO(USB2_CTL3, PIN(D, 4), GPIO_OUT_LOW) /* USB charger port 2 CTL3 output */ -GPIO(USB2_ENABLE, PIN(D, 5), GPIO_OUT_HIGH) /* USB charger port 2 enable */ -GPIO(USB2_ILIM_SEL_L, PIN(D, 6), GPIO_OUT_HIGH) /* USB charger port 2 ILIM_SEL output */ - -GPIO(I2C0_SCL, PIN(B, 2), GPIO_ODR_HIGH) /* I2C port 0 SCL */ -GPIO(I2C0_SDA, PIN(B, 3), GPIO_ODR_HIGH) /* I2C port 0 SDA */ -GPIO(I2C1_SCL, PIN(A, 6), GPIO_ODR_HIGH) /* I2C port 1 SCL */ -GPIO(I2C1_SDA, PIN(A, 7), GPIO_ODR_HIGH) /* I2C port 1 SDA */ -GPIO(I2C5_SCL, PIN(B, 6), GPIO_ODR_HIGH) /* I2C port 5 SCL */ -GPIO(I2C5_SDA, PIN(B, 7), GPIO_ODR_HIGH) /* I2C port 5 SDA */ - -ALTERNATE(PIN_MASK(A, 0x03), 1, MODULE_UART, 0) /* UART0 */ -ALTERNATE(PIN_MASK(A, 0x40), 3, MODULE_I2C, 0) /* I2C1 SCL */ -ALTERNATE(PIN_MASK(A, 0x80), 3, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C1 SDA */ -ALTERNATE(PIN_MASK(B, 0x04), 3, MODULE_I2C, 0) /* I2C0 SCL */ -ALTERNATE(PIN_MASK(B, 0x08), 3, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C0 SDA */ -ALTERNATE(PIN_MASK(B, 0x40), 3, MODULE_I2C, 0) /* I2C5 SCL */ -ALTERNATE(PIN_MASK(B, 0x80), 3, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C5 SDA */ -ALTERNATE(PIN_MASK(G, 0x30), 1, MODULE_UART, 0) /* UART2 */ -ALTERNATE(PIN_MASK(J, 0x40), 1, MODULE_PECI, 0) /* PECI Tx */ -ALTERNATE(PIN_MASK(J, 0x80), 0, MODULE_PECI, GPIO_ANALOG) /* PECI Rx */ -ALTERNATE(PIN_MASK(L, 0x3f), 15, MODULE_LPC, 0) /* LPC */ -ALTERNATE(PIN_MASK(M, 0x33), 15, MODULE_LPC, 0) /* LPC */ -#ifdef HEY_USE_BUILTIN_CLKRUN -ALTERNATE(PIN_MASK(M, 0x04), 15, MODULE_LPC, GPIO_OPEN_DRAIN) /* LPC */ -#endif - -ALTERNATE(PIN_MASK(N, 0x3c), 1, MODULE_PWM, 0) /* FAN0PWM 2&3 */ -ALTERNATE(PIN_MASK(N, 0x40), 1, MODULE_PWM, 0) /* FAN0PWM4 */ diff --git a/board/samus/panel.c b/board/samus/panel.c deleted file mode 100644 index b3fe6060aa..0000000000 --- a/board/samus/panel.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "lid_switch.h" -#include "timer.h" - -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) - -#define I2C_ADDR_BACKLIGHT_FLAGS (0x2C | I2C_FLAG_BIG_ENDIAN) -#define I2C_RETRIES 3 -#define I2C_RETRY_DELAY (5*MSEC) - -#define LP8555_REG_COMMAND 0x00 -#define LP8555_REG_COMMAND_ON 0x01 -#define LP8555_REG_CONFIG 0x10 -#define LP8555_REG_CONFIG_MODE_MASK 0x03 -#define LP8555_REG_CONFIG_MODE_PWM 0x00 -#define LP8555_REG_CURRENT 0x11 -#define LP8555_REG_CURRENT_MAXCURR_5MA 0x00 -#define LP8555_REG_CURRENT_MAXCURR_10MA 0x01 -#define LP8555_REG_CURRENT_MAXCURR_15MA 0x02 -#define LP8555_REG_CURRENT_MAXCURR_20MA 0x03 -#define LP8555_REG_CURRENT_MAXCURR_23MA 0x04 -#define LP8555_REG_CURRENT_MAXCURR_25MA 0x05 -#define LP8555_REG_CURRENT_MAXCURR_30MA 0x06 -#define LP8555_REG_CURRENT_MAXCURR_50MA 0x07 -#define LP8555_REG_STEP 0x15 -#define LP8555_REG_STEP_STEP_0MS (0 << 0) -#define LP8555_REG_STEP_STEP_8MS BIT(0) -#define LP8555_REG_STEP_STEP_16MS (2 << 0) -#define LP8555_REG_STEP_STEP_24MS (3 << 0) -#define LP8555_REG_STEP_STEP_28MS (4 << 0) -#define LP8555_REG_STEP_STEP_32MS (5 << 0) -#define LP8555_REG_STEP_STEP_100MS (6 << 0) -#define LP8555_REG_STEP_STEP_200MS (7 << 0) -#define LP8555_REG_STEP_PWM_IN_HYST_NONE (0 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_1LSB BIT(3) -#define LP8555_REG_STEP_PWM_IN_HYST_2LSB (2 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_4LSB (3 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_8LSB (4 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_16LSB (5 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_32LSB (6 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_64LSB (7 << 3) -#define LP8555_REG_STEP_SMOOTH_NONE (0 << 6) -#define LP8555_REG_STEP_SMOOTH_LIGHT BIT(6) -#define LP8555_REG_STEP_SMOOTH_MEDIUM (2 << 6) -#define LP8555_REG_STEP_SMOOTH_HEAVY (3 << 6) - -/* Read from lp8555 with automatic i2c retries */ -static int lp8555_read_with_retry(int reg, int *data) -{ - int i, rv; - - for (i = 0; i < I2C_RETRIES; i++) { - rv = i2c_read8(I2C_PORT_BACKLIGHT, - I2C_ADDR_BACKLIGHT_FLAGS, - reg, data); - if (rv == EC_SUCCESS) - return EC_SUCCESS; - usleep(I2C_RETRY_DELAY); - } - - CPRINTS("Backlight read fail: reg 0x%02x", reg); - return rv; -} - -/* Write to lp8555 with automatic i2c retries */ -static int lp8555_write_with_retry(int reg, int data) -{ - int i, rv; - - for (i = 0; i < I2C_RETRIES; i++) { - rv = i2c_write8(I2C_PORT_BACKLIGHT, - I2C_ADDR_BACKLIGHT_FLAGS, - reg, data); - if (rv == EC_SUCCESS) - return EC_SUCCESS; - usleep(I2C_RETRY_DELAY); - } - - CPRINTS("Backlight write fail: reg 0x%02x data %d", reg, data); - return rv; -} - -/** - * Setup backlight controller and turn it on. - */ -static void lp8555_enable_pwm_mode(void) -{ - int reg; - int rv; - - /* - * If not in S0, then PCH backlight enable will not be on, and if - * lid is closed EC backlight enable will not be on. Since these - * two signals are AND'ed together, no point in trying to talk to - * the lp8555 if either one of them is not true. - */ - if (!chipset_in_state(CHIPSET_STATE_ON) || !lid_is_open()) - return; - - /* Enable PWM mode. */ - rv = lp8555_read_with_retry(LP8555_REG_CONFIG, ®); - if (rv != EC_SUCCESS) - return; - reg &= ~LP8555_REG_CONFIG_MODE_MASK; - reg |= LP8555_REG_CONFIG_MODE_PWM; - rv = lp8555_write_with_retry(LP8555_REG_CONFIG, reg); - if (rv != EC_SUCCESS) - return; - - /* Set max LED current to 23mA. */ - rv = lp8555_write_with_retry(LP8555_REG_CURRENT, - LP8555_REG_CURRENT_MAXCURR_23MA); - if (rv != EC_SUCCESS) - return; - - /* Set the rate of brightness change. */ - rv = lp8555_write_with_retry(LP8555_REG_STEP, - LP8555_REG_STEP_STEP_200MS | - LP8555_REG_STEP_PWM_IN_HYST_8LSB | - LP8555_REG_STEP_SMOOTH_HEAVY); - if (rv != EC_SUCCESS) - return; - - /* Power on. */ - rv = lp8555_read_with_retry(LP8555_REG_COMMAND, ®); - if (rv != EC_SUCCESS) - return; - reg |= LP8555_REG_COMMAND_ON; - rv = lp8555_write_with_retry(LP8555_REG_COMMAND, reg); -} -DECLARE_DEFERRED(lp8555_enable_pwm_mode); - -/** - * Host command to toggle backlight. - */ -static enum ec_status -switch_command_enable_backlight(struct host_cmd_handler_args *args) -{ - const struct ec_params_switch_enable_backlight *p = args->params; - - gpio_set_level(GPIO_ENABLE_BACKLIGHT, p->enabled); - - if (p->enabled) - lp8555_enable_pwm_mode(); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SWITCH_ENABLE_BKLIGHT, - switch_command_enable_backlight, - EC_VER_MASK(0)); - -void backlight_interrupt(enum gpio_signal signal) -{ - /* - * PCH indicates it is turning on backlight so we should - * attempt to put the backlight controller into PWM mode. - */ - hook_call_deferred(&lp8555_enable_pwm_mode_data, 0); -} - -/** - * Update backlight state. - */ -static void update_backlight(void) -{ - /* - * Enable backlight if lid is open; this is AND'd with the request from - * the AP in hardware. - */ - gpio_set_level(GPIO_ENABLE_BACKLIGHT, lid_is_open()); - if (lid_is_open()) - hook_call_deferred(&lp8555_enable_pwm_mode_data, 0); -} -DECLARE_HOOK(HOOK_LID_CHANGE, update_backlight, HOOK_PRIO_DEFAULT); - -/** - * Initialize backlight module. - */ -static void backlight_init(void) -{ - gpio_enable_interrupt(GPIO_PCH_BL_EN); - gpio_set_level(GPIO_ENABLE_BACKLIGHT, lid_is_open()); -} -DECLARE_HOOK(HOOK_INIT, backlight_init, HOOK_PRIO_DEFAULT); diff --git a/board/samus/power_sequence.c b/board/samus/power_sequence.c deleted file mode 100644 index f6033055c4..0000000000 --- a/board/samus/power_sequence.c +++ /dev/null @@ -1,563 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* X86 chipset power control module for Chrome EC */ - -#include "battery.h" -#include "charge_state.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "extpower.h" -#include "i2c.h" -#include "lb_common.h" -#include "gpio.h" -#include "hooks.h" -#include "lid_switch.h" -#include "power.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "wireless.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) - -/* Input state flags */ -#define IN_PGOOD_PP1050 POWER_SIGNAL_MASK(X86_PGOOD_PP1050) -#define IN_PGOOD_PP1200 POWER_SIGNAL_MASK(X86_PGOOD_PP1200) -#define IN_PGOOD_PP1800 POWER_SIGNAL_MASK(X86_PGOOD_PP1800) -#define IN_PGOOD_VCORE POWER_SIGNAL_MASK(X86_PGOOD_VCORE) - -#define IN_PCH_SLP_S0_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_S0_DEASSERTED) -#define IN_PCH_SLP_S3_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_S3_DEASSERTED) -#define IN_PCH_SLP_S5_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_S5_DEASSERTED) -#define IN_PCH_SLP_SUS_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_SUS_DEASSERTED) - - -/* All non-core power rails */ -#define IN_PGOOD_ALL_NONCORE (IN_PGOOD_PP1050) -/* All core power rails */ -#define IN_PGOOD_ALL_CORE (IN_PGOOD_VCORE) -/* Rails required for S3 */ -#define IN_PGOOD_S3 (IN_PGOOD_PP1200) -/* Rails required for S0 */ -#define IN_PGOOD_S0 (IN_PGOOD_ALL_NONCORE) -/* Rails used to detect if PP5000 is up. 1.8V PGOOD is not - * a reliable signal to use here with an internal pullup. */ -#define IN_PGOOD_PP5000 (IN_PGOOD_PP1050 | IN_PGOOD_PP1200) - - -/* All PM_SLP signals from PCH deasserted */ -#define IN_ALL_PM_SLP_DEASSERTED (IN_PCH_SLP_S3_DEASSERTED | \ - IN_PCH_SLP_S5_DEASSERTED | \ - IN_PCH_SLP_SUS_DEASSERTED) - -/* All inputs in the right state for S0 */ -#define IN_ALL_S0 (IN_PGOOD_ALL_NONCORE | IN_PGOOD_ALL_CORE | \ - IN_ALL_PM_SLP_DEASSERTED) - -static int throttle_cpu; /* Throttle CPU? */ -static uint32_t pp5000_in_g3; /* Turn PP5000 on in G3? */ - -void chipset_force_shutdown(enum chipset_shutdown_reason reason) -{ - CPRINTS("%s(%d)", __func__, reason); - report_ap_reset(reason); - - /* - * Force off. This condition will reset once the state machine - * transitions to G3. - */ - gpio_set_level(GPIO_PCH_DPWROK, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); -} - -static void chipset_force_g3(void) -{ - CPRINTS("Forcing G3"); - - gpio_disable_interrupt(GPIO_VCORE_PGOOD); - gpio_set_level(GPIO_PCH_PWROK, 0); - gpio_set_level(GPIO_SYS_PWROK, 0); - gpio_set_level(GPIO_PP1050_EN, 0); - gpio_set_level(GPIO_PP1200_EN, 0); - gpio_set_level(GPIO_PP1800_EN, 0); - gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 0); - gpio_set_level(GPIO_PP5000_USB_EN, 0); - /* Disable PP5000 if allowed */ - if (!pp5000_in_g3) - gpio_set_level(GPIO_PP5000_EN, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - gpio_set_level(GPIO_PCH_DPWROK, 0); - gpio_set_level(GPIO_PP3300_DSW_EN, 0); - wireless_set_state(WIRELESS_OFF); -} - -static void chipset_reset_rtc(void) -{ - /* - * Assert RTCRST# to the PCH long enough for it to latch the - * assertion and reset the internal RTC backed state. - */ - CPRINTS("Asserting RTCRST# to PCH"); - gpio_set_level(GPIO_PCH_RTCRST_L, 0); - udelay(100); - gpio_set_level(GPIO_PCH_RTCRST_L, 1); - udelay(10 * MSEC); -} - -void chipset_reset(enum chipset_reset_reason reason) -{ - CPRINTS("%s(%d)", __func__, reason); - report_ap_reset(reason); - - /* - * Send a RCIN# pulse to the PCH. This just causes it to - * assert INIT# to the CPU without dropping power or asserting - * PLTRST# to reset the rest of the system. - */ - - /* - * Pulse must be at least 16 PCI clocks long = 500 ns. - */ - gpio_set_level(GPIO_PCH_RCIN_L, 0); - udelay(10); - gpio_set_level(GPIO_PCH_RCIN_L, 1); -} - -void chipset_throttle_cpu(int throttle) -{ - if (chipset_in_state(CHIPSET_STATE_ON)) - gpio_set_level(GPIO_CPU_PROCHOT, throttle); -} - -enum power_state power_chipset_init(void) -{ - /* - * If we're switching between images without rebooting, see if the x86 - * is already powered on; if so, leave it there instead of cycling - * through G3. - */ - if (system_jumped_to_this_image()) { - if ((power_get_signals() & IN_ALL_S0) == IN_ALL_S0) { - /* Disable idle task deep sleep when in S0. */ - disable_sleep(SLEEP_MASK_AP_RUN); - CPRINTS("already in S0"); - return POWER_S0; - } else { - /* Force all signals to their G3 states */ - chipset_force_g3(); - } - } - - return POWER_G3; -} - -enum power_state power_handle_state(enum power_state state) -{ - struct batt_params batt; - - switch (state) { - case POWER_G3: - break; - - case POWER_S5: - - while ((power_get_signals() & IN_PCH_SLP_S5_DEASSERTED) == 0) { - if (task_wait_event(SECOND*4) == TASK_EVENT_TIMER) { - CPRINTS("timeout waiting for S5 exit"); - /* Put system in G3 and assert RTCRST# */ - chipset_force_g3(); - chipset_reset_rtc(); - /* Try to power back up after RTC reset */ - return POWER_G3S5; - } - } - return POWER_S5S3; /* Power up to next state */ - break; - - case POWER_S3: - /* Check for state transitions */ - if (!power_has_signals(IN_PGOOD_S3)) { - /* Required rail went away */ - chipset_force_shutdown(CHIPSET_SHUTDOWN_POWERFAIL); - return POWER_S3S5; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 1) { - /* Power up to next state */ - return POWER_S3S0; - } else if (gpio_get_level(GPIO_PCH_SLP_S5_L) == 0) { - /* Power down to next state */ - return POWER_S3S5; - } - break; - - case POWER_S0: - if (!power_has_signals(IN_PGOOD_S0)) { - /* Required rail went away */ - chipset_force_shutdown(CHIPSET_SHUTDOWN_POWERFAIL); - return POWER_S0S3; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 0) { - /* Power down to next state */ - return POWER_S0S3; - } - break; - - case POWER_G3S5: - /* Return to G3 if battery level is too low */ - if (charge_want_shutdown() || - charge_prevent_power_on(0)) { - CPRINTS("power-up inhibited"); - chipset_force_g3(); - return POWER_G3; - } - - /* Enable 3.3V DSW */ - gpio_set_level(GPIO_PP3300_DSW_EN, 1); - - /* - * Wait 10ms after +3VALW good, since that powers VccDSW and - * VccSUS. - */ - msleep(10); - - /* Enable PP5000 (5V) rail as 1.05V and 1.2V rails need 5V - * rail to regulate properly. */ - gpio_set_level(GPIO_PP5000_EN, 1); - - /* Wait for PP1050/PP1200 PGOOD to go LOW to - * indicate that PP5000 is stable */ - while ((power_get_signals() & IN_PGOOD_PP5000) != 0) { - if (task_wait_event(SECOND) == TASK_EVENT_TIMER) { - CPRINTS("timeout waiting for PP5000"); - chipset_force_g3(); - return POWER_G3; - } - } - - /* - * TODO(crosbug.com/p/31583): Temporary hack to allow booting - * without battery. If battery is not present here, then delay - * to give time for PD MCU to negotiate to 20V. - */ - battery_get_params(&batt); - if (batt.is_present != BP_YES && !system_is_locked()) { - CPRINTS("Attempting boot w/o battery, adding delay"); - msleep(500); - } - - /* Assert DPWROK */ - gpio_set_level(GPIO_PCH_DPWROK, 1); - - /* - * Wait for SLP_SUS before enabling 1.05V rail. - */ - if (power_wait_signals(IN_PCH_SLP_SUS_DEASSERTED)) { - CPRINTS("timeout waiting for SLP_SUS deassert"); - chipset_force_g3(); - return POWER_G3; - } - - /* Enable PP1050 rail. */ - gpio_set_level(GPIO_PP1050_EN, 1); - - /* Wait for 1.05V to come up and CPU to notice */ - if (power_wait_signals(IN_PGOOD_PP1050)) { - CPRINTS("timeout waiting for PP1050"); - chipset_force_g3(); - return POWER_G3; - } - - /* Add 10ms delay between SUSP_VR and RSMRST */ - msleep(10); - - /* Deassert RSMRST# */ - gpio_set_level(GPIO_PCH_RSMRST_L, 1); - - /* Wait 5ms for SUSCLK to stabilize */ - msleep(5); - - /* Call hook to indicate out of G3 state */ - hook_notify(HOOK_CHIPSET_PRE_INIT); - return POWER_S5; - - case POWER_S5S3: - /* Turn on power to RAM */ - gpio_set_level(GPIO_PP1800_EN, 1); - gpio_set_level(GPIO_PP1200_EN, 1); - if (power_wait_signals(IN_PGOOD_S3)) { - gpio_set_level(GPIO_PP1800_EN, 0); - gpio_set_level(GPIO_PP1200_EN, 0); - chipset_force_shutdown(CHIPSET_SHUTDOWN_WAIT); - return POWER_S5; - } - - /* - * Take lightbar out of reset, now that +5VALW is - * available and we won't leak +3VALW through the reset - * line. - */ - i2c_lock(I2C_PORT_LIGHTBAR, 1); - gpio_set_level(GPIO_LIGHTBAR_RESET_L, 1); - msleep(1); - lb_init(0); - msleep(100); - i2c_lock(I2C_PORT_LIGHTBAR, 0); - - /* - * Enable touchpad power so it can wake the system from - * suspend. - */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 1); - - /* Turn on USB power rail. */ - gpio_set_level(GPIO_PP5000_USB_EN, 1); - - /* Call hooks now that rails are up */ - hook_notify(HOOK_CHIPSET_STARTUP); - return POWER_S3; - - case POWER_S3S0: - /* Turn on 3.3V DSW gated rail for core regulator */ - gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 1); - - /* Wait 20ms before allowing VCCST_PGOOD to rise. */ - msleep(20); - - /* Enable wireless. */ - wireless_set_state(WIRELESS_ON); - - /* Make sure the touchscreen is on, too. */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 1); - - /* Wait for non-core power rails good */ - if (power_wait_signals(IN_PGOOD_S0)) { - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - wireless_set_state(WIRELESS_OFF); - gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 1); - chipset_force_shutdown(CHIPSET_SHUTDOWN_WAIT); - return POWER_S3; - } - - /* Call hooks now that rails are up */ - hook_notify(HOOK_CHIPSET_RESUME); - - /* - * Disable idle task deep sleep. This means that the low - * power idle task will not go into deep sleep while in S0. - */ - disable_sleep(SLEEP_MASK_AP_RUN); - - /* - * Throttle CPU if necessary. This should only be asserted - * when +VCCP is powered (it is by now). - */ - gpio_set_level(GPIO_CPU_PROCHOT, throttle_cpu); - - /* - * VCORE_PGOOD signal buffer is powered by PP1050_VCCST which - * is gated by SLP_S3 assertion. Now the signal is valid and - * can be enabled as an interrupt source. - */ - gpio_enable_interrupt(GPIO_VCORE_PGOOD); - - /* Set PCH_PWROK */ - gpio_set_level(GPIO_PCH_PWROK, 1); - - /* Wait for VCORE_PGOOD before enabling SYS_PWROK */ - if (power_wait_signals(IN_PGOOD_VCORE)) { - gpio_disable_interrupt(GPIO_VCORE_PGOOD); - hook_notify(HOOK_CHIPSET_SUSPEND); - enable_sleep(SLEEP_MASK_AP_RUN); - gpio_set_level(GPIO_PCH_PWROK, 0); - gpio_set_level(GPIO_CPU_PROCHOT, 0); - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 1); - wireless_set_state(WIRELESS_OFF); - chipset_force_shutdown(CHIPSET_SHUTDOWN_WAIT); - return POWER_S3; - } - - /* - * Wait a bit for all voltages to be good. PCIe devices need - * 99ms, but mini-PCIe devices only need 1ms. Intel recommends - * at least 5ms between ALL_SYS_PWRGD and SYS_PWROK. - */ - msleep(5); - - /* Set SYS_PWROK */ - gpio_set_level(GPIO_SYS_PWROK, 1); - return POWER_S0; - - case POWER_S0S3: - /* Call hooks before we remove power rails */ - hook_notify(HOOK_CHIPSET_SUSPEND); - - /* Clear PCH_PWROK */ - gpio_set_level(GPIO_SYS_PWROK, 0); - gpio_set_level(GPIO_PCH_PWROK, 0); - - /* Wait 40ns */ - udelay(1); - - /* Suspend wireless */ - wireless_set_state(WIRELESS_SUSPEND); - - /* - * Enable idle task deep sleep. Allow the low power idle task - * to go into deep sleep in S3 or lower. - */ - enable_sleep(SLEEP_MASK_AP_RUN); - - /* Put touchscreen in reset */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - - /* - * Deassert prochot since CPU is off and we're about to drop - * +VCCP. - */ - gpio_set_level(GPIO_CPU_PROCHOT, 0); - - /* Turn off DSW gated */ - gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 0); - - /* - * VCORE_PGOOD signal buffer is powered by PP1050_VCCST which - * is gated by SLP_S3 assertion. The signal is no longer - * valid and should be disabled as an interrupt source. - */ - gpio_disable_interrupt(GPIO_VCORE_PGOOD); - return POWER_S3; - - case POWER_S3S5: - /* Call hooks before we remove power rails */ - hook_notify(HOOK_CHIPSET_SHUTDOWN); - - /* Disable wireless */ - wireless_set_state(WIRELESS_OFF); - - /* Disable peripheral power */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0); - gpio_set_level(GPIO_PP5000_USB_EN, 0); - - /* Turn off power to RAM */ - gpio_set_level(GPIO_PP1800_EN, 0); - gpio_set_level(GPIO_PP1200_EN, 0); - - /* - * Put touchscreen and lightbar in reset, so we won't - * leak +3VALW through the reset line to chips powered - * by +5VALW. - * - * (Note that we're no longer powering down +5VALW due - * to crosbug.com/p/16600, but to minimize side effects - * of that change we'll still reset these components in - * S5.) - */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - gpio_set_level(GPIO_LIGHTBAR_RESET_L, 0); - - /* Call hooks after we remove power rails */ - hook_notify(HOOK_CHIPSET_SHUTDOWN_COMPLETE); - - return power_get_pause_in_s5() ? POWER_S5 : POWER_S5G3; - - case POWER_S5G3: - /* Deassert DPWROK */ - gpio_set_level(GPIO_PCH_DPWROK, 0); - - /* Assert RSMRST# */ - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - - /* Turn off power rails enabled in S5 */ - gpio_set_level(GPIO_PP1050_EN, 0); - - /* Check if we can disable PP5000 */ - if (!pp5000_in_g3) - gpio_set_level(GPIO_PP5000_EN, 0); - - /* Disable 3.3V DSW */ - gpio_set_level(GPIO_PP3300_DSW_EN, 0); - return POWER_G3; - } - - return state; -} - -/** - * Set PP5000 rail in G3. The mask represents the reason for - * turning on/off the PP5000 rail in G3, and enable either - * enables or disables that mask. If any bit is enabled, then - * the PP5000 rail will remain on. If all bits are cleared, - * the rail will turn off. - * - * @param mask Mask to modify - * @param enable Enable flag - */ -void set_pp5000_in_g3(int mask, int enable) -{ - if (enable) - deprecated_atomic_or(&pp5000_in_g3, mask); - else - deprecated_atomic_clear_bits(&pp5000_in_g3, mask); - - /* if we are in G3 now, then set the rail accordingly */ - if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) - gpio_set_level(GPIO_PP5000_EN, !!pp5000_in_g3); -} - -#ifdef CONFIG_LIGHTBAR_POWER_RAILS -/* Returns true if a change was made, NOT the new state */ -int lb_power(int enabled) -{ - int ret = 0; - int pp5000_en = gpio_get_level(GPIO_PP5000_EN); - - set_pp5000_in_g3(PP5000_IN_G3_LIGHTBAR, enabled); - - /* If the AP is on, we don't change the rails. */ - if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) - return ret; - - /* Check if PP5000 rail changed */ - if (gpio_get_level(GPIO_PP5000_EN) != pp5000_en) - ret = 1; - - /* - * When turning on, we have to wait for the rails to come up - * fully before we the lightbar ICs will respond. There's not - * a reliable PGOOD signal for that (I tried), so we just - * have to wait. These delays seem to work. - * - * Note, we should delay even if the PP5000 rail was already - * enabled because we can't be sure it's been enabled long - * enough for lightbar IC to respond. - * - * Also, the lightbar do not expect other i2c traffic while - * being power up. Put a lock on the i2c bus. - * see chrome-os-partner:45223. - */ - if (enabled) { - i2c_lock(I2C_PORT_LIGHTBAR, 1); - msleep(10); - } - - if (enabled != gpio_get_level(GPIO_LIGHTBAR_RESET_L)) { - ret = 1; - gpio_set_level(GPIO_LIGHTBAR_RESET_L, enabled); - msleep(1); - } - if (enabled) { - lb_init(0); - msleep(100); - i2c_lock(I2C_PORT_LIGHTBAR, 0); - } - - return ret; -} -#endif diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c deleted file mode 100644 index 0f9c8cfbfe..0000000000 --- a/board/samus_pd/board.c +++ /dev/null @@ -1,620 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -/* samus_pd board configuration */ - -#include "adc.h" -#include "adc_chip.h" -#include "battery.h" -#include "charge_manager.h" -#include "charge_ramp.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "pi3usb9281.h" -#include "power.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "registers.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "usb_charge.h" -#include "usb_descriptor.h" -#include "usb_pd.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) - -/* - * When battery is high, system may not be pulling full current. Also, when - * high AND input voltage is below boost bypass, then limit input current - * limit to HIGH_BATT_LIMIT_CURR_MA to reduce audible ringing. - */ -#define HIGH_BATT_THRESHOLD 90 -#define HIGH_BATT_LIMIT_BOOST_BYPASS_MV 11000 -#define HIGH_BATT_LIMIT_CURR_MA 2000 - -/* Chipset power state */ -static enum power_state ps; - -/* Battery state of charge */ -static int batt_soc; - -/* Default to 5V charging allowed for dead battery case */ -static enum pd_charge_state charge_state = PD_CHARGE_5V; - -/* PD MCU status and host event status for host command */ -static int32_t host_event_status_flags; -static int32_t pd_status_flags; - -static struct ec_response_pd_status pd_status; - -/* Desired input current limit */ -static int desired_charge_rate_ma = -1; - -/* PWM channels. Must be in the exact same order as in enum pwm_channel. */ -const struct pwm_t pwm_channels[] = { - {STM32_TIM(15), STM32_TIM_CH(2), 0}, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -struct mutex pericom_mux_lock; -struct pi3usb9281_config pi3usb9281_chips[] = { - { - .i2c_port = I2C_PORT_PERICOM, - .mux_gpio = GPIO_USB_C_BC12_SEL, - .mux_gpio_level = 0, - .mux_lock = &pericom_mux_lock, - }, - { - .i2c_port = I2C_PORT_PERICOM, - .mux_gpio = GPIO_USB_C_BC12_SEL, - .mux_gpio_level = 1, - .mux_lock = &pericom_mux_lock, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) == - CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT); - -static void pericom_port0_reenable_interrupts(void) -{ - CPRINTS("VBUS p0 %d", gpio_get_level(GPIO_USB_C0_VBUS_WAKE)); - pi3usb9281_enable_interrupts(0); -} -DECLARE_DEFERRED(pericom_port0_reenable_interrupts); - -static void pericom_port1_reenable_interrupts(void) -{ - CPRINTS("VBUS p1 %d", gpio_get_level(GPIO_USB_C1_VBUS_WAKE)); - pi3usb9281_enable_interrupts(1); -} -DECLARE_DEFERRED(pericom_port1_reenable_interrupts); - -void vbus0_evt(enum gpio_signal signal) -{ - usb_charger_vbus_change(0, gpio_get_level(signal)); - task_wake(TASK_ID_PD_C0); -} - -void vbus1_evt(enum gpio_signal signal) -{ - usb_charger_vbus_change(1, gpio_get_level(signal)); - task_wake(TASK_ID_PD_C1); -} - -void usb0_evt(enum gpio_signal signal) -{ - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); -} - -void usb1_evt(enum gpio_signal signal) -{ - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); -} - -static void chipset_s5_to_s3(void) -{ - ps = POWER_S3; - hook_notify(HOOK_CHIPSET_STARTUP); -} - -static void chipset_s3_to_s0(void) -{ - /* Disable deep sleep and restore charge override port */ - disable_sleep(SLEEP_MASK_AP_RUN); - ps = POWER_S0; - hook_notify(HOOK_CHIPSET_RESUME); -} - -static void chipset_s3_to_s5(void) -{ - ps = POWER_S5; - hook_notify(HOOK_CHIPSET_SHUTDOWN); - hook_notify(HOOK_CHIPSET_SHUTDOWN_COMPLETE); -} - -static void chipset_s0_to_s3(void) -{ - /* Enable deep sleep and store charge override port */ - enable_sleep(SLEEP_MASK_AP_RUN); - ps = POWER_S3; - hook_notify(HOOK_CHIPSET_SUSPEND); -} - -static void pch_evt_deferred(void) -{ - /* Determine new chipset state, trigger corresponding transition */ - switch (ps) { - case POWER_S5: - if (gpio_get_level(GPIO_PCH_SLP_S5_L)) - chipset_s5_to_s3(); - if (gpio_get_level(GPIO_PCH_SLP_S3_L)) - chipset_s3_to_s0(); - break; - case POWER_S3: - if (gpio_get_level(GPIO_PCH_SLP_S3_L)) - chipset_s3_to_s0(); - else if (!gpio_get_level(GPIO_PCH_SLP_S5_L)) - chipset_s3_to_s5(); - break; - case POWER_S0: - if (!gpio_get_level(GPIO_PCH_SLP_S3_L)) - chipset_s0_to_s3(); - if (!gpio_get_level(GPIO_PCH_SLP_S5_L)) - chipset_s3_to_s5(); - break; - default: - break; - } -} -DECLARE_DEFERRED(pch_evt_deferred); - -void pch_evt(enum gpio_signal signal) -{ - hook_call_deferred(&pch_evt_deferred_data, 0); -} - -void board_config_pre_init(void) -{ - /* enable SYSCFG clock */ - STM32_RCC_APB2ENR |= BIT(0); - /* - * the DMA mapping is : - * Chan 2 : TIM1_CH1 (C0 RX) - * Chan 3 : SPI1_TX (C1 TX) - * Chan 4 : USART1_TX - * Chan 5 : USART1_RX - * Chan 6 : TIM3_CH1 (C1 RX) - * Chan 7 : SPI2_TX (C0 TX) - */ - - /* - * Remap USART1 RX/TX DMA to match uart driver. Remap SPI2 RX/TX and - * TIM3_CH1 for unique DMA channels. - */ - STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10) | BIT(24) | BIT(30); -} - -#include "gpio_list.h" - -/* Initialize board. */ -static void board_init(void) -{ - int slp_s5 = gpio_get_level(GPIO_PCH_SLP_S5_L); - int slp_s3 = gpio_get_level(GPIO_PCH_SLP_S3_L); - - /* - * Enable CC lines after all GPIO have been initialized. Note, it is - * important that this is enabled after the CC_ODL lines are set low - * to specify device mode. - */ - gpio_set_level(GPIO_USB_C_CC_EN, 1); - - /* Enable interrupts on VBUS transitions. */ - gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE); - gpio_enable_interrupt(GPIO_USB_C1_VBUS_WAKE); - - /* Enable pericom BC1.2 interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); - - /* Determine initial chipset state */ - if (slp_s5 && slp_s3) { - disable_sleep(SLEEP_MASK_AP_RUN); - hook_notify(HOOK_CHIPSET_RESUME); - ps = POWER_S0; - } else if (slp_s5 && !slp_s3) { - enable_sleep(SLEEP_MASK_AP_RUN); - hook_notify(HOOK_CHIPSET_STARTUP); - ps = POWER_S3; - } else { - enable_sleep(SLEEP_MASK_AP_RUN); - hook_notify(HOOK_CHIPSET_SHUTDOWN); - hook_notify(HOOK_CHIPSET_SHUTDOWN_COMPLETE); - ps = POWER_S5; - } - - /* Enable interrupts on PCH state change */ - gpio_enable_interrupt(GPIO_PCH_SLP_S3_L); - gpio_enable_interrupt(GPIO_PCH_SLP_S5_L); - - /* Initialize active charge port to none */ - pd_status.active_charge_port = CHARGE_PORT_NONE; - - /* Set PD MCU system status bits */ - if (system_jumped_to_this_image()) - pd_status_flags |= PD_STATUS_JUMPED_TO_IMAGE; - if (system_is_in_rw()) - pd_status_flags |= PD_STATUS_IN_RW; - -#ifdef CONFIG_PWM - /* Enable ILIM PWM: initial duty cycle 0% = 500mA limit. */ - pwm_enable(PWM_CH_ILIM, 1); - pwm_set_duty(PWM_CH_ILIM, 0); -#endif -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -/* ADC channels */ -const struct adc_t adc_channels[] = { - /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_C0_CC1_PD] = {"C0_CC1_PD", 3300, 4096, 0, STM32_AIN(0)}, - [ADC_C1_CC1_PD] = {"C1_CC1_PD", 3300, 4096, 0, STM32_AIN(2)}, - [ADC_C0_CC2_PD] = {"C0_CC2_PD", 3300, 4096, 0, STM32_AIN(4)}, - [ADC_C1_CC2_PD] = {"C1_CC2_PD", 3300, 4096, 0, STM32_AIN(5)}, - - /* Vbus sensing. Converted to mV, full ADC is equivalent to 25.774V. */ - [ADC_VBUS] = {"VBUS", 25774, 4096, 0, STM32_AIN(11)}, -}; -BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, - {"slave", I2C_PORT_SLAVE, 100, - GPIO_SLAVE_I2C_SCL, GPIO_SLAVE_I2C_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -int board_get_battery_soc(void) -{ - return batt_soc; -} - -enum battery_present battery_is_present(void) -{ - if (batt_soc >= 0) - return BP_YES; - return BP_NOT_SURE; -} - -static void pd_send_ec_int(void) -{ - gpio_set_level(GPIO_EC_INT, 1); - - /* - * Delay long enough to guarantee EC see's the change. Slowest - * EC clock speed is 250kHz in deep sleep -> 4us, and add 1us - * for buffer. - */ - usleep(5); - - gpio_set_level(GPIO_EC_INT, 0); -} - -/** - * Set active charge port -- only one port can be active at a time. - * - * @param charge_port Charge port to enable. - * - * Returns EC_SUCCESS if charge port is accepted and made active, - * EC_ERROR_* otherwise. - */ -int board_set_active_charge_port(int charge_port) -{ - /* charge port is a realy physical port */ - int is_real_port = (charge_port >= 0 && - charge_port < CONFIG_USB_PD_PORT_MAX_COUNT); - /* check if we are source vbus on that port */ - if (is_real_port && usb_charger_port_is_sourcing_vbus(charge_port)) { - CPRINTS("Skip enable p%d", charge_port); - return EC_ERROR_INVAL; - } - - CPRINTS("New chg p%d", charge_port); - - /* - * If charging and the active charge port is changed, then disable - * charging to guarantee charge circuit starts up cleanly. - */ - if (pd_status.active_charge_port != CHARGE_PORT_NONE && - (charge_port == CHARGE_PORT_NONE || - charge_port != pd_status.active_charge_port)) { - gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 1); - gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 1); - charge_state = PD_CHARGE_NONE; - pd_status.active_charge_port = charge_port; - CPRINTS("Chg: None"); - return EC_SUCCESS; - } - - /* Save active charge port and enable charging if allowed */ - pd_status.active_charge_port = charge_port; - if (charge_state != PD_CHARGE_NONE) { - gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, !(charge_port == 0)); - gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, !(charge_port == 1)); - } - - return EC_SUCCESS; -} - -/** - * Return if max voltage charging is allowed. - */ -int pd_is_max_request_allowed(void) -{ - return charge_state == PD_CHARGE_MAX; -} - -/** - * Return if board is consuming full amount of input current - */ -int charge_is_consuming_full_input_current(void) -{ - return batt_soc >= 1 && batt_soc < HIGH_BATT_THRESHOLD; -} - -/* - * Number of VBUS samples to average when computing if VBUS is too low - * for the ramp stable state. - */ -#define VBUS_STABLE_SAMPLE_COUNT 4 - -/* VBUS too low threshold */ -#define VBUS_LOW_THRESHOLD_MV 4600 - -/** - * Return if VBUS is sagging too low - */ -int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) -{ - static int vbus[VBUS_STABLE_SAMPLE_COUNT]; - static int vbus_idx, vbus_samples_full; - int vbus_sum, i; - - /* - * If we are not allowing charging, it's because the EC saw - * ACOK go low, so we know VBUS is drooping too far. - */ - if (charge_state == PD_CHARGE_NONE) - return 1; - - /* If we are ramping, only look at one reading */ - if (ramp_state == CHG_RAMP_VBUS_RAMPING) { - /* Reset the VBUS array vars used for the stable state */ - vbus_idx = vbus_samples_full = 0; - return adc_read_channel(ADC_VBUS) < VBUS_LOW_THRESHOLD_MV; - } - - /* Fill VBUS array with ADC readings */ - vbus[vbus_idx] = adc_read_channel(ADC_VBUS); - vbus_idx = (vbus_idx == VBUS_STABLE_SAMPLE_COUNT-1) ? 0 : vbus_idx + 1; - if (vbus_idx == 0) - vbus_samples_full = 1; - - /* If VBUS array is not full yet, then return ok */ - if (!vbus_samples_full) - return 0; - - /* All VBUS samples are populated, take average */ - vbus_sum = 0; - for (i = 0; i < VBUS_STABLE_SAMPLE_COUNT; i++) - vbus_sum += vbus[i]; - - /* Return if average is lower than threshold */ - return vbus_sum < (VBUS_STABLE_SAMPLE_COUNT * VBUS_LOW_THRESHOLD_MV); -} - -static int board_update_charge_limit(int charge_ma) -{ -#ifdef CONFIG_PWM - int pwm_duty; -#endif - static int actual_charge_rate_ma = -1; - - desired_charge_rate_ma = charge_ma; - - if (batt_soc >= HIGH_BATT_THRESHOLD && - adc_read_channel(ADC_VBUS) < HIGH_BATT_LIMIT_BOOST_BYPASS_MV) - charge_ma = MIN(charge_ma, HIGH_BATT_LIMIT_CURR_MA); - - /* if current hasn't changed, don't do anything */ - if (charge_ma == actual_charge_rate_ma) - return 0; - - actual_charge_rate_ma = charge_ma; - -#ifdef CONFIG_PWM - pwm_duty = MA_TO_PWM(charge_ma); - if (pwm_duty < 0) - pwm_duty = 0; - else if (pwm_duty > 100) - pwm_duty = 100; - - pwm_set_duty(PWM_CH_ILIM, pwm_duty); -#endif - - pd_status.curr_lim_ma = charge_ma >= 500 ? - (charge_ma - 500) * 92 / 100 + 256 : 0; - - CPRINTS("New ilim %d", charge_ma); - return 1; -} - -/** - * Set the charge limit based upon desired maximum. - * - * @param port Port number. - * @param supplier Charge supplier type. - * @param charge_ma Desired charge limit (mA). - * @param charge_mv Negotiated charge voltage (mV). - */ -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* Update current limit and notify EC if it changed */ - if (board_update_charge_limit(charge_ma), charge_mv) - pd_send_ec_int(); -} - -static void board_update_battery_soc(int soc) -{ - if (batt_soc != soc) { - batt_soc = soc; - if (batt_soc >= CONFIG_CHARGE_MANAGER_BAT_PCT_SAFE_MODE_EXIT) - charge_manager_leave_safe_mode(); - board_update_charge_limit(desired_charge_rate_ma); - hook_notify(HOOK_BATTERY_SOC_CHANGE); - } -} - -/* Send host event up to AP */ -void pd_send_host_event(int mask) -{ - /* mask must be set */ - if (!mask) - return; - - deprecated_atomic_or(&(host_event_status_flags), mask); - deprecated_atomic_or(&(pd_status_flags), PD_STATUS_HOST_EVENT); - pd_send_ec_int(); -} - -int battery_is_cut_off(void) -{ - return 0; /* Always return NOT cut off */ -} - -/****************************************************************************/ -/* Console commands */ -static int command_ec_int(int argc, char **argv) -{ - pd_send_ec_int(); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(ecint, command_ec_int, - "", - "Toggle EC interrupt line"); - -static int command_pd_host_event(int argc, char **argv) -{ - int event_mask; - char *e; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - event_mask = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - - pd_send_host_event(event_mask); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(pdevent, command_pd_host_event, - "event_mask", - "Send PD host event"); - -/****************************************************************************/ -/* Host commands */ -static enum ec_status ec_status_host_cmd(struct host_cmd_handler_args *args) -{ - const struct ec_params_pd_status *p = args->params; - struct ec_response_pd_status *r = args->response; - - /* update battery soc */ - board_update_battery_soc(p->batt_soc); - - if (p->charge_state != charge_state) { - switch (p->charge_state) { - case PD_CHARGE_NONE: - /* - * No current allowed in, set new power request - * so that PD negotiates down to vSafe5V. - */ - charge_state = p->charge_state; - gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 1); - gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 1); - pd_set_new_power_request( - pd_status.active_charge_port); - /* - * Wake charge ramp task so that it will check - * board_is_vbus_too_low() and stop ramping up. - */ - task_wake(TASK_ID_CHG_RAMP); - CPRINTS("Chg: None"); - break; - case PD_CHARGE_5V: - /* Allow current on the active charge port */ - charge_state = p->charge_state; - gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, - !(pd_status.active_charge_port == 0)); - gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, - !(pd_status.active_charge_port == 1)); - CPRINTS("Chg: 5V"); - break; - case PD_CHARGE_MAX: - /* - * Allow negotiation above vSafe5V. Should only - * ever get this command when 5V charging is - * already allowed. - */ - if (charge_state == PD_CHARGE_5V) { - charge_state = p->charge_state; - pd_set_new_power_request( - pd_status.active_charge_port); - CPRINTS("Chg: Max"); - } - break; - default: - break; - } - } - - *r = pd_status; - r->status = pd_status_flags; - - /* Clear host event */ - deprecated_atomic_clear_bits(&(pd_status_flags), PD_STATUS_HOST_EVENT); - - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_PD_EXCHANGE_STATUS, ec_status_host_cmd, - EC_VER_MASK(EC_VER_PD_EXCHANGE_STATUS)); - -static enum ec_status -host_event_status_host_cmd(struct host_cmd_handler_args *args) -{ - struct ec_response_host_event_status *r = args->response; - - /* Clear host event bit to avoid sending more unnecessary events */ - deprecated_atomic_clear_bits(&(pd_status_flags), PD_STATUS_HOST_EVENT); - - /* Read and clear the host event status to return to AP */ - r->status = deprecated_atomic_read_clear(&(host_event_status_flags)); - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_PD_HOST_EVENT_STATUS, host_event_status_host_cmd, - EC_VER_MASK(0)); diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h deleted file mode 100644 index 9102d097ce..0000000000 --- a/board/samus_pd/board.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* samus_pd board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* 48 MHz SYSCLK clock frequency */ -#define CPU_CLOCK 48000000 - -/* the UART console is on USART1 (PA9/PA10) */ -#undef CONFIG_UART_CONSOLE -#define CONFIG_UART_CONSOLE 1 - -/* Optional features */ -#define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG -#define CONFIG_BATTERY_PRESENT_CUSTOM -#define CONFIG_BOARD_PRE_INIT -#define CONFIG_CHARGE_MANAGER -#define CONFIG_CHARGE_RAMP_SW -#undef CONFIG_CMD_ADC -#undef CONFIG_CMD_CHARGE_SUPPLIER_INFO -#undef CONFIG_CMD_CRASH -#undef CONFIG_CMD_HASH -#undef CONFIG_CMD_HCDEBUG -#undef CONFIG_CMD_I2C_SCAN -#undef CONFIG_CMD_I2C_XFER -/* Minimum ilim = 500 mA */ -#define CONFIG_CHARGER_INPUT_CURRENT PWM_0_MA -#undef CONFIG_CMD_GETTIME -#undef CONFIG_CMD_IDLE_STATS -#undef CONFIG_CMD_MD -#undef CONFIG_CMD_RW -#undef CONFIG_CMD_SHMEM -#undef CONFIG_CMD_TIMERINFO -#define CONFIG_COMMON_GPIO_SHORTNAMES -#undef CONFIG_CONSOLE_CMDHELP -#undef CONFIG_CONSOLE_HISTORY -#undef CONFIG_DEBUG_ASSERT -#define CONFIG_FORCE_CONSOLE_RESUME -#define CONFIG_HIBERNATE_WAKEUP_PINS (STM32_PWR_CSR_EWUP3|STM32_PWR_CSR_EWUP8) -#define CONFIG_HOSTCMD_ALIGNED -#undef CONFIG_HOSTCMD_EVENTS -#define CONFIG_HW_CRC -#define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_I2C_SLAVE -#undef CONFIG_LID_SWITCH -#define CONFIG_LOW_POWER_IDLE -#define CONFIG_LTO -#undef CONFIG_PWM -#define CONFIG_STM_HWTIMER32 -#undef CONFIG_TASK_PROFILING -#define CONFIG_USB_CHARGER -#define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV1 -#undef CONFIG_USB_PD_TCPMV1_DEBUG -#define CONFIG_USB_PD_ALT_MODE -#define CONFIG_USB_PD_ALT_MODE_DFP -#define CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED -#define CONFIG_USB_PD_COMM_LOCKED -#define CONFIG_USB_PD_CUSTOM_PDO -#define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_TRY_SRC -#define CONFIG_USB_PD_FLASH_ERASE_CHECK -#define CONFIG_USB_PD_INTERNAL_COMP -#undef CONFIG_USB_PD_LOGGING -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define CONFIG_USB_PD_TCPC -#define CONFIG_USB_PD_TCPM_STUB -#define CONFIG_USB_PD_VBUS_DETECT_GPIO -#define CONFIG_BC12_DETECT_PI3USB9281 -#define CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT 2 -#define CONFIG_USBC_SS_MUX_DFP_ONLY -#define CONFIG_USBC_SS_MUX -#define CONFIG_USBC_VCONN -#define CONFIG_USBC_VCONN_SWAP -#define CONFIG_VBOOT_HASH -#undef CONFIG_WATCHDOG_HELP - -/* Use PSTATE embedded in the RO image, not in its own erase block */ -#undef CONFIG_FLASH_PSTATE_BANK -#undef CONFIG_FW_PSTATE_SIZE -#define CONFIG_FW_PSTATE_SIZE 0 - -/* I2C ports configuration */ -#define I2C_PORT_MASTER 1 -#define I2C_PORT_SLAVE 0 -#define I2C_PORT_EC I2C_PORT_SLAVE -#define I2C_PORT_PERICOM I2C_PORT_MASTER - -/* slave address for host commands */ -#ifdef HAS_TASK_HOSTCMD -#define CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS CONFIG_USB_PD_I2C_SLAVE_ADDR_FLAGS -#endif - -#ifndef __ASSEMBLER__ - -/* Timer selection */ -#define TIM_CLOCK32 2 -#define TIM_ADC 3 - -#include "gpio_signal.h" - -/* ADC signal */ -enum adc_channel { - ADC_C0_CC1_PD = 0, - ADC_C1_CC1_PD, - ADC_C0_CC2_PD, - ADC_C1_CC2_PD, - ADC_VBUS, - /* Number of ADC channels */ - ADC_CH_COUNT -}; - -enum pwm_channel { - PWM_CH_ILIM = 0, - /* Number of PWM channels */ - PWM_CH_COUNT -}; - -/* Standard-current Rp */ -#define PD_SRC_VNC PD_SRC_DEF_VNC_MV -#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV - -/* - * delay to turn on the power supply max is ~16ms. - * delay to turn off the power supply max is about ~180ms. - */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ - -/* delay to turn on/off vconn */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - -/* Define typical operating power and max power */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 - -/* Charge current limit min / max, based on PWM duty cycle */ -#define PWM_0_MA 500 -#define PWM_100_MA 4000 - -/* Map current in milli-amps to PWM duty cycle percentage */ -#define MA_TO_PWM(curr) (((curr) - PWM_0_MA) * 100 / (PWM_100_MA - PWM_0_MA)) - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/samus_pd/build.mk b/board/samus_pd/build.mk deleted file mode 100644 index 1946fc303c..0000000000 --- a/board/samus_pd/build.mk +++ /dev/null @@ -1,17 +0,0 @@ -# -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build - -# the IC is STmicro STM32F072VBH6 -CHIP:=stm32 -CHIP_FAMILY:=stm32f0 -CHIP_VARIANT:=stm32f07x - -# Not enough SRAM: Disable all tests -test-list-y= - -board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_mux.o usb_pd_policy.o diff --git a/board/samus_pd/ec.tasklist b/board/samus_pd/ec.tasklist deleted file mode 100644 index 297661df0b..0000000000 --- a/board/samus_pd/ec.tasklist +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/** - * See CONFIG_TASK_LIST in config.h for details. - */ -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/samus_pd/gpio.inc b/board/samus_pd/gpio.inc deleted file mode 100644 index a22f15375f..0000000000 --- a/board/samus_pd/gpio.inc +++ /dev/null @@ -1,137 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -/* Interrupts */ -GPIO_INT(USB_C0_VBUS_WAKE, PIN(E, 6), GPIO_INT_BOTH, vbus0_evt) -GPIO_INT(USB_C1_VBUS_WAKE, PIN(F, 2), GPIO_INT_BOTH, vbus1_evt) -GPIO_INT(USB_C0_BC12_INT_L, PIN(B, 0), GPIO_INT_FALLING, usb0_evt) -GPIO_INT(USB_C1_BC12_INT_L, PIN(C, 11), GPIO_INT_FALLING, usb1_evt) -GPIO_INT(PCH_SLP_S0_L, PIN(C, 14), GPIO_INT_BOTH, pch_evt) -GPIO_INT(PCH_SLP_S3_L, PIN(C, 15), GPIO_INT_BOTH, pch_evt) -GPIO_INT(PCH_SLP_S5_L, PIN(D, 7), GPIO_INT_BOTH, pch_evt) -GPIO_INT(WP_L, PIN(D, 2), GPIO_INT_BOTH, switch_interrupt) - -/* PD RX/TX */ -GPIO(USB_C0_CC1_PD, PIN(A, 0), GPIO_ANALOG) -GPIO(USB_C0_REF, PIN(A, 1), GPIO_ANALOG) -GPIO(USB_C1_CC1_PD, PIN(A, 2), GPIO_ANALOG) -GPIO(USB_C0_CC2_PD, PIN(A, 4), GPIO_ANALOG) -GPIO(USB_C1_CC2_PD, PIN(A, 5), GPIO_ANALOG) -GPIO(USB_C0_REF_PD_ODL, PIN(A, 6), GPIO_ODR_LOW) - -GPIO(USB_C_CC_EN, PIN(C, 10), GPIO_OUT_LOW) -GPIO(USB_C1_CC_TX_EN, PIN(A, 15), GPIO_OUT_LOW) -GPIO(USB_C0_CC_TX_EN, PIN(B, 9), GPIO_OUT_LOW) -GPIO(USB_C1_CC1_TX_DATA, PIN(B, 4), GPIO_OUT_LOW) -GPIO(USB_C0_CC1_TX_DATA, PIN(B, 14), GPIO_OUT_LOW) -GPIO(USB_C1_CC2_TX_DATA, PIN(E, 14), GPIO_OUT_LOW) -GPIO(USB_C0_CC2_TX_DATA, PIN(D, 3), GPIO_OUT_LOW) - -#if 0 -/* Alternate functions */ -GPIO(USB_C1_TX_CLKOUT, PIN(B, 1), GPIO_OUT_LOW) -GPIO(USB_C0_TX_CLKOUT, PIN(E, 1), GPIO_OUT_LOW) -GPIO(USB_C1_TX_CLKIN, PIN(B, 3), GPIO_OUT_LOW) -GPIO(USB_C0_TX_CLKIN, PIN(B, 13), GPIO_OUT_LOW) -#endif - -/* Power and muxes control */ -GPIO(PPVAR_BOOSTIN_SENSE, PIN(C, 1), GPIO_ANALOG) -GPIO(PP3300_USB_PD_EN, PIN(A, 8), GPIO_OUT_HIGH) -GPIO(USB_C0_CHARGE_EN_L, PIN(D, 12), GPIO_OUT_LOW) -GPIO(USB_C1_CHARGE_EN_L, PIN(D, 13), GPIO_OUT_LOW) -GPIO(USB_C0_5V_EN, PIN(D, 14), GPIO_OUT_LOW) -GPIO(USB_C1_5V_EN, PIN(D, 15), GPIO_OUT_LOW) -GPIO(USB_C0_CC1_VCONN1_EN_L, PIN(D, 8), GPIO_OUT_HIGH) -GPIO(USB_C0_CC2_VCONN1_EN_L, PIN(D, 9), GPIO_OUT_HIGH) -GPIO(USB_C1_CC1_VCONN1_EN_L, PIN(D, 10), GPIO_OUT_HIGH) -GPIO(USB_C1_CC2_VCONN1_EN_L, PIN(D, 11), GPIO_OUT_HIGH) -GPIO(USB_C0_CC_1A5_EN, PIN(B, 12), GPIO_OUT_LOW) -GPIO(USB_C1_CC_1A5_EN, PIN(E, 12), GPIO_OUT_LOW) -GPIO(ILIM_ADJ_PWM, PIN(B, 15), GPIO_OUT_LOW) - -GPIO(USB_C0_CC1_ODL, PIN(B, 8), GPIO_ODR_LOW) -GPIO(USB_C0_CC2_ODL, PIN(E, 0), GPIO_ODR_LOW) -GPIO(USB_C1_CC1_ODL, PIN(F, 9), GPIO_ODR_LOW) -GPIO(USB_C1_CC2_ODL, PIN(F, 10), GPIO_ODR_LOW) - -GPIO(USB_C_BC12_SEL, PIN(C, 0), GPIO_OUT_LOW) -GPIO(USB_C0_SS1_EN_L, PIN(E, 2), GPIO_OUT_HIGH) -GPIO(USB_C0_SS2_EN_L, PIN(E, 3), GPIO_OUT_HIGH) -GPIO(USB_C1_SS1_EN_L, PIN(E, 9), GPIO_OUT_HIGH) -GPIO(USB_C1_SS2_EN_L, PIN(E, 10), GPIO_OUT_HIGH) -GPIO(USB_C0_SS1_DP_MODE, PIN(E, 4), GPIO_OUT_HIGH) -GPIO(USB_C0_SS2_DP_MODE, PIN(E, 5), GPIO_OUT_HIGH) -GPIO(USB_C1_SS1_DP_MODE, PIN(E, 11), GPIO_OUT_HIGH) -GPIO(USB_C1_SS2_DP_MODE, PIN(E, 13), GPIO_OUT_HIGH) -GPIO(USB_C0_DP_MODE_L, PIN(E, 8), GPIO_OUT_HIGH) -GPIO(USB_C1_DP_MODE_L, PIN(F, 6), GPIO_OUT_HIGH) -GPIO(USB_C0_DP_POLARITY, PIN(E, 7), GPIO_OUT_HIGH) -GPIO(USB_C1_DP_POLARITY, PIN(F, 3), GPIO_OUT_HIGH) -GPIO(USB_C0_DP_HPD, PIN(F, 0), GPIO_OUT_LOW) -GPIO(USB_C1_DP_HPD, PIN(F, 1), GPIO_OUT_LOW) - -#if 0 -/* Alternate functions */ -GPIO(USB_DM, PIN(A, 11), GPIO_ANALOG) -GPIO(USB_DP, PIN(A, 12), GPIO_ANALOG) -GPIO(UART_TX, PIN(A, 9), GPIO_OUT_LOW) -GPIO(UART_RX, PIN(A, 10), GPIO_OUT_LOW) -GPIO(TP64, PIN(A, 13), GPIO_ODR_HIGH) -GPIO(TP71, PIN(A, 14), GPIO_ODR_HIGH) -#endif - -/* - * I2C pins should be configured as inputs until I2C module is - * initialized. This will avoid driving the lines unintentionally. - */ -GPIO(SLAVE_I2C_SCL, PIN(B, 6), GPIO_INPUT) -GPIO(SLAVE_I2C_SDA, PIN(B, 7), GPIO_INPUT) -GPIO(MASTER_I2C_SCL, PIN(B, 10), GPIO_INPUT) -GPIO(MASTER_I2C_SDA, PIN(B, 11), GPIO_INPUT) - -/* Case closed debugging. */ -GPIO(EC_INT, PIN(B, 2), GPIO_OUT_LOW) -GPIO(EC_IN_RW, PIN(C, 12), GPIO_INPUT | GPIO_PULL_UP) -GPIO(EC_RST_L, PIN(C, 13), GPIO_OUT_HIGH) -GPIO(SPI_FLASH_CS_L, PIN(D, 0), GPIO_INPUT) -GPIO(SPI_FLASH_CSK, PIN(D, 1), GPIO_INPUT) -GPIO(SPI_FLASH_MOSI, PIN(C, 3), GPIO_INPUT) -GPIO(SPI_FLASH_MISO, PIN(C, 2), GPIO_INPUT) -GPIO(EC_JTAG_TCK, PIN(C, 6), GPIO_INPUT) -GPIO(EC_JTAG_TMS, PIN(C, 7), GPIO_INPUT) -GPIO(EC_JTAG_TDO, PIN(C, 8), GPIO_INPUT) -GPIO(EC_JTAG_TDI, PIN(C, 9), GPIO_INPUT) -GPIO(ENTERING_RW, PIN(B, 5), GPIO_OUT_LOW) -GPIO(PD_DISABLE_DEBUG, PIN(E, 15), GPIO_OUT_HIGH) -GPIO(PD_DEBUG_EN_L, PIN(D, 4), GPIO_INPUT | GPIO_PULL_UP) -GPIO(PD_SPI_PP3300_EN_L, PIN(A, 7), GPIO_OUT_HIGH) -GPIO(BST_DISABLE, PIN(A, 3), GPIO_OUT_LOW) - -#if 0 -/* Alternate functions */ -GPIO(EC_UART_TX, PIN(C, 4), GPIO_OUT_LOW) -GPIO(EC_UART_RX, PIN(C, 5), GPIO_INPUT) -GPIO(AP_UART_TX, PIN(D, 5), GPIO_OUT_LOW) -GPIO(AP_UART_RX, PIN(D, 6), GPIO_INPUT) -#endif - -ALTERNATE(PIN_MASK(B, 0x0008), 0, MODULE_USB_PD, 0) /* SPI1: SCK(PB3) */ -ALTERNATE(PIN_MASK(B, 0x2000), 0, MODULE_USB_PD, 0) /* SPI2: SCK(PB13) */ -ALTERNATE(PIN_MASK(B, 0x0002), 0, MODULE_USB_PD, 0) /* TIM14_CH1: PB1) */ -ALTERNATE(PIN_MASK(E, 0x0002), 0, MODULE_USB_PD, 0) /* TIM17_CH1: PE1) */ -ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, 0) /* USART1: PA9/PA10 */ -ALTERNATE(PIN_MASK(D, 0x0060), 0, MODULE_UART, 0) /* USART2: PD5/PD6 */ -ALTERNATE(PIN_MASK(C, 0x0030), 1, MODULE_UART, 0) /* USART3: PC4/PC5 */ -ALTERNATE(PIN_MASK(B, 0x0cc0), 1, MODULE_I2C, 0) /* I2C SLAVE:PB6/7 MASTER:PB10/11 */ - -#ifdef CONFIG_PWM -ALTERNATE(PIN_MASK(B, 0x8000), 1, MODULE_PWM, 0) /* ILIM_PWM: PB15 */ -#endif diff --git a/board/samus_pd/usb_mux.c b/board/samus_pd/usb_mux.c deleted file mode 100644 index 2213fc41e0..0000000000 --- a/board/samus_pd/usb_mux.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Samus PD-custom USB mux driver. */ - -#include "common.h" -#include "gpio.h" -#include "usb_mux.h" -#include "util.h" - -struct usb_port_mux { - enum gpio_signal ss1_en_l; - enum gpio_signal ss2_en_l; - enum gpio_signal dp_mode_l; - enum gpio_signal dp_polarity; - enum gpio_signal ss1_dp_mode; - enum gpio_signal ss2_dp_mode; -}; - -static const struct usb_port_mux mux_gpios[] = { - { - .ss1_en_l = GPIO_USB_C0_SS1_EN_L, - .ss2_en_l = GPIO_USB_C0_SS2_EN_L, - .dp_mode_l = GPIO_USB_C0_DP_MODE_L, - .dp_polarity = GPIO_USB_C0_DP_POLARITY, - .ss1_dp_mode = GPIO_USB_C0_SS1_DP_MODE, - .ss2_dp_mode = GPIO_USB_C0_SS2_DP_MODE, - }, - { - .ss1_en_l = GPIO_USB_C1_SS1_EN_L, - .ss2_en_l = GPIO_USB_C1_SS2_EN_L, - .dp_mode_l = GPIO_USB_C1_DP_MODE_L, - .dp_polarity = GPIO_USB_C1_DP_POLARITY, - .ss1_dp_mode = GPIO_USB_C1_SS1_DP_MODE, - .ss2_dp_mode = GPIO_USB_C1_SS2_DP_MODE, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(mux_gpios) == CONFIG_USB_PD_PORT_MAX_COUNT); - - -static int board_init_usb_mux(const struct usb_mux *me) -{ - return EC_SUCCESS; -} - -static int board_set_usb_mux(const struct usb_mux *me, mux_state_t mux_state) -{ - const struct usb_port_mux *usb_mux = mux_gpios + me->usb_port; - int polarity = mux_state & USB_PD_MUX_POLARITY_INVERTED; - - /* reset everything */ - gpio_set_level(usb_mux->ss1_en_l, 1); - gpio_set_level(usb_mux->ss2_en_l, 1); - gpio_set_level(usb_mux->dp_mode_l, 1); - gpio_set_level(usb_mux->dp_polarity, 1); - gpio_set_level(usb_mux->ss1_dp_mode, 1); - gpio_set_level(usb_mux->ss2_dp_mode, 1); - - if (!(mux_state & (USB_PD_MUX_USB_ENABLED | USB_PD_MUX_DP_ENABLED))) - /* everything is already disabled, we can return */ - return EC_SUCCESS; - - if (mux_state & USB_PD_MUX_USB_ENABLED) - /* USB 3.0 uses 2 superspeed lanes */ - gpio_set_level(polarity ? usb_mux->ss2_dp_mode : - usb_mux->ss1_dp_mode, 0); - - if (mux_state & USB_PD_MUX_DP_ENABLED) { - /* DP uses available superspeed lanes (x2 or x4) */ - gpio_set_level(usb_mux->dp_polarity, polarity); - gpio_set_level(usb_mux->dp_mode_l, 0); - } - - /* switch on superspeed lanes */ - gpio_set_level(usb_mux->ss1_en_l, 0); - gpio_set_level(usb_mux->ss2_en_l, 0); - - return EC_SUCCESS; -} - -static int board_get_usb_mux(const struct usb_mux *me, mux_state_t *mux_state) -{ - const struct usb_port_mux *usb_mux = mux_gpios + me->usb_port; - - *mux_state = 0; - - if (!gpio_get_level(usb_mux->ss1_dp_mode) || - !gpio_get_level(usb_mux->ss2_dp_mode)) - *mux_state |= USB_PD_MUX_USB_ENABLED; - - if (!gpio_get_level(usb_mux->dp_mode_l)) - *mux_state |= USB_PD_MUX_DP_ENABLED; - - if (gpio_get_level(usb_mux->dp_polarity)) - *mux_state |= USB_PD_MUX_POLARITY_INVERTED; - - return EC_SUCCESS; -} - -const struct usb_mux_driver board_custom_usb_mux_driver = { - .init = board_init_usb_mux, - .set = board_set_usb_mux, - .get = board_get_usb_mux, -}; - -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .driver = &board_custom_usb_mux_driver, - }, - { - .usb_port = 1, - .driver = &board_custom_usb_mux_driver, - }, -}; diff --git a/board/samus_pd/usb_pd_config.h b/board/samus_pd/usb_pd_config.h deleted file mode 100644 index c81b0bf113..0000000000 --- a/board/samus_pd/usb_pd_config.h +++ /dev/null @@ -1,278 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "adc.h" -#include "chip/stm32/registers.h" -#include "gpio.h" -#include "usb_mux.h" - -/* USB Power delivery board configuration */ - -#ifndef __CROS_EC_USB_PD_CONFIG_H -#define __CROS_EC_USB_PD_CONFIG_H - -/* Timer selection for baseband PD communication */ -#define TIM_CLOCK_PD_TX_C0 17 -#define TIM_CLOCK_PD_RX_C0 1 -#define TIM_CLOCK_PD_TX_C1 14 -#define TIM_CLOCK_PD_RX_C1 3 - -#define TIM_CLOCK_PD_TX(p) ((p) ? TIM_CLOCK_PD_TX_C1 : TIM_CLOCK_PD_TX_C0) -#define TIM_CLOCK_PD_RX(p) ((p) ? TIM_CLOCK_PD_RX_C1 : TIM_CLOCK_PD_RX_C0) - -/* Timer channel */ -#define TIM_RX_CCR_C0 1 -#define TIM_RX_CCR_C1 1 -#define TIM_TX_CCR_C0 1 -#define TIM_TX_CCR_C1 1 - -/* RX timer capture/compare register */ -#define TIM_CCR_C0 (&STM32_TIM_CCRx(TIM_CLOCK_PD_RX_C0, TIM_RX_CCR_C0)) -#define TIM_CCR_C1 (&STM32_TIM_CCRx(TIM_CLOCK_PD_RX_C1, TIM_RX_CCR_C1)) -#define TIM_RX_CCR_REG(p) ((p) ? TIM_CCR_C1 : TIM_CCR_C0) - -/* TX and RX timer register */ -#define TIM_REG_TX_C0 (STM32_TIM_BASE(TIM_CLOCK_PD_TX_C0)) -#define TIM_REG_RX_C0 (STM32_TIM_BASE(TIM_CLOCK_PD_RX_C0)) -#define TIM_REG_TX_C1 (STM32_TIM_BASE(TIM_CLOCK_PD_TX_C1)) -#define TIM_REG_RX_C1 (STM32_TIM_BASE(TIM_CLOCK_PD_RX_C1)) -#define TIM_REG_TX(p) ((p) ? TIM_REG_TX_C1 : TIM_REG_TX_C0) -#define TIM_REG_RX(p) ((p) ? TIM_REG_RX_C1 : TIM_REG_RX_C0) - -/* use the hardware accelerator for CRC */ -#define CONFIG_HW_CRC - -/* TX uses SPI1 on PB3-4 for port C1, SPI2 on PB 13-14 for port C0 */ -#define SPI_REGS(p) ((p) ? STM32_SPI1_REGS : STM32_SPI2_REGS) -static inline void spi_enable_clock(int port) -{ - if (port == 0) - STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; - else - STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI1; -} - -/* DMA for transmit uses DMA CH7 for C0 and DMA_CH3 for C1 */ -#define DMAC_SPI_TX(p) ((p) ? STM32_DMAC_CH3 : STM32_DMAC_CH7) - -/* RX uses COMP1 and TIM1 CH1 on port C0 and COMP2 and TIM3_CH1 for port C1*/ -#define CMP1OUTSEL STM32_COMP_CMP1OUTSEL_TIM1_IC1 -#define CMP2OUTSEL STM32_COMP_CMP2OUTSEL_TIM3_IC1 - -#define TIM_TX_CCR_IDX(p) ((p) ? TIM_TX_CCR_C1 : TIM_TX_CCR_C0) -#define TIM_RX_CCR_IDX(p) ((p) ? TIM_RX_CCR_C1 : TIM_RX_CCR_C0) -#define TIM_CCR_CS 1 -#define EXTI_COMP_MASK(p) ((p) ? BIT(22) : BIT(21)) -#define IRQ_COMP STM32_IRQ_COMP -/* triggers packet detection on comparator falling edge */ -#define EXTI_XTSR STM32_EXTI_FTSR - -/* DMA for receive uses DMA_CH2 for C0 and DMA_CH6 for C1 */ -#define DMAC_TIM_RX(p) ((p) ? STM32_DMAC_CH6 : STM32_DMAC_CH2) - -/* the pins used for communication need to be hi-speed */ -static inline void pd_set_pins_speed(int port) -{ - if (port == 0) { - /* 40 MHz pin speed on SPI PB13/14 */ - STM32_GPIO_OSPEEDR(GPIO_B) |= 0x3C000000; - /* 40 MHz pin speed on TIM17_CH1 (PE1) */ - STM32_GPIO_OSPEEDR(GPIO_E) |= 0x0000000C; - } else { - /* 40 MHz pin speed on SPI PB3/4 */ - STM32_GPIO_OSPEEDR(GPIO_B) |= 0x000003C0; - /* 40 MHz pin speed on TIM14_CH1 (PB1) */ - STM32_GPIO_OSPEEDR(GPIO_B) |= 0x0000000C; - } -} - -/* Reset SPI peripheral used for TX */ -static inline void pd_tx_spi_reset(int port) -{ - if (port == 0) { - /* Reset SPI2 */ - STM32_RCC_APB1RSTR |= BIT(14); - STM32_RCC_APB1RSTR &= ~BIT(14); - } else { - /* Reset SPI1 */ - STM32_RCC_APB2RSTR |= BIT(12); - STM32_RCC_APB2RSTR &= ~BIT(12); - } -} - -/* Drive the CC line from the TX block */ -static inline void pd_tx_enable(int port, int polarity) -{ - if (port == 0) { - /* put SPI function on TX pin */ - if (polarity) /* PD3 is SPI2 MISO */ - gpio_set_alternate_function(GPIO_D, 0x0008, 1); - else /* PB14 is SPI2 MISO */ - gpio_set_alternate_function(GPIO_B, 0x4000, 0); - - /* set the low level reference */ - gpio_set_level(GPIO_USB_C0_CC_TX_EN, 1); - } else { - /* put SPI function on TX pin */ - if (polarity) /* PE14 is SPI1 MISO */ - gpio_set_alternate_function(GPIO_E, 0x4000, 1); - else /* PB4 is SPI1 MISO */ - gpio_set_alternate_function(GPIO_B, 0x0010, 0); - - /* set the low level reference */ - gpio_set_level(GPIO_USB_C1_CC_TX_EN, 1); - } -} - -/* Put the TX driver in Hi-Z state */ -static inline void pd_tx_disable(int port, int polarity) -{ - if (port == 0) { - /* output low on SPI TX to disable the FET */ - if (polarity) /* PD3 is SPI2 MISO */ - STM32_GPIO_MODER(GPIO_D) = (STM32_GPIO_MODER(GPIO_D) - & ~(3 << (2*3))) - | (1 << (2*3)); - else /* PB14 is SPI2 MISO */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - & ~(3 << (2*14))) - | (1 << (2*14)); - - /* put the low level reference in Hi-Z */ - gpio_set_level(GPIO_USB_C0_CC_TX_EN, 0); - } else { - /* output low on SPI TX to disable the FET */ - if (polarity) /* PE14 is SPI1 MISO */ - STM32_GPIO_MODER(GPIO_E) = (STM32_GPIO_MODER(GPIO_E) - & ~(3 << (2*14))) - | (1 << (2*14)); - else /* PB4 is SPI1 MISO */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - & ~(3 << (2*4))) - | (1 << (2*4)); - - /* put the low level reference in Hi-Z */ - gpio_set_level(GPIO_USB_C1_CC_TX_EN, 0); - } -} - -/* we know the plug polarity, do the right configuration */ -static inline void pd_select_polarity(int port, int polarity) -{ - uint32_t val = STM32_COMP_CSR; - - /* Use window mode so that COMP1 and COMP2 share non-inverting input */ - val |= STM32_COMP_CMP1EN | STM32_COMP_CMP2EN | STM32_COMP_WNDWEN; - - if (port == 0) { - /* use the right comparator inverted input for COMP1 */ - STM32_COMP_CSR = (val & ~STM32_COMP_CMP1INSEL_MASK) | - (polarity ? STM32_COMP_CMP1INSEL_INM4 - : STM32_COMP_CMP1INSEL_INM6); - } else { - /* use the right comparator inverted input for COMP2 */ - STM32_COMP_CSR = (val & ~STM32_COMP_CMP2INSEL_MASK) | - (polarity ? STM32_COMP_CMP2INSEL_INM5 - : STM32_COMP_CMP2INSEL_INM6); - } -} - -/* Initialize pins used for TX and put them in Hi-Z */ -static inline void pd_tx_init(void) -{ - gpio_config_module(MODULE_USB_PD, 1); -} - -static inline void pd_set_host_mode(int port, int enable) -{ - if (port == 0) { - if (enable) { - /* We never charging in power source mode */ - gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 1); - /* High-Z is used for host mode. */ - gpio_set_level(GPIO_USB_C0_CC1_ODL, 1); - gpio_set_level(GPIO_USB_C0_CC2_ODL, 1); - } else { - /* Kill VBUS power supply */ - gpio_set_level(GPIO_USB_C0_5V_EN, 0); - /* Pull low for device mode. */ - gpio_set_level(GPIO_USB_C0_CC1_ODL, 0); - gpio_set_level(GPIO_USB_C0_CC2_ODL, 0); - /* Let charge_manager decide to enable the port */ - } - } else { - if (enable) { - /* We never charging in power source mode */ - gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 1); - /* High-Z is used for host mode. */ - gpio_set_level(GPIO_USB_C1_CC1_ODL, 1); - gpio_set_level(GPIO_USB_C1_CC2_ODL, 1); - } else { - /* Kill VBUS power supply */ - gpio_set_level(GPIO_USB_C1_5V_EN, 0); - /* Pull low for device mode. */ - gpio_set_level(GPIO_USB_C1_CC1_ODL, 0); - gpio_set_level(GPIO_USB_C1_CC2_ODL, 0); - /* Let charge_manager decide to enable the port */ - } - } -} - -/** - * Initialize various GPIOs and interfaces to safe state at start of pd_task. - * - * These include: - * VBUS, charge path based on power role. - * Physical layer CC transmit. - * VCONNs disabled. - * - * @param port USB-C port number - * @param power_role Power role of device - */ -static inline void pd_config_init(int port, uint8_t power_role) -{ - /* - * Set CC pull resistors, and charge_en and vbus_en GPIOs to match - * the initial role. - */ - pd_set_host_mode(port, power_role); - - /* Initialize TX pins and put them in Hi-Z */ - pd_tx_init(); - - /* Reset mux ... for NONE polarity doesn't matter */ - usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_DISCONNECT, 0); - - if (port == 0) { - gpio_set_level(GPIO_USB_C0_CC1_VCONN1_EN_L, 1); - gpio_set_level(GPIO_USB_C0_CC2_VCONN1_EN_L, 1); - gpio_set_level(GPIO_USB_C0_DP_HPD, 0); - } else { - gpio_set_level(GPIO_USB_C1_CC1_VCONN1_EN_L, 1); - gpio_set_level(GPIO_USB_C1_CC2_VCONN1_EN_L, 1); - gpio_set_level(GPIO_USB_C1_DP_HPD, 0); - } -} - -static inline int pd_adc_read(int port, int cc) -{ - if (port == 0) - return adc_read_channel(cc ? ADC_C0_CC2_PD : ADC_C0_CC1_PD); - else - return adc_read_channel(cc ? ADC_C1_CC2_PD : ADC_C1_CC1_PD); -} - -static inline void pd_set_vconn(int port, int polarity, int enable) -{ - /* Set VCONN on the opposite CC line from the polarity */ - if (port == 0) - gpio_set_level(polarity ? GPIO_USB_C0_CC1_VCONN1_EN_L : - GPIO_USB_C0_CC2_VCONN1_EN_L, !enable); - else - gpio_set_level(polarity ? GPIO_USB_C1_CC1_VCONN1_EN_L : - GPIO_USB_C1_CC2_VCONN1_EN_L, !enable); -} - -#endif /* __CROS_EC_USB_PD_CONFIG_H */ diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c deleted file mode 100644 index 9eed4f77b5..0000000000 --- a/board/samus_pd/usb_pd_policy.c +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "atomic.h" -#include "charge_manager.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "usb_mux.h" -#include "usb_pd.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -/* Define typical operating power and max power */ -#define OPERATING_POWER_MW 15000 -#define MAX_POWER_MW 60000 -#define MAX_CURRENT_MA 3000 - -/* - * Do not request any voltage within this deadband region, where - * we're not sure whether or not the boost or the bypass will be on. - */ -#define INPUT_VOLTAGE_DEADBAND_MIN 9700 -#define INPUT_VOLTAGE_DEADBAND_MAX 11999 - -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP) - -const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 900, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); - -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), - PDO_BATT(4750, 21000, 15000), - PDO_VAR(4750, 21000, 3000), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); - -__override int pd_is_valid_input_voltage(int mv) -{ - /* Allow any voltage not in the boost bypass deadband */ - return (mv < INPUT_VOLTAGE_DEADBAND_MIN) || - (mv > INPUT_VOLTAGE_DEADBAND_MAX); -} - -int pd_set_power_supply_ready(int port) -{ - /* provide VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN, 1); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; /* we are ready */ -} - -void pd_power_supply_reset(int port) -{ - /* Kill VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN, 0); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -int pd_snk_is_vbus_provided(int port) -{ - return gpio_get_level(port ? GPIO_USB_C1_VBUS_WAKE : - GPIO_USB_C0_VBUS_WAKE); -} - -int pd_check_vconn_swap(int port) -{ - /* in S5, do not allow vconn swap since pp5000 rail is off */ - return gpio_get_level(GPIO_PCH_SLP_S5_L); -} - -/* ----------------- Vendor Defined Messages ------------------ */ -#define PORT_TO_HPD(port) ((port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD) -__override void svdm_dp_post_config(int port) -{ - dp_flags[port] |= DP_FLAGS_DP_ON; - if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) - return; - - gpio_set_level(PORT_TO_HPD(port), 1); -} - -static void hpd0_irq_deferred(void) -{ - gpio_set_level(GPIO_USB_C0_DP_HPD, 1); -} - -static void hpd1_irq_deferred(void) -{ - gpio_set_level(GPIO_USB_C1_DP_HPD, 1); -} - -DECLARE_DEFERRED(hpd0_irq_deferred); -DECLARE_DEFERRED(hpd1_irq_deferred); -#define PORT_TO_HPD_IRQ_DEFERRED(port) ((port) ? \ - &hpd1_irq_deferred_data : \ - &hpd0_irq_deferred_data) - -__override int svdm_dp_attention(int port, uint32_t *payload) -{ - int cur_lvl; - int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); - int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); - enum gpio_signal hpd = PORT_TO_HPD(port); - cur_lvl = gpio_get_level(hpd); - - dp_status[port] = payload[1]; - - /* Its initial DP status message prior to config */ - if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { - if (lvl) - dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; - return 1; - } - - if (irq & cur_lvl) { - gpio_set_level(hpd, 0); - hook_call_deferred(PORT_TO_HPD_IRQ_DEFERRED(port), - HPD_DSTREAM_DEBOUNCE_IRQ); - } else if (irq & !cur_lvl) { - CPRINTF("ERR:HPD:IRQ&LOW\n"); - return 0; /* nak */ - } else { - gpio_set_level(hpd, lvl); - } - /* ack */ - return 1; -} - -__override void svdm_exit_dp_mode(int port) -{ - svdm_safe_dp_mode(port); - gpio_set_level(PORT_TO_HPD(port), 0); -} diff --git a/board/sasuke/battery.c b/board/sasuke/battery.c new file mode 100644 index 0000000000..c06f88ddfd --- /dev/null +++ b/board/sasuke/battery.c @@ -0,0 +1,171 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" +#include "hooks.h" +#include "usb_pd.h" +#include "util.h" + +#define CHARGING_CURRENT_REDUCE 4000 +/* + * Battery info for all sasuke battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + * + * Battery FET Status in Manufacture Access : bit15 & bit14 + * b'00 - dfet : on / cfet : on + * b'01 - dfet : on / cfet : off + * b'10 - dfet : off / cfet : off + * b'11 - dfet : off / cfet : on + * The value b'10 is disconnect_val, so we can use b'01 for cfet_off_val + */ +const struct board_batt_params board_battery_info[] = { + /* SDI Battery Information */ + [BATTERY_SDI] = { + .fuel_gauge = { + .manuf_name = "SDI", + .device_name = "4432D53", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0xc000, + .disconnect_val = 0x8000, + .cfet_mask = 0xc000, + .cfet_off_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 8760, + .voltage_normal = 7720, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, + /* SWD(Sunwoda) Battery Information */ + [BATTERY_SWD] = { + .fuel_gauge = { + .manuf_name = "SWD", + .device_name = "4432W53", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0xc000, + .disconnect_val = 0x8000, + .cfet_mask = 0xc000, + .cfet_off_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 8760, + .voltage_normal = 7720, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SDI; + +int charger_profile_override(struct charge_state_data *curr) +{ + int current; + int voltage; + + current = curr->requested_current; + voltage = curr->requested_voltage; + + voltage -= 100; + if (current > CHARGING_CURRENT_REDUCE) + current -= (current / 10); + + curr->requested_voltage = MIN(curr->requested_voltage, voltage); + curr->requested_current = MIN(curr->requested_current, current); + + return 0; +} + +/* Customs options controllable by host command. */ +#define PARAM_FASTCHARGE (CS_PARAM_CUSTOM_PROFILE_MIN + 0) + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +/* Lower our input voltage to 5V in S0iX when battery is full. */ +#define PD_VOLTAGE_WHEN_FULL 5000 +static void reduce_input_voltage_when_full(void) +{ + static int saved_input_voltage = -1; + int max_pd_voltage_mv = pd_get_max_voltage(); + int port; + + if (charge_get_percent() == 100 && + chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + if (max_pd_voltage_mv != PD_VOLTAGE_WHEN_FULL) { + saved_input_voltage = max_pd_voltage_mv; + max_pd_voltage_mv = PD_VOLTAGE_WHEN_FULL; + } + } else if (saved_input_voltage != -1) { + if (max_pd_voltage_mv == PD_VOLTAGE_WHEN_FULL) + max_pd_voltage_mv = saved_input_voltage; + saved_input_voltage = -1; + } + + if (pd_get_max_voltage() != max_pd_voltage_mv) { + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, max_pd_voltage_mv); + } +} +DECLARE_HOOK(HOOK_SECOND, reduce_input_voltage_when_full, HOOK_PRIO_DEFAULT); diff --git a/board/sasuke/board.c b/board/sasuke/board.c new file mode 100644 index 0000000000..502fa60bd5 --- /dev/null +++ b/board/sasuke/board.c @@ -0,0 +1,772 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "cros_board_info.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/nb7v904m.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/pi3usb3x532.h" +#include "driver/usb_mux/ps8743.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_8042.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "stdbool.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "temp_sensor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void sub_usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} +static void sub_hdmi_hpd_interrupt(enum gpio_signal s) +{ + int hdmi_hpd_odl = gpio_get_level(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + + gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, !hdmi_hpd_odl); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SUB_ANALOG] = { + .name = "SUB_ANALOG", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +static int board_id = -1; +static int mux_c1 = SSFC_USB_SS_MUX_DEFAULT; + +extern const struct usb_mux_chain usbc0_retimer; +extern const struct usb_mux usbmux_ps8743; + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + check_c0_line(); + + if (get_cbi_fw_config_db() == DB_1A_HDMI) { + /* Disable i2c on HDMI pins */ + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, + 0); + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, + 0); + + /* Set HDMI and sub-rail enables to output */ + gpio_set_flags(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, + chipset_in_state(CHIPSET_STATE_ON) ? + GPIO_ODR_LOW : + GPIO_ODR_HIGH); + gpio_set_flags(GPIO_SUB_C1_INT_EN_RAILS_ODL, GPIO_ODR_HIGH); + + /* Select HDMI option */ + gpio_set_level(GPIO_HDMI_SEL_L, 0); + + /* Enable interrupt for passing through HPD */ + gpio_enable_interrupt(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); + } else { + /* Set SDA as an input */ + gpio_set_flags(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, GPIO_INPUT); + + /* Enable C1 interrupts */ + gpio_enable_interrupt(GPIO_SUB_C1_INT_EN_RAILS_ODL); + check_c1_line(); + } + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + if (board_id == -1) { + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS) { + board_id = val; + if (board_id == 2) { + nb7v904m_lpm_disable = 1; + nb7v904m_set_aux_ch_switch( + usbc0_retimer.mux, + NB7V904M_AUX_CH_FLIPPED); + } + } + } + + mux_c1 = get_cbi_ssfc_usb_ss_mux(); + + if (mux_c1 == SSFC_USB_SS_MUX_PS8743) { + usb_muxes[1].mux = &usbmux_ps8743; + usb_muxes[1].next = NULL; + } +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Enable HDMI any time the SoC is on */ +static void hdmi_enable(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + gpio_set_level(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, hdmi_enable, HOOK_PRIO_DEFAULT); + +static void hdmi_disable(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + gpio_set_level(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, hdmi_disable, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(1, true); + raa489000_hibernate(0, false); +} + +/* USB-A charging control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, +}; + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +static void set_5v_gpio(int level) +{ + gpio_set_level(GPIO_EN_PP5000, level); +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC, or send enable signal to HDMI + * DB. + */ + set_5v_gpio(!!enable); + + if (get_cbi_fw_config_db() == DB_1A_HDMI) { + gpio_set_level(GPIO_SUB_C1_INT_EN_RAILS_ODL, !enable); + } else { + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", + enable ? "en" : "dis"); + } +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; + else + return CONFIG_USB_PD_PORT_MAX_COUNT; +} + +__override uint8_t board_get_charger_chip_count(void) +{ + if (get_cbi_fw_config_db() == DB_1A_HDMI) + return CHARGER_NUM - 1; + else + return CHARGER_NUM; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, + + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +static int board_nb7v904m_mux_set_c0(const struct usb_mux *me, + mux_state_t mux_state); +static int board_nb7v904m_mux_set(const struct usb_mux *me, + mux_state_t mux_state); +static int ps8743_tune_mux(const struct usb_mux *me); + +const struct usb_mux_chain usbc0_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = NB7V904M_I2C_ADDR0, + .driver = &nb7v904m_usb_redriver_drv, + .board_set = &board_nb7v904m_mux_set_c0, + }, +}; +const struct usb_mux_chain usbc1_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = NB7V904M_I2C_ADDR0, + .driver = &nb7v904m_usb_redriver_drv, + .board_set = &board_nb7v904m_mux_set, + }, +}; + +const struct usb_mux usbmux_ps8743 = { + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8743_I2C_ADDR0_FLAG, + .driver = &ps8743_usb_mux_driver, + .board_init = &ps8743_tune_mux, +}; + +struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + .next = &usbc0_retimer, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + .next = &usbc1_retimer, + } +}; +/* USB Mux C1 : board_init of PS8743 */ +static int ps8743_tune_mux(const struct usb_mux *me) +{ + ps8743_tune_usb_eq(me, PS8743_USB_EQ_TX_3_6_DB, + PS8743_USB_EQ_RX_16_0_DB); + + return EC_SUCCESS; +} + +/* USB Mux C0 */ +static int board_nb7v904m_mux_set_c0(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + int flipped = !!(mux_state & USB_PD_MUX_POLARITY_INVERTED); + + if (board_id == -1) { + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS) + board_id = val; + if (board_id == 2) + nb7v904m_lpm_disable = 1; + } + + if (mux_state & USB_PD_MUX_USB_ENABLED) { + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* USB with DP */ + if (flipped) { + rv |= nb7v904m_tune_usb_set_eq( + me, NB7V904M_CH_A_EQ_10_DB, + NB7V904M_CH_B_EQ_0_DB, + NB7V904M_CH_C_EQ_2_DB, + NB7V904M_CH_D_EQ_2_DB); + rv |= nb7v904m_tune_usb_flat_gain( + me, NB7V904M_CH_A_GAIN_0_DB, + NB7V904M_CH_B_GAIN_1P5_DB, + NB7V904M_CH_C_GAIN_0_DB, + NB7V904M_CH_D_GAIN_0_DB); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_C, + NB7V904M_LOSS_PROFILE_C); + } else { + rv |= nb7v904m_tune_usb_set_eq( + me, NB7V904M_CH_A_EQ_2_DB, + NB7V904M_CH_B_EQ_2_DB, + NB7V904M_CH_C_EQ_0_DB, + NB7V904M_CH_D_EQ_10_DB); + rv |= nb7v904m_tune_usb_flat_gain( + me, NB7V904M_CH_A_GAIN_0_DB, + NB7V904M_CH_B_GAIN_0_DB, + NB7V904M_CH_C_GAIN_1P5_DB, + NB7V904M_CH_D_GAIN_0_DB); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_C, + NB7V904M_LOSS_PROFILE_C, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A); + } + } else { + /* USB only */ + if (board_id == 2) + rv |= nb7v904m_set_aux_ch_switch( + me, NB7V904M_AUX_CH_FLIPPED); + + rv |= nb7v904m_tune_usb_set_eq(me, + NB7V904M_CH_A_EQ_10_DB, + NB7V904M_CH_B_EQ_0_DB, + NB7V904M_CH_C_EQ_0_DB, + NB7V904M_CH_D_EQ_10_DB); + rv |= nb7v904m_tune_usb_flat_gain( + me, NB7V904M_CH_A_GAIN_0_DB, + NB7V904M_CH_B_GAIN_1P5_DB, + NB7V904M_CH_C_GAIN_1P5_DB, + NB7V904M_CH_D_GAIN_0_DB); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A); + } + + } else if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* 4 lanes DP */ + rv |= nb7v904m_tune_usb_set_eq(me, NB7V904M_CH_A_EQ_2_DB, + NB7V904M_CH_B_EQ_2_DB, + NB7V904M_CH_C_EQ_2_DB, + NB7V904M_CH_D_EQ_2_DB); + rv |= nb7v904m_tune_usb_flat_gain(me, NB7V904M_CH_A_GAIN_0_DB, + NB7V904M_CH_B_GAIN_0_DB, + NB7V904M_CH_C_GAIN_0_DB, + NB7V904M_CH_D_GAIN_0_DB); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_C, NB7V904M_LOSS_PROFILE_C, + NB7V904M_LOSS_PROFILE_C, NB7V904M_LOSS_PROFILE_C); + } + + return rv; +} + +/* USB Mux */ +static int board_nb7v904m_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + int flipped = !!(mux_state & USB_PD_MUX_POLARITY_INVERTED); + + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* USB with DP */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + if (flipped) { + rv |= nb7v904m_tune_usb_set_eq( + me, NB7V904M_CH_A_EQ_10_DB, + NB7V904M_CH_ALL_SKIP_EQ, + NB7V904M_CH_ALL_SKIP_EQ, + NB7V904M_CH_D_EQ_4_DB); + rv |= nb7v904m_tune_usb_flat_gain( + me, NB7V904M_CH_ALL_SKIP_GAIN, + NB7V904M_CH_B_GAIN_3P5_DB, + NB7V904M_CH_C_GAIN_0_DB, + NB7V904M_CH_ALL_SKIP_GAIN); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_D, + NB7V904M_LOSS_PROFILE_D); + } else { + rv |= nb7v904m_tune_usb_set_eq( + me, NB7V904M_CH_A_EQ_4_DB, + NB7V904M_CH_ALL_SKIP_EQ, + NB7V904M_CH_ALL_SKIP_EQ, + NB7V904M_CH_D_EQ_10_DB); + rv |= nb7v904m_tune_usb_flat_gain( + me, NB7V904M_CH_ALL_SKIP_GAIN, + NB7V904M_CH_B_GAIN_0_DB, + NB7V904M_CH_C_GAIN_3P5_DB, + NB7V904M_CH_ALL_SKIP_GAIN); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_D, + NB7V904M_LOSS_PROFILE_D, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A); + } + } else { + /* USB only */ + rv |= nb7v904m_tune_usb_set_eq(me, + NB7V904M_CH_A_EQ_10_DB, + NB7V904M_CH_ALL_SKIP_EQ, + NB7V904M_CH_ALL_SKIP_EQ, + NB7V904M_CH_D_EQ_10_DB); + rv |= nb7v904m_tune_usb_flat_gain( + me, NB7V904M_CH_ALL_SKIP_GAIN, + NB7V904M_CH_B_GAIN_3P5_DB, + NB7V904M_CH_C_GAIN_3P5_DB, + NB7V904M_CH_ALL_SKIP_GAIN); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A, + NB7V904M_LOSS_PROFILE_A); + } + + } else if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* 4 lanes DP */ + rv |= nb7v904m_tune_usb_set_eq(me, NB7V904M_CH_A_EQ_4_DB, + NB7V904M_CH_ALL_SKIP_EQ, + NB7V904M_CH_ALL_SKIP_EQ, + NB7V904M_CH_D_EQ_4_DB); + rv |= nb7v904m_tune_usb_flat_gain(me, NB7V904M_CH_ALL_SKIP_GAIN, + NB7V904M_CH_B_GAIN_0_DB, + NB7V904M_CH_C_GAIN_0_DB, + NB7V904M_CH_ALL_SKIP_GAIN); + rv |= nb7v904m_set_loss_profile_match( + me, NB7V904M_LOSS_PROFILE_D, NB7V904M_LOSS_PROFILE_D, + NB7V904M_LOSS_PROFILE_D, NB7V904M_LOSS_PROFILE_D); + } + + return rv; +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + if (board_get_usb_pd_port_count() > 1 && + !gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + /* TCPCI spec Rev 1.0 says to ignore bits 14:12. */ + if (!(tcpc_config[1].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +static const struct ec_response_keybd_config keybd1 = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad and no screenlock key */ +}; +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + /* + * Future boards should use fw_config if needed. + */ + + return &keybd1; +} diff --git a/board/sasuke/board.h b/board/sasuke/board.h new file mode 100644 index 0000000000..f43c287d8b --- /dev/null +++ b/board/sasuke/board.h @@ -0,0 +1,171 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_DEDEDE_EC_NPCX796FC +#include "baseboard.h" +#undef GPIO_VOLUME_UP_L +#undef GPIO_VOLUME_DOWN_L +#undef CONFIG_VOLUME_BUTTONS + +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_CMD_CHARGER_DUMP + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 +#define CONFIG_OCPC +#define CONFIG_CHARGER_PROFILE_OVERRIDE +#define CONFIG_CHARGE_RAMP_HW +#undef CONFIG_CHARGER_SINGLE_CHIP + +#define CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS + +/* + * GPIO for C1 interrupts, for baseboard use + * + * Note this line might already have its pull up disabled for HDMI DBs, but + * it should be fine to set again before z-state. + */ +#define GPIO_USB_C1_INT_ODL GPIO_SUB_C1_INT_EN_RAILS_ODL + +/* Keyboard */ + +/* LED */ +#define CONFIG_LED_COMMON +#define CONFIG_LED_ONOFF_STATES +#define GPIO_BAT_LED_RED_L GPIO_LED_R_ODL +#define GPIO_BAT_LED_GREEN_L GPIO_LED_G_ODL +#define GPIO_PWR_LED_BLUE_L GPIO_LED_B_ODL + +/* PWM */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 +#define CONFIG_USBC_RETIMER_NB7V904M +#define CONFIG_USB_MUX_RUNTIME_CONFIG +#define CONFIG_USB_MUX_PS8743 + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_RAA489000 +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +#define CONFIG_USB_PD_COMM_LOCKED + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +#undef PD_POWER_SUPPLY_TURN_ON_DELAY +#undef PD_POWER_SUPPLY_TURN_OFF_DELAY +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +/* 20% margin added for these timings */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 13080 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 16080 /* us */ +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +#define CONFIG_USBC_VCONN_SWAP_DELAY_US 787 /* us */ + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#undef CONFIG_USB_PORT_POWER_SMART_PORT_COUNT +#define CONFIG_USB_PORT_POWER_SMART_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_SMART +#define CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY +#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_CDP +#define CONFIG_USB_PORT_POWER_SMART_INVERTED +#define GPIO_USB1_ILIM_SEL GPIO_EN_USB_A0_5V_SUB + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +/* TODO(b:147440290): Need to handle multiple charger ICs */ +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ + +/* + * I2C pin names for baseboard + * + * Note: these lines will be set as i2c on start-up, but this should be + * okay since they're ODL. + */ +#define GPIO_EC_I2C_SUB_USB_C1_SCL GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL +#define GPIO_EC_I2C_SUB_USB_C1_SDA GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL + +#define CONFIG_MATH_UTIL + +/* + * There is ccd connection issue on board id = 2. + * NB7V904M is needed to be active to resolve this. + */ +#define CONFIG_NB7V904M_LPM_OVERRIDE + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_SDI, + BATTERY_SWD, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/sasuke/build.mk b/board/sasuke/build.mk new file mode 100644 index 0000000000..1531d1f3ae --- /dev/null +++ b/board/sasuke/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=dedede + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/sasuke/cbi_ssfc.c b/board/sasuke/cbi_ssfc.c new file mode 100644 index 0000000000..4f726ce6a3 --- /dev/null +++ b/board/sasuke/cbi_ssfc.c @@ -0,0 +1,41 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} + +enum ec_ssfc_usb_ss_mux get_cbi_ssfc_usb_ss_mux(void) +{ + return (enum ec_ssfc_usb_ss_mux)cached_ssfc.usb_ss_mux; +} diff --git a/board/sasuke/cbi_ssfc.h b/board/sasuke/cbi_ssfc.h new file mode 100644 index 0000000000..7cf6e954a1 --- /dev/null +++ b/board/sasuke/cbi_ssfc.h @@ -0,0 +1,76 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +/* + * USB SuperSpeed Mux (Bits 6-8) + */ +enum ec_ssfc_usb_ss_mux { + SSFC_USB_SS_MUX_DEFAULT = 0, + SSFC_USB_SS_MUX_PS8743 = 1, + SSFC_USB_SS_MUX_PI3USBX532 = 2, +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t usb_ss_mux : 3; + uint32_t reserved_2 : 23; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +/** + * Get the USB SuperSpeed Mux type from SSFC_CONFIG + * + * @return the USB SuperSpeed Mux type + */ +enum ec_ssfc_usb_ss_mux get_cbi_ssfc_usb_ss_mux(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/sasuke/ec.tasklist b/board/sasuke/ec.tasklist new file mode 100644 index 0000000000..17d4f989b3 --- /dev/null +++ b/board/sasuke/ec.tasklist @@ -0,0 +1,24 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/sasuke/gpio.inc b/board/sasuke/gpio.inc new file mode 100644 index 0000000000..46069c35eb --- /dev/null +++ b/board/sasuke/gpio.inc @@ -0,0 +1,142 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) +GPIO_INT(SUB_C1_INT_EN_RAILS_ODL, PIN(F, 5), GPIO_INT_FALLING | GPIO_PULL_UP, sub_usb_c1_interrupt) /* C1 interrupt OR 5V power en */ +GPIO_INT(EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, PIN(9, 1), GPIO_INT_BOTH, sub_hdmi_hpd_interrupt) /* C1 I2C SDA OR HDMI_HPD */ + +/* Button interrupts */ +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, PIN(9, 2), GPIO_INPUT) /* C1 I2C SCL OR HDMI en */ + +/* Extra Sub-board I/O pins */ +GPIO(EC_SUB_IO_1, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_SUB_IO_2, PIN(3, 4), GPIO_OUT_LOW) + +/* Misc Enables */ +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(IMVP9_PE, PIN(E, 0), GPIO_OUT_LOW) +GPIO(ECH1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(LED_R_ODL, PIN(C, 4), GPIO_OUT_HIGH) +GPIO(LED_G_ODL, PIN(C, 3), GPIO_OUT_HIGH) +GPIO(LED_B_ODL, PIN(C, 2), GPIO_OUT_HIGH) + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) + +GPIO(EN_USB_A0_5V_SUB, PIN(9, 7), GPIO_OUT_LOW) /* Don't limit USB-A charging by default - all ports */ +GPIO(EN_USB_A0_VBUS, PIN(4, 1), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(7, 2), GPIO_OUT_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) + +/* + * Waddledoo doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* ADC0-2 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x0C), 0, MODULE_I2C, 0) /* I2C7 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO00_NC, PIN(0, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO40_NC, PIN(4, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO50_NC, PIN(5, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO56_NC, PIN(5, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO60_NC, PIN(6, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO63_NC, PIN(6, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO73_NC, PIN(7, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO80_NC, PIN(8, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIO95_NC, PIN(9, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA2_NC, PIN(A, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_DOWN) diff --git a/board/sasuke/led.c b/board/sasuke/led.c new file mode 100644 index 0000000000..8ccce58d4c --- /dev/null +++ b/board/sasuke/led.c @@ -0,0 +1,134 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for sasuke + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1 = 1; + +__override const int led_charge_lvl_2 = 100; + +/* sasuke : There are 3 leds for AC, Battery and Power */ +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_BLUE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_power(enum ec_led_colors color) +{ + /* Don't set led if led_auto_control is disabled. */ + if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + return; + } + + if (color == EC_LED_COLOR_BLUE) { + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_ON_LVL); + } else { + /* LED_OFF and unsupported colors */ + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); + } +} + +__override void led_set_color_battery(enum ec_led_colors color) +{ + /* Don't set led if led_auto_control is disabled. */ + if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + return; + } + + /* Battery leds must be turn off when blue led is on + * because casta has 3-in-1 led. + */ + if (!gpio_get_level(GPIO_PWR_LED_BLUE_L)) { + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + return; + } + + switch (color) { + case EC_LED_COLOR_GREEN: + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_ON_LVL); /*green*/ + break; + case EC_LED_COLOR_RED: + gpio_set_level(GPIO_BAT_LED_RED_L, LED_ON_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_RED] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_GREEN_L, + !brightness[EC_LED_COLOR_GREEN]); + gpio_set_level(GPIO_BAT_LED_RED_L, + !brightness[EC_LED_COLOR_RED]); + } else if (led_id == EC_LED_ID_POWER_LED) { + gpio_set_level(GPIO_PWR_LED_BLUE_L, + !brightness[EC_LED_COLOR_BLUE]); + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); + } + + return EC_SUCCESS; +} diff --git a/board/sasuke/usb_pd_policy.c b/board/sasuke/usb_pd_policy.c new file mode 100644 index 0000000000..23166f7fca --- /dev/null +++ b/board/sasuke/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/sasuke/vif_override.xml b/board/sasuke/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/sasuke/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/sasukette/battery.c b/board/sasukette/battery.c new file mode 100644 index 0000000000..7a4670816e --- /dev/null +++ b/board/sasukette/battery.c @@ -0,0 +1,177 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_state.h" +#include "common.h" +#include "util.h" + +#define CHARGING_VOLTAGE_MV_SAFE 8400 +#define CHARGING_CURRENT_MA_SAFE 1500 + +/* + * Battery info for all sasukette battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* SDI Battery Information */ + [BATTERY_SDI] = { + .fuel_gauge = { + .manuf_name = "SDI", + .device_name = "4402D51", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x00, + .reg_mask = 0xc000, + .disconnect_val = 0x8000, + .cfet_mask = 0xc000, + .cfet_off_val = 0x2000, + } + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 50, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + } +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SDI; + +int charger_profile_override(struct charge_state_data *curr) +{ + int current; + int voltage; + /* battery temp in 0.1 deg C */ + int bat_temp_c; + const struct battery_info *batt_info; + + /* + * Keep track of battery temperature range: + * + * ZONE_0 ZONE_1 ZONE_2 ZONE_3 + * ---+------+--------+--------+------+--- Temperature (C) + * 0 5 12 45 50 + */ + enum { + TEMP_ZONE_0, /* 0 <= bat_temp_c <= 5 */ + TEMP_ZONE_1, /* 5 < bat_temp_c <= 12 */ + TEMP_ZONE_2, /* 12 < bat_temp_c <= 45 */ + TEMP_ZONE_3, /* 45 < bat_temp_c <= 50 */ + TEMP_ZONE_COUNT, + TEMP_OUT_OF_RANGE = TEMP_ZONE_COUNT + } temp_zone; + + /* + * Precharge must be executed when communication is failed on + * dead battery. + */ + if (!(curr->batt.flags & BATT_FLAG_RESPONSIVE)) + return 0; + + current = curr->requested_current; + voltage = curr->requested_voltage; + bat_temp_c = curr->batt.temperature - 2731; + batt_info = battery_get_info(); + + /* + * If the temperature reading is bad, assume the temperature + * is out of allowable range. + */ + if ((curr->batt.flags & BATT_FLAG_BAD_TEMPERATURE) || + (bat_temp_c < 0) || (bat_temp_c > 500)) + temp_zone = TEMP_OUT_OF_RANGE; + else if (bat_temp_c <= 50) + temp_zone = TEMP_ZONE_0; + else if (bat_temp_c <= 120) + temp_zone = TEMP_ZONE_1; + else if (bat_temp_c <= 450) + temp_zone = TEMP_ZONE_2; + else + temp_zone = TEMP_ZONE_3; + + switch (temp_zone) { + case TEMP_ZONE_0: + voltage = CHARGING_VOLTAGE_MV_SAFE; + current = CHARGING_CURRENT_MA_SAFE; + break; + + case TEMP_ZONE_1: + voltage += 100; + current = CHARGING_CURRENT_MA_SAFE; + break; + + case TEMP_ZONE_2: + voltage += 100; + break; + + case TEMP_ZONE_3: + voltage = CHARGING_VOLTAGE_MV_SAFE; + break; + + case TEMP_OUT_OF_RANGE: + /* Don't charge if outside of allowable temperature range */ + current = 0; + voltage = 0; + curr->batt.flags &= ~BATT_FLAG_WANT_CHARGE; + if (curr->state != ST_DISCHARGE) + curr->state = ST_IDLE; + break; + } + + if (voltage > batt_info->voltage_max) + voltage = batt_info->voltage_max; + + curr->requested_voltage = voltage; + curr->requested_current = MIN(curr->requested_current, current); + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/sasukette/board.c b/board/sasukette/board.c new file mode 100644 index 0000000000..7284d2d3c8 --- /dev/null +++ b/board/sasukette/board.c @@ -0,0 +1,350 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Sasukette configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "cros_board_info.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/tusb544.h" +#include "driver/tcpm/raa489000.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "math_util.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, +} }; + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, +} }; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + } +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, +} }; + +static uint32_t board_id; + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + /* Turn on 5V if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + /* modify AC DC prochot value */ + isl923x_set_ac_prochot(CHARGER_SOLO, 4096); + isl923x_set_dc_prochot(CHARGER_SOLO, 6000); + + cbi_get_board_version(&board_id); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_hibernate(void) +{ + /* + * Put all charger ICs present into low power mode before entering + * z-state. + * + * b:186335659: In order to solve the power consumption problem of + * hibernate,HW solution is adopted after board id 3 to solve the + * problem that AC cannot wake up hibernate mode. + */ + if (board_id > 2) + raa489000_hibernate(0, true); + else + raa489000_hibernate(0, false); +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +void board_reset_pd_mcu(void) +{ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + gpio_set_level(GPIO_EN_USB_A0_VBUS, !!enable); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_0; + } + } + + return status; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + raa489000_set_output_current(port, rp); +} + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Cpu", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); diff --git a/board/sasukette/board.h b/board/sasukette/board.h new file mode 100644 index 0000000000..848be6dffa --- /dev/null +++ b/board/sasukette/board.h @@ -0,0 +1,102 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Sasukette board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" +#undef GPIO_VOLUME_UP_L +#undef GPIO_VOLUME_DOWN_L +#undef CONFIG_VOLUME_BUTTONS +#undef CONFIG_I2C_DEBUG + +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_CMD_CHARGER_DUMP + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SINGLE_CHIP +#define CONFIG_CHARGER_PROFILE_OVERRIDE +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 + +/* LED */ +#define CONFIG_LED_COMMON +#define CONFIG_LED_ONOFF_STATES +#define GPIO_BAT_LED_RED_L GPIO_LED_R_ODL +#define GPIO_BAT_LED_GREEN_L GPIO_LED_G_ODL +#define GPIO_PWR_LED_BLUE_L GPIO_LED_B_ODL + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_TEMP_SENSOR_3, /* ADC15*/ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_SDI, + BATTERY_TYPE_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/sasukette/build.mk b/board/sasukette/build.mk new file mode 100644 index 0000000000..01b890bf29 --- /dev/null +++ b/board/sasukette/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/sasukette/cbi_ssfc.c b/board/sasukette/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/sasukette/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/sasukette/cbi_ssfc.h b/board/sasukette/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/sasukette/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/sasukette/ec.tasklist b/board/sasukette/ec.tasklist new file mode 100644 index 0000000000..d4a6c2cab3 --- /dev/null +++ b/board/sasukette/ec.tasklist @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) diff --git a/board/sasukette/gpio.inc b/board/sasukette/gpio.inc new file mode 100644 index 0000000000..de63737e75 --- /dev/null +++ b/board/sasukette/gpio.inc @@ -0,0 +1,139 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) /* Board rev 1, NC board rev 0 */ + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) +GPIO(LTE_EN, PIN(C, 3), GPIO_OUT_LOW) +GPIO(WWAN_CONFIG, PIN(A, 0), GPIO_INPUT |GPIO_PULL_UP) + +/* LED */ +GPIO(LED_R_ODL, PIN(A, 1), GPIO_ODR_HIGH) +GPIO(LED_G_ODL, PIN(A, 2), GPIO_ODR_HIGH) +GPIO(LED_B_ODL, PIN(A, 3), GPIO_ODR_HIGH) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOB5_NC, PIN(B, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC4_NC, PIN(C, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC6_NC, PIN(C, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE6_NC, PIN(E, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE7_NC, PIN(E, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF0_NC, PIN(F, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF1_NC, PIN(F, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF4_NC, PIN(F, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF6_NC, PIN(F, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF7_NC, PIN(F, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH2_NC, PIN(H, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOI6_NC, PIN(I, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOI7_NC, PIN(I, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ0_NC, PIN(J, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ1_NC, PIN(J, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ3_NC, PIN(J, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL0_NC, PIN(L, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL3_NC, PIN(L, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 EEPROM */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 BATTERY */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 USB_C0 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(2)), 0, MODULE_ADC, 0) /* ADC15:TEMP_SENSOR3 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ diff --git a/board/sasukette/led.c b/board/sasukette/led.c new file mode 100644 index 0000000000..af6d3635ac --- /dev/null +++ b/board/sasukette/led.c @@ -0,0 +1,135 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Sasukette + * + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1 = 1; + +__override const int led_charge_lvl_2 = 100; + +/* Sasukette : There are 3 leds for AC, Battery and Power */ +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, + 0.5 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_BLUE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_power(enum ec_led_colors color) +{ + /* Don't set led if led_auto_control is disabled. */ + if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + return; + } + + if (color == EC_LED_COLOR_BLUE) { + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_ON_LVL); + } else { + /* LED_OFF and unsupported colors */ + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); + } +} + +__override void led_set_color_battery(enum ec_led_colors color) +{ + /* Don't set led if led_auto_control is disabled. */ + if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED) || + !led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + return; + } + + /* Battery leds must be turn off when blue led is on + * because the led is 3-in-1 led. + */ + if (!gpio_get_level(GPIO_PWR_LED_BLUE_L)) { + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + return; + } + + switch (color) { + case EC_LED_COLOR_GREEN: + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_ON_LVL); /*green*/ + break; + case EC_LED_COLOR_RED: + gpio_set_level(GPIO_BAT_LED_RED_L, LED_ON_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); /*red*/ + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); /*green*/ + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_RED] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + gpio_set_level(GPIO_PWR_LED_BLUE_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_GREEN_L, + !brightness[EC_LED_COLOR_GREEN]); + gpio_set_level(GPIO_BAT_LED_RED_L, + !brightness[EC_LED_COLOR_RED]); + } else if (led_id == EC_LED_ID_POWER_LED) { + gpio_set_level(GPIO_PWR_LED_BLUE_L, + !brightness[EC_LED_COLOR_BLUE]); + gpio_set_level(GPIO_BAT_LED_GREEN_L, LED_OFF_LVL); + gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL); + } + + return EC_SUCCESS; +} diff --git a/board/sasukette/usb_pd_policy.c b/board/sasukette/usb_pd_policy.c new file mode 100644 index 0000000000..83c09bb99e --- /dev/null +++ b/board/sasukette/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/sasukette/vif_override.xml b/board/sasukette/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/sasukette/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/scarlet/battery.c b/board/scarlet/battery.c index 0be4cc93e2..f38e1f7896 100644 --- a/board/scarlet/battery.c +++ b/board/scarlet/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -32,11 +32,7 @@ static uint8_t batt_id = 0xff; /* Do not change the enum values. We directly use strap gpio level to index. */ -enum battery_type { - BATTERY_SIMPLO = 0, - BATTERY_AETECH, - BATTERY_COUNT -}; +enum battery_type { BATTERY_SIMPLO = 0, BATTERY_AETECH, BATTERY_COUNT }; static const struct battery_info info[] = { [BATTERY_SIMPLO] = { @@ -192,7 +188,7 @@ int charger_profile_override(struct charge_state_data *curr) else { for (temp_zone = 0; temp_zone < TEMP_ZONE_COUNT; temp_zone++) { if (bat_temp_c < - temp_zones[batt_id][temp_zone].temp_max) + temp_zones[batt_id][temp_zone].temp_max) break; } } @@ -233,9 +229,10 @@ int charger_profile_override(struct charge_state_data *curr) curr->requested_voltage = temp_zones[batt_id][temp_zone].desired_voltage; - curr->requested_current = (charge_phase) ? - CHARGE_PHASE_CHANGED_CURRENT_MA : - temp_zones[batt_id][temp_zone].desired_current; + curr->requested_current = + (charge_phase) ? + CHARGE_PHASE_CHANGED_CURRENT_MA : + temp_zones[batt_id][temp_zone].desired_current; break; case TEMP_OUT_OF_RANGE: curr->requested_current = curr->requested_voltage = 0; @@ -246,12 +243,12 @@ int charger_profile_override(struct charge_state_data *curr) /* * When the charger says it's done charging, even if fuel gauge says - * SOC < BATTERY_LEVEL_NEAR_FULL, we'll overwrite SOC with - * BATTERY_LEVEL_NEAR_FULL. So we can ensure both Chrome OS UI + * SOC < CONFIG_BATT_HOST_FULL_FACTOR, we'll overwrite SOC with + * CONFIG_BATT_HOST_FULL_FACTOR. So we can ensure both Chrome OS UI * and battery LED indicate full charge. */ if (rt946x_is_charge_done()) { - curr->batt.state_of_charge = MAX(BATTERY_LEVEL_NEAR_FULL, + curr->batt.state_of_charge = MAX(CONFIG_BATT_HOST_FULL_FACTOR, curr->batt.state_of_charge); /* * This is a workaround for b:78792296. When AP is off and @@ -281,8 +278,7 @@ static void board_charge_termination(void) te = 1; } } -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, - board_charge_termination, +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, board_charge_termination, HOOK_PRIO_DEFAULT); /* Customs options controllable by host command. */ diff --git a/board/scarlet/board.c b/board/scarlet/board.c index ef5dc6f6f1..daa247b385 100644 --- a/board/scarlet/board.c +++ b/board/scarlet/board.c @@ -1,30 +1,29 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" #include "charge_manager.h" #include "charge_state.h" -#include "charge_state_v2.h" #include "charger.h" #include "chipset.h" #include "common.h" #include "console.h" -#include "ec_commands.h" #include "driver/accelgyro_bmi_common.h" #include "driver/charger/rt946x.h" #include "driver/sync.h" #include "driver/tcpm/fusb302.h" #include "driver/temp_sensor/tmp432.h" +#include "ec_commands.h" #include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "i2c.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -34,18 +33,18 @@ #include "switch.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "temp_sensor.h" #include "temp_sensor_chip.h" -#include "timer.h" #include "thermal.h" +#include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { @@ -64,20 +63,29 @@ static void warm_reset_request_interrupt(enum gpio_signal signal) chipset_reset(CHIPSET_RESET_AP_REQ); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"charger", I2C_PORT_CHARGER, 400, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 1000, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, + { .name = "charger", + .port = I2C_PORT_CHARGER, + .kbps = 400, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -93,22 +101,22 @@ const struct charger_config_t chg_chips[] = { /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_PP1250_S3_PG, POWER_SIGNAL_ACTIVE_HIGH, "PP1250_S3_PWR_GOOD"}, - {GPIO_PP900_S0_PG, POWER_SIGNAL_ACTIVE_HIGH, "PP900_S0_PWR_GOOD"}, - {GPIO_AP_CORE_PG, POWER_SIGNAL_ACTIVE_HIGH, "AP_PWR_GOOD"}, - {GPIO_AP_EC_S3_S0_L, POWER_SIGNAL_ACTIVE_LOW, "SUSPEND_DEASSERTED"}, + { GPIO_PP1250_S3_PG, POWER_SIGNAL_ACTIVE_HIGH, "PP1250_S3_PWR_GOOD" }, + { GPIO_PP900_S0_PG, POWER_SIGNAL_ACTIVE_HIGH, "PP900_S0_PWR_GOOD" }, + { GPIO_AP_CORE_PG, POWER_SIGNAL_ACTIVE_HIGH, "AP_PWR_GOOD" }, + { GPIO_AP_EC_S3_S0_L, POWER_SIGNAL_ACTIVE_LOW, "SUSPEND_DEASSERTED" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); #ifdef CONFIG_TEMP_SENSOR_TMP432 /* Temperature sensors data; must be in same order as enum temp_sensor_id. */ const struct temp_sensor_t temp_sensors[] = { - {"TMP432_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_LOCAL, 4}, - {"TMP432_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE1, 4}, - {"TMP432_Sensor_2", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, - TMP432_IDX_REMOTE2, 4}, + { "TMP432_Internal", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_LOCAL, 4 }, + { "TMP432_Sensor_1", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE1, 4 }, + { "TMP432_Sensor_2", TEMP_SENSOR_TYPE_BOARD, tmp432_get_val, + TMP432_IDX_REMOTE2, 4 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -117,9 +125,9 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); * same order as enum temp_sensor_id. To always ignore any temp, use 0. */ struct ec_thermal_config thermal_params[] = { - {{0, 0, 0}, 0, 0}, /* TMP432_Internal */ - {{0, 0, 0}, 0, 0}, /* TMP432_Sensor_1 */ - {{0, 0, 0}, 0, 0}, /* TMP432_Sensor_2 */ + { { 0, 0, 0 }, 0, 0 }, /* TMP432_Internal */ + { { 0, 0, 0 }, 0, 0 }, /* TMP432_Sensor_1 */ + { { 0, 0, 0 }, 0, 0 }, /* TMP432_Sensor_2 */ }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); #endif @@ -137,17 +145,20 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }, }; @@ -155,11 +166,11 @@ void board_reset_pd_mcu(void) { } -enum critical_shutdown board_critical_shutdown_check( - struct charge_state_data *curr) +enum critical_shutdown +board_critical_shutdown_check(struct charge_state_data *curr) { if ((curr->batt.flags & BATT_FLAG_BAD_VOLTAGE) || - (curr->batt.voltage <= BAT_LOW_VOLTAGE_THRESH)) + (curr->batt.voltage <= BAT_LOW_VOLTAGE_THRESH)) return CRITICAL_SHUTDOWN_CUTOFF; else return CRITICAL_SHUTDOWN_IGNORE; @@ -201,13 +212,6 @@ int board_set_active_charge_port(int charge_port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - int extpower_is_present(void) { /* @@ -230,7 +234,7 @@ int pd_snk_is_vbus_provided(int port) static void board_spi_enable(void) { - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); /* Enable clocks to SPI2 module */ STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; @@ -239,23 +243,21 @@ static void board_spi_enable(void) STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_spi_enable, +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, MOTION_SENSE_HOOK_PRIO - 1); static void board_spi_disable(void) { - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); /* Disable clocks to SPI2 module */ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; - gpio_config_module(MODULE_SPI_MASTER, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_spi_disable, +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, MOTION_SENSE_HOOK_PRIO + 1); static void board_init(void) @@ -295,8 +297,8 @@ void board_config_pre_init(void) * Ch4: USART1_TX / Ch5: USART1_RX (1000) * Ch6: SPI2_RX / Ch7: SPI2_TX (0011) */ - STM32_DMA_CSELR(STM32_DMAC_CH4) = (8 << 12) | (8 << 16) | - (3 << 20) | (3 << 24); + STM32_DMA_CSELR(STM32_DMAC_CH4) = (8 << 12) | (8 << 16) | (3 << 20) | + (3 << 24); } enum scarlet_board_version { @@ -324,16 +326,16 @@ struct { enum scarlet_board_version version; int expect_mv; } const scarlet_boards[] = { - { BOARD_VERSION_REV0, 109 }, /* 51.1K , 2.2K(gru 3.3K) ohm */ - { BOARD_VERSION_REV1, 211 }, /* 51.1k , 6.8K ohm */ - { BOARD_VERSION_REV2, 319 }, /* 51.1K , 11K ohm */ - { BOARD_VERSION_REV3, 427 }, /* 56K , 17.4K ohm */ - { BOARD_VERSION_REV4, 542 }, /* 51.1K , 22K ohm */ - { BOARD_VERSION_REV5, 666 }, /* 51.1K , 30K ohm */ - { BOARD_VERSION_REV6, 781 }, /* 51.1K , 39.2K ohm */ - { BOARD_VERSION_REV7, 900 }, /* 56K , 56K ohm */ - { BOARD_VERSION_REV8, 1023 }, /* 47K , 61.9K ohm */ - { BOARD_VERSION_REV9, 1137 }, /* 47K , 80.6K ohm */ + { BOARD_VERSION_REV0, 109 }, /* 51.1K , 2.2K(gru 3.3K) ohm */ + { BOARD_VERSION_REV1, 211 }, /* 51.1k , 6.8K ohm */ + { BOARD_VERSION_REV2, 319 }, /* 51.1K , 11K ohm */ + { BOARD_VERSION_REV3, 427 }, /* 56K , 17.4K ohm */ + { BOARD_VERSION_REV4, 542 }, /* 51.1K , 22K ohm */ + { BOARD_VERSION_REV5, 666 }, /* 51.1K , 30K ohm */ + { BOARD_VERSION_REV6, 781 }, /* 51.1K , 39.2K ohm */ + { BOARD_VERSION_REV7, 900 }, /* 56K , 56K ohm */ + { BOARD_VERSION_REV8, 1023 }, /* 47K , 61.9K ohm */ + { BOARD_VERSION_REV9, 1137 }, /* 47K , 80.6K ohm */ { BOARD_VERSION_REV10, 1240 }, /* 56K , 124K ohm */ { BOARD_VERSION_REV11, 1343 }, /* 51.1K , 150K ohm */ { BOARD_VERSION_REV12, 1457 }, /* 47K , 200K ohm */ @@ -383,18 +385,15 @@ int board_get_version(void) } /* Motion sensors */ -#ifdef HAS_TASK_MOTIONSENSE /* Mutexes */ static struct mutex g_base_mutex; static struct bmi_drv_data_t g_bmi160_data; /* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { /* @@ -412,7 +411,7 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .rot_standard_ref = &base_standard_ref, .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, @@ -435,7 +434,7 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_GYRO_MIN_FREQ, @@ -454,9 +453,8 @@ struct motion_sensor_t motion_sensors[] = { }, }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#endif /* defined(HAS_TASK_MOTIONSENSE) */ -int board_allow_i2c_passthru(int port) +int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc) { - return (port == I2C_PORT_VIRTUAL_BATTERY); + return (cmd_desc->port == I2C_PORT_VIRTUAL_BATTERY); } diff --git a/board/scarlet/board.h b/board/scarlet/board.h index 7e48ffde52..0bd4473389 100644 --- a/board/scarlet/board.h +++ b/board/scarlet/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,17 +8,22 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H +/* Free up flash space */ +#define CONFIG_DEBUG_ASSERT_BRIEF +#define CONFIG_LTO +#define CONFIG_USB_PD_DEBUG_LEVEL 0 + /* Optional modules */ #define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG +#undef CONFIG_ADC_WATCHDOG #define CONFIG_CHIPSET_RK3399 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_RTC #define CONFIG_EMULATED_SYSRQ -#undef CONFIG_HIBERNATE +#undef CONFIG_HIBERNATE #define CONFIG_HOSTCMD_RTC #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_I2C_VIRTUAL_BATTERY #define CONFIG_I2C_PASSTHRU_RESTRICTED #define CONFIG_LED_COMMON @@ -26,8 +31,7 @@ #define CONFIG_LOW_POWER_IDLE_LIMITED #define CONFIG_POWER_COMMON #define CONFIG_SPI -#define CONFIG_SPI_MASTER -#define CONFIG_STM_HWTIMER32 +#define CONFIG_SPI_CONTROLLER /* Source RTCCLK from external 32.768kHz source on PC15/OSC32_IN. */ #define CONFIG_STM32_CLOCK_LSE #define CONFIG_SWITCH @@ -35,7 +39,7 @@ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */ -#undef CONFIG_UART_CONSOLE +#undef CONFIG_UART_CONSOLE #define CONFIG_UART_CONSOLE 1 #define CONFIG_UART_RX_DMA @@ -45,7 +49,6 @@ /* Optional features */ #define CONFIG_BOARD_PRE_INIT -#define CONFIG_BOARD_VERSION_CUSTOM #define CONFIG_BUTTON_TRIGGERED_RECOVERY #define CONFIG_CHARGER_ILIM_PIN_DISABLED #define CONFIG_FORCE_CONSOLE_RESUME @@ -58,18 +61,16 @@ #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF #undef CONFIG_LID_SWITCH -#undef CONFIG_LTO #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_IGNORE_LID #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE -#define CONFIG_SOFTWARE_PANIC #define CONFIG_VBOOT_HASH #define CONFIG_VOLUME_BUTTONS #define CONFIG_CHARGER #define CONFIG_CHARGER_RT9467 -#define CONFIG_CHARGER_INPUT_CURRENT 512 -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 2 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 +#define CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT 2 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 15000 #define CONFIG_CHARGER_PROFILE_OVERRIDE @@ -84,15 +85,13 @@ /* Motion Sensors */ #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) /* Camera VSYNC */ #define CONFIG_SYNC #define CONFIG_SYNC_COMMAND -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) /* To be able to indicate the device is in tablet mode. */ #define CONFIG_TABLET_MODE @@ -130,35 +129,36 @@ #define CONFIG_BATTERY_REVIVE_DISCONNECT #define CONFIG_BATTERY_MAX17055 +/* Disable verbose output in EC pd */ +#ifdef SECTION_IS_RO +#define CONFIG_CMD_PD_SRCCAPS_REDUCED_SIZE +#endif + /* Battery parameters for max17055 ModelGauge m5 algorithm. */ -#define BATTERY_MAX17055_RSENSE 5 /* m-ohm */ -#define BATTERY_DESIRED_CHARGING_CURRENT 4000 /* mA */ +#define BATTERY_MAX17055_RSENSE 5 /* m-ohm */ +#define BATTERY_DESIRED_CHARGING_CURRENT 4000 /* mA */ #define CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT -#define BAT_MAX_DISCHG_CURRENT 5000 /* mA */ - #define CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE -#define BAT_LOW_VOLTAGE_THRESH 3200 /* mV */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 12850 +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 12850 -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ /* Timer selection */ -#define TIM_CLOCK32 2 +#define TIM_CLOCK32 2 #define TIM_WATCHDOG 7 /* 48 MHz SYSCLK clock frequency */ #define CPU_CLOCK 48000000 /* Optional for testing */ -#undef CONFIG_PECI -#undef CONFIG_PSTORE +#undef CONFIG_PECI +#undef CONFIG_PSTORE /* Modules we want to exclude */ #undef CONFIG_CMD_BATTFAKE @@ -171,24 +171,24 @@ #define CONFIG_TASK_PROFILING -#define I2C_PORT_CHARGER 0 -#define I2C_PORT_BATTERY 0 +#define I2C_PORT_CHARGER 0 +#define I2C_PORT_BATTERY 0 #define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY -#define I2C_PORT_TCPC0 1 +#define I2C_PORT_TCPC0 1 /* Route sbs host requests to virtual battery driver */ #define VIRTUAL_BATTERY_ADDR_FLAGS 0x0B /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ -#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_MKBP_INPUT_DEVICES #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO /* Define the host events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) +#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) #ifndef __ASSEMBLER__ diff --git a/board/scarlet/build.mk b/board/scarlet/build.mk index f2966fea6a..adecf6b4ea 100644 --- a/board/scarlet/build.mk +++ b/board/scarlet/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/scarlet/ec.tasklist b/board/scarlet/ec.tasklist index 1548272184..08baec1e86 100644 --- a/board/scarlet/ec.tasklist +++ b/board/scarlet/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/scarlet/gpio.inc b/board/scarlet/gpio.inc index bfede671a8..15ce1cb681 100644 --- a/board/scarlet/gpio.inc +++ b/board/scarlet/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -99,4 +99,4 @@ ALTERNATE(PIN_MASK(B, 0x0038), 0, MODULE_SPI, 0) /* SPI SLAVE CS: PA15 */ ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) /* SPI MASTER: PD1/3/4 */ -ALTERNATE(PIN_MASK(D, 0x001a), 1, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(D, 0x001a), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/scarlet/led.c b/board/scarlet/led.c index d4c758cdcc..cccec4af73 100644 --- a/board/scarlet/led.c +++ b/board/scarlet/led.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,6 +8,7 @@ #include "battery.h" #include "charge_state.h" #include "chipset.h" +#include "gpio.h" #include "hooks.h" #include "led_common.h" #include "lid_switch.h" @@ -27,7 +28,7 @@ enum led_color { LED_RED, LED_AMBER, LED_GREEN, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int bat_led_set_color(enum led_color color) @@ -62,35 +63,35 @@ static void scarlet_led_set_battery(void) battery_second++; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: bat_led_set_color(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (charge_get_percent() < 3) - bat_led_set_color((battery_second & 1) - ? LED_OFF : LED_AMBER); + bat_led_set_color((battery_second & 1) ? LED_OFF : + LED_AMBER); else if (charge_get_percent() < 10) - bat_led_set_color((battery_second & 3) - ? LED_OFF : LED_AMBER); - else if (charge_get_percent() >= BATTERY_LEVEL_NEAR_FULL && - (chflags & CHARGE_FLAG_EXTERNAL_POWER)) + bat_led_set_color((battery_second & 3) ? LED_OFF : + LED_AMBER); + else if (charge_get_percent() >= CONFIG_BATT_HOST_FULL_FACTOR && + (chflags & CHARGE_FLAG_EXTERNAL_POWER)) bat_led_set_color(LED_GREEN); else bat_led_set_color(LED_OFF); break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: bat_led_set_color(LED_RED); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: bat_led_set_color(LED_GREEN); break; - case PWR_STATE_IDLE: /* External power connected in IDLE. */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - bat_led_set_color( - (battery_second & 0x2) ? LED_GREEN : LED_AMBER); - else - bat_led_set_color(LED_GREEN); + case LED_PWRS_IDLE: /* External power connected in IDLE. */ + bat_led_set_color(LED_GREEN); + break; + case LED_PWRS_FORCED_IDLE: + bat_led_set_color((battery_second & 0x2) ? LED_GREEN : + LED_AMBER); break; default: /* Other states don't alter LED behavior */ @@ -111,10 +112,12 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) if (led_id == EC_LED_ID_BATTERY_LED) { gpio_set_level(GPIO_BAT_LED_RED, (brightness[EC_LED_COLOR_RED] != 0) ? - BAT_LED_ON : BAT_LED_OFF); + BAT_LED_ON : + BAT_LED_OFF); gpio_set_level(GPIO_BAT_LED_GREEN, (brightness[EC_LED_COLOR_GREEN] != 0) ? - BAT_LED_ON : BAT_LED_OFF); + BAT_LED_ON : + BAT_LED_OFF); return EC_SUCCESS; } return EC_ERROR_UNKNOWN; diff --git a/board/scarlet/usb_pd_policy.c b/board/scarlet/usb_pd_policy.c index cba4540ecd..90c7dfb157 100644 --- a/board/scarlet/usb_pd_policy.c +++ b/board/scarlet/usb_pd_policy.c @@ -1,11 +1,11 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "charger.h" #include "charge_manager.h" +#include "charger.h" #include "common.h" #include "console.h" #include "driver/charger/rt946x.h" @@ -16,13 +16,13 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static uint8_t vbus_en; @@ -33,7 +33,6 @@ int board_vbus_source_enabled(int port) int pd_set_power_supply_ready(int port) { - pd_set_vbus_discharge(port, 0); /* Provide VBUS */ vbus_en = 1; diff --git a/board/scarlet/vif_override.xml b/board/scarlet/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/scarlet/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/scout/board.c b/board/scout/board.c new file mode 100644 index 0000000000..3d5306fdf0 --- /dev/null +++ b/board/scout/board.c @@ -0,0 +1,767 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Puff board-specific configuration */ + +#include "adc.h" +#include "button.h" +#include "chipset.h" +#include "common.h" +#include "core/cortex-m/cpu.h" +#include "cros_board_info.h" +#include "driver/als_tcs3400.h" +#include "driver/ina3221.h" +#include "ec_commands.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "lid_switch.h" +#include "power.h" +#include "power/cometlake-discrete.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "spi.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" +#include "uart.h" +#include "usb_common.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +/* Sensors */ + +/* TCS3400 private data */ +static struct als_drv_data_t g_tcs3400_data = { + .als_cal.scale = 1, + .als_cal.uscale = 0, + .als_cal.offset = 0, + .als_cal.channel_scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc */ + .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */ + }, +}; + +static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { + /* + * b/202465034: calculate the actual coefficients and scaling factors + */ + .calibration.rgb_cal[X] = { + .offset = 0, + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + }, + .calibration.rgb_cal[Y] = { + .offset = 0, + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.1), + }, + .calibration.rgb_cal[Z] = { + .offset = 0, + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + }, + .calibration.irt = INT_TO_FP(1), + .saturation.again = TCS_DEFAULT_AGAIN, + .saturation.atime = TCS_DEFAULT_ATIME, +}; + +struct motion_sensor_t motion_sensors[] = { + [CLEAR_ALS] = { + .name = "Clear Light", + .active_mask = SENSOR_ACTIVE_S0, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT, + .location = MOTIONSENSE_LOC_BASE, + .drv = &tcs3400_drv, + .drv_data = &g_tcs3400_data, + .port = I2C_PORT_SENSORS, + .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + .min_frequency = TCS3400_LIGHT_MIN_FREQ, + .max_frequency = TCS3400_LIGHT_MAX_FREQ, + .config = { + /* Run ALS sensor in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 1000, + }, + }, + }, + [RGB_ALS] = { + .name = "RGB Light", + .active_mask = SENSOR_ACTIVE_S0, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT_RGB, + .location = MOTIONSENSE_LOC_BASE, + .drv = &tcs3400_rgb_drv, + .drv_data = &g_tcs3400_rgb_data, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ +const struct motion_sensor_t *motion_als_sensors[] = { + &motion_sensors[CLEAR_ALS], +}; +BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); + +static void power_monitor(void); +DECLARE_DEFERRED(power_monitor); + +static uint8_t usbc_overcurrent; +static int32_t base_5v_power; + +/* + * Power usage for each port as measured or estimated. + * Units are milliwatts (5v x ma current) + */ +#define PWR_BASE_LOAD (5 * 1335) +#define PWR_FRONT_HIGH (5 * 1603) +#define PWR_FRONT_LOW (5 * 963) +#define PWR_REAR (5 * 1075) +#define PWR_HDMI (5 * 562) +#define PWR_C_HIGH (5 * 3740) +#define PWR_C_LOW (5 * 2090) +#define PWR_MAX (5 * 10000) + +/* + * Update the 5V power usage, assuming no throttling, + * and invoke the power monitoring. + */ +static void update_5v_usage(void) +{ + int front_ports = 0; + /* + * Recalculate the 5V load, assuming no throttling. + */ + base_5v_power = PWR_BASE_LOAD; + if (!gpio_get_level(GPIO_USB_A0_OC_ODL)) { + front_ports++; + base_5v_power += PWR_FRONT_LOW; + } + if (!gpio_get_level(GPIO_USB_A1_OC_ODL)) { + front_ports++; + base_5v_power += PWR_FRONT_LOW; + } + /* + * Only 1 front port can run higher power at a time. + */ + if (front_ports > 0) + base_5v_power += PWR_FRONT_HIGH - PWR_FRONT_LOW; + if (!gpio_get_level(GPIO_USB_A2_OC_ODL)) + base_5v_power += PWR_REAR; + if (!gpio_get_level(GPIO_USB_A3_OC_ODL)) + base_5v_power += PWR_REAR; + if (!gpio_get_level(GPIO_HDMI_CONN0_OC_ODL)) + base_5v_power += PWR_HDMI; + if (!gpio_get_level(GPIO_HDMI_CONN1_OC_ODL)) + base_5v_power += PWR_HDMI; + if (usbc_overcurrent) + base_5v_power += PWR_C_HIGH; + /* + * Invoke the power handler immediately. + */ + hook_call_deferred(&power_monitor_data, 0); +} +DECLARE_DEFERRED(update_5v_usage); +/* + * Start power monitoring after ADCs have been initialised. + */ +DECLARE_HOOK(HOOK_INIT, update_5v_usage, HOOK_PRIO_INIT_ADC + 1); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_5v_usage_data, 0); +} + +/******************************************************************************/ + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/******************************************************************************/ +/* SPI devices */ +const struct spi_device_t spi_devices[] = {}; +const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); + +/******************************************************************************/ +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, + [PWM_CH_LED_RED] = { .channel = 0, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000 }, + [PWM_CH_LED_WHITE] = { .channel = 2, + .flags = PWM_CONFIG_DSLEEP, + .freq = 2000 }, +}; + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { .name = "ina", + .port = I2C_PORT_INA, + .kbps = 400, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "ppc0", + .port = I2C_PORT_PPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "scaler", + .port = I2C_PORT_SCALER, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 400, + .scl = GPIO_I2C5_SCL, + .sda = GPIO_I2C5_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +const struct adc_t adc_channels[] = { + [ADC_SNS_PP3300] = { + /* + * 4700/5631 voltage divider: can take the value out of range + * for 32-bit signed integers, so truncate to 470/563 yielding + * <0.1% error and a maximum intermediate value of 1623457792, + * which comfortably fits in int32. + */ + .name = "SNS_PP3300", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT * 563, + .factor_div = (ADC_READ_MAX + 1) * 470, + }, + [ADC_SNS_PP1050] = { + .name = "SNS_PP1050", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + }, + [ADC_VBUS] = { /* 5/39 voltage divider */ + .name = "VBUS", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT * 39, + .factor_div = (ADC_READ_MAX + 1) * 5, + }, + [ADC_PPVAR_IMON] = { /* 500 mV/A */ + .name = "PPVAR_IMON", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT * 2, /* Milliamps */ + .factor_div = ADC_READ_MAX + 1, + }, + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR_1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR_2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_CORE] = { + .name = "Core", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1, + }, + [TEMP_SENSOR_WIFI] = { + .name = "Wifi", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/******************************************************************************/ +/* Wake up pins */ +const enum gpio_signal hibernate_wake_pins[] = {}; +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); + +/******************************************************************************/ +/* Physical fans. These are logically separate from pwm_channels. */ +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = -1, +}; + +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2400, + .rpm_start = 2400, + .rpm_max = 5300, +}; + +const struct fan_t fans[] = { + [FAN_CH_0] = { .conf = &fan_conf_0, .rpm = &fan_rpm_0, }, +}; +BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT); + +/******************************************************************************/ +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { NPCX_MFT_MODULE_2, TCKC_LFCLK, PWM_CH_FAN }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +/******************************************************************************/ +/* Thermal control; drive fan based on temperature sensors. */ +static const int temp_fan_off = C_TO_K(35); +static const int temp_fan_max = C_TO_K(55); +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(78), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = temp_fan_off, \ + .temp_fan_max = temp_fan_max, \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; + +static const struct ec_thermal_config thermal_b = { + .temp_host = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(78), + [EC_TEMP_THRESH_HALT] = C_TO_K(85), + }, + .temp_host_release = { + [EC_TEMP_THRESH_WARN] = 0, + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), + [EC_TEMP_THRESH_HALT] = 0, + }, + }; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_CORE] = THERMAL_A, + [TEMP_SENSOR_WIFI] = THERMAL_A, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +static const struct fan_step_1_1 fan_table0[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(35), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(41), + .rpm = 2400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(40), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .rpm = 2900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .rpm = 3400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .rpm = 3900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .rpm = 4400 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(52), + .rpm = 4900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(50), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(55), + .rpm = 5300 }, +}; +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_table0) + +static const struct fan_step_1_1 *fan_table = fan_table0; + +int fan_percent_to_rpm(int fan, int temp_ratio) +{ + return temp_ratio_to_rpm_hysteresis(fan_table, NUM_FAN_LEVELS, fan, + temp_ratio, NULL); +} + +/* Power sensors */ +const struct ina3221_t ina3221[] = { + { I2C_PORT_INA, 0x40, { "PP3300_G", "PP5000_A", "PP3300_WLAN" } }, + { I2C_PORT_INA, 0x42, { "PP3300_A", "PP3300_SSD", "PP3300_LAN" } }, + { I2C_PORT_INA, 0x43, { NULL, "PP1200_U", "PP2500_DRAM" } } +}; +const unsigned int ina3221_count = ARRAY_SIZE(ina3221); + +static uint16_t board_version; +static uint32_t sku_id; +static uint32_t fw_config; + +static void cbi_init(void) +{ + /* + * Load board info from CBI to control per-device configuration. + * + * If unset it's safe to treat the board as a proto, just C10 gating + * won't be enabled. + */ + uint32_t val; + + if (cbi_get_board_version(&val) == EC_SUCCESS && val <= UINT16_MAX) + board_version = val; + if (cbi_get_sku_id(&val) == EC_SUCCESS) + sku_id = val; + if (cbi_get_fw_config(&val) == EC_SUCCESS) + fw_config = val; + CPRINTS("Board Version: %d, SKU ID: 0x%08x, F/W config: 0x%08x", + board_version, sku_id, fw_config); +} +DECLARE_HOOK(HOOK_INIT, cbi_init, HOOK_PRIO_INIT_I2C + 1); + +static void board_sensors_init(void) +{ + /* Enable interrupt for the TCS3400 color light sensor */ + switch (board_version) { + case BOARD_VERSION_PROTO: + case BOARD_VERSION_PRE_EVT: + case BOARD_VERSION_EVT: + /* + * b/203224828: These versions incorrectly use a 1.8V interrupt + * line, which sends a constant interrupt signal and eventually + * triggers a watchdog reset, so we keep it disabled. + */ + gpio_disable_interrupt(GPIO_EC_RGB_INT_L); + CPRINTS("ALS interrupt disabled (detected known-bad hardware)"); + break; + + case BOARD_VERSION_DVT: + case BOARD_VERSION_PVT: + default: + gpio_enable_interrupt(GPIO_EC_RGB_INT_L); + CPRINTS("ALS interrupt enabled"); + break; + } +} +/* Ensure board_sensors_init runs after cbi_init. */ +DECLARE_HOOK(HOOK_INIT, board_sensors_init, HOOK_PRIO_INIT_I2C + 2); + +static void board_init(void) +{ + uint8_t *memmap_batt_flags; + + /* Override some GPIO interrupt priorities. + * + * These interrupts are timing-critical for AP power sequencing, so we + * increase their NVIC priority from the default of 3. This affects + * whole MIWU groups of 8 GPIOs since they share an IRQ. + * + * Latency at the default priority level can be hundreds of + * microseconds while other equal-priority IRQs are serviced, so GPIOs + * requiring faster response must be higher priority. + */ + /* CPU_C10_GATE_L on GPIO6.7: must be ~instant for ~60us response. */ + cpu_set_interrupt_priority(NPCX_IRQ_WKINTH_1, 1); + /* + * slp_s3_interrupt (GPIOA.5 on WKINTC_0) must respond within 200us + * (tPLT18); less critical than the C10 gate. + */ + cpu_set_interrupt_priority(NPCX_IRQ_WKINTC_0, 2); + + /* Always claim AC is online, because we don't have a battery. */ + memmap_batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); + *memmap_batt_flags |= EC_BATT_FLAG_AC_PRESENT; + /* + * For board version < 2, the directly connected recovery + * button is not available. + */ + if (board_version < 2) + button_disable_gpio(BUTTON_RECOVERY); + + /* + * Early Scout devices does not setup EC_MIC_OE in RO, so it needs + * to be done explicitly instead. + */ + gpio_set_level(GPIO_EC_MIC_OE, 1); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/******************************************************************************/ +/* USB-A port control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USB_VBUS, +}; + +int64_t get_time_dsw_pwrok(void) +{ + /* DSW_PWROK is turned on before EC was powered. */ + return -20 * MSEC; +} + +int extpower_is_present(void) +{ + /* genesis: If the EC is running, then there is external power */ + return 1; +} + +int board_is_c10_gate_enabled(void) +{ + /* + * Puff proto drives EN_PP5000_HDMI from EN_S0_RAILS so we cannot gate + * core rails while in S0 because HDMI should remain powered. + * EN_PP5000_HDMI is a separate EC output on all other boards. + */ + return board_version != 0; +} + +void board_enable_s0_rails(int enable) +{ + /* This output isn't connected on protos; safe to set anyway. */ + gpio_set_level(GPIO_EN_PP5000_HDMI, enable); + + /* + * Toggle scaler power and its downstream USB devices. + */ + gpio_set_level(GPIO_EC_SCALER_EN, enable); + gpio_set_level(GPIO_PWR_CTRL, enable); + gpio_set_level(GPIO_EC_MX8M_ONOFF, enable); + gpio_set_level(GPIO_EC_CAM_V3P3_EN, enable); + + gpio_set_level(GPIO_EN_LOAD_SWITCH, enable); +} + +/* + * TPU is turned on in S0, off in S0ix and lower. + */ +static void disable_tpu_power(void) +{ + gpio_set_level(GPIO_PP3300_TPU_A_EN, 0); + gpio_set_level(GPIO_EC_IMX8_EN, 0); +} + +static void enable_tpu_power(void) +{ + gpio_set_level(GPIO_PP3300_TPU_A_EN, 1); + gpio_set_level(GPIO_EC_IMX8_EN, 1); +} + +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, disable_tpu_power, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, enable_tpu_power, HOOK_PRIO_DEFAULT); + +int ec_config_get_usb4_present(void) +{ + return !(fw_config & EC_CFG_NO_USB4_MASK); +} + +unsigned int ec_config_get_thermal_solution(void) +{ + return (fw_config & EC_CFG_THERMAL_MASK) >> EC_CFG_THERMAL_L; +} + +static void setup_thermal(void) +{ + unsigned int table = ec_config_get_thermal_solution(); + /* Configure Fan */ + switch (table) { + /* Default and table0 use single fan */ + case 0: + default: + thermal_params[TEMP_SENSOR_CORE] = thermal_a; + thermal_params[TEMP_SENSOR_WIFI] = thermal_a; + break; + /* Table1 is fanless */ + case 1: + fan_set_count(0); + thermal_params[TEMP_SENSOR_CORE] = thermal_b; + break; + } +} +/* fan_set_count should be called before HOOK_INIT/HOOK_PRIO_DEFAULT */ +DECLARE_HOOK(HOOK_INIT, setup_thermal, HOOK_PRIO_DEFAULT - 1); + +/* + * Power monitoring and management. + * + * The overall goal is to gracefully manage the power demand so that + * the power budgets are met without letting the system fall into + * power deficit (perhaps causing a brownout). + * + * There are 2 power budgets that need to be managed: + * - overall system power as measured on the main power supply rail. + * - 5V power delivered to the USB and HDMI ports. + * + * The actual system power demand is calculated from the VBUS voltage and + * the input current (read from a shunt), averaged over 5 readings. + * The power budget limit is from the charge manager. + * + * The 5V power cannot be read directly. Instead, we rely on overcurrent + * inputs from the USB and HDMI ports to indicate that the port is in use + * (and drawing maximum power). + * + * There are 3 throttles that can be applied (in priority order): + * + * - Type A BC1.2 front port restriction (3W) + * - Type C PD (throttle to 1.5A if sourcing) + * - Turn on PROCHOT, which immediately throttles the CPU. + * + * The first 2 throttles affect both the system power and the 5V rails. + * The third is a last resort to force an immediate CPU throttle to + * reduce the overall power use. + * + * The strategy is to determine what the state of the throttles should be, + * and to then turn throttles off or on as needed to match this. + * + * This function runs on demand, or every 2 ms when the CPU is up, + * and continually monitors the power usage, applying the + * throttles when necessary. + * + * All measurements are in milliwatts. + */ +#define THROT_TYPE_A BIT(0) +#define THROT_TYPE_C BIT(1) +#define THROT_PROCHOT BIT(2) + +/* + * Power gain if front USB A ports are limited. + */ +#define POWER_GAIN_TYPE_A 3200 +/* + * Power gain if Type C port is limited. + */ +#define POWER_GAIN_TYPE_C 8800 +/* + * Power is averaged over 10 ms, with a reading every 2 ms. + */ +#define POWER_DELAY_MS 2 +#define POWER_READINGS (10 / POWER_DELAY_MS) + +static void power_monitor(void) +{ + static uint32_t current_state; + int32_t delay; + uint32_t new_state = 0, diff; + int32_t headroom_5v = PWR_MAX - base_5v_power; + + /* + * If CPU is off or suspended, no need to throttle + * or restrict power. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_SUSPEND)) { + /* + * Slow down monitoring, assume no throttling required. + */ + delay = 20 * MSEC; + } else { + delay = POWER_DELAY_MS * MSEC; + } + /* + * Check the 5v power usage and if necessary, + * adjust the throttles in priority order. + * + * Either throttle may have already been activated by + * the overall power control. + * + * We rely on the overcurrent detection to inform us + * if the port is in use. + * + * - If type C not already throttled: + * * If not overcurrent, prefer to limit type C [1]. + * * If in overcurrentuse: + * - limit type A first [2] + * - If necessary, limit type C [3]. + * - If type A not throttled, if necessary limit it [2]. + */ + if (headroom_5v < 0) { + /* + * Check whether type C is not throttled, + * and is not overcurrent. + */ + if (!((new_state & THROT_TYPE_C) || usbc_overcurrent)) { + /* + * [1] Type C not in overcurrent, throttle it. + */ + headroom_5v += PWR_C_HIGH - PWR_C_LOW; + new_state |= THROT_TYPE_C; + } + /* + * [2] If type A not already throttled, and power still + * needed, limit type A. + */ + if (!(new_state & THROT_TYPE_A) && headroom_5v < 0) { + headroom_5v += PWR_FRONT_HIGH - PWR_FRONT_LOW; + new_state |= THROT_TYPE_A; + } + /* + * [3] If still under-budget, limit type C. + * No need to check if it is already throttled or not. + */ + if (headroom_5v < 0) + new_state |= THROT_TYPE_C; + } + /* + * Turn the throttles on or off if they have changed. + */ + diff = new_state ^ current_state; + current_state = new_state; + if (diff & THROT_PROCHOT) { + int prochot = (new_state & THROT_PROCHOT) ? 0 : 1; + + gpio_set_level(GPIO_EC_PROCHOT_ODL, prochot); + } + if (diff & THROT_TYPE_A) { + int typea_bc = (new_state & THROT_TYPE_A) ? 1 : 0; + + gpio_set_level(GPIO_USB_A_LOW_PWR_OD, typea_bc); + } + hook_call_deferred(&power_monitor_data, delay); +} diff --git a/board/scout/board.h b/board/scout/board.h new file mode 100644 index 0000000000..33f3cb758f --- /dev/null +++ b/board/scout/board.h @@ -0,0 +1,266 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Puff board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* NPCX7 config */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ + +/* Internal SPI flash on NPCX796FC is 512 kB */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) +#define CONFIG_SPI_FLASH_REGS +#define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */ + +/* EC Defines */ +#define CONFIG_ADC +#define CONFIG_BOARD_HAS_RTC_RESET +#define CONFIG_BOARD_VERSION_CBI +#define CONFIG_DEDICATED_RECOVERY_BUTTON +#define CONFIG_DEDICATED_RECOVERY_BUTTON_2 +#define CONFIG_BUTTONS_RUNTIME_CONFIG +#define CONFIG_BOARD_RESET_AFTER_POWER_ON +/* TODO: (b/143496253) re-enable CEC */ +/* #define CONFIG_CEC */ +#define CONFIG_CRC8 +#define CONFIG_CBI_EEPROM +#define CONFIG_EMULATED_SYSRQ +#undef CONFIG_KEYBOARD_BOOT_KEYS +#define CONFIG_MKBP_INPUT_DEVICES +#define CONFIG_MKBP_USE_HOST_EVENT +#undef CONFIG_KEYBOARD_RUNTIME_KEYS +#undef CONFIG_HIBERNATE +#define CONFIG_HOST_INTERFACE_ESPI +#define CONFIG_LED_COMMON +#undef CONFIG_LID_SWITCH +#define CONFIG_LTO +#define CONFIG_PWM +#define CONFIG_VBOOT_EFS2 +#define CONFIG_VBOOT_HASH +#define CONFIG_VSTORE +#define CONFIG_VSTORE_SLOT_COUNT 1 +#define CONFIG_SHA256 + +/* Sensor */ +#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US +#define CONFIG_MOTION_SENSE_RESUME_DELAY_US (1000 * MSEC) +#define CONFIG_CMD_ACCEL_INFO +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* TCS3400 ALS */ +#define CONFIG_ALS +#define ALS_COUNT 1 +#define CONFIG_ALS_TCS3400 +#define CONFIG_ALS_TCS3400_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(CLEAR_ALS) + +/* EC Commands */ +#define CONFIG_CMD_BUTTON +/* Include CLI command needed to support CCD testing. */ +#define CONFIG_CMD_CHARGEN +#undef CONFIG_CMD_FASTCHARGE +#undef CONFIG_CMD_KEYBOARD +#define CONFIG_HOSTCMD_PD_CONTROL +#undef CONFIG_CMD_PWR_AVG +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_CMD_TCPC_DUMP +#ifdef SECTION_IS_RO +/* Reduce RO size by removing less-relevant commands. */ +#undef CONFIG_CMD_APTHROTTLE +#undef CONFIG_CMD_CHARGEN +#undef CONFIG_CMD_HCDEBUG +#undef CONFIG_CMD_MMAPINFO +#endif + +#undef CONFIG_CONSOLE_CMDHELP + +/* Don't generate host command debug by default */ +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + +/* Enable AP Reset command for TPM with old firmware version to detect it. */ +#define CONFIG_CMD_AP_RESET_LOG +#define CONFIG_HOSTCMD_AP_RESET + +/* Chipset config */ +#define CONFIG_CHIPSET_COMETLAKE_DISCRETE +/* check */ +#define CONFIG_CHIPSET_CAN_THROTTLE +#define CONFIG_CHIPSET_RESET_HOOK +#define CONFIG_CPU_PROCHOT_ACTIVE_LOW + +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_IGNORE_LID +#define CONFIG_POWER_BUTTON_X86 +/* Check: */ +#define CONFIG_POWER_BUTTON_INIT_IDLE +#define CONFIG_POWER_COMMON +#define CONFIG_POWER_SIGNAL_INTERRUPT_STORM_DETECT_THRESHOLD 30 +#define CONFIG_DELAY_DSW_PWROK_TO_PWRBTN +#define CONFIG_POWER_PP5000_CONTROL +#define CONFIG_POWER_S0IX +#define CONFIG_POWER_SLEEP_FAILURE_DETECTION +#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE +#define CONFIG_INA3221 + +/* Fan and temp. */ +#define CONFIG_FANS 1 +#undef CONFIG_FAN_INIT_SPEED +#define CONFIG_FAN_INIT_SPEED 0 +#define CONFIG_FAN_RPM_CUSTOM +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B +#define CONFIG_THROTTLE_AP + +#define CONFIG_USB_PD_PORT_MAX_COUNT 0 + +/* USB Type A Features */ +#define CONFIG_USB_PORT_POWER_DUMB +/* There are five ports, but power enable is ganged across all of them. */ +#define USB_PORT_COUNT 1 + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define CONFIG_I2C_CONTROLLER +#define I2C_PORT_INA NPCX_I2C_PORT0_0 +#define I2C_PORT_PPC0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SCALER NPCX_I2C_PORT2_0 +#define I2C_PORT_SENSORS NPCX_I2C_PORT3_0 +#define I2C_PORT_TCPC0 NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define PP5000_PGOOD_POWER_SIGNAL_MASK POWER_SIGNAL_MASK(PP5000_A_PGOOD) + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum board_version { + BOARD_VERSION_PROTO = 1, + BOARD_VERSION_PRE_EVT = 2, + BOARD_VERSION_EVT = 3, + BOARD_VERSION_DVT = 4, + BOARD_VERSION_PVT = 5, +}; + +enum adc_channel { + ADC_SNS_PP3300, /* ADC2 */ + ADC_SNS_PP1050, /* ADC7 */ + ADC_VBUS, /* ADC4 */ + ADC_PPVAR_IMON, /* ADC9 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + /* Number of ADC channels */ + ADC_CH_COUNT +}; + +enum pwm_channel { + PWM_CH_FAN, + PWM_CH_LED_RED, + PWM_CH_LED_WHITE, + /* Number of PWM channels */ + PWM_CH_COUNT +}; + +enum fan_channel { + FAN_CH_0, + /* Number of FAN channels */ + FAN_CH_COUNT +}; + +enum mft_channel { + MFT_CH_0 = 0, + /* Number of MFT channels */ + MFT_CH_COUNT, +}; + +enum temp_sensor_id { TEMP_SENSOR_CORE, TEMP_SENSOR_WIFI, TEMP_SENSOR_COUNT }; + +enum sensor_id { + CLEAR_ALS, + RGB_ALS, + SENSOR_COUNT, +}; + +/* Board specific handlers */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); +void led_alert(int enable); +void show_critical_error(void); + +/* + * firmware config fields + */ +/* + * Barrel-jack power (4 bits). + */ +#define EC_CFG_BJ_POWER_L 0 +#define EC_CFG_BJ_POWER_H 3 +#define EC_CFG_BJ_POWER_MASK GENMASK(EC_CFG_BJ_POWER_H, EC_CFG_BJ_POWER_L) +/* + * USB Connector 4 not present (1 bit). + */ +#define EC_CFG_NO_USB4_L 4 +#define EC_CFG_NO_USB4_H 4 +#define EC_CFG_NO_USB4_MASK GENMASK(EC_CFG_NO_USB4_H, EC_CFG_NO_USB4_L) +/* + * Thermal solution config (3 bits). + */ +#define EC_CFG_THERMAL_L 5 +#define EC_CFG_THERMAL_H 7 +#define EC_CFG_THERMAL_MASK GENMASK(EC_CFG_THERMAL_H, EC_CFG_THERMAL_L) + +int ec_config_get_usb4_present(void); +unsigned int ec_config_get_thermal_solution(void); + +#endif /* !__ASSEMBLER__ */ + +/* Pin renaming */ +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_PP5000_A_PG_OD GPIO_PG_PP5000_A_OD +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL +#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_ROA_RAILS +#define GPIO_AC_PRESENT GPIO_BJ_ADP_PRESENT_L + +/* + * There is no RSMRST input, so alias it to the output. This short-circuits + * common_intel_x86_handle_rsmrst. + */ +#define GPIO_PG_EC_RSMRST_ODL GPIO_PCH_RSMRST_L + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/scout/build.mk b/board/scout/build.mk new file mode 100644 index 0000000000..7b9d891a0c --- /dev/null +++ b/board/scout/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc + +board-y=board.o +board-y+=led.o diff --git a/board/scout/ec.tasklist b/board/scout/ec.tasklist new file mode 100644 index 0000000000..0c3296d173 --- /dev/null +++ b/board/scout/ec.tasklist @@ -0,0 +1,16 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 2048) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/scout/gpio.inc b/board/scout/gpio.inc new file mode 100644 index 0000000000..8a6b5bb074 --- /dev/null +++ b/board/scout/gpio.inc @@ -0,0 +1,172 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Pin names follow the schematic, and are aliased to other names if necessary. + * Note: Those with interrupt handlers must be declared first. */ + +/* Latency on this interrupt is extremely critical, so it comes first to ensure + * it gets placed first in gpio_wui_table so gpio_interrupt() needs to do + * minimal scanning. */ +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, c10_gate_interrupt) + +/* Wake Source interrupts */ +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(PG_PP5000_A_OD, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1800_A_OD, PIN(3, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VPRIM_CORE_A_OD, PIN(2, 3), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1050_A_OD, PIN(2, 2), GPIO_INT_BOTH, power_signal_interrupt) +/* EC output, but also interrupt so this can be polled as a power signal */ +GPIO_INT(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUTPUT | GPIO_INT_F_RISING | GPIO_INT_F_FALLING, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(PG_PP2500_DRAM_U_OD, PIN(2, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_PP1200_U_OD, PIN(2, 1), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, slp_s3_interrupt) +#endif +GPIO_INT(PG_PP950_VCCIO_OD, PIN(1, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(IMVP8_VRRDY_OD, PIN(1, 6), GPIO_INT_BOTH, power_signal_interrupt) +/* ALS signals */ +GPIO_INT(EC_RGB_INT_L, PIN(9, 7), GPIO_INT_FALLING, tcs3400_interrupt) +/* + * Directly connected recovery button (not available on some boards). + */ +GPIO_INT(EC_RECOVERY_BTN_ODL, PIN(F, 1), GPIO_INT_BOTH, button_interrupt) +/* + * Recovery button input from H1. + */ +GPIO_INT(H1_EC_RECOVERY_BTN_ODL, PIN(2, 4), GPIO_INT_BOTH, button_interrupt) +GPIO(BJ_ADP_PRESENT_L, PIN(8, 2), GPIO_INT_BOTH | GPIO_PULL_UP) + +/* Port power control interrupts */ +GPIO_INT(HDMI_CONN0_OC_ODL, PIN(0, 7), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(HDMI_CONN1_OC_ODL, PIN(0, 6), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A0_OC_ODL, PIN(E, 4), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A1_OC_ODL, PIN(A, 2), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A2_OC_ODL, PIN(F, 5), GPIO_INT_BOTH, port_ocp_interrupt) +GPIO_INT(USB_A3_OC_ODL, PIN(0, 3), GPIO_INT_BOTH, port_ocp_interrupt) + +/* PCH/CPU signals */ +GPIO(EC_PCH_PWROK, PIN(0, 5), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_IN_OD, PIN(3, 4), GPIO_INPUT) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +/* i.MX8 soundbar signals */ +GPIO(BOOT_IND_EC, PIN(E, 2), GPIO_INPUT) + +/* TSUM scaler signals */ +GPIO(TSUM_WAKEUP_EC, PIN(B, 1), GPIO_INPUT) + +/* Power control outputs */ +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PP3300_INA_H1_EC_ODL, PIN(5, 7), GPIO_ODR_HIGH) +GPIO(EN_PP1800_A, PIN(1, 5), GPIO_OUT_LOW) +GPIO(VCCST_PG_OD, PIN(1, 4), GPIO_ODR_LOW) +GPIO(EN_S0_RAILS, PIN(1, 1), GPIO_OUT_LOW) +GPIO(EN_ROA_RAILS, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP950_VCCIO, PIN(1, 0), GPIO_OUT_LOW) +GPIO(EC_IMVP8_PE, PIN(A, 7), GPIO_OUT_LOW) +GPIO(EN_IMVP8_VR, PIN(F, 4), GPIO_OUT_LOW) +GPIO(EC_CAM_V3P3_EN, PIN(C, 6), GPIO_OUT_LOW) +GPIO(EC_MX8M_ONOFF, PIN(9, 3), GPIO_OUT_LOW) +GPIO(EC_SCALER_EN, PIN(E, 0), GPIO_OUT_LOW) +GPIO(EC_IMX8_EN, PIN(C, 0), GPIO_OUT_LOW) +GPIO(PP3300_TPU_A_EN, PIN(B, 0), GPIO_OUT_LOW) +GPIO(PWR_CTRL, PIN(6, 2), GPIO_OUT_LOW) +GPIO(EN_LOAD_SWITCH, PIN(4, 2), GPIO_OUT_LOW) + +/* Barreljack */ +GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 4), GPIO_OUT_LOW) + +/* USB type A */ +GPIO(EN_PP5000_USB_VBUS, PIN(8, 3), GPIO_OUT_LOW) +GPIO(USB_A_LOW_PWR_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(USB_A2_STATUS_L, PIN(6, 1), GPIO_INPUT) +GPIO(USB_A3_STATUS_L, PIN(C, 7), GPIO_INPUT) + +/* USB type C */ +GPIO(USB_C0_POL_L, PIN(0, 0), GPIO_INPUT | GPIO_SEL_1P8V) /* USB-C Polarity */ + +/* Misc. */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) +GPIO(PACKET_MODE_EN, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EN_PP_MST_OD, PIN(9, 6), GPIO_OUT_HIGH) +GPIO(EC_MIC_OE, PIN(6, 0), GPIO_OUT_HIGH) + +/* HDMI/CEC */ +GPIO(EN_PP5000_HDMI, PIN(5, 0), GPIO_OUT_LOW) +GPIO(HDMI_CONN0_CEC_IN, PIN(4, 0), GPIO_INPUT) +GPIO(HDMI_CONN1_CEC_OUT, PIN(9, 5), GPIO_ODR_HIGH) +GPIO(HDMI_CONN1_CEC_IN, PIN(D, 3), GPIO_INPUT) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(I2C0_SCL, PIN(B, 5), GPIO_INPUT) /* EC_I2C_INA_SCL */ +GPIO(I2C0_SDA, PIN(B, 4), GPIO_INPUT) /* EC_I2C_INA_SDA */ +GPIO(I2C1_SCL, PIN(9, 0), GPIO_INPUT) /* EC_I2C_USB_C0_TCPPC_SCL */ +GPIO(I2C1_SDA, PIN(8, 7), GPIO_INPUT) /* EC_I2C_USB_C0_TCPPC_SDA */ +GPIO(I2C2_SCL, PIN(9, 2), GPIO_INPUT) /* EC_I2C_DDR_SCALER_SCL */ +GPIO(I2C2_SDA, PIN(9, 1), GPIO_INPUT) /* EC_I2C_DDR_SCALER_SDA */ +GPIO(I2C3_SCL, PIN(D, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* EC_I2C_ALS_SCL */ +GPIO(I2C3_SDA, PIN(D, 0), GPIO_INPUT | GPIO_SEL_1P8V) /* EC_I2C_ALS_SDA */ +GPIO(I2C5_SCL, PIN(3, 3), GPIO_INPUT) /* EC_I2C_IMVP8_SCL */ +GPIO(I2C5_SDA, PIN(3, 6), GPIO_INPUT) /* EC_I2C_IMVP8_SDA */ +GPIO(I2C7_SCL, PIN(B, 3), GPIO_INPUT) /* EC_I2C_EEPROM_SCL */ +GPIO(I2C7_SDA, PIN(B, 2), GPIO_INPUT) /* EC_I2C_EEPROM_SDA */ + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(9, 0x01), 0, MODULE_I2C, 0) /* I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(9, 0x03), 0, MODULE_I2C, 0) /* I2C2 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, 0x0C), 0, MODULE_I2C, 0) /* I2C7 */ + +/* PWM */ +ALTERNATE(PIN_MASK(C, 0x08), 0, MODULE_PWM, 0) /* PWM0 - Red Led */ +ALTERNATE(PIN_MASK(C, 0x10), 0, MODULE_PWM, 0) /* PWM2 - White Led */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* PWM5 - Fan 1 */ +ALTERNATE(PIN_MASK(7, 0x08), 0, MODULE_PWM, 0) /* TA2 - Fan Tachometer */ + +/* ADC */ +ALTERNATE(PIN_MASK(4, 0x3A), 0, MODULE_ADC, 0) /* ADC0, ADC1, ADC2, ADC4 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* ADC7 */ +ALTERNATE(PIN_MASK(F, 0x01), 0, MODULE_ADC, 0) /* ADC9 */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Unused pins */ +UNUSED(PIN(1, 3)) /* EC_GP_SEL1_ODL */ +UNUSED(PIN(8, 0)) /* LED_BLUE_L */ +UNUSED(PIN(C, 2)) /* A12 NC */ +UNUSED(PIN(1, 2)) /* C6 NC */ +UNUSED(PIN(6, 6)) /* H4 NC */ +UNUSED(PIN(8, 1)) /* L6 NC */ +UNUSED(PIN(8, 5)) /* L7 NC */ +UNUSED(PIN(3, 2)) /* E5 NC */ +UNUSED(PIN(D, 6)) /* F6 NC */ +UNUSED(PIN(3, 5)) /* F5 NC */ +UNUSED(PIN(5, 6)) /* M2 NC */ +UNUSED(PIN(D, 2)) /* C11 NC */ +UNUSED(PIN(8, 6)) /* J8 NC */ +UNUSED(PIN(7, 2)) /* H6 NC */ +UNUSED(PIN(F, 2)) /* E11 NC */ +UNUSED(PIN(F, 3)) /* F7 NC */ diff --git a/board/scout/led.c b/board/scout/led.c new file mode 100644 index 0000000000..ad244ab99e --- /dev/null +++ b/board/scout/led.c @@ -0,0 +1,284 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power LED control for Puff. + * Solid green - active power + * Green flashing - suspended + * Red flashing - alert + * Solid red - critical + */ + +#include "chipset.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_WHITE, + LED_AMBER, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +static int set_color_power(enum led_color color, int duty) +{ + int white = 0; + int red = 0; + + if (duty < 0 || 100 < duty) + return EC_ERROR_UNKNOWN; + + switch (color) { + case LED_OFF: + break; + case LED_WHITE: + white = 1; + break; + case LED_RED: + red = 1; + break; + case LED_AMBER: + red = 1; + white = 1; + break; + default: + return EC_ERROR_UNKNOWN; + } + + if (red) + pwm_set_duty(PWM_CH_LED_RED, duty); + else + pwm_set_duty(PWM_CH_LED_RED, 0); + + if (white) + pwm_set_duty(PWM_CH_LED_WHITE, duty); + else + pwm_set_duty(PWM_CH_LED_WHITE, 0); + + return EC_SUCCESS; +} + +static int set_color(enum ec_led_id id, enum led_color color, int duty) +{ + switch (id) { + case EC_LED_ID_POWER_LED: + return set_color_power(color, duty); + default: + return EC_ERROR_UNKNOWN; + } +} + +#define LED_PULSE_US (2 * SECOND) +/* 40 msec for nice and smooth transition. */ +#define LED_PULSE_TICK_US (40 * MSEC) + +/* When pulsing is enabled, brightness is incremented by every + * usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented + * likewise in LED_PULSE_US usec. + */ +static struct { + uint32_t interval; + int duty_inc; + enum led_color color; + int duty; +} led_pulse; + +#define CONFIG_TICK(interval, color) \ + config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color)) + +static void config_tick(uint32_t interval, int duty_inc, enum led_color color) +{ + led_pulse.interval = interval; + led_pulse.duty_inc = duty_inc; + led_pulse.color = color; + led_pulse.duty = 0; +} + +static void pulse_power_led(enum led_color color) +{ + set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty); + if (led_pulse.duty + led_pulse.duty_inc > 100) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + else if (led_pulse.duty + led_pulse.duty_inc < 0) + led_pulse.duty_inc = led_pulse.duty_inc * -1; + led_pulse.duty += led_pulse.duty_inc; +} + +static void led_tick(void); +DECLARE_DEFERRED(led_tick); +static void led_tick(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + pulse_power_led(led_pulse.color); + elapsed = get_time().le.lo - start; + next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0; + hook_call_deferred(&led_tick_data, next); +} + +static void led_suspend(void) +{ + CONFIG_TICK(LED_PULSE_TICK_US, LED_WHITE); + led_tick(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_tick_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_resume(void) +{ + /* Assume there is no race condition with led_tick, which also + * runs in hook_task. + */ + hook_call_deferred(&led_tick_data, -1); + /* + * Avoid invoking the suspend/shutdown delayed hooks. + */ + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_WHITE, 100); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT); + +static void led_init(void) +{ + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_WHITE, 1); + + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + led_suspend(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown(); +} +DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_INIT_PWM + 1); + +void board_led_auto_control(void) +{ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); +} + +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + config_tick(1 * SECOND, 100, LED_RED); + led_tick(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +void show_critical_error(void) +{ + hook_call_deferred(&led_tick_data, -1); + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + set_color(EC_LED_ID_POWER_LED, LED_RED, 100); +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + set_color(id, LED_OFF, 0); + } else if (!strcasecmp(argv[1], "red")) { + set_color(id, LED_RED, 100); + } else if (!strcasecmp(argv[1], "white")) { + set_color(id, LED_WHITE, 100); + } else if (!strcasecmp(argv[1], "amber")) { + set_color(id, LED_AMBER, 100); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, + "[debug|red|white|amber|off|alert|crit]", + "Turn on/off LED."); + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; + brightness_range[EC_LED_COLOR_AMBER] = 100; +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]); + else if (brightness[EC_LED_COLOR_WHITE]) + return set_color(id, LED_WHITE, brightness[EC_LED_COLOR_WHITE]); + else if (brightness[EC_LED_COLOR_AMBER]) + return set_color(id, LED_AMBER, brightness[EC_LED_COLOR_AMBER]); + else + return set_color(id, LED_OFF, 0); +} diff --git a/board/servo_micro/OWNERS b/board/servo_micro/OWNERS new file mode 100644 index 0000000000..3a4b8d3c05 --- /dev/null +++ b/board/servo_micro/OWNERS @@ -0,0 +1,2 @@ +bnemec@google.com +matthewb@chromium.org diff --git a/board/servo_micro/board.c b/board/servo_micro/board.c index 6bbbd85c84..5f8bf1066f 100644 --- a/board/servo_micro/board.c +++ b/board/servo_micro/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,14 +19,15 @@ #include "timer.h" #include "update_fw.h" #include "usart-stm32f0.h" -#include "usart_tx_dma.h" #include "usart_rx_dma.h" +#include "usart_tx_dma.h" +#include "usb-stream.h" #include "usb_hw.h" #include "usb_i2c.h" #include "usb_spi.h" -#include "usb-stream.h" #include "util.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" void board_config_pre_init(void) @@ -45,21 +46,20 @@ void board_config_pre_init(void) * i2c : no dma * tim16/17: no dma */ - STM32_SYSCFG_CFGR1 |= BIT(26); /* Remap USART3 RX/TX DMA */ + STM32_SYSCFG_CFGR1 |= BIT(26); /* Remap USART3 RX/TX DMA */ /* Remap SPI2 to DMA channels 6 and 7 */ /* STM32F072 SPI2 defaults to using DMA channels 4 and 5 */ /* but cros_ec hardcodes a 6/7 assumption in registers.h */ STM32_SYSCFG_CFGR1 |= BIT(24); - } /****************************************************************************** * Forward UARTs as a USB serial interface. */ -#define USB_STREAM_RX_SIZE 32 -#define USB_STREAM_TX_SIZE 64 +#define USB_STREAM_RX_SIZE 32 +#define USB_STREAM_TX_SIZE 64 /****************************************************************************** * Forward USART2 (EC) as a simple USB serial interface. @@ -68,33 +68,22 @@ void board_config_pre_init(void) static struct usart_config const usart2; struct usb_stream_config const usart2_usb; -static struct queue const usart2_to_usb = QUEUE_DIRECT(1024, uint8_t, - usart2.producer, usart2_usb.consumer); -static struct queue const usb_to_usart2 = QUEUE_DIRECT(64, uint8_t, - usart2_usb.producer, usart2.consumer); +static struct queue const usart2_to_usb = + QUEUE_DIRECT(1024, uint8_t, usart2.producer, usart2_usb.consumer); +static struct queue const usb_to_usart2 = + QUEUE_DIRECT(64, uint8_t, usart2_usb.producer, usart2.consumer); static struct usart_rx_dma const usart2_rx_dma = USART_RX_DMA(STM32_DMAC_CH5, 32); static struct usart_config const usart2 = - USART_CONFIG(usart2_hw, - usart2_rx_dma.usart_rx, - usart_tx_interrupt, - 115200, - 0, - usart2_to_usb, - usb_to_usart2); - -USB_STREAM_CONFIG_USART_IFACE(usart2_usb, - USB_IFACE_USART2_STREAM, - USB_STR_USART2_STREAM_NAME, - USB_EP_USART2_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart2, - usart2_to_usb, - usart2) + USART_CONFIG(usart2_hw, usart2_rx_dma.usart_rx, usart_tx_interrupt, + 115200, 0, usart2_to_usb, usb_to_usart2); +USB_STREAM_CONFIG_USART_IFACE(usart2_usb, USB_IFACE_USART2_STREAM, + USB_STR_USART2_STREAM_NAME, USB_EP_USART2_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, + usb_to_usart2, usart2_to_usb, usart2) /****************************************************************************** * Forward USART3 (CPU) as a simple USB serial interface. @@ -103,33 +92,22 @@ USB_STREAM_CONFIG_USART_IFACE(usart2_usb, static struct usart_config const usart3; struct usb_stream_config const usart3_usb; -static struct queue const usart3_to_usb = QUEUE_DIRECT(1024, uint8_t, - usart3.producer, usart3_usb.consumer); -static struct queue const usb_to_usart3 = QUEUE_DIRECT(64, uint8_t, - usart3_usb.producer, usart3.consumer); +static struct queue const usart3_to_usb = + QUEUE_DIRECT(1024, uint8_t, usart3.producer, usart3_usb.consumer); +static struct queue const usb_to_usart3 = + QUEUE_DIRECT(64, uint8_t, usart3_usb.producer, usart3.consumer); static struct usart_rx_dma const usart3_rx_dma = USART_RX_DMA(STM32_DMAC_CH3, 32); static struct usart_config const usart3 = - USART_CONFIG(usart3_hw, - usart3_rx_dma.usart_rx, - usart_tx_interrupt, - 115200, - 0, - usart3_to_usb, - usb_to_usart3); - -USB_STREAM_CONFIG_USART_IFACE(usart3_usb, - USB_IFACE_USART3_STREAM, - USB_STR_USART3_STREAM_NAME, - USB_EP_USART3_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart3, - usart3_to_usb, - usart3) + USART_CONFIG(usart3_hw, usart3_rx_dma.usart_rx, usart_tx_interrupt, + 115200, 0, usart3_to_usb, usb_to_usart3); +USB_STREAM_CONFIG_USART_IFACE(usart3_usb, USB_IFACE_USART3_STREAM, + USB_STR_USART3_STREAM_NAME, USB_EP_USART3_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, + usb_to_usart3, usart3_to_usb, usart3) /****************************************************************************** * Forward USART4 (cr50) as a simple USB serial interface. @@ -139,34 +117,24 @@ USB_STREAM_CONFIG_USART_IFACE(usart3_usb, static struct usart_config const usart4; struct usb_stream_config const usart4_usb; -static struct queue const usart4_to_usb = QUEUE_DIRECT(64, uint8_t, - usart4.producer, usart4_usb.consumer); -static struct queue const usb_to_usart4 = QUEUE_DIRECT(64, uint8_t, - usart4_usb.producer, usart4.consumer); +static struct queue const usart4_to_usb = + QUEUE_DIRECT(1024, uint8_t, usart4.producer, usart4_usb.consumer); +static struct queue const usb_to_usart4 = + QUEUE_DIRECT(64, uint8_t, usart4_usb.producer, usart4.consumer); static struct usart_config const usart4 = - USART_CONFIG(usart4_hw, - usart_rx_interrupt, - usart_tx_interrupt, - 115200, - 0, - usart4_to_usb, - usb_to_usart4); - -USB_STREAM_CONFIG_USART_IFACE(usart4_usb, - USB_IFACE_USART4_STREAM, - USB_STR_USART4_STREAM_NAME, - USB_EP_USART4_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart4, - usart4_to_usb, - usart4) + USART_CONFIG(usart4_hw, usart_rx_interrupt, usart_tx_interrupt, 115200, + 0, usart4_to_usb, usb_to_usart4); + +USB_STREAM_CONFIG_USART_IFACE(usart4_usb, USB_IFACE_USART4_STREAM, + USB_STR_USART4_STREAM_NAME, USB_EP_USART4_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, + usb_to_usart4, usart4_to_usb, usart4) /****************************************************************************** * Check parity setting on usarts. */ -static int command_uart_parity(int argc, char **argv) +static int command_uart_parity(int argc, const char **argv) { int parity = 0, newparity; struct usart_config const *usart; @@ -200,14 +168,13 @@ static int command_uart_parity(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(parity, command_uart_parity, - "usart[2|3|4] [0|1|2]", +DECLARE_CONSOLE_COMMAND(parity, command_uart_parity, "usart[2|3|4] [0|1|2]", "Set parity on uart"); /****************************************************************************** * Set baud rate setting on usarts. */ -static int command_uart_baud(int argc, char **argv) +static int command_uart_baud(int argc, const char **argv) { int baud = 0; struct usart_config const *usart; @@ -233,14 +200,13 @@ static int command_uart_baud(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(baud, command_uart_baud, - "usart[2|3|4] rate", +DECLARE_CONSOLE_COMMAND(baud, command_uart_baud, "usart[2|3|4] rate", "Set baud rate on uart"); /****************************************************************************** * Hold the usart pins low while disabling it, or return it to normal. */ -static int command_hold_usart_low(int argc, char **argv) +static int command_hold_usart_low(int argc, const char **argv) { /* Each bit represents if that port rx is being held low */ static int usart_status; @@ -297,7 +263,7 @@ static int command_hold_usart_low(int argc, char **argv) /* Print status for get and set case. */ ccprintf("USART status: %s\n", - usart_status & usart_mask ? "held low" : "normal"); + usart_status & usart_mask ? "held low" : "normal"); return EC_SUCCESS; } @@ -309,17 +275,18 @@ DECLARE_CONSOLE_COMMAND(hold_usart_low, command_hold_usart_low, * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("Servo Micro"), - [USB_STR_SERIALNO] = 0, - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), - [USB_STR_USART4_STREAM_NAME] = USB_STRING_DESC("UART3"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Servo Micro"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_SPI_NAME] = USB_STRING_DESC("SPI"), + [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), + [USB_STR_USART4_STREAM_NAME] = USB_STRING_DESC("UART3"), [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Servo Shell"), - [USB_STR_USART3_STREAM_NAME] = USB_STRING_DESC("CPU"), - [USB_STR_USART2_STREAM_NAME] = USB_STRING_DESC("EC"), - [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), + [USB_STR_USART3_STREAM_NAME] = USB_STRING_DESC("CPU"), + [USB_STR_USART2_STREAM_NAME] = USB_STRING_DESC("EC"), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); @@ -331,11 +298,11 @@ BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); /* SPI devices */ const struct spi_device_t spi_devices[] = { - { CONFIG_SPI_FLASH_PORT, 1, GPIO_SPI_CS}, + { CONFIG_SPI_FLASH_PORT, 1, GPIO_SPI_CS, USB_SPI_ENABLED }, }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); -void usb_spi_board_enable(struct usb_spi_config const *config) +void usb_spi_board_enable(void) { /* Configure SPI GPIOs */ gpio_config_module(MODULE_SPI_FLASH, 1); @@ -350,12 +317,12 @@ void usb_spi_board_enable(struct usb_spi_config const *config) STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(&spi_devices[0], 1); } -void usb_spi_board_disable(struct usb_spi_config const *config) +void usb_spi_board_disable(void) { - spi_enable(CONFIG_SPI_FLASH_PORT, 0); + spi_enable(&spi_devices[0], 0); /* Disable clocks to SPI2 module */ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; @@ -364,20 +331,24 @@ void usb_spi_board_disable(struct usb_spi_config const *config) gpio_config_module(MODULE_SPI_FLASH, 0); } -USB_SPI_CONFIG(usb_spi, USB_IFACE_SPI, USB_EP_SPI, 0); - /****************************************************************************** * Support I2C bridging over USB. */ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + { .name = "master", + .port = I2C_PORT_MASTER, + .kbps = 100, + .scl = GPIO_MASTER_I2C_SCL, + .sda = GPIO_MASTER_I2C_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -int usb_i2c_board_is_enabled(void) { return 1; } +int usb_i2c_board_is_enabled(void) +{ + return 1; +} /* Configure ITE flash support module */ const struct ite_dfu_config_t ite_dfu_config = { @@ -407,8 +378,8 @@ static void board_init(void) /* Enable GPIO expander. */ gpio_set_level(GPIO_TCA6416_RESET_L, 1); - /* Structured enpoints */ - usb_spi_enable(&usb_spi, 1); + /* Structured endpoints */ + usb_spi_enable(1); /* Enable UARTs by default. */ gpio_set_level(GPIO_UART1_EN_L, 0); @@ -445,6 +416,6 @@ static void board_jump(void) usart_shutdown(&usart4); /* Shutdown other hardware modules and let RW reinitialize them */ - usb_spi_enable(&usb_spi, 0); + usb_spi_enable(0); } DECLARE_HOOK(HOOK_SYSJUMP, board_jump, HOOK_PRIO_DEFAULT); diff --git a/board/servo_micro/board.h b/board/servo_micro/board.h index 50e6910811..109a40409d 100644 --- a/board/servo_micro/board.h +++ b/board/servo_micro/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -30,12 +30,12 @@ #undef CONFIG_UART_RX_DMA /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_HW_CRC #define CONFIG_PVD -/* See 'Programmable voltage detector characteristics' in the STM32F072x8 Datasheet. - PVD Threshold 1 corresponds to a falling voltage threshold of min:2.09V, max:2.27V. */ -#define PVD_THRESHOLD (1) +/* See 'Programmable voltage detector characteristics' in the STM32F072x8 + Datasheet. PVD Threshold 1 corresponds to a falling voltage threshold of + min:2.09V, max:2.27V. */ +#define PVD_THRESHOLD (1) /* USB Configuration */ #define CONFIG_USB @@ -50,33 +50,33 @@ #define DEFAULT_SERIALNO "Uninitialized" /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_USART4_STREAM 0 -#define USB_IFACE_UPDATE 1 -#define USB_IFACE_SPI 2 -#define USB_IFACE_CONSOLE 3 -#define USB_IFACE_I2C 4 -#define USB_IFACE_USART3_STREAM 5 -#define USB_IFACE_USART2_STREAM 6 -#define USB_IFACE_COUNT 7 +#define USB_IFACE_USART4_STREAM 0 +#define USB_IFACE_UPDATE 1 +#define USB_IFACE_SPI 2 +#define USB_IFACE_CONSOLE 3 +#define USB_IFACE_I2C 4 +#define USB_IFACE_USART3_STREAM 5 +#define USB_IFACE_USART2_STREAM 6 +#define USB_IFACE_COUNT 7 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_USART4_STREAM 1 -#define USB_EP_UPDATE 2 -#define USB_EP_SPI 3 -#define USB_EP_CONSOLE 4 -#define USB_EP_I2C 5 -#define USB_EP_USART3_STREAM 6 -#define USB_EP_USART2_STREAM 7 -#define USB_EP_COUNT 8 +#define USB_EP_CONTROL 0 +#define USB_EP_USART4_STREAM 1 +#define USB_EP_UPDATE 2 +#define USB_EP_SPI 3 +#define USB_EP_CONSOLE 4 +#define USB_EP_I2C 5 +#define USB_EP_USART3_STREAM 6 +#define USB_EP_USART2_STREAM 7 +#define USB_EP_COUNT 8 /* Enable console recasting of GPIO type. */ #define CONFIG_CMD_GPIO_EXTENDED /* Enable control of SPI over USB */ #define CONFIG_USB_SPI -#define CONFIG_SPI_MASTER -#define CONFIG_SPI_FLASH_PORT 0 /* First SPI master port */ +#define CONFIG_SPI_CONTROLLER +#define CONFIG_SPI_FLASH_PORT 0 /* First SPI controller port */ /* This is not actually an EC so disable some features. */ #undef CONFIG_WATCHDOG_HELP @@ -85,16 +85,16 @@ /* Enable control of I2C over USB */ #define CONFIG_USB_I2C #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define I2C_PORT_MASTER 0 /* See i2c_ite_flash_support.c for more information about these values */ #define CONFIG_ITE_FLASH_SUPPORT -#define CONFIG_I2C_XFER_LARGE_READ +#define CONFIG_I2C_XFER_LARGE_TRANSFER #undef CONFIG_USB_I2C_MAX_WRITE_COUNT #undef CONFIG_USB_I2C_MAX_READ_COUNT -#define CONFIG_USB_I2C_MAX_WRITE_COUNT ((1<<9) - 4) -#define CONFIG_USB_I2C_MAX_READ_COUNT ((1<<9) - 6) +#define CONFIG_USB_I2C_MAX_WRITE_COUNT ((1 << 9) - 4) +#define CONFIG_USB_I2C_MAX_READ_COUNT ((1 << 9) - 6) /* * Allow dangerous commands all the time, since we don't have a write protect @@ -120,6 +120,7 @@ enum usb_strings { USB_STR_PRODUCT, USB_STR_SERIALNO, USB_STR_VERSION, + USB_STR_SPI_NAME, USB_STR_I2C_NAME, USB_STR_USART4_STREAM_NAME, USB_STR_CONSOLE_NAME, diff --git a/board/servo_micro/build.mk b/board/servo_micro/build.mk index 0e069a31ad..7ac70706fc 100644 --- a/board/servo_micro/build.mk +++ b/board/servo_micro/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/servo_micro/ccd.md b/board/servo_micro/ccd.md index acb82adb94..2398e1dd46 100644 --- a/board/servo_micro/ccd.md +++ b/board/servo_micro/ccd.md @@ -1,35 +1,36 @@ # Case-Closed Debug in Chromebooks and Servo Micro -The Servo debug/test-automation connector has been required on all -chromebooks. It has proved essential to performing the required testing to meet -the six week OS release cycle, for bringing up new systems and qualifying new -components. In newer form-factors it is becoming hard to fit the Servo connector -(and related flex) and in some designs the thermal solution stops working when -the connector is used. The secure Case-Closed Debugging solution provides the -same capabilities and can take advantage of the Debug Mode detection available -on the USB-C connector. This application note gives an overview of Case-Closed -Debug (CCD) but does not address the related security issues. - +The Servo debug/test-automation connector has been required on all chromebooks. +It has proved essential to performing the required testing to meet the six week +OS release cycle, for bringing up new systems and qualifying new components. In +newer form-factors it is becoming hard to fit the Servo connector (and related +flex) and in some designs the thermal solution stops working when the connector +is used. The secure Case-Closed Debugging solution provides the same +capabilities and can take advantage of the Debug Mode detection available on the +USB-C connector. This application note gives an overview of Case-Closed Debug +(CCD) but does not address the related security issues. ## Introduction to Case-Closed Debug -Case-Closed Debug provides the same set of features as are available on the Servo connector: +Case-Closed Debug provides the same set of features as are available on the +Servo connector: * Access to console UART connections to AP, EC and on some systems a third MCU * Ability to reprogram firmware/BIOS SPI flash used by the AP * Ability to reprogram SPI flash used by the EC or use a firmware update mode to reprogram the internal flash on the EC (using UART or I2C) * GPIOs for holding the EC (and thus entire system) or AP in reset -* Act as master on a debug I2C that is primarily used for power - measurements. This bus normally contains INA voltage/current monitors and - temperature monitors that will not be populated on final MP systems. -* JTAG/SWD could be provided but has not been implemented on any existing system. +* Act as master on a debug I2C that is primarily used for power measurements. + This bus normally contains INA voltage/current monitors and temperature + monitors that will not be populated on final MP systems. +* JTAG/SWD could be provided but has not been implemented on any existing + system. When the Servo connector is used these interfaces are presented on well defined pins of the board-to-board connector and a flex is used to attach to the @@ -43,7 +44,6 @@ be used for the debug USB while the main link on the connector continues to be available. (The SBU pins are also used by some Alternate Modes, so the connector cannot be used for video out at the same time as debugging.) - ## Servo Micro: Using CCD with existing boards The Servo Micro implements the CCD functions in a way that can connect to @@ -60,8 +60,8 @@ original Servo connector, but on some designs) can be connected to either the JTAG pins or the SPI pins. It is capable of providing the SPI flash supply voltages. -The schematics for Servo Micro are available [as a -pdf](servo_micro_sch_20180404.pdf). +The schematics for Servo Micro are available +[as a pdf](servo_micro_sch_20180404.pdf). Servo Micro has a USB micro-B connector and acts as a USB device. @@ -75,8 +75,8 @@ UART connection on CN2. Schematic sheet 3 shows the I2C GPIO expander and the buffers for JTAG/SWD. The buffers adapt to the voltage needed on the DUT that is provided on -`PPDUT_JTAG_VREF`. In the SWD case the TDI becomes the bidirectional SWDIO but the -STM32 continues to use a discrete input and output pin. The DUT signal is +`PPDUT_JTAG_VREF`. In the SWD case the TDI becomes the bidirectional SWDIO but +the STM32 continues to use a discrete input and output pin. The DUT signal is received through U55 and a selection made with U1 to determine if to forward TDO from the DUT or the TDI/SWDIO. Because of the shared pins on the STM32 the JTAG interface can alternatively be used to connect UART3 to the DUT for a few @@ -103,26 +103,23 @@ load switches are carefully selected to have reverse blocking (protecting against a DUT providing a voltage or both being enabled). The code for the STM32 in Servo Micro is open source as the -[`servo_micro`](../../board/servo_micro) -board in the [Chromium EC -codebase](https://chromium.googlesource.com/chromiumos/platform/ec/). Essentially -it is a USB device that provides the standard control endpoint and 7 function -endpoints defined in -[`board.h`](board.h). +[`servo_micro`](../../board/servo_micro) board in the +[Chromium EC codebase](https://chromium.googlesource.com/chromiumos/platform/ec/). +Essentially it is a USB device that provides the standard control endpoint and 7 +function endpoints defined in [`board.h`](board.h). -``` c - #define USB_EP_USART4_STREAM 1 - #define USB_EP_UPDATE 2 - #define USB_EP_SPI 3 - #define USB_EP_CONSOLE 4 - #define USB_EP_I2C 5 - #define USB_EP_USART3_STREAM 6 - #define USB_EP_USART2_STREAM 7 +```c +#define USB_EP_USART4_STREAM 1 +#define USB_EP_UPDATE 2 +#define USB_EP_SPI 3 +#define USB_EP_CONSOLE 4 +#define USB_EP_I2C 5 +#define USB_EP_USART3_STREAM 6 +#define USB_EP_USART2_STREAM 7 ``` - The USART endpoints use the simple `GOOGLE_SERIAL` vendor class to connect the STM32 UARTs. The CONSOLE endpoint also uses `GOOGLE_STREAM` to connect to the console of the code running on the STM32. `GOOGLE_STREAM` provides simple byte @@ -131,32 +128,27 @@ standard Linux `drivers/usb/serial/usb-serial-simple.c` The SPI endpoint is described in [`chip/stm32/usb_spi.h`](../../chip/stm32/usb_spi.h) and provides a simple -connection to the SPI port. The host support is provided as a [driver in -flashrom](https://chromium.googlesource.com/chromiumos/third_party/flashrom/+/master/raiden_debug_spi.c). +connection to the SPI port. The host support is provided as a +[driver in flashrom](https://chromium.googlesource.com/chromiumos/third_party/flashrom/+/HEAD/raiden_debug_spi.c). The I2C endpoint is described in [`include/usb_i2c.h`](../../include/usb_i2c.h) and provides a simple connection to the I2C bus. The host support is provided in -the [hdctools servo -support](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/servo/stm32i2c.py). +the +[hdctools servo support](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/servo/stm32i2c.py). The GPIO endpoint is cryptically described in -[`chip/stm32/usb_gpio.h`](../../chip/stm32/usb_gpio.h) and provides simple access -to set/clear and read the GPIO pins. The host support is provided in the -[hdctools servo -support](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/servo/stm32gpio.py). +[`chip/stm32/usb_gpio.h`](../../chip/stm32/usb_gpio.h) and provides simple +access to set/clear and read the GPIO pins. The host support is provided in the +[hdctools servo support](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/servo/stm32gpio.py). The UPDATE endpoint is not part of CCD. It provides a method for updating the -STM32 without needing the special boot modes. This uses the [Chromium EC update -over -USB](../../docs/usb_updater.md) -method. The STM32 runs the code in -[`common/usb_update.c`](../../common/usb_update.c). -The host side code is in -[`extra/usb_updater/usb_updater2.c`](../../extra/usb_updater/usb_updater2.c) -and the -[`extra/usb_updater`](../../extra/usb_updater/) -directory contains additional scripts. - +STM32 without needing the special boot modes. This uses the +[Chromium EC update over USB](../../docs/usb_updater.md) method. The STM32 runs +the code in [`common/usb_update.c`](../../common/usb_update.c). The host side +code is in +[`extra/usb_updater/usb_updater2.c`](../../extra/usb_updater/usb_updater2.c) and +the [`extra/usb_updater`](../../extra/usb_updater/) directory contains +additional scripts. ## Using CCD on new designs diff --git a/board/servo_micro/ec.tasklist b/board/servo_micro/ec.tasklist index c1fb169118..c45a1e89a7 100644 --- a/board/servo_micro/ec.tasklist +++ b/board/servo_micro/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/servo_micro/gpio.inc b/board/servo_micro/gpio.inc index 10e411c5f2..ad1739f1e6 100644 --- a/board/servo_micro/gpio.inc +++ b/board/servo_micro/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/servo_v4/OWNERS b/board/servo_v4/OWNERS new file mode 100644 index 0000000000..150eefc951 --- /dev/null +++ b/board/servo_v4/OWNERS @@ -0,0 +1,3 @@ +bnemec@google.com +matthewb@chromium.org +waihong@google.com diff --git a/board/servo_v4/board.c b/board/servo_v4/board.c index fc6735e19c..6cb6cf5df9 100644 --- a/board/servo_v4/board.c +++ b/board/servo_v4/board.c @@ -1,11 +1,10 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Servo V4 configuration */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "console.h" #include "ec_version.h" @@ -24,18 +23,18 @@ #include "timer.h" #include "update_fw.h" #include "usart-stm32f0.h" -#include "usart_tx_dma.h" #include "usart_rx_dma.h" +#include "usart_tx_dma.h" +#include "usb-stream.h" #include "usb_gpio.h" #include "usb_i2c.h" #include "usb_pd.h" #include "usb_pd_config.h" #include "usb_spi.h" -#include "usb-stream.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) /****************************************************************************** * GPIO interrupt handlers. @@ -78,7 +77,7 @@ static volatile int hpd_prev_level; void hpd_irq_deferred(void) { - int dp_mode = pd_alt_mode(1, TCPC_TX_SOP, USB_SID_DISPLAYPORT); + int dp_mode = pd_alt_mode(1, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); if (dp_mode) { pd_send_hpd(DUT, hpd_irq); @@ -90,7 +89,7 @@ DECLARE_DEFERRED(hpd_irq_deferred); void hpd_lvl_deferred(void) { int level = gpio_get_level(GPIO_DP_HPD); - int dp_mode = pd_alt_mode(1, TCPC_TX_SOP, USB_SID_DISPLAYPORT); + int dp_mode = pd_alt_mode(1, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); if (level != hpd_prev_level) { /* It's a glitch while in deferred or canceled action */ @@ -132,6 +131,7 @@ void hpd_evt(enum gpio_signal signal) hpd_prev_level = level; } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /****************************************************************************** @@ -176,23 +176,22 @@ void board_config_pre_init(void) /* ADC channels */ const struct adc_t adc_channels[] = { /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_CHG_CC1_PD] = {"CHG_CC1_PD", 3300, 4096, 0, STM32_AIN(2)}, - [ADC_CHG_CC2_PD] = {"CHG_CC2_PD", 3300, 4096, 0, STM32_AIN(4)}, - [ADC_DUT_CC1_PD] = {"DUT_CC1_PD", 3300, 4096, 0, STM32_AIN(0)}, - [ADC_DUT_CC2_PD] = {"DUT_CC2_PD", 3300, 4096, 0, STM32_AIN(5)}, - [ADC_SBU1_DET] = {"SBU1_DET", 3300, 4096, 0, STM32_AIN(3)}, - [ADC_SBU2_DET] = {"SBU2_DET", 3300, 4096, 0, STM32_AIN(7)}, - [ADC_SUB_C_REF] = {"SUB_C_REF", 3300, 4096, 0, STM32_AIN(1)}, + [ADC_CHG_CC1_PD] = { "CHG_CC1_PD", 3300, 4096, 0, STM32_AIN(2) }, + [ADC_CHG_CC2_PD] = { "CHG_CC2_PD", 3300, 4096, 0, STM32_AIN(4) }, + [ADC_DUT_CC1_PD] = { "DUT_CC1_PD", 3300, 4096, 0, STM32_AIN(0) }, + [ADC_DUT_CC2_PD] = { "DUT_CC2_PD", 3300, 4096, 0, STM32_AIN(5) }, + [ADC_SBU1_DET] = { "SBU1_DET", 3300, 4096, 0, STM32_AIN(3) }, + [ADC_SBU2_DET] = { "SBU2_DET", 3300, 4096, 0, STM32_AIN(7) }, + [ADC_SUB_C_REF] = { "SUB_C_REF", 3300, 4096, 0, STM32_AIN(1) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - /****************************************************************************** * Forward UARTs as a USB serial interface. */ -#define USB_STREAM_RX_SIZE 16 -#define USB_STREAM_TX_SIZE 16 +#define USB_STREAM_RX_SIZE 16 +#define USB_STREAM_TX_SIZE 16 /****************************************************************************** * Forward USART3 as a simple USB serial interface. @@ -201,29 +200,19 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); static struct usart_config const usart3; struct usb_stream_config const usart3_usb; -static struct queue const usart3_to_usb = QUEUE_DIRECT(64, uint8_t, - usart3.producer, usart3_usb.consumer); -static struct queue const usb_to_usart3 = QUEUE_DIRECT(64, uint8_t, - usart3_usb.producer, usart3.consumer); +static struct queue const usart3_to_usb = + QUEUE_DIRECT(64, uint8_t, usart3.producer, usart3_usb.consumer); +static struct queue const usb_to_usart3 = + QUEUE_DIRECT(64, uint8_t, usart3_usb.producer, usart3.consumer); static struct usart_config const usart3 = - USART_CONFIG(usart3_hw, - usart_rx_interrupt, - usart_tx_interrupt, - 115200, - 0, - usart3_to_usb, - usb_to_usart3); - -USB_STREAM_CONFIG(usart3_usb, - USB_IFACE_USART3_STREAM, - USB_STR_USART3_STREAM_NAME, - USB_EP_USART3_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart3, - usart3_to_usb) + USART_CONFIG(usart3_hw, usart_rx_interrupt, usart_tx_interrupt, 115200, + 0, usart3_to_usb, usb_to_usart3); +USB_STREAM_CONFIG(usart3_usb, USB_IFACE_USART3_STREAM, + USB_STR_USART3_STREAM_NAME, USB_EP_USART3_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, usb_to_usart3, + usart3_to_usb) /****************************************************************************** * Forward USART4 as a simple USB serial interface. @@ -232,63 +221,73 @@ USB_STREAM_CONFIG(usart3_usb, static struct usart_config const usart4; struct usb_stream_config const usart4_usb; -static struct queue const usart4_to_usb = QUEUE_DIRECT(64, uint8_t, - usart4.producer, usart4_usb.consumer); -static struct queue const usb_to_usart4 = QUEUE_DIRECT(64, uint8_t, - usart4_usb.producer, usart4.consumer); +static struct queue const usart4_to_usb = + QUEUE_DIRECT(64, uint8_t, usart4.producer, usart4_usb.consumer); +static struct queue const usb_to_usart4 = + QUEUE_DIRECT(64, uint8_t, usart4_usb.producer, usart4.consumer); static struct usart_config const usart4 = - USART_CONFIG(usart4_hw, - usart_rx_interrupt, - usart_tx_interrupt, - 9600, - 0, - usart4_to_usb, - usb_to_usart4); - -USB_STREAM_CONFIG(usart4_usb, - USB_IFACE_USART4_STREAM, - USB_STR_USART4_STREAM_NAME, - USB_EP_USART4_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart4, - usart4_to_usb) + USART_CONFIG(usart4_hw, usart_rx_interrupt, usart_tx_interrupt, 9600, 0, + usart4_to_usb, usb_to_usart4); + +USB_STREAM_CONFIG(usart4_usb, USB_IFACE_USART4_STREAM, + USB_STR_USART4_STREAM_NAME, USB_EP_USART4_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, usb_to_usart4, + usart4_to_usb) +/* + * Define usb interface descriptor for the `EMPTY` usb interface, to satisfy + * UEFI and kernel requirements (see b/183857501). + */ +const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_EMPTY) = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = USB_IFACE_EMPTY, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, +}; /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("Servo V4"), - [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Servo V4"), + [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Servo EC Shell"), - [USB_STR_USART3_STREAM_NAME] = USB_STRING_DESC("DUT UART"), - [USB_STR_USART4_STREAM_NAME] = USB_STRING_DESC("Atmega UART"), - [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), + [USB_STR_USART3_STREAM_NAME] = USB_STRING_DESC("DUT UART"), + [USB_STR_USART4_STREAM_NAME] = USB_STRING_DESC("Atmega UART"), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); - - /****************************************************************************** * Support I2C bridging over USB. */ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + { .name = "master", + .port = I2C_PORT_MASTER, + .kbps = 100, + .scl = GPIO_MASTER_I2C_SCL, + .sda = GPIO_MASTER_I2C_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -int usb_i2c_board_is_enabled(void) { return 1; } +int usb_i2c_board_is_enabled(void) +{ + return 1; +} /****************************************************************************** * Initialize board. @@ -297,14 +296,13 @@ int usb_i2c_board_is_enabled(void) { return 1; } /* * Support tca6416 I2C ioexpander. */ -#define GPIOX_I2C_ADDR_FLAGS 0x20 -#define GPIOX_IN_PORT_A 0x0 -#define GPIOX_IN_PORT_B 0x1 -#define GPIOX_OUT_PORT_A 0x2 -#define GPIOX_OUT_PORT_B 0x3 -#define GPIOX_DIR_PORT_A 0x6 -#define GPIOX_DIR_PORT_B 0x7 - +#define GPIOX_I2C_ADDR_FLAGS 0x20 +#define GPIOX_IN_PORT_A 0x0 +#define GPIOX_IN_PORT_B 0x1 +#define GPIOX_OUT_PORT_A 0x2 +#define GPIOX_OUT_PORT_B 0x3 +#define GPIOX_DIR_PORT_A 0x6 +#define GPIOX_DIR_PORT_B 0x7 /* Write a GPIO output on the tca6416 I2C ioexpander. */ static void write_ioexpander(int bank, int gpio, int val) @@ -374,15 +372,15 @@ static void init_ioexpander(void) * Max observed USB low across sampled systems: 666mV * Min observed USB high across sampled systems: 3026mV */ -#define GND_MAX_MV 700 -#define USB_HIGH_MV 2500 -#define SBU_DIRECT 0 -#define SBU_FLIP 1 +#define GND_MAX_MV 700 +#define USB_HIGH_MV 2500 +#define SBU_DIRECT 0 +#define SBU_FLIP 1 -#define MODE_SBU_DISCONNECT 0 -#define MODE_SBU_CONNECT 1 -#define MODE_SBU_FLIP 2 -#define MODE_SBU_OTHER 3 +#define MODE_SBU_DISCONNECT 0 +#define MODE_SBU_CONNECT 1 +#define MODE_SBU_FLIP 2 +#define MODE_SBU_OTHER 3 static void ccd_measure_sbu(void); DECLARE_DEFERRED(ccd_measure_sbu); @@ -425,12 +423,12 @@ static void ccd_measure_sbu(void) } else { count++; } - /* - * If SuzyQ is enabled, we'll poll for a persistent no-signal for - * 500ms. Since USB is differential, we should never see GND/GND - * while the device is connected. - * If disconnected, electrically remove SuzyQ. - */ + /* + * If SuzyQ is enabled, we'll poll for a persistent no-signal + * for 500ms. Since USB is differential, we should never see + * GND/GND while the device is connected. If disconnected, + * electrically remove SuzyQ. + */ } else if ((mux_en) && (sbu1 < GND_MAX_MV) && (sbu2 < GND_MAX_MV)) { /* Check for SBU disconnect if connected. */ if (last != MODE_SBU_DISCONNECT) { diff --git a/board/servo_v4/board.h b/board/servo_v4/board.h index 8654ad901e..1c7d90eab4 100644 --- a/board/servo_v4/board.h +++ b/board/servo_v4/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,6 +10,12 @@ #define CONFIG_LTO +/* Free up flash space */ +#ifdef SECTION_IS_RO +#define CONFIG_DEBUG_ASSERT_BRIEF +#undef CONFIG_USB_PD_TCPMV1_DEBUG +#endif + /* * Board Versions: * Versions are designated by the PCB color and consist of red, blue, and @@ -17,7 +23,6 @@ * id from previous versions. */ #define BOARD_VERSION_BLACK 3 -#define CONFIG_BOARD_VERSION_CUSTOM /* 48 MHz SYSCLK clock frequency */ #define CPU_CLOCK 48000000 @@ -30,12 +35,12 @@ #define CONFIG_CMD_USART_INFO /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_HW_CRC #define CONFIG_PVD -/* See 'Programmable voltage detector characteristics' in the STM32F072x8 Datasheet. - PVD Threshold 1 corresponds to a falling voltage threshold of min:2.09V, max:2.27V. */ -#define PVD_THRESHOLD (1) +/* See 'Programmable voltage detector characteristics' in the STM32F072x8 + Datasheet. PVD Threshold 1 corresponds to a falling voltage threshold of + min:2.09V, max:2.27V. */ +#define PVD_THRESHOLD (1) /* USB Configuration */ #define CONFIG_USB @@ -55,23 +60,23 @@ #define DEFAULT_MAC_ADDR "Uninitialized" /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_CONSOLE 0 -#define USB_IFACE_EMPTY 1 -#define USB_IFACE_I2C 2 -#define USB_IFACE_USART3_STREAM 3 -#define USB_IFACE_USART4_STREAM 4 -#define USB_IFACE_UPDATE 5 -#define USB_IFACE_COUNT 6 +#define USB_IFACE_CONSOLE 0 +#define USB_IFACE_EMPTY 1 +#define USB_IFACE_I2C 2 +#define USB_IFACE_USART3_STREAM 3 +#define USB_IFACE_USART4_STREAM 4 +#define USB_IFACE_UPDATE 5 +#define USB_IFACE_COUNT 6 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_CONSOLE 1 -#define USB_EP_EMPTY 2 -#define USB_EP_I2C 3 -#define USB_EP_USART3_STREAM 4 -#define USB_EP_USART4_STREAM 5 -#define USB_EP_UPDATE 6 -#define USB_EP_COUNT 7 +#define USB_EP_CONTROL 0 +#define USB_EP_CONSOLE 1 +#define USB_EP_EMPTY 2 +#define USB_EP_I2C 3 +#define USB_EP_USART3_STREAM 4 +#define USB_EP_USART4_STREAM 5 +#define USB_EP_UPDATE 6 +#define USB_EP_COUNT 7 /* Enable console recasting of GPIO type. */ #define CONFIG_CMD_GPIO_EXTENDED @@ -89,22 +94,28 @@ #undef CONFIG_CMD_ACCELSPOOF #undef CONFIG_CMD_FASTCHARGE #undef CONFIG_CMD_FLASHINFO +#undef CONFIG_CMD_FLASH_WP #undef CONFIG_CMD_GETTIME +#undef CONFIG_CMD_I2C_SCAN +#undef CONFIG_CMD_I2C_XFER #undef CONFIG_CMD_MEM #undef CONFIG_CMD_SHMEM #undef CONFIG_CMD_SYSLOCK #undef CONFIG_CMD_TIMERINFO #undef CONFIG_CMD_WAITMS +#undef CONFIG_CMD_USART_INFO +#undef CONFIG_CMD_CHARGE_SUPPLIER_INFO +#define CONFIG_CMD_PD_SRCCAPS_REDUCED_SIZE /* Enable control of I2C over USB */ #define CONFIG_USB_I2C #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define I2C_PORT_MASTER 1 /* PD features */ #define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG +#undef CONFIG_ADC_WATCHDOG #define CONFIG_BOARD_PRE_INIT /* * If task profiling is enabled then the rx falling edge detection interrupts @@ -113,7 +124,7 @@ #undef CONFIG_TASK_PROFILING #define CONFIG_CHARGE_MANAGER -#undef CONFIG_CHARGE_MANAGER_SAFE_MODE +#undef CONFIG_CHARGE_MANAGER_SAFE_MODE #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_TCPMV1 #define CONFIG_CMD_PD @@ -128,28 +139,29 @@ #undef CONFIG_USB_PD_PULLUP #define CONFIG_USB_PD_PULLUP TYPEC_RP_USB #define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT +#define CONFIG_USB_PD_ONLY_FIXED_PDOS /* Don't automatically change roles */ #undef CONFIG_USB_PD_INITIAL_DRP_STATE #define CONFIG_USB_PD_INITIAL_DRP_STATE PD_DRP_FORCE_SINK /* Variable-current Rp no connect and Ra attach macros */ -#define CC_NC(port, cc, sel) (pd_tcpc_cc_nc(port, cc, sel)) -#define CC_RA(port, cc, sel) (pd_tcpc_cc_ra(port, cc, sel)) +#define CC_NC(port, cc, sel) (pd_tcpc_cc_nc(port, cc, sel)) +#define CC_RA(port, cc, sel) (pd_tcpc_cc_ra(port, cc, sel)) /* * TODO(crosbug.com/p/60792): The delay values are currently just place holders * and the delay will need to be relative to the circuitry that allows VBUS to * be supplied to the DUT port from the CHG port. */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* * Define PDO selection logic for SourceCap. * On a 45W PD charger, it might provide PDOs with 15V/3A and 20V/2.25A. @@ -170,8 +182,7 @@ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 - +#define TIM_ADC 3 #include "gpio_signal.h" @@ -190,7 +201,6 @@ enum usb_strings { USB_STR_COUNT }; - /* ADC signal */ enum adc_channel { ADC_CHG_CC1_PD, diff --git a/board/servo_v4/build.mk b/board/servo_v4/build.mk index 6336bbfab6..05a0684696 100644 --- a/board/servo_v4/build.mk +++ b/board/servo_v4/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -14,6 +14,6 @@ CHIP_VARIANT:=stm32f07x test-list-y= board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_pdo.o all_deps=$(patsubst ro,,$(def_all_deps)) diff --git a/board/servo_v4/ec.tasklist b/board/servo_v4/ec.tasklist index 2111c6b761..f51780dce4 100644 --- a/board/servo_v4/ec.tasklist +++ b/board/servo_v4/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/servo_v4/gpio.inc b/board/servo_v4/gpio.inc index 76b9a06d0f..afc5789636 100644 --- a/board/servo_v4/gpio.inc +++ b/board/servo_v4/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/servo_v4/usb_pd_config.h b/board/servo_v4/usb_pd_config.h index b865057618..d47e8e8868 100644 --- a/board/servo_v4/usb_pd_config.h +++ b/board/servo_v4/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,8 +6,8 @@ #include "adc.h" #include "chip/stm32/registers.h" #include "console.h" -#include "gpio.h" #include "ec_commands.h" +#include "gpio.h" #include "usb_pd_tcpm.h" /* USB Power delivery board configuration */ @@ -56,22 +56,22 @@ #define CONFIG_HW_CRC /* Servo v4 CC configuration */ -#define CC_DETACH BIT(0) /* Emulate detach: both CC open */ -#define CC_DISABLE_DTS BIT(1) /* Apply resistors to single or both CC? */ -#define CC_ALLOW_SRC BIT(2) /* Allow charge through by policy? */ -#define CC_ENABLE_DRP BIT(3) /* Enable dual-role port */ -#define CC_SNK_WITH_PD BIT(4) /* Force enabling PD comm for sink role */ -#define CC_POLARITY BIT(5) /* CC polarity */ +#define CC_DETACH BIT(0) /* Emulate detach: both CC open */ +#define CC_DISABLE_DTS BIT(1) /* Apply resistors to single or both CC? */ +#define CC_ALLOW_SRC BIT(2) /* Allow charge through by policy? */ +#define CC_ENABLE_DRP BIT(3) /* Enable dual-role port */ +#define CC_SNK_WITH_PD BIT(4) /* Force enabling PD comm for sink role */ +#define CC_POLARITY BIT(5) /* CC polarity */ /* Servo v4 DP alt-mode configuration */ -#define ALT_DP_ENABLE BIT(0) /* Enable DP alt-mode or not */ -#define ALT_DP_PIN_C BIT(1) /* Pin assignment C supported */ -#define ALT_DP_PIN_D BIT(2) /* Pin assignment D supported */ -#define ALT_DP_PIN_E BIT(3) /* Pin assignment E supported */ -#define ALT_DP_MF_PREF BIT(4) /* Multi-Function preferred */ -#define ALT_DP_PLUG BIT(5) /* Plug or receptacle */ -#define ALT_DP_OVERRIDE_HPD BIT(6) /* Override the HPD signal */ -#define ALT_DP_HPD_LVL BIT(7) /* HPD level if overridden */ +#define ALT_DP_ENABLE BIT(0) /* Enable DP alt-mode or not */ +#define ALT_DP_PIN_C BIT(1) /* Pin assignment C supported */ +#define ALT_DP_PIN_D BIT(2) /* Pin assignment D supported */ +#define ALT_DP_PIN_E BIT(3) /* Pin assignment E supported */ +#define ALT_DP_MF_PREF BIT(4) /* Multi-Function preferred */ +#define ALT_DP_PLUG BIT(5) /* Plug or receptacle */ +#define ALT_DP_OVERRIDE_HPD BIT(6) /* Override the HPD signal */ +#define ALT_DP_HPD_LVL BIT(7) /* HPD level if overridden */ /* TX uses SPI1 on PB3-4 for CHG port, SPI2 on PB 13-14 for DUT port */ #define SPI_REGS(p) ((p) ? STM32_SPI2_REGS : STM32_SPI1_REGS) @@ -94,14 +94,14 @@ static inline void spi_enable_clock(int port) #define TIM_TX_CCR_IDX(p) ((p) ? TIM_TX_CCR_DUT : TIM_TX_CCR_CHG) #define TIM_RX_CCR_IDX(p) ((p) ? TIM_RX_CCR_DUT : TIM_RX_CCR_CHG) -#define TIM_CCR_CS 1 +#define TIM_CCR_CS 1 /* * EXTI line 21 is connected to the CMP1 output, * EXTI line 22 is connected to the CMP2 output, * CHG uses CMP2, and DUT uses CMP1. */ -#define EXTI_COMP_MASK(p) ((p) ? (1<<21) : BIT(22)) +#define EXTI_COMP_MASK(p) ((p) ? (1 << 21) : BIT(22)) #define IRQ_COMP STM32_IRQ_COMP /* triggers packet detection on comparator falling edge */ @@ -193,13 +193,25 @@ static inline void pd_select_polarity(int port, int polarity) if (port == 0) { /* CHG use the right comparator inverted input for COMP2 */ STM32_COMP_CSR = (val & ~STM32_COMP_CMP2INSEL_MASK) | - (polarity ? STM32_COMP_CMP2INSEL_INM4 /* PA4: C0_CC2 */ - : STM32_COMP_CMP2INSEL_INM6);/* PA2: C0_CC1 */ + (polarity ? + STM32_COMP_CMP2INSEL_INM4 /* PA4: + C0_CC2 + */ + : + STM32_COMP_CMP2INSEL_INM6); /* PA2: + C0_CC1 + */ } else { /* DUT use the right comparator inverted input for COMP1 */ STM32_COMP_CSR = (val & ~STM32_COMP_CMP1INSEL_MASK) | - (polarity ? STM32_COMP_CMP1INSEL_INM5 /* PA5: C1_CC2 */ - : STM32_COMP_CMP1INSEL_INM6);/* PA0: C1_CC1 */ + (polarity ? + STM32_COMP_CMP1INSEL_INM5 /* PA5: + C1_CC2 + */ + : + STM32_COMP_CMP1INSEL_INM6); /* PA0: + C1_CC1 + */ } } @@ -279,10 +291,8 @@ static inline void pd_config_init(int port, uint8_t power_role) /* Initialize TX pins and put them in Hi-Z */ pd_tx_init(); - } int pd_adc_read(int port, int cc); #endif /* __CROS_EC_USB_PD_CONFIG_H */ - diff --git a/board/servo_v4/usb_pd_pdo.c b/board/servo_v4/usb_pd_pdo.c new file mode 100644 index 0000000000..b2eeee8e52 --- /dev/null +++ b/board/servo_v4/usb_pd_pdo.c @@ -0,0 +1,56 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_config.h" +#include "usb_pd_pdo.h" + +#define CHG_PDO_FIXED_FLAGS (PDO_FIXED_DATA_SWAP) + +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, CHG_PDO_FIXED_FLAGS), + PDO_BATT(4750, 21000, 15000), + PDO_VAR(4750, 21000, 3000), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); + +/* + * Dynamic PDO that reflects capabilities present on the CHG port. Allow for + * multiple entries so that we can offer greater than 5V charging. The 1st + * entry will be fixed 5V, but its current value may change based on the CHG + * port vbus info. Subsequent entries are used for when offering vbus greater + * than 5V. + */ +const uint16_t pd_src_voltages_mv[] = { + 5000, 9000, 10000, 12000, 15000, 20000, +}; +uint32_t pd_src_chg_pdo[ARRAY_SIZE(pd_src_voltages_mv)]; +uint8_t chg_pdo_cnt; + +int active_charge_port = CHARGE_PORT_NONE; +struct vbus_prop vbus[CONFIG_USB_PD_PORT_MAX_COUNT]; + +int charge_port_is_active(void) +{ + return active_charge_port == CHG && vbus[CHG].mv > 0; +} + +int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) +{ + int pdo_cnt = 0; + + /* + * If CHG is providing VBUS, then advertise what's available on the CHG + * port, otherwise we provide no power. + */ + if (charge_port_is_active()) { + *src_pdo = pd_src_chg_pdo; + pdo_cnt = chg_pdo_cnt; + } + + return pdo_cnt; +} diff --git a/board/servo_v4/usb_pd_pdo.h b/board/servo_v4/usb_pd_pdo.h new file mode 100644 index 0000000000..acab299690 --- /dev/null +++ b/board/servo_v4/usb_pd_pdo.h @@ -0,0 +1,30 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_SERVO_V4_USB_PD_PDO_H +#define __CROS_EC_BOARD_SERVO_V4_USB_PD_PDO_H + +#include "compile_time_macros.h" +#include "stdint.h" + +extern const uint32_t pd_snk_pdo[3]; +extern const int pd_snk_pdo_cnt; + +extern const uint16_t pd_src_voltages_mv[6]; +extern uint32_t pd_src_chg_pdo[ARRAY_SIZE(pd_src_voltages_mv)]; +extern uint8_t chg_pdo_cnt; + +extern int active_charge_port; + +struct vbus_prop { + int mv; + int ma; +}; +extern struct vbus_prop vbus[CONFIG_USB_PD_PORT_MAX_COUNT]; + +int charge_port_is_active(void); +int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port); + +#endif /* __CROS_EC_BOARD_SERVO_V4_USB_PD_PDO_H */ diff --git a/board/servo_v4/usb_pd_policy.c b/board/servo_v4/usb_pd_policy.c index b87130fbc8..68eb59ff97 100644 --- a/board/servo_v4/usb_pd_policy.c +++ b/board/servo_v4/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,66 +18,67 @@ #include "registers.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" -#include "util.h" #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_config.h" +#include "usb_pd_pdo.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define DUT_PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) -#define CHG_PDO_FIXED_FLAGS (PDO_FIXED_DATA_SWAP) +#define DUT_PDO_FIXED_FLAGS \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_COMM_CAP) -#define VBUS_UNCHANGED(curr, pend, new) (curr == new && pend == new) +#define VBUS_UNCHANGED(curr, pend, new) (curr == new &&pend == new) /* Macros to config the PD role */ #define CONF_SET_CLEAR(c, set, clear) ((c | (set)) & ~(clear)) -#define CONF_SRC(c) CONF_SET_CLEAR(c, \ - CC_DISABLE_DTS | CC_ALLOW_SRC, \ - CC_ENABLE_DRP | CC_SNK_WITH_PD) -#define CONF_SNK(c) CONF_SET_CLEAR(c, \ - CC_DISABLE_DTS, \ - CC_ALLOW_SRC | CC_ENABLE_DRP | CC_SNK_WITH_PD) -#define CONF_PDSNK(c) CONF_SET_CLEAR(c, \ - CC_DISABLE_DTS | CC_SNK_WITH_PD, \ - CC_ALLOW_SRC | CC_ENABLE_DRP) -#define CONF_DRP(c) CONF_SET_CLEAR(c, \ - CC_DISABLE_DTS | CC_ALLOW_SRC | CC_ENABLE_DRP, \ - CC_SNK_WITH_PD) -#define CONF_SRCDTS(c) CONF_SET_CLEAR(c, \ - CC_ALLOW_SRC, \ - CC_ENABLE_DRP | CC_DISABLE_DTS | CC_SNK_WITH_PD) -#define CONF_SNKDTS(c) CONF_SET_CLEAR(c, \ - 0, \ - CC_ALLOW_SRC | CC_ENABLE_DRP | \ - CC_DISABLE_DTS | CC_SNK_WITH_PD) -#define CONF_PDSNKDTS(c) CONF_SET_CLEAR(c, \ - CC_SNK_WITH_PD, \ - CC_ALLOW_SRC | CC_ENABLE_DRP | CC_DISABLE_DTS) -#define CONF_DRPDTS(c) CONF_SET_CLEAR(c, \ - CC_ALLOW_SRC | CC_ENABLE_DRP, \ - CC_DISABLE_DTS | CC_SNK_WITH_PD) +#define CONF_SRC(c) \ + CONF_SET_CLEAR(c, CC_DISABLE_DTS | CC_ALLOW_SRC, \ + CC_ENABLE_DRP | CC_SNK_WITH_PD) +#define CONF_SNK(c) \ + CONF_SET_CLEAR(c, CC_DISABLE_DTS, \ + CC_ALLOW_SRC | CC_ENABLE_DRP | CC_SNK_WITH_PD) +#define CONF_PDSNK(c) \ + CONF_SET_CLEAR(c, CC_DISABLE_DTS | CC_SNK_WITH_PD, \ + CC_ALLOW_SRC | CC_ENABLE_DRP) +#define CONF_DRP(c) \ + CONF_SET_CLEAR(c, CC_DISABLE_DTS | CC_ALLOW_SRC | CC_ENABLE_DRP, \ + CC_SNK_WITH_PD) +#define CONF_SRCDTS(c) \ + CONF_SET_CLEAR(c, CC_ALLOW_SRC, \ + CC_ENABLE_DRP | CC_DISABLE_DTS | CC_SNK_WITH_PD) +#define CONF_SNKDTS(c) \ + CONF_SET_CLEAR(c, 0, \ + CC_ALLOW_SRC | CC_ENABLE_DRP | CC_DISABLE_DTS | \ + CC_SNK_WITH_PD) +#define CONF_PDSNKDTS(c) \ + CONF_SET_CLEAR(c, CC_SNK_WITH_PD, \ + CC_ALLOW_SRC | CC_ENABLE_DRP | CC_DISABLE_DTS) +#define CONF_DRPDTS(c) \ + CONF_SET_CLEAR(c, CC_ALLOW_SRC | CC_ENABLE_DRP, \ + CC_DISABLE_DTS | CC_SNK_WITH_PD) +#define CONF_DTSOFF(c) CONF_SET_CLEAR(c, CC_DISABLE_DTS, 0) +#define CONF_DTSON(c) CONF_SET_CLEAR(c, 0, CC_DISABLE_DTS) /* Macros to apply Rd/Rp to CC lines */ -#define DUT_ACTIVE_CC_SET(r, flags) \ - gpio_set_flags(cc_config & CC_POLARITY ? \ - CONCAT2(GPIO_USB_DUT_CC2_, r) : \ - CONCAT2(GPIO_USB_DUT_CC1_, r), \ +#define DUT_ACTIVE_CC_SET(r, flags) \ + gpio_set_flags(cc_config &CC_POLARITY ? \ + CONCAT2(GPIO_USB_DUT_CC2_, r) : \ + CONCAT2(GPIO_USB_DUT_CC1_, r), \ flags) -#define DUT_INACTIVE_CC_SET(r, flags) \ - gpio_set_flags(cc_config & CC_POLARITY ? \ - CONCAT2(GPIO_USB_DUT_CC1_, r) : \ - CONCAT2(GPIO_USB_DUT_CC2_, r), \ +#define DUT_INACTIVE_CC_SET(r, flags) \ + gpio_set_flags(cc_config &CC_POLARITY ? \ + CONCAT2(GPIO_USB_DUT_CC1_, r) : \ + CONCAT2(GPIO_USB_DUT_CC2_, r), \ flags) -#define DUT_BOTH_CC_SET(r, flags) \ - do { \ +#define DUT_BOTH_CC_SET(r, flags) \ + do { \ gpio_set_flags(CONCAT2(GPIO_USB_DUT_CC1_, r), flags); \ gpio_set_flags(CONCAT2(GPIO_USB_DUT_CC2_, r), flags); \ } while (0) @@ -88,32 +89,6 @@ #define DUT_BOTH_CC_PD(r) DUT_BOTH_CC_SET(r, GPIO_OUT_LOW) #define DUT_BOTH_CC_OPEN(r) DUT_BOTH_CC_SET(r, GPIO_INPUT) -/* - * Dynamic PDO that reflects capabilities present on the CHG port. Allow for - * multiple entries so that we can offer greater than 5V charging. The 1st - * entry will be fixed 5V, but its current value may change based on the CHG - * port vbus info. Subsequent entries are used for when offering vbus greater - * than 5V. - */ -static const uint16_t pd_src_voltages_mv[] = { - 5000, 9000, 10000, 12000, 15000, 20000, -}; -static uint32_t pd_src_chg_pdo[ARRAY_SIZE(pd_src_voltages_mv)]; -static uint8_t chg_pdo_cnt; - -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, CHG_PDO_FIXED_FLAGS), - PDO_BATT(4750, 21000, 15000), - PDO_VAR(4750, 21000, 3000), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); - -struct vbus_prop { - int mv; - int ma; -}; -static struct vbus_prop vbus[CONFIG_USB_PD_PORT_MAX_COUNT]; -static int active_charge_port = CHARGE_PORT_NONE; static enum charge_supplier active_charge_supplier; static uint8_t vbus_rp = TYPEC_RP_RESERVED; @@ -121,15 +96,15 @@ static int cc_config = CC_ALLOW_SRC; /* Voltage thresholds for no connect in DTS mode */ static int pd_src_vnc_dts[TYPEC_RP_RESERVED][2] = { - {PD_SRC_3_0_VNC_MV, PD_SRC_1_5_VNC_MV}, - {PD_SRC_1_5_VNC_MV, PD_SRC_DEF_VNC_MV}, - {PD_SRC_3_0_VNC_MV, PD_SRC_DEF_VNC_MV}, + { PD_SRC_3_0_VNC_MV, PD_SRC_1_5_VNC_MV }, + { PD_SRC_1_5_VNC_MV, PD_SRC_DEF_VNC_MV }, + { PD_SRC_3_0_VNC_MV, PD_SRC_DEF_VNC_MV }, }; /* Voltage thresholds for Ra attach in DTS mode */ static int pd_src_rd_threshold_dts[TYPEC_RP_RESERVED][2] = { - {PD_SRC_3_0_RD_THRESH_MV, PD_SRC_1_5_RD_THRESH_MV}, - {PD_SRC_1_5_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV}, - {PD_SRC_3_0_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV}, + { PD_SRC_3_0_RD_THRESH_MV, PD_SRC_1_5_RD_THRESH_MV }, + { PD_SRC_1_5_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV }, + { PD_SRC_3_0_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV }, }; /* Voltage thresholds for no connect in normal SRC mode */ static int pd_src_vnc[TYPEC_RP_RESERVED] = { @@ -160,20 +135,19 @@ static int cc_pull_stored = TYPEC_CC_RD; static int user_limited_max_mv = 20000; +static uint8_t allow_pr_swap = 1; +static uint8_t allow_dr_swap = 1; + static uint32_t max_supported_voltage(void) { int board_max_mv = board_get_version() >= BOARD_VERSION_BLACK ? - PD_MAX_VOLTAGE_MV : MAX_MV_RED_BLUE; + PD_MAX_VOLTAGE_MV : + MAX_MV_RED_BLUE; return board_max_mv < user_limited_max_mv ? board_max_mv : user_limited_max_mv; } -static int charge_port_is_active(void) -{ - return active_charge_port == CHG && vbus[CHG].mv > 0; -} - static int is_charge_through_allowed(void) { return charge_port_is_active() && cc_config & CC_ALLOW_SRC; @@ -270,7 +244,7 @@ static void board_manage_dut_port(void) static void update_ports(void) { int pdo_index, src_index, snk_index, i; - uint32_t pdo, max_ma, max_mv; + uint32_t pdo, max_ma, max_mv, unused; /* * CHG Vbus has changed states, update PDO that reflects CHG port @@ -285,6 +259,20 @@ static void update_ports(void) src_index = 0; snk_index = -1; + /* + * TODO: This code artificially limits PDO + * to entries in pd_src_voltages_mv table + * + * This is artificially overconstrainted. + * + * Allow non-standard PDO objects so long + * as they are valid. See: crrev/c/730877 + * for where this started. + * + * This needs to be rearchitected in order + * to support Variable PDO passthrough. + */ + for (i = 0; i < ARRAY_SIZE(pd_src_voltages_mv); ++i) { /* Adhere to board voltage limits */ if (pd_src_voltages_mv[i] > @@ -292,8 +280,8 @@ static void update_ports(void) break; /* Find the 'best' PDO <= voltage */ - pdo_index = - pd_find_pdo_index(pd_get_src_cap_cnt(CHG), + pdo_index = pd_find_pdo_index( + pd_get_src_cap_cnt(CHG), pd_get_src_caps(CHG), pd_src_voltages_mv[i], &pdo); /* Don't duplicate PDOs */ @@ -304,20 +292,54 @@ static void update_ports(void) continue; snk_index = pdo_index; - pd_extract_pdo_power(pdo, &max_ma, &max_mv); - pd_src_chg_pdo[src_index++] = + pd_extract_pdo_power(pdo, &max_ma, &max_mv, + &unused); + pd_src_chg_pdo[src_index] = PDO_FIXED_VOLT(max_mv) | - PDO_FIXED_CURR(max_ma) | - DUT_PDO_FIXED_FLAGS | - PDO_FIXED_UNCONSTRAINED; + PDO_FIXED_CURR(max_ma); + + if (src_index == 0) { + /* + * TODO: 1st PDO *should* always be + * vSafe5v PDO. But not always with bad + * DUT. Should re-index and re-map. + * + * TODO: Add variable voltage PDO + * conversion. + */ + pd_src_chg_pdo[src_index] &= + ~(DUT_PDO_FIXED_FLAGS | + PDO_FIXED_UNCONSTRAINED); + + /* + * TODO: Keep Unconstrained Power knobs + * exposed and well-defined. + * + * Current method is workaround that + * force-rejects PR_SWAPs in lieu of UP. + * + * Migrate to use config flag such as: + * ((cc_config & + * CC_UNCONSTRAINED_POWER)? + * PDO_FIXED_UNCONSTRAINED:0) + */ + pd_src_chg_pdo[src_index] |= + (DUT_PDO_FIXED_FLAGS | + PDO_FIXED_UNCONSTRAINED); + } + src_index++; } chg_pdo_cnt = src_index; } else { /* 5V PDO */ pd_src_chg_pdo[0] = PDO_FIXED_VOLT(PD_MIN_MV) | - PDO_FIXED_CURR(vbus[CHG].ma) | - DUT_PDO_FIXED_FLAGS | - PDO_FIXED_UNCONSTRAINED; + PDO_FIXED_CURR(vbus[CHG].ma) | + DUT_PDO_FIXED_FLAGS | + PDO_FIXED_UNCONSTRAINED; + /* + * TODO: Keep Unconstrained Power knobs + * exposed and well-defined. + */ chg_pdo_cnt = 1; } @@ -342,8 +364,8 @@ int board_set_active_charge_port(int charge_port) return 0; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { if (port != CHG) return; @@ -389,8 +411,9 @@ int pd_tcpc_cc_nc(int port, int cc_volt, int cc_sel) if (cc_config & CC_DISABLE_DTS) nc = cc_volt >= pd_src_vnc[rp_index]; else - nc = cc_volt >= pd_src_vnc_dts[rp_index][ - cc_config & CC_POLARITY ? !cc_sel : cc_sel]; + nc = cc_volt >= + pd_src_vnc_dts[rp_index] + [cc_config & CC_POLARITY ? !cc_sel : cc_sel]; return nc; } @@ -416,19 +439,30 @@ int pd_tcpc_cc_ra(int port, int cc_volt, int cc_sel) if (cc_config & CC_DISABLE_DTS) ra = cc_volt < pd_src_rd_threshold[rp_index]; else - ra = cc_volt < pd_src_rd_threshold_dts[rp_index][ - cc_config & CC_POLARITY ? !cc_sel : cc_sel]; + ra = cc_volt < + pd_src_rd_threshold_dts[rp_index] + [cc_config & CC_POLARITY ? !cc_sel : + cc_sel]; return ra; } +/* DUT CC readings aren't valid if we aren't applying CC pulls */ +bool cc_is_valid(void) +{ + if ((cc_config & CC_DETACH) || (cc_pull_stored == TYPEC_CC_OPEN) || + ((cc_pull_stored == TYPEC_CC_RP) && + (rp_value_stored == TYPEC_RP_RESERVED))) + return false; + return true; +} + int pd_adc_read(int port, int cc) { int mv; - if (port == 0) mv = adc_read_channel(cc ? ADC_CHG_CC2_PD : ADC_CHG_CC1_PD); - else if (!(cc_config & CC_DETACH)) { + else if (cc_is_valid()) { /* * In servo v4 hardware logic, both CC lines are wired directly * to DUT. When servo v4 as a snk, DUT may source Vconn to CC2 @@ -459,7 +493,6 @@ int pd_adc_read(int port, int cc) */ mv = 0; } - return mv; } @@ -568,7 +601,6 @@ int pd_set_rp_rd(int port, int cc_pull, int rp_value) DUT_ACTIVE_CC_PD(RD); else DUT_BOTH_CC_PD(RD); - } rp_value_stored = rp_value; @@ -594,28 +626,12 @@ int board_select_rp_value(int port, int rp) return EC_SUCCESS; } -int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) -{ - int pdo_cnt = 0; - - /* - * If CHG is providing VBUS, then advertise what's available on the CHG - * port, otherwise we provide no power. - */ - if (charge_port_is_active()) { - *src_pdo = pd_src_chg_pdo; - pdo_cnt = chg_pdo_cnt; - } - - return pdo_cnt; -} - __override void pd_transition_voltage(int idx) { timestamp_t deadline; - uint32_t ma, mv; + uint32_t ma, mv, unused; - pd_extract_pdo_power(pd_src_chg_pdo[idx - 1], &ma, &mv); + pd_extract_pdo_power(pd_src_chg_pdo[idx - 1], &ma, &mv, &unused); /* Is this a transition to a new voltage? */ if (charge_port_is_active() && vbus[CHG].mv != mv) { /* @@ -627,8 +643,7 @@ __override void pd_transition_voltage(int idx) /* Wait for CHG transition */ deadline.val = get_time().val + PD_T_PS_TRANSITION; CPRINTS("Waiting for CHG port transition"); - while (charge_port_is_active() && - vbus[CHG].mv != mv && + while (charge_port_is_active() && vbus[CHG].mv != mv && get_time().val < deadline.val) msleep(10); @@ -688,9 +703,7 @@ void pd_power_supply_reset(int port) int pd_snk_is_vbus_provided(int port) { - - return gpio_get_level(port ? GPIO_USB_DET_PP_DUT : - GPIO_USB_DET_PP_CHG); + return gpio_get_level(port ? GPIO_USB_DET_PP_DUT : GPIO_USB_DET_PP_CHG); } __override int pd_check_power_swap(int port) @@ -707,14 +720,17 @@ __override int pd_check_power_swap(int port) if (port == CHG) return 0; + if (pd_get_power_role(port) == PD_ROLE_SINK && + !(cc_config & CC_ALLOW_SRC)) + return 0; + if (pd_snk_is_vbus_provided(CHG)) - return 1; + return allow_pr_swap; return 0; } -__override int pd_check_data_swap(int port, - enum pd_data_role data_role) +__override int pd_check_data_swap(int port, enum pd_data_role data_role) { /* * Servo should allow data role swaps to let DUT see the USB hub, but @@ -723,11 +739,10 @@ __override int pd_check_data_swap(int port, if (port == CHG) return 0; - return 1; + return allow_dr_swap; } -__override void pd_execute_data_swap(int port, - enum pd_data_role data_role) +__override void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* * TODO(b/137887386): Turn on the fastboot/DFU path when data swap to @@ -735,8 +750,7 @@ __override void pd_execute_data_swap(int port, */ } -__override void pd_check_pr_role(int port, - enum pd_power_role pr_role, +__override void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { /* @@ -747,9 +761,7 @@ __override void pd_check_pr_role(int port, */ } -__override void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +__override void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { if (port == CHG) return; @@ -759,15 +771,14 @@ __override void pd_check_dr_role(int port, pd_request_data_swap(port); } - /* ----------------- Vendor Defined Messages ------------------ */ /* * DP alt-mode config, user configurable. * Default is the mode disabled, supporting the C and D pin assignment, * multi-function preferred, and a plug. */ -static int alt_dp_config = (ALT_DP_PIN_C | ALT_DP_PIN_D | ALT_DP_MF_PREF | - ALT_DP_PLUG); +static int alt_dp_config = + (ALT_DP_PIN_C | ALT_DP_PIN_D | ALT_DP_MF_PREF | ALT_DP_PLUG); /** * Get the pins based on the user config. @@ -802,8 +813,8 @@ const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, - CONFIG_USB_PD_IDENTITY_SW_VERS, - 0, 0, 0, 0, /* SS[TR][12] */ + CONFIG_USB_PD_IDENTITY_SW_VERS, 0, 0, 0, + 0, /* SS[TR][12] */ 0, /* Vconn power */ 0, /* Vconn power required */ 0, /* Vbus power required */ @@ -841,13 +852,13 @@ uint32_t vdo_dp_mode[MODE_CNT]; static int svdm_response_modes(int port, uint32_t *payload) { - vdo_dp_mode[0] = - VDO_MODE_DP(0, /* UFP pin cfg supported: none */ - alt_dp_config_pins(), /* DFP pin */ - 1, /* no usb2.0 signalling in AMode */ - alt_dp_config_cable(), /* plug or receptacle */ - MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ - MODE_DP_SNK); /* Its a sink only */ + vdo_dp_mode[0] = VDO_MODE_DP(0, /* UFP pin cfg supported: none */ + alt_dp_config_pins(), /* DFP pin */ + 1, /* no usb2.0 signalling in AMode */ + alt_dp_config_cable(), /* plug or + receptacle */ + MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ + MODE_DP_SNK); /* Its a sink only */ /* CCD uses the SBU lines; don't enable DP when dts-mode enabled */ if (!(cc_config & CC_DISABLE_DTS)) @@ -914,17 +925,18 @@ static int dp_status(int port, uint32_t *payload) int hpd = get_hpd_level(); if (opos != OPOS) - return 0; /* NAK */ - - payload[1] = VDO_DP_STATUS( - 0, /* IRQ_HPD */ - hpd, /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - (alt_dp_config & ALT_DP_MF_PREF) != 0, /* MF pref */ - is_typec_dp_muxed(), - 0, /* power low */ - hpd ? 0x2 : 0); + return 0; /* NAK */ + + payload[1] = + VDO_DP_STATUS(0, /* IRQ_HPD */ + hpd, /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + (alt_dp_config & ALT_DP_MF_PREF) != 0, /* MF + pref + */ + is_typec_dp_muxed(), 0, /* power low */ + hpd ? 0x2 : 0); return 2; } @@ -944,15 +956,15 @@ static int svdm_enter_mode(int port, uint32_t *payload) /* SID & mode request is valid */ if ((PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) || (PD_VDO_OPOS(payload[0]) != OPOS)) - return 0; /* NAK */ + return 0; /* NAK */ alt_mode = OPOS; return 1; } -int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid) +int pd_alt_mode(int port, enum tcpci_msg_type type, uint16_t svid) { - if (type == TCPC_TX_SOP && svid == USB_SID_DISPLAYPORT) + if (type == TCPCI_MSG_SOP && svid == USB_SID_DISPLAYPORT) return alt_mode; return 0; @@ -983,7 +995,7 @@ const struct svdm_response svdm_rsp = { }; __override int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) + uint32_t **rpayload) { int cmd = PD_VDO_CMD(payload[0]); @@ -995,7 +1007,7 @@ __override int pd_custom_vdm(int port, int cnt, uint32_t *payload, case VDO_CMD_VERSION: /* guarantee last byte of payload is null character */ *(payload + cnt - 1) = 0; - CPRINTF("ver: %s\n", (char *)(payload+1)); + CPRINTF("ver: %s\n", (char *)(payload + 1)); break; case VDO_CMD_CURRENT: CPRINTF("Current: %dmA\n", payload[1]); @@ -1017,12 +1029,10 @@ static void print_cc_mode(void) gpio_get_level(GPIO_DUT_CHG_EN) ? "on" : "off"); ccprintf("chg allowed: %s\n", cc_config & CC_ALLOW_SRC ? "on" : "off"); ccprintf("drp enabled: %s\n", cc_config & CC_ENABLE_DRP ? "on" : "off"); - ccprintf("cc polarity: %s\n", cc_config & CC_POLARITY ? "cc2" : - "cc1"); + ccprintf("cc polarity: %s\n", cc_config & CC_POLARITY ? "cc2" : "cc1"); ccprintf("pd enabled: %s\n", pd_comm_is_enabled(DUT) ? "on" : "off"); } - static void do_cc(int cc_config_new) { int chargeable; @@ -1031,7 +1041,7 @@ static void do_cc(int cc_config_new) if (cc_config_new != cc_config) { if (!(cc_config & CC_DETACH)) { /* Force detach */ - pd_power_supply_reset(DUT); + gpio_set_level(GPIO_DUT_CHG_EN, 0); /* Always set to 0 here so both CC lines are changed */ cc_config &= ~(CC_DISABLE_DTS & CC_ALLOW_SRC); @@ -1092,7 +1102,7 @@ static void do_cc(int cc_config_new) } } -static int command_cc(int argc, char **argv) +static int command_cc(int argc, const char **argv) { int cc_config_new = cc_config; @@ -1123,6 +1133,10 @@ static int command_cc(int argc, char **argv) cc_config_new = CONF_PDSNKDTS(cc_config_new); else if (!strcasecmp(argv[1], "drpdts")) cc_config_new = CONF_DRPDTS(cc_config_new); + else if (!strcasecmp(argv[1], "dtsoff")) + cc_config_new = CONF_DTSOFF(cc_config_new); + else if (!strcasecmp(argv[1], "dtson")) + cc_config_new = CONF_DTSON(cc_config_new); else return EC_ERROR_PARAM2; } @@ -1141,7 +1155,7 @@ static int command_cc(int argc, char **argv) } DECLARE_CONSOLE_COMMAND(cc, command_cc, "[off|on|src|snk|pdsnk|drp|srcdts|snkdts|pdsnkdts|" - "drpdts] [cc1|cc2]", + "drpdts|dtsoff|dtson] [cc1|cc2]", "Servo_v4 DTS and CHG mode"); static void fake_disconnect_end(void) @@ -1161,7 +1175,7 @@ static void fake_disconnect_start(void) } DECLARE_DEFERRED(fake_disconnect_start); -static int cmd_fake_disconnect(int argc, char *argv[]) +static int cmd_fake_disconnect(int argc, const char *argv[]) { int delay_ms, duration_ms; char *e; @@ -1183,41 +1197,36 @@ static int cmd_fake_disconnect(int argc, char *argv[]) fake_pd_disconnect_duration_us = duration_ms * MSEC; hook_call_deferred(&fake_disconnect_start_data, delay_ms * MSEC); - ccprintf("Fake disconnect for %d ms starting in %d ms.\n", - duration_ms, delay_ms); + ccprintf("Fake disconnect for %d ms starting in %d ms.\n", duration_ms, + delay_ms); return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(fakedisconnect, cmd_fake_disconnect, " ", NULL); -static int cmd_ada_srccaps(int argc, char *argv[]) +static int cmd_ada_srccaps(int argc, const char *argv[]) { int i; - const uint32_t * const ada_srccaps = pd_get_src_caps(CHG); + const uint32_t *const ada_srccaps = pd_get_src_caps(CHG); for (i = 0; i < pd_get_src_cap_cnt(CHG); ++i) { - uint32_t max_ma, max_mv; + uint32_t max_ma, max_mv, unused; + + if (IS_ENABLED(CONFIG_USB_PD_ONLY_FIXED_PDOS) && + (ada_srccaps[i] & PDO_TYPE_MASK) != PDO_TYPE_FIXED) + continue; - pd_extract_pdo_power(ada_srccaps[i], &max_ma, &max_mv); + pd_extract_pdo_power(ada_srccaps[i], &max_ma, &max_mv, &unused); ccprintf("%d: %dmV/%dmA\n", i, max_mv, max_ma); } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(ada_srccaps, cmd_ada_srccaps, - "", +DECLARE_CONSOLE_COMMAND(ada_srccaps, cmd_ada_srccaps, "", "Print adapter SrcCap"); -static void chg_pd_disconnect(void) -{ - /* Clear charger PDO on CHG port disconnected. */ - if (pd_is_disconnected(CHG)) - pd_set_src_caps(CHG, 0, NULL); -} -DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, chg_pd_disconnect, HOOK_PRIO_DEFAULT); - -static int cmd_dp_action(int argc, char *argv[]) +static int cmd_dp_action(int argc, const char *argv[]) { int i; char *e; @@ -1236,8 +1245,8 @@ static int cmd_dp_action(int argc, char *argv[]) alt_dp_config &= ~ALT_DP_ENABLE; } else if (!strcasecmp(argv[1], "pins")) { if (argc >= 3) { - alt_dp_config &= ~(ALT_DP_PIN_C | ALT_DP_PIN_D | - ALT_DP_PIN_E); + alt_dp_config &= + ~(ALT_DP_PIN_C | ALT_DP_PIN_D | ALT_DP_PIN_E); for (i = 0; i < 3; i++) { if (!argv[2][i]) break; @@ -1310,10 +1319,10 @@ static int cmd_dp_action(int argc, char *argv[]) } } CPRINTS("HPD source: %s", - (alt_dp_config & ALT_DP_OVERRIDE_HPD) ? "overridden" - : "external"); + (alt_dp_config & ALT_DP_OVERRIDE_HPD) ? "overridden" : + "external"); CPRINTS("HPD level: %d", get_hpd_level()); - } else if (!strcasecmp(argv[1], "help")) { + } else if (!strcasecmp(argv[1], "help")) { CPRINTS("Usage: usbc_action dp [enable|disable|hpd|mf|pins|" "plug]"); } @@ -1321,7 +1330,7 @@ static int cmd_dp_action(int argc, char *argv[]) return EC_SUCCESS; } -static int cmd_usbc_action(int argc, char *argv[]) +static int cmd_usbc_action(int argc, const char *argv[]) { if (argc >= 2 && !strcasecmp(argv[1], "dp")) return cmd_dp_action(argc - 1, &argv[1]); @@ -1375,6 +1384,27 @@ static int cmd_usbc_action(int argc, char *argv[]) * Drop this message if when we phase out the usbc_role control. */ ccprintf("CHG SRC %dmV\n", user_limited_max_mv); + } else if (!strcasecmp(argv[1], "drswap")) { + if (argc == 2) { + CPRINTF("allow_dr_swap = %d\n", allow_dr_swap); + return EC_SUCCESS; + } + + if (argc != 3) + return EC_ERROR_PARAM2; + + allow_dr_swap = !!atoi(argv[2]); + + } else if (!strcasecmp(argv[1], "prswap")) { + if (argc == 2) { + CPRINTF("allow_pr_swap = %d\n", allow_pr_swap); + return EC_SUCCESS; + } + + if (argc != 3) + return EC_ERROR_PARAM2; + + allow_pr_swap = !!atoi(argv[2]); } else { return EC_ERROR_PARAM1; } @@ -1382,5 +1412,6 @@ static int cmd_usbc_action(int argc, char *argv[]) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(usbc_action, cmd_usbc_action, - "5v|12v|20v|dev|pol0|pol1|drp|dp|chg x(x=voltage)", + "5v|12v|20v|dev|pol0|pol1|drp|dp|chg x(x=voltage)|" + "drswap [1|0]|prswap [1|0]", "Set Servo v4 type-C port state"); diff --git a/board/servo_v4/vif_override.xml b/board/servo_v4/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/servo_v4/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/servo_v4p1/OWNERS b/board/servo_v4p1/OWNERS new file mode 100644 index 0000000000..8f4be1ea4d --- /dev/null +++ b/board/servo_v4p1/OWNERS @@ -0,0 +1,3 @@ +bnemec@google.com +matthewb@chromium.org +shurst@google.com diff --git a/board/servo_v4p1/board.c b/board/servo_v4p1/board.c index 6148358aff..24ffbbe84f 100644 --- a/board/servo_v4p1/board.c +++ b/board/servo_v4p1/board.c @@ -1,16 +1,16 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Servo V4p1 configuration */ #include "adc.h" -#include "adc_chip.h" #include "ccd_measure_sbu.h" #include "chg_control.h" #include "common.h" #include "console.h" #include "dacs.h" +#include "driver/ioexpander/tca64xxa.h" #include "ec_version.h" #include "fusb302b.h" #include "gpio.h" @@ -29,15 +29,18 @@ #include "tusb1064.h" #include "update_fw.h" #include "usart-stm32f0.h" -#include "usart_tx_dma.h" #include "usart_rx_dma.h" +#include "usart_tx_dma.h" +#include "usb-stream.h" #include "usb_gpio.h" #include "usb_i2c.h" +#include "usb_mux.h" #include "usb_pd.h" #include "usb_spi.h" -#include "usb-stream.h" #include "util.h" +#include + #ifdef SECTION_IS_RO #define CROS_EC_SECTION "RO" #else @@ -63,6 +66,146 @@ static void tca_evt(enum gpio_signal signal) irq_ioexpanders(); } +/* + * Some DUTs are known to be incompatible with servo_v4p1 and USB3. + * Due to this USB3 to DUT is forced to be disabled by default. + * This command can enable or disable USB3 to DUT manually. + * This command is issued during initialization of servod, + * automatically enabling USB3 only on DUTs that are known to work + * with USB3 servo. + * For more information please refer to b/254857085 and b/263573379. + */ +static bool usb3_to_dut_enable; +static int cmd_dut_usb3(int argc, const char *argv[]) +{ + mux_state_t mux_state; + + if (argc > 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "enable")) { + /* + * Need to set this flag before usb_mux_set to prevent + * calling additional set in board_tusb1064_set. + */ + usb3_to_dut_enable = true; + + /* Need to reset DUT hub and force re-enumeration. */ + gpio_set_level(GPIO_DUT_HUB_USB_RESET_L, 0); + + /* Overwrite current Type-C mux state to enable USB3. */ + mux_state = usb_mux_get(DUT) | USB_PD_MUX_USB_ENABLED; + + usb_mux_set(DUT, mux_state, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(DUT))); + + /* Delay enabling DUT hub to avoid enumeration problems. */ + usleep(MSEC); + gpio_set_level(GPIO_DUT_HUB_USB_RESET_L, 1); + } else if (!strcasecmp(argv[1], "disable")) { + /* + * Make sure this flag is set to avoid calling additional + * mux set operation in board specific routine. + */ + usb3_to_dut_enable = true; + + /* No need to reset hub, devices should auto re-enumerate. */ + mux_state = usb_mux_get(DUT) & ~USB_PD_MUX_USB_ENABLED; + + usb_mux_set(DUT, mux_state, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(DUT))); + usb3_to_dut_enable = false; + } else if (argc != 1) { + ccprintf("Invalid argument: %s\n", argv[1]); + return EC_ERROR_INVAL; + } + + ccprintf("USB3 to DUT: %s\n", + usb3_to_dut_enable ? "allowed/enabled" : "disabled"); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(dut_usb3, cmd_dut_usb3, "dut_usb3 [enable/disable]>", + "Enable or disable USB3 to DUT. Note that after every " + "'dut_usb3 enable' USB3 is enabled once and than only " + "allowed, not forced. Some other part of servo logic " + "(e.g. pd stack) can still enable/disable it."); + +/* + * TUSB1064 set mux board tuning. + * Adds in board specific gain and DP lane count configuration. + * Also adds USB3 quirk. + */ +static int board_tusb1064_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + bool unused; + + /* + * Apply 10dB gain. Note, this value is selected to match the gain that + * would be set by default if the 2 GPIO gain set pins are left + * floating. + */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + rv = tusb1064_set_dp_rx_eq(me, TUSB1064_DP_EQ_RX_10_0_DB); + /* + * There is no need to perform any of additional + * USB3 workaround related logic if we are using DP, so return. + */ + return rv; + } + + /* + * This function is issued after standard set operation. + * Logic below overwrites any mux set operation issued by e.g. + * pd stack. It prevents using USB3 to DUT on servo, unless + * it is explicitly allowed. + * If user is sure that specific DUT works with USB3 servo_v4p1, + * can skip this logic setting usb3_to_dut_enable flag. + * It can be done via console command usb3_dut [on\off]. + */ + if (!usb3_to_dut_enable) { + /* + * In this point servo is already connected to DUT. + * USB3 can be already enabled for short moment. + * Keep DUT hub in reset until MUX is finally set + * (USB3 disabled) to prevent any enumeration issues. + */ + gpio_set_level(GPIO_DUT_HUB_USB_RESET_L, 0); + + /* + * Overwrite any set operation to disable USB3. + * Note that we can use internal driver call as mux driver + * already locked mutex inside usb_mux_set operation. + * Also note that we can not use usb_mux_set to prevent + * infinite recursion. + */ + rv = tusb1064_set_mux(me, mux_state & ~USB_PD_MUX_USB_ENABLED, + &unused); + + /* MUX is set, add preventive delay and enable DUT USB hub. */ + usleep(MSEC); + gpio_set_level(GPIO_DUT_HUB_USB_RESET_L, 1); + } + return rv; +} + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [CHG] = { + /* CHG port connected directly to USB 3.0 hub, no mux */ + }, + [DUT] = { + /* DUT port with UFP mux */ + .mux = + &(const struct usb_mux){ + .usb_port = DUT, + .i2c_port = I2C_PORT_MASTER, + .i2c_addr_flags = TUSB1064_I2C_ADDR10_FLAGS, + .driver = &tusb1064_usb_mux_driver, + .board_set = &board_tusb1064_set, + }, + } +}; + static volatile uint64_t hpd_prev_ts; static volatile int hpd_prev_level; @@ -90,7 +233,7 @@ static volatile int hpd_prev_level; void hpd_irq_deferred(void) { - int dp_mode = pd_alt_mode(1, TCPC_TX_SOP, USB_SID_DISPLAYPORT); + int dp_mode = pd_alt_mode(1, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); if (dp_mode) { pd_send_hpd(DUT, hpd_irq); @@ -102,7 +245,7 @@ DECLARE_DEFERRED(hpd_irq_deferred); void hpd_lvl_deferred(void) { int level = gpio_get_level(GPIO_DP_HPD); - int dp_mode = pd_alt_mode(1, TCPC_TX_SOP, USB_SID_DISPLAYPORT); + int dp_mode = pd_alt_mode(1, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); if (level != hpd_prev_level) { /* It's a glitch while in deferred or canceled action */ @@ -149,21 +292,35 @@ static void tcpc_evt(enum gpio_signal signal) update_status_fusb302b(); } +#define HOST_HUB 0 +struct uhub_i2c_iface_t uhub_config[] = { + { I2C_PORT_MASTER, GL3590_I2C_ADDR0 }, +}; + +static void host_hub_evt(void) +{ + gl3590_irq_handler(HOST_HUB); +} +DECLARE_DEFERRED(host_hub_evt); + static void hub_evt(enum gpio_signal signal) { - ccprintf("hub event\n"); + hook_call_deferred(&host_hub_evt_data, 0); } -static void bc12_evt(enum gpio_signal signal) +static void dut_pwr_evt(enum gpio_signal signal) { - ccprintf("bc12_evt\n"); + ccprintf("dut_pwr_evt\n"); } /* Enable uservo USB. */ static void init_uservo_port(void) { /* Enable USERVO_POWER_EN */ - uservo_power_en(1); + ec_uservo_power_en(1); + + gl3590_enable_ports(0, GL3590_DFP4, 1); + /* Connect uservo to host hub */ uservo_fastboot_mux_sel(0); } @@ -180,34 +337,13 @@ void ext_hpd_detection_enable(int enable) gpio_disable_interrupt(GPIO_DP_HPD); } } -#else -void snk_task(void *u) -{ - /* DO NOTHING */ -} - -void pd_task(void *u) -{ - /* DO NOTHING */ -} -__override uint8_t board_get_usb_pd_port_count(void) -{ - return CONFIG_USB_PD_PORT_MAX_COUNT; -} - -void pd_set_suspend(int port, int suspend) -{ - /* - * Do nothing. This is only here to make the linker happy for this - * old board on ToT. - */ -} #endif /* SECTION_IS_RO */ +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) /****************************************************************************** * Board pre-init function. @@ -251,23 +387,22 @@ void board_config_pre_init(void) /* ADC channels */ const struct adc_t adc_channels[] = { /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_CHG_CC1_PD] = {"CHG_CC1_PD", 3300, 4096, 0, STM32_AIN(2)}, - [ADC_CHG_CC2_PD] = {"CHG_CC2_PD", 3300, 4096, 0, STM32_AIN(4)}, - [ADC_DUT_CC1_PD] = {"DUT_CC1_PD", 3300, 4096, 0, STM32_AIN(0)}, - [ADC_DUT_CC2_PD] = {"DUT_CC2_PD", 3300, 4096, 0, STM32_AIN(5)}, - [ADC_SBU1_DET] = {"SBU1_DET", 3300, 4096, 0, STM32_AIN(3)}, - [ADC_SBU2_DET] = {"SBU2_DET", 3300, 4096, 0, STM32_AIN(7)}, - [ADC_SUB_C_REF] = {"SUB_C_REF", 3300, 4096, 0, STM32_AIN(1)}, + [ADC_CHG_CC1_PD] = { "CHG_CC1_PD", 3300, 4096, 0, STM32_AIN(2) }, + [ADC_CHG_CC2_PD] = { "CHG_CC2_PD", 3300, 4096, 0, STM32_AIN(4) }, + [ADC_DUT_CC1_PD] = { "DUT_CC1_PD", 3300, 4096, 0, STM32_AIN(0) }, + [ADC_DUT_CC2_PD] = { "DUT_CC2_PD", 3300, 4096, 0, STM32_AIN(5) }, + [ADC_SBU1_DET] = { "SBU1_DET", 3300, 4096, 0, STM32_AIN(3) }, + [ADC_SBU2_DET] = { "SBU2_DET", 3300, 4096, 0, STM32_AIN(7) }, + [ADC_SUB_C_REF] = { "SUB_C_REF", 3300, 4096, 0, STM32_AIN(1) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - /****************************************************************************** * Forward UARTs as a USB serial interface. */ -#define USB_STREAM_RX_SIZE 16 -#define USB_STREAM_TX_SIZE 16 +#define USB_STREAM_RX_SIZE 16 +#define USB_STREAM_TX_SIZE 16 /****************************************************************************** * Forward USART3 as a simple USB serial interface. @@ -276,29 +411,19 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); static struct usart_config const usart3; struct usb_stream_config const usart3_usb; -static struct queue const usart3_to_usb = QUEUE_DIRECT(64, uint8_t, - usart3.producer, usart3_usb.consumer); -static struct queue const usb_to_usart3 = QUEUE_DIRECT(64, uint8_t, - usart3_usb.producer, usart3.consumer); +static struct queue const usart3_to_usb = + QUEUE_DIRECT(64, uint8_t, usart3.producer, usart3_usb.consumer); +static struct queue const usb_to_usart3 = + QUEUE_DIRECT(64, uint8_t, usart3_usb.producer, usart3.consumer); static struct usart_config const usart3 = - USART_CONFIG(usart3_hw, - usart_rx_interrupt, - usart_tx_interrupt, - 115200, - 0, - usart3_to_usb, - usb_to_usart3); - -USB_STREAM_CONFIG(usart3_usb, - USB_IFACE_USART3_STREAM, - USB_STR_USART3_STREAM_NAME, - USB_EP_USART3_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart3, - usart3_to_usb) + USART_CONFIG(usart3_hw, usart_rx_interrupt, usart_tx_interrupt, 115200, + 0, usart3_to_usb, usb_to_usart3); +USB_STREAM_CONFIG(usart3_usb, USB_IFACE_USART3_STREAM, + USB_STR_USART3_STREAM_NAME, USB_EP_USART3_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, usb_to_usart3, + usart3_to_usb) /****************************************************************************** * Forward USART4 as a simple USB serial interface. @@ -307,64 +432,73 @@ USB_STREAM_CONFIG(usart3_usb, static struct usart_config const usart4; struct usb_stream_config const usart4_usb; -static struct queue const usart4_to_usb = QUEUE_DIRECT(64, uint8_t, - usart4.producer, usart4_usb.consumer); -static struct queue const usb_to_usart4 = QUEUE_DIRECT(64, uint8_t, - usart4_usb.producer, usart4.consumer); +static struct queue const usart4_to_usb = + QUEUE_DIRECT(64, uint8_t, usart4.producer, usart4_usb.consumer); +static struct queue const usb_to_usart4 = + QUEUE_DIRECT(64, uint8_t, usart4_usb.producer, usart4.consumer); static struct usart_config const usart4 = - USART_CONFIG(usart4_hw, - usart_rx_interrupt, - usart_tx_interrupt, - 9600, - 0, - usart4_to_usb, - usb_to_usart4); - -USB_STREAM_CONFIG(usart4_usb, - USB_IFACE_USART4_STREAM, - USB_STR_USART4_STREAM_NAME, - USB_EP_USART4_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart4, - usart4_to_usb) + USART_CONFIG(usart4_hw, usart_rx_interrupt, usart_tx_interrupt, 9600, 0, + usart4_to_usb, usb_to_usart4); + +USB_STREAM_CONFIG_USART_IFACE(usart4_usb, USB_IFACE_USART4_STREAM, + USB_STR_USART4_STREAM_NAME, USB_EP_USART4_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, + usb_to_usart4, usart4_to_usb, usart4) +/* + * Define usb interface descriptor for the `EMPTY` usb interface, to satisfy + * UEFI and kernel requirements (see b/183857501). + */ +const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_EMPTY) = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = USB_IFACE_EMPTY, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, +}; /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("Servo V4p1"), - [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Servo V4p1"), + [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Servo EC Shell"), - [USB_STR_USART3_STREAM_NAME] = USB_STRING_DESC("DUT UART"), - [USB_STR_USART4_STREAM_NAME] = USB_STRING_DESC("Atmega UART"), - [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), + [USB_STR_USART3_STREAM_NAME] = USB_STRING_DESC("DUT UART"), + [USB_STR_USART4_STREAM_NAME] = USB_STRING_DESC("Atmega UART"), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); - - /****************************************************************************** * Support I2C bridging over USB. */ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + { .name = "master", + .port = I2C_PORT_MASTER, + .kbps = 100, + .scl = GPIO_MASTER_I2C_SCL, + .sda = GPIO_MASTER_I2C_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -int usb_i2c_board_is_enabled(void) { return 1; } - +int usb_i2c_board_is_enabled(void) +{ + return 1; +} /****************************************************************************** * Initialize board. @@ -375,6 +509,36 @@ int board_get_version(void) return board_id_det(); } +#ifdef SECTION_IS_RO +/* Forward declaration */ +static void evaluate_input_power_def(void); +DECLARE_DEFERRED(evaluate_input_power_def); + +static void evaluate_input_power_def(void) +{ + int state; + static int retry = 3; + + /* Wait until host hub INTR# signal is asserted */ + state = gpio_get_level(GPIO_USBH_I2C_BUSY_INT); + if ((state == 0) && retry--) { + hook_call_deferred(&evaluate_input_power_def_data, 100 * MSEC); + return; + } + + if (retry == 0) + CPRINTF("Host hub I2C isn't online, expect issues with its " + "behaviour\n"); + + gpio_enable_interrupt(GPIO_USBH_I2C_BUSY_INT); + + gl3590_init(HOST_HUB); + + init_uservo_port(); + init_pathsel(); +} +#endif + static void board_init(void) { /* USB to serial queues */ @@ -390,23 +554,33 @@ static void board_init(void) /* Delay DUT hub to avoid brownout. */ usleep(MSEC); - init_ioexpanders(); - init_dacs(); - init_tusb1064(1); init_pi3usb9201(); /* Clear BBRAM, we don't want any PD state carried over on reset. */ system_set_bbram(SYSTEM_BBRAM_IDX_PD0, 0); system_set_bbram(SYSTEM_BBRAM_IDX_PD1, 0); - /* Bring atmel part out of reset */ - atmel_reset_l(1); - #ifdef SECTION_IS_RO + init_ioexpanders(); + CPRINTS("Board ID is %d", board_id_det()); + + init_dacs(); init_uservo_port(); init_pathsel(); init_ina231s(); init_fusb302b(1); + vbus_dischrg_en(0); + + /* Bring atmel part out of reset */ + atmel_reset_l(1); + + /* + * Get data about available input power. Defer this check, since we need + * to wait for USB2/USB3 enumeration on host hub as well as I2C + * interface of this hub needs to be initialized. Genesys recommends at + * least 100ms. + */ + hook_call_deferred(&evaluate_input_power_def_data, 100 * MSEC); /* Enable DUT USB2.0 pair. */ gpio_set_level(GPIO_FASTBOOT_DUTHUB_MUX_EN_L, 0); @@ -417,8 +591,7 @@ static void board_init(void) gpio_enable_interrupt(GPIO_STM_FAULT_IRQ_L); gpio_enable_interrupt(GPIO_DP_HPD); - gpio_enable_interrupt(GPIO_USBH_I2C_BUSY_INT); - gpio_enable_interrupt(GPIO_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_DUT_PWR_IRQ_ODL); /* Disable power to DUT by default */ chg_power_select(CHG_POWER_OFF); @@ -431,6 +604,8 @@ static void board_init(void) /* Start SuzyQ detection */ start_ccd_meas_sbu_cycle(); +#else /* SECTION_IS_RO */ + CPRINTS("Board ID is %d", board_id_det()); #endif /* SECTION_IS_RO */ } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -456,4 +631,16 @@ void tick_event(void) } } DECLARE_HOOK(HOOK_TICK, tick_event, HOOK_PRIO_DEFAULT); + +struct ioexpander_config_t ioex_config[] = { + [0] = { .drv = &tca64xxa_ioexpander_drv, + .i2c_host_port = TCA6416A_PORT, + .i2c_addr_flags = TCA6416A_ADDR, + .flags = IOEX_FLAGS_TCA64XXA_FLAG_VER_TCA6416A }, + [1] = { .drv = &tca64xxa_ioexpander_drv, + .i2c_host_port = TCA6424A_PORT, + .i2c_addr_flags = TCA6424A_ADDR, + .flags = IOEX_FLAGS_TCA64XXA_FLAG_VER_TCA6424A } +}; + #endif /* SECTION_IS_RO */ diff --git a/board/servo_v4p1/board.h b/board/servo_v4p1/board.h index 471dd93177..4debd67b49 100644 --- a/board/servo_v4p1/board.h +++ b/board/servo_v4p1/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,8 +11,6 @@ /* Use Link-Time Optimizations to try to reduce the firmware code size */ #define CONFIG_LTO -#define CONFIG_BOARD_VERSION_CUSTOM - /* 48 MHz SYSCLK clock frequency */ #define CPU_CLOCK 48000000 @@ -23,6 +21,14 @@ #define CHG 0 #define DUT 1 +/* + * IO expanders I2C addresses and ports + */ +#define TCA6416A_PORT 1 +#define TCA6416A_ADDR 0x21 +#define TCA6424A_PORT 1 +#define TCA6424A_ADDR 0x23 + /* * Flash layout: we redefine the sections offsets and sizes as we want to * include a pstate region, and will use RO/RW regions of different sizes. @@ -52,31 +58,30 @@ #define CONFIG_RAM_BANK_SIZE CONFIG_RAM_SIZE - #define CONFIG_FLASH_PSTATE #define CONFIG_FLASH_PSTATE_BANK -#define CONFIG_SHAREDLIB_SIZE 0 +#define CONFIG_SHAREDLIB_SIZE 0 -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RO_SIZE (92*1024) +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (92 * 1024) -#define CONFIG_FW_PSTATE_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) -#define CONFIG_FW_PSTATE_SIZE CONFIG_FLASH_BANK_SIZE +#define CONFIG_FW_PSTATE_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) +#define CONFIG_FW_PSTATE_SIZE CONFIG_FLASH_BANK_SIZE -#define CONFIG_RW_MEM_OFF (CONFIG_FW_PSTATE_OFF + CONFIG_FW_PSTATE_SIZE) -#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE - \ - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) +#define CONFIG_RW_MEM_OFF (CONFIG_FW_PSTATE_OFF + CONFIG_FW_PSTATE_SIZE) +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) -#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE +#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* Enable USART1,3,4 and USB streams */ #define CONFIG_STREAM_USART @@ -85,8 +90,13 @@ #define CONFIG_STREAM_USB #define CONFIG_CMD_USART_INFO +/* The UART console is on USART1 (PA9/PA10) */ +#undef CONFIG_UART_CONSOLE +#define CONFIG_UART_CONSOLE 1 +#undef CONFIG_UART_TX_DMA +#undef CONFIG_UART_RX_DMA + /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_HW_CRC #define CONFIG_PVD /* @@ -94,7 +104,7 @@ * STM32F072x8 Datasheet. PVD Threshold 1 corresponds to a * falling voltage threshold of min:2.09V, max:2.27V. */ -#define PVD_THRESHOLD (1) +#define PVD_THRESHOLD (1) /* USB Configuration */ #define CONFIG_USB @@ -113,27 +123,35 @@ #define DEFAULT_MAC_ADDR "Uninitialized" /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_CONSOLE 0 -#define USB_IFACE_EMPTY 1 -#define USB_IFACE_I2C 2 -#define USB_IFACE_USART3_STREAM 3 -#define USB_IFACE_USART4_STREAM 4 -#define USB_IFACE_UPDATE 5 -#define USB_IFACE_COUNT 6 +#define USB_IFACE_CONSOLE 0 +#define USB_IFACE_EMPTY 1 +#define USB_IFACE_I2C 2 +#define USB_IFACE_USART3_STREAM 3 +#define USB_IFACE_USART4_STREAM 4 +#define USB_IFACE_UPDATE 5 +#define USB_IFACE_COUNT 6 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_CONSOLE 1 -#define USB_EP_EMPTY 2 -#define USB_EP_I2C 3 -#define USB_EP_USART3_STREAM 4 -#define USB_EP_USART4_STREAM 5 -#define USB_EP_UPDATE 6 -#define USB_EP_COUNT 7 +#define USB_EP_CONTROL 0 +#define USB_EP_CONSOLE 1 +#define USB_EP_EMPTY 2 +#define USB_EP_I2C 3 +#define USB_EP_USART3_STREAM 4 +#define USB_EP_USART4_STREAM 5 +#define USB_EP_UPDATE 6 +#define USB_EP_COUNT 7 /* Enable console recasting of GPIO type. */ #define CONFIG_CMD_GPIO_EXTENDED +/* Enable I/O expander */ +#ifdef SECTION_IS_RO +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_SUPPORT_GET_PORT +#define CONFIG_IO_EXPANDER_TCA64XXA +#define CONFIG_IO_EXPANDER_PORT_COUNT 2 +#endif + /* This is not actually an EC so disable some features. */ #undef CONFIG_WATCHDOG_HELP #undef CONFIG_LID_SWITCH @@ -157,12 +175,12 @@ /* Enable control of I2C over USB */ #define CONFIG_USB_I2C #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define I2C_PORT_MASTER 1 /* PD features */ #define CONFIG_ADC -#undef CONFIG_ADC_WATCHDOG +#undef CONFIG_ADC_WATCHDOG #define CONFIG_BOARD_PRE_INIT /* * If task profiling is enabled then the rx falling edge detection interrupts @@ -173,9 +191,11 @@ #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #ifdef SECTION_IS_RO +#define CONFIG_USB_HUB_GL3590 #define CONFIG_INA231 #define CONFIG_CHARGE_MANAGER -#undef CONFIG_CHARGE_MANAGER_SAFE_MODE +#undef CONFIG_CHARGE_MANAGER_SAFE_MODE +#define CONFIG_USB_MUX_TUSB1064 #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_TCPMV1 #define CONFIG_CMD_PD @@ -186,32 +206,45 @@ #define CONFIG_USB_PD_TCPC #define CONFIG_USB_PD_TCPM_STUB #undef CONFIG_USB_PD_PULLUP +/* Default pull-up should not be Rp3a0 due to Cr50 */ #define CONFIG_USB_PD_PULLUP TYPEC_RP_USB #define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT +#define CONFIG_USB_PD_ONLY_FIXED_PDOS #define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USBC_SS_MUX +#define CONFIG_USBC_SS_MUX_UFP_ONLY /* Don't automatically change roles */ #undef CONFIG_USB_PD_INITIAL_DRP_STATE #define CONFIG_USB_PD_INITIAL_DRP_STATE PD_DRP_FORCE_SINK /* Variable-current Rp no connect and Ra attach macros */ -#define CC_NC(port, cc, sel) (pd_tcpc_cc_nc(port, cc, sel)) -#define CC_RA(port, cc, sel) (pd_tcpc_cc_ra(port, cc, sel)) +#define CC_NC(port, cc, sel) (pd_tcpc_cc_nc(port, cc, sel)) +#define CC_RA(port, cc, sel) (pd_tcpc_cc_ra(port, cc, sel)) /* - * TODO(crosbug.com/p/60792): The delay values are currently just place holders - * and the delay will need to be relative to the circuitry that allows VBUS to - * be supplied to the DUT port from the CHG port. + * These power-supply timing values are now set towards maximum spec limit, + * to give the upstream charger the maximum time to respond. + * + * Currently tuned with the Apple 96W adapter. + * TODO: Change to EVENT-based PS_RDY notification (b/214216304) */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY (121 * MSEC) +#define PD_POWER_SUPPLY_TURN_OFF_DELAY (461 * MSEC) /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 100000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* Add the raw option to the i2c_xfer command */ +#define CONFIG_CMD_I2C_XFER_RAW + +/* Enable command for managing host hub */ +#define CONFIG_CMD_GL3590 #else +#undef CONFIG_CMD_I2C_XFER #undef CONFIG_USB_POWER_DELIVERY #endif /* SECTION_IS_RO */ @@ -231,8 +264,7 @@ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 - +#define TIM_ADC 3 #include "gpio_signal.h" @@ -251,7 +283,6 @@ enum usb_strings { USB_STR_COUNT }; - /* ADC signal */ enum adc_channel { ADC_CHG_CC1_PD, @@ -265,6 +296,14 @@ enum adc_channel { ADC_CH_COUNT }; +/* Servo V4.1 Board ID mappings */ +enum servo_board_id { + BOARD_ID_UNSET = -1, + BOARD_ID_REV0 = 0, /* Proto */ + BOARD_ID_REV1 = 1, /* EVT */ + BOARD_ID_REV2 = 2, /* DVT */ +}; + /** * Compare cc_voltage to disconnect threshold * diff --git a/board/servo_v4p1/build.mk b/board/servo_v4p1/build.mk index a8d22ccbc3..c1e8db9cd8 100644 --- a/board/servo_v4p1/build.mk +++ b/board/servo_v4p1/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -14,10 +14,9 @@ CHIP_VARIANT:=stm32f07x test-list-y= # These files are compiled into RO and RW -board-y=board.o tca6416a.o tca6424a.o +board-y=board.o board-y+=ioexpanders.o board-y+=dacs.o -board-y+=tusb1064.o board-y+=pi3usb9201.o # These files are compiled into RO only diff --git a/board/servo_v4p1/ccd_measure_sbu.c b/board/servo_v4p1/ccd_measure_sbu.c index b9c9680cc9..41d53ab597 100644 --- a/board/servo_v4p1/ccd_measure_sbu.c +++ b/board/servo_v4p1/ccd_measure_sbu.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,8 +11,8 @@ #include "ioexpanders.h" #include "timer.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) /* * Define voltage thresholds for SBU USB detection. @@ -20,15 +20,15 @@ * Max observed USB low across sampled systems: 666mV * Min observed USB high across sampled systems: 3026mV */ -#define GND_MAX_MV 700 -#define USB_HIGH_MV 2500 -#define SBU_DIRECT 0 -#define SBU_FLIP 1 +#define GND_MAX_MV 700 +#define USB_HIGH_MV 2500 +#define SBU_DIRECT 0 +#define SBU_FLIP 1 -#define MODE_SBU_DISCONNECT 0 -#define MODE_SBU_CONNECT 1 -#define MODE_SBU_FLIP 2 -#define MODE_SBU_OTHER 3 +#define MODE_SBU_DISCONNECT 0 +#define MODE_SBU_CONNECT 1 +#define MODE_SBU_FLIP 2 +#define MODE_SBU_OTHER 3 static void ccd_measure_sbu(void); DECLARE_DEFERRED(ccd_measure_sbu); diff --git a/board/servo_v4p1/ccd_measure_sbu.h b/board/servo_v4p1/ccd_measure_sbu.h index 0dd1ce0de7..8635f892a4 100644 --- a/board/servo_v4p1/ccd_measure_sbu.h +++ b/board/servo_v4p1/ccd_measure_sbu.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/servo_v4p1/chg_control.c b/board/servo_v4p1/chg_control.c index cddd8efc69..76f3dc9649 100644 --- a/board/servo_v4p1/chg_control.c +++ b/board/servo_v4p1/chg_control.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,8 +8,9 @@ #include "ioexpanders.h" #include "registers.h" #include "timer.h" +#include "usb_pd.h" -#define CHG_P5V_POWER 0 +#define CHG_P5V_POWER 0 #define CHG_VBUS_POWER 1 void chg_reset(void) @@ -20,7 +21,8 @@ void chg_reset(void) /* Disconnect CHG CC1(Rd) and CC2(Rd) */ chg_attach_cc_rds(0); - msleep(100); + /* Give time for CHG to detach, use tErrorRecovery. */ + msleep(PD_T_ERROR_RECOVERY); /* Connect CHG CC1(Rd) and CC2(Rd) to detect charger */ chg_attach_cc_rds(1); @@ -53,9 +55,11 @@ void chg_attach_cc_rds(bool en) * Configure USB_CHG_CC1_MCU and USB_CHG_CC2_MCU as * ANALOG input */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - | (3 << (2*2)) | /* PA2 in ANALOG mode */ - (3 << (2*4))); /* PA4 in ANALOG mode */ + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) | (3 << (2 * 2)) | /* PA2 in + ANALOG + mode */ + (3 << (2 * 4))); /* PA4 in ANALOG mode */ } else { /* * Configure USB_CHG_CC1_MCU and USB_CHG_CC2_MCU as GPIO and @@ -69,10 +73,12 @@ void chg_attach_cc_rds(bool en) gpio_set_level(GPIO_USB_CHG_CC2_MCU, 1); /* Disable Analog mode and Enable GPO */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) - & ~(3 << (2*2) | /* PA2 disable ADC */ - 3 << (2*4))) /* PA4 disable ADC */ - | (1 << (2*2) | /* Set as GPO */ - 1 << (2*4)); /* Set as GPO */ + STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) & + ~(3 << (2 * 2) | /* PA2 disable ADC + */ + 3 << (2 * 4))) /* PA4 disable ADC + */ + | (1 << (2 * 2) | /* Set as GPO */ + 1 << (2 * 4)); /* Set as GPO */ } } diff --git a/board/servo_v4p1/chg_control.h b/board/servo_v4p1/chg_control.h index 8b81708ccc..91e3601ac8 100644 --- a/board/servo_v4p1/chg_control.h +++ b/board/servo_v4p1/chg_control.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,11 +8,7 @@ #include -enum chg_cc_t { - CHG_OPEN, - CHG_CC1, - CHG_CC2 -}; +enum chg_cc_t { CHG_OPEN, CHG_CC1, CHG_CC2 }; enum chg_power_select_t { CHG_POWER_OFF, diff --git a/board/servo_v4p1/dacs.c b/board/servo_v4p1/dacs.c index b5c62bb438..355e27684b 100644 --- a/board/servo_v4p1/dacs.c +++ b/board/servo_v4p1/dacs.c @@ -1,8 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "console.h" #include "dacs.h" #include "i2c.h" #include "ioexpanders.h" @@ -13,17 +14,17 @@ #define CC1_DAC_ADDR 0x48 #define CC2_DAC_ADDR 0x49 -#define REG_NOOP 0 -#define REG_DEVID 1 -#define REG_SYNC 2 -#define REG_CONFIG 3 -#define REG_GAIN 4 +#define REG_NOOP 0 +#define REG_DEVID 1 +#define REG_SYNC 2 +#define REG_CONFIG 3 +#define REG_GAIN 4 #define REG_TRIGGER 5 -#define REG_STATUS 7 -#define REG_DAC 8 +#define REG_STATUS 7 +#define REG_DAC 8 -#define DAC1 BIT(0) -#define DAC2 BIT(1) +#define DAC1 BIT(0) +#define DAC2 BIT(1) static uint8_t dac_enabled; @@ -101,7 +102,8 @@ int write_dac(enum dac_t dac, uint16_t value) return EC_SUCCESS; } -static int cmd_cc_dac(int argc, char *argv[]) +#ifdef SECTION_IS_RO +static int cmd_cc_dac(int argc, const char *argv[]) { uint8_t dac; uint64_t mv; @@ -133,6 +135,6 @@ static int cmd_cc_dac(int argc, char *argv[]) } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(cc_dac, cmd_cc_dac, - "dac <\"on\"|\"off\"|mv>", +DECLARE_CONSOLE_COMMAND(cc_dac, cmd_cc_dac, "dac <\"on\"|\"off\"|mv>", "Set Servo v4.1 CC dacs"); +#endif diff --git a/board/servo_v4p1/dacs.h b/board/servo_v4p1/dacs.h index bd0ecd67da..4b2028c648 100644 --- a/board/servo_v4p1/dacs.h +++ b/board/servo_v4p1/dacs.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/servo_v4p1/ec.tasklist b/board/servo_v4p1/ec.tasklist index 3004799adf..6c9abf1c07 100644 --- a/board/servo_v4p1/ec.tasklist +++ b/board/servo_v4p1/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,8 +7,8 @@ * See CONFIG_TASK_LIST in config.h for details. */ #define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C2, snk_task, NULL, VENTI_TASK_STACK_SIZE) + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS_RO(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS_RO(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS_RO(PD_C2, snk_task, NULL, VENTI_TASK_STACK_SIZE) diff --git a/board/servo_v4p1/fusb302b.c b/board/servo_v4p1/fusb302b.c index fabb5b80ad..49959f1d65 100644 --- a/board/servo_v4p1/fusb302b.c +++ b/board/servo_v4p1/fusb302b.c @@ -1,17 +1,17 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "i2c.h" #include "fusb302b.h" #include "gpio.h" #include "hooks.h" +#include "i2c.h" #include "ioexpanders.h" -#include "util.h" #include "task.h" #include "time.h" #include "usb_pd.h" +#include "util.h" static int port; static int status0; @@ -21,12 +21,12 @@ static struct mutex measure_lock; static int tcpc_write(int reg, int val) { - return i2c_write8(port, FUSB302_I2C_SLAVE_ADDR_FLAGS, reg, val); + return i2c_write8(port, FUSB302_I2C_ADDR_FLAGS, reg, val); } static int tcpc_read(int reg, int *val) { - return i2c_read8(port, FUSB302_I2C_SLAVE_ADDR_FLAGS, reg, val); + return i2c_read8(port, FUSB302_I2C_ADDR_FLAGS, reg, val); } int init_fusb302b(int p) @@ -72,7 +72,6 @@ int init_fusb302b(int p) if (ret) return ret; - ret = tcpc_read(TCPC_REG_INTERRUPTA, &interrupta); if (ret) return ret; @@ -159,7 +158,6 @@ int get_cc(int *cc1, int *cc2) else orig_meas_cc2 = 0; - /* Disable CC2 measurement switch, enable CC1 measurement switch */ reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2; reg |= TCPC_REG_SWITCHES0_MEAS_CC1; diff --git a/board/servo_v4p1/fusb302b.h b/board/servo_v4p1/fusb302b.h index eddc97b7ca..cebf5409f5 100644 --- a/board/servo_v4p1/fusb302b.h +++ b/board/servo_v4p1/fusb302b.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,183 +12,183 @@ #define FUSB302_DEVID_302A 0x08 #define FUSB302_DEVID_302B 0x09 -/* I2C slave address varies by part number */ +/* I2C address varies by part number */ /* FUSB302BUCX / FUSB302BMPX */ -#define FUSB302_I2C_SLAVE_ADDR_FLAGS 0x22 +#define FUSB302_I2C_ADDR_FLAGS 0x22 /* FUSB302B01MPX */ -#define FUSB302_I2C_SLAVE_ADDR_B01_FLAGS 0x23 +#define FUSB302_I2C_ADDR_B01_FLAGS 0x23 /* FUSB302B10MPX */ -#define FUSB302_I2C_SLAVE_ADDR_B10_FLAGS 0x24 +#define FUSB302_I2C_ADDR_B10_FLAGS 0x24 /* FUSB302B11MPX */ -#define FUSB302_I2C_SLAVE_ADDR_B11_FLAGS 0x25 - -#define TCPC_REG_DEVICE_ID 0x01 - -#define TCPC_REG_SWITCHES0 0x02 -#define TCPC_REG_SWITCHES0_CC2_PU_EN (1<<7) -#define TCPC_REG_SWITCHES0_CC1_PU_EN (1<<6) -#define TCPC_REG_SWITCHES0_VCONN_CC2 (1<<5) -#define TCPC_REG_SWITCHES0_VCONN_CC1 (1<<4) -#define TCPC_REG_SWITCHES0_MEAS_CC2 (1<<3) -#define TCPC_REG_SWITCHES0_MEAS_CC1 (1<<2) -#define TCPC_REG_SWITCHES0_CC2_PD_EN (1<<1) -#define TCPC_REG_SWITCHES0_CC1_PD_EN (1<<0) - -#define TCPC_REG_SWITCHES1 0x03 -#define TCPC_REG_SWITCHES1_POWERROLE (1<<7) -#define TCPC_REG_SWITCHES1_SPECREV1 (1<<6) -#define TCPC_REG_SWITCHES1_SPECREV0 (1<<5) -#define TCPC_REG_SWITCHES1_DATAROLE (1<<4) -#define TCPC_REG_SWITCHES1_AUTO_GCRC (1<<2) -#define TCPC_REG_SWITCHES1_TXCC2_EN (1<<1) -#define TCPC_REG_SWITCHES1_TXCC1_EN (1<<0) - -#define TCPC_REG_MEASURE 0x04 -#define TCPC_REG_MEASURE_MDAC_MASK 0x3F -#define TCPC_REG_MEASURE_VBUS (1<<6) +#define FUSB302_I2C_ADDR_B11_FLAGS 0x25 + +#define TCPC_REG_DEVICE_ID 0x01 + +#define TCPC_REG_SWITCHES0 0x02 +#define TCPC_REG_SWITCHES0_CC2_PU_EN (1 << 7) +#define TCPC_REG_SWITCHES0_CC1_PU_EN (1 << 6) +#define TCPC_REG_SWITCHES0_VCONN_CC2 (1 << 5) +#define TCPC_REG_SWITCHES0_VCONN_CC1 (1 << 4) +#define TCPC_REG_SWITCHES0_MEAS_CC2 (1 << 3) +#define TCPC_REG_SWITCHES0_MEAS_CC1 (1 << 2) +#define TCPC_REG_SWITCHES0_CC2_PD_EN (1 << 1) +#define TCPC_REG_SWITCHES0_CC1_PD_EN (1 << 0) + +#define TCPC_REG_SWITCHES1 0x03 +#define TCPC_REG_SWITCHES1_POWERROLE (1 << 7) +#define TCPC_REG_SWITCHES1_SPECREV1 (1 << 6) +#define TCPC_REG_SWITCHES1_SPECREV0 (1 << 5) +#define TCPC_REG_SWITCHES1_DATAROLE (1 << 4) +#define TCPC_REG_SWITCHES1_AUTO_GCRC (1 << 2) +#define TCPC_REG_SWITCHES1_TXCC2_EN (1 << 1) +#define TCPC_REG_SWITCHES1_TXCC1_EN (1 << 0) + +#define TCPC_REG_MEASURE 0x04 +#define TCPC_REG_MEASURE_MDAC_MASK 0x3F +#define TCPC_REG_MEASURE_VBUS (1 << 6) /* * MDAC reference voltage step size is 42 mV. Round our thresholds to reduce * maximum error, which also matches suggested thresholds in datasheet * (Table 3. Host Interrupt Summary). */ -#define TCPC_REG_MEASURE_MDAC_MV(mv) (DIV_ROUND_NEAREST((mv), 42) & 0x3f) - -#define TCPC_REG_CONTROL0 0x06 -#define TCPC_REG_CONTROL0_TX_FLUSH (1<<6) -#define TCPC_REG_CONTROL0_INT_MASK (1<<5) -#define TCPC_REG_CONTROL0_HOST_CUR_MASK (3<<2) -#define TCPC_REG_CONTROL0_HOST_CUR_3A0 (3<<2) -#define TCPC_REG_CONTROL0_HOST_CUR_1A5 (2<<2) -#define TCPC_REG_CONTROL0_HOST_CUR_USB (1<<2) -#define TCPC_REG_CONTROL0_TX_START (1<<0) - -#define TCPC_REG_CONTROL1 0x07 -#define TCPC_REG_CONTROL1_ENSOP2DB (1<<6) -#define TCPC_REG_CONTROL1_ENSOP1DB (1<<5) -#define TCPC_REG_CONTROL1_BIST_MODE2 (1<<4) -#define TCPC_REG_CONTROL1_RX_FLUSH (1<<2) -#define TCPC_REG_CONTROL1_ENSOP2 (1<<1) -#define TCPC_REG_CONTROL1_ENSOP1 (1<<0) - -#define TCPC_REG_CONTROL2 0x08 +#define TCPC_REG_MEASURE_MDAC_MV(mv) (DIV_ROUND_NEAREST((mv), 42) & 0x3f) + +#define TCPC_REG_CONTROL0 0x06 +#define TCPC_REG_CONTROL0_TX_FLUSH (1 << 6) +#define TCPC_REG_CONTROL0_INT_MASK (1 << 5) +#define TCPC_REG_CONTROL0_HOST_CUR_MASK (3 << 2) +#define TCPC_REG_CONTROL0_HOST_CUR_3A0 (3 << 2) +#define TCPC_REG_CONTROL0_HOST_CUR_1A5 (2 << 2) +#define TCPC_REG_CONTROL0_HOST_CUR_USB (1 << 2) +#define TCPC_REG_CONTROL0_TX_START (1 << 0) + +#define TCPC_REG_CONTROL1 0x07 +#define TCPC_REG_CONTROL1_ENSOP2DB (1 << 6) +#define TCPC_REG_CONTROL1_ENSOP1DB (1 << 5) +#define TCPC_REG_CONTROL1_BIST_MODE2 (1 << 4) +#define TCPC_REG_CONTROL1_RX_FLUSH (1 << 2) +#define TCPC_REG_CONTROL1_ENSOP2 (1 << 1) +#define TCPC_REG_CONTROL1_ENSOP1 (1 << 0) + +#define TCPC_REG_CONTROL2 0x08 /* two-bit field, valid values below */ -#define TCPC_REG_CONTROL2_MODE_MASK (0x3<ioex, + IOEX_GET_INFO(IOEX_BOARD_ID_DET0)->port, &id)) + return id; - /* Board ID consists of bits 5, 4, and 3 */ - return (id >> 3) & 0x7; + /* Board ID consists of bits 5, 4, and 3 */ + board_id_val = (id >> BOARD_ID_DET_OFFSET) & BOARD_ID_DET_MASK; + } + + return board_id_val; } -inline int cmux_en(int en) +inline int dongle_det(void) { - return tca6416a_write_bit(1, TCA6416A_OUT_PORT_1, 6, en); + int val; + ioex_get_level(IOEX_DONGLE_DET, &val); + return val; } -inline int dongle_det(void) +inline int get_host_chrg_det(void) { - return tca6416a_read_bit(1, TCA6416A_IN_PORT_1, 7); + int val; + ioex_get_level(IOEX_HOST_CHRG_DET, &val); + return val; } inline int en_pp5000_alt_3p3(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_0, 0, en); + return ioex_set_level(IOEX_EN_PP5000_ALT_3P3, en); } inline int en_pp3300_eth(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_0, 1, en); + return ioex_set_level(IOEX_EN_PP3300_ETH, en); } inline int en_pp3300_dp(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_0, 2, en); + return ioex_set_level(IOEX_EN_PP3300_DP, en); } inline int fault_clear_cc(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_0, 3, en); + return ioex_set_level(IOEX_FAULT_CLEAR_CC, en); } inline int en_vout_buf_cc1(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_0, 4, en); + return ioex_set_level(IOEX_EN_VOUT_BUF_CC1, en); } inline int en_vout_buf_cc2(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_0, 5, en); + return ioex_set_level(IOEX_EN_VOUT_BUF_CC2, en); } int dut_chg_en(int en) { dut_chg_en_state = en; - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_0, 6, en); + return ioex_set_level(IOEX_DUT_CHG_EN, en); } int get_dut_chg_en(void) @@ -288,25 +287,70 @@ int get_dut_chg_en(void) inline int host_or_chg_ctl(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_0, 7, en); + return ioex_set_level(IOEX_HOST_OR_CHG_CTL, en); } inline int read_faults(void) { - return tca6424a_read_byte(1, TCA6424A_IN_PORT_1); + int val; + + ioex_get_port(IOEX_GET_INFO(IOEX_USERVO_FAULT_L)->ioex, + IOEX_GET_INFO(IOEX_USERVO_FAULT_L)->port, &val); + + return val; +} + +inline int read_irqs(void) +{ + int val; + + ioex_get_port(IOEX_GET_INFO(IOEX_SYS_PWR_IRQ_ODL)->ioex, + IOEX_GET_INFO(IOEX_SYS_PWR_IRQ_ODL)->port, &val); + + return val; } inline int vbus_dischrg_en(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_2, 0, en); + return ioex_set_level(IOEX_VBUS_DISCHRG_EN, en); } inline int usbh_pwrdn_l(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_2, 1, en); + return ioex_set_level(IOEX_USBH_PWRDN_L, en); } inline int tca_gpio_dbg_led_k_odl(int en) { - return tca6424a_write_bit(1, TCA6424A_OUT_PORT_2, 7, !en); + return ioex_set_level(IOEX_TCA_GPIO_DBG_LED_K_ODL, !en); +} + +#else /* SECTION_IS_RO */ + +/* + * Due to lack of flash in RW section, it is not possible to use IOEX subsystem + * in it. Instead, RO section uses IOEX, and RW implements only required + * function with raw i2c operation. This function is required by 'version' + * console command and should work without any special initialization. + */ +inline int board_id_det(void) +{ + if (board_id_val == BOARD_ID_UNSET) { + int id; + int res; + + /* Cache board ID at init */ + res = i2c_read8(TCA6416A_PORT, TCA6416A_ADDR, BOARD_ID_DET_PORT, + &id); + if (res != EC_SUCCESS) + return res; + + /* Board ID consists of bits 5, 4, and 3 */ + board_id_val = (id >> BOARD_ID_DET_OFFSET) & BOARD_ID_DET_MASK; + } + + /* Board ID consists of bits 5, 4, and 3 */ + return board_id_val; } + +#endif /* SECTION_IS_RO */ diff --git a/board/servo_v4p1/ioexpanders.h b/board/servo_v4p1/ioexpanders.h index d444a6fca3..313fea46a4 100644 --- a/board/servo_v4p1/ioexpanders.h +++ b/board/servo_v4p1/ioexpanders.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,10 +6,11 @@ #ifndef __CROS_EC_IOEXPANDERS_H #define __CROS_EC_IOEXPANDERS_H -enum uservo_fastboot_mux_sel_t { - MUX_SEL_USERVO = 0, - MUX_SEL_FASTBOOT = 1 -}; +#define BOARD_ID_DET_MASK 0x7 +#define BOARD_ID_DET_OFFSET 3 +#define BOARD_ID_DET_PORT 1 + +enum uservo_fastboot_mux_sel_t { MUX_SEL_USERVO = 0, MUX_SEL_FASTBOOT = 1 }; /* * Initialize Ioexpanders @@ -68,13 +69,13 @@ int usb3_a0_mux_sel(int en); int usb3_a0_mux_en_l(int en); /** - * Controls load switches for 5V to general USB type A + * Controls load switches for 5V to general USB type A. * * @param en 0 - Disable power * 1 - Enable power * @return EC_SUCCESS or EC_xxx on error */ -int usb3_a0_pwr_en(int en); +int ec_usb3_a0_pwr_en(int en); /** * Controls logic to select 1.8V or 3.3V UART from STM to DUT on SBU lines @@ -92,7 +93,7 @@ int uart_18_sel(int en); * 1 - Enable power * @return EC_SUCCESS or EC_xxx on error */ -int uservo_power_en(int en); +int ec_uservo_power_en(int en); /** * USB data path enable from host hub to downstream userv or DUT peripheral @@ -110,7 +111,7 @@ int uservo_fastboot_mux_sel(enum uservo_fastboot_mux_sel_t sel); * 1 - power enabled * @return EC_SUCCESS or EC_xxx on error */ -int usb3_a1_pwr_en(int en); +int ec_usb3_a1_pwr_en(int en); /** * USB data path for general USB type A port, second on J2 @@ -128,15 +129,6 @@ int usb3_a1_mux_sel(int en); */ int board_id_det(void); -/** - * USBC 4:6 redriver enable - * - * @param en 0 - TUSB1064 disabled - * 1 - TUSB1064 enabled - * @return EC_SUCCESS or EC_xxx on error - */ -int cmux_en(int en); - /** * Reads the TypeA/TypeC DUT cable assembly pigtail * @@ -145,6 +137,14 @@ int cmux_en(int en); */ int dongle_det(void); +/** + * Reads state of BC1.2 on host connection + * + * @return 0 - BC1.2 not present + * 1 - BC1.2 present + */ +int get_host_chrg_det(void); + /** * Enable signal for supplemental power supply. This supply will support higher * wattage servo needs. 10ms after enabling this bit, the server supply should @@ -233,14 +233,14 @@ int get_dut_chg_en(void); */ int host_or_chg_ctl(int en); -#define USERVO_FAULT_L BIT(0) -#define USB3_A0_FAULT_L BIT(1) -#define USB3_A1_FAULT_L BIT(2) -#define USB_DUTCHG_FLT_ODL BIT(3) -#define PP3300_DP_FAULT_L BIT(4) -#define DAC_BUF1_LATCH_FAULT_L BIT(5) -#define DAC_BUF2_LATCH_FAULT_L BIT(6) -#define PP5000_SRC_SEL BIT(7) +#define USERVO_FAULT_L BIT(0) +#define USB3_A0_FAULT_L BIT(1) +#define USB3_A1_FAULT_L BIT(2) +#define USB_DUTCHG_FLT_ODL BIT(3) +#define PP3300_DP_FAULT_L BIT(4) +#define DAC_BUF1_LATCH_FAULT_L BIT(5) +#define DAC_BUF2_LATCH_FAULT_L BIT(6) +#define PP5000_SRC_SEL BIT(7) /** * Read any faults that may have occurred. A fault has occurred if the @@ -268,6 +268,23 @@ int host_or_chg_ctl(int en); */ int read_faults(void); +#define HOST_CHRG_DET BIT(0) +#define SYS_PWR_IRQ_ODL BIT(6) + +/** + * Read irqs which indicate some system event. + * + * BIT + * 0 (HOST_CHRG_DET) - Change of state of BC1.2 on host connection + * 0 - BC1.2 not present + * 1 - BC1.2 present + * 6 (SYS_PWR_IRQ_ODL) - IRQ from system full power INA231 monitor. IRQ can be + * programmed to trip on wattage threshold. + * 0 - IRQ asserted + * 1 - no IRQ + */ +int read_irqs(void); + /** * Enables active discharge for USB DUT Charger * diff --git a/board/servo_v4p1/pathsel.c b/board/servo_v4p1/pathsel.c index 40100ce22a..eba1733e05 100644 --- a/board/servo_v4p1/pathsel.c +++ b/board/servo_v4p1/pathsel.c @@ -1,27 +1,44 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "gl3590.h" #include "gpio.h" #include "ioexpanders.h" #include "pathsel.h" +static void hh_usb3_a0_pwr_en(int en) +{ + gl3590_enable_ports(0, GL3590_DFP2, en); +} + +static void hh_usb3_a1_pwr_en(int en) +{ + gl3590_enable_ports(0, GL3590_DFP1, en); +} + void init_pathsel(void) { /* Connect TypeA port to DUT hub */ usb3_a0_to_dut(); /* Connect data lines */ usb3_a0_mux_en_l(0); + /* Enable power */ - usb3_a0_pwr_en(1); + ec_usb3_a0_pwr_en(1); + + hh_usb3_a0_pwr_en(1); /* Connect TypeA port to DUT hub */ usb3_a1_to_dut(); /* Connect data lines */ gpio_set_level(GPIO_USB3_A1_MUX_EN_L, 0); + /* Enable power */ - usb3_a1_pwr_en(1); + ec_usb3_a1_pwr_en(1); + + hh_usb3_a1_pwr_en(1); } void usb3_a0_to_dut(void) @@ -46,14 +63,14 @@ void usb3_a1_to_host(void) usb3_a1_mux_sel(0); } -void host_to_dut(void) +void dut_to_host(void) { gpio_set_level(GPIO_FASTBOOT_DUTHUB_MUX_SEL, 0); + gpio_set_level(GPIO_FASTBOOT_DUTHUB_MUX_EN_L, 0); uservo_fastboot_mux_sel(MUX_SEL_FASTBOOT); } void uservo_to_host(void) { - gpio_set_level(GPIO_FASTBOOT_DUTHUB_MUX_SEL, 1); uservo_fastboot_mux_sel(MUX_SEL_USERVO); } diff --git a/board/servo_v4p1/pathsel.h b/board/servo_v4p1/pathsel.h index d2f71be024..5f228aceb9 100644 --- a/board/servo_v4p1/pathsel.h +++ b/board/servo_v4p1/pathsel.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -32,9 +32,9 @@ void usb3_a0_to_host(void); void usb3_a1_to_host(void); /** - * Routes the HOST to the DUT. Used for fastboot + * Routes the DUT to the HOST. Used for fastboot */ -void host_to_dut(void); +void dut_to_host(void); /** * Routes the Micro Servo to the Host diff --git a/board/servo_v4p1/pi3usb9201.c b/board/servo_v4p1/pi3usb9201.c index 102eaf790d..976c213c49 100644 --- a/board/servo_v4p1/pi3usb9201.c +++ b/board/servo_v4p1/pi3usb9201.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,7 @@ #include "i2c.h" #include "pi3usb9201.h" -#define PI3USB9201_ADDR 0x5f +#define PI3USB9201_ADDR 0x5f inline void init_pi3usb9201(void) { @@ -19,7 +19,7 @@ inline void init_pi3usb9201(void) } inline void write_pi3usb9201(enum pi3usb9201_reg_t reg, - enum pi3usb9201_dat_t dat) + enum pi3usb9201_dat_t dat) { i2c_write8(1, PI3USB9201_ADDR, reg, dat); } diff --git a/board/servo_v4p1/pi3usb9201.h b/board/servo_v4p1/pi3usb9201.h index 826db8b871..863fc4129a 100644 --- a/board/servo_v4p1/pi3usb9201.h +++ b/board/servo_v4p1/pi3usb9201.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,35 +6,29 @@ #ifndef __CROS_EC_PI3USB9201_H #define __CROS_EC_PI3USB9201_H -enum pi3usb9201_reg_t { - CTRL_REG1, - CTRL_REG2, - CLIENT_STATUS, - HOST_STATUS -}; +enum pi3usb9201_reg_t { CTRL_REG1, CTRL_REG2, CLIENT_STATUS, HOST_STATUS }; enum pi3usb9201_dat_t { - POWER_DOWN = 0x0, - SDP_HOST_MODE = 0x2, - DCP_HOST_MODE = 0x4, - CDP_HOST_MODE = 0x6, - CLIENT_MODE = 0x8, - USB_PATH_ON = 0xe + POWER_DOWN = 0x0, + SDP_HOST_MODE = 0x2, + DCP_HOST_MODE = 0x4, + CDP_HOST_MODE = 0x6, + CLIENT_MODE = 0x8, + USB_PATH_ON = 0xe }; - /* Client Status bits */ -#define CS_DCP BIT(7) -#define CS_SDP BIT(6) -#define CS_CDP BIT(5) -#define CS_1A_CHARGER BIT(3) -#define CS_2A_CHARGER BIT(2) -#define CS_2_4A_CHARGER BIT(1) +#define CS_DCP BIT(7) +#define CS_SDP BIT(6) +#define CS_CDP BIT(5) +#define CS_1A_CHARGER BIT(3) +#define CS_2A_CHARGER BIT(2) +#define CS_2_4A_CHARGER BIT(1) /* Host Status bits */ -#define HS_USB_UNPLUGGED BIT(2) -#define HS_USB_PLUGGED BIT(1) -#define HS_BC1_2 BIT(0) +#define HS_USB_UNPLUGGED BIT(2) +#define HS_USB_PLUGGED BIT(1) +#define HS_BC1_2 BIT(0) /** * Selects Client Mode and client mode detection diff --git a/board/servo_v4p1/tca6416a.c b/board/servo_v4p1/tca6416a.c deleted file mode 100644 index d776ad86fe..0000000000 --- a/board/servo_v4p1/tca6416a.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "i2c.h" -#include "tca6416a.h" - -int tca6416a_write_bit(int port, enum tca6416a_bank bank, uint8_t bit, int val) -{ - int tmp; - int ret; - - /* Read output port register */ - ret = i2c_read8(port, TCA6416A_ADDR_FLAGS, bank, &tmp); - if (ret != EC_SUCCESS) - return ret; - - if (val) - tmp |= BIT(bit); - else - tmp &= ~BIT(bit); - - /* Write back modified output port register */ - ret = i2c_write8(port, TCA6416A_ADDR_FLAGS, bank, tmp); - if (ret != EC_SUCCESS) - return ret; - - return EC_SUCCESS; -} - -int tca6416a_write_byte(int port, enum tca6416a_bank bank, uint8_t val) -{ - int ret; - - ret = i2c_write8(port, TCA6416A_ADDR_FLAGS, bank, val); - if (ret != EC_SUCCESS) - return ret; - - return EC_SUCCESS; -} - -int tca6416a_read_byte(int port, enum tca6416a_bank bank) -{ - int tmp; - - if (i2c_read8(port, TCA6416A_ADDR_FLAGS, bank, &tmp) != EC_SUCCESS) - return -1; - - return tmp; -} - -int tca6416a_read_bit(int port, enum tca6416a_bank bank, uint8_t bit) -{ - int tmp; - int mask = 1 << bit; - - /* Read input port register */ - if (i2c_read8(port, TCA6416A_ADDR_FLAGS, bank, &tmp) != EC_SUCCESS) - return -1; - - return (tmp & mask) >> bit; -} diff --git a/board/servo_v4p1/tca6416a.h b/board/servo_v4p1/tca6416a.h deleted file mode 100644 index 5255059d99..0000000000 --- a/board/servo_v4p1/tca6416a.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_IOEXPANDER_TCA6416A_H -#define __CROS_EC_IOEXPANDER_TCA6416A_H - -#include - -#define TCA6416A_ADDR_FLAGS 0x21 - -enum tca6416a_bank { - TCA6416A_IN_PORT_0 = 0x0, - TCA6416A_IN_PORT_1 = 0x1, - TCA6416A_OUT_PORT_0 = 0x2, - TCA6416A_OUT_PORT_1 = 0x3, - TCA6416A_DIR_PORT_0 = 0x6, - TCA6416A_DIR_PORT_1 = 0x7, -}; - -/* - * Set a bit in the supplied bank - * - * @param port The I2C port of TCA6416A. - * @param bank The bank the bit belongs to. - * @param bit The index of the bit to set. - * @param val The value to set. - * - * @return EC_SUCCESS, or EC_ERROR_* on error. - */ -int tca6416a_write_bit(int port, - enum tca6416a_bank bank, uint8_t bit, int val); - -/* - * Get a bit in the supplied bank - * - * @param port The I2C port of TCA6416A. - * @param bank The bank the bit belongs to. - * @param bit The index of the bit to get. - * - * @return bit value, or -1 on error. - */ -int tca6416a_read_bit(int port, enum tca6416a_bank bank, uint8_t bit); - -/* - * Write a byt to the supplied bank - * - * @param port The I2C port of TCA6416A. - * @param bank The bank to write the byte to. - * - * @return EC_SUCCESS, or EC_ERROR_* on error. - */ -int tca6416a_write_byte(int port, enum tca6416a_bank bank, uint8_t val); - -/* - * Read a byte in the supplied bank - * - * @param port The I2C port of TCA6416A. - * @param bank The bank to read byte from. - * - * @return byte value, or -1 on error. - */ -int tca6416a_read_byte(int port, enum tca6416a_bank bank); - -#endif /* __CROS_EC_IOEXPANDER_TCA6416A_H */ diff --git a/board/servo_v4p1/tca6424a.c b/board/servo_v4p1/tca6424a.c deleted file mode 100644 index 28c768b046..0000000000 --- a/board/servo_v4p1/tca6424a.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "i2c.h" -#include "tca6424a.h" - -int tca6424a_write_bit(int port, enum tca6424a_bank bank, uint8_t bit, int val) -{ - int tmp; - int ret; - - /* Read output port register */ - ret = i2c_read8(port, TCA6424A_ADDR_FLAGS, bank, &tmp); - if (ret != EC_SUCCESS) - return ret; - - if (val) - tmp |= BIT(bit); - else - tmp &= ~BIT(bit); - - /* Write back modified output port register */ - ret = i2c_write8(port, TCA6424A_ADDR_FLAGS, bank, tmp); - if (ret != EC_SUCCESS) - return ret; - - return EC_SUCCESS; -} - -int tca6424a_write_byte(int port, enum tca6424a_bank bank, uint8_t val) -{ - int ret; - - ret = i2c_write8(port, TCA6424A_ADDR_FLAGS, bank, val); - if (ret != EC_SUCCESS) - return ret; - - return EC_SUCCESS; -} - -int tca6424a_read_byte(int port, enum tca6424a_bank bank) -{ - int tmp; - - if (i2c_read8(port, TCA6424A_ADDR_FLAGS, bank, &tmp) != EC_SUCCESS) - return -1; - - return tmp; -} - -int tca6424a_read_bit(int port, enum tca6424a_bank bank, uint8_t bit) -{ - int tmp; - int mask = 1 << bit; - - /* Read input port register */ - if (i2c_read8(port, TCA6424A_ADDR_FLAGS, bank, &tmp) != EC_SUCCESS) - return -1; - - return (tmp & mask) >> bit; -} diff --git a/board/servo_v4p1/tca6424a.h b/board/servo_v4p1/tca6424a.h deleted file mode 100644 index 80db7ebdba..0000000000 --- a/board/servo_v4p1/tca6424a.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_IOEXPANDER_TCA6424A_H -#define __CROS_EC_IOEXPANDER_TCA6424A_H - -#include - -#define TCA6424A_ADDR_FLAGS 0x23 - -enum tca6424a_bank { - TCA6424A_IN_PORT_0 = 0x0, - TCA6424A_IN_PORT_1 = 0x1, - TCA6424A_IN_PORT_2 = 0x2, - TCA6424A_OUT_PORT_0 = 0x4, - TCA6424A_OUT_PORT_1 = 0x5, - TCA6424A_OUT_PORT_2 = 0x6, - TCA6424A_DIR_PORT_0 = 0xc, - TCA6424A_DIR_PORT_1 = 0xd, - TCA6424A_DIR_PORT_2 = 0xe, -}; - -/* - * Set a bit in the supplied bank - * - * @param port The I2C port of TCA6424A. - * @param bank The bank the bit belongs to. - * @param bit The index of the bit to set. - * @param val The value to set. - * - * @return EC_SUCCESS, or EC_ERROR_* on error. - */ -int tca6424a_write_bit(int port, - enum tca6424a_bank bank, uint8_t bit, int val); - -/* - * Get a bit in the supplied bank - * - * @param port The I2C port of TCA6424A. - * @param bank The bank the bit belongs to. - * @param bit The index of the bit to get. - * - * @return bit value, or -1 on error. - */ -int tca6424a_read_bit(int port, enum tca6424a_bank bank, uint8_t bit); - -/* - * Write a byt to the supplied bank - * - * @param port The I2C port of TCA6424A. - * @param bank The bank to write the byte to. - * - * @return EC_SUCCESS, or EC_ERROR_* on error. - */ -int tca6424a_write_byte(int port, enum tca6424a_bank bank, uint8_t val); - -/* - * Read a byte in the supplied bank - * - * @param port The I2C port of TCA6424A. - * @param bank The bank to read byte from. - * - * @return byte value, or -1 on error. - */ -int tca6424a_read_byte(int port, enum tca6424a_bank bank); - -#endif /* __CROS_EC_IOEXPANDER_TCA6424A_H */ diff --git a/board/servo_v4p1/tusb1064.c b/board/servo_v4p1/tusb1064.c deleted file mode 100644 index 30816da11b..0000000000 --- a/board/servo_v4p1/tusb1064.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "i2c.h" -#include "tusb1064.h" -#include "ioexpanders.h" - -int init_tusb1064(int port) -{ - uint8_t val; - - /* Enable the TUSB1064 redriver */ - cmux_en(1); - - /* Disconnect USB3.1 and DP */ - val = tusb1064_read_byte(port, TUSB1064_REG_GENERAL); - if (val < 0) - return EC_ERROR_INVAL; - - val &= ~REG_GENERAL_CTLSEL_2DP_AND_USB3; - if (tusb1064_write_byte(port, TUSB1064_REG_GENERAL, val)) - return EC_ERROR_INVAL; - - return EC_SUCCESS; -} - -int tusb1064_write_byte(int port, uint8_t reg, uint8_t val) -{ - return i2c_write8(port, TUSB1064_ADDR_FLAGS, reg, val); -} - -int tusb1064_read_byte(int port, uint8_t reg) -{ - int tmp; - - if (i2c_read8(port, TUSB1064_ADDR_FLAGS, reg, &tmp)) - return -1; - - return tmp; -} diff --git a/board/servo_v4p1/tusb1064.h b/board/servo_v4p1/tusb1064.h deleted file mode 100644 index a6ca77b7b7..0000000000 --- a/board/servo_v4p1/tusb1064.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_TUSB1064_H -#define __CROS_EC_TUSB1064_H - -#include - -#define TUSB1064_ADDR_FLAGS 0x12 - -#define TUSB1064_REG_GENERAL 0x0a -#define REG_GENERAL_CTLSEL_DISABLE 0x00 -#define REG_GENERAL_CTLSEL_USB3 0x01 -#define REG_GENERAL_CTLSEL_4DP_LANES 0x02 -#define REG_GENERAL_CTLSEL_2DP_AND_USB3 0x03 -#define REG_GENERAL_FLIPSEL BIT(2) -#define REG_GENERAL_DP_ENABLE_CTRL BIT(3) -#define REG_GENERAL_EQ_OVERRIDE BIT(4) - -/* - * Initialize the TUSB1064 - * - * @param port The I2C port of TUSB1064 - * @return EC_SUCCESS or EC_ERROR_* - */ -int init_tusb1064(int port); - -/* - * Write a byte to the TUSB1064 - * - * @param port The I2C port of TUSB1064. - * @param reg Register to write byte to. - * @param val Value to write to TUSB1064. - * - * @return EC_SUCCESS, or EC_ERROR_* on error. - */ -int tusb1064_write_byte(int port, uint8_t reg, uint8_t val); - -/* - * Read a byte from TUSB1064 - * - * @param port The I2C port of TUSB1064. - * @param reg Register to read byte from. - * - * @return byte value, or -1 on error. - */ -int tusb1064_read_byte(int port, uint8_t reg); - -#endif /* __CROS_EC_TUSB1064_H */ diff --git a/board/servo_v4p1/usb_pd_config.h b/board/servo_v4p1/usb_pd_config.h index 7946ea5a6e..32ec29341a 100644 --- a/board/servo_v4p1/usb_pd_config.h +++ b/board/servo_v4p1/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,8 +6,8 @@ #include "adc.h" #include "chip/stm32/registers.h" #include "console.h" -#include "gpio.h" #include "ec_commands.h" +#include "gpio.h" #include "usb_pd_tcpm.h" /* USB Power delivery board configuration */ @@ -15,15 +15,6 @@ #ifndef __CROS_EC_USB_PD_CONFIG_H #define __CROS_EC_USB_PD_CONFIG_H -/* NOTES: Servo V4 and glados equivalents: - * Glados Servo V4 - * C0 CHG - * C1 DUT - * - */ -#define CHG 0 -#define DUT 1 - /* Timer selection for baseband PD communication */ #define TIM_CLOCK_PD_TX_CHG 16 #define TIM_CLOCK_PD_RX_CHG 1 @@ -56,31 +47,33 @@ #define CONFIG_HW_CRC /* Servo v4 CC configuration */ -#define CC_DETACH BIT(0) /* Emulate detach: both CC open */ -#define CC_DISABLE_DTS BIT(1) /* Apply resistors to single or both CC? */ -#define CC_ALLOW_SRC BIT(2) /* Allow charge through by policy? */ -#define CC_ENABLE_DRP BIT(3) /* Enable dual-role port */ -#define CC_SNK_WITH_PD BIT(4) /* Force enabling PD comm for sink role */ -#define CC_POLARITY BIT(5) /* CC polarity */ -#define CC_EMCA_SERVO BIT(6) /* - * Emulate Electronically Marked Cable Assembly - * (EMCA) servo (or non-EMCA) - */ +#define CC_DETACH BIT(0) /* Emulate detach: both CC open */ +#define CC_DISABLE_DTS BIT(1) /* Apply resistors to single or both CC? */ +#define CC_ALLOW_SRC BIT(2) /* Allow charge through by policy? */ +#define CC_ENABLE_DRP BIT(3) /* Enable dual-role port */ +#define CC_SNK_WITH_PD BIT(4) /* Force enabling PD comm for sink role */ +#define CC_POLARITY BIT(5) /* CC polarity */ +#define CC_EMCA_SERVO \ + BIT(6) /* \ + * Emulate Electronically Marked Cable Assembly \ + * (EMCA) servo (or non-EMCA) \ + */ +#define CC_FASTBOOT_DFP BIT(7) /* Allow mux uServo->Fastboot on DFP */ /* Servo v4 DP alt-mode configuration */ -#define ALT_DP_ENABLE BIT(0) /* Enable DP alt-mode or not */ -#define ALT_DP_PIN_C BIT(1) /* Pin assignment C supported */ -#define ALT_DP_PIN_D BIT(2) /* Pin assignment D supported */ -#define ALT_DP_MF_PREF BIT(3) /* Multi-Function preferred */ -#define ALT_DP_PLUG BIT(4) /* Plug or receptacle */ -#define ALT_DP_OVERRIDE_HPD BIT(5) /* Override the HPD signal */ -#define ALT_DP_HPD_LVL BIT(6) /* HPD level if overridden */ +#define ALT_DP_ENABLE BIT(0) /* Enable DP alt-mode or not */ +#define ALT_DP_PIN_C BIT(1) /* Pin assignment C supported */ +#define ALT_DP_PIN_D BIT(2) /* Pin assignment D supported */ +#define ALT_DP_MF_PREF BIT(3) /* Multi-Function preferred */ +#define ALT_DP_PLUG BIT(4) /* Plug or receptacle */ +#define ALT_DP_OVERRIDE_HPD BIT(5) /* Override the HPD signal */ +#define ALT_DP_HPD_LVL BIT(6) /* HPD level if overridden */ /* TX uses SPI1 on PB3-4 for CHG port, SPI2 on PB 13-14 for DUT port */ #define SPI_REGS(p) ((p) ? STM32_SPI2_REGS : STM32_SPI1_REGS) static inline void spi_enable_clock(int port) { - if (port == 0) + if (port == CHG) STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI1; else STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; @@ -97,14 +90,14 @@ static inline void spi_enable_clock(int port) #define TIM_TX_CCR_IDX(p) ((p) ? TIM_TX_CCR_DUT : TIM_TX_CCR_CHG) #define TIM_RX_CCR_IDX(p) ((p) ? TIM_RX_CCR_DUT : TIM_RX_CCR_CHG) -#define TIM_CCR_CS 1 +#define TIM_CCR_CS 1 /* * EXTI line 21 is connected to the CMP1 output, * EXTI line 22 is connected to the CMP2 output, * CHG uses CMP2, and DUT uses CMP1. */ -#define EXTI_COMP_MASK(p) ((p) ? (1<<21) : BIT(22)) +#define EXTI_COMP_MASK(p) ((p) ? (1 << 21) : BIT(22)) #define IRQ_COMP STM32_IRQ_COMP /* triggers packet detection on comparator falling edge */ @@ -116,7 +109,7 @@ static inline void spi_enable_clock(int port) /* the pins used for communication need to be hi-speed */ static inline void pd_set_pins_speed(int port) { - if (port == 0) { + if (port == CHG) { /* 40 MHz pin speed on SPI PB3&4, * (USB_CHG_TX_CLKIN & USB_CHG_CC1_TX_DATA) */ @@ -138,7 +131,7 @@ static inline void pd_set_pins_speed(int port) /* Reset SPI peripheral used for TX */ static inline void pd_tx_spi_reset(int port) { - if (port == 0) { + if (port == CHG) { /* Reset SPI1 */ STM32_RCC_APB2RSTR |= BIT(12); STM32_RCC_APB2RSTR &= ~BIT(12); @@ -193,16 +186,28 @@ static inline void pd_select_polarity(int port, int polarity) /* Use window mode so that COMP1 and COMP2 share non-inverting input */ val |= STM32_COMP_CMP1EN | STM32_COMP_CMP2EN | STM32_COMP_WNDWEN; - if (port == 0) { + if (port == CHG) { /* CHG use the right comparator inverted input for COMP2 */ STM32_COMP_CSR = (val & ~STM32_COMP_CMP2INSEL_MASK) | - (polarity ? STM32_COMP_CMP2INSEL_INM4 /* PA4: C0_CC2 */ - : STM32_COMP_CMP2INSEL_INM6);/* PA2: C0_CC1 */ + (polarity ? + STM32_COMP_CMP2INSEL_INM4 /* PA4: + C0_CC2 + */ + : + STM32_COMP_CMP2INSEL_INM6); /* PA2: + C0_CC1 + */ } else { /* DUT use the right comparator inverted input for COMP1 */ STM32_COMP_CSR = (val & ~STM32_COMP_CMP1INSEL_MASK) | - (polarity ? STM32_COMP_CMP1INSEL_INM5 /* PA5: C1_CC2 */ - : STM32_COMP_CMP1INSEL_INM6);/* PA0: C1_CC1 */ + (polarity ? + STM32_COMP_CMP1INSEL_INM5 /* PA5: + C1_CC2 + */ + : + STM32_COMP_CMP1INSEL_INM6); /* PA0: + C1_CC1 + */ } } @@ -237,7 +242,7 @@ static inline void pd_set_host_mode(int port, int enable) * present as a SNK device. If port != DUT (port == 1), then nothing to * do in this function. */ - if (!port) + if (port != DUT) return; if (enable) { @@ -282,10 +287,8 @@ static inline void pd_config_init(int port, uint8_t power_role) /* Initialize TX pins and put them in Hi-Z */ pd_tx_init(); - } int pd_adc_read(int port, int cc); #endif /* __CROS_EC_USB_PD_CONFIG_H */ - diff --git a/board/servo_v4p1/usb_pd_policy.c b/board/servo_v4p1/usb_pd_policy.c index 96af570aae..9ec6ead960 100644 --- a/board/servo_v4p1/usb_pd_policy.c +++ b/board/servo_v4p1/usb_pd_policy.c @@ -1,11 +1,11 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" -#include "chg_control.h" #include "charge_manager.h" +#include "chg_control.h" #include "common.h" #include "console.h" #include "gpio.h" @@ -13,70 +13,70 @@ #include "host_command.h" #include "i2c.h" #include "ioexpanders.h" +#include "pathsel.h" #include "registers.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" -#include "tusb1064.h" -#include "util.h" #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_config.h" #include "usb_pd_tcpm.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) -#define DUT_PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP) +#define DUT_PDO_FIXED_FLAGS \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_COMM_CAP) #define CHG_PDO_FIXED_FLAGS (PDO_FIXED_DATA_SWAP) -#define VBUS_UNCHANGED(curr, pend, new) (curr == new && pend == new) - /* Macros to config the PD role */ #define CONF_SET_CLEAR(c, set, clear) ((c | (set)) & ~(clear)) -#define CONF_SRC(c) CONF_SET_CLEAR(c, \ - CC_DISABLE_DTS | CC_ALLOW_SRC, \ - CC_ENABLE_DRP | CC_SNK_WITH_PD) -#define CONF_SNK(c) CONF_SET_CLEAR(c, \ - CC_DISABLE_DTS, \ - CC_ALLOW_SRC | CC_ENABLE_DRP | CC_SNK_WITH_PD) -#define CONF_PDSNK(c) CONF_SET_CLEAR(c, \ - CC_DISABLE_DTS | CC_SNK_WITH_PD, \ - CC_ALLOW_SRC | CC_ENABLE_DRP) -#define CONF_DRP(c) CONF_SET_CLEAR(c, \ - CC_DISABLE_DTS | CC_ALLOW_SRC | CC_ENABLE_DRP, \ - CC_SNK_WITH_PD) -#define CONF_SRCDTS(c) CONF_SET_CLEAR(c, \ - CC_ALLOW_SRC, \ - CC_ENABLE_DRP | CC_DISABLE_DTS | CC_SNK_WITH_PD) -#define CONF_SNKDTS(c) CONF_SET_CLEAR(c, \ - 0, \ - CC_ALLOW_SRC | CC_ENABLE_DRP | \ - CC_DISABLE_DTS | CC_SNK_WITH_PD) -#define CONF_PDSNKDTS(c) CONF_SET_CLEAR(c, \ - CC_SNK_WITH_PD, \ - CC_ALLOW_SRC | CC_ENABLE_DRP | CC_DISABLE_DTS) -#define CONF_DRPDTS(c) CONF_SET_CLEAR(c, \ - CC_ALLOW_SRC | CC_ENABLE_DRP, \ - CC_DISABLE_DTS | CC_SNK_WITH_PD) +#define CONF_SRC(c) \ + CONF_SET_CLEAR(c, CC_DISABLE_DTS | CC_ALLOW_SRC, \ + CC_ENABLE_DRP | CC_SNK_WITH_PD) +#define CONF_SNK(c) \ + CONF_SET_CLEAR(c, CC_DISABLE_DTS, \ + CC_ALLOW_SRC | CC_ENABLE_DRP | CC_SNK_WITH_PD) +#define CONF_PDSNK(c) \ + CONF_SET_CLEAR(c, CC_DISABLE_DTS | CC_SNK_WITH_PD, \ + CC_ALLOW_SRC | CC_ENABLE_DRP) +#define CONF_DRP(c) \ + CONF_SET_CLEAR(c, CC_DISABLE_DTS | CC_ALLOW_SRC | CC_ENABLE_DRP, \ + CC_SNK_WITH_PD) +#define CONF_SRCDTS(c) \ + CONF_SET_CLEAR(c, CC_ALLOW_SRC, \ + CC_ENABLE_DRP | CC_DISABLE_DTS | CC_SNK_WITH_PD) +#define CONF_SNKDTS(c) \ + CONF_SET_CLEAR(c, 0, \ + CC_ALLOW_SRC | CC_ENABLE_DRP | CC_DISABLE_DTS | \ + CC_SNK_WITH_PD) +#define CONF_PDSNKDTS(c) \ + CONF_SET_CLEAR(c, CC_SNK_WITH_PD, \ + CC_ALLOW_SRC | CC_ENABLE_DRP | CC_DISABLE_DTS) +#define CONF_DRPDTS(c) \ + CONF_SET_CLEAR(c, CC_ALLOW_SRC | CC_ENABLE_DRP, \ + CC_DISABLE_DTS | CC_SNK_WITH_PD) +#define CONF_DTSOFF(c) CONF_SET_CLEAR(c, CC_DISABLE_DTS, 0) +#define CONF_DTSON(c) CONF_SET_CLEAR(c, 0, CC_DISABLE_DTS) /* Macros to apply Rd/Rp to CC lines */ -#define DUT_ACTIVE_CC_SET(r, flags) \ - gpio_set_flags(cc_config & CC_POLARITY ? \ - CONCAT2(GPIO_USB_DUT_CC2_, r) : \ - CONCAT2(GPIO_USB_DUT_CC1_, r), \ +#define DUT_ACTIVE_CC_SET(r, flags) \ + gpio_set_flags(cc_config &CC_POLARITY ? \ + CONCAT2(GPIO_USB_DUT_CC2_, r) : \ + CONCAT2(GPIO_USB_DUT_CC1_, r), \ flags) -#define DUT_INACTIVE_CC_SET(r, flags) \ - gpio_set_flags(cc_config & CC_POLARITY ? \ - CONCAT2(GPIO_USB_DUT_CC1_, r) : \ - CONCAT2(GPIO_USB_DUT_CC2_, r), \ +#define DUT_INACTIVE_CC_SET(r, flags) \ + gpio_set_flags(cc_config &CC_POLARITY ? \ + CONCAT2(GPIO_USB_DUT_CC1_, r) : \ + CONCAT2(GPIO_USB_DUT_CC2_, r), \ flags) -#define DUT_BOTH_CC_SET(r, flags) \ - do { \ +#define DUT_BOTH_CC_SET(r, flags) \ + do { \ gpio_set_flags(CONCAT2(GPIO_USB_DUT_CC1_, r), flags); \ gpio_set_flags(CONCAT2(GPIO_USB_DUT_CC2_, r), flags); \ } while (0) @@ -98,15 +98,15 @@ * than 5V. */ static const uint16_t pd_src_voltages_mv[] = { - 5000, 9000, 10000, 12000, 15000, 20000, + 5000, 9000, 10000, 12000, 15000, 20000, }; static uint32_t pd_src_chg_pdo[ARRAY_SIZE(pd_src_voltages_mv)]; static uint8_t chg_pdo_cnt; const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, CHG_PDO_FIXED_FLAGS), - PDO_BATT(4750, 21000, 15000), - PDO_VAR(4750, 21000, 3000), + PDO_FIXED(5000, 500, CHG_PDO_FIXED_FLAGS), + PDO_BATT(4750, 21000, 15000), + PDO_VAR(4750, 21000, 3000), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); @@ -123,15 +123,15 @@ static int cc_config = CC_ALLOW_SRC | CC_EMCA_SERVO; /* Voltage thresholds for no connect in DTS mode */ static int pd_src_vnc_dts[TYPEC_RP_RESERVED][2] = { - {PD_SRC_3_0_VNC_MV, PD_SRC_1_5_VNC_MV}, - {PD_SRC_1_5_VNC_MV, PD_SRC_DEF_VNC_MV}, - {PD_SRC_3_0_VNC_MV, PD_SRC_DEF_VNC_MV}, + { PD_SRC_3_0_VNC_MV, PD_SRC_1_5_VNC_MV }, + { PD_SRC_1_5_VNC_MV, PD_SRC_DEF_VNC_MV }, + { PD_SRC_3_0_VNC_MV, PD_SRC_DEF_VNC_MV }, }; /* Voltage thresholds for Ra attach in DTS mode */ static int pd_src_rd_threshold_dts[TYPEC_RP_RESERVED][2] = { - {PD_SRC_3_0_RD_THRESH_MV, PD_SRC_1_5_RD_THRESH_MV}, - {PD_SRC_1_5_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV}, - {PD_SRC_3_0_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV}, + { PD_SRC_3_0_RD_THRESH_MV, PD_SRC_1_5_RD_THRESH_MV }, + { PD_SRC_1_5_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV }, + { PD_SRC_3_0_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV }, }; /* Voltage thresholds for no connect in normal SRC mode */ static int pd_src_vnc[TYPEC_RP_RESERVED] = { @@ -159,6 +159,9 @@ static int cc_pull_stored = TYPEC_CC_RD; static int user_limited_max_mv = 20000; +static uint8_t allow_pr_swap = 1; +static uint8_t allow_dr_swap = 1; + static uint32_t max_supported_voltage(void) { return user_limited_max_mv; @@ -266,7 +269,7 @@ static void board_manage_dut_port(void) static void update_ports(void) { int pdo_index, src_index, snk_index, i; - uint32_t pdo, max_ma, max_mv; + uint32_t pdo, max_ma, max_mv, unused; /* * CHG Vbus has changed states, update PDO that reflects CHG port @@ -281,6 +284,20 @@ static void update_ports(void) src_index = 0; snk_index = -1; + /* + * TODO: This code artificially limits PDO + * to entries in pd_src_voltages_mv table + * + * This is artificially overconstrainted. + * + * Allow non-standard PDO objects so long + * as they are valid. See: crrev/c/730877 + * for where this started. + * + * This needs to be rearchitected in order + * to support Variable PDO passthrough. + */ + for (i = 0; i < ARRAY_SIZE(pd_src_voltages_mv); ++i) { /* Adhere to board voltage limits */ if (pd_src_voltages_mv[i] > @@ -288,8 +305,8 @@ static void update_ports(void) break; /* Find the 'best' PDO <= voltage */ - pdo_index = - pd_find_pdo_index(pd_get_src_cap_cnt(CHG), + pdo_index = pd_find_pdo_index( + pd_get_src_cap_cnt(CHG), pd_get_src_caps(CHG), pd_src_voltages_mv[i], &pdo); /* Don't duplicate PDOs */ @@ -300,20 +317,54 @@ static void update_ports(void) continue; snk_index = pdo_index; - pd_extract_pdo_power(pdo, &max_ma, &max_mv); - pd_src_chg_pdo[src_index++] = + pd_extract_pdo_power(pdo, &max_ma, &max_mv, + &unused); + pd_src_chg_pdo[src_index] = PDO_FIXED_VOLT(max_mv) | - PDO_FIXED_CURR(max_ma) | - DUT_PDO_FIXED_FLAGS | - PDO_FIXED_UNCONSTRAINED; + PDO_FIXED_CURR(max_ma); + + if (src_index == 0) { + /* + * TODO: 1st PDO *should* always be + * vSafe5v PDO. But not always with bad + * DUT. Should re-index and re-map. + * + * TODO: Add variable voltage PDO + * conversion. + */ + pd_src_chg_pdo[src_index] &= + ~(DUT_PDO_FIXED_FLAGS | + PDO_FIXED_UNCONSTRAINED); + + /* + * TODO: Keep Unconstrained Power knobs + * exposed and well-defined. + * + * Current method is workaround that + * force-rejects PR_SWAPs in lieu of UP. + * + * Migrate to use config flag such as: + * ((cc_config & + * CC_UNCONSTRAINED_POWER)? + * PDO_FIXED_UNCONSTRAINED:0) + */ + pd_src_chg_pdo[src_index] |= + (DUT_PDO_FIXED_FLAGS | + PDO_FIXED_UNCONSTRAINED); + } + src_index++; } chg_pdo_cnt = src_index; } else { /* 5V PDO */ pd_src_chg_pdo[0] = PDO_FIXED_VOLT(PD_MIN_MV) | - PDO_FIXED_CURR(vbus[CHG].ma) | - DUT_PDO_FIXED_FLAGS | - PDO_FIXED_UNCONSTRAINED; + PDO_FIXED_CURR(vbus[CHG].ma) | + DUT_PDO_FIXED_FLAGS | + PDO_FIXED_UNCONSTRAINED; + /* + * TODO: Keep Unconstrained Power knobs + * exposed and well-defined. + */ chg_pdo_cnt = 1; } @@ -338,8 +389,8 @@ int board_set_active_charge_port(int charge_port) return 0; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) { if (port != CHG) return; @@ -385,8 +436,9 @@ int pd_tcpc_cc_nc(int port, int cc_volt, int cc_sel) if (cc_config & CC_DISABLE_DTS) nc = cc_volt >= pd_src_vnc[rp_index]; else - nc = cc_volt >= pd_src_vnc_dts[rp_index][ - cc_config & CC_POLARITY ? !cc_sel : cc_sel]; + nc = cc_volt >= + pd_src_vnc_dts[rp_index] + [cc_config & CC_POLARITY ? !cc_sel : cc_sel]; return nc; } @@ -412,19 +464,31 @@ int pd_tcpc_cc_ra(int port, int cc_volt, int cc_sel) if (cc_config & CC_DISABLE_DTS) ra = cc_volt < pd_src_rd_threshold[rp_index]; else - ra = cc_volt < pd_src_rd_threshold_dts[rp_index][ - cc_config & CC_POLARITY ? !cc_sel : cc_sel]; + ra = cc_volt < + pd_src_rd_threshold_dts[rp_index] + [cc_config & CC_POLARITY ? !cc_sel : + cc_sel]; return ra; } +/* DUT CC readings aren't valid if we aren't applying CC pulls */ +bool cc_is_valid(void) +{ + if ((cc_config & CC_DETACH) || (cc_pull_stored == TYPEC_CC_OPEN) || + ((cc_pull_stored == TYPEC_CC_RP) && + (rp_value_stored == TYPEC_RP_RESERVED))) + return false; + return true; +} + int pd_adc_read(int port, int cc) { int mv = -1; if (port == CHG) mv = adc_read_channel(cc ? ADC_CHG_CC2_PD : ADC_CHG_CC1_PD); - else if (!(cc_config & CC_DETACH)) { + else if (cc_is_valid()) { /* * In servo v4 hardware logic, both CC lines are wired directly * to DUT. When servo v4 as a snk, DUT may source Vconn to CC2 @@ -445,13 +509,11 @@ int pd_adc_read(int port, int cc) * * This is basically a hack faking "vOpen" from TCPCI spec. */ - if ((cc_config & CC_DISABLE_DTS) && - port == DUT && + if ((cc_config & CC_DISABLE_DTS) && port == DUT && cc == ((cc_config & CC_POLARITY) ? 0 : 1)) { - - if ((cc_pull_stored == TYPEC_CC_RD) || - (cc_pull_stored == TYPEC_CC_RA) || - (cc_pull_stored == TYPEC_CC_RA_RD)) + if ((cc_pull_stored == TYPEC_CC_RD) || + (cc_pull_stored == TYPEC_CC_RA) || + (cc_pull_stored == TYPEC_CC_RA_RD)) mv = -1; else if (cc_pull_stored == TYPEC_CC_RP) mv = 3301; @@ -580,7 +642,7 @@ int pd_set_rp_rd(int port, int cc_pull, int rp_value) if (cc_pull == TYPEC_CC_RP) { rv = board_set_rp(rp_value); } else if ((cc_pull == TYPEC_CC_RD) || (cc_pull == TYPEC_CC_RA_RD) || - (cc_pull == TYPEC_CC_RA)) { + (cc_pull == TYPEC_CC_RA)) { /* * The DUT port uses a captive cable. It can present Rd on both * CC1 and CC2. If DTS mode is enabled, then present Rd on both @@ -659,7 +721,7 @@ int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) * port, otherwise we provide no power. */ if (charge_port_is_active()) { - *src_pdo = pd_src_chg_pdo; + *src_pdo = pd_src_chg_pdo; pdo_cnt = chg_pdo_cnt; } @@ -669,9 +731,9 @@ int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) __override void pd_transition_voltage(int idx) { timestamp_t deadline; - uint32_t ma, mv; + uint32_t ma, mv, unused; - pd_extract_pdo_power(pd_src_chg_pdo[idx - 1], &ma, &mv); + pd_extract_pdo_power(pd_src_chg_pdo[idx - 1], &ma, &mv, &unused); /* Is this a transition to a new voltage? */ if (charge_port_is_active() && vbus[CHG].mv != mv) { /* @@ -683,8 +745,7 @@ __override void pd_transition_voltage(int idx) /* Wait for CHG transition */ deadline.val = get_time().val + PD_T_PS_TRANSITION; CPRINTS("Waiting for CHG port transition"); - while (charge_port_is_active() && - vbus[CHG].mv != mv && + while (charge_port_is_active() && vbus[CHG].mv != mv && get_time().val < deadline.val) msleep(10); @@ -746,8 +807,7 @@ void pd_power_supply_reset(int port) int pd_snk_is_vbus_provided(int port) { - return gpio_get_level(port ? GPIO_USB_DET_PP_DUT : - GPIO_USB_DET_PP_CHG); + return gpio_get_level(port ? GPIO_USB_DET_PP_DUT : GPIO_USB_DET_PP_CHG); } __override int pd_check_power_swap(int port) @@ -764,14 +824,17 @@ __override int pd_check_power_swap(int port) if (port == CHG) return 0; + if (pd_get_power_role(port) == PD_ROLE_SINK && + !(cc_config & CC_ALLOW_SRC)) + return 0; + if (pd_snk_is_vbus_provided(CHG)) - return 1; + return allow_pr_swap; return 0; } -__override int pd_check_data_swap(int port, - enum pd_data_role data_role) +__override int pd_check_data_swap(int port, enum pd_data_role data_role) { /* * Servo should allow data role swaps to let DUT see the USB hub, but @@ -780,20 +843,52 @@ __override int pd_check_data_swap(int port, if (port == CHG) return 0; - return 1; + return allow_dr_swap; } -__override void pd_execute_data_swap(int port, - enum pd_data_role data_role) +__override void pd_execute_data_swap(int port, enum pd_data_role data_role) { - /* - * TODO(b/137887386): Turn on the fastboot/DFU path when data swap to - * DFP? - */ + if (port == CHG) + return; + + switch (data_role) { + case PD_ROLE_DFP: + if (cc_config & CC_FASTBOOT_DFP) { + dut_to_host(); + } else { + /* Disable USB2 lines from DUT */ + gpio_set_level(GPIO_FASTBOOT_DUTHUB_MUX_EN_L, 1); + uservo_to_host(); + } + break; + case PD_ROLE_UFP: + /* Ensure that FASTBOOT is disabled */ + gpio_set_level(GPIO_FASTBOOT_DUTHUB_MUX_SEL, 1); + + /* Enable USB2 lines */ + gpio_set_level(GPIO_FASTBOOT_DUTHUB_MUX_EN_L, 0); + + /* + * By default, uServo port will be enabled. Only if the user + * explicitly enable CC_FASTBOOT_DFP then uServo is disabled. + */ + if (!(cc_config & CC_FASTBOOT_DFP)) + uservo_to_host(); + break; + case PD_ROLE_DISCONNECTED: + /* Disable USB2 lines */ + gpio_set_level(GPIO_FASTBOOT_DUTHUB_MUX_EN_L, 1); + + if (!(cc_config & CC_FASTBOOT_DFP)) + uservo_to_host(); + break; + default: + CPRINTS("C%d: %s: Invalid data_role:%d", port, __func__, + data_role); + } } -__override void pd_check_pr_role(int port, - enum pd_power_role pr_role, +__override void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { /* @@ -804,9 +899,7 @@ __override void pd_check_pr_role(int port, */ } -__override void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +__override void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { if (port == CHG) return; @@ -816,15 +909,14 @@ __override void pd_check_dr_role(int port, pd_request_data_swap(port); } - /* ----------------- Vendor Defined Messages ------------------ */ /* * DP alt-mode config, user configurable. * Default is the mode disabled, supporting the C and D pin assignment, * multi-function preferred, and a plug. */ -static int alt_dp_config = (ALT_DP_PIN_C | ALT_DP_PIN_D | ALT_DP_MF_PREF | - ALT_DP_PLUG); +static int alt_dp_config = + (ALT_DP_PIN_C | ALT_DP_PIN_D | ALT_DP_MF_PREF | ALT_DP_PLUG); /** * Get the pins based on the user config. @@ -857,8 +949,8 @@ const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, - CONFIG_USB_PD_IDENTITY_SW_VERS, - 0, 0, 0, 0, /* SS[TR][12] */ + CONFIG_USB_PD_IDENTITY_SW_VERS, 0, 0, 0, + 0, /* SS[TR][12] */ 0, /* Vconn power */ 0, /* Vconn power required */ 0, /* Vbus power required */ @@ -896,13 +988,13 @@ uint32_t vdo_dp_mode[MODE_CNT]; static int svdm_response_modes(int port, uint32_t *payload) { - vdo_dp_mode[0] = - VDO_MODE_DP(0, /* UFP pin cfg supported: none */ - alt_dp_config_pins(), /* DFP pin */ - 1, /* no usb2.0 signalling in AMode */ - alt_dp_config_cable(), /* plug or receptacle */ - MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ - MODE_DP_SNK); /* Its a sink only */ + vdo_dp_mode[0] = VDO_MODE_DP(0, /* UFP pin cfg supported: none */ + alt_dp_config_pins(), /* DFP pin */ + 1, /* no usb2.0 signalling in AMode */ + alt_dp_config_cable(), /* plug or + receptacle */ + MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ + MODE_DP_SNK); /* Its a sink only */ /* CCD uses the SBU lines; don't enable DP when dts-mode enabled */ if (!(cc_config & CC_DISABLE_DTS)) @@ -915,48 +1007,30 @@ static int svdm_response_modes(int port, uint32_t *payload) return MODE_CNT + 1; } -static int is_typec_dp_muxed(void) -{ - int value; - - value = tusb1064_read_byte(I2C_PORT_MASTER, TUSB1064_REG_GENERAL); - if (value < 0 || value & REG_GENERAL_CTLSEL_4DP_LANES) - return 0; - - return 1; -} - static void set_typec_mux(int pin_cfg) { - int value; - - value = tusb1064_read_byte(I2C_PORT_MASTER, TUSB1064_REG_GENERAL); - if (value < 0) - return; + mux_state_t mux_mode = USB_PD_MUX_NONE; - value &= ~(REG_GENERAL_CTLSEL_4DP_LANES | REG_GENERAL_CTLSEL_USB3); switch (pin_cfg) { - case 0: + case 0: /* return to USB3 only */ + mux_mode = USB_PD_MUX_USB_ENABLED; CPRINTS("PinCfg:off"); break; - case MODE_DP_PIN_C: - value |= REG_GENERAL_CTLSEL_4DP_LANES; + case MODE_DP_PIN_C: /* DisplayPort 4 lanes */ + mux_mode = USB_PD_MUX_DP_ENABLED; CPRINTS("PinCfg:C"); break; - case MODE_DP_PIN_D: - value |= REG_GENERAL_CTLSEL_2DP_AND_USB3; + case MODE_DP_PIN_D: /* DP + USB */ + mux_mode = USB_PD_MUX_DOCK; CPRINTS("PinCfg:D"); break; default: CPRINTS("PinCfg not supported: %d", pin_cfg); return; } - if (value && cc_config & CC_POLARITY) - value |= REG_GENERAL_FLIPSEL; - else - value &= ~REG_GENERAL_FLIPSEL; - tusb1064_write_byte(I2C_PORT_MASTER, TUSB1064_REG_GENERAL, value); + usb_mux_set(DUT, mux_mode, USB_SWITCH_CONNECT, + !!(cc_config & CC_POLARITY)); } static int get_hpd_level(void) @@ -971,19 +1045,22 @@ static int dp_status(int port, uint32_t *payload) { int opos = PD_VDO_OPOS(payload[0]); int hpd = get_hpd_level(); + mux_state_t state = usb_mux_get(DUT); + int dp_enabled = !!(state & USB_PD_MUX_DP_ENABLED); if (opos != OPOS) - return 0; /* NAK */ - - payload[1] = VDO_DP_STATUS( - 0, /* IRQ_HPD */ - hpd, /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - (alt_dp_config & ALT_DP_MF_PREF) != 0, /* MF pref */ - is_typec_dp_muxed(), - 0, /* power low */ - hpd ? 0x2 : 0); + return 0; /* NAK */ + + payload[1] = + VDO_DP_STATUS(0, /* IRQ_HPD */ + hpd, /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + (alt_dp_config & ALT_DP_MF_PREF) != 0, /* MF + pref + */ + dp_enabled, 0, /* power low */ + hpd ? 0x2 : 0); return 2; } @@ -1004,15 +1081,15 @@ static int svdm_enter_mode(int port, uint32_t *payload) /* SID & mode request is valid */ if ((PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) || (PD_VDO_OPOS(payload[0]) != OPOS)) - return 0; /* NAK */ + return 0; /* NAK */ alt_mode = OPOS; return 1; } -int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid) +int pd_alt_mode(int port, enum tcpci_msg_type type, uint16_t svid) { - if (type != TCPC_TX_SOP) + if (type != TCPCI_MSG_SOP) return 0; if (svid == USB_SID_DISPLAYPORT) @@ -1046,7 +1123,7 @@ const struct svdm_response svdm_rsp = { }; __override int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) + uint32_t **rpayload) { int cmd = PD_VDO_CMD(payload[0]); @@ -1058,7 +1135,7 @@ __override int pd_custom_vdm(int port, int cnt, uint32_t *payload, case VDO_CMD_VERSION: /* guarantee last byte of payload is null character */ *(payload + cnt - 1) = 0; - CPRINTF("ver: %s\n", (char *)(payload+1)); + CPRINTF("ver: %s\n", (char *)(payload + 1)); break; case VDO_CMD_CURRENT: CPRINTF("Current: %dmA\n", payload[1]); @@ -1076,18 +1153,15 @@ static void print_cc_mode(void) /* Get current CCD status */ ccprintf("cc: %s\n", cc_config & CC_DETACH ? "off" : "on"); ccprintf("dts mode: %s\n", cc_config & CC_DISABLE_DTS ? "off" : "on"); - ccprintf("chg mode: %s\n", - get_dut_chg_en() ? "on" : "off"); + ccprintf("chg mode: %s\n", get_dut_chg_en() ? "on" : "off"); ccprintf("chg allowed: %s\n", cc_config & CC_ALLOW_SRC ? "on" : "off"); ccprintf("drp enabled: %s\n", cc_config & CC_ENABLE_DRP ? "on" : "off"); - ccprintf("cc polarity: %s\n", cc_config & CC_POLARITY ? "cc2" : - "cc1"); + ccprintf("cc polarity: %s\n", cc_config & CC_POLARITY ? "cc2" : "cc1"); ccprintf("pd enabled: %s\n", pd_comm_is_enabled(DUT) ? "on" : "off"); - ccprintf("emca: %s\n", cc_config & CC_EMCA_SERVO ? - "emarked" : "non-emarked"); + ccprintf("emca: %s\n", + cc_config & CC_EMCA_SERVO ? "emarked" : "non-emarked"); } - static void do_cc(int cc_config_new) { int chargeable; @@ -1095,8 +1169,9 @@ static void do_cc(int cc_config_new) if (cc_config_new != cc_config) { if (!(cc_config & CC_DETACH)) { - /* Force detach */ - pd_power_supply_reset(DUT); + /* Force detach by disabling VBUS */ + chg_power_select(CHG_POWER_OFF); + dut_chg_en(0); /* Always set to 0 here so both CC lines are changed */ cc_config &= ~(CC_DISABLE_DTS & CC_ALLOW_SRC); @@ -1157,7 +1232,7 @@ static void do_cc(int cc_config_new) } } -static int command_cc(int argc, char **argv) +static int command_cc(int argc, const char **argv) { int cc_config_new = cc_config; @@ -1188,6 +1263,10 @@ static int command_cc(int argc, char **argv) cc_config_new = CONF_PDSNKDTS(cc_config_new); else if (!strcasecmp(argv[1], "drpdts")) cc_config_new = CONF_DRPDTS(cc_config_new); + else if (!strcasecmp(argv[1], "dtsoff")) + cc_config_new = CONF_DTSOFF(cc_config_new); + else if (!strcasecmp(argv[1], "dtson")) + cc_config_new = CONF_DTSON(cc_config_new); else if (!strcasecmp(argv[1], "emca")) cc_config_new |= CC_EMCA_SERVO; else if (!strcasecmp(argv[1], "nonemca")) @@ -1210,7 +1289,7 @@ static int command_cc(int argc, char **argv) } DECLARE_CONSOLE_COMMAND(cc, command_cc, "[off|on|src|snk|pdsnk|drp|srcdts|snkdts|pdsnkdts|" - "drpdts|emca|nonemca] [cc1|cc2]", + "drpdts|dtsoff|dtson|emca|nonemca] [cc1|cc2]", "Servo_v4 DTS and CHG mode"); static void fake_disconnect_end(void) @@ -1230,7 +1309,7 @@ static void fake_disconnect_start(void) } DECLARE_DEFERRED(fake_disconnect_start); -static int cmd_fake_disconnect(int argc, char *argv[]) +static int cmd_fake_disconnect(int argc, const char *argv[]) { int delay_ms, duration_ms; char *e; @@ -1252,41 +1331,37 @@ static int cmd_fake_disconnect(int argc, char *argv[]) fake_pd_disconnect_duration_us = duration_ms * MSEC; hook_call_deferred(&fake_disconnect_start_data, delay_ms * MSEC); - ccprintf("Fake disconnect for %d ms starting in %d ms.\n", - duration_ms, delay_ms); + ccprintf("Fake disconnect for %d ms starting in %d ms.\n", duration_ms, + delay_ms); return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(fakedisconnect, cmd_fake_disconnect, " ", NULL); -static int cmd_ada_srccaps(int argc, char *argv[]) +static int cmd_ada_srccaps(int argc, const char *argv[]) { int i; - const uint32_t * const ada_srccaps = pd_get_src_caps(CHG); + const uint32_t *const ada_srccaps = pd_get_src_caps(CHG); for (i = 0; i < pd_get_src_cap_cnt(CHG); ++i) { - uint32_t max_ma, max_mv; + uint32_t max_ma, max_mv, unused; + + if (IS_ENABLED(CONFIG_USB_PD_ONLY_FIXED_PDOS) && + (ada_srccaps[i] & PDO_TYPE_MASK) != PDO_TYPE_FIXED) + continue; + + pd_extract_pdo_power(ada_srccaps[i], &max_ma, &max_mv, &unused); - pd_extract_pdo_power(ada_srccaps[i], &max_ma, &max_mv); ccprintf("%d: %dmV/%dmA\n", i, max_mv, max_ma); } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(ada_srccaps, cmd_ada_srccaps, - "", +DECLARE_CONSOLE_COMMAND(ada_srccaps, cmd_ada_srccaps, "", "Print adapter SrcCap"); -static void chg_pd_disconnect(void) -{ - /* Clear charger PDO on CHG port disconnected. */ - if (pd_is_disconnected(CHG)) - pd_set_src_caps(CHG, 0, NULL); -} -DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, chg_pd_disconnect, HOOK_PRIO_DEFAULT); - -static int cmd_dp_action(int argc, char *argv[]) +static int cmd_dp_action(int argc, const char *argv[]) { int i; char *e; @@ -1322,8 +1397,7 @@ static int cmd_dp_action(int argc, char *argv[]) } } } - CPRINTS("Pins: %s%s", - (alt_dp_config & ALT_DP_PIN_C) ? "C" : "", + CPRINTS("Pins: %s%s", (alt_dp_config & ALT_DP_PIN_C) ? "C" : "", (alt_dp_config & ALT_DP_PIN_D) ? "D" : ""); } else if (!strcasecmp(argv[1], "mf")) { if (argc >= 3) { @@ -1373,10 +1447,10 @@ static int cmd_dp_action(int argc, char *argv[]) } } CPRINTS("HPD source: %s", - (alt_dp_config & ALT_DP_OVERRIDE_HPD) ? "overridden" - : "external"); + (alt_dp_config & ALT_DP_OVERRIDE_HPD) ? "overridden" : + "external"); CPRINTS("HPD level: %d", get_hpd_level()); - } else if (!strcasecmp(argv[1], "help")) { + } else if (!strcasecmp(argv[1], "help")) { CPRINTS("Usage: usbc_action dp [enable|disable|hpd|mf|pins|" "plug]"); } @@ -1384,7 +1458,7 @@ static int cmd_dp_action(int argc, char *argv[]) return EC_SUCCESS; } -static int cmd_usbc_action(int argc, char *argv[]) +static int cmd_usbc_action(int argc, const char *argv[]) { if (argc >= 2 && !strcasecmp(argv[1], "dp")) return cmd_dp_action(argc - 1, &argv[1]); @@ -1438,6 +1512,41 @@ static int cmd_usbc_action(int argc, char *argv[]) * Drop this message if when we phase out the usbc_role control. */ ccprintf("CHG SRC %dmV\n", user_limited_max_mv); + } else if (!strcasecmp(argv[1], "drswap")) { + if (argc == 2) { + CPRINTF("allow_dr_swap = %d\n", allow_dr_swap); + return EC_SUCCESS; + } + + if (argc != 3) + return EC_ERROR_PARAM2; + + allow_dr_swap = !!atoi(argv[2]); + + } else if (!strcasecmp(argv[1], "prswap")) { + if (argc == 2) { + CPRINTF("allow_pr_swap = %d\n", allow_pr_swap); + return EC_SUCCESS; + } + + if (argc != 3) + return EC_ERROR_PARAM2; + + allow_pr_swap = !!atoi(argv[2]); + } else if (!strcasecmp(argv[1], "fastboot")) { + if (argc == 2) { + CPRINTF("fastboot = %d\n", + !!(cc_config & CC_FASTBOOT_DFP)); + return EC_SUCCESS; + } + + if (argc != 3) + return EC_ERROR_PARAM2; + + if (!!atoi(argv[2])) + cc_config |= CC_FASTBOOT_DFP; + else + cc_config &= ~CC_FASTBOOT_DFP; } else { return EC_ERROR_PARAM1; } @@ -1445,5 +1554,6 @@ static int cmd_usbc_action(int argc, char *argv[]) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(usbc_action, cmd_usbc_action, - "5v|12v|20v|dev|pol0|pol1|drp|dp|chg x(x=voltage)", + "5v|12v|20v|dev|pol0|pol1|drp|dp|chg x(x=voltage)|" + "drswap [1|0]|prswap [1|0]", "Set Servo v4 type-C port state"); diff --git a/board/servo_v4p1/usb_sm.c b/board/servo_v4p1/usb_sm.c index 94b5e0c08d..4c448b7c9d 100644 --- a/board/servo_v4p1/usb_sm.c +++ b/board/servo_v4p1/usb_sm.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,8 +11,8 @@ #include "util.h" #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) #else /* CONFIG_COMMON_RUNTIME */ #define CPRINTF(format, args...) #define CPRINTS(format, args...) @@ -22,8 +22,8 @@ struct internal_ctx { usb_state_ptr last_entered; uint32_t running : 1; - uint32_t enter : 1; - uint32_t exit : 1; + uint32_t enter : 1; + uint32_t exit : 1; }; BUILD_ASSERT(sizeof(struct internal_ctx) == member_size(struct sm_ctx, internal)); @@ -64,9 +64,9 @@ static usb_state_ptr shared_parent_state(usb_state_ptr a, usb_state_ptr b) * functions. */ static void call_entry_functions(const int port, - struct internal_ctx *const internal, - const usb_state_ptr stop, - const usb_state_ptr current) + struct internal_ctx *const internal, + const usb_state_ptr stop, + const usb_state_ptr current) { if (current == stop) return; @@ -91,7 +91,7 @@ static void call_entry_functions(const int port, * during an exit function. */ static void call_exit_functions(const int port, const usb_state_ptr stop, - const usb_state_ptr current) + const usb_state_ptr current) { if (current == stop) return; @@ -105,7 +105,7 @@ static void call_exit_functions(const int port, const usb_state_ptr stop, void set_state(const int port, struct sm_ctx *const ctx, const usb_state_ptr new_state) { - struct internal_ctx * const internal = (void *) ctx->internal; + struct internal_ctx *const internal = (void *)ctx->internal; usb_state_ptr last_state; usb_state_ptr shared_parent; @@ -115,8 +115,8 @@ void set_state(const int port, struct sm_ctx *const ctx, * intended state to transition into. */ if (internal->exit) { - CPRINTF("C%d: Ignoring set state to 0x%pP within 0x%pP", - port, new_state, ctx->current); + CPRINTF("C%d: Ignoring set state to 0x%p within 0x%p", port, + new_state, ctx->current); return; } @@ -167,8 +167,8 @@ void set_state(const int port, struct sm_ctx *const ctx, * functions. */ static void call_run_functions(const int port, - const struct internal_ctx *const internal, - const usb_state_ptr current) + const struct internal_ctx *const internal, + const usb_state_ptr current) { if (!current) return; @@ -185,7 +185,7 @@ static void call_run_functions(const int port, void run_state(const int port, struct sm_ctx *const ctx) { - struct internal_ctx * const internal = (void *) ctx->internal; + struct internal_ctx *const internal = (void *)ctx->internal; internal->running = true; call_run_functions(port, internal, ctx->current); diff --git a/board/servo_v4p1/usb_tc_snk_sm.c b/board/servo_v4p1/usb_tc_snk_sm.c index f9a3966434..d76c2fe24f 100644 --- a/board/servo_v4p1/usb_tc_snk_sm.c +++ b/board/servo_v4p1/usb_tc_snk_sm.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,15 +14,15 @@ #include "usb_sm.h" #include "usb_tc_sm.h" -#define EVT_TIMEOUT_NEVER (-1) -#define EVT_TIMEOUT_5MS (5 * MSEC) +#define EVT_TIMEOUT_NEVER (-1) +#define EVT_TIMEOUT_5MS (5 * MSEC) /* * USB Type-C Sink * See Figure 4-13 in Release 1.4 of USB Type-C Spec. */ -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) /* Type-C Layer Flags */ @@ -36,9 +36,9 @@ enum usb_tc_state { static const struct usb_state tc_states[]; /* TypeC Power strings */ -static const char * const pwr2_5_str = "5V/0.5A"; -static const char * const pwr7_5_str = "5V/1.5A"; -static const char * const pwr15_str = "5V/3A"; +static const char *const pwr2_5_str = "5V/0.5A"; +static const char *const pwr7_5_str = "5V/1.5A"; +static const char *const pwr15_str = "5V/3A"; static struct type_c { /* state machine context */ @@ -101,8 +101,8 @@ static void print_alt_power(void) char const *pwr; cc = tc.polarity ? tc.cc2 : tc.cc1; - if (cc == TYPEC_CC_VOLT_OPEN || - cc == TYPEC_CC_VOLT_RA || cc == TYPEC_CC_VOLT_RD) { + if (cc == TYPEC_CC_VOLT_OPEN || cc == TYPEC_CC_VOLT_RA || + cc == TYPEC_CC_VOLT_RD) { /* Supply removed or not detected */ return; } @@ -288,4 +288,3 @@ void snk_task(void *u) run_state(0, &tc.ctx); } } - diff --git a/board/shotzo/board.c b/board/shotzo/board.c new file mode 100644 index 0000000000..6ae6d8e55c --- /dev/null +++ b/board/shotzo/board.c @@ -0,0 +1,490 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Shotzo board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "cros_board_info.h" +#include "driver/charger/sm5803.h" +#include "driver/led/oz554.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "system.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +uint32_t board_version; + +/* GPIO to enable/disable the USB Type-A port. */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +/* C0 interrupt line triggered by charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + sm5803_interrupt(0); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ + +static int barrel_jack_adapter_is_present(void) +{ + /* Shotzo barrel jack adapter present pin is active low. */ + return !gpio_get_level(GPIO_BJ_ADP_PRESENT_L); +} + +/* + * Barrel-jack power adapter ratings. + */ + +#define BJ_ADP_RATING_DEFAULT 0 /* BJ power ratings default */ +static const struct { + int voltage; + int current; +} bj_power[] = { + { /* 0 - 90W (also default) */ + .voltage = 19500, + .current = 4500 }, +}; + +/* Debounced connection state of the barrel jack */ +static int8_t adp_connected = -1; +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = barrel_jack_adapter_is_present(); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) { + unsigned int bj = BJ_ADP_RATING_DEFAULT; + + pi.voltage = bj_power[bj].voltage; + pi.current = bj_power[bj].current; + } + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +static void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} +static void adp_state_init(void) +{ + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_SUB_ANALOG] = { .name = "SUB_ANALOG", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, + [ADC_TEMP_SENSOR_4] = { .name = "TEMP_SENSOR4", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH16 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Charger chips */ +const struct charger_config_t + chg_chips[] = { [CHARGER_SOLO] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS, + .drv = &sm5803_drv, + } }; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &it83xx_tcpm_drv, +} }; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, +} }; + +void oz554_board_init(void) +{ + int panel_id = 0; + int oz554_id; + + oz554_id = gpio_get_level(GPIO_BL_OZ554_ID); + panel_id |= gpio_get_level(GPIO_PANEL_ID0) << 0; + panel_id |= gpio_get_level(GPIO_PANEL_ID1) << 1; + panel_id |= gpio_get_level(GPIO_PANEL_ID2) << 2; + panel_id |= gpio_get_level(GPIO_PANEL_ID3) << 3; + + if (oz554_id == 0) + CPRINTUSB("OZ554ELN"); + else if (oz554_id == 1) + CPRINTUSB("OZ554ALN"); + else + CPRINTUSB("OZ554A UNKNOWN"); + + switch (panel_id) { + case 0x00: + CPRINTUSB("PANEL M238HAN"); + oz554_set_config(0, 0xF1); + oz554_set_config(1, 0x43); + oz554_set_config(2, 0x44); + oz554_set_config(5, 0xBF); + break; + case 0x08: + CPRINTUSB("PANEL MV238FHM"); + oz554_set_config(0, 0xF1); + oz554_set_config(1, 0x43); + oz554_set_config(2, 0x3C); + oz554_set_config(5, 0xD7); + break; + default: + CPRINTUSB("PANEL UNKNOWN"); + break; + } +} + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT_L); + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + + /* Store board version for use in determining charge limits */ + cbi_get_board_version(&board_version); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + + oz554_board_init(); + gpio_enable_interrupt(GPIO_PANEL_BACKLIGHT_EN); + + /* Charger on the MB will be outputting PROCHOT_ODL and OD CHG_DET */ + sm5803_configure_gpio0(CHARGER_SOLO, GPIO0_MODE_PROCHOT, 1); + sm5803_configure_chg_det_od(CHARGER_SOLO, 1); + + /* Turn on 5V if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +static void board_resume(void) +{ + sm5803_disable_low_power_mode(CHARGER_SOLO); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); + +static void board_suspend(void) +{ + sm5803_enable_low_power_mode(CHARGER_SOLO); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + +static void board_shutdown(void) +{ +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_shutdown, HOOK_PRIO_DEFAULT); + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); +} + +uint16_t tcpc_get_alert_status(void) +{ + /* + * TCPC 0 is embedded in the EC and processes interrupts in the chip + * code (it83xx/intc.c) + */ + return 0; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + if (port == CHARGER_SOLO) { + charger_set_input_current_limit(CHARGER_SOLO, max_ma); + } +} + +__override int extpower_is_present(void) +{ + int port; + int rv; + bool acok; + + for (port = 0; port < board_get_usb_pd_port_count(); port++) { + rv = sm5803_is_acok(port, &acok); + if ((rv == EC_SUCCESS) && acok) + return 1; + } + + if (!gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L)) + return 1; + + CPRINTUSB("No external power present."); + + return 0; +} + +int board_set_active_charge_port(int port) +{ + CPRINTUSB("Requested charge port change to %d", port); + + /* + * The charge manager may ask us to switch to no charger if we're + * running off USB-C only but upstream doesn't support PD. It requires + * that we accept this switch otherwise it triggers an assert and EC + * reset; it's not possible to boot the AP anyway, but we want to avoid + * resetting the EC so we can continue to do the "low power" LED blink. + */ + if (port == CHARGE_PORT_NONE) + return EC_SUCCESS; + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == charge_manager_get_active_charge_port()) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_active, bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_active = !gpio_get_level(GPIO_EN_PPVAR_BJ_ADP_L); + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_active != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTUSB("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + sm5803_vbus_sink_enable(CHARGER_SOLO, 1); + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (!barrel_jack_adapter_is_present()) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + sm5803_vbus_sink_enable(CHARGER_SOLO, 0); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* Vconn control is only for port 0 */ + if (port) + return; + + if (cc_pin == USBPD_CC_PIN_1) + gpio_set_level(GPIO_EN_USB_C0_CC1_VCONN, !!enabled); + else + gpio_set_level(GPIO_EN_USB_C0_CC2_VCONN, !!enabled); +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + int current; + + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + current = (rp == TYPEC_RP_3A0) ? 3000 : 1500; + + charger_set_otg_current_voltage(port, current, 5000); +} + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, + [TEMP_SENSOR_4] = { .name = "5V regular", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_4 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); diff --git a/board/shotzo/board.h b/board/shotzo/board.h new file mode 100644 index 0000000000..c6fcceb045 --- /dev/null +++ b/board/shotzo/board.h @@ -0,0 +1,116 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Shotzo board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +/* Charger */ +#define CONFIG_CHARGER +#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 15000 +#define CONFIG_USB_PD_VBUS_DETECT_CHARGER +#define CONFIG_USB_PD_5V_CHARGER_CTRL +#define CONFIG_CHARGER_OTG + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* Buttons */ +#define CONFIG_DEDICATED_RECOVERY_BUTTON +#define CONFIG_DEDICATED_RECOVERY_BUTTON_2 +#define CONFIG_EMULATED_SYSRQ +#define CONFIG_POWER_BUTTON_IGNORE_LID + +/* Dedicated barreljack charger port */ +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 +#define DEDICATED_CHARGE_PORT 1 + +/* LED backlight controller */ +#define CONFIG_LED_DRIVER_OZ554 + +/* Unused Features */ +#undef CONFIG_BACKLIGHT_LID +#undef CONFIG_BATTERY_CUT_OFF +#undef CONFIG_BATTERY_PRESENT_GPIO +#undef CONFIG_BATTERY_SMART +#undef CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD +#undef CONFIG_BATTERY_REVIVE_DISCONNECT +#undef CONFIG_CMD_KEYBOARD +#undef CONFIG_HIBERNATE +#undef CONFIG_KEYBOARD_BOOT_KEYS +#undef CONFIG_KEYBOARD_RUNTIME_KEYS +#undef CONFIG_LID_SWITCH +#undef CONFIG_USB_CHARGER +#undef CONFIG_VOLUME_BUTTONS +#undef GPIO_USB_C1_DP_HPD + +/* I2C Bus Configuration */ +#define I2C_PORT_BACKLIGHT I2C_PORT_SENSOR + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_SUB_ANALOG, /* ADC13 */ + ADC_TEMP_SENSOR_3, /* ADC15 */ + ADC_TEMP_SENSOR_4, /* ADC16 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_4, + TEMP_SENSOR_COUNT +}; + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_BARRELJACK, +}; + +/* Board specific handlers */ +void led_alert(int enable); +#define PORT_TO_HPD(port) (GPIO_USB_C0_DP_HPD) + +/* Pin renaming */ +#define GPIO_AC_PRESENT GPIO_BJ_ADP_PRESENT_L +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_ODL +#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/shotzo/build.mk b/board/shotzo/build.mk new file mode 100644 index 0000000000..07ea50c392 --- /dev/null +++ b/board/shotzo/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o led.o usb_pd_policy.o diff --git a/board/shotzo/ec.tasklist b/board/shotzo/ec.tasklist new file mode 100644 index 0000000000..1447f9db15 --- /dev/null +++ b/board/shotzo/ec.tasklist @@ -0,0 +1,16 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) diff --git a/board/shotzo/gpio.inc b/board/shotzo/gpio.inc new file mode 100644 index 0000000000..4a26d2631a --- /dev/null +++ b/board/shotzo/gpio.inc @@ -0,0 +1,163 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* charger */ +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(BJ_ADP_PRESENT_L, PIN(J, 1), GPIO_INT_BOTH | GPIO_PULL_UP, adp_connect_interrupt) +GPIO_INT(PANEL_BACKLIGHT_EN, PIN(J, 3), GPIO_INT_RISING, oz554_interrupt) +GPIO_INT(EC_RECOVERY_BTN_ODL, PIN(F, 1), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(H1_EC_RECOVERY_BTN_ODL, PIN(KSI, 5), GPIO_INT_BOTH, button_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) + +/* USB pins */ +GPIO(EN_USB_A_5V, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC1_VCONN, PIN(H, 4), GPIO_OUT_LOW) +GPIO(EN_USB_C0_CC2_VCONN, PIN(H, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(USB_C0_FRS, PIN(C, 4), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(C, 6), GPIO_OUT_HIGH) + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* Misc */ +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) +GPIO(EN_PPVAR_BJ_ADP_L, PIN(J, 0), GPIO_OUT_LOW) +GPIO(EN_VBUS_PWR, PIN(F, 3), GPIO_OUT_HIGH) +GPIO(PANEL_ID0, PIN(K, 4), GPIO_INPUT) +GPIO(PANEL_ID1, PIN(J, 4), GPIO_INPUT) +GPIO(PANEL_ID2, PIN(J, 5), GPIO_INPUT) +GPIO(PANEL_ID3, PIN(J, 6), GPIO_INPUT) +GPIO(BL_OZ554_ID, PIN(A, 7), GPIO_INPUT) +GPIO(EC_CRTL, PIN(F, 0), GPIO_OUT_LOW) +GPIO(EC_EDID_WRITE_EN_L, PIN(B, 5), GPIO_ODR_HIGH) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOA0_NC, PIN(A, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA2_NC, PIN(A, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA3_NC, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOE6_NC, PIN(E, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOI4_NC, PIN(I, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOI6_NC, PIN(I, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOI7_NC, PIN(I, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOK7_NC, PIN(K, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSI0_NC, PIN(KSI, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSI1_NC, PIN(KSI, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSI2_NC, PIN(KSI, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSI3_NC, PIN(KSI, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSI4_NC, PIN(KSI, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSI6_NC, PIN(KSI, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSI7_NC, PIN(KSI, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO0_NC, PIN(KSO_L, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO1_NC, PIN(KSO_L, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO3_NC, PIN(KSO_L, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO4_NC, PIN(KSO_L, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO5_NC, PIN(KSO_L, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO6_NC, PIN(KSO_L, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO7_NC, PIN(KSO_L, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO8_NC, PIN(KSO_H, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO9_NC, PIN(KSO_H, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO10_NC, PIN(KSO_H, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO11_NC, PIN(KSO_H, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO12_NC, PIN(KSO_H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO13_NC, PIN(KSO_H, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO14_NC, PIN(KSO_H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(KSO15_NC, PIN(KSO_H, 7), GPIO_INPUT | GPIO_PULL_DOWN) + +/* LED */ +GPIO(PWR_LED_WHITE_L, PIN(A, 1), GPIO_OUT_HIGH) + +/* Alternate functions GPIO definitions */ +GPIO(EC_KSO_02_INV, PIN(KSO_L, 2), GPIO_OUT_HIGH) /* KSO2 inverted */ + +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC13: EC_SUB_ANALOG, ADC15: TEMP_SENSOR_3, ADC16: TEMP_SENSOR_4 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ diff --git a/board/shotzo/led.c b/board/shotzo/led.c new file mode 100644 index 0000000000..9ca9e7a498 --- /dev/null +++ b/board/shotzo/led.c @@ -0,0 +1,242 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Power LED control for Shotzo. + * Solid white - active power + * 25% duty cycle white, 1s on and 3s off- suspend + * Blinking quicky white, 0.5s on and 0.5s off - alert + * 2 long 2 short white, long for 1s, short for 0.5s and interval + * is 0.5s - critical + * Off - shut down + */ + +#include "chipset.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "timer.h" +#include "util.h" + +/* + * Due to the CSME-Lite processing, upon startup the CPU transitions through + * S0->S3->S5->S3->S0, causing the LED to turn on/off/on, so + * delay turning off the LED during suspend/shutdown. + */ +#define LED_CPU_DELAY_MS (2000 * MSEC) + +#define POWER_LED_ON 0 +#define POWER_LED_OFF 1 + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static int led_set_color_power(enum led_color color) +{ + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_OFF); + break; + case LED_WHITE: + gpio_set_level(GPIO_PWR_LED_WHITE_L, POWER_LED_ON); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} + +static int led_set_color(enum ec_led_id led_id, enum led_color color) +{ + int rv; + + switch (led_id) { + case EC_LED_ID_POWER_LED: + rv = led_set_color_power(color); + break; + default: + return EC_ERROR_UNKNOWN; + } + return rv; +} + +/* When blinking is enabled, led will blinking according to led_blinking_array. + * 1 means led on, 0 means led off, restart from head after reaching the tail. + * The interval is LED_BLINKING_MS. + */ +#define LED_BLINKING_MS (500 * MSEC) +static int *led_blinking_array; +static int led_blinking_count; +static int led_blinking_index; +static void led_blinking(void); +DECLARE_DEFERRED(led_blinking); +static void led_blinking(void) +{ + uint32_t elapsed; + uint32_t next = 0; + uint32_t start = get_time().le.lo; + int signal; + + if (led_blinking_array == NULL) + return; + + if (led_blinking_index > (led_blinking_count - 1)) + led_blinking_index = 0; + + signal = *(led_blinking_array + led_blinking_index); + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) { + switch (signal) { + case 0: + led_set_color(EC_LED_ID_POWER_LED, LED_OFF); + led_blinking_index += 1; + break; + case 1: + led_set_color(EC_LED_ID_POWER_LED, LED_WHITE); + led_blinking_index += 1; + break; + default: + led_blinking_index = 0; + } + } + + elapsed = get_time().le.lo - start; + next = elapsed < LED_BLINKING_MS ? LED_BLINKING_MS - elapsed : 0; + hook_call_deferred(&led_blinking_data, next); +} + +static int led_suspend_array[] = { 1, 1, 0, 0, 0, 0, 0, 0 }; +const int led_suspend_count = ARRAY_SIZE(led_suspend_array); +static void led_suspend(void) +{ + led_blinking_array = led_suspend_array; + led_blinking_count = led_suspend_count; + led_blinking_index = 0; + led_blinking(); +} +DECLARE_DEFERRED(led_suspend); + +static void led_shutdown(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + led_set_color(EC_LED_ID_POWER_LED, LED_OFF); +} +DECLARE_DEFERRED(led_shutdown); + +static void led_suspend_hook(void) +{ + hook_call_deferred(&led_blinking_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + hook_call_deferred(&led_suspend_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend_hook, HOOK_PRIO_DEFAULT); + +static void led_shutdown_hook(void) +{ + hook_call_deferred(&led_blinking_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, LED_CPU_DELAY_MS); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown_hook, HOOK_PRIO_DEFAULT); + +static void led_resume_hook(void) +{ + hook_call_deferred(&led_blinking_data, -1); + hook_call_deferred(&led_suspend_data, -1); + hook_call_deferred(&led_shutdown_data, -1); + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + led_set_color(EC_LED_ID_POWER_LED, LED_WHITE); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume_hook, HOOK_PRIO_DEFAULT); + +static int led_alert_array[] = { 1, 0 }; +const int led_alert_count = ARRAY_SIZE(led_alert_array); +void led_alert(int enable) +{ + if (enable) { + /* Overwrite the current signal */ + hook_call_deferred(&led_blinking_data, -1); + led_blinking_array = led_alert_array; + led_blinking_count = led_alert_count; + led_blinking_index = 0; + led_blinking(); + } else { + /* Restore the previous signal */ + if (chipset_in_state(CHIPSET_STATE_ON)) + led_resume_hook(); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + led_suspend_hook(); + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + led_shutdown_hook(); + } +} + +static int led_critical_array[] = { 1, 1, 0, 1, 1, 0, 1, 0, 1, 0 }; +const int led_critical_count = ARRAY_SIZE(led_critical_array); +void show_critical_error(void) +{ + hook_call_deferred(&led_blinking_data, -1); + led_blinking_array = led_critical_array; + led_blinking_count = led_critical_count; + led_blinking_index = 0; + led_blinking(); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + switch (led_id) { + case EC_LED_ID_POWER_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + break; + default: + break; + } +} + +int led_set_brightness(enum ec_led_id id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color(id, LED_WHITE); + else + led_set_color(id, LED_OFF); + + return EC_SUCCESS; +} + +static int command_led(int argc, const char **argv) +{ + enum ec_led_id id = EC_LED_ID_POWER_LED; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "debug")) { + led_auto_control(id, !led_auto_control_is_enabled(id)); + ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n"); + } else if (!strcasecmp(argv[1], "off")) { + led_set_color(id, LED_OFF); + } else if (!strcasecmp(argv[1], "white")) { + led_set_color(id, LED_WHITE); + } else if (!strcasecmp(argv[1], "alert")) { + led_alert(1); + } else if (!strcasecmp(argv[1], "crit")) { + show_critical_error(); + } else if (!strcasecmp(argv[1], "resume")) { + led_resume_hook(); + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(led, command_led, "[debug|white|off|alert|crit|resume]", + "Turn on/off LED."); diff --git a/board/shotzo/usb_pd_policy.c b/board/shotzo/usb_pd_policy.c new file mode 100644 index 0000000000..8c2b840121 --- /dev/null +++ b/board/shotzo/usb_pd_policy.c @@ -0,0 +1,82 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/sm5803.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + if (port < 0 || port >= board_get_usb_pd_port_count()) + return; + + prev_en = charger_is_sourcing_otg_power(port); + + /* Disable Vbus */ + charger_enable_otg_power(port, 0); + + /* Discharge Vbus if previously enabled */ + if (prev_en) + sm5803_set_vbus_disch(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + enum ec_error_list rv; + + /* Disable sinking */ + rv = sm5803_vbus_sink_enable(port, 0); + if (rv) + return rv; + + /* Disable Vbus discharge */ + sm5803_set_vbus_disch(port, 0); + + /* Provide Vbus */ + charger_enable_otg_power(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +__override bool pd_check_vbus_level(int port, enum vbus_level level) +{ + return sm5803_check_vbus_level(port, level); +} + +int pd_snk_is_vbus_provided(int port) +{ + return sm5803_is_vbus_present(port); +} + +int board_vbus_source_enabled(int port) +{ + /* Ignore non-PD ports (the barrel jack). */ + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return 0; + return charger_is_sourcing_otg_power(port); +} diff --git a/board/shotzo/vif_override.xml b/board/shotzo/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/shotzo/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/shuboz/analyzestack.yaml b/board/shuboz/analyzestack.yaml new file mode 100644 index 0000000000..7ff5f39644 --- /dev/null +++ b/board/shuboz/analyzestack.yaml @@ -0,0 +1,2 @@ +remove: +- panic_assert_fail diff --git a/board/shuboz/battery.c b/board/shuboz/battery.c new file mode 100644 index 0000000000..f24c50d931 --- /dev/null +++ b/board/shuboz/battery.c @@ -0,0 +1,154 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_state.h" +#include "common.h" +#include "hooks.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" + +/* + * Battery info for all Zork battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* CM1500 50Wh */ + [BATTERY_CM1500] = { + .fuel_gauge = { + .manuf_name = "AS3GXXD3KB", + .device_name = "C140243", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000c, + .disconnect_val = 0x000c, + } + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11880, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_CM1500; + +static uint16_t current_table[] = { + 2200, + 1800, + 1700, + 1600, +}; +#define NUM_CURRENT_LEVELS ARRAY_SIZE(current_table) + +#define TEMP_THRESHOLD 54 +static int current_level; + +/* Called by hook task every hook second (1 sec) */ +static void current_update(void) +{ + int t, temp; + int rv; + static int Uptime; + static int Dntime; + + rv = temp_sensor_read(TEMP_SENSOR_CHARGER, &t); + if (rv != EC_SUCCESS) + return; + + temp = K_TO_C(t); + + if (temp > TEMP_THRESHOLD) { + Dntime = 0; + if (Uptime < 5) + Uptime++; + else { + Uptime = 0; + current_level++; + } + } else if (current_level != 0 && temp < TEMP_THRESHOLD) { + Uptime = 0; + if (Dntime < 5) + Dntime++; + else { + Dntime = 0; + current_level--; + } + } else { + Uptime = 0; + Dntime = 0; + } + + if (current_level < 0) + current_level = 0; + else if (current_level > NUM_CURRENT_LEVELS) + current_level = NUM_CURRENT_LEVELS; +} +DECLARE_HOOK(HOOK_SECOND, current_update, HOOK_PRIO_DEFAULT); + +int charger_profile_override(struct charge_state_data *curr) +{ + /* + * Precharge must be executed when communication is failed on + * dead battery. + */ + if (!(curr->batt.flags & BATT_FLAG_RESPONSIVE)) + return 0; + + if (current_level != 0) { + if (curr->requested_current > current_table[current_level - 1]) + curr->requested_current = + current_table[current_level - 1]; + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/shuboz/board.c b/board/shuboz/board.c new file mode 100644 index 0000000000..81c0ebe01b --- /dev/null +++ b/board/shuboz/board.c @@ -0,0 +1,629 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery_smart.h" +#include "button.h" +#include "cbi_ssfc.h" +#include "cros_board_info.h" +#include "driver/accel_kionix.h" +#include "driver/accel_kx022.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/ppc/aoz1380_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/usb_mux/amd_fp5.h" +#include "driver/usb_mux/ps8740.h" +#include "driver/usb_mux/ps8743.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "ioexpander.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "thermal.h" +#include "usb_charge.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* This I2C moved. Temporarily detect and support the V0 HW. */ +int I2C_PORT_BATTERY = I2C_PORT_BATTERY_V1; + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Motion sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* sensor private data */ +static struct kionix_accel_data g_kx022_data; +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; + +/* Matrix to rotate accelrator into standard reference frame */ +static const mat33_fp_t lid_standard_ref = { + { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) }, +}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +static const mat33_fp_t base_standard_ref_icm = { + { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) }, +}; + +/* TODO(gcc >= 5.0) Remove the casts to const pointer at rot_standard_ref */ +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs. */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g, enough for laptop. */ + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void setup_base_gyro_config(void) +{ + if (get_cbi_ssfc_base_sensor() == SSFC_BASE_GYRO_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE GYRO is ICM426XX"); + } else + ccprints("BASE GYRO is BMI160"); +} + +void motion_interrupt(enum gpio_signal signal) +{ + if (get_cbi_ssfc_base_sensor() == SSFC_BASE_GYRO_ICM426XX) + icm426xx_interrupt(signal); + else + bmi160_interrupt(signal); +} + +/***************************************************************************** + * Board suspend / resume + */ + +static void board_chipset_resume(void) +{ + ioex_set_level(IOEX_USB_A1_RETIMER_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +static void board_chipset_suspend(void) +{ + ioex_set_level(IOEX_USB_A1_RETIMER_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +static int board_ps8743_mux_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int res; + + if (mux_state & USB_PD_MUX_DP_ENABLED) + /* Enable IN_HPD on the DB */ + ioex_set_level(IOEX_USB_C1_HPD_IN_DB, 1); + else + /* Disable IN_HPD on the DB */ + ioex_set_level(IOEX_USB_C1_HPD_IN_DB, 0); + + res = ps8743_write(me, PS8743_REG_USB_EQ_RX, 0xB0); + return res; +} + +/***************************************************************************** + * USB-C + */ + +/* + * USB C0 port SBU mux use standalone FSUSB42UMX + * chip and it need a board specific driver. + * Overall, it will use chained mux framework. + */ +static int fsusb42umx_set_mux(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) +{ + /* This driver does not use host command ACKs */ + *ack_required = false; + + if (mux_state & USB_PD_MUX_POLARITY_INVERTED) + ioex_set_level(IOEX_USB_C0_SBU_FLIP, 1); + else + ioex_set_level(IOEX_USB_C0_SBU_FLIP, 0); + + return EC_SUCCESS; +} + +/* + * .init is not necessary here because it has nothing + * to do. Primary mux will handle mux state so .get is + * not needed as well. usb_mux.c can handle the situation + * properly. + */ +const struct usb_mux_driver usbc0_sbu_mux_driver = { + .set = fsusb42umx_set_mux, +}; + +/* + * Since FSUSB42UMX is not a i2c device, .i2c_port and + * .i2c_addr_flags are not required here. + */ +const struct usb_mux_chain usbc0_sbu_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &usbc0_sbu_mux_driver, + }, +}; + +struct usb_mux_chain usbc1_amd_fp5_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + .flags = USB_MUX_FLAG_SET_WITHOUT_FLIP, + }, +}; + +struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_sbu_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PS8743_I2C_ADDR1_FLAG, + .driver = &ps8743_usb_mux_driver, + .board_set = &board_ps8743_mux_set, + }, + .next = &usbc1_amd_fp5_usb_mux, + } +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + /* Device does not talk I2C */ + .drv = &aoz1380_drv + }, + + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = NX20P3483_ADDR1_FLAGS, + .drv = &nx20p348x_drv + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_FAULT_ODL: + aoz1380_interrupt(USBC_PORT_C0); + break; + + case GPIO_USB_C1_PPC_INT_ODL: + /* + * Sensitive only to falling edges; GPIO is configured for both + * because this input may be used for HDMI HPD instead. + */ + if (!gpio_get_level(signal)) + nx20p348x_interrupt(USBC_PORT_C1); + break; + + default: + break; + } +} + +int board_set_active_charge_port(int port) +{ + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + switch (port) { + case USBC_PORT_C0: + ioex_set_level(IOEX_USB_C0_FAULT_ODL, !is_overcurrented); + break; + + case USBC_PORT_C1: + ioex_set_level(IOEX_USB_C1_FAULT_ODL, !is_overcurrented); + break; + + default: + break; + } +} + +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +static void reset_nct38xx_port(int port) +{ + enum gpio_signal reset_gpio_l; + + if (port == USBC_PORT_C0) + reset_gpio_l = GPIO_USB_C0_TCPC_RST_L; + else if (port == USBC_PORT_C1) + reset_gpio_l = GPIO_USB_C1_TCPC_RST_L; + else + /* Invalid port: do nothing */ + return; + + gpio_set_level(reset_gpio_l, 0); + msleep(NCT38XX_RESET_HOLD_DELAY_MS); + gpio_set_level(reset_gpio_l, 1); + nct38xx_reset_notify(port); + if (NCT3807_RESET_POST_DELAY_MS != 0) + msleep(NCT3807_RESET_POST_DELAY_MS); +} + +void board_reset_pd_mcu(void) +{ + /* Reset TCPC0 */ + reset_nct38xx_port(USBC_PORT_C0); + + /* Reset TCPC1 */ + reset_nct38xx_port(USBC_PORT_C1); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set and ignore if that TCPC has + * its reset line active. + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) { + if (gpio_get_level(GPIO_USB_C0_TCPC_RST_L) != 0) + status |= PD_STATUS_TCPC_ALERT_0; + } + + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) { + if (gpio_get_level(GPIO_USB_C1_TCPC_RST_L) != 0) + status |= PD_STATUS_TCPC_ALERT_1; + } + + return status; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_TCPC_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + + default: + break; + } +} + +int board_pd_set_frs_enable(int port, int enable) +{ + int rv = EC_SUCCESS; + + /* Use the TCPC to enable fast switch when FRS included */ + if (port == USBC_PORT_C0) { + rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, !!enable); + } else { + rv = ioex_set_level(IOEX_USB_C1_TCPC_FASTSW_CTL_EN, !!enable); + } + + return rv; +} + +static void setup_fw_config(void) +{ + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_FAULT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC 1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); + + /* Enable SBU fault interrupts */ + ioex_enable_interrupt(IOEX_USB_C0_SBU_FAULT_ODL); + ioex_enable_interrupt(IOEX_USB_C1_SBU_FAULT_DB_ODL); + + /* Config Thermal params */ + thermal_params[0].temp_host[EC_TEMP_THRESH_HIGH] = C_TO_K(72); + thermal_params[0].temp_host[EC_TEMP_THRESH_HALT] = C_TO_K(80); + thermal_params[0].temp_host_release[EC_TEMP_THRESH_HIGH] = C_TO_K(67); + thermal_params[1].temp_host[EC_TEMP_THRESH_HIGH] = C_TO_K(72); + thermal_params[1].temp_host[EC_TEMP_THRESH_HALT] = C_TO_K(80); + thermal_params[1].temp_host_release[EC_TEMP_THRESH_HIGH] = C_TO_K(67); + + if (ec_config_has_lid_angle_tablet_mode()) { + setup_base_gyro_config(); + /* Enable Gyro interrupts */ + gpio_enable_interrupt(GPIO_6AXIS_INT_L); + } else { + motion_sensor_count = 0; + /* Device is clamshell only */ + tablet_set_mode(0, TABLET_TRIGGER_LID); + /* Gyro is not present, don't allow line to float */ + gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + } +} +/* + * Use HOOK_PRIO_INIT_I2C + 2 to be after ioex_init(). + */ +DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP, + .freq = 100, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT3807] = { + .i2c_host_port = I2C_PORT_TCPC0, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + }, + [IOEX_C1_NCT3807] = { + .i2c_host_port = I2C_PORT_TCPC1, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +int usb_port_enable[USBA_PORT_COUNT] = { + IOEX_EN_USB_A0_5V, + IOEX_EN_USB_A1_5V_DB, +}; diff --git a/board/shuboz/board.h b/board/shuboz/board.h new file mode 100644 index 0000000000..64e54fc7a2 --- /dev/null +++ b/board/shuboz/board.h @@ -0,0 +1,163 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trembyle board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_ZORK_DALBOZ + +#include "baseboard.h" + +#include + +#define CONFIG_USBC_PPC_NX20P3483 +#define CONFIG_USB_MUX_PS8740 +#define CONFIG_USB_MUX_PS8743 +#define CONFIG_USB_MUX_RUNTIME_CONFIG + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PORT_ENABLE_DYNAMIC + +#undef PD_MAX_POWER_MW +#define PD_MAX_POWER_MW 45000 +#undef PD_MAX_CURRENT_MA +#define PD_MAX_CURRENT_MA 3000 +#undef CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 40000 + +#define CONFIG_CHARGER_PROFILE_OVERRIDE + +/* USB-A config */ +#define GPIO_USB1_ILIM_SEL IOEX_USB_A0_CHARGE_EN_L +#define GPIO_USB2_ILIM_SEL IOEX_USB_A1_CHARGE_EN_DB_L + +/* Power LEDs */ +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +/* Motion sensing drivers */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCEL_KX022 +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_TABLET_MODE +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +/* + * Jelboz's battery takes several seconds to come back out of its disconnect + * state (~4 seconds on the unit I have, so give it a little more for margin). + */ +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#define CONFIG_POWER_BUTTON_INIT_TIMEOUT 5 + +/* GPIO mapping from board specific name to EC common name. */ +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE + +#ifndef __ASSEMBLER__ + +/* This I2C moved. Temporarily detect and support the V0 HW. */ +extern int I2C_PORT_BATTERY; + +enum adc_channel { ADC_TEMP_SENSOR_CHARGER, ADC_TEMP_SENSOR_SOC, ADC_CH_COUNT }; + +enum battery_type { + BATTERY_CM1500, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_COUNT }; + +enum ioex_port { IOEX_C0_NCT3807 = 0, IOEX_C1_NCT3807, IOEX_PORT_COUNT }; + +#define PORT_TO_HPD(port) ((port == 0) ? GPIO_USB3_C0_DP2_HPD : GPIO_DP1_HPD) + +enum temp_sensor_id { + TEMP_SENSOR_CHARGER = 0, + TEMP_SENSOR_SOC, + TEMP_SENSOR_CPU, + TEMP_SENSOR_COUNT +}; + +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +/***************************************************************************** + * CBI EC FW Configuration + */ +/** + * SHUBOZ_MB_USBAC + * USB-A0 Speed: 5 Gbps + * Retimer: none + * USB-C0 Speed: 5 Gbps + * Retimer: none + * TCPC: NCT3807 + * PPC: AOZ1380 + * IOEX: TCPC + */ +enum ec_cfg_usb_mb_type { + SHUBOZ_MB_USBAC = 0, +}; + +/** + * SHUBOZ_DB_D_OPT1_USBAC + * USB-A1 Speed: 5 Gbps + * Retimer: TUSB522 + * USB-C1 Speed: 5 Gbps + * Retimer: PS8740 + * TCPC: NCT3807 + * PPC: NX20P3483 + * IOEX: TCPC + * HDMI Exists: no + * Retimer: none + * MST Hub: none + */ +enum ec_cfg_usb_db_type { + SHUBOZ_DB_D_OPT1_USBAC = 0, +}; + +#include "cbi_ec_fw_config.h" + +void board_reset_pd_mcu(void); + +/* Common definition for the USB PD interrupt handlers. */ +void tcpc_alert_event(enum gpio_signal signal); +void bc12_interrupt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/shuboz/build.mk b/board/shuboz/build.mk new file mode 100644 index 0000000000..45c71f962c --- /dev/null +++ b/board/shuboz/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7wc +BASEBOARD:=zork + +board-y=board.o led.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/shuboz/ec.tasklist b/board/shuboz/ec.tasklist new file mode 100644 index 0000000000..abc796f74f --- /dev/null +++ b/board/shuboz/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/shuboz/gpio.inc b/board/shuboz/gpio.inc new file mode 100644 index 0000000000..c824a80cd4 --- /dev/null +++ b/board/shuboz/gpio.inc @@ -0,0 +1,134 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(3, 4), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(F, 1), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_FAULT_ODL, PIN(6, 3), GPIO_INT_FALLING, ppc_interrupt) +/* PPC interrupts trigger on falling edge, but HDMI HPD triggers on rising edge. */ +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(D, 4), GPIO_INT_BOTH | GPIO_PULL_UP, ppc_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(9, 3), GPIO_INT_FALLING | GPIO_PULL_UP, bc12_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_PULL_UP, bc12_interrupt) +GPIO_INT(SLP_S3_L, PIN(7, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S5_L, PIN(E, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(S0_PWROK_OD, PIN(5, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(EC_PWROK_OD, PIN(3, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_WP_L, PIN(5, 0), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(A, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLDN_BTN_ODL, PIN(9, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, motion_interrupt) + +/* GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an interrupt handler. */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) + +GPIO(3AXIS_INT_L, PIN(9, 6), GPIO_INPUT | GPIO_PULL_DOWN) /* 3 Axis Accel */ +GPIO(CCD_MODE_ODL, PIN(C, 6), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(PROCHOT_ODL, PIN(D, 5), GPIO_ODR_HIGH) /* PROCHOT to SOC */ +GPIO(EC_BATT_PRES_ODL, PIN(4, 1), GPIO_INPUT) /* Battery Present */ +GPIO(EC_AP_INT_ODL, PIN(A, 3), GPIO_ODR_HIGH) /* Sensor MKBP event to SOC */ +GPIO(EN_PWR_A, PIN(B, 7), GPIO_OUT_LOW) /* Enable Power */ +GPIO(EC_EDP_BL_DISABLE, PIN(A, 2), GPIO_OUT_HIGH) /* Enable Backlight */ +GPIO(EC_ENTERING_RW, PIN(E, 5), GPIO_OUT_LOW) /* EC Entering RW */ +GPIO(EC_FCH_PWR_BTN_L, PIN(6, 7), GPIO_OUT_HIGH) /* Power Button to SOC */ +GPIO(EC_FCH_RSMRST_L, PIN(A, 1), GPIO_OUT_LOW) /* RSMRST# to SOC */ +GPIO(EC_FCH_PWROK, PIN(7, 0), GPIO_OUT_LOW) /* Power OK to SOC */ +GPIO(EC_FCH_WAKE_L, PIN(0, 3), GPIO_OUT_HIGH) /* Wake SOC */ +GPIO(EC_FCH_SCI_ODL, PIN(7, 6), GPIO_ODR_HIGH) /* SCI to SOC */ +GPIO(EC_SYS_RST_L, PIN(C, 7), GPIO_ODR_HIGH) /* Cold Reset to SOC */ +GPIO(USB_C0_TCPC_RST_L, PIN(E, 1), GPIO_OUT_HIGH) /* C0 TCPC Reset */ +GPIO(USB_C1_TCPC_RST_L, PIN(F, 0), GPIO_OUT_HIGH) /* C1 TCPC Reset */ +GPIO(USB3_C0_DP2_HPD, PIN(F, 5), GPIO_OUT_LOW) /* C0 DP Hotplug Detect */ +GPIO(DP1_HPD, PIN(F, 4), GPIO_OUT_LOW) /* C1 DP Hotplug Detect */ +GPIO(EC_H1_PACKET_MODE, PIN(8, 6), GPIO_OUT_LOW) /* H1 Packet Mode */ + +UNIMPLEMENTED(PCH_SMI_L) + +GPIO(LED_FULL_L, PIN(6, 0), GPIO_OUT_HIGH) +GPIO(LED_CHRG_L, PIN(C, 0), GPIO_OUT_HIGH) + +/* + * Dalboz has 2 DB options, with different IO expanders. IOEX_C1_NCT3807 is the + * OPT1 DB (USB-C1), IOEX_HDMI_PCAL6408 is the OPT2 DB (HDMI). + */ + +IOEX_INT(USB_C0_SBU_FAULT_ODL, EXPIN(IOEX_C0_NCT3807, 1, 2), GPIO_INT_FALLING, sbu_fault_interrupt) +IOEX_INT(USB_C1_SBU_FAULT_DB_ODL, EXPIN(IOEX_C1_NCT3807, 1, 2), GPIO_INT_FALLING, sbu_fault_interrupt) + +IOEX(USB_C0_FAULT_ODL, EXPIN(IOEX_C0_NCT3807, 0, 3), GPIO_ODR_HIGH) /* C0 Fault to SOC */ +IOEX(USB_C0_TCPC_FASTSW_CTL_EN, EXPIN(IOEX_C0_NCT3807, 0, 4), GPIO_OUT_LOW) /* C0 FastSwitch Control */ +IOEX(USB_C1_FAULT_ODL, EXPIN(IOEX_C0_NCT3807, 1, 0), GPIO_ODR_HIGH) /* C1 Fault to SOC */ +IOEX(USB_C0_PPC_ILIM_3A_EN, EXPIN(IOEX_C0_NCT3807, 1, 1), GPIO_OUT_LOW) /* C0 3A Current Limit Enable */ +IOEX(KB_BL_EN, EXPIN(IOEX_C0_NCT3807, 1, 3), GPIO_OUT_LOW) /* KB Backlight Enable */ +IOEX(EN_USB_A0_5V, EXPIN(IOEX_C0_NCT3807, 1, 5), GPIO_OUT_LOW) /* A0 5V Source Enable */ +IOEX(USB_A0_CHARGE_EN_L, EXPIN(IOEX_C0_NCT3807, 1, 6), GPIO_OUT_HIGH) /* A0 5V High Current Enable */ +IOEX(USB_C0_SBU_FLIP, EXPIN(IOEX_C0_NCT3807, 1, 7), GPIO_OUT_LOW) /* C0 SBU Flip */ + +IOEX(USB_A1_RETIMER_EN, EXPIN(IOEX_C1_NCT3807, 0, 0), GPIO_OUT_LOW) /* A1 Retimer Enable */ +IOEX(USB_C1_HPD_IN_DB, EXPIN(IOEX_C1_NCT3807, 0, 2), GPIO_OUT_LOW) /* C1 HPD */ +IOEX(USB_C1_TCPC_FASTSW_CTL_EN, EXPIN(IOEX_C1_NCT3807, 0, 4), GPIO_OUT_LOW) /* C1 FastSwitch Control */ +IOEX(USB_C1_PPC_EN_L, EXPIN(IOEX_C1_NCT3807, 1, 3), GPIO_OUT_LOW) /* C1 PPC Enable */ +IOEX(USB_C1_DATA_EN, EXPIN(IOEX_C1_NCT3807, 1, 5), GPIO_OUT_HIGH) /* C1 Retimer Enable */ +IOEX(EN_USB_A1_5V_DB, EXPIN(IOEX_C1_NCT3807, 1, 6), GPIO_OUT_LOW) /* A1 5V Source Enable */ +IOEX(USB_A1_CHARGE_EN_DB_L, EXPIN(IOEX_C1_NCT3807, 1, 7), GPIO_OUT_HIGH) /* A1 5V High Current Enable */ + +/* + * The NPCX LPC driver configures and controls SCI, so PCH_SCI_ODL [PIN(7, 6)] + * is not defined here as GPIO. + */ + +/* I2C pins - these will be reconfigured for alternate function below */ +GPIO(EC_I2C_USB_A0_C0_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_USB_A0_C0_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_A1_C1_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_A1_C1_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_POWER_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USBC_AP_MUX_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USBC_AP_MUX_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(FCH_SIC, PIN(F, 3), GPIO_INPUT) +GPIO(FCH_SID, PIN(F, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_CBI_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_CBI_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(I2C_AUDIO_USB_HUB_SCL, PIN(E, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(I2C_AUDIO_USB_HUB_SDA, PIN(E, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_BATT_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_BATT_SDA, PIN(B, 2), GPIO_INPUT) + +ALTERNATE(PIN_MASK(6, BIT(4) | BIT(5)), 0, MODULE_UART, 0) /* Cr50 requires no pullups. */ + +ALTERNATE(PIN_MASK(B, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C0 */ +ALTERNATE(PIN_MASK(9, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ +ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(D, BIT(0) | BIT(1)), 0, MODULE_I2C, 0) /* I2C3 */ +ALTERNATE(PIN_MASK(F, BIT(2) | BIT(3)), 0, MODULE_I2C, 0) /* I2C4 */ +ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(E, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C6 */ +ALTERNATE(PIN_MASK(B, BIT(2) | BIT(3)), 0, MODULE_I2C, 0) /* I2C7 */ + +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC2, ADC3 Temp Sensors */ + +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* PWM3 KB Backlight */ + +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT) /* KSI_00-01 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT) /* KSI_02-07 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 inverted */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ +ALTERNATE(PIN_MASK(0, 0xE0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-12 */ + +/* Power Switch Logic (PSL) inputs */ +ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* AC_PRESENT, POWER_BUTTON_L, EC_RST_ODL */ +ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* LID_OPEN */ + +ALTERNATE(PIN_MASK(A, 0xA0), 1, MODULE_WOV, 0) /* I2S_SYNC/I2S_SCLK GPIOA5/A7 */ +ALTERNATE(PIN_MASK(B, 0x01), 1, MODULE_WOV, 0) /* I2S_SDAT GPIOB0 */ +ALTERNATE(PIN_MASK(9, 0x90), 1, MODULE_WOV, 0) /* DMIC_CLK/DMIC_IN GPIO94/97 */ diff --git a/board/shuboz/led.c b/board/shuboz/led.c new file mode 100644 index 0000000000..dc3361ba5a --- /dev/null +++ b/board/shuboz/led.c @@ -0,0 +1,103 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { LED_OFF, 2 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_FULL_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_CHRG_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_FULL_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_CHRG_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_FULL_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_CHRG_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/shuboz/vif_override.xml b/board/shuboz/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/shuboz/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/spherion/battery.c b/board/spherion/battery.c new file mode 100644 index 0000000000..b103a58d56 --- /dev/null +++ b/board/spherion/battery.c @@ -0,0 +1,112 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_state.h" +#include "chipset.h" +#include "gpio.h" +#include "temp_sensor.h" +#include "util.h" + +const struct board_batt_params board_battery_info[] = { + [BATTERY_C235] = { + .fuel_gauge = { + .manuf_name = "AS3GWRc3KA", + .device_name = "C235-41", + .ship_mode = { + .reg_addr = 0x0, + .reg_data = { 0x10, 0x10 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x0c, + .disconnect_val = 0x0c, + } + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7700, + .voltage_min = 6000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = 0, + .discharging_max_c = 60, + }, + }, + /* Panasonic AP1505L Battery Information */ + [BATTERY_PANASONIC_AP15O5L] = { + .fuel_gauge = { + .manuf_name = "PANASONIC KT00305013", + .device_name = "AP15O5L", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x4000, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_PANASONIC_AP15O5L; + +int charger_profile_override(struct charge_state_data *curr) +{ + int charger_temp, charger_temp_c; + int on; + + /* charge confrol if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON); + if (!on) + return 0; + + /* charge control if outside of allowable temperature range */ + if (curr->state == ST_CHARGE) { + temp_sensor_read(TEMP_SENSOR_CHARGER, &charger_temp); + charger_temp_c = K_TO_C(charger_temp); + if (charger_temp_c > 52) + curr->requested_current = + MIN(curr->requested_current, 2200); + else if (charger_temp_c > 48) + curr->requested_current = + MIN(curr->requested_current, + CONFIG_CHARGER_MAX_INPUT_CURRENT); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/spherion/board.c b/board/spherion/board.c new file mode 100644 index 0000000000..b6df18b119 --- /dev/null +++ b/board/spherion/board.c @@ -0,0 +1,126 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Spherion board configuration */ + +#include "adc.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/als_tcs3400.h" +#include "driver/bc12/mt6360.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/ppc/syv682x.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "driver/usb_mux/ps8743.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "regulator.h" +#include "spi.h" +#include "switch.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "timer.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ +const struct adc_t adc_channels[] = { + /* Convert to mV (3000mV/1024). */ + { "VBUS_C0", ADC_MAX_MVOLT * 10, ADC_READ_MAX + 1, 0, CHIP_ADC_CH0 }, + { "BOARD_ID_0", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH1 }, + { "BOARD_ID_1", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH2 }, + /* AMON/BMON gain = 17.97 */ + { "CHARGER_AMON_R", ADC_MAX_MVOLT * 1000 / 17.97, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH3 }, + { "VBUS_C1", ADC_MAX_MVOLT * 10, ADC_READ_MAX + 1, 0, CHIP_ADC_CH5 }, + { "CHARGER_PMON", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, CHIP_ADC_CH6 }, + { "TEMP_SENSOR_CHARGER", ADC_MAX_MVOLT, ADC_READ_MAX + 1, 0, + CHIP_ADC_CH7 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* PWM */ + +/* + * PWM channels. Must be in the exactly same order as in enum pwm_channel. + * There total three 16 bits clock prescaler registers for all pwm channels, + * so use the same frequency and prescaler register setting is required if + * number of pwm channel greater than three. + */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { .channel = PWM_HW_CH_DCR2, + .flags = 0, + .freq_hz = 10000, + .pcfsr_sel = PWM_PRESCALER_C4 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void kb_backlight_enable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, kb_backlight_enable, HOOK_PRIO_DEFAULT); + +static void kb_backlight_disable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kb_backlight_disable, HOOK_PRIO_DEFAULT); + +void board_usb_mux_init(void) +{ + if (board_get_sub_board() == SUB_BOARD_TYPEC) { + ps8743_tune_usb_eq(usb_muxes[1].mux, PS8743_USB_EQ_TX_12_8_DB, + PS8743_USB_EQ_RX_12_8_DB); + ps8743_field_update(usb_muxes[1].mux, PS8743_REG_DCI_CONFIG_2, + PS8743_AUTO_DCI_MODE_MASK, + PS8743_AUTO_DCI_MODE_FORCE_USB); + } +} +DECLARE_HOOK(HOOK_INIT, board_usb_mux_init, HOOK_PRIO_INIT_I2C + 1); + +static void board_suspend(void) +{ + gpio_set_level(GPIO_EN_5V_USM, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_suspend, HOOK_PRIO_DEFAULT); + +static void board_resume(void) +{ + gpio_set_level(GPIO_EN_5V_USM, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_resume, HOOK_PRIO_DEFAULT); diff --git a/board/spherion/board.h b/board/spherion/board.h new file mode 100644 index 0000000000..3c20924605 --- /dev/null +++ b/board/spherion/board.h @@ -0,0 +1,97 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Spherion board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +/* Chipset config */ + +/* Optional features */ +#define CONFIG_LTO +#undef CONFIG_LOW_POWER_S0 + +/* + * TODO: Remove this option once the VBAT no longer keeps high when + * system's power isn't presented. + */ +#define CONFIG_IT83XX_RESET_PD_CONTRACT_IN_BRAM + +/* Temperature sensor */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* LED */ +#define CONFIG_LED_ONOFF_STATES + +/* Keyboard features */ +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* Keyboard backliht */ +#define CONFIG_PWM_KBLIGHT + +/* Charger*/ +#define CONFIG_CHARGER_MAX_INPUT_CURRENT 3100 +#define CONFIG_CHARGER_PROFILE_OVERRIDE + +/* PD / USB-C / PPC */ +#define CONFIG_USB_PD_DEBUG_LEVEL 3 +#define PD_MAX_POWER_MW 65000 +#define PD_MAX_CURRENT_MA CONFIG_CHARGER_MAX_INPUT_CURRENT +#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +/* Optional console commands */ +#define CONFIG_CMD_FLASH +#define CONFIG_CMD_SCRATCHPAD + +/* Sensor */ + +/* SPI / Host Command */ +#undef CONFIG_HOSTCMD_DEBUG_MODE +#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF + +/* USB-A */ +#define USBA_PORT_COUNT 1 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum battery_type { + BATTERY_C235, + BATTERY_PANASONIC_AP15O5L, + BATTERY_TYPE_COUNT, +}; + +enum temp_sensor_id { TEMP_SENSOR_CHARGER, TEMP_SENSOR_COUNT }; + +enum adc_channel { + ADC_VBUS_C0, /* ADC 0 */ + ADC_BOARD_ID_0, /* ADC 1 */ + ADC_BOARD_ID_1, /* ADC 2 */ + ADC_CHARGER_AMON_R, /* ADC 3 */ + ADC_VBUS_C1, /* ADC 5 */ + ADC_CHARGER_PMON, /* ADC 6 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC 7 */ + /* Number of ADC channels */ + ADC_CH_COUNT, +}; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/spherion/build.mk b/board/spherion/build.mk new file mode 100644 index 0000000000..9126acf43f --- /dev/null +++ b/board/spherion/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build + +# the IC is ITE IT8xxx2 +CHIP:=it83xx +CHIP_FAMILY:=it8xxx2 +CHIP_VARIANT:=it81202bx_1024 +BASEBOARD:=asurada + +board-y+=battery.o board.o led.o diff --git a/board/spherion/ec.tasklist b/board/spherion/ec.tasklist new file mode 100644 index 0000000000..ea717385a0 --- /dev/null +++ b/board/spherion/ec.tasklist @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * See CONFIG_TASK_LIST in config.h for details. + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(PDCMD, pd_command_task, NULL, 1024) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, 1024) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, 1280) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, 1280) \ + diff --git a/board/spherion/gpio.inc b/board/spherion/gpio.inc new file mode 100644 index 0000000000..177ccd07ca --- /dev/null +++ b/board/spherion/gpio.inc @@ -0,0 +1,149 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH | GPIO_PULL_UP | + GPIO_HIB_WAKE_HIGH, power_button_interrupt) /* H1_EC_PWR_BTN_ODL */ +GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, + lid_interrupt) + +/* Chipset interrupts */ +GPIO_INT(AP_EC_WARM_RST_REQ, PIN(D, 3), GPIO_INT_RISING | GPIO_SEL_1P8V, + chipset_reset_request_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 7), GPIO_INT_BOTH | GPIO_SEL_1P8V, + chipset_watchdog_interrupt) +GPIO_INT(AP_IN_SLEEP_L, PIN(F, 2), + GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PMIC_EC_PWRGD, PIN(F, 3), + GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) + +/* Sensor Interrupts */ + +/* USB-C interrupts */ +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(D, 1), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL,PIN(J, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_BC12_INT_L, PIN(J, 4), GPIO_INT_FALLING, bc12_interrupt) + +/* Volume button interrupts */ +GPIO_INT(VOLUME_DOWN_L, PIN(D, 5), GPIO_INT_BOTH | GPIO_PULL_UP, + button_interrupt) /* EC_VOLDN_BTN_ODL */ +GPIO_INT(VOLUME_UP_L, PIN(D, 6), GPIO_INT_BOTH | GPIO_PULL_UP, + button_interrupt) /* EC_VOLUP_BTN_ODL */ + +/* Other interrupts */ +GPIO_INT(AP_XHCI_INIT_DONE, PIN(D, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, + usb_a0_interrupt) +GPIO_INT(AC_PRESENT, PIN(E, 5), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, + extpower_interrupt) /* AC_OK / AC_PRESENT in rev1+ */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, + uart_deepsleep_interrupt) /* UART_DEBUG_TX_EC_RX */ +GPIO_INT(WP, PIN(I, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, + switch_interrupt) /* EC_FLASH_WP_OD */ +GPIO_INT(SPI0_CS, PIN(M, 5), GPIO_INT_FALLING, + spi_event) /* SPI slave Chip Select -- AP_SPI_EC_CS_L */ +GPIO_INT(X_EC_GPIO2, PIN(B, 2), GPIO_ODR_HIGH, x_ec_interrupt) + +/* Power Sequencing Signals */ +GPIO(EC_PMIC_EN_ODL, PIN(D, 0), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_PMIC_WATCHDOG_L, PIN(H, 0), GPIO_ODR_LOW | GPIO_SEL_1P8V) +GPIO(EN_PP5000_A, PIN(C, 6), GPIO_OUT_HIGH) +GPIO(PG_MT6315_PROC_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(PG_MT6360_ODL, PIN(F, 1), GPIO_INPUT) +GPIO(PG_PP5000_A_ODL, PIN(A, 6), GPIO_INPUT) +GPIO(EN_SLP_Z, PIN(E, 3), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(B, 6), GPIO_ODR_LOW) +GPIO(EC_BL_EN_OD, PIN(B, 5), GPIO_ODR_LOW | GPIO_SEL_1P8V) + +/* MKBP event synchronization */ +GPIO(EC_INT_L, PIN(E, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_AP_INT_ODL */ + +/* USB and USBC Signals */ +GPIO(DP_AUX_PATH_SEL, PIN(G, 0), GPIO_OUT_HIGH) +GPIO(EC_DPBRDG_HPD_ODL, PIN(J, 0), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EN_PP5000_USB_A0_VBUS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(USB_C0_FRS_EN, PIN(H, 3), GPIO_OUT_LOW) + +/* Misc Signals */ +GPIO(EC_BATT_PRES_ODL, PIN(C, 0), GPIO_INPUT) +GPIO(BC12_DET_EN, PIN(J, 5), GPIO_OUT_LOW) /* EN_USB_C0_BC12_DET */ +GPIO(EN_EC_ID_ODL, PIN(H, 5), GPIO_ODR_LOW) +GPIO(ENTERING_RW, PIN(C, 5), GPIO_OUT_LOW) /* EC_ENTERING_RW */ +GPIO(EC_KB_BL_EN, PIN(G, 3), GPIO_OUT_LOW) /* Keyboard backlight enable */ +GPIO(EN_5V_USM, PIN(D, 7), GPIO_OUT_LOW) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) /* I2C_CHG_BATT_SCL */ +GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) /* I2C_CHG_BATT_SDA */ +GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SCL */ +GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT | GPIO_SEL_1P8V) /* I2C_SENSOR_SDA */ +GPIO(I2C_C_SCL, PIN(F, 6), GPIO_INPUT) /* I2C_USB_C0_SCL */ +GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) /* I2C_USB_C0_SCL */ +GPIO(I2C_E_SCL, PIN(E, 0), GPIO_INPUT) /* I2C_USB_C1_SCL */ +GPIO(I2C_E_SDA, PIN(E, 7), GPIO_INPUT) /* I2C_USB_C1_SDA */ + +/* SPI pins - Alternate function below configures SPI module on these pins */ + +/* NC / TP */ + +/* Keyboard pins */ + +/* Subboards HDMI/TYPEC */ +GPIO(EC_X_GPIO1, PIN(H, 4), GPIO_OUT_LOW) +GPIO(EC_X_GPIO3, PIN(J, 1), GPIO_INPUT) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A */ +ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C B */ +ALTERNATE(PIN_MASK(F, 0xC0), 1, MODULE_I2C, 0) /* I2C C */ +ALTERNATE(PIN_MASK(E, 0x81), 1, MODULE_I2C, 0) /* I2C E */ + +/* UART */ +ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, 0) /* EC to Servo */ + +/* ADC */ +ALTERNATE(PIN_MASK(I, 0xEF), 0, MODULE_ADC, 0) /* ADC 0,1,2,3,5,6,7 */ + +/* SPI */ +ALTERNATE(PIN_MASK(M, 0x33), 0, MODULE_SPI, 0) /* SPI */ + +/* Unimplemented Pins */ +GPIO(SET_VMC_VOLT_AT_1V8, PIN(D, 4), GPIO_INPUT | GPIO_PULL_DOWN | GPIO_SEL_1P8V) +GPIO(PACKET_MODE_EN, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(UNUSED_GPIOA0, PIN(A, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOA1, PIN(A, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOA2, PIN(A, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(UNUSED_GPIOF0, PIN(F, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOJ2, PIN(J, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOJ3, PIN(J, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOJ7, PIN(J, 7), GPIO_INPUT | GPIO_PULL_UP) + +/* b/160218054: behavior not defined */ +/* *_ODL pin has external pullup so don't pull it down. */ +GPIO(USB_A0_FAULT_ODL, PIN(A, 7), GPIO_INPUT) +GPIO(CHARGER_PROCHOT_ODL, PIN(C, 3), GPIO_INPUT) +GPIO(PG_MT6315_GPU_ODL, PIN(H, 6), GPIO_INPUT) +GPIO(EN_PP3000_SD_U, PIN(G, 1), GPIO_INPUT | GPIO_PULL_DOWN | GPIO_SEL_1P8V) +/* reserved for future use */ +GPIO(CCD_MODE_ODL, PIN(C, 4), GPIO_INPUT) + +/* NC pins, enable internal pull-up/down to avoid floating state. */ +GPIO(NC_GPM2, PIN(M, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPM3, PIN(M, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(NC_GPM6, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(SPI_CLK_GPG6, PIN(G, 6), GPIO_INPUT | GPIO_PULL_UP) +/* + * These 3 pins don't have internal pull-down capability, + * so we set them as output low. + */ +GPIO(SPI_MOSI_GPG4, PIN(G, 4), GPIO_OUT_LOW) +GPIO(SPI_MISO_GPG5, PIN(G, 5), GPIO_OUT_LOW) +GPIO(SPI_CS_GPG7, PIN(G, 7), GPIO_OUT_LOW) diff --git a/board/spherion/led.c b/board/spherion/led.c new file mode 100644 index 0000000000..19ade3499e --- /dev/null +++ b/board/spherion/led.c @@ -0,0 +1,88 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery LED control for Spherion + */ + +#include "chipset.h" +#include "driver/bc12/mt6360.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + mt6360_led_set_brightness(MT6360_LED_RGB1, 50); + mt6360_led_set_brightness(MT6360_LED_RGB3, 50); + + switch (color) { + case EC_LED_COLOR_AMBER: + mt6360_led_enable(MT6360_LED_RGB1, 1); + mt6360_led_enable(MT6360_LED_RGB3, 0); + break; + case EC_LED_COLOR_BLUE: + mt6360_led_enable(MT6360_LED_RGB1, 0); + mt6360_led_enable(MT6360_LED_RGB3, 1); + break; + default: /* LED_OFF and other unsupported colors */ + mt6360_led_enable(MT6360_LED_RGB1, 0); + mt6360_led_enable(MT6360_LED_RGB3, 0); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = + MT6360_LED_BRIGHTNESS_MAX; + brightness_range[EC_LED_COLOR_BLUE] = MT6360_LED_BRIGHTNESS_MAX; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/spherion/vif_override.xml b/board/spherion/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/spherion/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/star b/board/star new file mode 120000 index 0000000000..7f4a914148 --- /dev/null +++ b/board/star @@ -0,0 +1 @@ +hammer \ No newline at end of file diff --git a/board/stern/battery.c b/board/stern/battery.c index 50d2bf397c..9edab52867 100644 --- a/board/stern/battery.c +++ b/board/stern/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/stern/board.c b/board/stern/board.c index 0a04842e35..39ab395006 100644 --- a/board/stern/board.c +++ b/board/stern/board.c @@ -1,10 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" #include "charge_manager.h" @@ -31,6 +30,7 @@ #include "it8801.h" #include "keyboard_scan.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "pwm.h" @@ -40,41 +40,55 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { schedule_deferred_pd_interrupt(0 /* port */); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct i2c_port_t i2c_bitbang_ports[] = { - {"battery", 2, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA, .drv = &bitbang_drv}, + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, }; const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); @@ -82,13 +96,13 @@ const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * TODO(b/133200075): Tune this once we have the final performance * out of the driver and the i2c bus. @@ -107,8 +121,8 @@ struct keyboard_scan_config keyscan_config = { struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { [0] = { - .i2c_host_port = I2C_PORT_IO_EXPANDER_IT8801, - .i2c_slave_addr = IT8801_I2C_ADDR, + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, .drv = &it8801_ioexpander_drv, }, }; @@ -133,15 +147,18 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -static void board_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -149,13 +166,16 @@ static void board_hpd_status(const struct usb_mux *me, host_set_single_event(EC_HOST_EVENT_USB_MUX); } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, }, }; @@ -201,7 +221,7 @@ int board_set_active_charge_port(int charge_port) if (board_vbus_source_enabled(charge_port)) return -1; break; - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -209,22 +229,11 @@ int board_set_active_charge_port(int charge_port) */ charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - int board_discharge_on_ac(int enable) { int ret, port; @@ -254,7 +263,7 @@ int pd_snk_is_vbus_provided(int port) void bc12_interrupt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } #ifndef VARIANT_KUKUI_NO_SENSORS @@ -274,13 +283,12 @@ static void board_spi_enable(void) STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; /* Reinitialize spi peripheral. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); /* Pin mux spi peripheral toward the sensor. */ - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_spi_enable, +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, MOTION_SENSE_HOOK_PRIO - 1); static void board_spi_disable(void) @@ -288,14 +296,13 @@ static void board_spi_disable(void) /* Set pins to a state calming the sensor down. */ gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); - gpio_config_module(MODULE_SPI_MASTER, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); /* Disable spi peripheral and clocks. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_spi_disable, +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, MOTION_SENSE_HOOK_PRIO + 1); #endif /* !VARIANT_KUKUI_NO_SENSORS */ @@ -334,17 +341,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Rotation matrixes */ -static const mat33_fp_t base_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(-1), 0}, - {0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -static const mat33_fp_t lid_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(1), 0}, - {0, 0, FLOAT_TO_FP(1) } -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ /* Lid accel private data */ @@ -394,9 +397,10 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = + ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .rot_standard_ref = &base_standard_ref, - .default_range = 2, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, .config = { @@ -422,7 +426,8 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = + ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_GYRO_MIN_FREQ, @@ -452,16 +457,3 @@ int board_get_charger_i2c(void) /* TODO(b:138415463): confirm the bus allocation for future builds */ return board_get_version() == 1 ? 2 : 1; } - -/* Enable or disable input devices, based on chipset state and tablet mode */ -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - /* If the lid is in 360 position, ignore the lid angle, - * which might be faulty. Disable keyboard. - */ - if (tablet_get_mode() || chipset_in_state(CHIPSET_STATE_ANY_OFF)) - enable = 0; - keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); -} -#endif diff --git a/board/stern/board.h b/board/stern/board.h index 1ee3d931eb..0cc8194270 100644 --- a/board/stern/board.h +++ b/board/stern/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,6 +11,7 @@ #define VARIANT_KUKUI_JACUZZI #define VARIANT_KUKUI_BATTERY_SMART #define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32F098 #ifndef SECTION_IS_RW #define VARIANT_KUKUI_NO_SENSORS @@ -18,6 +19,9 @@ #include "baseboard.h" +/* Disable deferred (async) flash protect*/ +#undef CONFIG_FLASH_PROTECT_DEFERRED + #undef CONFIG_CHIPSET_POWER_SEQ_VERSION #define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 @@ -27,6 +31,8 @@ #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_RUNTIME_CONFIG @@ -50,14 +56,12 @@ #define CONFIG_USB_MUX_IT5205 #define CONFIG_LED_ONOFF_STATES -#define CONFIG_LED_POWER_LED #define CONFIG_LED_COMMON /* Motion Sensors */ #ifndef VARIANT_KUKUI_NO_SENSORS -#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ +#define CONFIG_ACCEL_LIS2DWL /* Lid accel */ #define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_CMD_ACCEL_INFO @@ -72,25 +76,24 @@ #endif /* VARIANT_KUKUI_NO_SENSORS */ /* I2C ports */ -#define I2C_PORT_BC12 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_BATTERY 2 -#define I2C_PORT_CHARGER board_get_charger_i2c() -#define I2C_PORT_SENSORS 1 -#define I2C_PORT_IO_EXPANDER_IT8801 1 -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_BATTERY 2 +#define I2C_PORT_CHARGER board_get_charger_i2c() +#define I2C_PORT_SENSORS 1 +#define I2C_PORT_KB_DISCRETE 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY + +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -/* Define the MKBP events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) #ifndef __ASSEMBLER__ @@ -138,7 +141,6 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void bc12_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); /* returns the i2c port number of charger */ int board_get_charger_i2c(void); diff --git a/board/stern/build.mk b/board/stern/build.mk index a6e1c010d7..f583684804 100644 --- a/board/stern/build.mk +++ b/board/stern/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/stern/ec.tasklist b/board/stern/ec.tasklist index 36be2e96a4..e77603a8e2 100644 --- a/board/stern/ec.tasklist +++ b/board/stern/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/stern/gpio.inc b/board/stern/gpio.inc index 51972ec367..85d080b2e9 100644 --- a/board/stern/gpio.inc +++ b/board/stern/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -111,5 +111,5 @@ ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) /* EMMC SPI SLAVE: PB13/14/15 */ ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) /* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ -ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_MASTER, 0) -ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/stern/led.c b/board/stern/led.c index ff5f9f2373..7f4ecb6ace 100644 --- a/board/stern/led.c +++ b/board/stern/led.c @@ -1,50 +1,57 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Damu */ #include "common.h" -#include "ioexpander.h" #include "driver/ioexpander/it8801.h" #include "ec_commands.h" +#include "ioexpander.h" #include "led_common.h" #include "led_onoff_states.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_POWER_LED, + EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: @@ -62,7 +69,7 @@ void led_set_color_battery(enum ec_led_colors color) } } -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_WHITE: diff --git a/board/stern/vif_override.xml b/board/stern/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/stern/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/stm32f446e-eval/board.c b/board/stm32f446e-eval/board.c index fc796464e2..d8f345f9aa 100644 --- a/board/stm32f446e-eval/board.c +++ b/board/stm32f446e-eval/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,7 +7,6 @@ #include "dma.h" #include "ec_version.h" #include "gpio.h" -#include "gpio_list.h" #include "hooks.h" #include "i2c.h" #include "registers.h" @@ -16,16 +15,19 @@ #include "usb_dwc_console.h" #include "usb_hw.h" +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("stm32f446-eval"), - [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("EC Shell"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("stm32f446-eval"), + [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("EC Shell"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); @@ -43,15 +45,21 @@ struct dwc_usb usb_ctl = { /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"i2c1", I2C_PORT_0, 100, - GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"fmpi2c4", FMPI2C_PORT_3, 100, - GPIO_FMPI2C_SCL, GPIO_FMPI2C_SDA}, + { .name = "i2c1", + .port = I2C_PORT_0, + .kbps = 100, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "fmpi2c4", + .port = FMPI2C_PORT_3, + .kbps = 100, + .scl = GPIO_FMPI2C_SCL, + .sda = GPIO_FMPI2C_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -#define GPIO_SET_HS(bank, number) \ - (STM32_GPIO_OSPEEDR(GPIO_##bank) |= (0x3 << ((number) * 2))) +#define GPIO_SET_HS(bank, number) \ + (STM32_GPIO_OSPEEDR(GPIO_##bank) |= (0x3 << ((number)*2))) void board_config_post_gpio_init(void) { @@ -64,28 +72,27 @@ void board_config_post_gpio_init(void) GPIO_SET_HS(A, 11); GPIO_SET_HS(A, 12); - GPIO_SET_HS(C, 3); - GPIO_SET_HS(C, 2); - GPIO_SET_HS(C, 0); - GPIO_SET_HS(A, 5); + GPIO_SET_HS(C, 3); + GPIO_SET_HS(C, 2); + GPIO_SET_HS(C, 0); + GPIO_SET_HS(A, 5); - GPIO_SET_HS(B, 5); + GPIO_SET_HS(B, 5); GPIO_SET_HS(B, 13); GPIO_SET_HS(B, 12); - GPIO_SET_HS(B, 2); + GPIO_SET_HS(B, 2); GPIO_SET_HS(B, 10); - GPIO_SET_HS(B, 1); - GPIO_SET_HS(B, 0); - GPIO_SET_HS(A, 3); + GPIO_SET_HS(B, 1); + GPIO_SET_HS(B, 0); + GPIO_SET_HS(A, 3); /* Set I2C GPIO to HS */ - GPIO_SET_HS(B, 6); - GPIO_SET_HS(B, 7); - GPIO_SET_HS(F, 1); - GPIO_SET_HS(F, 0); - GPIO_SET_HS(A, 8); - GPIO_SET_HS(B, 4); - GPIO_SET_HS(C, 6); - GPIO_SET_HS(C, 7); + GPIO_SET_HS(B, 6); + GPIO_SET_HS(B, 7); + GPIO_SET_HS(F, 1); + GPIO_SET_HS(F, 0); + GPIO_SET_HS(A, 8); + GPIO_SET_HS(B, 4); + GPIO_SET_HS(C, 6); + GPIO_SET_HS(C, 7); } - diff --git a/board/stm32f446e-eval/board.h b/board/stm32f446e-eval/board.h index fa0b0177ef..667483d81f 100644 --- a/board/stm32f446e-eval/board.h +++ b/board/stm32f446e-eval/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -27,7 +27,7 @@ #define CONFIG_UART_RX_REQ_CH 4 #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define I2C_PORT_0 0 #define FMPI2C_PORT_3 3 @@ -43,12 +43,12 @@ /* USB interface indexes (use define rather than enum to expand them) */ #define USB_IFACE_CONSOLE 0 -#define USB_IFACE_COUNT 1 +#define USB_IFACE_COUNT 1 /* USB endpoint indexes (use define rather than enum to expand them) */ #define USB_EP_CONTROL 0 #define USB_EP_CONSOLE 1 -#define USB_EP_COUNT 2 +#define USB_EP_COUNT 2 /* This is not actually an EC so disable some features. */ #undef CONFIG_WATCHDOG_HELP @@ -56,9 +56,8 @@ #undef CONFIG_WATCHDOG /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_DMA_HELP -#define CONFIG_FLASH +#define CONFIG_FLASH_CROS /* * Allow dangerous commands all the time, since we don't have a write protect diff --git a/board/stm32f446e-eval/build.mk b/board/stm32f446e-eval/build.mk index 6b06f2bb8f..61e4b79d47 100644 --- a/board/stm32f446e-eval/build.mk +++ b/board/stm32f446e-eval/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/stm32f446e-eval/ec.tasklist b/board/stm32f446e-eval/ec.tasklist index 2a1ffbf652..6a12f02976 100644 --- a/board/stm32f446e-eval/ec.tasklist +++ b/board/stm32f446e-eval/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/stm32f446e-eval/gpio.inc b/board/stm32f446e-eval/gpio.inc index afc8d1e486..8eb7c6090d 100644 --- a/board/stm32f446e-eval/gpio.inc +++ b/board/stm32f446e-eval/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/stm32l476g-eval/board.c b/board/stm32l476g-eval/board.c index c7ebc2c6b8..1f22fa9373 100644 --- a/board/stm32l476g-eval/board.c +++ b/board/stm32l476g-eval/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,8 +6,8 @@ #include "common.h" #include "gpio.h" #include "hooks.h" -#include "registers.h" #include "i2c.h" +#include "registers.h" #ifdef CTS_MODULE /* @@ -19,6 +19,7 @@ __attribute__((weak)) void cts_irq(enum gpio_signal signal) } #endif +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" void tick_event(void) @@ -32,8 +33,12 @@ void tick_event(void) DECLARE_HOOK(HOOK_TICK, tick_event, HOOK_PRIO_DEFAULT); #ifdef CTS_MODULE_I2C -const struct i2c_port_t i2c_ports[] = { - {"test", STM32_I2C2_PORT, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, +const struct i2c_port_t i2c_ports[] = { + { .name = "test", + .port = STM32_I2C2_PORT, + .kbps = 100, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); #endif diff --git a/board/stm32l476g-eval/board.h b/board/stm32l476g-eval/board.h index 4b8033207b..40c7fb0eca 100644 --- a/board/stm32l476g-eval/board.h +++ b/board/stm32l476g-eval/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,8 +10,8 @@ #ifdef CTS_MODULE /* CTS tests are small. We can use smaller size to expedite flash time. */ -#undef CONFIG_FLASH_SIZE -#define CONFIG_FLASH_SIZE 0x00040000 /* 256k */ +#undef CONFIG_FLASH_SIZE_BYTES +#define CONFIG_FLASH_SIZE_BYTES 0x00040000 /* 256k */ #endif /* Optional features */ @@ -33,11 +33,10 @@ #endif /* Optional features */ -#define CONFIG_STM_HWTIMER32 #ifdef CTS_MODULE_I2C #define CONFIG_I2C -#define CONFIG_I2C_SLAVE +#define CONFIG_I2C_PERIPHERAL #define CONFIG_HOSTCMD_I2C_SLAVE_ADDR 0x3c #define I2C_PORT_EC STM32_I2C2_PORT #endif @@ -50,22 +49,22 @@ #ifndef __ASSEMBLER__ -#undef CONFIG_FLASH +#undef CONFIG_FLASH_CROS #undef CONFIG_FLASH_PHYSICAL /* Timer selection */ -#define TIM_CLOCK32 5 +#define TIM_CLOCK32 5 /* External clock speeds (8 MHz) */ #define STM32_HSE_CLOCK 8000000 /* PLL configuration. Freq = STM32_HSE_CLOCK * n/m/r */ #undef STM32_PLLM -#define STM32_PLLM 1 +#define STM32_PLLM 1 #undef STM32_PLLN -#define STM32_PLLN 10 +#define STM32_PLLN 10 #undef STM32_PLLR -#define STM32_PLLR 2 +#define STM32_PLLR 2 #include "gpio_signal.h" diff --git a/board/stm32l476g-eval/build.mk b/board/stm32l476g-eval/build.mk index 23c7cd9d38..d453ea9979 100644 --- a/board/stm32l476g-eval/build.mk +++ b/board/stm32l476g-eval/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/stm32l476g-eval/ec.tasklist b/board/stm32l476g-eval/ec.tasklist index adfd7c7e92..f580a9d9e5 100644 --- a/board/stm32l476g-eval/ec.tasklist +++ b/board/stm32l476g-eval/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/stm32l476g-eval/gpio.inc b/board/stm32l476g-eval/gpio.inc index 9cf5bc0aa4..e84543f8f6 100644 --- a/board/stm32l476g-eval/gpio.inc +++ b/board/stm32l476g-eval/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/stm32l476g-eval/openocd-flash.cfg b/board/stm32l476g-eval/openocd-flash.cfg index a347f88b79..2f6a266d93 100644 --- a/board/stm32l476g-eval/openocd-flash.cfg +++ b/board/stm32l476g-eval/openocd-flash.cfg @@ -1,4 +1,4 @@ -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/board/storo/battery.c b/board/storo/battery.c new file mode 100644 index 0000000000..5a927ffc26 --- /dev/null +++ b/board/storo/battery.c @@ -0,0 +1,99 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "charge_state.h" +#include "common.h" + +/* + * Battery info for all Storo battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* C21N2018_AS3GXXD3KA Battery Information */ + [BATTERY_AS3GXXD3KA] = { + .fuel_gauge = { + .manuf_name = "AS3GXXD3KA", + .device_name = "C110160", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000C, + .disconnect_val = 0x000C, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0004 + } + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7890, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + + /* C21N2018_AS3FXXD3KA Battery Information */ + [BATTERY_AS3FXXD3KA] = { + .fuel_gauge = { + .manuf_name = "AS3FXXD3KA", + .device_name = "C110160", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .reg_addr = 0x99, + .reg_mask = 0x000C, + .disconnect_val = 0x000C, + .cfet_mask = 0x0004, + .cfet_off_val = 0x0004 + } + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7890, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + } +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AS3GXXD3KA; diff --git a/board/storo/board.c b/board/storo/board.c new file mode 100644 index 0000000000..d8f1b09ae1 --- /dev/null +++ b/board/storo/board.c @@ -0,0 +1,931 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Storo configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "cros_board_info.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_bmi260.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/tusb544.h" +#include "driver/tcpm/raa489000.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprints(CC_SYSTEM, format, ##args) + +#define INT_RECHECK_US 5000 + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) +{ + cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event"); + pd_handle_cc_overvoltage(0); +} + +static void pen_detect_interrupt(enum gpio_signal s) +{ + int pen_detect = !gpio_get_level(GPIO_PEN_DET_ODL); + + gpio_set_level(GPIO_EN_PP3300_PEN, pen_detect); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* BC 1.2 chips */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +/* Charger chips */ +const struct charger_config_t chg_chips[] = { + [CHARGER_PRIMARY] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, + [CHARGER_SECONDARY] = { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +/* USB Retimer */ +enum tusb544_conf { USB_DP = 0, USB_DP_INV, USB, USB_INV, DP, DP_INV }; + +/* + * Registers we care about of are all the same between NCS8510 and TUSB544, + * so we leverage the driver of TUSB544 to control both of them. + * + * For EQ settings, these two chips are also almost the same, so we have one + * set of EQ settings here for both of them as well. When you need to modify + * the EQ settings, please make sure that both configurations are correct; + * otherwise you need to separate EQ settings then. + */ +static int board_tusb544_set(const struct usb_mux *me, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + int reg; + enum tusb544_conf usb_mode = 0; + + if (mux_state & USB_PD_MUX_USB_ENABLED) { + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* USB with DP */ + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? + USB_DP_INV : + USB_DP; + } else { + /* USB without DP */ + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? + USB_INV : + USB; + } + } else if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* DP without USB */ + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? DP_INV : + DP; + } else { + return EC_SUCCESS; + } + + rv = i2c_read8(me->i2c_port, me->i2c_addr_flags, TUSB544_REG_GENERAL6, + ®); + if (rv) + return rv; + + reg |= TUSB544_VOD_DCGAIN_OVERRIDE; + reg &= ~TUSB544_VOD_DCGAIN_SEL; + reg |= (TUSB544_VOD_DCGAIN_SETTING_5 << 2); + + rv = i2c_write8(me->i2c_port, me->i2c_addr_flags, TUSB544_REG_GENERAL6, + reg); + if (rv) + return rv; + + /* Write the retimer config byte */ + if (usb_mode == USB_INV) { + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x15); + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0xff); + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0xff); + } else if (usb_mode == USB) { + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x11); + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0xff); + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0xff); + } else if (usb_mode == USB_DP_INV) { + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1F); + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0xff); + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0xff); + } else if (usb_mode == USB_DP) { + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1B); + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_1, 0xff); + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_USB3_1_2, 0xff); + } else if (usb_mode == DP_INV) { + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1E); + } else if (usb_mode == DP) { + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_GENERAL4, 0x1A); + } + + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_1, 0x66); + rv |= i2c_write8(me->i2c_port, me->i2c_addr_flags, + TUSB544_REG_DISPLAYPORT_2, 0x66); + if (rv) + return EC_ERROR_UNKNOWN; + else + return EC_SUCCESS; +} + +/* USB Retimer */ +const struct usb_mux_chain usbc1_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = TUSB544_I2C_ADDR_FLAGS0, + .driver = &tusb544_drv, + .board_set = &board_tusb544_set, + }, +}; + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + .next = &usbc1_retimer, + }, +}; + +void board_hibernate(void) +{ + /* + * Put all charger ICs present into low power mode before entering + * z-state. + */ + raa489000_hibernate(CHARGER_PRIMARY, true); + if (board_get_charger_chip_count() > 1) + raa489000_hibernate(CHARGER_SECONDARY, true); +} + +__override void board_ocpc_init(struct ocpc_data *ocpc) +{ + /* There's no provision to measure Isys */ + ocpc->chg_flags[CHARGER_SECONDARY] |= OCPC_NO_ISYS_MEAS_CAP; +} + +__override void board_pulse_entering_rw(void) +{ + /* + * On the ITE variants, the EC_ENTERING_RW signal was connected to a pin + * which is active high by default. This causes Cr50 to think that the + * EC has jumped to its RW image even though this may not be the case. + * The pin is changed to GPIO_EC_ENTERING_RW2. + */ + gpio_set_level(GPIO_EC_ENTERING_RW, 1); + gpio_set_level(GPIO_EC_ENTERING_RW2, 1); + usleep(MSEC); + gpio_set_level(GPIO_EC_ENTERING_RW, 0); + gpio_set_level(GPIO_EC_ENTERING_RW2, 0); +} + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal, TCPC C1 reset pin is not + * connected to the EC. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board + * sets it through the charger GPIO. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + gpio_set_level(GPIO_EN_USB_A0_VBUS, !!enable); + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", enable ? "en" : "dis"); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_0; + } + } + + /* Check whether TCPC 1 pulled the shared interrupt line */ + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + if (regval) + status = PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if ((old_port != CHARGE_PORT_NONE) && (old_port != port)) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 3; + *kp_div = 14; + + *ki = 3; + *ki_div = 500; + + *kd = 4; + *kd_div = 40; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +/* Sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static struct accelgyro_saved_data_t g_bma253_data; +static struct bmi_drv_data_t g_bmi160_data; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR2_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static const mat33_fp_t lid_lis2dwl_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* Lid accel private data */ +static struct stprivate_data g_lis2dwl_data; +struct motion_sensor_t lis2dwl_lid_accel = { + + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DWL, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_lis2dwl_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DWL_ADDR1_FLAGS, + .rot_standard_ref = &lid_lis2dwl_ref, + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +static const mat33_fp_t lid_KX022_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static struct kionix_accel_data g_kx022_data; +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, + .rot_standard_ref = &lid_KX022_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +static struct icm_drv_data_t g_icm42607_data; +const mat33_fp_t based_ref_icm42607 = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; +struct motion_sensor_t icm42607_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &based_ref_icm42607, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm42607_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &based_ref_icm42607, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; + +static struct bmi_drv_data_t g_bmi220_data; +const mat33_fp_t based_ref_bmi220 = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; +struct motion_sensor_t bmi220_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI220, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi220_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &based_ref_bmi220, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t bmi220_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI220, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi220_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &based_ref_bmi220, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, +}; + +void board_init(void) +{ + int on; + uint32_t board_id; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_INT_ODL); + + /* + * If interrupt lines are already low, schedule them to be processed + * after inits are completed. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) + hook_call_deferred(&check_c0_line_data, 0); + if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) + hook_call_deferred(&check_c1_line_data, 0); + + gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); + /* Enable Base Accel interrupt */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + /* Enable gpio interrupt for pen detect */ + gpio_enable_interrupt(GPIO_PEN_DET_ODL); + + /* Turn on 5V if the system is on, otherwise turn it off */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + if (!gpio_get_level(GPIO_PEN_DET_ODL)) + gpio_set_level(GPIO_EN_PP3300_PEN, 1); + + cbi_get_board_version(&board_id); + + if (board_id > 2) { + if (get_cbi_fw_config_tablet_mode()) { + if (get_cbi_ssfc_base_sensor() == + SSFC_SENSOR_ICM42607) { + motion_sensors[BASE_ACCEL] = + icm42607_base_accel; + motion_sensors[BASE_GYRO] = icm42607_base_gyro; + CPRINTF("BASE GYRO is ICM42607"); + } else if (get_cbi_ssfc_base_sensor() == + SSFC_SENSOR_BMI220) { + motion_sensors[BASE_ACCEL] = bmi220_base_accel; + motion_sensors[BASE_GYRO] = bmi220_base_gyro; + CPRINTF("BASE GYRO is BMI220"); + } else { + CPRINTF("BASE GYRO is BMI160"); + } + + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LIS2DWL) { + motion_sensors[LID_ACCEL] = lis2dwl_lid_accel; + CPRINTF("LID_ACCEL is LIS2DWL"); + } else if (get_cbi_ssfc_lid_sensor() == + SSFC_SENSOR_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + CPRINTF("LID_ACCEL is KX022"); + } else { + CPRINTF("LID_ACCEL is BMA253"); + } + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* + * Base accel is not stuffed, don't allow + * line to float. + */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } + } else { + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_ICM42607) { + motion_sensors[BASE_ACCEL] = icm42607_base_accel; + motion_sensors[BASE_GYRO] = icm42607_base_gyro; + CPRINTF("BASE GYRO is ICM42607"); + } else if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BMI220) { + motion_sensors[BASE_ACCEL] = bmi220_base_accel; + motion_sensors[BASE_GYRO] = bmi220_base_gyro; + CPRINTF("BASE GYRO is BMI220"); + } else { + CPRINTF("BASE GYRO is BMI160"); + } + + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LIS2DWL) { + motion_sensors[LID_ACCEL] = lis2dwl_lid_accel; + CPRINTF("LID_ACCEL is LIS2DWL"); + } else if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + CPRINTF("LID_ACCEL is KX022"); + } else { + CPRINTF("LID_ACCEL is BMA253"); + } + } +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (get_cbi_ssfc_base_sensor()) { + case SSFC_SENSOR_ICM42607: + icm42607_interrupt(signal); + break; + case SSFC_SENSOR_BMI220: + bmi260_interrupt(signal); + break; + case SSFC_SENSOR_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Cpu", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} diff --git a/board/storo/board.h b/board/storo/board.h new file mode 100644 index 0000000000..930b92f95a --- /dev/null +++ b/board/storo/board.h @@ -0,0 +1,153 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Storo board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +/* EC console commands */ +#define CONFIG_CMD_TCPC_DUMP +#define CONFIG_CMD_CHARGER_DUMP + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_SMBUS_PEC + +/* BC 1.2 */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 +#define CONFIG_OCPC +#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) + +#define GPIO_USB_C1_INT_ODL GPIO_SUB_USB_C1_INT_ODL + +/* LED */ +#define CONFIG_LED_ONOFF_STATES +#define CONFIG_LED_ONOFF_STATES_BAT_LOW 10 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +/* Sensors */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCEL_LIS2DWL +#define CONFIG_ACCEL_KX022 +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_BMI220 +#define CONFIG_I2C_XFER_LARGE_TRANSFER + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +#define CONFIG_USBC_RETIMER_TUSB544 /* C1 Redriver: TUSB544 */ + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +/* Motion sensors */ +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_TEMP_SENSOR_3, /* ADC15*/ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +/* List of possible batteries */ +enum battery_type { + BATTERY_AS3GXXD3KA, + BATTERY_AS3FXXD3KA, + BATTERY_TYPE_COUNT, +}; + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/storo/build.mk b/board/storo/build.mk new file mode 100644 index 0000000000..01b890bf29 --- /dev/null +++ b/board/storo/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede + +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o +board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/storo/cbi_ssfc.c b/board/storo/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/storo/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/storo/cbi_ssfc.h b/board/storo/cbi_ssfc.h new file mode 100644 index 0000000000..bc6bc92286 --- /dev/null +++ b/board/storo/cbi_ssfc.h @@ -0,0 +1,60 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4, + SSFC_SENSOR_BMI220 = 5 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/storo/ec.tasklist b/board/storo/ec.tasklist new file mode 100644 index 0000000000..8abd36b4be --- /dev/null +++ b/board/storo/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, TRENTA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/storo/gpio.inc b/board/storo/gpio.inc new file mode 100644 index 0000000000..cb07474f52 --- /dev/null +++ b/board/storo/gpio.inc @@ -0,0 +1,141 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX */ +#endif + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */ +GPIO_INT(SUB_USB_C1_INT_ODL, PIN(E, 6), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c1_interrupt) +GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */ + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(PEN_DET_ODL, PIN(J, 1), GPIO_INT_BOTH | GPIO_PULL_UP, pen_detect_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(E, 3), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(K, 3), GPIO_OUT_LOW) + +/* Required for icelake chipset code, but implemented through other means for dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(F, 6), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(F, 7), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(A, 5), GPIO_INPUT) +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(K, 7), GPIO_OUT_LOW) +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) /* Board rev 1, NC board rev 0 */ + +/* MKBP event synchronization */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + + +/* Misc */ +GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) +GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) +GPIO(EC_ENTERING_RW2, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) +GPIO(EN_PP3300_PEN, PIN(B, 5), GPIO_OUT_LOW) +GPIO(ECH1_PACKET_MODE, PIN(H, 1), GPIO_OUT_LOW) + +/* LED */ +GPIO(LED_COLOR_AMBER, PIN(A, 1), GPIO_OUT_HIGH) +GPIO(LED_COLOR_WHITE, PIN(A, 2), GPIO_OUT_HIGH) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOA3_NC, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC3_NC, PIN(C, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC4_NC, PIN(C, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOC6_NC, PIN(C, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF0_NC, PIN(F, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF1_NC, PIN(F, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF4_NC, PIN(F, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOF5_NC, PIN(F, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH2_NC, PIN(H, 2), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ3_NC, PIN(J, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ4_NC, PIN(J, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ5_NC, PIN(J, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL0_NC, PIN(L, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOL3_NC, PIN(L, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 EEPROM */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 BATTERY */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, GPIO_SEL_1P8V) /* I2C2 - 1.8V SENSOR */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 SUB_USB_C1 */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 USB_C0 */ + +/* ADC */ +ALTERNATE(PIN_MASK(L, BIT(2)), 0, MODULE_ADC, 0) /* ADC15:TEMP_SENSOR3 */ +ALTERNATE(PIN_MASK(I, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) /* ADC0: EC_VSNS_PP3300_A, ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2 */ diff --git a/board/storo/led.c b/board/storo/led.c new file mode 100644 index 0000000000..76bfc05861 --- /dev/null +++ b/board/storo/led.c @@ -0,0 +1,108 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Storo + */ +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0_BAT_LOW] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_WHITE: + gpio_set_level(GPIO_LED_COLOR_AMBER, LED_OFF_LVL); + gpio_set_level(GPIO_LED_COLOR_WHITE, LED_ON_LVL); + break; + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_COLOR_AMBER, LED_ON_LVL); + gpio_set_level(GPIO_LED_COLOR_WHITE, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_COLOR_AMBER, LED_OFF_LVL); + gpio_set_level(GPIO_LED_COLOR_WHITE, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(EC_LED_COLOR_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} + +__override enum led_states board_led_get_state(enum led_states desired_state) +{ + /* + * Battery error LED behavior as below: + * S0: Blinking Amber LED, 1s on/ 1s off + * S3/S5: following S3/S5 behavior + * Add function to let battery error LED follow S3/S5 behavior in S3/S5. + */ + + if (desired_state == STATE_BATTERY_ERROR) { + if (chipset_in_state(CHIPSET_STATE_ON)) + return desired_state; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + return STATE_DISCHARGE_S3; + else + return STATE_DISCHARGE_S5; + } + return desired_state; +} diff --git a/board/storo/usb_pd_policy.c b/board/storo/usb_pd_policy.c new file mode 100644 index 0000000000..83c09bb99e --- /dev/null +++ b/board/storo/usb_pd_policy.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/charger/isl923x_public.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= board_get_usb_pd_port_count()) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/storo/vif_override.xml b/board/storo/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/storo/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/stryke/battery.c b/board/stryke/battery.c index 0144c049b5..7690cd420f 100644 --- a/board/stryke/battery.c +++ b/board/stryke/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/stryke/board.c b/board/stryke/board.c index afec23450c..c1701e18d7 100644 --- a/board/stryke/board.c +++ b/board/stryke/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Stryke board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "common.h" #include "cros_board_info.h" @@ -34,16 +33,16 @@ #include "system.h" #include "task.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "thermal.h" -#include "thermistor.h" #include "uart.h" #include "usb_charge.h" #include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* GPIO to enable/disable the USB Type-A port. */ const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { @@ -93,11 +92,11 @@ static void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; case GPIO_USB_C1_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); break; default: @@ -105,20 +104,21 @@ static void bc12_interrupt(enum gpio_signal signal) } } -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /******************************************************************************/ /* SPI devices */ -const struct spi_device_t spi_devices[] = { -}; +const struct spi_device_t spi_devices[] = {}; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, - [PWM_CH_FAN] = {.channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000}, + [PWM_CH_KBLIGHT] = { .channel = 3, .flags = 0, .freq = 10000 }, + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -138,22 +138,26 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, }, .drv = &ps8xxx_tcpm_drv, }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { [USB_PD_PORT_TCPC_0] = { - .usb_port = USB_PD_PORT_TCPC_0, - .driver = &anx7447_usb_mux_driver, - .hpd_update = &anx7447_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_0, + .driver = &anx7447_usb_mux_driver, + .hpd_update = &anx7447_tcpc_update_hpd_status, + }, }, [USB_PD_PORT_TCPC_1] = { - .usb_port = USB_PD_PORT_TCPC_1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, + .mux = &(const struct usb_mux) { + .usb_port = USB_PD_PORT_TCPC_1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, } }; @@ -182,22 +186,18 @@ static struct bmi_drv_data_t g_bmi160_data; static struct accelgyro_saved_data_t g_bma255_data; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* * TODO(b/124337208): P0 boards don't have this sensor mounted so the rotation * matrix can't be tested properly. This needs to be revisited after EVT to make * sure the rotaiton matrix for the lid sensor is correct. */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -278,7 +278,7 @@ unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -297,52 +297,56 @@ const struct fan_t fans[FAN_CH_COUNT] = { /******************************************************************************/ /* MFT channels. These are logically separate from pwm_channels. */ const struct mft_t mft_channels[] = { - [MFT_CH_0] = {NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN}, + [MFT_CH_0] = { NPCX_MFT_MODULE_1, TCKC_LFCLK, PWM_CH_FAN }, }; BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_1] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_2] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_1] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_2] = { "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Temp1", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Temp2", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_30k9_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, + [TEMP_SENSOR_1] = { .name = "Temp1", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Temp2", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - /* Stryke Temperature sensors */ /* * TODO(b/124316213): These setting need to be reviewed and set appropriately * for Stryke. They matter when the EC is controlling the fan as opposed to DPTF * control. */ -const static struct ec_thermal_config thermal_a = { - .temp_host = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_WARN] = 0, - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - [EC_TEMP_THRESH_HALT] = 0, - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -383,7 +387,6 @@ static void board_gpio_set_pp5000(void) } else if (board_id >= 1) { reset_gpio_flags(GPIO_EN_PP5000_A_V1, GPIO_OUT_LOW); } - } static void board_init(void) diff --git a/board/stryke/board.h b/board/stryke/board.h index 4bc1839787..165cdd53a8 100644 --- a/board/stryke/board.h +++ b/board/stryke/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ #define CONFIG_LED_COMMON #define CONFIG_LOW_POWER_IDLE -#define CONFIG_HOSTCMD_ESPI +#define CONFIG_HOST_INTERFACE_ESPI #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 @@ -26,7 +26,6 @@ /* Sensors */ /* BMI160 Base accel/gyro */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) @@ -81,7 +80,8 @@ #define CONFIG_FANS 1 #undef CONFIG_FAN_INIT_SPEED #define CONFIG_FAN_INIT_SPEED 50 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_A_RAILS +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER #define CONFIG_THERMISTOR #define CONFIG_THROTTLE_AP #define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B @@ -100,15 +100,16 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_PG_EC_RSMRST_ODL GPIO_PG_EC_RSMRST_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_PCH_SYS_PWROK +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S4_L GPIO_SLP_S4_L +#define GPIO_TEMP_SENSOR_POWER GPIO_EN_A_RAILS +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A #ifndef __ASSEMBLER__ @@ -120,8 +121,8 @@ extern enum gpio_signal gpio_en_pp5000_a; enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ ADC_CH_COUNT }; @@ -132,11 +133,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_FAN, PWM_CH_COUNT }; enum fan_channel { FAN_CH_0 = 0, @@ -150,11 +147,7 @@ enum mft_channel { MFT_CH_COUNT, }; -enum temp_sensor_id { - TEMP_SENSOR_1, - TEMP_SENSOR_2, - TEMP_SENSOR_COUNT -}; +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { diff --git a/board/stryke/build.mk b/board/stryke/build.mk index 733912454f..13153c1526 100644 --- a/board/stryke/build.mk +++ b/board/stryke/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/stryke/ec.tasklist b/board/stryke/ec.tasklist index 4a1024a091..829be2b7c8 100644 --- a/board/stryke/ec.tasklist +++ b/board/stryke/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/stryke/gpio.inc b/board/stryke/gpio.inc index 8b241b2850..f839d16f84 100644 --- a/board/stryke/gpio.inc +++ b/board/stryke/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,10 +16,10 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S4 GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(PG_EC_RSMRST_L, PIN(E, 2), GPIO_INT_BOTH, intel_x86_rsmrst_signal_interrupt) diff --git a/board/stryke/led.c b/board/stryke/led.c index b9ee4a9442..c5667edf2a 100644 --- a/board/stryke/led.c +++ b/board/stryke/led.c @@ -1,43 +1,48 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Stryke */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -76,4 +81,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/stryke/vif_override.xml b/board/stryke/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/stryke/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/sweetberry/OWNERS b/board/sweetberry/OWNERS new file mode 100644 index 0000000000..3a4b8d3c05 --- /dev/null +++ b/board/sweetberry/OWNERS @@ -0,0 +1,2 @@ +bnemec@google.com +matthewb@chromium.org diff --git a/board/sweetberry/board.c b/board/sweetberry/board.c index 66b21a81b9..b6b4460e51 100644 --- a/board/sweetberry/board.c +++ b/board/sweetberry/board.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,7 +8,6 @@ #include "dma.h" #include "ec_version.h" #include "gpio.h" -#include "gpio_list.h" #include "hooks.h" #include "i2c.h" #include "registers.h" @@ -24,18 +23,21 @@ #include "usb_power.h" #include "util.h" +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("Sweetberry"), - [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), - [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Sweetberry EC Shell"), - [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Sweetberry"), + [USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), + [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Sweetberry EC Shell"), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); @@ -59,28 +61,43 @@ struct dwc_usb usb_ctl = { /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"i2c1", I2C_PORT_0, 400, - GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"i2c2", I2C_PORT_1, 400, - GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"i2c3", I2C_PORT_2, 400, - GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"fmpi2c4", FMPI2C_PORT_3, 900, - GPIO_FMPI2C_SCL, GPIO_FMPI2C_SDA}, + { .name = "i2c1", + .port = I2C_PORT_0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "i2c2", + .port = I2C_PORT_1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "i2c3", + .port = I2C_PORT_2, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "fmpi2c4", + .port = FMPI2C_PORT_3, + .kbps = 900, + .scl = GPIO_FMPI2C_SCL, + .sda = GPIO_FMPI2C_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -int usb_i2c_board_is_enabled(void) { return 1; } +int usb_i2c_board_is_enabled(void) +{ + return 1; +} -#define GPIO_SET_HS(bank, number) \ - (STM32_GPIO_OSPEEDR(GPIO_##bank) |= (0x3 << ((number) * 2))) +#define GPIO_SET_HS(bank, number) \ + (STM32_GPIO_OSPEEDR(GPIO_##bank) |= (0x3 << ((number)*2))) void board_config_post_gpio_init(void) { /* We use MCO2 clock passthrough to provide a clock to USB HS */ gpio_config_module(MODULE_MCO, 1); /* GPIO PC9 to high speed */ - GPIO_SET_HS(C, 9); + GPIO_SET_HS(C, 9); if (usb_ctl.phy_type == USB_PHY_ULPI) gpio_set_level(GPIO_USB_MUX_SEL, 0); @@ -91,29 +108,29 @@ void board_config_post_gpio_init(void) GPIO_SET_HS(A, 11); GPIO_SET_HS(A, 12); - GPIO_SET_HS(C, 3); - GPIO_SET_HS(C, 2); - GPIO_SET_HS(C, 0); - GPIO_SET_HS(A, 5); + GPIO_SET_HS(C, 3); + GPIO_SET_HS(C, 2); + GPIO_SET_HS(C, 0); + GPIO_SET_HS(A, 5); - GPIO_SET_HS(B, 5); + GPIO_SET_HS(B, 5); GPIO_SET_HS(B, 13); GPIO_SET_HS(B, 12); - GPIO_SET_HS(B, 2); + GPIO_SET_HS(B, 2); GPIO_SET_HS(B, 10); - GPIO_SET_HS(B, 1); - GPIO_SET_HS(B, 0); - GPIO_SET_HS(A, 3); + GPIO_SET_HS(B, 1); + GPIO_SET_HS(B, 0); + GPIO_SET_HS(A, 3); /* Set I2C GPIO to HS */ - GPIO_SET_HS(B, 6); - GPIO_SET_HS(B, 7); - GPIO_SET_HS(F, 1); - GPIO_SET_HS(F, 0); - GPIO_SET_HS(A, 8); - GPIO_SET_HS(B, 4); - GPIO_SET_HS(C, 6); - GPIO_SET_HS(C, 7); + GPIO_SET_HS(B, 6); + GPIO_SET_HS(B, 7); + GPIO_SET_HS(F, 1); + GPIO_SET_HS(F, 0); + GPIO_SET_HS(A, 8); + GPIO_SET_HS(B, 4); + GPIO_SET_HS(C, 6); + GPIO_SET_HS(C, 7); } static void board_init(void) diff --git a/board/sweetberry/board.h b/board/sweetberry/board.h index 1edea99b9a..4d945f5dc4 100644 --- a/board/sweetberry/board.h +++ b/board/sweetberry/board.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -48,28 +48,28 @@ #define DEFAULT_SERIALNO "Uninitialized" /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_CONSOLE 0 -#define USB_IFACE_UPDATE 1 -#define USB_IFACE_POWER 2 -#define USB_IFACE_I2C 3 -#define USB_IFACE_COUNT 4 +#define USB_IFACE_CONSOLE 0 +#define USB_IFACE_UPDATE 1 +#define USB_IFACE_POWER 2 +#define USB_IFACE_I2C 3 +#define USB_IFACE_COUNT 4 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_CONSOLE 1 -#define USB_EP_UPDATE 2 -#define USB_EP_POWER 3 -#define USB_EP_I2C 4 -#define USB_EP_COUNT 5 +#define USB_EP_CONTROL 0 +#define USB_EP_CONSOLE 1 +#define USB_EP_UPDATE 2 +#define USB_EP_POWER 3 +#define USB_EP_I2C 4 +#define USB_EP_COUNT 5 #define CONFIG_USB_I2C #define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define I2C_PORT_0 0 -#define I2C_PORT_1 1 -#define I2C_PORT_2 2 -#define FMPI2C_PORT_3 3 -#define I2C_PORT_COUNT 4 +#define CONFIG_I2C_CONTROLLER +#define I2C_PORT_0 0 +#define I2C_PORT_1 1 +#define I2C_PORT_2 2 +#define FMPI2C_PORT_3 3 +#define I2C_PORT_COUNT 4 /* This is not actually a Chromium EC so disable some features. */ #undef CONFIG_WATCHDOG_HELP @@ -77,7 +77,6 @@ #undef CONFIG_WATCHDOG /* Optional features */ -#define CONFIG_STM_HWTIMER32 /* * Allow dangerous commands all the time, since we don't have a write protect diff --git a/board/sweetberry/build.mk b/board/sweetberry/build.mk index 6b06f2bb8f..61e4b79d47 100644 --- a/board/sweetberry/build.mk +++ b/board/sweetberry/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/sweetberry/ec.tasklist b/board/sweetberry/ec.tasklist index c1fb169118..c45a1e89a7 100644 --- a/board/sweetberry/ec.tasklist +++ b/board/sweetberry/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/sweetberry/gpio.inc b/board/sweetberry/gpio.inc index cfab7fc1f3..28b91d0dec 100644 --- a/board/sweetberry/gpio.inc +++ b/board/sweetberry/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/taeko/battery.c b/board/taeko/battery.c new file mode 100644 index 0000000000..24ce4c1bdf --- /dev/null +++ b/board/taeko/battery.c @@ -0,0 +1,159 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "common.h" +#include "util.h" +/* + * Battery info for all Taeko battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + [BATTERY_SMP_51W] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L21M4PG4", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + } + }, + .batt_info = { + .voltage_max = 8900, /* mV */ + .voltage_normal = 7720, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 330, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + [BATTERY_SUNWODA] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "L21D4PG4", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0100, + } + }, + .batt_info = { + .voltage_max = 8900, /* mV */ + .voltage_normal = 7720, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 330, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + [BATTERY_SMP_71W] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L21M4PG5", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7680, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 464, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "LGES", + .device_name = "L21L4PG5", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7680, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 512, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP_51W; + +__override bool board_battery_is_initialized(void) +{ + bool batt_initialization_state; + int batt_status; + + batt_initialization_state = + (battery_status(&batt_status) ? + false : + !!(batt_status & STATUS_INITIALIZED)); + return batt_initialization_state; +} diff --git a/board/taeko/board.c b/board/taeko/board.c new file mode 100644 index 0000000000..aaf7f215ff --- /dev/null +++ b/board/taeko/board.c @@ -0,0 +1,138 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/accelgyro_lsm6dso.h" +#include "driver/als_tcs3400.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +__override void board_cbi_init(void) +{ + config_usb_db_type(); +} + +void board_init(void) +{ + if (!ec_cfg_has_tabletmode()) { + /* applies only to clamshell devices */ + gpio_set_flags(GPIO_VOLUME_DOWN_L, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_VOLUME_UP_L, GPIO_INPUT | GPIO_PULL_DOWN); + button_disable_gpio(BUTTON_VOLUME_UP); + button_disable_gpio(BUTTON_VOLUME_DOWN); + } + if (!ec_cfg_has_keyboard_number_pad()) { + /* Disable scanning KSO13 and 14 if keypad isn't present. */ + keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); + } else { + /* Setting scan mask KSO11, KSO12, KSO13 and KSO14 */ + keyscan_config.actual_key_mask[11] = 0xfe; + keyscan_config.actual_key_mask[12] = 0xff; + keyscan_config.actual_key_mask[13] = 0xff; + keyscan_config.actual_key_mask[14] = 0xff; + } +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + if (ec_cfg_has_keyboard_backlight() == 1) { + /* GPIO_EC_KB_BL_EN_L is low active pin */ + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); + } +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + if (ec_cfg_has_keyboard_backlight() == 1) { + /* GPIO_EC_KB_BL_EN_L is low active pin */ + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); + } +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO: tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +enum battery_present battery_hw_present(void) +{ + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/taeko/board.h b/board/taeko/board.h new file mode 100644 index 0000000000..d57010a9ff --- /dev/null +++ b/board/taeko/board.h @@ -0,0 +1,261 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Taeko board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* + * Taeko boards are set up for vivaldi + */ +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_STRICT_DEBOUNCE +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* OEM requested 5% charger current margin */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +/* LED */ +#define CONFIG_LED_ONOFF_STATES + +/* Sensors */ +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +/* Button */ +#define CONFIG_BUTTONS_RUNTIME_CONFIG + +/* Change Request (b/199529373) + * GYRO sensor change from ST LSM6DSOETR3TR to ST LSM6DS3TR-C + * LSM6DSOETR3TR base accel/gyro if board id = 0 + * LSM6DS3TR-C Base accel/gyro if board id > 0 + */ +#define CONFIG_ACCELGYRO_LSM6DSO /* Base accel */ +#define CONFIG_ACCEL_LSM6DSO_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_LSM6DSM +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(LID_ACCEL)) + +/* Lid accel */ +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_ACCEL_BMA4XX +#define CONFIG_ACCEL_LIS2DWL + +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 1 + +#define CONFIG_USB_PD_FRS_PPC +#define CONFIG_USB_PD_FRS +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_NX20P3483 +#define CONFIG_USBC_NX20P348X_RCP_5VSRC_MASK_ENABLE + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* The lower the input voltage, the higher the power efficiency. */ +#define PD_PREFER_LOW_VOLTAGE + +#undef CONFIG_CMD_POWERINDEBUG + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 +#define I2C_PORT_USB_C0_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* Fan */ +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_BQ25720 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +/* 37h BIT7:2 VSYS_TH2 6.0V */ +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 60 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 +/* 30h BIT13:12 Enable PSYS 00b */ +#define CONFIG_CHARGER_BQ25710_PSYS_SENSING +/* 31h BIT3 = 1 Enable ACOC */ +#define CONFIG_CHARGER_BQ25710_EN_ACOC +/* 33h BIT15:11 ILIM2 TH 140% */ +#define CONFIG_CHARGER_BQ257X0_ILIM2_VTH_CUSTOM +#define CONFIG_CHARGER_BQ257X0_ILIM2_VTH \ + BQ257X0_PROCHOT_OPTION_0_ILIM2_VTH__1P40 +/* 34h BIT0 CONFIG_CHARGER_BQ25710_PP_ACOK */ +#define CONFIG_CHARGER_BQ25710_PP_ACOK +/* 34h BIT3 and BIT15:10 IDCHG 9728mA, step is 512mA */ +#define CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA 9728 +/* 34h BIT6 CONFIG_CHARGER_BQ25710_PP_COMP */ +#define CONFIG_CHARGER_BQ25710_PP_COMP +/* 36h UVP 5600mV */ +#define CONFIG_CHARGER_BQ25720_VSYS_UVP_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_UVP BQ25720_CHARGE_OPTION_4_VSYS_UVP__5P6 +/* 3Eh BIT15:8 VSYS_MIN 6.1V */ +#define CONFIG_CHARGER_BQ25710_VSYS_MIN_VOLTAGE_CUSTOM +#define CONFIG_CHARGER_BQ25710_VSYS_MIN_VOLTAGE_MV 6100 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_FAN, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_TEMP_SENSOR_4_CPUCHOKE, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_FAN, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_4_CPUCHOKE, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { LID_ACCEL = 0, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_PORT_COUNT }; + +enum battery_type { + BATTERY_SMP_51W, + BATTERY_SMP_71W, + BATTERY_LGC, + BATTERY_SUNWODA, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/taeko/build.mk b/board/taeko/build.mk new file mode 100644 index 0000000000..9d193faf4e --- /dev/null +++ b/board/taeko/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Taeko board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/taeko/charger.c b/board/taeko/charger.c new file mode 100644 index 0000000000..827152e115 --- /dev/null +++ b/board/taeko/charger.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/taeko/ec.tasklist b/board/taeko/ec.tasklist new file mode 100644 index 0000000000..29fd0bf4cb --- /dev/null +++ b/board/taeko/ec.tasklist @@ -0,0 +1,30 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/taeko/fans.c b/board/taeko/fans.c new file mode 100644 index 0000000000..ccfec5bc0d --- /dev/null +++ b/board/taeko/fans.c @@ -0,0 +1,88 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/194774929): need to update for real fan + * + * Prototype fan spins at about 7200 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2200, + .rpm_start = 2200, + .rpm_max = 7200, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/194774929): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/taeko/fw_config.c b/board/taeko/fw_config.c new file mode 100644 index 0000000000..e04386051d --- /dev/null +++ b/board/taeko/fw_config.c @@ -0,0 +1,102 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" +#include "gpio.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union taeko_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for Taeko if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union taeko_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_PS8815, + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Taeko FW_CONFIG access + */ +static void determine_storage(void) +{ + const bool has_nvme = fw_config.nvme_status == NVME_ENABLED; + const bool has_emmc = fw_config.emmc_status == EMMC_ENABLED; + + /* + * If both masks are enabled or disabled, read the EMMC_SKU_DET pin + * (should happen only in the factory). + */ + if (has_nvme == has_emmc) { + /* 0 = eMMC SKU, 1 = NVMe SKU */ + if (gpio_get_level(GPIO_EMMC_SKU_DET)) { + CPRINTS("CBI: Detected NVMe SKU, disabling eMMC"); + fw_config.emmc_status = EMMC_DISABLED; + fw_config.nvme_status = NVME_ENABLED; + } else { + CPRINTS("CBI: Detected eMMC SKU, disabling NVMe"); + fw_config.nvme_status = NVME_DISABLED; + fw_config.emmc_status = EMMC_ENABLED; + } + } + + cbi_set_board_info(CBI_TAG_FW_CONFIG, (uint8_t *)&fw_config, + sizeof(fw_config)); +} + +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* + * Early boards doesn't have correct FW_CONFIG, so replace + * it with a sensible default value. + */ + CPRINTS("CBI: Using board defaults for early board"); + if (ec_cfg_has_tabletmode()) { + fw_config = fw_config_defaults; + fw_config.tabletmode = TABLETMODE_ENABLED; + } else + fw_config = fw_config_defaults; + } + + determine_storage(); +} + +union taeko_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void) +{ + return fw_config.usb_db; +} + +bool ec_cfg_has_keyboard_backlight(void) +{ + return (fw_config.kb_bl == KEYBOARD_BACKLIGHT_ENABLED); +} + +bool ec_cfg_has_tabletmode(void) +{ + return (fw_config.tabletmode == TABLETMODE_ENABLED); +} + +bool ec_cfg_has_keyboard_number_pad(void) +{ + return (fw_config.kbnumpad == KEYBOARD_NUMBER_PAD); +} diff --git a/board/taeko/fw_config.h b/board/taeko/fw_config.h new file mode 100644 index 0000000000..5217a72d0a --- /dev/null +++ b/board/taeko/fw_config.h @@ -0,0 +1,101 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_TAEKO_FW_CONFIG_H_ +#define __BOARD_TAEKO_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Taeko board. + * + * Source of truth is the project/taeko/taeko/config.star configuration file. + */ + +enum ec_cfg_usb_db_type { DB_USB_ABSENT = 0, DB_USB3_PS8815 = 1 }; + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_tabletmode_type { TABLETMODE_DISABLED = 0, TABLETMODE_ENABLED = 1 }; + +enum ec_cfg_kbnumpad { + KEYBOARD_NUMBER_PAD_ABSENT = 0, + KEYBOARD_NUMBER_PAD = 1 +}; + +enum ec_cfg_nvme_status { + NVME_DISABLED = 0, + NVME_ENABLED = 1, +}; + +enum ec_cfg_emmc_status { + EMMC_DISABLED = 0, + EMMC_ENABLED = 1, +}; + +union taeko_cbi_fw_config { + struct { + enum ec_cfg_usb_db_type usb_db : 2; + uint32_t sd_db : 2; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t reserved_1 : 4; + /* b/194515356 - Fw config structure + * b/203630618 - Move tablet mode to bit14 + * bit8-9: kb_layout + * bit10-11: wifi_sar_id, + * bit12: nvme + * bit13: emmc + */ + enum ec_cfg_nvme_status nvme_status : 1; + enum ec_cfg_emmc_status emmc_status : 1; + enum ec_cfg_tabletmode_type tabletmode : 1; + enum ec_cfg_kbnumpad kbnumpad : 1; + uint32_t reserved_2 : 16; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union taeko_cbi_fw_config get_fw_config(void); + +/** + * Get the USB daughter board type from FW_CONFIG. + * + * @return the USB daughter board type. + */ +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void); + +/** + * Check if the FW_CONFIG has enabled keyboard backlight. + * + * @return true if board supports keyboard backlight, false if the board + * doesn't support it. + */ +bool ec_cfg_has_keyboard_backlight(void); + +/** + * Check if the FW_CONFIG has enabled tablet mode. + * + * @return true if board supports tablet mode, false if the board + * doesn't support it. + */ +bool ec_cfg_has_tabletmode(void); + +/** + * Check if the FW_CONFIG has enable keyboard number pad. + * + * @return true if board supports keyboard number pad, false if the + * keyboard number pad doesn't support it. + */ +bool ec_cfg_has_keyboard_number_pad(void); +#endif /* __BOARD_TAEKO_FW_CONFIG_H_ */ diff --git a/board/taeko/gpio.inc b/board/taeko/gpio.inc new file mode 100644 index 0000000000..44cb489257 --- /dev/null +++ b/board/taeko/gpio.inc @@ -0,0 +1,143 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_IMU_INT_R_L, PIN(5, 6), GPIO_SEL_1P8V | GPIO_INT_FALLING, lsm6dsm_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_ACCEL_INT_R_L, PIN(8, 1), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EMMC_SKU_DET, PIN(7, 0), GPIO_INPUT) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(B, 1)) /* KSO17/GPIOB1/CR_SIN4 */ +UNUSED(PIN(D, 4)) /* GPIOD4/CR_SIN3 */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(4, 1)) /* GPIO41/ADC4 */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ + +/* Pre-configured PSL balls: J8 K6 */ + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) + +/* LED */ +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) /* Battery - Red LED */ +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) /* Battery - Green LED */ +GPIO(LED_3_L, PIN(C, 2), GPIO_OUT_HIGH) /* Power - White LED */ diff --git a/board/taeko/i2c.c b/board/taeko/i2c.c new file mode 100644 index 0000000000..498df4dd81 --- /dev/null +++ b/board/taeko/i2c.c @@ -0,0 +1,70 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0", + .port = I2C_PORT_USB_C0_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_PPC_BC_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/taeko/keyboard.c b/board/taeko/keyboard.c new file mode 100644 index 0000000000..4a1b096668 --- /dev/null +++ b/board/taeko/keyboard.c @@ -0,0 +1,109 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 30 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config taeko_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config tarlo_kb = { + .num_top_row_keys = 11, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_MICMUTE, /* T8 */ + TK_VOL_MUTE, /* T9 */ + TK_VOL_DOWN, /* T10 */ + TK_VOL_UP, /* T11 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; + +/* + * Row Column info for Top row keys T1 - T15. + * Since tarlo keyboard top row keys have some issue when press with search + * key together. + * Needs to add row and col setting for top row. + * Change T8 row, col to (0,1) + * Change T9 row, col to (1,5) + * Change T10 row, col to (3,5) + * Change T11 row, col to (0,9) + */ +__override struct key { + uint8_t row; + uint8_t col; +} vivaldi_keys[] = { + { .row = 0, .col = 2 }, /* T1 */ + { .row = 3, .col = 2 }, /* T2 */ + { .row = 2, .col = 2 }, /* T3 */ + { .row = 1, .col = 2 }, /* T4 */ + { .row = 3, .col = 4 }, /* T5 */ + { .row = 2, .col = 4 }, /* T6 */ + { .row = 1, .col = 4 }, /* T7 */ + { .row = 0, .col = 1 }, /* T8 */ + { .row = 1, .col = 5 }, /* T9 */ + { .row = 3, .col = 5 }, /* T10 */ + { .row = 0, .col = 9 }, /* T11 */ + { .row = 2, .col = 9 }, /* T12 */ + { .row = 1, .col = 9 }, /* T13 */ + { .row = 0, .col = 4 }, /* T14 */ + { .row = 0, .col = 11 }, /* T15 */ +}; +BUILD_ASSERT(ARRAY_SIZE(vivaldi_keys) == MAX_TOP_ROW_KEYS); + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (ec_cfg_has_keyboard_number_pad()) + return &tarlo_kb; + else { + vivaldi_keys[7].row = 2; /* T8 */ + vivaldi_keys[7].col = 9; + vivaldi_keys[8].row = 1; /* T9 */ + vivaldi_keys[8].col = 9; + vivaldi_keys[9].row = 0; /* T10 */ + vivaldi_keys[9].col = 4; + return &taeko_kb; + } +} diff --git a/board/taeko/led.c b/board/taeko/led.c new file mode 100644 index 0000000000..1f8637cfe2 --- /dev/null +++ b/board/taeko/led.c @@ -0,0 +1,124 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Taeko specific PWM LED settings: there are 2 LEDs on each side of the board, + * each one can be controlled separately. The LED colors are white or amber, + * and the default behavior is tied to the charging process: both sides are + * amber while charging the battery and white when the battery is charged. + */ + +#include "common.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_power(enum ec_led_colors color) +{ + if (color == EC_LED_COLOR_WHITE) + gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); + else + /* LED_OFF and unsupported colors */ + gpio_set_level(GPIO_LED_3_L, LED_OFF_LVL); +} + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + break; + case EC_LED_COLOR_RED: + gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_GREEN: + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_battery(EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/taeko/pwm.c b/board/taeko/pwm.c new file mode 100644 index 0000000000..521043b859 --- /dev/null +++ b/board/taeko/pwm.c @@ -0,0 +1,37 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/taeko/sensors.c b/board/taeko/sensors.c new file mode 100644 index 0000000000..ccda469b87 --- /dev/null +++ b/board/taeko/sensors.c @@ -0,0 +1,408 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc_chip.h" +#include "common.h" +#include "driver/accel_bma422.h" +#include "driver/accel_bma4xx.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/accelgyro_lsm6dso.h" +#include "fw_config.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "motion_sense.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +#if 0 +#define CPRINTS(format, args...) ccprints(format, ##args) +#define CPRINTF(format, args...) ccprintf(format, ##args) +#else +#define CPRINTS(format, args...) +#define CPRINTF(format, args...) +#endif + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_FAN] = { + .name = "TEMP_FAN", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_CPUCHOKE] = { + .name = "CPU_CHOKE", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +static struct stprivate_data g_lis2dw12_data; +static struct accelgyro_saved_data_t g_bma422_data; +static struct lsm6dso_data lsm6dso_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* The matrix for new DB */ +static const mat33_fp_t lid_ref_for_new_DB = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +/* Matrix to rotate lid and base sensor into standard reference frame */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t bma422_lid_accel = { + .name = "Lid Accel - BMA", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_PRIMARY, /* 0x18 */ + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g, enough for laptop. */ + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, +}; + +struct motion_sensor_t lsm6dsm_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t lsm6dsm_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel - ST", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DW12, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_lis2dw12_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DW12_ADDR1, /* 0x19 */ + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &lsm6dso_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &lsm6dso_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void board_detect_motionsensor(void) +{ + int ret; + int val; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + + /* + * b/194765820 - Dynamic motion sensor count + * All board supports tablet mode if board id > 0 + */ + if (get_board_id() == 0 && !ec_cfg_has_tabletmode()) + return; + + /* Check lid accel chip */ + ret = i2c_read8(I2C_PORT_SENSOR, LIS2DW12_ADDR1, LIS2DW12_WHO_AM_I_REG, + &val); + if (ret == 0 && val == LIS2DW12_WHO_AM_I) { + CPRINTS("LID_ACCEL is LIS2DW12"); + return; + } + + ret = i2c_read8(I2C_PORT_SENSOR, BMA4_I2C_ADDR_PRIMARY, + BMA4_CHIP_ID_ADDR, &val); + if (ret == 0 && val == BMA422_CHIP_ID) { + CPRINTS("LID_ACCEL is BMA422"); + motion_sensors[LID_ACCEL] = bma422_lid_accel; + /* + * The driver for BMA422 doesn't have code to support + * INT1. So, it doesn't need to enable interrupt. + * Vendor recommend to configure EC gpio as high-z if + * we don't use INT1. Keep this pin as input w/o enable + * interrupt. + */ + if (get_board_id() >= 2) { + /* Need to change matrix when board ID >= 2 */ + bma422_lid_accel.rot_standard_ref = &lid_ref_for_new_DB; + } + return; + } + + /* Lid accel is not stuffed, don't allow line to float */ + gpio_disable_interrupt(GPIO_EC_ACCEL_INT_R_L); + gpio_set_flags(GPIO_EC_ACCEL_INT_R_L, GPIO_INPUT | GPIO_PULL_DOWN); + CPRINTS("No LID_ACCEL are detected"); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); + +static void baseboard_sensors_init(void) +{ + CPRINTS("baseboard_sensors_init"); + /* b/194765820 + * Dynamic motion sensor count + * All board supports tablet mode if board id > 0 + */ + if (ec_cfg_has_tabletmode()) { + /* Change Request (b/199529373) + * GYRO sensor change from ST LSM6DSOETR3TR to ST LSM6DS3TR-C + * LSM6DSOETR3TR base accel/gyro if board id = 0 + * LSM6DS3TR-C Base accel/gyro if board id > 0 + */ + if (get_board_id() > 0) { + motion_sensors[BASE_ACCEL] = lsm6dsm_base_accel; + motion_sensors[BASE_GYRO] = lsm6dsm_base_gyro; + } + + if (get_board_id() >= 2) { + /* Need to change matrix when board ID >= 2 */ + motion_sensors[LID_ACCEL].rot_standard_ref = + &lid_ref_for_new_DB; + } + + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_R_L); + } else { + CPRINTS("Clamshell"); + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + gpio_set_flags(GPIO_TABLET_MODE_L, GPIO_INPUT | GPIO_PULL_DOWN); + /* Gyro is not present, don't allow line to float */ + gpio_set_flags(GPIO_EC_IMU_INT_R_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC }, + [TEMP_SENSOR_2_FAN] = { .name = "FAN", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_FAN }, + [TEMP_SENSOR_3_CHARGER] = { .name = "CHARGER", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER }, + [TEMP_SENSOR_4_CPUCHOKE] = { .name = "CPU CHOKE", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_CPUCHOKE }, +}; + +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/201021109): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (100 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/201021109): update for Alder Lake/brya + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 100c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan = THERMAL_FAN; + +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_FAN] = THERMAL_FAN, + [TEMP_SENSOR_3_CHARGER] = THERMAL_FAN, + [TEMP_SENSOR_4_CPUCHOKE] = THERMAL_FAN, +}; + +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/taeko/usbc_config.c b/board/taeko/usbc_config.c new file mode 100644 index 0000000000..0c58ca5ff4 --- /dev/null +++ b/board/taeko/usbc_config.c @@ -0,0 +1,400 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +#if 0 +/* Debug only! */ +#define CPRINTSUSB(format, args...) cprints(CC_USBPD, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBPD, format, ##args) +#else +#define CPRINTSUSB(format, args...) +#define CPRINTFUSB(format, args...) +#endif + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_VCONN | + TCPC_FLAGS_CONTROL_FRS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM536A0 */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = NX20P3483_ADDR2_FLAGS, + .drv = &nx20p348x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ + +/* + * USB3 DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +void config_usb_db_type(void) +{ + enum ec_cfg_usb_db_type db_type = ec_cfg_usb_db_type(); + + /* + * TODO(b/194515356): implement multiple DB types + */ + CPRINTS("Configured USB DB type number is %d", db_type); +} + +static void ps8815_reset(void) +{ + int val; + + CPRINTS("%s: patching ps8815 registers", __func__); + + if (i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_FLAGS, 0x0f, + &val) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f was %02x", val); + else { + CPRINTS("delay 10ms to make sure PS8815 is waken from idle"); + msleep(10); + } + + if (i2c_write8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f set to 0x31"); + + if (i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_FLAGS, 0x0f, + &val) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f now %02x", val); +} + +/** + * b/197585292 + * It's used for early board to check if usb_db is plugged or not. + * That's used to avoid TCPC1 initialization abnormal if db isn't + * plugged into system. + */ +enum usb_db_present { + DB_USB_NOT_PRESENT = 0, + DB_USB_PRESENT = 1, +}; +static enum usb_db_present db_usb_hw_pres; + +/** + * Init hw ps8815 detection and keep it in db_usb_hw_press. + * Then, we don't need to keep query ps8815 mcu. + */ +static void board_init_ps8815_detection(void) +{ + int rv, val; + + CPRINTSUSB("%s", __func__); + + rv = i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_FLAGS, 0x00, + &val); + + db_usb_hw_pres = (rv == EC_SUCCESS) ? DB_USB_PRESENT : + DB_USB_NOT_PRESENT; + + if (db_usb_hw_pres == DB_USB_NOT_PRESENT) + CPRINTS("DB isn't plugged or something went wrong!"); +} + +/** + * @return true if ps8815_db is plugged, false if it isn't plugged. + */ +static bool board_detect_ps8815_db(void) +{ + CPRINTSUSB("%s", __func__); + + /* All dut should plug ps8815 db if board id > 0 */ + if (get_board_id() > 0) + return true; + + if (ec_cfg_usb_db_type() == DB_USB3_PS8815 && + db_usb_hw_pres == DB_USB_PRESENT) + return true; + + CPRINTSUSB("No PS8815 DB"); + return false; +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/194618663): figure out correct timing + */ + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 0); + + /* + * (b/202489681): Nx20p3483 cannot sink power after reset ec + * To avoid nx20p3483 cannot sink power after reset ec w/ AC + * only in TCPC1 port, EC shouldn't assert GPIO_USB_C1_RT_RST_R_ODL + * if no battery. + */ + if (battery_hw_present()) + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + + /* wait for chips to come up */ + msleep(PS8815_FW_INIT_DELAY_MS); + ps8815_reset(); + + /* + * board_init_ps8815_detection should be called before + * board_get_usb_pd_port_count(). usb_mux_hpd_update can check + * pd port count. + */ + board_init_ps8815_detection(); + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} + +static void board_tcpc_init(void) +{ + CPRINTSUSB("%s: board id = %d", __func__, get_board_id()); + + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C2 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + ioex_init(0); + } + + CPRINTSUSB("Enable GPIO INT"); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + if (board_detect_ps8815_db()) + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + if (board_detect_ps8815_db()) + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + if (board_detect_ps8815_db()) + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + + if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + nx20p348x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + CPRINTSUSB("%s is called by task_id:%d", __func__, task_get_current()); + + if (board_detect_ps8815_db()) + return CONFIG_USB_PD_PORT_MAX_COUNT; + + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; +} diff --git a/board/taeko/usbc_config.h b/board/taeko/usbc_config.h new file mode 100644 index 0000000000..9a35b4880f --- /dev/null +++ b/board/taeko/usbc_config.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Taeko board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void config_usb_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/taeko/vif_override.xml b/board/taeko/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/taeko/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/taniks/battery.c b/board/taniks/battery.c new file mode 100644 index 0000000000..013c27602c --- /dev/null +++ b/board/taniks/battery.c @@ -0,0 +1,132 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "common.h" +#include "util.h" +/* + * Battery info for all Taniks battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + [BATTERY_SMP_51W] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L21M4PG4", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 8900, /* mV */ + .voltage_normal = 7680, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 464, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + [BATTERY_SMP_71W] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L21M4PG5", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7680, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 464, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, + [BATTERY_LGC] = { + .fuel_gauge = { + .manuf_name = "LGES", + .device_name = "L21L4PG5", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x00, + .reg_mask = 0x0018, + .disconnect_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7680, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 512, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP_51W; + +__override bool board_battery_is_initialized(void) +{ + bool batt_initialization_state; + int batt_status; + + batt_initialization_state = + (battery_status(&batt_status) ? + false : + !!(batt_status & STATUS_INITIALIZED)); + return batt_initialization_state; +} diff --git a/board/taniks/board.c b/board/taniks/board.c new file mode 100644 index 0000000000..fdda313c9e --- /dev/null +++ b/board/taniks/board.c @@ -0,0 +1,117 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dso.h" +#include "driver/als_tcs3400.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "keyboard_raw.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "rgb_keyboard.h" +#include "switch.h" +#include "tablet_mode.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +const struct rgbkbd_init rgbkbd_init_taniks = { + .gcc = RGBKBD_MAX_GCC_LEVEL / 2, + .scale = { .r = 190, .g = 255, .b = 255 }, + .color = { .r = 255, .g = 255, .b = 255 }, +}; + +__override void board_cbi_init(void) +{ + config_usb_db_type(); +} + +void board_init(void) +{ + rgbkbd_register_init_setting(&rgbkbd_init_taniks); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +__override void board_kblight_shutdown(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); +} + +__override void board_kblight_init(void) +{ + gpio_set_level(GPIO_RGBKBD_SDB_L, 1); + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); + msleep(10); +} + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO: tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +enum battery_present battery_hw_present(void) +{ + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/taniks/board.h b/board/taniks/board.h new file mode 100644 index 0000000000..1c874d6b83 --- /dev/null +++ b/board/taniks/board.h @@ -0,0 +1,303 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Taniks board configuration */ +#define CONFIG_BUTTONS_RUNTIME_CONFIG + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* + * Taniks boards are set up for vivaldi + */ +#define CONFIG_KEYBOARD_VIVALDI +#undef CONFIG_VOLUME_BUTTONS +#define NPCX_SELECT_KSI_TO_GPIO +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_SCAN_ADC + +/* Baseboard features */ +#include "baseboard.h" + +#undef CONFIG_CMD_POWERINDEBUG +#undef CONFIG_MKBP_INPUT_DEVICES +#undef CONFIG_TABLET_MODE +#undef CONFIG_GMR_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_VOLUME_BUTTONS + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +/* OEM requested 5% charger margin */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +/* LED */ +#define CONFIG_LED_ONOFF_STATES + +/* Sensors */ +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +/* Change Request (b/211078551) + * GYRO sensor change from ST LSM6DSOETR3TR to ST LSM6DS3TR-C + * LSM6DSOETR3TR base accel/gyro if board id = 0 + * LSM6DS3TR-C Base accel/gyro if board id > 0 + */ +#define CONFIG_ACCELGYRO_LSM6DSO /* Base accel */ +#define CONFIG_ACCEL_LSM6DSO_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_LSM6DSM +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(LID_ACCEL)) + +/* Lid accel */ +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_ACCEL_BMA4XX +#define CONFIG_ACCEL_LIS2DWL + +/* Sensor console commands */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 1 + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_TCPM_PS8815 +#define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_NX20P3483 +#define CONFIG_USBC_NX20P348X_RCP_5VSRC_MASK_ENABLE + +#define CONFIG_USB_PD_FRS_PPC +#define CONFIG_USB_PD_FRS + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +/* The lower the input voltage, the higher the power efficiency. */ +#define PD_PREFER_LOW_VOLTAGE + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KSI_00 GPIO_EC_KSI_00 +#define GPIO_KSI_01 GPIO_EC_KSI_01 +#define GPIO_KSI_02 GPIO_EC_KSI_02 +#define GPIO_KSI_03 GPIO_EC_KSI_03 +#define GPIO_KSI_04 GPIO_EC_KSI_04 +#define GPIO_KSI_05 GPIO_EC_KSI_05 +#define GPIO_KSI_06 GPIO_EC_KSI_06 +#define GPIO_KSI_07 GPIO_EC_KSI_07 +#define GPIO_KSO_00 GPIO_EC_KSO_00 +#define GPIO_KSO_01 GPIO_EC_KSO_01 +#define GPIO_KSO_02 GPIO_EC_KSO_02_R +#define GPIO_KSO_03 GPIO_EC_KSO_03 +#define GPIO_KSO_04 GPIO_EC_KSO_04 +#define GPIO_KSO_05 GPIO_EC_KSO_05 +#define GPIO_KSO_06 GPIO_EC_KSO_06_R +#define GPIO_KSO_07 GPIO_EC_KSO_07_R +#define GPIO_KSO_08 GPIO_EC_KSO_08 +#define GPIO_KSO_09 GPIO_EC_KSO_09 +#define GPIO_KSO_10 GPIO_EC_KSO_10 +#define GPIO_KSO_11 GPIO_EC_KSO_11 +#define GPIO_KSO_12 GPIO_EC_KSO_12 +#define GPIO_KSO_13 GPIO_EC_KSO_13 +#define GPIO_KSO_14 GPIO_EC_KSO_14 +#define GPIO_RFR_KEY_L GPIO_EC_RFR_KEY_ODL_R +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM +#define CONFIG_KEYBOARD_BACKLIGHT + +/* I2C Bus Configuration */ +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 +#define I2C_PORT_USB_C0_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 +#define I2C_PORT_USB_C0_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 +#define I2C_PORT_KBMCU NPCX_I2C_PORT3_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_SEQ_EC_DSW_PWROK +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* Fan */ +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_BQ25720 +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_CUSTOM +/* 37h BIT7:2 VSYS_TH2 6.0V */ +#define CONFIG_CHARGER_BQ25720_VSYS_TH2_DV 60 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_BQ25710_SENSE_RESISTOR_AC 10 +/* 30h BIT13:12 Enable PSYS 00b */ +#define CONFIG_CHARGER_BQ25710_PSYS_SENSING +/* 30h BIT7 1.2V enable*/ +#define CONFIG_CHARGER_BQ25710_CMP_REF_1P2 +/* 30h BIT6 external hysteresis */ +#define CONFIG_CHARGER_BQ25710_CMP_POL_EXTERNAL +/* 31h BIT3 = 1 Enable ACOC */ +#define CONFIG_CHARGER_BQ25710_EN_ACOC +/* 33h BIT15:11 ILIM2 TH 140% */ +#define CONFIG_CHARGER_BQ257X0_ILIM2_VTH_CUSTOM +#define CONFIG_CHARGER_BQ257X0_ILIM2_VTH \ + BQ257X0_PROCHOT_OPTION_0_ILIM2_VTH__1P40 +/* 34h BIT0 CONFIG_CHARGER_BQ25710_PP_ACOK */ +#define CONFIG_CHARGER_BQ25710_PP_ACOK +/* 34h BIT3 and BIT15:10 IDCHG 9728mA, step is 512mA */ +#define CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA 9728 +/* 34h BIT6 CONFIG_CHARGER_BQ25710_PP_COMP */ +#define CONFIG_CHARGER_BQ25710_PP_COMP +/* 36h UVP 5600mV */ +#define CONFIG_CHARGER_BQ25720_VSYS_UVP_CUSTOM +#define CONFIG_CHARGER_BQ25720_VSYS_UVP BQ25720_CHARGE_OPTION_4_VSYS_UVP__5P6 +/* 3Eh BIT15:8 VSYS_MIN 6.1V */ +#define CONFIG_CHARGER_BQ25710_VSYS_MIN_VOLTAGE_CUSTOM +#define CONFIG_CHARGER_BQ25710_VSYS_MIN_VOLTAGE_MV 6100 + +/* RGB Keyboard */ +#define GPIO_RGBKBD_SDB_L GPIO_KBMCU_INT_ODL + +#define CONFIG_RGB_KEYBOARD +#define CONFIG_LED_DRIVER_AW20198 /* Awinic AW20198 on I2C */ + +#define RGB_GRID0_COL 8 +#define RGB_GRID0_ROW 6 + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_TEMP_SENSOR_4_CPUCHOKE, + ADC_KSI_00, + ADC_KSI_01, + ADC_KSI_02, + ADC_KSI_03, + ADC_KSI_04, + ADC_KSI_05, + ADC_KSI_06, + ADC_KSI_07, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_4_CPUCHOKE, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { LID_ACCEL = 0, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum ioex_port { IOEX_C0_NCT38XX = 0, IOEX_PORT_COUNT }; + +enum battery_type { + BATTERY_SMP_51W, + BATTERY_SMP_71W, + BATTERY_LGC, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/taniks/build.mk b/board/taniks/build.mk new file mode 100644 index 0000000000..7d01cfff96 --- /dev/null +++ b/board/taniks/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Taniks board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/taniks/charger.c b/board/taniks/charger.c new file mode 100644 index 0000000000..827152e115 --- /dev/null +++ b/board/taniks/charger.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/bq25710.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#ifndef CONFIG_ZEPHYR +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = BQ25710_SMBUS_ADDR1_FLAGS, + .drv = &bq25710_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); +#endif + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/taniks/ec.tasklist b/board/taniks/ec.tasklist new file mode 100644 index 0000000000..c879d3f77c --- /dev/null +++ b/board/taniks/ec.tasklist @@ -0,0 +1,31 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(RGBKBD, rgbkbd_task, NULL, BASEBOARD_RGBKBD_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/taniks/fans.c b/board/taniks/fans.c new file mode 100644 index 0000000000..ddb79803d1 --- /dev/null +++ b/board/taniks/fans.c @@ -0,0 +1,88 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TODO(b/211076077): need to update for real fan + * + * Prototype fan spins at about 7200 RPM at 100% PWM. + * Set minimum at around 30% PWM. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2200, + .rpm_start = 2200, + .rpm_max = 7200, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/211076077): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/taniks/fw_config.c b/board/taniks/fw_config.c new file mode 100644 index 0000000000..7d6323c868 --- /dev/null +++ b/board/taniks/fw_config.c @@ -0,0 +1,92 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" +#include "gpio.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union taniks_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for Taniks if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union taniks_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_PS8815, + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Taniks FW_CONFIG access + */ +static void determine_storage(void) +{ + const bool has_nvme = fw_config.nvme_status == NVME_ENABLED; + const bool has_emmc = fw_config.emmc_status == EMMC_ENABLED; + /* + * If both masks are enabled or disabled, read the EMMC_SKU_DET pin + * (should happen only in the factory). + */ + if (has_nvme == has_emmc) { + /* 0 = eMMC SKU, 1 = NVMe SKU */ + if (gpio_get_level(GPIO_EMMC_SKU_DET)) { + CPRINTS("CBI: Detected NVMe SKU, disabling eMMC"); + fw_config.emmc_status = EMMC_DISABLED; + fw_config.nvme_status = NVME_ENABLED; + } else { + CPRINTS("CBI: Detected eMMC SKU, disabling NVMe"); + fw_config.nvme_status = NVME_DISABLED; + fw_config.emmc_status = EMMC_ENABLED; + } + } + cbi_set_board_info(CBI_TAG_FW_CONFIG, (uint8_t *)&fw_config, + sizeof(fw_config)); +} + +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* TODO(b/211076082): Update CBI fw config structure + * Update correct FW_CONFIG. + */ + CPRINTS("CBI: Using board defaults for early board"); + if (ec_cfg_has_tabletmode()) { + fw_config = fw_config_defaults; + } + } + + determine_storage(); +} + +union taniks_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void) +{ + return fw_config.usb_db; +} + +bool ec_cfg_has_keyboard_backlight(void) +{ + return (fw_config.kb_bl == KEYBOARD_BACKLIGHT_ENABLED); +} + +bool ec_cfg_has_tabletmode(void) +{ + return (fw_config.tabletmode == TABLETMODE_ENABLED); +} diff --git a/board/taniks/fw_config.h b/board/taniks/fw_config.h new file mode 100644 index 0000000000..05ca552538 --- /dev/null +++ b/board/taniks/fw_config.h @@ -0,0 +1,87 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_TANIKS_FW_CONFIG_H_ +#define __BOARD_TANIKS_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Taniks board. + * + * Source of truth is the project/taniks/taniks/config.star configuration file. + */ + +enum ec_cfg_usb_db_type { DB_USB_ABSENT = 0, DB_USB3_PS8815 = 1 }; + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +enum ec_cfg_tabletmode_type { TABLETMODE_DISABLED = 0, TABLETMODE_ENABLED = 1 }; + +enum ec_cfg_nvme_status { + NVME_DISABLED = 0, + NVME_ENABLED = 1, +}; +enum ec_cfg_emmc_status { + EMMC_DISABLED = 0, + EMMC_ENABLED = 1, +}; + +union taniks_cbi_fw_config { + struct { + enum ec_cfg_usb_db_type usb_db : 2; + uint32_t sd_db : 2; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t reserved_1 : 4; + /* b/211079131 - Fw config structure + * b/211076082 - Move tablet mode to bit14 + * bit8-9: kb_layout + * bit10-11: wifi_sar_id, + * bit12: nvme + * bit13: emmc + */ + enum ec_cfg_nvme_status nvme_status : 1; + enum ec_cfg_emmc_status emmc_status : 1; + enum ec_cfg_tabletmode_type tabletmode : 1; + uint32_t reserved_2 : 17; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union taniks_cbi_fw_config get_fw_config(void); + +/** + * Get the USB daughter board type from FW_CONFIG. + * + * @return the USB daughter board type. + */ +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void); + +/** + * Check if the FW_CONFIG has enabled keyboard backlight. + * + * @return true if board supports keyboard backlight, false if the board + * doesn't support it. + */ +bool ec_cfg_has_keyboard_backlight(void); + +/** + * Check if the FW_CONFIG has enabled tablet mode. + * + * @return true if board supports tablet mode, false if the board + * doesn't support it. + */ +bool ec_cfg_has_tabletmode(void); + +#endif /* __BOARD_TANIKS_FW_CONFIG_H_ */ diff --git a/board/taniks/gpio.inc b/board/taniks/gpio.inc new file mode 100644 index 0000000000..d2c2bdffb9 --- /dev/null +++ b/board/taniks/gpio.inc @@ -0,0 +1,164 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(2, 4), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(2, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(2, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(2, 3), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) + +/* Keyboard interrupts */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_INT_RISING) + +GPIO_INT(EC_KSI_00, PIN(4, 4), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(EC_KSI_01, PIN(4, 3), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(EC_KSI_02, PIN(4, 1), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(EC_KSI_03, PIN(3, 7), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(EC_KSI_04, PIN(F, 1), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(EC_KSI_05, PIN(F, 0), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(EC_KSI_06, PIN(E, 0), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(EC_KSI_07, PIN(C, 7), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(EC_RFR_KEY_ODL_R, PIN(8, 3), GPIO_INT_BOTH, keyboard_raw_gpio_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_ACCEL_INT_R_L, PIN(8, 1), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_KBMCU_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_KBMCU_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(2, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(3, 0), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_HIGH) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(KBMCU_INT_ODL, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EMMC_SKU_DET, PIN(D, 4), GPIO_INPUT) + +/* KB Outputs */ +#define GPIO_KB_OUTPUT (GPIO_OUT_HIGH) + +GPIO(EC_KSO_00, PIN(2, 1), GPIO_KB_OUTPUT) +GPIO(EC_KSO_01, PIN(2, 0), GPIO_KB_OUTPUT) +GPIO(EC_KSO_02_R, PIN(1, 7), GPIO_KB_OUTPUT) +GPIO(EC_KSO_03, PIN(1, 6), GPIO_KB_OUTPUT) +GPIO(EC_KSO_04, PIN(1, 5), GPIO_KB_OUTPUT) +GPIO(EC_KSO_05, PIN(1, 4), GPIO_KB_OUTPUT) +GPIO(EC_KSO_06_R, PIN(9, 6), GPIO_KB_OUTPUT) +GPIO(EC_KSO_07_R, PIN(A, 0), GPIO_KB_OUTPUT) +GPIO(EC_KSO_08, PIN(1, 1), GPIO_KB_OUTPUT) +GPIO(EC_KSO_09, PIN(1, 0), GPIO_KB_OUTPUT) +GPIO(EC_KSO_10, PIN(0, 7), GPIO_KB_OUTPUT) +GPIO(EC_KSO_11, PIN(0, 6), GPIO_KB_OUTPUT) +GPIO(EC_KSO_12, PIN(0, 5), GPIO_KB_OUTPUT) +GPIO(EC_KSO_13, PIN(0, 4), GPIO_KB_OUTPUT) +GPIO(EC_KSO_14, PIN(8, 2), GPIO_KB_OUTPUT) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x24), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0 */ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(B, 1)) /* KSO17/GPIOB1/CR_SIN4 */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ +UNUSED(PIN(9, 5)) /* GPIO95/SPIP_MISO */ +UNUSED(PIN(5, 6)) /* GPIO56/CLKRUN# */ +UNUSED(PIN(9, 3)) /* GPIO93/TA1/F_DIO2 */ +UNUSED(PIN(9, 7)) /* GPIO97 */ + +/* Pre-configured PSL balls: J8 K6 */ + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ + +/* GPIO02_P2 to PU */ +/* GPIO03_P2 to PU */ +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) + +/* LED */ +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) /* Battery - Red LED */ +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) /* Battery - Green LED */ +GPIO(LED_3_L, PIN(C, 2), GPIO_OUT_HIGH) /* Power - White LED */ diff --git a/board/taniks/i2c.c b/board/taniks/i2c.c new file mode 100644 index 0000000000..28a49b0fae --- /dev/null +++ b/board/taniks/i2c.c @@ -0,0 +1,80 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0", + .port = I2C_PORT_USB_C0_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0", + .port = I2C_PORT_USB_C0_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "kbmcu", + .port = I2C_PORT_KBMCU, + .kbps = 400, + .scl = GPIO_EC_I2C_KBMCU_SCL, + .sda = GPIO_EC_I2C_KBMCU_SDA, + }, + { + /* I2C4 C1 TCPC */ + /* TODO(b/211080526): Change TCPC1's (PS8815) I2C frequency from + 400Khz to 1000Khz */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/taniks/keyboard.c b/board/taniks/keyboard.c new file mode 100644 index 0000000000..069627a168 --- /dev/null +++ b/board/taniks/keyboard.c @@ -0,0 +1,125 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "aw20198.h" +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "rgb_keyboard.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xa4, 0xff, 0xff, 0x55, 0xff, 0xff, 0xff, 0xff, /* full set */ + }, + .ksi_threshold_mv = 250, +}; + +static const struct ec_response_keybd_config taniks_kb = { + .num_top_row_keys = 11, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_MICMUTE, /* T8 */ + TK_VOL_MUTE, /* T9 */ + TK_VOL_DOWN, /* T10 */ + TK_VOL_UP, /* T11 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; + +/* + * Row Column info for Top row keys T1 - T15. + * For taniks keyboard layout(T11 - T14) and + * printing(F8 - F11) are different issue. + * Move T11 - T14 row and col setting to T8 - T11. + * Need define row col to mapping matrix layout. + * Change T8 row, col to (0,1) + * Change T9 row, col to (1,5) + * Change T10 row, col to (3,5) + * Change T11 row, col to (0,9) + */ +__override const struct key { + uint8_t row; + uint8_t col; +} vivaldi_keys[] = { + { .row = 0, .col = 2 }, /* T1 */ + { .row = 3, .col = 2 }, /* T2 */ + { .row = 2, .col = 2 }, /* T3 */ + { .row = 1, .col = 2 }, /* T4 */ + { .row = 3, .col = 4 }, /* T5 */ + { .row = 2, .col = 4 }, /* T6 */ + { .row = 1, .col = 4 }, /* T7 */ + { .row = 0, .col = 1 }, /* T8 */ + { .row = 1, .col = 5 }, /* T9 */ + { .row = 3, .col = 5 }, /* T10 */ + { .row = 0, .col = 9 }, /* T11 */ + { .row = 2, .col = 9 }, /* T12 */ + { .row = 1, .col = 9 }, /* T13 */ + { .row = 0, .col = 4 }, /* T14 */ + { .row = 0, .col = 11 }, /* T15 */ +}; +BUILD_ASSERT(ARRAY_SIZE(vivaldi_keys) == MAX_TOP_ROW_KEYS); + +static struct rgb_s grid0[RGB_GRID0_COL * RGB_GRID0_ROW]; + +struct rgbkbd rgbkbds[] = { + [0] = { + .cfg = &(const struct rgbkbd_cfg) { + .drv = &aw20198_drv, + .i2c = I2C_PORT_KBMCU, + .col_len = RGB_GRID0_COL, + .row_len = RGB_GRID0_ROW, + }, + .buf = grid0, + }, +}; +const uint8_t rgbkbd_count = ARRAY_SIZE(rgbkbds); + +const uint8_t rgbkbd_hsize = RGB_GRID0_COL; +const uint8_t rgbkbd_vsize = RGB_GRID0_ROW; + +enum ec_rgbkbd_type rgbkbd_type = EC_RGBKBD_TYPE_FOUR_ZONES_40_LEDS; + +#define LED(x, y) RGBKBD_COORD((x), (y)) +#define DELM RGBKBD_DELM + +const uint8_t rgbkbd_map[] = { + DELM, LED(0, 0), DELM, LED(1, 0), DELM, LED(2, 0), DELM, LED(3, 0), + DELM, LED(4, 0), DELM, LED(5, 0), DELM, LED(6, 0), DELM, LED(7, 0), + DELM, LED(0, 1), DELM, LED(1, 1), DELM, LED(2, 1), DELM, LED(3, 1), + DELM, LED(4, 1), DELM, LED(5, 1), DELM, LED(6, 1), DELM, LED(7, 1), + DELM, LED(0, 2), DELM, LED(1, 2), DELM, LED(2, 2), DELM, LED(3, 2), + DELM, LED(4, 2), DELM, LED(5, 2), DELM, LED(6, 2), DELM, LED(7, 2), + DELM, LED(0, 3), DELM, LED(1, 3), DELM, LED(2, 3), DELM, LED(3, 3), + DELM, LED(4, 3), DELM, LED(5, 3), DELM, LED(6, 3), DELM, LED(7, 3), + DELM, LED(0, 4), DELM, LED(1, 4), DELM, LED(2, 4), DELM, LED(3, 4), + DELM, LED(4, 4), DELM, LED(5, 4), DELM, LED(6, 4), DELM, LED(7, 4), + DELM, DELM, +}; +#undef LED +#undef DELM +const size_t rgbkbd_map_size = ARRAY_SIZE(rgbkbd_map); + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &taniks_kb; +} diff --git a/board/taniks/led.c b/board/taniks/led.c new file mode 100644 index 0000000000..b231d55909 --- /dev/null +++ b/board/taniks/led.c @@ -0,0 +1,124 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Taniks specific PWM LED settings: there are 2 LEDs on each side of the board, + * each one can be controlled separately. The LED colors are white or amber, + * and the default behavior is tied to the charging process: both sides are + * amber while charging the battery and white when the battery is charged. + */ + +#include "common.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) + +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 97; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; + +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_power(enum ec_led_colors color) +{ + if (color == EC_LED_COLOR_WHITE) + gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); + else + /* LED_OFF and unsupported colors */ + gpio_set_level(GPIO_LED_3_L, LED_OFF_LVL); +} + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + break; + case EC_LED_COLOR_RED: + gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_GREEN: + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + } else if (led_id == EC_LED_ID_POWER_LED) { + brightness_range[EC_LED_COLOR_WHITE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color_battery(EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_battery(EC_LED_COLOR_GREEN); + else + led_set_color_battery(LED_OFF); + } else if (led_id == EC_LED_ID_POWER_LED) { + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_power(EC_LED_COLOR_WHITE); + else + led_set_color_power(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/taniks/pwm.c b/board/taniks/pwm.c new file mode 100644 index 0000000000..62d6c5d8ea --- /dev/null +++ b/board/taniks/pwm.c @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/board/taniks/sensors.c b/board/taniks/sensors.c new file mode 100644 index 0000000000..54de4ffc56 --- /dev/null +++ b/board/taniks/sensors.c @@ -0,0 +1,419 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc_chip.h" +#include "common.h" +#include "driver/accel_bma422.h" +#include "driver/accel_bma4xx.h" +#include "driver/accel_lis2dw12.h" +#include "driver/accelgyro_lsm6dsm.h" +#include "driver/accelgyro_lsm6dso.h" +#include "fw_config.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "motion_sense.h" +#include "tablet_mode.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +#if 1 +#define CPRINTS(format, args...) ccprints(format, ##args) +#define CPRINTF(format, args...) ccprintf(format, ##args) +#else +#define CPRINTS(format, args...) +#define CPRINTF(format, args...) +#endif + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_CPUCHOKE] = { + .name = "CPU_CHOKE", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_KSI_00] = { + .name = "KSI_00", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_KSI_01] = { + .name = "KSI_01", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_KSI_02] = { + .name = "KSI_02", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_KSI_03] = { + .name = "KSI_03", + .input_ch = NPCX_ADC_CH5, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_KSI_04] = { + .name = "KSI_04", + .input_ch = NPCX_ADC_CH8, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_KSI_05] = { + .name = "KSI_05", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_KSI_06] = { + .name = "KSI_06", + .input_ch = NPCX_ADC_CH10, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_KSI_07] = { + .name = "KSI_07", + .input_ch = NPCX_ADC_CH11, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_accel_mutex); +static struct stprivate_data g_lis2dw12_data; +static struct accelgyro_saved_data_t g_bma422_data; +static struct lsm6dso_data lsm6dso_data; +static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; + +/* Matrix to rotate lid and base sensor into standard reference frame */ +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t bma422_lid_accel = { + .name = "Lid Accel - BMA", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA422, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma4_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma422_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA4_I2C_ADDR_PRIMARY, /* 0x18 */ + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g, enough for laptop. */ + .min_frequency = BMA4_ACCEL_MIN_FREQ, + .max_frequency = BMA4_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 12500 | ROUND_UP_FLAG, + .ec_rate = 0, + }, + }, +}; + +struct motion_sensor_t lsm6dsm_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, + MOTIONSENSE_TYPE_ACCEL), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t lsm6dsm_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSM, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dsm_drv, + .mutex = &g_base_accel_mutex, + .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSM_ODR_MIN_VAL, + .max_frequency = LSM6DSM_ODR_MAX_VAL, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel - ST", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LIS2DW12, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &lis2dw12_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_lis2dw12_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LIS2DW12_ADDR1, /* 0x19 */ + .rot_standard_ref = &lid_standard_ref, /* identity matrix */ + .default_range = 2, /* g */ + .min_frequency = LIS2DW12_ODR_MIN_VAL, + .max_frequency = LIS2DW12_ODR_MAX_VAL, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 12500 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &lsm6dso_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, /* g */ + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_LSM6DSO, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &lsm6dso_drv, + .mutex = &g_base_accel_mutex, + .drv_data = &lsm6dso_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = LSM6DSO_ADDR0_FLAGS, + .default_range = 1000 | ROUND_UP_FLAG, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = LSM6DSO_ODR_MIN_VAL, + .max_frequency = LSM6DSO_ODR_MAX_VAL, + }, + +}; + +#ifdef CONFIG_DYNAMIC_MOTION_SENSOR_COUNT +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +#else +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +#endif + +static void board_detect_motionsensor(void) +{ + int ret; + int val; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + + /* + * b/194765820 - Dynamic motion sensor count + * All board supports tablet mode if board id > 0 + */ + if (get_board_id() == 0 && !ec_cfg_has_tabletmode()) + return; + + /* Check lid accel chip */ + ret = i2c_read8(I2C_PORT_SENSOR, LIS2DW12_ADDR1, LIS2DW12_WHO_AM_I_REG, + &val); + if (ret == 0 && val == LIS2DW12_WHO_AM_I) { + CPRINTS("LID_ACCEL is LIS2DW12"); + return; + } + + ret = i2c_read8(I2C_PORT_SENSOR, BMA4_I2C_ADDR_PRIMARY, + BMA4_CHIP_ID_ADDR, &val); + if (ret == 0 && val == BMA422_CHIP_ID) { + CPRINTS("LID_ACCEL is BMA422"); + motion_sensors[LID_ACCEL] = bma422_lid_accel; + /* + * The driver for BMA422 doesn't have code to support + * INT1. So, it doesn't need to enable interrupt. + * Vendor recommend to configure EC gpio as high-z if + * we don't use INT1. Keep this pin as input w/o enable + * interrupt. + */ + return; + } + + /* Lid accel is not stuffed, don't allow line to float */ + gpio_disable_interrupt(GPIO_EC_ACCEL_INT_R_L); + gpio_set_flags(GPIO_EC_ACCEL_INT_R_L, GPIO_INPUT | GPIO_PULL_DOWN); + CPRINTS("No LID_ACCEL are detected"); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); + +static void baseboard_sensors_init(void) +{ + CPRINTS("baseboard_sensors_init"); + + CPRINTS("Clamshell"); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC }, + [TEMP_SENSOR_3_CHARGER] = { .name = "CHARGER", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER }, + [TEMP_SENSOR_4_CPUCHOKE] = { .name = "CPU CHOKE", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_CPUCHOKE }, +}; + +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/201021109): update for Alder Lake/brya + * + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (100 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/201021109): update for Alder Lake/brya + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 100c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(70), \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan = THERMAL_FAN; + +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_3_CHARGER] = THERMAL_FAN, + [TEMP_SENSOR_4_CPUCHOKE] = THERMAL_FAN, +}; + +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/taniks/usbc_config.c b/board/taniks/usbc_config.c new file mode 100644 index 0000000000..0c58ca5ff4 --- /dev/null +++ b/board/taniks/usbc_config.c @@ -0,0 +1,400 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +#if 0 +/* Debug only! */ +#define CPRINTSUSB(format, args...) cprints(CC_USBPD, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBPD, format, ##args) +#else +#define CPRINTSUSB(format, args...) +#define CPRINTFUSB(format, args...) +#endif + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V | + TCPC_FLAGS_CONTROL_VCONN | + TCPC_FLAGS_CONTROL_FRS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM536A0 */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = NX20P3483_ADDR2_FLAGS, + .drv = &nx20p348x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USBC mux configuration - Alder Lake includes internal mux */ + +/* + * USB3 DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +void config_usb_db_type(void) +{ + enum ec_cfg_usb_db_type db_type = ec_cfg_usb_db_type(); + + /* + * TODO(b/194515356): implement multiple DB types + */ + CPRINTS("Configured USB DB type number is %d", db_type); +} + +static void ps8815_reset(void) +{ + int val; + + CPRINTS("%s: patching ps8815 registers", __func__); + + if (i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_FLAGS, 0x0f, + &val) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f was %02x", val); + else { + CPRINTS("delay 10ms to make sure PS8815 is waken from idle"); + msleep(10); + } + + if (i2c_write8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f set to 0x31"); + + if (i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_FLAGS, 0x0f, + &val) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f now %02x", val); +} + +/** + * b/197585292 + * It's used for early board to check if usb_db is plugged or not. + * That's used to avoid TCPC1 initialization abnormal if db isn't + * plugged into system. + */ +enum usb_db_present { + DB_USB_NOT_PRESENT = 0, + DB_USB_PRESENT = 1, +}; +static enum usb_db_present db_usb_hw_pres; + +/** + * Init hw ps8815 detection and keep it in db_usb_hw_press. + * Then, we don't need to keep query ps8815 mcu. + */ +static void board_init_ps8815_detection(void) +{ + int rv, val; + + CPRINTSUSB("%s", __func__); + + rv = i2c_read8(I2C_PORT_USB_C1_TCPC, PS8XXX_I2C_ADDR1_FLAGS, 0x00, + &val); + + db_usb_hw_pres = (rv == EC_SUCCESS) ? DB_USB_PRESENT : + DB_USB_NOT_PRESENT; + + if (db_usb_hw_pres == DB_USB_NOT_PRESENT) + CPRINTS("DB isn't plugged or something went wrong!"); +} + +/** + * @return true if ps8815_db is plugged, false if it isn't plugged. + */ +static bool board_detect_ps8815_db(void) +{ + CPRINTSUSB("%s", __func__); + + /* All dut should plug ps8815 db if board id > 0 */ + if (get_board_id() > 0) + return true; + + if (ec_cfg_usb_db_type() == DB_USB3_PS8815 && + db_usb_hw_pres == DB_USB_PRESENT) + return true; + + CPRINTSUSB("No PS8815 DB"); + return false; +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/194618663): figure out correct timing + */ + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 0); + + /* + * (b/202489681): Nx20p3483 cannot sink power after reset ec + * To avoid nx20p3483 cannot sink power after reset ec w/ AC + * only in TCPC1 port, EC shouldn't assert GPIO_USB_C1_RT_RST_R_ODL + * if no battery. + */ + if (battery_hw_present()) + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + + gpio_set_level(GPIO_USB_C0_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + + /* wait for chips to come up */ + msleep(PS8815_FW_INIT_DELAY_MS); + ps8815_reset(); + + /* + * board_init_ps8815_detection should be called before + * board_get_usb_pd_port_count(). usb_mux_hpd_update can check + * pd port count. + */ + board_init_ps8815_detection(); + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} + +static void board_tcpc_init(void) +{ + CPRINTSUSB("%s: board id = %d", __func__, get_board_id()); + + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) { + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C2 TCPC, so they must be set up after the TCPC has + * been taken out of reset. + */ + ioex_init(0); + } + + CPRINTSUSB("Enable GPIO INT"); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + if (board_detect_ps8815_db()) + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + if (board_detect_ps8815_db()) + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + if (board_detect_ps8815_db()) + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0; + + if (gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + + if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + nx20p348x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} + +__override uint8_t board_get_usb_pd_port_count(void) +{ + CPRINTSUSB("%s is called by task_id:%d", __func__, task_get_current()); + + if (board_detect_ps8815_db()) + return CONFIG_USB_PD_PORT_MAX_COUNT; + + return CONFIG_USB_PD_PORT_MAX_COUNT - 1; +} diff --git a/board/taniks/usbc_config.h b/board/taniks/usbc_config.h new file mode 100644 index 0000000000..c9b8a8d71c --- /dev/null +++ b/board/taniks/usbc_config.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Taniks board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void config_usb_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/taniks/vif_override.xml b/board/taniks/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/taniks/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/taranza/board.c b/board/taranza/board.c new file mode 100644 index 0000000000..5cd32395a3 --- /dev/null +++ b/board/taranza/board.c @@ -0,0 +1,388 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Taranza board-specific configuration */ + +#include "adc_chip.h" +#include "board.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/tcpm/it83xx_pd.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/it5205.h" +#include "gpio.h" +#include "hooks.h" +#include "intc.h" +#include "power.h" +#include "power_button.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "tcpm/tcpci.h" +#include "temp_sensor.h" +#include "uart.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" + +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_VBUS] = { .name = "VBUS", /* 113/1113 voltage divider */ + .factor_mul = ADC_MAX_MVOLT * 1113, + .factor_div = (ADC_READ_MAX + 1) * 113, + .shift = 0, + .channel = CHIP_ADC_CH4 }, + [ADC_TEMP_SENSOR_3] = { .name = "TEMP_SENSOR3", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, + [ADC_PPVAR_PWR_IN_IMON] = { .name = "ADC_PPVAR_PWR_IN_IMON", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH15 }, + [ADC_SNS_PPVAR_PWR_IN] = { .name = "ADC_SNS_PPVAR_PWR_IN", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH16 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* TCPCs */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_EMBEDDED, + .drv = &it83xx_tcpm_drv, + }, +}; + +/* PPCs */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_EC_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* USB Muxes */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, + }, +}; + +/* USB-A ports */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, GPIO_EN_USB_A1_VBUS, GPIO_EN_USB_A2_VBUS, + GPIO_EN_USB_A3_VBUS, GPIO_EN_USB_A4_VBUS, +}; + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "SoC power", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, + [TEMP_SENSOR_3] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +void board_init(void) +{ + gpio_enable_interrupt(GPIO_BJ_ADP_PRESENT); + + /* Enable PPC interrupt */ + gpio_enable_interrupt(GPIO_USB_C0_FAULT_L); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void board_reset_pd_mcu(void) +{ + /* + * Nothing to do. TCPC C0 is internal. + */ +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Nothing to do. 5V should always be enabled while in Z1 or above. + */ +} + +void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma, + int charge_mv) +{ + int insufficient_power = + (charge_ma * charge_mv) < + (CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000); + /* TODO(b/259467280) blink LED on error */ + (void)insufficient_power; +} + +int board_vbus_source_enabled(int port) +{ + if (port != CHARGE_PORT_TYPEC0) + return 0; + + return ppc_is_sourcing_vbus(port); +} + +/* Vconn control for integrated ITE TCPC */ +void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) +{ + /* + * We ignore the cc_pin and PPC vconn because polarity and PPC vconn + * should already be set correctly in the PPC driver via the pd + * state machine. + */ +} + +/******************************************************************************/ +/* + * Since taranza has no battery, it must source all of its power from either + * USB-C or the barrel jack (preferred). Fizz operates in continuous safe + * mode (charge_manager_leave_safe_mode() will never be called), which + * modifies port selection as follows: + * + * - Dual-role / dedicated capability of the port partner is ignored. + * - Charge ceiling on PD voltage transition is ignored. + * - CHARGE_PORT_NONE will never be selected. + */ + +/* List of BJ adapters */ +enum bj_adapter { + BJ_NONE, + BJ_65W_19V, +}; + +/* Barrel-jack power adapter ratings. */ +static const struct charge_port_info bj_adapters[] = { + [BJ_NONE] = { .current = 0, .voltage = 0 }, + [BJ_65W_19V] = { .current = 3420, .voltage = 19000 }, +}; +#define BJ_ADP_RATING_DEFAULT BJ_65W_19V /* BJ power ratings default */ +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ + +/* Debounced connection state of the barrel jack */ +static int8_t bj_adp_connected = -1; +static void adp_connect_deferred(void) +{ + const struct charge_port_info *pi; + int connected = gpio_get_level(GPIO_BJ_ADP_PRESENT); + + /* Debounce */ + if (connected == bj_adp_connected) + return; + + if (connected) { + pi = &bj_adapters[BJ_ADP_RATING_DEFAULT]; + } else { + /* No barrel-jack, zero out this power supply */ + pi = &bj_adapters[BJ_NONE]; + } + /* This will result in a call to board_set_active_charge_port */ + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, pi); + bj_adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + +int board_set_active_charge_port(int port) +{ + const int active_port = charge_manager_get_active_charge_port(); + + CPRINTUSB("Requested charge port change to %d", port); + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == active_port) + return EC_SUCCESS; + + /* Don't sink from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + int bj_requested; + + if (charge_manager_get_active_charge_port() != CHARGE_PORT_NONE) + /* Change is only permitted while the system is off */ + return EC_ERROR_INVAL; + + /* + * Current setting is no charge port but the AP is on, so the + * charge manager is out of sync (probably because we're + * reinitializing after sysjump). Reject requests that aren't + * in sync with our outputs. + */ + bj_requested = port == CHARGE_PORT_BARRELJACK; + if (bj_adp_connected != bj_requested) + return EC_ERROR_INVAL; + } + + CPRINTUSB("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + ppc_vbus_sink_enable(USBC_PORT_C0, 1); + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_OD, 0); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (!gpio_get_level(GPIO_BJ_ADP_PRESENT)) + return EC_ERROR_INVAL; + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_OD, 1); + ppc_vbus_sink_enable(USBC_PORT_C0, 1); + break; + default: + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static void board_charge_manager_init(void) +{ + enum charge_port port; + + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + port = gpio_get_level(GPIO_BJ_ADP_PRESENT) ? CHARGE_PORT_BARRELJACK : + CHARGE_PORT_TYPEC0; + CPRINTUSB("Power source is p%d (%s)", port, + port == CHARGE_PORT_TYPEC0 ? "USB-C" : "BJ"); + + /* Initialize the power source supplier */ + switch (port) { + case CHARGE_PORT_TYPEC0: + typec_set_input_current_limit(port, 3000, 5000); + break; + case CHARGE_PORT_BARRELJACK: + charge_manager_update_charge( + CHARGE_SUPPLIER_DEDICATED, DEDICATED_CHARGE_PORT, + &bj_adapters[BJ_ADP_RATING_DEFAULT]); + break; + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, board_charge_manager_init, + HOOK_PRIO_INIT_CHARGE_MANAGER + 1); + +__override int extpower_is_present(void) +{ + /* + * There's no battery, so running this method implies we have power. + */ + return 1; +} + +void ppc_interrupt(enum gpio_signal signal) +{ + if (signal == GPIO_USB_C0_FAULT_L) + syv682x_interrupt(USBC_PORT_C0); +} + +/* I2C Ports */ +const struct i2c_port_t i2c_ports[] = { + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + + { .name = "hdmi2_edid", + .port = I2C_PORT_HDMI2_EDID, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI2_EDID_SCL, + .sda = GPIO_EC_I2C_HDMI2_EDID_SDA }, + + { .name = "usbc0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_SCL, + .sda = GPIO_EC_I2C_USB_C0_SDA }, + + { .name = "hdmi2_src_ddc", + .port = I2C_PORT_HDMI2_SRC_DDC, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI2_SRC_DDC_SCL, + .sda = GPIO_EC_I2C_HDMI2_SRC_DDC_SDA }, + + { .name = "hdmi1_edid", + .port = I2C_PORT_HDMI1_EDID, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI1_EDID_SCL, + .sda = GPIO_EC_I2C_HDMI1_EDID_SDA }, + + { .name = "hdmi1_src_ddc", + .port = I2C_PORT_HDMI1_SRC_DDC, + .kbps = 100, + .scl = GPIO_EC_I2C_HDMI1_SRC_DDC_SCL, + .sda = GPIO_EC_I2C_HDMI1_SRC_DDC_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" diff --git a/board/taranza/board.h b/board/taranza/board.h new file mode 100644 index 0000000000..8dc03d5a23 --- /dev/null +++ b/board/taranza/board.h @@ -0,0 +1,153 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Taranza board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Select Baseboard features */ +#define VARIANT_DEDEDE_EC_IT8320 +#include "baseboard.h" + +/* System unlocked in early development */ +#define CONFIG_SYSTEM_UNLOCKED + +#define CONFIG_CMD_CHARGER_DUMP + +/* I2C Bus Configuration */ +#define I2C_PORT_HDMI2_EDID IT83XX_I2C_CH_B +#undef I2C_PORT_USB_C0 +#define I2C_PORT_USB_C0 IT83XX_I2C_CH_C +#define I2C_PORT_HDMI2_SRC_DDC IT83XX_I2C_CH_D +#define I2C_PORT_HDMI1_EDID IT83XX_I2C_CH_E +#define I2C_PORT_HDMI1_SRC_DDC IT83XX_I2C_CH_F + +/* Power */ +#undef CONFIG_CHARGER +#undef CONFIG_CHARGER_DISCHARGE_ON_AC +#undef CONFIG_USB_PD_VBUS_MEASURE_CHARGER +#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 16000 +#define PD_MAX_VOLTAGE_MV 20000 +#undef PD_MAX_CURRENT_MA +#define PD_MAX_CURRENT_MA 3250 +#undef PD_MAX_POWER_MW +#define PD_MAX_POWER_MW 65000 +#define CONFIG_USB_PD_VBUS_DETECT_GPIO + +/* Override macro for C0 only */ +#define PORT_TO_HPD(port) (GPIO_USB_C0_DP_HPD) + +/* Power: Dedicated barreljack charger port */ +#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT +#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 +#define DEDICATED_CHARGE_PORT 1 + +/* USB Type-C */ +#undef CONFIG_USB_CHARGER +#undef CONFIG_USB_MUX_PI3USB31532 + +/* TCPC */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 + +/* PPC */ +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USBC_PPC +#define CONFIG_USBC_PPC_SYV682X + +/* USB Mux and Retimer */ +#define CONFIG_USB_MUX_IT5205 /* C0: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ + +/* USB Type A Features */ +#define CONFIG_USB_PORT_POWER_DUMB +#define USB_PORT_COUNT 5 /* Type A ports */ + +/* No battery */ +#undef CONFIG_BATTERY_CUT_OFF +#undef CONFIG_BATTERY_PRESENT_GPIO +#undef CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD +#undef CONFIG_BATTERY_REVIVE_DISCONNECT +#undef CONFIG_BATTERY_SMART + +/* Thermistors */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THERMISTOR +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* Buttons */ +#define CONFIG_DEDICATED_RECOVERY_BUTTON +#define CONFIG_DEDICATED_RECOVERY_BUTTON_2 +#define CONFIG_DEDICATED_RECOVERY_BUTTON_FLAGS BUTTON_FLAG_ACTIVE_HIGH +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_BUTTON_IGNORE_LID +#define CONFIG_POWER_BUTTON_X86 +#define CONFIG_EMULATED_SYSRQ + +/* No Keyboard */ +#undef CONFIG_KEYBOARD_COL2_INVERTED +#undef CONFIG_KEYBOARD_PROTOCOL_8042 +#undef CONFIG_CMD_KEYBOARD +#undef CONFIG_KEYBOARD_BOOT_KEYS +#undef CONFIG_KEYBOARD_RUNTIME_KEYS + +/* No backlight */ +#undef CONFIG_BACKLIGHT_LID +#undef GPIO_ENABLE_BACKLIGHT + +/* Unused features - Misc */ +#undef CONFIG_HIBERNATE +#undef CONFIG_VOLUME_BUTTONS +#undef CONFIG_LID_SWITCH +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE +#undef GPIO_TABLET_MODE_L + +/* Unused GPIOs */ +#undef GPIO_USB_C1_DP_HPD + +/* Pin renaming */ +#define GPIO_RECOVERY_L GPIO_EC_RECOVERY_BTN_OD +#define GPIO_RECOVERY_L_2 GPIO_H1_EC_RECOVERY_BTN_ODL +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_BARRELJACK, +}; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_COUNT }; + +/* ADC channels */ +enum adc_channel { + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_VBUS, /* ADC4 */ + ADC_TEMP_SENSOR_3, /* ADC13 */ + ADC_PPVAR_PWR_IN_IMON, /* ADC15 */ + ADC_SNS_PPVAR_PWR_IN, /* ADC16 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1, + TEMP_SENSOR_2, + TEMP_SENSOR_3, + TEMP_SENSOR_COUNT +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/taranza/build.mk b/board/taranza/build.mk new file mode 100644 index 0000000000..9bbf403060 --- /dev/null +++ b/board/taranza/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=it83xx +CHIP_FAMILY:=it8320 +CHIP_VARIANT:=it8320dx +BASEBOARD:=dedede +BOARD:=taranza + +board-y=board.o led.o usb_pd_policy.o diff --git a/board/taranza/ec.tasklist b/board/taranza/ec.tasklist new file mode 100644 index 0000000000..4aad682d14 --- /dev/null +++ b/board/taranza/ec.tasklist @@ -0,0 +1,16 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) diff --git a/board/taranza/gpio.inc b/board/taranza/gpio.inc new file mode 100644 index 0000000000..6ec6b94646 --- /dev/null +++ b/board/taranza/gpio.inc @@ -0,0 +1,175 @@ +/* -*- mode:c -*- + * + * Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Power State interrupts */ +GPIO_INT(SLP_S4_L, PIN(I, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(H, 3), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S0_L, PIN(E, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(D, 0), GPIO_INT_BOTH | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(K, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, + power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(G, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(D, 3), GPIO_INT_BOTH, + baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(L, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(EC_VSNS_PP3300_S5, PIN(I, 0), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(D, 7), GPIO_INT_BOTH, + baseboard_all_sys_pgood_interrupt) +GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, + espi_reset_pin_asserted_interrupt) + +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, + power_button_interrupt) +#ifdef CONFIG_LOW_POWER_IDLE +/* Used to wake up the EC from Deep Doze mode when writing to console */ +GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, + uart_deepsleep_interrupt) /* UART_DBG_TX_EC_RX + */ +#endif + +/* Other interrupts */ +GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) +/* Directly connected recovery button */ +GPIO_INT(EC_RECOVERY_BTN_OD, PIN(K, 7), GPIO_INT_BOTH, button_interrupt) +/* Recovery button input from H1 */ +GPIO_INT(H1_EC_RECOVERY_BTN_ODL, PIN(K, 4), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(BJ_ADP_PRESENT, PIN(A, 7), GPIO_INT_BOTH, adp_connect_interrupt) +GPIO_INT(USB_C0_FAULT_L, PIN(K, 0), GPIO_INT_FALLING, ppc_interrupt) + +/* Power sequence GPIOs */ +GPIO(EC_AP_PSYS, PIN(J, 2), GPIO_OUT_LOW) +GPIO(EC_AP_RTCRST, PIN(K, 2), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(B, 6), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(L, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(H, 0), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(D, 5), GPIO_ODR_HIGH) +GPIO(SYS_RST_ODL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_SYS_PWROK, PIN(F, 2), GPIO_OUT_LOW) +GPIO(PG_PP5000_U_OD, PIN(J, 0), GPIO_INPUT) +GPIO(EN_PP5000_U, PIN(K, 5), GPIO_OUT_HIGH) +GPIO(PG_PP3300_A, PIN(B, 5), GPIO_INPUT) +GPIO(EN_PP3300_A, PIN(C, 5), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(D, 6), GPIO_ODR_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(D, 4), GPIO_INPUT) +GPIO(EN_VCCIO_EXT, PIN(B, 2), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(I, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(E, 5), GPIO_ODR_LOW) +GPIO(ALL_SYS_PWRGD, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EN_PPVAR_BJ_ADP_OD, PIN(E, 3), GPIO_ODR_HIGH) +GPIO(ACK_PPVAR_BJ_ADP_ODL, PIN(A, 0), GPIO_INPUT) + +/* Required for icelake chipset code, but implemented through other means for + * dedede */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) + +/* Required for dedede baseboard but not used in taranza */ +UNIMPLEMENTED(USB_C0_INT_ODL) +UNIMPLEMENTED(EN_SLP_Z) +UNIMPLEMENTED(EC_BATTERY_PRES_ODL) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(F, 6), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(F, 7), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_EDID_SCL, PIN(E, 0), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_EDID_SDA, PIN(E, 7), GPIO_INPUT) +GPIO(EC_I2C_HDMI2_EDID_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(EC_I2C_HDMI2_EDID_SDA, PIN(C, 2), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_SRC_DDC_SCL, PIN(A, 4), GPIO_INPUT) +GPIO(EC_I2C_HDMI1_SRC_DDC_SDA, PIN(A, 5), GPIO_INPUT) +GPIO(EC_I2C_HDMI2_SRC_DDC_SCL, PIN(H, 1), GPIO_INPUT) +GPIO(EC_I2C_HDMI2_SRC_DDC_SDA, PIN(H, 2), GPIO_INPUT) + +/* USB pins */ +GPIO(EC_AP_USB_C0_HPD, PIN(L, 4), GPIO_OUT_LOW) +GPIO(EN_USB_A0_VBUS, PIN(L, 6), GPIO_OUT_LOW) +GPIO(EN_USB_A1_VBUS, PIN(C, 6), GPIO_OUT_LOW) +GPIO(EN_USB_A2_VBUS, PIN(C, 4), GPIO_OUT_LOW) +GPIO(EN_USB_A3_VBUS, PIN(J, 5), GPIO_OUT_LOW) +GPIO(EN_USB_A4_VBUS, PIN(J, 4), GPIO_OUT_LOW) +GPIO(EC_USB_C0_FRS_EN, PIN(K, 6), GPIO_OUT_LOW) +GPIO(USB_C0_SBU_MUX_FAULT, PIN(I, 7), GPIO_INPUT) + +/* MKBP event synchronization */ +/* TODO(b/257833880) Check whether this pin is needed */ +GPIO(EC_AP_MKBP_INT_L, PIN(L, 5), GPIO_ODR_HIGH) + +/* HDMI */ +GPIO(HDMI1_CEC, PIN(F, 0), GPIO_OUT_LOW) +GPIO(HDMI2_CEC_IN, PIN(J, 3), GPIO_INPUT) +GPIO(HDMI2_CEC, PIN(F, 1), GPIO_OUT_LOW) +GPIO(HDMI1_SRC_HPD, PIN(F, 3), GPIO_INPUT) +GPIO(HDMI2_SRC_HPD, PIN(KSO_L, 3), GPIO_INPUT) +GPIO(EC_HDMI1_SRC_HPD_OUT, PIN(I, 6), GPIO_OUT_LOW) +GPIO(EC_HDMI2_SRC_HPD_OUT, PIN(KSO_L, 4), GPIO_OUT_LOW) +GPIO(HDMI1_EDID_SEL, PIN(J, 1), GPIO_OUT_LOW) +GPIO(HDMI2_EDID_SEL, PIN(KSO_L, 5), GPIO_OUT_LOW) +GPIO(EDID_BTN_ODL, PIN(C, 3), GPIO_INPUT) +GPIO(EC_EN_PP5000_HDMI1, PIN(KSO_L, 6), GPIO_OUT_LOW) +GPIO(EC_EN_PP5000_HDMI2, PIN(KSO_L, 7), GPIO_OUT_LOW) + +/* Misc */ +GPIO(EC_ENTERING_RW, PIN(C, 7), GPIO_OUT_LOW) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) +GPIO(ECH1_PACKET_MODE, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EN_RS232_X, PIN(E, 6), GPIO_OUT_LOW) +GPIO(UART0_RX, PIN(B, 1), GPIO_OUT_LOW) /* UART_EC_TX_DBG_RX */ + +/* LED */ +GPIO(LED_W_ODL, PIN(A, 2), GPIO_OUT_HIGH) + +/* NC pins, enable internal pull-down to avoid floating state. */ +GPIO(GPIOG0_NC, PIN(G, 0), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG3_NC, PIN(G, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG4_NC, PIN(G, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG5_NC, PIN(G, 5), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG6_NC, PIN(G, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOG7_NC, PIN(G, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH4_NC, PIN(H, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOH6_NC, PIN(H, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOI4_NC, PIN(I, 4), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOJ6_NC, PIN(J, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOK3_NC, PIN(K, 3), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOM6_NC, PIN(M, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA1_NC, PIN(A, 1), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(GPIOA3_NC, PIN(A, 3), GPIO_INPUT | GPIO_PULL_DOWN) + +/* Alternate functions GPIO definitions */ +/* UART */ +ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), 0, MODULE_UART, 0) /* UART for debug */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), 0, MODULE_I2C, 0) /* I2C0 - EEPROM */ +ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C1 - HDMI2_EDID + */ +ALTERNATE(PIN_MASK(F, BIT(6) | BIT(7)), 0, MODULE_I2C, 0) /* I2C2 - USB_C0 */ +ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), 0, MODULE_I2C, 0) /* I2C4 - HDMI1_EDID + */ +ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), 0, MODULE_I2C, 0) /* I2C5 - + HDMI1_SRC_DDC */ +ALTERNATE(PIN_MASK(H, BIT(1) | BIT(2)), 0, MODULE_I2C, 0) /* I2C3 - + HDMI2_SRC_DDC */ + +/* ADC */ +/* ADC2: TEMP_SENSOR_1, ADC3: TEMP_SENSOR_2, ADC4: VBUS */ +ALTERNATE(PIN_MASK(I, BIT(2) | BIT(3) | BIT(4)), 0, MODULE_ADC, 0) +/* + * ADC13: TEMP_SENSOR_3 + * ADC15: ANALOG_PPVAR_PWR_IN_IMON + * ADC16: SNS_PPVAR_PWR_IN + */ +ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2) | BIT(3)), 0, MODULE_ADC, 0) diff --git a/board/taranza/led.c b/board/taranza/led.c new file mode 100644 index 0000000000..e37e36d6fa --- /dev/null +++ b/board/taranza/led.c @@ -0,0 +1,70 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Taranza specific LED settings. */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_POWER_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_GREEN, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static int led_set_color_power(enum led_color color) +{ + switch (color) { + case LED_GREEN: + gpio_set_level(GPIO_LED_W_ODL, LED_ON_LVL); + break; + case LED_OFF: + gpio_set_level(GPIO_LED_W_ODL, LED_OFF_LVL); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_GREEN] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color_power(LED_GREEN); + else + led_set_color_power(LED_OFF); + + return EC_SUCCESS; +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (!led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + return; + + if (chipset_in_state(CHIPSET_STATE_ON)) + led_set_color_power(LED_GREEN); + else + led_set_color_power(LED_OFF); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); diff --git a/board/taranza/usb_pd_policy.c b/board/taranza/usb_pd_policy.c new file mode 100644 index 0000000000..58bc80170f --- /dev/null +++ b/board/taranza/usb_pd_policy.c @@ -0,0 +1,72 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "usb_pd.h" +#include "usbc_ppc.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on */ + return gpio_get_level(GPIO_EN_PP5000_U); +} + +void pd_power_supply_reset(int port) +{ + int prev_en; + + if (port < 0 || port >= board_get_usb_pd_port_count()) + return; + + prev_en = ppc_is_sourcing_vbus(port); + + /* Disable VBUS source */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Enable VBUS source */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +__override int pd_snk_is_vbus_provided(int port) +{ + if (port != CHARGE_PORT_TYPEC0) + return 0; + + return ppc_is_vbus_present(port); +} diff --git a/board/taranza/vif_override.xml b/board/taranza/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/taranza/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/terrador/battery.c b/board/terrador/battery.c index d129ede528..caaf3d6d55 100644 --- a/board/terrador/battery.c +++ b/board/terrador/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/terrador/board.c b/board/terrador/board.c index 22a9b36eaa..a7356f53f5 100644 --- a/board/terrador/board.c +++ b/board/terrador/board.c @@ -1,23 +1,22 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "common.h" #include "accelgyro.h" +#include "button.h" #include "cbi_ec_fw_config.h" +#include "common.h" #include "driver/accel_bma2x2.h" #include "driver/accelgyro_bmi260.h" -#include "driver/bc12/pi3usb9201.h" #include "driver/als_tcs3400.h" +#include "driver/bc12/pi3usb9201.h" #include "driver/ppc/syv682x.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/sync.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tusb422.h" -#include "driver/retimer/bb_retimer.h" -#include "driver/sync.h" #include "extpower.h" #include "fan.h" #include "fan_chip.h" @@ -31,8 +30,8 @@ #include "pwm_chip.h" #include "switch.h" #include "system.h" -#include "task.h" #include "tablet_mode.h" +#include "task.h" #include "throttle_ap.h" #include "uart.h" #include "usb_mux.h" @@ -42,12 +41,13 @@ #include "usbc_ppc.h" #include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Increase from 50 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* Other values should be the same as the default configuration. */ @@ -72,7 +72,6 @@ union volteer_cbi_fw_config fw_config_defaults = { static void board_init(void) { - } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -171,17 +170,22 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); * 130 C. However, sensor is located next to DDR, so we need to use the lower * DDR temperature limit (85 C) */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; /* * Inductor limits - used for both charger and PP3300 regulator @@ -194,24 +198,29 @@ const static struct ec_thermal_config thermal_cpu = { * Inductors: limit of 125c * PCB: limit is 80c */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -235,11 +244,15 @@ void board_reset_pd_mcu(void) } /* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc0_usb4_mb_retimer = { - .usb_port = USBC_PORT_C0, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_0_MIX, - .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, +struct usb_mux_chain usbc0_usb4_mb_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_0_MIX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, }; /***************************************************************************** * USB-C MUX/Retimer dynamic configuration. @@ -248,7 +261,7 @@ static void setup_mux(void) { CPRINTS("C0 supports bb-retimer"); /* USB-C port 0 have a retimer */ - usb_muxes[USBC_PORT_C0].next_mux = &usbc0_usb4_mb_retimer; + usb_muxes[USBC_PORT_C0].next = &usbc0_usb4_mb_retimer; } __override void board_cbi_init(void) @@ -260,7 +273,6 @@ __override void board_cbi_init(void) /* Reassign USB_C0_RT_RST_ODL */ bb_controls[USBC_PORT_C0].usb_ls_en_gpio = GPIO_USB_C0_LS_EN; bb_controls[USBC_PORT_C0].retimer_rst_gpio = GPIO_USB_C0_RT_RST_ODL; - } /******************************************************************************/ @@ -290,6 +302,7 @@ void ppc_interrupt(enum gpio_signal signal) break; case GPIO_USB_C1_PPC_INT_ODL: syv682x_interrupt(USBC_PORT_C1); + break; default: break; } @@ -319,7 +332,6 @@ struct tcpc_config_t tcpc_config[] = { .addr_flags = TUSB422_I2C_ADDR_FLAGS, }, .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), }, [USBC_PORT_C1] = { .bus_type = EC_BUS_TYPE_I2C, @@ -328,7 +340,6 @@ struct tcpc_config_t tcpc_config[] = { .addr_flags = TUSB422_I2C_ADDR_FLAGS, }, .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), }, }; BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); @@ -336,23 +347,31 @@ BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); /******************************************************************************/ /* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, +struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }; -struct usb_mux usb_muxes[] = { +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }, [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_1_MIX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); @@ -412,3 +431,10 @@ int ppc_get_alert_status(int port) else return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; } + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; diff --git a/board/terrador/board.h b/board/terrador/board.h index 16c72663de..5f3e5171a8 100644 --- a/board/terrador/board.h +++ b/board/terrador/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,6 +11,40 @@ /* Baseboard features */ #include "baseboard.h" +/* Free flash space */ +#define CONFIG_USB_PD_DEBUG_LEVEL 0 +#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CMD_BATTFAKE +#undef CONFIG_CMD_HASH +#undef CONFIG_CMD_I2C_SCAN +#define CONFIG_DEBUG_ASSERT_BRIEF +#undef CONFIG_CONSOLE_HISTORY +#undef CONFIG_ACCEL_SPOOF_MODE +#undef CONFIG_USB_PD_TCPMV1_DEBUG +#undef CONFIG_CMD_SYSLOCK +#undef CONFIG_CMD_APTHROTTLE +#undef CONFIG_CMD_TIMERINFO +#undef CONFIG_CMD_MD +#undef CONFIG_CMD_I2C_SCAN +#undef CONFIG_CMD_I2C_XFER +#undef CONFIG_CMD_AP_RESET_LOG +#undef CONFIG_CMD_ADC +#undef CONFIG_CMD_CHARGE_SUPPLIER_INFO +#undef CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_CMD_IDLE_STATS +#undef CONFIG_CMD_MFALLOW +#undef CONFIG_CMD_MMAPINFO +#undef CONFIG_CMD_SLEEPMASK +#undef CONFIG_CMD_SLEEPMASK_SET +#undef CONFIG_CMD_USB_PD_CABLE +#undef CONFIG_CMD_FLASHINFO +#undef CONFIG_CMD_FLASH_WP +#undef CONFIG_CMD_GETTIME +#undef CONFIG_CMD_TEMP_SENSOR +#undef CONFIG_CMD_POWERINDEBUG +#undef CONFIG_CMD_POWER_AVG +#undef CONFIG_CMD_REGULATOR + /* Optional features */ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ @@ -21,6 +55,9 @@ #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 +/* Chipset features */ +#define CONFIG_POWER_PP5000_CONTROL + /* LED defines */ #define CONFIG_LED_PWM /* Although there are 2 LEDs, they are both controlled by the same lines. */ @@ -39,59 +76,48 @@ /* TCS3400 ALS */ #define CONFIG_ALS -#define ALS_COUNT 1 +#define ALS_COUNT 1 #define CONFIG_ALS_TCS3400 #define CONFIG_ALS_TCS3400_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) /* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL /* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 - -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ /* * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C * cables only support up to 60W. */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Enabling Thunderbolt-compatible mode */ #define CONFIG_USB_PD_TBT_COMPAT_MODE /* Enabling USB4 mode */ #define CONFIG_USB_PD_USB4 -#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x40 -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x40 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 /* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB /* USBC PPC*/ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C0/C1 */ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C0/C1 */ /* BC 1.2 */ @@ -101,8 +127,8 @@ #undef CONFIG_FANS /* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 /* * Macros for GPIO signals used in common code that don't match the @@ -110,48 +136,45 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK -#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL /* I2C Bus Configuration */ #define CONFIG_I2C -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_0_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT4_1 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_0_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT4_1 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER #ifndef __ASSEMBLER__ @@ -181,11 +204,7 @@ enum sensor_id { SENSOR_COUNT, }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; void board_reset_pd_mcu(void); diff --git a/board/terrador/build.mk b/board/terrador/build.mk index b78172d3cf..824bac888e 100644 --- a/board/terrador/build.mk +++ b/board/terrador/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/terrador/ec.tasklist b/board/terrador/ec.tasklist index 292de51cdb..c29125d517 100644 --- a/board/terrador/ec.tasklist +++ b/board/terrador/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,6 +16,7 @@ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/terrador/gpio.inc b/board/terrador/gpio.inc index b95ce51dc3..6d3c4cb720 100644 --- a/board/terrador/gpio.inc +++ b/board/terrador/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -77,6 +77,8 @@ GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) /* USB and USBC Signals */ +GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ +GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ /* * USB_C1 moved from GPIO32 to GPIO83 on boards with board ID >=1. @@ -165,3 +167,6 @@ ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = GPIO01 = H1_EC_PWR_BTN_ODL GPIO02 = EC_RST_ODL */ +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ diff --git a/board/terrador/led.c b/board/terrador/led.c index f792eb6e3f..ce2d497ea7 100644 --- a/board/terrador/led.c +++ b/board/terrador/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -18,17 +18,17 @@ const enum ec_led_id supported_led_ids[] = { }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -struct pwm_led led_color_map[] = { - /* Green, Red, Blue */ - [EC_LED_COLOR_GREEN] = { 100, 0, 0 }, - [EC_LED_COLOR_RED] = { 0, 100, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, +struct pwm_led_color_map led_color_map[] = { + /* Green, Red, Blue */ + [EC_LED_COLOR_GREEN] = { 100, 0, 0 }, + [EC_LED_COLOR_RED] = { 0, 100, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, /* The green LED seems to be brighter than the others, so turn down * green from its natural level for these secondary colors. */ - [EC_LED_COLOR_YELLOW] = { 70, 100, 0 }, - [EC_LED_COLOR_WHITE] = { 70, 100, 100 }, - [EC_LED_COLOR_AMBER] = { 20, 100, 0 }, + [EC_LED_COLOR_YELLOW] = { 70, 100, 0 }, + [EC_LED_COLOR_WHITE] = { 70, 100, 100 }, + [EC_LED_COLOR_AMBER] = { 20, 100, 0 }, }; struct pwm_led pwm_leds[] = { diff --git a/board/terrador/sensors.c b/board/terrador/sensors.c index 9e34812131..086f323b2e 100644 --- a/board/terrador/sensors.c +++ b/board/terrador/sensors.c @@ -1,21 +1,22 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer family-specific sensor configuration */ -#include "common.h" #include "accelgyro.h" +#include "common.h" #include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi_common.h" #include "driver/accelgyro_bmi260.h" +#include "driver/accelgyro_bmi_common.h" #include "driver/als_tcs3400.h" #include "driver/sync.h" -#include "keyboard_scan.h" +#include "gpio.h" #include "hooks.h" #include "i2c.h" -#include "task.h" +#include "keyboard_scan.h" #include "tablet_mode.h" +#include "task.h" #include "util.h" /******************************************************************************/ @@ -84,17 +85,13 @@ static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { }; /* Rotation matrix for the lid accelerometer */ -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -224,22 +221,3 @@ static void baseboard_sensors_init(void) gpio_enable_interrupt(GPIO_EC_IMU_INT_L); } DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); - -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); - - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif diff --git a/board/terrador/vif_override.xml b/board/terrador/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/terrador/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/tglrvp_ish/board.c b/board/tglrvp_ish/board.c index a0584410b3..5a8cbb45a9 100644 --- a/board/tglrvp_ish/board.c +++ b/board/tglrvp_ish/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,15 +15,17 @@ #include "power.h" #include "task.h" -#include "gpio_list.h" /* has to be included last */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /* I2C port map */ +#ifdef BOARD_ADL_ISH_LITE +const struct i2c_port_t i2c_ports[] = {}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +#elif defined(BOARD_TGLRVP_ISH) const struct i2c_port_t i2c_ports[] = { - { - .name = "sensor", - .port = I2C_PORT_SENSOR, - .kbps = 1000 - }, + { .name = "sensor", .port = I2C_PORT_SENSOR, .kbps = 1000 }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -60,6 +62,7 @@ struct motion_sensor_t motion_sensors[] = { }, }; const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +#endif /* BOARD_TGLRVP_ISH */ int chipset_in_state(int state_mask) { diff --git a/board/tglrvp_ish/board.h b/board/tglrvp_ish/board.h index a9a3d4d544..e285014e5e 100644 --- a/board/tglrvp_ish/board.h +++ b/board/tglrvp_ish/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,12 +8,6 @@ #ifndef __CROS_EC_BOARD_H #define __CROS_EC_BOARD_H -/* - * Allow dangerous commands. - * TODO: Don't use this on production systems. - */ -#define CONFIG_SYSTEM_UNLOCKED - /* * By default, enable all console messages except HC, ACPI and event * The sensor stack is generating a lot of activity. @@ -22,29 +16,32 @@ #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* ISH specific */ -#undef CONFIG_DEBUG_ASSERT +#undef CONFIG_DEBUG_ASSERT #define CONFIG_CLOCK_CRYSTAL #define CONFIG_ISH_UART_0 + /* EC */ -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER - -#define CONFIG_ACCELGYRO_LSM6DSM /* For LSM6DS3 */ -#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(BASE_ACCEL) +#define CONFIG_I2C_CONTROLLER /* Host command over HECI */ -#define CONFIG_HOSTCMD_HECI +#define CONFIG_HOST_INTERFACE_HECI + +#ifdef BOARD_TGLRVP_ISH +#define CONFIG_ACCELGYRO_LSM6DSM /* For LSM6DS3 */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(BASE_ACCEL) /* I2C ports */ #define I2C_PORT_SENSOR ISH_I2C1 -#define CONFIG_CMD_I2C_XFER /* EC Console Commands */ #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_CMD_TIMERINFO +#define CONFIG_CMD_I2C_XFER +#endif /* BOARD_TGLRVP_ISH */ /* Undefined features */ #undef CONFIG_CMD_HASH @@ -55,7 +52,7 @@ #undef CONFIG_CMD_SHMEM #undef CONFIG_EXTPOWER #undef CONFIG_KEYBOARD_KSO_BASE -#undef CONFIG_FLASH +#undef CONFIG_FLASH_CROS #undef CONFIG_FMAP #undef CONFIG_LID_SWITCH #undef CONFIG_SWITCH @@ -81,9 +78,12 @@ #define CONFIG_ISH_IPAPG -#define CONFIG_ISH_D0I2_MIN_USEC (15*MSEC) -#define CONFIG_ISH_D0I3_MIN_USEC (50*MSEC) - +#define CONFIG_ISH_D0I2_MIN_USEC (15 * MSEC) +#ifdef BOARD_ADL_ISH_LITE +#define CONFIG_ISH_D0I3_MIN_USEC (3000 * MSEC) +#else +#define CONFIG_ISH_D0I3_MIN_USEC (50 * MSEC) +#endif #define CONFIG_ISH_NEW_PM #ifndef __ASSEMBLER__ @@ -92,10 +92,7 @@ #include "registers.h" /* Motion sensors */ -enum sensor_id { - BASE_ACCEL, - SENSOR_COUNT -}; +enum sensor_id { BASE_ACCEL, SENSOR_COUNT }; #endif /* !__ASSEMBLER__ */ diff --git a/board/tglrvp_ish/build.mk b/board/tglrvp_ish/build.mk index 74ec3c865f..4a84a1f475 100644 --- a/board/tglrvp_ish/build.mk +++ b/board/tglrvp_ish/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/tglrvp_ish/ec.tasklist b/board/tglrvp_ish/ec.tasklist index a4db486e9a..aa98f37479 100644 --- a/board/tglrvp_ish/ec.tasklist +++ b/board/tglrvp_ish/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,6 +7,14 @@ * See CONFIG_TASK_LIST in config.h for details. */ +#ifdef BOARD_ADL_ISH_LITE +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HUGE_TASK_STACK_SIZE, 0) \ + TASK_NOTEST(CHIPSET, board_idle_task, NULL, IDLE_TASK_STACK_SIZE, 0) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE, 0) \ + TASK_ALWAYS(HECI_RX, heci_rx_task, NULL, HUGE_TASK_STACK_SIZE, 0) \ + TASK_ALWAYS(IPC_MNG, ipc_mng_task, NULL, LARGER_TASK_STACK_SIZE, 0) +#else #define CONFIG_TASK_LIST \ TASK_ALWAYS(HOOKS, hook_task, NULL, HUGE_TASK_STACK_SIZE, 0) \ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, LARGER_TASK_STACK_SIZE, 0) \ @@ -15,3 +23,4 @@ TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE, 0) \ TASK_ALWAYS(HECI_RX, heci_rx_task, NULL, HUGE_TASK_STACK_SIZE, 0) \ TASK_ALWAYS(IPC_MNG, ipc_mng_task, NULL, LARGER_TASK_STACK_SIZE, 0) +#endif diff --git a/board/tglrvp_ish/gpio.inc b/board/tglrvp_ish/gpio.inc index 286309e388..8b25af63cb 100644 --- a/board/tglrvp_ish/gpio.inc +++ b/board/tglrvp_ish/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/tglrvpu_ite/board.c b/board/tglrvpu_ite/board.c deleted file mode 100644 index 5698761c6a..0000000000 --- a/board/tglrvpu_ite/board.c +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel TGL-U-RVP-ITE board-specific configuration */ - -#include "bb_retimer.h" -#include "button.h" -#include "charger.h" -#include "driver/charger/isl9241.h" -#include "extpower.h" -#include "i2c.h" -#include "icelake.h" -#include "intc.h" -#include "lid_switch.h" -#include "power.h" -#include "power_button.h" -#include "switch.h" -#include "system.h" -#include "tablet_mode.h" -#include "uart.h" - -#include "gpio_list.h" - -#define CPRINTS(format, args...) cprints(CC_COMMAND, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_COMMAND, format, ## args) - -/* Mutex for shared NVM access */ -static struct mutex bb_nvm_mutex; - -/* TCPC gpios */ -const struct tcpc_gpio_config_t tcpc_gpios[] = { - [TYPE_C_PORT_0] = { - .vbus = { - .pin = GPIO_USB_C0_VBUS_INT, - .pin_pol = 1, - }, - .src = { - .pin = GPIO_USB_C0_SRC_EN, - .pin_pol = 1, - }, - .snk = { - .pin = GPIO_USB_C0_SNK_EN_L, - .pin_pol = 0, - }, - .vconn = { - .cc1_pin = GPIO_USB_C0_CC1_VCONN_EN, - .cc2_pin = GPIO_USB_C0_CC2_VCONN_EN, - .pin_pol = 1, - }, - .src_ilim = { - .pin = GPIO_USB_C0_SRC_HI_ILIM, - .pin_pol = 1, - }, - }, - [TYPE_C_PORT_1] = { - .vbus = { - .pin = GPIO_USB_C1_VBUS_INT, - .pin_pol = 1, - }, - .src = { - .pin = GPIO_USB_C1_SRC_EN, - .pin_pol = 1, - }, - .snk = { - .pin = GPIO_USB_C1_SNK_EN_L, - .pin_pol = 0, - }, - .vconn = { - .cc1_pin = GPIO_USB_C1_CC1_VCONN_EN, - .cc2_pin = GPIO_USB_C1_CC2_VCONN_EN, - .pin_pol = 1, - }, - .src_ilim = { - .pin = GPIO_USB_C1_SRC_HI_ILIM, - .pin_pol = 1, - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_gpios) == CONFIG_USB_PD_PORT_MAX_COUNT); - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - /* Flash EC */ - [I2C_CHAN_FLASH] = { - .name = "chan-A", - .port = IT83XX_I2C_CH_A, - .kbps = 100, - .scl = GPIO_I2C_A_SCL, - .sda = GPIO_I2C_A_SDA, - }, - /* - * Port-80 Display, Charger, Battery, IO-expanders, EEPROM, - * IMVP9, AUX-rail, power-monitor. - */ - [I2C_CHAN_BATT_CHG] = { - .name = "batt_chg", - .port = IT83XX_I2C_CH_B, - .kbps = 100, - .scl = GPIO_I2C_B_SCL, - .sda = GPIO_I2C_B_SDA, - }, - /* Retimers, PDs */ - [I2C_CHAN_RETIMER] = { - .name = "retimer", - .port = IT83XX_I2C_CH_E, - .kbps = 100, - .scl = GPIO_I2C_E_SCL, - .sda = GPIO_I2C_E_SDA, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(i2c_ports) == I2C_CHAN_COUNT); -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/* Charger Chips */ -const struct charger_config_t chg_chips[] = { - { - .i2c_port = I2C_PORT_CHARGER, - .i2c_addr_flags = ISL9241_ADDR_FLAGS, - .drv = &isl9241_drv, - }, -}; - -/******************************************************************************/ -/* PWROK signal configuration */ -/* - * On TGLRVP the ALL_SYS_PWRGD, VCCST_PWRGD, PCH_PWROK, and SYS_PWROK - * signals are handled by the board. No EC control needed. - */ -const struct intel_x86_pwrok_signal pwrok_signal_assert_list[] = {}; -const int pwrok_signal_assert_count = ARRAY_SIZE(pwrok_signal_assert_list); - -const struct intel_x86_pwrok_signal pwrok_signal_deassert_list[] = {}; -const int pwrok_signal_deassert_count = ARRAY_SIZE(pwrok_signal_assert_list); - -/* - * Returns board information (board id[7:0] and Fab id[15:8]) on success - * -1 on error. - */ -int board_get_version(void) -{ - int port0, port1; - int fab_id, board_id, bom_id; - - if (ioexpander_read_intelrvp_version(&port0, &port1)) - return -1; - /* - * Port0: bit 0 - BOM ID(2) - * bit 2:1 - FAB ID(1:0) + 1 - * Port1: bit 7:6 - BOM ID(1:0) - * bit 5:0 - BOARD ID(5:0) - */ - bom_id = ((port1 & 0xC0) >> 6) | ((port0 & 0x01) << 2); - fab_id = ((port0 & 0x06) >> 1) + 1; - board_id = port1 & 0x3F; - - CPRINTS("BID:0x%x, FID:0x%x, BOM:0x%x", board_id, fab_id, bom_id); - - return board_id | (fab_id << 8); -} - -__override void bb_retimer_power_handle(const struct usb_mux *me, int on_off) -{ - const struct bb_usb_control *control = &bb_controls[me->usb_port]; - - /* - * LSx based F/W updating is a POR, however to avoid the rework on - * RVP retain the FORCE_PWR GPIO with EC. - */ - enum gpio_signal force_power_gpio = me->usb_port ? - GPIO_USB_C1_RETIMER_FORCE_PWR : GPIO_USB_C0_RETIMER_FORCE_PWR; - - /* handle retimer's power domain */ - if (on_off) { - /* - * BB retimer NVM can be shared between multiple ports, hence - * lock enabling the retimer until the current retimer request - * is complete. - */ - mutex_lock(&bb_nvm_mutex); - - gpio_set_level(control->usb_ls_en_gpio, 1); - /* - * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. - * For boards that don't provide a load switch control, the - * retimer_init() function ensures power is up before calling - * this function. - */ - msleep(1); - gpio_set_level(control->retimer_rst_gpio, 1); - msleep(10); - gpio_set_level(force_power_gpio, 1); - - /* Allow 20ms time for the retimer to be initialized. */ - msleep(20); - - mutex_unlock(&bb_nvm_mutex); - } else { - gpio_set_level(force_power_gpio, 0); - msleep(1); - gpio_set_level(control->retimer_rst_gpio, 0); - msleep(1); - gpio_set_level(control->usb_ls_en_gpio, 0); - } -} diff --git a/board/tglrvpu_ite/board.h b/board/tglrvpu_ite/board.h deleted file mode 100644 index 222295c7cd..0000000000 --- a/board/tglrvpu_ite/board.h +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel TGL-U-RVP-ITE board-specific configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* USB MUX */ -#define CONFIG_USB_MUX_VIRTUAL - -#define CONFIG_USBC_VCONN - -/* FAN configs */ -#define CONFIG_FANS 1 -#define BOARD_FAN_MIN_RPM 3000 -#define BOARD_FAN_MAX_RPM 10000 - -/* Temperature sensor */ -#define CONFIG_TEMP_SENSOR - -/* Support early firmware selection */ -#define CONFIG_VBOOT_EFS2 -#define GPIO_PACKET_MODE_EN GPIO_ME_G3_TO_ME_EC - -#include "baseboard.h" - -#define CONFIG_CHIPSET_TIGERLAKE -#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD -#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK -#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_ALL_SYS_PWRGD - -/* Charger */ -#define CONFIG_CHARGER_ISL9241 - -/* DC Jack charge ports */ -#undef CONFIG_DEDICATED_CHARGE_PORT_COUNT -#define CONFIG_DEDICATED_CHARGE_PORT_COUNT 1 - -/* USB ports */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define DEDICATED_CHARGE_PORT 2 - -/* USB-C port's USB2 & USB3 port numbers */ -#if defined(BOARD_TGLRVPU_ITE) || defined(BOARD_TGLRVPU_ITE_TCPMV1) - #define TYPE_C_PORT_0_USB2_NUM 6 - #define TYPE_C_PORT_1_USB2_NUM 7 - - #define TYPE_C_PORT_0_USB3_NUM 3 - #define TYPE_C_PORT_1_USB3_NUM 4 -#else /* BOARD_TGLRVPY_ITE */ - #define TYPE_C_PORT_0_USB2_NUM 6 - #define TYPE_C_PORT_1_USB2_NUM 5 - - #define TYPE_C_PORT_0_USB3_NUM 3 - #define TYPE_C_PORT_1_USB3_NUM 2 -#endif /* BOARD_TGLRVPU_ITE */ - - -/* Config BB retimer */ -#define CONFIG_USBC_RETIMER_INTEL_BB - -/* Thermal configs */ - -/* I2C ports */ -#define CONFIG_IT83XX_SMCLK2_ON_GPC7 - -#define I2C_PORT_CHARGER IT83XX_I2C_CH_B -#define I2C_PORT_BATTERY IT83XX_I2C_CH_B -#define I2C_PORT_PCA9555_BOARD_ID_GPIO IT83XX_I2C_CH_B -#define I2C_PORT_PORT80 IT83XX_I2C_CH_B -#define I2C_PORT0_BB_RETIMER IT83XX_I2C_CH_E -#define I2C_PORT1_BB_RETIMER IT83XX_I2C_CH_E - -#define I2C_ADDR_PCA9555_BOARD_ID_GPIO 0x22 -#define PORT80_I2C_ADDR MAX695X_I2C_ADDR1_FLAGS -#if defined(BOARD_TGLRVPU_ITE) || defined(BOARD_TGLRVPU_ITE_TCPMV1) - #define I2C_PORT0_BB_RETIMER_ADDR 0x42 - #define I2C_PORT1_BB_RETIMER_ADDR 0x43 -#else /* BOARD_TGLRVPY_ITE */ - #define I2C_PORT0_BB_RETIMER_ADDR 0x42 - #define I2C_PORT1_BB_RETIMER_ADDR 0x41 -#endif /* BOARD_TGLRVPU_ITE */ - -/* Enabling SOP* communication */ -#define CONFIG_USB_PD_DECODE_SOP - -/* Enabling Thunderbolt-compatible mode */ -#define CONFIG_USB_PD_TBT_COMPAT_MODE - -/* Enabling USB4 mode */ -#define CONFIG_USB_PD_USB4 - -#ifndef __ASSEMBLER__ - -enum tglrvp_charge_ports { - TYPE_C_PORT_0, - TYPE_C_PORT_1, -}; - -enum tglrvp_i2c_channel { - I2C_CHAN_FLASH, - I2C_CHAN_BATT_CHG, - I2C_CHAN_RETIMER, - I2C_CHAN_COUNT, -}; - -/* Define max power */ -#define PD_MAX_POWER_MW 60000 - -int board_get_version(void); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/tglrvpu_ite/build.mk b/board/tglrvpu_ite/build.mk deleted file mode 100644 index 57c49d3569..0000000000 --- a/board/tglrvpu_ite/build.mk +++ /dev/null @@ -1,15 +0,0 @@ -# -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Intel TGL-U-RVP-ITE board-specific configuration -# - -#it8320 -CHIP:=it83xx -CHIP_FAMILY:=it8320 -CHIP_VARIANT:=it8320dx -BASEBOARD:=intelrvp - -board-y=board.o diff --git a/board/tglrvpu_ite/ec.tasklist b/board/tglrvpu_ite/ec.tasklist deleted file mode 100644 index 4e65a446e4..0000000000 --- a/board/tglrvpu_ite/ec.tasklist +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * Intel TGL-U-RVP-ITE board-specific configuration. - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/tglrvpu_ite/gpio.inc b/board/tglrvpu_ite/gpio.inc deleted file mode 100644 index e0bce1ddd8..0000000000 --- a/board/tglrvpu_ite/gpio.inc +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Intel TGL-U-RVP-ITE board-specific configuration */ - -/* - * Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. - */ - -/* Power sequencing interrupts */ -GPIO_INT(PG_EC_DSW_PWROK, PIN(C, 0), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(SLP_SUS_L, PIN(C, 3), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(ALL_SYS_PWRGD, PIN(F, 0), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(RSMRST_L_PGOOD, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PCH_SLP_S0_L, PIN(G, 6), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -GPIO_INT(PCH_SLP_S3_L, PIN(F, 2), GPIO_INT_BOTH, power_signal_interrupt) -#endif -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S4 -GPIO_INT(PCH_SLP_S4_L, PIN(F, 3), GPIO_INT_BOTH, power_signal_interrupt) -#endif - -/* Button interrupts */ -GPIO_INT(VOLUME_UP_L, PIN(D, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(VOLUME_DOWN_L, PIN(D, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) -GPIO_INT(POWER_BUTTON_L,PIN(E, 4), GPIO_INT_BOTH, power_button_interrupt) - -GPIO_INT(AC_PRESENT, PIN(A, 7), GPIO_INT_BOTH, extpower_interrupt) - -GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_FALLING, uart_deepsleep_interrupt) /* UART1 RX input */ - -GPIO_INT(WP_L, PIN(I, 4), GPIO_INT_BOTH, switch_interrupt) /* EC_WP_ODL */ - -#ifdef CONFIG_HOSTCMD_ESPI -/* enable 1.8v input of EC's espi_reset pin, and then this pin takes effect. */ -GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INT_FALLING | GPIO_SEL_1P8V, espi_reset_pin_asserted_interrupt) /* eSPI_reset# */ -#endif - -GPIO_INT(TABLET_MODE_L, PIN(K, 1), GPIO_INT_BOTH, gmr_tablet_switch_isr) - -/* DC Jack presence coming from +VADP_OUT */ -GPIO_INT(DC_JACK_PRESENT, PIN(J, 2), GPIO_INT_BOTH, board_dc_jack_interrupt) - -/* Type-C interrupts */ -#if defined(BOARD_TGLRVPU_ITE) || defined(BOARD_TGLRVPU_ITE_TCPMV1) -GPIO_INT(USB_C0_VBUS_INT, PIN(L, 5), GPIO_INT_BOTH, tcpc_alert_event) -GPIO_INT(USB_C1_VBUS_INT, PIN(D, 4), GPIO_INT_BOTH, tcpc_alert_event) -#else /* BOARD_TGLRVPY_ITE */ -GPIO_INT(USB_C0_VBUS_INT, PIN(D, 4), GPIO_INT_BOTH, tcpc_alert_event) -GPIO_INT(USB_C1_VBUS_INT, PIN(L, 5), GPIO_INT_BOTH, tcpc_alert_event) -#endif /* BOARD_TGLRVPU_ITE */ - -/* Power sequencing GPIOs */ -GPIO(CPU_PROCHOT, PIN(B, 2), GPIO_INPUT) -GPIO(SYS_RESET_L, PIN(B, 6), GPIO_ODR_HIGH) -GPIO(PCH_RSMRST_L, PIN(C, 6), GPIO_OUT_LOW) -GPIO(PCH_PWRBTN_L, PIN(D, 0), GPIO_ODR_HIGH) -GPIO(EC_SPI_OE_N, PIN(I, 2), GPIO_OUT_LOW) -/* - * PCH_SYS_PWROK is an input, driven by the Silego chip. The common x86 - * power sequencing expects that PCH_SYS_PWROK is an output and will drive - * this signal if GPIO_PCH_SYS_PWROK is configured. Map this pin as no-connect - * so that state can be monitored using the console. - */ -GPIO(NC_PCH_SYS_PWROK, PIN(K, 4), GPIO_INPUT) -GPIO(EN_PP5000, PIN(L, 4), GPIO_OUT_LOW) -GPIO(EN_PP3300_A, PIN(K, 2), GPIO_OUT_LOW) -GPIO(EC_PCH_DSW_PWROK, PIN(L, 6), GPIO_OUT_LOW) - -/* Host communication GPIOs */ -GPIO(PCH_WAKE_L, PIN(J, 0), GPIO_ODR_HIGH) -#ifndef CONFIG_HOSTCMD_ESPI -GPIO(PCH_PLTRST_L, PIN(E, 3), GPIO_INPUT | GPIO_PULL_UP) -#endif - -/* Battery present */ -GPIO(EC_BATT_PRES_L, PIN(K, 0), GPIO_INPUT) - -/* Type-C GPIOs */ -#if defined(BOARD_TGLRVPU_ITE) || defined(BOARD_TGLRVPU_ITE_TCPMV1) -GPIO(USB_C0_SRC_EN, PIN(L, 1), GPIO_OUT_LOW) -GPIO(USB_C0_SNK_EN_L, PIN(H, 6), GPIO_ODR_LOW) -GPIO(USB_C0_SRC_HI_ILIM, PIN(M, 6), GPIO_OUT_LOW) -GPIO(USB_C0_HPD, PIN(E, 6), GPIO_INPUT) -GPIO(USB_C0_FRS_EN, PIN(L, 7), GPIO_INPUT) - -GPIO(USB_C1_SRC_EN, PIN(G, 1), GPIO_OUT_LOW) -GPIO(USB_C1_SNK_EN_L, PIN(I, 5), GPIO_ODR_LOW) -GPIO(USB_C1_SRC_HI_ILIM, PIN(A, 0), GPIO_OUT_LOW) -GPIO(USB_C1_HPD, PIN(D, 3), GPIO_INPUT) -GPIO(USB_C1_FRS_EN, PIN(K, 5), GPIO_INPUT) - -/* Retimer GPIOs */ -GPIO(USB_C0_LS_EN, PIN(J, 1), GPIO_OUT_LOW) -GPIO(USB_C0_RETIMER_RST, PIN(J, 5), GPIO_OUT_LOW) -GPIO(USB_C0_RETIMER_FORCE_PWR, PIN(J, 3), GPIO_OUT_LOW) - -GPIO(USB_C1_LS_EN, PIN(C, 4), GPIO_OUT_LOW) -GPIO(USB_C1_RETIMER_RST, PIN(J, 4), GPIO_OUT_LOW) -GPIO(USB_C1_RETIMER_FORCE_PWR, PIN(H, 5), GPIO_OUT_LOW) -#else /* BOARD_TGLRVPY_ITE */ -GPIO(USB_C0_SRC_EN, PIN(G, 1), GPIO_OUT_LOW) -GPIO(USB_C0_SNK_EN_L, PIN(I, 5), GPIO_ODR_LOW | GPIO_PULL_DOWN) -GPIO(USB_C0_SRC_HI_ILIM, PIN(A, 0), GPIO_OUT_LOW) -GPIO(USB_C0_HPD, PIN(D, 3), GPIO_INPUT) -GPIO(USB_C0_FRS_EN, PIN(K, 5), GPIO_INPUT) - -GPIO(USB_C1_SRC_EN, PIN(L, 1), GPIO_OUT_LOW) -GPIO(USB_C1_SNK_EN_L, PIN(H, 6), GPIO_ODR_LOW | GPIO_PULL_DOWN) -GPIO(USB_C1_SRC_HI_ILIM, PIN(M, 6), GPIO_OUT_LOW) -GPIO(USB_C1_HPD, PIN(E, 6), GPIO_INPUT) -GPIO(USB_C1_FRS_EN, PIN(L, 7), GPIO_INPUT) - -/* Retimer GPIOs */ -GPIO(USB_C0_LS_EN, PIN(C, 4), GPIO_OUT_LOW) -GPIO(USB_C0_RETIMER_RST, PIN(J, 4), GPIO_OUT_LOW) -GPIO(USB_C0_RETIMER_FORCE_PWR, PIN(H, 5), GPIO_OUT_LOW) - -GPIO(USB_C1_LS_EN, PIN(J, 1), GPIO_OUT_LOW) -GPIO(USB_C1_RETIMER_RST, PIN(J, 5), GPIO_OUT_LOW) -GPIO(USB_C1_RETIMER_FORCE_PWR, PIN(J, 3), GPIO_OUT_LOW) -#endif /* BOARD_TGLRVPU_ITE */ - -/* Type-C BC1.2 GPIOs */ -GPIO(USB_C0_BC12_CHG_DET_L, PIN(A, 1), GPIO_INPUT) -GPIO(USB_C0_BC12_VBUS_ON_ODL, PIN(H, 4), GPIO_ODR_HIGH) - -GPIO(USB_C1_BC12_CHG_DET_L, PIN(B, 7), GPIO_INPUT) -GPIO(USB_C1_BC12_VBUS_ON_ODL, PIN(J, 6), GPIO_ODR_HIGH) - -/* VCONN enable pins */ -GPIO(USB_C0_CC1_VCONN_EN, PIN(D, 1), GPIO_OUT_LOW) -GPIO(USB_C0_CC2_VCONN_EN, PIN(G, 2), GPIO_OUT_LOW) -GPIO(USB_C1_CC1_VCONN_EN, PIN(E, 5), GPIO_OUT_LOW) -GPIO(USB_C1_CC2_VCONN_EN, PIN(I, 0), GPIO_OUT_LOW) - -/* USB-A GPIOs */ -GPIO(USB_A_5V_EN, PIN(K, 3), GPIO_INPUT) - -/* LED */ -GPIO(BAT_LED_GREEN_L, PIN(A, 6), GPIO_OUT_HIGH) /* LED_2_L */ -GPIO(AC_LED_GREEN_L, PIN(A, 3), GPIO_OUT_HIGH) /* LED_1_L */ - -/* FAN control pins */ -GPIO(FAN_POWER_EN, PIN(K, 6), GPIO_OUT_LOW) - -/* H1 pins */ -GPIO(CCD_MODE_ODL, PIN(B, 5), GPIO_INPUT) -GPIO(ENTERING_RW, PIN(C, 5), GPIO_OUT_LOW) -/* ME_GE_TO_ME_EC pin is re-purposed for H1 Packet Mode indication */ -GPIO(ME_G3_TO_ME_EC, PIN(H, 3), GPIO_OUT_LOW) - -/* Used with Discrete TBT and or with PD on RVP */ -GPIO(NC_TBT_C0_RESET_N, PIN(KSO_H, 7), GPIO_INPUT) -GPIO(NC_TBT_C1_RESET_N, PIN(K, 7), GPIO_INPUT) -GPIO(NC_USB_C0_RETIMER_ALRT, PIN(I, 7), GPIO_INPUT) -GPIO(NC_USB_C1_RETIMER_ALRT, PIN(G, 0), GPIO_INPUT) - -/* Used if Base EC is present */ -GPIO(NC_EC_BASE_DET, PIN(I, 3), GPIO_INPUT) - -#ifndef CONFIG_HOSTCMD_ESPI -GPIO_INT(ESPI_RESET_L, PIN(D, 2), GPIO_INPUT) -#endif - -/* Unused pins */ -GPIO(NC_SUSWARN, PIN(E, 1), GPIO_INPUT) -GPIO(NC_BATT_DISABLE, PIN(H, 0), GPIO_INPUT) -GPIO(NC_SMC_ONOFF_N, PIN(L, 3), GPIO_INPUT) /* Power button interrupt without H1 */ - -/* - * I2C pins should be configure as inputs until I2C module is - * initialized. This will avoid driving the lines unintentionally. - */ -GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) -GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) -GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT) -GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT) -GPIO(I2C_C_SCL, PIN(C, 7), GPIO_INPUT) -GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) -GPIO(I2C_E_SCL, PIN(E, 0), GPIO_INPUT) -GPIO(I2C_E_SDA, PIN(E, 7), GPIO_INPUT) -GPIO(I2C_F_SCL, PIN(A, 4), GPIO_INPUT) -GPIO(I2C_F_SDA, PIN(A, 5), GPIO_INPUT) - -/* Alternate pins for I2C */ -ALTERNATE(PIN_MASK(A, BIT(4) | BIT(5)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C F SCL/SDA A4/A5 */ -ALTERNATE(PIN_MASK(B, BIT(3) | BIT(4)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C A SCL/SDA B3/B4 */ -ALTERNATE(PIN_MASK(C, BIT(1) | BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C B SCL/SDA C1/C2 */ -ALTERNATE(PIN_MASK(E, BIT(0) | BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C E SCL/SDA E0/E7 */ -ALTERNATE(PIN_MASK(C, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C C SCL C7 */ -ALTERNATE(PIN_MASK(F, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_I2C, GPIO_FLAG_NONE) /* I2C C SDA F7 */ - -/* Alternate pins for UART */ -ALTERNATE(PIN_MASK(B, BIT(0) | BIT(1)), GPIO_ALT_FUNC_DEFAULT, MODULE_UART, GPIO_PULL_UP) /* UART1 B0/B1 */ - -/* Alternate pins for ADC */ -ALTERNATE(PIN_MASK(I, BIT(1) | BIT(6)), GPIO_ALT_FUNC_DEFAULT, MODULE_ADC, GPIO_FLAG_NONE) /* ADC 1,6 -> I1,I6 */ -ALTERNATE(PIN_MASK(L, BIT(0) | BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_ADC, GPIO_FLAG_NONE) /* ADC 13,15 -> L0,L2 */ - -/* Alternate pins for FAN */ -ALTERNATE(PIN_MASK(A, BIT(2)), GPIO_ALT_FUNC_DEFAULT, MODULE_PWM, GPIO_FLAG_NONE) /* PWM2 A2 */ -ALTERNATE(PIN_MASK(D, BIT(7)), GPIO_ALT_FUNC_DEFAULT, MODULE_PWM, GPIO_FLAG_NONE) /* TACH1A D7 */ diff --git a/board/tglrvpu_ite_tcpmv1 b/board/tglrvpu_ite_tcpmv1 deleted file mode 120000 index 05edd4d22f..0000000000 --- a/board/tglrvpu_ite_tcpmv1 +++ /dev/null @@ -1 +0,0 @@ -tglrvpu_ite \ No newline at end of file diff --git a/board/tglrvpy_ite b/board/tglrvpy_ite deleted file mode 120000 index 05edd4d22f..0000000000 --- a/board/tglrvpy_ite +++ /dev/null @@ -1 +0,0 @@ -tglrvpu_ite \ No newline at end of file diff --git a/board/tglrvpy_ite_tcpmv1 b/board/tglrvpy_ite_tcpmv1 deleted file mode 120000 index 560115c8ab..0000000000 --- a/board/tglrvpy_ite_tcpmv1 +++ /dev/null @@ -1 +0,0 @@ -tglrvpy_ite \ No newline at end of file diff --git a/board/tigertail/board.c b/board/tigertail/board.c index 8963c7e80a..73ba1ecc73 100644 --- a/board/tigertail/board.c +++ b/board/tigertail/board.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Tigertail board configuration */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "console.h" #include "ec_version.h" @@ -20,24 +19,23 @@ #include "timer.h" #include "update_fw.h" #include "usart-stm32f0.h" -#include "usart_tx_dma.h" #include "usart_rx_dma.h" -#include "usb_i2c.h" +#include "usart_tx_dma.h" #include "usb-stream.h" +#include "usb_i2c.h" #include "util.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" - -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) - +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /****************************************************************************** * Forward UARTs as a USB serial interface. */ -#define USB_STREAM_RX_SIZE 16 -#define USB_STREAM_TX_SIZE 16 +#define USB_STREAM_RX_SIZE 16 +#define USB_STREAM_TX_SIZE 16 /****************************************************************************** * Forward USART1 as a simple USB serial interface. @@ -45,43 +43,33 @@ static struct usart_config const usart1; struct usb_stream_config const usart1_usb; -static struct queue const usart1_to_usb = QUEUE_DIRECT(64, uint8_t, - usart1.producer, usart1_usb.consumer); -static struct queue const usb_to_usart1 = QUEUE_DIRECT(64, uint8_t, - usart1_usb.producer, usart1.consumer); +static struct queue const usart1_to_usb = + QUEUE_DIRECT(64, uint8_t, usart1.producer, usart1_usb.consumer); +static struct queue const usb_to_usart1 = + QUEUE_DIRECT(64, uint8_t, usart1_usb.producer, usart1.consumer); static struct usart_config const usart1 = - USART_CONFIG(usart1_hw, - usart_rx_interrupt, - usart_tx_interrupt, - 115200, - 0, - usart1_to_usb, - usb_to_usart1); - -USB_STREAM_CONFIG(usart1_usb, - USB_IFACE_USART1_STREAM, - USB_STR_USART1_STREAM_NAME, - USB_EP_USART1_STREAM, - USB_STREAM_RX_SIZE, - USB_STREAM_TX_SIZE, - usb_to_usart1, - usart1_to_usb) + USART_CONFIG(usart1_hw, usart_rx_interrupt, usart_tx_interrupt, 115200, + 0, usart1_to_usb, usb_to_usart1); +USB_STREAM_CONFIG(usart1_usb, USB_IFACE_USART1_STREAM, + USB_STR_USART1_STREAM_NAME, USB_EP_USART1_STREAM, + USB_STREAM_RX_SIZE, USB_STREAM_TX_SIZE, usb_to_usart1, + usart1_to_usb) /****************************************************************************** * Define the strings used in our USB descriptors. */ const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("Tigertail"), - [USB_STR_SERIALNO] = 0, - [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), - [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), - [USB_STR_USART1_STREAM_NAME] = USB_STRING_DESC("DUT UART"), + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), + [USB_STR_PRODUCT] = USB_STRING_DESC("Tigertail"), + [USB_STR_SERIALNO] = 0, + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"), + [USB_STR_USART1_STREAM_NAME] = USB_STRING_DESC("DUT UART"), [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Tigertail Console"), - [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), + [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"), }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); @@ -91,25 +79,29 @@ BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); */ /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_SBU1] = {"SBU1", 3300, 4096, 0, STM32_AIN(6)}, - [ADC_SBU2] = {"SBU2", 3300, 4096, 0, STM32_AIN(7)}, + [ADC_SBU1] = { "SBU1", 3300, 4096, 0, STM32_AIN(6) }, + [ADC_SBU2] = { "SBU2", 3300, 4096, 0, STM32_AIN(7) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - - /****************************************************************************** * Support I2C bridging over USB. */ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + { .name = "master", + .port = I2C_PORT_MASTER, + .kbps = 100, + .scl = GPIO_MASTER_I2C_SCL, + .sda = GPIO_MASTER_I2C_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -int usb_i2c_board_is_enabled(void) { return 1; } +int usb_i2c_board_is_enabled(void) +{ + return 1; +} /****************************************************************************** * Console commands. @@ -134,7 +126,7 @@ static void set_uart_gpios(int state) { int uart = GPIO_INPUT; int dir = 0; - int voltage = 1; /* 1: 1.8v, 0: 3.3v */ + int voltage = 1; /* 1: 1.8v, 0: 3.3v */ int enabled = 0; gpio_set_level(GPIO_ST_UART_LVL_DIS, 1); @@ -283,7 +275,7 @@ void set_uart_state(int state) */ void uart_sbu_tick(void) { - static int debounce; /* = 0 */ + static int debounce; /* = 0 */ if (uart_detect != UART_DETECT_AUTO) return; @@ -320,7 +312,7 @@ void uart_sbu_tick(void) } DECLARE_HOOK(HOOK_TICK, uart_sbu_tick, HOOK_PRIO_DEFAULT); -static int command_uart(int argc, char **argv) +static int command_uart(int argc, const char **argv) { const char *uart_state_str = "off"; const char *uart_detect_str = "manual"; @@ -345,15 +337,15 @@ static int command_uart(int argc, char **argv) uart_state_str = uart_state_names[uart_state]; if (uart_detect == UART_DETECT_AUTO) uart_detect_str = "auto"; - ccprintf("UART mux is: %s, setting: %s\n", - uart_state_str, uart_detect_str); + ccprintf("UART mux is: %s, setting: %s\n", uart_state_str, + uart_detect_str); return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(uart, command_uart, - "[off|on18|on33|flip18|flip33|auto]", - "Set the sbu uart state\n" - "WARNING: 3.3v may damage 1.8v devices.\n"); + "[off|on18|on33|flip18|flip33|auto]", + "Set the sbu uart state\n" + "WARNING: 3.3v may damage 1.8v devices.\n"); static void set_led_a(int r, int g, int b) { @@ -418,7 +410,6 @@ void set_mux_state(int state) set_led_b(1, 0, 0); } - /* On button press, toggle between mux A, B, off. */ static int button_ready = 1; void button_interrupt_deferred(void) @@ -457,7 +448,7 @@ void button_interrupt(enum gpio_signal signal) hook_call_deferred(&button_interrupt_deferred_data, 0); } -static int command_mux(int argc, char **argv) +static int command_mux(int argc, const char **argv) { char *mux_state_str = "off"; @@ -480,9 +471,8 @@ static int command_mux(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(mux, command_mux, - "[off|A|B]", - "Get/set the mux and enable state of the TYPE-C mux"); +DECLARE_CONSOLE_COMMAND(mux, command_mux, "[off|A|B]", + "Get/set the mux and enable state of the TYPE-C mux"); /****************************************************************************** * Initialize board. diff --git a/board/tigertail/board.h b/board/tigertail/board.h index 63019e717f..26e6af5985 100644 --- a/board/tigertail/board.h +++ b/board/tigertail/board.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -24,7 +24,6 @@ #undef CONFIG_UART_RX_DMA /* Optional features */ -#define CONFIG_STM_HWTIMER32 #define CONFIG_HW_CRC /* USB Configuration */ @@ -40,19 +39,19 @@ #define DEFAULT_SERIALNO "Uninitialized" /* USB interface indexes (use define rather than enum to expand them) */ -#define USB_IFACE_CONSOLE 0 -#define USB_IFACE_UPDATE 1 -#define USB_IFACE_USART1_STREAM 2 -#define USB_IFACE_I2C 3 -#define USB_IFACE_COUNT 4 +#define USB_IFACE_CONSOLE 0 +#define USB_IFACE_UPDATE 1 +#define USB_IFACE_USART1_STREAM 2 +#define USB_IFACE_I2C 3 +#define USB_IFACE_COUNT 4 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_CONSOLE 1 -#define USB_EP_UPDATE 2 -#define USB_EP_USART1_STREAM 3 -#define USB_EP_I2C 4 -#define USB_EP_COUNT 5 +#define USB_EP_CONTROL 0 +#define USB_EP_CONSOLE 1 +#define USB_EP_UPDATE 2 +#define USB_EP_USART1_STREAM 3 +#define USB_EP_I2C 4 +#define USB_EP_COUNT 5 /* Enable console recasting of GPIO type. */ #define CONFIG_CMD_GPIO_EXTENDED @@ -64,7 +63,7 @@ /* Enable control of I2C over USB */ #define CONFIG_USB_I2C #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define I2C_PORT_MASTER 0 #define CONFIG_INA231 @@ -77,14 +76,11 @@ */ #define CONFIG_SYSTEM_UNLOCKED - #ifndef __ASSEMBLER__ /* Timer selection */ #define TIM_CLOCK32 2 -#define TIM_ADC 3 - - +#define TIM_ADC 3 #include "gpio_signal.h" diff --git a/board/tigertail/build.mk b/board/tigertail/build.mk index 9e7fae1c07..7766dd5e6b 100644 --- a/board/tigertail/build.mk +++ b/board/tigertail/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/tigertail/ec.tasklist b/board/tigertail/ec.tasklist index afdb5dedc7..c254025ebc 100644 --- a/board/tigertail/ec.tasklist +++ b/board/tigertail/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/tigertail/gpio.inc b/board/tigertail/gpio.inc index 107d3b2a2e..41c96cba46 100644 --- a/board/tigertail/gpio.inc +++ b/board/tigertail/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/todor/battery.c b/board/todor/battery.c deleted file mode 100644 index d129ede528..0000000000 --- a/board/todor/battery.c +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery_fuel_gauge.h" -#include "common.h" -#include "util.h" - -/* - * Battery info for all Volteer battery types. Note that the fields - * start_charging_min/max and charging_min/max are not used for the charger. - * The effective temperature limits are given by discharging_min/max_c. - * - * Fuel Gauge (FG) parameters which are used for determining if the battery - * is connected, the appropriate ship mode (battery cutoff) command, and the - * charge/discharge FETs status. - * - * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery - * register. For some batteries, the charge/discharge FET bits are set when - * charging/discharging is active, in other types, these bits set mean that - * charging/discharging is disabled. Therefore, in addition to the mask for - * these bits, a disconnect value must be specified. Note that for TI fuel - * gauge, the charge/discharge FET status is found in Operation Status (0x54), - * but a read of Manufacturer Access (0x00) will return the lower 16 bits of - * Operation status which contains the FET status bits. - * - * The assumption for battery types supported is that the charge/discharge FET - * status can be read with a sb_read() command and therefore, only the register - * address, mask, and disconnect value need to be provided. - */ -const struct board_batt_params board_battery_info[] = { - /* LGC\011 L17L3PB0 Battery Information */ - /* - * Battery info provided by ODM on b/143477210, comment #11 - */ - [BATTERY_LGC011] = { - .fuel_gauge = { - .manuf_name = "LGC", - .ship_mode = { - .reg_addr = 0x00, - .reg_data = { 0x10, 0x10 }, - }, - .fet = { - .reg_addr = 0x0, - .reg_mask = 0x6000, - .disconnect_val = 0x6000, - } - }, - .batt_info = { - .voltage_max = TARGET_WITH_MARGIN(13200, 5), - .voltage_normal = 11550, /* mV */ - .voltage_min = 9000, /* mV */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = 0, - .discharging_max_c = 75, - }, - }, - /* LGC AP18C8K Battery Information */ - [BATTERY_LGC_AP18C8K] = { - .fuel_gauge = { - .manuf_name = "LGC KT0030G020", - .device_name = "AP18C8K", - .ship_mode = { - .reg_addr = 0x3A, - .reg_data = { 0xC574, 0xC574 }, - }, - .fet = { - .reg_addr = 0x43, - .reg_mask = 0x0001, - .disconnect_val = 0x0, - }, - }, - .batt_info = { - .voltage_max = 13050, - .voltage_normal = 11250, - .voltage_min = 9000, - .precharge_current = 256, - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 75, - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); - -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC011; diff --git a/board/todor/board.c b/board/todor/board.c deleted file mode 100644 index 6f189a7c33..0000000000 --- a/board/todor/board.c +++ /dev/null @@ -1,440 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "common.h" -#include "accelgyro.h" -#include "cbi_ec_fw_config.h" -#include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi260.h" -#include "driver/als_tcs3400.h" -#include "driver/bc12/pi3usb9201.h" -#include "driver/ppc/syv682x.h" -#include "driver/tcpm/tcpci.h" -#include "driver/tcpm/tusb422.h" -#include "driver/retimer/bb_retimer.h" -#include "driver/sync.h" -#include "extpower.h" -#include "fan.h" -#include "fan_chip.h" -#include "gpio.h" -#include "hooks.h" -#include "keyboard_scan.h" -#include "lid_switch.h" -#include "power.h" -#include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "tablet_mode.h" -#include "throttle_ap.h" -#include "uart.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usb_pd_tbt.h" -#include "usb_pd_tcpm.h" -#include "usbc_ppc.h" -#include "util.h" - -#include "gpio_list.h" /* Must come after other header files. */ - -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) - -/* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { - /* Increase from 50 us, because KSO_02 passes through the H1. */ - .output_settle_us = 80, - /* Other values should be the same as the default configuration. */ - .debounce_down_us = 9 * MSEC, - .debounce_up_us = 30 * MSEC, - .scan_period_us = 3 * MSEC, - .min_post_scan_delay_us = 1000, - .poll_timeout_us = 100 * MSEC, - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ - }, -}; - -/******************************************************************************/ -/* - * FW_CONFIG defaults for Todor if the CBI data is not initialized. - */ -union volteer_cbi_fw_config fw_config_defaults = { - .usb_db = DB_USB3_PASSIVE, -}; - -static void board_init(void) -{ - -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) -{ - /* Routing length exceeds 205mm prior to connection to re-timer */ - if (port == USBC_PORT_C1) - return TBT_SS_U32_GEN1_GEN2; - - /* - * Thunderbolt-compatible mode not supported - * - * TODO (b/147726366): All the USB-C ports need to support same speed. - * Need to fix once USB-C feature set is known for Volteer. - */ - return TBT_SS_RES_0; -} - -__override bool board_is_tbt_usb4_port(int port) -{ - /* - * On Proto-1 only Port 1 supports TBT & USB4 - * - * TODO (b/147732807): All the USB-C ports need to support same - * features. Need to fix once USB-C feature set is known for Volteer. - */ - return port == USBC_PORT_C1; -} - -/******************************************************************************/ -/* I2C port map configuration */ -const struct i2c_port_t i2c_ports[] = { - { - .name = "sensor", - .port = I2C_PORT_SENSOR, - .kbps = 400, - .scl = GPIO_EC_I2C0_SENSOR_SCL, - .sda = GPIO_EC_I2C0_SENSOR_SDA, - }, - { - .name = "usb_c0", - .port = I2C_PORT_USB_C0, - .kbps = 1000, - .scl = GPIO_EC_I2C1_USB_C0_SCL, - .sda = GPIO_EC_I2C1_USB_C0_SDA, - }, - { - .name = "usb_c1", - .port = I2C_PORT_USB_C1, - .kbps = 1000, - .scl = GPIO_EC_I2C2_USB_C1_SCL, - .sda = GPIO_EC_I2C2_USB_C1_SDA, - }, - { - .name = "usb_0_mix", - .port = I2C_PORT_USB_0_MIX, - .kbps = 100, - .scl = GPIO_EC_I2C3_USB_0_MIX_SCL, - .sda = GPIO_EC_I2C3_USB_0_MIX_SDA, - }, - { - .name = "usb_1_mix", - .port = I2C_PORT_USB_1_MIX, - .kbps = 100, - .scl = GPIO_EC_I2C4_USB_1_MIX_SCL, - .sda = GPIO_EC_I2C4_USB_1_MIX_SDA, - }, - { - .name = "power", - .port = I2C_PORT_POWER, - .kbps = 100, - .scl = GPIO_EC_I2C5_POWER_SCL, - .sda = GPIO_EC_I2C5_POWER_SDA, - }, - { - .name = "eeprom", - .port = I2C_PORT_EEPROM, - .kbps = 400, - .scl = GPIO_EC_I2C7_EEPROM_SCL, - .sda = GPIO_EC_I2C7_EEPROM_SDA, - }, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/******************************************************************************/ -/* PWM configuration */ -const struct pwm_t pwm_channels[] = { - [PWM_CH_LED1_BLUE] = { - .channel = 2, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 2400, - }, - [PWM_CH_LED2_GREEN] = { - .channel = 0, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 2400, - }, - [PWM_CH_LED3_RED] = { - .channel = 1, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 2400, - }, - [PWM_CH_KBLIGHT] = { - .channel = 3, - .flags = 0, - /* - * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent - * flicker. Higher frequencies consume similar average power to - * lower PWM frequencies, but higher frequencies record a much - * lower maximum power. - */ - .freq = 2400, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -/******************************************************************************/ -/* EC thermal management configuration */ - -/* - * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at - * 130 C. However, sensor is located next to DDR, so we need to use the lower - * DDR temperature limit (85 C) - */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; - -/* - * Inductor limits - used for both charger and PP3300 regulator - * - * Need to use the lower of the charger IC, PP3300 regulator, and the inductors - * - * Charger max recommended temperature 100C, max absolute temperature 125C - * PP3300 regulator: operating range -40 C to 145 C - * - * Inductors: limit of 125c - * PCB: limit is 80c - */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - - -struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, -}; -BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); - -/******************************************************************************/ - -static void kb_backlight_enable(void) -{ - gpio_set_level(GPIO_EC_KB_BL_EN, 1); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, kb_backlight_enable, HOOK_PRIO_DEFAULT); - -static void kb_backlight_disable(void) -{ - gpio_set_level(GPIO_EC_KB_BL_EN, 0); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kb_backlight_disable, HOOK_PRIO_DEFAULT); - -void board_reset_pd_mcu(void) -{ - /* TODO(b/159025015): Terrador: check USB PD reset operation */ -} - -/* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc0_usb4_mb_retimer = { - .usb_port = USBC_PORT_C0, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_0_MIX, - .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, -}; -/***************************************************************************** - * USB-C MUX/Retimer dynamic configuration. - */ -static void setup_mux(void) -{ - CPRINTS("C0 supports bb-retimer"); - /* USB-C port 0 have a retimer */ - usb_muxes[USBC_PORT_C0].next_mux = &usbc0_usb4_mb_retimer; -} - -__override void board_cbi_init(void) -{ - /* - * TODO(b/159025015): Terrador: check FW_CONFIG fields for USB DB type - */ - setup_mux(); - /* Reassign USB_C0_RT_RST_ODL */ - bb_controls[USBC_PORT_C0].usb_ls_en_gpio = GPIO_USB_C0_LS_EN; - bb_controls[USBC_PORT_C0].retimer_rst_gpio = GPIO_USB_C0_RT_RST_ODL; - -} - -/******************************************************************************/ -/* USBC PPC configuration */ -struct ppc_config_t ppc_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -/******************************************************************************/ -/* PPC support routines */ -void ppc_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_PPC_INT_ODL: - syv682x_interrupt(USBC_PORT_C0); - break; - case GPIO_USB_C1_PPC_INT_ODL: - syv682x_interrupt(USBC_PORT_C1); - default: - break; - } -} - -/******************************************************************************/ -/* BC1.2 charger detect configuration */ -const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC TCPC configuration */ -struct tcpc_config_t tcpc_config[] = { - [USBC_PORT_C0] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C0, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), - }, - [USBC_PORT_C1] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); -BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usb_muxes[] = { - [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); - -struct bb_usb_control bb_controls[] = { - [USBC_PORT_C0] = { - /* USB-C port 0 doesn't have a retimer */ - }, - [USBC_PORT_C1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); - -static void board_tcpc_init(void) -{ - /* Don't reset TCPCs after initial reset */ - if (!system_jumped_late()) - board_reset_pd_mcu(); - - /* Enable PPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); - - /* Enable TCPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); - - /* Enable BC1.2 interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); - -/******************************************************************************/ -/* TCPC support routines */ -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - /* - * Check which port has the ALERT line set - */ - if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} - -int ppc_get_alert_status(int port) -{ - if (port == USBC_PORT_C0) - return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; - else - return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; -} diff --git a/board/todor/board.h b/board/todor/board.h deleted file mode 100644 index 011fd8e359..0000000000 --- a/board/todor/board.h +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Baseboard features */ -#include "baseboard.h" - -/* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ - -#define CONFIG_VBOOT_EFS2 - -#define CONFIG_POWER_BUTTON - -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 4096 - -/* LED defines */ -#define CONFIG_LED_PWM -/* Although there are 2 LEDs, they are both controlled by the same lines. */ -#define CONFIG_LED_PWM_COUNT 1 - -/* Keyboard features */ - -/* Sensors */ -/* BMA253 accelerometer in base */ -#define CONFIG_ACCEL_BMA255 - -/* BMI260 accel/gyro in base */ -#define CONFIG_ACCELGYRO_BMI260 -#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) - -/* TCS3400 ALS */ -#define CONFIG_ALS -#define ALS_COUNT 1 -#define CONFIG_ALS_TCS3400 -#define CONFIG_ALS_TCS3400_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) - -/* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) - -#define CONFIG_LID_ANGLE -#define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL - -/* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 - -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - -/* - * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C - * cables only support up to 60W. - */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 - -/* Enabling Thunderbolt-compatible mode */ -#define CONFIG_USB_PD_TBT_COMPAT_MODE - -/* Enabling USB4 mode */ -#define CONFIG_USB_PD_USB4 -#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x40 -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 - -/* USB Type A Features */ - -/* USBC PPC*/ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C0/C1 */ - -/* BC 1.2 */ - -/* Volume Button feature */ - -/* Fan features */ -#undef CONFIG_FANS - -/* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 - -/* - * Macros for GPIO signals used in common code that don't match the - * schematic names. Signal names in gpio.inc match the schematic and are - * then redefined here to so it's more clear which signal is being used for - * which purpose. - */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_UART2_EC_RX -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L - -/* I2C Bus Configuration */ -#define CONFIG_I2C -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_0_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT4_1 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM - -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER - - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -enum battery_type { - BATTERY_LGC011, - BATTERY_LGC_AP18C8K, - BATTERY_TYPE_COUNT, -}; - -enum pwm_channel { - PWM_CH_LED1_BLUE = 0, - PWM_CH_LED2_GREEN, - PWM_CH_LED3_RED, - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; - -enum sensor_id { - LID_ACCEL = 0, - BASE_ACCEL, - BASE_GYRO, - CLEAR_ALS, - RGB_ALS, - SENSOR_COUNT, -}; - -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; - -void board_reset_pd_mcu(void); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/todor/build.mk b/board/todor/build.mk deleted file mode 100644 index b78172d3cf..0000000000 --- a/board/todor/build.mk +++ /dev/null @@ -1,17 +0,0 @@ -# -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -CHIP:=npcx -CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc -BASEBOARD:=volteer - -board-y=board.o -board-y+=battery.o -board-y+=led.o -board-y+=sensors.o diff --git a/board/todor/ec.tasklist b/board/todor/ec.tasklist deleted file mode 100644 index 292de51cdb..0000000000 --- a/board/todor/ec.tasklist +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/todor/gpio.inc b/board/todor/gpio.inc deleted file mode 100644 index 0ccb99815e..0000000000 --- a/board/todor/gpio.inc +++ /dev/null @@ -1,167 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -/* Wake Source interrupts */ -GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) -GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) -GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) -GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) - -/* Power sequencing interrupts */ -GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) -#endif -GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) - -/* Sensor Interrupts */ -GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi260_interrupt) -GPIO_INT(EC_ALS_RGB_INT_L, PIN(D, 4), GPIO_INT_FALLING, tcs3400_interrupt) -GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) - -/* USB-C interrupts */ -GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) -GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) - -GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) -GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) - -GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) -GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) - -/* HDMI interrupts */ - -/* Volume button interrupts */ -GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) - -/* Power Sequencing Signals */ -GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) -GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) -GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ -/* The EC does not buffer this signal on Volteer. */ -UNIMPLEMENTED(PCH_DSW_PWROK) - -/* Other wake sources */ -/* - * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an - * interrupt handler because it is automatically handled by the PSL. - * - * We need to lock the setting so this gpio can't be reconfigured to overdrive - * the real reset signal. (This is the PSL input pin not the real reset pin). - */ -GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | - GPIO_HIB_WAKE_HIGH | - GPIO_LOCKED) - -/* AP/PCH Signals */ -GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) -GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ -GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) -GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) -GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) -GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) -GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) -GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) -GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) - -GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) - -/* USB and USBC Signals */ - -/* - * USB_C1 moved from GPIO32 to GPIO83 on boards with board ID >=1. - * GPIO83/EN_PP1800_A is DNS on board ID 0 and GPIO32 is N/C on board ID >=1 - * so it's safe to define GPIOs compatible with both designs. - * TODO (b/149858568): remove board ID=0 support. - */ -GPIO(USB_C0_RT_RST_ODL, PIN(6, 1), GPIO_ODR_LOW) /* USB_C0 Reset */ -GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset */ -GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) -GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) -GPIO(USB_C0_FRS_EN, PIN(6, 0), GPIO_OUT_LOW) -GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) - -/* Don't have a load switch for retimer */ -UNIMPLEMENTED(USB_C0_LS_EN) -UNIMPLEMENTED(USB_C1_LS_EN) - -/* Misc Signals */ -GPIO(UART2_EC_RX, PIN(7, 5), GPIO_OUT_LOW) /* H1 Packet Mode */ -GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) /* Keyboard backlight enable*/ -GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ - -/* - * eDP backlight - both PCH and EC have enable pins that must be high - * for the backlight to turn on. Default state is high, and can be turned - * off during sleep states. - */ -GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) - -/* I2C pins - Alternate function below configures I2C module on these pins */ -GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) -GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) -GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) -GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) -GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) -GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) -GPIO(EC_I2C3_USB_0_MIX_SCL, PIN(D, 1), GPIO_INPUT) -GPIO(EC_I2C3_USB_0_MIX_SDA, PIN(D, 0), GPIO_INPUT) -GPIO(EC_I2C4_USB_1_MIX_SCL, PIN(F, 3), GPIO_INPUT) -GPIO(EC_I2C4_USB_1_MIX_SDA, PIN(F, 2), GPIO_INPUT) -GPIO(EC_I2C5_POWER_SCL, PIN(3, 3), GPIO_INPUT) -GPIO(EC_I2C5_POWER_SDA, PIN(3, 6), GPIO_INPUT) -GPIO(EC_I2C7_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) -GPIO(EC_I2C7_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) - -/* Battery signals */ -GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) - -/* Physical HPD pins are not needed on EC as these are configured by PMC */ -GPIO(USB_C0_DP_HPD, PIN(B, 7), GPIO_INPUT) -GPIO(USB_C1_DP_HPD, PIN(7, 0), GPIO_INPUT) - -/* Alternate functions GPIO definitions */ -ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */ -ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ -ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ -ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ -ALTERNATE(PIN_MASK(F, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C4 */ -ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ -ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ - -/* This selects between an LED module on the motherboard and one on the daughter - * board, to be controlled by LED_{1,2,3}_L. PWM allows driving both modules at - * the same time. */ -ALTERNATE(PIN_MASK(C, BIT(2) | BIT(3) | BIT(4)), 0, MODULE_PWM, 0) /* LED_{3,2,1}_L */ - -/* Keyboard pins */ -#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) -ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ -ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ -ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ -GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ -ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ -ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ -ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ -ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ - -/* UART */ -ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ - -/* Power Switch Logic (PSL) inputs */ -ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ -ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, - GPIO01 = H1_EC_PWR_BTN_ODL - GPIO02 = EC_RST_ODL */ - diff --git a/board/todor/led.c b/board/todor/led.c deleted file mode 100644 index c4053f0f10..0000000000 --- a/board/todor/led.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Power and battery LED control for Volteer - */ - -#include "common.h" -#include "ec_commands.h" -#include "led_common.h" -#include "led_pwm.h" -#include "pwm.h" - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, -}; -const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); - -struct pwm_led led_color_map[] = { - /* Red, Green, Blue */ - [EC_LED_COLOR_RED] = { 100, 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, - /* The green LED seems to be brighter than the others, so turn down - * green from its natural level for these secondary colors. - */ - [EC_LED_COLOR_YELLOW] = { 100, 70, 0 }, - [EC_LED_COLOR_WHITE] = { 100, 70, 100 }, - [EC_LED_COLOR_AMBER] = { 100, 20, 0 }, -}; - -struct pwm_led pwm_leds[] = { - /* 2 RGB diffusers controlled by 1 set of 3 channels. */ - [PWM_LED0] = { - .ch0 = PWM_CH_LED3_RED, - .ch1 = PWM_CH_LED2_GREEN, - .ch2 = PWM_CH_LED1_BLUE, - .enable = &pwm_enable, - .set_duty = &pwm_set_duty, - }, -}; - -void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) -{ - brightness_range[EC_LED_COLOR_RED] = 255; - brightness_range[EC_LED_COLOR_GREEN] = 255; - brightness_range[EC_LED_COLOR_BLUE] = 255; -} - -int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) -{ - enum pwm_led_id pwm_id; - - /* Convert ec_led_id to pwm_led_id. */ - if (led_id == EC_LED_ID_POWER_LED) - pwm_id = PWM_LED0; - else - return EC_ERROR_UNKNOWN; - - if (brightness[EC_LED_COLOR_RED]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_RED); - else if (brightness[EC_LED_COLOR_GREEN]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN); - else if (brightness[EC_LED_COLOR_BLUE]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE); - else if (brightness[EC_LED_COLOR_YELLOW]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_YELLOW); - else if (brightness[EC_LED_COLOR_WHITE]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE); - else if (brightness[EC_LED_COLOR_AMBER]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); - else - /* Otherwise, the "color" is "off". */ - set_pwm_led_color(pwm_id, -1); - - return EC_SUCCESS; -} diff --git a/board/todor/sensors.c b/board/todor/sensors.c deleted file mode 100644 index 9e34812131..0000000000 --- a/board/todor/sensors.c +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer family-specific sensor configuration */ -#include "common.h" -#include "accelgyro.h" -#include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi_common.h" -#include "driver/accelgyro_bmi260.h" -#include "driver/als_tcs3400.h" -#include "driver/sync.h" -#include "keyboard_scan.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "tablet_mode.h" -#include "util.h" - -/******************************************************************************/ -/* Sensors */ -static struct mutex g_lid_accel_mutex; -static struct mutex g_base_mutex; - -/* BMA253 private data */ -static struct accelgyro_saved_data_t g_bma253_data; - -/* BMI260 private data */ -static struct bmi_drv_data_t g_bmi260_data; - -/* TCS3400 private data */ -static struct als_drv_data_t g_tcs3400_data = { - .als_cal.scale = 1, - .als_cal.uscale = 0, - .als_cal.offset = 0, - .als_cal.channel_scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ - .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */ - }, -}; - -/* - * TODO: b/146166425 need to calibrate ALS/RGB sensor. At default settings, - * shining phone flashlight on sensor pegs all readings at 0xFFFF. - */ -static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { - .calibration.rgb_cal[X] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - } - }, - .calibration.rgb_cal[Y] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - }, - }, - .calibration.rgb_cal[Z] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - } - }, - .calibration.irt = INT_TO_FP(1), - .saturation.again = TCS_DEFAULT_AGAIN, - .saturation.atime = TCS_DEFAULT_ATIME, -}; - -/* Rotation matrix for the lid accelerometer */ -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; - -struct motion_sensor_t motion_sensors[] = { - [LID_ACCEL] = { - .name = "Lid Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMA255, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &bma2x2_accel_drv, - .mutex = &g_lid_accel_mutex, - .drv_data = &g_bma253_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .min_frequency = BMA255_ACCEL_MIN_FREQ, - .max_frequency = BMA255_ACCEL_MAX_FREQ, - .default_range = 2, /* g, to support tablet mode */ - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - /* Sensor on in S3 */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - }, - }, - [BASE_ACCEL] = { - .name = "Base Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMI260, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_BASE, - .drv = &bmi260_drv, - .mutex = &g_base_mutex, - .drv_data = &g_bmi260_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, - .rot_standard_ref = &base_standard_ref, - .min_frequency = BMI_ACCEL_MIN_FREQ, - .max_frequency = BMI_ACCEL_MAX_FREQ, - .default_range = 4, /* g */ - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - /* Sensor on in S3 */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, - }, - - [BASE_GYRO] = { - .name = "Base Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMI260, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_BASE, - .drv = &bmi260_drv, - .mutex = &g_base_mutex, - .drv_data = &g_bmi260_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, - .default_range = 1000, /* dps */ - .rot_standard_ref = &base_standard_ref, - .min_frequency = BMI_GYRO_MIN_FREQ, - .max_frequency = BMI_GYRO_MAX_FREQ, - }, - [CLEAR_ALS] = { - .name = "Clear Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT, - .location = MOTIONSENSE_LOC_BASE, - .drv = &tcs3400_drv, - .drv_data = &g_tcs3400_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - .min_frequency = TCS3400_LIGHT_MIN_FREQ, - .max_frequency = TCS3400_LIGHT_MAX_FREQ, - .config = { - /* Run ALS sensor in S0 */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 1000, - }, - }, - }, - - [RGB_ALS] = { - /* - * RGB channels read by CLEAR_ALS and so the i2c port and - * address do not need to be defined for RGB_ALS. - */ - .name = "RGB Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT_RGB, - .location = MOTIONSENSE_LOC_BASE, - .drv = &tcs3400_rgb_drv, - .drv_data = &g_tcs3400_rgb_data, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - }, -}; -unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ -const struct motion_sensor_t *motion_als_sensors[] = { - &motion_sensors[CLEAR_ALS], -}; -BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); - -static void baseboard_sensors_init(void) -{ - /* Note - BMA253 interrupt unused by EC */ - - /* Enable interrupt for the TCS3400 color light sensor */ - gpio_enable_interrupt(GPIO_EC_ALS_RGB_INT_L); - /* Enable interrupt for the BMI260 accel/gyro sensor */ - gpio_enable_interrupt(GPIO_EC_IMU_INT_L); -} -DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); - -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); - - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif diff --git a/board/tomato b/board/tomato new file mode 120000 index 0000000000..e96f559c72 --- /dev/null +++ b/board/tomato @@ -0,0 +1 @@ +cherry \ No newline at end of file diff --git a/board/treeya/battery.c b/board/treeya/battery.c index a98a38d3e9..8dce09612b 100644 --- a/board/treeya/battery.c +++ b/board/treeya/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/treeya/board.c b/board/treeya/board.c index c796bf43a0..35fbd3dde3 100644 --- a/board/treeya/board.c +++ b/board/treeya/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,38 +10,61 @@ #include "driver/accelgyro_bmi_common.h" #include "driver/accelgyro_lsm6dsm.h" #include "extpower.h" +#include "gpio.h" #include "i2c.h" #include "lid_switch.h" #include "power.h" #include "power_button.h" #include "pwm.h" -#include "system.h" #include "switch.h" +#include "system.h" +#include "system_chip.h" #include "tablet_mode.h" #include "task.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" +static uint8_t is_psl_hibernate; + const enum gpio_signal hibernate_wake_pins[] = { GPIO_LID_OPEN, GPIO_AC_PRESENT, GPIO_POWER_BUTTON_L, GPIO_EC_RST_ODL, }; -const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); /* I2C port map. */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, - {"thermal", I2C_PORT_THERMAL_AP, 400, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_I2C7_SCL, GPIO_I2C7_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_I2C0_SCL, + .sda = GPIO_I2C0_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, + { .name = "thermal", + .port = I2C_PORT_THERMAL_AP, + .kbps = 400, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_I2C7_SCL, + .sda = GPIO_I2C7_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -#ifdef HAS_TASK_MOTIONSENSE - /* Motion sensors */ static struct mutex g_lid_mutex_1; static struct mutex g_base_mutex_1; @@ -51,19 +74,15 @@ static struct stprivate_data g_lis2dwl_data; /* Base accel private data */ static struct lsm6dsm_data g_lsm6dsm_data = LSM6DSM_DATA; - /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t lsm6dsm_base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t lsm6dsm_base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, + FLOAT_TO_FP(1) } }; -static const mat33_fp_t treeya_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t treeya_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t lid_accel_1 = { .name = "Lid Accel", @@ -102,8 +121,6 @@ struct motion_sensor_t base_accel_1 = { .mutex = &g_base_mutex_1, .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_ACCEL, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &lsm6dsm_base_standard_ref, @@ -132,10 +149,7 @@ struct motion_sensor_t base_gyro_1 = { .location = MOTIONSENSE_LOC_BASE, .drv = &lsm6dsm_drv, .mutex = &g_base_mutex_1, - .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, - MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, + .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), .port = I2C_PORT_ACCEL, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -146,10 +160,14 @@ struct motion_sensor_t base_gyro_1 = { static int board_use_st_sensor(void) { - /* sku_id 0xa8-0xa9 use ST sensors */ + /* sku_id 0xa8-0xa9, 0xbe, 0xbf use ST sensors */ uint32_t sku_id = system_get_sku_id(); - return sku_id == 0xa8 || sku_id == 0xa9; + if (sku_id == 0xa8 || sku_id == 0xa9 || sku_id == 0xbe || + sku_id == 0xbf) + return 1; + else + return 0; } /* treeya board will use two sets of lid/base sensor, we need update @@ -157,16 +175,20 @@ static int board_use_st_sensor(void) */ void board_update_sensor_config_from_sku(void) { + uint32_t sku_id = system_get_sku_id(); + if (board_is_convertible()) { /* sku_id a8-a9 use ST sensors */ if (board_use_st_sensor()) { motion_sensors[LID_ACCEL] = lid_accel_1; motion_sensors[BASE_ACCEL] = base_accel_1; motion_sensors[BASE_GYRO] = base_gyro_1; - } else{ + } else { /*Need to change matrix for treeya*/ - motion_sensors[BASE_ACCEL].rot_standard_ref = &treeya_standard_ref; - motion_sensors[BASE_GYRO].rot_standard_ref = &treeya_standard_ref; + motion_sensors[BASE_ACCEL].rot_standard_ref = + &treeya_standard_ref; + motion_sensors[BASE_GYRO].rot_standard_ref = + &treeya_standard_ref; } /* Enable Gyro interrupts */ @@ -174,10 +196,16 @@ void board_update_sensor_config_from_sku(void) } else { motion_sensor_count = 0; /* Device is clamshell only */ - tablet_set_mode(0); + tablet_set_mode(0, TABLET_TRIGGER_LID); /* Gyro is not present, don't allow line to float */ - gpio_set_flags(GPIO_6AXIS_INT_L, - GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + } + + if (sku_id == 160 || sku_id == 168 || sku_id == 169 || sku_id == 190 || + sku_id == 191) { + is_psl_hibernate = 0; + } else { + is_psl_hibernate = 1; } } @@ -190,4 +218,89 @@ void board_bmi160_lsm6dsm_interrupt(enum gpio_signal signal) bmi160_interrupt(signal); } -#endif +static void system_psl_type_sel(int psl_no, uint32_t flags) +{ + /* Set PSL input events' type as level or edge trigger */ + if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) + CLEAR_BIT(NPCX_GLUE_PSL_CTS, psl_no + 4); + else if ((flags & GPIO_INT_F_RISING) || (flags & GPIO_INT_F_FALLING)) + SET_BIT(NPCX_GLUE_PSL_CTS, psl_no + 4); + + /* + * Set PSL input events' polarity is low (high-to-low) active or + * high (low-to-high) active + */ + if (flags & GPIO_HIB_WAKE_HIGH) + SET_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_no); + else + CLEAR_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_no); +} + +int system_config_psl_mode(enum gpio_signal signal) +{ + int psl_no; + const struct gpio_info *g = gpio_list + signal; + + if (g->port == GPIO_PORT_D && g->mask == MASK_PIN2) /* GPIOD2 */ + psl_no = 0; + else if (g->port == GPIO_PORT_0 && (g->mask & 0x07)) /* GPIO00/01/02 */ + psl_no = GPIO_MASK_TO_NUM(g->mask) + 1; + else + return 0; + + system_psl_type_sel(psl_no, g->flags); + return 1; +} + +void system_enter_psl_mode(void) +{ + /* Configure pins from GPIOs to PSL which rely on VSBY power rail. */ + gpio_config_module(MODULE_PMU, 1); + + /* + * Only PSL_IN events can pull PSL_OUT to high and reboot ec. + * We should treat it as wake-up pin reset. + */ + NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_PIN; + + /* + * Pull PSL_OUT (GPIO85) to low to cut off ec's VCC power rail by + * setting bit 5 of PDOUT(8). + */ + SET_BIT(NPCX_PDOUT(GPIO_PORT_8), 5); +} + +/* Hibernate function implemented by PSL (Power Switch Logic) mode. */ +noreturn void __keep __enter_hibernate_in_psl(void) +{ + system_enter_psl_mode(); + /* Spin and wait for PSL cuts power; should never return */ + while (1) + ; +} + +void board_hibernate_late(void) +{ + int i; + + /* + * If the SKU cannot use PSL hibernate, immediately return to go the + * non-PSL hibernate flow. + */ + if (!is_psl_hibernate) { + NPCX_KBSINPU = 0x0A; + return; + } + + for (i = 0; i < hibernate_wake_pins_used; i++) { + /* Config PSL pins setting for wake-up inputs */ + if (!system_config_psl_mode(hibernate_wake_pins[i])) + ccprintf("Invalid PSL setting in wake-up pin %d\n", i); + } + + /* Clear all pending IRQ otherwise wfi will have no affect */ + for (i = NPCX_IRQ_0; i < NPCX_IRQ_COUNT; i++) + task_clear_pending_irq(i); + + __enter_hibernate_in_psl(); +} diff --git a/board/treeya/board.h b/board/treeya/board.h index 4bda4cb64c..75c093cd71 100644 --- a/board/treeya/board.h +++ b/board/treeya/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,18 +12,31 @@ #include "baseboard.h" +/* b/203442963 + * It's workaround to reduce keyboard's "Silver Migration". + * From keyboard vendor's feedback, there are two factors to cause + * "Silver Migration". + * 1. A voltage potential between trace. + * 2. The presence of an electrolyte , such as moisture. + * The reason cause voltage potential between KSIxx trace is EC enter ec + * hibernate PSL and turn EC's VCC1 power off. Besides KSI2, the other + * KSIxx will be turn off. KSI2 is powered by H1. + * To avoid voltage potential is keep KSIxx on. That means not to enter + * ec hibernate PSL. + */ +#undef CONFIG_HIBERNATE_PSL + /* * By default, enable all console messages excepted HC, ACPI and event: * The sensor stack is generating a lot of activity. */ -#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) +#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC))) #undef CONFIG_HOSTCMD_DEBUG_MODE #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* Power and battery LEDs */ #define CONFIG_LED_COMMON #define CONFIG_CMD_LEDTEST -#define CONFIG_LED_POWER_LED #define CONFIG_LED_ONOFF_STATES @@ -37,7 +50,6 @@ #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCEL_KX022 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -49,7 +61,7 @@ /* * Slew rate on the PP1800_SENSOR load switch requires a short delay on startup. */ -#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US +#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US #define CONFIG_MOTION_SENSE_RESUME_DELAY_US (10 * MSEC) /* Second set of sensor drivers */ @@ -60,7 +72,6 @@ #ifndef __ASSEMBLER__ - enum battery_type { BATTERY_SMP, BATTERY_LGC, diff --git a/board/treeya/build.mk b/board/treeya/build.mk index 250abe6712..618554c11f 100644 --- a/board/treeya/build.mk +++ b/board/treeya/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/treeya/ec.tasklist b/board/treeya/ec.tasklist index fb6e2f75a1..7c9bfc2aff 100644 --- a/board/treeya/ec.tasklist +++ b/board/treeya/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/treeya/gpio.inc b/board/treeya/gpio.inc index 70e2e1b29c..f0de3fc62c 100644 --- a/board/treeya/gpio.inc +++ b/board/treeya/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/treeya/led.c b/board/treeya/led.c index 837d7a6723..60bcc33b16 100644 --- a/board/treeya/led.c +++ b/board/treeya/led.c @@ -1,51 +1,54 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" -#include "led_onoff_states.h" -#include "led_common.h" #include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 97; +__override const int led_charge_lvl_2 = 97; -struct led_descriptor - led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { LED_OFF, LED_INDEFINITE } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_POWER_LED_3_L, LED_ON_LVL); @@ -54,7 +57,7 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_POWER_LED_3_L, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_RED: diff --git a/board/treeya/vif_override.xml b/board/treeya/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/treeya/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/trembyle/battery.c b/board/trembyle/battery.c index 33e4e9ce5d..22724f11b4 100644 --- a/board/trembyle/battery.c +++ b/board/trembyle/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/trembyle/board.c b/board/trembyle/board.c index bcf1cc926c..c75f3fc732 100644 --- a/board/trembyle/board.c +++ b/board/trembyle/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,13 +6,12 @@ /* Trembyle board configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" -#include "charger.h" #include "cbi_ec_fw_config.h" -#include "driver/accelgyro_bmi_common.h" +#include "charger.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" +#include "driver/accelgyro_bmi_common.h" #include "driver/retimer/pi3dpx1207.h" #include "driver/retimer/pi3hdx1204.h" #include "driver/retimer/ps8811.h" @@ -31,17 +30,16 @@ #include "switch.h" #include "system.h" #include "task.h" -#include "thermistor.h" #include "temp_sensor.h" +#include "temp_sensor/thermistor.h" #include "usb_charge.h" #include "usb_mux.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -#ifdef HAS_TASK_MOTIONSENSE +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* Motion sensors */ static struct mutex g_lid_mutex; @@ -92,7 +90,7 @@ struct motion_sensor_t motion_sensors[] = { .drv_data = &g_bmi160_data, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .default_range = 2, /* g, enough for laptop */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ .rot_standard_ref = NULL, .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, @@ -129,8 +127,6 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#endif /* HAS_TASK_MOTIONSENSE */ - const struct power_signal_info power_signal_list[] = { [X86_SLP_S3_N] = { .gpio = GPIO_PCH_SLP_S3_L, @@ -187,7 +183,7 @@ const int usb_port_enable[USBA_PORT_COUNT] = { const struct pi3hdx1204_tuning pi3hdx1204_tuning = { .eq_ch0_ch1_offset = PI3HDX1204_EQ_DB710, .eq_ch2_ch3_offset = PI3HDX1204_EQ_DB710, - .vod_offset = PI3HDX1204_VOD_115_ALL_CHANNELS, + .vod_offset = PI3HDX1204_VOD_130_ALL_CHANNELS, .de_offset = PI3HDX1204_DE_DB_MINUS5, }; @@ -210,8 +206,8 @@ static void board_chipset_resume(void) int val; rv = i2c_read8(I2C_PORT_USBA0, - PS8811_I2C_ADDR_FLAGS + PS8811_REG_PAGE1, - PS8811_REG1_USB_BEQ_LEVEL, &val); + PS8811_I2C_ADDR_FLAGS3 + PS8811_REG_PAGE1, + PS8811_REG1_USB_BEQ_LEVEL, &val); if (!rv) break; } @@ -223,10 +219,12 @@ static void board_chipset_resume(void) /* USB-A1 needs to increase gain to get over MB/DB connector */ for (retry = 0; retry < PS8811_ACCESS_RETRIES; ++retry) { rv = i2c_write8(I2C_PORT_USBA1, - PS8811_I2C_ADDR_FLAGS + PS8811_REG_PAGE1, + PS8811_I2C_ADDR_FLAGS3 + PS8811_REG_PAGE1, PS8811_REG1_USB_BEQ_LEVEL, - PS8811_BEQ_I2C_LEVEL_UP_13DB | - PS8811_BEQ_PIN_LEVEL_UP_18DB); + (PS8811_BEQ_I2C_LEVEL_UP_13DB + << PS8811_BEQ_I2C_LEVEL_UP_SHIFT) | + (PS8811_BEQ_PIN_LEVEL_UP_18DB + << PS8811_BEQ_PIN_LEVEL_UP_SHIFT)); if (!rv) break; } @@ -236,9 +234,7 @@ static void board_chipset_resume(void) } if (ec_config_has_hdmi_retimer_pi3hdx1204()) { - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - 1); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, 1); } } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); @@ -249,9 +245,7 @@ static void board_chipset_suspend(void) ioex_set_level(IOEX_USB_A1_RETIMER_EN, 0); if (ec_config_has_hdmi_retimer_pi3hdx1204()) { - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - 0); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, 0); } } DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); @@ -259,6 +253,10 @@ DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); /***************************************************************************** * USB-C MUX/Retimer dynamic configuration */ + +/* Place holder for second mux in USBC1 chain */ +struct usb_mux_chain usbc1_mux1; + static void setup_mux(void) { if (ec_config_has_usbc1_retimer_ps8802()) { @@ -268,12 +266,10 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the PS8802 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_ps8802, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_ps8802; /* Set the AMD FP5 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_amd_fp5_usb_mux; + usbc1_mux1.mux = &usbc1_amd_fp5_usb_mux; /* Don't have the AMD FP5 flip */ usbc1_amd_fp5_usb_mux.flags = USB_MUX_FLAG_SET_WITHOUT_FLIP; @@ -285,12 +281,10 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the AMD FP5 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_amd_fp5_usb_mux, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_amd_fp5_usb_mux; /* Set the PS8818 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_ps8818; + usbc1_mux1.mux = &usbc1_ps8818; } } @@ -304,23 +298,29 @@ const struct pi3dpx1207_usb_control pi3dpx1207_controls[] = { }; BUILD_ASSERT(ARRAY_SIZE(pi3dpx1207_controls) == USBC_PORT_COUNT); -const struct usb_mux usbc0_pi3dpx1207_usb_retimer = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = PI3DPX1207_I2C_ADDR_FLAGS, - .driver = &pi3dpx1207_usb_retimer, +const struct usb_mux_chain usbc0_pi3dpx1207_usb_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = PI3DPX1207_I2C_ADDR_FLAGS, + .driver = &pi3dpx1207_usb_retimer, + }, }; -struct usb_mux usb_muxes[] = { +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .next_mux = &usbc0_pi3dpx1207_usb_retimer, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_pi3dpx1207_usb_retimer, }, [USBC_PORT_C1] = { /* Filled in dynamically at startup */ + .next = &usbc1_mux1, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); @@ -364,7 +364,7 @@ DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = -1, }; @@ -452,29 +452,40 @@ const struct temp_sensor_t temp_sensors[] = { }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -const static struct ec_thermal_config thermal_thermistor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(90), - [EC_TEMP_THRESH_HALT] = C_TO_K(92), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(80), - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(58), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_THERMISTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(92), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(58), \ + } +__maybe_unused static const struct ec_thermal_config thermal_thermistor = + THERMAL_THERMISTOR; -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(90), - [EC_TEMP_THRESH_HALT] = C_TO_K(92), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(80), - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(58), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(92), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(58), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; diff --git a/board/trembyle/board.h b/board/trembyle/board.h index 7a28379233..c04e963d1e 100644 --- a/board/trembyle/board.h +++ b/board/trembyle/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,17 +10,16 @@ #define VARIANT_ZORK_TREMBYLE -#include #include "baseboard.h" +#include + #define CONFIG_USBC_RETIMER_PI3DPX1207 -#define CONFIG_MKBP_USE_GPIO /* Motion sensing drivers */ #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCEL_KX022 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -31,36 +30,32 @@ #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL /* GPIO mapping from board specific name to EC common name. */ -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL -#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL -#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL -#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L -#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK -#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L -#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL -#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD -#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD -#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE #ifndef __ASSEMBLER__ -enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, - ADC_TEMP_SENSOR_SOC, - ADC_CH_COUNT -}; +enum adc_channel { ADC_TEMP_SENSOR_CHARGER, ADC_TEMP_SENSOR_SOC, ADC_CH_COUNT }; enum battery_type { BATTERY_AP18F4M, @@ -73,11 +68,7 @@ enum mft_channel { MFT_CH_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_FAN, PWM_CH_COUNT }; enum temp_sensor_id { TEMP_SENSOR_CHARGER = 0, @@ -86,16 +77,11 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum usba_port { - USBA_PORT_A0 = 0, - USBA_PORT_A1, - USBA_PORT_COUNT -}; +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; /***************************************************************************** * CBI EC FW Configuration */ -#include "cbi_ec_fw_config.h" /** * TREMBYLE_MB_USBAC @@ -154,62 +140,53 @@ enum ec_cfg_usb_db_type { TREMBYLE_DB_T_OPT3_USBAC_HDMI_MSTHUB = 2, }; +#include "cbi_ec_fw_config.h" -#define HAS_USBC1_RETIMER_PS8802 \ - (BIT(TREMBYLE_DB_T_OPT2_USBAC) | \ - BIT(TREMBYLE_DB_T_OPT3_USBAC_HDMI_MSTHUB)) +#define HAS_USBC1_RETIMER_PS8802 \ + (BIT(TREMBYLE_DB_T_OPT2_USBAC) | \ + BIT(TREMBYLE_DB_T_OPT3_USBAC_HDMI_MSTHUB)) static inline bool ec_config_has_usbc1_retimer_ps8802(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8802); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_PS8802); } -#define HAS_USBC1_RETIMER_PS8818 \ - (BIT(TREMBYLE_DB_T_OPT1_USBAC_HMDI)) +#define HAS_USBC1_RETIMER_PS8818 (BIT(TREMBYLE_DB_T_OPT1_USBAC_HMDI)) static inline bool ec_config_has_usbc1_retimer_ps8818(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8818); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_PS8818); } -#define HAS_HDMI_RETIMER_PI3HDX1204 \ - (BIT(TREMBYLE_DB_T_OPT1_USBAC_HMDI)) +#define HAS_HDMI_RETIMER_PI3HDX1204 (BIT(TREMBYLE_DB_T_OPT1_USBAC_HMDI)) static inline bool ec_config_has_hdmi_retimer_pi3hdx1204(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_RETIMER_PI3HDX1204); + return !!(BIT(ec_config_get_usb_db()) & HAS_HDMI_RETIMER_PI3HDX1204); } -#define HAS_MST_HUB_RTD2141B \ - (BIT(TREMBYLE_DB_T_OPT3_USBAC_HDMI_MSTHUB)) +#define HAS_MST_HUB_RTD2141B (BIT(TREMBYLE_DB_T_OPT3_USBAC_HDMI_MSTHUB)) static inline bool ec_config_has_mst_hub_rtd2141b(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_MST_HUB_RTD2141B); + return !!(BIT(ec_config_get_usb_db()) & HAS_MST_HUB_RTD2141B); } -#define HAS_HDMI_CONN_HPD \ - (BIT(TREMBYLE_DB_T_OPT1_USBAC_HMDI)) +#define HAS_HDMI_CONN_HPD (BIT(TREMBYLE_DB_T_OPT1_USBAC_HMDI)) static inline bool ec_config_has_hdmi_conn_hpd(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_CONN_HPD); + return !!(BIT(ec_config_get_usb_db()) & HAS_HDMI_CONN_HPD); } -#define PORT_TO_HPD(port) ((port == 0) \ - ? GPIO_USB_C0_HPD \ - : (ec_config_has_usbc1_retimer_ps8802()) \ - ? GPIO_DP1_HPD \ - : GPIO_DP2_HPD) +#define PORT_TO_HPD(port) \ + ((port == 0) ? GPIO_USB_C0_HPD : \ + (ec_config_has_usbc1_retimer_ps8802()) ? GPIO_DP1_HPD : \ + GPIO_DP2_HPD) -extern const struct usb_mux usbc0_pi3dpx1207_usb_retimer; -extern const struct usb_mux usbc1_ps8802; +extern const struct usb_mux_chain usbc0_pi3dpx1207_usb_retimer; extern const struct usb_mux usbc1_ps8818; +extern struct usb_mux usbc1_ps8802; extern struct usb_mux usbc1_amd_fp5_usb_mux; void hdmi_hpd_interrupt(enum ioex_signal signal); diff --git a/board/trembyle/build.mk b/board/trembyle/build.mk index 4ca0cbd96f..cd58c2b91b 100644 --- a/board/trembyle/build.mk +++ b/board/trembyle/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/trembyle/ec.tasklist b/board/trembyle/ec.tasklist index 41b83cf4f3..4bb60ed55d 100644 --- a/board/trembyle/ec.tasklist +++ b/board/trembyle/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/trembyle/gpio.inc b/board/trembyle/gpio.inc index 6cc3e6fe09..7c49eef74e 100644 --- a/board/trembyle/gpio.inc +++ b/board/trembyle/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/trembyle/led.c b/board/trembyle/led.c index ea8e445166..ec4e93dca5 100644 --- a/board/trembyle/led.c +++ b/board/trembyle/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,32 +8,41 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_1; +__override const int led_charge_lvl_2 = 100; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_RED, 2 * LED_ONE_SEC} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_RED, 2 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_BLUE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_RED, + 2 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_BLUE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_RED, + 2 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + }; BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_BLUE: diff --git a/board/trembyle/vif_override.xml b/board/trembyle/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/trembyle/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/trogdor/battery.c b/board/trogdor/battery.c index 0548a6e6d0..cffda632bc 100644 --- a/board/trogdor/battery.c +++ b/board/trogdor/battery.c @@ -1,45 +1,68 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Battery pack vendor provided charging profile */ -#include "battery.h" -#include "battery_smart.h" +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" -/* Shutdown mode parameter to write to manufacturer access register */ -#define SB_SHIP_MODE_REG SB_MANUFACTURER_ACCESS -#define SB_SHUTDOWN_DATA 0x0010 +/* + * Battery info for all trogdor battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ -/* Battery info */ -static const struct battery_info info = { - .voltage_max = 8800, - .voltage_normal = 7700, - .voltage_min = 6000, - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = -20, - .discharging_max_c = 75, +const struct board_batt_params board_battery_info[] = { + /* AP16L5J */ + [BATTERY_AP16L5J] = { + .fuel_gauge = { + .manuf_name = "PANASONIC", + .device_name = "AP16L5J", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 0, + .reg_addr = 0x0, + .reg_mask = 0x4000, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8800, + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, }; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const struct battery_info *battery_get_info(void) -{ - return &info; -} - -int board_cut_off_battery(void) -{ - int rv; - - /* Ship mode command must be sent twice to take effect */ - rv = sb_write(SB_SHIP_MODE_REG, SB_SHUTDOWN_DATA); - - if (rv != EC_SUCCESS) - return rv; - - return sb_write(SB_SHIP_MODE_REG, SB_SHUTDOWN_DATA); -} +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AP16L5J; diff --git a/board/trogdor/board.c b/board/trogdor/board.c index b39e100b56..ed3d32b757 100644 --- a/board/trogdor/board.c +++ b/board/trogdor/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,114 +7,41 @@ #include "adc_chip.h" #include "button.h" -#include "charge_manager.h" -#include "charge_state.h" -#include "extpower.h" +#include "driver/accel_bma2x2.h" #include "driver/accelgyro_bmi_common.h" -#include "driver/ppc/sn5s330.h" -#include "driver/tcpm/ps8xxx.h" -#include "driver/tcpm/tcpci.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "keyboard_scan.h" #include "lid_switch.h" -#if BOARD_REV >= TROGDOR_REV1 -#include "pi3usb9201.h" -#else -#include "pi3usb9281.h" -#endif /* BOARD_REV */ #include "power.h" #include "power_button.h" #include "pwm.h" #include "pwm_chip.h" -#include "system.h" #include "shi_chip.h" #include "switch.h" +#include "system.h" +#include "tablet_mode.h" #include "task.h" +#include "usbc_config.h" #include "usbc_ppc.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -/* Forward declaration */ -static void tcpc_alert_event(enum gpio_signal signal); -static void usb0_evt(enum gpio_signal signal); -static void usb1_evt(enum gpio_signal signal); -static void ppc_interrupt(enum gpio_signal signal); -static void board_connect_c0_sbu(enum gpio_signal s); +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -/* GPIO Interrupt Handlers */ -static void tcpc_alert_event(enum gpio_signal signal) -{ - int port = -1; - - switch (signal) { - case GPIO_USB_C0_PD_INT_ODL: - port = 0; - break; - case GPIO_USB_C1_PD_INT_ODL: - port = 1; - break; - default: - return; - } - - schedule_deferred_pd_interrupt(port); -} - -static void usb0_evt(enum gpio_signal signal) -{ - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); -} - -static void usb1_evt(enum gpio_signal signal) -{ - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); -} - -static void ppc_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_SWCTL_INT_ODL: - sn5s330_interrupt(0); - break; - case GPIO_USB_C1_SWCTL_INT_ODL: - sn5s330_interrupt(1); - break; - default: - break; - } -} - -static void board_connect_c0_sbu_deferred(void) -{ - /* - * If CCD_MODE_ODL asserts, it means there's a debug accessory connected - * and we should enable the SBU FETs. - */ - ppc_set_sbu(0, 1); -} -DECLARE_DEFERRED(board_connect_c0_sbu_deferred); - -static void board_connect_c0_sbu(enum gpio_signal s) -{ - hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); -} - /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Use 80 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* * Unmask 0x08 in [0] (KSO_00/KSI_03, the new location of Search key); * as it still uses the legacy location (KSO_01/KSI_00). */ - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca - }, + .actual_key_mask = { 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xa4, + 0xff, 0xfe, 0x55, 0xfa, 0xca }, /* Other values should be the same as the default configuration. */ .debounce_down_us = 9 * MSEC, .debounce_up_us = 30 * MSEC, @@ -125,16 +52,31 @@ struct keyboard_scan_config keyscan_config = { /* I2C port map */ const struct i2c_port_t i2c_ports[] = { - {"power", I2C_PORT_POWER, 100, GPIO_EC_I2C_POWER_SCL, - GPIO_EC_I2C_POWER_SDA}, - {"tcpc0", I2C_PORT_TCPC0, 1000, GPIO_EC_I2C_USB_C0_PD_SCL, - GPIO_EC_I2C_USB_C0_PD_SDA}, - {"tcpc1", I2C_PORT_TCPC1, 1000, GPIO_EC_I2C_USB_C1_PD_SCL, - GPIO_EC_I2C_USB_C1_PD_SDA}, - {"eeprom", I2C_PORT_EEPROM, 400, GPIO_EC_I2C_EEPROM_SCL, - GPIO_EC_I2C_EEPROM_SDA}, - {"sensor", I2C_PORT_SENSOR, 400, GPIO_EC_I2C_SENSOR_SCL, - GPIO_EC_I2C_SENSOR_SDA}, + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); @@ -142,37 +84,22 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); /* ADC channels */ const struct adc_t adc_channels[] = { /* Measure VBUS through a 1/10 voltage divider */ - [ADC_VBUS] = { - "VBUS", - NPCX_ADC_CH1, - ADC_MAX_VOLT * 10, - ADC_READ_MAX + 1, - 0 - }, + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, /* * Adapter current output or battery charging/discharging current (uV) * 18x amplification on charger side. */ - [ADC_AMON_BMON] = { - "AMON_BMON", - NPCX_ADC_CH2, - ADC_MAX_VOLT * 1000 / 18, - ADC_READ_MAX + 1, - 0 - }, + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, /* * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we * only divide by 2 (enough to avoid precision issues). */ - [ADC_PSYS] = { - "PSYS", - NPCX_ADC_CH3, - ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), - 2, - 0 - }, + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -183,136 +110,17 @@ const struct pwm_t pwm_channels[] = { }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); -/* Power Path Controller */ -struct ppc_config_t ppc_chips[] = { - { - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, - { - .i2c_port = I2C_PORT_TCPC1, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv - }, -}; -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -/* TCPC mux configuration */ -const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_TCPC0, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .drv = &ps8xxx_tcpm_drv, - }, - { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_TCPC1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .drv = &ps8xxx_tcpm_drv, - }, -}; - -/* - * Port-0/1 USB mux driver. - * - * The USB mux is handled by TCPC chip and the HPD update is through a GPIO - * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, - * the mux misbehaves. - */ -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - }, - { - .usb_port = 1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - } -}; - -const int usb_port_enable[USB_PORT_COUNT] = { - GPIO_EN_USB_A_5V, -}; - -/* BC1.2 */ -#if BOARD_REV >= TROGDOR_REV1 -const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { - { - .i2c_port = I2C_PORT_POWER, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, - { - .i2c_port = I2C_PORT_EEPROM, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, -}; -#else -struct pi3usb9281_config pi3usb9281_chips[] = { - { - .i2c_port = I2C_PORT_POWER, - }, - { - .i2c_port = I2C_PORT_EEPROM, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) == - CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT); -#endif /* BOARD_REV */ - /* Initialize board. */ static void board_init(void) { - /* Enable BC1.2 interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); - /* Enable interrupt for BMI160 sensor */ gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); - /* - * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs - * for SBU may be disconnected after DP alt mode is off. Should enable - * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. - */ - gpio_enable_interrupt(GPIO_CCD_MODE_ODL); - /* Set the backlight duty cycle to 0. AP will override it later. */ pwm_set_duty(PWM_CH_DISPLIGHT, 0); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -void board_tcpc_init(void) -{ - /* Only reset TCPC if not sysjump */ - if (!system_jumped_late()) { - /* TODO(crosbug.com/p/61098): How long do we need to wait? */ - board_reset_pd_mcu(); - } - - /* Enable PPC interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); - - /* Enable TCPC interrupts */ - gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); - - /* - * Initialize HPD to low; after sysjump SOC needs to see - * HPD pulse to enable video path - */ - for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, 0, 0); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); - /* Called on AP S0 -> S3 transition */ static void board_chipset_suspend(void) { @@ -335,162 +143,49 @@ static void board_chipset_resume(void) } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); -void board_set_switchcap_power(int enable) -{ - gpio_set_level(GPIO_SWITCHCAP_ON, enable); -} - -int board_is_switchcap_enabled(void) -{ - return gpio_get_level(GPIO_SWITCHCAP_ON); -} - -int board_is_switchcap_power_good(void) -{ - return gpio_get_level(GPIO_DA9313_GPIO0); -} - -void board_reset_pd_mcu(void) -{ - cprints(CC_USB, "Resetting TCPCs..."); - cflush(); - - gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); - gpio_set_level(GPIO_USB_C1_PD_RST_ODL, 0); - msleep(PS8XXX_RESET_DELAY_MS); - gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); - gpio_set_level(GPIO_USB_C1_PD_RST_ODL, 1); - msleep(PS8805_FW_INIT_DELAY_MS); -} - -void board_set_tcpc_power_mode(int port, int mode) -{ - /* Ignore the "mode" to turn the chip on. We can only do a reset. */ - if (mode) - return; - - board_reset_pd_mcu(); -} - -int board_vbus_sink_enable(int port, int enable) -{ - /* Both ports are controlled by PPC SN5S330 */ - return ppc_vbus_sink_enable(port, enable); -} - -int board_is_sourcing_vbus(int port) -{ - /* Both ports are controlled by PPC SN5S330 */ - return ppc_is_sourcing_vbus(port); -} - -void board_overcurrent_event(int port, int is_overcurrented) -{ - /* TODO(b/120231371): Notify AP */ - CPRINTS("p%d: overcurrent!", port); -} - -int board_set_active_charge_port(int port) -{ - int is_real_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); - int i; - - if (!is_real_port && port != CHARGE_PORT_NONE) - return EC_ERROR_INVAL; - - if (port == CHARGE_PORT_NONE) { - CPRINTS("Disabling all charging port"); - - /* Disable all ports. */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - /* - * Do not return early if one fails otherwise we can - * get into a boot loop assertion failure. - */ - if (board_vbus_sink_enable(i, 0)) - CPRINTS("Disabling p%d sink path failed.", i); - } - - return EC_SUCCESS; - } - - /* Check if the port is sourcing VBUS. */ - if (board_is_sourcing_vbus(port)) { - CPRINTS("Skip enable p%d", port); - return EC_ERROR_INVAL; - } - - - CPRINTS("New charge port: p%d", port); - - /* - * Turn off the other ports' sink path FETs, before enabling the - * requested charge port. - */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - if (i == port) - continue; - - if (board_vbus_sink_enable(i, 0)) - CPRINTS("p%d: sink path disable failed.", i); - } - - /* Enable requested charge port. */ - if (board_vbus_sink_enable(port, 1)) { - CPRINTS("p%d: sink path enable failed.", port); - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* - * Ignore lower charge ceiling on PD transition if our battery is - * critical, as we may brownout. - */ - if (supplier == CHARGE_SUPPLIER_PD && - charge_ma < 1500 && - charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { - CPRINTS("Using max ilim %d", max_ma); - charge_ma = max_ma; - } - - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), - charge_mv); -} - -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) - if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) - if (gpio_get_level(GPIO_USB_C1_PD_RST_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} - /* Mutexes */ static struct mutex g_base_mutex; +static struct mutex g_lid_mutex; static struct bmi_drv_data_t g_bmi160_data; +static struct accelgyro_saved_data_t g_bma255_data; /* Matrix to rotate accelerometer into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma255_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, /* g, to support lid angle calculation. */ + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, /* * Note: bmi160: supports accelerometer and gyro sensor * Requirement: accelerometer sensor must init before gyro sensor @@ -498,7 +193,7 @@ struct motion_sensor_t motion_sensors[] = { */ [BASE_ACCEL] = { .name = "Base Accel", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .active_mask = SENSOR_ACTIVE_S0_S3, .chip = MOTIONSENSE_CHIP_BMI160, .type = MOTIONSENSE_TYPE_ACCEL, .location = MOTIONSENSE_LOC_BASE, @@ -515,11 +210,15 @@ struct motion_sensor_t motion_sensors[] = { [SENSOR_CONFIG_EC_S0] = { .odr = 10000 | ROUND_UP_FLAG, }, + /* Sensor on for lid angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, }, }, [BASE_GYRO] = { .name = "Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, + .active_mask = SENSOR_ACTIVE_S0_S3, .chip = MOTIONSENSE_CHIP_BMI160, .type = MOTIONSENSE_TYPE_GYRO, .location = MOTIONSENSE_LOC_BASE, diff --git a/board/trogdor/board.h b/board/trogdor/board.h index e593207f29..2c8e67d26b 100644 --- a/board/trogdor/board.h +++ b/board/trogdor/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,32 +10,29 @@ #include "baseboard.h" -/* Board revision */ -#include "board_revs.h" - /* TODO(waihong): Remove the following bringup features */ #define CONFIG_BRINGUP #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands. */ #define CONFIG_USB_PD_DEBUG_LEVEL 3 -#define CONFIG_CMD_AP_RESET_LOG #define CONFIG_CMD_GPIO_EXTENDED #define CONFIG_CMD_POWERINDEBUG #define CONFIG_I2C_DEBUG /* Internal SPI flash on NPCX7 */ -#define CONFIG_FLASH_SIZE (1024 * 1024) /* 1MB internal spi flash */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ /* Keyboard */ -#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_KEYBOARD_PROTOCOL_MKBP + #define CONFIG_PWM_KBLIGHT +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_FUEL_GAUGE + /* BC 1.2 Charger */ -#if BOARD_REV >= TROGDOR_REV1 #define CONFIG_BC12_DETECT_PI3USB9201 -#else -#define CONFIG_BC12_DETECT_PI3USB9281 -#define CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT 2 -#endif /* BOARD_REV */ /* USB */ #define CONFIG_USB_PD_TCPM_PS8805 @@ -47,49 +44,54 @@ #define CONFIG_USB_PORT_POWER_DUMB /* Sensors */ +/* BMI160 Base accel/gyro */ #define CONFIG_ACCELGYRO_BMI160 -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS +/* BMA253 lid accel */ +#define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_UPDATE + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + /* GPIO alias */ #define GPIO_AC_PRESENT GPIO_ACOK_OD #define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_SWITCHCAP_PG GPIO_SWITCHCAP_GPIO_1 +#define GPIO_ACOK_OD GPIO_CHG_ACOK_OD #ifndef __ASSEMBLER__ #include "gpio_signal.h" #include "registers.h" -enum adc_channel { - ADC_VBUS, - ADC_AMON_BMON, - ADC_PSYS, - ADC_CH_COUNT -}; +enum adc_channel { ADC_VBUS, ADC_AMON_BMON, ADC_PSYS, ADC_CH_COUNT }; /* Motion sensors */ enum sensor_id { - BASE_ACCEL = 0, + LID_ACCEL = 0, + BASE_ACCEL, BASE_GYRO, SENSOR_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_DISPLIGHT, - PWM_CH_COUNT +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_DISPLIGHT, PWM_CH_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_AP16L5J, + BATTERY_TYPE_COUNT, }; -/* Swithcap functions */ -void board_set_switchcap_power(int enable); -int board_is_switchcap_enabled(void); -int board_is_switchcap_power_good(void); -/* Custom function to indicate if sourcing VBUS */ -int board_is_sourcing_vbus(int port); -/* Enable VBUS sink for a given port */ -int board_vbus_sink_enable(int port, int enable); /* Reset all TCPCs. */ void board_reset_pd_mcu(void); void board_set_tcpc_power_mode(int port, int mode); diff --git a/board/trogdor/board_revs.h b/board/trogdor/board_revs.h deleted file mode 100644 index 9d3273f813..0000000000 --- a/board/trogdor/board_revs.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_BOARD_REVS_H -#define __CROS_EC_BOARD_REVS_H - -#define TROGDOR_REV0 0 -#define TROGDOR_REV1 1 -#define TROGDOR_REV_LAST TROGDOR_REV1 - -#define TROGDOR_REV_DEFAULT TROGDOR_REV0 - -#if !defined(BOARD_REV) -#define BOARD_REV TROGDOR_REV_DEFAULT -#endif - -#if BOARD_REV < TROGDOR_REV0 || BOARD_REV > TROGDOR_REV_LAST -#error "Board revision out of range" -#endif - -#endif /* __CROS_EC_BOARD_REVS_H */ diff --git a/board/trogdor/build.mk b/board/trogdor/build.mk index c0a0e78c12..becaf09262 100644 --- a/board/trogdor/build.mk +++ b/board/trogdor/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,7 +8,12 @@ CHIP:=npcx CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m7wb +CHIP_VARIANT:=npcx7m6fc BASEBOARD:=trogdor -board-y=battery.o board.o led.o +board-y+=battery.o +board-y+=board.o +board-y+=hibernate.o +board-y+=led.o +board-y+=switchcap.o +board-y+=usbc_config.o diff --git a/board/trogdor/ec.tasklist b/board/trogdor/ec.tasklist index eb14fab204..97b5046f7f 100644 --- a/board/trogdor/ec.tasklist +++ b/board/trogdor/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/trogdor/gpio.inc b/board/trogdor/gpio.inc index e8b560f9a6..63d6e84963 100644 --- a/board/trogdor/gpio.inc +++ b/board/trogdor/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,26 +8,25 @@ /* Declare symbolic names for all the GPIOs that we care about. * Note: Those with interrupt handlers must be declared first. */ -/* USB-C interrupts */ +/* USB interrupts */ GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ -GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING, usb0_evt) /* Interrupt from port-0 BC1.2 */ -GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING, usb1_evt) /* Interrupt from port-1 BC1.2 */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb1_evt) /* Interrupt from port-1 BC1.2 */ +GPIO_INT(USB_A0_OC_ODL, PIN(D, 1), GPIO_INT_BOTH | GPIO_PULL_UP, usba_oc_interrupt) /* System interrupts */ -GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) /* AC OK? */ -GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ +GPIO_INT(CHG_ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ -GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) /* Lid open? */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ -GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ -GPIO_INT(PMIC_FAULT_L, PIN(A, 3), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) /* Any PMIC fault? */ -GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ /* * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down @@ -40,32 +39,26 @@ GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_wa GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ /* Sensor interrupts */ -GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) /* Accelerometer/gyro interrupt */ +GPIO_INT(TABLET_MODE_L, PIN(C, 6), GPIO_INT_BOTH, gmr_tablet_switch_isr) +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, bmi160_interrupt) /* Accelerometer/gyro interrupt */ /* - * EC_RST_ODL acts as a wake source from PSL hibernate mode. However, it does - * not need to be an interrupt for normal EC operations. Thus, configure it as - * GPIO_INT_BOTH with wake on low-to-high edge using GPIO_HIB_WAKE_HIGH so that - * PSL common code can configure PSL_IN correctly. - * - * Use the rising edge to wake EC up. If we chose the falling edge, it would - * still wake EC up, but EC is in an intermediate state until the signal goes - * back to high. + * EC_RST_ODL used to be a wake source from PSL mode. However, we disabled + * the PSL mode. This GPIO does nothing now. Simply set it an INPUT. */ -GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* Wake source: EC reset */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(CCD_MODE_ODL, PIN(E, 3), GPIO_INPUT) /* Case Closed Debug Mode */ GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ /* PMIC/AP 1.8V */ -GPIO(PMIC_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC reset trigger */ -GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* PMIC power button */ +GPIO(PMIC_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ -GPIO(QSIP_ON, PIN(5, 0), GPIO_OUT_LOW) /* Not used, for non-switchcap testing */ /* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ GPIO(SWITCHCAP_ON, PIN(D, 5), GPIO_OUT_LOW) /* Enable switch cap */ -/* TODO(waihong): Remove it. The VBOB switch is for backup. */ -GPIO(VBOB_EN, PIN(D, 3), GPIO_OUT_LOW) /* Enable VBOB */ GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ @@ -78,26 +71,29 @@ GPIO(TRACKPAD_INT_GATE, PIN(7, 4), GPIO_OUT_LOW) /* USB-C */ GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_OUT_HIGH) /* Port-0 TCPC chip reset */ -GPIO(USB_C1_PD_RST_ODL, PIN(E, 4), GPIO_ODR_HIGH) /* Port-1 TCPC chip reset */ -GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_OUT_HIGH) /* DP mux enable */ -GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_HIGH) /* DP mux selection: L:C0, H:C1 */ +GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_OUT_HIGH) /* Port-1 TCPC chip reset */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ -/* TODO(waihong): Remove it from schematic. No use. */ -GPIO(USBC_MUX_CONF0, PIN(5, 1), GPIO_INPUT) -GPIO(USB_C0_VBUS_DET_L, PIN(6, 2), GPIO_INPUT) /* Deprecated BC1.2 VBUS detection on port-0 */ -GPIO(USB_C1_VBUS_DET_L, PIN(8, 3), GPIO_INPUT) /* Deprecated BC1.2 VBUS detection on port-1 */ /* USB-A */ GPIO(EN_USB_A_5V, PIN(8, 6), GPIO_OUT_LOW) GPIO(USB_A_CDP_ILIM_EN_L, PIN(7, 5), GPIO_OUT_HIGH) /* H:CDP, L:SDP. Only one USB-A port, always CDP */ -GPIO(USB_A0_OC_ODL, PIN(D, 1), GPIO_ODR_HIGH) /* LEDs */ -GPIO(EC_CHG_LED_Y_C0, PIN(C, 3), GPIO_OUT_LOW) -GPIO(EC_CHG_LED_W_C0, PIN(C, 4), GPIO_OUT_LOW) -/* TODO(waihong): NC in the schematic. The C1 subboard doesn't have any LED. */ -GPIO(EC_CHG_LED_Y_C1, PIN(6, 0), GPIO_OUT_LOW) -GPIO(EC_CHG_LED_W_C1, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_Y_C0, PIN(6, 0), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_W_C0, PIN(C, 0), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_Y_C1, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_W_C1, PIN(C, 4), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) /* PWM */ GPIO(KB_BL_PWM, PIN(8, 0), GPIO_INPUT) /* PWM3 */ @@ -133,7 +129,36 @@ GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) * GPIO0 is configured as PVC_PG. When the chip in power down mode, it outputs * high-Z. Set pull-down to avoid floating. */ -GPIO(DA9313_GPIO0, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ +GPIO(SWITCHCAP_GPIO_1, PIN(E, 2), GPIO_INPUT | GPIO_PULL_DOWN) /* Switchcap GPIO0 */ + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(3, 7)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(7, 3)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(6, 2)) +UNUSED(PIN(0, 4)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(5, 0)) +UNUSED(PIN(D, 3)) /* Alternate functions GPIO definitions */ ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ @@ -147,10 +172,6 @@ ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* PWM3 (GPIO80) - KB_BL_PWM */ ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ -ALTERNATE(PIN_MASK(D, 0x04), 1, MODULE_PMU, 0) /* PSL_IN1 (GPIOD2) - LID_OPEN_EC */ -ALTERNATE(PIN_MASK(0, 0x01), 1, MODULE_PMU, 0) /* PSL_IN2 (GPIO00) - ACOK_OD */ -ALTERNATE(PIN_MASK(0, 0x02), 1, MODULE_PMU, 0) /* PSL_IN3 (GPIO01) - EC_PWR_BTN_ODL */ -ALTERNATE(PIN_MASK(0, 0x04), 1, MODULE_PMU, 0) /* PSL_IN4 (GPIO02) - EC_RST_ODL */ /* Keyboard */ #define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/trogdor/hibernate.c b/board/trogdor/hibernate.c new file mode 100644 index 0000000000..9b64e85053 --- /dev/null +++ b/board/trogdor/hibernate.c @@ -0,0 +1,16 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gpio.h" + +void board_hibernate(void) +{ + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + gpio_set_flags(GPIO_LID_ACCEL_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); +} diff --git a/board/trogdor/led.c b/board/trogdor/led.c index 3af5776e12..1fdab30f5a 100644 --- a/board/trogdor/led.c +++ b/board/trogdor/led.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -31,15 +31,15 @@ enum led_color { LED_OFF = 0, LED_AMBER, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static void side_led_set_color(int port, enum led_color color) { gpio_set_level(port ? GPIO_EC_CHG_LED_Y_C1 : GPIO_EC_CHG_LED_Y_C0, - (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_AMBER) ? BAT_LED_ON : BAT_LED_OFF); gpio_set_level(port ? GPIO_EC_CHG_LED_W_C1 : GPIO_EC_CHG_LED_W_C0, - (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); + (color == LED_WHITE) ? BAT_LED_ON : BAT_LED_OFF); } void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) @@ -90,20 +90,20 @@ static void set_active_port_color(enum led_color color) static void board_led_set_battery(void) { static int battery_ticks; - uint32_t chflags = charge_get_flags(); battery_ticks++; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Always indicate when charging, even in suspend. */ set_active_port_color(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { if (charge_get_percent() <= 10) - side_led_set_color(0, - (battery_ticks & 0x4) ? LED_WHITE : LED_OFF); + side_led_set_color(0, (battery_ticks & 0x4) ? + LED_WHITE : + LED_OFF); else side_led_set_color(0, LED_OFF); } @@ -111,19 +111,19 @@ static void board_led_set_battery(void) if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) side_led_set_color(1, LED_OFF); break; - case PWR_STATE_ERROR: - set_active_port_color((battery_ticks & 0x2) ? - LED_WHITE : LED_OFF); + case LED_PWRS_ERROR: + set_active_port_color((battery_ticks & 0x2) ? LED_WHITE : + LED_OFF); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: set_active_port_color(LED_WHITE); break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - set_active_port_color((battery_ticks & 0x4) ? - LED_AMBER : LED_OFF); - else - set_active_port_color(LED_WHITE); + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color((battery_ticks & 0x4) ? LED_AMBER : + LED_OFF); break; default: /* Other states don't alter LED behavior */ diff --git a/board/trogdor/switchcap.c b/board/trogdor/switchcap.c new file mode 100644 index 0000000000..5173e27f75 --- /dev/null +++ b/board/trogdor/switchcap.c @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gpio.h" +#include "power/qcom.h" + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON, enable); +} + +int board_is_switchcap_enabled(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_ON); +} + +int board_is_switchcap_power_good(void) +{ + return gpio_get_level(GPIO_SWITCHCAP_PG); +} diff --git a/board/trogdor/usbc_config.c b/board/trogdor/usbc_config.c new file mode 100644 index 0000000000..270c6c0d8f --- /dev/null +++ b/board/trogdor/usbc_config.c @@ -0,0 +1,365 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor board-specific USB-C configuration */ + +#include "bc12/pi3usb9201_public.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "common.h" +#include "config.h" +#include "gpio.h" +#include "hooks.h" +#include "ppc/sn5s330_public.h" +#include "system.h" +#include "tcpm/ps8xxx_public.h" +#include "tcpm/tcpci.h" +#include "timer.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usbc_config.h" +#include "usbc_ocp.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} + +/* GPIO Interrupt Handlers */ +void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_PD_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +void usb1_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void usba_oc_deferred(void) +{ + /* Use next number after all USB-C ports to indicate the USB-A port */ + board_overcurrent_event(CONFIG_USB_PD_PORT_MAX_COUNT, + !gpio_get_level(GPIO_USB_A0_OC_ODL)); +} +DECLARE_DEFERRED(usba_oc_deferred); + +void usba_oc_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&usba_oc_deferred_data, 0); +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + case GPIO_USB_C1_SWCTL_INT_ODL: + sn5s330_interrupt(1); + break; + default: + break; + } +} + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + } +}; + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A_5V, +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + { + .i2c_port = I2C_PORT_EEPROM, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/* Initialize board USC-C things */ +static void board_init_usbc(void) +{ + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + + /* Enable USB-A overcurrent interrupt */ + gpio_enable_interrupt(GPIO_USB_A0_OC_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_init_usbc, HOOK_PRIO_DEFAULT); + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); + msleep(PS8805_FW_INIT_DELAY_MS); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} diff --git a/board/trogdor/usbc_config.h b/board/trogdor/usbc_config.h new file mode 100644 index 0000000000..c9b676fc61 --- /dev/null +++ b/board/trogdor/usbc_config.h @@ -0,0 +1,19 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#include "gpio.h" + +void tcpc_alert_event(enum gpio_signal signal); +void usb0_evt(enum gpio_signal signal); +void usb1_evt(enum gpio_signal signal); +void usba_oc_interrupt(enum gpio_signal signal); +void ppc_interrupt(enum gpio_signal signal); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/trogdor/vif_override.xml b/board/trogdor/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/trogdor/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/trondo/battery.c b/board/trondo/battery.c deleted file mode 100644 index 9b356a8efd..0000000000 --- a/board/trondo/battery.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery_fuel_gauge.h" -#include "common.h" -#include "util.h" - -/* - * Battery info for all Volteer battery types. Note that the fields - * start_charging_min/max and charging_min/max are not used for the charger. - * The effective temperature limits are given by discharging_min/max_c. - * - * Fuel Gauge (FG) parameters which are used for determining if the battery - * is connected, the appropriate ship mode (battery cutoff) command, and the - * charge/discharge FETs status. - * - * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery - * register. For some batteries, the charge/discharge FET bits are set when - * charging/discharging is active, in other types, these bits set mean that - * charging/discharging is disabled. Therefore, in addition to the mask for - * these bits, a disconnect value must be specified. Note that for TI fuel - * gauge, the charge/discharge FET status is found in Operation Status (0x54), - * but a read of Manufacturer Access (0x00) will return the lower 16 bits of - * Operation status which contains the FET status bits. - * - * The assumption for battery types supported is that the charge/discharge FET - * status can be read with a sb_read() command and therefore, only the register - * address, mask, and disconnect value need to be provided. - */ -const struct board_batt_params board_battery_info[] = { - /* LGC\011 L17L3PB0 Battery Information */ - /* - * Battery info provided by ODM on b/143477210, comment #11 - */ - [BATTERY_LGC011] = { - .fuel_gauge = { - .manuf_name = "LGC", - .ship_mode = { - .reg_addr = 0x00, - .reg_data = { 0x10, 0x10 }, - }, - .fet = { - .reg_addr = 0x0, - .reg_mask = 0x6000, - .disconnect_val = 0x6000, - } - }, - .batt_info = { - .voltage_max = TARGET_WITH_MARGIN(13200, 5), - .voltage_normal = 11550, /* mV */ - .voltage_min = 9000, /* mV */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = 0, - .discharging_max_c = 75, - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); - -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC011; diff --git a/board/trondo/board.c b/board/trondo/board.c deleted file mode 100644 index 58c74283e4..0000000000 --- a/board/trondo/board.c +++ /dev/null @@ -1,453 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "common.h" -#include "accelgyro.h" -#include "cbi_ec_fw_config.h" -#include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi260.h" -#include "driver/als_tcs3400.h" -#include "driver/bc12/pi3usb9201.h" -#include "driver/ppc/sn5s330.h" -#include "driver/ppc/syv682x.h" -#include "driver/tcpm/tcpci.h" -#include "driver/tcpm/tusb422.h" -#include "driver/retimer/bb_retimer.h" -#include "driver/sync.h" -#include "extpower.h" -#include "fan.h" -#include "fan_chip.h" -#include "gpio.h" -#include "hooks.h" -#include "keyboard_scan.h" -#include "lid_switch.h" -#include "power.h" -#include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "tablet_mode.h" -#include "throttle_ap.h" -#include "uart.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usb_pd_tbt.h" -#include "usb_pd_tcpm.h" -#include "usbc_ppc.h" -#include "util.h" - -#include "gpio_list.h" /* Must come after other header files. */ - -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) - -/* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { - /* Increase from 50 us, because KSO_02 passes through the H1. */ - .output_settle_us = 80, - /* Other values should be the same as the default configuration. */ - .debounce_down_us = 9 * MSEC, - .debounce_up_us = 30 * MSEC, - .scan_period_us = 3 * MSEC, - .min_post_scan_delay_us = 1000, - .poll_timeout_us = 100 * MSEC, - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ - }, -}; - -/******************************************************************************/ -/* - * FW_CONFIG defaults for Trondo if the CBI data is not initialized. - */ -union volteer_cbi_fw_config fw_config_defaults = { - .usb_db = DB_USB3_PASSIVE, -}; - -static void board_init(void) -{ - /* Illuminate motherboard and daughter board LEDs equally to start. */ - pwm_enable(PWM_CH_LED4_SIDESEL, 1); - pwm_set_duty(PWM_CH_LED4_SIDESEL, 50); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) -{ - /* Routing length exceeds 205mm prior to connection to re-timer */ - if (port == USBC_PORT_C1) - return TBT_SS_U32_GEN1_GEN2; - - /* - * Thunderbolt-compatible mode not supported - * - * TODO (b/147726366): All the USB-C ports need to support same speed. - * Need to fix once USB-C feature set is known for Volteer. - */ - return TBT_SS_RES_0; -} - -__override bool board_is_tbt_usb4_port(int port) -{ - /* - * On Proto-1 only Port 1 supports TBT & USB4 - * - * TODO (b/147732807): All the USB-C ports need to support same - * features. Need to fix once USB-C feature set is known for Volteer. - */ - return port == USBC_PORT_C1; -} - -/******************************************************************************/ -/* Physical fans. These are logically separate from pwm_channels. */ - -const struct fan_conf fan_conf_0 = { - .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ - .pgood_gpio = -1, - .enable_gpio = GPIO_EN_PP5000_FAN, -}; - -/* - * Fan specs from datasheet: - * Max speed 5900 rpm (+/- 7%), minimum duty cycle 30%. - * Minimum speed not specified by RPM. Set minimum RPM to max speed (with - * margin) x 30%. - * 5900 x 1.07 x 0.30 = 1894, round up to 1900 - */ -const struct fan_rpm fan_rpm_0 = { - .rpm_min = 1900, - .rpm_start = 1900, - .rpm_max = 5900, -}; - -const struct fan_t fans[FAN_CH_COUNT] = { - [FAN_CH_0] = { - .conf = &fan_conf_0, - .rpm = &fan_rpm_0, - }, -}; - -/******************************************************************************/ -/* EC thermal management configuration */ - -/* - * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at - * 130 C. However, sensor is located next to DDR, so we need to use the lower - * DDR temperature limit (85 C) - */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; - -/* - * Inductor limits - used for both charger and PP3300 regulator - * - * Need to use the lower of the charger IC, PP3300 regulator, and the inductors - * - * Charger max recommended temperature 100C, max absolute temperature 125C - * PP3300 regulator: operating range -40 C to 145 C - * - * Inductors: limit of 125c - * PCB: limit is 80c - */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - - -struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, -}; -BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); - -/******************************************************************************/ -/* MFT channels. These are logically separate from pwm_channels. */ -const struct mft_t mft_channels[] = { - [MFT_CH_0] = { - .module = NPCX_MFT_MODULE_1, - .clk_src = TCKC_LFCLK, - .pwm_id = PWM_CH_FAN, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); - -/******************************************************************************/ -/* I2C port map configuration */ -const struct i2c_port_t i2c_ports[] = { - { - .name = "sensor", - .port = I2C_PORT_SENSOR, - .kbps = 400, - .scl = GPIO_EC_I2C0_SENSOR_SCL, - .sda = GPIO_EC_I2C0_SENSOR_SDA, - }, - { - .name = "usb_c0", - .port = I2C_PORT_USB_C0, - .kbps = 1000, - .scl = GPIO_EC_I2C1_USB_C0_SCL, - .sda = GPIO_EC_I2C1_USB_C0_SDA, - }, - { - .name = "usb_c1", - .port = I2C_PORT_USB_C1, - .kbps = 1000, - .scl = GPIO_EC_I2C2_USB_C1_SCL, - .sda = GPIO_EC_I2C2_USB_C1_SDA, - }, - { - .name = "usb_1_mix", - .port = I2C_PORT_USB_1_MIX, - .kbps = 100, - .scl = GPIO_EC_I2C3_USB_1_MIX_SCL, - .sda = GPIO_EC_I2C3_USB_1_MIX_SDA, - }, - { - .name = "power", - .port = I2C_PORT_POWER, - .kbps = 100, - .scl = GPIO_EC_I2C5_POWER_SCL, - .sda = GPIO_EC_I2C5_POWER_SDA, - }, - { - .name = "eeprom", - .port = I2C_PORT_EEPROM, - .kbps = 400, - .scl = GPIO_EC_I2C7_EEPROM_SCL, - .sda = GPIO_EC_I2C7_EEPROM_SDA, - }, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -/******************************************************************************/ -/* PWM configuration */ -const struct pwm_t pwm_channels[] = { - [PWM_CH_LED1_BLUE] = { - .channel = 2, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 2400, - }, - [PWM_CH_LED2_GREEN] = { - .channel = 0, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 2400, - }, - [PWM_CH_LED3_RED] = { - .channel = 1, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - .freq = 2400, - }, - [PWM_CH_LED4_SIDESEL] = { - .channel = 7, - .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP, - /* Run at a higher frequency than the color PWM signals to avoid - * timing-based color shifts. - */ - .freq = 4800, - }, - [PWM_CH_FAN] = { - .channel = 5, - .flags = PWM_CONFIG_OPEN_DRAIN, - .freq = 25000 - }, - [PWM_CH_KBLIGHT] = { - .channel = 3, - .flags = 0, - /* - * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent - * flicker. Higher frequencies consume similar average power to - * lower PWM frequencies, but higher frequencies record a much - * lower maximum power. - */ - .freq = 2400, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -void board_reset_pd_mcu(void) -{ - /* TODO(b/159025023): Trondo: check USB PD reset operation */ -} - -__override void board_cbi_init(void) -{ - /* TODO(b/159025023): Trondo: check FW_CONFIG fields for USB DB type */ -} - -/******************************************************************************/ -/* USBC PPC configuration */ -struct ppc_config_t ppc_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -/******************************************************************************/ -/* PPC support routines */ -void ppc_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_PPC_INT_ODL: - sn5s330_interrupt(USBC_PORT_C0); - break; - case GPIO_USB_C1_PPC_INT_ODL: - syv682x_interrupt(USBC_PORT_C1); - default: - break; - } -} - -/******************************************************************************/ -/* BC1.2 charger detect configuration */ -const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC TCPC configuration */ -struct tcpc_config_t tcpc_config[] = { - [USBC_PORT_C0] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C0, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), - }, - [USBC_PORT_C1] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); -BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usb_muxes[] = { - [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); - -struct bb_usb_control bb_controls[] = { - [USBC_PORT_C0] = { - /* USB-C port 0 doesn't have a retimer */ - }, - [USBC_PORT_C1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); - -static void board_tcpc_init(void) -{ - /* Don't reset TCPCs after initial reset */ - if (!system_jumped_late()) - board_reset_pd_mcu(); - - /* Enable PPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); - - /* Enable TCPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); - - /* Enable BC1.2 interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); - -/******************************************************************************/ -/* TCPC support routines */ -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - /* - * Check which port has the ALERT line set - */ - if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} - -int ppc_get_alert_status(int port) -{ - if (port == USBC_PORT_C0) - return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; - else - return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; -} - diff --git a/board/trondo/board.h b/board/trondo/board.h deleted file mode 100644 index c81bc1a5db..0000000000 --- a/board/trondo/board.h +++ /dev/null @@ -1,189 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer board configuration */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Baseboard features */ -#include "baseboard.h" - -/* Optional features */ -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ - -#define CONFIG_POWER_BUTTON - -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 4096 - -/* LED defines */ -#define CONFIG_LED_PWM -/* Although there are 2 LEDs, they are both controlled by the same lines. */ -#define CONFIG_LED_PWM_COUNT 1 - -/* Keyboard features */ - -/* Sensors */ -/* BMA253 accelerometer in base */ -#define CONFIG_ACCEL_BMA255 - -/* BMI260 accel/gyro in base */ -#define CONFIG_ACCELGYRO_BMI260 -#define CONFIG_ACCELGYRO_BMI260_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) - -/* TCS3400 ALS */ -#define CONFIG_ALS -#define ALS_COUNT 1 -#define CONFIG_ALS_TCS3400 -#define CONFIG_ALS_TCS3400_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) - -/* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) - -/* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 - -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - -/* - * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C - * cables only support up to 60W. - */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 - -/* Enabling Thunderbolt-compatible mode */ -#define CONFIG_USB_PD_TBT_COMPAT_MODE - -/* Enabling USB4 mode */ -#define CONFIG_USB_PD_USB4 -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 - -/* USB Type A Features */ - -/* USBC PPC*/ -#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ - -/* BC 1.2 */ - -/* Volume Button feature */ -/* - * TODO (b/149858568): remove CONFIG_BUTTONS_RUNTIME_CONFIG once board ID=0 - * support is stripped. - */ -#define CONFIG_BUTTONS_RUNTIME_CONFIG - -/* Fan features */ - -/* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 - -/* - * Macros for GPIO signals used in common code that don't match the - * schematic names. Signal names in gpio.inc match the schematic and are - * then redefined here to so it's more clear which signal is being used for - * which purpose. - */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PG_EC_DSW_PWROK GPIO_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L - -/* I2C Bus Configuration */ -#define CONFIG_I2C -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM - -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER - - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "registers.h" - -enum battery_type { - BATTERY_LGC011, - BATTERY_TYPE_COUNT, -}; - -enum pwm_channel { - PWM_CH_LED1_BLUE = 0, - PWM_CH_LED2_GREEN, - PWM_CH_LED3_RED, - PWM_CH_LED4_SIDESEL, - PWM_CH_FAN, - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; - -enum sensor_id { - LID_ACCEL = 0, - BASE_ACCEL, - BASE_GYRO, - CLEAR_ALS, - RGB_ALS, - SENSOR_COUNT, -}; - -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; - -void board_reset_pd_mcu(void); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/trondo/build.mk b/board/trondo/build.mk deleted file mode 100644 index b78172d3cf..0000000000 --- a/board/trondo/build.mk +++ /dev/null @@ -1,17 +0,0 @@ -# -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -CHIP:=npcx -CHIP_FAMILY:=npcx7 -CHIP_VARIANT:=npcx7m6fc -BASEBOARD:=volteer - -board-y=board.o -board-y+=battery.o -board-y+=led.o -board-y+=sensors.o diff --git a/board/trondo/ec.tasklist b/board/trondo/ec.tasklist deleted file mode 100644 index 292de51cdb..0000000000 --- a/board/trondo/ec.tasklist +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * See CONFIG_TASK_LIST in config.h for details. - */ - -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/trondo/gpio.inc b/board/trondo/gpio.inc deleted file mode 100644 index 4ea6194140..0000000000 --- a/board/trondo/gpio.inc +++ /dev/null @@ -1,171 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -/* Wake Source interrupts */ -GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) -GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) -GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) -GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) - -/* Power sequencing interrupts */ -GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 -GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) -#endif -GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) - -/* Sensor Interrupts */ -GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi260_interrupt) -GPIO_INT(EC_ALS_RGB_INT_L, PIN(D, 4), GPIO_INT_FALLING, tcs3400_interrupt) -GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) - -/* USB-C interrupts */ -GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) -GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) - -GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) -GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) - -GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) -GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) - -/* HDMI interrupts */ - -/* Volume button interrupts */ -GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -/* - * EC_VOLUP_BTN_ODL moved from GPIO75 to GPIO97 on boards with board ID >=1. - * GPIO97/EN_PP1050_BYPASS is DNS on board ID 0, and GPIO75 will be used once - * EFS support is added. - * TODO (b/149858568): remove board ID=0 support. - */ -GPIO_INT(EC_VOLUP_BTN_ODL_BOARDID_0, PIN(7, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) - -/* Power Sequencing Signals */ -GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) -GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) -GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ -/* The EC does not buffer this signal on Volteer. */ -UNIMPLEMENTED(PCH_DSW_PWROK) - -/* Other wake sources */ -/* - * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an - * interrupt handler because it is automatically handled by the PSL. - * - * We need to lock the setting so this gpio can't be reconfigured to overdrive - * the real reset signal. (This is the PSL input pin not the real reset pin). - */ -GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | - GPIO_HIB_WAKE_HIGH | - GPIO_LOCKED) - -/* AP/PCH Signals */ -GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) -GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ -GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) -GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) -GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) -GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) -GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) -GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) -GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) - -GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) - -/* USB and USBC Signals */ - -/* - * USB_C1 moved from GPIO32 to GPIO83 on boards with board ID >=1. - * GPIO83/EN_PP1800_A is DNS on board ID 0 and GPIO32 is N/C on board ID >=1 - * so it's safe to define GPIOs compatible with both designs. - * TODO (b/149858568): remove board ID=0 support. - */ -GPIO(USB_C1_RT_RST_ODL_BOARDID_0, PIN(3, 2), GPIO_ODR_LOW) /* USB_C1 Reset on boards without board ID */ -GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset on boards board ID >=1 */ -GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) -GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) - -/* Don't have a load switch for retimer */ -UNIMPLEMENTED(USB_C1_LS_EN) - -/* Misc Signals */ - -/* - * eDP backlight - both PCH and EC have enable pins that must be high - * for the backlight to turn on. Default state is high, and can be turned - * off during sleep states. - */ -GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) - -/* I2C pins - Alternate function below configures I2C module on these pins */ -GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) -GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) -GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) -GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) -GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) -GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) -GPIO(EC_I2C3_USB_1_MIX_SCL, PIN(D, 1), GPIO_INPUT) -GPIO(EC_I2C3_USB_1_MIX_SDA, PIN(D, 0), GPIO_INPUT) -GPIO(EC_I2C5_POWER_SCL, PIN(3, 3), GPIO_INPUT) -GPIO(EC_I2C5_POWER_SDA, PIN(3, 6), GPIO_INPUT) -GPIO(EC_I2C7_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) -GPIO(EC_I2C7_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) - -/* Battery signals */ -GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) - -/* Physical HPD pins are not needed on EC as these are configured by PMC */ -GPIO(USB_C0_DP_HPD, PIN(F, 3), GPIO_INPUT) -GPIO(USB_C1_DP_HPD, PIN(7, 0), GPIO_INPUT) - -/* Alternate functions GPIO definitions */ -ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */ -ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ -ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ -ALTERNATE(PIN_MASK(D, BIT(1) | BIT(0)), 0, MODULE_I2C, 0) /* I2C3 */ -ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ -ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ - -/* This selects between an LED module on the motherboard and one on the daughter - * board, to be controlled by LED_{1,2,3}_L. PWM allows driving both modules at - * the same time. */ -ALTERNATE(PIN_MASK(6, BIT(0)), 0, MODULE_PWM, 0) /* LED_SIDESEL_4_L */ -ALTERNATE(PIN_MASK(C, BIT(2) | BIT(3) | BIT(4)), 0, MODULE_PWM, 0) /* LED_{3,2,1}_L */ - -/* Fan signals */ -GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) -ALTERNATE(PIN_MASK(B, BIT(7)), 0, MODULE_PWM, 0) /* FAN_PWM */ -ALTERNATE(PIN_MASK(4, BIT(0)), 0, MODULE_PWM, 0) /* FAN_SPEED_TACH */ - -/* Keyboard pins */ -#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) -ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ -ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ -ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ -GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ -ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ -ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ -ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ -ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ - -/* UART */ -ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ - -/* Power Switch Logic (PSL) inputs */ -ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ -ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, - GPIO01 = H1_EC_PWR_BTN_ODL - GPIO02 = EC_RST_ODL */ - diff --git a/board/trondo/led.c b/board/trondo/led.c deleted file mode 100644 index 735df935d2..0000000000 --- a/board/trondo/led.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Power and battery LED control for Volteer - */ - -#include "charge_manager.h" -#include "common.h" -#include "ec_commands.h" -#include "hooks.h" -#include "led_common.h" -#include "led_pwm.h" -#include "pwm.h" - -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_POWER_LED, -}; -const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); - -struct pwm_led led_color_map[] = { - /* Red, Green, Blue */ - [EC_LED_COLOR_RED] = { 100, 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, - /* The green LED seems to be brighter than the others, so turn down - * green from its natural level for these secondary colors. - */ - [EC_LED_COLOR_YELLOW] = { 100, 70, 0 }, - [EC_LED_COLOR_WHITE] = { 100, 70, 100 }, - [EC_LED_COLOR_AMBER] = { 100, 20, 0 }, -}; - -struct pwm_led pwm_leds[] = { - /* 2 RGB diffusers controlled by 1 set of 3 channels. */ - [PWM_LED0] = { - .ch0 = PWM_CH_LED3_RED, - .ch1 = PWM_CH_LED2_GREEN, - .ch2 = PWM_CH_LED1_BLUE, - .enable = &pwm_enable, - .set_duty = &pwm_set_duty, - }, -}; - -void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) -{ - brightness_range[EC_LED_COLOR_RED] = 255; - brightness_range[EC_LED_COLOR_GREEN] = 255; - brightness_range[EC_LED_COLOR_BLUE] = 255; -} - -int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) -{ - enum pwm_led_id pwm_id; - - /* Convert ec_led_id to pwm_led_id. */ - if (led_id == EC_LED_ID_POWER_LED) - pwm_id = PWM_LED0; - else - return EC_ERROR_UNKNOWN; - - if (brightness[EC_LED_COLOR_RED]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_RED); - else if (brightness[EC_LED_COLOR_GREEN]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN); - else if (brightness[EC_LED_COLOR_BLUE]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE); - else if (brightness[EC_LED_COLOR_YELLOW]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_YELLOW); - else if (brightness[EC_LED_COLOR_WHITE]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE); - else if (brightness[EC_LED_COLOR_AMBER]) - set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER); - else - /* Otherwise, the "color" is "off". */ - set_pwm_led_color(pwm_id, -1); - - return EC_SUCCESS; -} - -/* Illuminates the LED on the side of the active charging port. If not charging, - * illuminates both LEDs. - */ -static void led_set_charge_port_tick(void) -{ - int port; - int side_select_duty; - - port = charge_manager_get_active_charge_port(); - switch (port) { - case 0: - side_select_duty = 100; - break; - case 1: - side_select_duty = 0; - break; - default: - side_select_duty = 50; - } - - pwm_set_duty(PWM_CH_LED4_SIDESEL, side_select_duty); -} -DECLARE_HOOK(HOOK_TICK, led_set_charge_port_tick, HOOK_PRIO_DEFAULT); diff --git a/board/trondo/sensors.c b/board/trondo/sensors.c deleted file mode 100644 index e9169abaae..0000000000 --- a/board/trondo/sensors.c +++ /dev/null @@ -1,229 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Volteer family-specific sensor configuration */ -#include "common.h" -#include "accelgyro.h" -#include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi_common.h" -#include "driver/accelgyro_bmi260.h" -#include "driver/als_tcs3400.h" -#include "driver/sync.h" -#include "keyboard_scan.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "util.h" - -/******************************************************************************/ -/* Sensors */ -static struct mutex g_lid_accel_mutex; -static struct mutex g_base_mutex; - -/* BMA253 private data */ -static struct accelgyro_saved_data_t g_bma253_data; - -/* BMI260 private data */ -static struct bmi_drv_data_t g_bmi260_data; - -/* TCS3400 private data */ -static struct als_drv_data_t g_tcs3400_data = { - .als_cal.scale = 1, - .als_cal.uscale = 0, - .als_cal.offset = 0, - .als_cal.channel_scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ - .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */ - }, -}; - -/* - * TODO: b/146166425 need to calibrate ALS/RGB sensor. At default settings, - * shining phone flashlight on sensor pegs all readings at 0xFFFF. - */ -static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { - .calibration.rgb_cal[X] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - } - }, - .calibration.rgb_cal[Y] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - }, - }, - .calibration.rgb_cal[Z] = { - .offset = 0, - .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), - .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), - .scale = { - .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ - .cover_scale = ALS_CHANNEL_SCALE(1.0) - } - }, - .calibration.irt = INT_TO_FP(1), - .saturation.again = TCS_DEFAULT_AGAIN, - .saturation.atime = TCS_DEFAULT_ATIME, -}; - -/* Rotation matrix for the lid accelerometer */ -/* TODO: b/146144170 - the accelerometer is on the motherboard for proto1 - * for testing. Once the sensor moves to the lid, the rotation matrix needs - * to be updated for correct behavior. - */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; - -struct motion_sensor_t motion_sensors[] = { - [LID_ACCEL] = { - .name = "Lid Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMA255, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &bma2x2_accel_drv, - .mutex = &g_lid_accel_mutex, - .drv_data = &g_bma253_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .min_frequency = BMA255_ACCEL_MIN_FREQ, - .max_frequency = BMA255_ACCEL_MAX_FREQ, - .default_range = 2, /* g, to support tablet mode */ - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - /* Sensor on in S3 */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - }, - }, - }, - [BASE_ACCEL] = { - .name = "Base Accel", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMI260, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_BASE, - .drv = &bmi260_drv, - .mutex = &g_base_mutex, - .drv_data = &g_bmi260_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, - .rot_standard_ref = &base_standard_ref, - .min_frequency = BMI_ACCEL_MIN_FREQ, - .max_frequency = BMI_ACCEL_MAX_FREQ, - .default_range = 4, /* g */ - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - /* Sensor on in S3 */ - [SENSOR_CONFIG_EC_S3] = { - .odr = 10000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, - }, - - [BASE_GYRO] = { - .name = "Base Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_BMI260, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_BASE, - .drv = &bmi260_drv, - .mutex = &g_base_mutex, - .drv_data = &g_bmi260_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, - .default_range = 1000, /* dps */ - .rot_standard_ref = &base_standard_ref, - .min_frequency = BMI_GYRO_MIN_FREQ, - .max_frequency = BMI_GYRO_MAX_FREQ, - }, - [CLEAR_ALS] = { - .name = "Clear Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT, - .location = MOTIONSENSE_LOC_BASE, - .drv = &tcs3400_drv, - .drv_data = &g_tcs3400_data, - .port = I2C_PORT_SENSOR, - .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - .min_frequency = TCS3400_LIGHT_MIN_FREQ, - .max_frequency = TCS3400_LIGHT_MAX_FREQ, - .config = { - /* Run ALS sensor in S0 */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 1000, - }, - }, - }, - - [RGB_ALS] = { - /* - * RGB channels read by CLEAR_ALS and so the i2c port and - * address do not need to be defined for RGB_ALS. - */ - .name = "RGB Light", - .active_mask = SENSOR_ACTIVE_S0_S3, - .chip = MOTIONSENSE_CHIP_TCS3400, - .type = MOTIONSENSE_TYPE_LIGHT_RGB, - .location = MOTIONSENSE_LOC_BASE, - .drv = &tcs3400_rgb_drv, - .drv_data = &g_tcs3400_rgb_data, - .rot_standard_ref = NULL, - .default_range = 0x10000, /* scale = 1x, uscale = 0 */ - }, -}; -unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ -const struct motion_sensor_t *motion_als_sensors[] = { - &motion_sensors[CLEAR_ALS], -}; -BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); - -static void baseboard_sensors_init(void) -{ - /* Note - BMA253 interrupt unused by EC */ - - /* Enable interrupt for the TCS3400 color light sensor */ - gpio_enable_interrupt(GPIO_EC_ALS_RGB_INT_L); - /* Enable interrupt for the BMI260 accel/gyro sensor */ - gpio_enable_interrupt(GPIO_EC_IMU_INT_L); -} -DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); diff --git a/board/twinkie/board.c b/board/twinkie/board.c index b50307397a..ffc3746432 100644 --- a/board/twinkie/board.c +++ b/board/twinkie/board.c @@ -1,11 +1,10 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Twinkie dongle configuration */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "console.h" #include "ec_version.h" @@ -28,6 +27,7 @@ void vbus_event(enum gpio_signal signal) ccprintf("INA!\n"); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* Initialize board. */ @@ -37,7 +37,7 @@ void board_config_pre_init(void) STM32_RCC_APB2ENR |= BIT(0); /* Remap USART DMA to match the USART driver and TIM2 DMA */ STM32_SYSCFG_CFGR1 |= BIT(9) | BIT(10) /* Remap USART1 RX/TX DMA */ - | BIT(29);/* Remap TIM2 DMA */ + | BIT(29); /* Remap TIM2 DMA */ /* 40 MHz pin speed on UART PA9/PA10 */ STM32_GPIO_OSPEEDR(GPIO_A) |= 0x003C0000; /* 40 MHz pin speed on TX clock out PB9 */ @@ -60,20 +60,24 @@ DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); /* ADC channels */ const struct adc_t adc_channels[] = { /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_CH_CC1_PD] = {"CC1_PD", 3300, 4096, 0, STM32_AIN(1)}, - [ADC_CH_CC2_PD] = {"CC2_PD", 3300, 4096, 0, STM32_AIN(3)}, + [ADC_CH_CC1_PD] = { "CC1_PD", 3300, 4096, 0, STM32_AIN(1) }, + [ADC_CH_CC2_PD] = { "CC2_PD", 3300, 4096, 0, STM32_AIN(3) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, GPIO_I2C_SCL, GPIO_I2C_SDA}, + { .name = "master", + .port = I2C_PORT_MASTER, + .kbps = 100, + .scl = GPIO_I2C_SCL, + .sda = GPIO_I2C_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -const void * const usb_strings[] = { +const void *const usb_strings[] = { [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), + [USB_STR_VENDOR] = USB_STRING_DESC("Google LLC"), [USB_STR_PRODUCT] = USB_STRING_DESC("Twinkie"), [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), [USB_STR_SNIFFER] = USB_STRING_DESC("USB-PD Sniffer"), diff --git a/board/twinkie/board.h b/board/twinkie/board.h index b5756fda34..808053d146 100644 --- a/board/twinkie/board.h +++ b/board/twinkie/board.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -42,7 +42,7 @@ #define CONFIG_ADC #define CONFIG_BOARD_PRE_INIT #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER #define CONFIG_INA231 #undef CONFIG_WATCHDOG_HELP #undef CONFIG_LID_SWITCH @@ -54,7 +54,7 @@ /* USB configuration */ #define CONFIG_USB_PID 0x500A /* By default, enable all console messages excepted USB */ -#define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_USB)) +#define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_USB)) /* * Allow dangerous commands all the time, since we don't have a write protect @@ -79,9 +79,8 @@ void trace_packets(void); void set_trace_mode(int mode); /* Timer selection */ -#define TIM_CLOCK_MSB 3 -#define TIM_CLOCK_LSB 15 -#define TIM_ADC 16 +#define TIM_CLOCK32 2 +#define TIM_ADC 16 #include "gpio_signal.h" @@ -106,28 +105,28 @@ enum usb_strings { }; /* Standard-current Rp */ -#define PD_SRC_VNC PD_SRC_DEF_VNC_MV -#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV +#define PD_SRC_VNC PD_SRC_DEF_VNC_MV +#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV /* delay necessary for the voltage transition on the power supply */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 #endif /* !__ASSEMBLER__ */ /* USB interface indexes (use define rather than enum to expand them) */ #define USB_IFACE_CONSOLE 0 -#define USB_IFACE_VENDOR 1 +#define USB_IFACE_VENDOR 1 /* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_CONSOLE 1 +#define USB_EP_CONTROL 0 +#define USB_EP_CONSOLE 1 /* * Endpoint 2 is missing because the console used to use two bidirectional @@ -137,13 +136,13 @@ enum usb_strings { */ #ifdef HAS_TASK_SNIFFER -#define USB_EP_SNIFFER 3 -#define USB_EP_COUNT 4 -#define USB_IFACE_COUNT 2 +#define USB_EP_SNIFFER 3 +#define USB_EP_COUNT 4 +#define USB_IFACE_COUNT 2 #else -#define USB_EP_COUNT 2 +#define USB_EP_COUNT 2 /* No IFACE_VENDOR for the sniffer */ -#define USB_IFACE_COUNT 1 +#define USB_IFACE_COUNT 1 #endif #endif /* __CROS_EC_BOARD_H */ diff --git a/board/twinkie/build.mk b/board/twinkie/build.mk index 6fc2067d8f..f710000486 100644 --- a/board/twinkie/build.mk +++ b/board/twinkie/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,5 +10,5 @@ CHIP:=stm32 CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f07x -board-y=board.o usb_pd_policy.o injector.o simpletrace.o +board-y=board.o usb_pd_policy.o injector.o simpletrace.o usb_pd_pdo.o board-$(HAS_TASK_SNIFFER)+=sniffer.o diff --git a/board/twinkie/ec.tasklist b/board/twinkie/ec.tasklist index 600df47c60..0dcfd38308 100644 --- a/board/twinkie/ec.tasklist +++ b/board/twinkie/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/twinkie/gpio.inc b/board/twinkie/gpio.inc index 551cb73748..45b34de766 100644 --- a/board/twinkie/gpio.inc +++ b/board/twinkie/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/twinkie/injector.c b/board/twinkie/injector.c index cae1d3557f..7688b68128 100644 --- a/board/twinkie/injector.c +++ b/board/twinkie/injector.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -48,26 +48,31 @@ static const struct res_cfg { uint32_t flags; } cfgs[2]; } res_cfg[] = { - [INJ_RES_NONE] = {"NONE"}, - [INJ_RES_RA] = {"RA", {{GPIO_CC1_RA, GPIO_ODR_LOW}, - {GPIO_CC2_RA, GPIO_ODR_LOW} } }, - [INJ_RES_RD] = {"RD", {{GPIO_CC1_RD, GPIO_ODR_LOW}, - {GPIO_CC2_RD, GPIO_ODR_LOW} } }, - [INJ_RES_RPUSB] = {"RPUSB", {{GPIO_CC1_RPUSB, GPIO_OUT_HIGH}, - {GPIO_CC2_RPUSB, GPIO_OUT_HIGH} } }, - [INJ_RES_RP1A5] = {"RP1A5", {{GPIO_CC1_RP1A5, GPIO_OUT_HIGH}, - {GPIO_CC2_RP1A5, GPIO_OUT_HIGH} } }, - [INJ_RES_RP3A0] = {"RP3A0", {{GPIO_CC1_RP3A0, GPIO_OUT_HIGH}, - {GPIO_CC2_RP3A0, GPIO_OUT_HIGH} } }, + [INJ_RES_NONE] = { "NONE" }, + [INJ_RES_RA] = { "RA", + { { GPIO_CC1_RA, GPIO_ODR_LOW }, + { GPIO_CC2_RA, GPIO_ODR_LOW } } }, + [INJ_RES_RD] = { "RD", + { { GPIO_CC1_RD, GPIO_ODR_LOW }, + { GPIO_CC2_RD, GPIO_ODR_LOW } } }, + [INJ_RES_RPUSB] = { "RPUSB", + { { GPIO_CC1_RPUSB, GPIO_OUT_HIGH }, + { GPIO_CC2_RPUSB, GPIO_OUT_HIGH } } }, + [INJ_RES_RP1A5] = { "RP1A5", + { { GPIO_CC1_RP1A5, GPIO_OUT_HIGH }, + { GPIO_CC2_RP1A5, GPIO_OUT_HIGH } } }, + [INJ_RES_RP3A0] = { "RP3A0", + { { GPIO_CC1_RP3A0, GPIO_OUT_HIGH }, + { GPIO_CC2_RP3A0, GPIO_OUT_HIGH } } }, }; -#define CC_RA(cc) (cc < PD_SRC_RD_THRESHOLD) +#define CC_RA(cc) (cc < PD_SRC_RD_THRESHOLD) #define CC_RD(cc) ((cc > PD_SRC_RD_THRESHOLD) && (cc < PD_SRC_VNC)) #define GET_POLARITY(cc1, cc2) (CC_RD(cc2) || CC_RA(cc1)) #ifdef HAS_TASK_SNIFFER /* we don't have the default DMA handlers */ -void dma_event_interrupt_channel_3(void) +static void dma_event_interrupt_channel_3(void) { if (STM32_DMA1_REGS->isr & STM32_DMA_ISR_TCIF(STM32_DMAC_CH3)) { dma_clear_isr(STM32_DMAC_CH3); @@ -103,8 +108,8 @@ static inline void enable_tracing_ifneeded(int flag) pd_rx_enable_monitoring(0); } -static int send_message(int polarity, uint16_t header, - uint8_t cnt, const uint32_t *data) +static int send_message(int polarity, uint16_t header, uint8_t cnt, + const uint32_t *data) { int bit_len; @@ -215,7 +220,7 @@ static void fsm_wait(uint32_t w) uint32_t timeout_ms = INJ_ARG0(w); uint32_t min_edges = INJ_ARG12(w); - wait_packet(inj_polarity, min_edges, timeout_ms * 1000); + wait_packet(inj_polarity, min_edges, timeout_ms * 1000); #endif } @@ -224,7 +229,7 @@ static void fsm_expect(uint32_t w) uint32_t timeout_ms = INJ_ARG0(w); uint8_t cmd = INJ_ARG2(w); - expect_packet(inj_polarity, cmd, timeout_ms * 1000); + expect_packet(inj_polarity, cmd, timeout_ms * 1000); } static void fsm_get(uint32_t w) { @@ -242,11 +247,11 @@ static void fsm_get(uint32_t w) break; case INJ_GET_VBUS: *store_ptr = (ina2xx_get_voltage(0) & 0xffff) | - ((ina2xx_get_current(0) & 0xffff) << 16); + ((ina2xx_get_current(0) & 0xffff) << 16); break; case INJ_GET_VCONN: *store_ptr = (ina2xx_get_voltage(1) & 0xffff) | - ((ina2xx_get_current(1) & 0xffff) << 16); + ((ina2xx_get_current(1) & 0xffff) << 16); break; case INJ_GET_POLARITY: *store_ptr = inj_polarity; @@ -336,9 +341,9 @@ static int fsm_run(int index) /* ------ Console commands ------ */ -static int hex8tou32(char *str, uint32_t *val) +static int hex8tou32(const char *str, uint32_t *val) { - char *ptr = str; + const char *ptr = str; uint32_t tmp = 0; while (*ptr) { @@ -358,7 +363,7 @@ static int hex8tou32(char *str, uint32_t *val) return EC_SUCCESS; } -static int cmd_fsm(int argc, char **argv) +static int cmd_fsm(int argc, const char **argv) { int index; char *e; @@ -375,8 +380,7 @@ static int cmd_fsm(int argc, char **argv) return EC_SUCCESS; } - -static int cmd_send(int argc, char **argv) +static int cmd_send(int argc, const char **argv) { int pol, cnt, i; uint16_t header; @@ -396,7 +400,7 @@ static int cmd_send(int argc, char **argv) return EC_ERROR_PARAM3; for (i = 0; i < cnt; i++) - if (hex8tou32(argv[i+2], data + i)) + if (hex8tou32(argv[i + 2], data + i)) return EC_ERROR_INVAL; bit_len = send_message(pol, header, cnt, data); @@ -405,15 +409,15 @@ static int cmd_send(int argc, char **argv) return EC_SUCCESS; } -static int cmd_cc_level(int argc, char **argv) +static int cmd_cc_level(int argc, const char **argv) { - ccprintf("CC1 = %d mV ; CC2 = %d mV\n", - pd_adc_read(0, 0), pd_adc_read(0, 1)); + ccprintf("CC1 = %d mV ; CC2 = %d mV\n", pd_adc_read(0, 0), + pd_adc_read(0, 1)); return EC_SUCCESS; } -static int cmd_resistor(int argc, char **argv) +static int cmd_resistor(int argc, const char **argv) { int p, r; @@ -435,7 +439,7 @@ static int cmd_resistor(int argc, char **argv) return EC_SUCCESS; } -static int cmd_tx_clock(int argc, char **argv) +static int cmd_tx_clock(int argc, const char **argv) { int freq; char *e; @@ -452,7 +456,7 @@ static int cmd_tx_clock(int argc, char **argv) return EC_SUCCESS; } -static int cmd_rx_threshold(int argc, char **argv) +static int cmd_rx_threshold(int argc, const char **argv) { int mv; char *e; @@ -471,7 +475,7 @@ static int cmd_rx_threshold(int argc, char **argv) return EC_SUCCESS; } -static int cmd_ina_dump(int argc, char **argv, int index) +static int cmd_ina_dump(int argc, const char **argv, int index) { if (index == 1) { /* VCONN INA is off by default, switch it on */ ina2xx_write(index, INA2XX_REG_CONFIG, 0x4123); @@ -483,7 +487,7 @@ static int cmd_ina_dump(int argc, char **argv, int index) } ccprintf("%s = %d mV ; %d mA\n", index == 0 ? "VBUS" : "VCONN", - ina2xx_get_voltage(index), ina2xx_get_current(index)); + ina2xx_get_voltage(index), ina2xx_get_current(index)); if (index == 1) /* power off VCONN INA */ ina2xx_write(index, INA2XX_REG_CONFIG, 0); @@ -491,7 +495,7 @@ static int cmd_ina_dump(int argc, char **argv, int index) return EC_SUCCESS; } -static int cmd_bufwr(int argc, char **argv) +static int cmd_bufwr(int argc, const char **argv) { int idx, cnt, i; char *e; @@ -505,13 +509,13 @@ static int cmd_bufwr(int argc, char **argv) return EC_ERROR_PARAM2; for (i = 0; i < cnt; i++) - if (hex8tou32(argv[i+1], inj_cmds + idx + i)) + if (hex8tou32(argv[i + 1], inj_cmds + idx + i)) return EC_ERROR_INVAL; return EC_SUCCESS; } -static int cmd_bufrd(int argc, char **argv) +static int cmd_bufrd(int argc, const char **argv) { int idx, i; int cnt = 1; @@ -537,7 +541,7 @@ static int cmd_bufrd(int argc, char **argv) return EC_SUCCESS; } -static int cmd_sink(int argc, char **argv) +static int cmd_sink(int argc, const char **argv) { /* * Jump to the RW section which should contain a firmware acting @@ -548,18 +552,16 @@ static int cmd_sink(int argc, char **argv) return EC_SUCCESS; } -static int cmd_trace(int argc, char **argv) +static int cmd_trace(int argc, const char **argv) { if (argc < 1) return EC_ERROR_PARAM_COUNT; - if (!strcasecmp(argv[0], "on") || - !strcasecmp(argv[0], "1")) + if (!strcasecmp(argv[0], "on") || !strcasecmp(argv[0], "1")) set_trace_mode(TRACE_MODE_ON); else if (!strcasecmp(argv[0], "raw")) set_trace_mode(TRACE_MODE_RAW); - else if (!strcasecmp(argv[0], "off") || - !strcasecmp(argv[0], "0")) + else if (!strcasecmp(argv[0], "off") || !strcasecmp(argv[0], "0")) set_trace_mode(TRACE_MODE_OFF); else return EC_ERROR_PARAM2; @@ -567,7 +569,7 @@ static int cmd_trace(int argc, char **argv) return EC_SUCCESS; } -static int command_tw(int argc, char **argv) +static int command_tw(int argc, const char **argv) { if (!strcasecmp(argv[1], "send")) return cmd_send(argc - 2, argv + 2); diff --git a/board/twinkie/injector.h b/board/twinkie/injector.h index 4a33f8ecf0..ed39522969 100644 --- a/board/twinkie/injector.h +++ b/board/twinkie/injector.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -21,50 +21,50 @@ /* Macros to extract values from FSM command words */ #define INJ_CMD(w) ((w) >> 28) -#define INJ_ARG(w) ((w) & 0x0FFFFFFF) -#define INJ_ARG0(w) ((w) & 0x0000FFFF) +#define INJ_ARG(w) ((w)&0x0FFFFFFF) +#define INJ_ARG0(w) ((w)&0x0000FFFF) #define INJ_ARG1(w) (((w) >> 16) & 0xFF) #define INJ_ARG2(w) (((w) >> 24) & 0xF) #define INJ_ARG12(w) (((w) >> 16) & 0xFFF) enum inj_cmd { - INJ_CMD_END = 0x0, /* stop the FSM */ - INJ_CMD_SEND = 0x1, /* Send message on CCx */ - /* arg0: header arg1/2:payload index/count */ - INJ_CMD_WAVE = 0x2, /* Send arbitrary waveform */ - /* stored at index arg1 of len arg0 */ - INJ_CMD_HRST = 0x3, /* Send Hard Reset on CCx */ - INJ_CMD_WAIT = 0x4, /* Wait for arg12 edges if arg12 != 0 */ - /* and timeout after arg0 ms */ - INJ_CMD_GET = 0x5, /* Get parameter arg1 (INJ_GET_x) at index arg0 */ - INJ_CMD_SET = 0x6, /* Set parameter arg1 (INJ_SET_x) with arg0 */ - INJ_CMD_JUMP = 0x8, /* Jump to index (as arg0) */ + INJ_CMD_END = 0x0, /* stop the FSM */ + INJ_CMD_SEND = 0x1, /* Send message on CCx */ + /* arg0: header arg1/2:payload index/count */ + INJ_CMD_WAVE = 0x2, /* Send arbitrary waveform */ + /* stored at index arg1 of len arg0 */ + INJ_CMD_HRST = 0x3, /* Send Hard Reset on CCx */ + INJ_CMD_WAIT = 0x4, /* Wait for arg12 edges if arg12 != 0 */ + /* and timeout after arg0 ms */ + INJ_CMD_GET = 0x5, /* Get parameter arg1 (INJ_GET_x) at index arg0 */ + INJ_CMD_SET = 0x6, /* Set parameter arg1 (INJ_SET_x) with arg0 */ + INJ_CMD_JUMP = 0x8, /* Jump to index (as arg0) */ INJ_CMD_EXPCT = 0xC, /* Expect a packet with command arg2 */ - /* and timeout after arg0 ms */ - INJ_CMD_NOP = 0xF, /* No-Operation */ + /* and timeout after arg0 ms */ + INJ_CMD_NOP = 0xF, /* No-Operation */ }; enum inj_set { - INJ_SET_RESISTOR1 = 0, /* CC1 resistor as arg0 (INJ_RES_x) */ - INJ_SET_RESISTOR2 = 1, /* CC2 resistor as arg0 (INJ_RES_x) */ - INJ_SET_RECORD = 2, /* Recording on/off */ - INJ_SET_TX_SPEED = 3, /* TX frequency is arg0 kHz */ - INJ_SET_RX_THRESH = 4, /* RX voltage threshold is arg0 mV */ - INJ_SET_POLARITY = 5, /* Polarity for other operations (INJ_POL_CC) */ - INJ_SET_TRACE = 6, /* Text packet trace on/raw/off */ + INJ_SET_RESISTOR1 = 0, /* CC1 resistor as arg0 (INJ_RES_x) */ + INJ_SET_RESISTOR2 = 1, /* CC2 resistor as arg0 (INJ_RES_x) */ + INJ_SET_RECORD = 2, /* Recording on/off */ + INJ_SET_TX_SPEED = 3, /* TX frequency is arg0 kHz */ + INJ_SET_RX_THRESH = 4, /* RX voltage threshold is arg0 mV */ + INJ_SET_POLARITY = 5, /* Polarity for other operations (INJ_POL_CC) */ + INJ_SET_TRACE = 6, /* Text packet trace on/raw/off */ }; enum inj_get { - INJ_GET_CC = 0, /* CC1/CC2 voltages in mV */ - INJ_GET_VBUS = 1, /* VBUS voltage in mV and current in mA */ - INJ_GET_VCONN = 2, /* VCONN voltage in mV and current in mA */ + INJ_GET_CC = 0, /* CC1/CC2 voltages in mV */ + INJ_GET_VBUS = 1, /* VBUS voltage in mV and current in mA */ + INJ_GET_VCONN = 2, /* VCONN voltage in mV and current in mA */ INJ_GET_POLARITY = 3, /* Current polarity (INJ_POL_CC) */ }; enum inj_res { - INJ_RES_NONE = 0, - INJ_RES_RA = 1, - INJ_RES_RD = 2, + INJ_RES_NONE = 0, + INJ_RES_RA = 1, + INJ_RES_RD = 2, INJ_RES_RPUSB = 3, INJ_RES_RP1A5 = 4, INJ_RES_RP3A0 = 5, @@ -79,7 +79,7 @@ enum inj_pol { enum trace_mode { TRACE_MODE_OFF = 0, TRACE_MODE_RAW = 1, - TRACE_MODE_ON = 2, + TRACE_MODE_ON = 2, }; /* Number of words in the FSM command/data buffer */ diff --git a/board/twinkie/simpletrace.c b/board/twinkie/simpletrace.c index f68a09adcf..fdc4cbfbb2 100644 --- a/board/twinkie/simpletrace.c +++ b/board/twinkie/simpletrace.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,6 +11,7 @@ #include "hooks.h" #include "hwtimer.h" #include "injector.h" +#include "printf.h" #include "registers.h" #include "system.h" #include "task.h" @@ -25,61 +26,57 @@ int trace_mode; /* The FSM is waiting for the following command (0 == None) */ uint8_t expected_cmd; -static const char * const ctrl_msg_name[] = { - [0] = "RSVD-C0", - [PD_CTRL_GOOD_CRC] = "GOODCRC", - [PD_CTRL_GOTO_MIN] = "GOTOMIN", - [PD_CTRL_ACCEPT] = "ACCEPT", - [PD_CTRL_REJECT] = "REJECT", - [PD_CTRL_PING] = "PING", - [PD_CTRL_PS_RDY] = "PSRDY", +static const char *const ctrl_msg_name[] = { + [0] = "RSVD-C0", + [PD_CTRL_GOOD_CRC] = "GOODCRC", + [PD_CTRL_GOTO_MIN] = "GOTOMIN", + [PD_CTRL_ACCEPT] = "ACCEPT", + [PD_CTRL_REJECT] = "REJECT", + [PD_CTRL_PING] = "PING", + [PD_CTRL_PS_RDY] = "PSRDY", [PD_CTRL_GET_SOURCE_CAP] = "GSRCCAP", - [PD_CTRL_GET_SINK_CAP] = "GSNKCAP", - [PD_CTRL_DR_SWAP] = "DRSWAP", - [PD_CTRL_PR_SWAP] = "PRSWAP", - [PD_CTRL_VCONN_SWAP] = "VCONNSW", - [PD_CTRL_WAIT] = "WAIT", - [PD_CTRL_SOFT_RESET] = "SFT-RST", - [14] = "RSVD-C14", - [15] = "RSVD-C15", + [PD_CTRL_GET_SINK_CAP] = "GSNKCAP", + [PD_CTRL_DR_SWAP] = "DRSWAP", + [PD_CTRL_PR_SWAP] = "PRSWAP", + [PD_CTRL_VCONN_SWAP] = "VCONNSW", + [PD_CTRL_WAIT] = "WAIT", + [PD_CTRL_SOFT_RESET] = "SFT-RST", + [14] = "RSVD-C14", + [15] = "RSVD-C15", }; -static const char * const data_msg_name[] = { - [0] = "RSVD-D0", - [PD_DATA_SOURCE_CAP] = "SRCCAP", - [PD_DATA_REQUEST] = "REQUEST", - [PD_DATA_BIST] = "BIST", - [PD_DATA_SINK_CAP] = "SNKCAP", +static const char *const data_msg_name[] = { + [0] = "RSVD-D0", + [PD_DATA_SOURCE_CAP] = "SRCCAP", + [PD_DATA_REQUEST] = "REQUEST", + [PD_DATA_BIST] = "BIST", + [PD_DATA_SINK_CAP] = "SNKCAP", /* 5-14 Reserved */ - [PD_DATA_VENDOR_DEF] = "VDM", + [PD_DATA_VENDOR_DEF] = "VDM", }; -static const char * const svdm_cmd_name[] = { - [CMD_DISCOVER_IDENT] = "DISCID", - [CMD_DISCOVER_SVID] = "DISCSVID", - [CMD_DISCOVER_MODES] = "DISCMODE", - [CMD_ENTER_MODE] = "ENTER", - [CMD_EXIT_MODE] = "EXIT", - [CMD_ATTENTION] = "ATTN", - [CMD_DP_STATUS] = "DPSTAT", - [CMD_DP_CONFIG] = "DPCFG", +static const char *const svdm_cmd_name[] = { + [CMD_DISCOVER_IDENT] = "DISCID", [CMD_DISCOVER_SVID] = "DISCSVID", + [CMD_DISCOVER_MODES] = "DISCMODE", [CMD_ENTER_MODE] = "ENTER", + [CMD_EXIT_MODE] = "EXIT", [CMD_ATTENTION] = "ATTN", + [CMD_DP_STATUS] = "DPSTAT", [CMD_DP_CONFIG] = "DPCFG", }; -static const char * const svdm_cmdt_name[] = { - [CMDT_INIT] = "INI", - [CMDT_RSP_ACK] = "ACK", - [CMDT_RSP_NAK] = "NAK", +static const char *const svdm_cmdt_name[] = { + [CMDT_INIT] = "INI", + [CMDT_RSP_ACK] = "ACK", + [CMDT_RSP_NAK] = "NAK", [CMDT_RSP_BUSY] = "BSY", }; static void print_pdo(uint32_t word) { if ((word & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) - ccprintf(" %dmV/%dmW", ((word>>10)&0x3ff)*50, - (word&0x3ff)*250); + ccprintf(" %dmV/%dmW", ((word >> 10) & 0x3ff) * 50, + (word & 0x3ff) * 250); else - ccprintf(" %dmV/%dmA", ((word>>10)&0x3ff)*50, - (word&0x3ff)*10); + ccprintf(" %dmV/%dmA", ((word >> 10) & 0x3ff) * 50, + (word & 0x3ff) * 10); } static void print_rdo(uint32_t word) @@ -109,9 +106,11 @@ static void print_packet(int head, uint32_t *payload) int id = PD_HEADER_ID(head); const char *name; const char *prole; + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; if (trace_mode == TRACE_MODE_RAW) { - ccprintf("%pT[%04x]", PRINTF_TIMESTAMP_NOW, head); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + ccprintf("%s[%04x]", ts_str, head); for (i = 0; i < cnt; i++) ccprintf(" %08x", payload[i]); ccputs("\n"); @@ -119,8 +118,8 @@ static void print_packet(int head, uint32_t *payload) } name = cnt ? data_msg_name[typ] : ctrl_msg_name[typ]; prole = head & (PD_ROLE_SOURCE << 8) ? "SRC" : "SNK"; - ccprintf("%pT %s/%d [%04x]%s", - PRINTF_TIMESTAMP_NOW, prole, id, head, name); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + ccprintf("%s %s/%d [%04x]%s", ts_str, prole, id, head, name); if (!cnt) { /* Control message : we are done */ ccputs("\n"); return; @@ -144,27 +143,32 @@ static void print_packet(int head, uint32_t *payload) break; default: ccprintf(" %08x", payload[i]); - } + } ccputs("\n"); } static void print_error(enum pd_rx_errors err) { + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; + + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + if (err == PD_RX_ERR_INVAL) - ccprintf("%pT TMOUT\n", PRINTF_TIMESTAMP_NOW); + ccprintf("%s TMOUT\n", ts_str); else if (err == PD_RX_ERR_HARD_RESET) - ccprintf("%pT HARD-RST\n", PRINTF_TIMESTAMP_NOW); + ccprintf("%s HARD-RST\n", ts_str); else if (err == PD_RX_ERR_UNSUPPORTED_SOP) - ccprintf("%pT SOP*\n", PRINTF_TIMESTAMP_NOW); + ccprintf("%s SOP*\n", ts_str); else ccprintf("ERR %d\n", err); } +#ifdef HAS_TASK_SNIFFER /* keep track of RX edge timing in order to trigger receive */ static timestamp_t rx_edge_ts[2][PD_RX_TRANSITION_COUNT]; static int rx_edge_ts_idx[2]; -void rx_event(void) +static void rx_event(void) { int pending, i; int next_idx; @@ -175,19 +179,20 @@ void rx_event(void) if (pending & (1 << (21 + i))) { rx_edge_ts[i][rx_edge_ts_idx[i]].val = get_time().val; next_idx = (rx_edge_ts_idx[i] == - PD_RX_TRANSITION_COUNT - 1) ? - 0 : rx_edge_ts_idx[i] + 1; + PD_RX_TRANSITION_COUNT - 1) ? + 0 : + rx_edge_ts_idx[i] + 1; /* * If we have seen enough edges in a certain amount of * time, then trigger RX start. */ if ((rx_edge_ts[i][rx_edge_ts_idx[i]].val - - rx_edge_ts[i][next_idx].val) - < PD_RX_TRANSITION_WINDOW) { + rx_edge_ts[i][next_idx].val) < + PD_RX_TRANSITION_WINDOW) { /* acquire the message only on the active CC */ - STM32_COMP_CSR &= ~(i ? STM32_COMP_CMP1EN - : STM32_COMP_CMP2EN); + STM32_COMP_CSR &= ~(i ? STM32_COMP_CMP1EN : + STM32_COMP_CMP2EN); /* start sampling */ pd_rx_start(0); /* @@ -197,7 +202,7 @@ void rx_event(void) pd_rx_disable_monitoring(0); /* trigger the analysis in the task */ #ifdef HAS_TASK_SNIFFER - task_set_event(TASK_ID_SNIFFER, 1 << i, 0); + task_set_event(TASK_ID_SNIFFER, 1 << i); #endif /* start reception only one CC line */ break; @@ -209,7 +214,6 @@ void rx_event(void) } } } -#ifdef HAS_TASK_SNIFFER DECLARE_IRQ(STM32_IRQ_COMP, rx_event, 1); #endif diff --git a/board/twinkie/sniffer.c b/board/twinkie/sniffer.c index 6eb2e0824e..501608717d 100644 --- a/board/twinkie/sniffer.c +++ b/board/twinkie/sniffer.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,8 +9,9 @@ #include "console.h" #include "dma.h" #include "gpio.h" -#include "hwtimer.h" #include "hooks.h" +#include "hwtimer.h" +#include "ina2xx.h" #include "injector.h" #include "link_defs.h" #include "registers.h" @@ -19,7 +20,6 @@ #include "usb_descriptor.h" #include "usb_hw.h" #include "util.h" -#include "ina2xx.h" /* Size of one USB packet buffer */ #define EP_BUF_SIZE 64 @@ -105,11 +105,11 @@ static void ep_tx(void) btable_ep[USB_EP_SNIFFER].tx_addr = usb_sram_addr(ep_buf[b]); } /* re-enable data transmission if we have available data */ - btable_ep[USB_EP_SNIFFER].tx_count = (free_usb & (1<> 12) & 0x1) +#define get_channel(b) (((b) >> 12) & 0x1) void tim_rx1_handler(uint32_t stat) { @@ -171,8 +170,7 @@ void tim_rx1_handler(uint32_t stat) uint32_t next = idx ? 0x0001 : 0x0100; sample_tstamp[idx] = __hw_clock_source_read(); - sample_seq[idx] = ((seq++ << 3) & 0x0ff8) | - (SNIFFER_CHANNEL_CC1<<12); + sample_seq[idx] = ((seq++ << 3) & 0x0ff8) | (SNIFFER_CHANNEL_CC1 << 12); if (filled_dma & next) { oflow++; sample_seq[idx] |= 0x8000; @@ -193,8 +191,7 @@ void tim_rx2_handler(uint32_t stat) idx += 2; sample_tstamp[idx] = __hw_clock_source_read(); - sample_seq[idx] = ((seq++ << 3) & 0x0ff8) | - (SNIFFER_CHANNEL_CC2<<12); + sample_seq[idx] = ((seq++ << 3) & 0x0ff8) | (SNIFFER_CHANNEL_CC2 << 12); if (filled_dma & next) { oflow++; sample_seq[idx] |= 0x8000; @@ -206,19 +203,19 @@ void tim_rx2_handler(uint32_t stat) led_set_activity(1); } -void tim_dma_handler(void) +static void tim_dma_handler(void) { stm32_dma_regs_t *dma = STM32_DMA1_REGS; - uint32_t stat = dma->isr & (STM32_DMA_ISR_HTIF(DMAC_TIM_RX1) - | STM32_DMA_ISR_TCIF(DMAC_TIM_RX1) - | STM32_DMA_ISR_HTIF(DMAC_TIM_RX2) - | STM32_DMA_ISR_TCIF(DMAC_TIM_RX2)); + uint32_t stat = dma->isr & (STM32_DMA_ISR_HTIF(DMAC_TIM_RX1) | + STM32_DMA_ISR_TCIF(DMAC_TIM_RX1) | + STM32_DMA_ISR_HTIF(DMAC_TIM_RX2) | + STM32_DMA_ISR_TCIF(DMAC_TIM_RX2)); if (stat & STM32_DMA_ISR_ALL(DMAC_TIM_RX2)) tim_rx2_handler(stat); else tim_rx1_handler(stat); /* time to process the samples */ - task_set_event(TASK_ID_SNIFFER, USB_EVENT, 0); + task_set_event(TASK_ID_SNIFFER, USB_EVENT); } DECLARE_IRQ(STM32_IRQ_DMA_CHANNEL_4_7, tim_dma_handler, 1); @@ -251,30 +248,26 @@ static void rx_timer_init(int tim_id, timer_ctlr_t *tim, int ch_idx, int up_idx) tim->sr = 0; } - - void sniffer_init(void) { /* remap TIM1 CH1/2/3 to DMA channel 6 */ STM32_SYSCFG_CFGR1 |= BIT(28); /* TIM1 CH1 for CC1 RX */ - rx_timer_init(TIM_RX1, (void *)STM32_TIM_BASE(TIM_RX1), - TIM_RX1_CCR_IDX, 2); + rx_timer_init(TIM_RX1, (void *)STM32_TIM_BASE(TIM_RX1), TIM_RX1_CCR_IDX, + 2); /* TIM3 CH4 for CC2 RX */ - rx_timer_init(TIM_RX2, (void *)STM32_TIM_BASE(TIM_RX2), - TIM_RX2_CCR_IDX, 2); + rx_timer_init(TIM_RX2, (void *)STM32_TIM_BASE(TIM_RX2), TIM_RX2_CCR_IDX, + 2); /* turn on COMP/SYSCFG */ STM32_RCC_APB2ENR |= BIT(0); - STM32_COMP_CSR = STM32_COMP_CMP1EN | STM32_COMP_CMP1MODE_HSPEED | - STM32_COMP_CMP1INSEL_VREF12 | - STM32_COMP_CMP1OUTSEL_TIM1_IC1 | - STM32_COMP_CMP1HYST_HI | - STM32_COMP_CMP2EN | STM32_COMP_CMP2MODE_HSPEED | - STM32_COMP_CMP2INSEL_VREF12 | - STM32_COMP_CMP2OUTSEL_TIM2_IC4 | - STM32_COMP_CMP2HYST_HI; + STM32_COMP_CSR = + STM32_COMP_CMP1EN | STM32_COMP_CMP1MODE_HSPEED | + STM32_COMP_CMP1INSEL_VREF12 | STM32_COMP_CMP1OUTSEL_TIM1_IC1 | + STM32_COMP_CMP1HYST_HI | STM32_COMP_CMP2EN | + STM32_COMP_CMP2MODE_HSPEED | STM32_COMP_CMP2INSEL_VREF12 | + STM32_COMP_CMP2OUTSEL_TIM2_IC4 | STM32_COMP_CMP2HYST_HI; /* start sampling the edges on the CC lines using the RX timers */ dma_start_rx(&dma_tim_cc1, RX_COUNT, samples[0]); @@ -311,15 +304,14 @@ void sniffer_task(void) ep_buf[u][0] = sample_seq[d >> 3] | (d & 7); ep_buf[u][1] = sample_tstamp[d >> 3]; - memcpy_to_usbram( - ((void *)usb_sram_addr(ep_buf[u] - + (EP_PACKET_HEADER_SIZE>>1))), - samples[d >> 4]+off, - EP_PAYLOAD_SIZE); - deprecated_atomic_clear_bits((uint32_t *)&free_usb, - 1 << u); + memcpy_to_usbram(((void *)usb_sram_addr( + ep_buf[u] + + (EP_PACKET_HEADER_SIZE >> 1))), + samples[d >> 4] + off, + EP_PAYLOAD_SIZE); + atomic_clear_bits((atomic_t *)&free_usb, 1 << u); u = !u; - deprecated_atomic_clear_bits(&filled_dma, 1 << d); + atomic_clear_bits((atomic_t *)&filled_dma, 1 << d); } led_reset_record(); @@ -333,8 +325,8 @@ void sniffer_task(void) int wait_packet(int pol, uint32_t min_edges, uint32_t timeout_us) { - stm32_dma_chan_t *chan = dma_get_channel(pol ? DMAC_TIM_RX2 - : DMAC_TIM_RX1); + stm32_dma_chan_t *chan = + dma_get_channel(pol ? DMAC_TIM_RX2 : DMAC_TIM_RX1); uint32_t t0 = __hw_clock_source_read(); uint32_t c0 = chan->cndtr; uint32_t t_gap = t0; @@ -356,7 +348,7 @@ int wait_packet(int pol, uint32_t min_edges, uint32_t timeout_us) total_edges += nb; } else { if ((t - t_gap) > 20 && - (total_edges - (t - t0)/256) >= min_edges) + (total_edges - (t - t0) / 256) >= min_edges) /* real gap after the packet */ break; } @@ -393,11 +385,10 @@ static void sniffer_sysjump(void) } DECLARE_HOOK(HOOK_SYSJUMP, sniffer_sysjump, HOOK_PRIO_DEFAULT); -static int command_sniffer(int argc, char **argv) +static int command_sniffer(int argc, const char **argv) { ccprintf("Seq number:%d Overflows: %d\n", seq, oflow); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(sniffer, command_sniffer, - "[]", "Buffering status"); +DECLARE_CONSOLE_COMMAND(sniffer, command_sniffer, "[]", "Buffering status"); diff --git a/board/twinkie/usb_pd_config.h b/board/twinkie/usb_pd_config.h index 1c20a9df77..062c174d8a 100644 --- a/board/twinkie/usb_pd_config.h +++ b/board/twinkie/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -50,7 +50,7 @@ static inline void spi_enable_clock(int port) #define DMAC_TIM_RX(p) STM32_DMAC_CH2 #define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 #define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 -#define TIM_CCR_CS 1 +#define TIM_CCR_CS 1 #define EXTI_COMP_MASK(p) (BIT(21) | BIT(22)) #define IRQ_COMP STM32_IRQ_COMP /* triggers packet detection on comparator falling edge */ @@ -102,11 +102,11 @@ static inline void pd_tx_enable(int port, int polarity) static inline void pd_tx_disable(int port, int polarity) { /* TX_DATA on PB4 is an output low GPIO to disable the FET */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) & ~(3 << (2*4))) - | (1 << (2*4)); + STM32_GPIO_MODER(GPIO_B) = + (STM32_GPIO_MODER(GPIO_B) & ~(3 << (2 * 4))) | (1 << (2 * 4)); /* TX_DATA on PA6 is an output low GPIO to disable the FET */ - STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) & ~(3 << (2*6))) - | (1 << (2*6)); + STM32_GPIO_MODER(GPIO_A) = + (STM32_GPIO_MODER(GPIO_A) & ~(3 << (2 * 6))) | (1 << (2 * 6)); /* * Tri-state the low side after the high side * to ensure we are not going above Vnc @@ -119,11 +119,12 @@ static inline void pd_tx_disable(int port, int polarity) static inline void pd_select_polarity(int port, int polarity) { /* use the right comparator */ - STM32_COMP_CSR = (STM32_COMP_CSR - & ~(STM32_COMP_CMP1INSEL_MASK | STM32_COMP_CMP2INSEL_MASK - |STM32_COMP_CMP1EN | STM32_COMP_CMP2EN)) - | STM32_COMP_CMP1INSEL_INM4 | STM32_COMP_CMP2INSEL_INM4 - | (polarity ? STM32_COMP_CMP2EN : STM32_COMP_CMP1EN); + STM32_COMP_CSR = + (STM32_COMP_CSR & + ~(STM32_COMP_CMP1INSEL_MASK | STM32_COMP_CMP2INSEL_MASK | + STM32_COMP_CMP1EN | STM32_COMP_CMP2EN)) | + STM32_COMP_CMP1INSEL_INM4 | STM32_COMP_CMP2INSEL_INM4 | + (polarity ? STM32_COMP_CMP2EN : STM32_COMP_CMP1EN); } /* Initialize pins used for clocking */ diff --git a/board/twinkie/usb_pd_pdo.c b/board/twinkie/usb_pd_pdo.c new file mode 100644 index 0000000000..fbc0624f80 --- /dev/null +++ b/board/twinkie/usb_pd_pdo.c @@ -0,0 +1,24 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +#define PDO_FIXED_FLAGS (PDO_FIXED_UNCONSTRAINED | PDO_FIXED_DATA_SWAP) + +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), + PDO_FIXED(12000, 3000, PDO_FIXED_FLAGS), + PDO_FIXED(20000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_BATT(4750, 21000, 15000), + PDO_VAR(4750, 21000, 3000), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/twinkie/usb_pd_pdo.h b/board/twinkie/usb_pd_pdo.h new file mode 100644 index 0000000000..0badd0f7bf --- /dev/null +++ b/board/twinkie/usb_pd_pdo.h @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_TWINKIE_USB_PD_PDO_H +#define __CROS_EC_BOARD_TWINKIE_USB_PD_PDO_H + +#include "stdint.h" + +extern const uint32_t pd_src_pdo[3]; +extern const int pd_src_pdo_cnt; + +extern const uint32_t pd_snk_pdo[3]; +extern const int pd_snk_pdo_cnt; + +#endif /* __CROS_EC_BOARD_TWINKIE_USB_PD_PDO_H */ diff --git a/board/twinkie/usb_pd_policy.c b/board/twinkie/usb_pd_policy.c index 62ecd6e0db..c3434cd0d5 100644 --- a/board/twinkie/usb_pd_policy.c +++ b/board/twinkie/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,27 +11,12 @@ #include "registers.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_pd.h" +#include "usb_pd_pdo.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define PDO_FIXED_FLAGS (PDO_FIXED_UNCONSTRAINED | PDO_FIXED_DATA_SWAP) - -const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), - PDO_FIXED(12000, 3000, PDO_FIXED_FLAGS), - PDO_FIXED(20000, 3000, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); - -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), - PDO_BATT(4750, 21000, 15000), - PDO_VAR(4750, 21000, 3000), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) void pd_set_input_current_limit(int port, uint32_t max_ma, uint32_t supply_voltage) @@ -65,27 +50,23 @@ __override int pd_check_power_swap(int port) return 0; } -__override int pd_check_data_swap(int port, - enum pd_data_role data_role) +__override int pd_check_data_swap(int port, enum pd_data_role data_role) { /* Always allow data swap */ return 1; } -__override void pd_check_pr_role(int port, - enum pd_power_role pr_role, +__override void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { } -__override void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +__override void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { } __override int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) + uint32_t **rpayload) { return 0; } diff --git a/board/twinkie/vif_override.xml b/board/twinkie/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/twinkie/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/vell/battery.c b/board/vell/battery.c new file mode 100644 index 0000000000..0ffb7fb015 --- /dev/null +++ b/board/vell/battery.c @@ -0,0 +1,99 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Vell battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* Simplo Coslight Battery Information */ + [BATTERY_SIMPLO_COS] = { + .fuel_gauge = { + .manuf_name = "333-1C-DA-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + }, + }, + .batt_info = { + .voltage_max = 8800, /* mV */ + .voltage_normal = 7600, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = 0, + .discharging_max_c = 60, + }, + }, + /* 916Q2303H Simplo CosMX Battery Information */ + [BATTERY_SIMPLO_COS2] = { + .fuel_gauge = { + .manuf_name = "133-1C-39-A", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x0010, 0x0010 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x0006, + }, + }, + .batt_info = { + .voltage_max = 8860, /* mV */ + .voltage_normal = 7720, + .voltage_min = 6000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 51, + .discharging_min_c = -10, + .discharging_max_c = 60, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO_COS2; + +enum battery_present battery_hw_present(void) +{ + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} diff --git a/board/vell/board.c b/board/vell/board.c new file mode 100644 index 0000000000..a475684a66 --- /dev/null +++ b/board/vell/board.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/als_tcs3400.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "panic.h" +#include "power.h" +#include "power/intel_x86.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +static void board_chipset_startup(void) +{ + /* Allow keyboard backlight to be enabled */ + + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); + +static void board_chipset_shutdown(void) +{ + /* Turn off the keyboard backlight if it's on. */ + + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT); + +static void set_board_id_5_gpios(void) +{ + if (get_board_id() < 6) { + power_signal_list[X86_ALL_SYS_PGOOD].gpio = + GPIO_ID_5_SEQ_EC_ALL_SYS_PG; + } +} +DECLARE_HOOK(HOOK_INIT, set_board_id_5_gpios, HOOK_PRIO_POST_FIRST); + +__override int intel_x86_get_pg_ec_all_sys_pwrgd(void) +{ + if (get_board_id() < 6) + return gpio_get_level(GPIO_ID_5_SEQ_EC_ALL_SYS_PG); + + return gpio_get_level(GPIO_PG_EC_ALL_SYS_PWRGD); +} diff --git a/board/vell/board.h b/board/vell/board.h new file mode 100644 index 0000000000..ca4d055b9b --- /dev/null +++ b/board/vell/board.h @@ -0,0 +1,247 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Vell board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +/* No side buttons */ +#undef CONFIG_MKBP_INPUT_DEVICES +#undef CONFIG_VOLUME_BUTTONS + +/* Sensors */ +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_GMR_TABLET_MODE + +/* TCS3400 ALS */ +#define CONFIG_ALS +#define ALS_COUNT 1 +#define CONFIG_ALS_TCS3400 +#define CONFIG_ALS_TCS3400_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) + +/* Enable sensor fifo, must also define the _SIZE and _THRES */ +#define CONFIG_ACCEL_FIFO +/* FIFO size is in power of 2. */ +#define CONFIG_ACCEL_FIFO_SIZE 256 +/* Depends on how fast the AP boots and typical ODRs */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(CLEAR_ALS) + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + +#define CONFIG_IO_EXPANDER +#define CONFIG_IO_EXPANDER_NCT38XX +#define CONFIG_IO_EXPANDER_PORT_COUNT 4 + +#define CONFIG_USB_PD_FRS_PPC + +#define CONFIG_USBC_RETIMER_INTEL_BB + +#define CONFIG_USBC_PPC_SYV682X + +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 + +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* USB Type C and USB PD defines */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_CURRENT_MA 5000 +#define PD_MAX_VOLTAGE_MV 20000 +/* Max Power = 100 W */ +#define PD_MAX_POWER_MW ((PD_MAX_VOLTAGE_MV * PD_MAX_CURRENT_MA) / 1000) + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL +#define GPIO_RIGHT_LED_AMBER_L GPIO_LED_1_L +#define GPIO_RIGHT_LED_WHITE_L GPIO_LED_2_L +#define GPIO_LEFT_LED_AMBER_L GPIO_LED_3_L +#define GPIO_LEFT_LED_WHITE_L GPIO_LED_4_L + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_C1_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C2_C3_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_C1_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C2_C3_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C1_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C2_C3_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C1_MUX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_C2_C3_MUX NPCX_I2C_PORT3_0 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +/* + * see b/174768555#comment22 + */ +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x56 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x57 +#define USBC_PORT_C2_BB_RETIMER_I2C_ADDR 0x58 +#define USBC_PORT_C3_BB_RETIMER_I2C_ADDR 0x59 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* Enabling USB4 mode */ +#define CONFIG_USB_PD_USB4 +#define CONFIG_USB_PD_DATA_RESET_MSG + +/* Retimer */ +#define CONFIG_USBC_RETIMER_FW_UPDATE + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +/* Fan features */ +#define CONFIG_FANS FAN_CH_COUNT +#define CONFIG_FAN_BYPASS_SLOW_RESPONSE +#define CONFIG_CUSTOM_FAN_CONTROL +#define RPM_DEVIATION 1 + +/* Charger defines */ +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_SENSE_RESISTOR 5 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +/* Keyboard features */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +#undef CONFIG_BATT_HOST_SHUTDOWN_PERCENTAGE +#define CONFIG_BATT_HOST_SHUTDOWN_PERCENTAGE 3 + +/* + * Older boards have a different ADC assignment. + */ + +#define CONFIG_ADC_CHANNELS_RUNTIME_CONFIG +#define CONFIG_POWER_SIGNAL_RUNTIME_CONFIG + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_SOC, + ADC_TEMP_SENSOR_2_CHARGER, + ADC_TEMP_SENSOR_3_WWAN, + ADC_TEMP_SENSOR_4_DDR, + ADC_TEMP_SENSOR_5_REGULATOR, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_SOC, + TEMP_SENSOR_2_CHARGER, + TEMP_SENSOR_3_WWAN, + TEMP_SENSOR_4_DDR, + TEMP_SENSOR_5_REGULATOR, + TEMP_SENSOR_COUNT +}; + +enum sensor_id { CLEAR_ALS = 0, RGB_ALS, SENSOR_COUNT }; + +enum ioex_port { + IOEX_C0_NCT38XX = 0, + IOEX_C1_NCT38XX, + IOEX_C2_NCT38XX, + IOEX_C3_NCT38XX, + IOEX_PORT_COUNT +}; + +enum battery_type { + BATTERY_SIMPLO_COS, + BATTERY_SIMPLO_COS2, + BATTERY_TYPE_COUNT +}; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +extern const int keyboard_factory_scan_pins[][2]; +extern const int keyboard_factory_scan_pins_used; +#endif + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/vell/build.mk b/board/vell/build.mk new file mode 100644 index 0000000000..cad0da2a4e --- /dev/null +++ b/board/vell/build.mk @@ -0,0 +1,26 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Brya board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=thermal.o +board-y+=usbc_config.o diff --git a/board/vell/charger.c b/board/vell/charger.c new file mode 100644 index 0000000000..59d8812993 --- /dev/null +++ b/board/vell/charger.c @@ -0,0 +1,94 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "hooks.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +static void set_ac_prochot(void) +{ + isl9241_set_ac_prochot(CHARGER_SOLO, PD_MAX_CURRENT_MA); +} +DECLARE_HOOK(HOOK_INIT, set_ac_prochot, HOOK_PRIO_DEFAULT); + +/* Set the DCPROCHOT base on battery over discharging current 10.5A */ +static void set_dc_prochot(void) +{ + isl9241_set_dc_prochot(CHARGER_SOLO, 10500); +} +DECLARE_HOOK(HOOK_INIT, set_dc_prochot, HOOK_PRIO_DEFAULT); diff --git a/board/vell/ec.tasklist b/board/vell/ec.tasklist new file mode 100644 index 0000000000..0bae104a07 --- /dev/null +++ b/board/vell/ec.tasklist @@ -0,0 +1,35 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(LED, led_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P2, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P3, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C2, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C3, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(1) | BIT(0)), BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_shared_alert_task, (BIT(3) | BIT(2)), BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/vell/fans.c b/board/vell/fans.c new file mode 100644 index 0000000000..050dc0cfa4 --- /dev/null +++ b/board/vell/fans.c @@ -0,0 +1,44 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2500, + .rpm_start = 2500, + .rpm_max = 6800, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; diff --git a/board/vell/fw_config.c b/board/vell/fw_config.c new file mode 100644 index 0000000000..137c5c9f9a --- /dev/null +++ b/board/vell/fw_config.c @@ -0,0 +1,33 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union vell_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for vell if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union vell_cbi_fw_config fw_config_defaults = {}; + +/**************************************************************************** + * Vell FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } +} diff --git a/board/vell/fw_config.h b/board/vell/fw_config.h new file mode 100644 index 0000000000..324057a8e9 --- /dev/null +++ b/board/vell/fw_config.h @@ -0,0 +1,27 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_VELL_FW_CONFIG_H_ +#define __BOARD_VELL_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Vell board. + * + * Source of truth is the project/brya/vell/config.star configuration file. + */ +union vell_cbi_fw_config { + struct { + uint32_t lte_db : 1; + uint32_t kb_color : 1; + uint32_t storage_nand : 1; + uint32_t wifi_sar_id : 2; + uint32_t reserved_1 : 27; + }; + uint32_t raw_value; +}; + +#endif /* __BOARD_VELL_FW_CONFIG_H_ */ diff --git a/board/vell/gpio.inc b/board/vell/gpio.inc new file mode 100644 index 0000000000..0bd8065ab4 --- /dev/null +++ b/board/vell/gpio.inc @@ -0,0 +1,164 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_ALS_RGB_INT_R_L, PIN(D, 4), GPIO_INT_FALLING, tcs3400_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(9, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C1_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C0_RT_INT_ODL, PIN(B, 1), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(9, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C2_BC12_INT_ODL, PIN(8, 3), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C2_C3_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C2_PPC_INT_ODL, PIN(7, 0), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C2_RT_INT_ODL, PIN(9, 4), GPIO_INT_FALLING, retimer_interrupt) +GPIO_INT(USB_C3_BC12_INT_ODL, PIN(5, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C3_PPC_INT_ODL, PIN(8, 1), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C3_RT_INT_ODL, PIN(9, 3), GPIO_INT_FALLING, retimer_interrupt) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_RT_SCL, PIN(D, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_RT_SDA, PIN(D, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C1_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_C3_PPC_BC_RT_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_C3_PPC_BC_RT_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_C3_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C2_C3_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN, PIN(8, 0), GPIO_OUT_LOW) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(ID_5_SEQ_EC_ALL_SYS_PG, PIN(D, 7), GPIO_INPUT) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_C1_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C2_C3_TCPC_RST_ODL, PIN(9, 6), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) + +/* LED */ +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_LOW) +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_LOW) +GPIO(LED_3_L, PIN(C, 2), GPIO_OUT_LOW) +GPIO(LED_4_L, PIN(6, 0), GPIO_OUT_LOW) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(D, 0x03), 0, MODULE_I2C, 0) /* GPIOD1/I2C3_SCL0, GPIOD0/I2C3_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x36), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1, GPIO41/ADC4*/ +ALTERNATE(PIN_MASK(E, 0x02), 0, MODULE_ADC, 0) /* GPIOE1/ADC7 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ +UNUSED(PIN(F, 4)) /* GPIOF4/I2C5_SDA1 */ +UNUSED(PIN(F, 5)) /* GPIOF5/I2C5_SCL1 */ +UNUSED(PIN(8, 6)) /* GPO86/TXD/CR_SOUT2 */ + +/* Pre-configured PSL balls: J8 K6 */ + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +/* IO expander configuration */ +/* GPIO02_P1 to PU */ +/* GPIO03_P1 to PU */ +IOEX(USB_C0_OC_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C0_FRS_EN, EXPIN(IOEX_C0_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C0_RT_RST_ODL, EXPIN(IOEX_C0_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C1_RT_RST_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 2), GPIO_ODR_LOW) +/* GPIO03_P2 to PU */ +IOEX(USB_C1_OC_ODL, EXPIN(IOEX_C1_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C1_FRS_EN, EXPIN(IOEX_C1_NCT38XX, 0, 6), GPIO_OUT_LOW) +/* GPIO07_P2 to PU */ + +/* GPIO02_P1 to PU */ +/* GPIO03_P1 to PU */ +IOEX(USB_C2_OC_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C2_FRS_EN, EXPIN(IOEX_C2_NCT38XX, 0, 6), GPIO_OUT_LOW) +IOEX(USB_C2_RT_RST_ODL, EXPIN(IOEX_C2_NCT38XX, 0, 7), GPIO_ODR_LOW) + +IOEX(USB_C3_RT_RST_ODL, EXPIN(IOEX_C3_NCT38XX, 0, 2), GPIO_ODR_LOW) +/* GPIO03_P2 to PU */ +IOEX(USB_C3_OC_ODL, EXPIN(IOEX_C3_NCT38XX, 0, 4), GPIO_ODR_HIGH) +IOEX(USB_C3_FRS_EN, EXPIN(IOEX_C3_NCT38XX, 0, 6), GPIO_OUT_LOW) +/* GPIO07_P2 to PU */ diff --git a/board/vell/i2c.c b/board/vell/i2c.c new file mode 100644 index 0000000000..822de9a0d1 --- /dev/null +++ b/board/vell/i2c.c @@ -0,0 +1,78 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "i2c.h" + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,1", + .port = I2C_PORT_USB_C0_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,1", + .port = I2C_PORT_USB_C0_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SDA, + }, + { + /* I2C3 */ + .name = "retimer0,1,2,3", + .port = I2C_PORT_USB_C0_C1_MUX, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_RT_SCL, + .sda = GPIO_EC_I2C_USB_RT_SDA, + }, + { + /* I2C4 */ + .name = "tcpc2,3", + .port = I2C_PORT_USB_C2_C3_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C2_C3_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C2_C3_TCPC_SDA, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc2,3", + .port = I2C_PORT_USB_C2_C3_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C2_C3_PPC_BC_RT_SCL, + .sda = GPIO_EC_I2C_USB_C2_C3_PPC_BC_RT_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/vell/keyboard.c b/board/vell/keyboard.c new file mode 100644 index 0000000000..f541f51e3b --- /dev/null +++ b/board/vell/keyboard.c @@ -0,0 +1,69 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config keybd1 = { + .num_top_row_keys = 13, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_KBD_BKLIGHT_TOGGLE, /* T8 */ + TK_PLAY_PAUSE, /* T9 */ + TK_MICMUTE, /* T10 */ + TK_VOL_MUTE, /* T11 */ + TK_VOL_DOWN, /* T12 */ + TK_VOL_UP, /* T13 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &keybd1; +} + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * Map keyboard connector pins to EC GPIO pins for factory test. + * Pins mapped to {-1, -1} are skipped. + * The connector has 24 pins total, and there is no pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, + { 0, 7 }, { 1, 4 }, { 1, 3 }, { 1, 6 }, { 1, 7 }, + { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, + { 2, 2 }, { 3, 0 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/vell/led.c b/board/vell/led.c new file mode 100644 index 0000000000..186a211744 --- /dev/null +++ b/board/vell/led.c @@ -0,0 +1,242 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Vell + */ + +#include "battery.h" +#include "cbi.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "task.h" +#include "util.h" + +#include + +#define BATT_LOW_BCT 10 + +#define LED_TICK_INTERVAL_MS (500 * MSEC) +#define LED_CYCLE_TIME_MS (2000 * MSEC) +#define LED_TICKS_PER_CYCLE (LED_CYCLE_TIME_MS / LED_TICK_INTERVAL_MS) +#define LED_ON_TIME_MS (1000 * MSEC) +#define LED_ON_TICKS (LED_ON_TIME_MS / LED_TICK_INTERVAL_MS) + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_LEFT_LED, + EC_LED_ID_RIGHT_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_AMBER, + LED_WHITE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +enum led_port { RIGHT_PORT = 0, LEFT_PORT }; + +uint8_t bat_led_on; +uint8_t bat_led_off; + +static void led_init(void) +{ + if (get_board_id() < 2) { + bat_led_on = 0; + bat_led_off = 1; + } else { + bat_led_on = 1; + bat_led_off = 0; + } +} +DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_DEFAULT); + +static void led_set_color_battery(int port, enum led_color color) +{ + enum gpio_signal amber_led, white_led; + + amber_led = (port == RIGHT_PORT ? GPIO_RIGHT_LED_AMBER_L : + GPIO_LEFT_LED_AMBER_L); + white_led = (port == RIGHT_PORT ? GPIO_RIGHT_LED_WHITE_L : + GPIO_LEFT_LED_WHITE_L); + + switch (color) { + case LED_WHITE: + gpio_set_level(white_led, bat_led_on); + gpio_set_level(amber_led, bat_led_off); + break; + case LED_AMBER: + gpio_set_level(white_led, bat_led_off); + gpio_set_level(amber_led, bat_led_on); + break; + case LED_OFF: + gpio_set_level(white_led, bat_led_off); + gpio_set_level(amber_led, bat_led_off); + break; + default: + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + memset(brightness_range, '\0', + sizeof(*brightness_range) * EC_LED_COLOR_COUNT); + switch (led_id) { + case EC_LED_ID_LEFT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + case EC_LED_ID_RIGHT_LED: + brightness_range[EC_LED_COLOR_WHITE] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; + break; + default: + break; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + switch (led_id) { + case EC_LED_ID_LEFT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(LEFT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(LEFT_PORT, LED_AMBER); + else + led_set_color_battery(LEFT_PORT, LED_OFF); + break; + case EC_LED_ID_RIGHT_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + led_set_color_battery(RIGHT_PORT, LED_WHITE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(RIGHT_PORT, LED_AMBER); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + break; + default: + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} + +/* + * Set active charge port color to the parameter, turn off all others. + * If no port is active (-1), turn off all LEDs. + */ +static void set_active_port_color(enum led_color color) +{ + int usbc_port = charge_manager_get_active_charge_port(); + int port = 0; + + if ((usbc_port == USBC_PORT_C0) || (usbc_port == USBC_PORT_C1)) + port = RIGHT_PORT; + else if ((usbc_port == USBC_PORT_C2) || (usbc_port == USBC_PORT_C3)) + port = LEFT_PORT; + + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) + led_set_color_battery(RIGHT_PORT, + (port == RIGHT_PORT) ? color : LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) + led_set_color_battery(LEFT_PORT, + (port == LEFT_PORT) ? color : LED_OFF); +} + +static void led_set_battery(void) +{ + static unsigned int battery_ticks; + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + /* Always indicate when charging, even in suspend. */ + set_active_port_color(LED_AMBER); + break; + case LED_PWRS_DISCHARGE: + /* + * Blinking amber LEDs slowly if battery is lower 10 + * percentage. + */ + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + if (charge_get_percent() < BATT_LOW_BCT) + led_set_color_battery( + RIGHT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(RIGHT_PORT, LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) { + if (charge_get_percent() < BATT_LOW_BCT) + led_set_color_battery( + LEFT_PORT, + (battery_ticks % LED_TICKS_PER_CYCLE < + LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + else + led_set_color_battery(LEFT_PORT, LED_OFF); + } + break; + case LED_PWRS_ERROR: + if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED)) { + led_set_color_battery( + RIGHT_PORT, + (battery_ticks & 0x1) ? LED_AMBER : LED_OFF); + } + + if (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)) { + led_set_color_battery(LEFT_PORT, (battery_ticks & 0x1) ? + LED_AMBER : + LED_OFF); + } + break; + case LED_PWRS_CHARGE_NEAR_FULL: + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + set_active_port_color(LED_WHITE); + break; + case LED_PWRS_FORCED_IDLE: + set_active_port_color( + (battery_ticks % LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? + LED_AMBER : + LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +void led_task(void *u) +{ + uint32_t start_time; + uint32_t task_duration; + + while (1) { + start_time = get_time().le.lo; + + led_set_battery(); + + /* Compute time for this iteration */ + task_duration = get_time().le.lo - start_time; + /* + * Compute wait time required to for next desired LED tick. If + * the duration exceeds the tick time, then don't sleep. + */ + if (task_duration < LED_TICK_INTERVAL_MS) + usleep(LED_TICK_INTERVAL_MS - task_duration); + } +} diff --git a/board/vell/pwm.c b/board/vell/pwm.c new file mode 100644 index 0000000000..fc81baf455 --- /dev/null +++ b/board/vell/pwm.c @@ -0,0 +1,40 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn on all the LED at 50%. + */ + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/vell/sensors.c b/board/vell/sensors.c new file mode 100644 index 0000000000..e57598ccbf --- /dev/null +++ b/board/vell/sensors.c @@ -0,0 +1,297 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "accelgyro.h" +#include "adc.h" +#include "common.h" +#include "driver/als_tcs3400_public.h" +#include "gpio.h" +#include "hooks.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_SOC] = { + .name = "TEMP_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_WWAN] = { + .name = "TEMP_WWAN", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_4_DDR] = { + .name = "TEMP_DDR", + .input_ch = NPCX_ADC_CH7, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_5_REGULATOR] = { + .name = "TEMP_REGULATOR", + .input_ch = NPCX_ADC_CH4, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* TCS3400 private data */ +static struct als_drv_data_t g_tcs3400_data = { + .als_cal.scale = 1, + .als_cal.uscale = 0, + .als_cal.offset = 0, + .als_cal.channel_scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ + .cover_scale = ALS_CHANNEL_SCALE(0.23), /* CT */ + }, +}; + +/* + * TODO: b/184702900 need to calibrate ALS/RGB sensor. At default settings, + * shining phone flashlight on sensor pegs all readings at 0xFFFF. + */ +static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { + .calibration.rgb_cal[X] = { + .offset = 448, /* 447.5509362 */ + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(-0.45511034), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(-0.21956361), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0.32628044), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.3610898), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ + .cover_scale = ALS_CHANNEL_SCALE(0.08) + } + }, + .calibration.rgb_cal[Y] = { + .offset = 436, /* 435.9025807*/ + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(-0.50765776), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(-0.34142269), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0.55352908), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.35923454), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + }, + .calibration.rgb_cal[Z] = { + .offset = 287, /* 286.51472391*/ + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(-0.11635731), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(-0.76700456), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(1.36663521), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.18494607), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ + .cover_scale = ALS_CHANNEL_SCALE(0.54) + } + }, + .calibration.irt = FLOAT_TO_FP(0.06), + .saturation.again = TCS_DEFAULT_AGAIN, + .saturation.atime = TCS_DEFAULT_ATIME, +}; + +struct motion_sensor_t motion_sensors[] = { + [CLEAR_ALS] = { + .name = "Clear Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &tcs3400_drv, + .drv_data = &g_tcs3400_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + .min_frequency = TCS3400_LIGHT_MIN_FREQ, + .max_frequency = TCS3400_LIGHT_MAX_FREQ, + .config = { + /* Run ALS sensor in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 1000, + }, + }, + }, + + [RGB_ALS] = { + /* + * RGB channels read by CLEAR_ALS and so the i2c port and + * address do not need to be defined for RGB_ALS. + */ + .name = "RGB Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT_RGB, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &tcs3400_rgb_drv, + .drv_data = &g_tcs3400_rgb_data, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ +const struct motion_sensor_t *motion_als_sensors[] = { + &motion_sensors[CLEAR_ALS], +}; +BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); + +static void baseboard_sensors_init(void) +{ + /* Enable interrupt for the TCS3400 color light sensor */ + gpio_enable_interrupt(GPIO_EC_ALS_RGB_INT_R_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_INIT_I2C + 1); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_SOC] = { + .name = "SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_SOC, + }, + [TEMP_SENSOR_2_CHARGER] = { + .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_CHARGER, + }, + [TEMP_SENSOR_3_WWAN] = { + .name = "WWAN", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_WWAN, + }, + [TEMP_SENSOR_4_DDR] = { + .name = "DDR", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_4_DDR, + }, + [TEMP_SENSOR_5_REGULATOR] = { + .name = "Regulator", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_5_REGULATOR, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/203839956): update for Alder Lake/vell + * + * Alder Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(95), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + }, \ + } + +/* + * TODO(b/203839956): update for Alder Lake/vell + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(95), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + }, \ + } + +/* + * TODO(b/203839956): update for vell WWAN module + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_WWAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } + +/* + * TODO(b/203839956): update for Alder Lake/vell + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ + +#define THERMAL_DDR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + }, \ + } + +/* + * TODO(b/203839956): update for Alder Lake/vell + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ + +#define THERMAL_REGULATOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + }, \ + } + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_CHARGER] = THERMAL_CHARGER, + [TEMP_SENSOR_3_WWAN] = THERMAL_WWAN, + [TEMP_SENSOR_4_DDR] = THERMAL_DDR, + [TEMP_SENSOR_5_REGULATOR] = THERMAL_REGULATOR, +}; diff --git a/board/vell/thermal.c b/board/vell/thermal.c new file mode 100644 index 0000000000..045bcb92fa --- /dev/null +++ b/board/vell/thermal.c @@ -0,0 +1,134 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "fan.h" +#include "hooks.h" +#include "host_command.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +struct fan_step { + /* + * Sensor 1~5 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t on[TEMP_SENSOR_COUNT]; + + /* + * Sensor 1~5 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t off[TEMP_SENSOR_COUNT]; + + /* Fan 1~2 rpm */ + uint16_t rpm[FAN_CH_COUNT]; +}; + +static const struct fan_step fan_table[] = { + { + /* level 0 */ + .on = { 47, 62, 48, 50, -1 }, + .off = { 99, 99, 99, 99, -1 }, + .rpm = { 0 }, + }, + { + /* level 1 */ + .on = { 49, 62, 50, 52, -1 }, + .off = { 46, 99, 47, 49, -1 }, + .rpm = { 3100 }, + }, + { + /* level 2 */ + .on = { 51, 62, 53, 54, -1 }, + .off = { 48, 99, 49, 51, -1 }, + .rpm = { 3750 }, + }, + { + /* level 3 */ + .on = { 100, 100, 100, 100, -1 }, + .off = { 50, 60, 51, 52, -1 }, + .rpm = { 5100 }, + }, +}; + +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_table) + +static int fan_table_to_rpm(int fan, int *temp) +{ + static int current_level; + static int prev_tmp[TEMP_SENSOR_COUNT]; + int i; + + /* + * Compare the current and previous temperature, we have + * the three paths : + * 1. decreasing path. (check the release point) + * 2. increasing path. (check the trigger point) + * 3. invariant path. (return the current RPM) + */ + if (temp[TEMP_SENSOR_1_SOC] < prev_tmp[TEMP_SENSOR_1_SOC] || + temp[TEMP_SENSOR_2_CHARGER] < prev_tmp[TEMP_SENSOR_2_CHARGER] || + temp[TEMP_SENSOR_3_WWAN] < prev_tmp[TEMP_SENSOR_3_WWAN] || + temp[TEMP_SENSOR_4_DDR] < prev_tmp[TEMP_SENSOR_4_DDR]) { + for (i = current_level; i > 0; i--) { + if (temp[TEMP_SENSOR_1_SOC] < + fan_table[i].off[TEMP_SENSOR_1_SOC] && + temp[TEMP_SENSOR_2_CHARGER] < + fan_table[i].off[TEMP_SENSOR_2_CHARGER] && + temp[TEMP_SENSOR_3_WWAN] < + fan_table[i].off[TEMP_SENSOR_3_WWAN] && + temp[TEMP_SENSOR_4_DDR] < + fan_table[i].off[TEMP_SENSOR_4_DDR]) + current_level = i - 1; + else + break; + } + } else if (temp[TEMP_SENSOR_1_SOC] > prev_tmp[TEMP_SENSOR_1_SOC] || + temp[TEMP_SENSOR_2_CHARGER] > + prev_tmp[TEMP_SENSOR_2_CHARGER] || + temp[TEMP_SENSOR_3_WWAN] > prev_tmp[TEMP_SENSOR_3_WWAN] || + temp[TEMP_SENSOR_4_DDR] > prev_tmp[TEMP_SENSOR_4_DDR]) { + for (i = current_level; i < NUM_FAN_LEVELS; i++) { + if (temp[TEMP_SENSOR_1_SOC] > + fan_table[i].on[TEMP_SENSOR_1_SOC] || + (temp[TEMP_SENSOR_2_CHARGER] > + fan_table[i].on[TEMP_SENSOR_2_CHARGER] && + temp[TEMP_SENSOR_3_WWAN] > + fan_table[i].on[TEMP_SENSOR_3_WWAN]) || + temp[TEMP_SENSOR_4_DDR] > + fan_table[i].on[TEMP_SENSOR_4_DDR]) + current_level = i + 1; + else + break; + } + } + + if (current_level < 0) + current_level = 0; + + if (current_level >= NUM_FAN_LEVELS) + current_level = NUM_FAN_LEVELS - 1; + + for (i = 0; i < TEMP_SENSOR_COUNT; ++i) + prev_tmp[i] = temp[i]; + + return fan_table[current_level].rpm[FAN_CH_0]; +} + +void board_override_fan_control(int fan, int *tmp) +{ + if (chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND)) { + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), fan_table_to_rpm(fan, tmp)); + } +} diff --git a/board/vell/usbc_config.c b/board/vell/usbc_config.c new file mode 100644 index 0000000000..4290c40936 --- /dev/null +++ b/board/vell/usbc_config.c @@ -0,0 +1,481 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/nx20p348x.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/nct38xx.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C1_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C2] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C2_C3_TCPC, + .addr_flags = NCT38XX_I2C_ADDR1_4_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, + [USBC_PORT_C3] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C2_C3_TCPC, + .addr_flags = NCT38XX_I2C_ADDR2_4_FLAGS, + }, + .drv = &nct38xx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR1_FLAGS, + .frs_en = IOEX_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C2_C3_PPC, + .i2c_addr_flags = SYV682X_ADDR2_FLAGS, + .frs_en = IOEX_USB_C2_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C3] = { + .i2c_port = I2C_PORT_USB_C2_C3_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = IOEX_USB_C3_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +struct ppc_config_t ppc_chips_old_c3 = { + .i2c_port = I2C_PORT_USB_C2_C3_PPC, + .i2c_addr_flags = SYV682X_ADDR3_FLAGS, + .frs_en = IOEX_USB_C3_FRS_EN, + .drv = &syv682x_drv, +}; + +/* USBC mux configuration - Alder Lake includes internal mux */ +static const struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc2_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C2, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; +static const struct usb_mux_chain usbc3_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C3, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C0_C1_MUX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, + }, + [USBC_PORT_C2] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C2, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C2_C3_MUX, + .i2c_addr_flags = USBC_PORT_C2_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc2_tcss_usb_mux, + }, + [USBC_PORT_C3] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C3, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_C2_C3_MUX, + .i2c_addr_flags = USBC_PORT_C3_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc3_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C0_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_2_FLAGS, + }, + [USBC_PORT_C2] = { + .i2c_port = I2C_PORT_USB_C2_C3_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_1_FLAGS, + }, + [USBC_PORT_C3] = { + .i2c_port = I2C_PORT_USB_C2_C3_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_0_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/* + * USB C0 and C2 uses burnside bridge chips and have their reset + * controlled by their respective TCPC chips acting as GPIO expanders. + * + * ioex_init() is normally called before we take the TCPCs out of + * reset, so we need to start in disabled mode, then explicitly + * call ioex_init(). + */ + +struct ioexpander_config_t ioex_config[] = { + [IOEX_C0_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C1_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C0_C1_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_1_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C2_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C2_C3_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_4_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, + [IOEX_C3_NCT38XX] = { + .i2c_host_port = I2C_PORT_USB_C2_C3_TCPC, + .i2c_addr_flags = NCT38XX_I2C_ADDR2_4_FLAGS, + .drv = &nct38xx_ioexpander_drv, + .flags = IOEX_FLAGS_DEFAULT_INIT_DISABLED, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ioex_config) == CONFIG_IO_EXPANDER_PORT_COUNT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +__override int bb_retimer_power_enable(const struct usb_mux *me, bool enable) +{ + enum ioex_signal rst_signal; + + if (me->usb_port == USBC_PORT_C0) + rst_signal = IOEX_USB_C0_RT_RST_ODL; + else if (me->usb_port == USBC_PORT_C1) + rst_signal = IOEX_USB_C1_RT_RST_ODL; + else if (me->usb_port == USBC_PORT_C2) + rst_signal = IOEX_USB_C2_RT_RST_ODL; + else if (me->usb_port == USBC_PORT_C3) + rst_signal = IOEX_USB_C3_RT_RST_ODL; + else + return EC_ERROR_INVAL; + + /* + * We do not have a load switch for the burnside bridge chips, + * so we only need to sequence reset. + */ + + if (enable) { + /* + * Tpw, minimum time from VCC to RESET_N de-assertion is 100us. + * For boards that don't provide a load switch control, the + * retimer_init() function ensures power is up before calling + * this function. + */ + ioex_set_level(rst_signal, 1); + /* + * Allow 1ms time for the retimer to power up lc_domain + * which powers I2C controller within retimer + */ + msleep(1); + } else { + ioex_set_level(rst_signal, 0); + msleep(1); + } + return EC_SUCCESS; +} + +void board_reset_pd_mcu(void) +{ + gpio_set_level(GPIO_USB_C0_C1_TCPC_RST_ODL, 0); + gpio_set_level(GPIO_USB_C2_C3_TCPC_RST_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + msleep(NCT38XX_RESET_HOLD_DELAY_MS); + + gpio_set_level(GPIO_USB_C0_C1_TCPC_RST_ODL, 1); + gpio_set_level(GPIO_USB_C2_C3_TCPC_RST_ODL, 1); + + nct38xx_reset_notify(USBC_PORT_C0); + nct38xx_reset_notify(USBC_PORT_C1); + nct38xx_reset_notify(USBC_PORT_C2); + nct38xx_reset_notify(USBC_PORT_C3); + + /* wait for chips to come up */ + if (NCT3808_RESET_POST_DELAY_MS != 0) + msleep(NCT3808_RESET_POST_DELAY_MS); +} + +static void board_tcpc_init(void) +{ + int i; + + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* + * These IO expander pins are implemented using the + * C0/C1/C2/C3 TCPCs, so they must be set up after the TCPC + * has been taken out of reset. + */ + for (i = 0; i < CONFIG_IO_EXPANDER_PORT_COUNT; ++i) + ioex_init(i); + + if (get_board_id() < 2) + ppc_chips[USBC_PORT_C3] = ppc_chips_old_c3; + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C3_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C1_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_C3_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C2_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C3_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_1; + + if (gpio_get_level(GPIO_USB_C2_C3_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_2 | PD_STATUS_TCPC_ALERT_3; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C1) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C2) + return gpio_get_level(GPIO_USB_C2_PPC_INT_ODL) == 0; + else if (port == USBC_PORT_C3) + return gpio_get_level(GPIO_USB_C3_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C1_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C2_C3_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C2); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C2_BC12_INT_ODL: + usb_charger_task_set_event(2, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C3_BC12_INT_ODL: + usb_charger_task_set_event(3, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + case GPIO_USB_C2_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C2); + break; + case GPIO_USB_C3_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C3); + break; + default: + break; + } +} + +void retimer_interrupt(enum gpio_signal signal) +{ + /* + * TODO(b/179513527): add USB-C support + */ +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} diff --git a/board/vell/usbc_config.h b/board/vell/usbc_config.h new file mode 100644 index 0000000000..694b316ee8 --- /dev/null +++ b/board/vell/usbc_config.h @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Vell board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 4 + +enum usbc_port { + USBC_PORT_C0 = 0, + USBC_PORT_C1, + USBC_PORT_C2, + USBC_PORT_C3, + USBC_PORT_COUNT +}; + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/vell/vif_override.xml b/board/vell/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/vell/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/vilboz/battery.c b/board/vilboz/battery.c index c9bbf70a86..a119ce38e8 100644 --- a/board/vilboz/battery.c +++ b/board/vilboz/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,7 +6,11 @@ */ #include "battery_fuel_gauge.h" +#include "battery_smart.h" +#include "charge_state.h" #include "common.h" +#include "temp_sensor.h" +#include "thermal.h" #include "util.h" /* @@ -125,6 +129,37 @@ const struct board_batt_params board_battery_info[] = { }, }, + /* SMP L20M3PG3 47W + * Gauge IC: Renesas RAJ240047 + */ + [BATTERY_SMP_3] = { + .fuel_gauge = { + .manuf_name = "SMP", + .device_name = "L20M3PG3", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x0010, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11520, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 70, + }, + }, + /* LGC L19L3PG1 */ [BATTERY_LGC] = { .fuel_gauge = { @@ -344,3 +379,79 @@ const struct board_batt_params board_battery_info[] = { BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SMP; + +struct chg_curr_step { + int on; + int off; + int curr_ma; +}; + +static const struct chg_curr_step chg_curr_table[] = { + { .on = 0, .off = 35, .curr_ma = 2800 }, + { .on = 36, .off = 35, .curr_ma = 1500 }, + { .on = 39, .off = 38, .curr_ma = 1000 }, +}; + +/* All charge current tables must have the same number of levels */ +#define NUM_CHG_CURRENT_LEVELS ARRAY_SIZE(chg_curr_table) + +int charger_profile_override(struct charge_state_data *curr) +{ + int rv; + int chg_temp_c; + int current; + int thermal_sensor0; + static int current_level; + static int prev_tmp; + + /* + * Precharge must be executed when communication is failed on + * dead battery. + */ + if (!(curr->batt.flags & BATT_FLAG_RESPONSIVE)) + return 0; + + current = curr->requested_current; + + rv = temp_sensor_read(TEMP_SENSOR_CHARGER, &thermal_sensor0); + chg_temp_c = K_TO_C(thermal_sensor0); + + if (rv != EC_SUCCESS) + return 0; + + if (chipset_in_state(CHIPSET_STATE_ON)) { + if (chg_temp_c < prev_tmp) { + if (chg_temp_c <= chg_curr_table[current_level].off) + current_level = current_level - 1; + } else if (chg_temp_c > prev_tmp) { + if (chg_temp_c >= chg_curr_table[current_level + 1].on) + current_level = current_level + 1; + } + /* + * Prevent level always minus 0 or over table steps. + */ + if (current_level < 0) + current_level = 0; + else if (current_level >= NUM_CHG_CURRENT_LEVELS) + current_level = NUM_CHG_CURRENT_LEVELS - 1; + + prev_tmp = chg_temp_c; + current = chg_curr_table[current_level].curr_ma; + + curr->requested_current = MIN(curr->requested_current, current); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/vilboz/board.c b/board/vilboz/board.c index 33cff6b0db..d759865fc7 100644 --- a/board/vilboz/board.c +++ b/board/vilboz/board.c @@ -1,16 +1,17 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "battery_smart.h" #include "button.h" +#include "charge_state.h" #include "cros_board_info.h" #include "driver/accel_lis2dw12.h" #include "driver/accelgyro_lsm6dsm.h" #include "driver/bc12/pi3usb9201.h" #include "driver/ioexpander/pcal6408.h" -#include "driver/ppc/aoz1380.h" +#include "driver/ppc/aoz1380_public.h" #include "driver/tcpm/nct38xx.h" #include "driver/usb_mux/amd_fp5.h" #include "extpower.h" @@ -28,12 +29,12 @@ #include "tablet_mode.h" #include "task.h" #include "usb_charge.h" -#include "usb_pd_tcpm.h" #include "usb_mux.h" +#include "usb_pd_tcpm.h" #include "usbc_ppc.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* This I2C moved. Temporarily detect and support the V0 HW. */ int I2C_PORT_BATTERY = I2C_PORT_BATTERY_V1; @@ -43,10 +44,9 @@ void hdmi_hpd_interrupt(enum gpio_signal signal) gpio_set_level(GPIO_DP1_HPD, gpio_get_level(signal)); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#ifdef HAS_TASK_MOTIONSENSE - /* Motion sensors */ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; @@ -56,17 +56,13 @@ static struct stprivate_data g_lis2dwl_data; static struct lsm6dsm_data g_lsm6dsm_data = LSM6DSM_DATA; /* Matrix to rotate accelrator into standard reference frame */ -static const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; /* TODO(gcc >= 5.0) Remove the casts to const pointer at rot_standard_ref */ struct motion_sensor_t motion_sensors[] = { @@ -107,11 +103,9 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, - .default_range = 4, /* g, enough for laptop */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ .rot_standard_ref = &base_standard_ref, .min_frequency = LSM6DSM_ODR_MIN_VAL, .max_frequency = LSM6DSM_ODR_MAX_VAL, @@ -139,8 +133,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(g_lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_6AXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -152,15 +144,17 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#endif /* HAS_TASK_MOTIONSENSE */ - /* * USB C0 port SBU mux use standalone FSUSB42UMX * chip and it need a board specific driver. * Overall, it will use chained mux framework. */ -static int fsusb42umx_set_mux(const struct usb_mux *me, mux_state_t mux_state) +static int fsusb42umx_set_mux(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + if (mux_state & USB_PD_MUX_POLARITY_INVERTED) ioex_set_level(IOEX_USB_C0_SBU_FLIP, 1); else @@ -183,18 +177,23 @@ const struct usb_mux_driver usbc0_sbu_mux_driver = { * Since FSUSB42UMX is not a i2c device, .i2c_port and * .i2c_addr_flags are not required here. */ -const struct usb_mux usbc0_sbu_mux = { - .usb_port = USBC_PORT_C0, - .driver = &usbc0_sbu_mux_driver, +const struct usb_mux_chain usbc0_sbu_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &usbc0_sbu_mux_driver, + }, }; -const struct usb_mux usb_muxes[] = { +const struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .next_mux = &usbc0_sbu_mux, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_sbu_mux, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); @@ -222,8 +221,7 @@ void ppc_interrupt(enum gpio_signal signal) int board_set_active_charge_port(int port) { - int is_valid_port = (port >= 0 && - port < CONFIG_USB_PD_PORT_MAX_COUNT); + int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); int i; if (port == CHARGE_PORT_NONE) { @@ -244,7 +242,6 @@ int board_set_active_charge_port(int port) return EC_ERROR_INVAL; } - /* Check if the port is sourcing VBUS. */ if (ppc_is_sourcing_vbus(port)) { CPRINTFUSB("Skip enable C%d", port); @@ -308,23 +305,28 @@ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { }; BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); -static void reset_pd_port(int port, enum gpio_signal reset_gpio_l, - int hold_delay, int finish_delay) +static void reset_nct38xx_port(int port) { + enum gpio_signal reset_gpio_l; + + if (port == USBC_PORT_C0) + reset_gpio_l = GPIO_USB_C0_TCPC_RST_L; + else + /* Invalid port: do nothing */ + return; + gpio_set_level(reset_gpio_l, 0); - msleep(hold_delay); + msleep(NCT38XX_RESET_HOLD_DELAY_MS); gpio_set_level(reset_gpio_l, 1); - if (finish_delay) - msleep(finish_delay); + nct38xx_reset_notify(port); + if (NCT3807_RESET_POST_DELAY_MS != 0) + msleep(NCT3807_RESET_POST_DELAY_MS); } void board_reset_pd_mcu(void) { /* Reset TCPC0 */ - reset_pd_port(USBC_PORT_C0, GPIO_USB_C0_TCPC_RST_L, - NCT38XX_RESET_HOLD_DELAY_MS, - NCT38XX_RESET_POST_DELAY_MS); - + reset_nct38xx_port(USBC_PORT_C0); } uint16_t tcpc_get_alert_status(void) @@ -364,8 +366,7 @@ int board_pd_set_frs_enable(int port, int enable) /* Use the TCPC to enable fast switch when FRS included */ if (port == USBC_PORT_C0) { - rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, - !!enable); + rv = ioex_set_level(IOEX_USB_C0_TCPC_FASTSW_CTL_EN, !!enable); } return rv; @@ -375,7 +376,7 @@ void bc12_interrupt(enum gpio_signal signal) { switch (signal) { case GPIO_USB_C0_BC12_INT_ODL: - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); break; default: @@ -406,34 +407,87 @@ static void setup_fw_config(void) } else { motion_sensor_count = 0; /* Device is clamshell only */ - tablet_set_mode(0); + tablet_set_mode(0, TABLET_TRIGGER_LID); /* Gyro is not present, don't allow line to float */ gpio_set_flags(GPIO_6AXIS_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); } } DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); -static void wwan_lte_startup(void) +static void lte_usb3_mux_init(void) +{ + /* + * the USB_C1 port might be used for the LTE modem if it is not used + * for type-C, we need to keep the superspeed mux in USB 3 position. + */ + if (ec_config_lte_present() == LTE_PRESENT) { + const struct usb_mux usb_c1 = { + .usb_port = 1 /* USBC_PORT_C1 */, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }; + bool unused; + /* + * Note: Direct mux driver calls are deprecated. Calls + * should go through the usb_mux APIs instead. + */ + /* steer the mux to connect the USB 3 superspeed pairs */ + usb_c1.driver->set(&usb_c1, USB_PD_MUX_USB_ENABLED, &unused); + } +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, lte_usb3_mux_init, HOOK_PRIO_DEFAULT); + +static void lte_function_resume(void) +{ + gpio_set_level(GPIO_LTE_FCPO, 1); +} +DECLARE_DEFERRED(lte_function_resume); + +static void lte_power_resume(void) { - /* Turn on WWAN LTE function as we go into S0 from S5. */ gpio_set_level(GPIO_LTE_EN, 1); gpio_set_level(GPIO_LTE_W_DISABLE_L, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, wwan_lte_startup, HOOK_PRIO_DEFAULT + 1); +DECLARE_DEFERRED(lte_power_resume); -static void wwan_lte_shutdown(void) +static void lte_power_suspend(void) { - /* Turn off WWAN LTE function as we go back to S5. */ gpio_set_level(GPIO_LTE_EN, 0); gpio_set_level(GPIO_LTE_W_DISABLE_L, 0); } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, wwan_lte_shutdown, HOOK_PRIO_DEFAULT + 1); +DECLARE_DEFERRED(lte_power_suspend); +static void lte_function_suspend(void) +{ + gpio_set_level(GPIO_LTE_FCPO, 0); + hook_call_deferred(<e_power_suspend_data, 100 * MSEC); +} +DECLARE_DEFERRED(lte_function_suspend); + +static void wwan_lte_resume_hook(void) +{ + /* Turn on WWAN LTE function as we go into S0 from S3/S5. */ + hook_call_deferred(<e_function_suspend_data, -1); + hook_call_deferred(<e_power_suspend_data, -1); + lte_power_resume(); + hook_call_deferred(<e_function_resume_data, 10 * MSEC); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, wwan_lte_resume_hook, HOOK_PRIO_DEFAULT); + +static void wwan_lte_suspend_hook(void) +{ + /* Turn off WWAN LTE function as we go into S3/S5 from S0. */ + hook_call_deferred(<e_power_resume_data, -1); + hook_call_deferred(<e_function_resume_data, -1); + hook_call_deferred(<e_function_suspend_data, 20 * MSEC); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, wwan_lte_suspend_hook, HOOK_PRIO_DEFAULT); const struct pwm_t pwm_channels[] = { [PWM_CH_KBLIGHT] = { .channel = 3, - .flags = PWM_CONFIG_DSLEEP, - .freq = 100, + .flags = 0, + .freq = 15000, }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -441,7 +495,7 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); struct ioexpander_config_t ioex_config[] = { [IOEX_C0_NCT3807] = { .i2c_host_port = I2C_PORT_TCPC0, - .i2c_slave_addr = NCT38XX_I2C_ADDR1_1_FLAGS, + .i2c_addr_flags = NCT38XX_I2C_ADDR1_1_FLAGS, .drv = &nct38xx_ioexpander_drv, }, }; diff --git a/board/vilboz/board.h b/board/vilboz/board.h index ff8fa06ae3..5bda55b8d3 100644 --- a/board/vilboz/board.h +++ b/board/vilboz/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,10 +10,9 @@ #define VARIANT_ZORK_DALBOZ -#include #include "baseboard.h" -#define CONFIG_MKBP_USE_GPIO +#include #define CONFIG_USB_PD_PORT_MAX_COUNT 1 @@ -21,15 +20,15 @@ #define GPIO_USB1_ILIM_SEL GPIO_USB_A0_CHARGE_EN_L #define GPIO_USB2_ILIM_SEL GPIO_USB_A1_CHARGE_EN_DB_L -/* Power LEDs */ -#define CONFIG_LED_POWER_LED +#define CONFIG_CHARGER_PROFILE_OVERRIDE +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 /* Motion sensing drivers */ #define CONFIG_ACCELGYRO_LSM6DSM #define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCEL_LIS2DWL -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_TABLET_MODE @@ -38,47 +37,49 @@ #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL - +/* + * Vilboz's battery takes ~3 seconds to come back out of its disconnect state, + * so give it a little more for margin. + */ +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#define CONFIG_POWER_BUTTON_INIT_TIMEOUT 4 /* GPIO mapping from board specific name to EC common name. */ -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL -#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL -#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL -#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L -#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK -#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L -#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL -#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD -#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD -#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE #ifndef __ASSEMBLER__ /* This I2C moved. Temporarily detect and support the V0 HW. */ extern int I2C_PORT_BATTERY; -enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, - ADC_TEMP_SENSOR_SOC, - ADC_CH_COUNT -}; +enum adc_channel { ADC_TEMP_SENSOR_CHARGER, ADC_TEMP_SENSOR_SOC, ADC_CH_COUNT }; enum battery_type { BATTERY_SMP, BATTERY_SMP_1, BATTERY_SMP_2, + BATTERY_SMP_3, BATTERY_LGC, BATTERY_LGC_1, BATTERY_LGC_2, @@ -89,19 +90,11 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_COUNT }; -enum ioex_port { - IOEX_C0_NCT3807 = 0, - IOEX_PORT_COUNT -}; +enum ioex_port { IOEX_C0_NCT3807 = 0, IOEX_PORT_COUNT }; -#define PORT_TO_HPD(port) ((port == 0) \ - ? GPIO_USB3_C0_DP2_HPD \ - : GPIO_DP1_HPD) +#define PORT_TO_HPD(port) ((port == 0) ? GPIO_USB3_C0_DP2_HPD : GPIO_DP1_HPD) enum temp_sensor_id { TEMP_SENSOR_CHARGER = 0, @@ -110,24 +103,16 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum usba_port { - USBA_PORT_A0 = 0, - USBA_PORT_A1, - USBA_PORT_COUNT -}; +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_A1, USBA_PORT_COUNT }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_COUNT }; /***************************************************************************** * CBI EC FW Configuration */ -#include "cbi_ec_fw_config.h" /** - * DALBOZ_MB_USBAC + * VILBOZ_MB_USBAC * USB-A0 Speed: 5 Gbps * Retimer: none * USB-C0 Speed: 5 Gbps @@ -137,62 +122,22 @@ enum usbc_port { * IOEX: TCPC */ enum ec_cfg_usb_mb_type { - DALBOZ_MB_USBAC = 0, + VILBOZ_MB_USBAC = 0, }; /** - * DALBOZ_DB_D_OPT1_USBAC + * VILBOZ_DB_D_OPT1_USBA_HDMI * USB-A1 Speed: 5 Gbps - * Retimer: TUSB522 - * USB-C1 Speed: 5 Gbps - * Retimer: PS8740 - * TCPC: NCT3807 - * PPC: NX20P3483 - * IOEX: TCPC - * HDMI Exists: no - * Retimer: none - * MST Hub: none - * - * DALBOZ_DB_D_OPT2_USBA_HDMI - * USB-A1 Speed: 5 Gbps - * Retimer: TUSB522 - * USB-C1 none - * IOEX: PCAL6408 - * HDMI Exists: yes - * Retimer: PI3HDX1204 + * Retimer: None + * HDMI Retimer: PS8203 * MST Hub: none + * P-Sensor SX9324 */ enum ec_cfg_usb_db_type { - DALBOZ_DB_D_OPT1_USBAC = 0, - DALBOZ_DB_D_OPT2_USBA_HDMI = 1, + VILBOZ_DB_D_OPT1_USBA_HDMI = 0, }; -#define HAS_USBC1 \ - (BIT(DALBOZ_DB_D_OPT1_USBAC)) - -static inline bool ec_config_has_usbc1(void) -{ - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1); -} - -#define HAS_USBC1_RETIMER_PS8740 \ - (BIT(DALBOZ_DB_D_OPT1_USBAC)) - -static inline bool ec_config_has_usbc1_retimer_ps8740(void) -{ - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8740); -} - -#define HAS_HDMI_RETIMER_PI3HDX1204 \ - (BIT(DALBOZ_DB_D_OPT2_USBA_HDMI)) - -static inline bool ec_config_has_hdmi_retimer_pi3hdx1204(void) -{ - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_RETIMER_PI3HDX1204); -} +#include "cbi_ec_fw_config.h" void board_reset_pd_mcu(void); diff --git a/board/vilboz/build.mk b/board/vilboz/build.mk index 1c0cbc4f63..45c71f962c 100644 --- a/board/vilboz/build.mk +++ b/board/vilboz/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/vilboz/ec.tasklist b/board/vilboz/ec.tasklist index 08801d1786..864ca42492 100644 --- a/board/vilboz/ec.tasklist +++ b/board/vilboz/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/vilboz/gpio.inc b/board/vilboz/gpio.inc index 79ea48848f..6897f16890 100644 --- a/board/vilboz/gpio.inc +++ b/board/vilboz/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -54,8 +54,9 @@ GPIO(LED_CHRG_L, PIN(C, 0), GPIO_OUT_HIGH) GPIO(LED3_PWM, PIN(C, 3), GPIO_OUT_HIGH) /* LTE control */ -GPIO(LTE_EN, PIN(6, 2), GPIO_OUT_LOW) /* WWAN LET Fuction enable */ -GPIO(LTE_W_DISABLE_L, PIN(4, 0), GPIO_OUT_LOW) /* WWAN LET flight mode */ +GPIO(LTE_EN, PIN(6, 2), GPIO_OUT_LOW) /* WWAN LTE Function enable */ +GPIO(LTE_W_DISABLE_L, PIN(4, 0), GPIO_OUT_LOW) /* WWAN LTE flight mode */ +GPIO(LTE_FCPO, PIN(7, 3), GPIO_OUT_LOW) /* WWAN LTE Full Card Power ON OFF */ /* * Vilboz has only 1 HDMI DB option diff --git a/board/vilboz/led.c b/board/vilboz/led.c index 5b8d650936..fa28eb5f40 100644 --- a/board/vilboz/led.c +++ b/board/vilboz/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,46 +8,53 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 97; +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 97; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_RED, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_GREEN, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_RED, 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_RED, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_GREEN, + 2 * LED_ONE_SEC } }, + }; BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 3 * LED_ONE_SEC}, - {LED_OFF, 0.5 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{LED_OFF, LED_INDEFINITE} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 3 * LED_ONE_SEC }, + { LED_OFF, + 0.5 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; BUILD_ASSERT(ARRAY_SIZE(led_pwr_state_table) == PWR_LED_NUM_STATES); -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, - EC_LED_ID_POWER_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_LED3_PWM, LED_ON_LVL); @@ -56,7 +63,7 @@ void led_set_color_power(enum ec_led_colors color) gpio_set_level(GPIO_LED3_PWM, LED_OFF_LVL); } -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_GREEN: diff --git a/board/vilboz/vif_override.xml b/board/vilboz/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/vilboz/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/voema/battery.c b/board/voema/battery.c new file mode 100644 index 0000000000..dcd45d31fd --- /dev/null +++ b/board/voema/battery.c @@ -0,0 +1,96 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all Volteer battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* LGC\011 L17L3PB0 Battery Information */ + /* + * Battery info provided by ODM on b/143477210, comment #11 + */ + [BATTERY_LGC011] = { + .fuel_gauge = { + .manuf_name = "LGC", + .ship_mode = { + .reg_addr = 0x00, + .reg_data = { 0x10, 0x10 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x6000, + .disconnect_val = 0x6000, + } + }, + .batt_info = { + .voltage_max = TARGET_WITH_MARGIN(13200, 5), + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = 0, + .discharging_max_c = 75, + }, + }, + /* Panasonic AP1505L Battery Information */ + [BATTERY_PANASONIC_AP15O5L] = { + .fuel_gauge = { + .manuf_name = "PANASONIC KT00305013", + .device_name = "AP15O5L", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x4000, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, /* mV */ + .voltage_min = 9000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_PANASONIC_AP15O5L; diff --git a/board/voema/board.c b/board/voema/board.c new file mode 100644 index 0000000000..beedb0d1b9 --- /dev/null +++ b/board/voema/board.c @@ -0,0 +1,449 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board-specific configuration */ +#include "accelgyro.h" +#include "button.h" +#include "cbi_ec_fw_config.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi260.h" +#include "driver/als_tcs3400.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/ppc/syv682x.h" +#include "driver/sync.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "throttle_ap.h" +#include "uart.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config voema_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &voema_kb; +} + +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +/******************************************************************************/ +/* + * FW_CONFIG defaults for Volteer if the CBI data is not initialized. + */ +union volteer_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_ACTIVE, +}; + +static void board_init(void) +{ +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/******************************************************************************/ +/* EC thermal management configuration */ + +/* + * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 80c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C0_SENSOR_SCL, + .sda = GPIO_EC_I2C0_SENSOR_SDA, + }, + { + .name = "usb_c0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C1_USB_C0_SCL, + .sda = GPIO_EC_I2C1_USB_C0_SDA, + }, + { + .name = "usb_c1", + .port = I2C_PORT_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C2_USB_C1_SCL, + .sda = GPIO_EC_I2C2_USB_C1_SDA, + }, + { + .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C5_BATTERY_SCL, + .sda = GPIO_EC_I2C5_BATTERY_SDA, + }, + { + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C7_EEPROM_PWR_SCL_R, + .sda = GPIO_EC_I2C7_EEPROM_PWR_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/******************************************************************************/ +/* PWM configuration */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; + +static void ps8815_reset(void) +{ + int val; + + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 0); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 1); + msleep(PS8815_FW_INIT_DELAY_MS); + + /* + * b/144397088 + * ps8815 firmware 0x01 needs special configuration + */ + + CPRINTS("%s: patching ps8815 registers", __func__); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f was %02x", val); + + if (i2c_write8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f set to 0x31"); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f now %02x", val); +} + +void board_reset_pd_mcu(void) +{ + /* No reset available for TCPC on port 0 */ + /* Daughterboard specific reset for port 1 */ + ps8815_reset(); + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} + +__override void board_cbi_init(void) +{ + if ((!IS_ENABLED(TEST_BUILD) && !ec_cfg_has_numeric_pad()) || + get_board_id() <= 2) + keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); +} + +/******************************************************************************/ +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_USB_C0_FRS_EN, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/******************************************************************************/ +/* PPC support routines */ +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +/******************************************************************************/ +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* + * USB3 DB mux configuration - the top level mux still needs to be set to the + * virtual_usb_mux_driver so the AP gets notified of mux changes and updates + * the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, +}; + +/******************************************************************************/ +/* USBC mux configuration - Tiger Lake includes internal mux */ +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +/******************************************************************************/ +/* TCPC support routines */ +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; +} + +static void kb_backlight_enable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, kb_backlight_enable, HOOK_PRIO_DEFAULT); + +static void kb_backlight_disable(void) +{ + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kb_backlight_disable, HOOK_PRIO_DEFAULT); diff --git a/board/voema/board.h b/board/voema/board.h new file mode 100644 index 0000000000..f10192b0b6 --- /dev/null +++ b/board/voema/board.h @@ -0,0 +1,182 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +#define CONFIG_VBOOT_EFS2 + +#define CONFIG_POWER_BUTTON + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Chipset features */ +#define CONFIG_POWER_PP5000_CONTROL + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES + +/* Keyboard features */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_KEYBOARD_VIVALDI +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* Sensors */ +/* BMA253 accelerometer in base */ +#define CONFIG_ACCEL_BMA255 +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCEL_KX022 + +/* TCS3400 ALS */ +#define CONFIG_ALS +#define ALS_COUNT 1 +#define CONFIG_ALS_TCS3400 +#define CONFIG_ALS_TCS3400_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) + +/* Sensors without hardware FIFO are in forced mode */ +#define CONFIG_ACCEL_FORCE_MODE_MASK (board_accel_force_mode_mask()) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* TODO: b/144165680 - measure and check these values on Volteer */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ + +/* + * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C + * cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 65000 +#define PD_MAX_CURRENT_MA 3250 +#define PD_MAX_VOLTAGE_MV 20000 + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USBC PPC*/ +#undef CONFIG_SYV682X_HV_ILIM +#define CONFIG_SYV682X_HV_ILIM SYV682X_HV_ILIM_5_50 +#define CONFIG_USBC_PPC_SYV682X /* USBC port C0/C1 */ +#define CONFIG_USB_PD_FRS_PPC +#undef CONFIG_USB_PD_TCPC_RUNTIME_CONFIG +#undef CONFIG_USB_PD_TCPM_TUSB422 +#undef CONFIG_USB_MUX_RUNTIME_CONFIG + +/* BC 1.2 */ + +/* Volume Button feature */ + +/* Fan features */ +#undef CONFIG_FANS + +/* charger defines */ +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +/* Retimer */ +#undef CONFIG_USBC_RETIMER_INTEL_BB +#undef CONFIG_USBC_RETIMER_INTEL_BB_RUNTIME_CONFIG + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM + +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum battery_type { + BATTERY_LGC011, + BATTERY_PANASONIC_AP15O5L, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; + +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + CLEAR_ALS, + RGB_ALS, + SENSOR_COUNT, +}; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void board_reset_pd_mcu(void); +void motion_interrupt(enum gpio_signal signal); +int board_accel_force_mode_mask(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/voema/build.mk b/board/voema/build.mk new file mode 100644 index 0000000000..7d375fe291 --- /dev/null +++ b/board/voema/build.mk @@ -0,0 +1,18 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc + +BASEBOARD:=volteer + +board-y=board.o +board-y+=battery.o +board-y+=led.o +board-y+=sensors.o diff --git a/board/voema/ec.tasklist b/board/voema/ec.tasklist new file mode 100644 index 0000000000..c29125d517 --- /dev/null +++ b/board/voema/ec.tasklist @@ -0,0 +1,27 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/voema/gpio.inc b/board/voema/gpio.inc new file mode 100644 index 0000000000..e1a931094c --- /dev/null +++ b/board/voema/gpio.inc @@ -0,0 +1,180 @@ +/* -*- mode:c -*- + * + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) + +/* Sensor Interrupts */ +GPIO_INT(EC_ALS_RGB_INT_L, PIN(D, 4), GPIO_INT_FALLING, tcs3400_interrupt) +GPIO_INT(EC_MB_ACCEL_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) + +/* + * Base / Lid g-sensor interrupt unused on Voema, configure as regular input + * for power saving. + */ +GPIO(EC_ACCEL_INT, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) + +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) + +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) +GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) + +/* HDMI interrupts */ + +/* Volume button interrupts */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) + +/* Power Sequencing Signals */ +GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ +GPIO(EC_PCH_DSW_PWROK, PIN(C, 0), GPIO_OUT_LOW) + +/* Other wake sources */ +/* + * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an + * interrupt handler because it is automatically handled by the PSL. + * + * We need to lock the setting so this gpio can't be reconfigured to overdrive + * the real reset signal. (This is the PSL input pin not the real reset pin). + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | + GPIO_HIB_WAKE_HIGH | + GPIO_LOCKED) + +/* AP/PCH Signals */ +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) + +/* USB and USBC Signals */ +GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ +GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ +GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) +GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) +GPIO(USB_C0_FRS_EN, PIN(6, 0), GPIO_OUT_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) + +/* Don't have a load switch for retimer */ +UNIMPLEMENTED(USB_C1_LS_EN) + +/* Misc Signals */ +GPIO(EC_H1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) /* H1 Packet Mode */ +/* + * Despite their names, M2_SSD_PLN and M2_SSD_PLA are active-low, and M2_SSD_PLN + * is open-drain. + * TODO(b/138954381): Change these names when they change on the schematic. + */ +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_ODR_HIGH) /* SSD power-loss notification */ +GPIO(M2_SSD_PLA, PIN(7, 0), GPIO_INPUT) /* SSD power-loss acknowledgment */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) + +/* Unused signals */ +GPIO(UNUSED_GPIO72, PIN(7, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO41, PIN(4, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOF2, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOF3, PIN(F, 3), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO96, PIN(9, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO57, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOC2, PIN(C, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO61, PIN(6, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOB7, PIN(B, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO40, PIN(4, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOD1, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOD0, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) + +/* + * eDP backlight - both PCH and EC have enable pins that must be high + * for the backlight to turn on. Default state is high, and can be turned + * off during sleep states. + */ +GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C5_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C5_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_PWR_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_PWR_SDA_R, PIN(B, 2), GPIO_INPUT) + +/* Battery signals */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) + + /* LED */ +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) /* Blue */ +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) /* Amber */ + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */ +ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ +ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ + +/* Keyboard pins */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ + +/* UART */ +ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Power Switch Logic (PSL) inputs */ +ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ +ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, + GPIO01 = H1_EC_PWR_BTN_ODL + GPIO02 = EC_RST_ODL */ + +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ + diff --git a/board/voema/led.c b/board/voema/led.c new file mode 100644 index 0000000000..a41f549faf --- /dev/null +++ b/board/voema/led.c @@ -0,0 +1,85 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for voema + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/voema/sensors.c b/board/voema/sensors.c new file mode 100644 index 0000000000..bcb8f9ee36 --- /dev/null +++ b/board/voema/sensors.c @@ -0,0 +1,311 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific sensor configuration */ +#include "accelgyro.h" +#include "cbi_ssfc.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/als_tcs3400.h" +#include "driver/sync.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "util.h" + +/******************************************************************************/ +/* Sensors */ +static struct mutex g_lid_accel_mutex; +static struct mutex g_base_mutex; + +/* BMA253 private data */ +static struct accelgyro_saved_data_t g_bma253_base_data; +static struct accelgyro_saved_data_t g_bma253_lid_data; + +static struct icm_drv_data_t g_icm426xx_data; + +static struct kionix_accel_data g_kx022_lid_data; + +/* TCS3400 private data */ +static struct als_drv_data_t g_tcs3400_data = { + .als_cal.scale = 1, + .als_cal.uscale = 0, + .als_cal.offset = 0, + .als_cal.channel_scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ + .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */ + }, +}; + +/* + * TODO: b/146166425 need to calibrate ALS/RGB sensor. At default settings, + * shining phone flashlight on sensor pegs all readings at 0xFFFF. + */ +static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { + .calibration.rgb_cal[X] = { + .offset = 0, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + } + }, + .calibration.rgb_cal[Y] = { + .offset = 0, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + }, + .calibration.rgb_cal[Z] = { + .offset = 0, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + } + }, + .calibration.irt = INT_TO_FP(1), + .saturation.again = TCS_DEFAULT_AGAIN, + .saturation.atime = TCS_DEFAULT_ATIME, +}; + +/* Rotation matrix for the lid accelerometer */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_kx022_lid_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma253_lid_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bma2x2_accel_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bma253_base_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR2_FLAGS, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [CLEAR_ALS] = { + .name = "Clear Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT, + .location = MOTIONSENSE_LOC_BASE, + .drv = &tcs3400_drv, + .drv_data = &g_tcs3400_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + .min_frequency = TCS3400_LIGHT_MIN_FREQ, + .max_frequency = TCS3400_LIGHT_MAX_FREQ, + .config = { + /* Run ALS sensor in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 1000, + }, + }, + }, + + [RGB_ALS] = { + /* + * RGB channels read by CLEAR_ALS and so the i2c port and + * address do not need to be defined for RGB_ALS. + */ + .name = "RGB Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT_RGB, + .location = MOTIONSENSE_LOC_BASE, + .drv = &tcs3400_rgb_drv, + .drv_data = &g_tcs3400_rgb_data, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +struct motion_sensor_t icm_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ +const struct motion_sensor_t *motion_als_sensors[] = { + &motion_sensors[CLEAR_ALS], +}; +BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); + +static void baseboard_sensors_init(void) +{ + /* Enable interrupt for the TCS3400 color light sensor */ + gpio_enable_interrupt(GPIO_EC_ALS_RGB_INT_L); + + /* + * TODO: If a SSFC for the base sensor is added, add the check + * here. + */ + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) { + gpio_enable_interrupt(GPIO_EC_MB_ACCEL_INT_L); + motion_sensors[BASE_ACCEL] = icm_base_accel; + motion_sensors[BASE_GYRO] = icm_base_gyro; + ccprints("BASE ACCEL/GYRO is ICM426XX"); + } else + ccprints("BASE_ACCEL is BMA253"); + + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LID_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + ccprints("LID_ACCEL is KX022"); + } else + ccprints("LID_ACCEL is BMA253"); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); + +void motion_interrupt(enum gpio_signal signal) +{ + icm426xx_interrupt(signal); +} + +int board_accel_force_mode_mask(void) +{ + if (system_get_board_version() <= 2) + return (BIT(LID_ACCEL) | BIT(CLEAR_ALS) | BIT(BASE_ACCEL)); + else + return (BIT(LID_ACCEL) | BIT(CLEAR_ALS)); +} diff --git a/board/voema/vif_override.xml b/board/voema/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/voema/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/volet/battery.c b/board/volet/battery.c new file mode 100644 index 0000000000..89769e8364 --- /dev/null +++ b/board/volet/battery.c @@ -0,0 +1,125 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all Volteer battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* AP19B8M */ + [BATTERY_AP19B8M] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G024", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13350, + .voltage_normal = 11610, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* LGC AP18C8K Battery Information */ + [BATTERY_LGC_AP18C8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G020", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* COSMX AP20CBL Battery Information */ + [BATTERY_COSMX_AP20CBL] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B002", + .device_name = "AP20CBL", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AP19B8M; diff --git a/board/volet/board.c b/board/volet/board.c new file mode 100644 index 0000000000..222fdde37e --- /dev/null +++ b/board/volet/board.c @@ -0,0 +1,509 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board-specific configuration */ +#include "accelgyro.h" +#include "button.h" +#include "cbi_ec_fw_config.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/als_tcs3400.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/ppc/syv682x.h" +#include "driver/sync.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "fan.h" +#include "fan_chip.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "throttle_ap.h" +#include "uart.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" +#include "usbc_ppc.h" +#include "util.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static const struct ec_response_keybd_config volet_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config volet_kb_num = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (!ec_cfg_has_numeric_pad()) + return &volet_kb; + else + return &volet_kb_num; +} + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfe, 0xff, 0xff, + 0xff, /* full set */ + }, +}; + +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +__override uint32_t board_override_feature_flags0(uint32_t flags0) +{ + /* + * Remove keyboard backlight feature for devices that don't support it. + */ + if (!ec_cfg_has_keyboard_backlight()) + return (flags0 & ~EC_FEATURE_MASK_0(EC_FEATURE_PWM_KEYB)); + else + return flags0; +} + +/******************************************************************************/ +/* + * FW_CONFIG defaults for Voxel if the CBI data is not initialized. + */ +union volteer_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB4_GEN3, +}; + +/******************************************************************************/ +/* Physical fans. These are logically separate from pwm_channels. */ + +const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * Fan specs from datasheet: + * Max speed 5900 rpm (+/- 7%), minimum duty cycle 30%. + * Minimum speed not specified by RPM. Set minimum RPM to max speed (with + * margin) x 30%. + * 5900 x 1.07 x 0.30 = 1894, round up to 1900 + * reference that temperature and fan settings + * are derived from data in b/167523658#39 + */ +const struct fan_rpm fan_rpm_0 = { + .rpm_min = 2100, + .rpm_start = 2100, + .rpm_max = 5800, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +/******************************************************************************/ +/* EC thermal management configuration */ + +/* + * Reference that temperature and fan settings + * are derived from data in b/167523658#39 + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(90), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_CHARGER] = THERMAL_CPU, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_CPU, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); + +/******************************************************************************/ +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +/******************************************************************************/ +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C0_SENSOR_SCL, + .sda = GPIO_EC_I2C0_SENSOR_SDA, + }, + { + .name = "usb_c0", + .port = I2C_PORT_USB_C0, + .kbps = 1000, + .scl = GPIO_EC_I2C1_USB_C0_SCL, + .sda = GPIO_EC_I2C1_USB_C0_SDA, + }, + { + .name = "usb_c1", + .port = I2C_PORT_USB_C1, + .kbps = 1000, + .scl = GPIO_EC_I2C2_USB_C1_SCL, + .sda = GPIO_EC_I2C2_USB_C1_SDA, + }, + { + .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C5_POWER_SCL, + .sda = GPIO_EC_I2C5_POWER_SDA, + }, + { + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C7_EEPROM_SCL, + .sda = GPIO_EC_I2C7_EEPROM_SDA, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/******************************************************************************/ +/* PWM configuration */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void kb_backlight_enable(void) +{ + if (ec_cfg_has_keyboard_backlight()) + gpio_set_level(GPIO_EC_KB_BL_EN, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, kb_backlight_enable, HOOK_PRIO_DEFAULT); + +static void kb_backlight_disable(void) +{ + if (ec_cfg_has_keyboard_backlight()) + gpio_set_level(GPIO_EC_KB_BL_EN, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kb_backlight_disable, HOOK_PRIO_DEFAULT); + +static void ps8815_reset(void) +{ + int val; + + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 0); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 1); + msleep(PS8815_FW_INIT_DELAY_MS); + + /* + * b/144397088 + * ps8815 firmware 0x01 needs special configuration + */ + + CPRINTS("%s: patching ps8815 registers", __func__); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f was %02x", val); + + if (i2c_write8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f set to 0x31"); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f now %02x", val); +} + +void board_reset_pd_mcu(void) +{ + /* + * Only the Burnside Bridge retimers provide a reset pin, but this is + * already handled by the bb_retimer.c driver. + */ + ps8815_reset(); + usb_mux_hpd_update(USBC_PORT_C1, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; + +/******************************************************************************/ +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + .frs_en = GPIO_USB_C0_FRS_EN, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + .frs_en = GPIO_USB_C1_FRS_EN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/******************************************************************************/ +/* PPC support routines */ +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +__override void board_cbi_init(void) +{ + if ((!IS_ENABLED(TEST_BUILD) && !ec_cfg_has_numeric_pad())) { + keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); + /* Search key is moved back to col=1,row=0 */ + keyscan_config.actual_key_mask[0] = 0x14; + keyscan_config.actual_key_mask[1] = 0xff; + keyscan_config.actual_key_mask[11] = 0xfa; + keyscan_config.actual_key_mask[12] = 0xca; + } +} + +/******************************************************************************/ +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/* + * USB3 DB mux configuration - the top level mux still needs to be set to the + * virtual_usb_mux_driver so the AP gets notified of mux changes and updates + * the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, +}; + +/******************************************************************************/ +/* USBC mux configuration - Tiger Lake includes internal mux */ +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +/******************************************************************************/ +/* TCPC support routines */ +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; +} diff --git a/board/volet/board.h b/board/volet/board.h new file mode 100644 index 0000000000..c616b1cbe1 --- /dev/null +++ b/board/volet/board.h @@ -0,0 +1,187 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* Baseboard features */ +#include "baseboard.h" + +/* Optional features */ +#undef NPCX7_PWM1_SEL +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ + +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +#define CONFIG_VBOOT_EFS2 + +#define CONFIG_POWER_BUTTON + +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 4096 + +/* Chipset features */ +#define CONFIG_POWER_PP5000_CONTROL +#define CONFIG_CPU_PROCHOT_GATE_ON_C10 + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES + +/* Keyboard features */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* Keyboard backliht */ +#define CONFIG_PWM +#define CONFIG_PWM_KBLIGHT + +/* Sensors */ +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT +/* BMI160 Base accel/gyro */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel second source*/ +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) + +/* BMA253 Lid accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCEL_BMA255 +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +/* USB Type C and USB PD defines */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ + +/* + * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C + * cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY +#ifdef BOARD_VOXEL_ECMODEENTRY +#undef CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY +#endif + +/* Enabling Thunderbolt-compatible mode */ +#define CONFIG_USB_PD_TBT_COMPAT_MODE + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USBC PPC*/ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C0/C1 */ +#define CONFIG_USB_PD_FRS_PPC +#undef CONFIG_USB_PD_TCPC_RUNTIME_CONFIG +#undef CONFIG_USB_PD_TCPM_TUSB422 +#undef CONFIG_USB_MUX_RUNTIME_CONFIG + +/* BC 1.2 */ + +/* Volume Button feature */ + +/* Fan features */ + +/* charger defines */ +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +/* Retimer */ +#undef CONFIG_USBC_RETIMER_INTEL_BB +#undef CONFIG_USBC_RETIMER_INTEL_BB_RUNTIME_CONFIG + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL + +/* I2C Bus Configuration */ +#define CONFIG_I2C +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM + +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum battery_type { + BATTERY_AP19B8M, + BATTERY_LGC_AP18C8K, + BATTERY_COSMX_AP20CBL, + BATTERY_TYPE_COUNT, +}; + +enum pwm_channel { PWM_CH_FAN, PWM_CH_KBLIGHT, PWM_CH_COUNT }; + +enum sensor_id { + LID_ACCEL = 0, + BASE_ACCEL, + BASE_GYRO, + SENSOR_COUNT, +}; + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void board_reset_pd_mcu(void); + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/volet/build.mk b/board/volet/build.mk new file mode 100644 index 0000000000..18397fdec3 --- /dev/null +++ b/board/volet/build.mk @@ -0,0 +1,17 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=volteer + +board-y=board.o +board-y+=battery.o +board-y+=led.o +board-y+=sensors.o diff --git a/board/volet/ec.tasklist b/board/volet/ec.tasklist new file mode 100644 index 0000000000..07a91894ed --- /dev/null +++ b/board/volet/ec.tasklist @@ -0,0 +1,27 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, TASK_STACK_SIZE) diff --git a/board/volet/gpio.inc b/board/volet/gpio.inc new file mode 100644 index 0000000000..079c731785 --- /dev/null +++ b/board/volet/gpio.inc @@ -0,0 +1,184 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* Wake Source interrupts */ +GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(EC_WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(H1_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) + +/* Power sequencing interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +#endif +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) + +/* Sensor Interrupts */ +GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO(EC_ALS_RGB_INT_L, PIN(D, 4), GPIO_INPUT | GPIO_PULL_UP) /* unused */ +GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) +/* + * Lid g-sensor interrupt unused on Voxel, configure as regular input for + * power saving. + */ +GPIO(EC_ACCEL_INT, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_BOTH, tcpc_alert_event) + +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_BOTH, ppc_interrupt) + +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(E, 4), GPIO_INT_BOTH, bc12_interrupt) +GPIO_INT(USB_C1_MIX_INT_ODL, PIN(0, 3), GPIO_INT_BOTH, bc12_interrupt) + +/* HDMI interrupts */ + +/* Volume button interrupts */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) + +/* Power Sequencing Signals */ +GPIO(EN_PP3300_A, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_A, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_PPVAR_VCCIN, PIN(4, 3), GPIO_OUT_LOW) /* Enables VCCIN IMPV9 */ +GPIO(EC_PCH_DSW_PWROK, PIN(C, 0), GPIO_OUT_LOW) + +/* Other wake sources */ +/* + * GPIO_INT_BOTH is required for PSL wake from hibernate, but we don't need an + * interrupt handler because it is automatically handled by the PSL. + * + * We need to lock the setting so this gpio can't be reconfigured to overdrive + * the real reset signal. (This is the PSL input pin not the real reset pin). + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INT_BOTH | + GPIO_HIB_WAKE_HIGH | + GPIO_LOCKED) + +/* AP/PCH Signals */ +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_RSMRST_ODL, PIN(A, 6), GPIO_ODR_LOW) /* TODO - b/140950085 - implement TGL sequencing requirement */ +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_RISING, throttle_ap_c10_input_interrupt) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) + +/* USB and USBC Signals */ +GPIO(EN_PP5000_USBA, PIN(3, 5), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ +GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ + +/* + * USB_C1 moved from GPIO32 to GPIO83 on boards with board ID >=1. + * GPIO83/EN_PP1800_A is DNS on board ID 0 and GPIO32 is N/C on board ID >=1 + * so it's safe to define GPIOs compatible with both designs. + * TODO (b/149858568): remove board ID=0 support. + */ +GPIO(USB_C0_RT_RST_ODL, PIN(4, 1), GPIO_ODR_LOW) +GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset on boards board ID >=1 */ +GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) +GPIO(USB_C0_RT_INT_ODL, PIN(C, 6), GPIO_INPUT) +GPIO(USB_C1_RT_INT_ODL, PIN(9, 6), GPIO_INPUT) +GPIO(USB_C0_FRS_EN, PIN(C, 2), GPIO_OUT_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) + +/* Don't have a load switch for retimer */ +UNIMPLEMENTED(USB_C0_LS_EN) +UNIMPLEMENTED(USB_C1_LS_EN) + +/* Misc Signals */ +GPIO(EC_H1_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) /* H1 Packet Mode */ +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) /* Blue */ +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) /* Yellow */ +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_OUT_LOW) /* Keyboard backlight enable*/ + +GPIO(M2_SSD_PLN, PIN(A, 0), GPIO_ODR_HIGH) /* SSD power-loss notification */ +GPIO(M2_SSD_PLA, PIN(7, 0), GPIO_INPUT) /* SSD power-loss acknowledgment */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ +GPIO(EC_SLP_S0IX, PIN(7, 2), GPIO_INPUT | GPIO_PULL_UP) + +/* Unused signals */ +GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIO60, PIN(6, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOA7, PIN(A, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOD0, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOD1, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOF2, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(UNUSED_GPIOF3, PIN(F, 3), GPIO_INPUT | GPIO_PULL_UP) + +/* + * eDP backlight - both PCH and EC have enable pins that must be high + * for the backlight to turn on. Default state is high, and can be turned + * off during sleep states. + */ +GPIO(EC_EDP_BL_EN, PIN(D, 3), GPIO_OUT_HIGH) + +/* I2C pins - Alternate function below configures I2C module on these pins */ +GPIO(EC_I2C0_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C0_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C1_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C1_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C2_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C5_POWER_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C5_POWER_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C7_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) + +/* Battery signals */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 1), GPIO_INPUT) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(B, BIT(5) | BIT(4)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V)) /* I2C0 */ +ALTERNATE(PIN_MASK(9, BIT(0) | BIT(2) | BIT(1)), 0, MODULE_I2C, 0) /* I2C1 SCL / I2C2 */ +ALTERNATE(PIN_MASK(8, BIT(7)), 0, MODULE_I2C, 0) /* I2C1 SDA */ +ALTERNATE(PIN_MASK(3, BIT(3) | BIT(6)), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) /* I2C7 */ + +/* Fan signals */ +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_LOW) +ALTERNATE(PIN_MASK(B, BIT(7)), 0, MODULE_PWM, 0) /* FAN_PWM */ +ALTERNATE(PIN_MASK(4, BIT(0)), 0, MODULE_PWM, 0) /* FAN_SPEED_TACH */ + +/* Keyboard pins */ +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_00-01 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_KB_INPUT) /* KSI_02-07 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_00-01 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_03-09 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO_14 */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* EC_KB_BL_PWM */ + +/* UART */ +ALTERNATE(PIN_MASK(6, BIT(5) | BIT(4)), 0, MODULE_UART, 0) /* UART from EC to Servo */ + +/* Power Switch Logic (PSL) inputs */ +ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) /* GPIOD2 = EC_LID_OPEN */ +ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = ACOK_OD, + GPIO01 = H1_EC_PWR_BTN_ODL + GPIO02 = EC_RST_ODL */ + +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ diff --git a/board/volet/led.c b/board/volet/led.c new file mode 100644 index 0000000000..2458e882e3 --- /dev/null +++ b/board/volet/led.c @@ -0,0 +1,84 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for Volteer + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} diff --git a/board/volet/sensors.c b/board/volet/sensors.c new file mode 100644 index 0000000000..932b39f43e --- /dev/null +++ b/board/volet/sensors.c @@ -0,0 +1,241 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific sensor configuration */ +#include "accelgyro.h" +#include "cbi_ec_fw_config.h" +#include "cbi_ssfc.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/als_tcs3400.h" +#include "driver/sync.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_scan.h" +#include "tablet_mode.h" +#include "task.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args) +/******************************************************************************/ +/* Sensors */ +static struct mutex g_lid_accel_mutex; +static struct mutex g_base_mutex; + +/* BMA253 private data */ +static struct accelgyro_saved_data_t g_bma253_data; +static struct kionix_accel_data g_kx022_data; + +/* BMI160 private data */ +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; + +/* Rotation matrix for the lid accelerometer */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void board_sensors_init(void) +{ + if (ec_cfg_has_tabletmode()) { + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_BASE_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE GYRO is ICM426XX"); + } else + ccprints("BASE GYRO is BMI160"); + + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LID_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + ccprints("LID_ACCEL is KX022"); + } else + ccprints("LID_ACCEL is BMA253"); + + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable interrupt for the accel/gyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_EC_IMU_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + } +} +DECLARE_HOOK(HOOK_INIT, board_sensors_init, HOOK_PRIO_DEFAULT); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (get_cbi_ssfc_base_sensor()) { + case SSFC_SENSOR_BASE_ICM426XX: + icm426xx_interrupt(signal); + break; + case SSFC_SENSOR_BASE_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} diff --git a/board/volet/vif_override.xml b/board/volet/vif_override.xml new file mode 100644 index 0000000000..56d132401e --- /dev/null +++ b/board/volet/vif_override.xml @@ -0,0 +1,158 @@ + + + Voxel + 0 + 0 + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 9A1B + + + + 8087 + + + + + + Not TBT3-Compatible + + + + + + + + Gen 3 (40Gb) + + + + + + + + + + HBR3 + 4 Lanes + + + USB 3.2 Gen 2x1 + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + PSD + Alternate Mode Controller (AMC) + + + 18D1 + 0000 + + + + + + 8087 + + + + + + + 00000000 + + + + + + + Gen 3 (40Gb) + + + + + + + + + + HBR3 + 4 Lanes + + + USB 3.2 Gen 2x1 + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + PSD + Alternate Mode Controller (AMC) + + + 18D1 + 0000 + + + + + + 8087 + + + + + + + 00000000 + + + + + + diff --git a/board/volmar/battery.c b/board/volmar/battery.c new file mode 100644 index 0000000000..852ed4b137 --- /dev/null +++ b/board/volmar/battery.c @@ -0,0 +1,238 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "cbi.h" +#include "charge_ramp.h" +#include "charge_state.h" +#include "charger_profile_override.h" +#include "common.h" +#include "compile_time_macros.h" +#include "gpio.h" +/* + * Battery info for all Volmar battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* COSMX AP20CBL Battery Information */ + [BATTERY_COSMX_AP20CBL] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B002", + .device_name = "AP20CBL", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* COSMX AP20CBL Battery Information (new firmware ver) */ + [BATTERY_COSMX_AP20CBL_004] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B004", + .device_name = "AP20CBL", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* LGC AP18C8K Battery Information */ + [BATTERY_LGC_AP18C8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G020", + .device_name = "AP18C8K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* LGC AP19B8M Battery Information */ + [BATTERY_AP19B8M] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G024", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13350, + .voltage_normal = 11610, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_COSMX_AP20CBL; + +enum battery_present battery_hw_present(void) +{ + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} + +static int charger_should_discharge_on_ac(struct charge_state_data *curr) +{ + /* can not discharge on AC without battery */ + if (curr->batt.is_present != BP_YES) + return 0; + + /* Do not discharge when battery disconnect */ + if (battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED) + return 0; + + /* Do not discharge on AC if the battery is still waking up */ + if ((curr->batt.flags & BATT_FLAG_BAD_STATUS) || + (!(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + !(curr->batt.status & STATUS_FULLY_CHARGED))) + return 0; + + /* + * In heavy load (>3A being withdrawn from VSYS) the DCDC of the + * charger operates on hybrid mode. This causes a slight voltage + * ripple on VSYS that falls in the audible noise frequency (single + * digit kHz range). This small ripple generates audible noise in + * the output ceramic capacitors (caps on VSYS and any input of + * DCDC under VSYS). + * + * To overcome this issue, force battery discharging when battery + * full, So the battery MOS of NVDC charger will turn on always, + * it make the Vsys same as Vbat and the noise has been improved. + */ + if (!battery_is_cut_off() && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + return 1; + + return 0; +} + +/* + * This can override the smart battery's charging profile. To make a change, + * modify one or more of requested_voltage, requested_current, or state. + * Leave everything else unchanged. + * + * Return the next poll period in usec, or zero to use the default (which is + * state dependent). + */ +int charger_profile_override(struct charge_state_data *curr) +{ + int disch_on_ac = charger_should_discharge_on_ac(curr); + + charger_discharge_on_ac(disch_on_ac); + + if (disch_on_ac) { + curr->state = ST_DISCHARGE; + return 0; + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/volmar/board.c b/board/volmar/board.c new file mode 100644 index 0000000000..e87a43a030 --- /dev/null +++ b/board/volmar/board.c @@ -0,0 +1,73 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "button.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "switch.h" +#include "throttle_ap.h" +#include "usbc_config.h" + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +__override void board_cbi_init(void) +{ + config_usb_db_type(); +} + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Allow keyboard backlight to be enabled */ + + gpio_set_level(GPIO_EC_KB_BL_EN_L, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* Turn off the keyboard backlight if it's on. */ + + gpio_set_level(GPIO_EC_KB_BL_EN_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* keyboard factory test */ +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif diff --git a/board/volmar/board.h b/board/volmar/board.h new file mode 100644 index 0000000000..12561dc314 --- /dev/null +++ b/board/volmar/board.h @@ -0,0 +1,196 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volmar board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "compile_time_macros.h" + +/* Baseboard features */ +#include "baseboard.h" + +/* + * This will happen automatically on NPCX9 ES2 and later. Do not remove + * until we can confirm all earlier chips are out of service. + */ +#define CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + +#define CONFIG_MP2964 + +/* Tablet mode is not supported */ +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH +#undef CONFIG_LID_ANGLE + +/* LED */ +#define CONFIG_LED_ONOFF_STATES + +/* USB Type A Features */ +#define USB_PORT_COUNT 1 +#define CONFIG_USB_PORT_POWER_DUMB + +/* USB Type C and USB PD defines */ +#undef CONFIG_USB_PD_TCPM_NCT38XX +#define CONFIG_USB_PD_TCPM_RT1715 /* C0 */ +#define CONFIG_USB_PD_TCPM_PS8815 /* C1 */ +#define CONFIG_USB_PD_TCPM_PS8815_FORCE_DID + +/* Retimer */ +#undef CONFIG_USBC_RETIMER_INTEL_BB + +/* I2C speed console command */ +#define CONFIG_CMD_I2C_SPEED + +/* I2C control host command */ +#define CONFIG_HOSTCMD_I2C_CONTROL + +#define CONFIG_USBC_PPC_SYV682X + +/* TODO: b/177608416 - measure and check these values on brya */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * Passive USB-C cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +#define CONFIG_CHARGER_PROFILE_OVERRIDE +#define CONFIG_PWR_STATE_DISCHARGE_FULL + +/* + * Macros for GPIO signals used in common code that don't match the + * schematic names. Signal names in gpio.inc match the schematic and are + * then redefined here to so it's more clear which signal is being used for + * which purpose. + */ +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_ENABLE_BACKLIGHT GPIO_EC_EN_EDP_BL +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_GSC_PACKET_MODE +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_L +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SYS_SLP_S0IX_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_TEMP_SENSOR_POWER GPIO_SEQ_EC_DSW_PWROK + +/* + * GPIO_EC_PCH_INT_ODL is used for MKBP events as well as a PCH wakeup + * signal. + */ +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_INT_ODL +#define GPIO_PG_EC_ALL_SYS_PWRGD GPIO_SEQ_EC_ALL_SYS_PG +#define GPIO_PG_EC_DSW_PWROK GPIO_SEQ_EC_DSW_PWROK +#define GPIO_PG_EC_RSMRST_ODL GPIO_SEQ_EC_RSMRST_ODL +#define GPIO_POWER_BUTTON_L GPIO_GSC_EC_PWR_BTN_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_ODL + +/* System has back-lit keyboard */ +#define CONFIG_PWM_KBLIGHT + +/* I2C Bus Configuration */ + +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 + +#define I2C_PORT_USB_C0_C2_TCPC NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1_TCPC NPCX_I2C_PORT4_1 + +#define I2C_PORT_USB_C0_C2_PPC NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_PPC NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C0_C2_BC12 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_C1_BC12 NPCX_I2C_PORT6_1 + +#define I2C_PORT_USB_C1_MUX NPCX_I2C_PORT6_1 + +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_CHARGER NPCX_I2C_PORT7_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0 + +#define I2C_ADDR_EEPROM_FLAGS 0x50 + +#define I2C_ADDR_MP2964_FLAGS 0x20 + +/* Thermal features */ +#define CONFIG_THERMISTOR +#define CONFIG_TEMP_SENSOR +#define CONFIG_TEMP_SENSOR_POWER +#define CONFIG_STEINHART_HART_3V3_30K9_47K_4050B + +#define CONFIG_FANS FAN_CH_COUNT + +/* Charger defines */ +#define CONFIG_CHARGER_ISL9241 +#define CONFIG_CHARGE_RAMP_SW +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 + +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#define CONFIG_POWER_BUTTON_INIT_TIMEOUT 2 + +/* Keyboard */ +#define CONFIG_KEYBOARD_REFRESH_ROW3 +#define CONFIG_KEYBOARD_FACTORY_TEST + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" /* needed by registers.h */ +#include "registers.h" +#include "usbc_config.h" + +enum adc_channel { + ADC_TEMP_SENSOR_1_DDR_SOC, + ADC_TEMP_SENSOR_2_FAN, + ADC_TEMP_SENSOR_3_CHARGER, + ADC_CH_COUNT +}; + +enum temp_sensor_id { + TEMP_SENSOR_1_DDR_SOC, + TEMP_SENSOR_2_FAN, + TEMP_SENSOR_3_CHARGER, + TEMP_SENSOR_COUNT +}; + +enum battery_type { + BATTERY_COSMX_AP20CBL, + BATTERY_COSMX_AP20CBL_004, + BATTERY_LGC_AP18C8K, + BATTERY_AP19B8M, + BATTERY_TYPE_COUNT +}; + +enum pwm_channel { + PWM_CH_KBLIGHT = 0, /* PWM3 */ + PWM_CH_FAN, /* PWM5 */ + PWM_CH_COUNT +}; + +enum fan_channel { FAN_CH_0 = 0, FAN_CH_COUNT }; + +enum mft_channel { MFT_CH_0 = 0, MFT_CH_COUNT }; + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +extern const int keyboard_factory_scan_pins[][2]; +extern const int keyboard_factory_scan_pins_used; +#endif + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/volmar/build.mk b/board/volmar/build.mk new file mode 100644 index 0000000000..ed25f9c9aa --- /dev/null +++ b/board/volmar/build.mk @@ -0,0 +1,25 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Volmar board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx9 +CHIP_VARIANT:=npcx9m3f +BASEBOARD:=brya + +board-y= +board-y+=battery.o +board-y+=board.o +board-y+=charger.o +board-y+=fans.o +board-y+=fw_config.o +board-y+=i2c.o +board-y+=keyboard.o +board-y+=led.o +board-y+=pwm.o +board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/volmar/charger.c b/board/volmar/charger.c new file mode 100644 index 0000000000..76e2712181 --- /dev/null +++ b/board/volmar/charger.c @@ -0,0 +1,80 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/charger/isl9241.h" +#include "usb_pd.h" +#include "usbc_ppc.h" +#include "util.h" + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Charger Chip Configuration */ +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL9241_ADDR_FLAGS, + .drv = &isl9241_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(chg_chips) == CHARGER_NUM); + +int board_set_active_charge_port(int port) +{ + int is_valid_port = board_is_usb_pd_port_present(port); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} diff --git a/board/volmar/ec.tasklist b/board/volmar/ec.tasklist new file mode 100644 index 0000000000..70b64bc757 --- /dev/null +++ b/board/volmar/ec.tasklist @@ -0,0 +1,29 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + * + * USB_CHG_Px tasks must be contiguous (see USB_CHG_PORT_TO_TASK_ID(x)). + * PD_Cx tasks must be contiguous (see PD_PORT_TO_TASK_ID(x)) + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, HOOKS_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, BASEBOARD_CHG_RAMP_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 0, TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, BASEBOARD_CHARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, BASEBOARD_CHIPSET_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, CONSOLE_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, BASEBOARD_POWERBTN_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, BASEBOARD_PD_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_shared_alert_task, (BIT(2) | BIT(0)), BASEBOARD_PD_INT_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, BASEBOARD_PD_INT_TASK_STACK_SIZE) diff --git a/board/volmar/fans.c b/board/volmar/fans.c new file mode 100644 index 0000000000..6b87f9cba3 --- /dev/null +++ b/board/volmar/fans.c @@ -0,0 +1,89 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Physical fans. These are logically separate from pwm_channels. */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "fan.h" +#include "fan_chip.h" +#include "hooks.h" +#include "pwm.h" + +/* MFT channels. These are logically separate from pwm_channels. */ +const struct mft_t mft_channels[] = { + [MFT_CH_0] = { + .module = NPCX_MFT_MODULE_1, + .clk_src = TCKC_LFCLK, + .pwm_id = PWM_CH_FAN, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); + +static const struct fan_conf fan_conf_0 = { + .flags = FAN_USE_RPM_MODE, + .ch = MFT_CH_0, /* Use MFT id to control fan */ + .pgood_gpio = -1, + .enable_gpio = GPIO_EN_PP5000_FAN, +}; + +/* + * TOOD(b/181271666): thermistor placement and calibration + * + * Prototype fan spins at about 4200 RPM at 100% PWM, this + * is specific to board ID 2 and might also apears in later + * boards as well. + */ +static const struct fan_rpm fan_rpm_0 = { + .rpm_min = 3000, + .rpm_start = 3000, + .rpm_max = 6000, +}; + +const struct fan_t fans[FAN_CH_COUNT] = { + [FAN_CH_0] = { + .conf = &fan_conf_0, + .rpm = &fan_rpm_0, + }, +}; + +#ifndef CONFIG_FANS + +/* + * TODO(b/181271666): use static fan speeds until fan and sensors are + * tuned. for now, use: + * + * AP off: 33% + * AP on: 100% + */ + +static void fan_slow(void) +{ + const int duty_pct = 33; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +static void fan_max(void) +{ + const int duty_pct = 100; + + ccprints("%s: speed %d%%", __func__, duty_pct); + + pwm_enable(PWM_CH_FAN, 1); + pwm_set_duty(PWM_CH_FAN, duty_pct); +} + +DECLARE_HOOK(HOOK_INIT, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, fan_slow, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, fan_max, HOOK_PRIO_FIRST); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, fan_max, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_FANS */ diff --git a/board/volmar/fw_config.c b/board/volmar/fw_config.c new file mode 100644 index 0000000000..5c62ed17b8 --- /dev/null +++ b/board/volmar/fw_config.c @@ -0,0 +1,61 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "cros_board_info.h" +#include "fw_config.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static union volmar_cbi_fw_config fw_config; +BUILD_ASSERT(sizeof(fw_config) == sizeof(uint32_t)); + +/* + * FW_CONFIG defaults for volmar if the CBI.FW_CONFIG data is not + * initialized. + */ +static const union volmar_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB3_PS8815, + .kb_bl = KEYBOARD_BACKLIGHT_ENABLED, +}; + +/**************************************************************************** + * Volmar FW_CONFIG access + */ +void board_init_fw_config(void) +{ + if (cbi_get_fw_config(&fw_config.raw_value)) { + CPRINTS("CBI: Read FW_CONFIG failed, using board defaults"); + fw_config = fw_config_defaults; + } + + if (get_board_id() == 0) { + /* + * Early boards have a zero'd out FW_CONFIG, so replace + * it with a sensible default value. If DB_USB_ABSENT2 + * was used as an alternate encoding of DB_USB_ABSENT to + * avoid the zero check, then fix it. + */ + if (fw_config.raw_value == 0) { + CPRINTS("CBI: FW_CONFIG is zero, using board defaults"); + fw_config = fw_config_defaults; + } else if (fw_config.usb_db == DB_USB_ABSENT2) { + fw_config.usb_db = DB_USB_ABSENT; + } + } +} + +union volmar_cbi_fw_config get_fw_config(void) +{ + return fw_config; +} + +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void) +{ + return fw_config.usb_db; +} diff --git a/board/volmar/fw_config.h b/board/volmar/fw_config.h new file mode 100644 index 0000000000..4dddec9273 --- /dev/null +++ b/board/volmar/fw_config.h @@ -0,0 +1,54 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __BOARD_VOLMAR_FW_CONFIG_H_ +#define __BOARD_VOLMAR_FW_CONFIG_H_ + +#include + +/**************************************************************************** + * CBI FW_CONFIG layout for Volmar board. + * + * Source of truth is the project/brya/volmar/config.star configuration file. + */ + +enum ec_cfg_usb_db_type { + DB_USB_ABSENT = 0, + DB_USB3_PS8815 = 1, + DB_USB_ABSENT2 = 15 +}; + +enum ec_cfg_keyboard_backlight_type { + KEYBOARD_BACKLIGHT_DISABLED = 0, + KEYBOARD_BACKLIGHT_ENABLED = 1 +}; + +union volmar_cbi_fw_config { + struct { + enum ec_cfg_usb_db_type usb_db : 4; + enum ec_cfg_keyboard_backlight_type kb_bl : 1; + uint32_t audio : 3; + uint32_t boot_nvme_mask : 1; + uint32_t boot_emmc_mask : 1; + uint32_t reserved_1 : 22; + }; + uint32_t raw_value; +}; + +/** + * Read the cached FW_CONFIG. Guaranteed to have valid values. + * + * @return the FW_CONFIG for the board. + */ +union volmar_cbi_fw_config get_fw_config(void); + +/** + * Get the USB daughter board type from FW_CONFIG. + * + * @return the USB daughter board type. + */ +enum ec_cfg_usb_db_type ec_cfg_usb_db_type(void); + +#endif /* __BOARD_VOLMAR_FW_CONFIG_H_ */ diff --git a/board/volmar/gpio.inc b/board/volmar/gpio.inc new file mode 100644 index 0000000000..b1d4e8c3dc --- /dev/null +++ b/board/volmar/gpio.inc @@ -0,0 +1,141 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define MODULE_KB MODULE_KEYBOARD_SCAN + +/* INTERRUPT GPIOs: */ +GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_interrupt) +GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(9, 3), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(9, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(EC_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(GSC_EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW, power_button_interrupt) +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt) +GPIO_INT(SEQ_EC_ALL_SYS_PG, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SEQ_EC_RSMRST_ODL, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SYS_SLP_S0IX_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(USB_C0_BC12_INT_ODL, PIN(C, 6), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C0_C2_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_BC12_INT_ODL, PIN(5, 0), GPIO_INT_FALLING, bc12_interrupt) +GPIO_INT(USB_C1_PPC_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, ppc_interrupt) +GPIO_INT(USB_C1_TCPC_INT_ODL, PIN(A, 2), GPIO_INT_FALLING, tcpc_alert_event) + +/* USED GPIOs: */ +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CHARGER_VAP_OTG_EN, PIN(7, 3), GPIO_OUT_LOW) +GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) +GPIO(EC_BATT_PRES_ODL, PIN(A, 3), GPIO_INPUT) +GPIO(EC_ENTERING_RW, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EC_EN_EDP_BL, PIN(D, 3), GPIO_OUT_HIGH) +GPIO(EC_GSC_PACKET_MODE, PIN(7, 5), GPIO_OUT_LOW) +GPIO(EC_I2C_BAT_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BAT_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_PPC_BC_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_C2_TCPC_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SCL, PIN(E, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_MIX_SDA, PIN(E, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SCL, PIN(F, 3), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_TCPC_SDA, PIN(F, 2), GPIO_INPUT) +GPIO(EC_KB_BL_EN_L, PIN(8, 6), GPIO_OUT_HIGH) +GPIO(EC_PCHHOT_ODL, PIN(7, 4), GPIO_INPUT) +GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) +GPIO(EC_PCH_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_PCH_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) +GPIO(EC_PCH_WAKE_R_ODL, PIN(C, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) +GPIO(EN_PP5000_FAN, PIN(6, 1), GPIO_OUT_HIGH) +GPIO(EN_PP5000_USBA_R, PIN(D, 7), GPIO_OUT_LOW) +GPIO(EN_S5_RAILS, PIN(B, 6), GPIO_OUT_LOW) +GPIO(IMVP9_VRRDY_OD, PIN(4, 3), GPIO_INPUT) +GPIO(PCH_PWROK, PIN(7, 2), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) +GPIO(USB_C0_C2_TCPC_RST_ODL, PIN(A, 7), GPIO_ODR_LOW) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) +GPIO(USB_C1_RST_ODL, PIN(9, 6), GPIO_ODR_LOW) +GPIO(USB_C1_RT_INT_ODL, PIN(A, 0), GPIO_INPUT) +GPIO(USB_C1_RT_RST_R_ODL, PIN(0, 2), GPIO_ODR_LOW) +GPIO(VCCST_PWRGD_OD, PIN(A, 4), GPIO_ODR_LOW) +GPIO(LED_1_L, PIN(C, 4), GPIO_OUT_HIGH) +GPIO(LED_2_L, PIN(C, 3), GPIO_OUT_HIGH) + +/* UART alternate functions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* GPIO64/CR_SIN1, GPO65/CR_SOUT1/FLPRG1_L */ + +/* I2C alternate functions */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* GPIO33/I2C5_SCL0/CTS_L, GPIO36/RTS_L/I2C5_SDA0 */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* GPIO87/I2C1_SDA0 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* GPIO92/I2C2_SCL0, GPIO91/I2C2_SDA0, GPIO90/I2C1_SCL0 */ +ALTERNATE(PIN_MASK(B, 0x0c), 0, MODULE_I2C, 0) /* GPIOB3/I2C7_SCL0/DCD_L, GPIOB2/I2C7_SDA0/DSR_L */ +ALTERNATE(PIN_MASK(B, 0x30), 0, MODULE_I2C, GPIO_SEL_1P8V) /* GPIOB5/I2C0_SCL0, GPIOB4/I2C0_SDA0 */ +ALTERNATE(PIN_MASK(E, 0x18), 0, MODULE_I2C, 0) /* GPIOE4/I2C6_SCL1/I3C_SCL, GPIOE3/I2C6_SDA1/I3C_SDA */ +ALTERNATE(PIN_MASK(F, 0x0c), 0, MODULE_I2C, 0) /* GPIOF3/I2C4_SCL1, GPIOF2/I2C4_SDA1 */ + +/* PWM alternate functions */ +ALTERNATE(PIN_MASK(4, 0x01), 0, MODULE_PWM, 0) /* GPIO40/TA1 */ +ALTERNATE(PIN_MASK(8, 0x01), 0, MODULE_PWM, 0) /* GPIO80/PWM3 */ +ALTERNATE(PIN_MASK(B, 0x80), 0, MODULE_PWM, 0) /* GPIOB7/PWM5 */ + +/* ADC alternate functions */ +ALTERNATE(PIN_MASK(3, 0x10), 0, MODULE_ADC, 0) /* GPIO34/PS2_DAT2/ADC6 */ +ALTERNATE(PIN_MASK(4, 0x34), 0, MODULE_ADC, 0) /* GPIO42/ADC3/RI_L, GPIO45/ADC0, GPIO44/ADC1 */ + +/* KB alternate functions */ +ALTERNATE(PIN_MASK(0, 0xf0), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO10&P80_CLK/GPIO07, KSO11&P80_DAT/GPIO06, KSO12/GPIO05, KSO13/GPIO04 */ +ALTERNATE(PIN_MASK(1, 0x7f), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO06/GPO13/GP_SEL_L, KSO07/GPO12/JEN_L, KSO03/GPIO16/JTAG_TDO0_SWO, KSO04/GPIO15/XNOR, KSO05/GPIO14, KSO08/GPIO11/CR_SOUT1, KSO09/GPIO10/CR_SIN1 */ +ALTERNATE(PIN_MASK(2, 0xfc), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI2/GPIO27/TRACEDATA1, KSI3/GPIO26/TRACEDATA0, KSI4/GPIO25/TRACECLK/GP_SCLK, KSI5/GPIO24/GP_MISO, KSI6/GPIO23/S_SBUB, KSI7/GPIO22/S_SBUA */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO00/GPIO21/JTAG_TCK_SWCLK, KSO01/GPIO20/JTAG_TMS_SWIO */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KB, GPIO_INPUT | GPIO_PULL_UP) /* KSI0/GPIO31/TRACEDATA3/GP_MOSI, KSI1/GPIO30/TRACEDATA2/GP_CS_L */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KB, GPIO_ODR_HIGH) /* KSO14/GPIO82 */ + +/* PMU alternate functions */ +ALTERNATE(PIN_MASK(0, 0x01), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN2_L&GPI00/GPIO00 */ +ALTERNATE(PIN_MASK(0, 0x02), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_LOW) /* GPIO01/PSL_IN3_L&GPI01 */ +ALTERNATE(PIN_MASK(D, 0x04), 0, MODULE_PMU, GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH) /* PSL_IN1_L&GPID2/GPIOD2 */ + +/* Unused Pins */ +UNUSED(PIN(D, 6)) /* GPOD6/CR_SOUT3/SHDF_ESPI_L */ +UNUSED(PIN(3, 2)) /* GPO32/TRIS_L */ +UNUSED(PIN(3, 4)) /* GPIO34 */ +UNUSED(PIN(3, 5)) /* GPO35/CR_SOUT4/TEST_L */ +UNUSED(PIN(6, 6)) /* GPIO66 */ +UNUSED(PIN(5, 7)) /* GPIO57/SER_IRQ/ESPI_ALERT_L */ +UNUSED(PIN(8, 3)) /* GPIO83 */ +UNUSED(PIN(7, 0)) /* GPIO70 */ +UNUSED(PIN(4, 1)) /* GPIO41 */ +UNUSED(PIN(8, 1)) /* GPIO81 */ +UNUSED(PIN(5, 6)) /* GPIO56 */ +UNUSED(PIN(B, 1)) /* GPIOB1 */ +UNUSED(PIN(D, 0)) /* GPIOD0/I2C3_SDA0 */ +UNUSED(PIN(D, 1)) /* GPIOD1/I2C3_SCL0 */ +UNUSED(PIN(9, 5)) /* GPIO95 */ + +/* Pre-configured PSL balls: J8 K6 */ + +/* + * The NPCX keyboard driver does not use named GPIOs to access + * keyboard scan pins, so we do not list them in *gpio.inc. However, when + * KEYBOARD_COL2_INVERTED is defined, this name is required. + */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) + +GPIO(USB_C0_OC_ODL, PIN(D, 4), GPIO_ODR_HIGH) +GPIO(USB_C0_FRS_EN, PIN(6, 0), GPIO_OUT_LOW) +GPIO(USB_C0_RT_RST_ODL, PIN(C, 2), GPIO_ODR_LOW) + +GPIO(USB_C1_OC_ODL, PIN(E, 1), GPIO_ODR_HIGH) diff --git a/board/volmar/i2c.c b/board/volmar/i2c.c new file mode 100644 index 0000000000..29dd2904c1 --- /dev/null +++ b/board/volmar/i2c.c @@ -0,0 +1,73 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "i2c.h" + +#define BOARD_ID_FAST_PLUS_CAPABLE 2 + +/* I2C port map configuration */ +const struct i2c_port_t i2c_ports[] = { + { + /* I2C0 */ + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA, + }, + { + /* I2C1 */ + .name = "tcpc0,2", + .port = I2C_PORT_USB_C0_C2_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_TCPC_SDA, + }, + { + /* I2C2 */ + .name = "ppc0,2", + .port = I2C_PORT_USB_C0_C2_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SCL, + .sda = GPIO_EC_I2C_USB_C0_C2_PPC_BC_SDA, + }, + { + /* I2C4 C1 TCPC */ + .name = "tcpc1", + .port = I2C_PORT_USB_C1_TCPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_TCPC_SCL, + .sda = GPIO_EC_I2C_USB_C1_TCPC_SDA, + .flags = I2C_PORT_FLAG_DYNAMIC_SPEED, + }, + { + /* I2C5 */ + .name = "battery", + .port = I2C_PORT_BATTERY, + .kbps = 100, + .scl = GPIO_EC_I2C_BAT_SCL, + .sda = GPIO_EC_I2C_BAT_SDA, + }, + { + /* I2C6 */ + .name = "ppc1", + .port = I2C_PORT_USB_C1_PPC, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_MIX_SCL, + .sda = GPIO_EC_I2C_USB_C1_MIX_SDA, + }, + { + /* I2C7 */ + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_MISC_SCL_R, + .sda = GPIO_EC_I2C_MISC_SDA_R, + }, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/volmar/keyboard.c b/board/volmar/keyboard.c new file mode 100644 index 0000000000..16857b53c9 --- /dev/null +++ b/board/volmar/keyboard.c @@ -0,0 +1,47 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "ec_commands.h" +#include "keyboard_scan.h" +#include "timer.h" + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* Increase from 50 us, because KSO_02 passes through the H1. */ + .output_settle_us = 80, + /* Other values should be the same as the default configuration. */ + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ + }, +}; + +static const struct ec_response_keybd_config volmar_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_REFRESH, /* T2 */ + TK_FULLSCREEN, /* T3 */ + TK_OVERVIEW, /* T4 */ + TK_SNAPSHOT, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &volmar_kb; +} diff --git a/board/volmar/led.c b/board/volmar/led.c new file mode 100644 index 0000000000..11b1cced9e --- /dev/null +++ b/board/volmar/led.c @@ -0,0 +1,87 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * Power and battery LED control for volmar + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +#define GPIO_LED_BLUE_L GPIO_LED_1_L +#define GPIO_LED_AMBER_L GPIO_LED_2_L + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_AMBER_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_BLUE_L, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_LED_BLUE_L, LED_ON_LVL); + gpio_set_level(GPIO_LED_AMBER_L, LED_OFF_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_BLUE_L, LED_OFF_LVL); + gpio_set_level(GPIO_LED_AMBER_L, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else + led_set_color_battery(LED_OFF); + } + + return EC_SUCCESS; +} diff --git a/board/volmar/pwm.c b/board/volmar/pwm.c new file mode 100644 index 0000000000..33622559a1 --- /dev/null +++ b/board/volmar/pwm.c @@ -0,0 +1,40 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "pwm.h" +#include "pwm_chip.h" + +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = 0, + /* + * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent + * flicker. Higher frequencies consume similar average power to + * lower PWM frequencies, but higher frequencies record a much + * lower maximum power. + */ + .freq = 2400, + }, + [PWM_CH_FAN] = { + .channel = 5, + .flags = PWM_CONFIG_OPEN_DRAIN, + .freq = 25000 + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +static void board_pwm_init(void) +{ + /* + * Turn on the fan at 50%. + */ + pwm_enable(PWM_CH_KBLIGHT, 1); + pwm_set_duty(PWM_CH_KBLIGHT, 50); +} +DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/volmar/sensors.c b/board/volmar/sensors.c new file mode 100644 index 0000000000..1a0a5f8398 --- /dev/null +++ b/board/volmar/sensors.c @@ -0,0 +1,152 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "common.h" +#include "hooks.h" +#include "motion_sense.h" +#include "temp_sensor.h" +#include "temp_sensor/thermistor.h" +#include "thermal.h" + +/* ADC configuration */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1_DDR_SOC] = { + .name = "TEMP_DDR_SOC", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2_FAN] = { + .name = "TEMP_FAN", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_3_CHARGER] = { + .name = "TEMP_CHARGER", + .input_ch = NPCX_ADC_CH6, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Temperature sensor configuration */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1_DDR_SOC] = { + .name = "DDR and SOC", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_1_DDR_SOC, + }, + [TEMP_SENSOR_2_FAN] = { + .name = "FAN", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_2_FAN, + }, + [TEMP_SENSOR_3_CHARGER] = { + .name = "CHARGER", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_30k9_47k_4050b, + .idx = ADC_TEMP_SENSOR_3_CHARGER, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Alder Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at + * 130 C. However, sensor is located next to DDR, so we need to use the lower + * DDR temperature limit (85 C) + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + }, \ + .temp_fan_off = C_TO_K(30), \ + .temp_fan_max = C_TO_K(84), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; + +/* + * TODO(b/180681346): update for Alder Lake/brya + * + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 100C, max absolute temperature 125C + * PP3300 regulator: operating range -40 C to 145 C + * + * Inductors: limit of 125c + * PCB: limit is 85c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_FAN \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_fan = THERMAL_FAN; + +/* + * Inductor limits - used for both charger and PP3300 regulator + * + * Need to use the lower of the charger IC, PP3300 regulator, and the inductors + * + * Charger max recommended temperature 125C, max absolute temperature 150C + * PP3300 regulator: operating range -40 C to 125 C + * + * Inductors: limit of 125c + * PCB: limit is 85c + */ +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CHARGER \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = 0, \ + }, \ + .temp_fan_off = 0, \ + .temp_fan_max = 0, \ + } +__maybe_unused static const struct ec_thermal_config thermal_charger = + THERMAL_CHARGER; + +/* this should really be "const" */ +struct ec_thermal_config thermal_params[] = { + [TEMP_SENSOR_1_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_2_FAN] = THERMAL_FAN, + [TEMP_SENSOR_3_CHARGER] = THERMAL_CHARGER, +}; +BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); diff --git a/board/volmar/usbc_config.c b/board/volmar/usbc_config.c new file mode 100644 index 0000000000..8357dfa690 --- /dev/null +++ b/board/volmar/usbc_config.c @@ -0,0 +1,312 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi.h" +#include "charge_ramp.h" +#include "charger.h" +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/rt1715.h" +#include "driver/tcpm/tcpci.h" +#include "ec_commands.h" +#include "fw_config.h" +#include "gpio.h" +#include "gpio_signal.h" +#include "hooks.h" +#include "ioexpander.h" +#include "system.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "usb_charge.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0_C2_TCPC, + .addr_flags = RT1715_I2C_ADDR_FLAGS, + }, + .drv = &rt1715_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1_TCPC, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | + TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA_R, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_port_enable) == USB_PORT_COUNT); + +/******************************************************************************/ + +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, + [USBC_PORT_C1] = { + /* Compatible with Silicon Mitus SM536A0 */ + .i2c_port = I2C_PORT_USB_C1_PPC, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); + +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* + * USB3 DB mux configuration - the top level mux still needs to be set + * to the virtual_usb_mux_driver so the AP gets notified of mux changes + * and updates the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, +}; + +const struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + /* PS8815 DB */ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0_C2_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1_BC12, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); + +#ifdef CONFIG_CHARGE_RAMP_SW + +/* + * TODO(b/181508008): tune this threshold + */ + +#define BC12_MIN_VOLTAGE 4400 + +/** + * Return true if VBUS is too low + */ +int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state) +{ + int voltage; + + if (charger_get_vbus_voltage(port, &voltage)) + voltage = 0; + + if (voltage == 0) { + CPRINTS("%s: must be disconnected", __func__); + return 1; + } + + if (voltage < BC12_MIN_VOLTAGE) { + CPRINTS("%s: port %d: vbus %d lower than %d", __func__, port, + voltage, BC12_MIN_VOLTAGE); + return 1; + } + + return 0; +} + +#endif /* CONFIG_CHARGE_RAMP_SW */ + +void config_usb_db_type(void) +{ + enum ec_cfg_usb_db_type db_type = ec_cfg_usb_db_type(); + + /* + * TODO(b/180434685): implement multiple DB types + */ + + CPRINTS("Configured USB DB type number is %d", db_type); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b/179648104): figure out correct timing + */ + + gpio_set_level(GPIO_USB_C0_RT_RST_ODL, 0); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 0); + + /* + * delay for power-on to reset-off and min. assertion time + */ + + msleep(20); + + gpio_set_level(GPIO_USB_C0_RT_RST_ODL, 1); + gpio_set_level(GPIO_USB_C1_RT_RST_R_ODL, 1); + + /* wait for chips to come up */ + + msleep(50); +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_C2_TCPC_INT_ODL); + + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + + if (ec_cfg_usb_db_type() != DB_USB_ABSENT) { + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); + } +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (gpio_get_level(GPIO_USB_C0_C2_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_0 | PD_STATUS_TCPC_ALERT_2; + + if ((ec_cfg_usb_db_type() != DB_USB_ABSENT) && + gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL) == 0) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else if ((port == USBC_PORT_C1) && + (ec_cfg_usb_db_type() != DB_USB_ABSENT)) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + return 0; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_C2_TCPC_INT_ODL: + schedule_deferred_pd_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_TCPC_INT_ODL: + if (ec_cfg_usb_db_type() == DB_USB_ABSENT) + break; + schedule_deferred_pd_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +void bc12_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_BC12_INT_ODL: + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); + break; + case GPIO_USB_C1_BC12_INT_ODL: + if (ec_cfg_usb_db_type() == DB_USB_ABSENT) + break; + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); + break; + default: + break; + } +} + +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + switch (ec_cfg_usb_db_type()) { + case DB_USB_ABSENT: + case DB_USB_ABSENT2: + break; + case DB_USB3_PS8815: + syv682x_interrupt(USBC_PORT_C1); + break; + } + break; + default: + break; + } +} + +__override bool board_is_dts_port(int port) +{ + return port == USBC_PORT_C0; +} diff --git a/board/volmar/usbc_config.h b/board/volmar/usbc_config.h new file mode 100644 index 0000000000..0722d00d6b --- /dev/null +++ b/board/volmar/usbc_config.h @@ -0,0 +1,17 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volmar board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +void config_usb_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/volmar/vif_override.xml b/board/volmar/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/volmar/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/volteer/battery.c b/board/volteer/battery.c index 1c24e1ec24..31cb7faaf9 100644 --- a/board/volteer/battery.c +++ b/board/volteer/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/volteer/board.c b/board/volteer/board.c index b8314d8a01..f8363ea4d7 100644 --- a/board/volteer/board.c +++ b/board/volteer/board.c @@ -1,32 +1,24 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "common.h" #include "accelgyro.h" +#include "button.h" #include "cbi_ec_fw_config.h" +#include "common.h" #include "driver/accel_bma2x2.h" #include "driver/accelgyro_bmi260.h" #include "driver/als_tcs3400.h" -#include "driver/bc12/pi3usb9201.h" -#include "driver/ppc/sn5s330.h" -#include "driver/ppc/syv682x.h" -#include "driver/retimer/bb_retimer.h" +#include "driver/retimer/bb_retimer_public.h" #include "driver/sync.h" #include "driver/tcpm/ps8xxx.h" -#include "driver/tcpm/rt1715.h" -#include "driver/tcpm/tcpci.h" -#include "driver/tcpm/tusb422.h" #include "extpower.h" #include "fan.h" #include "fan_chip.h" #include "gpio.h" #include "hooks.h" -#include "keyboard_raw.h" #include "keyboard_scan.h" #include "lid_switch.h" #include "power.h" @@ -35,23 +27,25 @@ #include "pwm_chip.h" #include "switch.h" #include "system.h" -#include "task.h" #include "tablet_mode.h" +#include "task.h" #include "throttle_ap.h" +#include "timer.h" #include "uart.h" -#include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tbt.h" #include "usb_pd_tcpm.h" -#include "usbc_ppc.h" #include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +/* Disable debug messages to save flash space */ +#define CPRINTS(format, args...) +/******************************************************************************/ /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Increase from 50 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* Other values should be the same as the default configuration. */ @@ -66,69 +60,12 @@ struct keyboard_scan_config keyscan_config = { }, }; -/******************************************************************************/ -/* - * FW_CONFIG defaults for Volteer if the CBI data is not initialized. - */ -union volteer_cbi_fw_config fw_config_defaults = { - .usb_db = DB_USB4_GEN2, -}; - -static void board_init(void) -{ - /* Illuminate motherboard and daughter board LEDs equally to start. */ - pwm_enable(PWM_CH_LED4_SIDESEL, 1); - pwm_set_duty(PWM_CH_LED4_SIDESEL, 50); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - if (port == USBC_PORT_C1) { - if (usb_db == DB_USB4_GEN2) { - /* - * Older boards violate 205mm trace length prior - * to connection to the re-timer and only support up - * to GEN2 speeds. - */ - return TBT_SS_U32_GEN1_GEN2; - } else if (usb_db == DB_USB4_GEN3) { - return TBT_SS_TBT_GEN3; - } - } - - /* - * Thunderbolt-compatible mode not supported - * - * TODO (b/147726366): All the USB-C ports need to support same speed. - * Need to fix once USB-C feature set is known for Volteer. - */ - return TBT_SS_RES_0; -} - -__override bool board_is_tbt_usb4_port(int port) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - /* - * Volteer reference design only supports TBT & USB4 on port 1 - * if the USB4 DB is present. - * - * TODO (b/147732807): All the USB-C ports need to support same - * features. Need to fix once USB-C feature set is known for Volteer. - */ - return ((port == USBC_PORT_C1) - && ((usb_db == DB_USB4_GEN2) || (usb_db == DB_USB4_GEN3))); -} - /******************************************************************************/ /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -161,17 +98,22 @@ const struct fan_t fans[FAN_CH_COUNT] = { * 130 C. However, sensor is located next to DDR, so we need to use the lower * DDR temperature limit (85 C) */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(35), \ + .temp_fan_max = C_TO_K(50), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; /* * Inductor limits - used for both charger and PP3300 regulator @@ -184,24 +126,29 @@ const static struct ec_thermal_config thermal_cpu = { * Inductors: limit of 125c * PCB: limit is 80c */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_INDUCTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + }, \ + .temp_fan_off = C_TO_K(40), \ + .temp_fan_max = C_TO_K(55), \ + } +__maybe_unused static const struct ec_thermal_config thermal_inductor = + THERMAL_INDUCTOR; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, + [TEMP_SENSOR_1_CHARGER] = THERMAL_INDUCTOR, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_INDUCTOR, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -310,341 +257,3 @@ const struct pwm_t pwm_channels[] = { }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -/******************************************************************************/ -/* Volteer specific USB daughter-board configuration */ - -/* USBC TCPC configuration for USB3 daughter board */ -static const struct tcpc_config_t tcpc_config_p1_usb3 = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = PS8751_I2C_ADDR1_FLAGS, - }, - .flags = TCPC_FLAGS_TCPCI_REV2_0 | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, - .drv = &ps8xxx_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), -}; - -/* - * USB3 DB mux configuration - the top level mux still needs to be set to the - * virtual_usb_mux_driver so the AP gets notified of mux changes and updates - * the TCSS configuration on state changes. - */ -static const struct usb_mux usbc1_usb3_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - .next_mux = NULL, -}; - -static const struct usb_mux mux_config_p1_usb3_active = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb3_db_retimer, -}; - -static const struct usb_mux mux_config_p1_usb3_passive = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, -}; - -/******************************************************************************/ -/* USB-A charging control */ - -const int usb_port_enable[USB_PORT_COUNT] = { - GPIO_EN_PP5000_USBA, -}; - -static enum gpio_signal ps8xxx_rst_odl = GPIO_USB_C1_RT_RST_ODL; - -static void ps8815_reset(void) -{ - int val; - - gpio_set_level(ps8xxx_rst_odl, 0); - msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, - PS8815_PWR_H_RST_H_DELAY_MS)); - gpio_set_level(ps8xxx_rst_odl, 1); - msleep(PS8815_FW_INIT_DELAY_MS); - - /* - * b/144397088 - * ps8815 firmware 0x01 needs special configuration - */ - - CPRINTS("%s: patching ps8815 registers", __func__); - - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) - CPRINTS("ps8815: reg 0x0f was %02x", val); - - if (i2c_write8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, 0x31) == EC_SUCCESS) - CPRINTS("ps8815: reg 0x0f set to 0x31"); - - if (i2c_read8(I2C_PORT_USB_C1, - PS8751_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == EC_SUCCESS) - CPRINTS("ps8815: reg 0x0f now %02x", val); -} - -void board_reset_pd_mcu(void) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - /* No reset available for TCPC on port 0 */ - /* Daughterboard specific reset for port 1 */ - if (usb_db == DB_USB3_ACTIVE) { - ps8815_reset(); - usb_mux_hpd_update(USBC_PORT_C1, 0, 0); - } -} - -/* - * Set up support for the USB3 daughterboard: - * Parade PS8815 TCPC (integrated retimer) - * Diodes PI3USB9201 BC 1.2 chip (same as USB4 board) - * Silergy SYV682A PPC (same as USB4 board) - * Virtual mux with stacked retimer - */ -static void config_db_usb3_active(void) -{ - tcpc_config[USBC_PORT_C1] = tcpc_config_p1_usb3; - usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3_active; -} - -/* - * Set up support for the passive USB3 daughterboard: - * TUSB422 TCPC (already the default) - * PI3USB9201 BC 1.2 chip (already the default) - * Silergy SYV682A PPC (already the default) - * Virtual mux without stacked retimer - */ - -static void config_db_usb3_passive(void) -{ - usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3_passive; -} - -static void config_port_discrete_tcpc(int port) -{ - /* - * Support 2 Pin-to-Pin compatible parts: TUSB422 and RT1715, for - * simplicity allow either and decide at runtime which we are using. - * Default to TUSB422, and switch to RT1715 if it is on the I2C bus and - * the VID matches. - */ - - int regval; - - if (i2c_read16(port ? I2C_PORT_USB_C1 : I2C_PORT_USB_C0, - RT1715_I2C_ADDR_FLAGS, TCPC_REG_VENDOR_ID, - ®val) == EC_SUCCESS) { - if (regval == RT1715_VENDOR_ID) { - CPRINTS("C%d: RT1715 detected", port); - tcpc_config[port].i2c_info.addr_flags = - RT1715_I2C_ADDR_FLAGS; - tcpc_config[port].drv = &rt1715_tcpm_drv; - return; - } - } - CPRINTS("C%d: Default to TUSB422", port); -} - -static const char *db_type_prefix = "USB DB type: "; -__override void board_cbi_init(void) -{ - enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); - - /* Reconfigure Volteer GPIOs based on the board ID */ - if (get_board_id() == 0) { - CPRINTS("Configuring GPIOs for board ID 0"); - CPRINTS("VOLUME_UP button disabled"); - - /* Reassign USB_C1_RT_RST_ODL */ - bb_controls[USBC_PORT_C1].retimer_rst_gpio = - GPIO_USB_C1_RT_RST_ODL_BOARDID_0; - ps8xxx_rst_odl = GPIO_USB_C1_RT_RST_ODL_BOARDID_0; - } - config_port_discrete_tcpc(0); - switch (usb_db) { - case DB_USB_ABSENT: - CPRINTS("%sNone", db_type_prefix); - break; - case DB_USB4_GEN2: - config_port_discrete_tcpc(1); - CPRINTS("%sUSB4 Gen1/2", db_type_prefix); - break; - case DB_USB4_GEN3: - config_port_discrete_tcpc(1); - CPRINTS("%sUSB4 Gen3", db_type_prefix); - break; - case DB_USB3_ACTIVE: - config_db_usb3_active(); - CPRINTS("%sUSB3 Active", db_type_prefix); - break; - case DB_USB3_PASSIVE: - config_db_usb3_passive(); - config_port_discrete_tcpc(1); - CPRINTS("%sUSB3 Passive", db_type_prefix); - break; - default: - CPRINTS("%sID %d not supported", db_type_prefix, usb_db); - } - - if ((!IS_ENABLED(TEST_BUILD) && !ec_cfg_has_numeric_pad()) || - get_board_id() <= 2) - keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); -} - -/******************************************************************************/ -/* USBC PPC configuration */ -struct ppc_config_t ppc_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = SN5S330_ADDR0_FLAGS, - .drv = &sn5s330_drv, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = SYV682X_ADDR0_FLAGS, - .drv = &syv682x_drv, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); -unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); - -/******************************************************************************/ -/* PPC support routines */ -void ppc_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_USB_C0_PPC_INT_ODL: - sn5s330_interrupt(USBC_PORT_C0); - break; - case GPIO_USB_C1_PPC_INT_ODL: - syv682x_interrupt(USBC_PORT_C1); - default: - break; - } -} - -/******************************************************************************/ -/* BC1.2 charger detect configuration */ -const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { - [USBC_PORT_C0] = { - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, - [USBC_PORT_C1] = { - .i2c_port = I2C_PORT_USB_C1, - .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC TCPC configuration */ -struct tcpc_config_t tcpc_config[] = { - [USBC_PORT_C0] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C0, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), - }, - [USBC_PORT_C1] = { - .bus_type = EC_BUS_TYPE_I2C, - .i2c_info = { - .port = I2C_PORT_USB_C1, - .addr_flags = TUSB422_I2C_ADDR_FLAGS, - }, - .drv = &tusb422_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), - }, -}; -BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); -BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); - -/******************************************************************************/ -/* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, -}; -struct usb_mux usb_muxes[] = { - [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - }, - [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); - -struct bb_usb_control bb_controls[] = { - [USBC_PORT_C0] = { - /* USB-C port 0 doesn't have a retimer */ - }, - [USBC_PORT_C1] = { - .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, - .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); - -static void board_tcpc_init(void) -{ - /* Don't reset TCPCs after initial reset */ - if (!system_jumped_late()) - board_reset_pd_mcu(); - - /* Enable PPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); - - /* Enable TCPC interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); - - /* Enable BC1.2 interrupts. */ - gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); - gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); - -/******************************************************************************/ -/* TCPC support routines */ -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - /* - * Check which port has the ALERT line set - */ - if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} - -int ppc_get_alert_status(int port) -{ - if (port == USBC_PORT_C0) - return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; - else - return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; -} diff --git a/board/volteer/board.h b/board/volteer/board.h index 4aa02f6d6b..557327a765 100644 --- a/board/volteer/board.h +++ b/board/volteer/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,17 +11,10 @@ /* Baseboard features */ #include "baseboard.h" -#ifdef BOARD_VOLTEER_TCPMV1 -/* Disable TCPMv2 configuration options */ -#undef CONFIG_USB_PD_TCPMV2 - -/* Enable the required TCPMv1 options */ -#define CONFIG_USB_PD_TCPMV1 - +#ifdef BOARD_VOLTEER_NPCX797FC /* - * Because the TPCMv1 stack has considerably smaller flash footprint, disable - * the CONFIG_CHIP_INIT_ROM_REGION for testing of the init_rom API and the - * BMI260 driver. + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. */ #undef CONFIG_CHIP_INIT_ROM_REGION #endif @@ -29,6 +22,9 @@ /* Optional features */ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ +/* Remove PRL state names to free flash space */ +#define CONFIG_USB_PD_DEBUG_LEVEL 0 + #define CONFIG_VBOOT_EFS2 #define CONFIG_POWER_BUTTON @@ -38,6 +34,7 @@ /* Chipset features */ #define CONFIG_POWER_PP5000_CONTROL +#define CONFIG_CPU_PROCHOT_GATE_ON_C10 /* LED defines */ #define CONFIG_LED_PWM @@ -57,62 +54,52 @@ /* TCS3400 ALS */ #define CONFIG_ALS -#define ALS_COUNT 1 +#define ALS_COUNT 1 #define CONFIG_ALS_TCS3400 #define CONFIG_ALS_TCS3400_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS) /* Sensors without hardware FIFO are in forced mode */ -#define CONFIG_ACCEL_FORCE_MODE_MASK \ - (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) +#define CONFIG_ACCEL_FORCE_MODE_MASK (BIT(LID_ACCEL) | BIT(CLEAR_ALS)) #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL /* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 - -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 /* TODO: b/144165680 - measure and check these values on Volteer */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ - +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ /* * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C * cables only support up to 60W. */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 /* Enabling Thunderbolt-compatible mode */ #define CONFIG_USB_PD_TBT_COMPAT_MODE /* Enabling USB4 mode */ #define CONFIG_USB_PD_USB4 -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x40 /* USB Type A Features */ -#define USB_PORT_COUNT 1 +#define USB_PORT_COUNT 1 #define CONFIG_USB_PORT_POWER_DUMB /* USBC PPC*/ -#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ +#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C1 */ +#define CONFIG_USB_PD_FRS_PPC + +/* Disable PPC logging to reduce EC image size */ +#undef CONFIG_USBC_PPC_LOGGING /* BC 1.2 */ @@ -121,8 +108,8 @@ /* Fan features */ /* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 /* * Macros for GPIO signals used in common code that don't match the @@ -130,51 +117,97 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL /* I2C Bus Configuration */ #define CONFIG_I2C -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM - -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER - +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 + +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM + +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER + +#define CONFIG_DEBUG_ASSERT_BRIEF + +/* Disable console commands to help save space */ +#undef CONFIG_CMD_ADC +#undef CONFIG_CMD_APTHROTTLE +#undef CONFIG_CMD_BATTFAKE +#undef CONFIG_CMD_BUTTON +#undef CONFIG_CMD_CBI +#undef CONFIG_CMD_CHARGER +#undef CONFIG_CMD_CHARGE_SUPPLIER_INFO +#undef CONFIG_CMD_CRASH +#undef CONFIG_CMD_DEVICE_EVENT +#undef CONFIG_CMD_FLASH_WP +#undef CONFIG_CMD_HASH +#undef CONFIG_CMD_I2C_XFER +#undef CONFIG_CMD_IDLE_STATS +#undef CONFIG_CMD_INA +#undef CONFIG_CMD_MFALLOW +#undef CONFIG_CMD_MMAPINFO +#undef CONFIG_CMD_POWERINDEBUG +#undef CONFIG_CMD_PWR_AVG +#undef CONFIG_CMD_REGULATOR +#undef CONFIG_CMD_USB_PD_CABLE +#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CONSOLE_HISTORY + +/* Free flash space */ +#undef CONFIG_ACCEL_SPOOF_MODE +#undef CONFIG_CMD_SYSLOCK +#undef CONFIG_CMD_TIMERINFO +#undef CONFIG_CMD_MD +#undef CONFIG_CMD_I2C_SCAN +#undef CONFIG_CMD_AP_RESET_LOG +#undef CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_CMD_SLEEPMASK_SET +#undef CONFIG_CONSOLE_VERBOSE +#undef CONFIG_CMD_TYPEC +#undef CONFIG_CMD_FASTCHARGE +#undef CONFIG_CMD_KEYBOARD +#undef CONFIG_CMD_MEM +#undef CONFIG_CMD_PD +#undef CONFIG_CMD_PECI +#undef CONFIG_CMD_RETIMER +#undef CONFIG_CMD_RW + +/* Disable volume button in ectool */ +#undef CONFIG_HOSTCMD_BUTTON #ifndef __ASSEMBLER__ #include "gpio_signal.h" #include "registers.h" +#include "usbc_config.h" enum battery_type { BATTERY_LGC011, @@ -200,12 +233,6 @@ enum sensor_id { SENSOR_COUNT, }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; - void board_reset_pd_mcu(void); #endif /* !__ASSEMBLER__ */ diff --git a/board/volteer/build.mk b/board/volteer/build.mk index bcf93c58cb..fc7828e29b 100644 --- a/board/volteer/build.mk +++ b/board/volteer/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -8,10 +8,18 @@ CHIP:=npcx CHIP_FAMILY:=npcx7 +# A limited Volteer boards are reworked with NPCX797FC variant. Set the +# modify the variant type to match. +ifeq ($(BOARD),volteer_npcx797fc) +CHIP_VARIANT:=npcx7m7fc +else CHIP_VARIANT:=npcx7m6fc +endif BASEBOARD:=volteer board-y=board.o board-y+=battery.o +board-y+=cbi.o board-y+=led.o board-y+=sensors.o +board-y+=usbc_config.o diff --git a/board/volteer/cbi.c b/board/volteer/cbi.c new file mode 100644 index 0000000000..c2bc656bb5 --- /dev/null +++ b/board/volteer/cbi.c @@ -0,0 +1,27 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Features common to ECOS and Zephyr */ +#include "cbi.h" +#include "cbi_ec_fw_config.h" +#include "common.h" +#include "keyboard_raw.h" +#include "usbc_config.h" + +/******************************************************************************/ +/* + * FW_CONFIG defaults for Volteer if the CBI data is not initialized. + */ +union volteer_cbi_fw_config fw_config_defaults = { + .usb_db = DB_USB4_GEN2, +}; + +__override void board_cbi_init(void) +{ + config_usb3_db_type(); + if ((!IS_ENABLED(TEST_BUILD) && !ec_cfg_has_numeric_pad()) || + get_board_id() <= 2) + keyboard_raw_set_cols(KEYBOARD_COLS_NO_KEYPAD); +} diff --git a/board/volteer/ec.tasklist b/board/volteer/ec.tasklist index ec9e64e850..0492fcc3c0 100644 --- a/board/volteer/ec.tasklist +++ b/board/volteer/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,6 +16,7 @@ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/volteer/gpio.inc b/board/volteer/gpio.inc index 183f20c890..04982595fe 100644 --- a/board/volteer/gpio.inc +++ b/board/volteer/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -77,6 +77,7 @@ GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_RISING, throttle_ap_c10_input_interrupt) GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) @@ -84,19 +85,12 @@ GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) /* USB and USBC Signals */ GPIO(EN_PP5000_USBA, PIN(C, 6), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ GPIO(USB_A_LOW_PWR_OD, PIN(6, 6), GPIO_ODR_LOW) /* Don't limit USB-A charging by default - all ports */ - -/* - * USB_C1 moved from GPIO32 to GPIO83 on boards with board ID >=1. - * GPIO83/EN_PP1800_A is DNS on board ID 0 and GPIO32 is N/C on board ID >=1 - * so it's safe to define GPIOs compatible with both designs. - * TODO (b/149858568): remove board ID=0 support. - */ -GPIO(USB_C1_RT_RST_ODL_BOARDID_0, PIN(3, 2), GPIO_ODR_LOW) /* USB_C1 Reset on boards without board ID */ -GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) /* USB_C1 Reset on boards board ID >=1 */ -GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) -GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) +GPIO(USB_C1_RT_RST_ODL, PIN(8, 3), GPIO_ODR_LOW) +GPIO(USB_C0_OC_ODL, PIN(B, 1), GPIO_ODR_HIGH) +GPIO(USB_C1_OC_ODL, PIN(5, 0), GPIO_ODR_HIGH) /* There is currently no need to service this interrupt. */ -GPIO(USB_C1_RT_INT_ODL, PIN(F, 3), GPIO_INPUT) +GPIO(USB_C1_RT_INT_ODL, PIN(F, 3), GPIO_INPUT) +GPIO(USB_C1_FRS_EN, PIN(9, 4), GPIO_OUT_LOW) /* Don't have a load switch for retimer */ UNIMPLEMENTED(USB_C1_LS_EN) @@ -114,10 +108,16 @@ GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) /* Case Closed Debug Mode */ GPIO(EC_SLP_S0IX, PIN(7, 2), GPIO_INPUT | GPIO_PULL_UP) /* Unused signals */ +GPIO(CHARGER_INT_L, PIN(7, 3), GPIO_INPUT) /* Interrupt not used from ISL9241, on board pull-up */ +GPIO(EC_GP_SEL0_ODL, PIN(B, 6), GPIO_OUT_LOW) /* Cannot be configured as input, drive output low, don't rely on the default setting of PxDOUT register */ +GPIO(EN_PP5000_USB_AG, PIN(A, 7), GPIO_INPUT | GPIO_PULL_UP) /* Unconnected power sequencing signal */ GPIO(UNUSED_GPIO41, PIN(4, 1), GPIO_INPUT | GPIO_PULL_UP) GPIO(UNUSED_GPIOF2, PIN(F, 2), GPIO_INPUT | GPIO_PULL_UP) GPIO(UNUSED_GPIO96, PIN(9, 6), GPIO_INPUT | GPIO_PULL_UP) GPIO(UNUSED_GPIO34, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) +/* Only connected to test points */ +GPIO(EC_KB_BL_EN, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(EC_ESPI_ALERT_L, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) /* * eDP backlight - both PCH and EC have enable pins that must be high @@ -182,3 +182,6 @@ ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = GPIO01 = H1_EC_PWR_BTN_ODL GPIO02 = EC_RST_ODL */ +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ diff --git a/board/volteer/led.c b/board/volteer/led.c index 4486bcb912..adc8f7b4a6 100644 --- a/board/volteer/led.c +++ b/board/volteer/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -18,17 +18,17 @@ const enum ec_led_id supported_led_ids[] = { }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -struct pwm_led led_color_map[] = { - /* Red, Green, Blue */ - [EC_LED_COLOR_RED] = { 100, 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Red, Green, Blue */ + [EC_LED_COLOR_RED] = { 100, 0, 0 }, + [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, /* The green LED seems to be brighter than the others, so turn down * green from its natural level for these secondary colors. */ - [EC_LED_COLOR_YELLOW] = { 100, 70, 0 }, - [EC_LED_COLOR_WHITE] = { 100, 70, 100 }, - [EC_LED_COLOR_AMBER] = { 100, 20, 0 }, + [EC_LED_COLOR_YELLOW] = { 100, 70, 0 }, + [EC_LED_COLOR_WHITE] = { 100, 70, 100 }, + [EC_LED_COLOR_AMBER] = { 100, 20, 0 }, }; struct pwm_led pwm_leds[] = { @@ -102,3 +102,11 @@ static void led_set_charge_port_tick(void) pwm_set_duty(PWM_CH_LED4_SIDESEL, side_select_duty); } DECLARE_HOOK(HOOK_TICK, led_set_charge_port_tick, HOOK_PRIO_DEFAULT); + +static void board_led_init(void) +{ + /* Illuminate motherboard and daughter board LEDs equally to start. */ + pwm_enable(PWM_CH_LED4_SIDESEL, 1); + pwm_set_duty(PWM_CH_LED4_SIDESEL, 50); +} +DECLARE_HOOK(HOOK_INIT, board_led_init, HOOK_PRIO_DEFAULT); diff --git a/board/volteer/sensors.c b/board/volteer/sensors.c index 9e34812131..61068c28f1 100644 --- a/board/volteer/sensors.c +++ b/board/volteer/sensors.c @@ -1,27 +1,27 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer family-specific sensor configuration */ -#include "common.h" #include "accelgyro.h" -#include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi_common.h" -#include "driver/accelgyro_bmi260.h" -#include "driver/als_tcs3400.h" -#include "driver/sync.h" -#include "keyboard_scan.h" +#include "common.h" +#include "driver/accel_bma2x2_public.h" +#include "driver/accelgyro_bmi260_public.h" +#include "driver/accelgyro_bmi_common_public.h" +#include "driver/als_tcs3400_public.h" +#include "gpio.h" #include "hooks.h" #include "i2c.h" -#include "task.h" +#include "keyboard_scan.h" #include "tablet_mode.h" +#include "task.h" #include "util.h" /******************************************************************************/ /* Sensors */ -static struct mutex g_lid_accel_mutex; -static struct mutex g_base_mutex; +K_MUTEX_DEFINE(g_lid_accel_mutex); +K_MUTEX_DEFINE(g_base_mutex); /* BMA253 private data */ static struct accelgyro_saved_data_t g_bma253_data; @@ -84,17 +84,13 @@ static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { }; /* Rotation matrix for the lid accelerometer */ -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { @@ -224,22 +220,3 @@ static void baseboard_sensors_init(void) gpio_enable_interrupt(GPIO_EC_IMU_INT_L); } DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); - -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) -{ - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); - - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } -} -#endif diff --git a/board/volteer/usbc_config.c b/board/volteer/usbc_config.c new file mode 100644 index 0000000000..e95143cd39 --- /dev/null +++ b/board/volteer/usbc_config.c @@ -0,0 +1,409 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific USB-C configuration */ +#include "cbi_ec_fw_config.h" +#include "common.h" +#include "driver/bc12/pi3usb9201_public.h" +#include "driver/ppc/sn5s330_public.h" +#include "driver/ppc/syv682x_public.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "driver/tcpm/rt1715_public.h" +#include "driver/tcpm/tcpci.h" +#include "driver/tcpm/tusb422_public.h" +#include "gpio.h" +#include "hooks.h" +#include "system.h" +#include "timer.h" +#include "usb_mux.h" +#include "usbc_config.h" +#include "usbc_ppc.h" + +/* Disable debug messages to save flash space */ +#define CPRINTS(format, args...) + +/* USBC TCPC configuration for USB3 daughter board */ +static const struct tcpc_config_t tcpc_config_p1_usb3 = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0 | TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V, + .drv = &ps8xxx_tcpm_drv, +}; + +/* + * USB3 DB mux configuration - the top level mux still needs to be set to the + * virtual_usb_mux_driver so the AP gets notified of mux changes and updates + * the TCSS configuration on state changes. + */ +static const struct usb_mux_chain usbc1_usb3_db_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + .next = NULL, +}; + +static const struct usb_mux_chain mux_config_p1_usb3_active = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + .next = &usbc1_usb3_db_retimer, +}; + +static const struct usb_mux_chain mux_config_p1_usb3_passive = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + } +}; + +/* + * Set up support for the USB3 daughterboard: + * Parade PS8815 TCPC (integrated retimer) + * Diodes PI3USB9201 BC 1.2 chip (same as USB4 board) + * Silergy SYV682A PPC (same as USB4 board) + * Virtual mux with stacked retimer + */ +static void config_db_usb3_active(void) +{ + tcpc_config[USBC_PORT_C1] = tcpc_config_p1_usb3; + usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3_active; +} + +/* + * Set up support for the passive USB3 daughterboard: + * TUSB422 TCPC (already the default) + * PI3USB9201 BC 1.2 chip (already the default) + * Silergy SYV682A PPC (already the default) + * Virtual mux without stacked retimer + */ + +static void config_db_usb3_passive(void) +{ + usb_muxes[USBC_PORT_C1] = mux_config_p1_usb3_passive; +} + +static void config_port_discrete_tcpc(int port) +{ + /* + * Support 2 Pin-to-Pin compatible parts: TUSB422 and RT1715, for + * simplicity allow either and decide at runtime which we are using. + * Default to TUSB422, and switch to RT1715 if it is on the I2C bus and + * the VID matches. + */ + + int regval; + + if (i2c_read16(port ? I2C_PORT_USB_C1 : I2C_PORT_USB_C0, + RT1715_I2C_ADDR_FLAGS, TCPC_REG_VENDOR_ID, + ®val) == EC_SUCCESS) { + if (regval == RT1715_VENDOR_ID) { + CPRINTS("C%d: RT1715 detected", port); + tcpc_config[port].i2c_info.addr_flags = + RT1715_I2C_ADDR_FLAGS; + tcpc_config[port].drv = &rt1715_tcpm_drv; + return; + } + } + CPRINTS("C%d: Default to TUSB422", port); +} + +void config_usb3_db_type(void) +{ + enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); + + config_port_discrete_tcpc(0); + switch (usb_db) { + case DB_USB_ABSENT: + CPRINTS("USB DB Type: None"); + break; + case DB_USB4_GEN2: + config_port_discrete_tcpc(1); + CPRINTS("USB DB Type: USB4 Gen1/2"); + break; + case DB_USB4_GEN3: + config_port_discrete_tcpc(1); + CPRINTS("USB DB Type: USB4 Gen3"); + break; + case DB_USB3_ACTIVE: + config_db_usb3_active(); + CPRINTS("USB DB Type: USB3 Active"); + break; + case DB_USB3_PASSIVE: + config_db_usb3_passive(); + config_port_discrete_tcpc(1); + CPRINTS("USB DB Type: USB3 Passive"); + break; + default: + CPRINTS("USB DB Type: ID %d not supported", usb_db); + } +} + +/******************************************************************************/ +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .frs_en = GPIO_USB_C1_FRS_EN, + .drv = &syv682x_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/******************************************************************************/ +/* PPC support routines */ +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + sn5s330_interrupt(USBC_PORT_C0); + break; + case GPIO_USB_C1_PPC_INT_ODL: + syv682x_interrupt(USBC_PORT_C1); + break; + default: + break; + } +} + +/******************************************************************************/ +/* USBC TCPC configuration */ +struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = TUSB422_I2C_ADDR_FLAGS, + }, + .drv = &tusb422_tcpm_drv, + }, + [USBC_PORT_C1] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C1, + .addr_flags = TUSB422_I2C_ADDR_FLAGS, + }, + .drv = &tusb422_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USB-A charging control */ + +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USBA, +}; + +/******************************************************************************/ +/* USBC mux configuration - Tiger Lake includes internal mux */ +struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + } +}; + +struct usb_mux_chain usb_muxes[] = { + [USBC_PORT_C0] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, + }, + [USBC_PORT_C1] = { + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_1_MIX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + +struct bb_usb_control bb_controls[] = { + [USBC_PORT_C0] = { + /* USB-C port 0 doesn't have a retimer */ + }, + [USBC_PORT_C1] = { + .usb_ls_en_gpio = GPIO_USB_C1_LS_EN, + .retimer_rst_gpio = GPIO_USB_C1_RT_RST_ODL, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(bb_controls) == USBC_PORT_COUNT); + +__override enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); + + if (port == USBC_PORT_C1) { + if (usb_db == DB_USB4_GEN2) { + /* + * Older boards violate 205mm trace length prior + * to connection to the re-timer and only support up + * to GEN2 speeds. + */ + return TBT_SS_U32_GEN1_GEN2; + } else if (usb_db == DB_USB4_GEN3) { + return TBT_SS_TBT_GEN3; + } + } + + /* + * Thunderbolt-compatible mode not supported + * + * TODO (b/147726366): All the USB-C ports need to support same speed. + * Need to fix once USB-C feature set is known for Volteer. + */ + return TBT_SS_RES_0; +} + +__override bool board_is_tbt_usb4_port(int port) +{ + enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); + + /* + * Volteer reference design only supports TBT & USB4 on port 1 + * if the USB4 DB is present. + * + * TODO (b/147732807): All the USB-C ports need to support same + * features. Need to fix once USB-C feature set is known for Volteer. + */ + return ((port == USBC_PORT_C1) && + ((usb_db == DB_USB4_GEN2) || (usb_db == DB_USB4_GEN3))); +} + +static void ps8815_reset(void) +{ + int val; + + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 0); + msleep(GENERIC_MAX(PS8XXX_RESET_DELAY_MS, PS8815_PWR_H_RST_H_DELAY_MS)); + gpio_set_level(GPIO_USB_C1_RT_RST_ODL, 1); + msleep(PS8815_FW_INIT_DELAY_MS); + + /* + * b/144397088 + * ps8815 firmware 0x01 needs special configuration + */ + + CPRINTS("%s: patching ps8815 registers", __func__); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f was %02x", val); + + if (i2c_write8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, + 0x31) == EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f set to 0x31"); + + if (i2c_read8(I2C_PORT_USB_C1, PS8XXX_I2C_ADDR1_P2_FLAGS, 0x0f, &val) == + EC_SUCCESS) + CPRINTS("ps8815: reg 0x0f now %02x", val); +} + +void board_reset_pd_mcu(void) +{ + enum ec_cfg_usb_db_type usb_db = ec_cfg_usb_db_type(); + + /* No reset available for TCPC on port 0 */ + /* Daughterboard specific reset for port 1 */ + if (usb_db == DB_USB3_ACTIVE) { + ps8815_reset(); + usb_mux_hpd_update(USBC_PORT_C1, + USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); + } +} + +static void board_tcpc_init(void) +{ + /* Don't reset TCPCs after initial reset */ + if (!system_jumped_late()) + board_reset_pd_mcu(); + + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_TCPC_INT_ODL); + +#ifndef CONFIG_ZEPHYR + /* Enable BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_ODL); +#endif /* !CONFIG_ZEPHYR */ +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_CHIPSET); + +#ifndef CONFIG_ZEPHYR +/******************************************************************************/ +/* BC1.2 charger detect configuration */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + [USBC_PORT_C1] = { + .i2c_port = I2C_PORT_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pi3usb9201_bc12_chips) == USBC_PORT_COUNT); +#endif /* !CONFIG_ZEPHYR */ + +/******************************************************************************/ +/* TCPC support routines */ +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} + +/******************************************************************************/ + +int ppc_get_alert_status(int port) +{ + if (port == USBC_PORT_C0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + else + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; +} diff --git a/board/volteer/usbc_config.h b/board/volteer/usbc_config.h new file mode 100644 index 0000000000..7428d0c436 --- /dev/null +++ b/board/volteer/usbc_config.h @@ -0,0 +1,16 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* volteer board-specific USB-C configuration */ + +#ifndef __CROS_EC_USBC_CONFIG_H +#define __CROS_EC_USBC_CONFIG_H + +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; + +/* Configure the USB3 daughterboard type */ +void config_usb3_db_type(void); + +#endif /* __CROS_EC_USBC_CONFIG_H */ diff --git a/board/volteer/vif_override.xml b/board/volteer/vif_override.xml new file mode 100644 index 0000000000..771f0fe076 --- /dev/null +++ b/board/volteer/vif_override.xml @@ -0,0 +1,114 @@ + + + Volteer RT1715 + 0 + 0 + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 9A1B + + + + 8087 + + + + + + Not TBT3-Compatible + + + + + + + + + NO + + + + + 50 msec + 3600 mA + + + + + + + Gen 3 (40Gb) + + + + + + + + + + HBR3 + 4 Lanes + + + USB 3.2 Gen 2x1 + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + PSD + Alternate Mode Controller (AMC) + + + 18D1 + 0000 + + + + + + 8087 + + + + + + + 00000000 + + + + + + diff --git a/board/volteer_ish/board.c b/board/volteer_ish/board.c index 76c127056b..59b63c2a28 100644 --- a/board/volteer_ish/board.c +++ b/board/volteer_ish/board.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,8 +6,8 @@ /* Volteer ISH board-specific configuration */ #include "console.h" -#include "driver/accelgyro_bmi_common.h" #include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -16,15 +16,12 @@ #include "power.h" #include "task.h" -#include "gpio_list.h" /* has to be included last */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" /* I2C port map */ const struct i2c_port_t i2c_ports[] = { - { - .name = "sensor", - .port = I2C_PORT_SENSOR, - .kbps = 1000 - }, + { .name = "sensor", .port = I2C_PORT_SENSOR, .kbps = 1000 }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/volteer_ish/board.h b/board/volteer_ish/board.h index b290d70b19..6f7d3bd1b7 100644 --- a/board/volteer_ish/board.h +++ b/board/volteer_ish/board.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,26 +22,24 @@ #define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF /* ISH specific */ -#undef CONFIG_DEBUG_ASSERT +#undef CONFIG_DEBUG_ASSERT #define CONFIG_CLOCK_CRYSTAL #define CONFIG_ISH_UART_0 /* EC */ -#define CONFIG_FLASH_SIZE 0x80000 +#define CONFIG_FLASH_SIZE_BYTES 0x80000 #define CONFIG_FPU #define CONFIG_I2C -#define CONFIG_I2C_MASTER +#define CONFIG_I2C_CONTROLLER /* BMA253 Lid accel */ #define CONFIG_ACCEL_BMA255 /* Host command over HECI */ -#define CONFIG_HOSTCMD_HECI +#define CONFIG_HOST_INTERFACE_HECI #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_HECI -#define CONFIG_ACCEL_INTERRUPTS - /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO /* FIFO size is in power of 2. */ @@ -70,7 +68,7 @@ #undef CONFIG_CMD_SHMEM #undef CONFIG_EXTPOWER #undef CONFIG_KEYBOARD_KSO_BASE -#undef CONFIG_FLASH +#undef CONFIG_FLASH_CROS #undef CONFIG_FMAP #undef CONFIG_LID_SWITCH #undef CONFIG_SWITCH @@ -88,10 +86,7 @@ #include "registers.h" /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, SENSOR_COUNT }; #endif /* !__ASSEMBLER__ */ diff --git a/board/volteer_ish/build.mk b/board/volteer_ish/build.mk index 74ec3c865f..4a84a1f475 100644 --- a/board/volteer_ish/build.mk +++ b/board/volteer_ish/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/volteer_ish/ec.tasklist b/board/volteer_ish/ec.tasklist index a4db486e9a..de7d256324 100644 --- a/board/volteer_ish/ec.tasklist +++ b/board/volteer_ish/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/volteer_ish/gpio.inc b/board/volteer_ish/gpio.inc index 286309e388..8b25af63cb 100644 --- a/board/volteer_ish/gpio.inc +++ b/board/volteer_ish/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/volteer_tcpmv1 b/board/volteer_npcx797fc similarity index 100% rename from board/volteer_tcpmv1 rename to board/volteer_npcx797fc diff --git a/board/voxel/battery.c b/board/voxel/battery.c index 4d314150e2..887ba27344 100644 --- a/board/voxel/battery.c +++ b/board/voxel/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -44,6 +44,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x43, .reg_mask = 0x0001, .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, } }, .batt_info = { @@ -59,37 +61,65 @@ const struct board_batt_params board_battery_info[] = { .discharging_max_c = 75, }, }, - /* LGC\011 L17L3PB0 Battery Information */ - /* - * Battery info provided by ODM on b/143477210, comment #11 - */ - [BATTERY_LGC011] = { + /* LGC AP18C8K Battery Information */ + [BATTERY_LGC_AP18C8K] = { .fuel_gauge = { - .manuf_name = "LGC", + .manuf_name = "LGC KT0030G020", .ship_mode = { - .reg_addr = 0x00, - .reg_data = { 0x10, 0x10 }, + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* COSMX AP20CBL Battery Information */ + [BATTERY_COSMX_AP20CBL] = { + .fuel_gauge = { + .manuf_name = "COSMX KT0030B002", + .device_name = "AP20CBL", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, }, .fet = { + .mfgacc_support = 1, .reg_addr = 0x0, - .reg_mask = 0x6000, - .disconnect_val = 0x6000, - } + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + }, }, .batt_info = { - .voltage_max = TARGET_WITH_MARGIN(13200, 5), - .voltage_normal = 11550, /* mV */ - .voltage_min = 9000, /* mV */ - .precharge_current = 256, /* mA */ - .start_charging_min_c = 0, - .start_charging_max_c = 45, - .charging_min_c = 0, - .charging_max_c = 60, - .discharging_min_c = 0, - .discharging_max_c = 75, + .voltage_max = 13200, + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, }, }, }; BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); -const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC011; +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_AP19B8M; diff --git a/board/voxel/board.c b/board/voxel/board.c index 6f6b1824fb..9faef2db6b 100644 --- a/board/voxel/board.c +++ b/board/voxel/board.c @@ -1,24 +1,23 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer board-specific configuration */ -#include "bb_retimer.h" -#include "button.h" -#include "common.h" #include "accelgyro.h" +#include "button.h" #include "cbi_ec_fw_config.h" +#include "common.h" #include "driver/accel_bma2x2.h" #include "driver/accelgyro_bmi160.h" #include "driver/als_tcs3400.h" #include "driver/bc12/pi3usb9201.h" #include "driver/ppc/syv682x.h" +#include "driver/retimer/bb_retimer_public.h" +#include "driver/sync.h" +#include "driver/tcpm/rt1715.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tusb422.h" -#include "driver/tcpm/rt1715.h" -#include "driver/retimer/bb_retimer.h" -#include "driver/sync.h" #include "extpower.h" #include "fan.h" #include "fan_chip.h" @@ -32,8 +31,8 @@ #include "pwm_chip.h" #include "switch.h" #include "system.h" -#include "task.h" #include "tablet_mode.h" +#include "task.h" #include "throttle_ap.h" #include "uart.h" #include "usb_mux.h" @@ -43,12 +42,56 @@ #include "usbc_ppc.h" #include "util.h" -#include "gpio_list.h" /* Must come after other header files. */ +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) + +static const struct ec_response_keybd_config zbu_new_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, + TK_REFRESH, + TK_FULLSCREEN, + TK_OVERVIEW, + TK_SNAPSHOT, + TK_BRIGHTNESS_DOWN, + TK_BRIGHTNESS_UP, + TK_VOL_MUTE, + TK_VOL_DOWN, + TK_VOL_UP, + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +static const struct ec_response_keybd_config zbu_old_kb = { + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + if (get_board_id() > 2) + return &zbu_new_kb; + else + return &zbu_old_kb; +} /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* Increase from 50 us, because KSO_02 passes through the H1. */ .output_settle_us = 80, /* Other values should be the same as the default configuration. */ @@ -63,6 +106,33 @@ struct keyboard_scan_config keyscan_config = { }, }; +/* + * We have total 30 pins for keyboard connecter {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + { -1, -1 }, { 0, 5 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 7 }, + { -1, -1 }, { -1, -1 }, { 1, 4 }, { 1, 3 }, { -1, -1 }, { 1, 6 }, + { 1, 7 }, { 3, 1 }, { 2, 0 }, { 1, 5 }, { 2, 6 }, { 2, 7 }, + { 2, 1 }, { 2, 4 }, { 2, 5 }, { 1, 2 }, { 2, 3 }, { 2, 2 }, + { 3, 0 }, { -1, -1 }, { 0, 4 }, { -1, -1 }, { 8, 2 }, { -1, -1 }, + { -1, -1 }, +}; +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); + +__override uint32_t board_override_feature_flags0(uint32_t flags0) +{ + /* + * Remove keyboard backlight feature for devices that don't support it. + */ + if (!ec_cfg_has_keyboard_backlight()) + return (flags0 & ~EC_FEATURE_MASK_0(EC_FEATURE_PWM_KEYB)); + else + return flags0; +} + /******************************************************************************/ /* * FW_CONFIG defaults for Voxel if the CBI data is not initialized. @@ -76,7 +146,7 @@ union volteer_cbi_fw_config fw_config_defaults = { const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = GPIO_EN_PP5000_FAN, }; @@ -87,11 +157,13 @@ const struct fan_conf fan_conf_0 = { * Minimum speed not specified by RPM. Set minimum RPM to max speed (with * margin) x 30%. * 5900 x 1.07 x 0.30 = 1894, round up to 1900 + * reference that temperature and fan settings + * are derived from data in b/167523658#39 */ const struct fan_rpm fan_rpm_0 = { - .rpm_min = 1900, - .rpm_start = 1900, - .rpm_max = 5900, + .rpm_min = 2100, + .rpm_start = 2100, + .rpm_max = 5800, }; const struct fan_t fans[FAN_CH_COUNT] = { @@ -105,51 +177,31 @@ const struct fan_t fans[FAN_CH_COUNT] = { /* EC thermal management configuration */ /* - * Tiger Lake specifies 100 C as maximum TDP temperature. THRMTRIP# occurs at - * 130 C. However, sensor is located next to DDR, so we need to use the lower - * DDR temperature limit (85 C) + * Reference that temperature and fan settings + * are derived from data in b/167523658#39 */ -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(35), - .temp_fan_max = C_TO_K(50), -}; - /* - * Inductor limits - used for both charger and PP3300 regulator - * - * Need to use the lower of the charger IC, PP3300 regulator, and the inductors - * - * Charger max recommended temperature 100C, max absolute temperature 125C - * PP3300 regulator: operating range -40 C to 145 C - * - * Inductors: limit of 125c - * PCB: limit is 80c + * TODO(b/202062363): Remove when clang is fixed. */ -const static struct ec_thermal_config thermal_inductor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(75), - [EC_TEMP_THRESH_HALT] = C_TO_K(80), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), - }, - .temp_fan_off = C_TO_K(40), - .temp_fan_max = C_TO_K(55), -}; - +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(75), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(68), \ + }, \ + .temp_fan_off = C_TO_K(25), \ + .temp_fan_max = C_TO_K(90), \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; struct ec_thermal_config thermal_params[] = { - [TEMP_SENSOR_1_CHARGER] = thermal_inductor, - [TEMP_SENSOR_2_PP3300_REGULATOR] = thermal_inductor, - [TEMP_SENSOR_3_DDR_SOC] = thermal_cpu, - [TEMP_SENSOR_4_FAN] = thermal_cpu, + [TEMP_SENSOR_1_CHARGER] = THERMAL_CPU, + [TEMP_SENSOR_2_PP3300_REGULATOR] = THERMAL_CPU, + [TEMP_SENSOR_3_DDR_SOC] = THERMAL_CPU, + [TEMP_SENSOR_4_FAN] = THERMAL_CPU, }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); @@ -243,13 +295,15 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); static void kb_backlight_enable(void) { - gpio_set_level(GPIO_EC_KB_BL_EN, 1); + if (ec_cfg_has_keyboard_backlight()) + gpio_set_level(GPIO_EC_KB_BL_EN, 1); } DECLARE_HOOK(HOOK_CHIPSET_RESUME, kb_backlight_enable, HOOK_PRIO_DEFAULT); static void kb_backlight_disable(void) { - gpio_set_level(GPIO_EC_KB_BL_EN, 0); + if (ec_cfg_has_keyboard_backlight()) + gpio_set_level(GPIO_EC_KB_BL_EN, 0); } DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kb_backlight_disable, HOOK_PRIO_DEFAULT); @@ -260,12 +314,12 @@ static void setup_board_tcpc(void) if (board_id == 0) { /* config typec C0 prot TUSB422 TCPC */ - tcpc_config[USBC_PORT_C0].i2c_info.addr_flags - = TUSB422_I2C_ADDR_FLAGS; + tcpc_config[USBC_PORT_C0].i2c_info.addr_flags = + TUSB422_I2C_ADDR_FLAGS; tcpc_config[USBC_PORT_C0].drv = &tusb422_tcpm_drv; /* config typec C1 prot TUSB422 TCPC */ - tcpc_config[USBC_PORT_C1].i2c_info.addr_flags - = TUSB422_I2C_ADDR_FLAGS; + tcpc_config[USBC_PORT_C1].i2c_info.addr_flags = + TUSB422_I2C_ADDR_FLAGS; tcpc_config[USBC_PORT_C1].drv = &tusb422_tcpm_drv; } } @@ -278,11 +332,6 @@ void board_reset_pd_mcu(void) */ } -__override void board_cbi_init(void) -{ - setup_board_tcpc(); -} - /******************************************************************************/ /* USB-A charging control */ @@ -297,11 +346,13 @@ struct ppc_config_t ppc_chips[] = { .i2c_port = I2C_PORT_USB_C0, .i2c_addr_flags = SYV682X_ADDR0_FLAGS, .drv = &syv682x_drv, + .frs_en = GPIO_USB_C0_FRS_EN, }, [USBC_PORT_C1] = { .i2c_port = I2C_PORT_USB_C1, .i2c_addr_flags = SYV682X_ADDR0_FLAGS, .drv = &syv682x_drv, + .frs_en = GPIO_USB_C1_FRS_EN, }, }; BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); @@ -317,11 +368,29 @@ void ppc_interrupt(enum gpio_signal signal) break; case GPIO_USB_C1_PPC_INT_ODL: syv682x_interrupt(USBC_PORT_C1); + break; default: break; } } +/* Disable FRS on boards with the SYV682A. FRS only works on the SYV682B. */ +void setup_board_ppc(void) +{ + uint8_t board_id = get_board_id(); + + if (board_id < 2) { + ppc_chips[USBC_PORT_C0].frs_en = 0; + ppc_chips[USBC_PORT_C1].frs_en = 0; + } +} + +__override void board_cbi_init(void) +{ + setup_board_tcpc(); + setup_board_ppc(); +} + /******************************************************************************/ /* BC1.2 charger detect configuration */ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { @@ -346,7 +415,6 @@ struct tcpc_config_t tcpc_config[] = { .addr_flags = RT1715_I2C_ADDR_FLAGS, }, .drv = &rt1715_tcpm_drv, - .usb23 = USBC_PORT_0_USB2_NUM | (USBC_PORT_0_USB3_NUM << 4), }, [USBC_PORT_C1] = { .bus_type = EC_BUS_TYPE_I2C, @@ -355,7 +423,6 @@ struct tcpc_config_t tcpc_config[] = { .addr_flags = RT1715_I2C_ADDR_FLAGS, }, .drv = &rt1715_tcpm_drv, - .usb23 = USBC_PORT_1_USB2_NUM | (USBC_PORT_1_USB3_NUM << 4), }, }; BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); @@ -363,30 +430,43 @@ BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); /******************************************************************************/ /* USBC mux configuration - Tiger Lake includes internal mux */ -struct usb_mux usbc0_usb4_db_retimer = { - .usb_port = USBC_PORT_C0, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_0_MIX, - .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, +struct usb_mux_chain usbc0_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }; -struct usb_mux usbc1_usb4_db_retimer = { - .usb_port = USBC_PORT_C1, - .driver = &bb_usb_retimer, - .i2c_port = I2C_PORT_USB_1_MIX, - .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, +struct usb_mux_chain usbc1_tcss_usb_mux = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C1, + .driver = &virtual_usb_mux_driver, + .hpd_update = &virtual_hpd_update, + }, }; -struct usb_mux usb_muxes[] = { + +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc0_usb4_db_retimer, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_0_MIX, + .i2c_addr_flags = USBC_PORT_C0_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc0_tcss_usb_mux, }, [USBC_PORT_C1] = { - .usb_port = USBC_PORT_C1, - .driver = &virtual_usb_mux_driver, - .hpd_update = &virtual_hpd_update, - .next_mux = &usbc1_usb4_db_retimer, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C1, + .driver = &bb_usb_retimer, + .hpd_update = bb_retimer_hpd_update, + .i2c_port = I2C_PORT_USB_1_MIX, + .i2c_addr_flags = USBC_PORT_C1_BB_RETIMER_I2C_ADDR, + }, + .next = &usbc1_tcss_usb_mux, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); diff --git a/board/voxel/board.h b/board/voxel/board.h index 9f81e1da5b..1b866a5749 100644 --- a/board/voxel/board.h +++ b/board/voxel/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,7 +13,7 @@ /* Optional features */ #undef NPCX7_PWM1_SEL -#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ +#define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ /* * The RAM and flash size combination on the the NPCX797FC does not leave @@ -21,8 +21,6 @@ */ #undef CONFIG_CHIP_INIT_ROM_REGION -#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands while in dev. */ - #define CONFIG_VBOOT_EFS2 #define CONFIG_POWER_BUTTON @@ -32,66 +30,79 @@ /* Chipset features */ #define CONFIG_POWER_PP5000_CONTROL +#define CONFIG_CPU_PROCHOT_GATE_ON_C10 /* LED defines */ #define CONFIG_LED_ONOFF_STATES /* Keyboard features */ +#define CONFIG_KEYBOARD_FACTORY_TEST +#define CONFIG_KEYBOARD_REFRESH_ROW3 + +/* Keyboard backliht */ +#define CONFIG_PWM +#define CONFIG_PWM_KBLIGHT /* Sensors */ +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT /* BMI160 Base accel/gyro */ #define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel second source*/ +#define CONFIG_ACCELGYRO_ICM42607 /* Base accel second source*/ #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) /* BMA253 Lid accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ #define CONFIG_ACCEL_BMA255 #define CONFIG_LID_ANGLE #define CONFIG_LID_ANGLE_UPDATE -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL /* USB Type C and USB PD defines */ -#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 -/* - * USB-C port's USB2 & USB3 mapping from schematics - * USB2 numbering on PCH - 1 to n - * USB3 numbering on AP - 0 to n (PMC's USB3 numbering for MUX - * configuration is - 1 to n hence add +1) - */ -#define USBC_PORT_0_USB2_NUM 9 -#define USBC_PORT_0_USB3_NUM 1 -#define USBC_PORT_1_USB2_NUM 4 -#define USBC_PORT_1_USB3_NUM 2 - -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ -#define PD_VCONN_SWAP_DELAY 5000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ /* * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C * cables only support up to 60W. */ -#define PD_OPERATING_POWER_MW 15000 -#define PD_MAX_POWER_MW 60000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_VOLTAGE_MV 20000 +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 45000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +#define CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY +#ifdef BOARD_VOXEL_ECMODEENTRY +#undef CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY +#endif /* Enabling Thunderbolt-compatible mode */ #define CONFIG_USB_PD_TBT_COMPAT_MODE /* Enabling USB4 mode */ #define CONFIG_USB_PD_USB4 -#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x40 -#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x41 +#define USBC_PORT_C0_BB_RETIMER_I2C_ADDR 0x40 +#define USBC_PORT_C1_BB_RETIMER_I2C_ADDR 0x41 +#define CONFIG_USB_PD_DATA_RESET_MSG /* USB Type A Features */ -#define USB_PORT_COUNT 1 +#define USB_PORT_COUNT 1 #define CONFIG_USB_PORT_POWER_DUMB /* USBC PPC*/ -#define CONFIG_USBC_PPC_SYV682X /* USBC port C0/C1 */ +#define CONFIG_USBC_PPC_SYV682X /* USBC port C0/C1 */ +#define CONFIG_USB_PD_FRS_PPC /* BC 1.2 */ @@ -103,8 +114,8 @@ /* Fan features */ /* charger defines */ -#define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 /* * Macros for GPIO signals used in common code that don't match the @@ -112,47 +123,44 @@ * then redefined here to so it's more clear which signal is being used for * which purpose. */ -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL -#define GPIO_EN_PP5000 GPIO_EN_PP5000_A -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_LID_OPEN GPIO_EC_LID_OPEN -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE -#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL -#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL -#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL -#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST -#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK -#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL -#define GPIO_RSMRST_L_PGOOD GPIO_PG_EC_RSMRST_ODL -#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL -#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL -#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL -#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_EC_INT_L GPIO_EC_PCH_INT_ODL +#define GPIO_EN_PP5000 GPIO_EN_PP5000_A +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_LID_OPEN GPIO_EC_LID_OPEN +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE +#define GPIO_PCH_WAKE_L GPIO_EC_PCH_WAKE_ODL +#define GPIO_PCH_PWRBTN_L GPIO_EC_PCH_PWR_BTN_ODL +#define GPIO_PCH_RSMRST_L GPIO_EC_PCH_RSMRST_ODL +#define GPIO_PCH_RTCRST GPIO_EC_PCH_RTCRST +#define GPIO_PCH_SLP_S0_L GPIO_SLP_S0_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_DSW_PWROK GPIO_EC_PCH_DSW_PWROK +#define GPIO_POWER_BUTTON_L GPIO_H1_EC_PWR_BTN_ODL +#define GPIO_CPU_PROCHOT GPIO_EC_PROCHOT_ODL +#define GPIO_SYS_RESET_L GPIO_SYS_RST_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_USB_C1_BC12_INT_ODL GPIO_USB_C1_MIX_INT_ODL +#define GPIO_VOLUME_UP_L GPIO_EC_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_EC_VOLDN_BTN_ODL /* I2C Bus Configuration */ #define CONFIG_I2C -#define I2C_PORT_ACCEL I2C_PORT_SENSOR -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_0_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT4_1 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 - -#define I2C_PORT_BATTERY I2C_PORT_POWER -#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_0_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT4_1 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_I2C_MASTER +#define I2C_PORT_BATTERY I2C_PORT_POWER +#define I2C_PORT_CHARGER I2C_PORT_EEPROM +#define I2C_ADDR_EEPROM_FLAGS 0x50 +#define CONFIG_I2C_CONTROLLER #ifndef __ASSEMBLER__ @@ -161,15 +169,12 @@ enum battery_type { BATTERY_AP19B8M, - BATTERY_LGC011, + BATTERY_LGC_AP18C8K, + BATTERY_COSMX_AP20CBL, BATTERY_TYPE_COUNT, }; -enum pwm_channel { - PWM_CH_FAN, - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_FAN, PWM_CH_KBLIGHT, PWM_CH_COUNT }; enum sensor_id { LID_ACCEL = 0, @@ -178,14 +183,12 @@ enum sensor_id { SENSOR_COUNT, }; -enum usbc_port { - USBC_PORT_C0 = 0, - USBC_PORT_C1, - USBC_PORT_COUNT -}; +enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT }; void board_reset_pd_mcu(void); +void motion_interrupt(enum gpio_signal signal); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/voxel/build.mk b/board/voxel/build.mk index 838d6a16ce..c994631759 100644 --- a/board/voxel/build.mk +++ b/board/voxel/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/voxel/ec.tasklist b/board/voxel/ec.tasklist index 292de51cdb..ebcf47c499 100644 --- a/board/voxel/ec.tasklist +++ b/board/voxel/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,7 +15,8 @@ TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_MUX, usb_mux_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/voxel/gpio.inc b/board/voxel/gpio.inc index 3d8c61dceb..171288a639 100644 --- a/board/voxel/gpio.inc +++ b/board/voxel/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, ex /* Power sequencing interrupts */ GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) -#ifndef CONFIG_HOSTCMD_ESPI_VW_SLP_S3 +#ifndef CONFIG_HOST_INTERFACE_ESPI_VW_SLP_S3 GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, power_signal_interrupt) #endif GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) @@ -25,7 +25,7 @@ GPIO_INT(PG_EC_DSW_PWROK, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt) /* Sensor Interrupts */ -GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, bmi160_interrupt) +GPIO_INT(EC_IMU_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) GPIO(EC_ALS_RGB_INT_L, PIN(D, 4), GPIO_INPUT | GPIO_PULL_UP) /* unused */ GPIO_INT(TABLET_MODE_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) /* @@ -77,10 +77,10 @@ GPIO(EC_PCH_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) GPIO(EC_PROCHOT_ODL, PIN(6, 3), GPIO_ODR_HIGH) GPIO_INT(EC_PROCHOT_IN_L, PIN(F, 0), GPIO_INT_BOTH, throttle_ap_prochot_input_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_RISING, throttle_ap_c10_input_interrupt) GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) GPIO(EC_PCH_INT_ODL, PIN(B, 0), GPIO_ODR_HIGH) -GPIO(CPU_C10_GATE_L, PIN(6, 7), GPIO_INPUT) /* USB and USBC Signals */ GPIO(EN_PP5000_USBA, PIN(3, 5), GPIO_OUT_LOW) /* Enable USB-A charging - all ports */ @@ -181,3 +181,6 @@ ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) /* GPIO00 = GPIO01 = H1_EC_PWR_BTN_ODL GPIO02 = EC_RST_ODL */ +/* Temperature sensors */ +ALTERNATE(PIN_MASK(4, BIT(2) | BIT(4) | BIT(5)), 0, MODULE_ADC, 0) /* TEMP_SENSOR1,2,4 */ +ALTERNATE(PIN_MASK(F, BIT(1)), 0, MODULE_ADC, 0) /* TEMP_SENSOR3 */ diff --git a/board/voxel/led.c b/board/voxel/led.c index 8ad3e9c1f8..acd00f8941 100644 --- a/board/voxel/led.c +++ b/board/voxel/led.c @@ -1,44 +1,50 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Volteer */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED -}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: diff --git a/board/voxel/sensors.c b/board/voxel/sensors.c index fab1fac66b..81e6b13b57 100644 --- a/board/voxel/sensors.c +++ b/board/voxel/sensors.c @@ -1,24 +1,31 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Volteer family-specific sensor configuration */ -#include "common.h" #include "accelgyro.h" +#include "cbi_ec_fw_config.h" +#include "cbi_ssfc.h" +#include "common.h" #include "driver/accel_bma2x2.h" -#include "driver/accelgyro_bmi_common.h" +#include "driver/accel_kionix.h" #include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/als_tcs3400.h" #include "driver/sync.h" -#include "keyboard_scan.h" +#include "gpio.h" #include "hooks.h" #include "i2c.h" -#include "task.h" +#include "keyboard_scan.h" #include "tablet_mode.h" +#include "task.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args) /******************************************************************************/ /* Sensors */ static struct mutex g_lid_accel_mutex; @@ -26,21 +33,142 @@ static struct mutex g_base_mutex; /* BMA253 private data */ static struct accelgyro_saved_data_t g_bma253_data; +static struct kionix_accel_data g_kx022_data; /* BMI160 private data */ static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; /* Rotation matrix for the lid accelerometer */ -static const mat33_fp_t lid_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +static const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t icm42607_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, }; -const mat33_fp_t base_standard_ref = { - { FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(1)} +struct motion_sensor_t icm42607_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm42607_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, }; struct motion_sensor_t motion_sensors[] = { @@ -118,32 +246,54 @@ struct motion_sensor_t motion_sensors[] = { }; unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); +static enum ec_ssfc_base_sensor base_gyro_config = SSFC_SENSOR_BASE_DEFAULT; + static void board_sensors_init(void) { - /* Note - BMA253 interrupt unused by EC */ + base_gyro_config = get_cbi_ssfc_base_sensor(); + + if (ec_cfg_has_tabletmode()) { + if (base_gyro_config == SSFC_SENSOR_BASE_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE GYRO is ICM426XX"); + } else if (base_gyro_config == SSFC_SENSOR_BASE_ICM42607) { + motion_sensors[BASE_ACCEL] = icm42607_base_accel; + motion_sensors[BASE_GYRO] = icm42607_base_gyro; + ccprints("BASE GYRO is ICM42607"); + } else + ccprints("BASE GYRO is BMI160"); - /* Enable interrupt for the BMI160 accel/gyro sensor */ - gpio_enable_interrupt(GPIO_EC_IMU_INT_L); + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LID_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + ccprints("LID_ACCEL is KX022"); + } else + ccprints("LID_ACCEL is BMA253"); - CPRINTS("Motion Sensor Count = %d", motion_sensor_count); + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable interrupt for the accel/gyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_EC_IMU_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + } } DECLARE_HOOK(HOOK_INIT, board_sensors_init, HOOK_PRIO_DEFAULT); -#ifndef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +void motion_interrupt(enum gpio_signal signal) { - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); - - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + switch (base_gyro_config) { + case SSFC_SENSOR_BASE_ICM426XX: + icm426xx_interrupt(signal); + break; + case SSFC_SENSOR_BASE_ICM42607: + icm42607_interrupt(signal); + break; + case SSFC_SENSOR_BASE_BMI160: + default: + bmi160_interrupt(signal); + break; } } -#endif diff --git a/board/voxel/vif_override.xml b/board/voxel/vif_override.xml new file mode 100644 index 0000000000..3875c2851f --- /dev/null +++ b/board/voxel/vif_override.xml @@ -0,0 +1,158 @@ + + + Voxel + 0 + 0 + + + + + + + + 8087 + + + + + + TBT3 Compatible + + + + 8087 + 8086 + 9A1B + + + + 8087 + + + + + + Not TBT3-Compatible + + + + + + + + Gen 3 (40Gb) + + + + + + + + + + HBR3 + 4 Lanes + + + USB 3.2 Gen 2x1 + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + PSD + Alternate Mode Controller (AMC) + + + 18D1 + 0000 + + + + + + 8087 + + + + + + + 00000000 + + + + + + + Gen 3 (40Gb) + + + + + + + + + + HBR3 + 4 Lanes + + + USB 3.2 Gen 2x1 + + + + + + 3A @ 5V + + + + + 50 msec + 3600 mA + + + + + + PSD + Alternate Mode Controller (AMC) + + + 18D1 + 0000 + + + + + + 8087 + + + + + + + 00000000 + + + + + + diff --git a/board/voxel_ecmodeentry b/board/voxel_ecmodeentry new file mode 120000 index 0000000000..082df00bc3 --- /dev/null +++ b/board/voxel_ecmodeentry @@ -0,0 +1 @@ +voxel \ No newline at end of file diff --git a/board/waddledee/battery.c b/board/waddledee/battery.c index 6b77248624..37b2dd2e3d 100644 --- a/board/waddledee/battery.c +++ b/board/waddledee/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -279,6 +279,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x43, .reg_mask = 0x0001, .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0, }, }, .batt_info = { diff --git a/board/waddledee/board.c b/board/waddledee/board.c index b85ce0cd97..229573eb42 100644 --- a/board/waddledee/board.c +++ b/board/waddledee/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,16 +8,16 @@ #include "adc_chip.h" #include "button.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "driver/accel_kionix.h" #include "driver/accelgyro_lsm6dsm.h" #include "driver/bc12/pi3usb9201.h" #include "driver/charger/sm5803.h" #include "driver/retimer/tusb544.h" -#include "driver/temp_sensor/thermistor.h" #include "driver/tcpm/anx7447.h" #include "driver/tcpm/it83xx_pd.h" +#include "driver/temp_sensor/thermistor.h" #include "driver/usb_mux/it5205.h" #include "gpio.h" #include "hooks.h" @@ -32,7 +32,7 @@ #include "system.h" #include "tablet_mode.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" #include "uart.h" #include "usb_charge.h" @@ -40,7 +40,7 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" -#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) #define INT_RECHECK_US 5000 @@ -53,7 +53,7 @@ DECLARE_DEFERRED(check_c0_line); static void notify_c0_chips(void) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); sm5803_interrupt(0); } @@ -88,7 +88,7 @@ DECLARE_DEFERRED(check_c1_line); static void notify_c1_chips(void) { schedule_deferred_pd_interrupt(1); - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); sm5803_interrupt(1); } @@ -127,34 +127,26 @@ static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_VSNS_PP3300_A] = { - .name = "PP3300_A_PGOOD", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH0 - }, - [ADC_TEMP_SENSOR_1] = { - .name = "TEMP_SENSOR1", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH2 - }, - [ADC_TEMP_SENSOR_2] = { - .name = "TEMP_SENSOR2", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH3 - }, - [ADC_SUB_ANALOG] = { - .name = "SUB_ANALOG", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH13 - }, + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_SUB_ANALOG] = { .name = "SUB_ANALOG", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -204,27 +196,36 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }; /* USB Retimer */ -const struct usb_mux usbc1_retimer = { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = TUSB544_I2C_ADDR_FLAGS0, - .driver = &tusb544_drv, +const struct usb_mux_chain usbc1_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = TUSB544_I2C_ADDR_FLAGS0, + .driver = &tusb544_drv, + }, }; /* USB Muxes */ -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, }, { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = AN7447_TCPC0_I2C_ADDR_FLAGS, - .driver = &anx7447_usb_mux_driver, - .next_mux = &usbc1_retimer, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = AN7447_TCPC0_I2C_ADDR_FLAGS, + .driver = &anx7447_usb_mux_driver, + }, + .next = &usbc1_retimer, }, }; @@ -239,7 +240,6 @@ void board_init(void) c1_int_line = GPIO_USB_C1_INT_V1_ODL; } - gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); gpio_enable_interrupt(c1_int_line); @@ -247,10 +247,8 @@ void board_init(void) * If interrupt lines are already low, schedule them to be processed * after inits are completed. */ - if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) - hook_call_deferred(&check_c0_line_data, 0); - if (!gpio_get_level(c1_int_line)) - hook_call_deferred(&check_c1_line_data, 0); + check_c0_line(); + check_c1_line(); gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL); /* Enable Base Accel interrupt */ @@ -264,7 +262,8 @@ void board_init(void) sm5803_configure_gpio0(CHARGER_SECONDARY, GPIO0_MODE_OUTPUT, 0); /* Turn on 5V if the system is on, otherwise turn it off */ - on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND); + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); board_power_5v_enable(on); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -343,18 +342,6 @@ uint16_t tcpc_get_alert_status(void) return status; } -void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma, - int charge_mv) -{ - int icl = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); - - /* - * TODO(b/151955431): Characterize the input current limit in case a - * scaling needs to be applied here - */ - charge_set_input_current_limit(icl, charge_mv); -} - int board_set_active_charge_port(int port) { int is_valid_port = (port >= 0 && port < board_get_usb_pd_port_count()); @@ -404,9 +391,8 @@ void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled) gpio_set_level(GPIO_EN_USB_C0_CC2_VCONN, !!enabled); } -__override void ocpc_get_pid_constants(int *kp, int *kp_div, - int *ki, int *ki_div, - int *kd, int *kd_div) +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) { *kp = 3; *kp_div = 14; @@ -464,7 +450,7 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Sensor Data */ -static struct kionix_accel_data g_kx022_data; +static struct kionix_accel_data g_kx022_data; static struct lsm6dsm_data lsm6dsm_data = LSM6DSM_DATA; /* Drivers */ @@ -504,8 +490,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = NULL, @@ -533,8 +517,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -548,20 +530,19 @@ const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Thermistors */ const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Memory", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); @@ -585,4 +566,3 @@ void lid_angle_peripheral_enable(int enable) keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); } } -#endif diff --git a/board/waddledee/board.h b/board/waddledee/board.h index 5540fdcbe7..1ac3fc76da 100644 --- a/board/waddledee/board.h +++ b/board/waddledee/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -24,13 +24,16 @@ #define CONFIG_BC12_DETECT_PI3USB9201 /* Charger */ -#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 15000 #define CONFIG_USB_PD_VBUS_DETECT_CHARGER #define CONFIG_USB_PD_5V_CHARGER_CTRL #define CONFIG_CHARGER_OTG -#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_CHARGER_SINGLE_CHIP #define CONFIG_OCPC -#define CONFIG_OCPC_DEF_RBATT_MOHMS 21 /* R_DS(on) 10.7mOhm + 10mOhm sns rstr */ +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 21 /* R_DS(on) 10.7mOhm + 10mOhm sns rstr \ + */ /* * GPIO for C1 interrupts, for baseboard use @@ -47,12 +50,13 @@ #define CONFIG_PWM /* Sensors */ -#define CONFIG_ACCEL_KX022 /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO /* Power of 2 - Too large of a fifo causes too much timestamp jitter */ @@ -70,21 +74,20 @@ /* TCPC */ #define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ -#define CONFIG_USB_PD_TCPM_ANX7447 /* C1: ANX TCPC + Mux */ +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_TCPM_ANX7447 /* C1: ANX TCPC + Mux */ #define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 /* Thermistors */ #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_PP3300_A /* USB Mux and Retimer */ -#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ -#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ -#define CONFIG_USBC_RETIMER_TUSB544 /* C1 Redriver: TUSB544 */ +#define CONFIG_USBC_RETIMER_TUSB544 /* C1 Redriver: TUSB544 */ #ifndef __ASSEMBLER__ @@ -106,27 +109,18 @@ enum pwm_channel { }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; /* ADC channels */ enum adc_channel { - ADC_VSNS_PP3300_A, /* ADC0 */ - ADC_TEMP_SENSOR_1, /* ADC2 */ - ADC_TEMP_SENSOR_2, /* ADC3 */ - ADC_SUB_ANALOG, /* ADC13 */ + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_SUB_ANALOG, /* ADC13 */ ADC_CH_COUNT }; -enum temp_sensor_id { - TEMP_SENSOR_1, - TEMP_SENSOR_2, - TEMP_SENSOR_COUNT -}; +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { @@ -143,8 +137,6 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -int board_is_sourcing_vbus(int port); - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/waddledee/build.mk b/board/waddledee/build.mk index 00e4e0bb5d..9b862c7624 100644 --- a/board/waddledee/build.mk +++ b/board/waddledee/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,5 +11,5 @@ CHIP_FAMILY:=it8320 CHIP_VARIANT:=it8320dx BASEBOARD:=dedede -board-y=board.o led.o usb_pd_policy.o +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/waddledee/cbi_ssfc.c b/board/waddledee/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/waddledee/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/waddledee/cbi_ssfc.h b/board/waddledee/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/waddledee/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/waddledee/ec.tasklist b/board/waddledee/ec.tasklist index 75181a4531..c3c360febb 100644 --- a/board/waddledee/ec.tasklist +++ b/board/waddledee/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,13 +12,13 @@ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, TRENTA_TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, ULTRA_TASK_STACK_SIZE) \ TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/waddledee/gpio.inc b/board/waddledee/gpio.inc index 3ce80593a7..b0c8d8cd03 100644 --- a/board/waddledee/gpio.inc +++ b/board/waddledee/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -37,8 +37,8 @@ GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_cc /* Other interrupts */ GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt) GPIO_INT(LID_360_L, PIN(A, 7), GPIO_INT_BOTH, gmr_tablet_switch_isr) -GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH, button_interrupt) -GPIO_INT(VOLUP_BTN_ODL, PIN(I, 7), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(VOLDN_BTN_ODL, PIN(I, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) +GPIO_INT(VOLUP_BTN_ODL, PIN(I, 7), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) GPIO_INT(BASE_SIXAXIS_INT_L, PIN(J, 0), GPIO_INT_FALLING | GPIO_SEL_1P8V, lsm6dsm_interrupt) GPIO_INT(EC_WP_OD, PIN(A, 6), GPIO_INT_BOTH, switch_interrupt) @@ -100,7 +100,7 @@ GPIO(EC_SUB_IO_2_2, PIN(L, 2), GPIO_INPUT) /* Misc */ GPIO(EN_BL_OD, PIN(K, 4), GPIO_ODR_LOW) GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) -GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_INPUT) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) GPIO(PEN_DET_ODL, PIN(J, 1), GPIO_INPUT | GPIO_PULL_UP) GPIO(EN_KB_BL, PIN(J, 3), GPIO_OUT_LOW) /* Currently unused */ diff --git a/board/waddledee/led.c b/board/waddledee/led.c index b19e594fbd..1a2bc16898 100644 --- a/board/waddledee/led.c +++ b/board/waddledee/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,14 +19,14 @@ const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); /* * Board has one physical LED with red, green, and blue */ -struct pwm_led led_color_map[EC_LED_COLOR_COUNT] = { - /* Red, Green, Blue */ - [EC_LED_COLOR_RED] = { 100, 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, - [EC_LED_COLOR_YELLOW] = { 50, 50, 0 }, - [EC_LED_COLOR_WHITE] = { 50, 50, 50 }, - [EC_LED_COLOR_AMBER] = { 70, 30, 0 }, +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Red, Green, Blue */ + [EC_LED_COLOR_RED] = { 100, 0, 0 }, + [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, + [EC_LED_COLOR_YELLOW] = { 50, 50, 0 }, + [EC_LED_COLOR_WHITE] = { 50, 50, 50 }, + [EC_LED_COLOR_AMBER] = { 70, 30, 0 }, }; /* One logical LED with red, green, and blue channels. */ diff --git a/board/waddledee/usb_pd_policy.c b/board/waddledee/usb_pd_policy.c index 9d53f20047..2433b25431 100644 --- a/board/waddledee/usb_pd_policy.c +++ b/board/waddledee/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,8 +13,8 @@ #include "driver/tcpm/tcpci.h" #include "usb_pd.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -38,11 +38,6 @@ void pd_power_supply_reset(int port) if (prev_en) sm5803_set_vbus_disch(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -62,11 +57,6 @@ int pd_set_power_supply_ready(int port) /* Provide Vbus */ charger_enable_otg_power(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -75,18 +65,7 @@ int pd_set_power_supply_ready(int port) __override bool pd_check_vbus_level(int port, enum vbus_level level) { - int vbus_voltage; - - /* If we're unable to speak to the charger, best to guess false */ - if (charger_get_vbus_voltage(port, &vbus_voltage)) - return false; - - if (level == VBUS_SAFE0V) - return vbus_voltage < PD_V_SAFE0V_MAX; - else if (level == VBUS_PRESENT) - return vbus_voltage > PD_V_SAFE5V_MIN; - else - return vbus_voltage < PD_V_SINK_DISCONNECT_MAX; + return sm5803_check_vbus_level(port, level); } int pd_snk_is_vbus_provided(int port) diff --git a/board/waddledee/vif_override.xml b/board/waddledee/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/waddledee/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/waddledoo/battery.c b/board/waddledoo/battery.c index 64af3b4302..29eac40158 100644 --- a/board/waddledoo/battery.c +++ b/board/waddledoo/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/waddledoo/board.c b/board/waddledoo/board.c index fb5c51a0a6..80234defdf 100644 --- a/board/waddledoo/board.c +++ b/board/waddledoo/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,7 +9,7 @@ #include "button.h" #include "cbi_fw_config.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" #include "common.h" @@ -42,34 +42,81 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) -static void tcpc_alert_event(enum gpio_signal s) -{ - int port = (s == GPIO_USB_C0_INT_ODL) ? 0 : 1; +#define INT_RECHECK_US 5000 - schedule_deferred_pd_interrupt(port); -} +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); -static void usb_c0_interrupt(enum gpio_signal s) +static void notify_c0_chips(void) { /* * The interrupt line is shared between the TCPC and BC 1.2 detection * chip. Therefore we'll need to check both ICs. */ - tcpc_alert_event(s); - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } -static void sub_usb_c1_interrupt(enum gpio_signal s) +static void check_c0_line(void) { /* - * The interrupt line is shared between the TCPC and BC 1.2 detection - * chip. Therefore we'll need to check both ICs. + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. */ - tcpc_alert_event(s); - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + if (!gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void sub_usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); } static void sub_hdmi_hpd_interrupt(enum gpio_signal s) @@ -79,6 +126,7 @@ static void sub_hdmi_hpd_interrupt(enum gpio_signal s) gpio_set_level(GPIO_EC_AP_USB_C1_HDMI_HPD, !hdmi_hpd_odl); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /* ADC channels */ @@ -118,20 +166,23 @@ void board_init(void) { int on; + /* Enable C0 interrupt and check if it needs processing */ gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + check_c0_line(); if (get_cbi_fw_config_db() == DB_1A_HDMI) { /* Disable i2c on HDMI pins */ - gpio_config_pin(MODULE_I2C, - GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, 0); - gpio_config_pin(MODULE_I2C, - GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, 0); + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, + 0); + gpio_config_pin(MODULE_I2C, GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, + 0); /* Set HDMI and sub-rail enables to output */ gpio_set_flags(GPIO_EC_I2C_SUB_C1_SCL_HDMI_EN_ODL, chipset_in_state(CHIPSET_STATE_ON) ? - GPIO_ODR_LOW : GPIO_ODR_HIGH); - gpio_set_flags(GPIO_SUB_C1_INT_EN_RAILS_ODL, GPIO_ODR_HIGH); + GPIO_ODR_LOW : + GPIO_ODR_HIGH); + gpio_set_flags(GPIO_SUB_C1_INT_EN_RAILS_ODL, GPIO_ODR_HIGH); /* Select HDMI option */ gpio_set_level(GPIO_HDMI_SEL_L, 0); @@ -140,17 +191,18 @@ void board_init(void) gpio_enable_interrupt(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL); } else { /* Set SDA as an input */ - gpio_set_flags(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, - GPIO_INPUT); + gpio_set_flags(GPIO_EC_I2C_SUB_C1_SDA_HDMI_HPD_ODL, GPIO_INPUT); - /* Enable C1 interrupts */ + /* Enable C1 interrupt and check if it needs processing */ gpio_enable_interrupt(GPIO_SUB_C1_INT_EN_RAILS_ODL); + check_c1_line(); } /* Enable gpio interrupt for base accelgyro sensor */ gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); /* Turn on 5V if the system is on, otherwise turn it off. */ - on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND); + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); board_power_5v_enable(on); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -177,8 +229,8 @@ void board_hibernate(void) * entering the Z-state. */ if (board_get_charger_chip_count() > 1) - raa489000_hibernate(1); - raa489000_hibernate(0); + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); } void board_reset_pd_mcu(void) @@ -189,38 +241,43 @@ void board_reset_pd_mcu(void) */ } +#ifdef BOARD_WADDLEDOO static void reconfigure_5v_gpio(void) { /* - * b/147257497: On early boards, GPIO_EN_PP5000 was swapped with - * GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that GPIO - * instead for those boards. Note that this breaks the volume up button - * functionality. + * b/147257497: On early waddledoo boards, GPIO_EN_PP5000 was swapped + * with GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that + * GPIO instead for those boards. Note that this breaks the volume up + * button functionality. */ if (system_get_board_version() < 0) { CPRINTS("old board - remapping 5V en"); gpio_set_flags(GPIO_VOLUP_BTN_ODL, GPIO_OUT_LOW); } } -DECLARE_HOOK(HOOK_INIT, reconfigure_5v_gpio, HOOK_PRIO_INIT_I2C+1); +DECLARE_HOOK(HOOK_INIT, reconfigure_5v_gpio, HOOK_PRIO_INIT_I2C + 1); +#endif /* BOARD_WADDLEDOO */ static void set_5v_gpio(int level) { int version; - enum gpio_signal gpio; + enum gpio_signal gpio = GPIO_EN_PP5000; /* - * b/147257497: On early boards, GPIO_EN_PP5000 was swapped with - * GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that GPIO - * instead for those boards. Note that this breaks the volume up button - * functionality. + * b/147257497: On early waddledoo boards, GPIO_EN_PP5000 was swapped + * with GPIO_VOLUP_BTN_ODL. Therefore, we'll actually need to set that + * GPIO instead for those boards. Note that this breaks the volume up + * button functionality. */ - version = system_get_board_version(); + if (IS_ENABLED(BOARD_WADDLEDOO)) { + version = system_get_board_version(); - /* - * If the CBI EEPROM wasn't formatted, assume it's a very early board. - */ - gpio = version < 0 ? GPIO_VOLUP_BTN_ODL : GPIO_EN_PP5000; + /* + * If the CBI EEPROM wasn't formatted, assume it's a very early + * board. + */ + gpio = version < 0 ? GPIO_VOLUP_BTN_ODL : GPIO_EN_PP5000; + } gpio_set_level(gpio, level); } @@ -239,10 +296,9 @@ __override void board_power_5v_enable(int enable) gpio_set_level(GPIO_SUB_C1_INT_EN_RAILS_ODL, !enable); } else { if (isl923x_set_comparator_inversion(1, !!enable)) - CPRINTS("Failed to %sable sub rails!", enable ? - "en" : "dis"); + CPRINTS("Failed to %sable sub rails!", + enable ? "en" : "dis"); } - } __override uint8_t board_get_usb_pd_port_count(void) @@ -267,13 +323,11 @@ int board_is_sourcing_vbus(int port) tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); - } int board_set_active_charge_port(int port) { - int is_real_port = (port >= 0 && - port < board_get_usb_pd_port_count()); + int is_real_port = (port >= 0 && port < board_get_usb_pd_port_count()); int i; int old_port; @@ -286,9 +340,11 @@ int board_set_active_charge_port(int port) /* Disable all ports. */ if (port == CHARGE_PORT_NONE) { - for (i = 0; i < board_get_usb_pd_port_count(); i++) + for (i = 0; i < board_get_usb_pd_port_count(); i++) { tcpc_write(i, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + raa489000_enable_asgate(i, false); + } return EC_SUCCESS; } @@ -310,6 +366,7 @@ int board_set_active_charge_port(int port) if (tcpc_write(i, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW)) CPRINTS("p%d: sink path disable failed.", i); + raa489000_enable_asgate(i, false); } /* @@ -320,7 +377,8 @@ int board_set_active_charge_port(int port) charger_discharge_on_ac(1); /* Enable requested charge port. */ - if (tcpc_write(port, TCPC_REG_COMMAND, + if (raa489000_enable_asgate(port, true) || + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { CPRINTS("p%d: sink path enable failed.", port); charger_discharge_on_ac(0); @@ -333,16 +391,12 @@ int board_set_active_charge_port(int port) return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) { - int icl = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); + if (port < 0 || port > board_get_usb_pd_port_count()) + return; - /* - * TODO(b:147463641): Characterize the input current limit in case that - * a scaling needs to be applied here. - */ - charge_set_input_current_limit(icl, charge_mv); + raa489000_set_output_current(port, rp); } /* Sensors */ @@ -350,17 +404,13 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrices to rotate accelerometers into the standard reference. */ -static const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t lid_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; -static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; static struct accelgyro_saved_data_t g_bma253_data; static struct bmi_drv_data_t g_bmi160_data; @@ -436,29 +486,15 @@ struct motion_sensor_t motion_sensors[] = { const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -__override void ocpc_get_pid_constants(int *kp, int *kp_div, - int *ki, int *ki_div, - int *kd, int *kd_div) +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) { - /* - * Early boards need different constants due to a change in charger IC - * silicon revision. - */ - if (system_get_board_version() >= 0) { - *kp = 1; - *kp_div = 128; - *ki = 1; - *ki_div = 1024; - *kd = 0; - *kd_div = 1; - } else { - *kp = 1; - *kp_div = 4; - *ki = 1; - *ki_div = 15; - *kd = 1; - *kd_div = 10; - } + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; } int pd_snk_is_vbus_provided(int port) @@ -538,25 +574,34 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }, }; -const struct usb_mux usbc1_retimer = { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = NB7V904M_I2C_ADDR0, - .driver = &nb7v904m_usb_redriver_drv, +const struct usb_mux_chain usbc1_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = NB7V904M_I2C_ADDR0, + .driver = &nb7v904m_usb_redriver_drv, + }, }; -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, - .driver = &pi3usb3x532_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, }, { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, - .driver = &pi3usb3x532_usb_mux_driver, - .next_mux = &usbc1_retimer, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + .next = &usbc1_retimer, } }; @@ -582,7 +627,7 @@ uint16_t tcpc_get_alert_status(void) } if (board_get_usb_pd_port_count() > 1 && - !gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { + !gpio_get_level(GPIO_SUB_C1_INT_EN_RAILS_ODL)) { if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { /* TCPCI spec Rev 1.0 says to ignore bits 14:12. */ if (!(tcpc_config[1].flags & TCPC_FLAGS_TCPCI_REV2_0)) @@ -596,9 +641,8 @@ uint16_t tcpc_get_alert_status(void) return status; } -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); @@ -622,4 +666,3 @@ void lid_angle_peripheral_enable(int enable) keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); } } -#endif diff --git a/board/waddledoo/board.h b/board/waddledoo/board.h index 3f788e0392..a53507ecad 100644 --- a/board/waddledoo/board.h +++ b/board/waddledoo/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,20 +17,42 @@ */ #define CONFIG_SYSTEM_UNLOCKED +/* Save some flash space */ +#undef CONFIG_ACCEL_SPOOF_MODE +#define CONFIG_CHIP_INIT_ROM_REGION +#undef CONFIG_CONSOLE_CMDHELP +#undef CONFIG_CONSOLE_HISTORY +#define CONFIG_DEBUG_ASSERT_BRIEF +#define CONFIG_USB_PD_DEBUG_LEVEL 0 + +/* EC console commands */ +#define CONFIG_CMD_CHARGER_DUMP + +/* Remove default commands to free flash space */ +#undef CONFIG_CMD_ACCELSPOOF +#undef CONFIG_CMD_BATTFAKE + /* Battery */ #define CONFIG_BATTERY_FUEL_GAUGE /* Charger */ #define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 #define CONFIG_CHARGER_SENSE_RESISTOR 10 -#define CONFIG_OCPC_DEF_RBATT_MOHMS 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr */ +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 #define CONFIG_OCPC -#undef CONFIG_CHARGER_SINGLE_CHIP - -/* EC console commands */ -#define CONFIG_CMD_TCPC_DUMP -#define CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) /* * GPIO for C1 interrupts, for baseboard use @@ -57,7 +79,7 @@ /* PWM */ #define CONFIG_PWM -#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ /* USB */ #define CONFIG_BC12_DETECT_PI3USB9201 @@ -76,17 +98,26 @@ /* Variant references the TCPCs to determine Vbus sourcing */ #define CONFIG_USB_PD_5V_EN_CUSTOM +#undef PD_POWER_SUPPLY_TURN_ON_DELAY +#undef PD_POWER_SUPPLY_TURN_OFF_DELAY +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +/* 20% margin added for these timings */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 13080 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 16080 /* us */ +#undef CONFIG_USBC_VCONN_SWAP_DELAY_US +#define CONFIG_USBC_VCONN_SWAP_DELAY_US 787 /* us */ + /* I2C configuration */ -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 -#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 #define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* TODO(b:147440290): Need to handle multiple charger ICs */ -#define I2C_PORT_CHARGER I2C_PORT_USB_C0 +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 -#define I2C_PORT_ACCEL I2C_PORT_SENSOR +#define I2C_PORT_ACCEL I2C_PORT_SENSOR #define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ @@ -103,16 +134,15 @@ #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO -#define CONFIG_ACCEL_BMA255 /* Lid accel */ -#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ /* Lid operates in forced mode, base in FIFO */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) #define CONFIG_ACCEL_FIFO -#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ #define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) @@ -125,9 +155,6 @@ #define CONFIG_TABLET_MODE_SWITCH #define CONFIG_GMR_TABLET_MODE -#define CONFIG_MKBP_EVENT -#define CONFIG_MKBP_USE_GPIO - #ifndef __ASSEMBLER__ #include "gpio_signal.h" @@ -140,19 +167,14 @@ enum chg_id { }; enum adc_channel { - ADC_TEMP_SENSOR_1, /* ADC0 */ - ADC_TEMP_SENSOR_2, /* ADC1 */ - ADC_SUB_ANALOG, /* ADC2 */ - ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_VSNS_PP3300_A, /* ADC9 */ ADC_CH_COUNT }; -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; enum pwm_channel { PWM_CH_KBLIGHT, @@ -167,7 +189,5 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -int board_is_sourcing_vbus(int port); - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/waddledoo/build.mk b/board/waddledoo/build.mk index 3cbadc55d7..6f205ebcf4 100644 --- a/board/waddledoo/build.mk +++ b/board/waddledoo/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,4 +11,4 @@ CHIP_FAMILY:=npcx7 CHIP_VARIANT:=npcx7m6fc BASEBOARD:=dedede -board-y=board.o battery.o led.o usb_pd_policy.o +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/waddledoo/cbi_ssfc.c b/board/waddledoo/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/waddledoo/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/waddledoo/cbi_ssfc.h b/board/waddledoo/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/waddledoo/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/waddledoo/ec.tasklist b/board/waddledoo/ec.tasklist index 0aba1fabeb..ba5855412d 100644 --- a/board/waddledoo/ec.tasklist +++ b/board/waddledoo/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/waddledoo/gpio.inc b/board/waddledoo/gpio.inc index e6bc32af1e..6b55d890b2 100644 --- a/board/waddledoo/gpio.inc +++ b/board/waddledoo/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -83,7 +83,7 @@ GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) -GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_INPUT) +GPIO(CCD_MODE_ODL, PIN(E, 5), GPIO_ODR_HIGH) GPIO(USB_C0_RST_ODL, PIN(9, 7), GPIO_OUT_HIGH) /* currently unused */ GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) diff --git a/board/waddledoo/led.c b/board/waddledoo/led.c index ca9a05bd84..4315e0b87d 100644 --- a/board/waddledoo/led.c +++ b/board/waddledoo/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,14 +19,11 @@ const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); * We only have a white and an amber LED, so setting any other colour results in * both LEDs being off. */ -struct pwm_led led_color_map[EC_LED_COLOR_COUNT] = { - /* Amber, White */ - [EC_LED_COLOR_RED] = { 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0 }, - [EC_LED_COLOR_YELLOW] = { 0, 0 }, - [EC_LED_COLOR_WHITE] = { 0, 100 }, - [EC_LED_COLOR_AMBER] = { 100, 0 }, +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Amber, White */ + [EC_LED_COLOR_RED] = { 0, 0 }, [EC_LED_COLOR_GREEN] = { 0, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0 }, [EC_LED_COLOR_YELLOW] = { 0, 0 }, + [EC_LED_COLOR_WHITE] = { 0, 100 }, [EC_LED_COLOR_AMBER] = { 100, 0 }, }; /* One logical LED with amber and white channels. */ diff --git a/board/waddledoo/usb_pd_policy.c b/board/waddledoo/usb_pd_policy.c index 905e049937..23166f7fca 100644 --- a/board/waddledoo/usb_pd_policy.c +++ b/board/waddledoo/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,11 +7,12 @@ #include "chipset.h" #include "common.h" #include "console.h" +#include "driver/charger/isl923x_public.h" #include "driver/tcpm/tcpci.h" #include "usb_pd.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -24,11 +25,6 @@ void pd_power_supply_reset(int port) /* Disable VBUS */ tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -54,10 +50,9 @@ int pd_set_power_supply_ready(int port) if (rv) return rv; -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ + rv = raa489000_enable_asgate(port, true); + if (rv) + return rv; /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/board/waddledoo/vif_override.xml b/board/waddledoo/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/waddledoo/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/waddledoo2/battery.c b/board/waddledoo2/battery.c new file mode 100644 index 0000000000..3696d4e38c --- /dev/null +++ b/board/waddledoo2/battery.c @@ -0,0 +1,128 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ +#include "battery.h" +#include "battery_fuel_gauge.h" +#include "common.h" +#include "gpio.h" +#include "util.h" + +/* + * Battery info for Waddledoo2 battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ +const struct board_batt_params board_battery_info[] = { + /* LGC AP18C8K Battery Information */ + [BATTERY_LGC_AP18C8K] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G020", + .device_name = "AP18C8K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + }, + }, + .batt_info = { + .voltage_max = 13050, + .voltage_normal = 11250, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* Murata AP18C4K Battery Information */ + [BATTERY_MURATA_AP18C4K] = { + .fuel_gauge = { + .manuf_name = "Murata KT00304012", + .device_name = "AP18C4K", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x0, + .reg_mask = 0x2000, + .disconnect_val = 0x2000, + .cfet_mask = 0x4000, + .cfet_off_val = 0x4000, + }, + }, + .batt_info = { + .voltage_max = 13200, + .voltage_normal = 11400, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, + /* AP19B8M */ + [BATTERY_AP19B8M] = { + .fuel_gauge = { + .manuf_name = "LGC KT0030G024", + .ship_mode = { + .reg_addr = 0x3A, + .reg_data = { 0xC574, 0xC574 }, + }, + .fet = { + .reg_addr = 0x43, + .reg_mask = 0x0001, + .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0000, + } + }, + .batt_info = { + .voltage_max = 13350, + .voltage_normal = 11610, + .voltage_min = 9000, + .precharge_current = 256, + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC_AP18C8K; diff --git a/board/waddledoo2/board.c b/board/waddledoo2/board.c new file mode 100644 index 0000000000..8a7a2b461d --- /dev/null +++ b/board/waddledoo2/board.c @@ -0,0 +1,843 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo2 board-specific configuration */ + +#include "adc.h" +#include "button.h" +#include "cbi_fw_config.h" +#include "cbi_ssfc.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "compile_time_macros.h" +#include "driver/accel_bma2x2.h" +#include "driver/accel_kionix.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/bc12/pi3usb9201.h" +#include "driver/charger/isl923x.h" +#include "driver/retimer/ps8802.h" +#include "driver/tcpm/raa489000.h" +#include "driver/tcpm/tcpci.h" +#include "driver/temp_sensor/thermistor.h" +#include "driver/usb_mux/pi3usb3x532.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "keyboard_config.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "motion_sense.h" +#include "power.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "stdbool.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "temp_sensor.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define INT_RECHECK_US 5000 + +#define ADC_VOL_UP_MASK BIT(0) +#define ADC_VOL_DOWN_MASK BIT(1) + +static uint8_t new_adc_key_state; + +static void ps8762_chaddr_deferred(void); +DECLARE_DEFERRED(ps8762_chaddr_deferred); + +/******************************************************************************/ +/* USB-A Configuration */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_USB_A0_VBUS, + GPIO_EN_USB_A1_VBUS, +}; + +/* Keyboard scan setting */ +__override struct keyboard_scan_config keyscan_config = { + /* + * F3 key scan cycle completed but scan input is not + * charging to logic high when EC start scan next + * column for "T" key, so we set .output_settle_us + * to 80us from 50us. + */ + .output_settle_us = 80, + .debounce_down_us = 9 * MSEC, + .debounce_up_us = 30 * MSEC, + .scan_period_us = 3 * MSEC, + .min_post_scan_delay_us = 1000, + .poll_timeout_us = 100 * MSEC, + .actual_key_mask = { + 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, + 0xa4, 0xff, 0xfe, 0x55, 0xfe, 0xff, 0xff, 0xff, /* full set */ + }, +}; + +static const struct ec_response_keybd_config waddledoo2_keybd = { + /* Default Chromeos keyboard config */ + .num_top_row_keys = 10, + .action_keys = { + TK_BACK, /* T1 */ + TK_FORWARD, /* T2 */ + TK_REFRESH, /* T3 */ + TK_FULLSCREEN, /* T4 */ + TK_OVERVIEW, /* T5 */ + TK_BRIGHTNESS_DOWN, /* T6 */ + TK_BRIGHTNESS_UP, /* T7 */ + TK_VOL_MUTE, /* T8 */ + TK_VOL_DOWN, /* T9 */ + TK_VOL_UP, /* T10 */ + }, + /* No function keys, no numeric keypad, has screenlock key */ + .capabilities = KEYBD_CAP_SCRNLOCK_KEY, +}; + +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) +{ + return &waddledoo2_keybd; +} + +/* C0 interrupt line shared by BC 1.2 and charger */ +static void check_c0_line(void); +DECLARE_DEFERRED(check_c0_line); + +static void notify_c0_chips(void) +{ + /* + * The interrupt line is shared between the TCPC and BC 1.2 detection + * chip. Therefore we'll need to check both ICs. + */ + schedule_deferred_pd_interrupt(0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void check_c0_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + notify_c0_chips(); + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); + } +} + +static void usb_c0_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c0_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c0_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c0_line_data, INT_RECHECK_US); +} + +/* C1 interrupt line shared by BC 1.2, TCPC, and charger */ +static void check_c1_line(void); +DECLARE_DEFERRED(check_c1_line); + +static void notify_c1_chips(void) +{ + schedule_deferred_pd_interrupt(1); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void check_c1_line(void) +{ + /* + * If line is still being held low, see if there's more to process from + * one of the chips. + */ + if (!gpio_get_level(GPIO_SUB_USB_C1_INT_ODL)) { + notify_c1_chips(); + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); + } +} + +static void sub_usb_c1_interrupt(enum gpio_signal s) +{ + /* Cancel any previous calls to check the interrupt line */ + hook_call_deferred(&check_c1_line_data, -1); + + /* Notify all chips using this line that an interrupt came in */ + notify_c1_chips(); + + /* Check the line again in 5ms */ + hook_call_deferred(&check_c1_line_data, INT_RECHECK_US); +} + +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + [ADC_TEMP_SENSOR_1] = { + .name = "TEMP_SENSOR1", + .input_ch = NPCX_ADC_CH0, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_TEMP_SENSOR_2] = { + .name = "TEMP_SENSOR2", + .input_ch = NPCX_ADC_CH1, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_SUB_ANALOG] = { + .name = "SUB_ANALOG", + .input_ch = NPCX_ADC_CH2, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, + [ADC_VSNS_PP3300_A] = { + .name = "PP3300_A_PGOOD", + .input_ch = NPCX_ADC_CH9, + .factor_mul = ADC_MAX_VOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* Thermistors */ +const struct temp_sensor_t temp_sensors[] = { + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, +}; +BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_A \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_a = THERMAL_A; + +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_B \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(85), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_WARN] = 0, \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HALT] = 0, \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_b = THERMAL_B; + +struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; + +static void setup_thermal(void) +{ + thermal_params[TEMP_SENSOR_1] = thermal_a; + thermal_params[TEMP_SENSOR_2] = thermal_b; +} + +void board_hibernate(void) +{ + /* + * Both charger ICs need to be put into their "low power mode" before + * entering the Z-state. + */ + raa489000_hibernate(1, true); + raa489000_hibernate(0, true); +} + +void board_reset_pd_mcu(void) +{ + /* + * TODO(b:147316511): Here we could issue a digital reset to the IC, + * unsure if we actually want to do that or not yet. + */ +} + +static void ps8762_chaddr_deferred(void) +{ + /* Switch PS8762 I2C Address to 0x50*/ + if (ps8802_chg_i2c_addr(I2C_PORT_SUB_USB_C1) == EC_SUCCESS) + CPRINTS("Switch PS8762 address to 0x50 success"); + else + CPRINTS("Switch PS8762 address to 0x50 failed"); +} + +__override void board_power_5v_enable(int enable) +{ + /* + * Port 0 simply has a GPIO to turn on the 5V regulator, however, 5V is + * generated locally on the sub board and we need to set the comparator + * polarity on the sub board charger IC. + */ + gpio_set_level(GPIO_EN_PP5000, !!enable); + if (isl923x_set_comparator_inversion(1, !!enable)) + CPRINTS("Failed to %sable sub rails!", enable ? "en" : "dis"); + + if (!enable) + return; + /* + * Port C1 the PP3300_USB_C1 assert, delay 15ms + * colud be accessed PS8762 by I2C. + */ + hook_call_deferred(&ps8762_chaddr_deferred_data, 15 * MSEC); +} + +int board_is_sourcing_vbus(int port) +{ + int regval; + + tcpc_read(port, TCPC_REG_POWER_STATUS, ®val); + return !!(regval & TCPC_REG_POWER_STATUS_SOURCING_VBUS); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + int old_port; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + old_port = charge_manager_get_active_charge_port(); + + CPRINTS("New chg p%d", port); + + /* Disable all ports. */ + if (port == CHARGE_PORT_NONE) { + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW); + + return EC_SUCCESS; + } + + /* Check if port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (tcpc_write(i, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_LOW)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* + * Stop the charger IC from switching while changing ports. Otherwise, + * we can overcurrent the adapter we're switching to. (crbug.com/926056) + */ + if (old_port != CHARGE_PORT_NONE) + charger_discharge_on_ac(1); + + /* Enable requested charge port. */ + if (tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_SNK_CTRL_HIGH)) { + CPRINTS("p%d: sink path enable failed.", port); + charger_discharge_on_ac(0); + return EC_ERROR_UNKNOWN; + } + + /* Allow the charger IC to begin/continue switching. */ + charger_discharge_on_ac(0); + + return EC_SUCCESS; +} + +__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + if (port < 0 || port > board_get_usb_pd_port_count()) + return; + + raa489000_set_output_current(port, rp); +} + +/* Sensors */ +static struct mutex g_lid_mutex; +static struct mutex g_base_mutex; + +/* Matrices to rotate accelerometers into the standard reference. */ +static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +static const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* BMA253 private data */ +static struct accelgyro_saved_data_t g_bma253_data; + +/* BMI160 private data */ +static struct bmi_drv_data_t g_bmi160_data; + +static const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(-1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + +/* ICM426 private data */ +static struct icm_drv_data_t g_icm426xx_data; +/* KX022 private data */ +static struct kionix_accel_data g_kx022_data; + +struct motion_sensor_t kx022_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_KX022, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &kionix_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_kx022_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = KX022_ACCEL_MIN_FREQ, + .max_frequency = KX022_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_ACCEL, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_icm_ref, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 2, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .default_range = 4, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 13000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi160_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; + +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +void board_init(void) +{ + int on; + + gpio_enable_interrupt(GPIO_USB_C0_INT_ODL); + gpio_enable_interrupt(GPIO_SUB_USB_C1_INT_ODL); + check_c0_line(); + check_c1_line(); + + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + if (get_cbi_fw_config_tablet_mode()) { + if (get_cbi_ssfc_base_sensor() == SSFC_SENSOR_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + cprints(CC_SYSTEM, "BASE GYRO is ICM426XX"); + } else + cprints(CC_SYSTEM, "BASE GYRO is BMI160"); + + if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_KX022) { + motion_sensors[LID_ACCEL] = kx022_lid_accel; + cprints(CC_SYSTEM, "LID_ACCEL is KX022"); + } else + cprints(CC_SYSTEM, "LID_ACCEL is BMA253"); + + motion_sensor_count = ARRAY_SIZE(motion_sensors); + /* Enable gpio interrupt for base accelgyro sensor */ + gpio_enable_interrupt(GPIO_BASE_SIXAXIS_INT_L); + } else { + motion_sensor_count = 0; + gmr_tablet_switch_disable(); + /* Base accel is not stuffed, don't allow line to float */ + gpio_set_flags(GPIO_BASE_SIXAXIS_INT_L, + GPIO_INPUT | GPIO_PULL_DOWN); + } + + /* Turn on 5V if the system is on, otherwise turn it off. */ + on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_SOFT_OFF); + board_power_5v_enable(on); + + /* Initialize THERMAL */ + setup_thermal(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (get_cbi_ssfc_base_sensor()) { + case SSFC_SENSOR_ICM426XX: + icm426xx_interrupt(signal); + break; + case SSFC_SENSOR_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +__override void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ + *kp = 1; + *kp_div = 20; + *ki = 1; + *ki_div = 250; + *kd = 0; + *kd_div = 1; +} + +int pd_snk_is_vbus_provided(int port) +{ + return pd_check_vbus_level(port, VBUS_PRESENT); +} + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; +const unsigned int chg_cnt = ARRAY_SIZE(chg_chips); + +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, + + { + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + .flags = PI3USB9201_ALWAYS_POWERED, + }, +}; + +/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + [PWM_CH_KBLIGHT] = { + .channel = 3, + .flags = PWM_CONFIG_DSLEEP, + .freq = 10000, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, + + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_SUB_USB_C1, + .addr_flags = RAA489000_TCPC0_I2C_FLAGS, + }, + .flags = TCPC_FLAGS_TCPCI_REV2_0, + .drv = &raa489000_tcpm_drv, + }, +}; + +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = PI3USB3X532_I2C_ADDR0, + .driver = &pi3usb3x532_usb_mux_driver, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = PS8802_I2C_ADDR_FLAGS_CUSTOM, + .driver = &ps8802_usb_mux_driver, + }, + } +}; + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + int regval; + + /* + * The interrupt line is shared between the TCPC and BC1.2 detector IC. + * Therefore, go out and actually read the alert registers to report the + * alert status. + */ + if (!gpio_get_level(GPIO_USB_C0_INT_ODL)) { + if (!tcpc_read16(0, TCPC_REG_ALERT, ®val)) { + /* The TCPCI Rev 1.0 spec says to ignore bits 14:12. */ + if (!(tcpc_config[0].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_0; + } + } + + if (!gpio_get_level(GPIO_SUB_USB_C1_INT_ODL)) { + if (!tcpc_read16(1, TCPC_REG_ALERT, ®val)) { + /* TCPCI spec Rev 1.0 says to ignore bits 14:12. */ + if (!(tcpc_config[1].flags & TCPC_FLAGS_TCPCI_REV2_0)) + regval &= ~((1 << 14) | (1 << 13) | (1 << 12)); + + if (regval) + status |= PD_STATUS_TCPC_ALERT_1; + } + } + + return status; +} + +int adc_to_physical_value(enum gpio_signal gpio) +{ + if (gpio == GPIO_VOLUME_UP_L) + return !!(new_adc_key_state & ADC_VOL_UP_MASK); + else if (gpio == GPIO_VOLUME_DOWN_L) + return !!(new_adc_key_state & ADC_VOL_DOWN_MASK); + + CPRINTS("Not a volume up or down key"); + return 0; +} + +int button_is_adc_detected(enum gpio_signal gpio) +{ + return (gpio == GPIO_VOLUME_DOWN_L) || (gpio == GPIO_VOLUME_UP_L); +} + +static void adc_vol_key_press_check(void) +{ + int volt = adc_read_channel(ADC_SUB_ANALOG); + static uint8_t old_adc_key_state; + uint8_t adc_key_state_change; + + if (volt > 2400 && volt < 2490) { + /* volume-up is pressed */ + new_adc_key_state = ADC_VOL_UP_MASK; + } else if (volt > 2600 && volt < 2690) { + /* volume-down is pressed */ + new_adc_key_state = ADC_VOL_DOWN_MASK; + } else if (volt < 2290) { + /* both volumn-up and volume-down are pressed */ + new_adc_key_state = ADC_VOL_UP_MASK | ADC_VOL_DOWN_MASK; + } else if (volt > 2700) { + /* both volumn-up and volume-down are released */ + new_adc_key_state = 0; + } + if (new_adc_key_state != old_adc_key_state) { + adc_key_state_change = old_adc_key_state ^ new_adc_key_state; + if (adc_key_state_change & ADC_VOL_UP_MASK) + button_interrupt(GPIO_VOLUME_UP_L); + if (adc_key_state_change & ADC_VOL_DOWN_MASK) + button_interrupt(GPIO_VOLUME_DOWN_L); + + old_adc_key_state = new_adc_key_state; + } +} +DECLARE_HOOK(HOOK_TICK, adc_vol_key_press_check, HOOK_PRIO_DEFAULT); + +/* This callback disables keyboard when convertibles are fully open */ +__override void lid_angle_peripheral_enable(int enable) +{ + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } +} diff --git a/board/waddledoo2/board.h b/board/waddledoo2/board.h new file mode 100644 index 0000000000..428a4cc3fc --- /dev/null +++ b/board/waddledoo2/board.h @@ -0,0 +1,181 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Waddledoo2 board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#define VARIANT_KEEBY_EC_NPCX797FC +#include "baseboard.h" + +/* + * The RAM and flash size combination on the the NPCX797FC does not leave + * any unused flash space that can be used to store the .init_rom section. + */ +#undef CONFIG_CHIP_INIT_ROM_REGION + +/* Battery */ +#define CONFIG_BATTERY_FUEL_GAUGE + +/* Charger */ +#define CONFIG_CHARGER_RAA489000 +#define PD_MAX_VOLTAGE_MV 20000 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_OCPC_DEF_RBATT_MOHMS \ + 22 /* R_DS(on) 11.6mOhm + 10mOhm sns rstr \ + */ +/* + * b/147463641: The charger IC seems to overdraw ~4%, therefore we + * reduce our target accordingly. + */ +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 4 +#define CONFIG_OCPC +#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_CMD_CHARGER_DUMP +#undef CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#define CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE (100 * MSEC) + +/* GPIO for C1 interrupts, for baseboard use */ +#define GPIO_USB_C1_INT_ODL GPIO_SUB_USB_C1_INT_ODL + +/* Keyboard */ + +#define CONFIG_KEYBOARD_KEYPAD +#define CONFIG_PWM_KBLIGHT + +/* LED defines */ +#define CONFIG_LED_ONOFF_STATES + +/* PWM */ +#define CONFIG_PWM +#define NPCX7_PWM1_SEL 1 /* GPIO C2 is used as PWM1. */ + +/* Temp sensor */ +#define CONFIG_TEMP_SENSOR +#define CONFIG_THROTTLE_AP +#define CONFIG_THERMISTOR_NCP15WB +#define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B + +/* USB */ +#define CONFIG_BC12_DETECT_PI3USB9201 +#define CONFIG_USBC_RETIMER_PS8802 + +/* Common USB-A defines */ +#define USB_PORT_COUNT 2 +#define CONFIG_USB_PORT_POWER_SMART +#define CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY +#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_CDP +#define CONFIG_USB_PORT_POWER_SMART_INVERTED +#define GPIO_USB1_ILIM_SEL GPIO_USB_A0_CHARGE_EN_L +#define GPIO_USB2_ILIM_SEL GPIO_USB_A1_CHARGE_EN_L + +/******************************************************************************/ + +/* USB PD */ +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 +#define CONFIG_USB_PD_TCPM_RAA489000 + +/* USB defines specific to external TCPCs */ +#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_DISCHARGE_TCPC +#define CONFIG_USB_PD_TCPC_LOW_POWER + +/* Variant references the TCPCs to determine Vbus sourcing */ +#define CONFIG_USB_PD_5V_EN_CUSTOM + +/* I2C configuration */ +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_BATTERY NPCX_I2C_PORT5_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_SUB_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 +/* TODO(b:147440290): Need to handle multiple charger ICs */ +#define I2C_PORT_CHARGER I2C_PORT_USB_C0 + +#define I2C_PORT_ACCEL I2C_PORT_SENSOR + +#define I2C_ADDR_EEPROM_FLAGS 0x50 /* 7b address */ + +/* Sensors */ +#define CONFIG_CMD_ACCELS +#define CONFIG_CMD_ACCEL_INFO +#define CONFIG_DYNAMIC_MOTION_SENSOR_COUNT + +#define CONFIG_ACCEL_BMA255 /* Lid accel */ +#define CONFIG_ACCELGYRO_BMI160 /* Base accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_ICM426XX /* Base accel second source*/ + +/* Lid operates in forced mode, base in FIFO */ +#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) +#define CONFIG_ACCEL_FIFO +#define CONFIG_ACCEL_FIFO_SIZE 256 /* Must be a power of 2 */ +#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3) + +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) + +#define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE +#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL +#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL + +#define CONFIG_TABLET_MODE +#define CONFIG_TABLET_MODE_SWITCH +#define CONFIG_GMR_TABLET_MODE + +/* Volume Button feature */ +#define CONFIG_ADC_BUTTONS +#define CONFIG_VOLUME_BUTTONS +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum chg_id { + CHARGER_PRIMARY, + CHARGER_SECONDARY, + CHARGER_NUM, +}; + +enum adc_channel { + ADC_TEMP_SENSOR_1, /* ADC0 */ + ADC_TEMP_SENSOR_2, /* ADC1 */ + ADC_SUB_ANALOG, /* ADC2 */ + ADC_VSNS_PP3300_A, /* ADC9 */ + ADC_CH_COUNT +}; + +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; + +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; + +enum pwm_channel { + PWM_CH_KBLIGHT, + PWM_CH_COUNT, +}; + +enum battery_type { + BATTERY_AP19B8M, + BATTERY_LGC_AP18C8K, + BATTERY_MURATA_AP18C4K, + BATTERY_TYPE_COUNT, +}; + +int board_is_sourcing_vbus(int port); +void motion_interrupt(enum gpio_signal signal); +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/waddledoo2/build.mk b/board/waddledoo2/build.mk new file mode 100644 index 0000000000..eb422dae93 --- /dev/null +++ b/board/waddledoo2/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m7fc +BASEBOARD:=keeby + +board-y=board.o battery.o cbi_ssfc.o led.o usb_pd_policy.o diff --git a/board/waddledoo2/cbi_ssfc.c b/board/waddledoo2/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/waddledoo2/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/waddledoo2/cbi_ssfc.h b/board/waddledoo2/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/waddledoo2/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/waddledoo2/ec.tasklist b/board/waddledoo2/ec.tasklist new file mode 100644 index 0000000000..29666dd959 --- /dev/null +++ b/board/waddledoo2/ec.tasklist @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/waddledoo2/gpio.inc b/board/waddledoo2/gpio.inc new file mode 100644 index 0000000000..f2a95f9762 --- /dev/null +++ b/board/waddledoo2/gpio.inc @@ -0,0 +1,145 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. + */ + +/* Power Interrupts */ +GPIO_INT(SLP_S0_L, PIN(D, 5), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_S3_L, PIN(A, 5), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(SLP_S4_L, PIN(D, 4), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(SLP_SUS_L, PIN(D, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(RSMRST_PWRGD_L, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID1, PIN(C, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(CPU_C10_GATE_L, PIN(6, 7), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(VCCIN_AUX_VID0, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, power_signal_interrupt) +GPIO_INT(PG_VCCIO_EXT_OD, PIN(B, 0), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP5000_U_OD, PIN(E, 2), GPIO_INT_BOTH, power_signal_interrupt) +GPIO_INT(PG_DRAM_OD, PIN(E, 4), GPIO_INT_BOTH, baseboard_all_sys_pgood_interrupt) +GPIO_INT(PG_PP1050_ST_OD, PIN(4, 2), GPIO_INT_BOTH, power_signal_interrupt) + +/* USB-C interrupts */ +GPIO_INT(USB_C0_INT_ODL, PIN(6, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) +GPIO_INT(SUB_USB_C1_INT_ODL, PIN(F, 5), GPIO_INT_FALLING | GPIO_PULL_UP, sub_usb_c1_interrupt) + +/* Button interrupts */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) + +/* Other interrupts */ +GPIO_INT(LID_OPEN, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) +GPIO_INT(EC_WP_OD, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) +GPIO_INT(BASE_SIXAXIS_INT_L, PIN(5, 6), GPIO_INT_FALLING | GPIO_SEL_1P8V, motion_interrupt) +GPIO_INT(LID_360_L, PIN(9, 5), GPIO_INT_BOTH, gmr_tablet_switch_isr) + +/* I2C Ports */ +GPIO(EC_I2C_EEPROM_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(B, 2), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_BATTERY_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_SUB_USB_C1_SDA, PIN(9, 1), GPIO_INPUT) + +/* Extra Sub-board I/O pins */ + +GPIO(EC_SUB_IO_2, PIN(3, 4), GPIO_OUT_LOW) + +/* Misc Enables */ +GPIO(EN_VCCIO_EXT, PIN(6, 1), GPIO_OUT_LOW) +/* TODO(b:149775160) - Modify if needed if we ever use this signal. */ +GPIO(EN_VCCST, PIN(A, 7), GPIO_INPUT) +GPIO(EN_PP3300_PEN, PIN(6, 3), GPIO_OUT_LOW) +GPIO(EN_PP3300_A, PIN(0, 3), GPIO_OUT_LOW) +GPIO(EN_PP5000_U, PIN(A, 4), GPIO_OUT_LOW) +GPIO(EN_SLP_Z, PIN(8, 3), GPIO_OUT_LOW) +GPIO(EN_KB_BL, PIN(6, 0), GPIO_OUT_LOW) +GPIO(EN_BL_OD, PIN(D, 3), GPIO_ODR_LOW) +GPIO(EC_CBI_WP, PIN(E, 5), GPIO_OUT_LOW) + +/* LED */ +GPIO(LED_B_ODL, PIN(C, 2), GPIO_OUT_HIGH) /* PWM_CH_LED2_BLUE */ +GPIO(LED_G_ODL, PIN(C, 3), GPIO_OUT_HIGH) /* PWM_CH_LED1_GREEN */ +GPIO(LED_R_ODL, PIN(C, 4), GPIO_OUT_HIGH) /* PWM_CH_LED2_ORANGE */ + +/* Power Sequencing */ +GPIO(EC_AP_PSYS, PIN(B, 7), GPIO_OUT_LOW) +GPIO(EC_AP_RSMRST_L, PIN(A, 6), GPIO_OUT_LOW) +GPIO(EC_AP_PWR_BTN_ODL, PIN(C, 1), GPIO_ODR_HIGH) +GPIO(EC_AP_RTCRST, PIN(7, 6), GPIO_OUT_LOW) +GPIO(EC_AP_WAKE_ODL, PIN(7, 4), GPIO_ODR_HIGH) +GPIO(EC_AP_DPWROK, PIN(A, 3), GPIO_OUT_LOW) +GPIO(EC_AP_PCH_PWROK_OD, PIN(9, 4), GPIO_ODR_LOW) +GPIO(EC_AP_VCCST_PWRGD_OD, PIN(B, 1), GPIO_ODR_LOW) +GPIO(EC_AP_SYS_PWROK, PIN(0, 2), GPIO_OUT_LOW) +GPIO(EC_AP_MKBP_INT_L, PIN(7, 0), GPIO_ODR_HIGH) +GPIO(EC_PROCHOT_ODL, PIN(F, 1), GPIO_ODR_HIGH | GPIO_SEL_1P8V) +GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) +GPIO(ALL_SYS_PWRGD, PIN(A, 0), GPIO_OUT_LOW) +GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + +/* USB pins */ +GPIO(EC_AP_USB_C1_HDMI_HPD, PIN(9, 6), GPIO_OUT_LOW) +GPIO(EC_AP_USB_C0_HPD, PIN(9, 3), GPIO_OUT_LOW) +GPIO(HDMI_SEL_L, PIN(7, 2), GPIO_OUT_HIGH) +GPIO(EC_BATTERY_PRES_ODL, PIN(E, 1), GPIO_INPUT) +GPIO(USB_A0_CHARGE_EN_L, PIN(3, 7), GPIO_OUT_HIGH) /* Enable A0 1.5A Charging */ +GPIO(USB_A1_CHARGE_EN_L, PIN(F, 3), GPIO_OUT_HIGH) /* Enable A1 1.5A Charging */ +GPIO(EN_USB_A0_VBUS, PIN(4, 1), GPIO_OUT_LOW) /* Enable A1 5V Charging */ +GPIO(EN_USB_A1_VBUS, PIN(F, 2), GPIO_OUT_LOW) /* Enable A1 5V Charging */ +/* + * Waddledoo2 doesn't have these physical pins coming to the EC but uses other + * logic. + */ +UNIMPLEMENTED(AC_PRESENT) +UNIMPLEMENTED(PG_EC_DSW_PWROK) +UNIMPLEMENTED(PG_EC_ALL_SYS_PWRGD) +UNIMPLEMENTED(VOLDN_BTN_ODL) +UNIMPLEMENTED(VOLUP_BTN_ODL) + +/* Alternate Functions */ +/* ADC */ +ALTERNATE(PIN_MASK(F, BIT(0)), 0, MODULE_ADC, 0) /* ADC9 */ +ALTERNATE(PIN_MASK(4, 0x38), 0, MODULE_ADC, 0) /* ADC0-2 */ + +/* Keyboard */ +ALTERNATE(PIN_MASK(3, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI0, KSI1 */ +ALTERNATE(PIN_MASK(2, 0xFC), 0, MODULE_KEYBOARD_SCAN, GPIO_INPUT | GPIO_PULL_UP) /* KSI2-7 */ +ALTERNATE(PIN_MASK(2, 0x03), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO0, KSO1 */ +ALTERNATE(PIN_MASK(1, 0x7F), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO3-9 */ +ALTERNATE(PIN_MASK(0, 0xF0), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO10-13 */ +ALTERNATE(PIN_MASK(8, 0x04), 0, MODULE_KEYBOARD_SCAN, GPIO_ODR_HIGH) /* KSO14 */ +GPIO(EC_KSO_02_INV, PIN(1, 7), GPIO_OUT_LOW) /* KSO2 inverted */ + +/* PWM */ +ALTERNATE(PIN_MASK(8, BIT(0)), 0, MODULE_PWM, 0) /* PWM3 */ + +/* UART */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART1 */ + +/* I2C */ +ALTERNATE(PIN_MASK(B, 0x3C), 0, MODULE_I2C, 0) /* I2C7,I2C0 */ +ALTERNATE(PIN_MASK(3, 0x48), 0, MODULE_I2C, 0) /* I2C5 */ +ALTERNATE(PIN_MASK(9, 0x07), 0, MODULE_I2C, 0) /* I2C2, I2C1 SCL */ +ALTERNATE(PIN_MASK(8, 0x80), 0, MODULE_I2C, 0) /* I2C1 SDA */ + +/* NC pins, enable internal pull-up to avoid floating state. */ +GPIO(GPIO32_NC, PIN(3, 2), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO35_NC, PIN(3, 5), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO57_NC, PIN(5, 7), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO81_NC, PIN(8, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO86_NC, PIN(8, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOC0_NC, PIN(C, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD0_NC, PIN(D, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD1_NC, PIN(D, 1), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOD6_NC, PIN(D, 6), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIOE0_NC, PIN(E, 0), GPIO_INPUT | GPIO_PULL_UP) +GPIO(GPIO40_NC, PIN(4, 0), GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/waddledoo2/led.c b/board/waddledoo2/led.c new file mode 100644 index 0000000000..9ef613e483 --- /dev/null +++ b/board/waddledoo2/led.c @@ -0,0 +1,84 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control for waddledoo2 + */ + +#include "chipset.h" +#include "ec_commands.h" +#include "gpio.h" +#include "led_common.h" +#include "led_onoff_states.h" + +#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 + +__override const int led_charge_lvl_1 = 5; + +__override const int led_charge_lvl_2 = 95; + +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; + +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +__override void led_set_color_battery(enum ec_led_colors color) +{ + switch (color) { + case EC_LED_COLOR_AMBER: + gpio_set_level(GPIO_LED_R_ODL, LED_ON_LVL); + gpio_set_level(GPIO_LED_B_ODL, LED_OFF_LVL); + break; + case EC_LED_COLOR_BLUE: + gpio_set_level(GPIO_LED_R_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_B_ODL, LED_ON_LVL); + break; + default: /* LED_OFF and other unsupported colors */ + gpio_set_level(GPIO_LED_R_ODL, LED_OFF_LVL); + gpio_set_level(GPIO_LED_B_ODL, LED_OFF_LVL); + break; + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + brightness_range[EC_LED_COLOR_AMBER] = 1; + brightness_range[EC_LED_COLOR_BLUE] = 1; + } +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (led_id == EC_LED_ID_BATTERY_LED) { + if (brightness[EC_LED_COLOR_BLUE] != 0) + led_set_color_battery(EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color_battery(EC_LED_COLOR_AMBER); + else + led_set_color_battery(LED_OFF); + } + return EC_SUCCESS; +} diff --git a/board/waddledoo2/usb_pd_policy.c b/board/waddledoo2/usb_pd_policy.c new file mode 100644 index 0000000000..3410726e87 --- /dev/null +++ b/board/waddledoo2/usb_pd_policy.c @@ -0,0 +1,56 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "charge_manager.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "driver/tcpm/tcpci.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +int pd_check_vconn_swap(int port) +{ + /* Allow VCONN swaps if the AP is on. */ + return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON); +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_LOW); + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return EC_ERROR_INVAL; + + /* Disable charging. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SNK_CTRL_LOW); + if (rv) + return rv; + + /* Our policy is not to source VBUS when the AP is off. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_NOT_POWERED; + + /* Provide Vbus. */ + rv = tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_SRC_CTRL_HIGH); + if (rv) + return rv; + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} diff --git a/board/waddledoo2/vif_override.xml b/board/waddledoo2/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/waddledoo2/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/wheelie/battery.c b/board/wheelie/battery.c index c9770124cd..bc2c5bec4d 100644 --- a/board/wheelie/battery.c +++ b/board/wheelie/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -277,6 +277,8 @@ const struct board_batt_params board_battery_info[] = { .reg_addr = 0x43, .reg_mask = 0x0001, .disconnect_val = 0x0, + .cfet_mask = 0x0002, + .cfet_off_val = 0x0, }, }, .batt_info = { diff --git a/board/wheelie/board.c b/board/wheelie/board.c index ab1cb03942..f2acbb4efa 100644 --- a/board/wheelie/board.c +++ b/board/wheelie/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,17 +8,17 @@ #include "adc_chip.h" #include "button.h" #include "charge_manager.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "driver/accel_lis2dh.h" #include "driver/accelgyro_lsm6dsm.h" #include "driver/bc12/pi3usb9201.h" #include "driver/charger/sm5803.h" -#include "driver/sync.h" #include "driver/retimer/tusb544.h" -#include "driver/temp_sensor/thermistor.h" +#include "driver/sync.h" #include "driver/tcpm/anx7447.h" #include "driver/tcpm/it83xx_pd.h" +#include "driver/temp_sensor/thermistor.h" #include "driver/usb_mux/it5205.h" #include "gpio.h" #include "hooks.h" @@ -32,7 +32,7 @@ #include "switch.h" #include "tablet_mode.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" #include "uart.h" #include "usb_charge.h" @@ -40,12 +40,12 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" -#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) /* C0 interrupt line shared by BC 1.2 and charger */ static void usb_c0_interrupt(enum gpio_signal s) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); sm5803_interrupt(0); } @@ -53,7 +53,7 @@ static void usb_c0_interrupt(enum gpio_signal s) static void usb_c1_interrupt(enum gpio_signal s) { schedule_deferred_pd_interrupt(1); - task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); sm5803_interrupt(1); } @@ -68,34 +68,26 @@ static void c0_ccsbu_ovp_interrupt(enum gpio_signal s) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_VSNS_PP3300_A] = { - .name = "PP3300_A_PGOOD", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH0 - }, - [ADC_TEMP_SENSOR_1] = { - .name = "TEMP_SENSOR1", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH2 - }, - [ADC_TEMP_SENSOR_2] = { - .name = "TEMP_SENSOR2", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH3 - }, - [ADC_SUB_ANALOG] = { - .name = "SUB_ANALOG", - .factor_mul = ADC_MAX_MVOLT, - .factor_div = ADC_READ_MAX + 1, - .shift = 0, - .channel = CHIP_ADC_CH13 - }, + [ADC_VSNS_PP3300_A] = { .name = "PP3300_A_PGOOD", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH0 }, + [ADC_TEMP_SENSOR_1] = { .name = "TEMP_SENSOR1", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH2 }, + [ADC_TEMP_SENSOR_2] = { .name = "TEMP_SENSOR2", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH3 }, + [ADC_SUB_ANALOG] = { .name = "SUB_ANALOG", + .factor_mul = ADC_MAX_MVOLT, + .factor_div = ADC_READ_MAX + 1, + .shift = 0, + .channel = CHIP_ADC_CH13 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); @@ -143,27 +135,36 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { }; /* USB Retimer */ -const struct usb_mux usbc1_retimer = { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = TUSB544_I2C_ADDR_FLAGS0, - .driver = &tusb544_drv, +const struct usb_mux_chain usbc1_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = TUSB544_I2C_ADDR_FLAGS0, + .driver = &tusb544_drv, + }, }; /* USB Muxes */ -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_C0, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + }, }, { - .usb_port = 1, - .i2c_port = I2C_PORT_SUB_USB_C1, - .i2c_addr_flags = AN7447_TCPC0_I2C_ADDR_FLAGS, - .driver = &anx7447_usb_mux_driver, - .next_mux = &usbc1_retimer, + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .i2c_port = I2C_PORT_SUB_USB_C1, + .i2c_addr_flags = AN7447_TCPC0_I2C_ADDR_FLAGS, + .driver = &anx7447_usb_mux_driver, + }, + .next = &usbc1_retimer, }, }; @@ -228,18 +229,6 @@ uint16_t tcpc_get_alert_status(void) return status; } -void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma, - int charge_mv) -{ - int icl = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); - - /* - * TODO(b/151955431): Characterize the input current limit in case a - * scaling needs to be applied here - */ - charge_set_input_current_limit(icl, charge_mv); -} - int board_set_active_charge_port(int port) { int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); @@ -394,8 +383,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = NULL, @@ -423,8 +410,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -449,20 +434,19 @@ const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); /* Thermistors */ const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_1] = {.name = "Memory", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_1}, - [TEMP_SENSOR_2] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_2}, + [TEMP_SENSOR_1] = { .name = "Memory", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_1 }, + [TEMP_SENSOR_2] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_2 }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -#ifndef TEST_BUILD /* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) +__override void lid_angle_peripheral_enable(int enable) { int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); @@ -486,4 +470,3 @@ void lid_angle_peripheral_enable(int enable) keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); } } -#endif diff --git a/board/wheelie/board.h b/board/wheelie/board.h index 7c680545c0..c53f22b512 100644 --- a/board/wheelie/board.h +++ b/board/wheelie/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,12 +22,13 @@ #define CONFIG_BC12_DETECT_PI3USB9201 /* Charger */ -#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ -#define CONFIG_FPU /* For charger calculations */ +#define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */ +#define PD_MAX_VOLTAGE_MV 15000 +#define CONFIG_FPU /* For charger calculations */ #define CONFIG_USB_PD_VBUS_DETECT_CHARGER #define CONFIG_USB_PD_5V_CHARGER_CTRL #define CONFIG_CHARGER_OTG -#undef CONFIG_CHARGER_SINGLE_CHIP +#undef CONFIG_CHARGER_SINGLE_CHIP /* LED */ #define CONFIG_LED_PWM @@ -37,13 +38,14 @@ #define CONFIG_PWM /* Sensors */ -#define CONFIG_ACCEL_LIS2DE /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ -#define CONFIG_SYNC /* Camera VSYNC */ +#define CONFIG_ACCEL_LIS2DE /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_SYNC /* Camera VSYNC */ +#define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS /* Enable sensor fifo, must also define the _SIZE and _THRES */ #define CONFIG_ACCEL_FIFO /* Power of 2 - Too large of a fifo causes too much timestamp jitter */ @@ -55,8 +57,7 @@ #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL -#define CONFIG_SYNC_INT_EVENT \ - TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) +#define CONFIG_SYNC_INT_EVENT TASK_EVENT_MOTION_SENSOR_INTERRUPT(VSYNC) #define CONFIG_TABLET_MODE #define CONFIG_TABLET_MODE_SWITCH @@ -64,21 +65,20 @@ /* TCPC */ #define CONFIG_USB_PD_PORT_MAX_COUNT 2 -#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ -#define CONFIG_USB_PD_TCPM_ANX7447 /* C1: ANX TCPC + Mux */ +#define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */ +#define CONFIG_USB_PD_TCPM_ANX7447 /* C1: ANX TCPC + Mux */ #define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 1 /* Thermistors */ #define CONFIG_TEMP_SENSOR #define CONFIG_THERMISTOR #define CONFIG_STEINHART_HART_3V3_51K1_47K_4050B -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_EN_PP3300_A /* USB Mux and Retimer */ -#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ -#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ +#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */ +#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */ -#define CONFIG_USBC_RETIMER_TUSB544 /* C1 Redriver: TUSB544 */ +#define CONFIG_USBC_RETIMER_TUSB544 /* C1 Redriver: TUSB544 */ #ifndef __ASSEMBLER__ @@ -100,28 +100,18 @@ enum pwm_channel { }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - VSYNC, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, VSYNC, SENSOR_COUNT }; /* ADC channels */ enum adc_channel { - ADC_VSNS_PP3300_A, /* ADC0 */ - ADC_TEMP_SENSOR_1, /* ADC2 */ - ADC_TEMP_SENSOR_2, /* ADC3 */ - ADC_SUB_ANALOG, /* ADC13 */ + ADC_VSNS_PP3300_A, /* ADC0 */ + ADC_TEMP_SENSOR_1, /* ADC2 */ + ADC_TEMP_SENSOR_2, /* ADC3 */ + ADC_SUB_ANALOG, /* ADC13 */ ADC_CH_COUNT }; -enum temp_sensor_id { - TEMP_SENSOR_1, - TEMP_SENSOR_2, - TEMP_SENSOR_COUNT -}; +enum temp_sensor_id { TEMP_SENSOR_1, TEMP_SENSOR_2, TEMP_SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { @@ -138,8 +128,6 @@ enum battery_type { BATTERY_TYPE_COUNT, }; -int board_is_sourcing_vbus(int port); - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/wheelie/build.mk b/board/wheelie/build.mk index 00e4e0bb5d..9b862c7624 100644 --- a/board/wheelie/build.mk +++ b/board/wheelie/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,5 +11,5 @@ CHIP_FAMILY:=it8320 CHIP_VARIANT:=it8320dx BASEBOARD:=dedede -board-y=board.o led.o usb_pd_policy.o +board-y=board.o cbi_ssfc.o led.o usb_pd_policy.o board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/wheelie/cbi_ssfc.c b/board/wheelie/cbi_ssfc.c new file mode 100644 index 0000000000..81f3ee0dad --- /dev/null +++ b/board/wheelie/cbi_ssfc.c @@ -0,0 +1,36 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "common.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) + +/* Cache SSFC on init since we don't expect it to change in runtime */ +static union dedede_cbi_ssfc cached_ssfc; +BUILD_ASSERT(sizeof(cached_ssfc) == sizeof(uint32_t)); + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) + /* Default to 0 when CBI isn't populated */ + cached_ssfc.raw_value = 0; + + CPRINTS("Read CBI SSFC : 0x%04X", cached_ssfc.raw_value); +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); + +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void) +{ + return (enum ec_ssfc_base_sensor)cached_ssfc.base_sensor; +} + +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void) +{ + return (enum ec_ssfc_lid_sensor)cached_ssfc.lid_sensor; +} diff --git a/board/wheelie/cbi_ssfc.h b/board/wheelie/cbi_ssfc.h new file mode 100644 index 0000000000..bf8853a43a --- /dev/null +++ b/board/wheelie/cbi_ssfc.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _DEDEDE_CBI_SSFC__H_ +#define _DEDEDE_CBI_SSFC__H_ + +#include "stdint.h" + +/**************************************************************************** + * Dedede CBI Second Source Factory Cache + */ + +/* + * Base Sensor (Bits 0-2) + */ +enum ec_ssfc_base_sensor { + SSFC_SENSOR_BASE_DEFAULT = 0, + SSFC_SENSOR_BMI160 = 1, + SSFC_SENSOR_ICM426XX = 2, + SSFC_SENSOR_LSM6DSM = 3, + SSFC_SENSOR_ICM42607 = 4 +}; + +/* + * Lid Sensor (Bits 3-5) + */ +enum ec_ssfc_lid_sensor { + SSFC_SENSOR_LID_DEFAULT = 0, + SSFC_SENSOR_BMA255 = 1, + SSFC_SENSOR_KX022 = 2, + SSFC_SENSOR_LIS2DWL = 3 +}; + +union dedede_cbi_ssfc { + struct { + uint32_t base_sensor : 3; + uint32_t lid_sensor : 3; + uint32_t reserved_2 : 26; + }; + uint32_t raw_value; +}; + +/** + * Get the Base sensor type from SSFC_CONFIG. + * + * @return the Base sensor board type. + */ +enum ec_ssfc_base_sensor get_cbi_ssfc_base_sensor(void); + +/** + * Get the Lid sensor type from SSFC_CONFIG. + * + * @return the Lid sensor board type. + */ +enum ec_ssfc_lid_sensor get_cbi_ssfc_lid_sensor(void); + +#endif /* _DEDEDE_CBI_SSFC__H_ */ diff --git a/board/wheelie/ec.tasklist b/board/wheelie/ec.tasklist index 75181a4531..701c1fa099 100644 --- a/board/wheelie/ec.tasklist +++ b/board/wheelie/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/wheelie/gpio.inc b/board/wheelie/gpio.inc index ba47baaa86..eb96828e07 100644 --- a/board/wheelie/gpio.inc +++ b/board/wheelie/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -100,7 +100,7 @@ GPIO(EC_SUB_IO_2_2, PIN(L, 2), GPIO_INPUT) /* Misc */ GPIO(EN_BL_OD, PIN(K, 4), GPIO_OUT_LOW) GPIO(EC_ENTERING_RW, PIN(G, 0), GPIO_OUT_LOW) -GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_INPUT) +GPIO(CCD_MODE_ODL, PIN(H, 5), GPIO_ODR_HIGH) GPIO(EC_BATTERY_PRES_ODL, PIN(I, 4), GPIO_INPUT) GPIO(PEN_DET_ODL, PIN(J, 1), GPIO_INPUT | GPIO_PULL_UP) GPIO(EN_KB_BL, PIN(J, 3), GPIO_OUT_LOW) /* Currently unused */ diff --git a/board/wheelie/led.c b/board/wheelie/led.c index 8c65f54568..59518dbe6c 100644 --- a/board/wheelie/led.c +++ b/board/wheelie/led.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,14 +19,14 @@ const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); /* * Board has one physical LED with red, green, and blue */ -struct pwm_led led_color_map[EC_LED_COLOR_COUNT] = { - /* Red, Green, Blue */ - [EC_LED_COLOR_RED] = { 100, 0, 0 }, - [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, - [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, - [EC_LED_COLOR_YELLOW] = { 50, 50, 0 }, - [EC_LED_COLOR_WHITE] = { 50, 50, 50 }, - [EC_LED_COLOR_AMBER] = { 70, 30, 0 }, +struct pwm_led_color_map led_color_map[EC_LED_COLOR_COUNT] = { + /* Red, Green, Blue */ + [EC_LED_COLOR_RED] = { 100, 0, 0 }, + [EC_LED_COLOR_GREEN] = { 0, 100, 0 }, + [EC_LED_COLOR_BLUE] = { 0, 0, 100 }, + [EC_LED_COLOR_YELLOW] = { 50, 50, 0 }, + [EC_LED_COLOR_WHITE] = { 50, 50, 50 }, + [EC_LED_COLOR_AMBER] = { 70, 30, 0 }, }; /* One logical LED with red, green, and blue channels. */ diff --git a/board/wheelie/usb_pd_policy.c b/board/wheelie/usb_pd_policy.c index 1611af23e0..3c7564fa12 100644 --- a/board/wheelie/usb_pd_policy.c +++ b/board/wheelie/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,8 +13,8 @@ #include "driver/tcpm/tcpci.h" #include "usb_pd.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) int pd_check_vconn_swap(int port) { @@ -39,11 +39,6 @@ void pd_power_supply_reset(int port) if (prev_en) sm5803_set_vbus_disch(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Give back the current quota we are no longer using */ - charge_manager_source_port(port, 0); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -63,11 +58,6 @@ int pd_set_power_supply_ready(int port) /* Provide Vbus */ chg_chips[port].drv->enable_otg_power(port, 1); -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Ensure we advertise the proper available current quota */ - charge_manager_source_port(port, 1); -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/board/wheelie/vif_override.xml b/board/wheelie/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/wheelie/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/willow/battery.c b/board/willow/battery.c index cc97838f48..a79785aaf8 100644 --- a/board/willow/battery.c +++ b/board/willow/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/willow/board.c b/board/willow/board.c index 17ccb305e0..7ba0cfb8cc 100644 --- a/board/willow/board.c +++ b/board/willow/board.c @@ -1,10 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "backlight.h" #include "button.h" #include "charge_manager.h" @@ -31,48 +30,62 @@ #include "it8801.h" #include "keyboard_scan.h" #include "lid_switch.h" +#include "panic.h" #include "power.h" #include "power_button.h" #include "registers.h" #include "spi.h" #include "system.h" -#include "tablet_mode.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) static void tcpc_alert_event(enum gpio_signal signal) { schedule_deferred_pd_interrupt(0 /* port */); } +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" /******************************************************************************/ /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { - [ADC_BOARD_ID] = {"BOARD_ID", 3300, 4096, 0, STM32_AIN(10)}, - [ADC_EC_SKU_ID] = {"EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8)}, + [ADC_BOARD_ID] = { "BOARD_ID", 3300, 4096, 0, STM32_AIN(10) }, + [ADC_EC_SKU_ID] = { "EC_SKU_ID", 3300, 4096, 0, STM32_AIN(8) }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"typec", 0, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"other", 1, 400, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + { .name = "typec", + .port = 0, + .kbps = 400, + .scl = GPIO_I2C1_SCL, + .sda = GPIO_I2C1_SDA }, + { .name = "other", + .port = 1, + .kbps = 400, + .scl = GPIO_I2C2_SCL, + .sda = GPIO_I2C2_SDA }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct i2c_port_t i2c_bitbang_ports[] = { - {"battery", 2, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA, .drv = &bitbang_drv}, + { .name = "battery", + .port = 2, + .kbps = 100, + .scl = GPIO_I2C3_SCL, + .sda = GPIO_I2C3_SDA, + .drv = &bitbang_drv }, }; const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); @@ -80,13 +93,13 @@ const unsigned int i2c_bitbang_ports_used = ARRAY_SIZE(i2c_bitbang_ports); /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { - {GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L"}, - {GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD"}, + { GPIO_AP_IN_SLEEP_L, POWER_SIGNAL_ACTIVE_LOW, "AP_IN_S3_L" }, + { GPIO_PMIC_EC_RESETB, POWER_SIGNAL_ACTIVE_HIGH, "PMIC_PWR_GOOD" }, }; BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /* Keyboard scan setting */ -struct keyboard_scan_config keyscan_config = { +__override struct keyboard_scan_config keyscan_config = { /* * TODO(b/133200075): Tune this once we have the final performance * out of the driver and the i2c bus. @@ -105,8 +118,8 @@ struct keyboard_scan_config keyscan_config = { struct ioexpander_config_t ioex_config[CONFIG_IO_EXPANDER_PORT_COUNT] = { [0] = { - .i2c_host_port = I2C_PORT_IO_EXPANDER_IT8801, - .i2c_slave_addr = IT8801_I2C_ADDR, + .i2c_host_port = I2C_PORT_KB_DISCRETE, + .i2c_addr_flags = IT8801_I2C_ADDR1, .drv = &it8801_ioexpander_drv, }, }; @@ -131,15 +144,18 @@ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { .bus_type = EC_BUS_TYPE_I2C, .i2c_info = { .port = I2C_PORT_TCPC0, - .addr_flags = FUSB302_I2C_SLAVE_ADDR_FLAGS, + .addr_flags = FUSB302_I2C_ADDR_FLAGS, }, .drv = &fusb302_tcpm_drv, }, }; -static void board_hpd_status(const struct usb_mux *me, - int hpd_lvl, int hpd_irq) +static void board_hpd_status(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* This driver does not use host command ACKs */ + *ack_required = false; + /* * svdm_dp_attention() did most of the work, we only need to notify * host here. @@ -147,13 +163,16 @@ static void board_hpd_status(const struct usb_mux *me, host_set_single_event(EC_HOST_EVENT_USB_MUX); } -const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { { - .usb_port = 0, - .i2c_port = I2C_PORT_USB_MUX, - .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, - .driver = &it5205_usb_mux_driver, - .hpd_update = &board_hpd_status, + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .i2c_port = I2C_PORT_USB_MUX, + .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS, + .driver = &it5205_usb_mux_driver, + .hpd_update = &board_hpd_status, + }, }, }; @@ -200,7 +219,7 @@ int board_set_active_charge_port(int charge_port) if (board_vbus_source_enabled(charge_port)) return -1; break; - case CHARGE_PORT_NONE: + default: /* * To ensure the fuel gauge (max17055) is always powered * even when battery is disconnected, keep VBAT rail on but @@ -208,22 +227,11 @@ int board_set_active_charge_port(int charge_port) */ charger_set_current(CHARGER_SOLO, 0); break; - default: - panic("Invalid charge port\n"); - break; } return EC_SUCCESS; } -void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - charge_ma = (charge_ma * 95) / 100; - charge_set_input_current_limit(MAX(charge_ma, - CONFIG_CHARGER_INPUT_CURRENT), charge_mv); -} - int board_discharge_on_ac(int enable) { int ret, port; @@ -253,7 +261,7 @@ int pd_snk_is_vbus_provided(int port) void bc12_interrupt(enum gpio_signal signal) { - task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); } #ifndef VARIANT_KUKUI_NO_SENSORS @@ -273,13 +281,12 @@ static void board_spi_enable(void) STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; /* Reinitialize spi peripheral. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 1); + spi_enable(&spi_devices[0], 1); /* Pin mux spi peripheral toward the sensor. */ - gpio_config_module(MODULE_SPI_MASTER, 1); + gpio_config_module(MODULE_SPI_CONTROLLER, 1); } -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, - board_spi_enable, +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_spi_enable, MOTION_SENSE_HOOK_PRIO - 1); static void board_spi_disable(void) @@ -287,14 +294,13 @@ static void board_spi_disable(void) /* Set pins to a state calming the sensor down. */ gpio_set_flags(GPIO_EC_SENSOR_SPI_CK, GPIO_OUT_LOW); gpio_set_level(GPIO_EC_SENSOR_SPI_CK, 0); - gpio_config_module(MODULE_SPI_MASTER, 0); + gpio_config_module(MODULE_SPI_CONTROLLER, 0); /* Disable spi peripheral and clocks. */ - spi_enable(CONFIG_SPI_ACCEL_PORT, 0); + spi_enable(&spi_devices[0], 0); STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - board_spi_disable, +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_spi_disable, MOTION_SENSE_HOOK_PRIO + 1); #endif /* !VARIANT_KUKUI_NO_SENSORS */ @@ -333,11 +339,9 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Rotation matrixes */ -static const mat33_fp_t base_standard_ref = { - {FLOAT_TO_FP(1), 0, 0}, - {0, FLOAT_TO_FP(1), 0}, - {0, 0, FLOAT_TO_FP(1)} -}; +static const mat33_fp_t base_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; @@ -356,7 +360,7 @@ struct motion_sensor_t motion_sensors[] = { .port = I2C_PORT_SENSORS, .i2c_spi_addr_flags = KX022_ADDR1_FLAGS, .rot_standard_ref = NULL, /* Identity matrix. */ - .default_range = 2, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .default_range = 2, /* g, enough to calculate lid angle. */ .config = { /* EC use accel for angle detection */ [SENSOR_CONFIG_EC_S0] = { @@ -383,9 +387,9 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .rot_standard_ref = &base_standard_ref, - .default_range = 2, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, .config = { @@ -411,7 +415,7 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = &g_bmi160_data, .port = CONFIG_SPI_ACCEL_PORT, - .i2c_spi_addr_flags = SLAVE_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), + .i2c_spi_addr_flags = ACCEL_MK_SPI_ADDR_FLAGS(CONFIG_SPI_ACCEL_PORT), .default_range = 1000, /* dps */ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_GYRO_MIN_FREQ, diff --git a/board/willow/board.h b/board/willow/board.h index 7d70a98ca6..1772022395 100644 --- a/board/willow/board.h +++ b/board/willow/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,6 +11,7 @@ #define VARIANT_KUKUI_JACUZZI #define VARIANT_KUKUI_BATTERY_SMART #define VARIANT_KUKUI_CHARGER_ISL9238 +#define VARIANT_KUKUI_EC_STM32F098 #ifndef SECTION_IS_RW #define VARIANT_KUKUI_NO_SENSORS @@ -18,6 +19,9 @@ #include "baseboard.h" +/* Disable deferred (async) flash protect*/ +#undef CONFIG_FLASH_PROTECT_DEFERRED + #undef CONFIG_CHIPSET_POWER_SEQ_VERSION #define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 @@ -26,6 +30,8 @@ #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_CHARGER_PSYS +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 #define CONFIG_CHARGER_RUNTIME_CONFIG @@ -49,15 +55,15 @@ /* Motion Sensors */ #ifndef VARIANT_KUKUI_NO_SENSORS -#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ #define CONFIG_ACCELGYRO_BMI160 /* Base accel */ -#define CONFIG_ACCEL_INTERRUPTS #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ALS #define CONFIG_CMD_ACCEL_INFO #define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE #define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL #define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL @@ -66,28 +72,32 @@ #endif /* VARIANT_KUKUI_NO_SENSORS */ /* I2C ports */ -#define I2C_PORT_BC12 0 -#define I2C_PORT_TCPC0 0 -#define I2C_PORT_USB_MUX 0 -#define I2C_PORT_CHARGER board_get_charger_i2c() -#define I2C_PORT_SENSORS 1 -#define I2C_PORT_IO_EXPANDER_IT8801 1 -#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY -#define I2C_PORT_BATTERY 2 +#define I2C_PORT_BC12 0 +#define I2C_PORT_TCPC0 0 +#define I2C_PORT_USB_MUX 0 +#define I2C_PORT_CHARGER board_get_charger_i2c() +#define I2C_PORT_SENSORS 1 +#define I2C_PORT_KB_DISCRETE 1 +#define I2C_PORT_VIRTUAL_BATTERY I2C_PORT_BATTERY +#define I2C_PORT_BATTERY 2 + +/* IT8801 I2C address */ +#define KB_DISCRETE_I2C_ADDR_FLAGS IT8801_I2C_ADDR1 /* Enable Accel over SPI */ -#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI master port (SPI2) */ +#define CONFIG_SPI_ACCEL_PORT 0 /* The first SPI controller port (SPI2) */ #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_MKBP_EVENT #define CONFIG_MKBP_USE_GPIO -/* Define the MKBP events which are allowed to wakeup AP in S3. */ -#define CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) #define CONFIG_LED_ONOFF_STATES +#undef CONFIG_GMR_TABLET_MODE +#undef GPIO_TABLET_MODE_L +#undef CONFIG_TABLET_MODE +#undef CONFIG_TABLET_MODE_SWITCH + #ifndef __ASSEMBLER__ enum adc_channel { @@ -141,7 +151,6 @@ void emmc_cmd_interrupt(enum gpio_signal signal); void bc12_interrupt(enum gpio_signal signal); void board_reset_pd_mcu(void); int board_get_version(void); -int board_is_sourcing_vbus(int port); /* returns the i2c port number of charger/battery */ int board_get_charger_i2c(void); diff --git a/board/willow/build.mk b/board/willow/build.mk index a6e1c010d7..f583684804 100644 --- a/board/willow/build.mk +++ b/board/willow/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/willow/ec.tasklist b/board/willow/ec.tasklist index c1330b86f8..fb131b8eb4 100644 --- a/board/willow/ec.tasklist +++ b/board/willow/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/willow/gpio.inc b/board/willow/gpio.inc index 1c5db485c8..684e1997c9 100644 --- a/board/willow/gpio.inc +++ b/board/willow/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -37,11 +37,10 @@ GPIO_INT(IT8801_SMB_INT, PIN(A, 8), GPIO_INT_FALLING | GPIO_PULL_UP, io_expander_it8801_interrupt) /* KB_INT_ODL */ GPIO_INT(AP_EC_WATCHDOG_L, PIN(D, 2), GPIO_INT_FALLING, chipset_watchdog_interrupt) -GPIO_INT(TABLET_MODE_L, PIN(B, 11), GPIO_INT_BOTH, - gmr_tablet_switch_isr) /* Unimplemented interrupts */ GPIO(ALS_RGB_INT_ODL, PIN(C, 10), GPIO_INPUT) +GPIO(TABLET_MODE_L, PIN(B, 11), GPIO_INPUT) /* Reset pins */ GPIO(AP_SYS_RST_L, PIN(C, 11), GPIO_OUT_LOW) @@ -117,5 +116,5 @@ ALTERNATE(PIN_MASK(A, 0x8000), 0, MODULE_SPI, 0) /* EMMC SPI SLAVE: PB13/14/15 */ ALTERNATE(PIN_MASK(B, 0xE000), 0, MODULE_SPI_FLASH, 0) /* SENSORS SPI MASTER: PB10, PB12, PC2, PC3 */ -ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_MASTER, 0) -ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_MASTER, 0) +ALTERNATE(PIN_MASK(B, 0x0400), 5, MODULE_SPI_CONTROLLER, 0) +ALTERNATE(PIN_MASK(C, 0x000C), 1, MODULE_SPI_CONTROLLER, 0) diff --git a/board/willow/led.c b/board/willow/led.c index e5b204f934..6e177f15d6 100644 --- a/board/willow/led.c +++ b/board/willow/led.c @@ -1,37 +1,43 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Power and battery LED control for Willow */ #include "common.h" -#include "ioexpander.h" #include "driver/ioexpander/it8801.h" #include "ec_commands.h" +#include "ioexpander.h" #include "led_common.h" #include "led_onoff_states.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; -const int led_charge_lvl_2 = 95; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED -}; +__override const int led_charge_lvl_1 = 5; +__override const int led_charge_lvl_2 = 95; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -77,4 +83,4 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) led_set_color_battery(LED_OFF); } return EC_SUCCESS; -} \ No newline at end of file +} diff --git a/board/willow/vif_override.xml b/board/willow/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/willow/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/woomax/battery.c b/board/woomax/battery.c index bd46c51cc7..0bed2f03f5 100644 --- a/board/woomax/battery.c +++ b/board/woomax/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/woomax/board.c b/board/woomax/board.c index 2a88f43bf4..cf47c10c70 100644 --- a/board/woomax/board.c +++ b/board/woomax/board.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,15 +6,20 @@ /* Trembyle board configuration */ #include "adc.h" -#include "adc_chip.h" #include "button.h" #include "cbi_ec_fw_config.h" -#include "driver/accelgyro_bmi_common.h" +#include "cbi_ssfc.h" +#include "cros_board_info.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm426xx.h" +#include "driver/accelgyro_icm_common.h" #include "driver/retimer/pi3dpx1207.h" #include "driver/retimer/pi3hdx1204.h" +#include "driver/retimer/ps8802.h" #include "driver/retimer/ps8811.h" +#include "driver/retimer/ps8818_public.h" #include "driver/temp_sensor/sb_tsi.h" #include "driver/usb_mux/amd_fp5.h" #include "extpower.h" @@ -33,16 +38,15 @@ #include "tablet_mode.h" #include "task.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_charge.h" #include "usb_mux.h" +/* Must come after other header files and interrupt handler declarations */ #include "gpio_list.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -#ifdef HAS_TASK_MOTIONSENSE +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) /* Motion sensors */ static struct mutex g_lid_mutex; @@ -51,6 +55,7 @@ static struct mutex g_base_mutex; /* sensor private data */ static struct kionix_accel_data g_kx022_data; static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm426xx_data; /* Rotation matrix for the lid accelerometer */ static const mat33_fp_t lid_standard_ref = { @@ -60,12 +65,63 @@ static const mat33_fp_t lid_standard_ref = { }; static const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)}, + { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) }, +}; + +static const mat33_fp_t base_standard_ref_icm = { + { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(-1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) }, }; /* TODO(gcc >= 5.0) Remove the casts to const pointer at rot_standard_ref */ +struct motion_sensor_t icm426xx_base_accel = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs. */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_ACCEL_MIN_FREQ, + .max_frequency = ICM426XX_ACCEL_MAX_FREQ, + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100, + }, + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm426xx_base_gyro = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM426XX, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &icm426xx_drv, + .mutex = &g_base_mutex, + .drv_data = &g_icm426xx_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref_icm, + .min_frequency = ICM426XX_GYRO_MIN_FREQ, + .max_frequency = ICM426XX_GYRO_MAX_FREQ, +}; + struct motion_sensor_t motion_sensors[] = { [LID_ACCEL] = { .name = "Lid Accel", @@ -106,7 +162,7 @@ struct motion_sensor_t motion_sensors[] = { .drv_data = &g_bmi160_data, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, - .default_range = 2, /* g, enough for laptop */ + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_ACCEL_MIN_FREQ, .max_frequency = BMI_ACCEL_MAX_FREQ, @@ -135,7 +191,7 @@ struct motion_sensor_t motion_sensors[] = { .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, .default_range = 1000, /* dps */ - .rot_standard_ref = NULL, + .rot_standard_ref = &base_standard_ref, .min_frequency = BMI_GYRO_MIN_FREQ, .max_frequency = BMI_GYRO_MAX_FREQ, }, @@ -143,7 +199,23 @@ struct motion_sensor_t motion_sensors[] = { unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); -#endif /* HAS_TASK_MOTIONSENSE */ +static void setup_base_gyro_config(void) +{ + if (get_cbi_ssfc_base_sensor() == SSFC_BASE_GYRO_ICM426XX) { + motion_sensors[BASE_ACCEL] = icm426xx_base_accel; + motion_sensors[BASE_GYRO] = icm426xx_base_gyro; + ccprints("BASE GYRO is ICM426XX"); + } else + ccprints("BASE GYRO is BMI160"); +} + +void motion_interrupt(enum gpio_signal signal) +{ + if (get_cbi_ssfc_base_sensor() == SSFC_BASE_GYRO_ICM426XX) + icm426xx_interrupt(signal); + else + bmi160_interrupt(signal); +} const struct power_signal_info power_signal_list[] = { [X86_SLP_S3_N] = { @@ -200,7 +272,7 @@ const int usb_port_enable[USBA_PORT_COUNT] = { const struct pi3hdx1204_tuning pi3hdx1204_tuning = { .eq_ch0_ch1_offset = PI3HDX1204_EQ_DB710, .eq_ch2_ch3_offset = PI3HDX1204_EQ_DB710, - .vod_offset = PI3HDX1204_VOD_115_ALL_CHANNELS, + .vod_offset = PI3HDX1204_VOD_130_ALL_CHANNELS, .de_offset = PI3HDX1204_DE_DB_MINUS5, }; @@ -223,8 +295,8 @@ static void board_chipset_resume(void) int val; rv = i2c_read8(I2C_PORT_USBA0, - PS8811_I2C_ADDR_FLAGS + PS8811_REG_PAGE1, - PS8811_REG1_USB_BEQ_LEVEL, &val); + PS8811_I2C_ADDR_FLAGS3 + PS8811_REG_PAGE1, + PS8811_REG1_USB_BEQ_LEVEL, &val); if (!rv) break; } @@ -236,8 +308,7 @@ static void board_chipset_resume(void) if (ec_config_has_hdmi_retimer_pi3hdx1204()) { ioex_set_level(IOEX_HDMI_POWER_EN_DB, 1); msleep(PI3HDX1204_POWER_ON_DELAY_MS); - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, hpd); } } @@ -248,9 +319,7 @@ static void board_chipset_suspend(void) ioex_set_level(IOEX_USB_A0_RETIMER_EN, 0); if (ec_config_has_hdmi_retimer_pi3hdx1204()) { - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - 0); + pi3hdx1204_enable(I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, 0); ioex_set_level(IOEX_HDMI_POWER_EN_DB, 0); } @@ -261,6 +330,136 @@ DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); /***************************************************************************** * USB-C MUX/Retimer dynamic configuration */ +static int woomax_ps8818_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_18DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_18DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + if (rv) + return rv; + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* Boost the DP gain */ + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_DPEQ_LEVEL, + PS8818_DPEQ_LEVEL_UP_MASK, + PS8818_DPEQ_LEVEL_UP_19DB); + if (rv) + return rv; + + /* Enable IN_HPD on the DB */ + gpio_or_ioex_set_level(board_usbc1_retimer_inhpd, 1); + } else { + gpio_or_ioex_set_level(board_usbc1_retimer_inhpd, 0); + } + + if (!(mux_state & USB_PD_MUX_POLARITY_INVERTED)) { + rv = ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, + PS8818_REG1_CRX1EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_MASK, + PS8818_EQ_LEVEL_UP_19DB); + rv |= ps8818_i2c_write(me, PS8818_REG_PAGE1, + PS8818_REG1_APRX1_DE_LEVEL, 0x02); + } + + /* set the RX input termination */ + rv |= ps8818_i2c_field_update8(me, PS8818_REG_PAGE1, PS8818_REG1_RX_PHY, + PS8818_RX_INPUT_TERM_MASK, + PS8818_RX_INPUT_TERM_85_OHM); + /* set register 0x40 ICP1 for 1G PD loop */ + rv |= ps8818_i2c_write(me, PS8818_REG_PAGE1, 0x40, 0x84); + + return rv; +} + +static int woomax_ps8802_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* Make sure the PS8802 is awake */ + rv = ps8802_i2c_wake(me); + if (rv) + return rv; + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + rv = ps8802_i2c_field_update16(me, PS8802_REG_PAGE2, + PS8802_REG2_USB_SSEQ_LEVEL, + PS8802_USBEQ_LEVEL_UP_MASK, + PS8802_USBEQ_LEVEL_UP_19DB); + if (rv) + return rv; + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /*Boost the DP gain */ + rv = ps8802_i2c_field_update16(me, PS8802_REG_PAGE2, + PS8802_REG2_DPEQ_LEVEL, + PS8802_DPEQ_LEVEL_UP_MASK, + PS8802_DPEQ_LEVEL_UP_19DB); + if (rv) + return rv; + + /* Enable IN_HPD on the DB */ + gpio_or_ioex_set_level(board_usbc1_retimer_inhpd, 1); + } else { + /* Disable IN_HPD on the DB */ + gpio_or_ioex_set_level(board_usbc1_retimer_inhpd, 0); + } + + /* Set extra swing level tuning at 800mV/P0 */ + rv = ps8802_i2c_field_update8(me, PS8802_REG_PAGE1, + PS8802_800MV_LEVEL_TUNING, + PS8802_EXTRA_SWING_LEVEL_P0_MASK, + PS8802_EXTRA_SWING_LEVEL_P0_UP_1); + + return rv; +} + +const struct usb_mux usbc1_woomax_ps8818 = { + .usb_port = USBC_PORT_C1, + .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = PS8818_I2C_ADDR0_FLAGS, + .driver = &ps8818_usb_retimer_driver, + .board_set = &woomax_ps8818_mux_set, +}; + +/* Place holder for second mux in USBC1 chain */ +struct usb_mux_chain usbc1_mux1; + static void setup_mux(void) { if (ec_config_has_usbc1_retimer_ps8802()) { @@ -272,12 +471,11 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the PS8802 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_ps8802, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_ps8802; /* Set the AMD FP5 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_amd_fp5_usb_mux; + usbc1_mux1.mux = &usbc1_amd_fp5_usb_mux; + usbc1_ps8802.board_set = &woomax_ps8802_mux_set; /* Don't have the AMD FP5 flip */ usbc1_amd_fp5_usb_mux.flags = USB_MUX_FLAG_SET_WITHOUT_FLIP; @@ -291,13 +489,228 @@ static void setup_mux(void) * Replace usb_muxes[USBC_PORT_C1] with the AMD FP5 * table entry. */ - memcpy(&usb_muxes[USBC_PORT_C1], - &usbc1_amd_fp5_usb_mux, - sizeof(struct usb_mux)); + usb_muxes[USBC_PORT_C1].mux = &usbc1_amd_fp5_usb_mux; /* Set the PS8818 as the secondary MUX */ - usb_muxes[USBC_PORT_C1].next_mux = &usbc1_ps8818; + usbc1_mux1.mux = &usbc1_woomax_ps8818; + } +} + +enum pi3dpx1207_usb_conf { USB_DP = 0, USB_DP_INV, USB, USB_INV, DP, DP_INV }; + +static uint8_t pi3dpx1207_picasso_eq[] = { + /*usb_dp*/ + 0x13, + 0x11, + 0x20, + 0x62, + 0x06, + 0x5B, + 0x5B, + 0x07, + 0x03, + 0x40, + 0xFC, + 0x42, + 0x71, + /*usb_dp_inv */ + 0x13, + 0x11, + 0x20, + 0x72, + 0x06, + 0x03, + 0x07, + 0x5B, + 0x5B, + 0x23, + 0xFC, + 0x42, + 0x71, + /*usb*/ + 0x13, + 0x11, + 0x20, + 0x42, + 0x00, + 0x03, + 0x07, + 0x07, + 0x03, + 0x00, + 0x42, + 0x42, + 0x71, + /*usb_inv*/ + 0x13, + 0x11, + 0x20, + 0x52, + 0x00, + 0x03, + 0x07, + 0x07, + 0x03, + 0x02, + 0x42, + 0x42, + 0x71, + /*dp*/ + 0x13, + 0x11, + 0x20, + 0x22, + 0x06, + 0x5B, + 0x5B, + 0x5B, + 0x5B, + 0x60, + 0xFC, + 0xFC, + 0x71, + /*dp_inv*/ + 0x13, + 0x11, + 0x20, + 0x32, + 0x06, + 0x5B, + 0x5B, + 0x5B, + 0x5B, + 0x63, + 0xFC, + 0xFC, + 0x71, +}; +static uint8_t pi3dpx1207_dali_eq[] = { + /*usb_dp*/ + 0x13, + 0x11, + 0x20, + 0x62, + 0x06, + 0x5B, + 0x5B, + 0x07, + 0x07, + 0x40, + 0xFC, + 0x42, + 0x71, + /*usb_dp_inv*/ + 0x13, + 0x11, + 0x20, + 0x72, + 0x06, + 0x07, + 0x07, + 0x5B, + 0x5B, + 0x23, + 0xFC, + 0x42, + 0x71, + /*usb*/ + 0x13, + 0x11, + 0x20, + 0x42, + 0x00, + 0x07, + 0x07, + 0x07, + 0x07, + 0x00, + 0x42, + 0x42, + 0x71, + /*usb_inv*/ + 0x13, + 0x11, + 0x20, + 0x52, + 0x00, + 0x07, + 0x07, + 0x07, + 0x07, + 0x02, + 0x42, + 0x42, + 0x71, + /*dp*/ + 0x13, + 0x11, + 0x20, + 0x22, + 0x06, + 0x5B, + 0x5B, + 0x5B, + 0x5B, + 0x60, + 0xFC, + 0xFC, + 0x71, + /*dp_inv*/ + 0x13, + 0x11, + 0x20, + 0x32, + 0x06, + 0x5B, + 0x5B, + 0x5B, + 0x5B, + 0x63, + 0xFC, + 0xFC, + 0x71, +}; + +static int board_pi3dpx1207_mux_set(const struct usb_mux *me, + mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + enum pi3dpx1207_usb_conf usb_mode = 0; + + /* USB */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* USB with DP */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? + USB_DP_INV : + USB_DP; + } + /* USB without DP */ + else { + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? + USB_INV : + USB; + } } + /* DP without USB */ + else if (mux_state & USB_PD_MUX_DP_ENABLED) { + usb_mode = (mux_state & USB_PD_MUX_POLARITY_INVERTED) ? DP_INV : + DP; + } + /* Nothing enabled */ + else + return EC_SUCCESS; + + /* Write the retimer config byte */ + if (ec_config_has_usbc1_retimer_ps8802()) + rv = i2c_xfer(me->i2c_port, me->i2c_addr_flags, + &pi3dpx1207_dali_eq[usb_mode * 13], 13, NULL, 0); + else + rv = i2c_xfer(me->i2c_port, me->i2c_addr_flags, + &pi3dpx1207_picasso_eq[usb_mode * 13], 13, NULL, + 0); + + return rv; } const struct pi3dpx1207_usb_control pi3dpx1207_controls[] = { @@ -310,23 +723,30 @@ const struct pi3dpx1207_usb_control pi3dpx1207_controls[] = { }; BUILD_ASSERT(ARRAY_SIZE(pi3dpx1207_controls) == USBC_PORT_COUNT); -const struct usb_mux usbc0_pi3dpx1207_usb_retimer = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_TCPC0, - .i2c_addr_flags = PI3DPX1207_I2C_ADDR_FLAGS, - .driver = &pi3dpx1207_usb_retimer, +const struct usb_mux_chain usbc0_pi3dpx1207_usb_retimer = { + .mux = + &(const struct usb_mux){ + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = PI3DPX1207_I2C_ADDR_FLAGS, + .driver = &pi3dpx1207_usb_retimer, + .board_set = &board_pi3dpx1207_mux_set, + }, }; -struct usb_mux usb_muxes[] = { +struct usb_mux_chain usb_muxes[] = { [USBC_PORT_C0] = { - .usb_port = USBC_PORT_C0, - .i2c_port = I2C_PORT_USB_AP_MUX, - .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, - .driver = &amd_fp5_usb_mux_driver, - .next_mux = &usbc0_pi3dpx1207_usb_retimer, + .mux = &(const struct usb_mux) { + .usb_port = USBC_PORT_C0, + .i2c_port = I2C_PORT_USB_AP_MUX, + .i2c_addr_flags = AMD_FP5_MUX_I2C_ADDR_FLAGS, + .driver = &amd_fp5_usb_mux_driver, + }, + .next = &usbc0_pi3dpx1207_usb_retimer, }, [USBC_PORT_C1] = { /* Filled in dynamically at startup */ + .next = &usbc1_mux1, }, }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); @@ -336,9 +756,14 @@ BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); */ int board_usbc1_retimer_inhpd = IOEX_USB_C1_HPD_IN_DB; - +static uint32_t board_ver; static void setup_fw_config(void) { + cbi_get_board_version(&board_ver); + + if (board_ver >= 2) + board_usbc1_retimer_inhpd = GPIO_USB_C1_HPD_IN_DB; + /* Enable Gyro interrupts */ gpio_enable_interrupt(GPIO_6AXIS_INT_L); @@ -346,6 +771,7 @@ static void setup_fw_config(void) if (ec_config_has_hdmi_retimer_pi3hdx1204()) gpio_enable_interrupt(GPIO_DP1_HPD_EC_IN); + setup_base_gyro_config(); setup_mux(); } /* Use HOOK_PRIO_INIT_I2C + 2 to be after ioex_init(). */ @@ -358,14 +784,14 @@ DECLARE_HOOK(HOOK_INIT, setup_fw_config, HOOK_PRIO_INIT_I2C + 2); /* Physical fans. These are logically separate from pwm_channels. */ const struct fan_conf fan_conf_0 = { .flags = FAN_USE_RPM_MODE, - .ch = MFT_CH_0, /* Use MFT id to control fan */ + .ch = MFT_CH_0, /* Use MFT id to control fan */ .pgood_gpio = -1, .enable_gpio = -1, }; const struct fan_rpm fan_rpm_0 = { - .rpm_min = 3000, - .rpm_start = 3000, - .rpm_max = 4900, + .rpm_min = 1100, + .rpm_start = 1100, + .rpm_max = 5120, }; const struct fan_t fans[] = { [FAN_CH_0] = { @@ -446,29 +872,36 @@ const struct temp_sensor_t temp_sensors[] = { }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); -const static struct ec_thermal_config thermal_thermistor = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(90), - [EC_TEMP_THRESH_HALT] = C_TO_K(92), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(80), - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(58), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_THERMISTOR \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(95), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_thermistor = + THERMAL_THERMISTOR; -const static struct ec_thermal_config thermal_cpu = { - .temp_host = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(90), - [EC_TEMP_THRESH_HALT] = C_TO_K(92), - }, - .temp_host_release = { - [EC_TEMP_THRESH_HIGH] = C_TO_K(80), - }, - .temp_fan_off = C_TO_K(25), - .temp_fan_max = C_TO_K(58), -}; +/* + * TODO(b/202062363): Remove when clang is fixed. + */ +#define THERMAL_CPU \ + { \ + .temp_host = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(95), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(100), \ + }, \ + .temp_host_release = { \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ + }, \ + } +__maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT]; @@ -497,8 +930,8 @@ static const struct ec_response_keybd_config woomax_kb = { .capabilities = KEYBD_CAP_SCRNLOCK_KEY | KEYBD_CAP_NUMERIC_KEYPAD, }; -__override const struct ec_response_keybd_config -*board_vivaldi_keybd_config(void) +__override const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) { return &woomax_kb; } @@ -517,10 +950,9 @@ static void hdmi_hpd_handler(void) { int hpd = gpio_get_level(GPIO_DP1_HPD_EC_IN); - pi3hdx1204_enable(I2C_PORT_TCPC1, - PI3HDX1204_I2C_ADDR_FLAGS, - chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON) - && hpd); + pi3hdx1204_enable( + I2C_PORT_TCPC1, PI3HDX1204_I2C_ADDR_FLAGS, + chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON) && hpd); } DECLARE_DEFERRED(hdmi_hpd_handler); @@ -530,3 +962,19 @@ void hdmi_hpd_interrupt(enum gpio_signal signal) hook_call_deferred(&hdmi_hpd_handler_data, (2 * MSEC)); } +int board_usbc_port_to_hpd_gpio_or_ioex(int port) +{ + /* USB-C0 always uses USB_C0_HPD */ + if (port == 0) + return GPIO_USB_C0_HPD; + /* + * USB-C1 OPT3 DB use IOEX_USB_C1_HPD_IN_DB for board version 1 + * USB-C1 OPT3 DB use GPIO_USB_C1_HPD_IN_DB for board version 2 + */ + else if (ec_config_has_mst_hub_rtd2141b()) + return (board_ver >= 2) ? GPIO_USB_C1_HPD_IN_DB : + IOEX_USB_C1_HPD_IN_DB; + + /* USB-C1 OPT1 DB use DP2_HPD. */ + return GPIO_DP2_HPD; +} diff --git a/board/woomax/board.h b/board/woomax/board.h index 1c28c4c90d..3723d9d485 100644 --- a/board/woomax/board.h +++ b/board/woomax/board.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,21 +10,21 @@ #define VARIANT_ZORK_TREMBYLE -#include #include "baseboard.h" +#include + #undef CONFIG_USB_PORT_POWER_SMART_PORT_COUNT #define CONFIG_USB_PORT_POWER_SMART_PORT_COUNT 1 #define CONFIG_USBC_RETIMER_PI3DPX1207 -#define CONFIG_MKBP_USE_GPIO - -#define CONFIG_LED_POWER_LED /* Motion sensing drivers */ #define CONFIG_ACCELGYRO_BMI160 #define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) -#define CONFIG_ACCEL_INTERRUPTS +#define CONFIG_ACCELGYRO_ICM426XX +#define CONFIG_ACCELGYRO_ICM426XX_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(BASE_ACCEL) #define CONFIG_ACCEL_KX022 #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -36,41 +36,47 @@ #define CONFIG_GMR_TABLET_MODE /* Keyboard */ +#define CONFIG_KEYBOARD_VIVALDI #define CONFIG_KEYBOARD_REFRESH_ROW3 #define CONFIG_KEYBOARD_KEYPAD +/* + * Woomax's battery takes several seconds to come back out of its disconnect + * state (~4 seconds on the unit I have, so give it a little more for margin). + */ +#undef CONFIG_POWER_BUTTON_INIT_TIMEOUT +#define CONFIG_POWER_BUTTON_INIT_TIMEOUT 5 + +/* Thermal */ +#define CONFIG_CUSTOM_FAN_CONTROL + /* GPIO mapping from board specific name to EC common name. */ -#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL -#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL -#define GPIO_AC_PRESENT GPIO_ACOK_OD -#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL -#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL -#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV -#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L -#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L -#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L -#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L -#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK -#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L -#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL -#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD -#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD -#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L -#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL -#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL -#define GPIO_WP_L GPIO_EC_WP_L -#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE -#define GMR_TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L +#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL +#define CONFIG_SCI_GPIO GPIO_EC_FCH_SCI_ODL +#define GPIO_AC_PRESENT GPIO_ACOK_OD +#define GPIO_CPU_PROCHOT GPIO_PROCHOT_ODL +#define GPIO_EC_INT_L GPIO_EC_AP_INT_ODL +#define GPIO_ENABLE_BACKLIGHT_L GPIO_EC_EDP_BL_DISABLE +#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW +#define GPIO_KBD_KSO2 GPIO_EC_KSO_02_INV +#define GPIO_PCH_PWRBTN_L GPIO_EC_FCH_PWR_BTN_L +#define GPIO_PCH_RSMRST_L GPIO_EC_FCH_RSMRST_L +#define GPIO_PCH_SLP_S3_L GPIO_SLP_S3_L +#define GPIO_PCH_SLP_S5_L GPIO_SLP_S5_L +#define GPIO_PCH_SYS_PWROK GPIO_EC_FCH_PWROK +#define GPIO_PCH_WAKE_L GPIO_EC_FCH_WAKE_L +#define GPIO_POWER_BUTTON_L GPIO_EC_PWR_BTN_ODL +#define GPIO_S0_PGOOD GPIO_S0_PWROK_OD +#define GPIO_S5_PGOOD GPIO_EC_PWROK_OD +#define GPIO_SYS_RESET_L GPIO_EC_SYS_RST_L +#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL +#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL +#define GPIO_WP_L GPIO_EC_WP_L +#define GPIO_PACKET_MODE_EN GPIO_EC_H1_PACKET_MODE #ifndef __ASSEMBLER__ -enum adc_channel { - ADC_TEMP_SENSOR_CHARGER, - ADC_TEMP_SENSOR_SOC, - ADC_CH_COUNT -}; +enum adc_channel { ADC_TEMP_SENSOR_CHARGER, ADC_TEMP_SENSOR_SOC, ADC_CH_COUNT }; enum battery_type { BATTERY_C536, @@ -83,11 +89,7 @@ enum mft_channel { MFT_CH_COUNT, }; -enum pwm_channel { - PWM_CH_KBLIGHT = 0, - PWM_CH_FAN, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT = 0, PWM_CH_FAN, PWM_CH_COUNT }; enum temp_sensor_id { TEMP_SENSOR_CHARGER = 0, @@ -96,15 +98,11 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum usba_port { - USBA_PORT_A0 = 0, - USBA_PORT_COUNT -}; +enum usba_port { USBA_PORT_A0 = 0, USBA_PORT_COUNT }; /***************************************************************************** * CBI EC FW Configuration */ -#include "cbi_ec_fw_config.h" /** * WOOMAX_MB_USBAC @@ -146,60 +144,56 @@ enum ec_cfg_usb_db_type { WOOMAX_DB_T_OPT3_USBAC_HDMI_MSTHUB = 1, }; -#define HAS_USBC1_RETIMER_PS8802 \ - (BIT(WOOMAX_DB_T_OPT3_USBAC_HDMI_MSTHUB)) +#include "cbi_ec_fw_config.h" + +#define HAS_USBC1_RETIMER_PS8802 (BIT(WOOMAX_DB_T_OPT3_USBAC_HDMI_MSTHUB)) static inline bool ec_config_has_usbc1_retimer_ps8802(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8802); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_PS8802); } -#define HAS_USBC1_RETIMER_PS8818 \ - (BIT(WOOMAX_DB_T_OPT1_USBAC_HMDI)) +#define HAS_USBC1_RETIMER_PS8818 (BIT(WOOMAX_DB_T_OPT1_USBAC_HMDI)) static inline bool ec_config_has_usbc1_retimer_ps8818(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_USBC1_RETIMER_PS8818); + return !!(BIT(ec_config_get_usb_db()) & HAS_USBC1_RETIMER_PS8818); } -#define HAS_HDMI_RETIMER_PI3HDX1204 \ - (BIT(WOOMAX_DB_T_OPT1_USBAC_HMDI)) +#define HAS_HDMI_RETIMER_PI3HDX1204 (BIT(WOOMAX_DB_T_OPT1_USBAC_HMDI)) static inline bool ec_config_has_hdmi_retimer_pi3hdx1204(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_HDMI_RETIMER_PI3HDX1204); + return !!(BIT(ec_config_get_usb_db()) & HAS_HDMI_RETIMER_PI3HDX1204); } -#define HAS_MST_HUB_RTD2141B \ - (BIT(WOOMAX_DB_T_OPT3_USBAC_HDMI_MSTHUB)) +#define HAS_MST_HUB_RTD2141B (BIT(WOOMAX_DB_T_OPT3_USBAC_HDMI_MSTHUB)) static inline bool ec_config_has_mst_hub_rtd2141b(void) { - return !!(BIT(ec_config_get_usb_db()) & - HAS_MST_HUB_RTD2141B); + return !!(BIT(ec_config_get_usb_db()) & HAS_MST_HUB_RTD2141B); } -/* +/** + * @warning Callers must use gpio_or_ioex_set_level to handle the return result + * since either type of signal can be returned. + * * USB-C0 always uses USB_C0_HPD (= DP3_HPD). * USB-C1 OPT1 DB uses DP2_HPD. * USB-C1 OPT3 DB uses DP1_HPD via RTD2141B MST hub to drive AP * HPD, EC drives MST hub HPD input from USB-PD messages. + * + * @return GPIO (gpio_signal) or IOEX (ioex_signal) */ +int board_usbc_port_to_hpd_gpio_or_ioex(int port); +#define PORT_TO_HPD(port) board_usbc_port_to_hpd_gpio_or_ioex(port) -#define PORT_TO_HPD(port) ((port == 0) \ - ? GPIO_USB_C0_HPD \ - : (ec_config_has_mst_hub_rtd2141b()) \ - ? IOEX_USB_C1_HPD_IN_DB \ - : GPIO_DP2_HPD) - -extern const struct usb_mux usbc0_pi3dpx1207_usb_retimer; -extern const struct usb_mux usbc1_ps8802; +extern const struct usb_mux_chain usbc0_pi3dpx1207_usb_retimer; extern const struct usb_mux usbc1_ps8818; +extern struct usb_mux usbc1_ps8802; extern struct usb_mux usbc1_amd_fp5_usb_mux; void hdmi_hpd_interrupt(enum gpio_signal signal); +void motion_interrupt(enum gpio_signal signal); #endif /* !__ASSEMBLER__ */ diff --git a/board/woomax/build.mk b/board/woomax/build.mk index 1c0cbc4f63..61be1882bf 100644 --- a/board/woomax/build.mk +++ b/board/woomax/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -11,5 +11,5 @@ CHIP_FAMILY:=npcx7 CHIP_VARIANT:=npcx7m7wc BASEBOARD:=zork -board-y=board.o led.o +board-y=board.o led.o thermal.o board-$(CONFIG_BATTERY_SMART)+=battery.o diff --git a/board/woomax/ec.tasklist b/board/woomax/ec.tasklist index d9c1606eb2..abc796f74f 100644 --- a/board/woomax/ec.tasklist +++ b/board/woomax/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/woomax/gpio.inc b/board/woomax/gpio.inc index 6654b88570..f085134b2e 100644 --- a/board/woomax/gpio.inc +++ b/board/woomax/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -24,7 +24,7 @@ GPIO_INT(ACOK_OD, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_inter GPIO_INT(EC_WP_L, PIN(5, 0), GPIO_INT_BOTH, switch_interrupt) GPIO_INT(VOLDN_BTN_ODL, PIN(A, 6), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) GPIO_INT(VOLUP_BTN_ODL, PIN(9, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) -GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, bmi160_interrupt) +GPIO_INT(6AXIS_INT_L, PIN(A, 0), GPIO_INT_FALLING | GPIO_PULL_UP, motion_interrupt) GPIO_INT(TABLET_MODE_L, PIN(4, 4), GPIO_INT_BOTH, gmr_tablet_switch_isr) GPIO_INT(DP1_HPD_EC_IN, PIN(7, 5), GPIO_INT_BOTH, hdmi_hpd_interrupt) @@ -53,6 +53,7 @@ GPIO(EC_DP1_HPD, PIN(F, 4), GPIO_OUT_LOW) /* C1 DP Hotplug Detect */ GPIO(DP2_HPD, PIN(C, 1), GPIO_OUT_LOW) /* C1 DP Hotplug Detect */ GPIO(EC_H1_PACKET_MODE, PIN(8, 6), GPIO_OUT_LOW) /* H1 Packet Mode */ GPIO(EN_PWR_TOUCHPAD_PS2, PIN(C, 2), GPIO_INPUT) /* Touchpad Power */ +GPIO(USB_C1_HPD_IN_DB, PIN(B, 1), GPIO_OUT_LOW) /* C1 HPD for board version 2 */ UNIMPLEMENTED(NO_HPD) UNIMPLEMENTED(PCH_SMI_L) @@ -75,7 +76,7 @@ IOEX(USB_C0_DATA_EN, EXPIN(USBC_PORT_C0, 1, 4), GPIO_OUT_LOW) /* C0 Data Enable IOEX(EN_USB_A0_5V, EXPIN(USBC_PORT_C0, 1, 5), GPIO_OUT_LOW) /* A0 5V Source Enable */ IOEX(USB_A0_CHARGE_EN_L, EXPIN(USBC_PORT_C0, 1, 6), GPIO_OUT_HIGH) /* A0 5V High Current Enable */ -IOEX(USB_C1_HPD_IN_DB, EXPIN(USBC_PORT_C1, 0, 2), GPIO_OUT_LOW) /* C1 HPD */ +IOEX(USB_C1_HPD_IN_DB, EXPIN(USBC_PORT_C1, 0, 2), GPIO_OUT_LOW) /* C1 HPD for board version 1*/ IOEX(HDMI_POWER_EN_DB, EXPIN(USBC_PORT_C1, 0, 3), GPIO_OUT_LOW) /* HDMI retimer power enable */ IOEX(USB_C1_TCPC_FASTSW_CTL_EN, EXPIN(USBC_PORT_C1, 0, 4), GPIO_OUT_LOW) /* C1 FastSwitch Control */ IOEX(USB_C1_MUX_RST_DB, EXPIN(USBC_PORT_C1, 1, 1), GPIO_OUT_LOW) /* C1 Mux Reset */ diff --git a/board/woomax/led.c b/board/woomax/led.c index 6aa6c74f94..9ecd0e8110 100644 --- a/board/woomax/led.c +++ b/board/woomax/led.c @@ -1,44 +1,53 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "led_common.h" #include "led_onoff_states.h" -#include "chipset.h" #define LED_ON_LVL 0 #define LED_OFF_LVL 1 -const int led_charge_lvl_1 = 5; - -const int led_charge_lvl_2 = 95; +__override const int led_charge_lvl_1 = 5; -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_WHITE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, -}; +__override const int led_charge_lvl_2 = 95; -const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_WHITE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 1 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_WHITE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + }; +__override const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { + [PWR_LED_STATE_ON] = { { EC_LED_COLOR_WHITE, LED_INDEFINITE } }, + [PWR_LED_STATE_SUSPEND_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_SUSPEND_NO_AC] = { { EC_LED_COLOR_WHITE, + 1 * LED_ONE_SEC }, + { LED_OFF, + 3 * LED_ONE_SEC } }, + [PWR_LED_STATE_OFF] = { { LED_OFF, LED_INDEFINITE } }, + }; const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, @@ -47,7 +56,7 @@ const enum ec_led_id supported_led_ids[] = { const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_AMBER: @@ -65,7 +74,7 @@ void led_set_color_battery(enum ec_led_colors color) } } -void led_set_color_power(enum ec_led_colors color) +__override void led_set_color_power(enum ec_led_colors color) { if (color == EC_LED_COLOR_WHITE) gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); @@ -102,4 +111,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/woomax/thermal.c b/board/woomax/thermal.c new file mode 100644 index 0000000000..a2ab52cc74 --- /dev/null +++ b/board/woomax/thermal.c @@ -0,0 +1,137 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "extpower.h" +#include "fan.h" +#include "hooks.h" +#include "host_command.h" +#include "temp_sensor.h" +#include "thermal.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_THERMAL, outstr) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) + +struct fan_step { + /* + * Sensor 1~3 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t on[TEMP_SENSOR_COUNT]; + + /* + * Sensor 1~3 trigger point, set -1 if we're not using this + * sensor to determine fan speed. + */ + int8_t off[TEMP_SENSOR_COUNT]; + + /* Fan rpm */ + uint16_t rpm; +}; + +static const struct fan_step fan_step_table[] = { + { + /* level 0 */ + .on = { -1, -1, 36 }, + .off = { -1, -1, 99 }, + .rpm = 0, + }, + { + /* level 1 */ + .on = { -1, -1, 40 }, + .off = { -1, -1, 32 }, + .rpm = 2244, + }, + { + /* level 2 */ + .on = { -1, -1, 45 }, + .off = { -1, -1, 35 }, + .rpm = 2580, + }, + { + /* level 3 */ + .on = { -1, -1, 50 }, + .off = { -1, -1, 40 }, + .rpm = 2824, + }, + { + /* level 4 */ + .on = { -1, -1, 55 }, + .off = { -1, -1, 45 }, + .rpm = 3120, + }, + { + /* level 5 */ + .on = { -1, -1, 60 }, + .off = { -1, -1, 50 }, + .rpm = 3321, + }, + { + /* level 6 */ + .on = { -1, -1, 70 }, + .off = { -1, -1, 55 }, + .rpm = 3780, + }, + { + /* level 7 */ + .on = { -1, -1, 80 }, + .off = { -1, -1, 60 }, + .rpm = 4330, + }, + { + /* level 8 */ + .on = { -1, -1, 99 }, + .off = { -1, -1, 74 }, + .rpm = 4915, + }, +}; + +#define NUM_FAN_LEVELS ARRAY_SIZE(fan_step_table) + +int fan_table_to_rpm(int fan, int *temp) +{ + static int current_level; + static int prev_tmp[TEMP_SENSOR_COUNT]; + int i; + + /* + * Comopare the current and previous temperature, we have + * the three path: + * 1. decreasing path. (check the release point) + * 2. increasing path. (check the trigger point) + * 3. invariant path. (return the current RPM) + */ + if (temp[TEMP_SENSOR_CPU] < prev_tmp[TEMP_SENSOR_CPU]) { + if (temp[TEMP_SENSOR_CPU] < + fan_step_table[current_level].off[TEMP_SENSOR_CPU]) + current_level = current_level - 1; + } else if (temp[TEMP_SENSOR_CPU] > prev_tmp[TEMP_SENSOR_CPU]) { + if (temp[TEMP_SENSOR_CPU] > + fan_step_table[current_level].on[TEMP_SENSOR_CPU]) + current_level = current_level + 1; + } + + if (current_level < 0) + current_level = 0; + else if (current_level > NUM_FAN_LEVELS) + current_level = NUM_FAN_LEVELS; + + for (i = 0; i < TEMP_SENSOR_COUNT; i++) + prev_tmp[i] = temp[i]; + + return fan_step_table[current_level].rpm; +} + +void board_override_fan_control(int fan, int *tmp) +{ + if (chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND)) { + fan_set_rpm_mode(FAN_CH(fan), 1); + fan_set_rpm_target(FAN_CH(fan), fan_table_to_rpm(fan, tmp)); + } +} diff --git a/board/woomax/vif_override.xml b/board/woomax/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/woomax/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/wormdingler/base_detect.c b/board/wormdingler/base_detect.c new file mode 100644 index 0000000000..dca23b4d2e --- /dev/null +++ b/board/wormdingler/base_detect.c @@ -0,0 +1,232 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Wormdingler base detection code */ + +#include "adc.h" +#include "base_state.h" +#include "board.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "system.h" +#include "tablet_mode.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +/* Make sure POGO VBUS starts later then PP3300_HUB when power on */ +#define BASE_DETECT_EN_LATER_US (600 * MSEC) + +/* Base detection and debouncing */ +#define BASE_DETECT_EN_DEBOUNCE_US (350 * MSEC) +#define BASE_DETECT_DIS_DEBOUNCE_US (20 * MSEC) + +/* + * If the base status is unclear (i.e. not within expected ranges, read + * the ADC value again every 500ms. + */ +#define BASE_DETECT_RETRY_US (500 * MSEC) + +/* + * Lid has 604K pull-up, base has 30.1K pull-down, so the + * ADC value should be around 30.1/(604+30.1)*3300 = 156 + * + * We add a significant margin on the maximum value, due to noise on the line, + * especially when PWM is active. See b/64193554 for details. + */ +#define BASE_DETECT_MIN_MV 120 +#define BASE_DETECT_MAX_MV 300 + +/* Minimum ADC value to indicate base is disconnected for sure */ +#define BASE_DETECT_DISCONNECT_MIN_MV 1500 + +/* + * Base EC pulses detection pin for 500 us to signal out of band USB wake (that + * can be used to wake system from deep S3). + */ +#define BASE_DETECT_PULSE_MIN_US 400 +#define BASE_DETECT_PULSE_MAX_US 650 + +static uint64_t base_detect_debounce_time; + +static void base_detect_deferred(void); +DECLARE_DEFERRED(base_detect_deferred); + +enum base_status { + BASE_UNKNOWN = 0, + BASE_DISCONNECTED = 1, + BASE_CONNECTED = 2, +}; + +static enum base_status current_base_status; + +/* + * This function is called whenever there is a change in the base detect + * status. Actions taken include: + * 1. Change in power to base + * 2. Indicate mode change to host. + * 3. Indicate tablet mode to host. Current assumption is that if base is + * disconnected then the system is in tablet mode, else if the base is + * connected, then the system is not in tablet mode. + */ +static void base_detect_change(enum base_status status) +{ + int connected = (status == BASE_CONNECTED); + + if (current_base_status == status) + return; + + gpio_set_level(GPIO_EN_BASE, connected); + base_set_state(connected); + current_base_status = status; +} + +/* Measure detection pin pulse duration (used to wake AP from deep S3). */ +static uint64_t pulse_start; +static uint32_t pulse_width; + +static void print_base_detect_value(int v, int tmp_pulse_width) +{ + CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name, v, + tmp_pulse_width); +} + +static void base_detect_deferred(void) +{ + uint64_t time_now = get_time().val; + int v; + uint32_t tmp_pulse_width = pulse_width; + + if (base_detect_debounce_time > time_now) { + hook_call_deferred(&base_detect_deferred_data, + base_detect_debounce_time - time_now); + return; + } + + v = adc_read_channel(ADC_BASE_DET); + if (v == ADC_READ_ERROR) + return; + + print_base_detect_value(v, tmp_pulse_width); + + if (v >= BASE_DETECT_MIN_MV && v <= BASE_DETECT_MAX_MV) { + if (current_base_status != BASE_CONNECTED) { + base_detect_change(BASE_CONNECTED); + } else if (tmp_pulse_width >= BASE_DETECT_PULSE_MIN_US && + tmp_pulse_width <= BASE_DETECT_PULSE_MAX_US) { + CPRINTS("Sending event to AP"); + host_set_single_event(EC_HOST_EVENT_KEY_PRESSED); + } + return; + } + + if (v >= BASE_DETECT_DISCONNECT_MIN_MV) { + base_detect_change(BASE_DISCONNECTED); + return; + } + + /* Unclear base status, schedule again in a while. */ + hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_RETRY_US); +} + +static inline int detect_pin_connected(enum gpio_signal det_pin) +{ + return gpio_get_level(det_pin) == 0; +} + +void base_detect_interrupt(enum gpio_signal signal) +{ + uint64_t time_now = get_time().val; + int debounce_us; + + if (detect_pin_connected(signal)) + debounce_us = BASE_DETECT_EN_DEBOUNCE_US; + else + debounce_us = BASE_DETECT_DIS_DEBOUNCE_US; + + if (base_detect_debounce_time <= time_now) { + /* + * Detect and measure detection pin pulse, when base is + * connected. Only a single pulse is measured over a debounce + * period. If no pulse, or multiple pulses are detected, + * pulse_width is set to 0. + */ + if (current_base_status == BASE_CONNECTED && + !detect_pin_connected(signal)) { + pulse_start = time_now; + } else { + pulse_start = 0; + } + pulse_width = 0; + + hook_call_deferred(&base_detect_deferred_data, debounce_us); + } else { + if (current_base_status == BASE_CONNECTED && + detect_pin_connected(signal) && !pulse_width && + pulse_start) { + /* First pulse within period. */ + pulse_width = time_now - pulse_start; + } else { + pulse_start = 0; + pulse_width = 0; + } + } + + base_detect_debounce_time = time_now + debounce_us; +} + +static void base_enable(void) +{ + /* Enable base detection interrupt. */ + base_detect_debounce_time = get_time().val; + hook_call_deferred(&base_detect_deferred_data, BASE_DETECT_EN_LATER_US); + gpio_enable_interrupt(GPIO_BASE_DET_L); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, base_enable, HOOK_PRIO_DEFAULT); + +static void base_disable(void) +{ + /* + * Disable base detection interrupt and disable power to base. + * Set the state UNKNOWN so the next startup will initialize a + * correct state and notify AP. + */ + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_UNKNOWN); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, base_disable, HOOK_PRIO_DEFAULT); + +static void base_init(void) +{ + /* + * If we jumped to this image and chipset is already in S0, enable + * base. + */ + if (system_jumped_late() && chipset_in_state(CHIPSET_STATE_ON)) + base_enable(); +} +DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT + 1); + +void base_force_state(enum ec_set_base_state_cmd state) +{ + if (state == EC_SET_BASE_STATE_ATTACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_CONNECTED); + CPRINTS("BD forced connected"); + } else if (state == EC_SET_BASE_STATE_DETACH) { + gpio_disable_interrupt(GPIO_BASE_DET_L); + base_detect_change(BASE_DISCONNECTED); + CPRINTS("BD forced disconnected"); + } else { + base_enable(); + CPRINTS("BD forced reset"); + } +} diff --git a/board/wormdingler/battery.c b/board/wormdingler/battery.c new file mode 100644 index 0000000000..001cd0474b --- /dev/null +++ b/board/wormdingler/battery.c @@ -0,0 +1,99 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery_fuel_gauge.h" +#include "common.h" +#include "util.h" + +/* + * Battery info for all wormdingler battery types. Note that the fields + * start_charging_min/max and charging_min/max are not used for the charger. + * The effective temperature limits are given by discharging_min/max_c. + * + * Fuel Gauge (FG) parameters which are used for determining if the battery + * is connected, the appropriate ship mode (battery cutoff) command, and the + * charge/discharge FETs status. + * + * Ship mode (battery cutoff) requires 2 writes to the appropriate smart battery + * register. For some batteries, the charge/discharge FET bits are set when + * charging/discharging is active, in other types, these bits set mean that + * charging/discharging is disabled. Therefore, in addition to the mask for + * these bits, a disconnect value must be specified. Note that for TI fuel + * gauge, the charge/discharge FET status is found in Operation Status (0x54), + * but a read of Manufacturer Access (0x00) will return the lower 16 bits of + * Operation status which contains the FET status bits. + * + * The assumption for battery types supported is that the charge/discharge FET + * status can be read with a sb_read() command and therefore, only the register + * address, mask, and disconnect value need to be provided. + */ + +const struct board_batt_params board_battery_info[] = { + /* Sunwoda L21D2PG2 */ + [BATTERY_L21D2PG2] = { + .fuel_gauge = { + .manuf_name = "Sunwoda", + .device_name = "L21D2PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8860, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 200, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 63, + .discharging_min_c = -20, + .discharging_max_c = 63, + .vendor_param_start = 0x70, + }, + }, + /* BYD L21B2PG2 */ + [BATTERY_L21B2PG2] = { + .fuel_gauge = { + .manuf_name = "BYD", + .device_name = "L21B2PG2", + .ship_mode = { + .reg_addr = 0x34, + .reg_data = { 0x0000, 0x1000 }, + }, + .fet = { + .mfgacc_support = 1, + .reg_addr = 0x34, + .reg_mask = 0x0100, + .disconnect_val = 0x0, + } + }, + .batt_info = { + .voltage_max = 8860, /* mV */ + .voltage_normal = 7700, /* mV */ + .voltage_min = 6000, /* mV */ + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, + .vendor_param_start = 0x70, + }, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT); + +const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_L21D2PG2; diff --git a/board/wormdingler/board.c b/board/wormdingler/board.c new file mode 100644 index 0000000000..4c02398e6c --- /dev/null +++ b/board/wormdingler/board.c @@ -0,0 +1,661 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Wormdingler board-specific configuration */ + +#include "adc_chip.h" +#include "button.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_icm42607.h" +#include "driver/accelgyro_icm_common.h" +#include "driver/ln9310.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/ps8xxx.h" +#include "driver/tcpm/tcpci.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_mkbp.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "peripheral_charger.h" +#include "pi3usb9201.h" +#include "power.h" +#include "power/qcom.h" +#include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" +#include "queue.h" +#include "shi_chip.h" +#include "switch.h" +#include "system.h" +#include "tablet_mode.h" +#include "task.h" +#include "usbc_ppc.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +#define KS_DEBOUNCE_US (30 * MSEC) /* Debounce time for kickstand switch */ + +/* Forward declaration */ +static void tcpc_alert_event(enum gpio_signal signal); +static void usb0_evt(enum gpio_signal signal); +static void usb1_evt(enum gpio_signal signal); +static void ppc_interrupt(enum gpio_signal signal); +static void board_connect_c0_sbu(enum gpio_signal s); +static void switchcap_interrupt(enum gpio_signal signal); + +#include "gpio_list.h" + +/* GPIO Interrupt Handlers */ +static void tcpc_alert_event(enum gpio_signal signal) +{ + int port = -1; + + switch (signal) { + case GPIO_USB_C0_PD_INT_ODL: + port = 0; + break; + case GPIO_USB_C1_PD_INT_ODL: + port = 1; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +static void usb0_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(0, USB_CHG_EVENT_BC12); +} + +static void usb1_evt(enum gpio_signal signal) +{ + usb_charger_task_set_event(1, USB_CHG_EVENT_BC12); +} + +static void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_SWCTL_INT_ODL: + sn5s330_interrupt(0); + break; + case GPIO_USB_C1_SWCTL_INT_ODL: + sn5s330_interrupt(1); + break; + default: + break; + } +} + +static void board_connect_c0_sbu_deferred(void) +{ + /* + * If CCD_MODE_ODL asserts, it means there's a debug accessory connected + * and we should enable the SBU FETs. + */ + ppc_set_sbu(0, 1); +} +DECLARE_DEFERRED(board_connect_c0_sbu_deferred); + +static void board_connect_c0_sbu(enum gpio_signal s) +{ + hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); +} + +static void switchcap_interrupt(enum gpio_signal signal) +{ + ln9310_interrupt(signal); +} + +/* I2C port map */ +const struct i2c_port_t i2c_ports[] = { + { .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C_POWER_SCL, + .sda = GPIO_EC_I2C_POWER_SDA }, + { .name = "tcpc0", + .port = I2C_PORT_TCPC0, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C0_PD_SCL, + .sda = GPIO_EC_I2C_USB_C0_PD_SDA }, + { .name = "tcpc1", + .port = I2C_PORT_TCPC1, + .kbps = 1000, + .scl = GPIO_EC_I2C_USB_C1_PD_SCL, + .sda = GPIO_EC_I2C_USB_C1_PD_SDA }, + { .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C_EEPROM_SCL, + .sda = GPIO_EC_I2C_EEPROM_SDA }, + { .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C_SENSOR_SCL, + .sda = GPIO_EC_I2C_SENSOR_SDA }, +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* Measure VBUS through a 1/10 voltage divider */ + [ADC_VBUS] = { "VBUS", NPCX_ADC_CH1, ADC_MAX_VOLT * 10, + ADC_READ_MAX + 1, 0 }, + /* + * Adapter current output or battery charging/discharging current (uV) + * 18x amplification on charger side. + */ + [ADC_AMON_BMON] = { "AMON_BMON", NPCX_ADC_CH2, ADC_MAX_VOLT * 1000 / 18, + ADC_READ_MAX + 1, 0 }, + /* + * ISL9238 PSYS output is 1.44 uA/W over 5.6K resistor, to read + * 0.8V @ 99 W, i.e. 124000 uW/mV. Using ADC_MAX_VOLT*124000 and + * ADC_READ_MAX+1 as multiplier/divider leads to overflows, so we + * only divide by 2 (enough to avoid precision issues). + */ + [ADC_PSYS] = { "PSYS", NPCX_ADC_CH3, + ADC_MAX_VOLT * 124000 * 2 / (ADC_READ_MAX + 1), 2, 0 }, + /* Base detection */ + [ADC_BASE_DET] = { "BASE_DET", NPCX_ADC_CH5, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +const struct pwm_t pwm_channels[] = { + /* TODO(waihong): Assign a proper frequency. */ + [PWM_CH_DISPLIGHT] = { .channel = 5, .flags = 0, .freq = 4800 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + +/* LN9310 switchcap */ +const struct ln9310_config_t ln9310_config = { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = LN9310_I2C_ADDR_0_FLAGS, +}; + +/* Power Path Controller */ +struct ppc_config_t ppc_chips[] = { + { .i2c_port = I2C_PORT_TCPC0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, + { .i2c_port = I2C_PORT_TCPC1, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/* TCPC mux configuration */ +const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC0, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, + { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_TCPC1, + .addr_flags = PS8XXX_I2C_ADDR1_FLAGS, + }, + .drv = &ps8xxx_tcpm_drv, + }, +}; + +/* + * Port-0/1 USB mux driver. + * + * The USB mux is handled by TCPC chip and the HPD update is through a GPIO + * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, + * the mux misbehaves. + */ +const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .mux = + &(const struct usb_mux){ + .usb_port = 0, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + }, + { + .mux = + &(const struct usb_mux){ + .usb_port = 1, + .driver = &tcpci_tcpm_usb_mux_driver, + .hpd_update = &ps8xxx_tcpc_update_hpd_status, + }, + } +}; + +/* BC1.2 */ +const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { + { + .i2c_port = I2C_PORT_POWER, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, + { + .i2c_port = I2C_PORT_EEPROM, + .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS, + }, +}; + +/* Mutexes */ +static struct mutex g_lid_mutex; + +static struct bmi_drv_data_t g_bmi160_data; +static struct icm_drv_data_t g_icm42607_data; + +enum lid_accelgyro_type { + LID_GYRO_NONE = 0, + LID_GYRO_BMI160 = 1, + LID_GYRO_ICM42607 = 2, +}; + +static enum lid_accelgyro_type lid_accelgyro_config; + +/* Matrix to rotate accelerometer into standard reference frame */ +const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +const mat33_fp_t lid_standard_ref_icm42607 = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; + +struct motion_sensor_t icm42607_lid_accel = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref_icm42607, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = ICM42607_ACCEL_MIN_FREQ, + .max_frequency = ICM42607_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, +}; + +struct motion_sensor_t icm42607_lid_gyro = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_ICM42607, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &icm42607_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_icm42607_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref_icm42607, + .min_frequency = ICM42607_GYRO_MIN_FREQ, + .max_frequency = ICM42607_GYRO_MAX_FREQ, +}; + +struct motion_sensor_t motion_sensors[] = { + /* + * Note: bmi160: supports accelerometer and gyro sensor + * Requirement: accelerometer sensor must init before gyro sensor + * DO NOT change the order of the following table. + */ + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs */ + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .config = { + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [LID_GYRO] = { + .name = "Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI160, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_LID, + .drv = &bmi160_drv, + .mutex = &g_lid_mutex, + .drv_data = &g_bmi160_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, +}; +const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +static void board_detect_motionsensor(void) +{ + int val = -1; + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + if (lid_accelgyro_config != LID_GYRO_NONE) + return; + + /* Check base accelgyro chip */ + icm_read8(&icm42607_lid_accel, ICM42607_REG_WHO_AM_I, &val); + if (val == ICM42607_CHIP_ICM42607P) { + motion_sensors[LID_ACCEL] = icm42607_lid_accel; + motion_sensors[LID_GYRO] = icm42607_lid_gyro; + lid_accelgyro_config = LID_GYRO_ICM42607; + CPRINTS("LID Accelgyro: ICM42607"); + } else { + lid_accelgyro_config = LID_GYRO_BMI160; + CPRINTS("LID Accelgyro: BMI160"); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_detect_motionsensor, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_detect_motionsensor, HOOK_PRIO_DEFAULT + 1); + +void motion_interrupt(enum gpio_signal signal) +{ + switch (lid_accelgyro_config) { + case LID_GYRO_ICM42607: + icm42607_interrupt(signal); + break; + case LID_GYRO_BMI160: + default: + bmi160_interrupt(signal); + break; + } +} + +enum battery_cell_type board_get_battery_cell_type(void) +{ + return BATTERY_CELL_TYPE_2S; +} + +static void board_switchcap_init(void) +{ + CPRINTS("Use switchcap: LN9310"); + + /* Configure and enable interrupt for LN9310 */ + gpio_set_flags(GPIO_SWITCHCAP_PG_INT_L, GPIO_INT_FALLING); + gpio_enable_interrupt(GPIO_SWITCHCAP_PG_INT_L); + + /* Only configure the switchcap if not sysjump */ + if (!system_jumped_late()) + ln9310_init(); +} + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable BC1.2 interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + gpio_enable_interrupt(GPIO_ACCEL_GYRO_INT_L); + + /* + * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs + * for SBU may be disconnected after DP alt mode is off. Should enable + * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. + */ + gpio_enable_interrupt(GPIO_CCD_MODE_ODL); + + /* Set the backlight duty cycle to 0. AP will override it later. */ + pwm_set_duty(PWM_CH_DISPLIGHT, 0); + + board_switchcap_init(); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +__overridable uint16_t board_get_ps8xxx_product_id(int port) +{ + if (check_ps8755_chip(port)) + return PS8755_PRODUCT_ID; + + return PS8805_PRODUCT_ID; +} + +void board_tcpc_init(void) +{ + /* Only reset TCPC if not sysjump */ + if (!system_jumped_late()) { + /* TODO(crosbug.com/p/61098): How long do we need to wait? */ + board_reset_pd_mcu(); + } + + /* Enable PPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_SWCTL_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_SWCTL_INT_ODL); + + /* Enable TCPC interrupts */ + gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); + gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); + + /* + * Initialize HPD to low; after sysjump SOC needs to see + * HPD pulse to enable video path + */ + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +} +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +void board_hibernate(void) +{ + int i; + + /* + * Sensors are unpowered in hibernate. Apply PD to the + * interrupt lines such that they don't float. + */ + gpio_set_flags(GPIO_ACCEL_GYRO_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); + + /* + * Board rev 1+ has the hardware fix. Don't need the following + * workaround. + */ + if (system_get_board_version() >= 1) + return; + + /* + * Enable the PPC power sink path before EC enters hibernate; + * otherwise, ACOK won't go High and can't wake EC up. Check the + * bug b/170324206 for details. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + ppc_vbus_sink_enable(i, 1); +} + +/* Called on AP S0 -> S3 transition */ +static void board_chipset_suspend(void) +{ + /* + * Turn off display backlight in S3. AP has its own control. The EC's + * and the AP's will be AND'ed together in hardware. + */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); + pwm_enable(PWM_CH_DISPLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); + +/* Called on AP S3 -> S0 transition */ +static void board_chipset_resume(void) +{ + /* Turn on display and keyboard backlight in S0. */ + gpio_set_level(GPIO_ENABLE_BACKLIGHT, 1); + if (pwm_get_duty(PWM_CH_DISPLIGHT)) + pwm_enable(PWM_CH_DISPLIGHT, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); + +void board_set_switchcap_power(int enable) +{ + gpio_set_level(GPIO_SWITCHCAP_ON_L, !enable); + ln9310_software_enable(enable); +} + +int board_is_switchcap_enabled(void) +{ + return !gpio_get_level(GPIO_SWITCHCAP_ON_L); +} + +int board_is_switchcap_power_good(void) +{ + return ln9310_power_good(); +} + +void board_reset_pd_mcu(void) +{ + cprints(CC_USB, "Resetting TCPCs..."); + cflush(); + + gpio_set_level(GPIO_USB_C0_PD_RST_L, 0); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 0); + msleep(PS8XXX_RESET_DELAY_MS); + gpio_set_level(GPIO_USB_C0_PD_RST_L, 1); + gpio_set_level(GPIO_USB_C1_PD_RST_L, 1); +} + +void board_set_tcpc_power_mode(int port, int mode) +{ + /* Ignore the "mode" to turn the chip on. We can only do a reset. */ + if (mode) + return; + + board_reset_pd_mcu(); +} + +int board_vbus_sink_enable(int port, int enable) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_vbus_sink_enable(port, enable); +} + +int board_is_sourcing_vbus(int port) +{ + /* Both ports are controlled by PPC SN5S330 */ + return ppc_is_sourcing_vbus(port); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO(b/120231371): Notify AP */ + CPRINTS("p%d: overcurrent!", port); +} + +int board_set_active_charge_port(int port) +{ + int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (!is_real_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("Disabling all charging port"); + + /* Disable all ports. */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (board_vbus_sink_enable(i, 0)) + CPRINTS("Disabling p%d sink path failed.", i); + } + + return EC_SUCCESS; + } + + /* Check if the port is sourcing VBUS. */ + if (board_is_sourcing_vbus(port)) { + CPRINTS("Skip enable p%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("New charge port: p%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (i == port) + continue; + + if (board_vbus_sink_enable(i, 0)) + CPRINTS("p%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (board_vbus_sink_enable(port, 1)) { + CPRINTS("p%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +__override void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + /* + * Ignore lower charge ceiling on PD transition if our battery is + * critical, as we may brownout. + */ + if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && + charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { + CPRINTS("Using max ilim %d", max_ma); + charge_ma = max_ma; + } + + charge_set_input_current_limit(charge_ma, charge_mv); +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_0; + if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) + if (gpio_get_level(GPIO_USB_C1_PD_RST_L)) + status |= PD_STATUS_TCPC_ALERT_1; + + return status; +} diff --git a/board/wormdingler/board.h b/board/wormdingler/board.h new file mode 100644 index 0000000000..595e16eac8 --- /dev/null +++ b/board/wormdingler/board.h @@ -0,0 +1,105 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Wormdingler board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +#include "baseboard.h" + +#define CONFIG_BUTTON_TRIGGERED_RECOVERY + +/* Internal SPI flash on NPCX7 */ +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) /* 512KB internal spi flash */ + +/* Switchcap */ +#define CONFIG_LN9310 + +/* Battery */ +#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION" +#define CONFIG_BATTERY_REVIVE_DISCONNECT +#define CONFIG_BATTERY_FUEL_GAUGE +#define CONFIG_BATTERY_VENDOR_PARAM + +#undef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT +#define CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT 5 + +/* Enable PD3.0 */ +#define CONFIG_USB_PD_REV30 + +/* BC 1.2 Charger */ +#define CONFIG_BC12_DETECT_PI3USB9201 + +/* USB */ +#define CONFIG_USB_PD_TCPM_MULTI_PS8XXX +#define CONFIG_USB_PD_TCPM_PS8755 +#define CONFIG_USB_PD_TCPM_PS8805 +#define CONFIG_USB_PD_TCPM_PS8805_FORCE_DID +#define CONFIG_USBC_PPC_SN5S330 +#define CONFIG_USB_PD_PORT_MAX_COUNT 2 + +/* Lid accel/gyro */ +#define CONFIG_ACCELGYRO_BMI160 +#define CONFIG_ACCELGYRO_BMI160_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) +#define OPT3001_I2C_ADDR_FLAGS OPT3001_I2C_ADDR1_FLAGS +#define CONFIG_ACCELGYRO_ICM42607 +#define CONFIG_ACCELGYRO_ICM42607_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(LID_ACCEL) + +#define CONFIG_FRONT_PROXIMITY_SWITCH + +#define CONFIG_DETACHABLE_BASE +#define CONFIG_BASE_ATTACHED_SWITCH + +/* GPIO alias */ +#define GPIO_AC_PRESENT GPIO_CHG_ACOK_OD +#define GPIO_WP_L GPIO_EC_FLASH_WP_ODL +#define GPIO_PMIC_RESIN_L GPIO_PM845_RESIN_L +#define GPIO_SWITCHCAP_PG_INT_L GPIO_LN9310_INT + +#define CONFIG_MKBP_INPUT_DEVICES + +#ifndef __ASSEMBLER__ + +#include "gpio_signal.h" +#include "registers.h" + +enum adc_channel { + ADC_VBUS, + ADC_AMON_BMON, + ADC_PSYS, + ADC_BASE_DET, + ADC_CH_COUNT +}; + +/* Motion sensors */ +enum sensor_id { + LID_ACCEL = 0, + LID_GYRO, + SENSOR_COUNT, +}; + +enum pwm_channel { PWM_CH_DISPLIGHT = 0, PWM_CH_COUNT }; + +/* List of possible batteries */ +enum battery_type { + BATTERY_L21D2PG2, + BATTERY_L21B2PG2, + BATTERY_TYPE_COUNT, +}; + +/* Reset all TCPCs. */ +void board_reset_pd_mcu(void); +void board_set_tcpc_power_mode(int port, int mode); +/* Base detection */ +void base_detect_interrupt(enum gpio_signal signal); + +void motion_interrupt(enum gpio_signal signal); + +#endif /* !defined(__ASSEMBLER__) */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/wormdingler/build.mk b/board/wormdingler/build.mk new file mode 100644 index 0000000000..363ef59a16 --- /dev/null +++ b/board/wormdingler/build.mk @@ -0,0 +1,14 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Board specific files build +# + +CHIP:=npcx +CHIP_FAMILY:=npcx7 +CHIP_VARIANT:=npcx7m6fc +BASEBOARD:=trogdor + +board-y=battery.o board.o led.o base_detect.o usbc_config.o diff --git a/board/wormdingler/ec.tasklist b/board/wormdingler/ec.tasklist new file mode 100644 index 0000000000..8fc8115afc --- /dev/null +++ b/board/wormdingler/ec.tasklist @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * See CONFIG_TASK_LIST in config.h for details. + */ + +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C1, pd_task, NULL, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, ULTRA_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, ULTRA_TASK_STACK_SIZE) diff --git a/board/wormdingler/gpio.inc b/board/wormdingler/gpio.inc new file mode 100644 index 0000000000..37e71977ac --- /dev/null +++ b/board/wormdingler/gpio.inc @@ -0,0 +1,196 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +/* USB-C interrupts */ +GPIO_INT(USB_C0_PD_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-0 TCPC */ +GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event) /* Interrupt from port-1 TCPC */ +GPIO_INT(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-0 PPC */ +GPIO_INT(USB_C1_SWCTL_INT_ODL, PIN(4, 0), GPIO_INT_FALLING, ppc_interrupt) /* Interrupt from port-1 PPC */ +GPIO_INT(USB_C0_BC12_INT_L, PIN(6, 1), GPIO_INT_FALLING | GPIO_PULL_UP, usb0_evt) /* Interrupt from port-0 BC1.2 */ +GPIO_INT(USB_C1_BC12_INT_L, PIN(8, 2), GPIO_INT_FALLING | GPIO_PULL_UP, usb1_evt) /* Interrupt from port-1 BC1.2 */ + +/* System interrupts */ +GPIO_INT(CHG_ACOK_OD, PIN(0, 0), GPIO_INT_BOTH, extpower_interrupt) /* ACOK */ +GPIO_INT(CCD_MODE_ODL, PIN(E, 3), GPIO_INT_FALLING, board_connect_c0_sbu) /* Case Closed Debug Mode */ +GPIO_INT(EC_PWR_BTN_ODL, PIN(0, 1), GPIO_INT_BOTH, power_button_interrupt) /* Power button */ +GPIO_INT(EC_VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Down button */ +GPIO_INT(EC_VOLUP_BTN_ODL, PIN(F, 2), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt) /* Volume Up button */ +GPIO_INT(EC_FLASH_WP_ODL, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protection */ +GPIO_INT(LID_OPEN_EC, PIN(D, 2), GPIO_INT_BOTH, lid_interrupt) /* Lid open */ +GPIO_INT(AP_RST_L, PIN(C, 1), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_ap_rst_interrupt) /* PMIC to signal AP reset */ +GPIO_INT(PS_HOLD, PIN(A, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) /* Indicate when AP triggers reset/shutdown */ +GPIO_INT(AP_SUSPEND, PIN(5, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Suspend signal from PMIC */ +GPIO_INT(DEPRECATED_AP_RST_REQ, PIN(C, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN | GPIO_SEL_1P8V, power_signal_interrupt) /* Deprecated AP initiated reset indicator */ + +/* + * When switch-cap is off, the POWER_GOOD signal is floating. Need a pull-down + * to make it low. Overload the interrupt function chipset_warm_reset_interrupt + * for not only signalling power_signal_interrupt but also handling the logic + * of WARM_RESET_L which is pulled-up by the same rail of POWER_GOOD. + */ +GPIO_INT(POWER_GOOD, PIN(5, 4), GPIO_INT_BOTH | GPIO_PULL_DOWN, chipset_power_good_interrupt) /* SRC_PP1800_S10A from PMIC */ +GPIO_INT(WARM_RESET_L, PIN(F, 4), GPIO_INT_BOTH | GPIO_SEL_1P8V, chipset_warm_reset_interrupt) /* AP warm reset */ +GPIO_INT(AP_EC_SPI_CS_L, PIN(5, 3), GPIO_INT_FALLING | GPIO_PULL_DOWN, shi_cs_event) /* EC SPI Chip Select */ + +GPIO_INT(BASE_DET_L, PIN(3, 7), GPIO_INT_BOTH, base_detect_interrupt) /* Detachable base attached? */ + +/* Sensor interrupts */ +GPIO_INT(ACCEL_GYRO_INT_L, PIN(A, 0), GPIO_INT_FALLING, motion_interrupt) /* Accelerometer/gyro interrupt */ + +/* Switchcap, for LN9310, it is the interrupt line of LN9310. */ +GPIO_INT(LN9310_INT, PIN(E, 2), GPIO_INT_FALLING, switchcap_interrupt) + +/* + * EC_RST_ODL acts as a wake source from hibernate mode. However, it does not + * need to be an interrupt for normal EC operations. Simply set it an INPUT. + */ +GPIO(EC_RST_ODL, PIN(0, 2), GPIO_INPUT) /* EC reset */ +GPIO(EC_ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ +GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */ + +/* PMIC/AP 1.8V */ +GPIO(PM845_RESIN_L, PIN(3, 2), GPIO_ODR_HIGH) /* PMIC reset trigger */ +GPIO(PMIC_KPD_PWR_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* PMIC power button */ +GPIO(EC_INT_L, PIN(A, 2), GPIO_ODR_HIGH) /* Interrupt line between AP and EC */ +GPIO(QSIP_ON, PIN(5, 0), GPIO_OUT_LOW) /* Not used, for non-switchcap testing */ + +/* Power enables */ +GPIO(HIBERNATE_L, PIN(5, 2), GPIO_ODR_HIGH) /* EC hibernate */ +GPIO(SWITCHCAP_ON_L, PIN(D, 5), GPIO_ODR_HIGH) /* Enable switch cap */ +GPIO(EN_PP3300_A, PIN(A, 6), GPIO_OUT_LOW) /* Enable PP3300 */ +GPIO(EN_PP5000_A, PIN(6, 7), GPIO_OUT_LOW) /* Enable PP5000 */ +GPIO(EC_BL_DISABLE_L, PIN(B, 6), GPIO_OUT_LOW) /* Backlight disable signal from EC */ + +/* Base detection */ +GPIO(EN_BASE, PIN(0, 4), GPIO_OUT_LOW) /* Enable power to detachable base */ + +/* POGO */ +GPIO(POGO_VBUS_PRESENT, PIN(6, 2), GPIO_INPUT) /* POGO PIN */ + +/* USB-C */ +GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_ODR_HIGH) /* Port-0 TCPC chip reset, actaully Open-Drain */ +GPIO(USB_C1_PD_RST_L, PIN(E, 4), GPIO_ODR_HIGH) /* Port-1 TCPC chip reset, actually Open-Drain */ +GPIO(DP_MUX_OE_L, PIN(9, 6), GPIO_ODR_HIGH) /* DP mux enable, actually Open-Drain */ +GPIO(DP_MUX_SEL, PIN(4, 5), GPIO_OUT_LOW) /* DP mux selection: L:C0, H:C1 */ +GPIO(DP_HOT_PLUG_DET, PIN(9, 5), GPIO_OUT_LOW) /* DP HPD to AP */ + +/* LEDs */ +GPIO(EC_CHG_LED_R_C0, PIN(C, 3), GPIO_OUT_LOW) +GPIO(EC_CHG_LED_G_C0, PIN(C, 4), GPIO_OUT_LOW) + +/* + * SPI host interface - enable PDs by default. These will be made functional + * by the SHI driver when the AP powers up, and restored back to GPIO when + * the AP powers down. + */ +GPIO(AP_EC_SPI_MOSI, PIN(4, 6), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_MISO, PIN(4, 7), GPIO_INPUT | GPIO_PULL_DOWN) +GPIO(AP_EC_SPI_CLK, PIN(5, 5), GPIO_INPUT | GPIO_PULL_DOWN) + +/* PWM */ +GPIO(EDP_BKLTCTL, PIN(B, 7), GPIO_INPUT) /* PWM5 */ +GPIO(WCAM_EC_VSYNC, PIN(C, 0), GPIO_INPUT) /* PWM6 */ +GPIO(FCAM_EC_VSYNC, PIN(6, 0), GPIO_INPUT) /* PWM7 */ + +/* ADC */ +GPIO(PPVAR_BOOSTIN_SENSE, PIN(4, 4), GPIO_INPUT) /* ADC1 */ +GPIO(CHARGER_IADP, PIN(4, 3), GPIO_INPUT) /* ADC2 */ +GPIO(CHARGER_PMON, PIN(4, 2), GPIO_INPUT) /* ADC3 */ + +/* I2C */ +GPIO(EC_I2C_POWER_SCL, PIN(B, 5), GPIO_INPUT) +GPIO(EC_I2C_POWER_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SCL, PIN(9, 0), GPIO_INPUT) +GPIO(EC_I2C_USB_C0_PD_SDA, PIN(8, 7), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SCL, PIN(9, 2), GPIO_INPUT) +GPIO(EC_I2C_USB_C1_PD_SDA, PIN(9, 1), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SCL, PIN(3, 3), GPIO_INPUT) +GPIO(EC_I2C_EEPROM_SDA, PIN(3, 6), GPIO_INPUT) +GPIO(EC_I2C_SENSOR_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) +GPIO(EC_I2C_SENSOR_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) + +/* Board/SKU IDs */ +GPIO(BRD_ID0, PIN(C, 7), GPIO_INPUT) +GPIO(BRD_ID1, PIN(9, 3), GPIO_INPUT) +GPIO(BRD_ID2, PIN(6, 3), GPIO_INPUT) +GPIO(SKU_ID0, PIN(F, 0), GPIO_INPUT) +GPIO(SKU_ID1, PIN(4, 1), GPIO_INPUT) +GPIO(SKU_ID2, PIN(D, 4), GPIO_INPUT) + +/* Special straps */ +GPIO(ARM_X86, PIN(6, 6), GPIO_OUT_LOW) /* NC, low for power saving */ + +/* Unused GPIOs, NC. Apply PU for power saving */ +UNUSED(PIN(5, 1)) +UNUSED(PIN(F, 3)) +UNUSED(PIN(3, 1)) +UNUSED(PIN(3, 0)) +UNUSED(PIN(2, 7)) +UNUSED(PIN(2, 6)) +UNUSED(PIN(2, 5)) +UNUSED(PIN(2, 4)) +UNUSED(PIN(2, 3)) +UNUSED(PIN(2, 2)) +UNUSED(PIN(2, 1)) +UNUSED(PIN(2, 0)) +UNUSED(PIN(1, 7)) +UNUSED(PIN(1, 6)) +UNUSED(PIN(1, 5)) +UNUSED(PIN(1, 4)) +UNUSED(PIN(1, 3)) +UNUSED(PIN(1, 2)) +UNUSED(PIN(1, 1)) +UNUSED(PIN(1, 0)) +UNUSED(PIN(0, 7)) +UNUSED(PIN(0, 6)) +UNUSED(PIN(0, 5)) +UNUSED(PIN(9, 4)) +UNUSED(PIN(9, 7)) +UNUSED(PIN(A, 7)) +UNUSED(PIN(B, 0)) +UNUSED(PIN(A, 5)) +UNUSED(PIN(3, 5)) +UNUSED(PIN(7, 2)) +UNUSED(PIN(8, 1)) +UNUSED(PIN(7, 6)) +UNUSED(PIN(3, 4)) +UNUSED(PIN(C, 5)) +UNUSED(PIN(C, 6)) +UNUSED(PIN(A, 3)) +UNUSED(PIN(8, 3)) +UNUSED(PIN(B, 1)) +UNUSED(PIN(5, 6)) +UNUSED(PIN(8, 0)) +UNUSED(PIN(D, 0)) +UNUSED(PIN(D, 1)) +UNUSED(PIN(D, 3)) +UNUSED(PIN(7, 5)) +UNUSED(PIN(8, 6)) +UNUSED(PIN(7, 3)) +UNUSED(PIN(7, 4)) +UNUSED(PIN(D, 7)) +UNUSED(PIN(8, 5)) + +/* Alternate functions GPIO definitions */ +ALTERNATE(PIN_MASK(6, 0x30), 0, MODULE_UART, 0) /* UART (GPIO64/65) */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0 (GPIOB4/B5) */ +ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1 SDA (GPIO90), I2C2 (GPIO91/92) */ +ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1 SCL (GPIO87) */ +ALTERNATE(PIN_MASK(3, 0x48), 1, MODULE_I2C, 0) /* I2C5 (GPIO33/36) */ +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, GPIO_SEL_1P8V) /* I2C7 (GPIOB2/B3) - 1.8V */ +ALTERNATE(PIN_MASK(4, 0x1C), 0, MODULE_ADC, 0) /* ADC1 (GPIO44), ADC2 (GPIO43), ADC3 (GPIO42) */ +ALTERNATE(PIN_MASK(4, 0xC0), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SDO (GPIO47), SHI_SDI (GPIO46) */ +ALTERNATE(PIN_MASK(5, 0x28), 1, MODULE_SPI, GPIO_SEL_1P8V) /* SHI_SCLK (GPIO55), SHI_CS# (GPIO53) */ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* PWM5 (GPIOB7) - EDP_BKLTCTL */ +/* TODO(Camera?) should have a poper config for this, PWM or not */ +ALTERNATE(PIN_MASK(C, 0x01), 1, MODULE_PWM, 0) /* PWM6 (GPIOC0) - WCAM_EC_VSYNC */ +ALTERNATE(PIN_MASK(6, 0x01), 1, MODULE_PWM, 0) /* PWM7 (GPIO60) - FCAM_EC_VSYNC */ + + diff --git a/board/wormdingler/led.c b/board/wormdingler/led.c new file mode 100644 index 0000000000..0b6f177b5a --- /dev/null +++ b/board/wormdingler/led.c @@ -0,0 +1,163 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Power and battery LED control. + */ + +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "chipset.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "led_common.h" +#include "system.h" +#include "util.h" + +#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) +/* Battery LED blinks every per 400ms */ +#define LED_HALF_ONE_SEC (500 / HOOK_TICK_INTERVAL_MS) + +#define BAT_LED_ON 1 +#define BAT_LED_OFF 0 + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_OFF = 0, + LED_RED, + LED_GREEN, + LED_AMBER, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static void led_set_color(enum led_color color) +{ + gpio_set_level(GPIO_EC_CHG_LED_R_C0, + (color == LED_RED) ? BAT_LED_ON : BAT_LED_OFF); + gpio_set_level(GPIO_EC_CHG_LED_G_C0, + (color == LED_GREEN) ? BAT_LED_ON : BAT_LED_OFF); + if (color == LED_AMBER) { + gpio_set_level(GPIO_EC_CHG_LED_R_C0, BAT_LED_ON); + gpio_set_level(GPIO_EC_CHG_LED_G_C0, BAT_LED_ON); + } +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 1; + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_AMBER] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED] != 0) + led_set_color(LED_RED); + else if (brightness[EC_LED_COLOR_GREEN] != 0) + led_set_color(LED_GREEN); + else if (brightness[EC_LED_COLOR_AMBER] != 0) + led_set_color(LED_AMBER); + else + led_set_color(LED_OFF); + + return EC_SUCCESS; +} + +static void board_led_set_battery(void) +{ + static int battery_ticks; + int color = LED_OFF; + int period = 0; + int percent = DIV_ROUND_NEAREST(charge_get_display_charge(), 10); + + battery_ticks++; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: + case LED_PWRS_CHARGE_NEAR_FULL: + if (chipset_in_state(CHIPSET_STATE_ON | + CHIPSET_STATE_ANY_SUSPEND | + CHIPSET_STATE_ANY_OFF)) { + if (percent <= BATTERY_LEVEL_CRITICAL) { + /* battery capa <= 5%, Red */ + color = LED_RED; + } else if (percent > BATTERY_LEVEL_CRITICAL && + percent < CONFIG_BATT_HOST_FULL_FACTOR) { + /* 5% < battery capa < 97%, Orange */ + color = LED_AMBER; + } else { + /* battery capa >= 97%, Green */ + color = LED_GREEN; + } + } + break; + case LED_PWRS_DISCHARGE: + /* Always indicate off on when discharging */ + color = LED_OFF; + break; + case LED_PWRS_ERROR: + /* Battery error, Red on 1sec off 1sec */ + period = (1 + 1) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 1 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_OFF; + break; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + color = LED_RED; + break; + case LED_PWRS_FORCED_IDLE: + /* Factory mode, Red 2 sec, green 2 sec */ + period = (2 + 2) * LED_ONE_SEC; + battery_ticks = battery_ticks % period; + if (battery_ticks < 2 * LED_ONE_SEC) + color = LED_RED; + else + color = LED_GREEN; + break; + default: + /* Other states don't alter LED behavior */ + break; + } + + led_set_color(color); +} + +/* Called by hook task every TICK */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + board_led_set_battery(); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +void led_control(enum ec_led_id led_id, enum ec_led_state state) +{ + enum led_color color; + + if ((led_id != EC_LED_ID_RECOVERY_HW_REINIT_LED) && + (led_id != EC_LED_ID_SYSRQ_DEBUG_LED)) + return; + + if (state == LED_STATE_RESET) { + led_auto_control(EC_LED_ID_BATTERY_LED, 1); + board_led_set_battery(); + return; + } + + color = state ? LED_RED : LED_OFF; + + led_auto_control(EC_LED_ID_BATTERY_LED, 0); + + led_set_color(color); +} diff --git a/board/wormdingler/usbc_config.c b/board/wormdingler/usbc_config.c new file mode 100644 index 0000000000..28f6b7a1c9 --- /dev/null +++ b/board/wormdingler/usbc_config.c @@ -0,0 +1,61 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Trogdor family-specific USB-C configuration */ + +#include "charge_state.h" +#include "charger.h" +#include "charger/isl923x_public.h" +#include "console.h" +#include "usb_pd.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +const struct charger_config_t chg_chips[] = { + { + .i2c_port = I2C_PORT_CHARGER, + .i2c_addr_flags = ISL923X_ADDR_FLAGS, + .drv = &isl923x_drv, + }, +}; + +int charger_profile_override(struct charge_state_data *curr) +{ + int usb_mv; + int port; + + if (curr->state != ST_CHARGE) + return 0; + + /* Lower the max requested voltage to 5V when battery is full. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && + !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && + (curr->batt.status & STATUS_FULLY_CHARGED)) + usb_mv = 5000; + else + usb_mv = PD_MAX_VOLTAGE_MV; + + if (pd_get_max_voltage() != usb_mv) { + CPRINTS("VBUS limited to %dmV", usb_mv); + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) + pd_set_external_voltage_limit(port, usb_mv); + } + + return 0; +} + +enum ec_status charger_profile_override_get_param(uint32_t param, + uint32_t *value) +{ + return EC_RES_INVALID_PARAM; +} + +enum ec_status charger_profile_override_set_param(uint32_t param, + uint32_t value) +{ + return EC_RES_INVALID_PARAM; +} diff --git a/board/wormdingler/vif_override.xml b/board/wormdingler/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/wormdingler/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/yorp/battery.c b/board/yorp/battery.c index 1d8ec33d3d..d391942ab3 100644 --- a/board/yorp/battery.c +++ b/board/yorp/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/board/yorp/board.c b/board/yorp/board.c index 1d4597311a..475ced087c 100644 --- a/board/yorp/board.c +++ b/board/yorp/board.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* Yorp board-specific configuration */ #include "adc.h" -#include "adc_chip.h" #include "battery.h" #include "charge_manager.h" #include "charge_state.h" @@ -32,17 +31,17 @@ #include "switch.h" #include "system.h" #include "tablet_mode.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "temp_sensor.h" -#include "thermistor.h" +#include "temp_sensor/thermistor.h" #include "usb_mux.h" #include "usbc_ppc.h" #include "util.h" -#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ##args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) static void ppc_interrupt(enum gpio_signal signal) { @@ -65,26 +64,26 @@ static void ppc_interrupt(enum gpio_signal signal) /* ADC channels */ const struct adc_t adc_channels[] = { - [ADC_TEMP_SENSOR_AMB] = { - "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, - [ADC_TEMP_SENSOR_CHARGER] = { - "TEMP_CHARGER", NPCX_ADC_CH1, ADC_MAX_VOLT, ADC_READ_MAX+1, 0}, + [ADC_TEMP_SENSOR_AMB] = { "TEMP_AMB", NPCX_ADC_CH0, ADC_MAX_VOLT, + ADC_READ_MAX + 1, 0 }, + [ADC_TEMP_SENSOR_CHARGER] = { "TEMP_CHARGER", NPCX_ADC_CH1, + ADC_MAX_VOLT, ADC_READ_MAX + 1, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); const struct temp_sensor_t temp_sensors[] = { - [TEMP_SENSOR_BATTERY] = {.name = "Battery", - .type = TEMP_SENSOR_TYPE_BATTERY, - .read = charge_get_battery_temp, - .idx = 0}, - [TEMP_SENSOR_AMBIENT] = {.name = "Ambient", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_51k1_47k_4050b, - .idx = ADC_TEMP_SENSOR_AMB}, - [TEMP_SENSOR_CHARGER] = {.name = "Charger", - .type = TEMP_SENSOR_TYPE_BOARD, - .read = get_temp_3v3_13k7_47k_4050b, - .idx = ADC_TEMP_SENSOR_CHARGER}, + [TEMP_SENSOR_BATTERY] = { .name = "Battery", + .type = TEMP_SENSOR_TYPE_BATTERY, + .read = charge_get_battery_temp, + .idx = 0 }, + [TEMP_SENSOR_AMBIENT] = { .name = "Ambient", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_51k1_47k_4050b, + .idx = ADC_TEMP_SENSOR_AMB }, + [TEMP_SENSOR_CHARGER] = { .name = "Charger", + .type = TEMP_SENSOR_TYPE_BOARD, + .read = get_temp_3v3_13k7_47k_4050b, + .idx = ADC_TEMP_SENSOR_CHARGER }, }; BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); @@ -94,11 +93,9 @@ static struct mutex g_lid_mutex; static struct mutex g_base_mutex; /* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - { 0, FLOAT_TO_FP(-1), 0}, - { FLOAT_TO_FP(1), 0, 0}, - { 0, 0, FLOAT_TO_FP(1)} -}; +const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(-1), 0 }, + { FLOAT_TO_FP(1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(1) } }; /* sensor private data */ static struct kionix_accel_data g_kx022_data; @@ -143,8 +140,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_ACCEL), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .rot_standard_ref = &base_standard_ref, @@ -175,8 +170,6 @@ struct motion_sensor_t motion_sensors[] = { .mutex = &g_base_mutex, .drv_data = LSM6DSM_ST_DATA(lsm6dsm_data, MOTIONSENSE_TYPE_GYRO), - .int_signal = GPIO_BASE_SIXAXIS_INT_L, - .flags = MOTIONSENSE_FLAG_INT_SIGNAL, .port = I2C_PORT_SENSOR, .i2c_spi_addr_flags = LSM6DSM_ADDR0_FLAGS, .default_range = 1000 | ROUND_UP_FLAG, /* dps */ @@ -196,14 +189,14 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); -void board_hibernate_late(void) { - +void board_hibernate_late(void) +{ int i; const uint32_t hibernate_pins[][2] = { /* Turn off LEDs before going to hibernate */ - {GPIO_BAT_LED_BLUE_L, GPIO_INPUT | GPIO_PULL_UP}, - {GPIO_BAT_LED_ORANGE_L, GPIO_INPUT | GPIO_PULL_UP}, + { GPIO_BAT_LED_BLUE_L, GPIO_INPUT | GPIO_PULL_UP }, + { GPIO_BAT_LED_ORANGE_L, GPIO_INPUT | GPIO_PULL_UP }, }; for (i = 0; i < ARRAY_SIZE(hibernate_pins); ++i) @@ -211,25 +204,6 @@ void board_hibernate_late(void) { } #ifndef TEST_BUILD -/* This callback disables keyboard when convertibles are fully open */ -void lid_angle_peripheral_enable(int enable) -{ - int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); - - if (enable) { - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - } else { - /* - * Ensure that the chipset is off before disabling the keyboard. - * When the chipset is on, the EC keeps the keyboard enabled and - * the AP decides whether to ignore input devices or not. - */ - if (!chipset_in_s0) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); - } -} - - static void post_old_board_warning(void) { uint32_t board_id = 0; @@ -244,7 +218,7 @@ static void post_old_board_warning(void) * warning. */ CPRINTS("\n\n\n ***** BOARD ID 0 is not officially supported!!! *****" - "\n\n\n"); + "\n\n\n"); } DECLARE_HOOK(HOOK_INIT, post_old_board_warning, HOOK_PRIO_INIT_I2C + 1); #endif diff --git a/board/yorp/board.h b/board/yorp/board.h index 01f701184a..8ffb6d2781 100644 --- a/board/yorp/board.h +++ b/board/yorp/board.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,6 +13,8 @@ #define VARIANT_OCTOPUS_CHARGER_ISL9238 #include "baseboard.h" +#define GPIO_PG_EC_RSMRST_ODL GPIO_RSMRST_L_PGOOD + /* EC console commands */ #define CONFIG_CMD_ACCELS #define CONFIG_CMD_ACCEL_INFO @@ -24,8 +26,8 @@ #define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT /* Sensors */ -#define CONFIG_ACCEL_KX022 /* Lid accel */ -#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ +#define CONFIG_ACCEL_KX022 /* Lid accel */ +#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */ /* Sensors without hardware FIFO are in forced mode */ #define CONFIG_ACCEL_FORCE_MODE_MASK BIT(LID_ACCEL) @@ -48,8 +50,8 @@ #include "registers.h" enum adc_channel { - ADC_TEMP_SENSOR_AMB, /* ADC0 */ - ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ + ADC_TEMP_SENSOR_AMB, /* ADC0 */ + ADC_TEMP_SENSOR_CHARGER, /* ADC1 */ ADC_CH_COUNT }; @@ -60,18 +62,10 @@ enum temp_sensor_id { TEMP_SENSOR_COUNT }; -enum pwm_channel { - PWM_CH_KBLIGHT, - PWM_CH_COUNT -}; +enum pwm_channel { PWM_CH_KBLIGHT, PWM_CH_COUNT }; /* Motion sensors */ -enum sensor_id { - LID_ACCEL, - BASE_ACCEL, - BASE_GYRO, - SENSOR_COUNT -}; +enum sensor_id { LID_ACCEL, BASE_ACCEL, BASE_GYRO, SENSOR_COUNT }; /* List of possible batteries */ enum battery_type { diff --git a/board/yorp/build.mk b/board/yorp/build.mk index 3d04b75731..998a65a3de 100644 --- a/board/yorp/build.mk +++ b/board/yorp/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/board/yorp/ec.tasklist b/board/yorp/ec.tasklist index d98db145e7..977b8b01be 100644 --- a/board/yorp/ec.tasklist +++ b/board/yorp/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/yorp/gpio.inc b/board/yorp/gpio.inc index 9edd6107c6..b3dbf60ab8 100644 --- a/board/yorp/gpio.inc +++ b/board/yorp/gpio.inc @@ -1,6 +1,6 @@ /* -*- mode:c -*- * - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/yorp/led.c b/board/yorp/led.c index e5dd48327b..f8b9898046 100644 --- a/board/yorp/led.c +++ b/board/yorp/led.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,34 +10,44 @@ #include "led_common.h" #include "led_onoff_states.h" -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 +#define LED_OFF_LVL 1 +#define LED_ON_LVL 0 -const int led_charge_lvl_1 = 0; +__override const int led_charge_lvl_1; -const int led_charge_lvl_2 = 100; +__override const int led_charge_lvl_2 = 100; /* Yorp: Note there is only LED for charge / power */ -struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{EC_LED_COLOR_AMBER, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_BLUE, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_AMBER, 2 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_BLUE, LED_INDEFINITE} }, -}; +__override struct led_descriptor + led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { + [STATE_CHARGING_LVL_1] = { { EC_LED_COLOR_BLUE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + [STATE_CHARGING_LVL_2] = { { EC_LED_COLOR_AMBER, + LED_INDEFINITE } }, + [STATE_CHARGING_FULL_CHARGE] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S0] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + [STATE_DISCHARGE_S3] = { { EC_LED_COLOR_AMBER, + 1 * LED_ONE_SEC }, + { LED_OFF, 3 * LED_ONE_SEC } }, + [STATE_DISCHARGE_S5] = { { LED_OFF, LED_INDEFINITE } }, + [STATE_BATTERY_ERROR] = { { EC_LED_COLOR_BLUE, + 2 * LED_ONE_SEC }, + { EC_LED_COLOR_AMBER, + 2 * LED_ONE_SEC } }, + [STATE_FACTORY_TEST] = { { EC_LED_COLOR_BLUE, + LED_INDEFINITE } }, + }; BUILD_ASSERT(ARRAY_SIZE(led_bat_state_table) == LED_NUM_STATES); const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); -void led_set_color_battery(enum ec_led_colors color) +__override void led_set_color_battery(enum ec_led_colors color) { switch (color) { case EC_LED_COLOR_BLUE: @@ -72,4 +82,3 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } - diff --git a/board/yorp/vif_override.xml b/board/yorp/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/yorp/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/board/zinger/board.c b/board/zinger/board.c index 74da1ca9eb..41d91ab438 100644 --- a/board/zinger/board.c +++ b/board/zinger/board.c @@ -1,10 +1,11 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Tiny charger configuration */ #include "common.h" +#include "cros_version.h" #include "debug_printf.h" #include "ec_commands.h" #include "registers.h" @@ -15,19 +16,16 @@ #include "task.h" #include "usb_pd.h" #include "util.h" -#include "version.h" /* Large 768-Byte buffer for RSA computation : could be re-use afterwards... */ static uint32_t rsa_workbuf[3 * RSANUMWORDS]; -extern void pd_rx_handler(void); - /* RW firmware reset vector */ -static uint32_t * const rw_rst = - (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE+CONFIG_RW_MEM_OFF+4); +static uint32_t *const rw_rst = + (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF + 4); /* External interrupt EXTINT7 for external comparator on PA7 */ -void pd_rx_interrupt(void) +static void pd_rx_interrupt(void) { /* trigger reception handling */ pd_rx_handler(); @@ -40,7 +38,7 @@ static void jump_to_rw(void) debug_printf("Jump to RW\n"); /* Disable interrupts */ - asm volatile("cpsid i"); + interrupt_disable(); /* Call RW firmware reset vector */ jump_rw_rst(); } @@ -59,8 +57,8 @@ static int check_rw_valid(void *rw_hash) return 0; good = rsa_verify((const struct rsa_public_key *)CONFIG_RO_PUBKEY_ADDR, - (const uint8_t *)CONFIG_RW_SIG_ADDR, - rw_hash, rsa_workbuf); + (const uint8_t *)CONFIG_RW_SIG_ADDR, rw_hash, + rsa_workbuf); if (!good) { debug_printf("RSA FAILED\n"); pd_log_event(PD_EVENT_ACC_RW_FAIL, 0, 0, NULL); @@ -77,8 +75,7 @@ int main(void) void *rw_hash; hardware_init(); - debug_printf("%s started\n", - is_ro_mode() ? "RO" : "RW"); + debug_printf("%s started\n", is_ro_mode() ? "RO" : "RW"); /* the RO partition protection is not enabled : do it */ if (!flash_physical_is_permanently_protected()) diff --git a/board/zinger/board.h b/board/zinger/board.h index 30abce115a..1ca83354bc 100644 --- a/board/zinger/board.h +++ b/board/zinger/board.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -37,11 +37,11 @@ #undef CONFIG_DEBUG_ASSERT #undef CONFIG_DEBUG_EXCEPTIONS #undef CONFIG_DEBUG_STACK_OVERFLOW -#undef CONFIG_FLASH +#undef CONFIG_FLASH_CROS #undef CONFIG_FLASH_PHYSICAL #undef CONFIG_FMAP /* Not using pstate but keep some space for the public key */ -#undef CONFIG_FW_PSTATE_SIZE +#undef CONFIG_FW_PSTATE_SIZE #define CONFIG_FW_PSTATE_SIZE 544 #define CONFIG_HIBERNATE #define CONFIG_HIBERNATE_WAKEUP_PINS STM32_PWR_CSR_EWUP1 @@ -59,7 +59,7 @@ #undef CONFIG_USB_PD_DUAL_ROLE #undef CONFIG_USB_PD_INTERNAL_COMP #define CONFIG_USB_PD_LOGGING -#undef CONFIG_EVENT_LOG_SIZE +#undef CONFIG_EVENT_LOG_SIZE #define CONFIG_EVENT_LOG_SIZE 256 #define CONFIG_USB_PD_LOW_POWER_IDLE_WHEN_CONNECTED #define CONFIG_USB_PD_PORT_MAX_COUNT 1 @@ -73,8 +73,8 @@ #undef CONFIG_WATCHDOG_PERIOD_MS #define CONFIG_WATCHDOG_PERIOD_MS 2300 -/* debug printf flash footprinf is about 1400 bytes */ -#define CONFIG_DEBUG_PRINTF +/* debug printf flash footprint is about 1400 bytes */ +#undef CONFIG_DEBUG_PRINTF #define UARTN CONFIG_UART_CONSOLE #define UARTN_BASE STM32_USART_BASE(CONFIG_UART_CONSOLE) @@ -90,9 +90,9 @@ #ifndef __ASSEMBLER__ #include "common.h" +#include "gpio_signal.h" /* No GPIO abstraction layer */ -enum gpio_signal; enum adc_channel { ADC_CH_CC1_PD = 1, @@ -105,10 +105,11 @@ enum adc_channel { #define ADC_CH_CC2_PD ADC_CH_CC1_PD /* 3.0A Rp */ -#define PD_SRC_VNC (PD_SRC_3_0_VNC_MV * 4096 / 3300/* 12-bit ADC, 3.3V range */) +#define PD_SRC_VNC \ + (PD_SRC_3_0_VNC_MV * 4096 / 3300 /* 12-bit ADC, 3.3V range */) /* delay necessary for the voltage transition on the power supply */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ #define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ /* Initialize all useful registers */ diff --git a/board/zinger/build.mk b/board/zinger/build.mk index 566cf34ce0..da1878efe9 100644 --- a/board/zinger/build.mk +++ b/board/zinger/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,4 +10,4 @@ CHIP:=stm32 CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f03x -board-y=board.o hardware.o runtime.o usb_pd_policy.o +board-y=board.o hardware.o runtime.o usb_pd_policy.o usb_pd_pdo.o diff --git a/board/zinger/ec.irqlist b/board/zinger/ec.irqlist index 690fa950fc..186c0f6338 100644 --- a/board/zinger/ec.irqlist +++ b/board/zinger/ec.irqlist @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/zinger/ec.tasklist b/board/zinger/ec.tasklist index 091eb90a22..89d9ffab76 100644 --- a/board/zinger/ec.tasklist +++ b/board/zinger/ec.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/board/zinger/gpio.inc b/board/zinger/gpio.inc new file mode 100644 index 0000000000..65e3066695 --- /dev/null +++ b/board/zinger/gpio.inc @@ -0,0 +1,8 @@ +/* -*- mode:c -*- + * + * Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Stub file only */ \ No newline at end of file diff --git a/board/zinger/hardware.c b/board/zinger/hardware.c index ceeac38d38..0ad5b7ff94 100644 --- a/board/zinger/hardware.c +++ b/board/zinger/hardware.c @@ -1,11 +1,10 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Hardware initialization and common functions */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "cpu.h" #include "registers.h" @@ -40,16 +39,16 @@ static void power_init(void) /* enable TIM2, TIM3, TIM14, PWR */ STM32_RCC_APB1ENR = 0x10000103; /* enable DMA, SRAM, CRC, GPA, GPB, GPF */ - STM32_RCC_AHBENR = 0x460045; + STM32_RCC_AHBENR = 0x460045; } /* GPIO setting helpers */ -#define OUT(n) (1 << ((n) * 2)) -#define AF(n) (2 << ((n) * 2)) -#define ANALOG(n) (3 << ((n) * 2)) +#define OUT(n) (1 << ((n)*2)) +#define AF(n) (2 << ((n)*2)) +#define ANALOG(n) (3 << ((n)*2)) #define HIGH(n) (1 << (n)) #define ODR(n) (1 << (n)) -#define HISPEED(n) (3 << ((n) * 2)) +#define HISPEED(n) (3 << ((n)*2)) #define AFx(n, x) (x << (((n) % 8) * 4)) static void pins_init(void) @@ -84,9 +83,9 @@ static void pins_init(void) STM32_GPIO_AFRH(GPIO_A) = AFx(9, 1) | AFx(10, 1); STM32_GPIO_OTYPER(GPIO_A) = ODR(4); STM32_GPIO_OSPEEDR(GPIO_A) = HISPEED(5) | HISPEED(6) | HISPEED(7); - STM32_GPIO_MODER(GPIO_A) = OUT(0) | ANALOG(1) | ANALOG(2) | ANALOG(3) - | OUT(4) | AF(5) /*| AF(6)*/ | AF(7) | AF(9) - | AF(10) | OUT(13) | OUT(14); + STM32_GPIO_MODER(GPIO_A) = OUT(0) | ANALOG(1) | ANALOG(2) | ANALOG(3) | + OUT(4) | AF(5) /*| AF(6)*/ | AF(7) | AF(9) | + AF(10) | OUT(13) | OUT(14); /* set PF0 / PF1 as output */ STM32_GPIO_ODR(GPIO_F) = 0; STM32_GPIO_MODER(GPIO_F) = OUT(0) | OUT(1); @@ -108,7 +107,8 @@ static void adc_init(void) ; } /* Single conversion, right aligned, 12-bit */ - STM32_ADC_CFGR1 = BIT(12); /* BIT(15) => AUTOOFF */; + STM32_ADC_CFGR1 = BIT(12); /* BIT(15) => AUTOOFF */ + ; /* clock is ADCCLK (ADEN must be off when writing this reg) */ STM32_ADC_CFGR2 = 0; /* Sampling time : 71.5 ADC clock cycles, about 5us */ @@ -133,8 +133,8 @@ static void uart_init(void) STM32_USART_BRR(UARTN_BASE) = DIV_ROUND_NEAREST(CPU_CLOCK, CONFIG_UART_BAUD_RATE); /* UART enabled, 8 Data bits, oversampling x16, no parity */ - STM32_USART_CR1(UARTN_BASE) = - STM32_USART_CR1_UE | STM32_USART_CR1_TE | STM32_USART_CR1_RE; + STM32_USART_CR1(UARTN_BASE) = STM32_USART_CR1_UE | STM32_USART_CR1_TE | + STM32_USART_CR1_RE; /* 1 stop bit, no fancy stuff */ STM32_USART_CR2(UARTN_BASE) = 0x0000; /* DMA disabled, special modes disabled, error interrupt disabled */ @@ -201,7 +201,7 @@ static int watchdog_ain_id, watchdog_ain_high, watchdog_ain_low; static int adc_enable_last_watchdog(void) { return adc_enable_watchdog(watchdog_ain_id, watchdog_ain_high, - watchdog_ain_low); + watchdog_ain_low); } static inline int adc_watchdog_enabled(void) @@ -249,8 +249,7 @@ int adc_enable_watchdog(int ch, int high, int low) /* Clear flags */ STM32_ADC_ISR = 0x8e; /* Set Watchdog enable bit on a single channel / continuous mode */ - STM32_ADC_CFGR1 = (ch << 26) | BIT(23) | BIT(22) - | BIT(13) | BIT(12); + STM32_ADC_CFGR1 = (ch << 26) | BIT(23) | BIT(22) | BIT(13) | BIT(12); /* Enable watchdog interrupt */ STM32_ADC_IER = BIT(7); /* Start continuous conversion */ @@ -290,25 +289,26 @@ int adc_disable_watchdog(void) (FLASH_TIMEOUT_US * (CPU_CLOCK / SECOND) / CYCLE_PER_FLASH_LOOP) /* Flash unlocking keys */ -#define KEY1 0x45670123 -#define KEY2 0xCDEF89AB +#define KEY1 0x45670123 +#define KEY2 0xCDEF89AB /* Lock bits for FLASH_CR register */ -#define PG BIT(0) -#define PER BIT(1) -#define OPTPG BIT(4) -#define OPTER BIT(5) -#define STRT BIT(6) -#define CR_LOCK BIT(7) -#define OPTWRE BIT(9) - -int flash_physical_write(int offset, int size, const char *data) +#define PG BIT(0) +#define PER BIT(1) +#define OPTPG BIT(4) +#define OPTER BIT(5) +#define STRT BIT(6) +#define CR_LOCK BIT(7) +#define OPTWRE BIT(9) + +int crec_flash_physical_write(int offset, int size, const char *data) { uint16_t *address = (uint16_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset); int res = EC_SUCCESS; int i; - if ((uint32_t)address > CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_SIZE) + if ((uint32_t)address > + CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; /* unlock CR if needed */ @@ -353,7 +353,7 @@ int flash_physical_write(int offset, int size, const char *data) return res; } -int flash_physical_erase(int offset, int size) +int crec_flash_physical_erase(int offset, int size) { int res = EC_SUCCESS; @@ -369,14 +369,13 @@ int flash_physical_erase(int offset, int size) STM32_FLASH_CR |= PER; for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE, - offset += CONFIG_FLASH_ERASE_SIZE) { + offset += CONFIG_FLASH_ERASE_SIZE) { int i; /* select page to erase */ STM32_FLASH_AR = CONFIG_PROGRAM_MEMORY_BASE + offset; /* set STRT bit : start erase */ STM32_FLASH_CR |= STRT; - /* Wait for erase to complete */ for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); i++) @@ -434,7 +433,6 @@ static void unlock_erase_optb(void) STM32_FLASH_CR = OPTWRE; } - static void write_optb(int byte, uint8_t value) { volatile int16_t *hword = (uint16_t *)(STM32_OPTB_BASE + byte); @@ -464,7 +462,7 @@ void flash_physical_permanent_protect(void) /* Set RDP to level 1 to prevent disabling the protection */ write_optb(0, 0x11); /* Reset by using OBL_LAUNCH to take changes into account */ - asm volatile("cpsid i"); + interrupt_disable(); STM32_FLASH_CR |= FLASH_CR_OBL_LAUNCH; /* Spin and wait for reboot; should never return */ while (1) @@ -475,6 +473,6 @@ int flash_physical_is_permanently_protected(void) { /* if RDP is still at level 0, the flash protection is not in place */ return (STM32_FLASH_OBR & STM32_FLASH_OBR_RDP_MASK) && - /* the low 16KB (RO partition) are write-protected */ - !(STM32_FLASH_WRPR & 0xF); + /* the low 16KB (RO partition) are write-protected */ + !(STM32_FLASH_WRPR & 0xF); } diff --git a/board/zinger/runtime.c b/board/zinger/runtime.c index da1a11a7ee..25d09d797c 100644 --- a/board/zinger/runtime.c +++ b/board/zinger/runtime.c @@ -1,9 +1,10 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* tiny substitute of the runtime layer */ +#include "atomic.h" #include "chip/stm32/clock-f.h" #include "clock.h" #include "common.h" @@ -16,7 +17,7 @@ #include "util.h" volatile uint32_t last_event; -uint32_t sleep_mask; +atomic_t sleep_mask; /* High word of the 64-bit timestamp counter */ static volatile uint32_t clksrc_high; @@ -35,9 +36,9 @@ void force_time(timestamp_t ts) STM32_TIM32_CNT(2) = ts.le.lo; } -void udelay(unsigned us) +void udelay(unsigned int us) { - unsigned t0 = STM32_TIM32_CNT(2); + unsigned int t0 = STM32_TIM32_CNT(2); while ((STM32_TIM32_CNT(2) - t0) < us) ; } @@ -67,14 +68,12 @@ void interrupt_enable(void) asm("cpsie i"); } -uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait) +void task_set_event(task_id_t tskid, uint32_t event) { last_event = event; - - return 0; } -void tim2_interrupt(void) +static void tim2_interrupt(void) { uint32_t stat = STM32_TIM_SR(2); @@ -107,7 +106,7 @@ static void zinger_config_hispeed_clock(void) STM32_RCC_CR |= BIT(24); /* Wait for PLL to be ready */ while (!(STM32_RCC_CR & BIT(25))) - ; + ; /* switch SYSCLK to PLL */ STM32_RCC_CFGR = 0x00288002; @@ -136,7 +135,7 @@ void runtime_init(void) * SET_RTC_MATCH_DELAY: max time to set RTC match alarm. if we set the alarm * in the past, it will never wake up and cause a watchdog. */ -#define STOP_MODE_LATENCY 300 /* us */ +#define STOP_MODE_LATENCY 300 /* us */ #define SET_RTC_MATCH_DELAY 200 /* us */ #define MAX_LATENCY (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY) @@ -148,7 +147,7 @@ uint32_t task_wait_event(int timeout_us) t1.val = get_time().val + timeout_us; - asm volatile("cpsid i"); + interrupt_disable(); /* the event already happened */ if (last_event || !timeout_us) { evt = last_event; @@ -162,10 +161,10 @@ uint32_t task_wait_event(int timeout_us) while (1) { /* set timeout on timer */ if (timeout_us < 0) { - asm volatile ("wfi"); + asm volatile("wfi"); } else if (timeout_us <= MAX_LATENCY || - t1.le.lo - timeout_us > t1.le.lo + MAX_LATENCY || - !DEEP_SLEEP_ALLOWED) { + t1.le.lo - timeout_us > t1.le.lo + MAX_LATENCY || + !DEEP_SLEEP_ALLOWED) { STM32_TIM32_CCR1(2) = STM32_TIM32_CNT(2) + timeout_us; STM32_TIM_DIER(2) = 3; /* match interrupt and UIE */ @@ -178,8 +177,8 @@ uint32_t task_wait_event(int timeout_us) /* set deep sleep bit */ CPU_SCB_SYSCTRL |= 0x4; - set_rtc_alarm(0, timeout_us - STOP_MODE_LATENCY, - &rtc0, 0); + set_rtc_alarm(0, timeout_us - STOP_MODE_LATENCY, &rtc0, + 0); asm volatile("wfi"); @@ -195,7 +194,7 @@ uint32_t task_wait_event(int timeout_us) asm volatile("cpsie i ; isb"); /* note: interrupt that woke us up will run here */ - asm volatile("cpsid i"); + interrupt_disable(); t0 = get_time(); /* check for timeout if timeout was set */ @@ -229,16 +228,15 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) /* Restore any pending events not in the event_mask */ if (evt & ~event_mask) - task_set_event(0, evt & ~event_mask, 0); + task_set_event(0, evt & ~event_mask); return evt & event_mask; } -noreturn -void __keep cpu_reset(void) +noreturn void __keep cpu_reset(void) { /* Disable interrupts */ - asm volatile("cpsid i"); + interrupt_disable(); /* reboot the CPU */ CPU_NVIC_APINT = 0x05fa0004; /* Spin and wait for reboot; should never return */ @@ -258,17 +256,18 @@ void system_reset(int flags) void exception_panic(void) __attribute__((naked)); void exception_panic(void) { -#ifdef CONFIG_DEBUG_PRINTF asm volatile( +#ifdef CONFIG_DEBUG_PRINTF "mov r0, %0\n" /* TODO: Should this be SP_process instead of SP_main? */ "mov r3, sp\n" "ldr r1, [r3, #6*4]\n" /* retrieve exception PC */ "ldr r2, [r3, #5*4]\n" /* retrieve exception LR */ "bl debug_printf\n" - : : "r"("PANIC PC=%08x LR=%08x\n\n")); #endif - cpu_reset(); + "bl cpu_reset\n" + : + : "r"("PANIC PC=%08x LR=%08x\n\n")); } void panic_reboot(void) @@ -287,7 +286,9 @@ enum ec_image system_get_image_copy(void) /* --- stubs --- */ void __hw_timer_enable_clock(int n, int enable) -{ /* Done in hardware init */ } +{ /* Done in hardware init */ +} -void usleep(unsigned us) -{ /* Used only as a workaround */ } +void usleep(unsigned int us) +{ /* Used only as a workaround */ +} diff --git a/board/zinger/usb_pd_config.h b/board/zinger/usb_pd_config.h index d0797b3d80..c3d86e2c2b 100644 --- a/board/zinger/usb_pd_config.h +++ b/board/zinger/usb_pd_config.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,7 +10,7 @@ /* Timer selection for baseband PD communication */ #define TIM_CLOCK_PD_TX_C0 14 -#define TIM_CLOCK_PD_RX_C0 3 +#define TIM_CLOCK_PD_RX_C0 3 #define TIM_CLOCK_PD_TX(p) TIM_CLOCK_PD_TX_C0 #define TIM_CLOCK_PD_RX(p) TIM_CLOCK_PD_RX_C0 @@ -46,7 +46,7 @@ static inline void spi_enable_clock(int port) #define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 #define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 /* connect TIM3 CH1 to TIM3_CH2 input */ -#define TIM_CCR_CS 2 +#define TIM_CCR_CS 2 #define EXTI_COMP_MASK(p) BIT(7) #define IRQ_COMP STM32_IRQ_EXTI4_15 /* the RX is inverted, triggers on rising edge */ @@ -72,7 +72,7 @@ static inline void pd_tx_spi_reset(int port) static inline void pd_tx_enable(int port, int polarity) { /* Drive SPI MISO on PA6 by putting it in AF mode */ - STM32_GPIO_MODER(GPIO_A) |= 0x2 << (2*6); + STM32_GPIO_MODER(GPIO_A) |= 0x2 << (2 * 6); /* Drive TX GND on PA4 */ STM32_GPIO_BSRR(GPIO_A) = 1 << (4 + 16 /* Reset */); } @@ -83,7 +83,7 @@ static inline void pd_tx_disable(int port, int polarity) /* Put TX GND (PA4) in Hi-Z state */ STM32_GPIO_BSRR(GPIO_A) = BIT(4) /* Set */; /* Put SPI MISO (PA6) in Hi-Z by putting it in input mode */ - STM32_GPIO_MODER(GPIO_A) &= ~(0x3 << (2*6)); + STM32_GPIO_MODER(GPIO_A) &= ~(0x3 << (2 * 6)); } /* we know the plug polarity, do the right configuration */ @@ -98,7 +98,9 @@ static inline void pd_tx_init(void) /* Already done in hardware_init() */ } -static inline void pd_config_init(int port, uint8_t power_role) {} +static inline void pd_config_init(int port, uint8_t power_role) +{ +} static inline int pd_adc_read(int port, int cc) { diff --git a/board/zinger/usb_pd_pdo.c b/board/zinger/usb_pd_pdo.c new file mode 100644 index 0000000000..36be87bd78 --- /dev/null +++ b/board/zinger/usb_pd_pdo.c @@ -0,0 +1,17 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" +#include "usb_pd.h" +#include "usb_pd_pdo.h" + +/* Power Delivery Objects */ +const uint32_t pd_src_pdo[] = { + [PDO_IDX_5V] = PDO_FIXED(5000, RATED_CURRENT, PDO_FIXED_FLAGS), + [PDO_IDX_12V] = PDO_FIXED(12000, RATED_CURRENT, PDO_FIXED_FLAGS), + [PDO_IDX_20V] = PDO_FIXED(20000, RATED_CURRENT, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +BUILD_ASSERT(ARRAY_SIZE(pd_src_pdo) == PDO_IDX_COUNT); diff --git a/board/zinger/usb_pd_pdo.h b/board/zinger/usb_pd_pdo.h new file mode 100644 index 0000000000..45f6668077 --- /dev/null +++ b/board/zinger/usb_pd_pdo.h @@ -0,0 +1,30 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_BOARD_ZINGER_USB_PD_PDO_H +#define __CROS_EC_BOARD_ZINGER_USB_PD_PDO_H + +/* Max current */ +#if defined(BOARD_ZINGER) +#define RATED_CURRENT 3000 +#elif defined(BOARD_MINIMUFFIN) +#define RATED_CURRENT 2250 +#endif + +/* Voltage indexes for the PDOs */ +enum volt_idx { + PDO_IDX_5V = 0, + PDO_IDX_12V = 1, + PDO_IDX_20V = 2, + + PDO_IDX_COUNT +}; + +#define PDO_FIXED_FLAGS (PDO_FIXED_UNCONSTRAINED | PDO_FIXED_DATA_SWAP) + +extern const uint32_t pd_src_pdo[3]; +extern const int pd_src_pdo_cnt; + +#endif /* __CROS_EC_BOARD_ZINGER_USB_PD_PDO_H */ diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c index f47789e063..157fda5ab4 100644 --- a/board/zinger/usb_pd_policy.c +++ b/board/zinger/usb_pd_policy.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,25 +9,27 @@ #include "debug_printf.h" #include "ec_commands.h" #include "hooks.h" +#include "printf.h" #include "registers.h" #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_pd.h" +#include "usb_pd_pdo.h" +#include "util.h" /* ------------------------- Power supply control ------------------------ */ /* GPIO level setting helpers through BSRR register */ -#define GPIO_SET(n) (1 << (n)) +#define GPIO_SET(n) (1 << (n)) #define GPIO_RESET(n) (1 << ((n) + 16)) /* Output voltage selection */ enum volt { - VO_5V = GPIO_RESET(13) | GPIO_RESET(14), - VO_12V = GPIO_SET(13) | GPIO_RESET(14), + VO_5V = GPIO_RESET(13) | GPIO_RESET(14), + VO_12V = GPIO_SET(13) | GPIO_RESET(14), VO_13V = GPIO_RESET(13) | GPIO_SET(14), - VO_20V = GPIO_SET(13) | GPIO_SET(14), + VO_20V = GPIO_SET(13) | GPIO_SET(14), }; static inline void set_output_voltage(enum volt v) @@ -72,33 +74,27 @@ static timestamp_t fault_deadline; /* ADC in 12-bit mode */ #define ADC_SCALE BIT(12) /* ADC power supply : VDDA = 3.3V */ -#define VDDA_MV 3300 +#define VDDA_MV 3300 /* Current sense resistor : 5 milliOhm */ -#define R_SENSE 5 +#define R_SENSE 5 /* VBUS voltage is measured through 10k / 100k voltage divider = /11 */ -#define VOLT_DIV ((10+100)/10) +#define VOLT_DIV ((10 + 100) / 10) /* The current sensing op-amp has a x100 gain */ #define CURR_GAIN 100 /* convert VBUS voltage in raw ADC value */ -#define VBUS_MV(mv) ((mv)*ADC_SCALE/VOLT_DIV/VDDA_MV) +#define VBUS_MV(mv) ((mv)*ADC_SCALE / VOLT_DIV / VDDA_MV) /* convert VBUS current in raw ADC value */ -#define VBUS_MA(ma) ((ma)*ADC_SCALE*R_SENSE/1000*CURR_GAIN/VDDA_MV) +#define VBUS_MA(ma) ((ma)*ADC_SCALE * R_SENSE / 1000 * CURR_GAIN / VDDA_MV) /* convert raw ADC value to mA */ -#define ADC_TO_CURR_MA(vbus) ((vbus)*1000/(ADC_SCALE*R_SENSE)*VDDA_MV/CURR_GAIN) +#define ADC_TO_CURR_MA(vbus) \ + ((vbus)*1000 / (ADC_SCALE * R_SENSE) * VDDA_MV / CURR_GAIN) /* convert raw ADC value to mV */ -#define ADC_TO_VOLT_MV(vbus) ((vbus)*VOLT_DIV*VDDA_MV/ADC_SCALE) - -/* Max current */ -#if defined(BOARD_ZINGER) -#define RATED_CURRENT 3000 -#elif defined(BOARD_MINIMUFFIN) -#define RATED_CURRENT 2250 -#endif +#define ADC_TO_VOLT_MV(vbus) ((vbus)*VOLT_DIV * VDDA_MV / ADC_SCALE) /* Max current : 20% over rated current */ -#define MAX_CURRENT VBUS_MA(RATED_CURRENT * 6/5) +#define MAX_CURRENT VBUS_MA(RATED_CURRENT * 6 / 5) /* Fast short circuit protection : 50% over rated current */ -#define MAX_CURRENT_FAST VBUS_MA(RATED_CURRENT * 3/2) +#define MAX_CURRENT_FAST VBUS_MA(RATED_CURRENT * 3 / 2) /* reset over-current after 1 second */ #define OCP_TIMEOUT SECOND @@ -106,19 +102,19 @@ static timestamp_t fault_deadline; #define SINK_IDLE_CURRENT VBUS_MA(500 /* mA */) /* Under-voltage limit is 0.8x Vnom */ -#define UVP_MV(mv) VBUS_MV((mv) * 8 / 10) +#define UVP_MV(mv) VBUS_MV((mv)*8 / 10) /* Over-voltage limit is 1.2x Vnom */ -#define OVP_MV(mv) VBUS_MV((mv) * 12 / 10) +#define OVP_MV(mv) VBUS_MV((mv)*12 / 10) /* Over-voltage recovery threshold is 1.1x Vnom */ -#define OVP_REC_MV(mv) VBUS_MV((mv) * 11 / 10) +#define OVP_REC_MV(mv) VBUS_MV((mv)*11 / 10) /* Maximum discharging delay */ -#define DISCHARGE_TIMEOUT (275*MSEC) +#define DISCHARGE_TIMEOUT (275 * MSEC) /* Voltage overshoot below the OVP threshold for discharging to avoid OVP */ #define DISCHARGE_OVERSHOOT_MV VBUS_MV(200) /* Time to wait after last RX edge interrupt before allowing deep sleep */ -#define PD_RX_SLEEP_TIMEOUT (100*MSEC) +#define PD_RX_SLEEP_TIMEOUT (100 * MSEC) /* ----- output voltage discharging ----- */ @@ -154,39 +150,18 @@ static void discharge_voltage(int target_volt) /* ----------------------- USB Power delivery policy ---------------------- */ -#define PDO_FIXED_FLAGS (PDO_FIXED_UNCONSTRAINED | PDO_FIXED_DATA_SWAP) - -/* Voltage indexes for the PDOs */ -enum volt_idx { - PDO_IDX_5V = 0, - PDO_IDX_12V = 1, - PDO_IDX_20V = 2, - - PDO_IDX_COUNT -}; - -/* Power Delivery Objects */ -const uint32_t pd_src_pdo[] = { - [PDO_IDX_5V] = PDO_FIXED(5000, RATED_CURRENT, PDO_FIXED_FLAGS), - [PDO_IDX_12V] = PDO_FIXED(12000, RATED_CURRENT, PDO_FIXED_FLAGS), - [PDO_IDX_20V] = PDO_FIXED(20000, RATED_CURRENT, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); -BUILD_ASSERT(ARRAY_SIZE(pd_src_pdo) == PDO_IDX_COUNT); - /* PDO voltages (should match the table above) */ static const struct { enum volt select; /* GPIO configuration to select the voltage */ - int uvp; /* under-voltage limit in mV */ - int ovp; /* over-voltage limit in mV */ - int ovp_rec;/* over-voltage recovery threshold in mV */ + int uvp; /* under-voltage limit in mV */ + int ovp; /* over-voltage limit in mV */ + int ovp_rec; /* over-voltage recovery threshold in mV */ } voltages[ARRAY_SIZE(pd_src_pdo)] = { - [PDO_IDX_5V] = {VO_5V, UVP_MV(5000), OVP_MV(5000), - OVP_REC_MV(5000)}, - [PDO_IDX_12V] = {VO_12V, UVP_MV(12000), OVP_MV(12000), - OVP_REC_MV(12000)}, - [PDO_IDX_20V] = {VO_20V, UVP_MV(20000), OVP_MV(20000), - OVP_REC_MV(20000)}, + [PDO_IDX_5V] = { VO_5V, UVP_MV(5000), OVP_MV(5000), OVP_REC_MV(5000) }, + [PDO_IDX_12V] = { VO_12V, UVP_MV(12000), OVP_MV(12000), + OVP_REC_MV(12000) }, + [PDO_IDX_20V] = { VO_20V, UVP_MV(20000), OVP_MV(20000), + OVP_REC_MV(20000) }, }; /* current and previous selected PDO entry */ @@ -225,8 +200,8 @@ void pd_transition_voltage(int idx) /* Make sure discharging is disabled */ discharge_disable(); /* Enable over-current monitoring */ - adc_enable_watchdog(ADC_CH_A_SENSE, - MAX_CURRENT_FAST, 0); + adc_enable_watchdog(ADC_CH_A_SENSE, MAX_CURRENT_FAST, + 0); } } set_output_voltage(voltages[volt_idx].select); @@ -267,28 +242,22 @@ void pd_power_supply_reset(int port) } } -int pd_check_data_swap(int port, - enum pd_data_role data_role) +int pd_check_data_swap(int port, enum pd_data_role data_role) { /* Allow data swap if we are a DFP, otherwise don't allow */ return (data_role == PD_ROLE_DFP) ? 1 : 0; } -void pd_execute_data_swap(int port, - enum pd_data_role data_role) +void pd_execute_data_swap(int port, enum pd_data_role data_role) { /* Do nothing */ } -void pd_check_pr_role(int port, - enum pd_power_role pr_role, - int flags) +void pd_check_pr_role(int port, enum pd_power_role pr_role, int flags) { } -void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) +void pd_check_dr_role(int port, enum pd_data_role dr_role, int flags) { /* If DFP, try to switch to UFP */ if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_DFP) @@ -315,7 +284,7 @@ int pd_board_checks(void) __enter_hibernate(0, 0); } } else { - hib_to.val = get_time().val + 60*SECOND; + hib_to.val = get_time().val + 60 * SECOND; hib_to_ready = 1; } #endif @@ -345,8 +314,8 @@ int pd_board_checks(void) /* trigger the slow OCP iff all 4 samples are above the max */ if (count == 3) { debug_printf("OCP %d mA\n", - vbus_amp * VDDA_MV / CURR_GAIN * 1000 - / R_SENSE / ADC_SCALE); + vbus_amp * VDDA_MV / CURR_GAIN * 1000 / + R_SENSE / ADC_SCALE); pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_OCP, NULL); fault = FAULT_OCP; /* reset over-current after 1 second */ @@ -375,8 +344,7 @@ int pd_board_checks(void) if ((output_is_enabled() && (vbus_volt > voltages[ovp_idx].ovp)) || (fault && (vbus_volt > voltages[ovp_idx].ovp_rec))) { if (!fault) { - debug_printf("OVP %d mV\n", - ADC_TO_VOLT_MV(vbus_volt)); + debug_printf("OVP %d mV\n", ADC_TO_VOLT_MV(vbus_volt)); pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_OVP, NULL); } fault = FAULT_OVP; @@ -387,7 +355,7 @@ int pd_board_checks(void) /* the discharge did not work properly */ if (discharge_is_enabled() && - (get_time().val > discharge_deadline.val)) { + (get_time().val > discharge_deadline.val)) { /* ensure we always finish a 2-step discharge */ volt_idx = discharge_volt_idx; set_output_voltage(voltages[volt_idx].select); @@ -395,8 +363,7 @@ int pd_board_checks(void) discharge_disable(); /* enable over-current monitoring */ adc_enable_watchdog(ADC_CH_A_SENSE, MAX_CURRENT_FAST, 0); - debug_printf("Disch FAIL %d mV\n", - ADC_TO_VOLT_MV(vbus_volt)); + debug_printf("Disch FAIL %d mV\n", ADC_TO_VOLT_MV(vbus_volt)); pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_DISCH, NULL); fault = FAULT_DISCHARGE; /* reset it after 1 second */ @@ -416,10 +383,9 @@ int pd_board_checks(void) } return EC_SUCCESS; - } -void pd_adc_interrupt(void) +static void pd_adc_interrupt(void) { /* Clear flags */ STM32_ADC_ISR = 0x8e; @@ -433,10 +399,10 @@ void pd_adc_interrupt(void) } else { /* discharge complete */ discharge_disable(); /* enable over-current monitoring */ - adc_enable_watchdog(ADC_CH_A_SENSE, - MAX_CURRENT_FAST, 0); + adc_enable_watchdog(ADC_CH_A_SENSE, MAX_CURRENT_FAST, + 0); } - } else {/* Over-current detection */ + } else { /* Over-current detection */ /* cut the power output */ pd_power_supply_reset(0); /* record a special fault */ @@ -479,9 +445,7 @@ static int svdm_response_svids(int port, uint32_t *payload) #define MODE_CNT 1 #define OPOS 1 -const uint32_t vdo_dp_mode[MODE_CNT] = { - VDO_MODE_GOOGLE(MODE_GOOGLE_FU) -}; +const uint32_t vdo_dp_mode[MODE_CNT] = { VDO_MODE_GOOGLE(MODE_GOOGLE_FU) }; static int svdm_response_modes(int port, uint32_t *payload) { @@ -525,16 +489,17 @@ const struct svdm_response svdm_rsp = { }; __override int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) + uint32_t **rpayload) { int cmd = PD_VDO_CMD(payload[0]); int rsize; + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE || !gfu_mode) return 0; - debug_printf("%pT] VDM/%d [%d] %08x\n", - PRINTF_TIMESTAMP_NOW, cnt, cmd, payload[0]); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + debug_printf("%s] VDM/%d [%d] %08x\n", ts_str, cnt, cmd, payload[0]); *rpayload = payload; rsize = pd_custom_flash_vdm(port, cnt, payload); diff --git a/board/zinger/vif_override.xml b/board/zinger/vif_override.xml new file mode 100644 index 0000000000..32736caf64 --- /dev/null +++ b/board/zinger/vif_override.xml @@ -0,0 +1,3 @@ + diff --git a/builtin/assert.h b/builtin/assert.h index e58a450fa8..71a275bf23 100644 --- a/builtin/assert.h +++ b/builtin/assert.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -21,33 +21,62 @@ extern "C" { #ifdef CONFIG_DEBUG_ASSERT_REBOOTS #ifdef CONFIG_DEBUG_ASSERT_BRIEF -extern noreturn void panic_assert_fail(const char *fname, int linenum); +#if defined(__cplusplus) && !defined(__clang__) +[[noreturn]] +#else +noreturn +#endif +void panic_assert_fail(const char *fname, int linenum); #define ASSERT(cond) \ do { \ if (!(cond)) \ panic_assert_fail(__FILE__, __LINE__); \ } while (0) + +#else /* !CONFIG_DEBUG_ASSERT_BRIEF */ + +#if defined(__cplusplus) && !defined(__clang__) +[[noreturn]] #else -extern noreturn void panic_assert_fail(const char *msg, const char *func, - const char *fname, int linenum); +noreturn +#endif +void panic_assert_fail(const char *msg, const char *func, + const char *fname, int linenum); #define ASSERT(cond) \ do { \ if (!(cond)) \ panic_assert_fail(#cond, __func__, __FILE__, \ __LINE__); \ } while (0) -#endif +#endif /* CONFIG_DEBUG_ASSERT_BRIEF */ + +#else /* !CONFIG_DEBUG_ASSERT_REBOOTS */ + +#if defined(__arm__) +#define ARCH_SOFTWARE_BREAKPOINT __asm("bkpt") +#elif defined(__nds32__) +#define ARCH_SOFTWARE_BREAKPOINT __asm("break 0") +#elif defined(__riscv) +#define ARCH_SOFTWARE_BREAKPOINT __asm("ebreak") +#elif defined(VIF_BUILD) +/* The genvif utility compiles usb_pd_policy.c and needs an empty definition. */ +#define ARCH_SOFTWARE_BREAKPOINT #else -#define ASSERT(cond) \ - do { \ - if (!(cond)) \ - __asm("bkpt"); \ - __builtin_unreachable(); \ - } while (0) +#error "CONFIG_DEBUG_ASSERT_REBOOTS must be defined on this architecture" #endif -#else + +#define ASSERT(cond) \ + do { \ + if (!(cond)) { \ + ARCH_SOFTWARE_BREAKPOINT; \ + __builtin_unreachable(); \ + } \ + } while (0) +#endif /* CONFIG_DEBUG_ASSERT_REBOOTS */ + +#else /* !CONFIG_DEBUG_ASSERT */ #define ASSERT(cond) -#endif +#endif /* CONFIG_DEBUG_ASSERT */ /* This collides with cstdlib, so exclude it where cstdlib is supported. */ #ifndef assert diff --git a/builtin/build.mk b/builtin/build.mk new file mode 100644 index 0000000000..6613bfec05 --- /dev/null +++ b/builtin/build.mk @@ -0,0 +1,6 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Build for EC's standard library implementation. +builtin-y=stdlib.o diff --git a/builtin/ctype.h b/builtin/ctype.h new file mode 100644 index 0000000000..8844adca67 --- /dev/null +++ b/builtin/ctype.h @@ -0,0 +1,16 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_CTYPE_H__ +#define __CROS_EC_CTYPE_H__ + +int isdigit(int c); +int isspace(int c); +int isalpha(int c); +int isupper(int c); +int isprint(int c); +int tolower(int c); + +#endif /* __CROS_EC_CTYPE_H__ */ diff --git a/builtin/endian.h b/builtin/endian.h index 8a50cb4815..0220836dca 100644 --- a/builtin/endian.h +++ b/builtin/endian.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,7 +17,7 @@ extern "C" { * host byte order. Note that the code currently does not require functions * for converting little endian integers. */ -#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) static inline uint16_t be16toh(uint16_t in) { @@ -36,10 +36,14 @@ static inline uint64_t be64toh(uint64_t in) #define htobe32 be32toh #define htobe64 be64toh -#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ +#define htole16(x) (uint16_t)(x) +#define htole32(x) (uint32_t)(x) +#define htole64(x) (uint64_t)(x) + +#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ #ifdef __cplusplus } #endif -#endif /* __EC_BUILTIN_ENDIAN_H */ +#endif /* __EC_BUILTIN_ENDIAN_H */ diff --git a/builtin/inttypes.h b/builtin/inttypes.h index c442fbe499..eed80407ce 100644 --- a/builtin/inttypes.h +++ b/builtin/inttypes.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,8 @@ #ifndef __CROS_EC_INTTYPES_H__ #define __CROS_EC_INTTYPES_H__ +#include + #define PRIx64 "llx" #define PRId64 "lld" diff --git a/builtin/limits.h b/builtin/limits.h index 5cbfa3e6d1..0e185614ae 100644 --- a/builtin/limits.h +++ b/builtin/limits.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,8 @@ #ifndef __CROS_EC_LIMITS_H_ #define __CROS_EC_LIMITS_H_ +#define CHAR_BIT 8 + #define ULONG_MAX 0xffffffffu #endif /* __CROS_EC_LIMITS_H_ */ diff --git a/builtin/math.h b/builtin/math.h new file mode 100644 index 0000000000..aa07a0286d --- /dev/null +++ b/builtin/math.h @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_MATH_H__ +#define __CROS_EC_MATH_H__ + +#include "fpu.h" + +#include + +static inline bool isnan(float a) +{ + return __builtin_isnan(a); +} + +static inline bool isinf(float a) +{ + return __builtin_isinf(a); +} + +#endif /* __CROS_EC_MATH_H__ */ diff --git a/builtin/stdarg.h b/builtin/stdarg.h index 66ab940b16..5bf0aa8aa2 100644 --- a/builtin/stdarg.h +++ b/builtin/stdarg.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,10 +13,10 @@ */ #ifdef __GNUC__ -#define va_start(v, l) __builtin_va_start(v, l) -#define va_end(v) __builtin_va_end(v) -#define va_arg(v, l) __builtin_va_arg(v, l) -typedef __builtin_va_list va_list; +#define va_start(v, l) __builtin_va_start(v, l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v, l) __builtin_va_arg(v, l) +typedef __builtin_va_list va_list; #else #include_next #endif diff --git a/builtin/stdbool.h b/builtin/stdbool.h index 6e0f92dfc0..72d4927484 100644 --- a/builtin/stdbool.h +++ b/builtin/stdbool.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,8 +6,8 @@ #ifndef __CROS_EC_STDBOOL_H__ #define __CROS_EC_STDBOOL_H__ -#define bool _Bool -#define true 1 -#define false 0 +#define bool _Bool +#define true 1 +#define false 0 #endif /* __CROS_EC_STDBOOL_H__ */ diff --git a/builtin/stddef.h b/builtin/stddef.h index 69fb1982c7..9e69ba55ad 100644 --- a/builtin/stddef.h +++ b/builtin/stddef.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,12 +11,6 @@ #endif typedef __SIZE_TYPE__ size_t; -/* There is a GCC macro for a size_t type, but not for a ssize_t type. - * The following construct convinces GCC to make __SIZE_TYPE__ signed. - */ -#define unsigned signed -typedef __SIZE_TYPE__ ssize_t; -#undef unsigned #ifndef NULL #define NULL ((void *)0) @@ -36,7 +30,7 @@ typedef __WCHAR_TYPE__ wchar_t; * check for safety. */ #ifndef offsetof -#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) +#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) #endif #endif /* __CROS_EC_STDDEF_H__ */ diff --git a/builtin/stdint.h b/builtin/stdint.h index dedc9de475..5a107e1730 100644 --- a/builtin/stdint.h +++ b/builtin/stdint.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,43 +6,43 @@ #ifndef __CROS_EC_STDINT_H__ #define __CROS_EC_STDINT_H__ -typedef unsigned char uint8_t; -typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; -typedef unsigned short uint16_t; -typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; -typedef unsigned int uint32_t; -typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; typedef unsigned long long uint64_t; -typedef signed long long int64_t; +typedef signed long long int64_t; -typedef unsigned int uintptr_t; -typedef int intptr_t; +typedef unsigned int uintptr_t; +typedef int intptr_t; /* uint_leastX_t represents the smallest type available with at least X bits. * uint_fastX_t represents the fastest type available with at least X bits. */ -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; - -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; + +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; #ifndef UINT8_MAX #define UINT8_MAX (255U) @@ -67,12 +67,15 @@ typedef int64_t int_fast64_t; #ifndef INT32_MAX #define INT32_MAX (2147483647U) #endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483648) +#endif #ifndef UINT64_C -#define UINT64_C(c) c ## ULL +#define UINT64_C(c) c##ULL #endif #ifndef INT64_C -#define INT64_C(c) c ## LL +#define INT64_C(c) c##LL #endif #ifndef UINT64_MAX @@ -81,5 +84,8 @@ typedef int64_t int_fast64_t; #ifndef INT64_MAX #define INT64_MAX INT64_C(9223372036854775807) #endif +#ifndef INT64_MIN +#define INT64_MIN (INT64_C(-9223372036854775807) - 1) +#endif #endif /* __CROS_EC_STDINT_H__ */ diff --git a/builtin/stdio.h b/builtin/stdio.h new file mode 100644 index 0000000000..bd75c01f53 --- /dev/null +++ b/builtin/stdio.h @@ -0,0 +1,61 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_STDIO_H__ +#define __CROS_EC_STDIO_H__ + +#include "common.h" + +#include +#include + +/** + * Print formatted outut to a string. + * + * Guarantees null-termination if size!=0. + * + * @param str Destination string + * @param size Size of destination in bytes + * @param format Format string + * @return EC_SUCCESS, or EC_ERROR_OVERFLOW if the output was truncated. + */ +__attribute__((__format__(__printf__, 3, 4))) +__warn_unused_result __stdlib_compat int +crec_snprintf(char *str, size_t size, const char *format, ...); + +/** + * Print formatted output to a string. + * + * Guarantees null-termination if size!=0. + * + * @param str Destination string + * @param size Size of destination in bytes + * @param format Format string + * @param args Parameters + * @return The string length written to str, or a negative value on error. + * The negative values can be -EC_ERROR_INVAL or -EC_ERROR_OVERFLOW. + */ +__warn_unused_result __stdlib_compat int +crec_vsnprintf(char *str, size_t size, const char *format, va_list args); + +/* + * Create weak aliases to the crec_* printf functions. This lets us call the + * crec_* printf functions in tests that link the C standard library. + */ + +/** + * Alias to crec_snprintf. + */ +__attribute__((__format__(__printf__, 3, 4))) +__warn_unused_result __stdlib_compat int +snprintf(char *str, size_t size, const char *format, ...); + +/** + * Alias to crec_vsnprintf. + */ +__warn_unused_result __stdlib_compat int +vsnprintf(char *str, size_t size, const char *format, va_list args); + +#endif /* __CROS_EC_STDIO_H__ */ diff --git a/builtin/stdlib.c b/builtin/stdlib.c new file mode 100644 index 0000000000..0d654f0395 --- /dev/null +++ b/builtin/stdlib.c @@ -0,0 +1,465 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Standard library utility functions for Chrome EC */ + +#include "common.h" +#include "console.h" +#include "printf.h" +#include "util.h" + +#include + +/* + * The following macros are defined in stdlib.h in the C standard library, which + * conflict with the definitions in this file. + */ +#undef isspace +#undef isdigit +#undef isalpha +#undef isupper +#undef isprint +#undef tolower + +/* Context for snprintf() */ +struct snprintf_context { + char *str; + int size; +}; + +/** + * Add a character to the string context. + * + * @param context Context receiving character + * @param c Character to add + * @return 0 if character added, 1 if character dropped because no space. + */ +static int snprintf_addchar(void *context, int c) +{ + struct snprintf_context *ctx = (struct snprintf_context *)context; + + if (!ctx->size) + return 1; + + *(ctx->str++) = c; + ctx->size--; + return 0; +} + +int crec_vsnprintf(char *str, size_t size, const char *format, va_list args) +{ + struct snprintf_context ctx; + int rv; + + if (!str || !format || size <= 0) + return -EC_ERROR_INVAL; + + ctx.str = str; + ctx.size = size - 1; /* Reserve space for terminating '\0' */ + + rv = vfnprintf(snprintf_addchar, &ctx, format, args); + + /* Terminate string */ + *ctx.str = '\0'; + + return (rv == EC_SUCCESS) ? (ctx.str - str) : -rv; +} +#ifndef CONFIG_ZEPHYR +int vsnprintf(char *str, size_t size, const char *format, va_list args) + __attribute__((weak, alias("crec_vsnprintf"))); +#endif /* CONFIG_ZEPHYR */ + +int crec_snprintf(char *str, size_t size, const char *format, ...) +{ + va_list args; + int rv; + + va_start(args, format); + rv = crec_vsnprintf(str, size, format, args); + va_end(args); + + return rv; +} +#ifndef CONFIG_ZEPHYR +int snprintf(char *str, size_t size, const char *format, ...) + __attribute__((weak, alias("crec_snprintf"))); +#endif /* CONFIG_ZEPHYR */ + +/* + * TODO(b/237712836): Zephyr's libc should provide strcasecmp. For now we'll + * use the EC implementation. + */ +__stdlib_compat int strcasecmp(const char *s1, const char *s2) +{ + int diff; + + do { + diff = tolower(*s1) - tolower(*s2); + if (diff) + return diff; + } while (*(s1++) && *(s2++)); + return 0; +} + +/* + * TODO(b/237712836): Remove this conditional once strcasecmp is added to + * Zephyr's libc. + */ +#ifndef CONFIG_ZEPHYR +__stdlib_compat size_t strlen(const char *s) +{ + int len = 0; + + while (*s++) + len++; + + return len; +} + +__stdlib_compat size_t strnlen(const char *s, size_t maxlen) +{ + size_t len = 0; + + while (len < maxlen && *s) { + s++; + len++; + } + return len; +} + +__stdlib_compat size_t strcspn(const char *s, const char *reject) +{ + size_t i; + size_t reject_len = strlen(reject); + + for (i = 0; s[i] != 0; i++) + for (size_t j = 0; j < reject_len; j++) + if (s[i] == reject[j]) + return i; + return i; +} + +__stdlib_compat int isspace(int c) +{ + return c == ' ' || c == '\t' || c == '\r' || c == '\n'; +} + +__stdlib_compat int isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +__stdlib_compat int isalpha(int c) +{ + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); +} + +__stdlib_compat int isupper(int c) +{ + return c >= 'A' && c <= 'Z'; +} + +__stdlib_compat int isprint(int c) +{ + return c >= ' ' && c <= '~'; +} + +__stdlib_compat int tolower(int c) +{ + return c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c; +} + +__stdlib_compat int strncasecmp(const char *s1, const char *s2, size_t size) +{ + int diff; + + if (!size) + return 0; + + do { + diff = tolower(*s1) - tolower(*s2); + if (diff) + return diff; + } while (*(s1++) && *(s2++) && --size); + return 0; +} + +__stdlib_compat char *strstr(const char *s1, const char *s2) +{ + const char *p, *q, *r; + size_t len1 = strlen(s1); + size_t len2 = strlen(s2); + + if (len1 == 0 || len2 == 0 || len1 < len2) + return NULL; + + r = s1 + len1 - len2 + 1; + for (; s1 < r; s1++) { + if (*s1 == *s2) { + p = s1 + 1; + q = s2 + 1; + for (; q < s2 + len2;) { + if (*p++ != *q++) + break; + } + if (*q == '\0') + return (char *)s1; + } + } + return NULL; +} + +__stdlib_compat unsigned long long int strtoull(const char *nptr, char **endptr, + int base) +{ + uint64_t result = 0; + int c = '\0'; + + while ((c = *nptr++) && isspace(c)) + ; + + if (c == '+') { + c = *nptr++; + } else if (c == '-') { + if (endptr) + *endptr = (char *)nptr - 1; + return result; + } + + base = find_base(base, &c, &nptr); + + while (c) { + if (c >= '0' && c < '0' + MIN(base, 10)) + result = result * base + (c - '0'); + else if (c >= 'A' && c < 'A' + base - 10) + result = result * base + (c - 'A' + 10); + else if (c >= 'a' && c < 'a' + base - 10) + result = result * base + (c - 'a' + 10); + else + break; + + c = *nptr++; + } + + if (endptr) + *endptr = (char *)nptr - 1; + return result; +} +BUILD_ASSERT(sizeof(unsigned long long int) == sizeof(uint64_t)); + +__stdlib_compat int atoi(const char *nptr) +{ + int result = 0; + int neg = 0; + char c = '\0'; + + while ((c = *nptr++) && isspace(c)) + ; + + if (c == '-') { + neg = 1; + c = *nptr++; + } + + while (isdigit(c)) { + result = result * 10 + (c - '0'); + c = *nptr++; + } + + return neg ? -result : result; +} + +__keep __stdlib_compat int memcmp(const void *s1, const void *s2, size_t len) +{ + const char *sa = s1; + const char *sb = s2; + int diff = 0; + + while (len-- > 0) { + diff = *(sa++) - *(sb++); + if (diff) + return diff; + } + + return 0; +} + +#if !(__has_feature(address_sanitizer) || __has_feature(memory_sanitizer)) +__keep __stdlib_compat void *memcpy(void *dest, const void *src, size_t len) +{ + char *d = (char *)dest; + const char *s = (const char *)src; + uint32_t *dw; + const uint32_t *sw; + char *head; + char *const tail = (char *)dest + len; + /* Set 'body' to the last word boundary */ + uint32_t *const body = (uint32_t *)((uintptr_t)tail & ~3); + + if (((uintptr_t)dest & 3) != ((uintptr_t)src & 3)) { + /* Misaligned. no body, no tail. */ + head = tail; + } else { + /* Aligned */ + if ((uintptr_t)tail < (((uintptr_t)d + 3) & ~3)) + /* len is shorter than the first word boundary */ + head = tail; + else + /* Set 'head' to the first word boundary */ + head = (char *)(((uintptr_t)d + 3) & ~3); + } + + /* Copy head */ + while (d < head) + *(d++) = *(s++); + + /* Copy body */ + dw = (uint32_t *)d; + sw = (uint32_t *)s; + while (dw < body) + *(dw++) = *(sw++); + + /* Copy tail */ + d = (char *)dw; + s = (const char *)sw; + while (d < tail) + *(d++) = *(s++); + + return dest; +} +#endif /* address_sanitizer || memory_sanitizer */ + +#if !(__has_feature(address_sanitizer) || __has_feature(memory_sanitizer)) +__keep __stdlib_compat __visible void *memset(void *dest, int c, size_t len) +{ + char *d = (char *)dest; + uint32_t cccc; + uint32_t *dw; + char *head; + char *const tail = (char *)dest + len; + /* Set 'body' to the last word boundary */ + uint32_t *const body = (uint32_t *)((uintptr_t)tail & ~3); + + c &= 0xff; /* Clear upper bits before ORing below */ + cccc = c | (c << 8) | (c << 16) | (c << 24); + + if ((uintptr_t)tail < (((uintptr_t)d + 3) & ~3)) + /* len is shorter than the first word boundary */ + head = tail; + else + /* Set 'head' to the first word boundary */ + head = (char *)(((uintptr_t)d + 3) & ~3); + + /* Copy head */ + while (d < head) + *(d++) = c; + + /* Copy body */ + dw = (uint32_t *)d; + while (dw < body) + *(dw++) = cccc; + + /* Copy tail */ + d = (char *)dw; + while (d < tail) + *(d++) = c; + + return dest; +} +#endif /* address_sanitizer || memory_sanitizer */ + +#if !(__has_feature(address_sanitizer) || __has_feature(memory_sanitizer)) +__keep __stdlib_compat void *memmove(void *dest, const void *src, size_t len) +{ + if ((uintptr_t)dest <= (uintptr_t)src || + (uintptr_t)dest >= (uintptr_t)src + len) { + /* Start of destination doesn't overlap source, so just use + * memcpy(). + */ + return memcpy(dest, src, len); + } else { + /* Need to copy from tail because there is overlap. */ + char *d = (char *)dest + len; + const char *s = (const char *)src + len; + uint32_t *dw; + const uint32_t *sw; + char *head; + char *const tail = (char *)dest; + /* Set 'body' to the last word boundary */ + uint32_t *const body = (uint32_t *)(((uintptr_t)tail + 3) & ~3); + + if (((uintptr_t)dest & 3) != ((uintptr_t)src & 3)) { + /* Misaligned. no body, no tail. */ + head = tail; + } else { + /* Aligned */ + if ((uintptr_t)tail > ((uintptr_t)d & ~3)) + /* Shorter than the first word boundary */ + head = tail; + else + /* Set 'head' to the first word boundary */ + head = (char *)((uintptr_t)d & ~3); + } + + /* Copy head */ + while (d > head) + *(--d) = *(--s); + + /* Copy body */ + dw = (uint32_t *)d; + sw = (uint32_t *)s; + while (dw > body) + *(--dw) = *(--sw); + + /* Copy tail */ + d = (char *)dw; + s = (const char *)sw; + while (d > tail) + *(--d) = *(--s); + + return dest; + } +} +#endif /* address_sanitizer || memory_sanitizer */ + +__stdlib_compat void *memchr(const void *buffer, int c, size_t n) +{ + char *current = (char *)buffer; + char *end = current + n; + + while (current != end) { + if (*current == c) + return current; + current++; + } + return NULL; +} + +__stdlib_compat char *strncpy(char *dest, const char *src, size_t n) +{ + char *d = dest; + + while (n && *src) { + *d++ = *src++; + n--; + } + if (n) + *d = '\0'; + return dest; +} + +__stdlib_compat int strncmp(const char *s1, const char *s2, size_t n) +{ + while (n--) { + if (*s1 != *s2) + return *s1 - *s2; + if (!*s1) + break; + s1++; + s2++; + } + return 0; +} +#endif /* !CONFIG_ZEPHYR */ diff --git a/builtin/stdlib.h b/builtin/stdlib.h new file mode 100644 index 0000000000..fcce72ee8d --- /dev/null +++ b/builtin/stdlib.h @@ -0,0 +1,11 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_STDLIB_H__ +#define __CROS_EC_STDLIB_H__ + +int atoi(const char *nptr); + +#endif /* __CROS_EC_STDLIB_H__ */ diff --git a/builtin/stdnoreturn.h b/builtin/stdnoreturn.h index 659d3c540f..078a0d6698 100644 --- a/builtin/stdnoreturn.h +++ b/builtin/stdnoreturn.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,7 +9,8 @@ /* * Only defined for C: https://en.cppreference.com/w/c/language/_Noreturn * - * C++ uses [[noreturn]]: https://en.cppreference.com/w/cpp/language/attributes/noreturn + * C++ uses [[noreturn]]: + * https://en.cppreference.com/w/cpp/language/attributes/noreturn */ #ifndef __cplusplus #ifndef noreturn diff --git a/builtin/string.h b/builtin/string.h index 8c9a71bd75..742d75a478 100644 --- a/builtin/string.h +++ b/builtin/string.h @@ -1,12 +1,10 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* This header is only needed for CR50 compatibility */ - -#ifndef __CROS_EC_STRINGS_H__ -#define __CROS_EC_STRINGS_H__ +#ifndef __CROS_EC_STRING_H__ +#define __CROS_EC_STRING_H__ #include @@ -20,12 +18,28 @@ void *memmove(void *dest, const void *src, size_t n); void *memset(void *dest, int c, size_t len); void *memchr(const void *buffer, int c, size_t n); +size_t strlen(const char *s); size_t strnlen(const char *s, size_t maxlen); char *strncpy(char *dest, const char *src, size_t n); int strncmp(const char *s1, const char *s2, size_t n); +/** + * Calculates the length of the initial segment of s which consists + * entirely of bytes not in reject. + */ +size_t strcspn(const char *s, const char *reject); + +/** + * Find the first occurrence of the substring in the string + * + * @param s1 String where is searched. + * @param s2 Substring to be located in + * @return Pointer to the located substring or NULL if not found. + */ +char *strstr(const char *s1, const char *s2); + #ifdef __cplusplus } #endif -#endif /* __CROS_EC_STRINGS_H__ */ +#endif /* __CROS_EC_STRING_H__ */ diff --git a/builtin/strings.h b/builtin/strings.h new file mode 100644 index 0000000000..cbcc858c36 --- /dev/null +++ b/builtin/strings.h @@ -0,0 +1,14 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_STRINGS_H__ +#define __CROS_EC_STRINGS_H__ + +#include + +int strcasecmp(const char *s1, const char *s2); +int strncasecmp(const char *s1, const char *s2, size_t size); + +#endif /* __CROS_EC_STRINGS_H__ */ diff --git a/builtin/sys/time.h b/builtin/sys/time.h new file mode 100644 index 0000000000..537ca6ceb0 --- /dev/null +++ b/builtin/sys/time.h @@ -0,0 +1,24 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_SYS_TIME_H__ +#define __CROS_EC_SYS_TIME_H__ + +#include + +/** + * Partial implementation of header: + * https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_time.h.html + */ + +typedef int64_t time_t; +typedef int32_t suseconds_t; + +struct timeval { + time_t tv_sec; /* seconds */ + suseconds_t tv_usec; /* microseconds */ +}; + +#endif /* __CROS_EC_SYS_TIME_H__ */ diff --git a/builtin/sys/types.h b/builtin/sys/types.h new file mode 100644 index 0000000000..01fc1a7749 --- /dev/null +++ b/builtin/sys/types.h @@ -0,0 +1,19 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_SYS_TYPES_H__ +#define __CROS_EC_SYS_TYPES_H__ + +/* Data type for POSIX style clock() implementation */ +typedef long clock_t; + +/* There is a GCC macro for a size_t type, but not for a ssize_t type. + * The following construct convinces GCC to make __SIZE_TYPE__ signed. + */ +#define unsigned signed +typedef __SIZE_TYPE__ ssize_t; +#undef unsigned + +#endif /* __CROS_EC_SYS_TYPES_H__ */ diff --git a/builtin/time.h b/builtin/time.h index a069ae18c9..36b07b4721 100644 --- a/builtin/time.h +++ b/builtin/time.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/host/adc_chip.h b/chip/host/adc_chip.h new file mode 100644 index 0000000000..cd55e1b5fb --- /dev/null +++ b/chip/host/adc_chip.h @@ -0,0 +1,16 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Host-specific ADC module for Chrome EC */ + +#ifndef __CROS_EC_ADC_CHIP_H +#define __CROS_EC_ADC_CHIP_H + +/* Place-holder data structure to define ADC channels. */ +struct adc_t { + int unused; +}; + +#endif /* __CROS_EC_ADC_CHIP_H */ diff --git a/chip/host/build.mk b/chip/host/build.mk index 8d2d69f3c3..b4a75cf3c6 100644 --- a/chip/host/build.mk +++ b/chip/host/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. +# Copyright 2013 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -9,9 +9,9 @@ CORE:=host chip-y=system.o gpio.o uart.o persistence.o flash.o lpc.o reboot.o \ - clock.o spi_master.o trng.o + clock.o spi_controller.o trng.o -ifndef CONFIG_KEYBOARD_NOT_RAW +ifndef CONFIG_KEYBOARD_DISCRETE chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o endif chip-$(CONFIG_USB_PD_TCPC)+=usb_pd_phy.o diff --git a/chip/host/clock.c b/chip/host/clock.c index 2c3c48661e..29fb0dfa5a 100644 --- a/chip/host/clock.c +++ b/chip/host/clock.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,8 +6,13 @@ */ #include "clock.h" +#include "common.h" int clock_get_freq(void) { return 16000000; } + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/host/config_chip.h b/chip/host/config_chip.h index 195744c556..323fb83d33 100644 --- a/chip/host/config_chip.h +++ b/chip/host/config_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,21 +10,21 @@ /* Memory mapping */ #if !defined(TEST_NVMEM) && !defined(TEST_CR50_FUZZ) -#define CONFIG_FLASH_SIZE 0x00020000 +#define CONFIG_FLASH_SIZE_BYTES 0x00020000 #define CONFIG_FLASH_BANK_SIZE 0x1000 #else -#define CONFIG_FLASH_SIZE (512 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) #define CONFIG_FLASH_BANK_SIZE 0x800 #endif -extern char __host_flash[CONFIG_FLASH_SIZE]; +extern char __host_flash[CONFIG_FLASH_SIZE_BYTES]; #define CONFIG_PROGRAM_MEMORY_BASE ((uintptr_t)__host_flash) -#define CONFIG_FLASH_ERASE_SIZE 0x0010 /* erase bank size */ -#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ +#define CONFIG_FLASH_ERASE_SIZE 0x0010 /* erase bank size */ +#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ #define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0080 /* ideal write size */ -#define CONFIG_RAM_BASE 0x0 /* Not supported */ -#define CONFIG_RAM_SIZE 0x0 /* Not supported */ +#define CONFIG_RAM_BASE 0x0 /* Not supported */ +#define CONFIG_RAM_SIZE 0x0 /* Not supported */ #define CONFIG_FPU @@ -43,7 +43,7 @@ extern char __host_flash[CONFIG_FLASH_SIZE]; /* Interval between HOOK_TICK notifications */ #define HOOK_TICK_INTERVAL_MS 250 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) +#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) /* Do NOT use common panic code (designed to output information on the UART) */ #undef CONFIG_COMMON_PANIC_OUTPUT diff --git a/chip/host/flash.c b/chip/host/flash.c index 9f79298d60..03a5fc777b 100644 --- a/chip/host/flash.c +++ b/chip/host/flash.c @@ -1,20 +1,21 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Flash module for emulator */ -#include - +#include "builtin/assert.h" #include "common.h" #include "config_chip.h" #include "flash.h" #include "persistence.h" #include "util.h" +#include + /* This needs to be aligned to the erase bank size for NVCTR. */ -__aligned(CONFIG_FLASH_ERASE_SIZE) char __host_flash[CONFIG_FLASH_SIZE]; +__aligned(CONFIG_FLASH_ERASE_SIZE) char __host_flash[CONFIG_FLASH_SIZE_BYTES]; uint8_t __host_flash_protect[PHYSICAL_BANKS]; /* Override this function to make flash erase/write operation fail */ @@ -26,8 +27,7 @@ test_mockable int flash_pre_op(void) static int flash_check_protect(int offset, int size) { int first_bank = offset / CONFIG_FLASH_BANK_SIZE; - int last_bank = DIV_ROUND_UP(offset + size, - CONFIG_FLASH_BANK_SIZE); + int last_bank = DIV_ROUND_UP(offset + size, CONFIG_FLASH_BANK_SIZE); int bank; for (bank = first_bank; bank < last_bank; ++bank) @@ -52,6 +52,7 @@ static void flash_set_persistent(void) static void flash_get_persistent(void) { FILE *f = get_persistent_storage("flash", "rb"); + int sz; if (f == NULL) { fprintf(stderr, @@ -60,12 +61,13 @@ static void flash_get_persistent(void) return; } - fread(__host_flash, sizeof(__host_flash), 1, f); + sz = fread(__host_flash, sizeof(__host_flash), 1, f); + ASSERT(sz == 1); release_persistent_storage(f); } -int flash_physical_write(int offset, int size, const char *data) +int crec_flash_physical_write(int offset, int size, const char *data) { ASSERT((size & (CONFIG_FLASH_WRITE_SIZE - 1)) == 0); @@ -81,7 +83,7 @@ int flash_physical_write(int offset, int size, const char *data) return EC_SUCCESS; } -int flash_physical_erase(int offset, int size) +int crec_flash_physical_erase(int offset, int size) { ASSERT((size & (CONFIG_FLASH_ERASE_SIZE - 1)) == 0); @@ -97,12 +99,12 @@ int flash_physical_erase(int offset, int size) return EC_SUCCESS; } -int flash_physical_get_protect(int bank) +int crec_flash_physical_get_protect(int bank) { return __host_flash_protect[bank]; } -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { int i; uint32_t flags = EC_FLASH_PROTECT_ALL_NOW; @@ -114,20 +116,19 @@ uint32_t flash_physical_get_protect_flags(void) return flags; } -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { memset(__host_flash_protect, 1, all ? PHYSICAL_BANKS : WP_BANK_COUNT); return EC_SUCCESS; } -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ALL_NOW; } -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { uint32_t ret = 0; @@ -146,13 +147,13 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) return ret; } -int flash_pre_init(void) +int crec_flash_pre_init(void) { uint32_t prot_flags; flash_get_persistent(); - prot_flags = flash_get_protect(); + prot_flags = crec_flash_get_protect(); if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) { /* @@ -161,13 +162,14 @@ int flash_pre_init(void) */ if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) && !(prot_flags & EC_FLASH_PROTECT_RO_NOW)) { - int rv = flash_set_protect(EC_FLASH_PROTECT_RO_NOW, - EC_FLASH_PROTECT_RO_NOW); + int rv = + crec_flash_set_protect(EC_FLASH_PROTECT_RO_NOW, + EC_FLASH_PROTECT_RO_NOW); if (rv) return rv; /* Re-read flags */ - prot_flags = flash_get_protect(); + prot_flags = crec_flash_get_protect(); } } diff --git a/chip/host/gpio.c b/chip/host/gpio.c index 3c15205ad5..d80d93dcf7 100644 --- a/chip/host/gpio.c +++ b/chip/host/gpio.c @@ -1,12 +1,10 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* GPIO module for emulator */ -#include "console.h" - #include "common.h" #include "console.h" #include "gpio.h" @@ -19,8 +17,8 @@ static int gpio_interrupt_enabled[GPIO_COUNT]; /* Create a dictionary of names for debug console print */ #define GPIO_INT(name, pin, flags, signal) #name, #define GPIO(name, pin, flags) #name, -const char * gpio_names[GPIO_COUNT] = { - #include "gpio.wrap" +const char *gpio_names[GPIO_COUNT] = { +#include "gpio.wrap" }; #undef GPIO #undef GPIO_INT @@ -92,7 +90,7 @@ test_mockable void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, } test_mockable void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) + enum gpio_alternate_func func) { /* Nothing */ } diff --git a/chip/host/host_test.h b/chip/host/host_test.h index e2bf5448c3..39516f751e 100644 --- a/chip/host/host_test.h +++ b/chip/host/host_test.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,4 +14,4 @@ /* Get emulator executable name */ const char *__get_prog_name(void); -#endif /* __CROS_EC_HOST_TEST_H */ +#endif /* __CROS_EC_HOST_TEST_H */ diff --git a/chip/host/i2c.c b/chip/host/i2c.c index 8e6f086b4f..3fddbbbac5 100644 --- a/chip/host/i2c.c +++ b/chip/host/i2c.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -15,7 +15,7 @@ struct i2c_dev { int port; - uint16_t slave_addr_flags; + uint16_t addr_flags; int valid; }; @@ -29,7 +29,7 @@ static void detach_init(void) } DECLARE_HOOK(HOOK_INIT, detach_init, HOOK_PRIO_FIRST); -int test_detach_i2c(const int port, const uint16_t slave_addr_flags) +int test_detach_i2c(const int port, const uint16_t addr_flags) { int i; @@ -41,20 +41,19 @@ int test_detach_i2c(const int port, const uint16_t slave_addr_flags) return EC_ERROR_OVERFLOW; detached_devs[i].port = port; - detached_devs[i].slave_addr_flags = slave_addr_flags; + detached_devs[i].addr_flags = addr_flags; detached_devs[i].valid = 1; return EC_SUCCESS; } -int test_attach_i2c(const int port, const uint16_t slave_addr_flags) +int test_attach_i2c(const int port, const uint16_t addr_flags) { int i; for (i = 0; i < MAX_DETACHED_DEV_COUNT; ++i) - if (detached_devs[i].valid && - detached_devs[i].port == port && - detached_devs[i].slave_addr_flags == slave_addr_flags) + if (detached_devs[i].valid && detached_devs[i].port == port && + detached_devs[i].addr_flags == addr_flags) break; if (i == MAX_DETACHED_DEV_COUNT) @@ -64,32 +63,28 @@ int test_attach_i2c(const int port, const uint16_t slave_addr_flags) return EC_SUCCESS; } -static int test_check_detached(const int port, - const uint16_t slave_addr_flags) +static int test_check_detached(const int port, const uint16_t addr_flags) { int i; for (i = 0; i < MAX_DETACHED_DEV_COUNT; ++i) - if (detached_devs[i].valid && - detached_devs[i].port == port && - detached_devs[i].slave_addr_flags == slave_addr_flags) + if (detached_devs[i].valid && detached_devs[i].port == port && + detached_devs[i].addr_flags == addr_flags) return 1; return 0; } -int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) +int chip_i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size, int flags) { const struct test_i2c_xfer *p; int rv; - if (test_check_detached(port, slave_addr_flags)) + if (test_check_detached(port, addr_flags)) return EC_ERROR_UNKNOWN; for (p = __test_i2c_xfer; p < __test_i2c_xfer_end; ++p) { - rv = p->routine(port, slave_addr_flags, - out, out_size, - in, in_size, flags); + rv = p->routine(port, addr_flags, out, out_size, in, in_size, + flags); if (rv != EC_ERROR_INVAL) return rv; } diff --git a/chip/host/keyboard_raw.c b/chip/host/keyboard_raw.c index 3e1f755f7f..47b9a7dda0 100644 --- a/chip/host/keyboard_raw.c +++ b/chip/host/keyboard_raw.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/host/lpc.c b/chip/host/lpc.c index dd64be9275..78619c5b75 100644 --- a/chip/host/lpc.c +++ b/chip/host/lpc.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/host/persistence.c b/chip/host/persistence.c index 90856b3bdf..369f58034b 100644 --- a/chip/host/persistence.c +++ b/chip/host/persistence.c @@ -1,15 +1,49 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Persistence module for emulator */ -#include -#include +/* This provides storage that can be opened, closed and reopened by the + * current process at will, whose naming even remains stable across multiple + * invocations of the same executable, while providing a unique name for + * each executable (as determined by path) that uses these routines. + * + * Useful when semi-permanent storage is required even with many + * similar processes running in parallel (e.g. in a highly parallel + * test suite run. + * + * mkstemp and friends don't provide these properties which is why we have + * this homegrown implementation of something similar-yet-different. + */ + +#include "builtin/assert.h" +#include "util.h" + #include #include +#include +#include + +/* The longest path in a chroot seems to be about 280 characters (as of + * April 2021) so define a cut-off instead of just hoping for the best: + * If we were to run into a path that is nearly PATH_MAX bytes long, + * file names could end up being reused inadvertedly because the various + * snprintf calls would cut off the trailing characters, so the "tag" (and + * maybe more) is gone even though it only exists for differentiation. + * + * Instead bail out if we encounter a path (to an executable using these + * routines) that is longer than we expect. + * + * Round up for some spare room because why not? + */ +static const int max_len = 300; + +/* This must be at least the size of the prefix added in get_storage_path */ +static const int max_prefix_len = 25; + static void get_storage_path(char *out) { char buf[PATH_MAX]; @@ -19,6 +53,8 @@ static void get_storage_path(char *out) sz = readlink("/proc/self/exe", buf, PATH_MAX - 1); buf[sz] = '\0'; + ASSERT(sz <= max_len); + /* replace / by underscores in the path to get the shared memory name */ current = strchr(buf, '/'); while (current) { @@ -26,21 +62,32 @@ static void get_storage_path(char *out) current = strchr(current, '/'); } - snprintf(out, PATH_MAX - 1, "/dev/shm/EC_persist_%s", buf); + sz = snprintf(out, PATH_MAX - 1, "/dev/shm/EC_persist_%.*s", max_len, + buf); + ASSERT(sz > 0); + out[PATH_MAX - 1] = '\0'; + + ASSERT(sz <= max_len + max_prefix_len); } FILE *get_persistent_storage(const char *tag, const char *mode) { char buf[PATH_MAX]; char path[PATH_MAX]; + int sz; + + /* There's no longer tag in use right now, and there shouldn't be. */ + ASSERT(strlen(tag) < 32); /* * The persistent storage with tag 'foo' for test 'bar' would * be named 'bar_persist_foo' */ get_storage_path(buf); - snprintf(path, PATH_MAX - 1, "%s_%s", buf, tag); + sz = snprintf(path, PATH_MAX - 1, "%.*s_%32s", max_len + max_prefix_len, + buf, tag); + ASSERT(sz > 0); path[PATH_MAX - 1] = '\0'; return fopen(path, mode); @@ -55,9 +102,15 @@ void remove_persistent_storage(const char *tag) { char buf[PATH_MAX]; char path[PATH_MAX]; + int sz; + + /* There's no longer tag in use right now, and there shouldn't be. */ + ASSERT(strlen(tag) < 32); get_storage_path(buf); - snprintf(path, PATH_MAX - 1, "%s_%s", buf, tag); + sz = snprintf(path, PATH_MAX - 1, "%.*s_%32s", max_len + max_prefix_len, + buf, tag); + ASSERT(sz > 0); path[PATH_MAX - 1] = '\0'; unlink(path); diff --git a/chip/host/persistence.h b/chip/host/persistence.h index a473f8dfb0..479788815f 100644 --- a/chip/host/persistence.h +++ b/chip/host/persistence.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/host/reboot.c b/chip/host/reboot.c index e932c5f11a..59e15ee81d 100644 --- a/chip/host/reboot.c +++ b/chip/host/reboot.c @@ -1,18 +1,19 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Emulator self-reboot procedure */ -#include -#include - #include "console.h" #include "host_test.h" #include "reboot.h" #include "test_util.h" +#include + +#include + #ifdef TEST_FUZZ /* reboot breaks fuzzing, let's just not do it. */ void emulator_reboot(void) @@ -20,10 +21,9 @@ void emulator_reboot(void) ccprints("Emulator would reboot here. Fuzzing: doing nothing."); } #else /* !TEST_FUZZ */ -noreturn -void emulator_reboot(void) +noreturn void emulator_reboot(void) { - char *argv[] = {strdup(__get_prog_name()), NULL}; + char *argv[] = { strdup(__get_prog_name()), NULL }; emulator_flush(); execv(__get_prog_name(), argv); while (1) diff --git a/chip/host/reboot.h b/chip/host/reboot.h index 1c1201f451..e382db0adf 100644 --- a/chip/host/reboot.h +++ b/chip/host/reboot.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,9 +10,10 @@ #include -#ifndef TEST_FUZZ +#if !(defined(TEST_FUZZ) || defined(CONFIG_ZTEST)) noreturn #endif -void emulator_reboot(void); + void + emulator_reboot(void); -#endif +#endif /* __CROS_EC_REBOOT_H */ diff --git a/chip/host/registers.h b/chip/host/registers.h index 7347ce04d3..3c75686b40 100644 --- a/chip/host/registers.h +++ b/chip/host/registers.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/host/spi_controller.c b/chip/host/spi_controller.c new file mode 100644 index 0000000000..ae6e2c9346 --- /dev/null +++ b/chip/host/spi_controller.c @@ -0,0 +1,41 @@ +/* Copyright 2019 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Mock SPI Controller driver for unit test. + */ + +#include "common.h" +#include "gpio.h" +#include "spi.h" + +#include + +test_mockable int spi_enable(const struct spi_device_t *spi_device, int enable) +{ + return EC_SUCCESS; +} + +test_mockable int spi_transaction(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, + uint8_t *rxdata, int rxlen) +{ + return EC_SUCCESS; +} + +test_mockable int spi_transaction_async(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, + uint8_t *rxdata, int rxlen) +{ + return EC_SUCCESS; +} + +test_mockable int spi_transaction_flush(const struct spi_device_t *spi_device) +{ + return EC_SUCCESS; +} + +test_mockable int spi_transaction_wait(const struct spi_device_t *spi_device) +{ + return EC_SUCCESS; +} diff --git a/chip/host/spi_master.c b/chip/host/spi_master.c deleted file mode 100644 index 1900e7b7a8..0000000000 --- a/chip/host/spi_master.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Mock Master SPI driver for unit test. - */ - -#include - -#include "common.h" -#include "gpio.h" - -#include "spi.h" - -test_mockable int spi_enable(int port, int enable) -{ - return EC_SUCCESS; -} - -test_mockable int spi_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - return EC_SUCCESS; -} - -test_mockable int spi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - return EC_SUCCESS; -} - -test_mockable int spi_transaction_flush(const struct spi_device_t *spi_device) -{ - return EC_SUCCESS; -} - -test_mockable int spi_transaction_wait(const struct spi_device_t *spi_device) -{ - return EC_SUCCESS; -} diff --git a/chip/host/system.c b/chip/host/system.c index 66d3442467..ae650e3f9f 100644 --- a/chip/host/system.c +++ b/chip/host/system.c @@ -1,10 +1,11 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* System module for emulator */ +#include "builtin/assert.h" #include "common.h" #include "ec_commands.h" #include "host_test.h" @@ -43,15 +44,12 @@ static void ramdata_get_persistent(void) { FILE *f = get_persistent_storage("ramdata", "rb"); - if (f == NULL) { - fprintf(stderr, - "No RAM data found. Initializing to 0x00.\n"); + if ((f == NULL) || (fread(__ram_data, RAM_DATA_SIZE, 1, f) != 1)) { + fprintf(stderr, "No RAM data found. Initializing to 0x00.\n"); memset(__ram_data, 0, RAM_DATA_SIZE); return; } - fread(__ram_data, RAM_DATA_SIZE, 1, f); - release_persistent_storage(f); /* @@ -76,9 +74,8 @@ static uint32_t get_image_copy(void) FILE *f = get_persistent_storage("image_copy", "rb"); uint32_t ret; - if (f == NULL) + if ((f == NULL) || (fread(&ret, sizeof(ret), 1, f) != 1)) return EC_IMAGE_UNKNOWN; - fread(&ret, sizeof(ret), 1, f); release_persistent_storage(f); remove_persistent_storage("image_copy"); @@ -100,9 +97,8 @@ static uint32_t load_reset_flags(void) FILE *f = get_persistent_storage("reset_flags", "rb"); uint32_t ret; - if (f == NULL) + if ((f == NULL) || (fread(&ret, sizeof(ret), 1, f) != 1)) return EC_RESET_FLAG_POWER_ON; - fread(&ret, sizeof(ret), 1, f); release_persistent_storage(f); remove_persistent_storage("reset_flags"); @@ -123,9 +119,8 @@ static int load_time(timestamp_t *t) { FILE *f = get_persistent_storage("time", "rb"); - if (f == NULL) + if ((f == NULL) || (fread(t, sizeof(*t), 1, f) != 1)) return 0; - fread(t, sizeof(*t), 1, f); release_persistent_storage(f); remove_persistent_storage("time"); @@ -134,14 +129,14 @@ static int load_time(timestamp_t *t) test_mockable struct panic_data *panic_get_data(void) { - return (struct panic_data *) - (__ram_data + RAM_DATA_SIZE - sizeof(struct panic_data)); + return (struct panic_data *)(__ram_data + RAM_DATA_SIZE - + sizeof(struct panic_data)); } -test_mockable uintptr_t get_panic_data_start() +test_mockable uintptr_t get_panic_data_start(void) { - return (uintptr_t) - (__ram_data + RAM_DATA_SIZE - sizeof(struct panic_data)); + return (uintptr_t)(__ram_data + RAM_DATA_SIZE - + sizeof(struct panic_data)); } test_mockable void system_reset(int flags) @@ -224,28 +219,27 @@ int system_set_scratchpad(uint32_t value) { FILE *f = get_persistent_storage("scratchpad", "w"); - fprintf(f, "%lu", value); + fprintf(f, "%u", value); release_persistent_storage(f); return EC_SUCCESS; } -uint32_t system_get_scratchpad(void) +int system_get_scratchpad(uint32_t *value) { FILE *f = get_persistent_storage("scratchpad", "r"); - uint32_t value; int success; if (f == NULL) - return 0; + return EC_ERROR_UNKNOWN; - success = fscanf(f, "%u", &value); + success = fscanf(f, "%u", value); release_persistent_storage(f); if (success) - return value; + return EC_SUCCESS; else - return 0; + return EC_ERROR_UNKNOWN; } static void __jump_resetvec(void) @@ -286,3 +280,10 @@ void system_pre_init(void) *(uintptr_t *)(__host_flash + CONFIG_RW_MEM_OFF + 4) = (uintptr_t)__rw_jump_resetvec; } + +test_mockable enum ec_error_list +get_ap_reset_stats(struct ap_reset_log_entry *reset_log_entries, + size_t num_reset_log_entries, uint32_t *resets_since_ec_boot) +{ + return EC_ERROR_INVAL; +} diff --git a/chip/host/trng.c b/chip/host/trng.c index 8407aa6ea1..f67dd6c4db 100644 --- a/chip/host/trng.c +++ b/chip/host/trng.c @@ -1,5 +1,5 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -14,27 +14,32 @@ #error "This fake trng driver must not be used in non-test builds." #endif +#include "common.h" + #include #include /* Only valid for host */ -#include "common.h" - static unsigned int seed; -test_mockable void init_trng(void) +test_mockable void trng_init(void) { seed = 0; srand(seed); } -test_mockable void exit_trng(void) +test_mockable void trng_exit(void) +{ +} + +test_mockable uint32_t trng_rand(void) { + return (uint32_t)rand_r(&seed); } -test_mockable void rand_bytes(void *buffer, size_t len) +test_mockable void trng_rand_bytes(void *buffer, size_t len) { uint8_t *b, *end; - for (b = buffer, end = b+len; b != end; b++) + for (b = buffer, end = b + len; b != end; b++) *b = (uint8_t)rand_r(&seed); } diff --git a/chip/host/uart.c b/chip/host/uart.c index 578924612f..71e8345196 100644 --- a/chip/host/uart.c +++ b/chip/host/uart.c @@ -1,16 +1,11 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* UART driver for emulator */ -#include -#include -#include -#include -#include - +#include "builtin/assert.h" #include "common.h" #include "queue.h" #include "task.h" @@ -18,6 +13,13 @@ #include "uart.h" #include "util.h" +#include +#include + +#include +#include +#include + static int stopped = 1; static int init_done; @@ -55,7 +57,6 @@ static void test_capture_char(char c) capture_buf[capture_size++] = c; } - const char *test_get_captured_console(void) { return (const char *)capture_buf; @@ -190,6 +191,6 @@ void uart_init(void) pthread_mutex_unlock(&mutex); #endif - stopped = 1; /* Not transmitting yet */ + stopped = 1; /* Not transmitting yet */ init_done = 1; } diff --git a/chip/host/usb_pd_phy.c b/chip/host/usb_pd_phy.c index ba81b986ad..aa5f022f3e 100644 --- a/chip/host/usb_pd_phy.c +++ b/chip/host/usb_pd_phy.c @@ -1,8 +1,9 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "crc.h" @@ -37,9 +38,9 @@ static struct pd_physical { int verified_idx; } pd_phy[CONFIG_USB_PD_PORT_MAX_COUNT]; -static const uint16_t enc4b5b[] = { - 0x1E, 0x09, 0x14, 0x15, 0x0A, 0x0B, 0x0E, 0x0F, 0x12, 0x13, 0x16, - 0x17, 0x1A, 0x1B, 0x1C, 0x1D}; +static const uint16_t enc4b5b[] = { 0x1E, 0x09, 0x14, 0x15, 0x0A, 0x0B, + 0x0E, 0x0F, 0x12, 0x13, 0x16, 0x17, + 0x1A, 0x1B, 0x1C, 0x1D }; /* Test utilities */ static void pd_test_reset_phy(int port) @@ -216,7 +217,6 @@ int pd_test_tx_msg_verify_crc(int port) return pd_test_tx_msg_verify_word(port, crc32_result()); } - /* Mock functions */ void pd_init_dequeue(int port) diff --git a/chip/ish/aontaskfw/ipapg.S b/chip/ish/aontaskfw/ipapg.S index f0d3f8c554..305b9a0fb6 100755 --- a/chip/ish/aontaskfw/ipapg.S +++ b/chip/ish/aontaskfw/ipapg.S @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/ish/aontaskfw/ish_aon_defs.h b/chip/ish/aontaskfw/ish_aon_defs.h index 3cc3a491c0..0b3990100a 100644 --- a/chip/ish/aontaskfw/ish_aon_defs.h +++ b/chip/ish/aontaskfw/ish_aon_defs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/ish/aontaskfw/ish_aon_share.h b/chip/ish/aontaskfw/ish_aon_share.h index 20b36ec2b2..b986150b73 100644 --- a/chip/ish/aontaskfw/ish_aon_share.h +++ b/chip/ish/aontaskfw/ish_aon_share.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,13 +11,12 @@ #include "power_mgt.h" /* magic ID for valid aontask image check */ -#define AON_MAGIC_ID 0x544E4F41 /*"AONT"*/ +#define AON_MAGIC_ID 0x544E4F41 /*"AONT"*/ /* aontask error code */ -#define AON_SUCCESS 0 -#define AON_ERROR_NOT_SUPPORT_POWER_MODE 1 -#define AON_ERROR_DMA_FAILED 2 - +#define AON_SUCCESS 0 +#define AON_ERROR_NOT_SUPPORT_POWER_MODE 1 +#define AON_ERROR_DMA_FAILED 2 /* shared data structure between main FW and aontask */ struct ish_aon_share { diff --git a/chip/ish/aontaskfw/ish_aontask.c b/chip/ish/aontaskfw/ish_aontask.c index ab9d02abbf..6f2d9c9f2d 100644 --- a/chip/ish/aontaskfw/ish_aontask.c +++ b/chip/ish/aontaskfw/ish_aontask.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -45,8 +45,8 @@ #include "common.h" #include "ia_structs.h" -#include "ish_aon_share.h" #include "ish_aon_defs.h" +#include "ish_aon_share.h" #include "ish_dma.h" #include "power_mgt.h" @@ -64,9 +64,9 @@ * AON_IDT_ENTRY_VEC_FIRST ~ AON_IDT_ENTRY_VEC_LAST */ #ifdef CONFIG_ISH_NEW_PM -#define AON_IDT_ENTRY_VEC_LAST ISH_PMU_WAKEUP_VEC +#define AON_IDT_ENTRY_VEC_LAST ISH_PMU_WAKEUP_VEC #else -#define AON_IDT_ENTRY_VEC_FIRST ISH_PMU_WAKEUP_VEC +#define AON_IDT_ENTRY_VEC_FIRST ISH_PMU_WAKEUP_VEC #endif #ifdef CONFIG_ISH_PM_RESET_PREP @@ -76,21 +76,71 @@ * (if CONFIG_ISH_PM_RESET_PREP defined) */ #ifdef CONFIG_ISH_NEW_PM -#define AON_IDT_ENTRY_VEC_FIRST ISH_RESET_PREP_VEC +#define AON_IDT_ENTRY_VEC_FIRST ISH_RESET_PREP_VEC #else -#define AON_IDT_ENTRY_VEC_LAST ISH_RESET_PREP_VEC +#define AON_IDT_ENTRY_VEC_LAST ISH_RESET_PREP_VEC #endif #else /* only need handle single PMU wakeup interrupt */ #ifdef CONFIG_ISH_NEW_PM -#define AON_IDT_ENTRY_VEC_FIRST ISH_PMU_WAKEUP_VEC +#define AON_IDT_ENTRY_VEC_FIRST ISH_PMU_WAKEUP_VEC #else -#define AON_IDT_ENTRY_VEC_LAST ISH_PMU_WAKEUP_VEC +#define AON_IDT_ENTRY_VEC_LAST ISH_PMU_WAKEUP_VEC #endif #endif static void handle_reset(enum ish_pm_state pm_state); +#if defined(CHIP_VARIANT_ISH5P4) +static void sb_upstream_write_raw_base(uint32_t addr, uint32_t attr, + uint32_t data, uint32_t sairs, + uint8_t addr48, uint16_t addr_hi) +{ + uint32_t eflags; + uint32_t addr_hi_32; + + addr_hi_32 = addr_hi | (1 << 31); + + eflags = interrupt_lock(); + + PMU_VNN_REQ = (1 << VNN_ID_SIDEBAND); + while (!(PMU_VNN_REQ_ACK & PMU_VNN_REQ_ACK_STATUS)) + continue; + + if (dma_poll(SBEP_REG_UP_MSG_STATUS_ADDR, 0, UP_STATUS_BUSY_MASK) == + DMA_RC_OK) { + SBEP_REG_UP_MSG_REQ_ADDR_LOW = addr; + + if (addr48) { + SBEP_REG_UP_MSG_REQ_ADDR_HIGH = addr_hi_32; + } else { + SBEP_REG_UP_MSG_REQ_ADDR_HIGH = 0; + } + + SBEP_REG_UP_MSG_REQ_ATTR = attr; + SBEP_REG_UP_MSG_REQ_DATA = data; + SBEP_REG_UP_MSG_REQ_EH = sairs; + SBEP_REG_UP_MSG_COMMAND = SBEP_CMD_WRITE; + + dma_poll(SBEP_REG_UP_MSG_STATUS_ADDR, 0, UP_STATUS_BUSY_MASK); + dma_poll(SBEP_REG_UP_MSG_STATUS_ADDR, UP_STATUS_MSG_SENT_MASK, + UP_STATUS_MSG_SENT_MASK); + SBEP_REG_UP_MSG_STATUS = UP_STATUS_MSG_SENT_CLR; + } + + PMU_VNN_REQ = (1 << VNN_ID_SIDEBAND); + interrupt_unlock(eflags); +} + +static void sb_upstream_write_raw(uint32_t addr, uint32_t attr, uint32_t data, + uint32_t sairs) +{ + addr = addr & 0x0000FFFF; + + sb_upstream_write_raw_base(addr, attr, data, sairs, 0, 0); +} +#endif + /* ISR for PMU wakeup interrupt */ static void pmu_wakeup_isr(void) { @@ -101,7 +151,7 @@ static void pmu_wakeup_isr(void) IOAPIC_EOI_REG = ISH_PMU_WAKEUP_VEC; LAPIC_EOI_REG = 0x0; - __asm__ volatile ("iret;"); + __asm__ volatile("iret;"); __builtin_unreachable(); } @@ -157,14 +207,15 @@ static void reset_prep_isr(void) * --------------------------- */ -static struct idt_entry aon_idt[AON_IDT_ENTRY_VEC_LAST - - AON_IDT_ENTRY_VEC_FIRST + 1]; +static struct idt_entry + aon_idt[AON_IDT_ENTRY_VEC_LAST - AON_IDT_ENTRY_VEC_FIRST + 1]; static struct idt_header aon_idt_hdr = { .limit = (sizeof(struct idt_entry) * (AON_IDT_ENTRY_VEC_LAST + 1)) - 1, .entries = (struct idt_entry *)((uint32_t)&aon_idt - - (sizeof(struct idt_entry) * AON_IDT_ENTRY_VEC_FIRST)) + (sizeof(struct idt_entry) * + AON_IDT_ENTRY_VEC_FIRST)) }; /** @@ -245,13 +296,9 @@ static ldt_entry aon_ldt[2] = { * limit: 0xFFFFFFFF * flag: 0x9B, Present = 1, DPL = 0, code segment */ - { - .dword_lo = GEN_GDT_DESC_LO(0x0, 0xFFFFFFFF, - GDT_DESC_CODE_FLAGS), + { .dword_lo = GEN_GDT_DESC_LO(0x0, 0xFFFFFFFF, GDT_DESC_CODE_FLAGS), - .dword_up = GEN_GDT_DESC_UP(0x0, 0xFFFFFFFF, - GDT_DESC_CODE_FLAGS) - }, + .dword_up = GEN_GDT_DESC_UP(0x0, 0xFFFFFFFF, GDT_DESC_CODE_FLAGS) }, /** * entry 1 for data segment @@ -259,16 +306,11 @@ static ldt_entry aon_ldt[2] = { * limit: 0xFFFFFFFF * flag: 0x93, Present = 1, DPL = 0, data segment */ - { - .dword_lo = GEN_GDT_DESC_LO(0x0, 0xFFFFFFFF, - GDT_DESC_DATA_FLAGS), + { .dword_lo = GEN_GDT_DESC_LO(0x0, 0xFFFFFFFF, GDT_DESC_DATA_FLAGS), - .dword_up = GEN_GDT_DESC_UP(0x0, 0xFFFFFFFF, - GDT_DESC_DATA_FLAGS) - } + .dword_up = GEN_GDT_DESC_UP(0x0, 0xFFFFFFFF, GDT_DESC_DATA_FLAGS) } }; - /* shared data structure between main FW and aon task */ struct ish_aon_share aon_share = { .magic_id = AON_MAGIC_ID, @@ -282,15 +324,14 @@ struct ish_aon_share aon_share = { /* snowball structure */ #if defined(CHIP_FAMILY_ISH3) /* on ISH3, reused ISH2PMC IPC message registers */ -#define SNOWBALL_BASE IPC_ISH2PMC_MSG_BASE +#define SNOWBALL_BASE IPC_ISH2PMC_MSG_BASE #else /* from ISH4, used reserved rom part of AON memory */ -#define SNOWBALL_BASE (CONFIG_AON_PERSISTENT_BASE + 256) +#define SNOWBALL_BASE (CONFIG_AON_PERSISTENT_BASE + 256) #endif struct snowball_struct *snowball = (void *)SNOWBALL_BASE; - /* In IMR DDR, ISH FW image has a manifest header */ #define ISH_FW_IMAGE_MANIFEST_HEADER_SIZE (0x1000) @@ -324,30 +365,24 @@ static int store_main_fw(void) uint64_t imr_fw_rw_addr; imr_fw_addr = (((uint64_t)snowball->uma_base_hi << 32) + - snowball->uma_base_lo + - snowball->fw_offset + + snowball->uma_base_lo + snowball->fw_offset + ISH_FW_IMAGE_MANIFEST_HEADER_SIZE); - imr_fw_rw_addr = (imr_fw_addr - + aon_share.main_fw_rw_addr - - CONFIG_RAM_BASE); + imr_fw_rw_addr = + (imr_fw_addr + aon_share.main_fw_rw_addr - CONFIG_RAM_BASE); /* disable BCG (Block Clock Gating) for DMA, DMA can be accessed now */ disable_dma_bcg(); /* store main FW's read and write data region to IMR/UMA DDR */ - ret = ish_dma_copy( - PAGING_CHAN, - imr_fw_rw_addr, - aon_share.main_fw_rw_addr, - aon_share.main_fw_rw_size, - SRAM_TO_UMA); + ret = ish_dma_copy(PAGING_CHAN, imr_fw_rw_addr, + aon_share.main_fw_rw_addr, aon_share.main_fw_rw_size, + SRAM_TO_UMA); /* enable BCG for DMA, DMA can't be accessed now */ enable_dma_bcg(); if (ret != DMA_RC_OK) { - aon_share.last_error = AON_ERROR_DMA_FAILED; aon_share.error_count++; @@ -365,31 +400,24 @@ static int restore_main_fw(void) uint64_t imr_fw_rw_addr; imr_fw_addr = (((uint64_t)snowball->uma_base_hi << 32) + - snowball->uma_base_lo + - snowball->fw_offset + + snowball->uma_base_lo + snowball->fw_offset + ISH_FW_IMAGE_MANIFEST_HEADER_SIZE); - imr_fw_ro_addr = (imr_fw_addr - + aon_share.main_fw_ro_addr - - CONFIG_RAM_BASE); + imr_fw_ro_addr = + (imr_fw_addr + aon_share.main_fw_ro_addr - CONFIG_RAM_BASE); - imr_fw_rw_addr = (imr_fw_addr - + aon_share.main_fw_rw_addr - - CONFIG_RAM_BASE); + imr_fw_rw_addr = + (imr_fw_addr + aon_share.main_fw_rw_addr - CONFIG_RAM_BASE); /* disable BCG (Block Clock Gating) for DMA, DMA can be accessed now */ disable_dma_bcg(); /* restore main FW's read only code and data region from IMR/UMA DDR */ - ret = ish_dma_copy( - PAGING_CHAN, - aon_share.main_fw_ro_addr, - imr_fw_ro_addr, - aon_share.main_fw_ro_size, - UMA_TO_SRAM); + ret = ish_dma_copy(PAGING_CHAN, aon_share.main_fw_ro_addr, + imr_fw_ro_addr, aon_share.main_fw_ro_size, + UMA_TO_SRAM); if (ret != DMA_RC_OK) { - aon_share.last_error = AON_ERROR_DMA_FAILED; aon_share.error_count++; @@ -400,19 +428,14 @@ static int restore_main_fw(void) } /* restore main FW's read and write data region from IMR/UMA DDR */ - ret = ish_dma_copy( - PAGING_CHAN, - aon_share.main_fw_rw_addr, - imr_fw_rw_addr, - aon_share.main_fw_rw_size, - UMA_TO_SRAM - ); + ret = ish_dma_copy(PAGING_CHAN, aon_share.main_fw_rw_addr, + imr_fw_rw_addr, aon_share.main_fw_rw_size, + UMA_TO_SRAM); /* enable BCG for DMA, DMA can't be accessed now */ enable_dma_bcg(); if (ret != DMA_RC_OK) { - aon_share.last_error = AON_ERROR_DMA_FAILED; aon_share.error_count++; @@ -424,10 +447,10 @@ static int restore_main_fw(void) #if defined(CHIP_FAMILY_ISH3) /* on ISH3, the last SRAM bank is reserved for AON use */ -#define SRAM_POWER_OFF_BANKS (CONFIG_RAM_BANKS - 1) +#define SRAM_POWER_OFF_BANKS (CONFIG_RAM_BANKS - 1) #elif defined(CHIP_FAMILY_ISH4) || defined(CHIP_FAMILY_ISH5) /* ISH4 and ISH5 have separate AON memory, can power off entire main SRAM */ -#define SRAM_POWER_OFF_BANKS CONFIG_RAM_BANKS +#define SRAM_POWER_OFF_BANKS CONFIG_RAM_BANKS #else #error "CHIP_FAMILY_ISH(3|4|5) must be defined" #endif @@ -436,33 +459,33 @@ static int restore_main_fw(void) * check SRAM bank i power gated status in PMU_SRAM_PG_EN register * 1: power gated 0: not power gated */ -#define BANK_PG_STATUS(i) (PMU_SRAM_PG_EN & (0x1 << (i))) +#define BANK_PG_STATUS(i) (PMU_SRAM_PG_EN & (0x1 << (i))) /* enable power gate of a SRAM bank */ -#define BANK_PG_ENABLE(i) (PMU_SRAM_PG_EN |= (0x1 << (i))) +#define BANK_PG_ENABLE(i) (PMU_SRAM_PG_EN |= (0x1 << (i))) /* disable power gate of a SRAM bank */ -#define BANK_PG_DISABLE(i) (PMU_SRAM_PG_EN &= ~(0x1 << (i))) +#define BANK_PG_DISABLE(i) (PMU_SRAM_PG_EN &= ~(0x1 << (i))) /** * check SRAM bank i disabled status in ISH_SRAM_CTRL_CSFGR register * 1: disabled 0: enabled */ -#define BANK_DISABLE_STATUS(i) (ISH_SRAM_CTRL_CSFGR & (0x1 << ((i) + 4))) +#define BANK_DISABLE_STATUS(i) (ISH_SRAM_CTRL_CSFGR & (0x1 << ((i) + 4))) /* enable a SRAM bank in ISH_SRAM_CTRL_CSFGR register */ -#define BANK_ENABLE(i) (ISH_SRAM_CTRL_CSFGR &= ~(0x1 << ((i) + 4))) +#define BANK_ENABLE(i) (ISH_SRAM_CTRL_CSFGR &= ~(0x1 << ((i) + 4))) /* disable a SRAM bank in ISH_SRAM_CTRL_CSFGR register */ -#define BANK_DISABLE(i) (ISH_SRAM_CTRL_CSFGR |= (0x1 << ((i) + 4))) +#define BANK_DISABLE(i) (ISH_SRAM_CTRL_CSFGR |= (0x1 << ((i) + 4))) /* SRAM needs time to warm up after power on */ -#define SRAM_WARM_UP_DELAY_CNT 10 +#define SRAM_WARM_UP_DELAY_CNT 10 /* SRAM needs time to enter retention mode */ -#define CYCLES_PER_US 100 -#define SRAM_RETENTION_US_DELAY 5 -#define SRAM_RETENTION_CYCLES_DELAY (SRAM_RETENTION_US_DELAY * CYCLES_PER_US) +#define CYCLES_PER_US 100 +#define SRAM_RETENTION_US_DELAY 5 +#define SRAM_RETENTION_CYCLES_DELAY (SRAM_RETENTION_US_DELAY * CYCLES_PER_US) static void sram_power(int on) { @@ -485,10 +508,9 @@ static void sram_power(int on) erase_cfg = (((bank_size - 4) >> 2) << 2) | 0x1; for (i = 0; i < SRAM_POWER_OFF_BANKS; i++) { - - if (on && (BANK_PG_STATUS(i) || (!IS_ENABLED(CONFIG_ISH_NEW_PM) - && BANK_DISABLE_STATUS(i)))) { - + if (on && + (BANK_PG_STATUS(i) || (!IS_ENABLED(CONFIG_ISH_NEW_PM) && + BANK_DISABLE_STATUS(i)))) { /* power on and enable a bank */ BANK_PG_DISABLE(i); @@ -519,13 +541,12 @@ static void sram_power(int on) * booting ISH */ ISH_SRAM_CTRL_INTR = 0xFFFFFFFF; - } } #define RTC_TICKS_IN_SECOND 32768 -static __maybe_unused uint64_t get_rtc(void) +static __maybe_unused uint64_t get_rtc(void) { uint32_t lower; uint32_t upper; @@ -645,8 +666,7 @@ static void handle_d0i2(void) } /* set main SRAM into retention mode*/ - PMU_LDO_CTRL = PMU_LDO_ENABLE_BIT - | PMU_LDO_RETENTION_BIT; + PMU_LDO_CTRL = PMU_LDO_ENABLE_BIT | PMU_LDO_RETENTION_BIT; /* delay some cycles before halt */ delay(SRAM_RETENTION_CYCLES_DELAY); @@ -670,6 +690,10 @@ static void handle_d0i2(void) clear_vnnred_aoncg(); + if (IS_ENABLED(CONFIG_ISH_NEW_PM) && + (PMU_RST_PREP & PMU_RST_PREP_AVAIL)) + handle_reset(ISH_PM_STATE_RESET_PREP); + /* set main SRAM intto normal mode */ PMU_LDO_CTRL = PMU_LDO_ENABLE_BIT; @@ -696,6 +720,13 @@ static void handle_d0i3(void) aon_share.pg_exit = 0; } +#if defined(CHIP_VARIANT_ISH5P4) + /* Set PMC LTR to 2ms before DMA copy */ + if (IS_ENABLED(CONFIG_ISH_NEW_PM)) + sb_upstream_write_raw(0, LTR_CMD_ATTR, LTR_CMD_DATA_2MS, + SBEP_PMC_SAIRS_VAL); +#endif + /* store main FW 's context to IMR DDR from main SRAM */ ret = store_main_fw(); @@ -706,6 +737,13 @@ static void handle_d0i3(void) /* power off main SRAM */ sram_power(0); +#if defined(CHIP_VARIANT_ISH5P4) + /* Set LTR to a large number after DMA copy done */ + if (IS_ENABLED(CONFIG_ISH_NEW_PM)) + sb_upstream_write_raw(0, LTR_CMD_ATTR, LTR_CMD_DATA_INFINITE, + SBEP_PMC_SAIRS_VAL); +#endif + set_vnnred_aoncg(); if (IS_ENABLED(CONFIG_ISH_IPAPG) && is_ipapg_allowed()) { @@ -725,6 +763,10 @@ static void handle_d0i3(void) clear_vnnred_aoncg(); + if (IS_ENABLED(CONFIG_ISH_NEW_PM) && + (PMU_RST_PREP & PMU_RST_PREP_AVAIL)) + handle_reset(ISH_PM_STATE_RESET_PREP); + /* power on main SRAM */ sram_power(1); @@ -734,6 +776,13 @@ static void handle_d0i3(void) aon_share.uma_msb); } +#if defined(CHIP_VARIANT_ISH5P4) + /* Set PMC LTR to 2ms before DMA copy */ + if (IS_ENABLED(CONFIG_ISH_NEW_PM)) + sb_upstream_write_raw(0, LTR_CMD_ATTR, LTR_CMD_DATA_2MS, + SBEP_PMC_SAIRS_VAL); +#endif + /* restore main FW 's context to main SRAM from IMR DDR */ ret = restore_main_fw(); @@ -782,7 +831,7 @@ static void handle_reset(enum ish_pm_state pm_state) * ISH ipc host driver will set DMA_ENABLED_MASK bit when it * is loaded and starts, and clear this bit when it is removed. * - * see: https://github.com/torvalds/linux/blob/master/drivers/ + * see: https://github.com/torvalds/linux/blob/HEAD/drivers/ * hid/intel-ish-hid/ipc/ipc.c * * we have two kinds of reset situations need to handle here: @@ -801,8 +850,8 @@ static void handle_reset(enum ish_pm_state pm_state) * Sx for long time. * */ - if (IPC_ISH_RMP2 & DMA_ENABLED_MASK) { - + if (IS_ENABLED(CONFIG_ISH_NEW_PM) || + (IPC_ISH_RMP2 & DMA_ENABLED_MASK)) { /* clear ISH2HOST doorbell register */ *IPC_ISH2HOST_DOORBELL_ADDR = 0; @@ -827,7 +876,6 @@ static void handle_reset(enum ish_pm_state pm_state) ish_mia_halt(); } - } static void handle_unknown_state(void) @@ -840,22 +888,21 @@ static void handle_unknown_state(void) void ish_aon_main(void) { - /* set PMU wakeup interrupt gate using LDT code segment selector(0x4) */ if (IS_ENABLED(CONFIG_ISH_NEW_PM)) { - aon_idt[AON_IDT_ENTRY_VEC_LAST - - AON_IDT_ENTRY_VEC_FIRST].dword_lo = + aon_idt[AON_IDT_ENTRY_VEC_LAST - AON_IDT_ENTRY_VEC_FIRST] + .dword_lo = GEN_IDT_DESC_LO(&pmu_wakeup_isr, 0x4, IDT_DESC_FLAGS); - aon_idt[AON_IDT_ENTRY_VEC_LAST - - AON_IDT_ENTRY_VEC_FIRST].dword_up = + aon_idt[AON_IDT_ENTRY_VEC_LAST - AON_IDT_ENTRY_VEC_FIRST] + .dword_up = GEN_IDT_DESC_UP(&pmu_wakeup_isr, 0x4, IDT_DESC_FLAGS); } else { - aon_idt[0].dword_lo = GEN_IDT_DESC_LO(&pmu_wakeup_isr, 0x4, - IDT_DESC_FLAGS); + aon_idt[0].dword_lo = + GEN_IDT_DESC_LO(&pmu_wakeup_isr, 0x4, IDT_DESC_FLAGS); - aon_idt[0].dword_up = GEN_IDT_DESC_UP(&pmu_wakeup_isr, 0x4, - IDT_DESC_FLAGS); + aon_idt[0].dword_up = + GEN_IDT_DESC_UP(&pmu_wakeup_isr, 0x4, IDT_DESC_FLAGS); } if (IS_ENABLED(CONFIG_ISH_PM_RESET_PREP)) { @@ -864,39 +911,34 @@ void ish_aon_main(void) * selector(0x4) */ if (IS_ENABLED(CONFIG_ISH_NEW_PM)) { - aon_idt[0].dword_lo = GEN_IDT_DESC_LO(&reset_prep_isr, - 0x4, IDT_DESC_FLAGS); + aon_idt[0].dword_lo = GEN_IDT_DESC_LO( + &reset_prep_isr, 0x4, IDT_DESC_FLAGS); - aon_idt[0].dword_up = GEN_IDT_DESC_UP(&reset_prep_isr, - 0x4, IDT_DESC_FLAGS); + aon_idt[0].dword_up = GEN_IDT_DESC_UP( + &reset_prep_isr, 0x4, IDT_DESC_FLAGS); } else { - aon_idt[AON_IDT_ENTRY_VEC_LAST - - AON_IDT_ENTRY_VEC_FIRST].dword_lo = - GEN_IDT_DESC_LO(&reset_prep_isr, 0x4, - IDT_DESC_FLAGS); - - aon_idt[AON_IDT_ENTRY_VEC_LAST - - AON_IDT_ENTRY_VEC_FIRST].dword_up = - GEN_IDT_DESC_UP(&reset_prep_isr, 0x4, - IDT_DESC_FLAGS); + aon_idt[AON_IDT_ENTRY_VEC_LAST - AON_IDT_ENTRY_VEC_FIRST] + .dword_lo = GEN_IDT_DESC_LO( + &reset_prep_isr, 0x4, IDT_DESC_FLAGS); + + aon_idt[AON_IDT_ENTRY_VEC_LAST - AON_IDT_ENTRY_VEC_FIRST] + .dword_up = GEN_IDT_DESC_UP( + &reset_prep_isr, 0x4, IDT_DESC_FLAGS); } } while (1) { - /** * will start to run from here when switched to aontask from * the second time */ /* save main FW's IDT and load aontask's IDT */ - __asm__ volatile ( - "sidtl %0;\n" - "lidtl %1;\n" - : - : "m" (aon_share.main_fw_idt_hdr), - "m" (aon_idt_hdr) - ); + __asm__ volatile("sidtl %0;\n" + "lidtl %1;\n" + : + : "m"(aon_share.main_fw_idt_hdr), + "m"(aon_idt_hdr)); aon_share.last_error = AON_SUCCESS; @@ -927,11 +969,9 @@ void ish_aon_main(void) } /* restore main FW's IDT and switch back to main FW */ - __asm__ volatile( - "lidtl %0;\n" - : - : "m" (aon_share.main_fw_idt_hdr) - ); + __asm__ volatile("lidtl %0;\n" + : + : "m"(aon_share.main_fw_idt_hdr)); if (IS_ENABLED(CONFIG_ISH_IPAPG) && aon_share.pg_exit) { mainfw_gdt.entries[tr / sizeof(struct gdt_entry)] @@ -939,6 +979,6 @@ void ish_aon_main(void) pg_exit_restore_ctx(); } - __asm__ volatile ("iret;"); + __asm__ volatile("iret;"); } } diff --git a/chip/ish/aontaskfw/ish_aontask.lds.S b/chip/ish/aontaskfw/ish_aontask.lds.S index ca5f54f705..306beef5e9 100644 --- a/chip/ish/aontaskfw/ish_aontask.lds.S +++ b/chip/ish/aontaskfw/ish_aontask.lds.S @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/ish/build.mk b/chip/ish/build.mk index 9f220abd21..3777f9f4ce 100644 --- a/chip/ish/build.mk +++ b/chip/ish/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -20,8 +20,8 @@ endif chip-y+=clock.o gpio.o system.o hwtimer.o uart.o flash.o ish_persistent_data.o chip-$(CONFIG_I2C)+=i2c.o chip-$(CONFIG_WATCHDOG)+=watchdog.o -chip-$(CONFIG_HOSTCMD_HECI)+=host_command_heci.o -chip-$(CONFIG_HOSTCMD_HECI)+=heci.o system_state_subsys.o ipc_heci.o +chip-$(CONFIG_HOST_INTERFACE_HECI)+=host_command_heci.o +chip-$(CONFIG_HOST_INTERFACE_HECI)+=heci.o system_state_subsys.o ipc_heci.o chip-$(CONFIG_HID_HECI)+=hid_subsys.o chip-$(CONFIG_HID_HECI)+=heci.o system_state_subsys.o ipc_heci.o chip-$(CONFIG_DMA_PAGING)+=dma.o diff --git a/chip/ish/clock.c b/chip/ish/clock.c index ac818f5733..133711edf7 100644 --- a/chip/ish/clock.c +++ b/chip/ish/clock.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,13 +7,12 @@ #include "clock.h" #include "common.h" -#include "util.h" #include "power_mgt.h" +#include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) - +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) void clock_init(void) { @@ -30,3 +29,7 @@ void clock_refresh_console_in_use(void) */ ish_pm_refresh_console_in_use(); } + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/ish/config_chip.h b/chip/ish/config_chip.h index 4c884d00cc..b76c302f4e 100644 --- a/chip/ish/config_chip.h +++ b/chip/ish/config_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,18 +15,18 @@ #endif /* Number of IRQ vectors on the ISH */ -#define CONFIG_IRQ_COUNT (VEC_TO_IRQ(255) + 1) +#define CONFIG_IRQ_COUNT (VEC_TO_IRQ(255) + 1) /* Use a bigger console output buffer */ #undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 2048 +#define CONFIG_UART_TX_BUF_SIZE 2048 /* Interval between HOOK_TICK notifications */ -#define HOOK_TICK_INTERVAL_MS 250 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) +#define HOOK_TICK_INTERVAL_MS 250 +#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) /* Maximum number of deferrable functions */ -#define DEFERRABLE_MAX_COUNT 8 +#define DEFERRABLE_MAX_COUNT 8 /* this macro causes 'pause' and reduces loop counts inside loop. */ #define CPU_RELAX() asm volatile("rep; nop" ::: "memory") @@ -36,49 +36,48 @@ /*****************************************************************************/ #ifdef CHIP_VARIANT_ISH5P4 -#define CONFIG_RAM_BASE 0xFF200000 +#define CONFIG_RAM_BASE 0xFF200000 #else -#define CONFIG_RAM_BASE 0xFF000000 +#define CONFIG_RAM_BASE 0xFF000000 #endif -#define CONFIG_RAM_SIZE 0x000A0000 +#define CONFIG_RAM_SIZE 0x000A0000 #ifdef CHIP_VARIANT_ISH5P4 -#define CONFIG_RAM_BANK_SIZE 0x00010000 +#define CONFIG_RAM_BANK_SIZE 0x00010000 #else -#define CONFIG_RAM_BANK_SIZE 0x00008000 +#define CONFIG_RAM_BANK_SIZE 0x00008000 #endif #if defined(CHIP_FAMILY_ISH3) /* On ISH3, there is no separate AON memory; use last 4KB of SRAM */ -#define CONFIG_AON_RAM_BASE 0xFF09F000 -#define CONFIG_AON_RAM_SIZE 0x00001000 +#define CONFIG_AON_RAM_BASE 0xFF09F000 +#define CONFIG_AON_RAM_SIZE 0x00001000 #elif defined(CHIP_FAMILY_ISH4) -#define CONFIG_AON_RAM_BASE 0xFF800000 -#define CONFIG_AON_RAM_SIZE 0x00001000 +#define CONFIG_AON_RAM_BASE 0xFF800000 +#define CONFIG_AON_RAM_SIZE 0x00001000 #elif defined(CHIP_FAMILY_ISH5) -#define CONFIG_AON_RAM_BASE 0xFF800000 -#define CONFIG_AON_RAM_SIZE 0x00002000 +#define CONFIG_AON_RAM_BASE 0xFF800000 +#define CONFIG_AON_RAM_SIZE 0x00002000 #else #error "CHIP_FAMILY_ISH(3|4|5) must be defined" #endif /* The end of the AON memory is reserved for read-only use */ -#define CONFIG_AON_PERSISTENT_SIZE 0x180 -#define CONFIG_AON_PERSISTENT_BASE (CONFIG_AON_RAM_BASE \ - + CONFIG_AON_RAM_SIZE \ - - CONFIG_AON_PERSISTENT_SIZE) +#define CONFIG_AON_PERSISTENT_SIZE 0x180 +#define CONFIG_AON_PERSISTENT_BASE \ + (CONFIG_AON_RAM_BASE + CONFIG_AON_RAM_SIZE - CONFIG_AON_PERSISTENT_SIZE) /* Store persistent panic data in AON memory. */ -#define CONFIG_PANIC_DATA_BASE (&(ish_persistent_data.panic_data)) +#define CONFIG_PANIC_DATA_BASE (&(ish_persistent_data.panic_data)) /* System stack size */ -#define CONFIG_STACK_SIZE 1024 +#define CONFIG_STACK_SIZE 1024 /* non-standard task stack sizes */ -#define IDLE_TASK_STACK_SIZE 640 -#define LARGER_TASK_STACK_SIZE 1024 -#define HUGE_TASK_STACK_SIZE 2048 +#define IDLE_TASK_STACK_SIZE 640 +#define LARGER_TASK_STACK_SIZE 1024 +#define HUGE_TASK_STACK_SIZE 2048 /* Default task stack size */ -#define TASK_STACK_SIZE 640 +#define TASK_STACK_SIZE 640 /****************************************************************************/ /* Define our flash layout. */ @@ -87,13 +86,13 @@ */ /* Protect bank size 4K bytes */ -#define CONFIG_FLASH_BANK_SIZE 0x00001000 +#define CONFIG_FLASH_BANK_SIZE 0x00001000 /* Sector erase size 4K bytes */ -#define CONFIG_FLASH_ERASE_SIZE 0x00000000 +#define CONFIG_FLASH_ERASE_SIZE 0x00000000 /* Minimum write size */ -#define CONFIG_FLASH_WRITE_SIZE 0x00000000 +#define CONFIG_FLASH_WRITE_SIZE 0x00000000 /* Program memory base address */ -#define CONFIG_PROGRAM_MEMORY_BASE 0x00100000 +#define CONFIG_PROGRAM_MEMORY_BASE 0x00100000 #include "config_flash_layout.h" @@ -101,16 +100,16 @@ /* Watchdog Timer Configuration */ /*****************************************************************************/ #if defined(CHIP_FAMILY_ISH3) || defined(CHIP_FAMILY_ISH5) -#define WDT_CLOCK_HZ (120000000) /* 120 MHz */ +#define WDT_CLOCK_HZ (120000000) /* 120 MHz */ #elif defined(CHIP_FAMILY_ISH4) -#define WDT_CLOCK_HZ (100000000) /* 100 MHz */ +#define WDT_CLOCK_HZ (100000000) /* 100 MHz */ #else #error "CHIP_FAMILY_ISH(3|4|5) must be defined" #endif /* Provide WDT vec number to Minute-IA core implementation */ #undef CONFIG_MIA_WDT_VEC -#define CONFIG_MIA_WDT_VEC ISH_WDT_VEC +#define CONFIG_MIA_WDT_VEC ISH_WDT_VEC /****************************************************************************/ /* Customize the build */ @@ -133,4 +132,4 @@ #define CONFIG_ISH_CLEAR_FABRIC_ERRORS #endif -#endif /* __CROS_EC_CONFIG_CHIP_H */ +#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/ish/config_flash_layout.h b/chip/ish/config_flash_layout.h index 0430baf3eb..4e4b7ad90b 100644 --- a/chip/ish/config_flash_layout.h +++ b/chip/ish/config_flash_layout.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,14 +8,14 @@ /* Mem-mapped, No external SPI for ISH */ #undef CONFIG_EXTERNAL_STORAGE -#define CONFIG_MAPPED_STORAGE -#undef CONFIG_FLASH_PSTATE +#define CONFIG_MAPPED_STORAGE +#undef CONFIG_FLASH_PSTATE #undef CONFIG_SPI_FLASH #ifdef CHIP_VARIANT_ISH5P4 -#define CONFIG_ISH_BOOT_START 0xFF200000 +#define CONFIG_ISH_BOOT_START 0xFF200000 #else -#define CONFIG_ISH_BOOT_START 0xFF000000 +#define CONFIG_ISH_BOOT_START 0xFF000000 #endif /*****************************************************************************/ @@ -24,40 +24,37 @@ * turn off SPI and flash, making these unnecessary. */ -#define CONFIG_MAPPED_STORAGE_BASE 0x0 +#define CONFIG_MAPPED_STORAGE_BASE 0x0 -#define CONFIG_EC_PROTECTED_STORAGE_OFF (CONFIG_FLASH_SIZE - 0x20000) +#define CONFIG_EC_PROTECTED_STORAGE_OFF (CONFIG_FLASH_SIZE_BYTES - 0x20000) #define CONFIG_EC_PROTECTED_STORAGE_SIZE 0x20000 -#define CONFIG_EC_WRITABLE_STORAGE_OFF (CONFIG_FLASH_SIZE - 0x40000) -#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x20000 +#define CONFIG_EC_WRITABLE_STORAGE_OFF (CONFIG_FLASH_SIZE_BYTES - 0x40000) +#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x20000 /* Unused for ISH - loader is external to ISH FW */ -#define CONFIG_LOADER_MEM_OFF 0 -#define CONFIG_LOADER_SIZE 0xC00 - +#define CONFIG_LOADER_MEM_OFF 0 +#define CONFIG_LOADER_SIZE 0xC00 /* RO/RW images - not relevant for ISH */ -#define CONFIG_RO_MEM_OFF (CONFIG_LOADER_MEM_OFF + \ - CONFIG_LOADER_SIZE) -#define CONFIG_RO_SIZE (97 * 1024) -#define CONFIG_RW_MEM_OFF CONFIG_RO_MEM_OFF -#define CONFIG_RW_SIZE CONFIG_RO_SIZE +#define CONFIG_RO_MEM_OFF (CONFIG_LOADER_MEM_OFF + CONFIG_LOADER_SIZE) +#define CONFIG_RO_SIZE (97 * 1024) +#define CONFIG_RW_MEM_OFF CONFIG_RO_MEM_OFF +#define CONFIG_RW_SIZE CONFIG_RO_SIZE /*****************************************************************************/ /* Not relevant for ISH */ -#define CONFIG_BOOT_HEADER_STORAGE_OFF 0 -#define CONFIG_BOOT_HEADER_STORAGE_SIZE 0x240 +#define CONFIG_BOOT_HEADER_STORAGE_OFF 0 +#define CONFIG_BOOT_HEADER_STORAGE_SIZE 0x240 -#define CONFIG_LOADER_STORAGE_OFF (CONFIG_BOOT_HEADER_STORAGE_OFF + \ - CONFIG_BOOT_HEADER_STORAGE_SIZE) +#define CONFIG_LOADER_STORAGE_OFF \ + (CONFIG_BOOT_HEADER_STORAGE_OFF + CONFIG_BOOT_HEADER_STORAGE_SIZE) /* RO image immediately follows the loader image */ -#define CONFIG_RO_STORAGE_OFF (CONFIG_LOADER_STORAGE_OFF + \ - CONFIG_LOADER_SIZE) +#define CONFIG_RO_STORAGE_OFF (CONFIG_LOADER_STORAGE_OFF + CONFIG_LOADER_SIZE) /* RW image starts at the beginning of SPI */ -#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_STORAGE_OFF 0 #endif /* __CROS_EC_CONFIG_FLASH_LAYOUT_H */ diff --git a/chip/ish/dma.c b/chip/ish/dma.c index b9744fd234..eae6a850f1 100644 --- a/chip/ish/dma.c +++ b/chip/ish/dma.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,34 +7,12 @@ #include "common.h" #include "console.h" -#include "registers.h" #include "ish_dma.h" +#include "registers.h" #include "util.h" static int dma_init_called; /* If ish_dma_init is called */ -static int dma_poll(uint32_t addr, uint32_t expected, uint32_t mask) -{ - int retval = -1; - uint32_t counter = 0; - - /* - * The timeout is approximately 2.2 seconds according to - * value of UINT32_MAX, 120MHZ ISH clock frequency and - * instruction count which is around 4. - */ - while (counter < (UINT32_MAX / 64)) { - /* test condition */ - if ((REG32(addr) & mask) == expected) { - retval = DMA_RC_OK; - break; - } - counter++; - } - - return retval; -} - void ish_dma_ocp_timeout_disable(void) { if (!IS_ENABLED(CONFIG_ISH_NEW_PM)) { @@ -44,24 +22,6 @@ void ish_dma_ocp_timeout_disable(void) } } -static inline uint32_t interrupt_lock(void) -{ - uint32_t eflags = 0; - __asm__ volatile("pushfl;" /* save eflag value */ - "popl %0;" - "cli;" - : "=r"(eflags)); /* shut off interrupts */ - return eflags; -} - -static inline void interrupt_unlock(uint32_t eflags) -{ - __asm__ volatile("pushl %0;" /* restore elfag values */ - "popfl;" - : - : "r"(eflags)); -} - void dma_configure_psize(void) { /* Give chan0 512 bytes for high performance, and chan1 128 bytes. */ @@ -112,8 +72,8 @@ int ish_dma_copy(uint32_t chan, uint32_t dst, uint32_t src, uint32_t length, mode |= NON_SNOOP; MISC_DMA_CTL_REG(chan) = mode; /* Set transfer direction */ - DMA_CFG_REG = DMA_ENABLE; /* Enable DMA module */ - DMA_LLP(chan_reg) = 0; /* Linked lists are not used */ + DMA_CFG_REG = DMA_ENABLE; /* Enable DMA module */ + DMA_LLP(chan_reg) = 0; /* Linked lists are not used */ DMA_CTL_LOW(chan_reg) = 0 /* Set transfer parameters */ | (DMA_CTL_TT_FC_M2M_DMAC << DMA_CTL_TT_FC_SHIFT) | @@ -126,24 +86,27 @@ int ish_dma_copy(uint32_t chan, uint32_t dst, uint32_t src, uint32_t length, interrupt_unlock(eflags); while (length) { - chunk = (length > DMA_MAX_BLOCK_SIZE) ? DMA_MAX_BLOCK_SIZE - : length; + chunk = (length > DMA_MAX_BLOCK_SIZE) ? DMA_MAX_BLOCK_SIZE : + length; if (rc != DMA_RC_OK) break; eflags = interrupt_lock(); MISC_CHID_CFG_REG = chan; /* Set channel to configure */ - DMA_CTL_HIGH(chan_reg) = - chunk; /* Set number of bytes to transfer */ + DMA_CTL_HIGH(chan_reg) = chunk; /* Set number of bytes to + transfer */ DMA_DAR(chan_reg) = dst; /* Destination address */ DMA_SAR(chan_reg) = src; /* Source address */ DMA_EN_REG = DMA_CH_EN_BIT(chan) | - DMA_CH_EN_WE_BIT(chan); /* Enable the channel */ + DMA_CH_EN_WE_BIT(chan); /* Enable + the + channel + */ interrupt_unlock(eflags); - rc = ish_wait_for_dma_done( - chan); /* Wait for trans completion */ + rc = ish_wait_for_dma_done(chan); /* Wait for trans completion + */ dst += chunk; src += chunk; diff --git a/chip/ish/flash.c b/chip/ish/flash.c index 8ef4d1a73c..c9c4a132d9 100644 --- a/chip/ish/flash.c +++ b/chip/ish/flash.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,13 +6,12 @@ #include "common.h" #include "flash.h" - /** * Initialize the module. * * Applies at-boot protection settings if necessary. */ -int flash_pre_init(void) +int crec_flash_pre_init(void) { return EC_SUCCESS; } diff --git a/chip/ish/gpio.c b/chip/ish/gpio.c index 6c7a27e1e7..287e7a375b 100644 --- a/chip/ish/gpio.c +++ b/chip/ish/gpio.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -24,7 +24,7 @@ test_mockable int gpio_get_level(enum gpio_signal signal) if (g->port == UNIMPLEMENTED_GPIO_BANK) return 0; - return !!(ISH_GPIO_GPLR & g->mask); + return !!(ISH_GPIO_GPLR & g->mask); } void gpio_set_level(enum gpio_signal signal, int value) @@ -55,8 +55,8 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) } /* ISH 3 can't support both rising and falling edge */ - if (IS_ENABLED(CHIP_FAMILY_ISH3) && - (flags & GPIO_INT_F_RISING) && (flags & GPIO_INT_F_FALLING)) { + if (IS_ENABLED(CHIP_FAMILY_ISH3) && (flags & GPIO_INT_F_RISING) && + (flags & GPIO_INT_F_FALLING)) { ccprintf("\n\nISH 2/3 does not support both rising & falling " "edge for %d 0x%02x\n\n", port, mask); @@ -65,7 +65,7 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) /* GPSR/GPCR Output high/low */ if (flags & GPIO_HIGH) /* Output high */ ISH_GPIO_GPSR |= mask; - else if (flags & GPIO_LOW) /* output low */ + else if (flags & GPIO_LOW) /* output low */ ISH_GPIO_GPCR |= mask; /* GPDR pin direction 1 = output, 0 = input*/ @@ -123,7 +123,6 @@ void gpio_pre_init(void) const struct gpio_info *g = gpio_list; for (i = 0; i < GPIO_COUNT; i++, g++) { - flags = g->flags; if (flags & GPIO_DEFAULT) diff --git a/chip/ish/hbm.h b/chip/ish/hbm.h index edfb587d21..17c7853b1d 100644 --- a/chip/ish/hbm.h +++ b/chip/ish/hbm.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,70 +6,69 @@ #ifndef __HBM_H #define __HBM_H -#include -#include - #include "heci_client.h" -#define HBM_MAJOR_VERSION 1 +#include +#include + +#define HBM_MAJOR_VERSION 1 #ifdef HECI_ENABLE_DMA -#define HBM_MINOR_VERSION 2 +#define HBM_MINOR_VERSION 2 #else -#define HBM_MINOR_VERSION 0 +#define HBM_MINOR_VERSION 0 #endif #define __packed __attribute__((packed)) -#define HECI_MSG_REPONSE_FLAG 0x80 +#define HECI_MSG_REPONSE_FLAG 0x80 enum HECI_BUS_MSG { /* requests */ - HECI_BUS_MSG_VERSION_REQ = 1, - HECI_BUS_MSG_HOST_STOP_REQ = 2, - HECI_BUS_MSG_ME_STOP_REQ = 3, - HECI_BUS_MSG_HOST_ENUM_REQ = 4, - HECI_BUS_MSG_HOST_CLIENT_PROP_REQ = 5, - HECI_BUS_MSG_CLIENT_CONNECT_REQ = 6, - HECI_BUS_MSG_CLIENT_DISCONNECT_REQ = 7, - HECI_BUS_MSG_FLOW_CONTROL = 8, - HECI_BUS_MSG_RESET_REQ = 9, - HECI_BUS_MSG_ADD_CLIENT_REQ = 0x0A, - HECI_BUS_MSG_DMA_REQ = 0x10, - HECI_BUS_MSG_DMA_ALLOC_NOTIFY = 0x11, - HECI_BUS_MSG_DMA_XFER_REQ = 0x12, + HECI_BUS_MSG_VERSION_REQ = 1, + HECI_BUS_MSG_HOST_STOP_REQ = 2, + HECI_BUS_MSG_ME_STOP_REQ = 3, + HECI_BUS_MSG_HOST_ENUM_REQ = 4, + HECI_BUS_MSG_HOST_CLIENT_PROP_REQ = 5, + HECI_BUS_MSG_CLIENT_CONNECT_REQ = 6, + HECI_BUS_MSG_CLIENT_DISCONNECT_REQ = 7, + HECI_BUS_MSG_FLOW_CONTROL = 8, + HECI_BUS_MSG_RESET_REQ = 9, + HECI_BUS_MSG_ADD_CLIENT_REQ = 0x0A, + HECI_BUS_MSG_DMA_REQ = 0x10, + HECI_BUS_MSG_DMA_ALLOC_NOTIFY = 0x11, + HECI_BUS_MSG_DMA_XFER_REQ = 0x12, /* responses */ - HECI_BUS_MSG_VERSION_RESP = + HECI_BUS_MSG_VERSION_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_VERSION_REQ), - HECI_BUS_MSG_HOST_STOP_RESP = + HECI_BUS_MSG_HOST_STOP_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_HOST_STOP_REQ), - HECI_BUS_MSG_HOST_ENUM_RESP = + HECI_BUS_MSG_HOST_ENUM_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_HOST_ENUM_REQ), - HECI_BUS_MSG_HOST_CLIENT_PROP_RESP = + HECI_BUS_MSG_HOST_CLIENT_PROP_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_HOST_CLIENT_PROP_REQ), - HECI_BUS_MSG_CLIENT_CONNECT_RESP = + HECI_BUS_MSG_CLIENT_CONNECT_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_CLIENT_CONNECT_REQ), - HECI_BUS_MSG_CLIENT_DISCONNECT_RESP = + HECI_BUS_MSG_CLIENT_DISCONNECT_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_CLIENT_DISCONNECT_REQ), - HECI_BUS_MSG_RESET_RESP = + HECI_BUS_MSG_RESET_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_RESET_REQ), - HECI_BUS_MSG_ADD_CLIENT_RESP = + HECI_BUS_MSG_ADD_CLIENT_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_ADD_CLIENT_REQ), - HECI_BUS_MSG_DMA_RESP = - (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_DMA_REQ), - HECI_BUS_MSG_DMA_ALLOC_RESP = + HECI_BUS_MSG_DMA_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_DMA_REQ), + HECI_BUS_MSG_DMA_ALLOC_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_DMA_ALLOC_NOTIFY), - HECI_BUS_MSG_DMA_XFER_RESP = + HECI_BUS_MSG_DMA_XFER_RESP = (HECI_MSG_REPONSE_FLAG | HECI_BUS_MSG_DMA_XFER_REQ) }; enum { - HECI_CONNECT_STATUS_SUCCESS = 0, - HECI_CONNECT_STATUS_CLIENT_NOT_FOUND = 1, - HECI_CONNECT_STATUS_ALREADY_EXISTS = 2, - HECI_CONNECT_STATUS_REJECTED = 3, + HECI_CONNECT_STATUS_SUCCESS = 0, + HECI_CONNECT_STATUS_CLIENT_NOT_FOUND = 1, + HECI_CONNECT_STATUS_ALREADY_EXISTS = 2, + HECI_CONNECT_STATUS_REJECTED = 3, HECI_CONNECT_STATUS_INVALID_PARAMETER = 4, - HECI_CONNECT_STATUS_INACTIVE_CLIENT = 5, + HECI_CONNECT_STATUS_INACTIVE_CLIENT = 5, }; struct hbm_version { @@ -101,14 +100,14 @@ struct hbm_client_prop_req { uint8_t reserved[2]; } __packed; -#define CLIENT_DMA_ENABLE 0x80 +#define CLIENT_DMA_ENABLE 0x80 struct hbm_client_properties { struct heci_guid protocol_name; /* heci client protocol ID */ - uint8_t protocol_version; /* protocol version */ + uint8_t protocol_version; /* protocol version */ /* max connection from host to client. currently only 1 is allowed */ uint8_t max_number_of_connections; - uint8_t fixed_address; /* not yet supported */ + uint8_t fixed_address; /* not yet supported */ uint8_t single_recv_buf; /* not yet supported */ uint32_t max_msg_length; /* max payload size */ /* not yet supported. [7] enable/disable, [6:0] dma length */ @@ -168,13 +167,13 @@ struct hbm_host_stop_res { struct hbm_h2i { uint8_t cmd; union { - struct hbm_version_req ver_req; - struct hbm_enum_req enum_req; - struct hbm_client_prop_req client_prop_req; - struct hbm_client_connect_req client_connect_req; - struct hbm_flow_control flow_ctrl; - struct hbm_client_disconnect_req client_disconnect_req; - struct hbm_host_stop_req host_stop_req; + struct hbm_version_req ver_req; + struct hbm_enum_req enum_req; + struct hbm_client_prop_req client_prop_req; + struct hbm_client_connect_req client_connect_req; + struct hbm_flow_control flow_ctrl; + struct hbm_client_disconnect_req client_disconnect_req; + struct hbm_host_stop_req host_stop_req; } data; } __packed; @@ -182,13 +181,13 @@ struct hbm_h2i { struct hbm_i2h { uint8_t cmd; union { - struct hbm_version_res ver_res; - struct hbm_enum_res enum_res; - struct hbm_client_prop_res client_prop_res; - struct hbm_client_connect_res client_connect_res; - struct hbm_flow_control flow_ctrl; - struct hbm_client_disconnect_res client_disconnect_res; - struct hbm_host_stop_res host_stop_res; + struct hbm_version_res ver_res; + struct hbm_enum_res enum_res; + struct hbm_client_prop_res client_prop_res; + struct hbm_client_connect_res client_connect_res; + struct hbm_flow_control flow_ctrl; + struct hbm_client_disconnect_res client_disconnect_res; + struct hbm_host_stop_res host_stop_res; } data; } __packed; diff --git a/chip/ish/heci.c b/chip/ish/heci.c index 309a17c0a1..6f99a486e7 100644 --- a/chip/ish/heci.c +++ b/chip/ish/heci.c @@ -1,9 +1,10 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" +#include "builtin/assert.h" #include "compile_time_macros.h" #include "console.h" #include "hbm.h" @@ -15,19 +16,19 @@ #include "util.h" #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_LPC, format, ##args) struct heci_header { uint8_t fw_addr; uint8_t host_addr; uint16_t length; /* [8:0] length, [14:9] reserved, [15] msg_complete */ } __packed; -#define HECI_MSG_CMPL_SHIFT 15 -#define HECI_MSG_LENGTH_MASK 0x01FF -#define HECI_MSG_LENGTH(length) ((length) & HECI_MSG_LENGTH_MASK) +#define HECI_MSG_CMPL_SHIFT 15 +#define HECI_MSG_LENGTH_MASK 0x01FF +#define HECI_MSG_LENGTH(length) ((length)&HECI_MSG_LENGTH_MASK) #define HECI_MSG_IS_COMPLETED(length) \ - (!!((length) & (0x01 << HECI_MSG_CMPL_SHIFT))) + (!!((length) & (0x01 << HECI_MSG_CMPL_SHIFT))) BUILD_ASSERT(HECI_IPC_PAYLOAD_SIZE == (IPC_MAX_PAYLOAD_SIZE - sizeof(struct heci_header))); @@ -38,26 +39,26 @@ struct heci_msg { } __packed; /* HECI addresses */ -#define HECI_HBM_ADDRESS 0 /* HECI Bus Message */ -#define HECI_DYN_CLIENT_ADDR_START 0x20 /* Dynamic client start addr */ +#define HECI_HBM_ADDRESS 0 /* HECI Bus Message */ +#define HECI_DYN_CLIENT_ADDR_START 0x20 /* Dynamic client start addr */ /* A fw client has the same value for both handle and fw address */ -#define TO_FW_ADDR(handle) ((uintptr_t)(handle)) -#define TO_HECI_HANDLE(fw_addr) ((heci_handle_t)(uintptr_t)(fw_addr)) +#define TO_FW_ADDR(handle) ((uintptr_t)(handle)) +#define TO_HECI_HANDLE(fw_addr) ((heci_handle_t)(uintptr_t)(fw_addr)) /* convert client fw address to client context index */ -#define TO_CLIENT_CTX_IDX(fw_addr) ((fw_addr) - HECI_DYN_CLIENT_ADDR_START) +#define TO_CLIENT_CTX_IDX(fw_addr) ((fw_addr)-HECI_DYN_CLIENT_ADDR_START) /* should be less than HECI_INVALID_HANDLE - 1 */ BUILD_ASSERT(HECI_MAX_NUM_OF_CLIENTS < 0x0FE); struct heci_client_connect { - uint8_t is_connected; /* client is connected to host */ - uint8_t host_addr; /* connected host address */ + uint8_t is_connected; /* client is connected to host */ + uint8_t host_addr; /* connected host address */ /* receiving message */ uint8_t ignore_rx_msg; - uint8_t rx_msg[HECI_MAX_MSG_SIZE]; - size_t rx_msg_length; + uint8_t rx_msg[HECI_MAX_MSG_SIZE]; + size_t rx_msg_length; uint32_t flow_ctrl_creds; /* flow control */ struct mutex lock; /* protects against 2 writers */ @@ -67,7 +68,7 @@ struct heci_client_connect { struct heci_client_context { const struct heci_client *client; - void *data; /* client specific data */ + void *data; /* client specific data */ struct heci_client_connect connect; /* connection context */ struct ss_subsys_device ss_device; /* system state receiver device */ @@ -82,7 +83,7 @@ struct heci_bus_context { /* declare heci bus */ struct heci_bus_context heci_bus_ctx = { - .ipc_handle = IPC_INVALID_HANDLE, + .ipc_handle = IPC_INVALID_HANDLE, }; static inline struct heci_client_context * @@ -118,11 +119,14 @@ static inline int heci_is_valid_handle(const heci_handle_t handle) /* find heci device that contains this system state device in it */ #define ss_device_to_heci_client_context(ss_dev) \ - ((struct heci_client_context *)((void *)(ss_dev) - \ - (void *)(&(((struct heci_client_context *)0)->ss_device)))) -#define client_context_to_handle(cli_ctx) \ - ((heci_handle_t)((uint32_t)((cli_ctx) - &heci_bus_ctx.client_ctxs[0]) \ - / sizeof(heci_bus_ctx.client_ctxs[0]) + 1)) + ((struct heci_client_context \ + *)((void *)(ss_dev) - \ + (void *)(&( \ + ((struct heci_client_context *)0)->ss_device)))) +#define client_context_to_handle(cli_ctx) \ + ((heci_handle_t)((uint32_t)((cli_ctx) - &heci_bus_ctx.client_ctxs[0]) / \ + sizeof(heci_bus_ctx.client_ctxs[0]) + \ + 1)) /* * each heci device registered as system state device which gets @@ -132,7 +136,7 @@ static inline int heci_is_valid_handle(const heci_handle_t handle) static int heci_client_suspend(struct ss_subsys_device *ss_device) { struct heci_client_context *cli_ctx = - ss_device_to_heci_client_context(ss_device); + ss_device_to_heci_client_context(ss_device); heci_handle_t handle = client_context_to_handle(cli_ctx); if (cli_ctx->client->cbs->suspend) @@ -144,7 +148,7 @@ static int heci_client_suspend(struct ss_subsys_device *ss_device) static int heci_client_resume(struct ss_subsys_device *ss_device) { struct heci_client_context *cli_ctx = - ss_device_to_heci_client_context(ss_device); + ss_device_to_heci_client_context(ss_device); heci_handle_t handle = client_context_to_handle(cli_ctx); if (cli_ctx->client->cbs->resume) @@ -239,8 +243,8 @@ static int heci_send_heci_msg_timestamp(struct heci_msg *msg, timestamp); if (written != length) { - CPRINTF("%s error : len = %d err = %d\n", __func__, - (int)length, written); + CPRINTF("%s error : len = %d err = %d\n", __func__, (int)length, + written); return -EC_ERROR_UNKNOWN; } @@ -381,7 +385,6 @@ int heci_send_msg(const heci_handle_t handle, uint8_t *buf, return heci_send_msg_timestamp(handle, buf, buf_size, NULL); } - int heci_send_msgs(const heci_handle_t handle, const struct heci_msg_list *msg_list) { @@ -453,8 +456,8 @@ int heci_send_msgs(const heci_handle_t handle, /* no leftovers, send the last msg here */ if (msg_sent == total_size) { - msg.hdr.length |= - (uint16_t)1 << HECI_MSG_CMPL_SHIFT; + msg.hdr.length |= (uint16_t)1 + << HECI_MSG_CMPL_SHIFT; } heci_send_heci_msg(&msg); @@ -488,7 +491,6 @@ int heci_send_msgs(const heci_handle_t handle, mutex_unlock(&connect->lock); return total_size; - } /* For now, we only support fixed client payload size < IPC payload size */ @@ -535,9 +537,9 @@ static int handle_version_req(struct hbm_version_req *ver_req) return EC_SUCCESS; } -#define BITS_PER_BYTE 8 +#define BITS_PER_BYTE 8 /* get number of bits for one element of "valid_addresses" array */ -#define BITS_PER_ELEMENT \ +#define BITS_PER_ELEMENT \ (sizeof(((struct hbm_enum_res *)0)->valid_addresses[0]) * BITS_PER_BYTE) static int handle_enum_req(struct hbm_enum_req *enum_req) @@ -604,11 +606,11 @@ static int handle_client_prop_req(struct hbm_client_prop_req *client_prop_req) client_prop->protocol_name = client->protocol_id; client_prop->protocol_version = client->protocol_ver; client_prop->max_number_of_connections = - client->max_n_of_connections; + client->max_n_of_connections; client_prop->max_msg_length = client->max_msg_size; client_prop->dma_hdr_len = client->dma_header_length; - client_prop->dma_hdr_len |= client->dma_enabled ? - CLIENT_DMA_ENABLE : 0; + client_prop->dma_hdr_len |= + client->dma_enabled ? CLIENT_DMA_ENABLE : 0; } heci_send_heci_msg(&heci_msg); @@ -642,8 +644,8 @@ static int heci_send_flow_control(uint8_t fw_addr) return EC_SUCCESS; } -static int handle_client_connect_req( - struct hbm_client_connect_req *client_connect_req) +static int +handle_client_connect_req(struct hbm_client_connect_req *client_connect_req) { struct hbm_client_connect_res *client_connect_res; struct heci_msg heci_msg; @@ -663,7 +665,7 @@ static int handle_client_connect_req( client_connect_res->host_addr = client_connect_req->host_addr; if (!heci_is_valid_client_addr(client_connect_req->fw_addr)) { client_connect_res->status = - HECI_CONNECT_STATUS_CLIENT_NOT_FOUND; + HECI_CONNECT_STATUS_CLIENT_NOT_FOUND; } else if (!client_connect_req->host_addr) { client_connect_res->status = HECI_CONNECT_STATUS_INVALID_PARAMETER; @@ -671,7 +673,7 @@ static int handle_client_connect_req( connect = heci_get_client_connect(client_connect_req->fw_addr); if (connect->is_connected) { client_connect_res->status = - HECI_CONNECT_STATUS_ALREADY_EXISTS; + HECI_CONNECT_STATUS_ALREADY_EXISTS; } else { connect->is_connected = 1; connect->host_addr = client_connect_req->host_addr; @@ -706,7 +708,7 @@ static int handle_flow_control_cmd(struct hbm_flow_control *flow_ctrl) mutex_unlock(&connect->cred_lock); if (waiting_task) - task_set_event(waiting_task, TASK_EVENT_IPC_READY, 0); + task_set_event(waiting_task, TASK_EVENT_IPC_READY); return EC_SUCCESS; } @@ -729,8 +731,7 @@ static void heci_handle_client_msg(struct heci_msg *msg, size_t length) connect = &cli_ctx->connect; payload_size = HECI_MSG_LENGTH(msg->hdr.length); - if (connect->is_connected && - msg->hdr.host_addr == connect->host_addr) { + if (connect->is_connected && msg->hdr.host_addr == connect->host_addr) { if (!connect->ignore_rx_msg && connect->rx_msg_length + payload_size > HECI_MAX_MSG_SIZE) { connect->ignore_rx_msg = 1; /* too big. discard */ @@ -760,7 +761,7 @@ static void heci_handle_client_msg(struct heci_msg *msg, size_t length) } static int handle_client_disconnect_req( - struct hbm_client_disconnect_req *client_disconnect_req) + struct hbm_client_disconnect_req *client_disconnect_req) { struct hbm_client_disconnect_res *client_disconnect_res; struct heci_msg heci_msg; @@ -772,8 +773,9 @@ static int handle_client_disconnect_req( CPRINTS("Got HECI disconnect request"); - heci_build_hbm_header(&heci_msg.hdr, sizeof(i2h->cmd) + - sizeof(*client_disconnect_res)); + heci_build_hbm_header(&heci_msg.hdr, + sizeof(i2h->cmd) + + sizeof(*client_disconnect_res)); i2h = (struct hbm_i2h *)heci_msg.payload; i2h->cmd = HECI_BUS_MSG_CLIENT_DISCONNECT_RESP; @@ -789,7 +791,7 @@ static int handle_client_disconnect_req( if (!heci_is_valid_client_addr(fw_addr) || !heci_is_client_connected(fw_addr)) { client_disconnect_res->status = - HECI_CONNECT_STATUS_CLIENT_NOT_FOUND; + HECI_CONNECT_STATUS_CLIENT_NOT_FOUND; } else { connect = heci_get_client_connect(fw_addr); if (connect->host_addr != host_addr) { @@ -891,8 +893,8 @@ static int is_hbm_validity(struct hbm_h2i *h2i, size_t length) } if (valid_msg_len != length) { - CPRINTF("invalid cmd(%d) valid : %d, cur : %zd\n", - h2i->cmd, valid_msg_len, length); + CPRINTF("invalid cmd(%d) valid : %d, cur : %zd\n", h2i->cmd, + valid_msg_len, length); /* TODO: invalid cmd. not sure to reply with error ? */ return 0; } @@ -922,7 +924,7 @@ static void heci_handle_hbm(struct hbm_h2i *h2i, size_t length) case HECI_BUS_MSG_CLIENT_CONNECT_REQ: handle_client_connect_req( - (struct hbm_client_connect_req *)data); + (struct hbm_client_connect_req *)data); break; case HECI_BUS_MSG_FLOW_CONTROL: @@ -931,7 +933,7 @@ static void heci_handle_hbm(struct hbm_h2i *h2i, size_t length) case HECI_BUS_MSG_CLIENT_DISCONNECT_REQ: handle_client_disconnect_req( - (struct hbm_client_disconnect_req *)data); + (struct hbm_client_disconnect_req *)data); break; case HECI_BUS_MSG_HOST_STOP_REQ: @@ -991,7 +993,7 @@ static void heci_handle_heci_msg(struct heci_msg *heci_msg, size_t msg_length) } /* event flag for HECI msg */ -#define EVENT_FLAG_BIT_HECI_MSG TASK_EVENT_CUSTOM_BIT(0) +#define EVENT_FLAG_BIT_HECI_MSG TASK_EVENT_CUSTOM_BIT(0) void heci_rx_task(void) { @@ -1017,8 +1019,9 @@ void heci_rx_task(void) continue; } - if (HECI_MSG_LENGTH(heci_msg.hdr.length) + sizeof(heci_msg.hdr) - == msg_len) + if (HECI_MSG_LENGTH(heci_msg.hdr.length) + + sizeof(heci_msg.hdr) == + msg_len) heci_handle_heci_msg(&heci_msg, msg_len); else CPRINTS("msg len mismatch.. discard.."); diff --git a/chip/ish/heci_client.h b/chip/ish/heci_client.h index 9dca4bff90..2ba9ea01db 100644 --- a/chip/ish/heci_client.h +++ b/chip/ish/heci_client.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,26 +6,26 @@ #ifndef __HECI_CLIENT_H #define __HECI_CLIENT_H -#include -#include - #include "hooks.h" -#define HECI_MAX_NUM_OF_CLIENTS 2 +#include +#include + +#define HECI_MAX_NUM_OF_CLIENTS 2 -#define HECI_MAX_MSG_SIZE 4960 -#define HECI_IPC_PAYLOAD_SIZE (IPC_MAX_PAYLOAD_SIZE - 4) -#define HECI_MAX_MSGS 3 +#define HECI_MAX_MSG_SIZE 4960 +#define HECI_IPC_PAYLOAD_SIZE (IPC_MAX_PAYLOAD_SIZE - 4) +#define HECI_MAX_MSGS 3 enum HECI_ERR { - HECI_ERR_TOO_MANY_MSG_ITEMS = EC_ERROR_INTERNAL_FIRST + 0, - HECI_ERR_NO_CRED_FROM_CLIENT_IN_HOST = EC_ERROR_INTERNAL_FIRST + 1, - HECI_ERR_CLIENT_IS_NOT_CONNECTED = EC_ERROR_INTERNAL_FIRST + 2, + HECI_ERR_TOO_MANY_MSG_ITEMS = EC_ERROR_INTERNAL_FIRST + 0, + HECI_ERR_NO_CRED_FROM_CLIENT_IN_HOST = EC_ERROR_INTERNAL_FIRST + 1, + HECI_ERR_CLIENT_IS_NOT_CONNECTED = EC_ERROR_INTERNAL_FIRST + 2, }; -typedef void * heci_handle_t; +typedef void *heci_handle_t; -#define HECI_INVALID_HANDLE NULL +#define HECI_INVALID_HANDLE NULL struct heci_guid { uint32_t data1; @@ -57,8 +57,8 @@ struct heci_client { uint32_t max_msg_size; uint8_t protocol_ver; uint8_t max_n_of_connections; - uint8_t dma_header_length :7; - uint8_t dma_enabled :1; + uint8_t dma_header_length : 7; + uint8_t dma_enabled : 1; const struct heci_client_callbacks *cbs; }; @@ -91,7 +91,7 @@ void *heci_get_client_data(const heci_handle_t handle); int heci_send_msg(const heci_handle_t handle, uint8_t *buf, const size_t buf_size); int heci_send_msg_timestamp(const heci_handle_t handle, uint8_t *buf, - const size_t buf_size, uint32_t *timestamp); + const size_t buf_size, uint32_t *timestamp); /* * send client msgs(using list of buffer&size). * heci_msg_item with size == 0 is not acceptable. @@ -102,11 +102,11 @@ int heci_send_msgs(const heci_handle_t handle, int heci_send_fixed_client_msg(const uint8_t fw_addr, uint8_t *buf, const size_t buf_size); -#define HECI_CLIENT_ENTRY(heci_client) \ - void _heci_entry_##heci_client(void) \ - { \ +#define HECI_CLIENT_ENTRY(heci_client) \ + void _heci_entry_##heci_client(void) \ + { \ heci_register_client(&(heci_client)); \ - } \ + } \ DECLARE_HOOK(HOOK_INIT, _heci_entry_##heci_client, HOOK_PRIO_LAST - 1) #endif /* __HECI_CLIENT_H */ diff --git a/chip/ish/hid_device.h b/chip/ish/hid_device.h index 0a32e305af..07d8a77673 100644 --- a/chip/ish/hid_device.h +++ b/chip/ish/hid_device.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,20 +6,20 @@ #ifndef __HID_DEVICE_H #define __HID_DEVICE_H -#include -#include - #include "hooks.h" -#define HID_SUBSYS_MAX_PAYLOAD_SIZE 4954 +#include +#include + +#define HID_SUBSYS_MAX_PAYLOAD_SIZE 4954 enum HID_SUBSYS_ERR { - HID_SUBSYS_ERR_NOT_READY = EC_ERROR_INTERNAL_FIRST + 0, - HID_SUBSYS_ERR_TOO_MANY_HID_DEVICES = EC_ERROR_INTERNAL_FIRST + 1, + HID_SUBSYS_ERR_NOT_READY = EC_ERROR_INTERNAL_FIRST + 0, + HID_SUBSYS_ERR_TOO_MANY_HID_DEVICES = EC_ERROR_INTERNAL_FIRST + 1, }; -typedef void * hid_handle_t; -#define HID_INVALID_HANDLE NULL +typedef void *hid_handle_t; +#define HID_INVALID_HANDLE NULL struct hid_callbacks { /* @@ -73,11 +73,11 @@ int hid_subsys_set_device_data(const hid_handle_t handle, void *data); /* retrieve HID device specific data */ void *hid_subsys_get_device_data(const hid_handle_t handle); -#define HID_DEVICE_ENTRY(hid_dev) \ - void _hid_dev_entry_##hid_dev(void) \ - { \ +#define HID_DEVICE_ENTRY(hid_dev) \ + void _hid_dev_entry_##hid_dev(void) \ + { \ hid_subsys_register_device(&(hid_dev)); \ - } \ + } \ DECLARE_HOOK(HOOK_INIT, _hid_dev_entry_##hid_dev, HOOK_PRIO_LAST - 2) #endif /* __HID_DEVICE_H */ diff --git a/chip/ish/hid_subsys.c b/chip/ish/hid_subsys.c index bd3f331fdc..555af9046a 100644 --- a/chip/ish/hid_subsys.c +++ b/chip/ish/hid_subsys.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,8 +11,8 @@ #ifdef HID_SUBSYS_DEBUG #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_LPC, format, ##args) #else #define CPUTS(outstr) #define CPRINTS(format, args...) @@ -21,10 +21,15 @@ #define __packed __attribute__((packed)) -#define HECI_CLIENT_HID_GUID { 0x33AECD58, 0xB679, 0x4E54,\ - { 0x9B, 0xD9, 0xA0, 0x4D, 0x34, 0xF0, 0xC2, 0x26 } } +#define HECI_CLIENT_HID_GUID \ + { \ + 0x33AECD58, 0xB679, 0x4E54, \ + { \ + 0x9B, 0xD9, 0xA0, 0x4D, 0x34, 0xF0, 0xC2, 0x26 \ + } \ + } -#define HID_SUBSYS_MAX_HID_DEVICES 3 +#define HID_SUBSYS_MAX_HID_DEVICES 3 /* * the following enum values and data structures with __packed are used for @@ -55,13 +60,13 @@ struct hid_device_info { uint16_t vid; } __packed; -struct hid_enum_payload { +struct hid_enum_payload { uint8_t num_of_hid_devices; struct hid_device_info dev_info[0]; } __packed; -#define COMMAND_MASK 0x7F -#define RESPONSE_FLAG 0x80 +#define COMMAND_MASK 0x7F +#define RESPONSE_FLAG 0x80 struct hid_msg_hdr { uint8_t command; /* bit 7 is used to indicate "response" */ uint8_t device_id; @@ -94,8 +99,8 @@ static struct hid_subsystem hid_subsys_ctx = { .heci_handle = HECI_INVALID_HANDLE, }; -#define handle_to_dev_id(_handle) ((uintptr_t)(_handle)) -#define dev_id_to_handle(_dev_id) ((hid_handle_t)(uintptr_t)(_dev_id)) +#define handle_to_dev_id(_handle) ((uintptr_t)(_handle)) +#define dev_id_to_handle(_dev_id) ((hid_handle_t)(uintptr_t)(_dev_id)) static inline hid_handle_t device_index_to_handle(int device_index) { @@ -108,8 +113,8 @@ static inline int is_valid_handle(hid_handle_t handle) (uintptr_t)handle <= hid_subsys_ctx.num_of_hid_devices; } -static inline -struct hid_subsys_hid_device *handle_to_hid_device(hid_handle_t handle) +static inline struct hid_subsys_hid_device * +handle_to_hid_device(hid_handle_t handle) { if (!is_valid_handle(handle)) return NULL; @@ -117,7 +122,6 @@ struct hid_subsys_hid_device *handle_to_hid_device(hid_handle_t handle) return &hid_subsys_ctx.hid_devices[(uintptr_t)handle - 1]; } - hid_handle_t hid_subsys_register_device(const struct hid_device *dev_info) { struct hid_subsys_hid_device *hid_device; @@ -156,7 +160,7 @@ int hid_subsys_send_input_report(const hid_handle_t handle, uint8_t *buf, const size_t buf_size) { struct hid_subsys_hid_device *hid_device; - struct hid_msg_hdr hid_msg_hdr = {0}; + struct hid_msg_hdr hid_msg_hdr = { 0 }; struct heci_msg_item msg_item[2]; struct heci_msg_list msg_list; @@ -253,7 +257,7 @@ static int handle_hid_device_msg(struct hid_msg *hid_msg) * re-use hid_msg from host for reply. */ switch (hid_msg->hdr.command & COMMAND_MASK) { - case HID_GET_HID_DESCRIPTOR: + case HID_GET_HID_DESCRIPTOR: if (cbs->get_hid_descriptor) ret = cbs->get_hid_descriptor(handle, payload, buf_size); @@ -277,10 +281,8 @@ static int handle_hid_device_msg(struct hid_msg *hid_msg) case HID_SET_FEATURE_REPORT: if (cbs->set_feature_report) { - ret = cbs->set_feature_report(handle, - payload[0], - payload, - payload_size); + ret = cbs->set_feature_report(handle, payload[0], + payload, payload_size); /* * if no error, reply only with the report id. * re-use the first byte of payload @@ -293,8 +295,8 @@ static int handle_hid_device_msg(struct hid_msg *hid_msg) break; case HID_GET_INPUT_REPORT: if (cbs->get_input_report) - ret = cbs->get_input_report(handle, payload[0], - payload, buf_size); + ret = cbs->get_input_report(handle, payload[0], payload, + buf_size); break; @@ -331,21 +333,21 @@ static int handle_hid_subsys_msg(struct hid_msg *hid_msg) struct hid_enum_payload *enum_payload; switch (hid_msg->hdr.command & COMMAND_MASK) { - case HID_DM_ENUM_DEVICES: + case HID_DM_ENUM_DEVICES: enum_payload = (struct hid_enum_payload *)hid_msg->payload; for (i = 0; i < hid_subsys_ctx.num_of_hid_devices; i++) { enum_payload->dev_info[i] = - hid_subsys_ctx.hid_devices[i].info; + hid_subsys_ctx.hid_devices[i].info; } enum_payload->num_of_hid_devices = - hid_subsys_ctx.num_of_hid_devices; + hid_subsys_ctx.num_of_hid_devices; /* reply payload size */ size = sizeof(enum_payload->num_of_hid_devices); size += enum_payload->num_of_hid_devices * - sizeof(enum_payload->dev_info[0]); + sizeof(enum_payload->dev_info[0]); break; @@ -408,7 +410,7 @@ static int hid_subsys_resume(const heci_handle_t heci_handle) for (i = 0; i < hid_subsys_ctx.num_of_hid_devices; i++) { if (hid_subsys_ctx.hid_devices[i].cbs->resume) ret |= hid_subsys_ctx.hid_devices[i].cbs->resume( - device_index_to_handle(i)); + device_index_to_handle(i)); } return ret; @@ -422,7 +424,7 @@ static int hid_subsys_suspend(const heci_handle_t heci_handle) for (i = hid_subsys_ctx.num_of_hid_devices - 1; i >= 0; i--) { if (hid_subsys_ctx.hid_devices[i].cbs->suspend) ret |= hid_subsys_ctx.hid_devices[i].cbs->suspend( - device_index_to_handle(i)); + device_index_to_handle(i)); } return ret; diff --git a/chip/ish/host_command_heci.c b/chip/ish/host_command_heci.c index 2fcab44b8b..fe82f94bda 100644 --- a/chip/ish/host_command_heci.c +++ b/chip/ish/host_command_heci.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,11 +13,16 @@ #include "util.h" #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args) - -#define HECI_CLIENT_CROS_EC_ISH_GUID { 0x7b7154d0, 0x56f4, 0x4bdc,\ - { 0xb0, 0xd8, 0x9e, 0x7c, 0xda, 0xe0, 0xd6, 0xa0 } } +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_LPC, format, ##args) + +#define HECI_CLIENT_CROS_EC_ISH_GUID \ + { \ + 0x7b7154d0, 0x56f4, 0x4bdc, \ + { \ + 0xb0, 0xd8, 0x9e, 0x7c, 0xda, 0xe0, 0xd6, 0xa0 \ + } \ + } /* Handle for all heci cros_ec interactions */ static heci_handle_t heci_cros_ec_handle = HECI_INVALID_HANDLE; @@ -33,13 +38,25 @@ static heci_handle_t heci_cros_ec_handle = HECI_INVALID_HANDLE; struct cros_ec_ishtp_msg_hdr { uint8_t channel; uint8_t status; - uint8_t id; /* Pairs up request and responses */ + uint8_t id; /* Pairs up request and responses */ uint8_t reserved; } __ec_align4; #define CROS_EC_ISHTP_MSG_HDR_SIZE sizeof(struct cros_ec_ishtp_msg_hdr) + +/* + * Increase response_buffer size + * some host command response messages use bigger space; so increase + * the buffer size on par with EC, which is 256 bytes in total. + * The size has to meet + * HECI_CROS_EC_RESPONSE_BUF_SIZE >= CROS_EC_ISHTP_MSG_HDR_SIZE + 256. + * Here 260 bytes is chosen. + */ +#define HECI_CROS_EC_RESPONSE_BUF_SIZE 260 #define HECI_CROS_EC_RESPONSE_MAX \ - (HECI_IPC_PAYLOAD_SIZE - CROS_EC_ISHTP_MSG_HDR_SIZE) + (HECI_CROS_EC_RESPONSE_BUF_SIZE - CROS_EC_ISHTP_MSG_HDR_SIZE) +BUILD_ASSERT(HECI_CROS_EC_RESPONSE_BUF_SIZE >= + CROS_EC_ISHTP_MSG_HDR_SIZE + 256); struct cros_ec_ishtp_msg { struct cros_ec_ishtp_msg_hdr hdr; @@ -51,7 +68,7 @@ enum heci_cros_ec_channel { CROS_MKBP_EVENT = 2, /* initiated from EC */ }; -static uint8_t response_buffer[IPC_MAX_PAYLOAD_SIZE] __aligned(4); +static uint8_t response_buffer[HECI_CROS_EC_RESPONSE_BUF_SIZE] __aligned(4); static struct host_packet heci_packet; int heci_send_mkbp_event(uint32_t *timestamp) @@ -88,10 +105,11 @@ static void heci_send_hostcmd_response(struct host_packet *pkt) } static void cros_ec_ishtp_subsys_new_msg_received(const heci_handle_t handle, - uint8_t *msg, const size_t msg_size) + uint8_t *msg, + const size_t msg_size) { - struct cros_ec_ishtp_msg *in = (void *) msg; - struct cros_ec_ishtp_msg *out = (void *) response_buffer; + struct cros_ec_ishtp_msg *in = (void *)msg; + struct cros_ec_ishtp_msg *out = (void *)response_buffer; if (in->hdr.channel != CROS_EC_COMMAND) { CPRINTS("Unknown HECI packet 0x%02x", in->hdr.channel); @@ -113,7 +131,8 @@ static void cros_ec_ishtp_subsys_new_msg_received(const heci_handle_t handle, heci_packet.response_size = 0; heci_packet.driver_result = EC_RES_SUCCESS; - host_packet_receive(&heci_packet); + if (IS_ENABLED(HAS_TASK_HOSTCMD)) + host_packet_receive(&heci_packet); } /* @@ -137,10 +156,10 @@ static enum ec_status heci_get_protocol_info(struct host_cmd_handler_args *args) args->response_size = sizeof(*r); - return EC_SUCCESS; + return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, heci_get_protocol_info, -EC_VER_MASK(0)); + EC_VER_MASK(0)); static int cros_ec_ishtp_subsys_initialize(const heci_handle_t heci_handle) { diff --git a/chip/ish/hpet.h b/chip/ish/hpet.h index 06738fafb1..7438f42949 100644 --- a/chip/ish/hpet.h +++ b/chip/ish/hpet.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,61 +10,58 @@ /* ISH HPET config and timer registers */ -#define TIMER0_CONF_CAP_REG 0x100 -#define TIMER0_COMP_VAL_REG 0x108 - +#define TIMER0_CONF_CAP_REG 0x100 +#define TIMER0_COMP_VAL_REG 0x108 /* HPET_GENERAL_CONFIG settings */ -#define HPET_GENERAL_CONFIG REG32(ISH_HPET_BASE + 0x10) -#define HPET_ENABLE_CNF BIT(0) -#define HPET_LEGACY_RT_CNF BIT(1) +#define HPET_GENERAL_CONFIG REG32(ISH_HPET_BASE + 0x10) +#define HPET_ENABLE_CNF BIT(0) +#define HPET_LEGACY_RT_CNF BIT(1) /* Interrupt status acknowledge register */ -#define HPET_INTR_CLEAR REG32(ISH_HPET_BASE + 0x20) +#define HPET_INTR_CLEAR REG32(ISH_HPET_BASE + 0x20) /* Main counter register. 64-bit */ -#define HPET_MAIN_COUNTER_64 REG64(ISH_HPET_BASE + 0xF0) -#define HPET_MAIN_COUNTER_64_LO REG32(ISH_HPET_BASE + 0xF0) -#define HPET_MAIN_COUNTER_64_HI REG32(ISH_HPET_BASE + 0xF4) +#define HPET_MAIN_COUNTER_64 REG64(ISH_HPET_BASE + 0xF0) +#define HPET_MAIN_COUNTER_64_LO REG32(ISH_HPET_BASE + 0xF0) +#define HPET_MAIN_COUNTER_64_HI REG32(ISH_HPET_BASE + 0xF4) /* HPET Timer 0/1/2 configuration*/ -#define HPET_TIMER_CONF_CAP(x) REG32(ISH_HPET_BASE + 0x100 + ((x) * 0x20)) -#define HPET_Tn_INT_TYPE_CNF BIT(1) -#define HPET_Tn_INT_ENB_CNF BIT(2) -#define HPET_Tn_TYPE_CNF BIT(3) -#define HPET_Tn_VAL_SET_CNF BIT(6) -#define HPET_Tn_32MODE_CNF BIT(8) -#define HPET_Tn_INT_ROUTE_CNF_SHIFT 0x9 -#define HPET_Tn_INT_ROUTE_CNF_MASK (0x1f << 9) +#define HPET_TIMER_CONF_CAP(x) REG32(ISH_HPET_BASE + 0x100 + ((x)*0x20)) +#define HPET_Tn_INT_TYPE_CNF BIT(1) +#define HPET_Tn_INT_ENB_CNF BIT(2) +#define HPET_Tn_TYPE_CNF BIT(3) +#define HPET_Tn_VAL_SET_CNF BIT(6) +#define HPET_Tn_32MODE_CNF BIT(8) +#define HPET_Tn_INT_ROUTE_CNF_SHIFT 0x9 +#define HPET_Tn_INT_ROUTE_CNF_MASK (0x1f << 9) /* * HPET Timer 0/1/2 comparator values. 1/2 are always 32-bit. 0 can be * configured as 64-bit. */ -#define HPET_TIMER_COMP(x) REG32(ISH_HPET_BASE + 0x108 + ((x) * 0x20)) -#define HPET_TIMER0_COMP_64 REG64(ISH_HPET_BASE + 0x108) +#define HPET_TIMER_COMP(x) REG32(ISH_HPET_BASE + 0x108 + ((x)*0x20)) +#define HPET_TIMER0_COMP_64 REG64(ISH_HPET_BASE + 0x108) /* ISH 4/5: Special status register * Use this register to see HPET timer are settled after a write. */ -#define HPET_CTRL_STATUS REG32(ISH_HPET_BASE + 0x160) -#define HPET_INT_STATUS_SETTLING BIT(1) -#define HPET_MAIN_COUNTER_SETTLING (BIT(2) | BIT(3)) -#define HPET_T0_CAP_SETTLING BIT(4) -#define HPET_T1_CAP_SETTLING BIT(5) -#define HPET_T0_CMP_SETTLING (BIT(7) | BIT(8)) -#define HPET_T1_CMP_SETTLING BIT(9) -#define HPET_MAIN_COUNTER_VALID BIT(13) -#define HPET_T1_SETTLING (HPET_T1_CAP_SETTLING | \ - HPET_T1_CMP_SETTLING) -#define HPET_T0_SETTLING (HPET_T0_CAP_SETTLING | \ - HPET_T0_CMP_SETTLING) -#define HPET_ANY_SETTLING (BIT(12) - 1) +#define HPET_CTRL_STATUS REG32(ISH_HPET_BASE + 0x160) +#define HPET_INT_STATUS_SETTLING BIT(1) +#define HPET_MAIN_COUNTER_SETTLING (BIT(2) | BIT(3)) +#define HPET_T0_CAP_SETTLING BIT(4) +#define HPET_T1_CAP_SETTLING BIT(5) +#define HPET_T0_CMP_SETTLING (BIT(7) | BIT(8)) +#define HPET_T1_CMP_SETTLING BIT(9) +#define HPET_MAIN_COUNTER_VALID BIT(13) +#define HPET_T1_SETTLING (HPET_T1_CAP_SETTLING | HPET_T1_CMP_SETTLING) +#define HPET_T0_SETTLING (HPET_T0_CAP_SETTLING | HPET_T0_CMP_SETTLING) +#define HPET_ANY_SETTLING (BIT(12) - 1) #if defined(CHIP_FAMILY_ISH3) -#define ISH_HPET_CLK_FREQ 12000000 /* 12 MHz clock */ +#define ISH_HPET_CLK_FREQ 12000000 /* 12 MHz clock */ #elif defined(CHIP_FAMILY_ISH4) || defined(CHIP_FAMILY_ISH5) -#define ISH_HPET_CLK_FREQ 32768 /* 32.768 KHz clock */ +#define ISH_HPET_CLK_FREQ 32768 /* 32.768 KHz clock */ #endif #endif /* __CROS_EC_HPET_H */ diff --git a/chip/ish/hwtimer.c b/chip/ish/hwtimer.c index 1259dae7f4..40c3de67a8 100644 --- a/chip/ish/hwtimer.c +++ b/chip/ish/hwtimer.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,14 +8,14 @@ #include "console.h" #include "hpet.h" #include "hwtimer.h" -#include "timer.h" #include "registers.h" #include "task.h" +#include "timer.h" #include "util.h" #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args) static uint32_t last_deadline; @@ -37,7 +37,7 @@ static uint32_t last_deadline; /* Scaling helper methods for different ISH chip variants */ #ifdef CHIP_FAMILY_ISH3 #define CLOCK_FACTOR 12 -BUILD_ASSERT(CLOCK_FACTOR * SECOND == ISH_HPET_CLK_FREQ); +BUILD_ASSERT(CLOCK_FACTOR *SECOND == ISH_HPET_CLK_FREQ); static inline uint64_t scale_us2ticks(uint64_t us) { @@ -239,8 +239,7 @@ int __hw_clock_source_init64(uint64_t start_t) /* Timer 1 - IRQ routing */ timer1_config &= ~HPET_Tn_INT_ROUTE_CNF_MASK; - timer1_config |= (ISH_HPET_TIMER1_IRQ << - HPET_Tn_INT_ROUTE_CNF_SHIFT); + timer1_config |= (ISH_HPET_TIMER1_IRQ << HPET_Tn_INT_ROUTE_CNF_SHIFT); /* Level triggered interrupt */ timer1_config |= HPET_Tn_INT_TYPE_CNF; diff --git a/chip/ish/i2c.c b/chip/ish/i2c.c index 3978011033..1da65b0b15 100644 --- a/chip/ish/i2c.c +++ b/chip/ish/i2c.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,78 +6,66 @@ /* I2C port module for ISH */ #include "common.h" -#include "console.h" #include "config_chip.h" +#include "console.h" #include "gpio.h" #include "hooks.h" +#include "hwtimer.h" #include "i2c.h" -#include "registers.h" #include "ish_i2c.h" +#include "registers.h" #include "task.h" #include "timer.h" -#include "hwtimer.h" #include "util.h" #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) /*25MHz, 50MHz, 100MHz, 120MHz, 40MHz, 20MHz, 37MHz*/ -static uint16_t default_hcnt_scl_100[] = { - 4000, 4420, 4920, 4400, 4000, 4000, 4300 -}; +static uint16_t default_hcnt_scl_100[] = { 4000, 4420, 4920, 4400, + 4000, 4000, 4300 }; -static uint16_t default_lcnt_scl_100[] = { - 4720, 5180, 4990, 5333, 4700, 5200, 4950 -}; +static uint16_t default_lcnt_scl_100[] = { 4720, 5180, 4990, 5333, + 4700, 5200, 4950 }; -static uint16_t default_hcnt_scl_400[] = { - 600, 820, 1120, 800, 600, 600, 450 -}; +static uint16_t default_hcnt_scl_400[] = { 600, 820, 1120, 800, 600, 600, 450 }; -static uint16_t default_lcnt_scl_400[] = { - 1320, 1380, 1300, 1550, 1300, 1200, 1250 -}; +static uint16_t default_lcnt_scl_400[] = { 1320, 1380, 1300, 1550, + 1300, 1200, 1250 }; -static uint16_t default_hcnt_scl_1000[] = { - 260, 260, 260, 305, 260, 260, 260 -}; +static uint16_t default_hcnt_scl_1000[] = { 260, 260, 260, 305, 260, 260, 260 }; -static uint16_t default_lcnt_scl_1000[] = { - 500, 500, 500, 525, 500, 500, 500 -}; +static uint16_t default_lcnt_scl_1000[] = { 500, 500, 500, 525, 500, 500, 500 }; static uint16_t default_hcnt_scl_hs[] = { 160, 300, 160, 166, 175, 150, 162 }; static uint16_t default_lcnt_scl_hs[] = { 320, 340, 320, 325, 325, 300, 297 }; - #ifdef CHIP_VARIANT_ISH5P4 /* Change to I2C_FREQ_100 in real silicon platform */ -static uint8_t bus_freq[ISH_I2C_PORT_COUNT] = { - I2C_FREQ_100, I2C_FREQ_100, I2C_FREQ_100 -}; +static uint8_t bus_freq[ISH_I2C_PORT_COUNT] = { I2C_FREQ_100, I2C_FREQ_100, + I2C_FREQ_100 }; #else -static uint8_t bus_freq[ISH_I2C_PORT_COUNT] = { - I2C_FREQ_120, I2C_FREQ_120, I2C_FREQ_120 -}; +static uint8_t bus_freq[ISH_I2C_PORT_COUNT] = { I2C_FREQ_120, I2C_FREQ_120, + I2C_FREQ_120 }; #endif static struct i2c_context i2c_ctxs[ISH_I2C_PORT_COUNT] = { { .bus = 0, - .base = (uint32_t *) ISH_I2C0_BASE, + .base = (uint32_t *)ISH_I2C0_BASE, .speed = I2C_SPEED_400KHZ, .int_pin = ISH_I2C0_IRQ, }, { .bus = 1, - .base = (uint32_t *) ISH_I2C1_BASE, + .base = (uint32_t *)ISH_I2C1_BASE, .speed = I2C_SPEED_400KHZ, .int_pin = ISH_I2C1_IRQ, }, { .bus = 2, - .base = (uint32_t *) ISH_I2C2_BASE, + .base = (uint32_t *)ISH_I2C2_BASE, .speed = I2C_SPEED_400KHZ, .int_pin = ISH_I2C2_IRQ, }, @@ -104,22 +92,20 @@ static struct i2c_bus_info board_config[ISH_I2C_PORT_COUNT] = { .fast_speed.sda_hold = DEFAULT_SDA_HOLD_FAST, .fast_plus_speed.sda_hold = DEFAULT_SDA_HOLD_FAST_PLUS, .high_speed.sda_hold = DEFAULT_SDA_HOLD_HIGH, - }, + }, }; -static inline void i2c_mmio_write(uint32_t *base, uint8_t offset, - uint32_t data) +static inline void i2c_mmio_write(uint32_t *base, uint8_t offset, uint32_t data) { - REG32((uint32_t) ((uint8_t *)base + offset)) = data; + REG32((uint32_t)((uint8_t *)base + offset)) = data; } static inline uint32_t i2c_mmio_read(uint32_t *base, uint8_t offset) { - return REG32((uint32_t) ((uint8_t *)base + offset)); + return REG32((uint32_t)((uint8_t *)base + offset)); } -static inline uint8_t i2c_read_byte(uint32_t *addr, uint8_t reg, - uint8_t offset) +static inline uint8_t i2c_read_byte(uint32_t *addr, uint8_t reg, uint8_t offset) { uint32_t ret = i2c_mmio_read(addr, reg) >> offset; @@ -129,7 +115,6 @@ static inline uint8_t i2c_read_byte(uint32_t *addr, uint8_t reg, static void i2c_intr_switch(uint32_t *base, int mode) { switch (mode) { - case ENABLE_WRITE_INT: i2c_mmio_write(base, IC_INTR_MASK, IC_INTR_WRITE_MASK_VAL); break; @@ -157,8 +142,8 @@ static void i2c_intr_switch(uint32_t *base, int mode) } } -static void i2c_init_transaction(struct i2c_context *ctx, - uint16_t slave_addr, uint8_t flags) +static void i2c_init_transaction(struct i2c_context *ctx, uint16_t addr, + uint8_t flags) { uint32_t con_value; uint32_t *base = ctx->base; @@ -169,64 +154,64 @@ static void i2c_init_transaction(struct i2c_context *ctx, i2c_intr_switch(base, DISABLE_INT); i2c_mmio_write(base, IC_ENABLE, IC_ENABLE_DISABLE); - i2c_mmio_write(base, IC_TAR, (slave_addr << IC_TAR_OFFSET) | - TAR_SPECIAL_VAL | IC_10BITADDR_MASTER_VAL); + i2c_mmio_write(base, IC_TAR, + (addr << IC_TAR_OFFSET) | TAR_SPECIAL_VAL | + IC_10BITADDR_MASTER_VAL); /* set Clock SCL Count */ switch (ctx->speed) { - case I2C_SPEED_100KHZ: i2c_mmio_write(base, IC_SS_SCL_HCNT, - NS_2_COUNTERS(bus_info->std_speed.hcnt, + NS_2_COUNTERS(bus_info->std_speed.hcnt, clk_in_val)); i2c_mmio_write(base, IC_SS_SCL_LCNT, - NS_2_COUNTERS(bus_info->std_speed.lcnt, + NS_2_COUNTERS(bus_info->std_speed.lcnt, clk_in_val)); i2c_mmio_write(base, IC_SDA_HOLD, - NS_2_COUNTERS(bus_info->std_speed.sda_hold, + NS_2_COUNTERS(bus_info->std_speed.sda_hold, clk_in_val)); break; case I2C_SPEED_400KHZ: i2c_mmio_write(base, IC_FS_SCL_HCNT, - NS_2_COUNTERS(bus_info->fast_speed.hcnt, + NS_2_COUNTERS(bus_info->fast_speed.hcnt, clk_in_val)); i2c_mmio_write(base, IC_FS_SCL_LCNT, - NS_2_COUNTERS(bus_info->fast_speed.lcnt, + NS_2_COUNTERS(bus_info->fast_speed.lcnt, clk_in_val)); i2c_mmio_write(base, IC_SDA_HOLD, - NS_2_COUNTERS(bus_info->fast_speed.sda_hold, + NS_2_COUNTERS(bus_info->fast_speed.sda_hold, clk_in_val)); break; case I2C_SPEED_1MHZ: i2c_mmio_write(base, IC_FS_SCL_HCNT, - NS_2_COUNTERS(bus_info->fast_plus_speed.hcnt, + NS_2_COUNTERS(bus_info->fast_plus_speed.hcnt, clk_in_val)); i2c_mmio_write(base, IC_FS_SCL_LCNT, - NS_2_COUNTERS(bus_info->fast_plus_speed.lcnt, + NS_2_COUNTERS(bus_info->fast_plus_speed.lcnt, clk_in_val)); i2c_mmio_write(base, IC_SDA_HOLD, - NS_2_COUNTERS(bus_info->fast_plus_speed.sda_hold, + NS_2_COUNTERS(bus_info->fast_plus_speed.sda_hold, clk_in_val)); break; case I2C_SPEED_3M4HZ: i2c_mmio_write(base, IC_HS_SCL_HCNT, - NS_2_COUNTERS(bus_info->high_speed.hcnt, + NS_2_COUNTERS(bus_info->high_speed.hcnt, clk_in_val)); i2c_mmio_write(base, IC_HS_SCL_LCNT, - NS_2_COUNTERS(bus_info->high_speed.lcnt, + NS_2_COUNTERS(bus_info->high_speed.lcnt, clk_in_val)); i2c_mmio_write(base, IC_SDA_HOLD, - NS_2_COUNTERS(bus_info->high_speed.sda_hold, + NS_2_COUNTERS(bus_info->high_speed.sda_hold, clk_in_val)); i2c_mmio_write(base, IC_FS_SCL_HCNT, - NS_2_COUNTERS(bus_info->fast_speed.hcnt, + NS_2_COUNTERS(bus_info->fast_speed.hcnt, clk_in_val)); i2c_mmio_write(base, IC_FS_SCL_LCNT, - NS_2_COUNTERS(bus_info->fast_speed.lcnt, + NS_2_COUNTERS(bus_info->fast_speed.lcnt, clk_in_val)); break; @@ -248,15 +233,13 @@ static void i2c_init_transaction(struct i2c_context *ctx, i2c_mmio_write(base, IC_ENABLE, IC_ENABLE_ENABLE); } -static void i2c_write_buffer(uint32_t *base, uint8_t len, - const uint8_t *buffer, ssize_t *cur_index, - ssize_t total_len) +static void i2c_write_buffer(uint32_t *base, uint8_t len, const uint8_t *buffer, + ssize_t *cur_index, ssize_t total_len) { int i; uint16_t out; for (i = 0; i < len; i++) { - ++(*cur_index); out = (buffer[i] << DATA_CMD_DAT_OFFSET) | DATA_CMD_WRITE_VAL; @@ -270,7 +253,7 @@ static void i2c_write_buffer(uint32_t *base, uint8_t len, } static void i2c_write_read_commands(uint32_t *base, uint8_t len, int more_data, - unsigned restart_flag) + unsigned int restart_flag) { /* this routine just set RX FIFO's control bit(s), * READ command or RESTART */ @@ -293,16 +276,15 @@ static void i2c_write_read_commands(uint32_t *base, uint8_t len, int more_data, } } -int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) +int chip_i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size, int flags) { int i; ssize_t total_len; uint64_t expire_ts; struct i2c_context *ctx; ssize_t curr_index = 0; - uint16_t addr = I2C_GET_ADDR(slave_addr_flags); + uint16_t addr = I2C_STRIP_FLAGS(addr_flags); int begin_indx; uint8_t repeat_start = 0; @@ -333,8 +315,8 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, /* Write W data */ if (out_size) - i2c_write_buffer(ctx->base, out_size, out, - &curr_index, total_len); + i2c_write_buffer(ctx->base, out_size, out, &curr_index, + total_len); /* Wait here until Tx is completed so that FIFO becomes empty. * This is optimized for smaller Tx data size. @@ -344,10 +326,8 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, * */ expire_ts = __hw_clock_source_read() + I2C_TX_FLUSH_TIMEOUT_USEC; if (in_size > (ISH_I2C_FIFO_SIZE - out_size)) { - while ((i2c_mmio_read(ctx->base, IC_STATUS) & BIT(IC_STATUS_TFE)) == 0) { - if (__hw_clock_source_read() >= expire_ts) { ctx->error_flag = 1; break; @@ -358,7 +338,7 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, begin_indx = 0; while (in_size) { - int rd_size; /* read size for on i2c transaction */ + int rd_size; /* read size for on i2c transaction */ /* * check if in_size > ISH_I2C_FIFO_SIZE, then try to read @@ -383,11 +363,11 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, * set R commands bit, start to read */ i2c_write_read_commands(ctx->base, rd_size, in_size, - (begin_indx == 0) && (repeat_start != 0)); - + (begin_indx == 0) && + (repeat_start != 0)); - /* need timeout in case no ACK from slave */ - task_wait_event_mask(TASK_EVENT_I2C_IDLE, 2*MSEC); + /* need timeout in case no ACK from peripheral */ + task_wait_event_mask(TASK_EVENT_I2C_IDLE, 2 * MSEC); if (ctx->interrupts & M_TX_ABRT) { ctx->error_flag = 1; @@ -396,8 +376,7 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, /* read data */ for (i = begin_indx; i < begin_indx + rd_size; i++) - in[i] = i2c_read_byte(ctx->base, - IC_DATA_CMD, 0); + in[i] = i2c_read_byte(ctx->base, IC_DATA_CMD, 0); begin_indx += rd_size; } /* while (in_size) */ @@ -411,7 +390,6 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, while ((i2c_mmio_read(ctx->base, IC_STATUS) & (BIT(IC_STATUS_MASTER_ACTIVITY) | BIT(IC_STATUS_TFE))) != BIT(IC_STATUS_TFE)) { - if (__hw_clock_source_read() >= expire_ts) { ctx->error_flag = 1; break; @@ -432,12 +410,12 @@ static void i2c_interrupt_handler(struct i2c_context *ctx) uint32_t raw_intr; if (IS_ENABLED(INTR_DEBUG)) - raw_intr = 0x0000FFFF & i2c_mmio_read(ctx->base, - IC_RAW_INTR_STAT); + raw_intr = 0x0000FFFF & + i2c_mmio_read(ctx->base, IC_RAW_INTR_STAT); /* check interrupts */ ctx->interrupts = i2c_mmio_read(ctx->base, IC_INTR_STAT); - ctx->reason = (uint16_t) i2c_mmio_read(ctx->base, IC_TX_ABRT_SOURCE); + ctx->reason = (uint16_t)i2c_mmio_read(ctx->base, IC_TX_ABRT_SOURCE); if (IS_ENABLED(INTR_DEBUG)) CPRINTS("INTR_STAT = 0x%04x, TX_ABORT_SRC = 0x%04x, " @@ -446,7 +424,7 @@ static void i2c_interrupt_handler(struct i2c_context *ctx) /* disable interrupts */ i2c_intr_switch(ctx->base, DISABLE_INT); - task_set_event(ctx->wait_task_id, TASK_EVENT_I2C_IDLE, 0); + task_set_event(ctx->wait_task_id, TASK_EVENT_I2C_IDLE); } static void i2c_isr_bus0(void) @@ -467,9 +445,8 @@ static void i2c_isr_bus2(void) } DECLARE_IRQ(ISH_I2C2_IRQ, i2c_isr_bus2); -static void i2c_config_speed(struct i2c_context *ctx, int kbps) +static void i2c_config_speed(struct i2c_context *ctx, int kbps) { - if (kbps > 1000) ctx->speed = I2C_SPEED_3M4HZ; else if (kbps > 400) @@ -478,7 +455,6 @@ static void i2c_config_speed(struct i2c_context *ctx, int kbps) ctx->speed = I2C_SPEED_400KHZ; else ctx->speed = I2C_SPEED_100KHZ; - } static void i2c_init_hardware(struct i2c_context *ctx) @@ -486,8 +462,8 @@ static void i2c_init_hardware(struct i2c_context *ctx) static const uint8_t speed_val_arr[] = { [I2C_SPEED_100KHZ] = STD_SPEED_VAL, [I2C_SPEED_400KHZ] = FAST_SPEED_VAL, - [I2C_SPEED_1MHZ] = FAST_SPEED_VAL, - [I2C_SPEED_3M4HZ] = HIGH_SPEED_VAL, + [I2C_SPEED_1MHZ] = FAST_SPEED_VAL, + [I2C_SPEED_3M4HZ] = HIGH_SPEED_VAL, }; uint32_t *base = ctx->base; @@ -495,19 +471,20 @@ static void i2c_init_hardware(struct i2c_context *ctx) /* disable interrupts */ i2c_intr_switch(base, DISABLE_INT); i2c_mmio_write(base, IC_ENABLE, IC_ENABLE_DISABLE); - i2c_mmio_write(base, IC_CON, (MASTER_MODE_VAL - | speed_val_arr[ctx->speed] - | IC_RESTART_EN_VAL - | IC_SLAVE_DISABLE_VAL)); + i2c_mmio_write(base, IC_CON, + (MASTER_MODE_VAL | speed_val_arr[ctx->speed] | + IC_RESTART_EN_VAL | IC_SLAVE_DISABLE_VAL)); i2c_mmio_write(base, IC_FS_SPKLEN, spkln[bus_freq[ctx->bus]]); i2c_mmio_write(base, IC_HS_SPKLEN, spkln[bus_freq[ctx->bus]]); /* get RX_FIFO and TX_FIFO depth */ - ctx->max_rx_depth = i2c_read_byte(base, IC_COMP_PARAM_1, - RX_BUFFER_DEPTH_OFFSET) + 1; - ctx->max_tx_depth = i2c_read_byte(base, IC_COMP_PARAM_1, - TX_BUFFER_DEPTH_OFFSET) + 1; + ctx->max_rx_depth = + i2c_read_byte(base, IC_COMP_PARAM_1, RX_BUFFER_DEPTH_OFFSET) + + 1; + ctx->max_tx_depth = + i2c_read_byte(base, IC_COMP_PARAM_1, TX_BUFFER_DEPTH_OFFSET) + + 1; } static void i2c_initial_board_config(struct i2c_context *ctx) diff --git a/chip/ish/ipc_heci.c b/chip/ish/ipc_heci.c index 5271aa3a91..8ce0a258e1 100644 --- a/chip/ish/ipc_heci.c +++ b/chip/ish/ipc_heci.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -23,19 +23,20 @@ * - Doorbell Clear Status Register (DB CSR) */ -#include "registers.h" +#include "builtin/assert.h" #include "console.h" -#include "task.h" -#include "util.h" +#include "hooks.h" +#include "hwtimer.h" #include "ipc_heci.h" #include "ish_fwst.h" #include "queue.h" -#include "hooks.h" -#include "hwtimer.h" +#include "registers.h" +#include "task.h" +#include "util.h" #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_LPC, format, ##args) /* * comminucation protocol is defined in Linux Documentation @@ -44,57 +45,55 @@ /* MNG commands */ /* The ipc_mng_task manages IPC link. It should be the highest priority */ -#define MNG_RX_CMPL_ENABLE 0 -#define MNG_RX_CMPL_DISABLE 1 -#define MNG_RX_CMPL_INDICATION 2 -#define MNG_RESET_NOTIFY 3 -#define MNG_RESET_NOTIFY_ACK 4 -#define MNG_SYNC_FW_CLOCK 5 -#define MNG_ILLEGAL_CMD 0xFF +#define MNG_RX_CMPL_ENABLE 0 +#define MNG_RX_CMPL_DISABLE 1 +#define MNG_RX_CMPL_INDICATION 2 +#define MNG_RESET_NOTIFY 3 +#define MNG_RESET_NOTIFY_ACK 4 +#define MNG_SYNC_FW_CLOCK 5 +#define MNG_ILLEGAL_CMD 0xFF /* Doorbell */ -#define IPC_DB_MSG_LENGTH_FIELD 0x3FF -#define IPC_DB_MSG_LENGTH_SHIFT 0 +#define IPC_DB_MSG_LENGTH_FIELD 0x3FF +#define IPC_DB_MSG_LENGTH_SHIFT 0 #define IPC_DB_MSG_LENGTH_MASK \ - (IPC_DB_MSG_LENGTH_FIELD << IPC_DB_MSG_LENGTH_SHIFT) + (IPC_DB_MSG_LENGTH_FIELD << IPC_DB_MSG_LENGTH_SHIFT) -#define IPC_DB_PROTOCOL_FIELD 0x0F -#define IPC_DB_PROTOCOL_SHIFT 10 +#define IPC_DB_PROTOCOL_FIELD 0x0F +#define IPC_DB_PROTOCOL_SHIFT 10 #define IPC_DB_PROTOCOL_MASK (IPC_DB_PROTOCOL_FIELD << IPC_DB_PROTOCOL_SHIFT) -#define IPC_DB_CMD_FIELD 0x0F -#define IPC_DB_CMD_SHIFT 16 -#define IPC_DB_CMD_MASK (IPC_DB_CMD_FIELD << IPC_DB_CMD_SHIFT) +#define IPC_DB_CMD_FIELD 0x0F +#define IPC_DB_CMD_SHIFT 16 +#define IPC_DB_CMD_MASK (IPC_DB_CMD_FIELD << IPC_DB_CMD_SHIFT) -#define IPC_DB_BUSY_SHIFT 31 -#define IPC_DB_BUSY_MASK BIT(IPC_DB_BUSY_SHIFT) +#define IPC_DB_BUSY_SHIFT 31 +#define IPC_DB_BUSY_MASK BIT(IPC_DB_BUSY_SHIFT) #define IPC_DB_MSG_LENGTH(drbl) \ - (((drbl) & IPC_DB_MSG_LENGTH_MASK) >> IPC_DB_MSG_LENGTH_SHIFT) + (((drbl)&IPC_DB_MSG_LENGTH_MASK) >> IPC_DB_MSG_LENGTH_SHIFT) #define IPC_DB_PROTOCOL(drbl) \ - (((drbl) & IPC_DB_PROTOCOL_MASK) >> IPC_DB_PROTOCOL_SHIFT) -#define IPC_DB_CMD(drbl) \ - (((drbl) & IPC_DB_CMD_MASK) >> IPC_DB_CMD_SHIFT) -#define IPC_DB_BUSY(drbl) (!!((drbl) & IPC_DB_BUSY_MASK)) + (((drbl)&IPC_DB_PROTOCOL_MASK) >> IPC_DB_PROTOCOL_SHIFT) +#define IPC_DB_CMD(drbl) (((drbl)&IPC_DB_CMD_MASK) >> IPC_DB_CMD_SHIFT) +#define IPC_DB_BUSY(drbl) (!!((drbl)&IPC_DB_BUSY_MASK)) -#define IPC_BUILD_DB(length, proto, cmd, busy) \ +#define IPC_BUILD_DB(length, proto, cmd, busy) \ (((busy) << IPC_DB_BUSY_SHIFT) | ((cmd) << IPC_DB_CMD_SHIFT) | \ - ((proto) << IPC_DB_PROTOCOL_SHIFT) | \ - ((length) << IPC_DB_MSG_LENGTH_SHIFT)) + ((proto) << IPC_DB_PROTOCOL_SHIFT) | \ + ((length) << IPC_DB_MSG_LENGTH_SHIFT)) #define IPC_BUILD_MNG_DB(cmd, length) \ IPC_BUILD_DB(length, IPC_PROTOCOL_MNG, cmd, 1) -#define IPC_BUILD_HECI_DB(length) \ - IPC_BUILD_DB(length, IPC_PROTOCOL_HECI, 0, 1) +#define IPC_BUILD_HECI_DB(length) IPC_BUILD_DB(length, IPC_PROTOCOL_HECI, 0, 1) -#define IPC_MSG_MAX_SIZE 0x80 -#define IPC_HOST_MSG_QUEUE_SIZE 8 -#define IPC_PMC_MSG_QUEUE_SIZE 2 +#define IPC_MSG_MAX_SIZE 0x80 +#define IPC_HOST_MSG_QUEUE_SIZE 8 +#define IPC_PMC_MSG_QUEUE_SIZE 2 -#define IPC_HANDLE_PEER_ID_SHIFT 4 -#define IPC_HANDLE_PROTOCOL_SHIFT 0 -#define IPC_HANDLE_PROTOCOL_MASK 0x0F +#define IPC_HANDLE_PEER_ID_SHIFT 4 +#define IPC_HANDLE_PROTOCOL_SHIFT 0 +#define IPC_HANDLE_PROTOCOL_MASK 0x0F #define IPC_BUILD_HANDLE(peer_id, protocol) \ ((ipc_handle_t)(((peer_id) << IPC_HANDLE_PEER_ID_SHIFT) | (protocol))) #define IPC_BUILD_MNG_HANDLE(peer_id) \ @@ -103,10 +102,10 @@ #define IPC_HANDLE_PEER_ID(handle) \ ((uint32_t)(handle) >> IPC_HANDLE_PEER_ID_SHIFT) #define IPC_HANDLE_PROTOCOL(handle) \ - ((uint32_t)(handle) & IPC_HANDLE_PROTOCOL_MASK) -#define IPC_IS_VALID_HANDLE(handle) \ + ((uint32_t)(handle)&IPC_HANDLE_PROTOCOL_MASK) +#define IPC_IS_VALID_HANDLE(handle) \ (IPC_HANDLE_PEER_ID(handle) < IPC_PEERS_COUNT && \ - IPC_HANDLE_PROTOCOL(handle) < IPC_PROTOCOL_COUNT) + IPC_HANDLE_PROTOCOL(handle) < IPC_PROTOCOL_COUNT) struct ipc_msg { uint32_t drbl; @@ -191,21 +190,20 @@ static inline void ipc_disable_pimr_db_interrupt(const struct ipc_if_ctx *ctx) IPC_PIMR &= ~ctx->pimr_2ish_bit; } -static inline void ipc_enable_pimr_clearing_interrupt( - const struct ipc_if_ctx *ctx) +static inline void +ipc_enable_pimr_clearing_interrupt(const struct ipc_if_ctx *ctx) { IPC_PIMR |= ctx->pimr_2host_clearing_bit; } -static inline void ipc_disable_pimr_clearing_interrupt( - const struct ipc_if_ctx *ctx) +static inline void +ipc_disable_pimr_clearing_interrupt(const struct ipc_if_ctx *ctx) { IPC_PIMR &= ~ctx->pimr_2host_clearing_bit; } static void write_payload_and_ring_drbl(const struct ipc_if_ctx *ctx, - uint32_t drbl, - const uint8_t *payload, + uint32_t drbl, const uint8_t *payload, size_t payload_size) { memcpy((void *)(ctx->out_msg_reg), payload, payload_size); @@ -280,7 +278,7 @@ static int ipc_send_reset_notify(const ipc_handle_t handle) static int ipc_send_cmpl_indication(struct ipc_if_ctx *ctx) { - struct ipc_msg msg; + struct ipc_msg msg = { 0 }; msg.drbl = IPC_BUILD_MNG_DB(MNG_RX_CMPL_INDICATION, 0); ipc_write_raw(ctx, msg.drbl, msg.payload, IPC_DB_MSG_LENGTH(msg.drbl)); @@ -289,8 +287,8 @@ static int ipc_send_cmpl_indication(struct ipc_if_ctx *ctx) } static int ipc_get_protocol_data(const struct ipc_if_ctx *ctx, - const uint32_t protocol, - uint8_t *buf, const size_t buf_size) + const uint32_t protocol, uint8_t *buf, + const size_t buf_size) { int len = 0, payload_size; uint8_t *src = NULL, *dest = NULL; @@ -325,9 +323,8 @@ static int ipc_get_protocol_data(const struct ipc_if_ctx *ctx, } if (IS_ENABLED(IPC_HECI_DEBUG)) - CPRINTF("ipc p=%d, db=0x%0x, payload_size=%d\n", - protocol, drbl_val, - IPC_DB_MSG_LENGTH(drbl_val)); + CPRINTF("ipc p=%d, db=0x%0x, payload_size=%d\n", protocol, + drbl_val, IPC_DB_MSG_LENGTH(drbl_val)); switch (protocol) { case IPC_PROTOCOL_HECI: @@ -340,7 +337,7 @@ static int ipc_get_protocol_data(const struct ipc_if_ctx *ctx, msg->drbl = drbl_val; dest = msg->payload; break; - default : + default: break; } @@ -377,7 +374,7 @@ static void handle_msg_recv_interrupt(const uint32_t peer_id) if (!invalid_msg) { /* send event to task */ task_set_event(ctx->msg_events[protocol].task_id, - ctx->msg_events[protocol].event, 0); + ctx->msg_events[protocol].event); } else { CPRINTS("discard msg (%d) : %d", protocol, invalid_msg); @@ -544,13 +541,11 @@ int ipc_write_timestamp(const ipc_handle_t handle, const void *buf, } ipc_handle_t ipc_open(const enum ipc_peer_id peer_id, - const enum ipc_protocol protocol, - const uint32_t event) + const enum ipc_protocol protocol, const uint32_t event) { struct ipc_if_ctx *ctx; - if (protocol >= IPC_PROTOCOL_COUNT || - peer_id >= IPC_PEERS_COUNT) + if (protocol >= IPC_PROTOCOL_COUNT || peer_id >= IPC_PEERS_COUNT) return IPC_INVALID_HANDLE; ctx = ipc_get_if_ctx(peer_id); @@ -564,9 +559,9 @@ ipc_handle_t ipc_open(const enum ipc_peer_id peer_id, ctx->msg_events[protocol].enabled = 1; ctx->msg_events[protocol].event = event; - /* For HECI protocol, set HECI UP status when IPC link is ready */ - if (peer_id == IPC_PEER_ID_HOST && - protocol == IPC_PROTOCOL_HECI && ish_fwst_is_ilup_set()) + /* For HECI protocol, set HECI UP status when IPC link is ready */ + if (peer_id == IPC_PEER_ID_HOST && protocol == IPC_PROTOCOL_HECI && + ish_fwst_is_ilup_set()) ish_fwst_set_hup(); if (ctx->initialized == 0) { @@ -686,7 +681,7 @@ int ipc_read(const ipc_handle_t handle, void *buf, const size_t buf_size, } /* event flag for MNG msg */ -#define EVENT_FLAG_BIT_MNG_MSG TASK_EVENT_CUSTOM_BIT(0) +#define EVENT_FLAG_BIT_MNG_MSG TASK_EVENT_CUSTOM_BIT(0) /* * This task handles MNG messages diff --git a/chip/ish/ipc_heci.h b/chip/ish/ipc_heci.h index 183e6a2c6b..96b08f9c4a 100644 --- a/chip/ish/ipc_heci.h +++ b/chip/ish/ipc_heci.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,17 +7,19 @@ #ifndef __IPC_HECI_H #define __IPC_HECI_H +#include + enum IPC_ERR { - IPC_ERR_IPC_IS_NOT_READY = EC_ERROR_INTERNAL_FIRST + 0, - IPC_ERR_TOO_SMALL_BUFFER = EC_ERROR_INTERNAL_FIRST + 1, - IPC_ERR_TX_QUEUE_FULL = EC_ERROR_INTERNAL_FIRST + 2, - IPC_ERR_INVALID_TASK = EC_ERROR_INTERNAL_FIRST + 3, - IPC_ERR_MSG_NOT_AVAILABLE = EC_ERROR_INTERNAL_FIRST + 4, - IPC_ERR_INVALID_MSG = EC_ERROR_INTERNAL_FIRST + 5, + IPC_ERR_IPC_IS_NOT_READY = EC_ERROR_INTERNAL_FIRST + 0, + IPC_ERR_TOO_SMALL_BUFFER = EC_ERROR_INTERNAL_FIRST + 1, + IPC_ERR_TX_QUEUE_FULL = EC_ERROR_INTERNAL_FIRST + 2, + IPC_ERR_INVALID_TASK = EC_ERROR_INTERNAL_FIRST + 3, + IPC_ERR_MSG_NOT_AVAILABLE = EC_ERROR_INTERNAL_FIRST + 4, + IPC_ERR_INVALID_MSG = EC_ERROR_INTERNAL_FIRST + 5, }; enum ipc_peer_id { - IPC_PEER_ID_HOST = 0, /* x64 host */ + IPC_PEER_ID_HOST = 0, /* x64 host */ #if 0 /* other peers are not implemented yet */ IPC_PEER_ID_PMC = 1, /* Power Management Controller */ IPC_PEER_ID_CSME = 2, /* Converged Security Management Engine */ @@ -33,11 +35,11 @@ enum ipc_peer_id { BUILD_ASSERT(IPC_PEERS_COUNT <= 0x0F); enum ipc_protocol { - IPC_PROTOCOL_BOOT = 0, /* Not supported */ - IPC_PROTOCOL_HECI, /* Host Embedded Controller Interface */ - IPC_PROTOCOL_MCTP, /* not supported */ - IPC_PROTOCOL_MNG, /* Management protocol */ - IPC_PROTOCOL_ECP, /* EC Protocol. not supported */ + IPC_PROTOCOL_BOOT = 0, /* Not supported */ + IPC_PROTOCOL_HECI, /* Host Embedded Controller Interface */ + IPC_PROTOCOL_MCTP, /* not supported */ + IPC_PROTOCOL_MNG, /* Management protocol */ + IPC_PROTOCOL_ECP, /* EC Protocol. not supported */ IPC_PROTOCOL_COUNT }; /* @@ -46,10 +48,10 @@ enum ipc_protocol { */ BUILD_ASSERT(IPC_PROTOCOL_COUNT <= 0x0F); -typedef void * ipc_handle_t; +typedef void *ipc_handle_t; -#define IPC_MAX_PAYLOAD_SIZE 128 -#define IPC_INVALID_HANDLE NULL +#define IPC_MAX_PAYLOAD_SIZE 128 +#define IPC_INVALID_HANDLE NULL /* * Open ipc channel @@ -61,8 +63,7 @@ typedef void * ipc_handle_t; * @return ipc handle or IPC_INVALID_HANDLE if there's error */ ipc_handle_t ipc_open(const enum ipc_peer_id peer_id, - const enum ipc_protocol protocol, - const uint32_t event); + const enum ipc_protocol protocol, const uint32_t event); void ipc_close(const ipc_handle_t handle); /* @@ -74,10 +75,10 @@ void ipc_close(const ipc_handle_t handle); * if > 0, wait for the specified microsecond duration time */ int ipc_read(const ipc_handle_t handle, void *buf, const size_t buf_size, - int timeout_us); + int timeout_us); /* Write message to ipc channel. */ int ipc_write_timestamp(const ipc_handle_t handle, const void *buf, - const size_t buf_size, uint32_t *timestamp); + const size_t buf_size, uint32_t *timestamp); #endif /* __IPC_HECI_H */ diff --git a/chip/ish/ish_dma.h b/chip/ish/ish_dma.h index 2c76c7d319..89d6cb7342 100644 --- a/chip/ish/ish_dma.h +++ b/chip/ish/ish_dma.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -27,6 +27,47 @@ #define PAGE_SIZE 4096 +static inline uint32_t interrupt_lock(void) +{ + uint32_t eflags = 0; + + __asm__ volatile("pushfl;" /* save eflag value */ + "popl %0;" + "cli;" + : "=r"(eflags)); /* shut off interrupts */ + return eflags; +} + +static inline void interrupt_unlock(uint32_t eflags) +{ + __asm__ volatile("pushl %0;" /* restore elfag values */ + "popfl;" + : + : "r"(eflags)); +} + +static inline int dma_poll(uint32_t addr, uint32_t expected, uint32_t mask) +{ + int retval = -1; + uint32_t counter = 0; + + /* + * The timeout is approximately 2.2 seconds according to + * value of UINT32_MAX, 120MHZ ISH clock frequency and + * instruction count which is around 4. + */ + while (counter < (UINT32_MAX / 64)) { + /* test condition */ + if ((REG32(addr) & mask) == expected) { + retval = DMA_RC_OK; + break; + } + counter++; + } + + return retval; +} + /** * SRAM: ISH local static ram * UMA: Protected system DRAM region dedicated for ISH diff --git a/chip/ish/ish_fwst.h b/chip/ish/ish_fwst.h index c114db3241..999546ca34 100644 --- a/chip/ish/ish_fwst.h +++ b/chip/ish/ish_fwst.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,84 +17,84 @@ * IPC link is up(ready) * IPC can be used by other protocols */ -#define IPC_ISH_FWSTS_ILUP_FIELD 0x01 -#define IPC_ISH_FWSTS_ILUP_SHIFT 0 -#define IPC_ISH_FWSTS_ILUP_MASK \ - (IPC_ISH_FWSTS_ILUP_FIELD << IPC_ISH_FWSTS_ILUP_SHIFT) +#define IPC_ISH_FWSTS_ILUP_FIELD 0x01 +#define IPC_ISH_FWSTS_ILUP_SHIFT 0 +#define IPC_ISH_FWSTS_ILUP_MASK \ + (IPC_ISH_FWSTS_ILUP_FIELD << IPC_ISH_FWSTS_ILUP_SHIFT) /* * HECI layer is up(ready) */ -#define IPC_ISH_FWSTS_HUP_FIELD 0x01 -#define IPC_ISH_FWSTS_HUP_SHIFT 1 +#define IPC_ISH_FWSTS_HUP_FIELD 0x01 +#define IPC_ISH_FWSTS_HUP_SHIFT 1 #define IPC_ISH_FWSTS_HUP_MASK \ - (IPC_ISH_FWSTS_HUP_FIELD << IPC_ISH_FWSTS_HUP_SHIFT) + (IPC_ISH_FWSTS_HUP_FIELD << IPC_ISH_FWSTS_HUP_SHIFT) /* * ISH FW reason reason */ -#define IPC_ISH_FWSTS_FAIL_REASON_FIELD 0x0F -#define IPC_ISH_FWSTS_FAIL_REASON_SHIFT 2 +#define IPC_ISH_FWSTS_FAIL_REASON_FIELD 0x0F +#define IPC_ISH_FWSTS_FAIL_REASON_SHIFT 2 #define IPC_ISH_FWSTS_FAIL_REASON_MASK \ - (IPC_ISH_FWSTS_FAIL_REASON_FIELD << IPC_ISH_FWSTS_FAIL_REASON_SHIFT) + (IPC_ISH_FWSTS_FAIL_REASON_FIELD << IPC_ISH_FWSTS_FAIL_REASON_SHIFT) /* * ISH FW reset ID */ -#define IPC_ISH_FWSTS_RESET_ID_FIELD 0x0F -#define IPC_ISH_FWSTS_RESET_ID_SHIFT 8 +#define IPC_ISH_FWSTS_RESET_ID_FIELD 0x0F +#define IPC_ISH_FWSTS_RESET_ID_SHIFT 8 #define IPC_ISH_FWSTS_RESET_ID_MASK \ - (IPC_ISH_FWSTS_RESET_ID_FIELD << IPC_ISH_FWSTS_RESET_ID_SHIFT) + (IPC_ISH_FWSTS_RESET_ID_FIELD << IPC_ISH_FWSTS_RESET_ID_SHIFT) /* * ISH FW status type */ enum { - FWSTS_AFTER_RESET = 0, - FWSTS_WAIT_FOR_HOST = 4, - FWSTS_START_KERNEL_DMA = 5, - FWSTS_FW_IS_RUNNING = 7, - FWSTS_SENSOR_APP_LOADED = 8, - FWSTS_SENSOR_APP_RUNNING = 15 + FWSTS_AFTER_RESET = 0, + FWSTS_WAIT_FOR_HOST = 4, + FWSTS_START_KERNEL_DMA = 5, + FWSTS_FW_IS_RUNNING = 7, + FWSTS_SENSOR_APP_LOADED = 8, + FWSTS_SENSOR_APP_RUNNING = 15 }; /* * General ISH FW status */ -#define IPC_ISH_FWSTS_FW_STATUS_FIELD 0x0F -#define IPC_ISH_FWSTS_FW_STATUS_SHIFT 12 +#define IPC_ISH_FWSTS_FW_STATUS_FIELD 0x0F +#define IPC_ISH_FWSTS_FW_STATUS_SHIFT 12 #define IPC_ISH_FWSTS_FW_STATUS_MASK \ - (IPC_ISH_FWSTS_FW_STATUS_FIELD << IPC_ISH_FWSTS_FW_STATUS_SHIFT) + (IPC_ISH_FWSTS_FW_STATUS_FIELD << IPC_ISH_FWSTS_FW_STATUS_SHIFT) -#define IPC_ISH_FWSTS_DMA0_IN_USE_FIELD 0x01 -#define IPC_ISH_FWSTS_DMA0_IN_USE_SHIFT 16 +#define IPC_ISH_FWSTS_DMA0_IN_USE_FIELD 0x01 +#define IPC_ISH_FWSTS_DMA0_IN_USE_SHIFT 16 #define IPC_ISH_FWSTS_DMA0_IN_USE_MASK \ - (IPC_ISH_FWSTS_DMA0_IN_USE_FIELD << IPC_ISH_FWSTS_DMA0_IN_USE_SHIFT) + (IPC_ISH_FWSTS_DMA0_IN_USE_FIELD << IPC_ISH_FWSTS_DMA0_IN_USE_SHIFT) -#define IPC_ISH_FWSTS_DMA1_IN_USE_FIELD 0x01 -#define IPC_ISH_FWSTS_DMA1_IN_USE_SHIFT 17 +#define IPC_ISH_FWSTS_DMA1_IN_USE_FIELD 0x01 +#define IPC_ISH_FWSTS_DMA1_IN_USE_SHIFT 17 #define IPC_ISH_FWSTS_DMA1_IN_USE_MASK \ - (IPC_ISH_FWSTS_DMA1_IN_USE_FIELD << IPC_ISH_FWSTS_DMA1_IN_USE_SHIFT) + (IPC_ISH_FWSTS_DMA1_IN_USE_FIELD << IPC_ISH_FWSTS_DMA1_IN_USE_SHIFT) -#define IPC_ISH_FWSTS_DMA2_IN_USE_FIELD 0x01 -#define IPC_ISH_FWSTS_DMA2_IN_USE_SHIFT 18 +#define IPC_ISH_FWSTS_DMA2_IN_USE_FIELD 0x01 +#define IPC_ISH_FWSTS_DMA2_IN_USE_SHIFT 18 #define IPC_ISH_FWSTS_DMA2_IN_USE_MASK \ - (IPC_ISH_FWSTS_DMA2_IN_USE_FIELD << IPC_ISH_FWSTS_DMA2_IN_USE_SHIFT) + (IPC_ISH_FWSTS_DMA2_IN_USE_FIELD << IPC_ISH_FWSTS_DMA2_IN_USE_SHIFT) -#define IPC_ISH_FWSTS_DMA3_IN_USE_FIELD 0x01 -#define IPC_ISH_FWSTS_DMA3_IN_USE_SHIFT 19 +#define IPC_ISH_FWSTS_DMA3_IN_USE_FIELD 0x01 +#define IPC_ISH_FWSTS_DMA3_IN_USE_SHIFT 19 #define IPC_ISH_FWSTS_DMA3_IN_USE_MASK \ - (IPC_ISH_FWSTS_DMA3_IN_USE_FIELD << IPC_ISH_FWSTS_DMA3_IN_USE_SHIFT) + (IPC_ISH_FWSTS_DMA3_IN_USE_FIELD << IPC_ISH_FWSTS_DMA3_IN_USE_SHIFT) -#define IPC_ISH_FWSTS_POWER_STATE_FIELD 0x0F -#define IPC_ISH_FWSTS_POWER_STATE_SHIFT 20 +#define IPC_ISH_FWSTS_POWER_STATE_FIELD 0x0F +#define IPC_ISH_FWSTS_POWER_STATE_SHIFT 20 #define IPC_ISH_FWSTS_POWER_STATE_MASK \ - (IPC_ISH_FWSTS_POWER_STATE_FIELD << IPC_ISH_FWSTS_POWER_STATE_SHIFT) + (IPC_ISH_FWSTS_POWER_STATE_FIELD << IPC_ISH_FWSTS_POWER_STATE_SHIFT) -#define IPC_ISH_FWSTS_AON_CHECK_FIELD 0x07 -#define IPC_ISH_FWSTS_AON_CHECK_SHIFT 24 +#define IPC_ISH_FWSTS_AON_CHECK_FIELD 0x07 +#define IPC_ISH_FWSTS_AON_CHECK_SHIFT 24 #define IPC_ISH_FWSTS_AON_CHECK_MASK \ - (IPC_ISH_FWSTS_AON_CHECK_FIELD << IPC_ISH_FWSTS_AON_CHECK_SHIFT) + (IPC_ISH_FWSTS_AON_CHECK_FIELD << IPC_ISH_FWSTS_AON_CHECK_SHIFT) /* get ISH FW status register */ static inline uint32_t ish_fwst_get(void) @@ -105,7 +105,7 @@ static inline uint32_t ish_fwst_get(void) /* set IPC link up */ static inline void ish_fwst_set_ilup(void) { - IPC_ISH_FWSTS |= (1<> IPC_ISH_FWSTS_FAIL_REASON_SHIFT; + return (IPC_ISH_FWSTS & IPC_ISH_FWSTS_FAIL_REASON_MASK) >> + IPC_ISH_FWSTS_FAIL_REASON_SHIFT; } /* set reset id */ @@ -160,14 +160,14 @@ static inline void ish_fwst_set_reset_id(uint32_t val) uint32_t fwst = IPC_ISH_FWSTS; IPC_ISH_FWSTS = (fwst & ~IPC_ISH_FWSTS_RESET_ID_MASK) | - (val << IPC_ISH_FWSTS_RESET_ID_SHIFT); + (val << IPC_ISH_FWSTS_RESET_ID_SHIFT); } /* get reset id */ static inline uint32_t ish_fwst_get_reset_id(void) { - return (IPC_ISH_FWSTS & IPC_ISH_FWSTS_RESET_ID_MASK) - >> IPC_ISH_FWSTS_RESET_ID_SHIFT; + return (IPC_ISH_FWSTS & IPC_ISH_FWSTS_RESET_ID_MASK) >> + IPC_ISH_FWSTS_RESET_ID_SHIFT; } /* set general fw status */ @@ -176,14 +176,14 @@ static inline void ish_fwst_set_fw_status(uint32_t val) uint32_t fwst = IPC_ISH_FWSTS; IPC_ISH_FWSTS = (fwst & ~IPC_ISH_FWSTS_FW_STATUS_MASK) | - (val << IPC_ISH_FWSTS_FW_STATUS_SHIFT); + (val << IPC_ISH_FWSTS_FW_STATUS_SHIFT); } /* get general fw status */ static inline uint32_t ish_fwst_get_fw_status(void) { - return (IPC_ISH_FWSTS & IPC_ISH_FWSTS_FW_STATUS_MASK) - >> IPC_ISH_FWSTS_FW_STATUS_SHIFT; + return (IPC_ISH_FWSTS & IPC_ISH_FWSTS_FW_STATUS_MASK) >> + IPC_ISH_FWSTS_FW_STATUS_SHIFT; } #endif /* __ISH_FWST_H */ diff --git a/chip/ish/ish_i2c.h b/chip/ish/ish_i2c.h index 5b30de775c..7aa2977178 100644 --- a/chip/ish/ish_i2c.h +++ b/chip/ish/ish_i2c.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,25 +6,25 @@ #ifndef __CROS_EC_ISH_I2C_H #define __CROS_EC_ISH_I2C_H -#include #include "task.h" -#define I2C_TSC_TIMEOUT 2000000 -#define I2C_CALIB_ADDRESS 0x3 -#define I2C_INTERRUPT_TIMEOUT (TICKFREQ / 20) -#define NS_IN_SEC 1000 -#define DEFAULT_SDA_HOLD 240 -#define DEFAULT_SDA_HOLD_STD 2400 -#define DEFAULT_SDA_HOLD_FAST 600 -#define DEFAULT_SDA_HOLD_FAST_PLUS 300 -#define DEFAULT_SDA_HOLD_HIGH 140 -#define NS_2_COUNTERS(ns, clk) ((ns * clk)/NS_IN_SEC) -#define COUNTERS_2_NS(counters, clk) (counters * (NANOSECONDS_IN_SEC / \ - (clk * HZ_IN_MEGAHZ))) -#define I2C_TX_FLUSH_TIMEOUT_USEC 200 +#include -#define ISH_I2C_FIFO_SIZE 64 +#define I2C_TSC_TIMEOUT 2000000 +#define I2C_CALIB_ADDRESS 0x3 +#define I2C_INTERRUPT_TIMEOUT (TICKFREQ / 20) +#define NS_IN_SEC 1000 +#define DEFAULT_SDA_HOLD 240 +#define DEFAULT_SDA_HOLD_STD 2400 +#define DEFAULT_SDA_HOLD_FAST 600 +#define DEFAULT_SDA_HOLD_FAST_PLUS 300 +#define DEFAULT_SDA_HOLD_HIGH 140 +#define NS_2_COUNTERS(ns, clk) ((ns * clk) / NS_IN_SEC) +#define COUNTERS_2_NS(counters, clk) \ + (counters * (NANOSECONDS_IN_SEC / (clk * HZ_IN_MEGAHZ))) +#define I2C_TX_FLUSH_TIMEOUT_USEC 200 +#define ISH_I2C_FIFO_SIZE 64 enum { /* freq mode values */ @@ -38,29 +38,18 @@ enum { }; const unsigned int clk_in[] = { - [I2C_FREQ_25] = 25, - [I2C_FREQ_50] = 50, - [I2C_FREQ_100] = 100, - [I2C_FREQ_120] = 120, - [I2C_FREQ_40] = 40, - [I2C_FREQ_20] = 20, + [I2C_FREQ_25] = 25, [I2C_FREQ_50] = 50, [I2C_FREQ_100] = 100, + [I2C_FREQ_120] = 120, [I2C_FREQ_40] = 40, [I2C_FREQ_20] = 20, [I2C_FREQ_37] = 37, }; const uint8_t spkln[] = { - [I2C_FREQ_25] = 2, - [I2C_FREQ_50] = 3, - [I2C_FREQ_100] = 5, - [I2C_FREQ_120] = 6, - [I2C_FREQ_40] = 2, - [I2C_FREQ_20] = 1, + [I2C_FREQ_25] = 2, [I2C_FREQ_50] = 3, [I2C_FREQ_100] = 5, + [I2C_FREQ_120] = 6, [I2C_FREQ_40] = 2, [I2C_FREQ_20] = 1, [I2C_FREQ_37] = 2, }; -enum { - I2C_READ, - I2C_WRITE -}; +enum { I2C_READ, I2C_WRITE }; enum { /* REGISTERS */ @@ -125,7 +114,7 @@ enum { IC_10BITADDR_MASTER = 0, /* IC_TAR WRITE VALUES */ IC_10BITADDR_MASTER_VAL = - (IC_10BITADDR_MASTER << IC_10BITADDR_MASTER_OFFSET), + (IC_10BITADDR_MASTER << IC_10BITADDR_MASTER_OFFSET), TAR_SPECIAL_VAL = (TAR_SPECIAL << SPECIAL_OFFSET), /* IC_DATA_CMD OFFSETS */ DATA_CMD_DAT_OFFSET = 0, @@ -180,13 +169,13 @@ struct i2c_bus_info { struct i2c_bus_data fast_speed; struct i2c_bus_data fast_plus_speed; struct i2c_bus_data high_speed; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); enum i2c_speed { - I2C_SPEED_100KHZ, /* 100kHz */ - I2C_SPEED_400KHZ, /* 400kHz */ - I2C_SPEED_1MHZ, /* 1MHz */ - I2C_SPEED_3M4HZ, /* 3.4MHz */ + I2C_SPEED_100KHZ, /* 100kHz */ + I2C_SPEED_400KHZ, /* 400kHz */ + I2C_SPEED_1MHZ, /* 1MHz */ + I2C_SPEED_3M4HZ, /* 3.4MHz */ }; struct i2c_context { diff --git a/chip/ish/ish_persistent_data.c b/chip/ish/ish_persistent_data.c index 003f781d5f..ed909d6f7b 100644 --- a/chip/ish/ish_persistent_data.c +++ b/chip/ish/ish_persistent_data.c @@ -1,14 +1,14 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" -#include "ec_commands.h" #include "config.h" +#include "ec_commands.h" #include "hooks.h" -#include "system.h" #include "ish_persistent_data.h" +#include "system.h" #define PERSISTENT_DATA_MAGIC 0x49534864 /* "ISHd" */ @@ -16,7 +16,7 @@ struct ish_persistent_data ish_persistent_data = { .magic = PERSISTENT_DATA_MAGIC, .reset_flags = EC_RESET_FLAG_POWER_ON, .watchdog_counter = 0, - .panic_data = {0}, + .panic_data = { 0 }, }; /* @@ -40,8 +40,7 @@ void ish_persistent_data_init(void) { if (ish_persistent_data_aon.magic == PERSISTENT_DATA_MAGIC) { /* Stored data is valid, load a copy */ - memcpy(&ish_persistent_data, - &ish_persistent_data_aon, + memcpy(&ish_persistent_data, &ish_persistent_data_aon, sizeof(struct ish_persistent_data)); /* Invalidate stored data, in case commit fails to happen */ @@ -54,7 +53,6 @@ void ish_persistent_data_init(void) void ish_persistent_data_commit(void) { - memcpy(&ish_persistent_data_aon, - &ish_persistent_data, + memcpy(&ish_persistent_data_aon, &ish_persistent_data, sizeof(struct ish_persistent_data)); } diff --git a/chip/ish/ish_persistent_data.h b/chip/ish/ish_persistent_data.h index 0fd973e1bb..60aa6b94ae 100644 --- a/chip/ish/ish_persistent_data.h +++ b/chip/ish/ish_persistent_data.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/ish/power_mgt.c b/chip/ish/power_mgt.c index 6664b589a8..de9022b55a 100644 --- a/chip/ish/power_mgt.c +++ b/chip/ish/power_mgt.c @@ -1,10 +1,8 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include - #include "aontaskfw/ish_aon_share.h" #include "console.h" #include "hwtimer.h" @@ -17,6 +15,8 @@ #include "util.h" #include "watchdog.h" +#include + #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) #define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) #define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) @@ -52,7 +52,7 @@ static void pg_exit_restore_hw(void) * fixed amount of time to keep the console in use flag true after boot in * order to give a permanent window in which the low speed clock is not used. */ -#define CONSOLE_IN_USE_ON_BOOT_TIME (15*SECOND) +#define CONSOLE_IN_USE_ON_BOOT_TIME (15 * SECOND) /* power management internal context data structure */ struct pm_context { @@ -172,20 +172,20 @@ static void init_aon_task(void) * limit: 0x67 * Present = 1, DPL = 0 */ - desc_lo = GEN_GDT_DESC_LO((uint32_t)&main_tss, - GDT_DESC_TSS_LIMIT, GDT_DESC_TSS_FLAGS); - desc_up = GEN_GDT_DESC_UP((uint32_t)&main_tss, - GDT_DESC_TSS_LIMIT, GDT_DESC_TSS_FLAGS); + desc_lo = GEN_GDT_DESC_LO((uint32_t)&main_tss, GDT_DESC_TSS_LIMIT, + GDT_DESC_TSS_FLAGS); + desc_up = GEN_GDT_DESC_UP((uint32_t)&main_tss, GDT_DESC_TSS_LIMIT, + GDT_DESC_TSS_FLAGS); add_gdt_entry(desc_lo, desc_up); /* set GDT entry 4 for TSS descriptor of aontask * limit: 0x67 * Present = 1, DPL = 0, Accessed = 1 */ - desc_lo = GEN_GDT_DESC_LO((uint32_t)aon_tss, - GDT_DESC_TSS_LIMIT, GDT_DESC_TSS_FLAGS); - desc_up = GEN_GDT_DESC_UP((uint32_t)aon_tss, - GDT_DESC_TSS_LIMIT, GDT_DESC_TSS_FLAGS); + desc_lo = GEN_GDT_DESC_LO((uint32_t)aon_tss, GDT_DESC_TSS_LIMIT, + GDT_DESC_TSS_FLAGS); + desc_up = GEN_GDT_DESC_UP((uint32_t)aon_tss, GDT_DESC_TSS_LIMIT, + GDT_DESC_TSS_FLAGS); pm_ctx.aon_tss_selector[1] = add_gdt_entry(desc_lo, desc_up); /* set GDT entry 5 for LDT descriptor of aontask @@ -205,12 +205,12 @@ static void init_aon_task(void) "pop %eax;"); aon_share->main_fw_ro_addr = (uint32_t)&__aon_ro_start; - aon_share->main_fw_ro_size = (uint32_t)&__aon_ro_end - - (uint32_t)&__aon_ro_start; + aon_share->main_fw_ro_size = + (uint32_t)&__aon_ro_end - (uint32_t)&__aon_ro_start; aon_share->main_fw_rw_addr = (uint32_t)&__aon_rw_start; - aon_share->main_fw_rw_size = (uint32_t)&__aon_rw_end - - (uint32_t)&__aon_rw_start; + aon_share->main_fw_rw_size = + (uint32_t)&__aon_rw_end - (uint32_t)&__aon_rw_start; aon_share->uma_msb = IPC_UMA_RANGE_LOWER_1; @@ -258,8 +258,7 @@ static void switch_to_aontask(void) interrupt_enable(); } -noreturn -static void handle_reset_in_aontask(enum ish_pm_state pm_state) +noreturn static void handle_reset_in_aontask(enum ish_pm_state pm_state) { pm_ctx.aon_share->pm_state = pm_state; @@ -318,10 +317,8 @@ static uint32_t convert_both_edge_gpio_to_single_edge(void) * interrupt trigger mode enabled pins. */ for (i = 0; i < 32; i++) { - if (ISH_GPIO_GIMR & BIT(i) && - ISH_GPIO_GRER & BIT(i) && + if (ISH_GPIO_GIMR & BIT(i) && ISH_GPIO_GRER & BIT(i) && ISH_GPIO_GFER & BIT(i)) { - /* Record the pin so we can restore it later */ both_edge_pins |= BIT(i); @@ -513,7 +510,6 @@ static int d0ix_decide(timestamp_t cur_time, uint32_t idle_us) int pm_state = ISH_PM_STATE_D0I0; if (DEEP_SLEEP_ALLOWED) { - /* check if the console use has expired. */ if (sleep_mask & SLEEP_MASK_CONSOLE) { if (cur_time.val > pm_ctx.console_expire_time.val) { @@ -525,8 +521,7 @@ static int d0ix_decide(timestamp_t cur_time, uint32_t idle_us) } if (IS_ENABLED(CONFIG_ISH_PM_D0I3) && - idle_us >= CONFIG_ISH_D0I3_MIN_USEC && - pm_ctx.aon_valid) + idle_us >= CONFIG_ISH_D0I3_MIN_USEC && pm_ctx.aon_valid) pm_state = ISH_PM_STATE_D0I3; else if (IS_ENABLED(CONFIG_ISH_PM_D0I2) && @@ -617,18 +612,41 @@ void ish_pm_init(void) /* clear reset history register in CCU */ CCU_RST_HST = CCU_RST_HST; +#if defined(CHIP_VARIANT_ISH5P4) + if (IS_ENABLED(CONFIG_ISH_NEW_PM)) + PMU_D3_STATUS_1 = 0xffffffff; +#endif + /* disable TCG and disable BCG */ - CCU_TCG_EN = 0; + CCU_TCG_ENABLE = 0; + CCU_BCG_ENABLE = 0; + + /* Disable power gate of CACHE and ROM */ + PMU_RF_ROM_PWR_CTRL = 0; + reset_bcg(); if (IS_ENABLED(CONFIG_ISH_PM_AONTASK)) init_aon_task(); - /* unmask all wake up events */ + if (IS_ENABLED(CONFIG_ISH_NEW_PM)) { + PMU_GPIO_WAKE_MASK0 = 0; + PMU_GPIO_WAKE_MASK1 = 0; + } + + /* Unmask all wake up events in event1 */ PMU_MASK_EVENT = ~PMU_MASK_EVENT_BIT_ALL; + /* Mask events in event2 */ + PMU_MASK_EVENT2 = PMU_MASK2_ALL_EVENTS; + +#if defined(CHIP_VARIANT_ISH5P4) + SBEP_REG_CLK_GATE_ENABLE = + (SB_CLK_GATE_EN_LOCAL_CLK_GATE | SB_CLK_GATE_EN_TRUNK_CLK_GATE); +#endif if (IS_ENABLED(CONFIG_ISH_NEW_PM)) { - PMU_ISH_FABRIC_CNT = (PMU_ISH_FABRIC_CNT & 0xffff0000) | FABRIC_IDLE_COUNT; + PMU_ISH_FABRIC_CNT = (PMU_ISH_FABRIC_CNT & 0xffff0000) | + FABRIC_IDLE_COUNT; PMU_PGCB_CLKGATE_CTRL = TRUNK_CLKGATE_COUNT; } @@ -647,15 +665,22 @@ void ish_pm_init(void) (PMU_D3_STATUS & PMU_BME_BIT_SET)) PMU_D3_STATUS = PMU_D3_STATUS; +#if defined(CHIP_VARIANT_ISH5P4) + if (IS_ENABLED(CONFIG_ISH_NEW_PM)) { + /* Mask all function1 */ + PMU_REG_MASK_D3_RISE = 0x2; + PMU_REG_MASK_D3_FALL = 0x2; + PMU_REG_MASK_BME_RISE = 0x2; + PMU_REG_MASK_BME_FALL = 0x2; + } +#endif enable_d3bme_irqs(); } } -noreturn -void ish_pm_reset(enum ish_pm_state pm_state) +noreturn void ish_pm_reset(enum ish_pm_state pm_state) { - if (IS_ENABLED(CONFIG_ISH_PM_AONTASK) && - pm_ctx.aon_valid) { + if (IS_ENABLED(CONFIG_ISH_PM_AONTASK) && pm_ctx.aon_valid) { handle_reset_in_aontask(pm_state); } else { ish_mia_reset(); @@ -674,8 +699,8 @@ void __idle(void) * time in order to give a fixed window on boot */ disable_sleep(SLEEP_MASK_CONSOLE); - pm_ctx.console_expire_time.val = get_time().val + - CONSOLE_IN_USE_ON_BOOT_TIME; + pm_ctx.console_expire_time.val = + get_time().val + CONSOLE_IN_USE_ON_BOOT_TIME; while (1) { t0 = get_time(); @@ -709,7 +734,7 @@ static void print_stats(const char *name, const struct pm_stat *stat) /** * Print low power idle statistics */ -static int command_idle_stats(int argc, char **argv) +static int command_idle_stats(int argc, const char **argv) { struct ish_aon_share *aon_share = pm_ctx.aon_share; @@ -737,13 +762,11 @@ static int command_idle_stats(int argc, char **argv) DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", "Print power management statistics"); - /** * main FW only need handle PMU wakeup interrupt for D0i1 state, aontask will * handle PMU wakeup interrupt for other low power states */ -__maybe_unused -static void pmu_wakeup_isr(void) +__maybe_unused static void pmu_wakeup_isr(void) { /* at current nothing need to do */ } @@ -758,8 +781,7 @@ DECLARE_IRQ(ISH_PMU_WAKEUP_IRQ, pmu_wakeup_isr); * */ -__maybe_unused noreturn -static void reset_prep_isr(void) +__maybe_unused noreturn static void reset_prep_isr(void) { /* mask reset prep avail interrupt */ PMU_RST_PREP = PMU_RST_PREP_INT_MASK; @@ -779,8 +801,7 @@ static void reset_prep_isr(void) DECLARE_IRQ(ISH_RESET_PREP_IRQ, reset_prep_isr); #endif -__maybe_unused -static void handle_d3(uint32_t irq_vec) +__maybe_unused static void handle_d3(uint32_t irq_vec) { PMU_D3_STATUS = PMU_D3_STATUS; @@ -834,5 +855,5 @@ void ish_pm_refresh_console_in_use(void) /* Set console in use expire time. */ pm_ctx.console_expire_time = get_time(); pm_ctx.console_expire_time.val += - pm_ctx.console_in_use_timeout_sec * SECOND; + pm_ctx.console_in_use_timeout_sec * SECOND; } diff --git a/chip/ish/power_mgt.h b/chip/ish/power_mgt.h index a1fd5aabb6..a7a702018f 100644 --- a/chip/ish/power_mgt.h +++ b/chip/ish/power_mgt.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,19 +6,19 @@ #ifndef __CROS_EC_POWER_MGT_H #define __CROS_EC_POWER_MGT_H -#include - #include "common.h" #include "registers.h" +#include + extern void uart_port_restore(void); extern void uart_to_idle(void); extern void clear_fabric_error(void); extern void i2c_port_restore(void); extern void lapic_restore(void); -#define FABRIC_IDLE_COUNT 50 -#define TRUNK_CLKGATE_COUNT 0xf +#define FABRIC_IDLE_COUNT 50 +#define TRUNK_CLKGATE_COUNT 0xf /* power states for ISH */ enum ish_pm_state { @@ -58,8 +58,7 @@ static inline void ish_mia_halt(void) } /* reset ISH mintue-ia cpu core */ -noreturn -static inline void ish_mia_reset(void) +noreturn static inline void ish_mia_reset(void) { /** * ISH HW looks at the rising edge of this bit to diff --git a/chip/ish/registers.h b/chip/ish/registers.h index 258abe33ef..7fe5d2c5ab 100644 --- a/chip/ish/registers.h +++ b/chip/ish/registers.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -19,99 +19,100 @@ * ISH3.0 has 3 controllers. Locking must occur by-controller (not by-port). */ enum ish_i2c_port { - ISH_I2C0 = 0, /* Controller 0 */ - ISH_I2C1 = 1, /* Controller 1 */ - ISH_I2C2 = 2, /* Controller 2 */ + ISH_I2C0 = 0, /* Controller 0 */ + ISH_I2C1 = 1, /* Controller 1 */ + ISH_I2C2 = 2, /* Controller 2 */ I2C_PORT_COUNT, }; #endif -#define ISH_I2C_PORT_COUNT I2C_PORT_COUNT +#define ISH_I2C_PORT_COUNT I2C_PORT_COUNT /* In ISH, the devices are mapped to pre-defined addresses in the 32-bit * linear address space. */ #ifdef CHIP_VARIANT_ISH5P4 -#define ISH_I2C0_BASE 0x00000000 -#define ISH_I2C1_BASE 0x00002000 -#define ISH_I2C2_BASE 0x00004000 -#define ISH_UART_BASE 0x08100000 -#define ISH_GPIO_BASE 0x00100000 -#define ISH_PMU_BASE 0x04200000 -#define ISH_OCP_BASE 0xFFFFFFFF -#define ISH_MISC_BASE 0x04400000 -#define ISH_DMA_BASE 0x10100000 -#define ISH_CCU_BASE 0x04300000 -#define ISH_IPC_BASE 0x04100000 -#define ISH_WDT_BASE 0x04900000 -#define ISH_IOAPIC_BASE 0xFEC00000 -#define ISH_HPET_BASE 0x04700000 -#define ISH_LAPIC_BASE 0xFEE00000 +#define ISH_I2C0_BASE 0x00000000 +#define ISH_I2C1_BASE 0x00002000 +#define ISH_I2C2_BASE 0x00004000 +#define ISH_UART_BASE 0x08100000 +#define ISH_GPIO_BASE 0x00100000 +#define ISH_PMU_BASE 0x04200000 +#define ISH_OCP_BASE 0xFFFFFFFF +#define ISH_MISC_BASE 0x04400000 +#define ISH_DMA_BASE 0x10100000 +#define ISH_CCU_BASE 0x04300000 +#define ISH_IPC_BASE 0x04100000 +#define ISH_WDT_BASE 0x04900000 +#define ISH_IOAPIC_BASE 0xFEC00000 +#define ISH_HPET_BASE 0x04700000 +#define ISH_LAPIC_BASE 0xFEE00000 +#define ISH_SBEP_BASE 0x04500000 #else -#define ISH_I2C0_BASE 0x00100000 -#define ISH_I2C1_BASE 0x00102000 -#define ISH_I2C2_BASE 0x00105000 -#define ISH_UART_BASE 0x00103000 -#define ISH_GPIO_BASE 0x001F0000 -#define ISH_PMU_BASE 0x00800000 -#define ISH_OCP_BASE 0x00700000 -#define ISH_MISC_BASE 0x00C00000 -#define ISH_DMA_BASE 0x00400000 -#define ISH_CCU_BASE 0x00900000 -#define ISH_IPC_BASE 0x00B00000 -#define ISH_WDT_BASE 0xFDE00000 -#define ISH_IOAPIC_BASE 0xFEC00000 -#define ISH_HPET_BASE 0xFED00000 -#define ISH_LAPIC_BASE 0xFEE00000 +#define ISH_I2C0_BASE 0x00100000 +#define ISH_I2C1_BASE 0x00102000 +#define ISH_I2C2_BASE 0x00105000 +#define ISH_UART_BASE 0x00103000 +#define ISH_GPIO_BASE 0x001F0000 +#define ISH_PMU_BASE 0x00800000 +#define ISH_OCP_BASE 0x00700000 +#define ISH_MISC_BASE 0x00C00000 +#define ISH_DMA_BASE 0x00400000 +#define ISH_CCU_BASE 0x00900000 +#define ISH_IPC_BASE 0x00B00000 +#define ISH_WDT_BASE 0xFDE00000 +#define ISH_IOAPIC_BASE 0xFEC00000 +#define ISH_HPET_BASE 0xFED00000 +#define ISH_LAPIC_BASE 0xFEE00000 #endif /* HW interrupt pins mapped to IOAPIC, from I/O sources */ #ifdef CHIP_VARIANT_ISH5P4 -#define ISH_I2C0_IRQ 15 -#define ISH_I2C1_IRQ 16 -#define ISH_FABRIC_IRQ 12 -#define ISH_I2C2_IRQ 17 -#define ISH_WDT_IRQ 26 -#define ISH_GPIO_IRQ 13 -#define ISH_HPET_TIMER1_IRQ 14 -#define ISH_IPC_HOST2ISH_IRQ 0 -#define ISH_PMU_WAKEUP_IRQ 10 -#define ISH_D3_RISE_IRQ 9 -#define ISH_D3_FALL_IRQ 9 -#define ISH_BME_RISE_IRQ 9 -#define ISH_BME_FALL_IRQ 9 -#define ISH_IPC_ISH2HOST_CLR_IRQ 0 -#define ISH_UART0_IRQ 23 -#define ISH_UART1_IRQ 24 -#define ISH_RESET_PREP_IRQ 6 +#define ISH_I2C0_IRQ 15 +#define ISH_I2C1_IRQ 16 +#define ISH_FABRIC_IRQ 12 +#define ISH_I2C2_IRQ 17 +#define ISH_WDT_IRQ 26 +#define ISH_GPIO_IRQ 13 +#define ISH_HPET_TIMER1_IRQ 14 +#define ISH_IPC_HOST2ISH_IRQ 0 +#define ISH_PMU_WAKEUP_IRQ 10 +#define ISH_D3_RISE_IRQ 9 +#define ISH_D3_FALL_IRQ 9 +#define ISH_BME_RISE_IRQ 9 +#define ISH_BME_FALL_IRQ 9 +#define ISH_IPC_ISH2HOST_CLR_IRQ 0 +#define ISH_UART0_IRQ 23 +#define ISH_UART1_IRQ 24 +#define ISH_RESET_PREP_IRQ 6 #else -#define ISH_I2C0_IRQ 0 -#define ISH_I2C1_IRQ 1 -#define ISH_FABRIC_IRQ 5 -#define ISH_I2C2_IRQ 40 -#define ISH_WDT_IRQ 6 -#define ISH_GPIO_IRQ 7 -#define ISH_HPET_TIMER1_IRQ 8 -#define ISH_IPC_HOST2ISH_IRQ 12 -#define ISH_PMU_WAKEUP_IRQ 18 -#define ISH_D3_RISE_IRQ 19 -#define ISH_D3_FALL_IRQ 29 -#define ISH_BME_RISE_IRQ 50 -#define ISH_BME_FALL_IRQ 51 -#define ISH_IPC_ISH2HOST_CLR_IRQ 24 -#define ISH_UART0_IRQ 34 -#define ISH_UART1_IRQ 35 -#define ISH_RESET_PREP_IRQ 62 +#define ISH_I2C0_IRQ 0 +#define ISH_I2C1_IRQ 1 +#define ISH_FABRIC_IRQ 5 +#define ISH_I2C2_IRQ 40 +#define ISH_WDT_IRQ 6 +#define ISH_GPIO_IRQ 7 +#define ISH_HPET_TIMER1_IRQ 8 +#define ISH_IPC_HOST2ISH_IRQ 12 +#define ISH_PMU_WAKEUP_IRQ 18 +#define ISH_D3_RISE_IRQ 19 +#define ISH_D3_FALL_IRQ 29 +#define ISH_BME_RISE_IRQ 50 +#define ISH_BME_FALL_IRQ 51 +#define ISH_IPC_ISH2HOST_CLR_IRQ 24 +#define ISH_UART0_IRQ 34 +#define ISH_UART1_IRQ 35 +#define ISH_RESET_PREP_IRQ 62 #endif /* Interrupt vectors 0-31 are architecture reserved. * Vectors 32-255 are user-defined. */ -#define USER_VEC_START 32 +#define USER_VEC_START 32 /* Map IRQs to vectors after offset 10 for certain APIC interrupts */ -#define IRQ_TO_VEC(irq) ((irq) + USER_VEC_START + 10) -#define VEC_TO_IRQ(vec) ((vec) - USER_VEC_START - 10) +#define IRQ_TO_VEC(irq) ((irq) + USER_VEC_START + 10) +#define VEC_TO_IRQ(vec) ((vec)-USER_VEC_START - 10) /* ISH GPIO Registers */ #define ISH_GPIO_GCCR REG32(ISH_GPIO_BASE + 0x000) /* Direction lock */ @@ -128,320 +129,400 @@ enum ish_i2c_port { #define ISH_GPIO_GWSR REG32(ISH_GPIO_BASE + 0x118) /* Wake Source */ #define ISH_GPIO_GSEC REG32(ISH_GPIO_BASE + 0x130) /* Secure Input */ +#if defined(CHIP_VARIANT_ISH5P4) +/* Side Band End Point registers */ +#define SBEP_REG_CLK_GATE_ENABLE REG32(ISH_SBEP_BASE + 0x006C) +#define SB_CLK_GATE_EN_LOCAL_CLK_GATE BIT(0) +#define SB_CLK_GATE_EN_TRUNK_CLK_GATE BIT(1) +#endif + +#define SBEP_REG_UP_MSG_STATUS_ADDR (ISH_SBEP_BASE + 0x0040) +#define SBEP_REG_UP_MSG_STATUS REG32(ISH_SBEP_BASE + 0x0040) +#define SBEP_REG_UP_MSG_COMMAND REG32(ISH_SBEP_BASE + 0x0044) +#define SBEP_REG_UP_MSG_REQ_ADDR_LOW REG32(ISH_SBEP_BASE + 0x0048) +#define SBEP_REG_UP_MSG_REQ_ADDR_HIGH REG32(ISH_SBEP_BASE + 0x004C) +#define SBEP_REG_UP_MSG_REQ_DATA REG32(ISH_SBEP_BASE + 0x0050) +#define SBEP_REG_UP_MSG_REQ_ATTR REG32(ISH_SBEP_BASE + 0x0054) +#define SBEP_REG_UP_MSG_REQ_EH REG32(ISH_SBEP_BASE + 0x0058) + +#define UP_STATUS_BUSY_MASK 0x01 +#define UP_STATUS_MSG_SENT_MASK 0x02 +#define UP_STATUS_MSG_SENT_CLR 0x02 + +#define SBEP_CMD_ACTION 0x1 +#define SBEP_CMD_TYPE_WRITE 0x0 +#define SBEP_CMD_TYPE_READ 0x1 +#define SBEP_CMD_POSTED 0x1 +#define SBEP_CMD_NON_POSTED 0x0 +#define SBEP_CMD_INT_ENABLED 0x1 +#define SBEP_CMD_ACTION_OFF 0 +#define SBEP_CMD_TYPE_OFF 1 +#define SBEP_CMD_POSTED_OFF 2 +#define SBEP_CMD_INT_OFF 3 + +#define SBEP_CMD_WRITE \ + ((SBEP_CMD_ACTION << SBEP_CMD_ACTION_OFF) | \ + (SBEP_CMD_TYPE_WRITE << SBEP_CMD_TYPE_OFF) | \ + (SBEP_CMD_POSTED << SBEP_CMD_POSTED_OFF) | \ + (SBEP_CMD_INT_ENABLED << SBEP_CMD_INT_OFF)) + +#define SBEP_ATTR_LTR_OPCODE 0x43 +#define SBEP_ATTR_PMC_DEST_ID 0xCC +#define SBEP_ATTR_DEST_ID_OFF 0 +#define SBEP_ATTR_OPCODE_OFF 8 +#define SBEP_ATTR_WRITE_ALL_BYTES 0xF +#define SBEP_ATTR_BYTE_ENABLE_OFF 16 +#define LTR_CMD_ATTR \ + ((SBEP_ATTR_PMC_DEST_ID << SBEP_ATTR_DEST_ID_OFF) | \ + (SBEP_ATTR_LTR_OPCODE << SBEP_ATTR_OPCODE_OFF) | \ + (SBEP_ATTR_WRITE_ALL_BYTES << SBEP_ATTR_BYTE_ENABLE_OFF)) +#define LTR_CMD_DATA_2MS 0x90029002 +#define LTR_CMD_DATA_INFINITE 0 + +#define SBEP_SAIRS_ROOT_SPACE_PMC 0 + +#define SBEP_SAIRS_EH_PRESENT 1 +#define SBEP_SAIRS_ROOT_SPACE_OFF 16 +#define SBEP_SAIRS_EH_PRESENT_OFF 31 + +#define SBEP_PMC_SAIRS_VAL \ + ((SBEP_SAIRS_ROOT_SPACE_PMC << SBEP_SAIRS_ROOT_SPACE_OFF) | \ + (SBEP_SAIRS_EH_PRESENT << SBEP_SAIRS_EH_PRESENT_OFF)) + /* APIC interrupt vectors */ -#define ISH_TS_VECTOR 0x20 /* Task switch vector */ -#define LAPIC_LVT_ERROR_VECTOR 0x21 /* Clears IOAPIC/LAPIC sync errors */ -#define SOFTIRQ_VECTOR 0x22 /* Handles software generated IRQs */ -#define LAPIC_SPURIOUS_INT_VECTOR 0xff +#define ISH_TS_VECTOR 0x20 /* Task switch vector */ +#define LAPIC_LVT_ERROR_VECTOR 0x21 /* Clears IOAPIC/LAPIC sync errors */ +#define SOFTIRQ_VECTOR 0x22 /* Handles software generated IRQs */ +#define LAPIC_SPURIOUS_INT_VECTOR 0xff /* Interrupt to vector mapping. To be programmed into IOAPIC */ -#define ISH_I2C0_VEC IRQ_TO_VEC(ISH_I2C0_IRQ) -#define ISH_I2C1_VEC IRQ_TO_VEC(ISH_I2C1_IRQ) -#define ISH_I2C2_VEC IRQ_TO_VEC(ISH_I2C2_IRQ) -#define ISH_WDT_VEC IRQ_TO_VEC(ISH_WDT_IRQ) -#define ISH_GPIO_VEC IRQ_TO_VEC(ISH_GPIO_IRQ) -#define ISH_HPET_TIMER1_VEC IRQ_TO_VEC(ISH_HPET_TIMER1_IRQ) -#define ISH_IPC_ISH2HOST_CLR_VEC IRQ_TO_VEC(ISH_IPC_ISH2HOST_CLR_IRQ) -#define ISH_UART0_VEC IRQ_TO_VEC(ISH_UART0_IRQ) -#define ISH_UART1_VEC IRQ_TO_VEC(ISH_UART1_IRQ) -#define ISH_IPC_VEC IRQ_TO_VEC(ISH_IPC_HOST2ISH_IRQ) -#define ISH_RESET_PREP_VEC IRQ_TO_VEC(ISH_RESET_PREP_IRQ) -#define ISH_PMU_WAKEUP_VEC IRQ_TO_VEC(ISH_PMU_WAKEUP_IRQ) -#define ISH_D3_RISE_VEC IRQ_TO_VEC(ISH_D3_RISE_IRQ) -#define ISH_D3_FALL_VEC IRQ_TO_VEC(ISH_D3_FALL_IRQ) -#define ISH_BME_RISE_VEC IRQ_TO_VEC(ISH_BME_RISE_IRQ) -#define ISH_BME_FALL_VEC IRQ_TO_VEC(ISH_BME_FALL_IRQ) -#define ISH_FABRIC_VEC IRQ_TO_VEC(ISH_FABRIC_IRQ) - -#define ISH_DEBUG_UART UART_PORT_0 -#define ISH_DEBUG_UART_IRQ ISH_UART0_IRQ -#define ISH_DEBUG_UART_VEC ISH_UART0_VEC +#define ISH_I2C0_VEC IRQ_TO_VEC(ISH_I2C0_IRQ) +#define ISH_I2C1_VEC IRQ_TO_VEC(ISH_I2C1_IRQ) +#define ISH_I2C2_VEC IRQ_TO_VEC(ISH_I2C2_IRQ) +#define ISH_WDT_VEC IRQ_TO_VEC(ISH_WDT_IRQ) +#define ISH_GPIO_VEC IRQ_TO_VEC(ISH_GPIO_IRQ) +#define ISH_HPET_TIMER1_VEC IRQ_TO_VEC(ISH_HPET_TIMER1_IRQ) +#define ISH_IPC_ISH2HOST_CLR_VEC IRQ_TO_VEC(ISH_IPC_ISH2HOST_CLR_IRQ) +#define ISH_UART0_VEC IRQ_TO_VEC(ISH_UART0_IRQ) +#define ISH_UART1_VEC IRQ_TO_VEC(ISH_UART1_IRQ) +#define ISH_IPC_VEC IRQ_TO_VEC(ISH_IPC_HOST2ISH_IRQ) +#define ISH_RESET_PREP_VEC IRQ_TO_VEC(ISH_RESET_PREP_IRQ) +#define ISH_PMU_WAKEUP_VEC IRQ_TO_VEC(ISH_PMU_WAKEUP_IRQ) +#define ISH_D3_RISE_VEC IRQ_TO_VEC(ISH_D3_RISE_IRQ) +#define ISH_D3_FALL_VEC IRQ_TO_VEC(ISH_D3_FALL_IRQ) +#define ISH_BME_RISE_VEC IRQ_TO_VEC(ISH_BME_RISE_IRQ) +#define ISH_BME_FALL_VEC IRQ_TO_VEC(ISH_BME_FALL_IRQ) +#define ISH_FABRIC_VEC IRQ_TO_VEC(ISH_FABRIC_IRQ) + +#define ISH_DEBUG_UART UART_PORT_0 +#define ISH_DEBUG_UART_IRQ ISH_UART0_IRQ +#define ISH_DEBUG_UART_VEC ISH_UART0_VEC /* IPC_Registers */ -#define IPC_PISR REG32(ISH_IPC_BASE + 0x0) -#define IPC_PISR_HOST2ISH_BIT BIT(0) - -#define IPC_PIMR REG32(ISH_IPC_BASE + 0x4) -#define IPC_PIMR_HOST2ISH_BIT BIT(0) -#define IPC_PIMR_ISH2HOST_CLR_BIT BIT(11) -#define IPC_PIMR_CSME_CSR_BIT BIT(23) -#define IPC_ISH2HOST_MSG_BASE REG8_ADDR(ISH_IPC_BASE + 0x60) -#define IPC_ISH_FWSTS REG32(ISH_IPC_BASE + 0x34) -#define IPC_HOST2ISH_DOORBELL_ADDR REG32_ADDR(ISH_IPC_BASE + 0x48) -#define IPC_HOST2ISH_MSG_BASE REG8_ADDR(ISH_IPC_BASE + 0xE0) -#define IPC_ISH2HOST_DOORBELL_ADDR REG32_ADDR(ISH_IPC_BASE + 0x54) -#define IPC_ISH2PMC_DOORBELL REG32(ISH_IPC_BASE + 0x58) -#define IPC_ISH2PMC_MSG_BASE (ISH_IPC_BASE + 0x260) -#define IPC_ISH_RMP0 REG32(ISH_IPC_BASE + 0x360) -#define IPC_ISH_RMP1 REG32(ISH_IPC_BASE + 0x364) -#define IPC_ISH_RMP2 REG32(ISH_IPC_BASE + 0x368) -#define DMA_ENABLED_MASK BIT(0) -#define IPC_BUSY_CLEAR REG32(ISH_IPC_BASE + 0x378) -#define IPC_DB_CLR_STS_ISH2HOST_BIT BIT(0) - -#define IPC_UMA_RANGE_LOWER_0 REG32(ISH_IPC_BASE + 0x380) -#define IPC_UMA_RANGE_LOWER_1 REG32(ISH_IPC_BASE + 0x384) -#define IPC_UMA_RANGE_UPPER_0 REG32(ISH_IPC_BASE + 0x388) -#define IPC_UMA_RANGE_UPPER_1 REG32(ISH_IPC_BASE + 0x38C) +#define IPC_PISR REG32(ISH_IPC_BASE + 0x0) +#define IPC_PISR_HOST2ISH_BIT BIT(0) + +#define IPC_PIMR REG32(ISH_IPC_BASE + 0x4) +#define IPC_PIMR_HOST2ISH_BIT BIT(0) +#define IPC_PIMR_ISH2HOST_CLR_BIT BIT(11) +#define IPC_PIMR_CSME_CSR_BIT BIT(23) +#define IPC_ISH2HOST_MSG_BASE REG8_ADDR(ISH_IPC_BASE + 0x60) +#define IPC_ISH_FWSTS REG32(ISH_IPC_BASE + 0x34) +#define IPC_HOST2ISH_DOORBELL_ADDR REG32_ADDR(ISH_IPC_BASE + 0x48) +#define IPC_HOST2ISH_MSG_BASE REG8_ADDR(ISH_IPC_BASE + 0xE0) +#define IPC_ISH2HOST_DOORBELL_ADDR REG32_ADDR(ISH_IPC_BASE + 0x54) +#define IPC_ISH2PMC_DOORBELL REG32(ISH_IPC_BASE + 0x58) +#define IPC_ISH2PMC_MSG_BASE (ISH_IPC_BASE + 0x260) +#define IPC_ISH_RMP0 REG32(ISH_IPC_BASE + 0x360) +#define IPC_ISH_RMP1 REG32(ISH_IPC_BASE + 0x364) +#define IPC_ISH_RMP2 REG32(ISH_IPC_BASE + 0x368) +#define DMA_ENABLED_MASK BIT(0) +#define IPC_BUSY_CLEAR REG32(ISH_IPC_BASE + 0x378) +#define IPC_DB_CLR_STS_ISH2HOST_BIT BIT(0) + +#define IPC_UMA_RANGE_LOWER_0 REG32(ISH_IPC_BASE + 0x380) +#define IPC_UMA_RANGE_LOWER_1 REG32(ISH_IPC_BASE + 0x384) +#define IPC_UMA_RANGE_UPPER_0 REG32(ISH_IPC_BASE + 0x388) +#define IPC_UMA_RANGE_UPPER_1 REG32(ISH_IPC_BASE + 0x38C) /* PMU Registers */ -#define PMU_SRAM_PG_EN REG32(ISH_PMU_BASE + 0x0) +#define PMU_SRAM_PG_EN REG32(ISH_PMU_BASE + 0x0) #ifndef CHIP_VARIANT_ISH5P4 -#define PMU_D3_STATUS REG32(ISH_PMU_BASE + 0x4) -#define PMU_D3_BIT_SET BIT(0) -#define PMU_D3_BIT_RISING_EDGE_STATUS BIT(1) -#define PMU_D3_BIT_FALLING_EDGE_STATUS BIT(2) -#define PMU_D3_BIT_RISING_EDGE_MASK BIT(3) -#define PMU_D3_BIT_FALLING_EDGE_MASK BIT(4) -#define PMU_BME_BIT_SET BIT(5) -#define PMU_BME_BIT_RISING_EDGE_STATUS BIT(6) +#define PMU_D3_STATUS REG32(ISH_PMU_BASE + 0x4) +#define PMU_D3_BIT_SET BIT(0) +#define PMU_D3_BIT_RISING_EDGE_STATUS BIT(1) +#define PMU_D3_BIT_FALLING_EDGE_STATUS BIT(2) +#define PMU_D3_BIT_RISING_EDGE_MASK BIT(3) +#define PMU_D3_BIT_FALLING_EDGE_MASK BIT(4) +#define PMU_BME_BIT_SET BIT(5) +#define PMU_BME_BIT_RISING_EDGE_STATUS BIT(6) #define PMU_BME_BIT_FALLING_EDGE_STATUS BIT(7) -#define PMU_BME_BIT_RISING_EDGE_MASK BIT(8) -#define PMU_BME_BIT_FALLING_EDGE_MASK BIT(9) +#define PMU_BME_BIT_RISING_EDGE_MASK BIT(8) +#define PMU_BME_BIT_FALLING_EDGE_MASK BIT(9) #else -#define PMU_STATUS_REG_ADDR (ISH_PMU_BASE + 0xF00) -#define PMU_SCRATCHPAD0_REG_ADDR (ISH_PMU_BASE + 0xF04) -#define PMU_SCRATCHPAD1_REG_ADDR (ISH_PMU_BASE + 0xF08) -#define PMU_PG_EN_REG_ADDR (ISH_PMU_BASE + 0xF10) -#define PMU_PMC_HOST_RST_CTL REG32(ISH_PMU_BASE + 0xF20) -#define PMU_SW_PG_REQ REG32(ISH_PMU_BASE + 0xF14) -#define PMU_PMC_PG_WAKE REG32(ISH_PMU_BASE + 0xF18) -#define PMU_INTERNAL_PCE REG32(ISH_PMU_BASE + 0xF30) -#define PMU_D3_STATUS REG32(ISH_PMU_BASE + 0x100) -#define PMU_HOST_RST_B BIT(0) -#define PMU_PCE_SHADOW_MASK 0x1F -#define PMU_PCE_PG_ALLOWED BIT(4) -#define PMU_PCE_CHANGE_MASK BIT(9) -#define PMU_PCE_CHANGE_DETECTED BIT(8) -#define PMU_PCE_PMCRE BIT(0) -#define PMU_SW_PG_REQ_B_VAL BIT(0) -#define PMU_SW_PG_REQ_B_RISE BIT(1) -#define PMU_SW_PG_REQ_B_FALL BIT(2) -#define PMU_PMC_PG_WAKE_VAL BIT(0) -#define PMU_PMC_PG_WAKE_RISE BIT(1) -#define PMU_PMC_PG_WAKE_FALL BIT(2) -#define PMU_PCE_PG_ALLOWED BIT(4) -#define PMU_D0I3_ENABLE_MASK BIT(23) -#define PMU_D3_BIT_SET BIT(16) -#define PMU_D3_BIT_RISING_EDGE_STATUS BIT(17) -#define PMU_D3_BIT_FALLING_EDGE_STATUS BIT(18) -#define PMU_D3_BIT_RISING_EDGE_MASK BIT(19) -#define PMU_D3_BIT_FALLING_EDGE_MASK BIT(20) -#define PMU_BME_BIT_SET BIT(24) -#define PMU_BME_BIT_RISING_EDGE_STATUS BIT(25) -#define PMU_BME_BIT_FALLING_EDGE_STATUS BIT(26) -#define PMU_BME_BIT_RISING_EDGE_MASK BIT(27) -#define PMU_BME_BIT_FALLING_EDGE_MASK BIT(28) +#define PMU_STATUS_REG_ADDR (ISH_PMU_BASE + 0xF00) +#define PMU_SCRATCHPAD0_REG_ADDR (ISH_PMU_BASE + 0xF04) +#define PMU_SCRATCHPAD1_REG_ADDR (ISH_PMU_BASE + 0xF08) +#define PMU_PG_EN_REG_ADDR (ISH_PMU_BASE + 0xF10) +#define PMU_PMC_HOST_RST_CTL REG32(ISH_PMU_BASE + 0xF20) +#define PMU_SW_PG_REQ REG32(ISH_PMU_BASE + 0xF14) +#define PMU_PMC_PG_WAKE REG32(ISH_PMU_BASE + 0xF18) +#define PMU_INTERNAL_PCE REG32(ISH_PMU_BASE + 0xF30) +#define PMU_D3_STATUS REG32(ISH_PMU_BASE + 0x100) +#define PMU_D3_STATUS_1 REG32(ISH_PMU_BASE + 0x104) +#define PMU_HOST_RST_B BIT(0) +#define PMU_PCE_SHADOW_MASK 0x1F +#define PMU_PCE_PG_ALLOWED BIT(4) +#define PMU_PCE_CHANGE_MASK BIT(9) +#define PMU_PCE_CHANGE_DETECTED BIT(8) +#define PMU_PCE_PMCRE BIT(0) +#define PMU_SW_PG_REQ_B_VAL BIT(0) +#define PMU_SW_PG_REQ_B_RISE BIT(1) +#define PMU_SW_PG_REQ_B_FALL BIT(2) +#define PMU_PMC_PG_WAKE_VAL BIT(0) +#define PMU_PMC_PG_WAKE_RISE BIT(1) +#define PMU_PMC_PG_WAKE_FALL BIT(2) +#define PMU_PCE_PG_ALLOWED BIT(4) +#define PMU_D0I3_ENABLE_MASK BIT(23) +#define PMU_D3_BIT_SET BIT(16) +#define PMU_D3_BIT_RISING_EDGE_STATUS BIT(17) +#define PMU_D3_BIT_FALLING_EDGE_STATUS BIT(18) +#define PMU_D3_BIT_RISING_EDGE_MASK BIT(19) +#define PMU_D3_BIT_FALLING_EDGE_MASK BIT(20) +#define PMU_BME_BIT_SET BIT(24) +#define PMU_BME_BIT_RISING_EDGE_STATUS BIT(25) +#define PMU_BME_BIT_FALLING_EDGE_STATUS BIT(26) +#define PMU_BME_BIT_RISING_EDGE_MASK BIT(27) +#define PMU_BME_BIT_FALLING_EDGE_MASK BIT(28) +#define PMU_REG_MASK_D3_RISE REG32(ISH_PMU_BASE + 0x200) +#define PMU_REG_MASK_D3_FALL REG32(ISH_PMU_BASE + 0x208) +#define PMU_REG_MASK_BME_RISE REG32(ISH_PMU_BASE + 0x220) +#define PMU_REG_MASK_BME_FALL REG32(ISH_PMU_BASE + 0x228) #endif -#define PMU_ISH_FABRIC_CNT REG32(ISH_PMU_BASE + 0x18) +#define PMU_GPIO_WAKE_MASK0 REG32(ISH_PMU_BASE + 0x250) +#define PMU_GPIO_WAKE_MASK1 REG32(ISH_PMU_BASE + 0x254) + +#define PMU_ISH_FABRIC_CNT REG32(ISH_PMU_BASE + 0x18) -#define PMU_PGCB_CLKGATE_CTRL REG32(ISH_PMU_BASE + 0x54) +#define PMU_PGCB_CLKGATE_CTRL REG32(ISH_PMU_BASE + 0x54) -#define PMU_VNN_REQ REG32(ISH_PMU_BASE + 0x3c) -#define VNN_REQ_IPC_HOST_WRITE BIT(3) /* Power for IPC host write */ +#define PMU_VNN_REQ REG32(ISH_PMU_BASE + 0x3c) +#define VNN_REQ_IPC_HOST_WRITE BIT(3) /* Power for IPC host write */ -#define PMU_VNN_REQ_ACK REG32(ISH_PMU_BASE + 0x40) -#define PMU_VNN_REQ_ACK_STATUS BIT(0) /* VNN req and ack status */ +#define PMU_VNN_REQ_ACK REG32(ISH_PMU_BASE + 0x40) +#define PMU_VNN_REQ_ACK_STATUS BIT(0) /* VNN req and ack status */ -#define PMU_VNNAON_RED REG32(ISH_PMU_BASE + 0x58) +#define PMU_VNNAON_RED REG32(ISH_PMU_BASE + 0x58) -#define PMU_RST_PREP REG32(ISH_PMU_BASE + 0x5c) -#define PMU_RST_PREP_GET BIT(0) -#define PMU_RST_PREP_AVAIL BIT(1) -#define PMU_RST_PREP_INT_MASK BIT(31) +#define PMU_RST_PREP REG32(ISH_PMU_BASE + 0x5c) +#define PMU_RST_PREP_GET BIT(0) +#define PMU_RST_PREP_AVAIL BIT(1) +#define PMU_RST_PREP_INT_MASK BIT(31) -#define VNN_ID_DMA0 4 -#define VNN_ID_DMA(chan) (VNN_ID_DMA0 + chan) +#define VNN_ID_DMA0 4 +#define VNN_ID_DMA(chan) (VNN_ID_DMA0 + chan) +#define VNN_ID_SIDEBAND 21 /* OCP registers */ -#define OCP_IOSF2OCP_BRIDGE (ISH_OCP_BASE + 0x9400) -#define OCP_AGENT_CONTROL REG32(OCP_IOSF2OCP_BRIDGE + 0x20) -#define OCP_RESPONSE_TO_DISABLE 0xFFFFF8FF +#define OCP_IOSF2OCP_BRIDGE (ISH_OCP_BASE + 0x9400) +#define OCP_AGENT_CONTROL REG32(OCP_IOSF2OCP_BRIDGE + 0x20) +#define OCP_RESPONSE_TO_DISABLE 0xFFFFF8FF /* MISC registers */ -#define MISC_REG_BASE ISH_MISC_BASE -#define DMA_REG_BASE ISH_DMA_BASE +#define MISC_REG_BASE ISH_MISC_BASE +#define DMA_REG_BASE ISH_DMA_BASE #ifndef CHIP_VARIANT_ISH5P4 -#define MISC_CHID_CFG_REG REG32(MISC_REG_BASE + 0x40) -#define MISC_DMA_CTL_REG(ch) REG32(MISC_REG_BASE + (4 * (ch))) -#define MISC_SRC_FILLIN_DMA(ch) REG32(MISC_REG_BASE + 0x20 + (4 * (ch))) -#define MISC_DST_FILLIN_DMA(ch) REG32(MISC_REG_BASE + 0x80 + (4 * (ch))) -#define MISC_ISH_ECC_ERR_SRESP REG32(MISC_REG_BASE + 0x94) +#define MISC_CHID_CFG_REG REG32(MISC_REG_BASE + 0x40) +#define MISC_DMA_CTL_REG(ch) REG32(MISC_REG_BASE + (4 * (ch))) +#define MISC_SRC_FILLIN_DMA(ch) REG32(MISC_REG_BASE + 0x20 + (4 * (ch))) +#define MISC_DST_FILLIN_DMA(ch) REG32(MISC_REG_BASE + 0x80 + (4 * (ch))) +#define MISC_ISH_ECC_ERR_SRESP REG32(MISC_REG_BASE + 0x94) #else -#define DMA_MISC_OFFSET 0x1000 -#define DMA_MISC_BASE (DMA_REG_BASE + DMA_MISC_OFFSET) -#define MISC_CHID_CFG_REG REG32(DMA_MISC_BASE + 0x400) -#define MISC_DMA_CTL_REG(ch) REG32(DMA_MISC_BASE + (4 * (ch))) -#define MISC_SRC_FILLIN_DMA(ch) REG32(DMA_MISC_BASE + 0x100 + (4 * (ch))) -#define MISC_DST_FILLIN_DMA(ch) REG32(DMA_MISC_BASE + 0x200 + (4 * (ch))) -#define MISC_ISH_ECC_ERR_SRESP REG32(DMA_MISC_BASE + 0x404) +#define DMA_MISC_OFFSET 0x1000 +#define DMA_MISC_BASE (DMA_REG_BASE + DMA_MISC_OFFSET) +#define MISC_CHID_CFG_REG REG32(DMA_MISC_BASE + 0x400) +#define MISC_DMA_CTL_REG(ch) REG32(DMA_MISC_BASE + (4 * (ch))) +#define MISC_SRC_FILLIN_DMA(ch) REG32(DMA_MISC_BASE + 0x100 + (4 * (ch))) +#define MISC_DST_FILLIN_DMA(ch) REG32(DMA_MISC_BASE + 0x200 + (4 * (ch))) +#define MISC_ISH_ECC_ERR_SRESP REG32(DMA_MISC_BASE + 0x404) #endif -#define MISC_ISH_RTC_COUNTER0 REG32(ISH_MISC_BASE + 0x70) -#define MISC_ISH_RTC_COUNTER1 REG32(ISH_MISC_BASE + 0x74) +#define MISC_ISH_RTC_COUNTER0 REG32(ISH_MISC_BASE + 0x70) +#define MISC_ISH_RTC_COUNTER1 REG32(ISH_MISC_BASE + 0x74) /* DMA registers */ -#define DMA_CH_REGS_SIZE 0x58 -#define DMA_CLR_BLOCK_REG REG32(DMA_REG_BASE + 0x340) -#define DMA_CLR_ERR_REG REG32(DMA_REG_BASE + 0x358) -#define DMA_EN_REG_ADDR (DMA_REG_BASE + 0x3A0) -#define DMA_EN_REG REG32(DMA_EN_REG_ADDR) -#define DMA_CFG_REG REG32(DMA_REG_BASE + 0x398) -#define DMA_PSIZE_01 REG32(DMA_REG_BASE + 0x400) -#define DMA_PSIZE_CHAN0_SIZE 512 -#define DMA_PSIZE_CHAN0_OFFSET 0 -#define DMA_PSIZE_CHAN1_SIZE 128 -#define DMA_PSIZE_CHAN1_OFFSET 13 -#define DMA_PSIZE_UPDATE BIT(26) -#define DMA_MAX_CHANNEL 4 -#define DMA_SAR(chan) REG32(chan + 0x000) -#define DMA_DAR(chan) REG32(chan + 0x008) -#define DMA_LLP(chan) REG32(chan + 0x010) -#define DMA_CTL_LOW(chan) REG32(chan + 0x018) -#define DMA_CTL_HIGH(chan) REG32(chan + 0x018 + 0x4) -#define DMA_CTL_INT_ENABLE BIT(0) -#define DMA_CTL_DST_TR_WIDTH_SHIFT 1 -#define DMA_CTL_SRC_TR_WIDTH_SHIFT 4 -#define DMA_CTL_DINC_SHIFT 7 -#define DMA_CTL_SINC_SHIFT 9 -#define DMA_CTL_ADDR_INC 0 -#define DMA_CTL_DEST_MSIZE_SHIFT 11 -#define DMA_CTL_SRC_MSIZE_SHIFT 14 -#define DMA_CTL_TT_FC_SHIFT 20 -#define DMA_CTL_TT_FC_M2M_DMAC 0 -#define DMA_ENABLE BIT(0) -#define DMA_CH_EN_BIT(n) BIT(n) -#define DMA_CH_EN_WE_BIT(n) BIT(8 + (n)) -#define DMA_MAX_BLOCK_SIZE (4096) -#define SRC_TR_WIDTH 2 -#define SRC_BURST_SIZE 3 -#define DEST_TR_WIDTH 2 -#define DEST_BURST_SIZE 3 - -#define PMU_MASK_EVENT REG32(ISH_PMU_BASE + 0x10) -#define PMU_MASK_EVENT_BIT_GPIO(pin) BIT(pin) -#define PMU_MASK_EVENT_BIT_HPET BIT(16) -#define PMU_MASK_EVENT_BIT_IPC BIT(17) -#define PMU_MASK_EVENT_BIT_D3 BIT(18) -#define PMU_MASK_EVENT_BIT_DMA BIT(19) -#define PMU_MASK_EVENT_BIT_I2C0 BIT(20) -#define PMU_MASK_EVENT_BIT_I2C1 BIT(21) -#define PMU_MASK_EVENT_BIT_SPI BIT(22) -#define PMU_MASK_EVENT_BIT_UART BIT(23) -#define PMU_MASK_EVENT_BIT_ALL (0xffffffff) - -#define PMU_RF_ROM_PWR_CTRL REG32(ISH_PMU_BASE + 0x30) - -#define PMU_LDO_CTRL REG32(ISH_PMU_BASE + 0x44) -#define PMU_LDO_ENABLE_BIT BIT(0) -#define PMU_LDO_RETENTION_BIT BIT(1) -#define PMU_LDO_CALIBRATION_BIT BIT(2) -#define PMU_LDO_READY_BIT BIT(3) +#define DMA_CH_REGS_SIZE 0x58 +#define DMA_CLR_BLOCK_REG REG32(DMA_REG_BASE + 0x340) +#define DMA_CLR_ERR_REG REG32(DMA_REG_BASE + 0x358) +#define DMA_EN_REG_ADDR (DMA_REG_BASE + 0x3A0) +#define DMA_EN_REG REG32(DMA_EN_REG_ADDR) +#define DMA_CFG_REG REG32(DMA_REG_BASE + 0x398) +#define DMA_PSIZE_01 REG32(DMA_REG_BASE + 0x400) +#define DMA_PSIZE_CHAN0_SIZE 512 +#define DMA_PSIZE_CHAN0_OFFSET 0 +#define DMA_PSIZE_CHAN1_SIZE 128 +#define DMA_PSIZE_CHAN1_OFFSET 13 +#define DMA_PSIZE_UPDATE BIT(26) +#define DMA_MAX_CHANNEL 4 +#define DMA_SAR(chan) REG32(chan + 0x000) +#define DMA_DAR(chan) REG32(chan + 0x008) +#define DMA_LLP(chan) REG32(chan + 0x010) +#define DMA_CTL_LOW(chan) REG32(chan + 0x018) +#define DMA_CTL_HIGH(chan) REG32(chan + 0x018 + 0x4) +#define DMA_CTL_INT_ENABLE BIT(0) +#define DMA_CTL_DST_TR_WIDTH_SHIFT 1 +#define DMA_CTL_SRC_TR_WIDTH_SHIFT 4 +#define DMA_CTL_DINC_SHIFT 7 +#define DMA_CTL_SINC_SHIFT 9 +#define DMA_CTL_ADDR_INC 0 +#define DMA_CTL_DEST_MSIZE_SHIFT 11 +#define DMA_CTL_SRC_MSIZE_SHIFT 14 +#define DMA_CTL_TT_FC_SHIFT 20 +#define DMA_CTL_TT_FC_M2M_DMAC 0 +#define DMA_ENABLE BIT(0) +#define DMA_CH_EN_BIT(n) BIT(n) +#define DMA_CH_EN_WE_BIT(n) BIT(8 + (n)) +#define DMA_MAX_BLOCK_SIZE (4096) +#define SRC_TR_WIDTH 2 +#define SRC_BURST_SIZE 3 +#define DEST_TR_WIDTH 2 +#define DEST_BURST_SIZE 3 + +#define PMU_MASK_EVENT REG32(ISH_PMU_BASE + 0x10) +#define PMU_MASK_EVENT2 REG32(ISH_PMU_BASE + 0x4C) +#define PMU_MASK_EVENT_BIT_GPIO(pin) BIT(pin) +#define PMU_MASK_EVENT_BIT_HPET BIT(16) +#define PMU_MASK_EVENT_BIT_IPC BIT(17) +#define PMU_MASK_EVENT_BIT_D3 BIT(18) +#define PMU_MASK_EVENT_BIT_DMA BIT(19) +#define PMU_MASK_EVENT_BIT_I2C0 BIT(20) +#define PMU_MASK_EVENT_BIT_I2C1 BIT(21) +#define PMU_MASK_EVENT_BIT_SPI BIT(22) +#define PMU_MASK_EVENT_BIT_UART BIT(23) +#define PMU_MASK_EVENT_BIT_ALL (0xffffffff) +#define PMU_MASK_EVENT2_SRAM_ERASE1 BIT(3) +#define PMU_MASK_EVENT2_SRAM_ERASE0 BIT(4) +#define PMU_MASK_EVENT2_ISOL_ACK_RISE BIT(14) +#define PMU_MASK_EVENT2_ISOL_ACK_FALL BIT(15) +#define PMU_MASK_EVENT2_HOST_RST_RISE BIT(16) +#define PMU_MASK_EVENT2_HOST_RST_FALL BIT(17) +#define PMU_MASK2_ALL_EVENTS \ + (PMU_MASK_EVENT2_SRAM_ERASE0 | PMU_MASK_EVENT2_SRAM_ERASE1 | \ + PMU_MASK_EVENT2_ISOL_ACK_RISE | PMU_MASK_EVENT2_ISOL_ACK_FALL | \ + PMU_MASK_EVENT2_HOST_RST_RISE | PMU_MASK_EVENT2_HOST_RST_FALL) + +#define PMU_RF_ROM_PWR_CTRL REG32(ISH_PMU_BASE + 0x30) + +#define PMU_LDO_CTRL REG32(ISH_PMU_BASE + 0x44) +#define PMU_LDO_ENABLE_BIT BIT(0) +#define PMU_LDO_RETENTION_BIT BIT(1) +#define PMU_LDO_CALIBRATION_BIT BIT(2) +#define PMU_LDO_READY_BIT BIT(3) /* CCU Registers */ -#define CCU_TCG_EN REG32(ISH_CCU_BASE + 0x0) -#define CCU_BCG_EN REG32(ISH_CCU_BASE + 0x4) +#define CCU_TCG_EN REG32(ISH_CCU_BASE + 0x0) +#define CCU_BCG_EN REG32(ISH_CCU_BASE + 0x4) #ifndef CHIP_VARIANT_ISH5P4 -#define CCU_WDT_CD REG32(ISH_CCU_BASE + 0x8) -#define CCU_RST_HST REG32(ISH_CCU_BASE + 0x34) /* Reset history */ -#define CCU_TCG_ENABLE REG32(ISH_CCU_BASE + 0x38) -#define CCU_BCG_ENABLE REG32(ISH_CCU_BASE + 0x3c) +#define CCU_WDT_CD REG32(ISH_CCU_BASE + 0x8) +#define CCU_RST_HST REG32(ISH_CCU_BASE + 0x34) /* Reset history */ +#define CCU_TCG_ENABLE REG32(ISH_CCU_BASE + 0x38) +#define CCU_BCG_ENABLE REG32(ISH_CCU_BASE + 0x3c) #else -#define CCU_WDT_CD REG32(ISH_CCU_BASE + 0x7c) -#define CCU_RST_HST REG32(ISH_CCU_BASE + 0x3c) /* Reset history */ -#define CCU_TCG_ENABLE REG32(ISH_CCU_BASE + 0x40) -#define CCU_BCG_ENABLE REG32(ISH_CCU_BASE + 0x44) +#define CCU_WDT_CD REG32(ISH_CCU_BASE + 0x7c) +#define CCU_RST_HST REG32(ISH_CCU_BASE + 0x3c) /* Reset history */ +#define CCU_TCG_ENABLE REG32(ISH_CCU_BASE + 0x40) +#define CCU_BCG_ENABLE REG32(ISH_CCU_BASE + 0x44) #endif -#define CCU_BCG_MIA REG32(ISH_CCU_BASE + 0x4) -#define CCU_BCG_UART REG32(ISH_CCU_BASE + 0x8) -#define CCU_BCG_I2C REG32(ISH_CCU_BASE + 0xc) -#define CCU_BCG_SPI REG32(ISH_CCU_BASE + 0x10) -#define CCU_BCG_GPIO REG32(ISH_CCU_BASE + 0x14) -#define CCU_BCG_DMA REG32(ISH_CCU_BASE + 0x28) -#define CCU_AONCG_EN REG32(ISH_CCU_BASE + 0xdc) -#define CCU_BCG_BIT_MIA BIT(0) -#define CCU_BCG_BIT_DMA BIT(1) -#define CCU_BCG_BIT_I2C0 BIT(2) -#define CCU_BCG_BIT_I2C1 BIT(3) -#define CCU_BCG_BIT_SPI BIT(4) -#define CCU_BCG_BIT_SRAM BIT(5) -#define CCU_BCG_BIT_HPET BIT(6) -#define CCU_BCG_BIT_UART BIT(7) -#define CCU_BCG_BIT_GPIO BIT(8) -#define CCU_BCG_BIT_I2C2 BIT(9) -#define CCU_BCG_BIT_SPI2 BIT(10) -#define CCU_BCG_BIT_ALL (0x7ff) +#define CCU_BCG_MIA REG32(ISH_CCU_BASE + 0x4) +#define CCU_BCG_UART REG32(ISH_CCU_BASE + 0x8) +#define CCU_BCG_I2C REG32(ISH_CCU_BASE + 0xc) +#define CCU_BCG_SPI REG32(ISH_CCU_BASE + 0x10) +#define CCU_BCG_GPIO REG32(ISH_CCU_BASE + 0x14) +#define CCU_BCG_DMA REG32(ISH_CCU_BASE + 0x28) +#define CCU_AONCG_EN REG32(ISH_CCU_BASE + 0xdc) +#define CCU_BCG_BIT_MIA BIT(0) +#define CCU_BCG_BIT_DMA BIT(1) +#define CCU_BCG_BIT_I2C0 BIT(2) +#define CCU_BCG_BIT_I2C1 BIT(3) +#define CCU_BCG_BIT_SPI BIT(4) +#define CCU_BCG_BIT_SRAM BIT(5) +#define CCU_BCG_BIT_HPET BIT(6) +#define CCU_BCG_BIT_UART BIT(7) +#define CCU_BCG_BIT_GPIO BIT(8) +#define CCU_BCG_BIT_I2C2 BIT(9) +#define CCU_BCG_BIT_SPI2 BIT(10) +#define CCU_BCG_BIT_ALL (0x7ff) /* Bitmasks for CCU_RST_HST */ -#define CCU_SW_RST BIT(0) /* Used to indicate SW reset */ -#define CCU_WDT_RST BIT(1) /* Used to indicate WDT reset */ -#define CCU_MIASS_RST BIT(2) /* Used to indicate UIA shutdown reset */ -#define CCU_SRECC_RST BIT(3) /* Used to indicate SRAM ECC reset */ +#define CCU_SW_RST BIT(0) /* Used to indicate SW reset */ +#define CCU_WDT_RST BIT(1) /* Used to indicate WDT reset */ +#define CCU_MIASS_RST BIT(2) /* Used to indicate UIA shutdown reset */ +#define CCU_SRECC_RST BIT(3) /* Used to indicate SRAM ECC reset */ /* Fabric Agent Status register */ -#define FABRIC_AGENT_STATUS REG32(ISH_OCP_BASE + 0x7828) +#define FABRIC_AGENT_STATUS REG32(ISH_OCP_BASE + 0x7828) #define FABRIC_INBAND_ERR_SECONDARY_BIT BIT(29) -#define FABRIC_INBAND_ERR_PRIMARY_BIT BIT(28) -#define FABRIC_M_ERR_BIT BIT(24) -#define FABRIC_MIA_STATUS_BIT_ERR (FABRIC_INBAND_ERR_SECONDARY_BIT | \ - FABRIC_INBAND_ERR_PRIMARY_BIT | \ - FABRIC_M_ERR_BIT) +#define FABRIC_INBAND_ERR_PRIMARY_BIT BIT(28) +#define FABRIC_M_ERR_BIT BIT(24) +#define FABRIC_MIA_STATUS_BIT_ERR \ + (FABRIC_INBAND_ERR_SECONDARY_BIT | FABRIC_INBAND_ERR_PRIMARY_BIT | \ + FABRIC_M_ERR_BIT) /* CSME Registers */ #ifdef CHIP_VARIANT_ISH5P4 -#define SEC_OFFSET 0x10000 +#define SEC_OFFSET 0x10000 #else -#define SEC_OFFSET 0x0 +#define SEC_OFFSET 0x0 #endif -#define ISH_RST_REG REG32(ISH_IPC_BASE + SEC_OFFSET + 0x44) -#define IPC_PIMR_CIM_SEC (ISH_IPC_BASE + SEC_OFFSET + 0x10) +#define ISH_RST_REG REG32(ISH_IPC_BASE + SEC_OFFSET + 0x44) +#define IPC_PIMR_CIM_SEC (ISH_IPC_BASE + SEC_OFFSET + 0x10) /* IOAPIC registers */ -#define IOAPIC_IDX REG32(ISH_IOAPIC_BASE + 0x0) -#define IOAPIC_WDW REG32(ISH_IOAPIC_BASE + 0x10) +#define IOAPIC_IDX REG32(ISH_IOAPIC_BASE + 0x0) +#define IOAPIC_WDW REG32(ISH_IOAPIC_BASE + 0x10) /* Bare address needed for assembler (ISH_IOAPIC_BASE + 0x40) */ -#define IOAPIC_EOI_REG_ADDR 0xFEC00040 -#define IOAPIC_EOI_REG REG32(IOAPIC_EOI_REG_ADDR) - -#define IOAPIC_VERSION (0x1) -#define IOAPIC_IOREDTBL (0x10) -#define IOAPIC_REDTBL_DELMOD_FIXED (0x00000000) -#define IOAPIC_REDTBL_DESTMOD_PHYS (0x00000000) -#define IOAPIC_REDTBL_INTPOL_HIGH (0x00000000) -#define IOAPIC_REDTBL_INTPOL_LOW (0x00002000) -#define IOAPIC_REDTBL_IRR (0x00004000) -#define IOAPIC_REDTBL_TRIGGER_EDGE (0x00000000) -#define IOAPIC_REDTBL_TRIGGER_LEVEL (0x00008000) -#define IOAPIC_REDTBL_MASK (0x00010000) +#define IOAPIC_EOI_REG_ADDR 0xFEC00040 +#define IOAPIC_EOI_REG REG32(IOAPIC_EOI_REG_ADDR) + +#define IOAPIC_VERSION (0x1) +#define IOAPIC_IOREDTBL (0x10) +#define IOAPIC_REDTBL_DELMOD_FIXED (0x00000000) +#define IOAPIC_REDTBL_DESTMOD_PHYS (0x00000000) +#define IOAPIC_REDTBL_INTPOL_HIGH (0x00000000) +#define IOAPIC_REDTBL_INTPOL_LOW (0x00002000) +#define IOAPIC_REDTBL_IRR (0x00004000) +#define IOAPIC_REDTBL_TRIGGER_EDGE (0x00000000) +#define IOAPIC_REDTBL_TRIGGER_LEVEL (0x00008000) +#define IOAPIC_REDTBL_MASK (0x00010000) /* WDT (Watchdog Timer) Registers */ -#define WDT_CONTROL REG32(ISH_WDT_BASE + 0x0) -#define WDT_RELOAD REG32(ISH_WDT_BASE + 0x4) -#define WDT_VALUES REG32(ISH_WDT_BASE + 0x8) -#define WDT_CONTROL_ENABLE_BIT BIT(17) +#define WDT_CONTROL REG32(ISH_WDT_BASE + 0x0) +#define WDT_RELOAD REG32(ISH_WDT_BASE + 0x4) +#define WDT_VALUES REG32(ISH_WDT_BASE + 0x8) +#define WDT_CONTROL_ENABLE_BIT BIT(17) /* LAPIC registers */ /* Bare address needed for assembler (ISH_LAPIC_BASE + 0xB0) */ -#define LAPIC_EOI_REG_ADDR 0xFEE000B0 -#define LAPIC_EOI_REG REG32(LAPIC_EOI_REG_ADDR) -#define LAPIC_ISR_REG REG32(ISH_LAPIC_BASE + 0x100) -#define LAPIC_ISR_LAST_REG REG32(ISH_LAPIC_BASE + 0x170) -#define LAPIC_IRR_REG REG32(ISH_LAPIC_BASE + 0x200) -#define LAPIC_ESR_REG REG32(ISH_LAPIC_BASE + 0x280) -#define LAPIC_ERR_RECV_ILLEGAL BIT(6) -#define LAPIC_ICR_REG REG32(ISH_LAPIC_BASE + 0x300) +#define LAPIC_EOI_REG_ADDR 0xFEE000B0 +#define LAPIC_EOI_REG REG32(LAPIC_EOI_REG_ADDR) +#define LAPIC_ISR_REG REG32(ISH_LAPIC_BASE + 0x100) +#define LAPIC_ISR_LAST_REG REG32(ISH_LAPIC_BASE + 0x170) +#define LAPIC_IRR_REG REG32(ISH_LAPIC_BASE + 0x200) +#define LAPIC_ESR_REG REG32(ISH_LAPIC_BASE + 0x280) +#define LAPIC_ERR_RECV_ILLEGAL BIT(6) +#define LAPIC_ICR_REG REG32(ISH_LAPIC_BASE + 0x300) /* SRAM control registers */ #ifndef CHIP_VARIANT_ISH5P4 -#define ISH_SRAM_CTRL_BASE 0x00500000 +#define ISH_SRAM_CTRL_BASE 0x00500000 #else -#define ISH_SRAM_CTRL_BASE 0x10500000 +#define ISH_SRAM_CTRL_BASE 0x10500000 #endif -#define ISH_SRAM_CTRL_CSFGR REG32(ISH_SRAM_CTRL_BASE + 0x00) -#define ISH_SRAM_CTRL_INTR REG32(ISH_SRAM_CTRL_BASE + 0x04) -#define ISH_SRAM_CTRL_INTR_MASK REG32(ISH_SRAM_CTRL_BASE + 0x08) -#define ISH_SRAM_CTRL_ERASE_CTRL REG32(ISH_SRAM_CTRL_BASE + 0x0c) -#define ISH_SRAM_CTRL_ERASE_ADDR REG32(ISH_SRAM_CTRL_BASE + 0x10) -#define ISH_SRAM_CTRL_BANK_STATUS REG32(ISH_SRAM_CTRL_BASE + 0x2c) +#define ISH_SRAM_CTRL_CSFGR REG32(ISH_SRAM_CTRL_BASE + 0x00) +#define ISH_SRAM_CTRL_INTR REG32(ISH_SRAM_CTRL_BASE + 0x04) +#define ISH_SRAM_CTRL_INTR_MASK REG32(ISH_SRAM_CTRL_BASE + 0x08) +#define ISH_SRAM_CTRL_ERASE_CTRL REG32(ISH_SRAM_CTRL_BASE + 0x0c) +#define ISH_SRAM_CTRL_ERASE_ADDR REG32(ISH_SRAM_CTRL_BASE + 0x10) +#define ISH_SRAM_CTRL_BANK_STATUS REG32(ISH_SRAM_CTRL_BASE + 0x2c) #endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/ish/system.c b/chip/ish/system.c index 1e6fe87800..22af124cd9 100644 --- a/chip/ish/system.c +++ b/chip/ish/system.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -23,8 +23,8 @@ #include "util.h" #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) int system_is_reboot_warm(void) { @@ -57,8 +57,7 @@ uint32_t chip_read_reset_flags(void) * Used when the watchdog timer exceeds max retries and we want to * disable ISH completely. */ -noreturn -static void system_halt(void) +noreturn static void system_halt(void) { cflush(); @@ -66,9 +65,8 @@ static void system_halt(void) disable_all_interrupts(); WDT_CONTROL = 0; CCU_TCG_EN = 1; - __asm__ volatile ( - "cli\n" - "hlt\n"); + __asm__ volatile("cli\n" + "hlt\n"); } } @@ -90,8 +88,8 @@ void system_reset(int flags) if (flags & SYSTEM_RESET_AP_WATCHDOG) { save_flags |= EC_RESET_FLAG_WATCHDOG; ish_persistent_data.watchdog_counter += 1; - if (ish_persistent_data.watchdog_counter - >= CONFIG_WATCHDOG_MAX_RETRIES) { + if (ish_persistent_data.watchdog_counter >= + CONFIG_WATCHDOG_MAX_RETRIES) { CPRINTS("Halting ISH due to max watchdog resets"); system_halt(); } @@ -147,9 +145,9 @@ int system_set_scratchpad(uint32_t value) return EC_SUCCESS; } -uint32_t system_get_scratchpad(void) +int system_get_scratchpad(uint32_t *unused) { - return 0; + return EC_ERROR_UNIMPLEMENTED; } void system_hibernate(uint32_t seconds, uint32_t microseconds) @@ -175,19 +173,13 @@ void system_set_image_copy(enum ec_image copy) { } -#define HBW_FABRIC_BASE 0x10000000 -#define PER0_FABRIC_BASE 0x04000000 -#define AGENT_STS 0x28 -#define ERROR_LOG 0x58 +#define HBW_FABRIC_BASE 0x10000000 +#define PER0_FABRIC_BASE 0x04000000 +#define AGENT_STS 0x28 +#define ERROR_LOG 0x58 -static uint16_t hbw_ia_offset[] = { - 0x1000, - 0x3400, - 0x3800, - 0x5000, - 0x5800, - 0x6000 -}; +static uint16_t hbw_ia_offset[] = { 0x1000, 0x3400, 0x3800, + 0x5000, 0x5800, 0x6000 }; static inline void clear_register(uint32_t reg) { diff --git a/chip/ish/system_state.h b/chip/ish/system_state.h index 20de1aaf4b..bcffcf49ee 100644 --- a/chip/ish/system_state.h +++ b/chip/ish/system_state.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,7 @@ #ifndef __SYSTEM_STATE_H #define __SYSTEM_STATE_H -#define HECI_FIXED_SYSTEM_STATE_ADDR 13 +#define HECI_FIXED_SYSTEM_STATE_ADDR 13 struct ss_subsys_device; diff --git a/chip/ish/system_state_subsys.c b/chip/ish/system_state_subsys.c index 36b79c747a..76053dcded 100644 --- a/chip/ish/system_state_subsys.c +++ b/chip/ish/system_state_subsys.c @@ -1,33 +1,32 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "console.h" #include "heci_client.h" #include "registers.h" #include "system_state.h" -#include "console.h" #ifdef SS_SUBSYSTEM_DEBUG #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_LPC, format, ##args) #else #define CPUTS(outstr) #define CPRINTS(format, args...) #define CPRINTF(format, args...) #endif - /* the following "define"s and structures are from host driver * and they are slightly modified for look&feel purpose. */ -#define SYSTEM_STATE_SUBSCRIBE 0x1 -#define SYSTEM_STATE_STATUS 0x2 -#define SYSTEM_STATE_QUERY_SUBSCRIBERS 0x3 -#define SYSTEM_STATE_STATE_CHANGE_REQ 0x4 +#define SYSTEM_STATE_SUBSCRIBE 0x1 +#define SYSTEM_STATE_STATUS 0x2 +#define SYSTEM_STATE_QUERY_SUBSCRIBERS 0x3 +#define SYSTEM_STATE_STATE_CHANGE_REQ 0x4 -#define SUSPEND_STATE_BIT BIT(1) /* suspend/resume */ +#define SUSPEND_STATE_BIT BIT(1) /* suspend/resume */ /* Cached state of ISH's requested power rails when AP suspends */ static uint32_t cached_vnn_request; @@ -67,7 +66,7 @@ struct ss_state_change_req { * "struct ss_subsys_device" in it and calls ss_subsys_register_client() like * HECI client. */ -#define MAX_SS_CLIENTS HECI_MAX_NUM_OF_CLIENTS +#define MAX_SS_CLIENTS HECI_MAX_NUM_OF_CLIENTS struct ss_subsystem_context { uint32_t registered_state; @@ -103,7 +102,7 @@ static int ss_subsys_suspend(void) for (i = ss_subsys_ctx.num_of_ss_client - 1; i >= 0; i--) { if (ss_subsys_ctx.clients[i]->cbs->suspend) ss_subsys_ctx.clients[i]->cbs->suspend( - ss_subsys_ctx.clients[i]); + ss_subsys_ctx.clients[i]); } /* @@ -126,8 +125,7 @@ static int ss_subsys_resume(void) /* * Restore VNN power request from before suspend. */ - if (IS_ENABLED(CHIP_FAMILY_ISH5) && - cached_vnn_request) { + if (IS_ENABLED(CHIP_FAMILY_ISH5) && cached_vnn_request) { /* Request all cached power rails that are not already on. */ PMU_VNN_REQ = cached_vnn_request & ~PMU_VNN_REQ; /* Wait for power request to get acknowledged */ @@ -138,7 +136,7 @@ static int ss_subsys_resume(void) for (i = 0; i < ss_subsys_ctx.num_of_ss_client; i++) { if (ss_subsys_ctx.clients[i]->cbs->resume) ss_subsys_ctx.clients[i]->cbs->resume( - ss_subsys_ctx.clients[i]); + ss_subsys_ctx.clients[i]); } return EC_SUCCESS; diff --git a/chip/ish/uart.c b/chip/ish/uart.c index b0f21cdf5f..0ff03da89a 100644 --- a/chip/ish/uart.c +++ b/chip/ish/uart.c @@ -1,36 +1,29 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* UART module for ISH */ +#include "atomic.h" #include "common.h" -#include "math_util.h" #include "console.h" -#include "uart_defs.h" -#include "atomic.h" -#include "task.h" +#include "interrupts.h" +#include "math_util.h" #include "registers.h" +#include "system.h" +#include "task.h" #include "uart.h" #include "uart_defs.h" -#include "interrupts.h" -#include "system.h" #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_LPC, format, ##args) static const uint32_t baud_conf[][BAUD_TABLE_MAX] = { - {B9600, 9600}, - {B57600, 57600}, - {B115200, 115200}, - {B921600, 921600}, - {B2000000, 2000000}, - {B3000000, 3000000}, - {B3250000, 3250000}, - {B3500000, 3500000}, - {B4000000, 4000000}, - {B19200, 19200}, + { B9600, 9600 }, { B57600, 57600 }, { B115200, 115200 }, + { B921600, 921600 }, { B2000000, 2000000 }, { B3000000, 3000000 }, + { B3250000, 3250000 }, { B3500000, 3500000 }, { B4000000, 4000000 }, + { B19200, 19200 }, }; static struct uart_ctx uart_ctx[UART_DEVICES] = { @@ -122,7 +115,7 @@ int uart_read_char(void) return RBR(ISH_DEBUG_UART); } -void uart_ec_interrupt(void) +static void uart_ec_interrupt(void) { /* Read input FIFO until empty, then fill output FIFO */ uart_process_input(); @@ -146,7 +139,7 @@ static int uart_return_baud_rate_by_id(int baud_rate_id) static void uart_hw_init(enum UART_PORT id) { - uint32_t divisor; /* baud rate divisor */ + uint32_t divisor; /* baud rate divisor */ uint8_t mcr = 0; uint8_t fcr = 0; struct uart_ctx *ctx = &uart_ctx[id]; @@ -156,7 +149,8 @@ static void uart_hw_init(enum UART_PORT id) divisor = (ctx->input_freq / ctx->baud_rate) >> 4; if (IS_ENABLED(CONFIG_ISH_DW_UART)) { /* calculate the fractional part */ - fraction = ceil_for(ctx->input_freq, ctx->baud_rate) - (divisor << 4); + fraction = ceil_for(ctx->input_freq, ctx->baud_rate) - + (divisor << 4); } else { MUL(ctx->id) = (divisor * ctx->baud_rate); DIV(ctx->id) = (ctx->input_freq / 16); @@ -189,8 +183,7 @@ static void uart_hw_init(enum UART_PORT id) fcr = FCR_FIFO_SIZE_64 | FCR_ITL_FIFO_64_BYTES_1; /* configure FIFOs */ - FCR(ctx->id) = (fcr | FCR_FIFO_ENABLE - | FCR_RESET_RX | FCR_RESET_TX); + FCR(ctx->id) = (fcr | FCR_FIFO_ENABLE | FCR_RESET_RX | FCR_RESET_TX); if (!IS_ENABLED(CONFIG_ISH_DW_UART)) /* enable UART unit */ @@ -229,8 +222,8 @@ static void uart_stop_hw(enum UART_PORT id) if (!IS_ENABLED(CONFIG_ISH_DW_UART)) { /* Manually clearing the fifo from possible noise. - * Entering D0i3 when fifo is not cleared may result in a hang. - */ + * Entering D0i3 when fifo is not cleared may result in a hang. + */ fifo_len = (FOR(id) & FOR_OCCUPANCY_MASK) >> FOR_OCCUPANCY_OFFS; for (i = 0; i < fifo_len; i++) @@ -264,7 +257,7 @@ static int uart_client_init(enum UART_PORT id, uint32_t baud_rate_id, int flags) uart_ctx[id].client_flags = flags; - deprecated_atomic_and(&uart_ctx[id].uart_state, ~UART_STATE_CG); + atomic_and(&uart_ctx[id].uart_state, ~UART_STATE_CG); uart_hw_init(id); return EC_SUCCESS; @@ -280,10 +273,10 @@ static void uart_drv_init(void) if (!IS_ENABLED(CONFIG_ISH_DW_UART)) /* Enable HSU global interrupts (DMA/U0/U1) and set PMEN bit - * to allow PMU to clock gate ISH - */ - HSU_REG_GIEN = (GIEN_DMA_EN | GIEN_UART0_EN - | GIEN_UART1_EN | GIEN_PWR_MGMT); + * to allow PMU to clock gate ISH + */ + HSU_REG_GIEN = (GIEN_DMA_EN | GIEN_UART0_EN | GIEN_UART1_EN | + GIEN_PWR_MGMT); task_enable_irq(ISH_DEBUG_UART_IRQ); } diff --git a/chip/ish/uart_defs.h b/chip/ish/uart_defs.h index b573ef7710..581a702d31 100644 --- a/chip/ish/uart_defs.h +++ b/chip/ish/uart_defs.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,353 +8,342 @@ #ifndef __CROS_EC_UART_DEFS_H_ #define __CROS_EC_UART_DEFS_H_ -#include +#include "atomic.h" + #include +#include -#define UART_ERROR -1 -#define UART_BUSY -2 +#define UART_ERROR -1 +#define UART_BUSY -2 #ifdef CHIP_VARIANT_ISH5P4 -#define UART0_OFFS (0x00) -#define UART1_OFFS (0x2000) -#define UART2_OFFS (0x4000) +#define UART0_OFFS (0x00) +#define UART1_OFFS (0x2000) +#define UART2_OFFS (0x4000) #else -#define UART0_OFFS (0x80) -#define UART1_OFFS (0x100) -#define UART2_OFFS (0x180) +#define UART0_OFFS (0x80) +#define UART1_OFFS (0x100) +#define UART2_OFFS (0x180) #endif -#define HSU_BASE ISH_UART_BASE -#define UART0_BASE (ISH_UART_BASE + UART0_OFFS) -#define UART1_BASE (ISH_UART_BASE + UART1_OFFS) -#define UART2_BASE (ISH_UART_BASE + UART2_OFFS) +#define HSU_BASE ISH_UART_BASE +#define UART0_BASE (ISH_UART_BASE + UART0_OFFS) +#define UART1_BASE (ISH_UART_BASE + UART1_OFFS) +#define UART2_BASE (ISH_UART_BASE + UART2_OFFS) -#define UART_REG(size, name, n) \ - REG##size(uart_ctx[n].base + \ +#define UART_REG(size, name, n) \ + REG##size(uart_ctx[n].base + \ UART_OFFSET_##name * uart_ctx[n].addr_interval) /* Register accesses */ -#define LSR(n) UART_REG(8, LSR, n) -#define THR(n) UART_REG(8, THR, n) -#define RBR(n) UART_REG(8, RBR, n) -#define DLL(n) UART_REG(8, DLL, n) -#define DLH(n) UART_REG(8, DLH, n) -#define IER(n) UART_REG(8, IER, n) -#define IIR(n) UART_REG(8, IIR, n) -#define FCR(n) UART_REG(8, FCR, n) -#define LCR(n) UART_REG(8, LCR, n) -#define MCR(n) UART_REG(8, MCR, n) -#define MSR(n) UART_REG(8, MSR, n) -#define DLF(n) UART_REG(8, DLF, n) -#define FOR(n) UART_REG(32, FOR, n) -#define ABR(n) UART_REG(32, ABR, n) -#define PS(n) UART_REG(32, PS, n) -#define MUL(n) UART_REG(32, MUL, n) -#define DIV(n) UART_REG(32, DIV, n) +#define LSR(n) UART_REG(8, LSR, n) +#define THR(n) UART_REG(8, THR, n) +#define RBR(n) UART_REG(8, RBR, n) +#define DLL(n) UART_REG(8, DLL, n) +#define DLH(n) UART_REG(8, DLH, n) +#define IER(n) UART_REG(8, IER, n) +#define IIR(n) UART_REG(8, IIR, n) +#define FCR(n) UART_REG(8, FCR, n) +#define LCR(n) UART_REG(8, LCR, n) +#define MCR(n) UART_REG(8, MCR, n) +#define MSR(n) UART_REG(8, MSR, n) +#define DLF(n) UART_REG(8, DLF, n) +#define FOR(n) UART_REG(32, FOR, n) +#define ABR(n) UART_REG(32, ABR, n) +#define PS(n) UART_REG(32, PS, n) +#define MUL(n) UART_REG(32, MUL, n) +#define DIV(n) UART_REG(32, DIV, n) #ifdef CONFIG_ISH_DW_UART /* * RBR: Receive Buffer register (BLAB bit = 0) */ -#define UART_OFFSET_RBR (0x00) +#define UART_OFFSET_RBR (0x00) /* * THR: Transmit Holding register (BLAB bit = 0) */ -#define UART_OFFSET_THR (0x00) +#define UART_OFFSET_THR (0x00) /* * DLL: Divisor Latch Reg. low byte (BLAB bit = 1) * baud rate = (serial clock freq) / (16 * divisor) */ -#define UART_OFFSET_DLL (0x00) +#define UART_OFFSET_DLL (0x00) /* * DLH: Divisor Latch Reg. high byte (BLAB bit = 1) */ -#define UART_OFFSET_DLH (0x04) +#define UART_OFFSET_DLH (0x04) /* * IER: Interrupt Enable register (BLAB bit = 0) */ -#define UART_OFFSET_IER (0x04) +#define UART_OFFSET_IER (0x04) -#define IER_RECV (0x01) /* Receive Data Available */ -#define IER_TDRQ (0x02) /* Transmit Holding Register Empty */ -#define IER_LINE_STAT (0x04) /* Receiver Line Status */ -#define IER_MODEM (0x08) /* Modem Status */ -#define IER_PTIME (0x80) /* Programmable THRE Interrupt Mode Enable */ +#define IER_RECV (0x01) /* Receive Data Available */ +#define IER_TDRQ (0x02) /* Transmit Holding Register Empty */ +#define IER_LINE_STAT (0x04) /* Receiver Line Status */ +#define IER_MODEM (0x08) /* Modem Status */ +#define IER_PTIME (0x80) /* Programmable THRE Interrupt Mode Enable */ /* * IIR: Interrupt ID register */ -#define UART_OFFSET_IIR (0x08) - -#define IIR_MODEM (0x00) /* Prio: 4 */ -#define IIR_NO_INTR (0x01) -#define IIR_THRE (0x02) /* Prio: 3 */ -#define IIR_RECV_DATA (0x04) /* Prio: 2 */ -#define IIR_LINE_STAT (0x06) /* Prio: 1 */ -#define IIR_BUSY (0x07) /* Prio: 5 */ -#define IIR_TIME_OUT (0x0C) /* Prio: 2 */ -#define IIR_SOURCE (0x0F) +#define UART_OFFSET_IIR (0x08) +#define IIR_MODEM (0x00) /* Prio: 4 */ +#define IIR_NO_INTR (0x01) +#define IIR_THRE (0x02) /* Prio: 3 */ +#define IIR_RECV_DATA (0x04) /* Prio: 2 */ +#define IIR_LINE_STAT (0x06) /* Prio: 1 */ +#define IIR_BUSY (0x07) /* Prio: 5 */ +#define IIR_TIME_OUT (0x0C) /* Prio: 2 */ +#define IIR_SOURCE (0x0F) /* * FCR: FIFO Control register (FIFO_MODE != NONE) */ -#define UART_OFFSET_FCR (0x08) +#define UART_OFFSET_FCR (0x08) -#define FIFO_SIZE 64 -#define FCR_FIFO_ENABLE (0x01) -#define FCR_RESET_RX (0x02) -#define FCR_RESET_TX (0x04) -#define FCR_DMA_MODE (0x08) +#define FIFO_SIZE 64 +#define FCR_FIFO_ENABLE (0x01) +#define FCR_RESET_RX (0x02) +#define FCR_RESET_TX (0x04) +#define FCR_DMA_MODE (0x08) /* * LCR: Line Control register */ -#define UART_OFFSET_LCR (0x0c) +#define UART_OFFSET_LCR (0x0c) -#define LCR_5BIT_CHR (0x00) -#define LCR_6BIT_CHR (0x01) -#define LCR_7BIT_CHR (0x02) -#define LCR_8BIT_CHR (0x03) -#define LCR_BIT_CHR_MASK (0x03) +#define LCR_5BIT_CHR (0x00) +#define LCR_6BIT_CHR (0x01) +#define LCR_7BIT_CHR (0x02) +#define LCR_8BIT_CHR (0x03) +#define LCR_BIT_CHR_MASK (0x03) -#define LCR_STOP BIT(2) /* 0: 1 stop bit, 1: 1.5/2 */ -#define LCR_PEN BIT(3) /* Parity Enable */ -#define LCR_EPS BIT(4) /* Even Parity Select */ -#define LCR_SP BIT(5) /* Stick Parity */ -#define LCR_BC BIT(6) /* Break Control */ -#define LCR_DLAB BIT(7) /* Divisor Latch Access */ +#define LCR_STOP BIT(2) /* 0: 1 stop bit, 1: 1.5/2 */ +#define LCR_PEN BIT(3) /* Parity Enable */ +#define LCR_EPS BIT(4) /* Even Parity Select */ +#define LCR_SP BIT(5) /* Stick Parity */ +#define LCR_BC BIT(6) /* Break Control */ +#define LCR_DLAB BIT(7) /* Divisor Latch Access */ /* * MCR: Modem Control register */ -#define UART_OFFSET_MCR (0x10) -#define MCR_DTR (0x1) /* Data terminal ready */ -#define MCR_RTS (0x2) /* Request to send */ -#define MCR_LOOP (0x10) /* LoopBack bit*/ +#define UART_OFFSET_MCR (0x10) +#define MCR_DTR (0x1) /* Data terminal ready */ +#define MCR_RTS (0x2) /* Request to send */ +#define MCR_LOOP (0x10) /* LoopBack bit*/ -#define MCR_INTR_ENABLE (0x08) /* User-designated OUT2 */ -#define MCR_AUTO_FLOW_EN (0x20) +#define MCR_INTR_ENABLE (0x08) /* User-designated OUT2 */ +#define MCR_AUTO_FLOW_EN (0x20) /* * LSR: Line Status register */ -#define UART_OFFSET_LSR (0x14) +#define UART_OFFSET_LSR (0x14) -#define LSR_DR (0x01) /* Data Ready */ -#define LSR_OE (0x02) /* Overrun error */ -#define LSR_PE (0x04) /* Parity error */ -#define LSR_FE (0x08) /* Framing error */ -#define LSR_BI (0x10) /* Breaking interrupt */ -#define LSR_TDRQ (0x20) /* Transmit Holding Register Empty */ -#define LSR_TEMT (0x40) /* Transmitter empty */ +#define LSR_DR (0x01) /* Data Ready */ +#define LSR_OE (0x02) /* Overrun error */ +#define LSR_PE (0x04) /* Parity error */ +#define LSR_FE (0x08) /* Framing error */ +#define LSR_BI (0x10) /* Breaking interrupt */ +#define LSR_TDRQ (0x20) /* Transmit Holding Register Empty */ +#define LSR_TEMT (0x40) /* Transmitter empty */ /* * MSR: Modem Status register */ -#define UART_OFFSET_MSR (0x18) +#define UART_OFFSET_MSR (0x18) -#define MSR_CTS BIT(4) /* Clear To Send signal */ +#define MSR_CTS BIT(4) /* Clear To Send signal */ /* * TFL: Transmit FIFO Level */ -#define UART_OFFSET_TFL (0x80) +#define UART_OFFSET_TFL (0x80) /* * RFL: Receive FIFO Level */ -#define UART_OFFSET_RFL (0x84) +#define UART_OFFSET_RFL (0x84) #else /* RBR: Receive Buffer register (BLAB bit = 0) */ -#define UART_OFFSET_RBR (0) +#define UART_OFFSET_RBR (0) /* THR: Transmit Holding register (BLAB bit = 0) */ -#define UART_OFFSET_THR (0) +#define UART_OFFSET_THR (0) /* IER: Interrupt Enable register (BLAB bit = 0) */ -#define UART_OFFSET_IER (1) +#define UART_OFFSET_IER (1) /* FCR: FIFO Control register */ -#define UART_OFFSET_FCR (2) -#define FCR_FIFO_ENABLE BIT(0) -#define FCR_RESET_RX BIT(1) -#define FCR_RESET_TX BIT(2) +#define UART_OFFSET_FCR (2) +#define FCR_FIFO_ENABLE BIT(0) +#define FCR_RESET_RX BIT(1) +#define FCR_RESET_TX BIT(2) /* LCR: Line Control register */ -#define UART_OFFSET_LCR (3) -#define LCR_DLAB (0x80) -#define LCR_5BIT_CHR (0x00) -#define LCR_6BIT_CHR (0x01) -#define LCR_7BIT_CHR (0x02) -#define LCR_8BIT_CHR (0x03) -#define LCR_BIT_CHR_MASK (0x03) -#define LCR_SB (0x40) /* Set Break */ +#define UART_OFFSET_LCR (3) +#define LCR_DLAB (0x80) +#define LCR_5BIT_CHR (0x00) +#define LCR_6BIT_CHR (0x01) +#define LCR_7BIT_CHR (0x02) +#define LCR_8BIT_CHR (0x03) +#define LCR_BIT_CHR_MASK (0x03) +#define LCR_SB (0x40) /* Set Break */ /* MCR: Modem Control register */ -#define UART_OFFSET_MCR (4) -#define MCR_DTR BIT(0) -#define MCR_RTS BIT(1) -#define MCR_LOO BIT(4) -#define MCR_INTR_ENABLE BIT(3) -#define MCR_AUTO_FLOW_EN BIT(5) +#define UART_OFFSET_MCR (4) +#define MCR_DTR BIT(0) +#define MCR_RTS BIT(1) +#define MCR_LOO BIT(4) +#define MCR_INTR_ENABLE BIT(3) +#define MCR_AUTO_FLOW_EN BIT(5) /* LSR: Line Status register */ -#define UART_OFFSET_LSR (5) -#define LSR_DR BIT(0) /* Data Ready */ -#define LSR_OE BIT(1) /* Overrun error */ -#define LSR_PE BIT(2) /* Parity error */ -#define LSR_FE BIT(3) /* Framing error */ -#define LSR_BI BIT(4) /* Breaking interrupt */ -#define LSR_THR_EMPTY BIT(5) /* Non FIFO mode: Transmit holding - * register empty - */ -#define LSR_TDRQ BIT(5) /* FIFO mode: Transmit Data request */ -#define LSR_TEMT BIT(6) /* Transmitter empty */ +#define UART_OFFSET_LSR (5) +#define LSR_DR BIT(0) /* Data Ready */ +#define LSR_OE BIT(1) /* Overrun error */ +#define LSR_PE BIT(2) /* Parity error */ +#define LSR_FE BIT(3) /* Framing error */ +#define LSR_BI BIT(4) /* Breaking interrupt */ +#define LSR_THR_EMPTY \ + BIT(5) /* Non FIFO mode: Transmit holding \ + * register empty \ + */ +#define LSR_TDRQ BIT(5) /* FIFO mode: Transmit Data request */ +#define LSR_TEMT BIT(6) /* Transmitter empty */ #define FCR_ITL_FIFO_64_BYTES_56 (BIT(6) | BIT(7)) -#define IER_RECV BIT(0) -#define IER_TDRQ BIT(1) -#define IER_LINE_STAT BIT(2) +#define IER_RECV BIT(0) +#define IER_TDRQ BIT(1) +#define IER_LINE_STAT BIT(2) -#define UART_OFFSET_IIR (2) +#define UART_OFFSET_IIR (2) /* MSR: Modem Status register */ -#define UART_OFFSET_MSR (6) +#define UART_OFFSET_MSR (6) /* DLL: Divisor Latch Reg. low byte (BLAB bit = 1) */ -#define UART_OFFSET_DLL (0) +#define UART_OFFSET_DLL (0) /* DLH: Divisor Latch Reg. high byte (BLAB bit = 1) */ -#define UART_OFFSET_DLH (1) +#define UART_OFFSET_DLH (1) #endif /* * DLF: Divisor Latch Fraction Register */ -#define UART_OFFSET_DLF (0xC0) +#define UART_OFFSET_DLF (0xC0) /* FOR: Fifo O Register (ISH only) */ -#define UART_OFFSET_FOR (0x20) -#define FOR_OCCUPANCY_OFFS 0 -#define FOR_OCCUPANCY_MASK 0x7F +#define UART_OFFSET_FOR (0x20) +#define FOR_OCCUPANCY_OFFS 0 +#define FOR_OCCUPANCY_MASK 0x7F /* ABR: Auto-Baud Control Register (ISH only) */ -#define UART_OFFSET_ABR (0x24) -#define ABR_UUE BIT(4) +#define UART_OFFSET_ABR (0x24) +#define ABR_UUE BIT(4) /* Pre-Scalar Register (ISH only) */ -#define UART_OFFSET_PS (0x30) +#define UART_OFFSET_PS (0x30) /* DDS registers (ISH only) */ -#define UART_OFFSET_MUL (0x34) -#define UART_OFFSET_DIV (0x38) +#define UART_OFFSET_MUL (0x34) +#define UART_OFFSET_DIV (0x38) -#define FCR_FIFO_SIZE_16 (0x00) -#define FCR_FIFO_SIZE_64 (0x20) -#define FCR_ITL_FIFO_64_BYTES_1 (0x00) +#define FCR_FIFO_SIZE_16 (0x00) +#define FCR_FIFO_SIZE_64 (0x20) +#define FCR_ITL_FIFO_64_BYTES_1 (0x00) /* tx empty trigger(TET) */ -#define FCR_TET_EMPTY (0x00) -#define FCR_TET_2CHAR (0x10) -#define FCR_TET_QTR_FULL (0x20) -#define FCR_TET_HALF_FULL (0x30) +#define FCR_TET_EMPTY (0x00) +#define FCR_TET_2CHAR (0x10) +#define FCR_TET_QTR_FULL (0x20) +#define FCR_TET_HALF_FULL (0x30) /* receive trigger(RT) */ -#define FCR_RT_1CHAR (0x00) -#define FCR_RT_QTR_FULL (0x40) -#define FCR_RT_HALF_FULL (0x80) -#define FCR_RT_2LESS_FULL (0xc0) +#define FCR_RT_1CHAR (0x00) +#define FCR_RT_QTR_FULL (0x40) +#define FCR_RT_HALF_FULL (0x80) +#define FCR_RT_2LESS_FULL (0xc0) /* G_IEN: Global Interrupt Enable (ISH only) */ -#define HSU_REG_GIEN REG32(HSU_BASE + 0x0) -#define HSU_REG_GIST REG32(HSU_BASE + 0x4) - -#define GIEN_PWR_MGMT BIT(24) -#define GIEN_DMA_EN BIT(5) -#define GIEN_UART2_EN BIT(2) -#define GIEN_UART1_EN BIT(1) -#define GIEN_UART0_EN BIT(0) -#define GIST_DMA_EN BIT(5) -#define GIST_UART2_EN BIT(2) -#define GIST_UART1_EN BIT(1) -#define GIST_UART0_EN BIT(0) -#define GIST_UARTx_EN (GIST_UART0_EN|GIST_UART1_EN|GIST_UART2_EN) +#define HSU_REG_GIEN REG32(HSU_BASE + 0x0) +#define HSU_REG_GIST REG32(HSU_BASE + 0x4) + +#define GIEN_PWR_MGMT BIT(24) +#define GIEN_DMA_EN BIT(5) +#define GIEN_UART2_EN BIT(2) +#define GIEN_UART1_EN BIT(1) +#define GIEN_UART0_EN BIT(0) +#define GIST_DMA_EN BIT(5) +#define GIST_UART2_EN BIT(2) +#define GIST_UART1_EN BIT(1) +#define GIST_UART0_EN BIT(0) +#define GIST_UARTx_EN (GIST_UART0_EN | GIST_UART1_EN | GIST_UART2_EN) /* UART config flag, send to sc_io_control if the current UART line has HW * flow control lines connected. */ -#define UART_CONFIG_HW_FLOW_CONTROL BIT(0) +#define UART_CONFIG_HW_FLOW_CONTROL BIT(0) /* UART config flag for sc_io_control. If defined a sc_io_event_rx_msg is * raised only when the rx buffer is completely full. Otherwise, the event * is raised after a timeout is received on the UART line, * and all data received until now is provided. */ -#define UART_CONFIG_DELIVER_FULL_RX_BUF BIT(1) +#define UART_CONFIG_DELIVER_FULL_RX_BUF BIT(1) /* UART config flag for sc_io_control. If defined a sc_io_event_rx_buf_depleted * is raised when all rx buffers that were added are full. Otherwise, no * event is raised. */ -#define UART_CONFIG_ANNOUNCE_DEPLETED_BUF BIT(2) - -#define UART_INT_DEVICES 3 -#define UART_EXT_DEVICES 8 -#define UART_DEVICES UART_INT_DEVICES -#define UART_ISH_ADDR_INTERVAL 1 - -#define B9600 0x0000d -#define B57600 0x00000018 -#define B115200 0x00000011 -#define B921600 0x00000012 -#define B2000000 0x00000013 -#define B3000000 0x00000014 -#define B3250000 0x00000015 -#define B3500000 0x00000016 -#define B4000000 0x00000017 -#define B19200 0x0000e -#define B38400 0x0000f +#define UART_CONFIG_ANNOUNCE_DEPLETED_BUF BIT(2) + +#define UART_INT_DEVICES 3 +#define UART_EXT_DEVICES 8 +#define UART_DEVICES UART_INT_DEVICES +#define UART_ISH_ADDR_INTERVAL 1 + +#define B9600 0x0000d +#define B57600 0x00000018 +#define B115200 0x00000011 +#define B921600 0x00000012 +#define B2000000 0x00000013 +#define B3000000 0x00000014 +#define B3250000 0x00000015 +#define B3500000 0x00000016 +#define B4000000 0x00000017 +#define B19200 0x0000e +#define B38400 0x0000f /* KHZ, MHZ */ -#define KHZ(x) ((x) * 1000) -#define MHZ(x) (KHZ(x) * 1000) +#define KHZ(x) ((x)*1000) +#define MHZ(x) (KHZ(x) * 1000) #if defined(CHIP_VARIANT_ISH5P4) /* Change to 100MHZ in real silicon platform */ -#define UART_ISH_INPUT_FREQ MHZ(100) +#define UART_ISH_INPUT_FREQ MHZ(100) #elif defined(CHIP_FAMILY_ISH3) || defined(CHIP_FAMILY_ISH5) -#define UART_ISH_INPUT_FREQ MHZ(120) +#define UART_ISH_INPUT_FREQ MHZ(120) #elif defined(CHIP_FAMILY_ISH4) -#define UART_ISH_INPUT_FREQ MHZ(100) +#define UART_ISH_INPUT_FREQ MHZ(100) #endif -#define UART_DEFAULT_BAUD_RATE 115200 -#define UART_STATE_CG BIT(UART_OP_CG) +#define UART_DEFAULT_BAUD_RATE 115200 +#define UART_STATE_CG BIT(UART_OP_CG) -enum UART_PORT { - UART_PORT_0, - UART_PORT_1, - UART_PORT_MAX -}; +enum UART_PORT { UART_PORT_0, UART_PORT_1, UART_PORT_MAX }; -enum UART_OP { - UART_OP_READ, - UART_OP_WRITE, - UART_OP_CG, - UART_OP_MAX -}; +enum UART_OP { UART_OP_READ, UART_OP_WRITE, UART_OP_CG, UART_OP_MAX }; -enum { - BAUD_IDX, - BAUD_SPEED, - BAUD_TABLE_MAX -}; +enum { BAUD_IDX, BAUD_SPEED, BAUD_TABLE_MAX }; struct uart_ctx { uint32_t id; uint32_t base; uint32_t addr_interval; - uint32_t uart_state; + atomic_t uart_state; uint32_t is_open; uint32_t baud_rate; uint32_t input_freq; diff --git a/chip/ish/util/pack_ec.py b/chip/ish/util/pack_ec.py index f1ce28539e..13a2afafd9 100755 --- a/chip/ish/util/pack_ec.py +++ b/chip/ish/util/pack_ec.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*-" -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -20,89 +20,109 @@ import argparse import struct + MANIFEST_ENTRY_SIZE = 0x80 HEADER_SIZE = 0x1000 PAGE_SIZE = 0x1000 + def parseargs(): - parser = argparse.ArgumentParser() - parser.add_argument("-k", "--kernel", - help="EC kernel binary to pack, \ - usually ec.RW.bin or ec.RW.flat.", - required=True) - parser.add_argument("--kernel-size", type=int, - help="Size of EC kernel image", - required=True) - parser.add_argument("-a", "--aon", - help="EC aontask binary to pack, \ - usually ish_aontask.bin.", - required=False) - parser.add_argument("--aon-size", type=int, - help="Size of EC aontask image", - required=False) - parser.add_argument("-o", "--output", - help="Output flash binary file") - - return parser.parse_args() + parser = argparse.ArgumentParser() + parser.add_argument( + "-k", + "--kernel", + help="EC kernel binary to pack, usually ec.RW.bin or ec.RW.flat.", + required=True, + ) + parser.add_argument( + "--kernel-size", type=int, help="Size of EC kernel image", required=True + ) + parser.add_argument( + "-a", + "--aon", + help="EC aontask binary to pack, usually ish_aontask.bin.", + required=False, + ) + parser.add_argument( + "--aon-size", type=int, help="Size of EC aontask image", required=False + ) + parser.add_argument("-o", "--output", help="Output flash binary file") + + return parser.parse_args() + def gen_manifest(ext_id, comp_app_name, code_offset, module_size): - """Returns a binary blob that represents a manifest entry""" - m = bytearray(MANIFEST_ENTRY_SIZE) + """Returns a binary blob that represents a manifest entry""" + m = bytearray(MANIFEST_ENTRY_SIZE) - # 4 bytes of ASCII encode ID (little endian) - struct.pack_into('<4s', m, 0, ext_id) - # 8 bytes of ASCII encode ID (little endian) - struct.pack_into('<8s', m, 32, comp_app_name) - # 4 bytes of code offset (little endian) - struct.pack_into(' 0) + """Returns roundup-ed page size from size of bytes""" + return int(size / PAGE_SIZE) + (size % PAGE_SIZE > 0) + def main(): - args = parseargs() - print(" Packing EC image file for ISH") - - with open(args.output, 'wb') as f: - print(" kernel binary size:", args.kernel_size) - kern_rdup_pg_size = roundup_page(args.kernel_size) - # Add manifest for main ISH binary - f.write(gen_manifest(b'ISHM', b'ISH_KERN', HEADER_SIZE, kern_rdup_pg_size)) - - if args.aon is not None: - print(" AON binary size: ", args.aon_size) - aon_rdup_pg_size = roundup_page(args.aon_size) - # Add manifest for aontask binary - f.write(gen_manifest(b'ISHM', b'AON_TASK', - (HEADER_SIZE + kern_rdup_pg_size * PAGE_SIZE - - MANIFEST_ENTRY_SIZE), aon_rdup_pg_size)) - - # Add manifest that signals end of manifests - f.write(gen_manifest(b'ISHE', b'', 0, 0)) - - # Pad the remaining HEADER with 0s - if args.aon is not None: - f.write(b'\x00' * (HEADER_SIZE - (MANIFEST_ENTRY_SIZE * 3))) - else: - f.write(b'\x00' * (HEADER_SIZE - (MANIFEST_ENTRY_SIZE * 2))) - - # Append original kernel image - with open(args.kernel, 'rb') as in_file: - f.write(in_file.read()) - # Filling padings due to size round up as pages - f.write(b'\x00' * (kern_rdup_pg_size * PAGE_SIZE - args.kernel_size)) - - if args.aon is not None: - # Append original aon image - with open(args.aon, 'rb') as in_file: - f.write(in_file.read()) - # Filling padings due to size round up as pages - f.write(b'\x00' * (aon_rdup_pg_size * PAGE_SIZE - args.aon_size)) - -if __name__ == '__main__': - main() + args = parseargs() + print(" Packing EC image file for ISH") + + with open(args.output, "wb") as f: + print(" kernel binary size:", args.kernel_size) + kern_rdup_pg_size = roundup_page(args.kernel_size) + # Add manifest for main ISH binary + f.write( + gen_manifest(b"ISHM", b"ISH_KERN", HEADER_SIZE, kern_rdup_pg_size) + ) + + if args.aon is not None: + print(" AON binary size: ", args.aon_size) + aon_rdup_pg_size = roundup_page(args.aon_size) + # Add manifest for aontask binary + f.write( + gen_manifest( + b"ISHM", + b"AON_TASK", + ( + HEADER_SIZE + + kern_rdup_pg_size * PAGE_SIZE + - MANIFEST_ENTRY_SIZE + ), + aon_rdup_pg_size, + ) + ) + + # Add manifest that signals end of manifests + f.write(gen_manifest(b"ISHE", b"", 0, 0)) + + # Pad the remaining HEADER with 0s + if args.aon is not None: + f.write(b"\x00" * (HEADER_SIZE - (MANIFEST_ENTRY_SIZE * 3))) + else: + f.write(b"\x00" * (HEADER_SIZE - (MANIFEST_ENTRY_SIZE * 2))) + + # Append original kernel image + with open(args.kernel, "rb") as in_file: + f.write(in_file.read()) + # Filling padings due to size round up as pages + f.write(b"\x00" * (kern_rdup_pg_size * PAGE_SIZE - args.kernel_size)) + + if args.aon is not None: + # Append original aon image + with open(args.aon, "rb") as in_file: + f.write(in_file.read()) + # Filling padings due to size round up as pages + f.write(b"\x00" * (aon_rdup_pg_size * PAGE_SIZE - args.aon_size)) + + +if __name__ == "__main__": + main() diff --git a/chip/ish/watchdog.c b/chip/ish/watchdog.c index bf78f49312..8f0ea5ddf1 100644 --- a/chip/ish/watchdog.c +++ b/chip/ish/watchdog.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -23,14 +23,14 @@ #include "ec_commands.h" #include "hooks.h" #include "ish_persistent_data.h" -#include "task.h" #include "registers.h" #include "system.h" +#include "task.h" #include "watchdog.h" /* Units are hundreds of milliseconds */ -#define WDT_T1_PERIOD (100) /* 10 seconds */ -#define WDT_T2_PERIOD (10) /* 1 second */ +#define WDT_T1_PERIOD (100) /* 10 seconds */ +#define WDT_T2_PERIOD (10) /* 1 second */ int watchdog_init(void) { @@ -45,9 +45,8 @@ int watchdog_init(void) CCU_WDT_CD = WDT_CLOCK_HZ / 10; /* 10 Hz => 100 ms period */ /* Enable the watchdog timer and set initial T1/T2 values */ - WDT_CONTROL = WDT_CONTROL_ENABLE_BIT - | (WDT_T2_PERIOD << 8) - | WDT_T1_PERIOD; + WDT_CONTROL = WDT_CONTROL_ENABLE_BIT | (WDT_T2_PERIOD << 8) | + WDT_T1_PERIOD; task_enable_irq(ISH_WDT_IRQ); diff --git a/chip/it83xx/adc.c b/chip/it83xx/adc.c index f8a113beab..7b08a8beb1 100644 --- a/chip/it83xx/adc.c +++ b/chip/it83xx/adc.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,10 +6,9 @@ /* IT83xx ADC module for Chrome EC */ #include "adc.h" -#include "adc_chip.h" #include "clock.h" -#include "console.h" #include "common.h" +#include "console.h" #include "gpio.h" #include "hooks.h" #include "registers.h" @@ -18,7 +17,7 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /* Global variables */ static struct mutex adc_lock; @@ -27,42 +26,42 @@ static volatile task_id_t task_waiting; /* Data structure of ADC channel control registers. */ const struct adc_ctrl_t adc_ctrl_regs[] = { - {&IT83XX_ADC_VCH0CTL, &IT83XX_ADC_VCH0DATM, &IT83XX_ADC_VCH0DATL}, - {&IT83XX_ADC_VCH1CTL, &IT83XX_ADC_VCH1DATM, &IT83XX_ADC_VCH1DATL}, - {&IT83XX_ADC_VCH2CTL, &IT83XX_ADC_VCH2DATM, &IT83XX_ADC_VCH2DATL}, - {&IT83XX_ADC_VCH3CTL, &IT83XX_ADC_VCH3DATM, &IT83XX_ADC_VCH3DATL}, - {&IT83XX_ADC_VCH4CTL, &IT83XX_ADC_VCH4DATM, &IT83XX_ADC_VCH4DATL}, - {&IT83XX_ADC_VCH5CTL, &IT83XX_ADC_VCH5DATM, &IT83XX_ADC_VCH5DATL}, - {&IT83XX_ADC_VCH6CTL, &IT83XX_ADC_VCH6DATM, &IT83XX_ADC_VCH6DATL}, - {&IT83XX_ADC_VCH7CTL, &IT83XX_ADC_VCH7DATM, &IT83XX_ADC_VCH7DATL}, - {&IT83XX_ADC_VCH13CTL, &IT83XX_ADC_VCH13DATM, &IT83XX_ADC_VCH13DATL}, - {&IT83XX_ADC_VCH14CTL, &IT83XX_ADC_VCH14DATM, &IT83XX_ADC_VCH14DATL}, - {&IT83XX_ADC_VCH15CTL, &IT83XX_ADC_VCH15DATM, &IT83XX_ADC_VCH15DATL}, - {&IT83XX_ADC_VCH16CTL, &IT83XX_ADC_VCH16DATM, &IT83XX_ADC_VCH16DATL}, + { &IT83XX_ADC_VCH0CTL, &IT83XX_ADC_VCH0DATM, &IT83XX_ADC_VCH0DATL }, + { &IT83XX_ADC_VCH1CTL, &IT83XX_ADC_VCH1DATM, &IT83XX_ADC_VCH1DATL }, + { &IT83XX_ADC_VCH2CTL, &IT83XX_ADC_VCH2DATM, &IT83XX_ADC_VCH2DATL }, + { &IT83XX_ADC_VCH3CTL, &IT83XX_ADC_VCH3DATM, &IT83XX_ADC_VCH3DATL }, + { &IT83XX_ADC_VCH4CTL, &IT83XX_ADC_VCH4DATM, &IT83XX_ADC_VCH4DATL }, + { &IT83XX_ADC_VCH5CTL, &IT83XX_ADC_VCH5DATM, &IT83XX_ADC_VCH5DATL }, + { &IT83XX_ADC_VCH6CTL, &IT83XX_ADC_VCH6DATM, &IT83XX_ADC_VCH6DATL }, + { &IT83XX_ADC_VCH7CTL, &IT83XX_ADC_VCH7DATM, &IT83XX_ADC_VCH7DATL }, + { &IT83XX_ADC_VCH13CTL, &IT83XX_ADC_VCH13DATM, &IT83XX_ADC_VCH13DATL }, + { &IT83XX_ADC_VCH14CTL, &IT83XX_ADC_VCH14DATM, &IT83XX_ADC_VCH14DATL }, + { &IT83XX_ADC_VCH15CTL, &IT83XX_ADC_VCH15DATM, &IT83XX_ADC_VCH15DATL }, + { &IT83XX_ADC_VCH16CTL, &IT83XX_ADC_VCH16DATM, &IT83XX_ADC_VCH16DATL }, }; BUILD_ASSERT(ARRAY_SIZE(adc_ctrl_regs) == CHIP_ADC_COUNT); #ifdef CONFIG_ADC_VOLTAGE_COMPARATOR -#define VCMP_ADC_CH_MASK_H BIT(3) -#define VCMP_ADC_CH_MASK_L 0x7 +#define VCMP_ADC_CH_MASK_H BIT(3) +#define VCMP_ADC_CH_MASK_L 0x7 /* 10-bits resolution */ -#define VCMP_RESOLUTION BIT(10) -#define VCMP_MAX_MVOLT 3000 +#define VCMP_RESOLUTION BIT(10) +#define VCMP_MAX_MVOLT 3000 /* Data structure of voltage comparator control registers. */ const struct vcmp_ctrl_t vcmp_ctrl_regs[] = { - {&IT83XX_ADC_VCMP0CTL, &IT83XX_ADC_VCMP0CSELM, &IT83XX_ADC_CMP0THRDATM, - &IT83XX_ADC_CMP0THRDATL}, - {&IT83XX_ADC_VCMP1CTL, &IT83XX_ADC_VCMP1CSELM, &IT83XX_ADC_CMP1THRDATM, - &IT83XX_ADC_CMP1THRDATL}, - {&IT83XX_ADC_VCMP2CTL, &IT83XX_ADC_VCMP2CSELM, &IT83XX_ADC_CMP2THRDATM, - &IT83XX_ADC_CMP2THRDATL}, - {&IT83XX_ADC_VCMP3CTL, &IT83XX_ADC_VCMP3CSELM, &IT83XX_ADC_CMP3THRDATM, - &IT83XX_ADC_CMP3THRDATL}, - {&IT83XX_ADC_VCMP4CTL, &IT83XX_ADC_VCMP4CSELM, &IT83XX_ADC_CMP4THRDATM, - &IT83XX_ADC_CMP4THRDATL}, - {&IT83XX_ADC_VCMP5CTL, &IT83XX_ADC_VCMP5CSELM, &IT83XX_ADC_CMP5THRDATM, - &IT83XX_ADC_CMP5THRDATL}, + { &IT83XX_ADC_VCMP0CTL, &IT83XX_ADC_VCMP0CSELM, &IT83XX_ADC_CMP0THRDATM, + &IT83XX_ADC_CMP0THRDATL }, + { &IT83XX_ADC_VCMP1CTL, &IT83XX_ADC_VCMP1CSELM, &IT83XX_ADC_CMP1THRDATM, + &IT83XX_ADC_CMP1THRDATL }, + { &IT83XX_ADC_VCMP2CTL, &IT83XX_ADC_VCMP2CSELM, &IT83XX_ADC_CMP2THRDATM, + &IT83XX_ADC_CMP2THRDATL }, + { &IT83XX_ADC_VCMP3CTL, &IT83XX_ADC_VCMP3CSELM, &IT83XX_ADC_CMP3THRDATM, + &IT83XX_ADC_CMP3THRDATL }, + { &IT83XX_ADC_VCMP4CTL, &IT83XX_ADC_VCMP4CSELM, &IT83XX_ADC_CMP4THRDATM, + &IT83XX_ADC_CMP4THRDATL }, + { &IT83XX_ADC_VCMP5CTL, &IT83XX_ADC_VCMP5CSELM, &IT83XX_ADC_CMP5THRDATM, + &IT83XX_ADC_CMP5THRDATL }, }; BUILD_ASSERT(ARRAY_SIZE(vcmp_ctrl_regs) == CHIP_VCMP_COUNT); #endif @@ -121,8 +120,8 @@ static void adc_disable_channel(int ch) static int adc_data_valid(enum chip_adc_channel adc_ch) { return (adc_ch <= CHIP_ADC_CH7) ? - (IT83XX_ADC_ADCDVSTS & BIT(adc_ch)) : - (IT83XX_ADC_ADCDVSTS2 & (1 << (adc_ch - CHIP_ADC_CH13))); + (IT83XX_ADC_ADCDVSTS & BIT(adc_ch)) : + (IT83XX_ADC_ADCDVSTS2 & (1 << (adc_ch - CHIP_ADC_CH13))); } int adc_read_channel(enum adc_channel ch) @@ -145,33 +144,39 @@ int adc_read_channel(enum adc_channel ch) /* Wait for interrupt */ events = task_wait_event_mask(TASK_EVENT_ADC_DONE, ADC_TIMEOUT_US); task_waiting = TASK_ID_INVALID; - - if (events & TASK_EVENT_ADC_DONE) { - /* data valid of adc channel[x] */ - if (adc_data_valid(adc_ch)) { - /* read adc raw data msb and lsb */ - adc_raw_data = (*adc_ctrl_regs[adc_ch].adc_datm << 8) + - *adc_ctrl_regs[adc_ch].adc_datl; - - /* W/C data valid flag */ - if (adc_ch <= CHIP_ADC_CH7) - IT83XX_ADC_ADCDVSTS = BIT(adc_ch); - else - IT83XX_ADC_ADCDVSTS2 = - (1 << (adc_ch - CHIP_ADC_CH13)); - - mv = adc_raw_data * adc_channels[ch].factor_mul / - adc_channels[ch].factor_div + - adc_channels[ch].shift; - valid = 1; - } + /* + * Ensure EC won't post the adc done event which is set after getting + * events (events |= __wait_evt() in task_wait_event_mask()) to next + * adc read. + * NOTE: clear TASK_EVENT_ADC_DONE event must happen after setting + * task_waiting to invalid. So TASK_EVENT_ADC_DONE would not set until + * next read. + */ + atomic_clear_bits(task_get_event_bitmap(task_get_current()), + TASK_EVENT_ADC_DONE); + + /* data valid of adc channel[x] */ + if (adc_data_valid(adc_ch)) { + /* read adc raw data msb and lsb */ + adc_raw_data = (*adc_ctrl_regs[adc_ch].adc_datm << 8) + + *adc_ctrl_regs[adc_ch].adc_datl; + + /* W/C data valid flag */ + if (adc_ch <= CHIP_ADC_CH7) + IT83XX_ADC_ADCDVSTS = BIT(adc_ch); + else + IT83XX_ADC_ADCDVSTS2 = (1 << (adc_ch - CHIP_ADC_CH13)); + + mv = (uint64_t)adc_raw_data * adc_channels[ch].factor_mul / + adc_channels[ch].factor_div + + adc_channels[ch].shift; + valid = 1; } if (!valid) { CPRINTS("ADC failed to read!!! (regs=%x, %x, ch=%d, evt=%x)", - IT83XX_ADC_ADCDVSTS, - IT83XX_ADC_ADCDVSTS2, - adc_ch, events); + IT83XX_ADC_ADCDVSTS, IT83XX_ADC_ADCDVSTS2, adc_ch, + events); } adc_disable_channel(adc_ch); @@ -202,7 +207,7 @@ void adc_interrupt(void) task_disable_irq(IT83XX_IRQ_ADC); /* Wake up the task which was waiting for the interrupt */ if (task_waiting != TASK_ID_INVALID) - task_set_event(task_waiting, TASK_EVENT_ADC_DONE, 0); + task_set_event(task_waiting, TASK_EVENT_ADC_DONE); } #ifdef CONFIG_ADC_VOLTAGE_COMPARATOR @@ -287,8 +292,8 @@ static void voltage_comparator_init(void) */ /* Select which ADC channel output voltage into comparator */ - *vcmp_ctrl_regs[idx].vcmp_ctrl |= - vcmp_list[idx].adc_ch & VCMP_ADC_CH_MASK_L; + *vcmp_ctrl_regs[idx].vcmp_ctrl |= vcmp_list[idx].adc_ch & + VCMP_ADC_CH_MASK_L; if (vcmp_list[idx].adc_ch & VCMP_ADC_CH_MASK_H) *vcmp_ctrl_regs[idx].vcmp_adc_chm |= ADC_VCMP_VCMPCSELM; @@ -350,6 +355,11 @@ static void adc_init(void) IT83XX_ADC_ADCSTS &= ~BIT(7); IT83XX_ADC_ADCCFG &= ~BIT(5); IT83XX_ADC_ADCCTL = 1; + /* + * Enable this bit, and data of VCHxDATL/VCHxDATM will be + * kept until data valid is cleared. + */ + IT83XX_ADC_ADCGCR |= IT83XX_ADC_DBKEN; task_waiting = TASK_ID_INVALID; /* disable adc interrupt */ diff --git a/chip/it83xx/adc_chip.h b/chip/it83xx/adc_chip.h index 23cc68fb34..3804a684e5 100644 --- a/chip/it83xx/adc_chip.h +++ b/chip/it83xx/adc_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,6 +10,8 @@ #include "common.h" +#include + /* * Maximum time we allow for an ADC conversion. * NOTE: @@ -59,13 +61,13 @@ enum vcmp_scan_period { VCMP_SCAN_PERIOD_400US = 0x30, VCMP_SCAN_PERIOD_600US = 0x40, VCMP_SCAN_PERIOD_800US = 0x50, - VCMP_SCAN_PERIOD_1MS = 0x60, + VCMP_SCAN_PERIOD_1MS = 0x60, VCMP_SCAN_PERIOD_1_5MS = 0x70, - VCMP_SCAN_PERIOD_2MS = 0x80, + VCMP_SCAN_PERIOD_2MS = 0x80, VCMP_SCAN_PERIOD_2_5MS = 0x90, - VCMP_SCAN_PERIOD_3MS = 0xA0, - VCMP_SCAN_PERIOD_4MS = 0xB0, - VCMP_SCAN_PERIOD_5MS = 0xC0, + VCMP_SCAN_PERIOD_3MS = 0xA0, + VCMP_SCAN_PERIOD_4MS = 0xB0, + VCMP_SCAN_PERIOD_5MS = 0xC0, }; /* Data structure to define ADC channel control registers. */ @@ -93,8 +95,8 @@ struct vcmp_ctrl_t { }; /* supported flags (member "flag" in struct vcmp_t) for voltage comparator */ -#define GREATER_THRESHOLD BIT(0) -#define LESS_EQUAL_THRESHOLD BIT(1) +#define GREATER_THRESHOLD BIT(0) +#define LESS_EQUAL_THRESHOLD BIT(1) /* Data structure for board to define voltage comparator list. */ struct vcmp_t { @@ -121,12 +123,6 @@ struct vcmp_t { enum chip_adc_channel adc_ch; }; -/* - * Boards must provide this list of ADC channel definitions. This must match - * the enum adc_channel list provided by the board. - */ -extern const struct adc_t adc_channels[]; - #ifdef CONFIG_ADC_VOLTAGE_COMPARATOR /* * Boards must provide this list of voltage comparator definitions. diff --git a/chip/it83xx/build.mk b/chip/it83xx/build.mk index eb4473f4a9..c23bc33a6e 100644 --- a/chip/it83xx/build.mk +++ b/chip/it83xx/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. +# Copyright 2013 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -29,12 +29,13 @@ chip-$(CONFIG_PWM)+=pwm.o chip-$(CONFIG_ADC)+=adc.o chip-$(CONFIG_DAC)+=dac.o chip-$(CONFIG_HOSTCMD_X86)+=lpc.o ec2i.o -chip-$(CONFIG_HOSTCMD_ESPI)+=espi.o -chip-$(CONFIG_SPI_MASTER)+=spi_master.o +chip-$(CONFIG_HOST_INTERFACE_ESPI)+=espi.o +chip-$(CONFIG_SPI_CONTROLLER)+=spi_controller.o chip-$(CONFIG_SPI)+=spi.o chip-$(CONFIG_PECI)+=peci.o -ifndef CONFIG_KEYBOARD_NOT_RAW +chip-$(CONFIG_CEC_BITBANG)+=cec_bitbang.o +ifndef CONFIG_KEYBOARD_DISCRETE chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o endif -chip-$(CONFIG_I2C_MASTER)+=i2c.o -chip-$(CONFIG_I2C_SLAVE)+=i2c_slave.o +chip-$(CONFIG_I2C_CONTROLLER)+=i2c.o +chip-$(CONFIG_I2C_PERIPHERAL)+=i2c_peripheral.o diff --git a/chip/it83xx/cec_bitbang.c b/chip/it83xx/cec_bitbang.c new file mode 100644 index 0000000000..25d01b3b19 --- /dev/null +++ b/chip/it83xx/cec_bitbang.c @@ -0,0 +1,140 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cec.h" +#include "cec_bitbang_chip.h" +#include "console.h" +#include "driver/cec/bitbang.h" +#include "gpio.h" +#include "hwtimer_chip.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#ifdef CONFIG_CEC_DEBUG +#define CPRINTF(format, args...) cprintf(CC_CEC, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CEC, format, ##args) +#else +#define CPRINTF(...) +#define CPRINTS(...) +#endif + +/* Timestamp when the most recent interrupt occurred */ +static timestamp_t interrupt_time; + +/* Timestamp when the second most recent interrupt occurred */ +static timestamp_t prev_interrupt_time; + +/* Flag set when a transfer is initiated from the AP */ +static bool transfer_initiated; + +/* + * ITE doesn't have a capture timer, so we use a countdown timer for timeout + * events combined with a GPIO interrupt for capture events. + */ +void cec_tmr_cap_start(enum cec_cap_edge edge, int timeout) +{ + switch (edge) { + case CEC_CAP_EDGE_NONE: + gpio_disable_interrupt(CEC_GPIO_IN); + break; + case CEC_CAP_EDGE_FALLING: + gpio_set_flags(CEC_GPIO_IN, GPIO_INT_FALLING); + gpio_enable_interrupt(CEC_GPIO_IN); + break; + case CEC_CAP_EDGE_RISING: + gpio_set_flags(CEC_GPIO_IN, GPIO_INT_RISING); + gpio_enable_interrupt(CEC_GPIO_IN); + break; + } + + if (timeout > 0) { + /* + * Take into account the delay from when the interrupt occurs to + * when we actually get here. + */ + int delay = + CEC_US_TO_TICKS(get_time().val - interrupt_time.val); + int timer_count = timeout - delay; + + /* + * Handle the case where the delay is greater than the timeout. + * This should never actually happen for typical delay and + * timeout values. + */ + if (timer_count < 0) { + timer_count = 0; + CPRINTS("CEC WARNING: timer_count < 0"); + } + + /* Start the timer and enable the timer interrupt */ + ext_timer_ms(CEC_EXT_TIMER, CEC_CLOCK_SOURCE, 1, 1, timer_count, + 0, 1); + } else { + ext_timer_stop(CEC_EXT_TIMER, 1); + } +} + +void cec_tmr_cap_stop(void) +{ + gpio_disable_interrupt(CEC_GPIO_IN); + ext_timer_stop(CEC_EXT_TIMER, 1); +} + +int cec_tmr_cap_get(void) +{ + return CEC_US_TO_TICKS(interrupt_time.val - prev_interrupt_time.val); +} + +__override void cec_update_interrupt_time(void) +{ + prev_interrupt_time = interrupt_time; + interrupt_time = get_time(); +} + +void cec_ext_timer_interrupt(void) +{ + if (transfer_initiated) { + transfer_initiated = false; + cec_event_tx(); + } else { + cec_update_interrupt_time(); + cec_event_timeout(); + } +} + +void cec_gpio_interrupt(enum gpio_signal signal) +{ + cec_update_interrupt_time(); + cec_event_cap(); +} + +void cec_trigger_send(void) +{ + /* Elevate to interrupt context */ + transfer_initiated = true; + task_trigger_irq(et_ctrl_regs[CEC_EXT_TIMER].irq); +} + +void cec_enable_timer(void) +{ + /* + * Nothing to do. Interrupts will be enabled as needed by + * cec_tmr_cap_start(). + */ +} + +void cec_disable_timer(void) +{ + cec_tmr_cap_stop(); + + interrupt_time.val = 0; + prev_interrupt_time.val = 0; +} + +void cec_init_timer(void) +{ + ext_timer_ms(CEC_EXT_TIMER, CEC_CLOCK_SOURCE, 0, 0, 0, 1, 0); +} diff --git a/chip/it83xx/cec_bitbang_chip.h b/chip/it83xx/cec_bitbang_chip.h new file mode 100644 index 0000000000..daca59c921 --- /dev/null +++ b/chip/it83xx/cec_bitbang_chip.h @@ -0,0 +1,21 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_CEC_CHIP_H +#define __CROS_EC_CEC_CHIP_H + +#include "hwtimer_chip.h" + +#define CEC_CLOCK_SOURCE EXT_PSR_32P768K_HZ +#define CEC_CLOCK_FREQ_HZ 32768 + +/* Time in us to timer clock ticks */ +#define CEC_US_TO_TICKS(t) ((t)*CEC_CLOCK_FREQ_HZ / 1000000) +#ifdef CONFIG_CEC_DEBUG +/* Timer clock ticks to us */ +#define CEC_TICKS_TO_US(ticks) (1000000 * (ticks) / CEC_CLOCK_FREQ_HZ) +#endif + +#endif /* __CROS_EC_CEC_CHIP_H */ diff --git a/chip/it83xx/clock.c b/chip/it83xx/clock.c index d38197379a..bd6ae01281 100644 --- a/chip/it83xx/clock.c +++ b/chip/it83xx/clock.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,6 +9,7 @@ #include "clock.h" #include "common.h" #include "console.h" +#include "gpio.h" #include "hwtimer.h" #include "hwtimer_chip.h" #include "intc.h" @@ -23,11 +24,11 @@ /* Console output macros. */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) #ifdef CONFIG_LOW_POWER_IDLE #define SLEEP_SET_HTIMER_DELAY_USEC 250 -#define SLEEP_FTIMER_SKIP_USEC (HOOK_TICK_INTERVAL * 2) +#define SLEEP_FTIMER_SKIP_USEC (HOOK_TICK_INTERVAL * 2) static timestamp_t sleep_mode_t0; static timestamp_t sleep_mode_t1; @@ -39,13 +40,13 @@ static uint32_t ec_sleep; * Fixed amount of time to keep the console in use flag true after boot in * order to give a permanent window in which the heavy sleep mode is not used. */ -#define CONSOLE_IN_USE_ON_BOOT_TIME (15*SECOND) +#define CONSOLE_IN_USE_ON_BOOT_TIME (15 * SECOND) static int console_in_use_timeout_sec = 5; static timestamp_t console_expire_time; /* clock source is 32.768KHz */ -#define TIMER_32P768K_CNT_TO_US(cnt) ((uint64_t)(cnt) * 1000000 / 32768) -#define TIMER_CNT_8M_32P768K(cnt) (((cnt) / (8000000 / 32768)) + 1) +#define TIMER_32P768K_CNT_TO_US(cnt) ((uint64_t)(cnt)*1000000 / 32768) +#define TIMER_CNT_8M_32P768K(cnt) (((cnt) / (8000000 / 32768)) + 1) #endif /*CONFIG_LOW_POWER_IDLE */ static int freq; @@ -65,10 +66,11 @@ static void clock_module_disable(void) IT83XX_GCTRL_MCCR &= ~BIT(7); clock_disable_peripheral((CGC_OFFSET_EGPC | CGC_OFFSET_CIR), 0, 0); clock_disable_peripheral((CGC_OFFSET_SMBA | CGC_OFFSET_SMBB | - CGC_OFFSET_SMBC | CGC_OFFSET_SMBD | CGC_OFFSET_SMBE | - CGC_OFFSET_SMBF), 0, 0); - clock_disable_peripheral((CGC_OFFSET_SSPI | CGC_OFFSET_PECI | - CGC_OFFSET_USB), 0, 0); + CGC_OFFSET_SMBC | CGC_OFFSET_SMBD | + CGC_OFFSET_SMBE | CGC_OFFSET_SMBF), + 0, 0); + clock_disable_peripheral( + (CGC_OFFSET_SSPI | CGC_OFFSET_PECI | CGC_OFFSET_USB), 0, 0); } enum pll_freq_idx { @@ -77,19 +79,11 @@ enum pll_freq_idx { PLL_96_MHZ = 4, }; -static const uint8_t pll_to_idx[8] = { - 0, - 0, - PLL_24_MHZ, - 0, - PLL_48_MHZ, - 0, - 0, - PLL_96_MHZ -}; +static const uint8_t pll_to_idx[8] = { 0, 0, PLL_24_MHZ, 0, + PLL_48_MHZ, 0, 0, PLL_96_MHZ }; struct clock_pll_t { - int pll_freq; + int pll_freq; uint8_t pll_setting; uint8_t div_fnd; uint8_t div_uart; @@ -113,17 +107,17 @@ const struct clock_pll_t clock_pll_ctrl[] = { * SSPI: 48MHz(24MHz if PLL=24MHz) */ /* PLL:24MHz, MCU:24MHz, Fnd(e-flash):24MHz */ - [PLL_24_MHZ] = {24000000, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0x2}, + [PLL_24_MHZ] = { 24000000, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0x2 }, #ifdef CONFIG_IT83XX_FLASH_CLOCK_48MHZ /* PLL:48MHz, MCU:48MHz, Fnd:48MHz */ - [PLL_48_MHZ] = {48000000, 4, 0, 1, 0, 1, 0, 6, 1, 0, 0x5}, + [PLL_48_MHZ] = { 48000000, 4, 0, 1, 0, 1, 0, 6, 1, 0, 0x5 }, /* PLL:96MHz, MCU:96MHz, Fnd:48MHz */ - [PLL_96_MHZ] = {96000000, 7, 1, 3, 1, 3, 1, 6, 3, 1, 0xb}, + [PLL_96_MHZ] = { 96000000, 7, 1, 3, 1, 3, 1, 6, 3, 1, 0xb }, #else /* PLL:48MHz, MCU:48MHz, Fnd:24MHz */ - [PLL_48_MHZ] = {48000000, 4, 1, 1, 0, 1, 0, 2, 1, 0, 0x5}, + [PLL_48_MHZ] = { 48000000, 4, 1, 1, 0, 1, 0, 2, 1, 0, 0x5 }, /* PLL:96MHz, MCU:96MHz, Fnd:32MHz */ - [PLL_96_MHZ] = {96000000, 7, 2, 3, 1, 3, 1, 4, 3, 1, 0xb}, + [PLL_96_MHZ] = { 96000000, 7, 2, 3, 1, 3, 1, 4, 3, 1, 0xb }, #endif }; @@ -134,9 +128,15 @@ static uint8_t pll_setting; void __ram_code clock_ec_pll_ctrl(enum ec_pll_ctrl mode) { + volatile uint8_t _pll_ctrl __unused; + IT83XX_ECPM_PLLCTRL = mode; - /* for deep doze / sleep mode */ - IT83XX_ECPM_PLLCTRL = mode; + /* + * for deep doze / sleep mode + * This load operation will ensure PLL setting is taken into + * control register before wait for interrupt instruction. + */ + _pll_ctrl = IT83XX_ECPM_PLLCTRL; #ifdef IT83XX_CHIP_FLASH_NO_DEEP_POWER_DOWN /* @@ -189,18 +189,18 @@ void __ram_code clock_pll_changed(void) clock_ec_pll_ctrl(EC_PLL_SLEEP); if (IS_ENABLED(CHIP_CORE_NDS32)) { /* Global interrupt enable */ - asm volatile ("setgie.e"); + asm volatile("setgie.e"); /* EC sleep */ asm("standby wake_grant"); /* Global interrupt disable */ - asm volatile ("setgie.d"); + asm volatile("setgie.d"); } else if (IS_ENABLED(CHIP_CORE_RISCV)) { /* Global interrupt enable */ - asm volatile ("csrsi mstatus, 0x8"); + asm volatile("csrsi mstatus, 0x8"); /* EC sleep */ asm("wfi"); /* Global interrupt disable */ - asm volatile ("csrci mstatus, 0x8"); + asm volatile("csrci mstatus, 0x8"); } /* New FND clock frequency */ IT83XX_ECPM_SCDCR0 = (pll_div_fnd << 4); @@ -213,20 +213,20 @@ static void clock_set_pll(enum pll_freq_idx idx) { int pll; - pll_div_fnd = clock_pll_ctrl[idx].div_fnd; - pll_div_ec = clock_pll_ctrl[idx].div_ec; + pll_div_fnd = clock_pll_ctrl[idx].div_fnd; + pll_div_ec = clock_pll_ctrl[idx].div_ec; pll_div_jtag = clock_pll_ctrl[idx].div_jtag; - pll_setting = clock_pll_ctrl[idx].pll_setting; + pll_setting = clock_pll_ctrl[idx].pll_setting; /* Update PLL settings or not */ if (((IT83XX_ECPM_PLLFREQR & 0xf) != pll_setting) || - ((IT83XX_ECPM_SCDCR0 & 0xf0) != (pll_div_fnd << 4)) || - ((IT83XX_ECPM_SCDCR3 & 0xf) != pll_div_ec)) { + ((IT83XX_ECPM_SCDCR0 & 0xf0) != (pll_div_fnd << 4)) || + ((IT83XX_ECPM_SCDCR3 & 0xf) != pll_div_ec)) { /* Enable hw timer to wakeup EC from the sleep mode */ - ext_timer_ms(LOW_POWER_EXT_TIMER, EXT_PSR_32P768K_HZ, - 1, 1, 5, 1, 0); + ext_timer_ms(LOW_POWER_EXT_TIMER, EXT_PSR_32P768K_HZ, 1, 1, 5, + 1, 0); task_clear_pending_irq(et_ctrl_regs[LOW_POWER_EXT_TIMER].irq); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI /* * Workaround for (b:70537592): * We have to set chip select pin as input mode in order to @@ -243,7 +243,7 @@ static void clock_set_pll(enum pll_freq_idx idx) #endif /* Update PLL settings. */ clock_pll_changed(); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI #ifdef IT83XX_ESPI_INHIBIT_CS_BY_PAD_DISABLED /* Enable eSPI pad after changing PLL sequence. */ espi_enable_pad(1); @@ -257,13 +257,13 @@ static void clock_set_pll(enum pll_freq_idx idx) pll = pll_to_idx[IT83XX_ECPM_PLLFREQR & 0xf]; /* USB and UART */ IT83XX_ECPM_SCDCR1 = (clock_pll_ctrl[pll].div_usb << 4) | - clock_pll_ctrl[pll].div_uart; + clock_pll_ctrl[pll].div_uart; /* SSPI and SMB */ IT83XX_ECPM_SCDCR2 = (clock_pll_ctrl[pll].div_sspi << 4) | - clock_pll_ctrl[pll].div_smb; + clock_pll_ctrl[pll].div_smb; /* USBPD and PWM */ IT83XX_ECPM_SCDCR4 = (clock_pll_ctrl[pll].div_usbpd << 4) | - clock_pll_ctrl[pll].div_pwm; + clock_pll_ctrl[pll].div_pwm; /* Current PLL frequency */ freq = clock_pll_ctrl[pll].pll_freq; } @@ -277,8 +277,7 @@ void clock_init(void) /* Interrupt Vector Table Base Address, in 64k Byte unit */ IT83XX_GCTRL_IVTBAR = (CONFIG_RW_MEM_OFF >> 16) & 0xFF; -#if (PLL_CLOCK == 24000000) || \ - (PLL_CLOCK == 48000000) || \ +#if (PLL_CLOCK == 24000000) || (PLL_CLOCK == 48000000) || \ (PLL_CLOCK == 96000000) /* Set PLL frequency */ clock_set_pll(PLL_CLOCK / 24000000); @@ -295,13 +294,17 @@ void clock_init(void) */ IT83XX_GCTRL_RSTS = (IT83XX_GCTRL_RSTS & 0x3F) + 0x40; -#if defined(IT83XX_ESPI_RESET_MODULE_BY_FW) && defined(CONFIG_HOSTCMD_ESPI) +#if defined(IT83XX_ESPI_RESET_MODULE_BY_FW) && \ + defined(CONFIG_HOST_INTERFACE_ESPI) /* * Because we don't support eSPI HW reset function (b/111480168) on DX * version, so we have to reset eSPI configurations during init to * ensure Host and EC are synchronized (especially for the field of * I/O mode) + * Since bit4 of VWCTRL2 register is enabled, the below reset routine + * will be able to reset pltrst# signal. */ + IT83XX_ESPI_VWCTRL2 |= ESPI_PLTRST_ESPI_RESET; if (!system_jumped_to_this_image()) espi_fw_reset_module(); #endif @@ -337,8 +340,8 @@ int clock_get_freq(void) */ void clock_enable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) { - volatile uint8_t *reg = (volatile uint8_t *) - (IT83XX_ECPM_BASE + (offset >> 8)); + volatile uint8_t *reg = + (volatile uint8_t *)(IT83XX_ECPM_BASE + (offset >> 8)); uint8_t reg_mask = offset & 0xff; /* @@ -360,8 +363,8 @@ void clock_enable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) */ void clock_disable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) { - volatile uint8_t *reg = (volatile uint8_t *) - (IT83XX_ECPM_BASE + (offset >> 8)); + volatile uint8_t *reg = + (volatile uint8_t *)(IT83XX_ECPM_BASE + (offset >> 8)); uint8_t reg_mask = offset & 0xff; uint8_t tmp_mask = 0; @@ -380,7 +383,7 @@ void clock_refresh_console_in_use(void) } static void clock_event_timer_clock_change(enum ext_timer_clock_source clock, - uint32_t count) + uint32_t count) { IT83XX_ETWD_ETXCTRL(EVENT_EXT_TIMER) &= ~BIT(0); IT83XX_ETWD_ETXPSR(EVENT_EXT_TIMER) = clock; @@ -412,19 +415,19 @@ static int clock_allow_low_power_idle(void) /* If timer interrupt status is set, don't go to sleep mode. */ if (*et_ctrl_regs[EVENT_EXT_TIMER].isr & - et_ctrl_regs[EVENT_EXT_TIMER].mask) + et_ctrl_regs[EVENT_EXT_TIMER].mask) return 0; - /* - * If timer is less than 250us to expire, then we don't go to sleep - * mode. - */ + /* + * If timer is less than 250us to expire, then we don't go to + * sleep mode. + */ #ifdef IT83XX_EXT_OBSERVATION_REG_READ_TWO_TIMES if (EVENT_TIMER_COUNT_TO_US(ext_observation_reg_read(EVENT_EXT_TIMER)) < #else if (EVENT_TIMER_COUNT_TO_US(IT83XX_ETWD_ETXCNTOR(EVENT_EXT_TIMER)) < #endif - SLEEP_SET_HTIMER_DELAY_USEC) + SLEEP_SET_HTIMER_DELAY_USEC) return 0; /* @@ -434,7 +437,7 @@ static int clock_allow_low_power_idle(void) */ sleep_mode_t0 = get_time(); if ((sleep_mode_t0.le.lo > (0xffffffff - SLEEP_FTIMER_SKIP_USEC)) || - (sleep_mode_t0.le.lo < SLEEP_FTIMER_SKIP_USEC)) + (sleep_mode_t0.le.lo < SLEEP_FTIMER_SKIP_USEC)) return 0; /* If we are waked up by console, then keep awake at least 5s. */ @@ -449,7 +452,7 @@ int clock_ec_wake_from_sleep(void) return ec_sleep; } -void clock_cpu_standby(void) +void __ram_code clock_cpu_standby(void) { /* standby instruction */ if (IS_ENABLED(CHIP_CORE_NDS32)) { @@ -533,7 +536,7 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds) /* EC sleep */ ec_sleep = 1; #if defined(IT83XX_ESPI_INHIBIT_CS_BY_PAD_DISABLED) && \ -defined(CONFIG_HOSTCMD_ESPI) + defined(CONFIG_HOST_INTERFACE_ESPI) /* Disable eSPI pad. */ espi_enable_pad(0); #endif @@ -546,14 +549,20 @@ defined(CONFIG_HOSTCMD_ESPI) __builtin_unreachable(); } +/* use data type int here not bool to get better instruction number. */ +static volatile int wait_interrupt_fired; void clock_sleep_mode_wakeup_isr(void) { uint32_t st_us, c; + /* Clear flag on each interrupt. */ + if (IS_ENABLED(CHIP_CORE_RISCV)) + wait_interrupt_fired = 0; + /* trigger a reboot if wake up EC from sleep mode (system hibernate) */ if (clock_ec_wake_from_sleep()) { #if defined(IT83XX_ESPI_INHIBIT_CS_BY_PAD_DISABLED) && \ -defined(CONFIG_HOSTCMD_ESPI) + defined(CONFIG_HOST_INTERFACE_ESPI) /* * Enable eSPI pad. * We will not need to enable eSPI pad here if Dx is able to @@ -571,9 +580,9 @@ defined(CONFIG_HOSTCMD_ESPI) if (IT83XX_ECPM_PLLCTRL == EC_PLL_DEEP_DOZE) { clock_ec_pll_ctrl(EC_PLL_DOZE); - /* update free running timer */ - c = 0xffffffff - IT83XX_ETWD_ETXCNTOR(LOW_POWER_EXT_TIMER); + c = LOW_POWER_TIMER_MASK - + IT83XX_ETWD_ETXCNTOR(LOW_POWER_EXT_TIMER); st_us = TIMER_32P768K_CNT_TO_US(c); sleep_mode_t1.val = sleep_mode_t0.val + st_us; __hw_clock_source_set(sleep_mode_t1.le.lo); @@ -595,15 +604,12 @@ defined(CONFIG_HOSTCMD_ESPI) } } -/** - * Low power idle task. Executed when no tasks are ready to be scheduled. - */ -void __idle(void) +void __keep __idle_init(void) { console_expire_time.val = get_time().val + CONSOLE_IN_USE_ON_BOOT_TIME; /* init hw timer and clock source is 32.768 KHz */ - ext_timer_ms(LOW_POWER_EXT_TIMER, EXT_PSR_32P768K_HZ, 1, 0, - 0xffffffff, 1, 1); + ext_timer_ms(LOW_POWER_EXT_TIMER, EXT_PSR_32P768K_HZ, 1, 0, 0xffffffff, + 1, 1); /* * Print when the idle task starts. This is the lowest priority task, @@ -611,10 +617,28 @@ void __idle(void) * their task inits and have gone to sleep. */ CPRINTS("low power idle task started"); +} + +/** + * Low power idle task. Executed when no tasks are ready to be scheduled. + */ +void __ram_code __idle(void) +{ + /* + * There is not enough space from ram code section to cache entire idle + * function, hence pull initialization function out of the section. + */ + __idle_init(); while (1) { /* Disable interrupts */ interrupt_disable(); +#ifdef CONFIG_IT83XX_I2C_CMD_QUEUE + if (i2c_idle_not_allowed()) { + interrupt_enable(); + continue; + } +#endif /* Check if the EC can enter deep doze mode or not */ if (DEEP_SLEEP_ALLOWED && clock_allow_low_power_idle()) { /* reset low power mode hw timer */ @@ -636,8 +660,21 @@ void __idle(void) clock_ec_pll_ctrl(EC_PLL_DOZE); idle_doze_cnt++; } + /* Set flag before entering low power mode. */ + if (IS_ENABLED(CHIP_CORE_RISCV)) + wait_interrupt_fired = 1; clock_cpu_standby(); interrupt_enable(); + /* + * Sometimes wfi instruction may fail due to CPU's MTIP@mip + * register is non-zero. + * If the wait_interrupt_fired flag is true at this point, + * it means that EC waked-up by the above issue not an + * interrupt. Hence we loop running wfi instruction here until + * wfi success. + */ + while (IS_ENABLED(CHIP_CORE_RISCV) && wait_interrupt_fired) + clock_cpu_standby(); } } #endif /* CONFIG_LOW_POWER_IDLE */ @@ -647,7 +684,7 @@ void __idle(void) /** * Print low power idle statistics */ -static int command_idle_stats(int argc, char **argv) +static int command_idle_stats(int argc, const char **argv) { timestamp_t ts = get_time(); @@ -655,13 +692,16 @@ static int command_idle_stats(int argc, char **argv) ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); ccprintf("Total Time spent in sleep(sec): %.6lld(s)\n", - total_idle_sleep_time_us); + total_idle_sleep_time_us); ccprintf("Total time on: %.6llds\n\n", ts.val); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, - "", +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", "Print last idle stats"); #endif /* CONFIG_CMD_IDLE_STATS */ #endif /* CONFIG_LOW_POWER_IDLE */ + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/it83xx/config_chip.h b/chip/it83xx/config_chip.h index 2cc683ba20..537069972f 100644 --- a/chip/it83xx/config_chip.h +++ b/chip/it83xx/config_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,7 @@ #ifndef __CROS_EC_CONFIG_CHIP_H #define __CROS_EC_CONFIG_CHIP_H -#if defined(CHIP_FAMILY_IT8320) /* N8 core */ +#if defined(CHIP_FAMILY_IT8320) /* N8 core */ #include "config_chip_it8320.h" #elif defined(CHIP_FAMILY_IT8XXX2) /* RISCV core */ #include "config_chip_it8xxx2.h" @@ -19,7 +19,7 @@ /* Interval between HOOK_TICK notifications */ #define HOOK_TICK_INTERVAL_MS 500 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) +#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) /* Default PLL frequency. */ #define PLL_CLOCK 48000000 @@ -35,34 +35,34 @@ #define I2C_ENHANCED_PORT_COUNT 3 /* System stack size */ -#define CONFIG_STACK_SIZE 1024 +#define CONFIG_STACK_SIZE 1024 /* non-standard task stack sizes */ -#define SMALLER_TASK_STACK_SIZE (384 + CHIP_EXTRA_STACK_SPACE) -#define IDLE_TASK_STACK_SIZE (512 + CHIP_EXTRA_STACK_SPACE) -#define LARGER_TASK_STACK_SIZE (768 + CHIP_EXTRA_STACK_SPACE) -#define VENTI_TASK_STACK_SIZE (896 + CHIP_EXTRA_STACK_SPACE) -#define ULTRA_TASK_STACK_SIZE (1056 + CHIP_EXTRA_STACK_SPACE) -#define TRENTA_TASK_STACK_SIZE (1184 + CHIP_EXTRA_STACK_SPACE) +#define SMALLER_TASK_STACK_SIZE (384 + CHIP_EXTRA_STACK_SPACE) +#define IDLE_TASK_STACK_SIZE (512 + CHIP_EXTRA_STACK_SPACE) +#define LARGER_TASK_STACK_SIZE (768 + CHIP_EXTRA_STACK_SPACE) +#define VENTI_TASK_STACK_SIZE (896 + CHIP_EXTRA_STACK_SPACE) +#define ULTRA_TASK_STACK_SIZE (1056 + CHIP_EXTRA_STACK_SPACE) +#define TRENTA_TASK_STACK_SIZE (1184 + CHIP_EXTRA_STACK_SPACE) /* Default task stack size */ -#define TASK_STACK_SIZE (512 + CHIP_EXTRA_STACK_SPACE) +#define TASK_STACK_SIZE (512 + CHIP_EXTRA_STACK_SPACE) #ifdef IT83XX_CHIP_FLASH_IS_KGD -#define CONFIG_FLASH_BANK_SIZE 0x00001000 /* protect bank size */ -#define CONFIG_FLASH_ERASE_SIZE 0x00001000 /* erase bank size */ +#define CONFIG_FLASH_BANK_SIZE 0x00001000 /* protect bank size */ +#define CONFIG_FLASH_ERASE_SIZE 0x00001000 /* erase bank size */ #else -#define CONFIG_FLASH_BANK_SIZE 0x00000800 /* protect bank size */ -#define CONFIG_FLASH_ERASE_SIZE 0x00000400 /* erase bank size */ +#define CONFIG_FLASH_BANK_SIZE 0x00000800 /* protect bank size */ +#define CONFIG_FLASH_ERASE_SIZE 0x00000400 /* erase bank size */ #endif -#define CONFIG_FLASH_WRITE_SIZE 0x00000004 /* minimum write size */ +#define CONFIG_FLASH_WRITE_SIZE 0x00000004 /* minimum write size */ /* * This is the block size of the ILM on the it83xx chip. * The ILM for static code cache, CPU fetch instruction from * ILM(ILM -> CPU)instead of flash(flash -> IMMU -> CPU) if enabled. */ -#define IT83XX_ILM_BLOCK_SIZE 0x00001000 +#define IT83XX_ILM_BLOCK_SIZE 0x00001000 #ifdef IT83XX_CHIP_FLASH_IS_KGD /* @@ -101,9 +101,9 @@ * IT8xxx2 series support mapping LPC/eSPI I/O cycle 800h ~ 9FFh * to 0x80081800 ~ 0x800819FF of DLM1. */ -#define CONFIG_H2RAM_BASE (CHIP_H2RAM_BASE) -#define CONFIG_H2RAM_SIZE 0x00001000 -#define CONFIG_H2RAM_HOST_LPC_IO_BASE 0x800 +#define CONFIG_H2RAM_BASE (CHIP_H2RAM_BASE) +#define CONFIG_H2RAM_SIZE 0x00001000 +#define CONFIG_H2RAM_HOST_LPC_IO_BASE 0x800 /****************************************************************************/ /* Customize the build */ @@ -121,4 +121,6 @@ #define GPIO_PIN(port, index) GPIO_##port, BIT(index) #define GPIO_PIN_MASK(p, m) .port = GPIO_##p, .mask = (m) -#endif /* __CROS_EC_CONFIG_CHIP_H */ +#define __RAM_CODE_SECTION_NAME ".ram_code" + +#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/it83xx/config_chip_it8320.h b/chip/it83xx/config_chip_it8320.h index 6163ef8fb9..0e5c48c96a 100644 --- a/chip/it83xx/config_chip_it8320.h +++ b/chip/it83xx/config_chip_it8320.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,19 +12,19 @@ /* N8 core */ #define CHIP_CORE_NDS32 /* The base address of EC interrupt controller registers. */ -#define CHIP_EC_INTC_BASE 0x00F01100 +#define CHIP_EC_INTC_BASE 0x00F01100 /****************************************************************************/ /* Memory mapping */ -#define CHIP_H2RAM_BASE 0x0008D000 /* 0x0008D000~0x0008DFFF */ -#define CHIP_RAMCODE_BASE 0x0008E000 /* 0x0008E000~0x0008EFFF */ -#define CHIP_EXTRA_STACK_SPACE 0 +#define CHIP_H2RAM_BASE 0x0008D000 /* 0x0008D000~0x0008DFFF */ +#define CHIP_RAMCODE_BASE 0x0008E000 /* 0x0008E000~0x0008EFFF */ +#define CHIP_EXTRA_STACK_SPACE 0 -#define CONFIG_RAM_BASE 0x00080000 -#define CONFIG_RAM_SIZE 0x0000C000 +#define CONFIG_RAM_BASE 0x00080000 +#define CONFIG_RAM_SIZE 0x0000C000 -#define CONFIG_PROGRAM_MEMORY_BASE 0x00000000 +#define CONFIG_PROGRAM_MEMORY_BASE 0x00000000 /****************************************************************************/ /* Chip IT8320 is used with IT83XX TCPM driver */ @@ -36,7 +36,7 @@ * doesn't support a write-protect pin, and if we make the write-protection * permanent, it can't be undone easily enough to support RMA. */ -#define CONFIG_FLASH_SIZE 0x00040000 +#define CONFIG_FLASH_SIZE_BYTES 0x00040000 /* For IT8320BX, we have to reload cc parameters after ec softreset. */ #define IT83XX_USBPD_CC_PARAMETER_RELOAD /* @@ -45,7 +45,7 @@ */ #define IT83XX_USBPD_CC_VOLTAGE_DETECTOR_INDEPENDENT /* Chip IT8320BX actually has TCPC physical port count */ -#define IT83XX_USBPD_PHY_PORT_COUNT 2 +#define IT83XX_USBPD_PHY_PORT_COUNT 2 /* For IT8320BX, we have to write 0xff to clear pending bit.*/ #define IT83XX_ESPI_VWCTRL1_WRITE_FF_CLEAR /* For IT8320BX, we have to read observation register of external timer two @@ -53,15 +53,18 @@ */ #define IT83XX_EXT_OBSERVATION_REG_READ_TWO_TIMES #elif defined(CHIP_VARIANT_IT8320DX) -#define CONFIG_FLASH_SIZE 0x00080000 +#define CONFIG_FLASH_SIZE_BYTES 0x00080000 #define CONFIG_IT83XX_FLASH_CLOCK_48MHZ /* * Disable eSPI pad, then PLL change * (include EC clock frequency) is succeed even CS# is low. */ #define IT83XX_ESPI_INHIBIT_CS_BY_PAD_DISABLED -/* The slave frequency is adjustable (bit[2-0] at register IT83XX_ESPI_GCAC1) */ -#define IT83XX_ESPI_SLAVE_MAX_FREQ_CONFIGURABLE +/* + * The peripheral frequency is adjustable + * (bit[2-0] at register IT83XX_ESPI_GCAC1) + */ +#define IT83XX_ESPI_PERIPHERAL_MAX_FREQ_CONFIGURABLE /* * TODO(b/111480168): eSPI HW reset can't be used because the DMA address * gets set incorrectly resulting in a memory access exception. @@ -93,9 +96,9 @@ /* Chip Dx transmit status bit of PD register is different from Bx. */ #define IT83XX_PD_TX_ERROR_STATUS_BIT5 /* Chip IT8320DX actually has TCPC physical port count */ -#define IT83XX_USBPD_PHY_PORT_COUNT 2 +#define IT83XX_USBPD_PHY_PORT_COUNT 2 #else #error "Unsupported chip variant!" #endif -#endif /* __CROS_EC_CONFIG_CHIP_IT8320_H */ +#endif /* __CROS_EC_CONFIG_CHIP_IT8320_H */ diff --git a/chip/it83xx/config_chip_it8xxx2.h b/chip/it83xx/config_chip_it8xxx2.h index fd7d4e94dd..cbbbd0bd55 100644 --- a/chip/it83xx/config_chip_it8xxx2.h +++ b/chip/it83xx/config_chip_it8xxx2.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,8 @@ #ifndef __CROS_EC_CONFIG_CHIP_IT8XXX2_H #define __CROS_EC_CONFIG_CHIP_IT8XXX2_H +#define __RAM_CODE_ILM0_SECTION_NAME ".ram_code_ilm0" + /* CPU core BFD configuration */ #include "core/riscv-rv32i/config_core.h" @@ -13,7 +15,7 @@ #define CHIP_CORE_RISCV #define CHIP_ILM_DLM_ORDER /* The base address of EC interrupt controller registers. */ -#define CHIP_EC_INTC_BASE 0x00F03F00 +#define CHIP_EC_INTC_BASE 0x00F03F00 #define CONFIG_IT83XX_FLASH_CLOCK_48MHZ /* * ILM/DLM size register. @@ -25,11 +27,11 @@ /****************************************************************************/ /* Memory mapping */ -#define CHIP_ILM_BASE 0x80000000 -#define CHIP_EXTRA_STACK_SPACE 128 +#define CHIP_ILM_BASE 0x80000000 +#define CHIP_EXTRA_STACK_SPACE 128 /* We reserve 12KB space for ramcode, h2ram, and immu sections. */ -#define CHIP_RAM_SPACE_RESERVED 0x3000 -#define CONFIG_PROGRAM_MEMORY_BASE (CHIP_ILM_BASE) +#define CHIP_RAM_SPACE_RESERVED 0x3000 +#define CONFIG_PROGRAM_MEMORY_BASE (CHIP_ILM_BASE) /****************************************************************************/ /* Chip IT83202 is used with IT8XXX2 TCPM driver */ @@ -37,9 +39,9 @@ #if defined(CHIP_VARIANT_IT83202BX) /* TODO(b/133460224): enable properly chip config option. */ -#define CONFIG_FLASH_SIZE 0x00080000 -#define CONFIG_RAM_BASE 0x80080000 -#define CONFIG_RAM_SIZE 0x00010000 +#define CONFIG_FLASH_SIZE_BYTES 0x00080000 +#define CONFIG_RAM_BASE 0x80080000 +#define CONFIG_RAM_SIZE 0x00010000 /* Embedded flash is KGD */ #define IT83XX_CHIP_FLASH_IS_KGD @@ -57,8 +59,11 @@ * (include EC clock frequency) is succeed even CS# is low. */ #define IT83XX_ESPI_INHIBIT_CS_BY_PAD_DISABLED -/* The slave frequency is adjustable (bit[2-0] at register IT83XX_ESPI_GCAC1) */ -#define IT83XX_ESPI_SLAVE_MAX_FREQ_CONFIGURABLE +/* + * The peripheral frequency is adjustable + * (bit[2-0] at register IT83XX_ESPI_GCAC1) + */ +#define IT83XX_ESPI_PERIPHERAL_MAX_FREQ_CONFIGURABLE /* Watchdog reset supports hardware reset. */ #define IT83XX_ETWD_HW_RESET_SUPPORT /* @@ -75,17 +80,34 @@ /* Enable detect type-c plug in and out interrupt. */ #define IT83XX_INTC_PLUG_IN_OUT_SUPPORT /* Chip IT83202BX actually has TCPC physical port count. */ -#define IT83XX_USBPD_PHY_PORT_COUNT 3 -#elif defined(CHIP_VARIANT_IT81302AX_1024) \ -|| defined(CHIP_VARIANT_IT81202AX_1024) -#define CONFIG_FLASH_SIZE 0x00100000 -#define CONFIG_RAM_BASE 0x80100000 -#define CONFIG_RAM_SIZE 0x0000f000 +#define IT83XX_USBPD_PHY_PORT_COUNT 3 +#elif defined(CHIP_VARIANT_IT81302AX_1024) || \ + defined(CHIP_VARIANT_IT81202AX_1024) || \ + defined(CHIP_VARIANT_IT81302BX_1024) || \ + defined(CHIP_VARIANT_IT81302BX_512) || \ + defined(CHIP_VARIANT_IT81202BX_1024) -/* Embedded flash is KGD */ -#define IT83XX_CHIP_FLASH_IS_KGD +/* + * Workaround mul instruction bug, see: + * https://www.ite.com.tw/uploads/product_download/it81202-bx-chip-errata.pdf + */ +#undef CONFIG_RISCV_EXTENSION_M +#define CONFIG_IT8XXX2_MUL_WORKAROUND + +#if defined(CHIP_VARIANT_IT81302BX_512) +#define CONFIG_FLASH_SIZE_BYTES 0x00080000 +#define CONFIG_RAM_BASE 0x80080000 +#else +#define CONFIG_FLASH_SIZE_BYTES 0x00100000 +#define CONFIG_RAM_BASE 0x80100000 /* Set ILM (instruction local memory) size up to 1M bytes */ #define IT83XX_CHIP_FLASH_SIZE_1MB +#endif + +#define CONFIG_RAM_SIZE 0x0000f000 + +/* Embedded flash is KGD */ +#define IT83XX_CHIP_FLASH_IS_KGD /* chip id is 3 bytes */ #define IT83XX_CHIP_ID_3BYTES /* @@ -98,8 +120,11 @@ * (include EC clock frequency) is succeed even CS# is low. */ #define IT83XX_ESPI_INHIBIT_CS_BY_PAD_DISABLED -/* The slave frequency is adjustable (bit[2-0] at register IT83XX_ESPI_GCAC1) */ -#define IT83XX_ESPI_SLAVE_MAX_FREQ_CONFIGURABLE +/* + * The peripheral frequency is adjustable + * (bit[2-0] at register IT83XX_ESPI_GCAC1) + */ +#define IT83XX_ESPI_PERIPHERAL_MAX_FREQ_CONFIGURABLE /* Watchdog reset supports hardware reset. */ #define IT83XX_ETWD_HW_RESET_SUPPORT /* @@ -107,7 +132,7 @@ * Please refer to gpio_1p8v_sel[] for 1.8v GPIOs. */ #define IT83XX_GPIO_1P8V_PIN_EXTENDED -#ifdef CHIP_VARIANT_IT81202AX_1024 +#if defined(CHIP_VARIANT_IT81202AX_1024) || defined(CHIP_VARIANT_IT81202BX_1024) /* Pins of group K and L are set as internal pull-down at initialization. */ #define IT83XX_GPIO_GROUP_K_L_DEFAULT_PULL_DOWN #endif @@ -123,19 +148,31 @@ #define IT83XX_INTC_PLUG_IN_OUT_SUPPORT /* Wake up CPU from low power mode even if interrupts are disabled */ #define IT83XX_RISCV_WAKEUP_CPU_WITHOUT_INT_ENABLED -/* Auto reset rx fifo while CS# deasserted. */ -#define IT83XX_SPI_AUTO_RESET_RX_FIFO -/* CPU accesses FIFO to reach rx valid data length. */ -#define IT83XX_SPI_RX_VALID_INT /* Individual setting CC1 and CC2 resistance. */ #define IT83XX_USBPD_CC1_CC2_RESISTANCE_SEPARATE /* Chip actually has TCPC physical port count. */ -#define IT83XX_USBPD_PHY_PORT_COUNT 2 +#define IT83XX_USBPD_PHY_PORT_COUNT 2 #else #error "Unsupported chip variant!" #endif -#define CHIP_H2RAM_BASE (CONFIG_RAM_BASE + 0x1000) /* base+1000h~base+1FFF */ -#define CHIP_RAMCODE_BASE (CONFIG_RAM_BASE + 0x2000) /* base+2000h~base+2FFF */ +#define CHIP_RAMCODE_ILM0 (CONFIG_RAM_BASE + 0) /* base+0000h~base+0FFF */ +#define CHIP_H2RAM_BASE (CONFIG_RAM_BASE + 0x1000) /* base+1000h~base+1FFF */ +#define CHIP_RAMCODE_BASE \ + (CONFIG_RAM_BASE + 0x2000) /* base+2000h~base+2FFF \ + */ + +#ifdef BASEBOARD_KUKUI +/* + * Reserved 0x80000~0xfffff 512kb on flash for saving EC logs (8kb space is + * enough to save the logs). This configuration reduces EC FW binary size to + * 512kb. With this config, we still have 4x kb space on RO and 6x kb space on + * RW. + */ +#define CHIP_FLASH_PRESERVE_LOGS_BASE 0x80000 +#define CHIP_FLASH_PRESERVE_LOGS_SIZE 0x2000 +#undef CONFIG_FLASH_SIZE_BYTES +#define CONFIG_FLASH_SIZE_BYTES CHIP_FLASH_PRESERVE_LOGS_BASE +#endif -#endif /* __CROS_EC_CONFIG_CHIP_IT8XXX2_H */ +#endif /* __CROS_EC_CONFIG_CHIP_IT8XXX2_H */ diff --git a/chip/it83xx/dac.c b/chip/it83xx/dac.c index 695d1cbc68..2e563f7557 100644 --- a/chip/it83xx/dac.c +++ b/chip/it83xx/dac.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -44,7 +44,7 @@ static void dac_init(void) } DECLARE_HOOK(HOOK_INIT, dac_init, HOOK_PRIO_INIT_DAC); -static int command_dac(int argc, char **argv) +static int command_dac(int argc, const char **argv) { char *e; int ch, mv, rv; @@ -85,6 +85,5 @@ static int command_dac(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(dac, command_dac, - "[ch2-5] [0-3300mV]", +DECLARE_CONSOLE_COMMAND(dac, command_dac, "[ch2-5] [0-3300mV]", "Enable or disable(0mV) DAC output voltage."); diff --git a/chip/it83xx/dac_chip.h b/chip/it83xx/dac_chip.h index fa50769c85..07e44e2e79 100644 --- a/chip/it83xx/dac_chip.h +++ b/chip/it83xx/dac_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -55,4 +55,3 @@ void dac_set_output_voltage(enum chip_dac_channel ch, int mv); int dac_get_output_voltage(enum chip_dac_channel ch); #endif /* __CROS_EC_DAC_CHIP_H */ - diff --git a/chip/it83xx/ec2i.c b/chip/it83xx/ec2i.c index be02a8f813..52f96b95d7 100644 --- a/chip/it83xx/ec2i.c +++ b/chip/it83xx/ec2i.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,11 +16,11 @@ static const struct ec2i_t keyboard_settings[] = { /* Select logical device 06h(keyboard) */ - {HOST_INDEX_LDN, LDN_KBC_KEYBOARD}, + { HOST_INDEX_LDN, LDN_KBC_KEYBOARD }, /* Set IRQ=01h for logical device */ - {HOST_INDEX_IRQNUMX, 0x01}, - /* Configure IRQTP for KBC. */ -#ifdef CONFIG_HOSTCMD_ESPI + { HOST_INDEX_IRQNUMX, 0x01 }, +/* Configure IRQTP for KBC. */ +#ifdef CONFIG_HOST_INTERFACE_ESPI /* * Interrupt request type select (IRQTP) for KBC. * bit 1, 0: IRQ request is buffered and applied to SERIRQ @@ -39,55 +39,55 @@ static const struct ec2i_t keyboard_settings[] = { * Additionally, this interrupt is configured as edge-triggered on the * host side. So, match the trigger mode on the EC side as well. */ - {HOST_INDEX_IRQTP, 0x02}, + { HOST_INDEX_IRQTP, 0x02 }, #endif /* Enable logical device */ - {HOST_INDEX_LDA, 0x01}, + { HOST_INDEX_LDA, 0x01 }, }; #ifdef CONFIG_IT83XX_ENABLE_MOUSE_DEVICE static const struct ec2i_t mouse_settings[] = { /* Select logical device 05h(mouse) */ - {HOST_INDEX_LDN, LDN_KBC_MOUSE}, + { HOST_INDEX_LDN, LDN_KBC_MOUSE }, /* Set IRQ=0Ch for logical device */ - {HOST_INDEX_IRQNUMX, 0x0C}, + { HOST_INDEX_IRQNUMX, 0x0C }, /* Enable logical device */ - {HOST_INDEX_LDA, 0x01}, + { HOST_INDEX_LDA, 0x01 }, }; #endif static const struct ec2i_t pm1_settings[] = { /* Select logical device 11h(PM1 ACPI) */ - {HOST_INDEX_LDN, LDN_PMC1}, + { HOST_INDEX_LDN, LDN_PMC1 }, /* Set IRQ=00h for logical device */ - {HOST_INDEX_IRQNUMX, 0x00}, + { HOST_INDEX_IRQNUMX, 0x00 }, /* Enable logical device */ - {HOST_INDEX_LDA, 0x01}, + { HOST_INDEX_LDA, 0x01 }, }; static const struct ec2i_t pm2_settings[] = { /* Select logical device 12h(PM2) */ - {HOST_INDEX_LDN, LDN_PMC2}, + { HOST_INDEX_LDN, LDN_PMC2 }, /* I/O Port Base Address 200h/204h */ - {HOST_INDEX_IOBAD0_MSB, 0x02}, - {HOST_INDEX_IOBAD0_LSB, 0x00}, - {HOST_INDEX_IOBAD1_MSB, 0x02}, - {HOST_INDEX_IOBAD1_LSB, 0x04}, + { HOST_INDEX_IOBAD0_MSB, 0x02 }, + { HOST_INDEX_IOBAD0_LSB, 0x00 }, + { HOST_INDEX_IOBAD1_MSB, 0x02 }, + { HOST_INDEX_IOBAD1_LSB, 0x04 }, /* Set IRQ=00h for logical device */ - {HOST_INDEX_IRQNUMX, 0x00}, + { HOST_INDEX_IRQNUMX, 0x00 }, /* Enable logical device */ - {HOST_INDEX_LDA, 0x01}, + { HOST_INDEX_LDA, 0x01 }, }; static const struct ec2i_t smfi_settings[] = { /* Select logical device 0Fh(SMFI) */ - {HOST_INDEX_LDN, LDN_SMFI}, + { HOST_INDEX_LDN, LDN_SMFI }, /* H2RAM LPC I/O cycle Dxxx */ - {HOST_INDEX_DSLDC6, 0x00}, + { HOST_INDEX_DSLDC6, 0x00 }, /* Enable H2RAM LPC I/O cycle */ - {HOST_INDEX_DSLDC7, 0x01}, + { HOST_INDEX_DSLDC7, 0x01 }, /* Enable logical device */ - {HOST_INDEX_LDA, 0x01}, + { HOST_INDEX_LDA, 0x01 }, }; /* @@ -96,16 +96,16 @@ static const struct ec2i_t smfi_settings[] = { */ static const struct ec2i_t pm3_settings[] = { /* Select logical device 17h(PM3) */ - {HOST_INDEX_LDN, LDN_PMC3}, + { HOST_INDEX_LDN, LDN_PMC3 }, /* I/O Port Base Address 80h */ - {HOST_INDEX_IOBAD0_MSB, 0x00}, - {HOST_INDEX_IOBAD0_LSB, 0x80}, - {HOST_INDEX_IOBAD1_MSB, 0x00}, - {HOST_INDEX_IOBAD1_LSB, 0x00}, + { HOST_INDEX_IOBAD0_MSB, 0x00 }, + { HOST_INDEX_IOBAD0_LSB, 0x80 }, + { HOST_INDEX_IOBAD1_MSB, 0x00 }, + { HOST_INDEX_IOBAD1_LSB, 0x00 }, /* Set IRQ=00h for logical device */ - {HOST_INDEX_IRQNUMX, 0x00}, + { HOST_INDEX_IRQNUMX, 0x00 }, /* Enable logical device */ - {HOST_INDEX_LDA, 0x01}, + { HOST_INDEX_LDA, 0x01 }, }; /* @@ -115,28 +115,28 @@ static const struct ec2i_t pm3_settings[] = { */ static const struct ec2i_t rtct_settings[] = { /* Select logical device 10h(RTCT) */ - {HOST_INDEX_LDN, LDN_RTCT}, + { HOST_INDEX_LDN, LDN_RTCT }, /* P80L Begin Index */ - {HOST_INDEX_DSLDC4, P80L_P80LB}, + { HOST_INDEX_DSLDC4, P80L_P80LB }, /* P80L End Index */ - {HOST_INDEX_DSLDC5, P80L_P80LE}, + { HOST_INDEX_DSLDC5, P80L_P80LE }, /* P80L Current Index */ - {HOST_INDEX_DSLDC6, P80L_P80LC}, + { HOST_INDEX_DSLDC6, P80L_P80LC }, }; #ifdef CONFIG_UART_HOST static const struct ec2i_t uart2_settings[] = { /* Select logical device 2h(UART2) */ - {HOST_INDEX_LDN, LDN_UART2}, + { HOST_INDEX_LDN, LDN_UART2 }, /* * I/O port base address is 2F8h. * Host can use LPC I/O port 0x2F8 ~ 0x2FF to access UART2. * See specification 7.24.4 for more detial. */ - {HOST_INDEX_IOBAD0_MSB, 0x02}, - {HOST_INDEX_IOBAD0_LSB, 0xF8}, + { HOST_INDEX_IOBAD0_MSB, 0x02 }, + { HOST_INDEX_IOBAD0_LSB, 0xF8 }, /* IRQ number is 3 */ - {HOST_INDEX_IRQNUMX, 0x03}, + { HOST_INDEX_IRQNUMX, 0x03 }, /* * Interrupt Request Type Select * bit1, 0: IRQ request is buffered and applied to SERIRQ. @@ -144,9 +144,9 @@ static const struct ec2i_t uart2_settings[] = { * bit0, 0: Edge triggered mode. * 1: Level triggered mode. */ - {HOST_INDEX_IRQTP, 0x02}, + { HOST_INDEX_IRQTP, 0x02 }, /* Enable logical device */ - {HOST_INDEX_LDA, 0x01}, + { HOST_INDEX_LDA, 0x01 }, }; #endif @@ -163,7 +163,7 @@ enum ec2i_status_mask { EC2I_STATUS_CRIB = BIT(1), /* 1: EC write-access is still processing with IHD register. */ EC2I_STATUS_CWIB = BIT(2), - EC2I_STATUS_ALL = (EC2I_STATUS_CRIB | EC2I_STATUS_CWIB), + EC2I_STATUS_ALL = (EC2I_STATUS_CRIB | EC2I_STATUS_CWIB), }; static int ec2i_wait_status_bit_cleared(enum ec2i_status_mask mask) @@ -288,8 +288,7 @@ static void pnpcfg_configure(const struct ec2i_t *settings, size_t entries) } } -#define PNPCFG(_s) \ - pnpcfg_configure(_s##_settings, ARRAY_SIZE(_s##_settings)) +#define PNPCFG(_s) pnpcfg_configure(_s##_settings, ARRAY_SIZE(_s##_settings)) static void pnpcfg_init(void) { diff --git a/chip/it83xx/ec2i_chip.h b/chip/it83xx/ec2i_chip.h index c8069f4ff5..73eeaa31f7 100644 --- a/chip/it83xx/ec2i_chip.h +++ b/chip/it83xx/ec2i_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,9 +8,9 @@ #ifndef __CROS_EC_EC2I_CHIP_H #define __CROS_EC_EC2I_CHIP_H -#define P80L_P80LB 0 -#define P80L_P80LE 0x3F -#define P80L_P80LC 0 +#define P80L_P80LB 0 +#define P80L_P80LE 0x3F +#define P80L_P80LC 0 #define P80L_BRAM_BANK1_SIZE_MASK 0x3F /* Index list of the host interface registers of PNPCFG */ diff --git a/chip/it83xx/espi.c b/chip/it83xx/espi.c index c731a7ad7e..f59f3728bf 100644 --- a/chip/it83xx/espi.c +++ b/chip/it83xx/espi.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,161 +7,131 @@ #include "console.h" #include "espi.h" +#include "gpio.h" #include "hooks.h" #include "port80.h" #include "power.h" #include "registers.h" #include "system.h" +#include "system_boot_time.h" #include "task.h" #include "uart.h" #include "util.h" /* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) struct vw_channel_t { - uint8_t index; /* VW index of signal */ - uint8_t level_mask; /* level bit of signal */ - uint8_t valid_mask; /* valid bit of signal */ + uint8_t index; /* VW index of signal */ + uint8_t level_mask; /* level bit of signal */ + uint8_t valid_mask; /* valid bit of signal */ }; -/* VW settings after the master enables the VW channel. */ +/* VW settings after the controller enables the VW channel. */ static const struct vw_channel_t en_vw_setting[] = { - /* EC sends SUS_ACK# = 1 VW to PCH. That does not apply to GLK SoC. */ +/* EC sends SUS_ACK# = 1 VW to PCH. That does not apply to GLK SoC. */ #ifndef CONFIG_CHIPSET_GEMINILAKE - {ESPI_SYSTEM_EVENT_VW_IDX_40, - VW_LEVEL_FIELD(0), - VW_VALID_FIELD(VW_IDX_40_SUS_ACK)}, + { ESPI_SYSTEM_EVENT_VW_IDX_40, VW_LEVEL_FIELD(0), + VW_VALID_FIELD(VW_IDX_40_SUS_ACK) }, #endif }; -/* VW settings after the master enables the OOB channel. */ +/* VW settings after the controller enables the OOB channel. */ static const struct vw_channel_t en_oob_setting[] = { - {ESPI_SYSTEM_EVENT_VW_IDX_4, - VW_LEVEL_FIELD(0), - VW_VALID_FIELD(VW_IDX_4_OOB_RST_ACK)}, + { ESPI_SYSTEM_EVENT_VW_IDX_4, VW_LEVEL_FIELD(0), + VW_VALID_FIELD(VW_IDX_4_OOB_RST_ACK) }, }; -/* VW settings after the master enables the flash channel. */ +/* VW settings after the controller enables the flash channel. */ static const struct vw_channel_t en_flash_setting[] = { - {ESPI_SYSTEM_EVENT_VW_IDX_5, - VW_LEVEL_FIELD(VW_IDX_5_BTLD_STATUS_DONE), - VW_VALID_FIELD(VW_IDX_5_BTLD_STATUS_DONE)}, + { ESPI_SYSTEM_EVENT_VW_IDX_5, VW_LEVEL_FIELD(VW_IDX_5_BTLD_STATUS_DONE), + VW_VALID_FIELD(VW_IDX_5_BTLD_STATUS_DONE) }, }; /* VW settings at host startup */ static const struct vw_channel_t vw_host_startup_setting[] = { - {ESPI_SYSTEM_EVENT_VW_IDX_6, - VW_LEVEL_FIELD(VW_IDX_6_SCI | VW_IDX_6_SMI | - VW_IDX_6_RCIN | VW_IDX_6_HOST_RST_ACK), - VW_VALID_FIELD(VW_IDX_6_SCI | VW_IDX_6_SMI | - VW_IDX_6_RCIN | VW_IDX_6_HOST_RST_ACK)}, + { ESPI_SYSTEM_EVENT_VW_IDX_6, + VW_LEVEL_FIELD(VW_IDX_6_SCI | VW_IDX_6_SMI | VW_IDX_6_RCIN | + VW_IDX_6_HOST_RST_ACK), + VW_VALID_FIELD(VW_IDX_6_SCI | VW_IDX_6_SMI | VW_IDX_6_RCIN | + VW_IDX_6_HOST_RST_ACK) }, }; #define VW_CHAN(name, idx, level, valid) \ - [(name - VW_SIGNAL_START)] = {idx, level, valid} + [(name - VW_SIGNAL_START)] = { idx, level, valid } /* VW signals used in eSPI (NOTE: must match order of enum espi_vw_signal). */ static const struct vw_channel_t vw_channel_list[] = { - /* index 02h: master to slave. */ - VW_CHAN(VW_SLP_S3_L, - ESPI_SYSTEM_EVENT_VW_IDX_2, + /* index 02h: controller to peripheral. */ + VW_CHAN(VW_SLP_S3_L, ESPI_SYSTEM_EVENT_VW_IDX_2, VW_LEVEL_FIELD(VW_IDX_2_SLP_S3), VW_VALID_FIELD(VW_IDX_2_SLP_S3)), - VW_CHAN(VW_SLP_S4_L, - ESPI_SYSTEM_EVENT_VW_IDX_2, + VW_CHAN(VW_SLP_S4_L, ESPI_SYSTEM_EVENT_VW_IDX_2, VW_LEVEL_FIELD(VW_IDX_2_SLP_S4), VW_VALID_FIELD(VW_IDX_2_SLP_S4)), - VW_CHAN(VW_SLP_S5_L, - ESPI_SYSTEM_EVENT_VW_IDX_2, + VW_CHAN(VW_SLP_S5_L, ESPI_SYSTEM_EVENT_VW_IDX_2, VW_LEVEL_FIELD(VW_IDX_2_SLP_S5), VW_VALID_FIELD(VW_IDX_2_SLP_S5)), - /* index 03h: master to slave. */ - VW_CHAN(VW_SUS_STAT_L, - ESPI_SYSTEM_EVENT_VW_IDX_3, + /* index 03h: controller to peripheral. */ + VW_CHAN(VW_SUS_STAT_L, ESPI_SYSTEM_EVENT_VW_IDX_3, VW_LEVEL_FIELD(VW_IDX_3_SUS_STAT), VW_VALID_FIELD(VW_IDX_3_SUS_STAT)), - VW_CHAN(VW_PLTRST_L, - ESPI_SYSTEM_EVENT_VW_IDX_3, + VW_CHAN(VW_PLTRST_L, ESPI_SYSTEM_EVENT_VW_IDX_3, VW_LEVEL_FIELD(VW_IDX_3_PLTRST), VW_VALID_FIELD(VW_IDX_3_PLTRST)), - VW_CHAN(VW_OOB_RST_WARN, - ESPI_SYSTEM_EVENT_VW_IDX_3, + VW_CHAN(VW_OOB_RST_WARN, ESPI_SYSTEM_EVENT_VW_IDX_3, VW_LEVEL_FIELD(VW_IDX_3_OOB_RST_WARN), VW_VALID_FIELD(VW_IDX_3_OOB_RST_WARN)), - /* index 04h: slave to master. */ - VW_CHAN(VW_OOB_RST_ACK, - ESPI_SYSTEM_EVENT_VW_IDX_4, + /* index 04h: peripheral to controller. */ + VW_CHAN(VW_OOB_RST_ACK, ESPI_SYSTEM_EVENT_VW_IDX_4, VW_LEVEL_FIELD(VW_IDX_4_OOB_RST_ACK), VW_VALID_FIELD(VW_IDX_4_OOB_RST_ACK)), - VW_CHAN(VW_WAKE_L, - ESPI_SYSTEM_EVENT_VW_IDX_4, - VW_LEVEL_FIELD(VW_IDX_4_WAKE), - VW_VALID_FIELD(VW_IDX_4_WAKE)), - VW_CHAN(VW_PME_L, - ESPI_SYSTEM_EVENT_VW_IDX_4, - VW_LEVEL_FIELD(VW_IDX_4_PME), - VW_VALID_FIELD(VW_IDX_4_PME)), - /* index 05h: slave to master. */ - VW_CHAN(VW_ERROR_FATAL, - ESPI_SYSTEM_EVENT_VW_IDX_5, - VW_LEVEL_FIELD(VW_IDX_5_FATAL), - VW_VALID_FIELD(VW_IDX_5_FATAL)), - VW_CHAN(VW_ERROR_NON_FATAL, - ESPI_SYSTEM_EVENT_VW_IDX_5, + VW_CHAN(VW_WAKE_L, ESPI_SYSTEM_EVENT_VW_IDX_4, + VW_LEVEL_FIELD(VW_IDX_4_WAKE), VW_VALID_FIELD(VW_IDX_4_WAKE)), + VW_CHAN(VW_PME_L, ESPI_SYSTEM_EVENT_VW_IDX_4, + VW_LEVEL_FIELD(VW_IDX_4_PME), VW_VALID_FIELD(VW_IDX_4_PME)), + /* index 05h: peripheral to controller. */ + VW_CHAN(VW_ERROR_FATAL, ESPI_SYSTEM_EVENT_VW_IDX_5, + VW_LEVEL_FIELD(VW_IDX_5_FATAL), VW_VALID_FIELD(VW_IDX_5_FATAL)), + VW_CHAN(VW_ERROR_NON_FATAL, ESPI_SYSTEM_EVENT_VW_IDX_5, VW_LEVEL_FIELD(VW_IDX_5_NON_FATAL), VW_VALID_FIELD(VW_IDX_5_NON_FATAL)), - VW_CHAN(VW_SLAVE_BTLD_STATUS_DONE, - ESPI_SYSTEM_EVENT_VW_IDX_5, + VW_CHAN(VW_PERIPHERAL_BTLD_STATUS_DONE, ESPI_SYSTEM_EVENT_VW_IDX_5, VW_LEVEL_FIELD(VW_IDX_5_BTLD_STATUS_DONE), VW_VALID_FIELD(VW_IDX_5_BTLD_STATUS_DONE)), - /* index 06h: slave to master. */ - VW_CHAN(VW_SCI_L, - ESPI_SYSTEM_EVENT_VW_IDX_6, - VW_LEVEL_FIELD(VW_IDX_6_SCI), - VW_VALID_FIELD(VW_IDX_6_SCI)), - VW_CHAN(VW_SMI_L, - ESPI_SYSTEM_EVENT_VW_IDX_6, - VW_LEVEL_FIELD(VW_IDX_6_SMI), - VW_VALID_FIELD(VW_IDX_6_SMI)), - VW_CHAN(VW_RCIN_L, - ESPI_SYSTEM_EVENT_VW_IDX_6, - VW_LEVEL_FIELD(VW_IDX_6_RCIN), - VW_VALID_FIELD(VW_IDX_6_RCIN)), - VW_CHAN(VW_HOST_RST_ACK, - ESPI_SYSTEM_EVENT_VW_IDX_6, + /* index 06h: peripheral to controller. */ + VW_CHAN(VW_SCI_L, ESPI_SYSTEM_EVENT_VW_IDX_6, + VW_LEVEL_FIELD(VW_IDX_6_SCI), VW_VALID_FIELD(VW_IDX_6_SCI)), + VW_CHAN(VW_SMI_L, ESPI_SYSTEM_EVENT_VW_IDX_6, + VW_LEVEL_FIELD(VW_IDX_6_SMI), VW_VALID_FIELD(VW_IDX_6_SMI)), + VW_CHAN(VW_RCIN_L, ESPI_SYSTEM_EVENT_VW_IDX_6, + VW_LEVEL_FIELD(VW_IDX_6_RCIN), VW_VALID_FIELD(VW_IDX_6_RCIN)), + VW_CHAN(VW_HOST_RST_ACK, ESPI_SYSTEM_EVENT_VW_IDX_6, VW_LEVEL_FIELD(VW_IDX_6_HOST_RST_ACK), VW_VALID_FIELD(VW_IDX_6_HOST_RST_ACK)), - /* index 07h: master to slave. */ - VW_CHAN(VW_HOST_RST_WARN, - ESPI_SYSTEM_EVENT_VW_IDX_7, + /* index 07h: controller to peripheral. */ + VW_CHAN(VW_HOST_RST_WARN, ESPI_SYSTEM_EVENT_VW_IDX_7, VW_LEVEL_FIELD(VW_IDX_7_HOST_RST_WARN), VW_VALID_FIELD(VW_IDX_7_HOST_RST_WARN)), - /* index 40h: slave to master. */ - VW_CHAN(VW_SUS_ACK, - ESPI_SYSTEM_EVENT_VW_IDX_40, + /* index 40h: peripheral to controller. */ + VW_CHAN(VW_SUS_ACK, ESPI_SYSTEM_EVENT_VW_IDX_40, VW_LEVEL_FIELD(VW_IDX_40_SUS_ACK), VW_VALID_FIELD(VW_IDX_40_SUS_ACK)), - /* index 41h: master to slave. */ - VW_CHAN(VW_SUS_WARN_L, - ESPI_SYSTEM_EVENT_VW_IDX_41, + /* index 41h: controller to peripheral. */ + VW_CHAN(VW_SUS_WARN_L, ESPI_SYSTEM_EVENT_VW_IDX_41, VW_LEVEL_FIELD(VW_IDX_41_SUS_WARN), VW_VALID_FIELD(VW_IDX_41_SUS_WARN)), - VW_CHAN(VW_SUS_PWRDN_ACK_L, - ESPI_SYSTEM_EVENT_VW_IDX_41, + VW_CHAN(VW_SUS_PWRDN_ACK_L, ESPI_SYSTEM_EVENT_VW_IDX_41, VW_LEVEL_FIELD(VW_IDX_41_SUS_PWRDN_ACK), VW_VALID_FIELD(VW_IDX_41_SUS_PWRDN_ACK)), - VW_CHAN(VW_SLP_A_L, - ESPI_SYSTEM_EVENT_VW_IDX_41, + VW_CHAN(VW_SLP_A_L, ESPI_SYSTEM_EVENT_VW_IDX_41, VW_LEVEL_FIELD(VW_IDX_41_SLP_A), VW_VALID_FIELD(VW_IDX_41_SLP_A)), - /* index 42h: master to slave. */ - VW_CHAN(VW_SLP_LAN, - ESPI_SYSTEM_EVENT_VW_IDX_42, + /* index 42h: controller to peripheral. */ + VW_CHAN(VW_SLP_LAN, ESPI_SYSTEM_EVENT_VW_IDX_42, VW_LEVEL_FIELD(VW_IDX_42_SLP_LAN), VW_VALID_FIELD(VW_IDX_42_SLP_LAN)), - VW_CHAN(VW_SLP_WLAN, - ESPI_SYSTEM_EVENT_VW_IDX_42, + VW_CHAN(VW_SLP_WLAN, ESPI_SYSTEM_EVENT_VW_IDX_42, VW_LEVEL_FIELD(VW_IDX_42_SLP_WLAN), VW_VALID_FIELD(VW_IDX_42_SLP_WLAN)), }; @@ -220,11 +190,11 @@ int espi_vw_get_wire(enum espi_vw_signal signal) /* Not valid */ if (!(IT83XX_ESPI_VWIDX(vw_channel_list[i].index) & - vw_channel_list[i].valid_mask)) + vw_channel_list[i].valid_mask)) return 0; return !!(IT83XX_ESPI_VWIDX(vw_channel_list[i].index) & - vw_channel_list[i].level_mask); + vw_channel_list[i].level_mask); } /** @@ -264,7 +234,7 @@ int espi_vw_disable_wire_int(enum espi_vw_signal signal) /* Configure virtual wire outputs */ static void espi_configure_vw(const struct vw_channel_t *settings, - size_t entries) + size_t entries) { size_t i; @@ -276,13 +246,13 @@ static void espi_configure_vw(const struct vw_channel_t *settings, static void espi_vw_host_startup(void) { espi_configure_vw(vw_host_startup_setting, - ARRAY_SIZE(vw_host_startup_setting)); + ARRAY_SIZE(vw_host_startup_setting)); } static void espi_vw_no_isr(uint8_t flag_changed, uint8_t vw_evt) { CPRINTS("espi VW interrupt event is ignored! (bit%d at VWCTRL1)", - vw_evt); + vw_evt); } #ifndef CONFIG_CHIPSET_GEMINILAKE @@ -297,13 +267,14 @@ static void espi_vw_idx7_isr(uint8_t flag_changed, uint8_t vw_evt) { if (flag_changed & VW_LEVEL_FIELD(VW_IDX_7_HOST_RST_WARN)) espi_vw_set_wire(VW_HOST_RST_ACK, - espi_vw_get_wire(VW_HOST_RST_WARN)); + espi_vw_get_wire(VW_HOST_RST_WARN)); } #ifdef CONFIG_CHIPSET_RESET_HOOK static void espi_chipset_reset(void) { hook_notify(HOOK_CHIPSET_RESET); + update_ap_boot_time(ESPIRST); } DECLARE_DEFERRED(espi_chipset_reset); #endif @@ -315,12 +286,14 @@ static void espi_vw_idx3_isr(uint8_t flag_changed, uint8_t vw_evt) if (pltrst) { espi_vw_host_startup(); + update_ap_boot_time(PLTRST_HIGH); } else { #ifdef CONFIG_CHIPSET_RESET_HOOK hook_call_deferred(&espi_chipset_reset_data, MSEC); #endif /* Store port 80 reset event */ port_80_write(PORT_80_EVENT_RESET); + update_ap_boot_time(PLTRST_LOW); } CPRINTS("VW PLTRST_L %sasserted", pltrst ? "de" : ""); @@ -328,7 +301,7 @@ static void espi_vw_idx3_isr(uint8_t flag_changed, uint8_t vw_evt) if (flag_changed & VW_LEVEL_FIELD(VW_IDX_3_OOB_RST_WARN)) espi_vw_set_wire(VW_OOB_RST_ACK, - espi_vw_get_wire(VW_OOB_RST_WARN)); + espi_vw_get_wire(VW_OOB_RST_WARN)); } static void espi_vw_idx2_isr(uint8_t flag_changed, uint8_t vw_evt) @@ -352,25 +325,25 @@ struct vw_interrupt_t { */ #ifdef CONFIG_CHIPSET_GEMINILAKE static const struct vw_interrupt_t vw_isr_list[] = { - [0] = {espi_vw_idx2_isr, ESPI_SYSTEM_EVENT_VW_IDX_2}, - [1] = {espi_vw_idx3_isr, ESPI_SYSTEM_EVENT_VW_IDX_3}, - [2] = {espi_vw_idx7_isr, ESPI_SYSTEM_EVENT_VW_IDX_7}, - [3] = {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_41}, - [4] = {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_42}, - [5] = {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_43}, - [6] = {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_44}, - [7] = {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_47}, + [0] = { espi_vw_idx2_isr, ESPI_SYSTEM_EVENT_VW_IDX_2 }, + [1] = { espi_vw_idx3_isr, ESPI_SYSTEM_EVENT_VW_IDX_3 }, + [2] = { espi_vw_idx7_isr, ESPI_SYSTEM_EVENT_VW_IDX_7 }, + [3] = { espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_41 }, + [4] = { espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_42 }, + [5] = { espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_43 }, + [6] = { espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_44 }, + [7] = { espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_47 }, }; #else static const struct vw_interrupt_t vw_isr_list[] = { - [0] = {espi_vw_idx2_isr, ESPI_SYSTEM_EVENT_VW_IDX_2}, - [1] = {espi_vw_idx3_isr, ESPI_SYSTEM_EVENT_VW_IDX_3}, - [2] = {espi_vw_idx7_isr, ESPI_SYSTEM_EVENT_VW_IDX_7}, - [3] = {espi_vw_idx41_isr, ESPI_SYSTEM_EVENT_VW_IDX_41}, - [4] = {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_42}, - [5] = {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_43}, - [6] = {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_44}, - [7] = {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_47}, + [0] = { espi_vw_idx2_isr, ESPI_SYSTEM_EVENT_VW_IDX_2 }, + [1] = { espi_vw_idx3_isr, ESPI_SYSTEM_EVENT_VW_IDX_3 }, + [2] = { espi_vw_idx7_isr, ESPI_SYSTEM_EVENT_VW_IDX_7 }, + [3] = { espi_vw_idx41_isr, ESPI_SYSTEM_EVENT_VW_IDX_41 }, + [4] = { espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_42 }, + [5] = { espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_43 }, + [6] = { espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_44 }, + [7] = { espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_47 }, }; #endif @@ -438,6 +411,12 @@ void espi_reset_pin_asserted_interrupt(enum gpio_signal signal) { #ifdef IT83XX_ESPI_RESET_MODULE_BY_FW espi_fw_reset_module(); + /* + * bit[7], enable P80L function. + * bit[6], accept port 80h cycle. + * bit[1-0], 10b: I2EC is read-only. + */ + IT83XX_GCTRL_SPCTRL1 |= 0xC2; #endif /* reset vw_index_flag when espi_reset# asserted. */ espi_reset_vw_index_flags(); @@ -483,39 +462,39 @@ static void espi_enable_reset(void) #endif IT83XX_GPIO_GCR = (IT83XX_GPIO_GCR & ~0x6) | - (config << IT83XX_GPIO_GCR_LPC_RST_POS); + (config << IT83XX_GPIO_GCR_LPC_RST_POS); /* enable interrupt of EC's espi_reset pin */ gpio_clear_pending_interrupt(GPIO_ESPI_RESET_L); gpio_enable_interrupt(GPIO_ESPI_RESET_L); } -/* Interrupt event of master enables the VW channel. */ +/* Interrupt event of controller enables the VW channel. */ static void espi_vw_en_asserted(uint8_t evt) { /* - * Configure slave to master virtual wire outputs after receiving - * the event of master enables the VW channel. + * Configure peripheral to controller virtual wire outputs after + * receiving the event of controller enables the VW channel. */ espi_configure_vw(en_vw_setting, ARRAY_SIZE(en_vw_setting)); } -/* Interrupt event of master enables the OOB channel. */ +/* Interrupt event of controller enables the OOB channel. */ static void espi_oob_en_asserted(uint8_t evt) { /* - * Configure slave to master virtual wire outputs after receiving - * the event of master enables the OOB channel. + * Configure peripheral to controller virtual wire outputs after + * receiving the event of controller enables the OOB channel. */ espi_configure_vw(en_oob_setting, ARRAY_SIZE(en_oob_setting)); } -/* Interrupt event of master enables the flash channel. */ +/* Interrupt event of controller enables the flash channel. */ static void espi_flash_en_asserted(uint8_t evt) { /* - * Configure slave to master virtual wire outputs after receiving - * the event of master enables the flash channel. + * Configure peripheral to controller virtual wire outputs after + * receiving the event of controller enables the flash channel. */ espi_configure_vw(en_flash_setting, ARRAY_SIZE(en_flash_setting)); } @@ -530,14 +509,10 @@ static void espi_no_isr(uint8_t evt) * IT83XX_ESPI_ESGCTRL0 register. */ static void (*espi_isr[])(uint8_t evt) = { - [0] = espi_no_isr, - [1] = espi_vw_en_asserted, - [2] = espi_oob_en_asserted, - [3] = espi_flash_en_asserted, - [4] = espi_no_isr, - [5] = espi_no_isr, - [6] = espi_no_isr, - [7] = espi_no_isr, + [0] = espi_no_isr, [1] = espi_vw_en_asserted, + [2] = espi_oob_en_asserted, [3] = espi_flash_en_asserted, + [4] = espi_no_isr, [5] = espi_no_isr, + [6] = espi_no_isr, [7] = espi_no_isr, }; void espi_interrupt(void) @@ -554,8 +529,8 @@ void espi_interrupt(void) espi_isr[i](i); } /* - * bit7: the slave has received a peripheral posted/completion. - * This bit indicates the slave has received a packet from eSPI + * bit7: the peripheral has received a peripheral posted/completion. + * This bit indicates the peripheral has received a packet from eSPI * peripheral channel. We can check cycle type (bit[3-0] at ESPCTRL0) * and make corresponding modification if needed. */ @@ -584,14 +559,14 @@ void espi_enable_pad(int enable) void espi_init(void) { /* - * bit[2-0], the maximum frequency of operation supported by slave: + * bit[2-0], the maximum frequency of operation supported by peripheral: * 000b: 20MHz * 001b: 25MHz * 010b: 33MHz * 011b: 50MHz * 100b: 66MHz */ -#ifdef IT83XX_ESPI_SLAVE_MAX_FREQ_CONFIGURABLE +#ifdef IT83XX_ESPI_PERIPHERAL_MAX_FREQ_CONFIGURABLE IT83XX_ESPI_GCAC1 = (IT83XX_ESPI_GCAC1 & ~0x7) | BIT(2); #endif /* reset vw_index_flag at initialization */ diff --git a/chip/it83xx/fan.c b/chip/it83xx/fan.c index adb3985025..b8b805453e 100644 --- a/chip/it83xx/fan.c +++ b/chip/it83xx/fan.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,12 +18,12 @@ #include "task.h" #include "util.h" -#define TACH_EC_FREQ 8000000 -#define FAN_CTRL_BASED_MS 10 -#define FAN_CTRL_INTERVAL_MAX_MS 60 +#define TACH_EC_FREQ 8000000 +#define FAN_CTRL_BASED_MS 10 +#define FAN_CTRL_INTERVAL_MAX_MS 60 /* The sampling rate (fs) is FreqEC / 128 */ -#define TACH_DATA_VALID_TIMEOUT_MS (0xFFFF * 128 / (TACH_EC_FREQ / 1000)) +#define TACH_DATA_VALID_TIMEOUT_MS (0xFFFF * 128 / (TACH_EC_FREQ / 1000)) /* * Fan Speed (RPM) = 60 / (1/fs sec * {FnTMRR, FnTLRR} * P) @@ -37,25 +37,25 @@ #define TACH1_TO_RPM(pulse, raw) (raw * 120 / (pulse * 2)) enum fan_output_s { - FAN_DUTY_I = 0x01, - FAN_DUTY_R = 0x02, + FAN_DUTY_I = 0x01, + FAN_DUTY_R = 0x02, FAN_DUTY_OV = 0x03, FAN_DUTY_DONE = 0x04, }; struct fan_info { - unsigned int flags; - int fan_mode; - int fan_p; - int rpm_target; - int rpm_actual; - int tach_valid_ms; - int rpm_re; - int fan_ms; - int fan_ms_idx; - int startup_duty; + unsigned int flags; + int fan_mode; + int fan_p; + int rpm_target; + int rpm_actual; + int tach_valid_ms; + int rpm_re; + int fan_ms; + int fan_ms_idx; + int startup_duty; enum fan_status fan_sts; - int enabled; + int enabled; }; static struct fan_info fan_info_data[TACH_CH_COUNT]; @@ -72,7 +72,8 @@ static void fan_set_interval(int ch) tach_ch = tach_bind(ch); diff = ABS(fan_info_data[tach_ch].rpm_target - - fan_info_data[tach_ch].rpm_actual) / 100; + fan_info_data[tach_ch].rpm_actual) / + 100; fan_ms = FAN_CTRL_INTERVAL_MAX_MS; @@ -122,7 +123,7 @@ void fan_set_enabled(int ch, int enabled) disable_sleep(SLEEP_MASK_FAN); /* enable timer interrupt for fan control */ ext_timer_start(FAN_CTRL_EXT_TIMER, 1); - /* disable */ + /* disable */ } else { fan_set_duty(ch, 0); @@ -245,9 +246,8 @@ enum fan_status fan_get_status(int ch) int fan_is_stalled(int ch) { /* Must be enabled with non-zero target to stall */ - if (!fan_get_enabled(ch) || - fan_get_rpm_target(ch) == 0 || - !fan_get_duty(ch)) + if (!fan_get_enabled(ch) || fan_get_rpm_target(ch) == 0 || + !fan_get_duty(ch)) return 0; /* Check for stall condition */ @@ -273,8 +273,7 @@ static void fan_ctrl(int ch) tach_ch = tach_bind(ch); fan_info_data[tach_ch].fan_ms_idx += FAN_CTRL_BASED_MS; - if (fan_info_data[tach_ch].fan_ms_idx > - fan_info_data[tach_ch].fan_ms) { + if (fan_info_data[tach_ch].fan_ms_idx > fan_info_data[tach_ch].fan_ms) { fan_info_data[tach_ch].fan_ms_idx = 0x00; adjust = 1; } @@ -411,7 +410,7 @@ static void proc_tach(int ch) } else { fan_info_data[tach_ch].tach_valid_ms += FAN_CTRL_BASED_MS; if (fan_info_data[tach_ch].tach_valid_ms > - TACH_DATA_VALID_TIMEOUT_MS) + TACH_DATA_VALID_TIMEOUT_MS) fan_info_data[tach_ch].rpm_actual = 0; } } @@ -436,14 +435,12 @@ static void fan_init(void) enum tach_ch_sel tach_ch; for (ch = 0; ch < fan_get_count(); ch++) { - rpm_re = fan_tach[pwm_channels[FAN_CH(ch)].channel].rpm_re; fan_p = fan_tach[pwm_channels[FAN_CH(ch)].channel].fan_p; s_duty = fan_tach[pwm_channels[FAN_CH(ch)].channel].s_duty; tach_ch = tach_bind(FAN_CH(ch)); if (tach_ch < TACH_CH_COUNT) { - if (tach_ch == TACH_CH_TACH0B) { /* GPJ2 will select TACH0B as its alt. */ IT83XX_GPIO_GRC5 |= 0x01; @@ -473,6 +470,6 @@ static void fan_init(void) /* init external timer for fan control */ ext_timer_ms(FAN_CTRL_EXT_TIMER, EXT_PSR_32P768K_HZ, 0, 0, - FAN_CTRL_BASED_MS, 1, 0); + FAN_CTRL_BASED_MS, 1, 0); } DECLARE_HOOK(HOOK_INIT, fan_init, HOOK_PRIO_INIT_FAN); diff --git a/chip/it83xx/flash.c b/chip/it83xx/flash.c index c0e062bce4..fa8ab65292 100644 --- a/chip/it83xx/flash.c +++ b/chip/it83xx/flash.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,53 +9,53 @@ #include "flash_chip.h" #include "host_command.h" #include "intc.h" -#include "system.h" -#include "util.h" -#include "watchdog.h" #include "registers.h" -#include "task.h" #include "shared_mem.h" +#include "system.h" +#include "task.h" #include "uart.h" +#include "util.h" +#include "watchdog.h" -#define FLASH_DMA_START ((uint32_t) &__flash_dma_start) +#define FLASH_DMA_START ((uint32_t)&__flash_dma_start) #define FLASH_DMA_CODE __attribute__((section(".flash_direct_map"))) +#define FLASH_ILM0_ADDR ((uint32_t)&__ilm0_ram_code) /* erase size of sector is 1KB or 4KB */ #define FLASH_SECTOR_ERASE_SIZE CONFIG_FLASH_ERASE_SIZE #ifdef IT83XX_CHIP_FLASH_IS_KGD /* page program command */ -#define FLASH_CMD_PAGE_WRITE 0x2 +#define FLASH_CMD_PAGE_WRITE 0x2 /* ector erase command (erase size is 4KB) */ -#define FLASH_CMD_SECTOR_ERASE 0x20 +#define FLASH_CMD_SECTOR_ERASE 0x20 /* command for flash write */ -#define FLASH_CMD_WRITE FLASH_CMD_PAGE_WRITE +#define FLASH_CMD_WRITE FLASH_CMD_PAGE_WRITE #else /* Auto address increment programming */ -#define FLASH_CMD_AAI_WORD 0xAD +#define FLASH_CMD_AAI_WORD 0xAD /* Flash sector erase (1K bytes) command */ -#define FLASH_CMD_SECTOR_ERASE 0xD7 +#define FLASH_CMD_SECTOR_ERASE 0xD7 /* command for flash write */ -#define FLASH_CMD_WRITE FLASH_CMD_AAI_WORD +#define FLASH_CMD_WRITE FLASH_CMD_AAI_WORD #endif /* Write status register */ -#define FLASH_CMD_WRSR 0x01 +#define FLASH_CMD_WRSR 0x01 /* Write disable */ -#define FLASH_CMD_WRDI 0x04 +#define FLASH_CMD_WRDI 0x04 /* Write enable */ -#define FLASH_CMD_WREN 0x06 +#define FLASH_CMD_WREN 0x06 /* Read status register */ -#define FLASH_CMD_RS 0x05 +#define FLASH_CMD_RS 0x05 -#define FLASH_TEXT_START ((uint32_t) &__flash_text_start) +#if (CONFIG_FLASH_SIZE_BYTES == 0x80000) && defined(CHIP_CORE_NDS32) +#define FLASH_TEXT_START ((uint32_t)&__flash_text_start) +/* Apply workaround of the issue (b:111808417) */ +#define IMMU_CACHE_TAG_INVALID /* The default tag index of immu. */ #define IMMU_TAG_INDEX_BY_DEFAULT 0x7E000 /* immu cache size is 8K bytes. */ -#define IMMU_SIZE 0x2000 - -#if (CONFIG_FLASH_SIZE == 0x80000) && defined(CHIP_CORE_NDS32) -/* Apply workaround of the issue (b:111808417) */ -#define IMMU_CACHE_TAG_INVALID +#define IMMU_SIZE 0x2000 #endif static int stuck_locked; @@ -88,18 +88,18 @@ enum flash_status_mask { }; enum dlm_address_view { - SCAR0_ILM0_DLM13 = 0x8D000, /* DLM ~ 0x8DFFF H2RAM map LPC I/O */ - SCAR1_ILM1_DLM11 = 0x8B000, /* DLM ~ 0x8BFFF ram 44K ~ 48K */ - SCAR2_ILM2_DLM14 = 0x8E000, /* DLM ~ 0x8EFFF RO/RW flash code DMA */ - SCAR3_ILM3_DLM6 = 0x86000, /* DLM ~ 0x86FFF ram 24K ~ 28K */ - SCAR4_ILM4_DLM7 = 0x87000, /* DLM ~ 0x87FFF ram 28K ~ 32K */ - SCAR5_ILM5_DLM8 = 0x88000, /* DLM ~ 0x88FFF ram 32K ~ 36K */ - SCAR6_ILM6_DLM9 = 0x89000, /* DLM ~ 0x89FFF ram 36K ~ 40K */ - SCAR7_ILM7_DLM10 = 0x8A000, /* DLM ~ 0x8AFFF ram 40K ~ 44K */ - SCAR8_ILM8_DLM4 = 0x84000, /* DLM ~ 0x84FFF ram 16K ~ 20K */ - SCAR9_ILM9_DLM5 = 0x85000, /* DLM ~ 0x85FFF ram 20K ~ 24K */ - SCAR10_ILM10_DLM2 = 0x82000, /* DLM ~ 0x82FFF ram 8K ~ 12K */ - SCAR11_ILM11_DLM3 = 0x83000, /* DLM ~ 0x83FFF ram 12K ~ 16K */ + SCAR0_ILM0_DLM13 = 0x8D000, /* DLM ~ 0x8DFFF H2RAM map LPC I/O */ + SCAR1_ILM1_DLM11 = 0x8B000, /* DLM ~ 0x8BFFF ram 44K ~ 48K */ + SCAR2_ILM2_DLM14 = 0x8E000, /* DLM ~ 0x8EFFF RO/RW flash code DMA */ + SCAR3_ILM3_DLM6 = 0x86000, /* DLM ~ 0x86FFF ram 24K ~ 28K */ + SCAR4_ILM4_DLM7 = 0x87000, /* DLM ~ 0x87FFF ram 28K ~ 32K */ + SCAR5_ILM5_DLM8 = 0x88000, /* DLM ~ 0x88FFF ram 32K ~ 36K */ + SCAR6_ILM6_DLM9 = 0x89000, /* DLM ~ 0x89FFF ram 36K ~ 40K */ + SCAR7_ILM7_DLM10 = 0x8A000, /* DLM ~ 0x8AFFF ram 40K ~ 44K */ + SCAR8_ILM8_DLM4 = 0x84000, /* DLM ~ 0x84FFF ram 16K ~ 20K */ + SCAR9_ILM9_DLM5 = 0x85000, /* DLM ~ 0x85FFF ram 20K ~ 24K */ + SCAR10_ILM10_DLM2 = 0x82000, /* DLM ~ 0x82FFF ram 8K ~ 12K */ + SCAR11_ILM11_DLM3 = 0x83000, /* DLM ~ 0x83FFF ram 12K ~ 16K */ SCAR12_ILM12_DLM12 = 0x8C000, /* DLM ~ 0x8CFFF immu cache */ }; @@ -177,8 +177,8 @@ void FLASH_DMA_CODE dma_flash_write_dat(uint8_t wdata) IT83XX_SMFI_ECINDDR = wdata; } -void FLASH_DMA_CODE dma_flash_transaction(int wlen, uint8_t *wbuf, - int rlen, uint8_t *rbuf, int cmd_end) +void FLASH_DMA_CODE dma_flash_transaction(int wlen, uint8_t *wbuf, int rlen, + uint8_t *rbuf, int cmd_end) { int i; @@ -197,10 +197,10 @@ void FLASH_DMA_CODE dma_flash_transaction(int wlen, uint8_t *wbuf, } void FLASH_DMA_CODE dma_flash_cmd_read_status(enum flash_status_mask mask, - enum flash_status_mask target) + enum flash_status_mask target) { uint8_t status[1]; - uint8_t cmd_rs[] = {FLASH_CMD_RS}; + uint8_t cmd_rs[] = { FLASH_CMD_RS }; /* * We prefer no timeout here. We can always get the status @@ -220,7 +220,7 @@ void FLASH_DMA_CODE dma_flash_cmd_read_status(enum flash_status_mask mask, void FLASH_DMA_CODE dma_flash_cmd_write_enable(void) { - uint8_t cmd_we[] = {FLASH_CMD_WREN}; + uint8_t cmd_we[] = { FLASH_CMD_WREN }; /* enter EC-indirect follow mode */ dma_flash_follow_mode(); @@ -234,7 +234,7 @@ void FLASH_DMA_CODE dma_flash_cmd_write_enable(void) void FLASH_DMA_CODE dma_flash_cmd_write_disable(void) { - uint8_t cmd_wd[] = {FLASH_CMD_WRDI}; + uint8_t cmd_wd[] = { FLASH_CMD_WRDI }; /* enter EC-indirect follow mode */ dma_flash_follow_mode(); @@ -248,8 +248,8 @@ void FLASH_DMA_CODE dma_flash_cmd_write_disable(void) void FLASH_DMA_CODE dma_flash_cmd_erase(int addr, int cmd) { - uint8_t cmd_erase[] = {cmd, ((addr >> 16) & 0xFF), - ((addr >> 8) & 0xFF), (addr & 0xFF)}; + uint8_t cmd_erase[] = { cmd, ((addr >> 16) & 0xFF), + ((addr >> 8) & 0xFF), (addr & 0xFF) }; /* enter EC-indirect follow mode */ dma_flash_follow_mode(); @@ -264,8 +264,8 @@ void FLASH_DMA_CODE dma_flash_cmd_erase(int addr, int cmd) void FLASH_DMA_CODE dma_flash_cmd_write(int addr, int wlen, uint8_t *wbuf) { int i; - uint8_t flash_write[] = {FLASH_CMD_WRITE, ((addr >> 16) & 0xFF), - ((addr >> 8) & 0xFF), (addr & 0xFF)}; + uint8_t flash_write[] = { FLASH_CMD_WRITE, ((addr >> 16) & 0xFF), + ((addr >> 8) & 0xFF), (addr & 0xFF) }; /* enter EC-indirect follow mode */ dma_flash_follow_mode(); @@ -281,12 +281,12 @@ void FLASH_DMA_CODE dma_flash_cmd_write(int addr, int wlen, uint8_t *wbuf) * chunk worth of data. */ if (!(++addr % CONFIG_FLASH_WRITE_IDEAL_SIZE)) { - uint8_t w_en[] = {FLASH_CMD_WREN}; + uint8_t w_en[] = { FLASH_CMD_WREN }; dma_flash_fsce_high(); /* make sure busy bit cleared. */ dma_flash_cmd_read_status(FLASH_SR_BUSY, - FLASH_SR_NO_BUSY); + FLASH_SR_NO_BUSY); /* send write enable command */ dma_flash_transaction(sizeof(w_en), w_en, 0, NULL, 1); /* make sure busy bit cleared and write enabled. */ @@ -296,7 +296,7 @@ void FLASH_DMA_CODE dma_flash_cmd_write(int addr, int wlen, uint8_t *wbuf) flash_write[2] = (addr >> 8) & 0xff; flash_write[3] = addr & 0xff; dma_flash_transaction(sizeof(flash_write), flash_write, - 0, NULL, 0); + 0, NULL, 0); } } dma_flash_fsce_high(); @@ -340,7 +340,7 @@ int FLASH_DMA_CODE dma_flash_verify(int addr, int size, const char *data) if (flash[i] != 0xFF) return EC_ERROR_UNKNOWN; } - /* verify for write */ + /* verify for write */ } else { for (i = 0; i < size; i++) { if (flash[i] != wbuf[i]) @@ -370,7 +370,7 @@ static enum flash_wp_status flash_check_wp(void) enum flash_wp_status wp_status; int all_bank_count, bank; - all_bank_count = CONFIG_FLASH_SIZE / CONFIG_FLASH_BANK_SIZE; + all_bank_count = CONFIG_FLASH_SIZE_BYTES / CONFIG_FLASH_BANK_SIZE; for (bank = 0; bank < all_bank_count; bank++) { if (!(IT83XX_GCTRL_EWPR0PFEC(FWP_REG(bank)) & FWP_MASK(bank))) @@ -395,8 +395,7 @@ static enum flash_wp_status flash_check_wp(void) * @param start_bank Start bank to protect * @param bank_count Number of banks to protect */ -static void flash_protect_banks(int start_bank, - int bank_count, +static void flash_protect_banks(int start_bank, int bank_count, enum flash_wp_interface wp_if) { int bank; @@ -411,7 +410,7 @@ static void flash_protect_banks(int start_bank, } } -int FLASH_DMA_CODE flash_physical_read(int offset, int size, char *data) +int FLASH_DMA_CODE crec_flash_physical_read(int offset, int size, char *data) { int i; @@ -432,7 +431,8 @@ int FLASH_DMA_CODE flash_physical_read(int offset, int size, char *data) * @param size Number of bytes to write. * @param data Data to write to flash. Must be 32-bit aligned. */ -int FLASH_DMA_CODE flash_physical_write(int offset, int size, const char *data) +int FLASH_DMA_CODE crec_flash_physical_write(int offset, int size, + const char *data) { int ret = EC_ERROR_UNKNOWN; @@ -452,7 +452,11 @@ int FLASH_DMA_CODE flash_physical_write(int offset, int size, const char *data) interrupt_disable(); dma_flash_write(offset, size, data); +#ifdef IMMU_CACHE_TAG_INVALID dma_reset_immu((offset + size) >= IMMU_TAG_INDEX_BY_DEFAULT); +#else + dma_reset_immu(0); +#endif /* * Internal flash of N8 or RISC-V core is ILM(Instruction Local Memory) * mapped, but RISC-V's ILM base address is 0x80000000. @@ -475,7 +479,7 @@ int FLASH_DMA_CODE flash_physical_write(int offset, int size, const char *data) * @param offset Flash offset to erase. * @param size Number of bytes to erase. */ -int FLASH_DMA_CODE flash_physical_erase(int offset, int size) +int FLASH_DMA_CODE crec_flash_physical_erase(int offset, int size) { int v_size = size, v_addr = offset, ret = EC_ERROR_UNKNOWN; @@ -496,8 +500,29 @@ int FLASH_DMA_CODE flash_physical_erase(int offset, int size) for (; size > 0; size -= FLASH_SECTOR_ERASE_SIZE) { dma_flash_erase(offset, FLASH_CMD_SECTOR_ERASE); offset += FLASH_SECTOR_ERASE_SIZE; + /* + * If requested erase size is too large at one time on KGD + * flash, we need to reload watchdog to prevent the reset. + */ + if (IS_ENABLED(IT83XX_CHIP_FLASH_IS_KGD) && (size > 0x10000)) + watchdog_reload(); + /* + * EC still need to handle AP's EC_CMD_GET_COMMS_STATUS + * command during erasing. + */ +#ifdef IT83XX_IRQ_SPI_PERIPHERAL + if (IS_ENABLED(CONFIG_SPI) && IS_ENABLED(HAS_TASK_HOSTCMD) && + IS_ENABLED(CONFIG_HOST_COMMAND_STATUS)) { + if (IT83XX_SPI_RX_VLISR & IT83XX_SPI_RVLI) + task_trigger_irq(IT83XX_IRQ_SPI_PERIPHERAL); + } +#endif } +#ifdef IMMU_CACHE_TAG_INVALID dma_reset_immu((v_addr + v_size) >= IMMU_TAG_INDEX_BY_DEFAULT); +#else + dma_reset_immu(0); +#endif /* get the ILM address of a flash offset. */ v_addr |= CONFIG_MAPPED_STORAGE_BASE; ret = dma_flash_verify(v_addr, v_size, NULL); @@ -513,7 +538,7 @@ int FLASH_DMA_CODE flash_physical_erase(int offset, int size) * @param bank Bank index to check. * @return non-zero if bank is protected until reboot. */ -int flash_physical_get_protect(int bank) +int crec_flash_physical_get_protect(int bank) { return IT83XX_GCTRL_EWPR0PFEC(FWP_REG(bank)) & FWP_MASK(bank); } @@ -524,21 +549,20 @@ int flash_physical_get_protect(int bank) * @param all Protect all (=1) or just read-only and pstate (=0). * @return non-zero if error. */ -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { if (all) { /* Protect the entire flash */ - flash_protect_banks(0, - CONFIG_FLASH_SIZE / CONFIG_FLASH_BANK_SIZE, + flash_protect_banks( + 0, CONFIG_FLASH_SIZE_BYTES / CONFIG_FLASH_BANK_SIZE, FLASH_WP_EC); all_protected = 1; } else { /* Protect the read-only section and persistent state */ - flash_protect_banks(WP_BANK_OFFSET, - WP_BANK_COUNT, FLASH_WP_EC); + flash_protect_banks(WP_BANK_OFFSET, WP_BANK_COUNT, FLASH_WP_EC); #ifdef PSTATE_BANK - flash_protect_banks(PSTATE_BANK, - PSTATE_BANK_COUNT, FLASH_WP_EC); + flash_protect_banks(PSTATE_BANK, PSTATE_BANK_COUNT, + FLASH_WP_EC); #endif } @@ -558,7 +582,7 @@ int flash_physical_protect_now(int all) * * Uses the EC_FLASH_PROTECT_* flags from ec_commands.h */ -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { uint32_t flags = 0; @@ -583,10 +607,9 @@ uint32_t flash_physical_get_protect_flags(void) * * @return A combination of EC_FLASH_PROTECT_* flags from ec_commands.h */ -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ALL_NOW; } @@ -596,7 +619,7 @@ uint32_t flash_physical_get_valid_flags(void) * @param cur_flags The current flash protect flags. * @return A combination of EC_FLASH_PROTECT_* flags from ec_commands.h */ -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { uint32_t ret = 0; @@ -615,9 +638,38 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) return ret; } -static void flash_code_static_dma(void) +static void flash_enable_second_ilm(void) { +#ifdef CHIP_CORE_RISCV + /* Make sure no interrupt while enable static cache */ + interrupt_disable(); + + /* Invalid ILM0 */ + IT83XX_GCTRL_RVILMCR0 &= ~ILMCR_ILM0_ENABLE; + IT83XX_SMFI_SCAR0H = BIT(3); + /* copy code to ram */ + memcpy((void *)CHIP_RAMCODE_ILM0, (const void *)FLASH_ILM0_ADDR, + IT83XX_ILM_BLOCK_SIZE); + /* + * Set the logic memory address(flash code of RO/RW) in flash + * by programming the register SCAR0x bit19-bit0. + */ + IT83XX_SMFI_SCAR0L = FLASH_ILM0_ADDR & GENMASK(7, 0); + IT83XX_SMFI_SCAR0M = (FLASH_ILM0_ADDR >> 8) & GENMASK(7, 0); + IT83XX_SMFI_SCAR0H = (FLASH_ILM0_ADDR >> 16) & GENMASK(2, 0); + if (FLASH_ILM0_ADDR & BIT(19)) + IT83XX_SMFI_SCAR0H |= BIT(7); + else + IT83XX_SMFI_SCAR0H &= ~BIT(7); + /* Enable ILM 0 */ + IT83XX_GCTRL_RVILMCR0 |= ILMCR_ILM0_ENABLE; + + interrupt_enable(); +#endif +} +static void flash_code_static_dma(void) +{ /* Make sure no interrupt while enable static DMA */ interrupt_disable(); @@ -630,7 +682,7 @@ static void flash_code_static_dma(void) if (IS_ENABLED(CHIP_CORE_NDS32)) IT83XX_GCTRL_MCCR2 |= IT83XX_DLM14_ENABLE; memcpy((void *)CHIP_RAMCODE_BASE, (const void *)FLASH_DMA_START, - IT83XX_ILM_BLOCK_SIZE); + IT83XX_ILM_BLOCK_SIZE); if (IS_ENABLED(CHIP_CORE_RISCV)) IT83XX_GCTRL_RVILMCR0 |= ILMCR_ILM2_ENABLE; /* Disable DLM 56k~60k region and be the ram code section */ @@ -669,7 +721,7 @@ static void flash_code_static_dma(void) * * Applies at-boot protection settings if necessary. */ -int flash_pre_init(void) +int crec_flash_pre_init(void) { int32_t reset_flags, prot_flags, unwanted_prot_flags; @@ -678,11 +730,16 @@ int flash_pre_init(void) if (IS_ENABLED(IT83XX_CHIP_FLASH_IS_KGD)) IT83XX_SMFI_FLHCTRL6R |= IT83XX_SMFI_MASK_ECINDPP; flash_code_static_dma(); + /* + * Enable second ilm (ILM0 of it8xxx2 series), so we can pull more code + * (4kB) into static cache to save latency of fetching code from flash. + */ + flash_enable_second_ilm(); reset_flags = system_get_reset_flags(); - prot_flags = flash_get_protect(); + prot_flags = crec_flash_get_protect(); unwanted_prot_flags = EC_FLASH_PROTECT_ALL_NOW | - EC_FLASH_PROTECT_ERROR_INCONSISTENT; + EC_FLASH_PROTECT_ERROR_INCONSISTENT; /* * If we have already jumped between images, an earlier image could @@ -693,12 +750,12 @@ int flash_pre_init(void) if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) { /* Protect the entire flash of host interface */ - flash_protect_banks(0, - CONFIG_FLASH_SIZE / CONFIG_FLASH_BANK_SIZE, + flash_protect_banks( + 0, CONFIG_FLASH_SIZE_BYTES / CONFIG_FLASH_BANK_SIZE, FLASH_WP_HOST); /* Protect the entire flash of DBGR interface */ - flash_protect_banks(0, - CONFIG_FLASH_SIZE / CONFIG_FLASH_BANK_SIZE, + flash_protect_banks( + 0, CONFIG_FLASH_SIZE_BYTES / CONFIG_FLASH_BANK_SIZE, FLASH_WP_DBGR); /* * Write protect is asserted. If we want RO flash protected, @@ -706,13 +763,14 @@ int flash_pre_init(void) */ if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) && !(prot_flags & EC_FLASH_PROTECT_RO_NOW)) { - int rv = flash_set_protect(EC_FLASH_PROTECT_RO_NOW, - EC_FLASH_PROTECT_RO_NOW); + int rv = + crec_flash_set_protect(EC_FLASH_PROTECT_RO_NOW, + EC_FLASH_PROTECT_RO_NOW); if (rv) return rv; /* Re-read flags */ - prot_flags = flash_get_protect(); + prot_flags = crec_flash_get_protect(); } } else { /* Don't want RO flash protected */ diff --git a/chip/it83xx/flash_chip.h b/chip/it83xx/flash_chip.h index 4a604ed7f7..c1cb44bdf2 100644 --- a/chip/it83xx/flash_chip.h +++ b/chip/it83xx/flash_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,6 +13,9 @@ */ extern const char __flash_dma_start; +/* This symbol is the begin address of the __ilm0_ram_code section. */ +extern const char __ilm0_ram_code; + /* This symbol is the begin address of the text section. */ extern const char __flash_text_start; diff --git a/chip/it83xx/gpio.c b/chip/it83xx/gpio.c index 3dd6d16268..2b1b8283be 100644 --- a/chip/it83xx/gpio.c +++ b/chip/it83xx/gpio.c @@ -1,10 +1,11 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* GPIO module for Chrome EC */ +#include "builtin/assert.h" #include "clock.h" #include "common.h" #include "gpio.h" @@ -19,6 +20,23 @@ #include "timer.h" #include "util.h" +/* Data structure to define KSI/KSO GPIO mode control registers. */ +struct kbs_gpio_ctrl_t { + /* GPIO mode control register. */ + volatile uint8_t *gpio_mode; + /* GPIO output enable register. */ + volatile uint8_t *gpio_out; +}; + +static const struct kbs_gpio_ctrl_t kbs_gpio_ctrl_regs[] = { + /* KSI pins 7:0 */ + { &IT83XX_KBS_KSIGCTRL, &IT83XX_KBS_KSIGOEN }, + /* KSO pins 15:8 */ + { &IT83XX_KBS_KSOHGCTRL, &IT83XX_KBS_KSOHGOEN }, + /* KSO pins 7:0 */ + { &IT83XX_KBS_KSOLGCTRL, &IT83XX_KBS_KSOLGOEN }, +}; + /** * Convert wake-up controller (WUC) group to the corresponding wake-up edge * sense register (WUESR). Return pointer to the register. @@ -34,8 +52,8 @@ static volatile uint8_t *wuesr(uint8_t grp) * the address increases by fours. */ return (grp <= 4) ? - (volatile uint8_t *)(IT83XX_WUC_WUESR1 + grp-1) : - (volatile uint8_t *)(IT83XX_WUC_WUESR5 + 4*(grp-5)); + (volatile uint8_t *)(IT83XX_WUC_WUESR1 + grp - 1) : + (volatile uint8_t *)(IT83XX_WUC_WUESR5 + 4 * (grp - 5)); } /** @@ -53,8 +71,8 @@ static volatile uint8_t *wuemr(uint8_t grp) * the address increases by fours. */ return (grp <= 4) ? - (volatile uint8_t *)(IT83XX_WUC_WUEMR1 + grp-1) : - (volatile uint8_t *)(IT83XX_WUC_WUEMR5 + 4*(grp-5)); + (volatile uint8_t *)(IT83XX_WUC_WUEMR1 + grp - 1) : + (volatile uint8_t *)(IT83XX_WUC_WUEMR5 + 4 * (grp - 5)); } /** @@ -73,8 +91,8 @@ static volatile uint8_t *wubemr(uint8_t grp) * the address increases by fours. */ return (grp <= 4) ? - (volatile uint8_t *)(IT83XX_WUC_WUBEMR1 + grp-1) : - (volatile uint8_t *)(IT83XX_WUC_WUBEMR5 + 4*(grp-5)); + (volatile uint8_t *)(IT83XX_WUC_WUBEMR1 + grp - 1) : + (volatile uint8_t *)(IT83XX_WUC_WUBEMR5 + 4 * (grp - 5)); } #endif @@ -95,140 +113,140 @@ static const struct { uint8_t wuc_mask; } gpio_irqs[] = { /* irq gpio_port,gpio_mask,wuc_group,wuc_mask */ - [IT83XX_IRQ_WKO20] = {GPIO_D, BIT(0), 2, BIT(0)}, - [IT83XX_IRQ_WKO21] = {GPIO_D, BIT(1), 2, BIT(1)}, - [IT83XX_IRQ_WKO22] = {GPIO_C, BIT(4), 2, BIT(2)}, - [IT83XX_IRQ_WKO23] = {GPIO_C, BIT(6), 2, BIT(3)}, - [IT83XX_IRQ_WKO24] = {GPIO_D, BIT(2), 2, BIT(4)}, + [IT83XX_IRQ_WKO20] = { GPIO_D, BIT(0), 2, BIT(0) }, + [IT83XX_IRQ_WKO21] = { GPIO_D, BIT(1), 2, BIT(1) }, + [IT83XX_IRQ_WKO22] = { GPIO_C, BIT(4), 2, BIT(2) }, + [IT83XX_IRQ_WKO23] = { GPIO_C, BIT(6), 2, BIT(3) }, + [IT83XX_IRQ_WKO24] = { GPIO_D, BIT(2), 2, BIT(4) }, #ifdef IT83XX_GPIO_INT_FLEXIBLE - [IT83XX_IRQ_WKO40] = {GPIO_E, BIT(5), 4, BIT(0)}, - [IT83XX_IRQ_WKO45] = {GPIO_E, BIT(6), 4, BIT(5)}, - [IT83XX_IRQ_WKO46] = {GPIO_E, BIT(7), 4, BIT(6)}, + [IT83XX_IRQ_WKO40] = { GPIO_E, BIT(5), 4, BIT(0) }, + [IT83XX_IRQ_WKO45] = { GPIO_E, BIT(6), 4, BIT(5) }, + [IT83XX_IRQ_WKO46] = { GPIO_E, BIT(7), 4, BIT(6) }, #endif - [IT83XX_IRQ_WKO50] = {GPIO_K, BIT(0), 5, BIT(0)}, - [IT83XX_IRQ_WKO51] = {GPIO_K, BIT(1), 5, BIT(1)}, - [IT83XX_IRQ_WKO52] = {GPIO_K, BIT(2), 5, BIT(2)}, - [IT83XX_IRQ_WKO53] = {GPIO_K, BIT(3), 5, BIT(3)}, - [IT83XX_IRQ_WKO54] = {GPIO_K, BIT(4), 5, BIT(4)}, - [IT83XX_IRQ_WKO55] = {GPIO_K, BIT(5), 5, BIT(5)}, - [IT83XX_IRQ_WKO56] = {GPIO_K, BIT(6), 5, BIT(6)}, - [IT83XX_IRQ_WKO57] = {GPIO_K, BIT(7), 5, BIT(7)}, - [IT83XX_IRQ_WKO60] = {GPIO_H, BIT(0), 6, BIT(0)}, - [IT83XX_IRQ_WKO61] = {GPIO_H, BIT(1), 6, BIT(1)}, - [IT83XX_IRQ_WKO62] = {GPIO_H, BIT(2), 6, BIT(2)}, - [IT83XX_IRQ_WKO63] = {GPIO_H, BIT(3), 6, BIT(3)}, - [IT83XX_IRQ_WKO64] = {GPIO_F, BIT(4), 6, BIT(4)}, - [IT83XX_IRQ_WKO65] = {GPIO_F, BIT(5), 6, BIT(5)}, - [IT83XX_IRQ_WKO65] = {GPIO_F, BIT(6), 6, BIT(6)}, - [IT83XX_IRQ_WKO67] = {GPIO_F, BIT(7), 6, BIT(7)}, - [IT83XX_IRQ_WKO70] = {GPIO_E, BIT(0), 7, BIT(0)}, - [IT83XX_IRQ_WKO71] = {GPIO_E, BIT(1), 7, BIT(1)}, - [IT83XX_IRQ_WKO72] = {GPIO_E, BIT(2), 7, BIT(2)}, - [IT83XX_IRQ_WKO73] = {GPIO_E, BIT(3), 7, BIT(3)}, - [IT83XX_IRQ_WKO74] = {GPIO_I, BIT(4), 7, BIT(4)}, - [IT83XX_IRQ_WKO75] = {GPIO_I, BIT(5), 7, BIT(5)}, - [IT83XX_IRQ_WKO76] = {GPIO_I, BIT(6), 7, BIT(6)}, - [IT83XX_IRQ_WKO77] = {GPIO_I, BIT(7), 7, BIT(7)}, - [IT83XX_IRQ_WKO80] = {GPIO_A, BIT(3), 8, BIT(0)}, - [IT83XX_IRQ_WKO81] = {GPIO_A, BIT(4), 8, BIT(1)}, - [IT83XX_IRQ_WKO82] = {GPIO_A, BIT(5), 8, BIT(2)}, - [IT83XX_IRQ_WKO83] = {GPIO_A, BIT(6), 8, BIT(3)}, - [IT83XX_IRQ_WKO84] = {GPIO_B, BIT(2), 8, BIT(4)}, - [IT83XX_IRQ_WKO85] = {GPIO_C, BIT(0), 8, BIT(5)}, - [IT83XX_IRQ_WKO86] = {GPIO_C, BIT(7), 8, BIT(6)}, - [IT83XX_IRQ_WKO87] = {GPIO_D, BIT(7), 8, BIT(7)}, - [IT83XX_IRQ_WKO88] = {GPIO_H, BIT(4), 9, BIT(0)}, - [IT83XX_IRQ_WKO89] = {GPIO_H, BIT(5), 9, BIT(1)}, - [IT83XX_IRQ_WKO90] = {GPIO_H, BIT(6), 9, BIT(2)}, - [IT83XX_IRQ_WKO91] = {GPIO_A, BIT(0), 9, BIT(3)}, - [IT83XX_IRQ_WKO92] = {GPIO_A, BIT(1), 9, BIT(4)}, - [IT83XX_IRQ_WKO93] = {GPIO_A, BIT(2), 9, BIT(5)}, - [IT83XX_IRQ_WKO94] = {GPIO_B, BIT(4), 9, BIT(6)}, - [IT83XX_IRQ_WKO95] = {GPIO_C, BIT(2), 9, BIT(7)}, - [IT83XX_IRQ_WKO96] = {GPIO_F, BIT(0), 10, BIT(0)}, - [IT83XX_IRQ_WKO97] = {GPIO_F, BIT(1), 10, BIT(1)}, - [IT83XX_IRQ_WKO98] = {GPIO_F, BIT(2), 10, BIT(2)}, - [IT83XX_IRQ_WKO99] = {GPIO_F, BIT(3), 10, BIT(3)}, - [IT83XX_IRQ_WKO100] = {GPIO_A, BIT(7), 10, BIT(4)}, - [IT83XX_IRQ_WKO101] = {GPIO_B, BIT(0), 10, BIT(5)}, - [IT83XX_IRQ_WKO102] = {GPIO_B, BIT(1), 10, BIT(6)}, - [IT83XX_IRQ_WKO103] = {GPIO_B, BIT(3), 10, BIT(7)}, - [IT83XX_IRQ_WKO104] = {GPIO_B, BIT(5), 11, BIT(0)}, - [IT83XX_IRQ_WKO105] = {GPIO_B, BIT(6), 11, BIT(1)}, - [IT83XX_IRQ_WKO106] = {GPIO_B, BIT(7), 11, BIT(2)}, - [IT83XX_IRQ_WKO107] = {GPIO_C, BIT(1), 11, BIT(3)}, - [IT83XX_IRQ_WKO108] = {GPIO_C, BIT(3), 11, BIT(4)}, - [IT83XX_IRQ_WKO109] = {GPIO_C, BIT(5), 11, BIT(5)}, - [IT83XX_IRQ_WKO110] = {GPIO_D, BIT(3), 11, BIT(6)}, - [IT83XX_IRQ_WKO111] = {GPIO_D, BIT(4), 11, BIT(7)}, - [IT83XX_IRQ_WKO112] = {GPIO_D, BIT(5), 12, BIT(0)}, - [IT83XX_IRQ_WKO113] = {GPIO_D, BIT(6), 12, BIT(1)}, - [IT83XX_IRQ_WKO114] = {GPIO_E, BIT(4), 12, BIT(2)}, - [IT83XX_IRQ_WKO115] = {GPIO_G, BIT(0), 12, BIT(3)}, - [IT83XX_IRQ_WKO116] = {GPIO_G, BIT(1), 12, BIT(4)}, - [IT83XX_IRQ_WKO117] = {GPIO_G, BIT(2), 12, BIT(5)}, - [IT83XX_IRQ_WKO118] = {GPIO_G, BIT(6), 12, BIT(6)}, - [IT83XX_IRQ_WKO119] = {GPIO_I, BIT(0), 12, BIT(7)}, - [IT83XX_IRQ_WKO120] = {GPIO_I, BIT(1), 13, BIT(0)}, - [IT83XX_IRQ_WKO121] = {GPIO_I, BIT(2), 13, BIT(1)}, - [IT83XX_IRQ_WKO122] = {GPIO_I, BIT(3), 13, BIT(2)}, + [IT83XX_IRQ_WKO50] = { GPIO_K, BIT(0), 5, BIT(0) }, + [IT83XX_IRQ_WKO51] = { GPIO_K, BIT(1), 5, BIT(1) }, + [IT83XX_IRQ_WKO52] = { GPIO_K, BIT(2), 5, BIT(2) }, + [IT83XX_IRQ_WKO53] = { GPIO_K, BIT(3), 5, BIT(3) }, + [IT83XX_IRQ_WKO54] = { GPIO_K, BIT(4), 5, BIT(4) }, + [IT83XX_IRQ_WKO55] = { GPIO_K, BIT(5), 5, BIT(5) }, + [IT83XX_IRQ_WKO56] = { GPIO_K, BIT(6), 5, BIT(6) }, + [IT83XX_IRQ_WKO57] = { GPIO_K, BIT(7), 5, BIT(7) }, + [IT83XX_IRQ_WKO60] = { GPIO_H, BIT(0), 6, BIT(0) }, + [IT83XX_IRQ_WKO61] = { GPIO_H, BIT(1), 6, BIT(1) }, + [IT83XX_IRQ_WKO62] = { GPIO_H, BIT(2), 6, BIT(2) }, + [IT83XX_IRQ_WKO63] = { GPIO_H, BIT(3), 6, BIT(3) }, + [IT83XX_IRQ_WKO64] = { GPIO_F, BIT(4), 6, BIT(4) }, + [IT83XX_IRQ_WKO65] = { GPIO_F, BIT(5), 6, BIT(5) }, + [IT83XX_IRQ_WKO65] = { GPIO_F, BIT(6), 6, BIT(6) }, + [IT83XX_IRQ_WKO67] = { GPIO_F, BIT(7), 6, BIT(7) }, + [IT83XX_IRQ_WKO70] = { GPIO_E, BIT(0), 7, BIT(0) }, + [IT83XX_IRQ_WKO71] = { GPIO_E, BIT(1), 7, BIT(1) }, + [IT83XX_IRQ_WKO72] = { GPIO_E, BIT(2), 7, BIT(2) }, + [IT83XX_IRQ_WKO73] = { GPIO_E, BIT(3), 7, BIT(3) }, + [IT83XX_IRQ_WKO74] = { GPIO_I, BIT(4), 7, BIT(4) }, + [IT83XX_IRQ_WKO75] = { GPIO_I, BIT(5), 7, BIT(5) }, + [IT83XX_IRQ_WKO76] = { GPIO_I, BIT(6), 7, BIT(6) }, + [IT83XX_IRQ_WKO77] = { GPIO_I, BIT(7), 7, BIT(7) }, + [IT83XX_IRQ_WKO80] = { GPIO_A, BIT(3), 8, BIT(0) }, + [IT83XX_IRQ_WKO81] = { GPIO_A, BIT(4), 8, BIT(1) }, + [IT83XX_IRQ_WKO82] = { GPIO_A, BIT(5), 8, BIT(2) }, + [IT83XX_IRQ_WKO83] = { GPIO_A, BIT(6), 8, BIT(3) }, + [IT83XX_IRQ_WKO84] = { GPIO_B, BIT(2), 8, BIT(4) }, + [IT83XX_IRQ_WKO85] = { GPIO_C, BIT(0), 8, BIT(5) }, + [IT83XX_IRQ_WKO86] = { GPIO_C, BIT(7), 8, BIT(6) }, + [IT83XX_IRQ_WKO87] = { GPIO_D, BIT(7), 8, BIT(7) }, + [IT83XX_IRQ_WKO88] = { GPIO_H, BIT(4), 9, BIT(0) }, + [IT83XX_IRQ_WKO89] = { GPIO_H, BIT(5), 9, BIT(1) }, + [IT83XX_IRQ_WKO90] = { GPIO_H, BIT(6), 9, BIT(2) }, + [IT83XX_IRQ_WKO91] = { GPIO_A, BIT(0), 9, BIT(3) }, + [IT83XX_IRQ_WKO92] = { GPIO_A, BIT(1), 9, BIT(4) }, + [IT83XX_IRQ_WKO93] = { GPIO_A, BIT(2), 9, BIT(5) }, + [IT83XX_IRQ_WKO94] = { GPIO_B, BIT(4), 9, BIT(6) }, + [IT83XX_IRQ_WKO95] = { GPIO_C, BIT(2), 9, BIT(7) }, + [IT83XX_IRQ_WKO96] = { GPIO_F, BIT(0), 10, BIT(0) }, + [IT83XX_IRQ_WKO97] = { GPIO_F, BIT(1), 10, BIT(1) }, + [IT83XX_IRQ_WKO98] = { GPIO_F, BIT(2), 10, BIT(2) }, + [IT83XX_IRQ_WKO99] = { GPIO_F, BIT(3), 10, BIT(3) }, + [IT83XX_IRQ_WKO100] = { GPIO_A, BIT(7), 10, BIT(4) }, + [IT83XX_IRQ_WKO101] = { GPIO_B, BIT(0), 10, BIT(5) }, + [IT83XX_IRQ_WKO102] = { GPIO_B, BIT(1), 10, BIT(6) }, + [IT83XX_IRQ_WKO103] = { GPIO_B, BIT(3), 10, BIT(7) }, + [IT83XX_IRQ_WKO104] = { GPIO_B, BIT(5), 11, BIT(0) }, + [IT83XX_IRQ_WKO105] = { GPIO_B, BIT(6), 11, BIT(1) }, + [IT83XX_IRQ_WKO106] = { GPIO_B, BIT(7), 11, BIT(2) }, + [IT83XX_IRQ_WKO107] = { GPIO_C, BIT(1), 11, BIT(3) }, + [IT83XX_IRQ_WKO108] = { GPIO_C, BIT(3), 11, BIT(4) }, + [IT83XX_IRQ_WKO109] = { GPIO_C, BIT(5), 11, BIT(5) }, + [IT83XX_IRQ_WKO110] = { GPIO_D, BIT(3), 11, BIT(6) }, + [IT83XX_IRQ_WKO111] = { GPIO_D, BIT(4), 11, BIT(7) }, + [IT83XX_IRQ_WKO112] = { GPIO_D, BIT(5), 12, BIT(0) }, + [IT83XX_IRQ_WKO113] = { GPIO_D, BIT(6), 12, BIT(1) }, + [IT83XX_IRQ_WKO114] = { GPIO_E, BIT(4), 12, BIT(2) }, + [IT83XX_IRQ_WKO115] = { GPIO_G, BIT(0), 12, BIT(3) }, + [IT83XX_IRQ_WKO116] = { GPIO_G, BIT(1), 12, BIT(4) }, + [IT83XX_IRQ_WKO117] = { GPIO_G, BIT(2), 12, BIT(5) }, + [IT83XX_IRQ_WKO118] = { GPIO_G, BIT(6), 12, BIT(6) }, + [IT83XX_IRQ_WKO119] = { GPIO_I, BIT(0), 12, BIT(7) }, + [IT83XX_IRQ_WKO120] = { GPIO_I, BIT(1), 13, BIT(0) }, + [IT83XX_IRQ_WKO121] = { GPIO_I, BIT(2), 13, BIT(1) }, + [IT83XX_IRQ_WKO122] = { GPIO_I, BIT(3), 13, BIT(2) }, #ifdef IT83XX_GPIO_INT_FLEXIBLE - [IT83XX_IRQ_WKO123] = {GPIO_G, BIT(3), 13, BIT(3)}, - [IT83XX_IRQ_WKO124] = {GPIO_G, BIT(4), 13, BIT(4)}, - [IT83XX_IRQ_WKO125] = {GPIO_G, BIT(5), 13, BIT(5)}, - [IT83XX_IRQ_WKO126] = {GPIO_G, BIT(7), 13, BIT(6)}, + [IT83XX_IRQ_WKO123] = { GPIO_G, BIT(3), 13, BIT(3) }, + [IT83XX_IRQ_WKO124] = { GPIO_G, BIT(4), 13, BIT(4) }, + [IT83XX_IRQ_WKO125] = { GPIO_G, BIT(5), 13, BIT(5) }, + [IT83XX_IRQ_WKO126] = { GPIO_G, BIT(7), 13, BIT(6) }, #endif - [IT83XX_IRQ_WKO128] = {GPIO_J, BIT(0), 14, BIT(0)}, - [IT83XX_IRQ_WKO129] = {GPIO_J, BIT(1), 14, BIT(1)}, - [IT83XX_IRQ_WKO130] = {GPIO_J, BIT(2), 14, BIT(2)}, - [IT83XX_IRQ_WKO131] = {GPIO_J, BIT(3), 14, BIT(3)}, - [IT83XX_IRQ_WKO132] = {GPIO_J, BIT(4), 14, BIT(4)}, - [IT83XX_IRQ_WKO133] = {GPIO_J, BIT(5), 14, BIT(5)}, - [IT83XX_IRQ_WKO134] = {GPIO_J, BIT(6), 14, BIT(6)}, - [IT83XX_IRQ_WKO135] = {GPIO_J, BIT(7), 14, BIT(7)}, - [IT83XX_IRQ_WKO136] = {GPIO_L, BIT(0), 15, BIT(0)}, - [IT83XX_IRQ_WKO137] = {GPIO_L, BIT(1), 15, BIT(1)}, - [IT83XX_IRQ_WKO138] = {GPIO_L, BIT(2), 15, BIT(2)}, - [IT83XX_IRQ_WKO139] = {GPIO_L, BIT(3), 15, BIT(3)}, - [IT83XX_IRQ_WKO140] = {GPIO_L, BIT(4), 15, BIT(4)}, - [IT83XX_IRQ_WKO141] = {GPIO_L, BIT(5), 15, BIT(5)}, - [IT83XX_IRQ_WKO142] = {GPIO_L, BIT(6), 15, BIT(6)}, - [IT83XX_IRQ_WKO143] = {GPIO_L, BIT(7), 15, BIT(7)}, + [IT83XX_IRQ_WKO128] = { GPIO_J, BIT(0), 14, BIT(0) }, + [IT83XX_IRQ_WKO129] = { GPIO_J, BIT(1), 14, BIT(1) }, + [IT83XX_IRQ_WKO130] = { GPIO_J, BIT(2), 14, BIT(2) }, + [IT83XX_IRQ_WKO131] = { GPIO_J, BIT(3), 14, BIT(3) }, + [IT83XX_IRQ_WKO132] = { GPIO_J, BIT(4), 14, BIT(4) }, + [IT83XX_IRQ_WKO133] = { GPIO_J, BIT(5), 14, BIT(5) }, + [IT83XX_IRQ_WKO134] = { GPIO_J, BIT(6), 14, BIT(6) }, + [IT83XX_IRQ_WKO135] = { GPIO_J, BIT(7), 14, BIT(7) }, + [IT83XX_IRQ_WKO136] = { GPIO_L, BIT(0), 15, BIT(0) }, + [IT83XX_IRQ_WKO137] = { GPIO_L, BIT(1), 15, BIT(1) }, + [IT83XX_IRQ_WKO138] = { GPIO_L, BIT(2), 15, BIT(2) }, + [IT83XX_IRQ_WKO139] = { GPIO_L, BIT(3), 15, BIT(3) }, + [IT83XX_IRQ_WKO140] = { GPIO_L, BIT(4), 15, BIT(4) }, + [IT83XX_IRQ_WKO141] = { GPIO_L, BIT(5), 15, BIT(5) }, + [IT83XX_IRQ_WKO142] = { GPIO_L, BIT(6), 15, BIT(6) }, + [IT83XX_IRQ_WKO143] = { GPIO_L, BIT(7), 15, BIT(7) }, #ifdef IT83XX_GPIO_INT_FLEXIBLE - [IT83XX_IRQ_WKO144] = {GPIO_M, BIT(0), 16, BIT(0)}, - [IT83XX_IRQ_WKO145] = {GPIO_M, BIT(1), 16, BIT(1)}, - [IT83XX_IRQ_WKO146] = {GPIO_M, BIT(2), 16, BIT(2)}, - [IT83XX_IRQ_WKO147] = {GPIO_M, BIT(3), 16, BIT(3)}, - [IT83XX_IRQ_WKO148] = {GPIO_M, BIT(4), 16, BIT(4)}, - [IT83XX_IRQ_WKO149] = {GPIO_M, BIT(5), 16, BIT(5)}, - [IT83XX_IRQ_WKO150] = {GPIO_M, BIT(6), 16, BIT(6)}, + [IT83XX_IRQ_WKO144] = { GPIO_M, BIT(0), 16, BIT(0) }, + [IT83XX_IRQ_WKO145] = { GPIO_M, BIT(1), 16, BIT(1) }, + [IT83XX_IRQ_WKO146] = { GPIO_M, BIT(2), 16, BIT(2) }, + [IT83XX_IRQ_WKO147] = { GPIO_M, BIT(3), 16, BIT(3) }, + [IT83XX_IRQ_WKO148] = { GPIO_M, BIT(4), 16, BIT(4) }, + [IT83XX_IRQ_WKO149] = { GPIO_M, BIT(5), 16, BIT(5) }, + [IT83XX_IRQ_WKO150] = { GPIO_M, BIT(6), 16, BIT(6) }, #endif #if defined(CHIP_FAMILY_IT8XXX1) || defined(CHIP_FAMILY_IT8XXX2) - [IT83XX_IRQ_GPO0] = {GPIO_O, BIT(0), 19, BIT(0)}, - [IT83XX_IRQ_GPO1] = {GPIO_O, BIT(1), 19, BIT(1)}, - [IT83XX_IRQ_GPO2] = {GPIO_O, BIT(2), 19, BIT(2)}, - [IT83XX_IRQ_GPO3] = {GPIO_O, BIT(3), 19, BIT(3)}, - [IT83XX_IRQ_GPP0] = {GPIO_P, BIT(0), 20, BIT(0)}, - [IT83XX_IRQ_GPP1] = {GPIO_P, BIT(1), 20, BIT(1)}, - [IT83XX_IRQ_GPP2] = {GPIO_P, BIT(2), 20, BIT(2)}, - [IT83XX_IRQ_GPP3] = {GPIO_P, BIT(3), 20, BIT(3)}, - [IT83XX_IRQ_GPP4] = {GPIO_P, BIT(4), 20, BIT(4)}, - [IT83XX_IRQ_GPP5] = {GPIO_P, BIT(5), 20, BIT(5)}, - [IT83XX_IRQ_GPP6] = {GPIO_P, BIT(6), 20, BIT(6)}, - [IT83XX_IRQ_GPQ0] = {GPIO_Q, BIT(0), 21, BIT(0)}, - [IT83XX_IRQ_GPQ1] = {GPIO_Q, BIT(1), 21, BIT(1)}, - [IT83XX_IRQ_GPQ2] = {GPIO_Q, BIT(2), 21, BIT(2)}, - [IT83XX_IRQ_GPQ3] = {GPIO_Q, BIT(3), 21, BIT(3)}, - [IT83XX_IRQ_GPQ4] = {GPIO_Q, BIT(4), 21, BIT(4)}, - [IT83XX_IRQ_GPQ5] = {GPIO_Q, BIT(5), 21, BIT(5)}, - [IT83XX_IRQ_GPR0] = {GPIO_R, BIT(0), 22, BIT(0)}, - [IT83XX_IRQ_GPR1] = {GPIO_R, BIT(1), 22, BIT(1)}, - [IT83XX_IRQ_GPR2] = {GPIO_R, BIT(2), 22, BIT(2)}, - [IT83XX_IRQ_GPR3] = {GPIO_R, BIT(3), 22, BIT(3)}, - [IT83XX_IRQ_GPR4] = {GPIO_R, BIT(4), 22, BIT(4)}, - [IT83XX_IRQ_GPR5] = {GPIO_R, BIT(5), 22, BIT(5)}, + [IT83XX_IRQ_GPO0] = { GPIO_O, BIT(0), 19, BIT(0) }, + [IT83XX_IRQ_GPO1] = { GPIO_O, BIT(1), 19, BIT(1) }, + [IT83XX_IRQ_GPO2] = { GPIO_O, BIT(2), 19, BIT(2) }, + [IT83XX_IRQ_GPO3] = { GPIO_O, BIT(3), 19, BIT(3) }, + [IT83XX_IRQ_GPP0] = { GPIO_P, BIT(0), 20, BIT(0) }, + [IT83XX_IRQ_GPP1] = { GPIO_P, BIT(1), 20, BIT(1) }, + [IT83XX_IRQ_GPP2] = { GPIO_P, BIT(2), 20, BIT(2) }, + [IT83XX_IRQ_GPP3] = { GPIO_P, BIT(3), 20, BIT(3) }, + [IT83XX_IRQ_GPP4] = { GPIO_P, BIT(4), 20, BIT(4) }, + [IT83XX_IRQ_GPP5] = { GPIO_P, BIT(5), 20, BIT(5) }, + [IT83XX_IRQ_GPP6] = { GPIO_P, BIT(6), 20, BIT(6) }, + [IT83XX_IRQ_GPQ0] = { GPIO_Q, BIT(0), 21, BIT(0) }, + [IT83XX_IRQ_GPQ1] = { GPIO_Q, BIT(1), 21, BIT(1) }, + [IT83XX_IRQ_GPQ2] = { GPIO_Q, BIT(2), 21, BIT(2) }, + [IT83XX_IRQ_GPQ3] = { GPIO_Q, BIT(3), 21, BIT(3) }, + [IT83XX_IRQ_GPQ4] = { GPIO_Q, BIT(4), 21, BIT(4) }, + [IT83XX_IRQ_GPQ5] = { GPIO_Q, BIT(5), 21, BIT(5) }, + [IT83XX_IRQ_GPR0] = { GPIO_R, BIT(0), 22, BIT(0) }, + [IT83XX_IRQ_GPR1] = { GPIO_R, BIT(1), 22, BIT(1) }, + [IT83XX_IRQ_GPR2] = { GPIO_R, BIT(2), 22, BIT(2) }, + [IT83XX_IRQ_GPR3] = { GPIO_R, BIT(3), 22, BIT(3) }, + [IT83XX_IRQ_GPR4] = { GPIO_R, BIT(4), 22, BIT(4) }, + [IT83XX_IRQ_GPR5] = { GPIO_R, BIT(5), 22, BIT(5) }, #endif - [IT83XX_IRQ_COUNT] = { 0, 0, 0, 0}, + [IT83XX_IRQ_COUNT] = { 0, 0, 0, 0 }, }; BUILD_ASSERT(ARRAY_SIZE(gpio_irqs) == IT83XX_IRQ_COUNT + 1); @@ -246,7 +264,7 @@ static int gpio_to_irq(uint8_t port, uint8_t mask) for (i = 0; i < IT83XX_IRQ_COUNT; i++) { if (gpio_irqs[i].gpio_port == port && - gpio_irqs[i].gpio_mask == mask) + gpio_irqs[i].gpio_mask == mask) return i; } @@ -260,133 +278,133 @@ struct gpio_1p8v_t { static const struct gpio_1p8v_t gpio_1p8v_sel[GPIO_PORT_COUNT][8] = { #ifdef IT83XX_GPIO_1P8V_PIN_EXTENDED - [GPIO_A] = { [4] = {&IT83XX_GPIO_GRC24, BIT(0)}, - [5] = {&IT83XX_GPIO_GRC24, BIT(1)}, - [6] = {&IT83XX_GPIO_GRC24, BIT(5)}, - [7] = {&IT83XX_GPIO_GRC24, BIT(6)} }, - [GPIO_B] = { [3] = {&IT83XX_GPIO_GRC22, BIT(1)}, - [4] = {&IT83XX_GPIO_GRC22, BIT(0)}, - [5] = {&IT83XX_GPIO_GRC19, BIT(7)}, - [6] = {&IT83XX_GPIO_GRC19, BIT(6)}, - [7] = {&IT83XX_GPIO_GRC24, BIT(4)} }, - [GPIO_C] = { [0] = {&IT83XX_GPIO_GRC22, BIT(7)}, - [1] = {&IT83XX_GPIO_GRC19, BIT(5)}, - [2] = {&IT83XX_GPIO_GRC19, BIT(4)}, - [4] = {&IT83XX_GPIO_GRC24, BIT(2)}, - [6] = {&IT83XX_GPIO_GRC24, BIT(3)}, - [7] = {&IT83XX_GPIO_GRC19, BIT(3)} }, - [GPIO_D] = { [0] = {&IT83XX_GPIO_GRC19, BIT(2)}, - [1] = {&IT83XX_GPIO_GRC19, BIT(1)}, - [2] = {&IT83XX_GPIO_GRC19, BIT(0)}, - [3] = {&IT83XX_GPIO_GRC20, BIT(7)}, - [4] = {&IT83XX_GPIO_GRC20, BIT(6)}, - [5] = {&IT83XX_GPIO_GRC22, BIT(4)}, - [6] = {&IT83XX_GPIO_GRC22, BIT(5)}, - [7] = {&IT83XX_GPIO_GRC22, BIT(6)} }, - [GPIO_E] = { [0] = {&IT83XX_GPIO_GRC20, BIT(5)}, - [1] = {&IT83XX_GPIO_GCR28, BIT(6)}, - [2] = {&IT83XX_GPIO_GCR28, BIT(7)}, - [4] = {&IT83XX_GPIO_GRC22, BIT(2)}, - [5] = {&IT83XX_GPIO_GRC22, BIT(3)}, - [6] = {&IT83XX_GPIO_GRC20, BIT(4)}, - [7] = {&IT83XX_GPIO_GRC20, BIT(3)} }, - [GPIO_F] = { [0] = {&IT83XX_GPIO_GCR28, BIT(4)}, - [1] = {&IT83XX_GPIO_GCR28, BIT(5)}, - [2] = {&IT83XX_GPIO_GRC20, BIT(2)}, - [3] = {&IT83XX_GPIO_GRC20, BIT(1)}, - [4] = {&IT83XX_GPIO_GRC20, BIT(0)}, - [5] = {&IT83XX_GPIO_GRC21, BIT(7)}, - [6] = {&IT83XX_GPIO_GRC21, BIT(6)}, - [7] = {&IT83XX_GPIO_GRC21, BIT(5)} }, - [GPIO_G] = { [0] = {&IT83XX_GPIO_GCR28, BIT(2)}, - [1] = {&IT83XX_GPIO_GRC21, BIT(4)}, - [2] = {&IT83XX_GPIO_GCR28, BIT(3)}, - [6] = {&IT83XX_GPIO_GRC21, BIT(3)} }, - [GPIO_H] = { [0] = {&IT83XX_GPIO_GRC21, BIT(2)}, - [1] = {&IT83XX_GPIO_GRC21, BIT(1)}, - [2] = {&IT83XX_GPIO_GRC21, BIT(0)}, - [5] = {&IT83XX_GPIO_GCR27, BIT(7)}, - [6] = {&IT83XX_GPIO_GCR28, BIT(0)} }, - [GPIO_I] = { [0] = {&IT83XX_GPIO_GCR27, BIT(3)}, - [1] = {&IT83XX_GPIO_GRC23, BIT(4)}, - [2] = {&IT83XX_GPIO_GRC23, BIT(5)}, - [3] = {&IT83XX_GPIO_GRC23, BIT(6)}, - [4] = {&IT83XX_GPIO_GRC23, BIT(7)}, - [5] = {&IT83XX_GPIO_GCR27, BIT(4)}, - [6] = {&IT83XX_GPIO_GCR27, BIT(5)}, - [7] = {&IT83XX_GPIO_GCR27, BIT(6)} }, - [GPIO_J] = { [0] = {&IT83XX_GPIO_GRC23, BIT(0)}, - [1] = {&IT83XX_GPIO_GRC23, BIT(1)}, - [2] = {&IT83XX_GPIO_GRC23, BIT(2)}, - [3] = {&IT83XX_GPIO_GRC23, BIT(3)}, - [4] = {&IT83XX_GPIO_GCR27, BIT(0)}, - [5] = {&IT83XX_GPIO_GCR27, BIT(1)}, - [6] = {&IT83XX_GPIO_GCR27, BIT(2)}, - [7] = {&IT83XX_GPIO_GCR33, BIT(2)} }, - [GPIO_K] = { [0] = {&IT83XX_GPIO_GCR26, BIT(0)}, - [1] = {&IT83XX_GPIO_GCR26, BIT(1)}, - [2] = {&IT83XX_GPIO_GCR26, BIT(2)}, - [3] = {&IT83XX_GPIO_GCR26, BIT(3)}, - [4] = {&IT83XX_GPIO_GCR26, BIT(4)}, - [5] = {&IT83XX_GPIO_GCR26, BIT(5)}, - [6] = {&IT83XX_GPIO_GCR26, BIT(6)}, - [7] = {&IT83XX_GPIO_GCR26, BIT(7)} }, - [GPIO_L] = { [0] = {&IT83XX_GPIO_GCR25, BIT(0)}, - [1] = {&IT83XX_GPIO_GCR25, BIT(1)}, - [2] = {&IT83XX_GPIO_GCR25, BIT(2)}, - [3] = {&IT83XX_GPIO_GCR25, BIT(3)}, - [4] = {&IT83XX_GPIO_GCR25, BIT(4)}, - [5] = {&IT83XX_GPIO_GCR25, BIT(5)}, - [6] = {&IT83XX_GPIO_GCR25, BIT(6)}, - [7] = {&IT83XX_GPIO_GCR25, BIT(7)} }, + [GPIO_A] = { [4] = { &IT83XX_GPIO_GRC24, BIT(0) }, + [5] = { &IT83XX_GPIO_GRC24, BIT(1) }, + [6] = { &IT83XX_GPIO_GRC24, BIT(5) }, + [7] = { &IT83XX_GPIO_GRC24, BIT(6) } }, + [GPIO_B] = { [3] = { &IT83XX_GPIO_GRC22, BIT(1) }, + [4] = { &IT83XX_GPIO_GRC22, BIT(0) }, + [5] = { &IT83XX_GPIO_GRC19, BIT(7) }, + [6] = { &IT83XX_GPIO_GRC19, BIT(6) }, + [7] = { &IT83XX_GPIO_GRC24, BIT(4) } }, + [GPIO_C] = { [0] = { &IT83XX_GPIO_GRC22, BIT(7) }, + [1] = { &IT83XX_GPIO_GRC19, BIT(5) }, + [2] = { &IT83XX_GPIO_GRC19, BIT(4) }, + [4] = { &IT83XX_GPIO_GRC24, BIT(2) }, + [6] = { &IT83XX_GPIO_GRC24, BIT(3) }, + [7] = { &IT83XX_GPIO_GRC19, BIT(3) } }, + [GPIO_D] = { [0] = { &IT83XX_GPIO_GRC19, BIT(2) }, + [1] = { &IT83XX_GPIO_GRC19, BIT(1) }, + [2] = { &IT83XX_GPIO_GRC19, BIT(0) }, + [3] = { &IT83XX_GPIO_GRC20, BIT(7) }, + [4] = { &IT83XX_GPIO_GRC20, BIT(6) }, + [5] = { &IT83XX_GPIO_GRC22, BIT(4) }, + [6] = { &IT83XX_GPIO_GRC22, BIT(5) }, + [7] = { &IT83XX_GPIO_GRC22, BIT(6) } }, + [GPIO_E] = { [0] = { &IT83XX_GPIO_GRC20, BIT(5) }, + [1] = { &IT83XX_GPIO_GCR28, BIT(6) }, + [2] = { &IT83XX_GPIO_GCR28, BIT(7) }, + [4] = { &IT83XX_GPIO_GRC22, BIT(2) }, + [5] = { &IT83XX_GPIO_GRC22, BIT(3) }, + [6] = { &IT83XX_GPIO_GRC20, BIT(4) }, + [7] = { &IT83XX_GPIO_GRC20, BIT(3) } }, + [GPIO_F] = { [0] = { &IT83XX_GPIO_GCR28, BIT(4) }, + [1] = { &IT83XX_GPIO_GCR28, BIT(5) }, + [2] = { &IT83XX_GPIO_GRC20, BIT(2) }, + [3] = { &IT83XX_GPIO_GRC20, BIT(1) }, + [4] = { &IT83XX_GPIO_GRC20, BIT(0) }, + [5] = { &IT83XX_GPIO_GRC21, BIT(7) }, + [6] = { &IT83XX_GPIO_GRC21, BIT(6) }, + [7] = { &IT83XX_GPIO_GRC21, BIT(5) } }, + [GPIO_G] = { [0] = { &IT83XX_GPIO_GCR28, BIT(2) }, + [1] = { &IT83XX_GPIO_GRC21, BIT(4) }, + [2] = { &IT83XX_GPIO_GCR28, BIT(3) }, + [6] = { &IT83XX_GPIO_GRC21, BIT(3) } }, + [GPIO_H] = { [0] = { &IT83XX_GPIO_GRC21, BIT(2) }, + [1] = { &IT83XX_GPIO_GRC21, BIT(1) }, + [2] = { &IT83XX_GPIO_GRC21, BIT(0) }, + [5] = { &IT83XX_GPIO_GCR27, BIT(7) }, + [6] = { &IT83XX_GPIO_GCR28, BIT(0) } }, + [GPIO_I] = { [0] = { &IT83XX_GPIO_GCR27, BIT(3) }, + [1] = { &IT83XX_GPIO_GRC23, BIT(4) }, + [2] = { &IT83XX_GPIO_GRC23, BIT(5) }, + [3] = { &IT83XX_GPIO_GRC23, BIT(6) }, + [4] = { &IT83XX_GPIO_GRC23, BIT(7) }, + [5] = { &IT83XX_GPIO_GCR27, BIT(4) }, + [6] = { &IT83XX_GPIO_GCR27, BIT(5) }, + [7] = { &IT83XX_GPIO_GCR27, BIT(6) } }, + [GPIO_J] = { [0] = { &IT83XX_GPIO_GRC23, BIT(0) }, + [1] = { &IT83XX_GPIO_GRC23, BIT(1) }, + [2] = { &IT83XX_GPIO_GRC23, BIT(2) }, + [3] = { &IT83XX_GPIO_GRC23, BIT(3) }, + [4] = { &IT83XX_GPIO_GCR27, BIT(0) }, + [5] = { &IT83XX_GPIO_GCR27, BIT(1) }, + [6] = { &IT83XX_GPIO_GCR27, BIT(2) }, + [7] = { &IT83XX_GPIO_GCR33, BIT(2) } }, + [GPIO_K] = { [0] = { &IT83XX_GPIO_GCR26, BIT(0) }, + [1] = { &IT83XX_GPIO_GCR26, BIT(1) }, + [2] = { &IT83XX_GPIO_GCR26, BIT(2) }, + [3] = { &IT83XX_GPIO_GCR26, BIT(3) }, + [4] = { &IT83XX_GPIO_GCR26, BIT(4) }, + [5] = { &IT83XX_GPIO_GCR26, BIT(5) }, + [6] = { &IT83XX_GPIO_GCR26, BIT(6) }, + [7] = { &IT83XX_GPIO_GCR26, BIT(7) } }, + [GPIO_L] = { [0] = { &IT83XX_GPIO_GCR25, BIT(0) }, + [1] = { &IT83XX_GPIO_GCR25, BIT(1) }, + [2] = { &IT83XX_GPIO_GCR25, BIT(2) }, + [3] = { &IT83XX_GPIO_GCR25, BIT(3) }, + [4] = { &IT83XX_GPIO_GCR25, BIT(4) }, + [5] = { &IT83XX_GPIO_GCR25, BIT(5) }, + [6] = { &IT83XX_GPIO_GCR25, BIT(6) }, + [7] = { &IT83XX_GPIO_GCR25, BIT(7) } }, #if defined(CHIP_FAMILY_IT8XXX1) || defined(CHIP_FAMILY_IT8XXX2) - [GPIO_O] = { [0] = {&IT83XX_GPIO_GCR31, BIT(0)}, - [1] = {&IT83XX_GPIO_GCR31, BIT(1)}, - [2] = {&IT83XX_GPIO_GCR31, BIT(2)}, - [3] = {&IT83XX_GPIO_GCR31, BIT(3)} }, - [GPIO_P] = { [0] = {&IT83XX_GPIO_GCR32, BIT(0)}, - [1] = {&IT83XX_GPIO_GCR32, BIT(1)}, - [2] = {&IT83XX_GPIO_GCR32, BIT(2)}, - [3] = {&IT83XX_GPIO_GCR32, BIT(3)}, - [4] = {&IT83XX_GPIO_GCR32, BIT(4)}, - [5] = {&IT83XX_GPIO_GCR32, BIT(5)}, - [6] = {&IT83XX_GPIO_GCR32, BIT(6)} }, + [GPIO_O] = { [0] = { &IT83XX_GPIO_GCR31, BIT(0) }, + [1] = { &IT83XX_GPIO_GCR31, BIT(1) }, + [2] = { &IT83XX_GPIO_GCR31, BIT(2) }, + [3] = { &IT83XX_GPIO_GCR31, BIT(3) } }, + [GPIO_P] = { [0] = { &IT83XX_GPIO_GCR32, BIT(0) }, + [1] = { &IT83XX_GPIO_GCR32, BIT(1) }, + [2] = { &IT83XX_GPIO_GCR32, BIT(2) }, + [3] = { &IT83XX_GPIO_GCR32, BIT(3) }, + [4] = { &IT83XX_GPIO_GCR32, BIT(4) }, + [5] = { &IT83XX_GPIO_GCR32, BIT(5) }, + [6] = { &IT83XX_GPIO_GCR32, BIT(6) } }, #endif #else - [GPIO_A] = { [4] = {&IT83XX_GPIO_GRC24, BIT(0)}, - [5] = {&IT83XX_GPIO_GRC24, BIT(1)} }, - [GPIO_B] = { [3] = {&IT83XX_GPIO_GRC22, BIT(1)}, - [4] = {&IT83XX_GPIO_GRC22, BIT(0)}, - [5] = {&IT83XX_GPIO_GRC19, BIT(7)}, - [6] = {&IT83XX_GPIO_GRC19, BIT(6)} }, - [GPIO_C] = { [1] = {&IT83XX_GPIO_GRC19, BIT(5)}, - [2] = {&IT83XX_GPIO_GRC19, BIT(4)}, - [7] = {&IT83XX_GPIO_GRC19, BIT(3)} }, - [GPIO_D] = { [0] = {&IT83XX_GPIO_GRC19, BIT(2)}, - [1] = {&IT83XX_GPIO_GRC19, BIT(1)}, - [2] = {&IT83XX_GPIO_GRC19, BIT(0)}, - [3] = {&IT83XX_GPIO_GRC20, BIT(7)}, - [4] = {&IT83XX_GPIO_GRC20, BIT(6)} }, - [GPIO_E] = { [0] = {&IT83XX_GPIO_GRC20, BIT(5)}, - [6] = {&IT83XX_GPIO_GRC20, BIT(4)}, - [7] = {&IT83XX_GPIO_GRC20, BIT(3)} }, - [GPIO_F] = { [2] = {&IT83XX_GPIO_GRC20, BIT(2)}, - [3] = {&IT83XX_GPIO_GRC20, BIT(1)}, - [4] = {&IT83XX_GPIO_GRC20, BIT(0)}, - [5] = {&IT83XX_GPIO_GRC21, BIT(7)}, - [6] = {&IT83XX_GPIO_GRC21, BIT(6)}, - [7] = {&IT83XX_GPIO_GRC21, BIT(5)} }, - [GPIO_H] = { [0] = {&IT83XX_GPIO_GRC21, BIT(2)}, - [1] = {&IT83XX_GPIO_GRC21, BIT(1)}, - [2] = {&IT83XX_GPIO_GRC21, BIT(0)} }, - [GPIO_I] = { [1] = {&IT83XX_GPIO_GRC23, BIT(4)}, - [2] = {&IT83XX_GPIO_GRC23, BIT(5)}, - [3] = {&IT83XX_GPIO_GRC23, BIT(6)}, - [4] = {&IT83XX_GPIO_GRC23, BIT(7)} }, - [GPIO_J] = { [0] = {&IT83XX_GPIO_GRC23, BIT(0)}, - [1] = {&IT83XX_GPIO_GRC23, BIT(1)}, - [2] = {&IT83XX_GPIO_GRC23, BIT(2)}, - [3] = {&IT83XX_GPIO_GRC23, BIT(3)} }, + [GPIO_A] = { [4] = { &IT83XX_GPIO_GRC24, BIT(0) }, + [5] = { &IT83XX_GPIO_GRC24, BIT(1) } }, + [GPIO_B] = { [3] = { &IT83XX_GPIO_GRC22, BIT(1) }, + [4] = { &IT83XX_GPIO_GRC22, BIT(0) }, + [5] = { &IT83XX_GPIO_GRC19, BIT(7) }, + [6] = { &IT83XX_GPIO_GRC19, BIT(6) } }, + [GPIO_C] = { [1] = { &IT83XX_GPIO_GRC19, BIT(5) }, + [2] = { &IT83XX_GPIO_GRC19, BIT(4) }, + [7] = { &IT83XX_GPIO_GRC19, BIT(3) } }, + [GPIO_D] = { [0] = { &IT83XX_GPIO_GRC19, BIT(2) }, + [1] = { &IT83XX_GPIO_GRC19, BIT(1) }, + [2] = { &IT83XX_GPIO_GRC19, BIT(0) }, + [3] = { &IT83XX_GPIO_GRC20, BIT(7) }, + [4] = { &IT83XX_GPIO_GRC20, BIT(6) } }, + [GPIO_E] = { [0] = { &IT83XX_GPIO_GRC20, BIT(5) }, + [6] = { &IT83XX_GPIO_GRC20, BIT(4) }, + [7] = { &IT83XX_GPIO_GRC20, BIT(3) } }, + [GPIO_F] = { [2] = { &IT83XX_GPIO_GRC20, BIT(2) }, + [3] = { &IT83XX_GPIO_GRC20, BIT(1) }, + [4] = { &IT83XX_GPIO_GRC20, BIT(0) }, + [5] = { &IT83XX_GPIO_GRC21, BIT(7) }, + [6] = { &IT83XX_GPIO_GRC21, BIT(6) }, + [7] = { &IT83XX_GPIO_GRC21, BIT(5) } }, + [GPIO_H] = { [0] = { &IT83XX_GPIO_GRC21, BIT(2) }, + [1] = { &IT83XX_GPIO_GRC21, BIT(1) }, + [2] = { &IT83XX_GPIO_GRC21, BIT(0) } }, + [GPIO_I] = { [1] = { &IT83XX_GPIO_GRC23, BIT(4) }, + [2] = { &IT83XX_GPIO_GRC23, BIT(5) }, + [3] = { &IT83XX_GPIO_GRC23, BIT(6) }, + [4] = { &IT83XX_GPIO_GRC23, BIT(7) } }, + [GPIO_J] = { [0] = { &IT83XX_GPIO_GRC23, BIT(0) }, + [1] = { &IT83XX_GPIO_GRC23, BIT(1) }, + [2] = { &IT83XX_GPIO_GRC23, BIT(2) }, + [3] = { &IT83XX_GPIO_GRC23, BIT(3) } }, #endif }; @@ -405,26 +423,45 @@ static void gpio_1p8v_3p3v_sel_by_pin(uint8_t port, uint8_t pin, int sel_1p8v) } static inline void it83xx_set_alt_func(uint32_t port, uint32_t pin, - enum gpio_alternate_func func) + enum gpio_alternate_func func) { /* * If func is not ALT_FUNC_NONE, set for alternate function. * Otherwise, turn the pin into an input as it's default. */ if (func != GPIO_ALT_FUNC_NONE) - IT83XX_GPIO_CTRL(port, pin) &= ~(GPCR_PORT_PIN_MODE_OUTPUT | - GPCR_PORT_PIN_MODE_INPUT); + IT83XX_GPIO_CTRL(port, pin) &= + ~(GPCR_PORT_PIN_MODE_OUTPUT | GPCR_PORT_PIN_MODE_INPUT); else - IT83XX_GPIO_CTRL(port, pin) = - (IT83XX_GPIO_CTRL(port, pin) | GPCR_PORT_PIN_MODE_INPUT) - & ~GPCR_PORT_PIN_MODE_OUTPUT; + IT83XX_GPIO_CTRL(port, pin) = (IT83XX_GPIO_CTRL(port, pin) | + GPCR_PORT_PIN_MODE_INPUT) & + ~GPCR_PORT_PIN_MODE_OUTPUT; } void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) + enum gpio_alternate_func func) { uint32_t pin = 0; + /* Alternate function configuration for KSI/KSO pins */ + if (port > GPIO_PORT_COUNT) { + port -= GPIO_KSI; + /* + * If func is non-negative, set for keyboard scan function. + * Otherwise, turn the pin into a GPIO input. + */ + if (func >= GPIO_ALT_FUNC_DEFAULT) { + /* KBS mode */ + *kbs_gpio_ctrl_regs[port].gpio_mode &= ~mask; + } else { + /* input */ + *kbs_gpio_ctrl_regs[port].gpio_out &= ~mask; + /* GPIO mode */ + *kbs_gpio_ctrl_regs[port].gpio_mode |= mask; + } + return; + } + /* For each bit high in the mask, set that pin to use alt. func. */ while (mask > 0) { if (mask & 1) @@ -437,7 +474,9 @@ void gpio_set_alternate_function(uint32_t port, uint32_t mask, test_mockable int gpio_get_level(enum gpio_signal signal) { return (IT83XX_GPIO_DATA_MIRROR(gpio_list[signal].port) & - gpio_list[signal].mask) ? 1 : 0; + gpio_list[signal].mask) ? + 1 : + 0; } void gpio_set_level(enum gpio_signal signal, int value) @@ -447,22 +486,53 @@ void gpio_set_level(enum gpio_signal signal, int value) if (value) IT83XX_GPIO_DATA(gpio_list[signal].port) |= - gpio_list[signal].mask; + gpio_list[signal].mask; else IT83XX_GPIO_DATA(gpio_list[signal].port) &= - ~gpio_list[signal].mask; + ~gpio_list[signal].mask; /* restore interrupts */ set_int_mask(int_mask); } void gpio_kbs_pin_gpio_mode(uint32_t port, uint32_t mask, uint32_t flags) { - if (port == GPIO_KSO_H) - IT83XX_KBS_KSOHGCTRL |= mask; - else if (port == GPIO_KSO_L) - IT83XX_KBS_KSOLGCTRL |= mask; - else if (port == GPIO_KSI) - IT83XX_KBS_KSIGCTRL |= mask; + uint32_t idx = port - GPIO_KSI; + + /* Set GPIO mode */ + *kbs_gpio_ctrl_regs[idx].gpio_mode |= mask; + + /* Set input or output */ + if (flags & GPIO_OUTPUT) { + /* + * Select open drain first, so that we don't glitch the signal + * when changing the line to an output. + */ + if (flags & GPIO_OPEN_DRAIN) + /* + * it83xx: need external pullup for output data high + * it8xxx2: this pin is always internal pullup + */ + IT83XX_GPIO_GPOT(port) |= mask; + else + /* + * it8xxx2: this pin is not internal pullup + */ + IT83XX_GPIO_GPOT(port) &= ~mask; + + /* Set level before change to output. */ + if (flags & GPIO_HIGH) + IT83XX_GPIO_DATA(port) |= mask; + else if (flags & GPIO_LOW) + IT83XX_GPIO_DATA(port) &= ~mask; + *kbs_gpio_ctrl_regs[idx].gpio_out |= mask; + } else { + *kbs_gpio_ctrl_regs[idx].gpio_out &= ~mask; + if (flags & GPIO_PULL_UP) + IT83XX_GPIO_GPOT(port) |= mask; + else + /* No internal pullup and pulldown */ + IT83XX_GPIO_GPOT(port) &= ~mask; + } } #ifndef IT83XX_GPIO_INT_FLEXIBLE @@ -495,8 +565,8 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) uint32_t pin = 0; uint32_t mask_copy = mask; + /* Set GPIO mode for KSI/KSO pins */ if (port > GPIO_PORT_COUNT) { - /* set up GPIO of KSO/KSI pins (support input only). */ gpio_kbs_pin_gpio_mode(port, mask, flags); return; } @@ -524,26 +594,26 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) /* Set input or output. */ if (flags & GPIO_OUTPUT) IT83XX_GPIO_CTRL(port, pin) = - (IT83XX_GPIO_CTRL(port, pin) | - GPCR_PORT_PIN_MODE_OUTPUT) & - ~GPCR_PORT_PIN_MODE_INPUT; + (IT83XX_GPIO_CTRL(port, pin) | + GPCR_PORT_PIN_MODE_OUTPUT) & + ~GPCR_PORT_PIN_MODE_INPUT; else IT83XX_GPIO_CTRL(port, pin) = - (IT83XX_GPIO_CTRL(port, pin) | - GPCR_PORT_PIN_MODE_INPUT) & - ~GPCR_PORT_PIN_MODE_OUTPUT; + (IT83XX_GPIO_CTRL(port, pin) | + GPCR_PORT_PIN_MODE_INPUT) & + ~GPCR_PORT_PIN_MODE_OUTPUT; /* Handle pullup / pulldown */ if (flags & GPIO_PULL_UP) { IT83XX_GPIO_CTRL(port, pin) = - (IT83XX_GPIO_CTRL(port, pin) | - GPCR_PORT_PIN_MODE_PULLUP) & - ~GPCR_PORT_PIN_MODE_PULLDOWN; + (IT83XX_GPIO_CTRL(port, pin) | + GPCR_PORT_PIN_MODE_PULLUP) & + ~GPCR_PORT_PIN_MODE_PULLDOWN; } else if (flags & GPIO_PULL_DOWN) { IT83XX_GPIO_CTRL(port, pin) = - (IT83XX_GPIO_CTRL(port, pin) | - GPCR_PORT_PIN_MODE_PULLDOWN) & - ~GPCR_PORT_PIN_MODE_PULLUP; + (IT83XX_GPIO_CTRL(port, pin) | + GPCR_PORT_PIN_MODE_PULLDOWN) & + ~GPCR_PORT_PIN_MODE_PULLUP; } else { /* No pull up/down */ IT83XX_GPIO_CTRL(port, pin) &= @@ -553,7 +623,7 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) /* To select 1.8v or 3.3v support. */ gpio_1p8v_3p3v_sel_by_pin(port, pin, - (flags & GPIO_SEL_1P8V)); + (flags & GPIO_SEL_1P8V)); } pin++; @@ -667,6 +737,24 @@ void gpio_pre_init(void) IT83XX_GPIO_GCR = 0x06; +#if !defined(CONFIG_IT83XX_VCC_1P8V) && !defined(CONFIG_IT83XX_VCC_3P3V) +#error Please select voltage level of VCC for EC. +#endif + +#if defined(CONFIG_IT83XX_VCC_1P8V) && defined(CONFIG_IT83XX_VCC_3P3V) +#error Must select only one voltage level of VCC for EC. +#endif + /* The power level of GPM6 follows VCC */ + IT83XX_GPIO_GCR29 |= BIT(0); + + /* The power level (VCC) of GPM0~6 is 1.8V */ + if (IS_ENABLED(CONFIG_IT83XX_VCC_1P8V)) + IT83XX_GPIO_GCR30 |= BIT(4); + + /* The power level (VCC) of GPM0~6 is 3.3V */ + if (IS_ENABLED(CONFIG_IT83XX_VCC_3P3V)) + IT83XX_GPIO_GCR30 &= ~BIT(4); + #if IT83XX_USBPD_PHY_PORT_COUNT < CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT #error "ITE pd active port count should be less than physical port count !" #endif @@ -719,10 +807,12 @@ void gpio_pre_init(void) */ if (IS_ENABLED(IT83XX_GPIO_GROUP_K_L_DEFAULT_PULL_DOWN)) { for (i = 0; i < 8; i++) { - IT83XX_GPIO_CTRL(GPIO_K, i) = (GPCR_PORT_PIN_MODE_INPUT - | GPCR_PORT_PIN_MODE_PULLDOWN); - IT83XX_GPIO_CTRL(GPIO_L, i) = (GPCR_PORT_PIN_MODE_INPUT - | GPCR_PORT_PIN_MODE_PULLDOWN); + IT83XX_GPIO_CTRL(GPIO_K, i) = + (GPCR_PORT_PIN_MODE_INPUT | + GPCR_PORT_PIN_MODE_PULLDOWN); + IT83XX_GPIO_CTRL(GPIO_L, i) = + (GPCR_PORT_PIN_MODE_INPUT | + GPCR_PORT_PIN_MODE_PULLDOWN); } } @@ -786,7 +876,10 @@ static void __gpio_irq(void) /* Determine interrupt number. */ int irq = intc_get_ec_int(); -#ifdef HAS_TASK_KEYSCAN + /* assert failure if interrupt number is zero */ + ASSERT(irq); + +#if defined(HAS_TASK_KEYSCAN) && !defined(CONFIG_KEYBOARD_DISCRETE) if (irq == IT83XX_IRQ_WKINTC) { keyboard_raw_interrupt(); return; diff --git a/chip/it83xx/hwtimer.c b/chip/it83xx/hwtimer.c index 291751a1cb..13c28ca57e 100644 --- a/chip/it83xx/hwtimer.c +++ b/chip/it83xx/hwtimer.c @@ -1,12 +1,12 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Hardware timers driver */ -#include "cpu.h" #include "common.h" +#include "cpu.h" #include "hooks.h" #include "hwtimer.h" #include "hwtimer_chip.h" @@ -55,18 +55,18 @@ #define MS_TO_COUNT(hz, ms) ((hz) * (ms) / 1000) const struct ext_timer_ctrl_t et_ctrl_regs[] = { - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x08, - IT83XX_IRQ_EXT_TIMER3}, - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x10, - IT83XX_IRQ_EXT_TIMER4}, - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x20, - IT83XX_IRQ_EXT_TIMER5}, - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x40, - IT83XX_IRQ_EXT_TIMER6}, - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x80, - IT83XX_IRQ_EXT_TIMER7}, - {&IT83XX_INTC_IELMR10, &IT83XX_INTC_IPOLR10, &IT83XX_INTC_ISR10, 0x01, - IT83XX_IRQ_EXT_TMR8}, + { &IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x08, + IT83XX_IRQ_EXT_TIMER3 }, + { &IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x10, + IT83XX_IRQ_EXT_TIMER4 }, + { &IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x20, + IT83XX_IRQ_EXT_TIMER5 }, + { &IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x40, + IT83XX_IRQ_EXT_TIMER6 }, + { &IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x80, + IT83XX_IRQ_EXT_TIMER7 }, + { &IT83XX_INTC_IELMR10, &IT83XX_INTC_IPOLR10, &IT83XX_INTC_ISR10, 0x01, + IT83XX_IRQ_EXT_TMR8 }, }; BUILD_ASSERT(ARRAY_SIZE(et_ctrl_regs) == EXT_TIMER_COUNT); @@ -128,7 +128,8 @@ void __hw_clock_event_set(uint32_t deadline) wait = deadline - __hw_clock_source_read(); IT83XX_ETWD_ETXCNTLR(EVENT_EXT_TIMER) = wait < EVENT_TIMER_COUNT_TO_US(0xffffffff) ? - EVENT_TIMER_US_TO_COUNT(wait) : 0xffffffff; + EVENT_TIMER_US_TO_COUNT(wait) : + 0xffffffff; /* enable and re-start timer */ IT83XX_ETWD_ETXCTRL(EVENT_EXT_TIMER) |= 0x03; task_enable_irq(et_ctrl_regs[EVENT_EXT_TIMER].irq); @@ -206,6 +207,13 @@ static void __hw_clock_source_irq(void) } #endif +#ifdef CONFIG_CEC_BITBANG + if (irq == et_ctrl_regs[CEC_EXT_TIMER].irq) { + cec_ext_timer_interrupt(); + return; + } +#endif + /* Interrupt of free running timer TIMER_H. */ if (irq == et_ctrl_regs[FREE_EXT_TIMER_H].irq) { free_run_timer_overflow(); @@ -225,7 +233,7 @@ DECLARE_IRQ(CPU_INT_GROUP_3, __hw_clock_source_irq, 1); #ifdef IT83XX_EXT_OBSERVATION_REG_READ_TWO_TIMES /* Number of CPU cycles in 125 us */ -#define CYCLES_125NS (125*(PLL_CLOCK/SECOND) / 1000) +#define CYCLES_125NS (125 * (PLL_CLOCK / SECOND) / 1000) uint32_t __ram_code ext_observation_reg_read(enum ext_timer_sel ext_timer) { uint32_t prev_mask = read_clear_int_mask(); @@ -245,8 +253,8 @@ uint32_t __ram_code ext_observation_reg_read(enum ext_timer_sel ext_timer) /* read for the second time */ "lwi %0,[%1]\n\t" : "=&r"(val) - : "r"((uintptr_t) &IT83XX_ETWD_ETXCNTOR(ext_timer)), - "i"(CYCLES_125NS)); + : "r"((uintptr_t)&IT83XX_ETWD_ETXCNTOR(ext_timer)), + "i"(CYCLES_125NS)); /* restore interrupts */ set_int_mask(prev_mask); @@ -275,10 +283,8 @@ void ext_timer_stop(enum ext_timer_sel ext_timer, int dis_irq) } static void ext_timer_ctrl(enum ext_timer_sel ext_timer, - enum ext_timer_clock_source ext_timer_clock, - int start, - int with_int, - int32_t count) + enum ext_timer_clock_source ext_timer_clock, + int start, int with_int, int32_t count) { uint8_t intc_mask; @@ -307,12 +313,8 @@ static void ext_timer_ctrl(enum ext_timer_sel ext_timer, } int ext_timer_ms(enum ext_timer_sel ext_timer, - enum ext_timer_clock_source ext_timer_clock, - int start, - int with_int, - int32_t ms, - int first_time_enable, - int raw) + enum ext_timer_clock_source ext_timer_clock, int start, + int with_int, int32_t ms, int first_time_enable, int raw) { uint32_t count; diff --git a/chip/it83xx/hwtimer_chip.h b/chip/it83xx/hwtimer_chip.h index ef53c4e871..756f669c4d 100644 --- a/chip/it83xx/hwtimer_chip.h +++ b/chip/it83xx/hwtimer_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,25 +8,51 @@ #ifndef __CROS_EC_HWTIMER_CHIP_H #define __CROS_EC_HWTIMER_CHIP_H -#define TIMER_COUNT_1US_SHIFT 3 +#define TIMER_COUNT_1US_SHIFT 3 /* Microseconds to event timer counter setting register */ -#define EVENT_TIMER_US_TO_COUNT(us) ((us) << TIMER_COUNT_1US_SHIFT) +#define EVENT_TIMER_US_TO_COUNT(us) ((us) << TIMER_COUNT_1US_SHIFT) /* Event timer counter observation value to microseconds */ #define EVENT_TIMER_COUNT_TO_US(cnt) ((cnt) >> TIMER_COUNT_1US_SHIFT) -#define FREE_EXT_TIMER_L EXT_TIMER_3 -#define FREE_EXT_TIMER_H EXT_TIMER_4 -#define FAN_CTRL_EXT_TIMER EXT_TIMER_5 -#define EVENT_EXT_TIMER EXT_TIMER_6 -#define WDT_EXT_TIMER EXT_TIMER_7 -#define LOW_POWER_EXT_TIMER EXT_TIMER_8 +#define FREE_EXT_TIMER_L EXT_TIMER_3 +#define FREE_EXT_TIMER_H EXT_TIMER_4 + +/* + * We only have one free timer, so use it for either fans or CEC. Since ITE also + * has a CEC peripheral, devices without a fan can have up to two CEC ports, and + * devices with a fan up to one. + */ +#if defined(CONFIG_FANS) && defined(CONFIG_CEC_BITBANG) +#error "Can't enable both CONFIG_FANS and CONFIG_CEC_BITBANG" +#endif +#if defined(CONFIG_FANS) +#define FAN_CTRL_EXT_TIMER EXT_TIMER_5 +#elif defined(CONFIG_CEC_BITBANG) +#define CEC_EXT_TIMER EXT_TIMER_5 +#endif + +#define EVENT_EXT_TIMER EXT_TIMER_6 +/* + * The low power timer is used to continue system time when EC goes into low + * power in idle task. Timer 7 is 24bit timer and configured at 32.768khz. + * The configuration is enough for continuing system time, because periodic + * tick event (interval is 500ms on it8xxx2) will wake EC up. + * + * IMPORTANT: + * If you change low power timer to a non-24bit timer, you also have to change + * mask of observation register in clock_sleep_mode_wakeup_isr() or EC will get + * wrong system time after resume. + */ +#define LOW_POWER_EXT_TIMER EXT_TIMER_7 +#define LOW_POWER_TIMER_MASK (BIT(24) - 1) +#define WDT_EXT_TIMER EXT_TIMER_8 enum ext_timer_clock_source { EXT_PSR_32P768K_HZ = 0, - EXT_PSR_1P024K_HZ = 1, - EXT_PSR_32_HZ = 2, - EXT_PSR_8M_HZ = 3 + EXT_PSR_1P024K_HZ = 1, + EXT_PSR_32_HZ = 2, + EXT_PSR_8M_HZ = 3 }; /* @@ -63,6 +89,7 @@ uint32_t __ram_code ext_observation_reg_read(enum ext_timer_sel ext_timer); void ext_timer_start(enum ext_timer_sel ext_timer, int en_irq); void ext_timer_stop(enum ext_timer_sel ext_timer, int dis_irq); void fan_ext_timer_interrupt(void); +void cec_ext_timer_interrupt(void); void update_exc_start_time(void); /** @@ -71,11 +98,7 @@ void update_exc_start_time(void); * @param raw (!=0) timer count equal to param "ms" no conversion. */ int ext_timer_ms(enum ext_timer_sel ext_timer, - enum ext_timer_clock_source ext_timer_clock, - int start, - int et_int, - int32_t ms, - int first_time_enable, - int raw); + enum ext_timer_clock_source ext_timer_clock, int start, + int et_int, int32_t ms, int first_time_enable, int raw); #endif /* __CROS_EC_HWTIMER_CHIP_H */ diff --git a/chip/it83xx/i2c.c b/chip/it83xx/i2c.c index 91863eb308..701f2a9576 100644 --- a/chip/it83xx/i2c.c +++ b/chip/it83xx/i2c.c @@ -1,10 +1,11 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* I2C module for Chrome EC */ +#include "builtin/assert.h" #include "clock.h" #include "common.h" #include "console.h" @@ -16,11 +17,53 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) /* Default maximum time we allow for an I2C transfer */ #define I2C_TIMEOUT_DEFAULT_US (100 * MSEC) +#ifdef CONFIG_IT83XX_I2C_CMD_QUEUE + +#ifdef CHIP_CORE_NDS32 +#error "Remapping DLM base is required on it8320 series" +#endif + +/* It is allowed to configure the size up to 2K bytes. */ +#define I2C_CQ_MODE_MAX_PAYLOAD_SIZE 128 +/* reserved 5 bytes for ID and CMD_x */ +#define I2C_CQ_MODE_TX_MAX_PAYLOAD_SIZE (I2C_CQ_MODE_MAX_PAYLOAD_SIZE - 5) +uint8_t i2c_cq_mode_tx_dlm[I2C_ENHANCED_PORT_COUNT] + [I2C_CQ_MODE_MAX_PAYLOAD_SIZE] __aligned(4); +uint8_t i2c_cq_mode_rx_dlm[I2C_ENHANCED_PORT_COUNT] + [I2C_CQ_MODE_MAX_PAYLOAD_SIZE] __aligned(4); + +/* Repeat Start */ +#define I2C_CQ_CMD_L_RS BIT(7) +/* + * R/W (Read/ Write) decides the I2C read or write direction + * 1: read, 0: write + */ +#define I2C_CQ_CMD_L_RW BIT(6) +/* P (STOP) is the I2C STOP condition */ +#define I2C_CQ_CMD_L_P BIT(5) +/* E (End) is this device end flag */ +#define I2C_CQ_CMD_L_E BIT(4) +/* LA (Last ACK) is Last ACK in master receiver */ +#define I2C_CQ_CMD_L_LA BIT(3) +/* bit[2:0] are number of transfer out or receive data which depends on R/W. */ +#define I2C_CQ_CMD_L_NUM_BIT_2_0 GENMASK(2, 0) + +struct i2c_cq_packet { + uint8_t id; + uint8_t cmd_l; + uint8_t cmd_h; + uint8_t wdata[0]; +}; + +/* Preventing CPU going into idle mode during command queue I2C transaction. */ +static uint32_t i2c_idle_disabled; +#endif /* CONFIG_IT83XX_I2C_CMD_QUEUE */ + enum enhanced_i2c_transfer_direct { TX_DIRECT, RX_DIRECT, @@ -44,8 +87,8 @@ enum i2c_host_status { /* Byte done status */ HOSTA_BDS = 0x80, /* Error bit is set */ - HOSTA_ANY_ERROR = (HOSTA_DVER | HOSTA_BSER | - HOSTA_FAIL | HOSTA_NACK | HOSTA_TMOE), + HOSTA_ANY_ERROR = (HOSTA_DVER | HOSTA_BSER | HOSTA_FAIL | HOSTA_NACK | + HOSTA_TMOE), /* W/C for next byte */ HOSTA_NEXT_BYTE = HOSTA_BDS, /* W/C host status register */ @@ -94,10 +137,12 @@ enum enhanced_i2c_ctl { E_RX_MODE = 0x80, /* State reset and hardware reset */ E_STS_AND_HW_RST = (E_STS_RST | E_HW_RST), - /* Generate start condition and transmit slave address */ + /* Generate start condition and transmit peripheral address */ E_START_ID = (E_INT_EN | E_MODE_SEL | E_ACK | E_START | E_HW_RST), /* Generate stop condition */ E_FINISH = (E_INT_EN | E_MODE_SEL | E_ACK | E_STOP | E_HW_RST), + /* start with command queue mode */ + E_START_CQ = (E_INT_EN | E_MODE_SEL | E_ACK | E_START), }; enum i2c_reset_cause { @@ -111,10 +156,10 @@ struct i2c_ch_freq { }; static const struct i2c_ch_freq i2c_freq_select[] = { - { 50, 1}, - { 100, 2}, - { 400, 3}, - { 1000, 4}, + { 50, 1 }, + { 100, 2 }, + { 400, 3 }, + { 1000, 4 }, }; struct i2c_pin { @@ -129,37 +174,30 @@ struct i2c_pin { }; static const struct i2c_pin i2c_pin_regs[] = { - { &IT83XX_GPIO_GPCRB3, &IT83XX_GPIO_GPCRB4, - &IT83XX_GPIO_GPDRB, &IT83XX_GPIO_GPDRB, - &IT83XX_GPIO_GPDMRB, &IT83XX_GPIO_GPDMRB, - 0x08, 0x10}, - { &IT83XX_GPIO_GPCRC1, &IT83XX_GPIO_GPCRC2, - &IT83XX_GPIO_GPDRC, &IT83XX_GPIO_GPDRC, - &IT83XX_GPIO_GPDMRC, &IT83XX_GPIO_GPDMRC, - 0x02, 0x04}, + { &IT83XX_GPIO_GPCRB3, &IT83XX_GPIO_GPCRB4, &IT83XX_GPIO_GPDRB, + &IT83XX_GPIO_GPDRB, &IT83XX_GPIO_GPDMRB, &IT83XX_GPIO_GPDMRB, 0x08, + 0x10 }, + { &IT83XX_GPIO_GPCRC1, &IT83XX_GPIO_GPCRC2, &IT83XX_GPIO_GPDRC, + &IT83XX_GPIO_GPDRC, &IT83XX_GPIO_GPDMRC, &IT83XX_GPIO_GPDMRC, 0x02, + 0x04 }, #ifdef CONFIG_IT83XX_SMCLK2_ON_GPC7 - { &IT83XX_GPIO_GPCRC7, &IT83XX_GPIO_GPCRF7, - &IT83XX_GPIO_GPDRC, &IT83XX_GPIO_GPDRF, - &IT83XX_GPIO_GPDMRC, &IT83XX_GPIO_GPDMRF, - 0x80, 0x80}, + { &IT83XX_GPIO_GPCRC7, &IT83XX_GPIO_GPCRF7, &IT83XX_GPIO_GPDRC, + &IT83XX_GPIO_GPDRF, &IT83XX_GPIO_GPDMRC, &IT83XX_GPIO_GPDMRF, 0x80, + 0x80 }, #else - { &IT83XX_GPIO_GPCRF6, &IT83XX_GPIO_GPCRF7, - &IT83XX_GPIO_GPDRF, &IT83XX_GPIO_GPDRF, - &IT83XX_GPIO_GPDMRF, &IT83XX_GPIO_GPDMRF, - 0x40, 0x80}, + { &IT83XX_GPIO_GPCRF6, &IT83XX_GPIO_GPCRF7, &IT83XX_GPIO_GPDRF, + &IT83XX_GPIO_GPDRF, &IT83XX_GPIO_GPDMRF, &IT83XX_GPIO_GPDMRF, 0x40, + 0x80 }, #endif - { &IT83XX_GPIO_GPCRH1, &IT83XX_GPIO_GPCRH2, - &IT83XX_GPIO_GPDRH, &IT83XX_GPIO_GPDRH, - &IT83XX_GPIO_GPDMRH, &IT83XX_GPIO_GPDMRH, - 0x02, 0x04}, - { &IT83XX_GPIO_GPCRE0, &IT83XX_GPIO_GPCRE7, - &IT83XX_GPIO_GPDRE, &IT83XX_GPIO_GPDRE, - &IT83XX_GPIO_GPDMRE, &IT83XX_GPIO_GPDMRE, - 0x01, 0x80}, - { &IT83XX_GPIO_GPCRA4, &IT83XX_GPIO_GPCRA5, - &IT83XX_GPIO_GPDRA, &IT83XX_GPIO_GPDRA, - &IT83XX_GPIO_GPDMRA, &IT83XX_GPIO_GPDMRA, - 0x10, 0x20}, + { &IT83XX_GPIO_GPCRH1, &IT83XX_GPIO_GPCRH2, &IT83XX_GPIO_GPDRH, + &IT83XX_GPIO_GPDRH, &IT83XX_GPIO_GPDMRH, &IT83XX_GPIO_GPDMRH, 0x02, + 0x04 }, + { &IT83XX_GPIO_GPCRE0, &IT83XX_GPIO_GPCRE7, &IT83XX_GPIO_GPDRE, + &IT83XX_GPIO_GPDRE, &IT83XX_GPIO_GPDMRE, &IT83XX_GPIO_GPDMRE, 0x01, + 0x80 }, + { &IT83XX_GPIO_GPCRA4, &IT83XX_GPIO_GPCRA5, &IT83XX_GPIO_GPDRA, + &IT83XX_GPIO_GPDRA, &IT83XX_GPIO_GPDMRA, &IT83XX_GPIO_GPDMRA, 0x10, + 0x20 }, }; struct i2c_ctrl_t { @@ -169,12 +207,12 @@ struct i2c_ctrl_t { }; const struct i2c_ctrl_t i2c_ctrl_regs[] = { - {IT83XX_IRQ_SMB_A, CGC_OFFSET_SMBA, -1}, - {IT83XX_IRQ_SMB_B, CGC_OFFSET_SMBB, -1}, - {IT83XX_IRQ_SMB_C, CGC_OFFSET_SMBC, -1}, - {IT83XX_IRQ_SMB_D, CGC_OFFSET_SMBD, 3}, - {IT83XX_IRQ_SMB_E, CGC_OFFSET_SMBE, 0}, - {IT83XX_IRQ_SMB_F, CGC_OFFSET_SMBF, 1}, + { IT83XX_IRQ_SMB_A, CGC_OFFSET_SMBA, -1 }, + { IT83XX_IRQ_SMB_B, CGC_OFFSET_SMBB, -1 }, + { IT83XX_IRQ_SMB_C, CGC_OFFSET_SMBC, -1 }, + { IT83XX_IRQ_SMB_D, CGC_OFFSET_SMBD, 3 }, + { IT83XX_IRQ_SMB_E, CGC_OFFSET_SMBE, 0 }, + { IT83XX_IRQ_SMB_F, CGC_OFFSET_SMBF, 1 }, }; enum i2c_ch_status { @@ -186,17 +224,17 @@ enum i2c_ch_status { /* I2C port state data */ struct i2c_port_data { - const uint8_t *out; /* Output data pointer */ - int out_size; /* Output data to transfer, in bytes */ - uint8_t *in; /* Input data pointer */ - int in_size; /* Input data to transfer, in bytes */ - int flags; /* Flags (I2C_XFER_*) */ - int widx; /* Index into output data */ - int ridx; /* Index into input data */ - int err; /* Error code, if any */ - uint8_t addr_8bit; /* address of device */ + const uint8_t *out; /* Output data pointer */ + int out_size; /* Output data to transfer, in bytes */ + uint8_t *in; /* Input data pointer */ + int in_size; /* Input data to transfer, in bytes */ + int flags; /* Flags (I2C_XFER_*) */ + int widx; /* Index into output data */ + int ridx; /* Index into input data */ + int err; /* Error code, if any */ + uint8_t addr_8bit; /* address of device */ uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ - uint8_t freq; /* Frequency setting */ + uint8_t freq; /* Frequency setting */ enum i2c_ch_status i2ccs; /* Task waiting on port, or TASK_ID_INVALID if none. */ @@ -284,9 +322,9 @@ static void i2c_pio_trans_data(int p, enum enhanced_i2c_transfer_direct direct, p_ch = i2c_ch_reg_shift(p); if (first_byte) { - /* First byte must be slave address. */ - IT83XX_I2C_DTR(p_ch) = - data | (direct == RX_DIRECT ? BIT(0) : 0); + /* First byte must be peripheral address. */ + IT83XX_I2C_DTR(p_ch) = data | + (direct == RX_DIRECT ? BIT(0) : 0); /* start or repeat start signal. */ IT83XX_I2C_CTR(p_ch) = E_START_ID; } else { @@ -299,12 +337,12 @@ static void i2c_pio_trans_data(int p, enum enhanced_i2c_transfer_direct direct, * Last byte should be NACK in the end of read cycle */ if (((pd->ridx + 1) == pd->in_size) && - (pd->flags & I2C_XFER_STOP)) + (pd->flags & I2C_XFER_STOP)) nack = 1; } /* Set hardware reset to start next transmission */ - IT83XX_I2C_CTR(p_ch) = - E_INT_EN | E_MODE_SEL | E_HW_RST | (nack ? 0 : E_ACK); + IT83XX_I2C_CTR(p_ch) = E_INT_EN | E_MODE_SEL | E_HW_RST | + (nack ? 0 : E_ACK); } } @@ -317,7 +355,7 @@ static int i2c_tran_write(int p) IT83XX_SMB_HOCTL2(p) = 0x13; /* * bit0, Direction of the host transfer. - * bit[1:7}, Address of the targeted slave. + * bit[1:7}, Address of the targeted peripheral. */ IT83XX_SMB_TRASLA(p) = pd->addr_8bit; /* Send first byte */ @@ -377,7 +415,7 @@ static int i2c_tran_read(int p) IT83XX_SMB_HOCTL2(p) = 0x13; /* * bit0, Direction of the host transfer. - * bit[1:7}, Address of the targeted slave. + * bit[1:7}, Address of the targeted peripheral. */ IT83XX_SMB_TRASLA(p) = pd->addr_8bit | 0x01; /* clear start flag */ @@ -395,7 +433,7 @@ static int i2c_tran_read(int p) IT83XX_SMB_HOCTL(p) = 0x5D; } else { if ((pd->i2ccs == I2C_CH_REPEAT_START) || - (pd->i2ccs == I2C_CH_WAIT_READ)) { + (pd->i2ccs == I2C_CH_WAIT_READ)) { if (pd->i2ccs == I2C_CH_REPEAT_START) { /* write to read */ i2c_w2r_change_direction(p); @@ -488,8 +526,8 @@ static int enhanced_i2c_tran_write(int p) /* Write to read protocol */ pd->i2ccs = I2C_CH_REPEAT_START; /* Repeat Start */ - i2c_pio_trans_data(p, RX_DIRECT, - pd->addr_8bit, 1); + i2c_pio_trans_data(p, RX_DIRECT, pd->addr_8bit, + 1); } else { if (pd->flags & I2C_XFER_STOP) { IT83XX_I2C_CTR(p_ch) = E_FINISH; @@ -538,8 +576,8 @@ static int enhanced_i2c_tran_read(int p) /* Write to read */ pd->i2ccs = I2C_CH_WAIT_READ; /* Send ID */ - i2c_pio_trans_data(p, RX_DIRECT, - pd->addr_8bit, 1); + i2c_pio_trans_data(p, RX_DIRECT, pd->addr_8bit, + 1); task_enable_irq(i2c_ctrl_regs[p].irq); } } else { @@ -578,7 +616,7 @@ static int enhanced_i2c_error(int p) if (i2c_str & E_HOSTA_ANY_ERROR) { pd->err = i2c_str & E_HOSTA_ANY_ERROR; - /* device does not respond ACK */ + /* device does not respond ACK */ } else if ((i2c_str & E_HOSTA_BDS_AND_ACK) == E_HOSTA_BDS) { if (IT83XX_I2C_CTR(p_ch) & E_ACK) pd->err = E_HOSTA_ACK; @@ -587,11 +625,199 @@ static int enhanced_i2c_error(int p) return pd->err; } -static int i2c_transaction(int p) +#ifdef CONFIG_IT83XX_I2C_CMD_QUEUE +static void enhanced_i2c_set_cmd_addr_regs(int p) +{ + int dlm_index = p - I2C_STANDARD_PORT_COUNT; + int p_ch = i2c_ch_reg_shift(p); + uint32_t dlm_base; + + /* set "Address Register" to store the I2C data */ + dlm_base = (uint32_t)&i2c_cq_mode_rx_dlm[dlm_index] & 0xffffff; + IT83XX_I2C_RAMH2A(p_ch) = (dlm_base >> 16) & 0xff; + IT83XX_I2C_RAMHA(p_ch) = (dlm_base >> 8) & 0xff; + IT83XX_I2C_RAMLA(p_ch) = dlm_base & 0xff; + + /* Set "Command Address Register" to get commands */ + dlm_base = (uint32_t)&i2c_cq_mode_tx_dlm[dlm_index] & 0xffffff; + IT83XX_I2C_CMD_ADDH2(p_ch) = (dlm_base >> 16) & 0xff; + IT83XX_I2C_CMD_ADDH(p_ch) = (dlm_base >> 8) & 0xff; + IT83XX_I2C_CMD_ADDL(p_ch) = dlm_base & 0xff; +} + +static void i2c_enable_idle(int port) +{ + i2c_idle_disabled &= ~BIT(port); +} + +static void i2c_disable_idle(int port) +{ + i2c_idle_disabled |= BIT(port); +} + +uint32_t i2c_idle_not_allowed(void) +{ + return i2c_idle_disabled; +} + +static int command_i2c_idle_mask(int argc, const char **argv) +{ + ccprintf("i2c idle mask: %08x\n", i2c_idle_disabled); + + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(i2cidlemask, command_i2c_idle_mask, NULL, + "Display i2c idle mask"); + +static void enhanced_i2c_cq_write(int p) +{ + struct i2c_port_data *pd = pdata + p; + struct i2c_cq_packet *i2c_cq_pckt; + uint8_t num_bit_2_0 = (pd->out_size - 1) & I2C_CQ_CMD_L_NUM_BIT_2_0; + uint8_t num_bit_10_3 = ((pd->out_size - 1) >> 3) & 0xff; + int dlm_index = p - I2C_STANDARD_PORT_COUNT; + + i2c_cq_pckt = (struct i2c_cq_packet *)&i2c_cq_mode_tx_dlm[dlm_index]; + /* Set commands in RAM. */ + i2c_cq_pckt->id = pd->addr_8bit; + i2c_cq_pckt->cmd_l = I2C_CQ_CMD_L_P | I2C_CQ_CMD_L_E | num_bit_2_0; + i2c_cq_pckt->cmd_h = num_bit_10_3; + for (int i = 0; i < pd->out_size; i++) + i2c_cq_pckt->wdata[i] = pd->out[i]; +} + +static void enhanced_i2c_cq_read(int p) +{ + struct i2c_port_data *pd = pdata + p; + struct i2c_cq_packet *i2c_cq_pckt; + uint8_t num_bit_2_0 = (pd->in_size - 1) & I2C_CQ_CMD_L_NUM_BIT_2_0; + uint8_t num_bit_10_3 = ((pd->in_size - 1) >> 3) & 0xff; + int dlm_index = p - I2C_STANDARD_PORT_COUNT; + + i2c_cq_pckt = (struct i2c_cq_packet *)&i2c_cq_mode_tx_dlm[dlm_index]; + /* Set commands in RAM. */ + i2c_cq_pckt->id = pd->addr_8bit; + i2c_cq_pckt->cmd_l = I2C_CQ_CMD_L_RW | I2C_CQ_CMD_L_P | I2C_CQ_CMD_L_E | + num_bit_2_0; + i2c_cq_pckt->cmd_h = num_bit_10_3; +} + +static void enhanced_i2c_cq_write_to_read(int p) +{ + struct i2c_port_data *pd = pdata + p; + struct i2c_cq_packet *i2c_cq_pckt; + uint8_t num_bit_2_0 = (pd->out_size - 1) & I2C_CQ_CMD_L_NUM_BIT_2_0; + uint8_t num_bit_10_3 = ((pd->out_size - 1) >> 3) & 0xff; + int dlm_index = p - I2C_STANDARD_PORT_COUNT; + int i; + + i2c_cq_pckt = (struct i2c_cq_packet *)&i2c_cq_mode_tx_dlm[dlm_index]; + /* Set commands in RAM. (command byte for write) */ + i2c_cq_pckt->id = pd->addr_8bit; + i2c_cq_pckt->cmd_l = num_bit_2_0; + i2c_cq_pckt->cmd_h = num_bit_10_3; + for (i = 0; i < pd->out_size; i++) + i2c_cq_pckt->wdata[i] = pd->out[i]; + /* Set commands in RAM. (command byte for read) */ + num_bit_2_0 = (pd->in_size - 1) & I2C_CQ_CMD_L_NUM_BIT_2_0; + num_bit_10_3 = ((pd->in_size - 1) >> 3) & 0xff; + i2c_cq_pckt->wdata[i++] = I2C_CQ_CMD_L_RS | I2C_CQ_CMD_L_RW | + I2C_CQ_CMD_L_P | I2C_CQ_CMD_L_E | num_bit_2_0; + i2c_cq_pckt->wdata[i] = num_bit_10_3; +} + +static int enhanced_i2c_cmd_queue_trans(int p) +{ + struct i2c_port_data *pd = pdata + p; + int p_ch = i2c_ch_reg_shift(p); + int dlm_index = p - I2C_STANDARD_PORT_COUNT; + + /* ISR of command queue mode */ + if (in_interrupt_context()) { + /* device 1 finish IRQ */ + if (IT83XX_I2C_FST(p_ch) & IT83XX_I2C_FST_DEV1_IRQ) { + /* get data if this is a read transaction */ + for (int i = 0; i < pd->in_size; i++) + pd->in[i] = i2c_cq_mode_rx_dlm[dlm_index][i]; + } else { + /* device 1 error have occurred. eg. nack, timeout... */ + if (IT83XX_I2C_NST(p_ch) & IT83XX_I2C_NST_ID_NACK) + pd->err = E_HOSTA_ACK; + else + pd->err = IT83XX_I2C_STR(p_ch) & + E_HOSTA_ANY_ERROR; + } + /* reset bus */ + IT83XX_I2C_CTR(p_ch) = E_STS_AND_HW_RST; + IT83XX_I2C_CTR1(p_ch) = 0; + + return 0; + } + + if ((pd->out_size > I2C_CQ_MODE_TX_MAX_PAYLOAD_SIZE) || + (pd->in_size > I2C_CQ_MODE_MAX_PAYLOAD_SIZE)) { + pd->err = EC_ERROR_INVAL; + return 0; + } + + /* State reset and hardware reset */ + IT83XX_I2C_CTR(p_ch) = E_STS_AND_HW_RST; + /* Set "PSR" registers to decide the i2c speed. */ + IT83XX_I2C_PSR(p_ch) = pdata[p].freq; + IT83XX_I2C_HSPR(p_ch) = pdata[p].freq; + /* Set time out register. port D, E, or F clock/data low timeout. */ + IT83XX_I2C_TOR(p_ch) = I2C_CLK_LOW_TIMEOUT; + + /* i2c write to read */ + if (pd->out_size && pd->in_size) + enhanced_i2c_cq_write_to_read(p); + /* i2c write */ + else if (pd->out_size) + enhanced_i2c_cq_write(p); + /* i2c read */ + else if (pd->in_size) + enhanced_i2c_cq_read(p); + + /* enable i2c module with command queue mode */ + IT83XX_I2C_CTR1(p_ch) = IT83XX_I2C_MDL_EN | IT83XX_I2C_COMQ_EN; + /* one shot on device 1 */ + IT83XX_I2C_MODE_SEL(p_ch) = 0; + IT83XX_I2C_CTR2(p_ch) = 1; + /* start */ + i2c_disable_idle(p); + IT83XX_I2C_CTR(p_ch) = E_START_CQ; + + return 0; +} +#endif /* CONFIG_IT83XX_I2C_CMD_QUEUE */ + +static int enhanced_i2c_pio_trans(int p) { struct i2c_port_data *pd = pdata + p; int p_ch; + /* no error */ + if (!(enhanced_i2c_error(p))) { + /* i2c write */ + if (pd->out_size) + return enhanced_i2c_tran_write(p); + /* i2c read */ + else if (pd->in_size) + return enhanced_i2c_tran_read(p); + } + + p_ch = i2c_ch_reg_shift(p); + IT83XX_I2C_CTR(p_ch) = E_STS_AND_HW_RST; + IT83XX_I2C_CTR1(p_ch) = 0; + + return 0; +} + +static int i2c_transaction(int p) +{ + struct i2c_port_data *pd = pdata + p; + int ret; + if (p < I2C_STANDARD_PORT_COUNT) { /* any error */ if (IT83XX_SMB_HOSTA(p) & HOSTA_ANY_ERROR) { @@ -612,18 +838,13 @@ static int i2c_transaction(int p) /* disable the SMBus host interface */ IT83XX_SMB_HOCTL2(p) = 0x00; } else { - /* no error */ - if (!(enhanced_i2c_error(p))) { - /* i2c write */ - if (pd->out_size) - return enhanced_i2c_tran_write(p); - /* i2c read */ - else if (pd->in_size) - return enhanced_i2c_tran_read(p); - } - p_ch = i2c_ch_reg_shift(p); - IT83XX_I2C_CTR(p_ch) = E_STS_AND_HW_RST; - IT83XX_I2C_CTR1(p_ch) = 0; +#ifdef CONFIG_IT83XX_I2C_CMD_QUEUE + if (pd->flags == I2C_XFER_SINGLE) + ret = enhanced_i2c_cmd_queue_trans(p); + else +#endif + ret = enhanced_i2c_pio_trans(p); + return ret; } /* done doing work */ return 0; @@ -641,9 +862,8 @@ int i2c_is_busy(int port) return (IT83XX_I2C_STR(p_ch) & E_HOSTA_BB); } -int chip_i2c_xfer(int port, uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) +int chip_i2c_xfer(int port, uint16_t addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size, int flags) { struct i2c_port_data *pd = pdata + port; uint32_t events = 0; @@ -651,10 +871,15 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, if (out_size == 0 && in_size == 0) return EC_SUCCESS; - if (pd->i2ccs) { - if ((flags & I2C_XFER_SINGLE) == I2C_XFER_SINGLE) - flags &= ~I2C_XFER_START; - } + /* + * Make the below i2c transaction work: + * - i2c_xfer with I2C_XFER_START flag + * - i2c_xfer with I2C_XFER_START flag + * - xxx + * - i2c_xfer with I2C_XFER_STOP flag + */ + if (pd->i2ccs) + flags &= ~I2C_XFER_START; /* Copy data to port struct */ pd->out = out; @@ -665,12 +890,12 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, pd->widx = 0; pd->ridx = 0; pd->err = 0; - pd->addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; + pd->addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; /* Make sure we're in a good state to start */ - if ((flags & I2C_XFER_START) && (i2c_is_busy(port) - || (i2c_get_line_levels(port) != I2C_LINE_IDLE))) { - + if ((flags & I2C_XFER_START) && + (i2c_is_busy(port) || + (i2c_get_line_levels(port) != I2C_LINE_IDLE))) { /* Attempt to unwedge the port. */ pd->err = i2c_unwedge(port); @@ -708,6 +933,10 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, if (pd->err) pd->i2ccs = I2C_CH_NORMAL; +#ifdef CONFIG_IT83XX_I2C_CMD_QUEUE + i2c_enable_idle(port); +#endif + return pd->err; } @@ -717,7 +946,7 @@ int i2c_raw_get_scl(int port) if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS) return !!(*i2c_pin_regs[port].mirror_clk & - i2c_pin_regs[port].clk_mask); + i2c_pin_regs[port].clk_mask); /* If no SCL pin defined for this port, then return 1 to appear idle */ return 1; @@ -729,7 +958,7 @@ int i2c_raw_get_sda(int port) if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS) return !!(*i2c_pin_regs[port].mirror_data & - i2c_pin_regs[port].data_mask); + i2c_pin_regs[port].data_mask); /* If no SDA pin defined for this port, then return 1 to appear idle */ return 1; @@ -769,7 +998,7 @@ void i2c_interrupt(int port) /* If done doing work, wake up the task waiting for the transfer */ if (!i2c_transaction(port)) { task_disable_irq(i2c_ctrl_regs[port].irq); - task_set_event(id, TASK_EVENT_I2C_IDLE, 0); + task_set_event(id, TASK_EVENT_I2C_IDLE); } } @@ -782,8 +1011,8 @@ static void i2c_standard_port_timing_regs_400khz(int port) /* Port clock frequency depends on setting of timing registers. */ IT83XX_SMB_SCLKTS(port) = 0; /* Suggested setting of timing registers of 400kHz. */ - IT83XX_SMB_4P7USL = 0x5; - IT83XX_SMB_4P0USL = 0x1; + IT83XX_SMB_4P7USL = 0x6; + IT83XX_SMB_4P0USL = 0; IT83XX_SMB_300NS = 0x1; IT83XX_SMB_250NS = 0x2; IT83XX_SMB_45P3USL = 0x6a; @@ -805,7 +1034,7 @@ static void i2c_standard_port_set_frequency(int port, int freq_khz) for (int f = ARRAY_SIZE(i2c_freq_select) - 1; f >= 0; f--) { if (freq_khz >= i2c_freq_select[f].kbps) { IT83XX_SMB_SCLKTS(port) = - i2c_freq_select[f].freq_set; + i2c_freq_select[f].freq_set; break; } } @@ -907,10 +1136,10 @@ void i2c_init(void) p_ch = i2c_ch_reg_shift(p); switch (p) { case IT83XX_I2C_CH_D: - #ifndef CONFIG_UART_HOST +#ifndef CONFIG_UART_HOST /* Enable SMBus D channel */ IT83XX_GPIO_GRC2 |= 0x20; - #endif +#endif break; case IT83XX_I2C_CH_E: /* Enable SMBus E channel */ @@ -928,6 +1157,10 @@ void i2c_init(void) IT83XX_I2C_CTR(p_ch) = E_STS_AND_HW_RST; /* bit1, Module enable */ IT83XX_I2C_CTR1(p_ch) = 0; +#ifdef CONFIG_IT83XX_I2C_CMD_QUEUE + /* set command address registers */ + enhanced_i2c_set_cmd_addr_regs(p); +#endif } pdata[i].task_waiting = TASK_ID_INVALID; } diff --git a/chip/it83xx/i2c_peripheral.c b/chip/it83xx/i2c_peripheral.c new file mode 100644 index 0000000000..dfb139514f --- /dev/null +++ b/chip/it83xx/i2c_peripheral.c @@ -0,0 +1,356 @@ +/* Copyright 2019 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* I2C module for Chrome EC */ +#include "clock.h" +#include "compile_time_macros.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c_peripheral.h" +#include "printf.h" +#include "registers.h" +#include "task.h" + +#include +#include + +/* Console output macros */ +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) + +/* The size must be a power of 2 */ +#define I2C_MAX_BUFFER_SIZE 0x100 +#define I2C_SIZE_MASK (I2C_MAX_BUFFER_SIZE - 1) + +#define I2C_READ_MAXFIFO_DATA 16 +#define I2C_ENHANCED_CH_INTERVAL 0x80 + +/* Store controller to peripheral data of channel D, E, F by DMA */ +static uint8_t in_data[I2C_ENHANCED_PORT_COUNT][I2C_MAX_BUFFER_SIZE] + __attribute__((section(".h2ram.pool.i2cslv"))); +/* Store peripheral to controller data of channel D, E, F by DMA */ +static uint8_t out_data[I2C_ENHANCED_PORT_COUNT][I2C_MAX_BUFFER_SIZE] + __attribute__((section(".h2ram.pool.i2cslv"))); +/* Store read and write data of channel A by FIFO mode */ +static uint8_t pbuffer[I2C_MAX_BUFFER_SIZE]; + +static uint32_t w_index; +static uint32_t r_index; +static int wr_done[I2C_ENHANCED_PORT_COUNT]; + +void buffer_index_reset(void) +{ + /* Reset write buffer index */ + w_index = 0; + /* Reset read buffer index */ + r_index = 0; +} + +/* Data structure to define I2C peripheral control configuration. */ +struct i2c_periph_ctrl_t { + int irq; /* peripheral irq */ + /* offset from base 0x00F03500 register; -1 means unused. */ + int offset; + enum clock_gate_offsets clock_gate; + int dma_index; +}; + +/* I2C peripheral control */ +const struct i2c_periph_ctrl_t i2c_periph_ctrl[] = { + [IT83XX_I2C_CH_A] = { .irq = IT83XX_IRQ_SMB_A, + .offset = -1, + .clock_gate = CGC_OFFSET_SMBA, + .dma_index = -1 }, + [IT83XX_I2C_CH_D] = { .irq = IT83XX_IRQ_SMB_D, + .offset = 0x180, + .clock_gate = CGC_OFFSET_SMBD, + .dma_index = 0 }, + [IT83XX_I2C_CH_E] = { .irq = IT83XX_IRQ_SMB_E, + .offset = 0x0, + .clock_gate = CGC_OFFSET_SMBE, + .dma_index = 1 }, + [IT83XX_I2C_CH_F] = { .irq = IT83XX_IRQ_SMB_F, + .offset = 0x80, + .clock_gate = CGC_OFFSET_SMBF, + .dma_index = 2 }, +}; + +void i2c_peripheral_read_write_data(int port) +{ + int periph_status, i; + + /* I2C peripheral channel A FIFO mode */ + if (port < I2C_STANDARD_PORT_COUNT) { + int count; + + periph_status = IT83XX_SMB_SLSTA; + + /* bit0-4 : FIFO byte count */ + count = IT83XX_SMB_SFFSTA & 0x1F; + + /* Peripheral data register is waiting for read or write. */ + if (periph_status & IT83XX_SMB_SDS) { + /* Controller to read data */ + if (periph_status & IT83XX_SMB_RCS) { + for (i = 0; i < I2C_READ_MAXFIFO_DATA; i++) + /* Return buffer data to controller */ + IT83XX_SMB_SLDA = + pbuffer[(i + r_index) & + I2C_SIZE_MASK]; + + /* Index to next 16 bytes of read buffer */ + r_index += I2C_READ_MAXFIFO_DATA; + } + /* Controller to write data */ + else { + /* FIFO Full */ + if (IT83XX_SMB_SFFSTA & IT83XX_SMB_SFFFULL) { + for (i = 0; i < count; i++) + /* Get data from controller to + * buffer */ + pbuffer[(w_index + i) & + I2C_SIZE_MASK] = + IT83XX_SMB_SLDA; + } + + /* Index to next byte of write buffer */ + w_index += count; + } + } + /* Stop condition, indicate stop condition detected. */ + if (periph_status & IT83XX_SMB_SPDS) { + /* Read data less 16 bytes status */ + if (periph_status & IT83XX_SMB_RCS) { + /* Disable FIFO mode to clear left count */ + IT83XX_SMB_SFFCTL &= ~IT83XX_SMB_SAFE; + + /* Peripheral A FIFO Enable */ + IT83XX_SMB_SFFCTL |= IT83XX_SMB_SAFE; + } + /* Controller to write data */ + else { + for (i = 0; i < count; i++) + /* Get data from controller to buffer */ + pbuffer[(i + w_index) & I2C_SIZE_MASK] = + IT83XX_SMB_SLDA; + } + + /* Reset read and write buffer index */ + buffer_index_reset(); + } + /* Peripheral time status, timeout status occurs. */ + if (periph_status & IT83XX_SMB_STS) { + /* Reset read and write buffer index */ + buffer_index_reset(); + } + + /* Write clear the peripheral status */ + IT83XX_SMB_SLSTA = periph_status; + } + /* Enhanced I2C peripheral channel D, E, F DMA mode */ + else { + int ch, idx; + + /* Get enhanced i2c channel */ + ch = i2c_periph_ctrl[port].offset / I2C_ENHANCED_CH_INTERVAL; + + idx = i2c_periph_ctrl[port].dma_index; + + /* Interrupt pending */ + if (IT83XX_I2C_STR(ch) & IT83XX_I2C_INTPEND) { + periph_status = IT83XX_I2C_IRQ_ST(ch); + + /* Controller to read data */ + if (periph_status & IT83XX_I2C_IDR_CLR) { + /* + * TODO(b:129360157): Return buffer data by + * "out_data" array. + * Ex: Write data to buffer from 0x00 to 0xFF + */ + for (i = 0; i < I2C_MAX_BUFFER_SIZE; i++) + out_data[idx][i] = i; + } + /* Controller to write data */ + if (periph_status & IT83XX_I2C_IDW_CLR) { + /* Controller to write data finish flag */ + wr_done[idx] = 1; + } + /* Peripheral finish */ + if (periph_status & IT83XX_I2C_P_CLR) { + if (wr_done[idx]) { + char str_buf[hex_str_buf_size( + I2C_MAX_BUFFER_SIZE)]; + /* + * TODO(b:129360157): Handle controller + * write data by "in_data" array. + */ + snprintf_hex_buffer( + str_buf, sizeof(str_buf), + HEX_BUF(in_data[idx], + I2C_MAX_BUFFER_SIZE)); + CPRINTS("WData: %s", str_buf); + wr_done[idx] = 0; + } + } + + /* Write clear the peripheral status */ + IT83XX_I2C_IRQ_ST(ch) = periph_status; + } + + /* Hardware reset */ + IT83XX_I2C_CTR(ch) |= IT83XX_I2C_HALT; + } +} + +void i2c_periph_interrupt(int port) +{ + /* Peripheral to read and write fifo data */ + i2c_peripheral_read_write_data(port); + + /* Clear the interrupt status */ + task_clear_pending_irq(i2c_periph_ctrl[port].irq); +} + +void i2c_peripheral_enable(int port, uint8_t periph_addr) +{ + clock_enable_peripheral(i2c_periph_ctrl[port].clock_gate, 0, 0); + + /* I2C peripheral channel A FIFO mode */ + if (port < I2C_STANDARD_PORT_COUNT) { + /* This field defines the SMCLK0/1/2 clock/data low timeout. */ + IT83XX_SMB_25MS = I2C_CLK_LOW_TIMEOUT; + + /* bit0 : Peripheral A FIFO Enable */ + IT83XX_SMB_SFFCTL |= IT83XX_SMB_SAFE; + + /* + * bit1 : Peripheral interrupt enable. + * bit2 : SMCLK/SMDAT will be released if timeout. + * bit3 : Peripheral detect STOP condition interrupt enable. + */ + IT83XX_SMB_SICR = 0x0E; + + /* Peripheral address 1 */ + IT83XX_SMB_RESLADR = periph_addr; + + /* Write clear all peripheral status */ + IT83XX_SMB_SLSTA = 0xE7; + + /* bit5 : Enable the SMBus peripheral device */ + IT83XX_SMB_HOCTL2(port) |= IT83XX_SMB_SLVEN; + } + /* Enhanced I2C peripheral channel D, E, F DMA mode */ + else { + int ch, idx; + uint32_t in_data_addr, out_data_addr; + + /* Get enhanced i2c channel */ + ch = i2c_periph_ctrl[port].offset / I2C_ENHANCED_CH_INTERVAL; + + idx = i2c_periph_ctrl[port].dma_index; + + switch (port) { + case IT83XX_I2C_CH_D: + /* Enable I2C D channel */ + IT83XX_GPIO_GRC2 |= (1 << 5); + break; + case IT83XX_I2C_CH_E: + /* Enable I2C E channel */ + IT83XX_GCTRL_PMER1 |= (1 << 0); + break; + case IT83XX_I2C_CH_F: + /* Enable I2C F channel */ + IT83XX_GCTRL_PMER1 |= (1 << 1); + break; + } + + /* Software reset */ + IT83XX_I2C_DHTR(ch) |= (1 << 7); + IT83XX_I2C_DHTR(ch) &= ~(1 << 7); + + /* This field defines the SMCLK3/4/5 clock/data low timeout. */ + IT83XX_I2C_TOR(ch) = I2C_CLK_LOW_TIMEOUT; + + /* Bit stretching */ + IT83XX_I2C_TOS(ch) |= IT83XX_I2C_CLK_STR; + + /* Peripheral address(8-bit)*/ + IT83XX_I2C_IDR(ch) = periph_addr << 1; + + /* I2C interrupt enable and set acknowledge */ + IT83XX_I2C_CTR(ch) = IT83XX_I2C_HALT | IT83XX_I2C_INTEN | + IT83XX_I2C_ACK; + + /* + * bit3 : Peripheral ID write flag + * bit2 : Peripheral ID read flag + * bit1 : Peripheral received data flag + * bit0 : Peripheral finish + */ + IT83XX_I2C_IRQ_ST(ch) = 0xFF; + + /* Clear read and write data buffer of DMA */ + memset(in_data[idx], 0, I2C_MAX_BUFFER_SIZE); + memset(out_data[idx], 0, I2C_MAX_BUFFER_SIZE); + + if (IS_ENABLED(CHIP_ILM_DLM_ORDER)) { + in_data_addr = (uint32_t)in_data[idx] & 0xffffff; + out_data_addr = (uint32_t)out_data[idx] & 0xffffff; + } else { + in_data_addr = (uint32_t)in_data[idx] & 0xfff; + out_data_addr = (uint32_t)out_data[idx] & 0xfff; + } + + /* DMA write target address register */ + IT83XX_I2C_RAMHA(ch) = in_data_addr >> 8; + IT83XX_I2C_RAMLA(ch) = in_data_addr; + + if (IS_ENABLED(CHIP_ILM_DLM_ORDER)) { + /* + * DMA write target address register + * for high order byte + */ + IT83XX_I2C_RAMH2A(ch) = in_data_addr >> 16; + /* + * DMA read target address register + * for high order byte + */ + IT83XX_I2C_CMD_ADDH2(ch) = out_data_addr >> 16; + IT83XX_I2C_CMD_ADDH(ch) = out_data_addr >> 8; + IT83XX_I2C_CMD_ADDL(ch) = out_data_addr; + } else { + /* DMA read target address register */ + IT83XX_I2C_RAMHA2(ch) = out_data_addr >> 8; + IT83XX_I2C_RAMLA2(ch) = out_data_addr; + } + + /* I2C module enable and command queue mode */ + IT83XX_I2C_CTR1(ch) = IT83XX_I2C_COMQ_EN | IT83XX_I2C_MDL_EN; + } +} + +static void i2c_peripheral_init(void) +{ + int i, p; + + /* DLM 52k~56k size select enable */ + IT83XX_GCTRL_MCCR2 |= (1 << 4); + + /* Enable I2C Peripheral function */ + for (i = 0; i < i2c_periphs_used; i++) { + /* I2c peripheral port mapping. */ + p = i2c_periph_ports[i].port; + + /* To enable peripheral ch[x] */ + i2c_peripheral_enable(p, i2c_periph_ports[i].addr); + + /* Clear the interrupt status */ + task_clear_pending_irq(i2c_periph_ctrl[p].irq); + + /* enable i2c interrupt */ + task_enable_irq(i2c_periph_ctrl[p].irq); + } +} +DECLARE_HOOK(HOOK_INIT, i2c_peripheral_init, HOOK_PRIO_POST_I2C); diff --git a/chip/it83xx/i2c_slave.c b/chip/it83xx/i2c_slave.c deleted file mode 100644 index adfa794d77..0000000000 --- a/chip/it83xx/i2c_slave.c +++ /dev/null @@ -1,345 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* I2C module for Chrome EC */ - -#include "clock.h" -#include "compile_time_macros.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c_slave.h" -#include "registers.h" -#include -#include -#include "task.h" - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) - -/* The size must be a power of 2 */ -#define I2C_MAX_BUFFER_SIZE 0x100 -#define I2C_SIZE_MASK (I2C_MAX_BUFFER_SIZE - 1) - -#define I2C_READ_MAXFIFO_DATA 16 -#define I2C_ENHANCED_CH_INTERVAL 0x80 - -/* Store master to slave data of channel D, E, F by DMA */ -static uint8_t in_data[I2C_ENHANCED_PORT_COUNT][I2C_MAX_BUFFER_SIZE] - __attribute__((section(".h2ram.pool.i2cslv"))); -/* Store slave to master data of channel D, E, F by DMA */ -static uint8_t out_data[I2C_ENHANCED_PORT_COUNT][I2C_MAX_BUFFER_SIZE] - __attribute__((section(".h2ram.pool.i2cslv"))); -/* Store read and write data of channel A by FIFO mode */ -static uint8_t pbuffer[I2C_MAX_BUFFER_SIZE]; - -static uint32_t w_index; -static uint32_t r_index; -static int wr_done[I2C_ENHANCED_PORT_COUNT]; - -void buffer_index_reset(void) -{ - /* Reset write buffer index */ - w_index = 0; - /* Reset read buffer index */ - r_index = 0; -} - -/* Data structure to define I2C slave control configuration. */ -struct i2c_slv_ctrl_t { - int irq; /* slave irq */ - /* offset from base 0x00F03500 register; -1 means unused. */ - int offset; - enum clock_gate_offsets clock_gate; - int dma_index; -}; - -/* I2C slave control */ -const struct i2c_slv_ctrl_t i2c_slv_ctrl[] = { - [IT83XX_I2C_CH_A] = {.irq = IT83XX_IRQ_SMB_A, .offset = -1, - .clock_gate = CGC_OFFSET_SMBA, .dma_index = -1}, - [IT83XX_I2C_CH_D] = {.irq = IT83XX_IRQ_SMB_D, .offset = 0x180, - .clock_gate = CGC_OFFSET_SMBD, .dma_index = 0}, - [IT83XX_I2C_CH_E] = {.irq = IT83XX_IRQ_SMB_E, .offset = 0x0, - .clock_gate = CGC_OFFSET_SMBE, .dma_index = 1}, - [IT83XX_I2C_CH_F] = {.irq = IT83XX_IRQ_SMB_F, .offset = 0x80, - .clock_gate = CGC_OFFSET_SMBF, .dma_index = 2}, -}; - -void i2c_slave_read_write_data(int port) -{ - int slv_status, i; - - /* I2C slave channel A FIFO mode */ - if (port < I2C_STANDARD_PORT_COUNT) { - int count; - - slv_status = IT83XX_SMB_SLSTA; - - /* bit0-4 : FIFO byte count */ - count = IT83XX_SMB_SFFSTA & 0x1F; - - /* Slave data register is waiting for read or write. */ - if (slv_status & IT83XX_SMB_SDS) { - /* Master to read data */ - if (slv_status & IT83XX_SMB_RCS) { - for (i = 0; i < I2C_READ_MAXFIFO_DATA; i++) - /* Return buffer data to master */ - IT83XX_SMB_SLDA = - pbuffer[(i + r_index) & I2C_SIZE_MASK]; - - /* Index to next 16 bytes of read buffer */ - r_index += I2C_READ_MAXFIFO_DATA; - } - /* Master to write data */ - else { - /* FIFO Full */ - if (IT83XX_SMB_SFFSTA & IT83XX_SMB_SFFFULL) { - for (i = 0; i < count; i++) - /* Get data from master to buffer */ - pbuffer[(w_index + i) & - I2C_SIZE_MASK] = IT83XX_SMB_SLDA; - } - - /* Index to next byte of write buffer */ - w_index += count; - } - } - /* Stop condition, indicate stop condition detected. */ - if (slv_status & IT83XX_SMB_SPDS) { - /* Read data less 16 bytes status */ - if (slv_status & IT83XX_SMB_RCS) { - /* Disable FIFO mode to clear left count */ - IT83XX_SMB_SFFCTL &= ~IT83XX_SMB_SAFE; - - /* Slave A FIFO Enable */ - IT83XX_SMB_SFFCTL |= IT83XX_SMB_SAFE; - } - /* Master to write data */ - else { - for (i = 0; i < count; i++) - /* Get data from master to buffer */ - pbuffer[(i + w_index) & - I2C_SIZE_MASK] = IT83XX_SMB_SLDA; - } - - /* Reset read and write buffer index */ - buffer_index_reset(); - } - /* Slave time status, timeout status occurs. */ - if (slv_status & IT83XX_SMB_STS) { - /* Reset read and write buffer index */ - buffer_index_reset(); - } - - /* Write clear the slave status */ - IT83XX_SMB_SLSTA = slv_status; - } - /* Enhanced I2C slave channel D, E, F DMA mode */ - else { - int ch, idx; - - /* Get enhanced i2c channel */ - ch = i2c_slv_ctrl[port].offset / I2C_ENHANCED_CH_INTERVAL; - - idx = i2c_slv_ctrl[port].dma_index; - - /* Interrupt pending */ - if (IT83XX_I2C_STR(ch) & IT83XX_I2C_INTPEND) { - - slv_status = IT83XX_I2C_IRQ_ST(ch); - - /* Master to read data */ - if (slv_status & IT83XX_I2C_IDR_CLR) { - /* - * TODO(b:129360157): Return buffer data by - * "out_data" array. - * Ex: Write data to buffer from 0x00 to 0xFF - */ - for (i = 0; i < I2C_MAX_BUFFER_SIZE; i++) - out_data[idx][i] = i; - } - /* Master to write data */ - if (slv_status & IT83XX_I2C_IDW_CLR) { - /* Master to write data finish flag */ - wr_done[idx] = 1; - } - /* Slave finish */ - if (slv_status & IT83XX_I2C_P_CLR) { - if (wr_done[idx]) { - /* - * TODO(b:129360157): Handle master write - * data by "in_data" array. - */ - CPRINTS("WData: %ph", - HEX_BUF(in_data[idx], - I2C_MAX_BUFFER_SIZE)); - wr_done[idx] = 0; - } - } - - /* Write clear the slave status */ - IT83XX_I2C_IRQ_ST(ch) = slv_status; - } - - /* Hardware reset */ - IT83XX_I2C_CTR(ch) |= IT83XX_I2C_HALT; - } -} - -void i2c_slv_interrupt(int port) -{ - /* Slave to read and write fifo data */ - i2c_slave_read_write_data(port); - - /* Clear the interrupt status */ - task_clear_pending_irq(i2c_slv_ctrl[port].irq); -} - -void i2c_slave_enable(int port, uint8_t slv_addr) -{ - - clock_enable_peripheral(i2c_slv_ctrl[port].clock_gate, 0, 0); - - /* I2C slave channel A FIFO mode */ - if (port < I2C_STANDARD_PORT_COUNT) { - - /* This field defines the SMCLK0/1/2 clock/data low timeout. */ - IT83XX_SMB_25MS = I2C_CLK_LOW_TIMEOUT; - - /* bit0 : Slave A FIFO Enable */ - IT83XX_SMB_SFFCTL |= IT83XX_SMB_SAFE; - - /* - * bit1 : Slave interrupt enable. - * bit2 : SMCLK/SMDAT will be released if timeout. - * bit3 : Slave detect STOP condition interrupt enable. - */ - IT83XX_SMB_SICR = 0x0E; - - /* Slave address 1 */ - IT83XX_SMB_RESLADR = slv_addr; - - /* Write clear all slave status */ - IT83XX_SMB_SLSTA = 0xE7; - - /* bit5 : Enable the SMBus slave device */ - IT83XX_SMB_HOCTL2(port) |= IT83XX_SMB_SLVEN; - } - /* Enhanced I2C slave channel D, E, F DMA mode */ - else { - int ch, idx; - uint32_t in_data_addr, out_data_addr; - - /* Get enhanced i2c channel */ - ch = i2c_slv_ctrl[port].offset / I2C_ENHANCED_CH_INTERVAL; - - idx = i2c_slv_ctrl[port].dma_index; - - switch (port) { - case IT83XX_I2C_CH_D: - /* Enable I2C D channel */ - IT83XX_GPIO_GRC2 |= (1 << 5); - break; - case IT83XX_I2C_CH_E: - /* Enable I2C E channel */ - IT83XX_GCTRL_PMER1 |= (1 << 0); - break; - case IT83XX_I2C_CH_F: - /* Enable I2C F channel */ - IT83XX_GCTRL_PMER1 |= (1 << 1); - break; - } - - /* Software reset */ - IT83XX_I2C_DHTR(ch) |= (1 << 7); - IT83XX_I2C_DHTR(ch) &= ~(1 << 7); - - /* This field defines the SMCLK3/4/5 clock/data low timeout. */ - IT83XX_I2C_TOR(ch) = I2C_CLK_LOW_TIMEOUT; - - /* Bit stretching */ - IT83XX_I2C_TOS(ch) |= IT83XX_I2C_CLK_STR; - - /* Slave address(8-bit)*/ - IT83XX_I2C_IDR(ch) = slv_addr << 1; - - /* I2C interrupt enable and set acknowledge */ - IT83XX_I2C_CTR(ch) = IT83XX_I2C_HALT | - IT83XX_I2C_INTEN | IT83XX_I2C_ACK; - - /* - * bit3 : Slave ID write flag - * bit2 : Slave ID read flag - * bit1 : Slave received data flag - * bit0 : Slave finish - */ - IT83XX_I2C_IRQ_ST(ch) = 0xFF; - - /* Clear read and write data buffer of DMA */ - memset(in_data[idx], 0, I2C_MAX_BUFFER_SIZE); - memset(out_data[idx], 0, I2C_MAX_BUFFER_SIZE); - - if (IS_ENABLED(CHIP_ILM_DLM_ORDER)) { - in_data_addr = (uint32_t)in_data[idx] & 0xffffff; - out_data_addr = (uint32_t)out_data[idx] & 0xffffff; - } else { - in_data_addr = (uint32_t)in_data[idx] & 0xfff; - out_data_addr = (uint32_t)out_data[idx] & 0xfff; - } - - /* DMA write target address register */ - IT83XX_I2C_RAMHA(ch) = in_data_addr >> 8; - IT83XX_I2C_RAMLA(ch) = in_data_addr; - - if (IS_ENABLED(CHIP_ILM_DLM_ORDER)) { - /* - * DMA write target address register - * for high order byte - */ - IT83XX_I2C_RAMH2A(ch) = in_data_addr >> 16; - /* - * DMA read target address register - * for high order byte - */ - IT83XX_I2C_CMD_ADDH2(ch) = out_data_addr >> 16; - IT83XX_I2C_CMD_ADDH(ch) = out_data_addr >> 8; - IT83XX_I2C_CMD_ADDL(ch) = out_data_addr; - } else { - /* DMA read target address register */ - IT83XX_I2C_RAMHA2(ch) = out_data_addr >> 8; - IT83XX_I2C_RAMLA2(ch) = out_data_addr; - } - - /* I2C module enable and command queue mode */ - IT83XX_I2C_CTR1(ch) = IT83XX_I2C_COMQ_EN | - IT83XX_I2C_MDL_EN; - } -} - -static void i2c_slave_init(void) -{ - int i, p; - - /* DLM 52k~56k size select enable */ - IT83XX_GCTRL_MCCR2 |= (1 << 4); - - /* Enable I2C Slave function */ - for (i = 0; i < i2c_slvs_used; i++) { - - /* I2c slave port mapping. */ - p = i2c_slv_ports[i].port; - - /* To enable slave ch[x] */ - i2c_slave_enable(p, i2c_slv_ports[i].slave_adr); - - /* Clear the interrupt status */ - task_clear_pending_irq(i2c_slv_ctrl[p].irq); - - /* enable i2c interrupt */ - task_enable_irq(i2c_slv_ctrl[p].irq); - } -} -DECLARE_HOOK(HOOK_INIT, i2c_slave_init, HOOK_PRIO_INIT_I2C + 1); diff --git a/chip/it83xx/intc.c b/chip/it83xx/intc.c index 2a6e3688d9..89e5d70a01 100644 --- a/chip/it83xx/intc.c +++ b/chip/it83xx/intc.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,98 +6,20 @@ #include "common.h" #include "intc.h" #include "it83xx_pd.h" +#include "ite_pd_intc.h" #include "kmsc_chip.h" #include "registers.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "usb_pd.h" -#if defined(CONFIG_USB_PD_TCPM_ITE_ON_CHIP) -static void chip_pd_irq(enum usbpd_port port) -{ - task_clear_pending_irq(usbpd_ctrl_regs[port].irq); - - /* check status */ - if (IS_ENABLED(IT83XX_INTC_FAST_SWAP_SUPPORT) && - IS_ENABLED(CONFIG_USB_PD_FRS_TCPC) && - IS_ENABLED(CONFIG_USB_PD_REV30)) { - /* - * FRS detection must handle first, because we need to short - * the interrupt -> board_frs_handler latency-critical time. - */ - if (USBPD_IS_FAST_SWAP_DETECT(port)) { - /* clear detect FRS signal (cc to GND) status */ - USBPD_CLEAR_FRS_DETECT_STATUS(port); - if (board_frs_handler) - board_frs_handler(port); - /* inform TCPMv2 to change state */ - pd_got_frs_signal(port); - } - } - - if (USBPD_IS_HARD_RESET_DETECT(port)) { - /* clear interrupt */ - IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_HARD_RESET_DETECT; - USBPD_SW_RESET(port); - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_RX_HARD_RESET, 0); - } - - if (USBPD_IS_RX_DONE(port)) { - tcpm_enqueue_message(port); - /* clear RX done interrupt */ - IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_MSG_RX_DONE; - } - - if (USBPD_IS_TX_DONE(port)) { -#ifdef CONFIG_USB_PD_TCPM_DRIVER_IT8XXX2 - it83xx_clear_tx_error_status(port); - /* check TX status, clear by TX_DONE status too */ - if (USBPD_IS_TX_ERR(port)) - it83xx_get_tx_error_status(port); -#endif - /* clear TX done interrupt */ - IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_MSG_TX_DONE; - task_set_event(PD_PORT_TO_TASK_ID(port), - TASK_EVENT_PHY_TX_DONE, 0); - } - - if (IS_ENABLED(IT83XX_INTC_PLUG_IN_OUT_SUPPORT)) { - if (USBPD_IS_PLUG_IN_OUT_DETECT(port)) { - if (USBPD_IS_PLUG_IN(port)) - /* - * When tcpc detect type-c plug in: - * 1)If we are sink, disable detect interrupt, - * messages on cc line won't trigger interrupt. - * 2)If we are source, then set plug out - * detection. - */ - switch_plug_out_type(port); - else - /* - * When tcpc detect type-c plug out: - * switch to detect plug in. - */ - IT83XX_USBPD_TCDCR(port) &= - ~USBPD_REG_PLUG_OUT_SELECT; - - /* clear type-c device plug in/out detect interrupt */ - IT83XX_USBPD_TCDCR(port) |= - USBPD_REG_PLUG_IN_OUT_DETECT_STAT; - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_CC, 0); - } - } -} -#endif - int __ram_code intc_get_ec_int(void) { extern volatile int ec_int; return ec_int; } -void intc_cpu_int_group_5(void) +static void intc_cpu_int_group_5(void) { /* Determine interrupt number. */ int intc_group_5 = intc_get_ec_int(); @@ -118,7 +40,7 @@ void intc_cpu_int_group_5(void) } DECLARE_IRQ(CPU_INT_GROUP_5, intc_cpu_int_group_5, 2); -void intc_cpu_int_group_4(void) +static void intc_cpu_int_group_4(void) { /* Determine interrupt number. */ int intc_group_4 = intc_get_ec_int(); @@ -151,7 +73,7 @@ void intc_cpu_int_group_4(void) } DECLARE_IRQ(CPU_INT_GROUP_4, intc_cpu_int_group_4, 2); -void intc_cpu_int_group_12(void) +static void intc_cpu_int_group_12(void) { /* Determine interrupt number. */ int intc_group_12 = intc_get_ec_int(); @@ -162,7 +84,7 @@ void intc_cpu_int_group_12(void) peci_interrupt(); break; #endif -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI case IT83XX_IRQ_ESPI: espi_interrupt(); break; @@ -186,8 +108,8 @@ void intc_cpu_int_group_12(void) #endif #endif #ifdef CONFIG_SPI - case IT83XX_IRQ_SPI_SLAVE: - spi_slv_int_handler(); + case IT83XX_IRQ_SPI_PERIPHERAL: + spi_peripheral_int_handler(); break; #endif default: @@ -196,7 +118,7 @@ void intc_cpu_int_group_12(void) } DECLARE_IRQ(CPU_INT_GROUP_12, intc_cpu_int_group_12, 2); -void intc_cpu_int_group_7(void) +static void intc_cpu_int_group_7(void) { /* Determine interrupt number. */ int intc_group_7 = intc_get_ec_int(); @@ -218,17 +140,17 @@ void intc_cpu_int_group_7(void) } DECLARE_IRQ(CPU_INT_GROUP_7, intc_cpu_int_group_7, 2); -void intc_cpu_int_group_6(void) +static void intc_cpu_int_group_6(void) { /* Determine interrupt number. */ int intc_group_6 = intc_get_ec_int(); switch (intc_group_6) { -#if defined(CONFIG_I2C_MASTER) || defined(CONFIG_I2C_SLAVE) +#if defined(CONFIG_I2C_CONTROLLER) || defined(CONFIG_I2C_PERIPHERAL) case IT83XX_IRQ_SMB_A: -#ifdef CONFIG_I2C_SLAVE +#ifdef CONFIG_I2C_PERIPHERAL if (IT83XX_SMB_SFFCTL & IT83XX_SMB_SAFE) - i2c_slv_interrupt(IT83XX_I2C_CH_A); + i2c_periph_interrupt(IT83XX_I2C_CH_A); else #endif i2c_interrupt(IT83XX_I2C_CH_A); @@ -243,27 +165,27 @@ void intc_cpu_int_group_6(void) break; case IT83XX_IRQ_SMB_D: -#ifdef CONFIG_I2C_SLAVE +#ifdef CONFIG_I2C_PERIPHERAL if (!(IT83XX_I2C_CTR(3) & IT83XX_I2C_MODE)) - i2c_slv_interrupt(IT83XX_I2C_CH_D); + i2c_periph_interrupt(IT83XX_I2C_CH_D); else #endif i2c_interrupt(IT83XX_I2C_CH_D); break; case IT83XX_IRQ_SMB_E: -#ifdef CONFIG_I2C_SLAVE +#ifdef CONFIG_I2C_PERIPHERAL if (!(IT83XX_I2C_CTR(0) & IT83XX_I2C_MODE)) - i2c_slv_interrupt(IT83XX_I2C_CH_E); + i2c_periph_interrupt(IT83XX_I2C_CH_E); else #endif i2c_interrupt(IT83XX_I2C_CH_E); break; case IT83XX_IRQ_SMB_F: -#ifdef CONFIG_I2C_SLAVE +#ifdef CONFIG_I2C_PERIPHERAL if (!(IT83XX_I2C_CTR(1) & IT83XX_I2C_MODE)) - i2c_slv_interrupt(IT83XX_I2C_CH_F); + i2c_periph_interrupt(IT83XX_I2C_CH_F); else #endif i2c_interrupt(IT83XX_I2C_CH_F); diff --git a/chip/it83xx/intc.h b/chip/it83xx/intc.h index bd6d947453..43adb3784d 100644 --- a/chip/it83xx/intc.h +++ b/chip/it83xx/intc.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,7 +15,7 @@ static inline void data_serialization_barrier(void) { if (IS_ENABLED(CHIP_CORE_NDS32)) - asm volatile ("dsb"); + asm volatile("dsb"); } int intc_get_ec_int(void); @@ -31,8 +31,8 @@ void adc_interrupt(void); void voltage_comparator_interrupt(void); #endif void i2c_interrupt(int port); -#ifdef CONFIG_I2C_SLAVE -void i2c_slv_interrupt(int port); +#ifdef CONFIG_I2C_PERIPHERAL +void i2c_periph_interrupt(int port); #endif void clock_sleep_mode_wakeup_isr(void); int clock_ec_wake_from_sleep(void); @@ -44,10 +44,14 @@ void espi_vw_interrupt(void); void espi_enable_pad(int enable); void espi_init(void); void clock_cpu_standby(void); -void spi_slv_int_handler(void); +void spi_emmc_cmd0_isr(uint32_t *cmd0_payload); +void spi_peripheral_int_handler(void); #if defined(CONFIG_HOSTCMD_X86) && defined(HAS_TASK_KEYPROTO) void lpc_kbc_ibf_interrupt(void); void lpc_kbc_obe_interrupt(void); #endif +#ifdef CONFIG_IT83XX_I2C_CMD_QUEUE +uint32_t i2c_idle_not_allowed(void); +#endif #endif /* __CROS_EC_INTC_H */ diff --git a/chip/it83xx/irq.c b/chip/it83xx/irq.c index 275c6e0e36..21e8070f06 100644 --- a/chip/it83xx/irq.c +++ b/chip/it83xx/irq.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -10,56 +10,59 @@ #include "registers.h" #include "util.h" -#define IRQ_GROUP(n, cpu_ints...) \ - {(uint32_t)&CONCAT2(IT83XX_INTC_ISR, n) - IT83XX_INTC_BASE, \ - (uint32_t)&CONCAT2(IT83XX_INTC_IER, n) - IT83XX_INTC_BASE, \ - ##cpu_ints} +#define IRQ_GROUP(n, cpu_ints...) \ + { \ + (uint32_t) & CONCAT2(IT83XX_INTC_ISR, n) - IT83XX_INTC_BASE, \ + (uint32_t)&CONCAT2(IT83XX_INTC_IER, n) - \ + IT83XX_INTC_BASE, \ + ##cpu_ints \ + } static const struct { uint8_t isr_off; uint8_t ier_off; uint8_t cpu_int[8]; } irq_groups[] = { - IRQ_GROUP(0, {-1, 2, 5, 4, 6, 2, 2, 4}), - IRQ_GROUP(1, { 7, 6, 6, 5, 2, 2, 2, 8}), - IRQ_GROUP(2, { 6, 2, 8, 8, 8, 2, 12, 12}), - IRQ_GROUP(3, { 5, 4, 4, 4, 11, 11, 3, 2}), - IRQ_GROUP(4, {11, 11, 11, 11, 8, 9, 9, 9}), - IRQ_GROUP(5, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(6, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(7, {10, 10, 3, 12, 3, 3, 3, 3}), - IRQ_GROUP(8, { 4, 4, 4, 4, 4, 4, -1, 12}), - IRQ_GROUP(9, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(10, { 3, 6, 12, 12, 5, 2, 2, 2}), - IRQ_GROUP(11, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(12, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(13, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(14, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(15, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(16, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(17, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(18, { 2, 2, 2, 2, -1, 4, 4, 7}), - IRQ_GROUP(19, { 6, 6, 12, 3, 3, 3, 3, 3}), - IRQ_GROUP(20, {12, 12, 12, 12, 12, 12, 12, -1}), + IRQ_GROUP(0, { -1, 2, 5, 4, 6, 2, 2, 4 }), + IRQ_GROUP(1, { 7, 6, 6, 5, 2, 2, 2, 8 }), + IRQ_GROUP(2, { 6, 2, 8, 8, 8, 2, 12, 12 }), + IRQ_GROUP(3, { 5, 4, 4, 4, 11, 11, 3, 2 }), + IRQ_GROUP(4, { 11, 11, 11, 11, 8, 9, 9, 9 }), + IRQ_GROUP(5, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(6, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(7, { 10, 10, 3, 12, 3, 3, 3, 3 }), + IRQ_GROUP(8, { 4, 4, 4, 4, 4, 4, -1, 12 }), + IRQ_GROUP(9, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(10, { 3, 6, 12, 12, 5, 2, 2, 2 }), + IRQ_GROUP(11, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(12, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(13, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(14, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(15, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(16, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(17, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(18, { 2, 2, 2, 2, -1, 4, 4, 7 }), + IRQ_GROUP(19, { 6, 6, 12, 3, 3, 3, 3, 3 }), + IRQ_GROUP(20, { 12, 12, 12, 12, 12, 12, 12, -1 }), #if defined(IT83XX_INTC_GROUP_21_22_SUPPORT) - IRQ_GROUP(21, { 2, 2, 2, 2, 2, 2, 2, 2}), - IRQ_GROUP(22, { 2, 2, -1, -1, -1, -1, -1, -1}), + IRQ_GROUP(21, { 2, 2, 2, 2, 2, 2, 2, 2 }), + IRQ_GROUP(22, { 2, 2, -1, -1, -1, -1, -1, -1 }), #elif defined(CHIP_FAMILY_IT8XXX1) || defined(CHIP_FAMILY_IT8XXX2) - IRQ_GROUP(21, {-1, -1, 12, 12, 12, 12, 12, 12}), - IRQ_GROUP(22, { 2, 2, 2, 2, 2, 2, 2, 2}), + IRQ_GROUP(21, { -1, -1, 12, 12, 12, 12, 12, 12 }), + IRQ_GROUP(22, { 2, 2, 2, 2, 2, 2, 2, 2 }), #else - IRQ_GROUP(21, {-1, -1, -1, -1, -1, -1, -1, -1}), - IRQ_GROUP(22, {-1, -1, -1, -1, -1, -1, -1, -1}), + IRQ_GROUP(21, { -1, -1, -1, -1, -1, -1, -1, -1 }), + IRQ_GROUP(22, { -1, -1, -1, -1, -1, -1, -1, -1 }), #endif - IRQ_GROUP(23, { 2, 2, -1, -1, -1, -1, -1, 2}), - IRQ_GROUP(24, { 2, 2, 2, 2, 2, 2, -1, 2}), - IRQ_GROUP(25, { 2, 2, 2, 2, -1, -1, -1, -1}), - IRQ_GROUP(26, { 2, 2, 2, 2, 2, 2, 2, -1}), - IRQ_GROUP(27, { 2, 2, 2, 2, 2, 2, -1, -1}), - IRQ_GROUP(28, { 2, 2, 2, 2, 2, 2, -1, -1}), + IRQ_GROUP(23, { 2, 2, -1, -1, -1, -1, -1, 2 }), + IRQ_GROUP(24, { 2, 2, 2, 2, 2, 2, -1, 2 }), + IRQ_GROUP(25, { 2, 2, 2, 2, -1, -1, -1, -1 }), + IRQ_GROUP(26, { 2, 2, 2, 2, 2, 2, 2, -1 }), + IRQ_GROUP(27, { 2, 2, 2, 2, 2, 2, -1, -1 }), + IRQ_GROUP(28, { 2, 2, 2, 2, 2, 2, -1, -1 }), }; -#if defined(CHIP_FAMILY_IT8320) /* N8 core */ +#if defined(CHIP_FAMILY_IT8320) /* N8 core */ /* Number of CPU hardware interrupts (HW0 ~ HW15) */ int cpu_int_entry_number; #endif @@ -68,7 +71,7 @@ int chip_get_ec_int(void) { extern volatile int ec_int; -#if defined(CHIP_FAMILY_IT8320) /* N8 core */ +#if defined(CHIP_FAMILY_IT8320) /* N8 core */ int i; for (i = 0; i < IT83XX_IRQ_COUNT; i++) { @@ -85,7 +88,14 @@ int chip_get_ec_int(void) /* Determine interrupt number */ ec_int -= 16; #else /* defined(CHIP_FAMILY_IT8XXX2) RISCV core */ - ec_int = IT83XX_INTC_AIVCT - 0x10; + /* wait until two equal interrupt values are read */ + do { + ec_int = IT83XX_INTC_AIVCT; + } while (ec_int != IT83XX_INTC_AIVCT); + ec_int -= 0x10; + /* Unsupported EC INT number. */ + if (chip_get_intc_group(ec_int) >= 16) + return -1; #endif return ec_int; } @@ -100,7 +110,11 @@ void chip_enable_irq(int irq) int group = irq / 8; int bit = irq % 8; - IT83XX_INTC_REG(irq_groups[group].ier_off) |= BIT(bit); + /* SOC's interrupts share CPU machine-mode external interrupt */ + if (IS_ENABLED(CHIP_CORE_RISCV)) + IT83XX_INTC_REG(irq_groups[group].ier_off) |= BIT(bit); + + /* SOC's interrupts use CPU HW interrupt 2 ~ 15 */ if (IS_ENABLED(CHIP_CORE_NDS32)) IT83XX_INTC_REG(IT83XX_INTC_EXT_IER_OFF(group)) |= BIT(bit); } @@ -110,9 +124,29 @@ void chip_disable_irq(int irq) int group = irq / 8; int bit = irq % 8; - IT83XX_INTC_REG(irq_groups[group].ier_off) &= ~BIT(bit); - if (IS_ENABLED(CHIP_CORE_NDS32)) + /* SOC's interrupts share CPU machine-mode external interrupt */ + if (IS_ENABLED(CHIP_CORE_RISCV)) { + volatile uint8_t _ier __unused; + + IT83XX_INTC_REG(irq_groups[group].ier_off) &= ~BIT(bit); + /* + * This load operation will guarantee the above modification of + * EC's register can be seen by any following instructions. + */ + _ier = IT83XX_INTC_REG(irq_groups[group].ier_off); + } + + /* SOC's interrupts use CPU HW interrupt 2 ~ 15 */ + if (IS_ENABLED(CHIP_CORE_NDS32)) { + volatile uint8_t _ext_ier __unused; + IT83XX_INTC_REG(IT83XX_INTC_EXT_IER_OFF(group)) &= ~BIT(bit); + /* + * This load operation will guarantee the above modification of + * EC's register can be seen by any following instructions. + */ + _ext_ier = IT83XX_INTC_REG(IT83XX_INTC_EXT_IER_OFF(group)); + } } void chip_clear_pending_irq(int irq) diff --git a/chip/it83xx/it83xx_fpu.S b/chip/it83xx/it83xx_fpu.S index 5265eb7253..a75145c835 100644 --- a/chip/it83xx/it83xx_fpu.S +++ b/chip/it83xx/it83xx_fpu.S @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/it83xx/keyboard_raw.c b/chip/it83xx/keyboard_raw.c index 5f44670576..9123a6e5e8 100644 --- a/chip/it83xx/keyboard_raw.c +++ b/chip/it83xx/keyboard_raw.c @@ -1,20 +1,24 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" +#include "irq_chip.h" #include "keyboard_raw.h" #include "keyboard_scan.h" #include "registers.h" #include "task.h" -#include "irq_chip.h" + +#define KSOH_PIN_MASK (((1 << (KEYBOARD_COLS_MAX - 8)) - 1) & 0xff) /* * Initialize the raw keyboard interface. */ void keyboard_raw_init(void) { + uint32_t int_mask; + /* Ensure top-level interrupt is disabled */ keyboard_raw_enable_interrupt(0); @@ -40,8 +44,17 @@ void keyboard_raw_init(void) IT83XX_KBS_KSOL = 0x00; #endif - /* KSO[15:8] pins low. */ - IT83XX_KBS_KSOH1 = 0x00; + /* critical section with interrupts off */ + int_mask = read_clear_int_mask(); + /* + * KSO[COLS_MAX:8] pins low. + * NOTE: KSO[15:8] pins can part be enabled for keyboard function and + * rest be configured as GPIO output mode. In this case that we + * disable the ISR in critical section to avoid race condition. + */ + IT83XX_KBS_KSOH1 &= ~KSOH_PIN_MASK; + /* restore interrupts */ + set_int_mask(int_mask); /* KSI[0-7] falling-edge triggered is selected */ IT83XX_WUC_WUEMR3 = 0xFF; @@ -71,6 +84,7 @@ void keyboard_raw_task_start(void) test_mockable void keyboard_raw_drive_column(int col) { int mask; + uint32_t int_mask; /* Tri-state all outputs */ if (col == KEYBOARD_COLUMN_NONE) @@ -87,7 +101,19 @@ test_mockable void keyboard_raw_drive_column(int col) mask ^= BIT(2); #endif IT83XX_KBS_KSOL = mask & 0xff; - IT83XX_KBS_KSOH1 = (mask >> 8) & 0xff; + + /* critical section with interrupts off */ + int_mask = read_clear_int_mask(); + /* + * Because IT83XX_KBS_KSOH1 register is shared by keyboard scan + * out and GPIO output mode, so we don't drive all KSOH pins + * here (this depends on how many keyboard matrix output pin + * we are using). + */ + IT83XX_KBS_KSOH1 = (IT83XX_KBS_KSOH1 & ~KSOH_PIN_MASK) | + ((mask >> 8) & KSOH_PIN_MASK); + /* restore interrupts */ + set_int_mask(int_mask); } /* @@ -125,3 +151,8 @@ void keyboard_raw_interrupt(void) /* Wake the scan task */ task_wake(TASK_ID_KEYSCAN); } + +int keyboard_raw_is_input_low(int port, int id) +{ + return !(IT83XX_GPIO_DATA_MIRROR(port) & BIT(id)); +} diff --git a/chip/it83xx/kmsc_chip.h b/chip/it83xx/kmsc_chip.h index cf4169a1c4..84f781c0a6 100644 --- a/chip/it83xx/kmsc_chip.h +++ b/chip/it83xx/kmsc_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/it83xx/lpc.c b/chip/it83xx/lpc.c index ae66181430..03606c6085 100644 --- a/chip/it83xx/lpc.c +++ b/chip/it83xx/lpc.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -30,7 +30,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) /* LPC PM channels */ enum lpc_pm_ch { @@ -48,25 +48,25 @@ enum pm_ctrl_mask { PM_CTRL_OBEIE = 0x02, }; -#define LPC_ACPI_CMD LPC_PM1 /* ACPI commands 62h/66h port */ -#define LPC_HOST_CMD LPC_PM2 /* Host commands 200h/204h port */ -#define LPC_HOST_PORT_80H LPC_PM3 /* Host 80h port */ +#define LPC_ACPI_CMD LPC_PM1 /* ACPI commands 62h/66h port */ +#define LPC_HOST_CMD LPC_PM2 /* Host commands 200h/204h port */ +#define LPC_HOST_PORT_80H LPC_PM3 /* Host 80h port */ static uint8_t acpi_ec_memmap[EC_MEMMAP_SIZE] - __attribute__((section(".h2ram.pool.acpiec"))); + __attribute__((section(".h2ram.pool.acpiec"))); static uint8_t host_cmd_memmap[256] - __attribute__((section(".h2ram.pool.hostcmd"))); + __attribute__((section(".h2ram.pool.hostcmd"))); static struct host_packet lpc_packet; static struct host_cmd_handler_args host_cmd_args; -static uint8_t host_cmd_flags; /* Flags from host command */ +static uint8_t host_cmd_flags; /* Flags from host command */ /* Params must be 32-bit aligned */ static uint8_t params_copy[EC_LPC_HOST_PACKET_SIZE] __aligned(4); static int init_done; static int p80l_index; -static struct ec_lpc_host_args * const lpc_host_args = +static struct ec_lpc_host_args *const lpc_host_args = (struct ec_lpc_host_args *)host_cmd_memmap; static void pm_set_ctrl(enum lpc_pm_ch ch, enum pm_ctrl_mask ctrl, int set) @@ -136,9 +136,9 @@ static void keyboard_irq_assert(void) */ static void lpc_generate_smi(void) { -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI espi_vw_set_wire(VW_SMI_L, 0); - udelay(65); + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); espi_vw_set_wire(VW_SMI_L, 1); #else gpio_set_level(GPIO_PCH_SMI_L, 0); @@ -149,9 +149,9 @@ static void lpc_generate_smi(void) static void lpc_generate_sci(void) { -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI espi_vw_set_wire(VW_SCI_L, 0); - udelay(65); + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); espi_vw_set_wire(VW_SCI_L, 1); #else gpio_set_level(GPIO_PCH_SCI_L, 0); @@ -195,15 +195,13 @@ static void lpc_send_response(struct host_cmd_handler_args *args) } /* New-style response */ - lpc_host_args->flags = - (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) | - EC_HOST_ARGS_FLAG_TO_HOST; + lpc_host_args->flags = (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) | + EC_HOST_ARGS_FLAG_TO_HOST; lpc_host_args->data_size = size; csum = args->command + lpc_host_args->flags + - lpc_host_args->command_version + - lpc_host_args->data_size; + lpc_host_args->command_version + lpc_host_args->data_size; for (i = 0, out = (uint8_t *)args->response; i < size; i++, out++) csum += *out; @@ -251,7 +249,7 @@ void lpc_update_host_event_status(void) /* Copy host events to mapped memory */ *(host_event_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = - lpc_get_host_events(); + lpc_get_host_events(); task_enable_irq(IT83XX_IRQ_PMC_IN); @@ -377,7 +375,7 @@ void lpc_clear_acpi_status_mask(uint8_t mask) pm_set_status(LPC_ACPI_CMD, mask, 0); } -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI int lpc_get_pltrst_asserted(void) { return !gpio_get_level(GPIO_PCH_PLTRST_L); @@ -390,7 +388,7 @@ void lpc_kbc_ibf_interrupt(void) { if (lpc_keyboard_input_pending()) { keyboard_host_write(IT83XX_KBC_KBHIDIR, - (IT83XX_KBC_KBHISR & 0x08) ? 1 : 0); + (IT83XX_KBC_KBHISR & 0x08) ? 1 : 0); /* bit7, write-1 clear IBF */ IT83XX_KBC_KBHICR |= BIT(7); IT83XX_KBC_KBHICR &= ~BIT(7); @@ -565,7 +563,7 @@ static void lpc_init(void) { enum ec2i_message ec2i_r; - /* SPI slave interface is disabled */ + /* SPI peripheral interface is disabled */ IT83XX_GCTRL_SSCR = 0; /* * DLM 52k~56k size select enable. @@ -688,7 +686,7 @@ static void lpc_init(void) */ IT83XX_GCTRL_SPCTRL1 |= 0xC2; -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI gpio_enable_interrupt(GPIO_PCH_PLTRST_L); #endif @@ -711,7 +709,7 @@ static void lpc_init(void) task_clear_pending_irq(IT83XX_IRQ_PMC3_IN); task_enable_irq(IT83XX_IRQ_PMC3_IN); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI espi_init(); #endif /* Sufficiently initialized */ @@ -726,15 +724,14 @@ static void lpc_init(void) */ DECLARE_HOOK(HOOK_INIT, lpc_init, HOOK_PRIO_INIT_LPC); -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI void lpcrst_interrupt(enum gpio_signal signal) { if (lpc_get_pltrst_asserted()) /* Store port 80 reset event */ port_80_write(PORT_80_EVENT_RESET); - CPRINTS("LPC RESET# %sasserted", - lpc_get_pltrst_asserted() ? "" : "de"); + CPRINTS("LPC RESET# %sasserted", lpc_get_pltrst_asserted() ? "" : "de"); } #endif @@ -765,6 +762,5 @@ static enum ec_status lpc_get_protocol_info(struct host_cmd_handler_args *args) return EC_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, - lpc_get_protocol_info, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, lpc_get_protocol_info, + EC_VER_MASK(0)); diff --git a/chip/it83xx/peci.c b/chip/it83xx/peci.c index 07336eaaf6..ee94f2baac 100644 --- a/chip/it83xx/peci.c +++ b/chip/it83xx/peci.c @@ -1,35 +1,34 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* PECI interface for Chrome EC */ +#include "builtin/assert.h" #include "clock.h" #include "hooks.h" #include "peci.h" #include "registers.h" -#include "util.h" -#include "timer.h" #include "task.h" +#include "timer.h" +#include "util.h" enum peci_status { - PECI_STATUS_NO_ERR = 0x00, - PECI_STATUS_HOBY = 0x01, - PECI_STATUS_FINISH = 0x02, - PECI_STATUS_RD_FCS_ERR = 0x04, - PECI_STATUS_WR_FCS_ERR = 0x08, - PECI_STATUS_EXTERR = 0x20, - PECI_STATUS_BUSERR = 0x40, - PECI_STATUS_RCV_ERRCODE = 0x80, - PECI_STATUS_ERR_NEED_RST = (PECI_STATUS_BUSERR | PECI_STATUS_EXTERR), - PECI_STATUS_ANY_ERR = (PECI_STATUS_RCV_ERRCODE | - PECI_STATUS_BUSERR | - PECI_STATUS_EXTERR | - PECI_STATUS_WR_FCS_ERR | - PECI_STATUS_RD_FCS_ERR), - PECI_STATUS_ANY_BIT = 0xFE, - PECI_STATUS_TIMEOUT = 0xFF, + PECI_STATUS_NO_ERR = 0x00, + PECI_STATUS_HOBY = 0x01, + PECI_STATUS_FINISH = 0x02, + PECI_STATUS_RD_FCS_ERR = 0x04, + PECI_STATUS_WR_FCS_ERR = 0x08, + PECI_STATUS_EXTERR = 0x20, + PECI_STATUS_BUSERR = 0x40, + PECI_STATUS_RCV_ERRCODE = 0x80, + PECI_STATUS_ERR_NEED_RST = (PECI_STATUS_BUSERR | PECI_STATUS_EXTERR), + PECI_STATUS_ANY_ERR = (PECI_STATUS_RCV_ERRCODE | PECI_STATUS_BUSERR | + PECI_STATUS_EXTERR | PECI_STATUS_WR_FCS_ERR | + PECI_STATUS_RD_FCS_ERR), + PECI_STATUS_ANY_BIT = 0xFE, + PECI_STATUS_TIMEOUT = 0xFF, }; static task_id_t peci_current_task; @@ -106,10 +105,9 @@ int peci_transaction(struct peci_data *peci) IT83XX_PECI_HOWRLR = 0x00; } else { if ((peci->cmd_code == PECI_CMD_WR_PKG_CFG) || - (peci->cmd_code == PECI_CMD_WR_IAMSR) || - (peci->cmd_code == PECI_CMD_WR_PCI_CFG) || - (peci->cmd_code == PECI_CMD_WR_PCI_CFG_LOCAL)) { - + (peci->cmd_code == PECI_CMD_WR_IAMSR) || + (peci->cmd_code == PECI_CMD_WR_PCI_CFG) || + (peci->cmd_code == PECI_CMD_WR_PCI_CFG_LOCAL)) { /* write length include Cmd Code + AW FCS */ IT83XX_PECI_HOWRLR = peci->w_len + 2; @@ -157,17 +155,14 @@ int peci_transaction(struct peci_data *peci) peci_current_task = TASK_ID_INVALID; if (index < peci->timeout_us) { - status = IT83XX_PECI_HOSTAR; /* any error */ if (IT83XX_PECI_HOSTAR & PECI_STATUS_ANY_ERR) { - if (IT83XX_PECI_HOSTAR & PECI_STATUS_ERR_NEED_RST) peci_reset(); } else if (IT83XX_PECI_HOSTAR & PECI_STATUS_FINISH) { - /* The read data field of the PECI protocol. */ for (index = 0x00; index < peci->r_len; index++) peci->r_buf[index] = IT83XX_PECI_HORDDR; diff --git a/chip/it83xx/pwm.c b/chip/it83xx/pwm.c index 6328c69b46..3d0d4eaeb6 100644 --- a/chip/it83xx/pwm.c +++ b/chip/it83xx/pwm.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,35 +8,35 @@ #include "clock.h" #include "gpio.h" #include "hooks.h" +#include "math_util.h" #include "pwm.h" #include "pwm_chip.h" #include "registers.h" #include "util.h" -#include "math_util.h" #define PWM_CTRX_MIN 100 -#define PWM_EC_FREQ 8000000 +#define PWM_EC_FREQ 8000000 const struct pwm_ctrl_t pwm_ctrl_regs[] = { - { &IT83XX_PWM_DCR0, &IT83XX_PWM_PCSSGL, &IT83XX_GPIO_GPCRA0}, - { &IT83XX_PWM_DCR1, &IT83XX_PWM_PCSSGL, &IT83XX_GPIO_GPCRA1}, - { &IT83XX_PWM_DCR2, &IT83XX_PWM_PCSSGL, &IT83XX_GPIO_GPCRA2}, - { &IT83XX_PWM_DCR3, &IT83XX_PWM_PCSSGL, &IT83XX_GPIO_GPCRA3}, - { &IT83XX_PWM_DCR4, &IT83XX_PWM_PCSSGH, &IT83XX_GPIO_GPCRA4}, - { &IT83XX_PWM_DCR5, &IT83XX_PWM_PCSSGH, &IT83XX_GPIO_GPCRA5}, - { &IT83XX_PWM_DCR6, &IT83XX_PWM_PCSSGH, &IT83XX_GPIO_GPCRA6}, - { &IT83XX_PWM_DCR7, &IT83XX_PWM_PCSSGH, &IT83XX_GPIO_GPCRA7}, + { &IT83XX_PWM_DCR0, &IT83XX_PWM_PCSSGL, &IT83XX_GPIO_GPCRA0 }, + { &IT83XX_PWM_DCR1, &IT83XX_PWM_PCSSGL, &IT83XX_GPIO_GPCRA1 }, + { &IT83XX_PWM_DCR2, &IT83XX_PWM_PCSSGL, &IT83XX_GPIO_GPCRA2 }, + { &IT83XX_PWM_DCR3, &IT83XX_PWM_PCSSGL, &IT83XX_GPIO_GPCRA3 }, + { &IT83XX_PWM_DCR4, &IT83XX_PWM_PCSSGH, &IT83XX_GPIO_GPCRA4 }, + { &IT83XX_PWM_DCR5, &IT83XX_PWM_PCSSGH, &IT83XX_GPIO_GPCRA5 }, + { &IT83XX_PWM_DCR6, &IT83XX_PWM_PCSSGH, &IT83XX_GPIO_GPCRA6 }, + { &IT83XX_PWM_DCR7, &IT83XX_PWM_PCSSGH, &IT83XX_GPIO_GPCRA7 }, }; const struct pwm_ctrl_t2 pwm_clock_ctrl_regs[] = { { &IT83XX_PWM_CTR, &IT83XX_PWM_C0CPRS, &IT83XX_PWM_C0CPRS, - &IT83XX_PWM_PCFSR, 0x01}, + &IT83XX_PWM_PCFSR, 0x01 }, { &IT83XX_PWM_CTR1, &IT83XX_PWM_C4CPRS, &IT83XX_PWM_C4MCPRS, - &IT83XX_PWM_PCFSR, 0x02}, + &IT83XX_PWM_PCFSR, 0x02 }, { &IT83XX_PWM_CTR2, &IT83XX_PWM_C6CPRS, &IT83XX_PWM_C6MCPRS, - &IT83XX_PWM_PCFSR, 0x04}, + &IT83XX_PWM_PCFSR, 0x04 }, { &IT83XX_PWM_CTR3, &IT83XX_PWM_C7CPRS, &IT83XX_PWM_C7MCPRS, - &IT83XX_PWM_PCFSR, 0x08}, + &IT83XX_PWM_PCFSR, 0x08 }, }; static int pwm_get_cycle_time(enum pwm_channel ch) @@ -67,18 +67,19 @@ static int pwm_get_cycle_time(enum pwm_channel ch) void pwm_enable(enum pwm_channel ch, int enabled) { /* pwm channel mapping */ - ch = pwm_channels[ch].channel; + int pwm_reg_index = pwm_channels[ch].channel; /* * enabled : pin to PWM function. * disabled : pin to GPIO input function. */ if (enabled) - *pwm_ctrl_regs[ch].pwm_pin = 0x00; + *pwm_ctrl_regs[pwm_reg_index].pwm_pin = 0x00; else - *pwm_ctrl_regs[ch].pwm_pin = 0x80 | - ((pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW) ? - 4 : 2); + *pwm_ctrl_regs[pwm_reg_index].pwm_pin = + 0x80 | + ((pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW) ? 4 : + 2); } int pwm_get_enabled(enum pwm_channel ch) @@ -88,7 +89,9 @@ int pwm_get_enabled(enum pwm_channel ch) /* pin is PWM function and PWMs clock counter was enabled */ return ((*pwm_ctrl_regs[ch].pwm_pin & ~0x04) == 0x00 && - IT83XX_PWM_ZTIER & 0x02) ? 1 : 0; + IT83XX_PWM_ZTIER & 0x02) ? + 1 : + 0; } void pwm_set_duty(enum pwm_channel ch, int percent) @@ -202,7 +205,8 @@ static int pwm_ch_freq(enum pwm_channel ch) int actual_freq = -1, targe_freq, deviation; int pcfsr, ctr, pcfsr_sel, pcs_shift, pcs_mask; int pwm_clk_src = (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP) ? - 32768 : PWM_EC_FREQ; + 32768 : + PWM_EC_FREQ; targe_freq = pwm_channels[ch].freq_hz; deviation = (targe_freq / 100) + 1; @@ -251,8 +255,8 @@ static int pwm_ch_freq(enum pwm_channel ch) *pwm_ctrl_regs[ch].pwm_clock_source |= pcs_mask; *pwm_clock_ctrl_regs[pcfsr_sel].pwm_cpr_lsb = pcfsr & 0xFF; - *pwm_clock_ctrl_regs[pcfsr_sel].pwm_cpr_msb = - (pcfsr >> 8) & 0xFF; + *pwm_clock_ctrl_regs[pcfsr_sel].pwm_cpr_msb = (pcfsr >> 8) & + 0xFF; } return actual_freq; diff --git a/chip/it83xx/pwm_chip.h b/chip/it83xx/pwm_chip.h index 4e8aba1c62..03435d03f6 100644 --- a/chip/it83xx/pwm_chip.h +++ b/chip/it83xx/pwm_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h index 7f70724864..ade0b97289 100644 --- a/chip/it83xx/registers.h +++ b/chip/it83xx/registers.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,775 +11,776 @@ #include "common.h" #include "compile_time_macros.h" -#define __ram_code __attribute__((section(".ram_code"))) +#define __ram_code __attribute__((section(__RAM_CODE_SECTION_NAME))) /* IRQ numbers */ /* Group 0 */ -#define IT83XX_IRQ_WKO20 1 -#define IT83XX_IRQ_KBC_OUT 2 -#define IT83XX_IRQ_PMC_OUT 3 -#define IT83XX_IRQ_SMB_D 4 -#define IT83XX_IRQ_WKINTAD 5 -#define IT83XX_IRQ_WKO23 6 -#define IT83XX_IRQ_PWM 7 +#define IT83XX_IRQ_WKO20 1 +#define IT83XX_IRQ_KBC_OUT 2 +#define IT83XX_IRQ_PMC_OUT 3 +#define IT83XX_IRQ_SMB_D 4 +#define IT83XX_IRQ_WKINTAD 5 +#define IT83XX_IRQ_WKO23 6 +#define IT83XX_IRQ_PWM 7 /* Group 1 */ -#define IT83XX_IRQ_ADC 8 -#define IT83XX_IRQ_SMB_A 9 -#define IT83XX_IRQ_SMB_B 10 -#define IT83XX_IRQ_KB_MATRIX 11 -#define IT83XX_IRQ_WKO26 12 -#define IT83XX_IRQ_WKINTC 13 -#define IT83XX_IRQ_WKO25 14 -#define IT83XX_IRQ_CIR 15 +#define IT83XX_IRQ_ADC 8 +#define IT83XX_IRQ_SMB_A 9 +#define IT83XX_IRQ_SMB_B 10 +#define IT83XX_IRQ_KB_MATRIX 11 +#define IT83XX_IRQ_WKO26 12 +#define IT83XX_IRQ_WKINTC 13 +#define IT83XX_IRQ_WKO25 14 +#define IT83XX_IRQ_CIR 15 /* Group 2 */ -#define IT83XX_IRQ_SMB_C 16 -#define IT83XX_IRQ_WKO24 17 -#define IT83XX_IRQ_PS2_2 18 -#define IT83XX_IRQ_PS2_1 19 -#define IT83XX_IRQ_PS2_0 20 -#define IT83XX_IRQ_WKO22 21 -#define IT83XX_IRQ_SMFI 22 -#define IT83XX_IRQ_USB 23 +#define IT83XX_IRQ_SMB_C 16 +#define IT83XX_IRQ_WKO24 17 +#define IT83XX_IRQ_PS2_2 18 +#define IT83XX_IRQ_PS2_1 19 +#define IT83XX_IRQ_PS2_0 20 +#define IT83XX_IRQ_WKO22 21 +#define IT83XX_IRQ_SMFI 22 +#define IT83XX_IRQ_USB 23 /* Group 3 */ -#define IT83XX_IRQ_KBC_IN 24 -#define IT83XX_IRQ_PMC_IN 25 -#define IT83XX_IRQ_PMC2_OUT 26 -#define IT83XX_IRQ_PMC2_IN 27 -#define IT83XX_IRQ_GINT 28 -#define IT83XX_IRQ_EGPC 29 -#define IT83XX_IRQ_EXT_TIMER1 30 -#define IT83XX_IRQ_WKO21 31 +#define IT83XX_IRQ_KBC_IN 24 +#define IT83XX_IRQ_PMC_IN 25 +#define IT83XX_IRQ_PMC2_OUT 26 +#define IT83XX_IRQ_PMC2_IN 27 +#define IT83XX_IRQ_GINT 28 +#define IT83XX_IRQ_EGPC 29 +#define IT83XX_IRQ_EXT_TIMER1 30 +#define IT83XX_IRQ_WKO21 31 /* Group 4 */ -#define IT83XX_IRQ_GPINT0 32 -#define IT83XX_IRQ_GPINT1 33 -#define IT83XX_IRQ_GPINT2 34 -#define IT83XX_IRQ_GPINT3 35 -#define IT83XX_IRQ_CIR_GPINT 36 -#define IT83XX_IRQ_SSPI 37 -#define IT83XX_IRQ_UART1 38 -#define IT83XX_IRQ_UART2 39 +#define IT83XX_IRQ_GPINT0 32 +#define IT83XX_IRQ_GPINT1 33 +#define IT83XX_IRQ_GPINT2 34 +#define IT83XX_IRQ_GPINT3 35 +#define IT83XX_IRQ_CIR_GPINT 36 +#define IT83XX_IRQ_SSPI 37 +#define IT83XX_IRQ_UART1 38 +#define IT83XX_IRQ_UART2 39 /* Group 5 */ -#define IT83XX_IRQ_WKO50 40 -#define IT83XX_IRQ_WKO51 41 -#define IT83XX_IRQ_WKO52 42 -#define IT83XX_IRQ_WKO53 43 -#define IT83XX_IRQ_WKO54 44 -#define IT83XX_IRQ_WKO55 45 -#define IT83XX_IRQ_WKO56 46 -#define IT83XX_IRQ_WKO57 47 +#define IT83XX_IRQ_WKO50 40 +#define IT83XX_IRQ_WKO51 41 +#define IT83XX_IRQ_WKO52 42 +#define IT83XX_IRQ_WKO53 43 +#define IT83XX_IRQ_WKO54 44 +#define IT83XX_IRQ_WKO55 45 +#define IT83XX_IRQ_WKO56 46 +#define IT83XX_IRQ_WKO57 47 /* Group 6 */ -#define IT83XX_IRQ_WKO60 48 -#define IT83XX_IRQ_WKO61 49 -#define IT83XX_IRQ_WKO62 50 -#define IT83XX_IRQ_WKO63 51 -#define IT83XX_IRQ_WKO64 52 -#define IT83XX_IRQ_WKO65 53 -#define IT83XX_IRQ_WKO66 54 -#define IT83XX_IRQ_WKO67 55 +#define IT83XX_IRQ_WKO60 48 +#define IT83XX_IRQ_WKO61 49 +#define IT83XX_IRQ_WKO62 50 +#define IT83XX_IRQ_WKO63 51 +#define IT83XX_IRQ_WKO64 52 +#define IT83XX_IRQ_WKO65 53 +#define IT83XX_IRQ_WKO66 54 +#define IT83XX_IRQ_WKO67 55 /* Group 7 */ -#define IT83XX_IRQ_RTCT_ALARM1 56 -#define IT83XX_IRQ_RTCT_ALARM2 57 -#define IT83XX_IRQ_EXT_TIMER2 58 -#define IT83XX_IRQ_DEFERRED_SPI 59 -#define IT83XX_IRQ_TMR_A0 60 -#define IT83XX_IRQ_TMR_A1 61 -#define IT83XX_IRQ_TMR_B0 62 -#define IT83XX_IRQ_TMR_B1 63 +#define IT83XX_IRQ_RTCT_ALARM1 56 +#define IT83XX_IRQ_RTCT_ALARM2 57 +#define IT83XX_IRQ_EXT_TIMER2 58 +#define IT83XX_IRQ_DEFERRED_SPI 59 +#define IT83XX_IRQ_TMR_A0 60 +#define IT83XX_IRQ_TMR_A1 61 +#define IT83XX_IRQ_TMR_B0 62 +#define IT83XX_IRQ_TMR_B1 63 /* Group 8 */ -#define IT83XX_IRQ_PMC2EX_OUT 64 -#define IT83XX_IRQ_PMC2EX_IN 65 -#define IT83XX_IRQ_PMC3_OUT 66 -#define IT83XX_IRQ_PMC3_IN 67 -#define IT83XX_IRQ_PMC4_OUT 68 -#define IT83XX_IRQ_PMC4_IN 69 -#define IT83XX_IRQ_I2BRAM 71 +#define IT83XX_IRQ_PMC2EX_OUT 64 +#define IT83XX_IRQ_PMC2EX_IN 65 +#define IT83XX_IRQ_PMC3_OUT 66 +#define IT83XX_IRQ_PMC3_IN 67 +#define IT83XX_IRQ_PMC4_OUT 68 +#define IT83XX_IRQ_PMC4_IN 69 +#define IT83XX_IRQ_I2BRAM 71 /* Group 9 */ -#define IT83XX_IRQ_WKO70 72 -#define IT83XX_IRQ_WKO71 73 -#define IT83XX_IRQ_WKO72 74 -#define IT83XX_IRQ_WKO73 75 -#define IT83XX_IRQ_WKO74 76 -#define IT83XX_IRQ_WKO75 77 -#define IT83XX_IRQ_WKO76 78 -#define IT83XX_IRQ_WKO77 79 +#define IT83XX_IRQ_WKO70 72 +#define IT83XX_IRQ_WKO71 73 +#define IT83XX_IRQ_WKO72 74 +#define IT83XX_IRQ_WKO73 75 +#define IT83XX_IRQ_WKO74 76 +#define IT83XX_IRQ_WKO75 77 +#define IT83XX_IRQ_WKO76 78 +#define IT83XX_IRQ_WKO77 79 /* Group 10 */ -#define IT83XX_IRQ_EXT_TMR8 80 +#define IT83XX_IRQ_EXT_TMR8 80 #define IT83XX_IRQ_SMB_CLOCK_HELD 81 -#define IT83XX_IRQ_CEC 82 -#define IT83XX_IRQ_H2RAM_LPC 83 -#define IT83XX_IRQ_HW_KB_SCAN 84 -#define IT83XX_IRQ_WKO88 85 -#define IT83XX_IRQ_WKO89 86 -#define IT83XX_IRQ_WKO90 87 +#define IT83XX_IRQ_CEC 82 +#define IT83XX_IRQ_H2RAM_LPC 83 +#define IT83XX_IRQ_HW_KB_SCAN 84 +#define IT83XX_IRQ_WKO88 85 +#define IT83XX_IRQ_WKO89 86 +#define IT83XX_IRQ_WKO90 87 /* Group 11 */ -#define IT83XX_IRQ_WKO80 88 -#define IT83XX_IRQ_WKO81 89 -#define IT83XX_IRQ_WKO82 90 -#define IT83XX_IRQ_WKO83 91 -#define IT83XX_IRQ_WKO84 92 -#define IT83XX_IRQ_WKO85 93 -#define IT83XX_IRQ_WKO86 94 -#define IT83XX_IRQ_WKO87 95 +#define IT83XX_IRQ_WKO80 88 +#define IT83XX_IRQ_WKO81 89 +#define IT83XX_IRQ_WKO82 90 +#define IT83XX_IRQ_WKO83 91 +#define IT83XX_IRQ_WKO84 92 +#define IT83XX_IRQ_WKO85 93 +#define IT83XX_IRQ_WKO86 94 +#define IT83XX_IRQ_WKO87 95 /* Group 12 */ -#define IT83XX_IRQ_WKO91 96 -#define IT83XX_IRQ_WKO92 97 -#define IT83XX_IRQ_WKO93 98 -#define IT83XX_IRQ_WKO94 99 -#define IT83XX_IRQ_WKO95 100 -#define IT83XX_IRQ_WKO96 101 -#define IT83XX_IRQ_WKO97 102 -#define IT83XX_IRQ_WKO98 103 +#define IT83XX_IRQ_WKO91 96 +#define IT83XX_IRQ_WKO92 97 +#define IT83XX_IRQ_WKO93 98 +#define IT83XX_IRQ_WKO94 99 +#define IT83XX_IRQ_WKO95 100 +#define IT83XX_IRQ_WKO96 101 +#define IT83XX_IRQ_WKO97 102 +#define IT83XX_IRQ_WKO98 103 /* Group 13 */ -#define IT83XX_IRQ_WKO99 104 -#define IT83XX_IRQ_WKO100 105 -#define IT83XX_IRQ_WKO101 106 -#define IT83XX_IRQ_WKO102 107 -#define IT83XX_IRQ_WKO103 108 -#define IT83XX_IRQ_WKO104 109 -#define IT83XX_IRQ_WKO105 110 -#define IT83XX_IRQ_WKO106 111 +#define IT83XX_IRQ_WKO99 104 +#define IT83XX_IRQ_WKO100 105 +#define IT83XX_IRQ_WKO101 106 +#define IT83XX_IRQ_WKO102 107 +#define IT83XX_IRQ_WKO103 108 +#define IT83XX_IRQ_WKO104 109 +#define IT83XX_IRQ_WKO105 110 +#define IT83XX_IRQ_WKO106 111 /* Group 14 */ -#define IT83XX_IRQ_WKO107 112 -#define IT83XX_IRQ_WKO108 113 -#define IT83XX_IRQ_WKO109 114 -#define IT83XX_IRQ_WKO110 115 -#define IT83XX_IRQ_WKO111 116 -#define IT83XX_IRQ_WKO112 117 -#define IT83XX_IRQ_WKO113 118 -#define IT83XX_IRQ_WKO114 119 +#define IT83XX_IRQ_WKO107 112 +#define IT83XX_IRQ_WKO108 113 +#define IT83XX_IRQ_WKO109 114 +#define IT83XX_IRQ_WKO110 115 +#define IT83XX_IRQ_WKO111 116 +#define IT83XX_IRQ_WKO112 117 +#define IT83XX_IRQ_WKO113 118 +#define IT83XX_IRQ_WKO114 119 /* Group 15 */ -#define IT83XX_IRQ_WKO115 120 -#define IT83XX_IRQ_WKO116 121 -#define IT83XX_IRQ_WKO117 122 -#define IT83XX_IRQ_WKO118 123 -#define IT83XX_IRQ_WKO119 124 -#define IT83XX_IRQ_WKO120 125 -#define IT83XX_IRQ_WKO121 126 -#define IT83XX_IRQ_WKO122 127 +#define IT83XX_IRQ_WKO115 120 +#define IT83XX_IRQ_WKO116 121 +#define IT83XX_IRQ_WKO117 122 +#define IT83XX_IRQ_WKO118 123 +#define IT83XX_IRQ_WKO119 124 +#define IT83XX_IRQ_WKO120 125 +#define IT83XX_IRQ_WKO121 126 +#define IT83XX_IRQ_WKO122 127 /* Group 16 */ -#define IT83XX_IRQ_WKO128 128 -#define IT83XX_IRQ_WKO129 129 -#define IT83XX_IRQ_WKO130 130 -#define IT83XX_IRQ_WKO131 131 -#define IT83XX_IRQ_WKO132 132 -#define IT83XX_IRQ_WKO133 133 -#define IT83XX_IRQ_WKO134 134 -#define IT83XX_IRQ_WKO135 135 +#define IT83XX_IRQ_WKO128 128 +#define IT83XX_IRQ_WKO129 129 +#define IT83XX_IRQ_WKO130 130 +#define IT83XX_IRQ_WKO131 131 +#define IT83XX_IRQ_WKO132 132 +#define IT83XX_IRQ_WKO133 133 +#define IT83XX_IRQ_WKO134 134 +#define IT83XX_IRQ_WKO135 135 /* Group 17 */ -#define IT83XX_IRQ_WKO136 136 -#define IT83XX_IRQ_WKO137 137 -#define IT83XX_IRQ_WKO138 138 -#define IT83XX_IRQ_WKO139 139 -#define IT83XX_IRQ_WKO140 140 -#define IT83XX_IRQ_WKO141 141 -#define IT83XX_IRQ_WKO142 142 -#define IT83XX_IRQ_WKO143 143 +#define IT83XX_IRQ_WKO136 136 +#define IT83XX_IRQ_WKO137 137 +#define IT83XX_IRQ_WKO138 138 +#define IT83XX_IRQ_WKO139 139 +#define IT83XX_IRQ_WKO140 140 +#define IT83XX_IRQ_WKO141 141 +#define IT83XX_IRQ_WKO142 142 +#define IT83XX_IRQ_WKO143 143 /* Group 18 */ -#define IT83XX_IRQ_WKO123 144 -#define IT83XX_IRQ_WKO124 145 -#define IT83XX_IRQ_WKO125 146 -#define IT83XX_IRQ_WKO126 147 -#define IT83XX_IRQ_PMC5_OUT 149 -#define IT83XX_IRQ_PMC5_IN 150 -#define IT83XX_IRQ_V_COMP 151 +#define IT83XX_IRQ_WKO123 144 +#define IT83XX_IRQ_WKO124 145 +#define IT83XX_IRQ_WKO125 146 +#define IT83XX_IRQ_WKO126 147 +#define IT83XX_IRQ_PMC5_OUT 149 +#define IT83XX_IRQ_PMC5_IN 150 +#define IT83XX_IRQ_V_COMP 151 /* Group 19 */ -#define IT83XX_IRQ_SMB_E 152 -#define IT83XX_IRQ_SMB_F 153 -#define IT83XX_IRQ_OSC_DMA 154 -#define IT83XX_IRQ_EXT_TIMER3 155 -#define IT83XX_IRQ_EXT_TIMER4 156 -#define IT83XX_IRQ_EXT_TIMER5 157 -#define IT83XX_IRQ_EXT_TIMER6 158 -#define IT83XX_IRQ_EXT_TIMER7 159 +#define IT83XX_IRQ_SMB_E 152 +#define IT83XX_IRQ_SMB_F 153 +#define IT83XX_IRQ_OSC_DMA 154 +#define IT83XX_IRQ_EXT_TIMER3 155 +#define IT83XX_IRQ_EXT_TIMER4 156 +#define IT83XX_IRQ_EXT_TIMER5 157 +#define IT83XX_IRQ_EXT_TIMER6 158 +#define IT83XX_IRQ_EXT_TIMER7 159 /* Group 20 */ -#define IT83XX_IRQ_PECI 160 -#define IT83XX_IRQ_SOFTWARE 161 -#define IT83XX_IRQ_ESPI 162 -#define IT83XX_IRQ_ESPI_VW 163 -#define IT83XX_IRQ_PCH_P80 164 -#define IT83XX_IRQ_USBPD0 165 -#define IT83XX_IRQ_USBPD1 166 +#define IT83XX_IRQ_PECI 160 +#define IT83XX_IRQ_SOFTWARE 161 +#define IT83XX_IRQ_ESPI 162 +#define IT83XX_IRQ_ESPI_VW 163 +#define IT83XX_IRQ_PCH_P80 164 +#define IT83XX_IRQ_USBPD0 165 +#define IT83XX_IRQ_USBPD1 166 /* Group 21 */ #if defined(CHIP_FAMILY_IT8320) -#define IT83XX_IRQ_WKO40 168 -#define IT83XX_IRQ_WKO45 169 -#define IT83XX_IRQ_WKO46 170 -#define IT83XX_IRQ_WKO144 171 -#define IT83XX_IRQ_WKO145 172 -#define IT83XX_IRQ_WKO146 173 -#define IT83XX_IRQ_WKO147 174 -#define IT83XX_IRQ_WKO148 175 +#define IT83XX_IRQ_WKO40 168 +#define IT83XX_IRQ_WKO45 169 +#define IT83XX_IRQ_WKO46 170 +#define IT83XX_IRQ_WKO144 171 +#define IT83XX_IRQ_WKO145 172 +#define IT83XX_IRQ_WKO146 173 +#define IT83XX_IRQ_WKO147 174 +#define IT83XX_IRQ_WKO148 175 /* Group 22 */ -#define IT83XX_IRQ_WKO149 176 -#define IT83XX_IRQ_WKO150 177 +#define IT83XX_IRQ_WKO149 176 +#define IT83XX_IRQ_WKO150 177 -#define IT83XX_IRQ_COUNT 178 +#define IT83XX_IRQ_COUNT 178 #elif defined(CHIP_FAMILY_IT8XXX1) || defined(CHIP_FAMILY_IT8XXX2) /* Group 21 */ -#define IT83XX_IRQ_AUDIO_IF 170 -#define IT83XX_IRQ_SPI_SLAVE 171 -#define IT83XX_IRQ_DSP_ENGINE 172 -#define IT83XX_IRQ_NN_ENGINE 173 -#define IT83XX_IRQ_USBPD2 174 -#define IT83XX_IRQ_CRYPTO 175 +#define IT83XX_IRQ_AUDIO_IF 170 +#define IT83XX_IRQ_SPI_PERIPHERAL 171 +#define IT83XX_IRQ_DSP_ENGINE 172 +#define IT83XX_IRQ_NN_ENGINE 173 +#define IT83XX_IRQ_USBPD2 174 +#define IT83XX_IRQ_CRYPTO 175 /* Group 22 */ -#define IT83XX_IRQ_WKO40 176 -#define IT83XX_IRQ_WKO45 177 -#define IT83XX_IRQ_WKO46 178 -#define IT83XX_IRQ_WKO144 179 -#define IT83XX_IRQ_WKO145 180 -#define IT83XX_IRQ_WKO146 181 -#define IT83XX_IRQ_WKO147 182 -#define IT83XX_IRQ_WKO148 183 +#define IT83XX_IRQ_WKO40 176 +#define IT83XX_IRQ_WKO45 177 +#define IT83XX_IRQ_WKO46 178 +#define IT83XX_IRQ_WKO144 179 +#define IT83XX_IRQ_WKO145 180 +#define IT83XX_IRQ_WKO146 181 +#define IT83XX_IRQ_WKO147 182 +#define IT83XX_IRQ_WKO148 183 /* Group 23 */ -#define IT83XX_IRQ_WKO149 184 -#define IT83XX_IRQ_WKO150 185 -#define IT83XX_IRQ_SSPI1 191 +#define IT83XX_IRQ_WKO149 184 +#define IT83XX_IRQ_WKO150 185 +#define IT83XX_IRQ_SSPI1 191 /* Group 24 */ -#define IT83XX_IRQ_XLPIN0 192 -#define IT83XX_IRQ_XLPIN1 193 -#define IT83XX_IRQ_XLPIN2 194 -#define IT83XX_IRQ_XLPIN3 195 -#define IT83XX_IRQ_XLPIN4 196 -#define IT83XX_IRQ_XLPIN5 197 -#define IT83XX_IRQ_WEEK_ALARM 199 +#define IT83XX_IRQ_XLPIN0 192 +#define IT83XX_IRQ_XLPIN1 193 +#define IT83XX_IRQ_XLPIN2 194 +#define IT83XX_IRQ_XLPIN3 195 +#define IT83XX_IRQ_XLPIN4 196 +#define IT83XX_IRQ_XLPIN5 197 +#define IT83XX_IRQ_WEEK_ALARM 199 /* Group 25 */ -#define IT83XX_IRQ_GPO0 200 -#define IT83XX_IRQ_GPO1 201 -#define IT83XX_IRQ_GPO2 202 -#define IT83XX_IRQ_GPO3 203 +#define IT83XX_IRQ_GPO0 200 +#define IT83XX_IRQ_GPO1 201 +#define IT83XX_IRQ_GPO2 202 +#define IT83XX_IRQ_GPO3 203 /* Group 26 */ -#define IT83XX_IRQ_GPP0 208 -#define IT83XX_IRQ_GPP1 209 -#define IT83XX_IRQ_GPP2 210 -#define IT83XX_IRQ_GPP3 211 -#define IT83XX_IRQ_GPP4 212 -#define IT83XX_IRQ_GPP5 213 -#define IT83XX_IRQ_GPP6 214 +#define IT83XX_IRQ_GPP0 208 +#define IT83XX_IRQ_GPP1 209 +#define IT83XX_IRQ_GPP2 210 +#define IT83XX_IRQ_GPP3 211 +#define IT83XX_IRQ_GPP4 212 +#define IT83XX_IRQ_GPP5 213 +#define IT83XX_IRQ_GPP6 214 /* Group 27 */ -#define IT83XX_IRQ_GPQ0 216 -#define IT83XX_IRQ_GPQ1 217 -#define IT83XX_IRQ_GPQ2 218 -#define IT83XX_IRQ_GPQ3 219 -#define IT83XX_IRQ_GPQ4 220 -#define IT83XX_IRQ_GPQ5 221 +#define IT83XX_IRQ_GPQ0 216 +#define IT83XX_IRQ_GPQ1 217 +#define IT83XX_IRQ_GPQ2 218 +#define IT83XX_IRQ_GPQ3 219 +#define IT83XX_IRQ_GPQ4 220 +#define IT83XX_IRQ_GPQ5 221 /* Group 28 */ -#define IT83XX_IRQ_GPR0 224 -#define IT83XX_IRQ_GPR1 225 -#define IT83XX_IRQ_GPR2 226 -#define IT83XX_IRQ_GPR3 227 -#define IT83XX_IRQ_GPR4 228 -#define IT83XX_IRQ_GPR5 229 - -#define IT83XX_IRQ_COUNT 230 +#define IT83XX_IRQ_GPR0 224 +#define IT83XX_IRQ_GPR1 225 +#define IT83XX_IRQ_GPR2 226 +#define IT83XX_IRQ_GPR3 227 +#define IT83XX_IRQ_GPR4 228 +#define IT83XX_IRQ_GPR5 229 + +#define IT83XX_IRQ_COUNT 230 #endif /* !defined(CHIP_FAMILY_IT8320) */ /* IRQ dispatching to CPU INT vectors */ -#define IT83XX_CPU_INT_IRQ_1 2 -#define IT83XX_CPU_INT_IRQ_2 5 -#define IT83XX_CPU_INT_IRQ_3 4 -#define IT83XX_CPU_INT_IRQ_4 6 -#define IT83XX_CPU_INT_IRQ_5 2 -#define IT83XX_CPU_INT_IRQ_6 2 -#define IT83XX_CPU_INT_IRQ_7 4 -#define IT83XX_CPU_INT_IRQ_8 7 -#define IT83XX_CPU_INT_IRQ_9 6 -#define IT83XX_CPU_INT_IRQ_10 6 -#define IT83XX_CPU_INT_IRQ_11 5 -#define IT83XX_CPU_INT_IRQ_12 2 -#define IT83XX_CPU_INT_IRQ_13 2 -#define IT83XX_CPU_INT_IRQ_14 2 -#define IT83XX_CPU_INT_IRQ_15 8 -#define IT83XX_CPU_INT_IRQ_16 6 -#define IT83XX_CPU_INT_IRQ_17 2 -#define IT83XX_CPU_INT_IRQ_18 8 -#define IT83XX_CPU_INT_IRQ_19 8 -#define IT83XX_CPU_INT_IRQ_20 8 -#define IT83XX_CPU_INT_IRQ_21 2 -#define IT83XX_CPU_INT_IRQ_22 12 -#define IT83XX_CPU_INT_IRQ_23 12 -#define IT83XX_CPU_INT_IRQ_24 5 -#define IT83XX_CPU_INT_IRQ_25 4 -#define IT83XX_CPU_INT_IRQ_26 4 -#define IT83XX_CPU_INT_IRQ_27 4 -#define IT83XX_CPU_INT_IRQ_28 11 -#define IT83XX_CPU_INT_IRQ_29 11 -#define IT83XX_CPU_INT_IRQ_30 3 -#define IT83XX_CPU_INT_IRQ_31 2 -#define IT83XX_CPU_INT_IRQ_32 11 -#define IT83XX_CPU_INT_IRQ_33 11 -#define IT83XX_CPU_INT_IRQ_34 11 -#define IT83XX_CPU_INT_IRQ_35 11 -#define IT83XX_CPU_INT_IRQ_36 8 -#define IT83XX_CPU_INT_IRQ_37 9 -#define IT83XX_CPU_INT_IRQ_38 9 -#define IT83XX_CPU_INT_IRQ_39 9 -#define IT83XX_CPU_INT_IRQ_40 2 -#define IT83XX_CPU_INT_IRQ_41 2 -#define IT83XX_CPU_INT_IRQ_42 2 -#define IT83XX_CPU_INT_IRQ_43 2 -#define IT83XX_CPU_INT_IRQ_44 2 -#define IT83XX_CPU_INT_IRQ_45 2 -#define IT83XX_CPU_INT_IRQ_46 2 -#define IT83XX_CPU_INT_IRQ_47 2 -#define IT83XX_CPU_INT_IRQ_48 2 -#define IT83XX_CPU_INT_IRQ_49 2 -#define IT83XX_CPU_INT_IRQ_50 2 -#define IT83XX_CPU_INT_IRQ_51 2 -#define IT83XX_CPU_INT_IRQ_52 2 -#define IT83XX_CPU_INT_IRQ_53 2 -#define IT83XX_CPU_INT_IRQ_54 2 -#define IT83XX_CPU_INT_IRQ_55 2 -#define IT83XX_CPU_INT_IRQ_56 10 -#define IT83XX_CPU_INT_IRQ_57 10 -#define IT83XX_CPU_INT_IRQ_58 3 -#define IT83XX_CPU_INT_IRQ_59 12 -#define IT83XX_CPU_INT_IRQ_60 3 -#define IT83XX_CPU_INT_IRQ_61 3 -#define IT83XX_CPU_INT_IRQ_62 3 -#define IT83XX_CPU_INT_IRQ_63 3 -#define IT83XX_CPU_INT_IRQ_64 4 -#define IT83XX_CPU_INT_IRQ_65 4 -#define IT83XX_CPU_INT_IRQ_66 4 -#define IT83XX_CPU_INT_IRQ_67 4 -#define IT83XX_CPU_INT_IRQ_68 4 -#define IT83XX_CPU_INT_IRQ_69 4 -#define IT83XX_CPU_INT_IRQ_71 12 -#define IT83XX_CPU_INT_IRQ_72 2 -#define IT83XX_CPU_INT_IRQ_73 2 -#define IT83XX_CPU_INT_IRQ_74 2 -#define IT83XX_CPU_INT_IRQ_75 2 -#define IT83XX_CPU_INT_IRQ_76 2 -#define IT83XX_CPU_INT_IRQ_77 2 -#define IT83XX_CPU_INT_IRQ_78 2 -#define IT83XX_CPU_INT_IRQ_79 2 -#define IT83XX_CPU_INT_IRQ_80 3 -#define IT83XX_CPU_INT_IRQ_81 6 -#define IT83XX_CPU_INT_IRQ_82 12 -#define IT83XX_CPU_INT_IRQ_83 12 -#define IT83XX_CPU_INT_IRQ_84 5 -#define IT83XX_CPU_INT_IRQ_85 2 -#define IT83XX_CPU_INT_IRQ_86 2 -#define IT83XX_CPU_INT_IRQ_87 2 -#define IT83XX_CPU_INT_IRQ_88 2 -#define IT83XX_CPU_INT_IRQ_89 2 -#define IT83XX_CPU_INT_IRQ_90 2 -#define IT83XX_CPU_INT_IRQ_91 2 -#define IT83XX_CPU_INT_IRQ_92 2 -#define IT83XX_CPU_INT_IRQ_93 2 -#define IT83XX_CPU_INT_IRQ_94 2 -#define IT83XX_CPU_INT_IRQ_95 2 -#define IT83XX_CPU_INT_IRQ_96 2 -#define IT83XX_CPU_INT_IRQ_97 2 -#define IT83XX_CPU_INT_IRQ_98 2 -#define IT83XX_CPU_INT_IRQ_99 2 -#define IT83XX_CPU_INT_IRQ_100 2 -#define IT83XX_CPU_INT_IRQ_101 2 -#define IT83XX_CPU_INT_IRQ_102 2 -#define IT83XX_CPU_INT_IRQ_103 2 -#define IT83XX_CPU_INT_IRQ_104 2 -#define IT83XX_CPU_INT_IRQ_105 2 -#define IT83XX_CPU_INT_IRQ_106 2 -#define IT83XX_CPU_INT_IRQ_107 2 -#define IT83XX_CPU_INT_IRQ_108 2 -#define IT83XX_CPU_INT_IRQ_109 2 -#define IT83XX_CPU_INT_IRQ_110 2 -#define IT83XX_CPU_INT_IRQ_111 2 -#define IT83XX_CPU_INT_IRQ_112 2 -#define IT83XX_CPU_INT_IRQ_113 2 -#define IT83XX_CPU_INT_IRQ_114 2 -#define IT83XX_CPU_INT_IRQ_115 2 -#define IT83XX_CPU_INT_IRQ_116 2 -#define IT83XX_CPU_INT_IRQ_117 2 -#define IT83XX_CPU_INT_IRQ_118 2 -#define IT83XX_CPU_INT_IRQ_119 2 -#define IT83XX_CPU_INT_IRQ_120 2 -#define IT83XX_CPU_INT_IRQ_121 2 -#define IT83XX_CPU_INT_IRQ_122 2 -#define IT83XX_CPU_INT_IRQ_123 2 -#define IT83XX_CPU_INT_IRQ_124 2 -#define IT83XX_CPU_INT_IRQ_125 2 -#define IT83XX_CPU_INT_IRQ_126 2 -#define IT83XX_CPU_INT_IRQ_127 2 -#define IT83XX_CPU_INT_IRQ_128 2 -#define IT83XX_CPU_INT_IRQ_129 2 -#define IT83XX_CPU_INT_IRQ_130 2 -#define IT83XX_CPU_INT_IRQ_131 2 -#define IT83XX_CPU_INT_IRQ_132 2 -#define IT83XX_CPU_INT_IRQ_133 2 -#define IT83XX_CPU_INT_IRQ_134 2 -#define IT83XX_CPU_INT_IRQ_135 2 -#define IT83XX_CPU_INT_IRQ_136 2 -#define IT83XX_CPU_INT_IRQ_137 2 -#define IT83XX_CPU_INT_IRQ_138 2 -#define IT83XX_CPU_INT_IRQ_139 2 -#define IT83XX_CPU_INT_IRQ_140 2 -#define IT83XX_CPU_INT_IRQ_141 2 -#define IT83XX_CPU_INT_IRQ_142 2 -#define IT83XX_CPU_INT_IRQ_143 2 -#define IT83XX_CPU_INT_IRQ_144 2 -#define IT83XX_CPU_INT_IRQ_145 2 -#define IT83XX_CPU_INT_IRQ_146 2 -#define IT83XX_CPU_INT_IRQ_147 2 -#define IT83XX_CPU_INT_IRQ_149 4 -#define IT83XX_CPU_INT_IRQ_150 4 -#define IT83XX_CPU_INT_IRQ_151 7 -#define IT83XX_CPU_INT_IRQ_152 6 -#define IT83XX_CPU_INT_IRQ_153 6 -#define IT83XX_CPU_INT_IRQ_154 12 -#define IT83XX_CPU_INT_IRQ_155 3 -#define IT83XX_CPU_INT_IRQ_156 3 -#define IT83XX_CPU_INT_IRQ_157 3 -#define IT83XX_CPU_INT_IRQ_158 3 -#define IT83XX_CPU_INT_IRQ_159 3 -#define IT83XX_CPU_INT_IRQ_160 12 -#define IT83XX_CPU_INT_IRQ_161 12 -#define IT83XX_CPU_INT_IRQ_162 12 -#define IT83XX_CPU_INT_IRQ_163 12 -#define IT83XX_CPU_INT_IRQ_164 12 -#define IT83XX_CPU_INT_IRQ_165 12 -#define IT83XX_CPU_INT_IRQ_166 12 -#define IT83XX_CPU_INT_IRQ_167 12 -#define IT83XX_CPU_INT_IRQ_168 2 -#define IT83XX_CPU_INT_IRQ_169 2 +#define IT83XX_CPU_INT_IRQ_1 2 +#define IT83XX_CPU_INT_IRQ_2 5 +#define IT83XX_CPU_INT_IRQ_3 4 +#define IT83XX_CPU_INT_IRQ_4 6 +#define IT83XX_CPU_INT_IRQ_5 2 +#define IT83XX_CPU_INT_IRQ_6 2 +#define IT83XX_CPU_INT_IRQ_7 4 +#define IT83XX_CPU_INT_IRQ_8 7 +#define IT83XX_CPU_INT_IRQ_9 6 +#define IT83XX_CPU_INT_IRQ_10 6 +#define IT83XX_CPU_INT_IRQ_11 5 +#define IT83XX_CPU_INT_IRQ_12 2 +#define IT83XX_CPU_INT_IRQ_13 2 +#define IT83XX_CPU_INT_IRQ_14 2 +#define IT83XX_CPU_INT_IRQ_15 8 +#define IT83XX_CPU_INT_IRQ_16 6 +#define IT83XX_CPU_INT_IRQ_17 2 +#define IT83XX_CPU_INT_IRQ_18 8 +#define IT83XX_CPU_INT_IRQ_19 8 +#define IT83XX_CPU_INT_IRQ_20 8 +#define IT83XX_CPU_INT_IRQ_21 2 +#define IT83XX_CPU_INT_IRQ_22 12 +#define IT83XX_CPU_INT_IRQ_23 12 +#define IT83XX_CPU_INT_IRQ_24 5 +#define IT83XX_CPU_INT_IRQ_25 4 +#define IT83XX_CPU_INT_IRQ_26 4 +#define IT83XX_CPU_INT_IRQ_27 4 +#define IT83XX_CPU_INT_IRQ_28 11 +#define IT83XX_CPU_INT_IRQ_29 11 +#define IT83XX_CPU_INT_IRQ_30 3 +#define IT83XX_CPU_INT_IRQ_31 2 +#define IT83XX_CPU_INT_IRQ_32 11 +#define IT83XX_CPU_INT_IRQ_33 11 +#define IT83XX_CPU_INT_IRQ_34 11 +#define IT83XX_CPU_INT_IRQ_35 11 +#define IT83XX_CPU_INT_IRQ_36 8 +#define IT83XX_CPU_INT_IRQ_37 9 +#define IT83XX_CPU_INT_IRQ_38 9 +#define IT83XX_CPU_INT_IRQ_39 9 +#define IT83XX_CPU_INT_IRQ_40 2 +#define IT83XX_CPU_INT_IRQ_41 2 +#define IT83XX_CPU_INT_IRQ_42 2 +#define IT83XX_CPU_INT_IRQ_43 2 +#define IT83XX_CPU_INT_IRQ_44 2 +#define IT83XX_CPU_INT_IRQ_45 2 +#define IT83XX_CPU_INT_IRQ_46 2 +#define IT83XX_CPU_INT_IRQ_47 2 +#define IT83XX_CPU_INT_IRQ_48 2 +#define IT83XX_CPU_INT_IRQ_49 2 +#define IT83XX_CPU_INT_IRQ_50 2 +#define IT83XX_CPU_INT_IRQ_51 2 +#define IT83XX_CPU_INT_IRQ_52 2 +#define IT83XX_CPU_INT_IRQ_53 2 +#define IT83XX_CPU_INT_IRQ_54 2 +#define IT83XX_CPU_INT_IRQ_55 2 +#define IT83XX_CPU_INT_IRQ_56 10 +#define IT83XX_CPU_INT_IRQ_57 10 +#define IT83XX_CPU_INT_IRQ_58 3 +#define IT83XX_CPU_INT_IRQ_59 12 +#define IT83XX_CPU_INT_IRQ_60 3 +#define IT83XX_CPU_INT_IRQ_61 3 +#define IT83XX_CPU_INT_IRQ_62 3 +#define IT83XX_CPU_INT_IRQ_63 3 +#define IT83XX_CPU_INT_IRQ_64 4 +#define IT83XX_CPU_INT_IRQ_65 4 +#define IT83XX_CPU_INT_IRQ_66 4 +#define IT83XX_CPU_INT_IRQ_67 4 +#define IT83XX_CPU_INT_IRQ_68 4 +#define IT83XX_CPU_INT_IRQ_69 4 +#define IT83XX_CPU_INT_IRQ_71 12 +#define IT83XX_CPU_INT_IRQ_72 2 +#define IT83XX_CPU_INT_IRQ_73 2 +#define IT83XX_CPU_INT_IRQ_74 2 +#define IT83XX_CPU_INT_IRQ_75 2 +#define IT83XX_CPU_INT_IRQ_76 2 +#define IT83XX_CPU_INT_IRQ_77 2 +#define IT83XX_CPU_INT_IRQ_78 2 +#define IT83XX_CPU_INT_IRQ_79 2 +#define IT83XX_CPU_INT_IRQ_80 3 +#define IT83XX_CPU_INT_IRQ_81 6 +#define IT83XX_CPU_INT_IRQ_82 12 +#define IT83XX_CPU_INT_IRQ_83 12 +#define IT83XX_CPU_INT_IRQ_84 5 +#define IT83XX_CPU_INT_IRQ_85 2 +#define IT83XX_CPU_INT_IRQ_86 2 +#define IT83XX_CPU_INT_IRQ_87 2 +#define IT83XX_CPU_INT_IRQ_88 2 +#define IT83XX_CPU_INT_IRQ_89 2 +#define IT83XX_CPU_INT_IRQ_90 2 +#define IT83XX_CPU_INT_IRQ_91 2 +#define IT83XX_CPU_INT_IRQ_92 2 +#define IT83XX_CPU_INT_IRQ_93 2 +#define IT83XX_CPU_INT_IRQ_94 2 +#define IT83XX_CPU_INT_IRQ_95 2 +#define IT83XX_CPU_INT_IRQ_96 2 +#define IT83XX_CPU_INT_IRQ_97 2 +#define IT83XX_CPU_INT_IRQ_98 2 +#define IT83XX_CPU_INT_IRQ_99 2 +#define IT83XX_CPU_INT_IRQ_100 2 +#define IT83XX_CPU_INT_IRQ_101 2 +#define IT83XX_CPU_INT_IRQ_102 2 +#define IT83XX_CPU_INT_IRQ_103 2 +#define IT83XX_CPU_INT_IRQ_104 2 +#define IT83XX_CPU_INT_IRQ_105 2 +#define IT83XX_CPU_INT_IRQ_106 2 +#define IT83XX_CPU_INT_IRQ_107 2 +#define IT83XX_CPU_INT_IRQ_108 2 +#define IT83XX_CPU_INT_IRQ_109 2 +#define IT83XX_CPU_INT_IRQ_110 2 +#define IT83XX_CPU_INT_IRQ_111 2 +#define IT83XX_CPU_INT_IRQ_112 2 +#define IT83XX_CPU_INT_IRQ_113 2 +#define IT83XX_CPU_INT_IRQ_114 2 +#define IT83XX_CPU_INT_IRQ_115 2 +#define IT83XX_CPU_INT_IRQ_116 2 +#define IT83XX_CPU_INT_IRQ_117 2 +#define IT83XX_CPU_INT_IRQ_118 2 +#define IT83XX_CPU_INT_IRQ_119 2 +#define IT83XX_CPU_INT_IRQ_120 2 +#define IT83XX_CPU_INT_IRQ_121 2 +#define IT83XX_CPU_INT_IRQ_122 2 +#define IT83XX_CPU_INT_IRQ_123 2 +#define IT83XX_CPU_INT_IRQ_124 2 +#define IT83XX_CPU_INT_IRQ_125 2 +#define IT83XX_CPU_INT_IRQ_126 2 +#define IT83XX_CPU_INT_IRQ_127 2 +#define IT83XX_CPU_INT_IRQ_128 2 +#define IT83XX_CPU_INT_IRQ_129 2 +#define IT83XX_CPU_INT_IRQ_130 2 +#define IT83XX_CPU_INT_IRQ_131 2 +#define IT83XX_CPU_INT_IRQ_132 2 +#define IT83XX_CPU_INT_IRQ_133 2 +#define IT83XX_CPU_INT_IRQ_134 2 +#define IT83XX_CPU_INT_IRQ_135 2 +#define IT83XX_CPU_INT_IRQ_136 2 +#define IT83XX_CPU_INT_IRQ_137 2 +#define IT83XX_CPU_INT_IRQ_138 2 +#define IT83XX_CPU_INT_IRQ_139 2 +#define IT83XX_CPU_INT_IRQ_140 2 +#define IT83XX_CPU_INT_IRQ_141 2 +#define IT83XX_CPU_INT_IRQ_142 2 +#define IT83XX_CPU_INT_IRQ_143 2 +#define IT83XX_CPU_INT_IRQ_144 2 +#define IT83XX_CPU_INT_IRQ_145 2 +#define IT83XX_CPU_INT_IRQ_146 2 +#define IT83XX_CPU_INT_IRQ_147 2 +#define IT83XX_CPU_INT_IRQ_149 4 +#define IT83XX_CPU_INT_IRQ_150 4 +#define IT83XX_CPU_INT_IRQ_151 7 +#define IT83XX_CPU_INT_IRQ_152 6 +#define IT83XX_CPU_INT_IRQ_153 6 +#define IT83XX_CPU_INT_IRQ_154 12 +#define IT83XX_CPU_INT_IRQ_155 3 +#define IT83XX_CPU_INT_IRQ_156 3 +#define IT83XX_CPU_INT_IRQ_157 3 +#define IT83XX_CPU_INT_IRQ_158 3 +#define IT83XX_CPU_INT_IRQ_159 3 +#define IT83XX_CPU_INT_IRQ_160 12 +#define IT83XX_CPU_INT_IRQ_161 12 +#define IT83XX_CPU_INT_IRQ_162 12 +#define IT83XX_CPU_INT_IRQ_163 12 +#define IT83XX_CPU_INT_IRQ_164 12 +#define IT83XX_CPU_INT_IRQ_165 12 +#define IT83XX_CPU_INT_IRQ_166 12 +#define IT83XX_CPU_INT_IRQ_167 12 +#define IT83XX_CPU_INT_IRQ_168 2 +#define IT83XX_CPU_INT_IRQ_169 2 #if defined(CHIP_FAMILY_IT8320) -#define IT83XX_CPU_INT_IRQ_170 2 -#define IT83XX_CPU_INT_IRQ_171 2 -#define IT83XX_CPU_INT_IRQ_172 2 -#define IT83XX_CPU_INT_IRQ_173 2 -#define IT83XX_CPU_INT_IRQ_174 2 -#define IT83XX_CPU_INT_IRQ_175 2 +#define IT83XX_CPU_INT_IRQ_170 2 +#define IT83XX_CPU_INT_IRQ_171 2 +#define IT83XX_CPU_INT_IRQ_172 2 +#define IT83XX_CPU_INT_IRQ_173 2 +#define IT83XX_CPU_INT_IRQ_174 2 +#define IT83XX_CPU_INT_IRQ_175 2 #elif defined(CHIP_FAMILY_IT8XXX1) || defined(CHIP_FAMILY_IT8XXX2) -#define IT83XX_CPU_INT_IRQ_170 12 -#define IT83XX_CPU_INT_IRQ_171 12 -#define IT83XX_CPU_INT_IRQ_172 12 -#define IT83XX_CPU_INT_IRQ_173 12 -#define IT83XX_CPU_INT_IRQ_174 12 -#define IT83XX_CPU_INT_IRQ_175 12 +#define IT83XX_CPU_INT_IRQ_170 12 +#define IT83XX_CPU_INT_IRQ_171 12 +#define IT83XX_CPU_INT_IRQ_172 12 +#define IT83XX_CPU_INT_IRQ_173 12 +#define IT83XX_CPU_INT_IRQ_174 12 +#define IT83XX_CPU_INT_IRQ_175 12 #endif -#define IT83XX_CPU_INT_IRQ_176 2 -#define IT83XX_CPU_INT_IRQ_177 2 -#define IT83XX_CPU_INT_IRQ_178 2 -#define IT83XX_CPU_INT_IRQ_179 2 -#define IT83XX_CPU_INT_IRQ_180 2 -#define IT83XX_CPU_INT_IRQ_181 2 -#define IT83XX_CPU_INT_IRQ_182 2 -#define IT83XX_CPU_INT_IRQ_183 2 -#define IT83XX_CPU_INT_IRQ_184 2 -#define IT83XX_CPU_INT_IRQ_185 2 -#define IT83XX_CPU_INT_IRQ_191 2 -#define IT83XX_CPU_INT_IRQ_192 2 -#define IT83XX_CPU_INT_IRQ_193 2 -#define IT83XX_CPU_INT_IRQ_194 2 -#define IT83XX_CPU_INT_IRQ_195 2 -#define IT83XX_CPU_INT_IRQ_196 2 -#define IT83XX_CPU_INT_IRQ_197 2 -#define IT83XX_CPU_INT_IRQ_199 2 -#define IT83XX_CPU_INT_IRQ_200 2 -#define IT83XX_CPU_INT_IRQ_201 2 -#define IT83XX_CPU_INT_IRQ_202 2 -#define IT83XX_CPU_INT_IRQ_203 2 -#define IT83XX_CPU_INT_IRQ_208 2 -#define IT83XX_CPU_INT_IRQ_209 2 -#define IT83XX_CPU_INT_IRQ_210 2 -#define IT83XX_CPU_INT_IRQ_211 2 -#define IT83XX_CPU_INT_IRQ_212 2 -#define IT83XX_CPU_INT_IRQ_213 2 -#define IT83XX_CPU_INT_IRQ_214 2 -#define IT83XX_CPU_INT_IRQ_216 2 -#define IT83XX_CPU_INT_IRQ_217 2 -#define IT83XX_CPU_INT_IRQ_218 2 -#define IT83XX_CPU_INT_IRQ_219 2 -#define IT83XX_CPU_INT_IRQ_220 2 -#define IT83XX_CPU_INT_IRQ_221 2 -#define IT83XX_CPU_INT_IRQ_224 2 -#define IT83XX_CPU_INT_IRQ_225 2 -#define IT83XX_CPU_INT_IRQ_226 2 -#define IT83XX_CPU_INT_IRQ_227 2 -#define IT83XX_CPU_INT_IRQ_228 2 -#define IT83XX_CPU_INT_IRQ_229 2 +#define IT83XX_CPU_INT_IRQ_176 2 +#define IT83XX_CPU_INT_IRQ_177 2 +#define IT83XX_CPU_INT_IRQ_178 2 +#define IT83XX_CPU_INT_IRQ_179 2 +#define IT83XX_CPU_INT_IRQ_180 2 +#define IT83XX_CPU_INT_IRQ_181 2 +#define IT83XX_CPU_INT_IRQ_182 2 +#define IT83XX_CPU_INT_IRQ_183 2 +#define IT83XX_CPU_INT_IRQ_184 2 +#define IT83XX_CPU_INT_IRQ_185 2 +#define IT83XX_CPU_INT_IRQ_191 2 +#define IT83XX_CPU_INT_IRQ_192 2 +#define IT83XX_CPU_INT_IRQ_193 2 +#define IT83XX_CPU_INT_IRQ_194 2 +#define IT83XX_CPU_INT_IRQ_195 2 +#define IT83XX_CPU_INT_IRQ_196 2 +#define IT83XX_CPU_INT_IRQ_197 2 +#define IT83XX_CPU_INT_IRQ_199 2 +#define IT83XX_CPU_INT_IRQ_200 2 +#define IT83XX_CPU_INT_IRQ_201 2 +#define IT83XX_CPU_INT_IRQ_202 2 +#define IT83XX_CPU_INT_IRQ_203 2 +#define IT83XX_CPU_INT_IRQ_208 2 +#define IT83XX_CPU_INT_IRQ_209 2 +#define IT83XX_CPU_INT_IRQ_210 2 +#define IT83XX_CPU_INT_IRQ_211 2 +#define IT83XX_CPU_INT_IRQ_212 2 +#define IT83XX_CPU_INT_IRQ_213 2 +#define IT83XX_CPU_INT_IRQ_214 2 +#define IT83XX_CPU_INT_IRQ_216 2 +#define IT83XX_CPU_INT_IRQ_217 2 +#define IT83XX_CPU_INT_IRQ_218 2 +#define IT83XX_CPU_INT_IRQ_219 2 +#define IT83XX_CPU_INT_IRQ_220 2 +#define IT83XX_CPU_INT_IRQ_221 2 +#define IT83XX_CPU_INT_IRQ_224 2 +#define IT83XX_CPU_INT_IRQ_225 2 +#define IT83XX_CPU_INT_IRQ_226 2 +#define IT83XX_CPU_INT_IRQ_227 2 +#define IT83XX_CPU_INT_IRQ_228 2 +#define IT83XX_CPU_INT_IRQ_229 2 /* "Fake" IRQ to declare in readable fashion all WKO IRQ routed to INT#2 */ -#define CPU_INT_2_ALL_GPIOS 255 -#define IT83XX_CPU_INT_IRQ_255 2 +#define CPU_INT_2_ALL_GPIOS 255 +#define IT83XX_CPU_INT_IRQ_255 2 -#define CPU_INT_GROUP_5 254 -#define IT83XX_CPU_INT_IRQ_254 5 +#define CPU_INT_GROUP_5 254 +#define IT83XX_CPU_INT_IRQ_254 5 -#define CPU_INT_GROUP_4 252 -#define IT83XX_CPU_INT_IRQ_252 4 +#define CPU_INT_GROUP_4 252 +#define IT83XX_CPU_INT_IRQ_252 4 -#define CPU_INT_GROUP_12 253 -#define IT83XX_CPU_INT_IRQ_253 12 +#define CPU_INT_GROUP_12 253 +#define IT83XX_CPU_INT_IRQ_253 12 -#define CPU_INT_GROUP_3 251 -#define IT83XX_CPU_INT_IRQ_251 3 +#define CPU_INT_GROUP_3 251 +#define IT83XX_CPU_INT_IRQ_251 3 -#define CPU_INT_GROUP_6 250 -#define IT83XX_CPU_INT_IRQ_250 6 +#define CPU_INT_GROUP_6 250 +#define IT83XX_CPU_INT_IRQ_250 6 -#define CPU_INT_GROUP_9 249 -#define IT83XX_CPU_INT_IRQ_249 9 +#define CPU_INT_GROUP_9 249 +#define IT83XX_CPU_INT_IRQ_249 9 -#define CPU_INT_GROUP_7 248 -#define IT83XX_CPU_INT_IRQ_248 7 +#define CPU_INT_GROUP_7 248 +#define IT83XX_CPU_INT_IRQ_248 7 #define CPU_INT(irq) CONCAT2(IT83XX_CPU_INT_IRQ_, irq) /* --- INTC --- */ -#define IT83XX_INTC_BASE CHIP_EC_INTC_BASE - -#define IT83XX_INTC_REG(n) REG8(IT83XX_INTC_BASE+(n)) - -#define IT83XX_INTC_AIVCT REG8(IT83XX_INTC_BASE+0x10) - -#define IT83XX_INTC_IER0 REG8(IT83XX_INTC_BASE+0x04) -#define IT83XX_INTC_IER1 REG8(IT83XX_INTC_BASE+0x05) -#define IT83XX_INTC_IER2 REG8(IT83XX_INTC_BASE+0x06) -#define IT83XX_INTC_IER3 REG8(IT83XX_INTC_BASE+0x07) -#define IT83XX_INTC_IER4 REG8(IT83XX_INTC_BASE+0x15) -#define IT83XX_INTC_IER5 REG8(IT83XX_INTC_BASE+0x19) -#define IT83XX_INTC_IER6 REG8(IT83XX_INTC_BASE+0x1d) -#define IT83XX_INTC_IER7 REG8(IT83XX_INTC_BASE+0x21) -#define IT83XX_INTC_IER8 REG8(IT83XX_INTC_BASE+0x25) -#define IT83XX_INTC_IER9 REG8(IT83XX_INTC_BASE+0x29) -#define IT83XX_INTC_IER10 REG8(IT83XX_INTC_BASE+0x2d) -#define IT83XX_INTC_IER11 REG8(IT83XX_INTC_BASE+0x31) -#define IT83XX_INTC_IER12 REG8(IT83XX_INTC_BASE+0x35) -#define IT83XX_INTC_IER13 REG8(IT83XX_INTC_BASE+0x39) -#define IT83XX_INTC_IER14 REG8(IT83XX_INTC_BASE+0x3d) -#define IT83XX_INTC_IER15 REG8(IT83XX_INTC_BASE+0x41) -#define IT83XX_INTC_IER16 REG8(IT83XX_INTC_BASE+0x45) -#define IT83XX_INTC_IER17 REG8(IT83XX_INTC_BASE+0x49) -#define IT83XX_INTC_IER18 REG8(IT83XX_INTC_BASE+0x4d) -#define IT83XX_INTC_IER19 REG8(IT83XX_INTC_BASE+0x51) -#define IT83XX_INTC_IER20 REG8(IT83XX_INTC_BASE+0x55) -#define IT83XX_INTC_IER21 REG8(IT83XX_INTC_BASE+0x59) -#define IT83XX_INTC_IER22 REG8(IT83XX_INTC_BASE+0x5d) -#define IT83XX_INTC_IER23 REG8(IT83XX_INTC_BASE+0x91) -#define IT83XX_INTC_IER24 REG8(IT83XX_INTC_BASE+0x95) -#define IT83XX_INTC_IER25 REG8(IT83XX_INTC_BASE+0x99) -#define IT83XX_INTC_IER26 REG8(IT83XX_INTC_BASE+0x9d) -#define IT83XX_INTC_IER27 REG8(IT83XX_INTC_BASE+0xa1) -#define IT83XX_INTC_IER28 REG8(IT83XX_INTC_BASE+0xa5) - -#define IT83XX_INTC_ISR0 REG8(IT83XX_INTC_BASE+0x00) -#define IT83XX_INTC_ISR1 REG8(IT83XX_INTC_BASE+0x01) -#define IT83XX_INTC_ISR2 REG8(IT83XX_INTC_BASE+0x02) -#define IT83XX_INTC_ISR3 REG8(IT83XX_INTC_BASE+0x03) -#define IT83XX_INTC_ISR4 REG8(IT83XX_INTC_BASE+0x14) -#define IT83XX_INTC_ISR5 REG8(IT83XX_INTC_BASE+0x18) -#define IT83XX_INTC_ISR6 REG8(IT83XX_INTC_BASE+0x1c) -#define IT83XX_INTC_ISR7 REG8(IT83XX_INTC_BASE+0x20) -#define IT83XX_INTC_ISR8 REG8(IT83XX_INTC_BASE+0x24) -#define IT83XX_INTC_ISR9 REG8(IT83XX_INTC_BASE+0x28) -#define IT83XX_INTC_ISR10 REG8(IT83XX_INTC_BASE+0x2c) -#define IT83XX_INTC_ISR11 REG8(IT83XX_INTC_BASE+0x30) -#define IT83XX_INTC_ISR12 REG8(IT83XX_INTC_BASE+0x34) -#define IT83XX_INTC_ISR13 REG8(IT83XX_INTC_BASE+0x38) -#define IT83XX_INTC_ISR14 REG8(IT83XX_INTC_BASE+0x3c) -#define IT83XX_INTC_ISR15 REG8(IT83XX_INTC_BASE+0x40) -#define IT83XX_INTC_ISR16 REG8(IT83XX_INTC_BASE+0x44) -#define IT83XX_INTC_ISR17 REG8(IT83XX_INTC_BASE+0x48) -#define IT83XX_INTC_ISR18 REG8(IT83XX_INTC_BASE+0x4c) -#define IT83XX_INTC_ISR19 REG8(IT83XX_INTC_BASE+0x50) -#define IT83XX_INTC_ISR20 REG8(IT83XX_INTC_BASE+0x54) -#define IT83XX_INTC_ISR21 REG8(IT83XX_INTC_BASE+0x58) -#define IT83XX_INTC_ISR22 REG8(IT83XX_INTC_BASE+0x5c) -#define IT83XX_INTC_ISR23 REG8(IT83XX_INTC_BASE+0x90) -#define IT83XX_INTC_ISR24 REG8(IT83XX_INTC_BASE+0x94) -#define IT83XX_INTC_ISR25 REG8(IT83XX_INTC_BASE+0x98) -#define IT83XX_INTC_ISR26 REG8(IT83XX_INTC_BASE+0x9c) -#define IT83XX_INTC_ISR27 REG8(IT83XX_INTC_BASE+0xa0) -#define IT83XX_INTC_ISR28 REG8(IT83XX_INTC_BASE+0xa4) - -#define IT83XX_INTC_IELMR10 REG8(IT83XX_INTC_BASE+0x2E) -#define IT83XX_INTC_IPOLR10 REG8(IT83XX_INTC_BASE+0x2F) -#define IT83XX_INTC_IELMR19 REG8(IT83XX_INTC_BASE+0x52) -#define IT83XX_INTC_IPOLR19 REG8(IT83XX_INTC_BASE+0x53) +#define IT83XX_INTC_BASE CHIP_EC_INTC_BASE + +#define IT83XX_INTC_REG(n) REG8(IT83XX_INTC_BASE + (n)) + +#define IT83XX_INTC_AIVCT REG8(IT83XX_INTC_BASE + 0x10) + +#define IT83XX_INTC_IER0 REG8(IT83XX_INTC_BASE + 0x04) +#define IT83XX_INTC_IER1 REG8(IT83XX_INTC_BASE + 0x05) +#define IT83XX_INTC_IER2 REG8(IT83XX_INTC_BASE + 0x06) +#define IT83XX_INTC_IER3 REG8(IT83XX_INTC_BASE + 0x07) +#define IT83XX_INTC_IER4 REG8(IT83XX_INTC_BASE + 0x15) +#define IT83XX_INTC_IER5 REG8(IT83XX_INTC_BASE + 0x19) +#define IT83XX_INTC_IER6 REG8(IT83XX_INTC_BASE + 0x1d) +#define IT83XX_INTC_IER7 REG8(IT83XX_INTC_BASE + 0x21) +#define IT83XX_INTC_IER8 REG8(IT83XX_INTC_BASE + 0x25) +#define IT83XX_INTC_IER9 REG8(IT83XX_INTC_BASE + 0x29) +#define IT83XX_INTC_IER10 REG8(IT83XX_INTC_BASE + 0x2d) +#define IT83XX_INTC_IER11 REG8(IT83XX_INTC_BASE + 0x31) +#define IT83XX_INTC_IER12 REG8(IT83XX_INTC_BASE + 0x35) +#define IT83XX_INTC_IER13 REG8(IT83XX_INTC_BASE + 0x39) +#define IT83XX_INTC_IER14 REG8(IT83XX_INTC_BASE + 0x3d) +#define IT83XX_INTC_IER15 REG8(IT83XX_INTC_BASE + 0x41) +#define IT83XX_INTC_IER16 REG8(IT83XX_INTC_BASE + 0x45) +#define IT83XX_INTC_IER17 REG8(IT83XX_INTC_BASE + 0x49) +#define IT83XX_INTC_IER18 REG8(IT83XX_INTC_BASE + 0x4d) +#define IT83XX_INTC_IER19 REG8(IT83XX_INTC_BASE + 0x51) +#define IT83XX_INTC_IER20 REG8(IT83XX_INTC_BASE + 0x55) +#define IT83XX_INTC_IER21 REG8(IT83XX_INTC_BASE + 0x59) +#define IT83XX_INTC_IER22 REG8(IT83XX_INTC_BASE + 0x5d) +#define IT83XX_INTC_IER23 REG8(IT83XX_INTC_BASE + 0x91) +#define IT83XX_INTC_IER24 REG8(IT83XX_INTC_BASE + 0x95) +#define IT83XX_INTC_IER25 REG8(IT83XX_INTC_BASE + 0x99) +#define IT83XX_INTC_IER26 REG8(IT83XX_INTC_BASE + 0x9d) +#define IT83XX_INTC_IER27 REG8(IT83XX_INTC_BASE + 0xa1) +#define IT83XX_INTC_IER28 REG8(IT83XX_INTC_BASE + 0xa5) + +#define IT83XX_INTC_ISR0 REG8(IT83XX_INTC_BASE + 0x00) +#define IT83XX_INTC_ISR1 REG8(IT83XX_INTC_BASE + 0x01) +#define IT83XX_INTC_ISR2 REG8(IT83XX_INTC_BASE + 0x02) +#define IT83XX_INTC_ISR3 REG8(IT83XX_INTC_BASE + 0x03) +#define IT83XX_INTC_ISR4 REG8(IT83XX_INTC_BASE + 0x14) +#define IT83XX_INTC_ISR5 REG8(IT83XX_INTC_BASE + 0x18) +#define IT83XX_INTC_ISR6 REG8(IT83XX_INTC_BASE + 0x1c) +#define IT83XX_INTC_ISR7 REG8(IT83XX_INTC_BASE + 0x20) +#define IT83XX_INTC_ISR8 REG8(IT83XX_INTC_BASE + 0x24) +#define IT83XX_INTC_ISR9 REG8(IT83XX_INTC_BASE + 0x28) +#define IT83XX_INTC_ISR10 REG8(IT83XX_INTC_BASE + 0x2c) +#define IT83XX_INTC_ISR11 REG8(IT83XX_INTC_BASE + 0x30) +#define IT83XX_INTC_ISR12 REG8(IT83XX_INTC_BASE + 0x34) +#define IT83XX_INTC_ISR13 REG8(IT83XX_INTC_BASE + 0x38) +#define IT83XX_INTC_ISR14 REG8(IT83XX_INTC_BASE + 0x3c) +#define IT83XX_INTC_ISR15 REG8(IT83XX_INTC_BASE + 0x40) +#define IT83XX_INTC_ISR16 REG8(IT83XX_INTC_BASE + 0x44) +#define IT83XX_INTC_ISR17 REG8(IT83XX_INTC_BASE + 0x48) +#define IT83XX_INTC_ISR18 REG8(IT83XX_INTC_BASE + 0x4c) +#define IT83XX_INTC_ISR19 REG8(IT83XX_INTC_BASE + 0x50) +#define IT83XX_INTC_ISR20 REG8(IT83XX_INTC_BASE + 0x54) +#define IT83XX_INTC_ISR21 REG8(IT83XX_INTC_BASE + 0x58) +#define IT83XX_INTC_ISR22 REG8(IT83XX_INTC_BASE + 0x5c) +#define IT83XX_INTC_ISR23 REG8(IT83XX_INTC_BASE + 0x90) +#define IT83XX_INTC_ISR24 REG8(IT83XX_INTC_BASE + 0x94) +#define IT83XX_INTC_ISR25 REG8(IT83XX_INTC_BASE + 0x98) +#define IT83XX_INTC_ISR26 REG8(IT83XX_INTC_BASE + 0x9c) +#define IT83XX_INTC_ISR27 REG8(IT83XX_INTC_BASE + 0xa0) +#define IT83XX_INTC_ISR28 REG8(IT83XX_INTC_BASE + 0xa4) + +#define IT83XX_INTC_IELMR10 REG8(IT83XX_INTC_BASE + 0x2E) +#define IT83XX_INTC_IPOLR10 REG8(IT83XX_INTC_BASE + 0x2F) +#define IT83XX_INTC_IELMR19 REG8(IT83XX_INTC_BASE + 0x52) +#define IT83XX_INTC_IPOLR19 REG8(IT83XX_INTC_BASE + 0x53) #define IT83XX_INTC_EXT_IER_OFF(n) (0x60 + (n)) -#define IT83XX_INTC_IVCT(i) REG8(IT83XX_INTC_BASE+0x80+(i)) +#define IT83XX_INTC_IVCT(i) REG8(IT83XX_INTC_BASE + 0x80 + (i)) /* --- EC Access to the Host Controlled Modules (EC2I Bridge) --- */ -#define IT83XX_EC2I_BASE 0x00F01200 +#define IT83XX_EC2I_BASE 0x00F01200 -#define IT83XX_EC2I_IHIOA REG8(IT83XX_EC2I_BASE+0x00) -#define IT83XX_EC2I_IHD REG8(IT83XX_EC2I_BASE+0x01) -#define IT83XX_EC2I_LSIOHA REG8(IT83XX_EC2I_BASE+0x02) -#define IT83XX_EC2I_SIOLV REG8(IT83XX_EC2I_BASE+0x03) -#define IT83XX_EC2I_IBMAE REG8(IT83XX_EC2I_BASE+0x04) -#define IT83XX_EC2I_IBCTL REG8(IT83XX_EC2I_BASE+0x05) +#define IT83XX_EC2I_IHIOA REG8(IT83XX_EC2I_BASE + 0x00) +#define IT83XX_EC2I_IHD REG8(IT83XX_EC2I_BASE + 0x01) +#define IT83XX_EC2I_LSIOHA REG8(IT83XX_EC2I_BASE + 0x02) +#define IT83XX_EC2I_SIOLV REG8(IT83XX_EC2I_BASE + 0x03) +#define IT83XX_EC2I_IBMAE REG8(IT83XX_EC2I_BASE + 0x04) +#define IT83XX_EC2I_IBCTL REG8(IT83XX_EC2I_BASE + 0x05) /* --- System Wake-UP Control (SWUC) --- */ -#define IT83XX_SWUC_BASE 0x00F01400 -#define IT83XX_SWUC_SWCTL1 REG8(IT83XX_SWUC_BASE+0x00) +#define IT83XX_SWUC_BASE 0x00F01400 +#define IT83XX_SWUC_SWCTL1 REG8(IT83XX_SWUC_BASE + 0x00) /* --- Wake-Up Control (WUC) --- */ -#define IT83XX_WUC_BASE 0x00F01B00 +#define IT83XX_WUC_BASE 0x00F01B00 -#define IT83XX_WUC_WUEMR1 (IT83XX_WUC_BASE+0x00) -#define IT83XX_WUC_WUEMR5 (IT83XX_WUC_BASE+0x0c) -#define IT83XX_WUC_WUESR1 (IT83XX_WUC_BASE+0x04) -#define IT83XX_WUC_WUESR5 (IT83XX_WUC_BASE+0x0d) -#define IT83XX_WUC_WUBEMR1 (IT83XX_WUC_BASE+0x3c) -#define IT83XX_WUC_WUBEMR5 (IT83XX_WUC_BASE+0x0f) +#define IT83XX_WUC_WUEMR1 (IT83XX_WUC_BASE + 0x00) +#define IT83XX_WUC_WUEMR5 (IT83XX_WUC_BASE + 0x0c) +#define IT83XX_WUC_WUESR1 (IT83XX_WUC_BASE + 0x04) +#define IT83XX_WUC_WUESR5 (IT83XX_WUC_BASE + 0x0d) +#define IT83XX_WUC_WUBEMR1 (IT83XX_WUC_BASE + 0x3c) +#define IT83XX_WUC_WUBEMR5 (IT83XX_WUC_BASE + 0x0f) -#define IT83XX_WUC_WUESR10 REG8(IT83XX_WUC_BASE+0x21) -#define IT83XX_WUC_WUESR11 REG8(IT83XX_WUC_BASE+0x25) +#define IT83XX_WUC_WUESR10 REG8(IT83XX_WUC_BASE + 0x21) +#define IT83XX_WUC_WUESR11 REG8(IT83XX_WUC_BASE + 0x25) -#define IT83XX_WUC_WUEMR3 REG8(IT83XX_WUC_BASE+0x02) -#define IT83XX_WUC_WUESR3 REG8(IT83XX_WUC_BASE+0x06) -#define IT83XX_WUC_WUENR3 REG8(IT83XX_WUC_BASE+0x0A) +#define IT83XX_WUC_WUEMR3 REG8(IT83XX_WUC_BASE + 0x02) +#define IT83XX_WUC_WUESR3 REG8(IT83XX_WUC_BASE + 0x06) +#define IT83XX_WUC_WUENR3 REG8(IT83XX_WUC_BASE + 0x0A) -#define IT83XX_WUC_WUEMR4 REG8(IT83XX_WUC_BASE+0x03) -#define IT83XX_WUC_WUESR4 REG8(IT83XX_WUC_BASE+0x07) -#define IT83XX_WUC_WUENR4 REG8(IT83XX_WUC_BASE+0x0B) +#define IT83XX_WUC_WUEMR4 REG8(IT83XX_WUC_BASE + 0x03) +#define IT83XX_WUC_WUESR4 REG8(IT83XX_WUC_BASE + 0x07) +#define IT83XX_WUC_WUENR4 REG8(IT83XX_WUC_BASE + 0x0B) /* --- UART --- */ #define IT83XX_UART0_BASE 0x00F02700 #define IT83XX_UART1_BASE 0x00F02800 -#define IT83XX_UART_BASE(n) CONCAT3(IT83XX_UART, n, _BASE) +#define IT83XX_UART_BASE(n) CONCAT3(IT83XX_UART, n, _BASE) #define IT83XX_UART_REG(n, offset) REG8(IT83XX_UART_BASE(n) + (offset)) -#define IT83XX_UART_DLL(n) IT83XX_UART_REG(n, 0x00) -#define IT83XX_UART_DLM(n) IT83XX_UART_REG(n, 0x01) -#define IT83XX_UART_RBR(n) IT83XX_UART_REG(n, 0x00) -#define IT83XX_UART_THR(n) IT83XX_UART_REG(n, 0x00) -#define IT83XX_UART_IER(n) IT83XX_UART_REG(n, 0x01) -#define IT83XX_UART_IIR(n) IT83XX_UART_REG(n, 0x02) -#define IT83XX_UART_FCR(n) IT83XX_UART_REG(n, 0x02) -#define IT83XX_UART_LCR(n) IT83XX_UART_REG(n, 0x03) -#define IT83XX_UART_MCR(n) IT83XX_UART_REG(n, 0x04) -#define IT83XX_UART_LSR(n) IT83XX_UART_REG(n, 0x05) -#define IT83XX_UART_MSR(n) IT83XX_UART_REG(n, 0x06) -#define IT83XX_UART_SCR(n) IT83XX_UART_REG(n, 0x07) -#define IT83XX_UART_ECSMPR(n) IT83XX_UART_REG(n, 0x08) -#define IT83XX_UART_CSSR(n) IT83XX_UART_REG(n, 0x09) +#define IT83XX_UART_DLL(n) IT83XX_UART_REG(n, 0x00) +#define IT83XX_UART_DLM(n) IT83XX_UART_REG(n, 0x01) +#define IT83XX_UART_RBR(n) IT83XX_UART_REG(n, 0x00) +#define IT83XX_UART_THR(n) IT83XX_UART_REG(n, 0x00) +#define IT83XX_UART_IER(n) IT83XX_UART_REG(n, 0x01) +#define IT83XX_UART_IIR(n) IT83XX_UART_REG(n, 0x02) +#define IT83XX_UART_FCR(n) IT83XX_UART_REG(n, 0x02) +#define IT83XX_UART_LCR(n) IT83XX_UART_REG(n, 0x03) +#define IT83XX_UART_MCR(n) IT83XX_UART_REG(n, 0x04) +#define IT83XX_UART_LSR(n) IT83XX_UART_REG(n, 0x05) +#define IT83XX_UART_MSR(n) IT83XX_UART_REG(n, 0x06) +#define IT83XX_UART_SCR(n) IT83XX_UART_REG(n, 0x07) +#define IT83XX_UART_ECSMPR(n) IT83XX_UART_REG(n, 0x08) +#define IT83XX_UART_CSSR(n) IT83XX_UART_REG(n, 0x09) /* --- GPIO --- */ -#define IT83XX_GPIO_BASE 0x00F01600 +#define IT83XX_GPIO_BASE 0x00F01600 #define IT83XX_GPIO2_BASE 0x00F03E00 -#define IT83XX_GPIO_GCR REG8(IT83XX_GPIO_BASE+0x00) -#define IT83XX_GPIO_GCR_LPC_RST_B7 0x1 -#define IT83XX_GPIO_GCR_LPC_RST_D2 0x2 +#define IT83XX_GPIO_GCR REG8(IT83XX_GPIO_BASE + 0x00) +#define IT83XX_GPIO_GCR_LPC_RST_B7 0x1 +#define IT83XX_GPIO_GCR_LPC_RST_D2 0x2 #define IT83XX_GPIO_GCR_LPC_RST_DISABLE 0x3 -#define IT83XX_GPIO_GCR_LPC_RST_POS 1 - -#define IT83XX_GPIO_GPDRA REG8(IT83XX_GPIO_BASE+0x01) -#define IT83XX_GPIO_GPDRB REG8(IT83XX_GPIO_BASE+0x02) -#define IT83XX_GPIO_GPDRC REG8(IT83XX_GPIO_BASE+0x03) -#define IT83XX_GPIO_GPDRE REG8(IT83XX_GPIO_BASE+0x05) -#define IT83XX_GPIO_GPDRF REG8(IT83XX_GPIO_BASE+0x06) -#define IT83XX_GPIO_GPDRH REG8(IT83XX_GPIO_BASE+0x08) - -#define IT83XX_GPIO_GPCRA0 REG8(IT83XX_GPIO_BASE+0x10) -#define IT83XX_GPIO_GPCRA1 REG8(IT83XX_GPIO_BASE+0x11) -#define IT83XX_GPIO_GPCRA2 REG8(IT83XX_GPIO_BASE+0x12) -#define IT83XX_GPIO_GPCRA3 REG8(IT83XX_GPIO_BASE+0x13) -#define IT83XX_GPIO_GPCRA4 REG8(IT83XX_GPIO_BASE+0x14) -#define IT83XX_GPIO_GPCRA5 REG8(IT83XX_GPIO_BASE+0x15) -#define IT83XX_GPIO_GPCRA6 REG8(IT83XX_GPIO_BASE+0x16) -#define IT83XX_GPIO_GPCRA7 REG8(IT83XX_GPIO_BASE+0x17) - -#define IT83XX_GPIO_GPCRB0 REG8(IT83XX_GPIO_BASE+0x18) -#define IT83XX_GPIO_GPCRB1 REG8(IT83XX_GPIO_BASE+0x19) -#define IT83XX_GPIO_GPCRB2 REG8(IT83XX_GPIO_BASE+0x1A) -#define IT83XX_GPIO_GPCRB3 REG8(IT83XX_GPIO_BASE+0x1B) -#define IT83XX_GPIO_GPCRB4 REG8(IT83XX_GPIO_BASE+0x1C) -#define IT83XX_GPIO_GPCRB5 REG8(IT83XX_GPIO_BASE+0x1D) -#define IT83XX_GPIO_GPCRB6 REG8(IT83XX_GPIO_BASE+0x1E) -#define IT83XX_GPIO_GPCRB7 REG8(IT83XX_GPIO_BASE+0x1F) - -#define IT83XX_GPIO_GPCRC0 REG8(IT83XX_GPIO_BASE+0x20) -#define IT83XX_GPIO_GPCRC1 REG8(IT83XX_GPIO_BASE+0x21) -#define IT83XX_GPIO_GPCRC2 REG8(IT83XX_GPIO_BASE+0x22) -#define IT83XX_GPIO_GPCRC3 REG8(IT83XX_GPIO_BASE+0x23) -#define IT83XX_GPIO_GPCRC4 REG8(IT83XX_GPIO_BASE+0x24) -#define IT83XX_GPIO_GPCRC5 REG8(IT83XX_GPIO_BASE+0x25) -#define IT83XX_GPIO_GPCRC6 REG8(IT83XX_GPIO_BASE+0x26) -#define IT83XX_GPIO_GPCRC7 REG8(IT83XX_GPIO_BASE+0x27) - -#define IT83XX_GPIO_GPCRE0 REG8(IT83XX_GPIO_BASE+0x30) -#define IT83XX_GPIO_GPCRE1 REG8(IT83XX_GPIO_BASE+0x31) -#define IT83XX_GPIO_GPCRE2 REG8(IT83XX_GPIO_BASE+0x32) -#define IT83XX_GPIO_GPCRE3 REG8(IT83XX_GPIO_BASE+0x33) -#define IT83XX_GPIO_GPCRE4 REG8(IT83XX_GPIO_BASE+0x34) -#define IT83XX_GPIO_GPCRE5 REG8(IT83XX_GPIO_BASE+0x35) -#define IT83XX_GPIO_GPCRE6 REG8(IT83XX_GPIO_BASE+0x36) -#define IT83XX_GPIO_GPCRE7 REG8(IT83XX_GPIO_BASE+0x37) - -#define IT83XX_GPIO_GPCRF0 REG8(IT83XX_GPIO_BASE+0x38) -#define IT83XX_GPIO_GPCRF1 REG8(IT83XX_GPIO_BASE+0x39) -#define IT83XX_GPIO_GPCRF2 REG8(IT83XX_GPIO_BASE+0x3A) -#define IT83XX_GPIO_GPCRF3 REG8(IT83XX_GPIO_BASE+0x3B) -#define IT83XX_GPIO_GPCRF4 REG8(IT83XX_GPIO_BASE+0x3C) -#define IT83XX_GPIO_GPCRF5 REG8(IT83XX_GPIO_BASE+0x3D) -#define IT83XX_GPIO_GPCRF6 REG8(IT83XX_GPIO_BASE+0x3E) -#define IT83XX_GPIO_GPCRF7 REG8(IT83XX_GPIO_BASE+0x3F) - -#define IT83XX_GPIO_GPCRH0 REG8(IT83XX_GPIO_BASE+0x48) -#define IT83XX_GPIO_GPCRH1 REG8(IT83XX_GPIO_BASE+0x49) -#define IT83XX_GPIO_GPCRH2 REG8(IT83XX_GPIO_BASE+0x4A) -#define IT83XX_GPIO_GPCRH3 REG8(IT83XX_GPIO_BASE+0x4B) -#define IT83XX_GPIO_GPCRH4 REG8(IT83XX_GPIO_BASE+0x4C) -#define IT83XX_GPIO_GPCRH5 REG8(IT83XX_GPIO_BASE+0x4D) -#define IT83XX_GPIO_GPCRH6 REG8(IT83XX_GPIO_BASE+0x4E) -#define IT83XX_GPIO_GPCRH7 REG8(IT83XX_GPIO_BASE+0x4F) - -#define IT83XX_GPIO_GPCRI0 REG8(IT83XX_GPIO_BASE+0x50) -#define IT83XX_GPIO_GPCRI1 REG8(IT83XX_GPIO_BASE+0x51) -#define IT83XX_GPIO_GPCRI2 REG8(IT83XX_GPIO_BASE+0x52) -#define IT83XX_GPIO_GPCRI3 REG8(IT83XX_GPIO_BASE+0x53) -#define IT83XX_GPIO_GPCRI4 REG8(IT83XX_GPIO_BASE+0x54) -#define IT83XX_GPIO_GPCRI5 REG8(IT83XX_GPIO_BASE+0x55) -#define IT83XX_GPIO_GPCRI6 REG8(IT83XX_GPIO_BASE+0x56) -#define IT83XX_GPIO_GPCRI7 REG8(IT83XX_GPIO_BASE+0x57) - -#define IT83XX_GPIO_GPCRM5 REG8(IT83XX_GPIO_BASE+0xA5) - -#define IT83XX_GPIO_GPDMRA REG8(IT83XX_GPIO_BASE+0x61) -#define IT83XX_GPIO_GPDMRB REG8(IT83XX_GPIO_BASE+0x62) -#define IT83XX_GPIO_GPDMRC REG8(IT83XX_GPIO_BASE+0x63) -#define IT83XX_GPIO_GPDMRE REG8(IT83XX_GPIO_BASE+0x65) -#define IT83XX_GPIO_GPDMRF REG8(IT83XX_GPIO_BASE+0x66) -#define IT83XX_GPIO_GPDMRH REG8(IT83XX_GPIO_BASE+0x68) - -#define IT83XX_GPIO_GPCRL0 REG8(IT83XX_GPIO_BASE+0x98) -#define IT83XX_GPIO_GPCRL1 REG8(IT83XX_GPIO_BASE+0x99) -#define IT83XX_GPIO_GPCRL2 REG8(IT83XX_GPIO_BASE+0x9A) -#define IT83XX_GPIO_GPCRL3 REG8(IT83XX_GPIO_BASE+0x9B) -#define IT83XX_GPIO_GPCRP0 REG8(IT83XX_GPIO2_BASE+0x18) -#define IT83XX_GPIO_GPCRP1 REG8(IT83XX_GPIO2_BASE+0x19) - -#define IT83XX_GPIO_GRC1 REG8(IT83XX_GPIO_BASE+0xF0) -#define IT83XX_GPIO_GRC2 REG8(IT83XX_GPIO_BASE+0xF1) -#define IT83XX_GPIO_GRC3 REG8(IT83XX_GPIO_BASE+0xF2) -#define IT83XX_GPIO_GRC4 REG8(IT83XX_GPIO_BASE+0xF3) -#define IT83XX_GPIO_GRC5 REG8(IT83XX_GPIO_BASE+0xF4) -#define IT83XX_GPIO_GRC6 REG8(IT83XX_GPIO_BASE+0xF5) -#define IT83XX_GPIO_GRC7 REG8(IT83XX_GPIO_BASE+0xF6) -#define IT83XX_GPIO_GRC8 REG8(IT83XX_GPIO_BASE+0xF7) -#define IT83XX_GPIO_GRC19 REG8(IT83XX_GPIO_BASE+0xE4) -#define IT83XX_GPIO_GRC20 REG8(IT83XX_GPIO_BASE+0xE5) -#define IT83XX_GPIO_GRC21 REG8(IT83XX_GPIO_BASE+0xE6) -#define IT83XX_GPIO_GRC22 REG8(IT83XX_GPIO_BASE+0xE7) -#define IT83XX_GPIO_GRC23 REG8(IT83XX_GPIO_BASE+0xE8) -#define IT83XX_GPIO_GRC24 REG8(IT83XX_GPIO_BASE+0xE9) -#define IT83XX_GPIO_GCR25 REG8(IT83XX_GPIO_BASE+0xD1) -#define IT83XX_GPIO_GCR26 REG8(IT83XX_GPIO_BASE+0xD2) -#define IT83XX_GPIO_GCR27 REG8(IT83XX_GPIO_BASE+0xD3) -#define IT83XX_GPIO_GCR28 REG8(IT83XX_GPIO_BASE+0xD4) -#define IT83XX_GPIO_GCR30 REG8(IT83XX_GPIO_BASE+0xED) -#define IT83XX_GPIO_GCR31 REG8(IT83XX_GPIO_BASE+0xD5) -#define IT83XX_GPIO_GCR32 REG8(IT83XX_GPIO_BASE+0xD6) -#define IT83XX_GPIO_GCR33 REG8(IT83XX_GPIO_BASE+0xD7) - -#define IT83XX_VBATPC_BGPOPSCR REG8(IT83XX_GPIO2_BASE+0xF0) -#define IT83XX_VBATPC_XLPIER REG8(IT83XX_GPIO2_BASE+0xF5) +#define IT83XX_GPIO_GCR_LPC_RST_POS 1 + +#define IT83XX_GPIO_GPDRA REG8(IT83XX_GPIO_BASE + 0x01) +#define IT83XX_GPIO_GPDRB REG8(IT83XX_GPIO_BASE + 0x02) +#define IT83XX_GPIO_GPDRC REG8(IT83XX_GPIO_BASE + 0x03) +#define IT83XX_GPIO_GPDRE REG8(IT83XX_GPIO_BASE + 0x05) +#define IT83XX_GPIO_GPDRF REG8(IT83XX_GPIO_BASE + 0x06) +#define IT83XX_GPIO_GPDRH REG8(IT83XX_GPIO_BASE + 0x08) + +#define IT83XX_GPIO_GPCRA0 REG8(IT83XX_GPIO_BASE + 0x10) +#define IT83XX_GPIO_GPCRA1 REG8(IT83XX_GPIO_BASE + 0x11) +#define IT83XX_GPIO_GPCRA2 REG8(IT83XX_GPIO_BASE + 0x12) +#define IT83XX_GPIO_GPCRA3 REG8(IT83XX_GPIO_BASE + 0x13) +#define IT83XX_GPIO_GPCRA4 REG8(IT83XX_GPIO_BASE + 0x14) +#define IT83XX_GPIO_GPCRA5 REG8(IT83XX_GPIO_BASE + 0x15) +#define IT83XX_GPIO_GPCRA6 REG8(IT83XX_GPIO_BASE + 0x16) +#define IT83XX_GPIO_GPCRA7 REG8(IT83XX_GPIO_BASE + 0x17) + +#define IT83XX_GPIO_GPCRB0 REG8(IT83XX_GPIO_BASE + 0x18) +#define IT83XX_GPIO_GPCRB1 REG8(IT83XX_GPIO_BASE + 0x19) +#define IT83XX_GPIO_GPCRB2 REG8(IT83XX_GPIO_BASE + 0x1A) +#define IT83XX_GPIO_GPCRB3 REG8(IT83XX_GPIO_BASE + 0x1B) +#define IT83XX_GPIO_GPCRB4 REG8(IT83XX_GPIO_BASE + 0x1C) +#define IT83XX_GPIO_GPCRB5 REG8(IT83XX_GPIO_BASE + 0x1D) +#define IT83XX_GPIO_GPCRB6 REG8(IT83XX_GPIO_BASE + 0x1E) +#define IT83XX_GPIO_GPCRB7 REG8(IT83XX_GPIO_BASE + 0x1F) + +#define IT83XX_GPIO_GPCRC0 REG8(IT83XX_GPIO_BASE + 0x20) +#define IT83XX_GPIO_GPCRC1 REG8(IT83XX_GPIO_BASE + 0x21) +#define IT83XX_GPIO_GPCRC2 REG8(IT83XX_GPIO_BASE + 0x22) +#define IT83XX_GPIO_GPCRC3 REG8(IT83XX_GPIO_BASE + 0x23) +#define IT83XX_GPIO_GPCRC4 REG8(IT83XX_GPIO_BASE + 0x24) +#define IT83XX_GPIO_GPCRC5 REG8(IT83XX_GPIO_BASE + 0x25) +#define IT83XX_GPIO_GPCRC6 REG8(IT83XX_GPIO_BASE + 0x26) +#define IT83XX_GPIO_GPCRC7 REG8(IT83XX_GPIO_BASE + 0x27) + +#define IT83XX_GPIO_GPCRE0 REG8(IT83XX_GPIO_BASE + 0x30) +#define IT83XX_GPIO_GPCRE1 REG8(IT83XX_GPIO_BASE + 0x31) +#define IT83XX_GPIO_GPCRE2 REG8(IT83XX_GPIO_BASE + 0x32) +#define IT83XX_GPIO_GPCRE3 REG8(IT83XX_GPIO_BASE + 0x33) +#define IT83XX_GPIO_GPCRE4 REG8(IT83XX_GPIO_BASE + 0x34) +#define IT83XX_GPIO_GPCRE5 REG8(IT83XX_GPIO_BASE + 0x35) +#define IT83XX_GPIO_GPCRE6 REG8(IT83XX_GPIO_BASE + 0x36) +#define IT83XX_GPIO_GPCRE7 REG8(IT83XX_GPIO_BASE + 0x37) + +#define IT83XX_GPIO_GPCRF0 REG8(IT83XX_GPIO_BASE + 0x38) +#define IT83XX_GPIO_GPCRF1 REG8(IT83XX_GPIO_BASE + 0x39) +#define IT83XX_GPIO_GPCRF2 REG8(IT83XX_GPIO_BASE + 0x3A) +#define IT83XX_GPIO_GPCRF3 REG8(IT83XX_GPIO_BASE + 0x3B) +#define IT83XX_GPIO_GPCRF4 REG8(IT83XX_GPIO_BASE + 0x3C) +#define IT83XX_GPIO_GPCRF5 REG8(IT83XX_GPIO_BASE + 0x3D) +#define IT83XX_GPIO_GPCRF6 REG8(IT83XX_GPIO_BASE + 0x3E) +#define IT83XX_GPIO_GPCRF7 REG8(IT83XX_GPIO_BASE + 0x3F) + +#define IT83XX_GPIO_GPCRH0 REG8(IT83XX_GPIO_BASE + 0x48) +#define IT83XX_GPIO_GPCRH1 REG8(IT83XX_GPIO_BASE + 0x49) +#define IT83XX_GPIO_GPCRH2 REG8(IT83XX_GPIO_BASE + 0x4A) +#define IT83XX_GPIO_GPCRH3 REG8(IT83XX_GPIO_BASE + 0x4B) +#define IT83XX_GPIO_GPCRH4 REG8(IT83XX_GPIO_BASE + 0x4C) +#define IT83XX_GPIO_GPCRH5 REG8(IT83XX_GPIO_BASE + 0x4D) +#define IT83XX_GPIO_GPCRH6 REG8(IT83XX_GPIO_BASE + 0x4E) +#define IT83XX_GPIO_GPCRH7 REG8(IT83XX_GPIO_BASE + 0x4F) + +#define IT83XX_GPIO_GPCRI0 REG8(IT83XX_GPIO_BASE + 0x50) +#define IT83XX_GPIO_GPCRI1 REG8(IT83XX_GPIO_BASE + 0x51) +#define IT83XX_GPIO_GPCRI2 REG8(IT83XX_GPIO_BASE + 0x52) +#define IT83XX_GPIO_GPCRI3 REG8(IT83XX_GPIO_BASE + 0x53) +#define IT83XX_GPIO_GPCRI4 REG8(IT83XX_GPIO_BASE + 0x54) +#define IT83XX_GPIO_GPCRI5 REG8(IT83XX_GPIO_BASE + 0x55) +#define IT83XX_GPIO_GPCRI6 REG8(IT83XX_GPIO_BASE + 0x56) +#define IT83XX_GPIO_GPCRI7 REG8(IT83XX_GPIO_BASE + 0x57) + +#define IT83XX_GPIO_GPCRM5 REG8(IT83XX_GPIO_BASE + 0xA5) + +#define IT83XX_GPIO_GPDMRA REG8(IT83XX_GPIO_BASE + 0x61) +#define IT83XX_GPIO_GPDMRB REG8(IT83XX_GPIO_BASE + 0x62) +#define IT83XX_GPIO_GPDMRC REG8(IT83XX_GPIO_BASE + 0x63) +#define IT83XX_GPIO_GPDMRE REG8(IT83XX_GPIO_BASE + 0x65) +#define IT83XX_GPIO_GPDMRF REG8(IT83XX_GPIO_BASE + 0x66) +#define IT83XX_GPIO_GPDMRH REG8(IT83XX_GPIO_BASE + 0x68) + +#define IT83XX_GPIO_GPCRL0 REG8(IT83XX_GPIO_BASE + 0x98) +#define IT83XX_GPIO_GPCRL1 REG8(IT83XX_GPIO_BASE + 0x99) +#define IT83XX_GPIO_GPCRL2 REG8(IT83XX_GPIO_BASE + 0x9A) +#define IT83XX_GPIO_GPCRL3 REG8(IT83XX_GPIO_BASE + 0x9B) +#define IT83XX_GPIO_GPCRP0 REG8(IT83XX_GPIO2_BASE + 0x18) +#define IT83XX_GPIO_GPCRP1 REG8(IT83XX_GPIO2_BASE + 0x19) + +#define IT83XX_GPIO_GRC1 REG8(IT83XX_GPIO_BASE + 0xF0) +#define IT83XX_GPIO_GRC2 REG8(IT83XX_GPIO_BASE + 0xF1) +#define IT83XX_GPIO_GRC3 REG8(IT83XX_GPIO_BASE + 0xF2) +#define IT83XX_GPIO_GRC4 REG8(IT83XX_GPIO_BASE + 0xF3) +#define IT83XX_GPIO_GRC5 REG8(IT83XX_GPIO_BASE + 0xF4) +#define IT83XX_GPIO_GRC6 REG8(IT83XX_GPIO_BASE + 0xF5) +#define IT83XX_GPIO_GRC7 REG8(IT83XX_GPIO_BASE + 0xF6) +#define IT83XX_GPIO_GRC8 REG8(IT83XX_GPIO_BASE + 0xF7) +#define IT83XX_GPIO_GRC19 REG8(IT83XX_GPIO_BASE + 0xE4) +#define IT83XX_GPIO_GRC20 REG8(IT83XX_GPIO_BASE + 0xE5) +#define IT83XX_GPIO_GRC21 REG8(IT83XX_GPIO_BASE + 0xE6) +#define IT83XX_GPIO_GRC22 REG8(IT83XX_GPIO_BASE + 0xE7) +#define IT83XX_GPIO_GRC23 REG8(IT83XX_GPIO_BASE + 0xE8) +#define IT83XX_GPIO_GRC24 REG8(IT83XX_GPIO_BASE + 0xE9) +#define IT83XX_GPIO_GCR25 REG8(IT83XX_GPIO_BASE + 0xD1) +#define IT83XX_GPIO_GCR26 REG8(IT83XX_GPIO_BASE + 0xD2) +#define IT83XX_GPIO_GCR27 REG8(IT83XX_GPIO_BASE + 0xD3) +#define IT83XX_GPIO_GCR28 REG8(IT83XX_GPIO_BASE + 0xD4) +#define IT83XX_GPIO_GCR29 REG8(IT83XX_GPIO_BASE + 0xEE) +#define IT83XX_GPIO_GCR30 REG8(IT83XX_GPIO_BASE + 0xED) +#define IT83XX_GPIO_GCR31 REG8(IT83XX_GPIO_BASE + 0xD5) +#define IT83XX_GPIO_GCR32 REG8(IT83XX_GPIO_BASE + 0xD6) +#define IT83XX_GPIO_GCR33 REG8(IT83XX_GPIO_BASE + 0xD7) + +#define IT83XX_VBATPC_BGPOPSCR REG8(IT83XX_GPIO2_BASE + 0xF0) +#define IT83XX_VBATPC_XLPIER REG8(IT83XX_GPIO2_BASE + 0xF5) enum { /* GPIO group index */ @@ -804,7 +805,16 @@ enum { #endif GPIO_PORT_COUNT, - /* NOTE: Support GPIO input only if KSO/KSI pins are used as GPIO. */ + /* + * NOTE: support flags when KSI/KSO are configured as GPIO + * 1) it8320bx: + * output: GPIO_OUTPUT, GPIO_OPEN_DRAIN, GPIO_HIGH, GPIO_LOW + * input: GPIO_INPUT + * 2) it8320dx, it8xxx1, and it8xxx2: + * output: GPIO_OUTPUT, GPIO_OPEN_DRAIN(always internal pullup), + * GPIO_HIGH, GPIO_LOW + * input: GPIO_INPUT, GPIO_PULL_UP + */ /* KSI[7-0] GPIO data mirror register. */ GPIO_KSI, /* KSO[15-8] GPIO data mirror register. */ @@ -816,11 +826,11 @@ enum { }; struct gpio_reg_t { - /* GPIO port data register (bit mapping to pin) */ + /* GPIO and KSI/KSO port data register (bit mapping to pin) */ uint32_t reg_gpdr; - /* GPIO port data mirror register (bit mapping to pin) */ + /* GPIO and KSI/KSO port data mirror register (bit mapping to pin) */ uint32_t reg_gpdmr; - /* GPIO port output type register (bit mapping to pin) */ + /* GPIO and KSI/KSO port output type register (bit mapping to pin) */ uint32_t reg_gpotr; /* GPIO port control register (byte mapping to pin) */ uint32_t reg_gpcr; @@ -829,70 +839,67 @@ struct gpio_reg_t { /* GPIO group index convert to GPIO data/output type/ctrl group address */ static const struct gpio_reg_t gpio_group_to_reg[] = { /* GPDR(set), GPDMR(get), GPOTR, GPCR */ - [GPIO_A] = { 0x00F01601, 0x00F01661, 0x00F01671, 0x00F01610 }, - [GPIO_B] = { 0x00F01602, 0x00F01662, 0x00F01672, 0x00F01618 }, - [GPIO_C] = { 0x00F01603, 0x00F01663, 0x00F01673, 0x00F01620 }, - [GPIO_D] = { 0x00F01604, 0x00F01664, 0x00F01674, 0x00F01628 }, - [GPIO_E] = { 0x00F01605, 0x00F01665, 0x00F01675, 0x00F01630 }, - [GPIO_F] = { 0x00F01606, 0x00F01666, 0x00F01676, 0x00F01638 }, - [GPIO_G] = { 0x00F01607, 0x00F01667, 0x00F01677, 0x00F01640 }, - [GPIO_H] = { 0x00F01608, 0x00F01668, 0x00F01678, 0x00F01648 }, - [GPIO_I] = { 0x00F01609, 0x00F01669, 0x00F01679, 0x00F01650 }, - [GPIO_J] = { 0x00F0160A, 0x00F0166A, 0x00F0167A, 0x00F01658 }, - [GPIO_K] = { 0x00F0160B, 0x00F0166B, 0x00F0167B, 0x00F01690 }, - [GPIO_L] = { 0x00F0160C, 0x00F0166C, 0x00F0167C, 0x00F01698 }, - [GPIO_M] = { 0x00F0160D, 0x00F0166D, 0x00F0167D, 0x00F016a0 }, + [GPIO_A] = { 0x00F01601, 0x00F01661, 0x00F01671, 0x00F01610 }, + [GPIO_B] = { 0x00F01602, 0x00F01662, 0x00F01672, 0x00F01618 }, + [GPIO_C] = { 0x00F01603, 0x00F01663, 0x00F01673, 0x00F01620 }, + [GPIO_D] = { 0x00F01604, 0x00F01664, 0x00F01674, 0x00F01628 }, + [GPIO_E] = { 0x00F01605, 0x00F01665, 0x00F01675, 0x00F01630 }, + [GPIO_F] = { 0x00F01606, 0x00F01666, 0x00F01676, 0x00F01638 }, + [GPIO_G] = { 0x00F01607, 0x00F01667, 0x00F01677, 0x00F01640 }, + [GPIO_H] = { 0x00F01608, 0x00F01668, 0x00F01678, 0x00F01648 }, + [GPIO_I] = { 0x00F01609, 0x00F01669, 0x00F01679, 0x00F01650 }, + [GPIO_J] = { 0x00F0160A, 0x00F0166A, 0x00F0167A, 0x00F01658 }, + [GPIO_K] = { 0x00F0160B, 0x00F0166B, 0x00F0167B, 0x00F01690 }, + [GPIO_L] = { 0x00F0160C, 0x00F0166C, 0x00F0167C, 0x00F01698 }, + [GPIO_M] = { 0x00F0160D, 0x00F0166D, 0x00F0167D, 0x00F016a0 }, #if defined(CHIP_FAMILY_IT8XXX1) || defined(CHIP_FAMILY_IT8XXX2) - [GPIO_O] = { 0x00F03E01, 0x00F03E61, 0x00F03E71, 0x00F03E10 }, - [GPIO_P] = { 0x00F03E02, 0x00F03E62, 0x00F03E72, 0x00F03E18 }, - [GPIO_Q] = { 0x00F03E03, 0x00F03E63, 0x00F03E73, 0x00F03E20 }, - [GPIO_R] = { 0x00F03E04, 0x00F03E64, 0x00F03E74, 0x00F03E28 }, + [GPIO_O] = { 0x00F03E01, 0x00F03E61, 0x00F03E71, 0x00F03E10 }, + [GPIO_P] = { 0x00F03E02, 0x00F03E62, 0x00F03E72, 0x00F03E18 }, + [GPIO_Q] = { 0x00F03E03, 0x00F03E63, 0x00F03E73, 0x00F03E20 }, + [GPIO_R] = { 0x00F03E04, 0x00F03E64, 0x00F03E74, 0x00F03E28 }, #endif - [GPIO_KSI] = { 0x00F01D09, 0x00F01D09, -1, -1 }, - [GPIO_KSO_H] = { 0x00F01D0C, 0x00F01D0C, -1, -1 }, - [GPIO_KSO_L] = { 0x00F01D0F, 0x00F01D0F, -1, -1 }, + [GPIO_KSI] = { 0x00F01D08, 0x00F01D09, 0x00F01D26, 0xFFFFFFFF }, + [GPIO_KSO_H] = { 0x00F01D01, 0x00F01D0C, 0x00F01D27, 0xFFFFFFFF }, + [GPIO_KSO_L] = { 0x00F01D00, 0x00F01D0F, 0x00F01D28, 0xFFFFFFFF }, }; BUILD_ASSERT(ARRAY_SIZE(gpio_group_to_reg) == (COUNT)); #define UNIMPLEMENTED_GPIO_BANK GPIO_A -#define IT83XX_GPIO_DATA(port) \ - REG8(gpio_group_to_reg[port].reg_gpdr) -#define IT83XX_GPIO_DATA_MIRROR(port) \ - REG8(gpio_group_to_reg[port].reg_gpdmr) -#define IT83XX_GPIO_GPOT(port) \ - REG8(gpio_group_to_reg[port].reg_gpotr) -#define IT83XX_GPIO_CTRL(port, pin_offset) \ +#define IT83XX_GPIO_DATA(port) REG8(gpio_group_to_reg[port].reg_gpdr) +#define IT83XX_GPIO_DATA_MIRROR(port) REG8(gpio_group_to_reg[port].reg_gpdmr) +#define IT83XX_GPIO_GPOT(port) REG8(gpio_group_to_reg[port].reg_gpotr) +#define IT83XX_GPIO_CTRL(port, pin_offset) \ REG8(gpio_group_to_reg[port].reg_gpcr + pin_offset) -#define GPCR_PORT_PIN_MODE_INPUT BIT(7) -#define GPCR_PORT_PIN_MODE_OUTPUT BIT(6) -#define GPCR_PORT_PIN_MODE_PULLUP BIT(2) -#define GPCR_PORT_PIN_MODE_PULLDOWN BIT(1) +#define GPCR_PORT_PIN_MODE_INPUT BIT(7) +#define GPCR_PORT_PIN_MODE_OUTPUT BIT(6) +#define GPCR_PORT_PIN_MODE_PULLUP BIT(2) +#define GPCR_PORT_PIN_MODE_PULLDOWN BIT(1) /* --- Clock and Power Management (ECPM) --- */ -#define IT83XX_ECPM_BASE 0x00F01E00 +#define IT83XX_ECPM_BASE 0x00F01E00 #define IT83XX_ECPM_CGCTRL1R_OFF 0x01 #define IT83XX_ECPM_CGCTRL2R_OFF 0x02 #define IT83XX_ECPM_CGCTRL3R_OFF 0x05 #define IT83XX_ECPM_CGCTRL4R_OFF 0x09 -#define IT83XX_ECPM_PLLCTRL REG8(IT83XX_ECPM_BASE+0x03) +#define IT83XX_ECPM_PLLCTRL REG8(IT83XX_ECPM_BASE + 0x03) enum ec_pll_ctrl { EC_PLL_DOZE = 0, EC_PLL_SLEEP = 1, EC_PLL_DEEP_DOZE = 3, }; -#define IT83XX_ECPM_AUTOCG REG8(IT83XX_ECPM_BASE+0x04) -#define IT83XX_ECPM_PLLFREQR REG8(IT83XX_ECPM_BASE+0x06) -#define IT83XX_ECPM_PLLCSS REG8(IT83XX_ECPM_BASE+0x08) -#define IT83XX_ECPM_SCDCR0 REG8(IT83XX_ECPM_BASE+0x0c) -#define IT83XX_ECPM_SCDCR1 REG8(IT83XX_ECPM_BASE+0x0d) -#define IT83XX_ECPM_SCDCR2 REG8(IT83XX_ECPM_BASE+0x0e) -#define IT83XX_ECPM_SCDCR3 REG8(IT83XX_ECPM_BASE+0x0f) -#define IT83XX_ECPM_SCDCR4 REG8(IT83XX_ECPM_BASE+0x10) +#define IT83XX_ECPM_AUTOCG REG8(IT83XX_ECPM_BASE + 0x04) +#define IT83XX_ECPM_PLLFREQR REG8(IT83XX_ECPM_BASE + 0x06) +#define IT83XX_ECPM_PLLCSS REG8(IT83XX_ECPM_BASE + 0x08) +#define IT83XX_ECPM_SCDCR0 REG8(IT83XX_ECPM_BASE + 0x0c) +#define IT83XX_ECPM_SCDCR1 REG8(IT83XX_ECPM_BASE + 0x0d) +#define IT83XX_ECPM_SCDCR2 REG8(IT83XX_ECPM_BASE + 0x0e) +#define IT83XX_ECPM_SCDCR3 REG8(IT83XX_ECPM_BASE + 0x0f) +#define IT83XX_ECPM_SCDCR4 REG8(IT83XX_ECPM_BASE + 0x10) /* * The clock gate offsets combine the register offset from ECPM_BASE and the @@ -900,514 +907,528 @@ enum ec_pll_ctrl { * clock_enable_peripheral() and clock_disable_peripheral() */ enum clock_gate_offsets { - CGC_OFFSET_EGPC = ((IT83XX_ECPM_CGCTRL2R_OFF << 8) | 0x40), - CGC_OFFSET_CIR = ((IT83XX_ECPM_CGCTRL2R_OFF << 8) | 0x20), - CGC_OFFSET_SWUC = ((IT83XX_ECPM_CGCTRL2R_OFF << 8) | 0x10), - CGC_OFFSET_USB = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x20), - CGC_OFFSET_PECI = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x08), - CGC_OFFSET_UART = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x04), - CGC_OFFSET_SSPI = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x02), - CGC_OFFSET_DBGR = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x01), - CGC_OFFSET_SMBF = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x80), - CGC_OFFSET_SMBE = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x40), - CGC_OFFSET_SMBD = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x20), - CGC_OFFSET_SMBC = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x10), - CGC_OFFSET_SMBB = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x08), - CGC_OFFSET_SMBA = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x04), - CGC_OFFSET_SMB = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x02), - CGC_OFFSET_CEC = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x01) + CGC_OFFSET_EGPC = ((IT83XX_ECPM_CGCTRL2R_OFF << 8) | 0x40), + CGC_OFFSET_CIR = ((IT83XX_ECPM_CGCTRL2R_OFF << 8) | 0x20), + CGC_OFFSET_SWUC = ((IT83XX_ECPM_CGCTRL2R_OFF << 8) | 0x10), + CGC_OFFSET_USB = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x20), + CGC_OFFSET_PECI = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x08), + CGC_OFFSET_UART = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x04), + CGC_OFFSET_SSPI = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x02), + CGC_OFFSET_DBGR = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x01), + CGC_OFFSET_SMBF = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x80), + CGC_OFFSET_SMBE = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x40), + CGC_OFFSET_SMBD = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x20), + CGC_OFFSET_SMBC = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x10), + CGC_OFFSET_SMBB = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x08), + CGC_OFFSET_SMBA = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x04), + CGC_OFFSET_SMB = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x02), + CGC_OFFSET_CEC = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x01) }; /* --- Timer (TMR) --- */ -#define IT83XX_TMR_BASE 0x00F02900 - -#define IT83XX_TMR_PRSC REG8(IT83XX_TMR_BASE+0x00) -#define IT83XX_TMR_GCSMS REG8(IT83XX_TMR_BASE+0x01) -#define IT83XX_TMR_CTR_A0 REG8(IT83XX_TMR_BASE+0x02) -#define IT83XX_TMR_CTR_A1 REG8(IT83XX_TMR_BASE+0x03) -#define IT83XX_TMR_CTR_B0 REG8(IT83XX_TMR_BASE+0x04) -#define IT83XX_TMR_CTR_B1 REG8(IT83XX_TMR_BASE+0x05) -#define IT83XX_TMR_DCR_A0 REG8(IT83XX_TMR_BASE+0x06) -#define IT83XX_TMR_DCR_A1 REG8(IT83XX_TMR_BASE+0x07) -#define IT83XX_TMR_DCR_B0 REG8(IT83XX_TMR_BASE+0x08) -#define IT83XX_TMR_DCR_B1 REG8(IT83XX_TMR_BASE+0x09) -#define IT83XX_TMR_CCGSR REG8(IT83XX_TMR_BASE+0x0A) -#define IT83XX_TMR_TMRCE REG8(IT83XX_TMR_BASE+0x0B) -#define IT83XX_TMR_TMRIE REG8(IT83XX_TMR_BASE+0x0C) +#define IT83XX_TMR_BASE 0x00F02900 + +#define IT83XX_TMR_PRSC REG8(IT83XX_TMR_BASE + 0x00) +#define IT83XX_TMR_GCSMS REG8(IT83XX_TMR_BASE + 0x01) +#define IT83XX_TMR_CTR_A0 REG8(IT83XX_TMR_BASE + 0x02) +#define IT83XX_TMR_CTR_A1 REG8(IT83XX_TMR_BASE + 0x03) +#define IT83XX_TMR_CTR_B0 REG8(IT83XX_TMR_BASE + 0x04) +#define IT83XX_TMR_CTR_B1 REG8(IT83XX_TMR_BASE + 0x05) +#define IT83XX_TMR_DCR_A0 REG8(IT83XX_TMR_BASE + 0x06) +#define IT83XX_TMR_DCR_A1 REG8(IT83XX_TMR_BASE + 0x07) +#define IT83XX_TMR_DCR_B0 REG8(IT83XX_TMR_BASE + 0x08) +#define IT83XX_TMR_DCR_B1 REG8(IT83XX_TMR_BASE + 0x09) +#define IT83XX_TMR_CCGSR REG8(IT83XX_TMR_BASE + 0x0A) +#define IT83XX_TMR_TMRCE REG8(IT83XX_TMR_BASE + 0x0B) +#define IT83XX_TMR_TMRIE REG8(IT83XX_TMR_BASE + 0x0C) /* --- External Timer and Watchdog (ETWD) --- */ -#define IT83XX_ETWD_BASE 0x00F01F00 - -#define IT83XX_ETWD_ETWCFG REG8(IT83XX_ETWD_BASE+0x01) -#define IT83XX_ETWD_ET1PSR REG8(IT83XX_ETWD_BASE+0x02) -#define IT83XX_ETWD_ET1CNTLHR REG8(IT83XX_ETWD_BASE+0x03) -#define IT83XX_ETWD_ET1CNTLLR REG8(IT83XX_ETWD_BASE+0x04) -#define IT83XX_ETWD_ETWCTRL REG8(IT83XX_ETWD_BASE+0x05) -#define IT83XX_ETWD_EWDCNTLLR REG8(IT83XX_ETWD_BASE+0x06) -#define IT83XX_ETWD_EWDKEYR REG8(IT83XX_ETWD_BASE+0x07) -#define IT83XX_ETWD_EWDCNTLHR REG8(IT83XX_ETWD_BASE+0x09) -#define IT83XX_ETWD_ETXCTRL(n) REG8(IT83XX_ETWD_BASE + 0x10 + (n << 3)) -#define IT83XX_ETWD_ETXPSR(n) REG8(IT83XX_ETWD_BASE + 0x11 + (n << 3)) -#define IT83XX_ETWD_ETXCNTLR(n) REG32(IT83XX_ETWD_BASE + 0x14 + (n << 3)) -#define IT83XX_ETWD_ETXCNTOR(n) REG32(IT83XX_ETWD_BASE + 0x48 + (n << 2)) +#define IT83XX_ETWD_BASE 0x00F01F00 + +#define IT83XX_ETWD_ETWCFG REG8(IT83XX_ETWD_BASE + 0x01) +#define IT83XX_ETWD_ET1PSR REG8(IT83XX_ETWD_BASE + 0x02) +#define IT83XX_ETWD_ET1CNTLHR REG8(IT83XX_ETWD_BASE + 0x03) +#define IT83XX_ETWD_ET1CNTLLR REG8(IT83XX_ETWD_BASE + 0x04) +#define IT83XX_ETWD_ETWCTRL REG8(IT83XX_ETWD_BASE + 0x05) +#define IT83XX_ETWD_EWDCNTLLR REG8(IT83XX_ETWD_BASE + 0x06) +#define IT83XX_ETWD_EWDKEYR REG8(IT83XX_ETWD_BASE + 0x07) +#define IT83XX_ETWD_EWDCNTLHR REG8(IT83XX_ETWD_BASE + 0x09) +#define IT83XX_ETWD_ETXCTRL(n) REG8(IT83XX_ETWD_BASE + 0x10 + (n << 3)) +#define IT83XX_ETWD_ETXPSR(n) REG8(IT83XX_ETWD_BASE + 0x11 + (n << 3)) +#define IT83XX_ETWD_ETXCNTLR(n) REG32(IT83XX_ETWD_BASE + 0x14 + (n << 3)) +#define IT83XX_ETWD_ETXCNTOR(n) REG32(IT83XX_ETWD_BASE + 0x48 + (n << 2)) /* --- General Control (GCTRL) --- */ #define IT83XX_GCTRL_BASE 0x00F02000 #ifdef IT83XX_CHIP_ID_3BYTES -#define IT83XX_GCTRL_CHIPID1 REG8(IT83XX_GCTRL_BASE+0x85) -#define IT83XX_GCTRL_CHIPID2 REG8(IT83XX_GCTRL_BASE+0x86) -#define IT83XX_GCTRL_CHIPID3 REG8(IT83XX_GCTRL_BASE+0x87) +#define IT83XX_GCTRL_CHIPID1 REG8(IT83XX_GCTRL_BASE + 0x85) +#define IT83XX_GCTRL_CHIPID2 REG8(IT83XX_GCTRL_BASE + 0x86) +#define IT83XX_GCTRL_CHIPID3 REG8(IT83XX_GCTRL_BASE + 0x87) #else -#define IT83XX_GCTRL_CHIPID1 REG8(IT83XX_GCTRL_BASE+0x00) -#define IT83XX_GCTRL_CHIPID2 REG8(IT83XX_GCTRL_BASE+0x01) +#define IT83XX_GCTRL_CHIPID1 REG8(IT83XX_GCTRL_BASE + 0x00) +#define IT83XX_GCTRL_CHIPID2 REG8(IT83XX_GCTRL_BASE + 0x01) #endif -#define IT83XX_GCTRL_CHIPVER REG8(IT83XX_GCTRL_BASE+0x02) -#define IT83XX_GCTRL_DBGROS REG8(IT83XX_GCTRL_BASE+0x03) -#define IT83XX_SMB_DBGR BIT(0) -#define IT83XX_GCTRL_WNCKR REG8(IT83XX_GCTRL_BASE+0x0B) -#define IT83XX_GCTRL_RSTS REG8(IT83XX_GCTRL_BASE+0x06) -#define IT83XX_GCTRL_BADRSEL REG8(IT83XX_GCTRL_BASE+0x0A) -#define IT83XX_GCTRL_SPCTRL1 REG8(IT83XX_GCTRL_BASE+0x0D) -#define IT83XX_GCTRL_RSTDMMC REG8(IT83XX_GCTRL_BASE+0x10) -#define IT83XX_GCTRL_RSTC4 REG8(IT83XX_GCTRL_BASE+0x11) -#define IT83XX_GCTRL_SPCTRL4 REG8(IT83XX_GCTRL_BASE+0x1C) -#define IT83XX_GCTRL_MCCR3 REG8(IT83XX_GCTRL_BASE+0x20) -#define IT83XX_GCTRL_SPISLVPFE BIT(6) -#define IT83XX_GCTRL_RSTC5 REG8(IT83XX_GCTRL_BASE+0x21) -#define IT83XX_GCTRL_MCCR REG8(IT83XX_GCTRL_BASE+0x30) -#define IT83XX_GCTRL_PMER1 REG8(IT83XX_GCTRL_BASE+0x32) -#define IT83XX_GCTRL_PMER2 REG8(IT83XX_GCTRL_BASE+0x33) -#define IT83XX_GCTRL_EPLR REG8(IT83XX_GCTRL_BASE+0x37) -#define IT83XX_GCTRL_IVTBAR REG8(IT83XX_GCTRL_BASE+0x41) -#define IT83XX_GCTRL_MCCR2 REG8(IT83XX_GCTRL_BASE+0x44) -#define IT83XX_DLM14_ENABLE BIT(5) -#define IT83XX_GCTRL_SSCR REG8(IT83XX_GCTRL_BASE+0x4A) -#define IT83XX_GCTRL_ETWDUARTCR REG8(IT83XX_GCTRL_BASE+0x4B) -#define IT83XX_GCTRL_WMCR REG8(IT83XX_GCTRL_BASE+0x4C) -#define IT83XX_GCTRL_H2ROFSR REG8(IT83XX_GCTRL_BASE+0x53) +#define IT83XX_GCTRL_CHIPVER REG8(IT83XX_GCTRL_BASE + 0x02) +#define IT83XX_GCTRL_DBGROS REG8(IT83XX_GCTRL_BASE + 0x03) +#define IT83XX_SMB_DBGR BIT(0) +#define IT83XX_GCTRL_WNCKR REG8(IT83XX_GCTRL_BASE + 0x0B) +#define IT83XX_GCTRL_RSTS REG8(IT83XX_GCTRL_BASE + 0x06) +#define IT83XX_GCTRL_BADRSEL REG8(IT83XX_GCTRL_BASE + 0x0A) +#define IT83XX_GCTRL_SPCTRL1 REG8(IT83XX_GCTRL_BASE + 0x0D) +#define IT83XX_GCTRL_RSTDMMC REG8(IT83XX_GCTRL_BASE + 0x10) +#define IT83XX_GCTRL_RSTC4 REG8(IT83XX_GCTRL_BASE + 0x11) +#define IT83XX_GCTRL_SPCTRL4 REG8(IT83XX_GCTRL_BASE + 0x1C) +#define IT83XX_GCTRL_MCCR3 REG8(IT83XX_GCTRL_BASE + 0x20) +#define IT83XX_GCTRL_SPISLVPFE BIT(6) +#define IT83XX_GCTRL_RSTC5 REG8(IT83XX_GCTRL_BASE + 0x21) +#define IT83XX_GCTRL_MCCR REG8(IT83XX_GCTRL_BASE + 0x30) +#define IT83XX_GCTRL_PMER1 REG8(IT83XX_GCTRL_BASE + 0x32) +#define IT83XX_GCTRL_PMER2 REG8(IT83XX_GCTRL_BASE + 0x33) +#define IT83XX_GCTRL_EPLR REG8(IT83XX_GCTRL_BASE + 0x37) +#define IT83XX_GCTRL_IVTBAR REG8(IT83XX_GCTRL_BASE + 0x41) +#define IT83XX_GCTRL_MCCR2 REG8(IT83XX_GCTRL_BASE + 0x44) +#define IT83XX_GCTRL_PIN_MUX0 REG8(IT83XX_GCTRL_BASE + 0x46) +#define IT83XX_DLM14_ENABLE BIT(5) +#define IT83XX_GCTRL_SSCR REG8(IT83XX_GCTRL_BASE + 0x4A) +#define IT83XX_GCTRL_ETWDUARTCR REG8(IT83XX_GCTRL_BASE + 0x4B) +#define IT83XX_GCTRL_WMCR REG8(IT83XX_GCTRL_BASE + 0x4C) +#define IT83XX_GCTRL_H2ROFSR REG8(IT83XX_GCTRL_BASE + 0x53) /* bit[0] = 0 or 1 : disable or enable ETWD hardware reset */ -#define ETWD_HW_RST_EN BIT(0) -#define IT83XX_GCTRL_RVILMCR0 REG8(IT83XX_GCTRL_BASE+0x5D) -#define ILMCR_ILM2_ENABLE BIT(2) -#define IT83XX_GCTRL_EWPR0PFH(i) REG8(IT83XX_GCTRL_BASE+0x60+i) -#define IT83XX_GCTRL_EWPR0PFD(i) REG8(IT83XX_GCTRL_BASE+0xA0+i) -#define IT83XX_GCTRL_EWPR0PFEC(i) REG8(IT83XX_GCTRL_BASE+0xC0+i) +#define ETWD_HW_RST_EN BIT(0) +#define IT83XX_GCTRL_RVILMCR0 REG8(IT83XX_GCTRL_BASE + 0x5D) +#define ILMCR_ILM0_ENABLE BIT(0) +#define ILMCR_ILM2_ENABLE BIT(2) +#define IT83XX_GCTRL_EWPR0PFH(i) REG8(IT83XX_GCTRL_BASE + 0x60 + i) +#define IT83XX_GCTRL_EWPR0PFD(i) REG8(IT83XX_GCTRL_BASE + 0xA0 + i) +#define IT83XX_GCTRL_EWPR0PFEC(i) REG8(IT83XX_GCTRL_BASE + 0xC0 + i) /* --- Pulse Width Modulation (PWM) --- */ -#define IT83XX_PWM_BASE 0x00F01800 - -#define IT83XX_PWM_C0CPRS REG8(IT83XX_PWM_BASE+0x00) -#define IT83XX_PWM_CTR REG8(IT83XX_PWM_BASE+0x01) -#define IT83XX_PWM_DCR0 REG8(IT83XX_PWM_BASE+0x02) -#define IT83XX_PWM_DCR1 REG8(IT83XX_PWM_BASE+0x03) -#define IT83XX_PWM_DCR2 REG8(IT83XX_PWM_BASE+0x04) -#define IT83XX_PWM_DCR3 REG8(IT83XX_PWM_BASE+0x05) -#define IT83XX_PWM_DCR4 REG8(IT83XX_PWM_BASE+0x06) -#define IT83XX_PWM_DCR5 REG8(IT83XX_PWM_BASE+0x07) -#define IT83XX_PWM_DCR6 REG8(IT83XX_PWM_BASE+0x08) -#define IT83XX_PWM_DCR7 REG8(IT83XX_PWM_BASE+0x09) -#define IT83XX_PWM_PWMPOL REG8(IT83XX_PWM_BASE+0x0A) -#define IT83XX_PWM_PCFSR REG8(IT83XX_PWM_BASE+0x0B) -#define IT83XX_PWM_PCSSGL REG8(IT83XX_PWM_BASE+0x0C) -#define IT83XX_PWM_PCSSGH REG8(IT83XX_PWM_BASE+0x0D) -#define IT83XX_PWM_CR256PCSSG REG8(IT83XX_PWM_BASE+0x0E) -#define IT83XX_PWM_PCSGR REG8(IT83XX_PWM_BASE+0x0F) -#define IT83XX_PWM_CTR1M REG8(IT83XX_PWM_BASE+0x10) -#define IT83XX_PWM_F1TLRR REG8(IT83XX_PWM_BASE+0x1E) -#define IT83XX_PWM_F1TMRR REG8(IT83XX_PWM_BASE+0x1F) -#define IT83XX_PWM_F2TLRR REG8(IT83XX_PWM_BASE+0x20) -#define IT83XX_PWM_F2TMRR REG8(IT83XX_PWM_BASE+0x21) -#define IT83XX_PWM_ZINTSCR REG8(IT83XX_PWM_BASE+0x22) -#define IT83XX_PWM_ZTIER REG8(IT83XX_PWM_BASE+0x23) -#define IT83XX_PWM_TSWCTLR REG8(IT83XX_PWM_BASE+0x24) -#define IT83XX_PWM_C4CPRS REG8(IT83XX_PWM_BASE+0x27) -#define IT83XX_PWM_C4MCPRS REG8(IT83XX_PWM_BASE+0x28) -#define IT83XX_PWM_C6CPRS REG8(IT83XX_PWM_BASE+0x2B) -#define IT83XX_PWM_C6MCPRS REG8(IT83XX_PWM_BASE+0x2C) -#define IT83XX_PWM_C7CPRS REG8(IT83XX_PWM_BASE+0x2D) -#define IT83XX_PWM_C7MCPRS REG8(IT83XX_PWM_BASE+0x2E) -#define IT83XX_PWM_CLK6MSEL REG8(IT83XX_PWM_BASE+0x40) -#define IT83XX_PWM_CTR1 REG8(IT83XX_PWM_BASE+0x41) -#define IT83XX_PWM_CTR2 REG8(IT83XX_PWM_BASE+0x42) -#define IT83XX_PWM_CTR3 REG8(IT83XX_PWM_BASE+0x43) -#define IT83XX_PWM_PWM5TOCTRL REG8(IT83XX_PWM_BASE+0x44) -#define IT83XX_PWM_CFLRR REG8(IT83XX_PWM_BASE+0x45) -#define IT83XX_PWM_CFMRR REG8(IT83XX_PWM_BASE+0x46) -#define IT83XX_PWM_CFINTCTRL REG8(IT83XX_PWM_BASE+0x47) -#define IT83XX_PWM_TSWCTRL REG8(IT83XX_PWM_BASE+0x48) -#define IT83XX_PWM_PWMODENR REG8(IT83XX_PWM_BASE+0x49) +#define IT83XX_PWM_BASE 0x00F01800 + +#define IT83XX_PWM_C0CPRS REG8(IT83XX_PWM_BASE + 0x00) +#define IT83XX_PWM_CTR REG8(IT83XX_PWM_BASE + 0x01) +#define IT83XX_PWM_DCR0 REG8(IT83XX_PWM_BASE + 0x02) +#define IT83XX_PWM_DCR1 REG8(IT83XX_PWM_BASE + 0x03) +#define IT83XX_PWM_DCR2 REG8(IT83XX_PWM_BASE + 0x04) +#define IT83XX_PWM_DCR3 REG8(IT83XX_PWM_BASE + 0x05) +#define IT83XX_PWM_DCR4 REG8(IT83XX_PWM_BASE + 0x06) +#define IT83XX_PWM_DCR5 REG8(IT83XX_PWM_BASE + 0x07) +#define IT83XX_PWM_DCR6 REG8(IT83XX_PWM_BASE + 0x08) +#define IT83XX_PWM_DCR7 REG8(IT83XX_PWM_BASE + 0x09) +#define IT83XX_PWM_PWMPOL REG8(IT83XX_PWM_BASE + 0x0A) +#define IT83XX_PWM_PCFSR REG8(IT83XX_PWM_BASE + 0x0B) +#define IT83XX_PWM_PCSSGL REG8(IT83XX_PWM_BASE + 0x0C) +#define IT83XX_PWM_PCSSGH REG8(IT83XX_PWM_BASE + 0x0D) +#define IT83XX_PWM_CR256PCSSG REG8(IT83XX_PWM_BASE + 0x0E) +#define IT83XX_PWM_PCSGR REG8(IT83XX_PWM_BASE + 0x0F) +#define IT83XX_PWM_CTR1M REG8(IT83XX_PWM_BASE + 0x10) +#define IT83XX_PWM_F1TLRR REG8(IT83XX_PWM_BASE + 0x1E) +#define IT83XX_PWM_F1TMRR REG8(IT83XX_PWM_BASE + 0x1F) +#define IT83XX_PWM_F2TLRR REG8(IT83XX_PWM_BASE + 0x20) +#define IT83XX_PWM_F2TMRR REG8(IT83XX_PWM_BASE + 0x21) +#define IT83XX_PWM_ZINTSCR REG8(IT83XX_PWM_BASE + 0x22) +#define IT83XX_PWM_ZTIER REG8(IT83XX_PWM_BASE + 0x23) +#define IT83XX_PWM_TSWCTLR REG8(IT83XX_PWM_BASE + 0x24) +#define IT83XX_PWM_C4CPRS REG8(IT83XX_PWM_BASE + 0x27) +#define IT83XX_PWM_C4MCPRS REG8(IT83XX_PWM_BASE + 0x28) +#define IT83XX_PWM_C6CPRS REG8(IT83XX_PWM_BASE + 0x2B) +#define IT83XX_PWM_C6MCPRS REG8(IT83XX_PWM_BASE + 0x2C) +#define IT83XX_PWM_C7CPRS REG8(IT83XX_PWM_BASE + 0x2D) +#define IT83XX_PWM_C7MCPRS REG8(IT83XX_PWM_BASE + 0x2E) +#define IT83XX_PWM_CLK6MSEL REG8(IT83XX_PWM_BASE + 0x40) +#define IT83XX_PWM_CTR1 REG8(IT83XX_PWM_BASE + 0x41) +#define IT83XX_PWM_CTR2 REG8(IT83XX_PWM_BASE + 0x42) +#define IT83XX_PWM_CTR3 REG8(IT83XX_PWM_BASE + 0x43) +#define IT83XX_PWM_PWM5TOCTRL REG8(IT83XX_PWM_BASE + 0x44) +#define IT83XX_PWM_CFLRR REG8(IT83XX_PWM_BASE + 0x45) +#define IT83XX_PWM_CFMRR REG8(IT83XX_PWM_BASE + 0x46) +#define IT83XX_PWM_CFINTCTRL REG8(IT83XX_PWM_BASE + 0x47) +#define IT83XX_PWM_TSWCTRL REG8(IT83XX_PWM_BASE + 0x48) +#define IT83XX_PWM_PWMODENR REG8(IT83XX_PWM_BASE + 0x49) /* Analog to Digital Converter (ADC) */ -#define IT83XX_ADC_BASE 0x00F01900 - -#define IT83XX_ADC_ADCSTS REG8(IT83XX_ADC_BASE+0x00) -#define IT83XX_ADC_ADCCFG REG8(IT83XX_ADC_BASE+0x01) -#define IT83XX_ADC_ADCCTL REG8(IT83XX_ADC_BASE+0x02) -#define IT83XX_ADC_ADCGCR REG8(IT83XX_ADC_BASE+0x03) -#define IT83XX_ADC_VCH0CTL REG8(IT83XX_ADC_BASE+0x04) -#define IT83XX_ADC_KDCTL REG8(IT83XX_ADC_BASE+0x05) -#define IT83XX_ADC_AHCE BIT(7) -#define IT83XX_ADC_VCH1CTL REG8(IT83XX_ADC_BASE+0x06) -#define IT83XX_ADC_VCH1DATL REG8(IT83XX_ADC_BASE+0x07) -#define IT83XX_ADC_VCH1DATM REG8(IT83XX_ADC_BASE+0x08) -#define IT83XX_ADC_VCH2CTL REG8(IT83XX_ADC_BASE+0x09) -#define IT83XX_ADC_VCH2DATL REG8(IT83XX_ADC_BASE+0x0A) -#define IT83XX_ADC_VCH2DATM REG8(IT83XX_ADC_BASE+0x0B) -#define IT83XX_ADC_VCH3CTL REG8(IT83XX_ADC_BASE+0x0C) -#define IT83XX_ADC_VCH3DATL REG8(IT83XX_ADC_BASE+0x0D) -#define IT83XX_ADC_VCH3DATM REG8(IT83XX_ADC_BASE+0x0E) -#define IT83XX_ADC_VHSCDBL REG8(IT83XX_ADC_BASE+0x14) -#define IT83XX_ADC_VHSCDBM REG8(IT83XX_ADC_BASE+0x15) -#define IT83XX_ADC_VCH0DATL REG8(IT83XX_ADC_BASE+0x18) -#define IT83XX_ADC_VCH0DATM REG8(IT83XX_ADC_BASE+0x19) -#define IT83XX_ADC_VHSGCDBL REG8(IT83XX_ADC_BASE+0x1C) -#define IT83XX_ADC_VHSGCDBM REG8(IT83XX_ADC_BASE+0x1D) -#define IT83XX_ADC_ADCSAR REG8(IT83XX_ADC_BASE+0x32) -#define IT83XX_ADC_VCMPSCP REG8(IT83XX_ADC_BASE+0x37) -#define IT83XX_ADC_VCH4CTL REG8(IT83XX_ADC_BASE+0x38) -#define IT83XX_ADC_VCH4DATM REG8(IT83XX_ADC_BASE+0x39) -#define IT83XX_ADC_VCH4DATL REG8(IT83XX_ADC_BASE+0x3A) -#define IT83XX_ADC_VCH5CTL REG8(IT83XX_ADC_BASE+0x3B) -#define IT83XX_ADC_VCH5DATM REG8(IT83XX_ADC_BASE+0x3C) -#define IT83XX_ADC_VCH5DATL REG8(IT83XX_ADC_BASE+0x3D) -#define IT83XX_ADC_VCH6CTL REG8(IT83XX_ADC_BASE+0x3E) -#define IT83XX_ADC_VCH6DATM REG8(IT83XX_ADC_BASE+0x3F) -#define IT83XX_ADC_VCH6DATL REG8(IT83XX_ADC_BASE+0x40) -#define IT83XX_ADC_VCH7CTL REG8(IT83XX_ADC_BASE+0x41) -#define IT83XX_ADC_VCH7DATM REG8(IT83XX_ADC_BASE+0x42) -#define IT83XX_ADC_VCH7DATL REG8(IT83XX_ADC_BASE+0x43) -#define IT83XX_ADC_ADCDVSTS REG8(IT83XX_ADC_BASE+0x44) -#define IT83XX_ADC_VCMPSTS REG8(IT83XX_ADC_BASE+0x45) -#define IT83XX_ADC_VCMP0CTL REG8(IT83XX_ADC_BASE+0x46) -#define ADC_VCMP_CMPEN BIT(7) -#define ADC_VCMP_CMPINTEN BIT(6) -#define ADC_VCMP_GREATER_THRESHOLD BIT(5) -#define ADC_VCMP_EDGE_TRIGGER BIT(4) -#define ADC_VCMP_GPIO_ACTIVE_LOW BIT(3) -#define IT83XX_ADC_CMP0THRDATM REG8(IT83XX_ADC_BASE+0x47) -#define IT83XX_ADC_CMP0THRDATL REG8(IT83XX_ADC_BASE+0x48) -#define IT83XX_ADC_VCMP1CTL REG8(IT83XX_ADC_BASE+0x49) -#define IT83XX_ADC_CMP1THRDATM REG8(IT83XX_ADC_BASE+0x4A) -#define IT83XX_ADC_CMP1THRDATL REG8(IT83XX_ADC_BASE+0x4B) -#define IT83XX_ADC_VCMP2CTL REG8(IT83XX_ADC_BASE+0x4C) -#define IT83XX_ADC_CMP2THRDATM REG8(IT83XX_ADC_BASE+0x4D) -#define IT83XX_ADC_CMP2THRDATL REG8(IT83XX_ADC_BASE+0x4E) -#define IT83XX_ADC_VCH13CTL REG8(IT83XX_ADC_BASE+0x60) -#define IT83XX_ADC_VCH13DATM REG8(IT83XX_ADC_BASE+0x61) -#define IT83XX_ADC_VCH13DATL REG8(IT83XX_ADC_BASE+0x62) -#define IT83XX_ADC_VCH14CTL REG8(IT83XX_ADC_BASE+0x63) -#define IT83XX_ADC_VCH14DATM REG8(IT83XX_ADC_BASE+0x64) -#define IT83XX_ADC_VCH14DATL REG8(IT83XX_ADC_BASE+0x65) -#define IT83XX_ADC_VCH15CTL REG8(IT83XX_ADC_BASE+0x66) -#define IT83XX_ADC_VCH15DATM REG8(IT83XX_ADC_BASE+0x67) -#define IT83XX_ADC_VCH15DATL REG8(IT83XX_ADC_BASE+0x68) -#define IT83XX_ADC_VCH16CTL REG8(IT83XX_ADC_BASE+0x69) -#define IT83XX_ADC_VCH16DATM REG8(IT83XX_ADC_BASE+0x6A) -#define IT83XX_ADC_VCH16DATL REG8(IT83XX_ADC_BASE+0x6B) -#define IT83XX_ADC_ADCDVSTS2 REG8(IT83XX_ADC_BASE+0x6C) -#define IT83XX_ADC_VCMPSTS2 REG8(IT83XX_ADC_BASE+0x6D) -#define IT83XX_ADC_VCMP3CTL REG8(IT83XX_ADC_BASE+0x6E) -#define IT83XX_ADC_CMP3THRDATM REG8(IT83XX_ADC_BASE+0x6F) -#define IT83XX_ADC_CMP3THRDATL REG8(IT83XX_ADC_BASE+0x70) -#define IT83XX_ADC_VCMP4CTL REG8(IT83XX_ADC_BASE+0x71) -#define IT83XX_ADC_CMP4THRDATM REG8(IT83XX_ADC_BASE+0x72) -#define IT83XX_ADC_CMP4THRDATL REG8(IT83XX_ADC_BASE+0x73) -#define IT83XX_ADC_VCMP5CTL REG8(IT83XX_ADC_BASE+0x74) -#define IT83XX_ADC_CMP5THRDATM REG8(IT83XX_ADC_BASE+0x75) -#define IT83XX_ADC_CMP5THRDATL REG8(IT83XX_ADC_BASE+0x76) -#define IT83XX_ADC_VCMP0CSELM REG8(IT83XX_ADC_BASE+0x77) -#define ADC_VCMP_VCMPCSELM BIT(0) -#define IT83XX_ADC_VCMP1CSELM REG8(IT83XX_ADC_BASE+0x78) -#define IT83XX_ADC_VCMP2CSELM REG8(IT83XX_ADC_BASE+0x79) -#define IT83XX_ADC_VCMP3CSELM REG8(IT83XX_ADC_BASE+0x7A) -#define IT83XX_ADC_VCMP4CSELM REG8(IT83XX_ADC_BASE+0x7B) -#define IT83XX_ADC_VCMP5CSELM REG8(IT83XX_ADC_BASE+0x7C) +#define IT83XX_ADC_BASE 0x00F01900 + +#define IT83XX_ADC_ADCSTS REG8(IT83XX_ADC_BASE + 0x00) +#define IT83XX_ADC_ADCCFG REG8(IT83XX_ADC_BASE + 0x01) +#define IT83XX_ADC_ADCCTL REG8(IT83XX_ADC_BASE + 0x02) +#define IT83XX_ADC_ADCGCR REG8(IT83XX_ADC_BASE + 0x03) +#define IT83XX_ADC_DBKEN BIT(7) /* ADC data buffer keep enable. */ +#define IT83XX_ADC_VCH0CTL REG8(IT83XX_ADC_BASE + 0x04) +#define IT83XX_ADC_KDCTL REG8(IT83XX_ADC_BASE + 0x05) +#define IT83XX_ADC_AHCE BIT(7) +#define IT83XX_ADC_VCH1CTL REG8(IT83XX_ADC_BASE + 0x06) +#define IT83XX_ADC_VCH1DATL REG8(IT83XX_ADC_BASE + 0x07) +#define IT83XX_ADC_VCH1DATM REG8(IT83XX_ADC_BASE + 0x08) +#define IT83XX_ADC_VCH2CTL REG8(IT83XX_ADC_BASE + 0x09) +#define IT83XX_ADC_VCH2DATL REG8(IT83XX_ADC_BASE + 0x0A) +#define IT83XX_ADC_VCH2DATM REG8(IT83XX_ADC_BASE + 0x0B) +#define IT83XX_ADC_VCH3CTL REG8(IT83XX_ADC_BASE + 0x0C) +#define IT83XX_ADC_VCH3DATL REG8(IT83XX_ADC_BASE + 0x0D) +#define IT83XX_ADC_VCH3DATM REG8(IT83XX_ADC_BASE + 0x0E) +#define IT83XX_ADC_VHSCDBL REG8(IT83XX_ADC_BASE + 0x14) +#define IT83XX_ADC_VHSCDBM REG8(IT83XX_ADC_BASE + 0x15) +#define IT83XX_ADC_VCH0DATL REG8(IT83XX_ADC_BASE + 0x18) +#define IT83XX_ADC_VCH0DATM REG8(IT83XX_ADC_BASE + 0x19) +#define IT83XX_ADC_VHSGCDBL REG8(IT83XX_ADC_BASE + 0x1C) +#define IT83XX_ADC_VHSGCDBM REG8(IT83XX_ADC_BASE + 0x1D) +#define IT83XX_ADC_ADCSAR REG8(IT83XX_ADC_BASE + 0x32) +#define IT83XX_ADC_VCMPSCP REG8(IT83XX_ADC_BASE + 0x37) +#define IT83XX_ADC_VCH4CTL REG8(IT83XX_ADC_BASE + 0x38) +#define IT83XX_ADC_VCH4DATM REG8(IT83XX_ADC_BASE + 0x39) +#define IT83XX_ADC_VCH4DATL REG8(IT83XX_ADC_BASE + 0x3A) +#define IT83XX_ADC_VCH5CTL REG8(IT83XX_ADC_BASE + 0x3B) +#define IT83XX_ADC_VCH5DATM REG8(IT83XX_ADC_BASE + 0x3C) +#define IT83XX_ADC_VCH5DATL REG8(IT83XX_ADC_BASE + 0x3D) +#define IT83XX_ADC_VCH6CTL REG8(IT83XX_ADC_BASE + 0x3E) +#define IT83XX_ADC_VCH6DATM REG8(IT83XX_ADC_BASE + 0x3F) +#define IT83XX_ADC_VCH6DATL REG8(IT83XX_ADC_BASE + 0x40) +#define IT83XX_ADC_VCH7CTL REG8(IT83XX_ADC_BASE + 0x41) +#define IT83XX_ADC_VCH7DATM REG8(IT83XX_ADC_BASE + 0x42) +#define IT83XX_ADC_VCH7DATL REG8(IT83XX_ADC_BASE + 0x43) +#define IT83XX_ADC_ADCDVSTS REG8(IT83XX_ADC_BASE + 0x44) +#define IT83XX_ADC_VCMPSTS REG8(IT83XX_ADC_BASE + 0x45) +#define IT83XX_ADC_VCMP0CTL REG8(IT83XX_ADC_BASE + 0x46) +#define ADC_VCMP_CMPEN BIT(7) +#define ADC_VCMP_CMPINTEN BIT(6) +#define ADC_VCMP_GREATER_THRESHOLD BIT(5) +#define ADC_VCMP_EDGE_TRIGGER BIT(4) +#define ADC_VCMP_GPIO_ACTIVE_LOW BIT(3) +#define IT83XX_ADC_CMP0THRDATM REG8(IT83XX_ADC_BASE + 0x47) +#define IT83XX_ADC_CMP0THRDATL REG8(IT83XX_ADC_BASE + 0x48) +#define IT83XX_ADC_VCMP1CTL REG8(IT83XX_ADC_BASE + 0x49) +#define IT83XX_ADC_CMP1THRDATM REG8(IT83XX_ADC_BASE + 0x4A) +#define IT83XX_ADC_CMP1THRDATL REG8(IT83XX_ADC_BASE + 0x4B) +#define IT83XX_ADC_VCMP2CTL REG8(IT83XX_ADC_BASE + 0x4C) +#define IT83XX_ADC_CMP2THRDATM REG8(IT83XX_ADC_BASE + 0x4D) +#define IT83XX_ADC_CMP2THRDATL REG8(IT83XX_ADC_BASE + 0x4E) +#define IT83XX_ADC_VCH13CTL REG8(IT83XX_ADC_BASE + 0x60) +#define IT83XX_ADC_VCH13DATM REG8(IT83XX_ADC_BASE + 0x61) +#define IT83XX_ADC_VCH13DATL REG8(IT83XX_ADC_BASE + 0x62) +#define IT83XX_ADC_VCH14CTL REG8(IT83XX_ADC_BASE + 0x63) +#define IT83XX_ADC_VCH14DATM REG8(IT83XX_ADC_BASE + 0x64) +#define IT83XX_ADC_VCH14DATL REG8(IT83XX_ADC_BASE + 0x65) +#define IT83XX_ADC_VCH15CTL REG8(IT83XX_ADC_BASE + 0x66) +#define IT83XX_ADC_VCH15DATM REG8(IT83XX_ADC_BASE + 0x67) +#define IT83XX_ADC_VCH15DATL REG8(IT83XX_ADC_BASE + 0x68) +#define IT83XX_ADC_VCH16CTL REG8(IT83XX_ADC_BASE + 0x69) +#define IT83XX_ADC_VCH16DATM REG8(IT83XX_ADC_BASE + 0x6A) +#define IT83XX_ADC_VCH16DATL REG8(IT83XX_ADC_BASE + 0x6B) +#define IT83XX_ADC_ADCDVSTS2 REG8(IT83XX_ADC_BASE + 0x6C) +#define IT83XX_ADC_VCMPSTS2 REG8(IT83XX_ADC_BASE + 0x6D) +#define IT83XX_ADC_VCMP3CTL REG8(IT83XX_ADC_BASE + 0x6E) +#define IT83XX_ADC_CMP3THRDATM REG8(IT83XX_ADC_BASE + 0x6F) +#define IT83XX_ADC_CMP3THRDATL REG8(IT83XX_ADC_BASE + 0x70) +#define IT83XX_ADC_VCMP4CTL REG8(IT83XX_ADC_BASE + 0x71) +#define IT83XX_ADC_CMP4THRDATM REG8(IT83XX_ADC_BASE + 0x72) +#define IT83XX_ADC_CMP4THRDATL REG8(IT83XX_ADC_BASE + 0x73) +#define IT83XX_ADC_VCMP5CTL REG8(IT83XX_ADC_BASE + 0x74) +#define IT83XX_ADC_CMP5THRDATM REG8(IT83XX_ADC_BASE + 0x75) +#define IT83XX_ADC_CMP5THRDATL REG8(IT83XX_ADC_BASE + 0x76) +#define IT83XX_ADC_VCMP0CSELM REG8(IT83XX_ADC_BASE + 0x77) +#define ADC_VCMP_VCMPCSELM BIT(0) +#define IT83XX_ADC_VCMP1CSELM REG8(IT83XX_ADC_BASE + 0x78) +#define IT83XX_ADC_VCMP2CSELM REG8(IT83XX_ADC_BASE + 0x79) +#define IT83XX_ADC_VCMP3CSELM REG8(IT83XX_ADC_BASE + 0x7A) +#define IT83XX_ADC_VCMP4CSELM REG8(IT83XX_ADC_BASE + 0x7B) +#define IT83XX_ADC_VCMP5CSELM REG8(IT83XX_ADC_BASE + 0x7C) /* Digital to Analog Converter (DAC) */ -#define IT83XX_DAC_BASE 0x00F01A00 +#define IT83XX_DAC_BASE 0x00F01A00 -#define IT83XX_DAC_DACPDREG REG8(IT83XX_DAC_BASE+0x01) -#define IT83XX_DAC_POWDN(ch) BIT(ch) -#define IT83XX_DAC_DACDAT(ch) REG8(IT83XX_DAC_BASE+0x02+ch) +#define IT83XX_DAC_DACPDREG REG8(IT83XX_DAC_BASE + 0x01) +#define IT83XX_DAC_POWDN(ch) BIT(ch) +#define IT83XX_DAC_DACDAT(ch) REG8(IT83XX_DAC_BASE + 0x02 + ch) /* Keyboard Controller (KBC) */ -#define IT83XX_KBC_BASE 0x00F01300 +#define IT83XX_KBC_BASE 0x00F01300 -#define IT83XX_KBC_KBHICR REG8(IT83XX_KBC_BASE+0x00) -#define IT83XX_KBC_KBIRQR REG8(IT83XX_KBC_BASE+0x02) -#define IT83XX_KBC_KBHISR REG8(IT83XX_KBC_BASE+0x04) -#define IT83XX_KBC_KBHIKDOR REG8(IT83XX_KBC_BASE+0x06) -#define IT83XX_KBC_KBHIMDOR REG8(IT83XX_KBC_BASE+0x08) -#define IT83XX_KBC_KBHIDIR REG8(IT83XX_KBC_BASE+0x0A) +#define IT83XX_KBC_KBHICR REG8(IT83XX_KBC_BASE + 0x00) +#define IT83XX_KBC_KBIRQR REG8(IT83XX_KBC_BASE + 0x02) +#define IT83XX_KBC_KBHISR REG8(IT83XX_KBC_BASE + 0x04) +#define IT83XX_KBC_KBHIKDOR REG8(IT83XX_KBC_BASE + 0x06) +#define IT83XX_KBC_KBHIMDOR REG8(IT83XX_KBC_BASE + 0x08) +#define IT83XX_KBC_KBHIDIR REG8(IT83XX_KBC_BASE + 0x0A) /* Power Management Channel (PMC) */ -#define IT83XX_PMC_BASE 0x00F01500 - -#define IT83XX_PMC_PM1STS REG8(IT83XX_PMC_BASE+0x00) -#define IT83XX_PMC_PM1DO REG8(IT83XX_PMC_BASE+0x01) -#define IT83XX_PMC_PM1DOSCI REG8(IT83XX_PMC_BASE+0x02) -#define IT83XX_PMC_PM1DOSMI REG8(IT83XX_PMC_BASE+0x03) -#define IT83XX_PMC_PM1DI REG8(IT83XX_PMC_BASE+0x04) -#define IT83XX_PMC_PM1DISCI REG8(IT83XX_PMC_BASE+0x05) -#define IT83XX_PMC_PM1CTL REG8(IT83XX_PMC_BASE+0x06) -#define IT83XX_PMC_PM1IC REG8(IT83XX_PMC_BASE+0x07) -#define IT83XX_PMC_PM1IE REG8(IT83XX_PMC_BASE+0x08) -#define IT83XX_PMC_PM2STS REG8(IT83XX_PMC_BASE+0x10) -#define IT83XX_PMC_PM2DO REG8(IT83XX_PMC_BASE+0x11) -#define IT83XX_PMC_PM2DOSCI REG8(IT83XX_PMC_BASE+0x12) -#define IT83XX_PMC_PM2DOSMI REG8(IT83XX_PMC_BASE+0x13) -#define IT83XX_PMC_PM2DI REG8(IT83XX_PMC_BASE+0x14) -#define IT83XX_PMC_PM2DISCI REG8(IT83XX_PMC_BASE+0x15) -#define IT83XX_PMC_PM2CTL REG8(IT83XX_PMC_BASE+0x16) -#define IT83XX_PMC_PM2IC REG8(IT83XX_PMC_BASE+0x17) -#define IT83XX_PMC_PM2IE REG8(IT83XX_PMC_BASE+0x18) -#define IT83XX_PMC_PM3STS REG8(IT83XX_PMC_BASE+0x20) -#define IT83XX_PMC_PM3DO REG8(IT83XX_PMC_BASE+0x21) -#define IT83XX_PMC_PM3DI REG8(IT83XX_PMC_BASE+0x22) -#define IT83XX_PMC_PM3CTL REG8(IT83XX_PMC_BASE+0x23) -#define IT83XX_PMC_PM3IC REG8(IT83XX_PMC_BASE+0x24) -#define IT83XX_PMC_PM3IE REG8(IT83XX_PMC_BASE+0x25) -#define IT83XX_PMC_PM4STS REG8(IT83XX_PMC_BASE+0x30) -#define IT83XX_PMC_PM4DO REG8(IT83XX_PMC_BASE+0x31) -#define IT83XX_PMC_PM4DI REG8(IT83XX_PMC_BASE+0x32) -#define IT83XX_PMC_PM4CTL REG8(IT83XX_PMC_BASE+0x33) -#define IT83XX_PMC_PM4IC REG8(IT83XX_PMC_BASE+0x34) -#define IT83XX_PMC_PM4IE REG8(IT83XX_PMC_BASE+0x35) -#define IT83XX_PMC_PM5STS REG8(IT83XX_PMC_BASE+0x40) -#define IT83XX_PMC_PM5DO REG8(IT83XX_PMC_BASE+0x41) -#define IT83XX_PMC_PM5DI REG8(IT83XX_PMC_BASE+0x42) -#define IT83XX_PMC_PM5CTL REG8(IT83XX_PMC_BASE+0x43) -#define IT83XX_PMC_PM5IC REG8(IT83XX_PMC_BASE+0x44) -#define IT83XX_PMC_PM5IE REG8(IT83XX_PMC_BASE+0x45) -#define IT83XX_PMC_MBXCTRL REG8(IT83XX_PMC_BASE+0x19) -#define IT83XX_PMC_MBXEC_00 REG8(IT83XX_PMC_BASE+0xF0) -#define IT83XX_PMC_MBXEC_01 REG8(IT83XX_PMC_BASE+0xF1) -#define IT83XX_PMC_MBXEC_02 REG8(IT83XX_PMC_BASE+0xF2) -#define IT83XX_PMC_MBXEC_03 REG8(IT83XX_PMC_BASE+0xF3) -#define IT83XX_PMC_MBXEC_04 REG8(IT83XX_PMC_BASE+0xF4) -#define IT83XX_PMC_MBXEC_05 REG8(IT83XX_PMC_BASE+0xF5) -#define IT83XX_PMC_MBXEC_06 REG8(IT83XX_PMC_BASE+0xF6) -#define IT83XX_PMC_MBXEC_07 REG8(IT83XX_PMC_BASE+0xF7) -#define IT83XX_PMC_MBXEC_08 REG8(IT83XX_PMC_BASE+0xF8) -#define IT83XX_PMC_MBXEC_09 REG8(IT83XX_PMC_BASE+0xF9) -#define IT83XX_PMC_MBXEC_10 REG8(IT83XX_PMC_BASE+0xFA) -#define IT83XX_PMC_MBXEC_11 REG8(IT83XX_PMC_BASE+0xFB) -#define IT83XX_PMC_MBXEC_12 REG8(IT83XX_PMC_BASE+0xFC) -#define IT83XX_PMC_MBXEC_13 REG8(IT83XX_PMC_BASE+0xFD) -#define IT83XX_PMC_MBXEC_14 REG8(IT83XX_PMC_BASE+0xFE) -#define IT83XX_PMC_MBXEC_15 REG8(IT83XX_PMC_BASE+0xFF) -#define IT83XX_PMC_PMSTS(ch) REG8(IT83XX_PMC_BASE + 0x00 + (ch << 4)) -#define IT83XX_PMC_PMDO(ch) REG8(IT83XX_PMC_BASE + 0x01 + (ch << 4)) -#define IT83XX_PMC_PMDI(ch) \ -REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 2 : 4) + (ch << 4)) -#define IT83XX_PMC_PMCTL(ch) \ -REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 3 : 6) + (ch << 4)) -#define IT83XX_PMC_PMIE(ch) \ -REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 5 : 8) + (ch << 4)) +#define IT83XX_PMC_BASE 0x00F01500 + +#define IT83XX_PMC_PM1STS REG8(IT83XX_PMC_BASE + 0x00) +#define IT83XX_PMC_PM1DO REG8(IT83XX_PMC_BASE + 0x01) +#define IT83XX_PMC_PM1DOSCI REG8(IT83XX_PMC_BASE + 0x02) +#define IT83XX_PMC_PM1DOSMI REG8(IT83XX_PMC_BASE + 0x03) +#define IT83XX_PMC_PM1DI REG8(IT83XX_PMC_BASE + 0x04) +#define IT83XX_PMC_PM1DISCI REG8(IT83XX_PMC_BASE + 0x05) +#define IT83XX_PMC_PM1CTL REG8(IT83XX_PMC_BASE + 0x06) +#define IT83XX_PMC_PM1IC REG8(IT83XX_PMC_BASE + 0x07) +#define IT83XX_PMC_PM1IE REG8(IT83XX_PMC_BASE + 0x08) +#define IT83XX_PMC_PM2STS REG8(IT83XX_PMC_BASE + 0x10) +#define IT83XX_PMC_PM2DO REG8(IT83XX_PMC_BASE + 0x11) +#define IT83XX_PMC_PM2DOSCI REG8(IT83XX_PMC_BASE + 0x12) +#define IT83XX_PMC_PM2DOSMI REG8(IT83XX_PMC_BASE + 0x13) +#define IT83XX_PMC_PM2DI REG8(IT83XX_PMC_BASE + 0x14) +#define IT83XX_PMC_PM2DISCI REG8(IT83XX_PMC_BASE + 0x15) +#define IT83XX_PMC_PM2CTL REG8(IT83XX_PMC_BASE + 0x16) +#define IT83XX_PMC_PM2IC REG8(IT83XX_PMC_BASE + 0x17) +#define IT83XX_PMC_PM2IE REG8(IT83XX_PMC_BASE + 0x18) +#define IT83XX_PMC_PM3STS REG8(IT83XX_PMC_BASE + 0x20) +#define IT83XX_PMC_PM3DO REG8(IT83XX_PMC_BASE + 0x21) +#define IT83XX_PMC_PM3DI REG8(IT83XX_PMC_BASE + 0x22) +#define IT83XX_PMC_PM3CTL REG8(IT83XX_PMC_BASE + 0x23) +#define IT83XX_PMC_PM3IC REG8(IT83XX_PMC_BASE + 0x24) +#define IT83XX_PMC_PM3IE REG8(IT83XX_PMC_BASE + 0x25) +#define IT83XX_PMC_PM4STS REG8(IT83XX_PMC_BASE + 0x30) +#define IT83XX_PMC_PM4DO REG8(IT83XX_PMC_BASE + 0x31) +#define IT83XX_PMC_PM4DI REG8(IT83XX_PMC_BASE + 0x32) +#define IT83XX_PMC_PM4CTL REG8(IT83XX_PMC_BASE + 0x33) +#define IT83XX_PMC_PM4IC REG8(IT83XX_PMC_BASE + 0x34) +#define IT83XX_PMC_PM4IE REG8(IT83XX_PMC_BASE + 0x35) +#define IT83XX_PMC_PM5STS REG8(IT83XX_PMC_BASE + 0x40) +#define IT83XX_PMC_PM5DO REG8(IT83XX_PMC_BASE + 0x41) +#define IT83XX_PMC_PM5DI REG8(IT83XX_PMC_BASE + 0x42) +#define IT83XX_PMC_PM5CTL REG8(IT83XX_PMC_BASE + 0x43) +#define IT83XX_PMC_PM5IC REG8(IT83XX_PMC_BASE + 0x44) +#define IT83XX_PMC_PM5IE REG8(IT83XX_PMC_BASE + 0x45) +#define IT83XX_PMC_MBXCTRL REG8(IT83XX_PMC_BASE + 0x19) +#define IT83XX_PMC_MBXEC_00 REG8(IT83XX_PMC_BASE + 0xF0) +#define IT83XX_PMC_MBXEC_01 REG8(IT83XX_PMC_BASE + 0xF1) +#define IT83XX_PMC_MBXEC_02 REG8(IT83XX_PMC_BASE + 0xF2) +#define IT83XX_PMC_MBXEC_03 REG8(IT83XX_PMC_BASE + 0xF3) +#define IT83XX_PMC_MBXEC_04 REG8(IT83XX_PMC_BASE + 0xF4) +#define IT83XX_PMC_MBXEC_05 REG8(IT83XX_PMC_BASE + 0xF5) +#define IT83XX_PMC_MBXEC_06 REG8(IT83XX_PMC_BASE + 0xF6) +#define IT83XX_PMC_MBXEC_07 REG8(IT83XX_PMC_BASE + 0xF7) +#define IT83XX_PMC_MBXEC_08 REG8(IT83XX_PMC_BASE + 0xF8) +#define IT83XX_PMC_MBXEC_09 REG8(IT83XX_PMC_BASE + 0xF9) +#define IT83XX_PMC_MBXEC_10 REG8(IT83XX_PMC_BASE + 0xFA) +#define IT83XX_PMC_MBXEC_11 REG8(IT83XX_PMC_BASE + 0xFB) +#define IT83XX_PMC_MBXEC_12 REG8(IT83XX_PMC_BASE + 0xFC) +#define IT83XX_PMC_MBXEC_13 REG8(IT83XX_PMC_BASE + 0xFD) +#define IT83XX_PMC_MBXEC_14 REG8(IT83XX_PMC_BASE + 0xFE) +#define IT83XX_PMC_MBXEC_15 REG8(IT83XX_PMC_BASE + 0xFF) +#define IT83XX_PMC_PMSTS(ch) REG8(IT83XX_PMC_BASE + 0x00 + (ch << 4)) +#define IT83XX_PMC_PMDO(ch) REG8(IT83XX_PMC_BASE + 0x01 + (ch << 4)) +#define IT83XX_PMC_PMDI(ch) \ + REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 2 : 4) + (ch << 4)) +#define IT83XX_PMC_PMCTL(ch) \ + REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 3 : 6) + (ch << 4)) +#define IT83XX_PMC_PMIE(ch) \ + REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 5 : 8) + (ch << 4)) /* Keyboard Matrix Scan control (KBS) */ -#define IT83XX_KBS_BASE 0x00F01D00 - -#define IT83XX_KBS_KSOL REG8(IT83XX_KBS_BASE+0x00) -#define IT83XX_KBS_KSOH1 REG8(IT83XX_KBS_BASE+0x01) -#define IT83XX_KBS_KSOCTRL REG8(IT83XX_KBS_BASE+0x02) -#define IT83XX_KBS_KSOH2 REG8(IT83XX_KBS_BASE+0x03) -#define IT83XX_KBS_KSI REG8(IT83XX_KBS_BASE+0x04) -#define IT83XX_KBS_KSICTRL REG8(IT83XX_KBS_BASE+0x05) -#define IT83XX_KBS_KSIGCTRL REG8(IT83XX_KBS_BASE+0x06) -#define IT83XX_KBS_KSIGOEN REG8(IT83XX_KBS_BASE+0x07) -#define IT83XX_KBS_KSIGDAT REG8(IT83XX_KBS_BASE+0x08) -#define IT83XX_KBS_KSIGDMRR REG8(IT83XX_KBS_BASE+0x09) -#define IT83XX_KBS_KSOHGCTRL REG8(IT83XX_KBS_BASE+0x0A) -#define IT83XX_KBS_KSOHGOEN REG8(IT83XX_KBS_BASE+0x0B) -#define IT83XX_KBS_KSOHGDMRR REG8(IT83XX_KBS_BASE+0x0C) -#define IT83XX_KBS_KSOLGCTRL REG8(IT83XX_KBS_BASE+0x0D) -#define IT83XX_KBS_KSOLGOEN REG8(IT83XX_KBS_BASE+0x0E) -#define IT83XX_KBS_KSOLGDMRR REG8(IT83XX_KBS_BASE+0x0F) -#define IT83XX_KBS_KSO0LSDR REG8(IT83XX_KBS_BASE+0x10) -#define IT83XX_KBS_KSO1LSDR REG8(IT83XX_KBS_BASE+0x11) -#define IT83XX_KBS_KSO2LSDR REG8(IT83XX_KBS_BASE+0x12) -#define IT83XX_KBS_KSO3LSDR REG8(IT83XX_KBS_BASE+0x13) -#define IT83XX_KBS_KSO4LSDR REG8(IT83XX_KBS_BASE+0x14) -#define IT83XX_KBS_KSO5LSDR REG8(IT83XX_KBS_BASE+0x15) -#define IT83XX_KBS_KSO6LSDR REG8(IT83XX_KBS_BASE+0x16) -#define IT83XX_KBS_KSO7LSDR REG8(IT83XX_KBS_BASE+0x17) -#define IT83XX_KBS_KSO8LSDR REG8(IT83XX_KBS_BASE+0x18) -#define IT83XX_KBS_KSO9LSDR REG8(IT83XX_KBS_BASE+0x19) -#define IT83XX_KBS_KSO10LSDR REG8(IT83XX_KBS_BASE+0x1A) -#define IT83XX_KBS_KSO11LSDR REG8(IT83XX_KBS_BASE+0x1B) -#define IT83XX_KBS_KSO12LSDR REG8(IT83XX_KBS_BASE+0x1C) -#define IT83XX_KBS_KSO13LSDR REG8(IT83XX_KBS_BASE+0x1D) -#define IT83XX_KBS_KSO14LSDR REG8(IT83XX_KBS_BASE+0x1E) -#define IT83XX_KBS_KSO15LSDR REG8(IT83XX_KBS_BASE+0x1F) -#define IT83XX_KBS_KSO16LSDR REG8(IT83XX_KBS_BASE+0x20) -#define IT83XX_KBS_KSO17LSDR REG8(IT83XX_KBS_BASE+0x21) -#define IT83XX_KBS_SDC1R REG8(IT83XX_KBS_BASE+0x22) -#define IT83XX_KBS_SDC2R REG8(IT83XX_KBS_BASE+0x23) -#define IT83XX_KBS_SDC3R REG8(IT83XX_KBS_BASE+0x24) -#define IT83XX_KBS_SDSR REG8(IT83XX_KBS_BASE+0x25) +#define IT83XX_KBS_BASE 0x00F01D00 + +#define IT83XX_KBS_KSOL REG8(IT83XX_KBS_BASE + 0x00) +#define IT83XX_KBS_KSOH1 REG8(IT83XX_KBS_BASE + 0x01) +#define IT83XX_KBS_KSOCTRL REG8(IT83XX_KBS_BASE + 0x02) +#define IT83XX_KBS_KSOH2 REG8(IT83XX_KBS_BASE + 0x03) +#define IT83XX_KBS_KSI REG8(IT83XX_KBS_BASE + 0x04) +#define IT83XX_KBS_KSICTRL REG8(IT83XX_KBS_BASE + 0x05) +#define IT83XX_KBS_KSIGCTRL REG8(IT83XX_KBS_BASE + 0x06) +#define IT83XX_KBS_KSIGOEN REG8(IT83XX_KBS_BASE + 0x07) +#define IT83XX_KBS_KSIGDAT REG8(IT83XX_KBS_BASE + 0x08) +#define IT83XX_KBS_KSIGDMRR REG8(IT83XX_KBS_BASE + 0x09) +#define IT83XX_KBS_KSOHGCTRL REG8(IT83XX_KBS_BASE + 0x0A) +#define IT83XX_KBS_KSOHGOEN REG8(IT83XX_KBS_BASE + 0x0B) +#define IT83XX_KBS_KSOHGDMRR REG8(IT83XX_KBS_BASE + 0x0C) +#define IT83XX_KBS_KSOLGCTRL REG8(IT83XX_KBS_BASE + 0x0D) +#define IT83XX_KBS_KSOLGOEN REG8(IT83XX_KBS_BASE + 0x0E) +#define IT83XX_KBS_KSOLGDMRR REG8(IT83XX_KBS_BASE + 0x0F) +#define IT83XX_KBS_KSO0LSDR REG8(IT83XX_KBS_BASE + 0x10) +#define IT83XX_KBS_KSO1LSDR REG8(IT83XX_KBS_BASE + 0x11) +#define IT83XX_KBS_KSO2LSDR REG8(IT83XX_KBS_BASE + 0x12) +#define IT83XX_KBS_KSO3LSDR REG8(IT83XX_KBS_BASE + 0x13) +#define IT83XX_KBS_KSO4LSDR REG8(IT83XX_KBS_BASE + 0x14) +#define IT83XX_KBS_KSO5LSDR REG8(IT83XX_KBS_BASE + 0x15) +#define IT83XX_KBS_KSO6LSDR REG8(IT83XX_KBS_BASE + 0x16) +#define IT83XX_KBS_KSO7LSDR REG8(IT83XX_KBS_BASE + 0x17) +#define IT83XX_KBS_KSO8LSDR REG8(IT83XX_KBS_BASE + 0x18) +#define IT83XX_KBS_KSO9LSDR REG8(IT83XX_KBS_BASE + 0x19) +#define IT83XX_KBS_KSO10LSDR REG8(IT83XX_KBS_BASE + 0x1A) +#define IT83XX_KBS_KSO11LSDR REG8(IT83XX_KBS_BASE + 0x1B) +#define IT83XX_KBS_KSO12LSDR REG8(IT83XX_KBS_BASE + 0x1C) +#define IT83XX_KBS_KSO13LSDR REG8(IT83XX_KBS_BASE + 0x1D) +#define IT83XX_KBS_KSO14LSDR REG8(IT83XX_KBS_BASE + 0x1E) +#define IT83XX_KBS_KSO15LSDR REG8(IT83XX_KBS_BASE + 0x1F) +#define IT83XX_KBS_KSO16LSDR REG8(IT83XX_KBS_BASE + 0x20) +#define IT83XX_KBS_KSO17LSDR REG8(IT83XX_KBS_BASE + 0x21) +#define IT83XX_KBS_SDC1R REG8(IT83XX_KBS_BASE + 0x22) +#define IT83XX_KBS_SDC2R REG8(IT83XX_KBS_BASE + 0x23) +#define IT83XX_KBS_SDC3R REG8(IT83XX_KBS_BASE + 0x24) +#define IT83XX_KBS_SDSR REG8(IT83XX_KBS_BASE + 0x25) +#define IT83XX_KBS_KSIGPODR REG8(IT83XX_KBS_BASE + 0x26) +#define IT83XX_KBS_KSOHGPODR REG8(IT83XX_KBS_BASE + 0x27) +#define IT83XX_KBS_KSOLGPODR REG8(IT83XX_KBS_BASE + 0x28) /* Shared Memory Flash Interface Bridge (SMFI) */ -#define IT83XX_SMFI_BASE 0x00F01000 - -#define IT83XX_SMFI_SMECCS REG8(IT83XX_SMFI_BASE+0x20) -#define IT83XX_SMFI_MASK_HOSTWA BIT(5) -#define IT83XX_SMFI_HRAMWC REG8(IT83XX_SMFI_BASE+0x5A) -#define IT83XX_SMFI_HRAMW0BA REG8(IT83XX_SMFI_BASE+0x5B) -#define IT83XX_SMFI_HRAMW1BA REG8(IT83XX_SMFI_BASE+0x5C) -#define IT83XX_SMFI_HRAMW0AAS REG8(IT83XX_SMFI_BASE+0x5D) -#define IT83XX_SMFI_HRAMW1AAS REG8(IT83XX_SMFI_BASE+0x5E) -#define IT83XX_SMFI_HRAMW2BA REG8(IT83XX_SMFI_BASE+0x76) -#define IT83XX_SMFI_HRAMW3BA REG8(IT83XX_SMFI_BASE+0x77) -#define IT83XX_SMFI_HRAMW2AAS REG8(IT83XX_SMFI_BASE+0x78) -#define IT83XX_SMFI_HRAMW3AAS REG8(IT83XX_SMFI_BASE+0x79) -#define IT83XX_SMFI_H2RAMECSIE REG8(IT83XX_SMFI_BASE+0x7A) -#define IT83XX_SMFI_H2RAMECSA REG8(IT83XX_SMFI_BASE+0x7B) -#define IT83XX_SMFI_H2RAMHSS REG8(IT83XX_SMFI_BASE+0x7C) -#define IT83XX_SMFI_ECINDAR0 REG8(IT83XX_SMFI_BASE+0x3B) -#define IT83XX_SMFI_ECINDAR1 REG8(IT83XX_SMFI_BASE+0x3C) -#define IT83XX_SMFI_ECINDAR2 REG8(IT83XX_SMFI_BASE+0x3D) -#define IT83XX_SMFI_ECINDAR3 REG8(IT83XX_SMFI_BASE+0x3E) +#define IT83XX_SMFI_BASE 0x00F01000 + +#define IT83XX_SMFI_SMECCS REG8(IT83XX_SMFI_BASE + 0x20) +#define IT83XX_SMFI_MASK_HOSTWA BIT(5) +#define IT83XX_SMFI_HRAMWC REG8(IT83XX_SMFI_BASE + 0x5A) +#define IT83XX_SMFI_HRAMW0BA REG8(IT83XX_SMFI_BASE + 0x5B) +#define IT83XX_SMFI_HRAMW1BA REG8(IT83XX_SMFI_BASE + 0x5C) +#define IT83XX_SMFI_HRAMW0AAS REG8(IT83XX_SMFI_BASE + 0x5D) +#define IT83XX_SMFI_HRAMW1AAS REG8(IT83XX_SMFI_BASE + 0x5E) +#define IT83XX_SMFI_HRAMW2BA REG8(IT83XX_SMFI_BASE + 0x76) +#define IT83XX_SMFI_HRAMW3BA REG8(IT83XX_SMFI_BASE + 0x77) +#define IT83XX_SMFI_HRAMW2AAS REG8(IT83XX_SMFI_BASE + 0x78) +#define IT83XX_SMFI_HRAMW3AAS REG8(IT83XX_SMFI_BASE + 0x79) +#define IT83XX_SMFI_H2RAMECSIE REG8(IT83XX_SMFI_BASE + 0x7A) +#define IT83XX_SMFI_H2RAMECSA REG8(IT83XX_SMFI_BASE + 0x7B) +#define IT83XX_SMFI_H2RAMHSS REG8(IT83XX_SMFI_BASE + 0x7C) +#define IT83XX_SMFI_ECINDAR0 REG8(IT83XX_SMFI_BASE + 0x3B) +#define IT83XX_SMFI_ECINDAR1 REG8(IT83XX_SMFI_BASE + 0x3C) +#define IT83XX_SMFI_ECINDAR2 REG8(IT83XX_SMFI_BASE + 0x3D) +#define IT83XX_SMFI_ECINDAR3 REG8(IT83XX_SMFI_BASE + 0x3E) #define EC_INDIRECT_READ_INTERNAL_FLASH BIT(6) -#define IT83XX_SMFI_ECINDDR REG8(IT83XX_SMFI_BASE+0x3F) -#define IT83XX_SMFI_SCAR2L REG8(IT83XX_SMFI_BASE+0x46) -#define IT83XX_SMFI_SCAR2M REG8(IT83XX_SMFI_BASE+0x47) -#define IT83XX_SMFI_SCAR2H REG8(IT83XX_SMFI_BASE+0x48) -#define IT83XX_SMFI_FLHCTRL3R REG8(IT83XX_SMFI_BASE+0x63) -#define IT83XX_SMFI_STCDMACR REG8(IT83XX_SMFI_BASE+0x80) -#define IT83XX_SMFI_FLHCTRL6R REG8(IT83XX_SMFI_BASE+0xA2) +#define IT83XX_SMFI_ECINDDR REG8(IT83XX_SMFI_BASE + 0x3F) +#define IT83XX_SMFI_SCAR0L REG8(IT83XX_SMFI_BASE + 0x40) +#define IT83XX_SMFI_SCAR0M REG8(IT83XX_SMFI_BASE + 0x41) +#define IT83XX_SMFI_SCAR0H REG8(IT83XX_SMFI_BASE + 0x42) +#define IT83XX_SMFI_SCAR2L REG8(IT83XX_SMFI_BASE + 0x46) +#define IT83XX_SMFI_SCAR2M REG8(IT83XX_SMFI_BASE + 0x47) +#define IT83XX_SMFI_SCAR2H REG8(IT83XX_SMFI_BASE + 0x48) +#define IT83XX_SMFI_FLHCTRL3R REG8(IT83XX_SMFI_BASE + 0x63) +#define IT83XX_SMFI_STCDMACR REG8(IT83XX_SMFI_BASE + 0x80) +#define IT83XX_SMFI_FLHCTRL6R REG8(IT83XX_SMFI_BASE + 0xA2) /* Enable EC-indirect page program command */ #define IT83XX_SMFI_MASK_ECINDPP BIT(3) /* Serial Peripheral Interface (SSPI) */ -#define IT83XX_SSPI_BASE 0x00F02600 +#define IT83XX_SSPI_BASE 0x00F02600 -#define IT83XX_SSPI_SPIDATA REG8(IT83XX_SSPI_BASE+0x00) -#define IT83XX_SSPI_SPICTRL1 REG8(IT83XX_SSPI_BASE+0x01) -#define IT83XX_SSPI_SPICTRL2 REG8(IT83XX_SSPI_BASE+0x02) -#define IT83XX_SSPI_SPISTS REG8(IT83XX_SSPI_BASE+0x03) -#define IT83XX_SSPI_SPICTRL3 REG8(IT83XX_SSPI_BASE+0x04) +#define IT83XX_SSPI_SPIDATA REG8(IT83XX_SSPI_BASE + 0x00) +#define IT83XX_SSPI_SPICTRL1 REG8(IT83XX_SSPI_BASE + 0x01) +#define IT83XX_SSPI_SPICTRL2 REG8(IT83XX_SSPI_BASE + 0x02) +#define IT83XX_SSPI_SPISTS REG8(IT83XX_SSPI_BASE + 0x03) +#define IT83XX_SSPI_SPICTRL3 REG8(IT83XX_SSPI_BASE + 0x04) /* Serial Peripheral Interface (SPI) */ -#define IT83XX_SPI_BASE 0x00F03A00 - -#define IT83XX_SPI_SPISGCR REG8(IT83XX_SPI_BASE+0x00) -#define IT83XX_SPI_SPISCEN BIT(0) -#define IT83XX_SPI_TXRXFAR REG8(IT83XX_SPI_BASE+0x01) -#define IT83XX_SPI_CPURXF2A BIT(4) -#define IT83XX_SPI_CPURXF1A BIT(3) -#define IT83XX_SPI_CPUTFA BIT(1) -#define IT83XX_SPI_TXFCR REG8(IT83XX_SPI_BASE+0x02) -#define IT83XX_SPI_TXFCMR BIT(2) -#define IT83XX_SPI_TXFR BIT(1) -#define IT83XX_SPI_TXFS BIT(0) -#define IT83XX_SPI_GCR2 REG8(IT83XX_SPI_BASE+0x03) -#define IT83XX_SPI_RXF2OC BIT(4) -#define IT83XX_SPI_RXF1OC BIT(3) -#define IT83XX_SPI_RXFAR BIT(0) -#define IT83XX_SPI_IMR REG8(IT83XX_SPI_BASE+0x04) -#define IT83XX_SPI_RX_REACH BIT(5) -#define IT83XX_SPI_EDIM BIT(2) -#define IT83XX_SPI_ISR REG8(IT83XX_SPI_BASE+0x05) -#define IT83XX_SPI_ENDDETECTINT BIT(2) -#define IT83XX_SPI_RXFSR REG8(IT83XX_SPI_BASE+0x07) -#define IT83XX_SPI_RXFFSM (BIT(4) | BIT(3)) -#define IT83XX_SPI_RXF2FS BIT(2) -#define IT83XX_SPI_RXF1FS BIT(1) +#define IT83XX_SPI_BASE 0x00F03A00 + +#define IT83XX_SPI_SPISGCR REG8(IT83XX_SPI_BASE + 0x00) +#define IT83XX_SPI_SPISCEN BIT(0) +#define IT83XX_SPI_TXRXFAR REG8(IT83XX_SPI_BASE + 0x01) +#define IT83XX_SPI_CPURXF2A BIT(4) +#define IT83XX_SPI_CPURXF1A BIT(3) +#define IT83XX_SPI_CPUTFA BIT(1) +#define IT83XX_SPI_TXFCR REG8(IT83XX_SPI_BASE + 0x02) +#define IT83XX_SPI_TXFCMR BIT(2) +#define IT83XX_SPI_TXFR BIT(1) +#define IT83XX_SPI_TXFS BIT(0) +#define IT83XX_SPI_GCR2 REG8(IT83XX_SPI_BASE + 0x03) +#define IT83XX_SPI_RXF2OC BIT(4) +#define IT83XX_SPI_RXF1OC BIT(3) +#define IT83XX_SPI_RXFAR BIT(0) +#define IT83XX_SPI_IMR REG8(IT83XX_SPI_BASE + 0x04) +#define IT83XX_SPI_RX_FIFO_FULL BIT(7) +#define IT83XX_SPI_RX_REACH BIT(5) +#define IT83XX_SPI_EDIM BIT(2) +#define IT83XX_SPI_ISR REG8(IT83XX_SPI_BASE + 0x05) +#define IT83XX_SPI_TXFSR REG8(IT83XX_SPI_BASE + 0x06) +#define IT83XX_SPI_ENDDETECTINT BIT(2) +#define IT83XX_SPI_RXFSR REG8(IT83XX_SPI_BASE + 0x07) +#define IT83XX_SPI_RXFFSM (BIT(4) | BIT(3)) +#define IT83XX_SPI_RXF2FS BIT(2) +#define IT83XX_SPI_RXF1FS BIT(1) #ifdef CHIP_VARIANT_IT83202BX -#define IT83XX_SPI_SPISRDR REG8(IT83XX_SPI_BASE+0x08) +#define IT83XX_SPI_SPISRDR REG8(IT83XX_SPI_BASE + 0x08) #else -#define IT83XX_SPI_SPISRDR REG8(IT83XX_SPI_BASE+0x0b) +#define IT83XX_SPI_SPISRDR REG8(IT83XX_SPI_BASE + 0x0b) #endif -#define IT83XX_SPI_CPUWTFDB0 REG32(IT83XX_SPI_BASE+0x08) -#define IT83XX_SPI_FCR REG8(IT83XX_SPI_BASE+0x09) -#define IT83XX_SPI_SPISRTXF BIT(2) -#define IT83XX_SPI_RXFR BIT(1) -#define IT83XX_SPI_RXFCMR BIT(0) -#define IT83XX_SPI_RXFRDRB0 REG32(IT83XX_SPI_BASE+0x0C) -#define IT83XX_SPI_FTCB0R REG8(IT83XX_SPI_BASE+0x18) -#define IT83XX_SPI_FTCB1R REG8(IT83XX_SPI_BASE+0x19) -#define IT83XX_SPI_TCCB0 REG8(IT83XX_SPI_BASE+0x1A) -#define IT83XX_SPI_TCCB1 REG8(IT83XX_SPI_BASE+0x1B) -#define IT83XX_SPI_HPR2 REG8(IT83XX_SPI_BASE+0x1E) -#define IT83XX_SPI_RX_VLISMR REG8(IT83XX_SPI_BASE+0x26) -#define IT83XX_SPI_RVLIM BIT(0) -#define IT83XX_SPI_RX_VLISR REG8(IT83XX_SPI_BASE+0x27) -#define IT83XX_SPI_RVLI BIT(0) +#define IT83XX_SPI_CPUWTFDB0 REG32(IT83XX_SPI_BASE + 0x08) +#define IT83XX_SPI_FCR REG8(IT83XX_SPI_BASE + 0x09) +#define IT83XX_SPI_SPISRTXF BIT(2) +#define IT83XX_SPI_RXFR BIT(1) +#define IT83XX_SPI_RXFCMR BIT(0) +#define IT83XX_SPI_RXFRDRB0 REG32(IT83XX_SPI_BASE + 0x0C) +#define IT83XX_SPI_FTCB0R REG8(IT83XX_SPI_BASE + 0x18) +#define IT83XX_SPI_FTCB1R REG8(IT83XX_SPI_BASE + 0x19) +#define IT83XX_SPI_TCCB0 REG8(IT83XX_SPI_BASE + 0x1A) +#define IT83XX_SPI_TCCB1 REG8(IT83XX_SPI_BASE + 0x1B) +#define IT83XX_SPI_HPR2 REG8(IT83XX_SPI_BASE + 0x1E) +#define IT83XX_SPI_EMMCBMR REG8(IT83XX_SPI_BASE + 0x21) +#define IT83XX_SPI_EMMCABM BIT(1) /* eMMC Alternative Boot Mode */ +#define IT83XX_SPI_RX_VLISMR REG8(IT83XX_SPI_BASE + 0x26) +#define IT83XX_SPI_RVLIM BIT(0) +#define IT83XX_SPI_RX_VLISR REG8(IT83XX_SPI_BASE + 0x27) +#define IT83XX_SPI_RVLI BIT(0) /* Platform Environment Control Interface (PECI) */ -#define IT83XX_PECI_BASE 0x00F02C00 - -#define IT83XX_PECI_HOSTAR REG8(IT83XX_PECI_BASE+0x00) -#define IT83XX_PECI_HOCTLR REG8(IT83XX_PECI_BASE+0x01) -#define IT83XX_PECI_HOCMDR REG8(IT83XX_PECI_BASE+0x02) -#define IT83XX_PECI_HOTRADDR REG8(IT83XX_PECI_BASE+0x03) -#define IT83XX_PECI_HOWRLR REG8(IT83XX_PECI_BASE+0x04) -#define IT83XX_PECI_HORDLR REG8(IT83XX_PECI_BASE+0x05) -#define IT83XX_PECI_HOWRDR REG8(IT83XX_PECI_BASE+0x06) -#define IT83XX_PECI_HORDDR REG8(IT83XX_PECI_BASE+0x07) -#define IT83XX_PECI_HOCTL2R REG8(IT83XX_PECI_BASE+0x08) -#define IT83XX_PECI_RWFCSV REG8(IT83XX_PECI_BASE+0x09) -#define IT83XX_PECI_RRFCSV REG8(IT83XX_PECI_BASE+0x0A) -#define IT83XX_PECI_WFCSV REG8(IT83XX_PECI_BASE+0x0B) -#define IT83XX_PECI_RFCSV REG8(IT83XX_PECI_BASE+0x0C) -#define IT83XX_PECI_AWFCSV REG8(IT83XX_PECI_BASE+0x0D) -#define IT83XX_PECI_PADCTLR REG8(IT83XX_PECI_BASE+0x0E) +#define IT83XX_PECI_BASE 0x00F02C00 + +#define IT83XX_PECI_HOSTAR REG8(IT83XX_PECI_BASE + 0x00) +#define IT83XX_PECI_HOCTLR REG8(IT83XX_PECI_BASE + 0x01) +#define IT83XX_PECI_HOCMDR REG8(IT83XX_PECI_BASE + 0x02) +#define IT83XX_PECI_HOTRADDR REG8(IT83XX_PECI_BASE + 0x03) +#define IT83XX_PECI_HOWRLR REG8(IT83XX_PECI_BASE + 0x04) +#define IT83XX_PECI_HORDLR REG8(IT83XX_PECI_BASE + 0x05) +#define IT83XX_PECI_HOWRDR REG8(IT83XX_PECI_BASE + 0x06) +#define IT83XX_PECI_HORDDR REG8(IT83XX_PECI_BASE + 0x07) +#define IT83XX_PECI_HOCTL2R REG8(IT83XX_PECI_BASE + 0x08) +#define IT83XX_PECI_RWFCSV REG8(IT83XX_PECI_BASE + 0x09) +#define IT83XX_PECI_RRFCSV REG8(IT83XX_PECI_BASE + 0x0A) +#define IT83XX_PECI_WFCSV REG8(IT83XX_PECI_BASE + 0x0B) +#define IT83XX_PECI_RFCSV REG8(IT83XX_PECI_BASE + 0x0C) +#define IT83XX_PECI_AWFCSV REG8(IT83XX_PECI_BASE + 0x0D) +#define IT83XX_PECI_PADCTLR REG8(IT83XX_PECI_BASE + 0x0E) /* * The count number of the counter for 25 ms register. * The 25 ms register is calculated by (count number *1.024 kHz). */ -#define I2C_CLK_LOW_TIMEOUT 255 /* ~=249 ms */ +#define I2C_CLK_LOW_TIMEOUT 255 /* ~=249 ms */ /* SMBus/I2C Interface (SMB/I2C) */ -#define IT83XX_SMB_BASE 0x00F01C00 - -#define IT83XX_SMB_4P7USL REG8(IT83XX_SMB_BASE+0x00) -#define IT83XX_SMB_4P0USL REG8(IT83XX_SMB_BASE+0x01) -#define IT83XX_SMB_300NS REG8(IT83XX_SMB_BASE+0x02) -#define IT83XX_SMB_250NS REG8(IT83XX_SMB_BASE+0x03) -#define IT83XX_SMB_25MS REG8(IT83XX_SMB_BASE+0x04) -#define IT83XX_SMB_45P3USL REG8(IT83XX_SMB_BASE+0x05) -#define IT83XX_SMB_45P3USH REG8(IT83XX_SMB_BASE+0x06) -#define IT83XX_SMB_4P7A4P0H REG8(IT83XX_SMB_BASE+0x07) -#define IT83XX_SMB_SLVISELR REG8(IT83XX_SMB_BASE+0x08) -#define IT83XX_SMB_SCLKTS(ch) REG8(IT83XX_SMB_BASE+0x09+ch) -#define IT83XX_SMB_CHSEF REG8(IT83XX_SMB_BASE+0x11) -#define IT83XX_SMB_CHSAB REG8(IT83XX_SMB_BASE+0x20) -#define IT83XX_SMB_CHSCD REG8(IT83XX_SMB_BASE+0x21) -#define IT83XX_SMB_HOSTA(ch) REG8(IT83XX_SMB_BASE+0x40+(ch << 6)) -#define IT83XX_SMB_HOCTL(ch) REG8(IT83XX_SMB_BASE+0x41+(ch << 6)) -#define IT83XX_SMB_HOCMD(ch) REG8(IT83XX_SMB_BASE+0x42+(ch << 6)) -#define IT83XX_SMB_TRASLA(ch) REG8(IT83XX_SMB_BASE+0x43+(ch << 6)) -#define IT83XX_SMB_D0REG(ch) REG8(IT83XX_SMB_BASE+0x44+(ch << 6)) -#define IT83XX_SMB_D1REG(ch) REG8(IT83XX_SMB_BASE+0x45+(ch << 6)) -#define IT83XX_SMB_HOBDB(ch) REG8(IT83XX_SMB_BASE+0x46+(ch << 6)) -#define IT83XX_SMB_PECERC(ch) REG8(IT83XX_SMB_BASE+0x47+(ch << 6)) -#define IT83XX_SMB_SMBPCTL(ch) REG8(IT83XX_SMB_BASE+0x4A+(ch << 6)) -#define IT83XX_SMB_HOCTL2(ch) REG8(IT83XX_SMB_BASE+0x50+(ch << 6)) -#define IT83XX_SMB_SLVEN (1 << 5) -#define IT83XX_SMB_RESLADR REG8(IT83XX_SMB_BASE+0x48) -#define IT83XX_SMB_SLDA REG8(IT83XX_SMB_BASE+0x49) -#define IT83XX_SMB_SLSTA REG8(IT83XX_SMB_BASE+0x4B) -#define IT83XX_SMB_SPDS (1 << 5) -#define IT83XX_SMB_RCS (1 << 3) -#define IT83XX_SMB_STS (1 << 2) -#define IT83XX_SMB_SDS (1 << 1) -#define IT83XX_SMB_SICR REG8(IT83XX_SMB_BASE+0x4C) -#define IT83XX_SMB_RESLADR2 REG8(IT83XX_SMB_BASE+0x51) -#define IT83XX_SMB_ENADDR2 (1 << 7) -#define IT83XX_SMB_SFFCTL REG8(IT83XX_SMB_BASE+0x55) -#define IT83XX_SMB_SAFE (1 << 0) -#define IT83XX_SMB_SFFSTA REG8(IT83XX_SMB_BASE+0x56) -#define IT83XX_SMB_SFFFULL (1 << 6) +#define IT83XX_SMB_BASE 0x00F01C00 + +#define IT83XX_SMB_4P7USL REG8(IT83XX_SMB_BASE + 0x00) +#define IT83XX_SMB_4P0USL REG8(IT83XX_SMB_BASE + 0x01) +#define IT83XX_SMB_300NS REG8(IT83XX_SMB_BASE + 0x02) +#define IT83XX_SMB_250NS REG8(IT83XX_SMB_BASE + 0x03) +#define IT83XX_SMB_25MS REG8(IT83XX_SMB_BASE + 0x04) +#define IT83XX_SMB_45P3USL REG8(IT83XX_SMB_BASE + 0x05) +#define IT83XX_SMB_45P3USH REG8(IT83XX_SMB_BASE + 0x06) +#define IT83XX_SMB_4P7A4P0H REG8(IT83XX_SMB_BASE + 0x07) +#define IT83XX_SMB_SLVISELR REG8(IT83XX_SMB_BASE + 0x08) +#define IT83XX_SMB_SCLKTS(ch) REG8(IT83XX_SMB_BASE + 0x09 + ch) +#define IT83XX_SMB_CHSEF REG8(IT83XX_SMB_BASE + 0x11) +#define IT83XX_SMB_CHSAB REG8(IT83XX_SMB_BASE + 0x20) +#define IT83XX_SMB_CHSCD REG8(IT83XX_SMB_BASE + 0x21) +#define IT83XX_SMB_HOSTA(ch) REG8(IT83XX_SMB_BASE + 0x40 + (ch << 6)) +#define IT83XX_SMB_HOCTL(ch) REG8(IT83XX_SMB_BASE + 0x41 + (ch << 6)) +#define IT83XX_SMB_HOCMD(ch) REG8(IT83XX_SMB_BASE + 0x42 + (ch << 6)) +#define IT83XX_SMB_TRASLA(ch) REG8(IT83XX_SMB_BASE + 0x43 + (ch << 6)) +#define IT83XX_SMB_D0REG(ch) REG8(IT83XX_SMB_BASE + 0x44 + (ch << 6)) +#define IT83XX_SMB_D1REG(ch) REG8(IT83XX_SMB_BASE + 0x45 + (ch << 6)) +#define IT83XX_SMB_HOBDB(ch) REG8(IT83XX_SMB_BASE + 0x46 + (ch << 6)) +#define IT83XX_SMB_PECERC(ch) REG8(IT83XX_SMB_BASE + 0x47 + (ch << 6)) +#define IT83XX_SMB_SMBPCTL(ch) REG8(IT83XX_SMB_BASE + 0x4A + (ch << 6)) +#define IT83XX_SMB_HOCTL2(ch) REG8(IT83XX_SMB_BASE + 0x50 + (ch << 6)) +#define IT83XX_SMB_SLVEN (1 << 5) +#define IT83XX_SMB_RESLADR REG8(IT83XX_SMB_BASE + 0x48) +#define IT83XX_SMB_SLDA REG8(IT83XX_SMB_BASE + 0x49) +#define IT83XX_SMB_SLSTA REG8(IT83XX_SMB_BASE + 0x4B) +#define IT83XX_SMB_SPDS (1 << 5) +#define IT83XX_SMB_RCS (1 << 3) +#define IT83XX_SMB_STS (1 << 2) +#define IT83XX_SMB_SDS (1 << 1) +#define IT83XX_SMB_SICR REG8(IT83XX_SMB_BASE + 0x4C) +#define IT83XX_SMB_RESLADR2 REG8(IT83XX_SMB_BASE + 0x51) +#define IT83XX_SMB_ENADDR2 (1 << 7) +#define IT83XX_SMB_SFFCTL REG8(IT83XX_SMB_BASE + 0x55) +#define IT83XX_SMB_HSAPE BIT(1) +#define IT83XX_SMB_SAFE (1 << 0) +#define IT83XX_SMB_SFFSTA REG8(IT83XX_SMB_BASE + 0x56) +#define IT83XX_SMB_SFFFULL (1 << 6) /* BRAM */ -#define IT83XX_BRAM_BASE 0x00F02200 +#define IT83XX_BRAM_BASE 0x00F02200 /* offset 0 ~ 0x7f */ -#define IT83XX_BRAM_BANK0(i) REG8(IT83XX_BRAM_BASE + i) +#define IT83XX_BRAM_BANK0(i) REG8(IT83XX_BRAM_BASE + i) /* Battery backed RAM indices. */ enum bram_indices { /* reset flags uses 4 bytes */ @@ -1417,187 +1438,232 @@ enum bram_indices { BRAM_IDX_RESET_FLAGS3 = 3, /* PD state data for CONFIG_USB_PD_DUAL_ROLE uses 1 byte per port */ - BRAM_IDX_PD0 = 4, - BRAM_IDX_PD1 = 5, - BRAM_IDX_PD2 = 6, + BRAM_IDX_PD0 = 4, + BRAM_IDX_PD1 = 5, + BRAM_IDX_PD2 = 6, /* index 7 is reserved */ - BRAM_IDX_SCRATCHPAD0 = 8, - BRAM_IDX_SCRATCHPAD1 = 9, - BRAM_IDX_SCRATCHPAD2 = 0xa, - BRAM_IDX_SCRATCHPAD3 = 0xb, - /* index 0xc ~ 0xf are reserved */ + BRAM_IDX_SCRATCHPAD0 = 8, + BRAM_IDX_SCRATCHPAD1 = 9, + BRAM_IDX_SCRATCHPAD2 = 0xa, + BRAM_IDX_SCRATCHPAD3 = 0xb, - /* NVCONTEXT uses 16 bytes */ - BRAM_IDX_NVCONTEXT = 0x10, - BRAM_IDX_NVCONTEXT_END = 0x1F, + /* EC logs status */ + BRAM_IDX_EC_LOG_STATUS = 0xc, - /* offset 0x20 ~ 0x7b are reserved for future use. */ +/* offset 0x0d ~ 0x1f are reserved for future use. */ +#if defined(CONFIG_HOST_INTERFACE_LPC) || defined(CONFIG_HOST_INTERFACE_ESPI) + /* + * offset 0x20 ~ 0x7b are reserved for future use. + * (apply to x86 platform) + */ /* This field is used to indicate BRAM is valid or not. */ - BRAM_IDX_VALID_FLAGS0 = 0x7c, - BRAM_IDX_VALID_FLAGS1 = 0x7d, - BRAM_IDX_VALID_FLAGS2 = 0x7e, - BRAM_IDX_VALID_FLAGS3 = 0x7f - /* offset 0x7f is the end of BRAM bank 0. */ + BRAM_IDX_VALID_FLAGS0 = 0x7c, + BRAM_IDX_VALID_FLAGS1 = 0x7d, + BRAM_IDX_VALID_FLAGS2 = 0x7e, + BRAM_IDX_VALID_FLAGS3 = 0x7f +/* offset 0x7f is the end of BRAM bank 0. */ +#else + + /* panic data uses 144 bytes (offset 0x20 ~ 0xaf) */ + BRAM_PANIC_DATA_START = 0x20, + BRAM_PANIC_DATA_END = 0xaf, + + /* This field is used to indicate BRAM is valid or not. */ + BRAM_IDX_VALID_FLAGS0 = 0xbc, + BRAM_IDX_VALID_FLAGS1 = 0xbd, + BRAM_IDX_VALID_FLAGS2 = 0xbe, + BRAM_IDX_VALID_FLAGS3 = 0xbf +/* offset 0xbf is the end of BRAM bank 1. */ +#endif }; -#define BRAM_RESET_FLAGS0 IT83XX_BRAM_BANK0(BRAM_IDX_RESET_FLAGS0) -#define BRAM_RESET_FLAGS1 IT83XX_BRAM_BANK0(BRAM_IDX_RESET_FLAGS1) -#define BRAM_RESET_FLAGS2 IT83XX_BRAM_BANK0(BRAM_IDX_RESET_FLAGS2) -#define BRAM_RESET_FLAGS3 IT83XX_BRAM_BANK0(BRAM_IDX_RESET_FLAGS3) +#define BRAM_RESET_FLAGS0 IT83XX_BRAM_BANK0(BRAM_IDX_RESET_FLAGS0) +#define BRAM_RESET_FLAGS1 IT83XX_BRAM_BANK0(BRAM_IDX_RESET_FLAGS1) +#define BRAM_RESET_FLAGS2 IT83XX_BRAM_BANK0(BRAM_IDX_RESET_FLAGS2) +#define BRAM_RESET_FLAGS3 IT83XX_BRAM_BANK0(BRAM_IDX_RESET_FLAGS3) -#define BRAM_SCRATCHPAD0 IT83XX_BRAM_BANK0(BRAM_IDX_SCRATCHPAD0) -#define BRAM_SCRATCHPAD1 IT83XX_BRAM_BANK0(BRAM_IDX_SCRATCHPAD1) -#define BRAM_SCRATCHPAD2 IT83XX_BRAM_BANK0(BRAM_IDX_SCRATCHPAD2) -#define BRAM_SCRATCHPAD3 IT83XX_BRAM_BANK0(BRAM_IDX_SCRATCHPAD3) +#define BRAM_SCRATCHPAD0 IT83XX_BRAM_BANK0(BRAM_IDX_SCRATCHPAD0) +#define BRAM_SCRATCHPAD1 IT83XX_BRAM_BANK0(BRAM_IDX_SCRATCHPAD1) +#define BRAM_SCRATCHPAD2 IT83XX_BRAM_BANK0(BRAM_IDX_SCRATCHPAD2) +#define BRAM_SCRATCHPAD3 IT83XX_BRAM_BANK0(BRAM_IDX_SCRATCHPAD3) -#define BRAM_VALID_FLAGS0 IT83XX_BRAM_BANK0(BRAM_IDX_VALID_FLAGS0) -#define BRAM_VALID_FLAGS1 IT83XX_BRAM_BANK0(BRAM_IDX_VALID_FLAGS1) -#define BRAM_VALID_FLAGS2 IT83XX_BRAM_BANK0(BRAM_IDX_VALID_FLAGS2) -#define BRAM_VALID_FLAGS3 IT83XX_BRAM_BANK0(BRAM_IDX_VALID_FLAGS3) +#define BRAM_EC_LOG_STATUS IT83XX_BRAM_BANK0(BRAM_IDX_EC_LOG_STATUS) +enum bram_ec_logs_status { EC_LOG_SAVED_IN_FLASH = 1, EC_LOG_SAVED_IN_MEMORY }; -#define IT83XX_BRAM_BANK1(i) REG8(IT83XX_BRAM_BASE + 0x80 + i) +#define BRAM_VALID_FLAGS0 IT83XX_BRAM_BANK0(BRAM_IDX_VALID_FLAGS0) +#define BRAM_VALID_FLAGS1 IT83XX_BRAM_BANK0(BRAM_IDX_VALID_FLAGS1) +#define BRAM_VALID_FLAGS2 IT83XX_BRAM_BANK0(BRAM_IDX_VALID_FLAGS2) +#define BRAM_VALID_FLAGS3 IT83XX_BRAM_BANK0(BRAM_IDX_VALID_FLAGS3) + +/* + * These 128 bytes are use to latch port 80h data on x86 platform. + * And they will be used to save panic data if the GPG1 reset mechanism + * is enabled. + */ +#if defined(CONFIG_HOST_INTERFACE_LPC) || defined(CONFIG_HOST_INTERFACE_ESPI) +/* offset 0x80 ~ 0xbf */ +#define IT83XX_BRAM_BANK1(i) REG8(IT83XX_BRAM_BASE + 0x80 + i) +#else +/* Length of bram panic data */ +#define BRAM_PANIC_LEN (BRAM_PANIC_DATA_END - BRAM_PANIC_DATA_START + 1) +#endif /* * Enhanced SMBus/I2C Interface * Ch_D: 0x00F03680 , Ch_E: 0x00F03500 , Ch_F: 0x00F03580 * Ch_D: ch = 0x03 , Ch_E: ch = 0x00 , Ch_F: ch = 0x01 */ -#define IT83XX_I2C_BASE 0x00F03500 - -#define IT83XX_I2C_DRR(ch) REG8(IT83XX_I2C_BASE+0x00+(ch << 7)) -#define IT83XX_I2C_PSR(ch) REG8(IT83XX_I2C_BASE+0x01+(ch << 7)) -#define IT83XX_I2C_HSPR(ch) REG8(IT83XX_I2C_BASE+0x02+(ch << 7)) -#define IT83XX_I2C_STR(ch) REG8(IT83XX_I2C_BASE+0x03+(ch << 7)) -#define IT83XX_I2C_BB (1 << 5) -#define IT83XX_I2C_TIME_OUT (1 << 3) -#define IT83XX_I2C_RW (1 << 2) -#define IT83XX_I2C_INTPEND (1 << 1) -#define IT83XX_I2C_DHTR(ch) REG8(IT83XX_I2C_BASE+0x04+(ch << 7)) -#define IT83XX_I2C_TOR(ch) REG8(IT83XX_I2C_BASE+0x05+(ch << 7)) -#define IT83XX_I2C_DTR(ch) REG8(IT83XX_I2C_BASE+0x08+(ch << 7)) -#define IT83XX_I2C_CTR(ch) REG8(IT83XX_I2C_BASE+0x09+(ch << 7)) -#define IT83XX_I2C_INTEN (1 << 6) -#define IT83XX_I2C_MODE (1 << 5) -#define IT83XX_I2C_STARST (1 << 4) -#define IT83XX_I2C_ACK (1 << 3) -#define IT83XX_I2C_HALT (1 << 0) -#define IT83XX_I2C_CTR1(ch) REG8(IT83XX_I2C_BASE+0x0A+(ch << 7)) -#define IT83XX_I2C_COMQ_EN (1 << 7) -#define IT83XX_I2C_MDL_EN (1 << 1) -#define IT83XX_I2C_BYTE_CNT_L(ch) REG8(IT83XX_I2C_BASE+0x0C+(ch << 7)) -#define IT83XX_I2C_IRQ_ST(ch) REG8(IT83XX_I2C_BASE+0x0D+(ch << 7)) -#define IT83XX_I2C_IDW_CLR (1 << 3) -#define IT83XX_I2C_IDR_CLR (1 << 2) -#define IT83XX_I2C_SLVDATAFLG (1 << 1) -#define IT83XX_I2C_P_CLR (1 << 0) -#define IT83XX_I2C_IDR(ch) REG8(IT83XX_I2C_BASE+0x06+(ch << 7)) -#define IT83XX_I2C_TOS(ch) REG8(IT83XX_I2C_BASE+0x07+(ch << 7)) -#define IT83XX_I2C_CLK_STR (1 << 7) -#define IT83XX_I2C_IDR2(ch) REG8(IT83XX_I2C_BASE+0x1F+(ch << 7)) -#define IT83XX_I2C_RAMHA(ch) REG8(IT83XX_I2C_BASE+0x23+(ch << 7)) -#define IT83XX_I2C_RAMLA(ch) REG8(IT83XX_I2C_BASE+0x24+(ch << 7)) -#define IT83XX_I2C_RAMHA2(ch) REG8(IT83XX_I2C_BASE+0x2B+(ch << 7)) -#define IT83XX_I2C_RAMLA2(ch) REG8(IT83XX_I2C_BASE+0x2C+(ch << 7)) -#define IT83XX_I2C_CMD_ADDH(ch) REG8(IT83XX_I2C_BASE+0x25+(ch << 7)) -#define IT83XX_I2C_CMD_ADDL(ch) REG8(IT83XX_I2C_BASE+0x26+(ch << 7)) -#define IT83XX_I2C_RAMH2A(ch) REG8(IT83XX_I2C_BASE+0x50+(ch << 7)) -#define IT83XX_I2C_CMD_ADDH2(ch) REG8(IT83XX_I2C_BASE+0x52+(ch << 7)) +#define IT83XX_I2C_BASE 0x00F03500 + +#define IT83XX_I2C_DRR(ch) REG8(IT83XX_I2C_BASE + 0x00 + (ch << 7)) +#define IT83XX_I2C_PSR(ch) REG8(IT83XX_I2C_BASE + 0x01 + (ch << 7)) +#define IT83XX_I2C_HSPR(ch) REG8(IT83XX_I2C_BASE + 0x02 + (ch << 7)) +#define IT83XX_I2C_STR(ch) REG8(IT83XX_I2C_BASE + 0x03 + (ch << 7)) +#define IT83XX_I2C_BB (1 << 5) +#define IT83XX_I2C_TIME_OUT (1 << 3) +#define IT83XX_I2C_RW (1 << 2) +#define IT83XX_I2C_INTPEND (1 << 1) +#define IT83XX_I2C_DHTR(ch) REG8(IT83XX_I2C_BASE + 0x04 + (ch << 7)) +#define IT83XX_I2C_TOR(ch) REG8(IT83XX_I2C_BASE + 0x05 + (ch << 7)) +#define IT83XX_I2C_DTR(ch) REG8(IT83XX_I2C_BASE + 0x08 + (ch << 7)) +#define IT83XX_I2C_CTR(ch) REG8(IT83XX_I2C_BASE + 0x09 + (ch << 7)) +#define IT83XX_I2C_INTEN (1 << 6) +#define IT83XX_I2C_MODE (1 << 5) +#define IT83XX_I2C_STARST (1 << 4) +#define IT83XX_I2C_ACK (1 << 3) +#define IT83XX_I2C_HALT (1 << 0) +#define IT83XX_I2C_CTR1(ch) REG8(IT83XX_I2C_BASE + 0x0A + (ch << 7)) +#define IT83XX_I2C_COMQ_EN (1 << 7) +#define IT83XX_I2C_MDL_EN (1 << 1) +#define IT83XX_I2C_BYTE_CNT_L(ch) REG8(IT83XX_I2C_BASE + 0x0C + (ch << 7)) +#define IT83XX_I2C_IRQ_ST(ch) REG8(IT83XX_I2C_BASE + 0x0D + (ch << 7)) +#define IT83XX_I2C_IDW_CLR (1 << 3) +#define IT83XX_I2C_IDR_CLR (1 << 2) +#define IT83XX_I2C_SLVDATAFLG (1 << 1) +#define IT83XX_I2C_P_CLR (1 << 0) +#define IT83XX_I2C_IDR(ch) REG8(IT83XX_I2C_BASE + 0x06 + (ch << 7)) +#define IT83XX_I2C_TOS(ch) REG8(IT83XX_I2C_BASE + 0x07 + (ch << 7)) +#define IT83XX_I2C_CLK_STR (1 << 7) +#define IT83XX_I2C_STR2(ch) REG8(IT83XX_I2C_BASE + 0x12 + (ch << 7)) +#define IT83XX_I2C_NST(ch) REG8(IT83XX_I2C_BASE + 0x13 + (ch << 7)) +#define IT83XX_I2C_NST_CNS BIT(7) +#define IT83XX_I2C_NST_ID_NACK BIT(3) +#define IT83XX_I2C_TO_ARB_ST(ch) REG8(IT83XX_I2C_BASE + 0x18 + (ch << 7)) +#define IT83XX_I2C_ERR_ST(ch) REG8(IT83XX_I2C_BASE + 0x19 + (ch << 7)) +#define IT83XX_I2C_ERR_ST_DEV1_EIRQ BIT(0) +#define IT83XX_I2C_FST(ch) REG8(IT83XX_I2C_BASE + 0x1b + (ch << 7)) +#define IT83XX_I2C_FST_DEV1_IRQ BIT(4) +#define IT83XX_I2C_EM(ch) REG8(IT83XX_I2C_BASE + 0x1c + (ch << 7)) +#define IT83XX_I2C_EM_DEV1_IRQ BIT(4) +#define IT83XX_I2C_MODE_SEL(ch) REG8(IT83XX_I2C_BASE + 0x1d + (ch << 7)) +#define IT83XX_I2C_IDR2(ch) REG8(IT83XX_I2C_BASE + 0x1F + (ch << 7)) +#define IT83XX_I2C_CTR2(ch) REG8(IT83XX_I2C_BASE + 0x20 + (ch << 7)) +#define IT83XX_I2C_RAMHA(ch) REG8(IT83XX_I2C_BASE + 0x23 + (ch << 7)) +#define IT83XX_I2C_RAMLA(ch) REG8(IT83XX_I2C_BASE + 0x24 + (ch << 7)) +#define IT83XX_I2C_RAMHA2(ch) REG8(IT83XX_I2C_BASE + 0x2B + (ch << 7)) +#define IT83XX_I2C_RAMLA2(ch) REG8(IT83XX_I2C_BASE + 0x2C + (ch << 7)) +#define IT83XX_I2C_CMD_ADDH(ch) REG8(IT83XX_I2C_BASE + 0x25 + (ch << 7)) +#define IT83XX_I2C_CMD_ADDL(ch) REG8(IT83XX_I2C_BASE + 0x26 + (ch << 7)) +#define IT83XX_I2C_RAMH2A(ch) REG8(IT83XX_I2C_BASE + 0x50 + (ch << 7)) +#define IT83XX_I2C_CMD_ADDH2(ch) REG8(IT83XX_I2C_BASE + 0x52 + (ch << 7)) enum i2c_channels { - IT83XX_I2C_CH_A, /* GPIO.B3/B4 */ - IT83XX_I2C_CH_B, /* GPIO.C1/C2 */ - IT83XX_I2C_CH_C, /* GPIO.F6/F7 or GPIO.C7/F7 */ - IT83XX_I2C_CH_D, /* GPIO.H1/H2 */ - IT83XX_I2C_CH_E, /* GPIO.E0/E7 */ - IT83XX_I2C_CH_F, /* GPIO.A4/A5 (for util/iteflash) */ + IT83XX_I2C_CH_A, /* GPIO.B3/B4 */ + IT83XX_I2C_CH_B, /* GPIO.C1/C2 */ + IT83XX_I2C_CH_C, /* GPIO.F6/F7 or GPIO.C7/F7 */ + IT83XX_I2C_CH_D, /* GPIO.H1/H2 */ + IT83XX_I2C_CH_E, /* GPIO.E0/E7 */ + IT83XX_I2C_CH_F, /* GPIO.A4/A5 (for util/iteflash) */ IT83XX_I2C_PORT_COUNT, }; #define USB_VID_ITE 0x048d -#define IT83XX_ESPI_BASE 0x00F03100 +#define IT83XX_ESPI_BASE 0x00F03100 -#define IT83XX_ESPI_GCAC1 REG8(IT83XX_ESPI_BASE+0x05) -#define IT83XX_ESPI_ESPCTRL0 REG8(IT83XX_ESPI_BASE+0x90) -#define IT83XX_ESPI_ESGCTRL0 REG8(IT83XX_ESPI_BASE+0xA0) -#define IT83XX_ESPI_ESGCTRL1 REG8(IT83XX_ESPI_BASE+0xA1) -#define IT83XX_ESPI_ESGCTRL2 REG8(IT83XX_ESPI_BASE+0xA2) +#define IT83XX_ESPI_GCAC1 REG8(IT83XX_ESPI_BASE + 0x05) +#define IT83XX_ESPI_ESPCTRL0 REG8(IT83XX_ESPI_BASE + 0x90) +#define IT83XX_ESPI_ESGCTRL0 REG8(IT83XX_ESPI_BASE + 0xA0) +#define IT83XX_ESPI_ESGCTRL1 REG8(IT83XX_ESPI_BASE + 0xA1) +#define IT83XX_ESPI_ESGCTRL2 REG8(IT83XX_ESPI_BASE + 0xA2) /* eSPI VW */ -#define IT83XX_ESPI_VW_BASE 0x00F03200 -#define IT83XX_ESPI_VWIDX(i) REG8(IT83XX_ESPI_VW_BASE+(i)) +#define IT83XX_ESPI_VW_BASE 0x00F03200 +#define IT83XX_ESPI_VWIDX(i) REG8(IT83XX_ESPI_VW_BASE + (i)) -#define VW_LEVEL_FIELD(f) ((f) << 0) -#define VW_VALID_FIELD(f) ((f) << 4) +#define VW_LEVEL_FIELD(f) ((f) << 0) +#define VW_VALID_FIELD(f) ((f) << 4) #define ESPI_SYSTEM_EVENT_VW_IDX_2 0x2 -#define VW_IDX_2_SLP_S3 BIT(0) -#define VW_IDX_2_SLP_S4 BIT(1) -#define VW_IDX_2_SLP_S5 BIT(2) +#define VW_IDX_2_SLP_S3 BIT(0) +#define VW_IDX_2_SLP_S4 BIT(1) +#define VW_IDX_2_SLP_S5 BIT(2) #define ESPI_SYSTEM_EVENT_VW_IDX_3 0x3 -#define VW_IDX_3_SUS_STAT BIT(0) -#define VW_IDX_3_PLTRST BIT(1) -#define VW_IDX_3_OOB_RST_WARN BIT(2) +#define VW_IDX_3_SUS_STAT BIT(0) +#define VW_IDX_3_PLTRST BIT(1) +#define VW_IDX_3_OOB_RST_WARN BIT(2) #define ESPI_SYSTEM_EVENT_VW_IDX_4 0x4 -#define VW_IDX_4_OOB_RST_ACK BIT(0) -#define VW_IDX_4_WAKE BIT(2) -#define VW_IDX_4_PME BIT(3) +#define VW_IDX_4_OOB_RST_ACK BIT(0) +#define VW_IDX_4_WAKE BIT(2) +#define VW_IDX_4_PME BIT(3) #define ESPI_SYSTEM_EVENT_VW_IDX_5 0x5 -#define VW_IDX_5_SLAVE_BTLD_DONE BIT(0) -#define VW_IDX_5_FATAL BIT(1) -#define VW_IDX_5_NON_FATAL BIT(2) +#define VW_IDX_5_SLAVE_BTLD_DONE BIT(0) +#define VW_IDX_5_FATAL BIT(1) +#define VW_IDX_5_NON_FATAL BIT(2) #define VW_IDX_5_SLAVE_BTLD_STATUS BIT(3) -#define VW_IDX_5_BTLD_STATUS_DONE (VW_IDX_5_SLAVE_BTLD_DONE | \ - VW_IDX_5_SLAVE_BTLD_STATUS) +#define VW_IDX_5_BTLD_STATUS_DONE \ + (VW_IDX_5_SLAVE_BTLD_DONE | VW_IDX_5_SLAVE_BTLD_STATUS) #define ESPI_SYSTEM_EVENT_VW_IDX_6 0x6 -#define VW_IDX_6_SCI BIT(0) -#define VW_IDX_6_SMI BIT(1) -#define VW_IDX_6_RCIN BIT(2) -#define VW_IDX_6_HOST_RST_ACK BIT(3) +#define VW_IDX_6_SCI BIT(0) +#define VW_IDX_6_SMI BIT(1) +#define VW_IDX_6_RCIN BIT(2) +#define VW_IDX_6_HOST_RST_ACK BIT(3) #define ESPI_SYSTEM_EVENT_VW_IDX_7 0x7 -#define VW_IDX_7_HOST_RST_WARN BIT(0) +#define VW_IDX_7_HOST_RST_WARN BIT(0) #define ESPI_SYSTEM_EVENT_VW_IDX_40 0x40 -#define VW_IDX_40_SUS_ACK BIT(0) +#define VW_IDX_40_SUS_ACK BIT(0) #define ESPI_SYSTEM_EVENT_VW_IDX_41 0x41 -#define VW_IDX_41_SUS_WARN BIT(0) -#define VW_IDX_41_SUS_PWRDN_ACK BIT(1) -#define VW_IDX_41_SLP_A BIT(3) +#define VW_IDX_41_SUS_WARN BIT(0) +#define VW_IDX_41_SUS_PWRDN_ACK BIT(1) +#define VW_IDX_41_SLP_A BIT(3) #define ESPI_SYSTEM_EVENT_VW_IDX_42 0x42 -#define VW_IDX_42_SLP_LAN BIT(0) -#define VW_IDX_42_SLP_WLAN BIT(1) +#define VW_IDX_42_SLP_LAN BIT(0) +#define VW_IDX_42_SLP_WLAN BIT(1) #define ESPI_SYSTEM_EVENT_VW_IDX_43 0x43 #define ESPI_SYSTEM_EVENT_VW_IDX_44 0x44 #define ESPI_SYSTEM_EVENT_VW_IDX_47 0x47 -#define IT83XX_ESPI_VWCTRL0 REG8(IT83XX_ESPI_VW_BASE+0x90) +#define IT83XX_ESPI_VWCTRL0 REG8(IT83XX_ESPI_VW_BASE + 0x90) #define ESPI_INTERRUPT_EVENT_PUT_PC BIT(7) -#define IT83XX_ESPI_VWCTRL1 REG8(IT83XX_ESPI_VW_BASE+0x91) -#define IT83XX_ESPI_VWCTRL2 REG8(IT83XX_ESPI_VW_BASE+0x92) -#define IT83XX_ESPI_VWCTRL3 REG8(IT83XX_ESPI_VW_BASE+0x93) +#define IT83XX_ESPI_VWCTRL1 REG8(IT83XX_ESPI_VW_BASE + 0x91) +#define IT83XX_ESPI_VWCTRL2 REG8(IT83XX_ESPI_VW_BASE + 0x92) +#define IT83XX_ESPI_VWCTRL3 REG8(IT83XX_ESPI_VW_BASE + 0x93) +/* 1b: Refers to espi_reset# for pltrst */ +#define ESPI_PLTRST_ESPI_RESET BIT(4) /* eSPI Queue 0 */ -#define IT83XX_ESPI_QUEUE_BASE 0x00F03300 +#define IT83XX_ESPI_QUEUE_BASE 0x00F03300 /* PUT_PC data byte 0 - 63 */ -#define IT83XX_ESPI_QUEUE_PUT_PC(i) REG8(IT83XX_ESPI_QUEUE_BASE+(i)) +#define IT83XX_ESPI_QUEUE_PUT_PC(i) REG8(IT83XX_ESPI_QUEUE_BASE + (i)) /* PUT_OOB data byte 0 - 79 */ -#define IT83XX_ESPI_QUEUE_PUT_OOB(i) REG8(IT83XX_ESPI_QUEUE_BASE+0x80+(i)) +#define IT83XX_ESPI_QUEUE_PUT_OOB(i) REG8(IT83XX_ESPI_QUEUE_BASE + 0x80 + (i)) /* USB Controller */ -#define IT83XX_USB_BASE 0x00F02F00 +#define IT83XX_USB_BASE 0x00F02F00 -#define IT83XX_USB_P0MCR REG8(IT83XX_USB_BASE+0xE4) +#define IT83XX_USB_P0MCR REG8(IT83XX_USB_BASE + 0xE4) #define USB_DP_DM_PULL_DOWN_EN BIT(4) /* Wake pin definitions, defined at board-level */ @@ -1611,11 +1677,11 @@ extern int hibernate_wake_pins_used; /* --- MISC (not implemented yet) --- */ -#define IT83XX_PS2_BASE 0x00F01700 +#define IT83XX_PS2_BASE 0x00F01700 #define IT83XX_EGPIO_BASE 0x00F02100 -#define IT83XX_CIR_BASE 0x00F02300 -#define IT83XX_DBGR_BASE 0x00F02500 -#define IT83XX_OW_BASE 0x00F02A00 -#define IT83XX_CEC_BASE 0x00F02E00 +#define IT83XX_CIR_BASE 0x00F02300 +#define IT83XX_DBGR_BASE 0x00F02500 +#define IT83XX_OW_BASE 0x00F02A00 +#define IT83XX_CEC_BASE 0x00F02E00 #endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/it83xx/spi.c b/chip/it83xx/spi.c index 1fb77f9c3b..c172e9fca9 100644 --- a/chip/it83xx/spi.c +++ b/chip/it83xx/spi.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -12,6 +12,7 @@ #include "gpio.h" #include "hooks.h" #include "host_command.h" +#include "intc.h" #include "registers.h" #include "spi.h" #include "system.h" @@ -19,8 +20,8 @@ #include "util.h" /* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SPI, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SPI, format, ##args) #define SPI_RX_MAX_FIFO_SIZE 256 #define SPI_TX_MAX_FIFO_SIZE 256 @@ -30,8 +31,8 @@ /* Max data size for a version 3 request/response packet. */ #define SPI_MAX_REQUEST_SIZE SPI_RX_MAX_FIFO_SIZE -#define SPI_MAX_RESPONSE_SIZE (SPI_TX_MAX_FIFO_SIZE - \ - EC_SPI_PREAMBLE_LENGTH - EC_SPI_PAST_END_LENGTH) +#define SPI_MAX_RESPONSE_SIZE \ + (SPI_TX_MAX_FIFO_SIZE - EC_SPI_PREAMBLE_LENGTH - EC_SPI_PAST_END_LENGTH) static const uint8_t out_preamble[EC_SPI_PREAMBLE_LENGTH] = { EC_SPI_PROCESSING, @@ -48,7 +49,7 @@ static uint8_t out_msg[SPI_TX_MAX_FIFO_SIZE] __aligned(4); /* Parameters used by host protocols */ static struct host_packet spi_packet; -enum spi_slave_state_machine { +enum spi_peripheral_state_machine { /* Ready to receive next request */ SPI_STATE_READY_TO_RECV, /* Receiving request */ @@ -59,21 +60,21 @@ enum spi_slave_state_machine { SPI_STATE_RX_BAD, SPI_STATE_COUNT, -} spi_slv_state; +} spi_peripheral_state; static const int spi_response_state[] = { - [SPI_STATE_READY_TO_RECV] = EC_SPI_OLD_READY, - [SPI_STATE_RECEIVING] = EC_SPI_RECEIVING, - [SPI_STATE_PROCESSING] = EC_SPI_PROCESSING, - [SPI_STATE_RX_BAD] = EC_SPI_RX_BAD_DATA, + [SPI_STATE_READY_TO_RECV] = EC_SPI_RX_READY, + [SPI_STATE_RECEIVING] = EC_SPI_RECEIVING, + [SPI_STATE_PROCESSING] = EC_SPI_PROCESSING, + [SPI_STATE_RX_BAD] = EC_SPI_RX_BAD_DATA, }; BUILD_ASSERT(ARRAY_SIZE(spi_response_state) == SPI_STATE_COUNT); static void spi_set_state(int state) { - /* SPI slave state machine */ - spi_slv_state = state; - /* Response spi slave state */ + /* SPI peripheral state machine */ + spi_peripheral_state = state; + /* Response spi peripheral state */ IT83XX_SPI_SPISRDR = spi_response_state[state]; } @@ -117,12 +118,12 @@ static void spi_response_host_data(uint8_t *out_msg_addr, int tx_size) /* * After writing data to Tx FIFO is finished, this bit will - * be to indicate the SPI slave controller. + * be to indicate the SPI peripheral. */ IT83XX_SPI_TXFCR = IT83XX_SPI_TXFS; /* End Tx FIFO access */ IT83XX_SPI_TXRXFAR = 0; - /* SPI slave read Tx FIFO */ + /* SPI peripheral read Tx FIFO */ IT83XX_SPI_FCR = IT83XX_SPI_SPISRTXF; } @@ -137,18 +138,18 @@ static void spi_send_response_packet(struct host_packet *pkt) { int i, tx_size; - if (spi_slv_state != SPI_STATE_PROCESSING) { + if (spi_peripheral_state != SPI_STATE_PROCESSING) { CPRINTS("The request data is not processing."); return; } /* Append our past-end byte, which we reserved space for. */ for (i = 0; i < EC_SPI_PAST_END_LENGTH; i++) - ((uint8_t *)pkt->response)[pkt->response_size + i] - = EC_SPI_PAST_END; + ((uint8_t *)pkt->response)[pkt->response_size + i] = + EC_SPI_PAST_END; tx_size = pkt->response_size + EC_SPI_PREAMBLE_LENGTH + - EC_SPI_PAST_END_LENGTH; + EC_SPI_PAST_END_LENGTH; /* Transmit the reply */ spi_response_host_data(out_msg, tx_size); @@ -169,7 +170,7 @@ static void spi_host_request_data(uint8_t *in_msg_addr, int count) */ for (i = 0; i < count; i += 4) - /* Get data from master to buffer */ + /* Get data from controller to buffer */ *(uint32_t *)(in_msg_addr + i) = IT83XX_SPI_RXFRDRB0; } @@ -193,7 +194,7 @@ static void spi_parse_header(void) /* Store request data from Rx FIFO to in_msg buffer */ spi_host_request_data(in_msg + sizeof(*r), - pkt_size - sizeof(*r)); + pkt_size - sizeof(*r)); /* Set up parameters for host request */ spi_packet.send_response = spi_send_response_packet; @@ -233,8 +234,24 @@ void spi_event(enum gpio_signal signal) } } -void spi_slv_int_handler(void) +void spi_peripheral_int_handler(void) { + if (IS_ENABLED(CONFIG_BOOTBLOCK) && + (IT83XX_SPI_ISR & IT83XX_SPI_RX_FIFO_FULL) && + (IT83XX_SPI_EMMCBMR & IT83XX_SPI_EMMCABM)) { + spi_host_request_data(in_msg, 128); + /* End CPU access RX FIFO */ + IT83XX_SPI_TXRXFAR = 0; + /* Write to clear interrupt status */ + IT83XX_SPI_ISR = 0xff; + /* + * Handle eMMC CMD0: + * GO_IDLE_STATE, GO_PRE_IDLE_STATE, and BOOT_INITIATION + */ + spi_emmc_cmd0_isr((uint32_t *)in_msg); + return; + } + /* * The status of SPI end detection interrupt bit is set, it * means that host command parse has been completed and AP @@ -242,12 +259,6 @@ void spi_slv_int_handler(void) * EC responded data, then AP ended the transaction. */ if (IT83XX_SPI_ISR & IT83XX_SPI_ENDDETECTINT) { - /* Reset fifo and prepare to receive next transaction */ - if (!IS_ENABLED(IT83XX_SPI_AUTO_RESET_RX_FIFO)) - reset_rx_fifo(); - /* Enable Rx byte reach interrupt */ - if (!IS_ENABLED(IT83XX_SPI_RX_VALID_INT)) - IT83XX_SPI_IMR &= ~IT83XX_SPI_RX_REACH; /* Ready to receive */ spi_set_state(SPI_STATE_READY_TO_RECV); /* @@ -255,50 +266,50 @@ void spi_slv_int_handler(void) * sleep bit of SPI in S3 or lower. */ enable_sleep(SLEEP_MASK_SPI); - /* CS# is deasserted, so write clear all slave status */ + /* CS# is deasserted, so write clear all peripheral status */ IT83XX_SPI_ISR = 0xff; } - - if (IS_ENABLED(IT83XX_SPI_RX_VALID_INT)) { - /* - * The status of Rx valid length interrupt bit is set that - * indicates reached target count(IT83XX_SPI_FTCB1R, - * IT83XX_SPI_FTCB0R) and the length field of the host - * requested data. - */ - if (IT83XX_SPI_RX_VLISR & IT83XX_SPI_RVLI) { - /* write clear slave status */ - IT83XX_SPI_RX_VLISR = IT83XX_SPI_RVLI; - /* Parse header for version of spi-protocol */ - spi_parse_header(); - } - } else { - /* - * The status of Rx byte reach interrupt bit is set, - * start to parse transaction. - * There is a limitation that Rx FIFO starts dropping - * data when the CPU access the the FIFO. So we will - * wait the data until Rx byte reach then to parse. - * The Rx FIFO to reach is mock data generated by - * generate clock that is not the bytes sent from - * the host. - */ - if (IT83XX_SPI_ISR & IT83XX_SPI_RX_REACH) { - /* Disable Rx byte reach interrupt */ - IT83XX_SPI_IMR |= IT83XX_SPI_RX_REACH; - /* write clear slave status */ - IT83XX_SPI_ISR = IT83XX_SPI_RX_REACH; - /* Parse header for version of spi-protocol */ - spi_parse_header(); - } + /* + * The status of Rx valid length interrupt bit is set that + * indicates reached target count(IT83XX_SPI_FTCB1R, + * IT83XX_SPI_FTCB0R) and the length field of the host + * requested data. + */ + if (IT83XX_SPI_RX_VLISR & IT83XX_SPI_RVLI) { + /* write clear peripheral status */ + IT83XX_SPI_RX_VLISR = IT83XX_SPI_RVLI; + /* Parse header for version of spi-protocol */ + spi_parse_header(); } /* Clear the interrupt status */ - task_clear_pending_irq(IT83XX_IRQ_SPI_SLAVE); + task_clear_pending_irq(IT83XX_IRQ_SPI_PERIPHERAL); } static void spi_init(void) { + /* Set FIFO data target count */ + struct ec_host_request cmd_head; + + /* + * Target count means the size of host request. + * And plus extra 4 bytes because the CPU accesses FIFO base on + * word. If host requested data length is one byte, we need to + * align the data length to 4 bytes. + */ + int target_count = sizeof(cmd_head) + 4; + /* Offset of data_len member of host request. */ + int offset = (char *)&cmd_head.data_len - (char *)&cmd_head; + + IT83XX_SPI_FTCB1R = (target_count >> 8) & 0xff; + IT83XX_SPI_FTCB0R = target_count & 0xff; + /* + * The register setting can capture the length field of host + * request. + */ + IT83XX_SPI_TCCB1 = (offset >> 8) & 0xff; + IT83XX_SPI_TCCB0 = offset & 0xff; + /* Set SPI pins to alternate function */ gpio_config_module(MODULE_SPI, 1); /* @@ -308,43 +319,16 @@ static void spi_init(void) IT83XX_GCTRL_MCCR3 |= IT83XX_GCTRL_SPISLVPFE; /* Set unused blocked byte */ IT83XX_SPI_HPR2 = 0x00; - /* Set FIFO data target count */ - if (IS_ENABLED(IT83XX_SPI_RX_VALID_INT)) { - struct ec_host_request cmd_head; - /* - * Target count means the size of host request. - * And plus extra 4 bytes because the CPU accesses FIFO base on - * word. If host requested data length is one byte, we need to - * align the data length to 4 bytes. - */ - int target_count = sizeof(cmd_head) + 4; - /* Offset of data_len member of host request. */ - int offset = (char *)&cmd_head.data_len - (char *)&cmd_head; - - IT83XX_SPI_FTCB1R = (target_count >> 8) & 0xff; - IT83XX_SPI_FTCB0R = target_count & 0xff; - /* - * The register setting can capture the length field of host - * request. - */ - IT83XX_SPI_TCCB1 = (offset >> 8) & 0xff; - IT83XX_SPI_TCCB0 = offset & 0xff; - } else { - IT83XX_SPI_FTCB1R = (SPI_RX_MAX_FIFO_SIZE >> 8) & 0xff; - IT83XX_SPI_FTCB0R = SPI_RX_MAX_FIFO_SIZE & 0xff; - } /* Rx valid length interrupt enabled */ - if (IS_ENABLED(IT83XX_SPI_RX_VALID_INT)) - IT83XX_SPI_RX_VLISMR &= ~IT83XX_SPI_RVLIM; + IT83XX_SPI_RX_VLISMR &= ~IT83XX_SPI_RVLIM; /* * General control register2 * bit4 : Rx FIFO2 will not be overwrited once it's full. * bit3 : Rx FIFO1 will not be overwrited once it's full. * bit0 : Rx FIFO1/FIFO2 will reset after each CS_N goes high. */ - if (IS_ENABLED(IT83XX_SPI_AUTO_RESET_RX_FIFO)) - IT83XX_SPI_GCR2 = IT83XX_SPI_RXF2OC | IT83XX_SPI_RXF1OC - | IT83XX_SPI_RXFAR; + IT83XX_SPI_GCR2 = IT83XX_SPI_RXF2OC | IT83XX_SPI_RXF1OC | + IT83XX_SPI_RXFAR; /* * Interrupt mask register (0b:Enable, 1b:Mask) * bit5 : Rx byte reach interrupt mask @@ -353,25 +337,22 @@ static void spi_init(void) IT83XX_SPI_IMR &= ~IT83XX_SPI_EDIM; /* Reset fifo and prepare to for next transaction */ reset_rx_fifo(); - /* Enable Rx byte reach interrupt */ - if (!IS_ENABLED(IT83XX_SPI_RX_VALID_INT)) - IT83XX_SPI_IMR &= ~IT83XX_SPI_RX_REACH; /* Ready to receive */ spi_set_state(SPI_STATE_READY_TO_RECV); /* Interrupt status register(write one to clear) */ IT83XX_SPI_ISR = 0xff; - /* SPI slave controller enable (after settings are ready) */ + /* SPI peripheral enable (after settings are ready) */ IT83XX_SPI_SPISGCR = IT83XX_SPI_SPISCEN; - /* Enable SPI slave interrupt */ - task_clear_pending_irq(IT83XX_IRQ_SPI_SLAVE); - task_enable_irq(IT83XX_IRQ_SPI_SLAVE); + /* Enable SPI peripheral interrupt */ + task_clear_pending_irq(IT83XX_IRQ_SPI_PERIPHERAL); + task_enable_irq(IT83XX_IRQ_SPI_PERIPHERAL); /* Enable SPI chip select pin interrupt */ gpio_clear_pending_interrupt(GPIO_SPI0_CS); gpio_enable_interrupt(GPIO_SPI0_CS); } DECLARE_HOOK(HOOK_INIT, spi_init, HOOK_PRIO_INIT_SPI); -/* reset slave SPI module */ +/* reset peripheral SPI module */ static void spi_reset(void) { /* @@ -382,8 +363,25 @@ static void spi_reset(void) } DECLARE_HOOK(HOOK_SYSJUMP, spi_reset, HOOK_PRIO_DEFAULT); +#if defined(SECTION_IS_RO) && defined(CONFIG_BOOTBLOCK) +/* AP has booted */ +void emmc_ap_jump_to_bl(enum gpio_signal signal) +{ + /* Transmission completed. Set SPI pin mux to AP communication mode */ + IT83XX_GCTRL_PIN_MUX0 &= ~BIT(7); + /* Reset and re-initialize SPI module to communication mode */ + spi_reset(); + spi_init(); + /* Disable interrupt of detection of AP's BOOTBLOCK_EN_L */ + gpio_disable_interrupt(GPIO_BOOTBLOCK_EN_L); + enable_sleep(SLEEP_MASK_EMMC); + + CPRINTS("eMMC emulation disabled. AP Jumped to BL"); +} +#endif + /* Get protocol information */ -enum ec_status spi_get_protocol_info(struct host_cmd_handler_args *args) +static enum ec_status _spi_get_protocol_info(struct host_cmd_handler_args *args) { struct ec_response_get_protocol_info *r = args->response; @@ -397,6 +395,10 @@ enum ec_status spi_get_protocol_info(struct host_cmd_handler_args *args) return EC_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, - spi_get_protocol_info, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, _spi_get_protocol_info, + EC_VER_MASK(0)); + +enum ec_status spi_get_protocol_info(struct host_cmd_handler_args *args) +{ + return _spi_get_protocol_info(args); +} diff --git a/chip/it83xx/spi_controller.c b/chip/it83xx/spi_controller.c new file mode 100644 index 0000000000..aaab27e138 --- /dev/null +++ b/chip/it83xx/spi_controller.c @@ -0,0 +1,173 @@ +/* Copyright 2015 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SPI module for Chrome EC */ + +#include "clock.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "registers.h" +#include "spi.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_SPI, outstr) +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) + +enum sspi_clk_sel { + sspi_clk_24mhz = 0, + sspi_clk_12mhz, + sspi_clk_8mhz, + sspi_clk_6mhz, + sspi_clk_4p8mhz, + sspi_clk_4mhz, + sspi_clk_3p428mhz, + sspi_clk_3mhz, +}; + +enum sspi_ch_sel { + SSPI_CH_CS0 = 0, + SSPI_CH_CS1, +}; + +static void sspi_frequency(enum sspi_clk_sel freq) +{ + /* + * bit[6:5] + * Bit 6:Clock Polarity (CLPOL) + * 0: SSCK is low in the idle mode. + * 1: SSCK is high in the idle mode. + * Bit 5:Clock Phase (CLPHS) + * 0: Latch data on the first SSCK edge. + * 1: Latch data on the second SSCK edge. + * + * bit[4:2] + * 000b: 1/2 clk_sspi + * 001b: 1/4 clk_sspi + * 010b: 1/6 clk_sspi + * 011b: 1/8 clk_sspi + * 100b: 1/10 clk_sspi + * 101b: 1/12 clk_sspi + * 110b: 1/14 clk_sspi + * 111b: 1/16 clk_sspi + * + * SSCK frequency is [freq] MHz and mode 3. + * note, clk_sspi need equal to 48MHz above. + */ + IT83XX_SSPI_SPICTRL1 |= (0x60 | (freq << 2)); +} + +static void sspi_transmission_end(void) +{ + /* Write 1 to end the SPI transmission. */ + IT83XX_SSPI_SPISTS = 0x20; + + /* Short delay for "Transfer End Flag" */ + IT83XX_GCTRL_WNCKR = 0; + + /* Write 1 to clear this bit and terminate data transmission. */ + IT83XX_SSPI_SPISTS = 0x02; +} + +/* We assume only one SPI port in the chip, one SPI device */ +int spi_enable(const struct spi_device_t *spi_device, int enable) +{ + int port = spi_device->port; + + if (enable) { + /* + * bit[5:4] + * 00b: SPI channel 0 and channel 1 are disabled. + * 10b: SSCK/SMOSI/SMISO/SSCE1# are enabled. + * 01b: SSCK/SMOSI/SMISO/SSCE0# are enabled. + * 11b: SSCK/SMOSI/SMISO/SSCE1#/SSCE0# are enabled. + */ + if (port == SSPI_CH_CS1) + IT83XX_GPIO_GRC1 |= 0x20; + else + IT83XX_GPIO_GRC1 |= 0x10; + + gpio_config_module(MODULE_SPI_CONTROLLER, 1); + } else { + if (port == SSPI_CH_CS1) + IT83XX_GPIO_GRC1 &= ~0x20; + else + IT83XX_GPIO_GRC1 &= ~0x10; + + gpio_config_module(MODULE_SPI_CONTROLLER, 0); + } + + return EC_SUCCESS; +} + +int spi_transaction(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) +{ + int idx; + uint8_t port = spi_device->port; + static struct mutex spi_mutex; + + mutex_lock(&spi_mutex); + /* bit[0]: Write cycle */ + IT83XX_SSPI_SPICTRL2 &= ~0x04; + for (idx = 0x00; idx < txlen; idx++) { + IT83XX_SSPI_SPIDATA = txdata[idx]; + if (port == SSPI_CH_CS1) + /* Write 1 to start the data transmission of CS1 */ + IT83XX_SSPI_SPISTS |= 0x08; + else + /* Write 1 to start the data transmission of CS0 */ + IT83XX_SSPI_SPISTS |= 0x10; + } + + /* bit[1]: Read cycle */ + IT83XX_SSPI_SPICTRL2 |= 0x04; + for (idx = 0x00; idx < rxlen; idx++) { + if (port == SSPI_CH_CS1) + /* Write 1 to start the data transmission of CS1 */ + IT83XX_SSPI_SPISTS |= 0x08; + else + /* Write 1 to start the data transmission of CS0 */ + IT83XX_SSPI_SPISTS |= 0x10; + rxdata[idx] = IT83XX_SSPI_SPIDATA; + } + + sspi_transmission_end(); + mutex_unlock(&spi_mutex); + + return EC_SUCCESS; +} + +static void sspi_init(void) +{ + int i; + + clock_enable_peripheral(CGC_OFFSET_SSPI, 0, 0); + sspi_frequency(sspi_clk_8mhz); + + /* + * bit[5:3] Byte Width (BYTEWIDTH) + * 000b: 8-bit transmission + * 001b: 1-bit transmission + * 010b: 2-bit transmission + * 011b: 3-bit transmission + * 100b: 4-bit transmission + * 101b: 5-bit transmission + * 110b: 6-bit transmission + * 111b: 7-bit transmission + * + * bit[1] Blocking selection + */ + IT83XX_SSPI_SPICTRL2 |= 0x02; + + for (i = 0; i < spi_devices_used; i++) + /* Disabling spi module */ + spi_enable(&spi_devices[i], 0); +} +DECLARE_HOOK(HOOK_INIT, sspi_init, HOOK_PRIO_INIT_SPI); diff --git a/chip/it83xx/spi_master.c b/chip/it83xx/spi_master.c deleted file mode 100644 index 23cea9d2ab..0000000000 --- a/chip/it83xx/spi_master.c +++ /dev/null @@ -1,171 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* SPI module for Chrome EC */ - -#include "clock.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "spi.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) - -enum sspi_clk_sel { - sspi_clk_24mhz = 0, - sspi_clk_12mhz, - sspi_clk_8mhz, - sspi_clk_6mhz, - sspi_clk_4p8mhz, - sspi_clk_4mhz, - sspi_clk_3p428mhz, - sspi_clk_3mhz, -}; - -enum sspi_ch_sel { - SSPI_CH_CS0 = 0, - SSPI_CH_CS1, -}; - -static void sspi_frequency(enum sspi_clk_sel freq) -{ - /* - * bit[6:5] - * Bit 6:Clock Polarity (CLPOL) - * 0: SSCK is low in the idle mode. - * 1: SSCK is high in the idle mode. - * Bit 5:Clock Phase (CLPHS) - * 0: Latch data on the first SSCK edge. - * 1: Latch data on the second SSCK edge. - * - * bit[4:2] - * 000b: 1/2 clk_sspi - * 001b: 1/4 clk_sspi - * 010b: 1/6 clk_sspi - * 011b: 1/8 clk_sspi - * 100b: 1/10 clk_sspi - * 101b: 1/12 clk_sspi - * 110b: 1/14 clk_sspi - * 111b: 1/16 clk_sspi - * - * SSCK frequency is [freq] MHz and mode 3. - * note, clk_sspi need equal to 48MHz above. - */ - IT83XX_SSPI_SPICTRL1 |= (0x60 | (freq << 2)); -} - -static void sspi_transmission_end(void) -{ - /* Write 1 to end the SPI transmission. */ - IT83XX_SSPI_SPISTS = 0x20; - - /* Short delay for "Transfer End Flag" */ - IT83XX_GCTRL_WNCKR = 0; - - /* Write 1 to clear this bit and terminate data transmission. */ - IT83XX_SSPI_SPISTS = 0x02; -} - -/* We assume only one SPI port in the chip, one SPI device */ -int spi_enable(int port, int enable) -{ - if (enable) { - /* - * bit[5:4] - * 00b: SPI channel 0 and channel 1 are disabled. - * 10b: SSCK/SMOSI/SMISO/SSCE1# are enabled. - * 01b: SSCK/SMOSI/SMISO/SSCE0# are enabled. - * 11b: SSCK/SMOSI/SMISO/SSCE1#/SSCE0# are enabled. - */ - if (port == SSPI_CH_CS1) - IT83XX_GPIO_GRC1 |= 0x20; - else - IT83XX_GPIO_GRC1 |= 0x10; - - gpio_config_module(MODULE_SPI_MASTER, 1); - } else { - if (port == SSPI_CH_CS1) - IT83XX_GPIO_GRC1 &= ~0x20; - else - IT83XX_GPIO_GRC1 &= ~0x10; - - gpio_config_module(MODULE_SPI_MASTER, 0); - } - - return EC_SUCCESS; -} - -int spi_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - int idx; - uint8_t port = spi_device->port; - static struct mutex spi_mutex; - - mutex_lock(&spi_mutex); - /* bit[0]: Write cycle */ - IT83XX_SSPI_SPICTRL2 &= ~0x04; - for (idx = 0x00; idx < txlen; idx++) { - IT83XX_SSPI_SPIDATA = txdata[idx]; - if (port == SSPI_CH_CS1) - /* Write 1 to start the data transmission of CS1 */ - IT83XX_SSPI_SPISTS |= 0x08; - else - /* Write 1 to start the data transmission of CS0 */ - IT83XX_SSPI_SPISTS |= 0x10; - } - - /* bit[1]: Read cycle */ - IT83XX_SSPI_SPICTRL2 |= 0x04; - for (idx = 0x00; idx < rxlen; idx++) { - if (port == SSPI_CH_CS1) - /* Write 1 to start the data transmission of CS1 */ - IT83XX_SSPI_SPISTS |= 0x08; - else - /* Write 1 to start the data transmission of CS0 */ - IT83XX_SSPI_SPISTS |= 0x10; - rxdata[idx] = IT83XX_SSPI_SPIDATA; - } - - sspi_transmission_end(); - mutex_unlock(&spi_mutex); - - return EC_SUCCESS; -} - -static void sspi_init(void) -{ - int i; - - clock_enable_peripheral(CGC_OFFSET_SSPI, 0, 0); - sspi_frequency(sspi_clk_8mhz); - - /* - * bit[5:3] Byte Width (BYTEWIDTH) - * 000b: 8-bit transmission - * 001b: 1-bit transmission - * 010b: 2-bit transmission - * 011b: 3-bit transmission - * 100b: 4-bit transmission - * 101b: 5-bit transmission - * 110b: 6-bit transmission - * 111b: 7-bit transmission - * - * bit[1] Blocking selection - */ - IT83XX_SSPI_SPICTRL2 |= 0x02; - - for (i = 0; i < spi_devices_used; i++) - /* Disabling spi module */ - spi_enable(spi_devices[i].port, 0); -} -DECLARE_HOOK(HOOK_INIT, sspi_init, HOOK_PRIO_INIT_SPI); diff --git a/chip/it83xx/system.c b/chip/it83xx/system.c index 960ef7b622..09c5678cd4 100644 --- a/chip/it83xx/system.c +++ b/chip/it83xx/system.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,16 +7,18 @@ #include "console.h" #include "cpu.h" +#include "cros_version.h" #include "ec2i_chip.h" #include "flash.h" #include "hooks.h" #include "host_command.h" #include "intc.h" +#include "link_defs.h" +#include "panic.h" #include "registers.h" #include "system.h" #include "task.h" #include "util.h" -#include "version.h" #include "watchdog.h" void system_hibernate(uint32_t seconds, uint32_t microseconds) @@ -43,12 +45,48 @@ static int delayed_clear_reset_flags; static void clear_reset_flags(void) { if (IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON) && - delayed_clear_reset_flags) { + delayed_clear_reset_flags) { chip_save_reset_flags(0); } } DECLARE_HOOK(HOOK_INIT, clear_reset_flags, HOOK_PRIO_LAST); +#if !defined(CONFIG_HOST_INTERFACE_LPC) && !defined(CONFIG_HOST_INTERFACE_ESPI) +static void system_save_panic_data_to_bram(void) +{ + uint8_t *ptr = (uint8_t *)PANIC_DATA_PTR; + + for (int i = 0; i < CONFIG_PANIC_DATA_SIZE; i++) + IT83XX_BRAM_BANK0(i + BRAM_PANIC_DATA_START) = ptr[i]; +} + +static void system_restore_panic_data_from_bram(void) +{ + uint8_t *ptr = (uint8_t *)PANIC_DATA_PTR; + + for (int i = 0; i < CONFIG_PANIC_DATA_SIZE; i++) + ptr[i] = IT83XX_BRAM_BANK0(i + BRAM_PANIC_DATA_START); +} +BUILD_ASSERT(BRAM_PANIC_LEN >= CONFIG_PANIC_DATA_SIZE); +#else +static void system_save_panic_data_to_bram(void) +{ +} +static void system_restore_panic_data_from_bram(void) +{ +} +#endif + +static void system_reset_ec_by_gpg1(void) +{ + system_save_panic_data_to_bram(); + /* Set GPG1 as output high and wait until EC reset. */ + IT83XX_GPIO_CTRL(GPIO_G, 1) = GPCR_PORT_PIN_MODE_OUTPUT; + IT83XX_GPIO_DATA(GPIO_G) |= BIT(1); + while (1) + ; +} + static void check_reset_cause(void) { uint32_t flags; @@ -65,6 +103,18 @@ static void check_reset_cause(void) /* Determine if watchdog reset or power on reset. */ if (raw_reset_cause & 0x02) { flags |= EC_RESET_FLAG_WATCHDOG; + if (IS_ENABLED(CONFIG_IT83XX_HARD_RESET_BY_GPG1)) { + /* + * Save watchdog reset flag to BRAM so we can restore + * the flag on next reboot. + */ + chip_save_reset_flags(EC_RESET_FLAG_WATCHDOG); + /* + * Assert GPG1 to reset EC and then EC_RST_ODL will be + * toggled. + */ + system_reset_ec_by_gpg1(); + } } else if (raw_reset_cause & 0x01) { flags |= EC_RESET_FLAG_POWER_ON; } else { @@ -87,7 +137,7 @@ static void check_reset_cause(void) * we know this is the first reset. */ if (IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON) && - (flags & EC_RESET_FLAG_POWER_ON)) { + (flags & EC_RESET_FLAG_POWER_ON)) { if (flags & EC_RESET_FLAG_INITIAL_PWR) { /* Second boot, clear the flag immediately */ chip_save_reset_flags(0); @@ -101,7 +151,7 @@ static void check_reset_cause(void) * fine because we will have the correct flag anyway. */ chip_save_reset_flags(chip_read_reset_flags() | - EC_RESET_FLAG_INITIAL_PWR); + EC_RESET_FLAG_INITIAL_PWR); /* * Schedule chip_save_reset_flags(0) later. @@ -118,10 +168,14 @@ static void check_reset_cause(void) /* Clear PD contract recorded in bram if this is a power-on reset. */ if (IS_ENABLED(CONFIG_IT83XX_RESET_PD_CONTRACT_IN_BRAM) && - (flags == (EC_RESET_FLAG_POWER_ON | EC_RESET_FLAG_RESET_PIN))) { + (flags == (EC_RESET_FLAG_POWER_ON | EC_RESET_FLAG_RESET_PIN))) { for (int i = 0; i < MAX_SYSTEM_BBRAM_IDX_PD_PORTS; i++) system_set_bbram((SYSTEM_BBRAM_IDX_PD0 + i), 0); } + + if ((IS_ENABLED(CONFIG_IT83XX_HARD_RESET_BY_GPG1)) && + (flags & ~(EC_RESET_FLAG_POWER_ON | EC_RESET_FLAG_RESET_PIN))) + system_restore_panic_data_from_bram(); } static void system_reset_cause_is_unknown(void) @@ -134,7 +188,7 @@ static void system_reset_cause_is_unknown(void) * eg: Andes core (jral5: LP=PC+2, jal: LP=PC+4) */ ccprintf("===Unknown reset! jump from %x or %x===\n", - ec_reset_lp - 4, ec_reset_lp - 2); + ec_reset_lp - 4, ec_reset_lp - 2); } DECLARE_HOOK(HOOK_INIT, system_reset_cause_is_unknown, HOOK_PRIO_FIRST); @@ -161,6 +215,9 @@ int system_is_reboot_warm(void) void chip_pre_init(void) { + /* bit1=0: disable pre-defined command */ + IT83XX_SMB_SFFCTL &= ~IT83XX_SMB_HSAPE; + /* bit0, EC received the special waveform from iteflash */ if (IT83XX_GCTRL_DBGROS & IT83XX_SMB_DBGR) { /* @@ -187,7 +244,7 @@ void chip_pre_init(void) IT83XX_GCTRL_WMCR |= BIT(7); } -#define BRAM_VALID_MAGIC 0x4252414D /* "BRAM" */ +#define BRAM_VALID_MAGIC 0x4252414D /* "BRAM" */ #define BRAM_VALID_MAGIC_FIELD0 (BRAM_VALID_MAGIC & 0xff) #define BRAM_VALID_MAGIC_FIELD1 ((BRAM_VALID_MAGIC >> 8) & 0xff) #define BRAM_VALID_MAGIC_FIELD2 ((BRAM_VALID_MAGIC >> 16) & 0xff) @@ -212,12 +269,21 @@ void chip_bram_valid(void) BRAM_VALID_FLAGS2 = BRAM_VALID_MAGIC_FIELD2; BRAM_VALID_FLAGS3 = BRAM_VALID_MAGIC_FIELD3; } + +#if defined(CONFIG_PRESERVE_LOGS) && defined(CONFIG_IT83XX_HARD_RESET_BY_GPG1) + if (BRAM_EC_LOG_STATUS == EC_LOG_SAVED_IN_FLASH) { + /* Restore EC logs from flash. */ + memcpy((void *)__preserved_logs_start, + (const void *)CHIP_FLASH_PRESERVE_LOGS_BASE, + (uintptr_t)__preserved_logs_size); + } + BRAM_EC_LOG_STATUS = 0; +#endif } void system_pre_init(void) { /* No initialization required */ - } uint32_t chip_read_reset_flags(void) @@ -248,6 +314,16 @@ void system_reset(int flags) cflush(); } +#if defined(CONFIG_PRESERVE_LOGS) && defined(CONFIG_IT83XX_HARD_RESET_BY_GPG1) + /* Saving EC logs into flash before reset. */ + crec_flash_physical_erase(CHIP_FLASH_PRESERVE_LOGS_BASE, + CHIP_FLASH_PRESERVE_LOGS_SIZE); + crec_flash_physical_write(CHIP_FLASH_PRESERVE_LOGS_BASE, + (uintptr_t)__preserved_logs_size, + __preserved_logs_start); + BRAM_EC_LOG_STATUS = EC_LOG_SAVED_IN_FLASH; +#endif + /* Disable interrupts to avoid task swaps during reboot. */ interrupt_disable(); @@ -276,6 +352,10 @@ void system_reset(int flags) if (flags & SYSTEM_RESET_HARD) IT83XX_GCTRL_ETWDUARTCR |= ETWD_HW_RST_EN; #endif + /* Set GPG1 as output high and wait until EC reset. */ + if (IS_ENABLED(CONFIG_IT83XX_HARD_RESET_BY_GPG1)) + system_reset_ec_by_gpg1(); + /* * Writing invalid key to watchdog module triggers a soft or hardware * reset. It depends on the setting of bit0 at ETWDUARTCR register. @@ -298,23 +378,18 @@ int system_set_scratchpad(uint32_t value) return EC_SUCCESS; } -uint32_t system_get_scratchpad(void) +int system_get_scratchpad(uint32_t *value) { - uint32_t value = 0; - - value |= BRAM_SCRATCHPAD3 << 24; - value |= BRAM_SCRATCHPAD2 << 16; - value |= BRAM_SCRATCHPAD1 << 8; - value |= BRAM_SCRATCHPAD0; - - return value; + *value = (BRAM_SCRATCHPAD3 << 24) | (BRAM_SCRATCHPAD2 << 16) | + (BRAM_SCRATCHPAD1 << 8) | (BRAM_SCRATCHPAD0); + return EC_SUCCESS; } static uint32_t system_get_chip_id(void) { #ifdef IT83XX_CHIP_ID_3BYTES return (IT83XX_GCTRL_CHIPID1 << 16) | (IT83XX_GCTRL_CHIPID2 << 8) | - IT83XX_GCTRL_CHIPID3; + IT83XX_GCTRL_CHIPID3; #else return (IT83XX_GCTRL_CHIPID1 << 8) | IT83XX_GCTRL_CHIPID2; #endif @@ -340,7 +415,7 @@ const char *system_get_chip_vendor(void) const char *system_get_chip_name(void) { - static char buf[8] = {'i', 't'}; + static char buf[8] = { 'i', 't' }; int num = (IS_ENABLED(IT83XX_CHIP_ID_3BYTES) ? 4 : 3); uint32_t chip_id = system_get_chip_id(); @@ -363,10 +438,6 @@ const char *system_get_chip_revision(void) static int bram_idx_lookup(enum system_bbram_idx idx) { - if (idx >= SYSTEM_BBRAM_IDX_VBNVBLOCK0 && - idx <= SYSTEM_BBRAM_IDX_VBNVBLOCK15) - return BRAM_IDX_NVCONTEXT + - idx - SYSTEM_BBRAM_IDX_VBNVBLOCK0; if (idx == SYSTEM_BBRAM_IDX_PD0) return BRAM_IDX_PD0; if (idx == SYSTEM_BBRAM_IDX_PD1) @@ -398,9 +469,6 @@ int system_set_bbram(enum system_bbram_idx idx, uint8_t value) return EC_SUCCESS; } -#define BRAM_NVCONTEXT_SIZE (BRAM_IDX_NVCONTEXT_END - BRAM_IDX_NVCONTEXT + 1) -BUILD_ASSERT(EC_VBNV_BLOCK_SIZE <= BRAM_NVCONTEXT_SIZE); - uintptr_t system_get_fw_reset_vector(uintptr_t base) { /* diff --git a/chip/it83xx/uart.c b/chip/it83xx/uart.c index d0b645e68c..6635c5966e 100644 --- a/chip/it83xx/uart.c +++ b/chip/it83xx/uart.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,7 +17,7 @@ #include "util.h" /* Traces on UART1 */ -#define UART_PORT 0 +#define UART_PORT 0 #define UART_PORT_HOST 1 static int init_done; diff --git a/chip/it83xx/watchdog.c b/chip/it83xx/watchdog.c index f0e200c4ac..b67987d899 100644 --- a/chip/it83xx/watchdog.c +++ b/chip/it83xx/watchdog.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -24,9 +24,9 @@ static int wdt_warning_fired; */ /* Magic value to tickle the watchdog register. */ -#define ITE83XX_WATCHDOG_MAGIC_WORD 0x5C +#define ITE83XX_WATCHDOG_MAGIC_WORD 0x5C /* Start to print warning message. */ -#define ITE83XX_WATCHDOG_WARNING_MS CONFIG_AUX_TIMER_PERIOD_MS +#define ITE83XX_WATCHDOG_WARNING_MS CONFIG_AUX_TIMER_PERIOD_MS /* The interval to print warning message at critical period. */ #define ITE83XX_WATCHDOG_CRITICAL_MS 30 @@ -38,14 +38,27 @@ static void watchdog_set_warning_timer(int32_t ms, int init) void watchdog_warning_irq(void) { -#ifdef CONFIG_SOFTWARE_PANIC - struct panic_data * const pdata_ptr = get_panic_data_write(); - + /* + * Why we directly use the PANIC_DATA_PTR: + * + * We don't get the panic data pointer from get_panic_data_write() + * because this interrupt fires on a warning and we don't want to + * initialize a panic with only a warning. We also don't use + * panic_get_data() because that function returns a NULL pointer if + * panic data was never prior initialized. + * + * Why we fill ipc/mepc here in the watchdog bark/warning interrupt: + * + * In ITE, a full watchdog bite results in an EC reset that bypasses all + * exception handlers. We save the program counter now (during a + * warning) before a full watchdog bite occurs so it is accessible after + * the bite. + */ + struct panic_data *const pdata_ptr = PANIC_DATA_PTR; #if defined(CHIP_CORE_NDS32) pdata_ptr->nds_n8.ipc = get_ipc(); #elif defined(CHIP_CORE_RISCV) pdata_ptr->riscv.mepc = get_mepc(); -#endif #endif /* clear interrupt status */ task_clear_pending_irq(et_ctrl_regs[WDT_EXT_TIMER].irq); @@ -64,10 +77,10 @@ void watchdog_warning_irq(void) * LP = PC+4 after a jump and link instruction (jal). */ panic_printf("Pre-WDT warning! IPC:%08x LP:%08x TASK_ID:%d\n", - get_ipc(), ilp, task_get_current()); + get_ipc(), ilp, task_get_current()); #elif defined(CHIP_CORE_RISCV) panic_printf("Pre-WDT warning! MEPC:%08x RA:%08x TASK_ID:%d\n", - get_mepc(), ira, task_get_current()); + get_mepc(), ira, task_get_current()); #endif if (!wdt_warning_fired++) @@ -93,6 +106,7 @@ void watchdog_reload(void) } } DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_SYSJUMP, watchdog_reload, HOOK_PRIO_LAST); int watchdog_init(void) { diff --git a/chip/lm4/adc.c b/chip/lm4/adc.c deleted file mode 100644 index c06ce35df3..0000000000 --- a/chip/lm4/adc.c +++ /dev/null @@ -1,274 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* LM4-specific ADC module for Chrome EC */ - -#include "adc.h" -#include "adc_chip.h" -#include "atomic.h" -#include "clock.h" -#include "console.h" -#include "common.h" -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Maximum time we allow for an ADC conversion */ -#define ADC_TIMEOUT_US SECOND - -static volatile task_id_t task_waiting_on_ss[LM4_ADC_SEQ_COUNT]; - -static void configure_gpio(void) -{ - int i, port, mask; - - /* Use analog function for AIN */ - for (i = 0; i < ADC_CH_COUNT; ++i) { - if (adc_channels[i].gpio_mask) { - mask = adc_channels[i].gpio_mask; - port = adc_channels[i].gpio_port; - LM4_GPIO_DEN(port) &= ~mask; - LM4_GPIO_AMSEL(port) |= mask; - } - } -} - -/** - * Flush an ADC sequencer and initiate a read. - * - * @param seq Sequencer to read - * @return Raw ADC value. - */ -static int flush_and_read(enum lm4_adc_sequencer seq) -{ - /* - * This is currently simple because we can dedicate a sequencer to each - * ADC channel. If we have enough channels that's no longer possible, - * this code will need to become more complex. For example, we could: - * - * 1) Read them all using a timer interrupt, and then return the most - * recent value? This is lowest-latency for the caller, but won't - * return accurate data if read frequently. - * - * 2) Reserve SS3 for reading a single value, and configure it on each - * read? Needs mutex if we could have multiple callers; doesn't matter - * if just used for debugging. - * - * 3) Both? - */ - volatile uint32_t scratch __attribute__((unused)); - int event; - - /* Empty the FIFO of any previous results */ - while (!(LM4_ADC_SSFSTAT(seq) & 0x100)) - scratch = LM4_ADC_SSFIFO(seq); - - /* - * This assumes we don't have multiple tasks accessing the same - * sequencer. Add mutex lock if needed. - */ - task_waiting_on_ss[seq] = task_get_current(); - - /* Clear the interrupt status */ - LM4_ADC_ADCISC |= 0x01 << seq; - - /* Enable interrupt */ - LM4_ADC_ADCIM |= 0x01 << seq; - - /* Initiate sample sequence */ - LM4_ADC_ADCPSSI |= 0x01 << seq; - - /* Wait for interrupt */ - event = task_wait_event_mask(TASK_EVENT_ADC_DONE, ADC_TIMEOUT_US); - - /* Disable interrupt */ - LM4_ADC_ADCIM &= ~(0x01 << seq); - - task_waiting_on_ss[seq] = TASK_ID_INVALID; - - if (!(event & TASK_EVENT_ADC_DONE)) - return ADC_READ_ERROR; - - /* Read the FIFO and convert to temperature */ - return LM4_ADC_SSFIFO(seq); -} - -/** - * Configure an ADC sequencer to be dedicated for an ADC input. - * - * @param seq Sequencer to configure - * @param ain_id ADC input to use - * @param ssctl Value for sampler sequencer control register - * - */ -static void adc_configure(const struct adc_t *adc) -{ - const enum lm4_adc_sequencer seq = adc->sequencer; - - /* Configure sample sequencer */ - LM4_ADC_ADCACTSS &= ~(0x01 << seq); - - /* Trigger sequencer by processor request */ - LM4_ADC_ADCEMUX = (LM4_ADC_ADCEMUX & ~(0xf << (seq * 4))) | 0x00; - - /* Sample internal temp sensor */ - if (adc->channel == LM4_AIN_NONE) { - LM4_ADC_SSMUX(seq) = 0x00; - LM4_ADC_SSEMUX(seq) = 0x00; - } else { - LM4_ADC_SSMUX(seq) = adc->channel & 0xf; - LM4_ADC_SSEMUX(seq) = adc->channel >> 4; - } - LM4_ADC_SSCTL(seq) = adc->flag; - - /* Enable sample sequencer */ - LM4_ADC_ADCACTSS |= 0x01 << seq; -} - -int adc_read_channel(enum adc_channel ch) -{ - const struct adc_t *adc = adc_channels + ch; - static uint32_t ch_busy_mask; - static struct mutex adc_clock; - int rv; - - /* - * TODO(crbug.com/314121): Generalize ADC reads such that any task can - * trigger a read of any channel. - */ - - /* - * Enable ADC clock and set a bit in ch_busy_mask to signify that this - * channel is busy. Note, this function may be called from multiple - * tasks, but each channel may be read by only one task. If assert - * fails, then it means multiple tasks are trying to read same channel. - */ - mutex_lock(&adc_clock); - ASSERT(!(ch_busy_mask & (1UL << ch))); - clock_enable_peripheral(CGC_OFFSET_ADC, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); - ch_busy_mask |= (1UL << ch); - mutex_unlock(&adc_clock); - - rv = flush_and_read(adc->sequencer); - - /* - * If no ADC channels are busy, then disable ADC clock to conserve - * power. - */ - mutex_lock(&adc_clock); - ch_busy_mask &= ~(1UL << ch); - if (!ch_busy_mask) - clock_disable_peripheral(CGC_OFFSET_ADC, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); - mutex_unlock(&adc_clock); - - if (rv == ADC_READ_ERROR) - return ADC_READ_ERROR; - - return rv * adc->factor_mul / adc->factor_div + adc->shift; -} - -/*****************************************************************************/ -/* Interrupt handlers */ - -/** - * Handle an interrupt on the specified sample sequencer. - */ -static void handle_interrupt(int ss) -{ - int id = task_waiting_on_ss[ss]; - - /* Clear the interrupt status */ - LM4_ADC_ADCISC = (0x1 << ss); - - /* Wake up the task which was waiting on the interrupt, if any */ - if (id != TASK_ID_INVALID) - task_set_event(id, TASK_EVENT_ADC_DONE, 0); -} - -void ss0_interrupt(void) { handle_interrupt(0); } -void ss1_interrupt(void) { handle_interrupt(1); } -void ss2_interrupt(void) { handle_interrupt(2); } -void ss3_interrupt(void) { handle_interrupt(3); } - -DECLARE_IRQ(LM4_IRQ_ADC0_SS0, ss0_interrupt, 2); -DECLARE_IRQ(LM4_IRQ_ADC0_SS1, ss1_interrupt, 2); -DECLARE_IRQ(LM4_IRQ_ADC0_SS2, ss2_interrupt, 2); -DECLARE_IRQ(LM4_IRQ_ADC0_SS3, ss3_interrupt, 2); - -/*****************************************************************************/ -/* Console commands */ - -#ifdef CONFIG_CMD_ECTEMP -static int command_ectemp(int argc, char **argv) -{ - int t = adc_read_channel(ADC_CH_EC_TEMP); - ccprintf("EC temperature is %d K = %d C\n", t, K_TO_C(t)); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(ectemp, command_ectemp, - NULL, - "Print EC temperature"); -#endif - -/*****************************************************************************/ -/* Initialization */ - -static void adc_init(void) -{ - int i; - - /* Configure GPIOs */ - configure_gpio(); - - /* - * Temporarily enable the PLL when turning on the clock to the ADC - * module, to work around chip errata (10.4). No need to notify - * other modules; the PLL isn't enabled long enough to matter. - */ - clock_enable_pll(1, 0); - - /* Enable ADC0 module in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_ADC, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - /* - * Use external voltage references (VREFA+, VREFA-) instead of - * VDDA and GNDA. - */ - LM4_ADC_ADCCTL = 0x01; - - /* Use internal oscillator */ - LM4_ADC_ADCCC = 0x1; - - /* Disable the PLL now that the ADC is using the internal oscillator */ - clock_enable_pll(0, 0); - - /* No tasks waiting yet */ - for (i = 0; i < LM4_ADC_SEQ_COUNT; i++) - task_waiting_on_ss[i] = TASK_ID_INVALID; - - /* Enable IRQs */ - task_enable_irq(LM4_IRQ_ADC0_SS0); - task_enable_irq(LM4_IRQ_ADC0_SS1); - task_enable_irq(LM4_IRQ_ADC0_SS2); - task_enable_irq(LM4_IRQ_ADC0_SS3); - - /* 2**6 = 64x oversampling */ - LM4_ADC_ADCSAC = 6; - - /* Initialize ADC sequencer */ - for (i = 0; i < ADC_CH_COUNT; ++i) - adc_configure(adc_channels + i); - - /* Disable ADC0 module until it is needed to conserve power. */ - clock_disable_peripheral(CGC_OFFSET_ADC, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); -} -DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_INIT_ADC); diff --git a/chip/lm4/adc_chip.h b/chip/lm4/adc_chip.h deleted file mode 100644 index b43bec2da3..0000000000 --- a/chip/lm4/adc_chip.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* LM4-specific ADC module for Chrome EC */ - -#ifndef __CROS_EC_ADC_CHIP_H -#define __CROS_EC_ADC_CHIP_H - -enum lm4_adc_sequencer { - LM4_ADC_SEQ0 = 0, - LM4_ADC_SEQ1, - LM4_ADC_SEQ2, - LM4_ADC_SEQ3, - LM4_ADC_SEQ_COUNT -}; - -/* Data structure to define ADC channels. */ -struct adc_t { - const char *name; - enum lm4_adc_sequencer sequencer; - int factor_mul; - int factor_div; - int shift; - int channel; - int flag; - uint32_t gpio_port; - uint8_t gpio_mask; -}; - -/* - * Boards must provide this list of ADC channel definitions. This must match - * the enum adc_channel list provided by the board. - */ -extern const struct adc_t adc_channels[]; - -/* Minimum and maximum values returned by raw ADC read. */ -#define ADC_READ_MIN 0 -#define ADC_READ_MAX 4095 - -/* Just plain id mapping for code readability */ -#define LM4_AIN(x) (x) - -/* Mock value for "channel" in adc_t if we don't have an external channel. */ -#define LM4_AIN_NONE (-1) - -#endif /* __CROS_EC_ADC_CHIP_H */ diff --git a/chip/lm4/build.mk b/chip/lm4/build.mk deleted file mode 100644 index 26419d3a04..0000000000 --- a/chip/lm4/build.mk +++ /dev/null @@ -1,31 +0,0 @@ -# -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# LM4 chip specific files build -# - -# LM4 SoC has a Cortex-M4F ARM core -CORE:=cortex-m -# Allow the full Cortex-M4 instruction set -CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4 - -# Required chip modules -chip-y=clock.o gpio.o hwtimer.o system.o uart.o - -# Optional chip modules -chip-$(CONFIG_ADC)+=adc.o chip_temp_sensor.o -chip-$(CONFIG_EEPROM)+=eeprom.o -chip-$(CONFIG_FANS)+=fan.o -chip-$(CONFIG_FLASH_PHYSICAL)+=flash.o -chip-$(CONFIG_I2C)+=i2c.o -chip-$(CONFIG_HOSTCMD_LPC)+=lpc.o -chip-$(CONFIG_PECI)+=peci.o -# pwm functions are implemented with the fan functions -chip-$(CONFIG_PWM)+=pwm.o fan.o -chip-$(CONFIG_SPI)+=spi.o -chip-$(CONFIG_WATCHDOG)+=watchdog.o -ifndef CONFIG_KEYBOARD_NOT_RAW -chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o -endif diff --git a/chip/lm4/chip_temp_sensor.c b/chip/lm4/chip_temp_sensor.c deleted file mode 100644 index eb1bc4d133..0000000000 --- a/chip/lm4/chip_temp_sensor.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Temperature sensor module for Chrome EC */ - -#include "adc.h" -#include "adc_chip.h" -#include "common.h" -#include "hooks.h" - -/* Initialize temperature reading to a valid value (27 C) */ -static int last_val = C_TO_K(27); - -static void chip_temp_sensor_poll(void) -{ - last_val = adc_read_channel(ADC_CH_EC_TEMP); -} -DECLARE_HOOK(HOOK_SECOND, chip_temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -int chip_temp_sensor_get_val(int idx, int *temp_ptr) -{ - if (last_val == ADC_READ_ERROR) - return EC_ERROR_UNKNOWN; - - *temp_ptr = last_val; - - return EC_SUCCESS; -} diff --git a/chip/lm4/clock.c b/chip/lm4/clock.c deleted file mode 100644 index 39800c9034..0000000000 --- a/chip/lm4/clock.c +++ /dev/null @@ -1,754 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Clocks and power management settings */ - -#include "clock.h" -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "gpio.h" -#include "hooks.h" -#include "hwtimer.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "uart.h" -#include "util.h" -#include "watchdog.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) - -#define PLL_CLOCK 66666667 /* System clock = 200MHz PLL/3 = 66.667MHz */ - -#ifdef CONFIG_LOW_POWER_USE_LFIOSC -/* - * Length of time for the processor to wake up from deep sleep. Actual - * measurement gives anywhere up to 780us, depending on the mode it is coming - * out of. The datasheet gives a maximum of 846us, for coming out of deep - * sleep in our worst case deep sleep mode. - */ -#define DEEP_SLEEP_RECOVER_TIME_USEC 850 -#else -/* - * Length of time for the processor to wake up from deep sleep. Datasheet - * maximum is 145us, but in practice have seen as much as 336us. - */ -#define DEEP_SLEEP_RECOVER_TIME_USEC 400 -#endif - -/* Low power idle statistics */ -#ifdef CONFIG_LOW_POWER_IDLE -static int idle_sleep_cnt; -static int idle_dsleep_cnt; -static uint64_t idle_dsleep_time_us; -static int dsleep_recovery_margin_us = 1000000; - -/* - * Fixed amount of time to keep the console in use flag true after boot in - * order to give a permanent window in which the low speed clock is not used. - */ -#define CONSOLE_IN_USE_ON_BOOT_TIME (15*SECOND) - -static int console_in_use_timeout_sec = 60; -static timestamp_t console_expire_time; -#endif - -static int freq; - -/** - * Disable the PLL; run off internal oscillator. - */ -static void disable_pll(void) -{ - /* Switch to 16MHz internal oscillator and power down the PLL */ - LM4_SYSTEM_RCC = LM4_SYSTEM_RCC_SYSDIV(0) | - LM4_SYSTEM_RCC_BYPASS | - LM4_SYSTEM_RCC_PWRDN | - LM4_SYSTEM_RCC_OSCSRC(1) | - LM4_SYSTEM_RCC_MOSCDIS; - -#ifdef CONFIG_LOW_POWER_IDLE - /* - * If using the low power idle, then set the ACG bit, which specifies - * that the sleep and deep sleep modes are using their own clock gating - * registers SCGC and DCGS respectively instead of using the run mode - * clock gating registers RCGC. - */ - LM4_SYSTEM_RCC |= LM4_SYSTEM_RCC_ACG; -#endif - - LM4_SYSTEM_RCC2 &= ~LM4_SYSTEM_RCC2_USERCC2; - - freq = INTERNAL_CLOCK; -} - -/** - * Enable the PLL to run at full clock speed. - */ -static void enable_pll(void) -{ - /* Disable the PLL so we can reconfigure it */ - disable_pll(); - - /* - * Enable the PLL (PWRDN is no longer set) and set divider. PLL is - * still bypassed, since it hasn't locked yet. - */ - LM4_SYSTEM_RCC = LM4_SYSTEM_RCC_SYSDIV(2) | - LM4_SYSTEM_RCC_USESYSDIV | - LM4_SYSTEM_RCC_BYPASS | - LM4_SYSTEM_RCC_OSCSRC(1) | - LM4_SYSTEM_RCC_MOSCDIS; - -#ifdef CONFIG_LOW_POWER_IDLE - /* - * If using the low power idle, then set the ACG bit, which specifies - * that the sleep and deep sleep modes are using their own clock gating - * registers SCGC and DCGS respectively instead of using the run mode - * clock gating registers RCGC. - */ - LM4_SYSTEM_RCC |= LM4_SYSTEM_RCC_ACG; -#endif - - /* Wait for the PLL to lock */ - clock_wait_cycles(1024); - while (!(LM4_SYSTEM_PLLSTAT & 1)) - ; - - /* Remove bypass on PLL */ - LM4_SYSTEM_RCC &= ~LM4_SYSTEM_RCC_BYPASS; - freq = PLL_CLOCK; -} - -void clock_enable_pll(int enable, int notify) -{ - if (enable) - enable_pll(); - else - disable_pll(); - - /* Notify modules of frequency change */ - if (notify) - hook_notify(HOOK_FREQ_CHANGE); -} - -void clock_wait_cycles(uint32_t cycles) -{ - asm volatile("1: subs %0, #1\n" - " bne 1b\n" : "+r"(cycles)); -} - -int clock_get_freq(void) -{ - return freq; -} - -void clock_init(void) -{ -#ifdef BOARD_BDS - /* - * Perform an auto calibration of the internal oscillator using the - * 32.768KHz hibernate clock, unless we've already done so. This is - * only necessary on A2 silicon as on BDS; A3 silicon is all - * factory-trimmed. - */ - if ((LM4_SYSTEM_PIOSCSTAT & 0x300) != 0x100) { - /* Start calibration */ - LM4_SYSTEM_PIOSCCAL = 0x80000000; - LM4_SYSTEM_PIOSCCAL = 0x80000200; - /* Wait for result */ - clock_wait_cycles(16); - while (!(LM4_SYSTEM_PIOSCSTAT & 0x300)) - ; - } -#else - /* - * Only BDS has an external crystal; other boards don't have one, and - * can disable main oscillator control to reduce power consumption. - */ - LM4_SYSTEM_MOSCCTL = 0x04; -#endif - - /* Make sure PLL is disabled */ - disable_pll(); -} - -void clock_enable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) -{ - if (mode & CGC_MODE_RUN) - *(LM4_SYSTEM_RCGC_BASE + offset) |= mask; - - if (mode & CGC_MODE_SLEEP) - *(LM4_SYSTEM_SCGC_BASE + offset) |= mask; - - if (mode & CGC_MODE_DSLEEP) - *(LM4_SYSTEM_DCGC_BASE + offset) |= mask; - - /* Wait for clock change to take affect. */ - clock_wait_cycles(3); -} - -void clock_disable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) -{ - if (mode & CGC_MODE_RUN) - *(LM4_SYSTEM_RCGC_BASE + offset) &= ~mask; - - if (mode & CGC_MODE_SLEEP) - *(LM4_SYSTEM_SCGC_BASE + offset) &= ~mask; - - if (mode & CGC_MODE_DSLEEP) - *(LM4_SYSTEM_DCGC_BASE + offset) &= ~mask; -} - -/* - * The low power idle task does not support using the EEPROM, - * because it is dangerous to go to deep sleep while EEPROM - * transaction is in progress. To fix, LM4_EEPROM_EEDONE, should - * be checked before going in to deep sleep. - */ -#if defined(CONFIG_LOW_POWER_IDLE) && defined(CONFIG_EEPROM) -#error "Low power idle mode does not support use of EEPROM" -#endif - -#ifdef CONFIG_LOW_POWER_IDLE - -void clock_refresh_console_in_use(void) -{ - disable_sleep(SLEEP_MASK_CONSOLE); - - /* Set console in use expire time. */ - console_expire_time = get_time(); - console_expire_time.val += console_in_use_timeout_sec * SECOND; - -} - -/* Low power idle task. Executed when no tasks are ready to be scheduled. */ -void __idle(void) -{ - timestamp_t t0, t1, rtc_t0, rtc_t1; - int next_delay = 0; - int time_for_dsleep, margin_us; - int use_low_speed_clock; - - /* Enable the hibernate IRQ used to wake up from deep sleep */ - system_enable_hib_interrupt(); - - /* Set SRAM and flash power management to 'low power' in deep sleep. */ - LM4_SYSTEM_DSLPPWRCFG = 0x23; - - /* Enable JTAG interrupt which will notify us when JTAG is in use. */ - gpio_enable_interrupt(GPIO_JTAG_TCK); - - /* - * Initialize console in use to true and specify the console expire - * time in order to give a fixed window on boot in which the low speed - * clock will not be used in idle. - */ - disable_sleep(SLEEP_MASK_CONSOLE); - console_expire_time.val = get_time().val + CONSOLE_IN_USE_ON_BOOT_TIME; - - /* - * Print when the idle task starts. This is the lowest priority task, - * so this only starts once all other tasks have gotten a chance to do - * their task inits and have gone to sleep. - */ - CPRINTS("low power idle task started"); - - while (1) { - /* - * Disable interrupts before going to deep sleep in order to - * calculate the appropriate time to wake up. Note: the wfi - * instruction waits until an interrupt is pending, so it - * will still wake up even with interrupts disabled. - */ - interrupt_disable(); - - t0 = get_time(); - next_delay = __hw_clock_event_get() - t0.le.lo; - - /* Do we have enough time before next event to deep sleep. */ - time_for_dsleep = next_delay > (DEEP_SLEEP_RECOVER_TIME_USEC + - HIB_SET_RTC_MATCH_DELAY_USEC); - - if (DEEP_SLEEP_ALLOWED && time_for_dsleep) { - /* Deep-sleep in STOP mode. */ - idle_dsleep_cnt++; - - /* Check if the console use has expired. */ - if ((sleep_mask & SLEEP_MASK_CONSOLE) && - t0.val > console_expire_time.val) { - /* Enable low speed deep sleep. */ - enable_sleep(SLEEP_MASK_CONSOLE); - - /* - * Wait one clock before checking if low speed - * deep sleep is allowed to give time for - * sleep mask to update. - */ - clock_wait_cycles(1); - - if (LOW_SPEED_DEEP_SLEEP_ALLOWED) - CPRINTS("Disabling console in " - "deep sleep"); - } - - /* - * Determine if we should use a lower clock speed or - * keep the same (16MHz) clock in deep sleep. Use the - * lower speed only if the sleep mask specifies that low - * speed sleep is allowed, the console UART TX is not - * busy, and the console UART buffer is empty. - */ - use_low_speed_clock = LOW_SPEED_DEEP_SLEEP_ALLOWED && - !uart_tx_in_progress() && uart_buffer_empty(); - -#ifdef CONFIG_LOW_POWER_USE_LFIOSC - /* Set the deep sleep clock register. Use either the - * normal PIOSC (16MHz) or the LFIOSC (32kHz). */ - LM4_SYSTEM_DSLPCLKCFG = use_low_speed_clock ? - 0x32 : 0x10; -#else - /* - * Set the deep sleep clock register. Use either the - * PIOSC with no divider (16MHz) or the PIOSC with - * a /64 divider (250kHz). - */ - LM4_SYSTEM_DSLPCLKCFG = use_low_speed_clock ? - 0x1f800010 : 0x10; -#endif - - /* - * If using low speed clock, disable console. - * This will also convert the console RX pin to a GPIO - * and set an edge interrupt to wake us from deep sleep - * if any action occurs on console. - */ - if (use_low_speed_clock) - uart_enter_dsleep(); - - /* Set deep sleep bit. */ - CPU_SCB_SYSCTRL |= 0x4; - - /* Record real time before sleeping. */ - rtc_t0 = system_get_rtc(); - - /* - * Set RTC interrupt in time to wake up before - * next event. - */ - system_set_rtc_alarm(0, next_delay - - DEEP_SLEEP_RECOVER_TIME_USEC); - - /* Wait for interrupt: goes into deep sleep. */ - asm("wfi"); - - /* Clear deep sleep bit. */ - CPU_SCB_SYSCTRL &= ~0x4; - - /* Disable and clear RTC interrupt. */ - system_reset_rtc_alarm(); - - /* Fast forward timer according to RTC counter. */ - rtc_t1 = system_get_rtc(); - t1.val = t0.val + (rtc_t1.val - rtc_t0.val); - force_time(t1); - - /* If using low speed clock, re-enable the console. */ - if (use_low_speed_clock) - uart_exit_dsleep(); - - /* Record time spent in deep sleep. */ - idle_dsleep_time_us += (rtc_t1.val - rtc_t0.val); - - /* Calculate how close we were to missing deadline */ - margin_us = next_delay - (int)(rtc_t1.val - rtc_t0.val); - if (margin_us < 0) - CPRINTS("overslept by %dus", -margin_us); - - /* Record the closest to missing a deadline. */ - if (margin_us < dsleep_recovery_margin_us) - dsleep_recovery_margin_us = margin_us; - } else { - idle_sleep_cnt++; - - /* Normal idle : only CPU clock stopped. */ - asm("wfi"); - } - interrupt_enable(); - } -} -#endif /* CONFIG_LOW_POWER_IDLE */ - -/*****************************************************************************/ -/* Console commands */ - -#ifdef CONFIG_CMD_SLEEP -/** - * Measure baseline for power consumption. - * - * Levels : - * 0 : CPU running in tight loop - * 1 : CPU running in tight loop but peripherals gated - * 2 : CPU in sleep mode - * 3 : CPU in sleep mode and peripherals gated - * 4 : CPU in deep sleep mode - * 5 : CPU in deep sleep mode and peripherals gated - * - * Clocks : - * 0 : No change - * 1 : 16MHz - * 2 : 1 MHz - * 3 : 30kHz - * - * SRAM Power Management: - * 0 : Active - * 1 : Standby - * 3 : Low Power - * - * Flash Power Management: - * 0 : Active - * 2 : Low Power - */ -static int command_sleep(int argc, char **argv) -{ - int level = 0; - int clock = 0; - int sram_pm = 0; - int flash_pm = 0; - uint32_t uartibrd = 0; - uint32_t uartfbrd = 0; - - if (argc >= 2) - level = strtoi(argv[1], NULL, 10); - if (argc >= 3) - clock = strtoi(argv[2], NULL, 10); - if (argc >= 4) - sram_pm = strtoi(argv[3], NULL, 10); - if (argc >= 5) - flash_pm = strtoi(argv[4], NULL, 10); - -#ifdef BOARD_BDS - /* Remove LED current sink. */ - gpio_set_level(GPIO_DEBUG_LED, 0); -#endif - - ccprintf("Sleep : level %d, clock %d, sram pm %d, flash_pm %d...\n", - level, clock, sram_pm, flash_pm); - cflush(); - - /* Set clock speed. */ - if (clock) { - /* Use ROM code function to set the clock */ - void **func_table = (void **)*(uint32_t *)0x01000044; - void (*rom_clock_set)(uint32_t rcc) = func_table[23]; - - /* Disable interrupts. */ - asm volatile("cpsid i"); - - switch (clock) { - case 1: /* 16MHz IOSC */ - uartibrd = 17; - uartfbrd = 23; - rom_clock_set(0x00000d51); - break; - case 2: /* 1MHz IOSC */ - uartibrd = 1; - uartfbrd = 5; - rom_clock_set(0x07C00d51); - break; - case 3: /* 30 kHz */ - uartibrd = 0; - uartfbrd = 0; - rom_clock_set(0x00000d71); - break; - } - - /* - * TODO(crosbug.com/p/23795): move this to the UART module; - * ugly to have UARTisms here. Also note this only fixes - * UART0, not UART1. Should just be able to trigger - * HOOK_FREQ_CHANGE and have that take care of it. - */ - if (uartfbrd) { - /* Disable the port via UARTCTL and add HSE. */ - LM4_UART_CTL(0) = 0x0320; - /* Set the baud rate divisor. */ - LM4_UART_IBRD(0) = uartibrd; - LM4_UART_FBRD(0) = uartfbrd; - /* Poke UARTLCRH to make the new divisor take effect. */ - LM4_UART_LCRH(0) = LM4_UART_LCRH(0); - /* Enable the port. */ - LM4_UART_CTL(0) |= 0x0001; - } - asm volatile("cpsie i"); - } - - if (uartfbrd) { - ccprintf("We are still alive. RCC=%08x\n", LM4_SYSTEM_RCC); - cflush(); - } - - /* Enable interrupts. */ - asm volatile("cpsid i"); - - /* gate peripheral clocks */ - if (level & 1) { - clock_disable_peripheral(CGC_OFFSET_WD, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_TIMER, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_GPIO, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_DMA, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_HIB, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_UART, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_SSI, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_I2C, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_ADC, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_LPC, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_PECI, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_FAN, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_EEPROM, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_WTIMER, 0xffffffff, - CGC_MODE_ALL); - } - - /* Set deep sleep bit. */ - if (level >= 4) - CPU_SCB_SYSCTRL |= 0x4; - - /* Set SRAM and flash PM for sleep and deep sleep. */ - LM4_SYSTEM_SLPPWRCFG = (flash_pm << 4) | sram_pm; - LM4_SYSTEM_DSLPPWRCFG = (flash_pm << 4) | sram_pm; - - /* Go to low power mode (forever ...) */ - if (level > 1) - while (1) { - asm("wfi"); - watchdog_reload(); - } - else - while (1) - watchdog_reload(); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(sleep, command_sleep, - "[level [clock] [sram pm] [flash pm]]", - "Drop into sleep"); -#endif /* CONFIG_CMD_SLEEP */ - -#ifdef CONFIG_CMD_PLL - -static int command_pll(int argc, char **argv) -{ - int v; - - /* Toggle the PLL */ - if (argc > 1) { - if (parse_bool(argv[1], &v)) { - clock_enable_pll(v, 1); - } else { - /* Disable PLL and set extra divider */ - char *e; - v = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - - LM4_SYSTEM_RCC = LM4_SYSTEM_RCC_SYSDIV(v - 1) | - LM4_SYSTEM_RCC_BYPASS | - LM4_SYSTEM_RCC_PWRDN | - LM4_SYSTEM_RCC_OSCSRC(1) | - LM4_SYSTEM_RCC_MOSCDIS; - - freq = INTERNAL_CLOCK / v; - - /* Notify modules of frequency change */ - hook_notify(HOOK_FREQ_CHANGE); - } - } - - /* Print current PLL state */ - ccprintf("RCC: 0x%08x\n", LM4_SYSTEM_RCC); - ccprintf("RCC2: 0x%08x\n", LM4_SYSTEM_RCC2); - ccprintf("PLLSTAT: 0x%08x\n", LM4_SYSTEM_PLLSTAT); - ccprintf("Clock: %d Hz\n", clock_get_freq()); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(pll, command_pll, - "[ on | off |
]", - "Get/set PLL state"); - -#endif /* CONFIG_CMD_PLL */ - -#ifdef CONFIG_CMD_CLOCKGATES -/** - * Print all clock gating registers - */ -static int command_clock_gating(int argc, char **argv) -{ - ccprintf(" Run , Sleep , Deep Sleep\n"); - - ccprintf("WD: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_WD)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_WD)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_WD)); - - ccprintf("TIMER: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_TIMER)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_TIMER)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_TIMER)); - - ccprintf("GPIO: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_GPIO)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_GPIO)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_GPIO)); - - ccprintf("DMA: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_DMA)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_DMA)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_DMA)); - - ccprintf("HIB: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_HIB)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_HIB)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_HIB)); - - ccprintf("UART: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_UART)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_UART)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_UART)); - - ccprintf("SSI: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_SSI)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_SSI)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_SSI)); - - ccprintf("I2C: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_I2C)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_I2C)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_I2C)); - - ccprintf("ADC: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_ADC)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_ADC)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_ADC)); - - ccprintf("LPC: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_LPC)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_LPC)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_LPC)); - - ccprintf("PECI: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_PECI)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_PECI)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_PECI)); - - ccprintf("FAN: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_FAN)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_FAN)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_FAN)); - - ccprintf("EEPROM: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_EEPROM)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_EEPROM)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_EEPROM)); - - ccprintf("WTIMER: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_WTIMER)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_WTIMER)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_WTIMER)); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(clockgates, command_clock_gating, - "", - "Get state of the clock gating controls regs"); -#endif /* CONFIG_CMD_CLOCKGATES */ - -#ifdef CONFIG_LOW_POWER_IDLE -/** - * Print low power idle statistics - */ -static int command_idle_stats(int argc, char **argv) -{ - timestamp_t ts = get_time(); - - ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); - ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); - ccprintf("Time spent in deep-sleep: %.6llds\n", - idle_dsleep_time_us); - ccprintf("Total time on: %.6llds\n", ts.val); - ccprintf("Deep-sleep closest to wake deadline: %dus\n", - dsleep_recovery_margin_us); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, - "", - "Print last idle stats"); - -/** - * Configure deep sleep clock settings. - */ -static int command_dsleep(int argc, char **argv) -{ - int v; - - if (argc > 1) { - if (parse_bool(argv[1], &v)) { - /* - * Force deep sleep not to use low speed clock or - * allow it to use the low speed clock. - */ - if (v) - disable_sleep(SLEEP_MASK_FORCE_NO_LOW_SPEED); - else - enable_sleep(SLEEP_MASK_FORCE_NO_LOW_SPEED); - } else { - /* Set console in use timeout. */ - char *e; - v = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - - console_in_use_timeout_sec = v; - - /* Refresh console in use to use new timeout. */ - clock_refresh_console_in_use(); - } - } - - ccprintf("Sleep mask: %08x\n", sleep_mask); - ccprintf("Console in use timeout: %d sec\n", - console_in_use_timeout_sec); - ccprintf("DSLPCLKCFG register: 0x%08x\n", LM4_SYSTEM_DSLPCLKCFG); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(dsleep, command_dsleep, - "[ on | off | sec]", - "Deep sleep clock settings:\nUse 'on' to force deep " - "sleep not to use low speed clock.\nUse 'off' to " - "allow deep sleep to auto-select using the low speed " - "clock.\n" - "Give a timeout value for the console in use timeout.\n" - "See also 'sleepmask'."); -#endif /* CONFIG_LOW_POWER_IDLE */ - diff --git a/chip/lm4/config_chip.h b/chip/lm4/config_chip.h deleted file mode 100644 index 8abe059e5b..0000000000 --- a/chip/lm4/config_chip.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_CONFIG_CHIP_H -#define __CROS_EC_CONFIG_CHIP_H - -/* CPU core BFD configuration */ -#include "core/cortex-m/config_core.h" - -/* 16.000 MHz internal oscillator frequency (PIOSC) */ -#define INTERNAL_CLOCK 16000000 - -/* Number of IRQ vectors on the NVIC */ -#define CONFIG_IRQ_COUNT 132 - -/* Use a bigger console output buffer */ -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 8192 - -/* Interval between HOOK_TICK notifications */ -#define HOOK_TICK_INTERVAL_MS 250 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) - -/* Number of I2C ports */ -#define I2C_PORT_COUNT 6 - -/* - * Time it takes to set the RTC match register. This value is conservatively - * set based on measurements around 200us. - */ -#define HIB_SET_RTC_MATCH_DELAY_USEC 300 - -/****************************************************************************/ -/* Memory mapping */ - -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00008000 - -/* System stack size */ -#define CONFIG_STACK_SIZE 4096 - -/* non-standard task stack sizes */ -#define IDLE_TASK_STACK_SIZE 512 -#define LARGER_TASK_STACK_SIZE 768 -#define SMALLER_TASK_STACK_SIZE 384 - -/* Default task stack size */ -#define TASK_STACK_SIZE 512 - -#define CONFIG_PROGRAM_MEMORY_BASE 0x00000000 -#define CONFIG_FLASH_BANK_SIZE 0x00000800 /* protect bank size */ -#define CONFIG_FLASH_ERASE_SIZE 0x00000400 /* erase bank size */ -#define CONFIG_FLASH_WRITE_SIZE 0x00000004 /* minimum write size */ - -/* Ideal flash write size fills the 32-entry flash write buffer */ -#define CONFIG_FLASH_WRITE_IDEAL_SIZE (32 * 4) - -/* This is the physical size of the flash on the chip. We'll reserve one bank - * in order to emulate per-bank write-protection UNTIL REBOOT. The hardware - * doesn't support a write-protect pin, and if we make the write-protection - * permanent, it can't be undone easily enough to support RMA. */ -#define CONFIG_FLASH_SIZE 0x00040000 - -/****************************************************************************/ -/* Define our flash layout. */ - -/* Memory-mapped internal flash */ -#define CONFIG_INTERNAL_STORAGE -#define CONFIG_MAPPED_STORAGE - -/* Program is run directly from storage */ -#define CONFIG_MAPPED_STORAGE_BASE CONFIG_PROGRAM_MEMORY_BASE - -/* Compute the rest of the flash params from these */ -#include "config_std_internal_flash.h" - -/****************************************************************************/ -/* Lock the boot configuration to prevent brickage. */ - -/* - * No GPIO trigger for ROM bootloader. - * Keep JTAG debugging enabled. - * Use 0xA442 flash write key. - * Lock it this way. - */ -#define CONFIG_BOOTCFG_VALUE 0x7ffffffe - -/****************************************************************************/ -/* Customize the build */ - -/* Optional features present on this chip */ -#define CONFIG_ADC -#define CONFIG_HOSTCMD_ALIGNED -#define CONFIG_HOSTCMD_LPC -#define CONFIG_PECI -#define CONFIG_RTC -#define CONFIG_SWITCH -#define CONFIG_MPU - -/* Chip needs to do custom pre-init */ -#define CONFIG_CHIP_PRE_INIT - -#define GPIO_PIN(port, index) GPIO_##port, BIT(index) -#define GPIO_PIN_MASK(p, m) .port = GPIO_##p, .mask = (m) - -#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/lm4/eeprom.c b/chip/lm4/eeprom.c deleted file mode 100644 index 97fd3bdc24..0000000000 --- a/chip/lm4/eeprom.c +++ /dev/null @@ -1,268 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* EEPROM module for Chrome EC */ - -#include "clock.h" -#include "console.h" -#include "eeprom.h" -#include "registers.h" -#include "timer.h" -#include "util.h" -#include "watchdog.h" - -/* Size of EEPROM block in bytes */ -#define EEPROM_BLOCK_SIZE 64 - -/* Count of EEPROM blocks */ -static int block_count; - -/* - * Wait for the current EEPROM operation to finish; all operations but write - * should normally finish in 4 system clocks, but worst case is up to - * 1800ms if the EEPROM needs to do an internal page erase/copy. We must - * spin-wait for this delay, because EEPROM operations will fail if the chip - * drops to sleep mode. - */ -static int wait_for_done(void) -{ - int j; - - for (j = 0; j < 20; j++) { /* 20 * 100 ms = 2000 ms */ - uint64_t tstop = get_time().val + 100 * MSEC; - while (get_time().val < tstop) { - if (!(LM4_EEPROM_EEDONE & 0x01)) - return EC_SUCCESS; - } - watchdog_reload(); - } - - return EC_ERROR_UNKNOWN; -} - - -int eeprom_get_block_count(void) -{ - return block_count; -} - - -int eeprom_get_block_size(void) -{ - return EEPROM_BLOCK_SIZE; -} - - -int eeprom_read(int block, int offset, int size, char *data) -{ - uint32_t *d = (uint32_t *)data; - int rv; - - if (block < 0 || block >= block_count || - offset < 0 || offset > EEPROM_BLOCK_SIZE || offset & 3 || - size < 0 || offset + size > EEPROM_BLOCK_SIZE || size & 3) - return EC_ERROR_UNKNOWN; - - rv = wait_for_done(); - if (rv) - return rv; - - LM4_EEPROM_EEBLOCK = block; - if (LM4_EEPROM_EEBLOCK != block) - return EC_ERROR_UNKNOWN; /* Error setting block */ - - LM4_EEPROM_EEOFFSET = offset >> 2; - - for (; size; size -= sizeof(uint32_t)) - *(d++) = LM4_EEPROM_EERDWRINC; - - return EC_SUCCESS; -} - - -int eeprom_write(int block, int offset, int size, const char *data) -{ - uint32_t *d = (uint32_t *)data; - int rv; - - if (block < 0 || block >= block_count || - offset < 0 || offset > EEPROM_BLOCK_SIZE || offset & 3 || - size < 0 || offset + size > EEPROM_BLOCK_SIZE || size & 3) - return EC_ERROR_UNKNOWN; - - rv = wait_for_done(); - if (rv) - return rv; - - LM4_EEPROM_EEBLOCK = block; - if (LM4_EEPROM_EEBLOCK != block) - return EC_ERROR_UNKNOWN; /* Error setting block */ - - LM4_EEPROM_EEOFFSET = offset >> 2; - - /* Write 32 bits at a time; wait for each write to complete */ - for (; size; size -= sizeof(uint32_t)) { - LM4_EEPROM_EERDWRINC = *(d++); - - rv = wait_for_done(); - if (rv) - return rv; - - if (LM4_EEPROM_EEDONE & 0x10) { - /* Failed due to write protect */ - return EC_ERROR_ACCESS_DENIED; - } else if (LM4_EEPROM_EEDONE & 0x100) { - /* Failed due to program voltage level */ - return EC_ERROR_UNKNOWN; - } - } - - return EC_SUCCESS; -} - - -int eeprom_hide(int block) -{ - /* Block 0 can't be hidden */ - if (block <= 0 || block >= block_count) - return EC_ERROR_UNKNOWN; - - LM4_EEPROM_EEHIDE |= 1 << block; - return EC_SUCCESS; -} - - -/*****************************************************************************/ -/* Console commands */ - -static int command_eeprom_info(int argc, char **argv) -{ - ccprintf("%d blocks @ %d bytes, hide=0x%08x\n", - eeprom_get_block_count(), eeprom_get_block_size(), - LM4_EEPROM_EEHIDE); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(eeinfo, command_eeprom_info, - NULL, - "Print EEPROM info"); - - -static int command_eeprom_read(int argc, char **argv) -{ - int block = 0; - int offset = 0; - char *e; - int rv; - uint32_t d; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - block = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - if (argc > 2) { - offset = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - } - - rv = eeprom_read(block, offset, sizeof(d), (char *)&d); - if (rv == EC_SUCCESS) - ccprintf("%d:%d = 0x%08x\n", block, offset, d); - return rv; -} -DECLARE_CONSOLE_COMMAND(eeread, command_eeprom_read, - "block [offset]", - "Read a word of EEPROM"); - - -static int command_eeprom_write(int argc, char **argv) -{ - int block = 0; - int offset = 0; - char *e; - uint32_t d; - - if (argc < 4) - return EC_ERROR_PARAM_COUNT; - - block = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - offset = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - d = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - ccprintf("Writing 0x%08x to %d:%d...\n", d, block, offset); - return eeprom_write(block, offset, sizeof(d), (char *)&d); -} -DECLARE_CONSOLE_COMMAND(eewrite, command_eeprom_write, - "block offset value", - "Write a word of EEPROM"); - - -#ifdef CONSOLE_COMMAND_EEHIDE -static int command_eeprom_hide(int argc, char **argv) -{ - int block = 0; - char *e; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - block = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - ccprintf("Hiding block %d\n", block); - return eeprom_hide(block); -} -DECLARE_CONSOLE_COMMAND(eehide, command_eeprom_hide, - "block", - "Hide a block of EEPROM"); -#endif - - -/*****************************************************************************/ -/* Initialization */ - - -int eeprom_init(void) -{ - /* Enable the EEPROM module in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_EEPROM, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - /* Wait for internal EEPROM init to finish */ - wait_for_done(); - - /* Store block count */ - block_count = LM4_EEPROM_EESIZE >> 16; - - /* - * Handle resetting the EEPROM module to clear state from a previous - * error condition. - */ - if (LM4_EEPROM_EESUPP & 0xc0) { - LM4_SYSTEM_SREEPROM = 1; - clock_wait_cycles(200); - LM4_SYSTEM_SREEPROM = 0; - - /* Wait again for internal init to finish */ - clock_wait_cycles(6); - wait_for_done(); - - /* Fail if error condition didn't clear */ - if (LM4_EEPROM_EESUPP & 0xc0) - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} diff --git a/chip/lm4/fan.c b/chip/lm4/fan.c deleted file mode 100644 index b09323a37b..0000000000 --- a/chip/lm4/fan.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* LM4 fan control module. */ - -#include "clock.h" -#include "fan.h" -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "util.h" - -/* Maximum RPM for fan controller */ -#define MAX_RPM 0x1fff - -/* Maximum PWM for PWM controller */ -#define MAX_PWM 0x1ff - -/* - * Scaling factor for requested/actual RPM for CPU fan. We need this because - * the fan controller on Blizzard filters tach pulses that are less than 64 - * 15625Hz ticks apart, which works out to ~7000rpm on an unscaled fan. By - * telling the controller we actually have twice as many edges per revolution, - * the controller can handle fans that actually go twice as fast. See - * crosbug.com/p/7718. - */ -#define RPM_SCALE 2 - - -void fan_set_enabled(int ch, int enabled) -{ - if (enabled) - LM4_FAN_FANCTL |= BIT(ch); - else - LM4_FAN_FANCTL &= ~BIT(ch); -} - -int fan_get_enabled(int ch) -{ - return (LM4_FAN_FANCTL & BIT(ch)) ? 1 : 0; -} - -void fan_set_duty(int ch, int percent) -{ - int duty; - - if (percent < 0) - percent = 0; - else if (percent > 100) - percent = 100; - - duty = (MAX_PWM * percent + 50) / 100; - - /* Always enable the channel */ - fan_set_enabled(ch, 1); - - /* Set the duty cycle */ - LM4_FAN_FANCMD(ch) = duty << 16; -} - -int fan_get_duty(int ch) -{ - return ((LM4_FAN_FANCMD(ch) >> 16) * 100 + MAX_PWM / 2) / MAX_PWM; -} - -int fan_get_rpm_mode(int ch) -{ - return (LM4_FAN_FANCH(ch) & 0x0001) ? 0 : 1; -} - -void fan_set_rpm_mode(int ch, int rpm_mode) -{ - int was_enabled = fan_get_enabled(ch); - int was_rpm = fan_get_rpm_mode(ch); - - if (!was_rpm && rpm_mode) { - /* Enable RPM control */ - fan_set_enabled(ch, 0); - LM4_FAN_FANCH(ch) &= ~0x0001; - fan_set_enabled(ch, was_enabled); - } else if (was_rpm && !rpm_mode) { - /* Disable RPM mode */ - fan_set_enabled(ch, 0); - LM4_FAN_FANCH(ch) |= 0x0001; - fan_set_enabled(ch, was_enabled); - } -} - -int fan_get_rpm_actual(int ch) -{ - return (LM4_FAN_FANCST(ch) & MAX_RPM) * RPM_SCALE; -} - -int fan_get_rpm_target(int ch) -{ - return (LM4_FAN_FANCMD(ch) & MAX_RPM) * RPM_SCALE; -} - -test_mockable void fan_set_rpm_target(int ch, int rpm) -{ - /* Apply fan scaling */ - if (rpm > 0) - rpm /= RPM_SCALE; - - /* Treat out-of-range requests as requests for maximum fan speed */ - if (rpm < 0 || rpm > MAX_RPM) - rpm = MAX_RPM; - - LM4_FAN_FANCMD(ch) = rpm; -} - -/* The LM4 status is the original definition of enum fan_status */ -enum fan_status fan_get_status(int ch) -{ - return (LM4_FAN_FANSTS >> (2 * ch)) & 0x03; -} - -/** - * Return non-zero if fan is enabled but stalled. - */ -int fan_is_stalled(int ch) -{ - /* Must be enabled with non-zero target to stall */ - if (!fan_get_enabled(ch) || fan_get_rpm_target(ch) == 0) - return 0; - - /* Check for stall condition */ - return fan_get_status(ch) == FAN_STATUS_STOPPED; -} - -void fan_channel_setup(int ch, unsigned int flags) -{ - uint32_t init; - - if (flags & FAN_USE_RPM_MODE) - /* - * Configure automatic/feedback mode: - * 0x8000 = bit 15 = auto-restart - * 0x0000 = bit 14 = slow acceleration - * 0x0000 = bits 13:11 = no hysteresis - * 0x0000 = bits 10:8 = start period (2<<0) edges - * 0x0000 = bits 7:6 = no fast start - * 0x0020 = bits 5:4 = average 4 edges when - * calculating RPM - * 0x000c = bits 3:2 = 8 pulses per revolution - * (see note at top of file) - * 0x0000 = bit 0 = automatic control - */ - init = 0x802c; - else - /* - * Configure drive-only mode: - * 0x0000 = bit 15 = no auto-restart - * 0x0000 = bit 14 = slow acceleration - * 0x0000 = bits 13:11 = no hysteresis - * 0x0000 = bits 10:8 = start period (2<<0) edges - * 0x0000 = bits 7:6 = no fast start - * 0x0000 = bits 5:4 = no RPM averaging - * 0x0000 = bits 3:2 = 1 pulses per revolution - * 0x0001 = bit 0 = manual control - */ - init = 0x0001; - - if (flags & FAN_USE_FAST_START) - /* - * Configure fast-start mode - * 0x0000 = bits 10:8 = start period (2<<0) edges - * 0x0040 = bits 7:6 = fast start at 50% duty - */ - init |= 0x0040; - - LM4_FAN_FANCH(ch) = init; -} - -static void fan_init(void) -{ - -#ifdef CONFIG_FAN_DSLEEP - /* Enable the fan module and delay a few clocks */ - clock_enable_peripheral(CGC_OFFSET_FAN, 0x1, CGC_MODE_ALL); -#else - /* Enable the fan module and delay a few clocks */ - clock_enable_peripheral(CGC_OFFSET_FAN, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); -#endif - /* Disable all fans */ - LM4_FAN_FANCTL = 0; -} -/* Init before PWM */ -DECLARE_HOOK(HOOK_INIT, fan_init, HOOK_PRIO_INIT_FAN); diff --git a/chip/lm4/flash.c b/chip/lm4/flash.c deleted file mode 100644 index 4f7e905e21..0000000000 --- a/chip/lm4/flash.c +++ /dev/null @@ -1,293 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Flash memory module for Chrome EC */ - -#include "flash.h" -#include "registers.h" -#include "switch.h" -#include "system.h" -#include "timer.h" -#include "util.h" -#include "watchdog.h" - -#define FLASH_FWB_WORDS 32 -#define FLASH_FWB_BYTES (FLASH_FWB_WORDS * 4) - -#define BANK_SHIFT 5 /* bank registers have 32bits each, 2^32 */ -#define BANK_MASK (BIT(BANK_SHIFT) - 1) /* 5 bits */ -#define F_BANK(b) ((b) >> BANK_SHIFT) -#define F_BIT(b) (1 << ((b) & BANK_MASK)) - -/* Flash timeouts. These are 2x the spec sheet max. */ -#define ERASE_TIMEOUT_MS 200 -#define WRITE_TIMEOUT_US 300 - -int stuck_locked; /* Is physical flash stuck protected? */ -int all_protected; /* Has all-flash protection been requested? */ - -/** - * Protect flash banks until reboot. - * - * @param start_bank Start bank to protect - * @param bank_count Number of banks to protect - */ -static void protect_banks(int start_bank, int bank_count) -{ - int bank; - for (bank = start_bank; bank < start_bank + bank_count; bank++) - LM4_FLASH_FMPPE[F_BANK(bank)] &= ~F_BIT(bank); -} - -/** - * Perform a write-buffer operation. Buffer (FWB) and address (FMA) must be - * pre-loaded. - * - * @return EC_SUCCESS, or nonzero if error. - */ -static int write_buffer(void) -{ - int t; - - if (all_protected) - return EC_ERROR_ACCESS_DENIED; - - if (!LM4_FLASH_FWBVAL) - return EC_SUCCESS; /* Nothing to do */ - - /* Clear previous error status */ - LM4_FLASH_FCMISC = LM4_FLASH_FCRIS; - - /* Start write operation at page boundary */ - LM4_FLASH_FMC2 = 0xa4420001; - - /* - * Reload the watchdog timer, so that writing a large amount of flash - * doesn't cause a watchdog reset. - */ - watchdog_reload(); - - /* Wait for write to complete */ - for (t = 0; LM4_FLASH_FMC2 & 0x01; t += 10) { - if (t > WRITE_TIMEOUT_US) - return EC_ERROR_TIMEOUT; - udelay(10); - } - - /* Check for error conditions - program failed, erase needed, - * voltage error. */ - if (LM4_FLASH_FCRIS & 0x2e01) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -/*****************************************************************************/ -/* Physical layer APIs */ - -int flash_physical_write(int offset, int size, const char *data) -{ - const uint32_t *data32 = (const uint32_t *)data; - int rv; - int i; - - if (all_protected) - return EC_ERROR_ACCESS_DENIED; - - /* Fail if offset, size, and data aren't at least word-aligned */ - if ((offset | size | (uint32_t)(uintptr_t)data) & 3) - return EC_ERROR_INVAL; - - /* Get initial write buffer index and page */ - LM4_FLASH_FMA = offset & ~(FLASH_FWB_BYTES - 1); - i = (offset >> 2) & (FLASH_FWB_WORDS - 1); - - /* Copy words into buffer */ - for (; size > 0; size -= 4) { - LM4_FLASH_FWB[i++] = *data32++; - if (i == FLASH_FWB_WORDS) { - rv = write_buffer(); - if (rv != EC_SUCCESS) - return rv; - - /* Advance to next page */ - i = 0; - LM4_FLASH_FMA += FLASH_FWB_BYTES; - } - } - - /* Handle final partial page, if any */ - if (i > 0) - return write_buffer(); - - return EC_SUCCESS; -} - -int flash_physical_erase(int offset, int size) -{ - if (all_protected) - return EC_ERROR_ACCESS_DENIED; - - LM4_FLASH_FCMISC = LM4_FLASH_FCRIS; /* Clear previous error status */ - - for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE, - offset += CONFIG_FLASH_ERASE_SIZE) { - int t; - - /* Do nothing if already erased */ - if (flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE)) - continue; - - LM4_FLASH_FMA = offset; - - /* - * Reload the watchdog timer, so that erasing many flash pages - * doesn't cause a watchdog reset. May not need this now that - * we're using msleep() below. - */ - watchdog_reload(); - - /* Start erase */ - LM4_FLASH_FMC = 0xa4420002; - - /* Wait for erase to complete */ - for (t = 0; LM4_FLASH_FMC & 0x02; t++) { - if (t > ERASE_TIMEOUT_MS) - return EC_ERROR_TIMEOUT; - msleep(1); - } - - /* Check for error conditions - erase failed, voltage error, - * protection error */ - if (LM4_FLASH_FCRIS & 0x0a01) - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -int flash_physical_get_protect(int bank) -{ - return (LM4_FLASH_FMPPE[F_BANK(bank)] & F_BIT(bank)) ? 0 : 1; -} - -uint32_t flash_physical_get_protect_flags(void) -{ - uint32_t flags = 0; - - /* Read all-protected state from our shadow copy */ - if (all_protected) - flags |= EC_FLASH_PROTECT_ALL_NOW; - - /* Check if blocks were stuck locked at pre-init */ - if (stuck_locked) - flags |= EC_FLASH_PROTECT_ERROR_STUCK; - - return flags; -} - -int flash_physical_protect_now(int all) -{ - if (all) { - /* Protect the entire flash */ - all_protected = 1; - protect_banks(0, CONFIG_FLASH_SIZE / - CONFIG_FLASH_BANK_SIZE); - } else - /* Protect the WP region (read-only section and pstate) */ - protect_banks(WP_BANK_OFFSET, WP_BANK_COUNT); - - return EC_SUCCESS; -} - -uint32_t flash_physical_get_valid_flags(void) -{ - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | - EC_FLASH_PROTECT_ALL_NOW; -} - -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) -{ - uint32_t ret = 0; - - /* If RO protection isn't enabled, its at-boot state can be changed. */ - if (!(cur_flags & EC_FLASH_PROTECT_RO_NOW)) - ret |= EC_FLASH_PROTECT_RO_AT_BOOT; - - /* - * If entire flash isn't protected at this boot, it can be enabled if - * the WP GPIO is asserted. - */ - if (!(cur_flags & EC_FLASH_PROTECT_ALL_NOW) && - (cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED)) - ret |= EC_FLASH_PROTECT_ALL_NOW; - - return ret; -} - - -/*****************************************************************************/ -/* High-level APIs */ - -int flash_pre_init(void) -{ - uint32_t reset_flags = system_get_reset_flags(); - uint32_t prot_flags = flash_get_protect(); - uint32_t unwanted_prot_flags = EC_FLASH_PROTECT_ALL_NOW | - EC_FLASH_PROTECT_ERROR_INCONSISTENT; - - /* - * If we have already jumped between images, an earlier image could - * have applied write protection. Nothing additional needs to be done. - */ - if (reset_flags & EC_RESET_FLAG_SYSJUMP) - return EC_SUCCESS; - - if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) { - /* - * Write protect is asserted. If we want RO flash protected, - * protect it now. - */ - if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) && - !(prot_flags & EC_FLASH_PROTECT_RO_NOW)) { - int rv = flash_set_protect(EC_FLASH_PROTECT_RO_NOW, - EC_FLASH_PROTECT_RO_NOW); - if (rv) - return rv; - - /* Re-read flags */ - prot_flags = flash_get_protect(); - } - - /* Update all-now flag if all flash is protected */ - if (prot_flags & EC_FLASH_PROTECT_ALL_NOW) - all_protected = 1; - - } else { - /* Don't want RO flash protected */ - unwanted_prot_flags |= EC_FLASH_PROTECT_RO_NOW; - } - - /* If there are no unwanted flags, done */ - if (!(prot_flags & unwanted_prot_flags)) - return EC_SUCCESS; - - /* - * If the last reboot was a power-on reset, it should have cleared - * write-protect. If it didn't, then the flash write protect registers - * have been permanently committed and we can't fix that. - */ - if (reset_flags & EC_RESET_FLAG_POWER_ON) { - stuck_locked = 1; - return EC_ERROR_ACCESS_DENIED; - } - - /* Otherwise, do a hard boot to clear the flash protection registers */ - system_reset(SYSTEM_RESET_HARD | SYSTEM_RESET_PRESERVE_FLAGS); - - /* That doesn't return, so if we're still here that's an error */ - return EC_ERROR_UNKNOWN; -} diff --git a/chip/lm4/gpio.c b/chip/lm4/gpio.c deleted file mode 100644 index 65d6548f90..0000000000 --- a/chip/lm4/gpio.c +++ /dev/null @@ -1,385 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* GPIO module for Chrome EC */ - -#include "clock.h" -#include "common.h" -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "switch.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* 0-terminated list of GPIO base addresses */ -static const uint32_t gpio_bases[] = { - LM4_GPIO_A, LM4_GPIO_B, LM4_GPIO_C, LM4_GPIO_D, - LM4_GPIO_E, LM4_GPIO_F, LM4_GPIO_G, LM4_GPIO_H, - LM4_GPIO_J, LM4_GPIO_K, LM4_GPIO_L, LM4_GPIO_M, - LM4_GPIO_N, LM4_GPIO_P, LM4_GPIO_Q, 0 -}; - -/** - * Find the index of a GPIO port base address - * - * This is used by the clock gating registers. - * - * @param port_base Base address to find (LM4_GPIO_[A-Q]) - * - * @return The index, or -1 if no match. - */ -static int find_gpio_port_index(uint32_t port_base) -{ - int i; - for (i = 0; gpio_bases[i]; i++) { - if (gpio_bases[i] == port_base) - return i; - } - return -1; -} - -void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) -{ - int port_index = find_gpio_port_index(port); - int cgmask; - - /* Ignore (do nothing for) invalid port values */ - if (port_index < 0) - return; - - /* Enable the GPIO port in run and sleep. */ - cgmask = 1 << port_index; - clock_enable_peripheral(CGC_OFFSET_GPIO, cgmask, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - if (func != GPIO_ALT_FUNC_NONE) { - int pctlmask = 0; - int i; - /* Expand mask from bits to nibbles */ - for (i = 0; i < 8; i++) { - if (mask & BIT(i)) - pctlmask |= 1 << (4 * i); - } - - LM4_GPIO_PCTL(port) = - (LM4_GPIO_PCTL(port) & ~(pctlmask * 0xf)) | - (pctlmask * func); - LM4_GPIO_AFSEL(port) |= mask; - } else { - LM4_GPIO_AFSEL(port) &= ~mask; - } -} - -test_mockable int gpio_get_level(enum gpio_signal signal) -{ - return LM4_GPIO_DATA(gpio_list[signal].port, - gpio_list[signal].mask) ? 1 : 0; -} - -void gpio_set_level(enum gpio_signal signal, int value) -{ - /* - * Ok to write 0xff because LM4_GPIO_DATA bit-masks only the bit - * we care about. - */ - LM4_GPIO_DATA(gpio_list[signal].port, - gpio_list[signal].mask) = (value ? 0xff : 0); -} - -void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) -{ - /* - * Select open drain first, so that we don't glitch the signal - * when changing the line to an output. - */ - if (flags & GPIO_OPEN_DRAIN) - LM4_GPIO_ODR(port) |= mask; - else - LM4_GPIO_ODR(port) &= ~mask; - - if (flags & GPIO_OUTPUT) - LM4_GPIO_DIR(port) |= mask; - else - LM4_GPIO_DIR(port) &= ~mask; - - /* Handle pullup / pulldown */ - if (flags & GPIO_PULL_UP) { - LM4_GPIO_PUR(port) |= mask; - } else if (flags & GPIO_PULL_DOWN) { - LM4_GPIO_PDR(port) |= mask; - } else { - /* No pull up/down */ - LM4_GPIO_PUR(port) &= ~mask; - LM4_GPIO_PDR(port) &= ~mask; - } - - /* Set up interrupt type */ - if (flags & (GPIO_INT_F_LOW | GPIO_INT_F_HIGH)) - LM4_GPIO_IS(port) |= mask; - else - LM4_GPIO_IS(port) &= ~mask; - - if (flags & (GPIO_INT_F_RISING | GPIO_INT_F_HIGH)) - LM4_GPIO_IEV(port) |= mask; - else - LM4_GPIO_IEV(port) &= ~mask; - - /* Handle interrupting on both edges */ - if ((flags & GPIO_INT_F_RISING) && - (flags & GPIO_INT_F_FALLING)) - LM4_GPIO_IBE(port) |= mask; - else - LM4_GPIO_IBE(port) &= ~mask; - - if (flags & GPIO_ANALOG) - LM4_GPIO_DEN(port) &= ~mask; - else - LM4_GPIO_DEN(port) |= mask; - - /* Set level */ - if (flags & GPIO_HIGH) - LM4_GPIO_DATA(port, mask) = 0xff; - else if (flags & GPIO_LOW) - LM4_GPIO_DATA(port, mask) = 0; -} - -int gpio_enable_interrupt(enum gpio_signal signal) -{ - const struct gpio_info *g = gpio_list + signal; - /* Fail if no interrupt handler */ - if (signal >= GPIO_IH_COUNT) - return EC_ERROR_UNKNOWN; - - LM4_GPIO_IM(g->port) |= g->mask; - return EC_SUCCESS; -} - -int gpio_disable_interrupt(enum gpio_signal signal) -{ - const struct gpio_info *g = gpio_list + signal; - - /* Fail if no interrupt handler */ - if (signal >= GPIO_IH_COUNT) - return EC_ERROR_UNKNOWN; - - LM4_GPIO_IM(g->port) &= ~g->mask; - return EC_SUCCESS; -} - -int gpio_clear_pending_interrupt(enum gpio_signal signal) -{ - const struct gpio_info *g = gpio_list + signal; - - /* Fail if no interrupt handler */ - if (signal >= GPIO_IH_COUNT) - return EC_ERROR_INVAL; - - LM4_GPIO_ICR(g->port) |= g->mask; - return EC_SUCCESS; -} - -#ifdef CONFIG_LOW_POWER_IDLE -/** - * Convert GPIO port to a mask that can be used to set the - * clock gate control register for GPIOs. - */ -static int gpio_port_to_clock_gate_mask(uint32_t gpio_port) -{ - int index = find_gpio_port_index(gpio_port); - - return index >= 0 ? BIT(index) : 0; -} -#endif - -void gpio_pre_init(void) -{ - const struct gpio_info *g = gpio_list; - int is_warm = 0; - int i; - - if (LM4_SYSTEM_RCGCGPIO == 0x7fff) { - /* This is a warm reboot */ - is_warm = 1; - } else { - /* - * Enable clocks to all the GPIO blocks since we use all of - * them as GPIOs in run and sleep modes. - */ - clock_enable_peripheral(CGC_OFFSET_GPIO, 0x7fff, - CGC_MODE_RUN | CGC_MODE_SLEEP); - } - - /* - * Disable GPIO commit control for PD7 and PF0, since we don't use the - * NMI pin function. - */ - LM4_GPIO_LOCK(LM4_GPIO_D) = LM4_GPIO_LOCK_UNLOCK; - LM4_GPIO_CR(LM4_GPIO_D) |= 0x80; - LM4_GPIO_LOCK(LM4_GPIO_D) = 0; - LM4_GPIO_LOCK(LM4_GPIO_F) = LM4_GPIO_LOCK_UNLOCK; - LM4_GPIO_CR(LM4_GPIO_F) |= 0x01; - LM4_GPIO_LOCK(LM4_GPIO_F) = 0; - - /* Clear SSI0 alternate function on PA2:5 */ - LM4_GPIO_AFSEL(LM4_GPIO_A) &= ~0x3c; - - /* Mask all GPIO interrupts */ - for (i = 0; gpio_bases[i]; i++) - LM4_GPIO_IM(gpio_bases[i]) = 0; - - /* Set all GPIOs to defaults */ - for (i = 0; i < GPIO_COUNT; i++, g++) { - int flags = g->flags; - - if (flags & GPIO_DEFAULT) - continue; - -#ifdef CONFIG_LOW_POWER_IDLE - /* - * Enable board specific GPIO ports to interrupt deep sleep by - * providing a clock to that port in deep sleep mode. - */ - if (flags & GPIO_INT_DSLEEP) { - clock_enable_peripheral(CGC_OFFSET_GPIO, - gpio_port_to_clock_gate_mask(g->port), - CGC_MODE_ALL); - } -#endif - - /* - * If this is a warm reboot, don't set the output levels or - * we'll shut off the main chipset. - */ - if (is_warm) - flags &= ~(GPIO_LOW | GPIO_HIGH); - - /* Set up GPIO based on flags */ - gpio_set_flags_by_mask(g->port, g->mask, flags); - - /* Use as GPIO, not alternate function */ - gpio_set_alternate_function(g->port, g->mask, - GPIO_ALT_FUNC_NONE); - } - -#ifdef CONFIG_LOW_POWER_IDLE - /* - * Enable KB scan row to interrupt deep sleep by providing a clock - * signal to that port in deep sleep mode. - */ - clock_enable_peripheral(CGC_OFFSET_GPIO, - gpio_port_to_clock_gate_mask(KB_SCAN_ROW_GPIO), - CGC_MODE_ALL); -#endif -} - -/* List of GPIO IRQs to enable. Don't automatically enable interrupts for - * the keyboard input GPIO bank - that's handled separately. Of course the - * bank is different for different systems. */ -static const uint8_t gpio_irqs[] = { - LM4_IRQ_GPIOA, LM4_IRQ_GPIOB, LM4_IRQ_GPIOC, LM4_IRQ_GPIOD, - LM4_IRQ_GPIOE, LM4_IRQ_GPIOF, LM4_IRQ_GPIOG, LM4_IRQ_GPIOH, - LM4_IRQ_GPIOJ, -#if defined(KB_SCAN_ROW_IRQ) && (KB_SCAN_ROW_IRQ != LM4_IRQ_GPIOK) - LM4_IRQ_GPIOK, -#endif - LM4_IRQ_GPIOL, LM4_IRQ_GPIOM, -#if defined(KB_SCAN_ROW_IRQ) && (KB_SCAN_ROW_IRQ != LM4_IRQ_GPION) - LM4_IRQ_GPION, -#endif - LM4_IRQ_GPIOP, LM4_IRQ_GPIOQ -}; - -static void gpio_init(void) -{ - int i; - - /* Enable IRQs now that pins are set up */ - for (i = 0; i < ARRAY_SIZE(gpio_irqs); i++) - task_enable_irq(gpio_irqs[i]); -} -DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); - -/*****************************************************************************/ -/* Interrupt handlers */ - -/** - * Handle a GPIO interrupt. - * - * @param port GPIO port (LM4_GPIO_*) - * @param mis Masked interrupt status value for that port - */ -static void gpio_interrupt(int port, uint32_t mis) -{ - int i = 0; - const struct gpio_info *g = gpio_list; - - for (i = 0; i < GPIO_IH_COUNT && mis; i++, g++) { - if (port == g->port && (mis & g->mask)) { - gpio_irq_handlers[i](i); - mis &= ~g->mask; - } - } -} - -/** - * Handlers for each GPIO port. These read and clear the interrupt bits for - * the port, then call the master handler above. - */ -#define GPIO_IRQ_FUNC(irqfunc, gpiobase) \ - void irqfunc(void) \ - { \ - uint32_t mis = LM4_GPIO_MIS(gpiobase); \ - LM4_GPIO_ICR(gpiobase) = mis; \ - gpio_interrupt(gpiobase, mis); \ - } - -GPIO_IRQ_FUNC(__gpio_a_interrupt, LM4_GPIO_A); -GPIO_IRQ_FUNC(__gpio_b_interrupt, LM4_GPIO_B); -GPIO_IRQ_FUNC(__gpio_c_interrupt, LM4_GPIO_C); -GPIO_IRQ_FUNC(__gpio_d_interrupt, LM4_GPIO_D); -GPIO_IRQ_FUNC(__gpio_e_interrupt, LM4_GPIO_E); -GPIO_IRQ_FUNC(__gpio_f_interrupt, LM4_GPIO_F); -GPIO_IRQ_FUNC(__gpio_g_interrupt, LM4_GPIO_G); -GPIO_IRQ_FUNC(__gpio_h_interrupt, LM4_GPIO_H); -GPIO_IRQ_FUNC(__gpio_j_interrupt, LM4_GPIO_J); -#if defined(KB_SCAN_ROW_GPIO) && (KB_SCAN_ROW_GPIO != LM4_GPIO_K) -GPIO_IRQ_FUNC(__gpio_k_interrupt, LM4_GPIO_K); -#endif -GPIO_IRQ_FUNC(__gpio_l_interrupt, LM4_GPIO_L); -GPIO_IRQ_FUNC(__gpio_m_interrupt, LM4_GPIO_M); -#if defined(KB_SCAN_ROW_GPIO) && (KB_SCAN_ROW_GPIO != LM4_GPIO_N) -GPIO_IRQ_FUNC(__gpio_n_interrupt, LM4_GPIO_N); -#endif -GPIO_IRQ_FUNC(__gpio_p_interrupt, LM4_GPIO_P); -GPIO_IRQ_FUNC(__gpio_q_interrupt, LM4_GPIO_Q); - -#undef GPIO_IRQ_FUNC - -/* - * Declare IRQs. Nesting this macro inside the GPIO_IRQ_FUNC macro works - * poorly because DECLARE_IRQ() stringizes its inputs. - */ -DECLARE_IRQ(LM4_IRQ_GPIOA, __gpio_a_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOB, __gpio_b_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOC, __gpio_c_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOD, __gpio_d_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOE, __gpio_e_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOF, __gpio_f_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOG, __gpio_g_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOH, __gpio_h_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOJ, __gpio_j_interrupt, 1); -#if defined(KB_SCAN_ROW_GPIO) && (KB_SCAN_ROW_GPIO != LM4_GPIO_K) -DECLARE_IRQ(LM4_IRQ_GPIOK, __gpio_k_interrupt, 1); -#endif -DECLARE_IRQ(LM4_IRQ_GPIOL, __gpio_l_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOM, __gpio_m_interrupt, 1); -#if defined(KB_SCAN_ROW_GPIO) && (KB_SCAN_ROW_GPIO != LM4_GPIO_N) -DECLARE_IRQ(LM4_IRQ_GPION, __gpio_n_interrupt, 1); -#endif -DECLARE_IRQ(LM4_IRQ_GPIOP, __gpio_p_interrupt, 1); -DECLARE_IRQ(LM4_IRQ_GPIOQ, __gpio_q_interrupt, 1); diff --git a/chip/lm4/hwtimer.c b/chip/lm4/hwtimer.c deleted file mode 100644 index 44e1c2fb27..0000000000 --- a/chip/lm4/hwtimer.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Hardware timers driver */ - -#include "clock.h" -#include "common.h" -#include "hooks.h" -#include "hwtimer.h" -#include "registers.h" -#include "task.h" -#include "timer.h" - -void __hw_clock_event_set(uint32_t deadline) -{ - /* set the match on the deadline */ - LM4_TIMER_TAMATCHR(6) = 0xffffffff - deadline; - /* Set the match interrupt */ - LM4_TIMER_IMR(6) |= 0x10; -} - -uint32_t __hw_clock_event_get(void) -{ - return 0xffffffff - LM4_TIMER_TAMATCHR(6); -} - -void __hw_clock_event_clear(void) -{ - /* Disable the match interrupt */ - LM4_TIMER_IMR(6) &= ~0x10; -} - -uint32_t __hw_clock_source_read(void) -{ - return 0xffffffff - LM4_TIMER_TAV(6); -} - -void __hw_clock_source_set(uint32_t ts) -{ - LM4_TIMER_TAV(6) = 0xffffffff - ts; -} - -void __hw_clock_source_irq(void) -{ - uint32_t status = LM4_TIMER_RIS(6); - - /* Clear interrupt */ - LM4_TIMER_ICR(6) = status; - - /* - * Find expired timers and set the new timer deadline; check the IRQ - * status to determine if the free-running counter overflowed. - */ - process_timers(status & 0x01); -} -DECLARE_IRQ(LM4_IRQ_TIMERW0A, __hw_clock_source_irq, 1); - -static void update_prescaler(void) -{ - /* - * Set the prescaler to increment every microsecond. This takes - * effect immediately, because the TAILD bit in TAMR is clear. - */ - LM4_TIMER_TAPR(6) = clock_get_freq() / SECOND; -} -DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT); - -int __hw_clock_source_init(uint32_t start_t) -{ - /* - * Use WTIMER0 (timer 6) configured as a free running counter with 1 us - * period. - */ - - /* Enable WTIMER0 clock in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_WTIMER, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - /* Ensure timer is disabled : TAEN = TBEN = 0 */ - LM4_TIMER_CTL(6) &= ~0x101; - /* Set overflow interrupt */ - LM4_TIMER_IMR(6) = 0x1; - /* 32-bit timer mode */ - LM4_TIMER_CFG(6) = 4; - - /* Set initial prescaler */ - update_prescaler(); - - /* Periodic mode, counting down */ - LM4_TIMER_TAMR(6) = 0x22; - /* Use the full 32-bits of the timer */ - LM4_TIMER_TAILR(6) = 0xffffffff; - /* Starts counting in timer A */ - LM4_TIMER_CTL(6) |= 0x1; - - /* - * Override the count with the start value now that counting has - * started. - */ - __hw_clock_source_set(start_t); - - /* Enable interrupt */ - task_enable_irq(LM4_IRQ_TIMERW0A); - - return LM4_IRQ_TIMERW0A; -} diff --git a/chip/lm4/i2c.c b/chip/lm4/i2c.c deleted file mode 100644 index 0608b433bc..0000000000 --- a/chip/lm4/i2c.c +++ /dev/null @@ -1,411 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* I2C port module for Chrome EC */ - -#include "atomic.h" -#include "clock.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) - -/* Flags for writes to MCS */ -#define LM4_I2C_MCS_RUN BIT(0) -#define LM4_I2C_MCS_START BIT(1) -#define LM4_I2C_MCS_STOP BIT(2) -#define LM4_I2C_MCS_ACK BIT(3) -#define LM4_I2C_MCS_HS BIT(4) -#define LM4_I2C_MCS_QCMD BIT(5) - -/* Flags for reads from MCS */ -#define LM4_I2C_MCS_BUSY BIT(0) -#define LM4_I2C_MCS_ERROR BIT(1) -#define LM4_I2C_MCS_ADRACK BIT(2) -#define LM4_I2C_MCS_DATACK BIT(3) -#define LM4_I2C_MCS_ARBLST BIT(4) -#define LM4_I2C_MCS_IDLE BIT(5) -#define LM4_I2C_MCS_BUSBSY BIT(6) -#define LM4_I2C_MCS_CLKTO BIT(7) - -/* - * Minimum delay between resetting the port or sending a stop condition, and - * when the port can be expected to be back in an idle state (and the slave - * has had long enough to see the start/stop condition edges). - * - * 500 us = 50 clocks at 100 KHz bus speed. This has been experimentally - * determined to be enough. - */ -#define I2C_IDLE_US 500 - -/* IRQ for each port */ -static const uint32_t i2c_irqs[] = {LM4_IRQ_I2C0, LM4_IRQ_I2C1, LM4_IRQ_I2C2, - LM4_IRQ_I2C3, LM4_IRQ_I2C4, LM4_IRQ_I2C5}; -BUILD_ASSERT(ARRAY_SIZE(i2c_irqs) == I2C_PORT_COUNT); - -/* I2C port state data */ -struct i2c_port_data { - const uint8_t *out; /* Output data pointer */ - int out_size; /* Output data to transfer, in bytes */ - uint8_t *in; /* Input data pointer */ - int in_size; /* Input data to transfer, in bytes */ - int flags; /* Flags (I2C_XFER_*) */ - int idx; /* Index into input/output data */ - int err; /* Error code, if any */ - uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ - - /* Task waiting on port, or TASK_ID_INVALID if none. */ - volatile int task_waiting; -}; -static struct i2c_port_data pdata[I2C_PORT_COUNT]; - -int i2c_is_busy(int port) -{ - return LM4_I2C_MCS(port) & LM4_I2C_MCS_BUSBSY; -} - -/** - * I2C transfer engine. - * - * @return Zero when done with transfer (ready to wake task). - * - * MCS sequence on multi-byte write: - * 0x3 0x1 0x1 ... 0x1 0x5 - * Single byte write: - * 0x7 - * - * MCS receive sequence on multi-byte read: - * 0xb 0x9 0x9 ... 0x9 0x5 - * Single byte read: - * 0x7 - */ -int i2c_do_work(int port) -{ - struct i2c_port_data *pd = pdata + port; - uint32_t reg_mcs = LM4_I2C_MCS_RUN; - - if (pd->flags & I2C_XFER_START) { - /* Set start bit on first byte */ - reg_mcs |= LM4_I2C_MCS_START; - pd->flags &= ~I2C_XFER_START; - } else if (LM4_I2C_MCS(port) & (LM4_I2C_MCS_CLKTO | LM4_I2C_MCS_ARBLST | - LM4_I2C_MCS_ERROR)) { - /* - * Error after starting; abort transfer. Ignore errors at - * start because arbitration and timeout errors are taken care - * of in chip_i2c_xfer(), and slave ack failures will - * automatically clear once we send a start condition. - */ - pd->err = EC_ERROR_UNKNOWN; - return 0; - } - - if (pd->out_size) { - /* Send next byte of output */ - LM4_I2C_MDR(port) = *(pd->out++); - pd->idx++; - - /* Handle starting to send last byte */ - if (pd->idx == pd->out_size) { - - /* Done with output after this */ - pd->out_size = 0; - pd->idx = 0; - - /* Resend start bit when changing direction */ - pd->flags |= I2C_XFER_START; - - /* - * Send stop bit after last byte if the stop flag is - * on, and caller doesn't expect to receive data. - */ - if ((pd->flags & I2C_XFER_STOP) && pd->in_size == 0) - reg_mcs |= LM4_I2C_MCS_STOP; - } - - LM4_I2C_MCS(port) = reg_mcs; - return 1; - - } else if (pd->in_size) { - if (pd->idx) { - /* Copy the byte we just read */ - *(pd->in++) = LM4_I2C_MDR(port) & 0xff; - } else { - /* Starting receive; switch to receive address */ - LM4_I2C_MSA(port) |= 0x01; - } - - if (pd->idx < pd->in_size) { - /* More data to read */ - pd->idx++; - - /* ACK all bytes except the last one */ - if ((pd->flags & I2C_XFER_STOP) && - pd->idx == pd->in_size) - reg_mcs |= LM4_I2C_MCS_STOP; - else - reg_mcs |= LM4_I2C_MCS_ACK; - - LM4_I2C_MCS(port) = reg_mcs; - return 1; - } - } - - /* If we're still here, done with transfer */ - return 0; -} - -int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) -{ - struct i2c_port_data *pd = pdata + port; - uint32_t reg_mcs = LM4_I2C_MCS(port); - int events = 0; - - if (out_size == 0 && in_size == 0) - return EC_SUCCESS; - - /* Copy data to port struct */ - pd->out = out; - pd->out_size = out_size; - pd->in = in; - pd->in_size = in_size; - pd->flags = flags; - pd->idx = 0; - pd->err = 0; - - /* Make sure we're in a good state to start */ - if ((flags & I2C_XFER_START) && - ((reg_mcs & (LM4_I2C_MCS_CLKTO | LM4_I2C_MCS_ARBLST)) || - (i2c_get_line_levels(port) != I2C_LINE_IDLE))) { - uint32_t tpr = LM4_I2C_MTPR(port); - - CPRINTS("I2C%d Addr:%02X bad status 0x%02x, SCL=%d, SDA=%d", - port, - I2C_GET_ADDR(slave_addr_flags), - reg_mcs, - i2c_get_line_levels(port) & I2C_LINE_SCL_HIGH, - i2c_get_line_levels(port) & I2C_LINE_SDA_HIGH); - - /* Attempt to unwedge the port. */ - i2c_unwedge(port); - - /* Clock timeout or arbitration lost. Reset port to clear. */ - deprecated_atomic_or(LM4_SYSTEM_SRI2C_ADDR, BIT(port)); - clock_wait_cycles(3); - deprecated_atomic_clear_bits(LM4_SYSTEM_SRI2C_ADDR, BIT(port)); - clock_wait_cycles(3); - - /* Restore settings */ - LM4_I2C_MCR(port) = 0x10; - LM4_I2C_MTPR(port) = tpr; - - /* - * We don't know what edges the slave saw, so sleep long enough - * that the slave will see the new start condition below. - */ - usleep(I2C_IDLE_US); - } - - /* Set slave address for transmit */ - LM4_I2C_MSA(port) = (I2C_GET_ADDR(slave_addr_flags) << 1) & 0xff; - - /* Enable interrupts */ - pd->task_waiting = task_get_current(); - LM4_I2C_MICR(port) = 0x03; - LM4_I2C_MIMR(port) = 0x03; - - /* Kick the port interrupt handler to start the transfer */ - task_trigger_irq(i2c_irqs[port]); - - /* Wait for transfer complete or timeout */ - events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, pd->timeout_us); - - /* Disable interrupts */ - LM4_I2C_MIMR(port) = 0x00; - pd->task_waiting = TASK_ID_INVALID; - - /* Handle timeout */ - if (events & TASK_EVENT_TIMER) - pd->err = EC_ERROR_TIMEOUT; - - if (pd->err) { - /* Force port back idle */ - LM4_I2C_MCS(port) = LM4_I2C_MCS_STOP; - usleep(I2C_IDLE_US); - } - - return pd->err; -} - -int i2c_raw_get_scl(int port) -{ - enum gpio_signal g; - int ret; - - /* If no SCL pin defined for this port, then return 1 to appear idle. */ - if (get_scl_from_i2c_port(port, &g) != EC_SUCCESS) - return 1; - - /* If we are driving the pin low, it must be low. */ - if (gpio_get_level(g) == 0) - return 0; - - /* - * Otherwise, we need to toggle it to an input to read the true pin - * state. - */ - gpio_set_flags(g, GPIO_INPUT); - ret = gpio_get_level(g); - gpio_set_flags(g, GPIO_ODR_HIGH); - - return ret; -} - -int i2c_raw_get_sda(int port) -{ - enum gpio_signal g; - int ret; - - /* If no SDA pin defined for this port, then return 1 to appear idle. */ - if (get_sda_from_i2c_port(port, &g) != EC_SUCCESS) - return 1; - - /* If we are driving the pin low, it must be low. */ - if (gpio_get_level(g) == 0) - return 0; - - /* - * Otherwise, we need to toggle it to an input to read the true pin - * state. - */ - gpio_set_flags(g, GPIO_INPUT); - ret = gpio_get_level(g); - gpio_set_flags(g, GPIO_ODR_HIGH); - - return ret; -} - -int i2c_get_line_levels(int port) -{ - /* Conveniently, MBMON bit BIT(1) is SDA and BIT(0) is SCL. */ - return LM4_I2C_MBMON(port) & 0x03; -} - -void i2c_set_timeout(int port, uint32_t timeout) -{ - pdata[port].timeout_us = timeout ? timeout : I2C_TIMEOUT_DEFAULT_US; -} - -/*****************************************************************************/ -/* Hooks */ - -static void i2c_freq_changed(void) -{ - int freq = clock_get_freq(); - int i; - - for (i = 0; i < i2c_ports_used; i++) { - /* - * From datasheet: - * SCL_PRD = 2 * (1 + TPR) * (SCL_LP + SCL_HP) * CLK_PRD - * - * so: - * TPR = SCL_PRD / (2 * (SCL_LP + SCL_HP) * CLK_PRD) - 1 - * - * converting from period to frequency: - * TPR = CLK_FREQ / (SCL_FREQ * 2 * (SCL_LP + SCL_HP)) - 1 - */ - const int d = 2 * (6 + 4) * (i2c_ports[i].kbps * 1000); - - /* Round TPR up, so desired kbps is an upper bound */ - const int tpr = (freq + d - 1) / d - 1; - -#ifdef PRINT_I2C_SPEEDS - const int f = freq / (2 * (1 + tpr) * (6 + 4)); - CPRINTS("I2C%d clk=%d tpr=%d freq=%d", - i2c_ports[i].port, freq, tpr, f); -#endif - - LM4_I2C_MTPR(i2c_ports[i].port) = tpr; - } -} -DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_changed, HOOK_PRIO_DEFAULT); - -void i2c_init(void) -{ - uint32_t mask = 0; - int i; - - /* Enable I2C modules in run and sleep modes. */ - for (i = 0; i < i2c_ports_used; i++) - mask |= 1 << i2c_ports[i].port; - - clock_enable_peripheral(CGC_OFFSET_I2C, mask, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - /* Configure GPIOs */ - gpio_config_module(MODULE_I2C, 1); - - /* Initialize ports as master, with interrupts enabled */ - for (i = 0; i < i2c_ports_used; i++) - LM4_I2C_MCR(i2c_ports[i].port) = 0x10; - - /* Set initial clock frequency */ - i2c_freq_changed(); - - /* Enable IRQs; no tasks are waiting on ports */ - for (i = 0; i < I2C_PORT_COUNT; i++) { - pdata[i].task_waiting = TASK_ID_INVALID; - task_enable_irq(i2c_irqs[i]); - - /* Use default timeout */ - i2c_set_timeout(i, 0); - } -} - -/** - * Handle an interrupt on the specified port. - * - * @param port I2C port generating interrupt - */ -static void handle_interrupt(int port) -{ - int id = pdata[port].task_waiting; - - /* Clear the interrupt status */ - LM4_I2C_MICR(port) = LM4_I2C_MMIS(port); - - /* If no task is waiting, just return */ - if (id == TASK_ID_INVALID) - return; - - /* If done doing work, wake up the task waiting for the transfer */ - if (!i2c_do_work(port)) - task_set_event(id, TASK_EVENT_I2C_IDLE, 0); -} - -void i2c0_interrupt(void) { handle_interrupt(0); } -void i2c1_interrupt(void) { handle_interrupt(1); } -void i2c2_interrupt(void) { handle_interrupt(2); } -void i2c3_interrupt(void) { handle_interrupt(3); } -void i2c4_interrupt(void) { handle_interrupt(4); } -void i2c5_interrupt(void) { handle_interrupt(5); } - -DECLARE_IRQ(LM4_IRQ_I2C0, i2c0_interrupt, 2); -DECLARE_IRQ(LM4_IRQ_I2C1, i2c1_interrupt, 2); -DECLARE_IRQ(LM4_IRQ_I2C2, i2c2_interrupt, 2); -DECLARE_IRQ(LM4_IRQ_I2C3, i2c3_interrupt, 2); -DECLARE_IRQ(LM4_IRQ_I2C4, i2c4_interrupt, 2); -DECLARE_IRQ(LM4_IRQ_I2C5, i2c5_interrupt, 2); diff --git a/chip/lm4/keyboard_raw.c b/chip/lm4/keyboard_raw.c deleted file mode 100644 index 81af0efdde..0000000000 --- a/chip/lm4/keyboard_raw.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Functions needed by keyboard scanner module for Chrome EC */ - -#include "common.h" -#include "keyboard_raw.h" -#include "keyboard_scan.h" -#include "registers.h" -#include "task.h" - -void keyboard_raw_init(void) -{ - /* Ensure top-level interrupt is disabled */ - keyboard_raw_enable_interrupt(0); - - /* - * Set column outputs as open-drain; we either pull them low or let - * them float high. - */ - LM4_GPIO_AFSEL(LM4_GPIO_P) = 0; /* KSO[7:0] */ - LM4_GPIO_AFSEL(LM4_GPIO_Q) &= ~0x1f; /* KSO[12:8] */ - LM4_GPIO_DEN(LM4_GPIO_P) = 0xff; - LM4_GPIO_DEN(LM4_GPIO_Q) |= 0x1f; - LM4_GPIO_DIR(LM4_GPIO_P) = 0xff; - LM4_GPIO_DIR(LM4_GPIO_Q) |= 0x1f; - LM4_GPIO_ODR(LM4_GPIO_P) = 0xff; - LM4_GPIO_ODR(LM4_GPIO_Q) |= 0x1f; - -#ifdef CONFIG_KEYBOARD_COL2_INVERTED - /* - * When column 2 is inverted, the Silego has a pulldown instead of a - * pullup. So drive it push-pull instead of open-drain. - */ - LM4_GPIO_ODR(LM4_GPIO_P) &= ~BIT(2); -#endif - - /* Set row inputs with pull-up */ - LM4_GPIO_AFSEL(KB_SCAN_ROW_GPIO) &= 0xff; - LM4_GPIO_DEN(KB_SCAN_ROW_GPIO) |= 0xff; - LM4_GPIO_DIR(KB_SCAN_ROW_GPIO) = 0; - LM4_GPIO_PUR(KB_SCAN_ROW_GPIO) = 0xff; - - /* Edge-sensitive on both edges. */ - LM4_GPIO_IS(KB_SCAN_ROW_GPIO) = 0; - LM4_GPIO_IBE(KB_SCAN_ROW_GPIO) = 0xff; - - /* - * Enable interrupts for the inputs. The top-level interrupt is still - * masked off, so this won't trigger interrupts yet. - */ - LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0xff; -} - -void keyboard_raw_task_start(void) -{ - task_enable_irq(KB_SCAN_ROW_IRQ); -} - -test_mockable void keyboard_raw_drive_column(int col) -{ - int mask; - - if (col == KEYBOARD_COLUMN_NONE) - mask = 0x1fff; /* Tri-state all outputs */ - else if (col == KEYBOARD_COLUMN_ALL) - mask = 0; /* Assert all outputs */ - else - mask = 0x1fff ^ BIT(col); /* Assert a single output */ - -#ifdef CONFIG_KEYBOARD_COL2_INVERTED - /* Invert column 2 output */ - mask ^= BIT(2); -#endif - - LM4_GPIO_DATA(LM4_GPIO_P, 0xff) = mask & 0xff; - LM4_GPIO_DATA(LM4_GPIO_Q, 0x1f) = (mask >> 8) & 0x1f; -} - -test_mockable int keyboard_raw_read_rows(void) -{ - /* Bits are active-low, so invert returned levels */ - return LM4_GPIO_DATA(KB_SCAN_ROW_GPIO, 0xff) ^ 0xff; -} - -void keyboard_raw_enable_interrupt(int enable) -{ - if (enable) { - /* - * Clear pending interrupts before enabling them, because the - * raw interrupt status may have been tripped by keyboard - * scanning or, if a key is already pressed, by driving all the - * outputs. - * - * We won't lose keyboard events because the scanning task will - * explicitly check the raw row state before waiting for an - * interrupt. If a key is pressed, the task won't wait. - */ - LM4_GPIO_ICR(KB_SCAN_ROW_GPIO) = 0xff; - LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0xff; - } else { - LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0; - } -} - -/** - * Interrupt handler for the entire GPIO bank of keyboard rows. - */ -void keyboard_raw_interrupt(void) -{ - /* Clear all pending keyboard interrupts */ - LM4_GPIO_ICR(KB_SCAN_ROW_GPIO) = 0xff; - - /* Wake the scan task */ - task_wake(TASK_ID_KEYSCAN); -} -DECLARE_IRQ(KB_SCAN_ROW_IRQ, keyboard_raw_interrupt, 3); diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c deleted file mode 100644 index 5b146ba32a..0000000000 --- a/chip/lm4/lpc.c +++ /dev/null @@ -1,834 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* LPC module for Chrome EC */ - -#include "acpi.h" -#include "clock.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "keyboard_protocol.h" -#include "lpc.h" -#include "port80.h" -#include "pwm.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "uart.h" -#include "util.h" - -/* LPC channels */ -#define LPC_CH_ACPI 0 /* ACPI commands */ -#define LPC_CH_PORT80 1 /* Port 80 debug output */ -#define LPC_CH_CMD_DATA 2 /* Data for host commands (args/params/response) */ -#define LPC_CH_KEYBOARD 3 /* 8042 keyboard emulation */ -#define LPC_CH_CMD 4 /* Host commands */ -#define LPC_CH_MEMMAP 5 /* Memory-mapped data */ -#define LPC_CH_COMX 7 /* UART emulation */ -/* LPC pool offsets */ -#define LPC_POOL_OFFS_ACPI 0 /* ACPI commands - 0=in, 1=out */ -#define LPC_POOL_OFFS_PORT80 4 /* Port 80 - 4=in, 5=out */ -#define LPC_POOL_OFFS_COMX 8 /* UART emulation range - 8-15 */ -#define LPC_POOL_OFFS_KEYBOARD 16 /* Keyboard - 16=in, 17=out */ -#define LPC_POOL_OFFS_CMD 20 /* Host commands - 20=in, 21=out */ -#define LPC_POOL_OFFS_CMD_DATA 512 /* Data range for host commands - 512-767 */ -#define LPC_POOL_OFFS_MEMMAP 768 /* Memory-mapped data - 768-1023 */ -/* LPC pool data pointers */ -#define LPC_POOL_ACPI (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_ACPI) -#define LPC_POOL_PORT80 (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_PORT80) -#define LPC_POOL_COMX (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_COMX) -#define LPC_POOL_KEYBOARD (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_KEYBOARD) -#define LPC_POOL_CMD (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_CMD) -#define LPC_POOL_CMD_DATA (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_CMD_DATA) -#define LPC_POOL_MEMMAP (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_MEMMAP) -/* LPC COMx I/O address (in x86 I/O address space) */ -#define LPC_COMX_ADDR 0x3f8 /* COM1 */ - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) - -static struct host_packet lpc_packet; -static struct host_cmd_handler_args host_cmd_args; -static uint8_t host_cmd_flags; /* Flags from host command */ - -/* Params must be 32-bit aligned */ -static uint8_t params_copy[EC_LPC_HOST_PACKET_SIZE] __aligned(4); -static int init_done; - -static uint8_t * const cmd_params = (uint8_t *)LPC_POOL_CMD_DATA + - EC_LPC_ADDR_HOST_PARAM - EC_LPC_ADDR_HOST_ARGS; -static struct ec_lpc_host_args * const lpc_host_args = - (struct ec_lpc_host_args *)LPC_POOL_CMD_DATA; - -static void wait_irq_sent(void) -{ - /* - * A hard-coded delay here isn't very elegant, but it's the best we can - * manage (and it's a short delay, so it's not that horrible). We need - * this because SIRQRIS isn't cleared in continuous mode, and the EC - * has trouble sending more than 1 frame in quiet mode. Waiting 4 us = - * 2 SERIRQ frames ensures the IRQ has been sent out. - */ - udelay(4); -} - -#ifdef CONFIG_KEYBOARD_IRQ_GPIO -static void keyboard_irq_assert(void) -{ - /* - * Enforce signal-high for long enough for the signal to be pulled high - * by the external pullup resistor. This ensures the host will see the - * following falling edge, regardless of the line state before this - * function call. - */ - uint64_t tstop = get_time().val + MSEC; - gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1); - udelay(4); - /* Generate a falling edge */ - gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 0); - /* Wait for host senses the interrupt and gets the char. */ - do { - if (get_time().val > tstop) - break; - } while (lpc_keyboard_has_char()); - /* Set signal high, now that we've generated the edge */ - gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1); -} -#else -static void wait_send_serirq(uint32_t lpcirqctl) -{ - LM4_LPC_LPCIRQCTL = lpcirqctl; - wait_irq_sent(); -} - -/** - * Manually generate an IRQ to host (edge-trigger). - * - * @param irq_num IRQ number to generate. Pass 0 to set the AH - * (active high) bit. - * - * For SERIRQ quite mode, we need to set LM4_LPC_LPCIRQCTL twice. - * The first one is to assert IRQ (pull low), and then the second one is - * to de-assert it. This generates a pulse (high-low-high) for an IRQ. - */ -static void lpc_manual_irq(int irq_num) -{ - uint32_t common_bits = - 0x00000004 | /* PULSE */ - 0x00000002 | /* ONCHG - for quiet mode */ - 0x00000001; /* SND - send immediately */ - - /* Send out the IRQ first. */ - wait_send_serirq((1 << (irq_num + 16)) | common_bits); - - /* Generate a all-high frame to simulate a rising edge. */ - wait_send_serirq(common_bits); -} - -static inline void keyboard_irq_assert(void) -{ - /* Use serirq method. */ - lpc_manual_irq(1); /* IRQ#1 */ -} -#endif - -/** - * Generate SMI pulse to the host chipset via GPIO. - * - * If the x86 is in S0, SMI# is sampled at 33MHz, so minimum pulse length is - * 60ns. If the x86 is in S3, SMI# is sampled at 32.768KHz, so we need pulse - * length >61us. Both are short enough and events are infrequent, so just - * delay for 65us. - */ -static void lpc_generate_smi(void) -{ - host_event_t smi; - - /* Enforce signal-high for long enough to debounce high */ - gpio_set_level(GPIO_PCH_SMI_L, 1); - udelay(65); - /* Generate a falling edge */ - gpio_set_level(GPIO_PCH_SMI_L, 0); - udelay(65); - /* Set signal high, now that we've generated the edge */ - gpio_set_level(GPIO_PCH_SMI_L, 1); - - smi = lpc_get_host_events_by_type(LPC_HOST_EVENT_SMI); - if (smi) - HOST_EVENT_CPRINTS("smi", smi); -} - -/** - * Generate SCI pulse to the host chipset via LPC0SCI. - */ -static void lpc_generate_sci(void) -{ - host_event_t sci; - -#ifdef CONFIG_SCI_GPIO - /* Enforce signal-high for long enough to debounce high */ - gpio_set_level(CONFIG_SCI_GPIO, 1); - udelay(65); - /* Generate a falling edge */ - gpio_set_level(CONFIG_SCI_GPIO, 0); - udelay(65); - /* Set signal high, now that we've generated the edge */ - gpio_set_level(CONFIG_SCI_GPIO, 1); -#else - LM4_LPC_LPCCTL |= LM4_LPC_SCI_START; -#endif - - sci = lpc_get_host_events_by_type(LPC_HOST_EVENT_SCI); - if (sci) - HOST_EVENT_CPRINTS("sci", sci); -} - -/** - * Update the level-sensitive wake signal to the AP. - * - * @param wake_events Currently asserted wake events - */ -static void lpc_update_wake(uint64_t wake_events) -{ - /* - * Mask off power button event, since the AP gets that through a - * separate dedicated GPIO. - */ - wake_events &= ~EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON); - - /* Signal is asserted low when wake events is non-zero */ - gpio_set_level(GPIO_PCH_WAKE_L, !wake_events); -} - -uint8_t *lpc_get_memmap_range(void) -{ - return (uint8_t *)LPC_POOL_MEMMAP; -} - -static void lpc_send_response(struct host_cmd_handler_args *args) -{ - uint8_t *out; - int size = args->response_size; - int csum; - int i; - - /* Ignore in-progress on LPC since interface is synchronous anyway */ - if (args->result == EC_RES_IN_PROGRESS) - return; - - /* Handle negative size */ - if (size < 0) { - args->result = EC_RES_INVALID_RESPONSE; - size = 0; - } - - /* New-style response */ - lpc_host_args->flags = - (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) | - EC_HOST_ARGS_FLAG_TO_HOST; - - lpc_host_args->data_size = size; - - csum = args->command + lpc_host_args->flags + - lpc_host_args->command_version + - lpc_host_args->data_size; - - for (i = 0, out = (uint8_t *)args->response; i < size; i++, out++) - csum += *out; - - lpc_host_args->checksum = (uint8_t)csum; - - /* Fail if response doesn't fit in the param buffer */ - if (size > EC_PROTO2_MAX_PARAM_SIZE) - args->result = EC_RES_INVALID_RESPONSE; - - /* Write result to the data byte. This sets the TOH status bit. */ - LPC_POOL_CMD[1] = args->result; - - /* Clear the busy bit, so the host knows the EC is done. */ - task_disable_irq(LM4_IRQ_LPC); - LM4_LPC_ST(LPC_CH_CMD) &= ~LM4_LPC_ST_BUSY; - task_enable_irq(LM4_IRQ_LPC); -} - -static void lpc_send_response_packet(struct host_packet *pkt) -{ - /* Ignore in-progress on LPC since interface is synchronous anyway */ - if (pkt->driver_result == EC_RES_IN_PROGRESS) - return; - - /* Write result to the data byte. This sets the TOH status bit. */ - LPC_POOL_CMD[1] = pkt->driver_result; - - /* Clear the busy bit, so the host knows the EC is done. */ - task_disable_irq(LM4_IRQ_LPC); - LM4_LPC_ST(LPC_CH_CMD) &= ~LM4_LPC_ST_BUSY; - task_enable_irq(LM4_IRQ_LPC); -} - -int lpc_keyboard_has_char(void) -{ - return (LM4_LPC_ST(LPC_CH_KEYBOARD) & LM4_LPC_ST_TOH) ? 1 : 0; -} - -/* Return true if the FRMH is set */ -int lpc_keyboard_input_pending(void) -{ - return (LM4_LPC_ST(LPC_CH_KEYBOARD) & LM4_LPC_ST_FRMH) ? 1 : 0; -} - -/* Put a char to host buffer and send IRQ if specified. */ -void lpc_keyboard_put_char(uint8_t chr, int send_irq) -{ - LPC_POOL_KEYBOARD[1] = chr; - if (send_irq) - keyboard_irq_assert(); -} - -void lpc_keyboard_clear_buffer(void) -{ - /* Make sure the previous TOH and IRQ has been sent out. */ - wait_irq_sent(); - - LM4_LPC_ST(LPC_CH_KEYBOARD) &= ~LM4_LPC_ST_TOH; - - /* Ensure there is no TOH set in this period. */ - wait_irq_sent(); -} - -void lpc_keyboard_resume_irq(void) -{ - if (lpc_keyboard_has_char()) - keyboard_irq_assert(); -} - -#ifdef CONFIG_UART_HOST - -int lpc_comx_has_char(void) -{ - return LM4_LPC_ST(LPC_CH_COMX) & LM4_LPC_ST_FRMH; -} - -int lpc_comx_get_char(void) -{ - return LPC_POOL_COMX[0]; -} - -void lpc_comx_put_char(int c) -{ - LPC_POOL_COMX[1] = c; - - /* - * We could in theory manually trigger an IRQ, like we do for the 8042 - * keyboard interface, but neither the kernel nor BIOS seems to require - * this. - */ -} - -#endif /* CONFIG_UART_HOST */ - -/** - * Update the host event status. - * - * Sends a pulse if masked event status becomes non-zero: - * - SMI pulse via EC_SMI_L GPIO - * - SCI pulse via LPC0SCI - */ -void lpc_update_host_event_status(void) -{ - int need_sci = 0; - int need_smi = 0; - - if (!init_done) - return; - - /* Disable LPC interrupt while updating status register */ - task_disable_irq(LM4_IRQ_LPC); - - if (lpc_get_host_events_by_type(LPC_HOST_EVENT_SMI)) { - /* Only generate SMI for first event */ - if (!(LM4_LPC_ST(LPC_CH_ACPI) & LM4_LPC_ST_SMI)) - need_smi = 1; - LM4_LPC_ST(LPC_CH_ACPI) |= LM4_LPC_ST_SMI; - } else - LM4_LPC_ST(LPC_CH_ACPI) &= ~LM4_LPC_ST_SMI; - - if (lpc_get_host_events_by_type(LPC_HOST_EVENT_SCI)) { - /* Generate SCI for every event */ - need_sci = 1; - LM4_LPC_ST(LPC_CH_ACPI) |= LM4_LPC_ST_SCI; - } else - LM4_LPC_ST(LPC_CH_ACPI) &= ~LM4_LPC_ST_SCI; - - /* Copy host events to mapped memory */ - *(host_event_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = - lpc_get_host_events(); - - task_enable_irq(LM4_IRQ_LPC); - - /* Process the wake events. */ - lpc_update_wake(lpc_get_host_events_by_type(LPC_HOST_EVENT_WAKE)); - - /* Send pulse on SMI signal if needed */ - if (need_smi) - lpc_generate_smi(); - - /* ACPI 5.0-12.6.1: Generate SCI for SCI_EVT=1. */ - if (need_sci) - lpc_generate_sci(); -} - -void lpc_set_acpi_status_mask(uint8_t mask) -{ - uint32_t set_mask = 0; - if (mask & EC_LPC_STATUS_BURST_MODE) - set_mask |= LM4_LPC_ST_BURST; - - LM4_LPC_ST(LPC_CH_ACPI) |= set_mask; -} - -void lpc_clear_acpi_status_mask(uint8_t mask) -{ - uint32_t clear_mask = 0; - if (mask & EC_LPC_STATUS_BURST_MODE) - clear_mask |= LM4_LPC_ST_BURST; - - LM4_LPC_ST(LPC_CH_ACPI) &= ~clear_mask; -} - -int lpc_get_pltrst_asserted(void) -{ - return (LM4_LPC_LPCSTS & BIT(10)) ? 1 : 0; -} - -/** - * Handle write to ACPI I/O port - * - * @param is_cmd Is write command (is_cmd=1) or data (is_cmd=0) - */ -static void handle_acpi_write(int is_cmd) -{ - uint8_t value, result; - - /* Set the busy bit */ - LM4_LPC_ST(LPC_CH_ACPI) |= LM4_LPC_ST_BUSY; - - /* Read command/data; this clears the FRMH status bit. */ - value = LPC_POOL_ACPI[0]; - - /* Handle whatever this was. */ - if (acpi_ap_to_ec(is_cmd, value, &result)) - LPC_POOL_ACPI[1] = result; - - /* Clear the busy bit */ - LM4_LPC_ST(LPC_CH_ACPI) &= ~LM4_LPC_ST_BUSY; - - /* - * ACPI 5.0-12.6.1: Generate SCI for Input Buffer Empty / Output Buffer - * Full condition on the kernel channel. - */ - lpc_generate_sci(); -} - -/** - * Handle write to host command I/O ports. - * - * @param is_cmd Is write command (1) or data (0)? - */ -static void handle_host_write(int is_cmd) -{ - /* Ignore data writes or overlapping commands from host */ - uint32_t is_overlapping = LM4_LPC_ST(LPC_CH_CMD) & LM4_LPC_ST_BUSY; - if (!is_cmd || is_overlapping) { - if (is_overlapping) - CPRINTS("LPC Ignoring overlapping HC"); - LM4_LPC_ST(LPC_CH_CMD) &= ~LM4_LPC_ST_FRMH; - return; - } - - /* Set the busy bit */ - LM4_LPC_ST(LPC_CH_CMD) |= LM4_LPC_ST_BUSY; - - /* - * Read the command byte. This clears the FRMH bit in - * the status byte. - */ - host_cmd_args.command = LPC_POOL_CMD[0]; - - host_cmd_args.result = EC_RES_SUCCESS; - host_cmd_args.send_response = lpc_send_response; - host_cmd_flags = lpc_host_args->flags; - - /* See if we have an old or new style command */ - if (host_cmd_args.command == EC_COMMAND_PROTOCOL_3) { - lpc_packet.send_response = lpc_send_response_packet; - - lpc_packet.request = (const void *)LPC_POOL_CMD_DATA; - lpc_packet.request_temp = params_copy; - lpc_packet.request_max = sizeof(params_copy); - /* Don't know the request size so pass in the entire buffer */ - lpc_packet.request_size = EC_LPC_HOST_PACKET_SIZE; - - lpc_packet.response = (void *)LPC_POOL_CMD_DATA; - lpc_packet.response_max = EC_LPC_HOST_PACKET_SIZE; - lpc_packet.response_size = 0; - - lpc_packet.driver_result = EC_RES_SUCCESS; - host_packet_receive(&lpc_packet); - return; - - } else if (host_cmd_flags & EC_HOST_ARGS_FLAG_FROM_HOST) { - /* Version 2 (link) style command */ - int size = lpc_host_args->data_size; - int csum, i; - - host_cmd_args.version = lpc_host_args->command_version; - host_cmd_args.params = params_copy; - host_cmd_args.params_size = size; - host_cmd_args.response = cmd_params; - host_cmd_args.response_max = EC_PROTO2_MAX_PARAM_SIZE; - host_cmd_args.response_size = 0; - - /* Verify params size */ - if (size > EC_PROTO2_MAX_PARAM_SIZE) { - host_cmd_args.result = EC_RES_INVALID_PARAM; - } else { - const uint8_t *src = cmd_params; - uint8_t *copy = params_copy; - - /* - * Verify checksum and copy params out of LPC space. - * This ensures the data acted on by the host command - * handler can't be changed by host writes after the - * checksum is verified. - */ - csum = host_cmd_args.command + - host_cmd_flags + - host_cmd_args.version + - host_cmd_args.params_size; - - for (i = 0; i < size; i++) { - csum += *src; - *(copy++) = *(src++); - } - - if ((uint8_t)csum != lpc_host_args->checksum) - host_cmd_args.result = EC_RES_INVALID_CHECKSUM; - } - } else { - /* Old style command, now unsupported */ - host_cmd_args.result = EC_RES_INVALID_COMMAND; - } - - /* Hand off to host command handler */ - host_command_received(&host_cmd_args); -} - -#ifdef CONFIG_CHIPSET_RESET_HOOK -static void lpc_chipset_reset(void) -{ - hook_notify(HOOK_CHIPSET_RESET); -} -DECLARE_DEFERRED(lpc_chipset_reset); -#endif - -/** - * LPC interrupt handler - */ -void lpc_interrupt(void) -{ - uint32_t mis = LM4_LPC_LPCMIS; - uint32_t st; - - /* Clear the interrupt bits we're handling */ - LM4_LPC_LPCIC = mis; - -#ifdef HAS_TASK_HOSTCMD - /* Handle ACPI command and data writes */ - st = LM4_LPC_ST(LPC_CH_ACPI); - if (st & LM4_LPC_ST_FRMH) - handle_acpi_write(st & LM4_LPC_ST_CMD); - - /* Handle user command writes */ - st = LM4_LPC_ST(LPC_CH_CMD); - if (st & LM4_LPC_ST_FRMH) - handle_host_write(st & LM4_LPC_ST_CMD); -#endif - - /* - * Handle port 80 writes (CH0MIS1). Due to crosbug.com/p/12349 the - * interrupt status (mis & LM4_LPC_INT_MASK(LPC_CH_PORT80, 2)) - * apparently gets lost on back-to-back writes to port 80, so check the - * FRMH bit in the channel status register to see if a write is - * pending. Loop to handle bursts of back-to-back writes. - */ - while (LM4_LPC_ST(LPC_CH_PORT80) & LM4_LPC_ST_FRMH) - port_80_write(LPC_POOL_PORT80[0]); - -#ifdef HAS_TASK_KEYPROTO - /* Handle keyboard interface writes */ - st = LM4_LPC_ST(LPC_CH_KEYBOARD); - if (st & LM4_LPC_ST_FRMH) - keyboard_host_write(LPC_POOL_KEYBOARD[0], st & LM4_LPC_ST_CMD); - - if (mis & LM4_LPC_INT_MASK(LPC_CH_KEYBOARD, 1)) { - /* Host read data; wake up task to send remaining bytes */ - task_wake(TASK_ID_KEYPROTO); - } -#endif - -#ifdef CONFIG_UART_HOST - /* Handle COMx */ - if (lpc_comx_has_char()) { - /* Copy a character to the UART if there's space */ - if (uart_comx_putc_ok()) - uart_comx_putc(lpc_comx_get_char()); - } -#endif - - /* Debugging: print changes to LPC0RESET */ - if (mis & BIT(31)) { - if (LM4_LPC_LPCSTS & BIT(10)) { - int i; - - /* Store port 80 reset event */ - port_80_write(PORT_80_EVENT_RESET); - - /* - * Workaround for crosbug.com/p/12349; clear all FRMH - * bits so host writes will trigger interrupts. - */ - for (i = 0; i < 8; i++) - LM4_LPC_ST(i) &= ~LM4_LPC_ST_FRMH; - -#ifdef CONFIG_CHIPSET_RESET_HOOK - /* Notify HOOK_CHIPSET_RESET */ - hook_call_deferred(&lpc_chipset_reset_data, MSEC); -#endif - } - - CPRINTS("LPC RESET# %sasserted", - lpc_get_pltrst_asserted() ? "" : "de"); - } -} -DECLARE_IRQ(LM4_IRQ_LPC, lpc_interrupt, 2); - -/* Enable LPC ACPI-EC interrupts */ -void lpc_enable_acpi_interrupts(void) -{ - LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_ACPI, 6); -} - -/* Disable LPC ACPI-EC interrupts */ -void lpc_disable_acpi_interrupts(void) -{ - LM4_LPC_LPCIM &= ~(LM4_LPC_INT_MASK(LPC_CH_ACPI, 6)); -} - -static void lpc_init(void) -{ - /* Enable LPC clock in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_LPC, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - LM4_LPC_LPCIM = 0; - LM4_LPC_LPCCTL = 0; - LM4_LPC_LPCIRQCTL = 0; - - /* Configure GPIOs */ - gpio_config_module(MODULE_LPC, 1); - - /* - * Set LPC channel 0 to I/O address 0x62 (data) / 0x66 (command), - * single endpoint, offset 0 for host command/writes and 1 for EC - * data writes, pool bytes 0(data)/1(cmd) - */ - LM4_LPC_ADR(LPC_CH_ACPI) = EC_LPC_ADDR_ACPI_DATA; - LM4_LPC_CTL(LPC_CH_ACPI) = (LPC_POOL_OFFS_ACPI << (5 - 1)); - LM4_LPC_ST(LPC_CH_ACPI) = 0; - /* Unmask interrupt for host command and data writes */ - LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_ACPI, 6); - - /* - * Set LPC channel 1 to I/O address 0x80 (data), single endpoint, - * pool bytes 4(data)/5(cmd). - */ - LM4_LPC_ADR(LPC_CH_PORT80) = 0x80; - LM4_LPC_CTL(LPC_CH_PORT80) = (LPC_POOL_OFFS_PORT80 << (5 - 1)); - /* Unmask interrupt for host data writes */ - LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_PORT80, 2); - - /* - * Set LPC channel 2 to I/O address 0x880, range endpoint, - * arbitration disabled, pool bytes 512-639. To access this from - * x86, use the following command to set GEN_LPC2: - * - * pci_write32 0 0x1f 0 0x88 0x007c0801 - */ - LM4_LPC_ADR(LPC_CH_CMD_DATA) = EC_LPC_ADDR_HOST_ARGS; - LM4_LPC_CTL(LPC_CH_CMD_DATA) = 0x8019 | - (LPC_POOL_OFFS_CMD_DATA << (5 - 1)); - - /* - * Set LPC channel 3 to I/O address 0x60 (data) / 0x64 (command), - * single endpoint, offset 0 for host command/writes and 1 for EC - * data writes, pool bytes 0(data)/1(cmd) - */ - LM4_LPC_ADR(LPC_CH_KEYBOARD) = 0x60; - LM4_LPC_CTL(LPC_CH_KEYBOARD) = (BIT(24)/* IRQSEL1 */) | - (0 << 18/* IRQEN1 */) | (LPC_POOL_OFFS_KEYBOARD << (5 - 1)); - LM4_LPC_ST(LPC_CH_KEYBOARD) = 0; - /* Unmask interrupt for host command/data writes and data reads */ - LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_KEYBOARD, 7); - - /* - * Set LPC channel 4 to I/O address 0x200 (data) / 0x204 (command), - * single endpoint, offset 0 for host command/writes and 1 for EC - * data writes, pool bytes 0(data)/1(cmd) - */ - LM4_LPC_ADR(LPC_CH_CMD) = EC_LPC_ADDR_HOST_DATA; - LM4_LPC_CTL(LPC_CH_CMD) = (LPC_POOL_OFFS_CMD << (5 - 1)); - /* - * Initialize status bits to 0. We never set the ACPI burst status bit, - * so this guarantees that at least one status bit will always be 0. - * This is used by comm_lpc.c to detect that the EC is present on the - * LPC bus. See crosbug.com/p/10963. - */ - LM4_LPC_ST(LPC_CH_CMD) = 0; - /* Unmask interrupt for host command writes */ - LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_CMD, 4); - - /* - * Set LPC channel 5 to I/O address 0x900, range endpoint, - * arbitration enabled, pool bytes 768-1023. To access this from - * x86, use the following command to set GEN_LPC3: - * - * pci_write32 0 0x1f 0 0x8c 0x007c0901 - */ - LM4_LPC_ADR(LPC_CH_MEMMAP) = EC_LPC_ADDR_MEMMAP; - LM4_LPC_CTL(LPC_CH_MEMMAP) = 0x0019 | (LPC_POOL_OFFS_MEMMAP << (5 - 1)); - -#ifdef CONFIG_UART_HOST - /* - * Set LPC channel 7 to COM port I/O address. Note that channel 7 - * ignores the TYPE bit and is always an 8-byte range. - */ - LM4_LPC_ADR(LPC_CH_COMX) = LPC_COMX_ADDR; - /* - * In theory we could configure IRQSELs and set IRQEN2/CX, and then the - * host could enable IRQs on its own. So far that hasn't been - * necessary, and due to the issues with IRQs (see wait_irq_sent() - * above) it might not work anyway. - */ - LM4_LPC_CTL(LPC_CH_COMX) = 0x0004 | (LPC_POOL_OFFS_COMX << (5 - 1)); - /* Enable COMx emulation for reads and writes. */ - LM4_LPC_LPCDMACX = 0x00310000; - /* - * Unmask interrupt for host data writes. We don't need interrupts for - * reads, because there's no flow control in that direction; LPC is - * much faster than the UART, and the UART doesn't have anywhere - * sensible to buffer input anyway. - */ - LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_COMX, 2); -#endif /* CONFIG_UART_HOST */ - - /* - * Unmask LPC bus reset interrupt. This lets us monitor the PCH - * PLTRST# signal for debugging. - */ - LM4_LPC_LPCIM |= BIT(31); - - /* Enable LPC channels */ - LM4_LPC_LPCCTL = LM4_LPC_SCI_CLK_1 | - BIT(LPC_CH_ACPI) | - BIT(LPC_CH_PORT80) | - BIT(LPC_CH_CMD_DATA) | - BIT(LPC_CH_KEYBOARD) | - BIT(LPC_CH_CMD) | - BIT(LPC_CH_MEMMAP); - -#ifdef CONFIG_UART_HOST - LM4_LPC_LPCCTL |= 1 << LPC_CH_COMX; -#endif - - /* - * Ensure the EC (slave) has control of the memory-mapped I/O space. - * Once the EC has won arbitration for the memory-mapped space, it will - * keep control of it until it writes the last byte in the space. - * (That never happens; we can't use the last byte in the space because - * ACPI can't see it anyway.) - */ - while (!(LM4_LPC_ST(LPC_CH_MEMMAP) & 0x10)) { - /* Clear HW1ST */ - LM4_LPC_ST(LPC_CH_MEMMAP) &= ~0x40; - /* Do a slave write; this should cause SW1ST to be set */ - *LPC_POOL_MEMMAP = *LPC_POOL_MEMMAP; - } - - /* Initialize host args and memory map to all zero */ - memset(lpc_host_args, 0, sizeof(*lpc_host_args)); - memset(lpc_get_memmap_range(), 0, EC_MEMMAP_SIZE); - - /* We support LPC args and version 3 protocol */ - *(lpc_get_memmap_range() + EC_MEMMAP_HOST_CMD_FLAGS) = - EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED | - EC_HOST_CMD_FLAG_VERSION_3; - - /* Enable LPC interrupt */ - task_enable_irq(LM4_IRQ_LPC); - -#ifdef CONFIG_UART_HOST - /* Enable COMx UART */ - uart_comx_enable(); -#endif - - /* Sufficiently initialized */ - init_done = 1; - - /* Update host events now that we can copy them to memmap */ - lpc_update_host_event_status(); -} -/* - * Set prio to higher than default; this way LPC memory mapped data is ready - * before other inits try to initialize their memmap data. - */ -DECLARE_HOOK(HOOK_INIT, lpc_init, HOOK_PRIO_INIT_LPC); - -static void lpc_tick(void) -{ - /* - * Make sure pending LPC interrupts have been processed. - * This works around a LM4 bug where host writes sometimes - * don't trigger interrupts. See crosbug.com/p/13965. - */ - task_trigger_irq(LM4_IRQ_LPC); -} -DECLARE_HOOK(HOOK_TICK, lpc_tick, HOOK_PRIO_DEFAULT); - -/** - * Get protocol information - */ -static enum ec_status lpc_get_protocol_info(struct host_cmd_handler_args *args) -{ - struct ec_response_get_protocol_info *r = args->response; - - memset(r, 0, sizeof(*r)); - r->protocol_versions = BIT(2) | BIT(3); - r->max_request_packet_size = EC_LPC_HOST_PACKET_SIZE; - r->max_response_packet_size = EC_LPC_HOST_PACKET_SIZE; - r->flags = 0; - - args->response_size = sizeof(*r); - - return EC_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, - lpc_get_protocol_info, - EC_VER_MASK(0)); diff --git a/chip/lm4/peci.c b/chip/lm4/peci.c deleted file mode 100644 index b3b54a64bc..0000000000 --- a/chip/lm4/peci.c +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* PECI interface for Chrome EC */ - -#include "chipset.h" -#include "clock.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "peci.h" -#include "registers.h" -#include "temp_sensor.h" -#include "util.h" - -/* Initial PECI baud rate */ -#define PECI_BAUD_RATE 100000 - -/* Polling interval for PECI, in ms */ -#define PECI_POLL_INTERVAL_MS 250 - -/* - * Internal and external path delays, in ns. The external delay is a - * best-guess measurement, but we're fairly tolerant of a bad guess because - * PECI_BAUD_RATE is slow compared to PECI's actual maximum baud rate. - */ -#define PECI_TD_FET_NS 60 -#define PECI_TD_INT_NS 80 - -/* Number of controller retries. Should be between 0 and 7. */ -#define PECI_RETRY_COUNT 4 - -/* Timing negotiation error bypass. 1 = on. 0 = off. */ -#define PECI_ERROR_BYPASS 1 - -#define TEMP_AVG_LENGTH 4 /* Should be power of 2 */ -static int temp_vals[TEMP_AVG_LENGTH]; -static int temp_idx; - -int peci_get_cpu_temp(void) -{ - int v = LM4_PECI_M0D0 & 0xffff; - - if (v >= 0x8000 && v <= 0x8fff) - return -1; - - return v >> 6; -} - -int peci_temp_sensor_get_val(int idx, int *temp_ptr) -{ - int sum = 0; - int success_cnt = 0; - int i; - - if (!chipset_in_state(CHIPSET_STATE_ON)) - return EC_ERROR_NOT_POWERED; - - for (i = 0; i < TEMP_AVG_LENGTH; ++i) { - if (temp_vals[i] >= 0) { - success_cnt++; - sum += temp_vals[i]; - } - } - - /* - * Require at least two valid samples. When the AP transitions into S0, - * it is possible, depending on the timing of the PECI sample, to read - * an invalid temperature. This is very rare, but when it does happen - * the temperature returned is CONFIG_PECI_TJMAX. Requiring two valid - * samples here assures us that one bad maximum temperature reading - * when entering S0 won't cause us to trigger an over temperature. - */ - if (success_cnt < 2) - return EC_ERROR_UNKNOWN; - - *temp_ptr = sum / success_cnt; - return EC_SUCCESS; -} - -static void peci_temp_sensor_poll(void) -{ - temp_vals[temp_idx] = peci_get_cpu_temp(); - temp_idx = (temp_idx + 1) & (TEMP_AVG_LENGTH - 1); -} -DECLARE_HOOK(HOOK_TICK, peci_temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -static void peci_freq_changed(void) -{ - int freq = clock_get_freq(); - int baud; - - /* Disable polling while reconfiguring */ - LM4_PECI_CTL = 0; - - /* - * Calculate baud setting from desired rate, compensating for internal - * and external delays. - */ - baud = freq / (4 * PECI_BAUD_RATE) - 2; - baud -= (freq / 1000000) * (PECI_TD_FET_NS + PECI_TD_INT_NS) / 1000; - - /* Set baud rate and polling rate */ - LM4_PECI_DIV = (baud << 16) | - (PECI_POLL_INTERVAL_MS * (freq / 1000 / 4096)); - - /* Set up temperature monitoring to report in degrees K */ - LM4_PECI_CTL = ((CONFIG_PECI_TJMAX + 273) << 22) | 0x0001 | - (PECI_RETRY_COUNT << 12) | - (PECI_ERROR_BYPASS << 11); -} -DECLARE_HOOK(HOOK_FREQ_CHANGE, peci_freq_changed, HOOK_PRIO_DEFAULT); - -static void peci_init(void) -{ - int i; - - /* Enable the PECI module in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_PECI, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - /* Configure GPIOs */ - gpio_config_module(MODULE_PECI, 1); - - /* Set initial clock frequency */ - peci_freq_changed(); - - /* Initialize temperature reading buffer to a valid value. */ - for (i = 0; i < TEMP_AVG_LENGTH; ++i) - temp_vals[i] = 300; /* 27 C */ -} -DECLARE_HOOK(HOOK_INIT, peci_init, HOOK_PRIO_DEFAULT); - -/*****************************************************************************/ -/* Console commands */ - -static int command_peci_temp(int argc, char **argv) -{ - int t = peci_get_cpu_temp(); - if (t == -1) { - ccprintf("PECI error 0x%04x\n", LM4_PECI_M0D0 & 0xffff); - return EC_ERROR_UNKNOWN; - } - ccprintf("CPU temp = %d K = %d C\n", t, K_TO_C(t)); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp, - NULL, - "Print CPU temperature"); diff --git a/chip/lm4/pwm.c b/chip/lm4/pwm.c deleted file mode 100644 index 38ce61714d..0000000000 --- a/chip/lm4/pwm.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* PWM control module for LM4. - * - * On this chip, the PWM logic is implemented by the hardware FAN modules. - */ - -#include "clock.h" -#include "fan.h" -#include "gpio.h" -#include "hooks.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "registers.h" -#include "util.h" - -void pwm_enable(enum pwm_channel ch, int enabled) -{ - fan_set_enabled(pwm_channels[ch].channel, enabled); -} - -int pwm_get_enabled(enum pwm_channel ch) -{ - return fan_get_enabled(pwm_channels[ch].channel); -} - -void pwm_set_duty(enum pwm_channel ch, int percent) -{ - if (percent < 0) - percent = 0; - else if (percent > 100) - percent = 100; - - /* Assume the fan control is active high and invert it ourselves */ - if (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW) - percent = 100 - percent; - - /* Always enable the channel */ - pwm_enable(ch, 1); - - /* Set the duty cycle */ - fan_set_duty(pwm_channels[ch].channel, percent); -} - -int pwm_get_duty(enum pwm_channel ch) -{ - int percent = fan_get_duty(pwm_channels[ch].channel); - - if (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW) - percent = 100 - percent; - - return percent; -} - -static void pwm_init(void) -{ - int i; - - for (i = 0; i < PWM_CH_COUNT; ++i) - fan_channel_setup(pwm_channels[i].channel, - (pwm_channels[i].flags & - PWM_CONFIG_HAS_RPM_MODE) - ? FAN_USE_RPM_MODE : 0); -} - -/* The chip-specific fan module initializes before this. */ -DECLARE_HOOK(HOOK_INIT, pwm_init, HOOK_PRIO_INIT_PWM); diff --git a/chip/lm4/pwm_chip.h b/chip/lm4/pwm_chip.h deleted file mode 100644 index ada5785495..0000000000 --- a/chip/lm4/pwm_chip.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* LM4-specific PWM module for Chrome EC */ - -#ifndef __CROS_EC_PWM_CHIP_H -#define __CROS_EC_PWM_CHIP_H - -/* Data structure to define PWM channels. */ -struct pwm_t { - /* PWM channel ID */ - int channel; - /* PWM channel flags. See include/pwm.h */ - uint32_t flags; -}; - -extern const struct pwm_t pwm_channels[]; - -#endif /* __CROS_EC_PWM_CHIP_H */ diff --git a/chip/lm4/registers.h b/chip/lm4/registers.h deleted file mode 100644 index 0c59da19f6..0000000000 --- a/chip/lm4/registers.h +++ /dev/null @@ -1,600 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Register map for LM4x processor - */ - -#ifndef __CROS_EC_REGISTERS_H -#define __CROS_EC_REGISTERS_H - -#include "common.h" - -#define LM4_UART_CH0_BASE 0x4000c000 -#define LM4_UART_CH1_BASE 0x4000d000 -#define LM4_UART_CH_SEP 0x00001000 -static inline int lm4_uart_addr(int ch, int offset) -{ - return offset + LM4_UART_CH0_BASE + LM4_UART_CH_SEP * ch; -} -#define LM4UARTREG(ch, offset) REG32(lm4_uart_addr(ch, offset)) -#define LM4_UART_DR(ch) LM4UARTREG(ch, 0x000) -#define LM4_UART_FR(ch) LM4UARTREG(ch, 0x018) -#define LM4_UART_IBRD(ch) LM4UARTREG(ch, 0x024) -#define LM4_UART_FBRD(ch) LM4UARTREG(ch, 0x028) -#define LM4_UART_LCRH(ch) LM4UARTREG(ch, 0x02c) -#define LM4_UART_CTL(ch) LM4UARTREG(ch, 0x030) -#define LM4_UART_IFLS(ch) LM4UARTREG(ch, 0x034) -#define LM4_UART_IM(ch) LM4UARTREG(ch, 0x038) -#define LM4_UART_ICR(ch) LM4UARTREG(ch, 0x044) -#define LM4_UART_DMACTL(ch) LM4UARTREG(ch, 0x048) -#define LM4_UART_CC(ch) LM4UARTREG(ch, 0xfc8) - -#define LM4_SSI_BASE 0x40008000 -#define LM4_SSI_CH_SEP 0x40001000 -static inline int lm4_spi_addr(int ch, int offset) -{ - return offset + LM4_SSI_BASE + LM4_SSI_CH_SEP * ch; -} -#define LM4SSIREG(ch, offset) REG32(lm4_spi_addr(ch, offset)) -#define LM4_SSI_CR0(ch) LM4SSIREG(ch, 0x000) -#define LM4_SSI_CR1(ch) LM4SSIREG(ch, 0x004) -#define LM4_SSI_DR(ch) LM4SSIREG(ch, 0x008) -#define LM4_SSI_SR(ch) LM4SSIREG(ch, 0x00c) -#define LM4_SSI_SR_TFE BIT(0) /* Transmit FIFO empty */ -#define LM4_SSI_SR_TNF BIT(1) /* Transmit FIFO not full */ -#define LM4_SSI_SR_RNE BIT(2) /* Receive FIFO not empty */ -#define LM4_SSI_SR_RFF BIT(3) /* Receive FIFO full */ -#define LM4_SSI_SR_BSY BIT(4) /* Busy */ -#define LM4_SSI_CPSR(ch) LM4SSIREG(ch, 0x010) -#define LM4_SSI_IM(ch) LM4SSIREG(ch, 0x014) -#define LM4_SSI_RIS(ch) LM4SSIREG(ch, 0x018) -#define LM4_SSI_MIS(ch) LM4SSIREG(ch, 0x01c) -#define LM4_SSI_ICR(ch) LM4SSIREG(ch, 0x020) -#define LM4_SSI_DMACTL(ch) LM4SSIREG(ch, 0x024) -#define LM4_SSI_CC(ch) LM4SSIREG(ch, 0xfc8) - -#define LM4_ADC_ADCACTSS REG32(0x40038000) -#define LM4_ADC_ADCRIS REG32(0x40038004) -#define LM4_ADC_ADCIM REG32(0x40038008) -#define LM4_ADC_ADCISC REG32(0x4003800c) -#define LM4_ADC_ADCOSTAT REG32(0x40038010) -#define LM4_ADC_ADCEMUX REG32(0x40038014) -#define LM4_ADC_ADCUSTAT REG32(0x40038018) -#define LM4_ADC_ADCSSPRI REG32(0x40038020) -#define LM4_ADC_ADCSPC REG32(0x40038024) -#define LM4_ADC_ADCPSSI REG32(0x40038028) -#define LM4_ADC_ADCSAC REG32(0x40038030) -#define LM4_ADC_ADCCTL REG32(0x40038038) -#define LM4_ADC_ADCCC REG32(0x40038fc8) -#define LM4_ADC_SS0_BASE 0x40038040 -#define LM4_ADC_SS1_BASE 0x40038060 -#define LM4_ADC_SS2_BASE 0x40038080 -#define LM4_ADC_SS3_BASE 0x400380a0 -#define LM4_ADC_SS_SEP 0x00000020 -static inline int lm4_adc_addr(int ss, int offset) -{ - return offset + LM4_ADC_SS0_BASE + LM4_ADC_SS_SEP * ss; -} -#define LM4ADCREG(ss, offset) REG32(lm4_adc_addr(ss, offset)) -#define LM4_ADC_SSMUX(ss) LM4ADCREG(ss, 0x000) -#define LM4_ADC_SSCTL(ss) LM4ADCREG(ss, 0x004) -#define LM4_ADC_SSFIFO(ss) LM4ADCREG(ss, 0x008) -#define LM4_ADC_SSFSTAT(ss) LM4ADCREG(ss, 0x00c) -#define LM4_ADC_SSOP(ss) LM4ADCREG(ss, 0x010) -#define LM4_ADC_SSEMUX(ss) LM4ADCREG(ss, 0x018) - -#define LM4_LPC_LPCCTL REG32(0x40080000) -#define LM4_LPC_SCI_START BIT(9) /* Start a pulse on LPC0SCI signal */ -#define LM4_LPC_SCI_CLK_1 (0 << 10) /* SCI asserted for 1 clock period */ -#define LM4_LPC_SCI_CLK_2 (1 << 10) /* SCI asserted for 2 clock periods */ -#define LM4_LPC_SCI_CLK_4 (2 << 10) /* SCI asserted for 4 clock periods */ -#define LM4_LPC_SCI_CLK_8 (3 << 10) /* SCI asserted for 8 clock periods */ -#define LM4_LPC_LPCSTS REG32(0x40080004) -#define LM4_LPC_LPCIRQCTL REG32(0x40080008) -#define LM4_LPC_LPCIRQST REG32(0x4008000c) -#define LM4_LPC_LPCIM REG32(0x40080100) -#define LM4_LPC_LPCRIS REG32(0x40080104) -#define LM4_LPC_LPCMIS REG32(0x40080108) -#define LM4_LPC_LPCIC REG32(0x4008010c) -#define LM4_LPC_INT_MASK(ch, bits) ((bits) << (4 * (ch))) -#define LM4_LPC_LPCDMACX REG32(0x40080120) -#define LM4_LPC_CH0_BASE 0x40080010 -#define LM4_LPC_CH1_BASE 0x40080020 -#define LM4_LPC_CH2_BASE 0x40080030 -#define LM4_LPC_CH3_BASE 0x40080040 -#define LM4_LPC_CH4_BASE 0x40080050 -#define LM4_LPC_CH5_BASE 0x40080060 -#define LM4_LPC_CH6_BASE 0x40080070 -#define LM4_LPC_CH7_BASE 0x40080080 -#define LM4_LPC_CH_SEP 0x00000010 -static inline int lm4_lpc_addr(int ch, int offset) -{ - return offset + LM4_LPC_CH0_BASE + LM4_LPC_CH_SEP * ch; -} -#define LM4LPCREG(ch, offset) REG32(lm4_lpc_addr(ch, offset)) -#define LM4_LPC_CTL(ch) LM4LPCREG(ch, 0x000) -#define LM4_LPC_ST(ch) LM4LPCREG(ch, 0x004) -#define LM4_LPC_ST_TOH BIT(0) /* TO Host bit */ -#define LM4_LPC_ST_FRMH BIT(1) /* FRoM Host bit */ -#define LM4_LPC_ST_CMD BIT(3) /* Last from-host byte was command */ -#define LM4_LPC_ST_BURST BIT(8) -#define LM4_LPC_ST_SCI BIT(9) -#define LM4_LPC_ST_SMI BIT(10) -#define LM4_LPC_ST_BUSY BIT(12) -#define LM4_LPC_ADR(ch) LM4LPCREG(ch, 0x008) -#define LM4_LPC_POOL_BYTES 1024 /* Size of LPCPOOL in bytes */ -#define LM4_LPC_LPCPOOL ((volatile unsigned char *)0x40080400) - -#define LM4_FAN_FANSTS REG32(0x40084000) -#define LM4_FAN_FANCTL REG32(0x40084004) -#define LM4_FAN_CH0_BASE 0x40084010 -#define LM4_FAN_CH1_BASE 0x40084020 -#define LM4_FAN_CH2_BASE 0x40084030 -#define LM4_FAN_CH3_BASE 0x40084040 -#define LM4_FAN_CH4_BASE 0x40084050 -#define LM4_FAN_CH5_BASE 0x40084060 -#define LM4_FAN_CH_SEP 0x00000010 -static inline int lm4_fan_addr(int ch, int offset) -{ - return offset + LM4_FAN_CH0_BASE + LM4_FAN_CH_SEP * ch; -} -#define LM4FANREG(ch, offset) REG32(lm4_fan_addr(ch, offset)) -#define LM4_FAN_FANCH(ch) LM4FANREG(ch, 0x000) -#define LM4_FAN_FANCMD(ch) LM4FANREG(ch, 0x004) -#define LM4_FAN_FANCST(ch) LM4FANREG(ch, 0x008) - -#define LM4_EEPROM_EESIZE REG32(0x400af000) -#define LM4_EEPROM_EEBLOCK REG32(0x400af004) -#define LM4_EEPROM_EEOFFSET REG32(0x400af008) -#define LM4_EEPROM_EERDWR REG32(0x400af010) -#define LM4_EEPROM_EERDWRINC REG32(0x400af014) -#define LM4_EEPROM_EEDONE REG32(0x400af018) -#define LM4_EEPROM_EESUPP REG32(0x400af01c) -#define LM4_EEPROM_EEUNLOCK REG32(0x400af020) -#define LM4_EEPROM_EEPROT REG32(0x400af030) -#define LM4_EEPROM_EEPASS0 REG32(0x400af034) -#define LM4_EEPROM_EEPASS1 REG32(0x400af038) -#define LM4_EEPROM_EEPASS2 REG32(0x400af03c) -#define LM4_EEPROM_EEINT REG32(0x400af040) -#define LM4_EEPROM_EEHIDE REG32(0x400af050) - -#define LM4_PECI_CTL REG32(0x400b0000) -#define LM4_PECI_DIV REG32(0x400b0004) -#define LM4_PECI_CMP REG32(0x400b0008) -#define LM4_PECI_M0D0C REG32(0x400b0010) -#define LM4_PECI_M0D1C REG32(0x400b0014) -#define LM4_PECI_M1D0C REG32(0x400b0018) -#define LM4_PECI_M1D1C REG32(0x400b001c) -#define LM4_PECI_M0D0 REG32(0x400b0040) -#define LM4_PECI_M0D1 REG32(0x400b0044) -#define LM4_PECI_M1D0 REG32(0x400b0048) -#define LM4_PECI_M1D1 REG32(0x400b004c) -#define LM4_PECI_IM REG32(0x400b0080) -#define LM4_PECI_RIS REG32(0x400b0084) -#define LM4_PECI_MIS REG32(0x400b0088) -#define LM4_PECI_IC REG32(0x400b008c) -#define LM4_PECI_ACADDR REG32(0x400b0100) -#define LM4_PECI_ACARG REG32(0x400b0104) -#define LM4_PECI_ACRDWR0 REG32(0x400b0108) -#define LM4_PECI_ACRDWR1 REG32(0x400b010c) -#define LM4_PECI_ACCMD REG32(0x400b0110) -#define LM4_PECI_ACCODE REG32(0x400b0114) - - -#define LM4_HIBERNATE_HIBRTCC REG32(0x400fc000) -#define LM4_HIBERNATE_HIBRTCM0 REG32(0x400fc004) -#define LM4_HIBERNATE_HIBRTCLD REG32(0x400fc00c) -#define LM4_HIBERNATE_HIBCTL REG32(0x400fc010) -#define LM4_HIBCTL_WRC BIT(31) -#define LM4_HIBCTL_CLK32EN BIT(6) -#define LM4_HIBCTL_PINWEN BIT(4) -#define LM4_HIBCTL_RTCWEN BIT(3) -#define LM4_HIBCTL_HIBREQ BIT(1) -#define LM4_HIBCTL_RTCEN BIT(0) -#define LM4_HIBERNATE_HIBIM REG32(0x400fc014) -#define LM4_HIBERNATE_HIBRIS REG32(0x400fc018) -#define LM4_HIBERNATE_HIBMIS REG32(0x400fc01c) -#define LM4_HIBERNATE_HIBIC REG32(0x400fc020) -#define LM4_HIBERNATE_HIBRTCT REG32(0x400fc024) -#define LM4_HIBERNATE_HIBRTCSS REG32(0x400fc028) -#define LM4_HIBERNATE_HIBDATA_ENTRIES 16 /* Number of entries in HIBDATA[] */ -#define LM4_HIBERNATE_HIBDATA ((volatile uint32_t *)0x400fc030) - -#define LM4_FLASH_FMA REG32(0x400fd000) -#define LM4_FLASH_FMD REG32(0x400fd004) -#define LM4_FLASH_FMC REG32(0x400fd008) -#define LM4_FLASH_FCRIS REG32(0x400fd00c) -#define LM4_FLASH_FCMISC REG32(0x400fd014) -#define LM4_FLASH_FMC2 REG32(0x400fd020) -#define LM4_FLASH_FWBVAL REG32(0x400fd030) -/* FWB size is 32 words = 128 bytes */ -#define LM4_FLASH_FWB ((volatile uint32_t*)0x400fd100) -#define LM4_FLASH_FSIZE REG32(0x400fdfc0) -#define LM4_FLASH_FMPRE0 REG32(0x400fe200) -#define LM4_FLASH_FMPRE1 REG32(0x400fe204) -#define LM4_FLASH_FMPRE2 REG32(0x400fe208) -#define LM4_FLASH_FMPRE3 REG32(0x400fe20c) -#define LM4_FLASH_FMPPE ((volatile uint32_t*)0x400fe400) -#define LM4_FLASH_FMPPE0 REG32(0x400fe400) -#define LM4_FLASH_FMPPE1 REG32(0x400fe404) -#define LM4_FLASH_FMPPE2 REG32(0x400fe408) -#define LM4_FLASH_FMPPE3 REG32(0x400fe40c) - -#define LM4_SYSTEM_DID0 REG32(0x400fe000) -#define LM4_SYSTEM_DID1 REG32(0x400fe004) -#define LM4_SYSTEM_PBORCTL REG32(0x400fe030) -#define LM4_SYSTEM_RIS REG32(0x400fe050) -#define LM4_SYSTEM_MISC REG32(0x400fe058) -#define LM4_SYSTEM_RESC REG32(0x400fe05c) -#define LM4_SYSTEM_RCC REG32(0x400fe060) -#define LM4_SYSTEM_RCC_ACG BIT(27) -#define LM4_SYSTEM_RCC_SYSDIV(x) (((x) & 0xf) << 23) -#define LM4_SYSTEM_RCC_USESYSDIV BIT(22) -#define LM4_SYSTEM_RCC_PWRDN BIT(13) -#define LM4_SYSTEM_RCC_BYPASS BIT(11) -#define LM4_SYSTEM_RCC_XTAL(x) (((x) & 0x1f) << 6) -#define LM4_SYSTEM_RCC_OSCSRC(x) (((x) & 0x3) << 4) -#define LM4_SYSTEM_RCC_IOSCDIS BIT(1) -#define LM4_SYSTEM_RCC_MOSCDIS BIT(0) -#define LM4_SYSTEM_RCC2 REG32(0x400fe070) -#define LM4_SYSTEM_RCC2_USERCC2 BIT(31) -#define LM4_SYSTEM_RCC2_DIV400 BIT(30) -#define LM4_SYSTEM_RCC2_SYSDIV2(x) (((x) & 0x3f) << 23) -#define LM4_SYSTEM_RCC2_SYSDIV2LSB BIT(22) -#define LM4_SYSTEM_RCC2_PWRDN2 BIT(13) -#define LM4_SYSTEM_RCC2_BYPASS2 BIT(11) -#define LM4_SYSTEM_RCC2_OSCSRC2(x) (((x) & 0x7) << 4) -#define LM4_SYSTEM_MOSCCTL REG32(0x400fe07c) -#define LM4_SYSTEM_DSLPCLKCFG REG32(0x400fe144) -#define LM4_SYSTEM_PIOSCCAL REG32(0x400fe150) -#define LM4_SYSTEM_PIOSCSTAT REG32(0x400fe154) -#define LM4_SYSTEM_PLLSTAT REG32(0x400fe168) -#define LM4_SYSTEM_SLPPWRCFG REG32(0x400fe188) -#define LM4_SYSTEM_DSLPPWRCFG REG32(0x400fe18c) -#define LM4_SYSTEM_LDOSPCTL REG32(0x400fe1b4) -#define LM4_SYSTEM_LDOSPCAL REG32(0x400fe1b8) -#define LM4_SYSTEM_LDODPCTL REG32(0x400fe1bc) -#define LM4_SYSTEM_LDODPCAL REG32(0x400fe1c0) -#define LM4_SYSTEM_SPDMST REG32(0x400fe1cc) -#define LM4_SYSTEM_BOOTCFG REG32(0x400fe1d0) -#define LM4_SYSTEM_BOOTCFG_MASK 0x7fff00ec /* Reserved bits of BOOTCFG reg */ -/* Note: USER_REG3 is used to hold pre-programming process data and should not - * be modified by EC code. See crosbug.com/p/8889. */ -#define LM4_SYSTEM_USER_REG3 REG32(0x400fe1ec) -#define LM4_SYSTEM_SRI2C REG32(0x400fe520) -#define LM4_SYSTEM_SREEPROM REG32(0x400fe558) - -#define LM4_SYSTEM_SRI2C_ADDR ((uint32_t *)0x400fe520) - -#define LM4_SYSTEM_RCGC_BASE ((volatile uint32_t *)0x400fe600) -#define LM4_SYSTEM_RCGCGPIO REG32(0x400fe608) -#define LM4_SYSTEM_SCGC_BASE ((volatile uint32_t *)0x400fe700) -#define LM4_SYSTEM_DCGC_BASE ((volatile uint32_t *)0x400fe800) - -/* - * Offsets from CGC_BASE registers for each peripheral. - * Note: these are in units of 32-bit words offset from - * the base address. - */ -enum clock_gate_offsets { - CGC_OFFSET_WD = 0, - CGC_OFFSET_TIMER = 1, - CGC_OFFSET_GPIO = 2, - CGC_OFFSET_DMA = 3, - CGC_OFFSET_HIB = 5, - CGC_OFFSET_UART = 6, - CGC_OFFSET_SSI = 7, - CGC_OFFSET_I2C = 8, - CGC_OFFSET_ADC = 14, - CGC_OFFSET_LPC = 18, - CGC_OFFSET_PECI = 20, - CGC_OFFSET_FAN = 21, - CGC_OFFSET_EEPROM = 22, - CGC_OFFSET_WTIMER = 23, -}; - -#define LM4_SYSTEM_PREEPROM REG32(0x400fea58) - -#define LM4_DMA_DMACFG REG32(0x400ff004) -#define LM4_DMA_DMACTLBASE REG32(0x400ff008) -#define LM4_DMA_DMACHMAP0 REG32(0x400ff510) -#define LM4_DMA_DMACHMAP1 REG32(0x400ff514) -#define LM4_DMA_DMACHMAP2 REG32(0x400ff518) -#define LM4_DMA_DMACHMAP3 REG32(0x400ff51c) - -/* IRQ numbers */ -#define LM4_IRQ_GPIOA 0 -#define LM4_IRQ_GPIOB 1 -#define LM4_IRQ_GPIOC 2 -#define LM4_IRQ_GPIOD 3 -#define LM4_IRQ_GPIOE 4 -#define LM4_IRQ_UART0 5 -#define LM4_IRQ_UART1 6 -#define LM4_IRQ_SSI0 7 -#define LM4_IRQ_I2C0 8 -/* 9 - 13 reserved */ -#define LM4_IRQ_ADC0_SS0 14 -#define LM4_IRQ_ADC0_SS1 15 -#define LM4_IRQ_ADC0_SS2 16 -#define LM4_IRQ_ADC0_SS3 17 -#define LM4_IRQ_WATCHDOG 18 -#define LM4_IRQ_TIMER0A 19 -#define LM4_IRQ_TIMER0B 20 -#define LM4_IRQ_TIMER1A 21 -#define LM4_IRQ_TIMER1B 22 -#define LM4_IRQ_TIMER2A 23 -#define LM4_IRQ_TIMER2B 24 -#define LM4_IRQ_ACMP0 25 -#define LM4_IRQ_ACMP1 26 -#define LM4_IRQ_ACMP2 27 -#define LM4_IRQ_SYSCTRL 28 -#define LM4_IRQ_EEPROM 29 -#define LM4_IRQ_GPIOF 30 -#define LM4_IRQ_GPIOG 31 -#define LM4_IRQ_GPIOH 32 -#define LM4_IRQ_UART2 33 -#define LM4_IRQ_SSI1 34 -#define LM4_IRQ_TIMER3A 35 -#define LM4_IRQ_TIMER3B 36 -#define LM4_IRQ_I2C1 37 -/* 38 - 42 reserved */ -#define LM4_IRQ_HIBERNATE 43 -/* 44 - 45 reserved */ -#define LM4_IRQ_UDMA_SOFTWARE 46 -#define LM4_IRQ_UDMA_ERROR 47 -#define LM4_IRQ_ADC1_SS0 48 -#define LM4_IRQ_ADC1_SS1 49 -#define LM4_IRQ_ADC1_SS2 50 -#define LM4_IRQ_ADC1_SS3 51 -/* 52 - 53 reserved */ -#define LM4_IRQ_GPIOJ 54 -#define LM4_IRQ_GPIOK 55 -#define LM4_IRQ_GPIOL 56 -#define LM4_IRQ_SSI2 57 -#define LM4_IRQ_SSI3 58 -#define LM4_IRQ_UART3 59 -#define LM4_IRQ_UART4 60 -#define LM4_IRQ_UART5 61 -#define LM4_IRQ_UART6 62 -#define LM4_IRQ_UART7 63 -/* 64 - 67 reserved */ -#define LM4_IRQ_I2C2 68 -#define LM4_IRQ_I2C3 69 -#define LM4_IRQ_TIMER4A 70 -#define LM4_IRQ_TIMER4B 71 -/* 72 - 91 reserved */ -#define LM4_IRQ_TIMER5A 92 -#define LM4_IRQ_TIMER5B 93 -#define LM4_IRQ_TIMERW0A 94 -#define LM4_IRQ_TIMERW0B 95 -#define LM4_IRQ_TIMERW1A 96 -#define LM4_IRQ_TIMERW1B 97 -#define LM4_IRQ_TIMERW2A 98 -#define LM4_IRQ_TIMERW2B 99 -#define LM4_IRQ_TIMERW3A 100 -#define LM4_IRQ_TIMERW3B 101 -#define LM4_IRQ_TIMERW4A 102 -#define LM4_IRQ_TIMERW4B 103 -#define LM4_IRQ_TIMERW5A 104 -#define LM4_IRQ_TIMERW5B 105 -#define LM4_IRQ_SYS_EXCEPTION 106 -#define LM4_IRQ_SYS_PECI 107 -#define LM4_IRQ_LPC 108 -#define LM4_IRQ_I2C4 109 -#define LM4_IRQ_I2C5 110 -#define LM4_IRQ_GPIOM 111 -#define LM4_IRQ_GPION 112 -/* 113 reserved */ -#define LM4_IRQ_FAN 114 -/* 115 reserved */ -#define LM4_IRQ_GPIOP 116 -#define LM4_IRQ_GPIOP1 117 -#define LM4_IRQ_GPIOP2 118 -#define LM4_IRQ_GPIOP3 119 -#define LM4_IRQ_GPIOP4 120 -#define LM4_IRQ_GPIOP5 121 -#define LM4_IRQ_GPIOP6 122 -#define LM4_IRQ_GPIOP7 123 -#define LM4_IRQ_GPIOQ 124 -#define LM4_IRQ_GPIOQ1 125 -#define LM4_IRQ_GPIOQ2 126 -#define LM4_IRQ_GPIOQ3 127 -#define LM4_IRQ_GPIOQ4 128 -#define LM4_IRQ_GPIOQ5 129 -#define LM4_IRQ_GPIOQ6 130 -#define LM4_IRQ_GPIOQ7 131 -/* 132 - 138 reserved */ - -/* GPIO */ -#define LM4_GPIO_PORTA_BASE 0x40004000 -#define LM4_GPIO_PORTB_BASE 0x40005000 -#define LM4_GPIO_PORTC_BASE 0x40006000 -#define LM4_GPIO_PORTD_BASE 0x40007000 -#define LM4_GPIO_PORTE_BASE 0x40024000 -#define LM4_GPIO_PORTF_BASE 0x40025000 -#define LM4_GPIO_PORTG_BASE 0x40026000 -#define LM4_GPIO_PORTH_BASE 0x40027000 -#define LM4_GPIO_PORTJ_BASE 0x4003d000 -#define LM4_GPIO_PORTK_BASE 0x40061000 -#define LM4_GPIO_PORTL_BASE 0x40062000 -#define LM4_GPIO_PORTM_BASE 0x40063000 -#define LM4_GPIO_PORTN_BASE 0x40064000 -#define LM4_GPIO_PORTP_BASE 0x40065000 -#define LM4_GPIO_PORTQ_BASE 0x40066000 -#define LM4_GPIO_PORTA_AHB_BASE 0x40058000 -#define LM4_GPIO_PORTB_AHB_BASE 0x40059000 -#define LM4_GPIO_PORTC_AHB_BASE 0x4005a000 -#define LM4_GPIO_PORTD_AHB_BASE 0x4005b000 -#define LM4_GPIO_PORTE_AHB_BASE 0x4005c000 -#define LM4_GPIO_PORTF_AHB_BASE 0x4005d000 -#define LM4_GPIO_PORTG_AHB_BASE 0x4005e000 -#define LM4_GPIO_PORTH_AHB_BASE 0x4005f000 -#define LM4_GPIO_PORTJ_AHB_BASE 0x40060000 -/* Ports for passing to LM4GPIOREG(); abstracted from base addresses above so - * that we can switch to/from AHB. */ -#define LM4_GPIO_A LM4_GPIO_PORTA_BASE -#define LM4_GPIO_B LM4_GPIO_PORTB_BASE -#define LM4_GPIO_C LM4_GPIO_PORTC_BASE -#define LM4_GPIO_D LM4_GPIO_PORTD_BASE -#define LM4_GPIO_E LM4_GPIO_PORTE_BASE -#define LM4_GPIO_F LM4_GPIO_PORTF_BASE -#define LM4_GPIO_G LM4_GPIO_PORTG_BASE -#define LM4_GPIO_H LM4_GPIO_PORTH_BASE -#define LM4_GPIO_J LM4_GPIO_PORTJ_BASE -#define LM4_GPIO_K LM4_GPIO_PORTK_BASE -#define LM4_GPIO_L LM4_GPIO_PORTL_BASE -#define LM4_GPIO_M LM4_GPIO_PORTM_BASE -#define LM4_GPIO_N LM4_GPIO_PORTN_BASE -#define LM4_GPIO_P LM4_GPIO_PORTP_BASE -#define LM4_GPIO_Q LM4_GPIO_PORTQ_BASE -#define LM4GPIOREG(port, offset) REG32((port) + (offset)) -#define LM4_GPIO_DATA(port, mask) LM4GPIOREG(port, ((mask) << 2)) -#define LM4_GPIO_DIR(port) LM4GPIOREG(port, 0x400) -#define LM4_GPIO_IS(port) LM4GPIOREG(port, 0x404) -#define LM4_GPIO_IBE(port) LM4GPIOREG(port, 0x408) -#define LM4_GPIO_IEV(port) LM4GPIOREG(port, 0x40c) -#define LM4_GPIO_IM(port) LM4GPIOREG(port, 0x410) -#define LM4_GPIO_RIS(port) LM4GPIOREG(port, 0x414) -#define LM4_GPIO_MIS(port) LM4GPIOREG(port, 0x418) -#define LM4_GPIO_ICR(port) LM4GPIOREG(port, 0x41c) -#define LM4_GPIO_AFSEL(port) LM4GPIOREG(port, 0x420) -#define LM4_GPIO_DR2R(port) LM4GPIOREG(port, 0x500) -#define LM4_GPIO_DR4R(port) LM4GPIOREG(port, 0x504) -#define LM4_GPIO_DR8R(port) LM4GPIOREG(port, 0x508) -#define LM4_GPIO_ODR(port) LM4GPIOREG(port, 0x50c) -#define LM4_GPIO_PUR(port) LM4GPIOREG(port, 0x510) -#define LM4_GPIO_PDR(port) LM4GPIOREG(port, 0x514) -#define LM4_GPIO_SLR(port) LM4GPIOREG(port, 0x518) -#define LM4_GPIO_DEN(port) LM4GPIOREG(port, 0x51c) -#define LM4_GPIO_LOCK(port) LM4GPIOREG(port, 0x520) -#define LM4_GPIO_CR(port) LM4GPIOREG(port, 0x524) -#define LM4_GPIO_AMSEL(port) LM4GPIOREG(port, 0x528) -#define LM4_GPIO_PCTL(port) LM4GPIOREG(port, 0x52c) - -/* Chip-independent aliases for port base addresses */ -#define GPIO_A LM4_GPIO_A -#define GPIO_B LM4_GPIO_B -#define GPIO_C LM4_GPIO_C -#define GPIO_D LM4_GPIO_D -#define GPIO_E LM4_GPIO_E -#define GPIO_F LM4_GPIO_F -#define GPIO_G LM4_GPIO_G -#define GPIO_H LM4_GPIO_H -#define GPIO_J LM4_GPIO_J -#define GPIO_K LM4_GPIO_K -#define GPIO_L LM4_GPIO_L -#define GPIO_M LM4_GPIO_M -#define GPIO_N LM4_GPIO_N -#define GPIO_P LM4_GPIO_P -#define GPIO_Q LM4_GPIO_Q - -#define UNIMPLEMENTED_GPIO_BANK GPIO_A - -/* Value to write to LM4_GPIO_LOCK to unlock writes */ -#define LM4_GPIO_LOCK_UNLOCK 0x4c4f434b - -/* I2C */ -#define LM4_I2C0_BASE 0x40020000 -#define LM4_I2C1_BASE 0x40021000 -#define LM4_I2C2_BASE 0x40022000 -#define LM4_I2C3_BASE 0x40023000 -#define LM4_I2C4_BASE 0x400c0000 -#define LM4_I2C5_BASE 0x400c1000 -#define LM4_I2C_BASESEP 0x00001000 -/* I2C base address by port. Compiles to a constant in gcc if port - and offset are constant. */ -static inline int lm4_i2c_addr(int port, int offset) -{ - return offset + (port < 4 ? - LM4_I2C0_BASE + LM4_I2C_BASESEP * port : - LM4_I2C4_BASE + LM4_I2C_BASESEP * (port - 4)); -} -#define LM4I2CREG(port, offset) REG32(lm4_i2c_addr(port, offset)) -#define LM4_I2C_MSA(port) LM4I2CREG(port, 0x000) -#define LM4_I2C_MCS(port) LM4I2CREG(port, 0x004) -#define LM4_I2C_MDR(port) LM4I2CREG(port, 0x008) -#define LM4_I2C_MTPR(port) LM4I2CREG(port, 0x00c) -#define LM4_I2C_MIMR(port) LM4I2CREG(port, 0x010) -#define LM4_I2C_MRIS(port) LM4I2CREG(port, 0x014) -#define LM4_I2C_MMIS(port) LM4I2CREG(port, 0x018) -#define LM4_I2C_MICR(port) LM4I2CREG(port, 0x01c) -#define LM4_I2C_MCR(port) LM4I2CREG(port, 0x020) -#define LM4_I2C_MCLKOCNT(port) LM4I2CREG(port, 0x024) -#define LM4_I2C_MBMON(port) LM4I2CREG(port, 0x02c) - - -/* Timers */ -/* Timers 0-5 are 16/32 bit */ -#define LM4_TIMER0_BASE 0x40030000 -#define LM4_TIMER1_BASE 0x40031000 -#define LM4_TIMER2_BASE 0x40032000 -#define LM4_TIMER3_BASE 0x40033000 -#define LM4_TIMER4_BASE 0x40034000 -#define LM4_TIMER5_BASE 0x40035000 -/* Timers 6-11 are 32/64 bit */ -#define LM4_TIMERW0_BASE 0x40036000 -#define LM4_TIMERW1_BASE 0x40037000 -#define LM4_TIMERW2_BASE 0x4004c000 -#define LM4_TIMERW3_BASE 0x4004d000 -#define LM4_TIMERW4_BASE 0x4004e000 -#define LM4_TIMERW5_BASE 0x4004f000 -#define LM4_TIMER_SEP 0x00001000 -static inline int lm4_timer_addr(int timer, int offset) -{ - if (timer < 8) - return offset + LM4_TIMER0_BASE + LM4_TIMER_SEP * timer; - else - return offset + LM4_TIMERW2_BASE + LM4_TIMER_SEP * (timer - 8); -} -#define LM4TIMERREG(timer, offset) REG32(lm4_timer_addr(timer, offset)) -#define LM4_TIMER_CFG(tmr) LM4TIMERREG(tmr, 0x00) -#define LM4_TIMER_TAMR(tmr) LM4TIMERREG(tmr, 0x04) -#define LM4_TIMER_TBMR(tmr) LM4TIMERREG(tmr, 0x08) -#define LM4_TIMER_CTL(tmr) LM4TIMERREG(tmr, 0x0c) -#define LM4_TIMER_SYNC(tmr) LM4TIMERREG(tmr, 0x10) -#define LM4_TIMER_IMR(tmr) LM4TIMERREG(tmr, 0x18) -#define LM4_TIMER_RIS(tmr) LM4TIMERREG(tmr, 0x1c) -#define LM4_TIMER_MIS(tmr) LM4TIMERREG(tmr, 0x20) -#define LM4_TIMER_ICR(tmr) LM4TIMERREG(tmr, 0x24) -#define LM4_TIMER_TAILR(tmr) LM4TIMERREG(tmr, 0x28) -#define LM4_TIMER_TBILR(tmr) LM4TIMERREG(tmr, 0x2c) -#define LM4_TIMER_TAMATCHR(tmr) LM4TIMERREG(tmr, 0x30) -#define LM4_TIMER_TBMATCHR(tmr) LM4TIMERREG(tmr, 0x34) -#define LM4_TIMER_TAPR(tmr) LM4TIMERREG(tmr, 0x38) -#define LM4_TIMER_TBPR(tmr) LM4TIMERREG(tmr, 0x3c) -#define LM4_TIMER_TAPMR(tmr) LM4TIMERREG(tmr, 0x40) -#define LM4_TIMER_TBPMR(tmr) LM4TIMERREG(tmr, 0x44) -#define LM4_TIMER_TAR(tmr) LM4TIMERREG(tmr, 0x48) -#define LM4_TIMER_TBR(tmr) LM4TIMERREG(tmr, 0x4c) -#define LM4_TIMER_TAV(tmr) LM4TIMERREG(tmr, 0x50) -#define LM4_TIMER_TBV(tmr) LM4TIMERREG(tmr, 0x54) -#define LM4_TIMER_RTCPD(tmr) LM4TIMERREG(tmr, 0x58) -#define LM4_TIMER_TAPS(tmr) LM4TIMERREG(tmr, 0x5c) -#define LM4_TIMER_TBPS(tmr) LM4TIMERREG(tmr, 0x60) -#define LM4_TIMER_TAPV(tmr) LM4TIMERREG(tmr, 0x64) -#define LM4_TIMER_TBPV(tmr) LM4TIMERREG(tmr, 0x68) - -#define LM4_SYSTICK_CTRL REG32(0xe000e010) -#define LM4_SYSTICK_RELOAD REG32(0xe000e014) -#define LM4_SYSTICK_CURRENT REG32(0xe000e018) - -/* Watchdogs */ -#define LM4_WATCHDOG0_BASE 0x40000000 -#define LM4_WATCHDOG1_BASE 0x40001000 -static inline int lm4_watchdog_addr(int num, int offset) -{ - return offset + (num ? LM4_WATCHDOG1_BASE : LM4_WATCHDOG0_BASE); -} -#define LM4WDTREG(num, offset) REG32(lm4_watchdog_addr(num, offset)) -#define LM4_WATCHDOG_LOAD(n) LM4WDTREG(n, 0x000) -#define LM4_WATCHDOG_VALUE(n) LM4WDTREG(n, 0x004) -#define LM4_WATCHDOG_CTL(n) LM4WDTREG(n, 0x008) -#define LM4_WATCHDOG_ICR(n) LM4WDTREG(n, 0x00c) -#define LM4_WATCHDOG_RIS(n) LM4WDTREG(n, 0x010) -#define LM4_WATCHDOG_TEST(n) LM4WDTREG(n, 0x418) -#define LM4_WATCHDOG_LOCK(n) LM4WDTREG(n, 0xc00) - -#define LM4_TEST_MODE_ENABLED REG32(0x400fdff0) - -#endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/lm4/spi.c b/chip/lm4/spi.c deleted file mode 100644 index be988b78a0..0000000000 --- a/chip/lm4/spi.c +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* SPI module for Chrome EC */ - -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "spi.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) - - -int spi_enable(int port, int enable) -{ - int i; - - if (enable) { - gpio_config_module(MODULE_SPI, 1); - for (i = 0; i < spi_devices_used; i++) { - if (spi_devices[i].port != port) - continue; - /* - * Don't use the SSI0 frame output. - * CS# is a GPIO so we can keep it low during an entire - * transaction. - */ - gpio_set_flags(spi_device[i]->gpio_cs, GPIO_OUTPUT); - gpio_set_level(spi_device[i]->gpio_cs, 1); - } - - /* Enable SSI port */ - LM4_SSI_CR1(0) |= 0x02; - } else { - /* Disable SSI port */ - LM4_SSI_CR1(0) &= ~0x02; - - for (i = 0; i < spi_devices_used; i++) { - if (spi_devices[i].port != port) - continue; - /* Make sure CS# is deselected */ - gpio_set_level(spi_device[i]->gpio_cs, 1); - gpio_set_flags(spi_device->gpio_cs[i], GPIO_ODR_HIGH); - } - - gpio_config_module(MODULE_SPI, 0); - } - - return EC_SUCCESS; -} - - -int spi_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - int totallen = txlen + rxlen; - int txcount = 0, rxcount = 0; - static struct mutex spi_mutex; - volatile uint32_t unused __attribute__((unused)); - - mutex_lock(&spi_mutex); - /* Empty the receive FIFO */ - while (LM4_SSI_SR(0) & LM4_SSI_SR_RNE) - unused = LM4_SSI_DR(0); - - /* Start transaction. Need to do this explicitly because the LM4 - * SSI controller pulses its frame select every byte, and the EEPROM - * wants the chip select held low during the entire transaction. */ - gpio_set_level(spi_device->gpio_cs, 0); - - while (rxcount < totallen) { - /* Handle received bytes if any. We just checked rxcount < - * totallen, so we don't need to worry about overflowing the - * receive buffer. */ - if (LM4_SSI_SR(0) & LM4_SSI_SR_RNE) { - if (rxcount < txlen) { - /* Throw away bytes received while we were - transmitting */ - unused = LM4_SSI_DR(0); - } else - *(rxdata++) = LM4_SSI_DR(0); - rxcount++; - } - - /* Transmit another byte if needed */ - if ((LM4_SSI_SR(0) & LM4_SSI_SR_TNF) && txcount < totallen) { - if (txcount < txlen) - LM4_SSI_DR(0) = *(txdata++); - else { - /* Clock out unused byte so we can clock in the - * response byte */ - LM4_SSI_DR(0) = 0; - } - txcount++; - } - } - - /* End transaction */ - gpio_set_level(spi_device->gpio_cs, 1); - mutex_unlock(&spi_mutex); - - return EC_SUCCESS; -} - -/*****************************************************************************/ -/* Hooks */ - -static int spi_init(void) -{ - /* Enable the SPI module in run and sleep modes */ - clock_enable_peripheral(CGC_OFFSET_SSI, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - LM4_SSI_CR1(0) = 0; /* Disable SSI */ - LM4_SSI_CR0(0) = 0x0007; /* SCR=0, SPH=0, SPO=0, FRF=SPI, 8-bit */ - - /* Use PIOSC for clock. This limits us to 8MHz (PIOSC/2), but is - * simpler to configure and we don't need to worry about clock - * frequency changing when the PLL is disabled. If we really start - * using this, might be worth using the system clock and handling - * frequency change (like we do with PECI) so we can go faster. */ - LM4_SSI_CC(0) = 1; - /* SSICLK = PIOSC / (CPSDVSR * (1 + SCR) - * = 16 MHz / (2 * (1 + 0)) - * = 8 MHz */ - LM4_SSI_CPSR(0) = 2; - - /* Ensure the SPI port is disabled. This keeps us from interfering - * with the main chipset when we're not explicitly using the SPI - * bus. */ - spi_enable(CONFIG_SPI_FLASH_PORT, 0); - - return EC_SUCCESS; -} -DECLARE_HOOK(HOOK_INIT, spi_init, HOOK_PRIO_INIT_SPI); - -/*****************************************************************************/ -/* Console commands */ - -static int printrx(const char *desc, const uint8_t *txdata, int txlen, - int rxlen) -{ - uint8_t rxdata[32]; - int rv; - int i; - - rv = spi_transaction(SPI_FLASH_DEVICE, txdata, txlen, rxdata, rxlen); - if (rv) - return rv; - - ccprintf("%-12s:", desc); - for (i = 0; i < rxlen; i++) - ccprintf(" 0x%02x", rxdata[i]); - ccputs("\n"); - return EC_SUCCESS; -} - - -static int command_spirom(int argc, char **argv) -{ - uint8_t txmandev[] = {0x90, 0x00, 0x00, 0x00}; - uint8_t txjedec[] = {0x9f}; - uint8_t txunique[] = {0x4b, 0x00, 0x00, 0x00, 0x00}; - uint8_t txsr1[] = {0x05}; - uint8_t txsr2[] = {0x35}; - - spi_enable(CONFIG_SPI_FLASH_PORT, 1); - - printrx("Man/Dev ID", txmandev, sizeof(txmandev), 2); - printrx("JEDEC ID", txjedec, sizeof(txjedec), 3); - printrx("Unique ID", txunique, sizeof(txunique), 8); - printrx("Status reg 1", txsr1, sizeof(txsr1), 1); - printrx("Status reg 2", txsr2, sizeof(txsr2), 1); - - spi_enable(CONFIG_SPI_FLASH_PORT, 0); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(spirom, command_spirom, - NULL, - "Test reading SPI EEPROM"); diff --git a/chip/lm4/system.c b/chip/lm4/system.c deleted file mode 100644 index 75e7d556ec..0000000000 --- a/chip/lm4/system.c +++ /dev/null @@ -1,767 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* System module for Chrome EC : LM4 hardware specific implementation */ - -#include "clock.h" -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "host_command.h" -#include "panic.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Indices for hibernate data registers */ -enum hibdata_index { - HIBDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */ - HIBDATA_INDEX_WAKE, /* Wake reasons for hibernate */ - HIBDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */ -#ifdef CONFIG_SOFTWARE_PANIC - HIBDATA_INDEX_SAVED_PANIC_REASON, /* Saved panic reason */ - HIBDATA_INDEX_SAVED_PANIC_INFO, /* Saved panic data */ - HIBDATA_INDEX_SAVED_PANIC_EXCEPTION /* Saved panic exception code */ -#endif -}; - -/* Flags for HIBDATA_INDEX_WAKE */ -#define HIBDATA_WAKE_RTC BIT(0) /* RTC alarm */ -#define HIBDATA_WAKE_HARD_RESET BIT(1) /* Hard reset via short RTC alarm */ -#define HIBDATA_WAKE_PIN BIT(2) /* Wake pin */ - -/* - * Time to hibernate to trigger a power-on reset. 50 ms is sufficient for the - * EC itself, but we need a longer delay to ensure the rest of the components - * on the same power rail are reset and 5VALW has dropped. - */ -#define HIB_RESET_USEC 1000000 - -/* - * Convert between microseconds and the hibernation module RTC subsecond - * register which has 15-bit resolution. Divide down both numerator and - * denominator to avoid integer overflow while keeping the math accurate. - */ -#define HIB_RTC_USEC_TO_SUBSEC(us) ((us) * (32768/64) / (1000000/64)) -#define HIB_RTC_SUBSEC_TO_USEC(ss) ((ss) * (1000000/64) / (32768/64)) - -/** - * Wait for a write to commit to a hibernate register. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -static int wait_for_hibctl_wc(void) -{ - int i; - - /* Wait for write-capable */ - for (i = 0; i < 1000000; i++) { - if (LM4_HIBERNATE_HIBCTL & LM4_HIBCTL_WRC) - return EC_SUCCESS; - } - return EC_ERROR_TIMEOUT; -} - -/** - * Read hibernate register at specified index. - * - * @return The value of the register or 0 if invalid index. - */ -static uint32_t hibdata_read(enum hibdata_index index) -{ - if (index < 0 || index >= LM4_HIBERNATE_HIBDATA_ENTRIES) - return 0; - - return LM4_HIBERNATE_HIBDATA[index]; -} - -/** - * Write hibernate register at specified index. - * - * @return nonzero if error. - */ -static int hibdata_write(enum hibdata_index index, uint32_t value) -{ - int rv; - - if (index < 0 || index >= LM4_HIBERNATE_HIBDATA_ENTRIES) - return EC_ERROR_INVAL; - - /* Wait for ok-to-write */ - rv = wait_for_hibctl_wc(); - if (rv != EC_SUCCESS) - return rv; - - /* Write register */ - LM4_HIBERNATE_HIBDATA[index] = value; - - /* Wait for write-complete */ - return wait_for_hibctl_wc(); -} - -uint32_t chip_read_reset_flags(void) -{ - return hibdata_read(HIBDATA_INDEX_SAVED_RESET_FLAGS); -} - -void chip_save_reset_flags(uint32_t flags) -{ - hibdata_write(HIBDATA_INDEX_SAVED_RESET_FLAGS, flags); -} - -static void check_reset_cause(void) -{ - uint32_t hib_status = LM4_HIBERNATE_HIBRIS; - uint32_t raw_reset_cause = LM4_SYSTEM_RESC; - uint32_t hib_wake_flags = hibdata_read(HIBDATA_INDEX_WAKE); - uint32_t flags = 0; - - /* Clear the reset causes now that we've read them */ - LM4_SYSTEM_RESC = 0; - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIC = hib_status; - hibdata_write(HIBDATA_INDEX_WAKE, 0); - - if (raw_reset_cause & 0x02) { - /* - * Full power-on reset of chip. This resets the flash - * protection registers to their permanently-stored values. - * Note that this is also triggered by hibernation, because - * that de-powers the chip. - */ - flags |= EC_RESET_FLAG_POWER_ON; - } else if (!flags && (raw_reset_cause & 0x01)) { - /* - * LM4 signals the reset pin in RESC for all power-on resets, - * even though the external pin wasn't asserted. Make setting - * this flag mutually-exclusive with power on flag, so we can - * use it to indicate a keyboard-triggered reset. - */ - flags |= EC_RESET_FLAG_RESET_PIN; - } - - if (raw_reset_cause & 0x04) - flags |= EC_RESET_FLAG_BROWNOUT; - - if (raw_reset_cause & 0x10) - flags |= EC_RESET_FLAG_SOFT; - - if (raw_reset_cause & 0x28) { - /* Watchdog timer 0 or 1 */ - flags |= EC_RESET_FLAG_WATCHDOG; - } - - /* Handle other raw reset causes */ - if (raw_reset_cause && !flags) - flags |= EC_RESET_FLAG_OTHER; - - - if ((hib_status & 0x09) && - (hib_wake_flags & HIBDATA_WAKE_HARD_RESET)) { - /* Hibernation caused by software-triggered hard reset */ - flags |= EC_RESET_FLAG_HARD; - - /* Consume the hibernate reasons so we don't see them below */ - hib_status &= ~0x09; - } - - if ((hib_status & 0x01) && (hib_wake_flags & HIBDATA_WAKE_RTC)) - flags |= EC_RESET_FLAG_RTC_ALARM; - - if ((hib_status & 0x08) && (hib_wake_flags & HIBDATA_WAKE_PIN)) - flags |= EC_RESET_FLAG_WAKE_PIN; - - if (hib_status & 0x04) - flags |= EC_RESET_FLAG_LOW_BATTERY; - - /* Restore then clear saved reset flags */ - flags |= chip_read_reset_flags(); - chip_save_reset_flags(0); - - system_set_reset_flags(flags); -} - -/* - * A3 and earlier chip stepping has a problem accessing flash during shutdown. - * To work around that, we jump to RAM before hibernating. This function must - * live in RAM. It must be called with interrupts disabled, cannot call other - * functions, and can't be declared static (or else the compiler optimizes it - * into the main hibernate function. - */ -void __attribute__((noinline)) __attribute__((section(".iram.text"))) -__enter_hibernate(int hibctl) -{ - LM4_HIBERNATE_HIBCTL = hibctl; - while (1) - ; -} - -/** - * Read the real-time clock. - * - * @param ss_ptr Destination for sub-seconds value, if not null. - * - * @return the real-time clock seconds value. - */ -uint32_t system_get_rtc_sec_subsec(uint32_t *ss_ptr) -{ - uint32_t rtc, rtc2; - uint32_t rtcss, rtcss2; - - /* - * The hibernate module isn't synchronized, so need to read repeatedly - * to guarantee a valid read. - */ - do { - rtc = LM4_HIBERNATE_HIBRTCC; - rtcss = LM4_HIBERNATE_HIBRTCSS & 0x7fff; - rtcss2 = LM4_HIBERNATE_HIBRTCSS & 0x7fff; - rtc2 = LM4_HIBERNATE_HIBRTCC; - } while (rtc != rtc2 || rtcss != rtcss2); - - if (ss_ptr) - *ss_ptr = rtcss; - - return rtc; -} - -timestamp_t system_get_rtc(void) -{ - uint32_t rtc, rtc_ss; - timestamp_t time; - - rtc = system_get_rtc_sec_subsec(&rtc_ss); - - time.val = ((uint64_t)rtc) * SECOND + HIB_RTC_SUBSEC_TO_USEC(rtc_ss); - return time; -} - -/** - * Set the real-time clock. - * - * @param seconds New clock value. - */ -void system_set_rtc(uint32_t seconds) -{ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBRTCLD = seconds; - wait_for_hibctl_wc(); -} - -/** - * Set the hibernate RTC match time at a given time from now - * - * @param seconds Number of seconds from now for RTC match - * @param microseconds Number of microseconds from now for RTC match - */ -static void set_hibernate_rtc_match_time(uint32_t seconds, - uint32_t microseconds) -{ - uint32_t rtc, rtcss; - - /* - * Make sure that the requested delay is not less then the - * amount of time it takes to set the RTC match registers, - * otherwise, the match event could be missed. - */ - if (seconds == 0 && microseconds < HIB_SET_RTC_MATCH_DELAY_USEC) - microseconds = HIB_SET_RTC_MATCH_DELAY_USEC; - - /* Calculate the wake match */ - rtc = system_get_rtc_sec_subsec(&rtcss) + seconds; - rtcss += HIB_RTC_USEC_TO_SUBSEC(microseconds); - if (rtcss > 0x7fff) { - rtc += rtcss >> 15; - rtcss &= 0x7fff; - } - - /* Set RTC alarm match */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBRTCM0 = rtc; - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBRTCSS = rtcss << 16; - wait_for_hibctl_wc(); -} - -/** - * Use hibernate module to set up an RTC interrupt at a given - * time from now - * - * @param seconds Number of seconds before RTC interrupt - * @param microseconds Number of microseconds before RTC interrupt - */ -void system_set_rtc_alarm(uint32_t seconds, uint32_t microseconds) -{ - /* Clear pending interrupt */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIC = LM4_HIBERNATE_HIBRIS; - - /* Set match time */ - set_hibernate_rtc_match_time(seconds, microseconds); - - /* Enable RTC interrupt on match */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIM = 1; - - /* - * Wait for the write to commit. This ensures that the RTC interrupt - * actually gets enabled. This is important if we're about to switch - * the system to the 30 kHz oscillator, which might prevent the write - * from committing. - */ - wait_for_hibctl_wc(); -} - -/** - * Disable and clear the RTC interrupt. - */ -void system_reset_rtc_alarm(void) -{ - /* Disable hibernate interrupts */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIM = 0; - - /* Clear interrupts */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIC = LM4_HIBERNATE_HIBRIS; -} - -/** - * Hibernate module interrupt - */ -void __hibernate_irq(void) -{ - system_reset_rtc_alarm(); -} -DECLARE_IRQ(LM4_IRQ_HIBERNATE, __hibernate_irq, 1); - -/** - * Enable hibernate interrupt - */ -void system_enable_hib_interrupt(void) -{ - task_enable_irq(LM4_IRQ_HIBERNATE); -} - -/** - * Internal hibernate function. - * - * @param seconds Number of seconds to sleep before RTC alarm - * @param microseconds Number of microseconds to sleep before RTC alarm - * @param flags Additional hibernate wake flags - */ -static void hibernate(uint32_t seconds, uint32_t microseconds, uint32_t flags) -{ - uint32_t hibctl; - - /* Set up wake reasons and hibernate flags */ - hibctl = LM4_HIBERNATE_HIBCTL | LM4_HIBCTL_PINWEN; - - if (flags & HIBDATA_WAKE_PIN) - hibctl |= LM4_HIBCTL_PINWEN; - else - hibctl &= ~LM4_HIBCTL_PINWEN; - - if (seconds || microseconds) { - hibctl |= LM4_HIBCTL_RTCWEN; - flags |= HIBDATA_WAKE_RTC; - - set_hibernate_rtc_match_time(seconds, microseconds); - - /* Enable RTC interrupt on match */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIM = 1; - } else { - hibctl &= ~LM4_HIBCTL_RTCWEN; - } - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBCTL = hibctl; - - /* Clear pending interrupt */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIC = LM4_HIBERNATE_HIBRIS; - - /* Store hibernate flags */ - hibdata_write(HIBDATA_INDEX_WAKE, flags); - - __enter_hibernate(hibctl | LM4_HIBCTL_HIBREQ); -} - -void system_hibernate(uint32_t seconds, uint32_t microseconds) -{ - /* Flush console before hibernating */ - cflush(); - hibernate(seconds, microseconds, HIBDATA_WAKE_PIN); -} - -void chip_pre_init(void) -{ - /* Enable clocks to GPIO block C in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_GPIO, 0x0004, CGC_MODE_ALL); - - /* - * Ensure PC0:3 are set to JTAG function. They should be set this way - * on a cold boot, but on a warm reboot a previous misbehaving image - * could have set them differently. - */ - if (((LM4_GPIO_PCTL(LM4_GPIO_C) & 0x0000ffff) == 0x00001111) && - ((LM4_GPIO_AFSEL(LM4_GPIO_C) & 0x0f) == 0x0f) && - ((LM4_GPIO_DEN(LM4_GPIO_C) & 0x0f) == 0x0f) && - ((LM4_GPIO_PUR(LM4_GPIO_C) & 0x0f) == 0x0f)) - return; /* Already properly configured */ - - /* Unlock commit register for JTAG pins */ - LM4_GPIO_LOCK(LM4_GPIO_C) = LM4_GPIO_LOCK_UNLOCK; - LM4_GPIO_CR(LM4_GPIO_C) |= 0x0f; - - /* Reset JTAG pins */ - LM4_GPIO_PCTL(LM4_GPIO_C) = - (LM4_GPIO_PCTL(LM4_GPIO_C) & 0xffff0000) | 0x00001111; - LM4_GPIO_AFSEL(LM4_GPIO_C) |= 0x0f; - LM4_GPIO_DEN(LM4_GPIO_C) |= 0x0f; - LM4_GPIO_PUR(LM4_GPIO_C) |= 0x0f; - - /* Set interrupt on either edge of the JTAG signals */ - LM4_GPIO_IS(LM4_GPIO_C) &= ~0x0f; - LM4_GPIO_IBE(LM4_GPIO_C) |= 0x0f; - - /* Re-lock commit register */ - LM4_GPIO_CR(LM4_GPIO_C) &= ~0x0f; - LM4_GPIO_LOCK(LM4_GPIO_C) = 0; -} - -void system_pre_init(void) -{ - uint32_t hibctl; -#ifdef CONFIG_SOFTWARE_PANIC - uint32_t reason, info; - uint8_t exception; -#endif - - /* - * Enable clocks to the hibernation module in run, sleep, - * and deep sleep modes. - */ - clock_enable_peripheral(CGC_OFFSET_HIB, 0x1, CGC_MODE_ALL); - - /* - * Enable the hibernation oscillator, if it's not already enabled. - * This should only need setting if the EC completely lost power (for - * example, the battery was pulled). - */ - if (!(LM4_HIBERNATE_HIBCTL & LM4_HIBCTL_CLK32EN)) { - int i; - - /* Enable clock to hibernate module */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBCTL |= LM4_HIBCTL_CLK32EN; - - /* Wait for write-complete */ - for (i = 0; i < 1000000; i++) { - if (LM4_HIBERNATE_HIBRIS & 0x10) - break; - } - - /* Enable and reset RTC */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBCTL |= LM4_HIBCTL_RTCEN; - system_set_rtc(0); - - /* Clear all hibernate data entries */ - for (i = 0; i < LM4_HIBERNATE_HIBDATA_ENTRIES; i++) - hibdata_write(i, 0); - } - - /* - * Set wake reasons to RTC match and WAKE pin by default. - * Before going in to hibernate, these may change. - */ - hibctl = LM4_HIBERNATE_HIBCTL; - hibctl |= LM4_HIBCTL_RTCWEN; - hibctl |= LM4_HIBCTL_PINWEN; - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBCTL = hibctl; - - /* - * Initialize registers after reset to work around LM4 chip errata - * (still present in A3 chip stepping). - */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBRTCT = 0x7fff; - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIM = 0; - - check_reset_cause(); - -#ifdef CONFIG_SOFTWARE_PANIC - /* Restore then clear saved panic reason */ - reason = hibdata_read(HIBDATA_INDEX_SAVED_PANIC_REASON); - info = hibdata_read(HIBDATA_INDEX_SAVED_PANIC_INFO); - exception = hibdata_read(HIBDATA_INDEX_SAVED_PANIC_EXCEPTION); - if (reason || info || exception) { - panic_set_reason(reason, info, exception); - hibdata_write(HIBDATA_INDEX_SAVED_PANIC_REASON, 0); - hibdata_write(HIBDATA_INDEX_SAVED_PANIC_INFO, 0); - hibdata_write(HIBDATA_INDEX_SAVED_PANIC_EXCEPTION, 0); - } -#endif - - /* Initialize bootcfg if needed */ - if (LM4_SYSTEM_BOOTCFG != CONFIG_BOOTCFG_VALUE) { - /* read-modify-write */ - LM4_FLASH_FMD = (LM4_SYSTEM_BOOTCFG_MASK & LM4_SYSTEM_BOOTCFG) - | (~LM4_SYSTEM_BOOTCFG_MASK & CONFIG_BOOTCFG_VALUE); - LM4_FLASH_FMA = 0x75100000; - LM4_FLASH_FMC = 0xa4420008; /* WRKEY | COMT */ - while (LM4_FLASH_FMC & 0x08) - ; - } - - /* Brown-outs should trigger a reset */ - LM4_SYSTEM_PBORCTL |= 0x02; -} - -void system_reset(int flags) -{ - uint32_t save_flags = 0; - - /* Disable interrupts to avoid task swaps during reboot */ - interrupt_disable(); - - /* Save current reset reasons if necessary */ - if (flags & SYSTEM_RESET_PRESERVE_FLAGS) - save_flags = system_get_reset_flags() | EC_RESET_FLAG_PRESERVED; - - if (flags & SYSTEM_RESET_LEAVE_AP_OFF) - save_flags |= EC_RESET_FLAG_AP_OFF; - - chip_save_reset_flags(save_flags); - - if (flags & SYSTEM_RESET_HARD) { -#ifdef CONFIG_SOFTWARE_PANIC - uint32_t reason, info; - uint8_t exception; - - /* Panic data will be wiped by hard reset, so save it */ - panic_get_reason(&reason, &info, &exception); - hibdata_write(HIBDATA_INDEX_SAVED_PANIC_REASON, reason); - hibdata_write(HIBDATA_INDEX_SAVED_PANIC_INFO, info); - hibdata_write(HIBDATA_INDEX_SAVED_PANIC_EXCEPTION, exception); -#endif - - /* - * Bounce through hibernate to trigger a hard reboot. Do - * not wake on wake pin, since we need the full duration. - */ - hibernate(0, HIB_RESET_USEC, HIBDATA_WAKE_HARD_RESET); - } else - CPU_NVIC_APINT = 0x05fa0004; - - /* Spin and wait for reboot; should never return */ - while (1) - ; -} - -int system_set_scratchpad(uint32_t value) -{ - return hibdata_write(HIBDATA_INDEX_SCRATCHPAD, value); -} - -uint32_t system_get_scratchpad(void) -{ - return hibdata_read(HIBDATA_INDEX_SCRATCHPAD); -} - -const char *system_get_chip_vendor(void) -{ - return "ti"; -} - -static char to_hex(int x) -{ - if (x >= 0 && x <= 9) - return '0' + x; - return 'a' + x - 10; -} - -const char *system_get_chip_id_string(void) -{ - static char str[15] = "Unknown-"; - char *p = str + 8; - uint32_t did = LM4_SYSTEM_DID1 >> 16; - - if (*p) - return (const char *)str; - - *p = to_hex(did >> 12); - *(p + 1) = to_hex((did >> 8) & 0xf); - *(p + 2) = to_hex((did >> 4) & 0xf); - *(p + 3) = to_hex(did & 0xf); - *(p + 4) = '\0'; - - return (const char *)str; -} - -const char *system_get_raw_chip_name(void) -{ - switch ((LM4_SYSTEM_DID1 & 0xffff0000) >> 16) { - case 0x10de: - return "tm4e1g31h6zrb"; - case 0x10e2: - return "lm4fsxhh5bb"; - case 0x10e3: - return "lm4fs232h5bb"; - case 0x10e4: - return "lm4fs99h5bb"; - case 0x10e6: - return "lm4fs1ah5bb"; - case 0x10ea: - return "lm4fs1gh5bb"; - default: - return system_get_chip_id_string(); - } -} - -const char *system_get_chip_name(void) -{ - const char *postfix = "-tm"; /* test mode */ - static char str[20]; - const char *raw_chip_name = system_get_raw_chip_name(); - char *p = str; - - if (LM4_TEST_MODE_ENABLED) { - /* Debug mode is enabled. Postfix chip name. */ - while (*raw_chip_name) - *(p++) = *(raw_chip_name++); - while (*postfix) - *(p++) = *(postfix++); - *p = '\0'; - return (const char *)str; - } else { - return raw_chip_name; - } -} - -int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int system_set_bbram(enum system_bbram_idx idx, uint8_t value) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -const char *system_get_chip_revision(void) -{ - static char rev[3]; - - /* Extract the major[15:8] and minor[7:0] revisions. */ - rev[0] = 'A' + ((LM4_SYSTEM_DID0 >> 8) & 0xff); - rev[1] = '0' + (LM4_SYSTEM_DID0 & 0xff); - rev[2] = 0; - - return rev; -} - -/*****************************************************************************/ -/* Console commands */ -void print_system_rtc(enum console_channel ch) -{ - uint32_t rtc; - uint32_t rtcss; - - rtc = system_get_rtc_sec_subsec(&rtcss); - cprintf(ch, "RTC: 0x%08x.%04x (%d.%06d s)\n", - rtc, rtcss, rtc, HIB_RTC_SUBSEC_TO_USEC(rtcss)); -} - -#ifdef CONFIG_CMD_RTC -static int command_system_rtc(int argc, char **argv) -{ - if (argc == 3 && !strcasecmp(argv[1], "set")) { - char *e; - uint32_t t = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - system_set_rtc(t); - } else if (argc > 1) { - return EC_ERROR_INVAL; - } - - print_system_rtc(CC_COMMAND); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(rtc, command_system_rtc, - "[set ]", - "Get/set real-time clock"); - -#ifdef CONFIG_CMD_RTC_ALARM -/** - * Test the RTC alarm by setting an interrupt on RTC match. - */ -static int command_rtc_alarm_test(int argc, char **argv) -{ - int s = 1, us = 0; - char *e; - - ccprintf("Setting RTC alarm\n"); - system_enable_hib_interrupt(); - - if (argc > 1) { - s = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - - } - if (argc > 2) { - us = strtoi(argv[2], &e, 10); - if (*e) - return EC_ERROR_PARAM2; - - } - - system_set_rtc_alarm(s, us); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(rtc_alarm, command_rtc_alarm_test, - "[seconds [microseconds]]", - "Test alarm"); -#endif /* CONFIG_CMD_RTC_ALARM */ -#endif /* CONFIG_CMD_RTC */ - -/*****************************************************************************/ -/* Host commands */ - -#ifdef CONFIG_HOSTCMD_RTC -static enum ec_status system_rtc_get_value(struct host_cmd_handler_args *args) -{ - struct ec_response_rtc *r = args->response; - - r->time = system_get_rtc_sec_subsec(NULL); - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_VALUE, - system_rtc_get_value, - EC_VER_MASK(0)); - -static enum ec_status system_rtc_set_value(struct host_cmd_handler_args *args) -{ - const struct ec_params_rtc *p = args->params; - - system_set_rtc(p->time); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_VALUE, - system_rtc_set_value, - EC_VER_MASK(0)); -#endif /* CONFIG_HOSTCMD_RTC */ diff --git a/chip/lm4/uart.c b/chip/lm4/uart.c deleted file mode 100644 index 7ccea9eb75..0000000000 --- a/chip/lm4/uart.c +++ /dev/null @@ -1,352 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* UART module for Chrome EC */ - -#include "clock.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "lpc.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "uart.h" -#include "util.h" - -#ifdef CONFIG_UART_HOST -#define IRQ_UART_HOST CONCAT2(LM4_IRQ_UART, CONFIG_UART_HOST) -#endif - -static int init_done; - -int uart_init_done(void) -{ - return init_done; -} - -void uart_tx_start(void) -{ - /* If interrupt is already enabled, nothing to do */ - if (LM4_UART_IM(0) & 0x20) - return; - - /* Do not allow deep sleep while transmit in progress */ - disable_sleep(SLEEP_MASK_UART); - - /* - * Re-enable the transmit interrupt, then forcibly trigger the - * interrupt. This works around a hardware problem with the - * UART where the FIFO only triggers the interrupt when its - * threshold is _crossed_, not just met. - */ - LM4_UART_IM(0) |= 0x20; - task_trigger_irq(LM4_IRQ_UART0); -} - -void uart_tx_stop(void) -{ - LM4_UART_IM(0) &= ~0x20; - - /* Re-allow deep sleep */ - enable_sleep(SLEEP_MASK_UART); -} - -void uart_tx_flush(void) -{ - /* Wait for transmit FIFO empty */ - while (!(LM4_UART_FR(0) & 0x80)) - ; -} - -int uart_tx_ready(void) -{ - return !(LM4_UART_FR(0) & 0x20); -} - -int uart_tx_in_progress(void) -{ - /* Transmit is in progress if the TX busy bit is set. */ - return LM4_UART_FR(0) & 0x08; -} - -int uart_rx_available(void) -{ - return !(LM4_UART_FR(0) & 0x10); -} - -void uart_write_char(char c) -{ - /* Wait for space in transmit FIFO. */ - while (!uart_tx_ready()) - ; - - LM4_UART_DR(0) = c; -} - -int uart_read_char(void) -{ - return LM4_UART_DR(0); -} - -static void uart_clear_rx_fifo(int channel) -{ - int scratch __attribute__ ((unused)); - while (!(LM4_UART_FR(channel) & 0x10)) - scratch = LM4_UART_DR(channel); -} - -/** - * Interrupt handler for UART0 - */ -void uart_ec_interrupt(void) -{ - /* Clear transmit and receive interrupt status */ - LM4_UART_ICR(0) = 0x70; - - - /* Read input FIFO until empty, then fill output FIFO */ - uart_process_input(); - uart_process_output(); -} -DECLARE_IRQ(LM4_IRQ_UART0, uart_ec_interrupt, 1); - -#ifdef CONFIG_UART_HOST - -/** - * Interrupt handler for Host UART - */ -void uart_host_interrupt(void) -{ - /* Clear transmit and receive interrupt status */ - LM4_UART_ICR(CONFIG_UART_HOST) = 0x70; - -#ifdef CONFIG_HOSTCMD_LPC - /* - * If we have space in our FIFO and a character is pending in LPC, - * handle that character. - */ - if (!(LM4_UART_FR(CONFIG_UART_HOST) & 0x20) && lpc_comx_has_char()) { - /* Copy the next byte then disable transmit interrupt */ - LM4_UART_DR(CONFIG_UART_HOST) = lpc_comx_get_char(); - LM4_UART_IM(CONFIG_UART_HOST) &= ~0x20; - } - - /* - * Handle received character. There is no flow control on input; - * received characters are blindly forwarded to LPC. This is ok - * because LPC is much faster than UART, and we don't have flow control - * on the UART receive-side either. - */ - if (!(LM4_UART_FR(CONFIG_UART_HOST) & 0x10)) - lpc_comx_put_char(LM4_UART_DR(CONFIG_UART_HOST)); -#endif -} -/* Must be same prio as LPC interrupt handler so they don't preempt */ -DECLARE_IRQ(IRQ_UART_HOST, uart_host_interrupt, 2); - -#endif /* CONFIG_UART_HOST */ - -static void uart_config(int port) -{ - /* Disable the port */ - LM4_UART_CTL(port) = 0x0300; - /* Use the internal oscillator */ - LM4_UART_CC(port) = 0x1; - /* Set the baud rate divisor */ - LM4_UART_IBRD(port) = (INTERNAL_CLOCK / 16) / CONFIG_UART_BAUD_RATE; - LM4_UART_FBRD(port) = - (((INTERNAL_CLOCK / 16) % CONFIG_UART_BAUD_RATE) * 64 - + CONFIG_UART_BAUD_RATE / 2) / CONFIG_UART_BAUD_RATE; - /* - * 8-N-1, FIFO enabled. Must be done after setting - * the divisor for the new divisor to take effect. - */ - LM4_UART_LCRH(port) = 0x70; - /* - * Interrupt when RX fifo at minimum (>= 1/8 full), and TX fifo - * when <= 1/4 full - */ - LM4_UART_IFLS(port) = 0x01; - /* - * Unmask receive-FIFO, receive-timeout. We need - * receive-timeout because the minimum RX FIFO depth is 1/8 = 2 - * bytes; without the receive-timeout we'd never be notified - * about single received characters. - */ - LM4_UART_IM(port) = 0x50; - /* Enable the port */ - LM4_UART_CTL(port) |= 0x0001; -} - -void uart_init(void) -{ - uint32_t mask = 0; - - /* - * Enable UART0 in run, sleep, and deep sleep modes. Enable the Host - * UART in run and sleep modes. - */ - mask |= 1; - clock_enable_peripheral(CGC_OFFSET_UART, mask, CGC_MODE_ALL); - -#ifdef CONFIG_UART_HOST - mask |= BIT(CONFIG_UART_HOST); -#endif - - clock_enable_peripheral(CGC_OFFSET_UART, mask, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - gpio_config_module(MODULE_UART, 1); - - /* Configure UARTs (identically) */ - uart_config(0); - -#ifdef CONFIG_UART_HOST - uart_config(CONFIG_UART_HOST); -#endif - - /* - * Enable interrupts for UART0 only. Host UART will have to wait - * until the LPC bus is initialized. - */ - uart_clear_rx_fifo(0); - task_enable_irq(LM4_IRQ_UART0); - - init_done = 1; -} - -#ifdef CONFIG_LOW_POWER_IDLE -void uart_enter_dsleep(void) -{ - const struct gpio_info g = gpio_list[GPIO_UART0_RX]; - - /* Disable the UART0 module interrupt. */ - task_disable_irq(LM4_IRQ_UART0); - - /* Disable UART0 peripheral in deep sleep. */ - clock_disable_peripheral(CGC_OFFSET_UART, 0x1, CGC_MODE_DSLEEP); - - /* - * Set the UART0 RX pin to be a generic GPIO with the flags defined - * in the board.c file. - */ - gpio_reset(GPIO_UART0_RX); - - /* Clear any pending GPIO interrupts on the UART0 RX pin. */ - LM4_GPIO_ICR(g.port) = g.mask; - - /* Enable GPIO interrupts on the UART0 RX pin. */ - gpio_enable_interrupt(GPIO_UART0_RX); -} - -void uart_exit_dsleep(void) -{ - const struct gpio_info g = gpio_list[GPIO_UART0_RX]; - - /* - * If the UART0 RX GPIO interrupt has not fired, then no edge has been - * detected. Disable the GPIO interrupt so that switching the pin over - * to a UART pin doesn't inadvertently cause a GPIO edge interrupt. - * Note: we can't disable this interrupt if it has already fired - * because then the IRQ will not get called. - */ - if (!(LM4_GPIO_MIS(g.port) & g.mask)) - gpio_disable_interrupt(GPIO_UART0_RX); - - /* Configure UART0 pins for use in UART peripheral. */ - gpio_config_module(MODULE_UART, 1); - - /* Clear pending interrupts on UART peripheral and enable interrupts. */ - uart_clear_rx_fifo(0); - task_enable_irq(LM4_IRQ_UART0); - - /* Enable UART0 peripheral in deep sleep */ - clock_enable_peripheral(CGC_OFFSET_UART, 0x1, CGC_MODE_DSLEEP); -} - -void uart_deepsleep_interrupt(enum gpio_signal signal) -{ - /* - * Activity seen on UART RX pin while UART was disabled for deep sleep. - * The console won't see that character because the UART is disabled, - * so we need to inform the clock module of UART activity ourselves. - */ - clock_refresh_console_in_use(); - - /* Disable interrupts on UART0 RX pin to avoid repeated interrupts. */ - gpio_disable_interrupt(GPIO_UART0_RX); -} -#endif /* CONFIG_LOW_POWER_IDLE */ - - -/*****************************************************************************/ -/* COMx functions */ - -#ifdef CONFIG_UART_HOST - -void uart_comx_enable(void) -{ - uart_clear_rx_fifo(CONFIG_UART_HOST); - task_enable_irq(IRQ_UART_HOST); -} - -int uart_comx_putc_ok(void) -{ - if (LM4_UART_FR(CONFIG_UART_HOST) & 0x20) { - /* - * FIFO is full, so enable transmit interrupt to let us know - * when it empties. - */ - LM4_UART_IM(CONFIG_UART_HOST) |= 0x20; - return 0; - } else { - return 1; - } -} - -void uart_comx_putc(int c) -{ - LM4_UART_DR(CONFIG_UART_HOST) = c; -} - -#endif /* CONFIG_UART_HOST */ - -/*****************************************************************************/ -/* Console commands */ - -#ifdef CONFIG_CMD_COMXTEST - -/** - * Write a character to COMx, waiting for space in the output buffer if - * necessary. - */ -static void uart_comx_putc_wait(int c) -{ - while (!uart_comx_putc_ok()) - ; - uart_comx_putc(c); -} - -static int command_comxtest(int argc, char **argv) -{ - /* Put characters to COMX port */ - const char *c = argc > 1 ? argv[1] : "testing comx output!"; - - ccprintf("Writing \"%s\\r\\n\" to COMx UART...\n", c); - - while (*c) - uart_comx_putc_wait(*c++); - - uart_comx_putc_wait('\r'); - uart_comx_putc_wait('\n'); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(comxtest, command_comxtest, - "[string]", - "Write test data to COMx uart"); - -#endif /* CONFIG_CMD_COMXTEST */ diff --git a/chip/lm4/watchdog.c b/chip/lm4/watchdog.c deleted file mode 100644 index 50f122bf02..0000000000 --- a/chip/lm4/watchdog.c +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Watchdog driver */ - -#include "clock.h" -#include "common.h" -#include "registers.h" -#include "gpio.h" -#include "hooks.h" -#include "task.h" -#include "util.h" -#include "watchdog.h" - -/* - * We use watchdog 0 which is clocked on the system clock - * to avoid the penalty cycles on each write access - */ - -/* magic value to unlock the watchdog registers */ -#define LM4_WATCHDOG_MAGIC_WORD 0x1ACCE551 - -static uint32_t watchdog_period; /* Watchdog counter initial value */ - -void IRQ_HANDLER(LM4_IRQ_WATCHDOG)(void) __attribute__((naked)); -void IRQ_HANDLER(LM4_IRQ_WATCHDOG)(void) -{ - /* Naked call so we can extract raw LR and SP */ - asm volatile("mov r0, lr\n" - "mov r1, sp\n" - /* Must push registers in pairs to keep 64-bit aligned - * stack for ARM EABI. This also conveniently saves - * R0=LR so we can pass it to task_resched_if_needed. */ - "push {r0, lr}\n" - "bl watchdog_trace\n" - /* Do NOT reset the watchdog interrupt here; it will - * be done in watchdog_reload(), or reset will be - * triggered if we don't call that by the next watchdog - * period. Instead, de-activate the interrupt in the - * NVIC, so the watchdog trace will only be printed - * once. - */ - "mov r0, %[irq]\n" - "bl task_disable_irq\n" - "pop {r0, lr}\n" - "b task_resched_if_needed\n" - : : [irq] "i" (LM4_IRQ_WATCHDOG)); -} -const struct irq_priority __keep IRQ_PRIORITY(LM4_IRQ_WATCHDOG) - __attribute__((section(".rodata.irqprio"))) - = {LM4_IRQ_WATCHDOG, 0}; /* put the watchdog at the highest - priority */ - -void watchdog_reload(void) -{ - uint32_t status = LM4_WATCHDOG_RIS(0); - - /* Unlock watchdog registers */ - LM4_WATCHDOG_LOCK(0) = LM4_WATCHDOG_MAGIC_WORD; - - /* As we reboot only on the second timeout, if we have already reached - * the first timeout we need to reset the interrupt bit. */ - if (status) { - LM4_WATCHDOG_ICR(0) = status; - /* That doesn't seem to unpend the watchdog interrupt (even if - * we do writes to force the write to be committed), so - * explicitly unpend the interrupt before re-enabling it. */ - task_clear_pending_irq(LM4_IRQ_WATCHDOG); - task_enable_irq(LM4_IRQ_WATCHDOG); - } - - /* Reload the watchdog counter */ - LM4_WATCHDOG_LOAD(0) = watchdog_period; - - /* Re-lock watchdog registers */ - LM4_WATCHDOG_LOCK(0) = 0xdeaddead; -} -DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); - -static void watchdog_freq_changed(void) -{ - /* Set the timeout period */ - watchdog_period = CONFIG_WATCHDOG_PERIOD_MS * (clock_get_freq() / 1000); - - /* Reload the watchdog timer now */ - watchdog_reload(); -} -DECLARE_HOOK(HOOK_FREQ_CHANGE, watchdog_freq_changed, HOOK_PRIO_DEFAULT); - -int watchdog_init(void) -{ - /* Enable watchdog 0 clock in run, sleep, and deep sleep modes */ - clock_enable_peripheral(CGC_OFFSET_WD, 0x1, CGC_MODE_ALL); - - /* Set initial timeout period */ - watchdog_freq_changed(); - - /* Unlock watchdog registers */ - LM4_WATCHDOG_LOCK(0) = LM4_WATCHDOG_MAGIC_WORD; - - /* De-activate the watchdog when the JTAG stops the CPU */ - LM4_WATCHDOG_TEST(0) |= BIT(8); - - /* Reset after 2 time-out, activate the watchdog and lock the control - * register. */ - LM4_WATCHDOG_CTL(0) = 0x3; - - /* Reset watchdog interrupt bits */ - LM4_WATCHDOG_ICR(0) = LM4_WATCHDOG_RIS(0); - - /* Lock watchdog registers against unintended accesses */ - LM4_WATCHDOG_LOCK(0) = 0xdeaddead; - - /* Enable watchdog interrupt */ - task_enable_irq(LM4_IRQ_WATCHDOG); - - return EC_SUCCESS; -} diff --git a/chip/max32660/build.mk b/chip/max32660/build.mk index e0f5636b2e..e0db8bc646 100644 --- a/chip/max32660/build.mk +++ b/chip/max32660/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -9,7 +9,7 @@ # MAX32660 SoC has a Cortex-M4F ARM core CORE:=cortex-m # Allow the full Cortex-M4 instruction set -CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4 +CFLAGS_CPU+=-mcpu=cortex-m4 # Required chip modules chip-y=clock_chip.o gpio_chip.o system_chip.o hwtimer_chip.o uart_chip.o @@ -18,4 +18,3 @@ chip-$(CONFIG_I2C)+=i2c_chip.o # Optional chip modules chip-$(CONFIG_FLASH_PHYSICAL)+=flash_chip.o chip-$(CONFIG_WATCHDOG)+=wdt_chip.o - diff --git a/chip/max32660/clock_chip.c b/chip/max32660/clock_chip.c index 901c5d559c..83fb2fa1d1 100644 --- a/chip/max32660/clock_chip.c +++ b/chip/max32660/clock_chip.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,16 +9,16 @@ #include "common.h" #include "console.h" #include "cpu.h" +#include "gcr_regs.h" #include "hooks.h" #include "hwtimer.h" +#include "pwrseq_regs.h" #include "registers.h" #include "system.h" #include "timer.h" +#include "tmr_regs.h" #include "util.h" #include "watchdog.h" -#include "tmr_regs.h" -#include "gcr_regs.h" -#include "pwrseq_regs.h" #define MAX32660_SYSTEMCLOCK SYS_CLOCK_HIRC @@ -26,9 +26,9 @@ typedef enum { SYS_CLOCK_NANORING = MXC_V_GCR_CLKCN_CLKSEL_NANORING, /**< 8KHz nanoring on MAX32660 */ - SYS_CLOCK_HFXIN = - MXC_V_GCR_CLKCN_CLKSEL_HFXIN, /**< 32KHz on MAX32660 */ - SYS_CLOCK_HFXIN_DIGITAL = 0x9, /**< External Clock Input*/ + SYS_CLOCK_HFXIN = MXC_V_GCR_CLKCN_CLKSEL_HFXIN, /**< 32KHz on MAX32660 + */ + SYS_CLOCK_HFXIN_DIGITAL = 0x9, /**< External Clock Input*/ SYS_CLOCK_HIRC = MXC_V_GCR_CLKCN_CLKSEL_HIRC, /**< High Frequency Internal Oscillator */ } sys_system_clock_t; @@ -139,3 +139,7 @@ void clock_init(void) } } } + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/max32660/config_chip.h b/chip/max32660/config_chip.h index b74ec591ad..9fa939a918 100644 --- a/chip/max32660/config_chip.h +++ b/chip/max32660/config_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -50,7 +50,7 @@ #define TASK_STACK_SIZE 512 #define CONFIG_PROGRAM_MEMORY_BASE 0x00000000 -#define CONFIG_FLASH_BANK_SIZE 0x00002000 /* protect bank size */ +#define CONFIG_FLASH_BANK_SIZE 0x00002000 /* protect bank size */ #define CONFIG_FLASH_ERASE_SIZE 0x00002000 /* erase bank size */ #define CONFIG_FLASH_WRITE_SIZE 0x00000004 /* minimum write size */ @@ -61,7 +61,7 @@ * in order to emulate per-bank write-protection UNTIL REBOOT. The hardware * doesn't support a write-protect pin, and if we make the write-protection * permanent, it can't be undone easily enough to support RMA. */ -#define CONFIG_FLASH_SIZE 0x00040000 /* 256K MAX32660 FLASH Size */ +#define CONFIG_FLASH_SIZE_BYTES 0x00040000 /* 256K MAX32660 FLASH Size */ /****************************************************************************/ /* Define our flash layout. */ diff --git a/chip/max32660/flash_chip.c b/chip/max32660/flash_chip.c index ace87294a7..01a26f94b5 100644 --- a/chip/max32660/flash_chip.c +++ b/chip/max32660/flash_chip.c @@ -1,20 +1,20 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* MAX32660 Flash Memory Module for Chrome EC */ +#include "common.h" #include "flash.h" +#include "flc_regs.h" +#include "icc_regs.h" +#include "registers.h" #include "switch.h" #include "system.h" #include "timer.h" #include "util.h" #include "watchdog.h" -#include "registers.h" -#include "common.h" -#include "icc_regs.h" -#include "flc_regs.h" #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) #define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) @@ -25,7 +25,7 @@ #define MXC_FLASH_PAGE_MASK ~(MXC_FLASH_PAGE_SIZE - 1) /// Calculate the address of a page in flash from the page number -#define MXC_FLASH_PAGE_ADDR(page) \ +#define MXC_FLASH_PAGE_ADDR(page) \ (MXC_FLASH_MEM_BASE + ((unsigned long)page * MXC_FLASH_PAGE_SIZE)) void flash_operation(void) @@ -108,7 +108,7 @@ static int flash_device_page_erase(uint32_t address) return EC_SUCCESS; } -int flash_physical_write(int offset, int size, const char *data) +int crec_flash_physical_write(int offset, int size, const char *data) { int err; uint32_t bytes_written; @@ -123,7 +123,6 @@ int flash_physical_write(int offset, int size, const char *data) // Align the address and read/write if we have to if (offset & 0x3) { - // Figure out how many bytes we have to write to round up the // address bytes_written = 4 - (offset & 0x3); @@ -163,7 +162,6 @@ int flash_physical_write(int offset, int size, const char *data) } if (size >= 16) { - // write in 128-bit bursts while we can MXC_FLC->cn &= ~MXC_F_FLC_CN_WDTH; @@ -232,7 +230,7 @@ int flash_physical_write(int offset, int size, const char *data) /*****************************************************************************/ /* Physical layer APIs */ -int flash_physical_erase(int offset, int size) +int crec_flash_physical_erase(int offset, int size) { int i; int pages; @@ -255,38 +253,38 @@ int flash_physical_erase(int offset, int size) return EC_SUCCESS; } -int flash_physical_get_protect(int bank) +int crec_flash_physical_get_protect(int bank) { /* Not protected */ return 0; } -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { /* no flags set */ return 0; } -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { /* These are the flags we're going to pay attention to */ return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ALL_NOW; } -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { /* no flags writable */ return 0; } -int flash_physical_protect_at_boot(uint32_t new_flags) +int crec_flash_physical_protect_at_boot(uint32_t new_flags) { /* nothing to do here */ return EC_SUCCESS; } -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { /* nothing to do here */ return EC_SUCCESS; @@ -295,7 +293,7 @@ int flash_physical_protect_now(int all) /*****************************************************************************/ /* High-level APIs */ -int flash_pre_init(void) +int crec_flash_pre_init(void) { return EC_SUCCESS; } @@ -308,7 +306,7 @@ int flash_pre_init(void) * NOTE: This is a DESTRUCTIVE test for the range of flash pages tested * make sure that PAGE_START is beyond your flash code. */ -static int command_flash_test1(int argc, char **argv) +static int command_flash_test1(int argc, const char **argv) { int i; uint8_t *ptr; @@ -330,10 +328,10 @@ static int command_flash_test1(int argc, char **argv) /* * erase page */ - error_status = flash_physical_erase(flash_address, - CONFIG_FLASH_ERASE_SIZE); + error_status = crec_flash_physical_erase( + flash_address, CONFIG_FLASH_ERASE_SIZE); if (error_status != EC_SUCCESS) { - CPRINTS("Error with flash_physical_erase\n"); + CPRINTS("Error with crec_flash_physical_erase\n"); return EC_ERROR_UNKNOWN; } @@ -356,10 +354,10 @@ static int command_flash_test1(int argc, char **argv) for (i = 0; i < BUFFER_SIZE; i++) { buffer[i] = i + page; } - error_status = flash_physical_write(flash_address, BUFFER_SIZE, - buffer); + error_status = crec_flash_physical_write(flash_address, + BUFFER_SIZE, buffer); if (error_status != EC_SUCCESS) { - CPRINTS("Error with flash_physical_write\n"); + CPRINTS("Error with crec_flash_physical_write\n"); return EC_ERROR_UNKNOWN; } } @@ -389,10 +387,10 @@ static int command_flash_test1(int argc, char **argv) */ for (page = PAGE_START; page <= PAGE_END; page++) { flash_address = page * CONFIG_FLASH_ERASE_SIZE; - error_status = flash_physical_erase(flash_address, - CONFIG_FLASH_ERASE_SIZE); + error_status = crec_flash_physical_erase( + flash_address, CONFIG_FLASH_ERASE_SIZE); if (error_status != EC_SUCCESS) { - CPRINTS("Error with flash_physical_erase\n"); + CPRINTS("Error with crec_flash_physical_erase\n"); return EC_ERROR_UNKNOWN; } } diff --git a/chip/max32660/flc_regs.h b/chip/max32660/flc_regs.h index a484763c0b..fb7691e759 100644 --- a/chip/max32660/flc_regs.h +++ b/chip/max32660/flc_regs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -43,14 +43,14 @@ extern "C" { * Structure type to access the FLC Registers. */ typedef struct { - __IO uint32_t addr; /**< \b 0x00:<\tt> FLC ADDR Register */ + __IO uint32_t addr; /**< \b 0x00:<\tt> FLC ADDR Register */ __IO uint32_t clkdiv; /**< \b 0x04:<\tt> FLC CLKDIV Register */ - __IO uint32_t cn; /**< \b 0x08:<\tt> FLC CN Register */ + __IO uint32_t cn; /**< \b 0x08:<\tt> FLC CN Register */ __R uint32_t rsv_0xc_0x23[6]; __IO uint32_t intr; /**< \b 0x024:<\tt> FLC INTR Register */ __R uint32_t rsv_0x28_0x2f[2]; __IO uint32_t data[4]; /**< \b 0x30:<\tt> FLC DATA Register */ - __O uint32_t acntl; /**< \b 0x40:<\tt> FLC ACNTL Register */ + __O uint32_t acntl; /**< \b 0x40:<\tt> FLC ACNTL Register */ } mxc_flc_regs_t; /* Register offsets for module FLC */ @@ -58,32 +58,32 @@ typedef struct { * FLC Peripheral Register Offsets from the FLC Base Peripheral * Address. */ -#define MXC_R_FLC_ADDR \ - ((uint32_t)0x00000000UL) /**< Offset from FLC Base Address: \ +#define MXC_R_FLC_ADDR \ + ((uint32_t)0x00000000UL) /**< Offset from FLC Base Address: \ 0x0x000 */ -#define MXC_R_FLC_CLKDIV \ - ((uint32_t)0x00000004UL) /**< Offset from FLC Base Address: \ +#define MXC_R_FLC_CLKDIV \ + ((uint32_t)0x00000004UL) /**< Offset from FLC Base Address: \ 0x0x004 */ -#define MXC_R_FLC_CN \ - ((uint32_t)0x00000008UL) /**< Offset from FLC Base Address: \ +#define MXC_R_FLC_CN \ + ((uint32_t)0x00000008UL) /**< Offset from FLC Base Address: \ 0x0x008 */ -#define MXC_R_FLC_INTR \ - ((uint32_t)0x00000024UL) /**< Offset from FLC Base Address: \ +#define MXC_R_FLC_INTR \ + ((uint32_t)0x00000024UL) /**< Offset from FLC Base Address: \ 0x0x024 */ -#define MXC_R_FLC_DATA \ - ((uint32_t)0x00000030UL) /**< Offset from FLC Base Address: \ +#define MXC_R_FLC_DATA \ + ((uint32_t)0x00000030UL) /**< Offset from FLC Base Address: \ 0x0x030 */ -#define MXC_R_FLC_ACNTL \ - ((uint32_t)0x00000040UL) /**< Offset from FLC Base Address: \ +#define MXC_R_FLC_ACNTL \ + ((uint32_t)0x00000040UL) /**< Offset from FLC Base Address: \ 0x0x040 */ /** * Flash Write Address. */ #define MXC_F_FLC_ADDR_ADDR_POS 0 /**< ADDR_ADDR Position */ -#define MXC_F_FLC_ADDR_ADDR \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_FLC_ADDR_ADDR_POS)) /**< ADDR_ADDR Mask */ +#define MXC_F_FLC_ADDR_ADDR \ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_FLC_ADDR_ADDR_POS)) /**< ADDR_ADDR \ + Mask */ /** * Flash Clock Divide. The clock (PLL0) is divided by this value to @@ -91,177 +91,200 @@ typedef struct { */ #define MXC_F_FLC_CLKDIV_CLKDIV_POS 0 /**< CLKDIV_CLKDIV Position */ #define MXC_F_FLC_CLKDIV_CLKDIV \ - ((uint32_t)( \ - 0xFFUL \ - << MXC_F_FLC_CLKDIV_CLKDIV_POS)) /**< CLKDIV_CLKDIV Mask */ + ((uint32_t)(0xFFUL << MXC_F_FLC_CLKDIV_CLKDIV_POS)) /**< CLKDIV_CLKDIV \ + Mask */ /** * Flash Control Register. */ #define MXC_F_FLC_CN_WR_POS 0 /**< CN_WR Position */ -#define MXC_F_FLC_CN_WR \ +#define MXC_F_FLC_CN_WR \ ((uint32_t)(0x1UL << MXC_F_FLC_CN_WR_POS)) /**< CN_WR Mask */ -#define MXC_V_FLC_CN_WR_COMPLETE \ - ((uint32_t)0x0UL) /**< CN_WR_COMPLETE Value \ +#define MXC_V_FLC_CN_WR_COMPLETE \ + ((uint32_t)0x0UL) /**< CN_WR_COMPLETE Value \ */ -#define MXC_S_FLC_CN_WR_COMPLETE \ - (MXC_V_FLC_CN_WR_COMPLETE \ - << MXC_F_FLC_CN_WR_POS) /**< CN_WR_COMPLETE Setting */ +#define MXC_S_FLC_CN_WR_COMPLETE \ + (MXC_V_FLC_CN_WR_COMPLETE << MXC_F_FLC_CN_WR_POS) /**< CN_WR_COMPLETE \ + Setting */ #define MXC_V_FLC_CN_WR_START ((uint32_t)0x1UL) /**< CN_WR_START Value */ -#define MXC_S_FLC_CN_WR_START \ - (MXC_V_FLC_CN_WR_START \ - << MXC_F_FLC_CN_WR_POS) /**< CN_WR_START Setting */ +#define MXC_S_FLC_CN_WR_START \ + (MXC_V_FLC_CN_WR_START << MXC_F_FLC_CN_WR_POS) /**< CN_WR_START \ + Setting */ #define MXC_F_FLC_CN_ME_POS 1 /**< CN_ME Position */ -#define MXC_F_FLC_CN_ME \ +#define MXC_F_FLC_CN_ME \ ((uint32_t)(0x1UL << MXC_F_FLC_CN_ME_POS)) /**< CN_ME Mask */ #define MXC_F_FLC_CN_PGE_POS 2 /**< CN_PGE Position */ -#define MXC_F_FLC_CN_PGE \ +#define MXC_F_FLC_CN_PGE \ ((uint32_t)(0x1UL << MXC_F_FLC_CN_PGE_POS)) /**< CN_PGE Mask */ #define MXC_F_FLC_CN_WDTH_POS 4 /**< CN_WDTH Position */ -#define MXC_F_FLC_CN_WDTH \ +#define MXC_F_FLC_CN_WDTH \ ((uint32_t)(0x1UL << MXC_F_FLC_CN_WDTH_POS)) /**< CN_WDTH Mask */ -#define MXC_V_FLC_CN_WDTH_SIZE128 \ +#define MXC_V_FLC_CN_WDTH_SIZE128 \ ((uint32_t)0x0UL) /**< CN_WDTH_SIZE128 Value */ -#define MXC_S_FLC_CN_WDTH_SIZE128 \ - (MXC_V_FLC_CN_WDTH_SIZE128 \ - << MXC_F_FLC_CN_WDTH_POS) /**< CN_WDTH_SIZE128 Setting */ -#define MXC_V_FLC_CN_WDTH_SIZE32 \ - ((uint32_t)0x1UL) /**< CN_WDTH_SIZE32 Value \ +#define MXC_S_FLC_CN_WDTH_SIZE128 \ + (MXC_V_FLC_CN_WDTH_SIZE128 \ + << MXC_F_FLC_CN_WDTH_POS) /**< \ + CN_WDTH_SIZE128 \ + Setting */ +#define MXC_V_FLC_CN_WDTH_SIZE32 \ + ((uint32_t)0x1UL) /**< CN_WDTH_SIZE32 Value \ */ -#define MXC_S_FLC_CN_WDTH_SIZE32 \ - (MXC_V_FLC_CN_WDTH_SIZE32 \ - << MXC_F_FLC_CN_WDTH_POS) /**< CN_WDTH_SIZE32 Setting */ +#define MXC_S_FLC_CN_WDTH_SIZE32 \ + (MXC_V_FLC_CN_WDTH_SIZE32 << MXC_F_FLC_CN_WDTH_POS) /**< \ + CN_WDTH_SIZE32 \ + Setting */ #define MXC_F_FLC_CN_ERASE_CODE_POS 8 /**< CN_ERASE_CODE Position */ #define MXC_F_FLC_CN_ERASE_CODE \ - ((uint32_t)( \ - 0xFFUL \ - << MXC_F_FLC_CN_ERASE_CODE_POS)) /**< CN_ERASE_CODE Mask */ -#define MXC_V_FLC_CN_ERASE_CODE_NOP \ + ((uint32_t)(0xFFUL << MXC_F_FLC_CN_ERASE_CODE_POS)) /**< CN_ERASE_CODE \ + Mask */ +#define MXC_V_FLC_CN_ERASE_CODE_NOP \ ((uint32_t)0x0UL) /**< CN_ERASE_CODE_NOP Value */ -#define MXC_S_FLC_CN_ERASE_CODE_NOP \ - (MXC_V_FLC_CN_ERASE_CODE_NOP \ - << MXC_F_FLC_CN_ERASE_CODE_POS) /**< CN_ERASE_CODE_NOP Setting */ -#define MXC_V_FLC_CN_ERASE_CODE_ERASEPAGE \ +#define MXC_S_FLC_CN_ERASE_CODE_NOP \ + (MXC_V_FLC_CN_ERASE_CODE_NOP \ + << MXC_F_FLC_CN_ERASE_CODE_POS) /**< \ + CN_ERASE_CODE_NOP \ + Setting \ + */ +#define MXC_V_FLC_CN_ERASE_CODE_ERASEPAGE \ ((uint32_t)0x55UL) /**< CN_ERASE_CODE_ERASEPAGE Value */ -#define MXC_S_FLC_CN_ERASE_CODE_ERASEPAGE \ - (MXC_V_FLC_CN_ERASE_CODE_ERASEPAGE \ - << MXC_F_FLC_CN_ERASE_CODE_POS) /**< CN_ERASE_CODE_ERASEPAGE Setting \ +#define MXC_S_FLC_CN_ERASE_CODE_ERASEPAGE \ + (MXC_V_FLC_CN_ERASE_CODE_ERASEPAGE \ + << MXC_F_FLC_CN_ERASE_CODE_POS) /**< CN_ERASE_CODE_ERASEPAGE Setting \ */ -#define MXC_V_FLC_CN_ERASE_CODE_ERASEALL \ +#define MXC_V_FLC_CN_ERASE_CODE_ERASEALL \ ((uint32_t)0xAAUL) /**< CN_ERASE_CODE_ERASEALL Value */ -#define MXC_S_FLC_CN_ERASE_CODE_ERASEALL \ - (MXC_V_FLC_CN_ERASE_CODE_ERASEALL \ - << MXC_F_FLC_CN_ERASE_CODE_POS) /**< CN_ERASE_CODE_ERASEALL Setting \ +#define MXC_S_FLC_CN_ERASE_CODE_ERASEALL \ + (MXC_V_FLC_CN_ERASE_CODE_ERASEALL \ + << MXC_F_FLC_CN_ERASE_CODE_POS) /**< CN_ERASE_CODE_ERASEALL Setting \ */ #define MXC_F_FLC_CN_PEND_POS 24 /**< CN_PEND Position */ -#define MXC_F_FLC_CN_PEND \ +#define MXC_F_FLC_CN_PEND \ ((uint32_t)(0x1UL << MXC_F_FLC_CN_PEND_POS)) /**< CN_PEND Mask */ -#define MXC_V_FLC_CN_PEND_IDLE ((uint32_t)0x0UL) /**< CN_PEND_IDLE Value */ -#define MXC_S_FLC_CN_PEND_IDLE \ - (MXC_V_FLC_CN_PEND_IDLE \ - << MXC_F_FLC_CN_PEND_POS) /**< CN_PEND_IDLE Setting */ +#define MXC_V_FLC_CN_PEND_IDLE ((uint32_t)0x0UL) /**< CN_PEND_IDLE Value */ +#define MXC_S_FLC_CN_PEND_IDLE \ + (MXC_V_FLC_CN_PEND_IDLE << MXC_F_FLC_CN_PEND_POS) /**< CN_PEND_IDLE \ + Setting */ #define MXC_V_FLC_CN_PEND_BUSY ((uint32_t)0x1UL) /**< CN_PEND_BUSY Value */ -#define MXC_S_FLC_CN_PEND_BUSY \ - (MXC_V_FLC_CN_PEND_BUSY \ - << MXC_F_FLC_CN_PEND_POS) /**< CN_PEND_BUSY Setting */ +#define MXC_S_FLC_CN_PEND_BUSY \ + (MXC_V_FLC_CN_PEND_BUSY << MXC_F_FLC_CN_PEND_POS) /**< CN_PEND_BUSY \ + Setting */ #define MXC_F_FLC_CN_LVE_POS 25 /**< CN_LVE Position */ -#define MXC_F_FLC_CN_LVE \ +#define MXC_F_FLC_CN_LVE \ ((uint32_t)(0x1UL << MXC_F_FLC_CN_LVE_POS)) /**< CN_LVE Mask */ -#define MXC_V_FLC_CN_LVE_DIS ((uint32_t)0x0UL) /**< CN_LVE_DIS Value */ +#define MXC_V_FLC_CN_LVE_DIS ((uint32_t)0x0UL) /**< CN_LVE_DIS Value */ #define MXC_S_FLC_CN_LVE_DIS \ - (MXC_V_FLC_CN_LVE_DIS \ - << MXC_F_FLC_CN_LVE_POS) /**< CN_LVE_DIS Setting */ + (MXC_V_FLC_CN_LVE_DIS << MXC_F_FLC_CN_LVE_POS) /**< CN_LVE_DIS Setting \ + */ #define MXC_V_FLC_CN_LVE_EN ((uint32_t)0x1UL) /**< CN_LVE_EN Value */ -#define MXC_S_FLC_CN_LVE_EN \ - (MXC_V_FLC_CN_LVE_EN << MXC_F_FLC_CN_LVE_POS) /**< CN_LVE_EN Setting \ +#define MXC_S_FLC_CN_LVE_EN \ + (MXC_V_FLC_CN_LVE_EN << MXC_F_FLC_CN_LVE_POS) /**< CN_LVE_EN Setting \ */ #define MXC_F_FLC_CN_BRST_POS 27 /**< CN_BRST Position */ -#define MXC_F_FLC_CN_BRST \ +#define MXC_F_FLC_CN_BRST \ ((uint32_t)(0x1UL << MXC_F_FLC_CN_BRST_POS)) /**< CN_BRST Mask */ -#define MXC_V_FLC_CN_BRST_DISABLE \ +#define MXC_V_FLC_CN_BRST_DISABLE \ ((uint32_t)0x0UL) /**< CN_BRST_DISABLE Value */ -#define MXC_S_FLC_CN_BRST_DISABLE \ - (MXC_V_FLC_CN_BRST_DISABLE \ - << MXC_F_FLC_CN_BRST_POS) /**< CN_BRST_DISABLE Setting */ -#define MXC_V_FLC_CN_BRST_ENABLE \ - ((uint32_t)0x1UL) /**< CN_BRST_ENABLE Value \ +#define MXC_S_FLC_CN_BRST_DISABLE \ + (MXC_V_FLC_CN_BRST_DISABLE \ + << MXC_F_FLC_CN_BRST_POS) /**< \ + CN_BRST_DISABLE \ + Setting */ +#define MXC_V_FLC_CN_BRST_ENABLE \ + ((uint32_t)0x1UL) /**< CN_BRST_ENABLE Value \ */ -#define MXC_S_FLC_CN_BRST_ENABLE \ - (MXC_V_FLC_CN_BRST_ENABLE \ - << MXC_F_FLC_CN_BRST_POS) /**< CN_BRST_ENABLE Setting */ +#define MXC_S_FLC_CN_BRST_ENABLE \ + (MXC_V_FLC_CN_BRST_ENABLE << MXC_F_FLC_CN_BRST_POS) /**< \ + CN_BRST_ENABLE \ + Setting */ #define MXC_F_FLC_CN_UNLOCK_POS 28 /**< CN_UNLOCK Position */ -#define MXC_F_FLC_CN_UNLOCK \ +#define MXC_F_FLC_CN_UNLOCK \ ((uint32_t)(0xFUL << MXC_F_FLC_CN_UNLOCK_POS)) /**< CN_UNLOCK Mask */ -#define MXC_V_FLC_CN_UNLOCK_UNLOCKED \ +#define MXC_V_FLC_CN_UNLOCK_UNLOCKED \ ((uint32_t)0x2UL) /**< CN_UNLOCK_UNLOCKED Value */ -#define MXC_S_FLC_CN_UNLOCK_UNLOCKED \ - (MXC_V_FLC_CN_UNLOCK_UNLOCKED \ - << MXC_F_FLC_CN_UNLOCK_POS) /**< CN_UNLOCK_UNLOCKED Setting */ +#define MXC_S_FLC_CN_UNLOCK_UNLOCKED \ + (MXC_V_FLC_CN_UNLOCK_UNLOCKED \ + << MXC_F_FLC_CN_UNLOCK_POS) /**< \ + CN_UNLOCK_UNLOCKED \ + Setting \ + */ /** * Flash Interrupt Register. */ #define MXC_F_FLC_INTR_DONE_POS 0 /**< INTR_DONE Position */ -#define MXC_F_FLC_INTR_DONE \ +#define MXC_F_FLC_INTR_DONE \ ((uint32_t)(0x1UL << MXC_F_FLC_INTR_DONE_POS)) /**< INTR_DONE Mask */ -#define MXC_V_FLC_INTR_DONE_INACTIVE \ +#define MXC_V_FLC_INTR_DONE_INACTIVE \ ((uint32_t)0x0UL) /**< INTR_DONE_INACTIVE Value */ -#define MXC_S_FLC_INTR_DONE_INACTIVE \ - (MXC_V_FLC_INTR_DONE_INACTIVE \ - << MXC_F_FLC_INTR_DONE_POS) /**< INTR_DONE_INACTIVE Setting */ -#define MXC_V_FLC_INTR_DONE_PENDING \ +#define MXC_S_FLC_INTR_DONE_INACTIVE \ + (MXC_V_FLC_INTR_DONE_INACTIVE \ + << MXC_F_FLC_INTR_DONE_POS) /**< \ + INTR_DONE_INACTIVE \ + Setting \ + */ +#define MXC_V_FLC_INTR_DONE_PENDING \ ((uint32_t)0x1UL) /**< INTR_DONE_PENDING Value */ -#define MXC_S_FLC_INTR_DONE_PENDING \ - (MXC_V_FLC_INTR_DONE_PENDING \ - << MXC_F_FLC_INTR_DONE_POS) /**< INTR_DONE_PENDING Setting */ +#define MXC_S_FLC_INTR_DONE_PENDING \ + (MXC_V_FLC_INTR_DONE_PENDING \ + << MXC_F_FLC_INTR_DONE_POS) /**< \ + INTR_DONE_PENDING \ + Setting */ #define MXC_F_FLC_INTR_AF_POS 1 /**< INTR_AF Position */ -#define MXC_F_FLC_INTR_AF \ +#define MXC_F_FLC_INTR_AF \ ((uint32_t)(0x1UL << MXC_F_FLC_INTR_AF_POS)) /**< INTR_AF Mask */ -#define MXC_V_FLC_INTR_AF_NOERROR \ +#define MXC_V_FLC_INTR_AF_NOERROR \ ((uint32_t)0x0UL) /**< INTR_AF_NOERROR Value */ -#define MXC_S_FLC_INTR_AF_NOERROR \ - (MXC_V_FLC_INTR_AF_NOERROR \ - << MXC_F_FLC_INTR_AF_POS) /**< INTR_AF_NOERROR Setting */ +#define MXC_S_FLC_INTR_AF_NOERROR \ + (MXC_V_FLC_INTR_AF_NOERROR \ + << MXC_F_FLC_INTR_AF_POS) /**< \ + INTR_AF_NOERROR \ + Setting */ #define MXC_V_FLC_INTR_AF_ERROR ((uint32_t)0x1UL) /**< INTR_AF_ERROR Value */ -#define MXC_S_FLC_INTR_AF_ERROR \ - (MXC_V_FLC_INTR_AF_ERROR \ - << MXC_F_FLC_INTR_AF_POS) /**< INTR_AF_ERROR Setting */ +#define MXC_S_FLC_INTR_AF_ERROR \ + (MXC_V_FLC_INTR_AF_ERROR << MXC_F_FLC_INTR_AF_POS) /**< INTR_AF_ERROR \ + Setting */ #define MXC_F_FLC_INTR_DONEIE_POS 8 /**< INTR_DONEIE Position */ #define MXC_F_FLC_INTR_DONEIE \ - ((uint32_t)( \ - 0x1UL << MXC_F_FLC_INTR_DONEIE_POS)) /**< INTR_DONEIE Mask */ -#define MXC_V_FLC_INTR_DONEIE_DISABLE \ + ((uint32_t)(0x1UL << MXC_F_FLC_INTR_DONEIE_POS)) /**< INTR_DONEIE Mask \ + */ +#define MXC_V_FLC_INTR_DONEIE_DISABLE \ ((uint32_t)0x0UL) /**< INTR_DONEIE_DISABLE Value */ -#define MXC_S_FLC_INTR_DONEIE_DISABLE \ - (MXC_V_FLC_INTR_DONEIE_DISABLE \ - << MXC_F_FLC_INTR_DONEIE_POS) /**< INTR_DONEIE_DISABLE Setting */ -#define MXC_V_FLC_INTR_DONEIE_ENABLE \ +#define MXC_S_FLC_INTR_DONEIE_DISABLE \ + (MXC_V_FLC_INTR_DONEIE_DISABLE \ + << MXC_F_FLC_INTR_DONEIE_POS) /**< \ + INTR_DONEIE_DISABLE \ + Setting \ + */ +#define MXC_V_FLC_INTR_DONEIE_ENABLE \ ((uint32_t)0x1UL) /**< INTR_DONEIE_ENABLE Value */ -#define MXC_S_FLC_INTR_DONEIE_ENABLE \ - (MXC_V_FLC_INTR_DONEIE_ENABLE \ - << MXC_F_FLC_INTR_DONEIE_POS) /**< INTR_DONEIE_ENABLE Setting */ +#define MXC_S_FLC_INTR_DONEIE_ENABLE \ + (MXC_V_FLC_INTR_DONEIE_ENABLE \ + << MXC_F_FLC_INTR_DONEIE_POS) /**< \ + INTR_DONEIE_ENABLE \ + Setting \ + */ #define MXC_F_FLC_INTR_AFIE_POS 9 /**< INTR_AFIE Position */ -#define MXC_F_FLC_INTR_AFIE \ +#define MXC_F_FLC_INTR_AFIE \ ((uint32_t)(0x1UL << MXC_F_FLC_INTR_AFIE_POS)) /**< INTR_AFIE Mask */ /** * Flash Write Data. */ #define MXC_F_FLC_DATA_DATA_POS 0 /**< DATA_DATA Position */ -#define MXC_F_FLC_DATA_DATA \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_FLC_DATA_DATA_POS)) /**< DATA_DATA Mask */ +#define MXC_F_FLC_DATA_DATA \ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_FLC_DATA_DATA_POS)) /**< DATA_DATA \ + Mask */ /** * Access Control Register. Writing the ACNTL register with the @@ -273,8 +296,9 @@ typedef struct { */ #define MXC_F_FLC_ACNTL_ACNTL_POS 0 /**< ACNTL_ACNTL Position */ #define MXC_F_FLC_ACNTL_ACNTL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_FLC_ACNTL_ACNTL_POS)) /**< ACNTL_ACNTL Mask */ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_FLC_ACNTL_ACNTL_POS)) /**< \ + ACNTL_ACNTL \ + Mask */ #ifdef __cplusplus } diff --git a/chip/max32660/gcr_regs.h b/chip/max32660/gcr_regs.h index c9de13812c..bed6cf4550 100644 --- a/chip/max32660/gcr_regs.h +++ b/chip/max32660/gcr_regs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -39,118 +39,123 @@ * Structure type to access the GCR Registers. */ typedef struct { - __IO uint32_t scon; /**< \b 0x00:<\tt> GCR SCON Register */ + __IO uint32_t scon; /**< \b 0x00:<\tt> GCR SCON Register */ __IO uint32_t rstr0; /**< \b 0x04:<\tt> GCR RSTR0 Register */ __IO uint32_t clkcn; /**< \b 0x08:<\tt> GCR CLKCN Register */ - __IO uint32_t pm; /**< \b 0x0C:<\tt> GCR PM Register */ + __IO uint32_t pm; /**< \b 0x0C:<\tt> GCR PM Register */ __R uint32_t rsv_0x10_0x17[2]; __IO uint32_t pckdiv; /**< \b 0x18:<\tt> GCR PCKDIV Register */ __R uint32_t rsv_0x1c_0x23[2]; __IO uint32_t perckcn0; /**< \b 0x24:<\tt> GCR PERCKCN0 Register */ - __IO uint32_t memckcn; /**< \b 0x28:<\tt> GCR MEMCKCN Register */ - __IO uint32_t memzcn; /**< \b 0x2C:<\tt> GCR MEMZCN Register */ + __IO uint32_t memckcn; /**< \b 0x28:<\tt> GCR MEMCKCN Register */ + __IO uint32_t memzcn; /**< \b 0x2C:<\tt> GCR MEMZCN Register */ __R uint32_t rsv_0x30; - __IO uint32_t scck; /**< \b 0x34:<\tt> GCR SCCK Register */ - __IO uint32_t mpri0; /**< \b 0x38:<\tt> GCR MPRI0 Register */ - __IO uint32_t mpri1; /**< \b 0x3C:<\tt> GCR MPRI1 Register */ - __IO uint32_t sysst; /**< \b 0x40:<\tt> GCR SYSST Register */ - __IO uint32_t rstr1; /**< \b 0x44:<\tt> GCR RSTR1 Register */ + __IO uint32_t scck; /**< \b 0x34:<\tt> GCR SCCK Register */ + __IO uint32_t mpri0; /**< \b 0x38:<\tt> GCR MPRI0 Register */ + __IO uint32_t mpri1; /**< \b 0x3C:<\tt> GCR MPRI1 Register */ + __IO uint32_t sysst; /**< \b 0x40:<\tt> GCR SYSST Register */ + __IO uint32_t rstr1; /**< \b 0x44:<\tt> GCR RSTR1 Register */ __IO uint32_t perckcn1; /**< \b 0x48:<\tt> GCR PERCKCN1 Register */ - __IO uint32_t evten; /**< \b 0x4C:<\tt> GCR EVTEN Register */ - __I uint32_t revision; /**< \b 0x50:<\tt> GCR REVISION Register */ - __IO uint32_t syssie; /**< \b 0x54:<\tt> GCR SYSSIE Register */ + __IO uint32_t evten; /**< \b 0x4C:<\tt> GCR EVTEN Register */ + __I uint32_t revision; /**< \b 0x50:<\tt> GCR REVISION Register */ + __IO uint32_t syssie; /**< \b 0x54:<\tt> GCR SYSSIE Register */ } mxc_gcr_regs_t; /** * GCR Peripheral Register Offsets from the GCR Base Peripheral * Address. */ -#define MXC_R_GCR_SCON \ - ((uint32_t)0x00000000UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_SCON \ + ((uint32_t)0x00000000UL) /**< Offset from GCR Base Address: \ 0x0x000 */ -#define MXC_R_GCR_RSTR0 \ - ((uint32_t)0x00000004UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_RSTR0 \ + ((uint32_t)0x00000004UL) /**< Offset from GCR Base Address: \ 0x0x004 */ -#define MXC_R_GCR_CLKCN \ - ((uint32_t)0x00000008UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_CLKCN \ + ((uint32_t)0x00000008UL) /**< Offset from GCR Base Address: \ 0x0x008 */ -#define MXC_R_GCR_PM \ - ((uint32_t)0x0000000CUL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_PM \ + ((uint32_t)0x0000000CUL) /**< Offset from GCR Base Address: \ 0x0x00C */ -#define MXC_R_GCR_PCKDIV \ - ((uint32_t)0x00000018UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_PCKDIV \ + ((uint32_t)0x00000018UL) /**< Offset from GCR Base Address: \ 0x0x018 */ -#define MXC_R_GCR_PERCKCN0 \ - ((uint32_t)0x00000024UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_PERCKCN0 \ + ((uint32_t)0x00000024UL) /**< Offset from GCR Base Address: \ 0x0x024 */ -#define MXC_R_GCR_MEMCKCN \ - ((uint32_t)0x00000028UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_MEMCKCN \ + ((uint32_t)0x00000028UL) /**< Offset from GCR Base Address: \ 0x0x028 */ -#define MXC_R_GCR_MEMZCN \ - ((uint32_t)0x0000002CUL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_MEMZCN \ + ((uint32_t)0x0000002CUL) /**< Offset from GCR Base Address: \ 0x0x02C */ -#define MXC_R_GCR_SCCK \ - ((uint32_t)0x00000034UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_SCCK \ + ((uint32_t)0x00000034UL) /**< Offset from GCR Base Address: \ 0x0x034 */ -#define MXC_R_GCR_MPRI0 \ - ((uint32_t)0x00000038UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_MPRI0 \ + ((uint32_t)0x00000038UL) /**< Offset from GCR Base Address: \ 0x0x038 */ -#define MXC_R_GCR_MPRI1 \ - ((uint32_t)0x0000003CUL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_MPRI1 \ + ((uint32_t)0x0000003CUL) /**< Offset from GCR Base Address: \ 0x0x03C */ -#define MXC_R_GCR_SYSST \ - ((uint32_t)0x00000040UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_SYSST \ + ((uint32_t)0x00000040UL) /**< Offset from GCR Base Address: \ 0x0x040 */ -#define MXC_R_GCR_RSTR1 \ - ((uint32_t)0x00000044UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_RSTR1 \ + ((uint32_t)0x00000044UL) /**< Offset from GCR Base Address: \ 0x0x044 */ -#define MXC_R_GCR_PERCKCN1 \ - ((uint32_t)0x00000048UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_PERCKCN1 \ + ((uint32_t)0x00000048UL) /**< Offset from GCR Base Address: \ 0x0x048 */ -#define MXC_R_GCR_EVTEN \ - ((uint32_t)0x0000004CUL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_EVTEN \ + ((uint32_t)0x0000004CUL) /**< Offset from GCR Base Address: \ 0x0x04C */ -#define MXC_R_GCR_REVISION \ - ((uint32_t)0x00000050UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_REVISION \ + ((uint32_t)0x00000050UL) /**< Offset from GCR Base Address: \ 0x0x050 */ -#define MXC_R_GCR_SYSSIE \ - ((uint32_t)0x00000054UL) /**< Offset from GCR Base Address: \ +#define MXC_R_GCR_SYSSIE \ + ((uint32_t)0x00000054UL) /**< Offset from GCR Base Address: \ 0x0x054 */ /** * System Control. */ #define MXC_F_GCR_SCON_SBUSARB_POS 1 /**< SCON_SBUSARB Position */ -#define MXC_F_GCR_SCON_SBUSARB \ - ((uint32_t)(0x3UL \ - << MXC_F_GCR_SCON_SBUSARB_POS)) /**< SCON_SBUSARB Mask */ -#define MXC_V_GCR_SCON_SBUSARB_FIX \ +#define MXC_F_GCR_SCON_SBUSARB \ + ((uint32_t)(0x3UL << MXC_F_GCR_SCON_SBUSARB_POS)) /**< SCON_SBUSARB \ + Mask */ +#define MXC_V_GCR_SCON_SBUSARB_FIX \ ((uint32_t)0x0UL) /**< SCON_SBUSARB_FIX Value */ -#define MXC_S_GCR_SCON_SBUSARB_FIX \ - (MXC_V_GCR_SCON_SBUSARB_FIX \ - << MXC_F_GCR_SCON_SBUSARB_POS) /**< SCON_SBUSARB_FIX Setting */ -#define MXC_V_GCR_SCON_SBUSARB_ROUND \ +#define MXC_S_GCR_SCON_SBUSARB_FIX \ + (MXC_V_GCR_SCON_SBUSARB_FIX \ + << MXC_F_GCR_SCON_SBUSARB_POS) /**< \ + SCON_SBUSARB_FIX \ + Setting \ + */ +#define MXC_V_GCR_SCON_SBUSARB_ROUND \ ((uint32_t)0x1UL) /**< SCON_SBUSARB_ROUND Value */ -#define MXC_S_GCR_SCON_SBUSARB_ROUND \ - (MXC_V_GCR_SCON_SBUSARB_ROUND \ - << MXC_F_GCR_SCON_SBUSARB_POS) /**< SCON_SBUSARB_ROUND Setting */ +#define MXC_S_GCR_SCON_SBUSARB_ROUND \ + (MXC_V_GCR_SCON_SBUSARB_ROUND \ + << MXC_F_GCR_SCON_SBUSARB_POS) /**< \ + SCON_SBUSARB_ROUND \ + Setting \ + */ -#define MXC_F_GCR_SCON_FLASH_PAGE_FLIP_POS \ +#define MXC_F_GCR_SCON_FLASH_PAGE_FLIP_POS \ 4 /**< SCON_FLASH_PAGE_FLIP Position */ -#define MXC_F_GCR_SCON_FLASH_PAGE_FLIP \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_SCON_FLASH_PAGE_FLIP_POS)) /**< \ - SCON_FLASH_PAGE_FLIP \ - Mask */ -#define MXC_V_GCR_SCON_FLASH_PAGE_FLIP_NORMAL \ +#define MXC_F_GCR_SCON_FLASH_PAGE_FLIP \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_SCON_FLASH_PAGE_FLIP_POS)) /**< \ + SCON_FLASH_PAGE_FLIP \ + Mask */ +#define MXC_V_GCR_SCON_FLASH_PAGE_FLIP_NORMAL \ ((uint32_t)0x0UL) /**< SCON_FLASH_PAGE_FLIP_NORMAL Value */ #define MXC_S_GCR_SCON_FLASH_PAGE_FLIP_NORMAL \ (MXC_V_GCR_SCON_FLASH_PAGE_FLIP_NORMAL \ << MXC_F_GCR_SCON_FLASH_PAGE_FLIP_POS) /**< \ SCON_FLASH_PAGE_FLIP_NORMAL \ Setting */ -#define MXC_V_GCR_SCON_FLASH_PAGE_FLIP_SWAPPED \ +#define MXC_V_GCR_SCON_FLASH_PAGE_FLIP_SWAPPED \ ((uint32_t)0x1UL) /**< SCON_FLASH_PAGE_FLIP_SWAPPED Value */ #define MXC_S_GCR_SCON_FLASH_PAGE_FLIP_SWAPPED \ (MXC_V_GCR_SCON_FLASH_PAGE_FLIP_SWAPPED \ @@ -159,1053 +164,1360 @@ typedef struct { Setting */ #define MXC_F_GCR_SCON_FPU_DIS_POS 5 /**< SCON_FPU_DIS Position */ -#define MXC_F_GCR_SCON_FPU_DIS \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_SCON_FPU_DIS_POS)) /**< SCON_FPU_DIS Mask */ -#define MXC_V_GCR_SCON_FPU_DIS_ENABLE \ +#define MXC_F_GCR_SCON_FPU_DIS \ + ((uint32_t)(0x1UL << MXC_F_GCR_SCON_FPU_DIS_POS)) /**< SCON_FPU_DIS \ + Mask */ +#define MXC_V_GCR_SCON_FPU_DIS_ENABLE \ ((uint32_t)0x0UL) /**< SCON_FPU_DIS_ENABLE Value */ -#define MXC_S_GCR_SCON_FPU_DIS_ENABLE \ - (MXC_V_GCR_SCON_FPU_DIS_ENABLE \ - << MXC_F_GCR_SCON_FPU_DIS_POS) /**< SCON_FPU_DIS_ENABLE Setting */ -#define MXC_V_GCR_SCON_FPU_DIS_DISABLE \ +#define MXC_S_GCR_SCON_FPU_DIS_ENABLE \ + (MXC_V_GCR_SCON_FPU_DIS_ENABLE \ + << MXC_F_GCR_SCON_FPU_DIS_POS) /**< \ + SCON_FPU_DIS_ENABLE \ + Setting \ + */ +#define MXC_V_GCR_SCON_FPU_DIS_DISABLE \ ((uint32_t)0x1UL) /**< SCON_FPU_DIS_DISABLE Value */ -#define MXC_S_GCR_SCON_FPU_DIS_DISABLE \ - (MXC_V_GCR_SCON_FPU_DIS_DISABLE \ - << MXC_F_GCR_SCON_FPU_DIS_POS) /**< SCON_FPU_DIS_DISABLE Setting */ +#define MXC_S_GCR_SCON_FPU_DIS_DISABLE \ + (MXC_V_GCR_SCON_FPU_DIS_DISABLE \ + << MXC_F_GCR_SCON_FPU_DIS_POS) /**< \ + SCON_FPU_DIS_DISABLE \ + Setting \ + */ #define MXC_F_GCR_SCON_CCACHE_FLUSH_POS 6 /**< SCON_CCACHE_FLUSH Position */ -#define MXC_F_GCR_SCON_CCACHE_FLUSH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_SCON_CCACHE_FLUSH_POS)) /**< SCON_CCACHE_FLUSH \ - Mask */ -#define MXC_V_GCR_SCON_CCACHE_FLUSH_NORMAL \ +#define MXC_F_GCR_SCON_CCACHE_FLUSH \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_SCON_CCACHE_FLUSH_POS)) /**< \ + SCON_CCACHE_FLUSH \ + Mask */ +#define MXC_V_GCR_SCON_CCACHE_FLUSH_NORMAL \ ((uint32_t)0x0UL) /**< SCON_CCACHE_FLUSH_NORMAL Value */ -#define MXC_S_GCR_SCON_CCACHE_FLUSH_NORMAL \ - (MXC_V_GCR_SCON_CCACHE_FLUSH_NORMAL \ - << MXC_F_GCR_SCON_CCACHE_FLUSH_POS) /**< SCON_CCACHE_FLUSH_NORMAL \ +#define MXC_S_GCR_SCON_CCACHE_FLUSH_NORMAL \ + (MXC_V_GCR_SCON_CCACHE_FLUSH_NORMAL \ + << MXC_F_GCR_SCON_CCACHE_FLUSH_POS) /**< SCON_CCACHE_FLUSH_NORMAL \ Setting */ -#define MXC_V_GCR_SCON_CCACHE_FLUSH_FLUSH \ +#define MXC_V_GCR_SCON_CCACHE_FLUSH_FLUSH \ ((uint32_t)0x1UL) /**< SCON_CCACHE_FLUSH_FLUSH Value */ -#define MXC_S_GCR_SCON_CCACHE_FLUSH_FLUSH \ - (MXC_V_GCR_SCON_CCACHE_FLUSH_FLUSH \ - << MXC_F_GCR_SCON_CCACHE_FLUSH_POS) /**< SCON_CCACHE_FLUSH_FLUSH \ +#define MXC_S_GCR_SCON_CCACHE_FLUSH_FLUSH \ + (MXC_V_GCR_SCON_CCACHE_FLUSH_FLUSH \ + << MXC_F_GCR_SCON_CCACHE_FLUSH_POS) /**< SCON_CCACHE_FLUSH_FLUSH \ Setting */ #define MXC_F_GCR_SCON_SWD_DIS_POS 14 /**< SCON_SWD_DIS Position */ -#define MXC_F_GCR_SCON_SWD_DIS \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_SCON_SWD_DIS_POS)) /**< SCON_SWD_DIS Mask */ -#define MXC_V_GCR_SCON_SWD_DIS_ENABLE \ +#define MXC_F_GCR_SCON_SWD_DIS \ + ((uint32_t)(0x1UL << MXC_F_GCR_SCON_SWD_DIS_POS)) /**< SCON_SWD_DIS \ + Mask */ +#define MXC_V_GCR_SCON_SWD_DIS_ENABLE \ ((uint32_t)0x0UL) /**< SCON_SWD_DIS_ENABLE Value */ -#define MXC_S_GCR_SCON_SWD_DIS_ENABLE \ - (MXC_V_GCR_SCON_SWD_DIS_ENABLE \ - << MXC_F_GCR_SCON_SWD_DIS_POS) /**< SCON_SWD_DIS_ENABLE Setting */ -#define MXC_V_GCR_SCON_SWD_DIS_DISABLE \ +#define MXC_S_GCR_SCON_SWD_DIS_ENABLE \ + (MXC_V_GCR_SCON_SWD_DIS_ENABLE \ + << MXC_F_GCR_SCON_SWD_DIS_POS) /**< \ + SCON_SWD_DIS_ENABLE \ + Setting \ + */ +#define MXC_V_GCR_SCON_SWD_DIS_DISABLE \ ((uint32_t)0x1UL) /**< SCON_SWD_DIS_DISABLE Value */ -#define MXC_S_GCR_SCON_SWD_DIS_DISABLE \ - (MXC_V_GCR_SCON_SWD_DIS_DISABLE \ - << MXC_F_GCR_SCON_SWD_DIS_POS) /**< SCON_SWD_DIS_DISABLE Setting */ +#define MXC_S_GCR_SCON_SWD_DIS_DISABLE \ + (MXC_V_GCR_SCON_SWD_DIS_DISABLE \ + << MXC_F_GCR_SCON_SWD_DIS_POS) /**< \ + SCON_SWD_DIS_DISABLE \ + Setting \ + */ /** * Reset Register 0. */ #define MXC_F_GCR_RSTR0_DMA_POS 0 /**< RSTR0_DMA Position */ -#define MXC_F_GCR_RSTR0_DMA \ +#define MXC_F_GCR_RSTR0_DMA \ ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_DMA_POS)) /**< RSTR0_DMA Mask */ #define MXC_V_GCR_RSTR0_DMA_RFU ((uint32_t)0x0UL) /**< RSTR0_DMA_RFU Value */ -#define MXC_S_GCR_RSTR0_DMA_RFU \ - (MXC_V_GCR_RSTR0_DMA_RFU \ - << MXC_F_GCR_RSTR0_DMA_POS) /**< RSTR0_DMA_RFU Setting */ -#define MXC_V_GCR_RSTR0_DMA_RESET \ +#define MXC_S_GCR_RSTR0_DMA_RFU \ + (MXC_V_GCR_RSTR0_DMA_RFU << MXC_F_GCR_RSTR0_DMA_POS) /**< \ + RSTR0_DMA_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_DMA_RESET \ ((uint32_t)0x1UL) /**< RSTR0_DMA_RESET Value */ -#define MXC_S_GCR_RSTR0_DMA_RESET \ - (MXC_V_GCR_RSTR0_DMA_RESET \ - << MXC_F_GCR_RSTR0_DMA_POS) /**< RSTR0_DMA_RESET Setting */ -#define MXC_V_GCR_RSTR0_DMA_RESET_DONE \ +#define MXC_S_GCR_RSTR0_DMA_RESET \ + (MXC_V_GCR_RSTR0_DMA_RESET \ + << MXC_F_GCR_RSTR0_DMA_POS) /**< \ + RSTR0_DMA_RESET \ + Setting */ +#define MXC_V_GCR_RSTR0_DMA_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_DMA_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_DMA_RESET_DONE \ - (MXC_V_GCR_RSTR0_DMA_RESET_DONE \ - << MXC_F_GCR_RSTR0_DMA_POS) /**< RSTR0_DMA_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_DMA_BUSY \ - ((uint32_t)0x1UL) /**< RSTR0_DMA_BUSY Value \ +#define MXC_S_GCR_RSTR0_DMA_RESET_DONE \ + (MXC_V_GCR_RSTR0_DMA_RESET_DONE \ + << MXC_F_GCR_RSTR0_DMA_POS) /**< \ + RSTR0_DMA_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_DMA_BUSY \ + ((uint32_t)0x1UL) /**< RSTR0_DMA_BUSY Value \ */ -#define MXC_S_GCR_RSTR0_DMA_BUSY \ - (MXC_V_GCR_RSTR0_DMA_BUSY \ - << MXC_F_GCR_RSTR0_DMA_POS) /**< RSTR0_DMA_BUSY Setting */ +#define MXC_S_GCR_RSTR0_DMA_BUSY \ + (MXC_V_GCR_RSTR0_DMA_BUSY \ + << MXC_F_GCR_RSTR0_DMA_POS) /**< \ + RSTR0_DMA_BUSY \ + Setting */ #define MXC_F_GCR_RSTR0_WDT_POS 1 /**< RSTR0_WDT Position */ -#define MXC_F_GCR_RSTR0_WDT \ +#define MXC_F_GCR_RSTR0_WDT \ ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_WDT_POS)) /**< RSTR0_WDT Mask */ #define MXC_V_GCR_RSTR0_WDT_RFU ((uint32_t)0x0UL) /**< RSTR0_WDT_RFU Value */ -#define MXC_S_GCR_RSTR0_WDT_RFU \ - (MXC_V_GCR_RSTR0_WDT_RFU \ - << MXC_F_GCR_RSTR0_WDT_POS) /**< RSTR0_WDT_RFU Setting */ -#define MXC_V_GCR_RSTR0_WDT_RESET \ +#define MXC_S_GCR_RSTR0_WDT_RFU \ + (MXC_V_GCR_RSTR0_WDT_RFU << MXC_F_GCR_RSTR0_WDT_POS) /**< \ + RSTR0_WDT_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_WDT_RESET \ ((uint32_t)0x1UL) /**< RSTR0_WDT_RESET Value */ -#define MXC_S_GCR_RSTR0_WDT_RESET \ - (MXC_V_GCR_RSTR0_WDT_RESET \ - << MXC_F_GCR_RSTR0_WDT_POS) /**< RSTR0_WDT_RESET Setting */ -#define MXC_V_GCR_RSTR0_WDT_RESET_DONE \ +#define MXC_S_GCR_RSTR0_WDT_RESET \ + (MXC_V_GCR_RSTR0_WDT_RESET \ + << MXC_F_GCR_RSTR0_WDT_POS) /**< \ + RSTR0_WDT_RESET \ + Setting */ +#define MXC_V_GCR_RSTR0_WDT_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_WDT_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_WDT_RESET_DONE \ - (MXC_V_GCR_RSTR0_WDT_RESET_DONE \ - << MXC_F_GCR_RSTR0_WDT_POS) /**< RSTR0_WDT_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_WDT_BUSY \ - ((uint32_t)0x1UL) /**< RSTR0_WDT_BUSY Value \ +#define MXC_S_GCR_RSTR0_WDT_RESET_DONE \ + (MXC_V_GCR_RSTR0_WDT_RESET_DONE \ + << MXC_F_GCR_RSTR0_WDT_POS) /**< \ + RSTR0_WDT_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_WDT_BUSY \ + ((uint32_t)0x1UL) /**< RSTR0_WDT_BUSY Value \ */ -#define MXC_S_GCR_RSTR0_WDT_BUSY \ - (MXC_V_GCR_RSTR0_WDT_BUSY \ - << MXC_F_GCR_RSTR0_WDT_POS) /**< RSTR0_WDT_BUSY Setting */ +#define MXC_S_GCR_RSTR0_WDT_BUSY \ + (MXC_V_GCR_RSTR0_WDT_BUSY \ + << MXC_F_GCR_RSTR0_WDT_POS) /**< \ + RSTR0_WDT_BUSY \ + Setting */ #define MXC_F_GCR_RSTR0_GPIO0_POS 2 /**< RSTR0_GPIO0 Position */ #define MXC_F_GCR_RSTR0_GPIO0 \ - ((uint32_t)( \ - 0x1UL << MXC_F_GCR_RSTR0_GPIO0_POS)) /**< RSTR0_GPIO0 Mask */ -#define MXC_V_GCR_RSTR0_GPIO0_RFU \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_GPIO0_POS)) /**< RSTR0_GPIO0 Mask \ + */ +#define MXC_V_GCR_RSTR0_GPIO0_RFU \ ((uint32_t)0x0UL) /**< RSTR0_GPIO0_RFU Value */ -#define MXC_S_GCR_RSTR0_GPIO0_RFU \ - (MXC_V_GCR_RSTR0_GPIO0_RFU \ - << MXC_F_GCR_RSTR0_GPIO0_POS) /**< RSTR0_GPIO0_RFU Setting */ -#define MXC_V_GCR_RSTR0_GPIO0_RESET \ +#define MXC_S_GCR_RSTR0_GPIO0_RFU \ + (MXC_V_GCR_RSTR0_GPIO0_RFU \ + << MXC_F_GCR_RSTR0_GPIO0_POS) /**< \ + RSTR0_GPIO0_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_GPIO0_RESET \ ((uint32_t)0x1UL) /**< RSTR0_GPIO0_RESET Value */ -#define MXC_S_GCR_RSTR0_GPIO0_RESET \ - (MXC_V_GCR_RSTR0_GPIO0_RESET \ - << MXC_F_GCR_RSTR0_GPIO0_POS) /**< RSTR0_GPIO0_RESET Setting */ -#define MXC_V_GCR_RSTR0_GPIO0_RESET_DONE \ +#define MXC_S_GCR_RSTR0_GPIO0_RESET \ + (MXC_V_GCR_RSTR0_GPIO0_RESET \ + << MXC_F_GCR_RSTR0_GPIO0_POS) /**< \ + RSTR0_GPIO0_RESET \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_GPIO0_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_GPIO0_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_GPIO0_RESET_DONE \ - (MXC_V_GCR_RSTR0_GPIO0_RESET_DONE \ - << MXC_F_GCR_RSTR0_GPIO0_POS) /**< RSTR0_GPIO0_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_GPIO0_BUSY \ +#define MXC_S_GCR_RSTR0_GPIO0_RESET_DONE \ + (MXC_V_GCR_RSTR0_GPIO0_RESET_DONE \ + << MXC_F_GCR_RSTR0_GPIO0_POS) /**< \ + RSTR0_GPIO0_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_GPIO0_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_GPIO0_BUSY Value */ -#define MXC_S_GCR_RSTR0_GPIO0_BUSY \ - (MXC_V_GCR_RSTR0_GPIO0_BUSY \ - << MXC_F_GCR_RSTR0_GPIO0_POS) /**< RSTR0_GPIO0_BUSY Setting */ +#define MXC_S_GCR_RSTR0_GPIO0_BUSY \ + (MXC_V_GCR_RSTR0_GPIO0_BUSY \ + << MXC_F_GCR_RSTR0_GPIO0_POS) /**< \ + RSTR0_GPIO0_BUSY \ + Setting \ + */ #define MXC_F_GCR_RSTR0_TIMER0_POS 5 /**< RSTR0_TIMER0 Position */ -#define MXC_F_GCR_RSTR0_TIMER0 \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_RSTR0_TIMER0_POS)) /**< RSTR0_TIMER0 Mask */ -#define MXC_V_GCR_RSTR0_TIMER0_RFU \ +#define MXC_F_GCR_RSTR0_TIMER0 \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_TIMER0_POS)) /**< RSTR0_TIMER0 \ + Mask */ +#define MXC_V_GCR_RSTR0_TIMER0_RFU \ ((uint32_t)0x0UL) /**< RSTR0_TIMER0_RFU Value */ -#define MXC_S_GCR_RSTR0_TIMER0_RFU \ - (MXC_V_GCR_RSTR0_TIMER0_RFU \ - << MXC_F_GCR_RSTR0_TIMER0_POS) /**< RSTR0_TIMER0_RFU Setting */ -#define MXC_V_GCR_RSTR0_TIMER0_RESET \ +#define MXC_S_GCR_RSTR0_TIMER0_RFU \ + (MXC_V_GCR_RSTR0_TIMER0_RFU \ + << MXC_F_GCR_RSTR0_TIMER0_POS) /**< \ + RSTR0_TIMER0_RFU \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_TIMER0_RESET \ ((uint32_t)0x1UL) /**< RSTR0_TIMER0_RESET Value */ -#define MXC_S_GCR_RSTR0_TIMER0_RESET \ - (MXC_V_GCR_RSTR0_TIMER0_RESET \ - << MXC_F_GCR_RSTR0_TIMER0_POS) /**< RSTR0_TIMER0_RESET Setting */ -#define MXC_V_GCR_RSTR0_TIMER0_RESET_DONE \ +#define MXC_S_GCR_RSTR0_TIMER0_RESET \ + (MXC_V_GCR_RSTR0_TIMER0_RESET \ + << MXC_F_GCR_RSTR0_TIMER0_POS) /**< \ + RSTR0_TIMER0_RESET \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_TIMER0_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_TIMER0_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_TIMER0_RESET_DONE \ - (MXC_V_GCR_RSTR0_TIMER0_RESET_DONE \ - << MXC_F_GCR_RSTR0_TIMER0_POS) /**< RSTR0_TIMER0_RESET_DONE Setting \ +#define MXC_S_GCR_RSTR0_TIMER0_RESET_DONE \ + (MXC_V_GCR_RSTR0_TIMER0_RESET_DONE \ + << MXC_F_GCR_RSTR0_TIMER0_POS) /**< RSTR0_TIMER0_RESET_DONE Setting \ */ -#define MXC_V_GCR_RSTR0_TIMER0_BUSY \ +#define MXC_V_GCR_RSTR0_TIMER0_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_TIMER0_BUSY Value */ -#define MXC_S_GCR_RSTR0_TIMER0_BUSY \ - (MXC_V_GCR_RSTR0_TIMER0_BUSY \ - << MXC_F_GCR_RSTR0_TIMER0_POS) /**< RSTR0_TIMER0_BUSY Setting */ +#define MXC_S_GCR_RSTR0_TIMER0_BUSY \ + (MXC_V_GCR_RSTR0_TIMER0_BUSY \ + << MXC_F_GCR_RSTR0_TIMER0_POS) /**< \ + RSTR0_TIMER0_BUSY \ + Setting \ + */ #define MXC_F_GCR_RSTR0_TIMER1_POS 6 /**< RSTR0_TIMER1 Position */ -#define MXC_F_GCR_RSTR0_TIMER1 \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_RSTR0_TIMER1_POS)) /**< RSTR0_TIMER1 Mask */ -#define MXC_V_GCR_RSTR0_TIMER1_RFU \ +#define MXC_F_GCR_RSTR0_TIMER1 \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_TIMER1_POS)) /**< RSTR0_TIMER1 \ + Mask */ +#define MXC_V_GCR_RSTR0_TIMER1_RFU \ ((uint32_t)0x0UL) /**< RSTR0_TIMER1_RFU Value */ -#define MXC_S_GCR_RSTR0_TIMER1_RFU \ - (MXC_V_GCR_RSTR0_TIMER1_RFU \ - << MXC_F_GCR_RSTR0_TIMER1_POS) /**< RSTR0_TIMER1_RFU Setting */ -#define MXC_V_GCR_RSTR0_TIMER1_RESET \ +#define MXC_S_GCR_RSTR0_TIMER1_RFU \ + (MXC_V_GCR_RSTR0_TIMER1_RFU \ + << MXC_F_GCR_RSTR0_TIMER1_POS) /**< \ + RSTR0_TIMER1_RFU \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_TIMER1_RESET \ ((uint32_t)0x1UL) /**< RSTR0_TIMER1_RESET Value */ -#define MXC_S_GCR_RSTR0_TIMER1_RESET \ - (MXC_V_GCR_RSTR0_TIMER1_RESET \ - << MXC_F_GCR_RSTR0_TIMER1_POS) /**< RSTR0_TIMER1_RESET Setting */ -#define MXC_V_GCR_RSTR0_TIMER1_RESET_DONE \ +#define MXC_S_GCR_RSTR0_TIMER1_RESET \ + (MXC_V_GCR_RSTR0_TIMER1_RESET \ + << MXC_F_GCR_RSTR0_TIMER1_POS) /**< \ + RSTR0_TIMER1_RESET \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_TIMER1_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_TIMER1_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_TIMER1_RESET_DONE \ - (MXC_V_GCR_RSTR0_TIMER1_RESET_DONE \ - << MXC_F_GCR_RSTR0_TIMER1_POS) /**< RSTR0_TIMER1_RESET_DONE Setting \ +#define MXC_S_GCR_RSTR0_TIMER1_RESET_DONE \ + (MXC_V_GCR_RSTR0_TIMER1_RESET_DONE \ + << MXC_F_GCR_RSTR0_TIMER1_POS) /**< RSTR0_TIMER1_RESET_DONE Setting \ */ -#define MXC_V_GCR_RSTR0_TIMER1_BUSY \ +#define MXC_V_GCR_RSTR0_TIMER1_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_TIMER1_BUSY Value */ -#define MXC_S_GCR_RSTR0_TIMER1_BUSY \ - (MXC_V_GCR_RSTR0_TIMER1_BUSY \ - << MXC_F_GCR_RSTR0_TIMER1_POS) /**< RSTR0_TIMER1_BUSY Setting */ +#define MXC_S_GCR_RSTR0_TIMER1_BUSY \ + (MXC_V_GCR_RSTR0_TIMER1_BUSY \ + << MXC_F_GCR_RSTR0_TIMER1_POS) /**< \ + RSTR0_TIMER1_BUSY \ + Setting \ + */ #define MXC_F_GCR_RSTR0_TIMER2_POS 7 /**< RSTR0_TIMER2 Position */ -#define MXC_F_GCR_RSTR0_TIMER2 \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_RSTR0_TIMER2_POS)) /**< RSTR0_TIMER2 Mask */ -#define MXC_V_GCR_RSTR0_TIMER2_RFU \ +#define MXC_F_GCR_RSTR0_TIMER2 \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_TIMER2_POS)) /**< RSTR0_TIMER2 \ + Mask */ +#define MXC_V_GCR_RSTR0_TIMER2_RFU \ ((uint32_t)0x0UL) /**< RSTR0_TIMER2_RFU Value */ -#define MXC_S_GCR_RSTR0_TIMER2_RFU \ - (MXC_V_GCR_RSTR0_TIMER2_RFU \ - << MXC_F_GCR_RSTR0_TIMER2_POS) /**< RSTR0_TIMER2_RFU Setting */ -#define MXC_V_GCR_RSTR0_TIMER2_RESET \ +#define MXC_S_GCR_RSTR0_TIMER2_RFU \ + (MXC_V_GCR_RSTR0_TIMER2_RFU \ + << MXC_F_GCR_RSTR0_TIMER2_POS) /**< \ + RSTR0_TIMER2_RFU \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_TIMER2_RESET \ ((uint32_t)0x1UL) /**< RSTR0_TIMER2_RESET Value */ -#define MXC_S_GCR_RSTR0_TIMER2_RESET \ - (MXC_V_GCR_RSTR0_TIMER2_RESET \ - << MXC_F_GCR_RSTR0_TIMER2_POS) /**< RSTR0_TIMER2_RESET Setting */ -#define MXC_V_GCR_RSTR0_TIMER2_RESET_DONE \ +#define MXC_S_GCR_RSTR0_TIMER2_RESET \ + (MXC_V_GCR_RSTR0_TIMER2_RESET \ + << MXC_F_GCR_RSTR0_TIMER2_POS) /**< \ + RSTR0_TIMER2_RESET \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_TIMER2_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_TIMER2_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_TIMER2_RESET_DONE \ - (MXC_V_GCR_RSTR0_TIMER2_RESET_DONE \ - << MXC_F_GCR_RSTR0_TIMER2_POS) /**< RSTR0_TIMER2_RESET_DONE Setting \ +#define MXC_S_GCR_RSTR0_TIMER2_RESET_DONE \ + (MXC_V_GCR_RSTR0_TIMER2_RESET_DONE \ + << MXC_F_GCR_RSTR0_TIMER2_POS) /**< RSTR0_TIMER2_RESET_DONE Setting \ */ -#define MXC_V_GCR_RSTR0_TIMER2_BUSY \ +#define MXC_V_GCR_RSTR0_TIMER2_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_TIMER2_BUSY Value */ -#define MXC_S_GCR_RSTR0_TIMER2_BUSY \ - (MXC_V_GCR_RSTR0_TIMER2_BUSY \ - << MXC_F_GCR_RSTR0_TIMER2_POS) /**< RSTR0_TIMER2_BUSY Setting */ +#define MXC_S_GCR_RSTR0_TIMER2_BUSY \ + (MXC_V_GCR_RSTR0_TIMER2_BUSY \ + << MXC_F_GCR_RSTR0_TIMER2_POS) /**< \ + RSTR0_TIMER2_BUSY \ + Setting \ + */ #define MXC_F_GCR_RSTR0_UART0_POS 11 /**< RSTR0_UART0 Position */ #define MXC_F_GCR_RSTR0_UART0 \ - ((uint32_t)( \ - 0x1UL << MXC_F_GCR_RSTR0_UART0_POS)) /**< RSTR0_UART0 Mask */ -#define MXC_V_GCR_RSTR0_UART0_RFU \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_UART0_POS)) /**< RSTR0_UART0 Mask \ + */ +#define MXC_V_GCR_RSTR0_UART0_RFU \ ((uint32_t)0x0UL) /**< RSTR0_UART0_RFU Value */ -#define MXC_S_GCR_RSTR0_UART0_RFU \ - (MXC_V_GCR_RSTR0_UART0_RFU \ - << MXC_F_GCR_RSTR0_UART0_POS) /**< RSTR0_UART0_RFU Setting */ -#define MXC_V_GCR_RSTR0_UART0_RESET \ +#define MXC_S_GCR_RSTR0_UART0_RFU \ + (MXC_V_GCR_RSTR0_UART0_RFU \ + << MXC_F_GCR_RSTR0_UART0_POS) /**< \ + RSTR0_UART0_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_UART0_RESET \ ((uint32_t)0x1UL) /**< RSTR0_UART0_RESET Value */ -#define MXC_S_GCR_RSTR0_UART0_RESET \ - (MXC_V_GCR_RSTR0_UART0_RESET \ - << MXC_F_GCR_RSTR0_UART0_POS) /**< RSTR0_UART0_RESET Setting */ -#define MXC_V_GCR_RSTR0_UART0_RESET_DONE \ +#define MXC_S_GCR_RSTR0_UART0_RESET \ + (MXC_V_GCR_RSTR0_UART0_RESET \ + << MXC_F_GCR_RSTR0_UART0_POS) /**< \ + RSTR0_UART0_RESET \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_UART0_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_UART0_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_UART0_RESET_DONE \ - (MXC_V_GCR_RSTR0_UART0_RESET_DONE \ - << MXC_F_GCR_RSTR0_UART0_POS) /**< RSTR0_UART0_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_UART0_BUSY \ +#define MXC_S_GCR_RSTR0_UART0_RESET_DONE \ + (MXC_V_GCR_RSTR0_UART0_RESET_DONE \ + << MXC_F_GCR_RSTR0_UART0_POS) /**< \ + RSTR0_UART0_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_UART0_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_UART0_BUSY Value */ -#define MXC_S_GCR_RSTR0_UART0_BUSY \ - (MXC_V_GCR_RSTR0_UART0_BUSY \ - << MXC_F_GCR_RSTR0_UART0_POS) /**< RSTR0_UART0_BUSY Setting */ +#define MXC_S_GCR_RSTR0_UART0_BUSY \ + (MXC_V_GCR_RSTR0_UART0_BUSY \ + << MXC_F_GCR_RSTR0_UART0_POS) /**< \ + RSTR0_UART0_BUSY \ + Setting \ + */ #define MXC_F_GCR_RSTR0_UART1_POS 12 /**< RSTR0_UART1 Position */ #define MXC_F_GCR_RSTR0_UART1 \ - ((uint32_t)( \ - 0x1UL << MXC_F_GCR_RSTR0_UART1_POS)) /**< RSTR0_UART1 Mask */ -#define MXC_V_GCR_RSTR0_UART1_RFU \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_UART1_POS)) /**< RSTR0_UART1 Mask \ + */ +#define MXC_V_GCR_RSTR0_UART1_RFU \ ((uint32_t)0x0UL) /**< RSTR0_UART1_RFU Value */ -#define MXC_S_GCR_RSTR0_UART1_RFU \ - (MXC_V_GCR_RSTR0_UART1_RFU \ - << MXC_F_GCR_RSTR0_UART1_POS) /**< RSTR0_UART1_RFU Setting */ -#define MXC_V_GCR_RSTR0_UART1_RESET \ +#define MXC_S_GCR_RSTR0_UART1_RFU \ + (MXC_V_GCR_RSTR0_UART1_RFU \ + << MXC_F_GCR_RSTR0_UART1_POS) /**< \ + RSTR0_UART1_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_UART1_RESET \ ((uint32_t)0x1UL) /**< RSTR0_UART1_RESET Value */ -#define MXC_S_GCR_RSTR0_UART1_RESET \ - (MXC_V_GCR_RSTR0_UART1_RESET \ - << MXC_F_GCR_RSTR0_UART1_POS) /**< RSTR0_UART1_RESET Setting */ -#define MXC_V_GCR_RSTR0_UART1_RESET_DONE \ +#define MXC_S_GCR_RSTR0_UART1_RESET \ + (MXC_V_GCR_RSTR0_UART1_RESET \ + << MXC_F_GCR_RSTR0_UART1_POS) /**< \ + RSTR0_UART1_RESET \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_UART1_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_UART1_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_UART1_RESET_DONE \ - (MXC_V_GCR_RSTR0_UART1_RESET_DONE \ - << MXC_F_GCR_RSTR0_UART1_POS) /**< RSTR0_UART1_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_UART1_BUSY \ +#define MXC_S_GCR_RSTR0_UART1_RESET_DONE \ + (MXC_V_GCR_RSTR0_UART1_RESET_DONE \ + << MXC_F_GCR_RSTR0_UART1_POS) /**< \ + RSTR0_UART1_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_UART1_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_UART1_BUSY Value */ -#define MXC_S_GCR_RSTR0_UART1_BUSY \ - (MXC_V_GCR_RSTR0_UART1_BUSY \ - << MXC_F_GCR_RSTR0_UART1_POS) /**< RSTR0_UART1_BUSY Setting */ +#define MXC_S_GCR_RSTR0_UART1_BUSY \ + (MXC_V_GCR_RSTR0_UART1_BUSY \ + << MXC_F_GCR_RSTR0_UART1_POS) /**< \ + RSTR0_UART1_BUSY \ + Setting \ + */ #define MXC_F_GCR_RSTR0_SPI0_POS 13 /**< RSTR0_SPI0 Position */ -#define MXC_F_GCR_RSTR0_SPI0 \ - ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SPI0_POS)) /**< RSTR0_SPI0 Mask \ +#define MXC_F_GCR_RSTR0_SPI0 \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SPI0_POS)) /**< RSTR0_SPI0 Mask \ */ -#define MXC_V_GCR_RSTR0_SPI0_RFU \ - ((uint32_t)0x0UL) /**< RSTR0_SPI0_RFU Value \ +#define MXC_V_GCR_RSTR0_SPI0_RFU \ + ((uint32_t)0x0UL) /**< RSTR0_SPI0_RFU Value \ */ -#define MXC_S_GCR_RSTR0_SPI0_RFU \ - (MXC_V_GCR_RSTR0_SPI0_RFU \ - << MXC_F_GCR_RSTR0_SPI0_POS) /**< RSTR0_SPI0_RFU Setting */ -#define MXC_V_GCR_RSTR0_SPI0_RESET \ +#define MXC_S_GCR_RSTR0_SPI0_RFU \ + (MXC_V_GCR_RSTR0_SPI0_RFU \ + << MXC_F_GCR_RSTR0_SPI0_POS) /**< \ + RSTR0_SPI0_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_SPI0_RESET \ ((uint32_t)0x1UL) /**< RSTR0_SPI0_RESET Value */ -#define MXC_S_GCR_RSTR0_SPI0_RESET \ - (MXC_V_GCR_RSTR0_SPI0_RESET \ - << MXC_F_GCR_RSTR0_SPI0_POS) /**< RSTR0_SPI0_RESET Setting */ -#define MXC_V_GCR_RSTR0_SPI0_RESET_DONE \ +#define MXC_S_GCR_RSTR0_SPI0_RESET \ + (MXC_V_GCR_RSTR0_SPI0_RESET \ + << MXC_F_GCR_RSTR0_SPI0_POS) /**< \ + RSTR0_SPI0_RESET \ + Setting */ +#define MXC_V_GCR_RSTR0_SPI0_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_SPI0_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_SPI0_RESET_DONE \ - (MXC_V_GCR_RSTR0_SPI0_RESET_DONE \ - << MXC_F_GCR_RSTR0_SPI0_POS) /**< RSTR0_SPI0_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_SPI0_BUSY \ +#define MXC_S_GCR_RSTR0_SPI0_RESET_DONE \ + (MXC_V_GCR_RSTR0_SPI0_RESET_DONE \ + << MXC_F_GCR_RSTR0_SPI0_POS) /**< \ + RSTR0_SPI0_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_SPI0_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_SPI0_BUSY Value */ -#define MXC_S_GCR_RSTR0_SPI0_BUSY \ - (MXC_V_GCR_RSTR0_SPI0_BUSY \ - << MXC_F_GCR_RSTR0_SPI0_POS) /**< RSTR0_SPI0_BUSY Setting */ +#define MXC_S_GCR_RSTR0_SPI0_BUSY \ + (MXC_V_GCR_RSTR0_SPI0_BUSY \ + << MXC_F_GCR_RSTR0_SPI0_POS) /**< \ + RSTR0_SPI0_BUSY \ + Setting */ #define MXC_F_GCR_RSTR0_SPI1_POS 14 /**< RSTR0_SPI1 Position */ -#define MXC_F_GCR_RSTR0_SPI1 \ - ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SPI1_POS)) /**< RSTR0_SPI1 Mask \ +#define MXC_F_GCR_RSTR0_SPI1 \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SPI1_POS)) /**< RSTR0_SPI1 Mask \ */ -#define MXC_V_GCR_RSTR0_SPI1_RFU \ - ((uint32_t)0x0UL) /**< RSTR0_SPI1_RFU Value \ +#define MXC_V_GCR_RSTR0_SPI1_RFU \ + ((uint32_t)0x0UL) /**< RSTR0_SPI1_RFU Value \ */ -#define MXC_S_GCR_RSTR0_SPI1_RFU \ - (MXC_V_GCR_RSTR0_SPI1_RFU \ - << MXC_F_GCR_RSTR0_SPI1_POS) /**< RSTR0_SPI1_RFU Setting */ -#define MXC_V_GCR_RSTR0_SPI1_RESET \ +#define MXC_S_GCR_RSTR0_SPI1_RFU \ + (MXC_V_GCR_RSTR0_SPI1_RFU \ + << MXC_F_GCR_RSTR0_SPI1_POS) /**< \ + RSTR0_SPI1_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_SPI1_RESET \ ((uint32_t)0x1UL) /**< RSTR0_SPI1_RESET Value */ -#define MXC_S_GCR_RSTR0_SPI1_RESET \ - (MXC_V_GCR_RSTR0_SPI1_RESET \ - << MXC_F_GCR_RSTR0_SPI1_POS) /**< RSTR0_SPI1_RESET Setting */ -#define MXC_V_GCR_RSTR0_SPI1_RESET_DONE \ +#define MXC_S_GCR_RSTR0_SPI1_RESET \ + (MXC_V_GCR_RSTR0_SPI1_RESET \ + << MXC_F_GCR_RSTR0_SPI1_POS) /**< \ + RSTR0_SPI1_RESET \ + Setting */ +#define MXC_V_GCR_RSTR0_SPI1_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_SPI1_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_SPI1_RESET_DONE \ - (MXC_V_GCR_RSTR0_SPI1_RESET_DONE \ - << MXC_F_GCR_RSTR0_SPI1_POS) /**< RSTR0_SPI1_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_SPI1_BUSY \ +#define MXC_S_GCR_RSTR0_SPI1_RESET_DONE \ + (MXC_V_GCR_RSTR0_SPI1_RESET_DONE \ + << MXC_F_GCR_RSTR0_SPI1_POS) /**< \ + RSTR0_SPI1_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_SPI1_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_SPI1_BUSY Value */ -#define MXC_S_GCR_RSTR0_SPI1_BUSY \ - (MXC_V_GCR_RSTR0_SPI1_BUSY \ - << MXC_F_GCR_RSTR0_SPI1_POS) /**< RSTR0_SPI1_BUSY Setting */ +#define MXC_S_GCR_RSTR0_SPI1_BUSY \ + (MXC_V_GCR_RSTR0_SPI1_BUSY \ + << MXC_F_GCR_RSTR0_SPI1_POS) /**< \ + RSTR0_SPI1_BUSY \ + Setting */ #define MXC_F_GCR_RSTR0_I2C0_POS 16 /**< RSTR0_I2C0 Position */ -#define MXC_F_GCR_RSTR0_I2C0 \ - ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_I2C0_POS)) /**< RSTR0_I2C0 Mask \ +#define MXC_F_GCR_RSTR0_I2C0 \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_I2C0_POS)) /**< RSTR0_I2C0 Mask \ */ -#define MXC_V_GCR_RSTR0_I2C0_RFU \ - ((uint32_t)0x0UL) /**< RSTR0_I2C0_RFU Value \ +#define MXC_V_GCR_RSTR0_I2C0_RFU \ + ((uint32_t)0x0UL) /**< RSTR0_I2C0_RFU Value \ */ -#define MXC_S_GCR_RSTR0_I2C0_RFU \ - (MXC_V_GCR_RSTR0_I2C0_RFU \ - << MXC_F_GCR_RSTR0_I2C0_POS) /**< RSTR0_I2C0_RFU Setting */ -#define MXC_V_GCR_RSTR0_I2C0_RESET \ +#define MXC_S_GCR_RSTR0_I2C0_RFU \ + (MXC_V_GCR_RSTR0_I2C0_RFU \ + << MXC_F_GCR_RSTR0_I2C0_POS) /**< \ + RSTR0_I2C0_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_I2C0_RESET \ ((uint32_t)0x1UL) /**< RSTR0_I2C0_RESET Value */ -#define MXC_S_GCR_RSTR0_I2C0_RESET \ - (MXC_V_GCR_RSTR0_I2C0_RESET \ - << MXC_F_GCR_RSTR0_I2C0_POS) /**< RSTR0_I2C0_RESET Setting */ -#define MXC_V_GCR_RSTR0_I2C0_RESET_DONE \ +#define MXC_S_GCR_RSTR0_I2C0_RESET \ + (MXC_V_GCR_RSTR0_I2C0_RESET \ + << MXC_F_GCR_RSTR0_I2C0_POS) /**< \ + RSTR0_I2C0_RESET \ + Setting */ +#define MXC_V_GCR_RSTR0_I2C0_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_I2C0_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_I2C0_RESET_DONE \ - (MXC_V_GCR_RSTR0_I2C0_RESET_DONE \ - << MXC_F_GCR_RSTR0_I2C0_POS) /**< RSTR0_I2C0_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_I2C0_BUSY \ +#define MXC_S_GCR_RSTR0_I2C0_RESET_DONE \ + (MXC_V_GCR_RSTR0_I2C0_RESET_DONE \ + << MXC_F_GCR_RSTR0_I2C0_POS) /**< \ + RSTR0_I2C0_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_I2C0_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_I2C0_BUSY Value */ -#define MXC_S_GCR_RSTR0_I2C0_BUSY \ - (MXC_V_GCR_RSTR0_I2C0_BUSY \ - << MXC_F_GCR_RSTR0_I2C0_POS) /**< RSTR0_I2C0_BUSY Setting */ +#define MXC_S_GCR_RSTR0_I2C0_BUSY \ + (MXC_V_GCR_RSTR0_I2C0_BUSY \ + << MXC_F_GCR_RSTR0_I2C0_POS) /**< \ + RSTR0_I2C0_BUSY \ + Setting */ #define MXC_F_GCR_RSTR0_RTC_POS 17 /**< RSTR0_RTC Position */ -#define MXC_F_GCR_RSTR0_RTC \ +#define MXC_F_GCR_RSTR0_RTC \ ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_RTC_POS)) /**< RSTR0_RTC Mask */ #define MXC_V_GCR_RSTR0_RTC_RFU ((uint32_t)0x0UL) /**< RSTR0_RTC_RFU Value */ -#define MXC_S_GCR_RSTR0_RTC_RFU \ - (MXC_V_GCR_RSTR0_RTC_RFU \ - << MXC_F_GCR_RSTR0_RTC_POS) /**< RSTR0_RTC_RFU Setting */ -#define MXC_V_GCR_RSTR0_RTC_RESET \ +#define MXC_S_GCR_RSTR0_RTC_RFU \ + (MXC_V_GCR_RSTR0_RTC_RFU << MXC_F_GCR_RSTR0_RTC_POS) /**< \ + RSTR0_RTC_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_RTC_RESET \ ((uint32_t)0x1UL) /**< RSTR0_RTC_RESET Value */ -#define MXC_S_GCR_RSTR0_RTC_RESET \ - (MXC_V_GCR_RSTR0_RTC_RESET \ - << MXC_F_GCR_RSTR0_RTC_POS) /**< RSTR0_RTC_RESET Setting */ -#define MXC_V_GCR_RSTR0_RTC_RESET_DONE \ +#define MXC_S_GCR_RSTR0_RTC_RESET \ + (MXC_V_GCR_RSTR0_RTC_RESET \ + << MXC_F_GCR_RSTR0_RTC_POS) /**< \ + RSTR0_RTC_RESET \ + Setting */ +#define MXC_V_GCR_RSTR0_RTC_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_RTC_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_RTC_RESET_DONE \ - (MXC_V_GCR_RSTR0_RTC_RESET_DONE \ - << MXC_F_GCR_RSTR0_RTC_POS) /**< RSTR0_RTC_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_RTC_BUSY \ - ((uint32_t)0x1UL) /**< RSTR0_RTC_BUSY Value \ +#define MXC_S_GCR_RSTR0_RTC_RESET_DONE \ + (MXC_V_GCR_RSTR0_RTC_RESET_DONE \ + << MXC_F_GCR_RSTR0_RTC_POS) /**< \ + RSTR0_RTC_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_RTC_BUSY \ + ((uint32_t)0x1UL) /**< RSTR0_RTC_BUSY Value \ */ -#define MXC_S_GCR_RSTR0_RTC_BUSY \ - (MXC_V_GCR_RSTR0_RTC_BUSY \ - << MXC_F_GCR_RSTR0_RTC_POS) /**< RSTR0_RTC_BUSY Setting */ +#define MXC_S_GCR_RSTR0_RTC_BUSY \ + (MXC_V_GCR_RSTR0_RTC_BUSY \ + << MXC_F_GCR_RSTR0_RTC_POS) /**< \ + RSTR0_RTC_BUSY \ + Setting */ #define MXC_F_GCR_RSTR0_SRST_POS 29 /**< RSTR0_SRST Position */ -#define MXC_F_GCR_RSTR0_SRST \ - ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SRST_POS)) /**< RSTR0_SRST Mask \ +#define MXC_F_GCR_RSTR0_SRST \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SRST_POS)) /**< RSTR0_SRST Mask \ */ -#define MXC_V_GCR_RSTR0_SRST_RFU \ - ((uint32_t)0x0UL) /**< RSTR0_SRST_RFU Value \ +#define MXC_V_GCR_RSTR0_SRST_RFU \ + ((uint32_t)0x0UL) /**< RSTR0_SRST_RFU Value \ */ -#define MXC_S_GCR_RSTR0_SRST_RFU \ - (MXC_V_GCR_RSTR0_SRST_RFU \ - << MXC_F_GCR_RSTR0_SRST_POS) /**< RSTR0_SRST_RFU Setting */ -#define MXC_V_GCR_RSTR0_SRST_RESET \ +#define MXC_S_GCR_RSTR0_SRST_RFU \ + (MXC_V_GCR_RSTR0_SRST_RFU \ + << MXC_F_GCR_RSTR0_SRST_POS) /**< \ + RSTR0_SRST_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_SRST_RESET \ ((uint32_t)0x1UL) /**< RSTR0_SRST_RESET Value */ -#define MXC_S_GCR_RSTR0_SRST_RESET \ - (MXC_V_GCR_RSTR0_SRST_RESET \ - << MXC_F_GCR_RSTR0_SRST_POS) /**< RSTR0_SRST_RESET Setting */ -#define MXC_V_GCR_RSTR0_SRST_RESET_DONE \ +#define MXC_S_GCR_RSTR0_SRST_RESET \ + (MXC_V_GCR_RSTR0_SRST_RESET \ + << MXC_F_GCR_RSTR0_SRST_POS) /**< \ + RSTR0_SRST_RESET \ + Setting */ +#define MXC_V_GCR_RSTR0_SRST_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_SRST_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_SRST_RESET_DONE \ - (MXC_V_GCR_RSTR0_SRST_RESET_DONE \ - << MXC_F_GCR_RSTR0_SRST_POS) /**< RSTR0_SRST_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_SRST_BUSY \ +#define MXC_S_GCR_RSTR0_SRST_RESET_DONE \ + (MXC_V_GCR_RSTR0_SRST_RESET_DONE \ + << MXC_F_GCR_RSTR0_SRST_POS) /**< \ + RSTR0_SRST_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_SRST_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_SRST_BUSY Value */ -#define MXC_S_GCR_RSTR0_SRST_BUSY \ - (MXC_V_GCR_RSTR0_SRST_BUSY \ - << MXC_F_GCR_RSTR0_SRST_POS) /**< RSTR0_SRST_BUSY Setting */ +#define MXC_S_GCR_RSTR0_SRST_BUSY \ + (MXC_V_GCR_RSTR0_SRST_BUSY \ + << MXC_F_GCR_RSTR0_SRST_POS) /**< \ + RSTR0_SRST_BUSY \ + Setting */ #define MXC_F_GCR_RSTR0_PRST_POS 30 /**< RSTR0_PRST Position */ -#define MXC_F_GCR_RSTR0_PRST \ - ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_PRST_POS)) /**< RSTR0_PRST Mask \ +#define MXC_F_GCR_RSTR0_PRST \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_PRST_POS)) /**< RSTR0_PRST Mask \ */ -#define MXC_V_GCR_RSTR0_PRST_RFU \ - ((uint32_t)0x0UL) /**< RSTR0_PRST_RFU Value \ +#define MXC_V_GCR_RSTR0_PRST_RFU \ + ((uint32_t)0x0UL) /**< RSTR0_PRST_RFU Value \ */ -#define MXC_S_GCR_RSTR0_PRST_RFU \ - (MXC_V_GCR_RSTR0_PRST_RFU \ - << MXC_F_GCR_RSTR0_PRST_POS) /**< RSTR0_PRST_RFU Setting */ -#define MXC_V_GCR_RSTR0_PRST_RESET \ +#define MXC_S_GCR_RSTR0_PRST_RFU \ + (MXC_V_GCR_RSTR0_PRST_RFU \ + << MXC_F_GCR_RSTR0_PRST_POS) /**< \ + RSTR0_PRST_RFU \ + Setting */ +#define MXC_V_GCR_RSTR0_PRST_RESET \ ((uint32_t)0x1UL) /**< RSTR0_PRST_RESET Value */ -#define MXC_S_GCR_RSTR0_PRST_RESET \ - (MXC_V_GCR_RSTR0_PRST_RESET \ - << MXC_F_GCR_RSTR0_PRST_POS) /**< RSTR0_PRST_RESET Setting */ -#define MXC_V_GCR_RSTR0_PRST_RESET_DONE \ +#define MXC_S_GCR_RSTR0_PRST_RESET \ + (MXC_V_GCR_RSTR0_PRST_RESET \ + << MXC_F_GCR_RSTR0_PRST_POS) /**< \ + RSTR0_PRST_RESET \ + Setting */ +#define MXC_V_GCR_RSTR0_PRST_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_PRST_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_PRST_RESET_DONE \ - (MXC_V_GCR_RSTR0_PRST_RESET_DONE \ - << MXC_F_GCR_RSTR0_PRST_POS) /**< RSTR0_PRST_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR0_PRST_BUSY \ +#define MXC_S_GCR_RSTR0_PRST_RESET_DONE \ + (MXC_V_GCR_RSTR0_PRST_RESET_DONE \ + << MXC_F_GCR_RSTR0_PRST_POS) /**< \ + RSTR0_PRST_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_PRST_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_PRST_BUSY Value */ -#define MXC_S_GCR_RSTR0_PRST_BUSY \ - (MXC_V_GCR_RSTR0_PRST_BUSY \ - << MXC_F_GCR_RSTR0_PRST_POS) /**< RSTR0_PRST_BUSY Setting */ +#define MXC_S_GCR_RSTR0_PRST_BUSY \ + (MXC_V_GCR_RSTR0_PRST_BUSY \ + << MXC_F_GCR_RSTR0_PRST_POS) /**< \ + RSTR0_PRST_BUSY \ + Setting */ #define MXC_F_GCR_RSTR0_SYSTEM_POS 31 /**< RSTR0_SYSTEM Position */ -#define MXC_F_GCR_RSTR0_SYSTEM \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_RSTR0_SYSTEM_POS)) /**< RSTR0_SYSTEM Mask */ -#define MXC_V_GCR_RSTR0_SYSTEM_RFU \ +#define MXC_F_GCR_RSTR0_SYSTEM \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SYSTEM_POS)) /**< RSTR0_SYSTEM \ + Mask */ +#define MXC_V_GCR_RSTR0_SYSTEM_RFU \ ((uint32_t)0x0UL) /**< RSTR0_SYSTEM_RFU Value */ -#define MXC_S_GCR_RSTR0_SYSTEM_RFU \ - (MXC_V_GCR_RSTR0_SYSTEM_RFU \ - << MXC_F_GCR_RSTR0_SYSTEM_POS) /**< RSTR0_SYSTEM_RFU Setting */ -#define MXC_V_GCR_RSTR0_SYSTEM_RESET \ +#define MXC_S_GCR_RSTR0_SYSTEM_RFU \ + (MXC_V_GCR_RSTR0_SYSTEM_RFU \ + << MXC_F_GCR_RSTR0_SYSTEM_POS) /**< \ + RSTR0_SYSTEM_RFU \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_SYSTEM_RESET \ ((uint32_t)0x1UL) /**< RSTR0_SYSTEM_RESET Value */ -#define MXC_S_GCR_RSTR0_SYSTEM_RESET \ - (MXC_V_GCR_RSTR0_SYSTEM_RESET \ - << MXC_F_GCR_RSTR0_SYSTEM_POS) /**< RSTR0_SYSTEM_RESET Setting */ -#define MXC_V_GCR_RSTR0_SYSTEM_RESET_DONE \ +#define MXC_S_GCR_RSTR0_SYSTEM_RESET \ + (MXC_V_GCR_RSTR0_SYSTEM_RESET \ + << MXC_F_GCR_RSTR0_SYSTEM_POS) /**< \ + RSTR0_SYSTEM_RESET \ + Setting \ + */ +#define MXC_V_GCR_RSTR0_SYSTEM_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR0_SYSTEM_RESET_DONE Value */ -#define MXC_S_GCR_RSTR0_SYSTEM_RESET_DONE \ - (MXC_V_GCR_RSTR0_SYSTEM_RESET_DONE \ - << MXC_F_GCR_RSTR0_SYSTEM_POS) /**< RSTR0_SYSTEM_RESET_DONE Setting \ +#define MXC_S_GCR_RSTR0_SYSTEM_RESET_DONE \ + (MXC_V_GCR_RSTR0_SYSTEM_RESET_DONE \ + << MXC_F_GCR_RSTR0_SYSTEM_POS) /**< RSTR0_SYSTEM_RESET_DONE Setting \ */ -#define MXC_V_GCR_RSTR0_SYSTEM_BUSY \ +#define MXC_V_GCR_RSTR0_SYSTEM_BUSY \ ((uint32_t)0x1UL) /**< RSTR0_SYSTEM_BUSY Value */ -#define MXC_S_GCR_RSTR0_SYSTEM_BUSY \ - (MXC_V_GCR_RSTR0_SYSTEM_BUSY \ - << MXC_F_GCR_RSTR0_SYSTEM_POS) /**< RSTR0_SYSTEM_BUSY Setting */ +#define MXC_S_GCR_RSTR0_SYSTEM_BUSY \ + (MXC_V_GCR_RSTR0_SYSTEM_BUSY \ + << MXC_F_GCR_RSTR0_SYSTEM_POS) /**< \ + RSTR0_SYSTEM_BUSY \ + Setting \ + */ /** * Clock Control. */ #define MXC_F_GCR_CLKCN_PSC_POS 6 /**< CLKCN_PSC Position */ -#define MXC_F_GCR_CLKCN_PSC \ +#define MXC_F_GCR_CLKCN_PSC \ ((uint32_t)(0x7UL << MXC_F_GCR_CLKCN_PSC_POS)) /**< CLKCN_PSC Mask */ -#define MXC_V_GCR_CLKCN_PSC_DIV1 \ - ((uint32_t)0x0UL) /**< CLKCN_PSC_DIV1 Value \ +#define MXC_V_GCR_CLKCN_PSC_DIV1 \ + ((uint32_t)0x0UL) /**< CLKCN_PSC_DIV1 Value \ */ -#define MXC_S_GCR_CLKCN_PSC_DIV1 \ - (MXC_V_GCR_CLKCN_PSC_DIV1 \ - << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV1 Setting */ -#define MXC_V_GCR_CLKCN_PSC_DIV2 \ - ((uint32_t)0x1UL) /**< CLKCN_PSC_DIV2 Value \ +#define MXC_S_GCR_CLKCN_PSC_DIV1 \ + (MXC_V_GCR_CLKCN_PSC_DIV1 \ + << MXC_F_GCR_CLKCN_PSC_POS) /**< \ + CLKCN_PSC_DIV1 \ + Setting */ +#define MXC_V_GCR_CLKCN_PSC_DIV2 \ + ((uint32_t)0x1UL) /**< CLKCN_PSC_DIV2 Value \ */ -#define MXC_S_GCR_CLKCN_PSC_DIV2 \ - (MXC_V_GCR_CLKCN_PSC_DIV2 \ - << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV2 Setting */ -#define MXC_V_GCR_CLKCN_PSC_DIV4 \ - ((uint32_t)0x2UL) /**< CLKCN_PSC_DIV4 Value \ +#define MXC_S_GCR_CLKCN_PSC_DIV2 \ + (MXC_V_GCR_CLKCN_PSC_DIV2 \ + << MXC_F_GCR_CLKCN_PSC_POS) /**< \ + CLKCN_PSC_DIV2 \ + Setting */ +#define MXC_V_GCR_CLKCN_PSC_DIV4 \ + ((uint32_t)0x2UL) /**< CLKCN_PSC_DIV4 Value \ */ -#define MXC_S_GCR_CLKCN_PSC_DIV4 \ - (MXC_V_GCR_CLKCN_PSC_DIV4 \ - << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV4 Setting */ -#define MXC_V_GCR_CLKCN_PSC_DIV8 \ - ((uint32_t)0x3UL) /**< CLKCN_PSC_DIV8 Value \ +#define MXC_S_GCR_CLKCN_PSC_DIV4 \ + (MXC_V_GCR_CLKCN_PSC_DIV4 \ + << MXC_F_GCR_CLKCN_PSC_POS) /**< \ + CLKCN_PSC_DIV4 \ + Setting */ +#define MXC_V_GCR_CLKCN_PSC_DIV8 \ + ((uint32_t)0x3UL) /**< CLKCN_PSC_DIV8 Value \ */ -#define MXC_S_GCR_CLKCN_PSC_DIV8 \ - (MXC_V_GCR_CLKCN_PSC_DIV8 \ - << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV8 Setting */ -#define MXC_V_GCR_CLKCN_PSC_DIV16 \ +#define MXC_S_GCR_CLKCN_PSC_DIV8 \ + (MXC_V_GCR_CLKCN_PSC_DIV8 \ + << MXC_F_GCR_CLKCN_PSC_POS) /**< \ + CLKCN_PSC_DIV8 \ + Setting */ +#define MXC_V_GCR_CLKCN_PSC_DIV16 \ ((uint32_t)0x4UL) /**< CLKCN_PSC_DIV16 Value */ -#define MXC_S_GCR_CLKCN_PSC_DIV16 \ - (MXC_V_GCR_CLKCN_PSC_DIV16 \ - << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV16 Setting */ -#define MXC_V_GCR_CLKCN_PSC_DIV32 \ +#define MXC_S_GCR_CLKCN_PSC_DIV16 \ + (MXC_V_GCR_CLKCN_PSC_DIV16 \ + << MXC_F_GCR_CLKCN_PSC_POS) /**< \ + CLKCN_PSC_DIV16 \ + Setting */ +#define MXC_V_GCR_CLKCN_PSC_DIV32 \ ((uint32_t)0x5UL) /**< CLKCN_PSC_DIV32 Value */ -#define MXC_S_GCR_CLKCN_PSC_DIV32 \ - (MXC_V_GCR_CLKCN_PSC_DIV32 \ - << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV32 Setting */ -#define MXC_V_GCR_CLKCN_PSC_DIV64 \ +#define MXC_S_GCR_CLKCN_PSC_DIV32 \ + (MXC_V_GCR_CLKCN_PSC_DIV32 \ + << MXC_F_GCR_CLKCN_PSC_POS) /**< \ + CLKCN_PSC_DIV32 \ + Setting */ +#define MXC_V_GCR_CLKCN_PSC_DIV64 \ ((uint32_t)0x6UL) /**< CLKCN_PSC_DIV64 Value */ -#define MXC_S_GCR_CLKCN_PSC_DIV64 \ - (MXC_V_GCR_CLKCN_PSC_DIV64 \ - << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV64 Setting */ -#define MXC_V_GCR_CLKCN_PSC_DIV128 \ +#define MXC_S_GCR_CLKCN_PSC_DIV64 \ + (MXC_V_GCR_CLKCN_PSC_DIV64 \ + << MXC_F_GCR_CLKCN_PSC_POS) /**< \ + CLKCN_PSC_DIV64 \ + Setting */ +#define MXC_V_GCR_CLKCN_PSC_DIV128 \ ((uint32_t)0x7UL) /**< CLKCN_PSC_DIV128 Value */ -#define MXC_S_GCR_CLKCN_PSC_DIV128 \ - (MXC_V_GCR_CLKCN_PSC_DIV128 \ - << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV128 Setting */ +#define MXC_S_GCR_CLKCN_PSC_DIV128 \ + (MXC_V_GCR_CLKCN_PSC_DIV128 \ + << MXC_F_GCR_CLKCN_PSC_POS) /**< \ + CLKCN_PSC_DIV128 \ + Setting */ #define MXC_F_GCR_CLKCN_CLKSEL_POS 9 /**< CLKCN_CLKSEL Position */ -#define MXC_F_GCR_CLKCN_CLKSEL \ - ((uint32_t)(0x7UL \ - << MXC_F_GCR_CLKCN_CLKSEL_POS)) /**< CLKCN_CLKSEL Mask */ -#define MXC_V_GCR_CLKCN_CLKSEL_HIRC \ +#define MXC_F_GCR_CLKCN_CLKSEL \ + ((uint32_t)(0x7UL << MXC_F_GCR_CLKCN_CLKSEL_POS)) /**< CLKCN_CLKSEL \ + Mask */ +#define MXC_V_GCR_CLKCN_CLKSEL_HIRC \ ((uint32_t)0x0UL) /**< CLKCN_CLKSEL_HIRC Value */ -#define MXC_S_GCR_CLKCN_CLKSEL_HIRC \ - (MXC_V_GCR_CLKCN_CLKSEL_HIRC \ - << MXC_F_GCR_CLKCN_CLKSEL_POS) /**< CLKCN_CLKSEL_HIRC Setting */ -#define MXC_V_GCR_CLKCN_CLKSEL_NANORING \ +#define MXC_S_GCR_CLKCN_CLKSEL_HIRC \ + (MXC_V_GCR_CLKCN_CLKSEL_HIRC \ + << MXC_F_GCR_CLKCN_CLKSEL_POS) /**< \ + CLKCN_CLKSEL_HIRC \ + Setting \ + */ +#define MXC_V_GCR_CLKCN_CLKSEL_NANORING \ ((uint32_t)0x3UL) /**< CLKCN_CLKSEL_NANORING Value */ -#define MXC_S_GCR_CLKCN_CLKSEL_NANORING \ - (MXC_V_GCR_CLKCN_CLKSEL_NANORING \ - << MXC_F_GCR_CLKCN_CLKSEL_POS) /**< CLKCN_CLKSEL_NANORING Setting */ -#define MXC_V_GCR_CLKCN_CLKSEL_HFXIN \ +#define MXC_S_GCR_CLKCN_CLKSEL_NANORING \ + (MXC_V_GCR_CLKCN_CLKSEL_NANORING \ + << MXC_F_GCR_CLKCN_CLKSEL_POS) /**< \ + CLKCN_CLKSEL_NANORING \ + Setting \ + */ +#define MXC_V_GCR_CLKCN_CLKSEL_HFXIN \ ((uint32_t)0x6UL) /**< CLKCN_CLKSEL_HFXIN Value */ -#define MXC_S_GCR_CLKCN_CLKSEL_HFXIN \ - (MXC_V_GCR_CLKCN_CLKSEL_HFXIN \ - << MXC_F_GCR_CLKCN_CLKSEL_POS) /**< CLKCN_CLKSEL_HFXIN Setting */ +#define MXC_S_GCR_CLKCN_CLKSEL_HFXIN \ + (MXC_V_GCR_CLKCN_CLKSEL_HFXIN \ + << MXC_F_GCR_CLKCN_CLKSEL_POS) /**< \ + CLKCN_CLKSEL_HFXIN \ + Setting \ + */ #define MXC_F_GCR_CLKCN_CKRDY_POS 13 /**< CLKCN_CKRDY Position */ #define MXC_F_GCR_CLKCN_CKRDY \ - ((uint32_t)( \ - 0x1UL << MXC_F_GCR_CLKCN_CKRDY_POS)) /**< CLKCN_CKRDY Mask */ -#define MXC_V_GCR_CLKCN_CKRDY_BUSY \ + ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_CKRDY_POS)) /**< CLKCN_CKRDY Mask \ + */ +#define MXC_V_GCR_CLKCN_CKRDY_BUSY \ ((uint32_t)0x0UL) /**< CLKCN_CKRDY_BUSY Value */ -#define MXC_S_GCR_CLKCN_CKRDY_BUSY \ - (MXC_V_GCR_CLKCN_CKRDY_BUSY \ - << MXC_F_GCR_CLKCN_CKRDY_POS) /**< CLKCN_CKRDY_BUSY Setting */ -#define MXC_V_GCR_CLKCN_CKRDY_READY \ +#define MXC_S_GCR_CLKCN_CKRDY_BUSY \ + (MXC_V_GCR_CLKCN_CKRDY_BUSY \ + << MXC_F_GCR_CLKCN_CKRDY_POS) /**< \ + CLKCN_CKRDY_BUSY \ + Setting \ + */ +#define MXC_V_GCR_CLKCN_CKRDY_READY \ ((uint32_t)0x1UL) /**< CLKCN_CKRDY_READY Value */ -#define MXC_S_GCR_CLKCN_CKRDY_READY \ - (MXC_V_GCR_CLKCN_CKRDY_READY \ - << MXC_F_GCR_CLKCN_CKRDY_POS) /**< CLKCN_CKRDY_READY Setting */ +#define MXC_S_GCR_CLKCN_CKRDY_READY \ + (MXC_V_GCR_CLKCN_CKRDY_READY \ + << MXC_F_GCR_CLKCN_CKRDY_POS) /**< \ + CLKCN_CKRDY_READY \ + Setting \ + */ #define MXC_F_GCR_CLKCN_X32K_EN_POS 17 /**< CLKCN_X32K_EN Position */ -#define MXC_F_GCR_CLKCN_X32K_EN \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_CLKCN_X32K_EN_POS)) /**< CLKCN_X32K_EN Mask */ -#define MXC_V_GCR_CLKCN_X32K_EN_DIS \ +#define MXC_F_GCR_CLKCN_X32K_EN \ + ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_X32K_EN_POS)) /**< CLKCN_X32K_EN \ + Mask */ +#define MXC_V_GCR_CLKCN_X32K_EN_DIS \ ((uint32_t)0x0UL) /**< CLKCN_X32K_EN_DIS Value */ -#define MXC_S_GCR_CLKCN_X32K_EN_DIS \ - (MXC_V_GCR_CLKCN_X32K_EN_DIS \ - << MXC_F_GCR_CLKCN_X32K_EN_POS) /**< CLKCN_X32K_EN_DIS Setting */ -#define MXC_V_GCR_CLKCN_X32K_EN_EN \ +#define MXC_S_GCR_CLKCN_X32K_EN_DIS \ + (MXC_V_GCR_CLKCN_X32K_EN_DIS \ + << MXC_F_GCR_CLKCN_X32K_EN_POS) /**< \ + CLKCN_X32K_EN_DIS \ + Setting \ + */ +#define MXC_V_GCR_CLKCN_X32K_EN_EN \ ((uint32_t)0x1UL) /**< CLKCN_X32K_EN_EN Value */ -#define MXC_S_GCR_CLKCN_X32K_EN_EN \ - (MXC_V_GCR_CLKCN_X32K_EN_EN \ - << MXC_F_GCR_CLKCN_X32K_EN_POS) /**< CLKCN_X32K_EN_EN Setting */ +#define MXC_S_GCR_CLKCN_X32K_EN_EN \ + (MXC_V_GCR_CLKCN_X32K_EN_EN \ + << MXC_F_GCR_CLKCN_X32K_EN_POS) /**< \ + CLKCN_X32K_EN_EN \ + Setting \ + */ #define MXC_F_GCR_CLKCN_HIRC_EN_POS 18 /**< CLKCN_HIRC_EN Position */ -#define MXC_F_GCR_CLKCN_HIRC_EN \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_CLKCN_HIRC_EN_POS)) /**< CLKCN_HIRC_EN Mask */ -#define MXC_V_GCR_CLKCN_HIRC_EN_DIS \ +#define MXC_F_GCR_CLKCN_HIRC_EN \ + ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_HIRC_EN_POS)) /**< CLKCN_HIRC_EN \ + Mask */ +#define MXC_V_GCR_CLKCN_HIRC_EN_DIS \ ((uint32_t)0x0UL) /**< CLKCN_HIRC_EN_DIS Value */ -#define MXC_S_GCR_CLKCN_HIRC_EN_DIS \ - (MXC_V_GCR_CLKCN_HIRC_EN_DIS \ - << MXC_F_GCR_CLKCN_HIRC_EN_POS) /**< CLKCN_HIRC_EN_DIS Setting */ -#define MXC_V_GCR_CLKCN_HIRC_EN_EN \ +#define MXC_S_GCR_CLKCN_HIRC_EN_DIS \ + (MXC_V_GCR_CLKCN_HIRC_EN_DIS \ + << MXC_F_GCR_CLKCN_HIRC_EN_POS) /**< \ + CLKCN_HIRC_EN_DIS \ + Setting \ + */ +#define MXC_V_GCR_CLKCN_HIRC_EN_EN \ ((uint32_t)0x1UL) /**< CLKCN_HIRC_EN_EN Value */ -#define MXC_S_GCR_CLKCN_HIRC_EN_EN \ - (MXC_V_GCR_CLKCN_HIRC_EN_EN \ - << MXC_F_GCR_CLKCN_HIRC_EN_POS) /**< CLKCN_HIRC_EN_EN Setting */ +#define MXC_S_GCR_CLKCN_HIRC_EN_EN \ + (MXC_V_GCR_CLKCN_HIRC_EN_EN \ + << MXC_F_GCR_CLKCN_HIRC_EN_POS) /**< \ + CLKCN_HIRC_EN_EN \ + Setting \ + */ #define MXC_F_GCR_CLKCN_X32K_RDY_POS 25 /**< CLKCN_X32K_RDY Position */ -#define MXC_F_GCR_CLKCN_X32K_RDY \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_CLKCN_X32K_RDY_POS)) /**< CLKCN_X32K_RDY Mask */ -#define MXC_V_GCR_CLKCN_X32K_RDY_NOT \ +#define MXC_F_GCR_CLKCN_X32K_RDY \ + ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_X32K_RDY_POS)) /**< \ + CLKCN_X32K_RDY \ + Mask */ +#define MXC_V_GCR_CLKCN_X32K_RDY_NOT \ ((uint32_t)0x0UL) /**< CLKCN_X32K_RDY_NOT Value */ -#define MXC_S_GCR_CLKCN_X32K_RDY_NOT \ - (MXC_V_GCR_CLKCN_X32K_RDY_NOT \ - << MXC_F_GCR_CLKCN_X32K_RDY_POS) /**< CLKCN_X32K_RDY_NOT Setting */ -#define MXC_V_GCR_CLKCN_X32K_RDY_READY \ +#define MXC_S_GCR_CLKCN_X32K_RDY_NOT \ + (MXC_V_GCR_CLKCN_X32K_RDY_NOT \ + << MXC_F_GCR_CLKCN_X32K_RDY_POS) /**< \ + CLKCN_X32K_RDY_NOT \ + Setting \ + */ +#define MXC_V_GCR_CLKCN_X32K_RDY_READY \ ((uint32_t)0x1UL) /**< CLKCN_X32K_RDY_READY Value */ -#define MXC_S_GCR_CLKCN_X32K_RDY_READY \ - (MXC_V_GCR_CLKCN_X32K_RDY_READY \ - << MXC_F_GCR_CLKCN_X32K_RDY_POS) /**< CLKCN_X32K_RDY_READY Setting */ +#define MXC_S_GCR_CLKCN_X32K_RDY_READY \ + (MXC_V_GCR_CLKCN_X32K_RDY_READY \ + << MXC_F_GCR_CLKCN_X32K_RDY_POS) /**< \ + CLKCN_X32K_RDY_READY \ + Setting \ + */ #define MXC_F_GCR_CLKCN_HIRC_RDY_POS 26 /**< CLKCN_HIRC_RDY Position */ -#define MXC_F_GCR_CLKCN_HIRC_RDY \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_CLKCN_HIRC_RDY_POS)) /**< CLKCN_HIRC_RDY Mask */ -#define MXC_V_GCR_CLKCN_HIRC_RDY_NOT \ +#define MXC_F_GCR_CLKCN_HIRC_RDY \ + ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_HIRC_RDY_POS)) /**< \ + CLKCN_HIRC_RDY \ + Mask */ +#define MXC_V_GCR_CLKCN_HIRC_RDY_NOT \ ((uint32_t)0x0UL) /**< CLKCN_HIRC_RDY_NOT Value */ -#define MXC_S_GCR_CLKCN_HIRC_RDY_NOT \ - (MXC_V_GCR_CLKCN_HIRC_RDY_NOT \ - << MXC_F_GCR_CLKCN_HIRC_RDY_POS) /**< CLKCN_HIRC_RDY_NOT Setting */ -#define MXC_V_GCR_CLKCN_HIRC_RDY_READY \ +#define MXC_S_GCR_CLKCN_HIRC_RDY_NOT \ + (MXC_V_GCR_CLKCN_HIRC_RDY_NOT \ + << MXC_F_GCR_CLKCN_HIRC_RDY_POS) /**< \ + CLKCN_HIRC_RDY_NOT \ + Setting \ + */ +#define MXC_V_GCR_CLKCN_HIRC_RDY_READY \ ((uint32_t)0x1UL) /**< CLKCN_HIRC_RDY_READY Value */ -#define MXC_S_GCR_CLKCN_HIRC_RDY_READY \ - (MXC_V_GCR_CLKCN_HIRC_RDY_READY \ - << MXC_F_GCR_CLKCN_HIRC_RDY_POS) /**< CLKCN_HIRC_RDY_READY Setting */ +#define MXC_S_GCR_CLKCN_HIRC_RDY_READY \ + (MXC_V_GCR_CLKCN_HIRC_RDY_READY \ + << MXC_F_GCR_CLKCN_HIRC_RDY_POS) /**< \ + CLKCN_HIRC_RDY_READY \ + Setting \ + */ #define MXC_F_GCR_CLKCN_LIRC8K_RDY_POS 29 /**< CLKCN_LIRC8K_RDY Position */ -#define MXC_F_GCR_CLKCN_LIRC8K_RDY \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_CLKCN_LIRC8K_RDY_POS)) /**< CLKCN_LIRC8K_RDY \ +#define MXC_F_GCR_CLKCN_LIRC8K_RDY \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_CLKCN_LIRC8K_RDY_POS)) /**< CLKCN_LIRC8K_RDY \ Mask */ -#define MXC_V_GCR_CLKCN_LIRC8K_RDY_NOT \ +#define MXC_V_GCR_CLKCN_LIRC8K_RDY_NOT \ ((uint32_t)0x0UL) /**< CLKCN_LIRC8K_RDY_NOT Value */ -#define MXC_S_GCR_CLKCN_LIRC8K_RDY_NOT \ - (MXC_V_GCR_CLKCN_LIRC8K_RDY_NOT \ - << MXC_F_GCR_CLKCN_LIRC8K_RDY_POS) /**< CLKCN_LIRC8K_RDY_NOT Setting \ +#define MXC_S_GCR_CLKCN_LIRC8K_RDY_NOT \ + (MXC_V_GCR_CLKCN_LIRC8K_RDY_NOT \ + << MXC_F_GCR_CLKCN_LIRC8K_RDY_POS) /**< CLKCN_LIRC8K_RDY_NOT Setting \ */ -#define MXC_V_GCR_CLKCN_LIRC8K_RDY_READY \ +#define MXC_V_GCR_CLKCN_LIRC8K_RDY_READY \ ((uint32_t)0x1UL) /**< CLKCN_LIRC8K_RDY_READY Value */ -#define MXC_S_GCR_CLKCN_LIRC8K_RDY_READY \ - (MXC_V_GCR_CLKCN_LIRC8K_RDY_READY \ - << MXC_F_GCR_CLKCN_LIRC8K_RDY_POS) /**< CLKCN_LIRC8K_RDY_READY \ +#define MXC_S_GCR_CLKCN_LIRC8K_RDY_READY \ + (MXC_V_GCR_CLKCN_LIRC8K_RDY_READY \ + << MXC_F_GCR_CLKCN_LIRC8K_RDY_POS) /**< CLKCN_LIRC8K_RDY_READY \ Setting */ /** * Power Management. */ #define MXC_F_GCR_PM_MODE_POS 0 /**< PM_MODE Position */ -#define MXC_F_GCR_PM_MODE \ +#define MXC_F_GCR_PM_MODE \ ((uint32_t)(0x7UL << MXC_F_GCR_PM_MODE_POS)) /**< PM_MODE Mask */ -#define MXC_V_GCR_PM_MODE_ACTIVE \ - ((uint32_t)0x0UL) /**< PM_MODE_ACTIVE Value \ +#define MXC_V_GCR_PM_MODE_ACTIVE \ + ((uint32_t)0x0UL) /**< PM_MODE_ACTIVE Value \ */ -#define MXC_S_GCR_PM_MODE_ACTIVE \ - (MXC_V_GCR_PM_MODE_ACTIVE \ - << MXC_F_GCR_PM_MODE_POS) /**< PM_MODE_ACTIVE Setting */ -#define MXC_V_GCR_PM_MODE_SHUTDOWN \ +#define MXC_S_GCR_PM_MODE_ACTIVE \ + (MXC_V_GCR_PM_MODE_ACTIVE << MXC_F_GCR_PM_MODE_POS) /**< \ + PM_MODE_ACTIVE \ + Setting */ +#define MXC_V_GCR_PM_MODE_SHUTDOWN \ ((uint32_t)0x3UL) /**< PM_MODE_SHUTDOWN Value */ -#define MXC_S_GCR_PM_MODE_SHUTDOWN \ - (MXC_V_GCR_PM_MODE_SHUTDOWN \ - << MXC_F_GCR_PM_MODE_POS) /**< PM_MODE_SHUTDOWN Setting */ -#define MXC_V_GCR_PM_MODE_BACKUP \ - ((uint32_t)0x4UL) /**< PM_MODE_BACKUP Value \ +#define MXC_S_GCR_PM_MODE_SHUTDOWN \ + (MXC_V_GCR_PM_MODE_SHUTDOWN \ + << MXC_F_GCR_PM_MODE_POS) /**< \ + PM_MODE_SHUTDOWN \ + Setting */ +#define MXC_V_GCR_PM_MODE_BACKUP \ + ((uint32_t)0x4UL) /**< PM_MODE_BACKUP Value \ */ -#define MXC_S_GCR_PM_MODE_BACKUP \ - (MXC_V_GCR_PM_MODE_BACKUP \ - << MXC_F_GCR_PM_MODE_POS) /**< PM_MODE_BACKUP Setting */ +#define MXC_S_GCR_PM_MODE_BACKUP \ + (MXC_V_GCR_PM_MODE_BACKUP << MXC_F_GCR_PM_MODE_POS) /**< \ + PM_MODE_BACKUP \ + Setting */ #define MXC_F_GCR_PM_GPIOWKEN_POS 4 /**< PM_GPIOWKEN Position */ #define MXC_F_GCR_PM_GPIOWKEN \ - ((uint32_t)( \ - 0x1UL << MXC_F_GCR_PM_GPIOWKEN_POS)) /**< PM_GPIOWKEN Mask */ -#define MXC_V_GCR_PM_GPIOWKEN_DIS \ + ((uint32_t)(0x1UL << MXC_F_GCR_PM_GPIOWKEN_POS)) /**< PM_GPIOWKEN Mask \ + */ +#define MXC_V_GCR_PM_GPIOWKEN_DIS \ ((uint32_t)0x0UL) /**< PM_GPIOWKEN_DIS Value */ -#define MXC_S_GCR_PM_GPIOWKEN_DIS \ - (MXC_V_GCR_PM_GPIOWKEN_DIS \ - << MXC_F_GCR_PM_GPIOWKEN_POS) /**< PM_GPIOWKEN_DIS Setting */ -#define MXC_V_GCR_PM_GPIOWKEN_EN \ - ((uint32_t)0x1UL) /**< PM_GPIOWKEN_EN Value \ +#define MXC_S_GCR_PM_GPIOWKEN_DIS \ + (MXC_V_GCR_PM_GPIOWKEN_DIS \ + << MXC_F_GCR_PM_GPIOWKEN_POS) /**< \ + PM_GPIOWKEN_DIS \ + Setting */ +#define MXC_V_GCR_PM_GPIOWKEN_EN \ + ((uint32_t)0x1UL) /**< PM_GPIOWKEN_EN Value \ */ -#define MXC_S_GCR_PM_GPIOWKEN_EN \ - (MXC_V_GCR_PM_GPIOWKEN_EN \ - << MXC_F_GCR_PM_GPIOWKEN_POS) /**< PM_GPIOWKEN_EN Setting */ +#define MXC_S_GCR_PM_GPIOWKEN_EN \ + (MXC_V_GCR_PM_GPIOWKEN_EN \ + << MXC_F_GCR_PM_GPIOWKEN_POS) /**< \ + PM_GPIOWKEN_EN \ + Setting */ #define MXC_F_GCR_PM_RTCWKEN_POS 5 /**< PM_RTCWKEN Position */ -#define MXC_F_GCR_PM_RTCWKEN \ - ((uint32_t)(0x1UL << MXC_F_GCR_PM_RTCWKEN_POS)) /**< PM_RTCWKEN Mask \ +#define MXC_F_GCR_PM_RTCWKEN \ + ((uint32_t)(0x1UL << MXC_F_GCR_PM_RTCWKEN_POS)) /**< PM_RTCWKEN Mask \ */ -#define MXC_V_GCR_PM_RTCWKEN_DIS \ - ((uint32_t)0x0UL) /**< PM_RTCWKEN_DIS Value \ +#define MXC_V_GCR_PM_RTCWKEN_DIS \ + ((uint32_t)0x0UL) /**< PM_RTCWKEN_DIS Value \ */ -#define MXC_S_GCR_PM_RTCWKEN_DIS \ - (MXC_V_GCR_PM_RTCWKEN_DIS \ - << MXC_F_GCR_PM_RTCWKEN_POS) /**< PM_RTCWKEN_DIS Setting */ +#define MXC_S_GCR_PM_RTCWKEN_DIS \ + (MXC_V_GCR_PM_RTCWKEN_DIS \ + << MXC_F_GCR_PM_RTCWKEN_POS) /**< \ + PM_RTCWKEN_DIS \ + Setting */ #define MXC_V_GCR_PM_RTCWKEN_EN ((uint32_t)0x1UL) /**< PM_RTCWKEN_EN Value */ #define MXC_S_GCR_PM_RTCWKEN_EN \ - (MXC_V_GCR_PM_RTCWKEN_EN \ - << MXC_F_GCR_PM_RTCWKEN_POS) /**< PM_RTCWKEN_EN Setting */ + (MXC_V_GCR_PM_RTCWKEN_EN << MXC_F_GCR_PM_RTCWKEN_POS) /**< \ + PM_RTCWKEN_EN \ + Setting */ #define MXC_F_GCR_PM_HIRCPD_POS 15 /**< PM_HIRCPD Position */ -#define MXC_F_GCR_PM_HIRCPD \ +#define MXC_F_GCR_PM_HIRCPD \ ((uint32_t)(0x1UL << MXC_F_GCR_PM_HIRCPD_POS)) /**< PM_HIRCPD Mask */ -#define MXC_V_GCR_PM_HIRCPD_ACTIVE \ +#define MXC_V_GCR_PM_HIRCPD_ACTIVE \ ((uint32_t)0x0UL) /**< PM_HIRCPD_ACTIVE Value */ -#define MXC_S_GCR_PM_HIRCPD_ACTIVE \ - (MXC_V_GCR_PM_HIRCPD_ACTIVE \ - << MXC_F_GCR_PM_HIRCPD_POS) /**< PM_HIRCPD_ACTIVE Setting */ -#define MXC_V_GCR_PM_HIRCPD_DEEPSLEEP \ +#define MXC_S_GCR_PM_HIRCPD_ACTIVE \ + (MXC_V_GCR_PM_HIRCPD_ACTIVE \ + << MXC_F_GCR_PM_HIRCPD_POS) /**< \ + PM_HIRCPD_ACTIVE \ + Setting */ +#define MXC_V_GCR_PM_HIRCPD_DEEPSLEEP \ ((uint32_t)0x1UL) /**< PM_HIRCPD_DEEPSLEEP Value */ -#define MXC_S_GCR_PM_HIRCPD_DEEPSLEEP \ - (MXC_V_GCR_PM_HIRCPD_DEEPSLEEP \ - << MXC_F_GCR_PM_HIRCPD_POS) /**< PM_HIRCPD_DEEPSLEEP Setting */ +#define MXC_S_GCR_PM_HIRCPD_DEEPSLEEP \ + (MXC_V_GCR_PM_HIRCPD_DEEPSLEEP \ + << MXC_F_GCR_PM_HIRCPD_POS) /**< \ + PM_HIRCPD_DEEPSLEEP \ + Setting \ + */ /** * Peripheral Clock Divider. */ #define MXC_F_GCR_PCKDIV_AONCD_POS 0 /**< PCKDIV_AONCD Position */ -#define MXC_F_GCR_PCKDIV_AONCD \ - ((uint32_t)(0x3UL \ - << MXC_F_GCR_PCKDIV_AONCD_POS)) /**< PCKDIV_AONCD Mask */ -#define MXC_V_GCR_PCKDIV_AONCD_DIV_4 \ +#define MXC_F_GCR_PCKDIV_AONCD \ + ((uint32_t)(0x3UL << MXC_F_GCR_PCKDIV_AONCD_POS)) /**< PCKDIV_AONCD \ + Mask */ +#define MXC_V_GCR_PCKDIV_AONCD_DIV_4 \ ((uint32_t)0x0UL) /**< PCKDIV_AONCD_DIV_4 Value */ -#define MXC_S_GCR_PCKDIV_AONCD_DIV_4 \ - (MXC_V_GCR_PCKDIV_AONCD_DIV_4 \ - << MXC_F_GCR_PCKDIV_AONCD_POS) /**< PCKDIV_AONCD_DIV_4 Setting */ -#define MXC_V_GCR_PCKDIV_AONCD_DIV_8 \ +#define MXC_S_GCR_PCKDIV_AONCD_DIV_4 \ + (MXC_V_GCR_PCKDIV_AONCD_DIV_4 \ + << MXC_F_GCR_PCKDIV_AONCD_POS) /**< \ + PCKDIV_AONCD_DIV_4 \ + Setting \ + */ +#define MXC_V_GCR_PCKDIV_AONCD_DIV_8 \ ((uint32_t)0x1UL) /**< PCKDIV_AONCD_DIV_8 Value */ -#define MXC_S_GCR_PCKDIV_AONCD_DIV_8 \ - (MXC_V_GCR_PCKDIV_AONCD_DIV_8 \ - << MXC_F_GCR_PCKDIV_AONCD_POS) /**< PCKDIV_AONCD_DIV_8 Setting */ -#define MXC_V_GCR_PCKDIV_AONCD_DIV_16 \ +#define MXC_S_GCR_PCKDIV_AONCD_DIV_8 \ + (MXC_V_GCR_PCKDIV_AONCD_DIV_8 \ + << MXC_F_GCR_PCKDIV_AONCD_POS) /**< \ + PCKDIV_AONCD_DIV_8 \ + Setting \ + */ +#define MXC_V_GCR_PCKDIV_AONCD_DIV_16 \ ((uint32_t)0x2UL) /**< PCKDIV_AONCD_DIV_16 Value */ -#define MXC_S_GCR_PCKDIV_AONCD_DIV_16 \ - (MXC_V_GCR_PCKDIV_AONCD_DIV_16 \ - << MXC_F_GCR_PCKDIV_AONCD_POS) /**< PCKDIV_AONCD_DIV_16 Setting */ -#define MXC_V_GCR_PCKDIV_AONCD_DIV_32 \ +#define MXC_S_GCR_PCKDIV_AONCD_DIV_16 \ + (MXC_V_GCR_PCKDIV_AONCD_DIV_16 \ + << MXC_F_GCR_PCKDIV_AONCD_POS) /**< \ + PCKDIV_AONCD_DIV_16 \ + Setting \ + */ +#define MXC_V_GCR_PCKDIV_AONCD_DIV_32 \ ((uint32_t)0x3UL) /**< PCKDIV_AONCD_DIV_32 Value */ -#define MXC_S_GCR_PCKDIV_AONCD_DIV_32 \ - (MXC_V_GCR_PCKDIV_AONCD_DIV_32 \ - << MXC_F_GCR_PCKDIV_AONCD_POS) /**< PCKDIV_AONCD_DIV_32 Setting */ +#define MXC_S_GCR_PCKDIV_AONCD_DIV_32 \ + (MXC_V_GCR_PCKDIV_AONCD_DIV_32 \ + << MXC_F_GCR_PCKDIV_AONCD_POS) /**< \ + PCKDIV_AONCD_DIV_32 \ + Setting \ + */ /** * Peripheral Clock Disable. */ #define MXC_F_GCR_PERCKCN0_GPIO0D_POS 0 /**< PERCKCN0_GPIO0D Position */ -#define MXC_F_GCR_PERCKCN0_GPIO0D \ - ((uint32_t)( \ - 0x1UL << MXC_F_GCR_PERCKCN0_GPIO0D_POS)) /**< PERCKCN0_GPIO0D \ - Mask */ -#define MXC_V_GCR_PERCKCN0_GPIO0D_EN \ +#define MXC_F_GCR_PERCKCN0_GPIO0D \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_PERCKCN0_GPIO0D_POS)) /**< PERCKCN0_GPIO0D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_GPIO0D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_GPIO0D_EN Value */ -#define MXC_S_GCR_PERCKCN0_GPIO0D_EN \ - (MXC_V_GCR_PERCKCN0_GPIO0D_EN \ - << MXC_F_GCR_PERCKCN0_GPIO0D_POS) /**< PERCKCN0_GPIO0D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_GPIO0D_DIS \ +#define MXC_S_GCR_PERCKCN0_GPIO0D_EN \ + (MXC_V_GCR_PERCKCN0_GPIO0D_EN \ + << MXC_F_GCR_PERCKCN0_GPIO0D_POS) /**< \ + PERCKCN0_GPIO0D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_GPIO0D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_GPIO0D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_GPIO0D_DIS \ - (MXC_V_GCR_PERCKCN0_GPIO0D_DIS \ - << MXC_F_GCR_PERCKCN0_GPIO0D_POS) /**< PERCKCN0_GPIO0D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_GPIO0D_DIS \ + (MXC_V_GCR_PERCKCN0_GPIO0D_DIS \ + << MXC_F_GCR_PERCKCN0_GPIO0D_POS) /**< \ + PERCKCN0_GPIO0D_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_DMAD_POS 5 /**< PERCKCN0_DMAD Position */ -#define MXC_F_GCR_PERCKCN0_DMAD \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_PERCKCN0_DMAD_POS)) /**< PERCKCN0_DMAD Mask */ -#define MXC_V_GCR_PERCKCN0_DMAD_EN \ +#define MXC_F_GCR_PERCKCN0_DMAD \ + ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_DMAD_POS)) /**< PERCKCN0_DMAD \ + Mask */ +#define MXC_V_GCR_PERCKCN0_DMAD_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_DMAD_EN Value */ -#define MXC_S_GCR_PERCKCN0_DMAD_EN \ - (MXC_V_GCR_PERCKCN0_DMAD_EN \ - << MXC_F_GCR_PERCKCN0_DMAD_POS) /**< PERCKCN0_DMAD_EN Setting */ -#define MXC_V_GCR_PERCKCN0_DMAD_DIS \ +#define MXC_S_GCR_PERCKCN0_DMAD_EN \ + (MXC_V_GCR_PERCKCN0_DMAD_EN \ + << MXC_F_GCR_PERCKCN0_DMAD_POS) /**< \ + PERCKCN0_DMAD_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_DMAD_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_DMAD_DIS Value */ -#define MXC_S_GCR_PERCKCN0_DMAD_DIS \ - (MXC_V_GCR_PERCKCN0_DMAD_DIS \ - << MXC_F_GCR_PERCKCN0_DMAD_POS) /**< PERCKCN0_DMAD_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_DMAD_DIS \ + (MXC_V_GCR_PERCKCN0_DMAD_DIS \ + << MXC_F_GCR_PERCKCN0_DMAD_POS) /**< \ + PERCKCN0_DMAD_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_SPI0D_POS 6 /**< PERCKCN0_SPI0D Position */ -#define MXC_F_GCR_PERCKCN0_SPI0D \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_PERCKCN0_SPI0D_POS)) /**< PERCKCN0_SPI0D Mask */ -#define MXC_V_GCR_PERCKCN0_SPI0D_EN \ +#define MXC_F_GCR_PERCKCN0_SPI0D \ + ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_SPI0D_POS)) /**< \ + PERCKCN0_SPI0D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_SPI0D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_SPI0D_EN Value */ -#define MXC_S_GCR_PERCKCN0_SPI0D_EN \ - (MXC_V_GCR_PERCKCN0_SPI0D_EN \ - << MXC_F_GCR_PERCKCN0_SPI0D_POS) /**< PERCKCN0_SPI0D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_SPI0D_DIS \ +#define MXC_S_GCR_PERCKCN0_SPI0D_EN \ + (MXC_V_GCR_PERCKCN0_SPI0D_EN \ + << MXC_F_GCR_PERCKCN0_SPI0D_POS) /**< \ + PERCKCN0_SPI0D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_SPI0D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_SPI0D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_SPI0D_DIS \ - (MXC_V_GCR_PERCKCN0_SPI0D_DIS \ - << MXC_F_GCR_PERCKCN0_SPI0D_POS) /**< PERCKCN0_SPI0D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_SPI0D_DIS \ + (MXC_V_GCR_PERCKCN0_SPI0D_DIS \ + << MXC_F_GCR_PERCKCN0_SPI0D_POS) /**< \ + PERCKCN0_SPI0D_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_SPI1D_POS 7 /**< PERCKCN0_SPI1D Position */ -#define MXC_F_GCR_PERCKCN0_SPI1D \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_PERCKCN0_SPI1D_POS)) /**< PERCKCN0_SPI1D Mask */ -#define MXC_V_GCR_PERCKCN0_SPI1D_EN \ +#define MXC_F_GCR_PERCKCN0_SPI1D \ + ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_SPI1D_POS)) /**< \ + PERCKCN0_SPI1D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_SPI1D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_SPI1D_EN Value */ -#define MXC_S_GCR_PERCKCN0_SPI1D_EN \ - (MXC_V_GCR_PERCKCN0_SPI1D_EN \ - << MXC_F_GCR_PERCKCN0_SPI1D_POS) /**< PERCKCN0_SPI1D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_SPI1D_DIS \ +#define MXC_S_GCR_PERCKCN0_SPI1D_EN \ + (MXC_V_GCR_PERCKCN0_SPI1D_EN \ + << MXC_F_GCR_PERCKCN0_SPI1D_POS) /**< \ + PERCKCN0_SPI1D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_SPI1D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_SPI1D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_SPI1D_DIS \ - (MXC_V_GCR_PERCKCN0_SPI1D_DIS \ - << MXC_F_GCR_PERCKCN0_SPI1D_POS) /**< PERCKCN0_SPI1D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_SPI1D_DIS \ + (MXC_V_GCR_PERCKCN0_SPI1D_DIS \ + << MXC_F_GCR_PERCKCN0_SPI1D_POS) /**< \ + PERCKCN0_SPI1D_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_UART0D_POS 9 /**< PERCKCN0_UART0D Position */ -#define MXC_F_GCR_PERCKCN0_UART0D \ - ((uint32_t)( \ - 0x1UL << MXC_F_GCR_PERCKCN0_UART0D_POS)) /**< PERCKCN0_UART0D \ - Mask */ -#define MXC_V_GCR_PERCKCN0_UART0D_EN \ +#define MXC_F_GCR_PERCKCN0_UART0D \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_PERCKCN0_UART0D_POS)) /**< PERCKCN0_UART0D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_UART0D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_UART0D_EN Value */ -#define MXC_S_GCR_PERCKCN0_UART0D_EN \ - (MXC_V_GCR_PERCKCN0_UART0D_EN \ - << MXC_F_GCR_PERCKCN0_UART0D_POS) /**< PERCKCN0_UART0D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_UART0D_DIS \ +#define MXC_S_GCR_PERCKCN0_UART0D_EN \ + (MXC_V_GCR_PERCKCN0_UART0D_EN \ + << MXC_F_GCR_PERCKCN0_UART0D_POS) /**< \ + PERCKCN0_UART0D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_UART0D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_UART0D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_UART0D_DIS \ - (MXC_V_GCR_PERCKCN0_UART0D_DIS \ - << MXC_F_GCR_PERCKCN0_UART0D_POS) /**< PERCKCN0_UART0D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_UART0D_DIS \ + (MXC_V_GCR_PERCKCN0_UART0D_DIS \ + << MXC_F_GCR_PERCKCN0_UART0D_POS) /**< \ + PERCKCN0_UART0D_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_UART1D_POS 10 /**< PERCKCN0_UART1D Position */ -#define MXC_F_GCR_PERCKCN0_UART1D \ - ((uint32_t)( \ - 0x1UL << MXC_F_GCR_PERCKCN0_UART1D_POS)) /**< PERCKCN0_UART1D \ - Mask */ -#define MXC_V_GCR_PERCKCN0_UART1D_EN \ +#define MXC_F_GCR_PERCKCN0_UART1D \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_PERCKCN0_UART1D_POS)) /**< PERCKCN0_UART1D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_UART1D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_UART1D_EN Value */ -#define MXC_S_GCR_PERCKCN0_UART1D_EN \ - (MXC_V_GCR_PERCKCN0_UART1D_EN \ - << MXC_F_GCR_PERCKCN0_UART1D_POS) /**< PERCKCN0_UART1D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_UART1D_DIS \ +#define MXC_S_GCR_PERCKCN0_UART1D_EN \ + (MXC_V_GCR_PERCKCN0_UART1D_EN \ + << MXC_F_GCR_PERCKCN0_UART1D_POS) /**< \ + PERCKCN0_UART1D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_UART1D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_UART1D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_UART1D_DIS \ - (MXC_V_GCR_PERCKCN0_UART1D_DIS \ - << MXC_F_GCR_PERCKCN0_UART1D_POS) /**< PERCKCN0_UART1D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_UART1D_DIS \ + (MXC_V_GCR_PERCKCN0_UART1D_DIS \ + << MXC_F_GCR_PERCKCN0_UART1D_POS) /**< \ + PERCKCN0_UART1D_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_I2C0D_POS 13 /**< PERCKCN0_I2C0D Position */ -#define MXC_F_GCR_PERCKCN0_I2C0D \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_PERCKCN0_I2C0D_POS)) /**< PERCKCN0_I2C0D Mask */ -#define MXC_V_GCR_PERCKCN0_I2C0D_EN \ +#define MXC_F_GCR_PERCKCN0_I2C0D \ + ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_I2C0D_POS)) /**< \ + PERCKCN0_I2C0D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_I2C0D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_I2C0D_EN Value */ -#define MXC_S_GCR_PERCKCN0_I2C0D_EN \ - (MXC_V_GCR_PERCKCN0_I2C0D_EN \ - << MXC_F_GCR_PERCKCN0_I2C0D_POS) /**< PERCKCN0_I2C0D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_I2C0D_DIS \ +#define MXC_S_GCR_PERCKCN0_I2C0D_EN \ + (MXC_V_GCR_PERCKCN0_I2C0D_EN \ + << MXC_F_GCR_PERCKCN0_I2C0D_POS) /**< \ + PERCKCN0_I2C0D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_I2C0D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_I2C0D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_I2C0D_DIS \ - (MXC_V_GCR_PERCKCN0_I2C0D_DIS \ - << MXC_F_GCR_PERCKCN0_I2C0D_POS) /**< PERCKCN0_I2C0D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_I2C0D_DIS \ + (MXC_V_GCR_PERCKCN0_I2C0D_DIS \ + << MXC_F_GCR_PERCKCN0_I2C0D_POS) /**< \ + PERCKCN0_I2C0D_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_T0D_POS 15 /**< PERCKCN0_T0D Position */ -#define MXC_F_GCR_PERCKCN0_T0D \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_PERCKCN0_T0D_POS)) /**< PERCKCN0_T0D Mask */ -#define MXC_V_GCR_PERCKCN0_T0D_EN \ +#define MXC_F_GCR_PERCKCN0_T0D \ + ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_T0D_POS)) /**< PERCKCN0_T0D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_T0D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_T0D_EN Value */ -#define MXC_S_GCR_PERCKCN0_T0D_EN \ - (MXC_V_GCR_PERCKCN0_T0D_EN \ - << MXC_F_GCR_PERCKCN0_T0D_POS) /**< PERCKCN0_T0D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_T0D_DIS \ +#define MXC_S_GCR_PERCKCN0_T0D_EN \ + (MXC_V_GCR_PERCKCN0_T0D_EN \ + << MXC_F_GCR_PERCKCN0_T0D_POS) /**< \ + PERCKCN0_T0D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_T0D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_T0D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_T0D_DIS \ - (MXC_V_GCR_PERCKCN0_T0D_DIS \ - << MXC_F_GCR_PERCKCN0_T0D_POS) /**< PERCKCN0_T0D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_T0D_DIS \ + (MXC_V_GCR_PERCKCN0_T0D_DIS \ + << MXC_F_GCR_PERCKCN0_T0D_POS) /**< \ + PERCKCN0_T0D_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_T1D_POS 16 /**< PERCKCN0_T1D Position */ -#define MXC_F_GCR_PERCKCN0_T1D \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_PERCKCN0_T1D_POS)) /**< PERCKCN0_T1D Mask */ -#define MXC_V_GCR_PERCKCN0_T1D_EN \ +#define MXC_F_GCR_PERCKCN0_T1D \ + ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_T1D_POS)) /**< PERCKCN0_T1D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_T1D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_T1D_EN Value */ -#define MXC_S_GCR_PERCKCN0_T1D_EN \ - (MXC_V_GCR_PERCKCN0_T1D_EN \ - << MXC_F_GCR_PERCKCN0_T1D_POS) /**< PERCKCN0_T1D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_T1D_DIS \ +#define MXC_S_GCR_PERCKCN0_T1D_EN \ + (MXC_V_GCR_PERCKCN0_T1D_EN \ + << MXC_F_GCR_PERCKCN0_T1D_POS) /**< \ + PERCKCN0_T1D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_T1D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_T1D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_T1D_DIS \ - (MXC_V_GCR_PERCKCN0_T1D_DIS \ - << MXC_F_GCR_PERCKCN0_T1D_POS) /**< PERCKCN0_T1D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_T1D_DIS \ + (MXC_V_GCR_PERCKCN0_T1D_DIS \ + << MXC_F_GCR_PERCKCN0_T1D_POS) /**< \ + PERCKCN0_T1D_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_T2D_POS 17 /**< PERCKCN0_T2D Position */ -#define MXC_F_GCR_PERCKCN0_T2D \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_PERCKCN0_T2D_POS)) /**< PERCKCN0_T2D Mask */ -#define MXC_V_GCR_PERCKCN0_T2D_EN \ +#define MXC_F_GCR_PERCKCN0_T2D \ + ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_T2D_POS)) /**< PERCKCN0_T2D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_T2D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_T2D_EN Value */ -#define MXC_S_GCR_PERCKCN0_T2D_EN \ - (MXC_V_GCR_PERCKCN0_T2D_EN \ - << MXC_F_GCR_PERCKCN0_T2D_POS) /**< PERCKCN0_T2D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_T2D_DIS \ +#define MXC_S_GCR_PERCKCN0_T2D_EN \ + (MXC_V_GCR_PERCKCN0_T2D_EN \ + << MXC_F_GCR_PERCKCN0_T2D_POS) /**< \ + PERCKCN0_T2D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_T2D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_T2D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_T2D_DIS \ - (MXC_V_GCR_PERCKCN0_T2D_DIS \ - << MXC_F_GCR_PERCKCN0_T2D_POS) /**< PERCKCN0_T2D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_T2D_DIS \ + (MXC_V_GCR_PERCKCN0_T2D_DIS \ + << MXC_F_GCR_PERCKCN0_T2D_POS) /**< \ + PERCKCN0_T2D_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN0_I2C1D_POS 28 /**< PERCKCN0_I2C1D Position */ -#define MXC_F_GCR_PERCKCN0_I2C1D \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_PERCKCN0_I2C1D_POS)) /**< PERCKCN0_I2C1D Mask */ -#define MXC_V_GCR_PERCKCN0_I2C1D_EN \ +#define MXC_F_GCR_PERCKCN0_I2C1D \ + ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_I2C1D_POS)) /**< \ + PERCKCN0_I2C1D \ + Mask */ +#define MXC_V_GCR_PERCKCN0_I2C1D_EN \ ((uint32_t)0x0UL) /**< PERCKCN0_I2C1D_EN Value */ -#define MXC_S_GCR_PERCKCN0_I2C1D_EN \ - (MXC_V_GCR_PERCKCN0_I2C1D_EN \ - << MXC_F_GCR_PERCKCN0_I2C1D_POS) /**< PERCKCN0_I2C1D_EN Setting */ -#define MXC_V_GCR_PERCKCN0_I2C1D_DIS \ +#define MXC_S_GCR_PERCKCN0_I2C1D_EN \ + (MXC_V_GCR_PERCKCN0_I2C1D_EN \ + << MXC_F_GCR_PERCKCN0_I2C1D_POS) /**< \ + PERCKCN0_I2C1D_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN0_I2C1D_DIS \ ((uint32_t)0x1UL) /**< PERCKCN0_I2C1D_DIS Value */ -#define MXC_S_GCR_PERCKCN0_I2C1D_DIS \ - (MXC_V_GCR_PERCKCN0_I2C1D_DIS \ - << MXC_F_GCR_PERCKCN0_I2C1D_POS) /**< PERCKCN0_I2C1D_DIS Setting */ +#define MXC_S_GCR_PERCKCN0_I2C1D_DIS \ + (MXC_V_GCR_PERCKCN0_I2C1D_DIS \ + << MXC_F_GCR_PERCKCN0_I2C1D_POS) /**< \ + PERCKCN0_I2C1D_DIS \ + Setting \ + */ /** * Memory Clock Control Register. */ #define MXC_F_GCR_MEMCKCN_FWS_POS 0 /**< MEMCKCN_FWS Position */ #define MXC_F_GCR_MEMCKCN_FWS \ - ((uint32_t)( \ - 0x7UL << MXC_F_GCR_MEMCKCN_FWS_POS)) /**< MEMCKCN_FWS Mask */ + ((uint32_t)(0x7UL << MXC_F_GCR_MEMCKCN_FWS_POS)) /**< MEMCKCN_FWS Mask \ + */ #define MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS 8 /**< MEMCKCN_SYSRAM0LS Position */ -#define MXC_F_GCR_MEMCKCN_SYSRAM0LS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS)) /**< MEMCKCN_SYSRAM0LS \ - Mask */ -#define MXC_V_GCR_MEMCKCN_SYSRAM0LS_ACTIVE \ +#define MXC_F_GCR_MEMCKCN_SYSRAM0LS \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS)) /**< \ + MEMCKCN_SYSRAM0LS \ + Mask */ +#define MXC_V_GCR_MEMCKCN_SYSRAM0LS_ACTIVE \ ((uint32_t)0x0UL) /**< MEMCKCN_SYSRAM0LS_ACTIVE Value */ -#define MXC_S_GCR_MEMCKCN_SYSRAM0LS_ACTIVE \ - (MXC_V_GCR_MEMCKCN_SYSRAM0LS_ACTIVE \ - << MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS) /**< MEMCKCN_SYSRAM0LS_ACTIVE \ +#define MXC_S_GCR_MEMCKCN_SYSRAM0LS_ACTIVE \ + (MXC_V_GCR_MEMCKCN_SYSRAM0LS_ACTIVE \ + << MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS) /**< MEMCKCN_SYSRAM0LS_ACTIVE \ Setting */ -#define MXC_V_GCR_MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \ +#define MXC_V_GCR_MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \ ((uint32_t)0x1UL) /**< MEMCKCN_SYSRAM0LS_LIGHT_SLEEP Value */ -#define MXC_S_GCR_MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \ - (MXC_V_GCR_MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \ - << MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS) /**< \ - MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \ +#define MXC_S_GCR_MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \ + (MXC_V_GCR_MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \ + << MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS) /**< \ + MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \ Setting */ #define MXC_F_GCR_MEMCKCN_SYSRAM1LS_POS 9 /**< MEMCKCN_SYSRAM1LS Position */ -#define MXC_F_GCR_MEMCKCN_SYSRAM1LS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_MEMCKCN_SYSRAM1LS_POS)) /**< MEMCKCN_SYSRAM1LS \ - Mask */ -#define MXC_V_GCR_MEMCKCN_SYSRAM1LS_ACTIVE \ +#define MXC_F_GCR_MEMCKCN_SYSRAM1LS \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_MEMCKCN_SYSRAM1LS_POS)) /**< \ + MEMCKCN_SYSRAM1LS \ + Mask */ +#define MXC_V_GCR_MEMCKCN_SYSRAM1LS_ACTIVE \ ((uint32_t)0x0UL) /**< MEMCKCN_SYSRAM1LS_ACTIVE Value */ -#define MXC_S_GCR_MEMCKCN_SYSRAM1LS_ACTIVE \ - (MXC_V_GCR_MEMCKCN_SYSRAM1LS_ACTIVE \ - << MXC_F_GCR_MEMCKCN_SYSRAM1LS_POS) /**< MEMCKCN_SYSRAM1LS_ACTIVE \ +#define MXC_S_GCR_MEMCKCN_SYSRAM1LS_ACTIVE \ + (MXC_V_GCR_MEMCKCN_SYSRAM1LS_ACTIVE \ + << MXC_F_GCR_MEMCKCN_SYSRAM1LS_POS) /**< MEMCKCN_SYSRAM1LS_ACTIVE \ Setting */ -#define MXC_V_GCR_MEMCKCN_SYSRAM1LS_LIGHT_SLEEP \ +#define MXC_V_GCR_MEMCKCN_SYSRAM1LS_LIGHT_SLEEP \ ((uint32_t)0x1UL) /**< MEMCKCN_SYSRAM1LS_LIGHT_SLEEP Value */ -#define MXC_S_GCR_MEMCKCN_SYSRAM1LS_LIGHT_SLEEP \ - (MXC_V_GCR_MEMCKCN_SYSRAM1LS_LIGHT_SLEEP \ - << MXC_F_GCR_MEMCKCN_SYSRAM1LS_POS) /**< \ - MEMCKCN_SYSRAM1LS_LIGHT_SLEEP \ +#define MXC_S_GCR_MEMCKCN_SYSRAM1LS_LIGHT_SLEEP \ + (MXC_V_GCR_MEMCKCN_SYSRAM1LS_LIGHT_SLEEP \ + << MXC_F_GCR_MEMCKCN_SYSRAM1LS_POS) /**< \ + MEMCKCN_SYSRAM1LS_LIGHT_SLEEP \ Setting */ #define MXC_F_GCR_MEMCKCN_SYSRAM2LS_POS 10 /**< MEMCKCN_SYSRAM2LS Position */ -#define MXC_F_GCR_MEMCKCN_SYSRAM2LS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_MEMCKCN_SYSRAM2LS_POS)) /**< MEMCKCN_SYSRAM2LS \ - Mask */ -#define MXC_V_GCR_MEMCKCN_SYSRAM2LS_ACTIVE \ +#define MXC_F_GCR_MEMCKCN_SYSRAM2LS \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_MEMCKCN_SYSRAM2LS_POS)) /**< \ + MEMCKCN_SYSRAM2LS \ + Mask */ +#define MXC_V_GCR_MEMCKCN_SYSRAM2LS_ACTIVE \ ((uint32_t)0x0UL) /**< MEMCKCN_SYSRAM2LS_ACTIVE Value */ -#define MXC_S_GCR_MEMCKCN_SYSRAM2LS_ACTIVE \ - (MXC_V_GCR_MEMCKCN_SYSRAM2LS_ACTIVE \ - << MXC_F_GCR_MEMCKCN_SYSRAM2LS_POS) /**< MEMCKCN_SYSRAM2LS_ACTIVE \ +#define MXC_S_GCR_MEMCKCN_SYSRAM2LS_ACTIVE \ + (MXC_V_GCR_MEMCKCN_SYSRAM2LS_ACTIVE \ + << MXC_F_GCR_MEMCKCN_SYSRAM2LS_POS) /**< MEMCKCN_SYSRAM2LS_ACTIVE \ Setting */ -#define MXC_V_GCR_MEMCKCN_SYSRAM2LS_LIGHT_SLEEP \ +#define MXC_V_GCR_MEMCKCN_SYSRAM2LS_LIGHT_SLEEP \ ((uint32_t)0x1UL) /**< MEMCKCN_SYSRAM2LS_LIGHT_SLEEP Value */ -#define MXC_S_GCR_MEMCKCN_SYSRAM2LS_LIGHT_SLEEP \ - (MXC_V_GCR_MEMCKCN_SYSRAM2LS_LIGHT_SLEEP \ - << MXC_F_GCR_MEMCKCN_SYSRAM2LS_POS) /**< \ - MEMCKCN_SYSRAM2LS_LIGHT_SLEEP \ +#define MXC_S_GCR_MEMCKCN_SYSRAM2LS_LIGHT_SLEEP \ + (MXC_V_GCR_MEMCKCN_SYSRAM2LS_LIGHT_SLEEP \ + << MXC_F_GCR_MEMCKCN_SYSRAM2LS_POS) /**< \ + MEMCKCN_SYSRAM2LS_LIGHT_SLEEP \ Setting */ #define MXC_F_GCR_MEMCKCN_SYSRAM3LS_POS 11 /**< MEMCKCN_SYSRAM3LS Position */ -#define MXC_F_GCR_MEMCKCN_SYSRAM3LS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_MEMCKCN_SYSRAM3LS_POS)) /**< MEMCKCN_SYSRAM3LS \ - Mask */ -#define MXC_V_GCR_MEMCKCN_SYSRAM3LS_ACTIVE \ +#define MXC_F_GCR_MEMCKCN_SYSRAM3LS \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_MEMCKCN_SYSRAM3LS_POS)) /**< \ + MEMCKCN_SYSRAM3LS \ + Mask */ +#define MXC_V_GCR_MEMCKCN_SYSRAM3LS_ACTIVE \ ((uint32_t)0x0UL) /**< MEMCKCN_SYSRAM3LS_ACTIVE Value */ -#define MXC_S_GCR_MEMCKCN_SYSRAM3LS_ACTIVE \ - (MXC_V_GCR_MEMCKCN_SYSRAM3LS_ACTIVE \ - << MXC_F_GCR_MEMCKCN_SYSRAM3LS_POS) /**< MEMCKCN_SYSRAM3LS_ACTIVE \ +#define MXC_S_GCR_MEMCKCN_SYSRAM3LS_ACTIVE \ + (MXC_V_GCR_MEMCKCN_SYSRAM3LS_ACTIVE \ + << MXC_F_GCR_MEMCKCN_SYSRAM3LS_POS) /**< MEMCKCN_SYSRAM3LS_ACTIVE \ Setting */ -#define MXC_V_GCR_MEMCKCN_SYSRAM3LS_LIGHT_SLEEP \ +#define MXC_V_GCR_MEMCKCN_SYSRAM3LS_LIGHT_SLEEP \ ((uint32_t)0x1UL) /**< MEMCKCN_SYSRAM3LS_LIGHT_SLEEP Value */ -#define MXC_S_GCR_MEMCKCN_SYSRAM3LS_LIGHT_SLEEP \ - (MXC_V_GCR_MEMCKCN_SYSRAM3LS_LIGHT_SLEEP \ - << MXC_F_GCR_MEMCKCN_SYSRAM3LS_POS) /**< \ - MEMCKCN_SYSRAM3LS_LIGHT_SLEEP \ +#define MXC_S_GCR_MEMCKCN_SYSRAM3LS_LIGHT_SLEEP \ + (MXC_V_GCR_MEMCKCN_SYSRAM3LS_LIGHT_SLEEP \ + << MXC_F_GCR_MEMCKCN_SYSRAM3LS_POS) /**< \ + MEMCKCN_SYSRAM3LS_LIGHT_SLEEP \ Setting */ #define MXC_F_GCR_MEMCKCN_ICACHELS_POS 12 /**< MEMCKCN_ICACHELS Position */ -#define MXC_F_GCR_MEMCKCN_ICACHELS \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_MEMCKCN_ICACHELS_POS)) /**< MEMCKCN_ICACHELS \ +#define MXC_F_GCR_MEMCKCN_ICACHELS \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_MEMCKCN_ICACHELS_POS)) /**< MEMCKCN_ICACHELS \ Mask */ -#define MXC_V_GCR_MEMCKCN_ICACHELS_ACTIVE \ +#define MXC_V_GCR_MEMCKCN_ICACHELS_ACTIVE \ ((uint32_t)0x0UL) /**< MEMCKCN_ICACHELS_ACTIVE Value */ -#define MXC_S_GCR_MEMCKCN_ICACHELS_ACTIVE \ - (MXC_V_GCR_MEMCKCN_ICACHELS_ACTIVE \ - << MXC_F_GCR_MEMCKCN_ICACHELS_POS) /**< MEMCKCN_ICACHELS_ACTIVE \ +#define MXC_S_GCR_MEMCKCN_ICACHELS_ACTIVE \ + (MXC_V_GCR_MEMCKCN_ICACHELS_ACTIVE \ + << MXC_F_GCR_MEMCKCN_ICACHELS_POS) /**< MEMCKCN_ICACHELS_ACTIVE \ Setting */ -#define MXC_V_GCR_MEMCKCN_ICACHELS_LIGHT_SLEEP \ +#define MXC_V_GCR_MEMCKCN_ICACHELS_LIGHT_SLEEP \ ((uint32_t)0x1UL) /**< MEMCKCN_ICACHELS_LIGHT_SLEEP Value */ -#define MXC_S_GCR_MEMCKCN_ICACHELS_LIGHT_SLEEP \ - (MXC_V_GCR_MEMCKCN_ICACHELS_LIGHT_SLEEP \ - << MXC_F_GCR_MEMCKCN_ICACHELS_POS) /**< MEMCKCN_ICACHELS_LIGHT_SLEEP \ +#define MXC_S_GCR_MEMCKCN_ICACHELS_LIGHT_SLEEP \ + (MXC_V_GCR_MEMCKCN_ICACHELS_LIGHT_SLEEP \ + << MXC_F_GCR_MEMCKCN_ICACHELS_POS) /**< MEMCKCN_ICACHELS_LIGHT_SLEEP \ Setting */ /** * Memory Zeroize Control. */ #define MXC_F_GCR_MEMZCN_SRAM0Z_POS 0 /**< MEMZCN_SRAM0Z Position */ -#define MXC_F_GCR_MEMZCN_SRAM0Z \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_MEMZCN_SRAM0Z_POS)) /**< MEMZCN_SRAM0Z Mask */ -#define MXC_V_GCR_MEMZCN_SRAM0Z_NOP \ +#define MXC_F_GCR_MEMZCN_SRAM0Z \ + ((uint32_t)(0x1UL << MXC_F_GCR_MEMZCN_SRAM0Z_POS)) /**< MEMZCN_SRAM0Z \ + Mask */ +#define MXC_V_GCR_MEMZCN_SRAM0Z_NOP \ ((uint32_t)0x0UL) /**< MEMZCN_SRAM0Z_NOP Value */ -#define MXC_S_GCR_MEMZCN_SRAM0Z_NOP \ - (MXC_V_GCR_MEMZCN_SRAM0Z_NOP \ - << MXC_F_GCR_MEMZCN_SRAM0Z_POS) /**< MEMZCN_SRAM0Z_NOP Setting */ -#define MXC_V_GCR_MEMZCN_SRAM0Z_START \ +#define MXC_S_GCR_MEMZCN_SRAM0Z_NOP \ + (MXC_V_GCR_MEMZCN_SRAM0Z_NOP \ + << MXC_F_GCR_MEMZCN_SRAM0Z_POS) /**< \ + MEMZCN_SRAM0Z_NOP \ + Setting \ + */ +#define MXC_V_GCR_MEMZCN_SRAM0Z_START \ ((uint32_t)0x1UL) /**< MEMZCN_SRAM0Z_START Value */ -#define MXC_S_GCR_MEMZCN_SRAM0Z_START \ - (MXC_V_GCR_MEMZCN_SRAM0Z_START \ - << MXC_F_GCR_MEMZCN_SRAM0Z_POS) /**< MEMZCN_SRAM0Z_START Setting */ +#define MXC_S_GCR_MEMZCN_SRAM0Z_START \ + (MXC_V_GCR_MEMZCN_SRAM0Z_START \ + << MXC_F_GCR_MEMZCN_SRAM0Z_POS) /**< \ + MEMZCN_SRAM0Z_START \ + Setting \ + */ #define MXC_F_GCR_MEMZCN_ICACHEZ_POS 1 /**< MEMZCN_ICACHEZ Position */ -#define MXC_F_GCR_MEMZCN_ICACHEZ \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_MEMZCN_ICACHEZ_POS)) /**< MEMZCN_ICACHEZ Mask */ -#define MXC_V_GCR_MEMZCN_ICACHEZ_NOP \ +#define MXC_F_GCR_MEMZCN_ICACHEZ \ + ((uint32_t)(0x1UL << MXC_F_GCR_MEMZCN_ICACHEZ_POS)) /**< \ + MEMZCN_ICACHEZ \ + Mask */ +#define MXC_V_GCR_MEMZCN_ICACHEZ_NOP \ ((uint32_t)0x0UL) /**< MEMZCN_ICACHEZ_NOP Value */ -#define MXC_S_GCR_MEMZCN_ICACHEZ_NOP \ - (MXC_V_GCR_MEMZCN_ICACHEZ_NOP \ - << MXC_F_GCR_MEMZCN_ICACHEZ_POS) /**< MEMZCN_ICACHEZ_NOP Setting */ -#define MXC_V_GCR_MEMZCN_ICACHEZ_START \ +#define MXC_S_GCR_MEMZCN_ICACHEZ_NOP \ + (MXC_V_GCR_MEMZCN_ICACHEZ_NOP \ + << MXC_F_GCR_MEMZCN_ICACHEZ_POS) /**< \ + MEMZCN_ICACHEZ_NOP \ + Setting \ + */ +#define MXC_V_GCR_MEMZCN_ICACHEZ_START \ ((uint32_t)0x1UL) /**< MEMZCN_ICACHEZ_START Value */ -#define MXC_S_GCR_MEMZCN_ICACHEZ_START \ - (MXC_V_GCR_MEMZCN_ICACHEZ_START \ - << MXC_F_GCR_MEMZCN_ICACHEZ_POS) /**< MEMZCN_ICACHEZ_START Setting */ +#define MXC_S_GCR_MEMZCN_ICACHEZ_START \ + (MXC_V_GCR_MEMZCN_ICACHEZ_START \ + << MXC_F_GCR_MEMZCN_ICACHEZ_POS) /**< \ + MEMZCN_ICACHEZ_START \ + Setting \ + */ /** * System Status Register. */ #define MXC_F_GCR_SYSST_ICECLOCK_POS 0 /**< SYSST_ICECLOCK Position */ -#define MXC_F_GCR_SYSST_ICECLOCK \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_SYSST_ICECLOCK_POS)) /**< SYSST_ICECLOCK Mask */ -#define MXC_V_GCR_SYSST_ICECLOCK_UNLOCKED \ +#define MXC_F_GCR_SYSST_ICECLOCK \ + ((uint32_t)(0x1UL << MXC_F_GCR_SYSST_ICECLOCK_POS)) /**< \ + SYSST_ICECLOCK \ + Mask */ +#define MXC_V_GCR_SYSST_ICECLOCK_UNLOCKED \ ((uint32_t)0x0UL) /**< SYSST_ICECLOCK_UNLOCKED Value */ #define MXC_S_GCR_SYSST_ICECLOCK_UNLOCKED \ (MXC_V_GCR_SYSST_ICECLOCK_UNLOCKED \ << MXC_F_GCR_SYSST_ICECLOCK_POS) /**< SYSST_ICECLOCK_UNLOCKED Setting \ */ -#define MXC_V_GCR_SYSST_ICECLOCK_LOCKED \ +#define MXC_V_GCR_SYSST_ICECLOCK_LOCKED \ ((uint32_t)0x1UL) /**< SYSST_ICECLOCK_LOCKED Value */ -#define MXC_S_GCR_SYSST_ICECLOCK_LOCKED \ - (MXC_V_GCR_SYSST_ICECLOCK_LOCKED \ - << MXC_F_GCR_SYSST_ICECLOCK_POS) /**< SYSST_ICECLOCK_LOCKED Setting \ +#define MXC_S_GCR_SYSST_ICECLOCK_LOCKED \ + (MXC_V_GCR_SYSST_ICECLOCK_LOCKED \ + << MXC_F_GCR_SYSST_ICECLOCK_POS) /**< SYSST_ICECLOCK_LOCKED Setting \ */ #define MXC_F_GCR_SYSST_CODEINTERR_POS 1 /**< SYSST_CODEINTERR Position */ -#define MXC_F_GCR_SYSST_CODEINTERR \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_SYSST_CODEINTERR_POS)) /**< SYSST_CODEINTERR \ +#define MXC_F_GCR_SYSST_CODEINTERR \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_SYSST_CODEINTERR_POS)) /**< SYSST_CODEINTERR \ Mask */ -#define MXC_V_GCR_SYSST_CODEINTERR_NORM \ +#define MXC_V_GCR_SYSST_CODEINTERR_NORM \ ((uint32_t)0x0UL) /**< SYSST_CODEINTERR_NORM Value */ #define MXC_S_GCR_SYSST_CODEINTERR_NORM \ (MXC_V_GCR_SYSST_CODEINTERR_NORM \ << MXC_F_GCR_SYSST_CODEINTERR_POS) /**< SYSST_CODEINTERR_NORM Setting \ */ -#define MXC_V_GCR_SYSST_CODEINTERR_CODE \ +#define MXC_V_GCR_SYSST_CODEINTERR_CODE \ ((uint32_t)0x1UL) /**< SYSST_CODEINTERR_CODE Value */ #define MXC_S_GCR_SYSST_CODEINTERR_CODE \ (MXC_V_GCR_SYSST_CODEINTERR_CODE \ @@ -1213,153 +1525,187 @@ typedef struct { */ #define MXC_F_GCR_SYSST_SCMEMF_POS 5 /**< SYSST_SCMEMF Position */ -#define MXC_F_GCR_SYSST_SCMEMF \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_SYSST_SCMEMF_POS)) /**< SYSST_SCMEMF Mask */ -#define MXC_V_GCR_SYSST_SCMEMF_NORM \ +#define MXC_F_GCR_SYSST_SCMEMF \ + ((uint32_t)(0x1UL << MXC_F_GCR_SYSST_SCMEMF_POS)) /**< SYSST_SCMEMF \ + Mask */ +#define MXC_V_GCR_SYSST_SCMEMF_NORM \ ((uint32_t)0x0UL) /**< SYSST_SCMEMF_NORM Value */ -#define MXC_S_GCR_SYSST_SCMEMF_NORM \ - (MXC_V_GCR_SYSST_SCMEMF_NORM \ - << MXC_F_GCR_SYSST_SCMEMF_POS) /**< SYSST_SCMEMF_NORM Setting */ -#define MXC_V_GCR_SYSST_SCMEMF_MEMORY \ +#define MXC_S_GCR_SYSST_SCMEMF_NORM \ + (MXC_V_GCR_SYSST_SCMEMF_NORM \ + << MXC_F_GCR_SYSST_SCMEMF_POS) /**< \ + SYSST_SCMEMF_NORM \ + Setting \ + */ +#define MXC_V_GCR_SYSST_SCMEMF_MEMORY \ ((uint32_t)0x1UL) /**< SYSST_SCMEMF_MEMORY Value */ -#define MXC_S_GCR_SYSST_SCMEMF_MEMORY \ - (MXC_V_GCR_SYSST_SCMEMF_MEMORY \ - << MXC_F_GCR_SYSST_SCMEMF_POS) /**< SYSST_SCMEMF_MEMORY Setting */ +#define MXC_S_GCR_SYSST_SCMEMF_MEMORY \ + (MXC_V_GCR_SYSST_SCMEMF_MEMORY \ + << MXC_F_GCR_SYSST_SCMEMF_POS) /**< \ + SYSST_SCMEMF_MEMORY \ + Setting \ + */ /** * Reset Register. */ #define MXC_F_GCR_RSTR1_I2C1_POS 0 /**< RSTR1_I2C1 Position */ -#define MXC_F_GCR_RSTR1_I2C1 \ - ((uint32_t)(0x1UL << MXC_F_GCR_RSTR1_I2C1_POS)) /**< RSTR1_I2C1 Mask \ +#define MXC_F_GCR_RSTR1_I2C1 \ + ((uint32_t)(0x1UL << MXC_F_GCR_RSTR1_I2C1_POS)) /**< RSTR1_I2C1 Mask \ */ -#define MXC_V_GCR_RSTR1_I2C1_RESET \ +#define MXC_V_GCR_RSTR1_I2C1_RESET \ ((uint32_t)0x1UL) /**< RSTR1_I2C1_RESET Value */ -#define MXC_S_GCR_RSTR1_I2C1_RESET \ - (MXC_V_GCR_RSTR1_I2C1_RESET \ - << MXC_F_GCR_RSTR1_I2C1_POS) /**< RSTR1_I2C1_RESET Setting */ -#define MXC_V_GCR_RSTR1_I2C1_RESET_DONE \ +#define MXC_S_GCR_RSTR1_I2C1_RESET \ + (MXC_V_GCR_RSTR1_I2C1_RESET \ + << MXC_F_GCR_RSTR1_I2C1_POS) /**< \ + RSTR1_I2C1_RESET \ + Setting */ +#define MXC_V_GCR_RSTR1_I2C1_RESET_DONE \ ((uint32_t)0x0UL) /**< RSTR1_I2C1_RESET_DONE Value */ -#define MXC_S_GCR_RSTR1_I2C1_RESET_DONE \ - (MXC_V_GCR_RSTR1_I2C1_RESET_DONE \ - << MXC_F_GCR_RSTR1_I2C1_POS) /**< RSTR1_I2C1_RESET_DONE Setting */ -#define MXC_V_GCR_RSTR1_I2C1_BUSY \ +#define MXC_S_GCR_RSTR1_I2C1_RESET_DONE \ + (MXC_V_GCR_RSTR1_I2C1_RESET_DONE \ + << MXC_F_GCR_RSTR1_I2C1_POS) /**< \ + RSTR1_I2C1_RESET_DONE \ + Setting \ + */ +#define MXC_V_GCR_RSTR1_I2C1_BUSY \ ((uint32_t)0x1UL) /**< RSTR1_I2C1_BUSY Value */ -#define MXC_S_GCR_RSTR1_I2C1_BUSY \ - (MXC_V_GCR_RSTR1_I2C1_BUSY \ - << MXC_F_GCR_RSTR1_I2C1_POS) /**< RSTR1_I2C1_BUSY Setting */ +#define MXC_S_GCR_RSTR1_I2C1_BUSY \ + (MXC_V_GCR_RSTR1_I2C1_BUSY \ + << MXC_F_GCR_RSTR1_I2C1_POS) /**< \ + RSTR1_I2C1_BUSY \ + Setting */ /** * Peripheral Clock Disable. */ #define MXC_F_GCR_PERCKCN1_FLCD_POS 3 /**< PERCKCN1_FLCD Position */ -#define MXC_F_GCR_PERCKCN1_FLCD \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_PERCKCN1_FLCD_POS)) /**< PERCKCN1_FLCD Mask */ -#define MXC_V_GCR_PERCKCN1_FLCD_EN \ +#define MXC_F_GCR_PERCKCN1_FLCD \ + ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN1_FLCD_POS)) /**< PERCKCN1_FLCD \ + Mask */ +#define MXC_V_GCR_PERCKCN1_FLCD_EN \ ((uint32_t)0x0UL) /**< PERCKCN1_FLCD_EN Value */ -#define MXC_S_GCR_PERCKCN1_FLCD_EN \ - (MXC_V_GCR_PERCKCN1_FLCD_EN \ - << MXC_F_GCR_PERCKCN1_FLCD_POS) /**< PERCKCN1_FLCD_EN Setting */ -#define MXC_V_GCR_PERCKCN1_FLCD_DIS \ +#define MXC_S_GCR_PERCKCN1_FLCD_EN \ + (MXC_V_GCR_PERCKCN1_FLCD_EN \ + << MXC_F_GCR_PERCKCN1_FLCD_POS) /**< \ + PERCKCN1_FLCD_EN \ + Setting \ + */ +#define MXC_V_GCR_PERCKCN1_FLCD_DIS \ ((uint32_t)0x1UL) /**< PERCKCN1_FLCD_DIS Value */ -#define MXC_S_GCR_PERCKCN1_FLCD_DIS \ - (MXC_V_GCR_PERCKCN1_FLCD_DIS \ - << MXC_F_GCR_PERCKCN1_FLCD_POS) /**< PERCKCN1_FLCD_DIS Setting */ +#define MXC_S_GCR_PERCKCN1_FLCD_DIS \ + (MXC_V_GCR_PERCKCN1_FLCD_DIS \ + << MXC_F_GCR_PERCKCN1_FLCD_POS) /**< \ + PERCKCN1_FLCD_DIS \ + Setting \ + */ #define MXC_F_GCR_PERCKCN1_ICACHED_POS 11 /**< PERCKCN1_ICACHED Position */ -#define MXC_F_GCR_PERCKCN1_ICACHED \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_PERCKCN1_ICACHED_POS)) /**< PERCKCN1_ICACHED \ +#define MXC_F_GCR_PERCKCN1_ICACHED \ + ((uint32_t)(0x1UL \ + << MXC_F_GCR_PERCKCN1_ICACHED_POS)) /**< PERCKCN1_ICACHED \ Mask */ -#define MXC_V_GCR_PERCKCN1_ICACHED_EN \ +#define MXC_V_GCR_PERCKCN1_ICACHED_EN \ ((uint32_t)0x0UL) /**< PERCKCN1_ICACHED_EN Value */ -#define MXC_S_GCR_PERCKCN1_ICACHED_EN \ - (MXC_V_GCR_PERCKCN1_ICACHED_EN \ - << MXC_F_GCR_PERCKCN1_ICACHED_POS) /**< PERCKCN1_ICACHED_EN Setting \ +#define MXC_S_GCR_PERCKCN1_ICACHED_EN \ + (MXC_V_GCR_PERCKCN1_ICACHED_EN \ + << MXC_F_GCR_PERCKCN1_ICACHED_POS) /**< PERCKCN1_ICACHED_EN Setting \ */ -#define MXC_V_GCR_PERCKCN1_ICACHED_DIS \ +#define MXC_V_GCR_PERCKCN1_ICACHED_DIS \ ((uint32_t)0x1UL) /**< PERCKCN1_ICACHED_DIS Value */ -#define MXC_S_GCR_PERCKCN1_ICACHED_DIS \ - (MXC_V_GCR_PERCKCN1_ICACHED_DIS \ - << MXC_F_GCR_PERCKCN1_ICACHED_POS) /**< PERCKCN1_ICACHED_DIS Setting \ +#define MXC_S_GCR_PERCKCN1_ICACHED_DIS \ + (MXC_V_GCR_PERCKCN1_ICACHED_DIS \ + << MXC_F_GCR_PERCKCN1_ICACHED_POS) /**< PERCKCN1_ICACHED_DIS Setting \ */ /** * Event Enable Register. */ #define MXC_F_GCR_EVTEN_DMAEVENT_POS 0 /**< EVTEN_DMAEVENT Position */ -#define MXC_F_GCR_EVTEN_DMAEVENT \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_EVTEN_DMAEVENT_POS)) /**< EVTEN_DMAEVENT Mask */ +#define MXC_F_GCR_EVTEN_DMAEVENT \ + ((uint32_t)(0x1UL << MXC_F_GCR_EVTEN_DMAEVENT_POS)) /**< \ + EVTEN_DMAEVENT \ + Mask */ #define MXC_F_GCR_EVTEN_RXEVENT_POS 1 /**< EVTEN_RXEVENT Position */ -#define MXC_F_GCR_EVTEN_RXEVENT \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_EVTEN_RXEVENT_POS)) /**< EVTEN_RXEVENT Mask */ +#define MXC_F_GCR_EVTEN_RXEVENT \ + ((uint32_t)(0x1UL << MXC_F_GCR_EVTEN_RXEVENT_POS)) /**< EVTEN_RXEVENT \ + Mask */ /** * Revision Register. */ #define MXC_F_GCR_REVISION_REVISION_POS 0 /**< REVISION_REVISION Position */ -#define MXC_F_GCR_REVISION_REVISION \ - ((uint32_t)( \ - 0xFFFFUL \ - << MXC_F_GCR_REVISION_REVISION_POS)) /**< REVISION_REVISION \ - Mask */ +#define MXC_F_GCR_REVISION_REVISION \ + ((uint32_t)(0xFFFFUL \ + << MXC_F_GCR_REVISION_REVISION_POS)) /**< \ + REVISION_REVISION \ + Mask */ /** * System Status Interrupt Enable Register. */ #define MXC_F_GCR_SYSSIE_ICEULIE_POS 0 /**< SYSSIE_ICEULIE Position */ -#define MXC_F_GCR_SYSSIE_ICEULIE \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_SYSSIE_ICEULIE_POS)) /**< SYSSIE_ICEULIE Mask */ -#define MXC_V_GCR_SYSSIE_ICEULIE_DIS \ +#define MXC_F_GCR_SYSSIE_ICEULIE \ + ((uint32_t)(0x1UL << MXC_F_GCR_SYSSIE_ICEULIE_POS)) /**< \ + SYSSIE_ICEULIE \ + Mask */ +#define MXC_V_GCR_SYSSIE_ICEULIE_DIS \ ((uint32_t)0x0UL) /**< SYSSIE_ICEULIE_DIS Value */ -#define MXC_S_GCR_SYSSIE_ICEULIE_DIS \ - (MXC_V_GCR_SYSSIE_ICEULIE_DIS \ - << MXC_F_GCR_SYSSIE_ICEULIE_POS) /**< SYSSIE_ICEULIE_DIS Setting */ -#define MXC_V_GCR_SYSSIE_ICEULIE_EN \ +#define MXC_S_GCR_SYSSIE_ICEULIE_DIS \ + (MXC_V_GCR_SYSSIE_ICEULIE_DIS \ + << MXC_F_GCR_SYSSIE_ICEULIE_POS) /**< \ + SYSSIE_ICEULIE_DIS \ + Setting \ + */ +#define MXC_V_GCR_SYSSIE_ICEULIE_EN \ ((uint32_t)0x1UL) /**< SYSSIE_ICEULIE_EN Value */ -#define MXC_S_GCR_SYSSIE_ICEULIE_EN \ - (MXC_V_GCR_SYSSIE_ICEULIE_EN \ - << MXC_F_GCR_SYSSIE_ICEULIE_POS) /**< SYSSIE_ICEULIE_EN Setting */ +#define MXC_S_GCR_SYSSIE_ICEULIE_EN \ + (MXC_V_GCR_SYSSIE_ICEULIE_EN \ + << MXC_F_GCR_SYSSIE_ICEULIE_POS) /**< \ + SYSSIE_ICEULIE_EN \ + Setting \ + */ #define MXC_F_GCR_SYSSIE_CIEIE_POS 1 /**< SYSSIE_CIEIE Position */ -#define MXC_F_GCR_SYSSIE_CIEIE \ - ((uint32_t)(0x1UL \ - << MXC_F_GCR_SYSSIE_CIEIE_POS)) /**< SYSSIE_CIEIE Mask */ -#define MXC_V_GCR_SYSSIE_CIEIE_DIS \ +#define MXC_F_GCR_SYSSIE_CIEIE \ + ((uint32_t)(0x1UL << MXC_F_GCR_SYSSIE_CIEIE_POS)) /**< SYSSIE_CIEIE \ + Mask */ +#define MXC_V_GCR_SYSSIE_CIEIE_DIS \ ((uint32_t)0x0UL) /**< SYSSIE_CIEIE_DIS Value */ -#define MXC_S_GCR_SYSSIE_CIEIE_DIS \ - (MXC_V_GCR_SYSSIE_CIEIE_DIS \ - << MXC_F_GCR_SYSSIE_CIEIE_POS) /**< SYSSIE_CIEIE_DIS Setting */ -#define MXC_V_GCR_SYSSIE_CIEIE_EN \ +#define MXC_S_GCR_SYSSIE_CIEIE_DIS \ + (MXC_V_GCR_SYSSIE_CIEIE_DIS \ + << MXC_F_GCR_SYSSIE_CIEIE_POS) /**< \ + SYSSIE_CIEIE_DIS \ + Setting \ + */ +#define MXC_V_GCR_SYSSIE_CIEIE_EN \ ((uint32_t)0x1UL) /**< SYSSIE_CIEIE_EN Value */ -#define MXC_S_GCR_SYSSIE_CIEIE_EN \ - (MXC_V_GCR_SYSSIE_CIEIE_EN \ - << MXC_F_GCR_SYSSIE_CIEIE_POS) /**< SYSSIE_CIEIE_EN Setting */ +#define MXC_S_GCR_SYSSIE_CIEIE_EN \ + (MXC_V_GCR_SYSSIE_CIEIE_EN \ + << MXC_F_GCR_SYSSIE_CIEIE_POS) /**< \ + SYSSIE_CIEIE_EN \ + Setting \ + */ #define MXC_F_GCR_SYSSIE_SCMFIE_POS 5 /**< SYSSIE_SCMFIE Position */ -#define MXC_F_GCR_SYSSIE_SCMFIE \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_GCR_SYSSIE_SCMFIE_POS)) /**< SYSSIE_SCMFIE Mask */ -#define MXC_V_GCR_SYSSIE_SCMFIE_DIS \ +#define MXC_F_GCR_SYSSIE_SCMFIE \ + ((uint32_t)(0x1UL << MXC_F_GCR_SYSSIE_SCMFIE_POS)) /**< SYSSIE_SCMFIE \ + Mask */ +#define MXC_V_GCR_SYSSIE_SCMFIE_DIS \ ((uint32_t)0x0UL) /**< SYSSIE_SCMFIE_DIS Value */ -#define MXC_S_GCR_SYSSIE_SCMFIE_DIS \ - (MXC_V_GCR_SYSSIE_SCMFIE_DIS \ - << MXC_F_GCR_SYSSIE_SCMFIE_POS) /**< SYSSIE_SCMFIE_DIS Setting */ -#define MXC_V_GCR_SYSSIE_SCMFIE_EN \ +#define MXC_S_GCR_SYSSIE_SCMFIE_DIS \ + (MXC_V_GCR_SYSSIE_SCMFIE_DIS \ + << MXC_F_GCR_SYSSIE_SCMFIE_POS) /**< \ + SYSSIE_SCMFIE_DIS \ + Setting \ + */ +#define MXC_V_GCR_SYSSIE_SCMFIE_EN \ ((uint32_t)0x1UL) /**< SYSSIE_SCMFIE_EN Value */ -#define MXC_S_GCR_SYSSIE_SCMFIE_EN \ - (MXC_V_GCR_SYSSIE_SCMFIE_EN \ - << MXC_F_GCR_SYSSIE_SCMFIE_POS) /**< SYSSIE_SCMFIE_EN Setting */ +#define MXC_S_GCR_SYSSIE_SCMFIE_EN \ + (MXC_V_GCR_SYSSIE_SCMFIE_EN \ + << MXC_F_GCR_SYSSIE_SCMFIE_POS) /**< \ + SYSSIE_SCMFIE_EN \ + Setting \ + */ #endif /* _GCR_REGS_H_ */ diff --git a/chip/max32660/gpio_chip.c b/chip/max32660/gpio_chip.c index 5fe38cd657..b6deaa9111 100644 --- a/chip/max32660/gpio_chip.c +++ b/chip/max32660/gpio_chip.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,25 +6,25 @@ /* MAX32660 GPIO module for Chrome EC */ #include "clock.h" -#include "console.h" #include "common.h" +#include "console.h" #include "gpio.h" +#include "gpio_regs.h" #include "hooks.h" +#include "registers.h" #include "switch.h" #include "task.h" #include "timer.h" #include "util.h" -#include "registers.h" -#include "gpio_regs.h" #define CPRINTF(format, args...) cprintf(CC_GPIO, format, ##args) #define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) /* 0-terminated list of GPIO base addresses */ -static mxc_gpio_regs_t *gpio_bases[] = {MXC_GPIO0, 0}; +static mxc_gpio_regs_t *gpio_bases[] = { MXC_GPIO0, 0 }; void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) + enum gpio_alternate_func func) { mxc_gpio_regs_t *gpio = MXC_GPIO_GET_GPIO(port); @@ -42,7 +42,7 @@ void gpio_set_alternate_function(uint32_t port, uint32_t mask, gpio->en1_set = mask; break; default: - /* Default as input */ + /* Default as input */ gpio->out_en_clr = mask; gpio->en_set = mask; gpio->en1_clr = mask; @@ -184,7 +184,7 @@ void gpio_pre_init(void) /* Use as GPIO, not alternate function */ gpio_set_alternate_function(g->port, g->mask, - GPIO_ALT_FUNC_NONE); + GPIO_ALT_FUNC_NONE); /* Set up GPIO based on flags */ gpio_set_flags_by_mask(g->port, g->mask, flags); @@ -194,8 +194,8 @@ void gpio_pre_init(void) static void gpio_init(void) { /* - * Enable global GPIO0 Port interrupt. Note that interrupts still need to be - * enabled at the per pin level. + * Enable global GPIO0 Port interrupt. Note that interrupts still need + * to be enabled at the per pin level. */ task_enable_irq(EC_GPIO0_IRQn); } @@ -227,13 +227,13 @@ static void gpio_interrupt(int port, uint32_t mis) * Handlers for each GPIO port. Read the interrupt status, call the common GPIO * interrupt handler and clear the GPIO hardware interrupt status. */ -#define GPIO_IRQ_FUNC(irqfunc, gpiobase) \ - void irqfunc(void) \ - { \ - mxc_gpio_regs_t *gpio = MXC_GPIO_GET_GPIO(gpiobase); \ - uint32_t mis = gpio->int_stat; \ - gpio_interrupt(gpiobase, mis); \ - gpio->int_clr = mis; \ +#define GPIO_IRQ_FUNC(irqfunc, gpiobase) \ + static void irqfunc(void) \ + { \ + mxc_gpio_regs_t *gpio = MXC_GPIO_GET_GPIO(gpiobase); \ + uint32_t mis = gpio->int_stat; \ + gpio_interrupt(gpiobase, mis); \ + gpio->int_clr = mis; \ } GPIO_IRQ_FUNC(__gpio_0_interrupt, PORT_0); diff --git a/chip/max32660/gpio_regs.h b/chip/max32660/gpio_regs.h index 1c6fcf7a71..70b706b2c0 100644 --- a/chip/max32660/gpio_regs.h +++ b/chip/max32660/gpio_regs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -40,65 +40,65 @@ * Structure type to access the GPIO Registers. */ typedef struct { - __IO uint32_t en; /**< \b 0x00:<\tt> GPIO EN Register */ + __IO uint32_t en; /**< \b 0x00:<\tt> GPIO EN Register */ __IO uint32_t en_set; /**< \b 0x04:<\tt> GPIO EN_SET Register */ __IO uint32_t en_clr; /**< \b 0x08:<\tt> GPIO EN_CLR Register */ __IO uint32_t out_en; /**< \b 0x0C:<\tt> GPIO OUT_EN Register */ - __IO uint32_t - out_en_set; /**< \b 0x10:<\tt> GPIO OUT_EN_SET Register */ - __IO uint32_t - out_en_clr; /**< \b 0x14:<\tt> GPIO OUT_EN_CLR Register */ - __IO uint32_t out; /**< \b 0x18:<\tt> GPIO OUT Register */ + __IO uint32_t out_en_set; /**< \b 0x10:<\tt> GPIO OUT_EN_SET + Register */ + __IO uint32_t out_en_clr; /**< \b 0x14:<\tt> GPIO OUT_EN_CLR + Register */ + __IO uint32_t out; /**< \b 0x18:<\tt> GPIO OUT Register */ __O uint32_t out_set; /**< \b 0x1C:<\tt> GPIO OUT_SET Register */ __O uint32_t out_clr; /**< \b 0x20:<\tt> GPIO OUT_CLR Register */ - __I uint32_t in; /**< \b 0x24:<\tt> GPIO IN Register */ + __I uint32_t in; /**< \b 0x24:<\tt> GPIO IN Register */ __IO uint32_t int_mod; /**< \b 0x28:<\tt> GPIO INT_MOD Register */ __IO uint32_t int_pol; /**< \b 0x2C:<\tt> GPIO INT_POL Register */ __R uint32_t rsv_0x30; __IO uint32_t int_en; /**< \b 0x34:<\tt> GPIO INT_EN Register */ - __IO uint32_t - int_en_set; /**< \b 0x38:<\tt> GPIO INT_EN_SET Register */ - __IO uint32_t - int_en_clr; /**< \b 0x3C:<\tt> GPIO INT_EN_CLR Register */ + __IO uint32_t int_en_set; /**< \b 0x38:<\tt> GPIO INT_EN_SET + Register */ + __IO uint32_t int_en_clr; /**< \b 0x3C:<\tt> GPIO INT_EN_CLR + Register */ __I uint32_t int_stat; /**< \b 0x40:<\tt> GPIO INT_STAT Register */ __R uint32_t rsv_0x44; __IO uint32_t int_clr; /**< \b 0x48:<\tt> GPIO INT_CLR Register */ __IO uint32_t wake_en; /**< \b 0x4C:<\tt> GPIO WAKE_EN Register */ - __IO uint32_t - wake_en_set; /**< \b 0x50:<\tt> GPIO WAKE_EN_SET Register */ - __IO uint32_t - wake_en_clr; /**< \b 0x54:<\tt> GPIO WAKE_EN_CLR Register */ + __IO uint32_t wake_en_set; /**< \b 0x50:<\tt> GPIO WAKE_EN_SET + Register */ + __IO uint32_t wake_en_clr; /**< \b 0x54:<\tt> GPIO WAKE_EN_CLR + Register */ __R uint32_t rsv_0x58; __IO uint32_t int_dual_edge; /**< \b 0x5C:<\tt> GPIO INT_DUAL_EDGE Register */ __IO uint32_t pad_cfg1; /**< \b 0x60:<\tt> GPIO PAD_CFG1 Register */ __IO uint32_t pad_cfg2; /**< \b 0x64:<\tt> GPIO PAD_CFG2 Register */ - __IO uint32_t en1; /**< \b 0x68:<\tt> GPIO EN1 Register */ - __IO uint32_t en1_set; /**< \b 0x6C:<\tt> GPIO EN1_SET Register */ - __IO uint32_t en1_clr; /**< \b 0x70:<\tt> GPIO EN1_CLR Register */ - __IO uint32_t en2; /**< \b 0x74:<\tt> GPIO EN2 Register */ - __IO uint32_t en2_set; /**< \b 0x78:<\tt> GPIO EN2_SET Register */ - __IO uint32_t en2_clr; /**< \b 0x7C:<\tt> GPIO EN2_CLR Register */ + __IO uint32_t en1; /**< \b 0x68:<\tt> GPIO EN1 Register */ + __IO uint32_t en1_set; /**< \b 0x6C:<\tt> GPIO EN1_SET Register */ + __IO uint32_t en1_clr; /**< \b 0x70:<\tt> GPIO EN1_CLR Register */ + __IO uint32_t en2; /**< \b 0x74:<\tt> GPIO EN2 Register */ + __IO uint32_t en2_set; /**< \b 0x78:<\tt> GPIO EN2_SET Register */ + __IO uint32_t en2_clr; /**< \b 0x7C:<\tt> GPIO EN2_CLR Register */ __R uint32_t rsv_0x80_0xa7[10]; - __IO uint32_t is; /**< \b 0xA8:<\tt> GPIO IS Register */ - __IO uint32_t sr; /**< \b 0xAC:<\tt> GPIO SR Register */ - __IO uint32_t ds; /**< \b 0xB0:<\tt> GPIO DS Register */ + __IO uint32_t is; /**< \b 0xA8:<\tt> GPIO IS Register */ + __IO uint32_t sr; /**< \b 0xAC:<\tt> GPIO SR Register */ + __IO uint32_t ds; /**< \b 0xB0:<\tt> GPIO DS Register */ __IO uint32_t ds1; /**< \b 0xB4:<\tt> GPIO DS1 Register */ - __IO uint32_t ps; /**< \b 0xB8:<\tt> GPIO PS Register */ + __IO uint32_t ps; /**< \b 0xB8:<\tt> GPIO PS Register */ __R uint32_t rsv_0xbc; __IO uint32_t vssel; /**< \b 0xC0:<\tt> GPIO VSSEL Register */ } mxc_gpio_regs_t; -#define PIN_0 ((uint32_t)(1UL << 0)) /**< Pin 0 Define */ -#define PIN_1 ((uint32_t)(1UL << 1)) /**< Pin 1 Define */ -#define PIN_2 ((uint32_t)(1UL << 2)) /**< Pin 2 Define */ -#define PIN_3 ((uint32_t)(1UL << 3)) /**< Pin 3 Define */ -#define PIN_4 ((uint32_t)(1UL << 4)) /**< Pin 4 Define */ -#define PIN_5 ((uint32_t)(1UL << 5)) /**< Pin 5 Define */ -#define PIN_6 ((uint32_t)(1UL << 6)) /**< Pin 6 Define */ -#define PIN_7 ((uint32_t)(1UL << 7)) /**< Pin 7 Define */ -#define PIN_8 ((uint32_t)(1UL << 8)) /**< Pin 8 Define */ -#define PIN_9 ((uint32_t)(1UL << 9)) /**< Pin 9 Define */ +#define PIN_0 ((uint32_t)(1UL << 0)) /**< Pin 0 Define */ +#define PIN_1 ((uint32_t)(1UL << 1)) /**< Pin 1 Define */ +#define PIN_2 ((uint32_t)(1UL << 2)) /**< Pin 2 Define */ +#define PIN_3 ((uint32_t)(1UL << 3)) /**< Pin 3 Define */ +#define PIN_4 ((uint32_t)(1UL << 4)) /**< Pin 4 Define */ +#define PIN_5 ((uint32_t)(1UL << 5)) /**< Pin 5 Define */ +#define PIN_6 ((uint32_t)(1UL << 6)) /**< Pin 6 Define */ +#define PIN_7 ((uint32_t)(1UL << 7)) /**< Pin 7 Define */ +#define PIN_8 ((uint32_t)(1UL << 8)) /**< Pin 8 Define */ +#define PIN_9 ((uint32_t)(1UL << 9)) /**< Pin 9 Define */ #define PIN_10 ((uint32_t)(1UL << 10)) /**< Pin 10 Define */ #define PIN_11 ((uint32_t)(1UL << 11)) /**< Pin 11 Define */ #define PIN_12 ((uint32_t)(1UL << 12)) /**< Pin 12 Define */ @@ -126,8 +126,8 @@ typedef struct { * Enumeration type for the GPIO Function Type */ typedef enum { - GPIO_FUNC_IN, /**< GPIO Input */ - GPIO_FUNC_OUT, /**< GPIO Output */ + GPIO_FUNC_IN, /**< GPIO Input */ + GPIO_FUNC_OUT, /**< GPIO Output */ GPIO_FUNC_ALT1, /**< Alternate Function Selection */ GPIO_FUNC_ALT2, /**< Alternate Function Selection */ GPIO_FUNC_ALT3, /**< Alternate Function Selection */ @@ -138,8 +138,8 @@ typedef enum { * Enumeration type for the type of GPIO pad on a given pin. */ typedef enum { - GPIO_PAD_NONE, /**< No pull-up or pull-down */ - GPIO_PAD_PULL_UP, /**< Set pad to weak pull-up */ + GPIO_PAD_NONE, /**< No pull-up or pull-down */ + GPIO_PAD_PULL_UP, /**< Set pad to weak pull-up */ GPIO_PAD_PULL_DOWN, /**< Set pad to weak pull-down */ } gpio_pad_t; @@ -147,10 +147,10 @@ typedef enum { * Structure type for configuring a GPIO port. */ typedef struct { - uint32_t port; /**< Index of GPIO port */ - uint32_t mask; /**< Pin mask (multiple pins may be set) */ + uint32_t port; /**< Index of GPIO port */ + uint32_t mask; /**< Pin mask (multiple pins may be set) */ gpio_func_t func; /**< Function type */ - gpio_pad_t pad; /**< Pad type */ + gpio_pad_t pad; /**< Pad type */ } gpio_cfg_t; typedef enum { GPIO_INTERRUPT_LEVEL, GPIO_INTERRUPT_EDGE } gpio_int_mode_t; @@ -166,110 +166,110 @@ typedef enum { } gpio_int_pol_t; /* Register offsets for module GPIO */ -#define MXC_R_GPIO_EN \ - ((uint32_t)0x00000000UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_EN \ + ((uint32_t)0x00000000UL) /**< Offset from GPIO Base Address: \ 0x0x000 */ -#define MXC_R_GPIO_EN_SET \ - ((uint32_t)0x00000004UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_EN_SET \ + ((uint32_t)0x00000004UL) /**< Offset from GPIO Base Address: \ 0x0x004 */ -#define MXC_R_GPIO_EN_CLR \ - ((uint32_t)0x00000008UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_EN_CLR \ + ((uint32_t)0x00000008UL) /**< Offset from GPIO Base Address: \ 0x0x008 */ -#define MXC_R_GPIO_OUT_EN \ - ((uint32_t)0x0000000CUL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_OUT_EN \ + ((uint32_t)0x0000000CUL) /**< Offset from GPIO Base Address: \ 0x0x00C */ -#define MXC_R_GPIO_OUT_EN_SET \ - ((uint32_t)0x00000010UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_OUT_EN_SET \ + ((uint32_t)0x00000010UL) /**< Offset from GPIO Base Address: \ 0x0x010 */ -#define MXC_R_GPIO_OUT_EN_CLR \ - ((uint32_t)0x00000014UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_OUT_EN_CLR \ + ((uint32_t)0x00000014UL) /**< Offset from GPIO Base Address: \ 0x0x014 */ -#define MXC_R_GPIO_OUT \ - ((uint32_t)0x00000018UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_OUT \ + ((uint32_t)0x00000018UL) /**< Offset from GPIO Base Address: \ 0x0x018 */ -#define MXC_R_GPIO_OUT_SET \ - ((uint32_t)0x0000001CUL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_OUT_SET \ + ((uint32_t)0x0000001CUL) /**< Offset from GPIO Base Address: \ 0x0x01C */ -#define MXC_R_GPIO_OUT_CLR \ - ((uint32_t)0x00000020UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_OUT_CLR \ + ((uint32_t)0x00000020UL) /**< Offset from GPIO Base Address: \ 0x0x020 */ -#define MXC_R_GPIO_IN \ - ((uint32_t)0x00000024UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_IN \ + ((uint32_t)0x00000024UL) /**< Offset from GPIO Base Address: \ 0x0x024 */ -#define MXC_R_GPIO_INT_MOD \ - ((uint32_t)0x00000028UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_INT_MOD \ + ((uint32_t)0x00000028UL) /**< Offset from GPIO Base Address: \ 0x0x028 */ -#define MXC_R_GPIO_INT_POL \ - ((uint32_t)0x0000002CUL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_INT_POL \ + ((uint32_t)0x0000002CUL) /**< Offset from GPIO Base Address: \ 0x0x02C */ -#define MXC_R_GPIO_INT_EN \ - ((uint32_t)0x00000034UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_INT_EN \ + ((uint32_t)0x00000034UL) /**< Offset from GPIO Base Address: \ 0x0x034 */ -#define MXC_R_GPIO_INT_EN_SET \ - ((uint32_t)0x00000038UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_INT_EN_SET \ + ((uint32_t)0x00000038UL) /**< Offset from GPIO Base Address: \ 0x0x038 */ -#define MXC_R_GPIO_INT_EN_CLR \ - ((uint32_t)0x0000003CUL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_INT_EN_CLR \ + ((uint32_t)0x0000003CUL) /**< Offset from GPIO Base Address: \ 0x0x03C */ -#define MXC_R_GPIO_INT_STAT \ - ((uint32_t)0x00000040UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_INT_STAT \ + ((uint32_t)0x00000040UL) /**< Offset from GPIO Base Address: \ 0x0x040 */ -#define MXC_R_GPIO_INT_CLR \ - ((uint32_t)0x00000048UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_INT_CLR \ + ((uint32_t)0x00000048UL) /**< Offset from GPIO Base Address: \ 0x0x048 */ -#define MXC_R_GPIO_WAKE_EN \ - ((uint32_t)0x0000004CUL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_WAKE_EN \ + ((uint32_t)0x0000004CUL) /**< Offset from GPIO Base Address: \ 0x0x04C */ -#define MXC_R_GPIO_WAKE_EN_SET \ - ((uint32_t)0x00000050UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_WAKE_EN_SET \ + ((uint32_t)0x00000050UL) /**< Offset from GPIO Base Address: \ 0x0x050 */ -#define MXC_R_GPIO_WAKE_EN_CLR \ - ((uint32_t)0x00000054UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_WAKE_EN_CLR \ + ((uint32_t)0x00000054UL) /**< Offset from GPIO Base Address: \ 0x0x054 */ -#define MXC_R_GPIO_INT_DUAL_EDGE \ - ((uint32_t)0x0000005CUL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_INT_DUAL_EDGE \ + ((uint32_t)0x0000005CUL) /**< Offset from GPIO Base Address: \ 0x0x05C */ -#define MXC_R_GPIO_PAD_CFG1 \ - ((uint32_t)0x00000060UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_PAD_CFG1 \ + ((uint32_t)0x00000060UL) /**< Offset from GPIO Base Address: \ 0x0x060 */ -#define MXC_R_GPIO_PAD_CFG2 \ - ((uint32_t)0x00000064UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_PAD_CFG2 \ + ((uint32_t)0x00000064UL) /**< Offset from GPIO Base Address: \ 0x0x064 */ -#define MXC_R_GPIO_EN1 \ - ((uint32_t)0x00000068UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_EN1 \ + ((uint32_t)0x00000068UL) /**< Offset from GPIO Base Address: \ 0x0x068 */ -#define MXC_R_GPIO_EN1_SET \ - ((uint32_t)0x0000006CUL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_EN1_SET \ + ((uint32_t)0x0000006CUL) /**< Offset from GPIO Base Address: \ 0x0x06C */ -#define MXC_R_GPIO_EN1_CLR \ - ((uint32_t)0x00000070UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_EN1_CLR \ + ((uint32_t)0x00000070UL) /**< Offset from GPIO Base Address: \ 0x0x070 */ -#define MXC_R_GPIO_EN2 \ - ((uint32_t)0x00000074UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_EN2 \ + ((uint32_t)0x00000074UL) /**< Offset from GPIO Base Address: \ 0x0x074 */ -#define MXC_R_GPIO_EN2_SET \ - ((uint32_t)0x00000078UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_EN2_SET \ + ((uint32_t)0x00000078UL) /**< Offset from GPIO Base Address: \ 0x0x078 */ -#define MXC_R_GPIO_EN2_CLR \ - ((uint32_t)0x0000007CUL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_EN2_CLR \ + ((uint32_t)0x0000007CUL) /**< Offset from GPIO Base Address: \ 0x0x07C */ -#define MXC_R_GPIO_IS \ - ((uint32_t)0x000000A8UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_IS \ + ((uint32_t)0x000000A8UL) /**< Offset from GPIO Base Address: \ 0x0x0A8 */ -#define MXC_R_GPIO_SR \ - ((uint32_t)0x000000ACUL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_SR \ + ((uint32_t)0x000000ACUL) /**< Offset from GPIO Base Address: \ 0x0x0AC */ -#define MXC_R_GPIO_DS \ - ((uint32_t)0x000000B0UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_DS \ + ((uint32_t)0x000000B0UL) /**< Offset from GPIO Base Address: \ 0x0x0B0 */ -#define MXC_R_GPIO_DS1 \ - ((uint32_t)0x000000B4UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_DS1 \ + ((uint32_t)0x000000B4UL) /**< Offset from GPIO Base Address: \ 0x0x0B4 */ -#define MXC_R_GPIO_PS \ - ((uint32_t)0x000000B8UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_PS \ + ((uint32_t)0x000000B8UL) /**< Offset from GPIO Base Address: \ 0x0x0B8 */ -#define MXC_R_GPIO_VSSEL \ - ((uint32_t)0x000000C0UL) /**< Offset from GPIO Base Address: \ +#define MXC_R_GPIO_VSSEL \ + ((uint32_t)0x000000C0UL) /**< Offset from GPIO Base Address: \ 0x0x0C0 */ /** @@ -277,19 +277,26 @@ typedef enum { * setting for one GPIO pin on the associated port. */ #define MXC_F_GPIO_EN_GPIO_EN_POS 0 /**< EN_GPIO_EN Position */ -#define MXC_F_GPIO_EN_GPIO_EN \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_EN_GPIO_EN_POS)) /**< EN_GPIO_EN Mask */ -#define MXC_V_GPIO_EN_GPIO_EN_ALTERNATE \ +#define MXC_F_GPIO_EN_GPIO_EN \ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_GPIO_EN_GPIO_EN_POS)) /**< \ + EN_GPIO_EN \ + Mask */ +#define MXC_V_GPIO_EN_GPIO_EN_ALTERNATE \ ((uint32_t)0x0UL) /**< EN_GPIO_EN_ALTERNATE Value */ -#define MXC_S_GPIO_EN_GPIO_EN_ALTERNATE \ - (MXC_V_GPIO_EN_GPIO_EN_ALTERNATE \ - << MXC_F_GPIO_EN_GPIO_EN_POS) /**< EN_GPIO_EN_ALTERNATE Setting */ -#define MXC_V_GPIO_EN_GPIO_EN_GPIO \ +#define MXC_S_GPIO_EN_GPIO_EN_ALTERNATE \ + (MXC_V_GPIO_EN_GPIO_EN_ALTERNATE \ + << MXC_F_GPIO_EN_GPIO_EN_POS) /**< \ + EN_GPIO_EN_ALTERNATE \ + Setting \ + */ +#define MXC_V_GPIO_EN_GPIO_EN_GPIO \ ((uint32_t)0x1UL) /**< EN_GPIO_EN_GPIO Value */ -#define MXC_S_GPIO_EN_GPIO_EN_GPIO \ - (MXC_V_GPIO_EN_GPIO_EN_GPIO \ - << MXC_F_GPIO_EN_GPIO_EN_POS) /**< EN_GPIO_EN_GPIO Setting */ +#define MXC_S_GPIO_EN_GPIO_EN_GPIO \ + (MXC_V_GPIO_EN_GPIO_EN_GPIO \ + << MXC_F_GPIO_EN_GPIO_EN_POS) /**< \ + EN_GPIO_EN_GPIO \ + Setting \ + */ /** * GPIO Set Function Enable Register. Writing a 1 to one or more bits @@ -297,9 +304,10 @@ typedef enum { * affecting other bits in that register. */ #define MXC_F_GPIO_EN_SET_ALL_POS 0 /**< EN_SET_ALL Position */ -#define MXC_F_GPIO_EN_SET_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_EN_SET_ALL_POS)) /**< EN_SET_ALL Mask */ +#define MXC_F_GPIO_EN_SET_ALL \ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_GPIO_EN_SET_ALL_POS)) /**< \ + EN_SET_ALL \ + Mask */ /** * GPIO Clear Function Enable Register. Writing a 1 to one or more @@ -307,33 +315,34 @@ typedef enum { * without affecting other bits in that register. */ #define MXC_F_GPIO_EN_CLR_ALL_POS 0 /**< EN_CLR_ALL Position */ -#define MXC_F_GPIO_EN_CLR_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_EN_CLR_ALL_POS)) /**< EN_CLR_ALL Mask */ +#define MXC_F_GPIO_EN_CLR_ALL \ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_GPIO_EN_CLR_ALL_POS)) /**< \ + EN_CLR_ALL \ + Mask */ /** * GPIO Output Enable Register. Each bit controls the GPIO_OUT_EN * setting for one GPIO pin in the associated port. */ -#define MXC_F_GPIO_OUT_EN_GPIO_OUT_EN_POS \ - 0 /**< OUT_EN_GPIO_OUT_EN Position \ +#define MXC_F_GPIO_OUT_EN_GPIO_OUT_EN_POS \ + 0 /**< OUT_EN_GPIO_OUT_EN Position \ */ -#define MXC_F_GPIO_OUT_EN_GPIO_OUT_EN \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_OUT_EN_GPIO_OUT_EN_POS)) /**< OUT_EN_GPIO_OUT_EN \ - Mask */ -#define MXC_V_GPIO_OUT_EN_GPIO_OUT_EN_DIS \ +#define MXC_F_GPIO_OUT_EN_GPIO_OUT_EN \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_OUT_EN_GPIO_OUT_EN_POS)) /**< \ + OUT_EN_GPIO_OUT_EN \ + Mask */ +#define MXC_V_GPIO_OUT_EN_GPIO_OUT_EN_DIS \ ((uint32_t)0x0UL) /**< OUT_EN_GPIO_OUT_EN_DIS Value */ -#define MXC_S_GPIO_OUT_EN_GPIO_OUT_EN_DIS \ - (MXC_V_GPIO_OUT_EN_GPIO_OUT_EN_DIS \ - << MXC_F_GPIO_OUT_EN_GPIO_OUT_EN_POS) /**< OUT_EN_GPIO_OUT_EN_DIS \ +#define MXC_S_GPIO_OUT_EN_GPIO_OUT_EN_DIS \ + (MXC_V_GPIO_OUT_EN_GPIO_OUT_EN_DIS \ + << MXC_F_GPIO_OUT_EN_GPIO_OUT_EN_POS) /**< OUT_EN_GPIO_OUT_EN_DIS \ Setting */ -#define MXC_V_GPIO_OUT_EN_GPIO_OUT_EN_EN \ +#define MXC_V_GPIO_OUT_EN_GPIO_OUT_EN_EN \ ((uint32_t)0x1UL) /**< OUT_EN_GPIO_OUT_EN_EN Value */ -#define MXC_S_GPIO_OUT_EN_GPIO_OUT_EN_EN \ - (MXC_V_GPIO_OUT_EN_GPIO_OUT_EN_EN \ - << MXC_F_GPIO_OUT_EN_GPIO_OUT_EN_POS) /**< OUT_EN_GPIO_OUT_EN_EN \ +#define MXC_S_GPIO_OUT_EN_GPIO_OUT_EN_EN \ + (MXC_V_GPIO_OUT_EN_GPIO_OUT_EN_EN \ + << MXC_F_GPIO_OUT_EN_GPIO_OUT_EN_POS) /**< OUT_EN_GPIO_OUT_EN_EN \ Setting */ /** @@ -342,10 +351,11 @@ typedef enum { * GPIO_OUT_EN to 1, without affecting other bits in that register. */ #define MXC_F_GPIO_OUT_EN_SET_ALL_POS 0 /**< OUT_EN_SET_ALL Position */ -#define MXC_F_GPIO_OUT_EN_SET_ALL \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_OUT_EN_SET_ALL_POS)) /**< OUT_EN_SET_ALL Mask */ +#define MXC_F_GPIO_OUT_EN_SET_ALL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_OUT_EN_SET_ALL_POS)) /**< \ + OUT_EN_SET_ALL \ + Mask */ /** * GPIO Output Enable Clear Function Enable Register. Writing a 1 to @@ -353,10 +363,11 @@ typedef enum { * GPIO_OUT_EN to 0, without affecting other bits in that register. */ #define MXC_F_GPIO_OUT_EN_CLR_ALL_POS 0 /**< OUT_EN_CLR_ALL Position */ -#define MXC_F_GPIO_OUT_EN_CLR_ALL \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_OUT_EN_CLR_ALL_POS)) /**< OUT_EN_CLR_ALL Mask */ +#define MXC_F_GPIO_OUT_EN_CLR_ALL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_OUT_EN_CLR_ALL_POS)) /**< \ + OUT_EN_CLR_ALL \ + Mask */ /** * GPIO Output Register. Each bit controls the GPIO_OUT setting for @@ -364,40 +375,47 @@ typedef enum { * directly, or by using the GPIO_OUT_SET and GPIO_OUT_CLR registers. */ #define MXC_F_GPIO_OUT_GPIO_OUT_POS 0 /**< OUT_GPIO_OUT Position */ -#define MXC_F_GPIO_OUT_GPIO_OUT \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_OUT_GPIO_OUT_POS)) /**< OUT_GPIO_OUT Mask */ -#define MXC_V_GPIO_OUT_GPIO_OUT_LOW \ +#define MXC_F_GPIO_OUT_GPIO_OUT \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_OUT_GPIO_OUT_POS)) /**< \ + OUT_GPIO_OUT \ + Mask */ +#define MXC_V_GPIO_OUT_GPIO_OUT_LOW \ ((uint32_t)0x0UL) /**< OUT_GPIO_OUT_LOW Value */ -#define MXC_S_GPIO_OUT_GPIO_OUT_LOW \ - (MXC_V_GPIO_OUT_GPIO_OUT_LOW \ - << MXC_F_GPIO_OUT_GPIO_OUT_POS) /**< OUT_GPIO_OUT_LOW Setting */ -#define MXC_V_GPIO_OUT_GPIO_OUT_HIGH \ +#define MXC_S_GPIO_OUT_GPIO_OUT_LOW \ + (MXC_V_GPIO_OUT_GPIO_OUT_LOW \ + << MXC_F_GPIO_OUT_GPIO_OUT_POS) /**< \ + OUT_GPIO_OUT_LOW \ + Setting \ + */ +#define MXC_V_GPIO_OUT_GPIO_OUT_HIGH \ ((uint32_t)0x1UL) /**< OUT_GPIO_OUT_HIGH Value */ -#define MXC_S_GPIO_OUT_GPIO_OUT_HIGH \ - (MXC_V_GPIO_OUT_GPIO_OUT_HIGH \ - << MXC_F_GPIO_OUT_GPIO_OUT_POS) /**< OUT_GPIO_OUT_HIGH Setting */ +#define MXC_S_GPIO_OUT_GPIO_OUT_HIGH \ + (MXC_V_GPIO_OUT_GPIO_OUT_HIGH \ + << MXC_F_GPIO_OUT_GPIO_OUT_POS) /**< \ + OUT_GPIO_OUT_HIGH \ + Setting \ + */ /** * GPIO Output Set. Writing a 1 to one or more bits in this register * sets the bits in the same positions in GPIO_OUT to 1, without affecting other * bits in that register. */ -#define MXC_F_GPIO_OUT_SET_GPIO_OUT_SET_POS \ +#define MXC_F_GPIO_OUT_SET_GPIO_OUT_SET_POS \ 0 /**< OUT_SET_GPIO_OUT_SET Position */ -#define MXC_F_GPIO_OUT_SET_GPIO_OUT_SET \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_OUT_SET_GPIO_OUT_SET_POS)) /**< \ - OUT_SET_GPIO_OUT_SET \ - Mask */ -#define MXC_V_GPIO_OUT_SET_GPIO_OUT_SET_NO \ +#define MXC_F_GPIO_OUT_SET_GPIO_OUT_SET \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_OUT_SET_GPIO_OUT_SET_POS)) /**< \ + OUT_SET_GPIO_OUT_SET \ + Mask */ +#define MXC_V_GPIO_OUT_SET_GPIO_OUT_SET_NO \ ((uint32_t)0x0UL) /**< OUT_SET_GPIO_OUT_SET_NO Value */ -#define MXC_S_GPIO_OUT_SET_GPIO_OUT_SET_NO \ - (MXC_V_GPIO_OUT_SET_GPIO_OUT_SET_NO \ - << MXC_F_GPIO_OUT_SET_GPIO_OUT_SET_POS) /**< OUT_SET_GPIO_OUT_SET_NO \ +#define MXC_S_GPIO_OUT_SET_GPIO_OUT_SET_NO \ + (MXC_V_GPIO_OUT_SET_GPIO_OUT_SET_NO \ + << MXC_F_GPIO_OUT_SET_GPIO_OUT_SET_POS) /**< OUT_SET_GPIO_OUT_SET_NO \ Setting */ -#define MXC_V_GPIO_OUT_SET_GPIO_OUT_SET_SET \ +#define MXC_V_GPIO_OUT_SET_GPIO_OUT_SET_SET \ ((uint32_t)0x1UL) /**< OUT_SET_GPIO_OUT_SET_SET Value */ #define MXC_S_GPIO_OUT_SET_GPIO_OUT_SET_SET \ (MXC_V_GPIO_OUT_SET_GPIO_OUT_SET_SET \ @@ -408,49 +426,48 @@ typedef enum { * clears the bits in the same positions in GPIO_OUT to 0, without affecting * other bits in that register. */ -#define MXC_F_GPIO_OUT_CLR_GPIO_OUT_CLR_POS \ +#define MXC_F_GPIO_OUT_CLR_GPIO_OUT_CLR_POS \ 0 /**< OUT_CLR_GPIO_OUT_CLR Position */ -#define MXC_F_GPIO_OUT_CLR_GPIO_OUT_CLR \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_OUT_CLR_GPIO_OUT_CLR_POS)) /**< \ - OUT_CLR_GPIO_OUT_CLR \ - Mask */ +#define MXC_F_GPIO_OUT_CLR_GPIO_OUT_CLR \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_OUT_CLR_GPIO_OUT_CLR_POS)) /**< \ + OUT_CLR_GPIO_OUT_CLR \ + Mask */ /** * GPIO Input Register. Read-only register to read from the logic * states of the GPIO pins on this port. */ #define MXC_F_GPIO_IN_GPIO_IN_POS 0 /**< IN_GPIO_IN Position */ -#define MXC_F_GPIO_IN_GPIO_IN \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_IN_GPIO_IN_POS)) /**< IN_GPIO_IN Mask */ +#define MXC_F_GPIO_IN_GPIO_IN \ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_GPIO_IN_GPIO_IN_POS)) /**< \ + IN_GPIO_IN \ + Mask */ /** * GPIO Interrupt Mode Register. Each bit in this register controls * the interrupt mode setting for the associated GPIO pin on this port. */ -#define MXC_F_GPIO_INT_MOD_GPIO_INT_MOD_POS \ +#define MXC_F_GPIO_INT_MOD_GPIO_INT_MOD_POS \ 0 /**< INT_MOD_GPIO_INT_MOD Position */ -#define MXC_F_GPIO_INT_MOD_GPIO_INT_MOD \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_INT_MOD_GPIO_INT_MOD_POS)) /**< \ - INT_MOD_GPIO_INT_MOD \ - Mask */ -#define MXC_V_GPIO_INT_MOD_GPIO_INT_MOD_LEVEL \ +#define MXC_F_GPIO_INT_MOD_GPIO_INT_MOD \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_INT_MOD_GPIO_INT_MOD_POS)) /**< \ + INT_MOD_GPIO_INT_MOD \ + Mask */ +#define MXC_V_GPIO_INT_MOD_GPIO_INT_MOD_LEVEL \ ((uint32_t)0x0UL) /**< INT_MOD_GPIO_INT_MOD_LEVEL Value */ #define MXC_S_GPIO_INT_MOD_GPIO_INT_MOD_LEVEL \ (MXC_V_GPIO_INT_MOD_GPIO_INT_MOD_LEVEL \ << MXC_F_GPIO_INT_MOD_GPIO_INT_MOD_POS) /**< \ INT_MOD_GPIO_INT_MOD_LEVEL \ Setting */ -#define MXC_V_GPIO_INT_MOD_GPIO_INT_MOD_EDGE \ +#define MXC_V_GPIO_INT_MOD_GPIO_INT_MOD_EDGE \ ((uint32_t)0x1UL) /**< INT_MOD_GPIO_INT_MOD_EDGE Value */ -#define MXC_S_GPIO_INT_MOD_GPIO_INT_MOD_EDGE \ - (MXC_V_GPIO_INT_MOD_GPIO_INT_MOD_EDGE \ - << MXC_F_GPIO_INT_MOD_GPIO_INT_MOD_POS) /**< \ - INT_MOD_GPIO_INT_MOD_EDGE \ +#define MXC_S_GPIO_INT_MOD_GPIO_INT_MOD_EDGE \ + (MXC_V_GPIO_INT_MOD_GPIO_INT_MOD_EDGE \ + << MXC_F_GPIO_INT_MOD_GPIO_INT_MOD_POS) /**< \ + INT_MOD_GPIO_INT_MOD_EDGE \ Setting */ /** @@ -458,22 +475,21 @@ typedef enum { * controls the interrupt polarity setting for one GPIO pin in the associated * port. */ -#define MXC_F_GPIO_INT_POL_GPIO_INT_POL_POS \ +#define MXC_F_GPIO_INT_POL_GPIO_INT_POL_POS \ 0 /**< INT_POL_GPIO_INT_POL Position */ -#define MXC_F_GPIO_INT_POL_GPIO_INT_POL \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_INT_POL_GPIO_INT_POL_POS)) /**< \ - INT_POL_GPIO_INT_POL \ - Mask */ -#define MXC_V_GPIO_INT_POL_GPIO_INT_POL_FALLING \ +#define MXC_F_GPIO_INT_POL_GPIO_INT_POL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_INT_POL_GPIO_INT_POL_POS)) /**< \ + INT_POL_GPIO_INT_POL \ + Mask */ +#define MXC_V_GPIO_INT_POL_GPIO_INT_POL_FALLING \ ((uint32_t)0x0UL) /**< INT_POL_GPIO_INT_POL_FALLING Value */ #define MXC_S_GPIO_INT_POL_GPIO_INT_POL_FALLING \ (MXC_V_GPIO_INT_POL_GPIO_INT_POL_FALLING \ << MXC_F_GPIO_INT_POL_GPIO_INT_POL_POS) /**< \ INT_POL_GPIO_INT_POL_FALLING \ Setting */ -#define MXC_V_GPIO_INT_POL_GPIO_INT_POL_RISING \ +#define MXC_V_GPIO_INT_POL_GPIO_INT_POL_RISING \ ((uint32_t)0x1UL) /**< INT_POL_GPIO_INT_POL_RISING Value */ #define MXC_S_GPIO_INT_POL_GPIO_INT_POL_RISING \ (MXC_V_GPIO_INT_POL_GPIO_INT_POL_RISING \ @@ -485,25 +501,25 @@ typedef enum { * GPIO Interrupt Enable Register. Each bit in this register controls * the GPIO interrupt enable for the associated pin on the GPIO port. */ -#define MXC_F_GPIO_INT_EN_GPIO_INT_EN_POS \ - 0 /**< INT_EN_GPIO_INT_EN Position \ +#define MXC_F_GPIO_INT_EN_GPIO_INT_EN_POS \ + 0 /**< INT_EN_GPIO_INT_EN Position \ */ -#define MXC_F_GPIO_INT_EN_GPIO_INT_EN \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_INT_EN_GPIO_INT_EN_POS)) /**< INT_EN_GPIO_INT_EN \ - Mask */ -#define MXC_V_GPIO_INT_EN_GPIO_INT_EN_DIS \ +#define MXC_F_GPIO_INT_EN_GPIO_INT_EN \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_INT_EN_GPIO_INT_EN_POS)) /**< \ + INT_EN_GPIO_INT_EN \ + Mask */ +#define MXC_V_GPIO_INT_EN_GPIO_INT_EN_DIS \ ((uint32_t)0x0UL) /**< INT_EN_GPIO_INT_EN_DIS Value */ -#define MXC_S_GPIO_INT_EN_GPIO_INT_EN_DIS \ - (MXC_V_GPIO_INT_EN_GPIO_INT_EN_DIS \ - << MXC_F_GPIO_INT_EN_GPIO_INT_EN_POS) /**< INT_EN_GPIO_INT_EN_DIS \ +#define MXC_S_GPIO_INT_EN_GPIO_INT_EN_DIS \ + (MXC_V_GPIO_INT_EN_GPIO_INT_EN_DIS \ + << MXC_F_GPIO_INT_EN_GPIO_INT_EN_POS) /**< INT_EN_GPIO_INT_EN_DIS \ Setting */ -#define MXC_V_GPIO_INT_EN_GPIO_INT_EN_EN \ +#define MXC_V_GPIO_INT_EN_GPIO_INT_EN_EN \ ((uint32_t)0x1UL) /**< INT_EN_GPIO_INT_EN_EN Value */ -#define MXC_S_GPIO_INT_EN_GPIO_INT_EN_EN \ - (MXC_V_GPIO_INT_EN_GPIO_INT_EN_EN \ - << MXC_F_GPIO_INT_EN_GPIO_INT_EN_POS) /**< INT_EN_GPIO_INT_EN_EN \ +#define MXC_S_GPIO_INT_EN_GPIO_INT_EN_EN \ + (MXC_V_GPIO_INT_EN_GPIO_INT_EN_EN \ + << MXC_F_GPIO_INT_EN_GPIO_INT_EN_POS) /**< INT_EN_GPIO_INT_EN_EN \ Setting */ /** @@ -511,22 +527,21 @@ typedef enum { * register sets the bits in the same positions in GPIO_INT_EN to 1, without * affecting other bits in that register. */ -#define MXC_F_GPIO_INT_EN_SET_GPIO_INT_EN_SET_POS \ +#define MXC_F_GPIO_INT_EN_SET_GPIO_INT_EN_SET_POS \ 0 /**< INT_EN_SET_GPIO_INT_EN_SET Position */ -#define MXC_F_GPIO_INT_EN_SET_GPIO_INT_EN_SET \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_INT_EN_SET_GPIO_INT_EN_SET_POS)) /**< \ - INT_EN_SET_GPIO_INT_EN_SET \ - Mask */ -#define MXC_V_GPIO_INT_EN_SET_GPIO_INT_EN_SET_NO \ +#define MXC_F_GPIO_INT_EN_SET_GPIO_INT_EN_SET \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_INT_EN_SET_GPIO_INT_EN_SET_POS)) /**< \ + INT_EN_SET_GPIO_INT_EN_SET \ + Mask */ +#define MXC_V_GPIO_INT_EN_SET_GPIO_INT_EN_SET_NO \ ((uint32_t)0x0UL) /**< INT_EN_SET_GPIO_INT_EN_SET_NO Value */ #define MXC_S_GPIO_INT_EN_SET_GPIO_INT_EN_SET_NO \ (MXC_V_GPIO_INT_EN_SET_GPIO_INT_EN_SET_NO \ << MXC_F_GPIO_INT_EN_SET_GPIO_INT_EN_SET_POS) /**< \ INT_EN_SET_GPIO_INT_EN_SET_NO \ Setting */ -#define MXC_V_GPIO_INT_EN_SET_GPIO_INT_EN_SET_SET \ +#define MXC_V_GPIO_INT_EN_SET_GPIO_INT_EN_SET_SET \ ((uint32_t)0x1UL) /**< INT_EN_SET_GPIO_INT_EN_SET_SET Value */ #define MXC_S_GPIO_INT_EN_SET_GPIO_INT_EN_SET_SET \ (MXC_V_GPIO_INT_EN_SET_GPIO_INT_EN_SET_SET \ @@ -538,22 +553,21 @@ typedef enum { * this register clears the bits in the same positions in GPIO_INT_EN to 0, * without affecting other bits in that register. */ -#define MXC_F_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_POS \ +#define MXC_F_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_POS \ 0 /**< INT_EN_CLR_GPIO_INT_EN_CLR Position */ -#define MXC_F_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_POS)) /**< \ - INT_EN_CLR_GPIO_INT_EN_CLR \ - Mask */ -#define MXC_V_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_NO \ +#define MXC_F_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_POS)) /**< \ + INT_EN_CLR_GPIO_INT_EN_CLR \ + Mask */ +#define MXC_V_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_NO \ ((uint32_t)0x0UL) /**< INT_EN_CLR_GPIO_INT_EN_CLR_NO Value */ #define MXC_S_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_NO \ (MXC_V_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_NO \ << MXC_F_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_POS) /**< \ INT_EN_CLR_GPIO_INT_EN_CLR_NO \ Setting */ -#define MXC_V_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_CLEAR \ +#define MXC_V_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_CLEAR \ ((uint32_t)0x1UL) /**< INT_EN_CLR_GPIO_INT_EN_CLR_CLEAR Value */ #define MXC_S_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_CLEAR \ (MXC_V_GPIO_INT_EN_CLR_GPIO_INT_EN_CLR_CLEAR \ @@ -564,22 +578,21 @@ typedef enum { * GPIO Interrupt Status Register. Each bit in this register contains * the pending interrupt status for the associated GPIO pin in this port. */ -#define MXC_F_GPIO_INT_STAT_GPIO_INT_STAT_POS \ +#define MXC_F_GPIO_INT_STAT_GPIO_INT_STAT_POS \ 0 /**< INT_STAT_GPIO_INT_STAT Position */ -#define MXC_F_GPIO_INT_STAT_GPIO_INT_STAT \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_INT_STAT_GPIO_INT_STAT_POS)) /**< \ - INT_STAT_GPIO_INT_STAT \ - Mask */ -#define MXC_V_GPIO_INT_STAT_GPIO_INT_STAT_NO \ +#define MXC_F_GPIO_INT_STAT_GPIO_INT_STAT \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_INT_STAT_GPIO_INT_STAT_POS)) /**< \ + INT_STAT_GPIO_INT_STAT \ + Mask */ +#define MXC_V_GPIO_INT_STAT_GPIO_INT_STAT_NO \ ((uint32_t)0x0UL) /**< INT_STAT_GPIO_INT_STAT_NO Value */ #define MXC_S_GPIO_INT_STAT_GPIO_INT_STAT_NO \ (MXC_V_GPIO_INT_STAT_GPIO_INT_STAT_NO \ << MXC_F_GPIO_INT_STAT_GPIO_INT_STAT_POS) /**< \ INT_STAT_GPIO_INT_STAT_NO \ Setting */ -#define MXC_V_GPIO_INT_STAT_GPIO_INT_STAT_PENDING \ +#define MXC_V_GPIO_INT_STAT_GPIO_INT_STAT_PENDING \ ((uint32_t)0x1UL) /**< INT_STAT_GPIO_INT_STAT_PENDING Value */ #define MXC_S_GPIO_INT_STAT_GPIO_INT_STAT_PENDING \ (MXC_V_GPIO_INT_STAT_GPIO_INT_STAT_PENDING \ @@ -593,33 +606,34 @@ typedef enum { * affecting other bits in that register. */ #define MXC_F_GPIO_INT_CLR_ALL_POS 0 /**< INT_CLR_ALL Position */ -#define MXC_F_GPIO_INT_CLR_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_INT_CLR_ALL_POS)) /**< INT_CLR_ALL Mask */ +#define MXC_F_GPIO_INT_CLR_ALL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_INT_CLR_ALL_POS)) /**< \ + INT_CLR_ALL \ + Mask */ /** * GPIO Wake Enable Register. Each bit in this register controls the * PMU wakeup enable for the associated GPIO pin in this port. */ -#define MXC_F_GPIO_WAKE_EN_GPIO_WAKE_EN_POS \ +#define MXC_F_GPIO_WAKE_EN_GPIO_WAKE_EN_POS \ 0 /**< WAKE_EN_GPIO_WAKE_EN Position */ -#define MXC_F_GPIO_WAKE_EN_GPIO_WAKE_EN \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_WAKE_EN_GPIO_WAKE_EN_POS)) /**< \ - WAKE_EN_GPIO_WAKE_EN \ - Mask */ -#define MXC_V_GPIO_WAKE_EN_GPIO_WAKE_EN_DIS \ +#define MXC_F_GPIO_WAKE_EN_GPIO_WAKE_EN \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_WAKE_EN_GPIO_WAKE_EN_POS)) /**< \ + WAKE_EN_GPIO_WAKE_EN \ + Mask */ +#define MXC_V_GPIO_WAKE_EN_GPIO_WAKE_EN_DIS \ ((uint32_t)0x0UL) /**< WAKE_EN_GPIO_WAKE_EN_DIS Value */ #define MXC_S_GPIO_WAKE_EN_GPIO_WAKE_EN_DIS \ (MXC_V_GPIO_WAKE_EN_GPIO_WAKE_EN_DIS \ << MXC_F_GPIO_WAKE_EN_GPIO_WAKE_EN_POS) /**< WAKE_EN_GPIO_WAKE_EN_DIS \ Setting */ -#define MXC_V_GPIO_WAKE_EN_GPIO_WAKE_EN_EN \ +#define MXC_V_GPIO_WAKE_EN_GPIO_WAKE_EN_EN \ ((uint32_t)0x1UL) /**< WAKE_EN_GPIO_WAKE_EN_EN Value */ -#define MXC_S_GPIO_WAKE_EN_GPIO_WAKE_EN_EN \ - (MXC_V_GPIO_WAKE_EN_GPIO_WAKE_EN_EN \ - << MXC_F_GPIO_WAKE_EN_GPIO_WAKE_EN_POS) /**< WAKE_EN_GPIO_WAKE_EN_EN \ +#define MXC_S_GPIO_WAKE_EN_GPIO_WAKE_EN_EN \ + (MXC_V_GPIO_WAKE_EN_GPIO_WAKE_EN_EN \ + << MXC_F_GPIO_WAKE_EN_GPIO_WAKE_EN_POS) /**< WAKE_EN_GPIO_WAKE_EN_EN \ Setting */ /** @@ -628,9 +642,9 @@ typedef enum { * affecting other bits in that register. */ #define MXC_F_GPIO_WAKE_EN_SET_ALL_POS 0 /**< WAKE_EN_SET_ALL Position */ -#define MXC_F_GPIO_WAKE_EN_SET_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_WAKE_EN_SET_ALL_POS)) /**< WAKE_EN_SET_ALL \ +#define MXC_F_GPIO_WAKE_EN_SET_ALL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_WAKE_EN_SET_ALL_POS)) /**< WAKE_EN_SET_ALL \ Mask */ /** @@ -639,32 +653,31 @@ typedef enum { * affecting other bits in that register. */ #define MXC_F_GPIO_WAKE_EN_CLR_ALL_POS 0 /**< WAKE_EN_CLR_ALL Position */ -#define MXC_F_GPIO_WAKE_EN_CLR_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_WAKE_EN_CLR_ALL_POS)) /**< WAKE_EN_CLR_ALL \ +#define MXC_F_GPIO_WAKE_EN_CLR_ALL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_WAKE_EN_CLR_ALL_POS)) /**< WAKE_EN_CLR_ALL \ Mask */ /** * GPIO Interrupt Dual Edge Mode Register. Each bit in this register * selects dual edge mode for the associated GPIO pin in this port. */ -#define MXC_F_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_POS \ +#define MXC_F_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_POS \ 0 /**< INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE Position */ -#define MXC_F_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_POS)) /**< \ - INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE \ - Mask \ - */ -#define MXC_V_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_NO \ +#define MXC_F_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_POS)) /**< \ + INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE \ + Mask \ + */ +#define MXC_V_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_NO \ ((uint32_t)0x0UL) /**< INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_NO Value */ #define MXC_S_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_NO \ (MXC_V_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_NO \ << MXC_F_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_POS) /**< \ INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_NO \ Setting */ -#define MXC_V_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_EN \ +#define MXC_V_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_EN \ ((uint32_t)0x1UL) /**< INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_EN Value */ #define MXC_S_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_EN \ (MXC_V_GPIO_INT_DUAL_EDGE_GPIO_INT_DUAL_EDGE_EN \ @@ -676,29 +689,28 @@ typedef enum { * GPIO Input Mode Config 1. Each bit in this register enables the * weak pull-up for the associated GPIO pin in this port. */ -#define MXC_F_GPIO_PAD_CFG1_GPIO_PAD_CFG1_POS \ +#define MXC_F_GPIO_PAD_CFG1_GPIO_PAD_CFG1_POS \ 0 /**< PAD_CFG1_GPIO_PAD_CFG1 Position */ -#define MXC_F_GPIO_PAD_CFG1_GPIO_PAD_CFG1 \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_PAD_CFG1_GPIO_PAD_CFG1_POS)) /**< \ - PAD_CFG1_GPIO_PAD_CFG1 \ - Mask */ -#define MXC_V_GPIO_PAD_CFG1_GPIO_PAD_CFG1_IMPEDANCE \ +#define MXC_F_GPIO_PAD_CFG1_GPIO_PAD_CFG1 \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_PAD_CFG1_GPIO_PAD_CFG1_POS)) /**< \ + PAD_CFG1_GPIO_PAD_CFG1 \ + Mask */ +#define MXC_V_GPIO_PAD_CFG1_GPIO_PAD_CFG1_IMPEDANCE \ ((uint32_t)0x0UL) /**< PAD_CFG1_GPIO_PAD_CFG1_IMPEDANCE Value */ #define MXC_S_GPIO_PAD_CFG1_GPIO_PAD_CFG1_IMPEDANCE \ (MXC_V_GPIO_PAD_CFG1_GPIO_PAD_CFG1_IMPEDANCE \ << MXC_F_GPIO_PAD_CFG1_GPIO_PAD_CFG1_POS) /**< \ PAD_CFG1_GPIO_PAD_CFG1_IMPEDANCE \ Setting */ -#define MXC_V_GPIO_PAD_CFG1_GPIO_PAD_CFG1_PU \ +#define MXC_V_GPIO_PAD_CFG1_GPIO_PAD_CFG1_PU \ ((uint32_t)0x1UL) /**< PAD_CFG1_GPIO_PAD_CFG1_PU Value */ #define MXC_S_GPIO_PAD_CFG1_GPIO_PAD_CFG1_PU \ (MXC_V_GPIO_PAD_CFG1_GPIO_PAD_CFG1_PU \ << MXC_F_GPIO_PAD_CFG1_GPIO_PAD_CFG1_POS) /**< \ PAD_CFG1_GPIO_PAD_CFG1_PU \ Setting */ -#define MXC_V_GPIO_PAD_CFG1_GPIO_PAD_CFG1_PD \ +#define MXC_V_GPIO_PAD_CFG1_GPIO_PAD_CFG1_PD \ ((uint32_t)0x2UL) /**< PAD_CFG1_GPIO_PAD_CFG1_PD Value */ #define MXC_S_GPIO_PAD_CFG1_GPIO_PAD_CFG1_PD \ (MXC_V_GPIO_PAD_CFG1_GPIO_PAD_CFG1_PD \ @@ -710,29 +722,28 @@ typedef enum { * GPIO Input Mode Config 2. Each bit in this register enables the * weak pull-up for the associated GPIO pin in this port. */ -#define MXC_F_GPIO_PAD_CFG2_GPIO_PAD_CFG2_POS \ +#define MXC_F_GPIO_PAD_CFG2_GPIO_PAD_CFG2_POS \ 0 /**< PAD_CFG2_GPIO_PAD_CFG2 Position */ -#define MXC_F_GPIO_PAD_CFG2_GPIO_PAD_CFG2 \ - ((uint32_t)( \ - 0xFFFFFFFFUL \ - << MXC_F_GPIO_PAD_CFG2_GPIO_PAD_CFG2_POS)) /**< \ - PAD_CFG2_GPIO_PAD_CFG2 \ - Mask */ -#define MXC_V_GPIO_PAD_CFG2_GPIO_PAD_CFG2_IMPEDANCE \ +#define MXC_F_GPIO_PAD_CFG2_GPIO_PAD_CFG2 \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_PAD_CFG2_GPIO_PAD_CFG2_POS)) /**< \ + PAD_CFG2_GPIO_PAD_CFG2 \ + Mask */ +#define MXC_V_GPIO_PAD_CFG2_GPIO_PAD_CFG2_IMPEDANCE \ ((uint32_t)0x0UL) /**< PAD_CFG2_GPIO_PAD_CFG2_IMPEDANCE Value */ #define MXC_S_GPIO_PAD_CFG2_GPIO_PAD_CFG2_IMPEDANCE \ (MXC_V_GPIO_PAD_CFG2_GPIO_PAD_CFG2_IMPEDANCE \ << MXC_F_GPIO_PAD_CFG2_GPIO_PAD_CFG2_POS) /**< \ PAD_CFG2_GPIO_PAD_CFG2_IMPEDANCE \ Setting */ -#define MXC_V_GPIO_PAD_CFG2_GPIO_PAD_CFG2_PU \ +#define MXC_V_GPIO_PAD_CFG2_GPIO_PAD_CFG2_PU \ ((uint32_t)0x1UL) /**< PAD_CFG2_GPIO_PAD_CFG2_PU Value */ #define MXC_S_GPIO_PAD_CFG2_GPIO_PAD_CFG2_PU \ (MXC_V_GPIO_PAD_CFG2_GPIO_PAD_CFG2_PU \ << MXC_F_GPIO_PAD_CFG2_GPIO_PAD_CFG2_POS) /**< \ PAD_CFG2_GPIO_PAD_CFG2_PU \ Setting */ -#define MXC_V_GPIO_PAD_CFG2_GPIO_PAD_CFG2_PD \ +#define MXC_V_GPIO_PAD_CFG2_GPIO_PAD_CFG2_PD \ ((uint32_t)0x2UL) /**< PAD_CFG2_GPIO_PAD_CFG2_PD Value */ #define MXC_S_GPIO_PAD_CFG2_GPIO_PAD_CFG2_PD \ (MXC_V_GPIO_PAD_CFG2_GPIO_PAD_CFG2_PD \ @@ -746,19 +757,24 @@ typedef enum { * this port. */ #define MXC_F_GPIO_EN1_GPIO_EN1_POS 0 /**< EN1_GPIO_EN1 Position */ -#define MXC_F_GPIO_EN1_GPIO_EN1 \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_EN1_GPIO_EN1_POS)) /**< EN1_GPIO_EN1 Mask */ -#define MXC_V_GPIO_EN1_GPIO_EN1_PRIMARY \ +#define MXC_F_GPIO_EN1_GPIO_EN1 \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_EN1_GPIO_EN1_POS)) /**< \ + EN1_GPIO_EN1 \ + Mask */ +#define MXC_V_GPIO_EN1_GPIO_EN1_PRIMARY \ ((uint32_t)0x0UL) /**< EN1_GPIO_EN1_PRIMARY Value */ -#define MXC_S_GPIO_EN1_GPIO_EN1_PRIMARY \ - (MXC_V_GPIO_EN1_GPIO_EN1_PRIMARY \ - << MXC_F_GPIO_EN1_GPIO_EN1_POS) /**< EN1_GPIO_EN1_PRIMARY Setting */ -#define MXC_V_GPIO_EN1_GPIO_EN1_SECONDARY \ +#define MXC_S_GPIO_EN1_GPIO_EN1_PRIMARY \ + (MXC_V_GPIO_EN1_GPIO_EN1_PRIMARY \ + << MXC_F_GPIO_EN1_GPIO_EN1_POS) /**< \ + EN1_GPIO_EN1_PRIMARY \ + Setting \ + */ +#define MXC_V_GPIO_EN1_GPIO_EN1_SECONDARY \ ((uint32_t)0x1UL) /**< EN1_GPIO_EN1_SECONDARY Value */ -#define MXC_S_GPIO_EN1_GPIO_EN1_SECONDARY \ - (MXC_V_GPIO_EN1_GPIO_EN1_SECONDARY \ - << MXC_F_GPIO_EN1_GPIO_EN1_POS) /**< EN1_GPIO_EN1_SECONDARY Setting \ +#define MXC_S_GPIO_EN1_GPIO_EN1_SECONDARY \ + (MXC_V_GPIO_EN1_GPIO_EN1_SECONDARY \ + << MXC_F_GPIO_EN1_GPIO_EN1_POS) /**< EN1_GPIO_EN1_SECONDARY Setting \ */ /** @@ -767,9 +783,11 @@ typedef enum { * affecting other bits in that register. */ #define MXC_F_GPIO_EN1_SET_ALL_POS 0 /**< EN1_SET_ALL Position */ -#define MXC_F_GPIO_EN1_SET_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_EN1_SET_ALL_POS)) /**< EN1_SET_ALL Mask */ +#define MXC_F_GPIO_EN1_SET_ALL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_EN1_SET_ALL_POS)) /**< \ + EN1_SET_ALL \ + Mask */ /** * GPIO Alternate Function Clear. Writing a 1 to one or more bits in @@ -777,9 +795,11 @@ typedef enum { * affecting other bits in that register. */ #define MXC_F_GPIO_EN1_CLR_ALL_POS 0 /**< EN1_CLR_ALL Position */ -#define MXC_F_GPIO_EN1_CLR_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_EN1_CLR_ALL_POS)) /**< EN1_CLR_ALL Mask */ +#define MXC_F_GPIO_EN1_CLR_ALL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_EN1_CLR_ALL_POS)) /**< \ + EN1_CLR_ALL \ + Mask */ /** * GPIO Alternate Function Enable Register. Each bit in this register @@ -787,19 +807,24 @@ typedef enum { * this port. */ #define MXC_F_GPIO_EN2_GPIO_EN2_POS 0 /**< EN2_GPIO_EN2 Position */ -#define MXC_F_GPIO_EN2_GPIO_EN2 \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_EN2_GPIO_EN2_POS)) /**< EN2_GPIO_EN2 Mask */ -#define MXC_V_GPIO_EN2_GPIO_EN2_PRIMARY \ +#define MXC_F_GPIO_EN2_GPIO_EN2 \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_EN2_GPIO_EN2_POS)) /**< \ + EN2_GPIO_EN2 \ + Mask */ +#define MXC_V_GPIO_EN2_GPIO_EN2_PRIMARY \ ((uint32_t)0x0UL) /**< EN2_GPIO_EN2_PRIMARY Value */ -#define MXC_S_GPIO_EN2_GPIO_EN2_PRIMARY \ - (MXC_V_GPIO_EN2_GPIO_EN2_PRIMARY \ - << MXC_F_GPIO_EN2_GPIO_EN2_POS) /**< EN2_GPIO_EN2_PRIMARY Setting */ -#define MXC_V_GPIO_EN2_GPIO_EN2_SECONDARY \ +#define MXC_S_GPIO_EN2_GPIO_EN2_PRIMARY \ + (MXC_V_GPIO_EN2_GPIO_EN2_PRIMARY \ + << MXC_F_GPIO_EN2_GPIO_EN2_POS) /**< \ + EN2_GPIO_EN2_PRIMARY \ + Setting \ + */ +#define MXC_V_GPIO_EN2_GPIO_EN2_SECONDARY \ ((uint32_t)0x1UL) /**< EN2_GPIO_EN2_SECONDARY Value */ -#define MXC_S_GPIO_EN2_GPIO_EN2_SECONDARY \ - (MXC_V_GPIO_EN2_GPIO_EN2_SECONDARY \ - << MXC_F_GPIO_EN2_GPIO_EN2_POS) /**< EN2_GPIO_EN2_SECONDARY Setting \ +#define MXC_S_GPIO_EN2_GPIO_EN2_SECONDARY \ + (MXC_V_GPIO_EN2_GPIO_EN2_SECONDARY \ + << MXC_F_GPIO_EN2_GPIO_EN2_POS) /**< EN2_GPIO_EN2_SECONDARY Setting \ */ /** @@ -808,9 +833,11 @@ typedef enum { * affecting other bits in that register. */ #define MXC_F_GPIO_EN2_SET_ALL_POS 0 /**< EN2_SET_ALL Position */ -#define MXC_F_GPIO_EN2_SET_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_EN2_SET_ALL_POS)) /**< EN2_SET_ALL Mask */ +#define MXC_F_GPIO_EN2_SET_ALL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_EN2_SET_ALL_POS)) /**< \ + EN2_SET_ALL \ + Mask */ /** * GPIO Wake Alternate Function Clear. Writing a 1 to one or more bits @@ -818,9 +845,11 @@ typedef enum { * without affecting other bits in that register. */ #define MXC_F_GPIO_EN2_CLR_ALL_POS 0 /**< EN2_CLR_ALL Position */ -#define MXC_F_GPIO_EN2_CLR_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_EN2_CLR_ALL_POS)) /**< EN2_CLR_ALL Mask */ +#define MXC_F_GPIO_EN2_CLR_ALL \ + ((uint32_t)(0xFFFFFFFFUL \ + << MXC_F_GPIO_EN2_CLR_ALL_POS)) /**< \ + EN2_CLR_ALL \ + Mask */ /** * GPIO Drive Strength Register. Each bit in this register selects @@ -828,13 +857,13 @@ typedef enum { * Datasheet for sink/source current of GPIO pins in each mode. */ #define MXC_F_GPIO_DS_DS_POS 0 /**< DS_DS Position */ -#define MXC_F_GPIO_DS_DS \ +#define MXC_F_GPIO_DS_DS \ ((uint32_t)(0xFFFFFFFFUL << MXC_F_GPIO_DS_DS_POS)) /**< DS_DS Mask */ #define MXC_V_GPIO_DS_DS_LD ((uint32_t)0x0UL) /**< DS_DS_LD Value */ -#define MXC_S_GPIO_DS_DS_LD \ +#define MXC_S_GPIO_DS_DS_LD \ (MXC_V_GPIO_DS_DS_LD << MXC_F_GPIO_DS_DS_POS) /**< DS_DS_LD Setting */ -#define MXC_V_GPIO_DS_DS_HD ((uint32_t)0x1UL) /**< DS_DS_HD Value */ -#define MXC_S_GPIO_DS_DS_HD \ +#define MXC_V_GPIO_DS_DS_HD ((uint32_t)0x1UL) /**< DS_DS_HD Value */ +#define MXC_S_GPIO_DS_DS_HD \ (MXC_V_GPIO_DS_DS_HD << MXC_F_GPIO_DS_DS_POS) /**< DS_DS_HD Setting */ /** @@ -844,23 +873,23 @@ typedef enum { */ #define MXC_F_GPIO_DS1_ALL_POS 0 /**< DS1_ALL Position */ #define MXC_F_GPIO_DS1_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_DS1_ALL_POS)) /**< DS1_ALL Mask */ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_GPIO_DS1_ALL_POS)) /**< DS1_ALL Mask \ + */ /** * GPIO Pull Select Mode. */ #define MXC_F_GPIO_PS_ALL_POS 0 /**< PS_ALL Position */ -#define MXC_F_GPIO_PS_ALL \ - ((uint32_t)(0xFFFFFFFFUL << MXC_F_GPIO_PS_ALL_POS)) /**< PS_ALL Mask \ +#define MXC_F_GPIO_PS_ALL \ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_GPIO_PS_ALL_POS)) /**< PS_ALL Mask \ */ /** * GPIO Voltage Select. */ #define MXC_F_GPIO_VSSEL_ALL_POS 0 /**< VSSEL_ALL Position */ -#define MXC_F_GPIO_VSSEL_ALL \ - ((uint32_t)(0xFFFFFFFFUL \ - << MXC_F_GPIO_VSSEL_ALL_POS)) /**< VSSEL_ALL Mask */ +#define MXC_F_GPIO_VSSEL_ALL \ + ((uint32_t)(0xFFFFFFFFUL << MXC_F_GPIO_VSSEL_ALL_POS)) /**< VSSEL_ALL \ + Mask */ #endif /* _GPIO_REGS_H_ */ diff --git a/chip/max32660/hwtimer_chip.c b/chip/max32660/hwtimer_chip.c index 5417e161b2..b6c39f4036 100644 --- a/chip/max32660/hwtimer_chip.c +++ b/chip/max32660/hwtimer_chip.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,15 +6,15 @@ /* MAX32660 HW Timer module for Chrome EC */ #include "clock.h" -#include "console.h" #include "common.h" +#include "console.h" +#include "gcr_regs.h" #include "hooks.h" #include "hwtimer.h" +#include "registers.h" #include "task.h" #include "timer.h" -#include "registers.h" #include "tmr_regs.h" -#include "gcr_regs.h" /* Define the rollover timer */ #define TMR_ROLLOVER MXC_TMR0 @@ -41,36 +41,36 @@ static uint32_t last_deadline; /* brief Timer prescaler values */ enum tmr_pres { - TMR_PRES_1 = MXC_V_TMR_CN_PRES_DIV1, /// Divide input clock by 1 - TMR_PRES_2 = MXC_V_TMR_CN_PRES_DIV2, /// Divide input clock by 2 - TMR_PRES_4 = MXC_V_TMR_CN_PRES_DIV4, /// Divide input clock by 4 - TMR_PRES_8 = MXC_V_TMR_CN_PRES_DIV8, /// Divide input clock by 8 - TMR_PRES_16 = MXC_V_TMR_CN_PRES_DIV16, /// Divide input clock by 16 - TMR_PRES_32 = MXC_V_TMR_CN_PRES_DIV32, /// Divide input clock by 32 - TMR_PRES_64 = MXC_V_TMR_CN_PRES_DIV64, /// Divide input clock by 64 + TMR_PRES_1 = MXC_V_TMR_CN_PRES_DIV1, /// Divide input clock by 1 + TMR_PRES_2 = MXC_V_TMR_CN_PRES_DIV2, /// Divide input clock by 2 + TMR_PRES_4 = MXC_V_TMR_CN_PRES_DIV4, /// Divide input clock by 4 + TMR_PRES_8 = MXC_V_TMR_CN_PRES_DIV8, /// Divide input clock by 8 + TMR_PRES_16 = MXC_V_TMR_CN_PRES_DIV16, /// Divide input clock by 16 + TMR_PRES_32 = MXC_V_TMR_CN_PRES_DIV32, /// Divide input clock by 32 + TMR_PRES_64 = MXC_V_TMR_CN_PRES_DIV64, /// Divide input clock by 64 TMR_PRES_128 = MXC_V_TMR_CN_PRES_DIV128, /// Divide input clock by 128 - TMR_PRES_256 = - (0x20 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock by 256 - TMR_PRES_512 = - (0x21 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock by 512 - TMR_PRES_1024 = - (0x22 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock by 1024 - TMR_PRES_2048 = - (0x23 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock by 2048 - TMR_PRES_4096 = - (0x24 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock by 4096 + TMR_PRES_256 = (0x20 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock + /// by 256 + TMR_PRES_512 = (0x21 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock + /// by 512 + TMR_PRES_1024 = (0x22 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock + /// by 1024 + TMR_PRES_2048 = (0x23 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock + /// by 2048 + TMR_PRES_4096 = (0x24 << MXC_F_TMR_CN_PRES_POS), /// Divide input clock + /// by 4096 }; /* Timer modes */ enum tmr_mode { TMR_MODE_ONESHOT = MXC_V_TMR_CN_TMODE_ONESHOT, /// Timer Mode ONESHOT - TMR_MODE_CONTINUOUS = - MXC_V_TMR_CN_TMODE_CONTINUOUS, /// Timer Mode CONTINUOUS + TMR_MODE_CONTINUOUS = MXC_V_TMR_CN_TMODE_CONTINUOUS, /// Timer Mode + /// CONTINUOUS TMR_MODE_COUNTER = MXC_V_TMR_CN_TMODE_COUNTER, /// Timer Mode COUNTER - TMR_MODE_PWM = MXC_V_TMR_CN_TMODE_PWM, /// Timer Mode PWM + TMR_MODE_PWM = MXC_V_TMR_CN_TMODE_PWM, /// Timer Mode PWM TMR_MODE_CAPTURE = MXC_V_TMR_CN_TMODE_CAPTURE, /// Timer Mode CAPTURE TMR_MODE_COMPARE = MXC_V_TMR_CN_TMODE_COMPARE, /// Timer Mode COMPARE - TMR_MODE_GATED = MXC_V_TMR_CN_TMODE_GATED, /// Timer Mode GATED + TMR_MODE_GATED = MXC_V_TMR_CN_TMODE_GATED, /// Timer Mode GATED TMR_MODE_CAPTURE_COMPARE = MXC_V_TMR_CN_TMODE_CAPTURECOMPARE /// Timer Mode CAPTURECOMPARE }; @@ -220,7 +220,7 @@ int __hw_clock_source_init(uint32_t start_t) return TMR_EVENT_IRQ; } -static int hwtimer_display(int argc, char **argv) +static int hwtimer_display(int argc, const char **argv) { CPRINTS(" TMR_EVENT count 0x%08x", TMR_EVENT->cnt); CPRINTS(" TMR_ROLLOVER count 0x%08x", TMR_ROLLOVER->cnt); diff --git a/chip/max32660/i2c_chip.c b/chip/max32660/i2c_chip.c index 1279e9e50c..1e4dd3f365 100644 --- a/chip/max32660/i2c_chip.c +++ b/chip/max32660/i2c_chip.c @@ -1,32 +1,34 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* MAX32660 I2C port module for Chrome EC. */ -#include -#include #include "common.h" #include "config_chip.h" +#include "gpio.h" #include "hooks.h" #include "i2c.h" +#include "i2c_regs.h" +#include "registers.h" #include "stdbool.h" #include "system.h" #include "task.h" -#include "registers.h" -#include "i2c_regs.h" + +#include +#include /** * Byte to use if the EC HOST requested more data - * than the I2C Slave is able to send. + * than the I2C Target is able to send. */ #define EC_PADDING_BYTE 0xec /* **** Definitions **** */ -#define I2C_ERROR \ - (MXC_F_I2C_INT_FL0_ARB_ER | MXC_F_I2C_INT_FL0_TO_ER | \ - MXC_F_I2C_INT_FL0_ADDR_NACK_ER | MXC_F_I2C_INT_FL0_DATA_ER | \ +#define I2C_ERROR \ + (MXC_F_I2C_INT_FL0_ARB_ER | MXC_F_I2C_INT_FL0_TO_ER | \ + MXC_F_I2C_INT_FL0_ADDR_NACK_ER | MXC_F_I2C_INT_FL0_DATA_ER | \ MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER | MXC_F_I2C_INT_FL0_START_ER | \ MXC_F_I2C_INT_FL0_STOP_ER) @@ -34,7 +36,7 @@ #define T_HIGH_MIN (60) /* tHIGH minimum in nanoseconds */ #define T_R_MAX_HS (40) /* tR maximum for high speed mode in nanoseconds */ #define T_F_MAX_HS (40) /* tF maximum for high speed mode in nanoseconds */ -#define T_AF_MIN (10) /* tAF minimun in nanoseconds */ +#define T_AF_MIN (10) /* tAF minimun in nanoseconds */ /** * typedef i2c_speed_t - I2C speed modes. @@ -59,23 +61,24 @@ typedef enum { } i2c_autoflush_disable_t; /** - * typedef i2c_master_state_t - Available transaction states for I2C Master. + * typedef i2c_controller_state_t - Available transaction states for I2C + * Controller. */ typedef enum { - I2C_MASTER_IDLE = 1, - I2C_MASTER_START = 2, - I2C_MASTER_WRITE_COMPLETE = 3, - I2C_MASTER_READ_COMPLETE = 4 -} i2c_master_state_t; + I2C_CONTROLLER_IDLE = 1, + I2C_CONTROLLER_START = 2, + I2C_CONTROLLER_WRITE_COMPLETE = 3, + I2C_CONTROLLER_READ_COMPLETE = 4 +} i2c_controller_state_t; /** - * typedef i2c_slave_state_t - Available transaction states for I2C Slave. + * typedef i2c_target_state_t - Available transaction states for I2C Target. */ typedef enum { - I2C_SLAVE_WRITE_COMPLETE = 0, - I2C_SLAVE_ADDR_MATCH_READ = 1, - I2C_SLAVE_ADDR_MATCH_WRITE = 2, -} i2c_slave_state_t; + I2C_TARGET_WRITE_COMPLETE = 0, + I2C_TARGET_ADDR_MATCH_READ = 1, + I2C_TARGET_ADDR_MATCH_WRITE = 2, +} i2c_target_state_t; /** * typedef i2c_req_t - I2C Transaction request. @@ -93,29 +96,29 @@ typedef struct { /** * struct i2c_req - I2C Transaction request. * @addr: I2C 7-bit Address right aligned, bit 6 to bit 0. - * Only supports 7-bit addressing. LSb of the given - * address will be used as the read/write bit, the addr - * will not be shifted. Used for both master and slave - * transactions. - * @addr_match_flag: Indicates which slave address was matched. - * 0x1 indicates first slave address matched. - * 0x2 indicates second slave address matched. - * 0x4 indicates third slave address matched. - * 0x8 indicates fourth slave address matched. - * @tx_data: Data for master write/slave read. - * @rx_data: Data for master read/slave write. + * Only supports 7-bit addressing. LSb of the given + * address will be used as the read/write bit, the addr + * will not be shifted. Used for both controller and target + * transactions. + * @addr_match_flag: Indicates which target address was matched. + * 0x1 indicates first target address matched. + * 0x2 indicates second target address matched. + * 0x4 indicates third target address matched. + * 0x8 indicates fourth target address matched. + * @tx_data: Data for controller write/target read. + * @rx_data: Data for controller read/target write. * @received_count: Number of rx bytes sent. - * @tx_remain: Number of bytes to transmit to the master. This + * @tx_remain: Number of bytes to transmit to the controller. This * value is -1 if should clock stretch, 0 if start * sending EC_PADDING_BYTE. Any other values in this - * field will transmit data to the Master. - * @state: I2C slave state that indicates address match, read and + * field will transmit data to the Controller. + * @state: I2C target state that indicates address match, read and * write status. * @restart: Restart or stop bit indicator. * 0 to send a stop bit at the end of the transaction * Non-zero to send a restart at end of the transaction - * Only used for Master transactions. - * @response_pending: Indicates that a response to the I2C master + * Only used for Controller transactions. + * @response_pending: Indicates that a response to the I2C controller * is pending. * @expecting_done: Indicates if an I2C done flag is expected. This * is used by the driver to determine the order to process @@ -129,9 +132,9 @@ struct i2c_req { uint8_t addr_match_flag; const uint8_t *tx_data; uint8_t *rx_data; - volatile unsigned received_count; + volatile unsigned int received_count; volatile int tx_remain; - volatile i2c_slave_state_t state; + volatile i2c_target_state_t state; volatile int restart; volatile bool response_pending; volatile bool expecting_done; @@ -167,35 +170,35 @@ static struct i2c_port_data pdata[I2C_PORT_COUNT]; /* **** Function Prototypes **** */ static int i2c_init_peripheral(mxc_i2c_regs_t *i2c, i2c_speed_t i2cspeed); -static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, - int stop, const uint8_t *data, int len, - int restart); -static int i2c_master_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, - int stop, uint8_t *data, int len, int restart); +static int i2c_controller_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, + int stop, const uint8_t *data, int len, + int restart); +static int i2c_controller_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, + int stop, uint8_t *data, int len, int restart); -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS static void init_i2cs(int port); -static int i2c_slave_async(mxc_i2c_regs_t *i2c, i2c_req_t *req); -static void i2c_slave_handler(mxc_i2c_regs_t *i2c); -#endif /* CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS */ +static int i2c_target_async(mxc_i2c_regs_t *i2c, i2c_req_t *req); +static void i2c_target_handler(mxc_i2c_regs_t *i2c); +#endif /* CONFIG_HOSTCMD_I2C_ADDR_FLAGS */ /* Port address for each I2C */ -static mxc_i2c_regs_t *i2c_bus_ports[] = {MXC_I2C0, MXC_I2C1}; +static mxc_i2c_regs_t *i2c_bus_ports[] = { MXC_I2C0, MXC_I2C1 }; -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS static void i2c_send_board_response(int len); static void i2c_process_board_command(int read, int addr, int len); void board_i2c_process(int read, uint8_t addr, int len, char *buffer, void (*send_response)(int len)); -#endif /* CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS */ -#endif /* CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS */ +#endif /* CONFIG_BOARD_I2C_ADDR_FLAGS */ +#endif /* CONFIG_HOSTCMD_I2C_ADDR_FLAGS */ /** - * chip_i2c_xfer() - Low Level function for I2C Master Reads and Writes. + * chip_i2c_xfer() - Low Level function for I2C Controller Reads and Writes. * @port: Port to access - * @slave_addr: Slave device address + * @addr_flags: Device address and flags * @out: Data to send * @out_size: Number of bytes to send * @in: Destination buffer for received data @@ -210,7 +213,7 @@ void board_i2c_process(int read, uint8_t addr, int len, char *buffer, * * Return EC_SUCCESS, or non-zero if error. */ -int chip_i2c_xfer(int port, const uint16_t slave_addr_flags, const uint8_t *out, +int chip_i2c_xfer(int port, const uint16_t addr_flags, const uint8_t *out, int out_size, uint8_t *in, int in_size, int flags) { int xfer_start; @@ -221,16 +224,17 @@ int chip_i2c_xfer(int port, const uint16_t slave_addr_flags, const uint8_t *out, xfer_stop = flags & I2C_XFER_STOP; if (out_size) { - status = i2c_master_write(i2c_bus_ports[port], slave_addr_flags, - xfer_start, xfer_stop, out, out_size, - 1); + status = i2c_controller_write(i2c_bus_ports[port], addr_flags, + xfer_start, xfer_stop, out, + out_size, 1); if (status != EC_SUCCESS) { return status; } } if (in_size) { - status = i2c_master_read(i2c_bus_ports[port], slave_addr_flags, - xfer_start, xfer_stop, in, in_size, 0); + status = i2c_controller_read(i2c_bus_ports[port], addr_flags, + xfer_start, xfer_stop, in, in_size, + 0); if (status != EC_SUCCESS) { return status; } @@ -280,34 +284,33 @@ void i2c_init(void) i2c_set_timeout(i, 0); } -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS - /* Initialize the I2C Slave */ +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS + /* Initialize the I2C Target */ init_i2cs(I2C_PORT_EC); -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS /* - * Set the secondary I2C slave address for the board. + * Set the secondary I2C target address for the board. */ - /* Index the secondary slave address. */ - i2c_bus_ports[I2C_PORT_EC]->slave_addr = - (i2c_bus_ports[I2C_PORT_EC]->slave_addr & - ~(MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_IDX | - MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_DIS)) | - (1 << MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_IDX_POS); - /* Set the secondary slave address. */ - i2c_bus_ports[I2C_PORT_EC]->slave_addr = - (1 << MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_IDX_POS) | - CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS; -#endif /* CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS */ -#endif /* CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS */ - + /* Index the secondary target address. */ + i2c_bus_ports[I2C_PORT_EC]->target_addr = + (i2c_bus_ports[I2C_PORT_EC]->target_addr & + ~(MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_IDX | + MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_DIS)) | + (1 << MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_IDX_POS); + /* Set the secondary target address. */ + i2c_bus_ports[I2C_PORT_EC]->target_addr = + (1 << MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_IDX_POS) | + CONFIG_BOARD_I2C_ADDR_FLAGS; +#endif /* CONFIG_BOARD_I2C_ADDR_FLAGS */ +#endif /* CONFIG_HOSTCMD_I2C_ADDR_FLAGS */ } /** - * I2C Slave Implentation + * I2C Peripheral Implementation */ -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS /* IRQ for each I2C */ -static uint32_t i2c_bus_irqs[] = {EC_I2C0_IRQn, EC_I2C1_IRQn}; +static uint32_t i2c_bus_irqs[] = { EC_I2C0_IRQn, EC_I2C1_IRQn }; /** * Buffer for received host command packets (including prefix byte on request, @@ -320,7 +323,7 @@ static uint8_t *const host_buffer = host_buffer_padded + 2; static uint8_t params_copy[I2C_MAX_HOST_PACKET_SIZE] __aligned(4); static struct host_packet i2c_packet; -static i2c_req_t req_slave; +static i2c_req_t req_target; volatile int ec_pending_response = 0; /** @@ -341,11 +344,11 @@ static void i2c_send_response_packet(struct host_packet *pkt) *out++ = size; /* Host_buffer data range. */ - req_slave.tx_remain = size + 2; - req_slave.response_pending = true; + req_target.tx_remain = size + 2; + req_target.response_pending = true; /* Call the handler to send the response packet. */ - i2c_slave_handler(i2c_bus_ports[I2C_PORT_EC]); + i2c_target_handler(i2c_bus_ports[I2C_PORT_EC]); } /** @@ -383,24 +386,24 @@ static void i2c_process_command(void) } /** - * i2c_slave_service() - Called by the I2C slave interrupt controller. + * i2c_target_service() - Called by the I2C target interrupt controller. * @req: Request currently being processed. */ -void i2c_slave_service(i2c_req_t *req) +void i2c_target_service(i2c_req_t *req) { - /* Check if there was a host command (I2C master write). */ - if (req->state == I2C_SLAVE_ADDR_MATCH_WRITE) { - req->state = I2C_SLAVE_WRITE_COMPLETE; + /* Check if there was a host command (I2C controller write). */ + if (req->state == I2C_TARGET_ADDR_MATCH_WRITE) { + req->state = I2C_TARGET_WRITE_COMPLETE; /* A response to this write is pending. */ /* Assume that there is nothing to send back to the HOST. */ req->tx_remain = -1; -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS if (req->addr_match_flag != 0x1) { - i2c_process_board_command( - 0, CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS, - req->received_count); + i2c_process_board_command(0, + CONFIG_BOARD_I2C_ADDR_FLAGS, + req->received_count); } else -#endif /* CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS */ +#endif /* CONFIG_BOARD_I2C_ADDR_FLAGS */ { i2c_process_command(); } @@ -408,38 +411,39 @@ void i2c_slave_service(i2c_req_t *req) } /** - * I2C0_IRQHandler() - Async Handler for I2C Slave driver. + * I2C0_IRQHandler() - Async Handler for I2C Target driver. */ -void I2C0_IRQHandler(void) +static void I2C0_IRQHandler(void) { - i2c_slave_handler(i2c_bus_ports[0]); + i2c_target_handler(i2c_bus_ports[0]); } /** - * I2C1_IRQHandler() - Async Handler for I2C Slave driver. + * I2C1_IRQHandler() - Async Handler for I2C Target driver. */ -void I2C1_IRQHandler(void) +static void I2C1_IRQHandler(void) { - i2c_slave_handler(i2c_bus_ports[1]); + i2c_target_handler(i2c_bus_ports[1]); } DECLARE_IRQ(EC_I2C0_IRQn, I2C0_IRQHandler, 1); DECLARE_IRQ(EC_I2C1_IRQn, I2C1_IRQHandler, 1); /** - * i2c_slave_service_read() - Services the Master I2C read from the slave. + * i2c_target_service_read() - Services the Controller I2C read from the target. * @i2c: I2C peripheral pointer. * @req: Pointer to the request info. */ -static void i2c_slave_service_read(mxc_i2c_regs_t *i2c, i2c_req_t *req) +static void i2c_target_service_read(mxc_i2c_regs_t *i2c, i2c_req_t *req) { /* * Clear the RX Threshold interrupt if set. Make sure and preserve - * a possible done bit, address match, or multiple slave address + * a possible done bit, address match, or multiple target address * flags. */ - i2c->int_fl0 = i2c->int_fl0 & ~(MXC_F_I2C_INT_FL0_ADDR_MATCH | - MXC_F_I2C_INT_FL0_MAMI_MASK | MXC_F_I2C_INT_FL0_DONE); + i2c->int_fl0 = i2c->int_fl0 & + ~(MXC_F_I2C_INT_FL0_ADDR_MATCH | + MXC_F_I2C_INT_FL0_MAMI_MASK | MXC_F_I2C_INT_FL0_DONE); i2c->int_fl1 = i2c->int_fl1; /* * If there is nothing to transmit to the EC HOST, then default @@ -448,19 +452,22 @@ static void i2c_slave_service_read(mxc_i2c_regs_t *i2c, i2c_req_t *req) if (req->tx_remain < 0) { return; } - /* If there is data to send to the Master then fill the TX FIFO. */ + /* If there is data to send to the Controller then fill the TX FIFO. */ if (req->tx_remain != 0) { - /* There is no longer a response pending from the slave to the master. */ + /* + * There is no longer a response pending from the target to the + * controller. + */ req->response_pending = false; - /* Fill the FIFO with data to transimit to the I2C Master. */ + /* Fill the FIFO with data to transimit to the I2C Controller */ while ((req->tx_remain > 0) && - !(i2c->status & MXC_F_I2C_STATUS_TX_FULL)) { + !(i2c->status & MXC_F_I2C_STATUS_TX_FULL)) { i2c->fifo = *(req->tx_data)++; req->tx_remain--; } } /* - * If we have sent everything to the Master that we can, + * If we have sent everything to the Controller that we can, * then send padding byte. */ if (req->tx_remain == 0) { @@ -472,22 +479,23 @@ static void i2c_slave_service_read(mxc_i2c_regs_t *i2c, i2c_req_t *req) } /* Set the threshold for TX, the threshold is a four bit field. */ i2c->tx_ctrl0 = ((i2c->tx_ctrl0 & ~(MXC_F_I2C_TX_CTRL0_TX_THRESH)) | - (2 << MXC_F_I2C_TX_CTRL0_TX_THRESH_POS)); + (2 << MXC_F_I2C_TX_CTRL0_TX_THRESH_POS)); /* Enable interrupts of interest. */ i2c->int_en0 = MXC_F_I2C_INT_EN0_TX_THRESH | MXC_F_I2C_INT_EN0_DONE | - I2C_ERROR | MXC_F_I2C_INT_EN0_ADDR_MATCH; + I2C_ERROR | MXC_F_I2C_INT_EN0_ADDR_MATCH; } /** - * i2c_slave_service_write() - Services the Master I2C write to the slave. + * i2c_target_service_write() - Services the Controller I2C write to the target. * @i2c: I2C peripheral pointer. * @req: Pointer to the request info. */ -static void i2c_slave_service_write(mxc_i2c_regs_t *i2c, i2c_req_t *req) +static void i2c_target_service_write(mxc_i2c_regs_t *i2c, i2c_req_t *req) { /* Clear all flags except address matching and done. */ - i2c->int_fl0 = i2c->int_fl0 & ~(MXC_F_I2C_INT_FL0_ADDR_MATCH | - MXC_F_I2C_INT_FL0_MAMI_MASK | MXC_F_I2C_INT_FL0_DONE); + i2c->int_fl0 = i2c->int_fl0 & + ~(MXC_F_I2C_INT_FL0_ADDR_MATCH | + MXC_F_I2C_INT_FL0_MAMI_MASK | MXC_F_I2C_INT_FL0_DONE); i2c->int_fl1 = i2c->int_fl1; /* Read out any data in the RX FIFO. */ while (!(i2c->status & MXC_F_I2C_STATUS_RX_EMPTY)) { @@ -495,17 +503,16 @@ static void i2c_slave_service_write(mxc_i2c_regs_t *i2c, i2c_req_t *req) req->received_count++; } /* Set the RX threshold interrupt level. */ - i2c->rx_ctrl0 = ((i2c->rx_ctrl0 & - ~(MXC_F_I2C_RX_CTRL0_RX_THRESH)) | - (MXC_I2C_FIFO_DEPTH - 1) - << MXC_F_I2C_RX_CTRL0_RX_THRESH_POS); + i2c->rx_ctrl0 = + ((i2c->rx_ctrl0 & ~(MXC_F_I2C_RX_CTRL0_RX_THRESH)) | + (MXC_I2C_FIFO_DEPTH - 1) << MXC_F_I2C_RX_CTRL0_RX_THRESH_POS); /* Enable interrupts of interest. */ i2c->int_en0 = MXC_F_I2C_INT_EN0_RX_THRESH | MXC_F_I2C_INT_EN0_DONE | - I2C_ERROR | MXC_F_I2C_INT_EN0_ADDR_MATCH; + I2C_ERROR | MXC_F_I2C_INT_EN0_ADDR_MATCH; } /** - * i2c_slave_handler() - I2C interrupt handler. + * i2c_target_handler() - I2C interrupt handler. * @i2c: Base address of the I2C module. * * This function should be called by the application from the interrupt @@ -513,22 +520,22 @@ static void i2c_slave_service_write(mxc_i2c_regs_t *i2c, i2c_req_t *req) * can be periodically called by the application if I2C interrupts are * disabled. */ -static void i2c_slave_handler(mxc_i2c_regs_t *i2c) +static void i2c_target_handler(mxc_i2c_regs_t *i2c) { i2c_req_t *req; /* Get the request context for this interrupt. */ req = states[MXC_I2C_GET_IDX(i2c)].req; - /* Check for an address match flag. */ - if ((req->expecting_start) && (i2c->int_fl0 & MXC_F_I2C_INT_FL0_ADDR_MATCH)) { + if ((req->expecting_start) && + (i2c->int_fl0 & MXC_F_I2C_INT_FL0_ADDR_MATCH)) { req->expecting_done = true; req->expecting_start = false; /* - * Save the address match index to identify - * targeted slave address. - */ + * Save the address match index to identify + * targeted target address. + */ req->addr_match_flag = (i2c->int_fl0 & MXC_F_I2C_INT_FL0_MAMI_MASK) >> MXC_F_I2C_INT_FL0_MAMI_POS; @@ -538,51 +545,64 @@ static void i2c_slave_handler(mxc_i2c_regs_t *i2c) i2c->int_fl1 = i2c->int_fl1; /* Only enable done, error and address match interrupts. */ - i2c->int_en0 = MXC_F_I2C_INT_EN0_DONE | - I2C_ERROR | MXC_F_I2C_INT_EN0_ADDR_MATCH; + i2c->int_en0 = MXC_F_I2C_INT_EN0_DONE | I2C_ERROR | + MXC_F_I2C_INT_EN0_ADDR_MATCH; - /* Check if Master is writing to the slave. */ + /* Check if Controller is writing to the target. */ if (!(i2c->ctrl & MXC_F_I2C_CTRL_READ)) { - /* I2C Master is writing to the slave. */ + /* I2C Controller is writing to the target. */ req->rx_data = host_buffer; req->tx_data = host_buffer; req->tx_remain = -1; /* Nothing to send yet. */ - /* Clear the RX (receive from I2C Master) byte counter. */ + /* + * Clear the RX (receive from I2C Controller) byte + * counter. + */ req->received_count = 0; - req->state = I2C_SLAVE_ADDR_MATCH_WRITE; - /* The Master is writing, there can not be a response pending yet. */ + req->state = I2C_TARGET_ADDR_MATCH_WRITE; + /* + * The Controller is writing, there can not be a + * response pending yet. + */ req->response_pending = false; /* Set the RX threshold interrupt level. */ - i2c->rx_ctrl0 = ((i2c->rx_ctrl0 & - ~(MXC_F_I2C_RX_CTRL0_RX_THRESH)) | - (MXC_I2C_FIFO_DEPTH - 2) - << MXC_F_I2C_RX_CTRL0_RX_THRESH_POS); + i2c->rx_ctrl0 = + ((i2c->rx_ctrl0 & + ~(MXC_F_I2C_RX_CTRL0_RX_THRESH)) | + (MXC_I2C_FIFO_DEPTH - 2) + << MXC_F_I2C_RX_CTRL0_RX_THRESH_POS); } else { - /* The Master is reading from the slave. */ - /* Start transmitting to the Master from the start of buffer. */ + /* + * The Controller is reading from the target. + * Start transmitting to the Controller from the start + * of buffer. + */ req->tx_data = host_buffer; - req->state = I2C_SLAVE_ADDR_MATCH_READ; - /* Set the threshold for TX, the threshold is a four bit field. */ - i2c->tx_ctrl0 = ((i2c->tx_ctrl0 & ~(MXC_F_I2C_TX_CTRL0_TX_THRESH)) | - (2 << MXC_F_I2C_TX_CTRL0_TX_THRESH_POS)); -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS + req->state = I2C_TARGET_ADDR_MATCH_READ; + /* Set the threshold for TX, the threshold is a four bit + * field. */ + i2c->tx_ctrl0 = + ((i2c->tx_ctrl0 & + ~(MXC_F_I2C_TX_CTRL0_TX_THRESH)) | + (2 << MXC_F_I2C_TX_CTRL0_TX_THRESH_POS)); +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS /* - * If this is a board address match and there is not - * already a pending response to the I2C Master then - * fulfill this board read request. - */ + * If this is a board address match and there is not + * already a pending response to the I2C Controller then + * fulfill this board read request. + */ if ((req->response_pending == 0) && - (req->addr_match_flag != 0x1)) { + (req->addr_match_flag != 0x1)) { i2c_process_board_command( - 1, CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS, 0); + 1, CONFIG_BOARD_I2C_ADDR_FLAGS, 0); } -#endif /* CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS */ +#endif /* CONFIG_BOARD_I2C_ADDR_FLAGS */ } /* Only enable done, error and address match interrupts. */ - i2c->int_en0 = MXC_F_I2C_INT_EN0_DONE | - I2C_ERROR | MXC_F_I2C_INT_EN0_ADDR_MATCH; + i2c->int_en0 = MXC_F_I2C_INT_EN0_DONE | I2C_ERROR | + MXC_F_I2C_INT_EN0_ADDR_MATCH; /* Inhibit sleep mode when addressed until STOPF flag is set. */ - disable_sleep(SLEEP_MASK_I2C_SLAVE); + disable_sleep(SLEEP_MASK_I2C_PERIPHERAL); } /* Check for DONE interrupt. */ @@ -591,15 +611,16 @@ static void i2c_slave_handler(mxc_i2c_regs_t *i2c) req->expecting_done = false; /* Clear all interrupts except a possible address match. */ i2c->int_fl0 = i2c->int_fl0 & ~(MXC_F_I2C_INT_FL0_ADDR_MATCH | - MXC_F_I2C_INT_FL0_MAMI_MASK); + MXC_F_I2C_INT_FL0_MAMI_MASK); i2c->int_fl1 = i2c->int_fl1; /* Only enable done, error and address match interrupts. */ - i2c->int_en0 = MXC_F_I2C_INT_EN0_DONE | - I2C_ERROR | MXC_F_I2C_INT_EN0_ADDR_MATCH; + i2c->int_en0 = MXC_F_I2C_INT_EN0_DONE | I2C_ERROR | + MXC_F_I2C_INT_EN0_ADDR_MATCH; i2c->int_en1 = 0; - /* If this was a DONE after a write then read the fifo until empty. */ - if (req->state == I2C_SLAVE_ADDR_MATCH_WRITE) { + /* If this was a DONE after a write then read the fifo until + * empty. */ + if (req->state == I2C_TARGET_ADDR_MATCH_WRITE) { /* Read out any data in the RX FIFO. */ while (!(i2c->status & MXC_F_I2C_STATUS_RX_EMPTY)) { *(req->rx_data)++ = i2c->fifo; @@ -611,14 +632,14 @@ static void i2c_slave_handler(mxc_i2c_regs_t *i2c) /* Manually clear the TX FIFO. */ i2c->tx_ctrl0 |= MXC_F_I2C_TX_CTRL0_TX_FLUSH; - /* Process the Master write that just finished. */ - i2c_slave_service(req); + /* Process the Controller write that just finished. */ + i2c_target_service(req); /* No longer inhibit deep sleep after done. */ - enable_sleep(SLEEP_MASK_I2C_SLAVE); + enable_sleep(SLEEP_MASK_I2C_PERIPHERAL); } - /* Check for an I2C Master Read or Write. */ + /* Check for an I2C Controller Read or Write. */ if (i2c->int_fl0 & I2C_ERROR) { /* Clear the error interrupt. */ i2c->int_fl0 = I2C_ERROR; @@ -633,18 +654,17 @@ static void i2c_slave_handler(mxc_i2c_regs_t *i2c) /* Cycle the I2C peripheral enable on error. */ i2c->ctrl = 0; i2c->ctrl = MXC_F_I2C_CTRL_I2C_EN; - } else if (req->state == I2C_SLAVE_ADDR_MATCH_READ) { - /* Service a read request from the I2C Master. */ - i2c_slave_service_read(i2c, req); - } else if (req->state == I2C_SLAVE_ADDR_MATCH_WRITE) { - /* Service a write request from the I2C Master. */ - i2c_slave_service_write(i2c, req); + } else if (req->state == I2C_TARGET_ADDR_MATCH_READ) { + /* Service a read request from the I2C Controller. */ + i2c_target_service_read(i2c, req); + } else if (req->state == I2C_TARGET_ADDR_MATCH_WRITE) { + /* Service a write request from the I2C Controller. */ + i2c_target_service_write(i2c, req); } - } /** - * init_i2cs() - Async Handler for I2C Slave driver. + * init_i2cs() - Async Handler for I2C Target driver. * @port: I2C port number to initialize. */ void init_i2cs(int port) @@ -656,15 +676,15 @@ void init_i2cs(int port) while (1) ; } - /* Prepare for interrupt driven slave requests. */ - req_slave.addr = CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS; - req_slave.tx_data = host_buffer; /* Transmitted to host. */ - req_slave.tx_remain = -1; - req_slave.rx_data = host_buffer; /* Received from host. */ - req_slave.restart = 0; - req_slave.response_pending = false; - states[port].req = &req_slave; - error = i2c_slave_async(i2c_bus_ports[port], &req_slave); + /* Prepare for interrupt driven target requests. */ + req_target.addr = CONFIG_HOSTCMD_I2C_ADDR_FLAGS; + req_target.tx_data = host_buffer; /* Transmitted to host. */ + req_target.tx_remain = -1; + req_target.rx_data = host_buffer; /* Received from host. */ + req_target.restart = 0; + req_target.response_pending = false; + states[port].req = &req_target; + error = i2c_target_async(i2c_bus_ports[port], &req_target); if (error != EC_SUCCESS) { while (1) ; @@ -675,22 +695,22 @@ void init_i2cs(int port) } /** - * i2c_slave_async() - Slave Read and Write Asynchronous. + * i2c_target_async() - Target Read and Write Asynchronous. * @i2c: Pointer to I2C regs. * @req: Request for an I2C transaction. * * Return EC_SUCCESS if successful, otherwise returns a common error code. */ -static int i2c_slave_async(mxc_i2c_regs_t *i2c, i2c_req_t *req) +static int i2c_target_async(mxc_i2c_regs_t *i2c, i2c_req_t *req) { /* Make sure the I2C has been initialized. */ if (!(i2c->ctrl & MXC_F_I2C_CTRL_I2C_EN)) return EC_ERROR_UNKNOWN; - /* Disable master mode. */ + /* Disable controller mode. */ i2c->ctrl &= ~(MXC_F_I2C_CTRL_MST); - /* Set the Slave Address in the I2C peripheral register. */ - i2c->slave_addr = req->addr; - /* Clear the receive count from the I2C Master. */ + /* Set the Target Address in the I2C peripheral register. */ + i2c->target_addr = req->addr; + /* Clear the receive count from the I2C Controller. */ req->received_count = 0; /* Disable and clear the interrupts. */ i2c->int_en0 = 0; @@ -699,10 +719,9 @@ static int i2c_slave_async(mxc_i2c_regs_t *i2c, i2c_req_t *req) i2c->int_fl1 = i2c->int_fl1; /* Set the RX threshold interrupt level. */ - i2c->rx_ctrl0 = ((i2c->rx_ctrl0 & - ~(MXC_F_I2C_RX_CTRL0_RX_THRESH)) | - (MXC_I2C_FIFO_DEPTH - 2) - << MXC_F_I2C_RX_CTRL0_RX_THRESH_POS); + i2c->rx_ctrl0 = + ((i2c->rx_ctrl0 & ~(MXC_F_I2C_RX_CTRL0_RX_THRESH)) | + (MXC_I2C_FIFO_DEPTH - 2) << MXC_F_I2C_RX_CTRL0_RX_THRESH_POS); /* Only enable the I2C Address match interrupt. */ i2c->int_en0 = MXC_F_I2C_INT_EN0_ADDR_MATCH; @@ -710,24 +729,23 @@ static int i2c_slave_async(mxc_i2c_regs_t *i2c, i2c_req_t *req) return EC_SUCCESS; } -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS static void i2c_send_board_response(int len) { - /* Set the number of bytes to send to the I2C master. */ - req_slave.tx_remain = len; - /* Indicate that there is a response pending from the slave. */ - req_slave.response_pending = true; + /* Set the number of bytes to send to the I2C controller. */ + req_target.tx_remain = len; + /* Indicate that there is a response pending from the target. */ + req_target.response_pending = true; } - static void i2c_process_board_command(int read, int addr, int len) { board_i2c_process(read, addr, len, &host_buffer[0], i2c_send_board_response); } -#endif /* CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS */ -#endif /* CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS */ +#endif /* CONFIG_BOARD_I2C_ADDR_FLAGS */ +#endif /* CONFIG_HOSTCMD_I2C_ADDR_FLAGS */ /** * i2c_set_speed() - Set the transfer speed of the selected I2C. @@ -760,15 +778,17 @@ static int i2c_set_speed(mxc_i2c_regs_t *i2c, i2c_speed_t i2cspeed) time_scl_min = 1000000 / (target_bus_freq / 1000); clock_low_min = ((T_LOW_MIN + T_F_MAX_HS + (time_pclk - 1) - T_AF_MIN) / - time_pclk) - 1; + time_pclk) - + 1; clock_high_min = ((T_HIGH_MIN + T_R_MAX_HS + (time_pclk - 1) - - T_AF_MIN) / - time_pclk) - 1; + T_AF_MIN) / + time_pclk) - + 1; clock_min = ((time_scl_min + (time_pclk - 1)) / time_pclk) - 2; - ticks_lo = (clock_low_min > (clock_min - clock_high_min)) - ? (clock_low_min) - : (clock_min - clock_high_min); + ticks_lo = (clock_low_min > (clock_min - clock_high_min)) ? + (clock_low_min) : + (clock_min - clock_high_min); ticks_hi = clock_high_min; if ((ticks_lo > (MXC_F_I2C_HS_CLK_HS_CLK_LO >> @@ -842,12 +862,12 @@ static int i2c_init_peripheral(mxc_i2c_regs_t *i2c, i2c_speed_t i2cspeed) i2c->ctrl = 0; /* Clear configuration bits. */ i2c->ctrl = MXC_F_I2C_CTRL_I2C_EN; /* Enable I2C. */ - i2c->master_ctrl = 0; /* Clear master configuration bits. */ + i2c->controller_ctrl = 0; /* Clear controller configuration bits. */ i2c->status = 0; /* Clear status bits. */ i2c->ctrl = 0; /* Clear configuration bits. */ i2c->ctrl = MXC_F_I2C_CTRL_I2C_EN; /* Enable I2C. */ - i2c->master_ctrl = 0; /* Clear master configuration bits. */ + i2c->controller_ctrl = 0; /* Clear controller configuration bits. */ i2c->status = 0; /* Clear status bits. */ /* Check for HS mode. */ @@ -869,13 +889,13 @@ static int i2c_init_peripheral(mxc_i2c_regs_t *i2c, i2c_speed_t i2cspeed) } /** - * i2c_master_write() + * i2c_controller_write() * @i2c: Pointer to I2C regs. * @addr: I2C 7-bit Address left aligned, bit 7 to bit 1. * Only supports 7-bit addressing. LSb of the given address * will be used as the read/write bit, the \p addr will - * not be shifted. Used for both master and - * slave transactions. + * not be shifted. Used for both controller and + * target transactions. * @data: Data to be written. * @len: Number of bytes to Write. * @restart: 0 to send a stop bit at the end of the transaction, @@ -885,8 +905,9 @@ static int i2c_init_peripheral(mxc_i2c_regs_t *i2c, i2c_speed_t i2cspeed) * * Return EC_SUCCESS, or non-zero if error. */ -static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, - int stop, const uint8_t *data, int len, int restart) +static int i2c_controller_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, + int stop, const uint8_t *data, int len, + int restart) { if (len == 0) { return EC_SUCCESS; @@ -900,16 +921,16 @@ static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, return EC_ERROR_UNKNOWN; } - /* Enable master mode. */ + /* Enable controller mode. */ i2c->ctrl |= MXC_F_I2C_CTRL_MST; - /* Load FIFO with slave address for WRITE and as much data as we can. */ + /* Load FIFO with target address for WRITE and as much data as we can */ while (i2c->status & MXC_F_I2C_STATUS_TX_FULL) { } if (start) { /** - * The slave address is right-aligned, bits 6 to 0, shift + * The target address is right-aligned, bits 6 to 0, shift * to the left and make room for the write bit. */ i2c->fifo = (addr << 1) & ~(0x1); @@ -921,7 +942,7 @@ static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, } /* Generate Start signal. */ if (start) { - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_START; + i2c->controller_ctrl |= MXC_F_I2C_CONTROLLER_CTRL_START; } /* Write remaining data to FIFO. */ @@ -929,8 +950,9 @@ static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, /* Check for errors. */ if (i2c->int_fl0 & I2C_ERROR) { /* Set the stop bit. */ - i2c->master_ctrl &= ~(MXC_F_I2C_MASTER_CTRL_RESTART); - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_STOP; + i2c->controller_ctrl &= + ~MXC_F_I2C_CONTROLLER_CTRL_RESTART; + i2c->controller_ctrl |= MXC_F_I2C_CONTROLLER_CTRL_STOP; return EC_ERROR_UNKNOWN; } @@ -941,10 +963,10 @@ static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, } /* Check if Repeated Start requested. */ if (restart) { - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_RESTART; + i2c->controller_ctrl |= MXC_F_I2C_CONTROLLER_CTRL_RESTART; } else { if (stop) { - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_STOP; + i2c->controller_ctrl |= MXC_F_I2C_CONTROLLER_CTRL_STOP; } } @@ -954,9 +976,10 @@ static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, /* Check for errors */ if (i2c->int_fl0 & I2C_ERROR) { /* Set the stop bit */ - i2c->master_ctrl &= - ~(MXC_F_I2C_MASTER_CTRL_RESTART); - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_STOP; + i2c->controller_ctrl &= + ~MXC_F_I2C_CONTROLLER_CTRL_RESTART; + i2c->controller_ctrl |= + MXC_F_I2C_CONTROLLER_CTRL_STOP; return EC_ERROR_UNKNOWN; } } @@ -970,9 +993,10 @@ static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, /* Check for errors */ if (i2c->int_fl0 & I2C_ERROR) { /* Set the stop bit */ - i2c->master_ctrl &= - ~(MXC_F_I2C_MASTER_CTRL_RESTART); - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_STOP; + i2c->controller_ctrl &= + ~MXC_F_I2C_CONTROLLER_CTRL_RESTART; + i2c->controller_ctrl |= + MXC_F_I2C_CONTROLLER_CTRL_STOP; return EC_ERROR_UNKNOWN; } } @@ -989,7 +1013,7 @@ static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, } /** - * i2c_master_read() + * i2c_controller_read() * @i2c: Pointer to I2C regs. * @addr: I2C 7-bit Address right aligned, bit 6 to bit 0. * @data: Data to be written. @@ -1001,8 +1025,8 @@ static int i2c_master_write(mxc_i2c_regs_t *i2c, uint8_t addr, int start, * * Return: EC_SUCCESS if successful, otherwise returns a common error code */ -static int i2c_master_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, - int stop, uint8_t *data, int len, int restart) +static int i2c_controller_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, + int stop, uint8_t *data, int len, int restart) { volatile int length = len; int interactive_receive_mode; @@ -1023,7 +1047,7 @@ static int i2c_master_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, return EC_ERROR_UNKNOWN; } - /* Enable master mode. */ + /* Enable controller mode. */ i2c->ctrl |= MXC_F_I2C_CTRL_MST; if (stop) { @@ -1037,13 +1061,13 @@ static int i2c_master_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, interactive_receive_mode = 1; } - /* Load FIFO with slave address. */ + /* Load FIFO with target address. */ if (start) { - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_START; + i2c->controller_ctrl |= MXC_F_I2C_CONTROLLER_CTRL_START; while (i2c->status & MXC_F_I2C_STATUS_TX_FULL) { } /** - * The slave address is right-aligned, bits 6 to 0, shift + * The target address is right-aligned, bits 6 to 0, shift * to the left and make room for the read bit. */ i2c->fifo = ((addr << 1) | 1); @@ -1054,12 +1078,14 @@ static int i2c_master_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, /* Check for errors */ if (i2c->int_fl0 & I2C_ERROR) { /* Set the stop bit. */ - i2c->master_ctrl &= ~(MXC_F_I2C_MASTER_CTRL_RESTART); - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_STOP; + i2c->controller_ctrl &= + ~MXC_F_I2C_CONTROLLER_CTRL_RESTART; + i2c->controller_ctrl |= MXC_F_I2C_CONTROLLER_CTRL_STOP; return EC_ERROR_UNKNOWN; } - /* If in interactive receive mode then ack each received byte. */ + /* If in interactive receive mode then ack each received byte. + */ if (interactive_receive_mode) { while (!(i2c->int_fl0 & MXC_F_I2C_INT_EN0_RX_MODE)) ; @@ -1082,10 +1108,10 @@ static int i2c_master_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, } if (restart) { - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_RESTART; + i2c->controller_ctrl |= MXC_F_I2C_CONTROLLER_CTRL_RESTART; } else { if (stop) { - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_STOP; + i2c->controller_ctrl |= MXC_F_I2C_CONTROLLER_CTRL_STOP; } } @@ -1095,9 +1121,10 @@ static int i2c_master_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, /* Check for errors. */ if (i2c->int_fl0 & I2C_ERROR) { /* Set the stop bit. */ - i2c->master_ctrl &= - ~(MXC_F_I2C_MASTER_CTRL_RESTART); - i2c->master_ctrl |= MXC_F_I2C_MASTER_CTRL_STOP; + i2c->controller_ctrl &= + ~MXC_F_I2C_CONTROLLER_CTRL_RESTART; + i2c->controller_ctrl |= + MXC_F_I2C_CONTROLLER_CTRL_STOP; return EC_ERROR_UNKNOWN; } } @@ -1106,22 +1133,20 @@ static int i2c_master_read(mxc_i2c_regs_t *i2c, uint8_t addr, int start, } /* Wait for Stop. */ - if (!restart) { - if (stop) { - while (!(i2c->int_fl0 & MXC_F_I2C_INT_FL0_STOP)) { - /* Check for errors. */ - if (i2c->int_fl0 & I2C_ERROR) { - /* Set the stop bit. */ - i2c->master_ctrl &= ~( - MXC_F_I2C_MASTER_CTRL_RESTART); - i2c->master_ctrl |= - MXC_F_I2C_MASTER_CTRL_STOP; - return EC_ERROR_UNKNOWN; - } + if (!restart && stop) { + while (!(i2c->int_fl0 & MXC_F_I2C_INT_FL0_STOP)) { + /* Check for errors. */ + if (i2c->int_fl0 & I2C_ERROR) { + /* Set the stop bit. */ + i2c->controller_ctrl &= + ~MXC_F_I2C_CONTROLLER_CTRL_RESTART; + i2c->controller_ctrl |= + MXC_F_I2C_CONTROLLER_CTRL_STOP; + return EC_ERROR_UNKNOWN; } - /* Clear Stop interrupt flag. */ - i2c->int_fl0 = MXC_F_I2C_INT_FL0_STOP; } + /* Clear Stop interrupt flag. */ + i2c->int_fl0 = MXC_F_I2C_INT_FL0_STOP; } /* Check for errors. */ diff --git a/chip/max32660/i2c_regs.h b/chip/max32660/i2c_regs.h index 8cd2fd8868..4d8daf63c7 100644 --- a/chip/max32660/i2c_regs.h +++ b/chip/max32660/i2c_regs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,8 +11,8 @@ #include /* - If types are not defined elsewhere (CMSIS) define them here -*/ + * If types are not defined elsewhere (CMSIS) define them here + */ #ifndef __IO #define __IO volatile #endif @@ -26,1602 +26,1338 @@ #define __R volatile const #endif -/** +/* * Registers, Bit Masks and Bit Positions for the I2C Peripheral Module. */ -/** +/* * typedef mxc_i2c_regs_t - Structure type to access the I2C Registers. */ typedef struct { - __IO uint32_t ctrl; /**< \b 0x00: I2C CTRL Register */ - __IO uint32_t status; /**< \b 0x04: I2C STATUS Register */ - __IO uint32_t int_fl0; /**< \b 0x08: I2C INT_FL0 Register */ - __IO uint32_t int_en0; /**< \b 0x0C: I2C INT_EN0 Register */ - __IO uint32_t int_fl1; /**< \b 0x10: I2C INT_FL1 Register */ - __IO uint32_t int_en1; /**< \b 0x14: I2C INT_EN1 Register */ - __IO uint32_t fifo_len; /**< \b 0x18: I2C FIFO_LEN Register */ - __IO uint32_t rx_ctrl0; /**< \b 0x1C: I2C RX_CTRL0 Register */ - __IO uint32_t rx_ctrl1; /**< \b 0x20: I2C RX_CTRL1 Register */ - __IO uint32_t tx_ctrl0; /**< \b 0x24: I2C TX_CTRL0 Register */ - __IO uint32_t tx_ctrl1; /**< \b 0x28: I2C TX_CTRL1 Register */ - __IO uint32_t fifo; /**< \b 0x2C: I2C FIFO Register */ - __IO uint32_t - master_ctrl; /**< \b 0x30: I2C MASTER_CTRL Register */ - __IO uint32_t clk_lo; /**< \b 0x34: I2C CLK_LO Register */ - __IO uint32_t clk_hi; /**< \b 0x38: I2C CLK_HI Register */ - __IO uint32_t hs_clk; /**< \b 0x3C: I2C HS_CLK Register */ - __IO uint32_t timeout; /**< \b 0x40: I2C TIMEOUT Register */ - __IO uint32_t - slave_addr; /**< \b 0x44: I2C SLAVE_ADDR Register */ - __IO uint32_t dma; /**< \b 0x48: I2C DMA Register */ + __IO uint32_t ctrl; /* 0x00: I2C CTRL Register */ + __IO uint32_t status; /* 0x04: I2C STATUS Register */ + __IO uint32_t int_fl0; /* 0x08: I2C INT_FL0 Register */ + __IO uint32_t int_en0; /* 0x0C: I2C INT_EN0 Register */ + __IO uint32_t int_fl1; /* 0x10: I2C INT_FL1 Register */ + __IO uint32_t int_en1; /* 0x14: I2C INT_EN1 Register */ + __IO uint32_t fifo_len; /* 0x18: I2C FIFO_LEN Register */ + __IO uint32_t rx_ctrl0; /* 0x1C: I2C RX_CTRL0 Register */ + __IO uint32_t rx_ctrl1; /* 0x20: I2C RX_CTRL1 Register */ + __IO uint32_t tx_ctrl0; /* 0x24: I2C TX_CTRL0 Register */ + __IO uint32_t tx_ctrl1; /* 0x28: I2C TX_CTRL1 Register */ + __IO uint32_t fifo; /* 0x2C: I2C FIFO Register */ + __IO uint32_t controller_ctrl; /* 0x30: I2C CONTROLLER_CTRL Register */ + __IO uint32_t clk_lo; /* 0x34: I2C CLK_LO Register */ + __IO uint32_t clk_hi; /* 0x38: I2C CLK_HI Register */ + __IO uint32_t hs_clk; /* 0x3C: I2C HS_CLK Register */ + __IO uint32_t timeout; /* 0x40: I2C TIMEOUT Register */ + __IO uint32_t target_addr; /* 0x44: I2C TARGET_ADDR Register */ + __IO uint32_t dma; /* 0x48: I2C DMA Register */ } mxc_i2c_regs_t; /* Register offsets for module I2C */ -/** +/* * I2C Peripheral Register Offsets from the I2C Base Peripheral Address. */ -#define MXC_R_I2C_CTRL \ - ((uint32_t)0x00000000UL) /**< Offset from I2C Base Address: \ - 0x0000 */ -#define MXC_R_I2C_STATUS \ - ((uint32_t)0x00000004UL) /**< Offset from I2C Base Address: \ - 0x0004 */ -#define MXC_R_I2C_INT_FL0 \ - ((uint32_t)0x00000008UL) /**< Offset from I2C Base Address: \ - 0x0008 */ -#define MXC_R_I2C_INT_EN0 \ - ((uint32_t)0x0000000CUL) /**< Offset from I2C Base Address: \ - 0x000C */ -#define MXC_R_I2C_INT_FL1 \ - ((uint32_t)0x00000010UL) /**< Offset from I2C Base Address: \ - 0x0010 */ -#define MXC_R_I2C_INT_EN1 \ - ((uint32_t)0x00000014UL) /**< Offset from I2C Base Address: \ - 0x0014 */ -#define MXC_R_I2C_FIFO_LEN \ - ((uint32_t)0x00000018UL) /**< Offset from I2C Base Address: \ - 0x0018 */ -#define MXC_R_I2C_RX_CTRL0 \ - ((uint32_t)0x0000001CUL) /**< Offset from I2C Base Address: \ - 0x001C */ -#define MXC_R_I2C_RX_CTRL1 \ - ((uint32_t)0x00000020UL) /**< Offset from I2C Base Address: \ - 0x0020 */ -#define MXC_R_I2C_TX_CTRL0 \ - ((uint32_t)0x00000024UL) /**< Offset from I2C Base Address: \ - 0x0024 */ -#define MXC_R_I2C_TX_CTRL1 \ - ((uint32_t)0x00000028UL) /**< Offset from I2C Base Address: \ - 0x0028 */ -#define MXC_R_I2C_FIFO \ - ((uint32_t)0x0000002CUL) /**< Offset from I2C Base Address: \ - 0x002C */ -#define MXC_R_I2C_MASTER_CTRL \ - ((uint32_t)0x00000030UL) /**< Offset from I2C Base Address: \ - 0x0030 */ -#define MXC_R_I2C_CLK_LO \ - ((uint32_t)0x00000034UL) /**< Offset from I2C Base Address: \ - 0x0034 */ -#define MXC_R_I2C_CLK_HI \ - ((uint32_t)0x00000038UL) /**< Offset from I2C Base Address: \ - 0x0038 */ -#define MXC_R_I2C_HS_CLK \ - ((uint32_t)0x0000003CUL) /**< Offset from I2C Base Address: \ - 0x003C */ -#define MXC_R_I2C_TIMEOUT \ - ((uint32_t)0x00000040UL) /**< Offset from I2C Base Address: \ - 0x0040 */ -#define MXC_R_I2C_SLAVE_ADDR \ - ((uint32_t)0x00000044UL) /**< Offset from I2C Base Address: \ - 0x0044 */ -#define MXC_R_I2C_DMA \ - ((uint32_t)0x00000048UL) /**< Offset from I2C Base Address: \ - 0x0048 */ +#define MXC_R_I2C_CTRL 0x00000000UL +#define MXC_R_I2C_STATUS 0x00000004UL +#define MXC_R_I2C_INT_FL0 0x00000008UL +#define MXC_R_I2C_INT_EN0 0x0000000CUL +#define MXC_R_I2C_INT_FL1 0x00000010UL +#define MXC_R_I2C_INT_EN1 0x00000014UL +#define MXC_R_I2C_FIFO_LEN 0x00000018UL +#define MXC_R_I2C_RX_CTRL0 0x0000001CUL +#define MXC_R_I2C_RX_CTRL1 0x00000020UL +#define MXC_R_I2C_TX_CTRL0 0x00000024UL +#define MXC_R_I2C_TX_CTRL1 0x00000028UL +#define MXC_R_I2C_FIFO 0x0000002CUL +#define MXC_R_I2C_CONTROLLER_CTRL 0x00000030UL +#define MXC_R_I2C_CLK_LO 0x00000034UL +#define MXC_R_I2C_CLK_HI 0x00000038UL +#define MXC_R_I2C_HS_CLK 0x0000003CUL +#define MXC_R_I2C_TIMEOUT 0x00000040UL +#define MXC_R_I2C_TARGET_ADDR 0x00000044UL +#define MXC_R_I2C_DMA 0x00000048UL /** * Control Register0. */ -#define MXC_F_I2C_CTRL_I2C_EN_POS 0 /**< CTRL_I2C_EN Position */ -#define MXC_F_I2C_CTRL_I2C_EN \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_CTRL_I2C_EN_POS)) /**< CTRL_I2C_EN Mask */ -#define MXC_V_I2C_CTRL_I2C_EN_DIS \ - ((uint32_t)0x0UL) /**< CTRL_I2C_EN_DIS Value */ -#define MXC_S_I2C_CTRL_I2C_EN_DIS \ - (MXC_V_I2C_CTRL_I2C_EN_DIS \ - << MXC_F_I2C_CTRL_I2C_EN_POS) /**< CTRL_I2C_EN_DIS Setting */ -#define MXC_V_I2C_CTRL_I2C_EN_EN \ - ((uint32_t)0x1UL) /**< CTRL_I2C_EN_EN Value \ - */ -#define MXC_S_I2C_CTRL_I2C_EN_EN \ - (MXC_V_I2C_CTRL_I2C_EN_EN \ - << MXC_F_I2C_CTRL_I2C_EN_POS) /**< CTRL_I2C_EN_EN Setting */ - -#define MXC_F_I2C_CTRL_MST_POS 1 /**< CTRL_MST Position */ -#define MXC_F_I2C_CTRL_MST \ - ((uint32_t)(0x1UL << MXC_F_I2C_CTRL_MST_POS)) /**< CTRL_MST Mask */ -#define MXC_V_I2C_CTRL_MST_SLAVE_MODE \ - ((uint32_t)0x0UL) /**< CTRL_MST_SLAVE_MODE Value */ -#define MXC_S_I2C_CTRL_MST_SLAVE_MODE \ - (MXC_V_I2C_CTRL_MST_SLAVE_MODE \ - << MXC_F_I2C_CTRL_MST_POS) /**< CTRL_MST_SLAVE_MODE Setting */ -#define MXC_V_I2C_CTRL_MST_MASTER_MODE \ - ((uint32_t)0x1UL) /**< CTRL_MST_MASTER_MODE Value */ -#define MXC_S_I2C_CTRL_MST_MASTER_MODE \ - (MXC_V_I2C_CTRL_MST_MASTER_MODE \ - << MXC_F_I2C_CTRL_MST_POS) /**< CTRL_MST_MASTER_MODE Setting */ - -#define MXC_F_I2C_CTRL_GEN_CALL_ADDR_POS 2 /**< CTRL_GEN_CALL_ADDR Position */ -#define MXC_F_I2C_CTRL_GEN_CALL_ADDR \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_CTRL_GEN_CALL_ADDR_POS)) /**< CTRL_GEN_CALL_ADDR \ - Mask */ -#define MXC_V_I2C_CTRL_GEN_CALL_ADDR_DIS \ - ((uint32_t)0x0UL) /**< CTRL_GEN_CALL_ADDR_DIS Value */ -#define MXC_S_I2C_CTRL_GEN_CALL_ADDR_DIS \ - (MXC_V_I2C_CTRL_GEN_CALL_ADDR_DIS \ - << MXC_F_I2C_CTRL_GEN_CALL_ADDR_POS) /**< CTRL_GEN_CALL_ADDR_DIS \ - Setting */ -#define MXC_V_I2C_CTRL_GEN_CALL_ADDR_EN \ - ((uint32_t)0x1UL) /**< CTRL_GEN_CALL_ADDR_EN Value */ -#define MXC_S_I2C_CTRL_GEN_CALL_ADDR_EN \ - (MXC_V_I2C_CTRL_GEN_CALL_ADDR_EN \ - << MXC_F_I2C_CTRL_GEN_CALL_ADDR_POS) /**< CTRL_GEN_CALL_ADDR_EN \ - Setting */ - -#define MXC_F_I2C_CTRL_RX_MODE_POS 3 /**< CTRL_RX_MODE Position */ -#define MXC_F_I2C_CTRL_RX_MODE \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_CTRL_RX_MODE_POS)) /**< CTRL_RX_MODE Mask */ -#define MXC_V_I2C_CTRL_RX_MODE_DIS \ - ((uint32_t)0x0UL) /**< CTRL_RX_MODE_DIS Value */ -#define MXC_S_I2C_CTRL_RX_MODE_DIS \ - (MXC_V_I2C_CTRL_RX_MODE_DIS \ - << MXC_F_I2C_CTRL_RX_MODE_POS) /**< CTRL_RX_MODE_DIS Setting */ -#define MXC_V_I2C_CTRL_RX_MODE_EN \ - ((uint32_t)0x1UL) /**< CTRL_RX_MODE_EN Value */ -#define MXC_S_I2C_CTRL_RX_MODE_EN \ - (MXC_V_I2C_CTRL_RX_MODE_EN \ - << MXC_F_I2C_CTRL_RX_MODE_POS) /**< CTRL_RX_MODE_EN Setting */ - -#define MXC_F_I2C_CTRL_RX_MODE_ACK_POS 4 /**< CTRL_RX_MODE_ACK Position */ -#define MXC_F_I2C_CTRL_RX_MODE_ACK \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_CTRL_RX_MODE_ACK_POS)) /**< CTRL_RX_MODE_ACK \ - Mask */ -#define MXC_V_I2C_CTRL_RX_MODE_ACK_ACK \ - ((uint32_t)0x0UL) /**< CTRL_RX_MODE_ACK_ACK Value */ -#define MXC_S_I2C_CTRL_RX_MODE_ACK_ACK \ - (MXC_V_I2C_CTRL_RX_MODE_ACK_ACK \ - << MXC_F_I2C_CTRL_RX_MODE_ACK_POS) /**< CTRL_RX_MODE_ACK_ACK Setting \ - */ -#define MXC_V_I2C_CTRL_RX_MODE_ACK_NACK \ - ((uint32_t)0x1UL) /**< CTRL_RX_MODE_ACK_NACK Value */ -#define MXC_S_I2C_CTRL_RX_MODE_ACK_NACK \ - (MXC_V_I2C_CTRL_RX_MODE_ACK_NACK \ - << MXC_F_I2C_CTRL_RX_MODE_ACK_POS) /**< CTRL_RX_MODE_ACK_NACK Setting \ - */ - -#define MXC_F_I2C_CTRL_SCL_OUT_POS 6 /**< CTRL_SCL_OUT Position */ -#define MXC_F_I2C_CTRL_SCL_OUT \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_CTRL_SCL_OUT_POS)) /**< CTRL_SCL_OUT Mask */ -#define MXC_V_I2C_CTRL_SCL_OUT_DRIVE_SCL_LOW \ - ((uint32_t)0x0UL) /**< CTRL_SCL_OUT_DRIVE_SCL_LOW Value */ -#define MXC_S_I2C_CTRL_SCL_OUT_DRIVE_SCL_LOW \ - (MXC_V_I2C_CTRL_SCL_OUT_DRIVE_SCL_LOW \ - << MXC_F_I2C_CTRL_SCL_OUT_POS) /**< CTRL_SCL_OUT_DRIVE_SCL_LOW \ - Setting */ -#define MXC_V_I2C_CTRL_SCL_OUT_RELEASE_SCL \ - ((uint32_t)0x1UL) /**< CTRL_SCL_OUT_RELEASE_SCL Value */ -#define MXC_S_I2C_CTRL_SCL_OUT_RELEASE_SCL \ - (MXC_V_I2C_CTRL_SCL_OUT_RELEASE_SCL \ - << MXC_F_I2C_CTRL_SCL_OUT_POS) /**< CTRL_SCL_OUT_RELEASE_SCL Setting \ - */ - -#define MXC_F_I2C_CTRL_SDA_OUT_POS 7 /**< CTRL_SDA_OUT Position */ -#define MXC_F_I2C_CTRL_SDA_OUT \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_CTRL_SDA_OUT_POS)) /**< CTRL_SDA_OUT Mask */ -#define MXC_V_I2C_CTRL_SDA_OUT_DRIVE_SDA_LOW \ - ((uint32_t)0x0UL) /**< CTRL_SDA_OUT_DRIVE_SDA_LOW Value */ -#define MXC_S_I2C_CTRL_SDA_OUT_DRIVE_SDA_LOW \ - (MXC_V_I2C_CTRL_SDA_OUT_DRIVE_SDA_LOW \ - << MXC_F_I2C_CTRL_SDA_OUT_POS) /**< CTRL_SDA_OUT_DRIVE_SDA_LOW \ - Setting */ -#define MXC_V_I2C_CTRL_SDA_OUT_RELEASE_SDA \ - ((uint32_t)0x1UL) /**< CTRL_SDA_OUT_RELEASE_SDA Value */ -#define MXC_S_I2C_CTRL_SDA_OUT_RELEASE_SDA \ - (MXC_V_I2C_CTRL_SDA_OUT_RELEASE_SDA \ - << MXC_F_I2C_CTRL_SDA_OUT_POS) /**< CTRL_SDA_OUT_RELEASE_SDA Setting \ - */ - -#define MXC_F_I2C_CTRL_SCL_POS 8 /**< CTRL_SCL Position */ -#define MXC_F_I2C_CTRL_SCL \ - ((uint32_t)(0x1UL << MXC_F_I2C_CTRL_SCL_POS)) /**< CTRL_SCL Mask */ - -#define MXC_F_I2C_CTRL_SDA_POS 9 /**< CTRL_SDA Position */ -#define MXC_F_I2C_CTRL_SDA \ - ((uint32_t)(0x1UL << MXC_F_I2C_CTRL_SDA_POS)) /**< CTRL_SDA Mask */ - -#define MXC_F_I2C_CTRL_SW_OUT_EN_POS 10 /**< CTRL_SW_OUT_EN Position */ -#define MXC_F_I2C_CTRL_SW_OUT_EN \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_CTRL_SW_OUT_EN_POS)) /**< CTRL_SW_OUT_EN Mask */ -#define MXC_V_I2C_CTRL_SW_OUT_EN_OUTPUTS_DISABLE \ - ((uint32_t)0x0UL) /**< CTRL_SW_OUT_EN_OUTPUTS_DISABLE Value */ +/* CTRL_I2C_EN Position */ +#define MXC_F_I2C_CTRL_I2C_EN_POS 0 +/* CTRL_I2C_EN Mask */ +#define MXC_F_I2C_CTRL_I2C_EN (0x1UL << MXC_F_I2C_CTRL_I2C_EN_POS) +/* CTRL_I2C_EN_DIS Value */ +#define MXC_V_I2C_CTRL_I2C_EN_DIS 0x0UL +/* CTRL_I2C_EN_DIS Setting */ +#define MXC_S_I2C_CTRL_I2C_EN_DIS \ + (MXC_V_I2C_CTRL_I2C_EN_DIS << MXC_F_I2C_CTRL_I2C_EN_POS) +/* CTRL_I2C_EN_EN Value */ +#define MXC_V_I2C_CTRL_I2C_EN_EN 0x1UL +/* CTRL_I2C_EN_EN Setting */ +#define MXC_S_I2C_CTRL_I2C_EN_EN \ + (MXC_V_I2C_CTRL_I2C_EN_EN << MXC_F_I2C_CTRL_I2C_EN_POS) + +/* CTRL_MST Position */ +#define MXC_F_I2C_CTRL_MST_POS 1 +/* CTRL_MST Mask */ +#define MXC_F_I2C_CTRL_MST (0x1UL << MXC_F_I2C_CTRL_MST_POS) +/* CTRL_MST_TARGET_MODE Value */ +#define MXC_V_I2C_CTRL_MST_TARGET_MODE 0x0UL +/* CTRL_MST_TARGET_MODE Setting */ +#define MXC_S_I2C_CTRL_MST_TARGET_MODE \ + (MXC_V_I2C_CTRL_MST_TARGET_MODE << MXC_F_I2C_CTRL_MST_POS) +/* CTRL_MST_CONTROLLER_MODE Value */ +#define MXC_V_I2C_CTRL_MST_CONTROLLER_MODE 0x1UL +/* CTRL_MST_CONTROLLER_MODE Setting */ +#define MXC_S_I2C_CTRL_MST_CONTROLLER_MODE \ + (MXC_V_I2C_CTRL_MST_CONTROLLER_MODE << MXC_F_I2C_CTRL_MST_POS) + +/* CTRL_GEN_CALL_ADDR Position */ +#define MXC_F_I2C_CTRL_GEN_CALL_ADDR_POS 2 +/* CTRL_GEN_CALL_ADDR Mask */ +#define MXC_F_I2C_CTRL_GEN_CALL_ADDR (0x1UL << MXC_F_I2C_CTRL_GEN_CALL_ADDR_POS) +/* CTRL_GEN_CALL_ADDR_DIS Value */ +#define MXC_V_I2C_CTRL_GEN_CALL_ADDR_DIS 0x0UL +/* CTRL_GEN_CALL_ADDR_DIS Setting */ +#define MXC_S_I2C_CTRL_GEN_CALL_ADDR_DIS \ + (MXC_V_I2C_CTRL_GEN_CALL_ADDR_DIS << MXC_F_I2C_CTRL_GEN_CALL_ADDR_POS) +/* CTRL_GEN_CALL_ADDR_EN Value */ +#define MXC_V_I2C_CTRL_GEN_CALL_ADDR_EN 0x1UL +/* CTRL_GEN_CALL_ADDR_EN Setting */ +#define MXC_S_I2C_CTRL_GEN_CALL_ADDR_EN \ + (MXC_V_I2C_CTRL_GEN_CALL_ADDR_EN << MXC_F_I2C_CTRL_GEN_CALL_ADDR_POS) + +/* CTRL_RX_MODE Position */ +#define MXC_F_I2C_CTRL_RX_MODE_POS 3 +/* CTRL_RX_MODE Mask */ +#define MXC_F_I2C_CTRL_RX_MODE (0x1UL << MXC_F_I2C_CTRL_RX_MODE_POS) +/* CTRL_RX_MODE_DIS Value */ +#define MXC_V_I2C_CTRL_RX_MODE_DIS 0x0UL +/* CTRL_RX_MODE_DIS Setting */ +#define MXC_S_I2C_CTRL_RX_MODE_DIS \ + (MXC_V_I2C_CTRL_RX_MODE_DIS << MXC_F_I2C_CTRL_RX_MODE_POS) +/* CTRL_RX_MODE_EN Value */ +#define MXC_V_I2C_CTRL_RX_MODE_EN 0x1UL +/* CTRL_RX_MODE_EN Setting */ +#define MXC_S_I2C_CTRL_RX_MODE_EN \ + (MXC_V_I2C_CTRL_RX_MODE_EN << MXC_F_I2C_CTRL_RX_MODE_POS) + +/* CTRL_RX_MODE_ACK Position */ +#define MXC_F_I2C_CTRL_RX_MODE_ACK_POS 4 +/* CTRL_RX_MODE_ACK Mask */ +#define MXC_F_I2C_CTRL_RX_MODE_ACK (0x1UL << MXC_F_I2C_CTRL_RX_MODE_ACK_POS) +/* CTRL_RX_MODE_ACK_ACK Value */ +#define MXC_V_I2C_CTRL_RX_MODE_ACK_ACK 0x0UL +/* CTRL_RX_MODE_ACK_ACK Setting */ +#define MXC_S_I2C_CTRL_RX_MODE_ACK_ACK \ + (MXC_V_I2C_CTRL_RX_MODE_ACK_ACK << MXC_F_I2C_CTRL_RX_MODE_ACK_POS) +/* CTRL_RX_MODE_ACK_NACK Value */ +#define MXC_V_I2C_CTRL_RX_MODE_ACK_NACK 0x1UL +/* CTRL_RX_MODE_ACK_NACK Setting */ +#define MXC_S_I2C_CTRL_RX_MODE_ACK_NACK \ + (MXC_V_I2C_CTRL_RX_MODE_ACK_NACK << MXC_F_I2C_CTRL_RX_MODE_ACK_POS) + +/* CTRL_SCL_OUT Position */ +#define MXC_F_I2C_CTRL_SCL_OUT_POS 6 +/* CTRL_SCL_OUT Mask */ +#define MXC_F_I2C_CTRL_SCL_OUT (0x1UL << MXC_F_I2C_CTRL_SCL_OUT_POS) +/* CTRL_SCL_OUT_DRIVE_SCL_LOW Value */ +#define MXC_V_I2C_CTRL_SCL_OUT_DRIVE_SCL_LOW 0x0UL +/* CTRL_SCL_OUT_DRIVE_SCL_LOW Setting */ +#define MXC_S_I2C_CTRL_SCL_OUT_DRIVE_SCL_LOW \ + (MXC_V_I2C_CTRL_SCL_OUT_DRIVE_SCL_LOW << MXC_F_I2C_CTRL_SCL_OUT_POS) +/* CTRL_SCL_OUT_RELEASE_SCL Value */ +#define MXC_V_I2C_CTRL_SCL_OUT_RELEASE_SCL 0x1UL +/* CTRL_SCL_OUT_RELEASE_SCL Setting */ +#define MXC_S_I2C_CTRL_SCL_OUT_RELEASE_SCL \ + (MXC_V_I2C_CTRL_SCL_OUT_RELEASE_SCL << MXC_F_I2C_CTRL_SCL_OUT_POS) + +/* CTRL_SDA_OUT Position */ +#define MXC_F_I2C_CTRL_SDA_OUT_POS 7 +/* CTRL_SDA_OUT Mask */ +#define MXC_F_I2C_CTRL_SDA_OUT (0x1UL << MXC_F_I2C_CTRL_SDA_OUT_POS) +/* CTRL_SDA_OUT_DRIVE_SDA_LOW Value */ +#define MXC_V_I2C_CTRL_SDA_OUT_DRIVE_SDA_LOW 0x0UL +/* CTRL_SDA_OUT_DRIVE_SDA_LOW Setting */ +#define MXC_S_I2C_CTRL_SDA_OUT_DRIVE_SDA_LOW \ + (MXC_V_I2C_CTRL_SDA_OUT_DRIVE_SDA_LOW << MXC_F_I2C_CTRL_SDA_OUT_POS) +/* CTRL_SDA_OUT_RELEASE_SDA Value */ +#define MXC_V_I2C_CTRL_SDA_OUT_RELEASE_SDA 0x1UL +/* CTRL_SDA_OUT_RELEASE_SDA Setting */ +#define MXC_S_I2C_CTRL_SDA_OUT_RELEASE_SDA \ + (MXC_V_I2C_CTRL_SDA_OUT_RELEASE_SDA << MXC_F_I2C_CTRL_SDA_OUT_POS) + +/* CTRL_SCL Position */ +#define MXC_F_I2C_CTRL_SCL_POS 8 +/* CTRL_SCL Mask */ +#define MXC_F_I2C_CTRL_SCL (0x1UL << MXC_F_I2C_CTRL_SCL_POS) + +/* CTRL_SDA Position */ +#define MXC_F_I2C_CTRL_SDA_POS 9 +/* CTRL_SDA Mask */ +#define MXC_F_I2C_CTRL_SDA (0x1UL << MXC_F_I2C_CTRL_SDA_POS) + +/* CTRL_SW_OUT_EN Position */ +#define MXC_F_I2C_CTRL_SW_OUT_EN_POS 10 +/* CTRL_SW_OUT_EN Mask */ +#define MXC_F_I2C_CTRL_SW_OUT_EN (0x1UL << MXC_F_I2C_CTRL_SW_OUT_EN_POS) +/* CTRL_SW_OUT_EN_OUTPUTS_DISABLE Value */ +#define MXC_V_I2C_CTRL_SW_OUT_EN_OUTPUTS_DISABLE 0x0UL +/* CTRL_SW_OUT_EN_OUTPUTS_DISABLE Setting */ #define MXC_S_I2C_CTRL_SW_OUT_EN_OUTPUTS_DISABLE \ (MXC_V_I2C_CTRL_SW_OUT_EN_OUTPUTS_DISABLE \ - << MXC_F_I2C_CTRL_SW_OUT_EN_POS) /**< CTRL_SW_OUT_EN_OUTPUTS_DISABLE \ - Setting */ -#define MXC_V_I2C_CTRL_SW_OUT_EN_OUTPUTS_ENABLE \ - ((uint32_t)0x1UL) /**< CTRL_SW_OUT_EN_OUTPUTS_ENABLE Value */ + << MXC_F_I2C_CTRL_SW_OUT_EN_POS) +/* CTRL_SW_OUT_EN_OUTPUTS_ENABLE Value */ +#define MXC_V_I2C_CTRL_SW_OUT_EN_OUTPUTS_ENABLE 0x1UL +/* CTRL_SW_OUT_EN_OUTPUTS_ENABLE Setting */ #define MXC_S_I2C_CTRL_SW_OUT_EN_OUTPUTS_ENABLE \ (MXC_V_I2C_CTRL_SW_OUT_EN_OUTPUTS_ENABLE \ - << MXC_F_I2C_CTRL_SW_OUT_EN_POS) /**< CTRL_SW_OUT_EN_OUTPUTS_ENABLE \ - Setting */ - -#define MXC_F_I2C_CTRL_READ_POS 11 /**< CTRL_READ Position */ -#define MXC_F_I2C_CTRL_READ \ - ((uint32_t)(0x1UL << MXC_F_I2C_CTRL_READ_POS)) /**< CTRL_READ Mask */ -#define MXC_V_I2C_CTRL_READ_WRITE \ - ((uint32_t)0x0UL) /**< CTRL_READ_WRITE Value */ -#define MXC_S_I2C_CTRL_READ_WRITE \ - (MXC_V_I2C_CTRL_READ_WRITE \ - << MXC_F_I2C_CTRL_READ_POS) /**< CTRL_READ_WRITE Setting */ -#define MXC_V_I2C_CTRL_READ_READ \ - ((uint32_t)0x1UL) /**< CTRL_READ_READ Value \ - */ -#define MXC_S_I2C_CTRL_READ_READ \ - (MXC_V_I2C_CTRL_READ_READ \ - << MXC_F_I2C_CTRL_READ_POS) /**< CTRL_READ_READ Setting */ - -#define MXC_F_I2C_CTRL_SCL_CLK_STRECH_DIS_POS \ - 12 /**< CTRL_SCL_CLK_STRECH_DIS Position */ + << MXC_F_I2C_CTRL_SW_OUT_EN_POS) + +/* CTRL_READ Position */ +#define MXC_F_I2C_CTRL_READ_POS 11 +/* CTRL_READ Mask */ +#define MXC_F_I2C_CTRL_READ (0x1UL << MXC_F_I2C_CTRL_READ_POS) +/* CTRL_READ_WRITE Value */ +#define MXC_V_I2C_CTRL_READ_WRITE 0x0UL +/* CTRL_READ_WRITE Setting */ +#define MXC_S_I2C_CTRL_READ_WRITE \ + (MXC_V_I2C_CTRL_READ_WRITE << MXC_F_I2C_CTRL_READ_POS) +/* CTRL_READ_READ Value */ +#define MXC_V_I2C_CTRL_READ_READ 0x1UL +/* CTRL_READ_READ Setting */ +#define MXC_S_I2C_CTRL_READ_READ \ + (MXC_V_I2C_CTRL_READ_READ << MXC_F_I2C_CTRL_READ_POS) + +/* CTRL_SCL_CLK_STRECH_DIS Position */ +#define MXC_F_I2C_CTRL_SCL_CLK_STRECH_DIS_POS 12 +/* CTRL_SCL_CLK_STRECH_DIS Mask */ #define MXC_F_I2C_CTRL_SCL_CLK_STRECH_DIS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_CTRL_SCL_CLK_STRECH_DIS_POS)) /**< \ - CTRL_SCL_CLK_STRECH_DIS \ - Mask */ -#define MXC_V_I2C_CTRL_SCL_CLK_STRECH_DIS_EN \ - ((uint32_t)0x0UL) /**< CTRL_SCL_CLK_STRECH_DIS_EN Value */ + (0x1UL << MXC_F_I2C_CTRL_SCL_CLK_STRECH_DIS_POS) +/* CTRL_SCL_CLK_STRECH_DIS_EN Value */ +#define MXC_V_I2C_CTRL_SCL_CLK_STRECH_DIS_EN 0x0UL +/* CTRL_SCL_CLK_STRECH_DIS_EN Setting */ #define MXC_S_I2C_CTRL_SCL_CLK_STRECH_DIS_EN \ (MXC_V_I2C_CTRL_SCL_CLK_STRECH_DIS_EN \ - << MXC_F_I2C_CTRL_SCL_CLK_STRECH_DIS_POS) /**< \ - CTRL_SCL_CLK_STRECH_DIS_EN \ - Setting */ -#define MXC_V_I2C_CTRL_SCL_CLK_STRECH_DIS_DIS \ - ((uint32_t)0x1UL) /**< CTRL_SCL_CLK_STRECH_DIS_DIS Value */ + << MXC_F_I2C_CTRL_SCL_CLK_STRECH_DIS_POS) +/* CTRL_SCL_CLK_STRECH_DIS_DIS Value */ +#define MXC_V_I2C_CTRL_SCL_CLK_STRECH_DIS_DIS 0x1UL +/* CTRL_SCL_CLK_STRECH_DIS_DIS Setting */ #define MXC_S_I2C_CTRL_SCL_CLK_STRECH_DIS_DIS \ (MXC_V_I2C_CTRL_SCL_CLK_STRECH_DIS_DIS \ - << MXC_F_I2C_CTRL_SCL_CLK_STRECH_DIS_POS) /**< \ - CTRL_SCL_CLK_STRECH_DIS_DIS \ - Setting */ - -#define MXC_F_I2C_CTRL_SCL_PP_MODE_POS 13 /**< CTRL_SCL_PP_MODE Position */ -#define MXC_F_I2C_CTRL_SCL_PP_MODE \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_CTRL_SCL_PP_MODE_POS)) /**< CTRL_SCL_PP_MODE \ - Mask */ -#define MXC_V_I2C_CTRL_SCL_PP_MODE_DIS \ - ((uint32_t)0x0UL) /**< CTRL_SCL_PP_MODE_DIS Value */ -#define MXC_S_I2C_CTRL_SCL_PP_MODE_DIS \ - (MXC_V_I2C_CTRL_SCL_PP_MODE_DIS \ - << MXC_F_I2C_CTRL_SCL_PP_MODE_POS) /**< CTRL_SCL_PP_MODE_DIS Setting \ - */ -#define MXC_V_I2C_CTRL_SCL_PP_MODE_EN \ - ((uint32_t)0x1UL) /**< CTRL_SCL_PP_MODE_EN Value */ -#define MXC_S_I2C_CTRL_SCL_PP_MODE_EN \ - (MXC_V_I2C_CTRL_SCL_PP_MODE_EN \ - << MXC_F_I2C_CTRL_SCL_PP_MODE_POS) /**< CTRL_SCL_PP_MODE_EN Setting \ - */ - -#define MXC_F_I2C_CTRL_HS_MODE_POS 15 /**< CTRL_HS_MODE Position */ -#define MXC_F_I2C_CTRL_HS_MODE \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_CTRL_HS_MODE_POS)) /**< CTRL_HS_MODE Mask */ -#define MXC_V_I2C_CTRL_HS_MODE_DIS \ - ((uint32_t)0x0UL) /**< CTRL_HS_MODE_DIS Value */ -#define MXC_S_I2C_CTRL_HS_MODE_DIS \ - (MXC_V_I2C_CTRL_HS_MODE_DIS \ - << MXC_F_I2C_CTRL_HS_MODE_POS) /**< CTRL_HS_MODE_DIS Setting */ -#define MXC_V_I2C_CTRL_HS_MODE_EN \ - ((uint32_t)0x1UL) /**< CTRL_HS_MODE_EN Value */ -#define MXC_S_I2C_CTRL_HS_MODE_EN \ - (MXC_V_I2C_CTRL_HS_MODE_EN \ - << MXC_F_I2C_CTRL_HS_MODE_POS) /**< CTRL_HS_MODE_EN Setting */ + << MXC_F_I2C_CTRL_SCL_CLK_STRECH_DIS_POS) + +/* CTRL_SCL_PP_MODE Position */ +#define MXC_F_I2C_CTRL_SCL_PP_MODE_POS 13 +/* CTRL_SCL_PP_MODE Mask */ +#define MXC_F_I2C_CTRL_SCL_PP_MODE (0x1UL << MXC_F_I2C_CTRL_SCL_PP_MODE_POS) +/* CTRL_SCL_PP_MODE_DIS Value */ +#define MXC_V_I2C_CTRL_SCL_PP_MODE_DIS 0x0UL +/* CTRL_SCL_PP_MODE_DIS Setting */ +#define MXC_S_I2C_CTRL_SCL_PP_MODE_DIS \ + (MXC_V_I2C_CTRL_SCL_PP_MODE_DIS << MXC_F_I2C_CTRL_SCL_PP_MODE_POS) +/* CTRL_SCL_PP_MODE_EN Value */ +#define MXC_V_I2C_CTRL_SCL_PP_MODE_EN 0x1UL +/* CTRL_SCL_PP_MODE_EN Setting */ +#define MXC_S_I2C_CTRL_SCL_PP_MODE_EN \ + (MXC_V_I2C_CTRL_SCL_PP_MODE_EN << MXC_F_I2C_CTRL_SCL_PP_MODE_POS) + +/* CTRL_HS_MODE Position */ +#define MXC_F_I2C_CTRL_HS_MODE_POS 15 +/* CTRL_HS_MODE Mask */ +#define MXC_F_I2C_CTRL_HS_MODE (0x1UL << MXC_F_I2C_CTRL_HS_MODE_POS) +/* CTRL_HS_MODE_DIS Value */ +#define MXC_V_I2C_CTRL_HS_MODE_DIS 0x0UL +/* CTRL_HS_MODE_DIS Setting */ +#define MXC_S_I2C_CTRL_HS_MODE_DIS \ + (MXC_V_I2C_CTRL_HS_MODE_DIS << MXC_F_I2C_CTRL_HS_MODE_POS) +/* CTRL_HS_MODE_EN Value */ +#define MXC_V_I2C_CTRL_HS_MODE_EN 0x1UL +/* CTRL_HS_MODE_EN Setting */ +#define MXC_S_I2C_CTRL_HS_MODE_EN \ + (MXC_V_I2C_CTRL_HS_MODE_EN << MXC_F_I2C_CTRL_HS_MODE_POS) /** * I2C_STATUS I2C_STATUS */ -#define MXC_F_I2C_STATUS_BUS_POS 0 /**< STATUS_BUS Position */ -#define MXC_F_I2C_STATUS_BUS \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_STATUS_BUS_POS)) /**< STATUS_BUS Mask \ - */ -#define MXC_V_I2C_STATUS_BUS_IDLE \ - ((uint32_t)0x0UL) /**< STATUS_BUS_IDLE Value */ -#define MXC_S_I2C_STATUS_BUS_IDLE \ - (MXC_V_I2C_STATUS_BUS_IDLE \ - << MXC_F_I2C_STATUS_BUS_POS) /**< STATUS_BUS_IDLE Setting */ -#define MXC_V_I2C_STATUS_BUS_BUSY \ - ((uint32_t)0x1UL) /**< STATUS_BUS_BUSY Value */ -#define MXC_S_I2C_STATUS_BUS_BUSY \ - (MXC_V_I2C_STATUS_BUS_BUSY \ - << MXC_F_I2C_STATUS_BUS_POS) /**< STATUS_BUS_BUSY Setting */ - -#define MXC_F_I2C_STATUS_RX_EMPTY_POS 1 /**< STATUS_RX_EMPTY Position */ -#define MXC_F_I2C_STATUS_RX_EMPTY \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_STATUS_RX_EMPTY_POS)) /**< STATUS_RX_EMPTY \ - Mask */ -#define MXC_V_I2C_STATUS_RX_EMPTY_NOT_EMPTY \ - ((uint32_t)0x0UL) /**< STATUS_RX_EMPTY_NOT_EMPTY Value */ -#define MXC_S_I2C_STATUS_RX_EMPTY_NOT_EMPTY \ - (MXC_V_I2C_STATUS_RX_EMPTY_NOT_EMPTY \ - << MXC_F_I2C_STATUS_RX_EMPTY_POS) /**< STATUS_RX_EMPTY_NOT_EMPTY \ - Setting */ -#define MXC_V_I2C_STATUS_RX_EMPTY_EMPTY \ - ((uint32_t)0x1UL) /**< STATUS_RX_EMPTY_EMPTY Value */ -#define MXC_S_I2C_STATUS_RX_EMPTY_EMPTY \ - (MXC_V_I2C_STATUS_RX_EMPTY_EMPTY \ - << MXC_F_I2C_STATUS_RX_EMPTY_POS) /**< STATUS_RX_EMPTY_EMPTY Setting \ - */ - -#define MXC_F_I2C_STATUS_RX_FULL_POS 2 /**< STATUS_RX_FULL Position */ -#define MXC_F_I2C_STATUS_RX_FULL \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_STATUS_RX_FULL_POS)) /**< STATUS_RX_FULL Mask */ -#define MXC_V_I2C_STATUS_RX_FULL_NOT_FULL \ - ((uint32_t)0x0UL) /**< STATUS_RX_FULL_NOT_FULL Value */ -#define MXC_S_I2C_STATUS_RX_FULL_NOT_FULL \ - (MXC_V_I2C_STATUS_RX_FULL_NOT_FULL \ - << MXC_F_I2C_STATUS_RX_FULL_POS) /**< STATUS_RX_FULL_NOT_FULL Setting \ - */ -#define MXC_V_I2C_STATUS_RX_FULL_FULL \ - ((uint32_t)0x1UL) /**< STATUS_RX_FULL_FULL Value */ -#define MXC_S_I2C_STATUS_RX_FULL_FULL \ - (MXC_V_I2C_STATUS_RX_FULL_FULL \ - << MXC_F_I2C_STATUS_RX_FULL_POS) /**< STATUS_RX_FULL_FULL Setting */ - -#define MXC_F_I2C_STATUS_TX_EMPTY_POS 3 /**< STATUS_TX_EMPTY Position */ -#define MXC_F_I2C_STATUS_TX_EMPTY \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_STATUS_TX_EMPTY_POS)) /**< STATUS_TX_EMPTY \ - Mask */ -#define MXC_V_I2C_STATUS_TX_EMPTY_NOT_EMPTY \ - ((uint32_t)0x0UL) /**< STATUS_TX_EMPTY_NOT_EMPTY Value */ -#define MXC_S_I2C_STATUS_TX_EMPTY_NOT_EMPTY \ - (MXC_V_I2C_STATUS_TX_EMPTY_NOT_EMPTY \ - << MXC_F_I2C_STATUS_TX_EMPTY_POS) /**< STATUS_TX_EMPTY_NOT_EMPTY \ - Setting */ -#define MXC_V_I2C_STATUS_TX_EMPTY_EMPTY \ - ((uint32_t)0x1UL) /**< STATUS_TX_EMPTY_EMPTY Value */ -#define MXC_S_I2C_STATUS_TX_EMPTY_EMPTY \ - (MXC_V_I2C_STATUS_TX_EMPTY_EMPTY \ - << MXC_F_I2C_STATUS_TX_EMPTY_POS) /**< STATUS_TX_EMPTY_EMPTY Setting \ - */ - -#define MXC_F_I2C_STATUS_TX_FULL_POS 4 /**< STATUS_TX_FULL Position */ -#define MXC_F_I2C_STATUS_TX_FULL \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_STATUS_TX_FULL_POS)) /**< STATUS_TX_FULL Mask */ -#define MXC_V_I2C_STATUS_TX_FULL_NOT_EMPTY \ - ((uint32_t)0x0UL) /**< STATUS_TX_FULL_NOT_EMPTY Value */ -#define MXC_S_I2C_STATUS_TX_FULL_NOT_EMPTY \ - (MXC_V_I2C_STATUS_TX_FULL_NOT_EMPTY \ - << MXC_F_I2C_STATUS_TX_FULL_POS) /**< STATUS_TX_FULL_NOT_EMPTY \ - Setting */ -#define MXC_V_I2C_STATUS_TX_FULL_EMPTY \ - ((uint32_t)0x1UL) /**< STATUS_TX_FULL_EMPTY Value */ -#define MXC_S_I2C_STATUS_TX_FULL_EMPTY \ - (MXC_V_I2C_STATUS_TX_FULL_EMPTY \ - << MXC_F_I2C_STATUS_TX_FULL_POS) /**< STATUS_TX_FULL_EMPTY Setting */ - -#define MXC_F_I2C_STATUS_CLK_MODE_POS 5 /**< STATUS_CLK_MODE Position */ -#define MXC_F_I2C_STATUS_CLK_MODE \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_STATUS_CLK_MODE_POS)) /**< STATUS_CLK_MODE \ - Mask */ -#define MXC_V_I2C_STATUS_CLK_MODE_NOT_ACTIVELY_DRIVING_SCL_CLOCK \ - ((uint32_t)0x0UL) /**< STATUS_CLK_MODE_NOT_ACTIVELY_DRIVING_SCL_CLOCK \ - Value */ +/* STATUS_BUS Position */ +#define MXC_F_I2C_STATUS_BUS_POS 0 +/* STATUS_BUS Mask */ +#define MXC_F_I2C_STATUS_BUS (0x1UL << MXC_F_I2C_STATUS_BUS_POS) +#define MXC_V_I2C_STATUS_BUS_IDLE 0x0UL /* STATUS_BUS_IDLE Value */ +/* STATUS_BUS_IDLE Setting */ +#define MXC_S_I2C_STATUS_BUS_IDLE \ + (MXC_V_I2C_STATUS_BUS_IDLE << MXC_F_I2C_STATUS_BUS_POS) +/* STATUS_BUS_BUSY Value */ +#define MXC_V_I2C_STATUS_BUS_BUSY 0x1UL +/* STATUS_BUS_BUSY Setting */ +#define MXC_S_I2C_STATUS_BUS_BUSY \ + (MXC_V_I2C_STATUS_BUS_BUSY << MXC_F_I2C_STATUS_BUS_POS) + +/* STATUS_RX_EMPTY Position */ +#define MXC_F_I2C_STATUS_RX_EMPTY_POS 1 +/* STATUS_RX_EMPTY Mask */ +#define MXC_F_I2C_STATUS_RX_EMPTY (0x1UL << MXC_F_I2C_STATUS_RX_EMPTY_POS) +/* STATUS_RX_EMPTY_NOT_EMPTY Value */ +#define MXC_V_I2C_STATUS_RX_EMPTY_NOT_EMPTY 0x0UL +/* STATUS_RX_EMPTY_NOT_EMPTY Setting */ +#define MXC_S_I2C_STATUS_RX_EMPTY_NOT_EMPTY \ + (MXC_V_I2C_STATUS_RX_EMPTY_NOT_EMPTY << MXC_F_I2C_STATUS_RX_EMPTY_POS) +/* STATUS_RX_EMPTY_EMPTY Value */ +#define MXC_V_I2C_STATUS_RX_EMPTY_EMPTY 0x1UL +/* STATUS_RX_EMPTY_EMPTY Setting */ +#define MXC_S_I2C_STATUS_RX_EMPTY_EMPTY \ + (MXC_V_I2C_STATUS_RX_EMPTY_EMPTY << MXC_F_I2C_STATUS_RX_EMPTY_POS) + +/* STATUS_RX_FULL Position */ +#define MXC_F_I2C_STATUS_RX_FULL_POS 2 +/* STATUS_RX_FULL Mask */ +#define MXC_F_I2C_STATUS_RX_FULL (0x1UL << MXC_F_I2C_STATUS_RX_FULL_POS) +/* STATUS_RX_FULL_NOT_FULL Value */ +#define MXC_V_I2C_STATUS_RX_FULL_NOT_FULL 0x0UL +/* STATUS_RX_FULL_NOT_FULL Setting */ +#define MXC_S_I2C_STATUS_RX_FULL_NOT_FULL \ + (MXC_V_I2C_STATUS_RX_FULL_NOT_FULL << MXC_F_I2C_STATUS_RX_FULL_POS) +/* STATUS_RX_FULL_FULL Value */ +#define MXC_V_I2C_STATUS_RX_FULL_FULL 0x1UL +/* STATUS_RX_FULL_FULL Setting */ +#define MXC_S_I2C_STATUS_RX_FULL_FULL \ + (MXC_V_I2C_STATUS_RX_FULL_FULL << MXC_F_I2C_STATUS_RX_FULL_POS) + +/* STATUS_TX_EMPTY Position */ +#define MXC_F_I2C_STATUS_TX_EMPTY_POS 3 +/* STATUS_TX_EMPTY Mask */ +#define MXC_F_I2C_STATUS_TX_EMPTY (0x1UL << MXC_F_I2C_STATUS_TX_EMPTY_POS) +/* STATUS_TX_EMPTY_NOT_EMPTY Value */ +#define MXC_V_I2C_STATUS_TX_EMPTY_NOT_EMPTY 0x0UL +/* STATUS_TX_EMPTY_NOT_EMPTY Setting */ +#define MXC_S_I2C_STATUS_TX_EMPTY_NOT_EMPTY \ + (MXC_V_I2C_STATUS_TX_EMPTY_NOT_EMPTY << MXC_F_I2C_STATUS_TX_EMPTY_POS) +/* STATUS_TX_EMPTY_EMPTY Value */ +#define MXC_V_I2C_STATUS_TX_EMPTY_EMPTY 0x1UL +/* STATUS_TX_EMPTY_EMPTY Setting */ +#define MXC_S_I2C_STATUS_TX_EMPTY_EMPTY \ + (MXC_V_I2C_STATUS_TX_EMPTY_EMPTY << MXC_F_I2C_STATUS_TX_EMPTY_POS) + +/* STATUS_TX_FULL Position */ +#define MXC_F_I2C_STATUS_TX_FULL_POS 4 +/* STATUS_TX_FULL Mask */ +#define MXC_F_I2C_STATUS_TX_FULL (0x1UL << MXC_F_I2C_STATUS_TX_FULL_POS) +/* STATUS_TX_FULL_NOT_EMPTY Value */ +#define MXC_V_I2C_STATUS_TX_FULL_NOT_EMPTY 0x0UL +/* STATUS_TX_FULL_NOT_EMPTY Setting */ +#define MXC_S_I2C_STATUS_TX_FULL_NOT_EMPTY \ + (MXC_V_I2C_STATUS_TX_FULL_NOT_EMPTY << MXC_F_I2C_STATUS_TX_FULL_POS) +/* STATUS_TX_FULL_EMPTY Value */ +#define MXC_V_I2C_STATUS_TX_FULL_EMPTY 0x1UL +/* STATUS_TX_FULL_EMPTY Setting */ +#define MXC_S_I2C_STATUS_TX_FULL_EMPTY \ + (MXC_V_I2C_STATUS_TX_FULL_EMPTY << MXC_F_I2C_STATUS_TX_FULL_POS) + +/* STATUS_CLK_MODE Position */ +#define MXC_F_I2C_STATUS_CLK_MODE_POS 5 +/* STATUS_CLK_MODE Mask */ +#define MXC_F_I2C_STATUS_CLK_MODE (0x1UL << MXC_F_I2C_STATUS_CLK_MODE_POS) +/* STATUS_CLK_MODE_NOT_ACTIVELY_DRIVING_SCL_CLOCK Value */ +#define MXC_V_I2C_STATUS_CLK_MODE_NOT_ACTIVELY_DRIVING_SCL_CLOCK 0x0UL +/* STATUS_CLK_MODE_NOT_ACTIVELY_DRIVING_SCL_CLOCK Setting */ #define MXC_S_I2C_STATUS_CLK_MODE_NOT_ACTIVELY_DRIVING_SCL_CLOCK \ (MXC_V_I2C_STATUS_CLK_MODE_NOT_ACTIVELY_DRIVING_SCL_CLOCK \ - << MXC_F_I2C_STATUS_CLK_MODE_POS) /**< \ - STATUS_CLK_MODE_NOT_ACTIVELY_DRIVING_SCL_CLOCK \ - Setting */ -#define MXC_V_I2C_STATUS_CLK_MODE_ACTIVELY_DRIVING_SCL_CLOCK \ - ((uint32_t)0x1UL) /**< STATUS_CLK_MODE_ACTIVELY_DRIVING_SCL_CLOCK \ - Value */ + << MXC_F_I2C_STATUS_CLK_MODE_POS) +/* STATUS_CLK_MODE_ACTIVELY_DRIVING_SCL_CLOCK Value */ +#define MXC_V_I2C_STATUS_CLK_MODE_ACTIVELY_DRIVING_SCL_CLOCK 0x1UL +/* STATUS_CLK_MODE_ACTIVELY_DRIVING_SCL_CLOCK Setting */ #define MXC_S_I2C_STATUS_CLK_MODE_ACTIVELY_DRIVING_SCL_CLOCK \ (MXC_V_I2C_STATUS_CLK_MODE_ACTIVELY_DRIVING_SCL_CLOCK \ - << MXC_F_I2C_STATUS_CLK_MODE_POS) /**< \ - STATUS_CLK_MODE_ACTIVELY_DRIVING_SCL_CLOCK \ - Setting */ - -#define MXC_F_I2C_STATUS_STATUS_POS 8 /**< STATUS_STATUS Position */ -#define MXC_F_I2C_STATUS_STATUS \ - ((uint32_t)( \ - 0xFUL \ - << MXC_F_I2C_STATUS_STATUS_POS)) /**< STATUS_STATUS Mask */ -#define MXC_V_I2C_STATUS_STATUS_IDLE \ - ((uint32_t)0x0UL) /**< STATUS_STATUS_IDLE Value */ -#define MXC_S_I2C_STATUS_STATUS_IDLE \ - (MXC_V_I2C_STATUS_STATUS_IDLE \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_IDLE Setting */ -#define MXC_V_I2C_STATUS_STATUS_MTX_ADDR \ - ((uint32_t)0x1UL) /**< STATUS_STATUS_MTX_ADDR Value */ -#define MXC_S_I2C_STATUS_STATUS_MTX_ADDR \ - (MXC_V_I2C_STATUS_STATUS_MTX_ADDR \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_MTX_ADDR Setting \ - */ -#define MXC_V_I2C_STATUS_STATUS_MRX_ADDR_ACK \ - ((uint32_t)0x2UL) /**< STATUS_STATUS_MRX_ADDR_ACK Value */ -#define MXC_S_I2C_STATUS_STATUS_MRX_ADDR_ACK \ - (MXC_V_I2C_STATUS_STATUS_MRX_ADDR_ACK \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_MRX_ADDR_ACK \ - Setting */ -#define MXC_V_I2C_STATUS_STATUS_MTX_EX_ADDR \ - ((uint32_t)0x3UL) /**< STATUS_STATUS_MTX_EX_ADDR Value */ -#define MXC_S_I2C_STATUS_STATUS_MTX_EX_ADDR \ - (MXC_V_I2C_STATUS_STATUS_MTX_EX_ADDR \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_MTX_EX_ADDR \ - Setting */ -#define MXC_V_I2C_STATUS_STATUS_MRX_EX_ADDR \ - ((uint32_t)0x4UL) /**< STATUS_STATUS_MRX_EX_ADDR Value */ -#define MXC_S_I2C_STATUS_STATUS_MRX_EX_ADDR \ - (MXC_V_I2C_STATUS_STATUS_MRX_EX_ADDR \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_MRX_EX_ADDR \ - Setting */ -#define MXC_V_I2C_STATUS_STATUS_SRX_ADDR \ - ((uint32_t)0x5UL) /**< STATUS_STATUS_SRX_ADDR Value */ -#define MXC_S_I2C_STATUS_STATUS_SRX_ADDR \ - (MXC_V_I2C_STATUS_STATUS_SRX_ADDR \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_SRX_ADDR Setting \ - */ -#define MXC_V_I2C_STATUS_STATUS_STX_ADDR_ACK \ - ((uint32_t)0x6UL) /**< STATUS_STATUS_STX_ADDR_ACK Value */ -#define MXC_S_I2C_STATUS_STATUS_STX_ADDR_ACK \ - (MXC_V_I2C_STATUS_STATUS_STX_ADDR_ACK \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_STX_ADDR_ACK \ - Setting */ -#define MXC_V_I2C_STATUS_STATUS_SRX_EX_ADDR \ - ((uint32_t)0x7UL) /**< STATUS_STATUS_SRX_EX_ADDR Value */ -#define MXC_S_I2C_STATUS_STATUS_SRX_EX_ADDR \ - (MXC_V_I2C_STATUS_STATUS_SRX_EX_ADDR \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_SRX_EX_ADDR \ - Setting */ -#define MXC_V_I2C_STATUS_STATUS_STX_EX_ADDR_ACK \ - ((uint32_t)0x8UL) /**< STATUS_STATUS_STX_EX_ADDR_ACK Value */ -#define MXC_S_I2C_STATUS_STATUS_STX_EX_ADDR_ACK \ - (MXC_V_I2C_STATUS_STATUS_STX_EX_ADDR_ACK \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_STX_EX_ADDR_ACK \ - Setting */ -#define MXC_V_I2C_STATUS_STATUS_TX \ - ((uint32_t)0x9UL) /**< STATUS_STATUS_TX Value */ -#define MXC_S_I2C_STATUS_STATUS_TX \ - (MXC_V_I2C_STATUS_STATUS_TX \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_TX Setting */ -#define MXC_V_I2C_STATUS_STATUS_RX_ACK \ - ((uint32_t)0xAUL) /**< STATUS_STATUS_RX_ACK Value */ -#define MXC_S_I2C_STATUS_STATUS_RX_ACK \ - (MXC_V_I2C_STATUS_STATUS_RX_ACK \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_RX_ACK Setting */ -#define MXC_V_I2C_STATUS_STATUS_RX \ - ((uint32_t)0xBUL) /**< STATUS_STATUS_RX Value */ -#define MXC_S_I2C_STATUS_STATUS_RX \ - (MXC_V_I2C_STATUS_STATUS_RX \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_RX Setting */ -#define MXC_V_I2C_STATUS_STATUS_TX_ACK \ - ((uint32_t)0xCUL) /**< STATUS_STATUS_TX_ACK Value */ -#define MXC_S_I2C_STATUS_STATUS_TX_ACK \ - (MXC_V_I2C_STATUS_STATUS_TX_ACK \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_TX_ACK Setting */ -#define MXC_V_I2C_STATUS_STATUS_NACK \ - ((uint32_t)0xDUL) /**< STATUS_STATUS_NACK Value */ -#define MXC_S_I2C_STATUS_STATUS_NACK \ - (MXC_V_I2C_STATUS_STATUS_NACK \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_NACK Setting */ -#define MXC_V_I2C_STATUS_STATUS_BY_ST \ - ((uint32_t)0xFUL) /**< STATUS_STATUS_BY_ST Value */ -#define MXC_S_I2C_STATUS_STATUS_BY_ST \ - (MXC_V_I2C_STATUS_STATUS_BY_ST \ - << MXC_F_I2C_STATUS_STATUS_POS) /**< STATUS_STATUS_BY_ST Setting */ + << MXC_F_I2C_STATUS_CLK_MODE_POS) + +/* STATUS_STATUS Position */ +#define MXC_F_I2C_STATUS_STATUS_POS 8 +/* STATUS_STATUS Mask */ +#define MXC_F_I2C_STATUS_STATUS (0xFUL << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_IDLE Value */ +#define MXC_V_I2C_STATUS_STATUS_IDLE 0x0UL +/* STATUS_STATUS_IDLE Setting */ +#define MXC_S_I2C_STATUS_STATUS_IDLE \ + (MXC_V_I2C_STATUS_STATUS_IDLE << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_MTX_ADDR Value */ +#define MXC_V_I2C_STATUS_STATUS_MTX_ADDR 0x1UL +/* STATUS_STATUS_MTX_ADDR Setting */ +#define MXC_S_I2C_STATUS_STATUS_MTX_ADDR \ + (MXC_V_I2C_STATUS_STATUS_MTX_ADDR << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_MRX_ADDR_ACK Value */ +#define MXC_V_I2C_STATUS_STATUS_MRX_ADDR_ACK 0x2UL +/* STATUS_STATUS_MRX_ADDR_ACK Setting */ +#define MXC_S_I2C_STATUS_STATUS_MRX_ADDR_ACK \ + (MXC_V_I2C_STATUS_STATUS_MRX_ADDR_ACK << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_MTX_EX_ADDR Value */ +#define MXC_V_I2C_STATUS_STATUS_MTX_EX_ADDR 0x3UL +/* STATUS_STATUS_MTX_EX_ADDR Setting */ +#define MXC_S_I2C_STATUS_STATUS_MTX_EX_ADDR \ + (MXC_V_I2C_STATUS_STATUS_MTX_EX_ADDR << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_MRX_EX_ADDR Value */ +#define MXC_V_I2C_STATUS_STATUS_MRX_EX_ADDR 0x4UL +/* STATUS_STATUS_MRX_EX_ADDR Setting */ +#define MXC_S_I2C_STATUS_STATUS_MRX_EX_ADDR \ + (MXC_V_I2C_STATUS_STATUS_MRX_EX_ADDR << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_SRX_ADDR Value */ +#define MXC_V_I2C_STATUS_STATUS_SRX_ADDR 0x5UL +/* STATUS_STATUS_SRX_ADDR Setting */ +#define MXC_S_I2C_STATUS_STATUS_SRX_ADDR \ + (MXC_V_I2C_STATUS_STATUS_SRX_ADDR << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_STX_ADDR_ACK Value */ +#define MXC_V_I2C_STATUS_STATUS_STX_ADDR_ACK 0x6UL +/* STATUS_STATUS_STX_ADDR_ACK Setting */ +#define MXC_S_I2C_STATUS_STATUS_STX_ADDR_ACK \ + (MXC_V_I2C_STATUS_STATUS_STX_ADDR_ACK << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_SRX_EX_ADDR Value */ +#define MXC_V_I2C_STATUS_STATUS_SRX_EX_ADDR 0x7UL +/* STATUS_STATUS_SRX_EX_ADDR Setting */ +#define MXC_S_I2C_STATUS_STATUS_SRX_EX_ADDR \ + (MXC_V_I2C_STATUS_STATUS_SRX_EX_ADDR << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_STX_EX_ADDR_ACK Value */ +#define MXC_V_I2C_STATUS_STATUS_STX_EX_ADDR_ACK 0x8UL +/* STATUS_STATUS_STX_EX_ADDR_ACK Setting */ +#define MXC_S_I2C_STATUS_STATUS_STX_EX_ADDR_ACK \ + (MXC_V_I2C_STATUS_STATUS_STX_EX_ADDR_ACK << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_TX Value */ +#define MXC_V_I2C_STATUS_STATUS_TX 0x9UL +/* STATUS_STATUS_TX Setting */ +#define MXC_S_I2C_STATUS_STATUS_TX \ + (MXC_V_I2C_STATUS_STATUS_TX << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_RX_ACK Value */ +#define MXC_V_I2C_STATUS_STATUS_RX_ACK 0xAUL +/* STATUS_STATUS_RX_ACK Setting */ +#define MXC_S_I2C_STATUS_STATUS_RX_ACK \ + (MXC_V_I2C_STATUS_STATUS_RX_ACK << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_RX Value */ +#define MXC_V_I2C_STATUS_STATUS_RX 0xBUL +/* STATUS_STATUS_RX Setting */ +#define MXC_S_I2C_STATUS_STATUS_RX \ + (MXC_V_I2C_STATUS_STATUS_RX << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_TX_ACK Value */ +#define MXC_V_I2C_STATUS_STATUS_TX_ACK 0xCUL +/* STATUS_STATUS_TX_ACK Setting */ +#define MXC_S_I2C_STATUS_STATUS_TX_ACK \ + (MXC_V_I2C_STATUS_STATUS_TX_ACK << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_NACK Value */ +#define MXC_V_I2C_STATUS_STATUS_NACK 0xDUL +/* STATUS_STATUS_NACK Setting */ +#define MXC_S_I2C_STATUS_STATUS_NACK \ + (MXC_V_I2C_STATUS_STATUS_NACK << MXC_F_I2C_STATUS_STATUS_POS) +/* STATUS_STATUS_BY_ST Value */ +#define MXC_V_I2C_STATUS_STATUS_BY_ST 0xFUL +/* STATUS_STATUS_BY_ST Setting */ +#define MXC_S_I2C_STATUS_STATUS_BY_ST \ + (MXC_V_I2C_STATUS_STATUS_BY_ST << MXC_F_I2C_STATUS_STATUS_POS) /** * Interrupt Status Register. */ -#define MXC_F_I2C_INT_FL0_DONE_POS 0 /**< INT_FL0_DONE Position */ -#define MXC_F_I2C_INT_FL0_DONE \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_FL0_DONE_POS)) /**< INT_FL0_DONE Mask */ -#define MXC_V_I2C_INT_FL0_DONE_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_DONE_INACTIVE Value */ -#define MXC_S_I2C_INT_FL0_DONE_INACTIVE \ - (MXC_V_I2C_INT_FL0_DONE_INACTIVE \ - << MXC_F_I2C_INT_FL0_DONE_POS) /**< INT_FL0_DONE_INACTIVE Setting */ -#define MXC_V_I2C_INT_FL0_DONE_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_DONE_PENDING Value */ -#define MXC_S_I2C_INT_FL0_DONE_PENDING \ - (MXC_V_I2C_INT_FL0_DONE_PENDING \ - << MXC_F_I2C_INT_FL0_DONE_POS) /**< INT_FL0_DONE_PENDING Setting */ - -#define MXC_F_I2C_INT_FL0_RX_MODE_POS 1 /**< INT_FL0_RX_MODE Position */ -#define MXC_F_I2C_INT_FL0_RX_MODE \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_FL0_RX_MODE_POS)) /**< INT_FL0_RX_MODE \ - Mask */ -#define MXC_V_I2C_INT_FL0_RX_MODE_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_RX_MODE_INACTIVE Value */ -#define MXC_S_I2C_INT_FL0_RX_MODE_INACTIVE \ - (MXC_V_I2C_INT_FL0_RX_MODE_INACTIVE \ - << MXC_F_I2C_INT_FL0_RX_MODE_POS) /**< INT_FL0_RX_MODE_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_RX_MODE_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_RX_MODE_PENDING Value */ -#define MXC_S_I2C_INT_FL0_RX_MODE_PENDING \ - (MXC_V_I2C_INT_FL0_RX_MODE_PENDING \ - << MXC_F_I2C_INT_FL0_RX_MODE_POS) /**< INT_FL0_RX_MODE_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_GEN_CALL_ADDR_POS \ - 2 /**< INT_FL0_GEN_CALL_ADDR Position */ +/* INT_FL0_DONE Position */ +#define MXC_F_I2C_INT_FL0_DONE_POS 0 +/* INT_FL0_DONE Mask */ +#define MXC_F_I2C_INT_FL0_DONE (0x1UL << MXC_F_I2C_INT_FL0_DONE_POS) +/* INT_FL0_DONE_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_DONE_INACTIVE 0x0UL +/* INT_FL0_DONE_INACTIVE Setting */ +#define MXC_S_I2C_INT_FL0_DONE_INACTIVE \ + (MXC_V_I2C_INT_FL0_DONE_INACTIVE << MXC_F_I2C_INT_FL0_DONE_POS) +/* INT_FL0_DONE_PENDING Value */ +#define MXC_V_I2C_INT_FL0_DONE_PENDING 0x1UL +/* INT_FL0_DONE_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_DONE_PENDING \ + (MXC_V_I2C_INT_FL0_DONE_PENDING << MXC_F_I2C_INT_FL0_DONE_POS) + +/* INT_FL0_RX_MODE Position */ +#define MXC_F_I2C_INT_FL0_RX_MODE_POS 1 +/* INT_FL0_RX_MODE Mask */ +#define MXC_F_I2C_INT_FL0_RX_MODE (0x1UL << MXC_F_I2C_INT_FL0_RX_MODE_POS) +/* INT_FL0_RX_MODE_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_RX_MODE_INACTIVE 0x0UL +/* INT_FL0_RX_MODE_INACTIVE Setting */ +#define MXC_S_I2C_INT_FL0_RX_MODE_INACTIVE \ + (MXC_V_I2C_INT_FL0_RX_MODE_INACTIVE << MXC_F_I2C_INT_FL0_RX_MODE_POS) +/* INT_FL0_RX_MODE_PENDING Value */ +#define MXC_V_I2C_INT_FL0_RX_MODE_PENDING 0x1UL +/* INT_FL0_RX_MODE_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_RX_MODE_PENDING \ + (MXC_V_I2C_INT_FL0_RX_MODE_PENDING << MXC_F_I2C_INT_FL0_RX_MODE_POS) + +/* INT_FL0_GEN_CALL_ADDR Position */ +#define MXC_F_I2C_INT_FL0_GEN_CALL_ADDR_POS 2 +/* INT_FL0_GEN_CALL_ADDR Mask */ #define MXC_F_I2C_INT_FL0_GEN_CALL_ADDR \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_GEN_CALL_ADDR_POS)) /**< \ - INT_FL0_GEN_CALL_ADDR \ - Mask */ -#define MXC_V_I2C_INT_FL0_GEN_CALL_ADDR_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_GEN_CALL_ADDR_INACTIVE Value */ + (0x1UL << MXC_F_I2C_INT_FL0_GEN_CALL_ADDR_POS) +/* INT_FL0_GEN_CALL_ADDR_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_GEN_CALL_ADDR_INACTIVE 0x0UL +/* INT_FL0_GEN_CALL_ADDR_INACTIVE Setting */ #define MXC_S_I2C_INT_FL0_GEN_CALL_ADDR_INACTIVE \ (MXC_V_I2C_INT_FL0_GEN_CALL_ADDR_INACTIVE \ - << MXC_F_I2C_INT_FL0_GEN_CALL_ADDR_POS) /**< \ - INT_FL0_GEN_CALL_ADDR_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_GEN_CALL_ADDR_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_GEN_CALL_ADDR_PENDING Value */ + << MXC_F_I2C_INT_FL0_GEN_CALL_ADDR_POS) +/* INT_FL0_GEN_CALL_ADDR_PENDING Value */ +#define MXC_V_I2C_INT_FL0_GEN_CALL_ADDR_PENDING 0x1UL +/* INT_FL0_GEN_CALL_ADDR_PENDING Setting */ #define MXC_S_I2C_INT_FL0_GEN_CALL_ADDR_PENDING \ (MXC_V_I2C_INT_FL0_GEN_CALL_ADDR_PENDING \ - << MXC_F_I2C_INT_FL0_GEN_CALL_ADDR_POS) /**< \ - INT_FL0_GEN_CALL_ADDR_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_ADDR_MATCH_POS 3 /**< INT_FL0_ADDR_MATCH Position */ -#define MXC_F_I2C_INT_FL0_ADDR_MATCH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_ADDR_MATCH_POS)) /**< INT_FL0_ADDR_MATCH \ - Mask */ -#define MXC_V_I2C_INT_FL0_ADDR_MATCH_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_ADDR_MATCH_INACTIVE Value */ + << MXC_F_I2C_INT_FL0_GEN_CALL_ADDR_POS) + +/* INT_FL0_ADDR_MATCH Position */ +#define MXC_F_I2C_INT_FL0_ADDR_MATCH_POS 3 +/* INT_FL0_ADDR_MATCH Mask */ +#define MXC_F_I2C_INT_FL0_ADDR_MATCH (0x1UL << MXC_F_I2C_INT_FL0_ADDR_MATCH_POS) +/* INT_FL0_ADDR_MATCH_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_ADDR_MATCH_INACTIVE 0x0UL +/* INT_FL0_ADDR_MATCH_INACTIVE Setting */ #define MXC_S_I2C_INT_FL0_ADDR_MATCH_INACTIVE \ (MXC_V_I2C_INT_FL0_ADDR_MATCH_INACTIVE \ - << MXC_F_I2C_INT_FL0_ADDR_MATCH_POS) /**< INT_FL0_ADDR_MATCH_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_ADDR_MATCH_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_ADDR_MATCH_PENDING Value */ + << MXC_F_I2C_INT_FL0_ADDR_MATCH_POS) +/* INT_FL0_ADDR_MATCH_PENDING Value */ +#define MXC_V_I2C_INT_FL0_ADDR_MATCH_PENDING 0x1UL +/* INT_FL0_ADDR_MATCH_PENDING Setting */ #define MXC_S_I2C_INT_FL0_ADDR_MATCH_PENDING \ (MXC_V_I2C_INT_FL0_ADDR_MATCH_PENDING \ - << MXC_F_I2C_INT_FL0_ADDR_MATCH_POS) /**< INT_FL0_ADDR_MATCH_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_RX_THRESH_POS 4 /**< INT_FL0_RX_THRESH Position */ -#define MXC_F_I2C_INT_FL0_RX_THRESH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_RX_THRESH_POS)) /**< INT_FL0_RX_THRESH \ - Mask */ -#define MXC_V_I2C_INT_FL0_RX_THRESH_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_RX_THRESH_INACTIVE Value */ + << MXC_F_I2C_INT_FL0_ADDR_MATCH_POS) + +/* INT_FL0_RX_THRESH Position */ +#define MXC_F_I2C_INT_FL0_RX_THRESH_POS 4 +/* INT_FL0_RX_THRESH Mask */ +#define MXC_F_I2C_INT_FL0_RX_THRESH (0x1UL << MXC_F_I2C_INT_FL0_RX_THRESH_POS) +/* INT_FL0_RX_THRESH_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_RX_THRESH_INACTIVE 0x0UL +/* INT_FL0_RX_THRESH_INACTIVE Setting */ #define MXC_S_I2C_INT_FL0_RX_THRESH_INACTIVE \ (MXC_V_I2C_INT_FL0_RX_THRESH_INACTIVE \ - << MXC_F_I2C_INT_FL0_RX_THRESH_POS) /**< INT_FL0_RX_THRESH_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_RX_THRESH_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_RX_THRESH_PENDING Value */ -#define MXC_S_I2C_INT_FL0_RX_THRESH_PENDING \ - (MXC_V_I2C_INT_FL0_RX_THRESH_PENDING \ - << MXC_F_I2C_INT_FL0_RX_THRESH_POS) /**< INT_FL0_RX_THRESH_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_TX_THRESH_POS 5 /**< INT_FL0_TX_THRESH Position */ -#define MXC_F_I2C_INT_FL0_TX_THRESH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_TX_THRESH_POS)) /**< INT_FL0_TX_THRESH \ - Mask */ -#define MXC_V_I2C_INT_FL0_TX_THRESH_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_TX_THRESH_INACTIVE Value */ + << MXC_F_I2C_INT_FL0_RX_THRESH_POS) +/* INT_FL0_RX_THRESH_PENDING Value */ +#define MXC_V_I2C_INT_FL0_RX_THRESH_PENDING 0x1UL +/* INT_FL0_RX_THRESH_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_RX_THRESH_PENDING \ + (MXC_V_I2C_INT_FL0_RX_THRESH_PENDING << MXC_F_I2C_INT_FL0_RX_THRESH_POS) + +/* INT_FL0_TX_THRESH Position */ +#define MXC_F_I2C_INT_FL0_TX_THRESH_POS 5 +/* INT_FL0_TX_THRESH Mask */ +#define MXC_F_I2C_INT_FL0_TX_THRESH (0x1UL << MXC_F_I2C_INT_FL0_TX_THRESH_POS) +/* INT_FL0_TX_THRESH_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_TX_THRESH_INACTIVE 0x0UL +/* INT_FL0_TX_THRESH_INACTIVE Setting */ #define MXC_S_I2C_INT_FL0_TX_THRESH_INACTIVE \ (MXC_V_I2C_INT_FL0_TX_THRESH_INACTIVE \ - << MXC_F_I2C_INT_FL0_TX_THRESH_POS) /**< INT_FL0_TX_THRESH_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_TX_THRESH_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_TX_THRESH_PENDING Value */ -#define MXC_S_I2C_INT_FL0_TX_THRESH_PENDING \ - (MXC_V_I2C_INT_FL0_TX_THRESH_PENDING \ - << MXC_F_I2C_INT_FL0_TX_THRESH_POS) /**< INT_FL0_TX_THRESH_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_STOP_POS 6 /**< INT_FL0_STOP Position */ -#define MXC_F_I2C_INT_FL0_STOP \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_FL0_STOP_POS)) /**< INT_FL0_STOP Mask */ -#define MXC_V_I2C_INT_FL0_STOP_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_STOP_INACTIVE Value */ -#define MXC_S_I2C_INT_FL0_STOP_INACTIVE \ - (MXC_V_I2C_INT_FL0_STOP_INACTIVE \ - << MXC_F_I2C_INT_FL0_STOP_POS) /**< INT_FL0_STOP_INACTIVE Setting */ -#define MXC_V_I2C_INT_FL0_STOP_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_STOP_PENDING Value */ -#define MXC_S_I2C_INT_FL0_STOP_PENDING \ - (MXC_V_I2C_INT_FL0_STOP_PENDING \ - << MXC_F_I2C_INT_FL0_STOP_POS) /**< INT_FL0_STOP_PENDING Setting */ - -#define MXC_F_I2C_INT_FL0_ADDR_ACK_POS 7 /**< INT_FL0_ADDR_ACK Position */ -#define MXC_F_I2C_INT_FL0_ADDR_ACK \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_ADDR_ACK_POS)) /**< INT_FL0_ADDR_ACK \ - Mask */ -#define MXC_V_I2C_INT_FL0_ADDR_ACK_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_ADDR_ACK_INACTIVE Value */ -#define MXC_S_I2C_INT_FL0_ADDR_ACK_INACTIVE \ - (MXC_V_I2C_INT_FL0_ADDR_ACK_INACTIVE \ - << MXC_F_I2C_INT_FL0_ADDR_ACK_POS) /**< INT_FL0_ADDR_ACK_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_ADDR_ACK_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_ADDR_ACK_PENDING Value */ -#define MXC_S_I2C_INT_FL0_ADDR_ACK_PENDING \ - (MXC_V_I2C_INT_FL0_ADDR_ACK_PENDING \ - << MXC_F_I2C_INT_FL0_ADDR_ACK_POS) /**< INT_FL0_ADDR_ACK_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_ARB_ER_POS 8 /**< INT_FL0_ARB_ER Position */ -#define MXC_F_I2C_INT_FL0_ARB_ER \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_ARB_ER_POS)) /**< INT_FL0_ARB_ER Mask */ -#define MXC_V_I2C_INT_FL0_ARB_ER_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_ARB_ER_INACTIVE Value */ -#define MXC_S_I2C_INT_FL0_ARB_ER_INACTIVE \ - (MXC_V_I2C_INT_FL0_ARB_ER_INACTIVE \ - << MXC_F_I2C_INT_FL0_ARB_ER_POS) /**< INT_FL0_ARB_ER_INACTIVE Setting \ - */ -#define MXC_V_I2C_INT_FL0_ARB_ER_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_ARB_ER_PENDING Value */ -#define MXC_S_I2C_INT_FL0_ARB_ER_PENDING \ - (MXC_V_I2C_INT_FL0_ARB_ER_PENDING \ - << MXC_F_I2C_INT_FL0_ARB_ER_POS) /**< INT_FL0_ARB_ER_PENDING Setting \ - */ - -#define MXC_F_I2C_INT_FL0_TO_ER_POS 9 /**< INT_FL0_TO_ER Position */ -#define MXC_F_I2C_INT_FL0_TO_ER \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_TO_ER_POS)) /**< INT_FL0_TO_ER Mask */ -#define MXC_V_I2C_INT_FL0_TO_ER_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_TO_ER_INACTIVE Value */ -#define MXC_S_I2C_INT_FL0_TO_ER_INACTIVE \ - (MXC_V_I2C_INT_FL0_TO_ER_INACTIVE \ - << MXC_F_I2C_INT_FL0_TO_ER_POS) /**< INT_FL0_TO_ER_INACTIVE Setting \ - */ -#define MXC_V_I2C_INT_FL0_TO_ER_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_TO_ER_PENDING Value */ -#define MXC_S_I2C_INT_FL0_TO_ER_PENDING \ - (MXC_V_I2C_INT_FL0_TO_ER_PENDING \ - << MXC_F_I2C_INT_FL0_TO_ER_POS) /**< INT_FL0_TO_ER_PENDING Setting */ - -#define MXC_F_I2C_INT_FL0_ADDR_NACK_ER_POS \ - 10 /**< INT_FL0_ADDR_NACK_ER Position */ + << MXC_F_I2C_INT_FL0_TX_THRESH_POS) +/* INT_FL0_TX_THRESH_PENDING Value */ +#define MXC_V_I2C_INT_FL0_TX_THRESH_PENDING 0x1UL +/* INT_FL0_TX_THRESH_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_TX_THRESH_PENDING \ + (MXC_V_I2C_INT_FL0_TX_THRESH_PENDING << MXC_F_I2C_INT_FL0_TX_THRESH_POS) + +/* INT_FL0_STOP Position */ +#define MXC_F_I2C_INT_FL0_STOP_POS 6 +/* INT_FL0_STOP Mask */ +#define MXC_F_I2C_INT_FL0_STOP (0x1UL << MXC_F_I2C_INT_FL0_STOP_POS) +/* INT_FL0_STOP_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_STOP_INACTIVE 0x0UL +/* INT_FL0_STOP_INACTIVE Setting */ +#define MXC_S_I2C_INT_FL0_STOP_INACTIVE \ + (MXC_V_I2C_INT_FL0_STOP_INACTIVE << MXC_F_I2C_INT_FL0_STOP_POS) +/* INT_FL0_STOP_PENDING Value */ +#define MXC_V_I2C_INT_FL0_STOP_PENDING 0x1UL +/* INT_FL0_STOP_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_STOP_PENDING \ + (MXC_V_I2C_INT_FL0_STOP_PENDING << MXC_F_I2C_INT_FL0_STOP_POS) + +/* INT_FL0_ADDR_ACK Position */ +#define MXC_F_I2C_INT_FL0_ADDR_ACK_POS 7 +/* INT_FL0_ADDR_ACK Mask */ +#define MXC_F_I2C_INT_FL0_ADDR_ACK (0x1UL << MXC_F_I2C_INT_FL0_ADDR_ACK_POS) +/* INT_FL0_ADDR_ACK_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_ADDR_ACK_INACTIVE 0x0UL +/* INT_FL0_ADDR_ACK_INACTIVE Setting */ +#define MXC_S_I2C_INT_FL0_ADDR_ACK_INACTIVE \ + (MXC_V_I2C_INT_FL0_ADDR_ACK_INACTIVE << MXC_F_I2C_INT_FL0_ADDR_ACK_POS) +/* INT_FL0_ADDR_ACK_PENDING Value */ +#define MXC_V_I2C_INT_FL0_ADDR_ACK_PENDING 0x1UL +/* INT_FL0_ADDR_ACK_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_ADDR_ACK_PENDING \ + (MXC_V_I2C_INT_FL0_ADDR_ACK_PENDING << MXC_F_I2C_INT_FL0_ADDR_ACK_POS) + +/* INT_FL0_ARB_ER Position */ +#define MXC_F_I2C_INT_FL0_ARB_ER_POS 8 +/* INT_FL0_ARB_ER Mask */ +#define MXC_F_I2C_INT_FL0_ARB_ER (0x1UL << MXC_F_I2C_INT_FL0_ARB_ER_POS) +/* INT_FL0_ARB_ER_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_ARB_ER_INACTIVE 0x0UL +/* INT_FL0_ARB_ER_INACTIVE Setting */ +#define MXC_S_I2C_INT_FL0_ARB_ER_INACTIVE \ + (MXC_V_I2C_INT_FL0_ARB_ER_INACTIVE << MXC_F_I2C_INT_FL0_ARB_ER_POS) +/* INT_FL0_ARB_ER_PENDING Value */ +#define MXC_V_I2C_INT_FL0_ARB_ER_PENDING 0x1UL +/* INT_FL0_ARB_ER_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_ARB_ER_PENDING \ + (MXC_V_I2C_INT_FL0_ARB_ER_PENDING << MXC_F_I2C_INT_FL0_ARB_ER_POS) + +/* INT_FL0_TO_ER Position */ +#define MXC_F_I2C_INT_FL0_TO_ER_POS 9 +/* INT_FL0_TO_ER Mask */ +#define MXC_F_I2C_INT_FL0_TO_ER (0x1UL << MXC_F_I2C_INT_FL0_TO_ER_POS) +/* INT_FL0_TO_ER_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_TO_ER_INACTIVE 0x0UL +/* INT_FL0_TO_ER_INACTIVE Setting */ +#define MXC_S_I2C_INT_FL0_TO_ER_INACTIVE \ + (MXC_V_I2C_INT_FL0_TO_ER_INACTIVE << MXC_F_I2C_INT_FL0_TO_ER_POS) +/* INT_FL0_TO_ER_PENDING Value */ +#define MXC_V_I2C_INT_FL0_TO_ER_PENDING 0x1UL +/* INT_FL0_TO_ER_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_TO_ER_PENDING \ + (MXC_V_I2C_INT_FL0_TO_ER_PENDING << MXC_F_I2C_INT_FL0_TO_ER_POS) + +/* INT_FL0_ADDR_NACK_ER Position */ +#define MXC_F_I2C_INT_FL0_ADDR_NACK_ER_POS 10 +/* INT_FL0_ADDR_NACK_ER Mask */ #define MXC_F_I2C_INT_FL0_ADDR_NACK_ER \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_ADDR_NACK_ER_POS)) /**< \ - INT_FL0_ADDR_NACK_ER \ - Mask */ -#define MXC_V_I2C_INT_FL0_ADDR_NACK_ER_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_ADDR_NACK_ER_INACTIVE Value */ + (0x1UL << MXC_F_I2C_INT_FL0_ADDR_NACK_ER_POS) +/* INT_FL0_ADDR_NACK_ER_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_ADDR_NACK_ER_INACTIVE 0x0UL +/* INT_FL0_ADDR_NACK_ER_INACTIVE Setting */ #define MXC_S_I2C_INT_FL0_ADDR_NACK_ER_INACTIVE \ (MXC_V_I2C_INT_FL0_ADDR_NACK_ER_INACTIVE \ - << MXC_F_I2C_INT_FL0_ADDR_NACK_ER_POS) /**< \ - INT_FL0_ADDR_NACK_ER_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_ADDR_NACK_ER_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_ADDR_NACK_ER_PENDING Value */ + << MXC_F_I2C_INT_FL0_ADDR_NACK_ER_POS) +/* INT_FL0_ADDR_NACK_ER_PENDING Value */ +#define MXC_V_I2C_INT_FL0_ADDR_NACK_ER_PENDING 0x1UL +/* INT_FL0_ADDR_NACK_ER_PENDING Setting */ #define MXC_S_I2C_INT_FL0_ADDR_NACK_ER_PENDING \ (MXC_V_I2C_INT_FL0_ADDR_NACK_ER_PENDING \ - << MXC_F_I2C_INT_FL0_ADDR_NACK_ER_POS) /**< \ - INT_FL0_ADDR_NACK_ER_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_DATA_ER_POS 11 /**< INT_FL0_DATA_ER Position */ -#define MXC_F_I2C_INT_FL0_DATA_ER \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_FL0_DATA_ER_POS)) /**< INT_FL0_DATA_ER \ - Mask */ -#define MXC_V_I2C_INT_FL0_DATA_ER_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_DATA_ER_INACTIVE Value */ -#define MXC_S_I2C_INT_FL0_DATA_ER_INACTIVE \ - (MXC_V_I2C_INT_FL0_DATA_ER_INACTIVE \ - << MXC_F_I2C_INT_FL0_DATA_ER_POS) /**< INT_FL0_DATA_ER_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_DATA_ER_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_DATA_ER_PENDING Value */ -#define MXC_S_I2C_INT_FL0_DATA_ER_PENDING \ - (MXC_V_I2C_INT_FL0_DATA_ER_PENDING \ - << MXC_F_I2C_INT_FL0_DATA_ER_POS) /**< INT_FL0_DATA_ER_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER_POS \ - 12 /**< INT_FL0_DO_NOT_RESP_ER Position */ + << MXC_F_I2C_INT_FL0_ADDR_NACK_ER_POS) + +/* INT_FL0_DATA_ER Position */ +#define MXC_F_I2C_INT_FL0_DATA_ER_POS 11 +/* INT_FL0_DATA_ER Mask */ +#define MXC_F_I2C_INT_FL0_DATA_ER (0x1UL << MXC_F_I2C_INT_FL0_DATA_ER_POS) +/* INT_FL0_DATA_ER_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_DATA_ER_INACTIVE 0x0UL +/* INT_FL0_DATA_ER_INACTIVE Setting */ +#define MXC_S_I2C_INT_FL0_DATA_ER_INACTIVE \ + (MXC_V_I2C_INT_FL0_DATA_ER_INACTIVE << MXC_F_I2C_INT_FL0_DATA_ER_POS) +/* INT_FL0_DATA_ER_PENDING Value */ +#define MXC_V_I2C_INT_FL0_DATA_ER_PENDING 0x1UL +/* INT_FL0_DATA_ER_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_DATA_ER_PENDING \ + (MXC_V_I2C_INT_FL0_DATA_ER_PENDING << MXC_F_I2C_INT_FL0_DATA_ER_POS) + +/* INT_FL0_DO_NOT_RESP_ER Position */ +#define MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER_POS 12 +/* INT_FL0_DO_NOT_RESP_ER Mask */ #define MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER_POS)) /**< \ - INT_FL0_DO_NOT_RESP_ER \ - Mask */ -#define MXC_V_I2C_INT_FL0_DO_NOT_RESP_ER_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_DO_NOT_RESP_ER_INACTIVE Value */ + (0x1UL << MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER_POS) +/* INT_FL0_DO_NOT_RESP_ER_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_DO_NOT_RESP_ER_INACTIVE 0x0UL +/* INT_FL0_DO_NOT_RESP_ER_INACTIVE Setting */ #define MXC_S_I2C_INT_FL0_DO_NOT_RESP_ER_INACTIVE \ (MXC_V_I2C_INT_FL0_DO_NOT_RESP_ER_INACTIVE \ - << MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER_POS) /**< \ - INT_FL0_DO_NOT_RESP_ER_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_DO_NOT_RESP_ER_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_DO_NOT_RESP_ER_PENDING Value */ + << MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER_POS) +/* INT_FL0_DO_NOT_RESP_ER_PENDING Value */ +#define MXC_V_I2C_INT_FL0_DO_NOT_RESP_ER_PENDING 0x1UL +/* INT_FL0_DO_NOT_RESP_ER_PENDING Setting */ #define MXC_S_I2C_INT_FL0_DO_NOT_RESP_ER_PENDING \ (MXC_V_I2C_INT_FL0_DO_NOT_RESP_ER_PENDING \ - << MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER_POS) /**< \ - INT_FL0_DO_NOT_RESP_ER_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_START_ER_POS 13 /**< INT_FL0_START_ER Position */ -#define MXC_F_I2C_INT_FL0_START_ER \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_START_ER_POS)) /**< INT_FL0_START_ER \ - Mask */ -#define MXC_V_I2C_INT_FL0_START_ER_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_START_ER_INACTIVE Value */ -#define MXC_S_I2C_INT_FL0_START_ER_INACTIVE \ - (MXC_V_I2C_INT_FL0_START_ER_INACTIVE \ - << MXC_F_I2C_INT_FL0_START_ER_POS) /**< INT_FL0_START_ER_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_START_ER_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_START_ER_PENDING Value */ -#define MXC_S_I2C_INT_FL0_START_ER_PENDING \ - (MXC_V_I2C_INT_FL0_START_ER_PENDING \ - << MXC_F_I2C_INT_FL0_START_ER_POS) /**< INT_FL0_START_ER_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_STOP_ER_POS 14 /**< INT_FL0_STOP_ER Position */ -#define MXC_F_I2C_INT_FL0_STOP_ER \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_FL0_STOP_ER_POS)) /**< INT_FL0_STOP_ER \ - Mask */ -#define MXC_V_I2C_INT_FL0_STOP_ER_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL0_STOP_ER_INACTIVE Value */ -#define MXC_S_I2C_INT_FL0_STOP_ER_INACTIVE \ - (MXC_V_I2C_INT_FL0_STOP_ER_INACTIVE \ - << MXC_F_I2C_INT_FL0_STOP_ER_POS) /**< INT_FL0_STOP_ER_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL0_STOP_ER_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL0_STOP_ER_PENDING Value */ -#define MXC_S_I2C_INT_FL0_STOP_ER_PENDING \ - (MXC_V_I2C_INT_FL0_STOP_ER_PENDING \ - << MXC_F_I2C_INT_FL0_STOP_ER_POS) /**< INT_FL0_STOP_ER_PENDING \ - Setting */ - -#define MXC_F_I2C_INT_FL0_TX_LOCK_OUT_POS \ - 15 /**< INT_FL0_TX_LOCK_OUT Position */ + << MXC_F_I2C_INT_FL0_DO_NOT_RESP_ER_POS) + +/* INT_FL0_START_ER Position */ +#define MXC_F_I2C_INT_FL0_START_ER_POS 13 +/* INT_FL0_START_ER Mask */ +#define MXC_F_I2C_INT_FL0_START_ER (0x1UL << MXC_F_I2C_INT_FL0_START_ER_POS) +/* INT_FL0_START_ER_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_START_ER_INACTIVE 0x0UL +/* INT_FL0_START_ER_INACTIVE Setting */ +#define MXC_S_I2C_INT_FL0_START_ER_INACTIVE \ + (MXC_V_I2C_INT_FL0_START_ER_INACTIVE << MXC_F_I2C_INT_FL0_START_ER_POS) +/* INT_FL0_START_ER_PENDING Value */ +#define MXC_V_I2C_INT_FL0_START_ER_PENDING 0x1UL +/* INT_FL0_START_ER_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_START_ER_PENDING \ + (MXC_V_I2C_INT_FL0_START_ER_PENDING << MXC_F_I2C_INT_FL0_START_ER_POS) + +/* INT_FL0_STOP_ER Position */ +#define MXC_F_I2C_INT_FL0_STOP_ER_POS 14 +/* INT_FL0_STOP_ER Mask */ +#define MXC_F_I2C_INT_FL0_STOP_ER (0x1UL << MXC_F_I2C_INT_FL0_STOP_ER_POS) +/* INT_FL0_STOP_ER_INACTIVE Value */ +#define MXC_V_I2C_INT_FL0_STOP_ER_INACTIVE 0x0UL +/* INT_FL0_STOP_ER_INACTIVE Setting */ +#define MXC_S_I2C_INT_FL0_STOP_ER_INACTIVE \ + (MXC_V_I2C_INT_FL0_STOP_ER_INACTIVE << MXC_F_I2C_INT_FL0_STOP_ER_POS) +/* INT_FL0_STOP_ER_PENDING Value */ +#define MXC_V_I2C_INT_FL0_STOP_ER_PENDING 0x1UL +/* INT_FL0_STOP_ER_PENDING Setting */ +#define MXC_S_I2C_INT_FL0_STOP_ER_PENDING \ + (MXC_V_I2C_INT_FL0_STOP_ER_PENDING << MXC_F_I2C_INT_FL0_STOP_ER_POS) + +/* INT_FL0_TX_LOCK_OUT Position */ +#define MXC_F_I2C_INT_FL0_TX_LOCK_OUT_POS 15 +/* INT_FL0_TX_LOCK_OUT Mask */ #define MXC_F_I2C_INT_FL0_TX_LOCK_OUT \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL0_TX_LOCK_OUT_POS)) /**< \ - INT_FL0_TX_LOCK_OUT \ - Mask */ + (0x1UL << MXC_F_I2C_INT_FL0_TX_LOCK_OUT_POS) -#define MXC_F_I2C_INT_FL0_MAMI_POS 16 /**< INT_FL0_MAMI Position */ +/* INT_FL0_MAMI Position */ +#define MXC_F_I2C_INT_FL0_MAMI_POS 16 /* INT_FL0_MAMI Mask */ -#define MXC_F_I2C_INT_FL0_MAMI_MASK \ - ((uint32_t)(0xFUL << MXC_F_I2C_INT_FL0_MAMI_POS)) +#define MXC_F_I2C_INT_FL0_MAMI_MASK (0xFUL << MXC_F_I2C_INT_FL0_MAMI_POS) /* INT_FL0_MAMI Address Match 0 */ -#define MXC_F_I2C_INT_FL0_MAMI_MATCH_0 \ - ((uint32_t)(0x1UL << MXC_F_I2C_INT_FL0_MAMI_POS)) +#define MXC_F_I2C_INT_FL0_MAMI_MATCH_0 (0x1UL << MXC_F_I2C_INT_FL0_MAMI_POS) /* INT_FL0_MAMI Address Match 1 */ -#define MXC_F_I2C_INT_FL0_MAMI_MATCH_1 \ - ((uint32_t)(0x2UL << MXC_F_I2C_INT_FL0_MAMI_POS)) +#define MXC_F_I2C_INT_FL0_MAMI_MATCH_1 (0x2UL << MXC_F_I2C_INT_FL0_MAMI_POS) /* INT_FL0_MAMI Address Match 2 */ -#define MXC_F_I2C_INT_FL0_MAMI_MATCH_2 \ - ((uint32_t)(0x4UL << MXC_F_I2C_INT_FL0_MAMI_POS)) +#define MXC_F_I2C_INT_FL0_MAMI_MATCH_2 (0x4UL << MXC_F_I2C_INT_FL0_MAMI_POS) /* INT_FL0_MAMI Address Match 3 */ -#define MXC_F_I2C_INT_FL0_MAMI_MATCH_3 \ - ((uint32_t)(0x8UL << MXC_F_I2C_INT_FL0_MAMI_POS)) +#define MXC_F_I2C_INT_FL0_MAMI_MATCH_3 (0x8UL << MXC_F_I2C_INT_FL0_MAMI_POS) /** * Interrupt Enable Register. */ -#define MXC_F_I2C_INT_EN0_DONE_POS 0 /**< INT_EN0_DONE Position */ -#define MXC_F_I2C_INT_EN0_DONE \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_EN0_DONE_POS)) /**< INT_EN0_DONE Mask */ -#define MXC_V_I2C_INT_EN0_DONE_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_DONE_DIS Value */ -#define MXC_S_I2C_INT_EN0_DONE_DIS \ - (MXC_V_I2C_INT_EN0_DONE_DIS \ - << MXC_F_I2C_INT_EN0_DONE_POS) /**< INT_EN0_DONE_DIS Setting */ -#define MXC_V_I2C_INT_EN0_DONE_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_DONE_EN Value */ -#define MXC_S_I2C_INT_EN0_DONE_EN \ - (MXC_V_I2C_INT_EN0_DONE_EN \ - << MXC_F_I2C_INT_EN0_DONE_POS) /**< INT_EN0_DONE_EN Setting */ - -#define MXC_F_I2C_INT_EN0_RX_MODE_POS 1 /**< INT_EN0_RX_MODE Position */ -#define MXC_F_I2C_INT_EN0_RX_MODE \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_EN0_RX_MODE_POS)) /**< INT_EN0_RX_MODE \ - Mask */ -#define MXC_V_I2C_INT_EN0_RX_MODE_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_RX_MODE_DIS Value */ -#define MXC_S_I2C_INT_EN0_RX_MODE_DIS \ - (MXC_V_I2C_INT_EN0_RX_MODE_DIS \ - << MXC_F_I2C_INT_EN0_RX_MODE_POS) /**< INT_EN0_RX_MODE_DIS Setting */ -#define MXC_V_I2C_INT_EN0_RX_MODE_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_RX_MODE_EN Value */ -#define MXC_S_I2C_INT_EN0_RX_MODE_EN \ - (MXC_V_I2C_INT_EN0_RX_MODE_EN \ - << MXC_F_I2C_INT_EN0_RX_MODE_POS) /**< INT_EN0_RX_MODE_EN Setting */ - -#define MXC_F_I2C_INT_EN0_GEN_CTRL_ADDR_POS \ - 2 /**< INT_EN0_GEN_CTRL_ADDR Position */ +#define MXC_F_I2C_INT_EN0_DONE_POS 0 /* INT_EN0_DONE Position */ +/* INT_EN0_DONE Mask */ +#define MXC_F_I2C_INT_EN0_DONE (0x1UL << MXC_F_I2C_INT_EN0_DONE_POS) +/* INT_EN0_DONE_DIS Value */ +#define MXC_V_I2C_INT_EN0_DONE_DIS 0x0UL +/* INT_EN0_DONE_DIS Setting */ +#define MXC_S_I2C_INT_EN0_DONE_DIS \ + (MXC_V_I2C_INT_EN0_DONE_DIS << MXC_F_I2C_INT_EN0_DONE_POS) +/* INT_EN0_DONE_EN Value */ +#define MXC_V_I2C_INT_EN0_DONE_EN 0x1UL +/* INT_EN0_DONE_EN Setting */ +#define MXC_S_I2C_INT_EN0_DONE_EN \ + (MXC_V_I2C_INT_EN0_DONE_EN << MXC_F_I2C_INT_EN0_DONE_POS) + +/* INT_EN0_RX_MODE Position */ +#define MXC_F_I2C_INT_EN0_RX_MODE_POS 1 +/* INT_EN0_RX_MODE Mask */ +#define MXC_F_I2C_INT_EN0_RX_MODE (0x1UL << MXC_F_I2C_INT_EN0_RX_MODE_POS) +/* INT_EN0_RX_MODE_DIS Value */ +#define MXC_V_I2C_INT_EN0_RX_MODE_DIS 0x0UL +/* INT_EN0_RX_MODE_DIS Setting */ +#define MXC_S_I2C_INT_EN0_RX_MODE_DIS \ + (MXC_V_I2C_INT_EN0_RX_MODE_DIS << MXC_F_I2C_INT_EN0_RX_MODE_POS) +/* INT_EN0_RX_MODE_EN Value */ +#define MXC_V_I2C_INT_EN0_RX_MODE_EN 0x1UL +/* INT_EN0_RX_MODE_EN Setting */ +#define MXC_S_I2C_INT_EN0_RX_MODE_EN \ + (MXC_V_I2C_INT_EN0_RX_MODE_EN << MXC_F_I2C_INT_EN0_RX_MODE_POS) + +/* INT_EN0_GEN_CTRL_ADDR Position */ +#define MXC_F_I2C_INT_EN0_GEN_CTRL_ADDR_POS 2 +/* INT_EN0_GEN_CTRL_ADDR Mask */ #define MXC_F_I2C_INT_EN0_GEN_CTRL_ADDR \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_GEN_CTRL_ADDR_POS)) /**< \ - INT_EN0_GEN_CTRL_ADDR \ - Mask */ -#define MXC_V_I2C_INT_EN0_GEN_CTRL_ADDR_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_GEN_CTRL_ADDR_DIS Value */ + (0x1UL << MXC_F_I2C_INT_EN0_GEN_CTRL_ADDR_POS) +/* INT_EN0_GEN_CTRL_ADDR_DIS Value */ +#define MXC_V_I2C_INT_EN0_GEN_CTRL_ADDR_DIS 0x0UL +/* INT_EN0_GEN_CTRL_ADDR_DIS Setting */ #define MXC_S_I2C_INT_EN0_GEN_CTRL_ADDR_DIS \ (MXC_V_I2C_INT_EN0_GEN_CTRL_ADDR_DIS \ - << MXC_F_I2C_INT_EN0_GEN_CTRL_ADDR_POS) /**< \ - INT_EN0_GEN_CTRL_ADDR_DIS \ - Setting */ -#define MXC_V_I2C_INT_EN0_GEN_CTRL_ADDR_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_GEN_CTRL_ADDR_EN Value */ + << MXC_F_I2C_INT_EN0_GEN_CTRL_ADDR_POS) +/* INT_EN0_GEN_CTRL_ADDR_EN Value */ +#define MXC_V_I2C_INT_EN0_GEN_CTRL_ADDR_EN 0x1UL +/* INT_EN0_GEN_CTRL_ADDR_EN Setting */ #define MXC_S_I2C_INT_EN0_GEN_CTRL_ADDR_EN \ (MXC_V_I2C_INT_EN0_GEN_CTRL_ADDR_EN \ - << MXC_F_I2C_INT_EN0_GEN_CTRL_ADDR_POS) /**< INT_EN0_GEN_CTRL_ADDR_EN \ - Setting */ - -#define MXC_F_I2C_INT_EN0_ADDR_MATCH_POS 3 /**< INT_EN0_ADDR_MATCH Position */ -#define MXC_F_I2C_INT_EN0_ADDR_MATCH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_ADDR_MATCH_POS)) /**< INT_EN0_ADDR_MATCH \ - Mask */ -#define MXC_V_I2C_INT_EN0_ADDR_MATCH_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_ADDR_MATCH_DIS Value */ -#define MXC_S_I2C_INT_EN0_ADDR_MATCH_DIS \ - (MXC_V_I2C_INT_EN0_ADDR_MATCH_DIS \ - << MXC_F_I2C_INT_EN0_ADDR_MATCH_POS) /**< INT_EN0_ADDR_MATCH_DIS \ - Setting */ -#define MXC_V_I2C_INT_EN0_ADDR_MATCH_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_ADDR_MATCH_EN Value */ -#define MXC_S_I2C_INT_EN0_ADDR_MATCH_EN \ - (MXC_V_I2C_INT_EN0_ADDR_MATCH_EN \ - << MXC_F_I2C_INT_EN0_ADDR_MATCH_POS) /**< INT_EN0_ADDR_MATCH_EN \ - Setting */ - -#define MXC_F_I2C_INT_EN0_RX_THRESH_POS 4 /**< INT_EN0_RX_THRESH Position */ -#define MXC_F_I2C_INT_EN0_RX_THRESH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_RX_THRESH_POS)) /**< INT_EN0_RX_THRESH \ - Mask */ -#define MXC_V_I2C_INT_EN0_RX_THRESH_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_RX_THRESH_DIS Value */ -#define MXC_S_I2C_INT_EN0_RX_THRESH_DIS \ - (MXC_V_I2C_INT_EN0_RX_THRESH_DIS \ - << MXC_F_I2C_INT_EN0_RX_THRESH_POS) /**< INT_EN0_RX_THRESH_DIS \ - Setting */ -#define MXC_V_I2C_INT_EN0_RX_THRESH_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_RX_THRESH_EN Value */ -#define MXC_S_I2C_INT_EN0_RX_THRESH_EN \ - (MXC_V_I2C_INT_EN0_RX_THRESH_EN \ - << MXC_F_I2C_INT_EN0_RX_THRESH_POS) /**< INT_EN0_RX_THRESH_EN Setting \ - */ - -#define MXC_F_I2C_INT_EN0_TX_THRESH_POS 5 /**< INT_EN0_TX_THRESH Position */ -#define MXC_F_I2C_INT_EN0_TX_THRESH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_TX_THRESH_POS)) /**< INT_EN0_TX_THRESH \ - Mask */ -#define MXC_V_I2C_INT_EN0_TX_THRESH_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_TX_THRESH_DIS Value */ -#define MXC_S_I2C_INT_EN0_TX_THRESH_DIS \ - (MXC_V_I2C_INT_EN0_TX_THRESH_DIS \ - << MXC_F_I2C_INT_EN0_TX_THRESH_POS) /**< INT_EN0_TX_THRESH_DIS \ - Setting */ -#define MXC_V_I2C_INT_EN0_TX_THRESH_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_TX_THRESH_EN Value */ -#define MXC_S_I2C_INT_EN0_TX_THRESH_EN \ - (MXC_V_I2C_INT_EN0_TX_THRESH_EN \ - << MXC_F_I2C_INT_EN0_TX_THRESH_POS) /**< INT_EN0_TX_THRESH_EN Setting \ - */ - -#define MXC_F_I2C_INT_EN0_STOP_POS 6 /**< INT_EN0_STOP Position */ -#define MXC_F_I2C_INT_EN0_STOP \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_EN0_STOP_POS)) /**< INT_EN0_STOP Mask */ -#define MXC_V_I2C_INT_EN0_STOP_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_STOP_DIS Value */ -#define MXC_S_I2C_INT_EN0_STOP_DIS \ - (MXC_V_I2C_INT_EN0_STOP_DIS \ - << MXC_F_I2C_INT_EN0_STOP_POS) /**< INT_EN0_STOP_DIS Setting */ -#define MXC_V_I2C_INT_EN0_STOP_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_STOP_EN Value */ -#define MXC_S_I2C_INT_EN0_STOP_EN \ - (MXC_V_I2C_INT_EN0_STOP_EN \ - << MXC_F_I2C_INT_EN0_STOP_POS) /**< INT_EN0_STOP_EN Setting */ - -#define MXC_F_I2C_INT_EN0_ADDR_ACK_POS 7 /**< INT_EN0_ADDR_ACK Position */ -#define MXC_F_I2C_INT_EN0_ADDR_ACK \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_ADDR_ACK_POS)) /**< INT_EN0_ADDR_ACK \ - Mask */ -#define MXC_V_I2C_INT_EN0_ADDR_ACK_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_ADDR_ACK_DIS Value */ -#define MXC_S_I2C_INT_EN0_ADDR_ACK_DIS \ - (MXC_V_I2C_INT_EN0_ADDR_ACK_DIS \ - << MXC_F_I2C_INT_EN0_ADDR_ACK_POS) /**< INT_EN0_ADDR_ACK_DIS Setting \ - */ -#define MXC_V_I2C_INT_EN0_ADDR_ACK_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_ADDR_ACK_EN Value */ -#define MXC_S_I2C_INT_EN0_ADDR_ACK_EN \ - (MXC_V_I2C_INT_EN0_ADDR_ACK_EN \ - << MXC_F_I2C_INT_EN0_ADDR_ACK_POS) /**< INT_EN0_ADDR_ACK_EN Setting \ - */ - -#define MXC_F_I2C_INT_EN0_ARB_ER_POS 8 /**< INT_EN0_ARB_ER Position */ -#define MXC_F_I2C_INT_EN0_ARB_ER \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_ARB_ER_POS)) /**< INT_EN0_ARB_ER Mask */ -#define MXC_V_I2C_INT_EN0_ARB_ER_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_ARB_ER_DIS Value */ -#define MXC_S_I2C_INT_EN0_ARB_ER_DIS \ - (MXC_V_I2C_INT_EN0_ARB_ER_DIS \ - << MXC_F_I2C_INT_EN0_ARB_ER_POS) /**< INT_EN0_ARB_ER_DIS Setting */ -#define MXC_V_I2C_INT_EN0_ARB_ER_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_ARB_ER_EN Value */ -#define MXC_S_I2C_INT_EN0_ARB_ER_EN \ - (MXC_V_I2C_INT_EN0_ARB_ER_EN \ - << MXC_F_I2C_INT_EN0_ARB_ER_POS) /**< INT_EN0_ARB_ER_EN Setting */ - -#define MXC_F_I2C_INT_EN0_TO_ER_POS 9 /**< INT_EN0_TO_ER Position */ -#define MXC_F_I2C_INT_EN0_TO_ER \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_TO_ER_POS)) /**< INT_EN0_TO_ER Mask */ -#define MXC_V_I2C_INT_EN0_TO_ER_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_TO_ER_DIS Value */ -#define MXC_S_I2C_INT_EN0_TO_ER_DIS \ - (MXC_V_I2C_INT_EN0_TO_ER_DIS \ - << MXC_F_I2C_INT_EN0_TO_ER_POS) /**< INT_EN0_TO_ER_DIS Setting */ -#define MXC_V_I2C_INT_EN0_TO_ER_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_TO_ER_EN Value */ -#define MXC_S_I2C_INT_EN0_TO_ER_EN \ - (MXC_V_I2C_INT_EN0_TO_ER_EN \ - << MXC_F_I2C_INT_EN0_TO_ER_POS) /**< INT_EN0_TO_ER_EN Setting */ - -#define MXC_F_I2C_INT_EN0_ADDR_ER_POS 10 /**< INT_EN0_ADDR_ER Position */ -#define MXC_F_I2C_INT_EN0_ADDR_ER \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_EN0_ADDR_ER_POS)) /**< INT_EN0_ADDR_ER \ - Mask */ -#define MXC_V_I2C_INT_EN0_ADDR_ER_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_ADDR_ER_DIS Value */ -#define MXC_S_I2C_INT_EN0_ADDR_ER_DIS \ - (MXC_V_I2C_INT_EN0_ADDR_ER_DIS \ - << MXC_F_I2C_INT_EN0_ADDR_ER_POS) /**< INT_EN0_ADDR_ER_DIS Setting */ -#define MXC_V_I2C_INT_EN0_ADDR_ER_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_ADDR_ER_EN Value */ -#define MXC_S_I2C_INT_EN0_ADDR_ER_EN \ - (MXC_V_I2C_INT_EN0_ADDR_ER_EN \ - << MXC_F_I2C_INT_EN0_ADDR_ER_POS) /**< INT_EN0_ADDR_ER_EN Setting */ - -#define MXC_F_I2C_INT_EN0_DATA_ER_POS 11 /**< INT_EN0_DATA_ER Position */ -#define MXC_F_I2C_INT_EN0_DATA_ER \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_EN0_DATA_ER_POS)) /**< INT_EN0_DATA_ER \ - Mask */ -#define MXC_V_I2C_INT_EN0_DATA_ER_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_DATA_ER_DIS Value */ -#define MXC_S_I2C_INT_EN0_DATA_ER_DIS \ - (MXC_V_I2C_INT_EN0_DATA_ER_DIS \ - << MXC_F_I2C_INT_EN0_DATA_ER_POS) /**< INT_EN0_DATA_ER_DIS Setting */ -#define MXC_V_I2C_INT_EN0_DATA_ER_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_DATA_ER_EN Value */ -#define MXC_S_I2C_INT_EN0_DATA_ER_EN \ - (MXC_V_I2C_INT_EN0_DATA_ER_EN \ - << MXC_F_I2C_INT_EN0_DATA_ER_POS) /**< INT_EN0_DATA_ER_EN Setting */ - -#define MXC_F_I2C_INT_EN0_DO_NOT_RESP_ER_POS \ - 12 /**< INT_EN0_DO_NOT_RESP_ER Position */ + << MXC_F_I2C_INT_EN0_GEN_CTRL_ADDR_POS) + +/* INT_EN0_ADDR_MATCH Position */ +#define MXC_F_I2C_INT_EN0_ADDR_MATCH_POS 3 +/* INT_EN0_ADDR_MATCH Mask */ +#define MXC_F_I2C_INT_EN0_ADDR_MATCH (0x1UL << MXC_F_I2C_INT_EN0_ADDR_MATCH_POS) +/* INT_EN0_ADDR_MATCH_DIS Value */ +#define MXC_V_I2C_INT_EN0_ADDR_MATCH_DIS 0x0UL +/* INT_EN0_ADDR_MATCH_DIS Setting */ +#define MXC_S_I2C_INT_EN0_ADDR_MATCH_DIS \ + (MXC_V_I2C_INT_EN0_ADDR_MATCH_DIS << MXC_F_I2C_INT_EN0_ADDR_MATCH_POS) +/* INT_EN0_ADDR_MATCH_EN Value */ +#define MXC_V_I2C_INT_EN0_ADDR_MATCH_EN 0x1UL +/* INT_EN0_ADDR_MATCH_EN Setting */ +#define MXC_S_I2C_INT_EN0_ADDR_MATCH_EN \ + (MXC_V_I2C_INT_EN0_ADDR_MATCH_EN << MXC_F_I2C_INT_EN0_ADDR_MATCH_POS) + +/* INT_EN0_RX_THRESH Position */ +#define MXC_F_I2C_INT_EN0_RX_THRESH_POS 4 +/* INT_EN0_RX_THRESH Mask */ +#define MXC_F_I2C_INT_EN0_RX_THRESH (0x1UL << MXC_F_I2C_INT_EN0_RX_THRESH_POS) +/* INT_EN0_RX_THRESH_DIS Value */ +#define MXC_V_I2C_INT_EN0_RX_THRESH_DIS 0x0UL +/* INT_EN0_RX_THRESH_DIS Setting */ +#define MXC_S_I2C_INT_EN0_RX_THRESH_DIS \ + (MXC_V_I2C_INT_EN0_RX_THRESH_DIS << MXC_F_I2C_INT_EN0_RX_THRESH_POS) +/* INT_EN0_RX_THRESH_EN Value */ +#define MXC_V_I2C_INT_EN0_RX_THRESH_EN 0x1UL +/* INT_EN0_RX_THRESH_EN Setting */ +#define MXC_S_I2C_INT_EN0_RX_THRESH_EN \ + (MXC_V_I2C_INT_EN0_RX_THRESH_EN << MXC_F_I2C_INT_EN0_RX_THRESH_POS) + +/* INT_EN0_TX_THRESH Position */ +#define MXC_F_I2C_INT_EN0_TX_THRESH_POS 5 +/* INT_EN0_TX_THRESH Mask */ +#define MXC_F_I2C_INT_EN0_TX_THRESH (0x1UL << MXC_F_I2C_INT_EN0_TX_THRESH_POS) +/* INT_EN0_TX_THRESH_DIS Value */ +#define MXC_V_I2C_INT_EN0_TX_THRESH_DIS 0x0UL +/* INT_EN0_TX_THRESH_DIS Setting */ +#define MXC_S_I2C_INT_EN0_TX_THRESH_DIS \ + (MXC_V_I2C_INT_EN0_TX_THRESH_DIS << MXC_F_I2C_INT_EN0_TX_THRESH_POS) +/* INT_EN0_TX_THRESH_EN Value */ +#define MXC_V_I2C_INT_EN0_TX_THRESH_EN 0x1UL +/* INT_EN0_TX_THRESH_EN Setting */ +#define MXC_S_I2C_INT_EN0_TX_THRESH_EN \ + (MXC_V_I2C_INT_EN0_TX_THRESH_EN << MXC_F_I2C_INT_EN0_TX_THRESH_POS) + +/* INT_EN0_STOP Position */ +#define MXC_F_I2C_INT_EN0_STOP_POS 6 +/* INT_EN0_STOP Mask */ +#define MXC_F_I2C_INT_EN0_STOP (0x1UL << MXC_F_I2C_INT_EN0_STOP_POS) +/* INT_EN0_STOP_DIS Value */ +#define MXC_V_I2C_INT_EN0_STOP_DIS 0x0UL +/* INT_EN0_STOP_DIS Setting */ +#define MXC_S_I2C_INT_EN0_STOP_DIS \ + (MXC_V_I2C_INT_EN0_STOP_DIS << MXC_F_I2C_INT_EN0_STOP_POS) +/* INT_EN0_STOP_EN Value */ +#define MXC_V_I2C_INT_EN0_STOP_EN 0x1UL +/* INT_EN0_STOP_EN Setting */ +#define MXC_S_I2C_INT_EN0_STOP_EN \ + (MXC_V_I2C_INT_EN0_STOP_EN << MXC_F_I2C_INT_EN0_STOP_POS) + +/* INT_EN0_ADDR_ACK Position */ +#define MXC_F_I2C_INT_EN0_ADDR_ACK_POS 7 +/* INT_EN0_ADDR_ACK Mask */ +#define MXC_F_I2C_INT_EN0_ADDR_ACK (0x1UL << MXC_F_I2C_INT_EN0_ADDR_ACK_POS) +/* INT_EN0_ADDR_ACK_DIS Value */ +#define MXC_V_I2C_INT_EN0_ADDR_ACK_DIS 0x0UL +/* INT_EN0_ADDR_ACK_DIS Setting */ +#define MXC_S_I2C_INT_EN0_ADDR_ACK_DIS \ + (MXC_V_I2C_INT_EN0_ADDR_ACK_DIS << MXC_F_I2C_INT_EN0_ADDR_ACK_POS) +/* INT_EN0_ADDR_ACK_EN Value */ +#define MXC_V_I2C_INT_EN0_ADDR_ACK_EN 0x1UL +/* INT_EN0_ADDR_ACK_EN Setting */ +#define MXC_S_I2C_INT_EN0_ADDR_ACK_EN \ + (MXC_V_I2C_INT_EN0_ADDR_ACK_EN << MXC_F_I2C_INT_EN0_ADDR_ACK_POS) + +/* INT_EN0_ARB_ER Position */ +#define MXC_F_I2C_INT_EN0_ARB_ER_POS 8 +/* INT_EN0_ARB_ER Mask */ +#define MXC_F_I2C_INT_EN0_ARB_ER (0x1UL << MXC_F_I2C_INT_EN0_ARB_ER_POS) +/* INT_EN0_ARB_ER_DIS Value */ +#define MXC_V_I2C_INT_EN0_ARB_ER_DIS 0x0UL +/* INT_EN0_ARB_ER_DIS Setting */ +#define MXC_S_I2C_INT_EN0_ARB_ER_DIS \ + (MXC_V_I2C_INT_EN0_ARB_ER_DIS << MXC_F_I2C_INT_EN0_ARB_ER_POS) +/* INT_EN0_ARB_ER_EN Value */ +#define MXC_V_I2C_INT_EN0_ARB_ER_EN 0x1UL +/* INT_EN0_ARB_ER_EN Setting */ +#define MXC_S_I2C_INT_EN0_ARB_ER_EN \ + (MXC_V_I2C_INT_EN0_ARB_ER_EN << MXC_F_I2C_INT_EN0_ARB_ER_POS) + +/* INT_EN0_TO_ER Position */ +#define MXC_F_I2C_INT_EN0_TO_ER_POS 9 +/* INT_EN0_TO_ER Mask */ +#define MXC_F_I2C_INT_EN0_TO_ER (0x1UL << MXC_F_I2C_INT_EN0_TO_ER_POS) +/* INT_EN0_TO_ER_DIS Value */ +#define MXC_V_I2C_INT_EN0_TO_ER_DIS 0x0UL +/* INT_EN0_TO_ER_DIS Setting */ +#define MXC_S_I2C_INT_EN0_TO_ER_DIS \ + (MXC_V_I2C_INT_EN0_TO_ER_DIS << MXC_F_I2C_INT_EN0_TO_ER_POS) +/* INT_EN0_TO_ER_EN Value */ +#define MXC_V_I2C_INT_EN0_TO_ER_EN 0x1UL +/* INT_EN0_TO_ER_EN Setting */ +#define MXC_S_I2C_INT_EN0_TO_ER_EN \ + (MXC_V_I2C_INT_EN0_TO_ER_EN << MXC_F_I2C_INT_EN0_TO_ER_POS) + +/* INT_EN0_ADDR_ER Position */ +#define MXC_F_I2C_INT_EN0_ADDR_ER_POS 10 +/* INT_EN0_ADDR_ER Mask */ +#define MXC_F_I2C_INT_EN0_ADDR_ER (0x1UL << MXC_F_I2C_INT_EN0_ADDR_ER_POS) +/* INT_EN0_ADDR_ER_DIS Value */ +#define MXC_V_I2C_INT_EN0_ADDR_ER_DIS 0x0UL +/* INT_EN0_ADDR_ER_DIS Setting */ +#define MXC_S_I2C_INT_EN0_ADDR_ER_DIS \ + (MXC_V_I2C_INT_EN0_ADDR_ER_DIS << MXC_F_I2C_INT_EN0_ADDR_ER_POS) +/* INT_EN0_ADDR_ER_EN Value */ +#define MXC_V_I2C_INT_EN0_ADDR_ER_EN 0x1UL +/* INT_EN0_ADDR_ER_EN Setting */ +#define MXC_S_I2C_INT_EN0_ADDR_ER_EN \ + (MXC_V_I2C_INT_EN0_ADDR_ER_EN << MXC_F_I2C_INT_EN0_ADDR_ER_POS) + +/* INT_EN0_DATA_ER Position */ +#define MXC_F_I2C_INT_EN0_DATA_ER_POS 11 +/* INT_EN0_DATA_ER Mask */ +#define MXC_F_I2C_INT_EN0_DATA_ER (0x1UL << MXC_F_I2C_INT_EN0_DATA_ER_POS) +/* INT_EN0_DATA_ER_DIS Value */ +#define MXC_V_I2C_INT_EN0_DATA_ER_DIS 0x0UL +/* INT_EN0_DATA_ER_DIS Setting */ +#define MXC_S_I2C_INT_EN0_DATA_ER_DIS \ + (MXC_V_I2C_INT_EN0_DATA_ER_DIS << MXC_F_I2C_INT_EN0_DATA_ER_POS) +/* INT_EN0_DATA_ER_EN Value */ +#define MXC_V_I2C_INT_EN0_DATA_ER_EN 0x1UL +/* INT_EN0_DATA_ER_EN Setting */ +#define MXC_S_I2C_INT_EN0_DATA_ER_EN \ + (MXC_V_I2C_INT_EN0_DATA_ER_EN << MXC_F_I2C_INT_EN0_DATA_ER_POS) + +/* INT_EN0_DO_NOT_RESP_ER Position */ +#define MXC_F_I2C_INT_EN0_DO_NOT_RESP_ER_POS 12 +/* INT_EN0_DO_NOT_RESP_ER Mask */ #define MXC_F_I2C_INT_EN0_DO_NOT_RESP_ER \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_DO_NOT_RESP_ER_POS)) /**< \ - INT_EN0_DO_NOT_RESP_ER \ - Mask */ -#define MXC_V_I2C_INT_EN0_DO_NOT_RESP_ER_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_DO_NOT_RESP_ER_DIS Value */ + (0x1UL << MXC_F_I2C_INT_EN0_DO_NOT_RESP_ER_POS) +/* INT_EN0_DO_NOT_RESP_ER_DIS Value */ +#define MXC_V_I2C_INT_EN0_DO_NOT_RESP_ER_DIS 0x0UL +/* INT_EN0_DO_NOT_RESP_ER_DIS Setting */ #define MXC_S_I2C_INT_EN0_DO_NOT_RESP_ER_DIS \ (MXC_V_I2C_INT_EN0_DO_NOT_RESP_ER_DIS \ - << MXC_F_I2C_INT_EN0_DO_NOT_RESP_ER_POS) /**< \ - INT_EN0_DO_NOT_RESP_ER_DIS \ - Setting */ -#define MXC_V_I2C_INT_EN0_DO_NOT_RESP_ER_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_DO_NOT_RESP_ER_EN Value */ + << MXC_F_I2C_INT_EN0_DO_NOT_RESP_ER_POS) +/* INT_EN0_DO_NOT_RESP_ER_EN Value */ +#define MXC_V_I2C_INT_EN0_DO_NOT_RESP_ER_EN 0x1UL +/* INT_EN0_DO_NOT_RESP_ER_EN Setting */ #define MXC_S_I2C_INT_EN0_DO_NOT_RESP_ER_EN \ (MXC_V_I2C_INT_EN0_DO_NOT_RESP_ER_EN \ - << MXC_F_I2C_INT_EN0_DO_NOT_RESP_ER_POS) /**< \ - INT_EN0_DO_NOT_RESP_ER_EN \ - Setting */ - -#define MXC_F_I2C_INT_EN0_START_ER_POS 13 /**< INT_EN0_START_ER Position */ -#define MXC_F_I2C_INT_EN0_START_ER \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_START_ER_POS)) /**< INT_EN0_START_ER \ - Mask */ -#define MXC_V_I2C_INT_EN0_START_ER_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_START_ER_DIS Value */ -#define MXC_S_I2C_INT_EN0_START_ER_DIS \ - (MXC_V_I2C_INT_EN0_START_ER_DIS \ - << MXC_F_I2C_INT_EN0_START_ER_POS) /**< INT_EN0_START_ER_DIS Setting \ - */ -#define MXC_V_I2C_INT_EN0_START_ER_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_START_ER_EN Value */ -#define MXC_S_I2C_INT_EN0_START_ER_EN \ - (MXC_V_I2C_INT_EN0_START_ER_EN \ - << MXC_F_I2C_INT_EN0_START_ER_POS) /**< INT_EN0_START_ER_EN Setting \ - */ - -#define MXC_F_I2C_INT_EN0_STOP_ER_POS 14 /**< INT_EN0_STOP_ER Position */ -#define MXC_F_I2C_INT_EN0_STOP_ER \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_INT_EN0_STOP_ER_POS)) /**< INT_EN0_STOP_ER \ - Mask */ -#define MXC_V_I2C_INT_EN0_STOP_ER_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_STOP_ER_DIS Value */ -#define MXC_S_I2C_INT_EN0_STOP_ER_DIS \ - (MXC_V_I2C_INT_EN0_STOP_ER_DIS \ - << MXC_F_I2C_INT_EN0_STOP_ER_POS) /**< INT_EN0_STOP_ER_DIS Setting */ -#define MXC_V_I2C_INT_EN0_STOP_ER_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_STOP_ER_EN Value */ -#define MXC_S_I2C_INT_EN0_STOP_ER_EN \ - (MXC_V_I2C_INT_EN0_STOP_ER_EN \ - << MXC_F_I2C_INT_EN0_STOP_ER_POS) /**< INT_EN0_STOP_ER_EN Setting */ - -#define MXC_F_I2C_INT_EN0_TX_LOCK_OUT_POS \ - 15 /**< INT_EN0_TX_LOCK_OUT Position */ + << MXC_F_I2C_INT_EN0_DO_NOT_RESP_ER_POS) + +/* INT_EN0_START_ER Position */ +#define MXC_F_I2C_INT_EN0_START_ER_POS 13 +/* INT_EN0_START_ER Mask */ +#define MXC_F_I2C_INT_EN0_START_ER (0x1UL << MXC_F_I2C_INT_EN0_START_ER_POS) +/* INT_EN0_START_ER_DIS Value */ +#define MXC_V_I2C_INT_EN0_START_ER_DIS 0x0UL +/* INT_EN0_START_ER_DIS Setting */ +#define MXC_S_I2C_INT_EN0_START_ER_DIS \ + (MXC_V_I2C_INT_EN0_START_ER_DIS << MXC_F_I2C_INT_EN0_START_ER_POS) +/* INT_EN0_START_ER_EN Value */ +#define MXC_V_I2C_INT_EN0_START_ER_EN 0x1UL +/* INT_EN0_START_ER_EN Setting */ +#define MXC_S_I2C_INT_EN0_START_ER_EN \ + (MXC_V_I2C_INT_EN0_START_ER_EN << MXC_F_I2C_INT_EN0_START_ER_POS) + +/* INT_EN0_STOP_ER Position */ +#define MXC_F_I2C_INT_EN0_STOP_ER_POS 14 +/* INT_EN0_STOP_ER Mask */ +#define MXC_F_I2C_INT_EN0_STOP_ER (0x1UL << MXC_F_I2C_INT_EN0_STOP_ER_POS) +/* INT_EN0_STOP_ER_DIS Value */ +#define MXC_V_I2C_INT_EN0_STOP_ER_DIS 0x0UL +/* INT_EN0_STOP_ER_DIS Setting */ +#define MXC_S_I2C_INT_EN0_STOP_ER_DIS \ + (MXC_V_I2C_INT_EN0_STOP_ER_DIS << MXC_F_I2C_INT_EN0_STOP_ER_POS) +/* INT_EN0_STOP_ER_EN Value */ +#define MXC_V_I2C_INT_EN0_STOP_ER_EN 0x1UL +/* INT_EN0_STOP_ER_EN Setting */ +#define MXC_S_I2C_INT_EN0_STOP_ER_EN \ + (MXC_V_I2C_INT_EN0_STOP_ER_EN << MXC_F_I2C_INT_EN0_STOP_ER_POS) + +/* INT_EN0_TX_LOCK_OUT Position */ +#define MXC_F_I2C_INT_EN0_TX_LOCK_OUT_POS 15 +/* INT_EN0_TX_LOCK_OUT Mask */ #define MXC_F_I2C_INT_EN0_TX_LOCK_OUT \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN0_TX_LOCK_OUT_POS)) /**< \ - INT_EN0_TX_LOCK_OUT \ - Mask */ -#define MXC_V_I2C_INT_EN0_TX_LOCK_OUT_DIS \ - ((uint32_t)0x0UL) /**< INT_EN0_TX_LOCK_OUT_DIS Value */ -#define MXC_S_I2C_INT_EN0_TX_LOCK_OUT_DIS \ - (MXC_V_I2C_INT_EN0_TX_LOCK_OUT_DIS \ - << MXC_F_I2C_INT_EN0_TX_LOCK_OUT_POS) /**< INT_EN0_TX_LOCK_OUT_DIS \ - Setting */ -#define MXC_V_I2C_INT_EN0_TX_LOCK_OUT_EN \ - ((uint32_t)0x1UL) /**< INT_EN0_TX_LOCK_OUT_EN Value */ -#define MXC_S_I2C_INT_EN0_TX_LOCK_OUT_EN \ - (MXC_V_I2C_INT_EN0_TX_LOCK_OUT_EN \ - << MXC_F_I2C_INT_EN0_TX_LOCK_OUT_POS) /**< INT_EN0_TX_LOCK_OUT_EN \ - Setting */ + (0x1UL << MXC_F_I2C_INT_EN0_TX_LOCK_OUT_POS) +/* INT_EN0_TX_LOCK_OUT_DIS Value */ +#define MXC_V_I2C_INT_EN0_TX_LOCK_OUT_DIS 0x0UL +/* INT_EN0_TX_LOCK_OUT_DIS Setting */ +#define MXC_S_I2C_INT_EN0_TX_LOCK_OUT_DIS \ + (MXC_V_I2C_INT_EN0_TX_LOCK_OUT_DIS << MXC_F_I2C_INT_EN0_TX_LOCK_OUT_POS) +/* INT_EN0_TX_LOCK_OUT_EN Value */ +#define MXC_V_I2C_INT_EN0_TX_LOCK_OUT_EN 0x1UL +/* INT_EN0_TX_LOCK_OUT_EN Setting */ +#define MXC_S_I2C_INT_EN0_TX_LOCK_OUT_EN \ + (MXC_V_I2C_INT_EN0_TX_LOCK_OUT_EN << MXC_F_I2C_INT_EN0_TX_LOCK_OUT_POS) /** * Interrupt Status Register 1. */ -#define MXC_F_I2C_INT_FL1_RX_OVERFLOW_POS \ - 0 /**< INT_FL1_RX_OVERFLOW Position \ - */ +/* INT_FL1_RX_OVERFLOW Position */ +#define MXC_F_I2C_INT_FL1_RX_OVERFLOW_POS 0 +/* INT_FL1_RX_OVERFLOW Mask */ #define MXC_F_I2C_INT_FL1_RX_OVERFLOW \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL1_RX_OVERFLOW_POS)) /**< \ - INT_FL1_RX_OVERFLOW \ - Mask */ -#define MXC_V_I2C_INT_FL1_RX_OVERFLOW_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL1_RX_OVERFLOW_INACTIVE Value */ + (0x1UL << MXC_F_I2C_INT_FL1_RX_OVERFLOW_POS) +/* INT_FL1_RX_OVERFLOW_INACTIVE Value */ +#define MXC_V_I2C_INT_FL1_RX_OVERFLOW_INACTIVE 0x0UL +/* INT_FL1_RX_OVERFLOW_INACTIVE Setting */ #define MXC_S_I2C_INT_FL1_RX_OVERFLOW_INACTIVE \ (MXC_V_I2C_INT_FL1_RX_OVERFLOW_INACTIVE \ - << MXC_F_I2C_INT_FL1_RX_OVERFLOW_POS) /**< \ - INT_FL1_RX_OVERFLOW_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL1_RX_OVERFLOW_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL1_RX_OVERFLOW_PENDING Value */ + << MXC_F_I2C_INT_FL1_RX_OVERFLOW_POS) +/* INT_FL1_RX_OVERFLOW_PENDING Value */ +#define MXC_V_I2C_INT_FL1_RX_OVERFLOW_PENDING 0x1UL +/* INT_FL1_RX_OVERFLOW_PENDING Setting */ #define MXC_S_I2C_INT_FL1_RX_OVERFLOW_PENDING \ (MXC_V_I2C_INT_FL1_RX_OVERFLOW_PENDING \ - << MXC_F_I2C_INT_FL1_RX_OVERFLOW_POS) /**< \ - INT_FL1_RX_OVERFLOW_PENDING \ - Setting */ + << MXC_F_I2C_INT_FL1_RX_OVERFLOW_POS) -#define MXC_F_I2C_INT_FL1_TX_UNDERFLOW_POS \ - 1 /**< INT_FL1_TX_UNDERFLOW Position */ +/* INT_FL1_TX_UNDERFLOW Position */ +#define MXC_F_I2C_INT_FL1_TX_UNDERFLOW_POS 1 +/* INT_FL1_TX_UNDERFLOW Mask */ #define MXC_F_I2C_INT_FL1_TX_UNDERFLOW \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_FL1_TX_UNDERFLOW_POS)) /**< \ - INT_FL1_TX_UNDERFLOW \ - Mask */ -#define MXC_V_I2C_INT_FL1_TX_UNDERFLOW_INACTIVE \ - ((uint32_t)0x0UL) /**< INT_FL1_TX_UNDERFLOW_INACTIVE Value */ + (0x1UL << MXC_F_I2C_INT_FL1_TX_UNDERFLOW_POS) +/* INT_FL1_TX_UNDERFLOW_INACTIVE Value */ +#define MXC_V_I2C_INT_FL1_TX_UNDERFLOW_INACTIVE 0x0UL +/* INT_FL1_TX_UNDERFLOW_INACTIVE Setting */ #define MXC_S_I2C_INT_FL1_TX_UNDERFLOW_INACTIVE \ (MXC_V_I2C_INT_FL1_TX_UNDERFLOW_INACTIVE \ - << MXC_F_I2C_INT_FL1_TX_UNDERFLOW_POS) /**< \ - INT_FL1_TX_UNDERFLOW_INACTIVE \ - Setting */ -#define MXC_V_I2C_INT_FL1_TX_UNDERFLOW_PENDING \ - ((uint32_t)0x1UL) /**< INT_FL1_TX_UNDERFLOW_PENDING Value */ + << MXC_F_I2C_INT_FL1_TX_UNDERFLOW_POS) +/* INT_FL1_TX_UNDERFLOW_PENDING Value */ +#define MXC_V_I2C_INT_FL1_TX_UNDERFLOW_PENDING 0x1UL +/* INT_FL1_TX_UNDERFLOW_PENDING Setting */ #define MXC_S_I2C_INT_FL1_TX_UNDERFLOW_PENDING \ (MXC_V_I2C_INT_FL1_TX_UNDERFLOW_PENDING \ - << MXC_F_I2C_INT_FL1_TX_UNDERFLOW_POS) /**< \ - INT_FL1_TX_UNDERFLOW_PENDING \ - Setting */ + << MXC_F_I2C_INT_FL1_TX_UNDERFLOW_POS) /** * Interrupt Staus Register 1. */ -#define MXC_F_I2C_INT_EN1_RX_OVERFLOW_POS \ - 0 /**< INT_EN1_RX_OVERFLOW Position \ - */ +/* INT_EN1_RX_OVERFLOW Position */ +#define MXC_F_I2C_INT_EN1_RX_OVERFLOW_POS 0 +/* INT_EN1_RX_OVERFLOW Mask */ #define MXC_F_I2C_INT_EN1_RX_OVERFLOW \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN1_RX_OVERFLOW_POS)) /**< \ - INT_EN1_RX_OVERFLOW \ - Mask */ -#define MXC_V_I2C_INT_EN1_RX_OVERFLOW_DIS \ - ((uint32_t)0x0UL) /**< INT_EN1_RX_OVERFLOW_DIS Value */ -#define MXC_S_I2C_INT_EN1_RX_OVERFLOW_DIS \ - (MXC_V_I2C_INT_EN1_RX_OVERFLOW_DIS \ - << MXC_F_I2C_INT_EN1_RX_OVERFLOW_POS) /**< INT_EN1_RX_OVERFLOW_DIS \ - Setting */ -#define MXC_V_I2C_INT_EN1_RX_OVERFLOW_EN \ - ((uint32_t)0x1UL) /**< INT_EN1_RX_OVERFLOW_EN Value */ -#define MXC_S_I2C_INT_EN1_RX_OVERFLOW_EN \ - (MXC_V_I2C_INT_EN1_RX_OVERFLOW_EN \ - << MXC_F_I2C_INT_EN1_RX_OVERFLOW_POS) /**< INT_EN1_RX_OVERFLOW_EN \ - Setting */ - -#define MXC_F_I2C_INT_EN1_TX_UNDERFLOW_POS \ - 1 /**< INT_EN1_TX_UNDERFLOW Position */ + (0x1UL << MXC_F_I2C_INT_EN1_RX_OVERFLOW_POS) +/* INT_EN1_RX_OVERFLOW_DIS Value */ +#define MXC_V_I2C_INT_EN1_RX_OVERFLOW_DIS 0x0UL +/* INT_EN1_RX_OVERFLOW_DIS Setting */ +#define MXC_S_I2C_INT_EN1_RX_OVERFLOW_DIS \ + (MXC_V_I2C_INT_EN1_RX_OVERFLOW_DIS << MXC_F_I2C_INT_EN1_RX_OVERFLOW_POS) +/* INT_EN1_RX_OVERFLOW_EN Value */ +#define MXC_V_I2C_INT_EN1_RX_OVERFLOW_EN 0x1UL +/* INT_EN1_RX_OVERFLOW_EN Setting */ +#define MXC_S_I2C_INT_EN1_RX_OVERFLOW_EN \ + (MXC_V_I2C_INT_EN1_RX_OVERFLOW_EN << MXC_F_I2C_INT_EN1_RX_OVERFLOW_POS) + +/* INT_EN1_TX_UNDERFLOW Position */ +#define MXC_F_I2C_INT_EN1_TX_UNDERFLOW_POS 1 +/* INT_EN1_TX_UNDERFLOW Mask */ #define MXC_F_I2C_INT_EN1_TX_UNDERFLOW \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_INT_EN1_TX_UNDERFLOW_POS)) /**< \ - INT_EN1_TX_UNDERFLOW \ - Mask */ -#define MXC_V_I2C_INT_EN1_TX_UNDERFLOW_DIS \ - ((uint32_t)0x0UL) /**< INT_EN1_TX_UNDERFLOW_DIS Value */ + (0x1UL << MXC_F_I2C_INT_EN1_TX_UNDERFLOW_POS) +/* INT_EN1_TX_UNDERFLOW_DIS Value */ +#define MXC_V_I2C_INT_EN1_TX_UNDERFLOW_DIS 0x0UL +/* INT_EN1_TX_UNDERFLOW_DIS Setting */ #define MXC_S_I2C_INT_EN1_TX_UNDERFLOW_DIS \ (MXC_V_I2C_INT_EN1_TX_UNDERFLOW_DIS \ - << MXC_F_I2C_INT_EN1_TX_UNDERFLOW_POS) /**< INT_EN1_TX_UNDERFLOW_DIS \ - Setting */ -#define MXC_V_I2C_INT_EN1_TX_UNDERFLOW_EN \ - ((uint32_t)0x1UL) /**< INT_EN1_TX_UNDERFLOW_EN Value */ + << MXC_F_I2C_INT_EN1_TX_UNDERFLOW_POS) +/* INT_EN1_TX_UNDERFLOW_EN Value */ +#define MXC_V_I2C_INT_EN1_TX_UNDERFLOW_EN 0x1UL +/* INT_EN1_TX_UNDERFLOW_EN Setting */ #define MXC_S_I2C_INT_EN1_TX_UNDERFLOW_EN \ (MXC_V_I2C_INT_EN1_TX_UNDERFLOW_EN \ - << MXC_F_I2C_INT_EN1_TX_UNDERFLOW_POS) /**< INT_EN1_TX_UNDERFLOW_EN \ - Setting */ + << MXC_F_I2C_INT_EN1_TX_UNDERFLOW_POS) /** * FIFO Configuration Register. */ -#define MXC_F_I2C_FIFO_LEN_RX_LEN_POS 0 /**< FIFO_LEN_RX_LEN Position */ -#define MXC_F_I2C_FIFO_LEN_RX_LEN \ - ((uint32_t)(0xFFUL \ - << MXC_F_I2C_FIFO_LEN_RX_LEN_POS)) /**< FIFO_LEN_RX_LEN \ - Mask */ - -#define MXC_F_I2C_FIFO_LEN_TX_LEN_POS 8 /**< FIFO_LEN_TX_LEN Position */ -#define MXC_F_I2C_FIFO_LEN_TX_LEN \ - ((uint32_t)(0xFFUL \ - << MXC_F_I2C_FIFO_LEN_TX_LEN_POS)) /**< FIFO_LEN_TX_LEN \ - Mask */ +/* FIFO_LEN_RX_LEN Position */ +#define MXC_F_I2C_FIFO_LEN_RX_LEN_POS 0 +/* FIFO_LEN_RX_LEN Mask */ +#define MXC_F_I2C_FIFO_LEN_RX_LEN (0xFFUL << MXC_F_I2C_FIFO_LEN_RX_LEN_POS) + +/* FIFO_LEN_TX_LEN Position */ +#define MXC_F_I2C_FIFO_LEN_TX_LEN_POS 8 +/* FIFO_LEN_TX_LEN Mask */ +#define MXC_F_I2C_FIFO_LEN_TX_LEN (0xFFUL << MXC_F_I2C_FIFO_LEN_TX_LEN_POS) /** * Receive Control Register 0. */ -#define MXC_F_I2C_RX_CTRL0_DNR_POS 0 /**< RX_CTRL0_DNR Position */ -#define MXC_F_I2C_RX_CTRL0_DNR \ - ((uint32_t)(0x1UL \ - << MXC_F_I2C_RX_CTRL0_DNR_POS)) /**< RX_CTRL0_DNR Mask */ -#define MXC_V_I2C_RX_CTRL0_DNR_RESPOND \ - ((uint32_t)0x0UL) /**< RX_CTRL0_DNR_RESPOND Value */ -#define MXC_S_I2C_RX_CTRL0_DNR_RESPOND \ - (MXC_V_I2C_RX_CTRL0_DNR_RESPOND \ - << MXC_F_I2C_RX_CTRL0_DNR_POS) /**< RX_CTRL0_DNR_RESPOND Setting */ -#define MXC_V_I2C_RX_CTRL0_DNR_NOT_RESPOND_RX_FIFO_EMPTY \ - ((uint32_t)0x1UL) /**< RX_CTRL0_DNR_NOT_RESPOND_RX_FIFO_EMPTY Value */ +/* RX_CTRL0_DNR Position */ +#define MXC_F_I2C_RX_CTRL0_DNR_POS 0 +/* RX_CTRL0_DNR Mask */ +#define MXC_F_I2C_RX_CTRL0_DNR (0x1UL << MXC_F_I2C_RX_CTRL0_DNR_POS) +/* RX_CTRL0_DNR_RESPOND Value */ +#define MXC_V_I2C_RX_CTRL0_DNR_RESPOND 0x0UL +/* RX_CTRL0_DNR_RESPOND Setting */ +#define MXC_S_I2C_RX_CTRL0_DNR_RESPOND \ + (MXC_V_I2C_RX_CTRL0_DNR_RESPOND << MXC_F_I2C_RX_CTRL0_DNR_POS) +/* RX_CTRL0_DNR_NOT_RESPOND_RX_FIFO_EMPTY Value */ +#define MXC_V_I2C_RX_CTRL0_DNR_NOT_RESPOND_RX_FIFO_EMPTY 0x1UL +/* RX_CTRL0_DNR_NOT_RESPOND_RX_FIFO_EMPTY Setting */ #define MXC_S_I2C_RX_CTRL0_DNR_NOT_RESPOND_RX_FIFO_EMPTY \ (MXC_V_I2C_RX_CTRL0_DNR_NOT_RESPOND_RX_FIFO_EMPTY \ - << MXC_F_I2C_RX_CTRL0_DNR_POS) /**< \ - RX_CTRL0_DNR_NOT_RESPOND_RX_FIFO_EMPTY \ - Setting */ - -#define MXC_F_I2C_RX_CTRL0_RX_FLUSH_POS 7 /**< RX_CTRL0_RX_FLUSH Position */ -#define MXC_F_I2C_RX_CTRL0_RX_FLUSH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_RX_CTRL0_RX_FLUSH_POS)) /**< RX_CTRL0_RX_FLUSH \ - Mask */ -#define MXC_V_I2C_RX_CTRL0_RX_FLUSH_NOT_FLUSHED \ - ((uint32_t)0x0UL) /**< RX_CTRL0_RX_FLUSH_NOT_FLUSHED Value */ + << MXC_F_I2C_RX_CTRL0_DNR_POS) + +/* RX_CTRL0_RX_FLUSH Position */ +#define MXC_F_I2C_RX_CTRL0_RX_FLUSH_POS 7 +/* RX_CTRL0_RX_FLUSH Mask */ +#define MXC_F_I2C_RX_CTRL0_RX_FLUSH (0x1UL << MXC_F_I2C_RX_CTRL0_RX_FLUSH_POS) +/* RX_CTRL0_RX_FLUSH_NOT_FLUSHED Value */ +#define MXC_V_I2C_RX_CTRL0_RX_FLUSH_NOT_FLUSHED 0x0UL +/* RX_CTRL0_RX_FLUSH_NOT_FLUSHED Setting */ #define MXC_S_I2C_RX_CTRL0_RX_FLUSH_NOT_FLUSHED \ (MXC_V_I2C_RX_CTRL0_RX_FLUSH_NOT_FLUSHED \ - << MXC_F_I2C_RX_CTRL0_RX_FLUSH_POS) /**< \ - RX_CTRL0_RX_FLUSH_NOT_FLUSHED \ - Setting */ -#define MXC_V_I2C_RX_CTRL0_RX_FLUSH_FLUSH \ - ((uint32_t)0x1UL) /**< RX_CTRL0_RX_FLUSH_FLUSH Value */ -#define MXC_S_I2C_RX_CTRL0_RX_FLUSH_FLUSH \ - (MXC_V_I2C_RX_CTRL0_RX_FLUSH_FLUSH \ - << MXC_F_I2C_RX_CTRL0_RX_FLUSH_POS) /**< RX_CTRL0_RX_FLUSH_FLUSH \ - Setting */ - -#define MXC_F_I2C_RX_CTRL0_RX_THRESH_POS 8 /**< RX_CTRL0_RX_THRESH Position */ -#define MXC_F_I2C_RX_CTRL0_RX_THRESH \ - ((uint32_t)( \ - 0xFUL \ - << MXC_F_I2C_RX_CTRL0_RX_THRESH_POS)) /**< RX_CTRL0_RX_THRESH \ - Mask */ + << MXC_F_I2C_RX_CTRL0_RX_FLUSH_POS) +/* RX_CTRL0_RX_FLUSH_FLUSH Value */ +#define MXC_V_I2C_RX_CTRL0_RX_FLUSH_FLUSH 0x1UL +/* RX_CTRL0_RX_FLUSH_FLUSH Setting */ +#define MXC_S_I2C_RX_CTRL0_RX_FLUSH_FLUSH \ + (MXC_V_I2C_RX_CTRL0_RX_FLUSH_FLUSH << MXC_F_I2C_RX_CTRL0_RX_FLUSH_POS) + +/* RX_CTRL0_RX_THRESH Position */ +#define MXC_F_I2C_RX_CTRL0_RX_THRESH_POS 8 +/* RX_CTRL0_RX_THRESH Mask */ +#define MXC_F_I2C_RX_CTRL0_RX_THRESH (0xFUL << MXC_F_I2C_RX_CTRL0_RX_THRESH_POS) /** * Receive Control Register 1. */ -#define MXC_F_I2C_RX_CTRL1_RX_CNT_POS 0 /**< RX_CTRL1_RX_CNT Position */ -#define MXC_F_I2C_RX_CTRL1_RX_CNT \ - ((uint32_t)(0xFFUL \ - << MXC_F_I2C_RX_CTRL1_RX_CNT_POS)) /**< RX_CTRL1_RX_CNT \ - Mask */ - -#define MXC_F_I2C_RX_CTRL1_RX_FIFO_POS 8 /**< RX_CTRL1_RX_FIFO Position */ -#define MXC_F_I2C_RX_CTRL1_RX_FIFO \ - ((uint32_t)( \ - 0xFUL \ - << MXC_F_I2C_RX_CTRL1_RX_FIFO_POS)) /**< RX_CTRL1_RX_FIFO \ - Mask */ +/* RX_CTRL1_RX_CNT Position */ +#define MXC_F_I2C_RX_CTRL1_RX_CNT_POS 0 +/* RX_CTRL1_RX_CNT Mask */ +#define MXC_F_I2C_RX_CTRL1_RX_CNT (0xFFUL << MXC_F_I2C_RX_CTRL1_RX_CNT_POS) + +/* RX_CTRL1_RX_FIFO Position */ +#define MXC_F_I2C_RX_CTRL1_RX_FIFO_POS 8 +/* RX_CTRL1_RX_FIFO Mask */ +#define MXC_F_I2C_RX_CTRL1_RX_FIFO (0xFUL << MXC_F_I2C_RX_CTRL1_RX_FIFO_POS) /** * Transmit Control Register 0. */ -#define MXC_F_I2C_TX_CTRL0_TX_PRELOAD_POS \ - 0 /**< TX_CTRL0_TX_PRELOAD Position \ - */ +/* TX_CTRL0_TX_PRELOAD Position */ +#define MXC_F_I2C_TX_CTRL0_TX_PRELOAD_POS 0 +/* TX_CTRL0_TX_PRELOAD Mask */ #define MXC_F_I2C_TX_CTRL0_TX_PRELOAD \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_TX_CTRL0_TX_PRELOAD_POS)) /**< \ - TX_CTRL0_TX_PRELOAD \ - Mask */ - -#define MXC_F_I2C_TX_CTRL0_TX_READY_MODE_POS \ - 1 /**< TX_CTRL0_TX_READY_MODE Position */ + (0x1UL << MXC_F_I2C_TX_CTRL0_TX_PRELOAD_POS) + +/* TX_CTRL0_TX_READY_MODE Position */ +#define MXC_F_I2C_TX_CTRL0_TX_READY_MODE_POS 1 +/* TX_CTRL0_TX_READY_MODE Mask */ #define MXC_F_I2C_TX_CTRL0_TX_READY_MODE \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_TX_CTRL0_TX_READY_MODE_POS)) /**< \ - TX_CTRL0_TX_READY_MODE \ - Mask */ -#define MXC_V_I2C_TX_CTRL0_TX_READY_MODE_EN \ - ((uint32_t)0x0UL) /**< TX_CTRL0_TX_READY_MODE_EN Value */ + (0x1UL << MXC_F_I2C_TX_CTRL0_TX_READY_MODE_POS) +/* TX_CTRL0_TX_READY_MODE_EN Value */ +#define MXC_V_I2C_TX_CTRL0_TX_READY_MODE_EN 0x0UL +/* TX_CTRL0_TX_READY_MODE_EN Setting */ #define MXC_S_I2C_TX_CTRL0_TX_READY_MODE_EN \ (MXC_V_I2C_TX_CTRL0_TX_READY_MODE_EN \ - << MXC_F_I2C_TX_CTRL0_TX_READY_MODE_POS) /**< \ - TX_CTRL0_TX_READY_MODE_EN \ - Setting */ -#define MXC_V_I2C_TX_CTRL0_TX_READY_MODE_DIS \ - ((uint32_t)0x1UL) /**< TX_CTRL0_TX_READY_MODE_DIS Value */ + << MXC_F_I2C_TX_CTRL0_TX_READY_MODE_POS) +/* TX_CTRL0_TX_READY_MODE_DIS Value */ +#define MXC_V_I2C_TX_CTRL0_TX_READY_MODE_DIS 0x1UL +/* TX_CTRL0_TX_READY_MODE_DIS Setting */ #define MXC_S_I2C_TX_CTRL0_TX_READY_MODE_DIS \ (MXC_V_I2C_TX_CTRL0_TX_READY_MODE_DIS \ - << MXC_F_I2C_TX_CTRL0_TX_READY_MODE_POS) /**< \ - TX_CTRL0_TX_READY_MODE_DIS \ - Setting */ - -#define MXC_F_I2C_TX_CTRL0_TX_FLUSH_POS 7 /**< TX_CTRL0_TX_FLUSH Position */ -#define MXC_F_I2C_TX_CTRL0_TX_FLUSH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_TX_CTRL0_TX_FLUSH_POS)) /**< TX_CTRL0_TX_FLUSH \ - Mask */ -#define MXC_V_I2C_TX_CTRL0_TX_FLUSH_NOT_FLUSHED \ - ((uint32_t)0x0UL) /**< TX_CTRL0_TX_FLUSH_NOT_FLUSHED Value */ + << MXC_F_I2C_TX_CTRL0_TX_READY_MODE_POS) + +/* TX_CTRL0_TX_FLUSH Position */ +#define MXC_F_I2C_TX_CTRL0_TX_FLUSH_POS 7 +/* TX_CTRL0_TX_FLUSH Mask */ +#define MXC_F_I2C_TX_CTRL0_TX_FLUSH (0x1UL << MXC_F_I2C_TX_CTRL0_TX_FLUSH_POS) +/* TX_CTRL0_TX_FLUSH_NOT_FLUSHED Value */ +#define MXC_V_I2C_TX_CTRL0_TX_FLUSH_NOT_FLUSHED 0x0UL +/* TX_CTRL0_TX_FLUSH_NOT_FLUSHED Setting */ #define MXC_S_I2C_TX_CTRL0_TX_FLUSH_NOT_FLUSHED \ (MXC_V_I2C_TX_CTRL0_TX_FLUSH_NOT_FLUSHED \ - << MXC_F_I2C_TX_CTRL0_TX_FLUSH_POS) /**< \ - TX_CTRL0_TX_FLUSH_NOT_FLUSHED \ - Setting */ -#define MXC_V_I2C_TX_CTRL0_TX_FLUSH_FLUSH \ - ((uint32_t)0x1UL) /**< TX_CTRL0_TX_FLUSH_FLUSH Value */ -#define MXC_S_I2C_TX_CTRL0_TX_FLUSH_FLUSH \ - (MXC_V_I2C_TX_CTRL0_TX_FLUSH_FLUSH \ - << MXC_F_I2C_TX_CTRL0_TX_FLUSH_POS) /**< TX_CTRL0_TX_FLUSH_FLUSH \ - Setting */ - -#define MXC_F_I2C_TX_CTRL0_TX_THRESH_POS 8 /**< TX_CTRL0_TX_THRESH Position */ -#define MXC_F_I2C_TX_CTRL0_TX_THRESH \ - ((uint32_t)( \ - 0xFUL \ - << MXC_F_I2C_TX_CTRL0_TX_THRESH_POS)) /**< TX_CTRL0_TX_THRESH \ - Mask */ + << MXC_F_I2C_TX_CTRL0_TX_FLUSH_POS) +/* TX_CTRL0_TX_FLUSH_FLUSH Value */ +#define MXC_V_I2C_TX_CTRL0_TX_FLUSH_FLUSH 0x1UL +/* TX_CTRL0_TX_FLUSH_FLUSH Setting */ +#define MXC_S_I2C_TX_CTRL0_TX_FLUSH_FLUSH \ + (MXC_V_I2C_TX_CTRL0_TX_FLUSH_FLUSH << MXC_F_I2C_TX_CTRL0_TX_FLUSH_POS) + +/* TX_CTRL0_TX_THRESH Position */ +#define MXC_F_I2C_TX_CTRL0_TX_THRESH_POS 8 +/* TX_CTRL0_TX_THRESH Mask */ +#define MXC_F_I2C_TX_CTRL0_TX_THRESH (0xFUL << MXC_F_I2C_TX_CTRL0_TX_THRESH_POS) /** * Transmit Control Register 1. */ -#define MXC_F_I2C_TX_CTRL1_TX_READY_POS 0 /**< TX_CTRL1_TX_READY Position */ -#define MXC_F_I2C_TX_CTRL1_TX_READY \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_TX_CTRL1_TX_READY_POS)) /**< TX_CTRL1_TX_READY \ - Mask */ - -#define MXC_F_I2C_TX_CTRL1_TX_LAST_POS 1 /**< TX_CTRL1_TX_LAST Position */ -#define MXC_F_I2C_TX_CTRL1_TX_LAST \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_TX_CTRL1_TX_LAST_POS)) /**< TX_CTRL1_TX_LAST \ - Mask */ -#define MXC_V_I2C_TX_CTRL1_TX_LAST_HOLD_SCL_LOW \ - ((uint32_t)0x0UL) /**< TX_CTRL1_TX_LAST_HOLD_SCL_LOW Value */ +/* TX_CTRL1_TX_READY Position */ +#define MXC_F_I2C_TX_CTRL1_TX_READY_POS 0 +/* TX_CTRL1_TX_READY Mask */ +#define MXC_F_I2C_TX_CTRL1_TX_READY (0x1UL << MXC_F_I2C_TX_CTRL1_TX_READY_POS) + +/* TX_CTRL1_TX_LAST Position */ +#define MXC_F_I2C_TX_CTRL1_TX_LAST_POS 1 +/* TX_CTRL1_TX_LAST Mask */ +#define MXC_F_I2C_TX_CTRL1_TX_LAST (0x1UL << MXC_F_I2C_TX_CTRL1_TX_LAST_POS) +/* TX_CTRL1_TX_LAST_HOLD_SCL_LOW Value */ +#define MXC_V_I2C_TX_CTRL1_TX_LAST_HOLD_SCL_LOW 0x0UL +/* TX_CTRL1_TX_LAST_HOLD_SCL_LOW Setting */ #define MXC_S_I2C_TX_CTRL1_TX_LAST_HOLD_SCL_LOW \ (MXC_V_I2C_TX_CTRL1_TX_LAST_HOLD_SCL_LOW \ - << MXC_F_I2C_TX_CTRL1_TX_LAST_POS) /**< TX_CTRL1_TX_LAST_HOLD_SCL_LOW \ - Setting */ -#define MXC_V_I2C_TX_CTRL1_TX_LAST_END_TRANSACTION \ - ((uint32_t)0x1UL) /**< TX_CTRL1_TX_LAST_END_TRANSACTION Value */ + << MXC_F_I2C_TX_CTRL1_TX_LAST_POS) +/* TX_CTRL1_TX_LAST_END_TRANSACTION Value */ +#define MXC_V_I2C_TX_CTRL1_TX_LAST_END_TRANSACTION 0x1UL +/* TX_CTRL1_TX_LAST_END_TRANSACTION Setting */ #define MXC_S_I2C_TX_CTRL1_TX_LAST_END_TRANSACTION \ (MXC_V_I2C_TX_CTRL1_TX_LAST_END_TRANSACTION \ - << MXC_F_I2C_TX_CTRL1_TX_LAST_POS) /**< \ - TX_CTRL1_TX_LAST_END_TRANSACTION \ - Setting */ + << MXC_F_I2C_TX_CTRL1_TX_LAST_POS) -#define MXC_F_I2C_TX_CTRL1_TX_FIFO_POS 8 /**< TX_CTRL1_TX_FIFO Position */ -#define MXC_F_I2C_TX_CTRL1_TX_FIFO \ - ((uint32_t)( \ - 0xFUL \ - << MXC_F_I2C_TX_CTRL1_TX_FIFO_POS)) /**< TX_CTRL1_TX_FIFO \ - Mask */ +/* TX_CTRL1_TX_FIFO Position */ +#define MXC_F_I2C_TX_CTRL1_TX_FIFO_POS 8 +/* TX_CTRL1_TX_FIFO Mask */ +#define MXC_F_I2C_TX_CTRL1_TX_FIFO (0xFUL << MXC_F_I2C_TX_CTRL1_TX_FIFO_POS) /** * Data Register. */ -#define MXC_F_I2C_FIFO_DATA_POS 0 /**< FIFO_DATA Position */ -#define MXC_F_I2C_FIFO_DATA \ - ((uint32_t)(0xFFUL << MXC_F_I2C_FIFO_DATA_POS)) /**< FIFO_DATA Mask */ +/* FIFO_DATA Position */ +#define MXC_F_I2C_FIFO_DATA_POS 0 +/* FIFO_DATA Mask */ +#define MXC_F_I2C_FIFO_DATA (0xFFUL << MXC_F_I2C_FIFO_DATA_POS) /** - * Master Control Register. + * Controller Control Register. */ -#define MXC_F_I2C_MASTER_CTRL_START_POS 0 /**< MASTER_CTRL_START Position */ -#define MXC_F_I2C_MASTER_CTRL_START \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_MASTER_CTRL_START_POS)) /**< MASTER_CTRL_START \ - Mask */ - -#define MXC_F_I2C_MASTER_CTRL_RESTART_POS \ - 1 /**< MASTER_CTRL_RESTART Position \ - */ -#define MXC_F_I2C_MASTER_CTRL_RESTART \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_MASTER_CTRL_RESTART_POS)) /**< \ - MASTER_CTRL_RESTART \ - Mask */ - -#define MXC_F_I2C_MASTER_CTRL_STOP_POS 2 /**< MASTER_CTRL_STOP Position */ -#define MXC_F_I2C_MASTER_CTRL_STOP \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_MASTER_CTRL_STOP_POS)) /**< MASTER_CTRL_STOP \ - Mask */ - -#define MXC_F_I2C_MASTER_CTRL_SL_EX_ADDR_POS \ - 7 /**< MASTER_CTRL_SL_EX_ADDR Position */ -#define MXC_F_I2C_MASTER_CTRL_SL_EX_ADDR \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_MASTER_CTRL_SL_EX_ADDR_POS)) /**< \ - MASTER_CTRL_SL_EX_ADDR \ - Mask */ -#define MXC_V_I2C_MASTER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS \ - ((uint32_t)0x0UL) /**< MASTER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS Value */ -#define MXC_S_I2C_MASTER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS \ - (MXC_V_I2C_MASTER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS \ - << MXC_F_I2C_MASTER_CTRL_SL_EX_ADDR_POS) /**< \ - MASTER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS \ - Setting */ -#define MXC_V_I2C_MASTER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS \ - ((uint32_t)0x1UL) /**< MASTER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS Value */ -#define MXC_S_I2C_MASTER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS \ - (MXC_V_I2C_MASTER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS \ - << MXC_F_I2C_MASTER_CTRL_SL_EX_ADDR_POS) /**< \ - MASTER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS \ - Setting */ - -#define MXC_F_I2C_MASTER_CTRL_MASTER_CODE_POS \ - 8 /**< MASTER_CTRL_MASTER_CODE Position */ -#define MXC_F_I2C_MASTER_CTRL_MASTER_CODE \ - ((uint32_t)( \ - 0x7UL \ - << MXC_F_I2C_MASTER_CTRL_MASTER_CODE_POS)) /**< \ - MASTER_CTRL_MASTER_CODE \ - Mask */ - -#define MXC_F_I2C_MASTER_CTRL_SCL_SPEED_UP_POS \ - 11 /**< MASTER_CTRL_SCL_SPEED_UP Position */ -#define MXC_F_I2C_MASTER_CTRL_SCL_SPEED_UP \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_MASTER_CTRL_SCL_SPEED_UP_POS)) /**< \ - MASTER_CTRL_SCL_SPEED_UP \ - Mask */ -#define MXC_V_I2C_MASTER_CTRL_SCL_SPEED_UP_EN \ - ((uint32_t)0x0UL) /**< MASTER_CTRL_SCL_SPEED_UP_EN Value */ -#define MXC_S_I2C_MASTER_CTRL_SCL_SPEED_UP_EN \ - (MXC_V_I2C_MASTER_CTRL_SCL_SPEED_UP_EN \ - << MXC_F_I2C_MASTER_CTRL_SCL_SPEED_UP_POS) /**< \ - MASTER_CTRL_SCL_SPEED_UP_EN \ - Setting */ -#define MXC_V_I2C_MASTER_CTRL_SCL_SPEED_UP_DIS \ - ((uint32_t)0x1UL) /**< MASTER_CTRL_SCL_SPEED_UP_DIS Value */ -#define MXC_S_I2C_MASTER_CTRL_SCL_SPEED_UP_DIS \ - (MXC_V_I2C_MASTER_CTRL_SCL_SPEED_UP_DIS \ - << MXC_F_I2C_MASTER_CTRL_SCL_SPEED_UP_POS) /**< \ - MASTER_CTRL_SCL_SPEED_UP_DIS \ - Setting */ +/* CONTROLLER_CTRL_START Position */ +#define MXC_F_I2C_CONTROLLER_CTRL_START_POS 0 +/* CONTROLLER_CTRL_START Mask */ +#define MXC_F_I2C_CONTROLLER_CTRL_START \ + (0x1UL << MXC_F_I2C_CONTROLLER_CTRL_START_POS) + +/* CONTROLLER_CTRL_RESTART Position */ +#define MXC_F_I2C_CONTROLLER_CTRL_RESTART_POS 1 +/* CONTROLLER_CTRL_RESTART Mask */ +#define MXC_F_I2C_CONTROLLER_CTRL_RESTART \ + (0x1UL << MXC_F_I2C_CONTROLLER_CTRL_RESTART_POS) + +/* CONTROLLER_CTRL_STOP Position */ +#define MXC_F_I2C_CONTROLLER_CTRL_STOP_POS 2 +/* CONTROLLER_CTRL_STOP Mask */ +#define MXC_F_I2C_CONTROLLER_CTRL_STOP \ + (0x1UL << MXC_F_I2C_CONTROLLER_CTRL_STOP_POS) + +/* CONTROLLER_CTRL_SL_EX_ADDR Position */ +#define MXC_F_I2C_CONTROLLER_CTRL_SL_EX_ADDR_POS 7 +/* CONTROLLER_CTRL_SL_EX_ADDR Mask */ +#define MXC_F_I2C_CONTROLLER_CTRL_SL_EX_ADDR \ + (0x1UL << MXC_F_I2C_CONTROLLER_CTRL_SL_EX_ADDR_POS) +/* CONTROLLER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS Value */ +#define MXC_V_I2C_CONTROLLER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS 0x0UL +/* CONTROLLER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS Setting */ +#define MXC_S_I2C_CONTROLLER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS \ + (MXC_V_I2C_CONTROLLER_CTRL_SL_EX_ADDR_7_BITS_ADDRESS \ + << MXC_F_I2C_CONTROLLER_CTRL_SL_EX_ADDR_POS) +/* CONTROLLER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS Value */ +#define MXC_V_I2C_CONTROLLER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS 0x1UL +/* CONTROLLER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS Setting */ +#define MXC_S_I2C_CONTROLLER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS \ + (MXC_V_I2C_CONTROLLER_CTRL_SL_EX_ADDR_10_BITS_ADDRESS \ + << MXC_F_I2C_CONTROLLER_CTRL_SL_EX_ADDR_POS) + +/* CONTROLLER_CTRL_CONTROLLER_CODE Position */ +#define MXC_F_I2C_CONTROLLER_CTRL_CONTROLLER_CODE_POS 8 +/* CONTROLLER_CTRL_CONTROLLER_CODE Mask */ +#define MXC_F_I2C_CONTROLLER_CTRL_CONTROLLER_CODE \ + (0x7UL << MXC_F_I2C_CONTROLLER_CTRL_CONTROLLER_CODE_POS) + +/* CONTROLLER_CTRL_SCL_SPEED_UP Position */ +#define MXC_F_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_POS 11 +/* CONTROLLER_CTRL_SCL_SPEED_UP Mask */ +#define MXC_F_I2C_CONTROLLER_CTRL_SCL_SPEED_UP \ + (0x1UL << MXC_F_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_POS) +/* CONTROLLER_CTRL_SCL_SPEED_UP_EN Value */ +#define MXC_V_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_EN 0x0UL +/* CONTROLLER_CTRL_SCL_SPEED_UP_EN Setting */ +#define MXC_S_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_EN \ + (MXC_V_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_EN \ + << MXC_F_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_POS) +/* CONTROLLER_CTRL_SCL_SPEED_UP_DIS Value */ +#define MXC_V_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_DIS 0x1UL +/* CONTROLLER_CTRL_SCL_SPEED_UP_DIS Setting */ +#define MXC_S_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_DIS \ + (MXC_V_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_DIS \ + << MXC_F_I2C_CONTROLLER_CTRL_SCL_SPEED_UP_POS) /** * Clock Low Register. */ -#define MXC_F_I2C_CLK_LO_CLK_LO_POS 0 /**< CLK_LO_CLK_LO Position */ -#define MXC_F_I2C_CLK_LO_CLK_LO \ - ((uint32_t)( \ - 0x1FFUL \ - << MXC_F_I2C_CLK_LO_CLK_LO_POS)) /**< CLK_LO_CLK_LO Mask */ +/* CLK_LO_CLK_LO Position */ +#define MXC_F_I2C_CLK_LO_CLK_LO_POS 0 +/* CLK_LO_CLK_LO Mask */ +#define MXC_F_I2C_CLK_LO_CLK_LO (0x1FFUL << MXC_F_I2C_CLK_LO_CLK_LO_POS) /** * Clock high Register. */ -#define MXC_F_I2C_CLK_HI_CKH_POS 0 /**< CLK_HI_CKH Position */ -#define MXC_F_I2C_CLK_HI_CKH \ - ((uint32_t)(0x1FFUL \ - << MXC_F_I2C_CLK_HI_CKH_POS)) /**< CLK_HI_CKH Mask */ +/* CLK_HI_CKH Position */ +#define MXC_F_I2C_CLK_HI_CKH_POS 0 +/* CLK_HI_CKH Mask */ +#define MXC_F_I2C_CLK_HI_CKH (0x1FFUL << MXC_F_I2C_CLK_HI_CKH_POS) /** * HS-Mode Clock Control Register */ -#define MXC_F_I2C_HS_CLK_HS_CLK_LO_POS 0 /**< HS_CLK_HS_CLK_LO Position */ -#define MXC_F_I2C_HS_CLK_HS_CLK_LO \ - ((uint32_t)( \ - 0xFFUL \ - << MXC_F_I2C_HS_CLK_HS_CLK_LO_POS)) /**< HS_CLK_HS_CLK_LO \ - Mask */ - -#define MXC_F_I2C_HS_CLK_HS_CLK_HI_POS 8 /**< HS_CLK_HS_CLK_HI Position */ -#define MXC_F_I2C_HS_CLK_HS_CLK_HI \ - ((uint32_t)( \ - 0xFFUL \ - << MXC_F_I2C_HS_CLK_HS_CLK_HI_POS)) /**< HS_CLK_HS_CLK_HI \ - Mask */ +/* HS_CLK_HS_CLK_LO Position */ +#define MXC_F_I2C_HS_CLK_HS_CLK_LO_POS 0 +/* HS_CLK_HS_CLK_LO Mask */ +#define MXC_F_I2C_HS_CLK_HS_CLK_LO (0xFFUL << MXC_F_I2C_HS_CLK_HS_CLK_LO_POS) + +/* HS_CLK_HS_CLK_HI Position */ +#define MXC_F_I2C_HS_CLK_HS_CLK_HI_POS 8 +/* HS_CLK_HS_CLK_HI Mask */ +#define MXC_F_I2C_HS_CLK_HS_CLK_HI (0xFFUL << MXC_F_I2C_HS_CLK_HS_CLK_HI_POS) /** * Timeout Register */ -#define MXC_F_I2C_TIMEOUT_TO_POS 0 /**< TIMEOUT_TO Position */ -#define MXC_F_I2C_TIMEOUT_TO \ - ((uint32_t)(0xFFFFUL \ - << MXC_F_I2C_TIMEOUT_TO_POS)) /**< TIMEOUT_TO Mask */ +/* TIMEOUT_TO Position */ +#define MXC_F_I2C_TIMEOUT_TO_POS 0 +/* TIMEOUT_TO Mask */ +#define MXC_F_I2C_TIMEOUT_TO (0xFFFFUL << MXC_F_I2C_TIMEOUT_TO_POS) /** - * Slave Address Register. + * Target Address Register. */ -#define MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_POS \ - 0 /**< SLAVE_ADDR_SLAVE_ADDR Position */ -#define MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR \ - ((uint32_t)( \ - 0x3FFUL \ - << MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_POS)) /**< \ - SLAVE_ADDR_SLAVE_ADDR \ - Mask */ - -#define MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_DIS_POS \ - 10 /**< SLAVE_ADDR_SLAVE_ADDR_DIS Position */ -#define MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_DIS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_DIS_POS)) /**< \ - SLAVE_ADDR_SLAVE_ADDR_DIS \ - Mask */ - -#define MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_IDX_POS \ - 11 /**< SLAVE_ADDR_SLAVE_ADDR_IDX Position */ -#define MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_IDX \ - ((uint32_t)( \ - 0xFUL \ - << MXC_F_I2C_SLAVE_ADDR_SLAVE_ADDR_IDX_POS)) /**< \ - SLAVE_ADDR_SLAVE_ADDR_IDX \ - Mask */ - -#define MXC_F_I2C_SLAVE_ADDR_EX_ADDR_POS \ - 15 /**< SLAVE_ADDR_EX_ADDR Position \ - */ -#define MXC_F_I2C_SLAVE_ADDR_EX_ADDR \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_I2C_SLAVE_ADDR_EX_ADDR_POS)) /**< SLAVE_ADDR_EX_ADDR \ - Mask */ -#define MXC_V_I2C_SLAVE_ADDR_EX_ADDR_7_BITS_ADDRESS \ - ((uint32_t)0x0UL) /**< SLAVE_ADDR_EX_ADDR_7_BITS_ADDRESS Value */ -#define MXC_S_I2C_SLAVE_ADDR_EX_ADDR_7_BITS_ADDRESS \ - (MXC_V_I2C_SLAVE_ADDR_EX_ADDR_7_BITS_ADDRESS \ - << MXC_F_I2C_SLAVE_ADDR_EX_ADDR_POS) /**< \ - SLAVE_ADDR_EX_ADDR_7_BITS_ADDRESS \ - Setting */ -#define MXC_V_I2C_SLAVE_ADDR_EX_ADDR_10_BITS_ADDRESS \ - ((uint32_t)0x1UL) /**< SLAVE_ADDR_EX_ADDR_10_BITS_ADDRESS Value */ -#define MXC_S_I2C_SLAVE_ADDR_EX_ADDR_10_BITS_ADDRESS \ - (MXC_V_I2C_SLAVE_ADDR_EX_ADDR_10_BITS_ADDRESS \ - << MXC_F_I2C_SLAVE_ADDR_EX_ADDR_POS) /**< \ - SLAVE_ADDR_EX_ADDR_10_BITS_ADDRESS \ - Setting */ +/* TARGET_ADDR_TARGET_ADDR Position */ +#define MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_POS 0 +/* TARGET_ADDR_TARGET_ADDR Mask */ +#define MXC_F_I2C_TARGET_ADDR_TARGET_ADDR \ + (0x3FFUL << MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_POS) + +/* TARGET_ADDR_TARGET_ADDR_DIS Position */ +#define MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_DIS_POS 10 +/* TARGET_ADDR_TARGET_ADDR_DIS Mask */ +#define MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_DIS \ + (0x1UL << MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_DIS_POS) + +/* TARGET_ADDR_TARGET_ADDR_IDX Position */ +#define MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_IDX_POS 11 +/* TARGET_ADDR_TARGET_ADDR_IDX Mask */ +#define MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_IDX \ + (0xFUL << MXC_F_I2C_TARGET_ADDR_TARGET_ADDR_IDX_POS) + +/* TARGET_ADDR_EX_ADDR Position */ +#define MXC_F_I2C_TARGET_ADDR_EX_ADDR_POS 15 +/* TARGET_ADDR_EX_ADDR Mask */ +#define MXC_F_I2C_TARGET_ADDR_EX_ADDR \ + (0x1UL << MXC_F_I2C_TARGET_ADDR_EX_ADDR_POS) +/* TARGET_ADDR_EX_ADDR_7_BITS_ADDRESS Value */ +#define MXC_V_I2C_TARGET_ADDR_EX_ADDR_7_BITS_ADDRESS 0x0UL +/* TARGET_ADDR_EX_ADDR_7_BITS_ADDRESS Setting */ +#define MXC_S_I2C_TARGET_ADDR_EX_ADDR_7_BITS_ADDRESS \ + (MXC_V_I2C_TARGET_ADDR_EX_ADDR_7_BITS_ADDRESS \ + << MXC_F_I2C_TARGET_ADDR_EX_ADDR_POS) +/* TARGET_ADDR_EX_ADDR_10_BITS_ADDRESS Value */ +#define MXC_V_I2C_TARGET_ADDR_EX_ADDR_10_BITS_ADDRESS 0x1UL +/* TARGET_ADDR_EX_ADDR_10_BITS_ADDRESS Setting */ +#define MXC_S_I2C_TARGET_ADDR_EX_ADDR_10_BITS_ADDRESS \ + (MXC_V_I2C_TARGET_ADDR_EX_ADDR_10_BITS_ADDRESS \ + << MXC_F_I2C_TARGET_ADDR_EX_ADDR_POS) /** * DMA Register. */ -#define MXC_F_I2C_DMA_TX_EN_POS 0 /**< DMA_TX_EN Position */ -#define MXC_F_I2C_DMA_TX_EN \ - ((uint32_t)(0x1UL << MXC_F_I2C_DMA_TX_EN_POS)) /**< DMA_TX_EN Mask */ -#define MXC_V_I2C_DMA_TX_EN_DIS ((uint32_t)0x0UL) /**< DMA_TX_EN_DIS Value */ -#define MXC_S_I2C_DMA_TX_EN_DIS \ - (MXC_V_I2C_DMA_TX_EN_DIS \ - << MXC_F_I2C_DMA_TX_EN_POS) /**< DMA_TX_EN_DIS Setting */ -#define MXC_V_I2C_DMA_TX_EN_EN ((uint32_t)0x1UL) /**< DMA_TX_EN_EN Value */ -#define MXC_S_I2C_DMA_TX_EN_EN \ - (MXC_V_I2C_DMA_TX_EN_EN \ - << MXC_F_I2C_DMA_TX_EN_POS) /**< DMA_TX_EN_EN Setting */ - -#define MXC_F_I2C_DMA_RX_EN_POS 1 /**< DMA_RX_EN Position */ -#define MXC_F_I2C_DMA_RX_EN \ - ((uint32_t)(0x1UL << MXC_F_I2C_DMA_RX_EN_POS)) /**< DMA_RX_EN Mask */ -#define MXC_V_I2C_DMA_RX_EN_DIS ((uint32_t)0x0UL) /**< DMA_RX_EN_DIS Value */ -#define MXC_S_I2C_DMA_RX_EN_DIS \ - (MXC_V_I2C_DMA_RX_EN_DIS \ - << MXC_F_I2C_DMA_RX_EN_POS) /**< DMA_RX_EN_DIS Setting */ -#define MXC_V_I2C_DMA_RX_EN_EN ((uint32_t)0x1UL) /**< DMA_RX_EN_EN Value */ -#define MXC_S_I2C_DMA_RX_EN_EN \ - (MXC_V_I2C_DMA_RX_EN_EN \ - << MXC_F_I2C_DMA_RX_EN_POS) /**< DMA_RX_EN_EN Setting */ +/* DMA_TX_EN Position */ +#define MXC_F_I2C_DMA_TX_EN_POS 0 +/* DMA_TX_EN Mask */ +#define MXC_F_I2C_DMA_TX_EN (0x1UL << MXC_F_I2C_DMA_TX_EN_POS) +/* DMA_TX_EN_DIS Value */ +#define MXC_V_I2C_DMA_TX_EN_DIS 0x0UL +/* DMA_TX_EN_DIS Setting */ +#define MXC_S_I2C_DMA_TX_EN_DIS \ + (MXC_V_I2C_DMA_TX_EN_DIS << MXC_F_I2C_DMA_TX_EN_POS) +/* DMA_TX_EN_EN Value */ +#define MXC_V_I2C_DMA_TX_EN_EN 0x1UL +/* DMA_TX_EN_EN Setting */ +#define MXC_S_I2C_DMA_TX_EN_EN \ + (MXC_V_I2C_DMA_TX_EN_EN << MXC_F_I2C_DMA_TX_EN_POS) + +/* DMA_RX_EN Position */ +#define MXC_F_I2C_DMA_RX_EN_POS 1 +/* DMA_RX_EN Mask */ +#define MXC_F_I2C_DMA_RX_EN (0x1UL << MXC_F_I2C_DMA_RX_EN_POS) +/* DMA_RX_EN_DIS Value */ +#define MXC_V_I2C_DMA_RX_EN_DIS 0x0UL +/* DMA_RX_EN_DIS Setting */ +#define MXC_S_I2C_DMA_RX_EN_DIS \ + (MXC_V_I2C_DMA_RX_EN_DIS << MXC_F_I2C_DMA_RX_EN_POS) +/* DMA_RX_EN_EN Value */ +#define MXC_V_I2C_DMA_RX_EN_EN 0x1UL +/* DMA_RX_EN_EN Setting */ +#define MXC_S_I2C_DMA_RX_EN_EN \ + (MXC_V_I2C_DMA_RX_EN_EN << MXC_F_I2C_DMA_RX_EN_POS) #endif /* _I2C_REGS_H_ */ diff --git a/chip/max32660/icc_regs.h b/chip/max32660/icc_regs.h index 5f40e4203d..b2dbc75ec3 100644 --- a/chip/max32660/icc_regs.h +++ b/chip/max32660/icc_regs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -32,112 +32,110 @@ */ typedef struct { __I uint32_t cache_id; /**< \b 0x0000:<\tt> ICC CACHE_ID Register */ - __I uint32_t memcfg; /**< \b 0x0004:<\tt> ICC MEMCFG Register */ + __I uint32_t memcfg; /**< \b 0x0004:<\tt> ICC MEMCFG Register */ __R uint32_t rsv_0x8_0xff[62]; - __IO uint32_t - cache_ctrl; /**< \b 0x0100:<\tt> ICC CACHE_CTRL Register */ + __IO uint32_t cache_ctrl; /**< \b 0x0100:<\tt> ICC CACHE_CTRL + Register */ __R uint32_t rsv_0x104_0x6ff[383]; - __IO uint32_t - invalidate; /**< \b 0x0700:<\tt> ICC INVALIDATE Register */ + __IO uint32_t invalidate; /**< \b 0x0700:<\tt> ICC INVALIDATE + Register */ } mxc_icc_regs_t; /** * ICC Peripheral Register Offsets from the ICC Base Peripheral * Address. */ -#define MXC_R_ICC_CACHE_ID \ - ((uint32_t)0x00000000UL) /**< Offset from ICC Base Address: \ +#define MXC_R_ICC_CACHE_ID \ + ((uint32_t)0x00000000UL) /**< Offset from ICC Base Address: \ 0x0x000 */ -#define MXC_R_ICC_MEMCFG \ - ((uint32_t)0x00000004UL) /**< Offset from ICC Base Address: \ +#define MXC_R_ICC_MEMCFG \ + ((uint32_t)0x00000004UL) /**< Offset from ICC Base Address: \ 0x0x004 */ -#define MXC_R_ICC_CACHE_CTRL \ - ((uint32_t)0x00000100UL) /**< Offset from ICC Base Address: \ +#define MXC_R_ICC_CACHE_CTRL \ + ((uint32_t)0x00000100UL) /**< Offset from ICC Base Address: \ 0x0x100 */ -#define MXC_R_ICC_INVALIDATE \ - ((uint32_t)0x00000700UL) /**< Offset from ICC Base Address: \ +#define MXC_R_ICC_INVALIDATE \ + ((uint32_t)0x00000700UL) /**< Offset from ICC Base Address: \ 0x0x700 */ /** * Cache ID Register. */ #define MXC_F_ICC_CACHE_ID_RELNUM_POS 0 /**< CACHE_ID_RELNUM Position */ -#define MXC_F_ICC_CACHE_ID_RELNUM \ - ((uint32_t)( \ - 0x3FUL << MXC_F_ICC_CACHE_ID_RELNUM_POS)) /**< CACHE_ID_RELNUM \ - Mask */ +#define MXC_F_ICC_CACHE_ID_RELNUM \ + ((uint32_t)(0x3FUL \ + << MXC_F_ICC_CACHE_ID_RELNUM_POS)) /**< CACHE_ID_RELNUM \ + Mask */ #define MXC_F_ICC_CACHE_ID_PARTNUM_POS 6 /**< CACHE_ID_PARTNUM Position */ -#define MXC_F_ICC_CACHE_ID_PARTNUM \ - ((uint32_t)(0xFUL \ - << MXC_F_ICC_CACHE_ID_PARTNUM_POS)) /**< CACHE_ID_PARTNUM \ +#define MXC_F_ICC_CACHE_ID_PARTNUM \ + ((uint32_t)(0xFUL \ + << MXC_F_ICC_CACHE_ID_PARTNUM_POS)) /**< CACHE_ID_PARTNUM \ Mask */ #define MXC_F_ICC_CACHE_ID_CCHID_POS 10 /**< CACHE_ID_CCHID Position */ #define MXC_F_ICC_CACHE_ID_CCHID \ - ((uint32_t)( \ - 0x3FUL \ - << MXC_F_ICC_CACHE_ID_CCHID_POS)) /**< CACHE_ID_CCHID Mask */ + ((uint32_t)(0x3FUL << MXC_F_ICC_CACHE_ID_CCHID_POS)) /**< \ + CACHE_ID_CCHID \ + Mask */ /** * Memory Configuration Register. */ #define MXC_F_ICC_MEMCFG_CCHSZ_POS 0 /**< MEMCFG_CCHSZ Position */ #define MXC_F_ICC_MEMCFG_CCHSZ \ - ((uint32_t)(0xFFFFUL \ - << MXC_F_ICC_MEMCFG_CCHSZ_POS)) /**< MEMCFG_CCHSZ Mask */ + ((uint32_t)(0xFFFFUL << MXC_F_ICC_MEMCFG_CCHSZ_POS)) /**< MEMCFG_CCHSZ \ + Mask */ #define MXC_F_ICC_MEMCFG_MEMSZ_POS 16 /**< MEMCFG_MEMSZ Position */ #define MXC_F_ICC_MEMCFG_MEMSZ \ - ((uint32_t)(0xFFFFUL \ - << MXC_F_ICC_MEMCFG_MEMSZ_POS)) /**< MEMCFG_MEMSZ Mask */ + ((uint32_t)(0xFFFFUL << MXC_F_ICC_MEMCFG_MEMSZ_POS)) /**< MEMCFG_MEMSZ \ + Mask */ /** * Cache Control and Status Register. */ -#define MXC_F_ICC_CACHE_CTRL_CACHE_EN_POS \ - 0 /**< CACHE_CTRL_CACHE_EN Position \ +#define MXC_F_ICC_CACHE_CTRL_CACHE_EN_POS \ + 0 /**< CACHE_CTRL_CACHE_EN Position \ */ -#define MXC_F_ICC_CACHE_CTRL_CACHE_EN \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_ICC_CACHE_CTRL_CACHE_EN_POS)) /**< \ - CACHE_CTRL_CACHE_EN \ - Mask */ -#define MXC_V_ICC_CACHE_CTRL_CACHE_EN_DIS \ +#define MXC_F_ICC_CACHE_CTRL_CACHE_EN \ + ((uint32_t)(0x1UL \ + << MXC_F_ICC_CACHE_CTRL_CACHE_EN_POS)) /**< \ + CACHE_CTRL_CACHE_EN \ + Mask */ +#define MXC_V_ICC_CACHE_CTRL_CACHE_EN_DIS \ ((uint32_t)0x0UL) /**< CACHE_CTRL_CACHE_EN_DIS Value */ -#define MXC_S_ICC_CACHE_CTRL_CACHE_EN_DIS \ - (MXC_V_ICC_CACHE_CTRL_CACHE_EN_DIS \ - << MXC_F_ICC_CACHE_CTRL_CACHE_EN_POS) /**< CACHE_CTRL_CACHE_EN_DIS \ +#define MXC_S_ICC_CACHE_CTRL_CACHE_EN_DIS \ + (MXC_V_ICC_CACHE_CTRL_CACHE_EN_DIS \ + << MXC_F_ICC_CACHE_CTRL_CACHE_EN_POS) /**< CACHE_CTRL_CACHE_EN_DIS \ Setting */ -#define MXC_V_ICC_CACHE_CTRL_CACHE_EN_EN \ +#define MXC_V_ICC_CACHE_CTRL_CACHE_EN_EN \ ((uint32_t)0x1UL) /**< CACHE_CTRL_CACHE_EN_EN Value */ -#define MXC_S_ICC_CACHE_CTRL_CACHE_EN_EN \ - (MXC_V_ICC_CACHE_CTRL_CACHE_EN_EN \ - << MXC_F_ICC_CACHE_CTRL_CACHE_EN_POS) /**< CACHE_CTRL_CACHE_EN_EN \ +#define MXC_S_ICC_CACHE_CTRL_CACHE_EN_EN \ + (MXC_V_ICC_CACHE_CTRL_CACHE_EN_EN \ + << MXC_F_ICC_CACHE_CTRL_CACHE_EN_POS) /**< CACHE_CTRL_CACHE_EN_EN \ Setting */ -#define MXC_F_ICC_CACHE_CTRL_CACHE_RDY_POS \ +#define MXC_F_ICC_CACHE_CTRL_CACHE_RDY_POS \ 16 /**< CACHE_CTRL_CACHE_RDY Position */ -#define MXC_F_ICC_CACHE_CTRL_CACHE_RDY \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_ICC_CACHE_CTRL_CACHE_RDY_POS)) /**< \ - CACHE_CTRL_CACHE_RDY \ - Mask */ -#define MXC_V_ICC_CACHE_CTRL_CACHE_RDY_NOTREADY \ +#define MXC_F_ICC_CACHE_CTRL_CACHE_RDY \ + ((uint32_t)(0x1UL \ + << MXC_F_ICC_CACHE_CTRL_CACHE_RDY_POS)) /**< \ + CACHE_CTRL_CACHE_RDY \ + Mask */ +#define MXC_V_ICC_CACHE_CTRL_CACHE_RDY_NOTREADY \ ((uint32_t)0x0UL) /**< CACHE_CTRL_CACHE_RDY_NOTREADY Value */ #define MXC_S_ICC_CACHE_CTRL_CACHE_RDY_NOTREADY \ (MXC_V_ICC_CACHE_CTRL_CACHE_RDY_NOTREADY \ << MXC_F_ICC_CACHE_CTRL_CACHE_RDY_POS) /**< \ CACHE_CTRL_CACHE_RDY_NOTREADY \ Setting */ -#define MXC_V_ICC_CACHE_CTRL_CACHE_RDY_READY \ +#define MXC_V_ICC_CACHE_CTRL_CACHE_RDY_READY \ ((uint32_t)0x1UL) /**< CACHE_CTRL_CACHE_RDY_READY Value */ -#define MXC_S_ICC_CACHE_CTRL_CACHE_RDY_READY \ - (MXC_V_ICC_CACHE_CTRL_CACHE_RDY_READY \ - << MXC_F_ICC_CACHE_CTRL_CACHE_RDY_POS) /**< \ - CACHE_CTRL_CACHE_RDY_READY \ +#define MXC_S_ICC_CACHE_CTRL_CACHE_RDY_READY \ + (MXC_V_ICC_CACHE_CTRL_CACHE_RDY_READY \ + << MXC_F_ICC_CACHE_CTRL_CACHE_RDY_POS) /**< \ + CACHE_CTRL_CACHE_RDY_READY \ Setting */ #endif /* _ICC_REGS_H_ */ diff --git a/chip/max32660/pwrseq_regs.h b/chip/max32660/pwrseq_regs.h index f323b4568c..e42ab8fd9d 100644 --- a/chip/max32660/pwrseq_regs.h +++ b/chip/max32660/pwrseq_regs.h @@ -1,489 +1,502 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* MAX32660 Registers, Bit Masks and Bit Positions for the PWRSEQ Peripheral */ - -#ifndef _PWRSEQ_REGS_H_ -#define _PWRSEQ_REGS_H_ - -/* **** Includes **** */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(__ICCARM__) -#pragma system_include -#endif - -#if defined(__CC_ARM) -#pragma anon_unions -#endif - -/* - If types are not defined elsewhere (CMSIS) define them here -*/ -#ifndef __IO -#define __IO volatile -#endif -#ifndef __I -#define __I volatile const -#endif -#ifndef __O -#define __O volatile -#endif -#ifndef __R -#define __R volatile const -#endif - -/* **** Definitions **** */ - -/** - * mxc_pwrseq_regs_t - * Registers, Bit Masks and Bit Positions for the PWRSEQ Peripheral - * Module. - */ - -/** - * pwrseq_registers - * Structure type to access the PWRSEQ Registers. - */ -typedef struct { - __IO uint32_t lp_ctrl; /**< \b 0x00: PWRSEQ LP_CTRL Register */ - __IO uint32_t - lp_wakefl; /**< \b 0x04: PWRSEQ LP_WAKEFL Register */ - __IO uint32_t lpwk_en; /**< \b 0x08: PWRSEQ LPWK_EN Register */ - __R uint32_t rsv_0xc_0x3f[13]; - __IO uint32_t lpmemsd; /**< \b 0x40: PWRSEQ LPMEMSD Register */ -} mxc_pwrseq_regs_t; - -/** - * Register offsets for module PWRSEQ - * PWRSEQ Peripheral Register Offsets from the PWRSEQ Base - */ -#define MXC_R_PWRSEQ_LP_CTRL \ - ((uint32_t)0x00000000UL) /**< Offset from PWRSEQ Base Address: \ \ - \ \ \ 0x0000 */ -#define MXC_R_PWRSEQ_LP_WAKEFL \ - ((uint32_t)0x00000004UL) /**< Offset from PWRSEQ Base Address: \ \ - \ \ \ 0x0004 */ -#define MXC_R_PWRSEQ_LPWK_EN \ - ((uint32_t)0x00000008UL) /**< Offset from PWRSEQ Base Address: \ \ - \ \ \ 0x0008 */ -#define MXC_R_PWRSEQ_LPMEMSD \ - ((uint32_t)0x00000040UL) /**< Offset from PWRSEQ Base Address: \ \ - \ \ \ 0x0040 */ - -/** - * pwrseq_registers - * Low Power Control Register. - */ -#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0_POS \ - 0 /**< LP_CTRL_RAMRET_SEL0 Position */ -#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0 \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0_POS)) /**< \ \ \ \ \ - LP_CTRL_RAMRET_SEL0 \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL0_DIS \ - ((uint32_t)0x0UL) /**< LP_CTRL_RAMRET_SEL0_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL0_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL0_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0_POS) /**< LP_CTRL_RAMRET_SEL0_DIS \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL0_EN \ - ((uint32_t)0x1UL) /**< LP_CTRL_RAMRET_SEL0_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL0_EN \ - (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL0_EN \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0_POS) /**< LP_CTRL_RAMRET_SEL0_EN \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1_POS \ - 1 /**< LP_CTRL_RAMRET_SEL1 Position */ -#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1 \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1_POS)) /**< \ \ \ \ \ - LP_CTRL_RAMRET_SEL1 \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL1_DIS \ - ((uint32_t)0x0UL) /**< LP_CTRL_RAMRET_SEL1_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL1_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL1_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1_POS) /**< LP_CTRL_RAMRET_SEL1_DIS \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL1_EN \ - ((uint32_t)0x1UL) /**< LP_CTRL_RAMRET_SEL1_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL1_EN \ - (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL1_EN \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1_POS) /**< LP_CTRL_RAMRET_SEL1_EN \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2_POS \ - 2 /**< LP_CTRL_RAMRET_SEL2 Position */ -#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2 \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2_POS)) /**< \ \ \ \ \ - LP_CTRL_RAMRET_SEL2 \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL2_DIS \ - ((uint32_t)0x0UL) /**< LP_CTRL_RAMRET_SEL2_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL2_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL2_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2_POS) /**< LP_CTRL_RAMRET_SEL2_DIS \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL2_EN \ - ((uint32_t)0x1UL) /**< LP_CTRL_RAMRET_SEL2_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL2_EN \ - (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL2_EN \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2_POS) /**< LP_CTRL_RAMRET_SEL2_EN \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3_POS \ - 3 /**< LP_CTRL_RAMRET_SEL3 Position */ -#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3 \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3_POS)) /**< \ \ \ \ \ - LP_CTRL_RAMRET_SEL3 \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL3_DIS \ - ((uint32_t)0x0UL) /**< LP_CTRL_RAMRET_SEL3_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL3_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL3_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3_POS) /**< LP_CTRL_RAMRET_SEL3_DIS \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL3_EN \ - ((uint32_t)0x1UL) /**< LP_CTRL_RAMRET_SEL3_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL3_EN \ - (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL3_EN \ - << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3_POS) /**< LP_CTRL_RAMRET_SEL3_EN \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_OVR_POS 4 /**< LP_CTRL_OVR Position */ -#define MXC_F_PWRSEQ_LP_CTRL_OVR \ - ((uint32_t)(0x3UL \ - << MXC_F_PWRSEQ_LP_CTRL_OVR_POS)) /**< LP_CTRL_OVR Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_OVR_0_9V \ - ((uint32_t)0x0UL) /**< LP_CTRL_OVR_0_9V Value */ -#define MXC_S_PWRSEQ_LP_CTRL_OVR_0_9V \ - (MXC_V_PWRSEQ_LP_CTRL_OVR_0_9V \ - << MXC_F_PWRSEQ_LP_CTRL_OVR_POS) /**< LP_CTRL_OVR_0_9V Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_OVR_1_0V \ - ((uint32_t)0x1UL) /**< LP_CTRL_OVR_1_0V Value */ -#define MXC_S_PWRSEQ_LP_CTRL_OVR_1_0V \ - (MXC_V_PWRSEQ_LP_CTRL_OVR_1_0V \ - << MXC_F_PWRSEQ_LP_CTRL_OVR_POS) /**< LP_CTRL_OVR_1_0V Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_OVR_1_1V \ - ((uint32_t)0x2UL) /**< LP_CTRL_OVR_1_1V Value */ -#define MXC_S_PWRSEQ_LP_CTRL_OVR_1_1V \ - (MXC_V_PWRSEQ_LP_CTRL_OVR_1_1V \ - << MXC_F_PWRSEQ_LP_CTRL_OVR_POS) /**< LP_CTRL_OVR_1_1V Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_POS \ - 6 /**< LP_CTRL_VCORE_DET_BYPASS Position */ -#define MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_POS)) /**< \ \ \ \ \ - LP_CTRL_VCORE_DET_BYPASS \ - \ \ - \ \ \ \ \ - Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_ENABLED \ - ((uint32_t)0x0UL) /**< LP_CTRL_VCORE_DET_BYPASS_ENABLED Value */ -#define MXC_S_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_ENABLED \ - (MXC_V_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_ENABLED \ - << MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_POS) /**< \ \ \ \ \ - LP_CTRL_VCORE_DET_BYPASS_ENABLED \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_DISABLE \ - ((uint32_t)0x1UL) /**< LP_CTRL_VCORE_DET_BYPASS_DISABLE Value */ -#define MXC_S_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_DISABLE \ - (MXC_V_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_DISABLE \ - << MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_POS) /**< \ \ \ \ \ - LP_CTRL_VCORE_DET_BYPASS_DISABLE \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_RETREG_EN_POS \ - 8 /**< LP_CTRL_RETREG_EN Position \ \ \ \ \ - */ -#define MXC_F_PWRSEQ_LP_CTRL_RETREG_EN \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_RETREG_EN_POS)) /**< LP_CTRL_RETREG_EN \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_RETREG_EN_DIS \ - ((uint32_t)0x0UL) /**< LP_CTRL_RETREG_EN_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RETREG_EN_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_RETREG_EN_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_RETREG_EN_POS) /**< LP_CTRL_RETREG_EN_DIS \ \ \ - \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_RETREG_EN_EN \ - ((uint32_t)0x1UL) /**< LP_CTRL_RETREG_EN_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_RETREG_EN_EN \ - (MXC_V_PWRSEQ_LP_CTRL_RETREG_EN_EN \ - << MXC_F_PWRSEQ_LP_CTRL_RETREG_EN_POS) /**< LP_CTRL_RETREG_EN_EN \ \ \ - \ \ Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN_POS \ - 10 /**< LP_CTRL_FAST_WK_EN Position */ -#define MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN_POS)) /**< \ \ \ \ \ - LP_CTRL_FAST_WK_EN \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_FAST_WK_EN_DIS \ - ((uint32_t)0x0UL) /**< LP_CTRL_FAST_WK_EN_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_FAST_WK_EN_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_FAST_WK_EN_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN_POS) /**< LP_CTRL_FAST_WK_EN_DIS \ \ - \ \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_FAST_WK_EN_EN \ - ((uint32_t)0x1UL) /**< LP_CTRL_FAST_WK_EN_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_FAST_WK_EN_EN \ - (MXC_V_PWRSEQ_LP_CTRL_FAST_WK_EN_EN \ - << MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN_POS) /**< LP_CTRL_FAST_WK_EN_EN \ \ - \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_BG_OFF_POS 11 /**< LP_CTRL_BG_OFF Position */ -#define MXC_F_PWRSEQ_LP_CTRL_BG_OFF \ - ((uint32_t)( \ - 0x1UL << MXC_F_PWRSEQ_LP_CTRL_BG_OFF_POS)) /**< LP_CTRL_BG_OFF \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_BG_OFF_ON \ - ((uint32_t)0x0UL) /**< LP_CTRL_BG_OFF_ON Value */ -#define MXC_S_PWRSEQ_LP_CTRL_BG_OFF_ON \ - (MXC_V_PWRSEQ_LP_CTRL_BG_OFF_ON \ - << MXC_F_PWRSEQ_LP_CTRL_BG_OFF_POS) /**< LP_CTRL_BG_OFF_ON Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_BG_OFF_OFF \ - ((uint32_t)0x1UL) /**< LP_CTRL_BG_OFF_OFF Value */ -#define MXC_S_PWRSEQ_LP_CTRL_BG_OFF_OFF \ - (MXC_V_PWRSEQ_LP_CTRL_BG_OFF_OFF \ - << MXC_F_PWRSEQ_LP_CTRL_BG_OFF_POS) /**< LP_CTRL_BG_OFF_OFF Setting \ \ - * \ \ - * \ \ \ - * \ \ \ \ - */ - -#define MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS_POS \ - 12 /**< LP_CTRL_VCORE_POR_DIS Position */ -#define MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS_POS)) /**< \ \ \ \ \ - LP_CTRL_VCORE_POR_DIS \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_VCORE_POR_DIS_DIS \ - ((uint32_t)0x0UL) /**< LP_CTRL_VCORE_POR_DIS_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_VCORE_POR_DIS_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_VCORE_POR_DIS_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS_POS) /**< \ \ \ \ \ - LP_CTRL_VCORE_POR_DIS_DIS \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_VCORE_POR_DIS_EN \ - ((uint32_t)0x1UL) /**< LP_CTRL_VCORE_POR_DIS_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_VCORE_POR_DIS_EN \ - (MXC_V_PWRSEQ_LP_CTRL_VCORE_POR_DIS_EN \ - << MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS_POS) /**< \ \ \ \ \ - LP_CTRL_VCORE_POR_DIS_EN \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_LDO_DIS_POS 16 /**< LP_CTRL_LDO_DIS Position */ -#define MXC_F_PWRSEQ_LP_CTRL_LDO_DIS \ - ((uint32_t)(0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_LDO_DIS_POS)) /**< LP_CTRL_LDO_DIS \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_LDO_DIS_EN \ - ((uint32_t)0x0UL) /**< LP_CTRL_LDO_DIS_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_LDO_DIS_EN \ - (MXC_V_PWRSEQ_LP_CTRL_LDO_DIS_EN \ - << MXC_F_PWRSEQ_LP_CTRL_LDO_DIS_POS) /**< LP_CTRL_LDO_DIS_EN Setting \ - * \ \ - * \ \ \ - * \ \ \ \ - * \ \ \ \ \ - */ -#define MXC_V_PWRSEQ_LP_CTRL_LDO_DIS_DIS \ - ((uint32_t)0x1UL) /**< LP_CTRL_LDO_DIS_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_LDO_DIS_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_LDO_DIS_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_LDO_DIS_POS) /**< LP_CTRL_LDO_DIS_DIS Setting \ - * \ \ - * \ \ \ - * \ \ \ \ - * \ \ \ \ \ - */ - -#define MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_POS \ - 20 /**< LP_CTRL_VCORE_SVM_DIS Position */ -#define MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_POS)) /**< \ \ \ \ \ - LP_CTRL_VCORE_SVM_DIS \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_EN \ - ((uint32_t)0x0UL) /**< LP_CTRL_VCORE_SVM_DIS_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_EN \ - (MXC_V_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_EN \ - << MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_POS) /**< \ \ \ \ \ - LP_CTRL_VCORE_SVM_DIS_EN \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_DIS \ - ((uint32_t)0x1UL) /**< LP_CTRL_VCORE_SVM_DIS_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_POS) /**< \ \ \ \ \ - LP_CTRL_VCORE_SVM_DIS_DIS \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_POS \ - 25 /**< LP_CTRL_VDDIO_POR_DIS Position */ -#define MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_POS)) /**< \ \ \ \ \ - LP_CTRL_VDDIO_POR_DIS \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_EN \ - ((uint32_t)0x0UL) /**< LP_CTRL_VDDIO_POR_DIS_EN Value */ -#define MXC_S_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_EN \ - (MXC_V_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_EN \ - << MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_POS) /**< \ \ \ \ \ - LP_CTRL_VDDIO_POR_DIS_EN \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_DIS \ - ((uint32_t)0x1UL) /**< LP_CTRL_VDDIO_POR_DIS_DIS Value */ -#define MXC_S_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_DIS \ - (MXC_V_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_DIS \ - << MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_POS) /**< \ \ \ \ \ - LP_CTRL_VDDIO_POR_DIS_DIS \ - \ \ \ \ Setting */ - -/** - * pwrseq_registers - * Low Power Mode Wakeup Flags for GPIO0 - */ -#define MXC_F_PWRSEQ_LP_WAKEFL_WAKEST_POS 0 /**< LP_WAKEFL_WAKEST Position */ -#define MXC_F_PWRSEQ_LP_WAKEFL_WAKEST \ - ((uint32_t)( \ - 0x3FFFUL \ - << MXC_F_PWRSEQ_LP_WAKEFL_WAKEST_POS)) /**< LP_WAKEFL_WAKEST \ \ - \ \ \ Mask */ - -/** - * pwrseq_registers - * Low Power I/O Wakeup Enable Register 0. This register enables low - * power wakeup functionality for GPIO0. - */ -#define MXC_F_PWRSEQ_LPWK_EN_WAKEEN_POS 0 /**< LPWK_EN_WAKEEN Position */ -#define MXC_F_PWRSEQ_LPWK_EN_WAKEEN \ - ((uint32_t)(0x3FFFUL \ - << MXC_F_PWRSEQ_LPWK_EN_WAKEEN_POS)) /**< LPWK_EN_WAKEEN \ \ - \ \ \ Mask */ - -/** - * pwrseq_registers - * Low Power Memory Shutdown Control. - */ -#define MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF_POS \ - 0 /**< LPMEMSD_SRAM0_OFF Position \ \ \ \ \ - */ -#define MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF_POS)) /**< LPMEMSD_SRAM0_OFF \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LPMEMSD_SRAM0_OFF_NORMAL \ - ((uint32_t)0x0UL) /**< LPMEMSD_SRAM0_OFF_NORMAL Value */ -#define MXC_S_PWRSEQ_LPMEMSD_SRAM0_OFF_NORMAL \ - (MXC_V_PWRSEQ_LPMEMSD_SRAM0_OFF_NORMAL \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF_POS) /**< LPMEMSD_SRAM0_OFF_NORMAL \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LPMEMSD_SRAM0_OFF_SHUTDOWN \ - ((uint32_t)0x1UL) /**< LPMEMSD_SRAM0_OFF_SHUTDOWN Value */ -#define MXC_S_PWRSEQ_LPMEMSD_SRAM0_OFF_SHUTDOWN \ - (MXC_V_PWRSEQ_LPMEMSD_SRAM0_OFF_SHUTDOWN \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF_POS) /**< \ \ \ \ \ - LPMEMSD_SRAM0_OFF_SHUTDOWN \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF_POS \ - 1 /**< LPMEMSD_SRAM1_OFF Position \ \ \ \ \ - */ -#define MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF_POS)) /**< LPMEMSD_SRAM1_OFF \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LPMEMSD_SRAM1_OFF_NORMAL \ - ((uint32_t)0x0UL) /**< LPMEMSD_SRAM1_OFF_NORMAL Value */ -#define MXC_S_PWRSEQ_LPMEMSD_SRAM1_OFF_NORMAL \ - (MXC_V_PWRSEQ_LPMEMSD_SRAM1_OFF_NORMAL \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF_POS) /**< LPMEMSD_SRAM1_OFF_NORMAL \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LPMEMSD_SRAM1_OFF_SHUTDOWN \ - ((uint32_t)0x1UL) /**< LPMEMSD_SRAM1_OFF_SHUTDOWN Value */ -#define MXC_S_PWRSEQ_LPMEMSD_SRAM1_OFF_SHUTDOWN \ - (MXC_V_PWRSEQ_LPMEMSD_SRAM1_OFF_SHUTDOWN \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF_POS) /**< \ \ \ \ \ - LPMEMSD_SRAM1_OFF_SHUTDOWN \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF_POS \ - 2 /**< LPMEMSD_SRAM2_OFF Position \ \ \ \ \ - */ -#define MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF_POS)) /**< LPMEMSD_SRAM2_OFF \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LPMEMSD_SRAM2_OFF_NORMAL \ - ((uint32_t)0x0UL) /**< LPMEMSD_SRAM2_OFF_NORMAL Value */ -#define MXC_S_PWRSEQ_LPMEMSD_SRAM2_OFF_NORMAL \ - (MXC_V_PWRSEQ_LPMEMSD_SRAM2_OFF_NORMAL \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF_POS) /**< LPMEMSD_SRAM2_OFF_NORMAL \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LPMEMSD_SRAM2_OFF_SHUTDOWN \ - ((uint32_t)0x1UL) /**< LPMEMSD_SRAM2_OFF_SHUTDOWN Value */ -#define MXC_S_PWRSEQ_LPMEMSD_SRAM2_OFF_SHUTDOWN \ - (MXC_V_PWRSEQ_LPMEMSD_SRAM2_OFF_SHUTDOWN \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF_POS) /**< \ \ \ \ \ - LPMEMSD_SRAM2_OFF_SHUTDOWN \ - \ \ \ \ Setting */ - -#define MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF_POS \ - 3 /**< LPMEMSD_SRAM3_OFF Position \ \ \ \ \ - */ -#define MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF_POS)) /**< LPMEMSD_SRAM3_OFF \ - \ \ \ \ Mask */ -#define MXC_V_PWRSEQ_LPMEMSD_SRAM3_OFF_NORMAL \ - ((uint32_t)0x0UL) /**< LPMEMSD_SRAM3_OFF_NORMAL Value */ -#define MXC_S_PWRSEQ_LPMEMSD_SRAM3_OFF_NORMAL \ - (MXC_V_PWRSEQ_LPMEMSD_SRAM3_OFF_NORMAL \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF_POS) /**< LPMEMSD_SRAM3_OFF_NORMAL \ - \ \ \ \ Setting */ -#define MXC_V_PWRSEQ_LPMEMSD_SRAM3_OFF_SHUTDOWN \ - ((uint32_t)0x1UL) /**< LPMEMSD_SRAM3_OFF_SHUTDOWN Value */ -#define MXC_S_PWRSEQ_LPMEMSD_SRAM3_OFF_SHUTDOWN \ - (MXC_V_PWRSEQ_LPMEMSD_SRAM3_OFF_SHUTDOWN \ - << MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF_POS) /**< \ \ \ \ \ - LPMEMSD_SRAM3_OFF_SHUTDOWN \ - \ \ \ \ Setting */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _PWRSEQ_REGS_H_ */ +/* Copyright 2019 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* MAX32660 Registers, Bit Masks and Bit Positions for the PWRSEQ Peripheral */ + +#ifndef _PWRSEQ_REGS_H_ +#define _PWRSEQ_REGS_H_ + +/* **** Includes **** */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__ICCARM__) +#pragma system_include +#endif + +#if defined(__CC_ARM) +#pragma anon_unions +#endif + +/* + If types are not defined elsewhere (CMSIS) define them here +*/ +#ifndef __IO +#define __IO volatile +#endif +#ifndef __I +#define __I volatile const +#endif +#ifndef __O +#define __O volatile +#endif +#ifndef __R +#define __R volatile const +#endif + +/* **** Definitions **** */ + +/** + * mxc_pwrseq_regs_t + * Registers, Bit Masks and Bit Positions for the PWRSEQ Peripheral + * Module. + */ + +/** + * pwrseq_registers + * Structure type to access the PWRSEQ Registers. + */ +typedef struct { + __IO uint32_t lp_ctrl; /**< \b 0x00: PWRSEQ LP_CTRL Register */ + __IO uint32_t lp_wakefl; /**< \b 0x04: PWRSEQ LP_WAKEFL + Register */ + __IO uint32_t lpwk_en; /**< \b 0x08: PWRSEQ LPWK_EN Register */ + __R uint32_t rsv_0xc_0x3f[13]; + __IO uint32_t lpmemsd; /**< \b 0x40: PWRSEQ LPMEMSD Register */ +} mxc_pwrseq_regs_t; + +/** + * Register offsets for module PWRSEQ + * PWRSEQ Peripheral Register Offsets from the PWRSEQ Base + */ +#define MXC_R_PWRSEQ_LP_CTRL \ + ((uint32_t)0x00000000UL) /**< Offset from PWRSEQ Base Address: \ \ + \ \ \ 0x0000 */ +#define MXC_R_PWRSEQ_LP_WAKEFL \ + ((uint32_t)0x00000004UL) /**< Offset from PWRSEQ Base Address: \ \ + \ \ \ 0x0004 */ +#define MXC_R_PWRSEQ_LPWK_EN \ + ((uint32_t)0x00000008UL) /**< Offset from PWRSEQ Base Address: \ \ + \ \ \ 0x0008 */ +#define MXC_R_PWRSEQ_LPMEMSD \ + ((uint32_t)0x00000040UL) /**< Offset from PWRSEQ Base Address: \ \ + \ \ \ 0x0040 */ + +/** + * pwrseq_registers + * Low Power Control Register. + */ +#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0_POS \ + 0 /**< LP_CTRL_RAMRET_SEL0 Position */ +#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0 \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0_POS)) /**< \ \ \ \ \ + LP_CTRL_RAMRET_SEL0 \ + \ \ \ \ Mask \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL0_DIS \ + ((uint32_t)0x0UL) /**< LP_CTRL_RAMRET_SEL0_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL0_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL0_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0_POS) /**< LP_CTRL_RAMRET_SEL0_DIS \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL0_EN \ + ((uint32_t)0x1UL) /**< LP_CTRL_RAMRET_SEL0_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL0_EN \ + (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL0_EN \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0_POS) /**< LP_CTRL_RAMRET_SEL0_EN \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1_POS \ + 1 /**< LP_CTRL_RAMRET_SEL1 Position */ +#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1 \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1_POS)) /**< \ \ \ \ \ + LP_CTRL_RAMRET_SEL1 \ + \ \ \ \ Mask \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL1_DIS \ + ((uint32_t)0x0UL) /**< LP_CTRL_RAMRET_SEL1_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL1_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL1_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1_POS) /**< LP_CTRL_RAMRET_SEL1_DIS \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL1_EN \ + ((uint32_t)0x1UL) /**< LP_CTRL_RAMRET_SEL1_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL1_EN \ + (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL1_EN \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1_POS) /**< LP_CTRL_RAMRET_SEL1_EN \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2_POS \ + 2 /**< LP_CTRL_RAMRET_SEL2 Position */ +#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2 \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2_POS)) /**< \ \ \ \ \ + LP_CTRL_RAMRET_SEL2 \ + \ \ \ \ Mask \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL2_DIS \ + ((uint32_t)0x0UL) /**< LP_CTRL_RAMRET_SEL2_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL2_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL2_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2_POS) /**< LP_CTRL_RAMRET_SEL2_DIS \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL2_EN \ + ((uint32_t)0x1UL) /**< LP_CTRL_RAMRET_SEL2_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL2_EN \ + (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL2_EN \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2_POS) /**< LP_CTRL_RAMRET_SEL2_EN \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3_POS \ + 3 /**< LP_CTRL_RAMRET_SEL3 Position */ +#define MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3 \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3_POS)) /**< \ \ \ \ \ + LP_CTRL_RAMRET_SEL3 \ + \ \ \ \ Mask \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL3_DIS \ + ((uint32_t)0x0UL) /**< LP_CTRL_RAMRET_SEL3_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL3_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL3_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3_POS) /**< LP_CTRL_RAMRET_SEL3_DIS \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL3_EN \ + ((uint32_t)0x1UL) /**< LP_CTRL_RAMRET_SEL3_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RAMRET_SEL3_EN \ + (MXC_V_PWRSEQ_LP_CTRL_RAMRET_SEL3_EN \ + << MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3_POS) /**< LP_CTRL_RAMRET_SEL3_EN \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LP_CTRL_OVR_POS 4 /**< LP_CTRL_OVR Position */ +#define MXC_F_PWRSEQ_LP_CTRL_OVR \ + ((uint32_t)(0x3UL << MXC_F_PWRSEQ_LP_CTRL_OVR_POS)) /**< LP_CTRL_OVR \ + Mask */ +#define MXC_V_PWRSEQ_LP_CTRL_OVR_0_9V \ + ((uint32_t)0x0UL) /**< LP_CTRL_OVR_0_9V Value */ +#define MXC_S_PWRSEQ_LP_CTRL_OVR_0_9V \ + (MXC_V_PWRSEQ_LP_CTRL_OVR_0_9V \ + << MXC_F_PWRSEQ_LP_CTRL_OVR_POS) /**< \ + LP_CTRL_OVR_0_9V \ + Setting \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_OVR_1_0V \ + ((uint32_t)0x1UL) /**< LP_CTRL_OVR_1_0V Value */ +#define MXC_S_PWRSEQ_LP_CTRL_OVR_1_0V \ + (MXC_V_PWRSEQ_LP_CTRL_OVR_1_0V \ + << MXC_F_PWRSEQ_LP_CTRL_OVR_POS) /**< \ + LP_CTRL_OVR_1_0V \ + Setting \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_OVR_1_1V \ + ((uint32_t)0x2UL) /**< LP_CTRL_OVR_1_1V Value */ +#define MXC_S_PWRSEQ_LP_CTRL_OVR_1_1V \ + (MXC_V_PWRSEQ_LP_CTRL_OVR_1_1V \ + << MXC_F_PWRSEQ_LP_CTRL_OVR_POS) /**< \ + LP_CTRL_OVR_1_1V \ + Setting \ + */ + +#define MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_POS \ + 6 /**< LP_CTRL_VCORE_DET_BYPASS Position */ +#define MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_POS)) /**< \ + \ \ \ \ \ + LP_CTRL_VCORE_DET_BYPASS \ + \ \ + \ \ \ \ \ + Mask */ +#define MXC_V_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_ENABLED \ + ((uint32_t)0x0UL) /**< LP_CTRL_VCORE_DET_BYPASS_ENABLED Value */ +#define MXC_S_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_ENABLED \ + (MXC_V_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_ENABLED \ + << MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_POS) /**< \ \ \ \ \ + LP_CTRL_VCORE_DET_BYPASS_ENABLED \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_DISABLE \ + ((uint32_t)0x1UL) /**< LP_CTRL_VCORE_DET_BYPASS_DISABLE Value */ +#define MXC_S_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_DISABLE \ + (MXC_V_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_DISABLE \ + << MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS_POS) /**< \ \ \ \ \ + LP_CTRL_VCORE_DET_BYPASS_DISABLE \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LP_CTRL_RETREG_EN_POS \ + 8 /**< LP_CTRL_RETREG_EN Position \ \ \ \ \ + */ +#define MXC_F_PWRSEQ_LP_CTRL_RETREG_EN \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_RETREG_EN_POS)) /**< \ + LP_CTRL_RETREG_EN \ + \ \ \ \ Mask */ +#define MXC_V_PWRSEQ_LP_CTRL_RETREG_EN_DIS \ + ((uint32_t)0x0UL) /**< LP_CTRL_RETREG_EN_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RETREG_EN_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_RETREG_EN_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_RETREG_EN_POS) /**< LP_CTRL_RETREG_EN_DIS \ \ \ + \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_RETREG_EN_EN \ + ((uint32_t)0x1UL) /**< LP_CTRL_RETREG_EN_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_RETREG_EN_EN \ + (MXC_V_PWRSEQ_LP_CTRL_RETREG_EN_EN \ + << MXC_F_PWRSEQ_LP_CTRL_RETREG_EN_POS) /**< LP_CTRL_RETREG_EN_EN \ \ \ + \ \ Setting */ + +#define MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN_POS \ + 10 /**< LP_CTRL_FAST_WK_EN Position */ +#define MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN_POS)) /**< \ \ \ \ \ + LP_CTRL_FAST_WK_EN \ + \ \ \ \ Mask \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_FAST_WK_EN_DIS \ + ((uint32_t)0x0UL) /**< LP_CTRL_FAST_WK_EN_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_FAST_WK_EN_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_FAST_WK_EN_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN_POS) /**< LP_CTRL_FAST_WK_EN_DIS \ \ + \ \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_FAST_WK_EN_EN \ + ((uint32_t)0x1UL) /**< LP_CTRL_FAST_WK_EN_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_FAST_WK_EN_EN \ + (MXC_V_PWRSEQ_LP_CTRL_FAST_WK_EN_EN \ + << MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN_POS) /**< LP_CTRL_FAST_WK_EN_EN \ \ + \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LP_CTRL_BG_OFF_POS 11 /**< LP_CTRL_BG_OFF Position */ +#define MXC_F_PWRSEQ_LP_CTRL_BG_OFF \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_BG_OFF_POS)) /**< LP_CTRL_BG_OFF \ + \ \ \ \ Mask */ +#define MXC_V_PWRSEQ_LP_CTRL_BG_OFF_ON \ + ((uint32_t)0x0UL) /**< LP_CTRL_BG_OFF_ON Value */ +#define MXC_S_PWRSEQ_LP_CTRL_BG_OFF_ON \ + (MXC_V_PWRSEQ_LP_CTRL_BG_OFF_ON \ + << MXC_F_PWRSEQ_LP_CTRL_BG_OFF_POS) /**< LP_CTRL_BG_OFF_ON Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_BG_OFF_OFF \ + ((uint32_t)0x1UL) /**< LP_CTRL_BG_OFF_OFF Value */ +#define MXC_S_PWRSEQ_LP_CTRL_BG_OFF_OFF \ + (MXC_V_PWRSEQ_LP_CTRL_BG_OFF_OFF \ + << MXC_F_PWRSEQ_LP_CTRL_BG_OFF_POS) /**< LP_CTRL_BG_OFF_OFF Setting \ \ + * \ \ + * \ \ \ + * \ \ \ \ + */ + +#define MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS_POS \ + 12 /**< LP_CTRL_VCORE_POR_DIS Position */ +#define MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS_POS)) /**< \ \ \ \ \ + LP_CTRL_VCORE_POR_DIS \ + \ \ \ \ Mask \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_VCORE_POR_DIS_DIS \ + ((uint32_t)0x0UL) /**< LP_CTRL_VCORE_POR_DIS_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_VCORE_POR_DIS_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_VCORE_POR_DIS_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS_POS) /**< \ \ \ \ \ + LP_CTRL_VCORE_POR_DIS_DIS \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_VCORE_POR_DIS_EN \ + ((uint32_t)0x1UL) /**< LP_CTRL_VCORE_POR_DIS_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_VCORE_POR_DIS_EN \ + (MXC_V_PWRSEQ_LP_CTRL_VCORE_POR_DIS_EN \ + << MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS_POS) /**< \ \ \ \ \ + LP_CTRL_VCORE_POR_DIS_EN \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LP_CTRL_LDO_DIS_POS 16 /**< LP_CTRL_LDO_DIS Position */ +#define MXC_F_PWRSEQ_LP_CTRL_LDO_DIS \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_LDO_DIS_POS)) /**< LP_CTRL_LDO_DIS \ + \ \ \ \ Mask */ +#define MXC_V_PWRSEQ_LP_CTRL_LDO_DIS_EN \ + ((uint32_t)0x0UL) /**< LP_CTRL_LDO_DIS_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_LDO_DIS_EN \ + (MXC_V_PWRSEQ_LP_CTRL_LDO_DIS_EN \ + << MXC_F_PWRSEQ_LP_CTRL_LDO_DIS_POS) /**< LP_CTRL_LDO_DIS_EN Setting \ + * \ \ + * \ \ \ + * \ \ \ \ + * \ \ \ \ \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_LDO_DIS_DIS \ + ((uint32_t)0x1UL) /**< LP_CTRL_LDO_DIS_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_LDO_DIS_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_LDO_DIS_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_LDO_DIS_POS) /**< LP_CTRL_LDO_DIS_DIS Setting \ + * \ \ + * \ \ \ + * \ \ \ \ + * \ \ \ \ \ + */ + +#define MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_POS \ + 20 /**< LP_CTRL_VCORE_SVM_DIS Position */ +#define MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_POS)) /**< \ \ \ \ \ + LP_CTRL_VCORE_SVM_DIS \ + \ \ \ \ Mask \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_EN \ + ((uint32_t)0x0UL) /**< LP_CTRL_VCORE_SVM_DIS_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_EN \ + (MXC_V_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_EN \ + << MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_POS) /**< \ \ \ \ \ + LP_CTRL_VCORE_SVM_DIS_EN \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_DIS \ + ((uint32_t)0x1UL) /**< LP_CTRL_VCORE_SVM_DIS_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS_POS) /**< \ \ \ \ \ + LP_CTRL_VCORE_SVM_DIS_DIS \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_POS \ + 25 /**< LP_CTRL_VDDIO_POR_DIS Position */ +#define MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_POS)) /**< \ \ \ \ \ + LP_CTRL_VDDIO_POR_DIS \ + \ \ \ \ Mask \ + */ +#define MXC_V_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_EN \ + ((uint32_t)0x0UL) /**< LP_CTRL_VDDIO_POR_DIS_EN Value */ +#define MXC_S_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_EN \ + (MXC_V_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_EN \ + << MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_POS) /**< \ \ \ \ \ + LP_CTRL_VDDIO_POR_DIS_EN \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_DIS \ + ((uint32_t)0x1UL) /**< LP_CTRL_VDDIO_POR_DIS_DIS Value */ +#define MXC_S_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_DIS \ + (MXC_V_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_DIS \ + << MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS_POS) /**< \ \ \ \ \ + LP_CTRL_VDDIO_POR_DIS_DIS \ + \ \ \ \ Setting */ + +/** + * pwrseq_registers + * Low Power Mode Wakeup Flags for GPIO0 + */ +#define MXC_F_PWRSEQ_LP_WAKEFL_WAKEST_POS 0 /**< LP_WAKEFL_WAKEST Position */ +#define MXC_F_PWRSEQ_LP_WAKEFL_WAKEST \ + ((uint32_t)(0x3FFFUL \ + << MXC_F_PWRSEQ_LP_WAKEFL_WAKEST_POS)) /**< \ + LP_WAKEFL_WAKEST \ + \ \ + \ \ \ Mask \ + */ + +/** + * pwrseq_registers + * Low Power I/O Wakeup Enable Register 0. This register enables low + * power wakeup functionality for GPIO0. + */ +#define MXC_F_PWRSEQ_LPWK_EN_WAKEEN_POS 0 /**< LPWK_EN_WAKEEN Position */ +#define MXC_F_PWRSEQ_LPWK_EN_WAKEEN \ + ((uint32_t)(0x3FFFUL \ + << MXC_F_PWRSEQ_LPWK_EN_WAKEEN_POS)) /**< \ + LPWK_EN_WAKEEN \ + \ \ + \ \ \ Mask \ + */ + +/** + * pwrseq_registers + * Low Power Memory Shutdown Control. + */ +#define MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF_POS \ + 0 /**< LPMEMSD_SRAM0_OFF Position \ \ \ \ \ + */ +#define MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF_POS)) /**< \ + LPMEMSD_SRAM0_OFF \ + \ \ \ \ Mask */ +#define MXC_V_PWRSEQ_LPMEMSD_SRAM0_OFF_NORMAL \ + ((uint32_t)0x0UL) /**< LPMEMSD_SRAM0_OFF_NORMAL Value */ +#define MXC_S_PWRSEQ_LPMEMSD_SRAM0_OFF_NORMAL \ + (MXC_V_PWRSEQ_LPMEMSD_SRAM0_OFF_NORMAL \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF_POS) /**< LPMEMSD_SRAM0_OFF_NORMAL \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LPMEMSD_SRAM0_OFF_SHUTDOWN \ + ((uint32_t)0x1UL) /**< LPMEMSD_SRAM0_OFF_SHUTDOWN Value */ +#define MXC_S_PWRSEQ_LPMEMSD_SRAM0_OFF_SHUTDOWN \ + (MXC_V_PWRSEQ_LPMEMSD_SRAM0_OFF_SHUTDOWN \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF_POS) /**< \ \ \ \ \ + LPMEMSD_SRAM0_OFF_SHUTDOWN \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF_POS \ + 1 /**< LPMEMSD_SRAM1_OFF Position \ \ \ \ \ + */ +#define MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF_POS)) /**< \ + LPMEMSD_SRAM1_OFF \ + \ \ \ \ Mask */ +#define MXC_V_PWRSEQ_LPMEMSD_SRAM1_OFF_NORMAL \ + ((uint32_t)0x0UL) /**< LPMEMSD_SRAM1_OFF_NORMAL Value */ +#define MXC_S_PWRSEQ_LPMEMSD_SRAM1_OFF_NORMAL \ + (MXC_V_PWRSEQ_LPMEMSD_SRAM1_OFF_NORMAL \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF_POS) /**< LPMEMSD_SRAM1_OFF_NORMAL \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LPMEMSD_SRAM1_OFF_SHUTDOWN \ + ((uint32_t)0x1UL) /**< LPMEMSD_SRAM1_OFF_SHUTDOWN Value */ +#define MXC_S_PWRSEQ_LPMEMSD_SRAM1_OFF_SHUTDOWN \ + (MXC_V_PWRSEQ_LPMEMSD_SRAM1_OFF_SHUTDOWN \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF_POS) /**< \ \ \ \ \ + LPMEMSD_SRAM1_OFF_SHUTDOWN \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF_POS \ + 2 /**< LPMEMSD_SRAM2_OFF Position \ \ \ \ \ + */ +#define MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF_POS)) /**< \ + LPMEMSD_SRAM2_OFF \ + \ \ \ \ Mask */ +#define MXC_V_PWRSEQ_LPMEMSD_SRAM2_OFF_NORMAL \ + ((uint32_t)0x0UL) /**< LPMEMSD_SRAM2_OFF_NORMAL Value */ +#define MXC_S_PWRSEQ_LPMEMSD_SRAM2_OFF_NORMAL \ + (MXC_V_PWRSEQ_LPMEMSD_SRAM2_OFF_NORMAL \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF_POS) /**< LPMEMSD_SRAM2_OFF_NORMAL \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LPMEMSD_SRAM2_OFF_SHUTDOWN \ + ((uint32_t)0x1UL) /**< LPMEMSD_SRAM2_OFF_SHUTDOWN Value */ +#define MXC_S_PWRSEQ_LPMEMSD_SRAM2_OFF_SHUTDOWN \ + (MXC_V_PWRSEQ_LPMEMSD_SRAM2_OFF_SHUTDOWN \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF_POS) /**< \ \ \ \ \ + LPMEMSD_SRAM2_OFF_SHUTDOWN \ + \ \ \ \ Setting */ + +#define MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF_POS \ + 3 /**< LPMEMSD_SRAM3_OFF Position \ \ \ \ \ + */ +#define MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF \ + ((uint32_t)(0x1UL \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF_POS)) /**< \ + LPMEMSD_SRAM3_OFF \ + \ \ \ \ Mask */ +#define MXC_V_PWRSEQ_LPMEMSD_SRAM3_OFF_NORMAL \ + ((uint32_t)0x0UL) /**< LPMEMSD_SRAM3_OFF_NORMAL Value */ +#define MXC_S_PWRSEQ_LPMEMSD_SRAM3_OFF_NORMAL \ + (MXC_V_PWRSEQ_LPMEMSD_SRAM3_OFF_NORMAL \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF_POS) /**< LPMEMSD_SRAM3_OFF_NORMAL \ + \ \ \ \ Setting */ +#define MXC_V_PWRSEQ_LPMEMSD_SRAM3_OFF_SHUTDOWN \ + ((uint32_t)0x1UL) /**< LPMEMSD_SRAM3_OFF_SHUTDOWN Value */ +#define MXC_S_PWRSEQ_LPMEMSD_SRAM3_OFF_SHUTDOWN \ + (MXC_V_PWRSEQ_LPMEMSD_SRAM3_OFF_SHUTDOWN \ + << MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF_POS) /**< \ \ \ \ \ + LPMEMSD_SRAM3_OFF_SHUTDOWN \ + \ \ \ \ Setting */ + +#ifdef __cplusplus +} +#endif + +#endif /* _PWRSEQ_REGS_H_ */ diff --git a/chip/max32660/registers.h b/chip/max32660/registers.h index e444888fa0..72118bf744 100644 --- a/chip/max32660/registers.h +++ b/chip/max32660/registers.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -72,9 +72,8 @@ extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ #ifndef PeripheralClock -#define PeripheralClock \ - (SystemCoreClock / \ - 2) /*!< Peripheral Clock Frequency \ +#define PeripheralClock \ + (SystemCoreClock / 2) /*!< Peripheral Clock Frequency \ */ #endif @@ -173,14 +172,17 @@ extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ #define MXC_BASE_TMR2 ((uint32_t)0x40012000UL) #define MXC_TMR2 ((mxc_tmr_regs_t *)MXC_BASE_TMR2) -#define MXC_TMR_GET_IRQ(i) \ - (IRQn_Type)((i) == 0 ? \ - TMR0_IRQn : \ - (i) == 1 ? TMR1_IRQn : (i) == 2 ? TMR2_IRQn : 0) +#define MXC_TMR_GET_IRQ(i) \ + (IRQn_Type)((i) == 0 ? TMR0_IRQn : \ + (i) == 1 ? TMR1_IRQn : \ + (i) == 2 ? TMR2_IRQn : \ + 0) #define MXC_TMR_GET_BASE(i) \ ((i) == 0 ? MXC_BASE_TMR0 : \ - (i) == 1 ? MXC_BASE_TMR1 : (i) == 2 ? MXC_BASE_TMR2 : 0) + (i) == 1 ? MXC_BASE_TMR1 : \ + (i) == 2 ? MXC_BASE_TMR2 : \ + 0) #define MXC_TMR_GET_TMR(i) \ ((i) == 0 ? MXC_TMR0 : (i) == 1 ? MXC_TMR1 : (i) == 2 ? MXC_TMR2 : 0) diff --git a/chip/max32660/system_chip.c b/chip/max32660/system_chip.c index 07127dc8c5..f63e22dc26 100644 --- a/chip/max32660/system_chip.c +++ b/chip/max32660/system_chip.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,14 +9,14 @@ #include "common.h" #include "console.h" #include "cpu.h" +#include "gcr_regs.h" #include "host_command.h" #include "panic.h" +#include "registers.h" #include "system.h" #include "task.h" #include "timer.h" #include "util.h" -#include "registers.h" -#include "gcr_regs.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) diff --git a/chip/max32660/tmr_regs.h b/chip/max32660/tmr_regs.h index 946cacbc50..ab3ac5c5ed 100644 --- a/chip/max32660/tmr_regs.h +++ b/chip/max32660/tmr_regs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -42,11 +42,11 @@ extern "C" { * Structure type to access the TMR Registers. */ typedef struct { - __IO uint32_t cnt; /**< \b 0x00:<\tt> TMR CNT Register */ - __IO uint32_t cmp; /**< \b 0x04:<\tt> TMR CMP Register */ - __IO uint32_t pwm; /**< \b 0x08:<\tt> TMR PWM Register */ - __IO uint32_t intr; /**< \b 0x0C:<\tt> TMR INTR Register */ - __IO uint32_t cn; /**< \b 0x10:<\tt> TMR CN Register */ + __IO uint32_t cnt; /**< \b 0x00:<\tt> TMR CNT Register */ + __IO uint32_t cmp; /**< \b 0x04:<\tt> TMR CMP Register */ + __IO uint32_t pwm; /**< \b 0x08:<\tt> TMR PWM Register */ + __IO uint32_t intr; /**< \b 0x0C:<\tt> TMR INTR Register */ + __IO uint32_t cn; /**< \b 0x10:<\tt> TMR CN Register */ __IO uint32_t nolcmp; /**< \b 0x14:<\tt> TMR NOLCMP Register */ } mxc_tmr_regs_t; @@ -54,23 +54,23 @@ typedef struct { * TMR Peripheral Register Offsets from the TMR Base Peripheral * Address. */ -#define MXC_R_TMR_CNT \ - ((uint32_t)0x00000000UL) /**< Offset from TMR Base Address: \ +#define MXC_R_TMR_CNT \ + ((uint32_t)0x00000000UL) /**< Offset from TMR Base Address: \ 0x0x000 */ -#define MXC_R_TMR_CMP \ - ((uint32_t)0x00000004UL) /**< Offset from TMR Base Address: \ +#define MXC_R_TMR_CMP \ + ((uint32_t)0x00000004UL) /**< Offset from TMR Base Address: \ 0x0x004 */ -#define MXC_R_TMR_PWM \ - ((uint32_t)0x00000008UL) /**< Offset from TMR Base Address: \ +#define MXC_R_TMR_PWM \ + ((uint32_t)0x00000008UL) /**< Offset from TMR Base Address: \ 0x0x008 */ -#define MXC_R_TMR_INTR \ - ((uint32_t)0x0000000CUL) /**< Offset from TMR Base Address: \ +#define MXC_R_TMR_INTR \ + ((uint32_t)0x0000000CUL) /**< Offset from TMR Base Address: \ 0x0x00C */ -#define MXC_R_TMR_CN \ - ((uint32_t)0x00000010UL) /**< Offset from TMR Base Address: \ +#define MXC_R_TMR_CN \ + ((uint32_t)0x00000010UL) /**< Offset from TMR Base Address: \ 0x0x010 */ -#define MXC_R_TMR_NOLCMP \ - ((uint32_t)0x00000014UL) /**< Offset from TMR Base Address: \ +#define MXC_R_TMR_NOLCMP \ + ((uint32_t)0x00000014UL) /**< Offset from TMR Base Address: \ 0x0x014 */ /** @@ -78,199 +78,231 @@ typedef struct { * clears the associated interrupt. */ #define MXC_F_TMR_INTR_IRQ_CLR_POS 0 /**< INTR_IRQ_CLR Position */ -#define MXC_F_TMR_INTR_IRQ_CLR \ - ((uint32_t)(0x1UL \ - << MXC_F_TMR_INTR_IRQ_CLR_POS)) /**< INTR_IRQ_CLR Mask */ +#define MXC_F_TMR_INTR_IRQ_CLR \ + ((uint32_t)(0x1UL << MXC_F_TMR_INTR_IRQ_CLR_POS)) /**< INTR_IRQ_CLR \ + Mask */ /** * Timer Control Register. */ #define MXC_F_TMR_CN_TMODE_POS 0 /**< CN_TMODE Position */ -#define MXC_F_TMR_CN_TMODE \ +#define MXC_F_TMR_CN_TMODE \ ((uint32_t)(0x7UL << MXC_F_TMR_CN_TMODE_POS)) /**< CN_TMODE Mask */ -#define MXC_V_TMR_CN_TMODE_ONESHOT \ +#define MXC_V_TMR_CN_TMODE_ONESHOT \ ((uint32_t)0x0UL) /**< CN_TMODE_ONESHOT Value */ -#define MXC_S_TMR_CN_TMODE_ONESHOT \ - (MXC_V_TMR_CN_TMODE_ONESHOT \ - << MXC_F_TMR_CN_TMODE_POS) /**< CN_TMODE_ONESHOT Setting */ -#define MXC_V_TMR_CN_TMODE_CONTINUOUS \ +#define MXC_S_TMR_CN_TMODE_ONESHOT \ + (MXC_V_TMR_CN_TMODE_ONESHOT \ + << MXC_F_TMR_CN_TMODE_POS) /**< \ + CN_TMODE_ONESHOT \ + Setting */ +#define MXC_V_TMR_CN_TMODE_CONTINUOUS \ ((uint32_t)0x1UL) /**< CN_TMODE_CONTINUOUS Value */ -#define MXC_S_TMR_CN_TMODE_CONTINUOUS \ - (MXC_V_TMR_CN_TMODE_CONTINUOUS \ - << MXC_F_TMR_CN_TMODE_POS) /**< CN_TMODE_CONTINUOUS Setting */ -#define MXC_V_TMR_CN_TMODE_COUNTER \ +#define MXC_S_TMR_CN_TMODE_CONTINUOUS \ + (MXC_V_TMR_CN_TMODE_CONTINUOUS \ + << MXC_F_TMR_CN_TMODE_POS) /**< \ + CN_TMODE_CONTINUOUS \ + Setting \ + */ +#define MXC_V_TMR_CN_TMODE_COUNTER \ ((uint32_t)0x2UL) /**< CN_TMODE_COUNTER Value */ -#define MXC_S_TMR_CN_TMODE_COUNTER \ - (MXC_V_TMR_CN_TMODE_COUNTER \ - << MXC_F_TMR_CN_TMODE_POS) /**< CN_TMODE_COUNTER Setting */ +#define MXC_S_TMR_CN_TMODE_COUNTER \ + (MXC_V_TMR_CN_TMODE_COUNTER \ + << MXC_F_TMR_CN_TMODE_POS) /**< \ + CN_TMODE_COUNTER \ + Setting */ #define MXC_V_TMR_CN_TMODE_PWM ((uint32_t)0x3UL) /**< CN_TMODE_PWM Value */ -#define MXC_S_TMR_CN_TMODE_PWM \ - (MXC_V_TMR_CN_TMODE_PWM \ - << MXC_F_TMR_CN_TMODE_POS) /**< CN_TMODE_PWM Setting */ -#define MXC_V_TMR_CN_TMODE_CAPTURE \ +#define MXC_S_TMR_CN_TMODE_PWM \ + (MXC_V_TMR_CN_TMODE_PWM << MXC_F_TMR_CN_TMODE_POS) /**< CN_TMODE_PWM \ + Setting */ +#define MXC_V_TMR_CN_TMODE_CAPTURE \ ((uint32_t)0x4UL) /**< CN_TMODE_CAPTURE Value */ -#define MXC_S_TMR_CN_TMODE_CAPTURE \ - (MXC_V_TMR_CN_TMODE_CAPTURE \ - << MXC_F_TMR_CN_TMODE_POS) /**< CN_TMODE_CAPTURE Setting */ -#define MXC_V_TMR_CN_TMODE_COMPARE \ +#define MXC_S_TMR_CN_TMODE_CAPTURE \ + (MXC_V_TMR_CN_TMODE_CAPTURE \ + << MXC_F_TMR_CN_TMODE_POS) /**< \ + CN_TMODE_CAPTURE \ + Setting */ +#define MXC_V_TMR_CN_TMODE_COMPARE \ ((uint32_t)0x5UL) /**< CN_TMODE_COMPARE Value */ -#define MXC_S_TMR_CN_TMODE_COMPARE \ - (MXC_V_TMR_CN_TMODE_COMPARE \ - << MXC_F_TMR_CN_TMODE_POS) /**< CN_TMODE_COMPARE Setting */ -#define MXC_V_TMR_CN_TMODE_GATED \ - ((uint32_t)0x6UL) /**< CN_TMODE_GATED Value \ +#define MXC_S_TMR_CN_TMODE_COMPARE \ + (MXC_V_TMR_CN_TMODE_COMPARE \ + << MXC_F_TMR_CN_TMODE_POS) /**< \ + CN_TMODE_COMPARE \ + Setting */ +#define MXC_V_TMR_CN_TMODE_GATED \ + ((uint32_t)0x6UL) /**< CN_TMODE_GATED Value \ */ #define MXC_S_TMR_CN_TMODE_GATED \ - (MXC_V_TMR_CN_TMODE_GATED \ - << MXC_F_TMR_CN_TMODE_POS) /**< CN_TMODE_GATED Setting */ -#define MXC_V_TMR_CN_TMODE_CAPTURECOMPARE \ + (MXC_V_TMR_CN_TMODE_GATED << MXC_F_TMR_CN_TMODE_POS) /**< \ + CN_TMODE_GATED \ + Setting */ +#define MXC_V_TMR_CN_TMODE_CAPTURECOMPARE \ ((uint32_t)0x7UL) /**< CN_TMODE_CAPTURECOMPARE Value */ -#define MXC_S_TMR_CN_TMODE_CAPTURECOMPARE \ - (MXC_V_TMR_CN_TMODE_CAPTURECOMPARE \ - << MXC_F_TMR_CN_TMODE_POS) /**< CN_TMODE_CAPTURECOMPARE Setting */ +#define MXC_S_TMR_CN_TMODE_CAPTURECOMPARE \ + (MXC_V_TMR_CN_TMODE_CAPTURECOMPARE \ + << MXC_F_TMR_CN_TMODE_POS) /**< \ + CN_TMODE_CAPTURECOMPARE \ + Setting \ + */ #define MXC_F_TMR_CN_PRES_POS 3 /**< CN_PRES Position */ -#define MXC_F_TMR_CN_PRES \ +#define MXC_F_TMR_CN_PRES \ ((uint32_t)(0x7UL << MXC_F_TMR_CN_PRES_POS)) /**< CN_PRES Mask */ -#define MXC_V_TMR_CN_PRES_DIV1 ((uint32_t)0x0UL) /**< CN_PRES_DIV1 Value */ -#define MXC_S_TMR_CN_PRES_DIV1 \ - (MXC_V_TMR_CN_PRES_DIV1 \ - << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV1 Setting */ +#define MXC_V_TMR_CN_PRES_DIV1 ((uint32_t)0x0UL) /**< CN_PRES_DIV1 Value */ +#define MXC_S_TMR_CN_PRES_DIV1 \ + (MXC_V_TMR_CN_PRES_DIV1 << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV1 \ + Setting */ #define MXC_V_TMR_CN_PRES_DIV2 ((uint32_t)0x1UL) /**< CN_PRES_DIV2 Value */ -#define MXC_S_TMR_CN_PRES_DIV2 \ - (MXC_V_TMR_CN_PRES_DIV2 \ - << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV2 Setting */ +#define MXC_S_TMR_CN_PRES_DIV2 \ + (MXC_V_TMR_CN_PRES_DIV2 << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV2 \ + Setting */ #define MXC_V_TMR_CN_PRES_DIV4 ((uint32_t)0x2UL) /**< CN_PRES_DIV4 Value */ -#define MXC_S_TMR_CN_PRES_DIV4 \ - (MXC_V_TMR_CN_PRES_DIV4 \ - << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV4 Setting */ +#define MXC_S_TMR_CN_PRES_DIV4 \ + (MXC_V_TMR_CN_PRES_DIV4 << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV4 \ + Setting */ #define MXC_V_TMR_CN_PRES_DIV8 ((uint32_t)0x3UL) /**< CN_PRES_DIV8 Value */ -#define MXC_S_TMR_CN_PRES_DIV8 \ - (MXC_V_TMR_CN_PRES_DIV8 \ - << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV8 Setting */ +#define MXC_S_TMR_CN_PRES_DIV8 \ + (MXC_V_TMR_CN_PRES_DIV8 << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV8 \ + Setting */ #define MXC_V_TMR_CN_PRES_DIV16 ((uint32_t)0x4UL) /**< CN_PRES_DIV16 Value */ -#define MXC_S_TMR_CN_PRES_DIV16 \ - (MXC_V_TMR_CN_PRES_DIV16 \ - << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV16 Setting */ +#define MXC_S_TMR_CN_PRES_DIV16 \ + (MXC_V_TMR_CN_PRES_DIV16 << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV16 \ + Setting */ #define MXC_V_TMR_CN_PRES_DIV32 ((uint32_t)0x5UL) /**< CN_PRES_DIV32 Value */ -#define MXC_S_TMR_CN_PRES_DIV32 \ - (MXC_V_TMR_CN_PRES_DIV32 \ - << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV32 Setting */ +#define MXC_S_TMR_CN_PRES_DIV32 \ + (MXC_V_TMR_CN_PRES_DIV32 << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV32 \ + Setting */ #define MXC_V_TMR_CN_PRES_DIV64 ((uint32_t)0x6UL) /**< CN_PRES_DIV64 Value */ -#define MXC_S_TMR_CN_PRES_DIV64 \ - (MXC_V_TMR_CN_PRES_DIV64 \ - << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV64 Setting */ -#define MXC_V_TMR_CN_PRES_DIV128 \ - ((uint32_t)0x7UL) /**< CN_PRES_DIV128 Value \ +#define MXC_S_TMR_CN_PRES_DIV64 \ + (MXC_V_TMR_CN_PRES_DIV64 << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV64 \ + Setting */ +#define MXC_V_TMR_CN_PRES_DIV128 \ + ((uint32_t)0x7UL) /**< CN_PRES_DIV128 Value \ */ -#define MXC_S_TMR_CN_PRES_DIV128 \ - (MXC_V_TMR_CN_PRES_DIV128 \ - << MXC_F_TMR_CN_PRES_POS) /**< CN_PRES_DIV128 Setting */ +#define MXC_S_TMR_CN_PRES_DIV128 \ + (MXC_V_TMR_CN_PRES_DIV128 << MXC_F_TMR_CN_PRES_POS) /**< \ + CN_PRES_DIV128 \ + Setting */ #define MXC_F_TMR_CN_TPOL_POS 6 /**< CN_TPOL Position */ -#define MXC_F_TMR_CN_TPOL \ +#define MXC_F_TMR_CN_TPOL \ ((uint32_t)(0x1UL << MXC_F_TMR_CN_TPOL_POS)) /**< CN_TPOL Mask */ -#define MXC_V_TMR_CN_TPOL_ACTIVEHI \ +#define MXC_V_TMR_CN_TPOL_ACTIVEHI \ ((uint32_t)0x0UL) /**< CN_TPOL_ACTIVEHI Value */ -#define MXC_S_TMR_CN_TPOL_ACTIVEHI \ - (MXC_V_TMR_CN_TPOL_ACTIVEHI \ - << MXC_F_TMR_CN_TPOL_POS) /**< CN_TPOL_ACTIVEHI Setting */ -#define MXC_V_TMR_CN_TPOL_ACTIVELO \ +#define MXC_S_TMR_CN_TPOL_ACTIVEHI \ + (MXC_V_TMR_CN_TPOL_ACTIVEHI \ + << MXC_F_TMR_CN_TPOL_POS) /**< \ + CN_TPOL_ACTIVEHI \ + Setting */ +#define MXC_V_TMR_CN_TPOL_ACTIVELO \ ((uint32_t)0x1UL) /**< CN_TPOL_ACTIVELO Value */ -#define MXC_S_TMR_CN_TPOL_ACTIVELO \ - (MXC_V_TMR_CN_TPOL_ACTIVELO \ - << MXC_F_TMR_CN_TPOL_POS) /**< CN_TPOL_ACTIVELO Setting */ +#define MXC_S_TMR_CN_TPOL_ACTIVELO \ + (MXC_V_TMR_CN_TPOL_ACTIVELO \ + << MXC_F_TMR_CN_TPOL_POS) /**< \ + CN_TPOL_ACTIVELO \ + Setting */ #define MXC_F_TMR_CN_TEN_POS 7 /**< CN_TEN Position */ -#define MXC_F_TMR_CN_TEN \ +#define MXC_F_TMR_CN_TEN \ ((uint32_t)(0x1UL << MXC_F_TMR_CN_TEN_POS)) /**< CN_TEN Mask */ -#define MXC_V_TMR_CN_TEN_DIS ((uint32_t)0x0UL) /**< CN_TEN_DIS Value */ +#define MXC_V_TMR_CN_TEN_DIS ((uint32_t)0x0UL) /**< CN_TEN_DIS Value */ #define MXC_S_TMR_CN_TEN_DIS \ - (MXC_V_TMR_CN_TEN_DIS \ - << MXC_F_TMR_CN_TEN_POS) /**< CN_TEN_DIS Setting */ + (MXC_V_TMR_CN_TEN_DIS << MXC_F_TMR_CN_TEN_POS) /**< CN_TEN_DIS Setting \ + */ #define MXC_V_TMR_CN_TEN_EN ((uint32_t)0x1UL) /**< CN_TEN_EN Value */ -#define MXC_S_TMR_CN_TEN_EN \ - (MXC_V_TMR_CN_TEN_EN << MXC_F_TMR_CN_TEN_POS) /**< CN_TEN_EN Setting \ +#define MXC_S_TMR_CN_TEN_EN \ + (MXC_V_TMR_CN_TEN_EN << MXC_F_TMR_CN_TEN_POS) /**< CN_TEN_EN Setting \ */ #define MXC_F_TMR_CN_PRES3_POS 8 /**< CN_PRES3 Position */ -#define MXC_F_TMR_CN_PRES3 \ +#define MXC_F_TMR_CN_PRES3 \ ((uint32_t)(0x1UL << MXC_F_TMR_CN_PRES3_POS)) /**< CN_PRES3 Mask */ #define MXC_F_TMR_CN_PWMSYNC_POS 9 /**< CN_PWMSYNC Position */ -#define MXC_F_TMR_CN_PWMSYNC \ - ((uint32_t)(0x1UL << MXC_F_TMR_CN_PWMSYNC_POS)) /**< CN_PWMSYNC Mask \ +#define MXC_F_TMR_CN_PWMSYNC \ + ((uint32_t)(0x1UL << MXC_F_TMR_CN_PWMSYNC_POS)) /**< CN_PWMSYNC Mask \ */ -#define MXC_V_TMR_CN_PWMSYNC_DIS \ - ((uint32_t)0x0UL) /**< CN_PWMSYNC_DIS Value \ +#define MXC_V_TMR_CN_PWMSYNC_DIS \ + ((uint32_t)0x0UL) /**< CN_PWMSYNC_DIS Value \ */ -#define MXC_S_TMR_CN_PWMSYNC_DIS \ - (MXC_V_TMR_CN_PWMSYNC_DIS \ - << MXC_F_TMR_CN_PWMSYNC_POS) /**< CN_PWMSYNC_DIS Setting */ +#define MXC_S_TMR_CN_PWMSYNC_DIS \ + (MXC_V_TMR_CN_PWMSYNC_DIS \ + << MXC_F_TMR_CN_PWMSYNC_POS) /**< \ + CN_PWMSYNC_DIS \ + Setting */ #define MXC_V_TMR_CN_PWMSYNC_EN ((uint32_t)0x1UL) /**< CN_PWMSYNC_EN Value */ #define MXC_S_TMR_CN_PWMSYNC_EN \ - (MXC_V_TMR_CN_PWMSYNC_EN \ - << MXC_F_TMR_CN_PWMSYNC_POS) /**< CN_PWMSYNC_EN Setting */ + (MXC_V_TMR_CN_PWMSYNC_EN << MXC_F_TMR_CN_PWMSYNC_POS) /**< \ + CN_PWMSYNC_EN \ + Setting */ #define MXC_F_TMR_CN_NOLHPOL_POS 10 /**< CN_NOLHPOL Position */ -#define MXC_F_TMR_CN_NOLHPOL \ - ((uint32_t)(0x1UL << MXC_F_TMR_CN_NOLHPOL_POS)) /**< CN_NOLHPOL Mask \ +#define MXC_F_TMR_CN_NOLHPOL \ + ((uint32_t)(0x1UL << MXC_F_TMR_CN_NOLHPOL_POS)) /**< CN_NOLHPOL Mask \ */ -#define MXC_V_TMR_CN_NOLHPOL_DIS \ - ((uint32_t)0x0UL) /**< CN_NOLHPOL_DIS Value \ +#define MXC_V_TMR_CN_NOLHPOL_DIS \ + ((uint32_t)0x0UL) /**< CN_NOLHPOL_DIS Value \ */ -#define MXC_S_TMR_CN_NOLHPOL_DIS \ - (MXC_V_TMR_CN_NOLHPOL_DIS \ - << MXC_F_TMR_CN_NOLHPOL_POS) /**< CN_NOLHPOL_DIS Setting */ +#define MXC_S_TMR_CN_NOLHPOL_DIS \ + (MXC_V_TMR_CN_NOLHPOL_DIS \ + << MXC_F_TMR_CN_NOLHPOL_POS) /**< \ + CN_NOLHPOL_DIS \ + Setting */ #define MXC_V_TMR_CN_NOLHPOL_EN ((uint32_t)0x1UL) /**< CN_NOLHPOL_EN Value */ #define MXC_S_TMR_CN_NOLHPOL_EN \ - (MXC_V_TMR_CN_NOLHPOL_EN \ - << MXC_F_TMR_CN_NOLHPOL_POS) /**< CN_NOLHPOL_EN Setting */ + (MXC_V_TMR_CN_NOLHPOL_EN << MXC_F_TMR_CN_NOLHPOL_POS) /**< \ + CN_NOLHPOL_EN \ + Setting */ #define MXC_F_TMR_CN_NOLLPOL_POS 11 /**< CN_NOLLPOL Position */ -#define MXC_F_TMR_CN_NOLLPOL \ - ((uint32_t)(0x1UL << MXC_F_TMR_CN_NOLLPOL_POS)) /**< CN_NOLLPOL Mask \ +#define MXC_F_TMR_CN_NOLLPOL \ + ((uint32_t)(0x1UL << MXC_F_TMR_CN_NOLLPOL_POS)) /**< CN_NOLLPOL Mask \ */ -#define MXC_V_TMR_CN_NOLLPOL_DIS \ - ((uint32_t)0x0UL) /**< CN_NOLLPOL_DIS Value \ +#define MXC_V_TMR_CN_NOLLPOL_DIS \ + ((uint32_t)0x0UL) /**< CN_NOLLPOL_DIS Value \ */ -#define MXC_S_TMR_CN_NOLLPOL_DIS \ - (MXC_V_TMR_CN_NOLLPOL_DIS \ - << MXC_F_TMR_CN_NOLLPOL_POS) /**< CN_NOLLPOL_DIS Setting */ +#define MXC_S_TMR_CN_NOLLPOL_DIS \ + (MXC_V_TMR_CN_NOLLPOL_DIS \ + << MXC_F_TMR_CN_NOLLPOL_POS) /**< \ + CN_NOLLPOL_DIS \ + Setting */ #define MXC_V_TMR_CN_NOLLPOL_EN ((uint32_t)0x1UL) /**< CN_NOLLPOL_EN Value */ #define MXC_S_TMR_CN_NOLLPOL_EN \ - (MXC_V_TMR_CN_NOLLPOL_EN \ - << MXC_F_TMR_CN_NOLLPOL_POS) /**< CN_NOLLPOL_EN Setting */ + (MXC_V_TMR_CN_NOLLPOL_EN << MXC_F_TMR_CN_NOLLPOL_POS) /**< \ + CN_NOLLPOL_EN \ + Setting */ #define MXC_F_TMR_CN_PWMCKBD_POS 12 /**< CN_PWMCKBD Position */ -#define MXC_F_TMR_CN_PWMCKBD \ - ((uint32_t)(0x1UL << MXC_F_TMR_CN_PWMCKBD_POS)) /**< CN_PWMCKBD Mask \ +#define MXC_F_TMR_CN_PWMCKBD \ + ((uint32_t)(0x1UL << MXC_F_TMR_CN_PWMCKBD_POS)) /**< CN_PWMCKBD Mask \ */ -#define MXC_V_TMR_CN_PWMCKBD_DIS \ - ((uint32_t)0x1UL) /**< CN_PWMCKBD_DIS Value \ +#define MXC_V_TMR_CN_PWMCKBD_DIS \ + ((uint32_t)0x1UL) /**< CN_PWMCKBD_DIS Value \ */ -#define MXC_S_TMR_CN_PWMCKBD_DIS \ - (MXC_V_TMR_CN_PWMCKBD_DIS \ - << MXC_F_TMR_CN_PWMCKBD_POS) /**< CN_PWMCKBD_DIS Setting */ +#define MXC_S_TMR_CN_PWMCKBD_DIS \ + (MXC_V_TMR_CN_PWMCKBD_DIS \ + << MXC_F_TMR_CN_PWMCKBD_POS) /**< \ + CN_PWMCKBD_DIS \ + Setting */ #define MXC_V_TMR_CN_PWMCKBD_EN ((uint32_t)0x0UL) /**< CN_PWMCKBD_EN Value */ #define MXC_S_TMR_CN_PWMCKBD_EN \ - (MXC_V_TMR_CN_PWMCKBD_EN \ - << MXC_F_TMR_CN_PWMCKBD_POS) /**< CN_PWMCKBD_EN Setting */ + (MXC_V_TMR_CN_PWMCKBD_EN << MXC_F_TMR_CN_PWMCKBD_POS) /**< \ + CN_PWMCKBD_EN \ + Setting */ /** * Timer Non-Overlapping Compare Register. */ #define MXC_F_TMR_NOLCMP_NOLLCMP_POS 0 /**< NOLCMP_NOLLCMP Position */ #define MXC_F_TMR_NOLCMP_NOLLCMP \ - ((uint32_t)( \ - 0xFFUL \ - << MXC_F_TMR_NOLCMP_NOLLCMP_POS)) /**< NOLCMP_NOLLCMP Mask */ + ((uint32_t)(0xFFUL << MXC_F_TMR_NOLCMP_NOLLCMP_POS)) /**< \ + NOLCMP_NOLLCMP \ + Mask */ #define MXC_F_TMR_NOLCMP_NOLHCMP_POS 8 /**< NOLCMP_NOLHCMP Position */ #define MXC_F_TMR_NOLCMP_NOLHCMP \ - ((uint32_t)( \ - 0xFFUL \ - << MXC_F_TMR_NOLCMP_NOLHCMP_POS)) /**< NOLCMP_NOLHCMP Mask */ + ((uint32_t)(0xFFUL << MXC_F_TMR_NOLCMP_NOLHCMP_POS)) /**< \ + NOLCMP_NOLHCMP \ + Mask */ #ifdef __cplusplus } diff --git a/chip/max32660/uart_chip.c b/chip/max32660/uart_chip.c index c30a6ebd45..ec25d9e476 100644 --- a/chip/max32660/uart_chip.c +++ b/chip/max32660/uart_chip.c @@ -1,21 +1,23 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* MAX32660 Console UART Module for Chrome EC */ -#include +#include "common.h" +#include "gcr_regs.h" +#include "gpio.h" +#include "gpio_regs.h" +#include "registers.h" #include "system.h" #include "task.h" -#include "uart.h" -#include "registers.h" #include "tmr_regs.h" -#include "gpio_regs.h" -#include "common.h" -#include "gcr_regs.h" +#include "uart.h" #include "uart_regs.h" +#include + static int done_uart_init_yet; #ifndef UARTN @@ -34,24 +36,24 @@ static int done_uart_init_yet; #define UART_BAUD 115200 -#define UART_ER_IF \ - (MXC_F_UART_INT_FL_RX_FRAME_ERROR | \ +#define UART_ER_IF \ + (MXC_F_UART_INT_FL_RX_FRAME_ERROR | \ MXC_F_UART_INT_FL_RX_PARITY_ERROR | MXC_F_UART_INT_FL_RX_OVERRUN) -#define UART_ER_IE \ - (MXC_F_UART_INT_EN_RX_FRAME_ERROR | \ +#define UART_ER_IE \ + (MXC_F_UART_INT_EN_RX_FRAME_ERROR | \ MXC_F_UART_INT_EN_RX_PARITY_ERROR | MXC_F_UART_INT_EN_RX_OVERRUN) #define UART_RX_IF (UART_ER_IF | MXC_F_UART_INT_FL_RX_FIFO_THRESH) #define UART_RX_IE (UART_ER_IE | MXC_F_UART_INT_EN_RX_FIFO_THRESH) -#define UART_TX_IF \ - (UART_ER_IF | MXC_F_UART_INT_FL_TX_FIFO_ALMOST_EMPTY | \ +#define UART_TX_IF \ + (UART_ER_IF | MXC_F_UART_INT_FL_TX_FIFO_ALMOST_EMPTY | \ MXC_F_UART_INT_FL_TX_FIFO_THRESH) -#define UART_TX_IE \ - (UART_ER_IE | MXC_F_UART_INT_EN_TX_FIFO_ALMOST_EMPTY | \ +#define UART_TX_IE \ + (UART_ER_IE | MXC_F_UART_INT_EN_TX_FIFO_ALMOST_EMPTY | \ MXC_F_UART_INT_EN_TX_FIFO_THRESH) #define UART_RX_THRESHOLD_LEVEL 1 @@ -221,7 +223,7 @@ int uart_read_char(void) /** * Interrupt handlers for UART */ -void uart_rxtx_interrupt(void) +static void uart_rxtx_interrupt(void) { /* Process the Console Input */ uart_process_input(); @@ -241,19 +243,20 @@ void uart_init(void) gpio_config_module(MODULE_UART, 1); /* Drain FIFOs and enable UART and set configuration */ - MXC_UART->ctrl = (MXC_F_UART_CTRL_ENABLE | MXC_S_UART_CTRL_CHAR_SIZE_8 | 1); + MXC_UART->ctrl = + (MXC_F_UART_CTRL_ENABLE | MXC_S_UART_CTRL_CHAR_SIZE_8 | 1); /* Set the baud rate */ - div = PeripheralClock / (UART_BAUD); // constant part of DIV (i.e. DIV - // * (Baudrate*factor_int)) + div = PeripheralClock / (UART_BAUD); // constant part of DIV (i.e. DIV + // * (Baudrate*factor_int)) do { factor += 1; - baud0 = div >> (7 - factor); // divide by 128,64,32,16 to - // extract integer part - baud1 = ((div << factor) - - (baud0 << 7)); // subtract factor corrected div - - // integer parts + baud0 = div >> (7 - factor); // divide by 128,64,32,16 to + // extract integer part + baud1 = ((div << factor) - (baud0 << 7)); // subtract factor + // corrected div - + // integer parts } while ((baud0 == 0) && (factor < 4)); @@ -261,7 +264,7 @@ void uart_init(void) MXC_UART->baud1 = baud1; MXC_UART->thresh_ctrl = UART_RX_THRESHOLD_LEVEL - << MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH_POS; + << MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH_POS; /* Clear Interrupt Flags */ flags = MXC_UART->int_fl; diff --git a/chip/max32660/uart_regs.h b/chip/max32660/uart_regs.h index a2de0cc0a0..64d4ac5654 100644 --- a/chip/max32660/uart_regs.h +++ b/chip/max32660/uart_regs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -32,15 +32,15 @@ */ typedef struct { __IO uint32_t ctrl; /**< \b 0x00:<\tt> UART CTRL Register */ - __IO uint32_t - thresh_ctrl; /**< \b 0x04:<\tt> UART THRESH_CTRL Register */ + __IO uint32_t thresh_ctrl; /**< \b 0x04:<\tt> UART THRESH_CTRL + Register */ __I uint32_t status; /**< \b 0x08:<\tt> UART STATUS Register */ - __IO uint32_t int_en; /**< \b 0x0C:<\tt> UART INT_EN Register */ - __IO uint32_t int_fl; /**< \b 0x10:<\tt> UART INT_FL Register */ - __IO uint32_t baud0; /**< \b 0x14:<\tt> UART BAUD0 Register */ - __IO uint32_t baud1; /**< \b 0x18:<\tt> UART BAUD1 Register */ - __IO uint32_t fifo; /**< \b 0x1C:<\tt> UART FIFO Register */ - __IO uint32_t dma; /**< \b 0x20:<\tt> UART DMA Register */ + __IO uint32_t int_en; /**< \b 0x0C:<\tt> UART INT_EN Register */ + __IO uint32_t int_fl; /**< \b 0x10:<\tt> UART INT_FL Register */ + __IO uint32_t baud0; /**< \b 0x14:<\tt> UART BAUD0 Register */ + __IO uint32_t baud1; /**< \b 0x18:<\tt> UART BAUD1 Register */ + __IO uint32_t fifo; /**< \b 0x1C:<\tt> UART FIFO Register */ + __IO uint32_t dma; /**< \b 0x20:<\tt> UART DMA Register */ __IO uint32_t tx_fifo; /**< \b 0x24:<\tt> UART TX_FIFO Register */ } mxc_uart_regs_t; @@ -48,630 +48,707 @@ typedef struct { * UART Peripheral Register Offsets from the UART Base Peripheral * Address. */ -#define MXC_R_UART_CTRL \ - ((uint32_t)0x00000000UL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_CTRL \ + ((uint32_t)0x00000000UL) /**< Offset from UART Base Address: \ 0x0x000 */ -#define MXC_R_UART_THRESH_CTRL \ - ((uint32_t)0x00000004UL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_THRESH_CTRL \ + ((uint32_t)0x00000004UL) /**< Offset from UART Base Address: \ 0x0x004 */ -#define MXC_R_UART_STATUS \ - ((uint32_t)0x00000008UL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_STATUS \ + ((uint32_t)0x00000008UL) /**< Offset from UART Base Address: \ 0x0x008 */ -#define MXC_R_UART_INT_EN \ - ((uint32_t)0x0000000CUL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_INT_EN \ + ((uint32_t)0x0000000CUL) /**< Offset from UART Base Address: \ 0x0x00C */ -#define MXC_R_UART_INT_FL \ - ((uint32_t)0x00000010UL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_INT_FL \ + ((uint32_t)0x00000010UL) /**< Offset from UART Base Address: \ 0x0x010 */ -#define MXC_R_UART_BAUD0 \ - ((uint32_t)0x00000014UL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_BAUD0 \ + ((uint32_t)0x00000014UL) /**< Offset from UART Base Address: \ 0x0x014 */ -#define MXC_R_UART_BAUD1 \ - ((uint32_t)0x00000018UL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_BAUD1 \ + ((uint32_t)0x00000018UL) /**< Offset from UART Base Address: \ 0x0x018 */ -#define MXC_R_UART_FIFO \ - ((uint32_t)0x0000001CUL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_FIFO \ + ((uint32_t)0x0000001CUL) /**< Offset from UART Base Address: \ 0x0x01C */ -#define MXC_R_UART_DMA \ - ((uint32_t)0x00000020UL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_DMA \ + ((uint32_t)0x00000020UL) /**< Offset from UART Base Address: \ 0x0x020 */ -#define MXC_R_UART_TX_FIFO \ - ((uint32_t)0x00000024UL) /**< Offset from UART Base Address: \ +#define MXC_R_UART_TX_FIFO \ + ((uint32_t)0x00000024UL) /**< Offset from UART Base Address: \ 0x0x024 */ /** * Control Register. */ #define MXC_F_UART_CTRL_ENABLE_POS 0 /**< CTRL_ENABLE Position */ -#define MXC_F_UART_CTRL_ENABLE \ - ((uint32_t)( \ - 0x1UL << MXC_F_UART_CTRL_ENABLE_POS)) /**< CTRL_ENABLE Mask */ -#define MXC_V_UART_CTRL_ENABLE_DIS \ +#define MXC_F_UART_CTRL_ENABLE \ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_ENABLE_POS)) /**< CTRL_ENABLE \ + Mask */ +#define MXC_V_UART_CTRL_ENABLE_DIS \ ((uint32_t)0x0UL) /**< CTRL_ENABLE_DIS Value */ -#define MXC_S_UART_CTRL_ENABLE_DIS \ - (MXC_V_UART_CTRL_ENABLE_DIS \ - << MXC_F_UART_CTRL_ENABLE_POS) /**< CTRL_ENABLE_DIS Setting */ -#define MXC_V_UART_CTRL_ENABLE_EN \ - ((uint32_t)0x1UL) /**< CTRL_ENABLE_EN Value \ +#define MXC_S_UART_CTRL_ENABLE_DIS \ + (MXC_V_UART_CTRL_ENABLE_DIS \ + << MXC_F_UART_CTRL_ENABLE_POS) /**< \ + CTRL_ENABLE_DIS \ + Setting \ + */ +#define MXC_V_UART_CTRL_ENABLE_EN \ + ((uint32_t)0x1UL) /**< CTRL_ENABLE_EN Value \ */ -#define MXC_S_UART_CTRL_ENABLE_EN \ - (MXC_V_UART_CTRL_ENABLE_EN \ - << MXC_F_UART_CTRL_ENABLE_POS) /**< CTRL_ENABLE_EN Setting */ +#define MXC_S_UART_CTRL_ENABLE_EN \ + (MXC_V_UART_CTRL_ENABLE_EN \ + << MXC_F_UART_CTRL_ENABLE_POS) /**< \ + CTRL_ENABLE_EN \ + Setting \ + */ #define MXC_F_UART_CTRL_PARITY_EN_POS 1 /**< CTRL_PARITY_EN Position */ #define MXC_F_UART_CTRL_PARITY_EN \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_CTRL_PARITY_EN_POS)) /**< CTRL_PARITY_EN Mask */ -#define MXC_V_UART_CTRL_PARITY_EN_DIS \ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_PARITY_EN_POS)) /**< \ + CTRL_PARITY_EN \ + Mask */ +#define MXC_V_UART_CTRL_PARITY_EN_DIS \ ((uint32_t)0x0UL) /**< CTRL_PARITY_EN_DIS Value */ -#define MXC_S_UART_CTRL_PARITY_EN_DIS \ - (MXC_V_UART_CTRL_PARITY_EN_DIS \ - << MXC_F_UART_CTRL_PARITY_EN_POS) /**< CTRL_PARITY_EN_DIS Setting */ -#define MXC_V_UART_CTRL_PARITY_EN_EN \ +#define MXC_S_UART_CTRL_PARITY_EN_DIS \ + (MXC_V_UART_CTRL_PARITY_EN_DIS \ + << MXC_F_UART_CTRL_PARITY_EN_POS) /**< \ + CTRL_PARITY_EN_DIS \ + Setting \ + */ +#define MXC_V_UART_CTRL_PARITY_EN_EN \ ((uint32_t)0x1UL) /**< CTRL_PARITY_EN_EN Value */ -#define MXC_S_UART_CTRL_PARITY_EN_EN \ - (MXC_V_UART_CTRL_PARITY_EN_EN \ - << MXC_F_UART_CTRL_PARITY_EN_POS) /**< CTRL_PARITY_EN_EN Setting */ +#define MXC_S_UART_CTRL_PARITY_EN_EN \ + (MXC_V_UART_CTRL_PARITY_EN_EN \ + << MXC_F_UART_CTRL_PARITY_EN_POS) /**< \ + CTRL_PARITY_EN_EN \ + Setting \ + */ #define MXC_F_UART_CTRL_PARITY_POS 2 /**< CTRL_PARITY Position */ -#define MXC_F_UART_CTRL_PARITY \ - ((uint32_t)( \ - 0x3UL << MXC_F_UART_CTRL_PARITY_POS)) /**< CTRL_PARITY Mask */ -#define MXC_V_UART_CTRL_PARITY_EVEN \ +#define MXC_F_UART_CTRL_PARITY \ + ((uint32_t)(0x3UL << MXC_F_UART_CTRL_PARITY_POS)) /**< CTRL_PARITY \ + Mask */ +#define MXC_V_UART_CTRL_PARITY_EVEN \ ((uint32_t)0x0UL) /**< CTRL_PARITY_EVEN Value */ -#define MXC_S_UART_CTRL_PARITY_EVEN \ - (MXC_V_UART_CTRL_PARITY_EVEN \ - << MXC_F_UART_CTRL_PARITY_POS) /**< CTRL_PARITY_EVEN Setting */ -#define MXC_V_UART_CTRL_PARITY_ODD \ +#define MXC_S_UART_CTRL_PARITY_EVEN \ + (MXC_V_UART_CTRL_PARITY_EVEN \ + << MXC_F_UART_CTRL_PARITY_POS) /**< \ + CTRL_PARITY_EVEN \ + Setting \ + */ +#define MXC_V_UART_CTRL_PARITY_ODD \ ((uint32_t)0x1UL) /**< CTRL_PARITY_ODD Value */ -#define MXC_S_UART_CTRL_PARITY_ODD \ - (MXC_V_UART_CTRL_PARITY_ODD \ - << MXC_F_UART_CTRL_PARITY_POS) /**< CTRL_PARITY_ODD Setting */ -#define MXC_V_UART_CTRL_PARITY_MARK \ +#define MXC_S_UART_CTRL_PARITY_ODD \ + (MXC_V_UART_CTRL_PARITY_ODD \ + << MXC_F_UART_CTRL_PARITY_POS) /**< \ + CTRL_PARITY_ODD \ + Setting \ + */ +#define MXC_V_UART_CTRL_PARITY_MARK \ ((uint32_t)0x2UL) /**< CTRL_PARITY_MARK Value */ -#define MXC_S_UART_CTRL_PARITY_MARK \ - (MXC_V_UART_CTRL_PARITY_MARK \ - << MXC_F_UART_CTRL_PARITY_POS) /**< CTRL_PARITY_MARK Setting */ -#define MXC_V_UART_CTRL_PARITY_SPACE \ +#define MXC_S_UART_CTRL_PARITY_MARK \ + (MXC_V_UART_CTRL_PARITY_MARK \ + << MXC_F_UART_CTRL_PARITY_POS) /**< \ + CTRL_PARITY_MARK \ + Setting \ + */ +#define MXC_V_UART_CTRL_PARITY_SPACE \ ((uint32_t)0x3UL) /**< CTRL_PARITY_SPACE Value */ -#define MXC_S_UART_CTRL_PARITY_SPACE \ - (MXC_V_UART_CTRL_PARITY_SPACE \ - << MXC_F_UART_CTRL_PARITY_POS) /**< CTRL_PARITY_SPACE Setting */ +#define MXC_S_UART_CTRL_PARITY_SPACE \ + (MXC_V_UART_CTRL_PARITY_SPACE \ + << MXC_F_UART_CTRL_PARITY_POS) /**< \ + CTRL_PARITY_SPACE \ + Setting \ + */ #define MXC_F_UART_CTRL_PARMD_POS 4 /**< CTRL_PARMD Position */ -#define MXC_F_UART_CTRL_PARMD \ - ((uint32_t)(0x1UL << MXC_F_UART_CTRL_PARMD_POS)) /**< CTRL_PARMD Mask \ +#define MXC_F_UART_CTRL_PARMD \ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_PARMD_POS)) /**< CTRL_PARMD Mask \ */ #define MXC_V_UART_CTRL_PARMD_1 ((uint32_t)0x0UL) /**< CTRL_PARMD_1 Value */ #define MXC_S_UART_CTRL_PARMD_1 \ - (MXC_V_UART_CTRL_PARMD_1 \ - << MXC_F_UART_CTRL_PARMD_POS) /**< CTRL_PARMD_1 Setting */ + (MXC_V_UART_CTRL_PARMD_1 << MXC_F_UART_CTRL_PARMD_POS) /**< \ + CTRL_PARMD_1 \ + Setting */ #define MXC_V_UART_CTRL_PARMD_0 ((uint32_t)0x1UL) /**< CTRL_PARMD_0 Value */ #define MXC_S_UART_CTRL_PARMD_0 \ - (MXC_V_UART_CTRL_PARMD_0 \ - << MXC_F_UART_CTRL_PARMD_POS) /**< CTRL_PARMD_0 Setting */ + (MXC_V_UART_CTRL_PARMD_0 << MXC_F_UART_CTRL_PARMD_POS) /**< \ + CTRL_PARMD_0 \ + Setting */ #define MXC_F_UART_CTRL_TX_FLUSH_POS 5 /**< CTRL_TX_FLUSH Position */ #define MXC_F_UART_CTRL_TX_FLUSH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_CTRL_TX_FLUSH_POS)) /**< CTRL_TX_FLUSH Mask */ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_TX_FLUSH_POS)) /**< CTRL_TX_FLUSH \ + Mask */ #define MXC_F_UART_CTRL_RX_FLUSH_POS 6 /**< CTRL_RX_FLUSH Position */ #define MXC_F_UART_CTRL_RX_FLUSH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_CTRL_RX_FLUSH_POS)) /**< CTRL_RX_FLUSH Mask */ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_RX_FLUSH_POS)) /**< CTRL_RX_FLUSH \ + Mask */ #define MXC_F_UART_CTRL_BITACC_POS 7 /**< CTRL_BITACC Position */ -#define MXC_F_UART_CTRL_BITACC \ - ((uint32_t)( \ - 0x1UL << MXC_F_UART_CTRL_BITACC_POS)) /**< CTRL_BITACC Mask */ -#define MXC_V_UART_CTRL_BITACC_FRAME \ +#define MXC_F_UART_CTRL_BITACC \ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_BITACC_POS)) /**< CTRL_BITACC \ + Mask */ +#define MXC_V_UART_CTRL_BITACC_FRAME \ ((uint32_t)0x0UL) /**< CTRL_BITACC_FRAME Value */ -#define MXC_S_UART_CTRL_BITACC_FRAME \ - (MXC_V_UART_CTRL_BITACC_FRAME \ - << MXC_F_UART_CTRL_BITACC_POS) /**< CTRL_BITACC_FRAME Setting */ -#define MXC_V_UART_CTRL_BITACC_BIT \ +#define MXC_S_UART_CTRL_BITACC_FRAME \ + (MXC_V_UART_CTRL_BITACC_FRAME \ + << MXC_F_UART_CTRL_BITACC_POS) /**< \ + CTRL_BITACC_FRAME \ + Setting \ + */ +#define MXC_V_UART_CTRL_BITACC_BIT \ ((uint32_t)0x1UL) /**< CTRL_BITACC_BIT Value */ -#define MXC_S_UART_CTRL_BITACC_BIT \ - (MXC_V_UART_CTRL_BITACC_BIT \ - << MXC_F_UART_CTRL_BITACC_POS) /**< CTRL_BITACC_BIT Setting */ +#define MXC_S_UART_CTRL_BITACC_BIT \ + (MXC_V_UART_CTRL_BITACC_BIT \ + << MXC_F_UART_CTRL_BITACC_POS) /**< \ + CTRL_BITACC_BIT \ + Setting \ + */ #define MXC_F_UART_CTRL_CHAR_SIZE_POS 8 /**< CTRL_CHAR_SIZE Position */ #define MXC_F_UART_CTRL_CHAR_SIZE \ - ((uint32_t)( \ - 0x3UL \ - << MXC_F_UART_CTRL_CHAR_SIZE_POS)) /**< CTRL_CHAR_SIZE Mask */ -#define MXC_V_UART_CTRL_CHAR_SIZE_5 \ + ((uint32_t)(0x3UL << MXC_F_UART_CTRL_CHAR_SIZE_POS)) /**< \ + CTRL_CHAR_SIZE \ + Mask */ +#define MXC_V_UART_CTRL_CHAR_SIZE_5 \ ((uint32_t)0x0UL) /**< CTRL_CHAR_SIZE_5 Value */ -#define MXC_S_UART_CTRL_CHAR_SIZE_5 \ - (MXC_V_UART_CTRL_CHAR_SIZE_5 \ - << MXC_F_UART_CTRL_CHAR_SIZE_POS) /**< CTRL_CHAR_SIZE_5 Setting */ -#define MXC_V_UART_CTRL_CHAR_SIZE_6 \ +#define MXC_S_UART_CTRL_CHAR_SIZE_5 \ + (MXC_V_UART_CTRL_CHAR_SIZE_5 \ + << MXC_F_UART_CTRL_CHAR_SIZE_POS) /**< \ + CTRL_CHAR_SIZE_5 \ + Setting \ + */ +#define MXC_V_UART_CTRL_CHAR_SIZE_6 \ ((uint32_t)0x1UL) /**< CTRL_CHAR_SIZE_6 Value */ -#define MXC_S_UART_CTRL_CHAR_SIZE_6 \ - (MXC_V_UART_CTRL_CHAR_SIZE_6 \ - << MXC_F_UART_CTRL_CHAR_SIZE_POS) /**< CTRL_CHAR_SIZE_6 Setting */ -#define MXC_V_UART_CTRL_CHAR_SIZE_7 \ +#define MXC_S_UART_CTRL_CHAR_SIZE_6 \ + (MXC_V_UART_CTRL_CHAR_SIZE_6 \ + << MXC_F_UART_CTRL_CHAR_SIZE_POS) /**< \ + CTRL_CHAR_SIZE_6 \ + Setting \ + */ +#define MXC_V_UART_CTRL_CHAR_SIZE_7 \ ((uint32_t)0x2UL) /**< CTRL_CHAR_SIZE_7 Value */ -#define MXC_S_UART_CTRL_CHAR_SIZE_7 \ - (MXC_V_UART_CTRL_CHAR_SIZE_7 \ - << MXC_F_UART_CTRL_CHAR_SIZE_POS) /**< CTRL_CHAR_SIZE_7 Setting */ -#define MXC_V_UART_CTRL_CHAR_SIZE_8 \ +#define MXC_S_UART_CTRL_CHAR_SIZE_7 \ + (MXC_V_UART_CTRL_CHAR_SIZE_7 \ + << MXC_F_UART_CTRL_CHAR_SIZE_POS) /**< \ + CTRL_CHAR_SIZE_7 \ + Setting \ + */ +#define MXC_V_UART_CTRL_CHAR_SIZE_8 \ ((uint32_t)0x3UL) /**< CTRL_CHAR_SIZE_8 Value */ -#define MXC_S_UART_CTRL_CHAR_SIZE_8 \ - (MXC_V_UART_CTRL_CHAR_SIZE_8 \ - << MXC_F_UART_CTRL_CHAR_SIZE_POS) /**< CTRL_CHAR_SIZE_8 Setting */ +#define MXC_S_UART_CTRL_CHAR_SIZE_8 \ + (MXC_V_UART_CTRL_CHAR_SIZE_8 \ + << MXC_F_UART_CTRL_CHAR_SIZE_POS) /**< \ + CTRL_CHAR_SIZE_8 \ + Setting \ + */ #define MXC_F_UART_CTRL_STOPBITS_POS 10 /**< CTRL_STOPBITS Position */ #define MXC_F_UART_CTRL_STOPBITS \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_CTRL_STOPBITS_POS)) /**< CTRL_STOPBITS Mask */ -#define MXC_V_UART_CTRL_STOPBITS_1 \ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_STOPBITS_POS)) /**< CTRL_STOPBITS \ + Mask */ +#define MXC_V_UART_CTRL_STOPBITS_1 \ ((uint32_t)0x0UL) /**< CTRL_STOPBITS_1 Value */ -#define MXC_S_UART_CTRL_STOPBITS_1 \ - (MXC_V_UART_CTRL_STOPBITS_1 \ - << MXC_F_UART_CTRL_STOPBITS_POS) /**< CTRL_STOPBITS_1 Setting */ -#define MXC_V_UART_CTRL_STOPBITS_1_5 \ +#define MXC_S_UART_CTRL_STOPBITS_1 \ + (MXC_V_UART_CTRL_STOPBITS_1 \ + << MXC_F_UART_CTRL_STOPBITS_POS) /**< \ + CTRL_STOPBITS_1 \ + Setting \ + */ +#define MXC_V_UART_CTRL_STOPBITS_1_5 \ ((uint32_t)0x1UL) /**< CTRL_STOPBITS_1_5 Value */ -#define MXC_S_UART_CTRL_STOPBITS_1_5 \ - (MXC_V_UART_CTRL_STOPBITS_1_5 \ - << MXC_F_UART_CTRL_STOPBITS_POS) /**< CTRL_STOPBITS_1_5 Setting */ +#define MXC_S_UART_CTRL_STOPBITS_1_5 \ + (MXC_V_UART_CTRL_STOPBITS_1_5 \ + << MXC_F_UART_CTRL_STOPBITS_POS) /**< \ + CTRL_STOPBITS_1_5 \ + Setting \ + */ #define MXC_F_UART_CTRL_FLOW_CTRL_POS 11 /**< CTRL_FLOW_CTRL Position */ #define MXC_F_UART_CTRL_FLOW_CTRL \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_CTRL_FLOW_CTRL_POS)) /**< CTRL_FLOW_CTRL Mask */ -#define MXC_V_UART_CTRL_FLOW_CTRL_EN \ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_FLOW_CTRL_POS)) /**< \ + CTRL_FLOW_CTRL \ + Mask */ +#define MXC_V_UART_CTRL_FLOW_CTRL_EN \ ((uint32_t)0x1UL) /**< CTRL_FLOW_CTRL_EN Value */ -#define MXC_S_UART_CTRL_FLOW_CTRL_EN \ - (MXC_V_UART_CTRL_FLOW_CTRL_EN \ - << MXC_F_UART_CTRL_FLOW_CTRL_POS) /**< CTRL_FLOW_CTRL_EN Setting */ -#define MXC_V_UART_CTRL_FLOW_CTRL_DIS \ +#define MXC_S_UART_CTRL_FLOW_CTRL_EN \ + (MXC_V_UART_CTRL_FLOW_CTRL_EN \ + << MXC_F_UART_CTRL_FLOW_CTRL_POS) /**< \ + CTRL_FLOW_CTRL_EN \ + Setting \ + */ +#define MXC_V_UART_CTRL_FLOW_CTRL_DIS \ ((uint32_t)0x0UL) /**< CTRL_FLOW_CTRL_DIS Value */ -#define MXC_S_UART_CTRL_FLOW_CTRL_DIS \ - (MXC_V_UART_CTRL_FLOW_CTRL_DIS \ - << MXC_F_UART_CTRL_FLOW_CTRL_POS) /**< CTRL_FLOW_CTRL_DIS Setting */ +#define MXC_S_UART_CTRL_FLOW_CTRL_DIS \ + (MXC_V_UART_CTRL_FLOW_CTRL_DIS \ + << MXC_F_UART_CTRL_FLOW_CTRL_POS) /**< \ + CTRL_FLOW_CTRL_DIS \ + Setting \ + */ #define MXC_F_UART_CTRL_FLOW_POL_POS 12 /**< CTRL_FLOW_POL Position */ #define MXC_F_UART_CTRL_FLOW_POL \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_CTRL_FLOW_POL_POS)) /**< CTRL_FLOW_POL Mask */ -#define MXC_V_UART_CTRL_FLOW_POL_0 \ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_FLOW_POL_POS)) /**< CTRL_FLOW_POL \ + Mask */ +#define MXC_V_UART_CTRL_FLOW_POL_0 \ ((uint32_t)0x0UL) /**< CTRL_FLOW_POL_0 Value */ -#define MXC_S_UART_CTRL_FLOW_POL_0 \ - (MXC_V_UART_CTRL_FLOW_POL_0 \ - << MXC_F_UART_CTRL_FLOW_POL_POS) /**< CTRL_FLOW_POL_0 Setting */ -#define MXC_V_UART_CTRL_FLOW_POL_1 \ +#define MXC_S_UART_CTRL_FLOW_POL_0 \ + (MXC_V_UART_CTRL_FLOW_POL_0 \ + << MXC_F_UART_CTRL_FLOW_POL_POS) /**< \ + CTRL_FLOW_POL_0 \ + Setting \ + */ +#define MXC_V_UART_CTRL_FLOW_POL_1 \ ((uint32_t)0x1UL) /**< CTRL_FLOW_POL_1 Value */ -#define MXC_S_UART_CTRL_FLOW_POL_1 \ - (MXC_V_UART_CTRL_FLOW_POL_1 \ - << MXC_F_UART_CTRL_FLOW_POL_POS) /**< CTRL_FLOW_POL_1 Setting */ +#define MXC_S_UART_CTRL_FLOW_POL_1 \ + (MXC_V_UART_CTRL_FLOW_POL_1 \ + << MXC_F_UART_CTRL_FLOW_POL_POS) /**< \ + CTRL_FLOW_POL_1 \ + Setting \ + */ #define MXC_F_UART_CTRL_NULL_MODEM_POS 13 /**< CTRL_NULL_MODEM Position */ -#define MXC_F_UART_CTRL_NULL_MODEM \ - ((uint32_t)( \ - 0x1UL << MXC_F_UART_CTRL_NULL_MODEM_POS)) /**< CTRL_NULL_MODEM \ - Mask */ -#define MXC_V_UART_CTRL_NULL_MODEM_DIS \ +#define MXC_F_UART_CTRL_NULL_MODEM \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_CTRL_NULL_MODEM_POS)) /**< CTRL_NULL_MODEM \ + Mask */ +#define MXC_V_UART_CTRL_NULL_MODEM_DIS \ ((uint32_t)0x0UL) /**< CTRL_NULL_MODEM_DIS Value */ -#define MXC_S_UART_CTRL_NULL_MODEM_DIS \ - (MXC_V_UART_CTRL_NULL_MODEM_DIS \ - << MXC_F_UART_CTRL_NULL_MODEM_POS) /**< CTRL_NULL_MODEM_DIS Setting \ +#define MXC_S_UART_CTRL_NULL_MODEM_DIS \ + (MXC_V_UART_CTRL_NULL_MODEM_DIS \ + << MXC_F_UART_CTRL_NULL_MODEM_POS) /**< CTRL_NULL_MODEM_DIS Setting \ */ -#define MXC_V_UART_CTRL_NULL_MODEM_EN \ +#define MXC_V_UART_CTRL_NULL_MODEM_EN \ ((uint32_t)0x1UL) /**< CTRL_NULL_MODEM_EN Value */ -#define MXC_S_UART_CTRL_NULL_MODEM_EN \ - (MXC_V_UART_CTRL_NULL_MODEM_EN \ +#define MXC_S_UART_CTRL_NULL_MODEM_EN \ + (MXC_V_UART_CTRL_NULL_MODEM_EN \ << MXC_F_UART_CTRL_NULL_MODEM_POS) /**< CTRL_NULL_MODEM_EN Setting */ #define MXC_F_UART_CTRL_BREAK_POS 14 /**< CTRL_BREAK Position */ -#define MXC_F_UART_CTRL_BREAK \ - ((uint32_t)(0x1UL << MXC_F_UART_CTRL_BREAK_POS)) /**< CTRL_BREAK Mask \ +#define MXC_F_UART_CTRL_BREAK \ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_BREAK_POS)) /**< CTRL_BREAK Mask \ */ -#define MXC_V_UART_CTRL_BREAK_DIS \ - ((uint32_t)0x0UL) /**< CTRL_BREAK_DIS Value \ +#define MXC_V_UART_CTRL_BREAK_DIS \ + ((uint32_t)0x0UL) /**< CTRL_BREAK_DIS Value \ */ -#define MXC_S_UART_CTRL_BREAK_DIS \ - (MXC_V_UART_CTRL_BREAK_DIS \ - << MXC_F_UART_CTRL_BREAK_POS) /**< CTRL_BREAK_DIS Setting */ +#define MXC_S_UART_CTRL_BREAK_DIS \ + (MXC_V_UART_CTRL_BREAK_DIS \ + << MXC_F_UART_CTRL_BREAK_POS) /**< \ + CTRL_BREAK_DIS \ + Setting */ #define MXC_V_UART_CTRL_BREAK_EN ((uint32_t)0x1UL) /**< CTRL_BREAK_EN Value */ -#define MXC_S_UART_CTRL_BREAK_EN \ - (MXC_V_UART_CTRL_BREAK_EN \ - << MXC_F_UART_CTRL_BREAK_POS) /**< CTRL_BREAK_EN Setting */ +#define MXC_S_UART_CTRL_BREAK_EN \ + (MXC_V_UART_CTRL_BREAK_EN \ + << MXC_F_UART_CTRL_BREAK_POS) /**< \ + CTRL_BREAK_EN \ + Setting */ #define MXC_F_UART_CTRL_CLKSEL_POS 15 /**< CTRL_CLKSEL Position */ -#define MXC_F_UART_CTRL_CLKSEL \ - ((uint32_t)( \ - 0x1UL << MXC_F_UART_CTRL_CLKSEL_POS)) /**< CTRL_CLKSEL Mask */ -#define MXC_V_UART_CTRL_CLKSEL_SYSTEM \ +#define MXC_F_UART_CTRL_CLKSEL \ + ((uint32_t)(0x1UL << MXC_F_UART_CTRL_CLKSEL_POS)) /**< CTRL_CLKSEL \ + Mask */ +#define MXC_V_UART_CTRL_CLKSEL_SYSTEM \ ((uint32_t)0x0UL) /**< CTRL_CLKSEL_SYSTEM Value */ -#define MXC_S_UART_CTRL_CLKSEL_SYSTEM \ - (MXC_V_UART_CTRL_CLKSEL_SYSTEM \ - << MXC_F_UART_CTRL_CLKSEL_POS) /**< CTRL_CLKSEL_SYSTEM Setting */ -#define MXC_V_UART_CTRL_CLKSEL_ALTERNATE \ +#define MXC_S_UART_CTRL_CLKSEL_SYSTEM \ + (MXC_V_UART_CTRL_CLKSEL_SYSTEM \ + << MXC_F_UART_CTRL_CLKSEL_POS) /**< \ + CTRL_CLKSEL_SYSTEM \ + Setting \ + */ +#define MXC_V_UART_CTRL_CLKSEL_ALTERNATE \ ((uint32_t)0x1UL) /**< CTRL_CLKSEL_ALTERNATE Value */ -#define MXC_S_UART_CTRL_CLKSEL_ALTERNATE \ - (MXC_V_UART_CTRL_CLKSEL_ALTERNATE \ - << MXC_F_UART_CTRL_CLKSEL_POS) /**< CTRL_CLKSEL_ALTERNATE Setting */ +#define MXC_S_UART_CTRL_CLKSEL_ALTERNATE \ + (MXC_V_UART_CTRL_CLKSEL_ALTERNATE \ + << MXC_F_UART_CTRL_CLKSEL_POS) /**< \ + CTRL_CLKSEL_ALTERNATE \ + Setting \ + */ #define MXC_F_UART_CTRL_RX_TO_POS 16 /**< CTRL_RX_TO Position */ #define MXC_F_UART_CTRL_RX_TO \ - ((uint32_t)( \ - 0xFFUL << MXC_F_UART_CTRL_RX_TO_POS)) /**< CTRL_RX_TO Mask */ + ((uint32_t)(0xFFUL << MXC_F_UART_CTRL_RX_TO_POS)) /**< CTRL_RX_TO Mask \ + */ /** * Threshold Control register. */ -#define MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH_POS \ +#define MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH_POS \ 0 /**< THRESH_CTRL_RX_FIFO_THRESH Position */ -#define MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH \ - ((uint32_t)( \ - 0x3FUL \ - << MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH_POS)) /**< \ - THRESH_CTRL_RX_FIFO_THRESH \ - Mask */ +#define MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH \ + ((uint32_t)(0x3FUL \ + << MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH_POS)) /**< \ + THRESH_CTRL_RX_FIFO_THRESH \ + Mask */ -#define MXC_F_UART_THRESH_CTRL_TX_FIFO_THRESH_POS \ +#define MXC_F_UART_THRESH_CTRL_TX_FIFO_THRESH_POS \ 8 /**< THRESH_CTRL_TX_FIFO_THRESH Position */ -#define MXC_F_UART_THRESH_CTRL_TX_FIFO_THRESH \ - ((uint32_t)( \ - 0x3FUL \ - << MXC_F_UART_THRESH_CTRL_TX_FIFO_THRESH_POS)) /**< \ - THRESH_CTRL_TX_FIFO_THRESH \ - Mask */ +#define MXC_F_UART_THRESH_CTRL_TX_FIFO_THRESH \ + ((uint32_t)(0x3FUL \ + << MXC_F_UART_THRESH_CTRL_TX_FIFO_THRESH_POS)) /**< \ + THRESH_CTRL_TX_FIFO_THRESH \ + Mask */ -#define MXC_F_UART_THRESH_CTRL_RTS_FIFO_THRESH_POS \ +#define MXC_F_UART_THRESH_CTRL_RTS_FIFO_THRESH_POS \ 16 /**< THRESH_CTRL_RTS_FIFO_THRESH Position */ -#define MXC_F_UART_THRESH_CTRL_RTS_FIFO_THRESH \ - ((uint32_t)( \ - 0x3FUL \ - << MXC_F_UART_THRESH_CTRL_RTS_FIFO_THRESH_POS)) /**< \ - THRESH_CTRL_RTS_FIFO_THRESH \ - Mask */ +#define MXC_F_UART_THRESH_CTRL_RTS_FIFO_THRESH \ + ((uint32_t)(0x3FUL \ + << MXC_F_UART_THRESH_CTRL_RTS_FIFO_THRESH_POS)) /**< \ + THRESH_CTRL_RTS_FIFO_THRESH \ + Mask */ /** * Status Register. */ #define MXC_F_UART_STATUS_TX_BUSY_POS 0 /**< STATUS_TX_BUSY Position */ #define MXC_F_UART_STATUS_TX_BUSY \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_STATUS_TX_BUSY_POS)) /**< STATUS_TX_BUSY Mask */ + ((uint32_t)(0x1UL << MXC_F_UART_STATUS_TX_BUSY_POS)) /**< \ + STATUS_TX_BUSY \ + Mask */ #define MXC_F_UART_STATUS_RX_BUSY_POS 1 /**< STATUS_RX_BUSY Position */ #define MXC_F_UART_STATUS_RX_BUSY \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_STATUS_RX_BUSY_POS)) /**< STATUS_RX_BUSY Mask */ + ((uint32_t)(0x1UL << MXC_F_UART_STATUS_RX_BUSY_POS)) /**< \ + STATUS_RX_BUSY \ + Mask */ #define MXC_F_UART_STATUS_PARITY_POS 2 /**< STATUS_PARITY Position */ #define MXC_F_UART_STATUS_PARITY \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_STATUS_PARITY_POS)) /**< STATUS_PARITY Mask */ + ((uint32_t)(0x1UL << MXC_F_UART_STATUS_PARITY_POS)) /**< STATUS_PARITY \ + Mask */ #define MXC_F_UART_STATUS_BREAK_POS 3 /**< STATUS_BREAK Position */ -#define MXC_F_UART_STATUS_BREAK \ - ((uint32_t)(0x1UL \ - << MXC_F_UART_STATUS_BREAK_POS)) /**< STATUS_BREAK Mask */ +#define MXC_F_UART_STATUS_BREAK \ + ((uint32_t)(0x1UL << MXC_F_UART_STATUS_BREAK_POS)) /**< STATUS_BREAK \ + Mask */ #define MXC_F_UART_STATUS_RX_EMPTY_POS 4 /**< STATUS_RX_EMPTY Position */ -#define MXC_F_UART_STATUS_RX_EMPTY \ - ((uint32_t)( \ - 0x1UL << MXC_F_UART_STATUS_RX_EMPTY_POS)) /**< STATUS_RX_EMPTY \ - Mask */ +#define MXC_F_UART_STATUS_RX_EMPTY \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_STATUS_RX_EMPTY_POS)) /**< STATUS_RX_EMPTY \ + Mask */ #define MXC_F_UART_STATUS_RX_FULL_POS 5 /**< STATUS_RX_FULL Position */ #define MXC_F_UART_STATUS_RX_FULL \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_STATUS_RX_FULL_POS)) /**< STATUS_RX_FULL Mask */ + ((uint32_t)(0x1UL << MXC_F_UART_STATUS_RX_FULL_POS)) /**< \ + STATUS_RX_FULL \ + Mask */ #define MXC_F_UART_STATUS_TX_EMPTY_POS 6 /**< STATUS_TX_EMPTY Position */ -#define MXC_F_UART_STATUS_TX_EMPTY \ - ((uint32_t)( \ - 0x1UL << MXC_F_UART_STATUS_TX_EMPTY_POS)) /**< STATUS_TX_EMPTY \ - Mask */ +#define MXC_F_UART_STATUS_TX_EMPTY \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_STATUS_TX_EMPTY_POS)) /**< STATUS_TX_EMPTY \ + Mask */ #define MXC_F_UART_STATUS_TX_FULL_POS 7 /**< STATUS_TX_FULL Position */ #define MXC_F_UART_STATUS_TX_FULL \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_STATUS_TX_FULL_POS)) /**< STATUS_TX_FULL Mask */ + ((uint32_t)(0x1UL << MXC_F_UART_STATUS_TX_FULL_POS)) /**< \ + STATUS_TX_FULL \ + Mask */ -#define MXC_F_UART_STATUS_RX_FIFO_CNT_POS \ - 8 /**< STATUS_RX_FIFO_CNT Position \ +#define MXC_F_UART_STATUS_RX_FIFO_CNT_POS \ + 8 /**< STATUS_RX_FIFO_CNT Position \ */ -#define MXC_F_UART_STATUS_RX_FIFO_CNT \ - ((uint32_t)( \ - 0x3FUL \ - << MXC_F_UART_STATUS_RX_FIFO_CNT_POS)) /**< STATUS_RX_FIFO_CNT \ - Mask */ - -#define MXC_F_UART_STATUS_TX_FIFO_CNT_POS \ - 16 /**< STATUS_TX_FIFO_CNT Position \ +#define MXC_F_UART_STATUS_RX_FIFO_CNT \ + ((uint32_t)(0x3FUL \ + << MXC_F_UART_STATUS_RX_FIFO_CNT_POS)) /**< \ + STATUS_RX_FIFO_CNT \ + Mask */ + +#define MXC_F_UART_STATUS_TX_FIFO_CNT_POS \ + 16 /**< STATUS_TX_FIFO_CNT Position \ */ -#define MXC_F_UART_STATUS_TX_FIFO_CNT \ - ((uint32_t)( \ - 0x3FUL \ - << MXC_F_UART_STATUS_TX_FIFO_CNT_POS)) /**< STATUS_TX_FIFO_CNT \ - Mask */ +#define MXC_F_UART_STATUS_TX_FIFO_CNT \ + ((uint32_t)(0x3FUL \ + << MXC_F_UART_STATUS_TX_FIFO_CNT_POS)) /**< \ + STATUS_TX_FIFO_CNT \ + Mask */ #define MXC_F_UART_STATUS_RX_TO_POS 24 /**< STATUS_RX_TO Position */ -#define MXC_F_UART_STATUS_RX_TO \ - ((uint32_t)(0x1UL \ - << MXC_F_UART_STATUS_RX_TO_POS)) /**< STATUS_RX_TO Mask */ +#define MXC_F_UART_STATUS_RX_TO \ + ((uint32_t)(0x1UL << MXC_F_UART_STATUS_RX_TO_POS)) /**< STATUS_RX_TO \ + Mask */ /** * Interrupt Enable Register. */ -#define MXC_F_UART_INT_EN_RX_FRAME_ERROR_POS \ +#define MXC_F_UART_INT_EN_RX_FRAME_ERROR_POS \ 0 /**< INT_EN_RX_FRAME_ERROR Position */ -#define MXC_F_UART_INT_EN_RX_FRAME_ERROR \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_EN_RX_FRAME_ERROR_POS)) /**< \ - INT_EN_RX_FRAME_ERROR \ - Mask */ +#define MXC_F_UART_INT_EN_RX_FRAME_ERROR \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_EN_RX_FRAME_ERROR_POS)) /**< \ + INT_EN_RX_FRAME_ERROR \ + Mask */ -#define MXC_F_UART_INT_EN_RX_PARITY_ERROR_POS \ +#define MXC_F_UART_INT_EN_RX_PARITY_ERROR_POS \ 1 /**< INT_EN_RX_PARITY_ERROR Position */ -#define MXC_F_UART_INT_EN_RX_PARITY_ERROR \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_EN_RX_PARITY_ERROR_POS)) /**< \ - INT_EN_RX_PARITY_ERROR \ - Mask */ +#define MXC_F_UART_INT_EN_RX_PARITY_ERROR \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_EN_RX_PARITY_ERROR_POS)) /**< \ + INT_EN_RX_PARITY_ERROR \ + Mask */ #define MXC_F_UART_INT_EN_CTS_CHANGE_POS 2 /**< INT_EN_CTS_CHANGE Position */ #define MXC_F_UART_INT_EN_CTS_CHANGE \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_EN_CTS_CHANGE_POS)) /**< INT_EN_CTS_CHANGE \ - Mask */ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_EN_CTS_CHANGE_POS)) /**< \ + INT_EN_CTS_CHANGE \ + Mask */ #define MXC_F_UART_INT_EN_RX_OVERRUN_POS 3 /**< INT_EN_RX_OVERRUN Position */ #define MXC_F_UART_INT_EN_RX_OVERRUN \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_EN_RX_OVERRUN_POS)) /**< INT_EN_RX_OVERRUN \ - Mask */ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_EN_RX_OVERRUN_POS)) /**< \ + INT_EN_RX_OVERRUN \ + Mask */ -#define MXC_F_UART_INT_EN_RX_FIFO_THRESH_POS \ +#define MXC_F_UART_INT_EN_RX_FIFO_THRESH_POS \ 4 /**< INT_EN_RX_FIFO_THRESH Position */ -#define MXC_F_UART_INT_EN_RX_FIFO_THRESH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_EN_RX_FIFO_THRESH_POS)) /**< \ - INT_EN_RX_FIFO_THRESH \ - Mask */ +#define MXC_F_UART_INT_EN_RX_FIFO_THRESH \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_EN_RX_FIFO_THRESH_POS)) /**< \ + INT_EN_RX_FIFO_THRESH \ + Mask */ -#define MXC_F_UART_INT_EN_TX_FIFO_ALMOST_EMPTY_POS \ +#define MXC_F_UART_INT_EN_TX_FIFO_ALMOST_EMPTY_POS \ 5 /**< INT_EN_TX_FIFO_ALMOST_EMPTY Position */ -#define MXC_F_UART_INT_EN_TX_FIFO_ALMOST_EMPTY \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_EN_TX_FIFO_ALMOST_EMPTY_POS)) /**< \ - INT_EN_TX_FIFO_ALMOST_EMPTY \ - Mask */ - -#define MXC_F_UART_INT_EN_TX_FIFO_THRESH_POS \ +#define MXC_F_UART_INT_EN_TX_FIFO_ALMOST_EMPTY \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_EN_TX_FIFO_ALMOST_EMPTY_POS)) /**< \ + INT_EN_TX_FIFO_ALMOST_EMPTY \ + Mask */ + +#define MXC_F_UART_INT_EN_TX_FIFO_THRESH_POS \ 6 /**< INT_EN_TX_FIFO_THRESH Position */ -#define MXC_F_UART_INT_EN_TX_FIFO_THRESH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_EN_TX_FIFO_THRESH_POS)) /**< \ - INT_EN_TX_FIFO_THRESH \ - Mask */ +#define MXC_F_UART_INT_EN_TX_FIFO_THRESH \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_EN_TX_FIFO_THRESH_POS)) /**< \ + INT_EN_TX_FIFO_THRESH \ + Mask */ #define MXC_F_UART_INT_EN_BREAK_POS 7 /**< INT_EN_BREAK Position */ -#define MXC_F_UART_INT_EN_BREAK \ - ((uint32_t)(0x1UL \ - << MXC_F_UART_INT_EN_BREAK_POS)) /**< INT_EN_BREAK Mask */ +#define MXC_F_UART_INT_EN_BREAK \ + ((uint32_t)(0x1UL << MXC_F_UART_INT_EN_BREAK_POS)) /**< INT_EN_BREAK \ + Mask */ #define MXC_F_UART_INT_EN_RX_TIMEOUT_POS 8 /**< INT_EN_RX_TIMEOUT Position */ #define MXC_F_UART_INT_EN_RX_TIMEOUT \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_EN_RX_TIMEOUT_POS)) /**< INT_EN_RX_TIMEOUT \ - Mask */ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_EN_RX_TIMEOUT_POS)) /**< \ + INT_EN_RX_TIMEOUT \ + Mask */ #define MXC_F_UART_INT_EN_LAST_BREAK_POS 9 /**< INT_EN_LAST_BREAK Position */ #define MXC_F_UART_INT_EN_LAST_BREAK \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_EN_LAST_BREAK_POS)) /**< INT_EN_LAST_BREAK \ - Mask */ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_EN_LAST_BREAK_POS)) /**< \ + INT_EN_LAST_BREAK \ + Mask */ /** * Interrupt Status Flags. */ -#define MXC_F_UART_INT_FL_RX_FRAME_ERROR_POS \ +#define MXC_F_UART_INT_FL_RX_FRAME_ERROR_POS \ 0 /**< INT_FL_RX_FRAME_ERROR Position */ -#define MXC_F_UART_INT_FL_RX_FRAME_ERROR \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_FL_RX_FRAME_ERROR_POS)) /**< \ - INT_FL_RX_FRAME_ERROR \ - Mask */ +#define MXC_F_UART_INT_FL_RX_FRAME_ERROR \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_FL_RX_FRAME_ERROR_POS)) /**< \ + INT_FL_RX_FRAME_ERROR \ + Mask */ -#define MXC_F_UART_INT_FL_RX_PARITY_ERROR_POS \ +#define MXC_F_UART_INT_FL_RX_PARITY_ERROR_POS \ 1 /**< INT_FL_RX_PARITY_ERROR Position */ -#define MXC_F_UART_INT_FL_RX_PARITY_ERROR \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_FL_RX_PARITY_ERROR_POS)) /**< \ - INT_FL_RX_PARITY_ERROR \ - Mask */ +#define MXC_F_UART_INT_FL_RX_PARITY_ERROR \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_FL_RX_PARITY_ERROR_POS)) /**< \ + INT_FL_RX_PARITY_ERROR \ + Mask */ #define MXC_F_UART_INT_FL_CTS_CHANGE_POS 2 /**< INT_FL_CTS_CHANGE Position */ #define MXC_F_UART_INT_FL_CTS_CHANGE \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_FL_CTS_CHANGE_POS)) /**< INT_FL_CTS_CHANGE \ - Mask */ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_FL_CTS_CHANGE_POS)) /**< \ + INT_FL_CTS_CHANGE \ + Mask */ #define MXC_F_UART_INT_FL_RX_OVERRUN_POS 3 /**< INT_FL_RX_OVERRUN Position */ #define MXC_F_UART_INT_FL_RX_OVERRUN \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_FL_RX_OVERRUN_POS)) /**< INT_FL_RX_OVERRUN \ - Mask */ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_FL_RX_OVERRUN_POS)) /**< \ + INT_FL_RX_OVERRUN \ + Mask */ -#define MXC_F_UART_INT_FL_RX_FIFO_THRESH_POS \ +#define MXC_F_UART_INT_FL_RX_FIFO_THRESH_POS \ 4 /**< INT_FL_RX_FIFO_THRESH Position */ -#define MXC_F_UART_INT_FL_RX_FIFO_THRESH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_FL_RX_FIFO_THRESH_POS)) /**< \ - INT_FL_RX_FIFO_THRESH \ - Mask */ +#define MXC_F_UART_INT_FL_RX_FIFO_THRESH \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_FL_RX_FIFO_THRESH_POS)) /**< \ + INT_FL_RX_FIFO_THRESH \ + Mask */ -#define MXC_F_UART_INT_FL_TX_FIFO_ALMOST_EMPTY_POS \ +#define MXC_F_UART_INT_FL_TX_FIFO_ALMOST_EMPTY_POS \ 5 /**< INT_FL_TX_FIFO_ALMOST_EMPTY Position */ -#define MXC_F_UART_INT_FL_TX_FIFO_ALMOST_EMPTY \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_FL_TX_FIFO_ALMOST_EMPTY_POS)) /**< \ - INT_FL_TX_FIFO_ALMOST_EMPTY \ - Mask */ - -#define MXC_F_UART_INT_FL_TX_FIFO_THRESH_POS \ +#define MXC_F_UART_INT_FL_TX_FIFO_ALMOST_EMPTY \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_FL_TX_FIFO_ALMOST_EMPTY_POS)) /**< \ + INT_FL_TX_FIFO_ALMOST_EMPTY \ + Mask */ + +#define MXC_F_UART_INT_FL_TX_FIFO_THRESH_POS \ 6 /**< INT_FL_TX_FIFO_THRESH Position */ -#define MXC_F_UART_INT_FL_TX_FIFO_THRESH \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_FL_TX_FIFO_THRESH_POS)) /**< \ - INT_FL_TX_FIFO_THRESH \ - Mask */ +#define MXC_F_UART_INT_FL_TX_FIFO_THRESH \ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_FL_TX_FIFO_THRESH_POS)) /**< \ + INT_FL_TX_FIFO_THRESH \ + Mask */ #define MXC_F_UART_INT_FL_BREAK_POS 7 /**< INT_FL_BREAK Position */ -#define MXC_F_UART_INT_FL_BREAK \ - ((uint32_t)(0x1UL \ - << MXC_F_UART_INT_FL_BREAK_POS)) /**< INT_FL_BREAK Mask */ +#define MXC_F_UART_INT_FL_BREAK \ + ((uint32_t)(0x1UL << MXC_F_UART_INT_FL_BREAK_POS)) /**< INT_FL_BREAK \ + Mask */ #define MXC_F_UART_INT_FL_RX_TIMEOUT_POS 8 /**< INT_FL_RX_TIMEOUT Position */ #define MXC_F_UART_INT_FL_RX_TIMEOUT \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_FL_RX_TIMEOUT_POS)) /**< INT_FL_RX_TIMEOUT \ - Mask */ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_FL_RX_TIMEOUT_POS)) /**< \ + INT_FL_RX_TIMEOUT \ + Mask */ #define MXC_F_UART_INT_FL_LAST_BREAK_POS 9 /**< INT_FL_LAST_BREAK Position */ #define MXC_F_UART_INT_FL_LAST_BREAK \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_UART_INT_FL_LAST_BREAK_POS)) /**< INT_FL_LAST_BREAK \ - Mask */ + ((uint32_t)(0x1UL \ + << MXC_F_UART_INT_FL_LAST_BREAK_POS)) /**< \ + INT_FL_LAST_BREAK \ + Mask */ /** * Baud rate register. Integer portion. */ #define MXC_F_UART_BAUD0_IBAUD_POS 0 /**< BAUD0_IBAUD Position */ -#define MXC_F_UART_BAUD0_IBAUD \ - ((uint32_t)(0xFFFUL \ - << MXC_F_UART_BAUD0_IBAUD_POS)) /**< BAUD0_IBAUD Mask */ +#define MXC_F_UART_BAUD0_IBAUD \ + ((uint32_t)(0xFFFUL << MXC_F_UART_BAUD0_IBAUD_POS)) /**< BAUD0_IBAUD \ + Mask */ #define MXC_F_UART_BAUD0_FACTOR_POS 16 /**< BAUD0_FACTOR Position */ -#define MXC_F_UART_BAUD0_FACTOR \ - ((uint32_t)(0x3UL \ - << MXC_F_UART_BAUD0_FACTOR_POS)) /**< BAUD0_FACTOR Mask */ -#define MXC_V_UART_BAUD0_FACTOR_128 \ +#define MXC_F_UART_BAUD0_FACTOR \ + ((uint32_t)(0x3UL << MXC_F_UART_BAUD0_FACTOR_POS)) /**< BAUD0_FACTOR \ + Mask */ +#define MXC_V_UART_BAUD0_FACTOR_128 \ ((uint32_t)0x0UL) /**< BAUD0_FACTOR_128 Value */ -#define MXC_S_UART_BAUD0_FACTOR_128 \ - (MXC_V_UART_BAUD0_FACTOR_128 \ - << MXC_F_UART_BAUD0_FACTOR_POS) /**< BAUD0_FACTOR_128 Setting */ -#define MXC_V_UART_BAUD0_FACTOR_64 \ +#define MXC_S_UART_BAUD0_FACTOR_128 \ + (MXC_V_UART_BAUD0_FACTOR_128 \ + << MXC_F_UART_BAUD0_FACTOR_POS) /**< \ + BAUD0_FACTOR_128 \ + Setting \ + */ +#define MXC_V_UART_BAUD0_FACTOR_64 \ ((uint32_t)0x1UL) /**< BAUD0_FACTOR_64 Value */ -#define MXC_S_UART_BAUD0_FACTOR_64 \ - (MXC_V_UART_BAUD0_FACTOR_64 \ - << MXC_F_UART_BAUD0_FACTOR_POS) /**< BAUD0_FACTOR_64 Setting */ -#define MXC_V_UART_BAUD0_FACTOR_32 \ +#define MXC_S_UART_BAUD0_FACTOR_64 \ + (MXC_V_UART_BAUD0_FACTOR_64 \ + << MXC_F_UART_BAUD0_FACTOR_POS) /**< \ + BAUD0_FACTOR_64 \ + Setting \ + */ +#define MXC_V_UART_BAUD0_FACTOR_32 \ ((uint32_t)0x2UL) /**< BAUD0_FACTOR_32 Value */ -#define MXC_S_UART_BAUD0_FACTOR_32 \ - (MXC_V_UART_BAUD0_FACTOR_32 \ - << MXC_F_UART_BAUD0_FACTOR_POS) /**< BAUD0_FACTOR_32 Setting */ -#define MXC_V_UART_BAUD0_FACTOR_16 \ +#define MXC_S_UART_BAUD0_FACTOR_32 \ + (MXC_V_UART_BAUD0_FACTOR_32 \ + << MXC_F_UART_BAUD0_FACTOR_POS) /**< \ + BAUD0_FACTOR_32 \ + Setting \ + */ +#define MXC_V_UART_BAUD0_FACTOR_16 \ ((uint32_t)0x3UL) /**< BAUD0_FACTOR_16 Value */ -#define MXC_S_UART_BAUD0_FACTOR_16 \ - (MXC_V_UART_BAUD0_FACTOR_16 \ - << MXC_F_UART_BAUD0_FACTOR_POS) /**< BAUD0_FACTOR_16 Setting */ +#define MXC_S_UART_BAUD0_FACTOR_16 \ + (MXC_V_UART_BAUD0_FACTOR_16 \ + << MXC_F_UART_BAUD0_FACTOR_POS) /**< \ + BAUD0_FACTOR_16 \ + Setting \ + */ /** * Baud rate register. Decimal Setting. */ #define MXC_F_UART_BAUD1_DBAUD_POS 0 /**< BAUD1_DBAUD Position */ -#define MXC_F_UART_BAUD1_DBAUD \ - ((uint32_t)(0xFFFUL \ - << MXC_F_UART_BAUD1_DBAUD_POS)) /**< BAUD1_DBAUD Mask */ +#define MXC_F_UART_BAUD1_DBAUD \ + ((uint32_t)(0xFFFUL << MXC_F_UART_BAUD1_DBAUD_POS)) /**< BAUD1_DBAUD \ + Mask */ /** * FIFO Data buffer. */ #define MXC_F_UART_FIFO_FIFO_POS 0 /**< FIFO_FIFO Position */ -#define MXC_F_UART_FIFO_FIFO \ - ((uint32_t)(0xFFUL << MXC_F_UART_FIFO_FIFO_POS)) /**< FIFO_FIFO Mask \ +#define MXC_F_UART_FIFO_FIFO \ + ((uint32_t)(0xFFUL << MXC_F_UART_FIFO_FIFO_POS)) /**< FIFO_FIFO Mask \ */ - /** * DMA Configuration. */ #define MXC_F_UART_DMA_TDMA_EN_POS 0 /**< DMA_TDMA_EN Position */ -#define MXC_F_UART_DMA_TDMA_EN \ - ((uint32_t)( \ - 0x1UL << MXC_F_UART_DMA_TDMA_EN_POS)) /**< DMA_TDMA_EN Mask */ -#define MXC_V_UART_DMA_TDMA_EN_DIS \ +#define MXC_F_UART_DMA_TDMA_EN \ + ((uint32_t)(0x1UL << MXC_F_UART_DMA_TDMA_EN_POS)) /**< DMA_TDMA_EN \ + Mask */ +#define MXC_V_UART_DMA_TDMA_EN_DIS \ ((uint32_t)0x0UL) /**< DMA_TDMA_EN_DIS Value */ -#define MXC_S_UART_DMA_TDMA_EN_DIS \ - (MXC_V_UART_DMA_TDMA_EN_DIS \ - << MXC_F_UART_DMA_TDMA_EN_POS) /**< DMA_TDMA_EN_DIS Setting */ -#define MXC_V_UART_DMA_TDMA_EN_EN \ - ((uint32_t)0x1UL) /**< DMA_TDMA_EN_EN Value \ +#define MXC_S_UART_DMA_TDMA_EN_DIS \ + (MXC_V_UART_DMA_TDMA_EN_DIS \ + << MXC_F_UART_DMA_TDMA_EN_POS) /**< \ + DMA_TDMA_EN_DIS \ + Setting \ + */ +#define MXC_V_UART_DMA_TDMA_EN_EN \ + ((uint32_t)0x1UL) /**< DMA_TDMA_EN_EN Value \ */ -#define MXC_S_UART_DMA_TDMA_EN_EN \ - (MXC_V_UART_DMA_TDMA_EN_EN \ - << MXC_F_UART_DMA_TDMA_EN_POS) /**< DMA_TDMA_EN_EN Setting */ +#define MXC_S_UART_DMA_TDMA_EN_EN \ + (MXC_V_UART_DMA_TDMA_EN_EN \ + << MXC_F_UART_DMA_TDMA_EN_POS) /**< \ + DMA_TDMA_EN_EN \ + Setting \ + */ #define MXC_F_UART_DMA_RXDMA_EN_POS 1 /**< DMA_RXDMA_EN Position */ -#define MXC_F_UART_DMA_RXDMA_EN \ - ((uint32_t)(0x1UL \ - << MXC_F_UART_DMA_RXDMA_EN_POS)) /**< DMA_RXDMA_EN Mask */ -#define MXC_V_UART_DMA_RXDMA_EN_DIS \ +#define MXC_F_UART_DMA_RXDMA_EN \ + ((uint32_t)(0x1UL << MXC_F_UART_DMA_RXDMA_EN_POS)) /**< DMA_RXDMA_EN \ + Mask */ +#define MXC_V_UART_DMA_RXDMA_EN_DIS \ ((uint32_t)0x0UL) /**< DMA_RXDMA_EN_DIS Value */ -#define MXC_S_UART_DMA_RXDMA_EN_DIS \ - (MXC_V_UART_DMA_RXDMA_EN_DIS \ - << MXC_F_UART_DMA_RXDMA_EN_POS) /**< DMA_RXDMA_EN_DIS Setting */ -#define MXC_V_UART_DMA_RXDMA_EN_EN \ +#define MXC_S_UART_DMA_RXDMA_EN_DIS \ + (MXC_V_UART_DMA_RXDMA_EN_DIS \ + << MXC_F_UART_DMA_RXDMA_EN_POS) /**< \ + DMA_RXDMA_EN_DIS \ + Setting \ + */ +#define MXC_V_UART_DMA_RXDMA_EN_EN \ ((uint32_t)0x1UL) /**< DMA_RXDMA_EN_EN Value */ -#define MXC_S_UART_DMA_RXDMA_EN_EN \ - (MXC_V_UART_DMA_RXDMA_EN_EN \ - << MXC_F_UART_DMA_RXDMA_EN_POS) /**< DMA_RXDMA_EN_EN Setting */ +#define MXC_S_UART_DMA_RXDMA_EN_EN \ + (MXC_V_UART_DMA_RXDMA_EN_EN \ + << MXC_F_UART_DMA_RXDMA_EN_POS) /**< \ + DMA_RXDMA_EN_EN \ + Setting \ + */ #define MXC_F_UART_DMA_TXDMA_LEVEL_POS 8 /**< DMA_TXDMA_LEVEL Position */ -#define MXC_F_UART_DMA_TXDMA_LEVEL \ - ((uint32_t)(0x3FUL \ - << MXC_F_UART_DMA_TXDMA_LEVEL_POS)) /**< DMA_TXDMA_LEVEL \ +#define MXC_F_UART_DMA_TXDMA_LEVEL \ + ((uint32_t)(0x3FUL \ + << MXC_F_UART_DMA_TXDMA_LEVEL_POS)) /**< DMA_TXDMA_LEVEL \ Mask */ #define MXC_F_UART_DMA_RXDMA_LEVEL_POS 16 /**< DMA_RXDMA_LEVEL Position */ -#define MXC_F_UART_DMA_RXDMA_LEVEL \ - ((uint32_t)(0x3FUL \ - << MXC_F_UART_DMA_RXDMA_LEVEL_POS)) /**< DMA_RXDMA_LEVEL \ +#define MXC_F_UART_DMA_RXDMA_LEVEL \ + ((uint32_t)(0x3FUL \ + << MXC_F_UART_DMA_RXDMA_LEVEL_POS)) /**< DMA_RXDMA_LEVEL \ Mask */ /** * Transmit FIFO Status register. */ #define MXC_F_UART_TX_FIFO_DATA_POS 0 /**< TX_FIFO_DATA Position */ -#define MXC_F_UART_TX_FIFO_DATA \ - ((uint32_t)(0x7FUL \ - << MXC_F_UART_TX_FIFO_DATA_POS)) /**< TX_FIFO_DATA Mask */ +#define MXC_F_UART_TX_FIFO_DATA \ + ((uint32_t)(0x7FUL << MXC_F_UART_TX_FIFO_DATA_POS)) /**< TX_FIFO_DATA \ + Mask */ #endif /* _UART_REGS_H_ */ diff --git a/chip/max32660/wdt_chip.c b/chip/max32660/wdt_chip.c index 1c99c798fc..4890c34536 100644 --- a/chip/max32660/wdt_chip.c +++ b/chip/max32660/wdt_chip.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,20 +7,20 @@ #include "clock.h" #include "common.h" +#include "config.h" +#include "console.h" #include "gpio.h" #include "hooks.h" +#include "registers.h" #include "task.h" #include "util.h" #include "watchdog.h" -#include "console.h" -#include "registers.h" -#include "board.h" #include "wdt_regs.h" #define CPUTS(outstr) cputs(CC_COMMAND, outstr) #define CPRINTS(format, args...) cprints(CC_COMMAND, format, ##args) -/* For a System clock of 96MHz, +/* For a System clock of 96MHz, * Time in seconds = 96000000 / 2 * 2^power * Example for MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW29 * Time in seconds = 96000000 / 2 * 2^29 @@ -56,7 +56,7 @@ int watchdog_init(void) return EC_SUCCESS; } -static int command_watchdog_test(int argc, char **argv) +static int command_watchdog_test(int argc, const char **argv) { starve_dog = 1; diff --git a/chip/max32660/wdt_regs.h b/chip/max32660/wdt_regs.h index 32d6fe0925..440e8e8b0d 100644 --- a/chip/max32660/wdt_regs.h +++ b/chip/max32660/wdt_regs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -31,325 +31,347 @@ */ typedef struct { __IO uint32_t ctrl; /**< \b 0x00:<\tt> WDT CTRL Register */ - __O uint32_t rst; /**< \b 0x04:<\tt> WDT RST Register */ + __O uint32_t rst; /**< \b 0x04:<\tt> WDT RST Register */ } mxc_wdt_regs_t; /** * WDT Peripheral Register Offsets from the WDT Base Peripheral * Address. */ -#define MXC_R_WDT_CTRL \ - ((uint32_t)0x00000000UL) /**< Offset from WDT Base Address: \ +#define MXC_R_WDT_CTRL \ + ((uint32_t)0x00000000UL) /**< Offset from WDT Base Address: \ 0x0x000 */ -#define MXC_R_WDT_RST \ - ((uint32_t)0x00000004UL) /**< Offset from WDT Base Address: \ +#define MXC_R_WDT_RST \ + ((uint32_t)0x00000004UL) /**< Offset from WDT Base Address: \ 0x0x004 */ /** * Watchdog Timer Control Register. */ #define MXC_F_WDT_CTRL_INT_PERIOD_POS 0 /**< CTRL_INT_PERIOD Position */ -#define MXC_F_WDT_CTRL_INT_PERIOD \ - ((uint32_t)( \ - 0xFUL << MXC_F_WDT_CTRL_INT_PERIOD_POS)) /**< CTRL_INT_PERIOD \ - Mask */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW31 \ +#define MXC_F_WDT_CTRL_INT_PERIOD \ + ((uint32_t)(0xFUL \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS)) /**< CTRL_INT_PERIOD \ + Mask */ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW31 \ ((uint32_t)0x0UL) /**< CTRL_INT_PERIOD_WDT2POW31 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW31 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW31 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW31 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW31 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW31 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW31 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW30 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW30 \ ((uint32_t)0x1UL) /**< CTRL_INT_PERIOD_WDT2POW30 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW30 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW30 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW30 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW30 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW30 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW30 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW29 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW29 \ ((uint32_t)0x2UL) /**< CTRL_INT_PERIOD_WDT2POW29 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW29 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW29 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW29 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW29 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW29 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW29 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW28 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW28 \ ((uint32_t)0x3UL) /**< CTRL_INT_PERIOD_WDT2POW28 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW28 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW28 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW28 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW28 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW28 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW28 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW27 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW27 \ ((uint32_t)0x4UL) /**< CTRL_INT_PERIOD_WDT2POW27 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW27 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW27 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW27 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW27 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW27 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW27 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW26 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW26 \ ((uint32_t)0x5UL) /**< CTRL_INT_PERIOD_WDT2POW26 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW26 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW26 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW26 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW26 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW26 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW26 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW25 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW25 \ ((uint32_t)0x6UL) /**< CTRL_INT_PERIOD_WDT2POW25 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW25 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW25 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW25 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW25 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW25 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW25 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW24 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW24 \ ((uint32_t)0x7UL) /**< CTRL_INT_PERIOD_WDT2POW24 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW24 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW24 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW24 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW24 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW24 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW24 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW23 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW23 \ ((uint32_t)0x8UL) /**< CTRL_INT_PERIOD_WDT2POW23 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW23 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW23 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW23 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW23 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW23 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW23 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW22 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW22 \ ((uint32_t)0x9UL) /**< CTRL_INT_PERIOD_WDT2POW22 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW22 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW22 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW22 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW22 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW22 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW22 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW21 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW21 \ ((uint32_t)0xAUL) /**< CTRL_INT_PERIOD_WDT2POW21 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW21 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW21 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW21 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW21 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW21 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW21 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW20 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW20 \ ((uint32_t)0xBUL) /**< CTRL_INT_PERIOD_WDT2POW20 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW20 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW20 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW20 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW20 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW20 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW20 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW19 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW19 \ ((uint32_t)0xCUL) /**< CTRL_INT_PERIOD_WDT2POW19 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW19 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW19 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW19 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW19 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW19 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW19 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW18 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW18 \ ((uint32_t)0xDUL) /**< CTRL_INT_PERIOD_WDT2POW18 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW18 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW18 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW18 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW18 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW18 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW18 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW17 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW17 \ ((uint32_t)0xEUL) /**< CTRL_INT_PERIOD_WDT2POW17 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW17 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW17 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW17 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW17 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW17 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW17 \ Setting */ -#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW16 \ +#define MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW16 \ ((uint32_t)0xFUL) /**< CTRL_INT_PERIOD_WDT2POW16 Value */ -#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW16 \ - (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW16 \ - << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW16 \ +#define MXC_S_WDT_CTRL_INT_PERIOD_WDT2POW16 \ + (MXC_V_WDT_CTRL_INT_PERIOD_WDT2POW16 \ + << MXC_F_WDT_CTRL_INT_PERIOD_POS) /**< CTRL_INT_PERIOD_WDT2POW16 \ Setting */ #define MXC_F_WDT_CTRL_RST_PERIOD_POS 4 /**< CTRL_RST_PERIOD Position */ -#define MXC_F_WDT_CTRL_RST_PERIOD \ - ((uint32_t)( \ - 0xFUL << MXC_F_WDT_CTRL_RST_PERIOD_POS)) /**< CTRL_RST_PERIOD \ - Mask */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW31 \ +#define MXC_F_WDT_CTRL_RST_PERIOD \ + ((uint32_t)(0xFUL \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS)) /**< CTRL_RST_PERIOD \ + Mask */ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW31 \ ((uint32_t)0x0UL) /**< CTRL_RST_PERIOD_WDT2POW31 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW31 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW31 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW31 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW31 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW31 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW31 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW30 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW30 \ ((uint32_t)0x1UL) /**< CTRL_RST_PERIOD_WDT2POW30 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW30 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW30 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW30 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW30 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW30 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW30 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW29 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW29 \ ((uint32_t)0x2UL) /**< CTRL_RST_PERIOD_WDT2POW29 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW29 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW29 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW29 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW29 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW29 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW29 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW28 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW28 \ ((uint32_t)0x3UL) /**< CTRL_RST_PERIOD_WDT2POW28 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW28 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW28 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW28 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW28 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW28 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW28 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW27 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW27 \ ((uint32_t)0x4UL) /**< CTRL_RST_PERIOD_WDT2POW27 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW27 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW27 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW27 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW27 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW27 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW27 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW26 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW26 \ ((uint32_t)0x5UL) /**< CTRL_RST_PERIOD_WDT2POW26 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW26 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW26 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW26 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW26 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW26 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW26 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW25 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW25 \ ((uint32_t)0x6UL) /**< CTRL_RST_PERIOD_WDT2POW25 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW25 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW25 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW25 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW25 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW25 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW25 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW24 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW24 \ ((uint32_t)0x7UL) /**< CTRL_RST_PERIOD_WDT2POW24 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW24 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW24 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW24 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW24 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW24 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW24 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW23 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW23 \ ((uint32_t)0x8UL) /**< CTRL_RST_PERIOD_WDT2POW23 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW23 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW23 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW23 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW23 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW23 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW23 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW22 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW22 \ ((uint32_t)0x9UL) /**< CTRL_RST_PERIOD_WDT2POW22 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW22 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW22 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW22 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW22 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW22 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW22 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW21 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW21 \ ((uint32_t)0xAUL) /**< CTRL_RST_PERIOD_WDT2POW21 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW21 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW21 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW21 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW21 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW21 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW21 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW20 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW20 \ ((uint32_t)0xBUL) /**< CTRL_RST_PERIOD_WDT2POW20 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW20 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW20 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW20 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW20 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW20 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW20 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW19 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW19 \ ((uint32_t)0xCUL) /**< CTRL_RST_PERIOD_WDT2POW19 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW19 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW19 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW19 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW19 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW19 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW19 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW18 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW18 \ ((uint32_t)0xDUL) /**< CTRL_RST_PERIOD_WDT2POW18 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW18 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW18 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW18 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW18 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW18 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW18 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW17 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW17 \ ((uint32_t)0xEUL) /**< CTRL_RST_PERIOD_WDT2POW17 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW17 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW17 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW17 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW17 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW17 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW17 \ Setting */ -#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW16 \ +#define MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW16 \ ((uint32_t)0xFUL) /**< CTRL_RST_PERIOD_WDT2POW16 Value */ -#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW16 \ - (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW16 \ - << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW16 \ +#define MXC_S_WDT_CTRL_RST_PERIOD_WDT2POW16 \ + (MXC_V_WDT_CTRL_RST_PERIOD_WDT2POW16 \ + << MXC_F_WDT_CTRL_RST_PERIOD_POS) /**< CTRL_RST_PERIOD_WDT2POW16 \ Setting */ #define MXC_F_WDT_CTRL_WDT_EN_POS 8 /**< CTRL_WDT_EN Position */ #define MXC_F_WDT_CTRL_WDT_EN \ - ((uint32_t)( \ - 0x1UL << MXC_F_WDT_CTRL_WDT_EN_POS)) /**< CTRL_WDT_EN Mask */ -#define MXC_V_WDT_CTRL_WDT_EN_DIS \ + ((uint32_t)(0x1UL << MXC_F_WDT_CTRL_WDT_EN_POS)) /**< CTRL_WDT_EN Mask \ + */ +#define MXC_V_WDT_CTRL_WDT_EN_DIS \ ((uint32_t)0x0UL) /**< CTRL_WDT_EN_DIS Value */ -#define MXC_S_WDT_CTRL_WDT_EN_DIS \ - (MXC_V_WDT_CTRL_WDT_EN_DIS \ - << MXC_F_WDT_CTRL_WDT_EN_POS) /**< CTRL_WDT_EN_DIS Setting */ -#define MXC_V_WDT_CTRL_WDT_EN_EN \ - ((uint32_t)0x1UL) /**< CTRL_WDT_EN_EN Value \ +#define MXC_S_WDT_CTRL_WDT_EN_DIS \ + (MXC_V_WDT_CTRL_WDT_EN_DIS \ + << MXC_F_WDT_CTRL_WDT_EN_POS) /**< \ + CTRL_WDT_EN_DIS \ + Setting */ +#define MXC_V_WDT_CTRL_WDT_EN_EN \ + ((uint32_t)0x1UL) /**< CTRL_WDT_EN_EN Value \ */ -#define MXC_S_WDT_CTRL_WDT_EN_EN \ - (MXC_V_WDT_CTRL_WDT_EN_EN \ - << MXC_F_WDT_CTRL_WDT_EN_POS) /**< CTRL_WDT_EN_EN Setting */ +#define MXC_S_WDT_CTRL_WDT_EN_EN \ + (MXC_V_WDT_CTRL_WDT_EN_EN \ + << MXC_F_WDT_CTRL_WDT_EN_POS) /**< \ + CTRL_WDT_EN_EN \ + Setting */ #define MXC_F_WDT_CTRL_INT_FLAG_POS 9 /**< CTRL_INT_FLAG Position */ -#define MXC_F_WDT_CTRL_INT_FLAG \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_WDT_CTRL_INT_FLAG_POS)) /**< CTRL_INT_FLAG Mask */ -#define MXC_V_WDT_CTRL_INT_FLAG_INACTIVE \ +#define MXC_F_WDT_CTRL_INT_FLAG \ + ((uint32_t)(0x1UL << MXC_F_WDT_CTRL_INT_FLAG_POS)) /**< CTRL_INT_FLAG \ + Mask */ +#define MXC_V_WDT_CTRL_INT_FLAG_INACTIVE \ ((uint32_t)0x0UL) /**< CTRL_INT_FLAG_INACTIVE Value */ -#define MXC_S_WDT_CTRL_INT_FLAG_INACTIVE \ - (MXC_V_WDT_CTRL_INT_FLAG_INACTIVE \ - << MXC_F_WDT_CTRL_INT_FLAG_POS) /**< CTRL_INT_FLAG_INACTIVE Setting \ +#define MXC_S_WDT_CTRL_INT_FLAG_INACTIVE \ + (MXC_V_WDT_CTRL_INT_FLAG_INACTIVE \ + << MXC_F_WDT_CTRL_INT_FLAG_POS) /**< CTRL_INT_FLAG_INACTIVE Setting \ */ -#define MXC_V_WDT_CTRL_INT_FLAG_PENDING \ +#define MXC_V_WDT_CTRL_INT_FLAG_PENDING \ ((uint32_t)0x1UL) /**< CTRL_INT_FLAG_PENDING Value */ -#define MXC_S_WDT_CTRL_INT_FLAG_PENDING \ - (MXC_V_WDT_CTRL_INT_FLAG_PENDING \ - << MXC_F_WDT_CTRL_INT_FLAG_POS) /**< CTRL_INT_FLAG_PENDING Setting */ +#define MXC_S_WDT_CTRL_INT_FLAG_PENDING \ + (MXC_V_WDT_CTRL_INT_FLAG_PENDING \ + << MXC_F_WDT_CTRL_INT_FLAG_POS) /**< \ + CTRL_INT_FLAG_PENDING \ + Setting \ + */ #define MXC_F_WDT_CTRL_INT_EN_POS 10 /**< CTRL_INT_EN Position */ #define MXC_F_WDT_CTRL_INT_EN \ - ((uint32_t)( \ - 0x1UL << MXC_F_WDT_CTRL_INT_EN_POS)) /**< CTRL_INT_EN Mask */ -#define MXC_V_WDT_CTRL_INT_EN_DIS \ + ((uint32_t)(0x1UL << MXC_F_WDT_CTRL_INT_EN_POS)) /**< CTRL_INT_EN Mask \ + */ +#define MXC_V_WDT_CTRL_INT_EN_DIS \ ((uint32_t)0x0UL) /**< CTRL_INT_EN_DIS Value */ -#define MXC_S_WDT_CTRL_INT_EN_DIS \ - (MXC_V_WDT_CTRL_INT_EN_DIS \ - << MXC_F_WDT_CTRL_INT_EN_POS) /**< CTRL_INT_EN_DIS Setting */ -#define MXC_V_WDT_CTRL_INT_EN_EN \ - ((uint32_t)0x1UL) /**< CTRL_INT_EN_EN Value \ +#define MXC_S_WDT_CTRL_INT_EN_DIS \ + (MXC_V_WDT_CTRL_INT_EN_DIS \ + << MXC_F_WDT_CTRL_INT_EN_POS) /**< \ + CTRL_INT_EN_DIS \ + Setting */ +#define MXC_V_WDT_CTRL_INT_EN_EN \ + ((uint32_t)0x1UL) /**< CTRL_INT_EN_EN Value \ */ -#define MXC_S_WDT_CTRL_INT_EN_EN \ - (MXC_V_WDT_CTRL_INT_EN_EN \ - << MXC_F_WDT_CTRL_INT_EN_POS) /**< CTRL_INT_EN_EN Setting */ +#define MXC_S_WDT_CTRL_INT_EN_EN \ + (MXC_V_WDT_CTRL_INT_EN_EN \ + << MXC_F_WDT_CTRL_INT_EN_POS) /**< \ + CTRL_INT_EN_EN \ + Setting */ #define MXC_F_WDT_CTRL_RST_EN_POS 11 /**< CTRL_RST_EN Position */ #define MXC_F_WDT_CTRL_RST_EN \ - ((uint32_t)( \ - 0x1UL << MXC_F_WDT_CTRL_RST_EN_POS)) /**< CTRL_RST_EN Mask */ -#define MXC_V_WDT_CTRL_RST_EN_DIS \ + ((uint32_t)(0x1UL << MXC_F_WDT_CTRL_RST_EN_POS)) /**< CTRL_RST_EN Mask \ + */ +#define MXC_V_WDT_CTRL_RST_EN_DIS \ ((uint32_t)0x0UL) /**< CTRL_RST_EN_DIS Value */ -#define MXC_S_WDT_CTRL_RST_EN_DIS \ - (MXC_V_WDT_CTRL_RST_EN_DIS \ - << MXC_F_WDT_CTRL_RST_EN_POS) /**< CTRL_RST_EN_DIS Setting */ -#define MXC_V_WDT_CTRL_RST_EN_EN \ - ((uint32_t)0x1UL) /**< CTRL_RST_EN_EN Value \ +#define MXC_S_WDT_CTRL_RST_EN_DIS \ + (MXC_V_WDT_CTRL_RST_EN_DIS \ + << MXC_F_WDT_CTRL_RST_EN_POS) /**< \ + CTRL_RST_EN_DIS \ + Setting */ +#define MXC_V_WDT_CTRL_RST_EN_EN \ + ((uint32_t)0x1UL) /**< CTRL_RST_EN_EN Value \ */ -#define MXC_S_WDT_CTRL_RST_EN_EN \ - (MXC_V_WDT_CTRL_RST_EN_EN \ - << MXC_F_WDT_CTRL_RST_EN_POS) /**< CTRL_RST_EN_EN Setting */ +#define MXC_S_WDT_CTRL_RST_EN_EN \ + (MXC_V_WDT_CTRL_RST_EN_EN \ + << MXC_F_WDT_CTRL_RST_EN_POS) /**< \ + CTRL_RST_EN_EN \ + Setting */ #define MXC_F_WDT_CTRL_RST_FLAG_POS 31 /**< CTRL_RST_FLAG Position */ -#define MXC_F_WDT_CTRL_RST_FLAG \ - ((uint32_t)( \ - 0x1UL \ - << MXC_F_WDT_CTRL_RST_FLAG_POS)) /**< CTRL_RST_FLAG Mask */ -#define MXC_V_WDT_CTRL_RST_FLAG_NOEVENT \ +#define MXC_F_WDT_CTRL_RST_FLAG \ + ((uint32_t)(0x1UL << MXC_F_WDT_CTRL_RST_FLAG_POS)) /**< CTRL_RST_FLAG \ + Mask */ +#define MXC_V_WDT_CTRL_RST_FLAG_NOEVENT \ ((uint32_t)0x0UL) /**< CTRL_RST_FLAG_NOEVENT Value */ -#define MXC_S_WDT_CTRL_RST_FLAG_NOEVENT \ - (MXC_V_WDT_CTRL_RST_FLAG_NOEVENT \ - << MXC_F_WDT_CTRL_RST_FLAG_POS) /**< CTRL_RST_FLAG_NOEVENT Setting */ -#define MXC_V_WDT_CTRL_RST_FLAG_OCCURRED \ +#define MXC_S_WDT_CTRL_RST_FLAG_NOEVENT \ + (MXC_V_WDT_CTRL_RST_FLAG_NOEVENT \ + << MXC_F_WDT_CTRL_RST_FLAG_POS) /**< \ + CTRL_RST_FLAG_NOEVENT \ + Setting \ + */ +#define MXC_V_WDT_CTRL_RST_FLAG_OCCURRED \ ((uint32_t)0x1UL) /**< CTRL_RST_FLAG_OCCURRED Value */ -#define MXC_S_WDT_CTRL_RST_FLAG_OCCURRED \ - (MXC_V_WDT_CTRL_RST_FLAG_OCCURRED \ - << MXC_F_WDT_CTRL_RST_FLAG_POS) /**< CTRL_RST_FLAG_OCCURRED Setting \ +#define MXC_S_WDT_CTRL_RST_FLAG_OCCURRED \ + (MXC_V_WDT_CTRL_RST_FLAG_OCCURRED \ + << MXC_F_WDT_CTRL_RST_FLAG_POS) /**< CTRL_RST_FLAG_OCCURRED Setting \ */ /** * Watchdog Timer Reset Register. */ #define MXC_F_WDT_RST_WDT_RST_POS 0 /**< RST_WDT_RST Position */ -#define MXC_F_WDT_RST_WDT_RST \ - ((uint32_t)( \ - 0xFFUL << MXC_F_WDT_RST_WDT_RST_POS)) /**< RST_WDT_RST Mask */ -#define MXC_V_WDT_RST_WDT_RST_SEQ0 \ +#define MXC_F_WDT_RST_WDT_RST \ + ((uint32_t)(0xFFUL << MXC_F_WDT_RST_WDT_RST_POS)) /**< RST_WDT_RST \ + Mask */ +#define MXC_V_WDT_RST_WDT_RST_SEQ0 \ ((uint32_t)0xA5UL) /**< RST_WDT_RST_SEQ0 Value */ -#define MXC_S_WDT_RST_WDT_RST_SEQ0 \ - (MXC_V_WDT_RST_WDT_RST_SEQ0 \ - << MXC_F_WDT_RST_WDT_RST_POS) /**< RST_WDT_RST_SEQ0 Setting */ -#define MXC_V_WDT_RST_WDT_RST_SEQ1 \ +#define MXC_S_WDT_RST_WDT_RST_SEQ0 \ + (MXC_V_WDT_RST_WDT_RST_SEQ0 \ + << MXC_F_WDT_RST_WDT_RST_POS) /**< \ + RST_WDT_RST_SEQ0 \ + Setting \ + */ +#define MXC_V_WDT_RST_WDT_RST_SEQ1 \ ((uint32_t)0x5AUL) /**< RST_WDT_RST_SEQ1 Value */ -#define MXC_S_WDT_RST_WDT_RST_SEQ1 \ - (MXC_V_WDT_RST_WDT_RST_SEQ1 \ - << MXC_F_WDT_RST_WDT_RST_POS) /**< RST_WDT_RST_SEQ1 Setting */ +#define MXC_S_WDT_RST_WDT_RST_SEQ1 \ + (MXC_V_WDT_RST_WDT_RST_SEQ1 \ + << MXC_F_WDT_RST_WDT_RST_POS) /**< \ + RST_WDT_RST_SEQ1 \ + Setting \ + */ #endif /* _WDT_REGS_H_ */ diff --git a/chip/mchp/adc.c b/chip/mchp/adc.c index e8ec10a0e5..f09c04d26b 100644 --- a/chip/mchp/adc.c +++ b/chip/mchp/adc.c @@ -1,19 +1,18 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "console.h" #include "gpio.h" #include "hooks.h" #include "registers.h" #include "task.h" +#include "tfdp_chip.h" #include "timer.h" #include "util.h" -#include "tfdp_chip.h" /* * Conversion on a single channel takes less than 12 ms. Set timeout to @@ -54,7 +53,7 @@ static int start_single_and_wait(int timeout) /* clear GIRQ single status */ MCHP_INT_SOURCE(MCHP_ADC_GIRQ) = MCHP_ADC_GIRQ_SINGLE_BIT; /* make sure all writes are issued before starting conversion */ - asm volatile ("dsb"); + asm volatile("dsb"); /* Start conversion */ MCHP_ADC_CTRL |= BIT(1); @@ -78,7 +77,8 @@ int adc_read_channel(enum adc_channel ch) if (start_single_and_wait(ADC_SINGLE_READ_TIME)) value = (MCHP_ADC_READ(adc->channel) * adc->factor_mul) / - adc->factor_div + adc->shift; + adc->factor_div + + adc->shift; else value = ADC_READ_ERROR; @@ -106,7 +106,8 @@ int adc_read_all_channels(int *data) for (i = 0; i < ADC_CH_COUNT; ++i) { adc = adc_channels + i; data[i] = (MCHP_ADC_READ(adc->channel) * adc->factor_mul) / - adc->factor_div + adc->shift; + adc->factor_div + + adc->shift; } exit_all_channels: @@ -140,7 +141,7 @@ static void adc_init(void) } DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_INIT_ADC); -void adc_interrupt(void) +static void adc_interrupt(void) { MCHP_INT_DISABLE(MCHP_ADC_GIRQ) = MCHP_ADC_GIRQ_SINGLE_BIT; diff --git a/chip/mchp/adc_chip.h b/chip/mchp/adc_chip.h index 4b1f8df8f1..fa60efa960 100644 --- a/chip/mchp/adc_chip.h +++ b/chip/mchp/adc_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,15 +17,27 @@ struct adc_t { int channel; }; -/* - * Boards must provide this list of ADC channel definitions. - * This must match the enum adc_channel list provided by the board. - */ -extern const struct adc_t adc_channels[]; +/* List of ADC channels */ +enum chip_adc_channel { + CHIP_ADC_CH0 = 0, + CHIP_ADC_CH1, + CHIP_ADC_CH2, + CHIP_ADC_CH3, + CHIP_ADC_CH4, + CHIP_ADC_CH5, + CHIP_ADC_CH6, + CHIP_ADC_CH7, + CHIP_ADC_COUNT, +}; /* Minimum and maximum values returned by adc_read_channel(). */ #define ADC_READ_MIN 0 +#ifdef CHIP_FAMILY_MEC172X +/* MEC172x ADC is 12BIT resolution in default */ +#define ADC_READ_MAX 4095 +#else #define ADC_READ_MAX 1023 +#endif /* Just plain id mapping for code readability */ #define MCHP_ADC_CH(x) (x) diff --git a/chip/mchp/build.mk b/chip/mchp/build.mk index cea514ec43..972dd972ae 100644 --- a/chip/mchp/build.mk +++ b/chip/mchp/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. +# Copyright 2013 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -15,7 +15,7 @@ endif # MCHP MEC SoC's have a Cortex-M4 ARM core CORE:=cortex-m # Allow the full Cortex-M4 instruction set -CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4 +CFLAGS_CPU+=-mcpu=cortex-m4 # JTAG debug with Keil ARM MDK debugger # do not allow GCC dwarf debug extensions @@ -31,8 +31,8 @@ endif # Required chip modules chip-y=clock.o gpio.o hwtimer.o system.o uart.o port80.o tfdp.o chip-$(CONFIG_ADC)+=adc.o -chip-$(CONFIG_DMA)+=dma.o -chip-$(CONFIG_HOSTCMD_ESPI)+=espi.o +chip-$(CONFIG_DMA_CROS)+=dma.o +chip-$(CONFIG_HOST_INTERFACE_ESPI)+=espi.o chip-$(CONFIG_FANS)+=fan.o chip-$(CONFIG_FLASH_PHYSICAL)+=flash.o chip-$(CONFIG_I2C)+=i2c.o @@ -43,7 +43,7 @@ chip-$(CONFIG_PWM)+=pwm.o chip-$(CONFIG_SPI)+=spi.o qmspi.o chip-$(CONFIG_TFDP)+=tfdp.o chip-$(CONFIG_WATCHDOG)+=watchdog.o -ifndef CONFIG_KEYBOARD_NOT_RAW +ifndef CONFIG_KEYBOARD_DISCRETE chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o endif @@ -58,11 +58,20 @@ ifeq ($(CONFIG_MCHP_LFW_DEBUG),y) TEST_SPI=--test_spi endif +# Select chip. Default is MEC170X +PACK_EC=pack_ec.py +ifeq ($(CHIP_FAMILY),mec152x) + PACK_EC=pack_ec_mec152x.py +endif +ifeq ($(CHIP_FAMILY),mec172x) + PACK_EC=pack_ec_mec172x.py +endif + # pack_ec.py creates SPI flash image for MEC # _rw_size is CONFIG_RW_SIZE # Commands to convert $^ to $@.tmp cmd_obj_to_bin = $(OBJCOPY) --gap-fill=0xff -O binary $< $@.tmp1 ; \ - ${SCRIPTDIR}/pack_ec.py -o $@.tmp -i $@.tmp1 \ + ${SCRIPTDIR}/${PACK_EC} -o $@.tmp -i $@.tmp1 \ --loader_file $(chip-lfw-flat) ${TEST_SPI} \ --spi_size ${CHIP_SPI_SIZE_KB} \ --image_size $(_rw_size) ${SCRIPTVERBOSE}; rm -f $@.tmp1 @@ -74,7 +83,9 @@ chip-lfw-flat = $(out)/RW/$(chip-lfw)-lfw.flat objs_lfw = $(patsubst %, $(out)/RW/%-lfw.o, \ $(addprefix common/, util gpio) \ $(addprefix chip/$(CHIP)/, spi qmspi dma gpio clock hwtimer tfdp) \ - core/$(CORE)/cpu $(chip-lfw)) + core/$(CORE)/cpu $(chip-lfw) \ + builtin/stdlib \ + ) # reuse version.o (and its dependencies) from main board objs_lfw += $(out)/RW/common/version.o @@ -82,7 +93,7 @@ objs_lfw += $(out)/RW/common/version.o dirs-y+=chip/$(CHIP)/lfw # objs with -lfw suffix are to include lfw's gpio -$(out)/RW/%-lfw.o: private CC+=-I$(BDIR)/lfw -DLFW=$(EMPTY) +$(out)/RW/%-lfw.o: private CC+=-Ichip/mchp/lfw -DLFW=$(EMPTY) # Remove the lto flag for the loader. It actually causes it to bloat in size. ifeq ($(CONFIG_LTO),y) $(out)/RW/%-lfw.o: private CFLAGS_CPU := $(filter-out -flto, $(CFLAGS_CPU)) @@ -91,6 +102,15 @@ $(out)/RW/%-lfw.o: %.c $(call quiet,c_to_o,CC ) # let lfw's elf link only with selected objects +ifeq ($(CHIP_FAMILY),mec172x) +$(out)/RW/%-lfw.elf: private objs = $(objs_lfw) +$(out)/RW/%-lfw.elf: override shlib := +$(out)/RW/%-lfw.elf: %_416kb.ld $(objs_lfw) + $(call quiet,elf,LD ) + +# final image needs lfw loader +$(out)/$(PROJECT).bin: $(chip-lfw-flat) +else $(out)/RW/%-lfw.elf: private objs = $(objs_lfw) $(out)/RW/%-lfw.elf: override shlib := $(out)/RW/%-lfw.elf: %.ld $(objs_lfw) @@ -98,3 +118,4 @@ $(out)/RW/%-lfw.elf: %.ld $(objs_lfw) # final image needs lfw loader $(out)/$(PROJECT).bin: $(chip-lfw-flat) +endif diff --git a/chip/mchp/clock.c b/chip/mchp/clock.c index 9fdb058898..812825db5a 100644 --- a/chip/mchp/clock.c +++ b/chip/mchp/clock.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,25 +17,25 @@ #include "shared_mem.h" #include "system.h" #include "task.h" +#include "tfdp_chip.h" #include "timer.h" #include "uart.h" #include "util.h" -#include "tfdp_chip.h" #include "vboot_hash.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) #ifdef CONFIG_LOW_POWER_IDLE -#define HTIMER_DIV_1_US_MAX (1998848) -#define HTIMER_DIV_1_1SEC (0x8012) +#define HTIMER_DIV_1_US_MAX (1998848) +#define HTIMER_DIV_1_1SEC (0x8012) -/* Recovery time for HvySlp2 is 0 usec */ -#define HEAVY_SLEEP_RECOVER_TIME_USEC 75 +/* Recovery time for HvySlp2 is 0 us */ +#define HEAVY_SLEEP_RECOVER_TIME_USEC 75 -#define SET_HTIMER_DELAY_USEC 200 +#define SET_HTIMER_DELAY_USEC 200 static int idle_sleep_cnt; static int idle_dsleep_cnt; @@ -52,7 +52,7 @@ static uint32_t ecia_result[MCHP_INT_GIRQ_NUM]; * boot in order to give a permanent window in which the heavy sleep * mode is not used. */ -#define CONSOLE_IN_USE_ON_BOOT_TIME (15*SECOND) +#define CONSOLE_IN_USE_ON_BOOT_TIME (15 * SECOND) static int console_in_use_timeout_sec = 60; static timestamp_t console_expire_time; #endif /*CONFIG_LOW_POWER_IDLE */ @@ -62,7 +62,8 @@ static int freq = 48000000; void clock_wait_cycles(uint32_t cycles) { asm volatile("1: subs %0, #1\n" - " bne 1b\n" : "+r"(cycles)); + " bne 1b\n" + : "+r"(cycles)); } int clock_get_freq(void) @@ -70,6 +71,51 @@ int clock_get_freq(void) return freq; } +/* + * MEC170x and MEC152x have the same 32 KHz clock enable hardware. + * MEC172x 32 KHz clock configuration is different and includes + * hardware to check the crystal before switching and to monitor + * the 32 KHz input if desired. + */ +#ifdef CHIP_FAMILY_MEC172X +/* 32 KHz crystal connected in parallel */ +static inline void config_32k_src_crystal(void) +{ + MCHP_VBAT_CSS = MCHP_VBAT_CSS_XTAL_EN | MCHP_VBAT_CSS_SRC_XTAL; +} + +/* 32 KHz source is 32KHZ_IN pin which must be configured */ +static inline void config_32k_src_se_input(void) +{ + MCHP_VBAT_CSS = MCHP_VBAT_CSS_SIL32K_EN | MCHP_VBAT_CSS_SRC_SWPS; +} + +static inline void config_32k_src_sil_osc(void) +{ + MCHP_VBAT_CSS = MCHP_VBAT_CSS_SIL32K_EN; +} + +#else +static void config_32k_src_crystal(void) +{ + MCHP_VBAT_CE = MCHP_VBAT_CE_XOSEL_PAR | + MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_CRYSTAL; +} + +/* 32 KHz source is 32KHZ_IN pin which must be configured */ +static inline void config_32k_src_se_input(void) +{ + MCHP_VBAT_CE = MCHP_VBAT_CE_32K_DOMAIN_32KHZ_IN_PIN | + MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_INT; +} + +static inline void config_32k_src_sil_osc(void) +{ + MCHP_VBAT_CE = ~(MCHP_VBAT_CE_32K_DOMAIN_32KHZ_IN_PIN | + MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_CRYSTAL); +} +#endif + /** clock_init * @note * MCHP MEC implements 4 control bits in the VBAT Clock Enable register. @@ -94,32 +140,19 @@ int clock_get_freq(void) */ void clock_init(void) { - int __attribute__((unused)) unused; - - trace0(0, MEC, 0, "Clock Init"); - -#ifdef CONFIG_CLOCK_CRYSTAL - /* XOSEL: 0 = Parallel resonant crystal */ - MCHP_VBAT_CE &= ~(1ul << 3); - -#else - /* XOSEL: 1 = Single ended clock source */ - MCHP_VBAT_CE |= (1ul << 3); -#endif - - /* 32K clock enable */ - MCHP_VBAT_CE = (MCHP_VBAT_CE & ~(0x03)) | (1ul << 2); + if (IS_ENABLED(CONFIG_CLOCK_SRC_EXTERNAL)) + if (IS_ENABLED(CONFIG_CLOCK_CRYSTAL)) + config_32k_src_crystal(); + else + /* 32KHz 50% duty waveform on 32KHZ_IN pin */ + config_32k_src_se_input(); + else + /* Use internal silicon 32KHz OSC */ + config_32k_src_sil_osc(); -#ifdef CONFIG_CLOCK_CRYSTAL - /* Wait for crystal to stabilize (OSC_LOCK == 1) */ + /* Wait for PLL to lock onto 32KHz source (OSC_LOCK == 1) */ while (!(MCHP_PCR_CHIP_OSC_ID & 0x100)) ; -#endif - trace0(0, MEC, 0, "PLL OSC is Locked"); -#ifndef LFW - unused = shared_mem_size(); - trace11(0, MEC, 0, "Shared Memory size = 0x%08x", (uint32_t)unused); -#endif } /** @@ -137,14 +170,12 @@ static void clock_turbo_disable(void) else #endif /* Use 12 MHz processor clock for power savings */ - MCHP_PCR_PROC_CLK_CTL = 4; + MCHP_PCR_PROC_CLK_CTL = MCHP_PCR_CLK_CTL_12MHZ; } -DECLARE_HOOK(HOOK_INIT, - clock_turbo_disable, - HOOK_PRIO_INIT_VBOOT_HASH + 1); +DECLARE_HOOK(HOOK_INIT, clock_turbo_disable, HOOK_PRIO_INIT_VBOOT_HASH + 1); /** - * initialization of Hibernation timer0 + * initialization of Hibernation timer 0 * Clear PCR sleep enable. * GIRQ=21, aggregator bit = 1, Direct NVIC = 112 * NVIC direct connect interrupts are used for all peripherals @@ -155,10 +186,8 @@ void htimer_init(void) { MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_HTMR0); MCHP_HTIMER_PRELOAD(0) = 0; /* disable at beginning */ - MCHP_INT_SOURCE(MCHP_HTIMER_GIRQ) = - MCHP_HTIMER_GIRQ_BIT(0); - MCHP_INT_ENABLE(MCHP_HTIMER_GIRQ) = - MCHP_HTIMER_GIRQ_BIT(0); + MCHP_INT_SOURCE(MCHP_HTIMER_GIRQ) = MCHP_HTIMER_GIRQ_BIT(0); + MCHP_INT_ENABLE(MCHP_HTIMER_GIRQ) = MCHP_HTIMER_GIRQ_BIT(0); task_enable_irq(MCHP_IRQ_HTIMER0); } @@ -171,22 +200,18 @@ void htimer_init(void) * @param microseconds Number of microseconds before htimer interrupt * @note hibernation timer input clock is 32.768KHz. * Control register bit[0] selects the divider. - * 0 is divide by 1 for 30.5us per LSB for a maximum of - * 65535 * 30.5us = 1998817.5 us or 32.786 counts per second - * 1 is divide by 4096 for 0.125s per LSB for a maximum of ~2 hours. - * 65535 * 0.125s ~ 8192 s = 2.27 hours + * 0 is divide by 1 for 30.5 us per LSB for a maximum of + * 65535 * 30.5 us = 1998817.5 us or 32.786 counts per second + * 1 is divide by 4096 for 0.125 s per LSB for a maximum of ~2 hours. + * 65535 * 0.125 s ~ 8192 s = 2.27 hours */ -void system_set_htimer_alarm(uint32_t seconds, - uint32_t microseconds) +void system_set_htimer_alarm(uint32_t seconds, uint32_t microseconds) { uint32_t hcnt, ns; uint8_t hctrl; MCHP_HTIMER_PRELOAD(0) = 0; /* disable */ - trace12(0, SLP, 0, "sys set htimer: sec=%d us=%d", - seconds, microseconds); - if (microseconds > 1000000ul) { ns = (microseconds / 1000000ul); microseconds %= 1000000ul; @@ -197,23 +222,20 @@ void system_set_htimer_alarm(uint32_t seconds, } if (seconds > 1) { - hcnt = (seconds << 3); /* divide by 0.125 */ + hcnt = (seconds << 3); /* divide by 0.125 */ if (hcnt > 0xfffful) hcnt = 0xfffful; hctrl = 1; } else { /* * approximate(~2% error) as seconds is 0 or 1 - * seconds / 30.5e-6 + microseonds / 30.5 + * seconds / 30.5e-6 + microseconds / 30.5 */ hcnt = (seconds << 15) + (microseconds >> 5) + - (microseconds >> 10); + (microseconds >> 10); hctrl = 0; } - trace12(0, SLP, 0, - "sys set htimer: ctrl=0x%0x preload=0x%0x", - hctrl, hcnt); MCHP_HTIMER_CONTROL(0) = hctrl; MCHP_HTIMER_PRELOAD(0) = hcnt; } @@ -228,19 +250,18 @@ static timestamp_t system_get_htimer(void) uint16_t count; timestamp_t time; - count = MCHP_HTIMER_COUNT(0); - + count = MCHP_HTIMER_COUNT(0); if (MCHP_HTIMER_CONTROL(0) == 1) /* if > 2 sec */ /* 0.125 sec per count */ time.le.lo = (uint32_t)(count * 125000); - else /* if < 2 sec */ - /* 30.5(=61/2)usec per count */ + else /* if < 2 sec */ + /* 30.5(=61/2) us per count */ time.le.lo = (uint32_t)(count * 61 / 2); time.le.hi = 0; - return time; /* in uSec */ + return time; /* in uSec */ } /** @@ -249,8 +270,7 @@ static timestamp_t system_get_htimer(void) static void system_reset_htimer_alarm(void) { MCHP_HTIMER_PRELOAD(0) = 0; - MCHP_INT_SOURCE(MCHP_HTIMER_GIRQ) = - MCHP_HTIMER_GIRQ_BIT(0); + MCHP_INT_SOURCE(MCHP_HTIMER_GIRQ) = MCHP_HTIMER_GIRQ_BIT(0); } #ifdef CONFIG_MCHP_DEEP_SLP_DEBUG @@ -260,10 +280,10 @@ static void print_pcr_regs(void) trace0(0, MEC, 0, "Current PCR registers"); for (i = 0; i < 5; i++) { - trace12(0, MEC, 0, "REG SLP_EN[%d] = 0x%08X", - i, MCHP_PCR_SLP_EN(i)); - trace12(0, MEC, 0, "REG CLK_REQ[%d] = 0x%08X", - i, MCHP_PCR_CLK_REQ(i)); + trace12(0, MEC, 0, "REG SLP_EN[%d] = 0x%08X", i, + MCHP_PCR_SLP_EN(i)); + trace12(0, MEC, 0, "REG CLK_REQ[%d] = 0x%08X", i, + MCHP_PCR_CLK_REQ(i)); } } @@ -272,10 +292,9 @@ static void print_ecia_regs(void) int i; trace0(0, MEC, 0, "Current GIRQn.Result registers"); - for (i = MCHP_INT_GIRQ_FIRST; - i <= MCHP_INT_GIRQ_LAST; i++) - trace12(0, MEC, 0, "GIRQ[%d].Result = 0x%08X", - i, MCHP_INT_RESULT(i)); + for (i = MCHP_INT_GIRQ_FIRST; i <= MCHP_INT_GIRQ_LAST; i++) + trace12(0, MEC, 0, "GIRQ[%d].Result = 0x%08X", i, + MCHP_INT_RESULT(i)); } static void save_regs(void) @@ -288,8 +307,7 @@ static void save_regs(void) } for (i = 0; i < MCHP_INT_GIRQ_NUM; i++) - ecia_result[i] = - MCHP_INT_RESULT(MCHP_INT_GIRQ_FIRST + i); + ecia_result[i] = MCHP_INT_RESULT(MCHP_INT_GIRQ_FIRST + i); } static void print_saved_regs(void) @@ -298,15 +316,28 @@ static void print_saved_regs(void) trace0(0, BRD, 0, "Before sleep saved registers"); for (i = 0; i < MCHP_PCR_SLP_RST_REG_MAX; i++) { - trace12(0, BRD, 0, "PCR_SLP_EN[%d] = 0x%08X", - i, pcr_slp_en[i]); - trace12(0, BRD, 0, "PCR_CLK_REQ[%d] = 0x%08X", - i, pcr_clk_req[i]); + trace12(0, BRD, 0, "PCR_SLP_EN[%d] = 0x%08X", i, + pcr_slp_en[i]); + trace12(0, BRD, 0, "PCR_CLK_REQ[%d] = 0x%08X", i, + pcr_clk_req[i]); } for (i = 0; i < MCHP_INT_GIRQ_NUM; i++) trace12(0, BRD, 0, "GIRQ[%d].Result = 0x%08X", - (i+MCHP_INT_GIRQ_FIRST), ecia_result[i]); + (i + MCHP_INT_GIRQ_FIRST), ecia_result[i]); +} +#else +static __maybe_unused void print_pcr_regs(void) +{ +} +static __maybe_unused void print_ecia_regs(void) +{ +} +static __maybe_unused void save_regs(void) +{ +} +static __maybe_unused void print_saved_regs(void) +{ } #endif /* #ifdef CONFIG_MCHP_DEEP_SLP_DEBUG */ @@ -320,7 +351,7 @@ static void print_saved_regs(void) * 3. System sleeps * 4. wake event wakes system * 5. HW restores original values of all PCR.SLP_EN registers - * NOTE1: Current RTOS core (Cortex-Mx) does not use SysTick timer. + * NOTE1: Current RTOS core (Cortex-M4) does not use SysTick timer. * We can leave code to disable it but do not re-enable on wake. * NOTE2: Some peripherals will not sleep until outstanding transactions * are complete: I2C, DMA, GPSPI, QMSPI, etc. @@ -330,8 +361,6 @@ static void print_saved_regs(void) */ static void prepare_for_deep_sleep(void) { - trace0(0, MEC, 0, "Prepare for Deep Sleep"); - /* sysTick timer */ CPU_NVIC_ST_CTRL &= ~ST_ENABLE; CPU_NVIC_ST_CTRL &= ~ST_COUNTFLAG; @@ -348,25 +377,20 @@ static void prepare_for_deep_sleep(void) MCHP_TMR32_CTL(1) &= ~1; #ifdef CONFIG_WATCHDOG_HELP MCHP_TMR16_CTL(0) &= ~1; - MCHP_INT_DISABLE(MCHP_TMR16_GIRQ) = - MCHP_TMR16_GIRQ_BIT(0); - MCHP_INT_SOURCE(MCHP_TMR16_GIRQ) = - MCHP_TMR16_GIRQ_BIT(0); + MCHP_INT_DISABLE(MCHP_TMR16_GIRQ) = MCHP_TMR16_GIRQ_BIT(0); + MCHP_INT_SOURCE(MCHP_TMR16_GIRQ) = MCHP_TMR16_GIRQ_BIT(0); #endif MCHP_INT_DISABLE(MCHP_TMR32_GIRQ) = - MCHP_TMR32_GIRQ_BIT(0) + - MCHP_TMR32_GIRQ_BIT(1); + MCHP_TMR32_GIRQ_BIT(0) + MCHP_TMR32_GIRQ_BIT(1); MCHP_INT_SOURCE(MCHP_TMR32_GIRQ) = - MCHP_TMR32_GIRQ_BIT(0) + - MCHP_TMR32_GIRQ_BIT(1); + MCHP_TMR32_GIRQ_BIT(0) + MCHP_TMR32_GIRQ_BIT(1); #ifdef CONFIG_WATCHDOG /* Stop watchdog */ MCHP_WDG_CTL &= ~1; #endif - -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI MCHP_INT_SOURCE(22) = MCHP_INT22_WAKE_ONLY_ESPI; MCHP_INT_ENABLE(22) = MCHP_INT22_WAKE_ONLY_ESPI; #else @@ -377,14 +401,16 @@ static void prepare_for_deep_sleep(void) #ifdef CONFIG_ADC /* * Clear ADC activate bit. If a conversion is in progress the - * ADC block will not enter low power until the converstion is + * ADC block will not enter low power until the conversion is * complete. */ MCHP_ADC_CTRL &= ~1; #endif /* stop Port80 capture timer */ +#ifndef CHIP_FAMILY_MEC172X MCHP_P80_ACTIVATE(0) = 0; +#endif /* * Clear SLP_EN bit(s) for wake sources. @@ -417,9 +443,7 @@ static void prepare_for_deep_sleep(void) static void resume_from_deep_sleep(void) { - trace0(0, MEC, 0, "resume_from_deep_sleep"); - - MCHP_PCR_SYS_SLP_CTL = 0x00; /* default */ + MCHP_PCR_SYS_SLP_CTL = 0x00; /* default */ /* Disable assertion of DeepSleep signal when core executes WFI */ CPU_SCB_SYSCTRL &= ~BIT(2); @@ -446,24 +470,26 @@ static void resume_from_deep_sleep(void) */ MCHP_PCR_SLP_EN3 |= (MCHP_PCR_SLP_EN3_HTMR0); -#ifdef CONFIG_HOSTCMD_ESPI - #ifdef CONFIG_POWER_S0IX +#ifdef CONFIG_HOST_INTERFACE_ESPI +#ifdef CONFIG_POWER_S0IX MCHP_INT_DISABLE(22) = MCHP_INT22_WAKE_ONLY_ESPI; MCHP_INT_SOURCE(22) = MCHP_INT22_WAKE_ONLY_ESPI; - #else +#else MCHP_ESPI_ACTIVATE |= 1; - #endif +#endif #else - #ifdef CONFIG_POWER_S0IX +#ifdef CONFIG_POWER_S0IX MCHP_INT_DISABLE(22) = MCHP_INT22_WAKE_ONLY_LPC; MCHP_INT_SOURCE(22) = MCHP_INT22_WAKE_ONLY_LPC; - #else +#else MCHP_LPC_ACT |= 1; - #endif +#endif #endif - /* re-enable Port80 capture */ + /* re-enable Port 80 capture */ +#ifndef CHIP_FAMILY_MEC172X MCHP_P80_ACTIVATE(0) = 1; +#endif #ifdef CONFIG_ADC MCHP_ADC_CTRL |= 1; @@ -474,10 +500,8 @@ static void resume_from_deep_sleep(void) MCHP_TMR32_CTL(1) |= 1; MCHP_TMR16_CTL(0) |= 1; MCHP_INT_ENABLE(MCHP_TMR32_GIRQ) = - MCHP_TMR32_GIRQ_BIT(0) + - MCHP_TMR32_GIRQ_BIT(1); - MCHP_INT_ENABLE(MCHP_TMR16_GIRQ) = - MCHP_TMR16_GIRQ_BIT(0); + MCHP_TMR32_GIRQ_BIT(0) + MCHP_TMR32_GIRQ_BIT(1); + MCHP_INT_ENABLE(MCHP_TMR16_GIRQ) = MCHP_TMR16_GIRQ_BIT(0); /* Enable watchdog */ #ifdef CONFIG_WATCHDOG @@ -490,7 +514,6 @@ static void resume_from_deep_sleep(void) #endif } - void clock_refresh_console_in_use(void) { disable_sleep(SLEEP_MASK_CONSOLE); @@ -516,43 +539,38 @@ void __idle(void) htimer_init(); /* hibernation timer initialize */ disable_sleep(SLEEP_MASK_CONSOLE); - console_expire_time.val = get_time().val + - CONSOLE_IN_USE_ON_BOOT_TIME; - + console_expire_time.val = get_time().val + CONSOLE_IN_USE_ON_BOOT_TIME; /* * Print when the idle task starts. This is the lowest priority * task, so this only starts once all other tasks have gotten a - * chance to do their task inits and have gone to sleep. + * chance to do their task initializations and have gone to sleep. */ - CPRINTS("MEC1701 low power idle task started"); + CPRINTS("MEC low power idle task started"); while (1) { /* Disable interrupts */ interrupt_disable(); - t0 = get_time(); /* uSec */ + t0 = get_time(); /* uSec */ /* __hw_clock_event_get() is next programmed timer event */ next_delay = __hw_clock_event_get() - t0.le.lo; - time_for_dsleep = next_delay > - (HEAVY_SLEEP_RECOVER_TIME_USEC + - SET_HTIMER_DELAY_USEC); + time_for_dsleep = next_delay > (HEAVY_SLEEP_RECOVER_TIME_USEC + + SET_HTIMER_DELAY_USEC); - max_sleep_time = next_delay - - HEAVY_SLEEP_RECOVER_TIME_USEC; + max_sleep_time = next_delay - HEAVY_SLEEP_RECOVER_TIME_USEC; /* check if there enough time for deep sleep */ if (DEEP_SLEEP_ALLOWED && time_for_dsleep) { - trace0(0, MEC, 0, "Enough time for Deep Sleep"); /* * Check if the console use has expired and * console sleep is masked by GPIO(UART-RX) * interrupt. */ if ((sleep_mask & SLEEP_MASK_CONSOLE) && - t0.val > console_expire_time.val) { + t0.val > console_expire_time.val) { /* allow console to sleep. */ enable_sleep(SLEEP_MASK_CONSOLE); @@ -564,29 +582,26 @@ void __idle(void) clock_wait_cycles(1); if (LOW_SPEED_DEEP_SLEEP_ALLOWED) - CPRINTS("MEC1701 Disable console " - "in deepsleep"); + CPRINTS("MEC Disable console " + "in deep sleep"); } - /* UART is not being used */ uart_ready_for_deepsleep = LOW_SPEED_DEEP_SLEEP_ALLOWED && - !uart_tx_in_progress() && - uart_buffer_empty(); + !uart_tx_in_progress() && uart_buffer_empty(); /* * Since MCHP's heavy sleep mode requires all - * blocks to be sleepable, UART/console's + * blocks to be sleep capable, UART/console * readiness is final decision factor of * heavy sleep of EC. */ if (uart_ready_for_deepsleep) { - idle_dsleep_cnt++; /* - * config UART Rx as GPIO wakeup + * configure UART Rx as GPIO wakeup * interrupt source */ uart_enter_dsleep(); @@ -598,20 +613,16 @@ void __idle(void) * 'max_sleep_time' value should be big * enough so that hibernation timer's * interrupt triggers only after 'wfi' - * completes its excution. + * completes its execution. */ - max_sleep_time -= - (get_time().le.lo - t0.le.lo); + max_sleep_time -= (get_time().le.lo - t0.le.lo); /* setup/enable htimer wakeup interrupt */ - system_set_htimer_alarm(0, - max_sleep_time); + system_set_htimer_alarm(0, max_sleep_time); /* set sleep all just before WFI */ - MCHP_PCR_SYS_SLP_CTL |= - MCHP_PCR_SYS_SLP_HEAVY; - MCHP_PCR_SYS_SLP_CTL |= - MCHP_PCR_SYS_SLP_ALL; + MCHP_PCR_SYS_SLP_CTL |= MCHP_PCR_SYS_SLP_HEAVY; + MCHP_PCR_SYS_SLP_CTL |= MCHP_PCR_SYS_SLP_ALL; } else { idle_sleep_cnt++; @@ -619,12 +630,11 @@ void __idle(void) /* Wait for interrupt: goes into deep sleep. */ asm("dsb"); - asm("wfi"); + cpu_enter_suspend_mode(); asm("isb"); asm("nop"); if (uart_ready_for_deepsleep) { - resume_from_deep_sleep(); /* @@ -643,27 +653,25 @@ void __idle(void) /* disable/clear htimer wakeup interrupt */ system_reset_htimer_alarm(); - t1.val = t0.val + - (uint64_t)(max_sleep_time - - ht_t1.le.lo); + t1.val = t0.val + (uint64_t)(max_sleep_time - + ht_t1.le.lo); force_time(t1); - /* re-eanble UART */ + /* re-enable UART */ uart_exit_dsleep(); /* Record time spent in deep sleep. */ total_idle_dsleep_time_us += (uint64_t)(max_sleep_time - - ht_t1.le.lo); + ht_t1.le.lo); } } else { /* CPU 'Sleep' mode */ idle_sleep_cnt++; - asm("wfi"); - + cpu_enter_suspend_mode(); } interrupt_enable(); @@ -675,47 +683,30 @@ void __idle(void) * Print low power idle statistics */ -#ifdef CONFIG_MCHP_DEEP_SLP_DEBUG -static void print_pcr_regs(void) -{ - int i; - - ccprintf("PCR regs before WFI\n"); - for (i = 0; i < 5; i++) { - ccprintf("PCR SLP_EN[%d] = 0x%08X\n", pcr_slp_en[i]); - ccprintf("PCR CLK_REQ[%d] = 0x%08X\n", pcr_clk_req[i]); - } -} -#endif - -static int command_idle_stats(int argc, char **argv) +static int command_idle_stats(int argc, const char **argv) { timestamp_t ts = get_time(); - ccprintf("Num idle calls that sleep: %d\n", - idle_sleep_cnt); - ccprintf("Num idle calls that deep-sleep: %d\n", - idle_dsleep_cnt); + ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); + ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); ccprintf("Total Time spent in deep-sleep(sec): %.6lld(s)\n", - total_idle_dsleep_time_us); - ccprintf("Total time on: %.6llds\n\n", - ts.val); + total_idle_dsleep_time_us); + ccprintf("Total time on: %.6llds\n\n", ts.val); + + if (IS_ENABLED(CONFIG_MCHP_DEEP_SLP_DEBUG)) + print_pcr_regs(); /* debug */ -#ifdef CONFIG_MCHP_DEEP_SLP_DEBUG - print_pcr_regs(); /* debug */ -#endif return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, - "", +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", "Print last idle stats"); #endif /* defined(CONFIG_CMD_IDLE_STATS) */ /** * Configure deep sleep clock settings. */ -static int command_dsleep(int argc, char **argv) +static int command_dsleep(int argc, const char **argv) { int v; @@ -725,12 +716,10 @@ static int command_dsleep(int argc, char **argv) * Force deep sleep not to use heavy sleep mode or * allow it to use the heavy sleep mode. */ - if (v) /* 'on' */ - disable_sleep( - SLEEP_MASK_FORCE_NO_LOW_SPEED); - else /* 'off' */ - enable_sleep( - SLEEP_MASK_FORCE_NO_LOW_SPEED); + if (v) /* 'on' */ + disable_sleep(SLEEP_MASK_FORCE_NO_LOW_SPEED); + else /* 'off' */ + enable_sleep(SLEEP_MASK_FORCE_NO_LOW_SPEED); } else { /* Set console in use timeout. */ char *e; @@ -746,18 +735,22 @@ static int command_dsleep(int argc, char **argv) } } - ccprintf("Sleep mask: %08x\n", sleep_mask); + ccprintf("Sleep mask: %08x\n", (int)sleep_mask); ccprintf("Console in use timeout: %d sec\n", - console_in_use_timeout_sec); + console_in_use_timeout_sec); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(dsleep, command_dsleep, - "[ on | off | sec]", - "Deep sleep clock settings:\nUse 'on' to force deep " - "sleep NOT to enter heavysleep mode.\nUse 'off' to " - "allow deepsleep to use heavysleep whenever conditions " - "allow.\n" - "Give a timeout value for the console in use timeout.\n" - "See also 'sleepmask'."); +DECLARE_CONSOLE_COMMAND( + dsleep, command_dsleep, "[ on | off | sec]", + "Deep sleep clock settings:\nUse 'on' to force deep " + "sleep NOT to enter heavy sleep mode.\nUse 'off' to " + "allow deep sleep to use heavy sleep whenever conditions " + "allow.\n" + "Give a timeout value for the console in use timeout.\n" + "See also 'sleep mask'."); #endif /* CONFIG_LOW_POWER_IDLE */ + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mchp/clock_chip.h b/chip/mchp/clock_chip.h index 2e7de60358..4b851aa2bd 100644 --- a/chip/mchp/clock_chip.h +++ b/chip/mchp/clock_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,7 +11,6 @@ #include void htimer_init(void); -void system_set_htimer_alarm(uint32_t seconds, - uint32_t microseconds); +void system_set_htimer_alarm(uint32_t seconds, uint32_t microseconds); #endif /* __CROS_EC_I2C_CLOCK_H */ diff --git a/chip/mchp/config_chip.h b/chip/mchp/config_chip.h index 747a10a8b8..fbd1a3565b 100644 --- a/chip/mchp/config_chip.h +++ b/chip/mchp/config_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,15 +10,21 @@ #include "core/cortex-m/config_core.h" /* Number of IRQ vectors on the NVIC */ -#define CONFIG_IRQ_COUNT 157 +#ifdef CHIP_FAMILY_MEC152X +#define CONFIG_IRQ_COUNT 174 +#elif defined(CHIP_FAMILY_MEC170X) +#define CONFIG_IRQ_COUNT 157 +#elif defined(CHIP_FAMILY_MEC172X) +#define CONFIG_IRQ_COUNT 181 +#endif /* Use a bigger console output buffer */ #undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 1024 +#define CONFIG_UART_TX_BUF_SIZE 1024 /* Interval between HOOK_TICK notifications */ -#define HOOK_TICK_INTERVAL_MS 250 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) +#define HOOK_TICK_INTERVAL_MS 250 +#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) /* * Enable chip_pre_init called from main @@ -28,93 +34,132 @@ #define CONFIG_CHIP_PRE_INIT /* - * MCHP EC's have I2C master/slave - * controllers and multiple I2C ports. Any - * port may be mapped to any controller. - * Enable multi-port controller feature. - * Board level configuration determines - * how many controllers/ports are used and - * the mapping of port(s) to controller(s). - * NOTE: Some MCHP reduced pin packages - * may not implement all 11 I2C ports. + * MCHP EC's have I2C controllers and multiple I2C ports. Any port may be + * mapped to any controller at run time. Enable multi-port controller feature. + * Board level configuration determines how many controllers/ports are used + * and the mapping of port(s) to controller(s). NOTE: Some MCHP packages + * may not implement all I2C ports. */ #define CONFIG_I2C_MULTI_PORT_CONTROLLER /* - * MCHP I2C controller is master-slave capable and requires - * a slave address be programmed even if used as master only. - * Each I2C controller can respond to two slave address. - * Define fake slave addresses that aren't used on the I2C port(s) - * connected to each controller. + * MCHP I2C controllers also act as I2C peripherals listening for their + * peripheral address. Each controller has two programmable peripheral + * addresses. Define fake peripheral addresses that aren't used by + * peripherals on the board. */ -#define CONFIG_MCHP_I2C0_SLAVE_ADDRS 0xE3E1 -#define CONFIG_MCHP_I2C1_SLAVE_ADDRS 0xE3E1 -#define CONFIG_MCHP_I2C2_SLAVE_ADDRS 0xE3E1 -#define CONFIG_MCHP_I2C3_SLAVE_ADDRS 0xE3E1 - +#define CONFIG_MCHP_I2C0_SLAVE_ADDRS 0xE3E1 +#define CONFIG_MCHP_I2C1_SLAVE_ADDRS 0xE3E1 +#define CONFIG_MCHP_I2C2_SLAVE_ADDRS 0xE3E1 +#define CONFIG_MCHP_I2C3_SLAVE_ADDRS 0xE3E1 +#define CONFIG_MCHP_I2C4_SLAVE_ADDRS 0xE3E1 +#define CONFIG_MCHP_I2C5_SLAVE_ADDRS 0xE3E1 +#define CONFIG_MCHP_I2C6_SLAVE_ADDRS 0xE3E1 +#define CONFIG_MCHP_I2C7_SLAVE_ADDRS 0xE3E1 /************************************************************************/ /* Memory mapping */ /* - * MEC1701H has a total of 256KB SRAM. + * MEC170x-H and MEC152x-H have a total of 256KB SRAM. * CODE at 0xE0000 - 0x117FFF, DATA at 0x118000 - 0x11FFFF - * MCHP MEC can fetch code from data or data from code. + * MEC172x-N has a total of 416KB SRAM: 352KB CODE 64KB DATA + * CODE at 0xC0000 - 0x117FFF, DATA at 0x118000 - 0x127FFF + * Customer data preserved across reset is 1KB at 0x12_7400. + * Set top of SRAM to 0x12_7800. We lose the top 2KB. + * MCHP MEC can fetch code from data or data from code. */ /************************************************************************/ /* Define our RAM layout. */ -#define CONFIG_MEC_SRAM_BASE_START 0x000E0000 -#define CONFIG_MEC_SRAM_BASE_END 0x00120000 -#define CONFIG_MEC_SRAM_SIZE (CONFIG_MEC_SRAM_BASE_END - \ - CONFIG_MEC_SRAM_BASE_START) +#if defined(CHIP_FAMILY_MEC172X) +#define CONFIG_MEC_SRAM_BASE_START 0x000C0000 +#define CONFIG_MEC_SRAM_BASE_END (0x00128000 - (2 * 1024)) +#else +#define CONFIG_MEC_SRAM_BASE_START 0x000E0000 +#define CONFIG_MEC_SRAM_BASE_END 0x00120000 +#endif +#define CONFIG_MEC_SRAM_SIZE \ + (CONFIG_MEC_SRAM_BASE_END - CONFIG_MEC_SRAM_BASE_START) /* 64k Data RAM for RO / RW / loader */ -#define CONFIG_RAM_SIZE 0x00010000 -#define CONFIG_RAM_BASE (CONFIG_MEC_SRAM_BASE_END - \ - CONFIG_RAM_SIZE) +#define CONFIG_RAM_SIZE 0x00010000 +#define CONFIG_RAM_BASE (CONFIG_MEC_SRAM_BASE_END - CONFIG_RAM_SIZE) /* System stack size */ /* was 1024, temporarily expanded to 2048 for debug */ -#define CONFIG_STACK_SIZE 2048 +#define CONFIG_STACK_SIZE 2048 /* non-standard task stack sizes */ -/* temporarily expanded for debug */ -#define IDLE_TASK_STACK_SIZE 1024 /* 512 */ -#define LARGER_TASK_STACK_SIZE 1024 /* 640 */ -#define VENTI_TASK_STACK_SIZE 1024 /* 768 */ +#define IDLE_TASK_STACK_SIZE 672 +#define LARGER_TASK_STACK_SIZE 800 +#define VENTI_TASK_STACK_SIZE 928 +#define ULTRA_TASK_STACK_SIZE 1056 +#define TRENTA_TASK_STACK_SIZE 1184 -#define CHARGER_TASK_STACK_SIZE 1024 /* 640 */ -#define HOOKS_TASK_STACK_SIZE 1024 /* 640 */ -#define CONSOLE_TASK_STACK_SIZE 1024 /* 640 */ -#define HOST_CMD_TASK_STACK_SIZE 1024 /* 640 */ +#define CHARGER_TASK_STACK_SIZE 1024 /* 640 */ +#define HOOKS_TASK_STACK_SIZE 1024 /* 640 */ +#define CONSOLE_TASK_STACK_SIZE 1024 /* 640 */ +#define HOST_CMD_TASK_STACK_SIZE 1024 /* 640 */ /* * TODO: Large stack consumption * https://code.google.com/p/chrome-os-partner/issues/detail?id=49245 */ -/* dsw original = 800, if stack exceptions expand to 1024 for debug */ -#define PD_TASK_STACK_SIZE 2048 +/* original = 800, if stack exceptions expand to 1024 for debug */ +#define PD_TASK_STACK_SIZE 2048 /* Default task stack size */ -#define TASK_STACK_SIZE 1024 /* 512 */ +#define TASK_STACK_SIZE 672 /************************************************************************/ /* Define our flash layout. */ +/* + * MEC1521H loads firmware using QMSPI controller + * CONFIG_SPI_FLASH_PORT is the index into + * spi_devices[] in board.c + */ +#define CONFIG_SPI_FLASH_PORT 0 +#define CONFIG_SPI_FLASH + +/* + * MEC1727 chip has integrated SPI flash with 512KB size + */ +#if (defined(CHIP_VARIANT_MEC1727SZ) || defined(CHIP_VARIANT_MEC1727LJ)) +/* Total size of writable flash */ +#define CONFIG_FLASH_SIZE_BYTES 524288 +#endif + /* Protect bank size 4K bytes */ -#define CONFIG_FLASH_BANK_SIZE 0x00001000 +#define CONFIG_FLASH_BANK_SIZE 0x00001000 /* Sector erase size 4K bytes */ -#define CONFIG_FLASH_ERASE_SIZE 0x00001000 +#define CONFIG_FLASH_ERASE_SIZE 0x00001000 /* Minimum write size */ -#define CONFIG_FLASH_WRITE_SIZE 0x00000004 +#define CONFIG_FLASH_WRITE_SIZE 0x00000004 /* One page size for write */ -#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 +#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 /* Program memory base address */ -#define CONFIG_PROGRAM_MEMORY_BASE 0x000E0000 +#if defined(CHIP_FAMILY_MEC172X) +#define CONFIG_PROGRAM_MEMORY_BASE 0x000C0000 +#else +#define CONFIG_PROGRAM_MEMORY_BASE 0x000E0000 +#endif + +/* + * Optimize SPI flash read timing, MEC172x QMSPI controller controls CS# + * by hardware, it will add several system clock cycles delay between CS + * deassertion to CS assertion at the start of the next transaction, this + * guarantees SPI back to back transactions, so 1ms delay can be removed + * to optimze timing. MEC172x chip supports this hardware feature. + */ +#if defined(CHIP_FAMILY_MEC172X) +#undef CONFIG_SPI_FLASH_READ_WAIT_MS +#define CONFIG_SPI_FLASH_READ_WAIT_MS 0 +#endif #include "config_flash_layout.h" @@ -122,7 +167,7 @@ /* Customize the build */ /* Optional features present on this chip */ #define CONFIG_ADC -#define CONFIG_DMA +#define CONFIG_DMA_CROS #define CONFIG_HOSTCMD_X86 #define CONFIG_SPI #define CONFIG_SWITCH @@ -159,7 +204,9 @@ * Use DMA when transmitting commands & data * with GPSPI controllers. */ +#if defined(CHIP_FAMILY_MEC170X) || defined(CHIP_FAMILY_MEC172X) #define CONFIG_MCHP_GPSPI_TX_DMA +#endif /* * Use DMA when transmitting command & data of length @@ -184,14 +231,13 @@ * GPIO(PCH_SLP_S0_L, PIN(0x89), GPIO_INPUT | GPIO_PULL_DOWN) */ #define GPIO_BANK(index) ((index) >> 5) -#define GPIO_BANK_MASK(index) (1ul << ((index) & 0x1F)) +#define GPIO_BANK_MASK(index) (1ul << ((index)&0x1F)) #define GPIO_PIN(index) GPIO_BANK(index), GPIO_BANK_MASK(index) #define GPIO_PIN_MASK(p, m) .port = (p), .mask = (m) #ifndef __ASSEMBLER__ - #endif /* #ifndef __ASSEMBLER__ */ -#endif /* __CROS_EC_CONFIG_CHIP_H */ +#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/mchp/config_flash_layout.h b/chip/mchp/config_flash_layout.h index b25ab02b06..f495f65465 100644 --- a/chip/mchp/config_flash_layout.h +++ b/chip/mchp/config_flash_layout.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,14 +14,14 @@ * - Loader + (RO | RW) loaded into program memory. */ -/* Non-memmapped, external SPI */ +/* Non-memmory mapped, external SPI */ #define CONFIG_EXTERNAL_STORAGE -#undef CONFIG_MAPPED_STORAGE -#undef CONFIG_FLASH_PSTATE +#undef CONFIG_MAPPED_STORAGE +#undef CONFIG_FLASH_PSTATE #define CONFIG_SPI_FLASH /* - * MEC17xx BootROM uses two 4-byte TAG's at SPI offset 0x0 and 0x04. + * MEC170x/MEC152x BootROM uses two 4-byte TAG's at SPI offset 0x0 and 0x04. * One valid TAG must be present. * TAG's point to a Header which must be located on a 256 byte * boundary anywhere in the flash (24-bit addressing). @@ -33,32 +33,30 @@ * EC_RO and EC_RW padded sizes from the build are 188KB each. * Storage size is 1/2 flash size. */ -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 /* Lower 256KB of flash is protected region */ #define CONFIG_EC_PROTECTED_STORAGE_SIZE 0x40000 /* Writable storage for EC_RW starts at 256KB */ #define CONFIG_EC_WRITABLE_STORAGE_OFF 0x40000 /* Writeable storage is 256KB */ -#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x40000 - +#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x40000 /* Loader resides at the beginning of program memory */ -#define CONFIG_LOADER_MEM_OFF 0 -#define CONFIG_LOADER_SIZE 0x1000 +#define CONFIG_LOADER_MEM_OFF 0 +#define CONFIG_LOADER_SIZE 0x1000 /* Write protect Loader and RO Image */ -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF /* * Write protect LFW + EC_RO */ -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* * RO / RW images follow the loader in program memory. Either RO or RW * image will be loaded -- both cannot be loaded at the same time. */ -#define CONFIG_RO_MEM_OFF (CONFIG_LOADER_MEM_OFF + \ - CONFIG_LOADER_SIZE) +#define CONFIG_RO_MEM_OFF (CONFIG_LOADER_MEM_OFF + CONFIG_LOADER_SIZE) /* * Total SRAM and the amount allocated for data are specified * by CONFIG_MEC_SRAM_SIZE and CONFIG_RAM_SIZE in config_chip.h @@ -68,50 +66,86 @@ * defined by CONFIG_FLASH_ERASE_SIZE in chip/config_chip.h * and must be located on a erase block boundary. !!! */ -#define CONFIG_RO_SIZE (CONFIG_MEC_SRAM_SIZE - \ - CONFIG_RAM_SIZE - CONFIG_LOADER_SIZE) -#define CONFIG_RW_MEM_OFF CONFIG_RO_MEM_OFF +#if (CONFIG_MEC_SRAM_SIZE > CONFIG_EC_PROTECTED_STORAGE_SIZE) +#define CONFIG_RO_SIZE \ + (CONFIG_EC_PROTECTED_STORAGE_SIZE - CONFIG_LOADER_SIZE - 0x2000) +#else +#define CONFIG_RO_SIZE \ + (CONFIG_MEC_SRAM_SIZE - CONFIG_RAM_SIZE - CONFIG_LOADER_SIZE) +#endif + +#define CONFIG_RW_MEM_OFF CONFIG_RO_MEM_OFF /* - * NOTE: CONFIG_RW_SIZE is passed to chip/mchp/util/pack_ec.py + * NOTE: CONFIG_RW_SIZE is passed to the SPI image generation script by + * chip build.mk + * LFW requires CONFIG_RW_SIZE is equal to CONFIG_RO_SIZE !!! */ -#define CONFIG_RW_SIZE CONFIG_RO_SIZE +#define CONFIG_RW_SIZE CONFIG_RO_SIZE /* * WP region consists of first half of SPI containing TAGs at beginning * of SPI flash and header + binary(LFW+EC_RO) an offset aligned on * a 256 byte boundary. * NOTE: Changing CONFIG_BOOT_HEADER_STORAGE_OFF requires changing - * parameter --payload_offset of pack_ec.py in build.mk! + * parameter --payload_offset parameter in build.mk passed to the + * python image builder. * Two 4-byte TAG's exist at offset 0 and 4 in the SPI flash device. * We only use first TAG pointing to LFW + EC_RO. - * Header size is 128 bytes. Firmware binary is located immediately - * after the header. + * MEC170x Header size is 128 bytes. + * MEC152x Header size is 320 bytes. + * Firmware binary is located immediately after the header. * Second half of SPI flash contains: - * Header(128 bytes) + EC_RW - * EC flash erase/write commands check alginment base on + * Header(128/320 bytes) + EC_RW + * EC flash erase/write commands check alignment base on * CONFIG_FLASH_ERASE_SIZE defined in config_chip.h * NOTE: EC_RO and EC_RW must start at CONFIG_FLASH_ERASE_SIZE or * greater aligned boundaries. */ -#define CONFIG_BOOT_HEADER_STORAGE_OFF 0x1000 -#define CONFIG_RW_BOOT_HEADER_STORAGE_OFF 0 -#define CONFIG_BOOT_HEADER_STORAGE_SIZE 0x80 -#define CONFIG_RW_BOOT_HEADER_STORAGE_SIZE 0 + +#define CONFIG_RW_BOOT_HEADER_STORAGE_OFF 0 +#if defined(CHIP_FAMILY_MEC172X) +/* + * Changed to 0x140 original 0xc0 which is incorrect + * Python SPI image generator is locating header at offset 0x100 which is + * in first 4KB. We moved header into first 4KB to free up the 0x140 (320) + * bytes of code image space. Layout is: + * SPI Offset: + * 0x0 - 0x3 = Boot-ROM TAG + * 0x4 - 0xff = 0xFF padding + * 0x100 - 0x23F = Boot-ROM Header must be on >= 0x100 boundary + * This header points to LFW at 0x1000 + * 0x240 - 0xfff = 0xFF padding + * 0x1000 - 0x1fff = 4KB Little Firmware loaded by Boot-ROM into first 4KB + * of CODE SRAM. + * 0x2000 - 0x3ffff = EC_RO padded with 0xFF + * 0x40000 - 0x7ffff = EC_RW padded with 0xFF + * To EC the "header" is one 4KB chunk at offset 0 + */ +#define CONFIG_BOOT_HEADER_STORAGE_OFF 0 +#define CONFIG_BOOT_HEADER_STORAGE_SIZE 0x1000 +#elif defined(CHIP_FAMILY_MEC152X) +#define CONFIG_BOOT_HEADER_STORAGE_OFF 0x1000 +#define CONFIG_BOOT_HEADER_STORAGE_SIZE 0x140 +#elif defined(CHIP_FAMILY_MEC170X) +#define CONFIG_BOOT_HEADER_STORAGE_OFF 0x1000 +#define CONFIG_BOOT_HEADER_STORAGE_SIZE 0x80 +#else +#error "FORCED BUILD ERROR: CHIP_FAMILY_xxxx not set or invalid" +#endif +#define CONFIG_RW_BOOT_HEADER_STORAGE_SIZE 0 /* Loader / lfw image immediately follows the boot header on SPI */ -#define CONFIG_LOADER_STORAGE_OFF (CONFIG_BOOT_HEADER_STORAGE_OFF + \ - CONFIG_BOOT_HEADER_STORAGE_SIZE) +#define CONFIG_LOADER_STORAGE_OFF \ + (CONFIG_BOOT_HEADER_STORAGE_OFF + CONFIG_BOOT_HEADER_STORAGE_SIZE) /* RO image immediately follows the loader image */ -#define CONFIG_RO_STORAGE_OFF (CONFIG_LOADER_STORAGE_OFF + \ - CONFIG_LOADER_SIZE) +#define CONFIG_RO_STORAGE_OFF (CONFIG_LOADER_STORAGE_OFF + CONFIG_LOADER_SIZE) /* * RW image starts at offset 0 of second half of SPI. * RW Header not needed. */ -#define CONFIG_RW_STORAGE_OFF (CONFIG_RW_BOOT_HEADER_STORAGE_OFF + \ - CONFIG_RW_BOOT_HEADER_STORAGE_SIZE) - +#define CONFIG_RW_STORAGE_OFF \ + (CONFIG_RW_BOOT_HEADER_STORAGE_OFF + CONFIG_RW_BOOT_HEADER_STORAGE_SIZE) #endif /* __CROS_EC_CONFIG_FLASH_LAYOUT_H */ diff --git a/chip/mchp/dma.c b/chip/mchp/dma.c index 982dfa8122..180735dbb5 100644 --- a/chip/mchp/dma.c +++ b/chip/mchp/dma.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,13 +9,13 @@ #include "hooks.h" #include "registers.h" #include "task.h" +#include "tfdp_chip.h" #include "timer.h" #include "util.h" -#include "tfdp_chip.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_DMA, outstr) -#define CPRINTS(format, args...) cprints(CC_DMA, format, ## args) +#define CPRINTS(format, args...) cprints(CC_DMA, format, ##args) dma_chan_t *dma_get_channel(enum dma_channel channel) { @@ -23,7 +23,7 @@ dma_chan_t *dma_get_channel(enum dma_channel channel) if (channel < MCHP_DMAC_COUNT) { pd = (dma_chan_t *)(MCHP_DMA_BASE + MCHP_DMA_CH_OFS + - (channel << MCHP_DMA_CH_OFS_BITPOS)); + (channel << MCHP_DMA_CH_OFS_BITPOS)); } return pd; @@ -35,7 +35,7 @@ void dma_disable(enum dma_channel channel) if (MCHP_DMA_CH_CTRL(channel) & MCHP_DMA_RUN) MCHP_DMA_CH_CTRL(channel) &= ~(MCHP_DMA_RUN); - if (MCHP_DMA_CH_ACT(channel) & MCHP_DMA_ACT_EN) + if (MCHP_DMA_CH_ACT(channel) & MCHP_DMA_ACT_EN) MCHP_DMA_CH_ACT(channel) = 0; } } @@ -74,10 +74,9 @@ void dma_disable_all(void) * is the number of bytes to transfer memory start - memory end = count. */ static void prepare_channel(enum dma_channel ch, unsigned int count, - void *periph, void *memory, unsigned int flags) + void *periph, void *memory, unsigned int flags) { if (ch < MCHP_DMAC_COUNT) { - MCHP_DMA_CH_CTRL(ch) = 0; MCHP_DMA_CH_MEM_START(ch) = (uint32_t)memory; MCHP_DMA_CH_MEM_END(ch) = (uint32_t)memory + count; @@ -107,7 +106,7 @@ void dma_go_chan(enum dma_channel ch) MCHP_DMA_CH_CTRL(ch) |= MCHP_DMA_RUN; } -void dma_prepare_tx(const struct dma_option *option, unsigned count, +void dma_prepare_tx(const struct dma_option *option, unsigned int count, const void *memory) { if (option != NULL) @@ -115,16 +114,14 @@ void dma_prepare_tx(const struct dma_option *option, unsigned count, * Cast away const for memory pointer; this is ok because * we know we're preparing the channel for transmit. */ - prepare_channel(option->channel, count, option->periph, - (void *)memory, - MCHP_DMA_INC_MEM | - MCHP_DMA_TO_DEV | - MCHP_DMA_DEV(option->channel) | - option->flags); + prepare_channel( + option->channel, count, option->periph, (void *)memory, + MCHP_DMA_INC_MEM | MCHP_DMA_TO_DEV | + MCHP_DMA_DEV(option->channel) | option->flags); } void dma_xfr_prepare_tx(const struct dma_option *option, uint32_t count, - const void *memory, uint32_t dma_xfr_units) + const void *memory, uint32_t dma_xfr_units) { uint32_t nflags; @@ -136,23 +133,20 @@ void dma_xfr_prepare_tx(const struct dma_option *option, uint32_t count, * we know we're preparing the channel for transmit. */ prepare_channel(option->channel, count, option->periph, - (void *)memory, - MCHP_DMA_INC_MEM | - MCHP_DMA_TO_DEV | - MCHP_DMA_DEV(option->channel) | - nflags); + (void *)memory, + MCHP_DMA_INC_MEM | MCHP_DMA_TO_DEV | + MCHP_DMA_DEV(option->channel) | nflags); } } -void dma_start_rx(const struct dma_option *option, unsigned count, +void dma_start_rx(const struct dma_option *option, unsigned int count, void *memory) { if (option != NULL) { - prepare_channel(option->channel, count, option->periph, - memory, + prepare_channel(option->channel, count, option->periph, memory, MCHP_DMA_INC_MEM | - MCHP_DMA_DEV(option->channel) | - option->flags); + MCHP_DMA_DEV(option->channel) | + option->flags); dma_go_chan(option->channel); } } @@ -161,26 +155,21 @@ void dma_start_rx(const struct dma_option *option, unsigned count, * Configure and start DMA channel for read from device and write to * memory. Allow caller to override DMA transfer unit length. */ -void dma_xfr_start_rx(const struct dma_option *option, - uint32_t dma_xfr_ulen, - uint32_t count, void *memory) +void dma_xfr_start_rx(const struct dma_option *option, uint32_t dma_xfr_ulen, + uint32_t count, void *memory) { uint32_t ch, ctrl; if (option != NULL) { ch = option->channel; if (ch < MCHP_DMAC_COUNT) { - MCHP_DMA_CH_CTRL(ch) = 0; MCHP_DMA_CH_MEM_START(ch) = (uint32_t)memory; - MCHP_DMA_CH_MEM_END(ch) = (uint32_t)memory + - count; + MCHP_DMA_CH_MEM_END(ch) = (uint32_t)memory + count; - MCHP_DMA_CH_DEV_ADDR(ch) = - (uint32_t)option->periph; + MCHP_DMA_CH_DEV_ADDR(ch) = (uint32_t)option->periph; - ctrl = option->flags & - ~(MCHP_DMA_XFER_SIZE_MASK); + ctrl = option->flags & ~(MCHP_DMA_XFER_SIZE_MASK); ctrl |= MCHP_DMA_INC_MEM; ctrl |= MCHP_DMA_XFER_SIZE(dma_xfr_ulen); ctrl |= MCHP_DMA_DEV(option->channel); @@ -228,8 +217,8 @@ int dma_bytes_done_chan(enum dma_channel ch, uint32_t orig_count) if (ch < MCHP_DMAC_COUNT) if (MCHP_DMA_CH_CTRL(ch) & MCHP_DMA_RUN) cnt = (uint32_t)orig_count - - (MCHP_DMA_CH_MEM_END(ch) - - MCHP_DMA_CH_MEM_START(ch)); + (MCHP_DMA_CH_MEM_END(ch) - + MCHP_DMA_CH_MEM_START(ch)); return (int)cnt; } @@ -259,9 +248,7 @@ int dma_wait(enum dma_channel channel) deadline.val = get_time().val + DMA_TRANSFER_TIMEOUT_US; - while (!(MCHP_DMA_CH_ISTS(channel) & - MCHP_DMA_STS_DONE)) { - + while (!(MCHP_DMA_CH_ISTS(channel) & MCHP_DMA_STS_DONE)) { if (deadline.val <= get_time().val) return EC_ERROR_TIMEOUT; @@ -282,8 +269,8 @@ void dma_clear_isr(enum dma_channel channel) MCHP_DMA_CH_ISTS(channel) = 0x0f; } -void dma_cfg_buffers(enum dma_channel ch, const void *membuf, - uint32_t nb, const void *pdev) +void dma_cfg_buffers(enum dma_channel ch, const void *membuf, uint32_t nb, + const void *pdev) { if (ch < MCHP_DMAC_COUNT) { MCHP_DMA_CH_MEM_START(ch) = (uint32_t)membuf; @@ -301,8 +288,8 @@ void dma_cfg_buffers(enum dma_channel ch, const void *membuf, * b[2] = 1 increment device address * b[3] = disable HW flow control */ -void dma_cfg_xfr(enum dma_channel ch, uint8_t unit_len, - uint8_t dev_id, uint8_t flags) +void dma_cfg_xfr(enum dma_channel ch, uint8_t unit_len, uint8_t dev_id, + uint8_t flags) { uint32_t ctrl; @@ -378,7 +365,7 @@ int dma_crc32_start(const uint8_t *mstart, const uint32_t nbytes, int ien) MCHP_DMA_CH_IEN(0) = 0; MCHP_DMA_CH_ISTS(0) = 0xff; MCHP_DMA_CH0_CRC32_EN = 1; - MCHP_DMA_CH0_CRC32_DATA = 0xfffffffful; + MCHP_DMA_CH0_CRC32_DATA = 0xfffffffful; /* program device address to point to read-only register */ MCHP_DMA_CH_DEV_ADDR(0) = (uint32_t)(MCHP_DMA_CH_BASE + 0x1c); MCHP_DMA_CH_MEM_START(0) = (uint32_t)mstart; @@ -387,7 +374,7 @@ int dma_crc32_start(const uint8_t *mstart, const uint32_t nbytes, int ien) MCHP_DMA_CH_IEN(0) = 0x07; MCHP_DMA_CH_ACT(0) = 1; MCHP_DMA_CH_CTRL(0) = MCHP_DMA_TO_DEV + MCHP_DMA_INC_MEM + - MCHP_DMA_DIS_HW_FLOW + MCHP_DMA_XFER_SIZE(4); + MCHP_DMA_DIS_HW_FLOW + MCHP_DMA_XFER_SIZE(4); MCHP_DMA_CH_CTRL(0) |= MCHP_DMA_SW_GO; return EC_SUCCESS; } diff --git a/chip/mchp/dma_chip.h b/chip/mchp/dma_chip.h index 4784b2c922..bfdb8ab9be 100644 --- a/chip/mchp/dma_chip.h +++ b/chip/mchp/dma_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -13,9 +13,8 @@ #ifndef _DMA_CHIP_H #define _DMA_CHIP_H -#include #include - +#include #ifdef __cplusplus extern "C" { @@ -23,17 +22,16 @@ extern "C" { /* Place any C interfaces here */ -void dma_xfr_start_rx(const struct dma_option *option, - uint32_t dma_xfr_ulen, - uint32_t count, void *memory); +void dma_xfr_start_rx(const struct dma_option *option, uint32_t dma_xfr_ulen, + uint32_t count, void *memory); void dma_xfr_prepare_tx(const struct dma_option *option, uint32_t count, - const void *memory, uint32_t dma_xfr_units); + const void *memory, uint32_t dma_xfr_units); void dma_clr_chan(enum dma_channel ch); -void dma_cfg_buffers(enum dma_channel ch, const void *membuf, - uint32_t nb, const void *pdev); +void dma_cfg_buffers(enum dma_channel ch, const void *membuf, uint32_t nb, + const void *pdev); /* * ch = zero based DMA channel number @@ -44,13 +42,13 @@ void dma_cfg_buffers(enum dma_channel ch, const void *membuf, * b[2] = 1 increment device address * b[3] = disable HW flow control */ -#define DMA_FLAG_D2M 0 -#define DMA_FLAG_M2D 1 -#define DMA_FLAG_INCR_MEM 2 -#define DMA_FLAG_INCR_DEV 4 -#define DMA_FLAG_SW_FLOW 8 -void dma_cfg_xfr(enum dma_channel ch, uint8_t unit_len, - uint8_t dev_id, uint8_t flags); +#define DMA_FLAG_D2M 0 +#define DMA_FLAG_M2D 1 +#define DMA_FLAG_INCR_MEM 2 +#define DMA_FLAG_INCR_DEV 4 +#define DMA_FLAG_SW_FLOW 8 +void dma_cfg_xfr(enum dma_channel ch, uint8_t unit_len, uint8_t dev_id, + uint8_t flags); void dma_run(enum dma_channel ch); @@ -65,4 +63,3 @@ int dma_crc32_start(const uint8_t *mstart, const uint32_t nbytes, int ien); #endif /* #ifndef _DMA_CHIP_H */ /** @} */ - diff --git a/chip/mchp/espi.c b/chip/mchp/espi.c index 1cc06d8f90..552739abc7 100644 --- a/chip/mchp/espi.c +++ b/chip/mchp/espi.c @@ -1,33 +1,31 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* ESPI module for Chrome EC */ -#include "common.h" #include "acpi.h" +#include "chipset.h" +#include "common.h" #include "console.h" +#include "espi.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "keyboard_protocol.h" -#include "port80.h" -#include "util.h" -#include "chipset.h" - -#include "registers.h" -#include "espi.h" #include "lpc.h" #include "lpc_chip.h" +#include "port80.h" +#include "power.h" +#include "registers.h" #include "system.h" +#include "system_boot_time.h" #include "task.h" -#include "console.h" +#include "tfdp_chip.h" +#include "timer.h" #include "uart.h" #include "util.h" -#include "power.h" -#include "timer.h" -#include "tfdp_chip.h" /* Console output macros */ #ifdef CONFIG_MCHP_ESPI_DEBUG @@ -36,18 +34,36 @@ #define CPRINTS(...) #else #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) #endif #else #define CPUTS(...) #define CPRINTS(...) #endif +/* Default config to use maximum frequency */ +#ifndef CONFIG_HOST_INTERFACE_ESPI_EC_MAX_FREQ +#if defined(CHIP_FAMILY_MEC172X) +#define CONFIG_HOST_INTERFACE_ESPI_EC_MAX_FREQ MCHP_ESPI_CAP1_MAX_FREQ_66M +#else +#define CONFIG_HOST_INTERFACE_ESPI_EC_MAX_FREQ MCHP_ESPI_CAP1_MAX_FREQ_50M +#endif +#endif + +/* Default config to support all modes */ +#ifndef CONFIG_HOST_INTERFACE_ESPI_EC_MODE +#define CONFIG_HOST_INTERFACE_ESPI_EC_MODE MCHP_ESPI_CAP1_ALL_MODE +#endif + +/* Default config to support all channels */ +#ifndef CONFIG_HOST_INTERFACE_ESPI_EC_CHAN_BITMAP +#define CONFIG_HOST_INTERFACE_ESPI_EC_CHAN_BITMAP MCHP_ESPI_CAP0_ALL_CHAN_SUPP +#endif /* * eSPI slave to master virtual wire pulse timeout. */ -#define ESPI_S2M_VW_PULSE_LOOP_CNT 50 -#define ESPI_S2M_VW_PULSE_LOOP_DLY_US 10 +#define ESPI_S2M_VW_PULSE_LOOP_CNT 50 +#define ESPI_S2M_VW_PULSE_LOOP_DLY_US 10 /* * eSPI master enable virtual wire channel timeout. @@ -86,16 +102,15 @@ static uint32_t espi_channels_ready; * */ struct vw_info_t { - uint16_t name; /* signal name */ - uint8_t host_idx; /* Host VWire index of signal */ - uint8_t reset_val; /* reset value of VWire */ - uint8_t flags; /* b[0]=0(MSVW), =1(SMVW) */ - uint8_t reg_idx; /* MSVW or SMVW index */ - uint8_t src_num; /* SRC number */ - uint8_t rsvd; + uint16_t name; /* signal name */ + uint8_t host_idx; /* Host VWire index of signal */ + uint8_t reset_val; /* reset value of VWire */ + uint8_t flags; /* b[0]=0(MSVW), =1(SMVW) */ + uint8_t reg_idx; /* MSVW or SMVW index */ + uint8_t src_num; /* SRC number */ + uint8_t rsvd; }; - /* VW signals used in eSPI */ /* * MEC1701H VWire mapping based on eSPI Spec 1.0, @@ -137,7 +152,7 @@ struct vw_info_t { * SRC0 = SLAVE_BOOT_LOAD_DONE !!! NOTE: Google combines SRC0 & SRC3 * SRC1 = VW_ERROR_FATAL * SRC2 = VW_ERROR_NON_FATAL - * SRC3 = SLAVE_BOOT_LOAD_STATUS !!! into VW_SLAVE_BTLD_STATUS_DONE + * SRC3 = SLAVE_BOOT_LOAD_STATUS !!! into VW_PERIPHERAL_BTLD_STATUS_DONE * SMVW02 index=06h PORValue=00010101_00007306 STOM=0111 reset=PLTRST * SRC0 = VW_SCI_L * SRC1 = VW_SMI_L @@ -175,41 +190,40 @@ static const struct vw_info_t vw_info_tbl[] = { * index value flags index num rsvd */ /* MSVW00 Host index 02h (In) */ - {VW_SLP_S3_L, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}, - {VW_SLP_S4_L, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00}, - {VW_SLP_S5_L, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00}, + { VW_SLP_S3_L, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { VW_SLP_S4_L, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00 }, + { VW_SLP_S5_L, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00 }, /* MSVW01 Host index 03h (In) */ - {VW_SUS_STAT_L, 0x03, 0x00, 0x10, 0x01, 0x00, 0x00}, - {VW_PLTRST_L, 0x03, 0x00, 0x10, 0x01, 0x01, 0x00}, - {VW_OOB_RST_WARN, 0x03, 0x00, 0x10, 0x01, 0x02, 0x00}, + { VW_SUS_STAT_L, 0x03, 0x00, 0x10, 0x01, 0x00, 0x00 }, + { VW_PLTRST_L, 0x03, 0x00, 0x10, 0x01, 0x01, 0x00 }, + { VW_OOB_RST_WARN, 0x03, 0x00, 0x10, 0x01, 0x02, 0x00 }, /* SMVW00 Host Index 04h (Out) */ - {VW_OOB_RST_ACK, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00}, - {VW_WAKE_L, 0x04, 0x01, 0x01, 0x00, 0x02, 0x00}, - {VW_PME_L, 0x04, 0x01, 0x01, 0x00, 0x03, 0x00}, + { VW_OOB_RST_ACK, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00 }, + { VW_WAKE_L, 0x04, 0x01, 0x01, 0x00, 0x02, 0x00 }, + { VW_PME_L, 0x04, 0x01, 0x01, 0x00, 0x03, 0x00 }, /* SMVW01 Host index 05h (Out) */ - {VW_ERROR_FATAL, 0x05, 0x00, 0x01, 0x01, 0x01, 0x00}, - {VW_ERROR_NON_FATAL, 0x05, 0x00, 0x01, 0x01, 0x02, 0x00}, - {VW_SLAVE_BTLD_STATUS_DONE, 0x05, 0x00, 0x01, 0x01, 0x30, 0x00}, + { VW_ERROR_FATAL, 0x05, 0x00, 0x01, 0x01, 0x01, 0x00 }, + { VW_ERROR_NON_FATAL, 0x05, 0x00, 0x01, 0x01, 0x02, 0x00 }, + { VW_PERIPHERAL_BTLD_STATUS_DONE, 0x05, 0x00, 0x01, 0x01, 0x30, 0x00 }, /* SMVW02 Host index 06h (Out) */ - {VW_SCI_L, 0x06, 0x01, 0x01, 0x02, 0x00, 0x00}, - {VW_SMI_L, 0x06, 0x01, 0x01, 0x02, 0x01, 0x00}, - {VW_RCIN_L, 0x06, 0x01, 0x01, 0x02, 0x02, 0x00}, - {VW_HOST_RST_ACK, 0x06, 0x00, 0x01, 0x02, 0x03, 0x00}, + { VW_SCI_L, 0x06, 0x01, 0x01, 0x02, 0x00, 0x00 }, + { VW_SMI_L, 0x06, 0x01, 0x01, 0x02, 0x01, 0x00 }, + { VW_RCIN_L, 0x06, 0x01, 0x01, 0x02, 0x02, 0x00 }, + { VW_HOST_RST_ACK, 0x06, 0x00, 0x01, 0x02, 0x03, 0x00 }, /* MSVW02 Host index 07h (In) */ - {VW_HOST_RST_WARN, 0x07, 0x00, 0x10, 0x02, 0x00, 0x00}, + { VW_HOST_RST_WARN, 0x07, 0x00, 0x10, 0x02, 0x00, 0x00 }, /* SMVW03 Host Index 40h (Out) */ - {VW_SUS_ACK, 0x40, 0x00, 0x01, 0x03, 0x00, 0x00}, + { VW_SUS_ACK, 0x40, 0x00, 0x01, 0x03, 0x00, 0x00 }, /* MSVW03 Host Index 41h (In) */ - {VW_SUS_WARN_L, 0x41, 0x00, 0x10, 0x03, 0x00, 0x00}, - {VW_SUS_PWRDN_ACK_L, 0x41, 0x00, 0x10, 0x03, 0x01, 0x00}, - {VW_SLP_A_L, 0x41, 0x00, 0x10, 0x03, 0x03, 0x00}, + { VW_SUS_WARN_L, 0x41, 0x00, 0x10, 0x03, 0x00, 0x00 }, + { VW_SUS_PWRDN_ACK_L, 0x41, 0x00, 0x10, 0x03, 0x01, 0x00 }, + { VW_SLP_A_L, 0x41, 0x00, 0x10, 0x03, 0x03, 0x00 }, /* MSVW04 Host index 42h (In) */ - {VW_SLP_LAN, 0x42, 0x00, 0x10, 0x04, 0x00, 0x00}, - {VW_SLP_WLAN, 0x42, 0x00, 0x10, 0x04, 0x01, 0x00} + { VW_SLP_LAN, 0x42, 0x00, 0x10, 0x04, 0x00, 0x00 }, + { VW_SLP_WLAN, 0x42, 0x00, 0x10, 0x04, 0x01, 0x00 } }; BUILD_ASSERT(ARRAY_SIZE(vw_info_tbl) == VW_SIGNAL_COUNT); - /************************************************************************/ /* eSPI internal utilities */ @@ -226,14 +240,12 @@ static int espi_vw_get_signal_index(enum espi_vw_signal event) return -1; } - /* * Initialize eSPI hardware upon ESPI_RESET# de-assertion */ #ifdef CONFIG_MCHP_ESPI_RESET_DEASSERT_INIT static void espi_reset_deassert_init(void) { - } #endif @@ -311,7 +323,6 @@ static void espi_vw_restore(void) } MCHP_ESPI_VW_M2S_SRC_ALL(MSVW_H02) = r; CPRINTS("eSPI restore MSVW00(Index 02h) = 0x%08x", r); - trace11(0, ESPI, 0, "eSPI restore MSVW00(Index 02h) = 0x%08x", r); vb >>= 4; r = 0; @@ -321,11 +332,9 @@ static void espi_vw_restore(void) } MCHP_ESPI_VW_M2S_SRC_ALL(MSVW_H42) = r; CPRINTS("eSPI restore MSVW00(Index 42h) = 0x%08x", r); - trace11(0, ESPI, 0, "eSPI restore MSVW04(Index 42h) = 0x%08x", r); r = MCHP_VBAT_RAM(MCHP_VBAT_VWIRE_BACKUP); MCHP_VBAT_RAM(MCHP_VBAT_VWIRE_BACKUP) = r & 0xFFFFFF00; - } #endif @@ -346,8 +355,8 @@ static uint8_t __attribute__((unused)) espi_msvw_srcs_get(uint8_t msvw_id) return msvw; } -static void __attribute__((unused)) espi_msvw_srcs_set(uint8_t msvw_id, - uint8_t src_bitmap) +static void __attribute__((unused)) +espi_msvw_srcs_set(uint8_t msvw_id, uint8_t src_bitmap) { if (msvw_id < MSVW_MAX) { uint32_t r = (src_bitmap & 0x08) << 21; @@ -376,8 +385,8 @@ static uint8_t __attribute__((unused)) espi_smvw_srcs_get(uint8_t smvw_id) return smvw; } -static void __attribute__((unused)) espi_smvw_srcs_set(uint8_t smvw_id, - uint8_t src_bitmap) +static void __attribute__((unused)) +espi_smvw_srcs_set(uint8_t smvw_id, uint8_t src_bitmap) { if (smvw_id < SMVW_MAX) { uint32_t r = (src_bitmap & 0x08) << 21; @@ -389,7 +398,6 @@ static void __attribute__((unused)) espi_smvw_srcs_set(uint8_t smvw_id, } } - /* * Called before releasing RSMRST# * ESPI_RESET# is asserted @@ -416,7 +424,6 @@ static void espi_vw_pre_init(void) uint32_t i; CPRINTS("eSPI VW Pre-Init"); - trace0(0, ESPI, 0, "eSPI VW Pre-Init"); #ifdef CONFIG_MCHP_ESPI_VW_SAVE_ON_SLEEP espi_vw_restore(); @@ -449,10 +456,8 @@ static void espi_vw_pre_init(void) task_enable_irq(MCHP_IRQ_GIRQ25); CPRINTS("eSPI VW Pre-Init Done"); - trace0(0, ESPI, 0, "eSPI VW Pre-Init Done"); } - /* * If VWire, Flash, and OOB channels have been enabled * then set VWires SLAVE_BOOT_LOAD_STATUS = SLAVE_BOOT_LOAD_DONE = 1 @@ -472,10 +477,8 @@ static void espi_send_boot_load_done(void) MCHP_ESPI_VW_S2M_SRC0(SMVW_H05) = 1; CPRINTS("eSPI Send SLAVE_BOOT_LOAD_STATUS/DONE = 1"); - trace0(0, ESPI, 0, "VW SLAVE_BOOT_LOAD_STATUS/DONE = 1"); } - /* * Called when eSPI PLTRST# VWire de-asserts * Re-initialize any hardware that was reset while PLTRST# was @@ -498,7 +501,6 @@ static void espi_send_boot_load_done(void) static void espi_host_init(void) { CPRINTS("eSPI - espi_host_init"); - trace0(0, ESPI, 0, "eSPI Host Init"); /* BAR's */ @@ -529,7 +531,6 @@ static void espi_host_init(void) /* PC enable & Mastering enable changes */ MCHP_ESPI_PC_IEN = (1ul << 25) + (1ul << 28); - /* Sufficiently initialized */ lpc_set_init_done(1); @@ -546,11 +547,9 @@ static void espi_host_init(void) lpc_update_host_event_status(); CPRINTS("eSPI - espi_host_init Done"); - trace0(0, ESPI, 0, "eSPI Host Init Done"); } DECLARE_HOOK(HOOK_CHIPSET_STARTUP, espi_host_init, HOOK_PRIO_FIRST); - /* * Called in response to VWire OOB_RST_WARN==1 from * espi_vw_evt_oob_rst_warn. @@ -562,7 +561,6 @@ static void espi_oob_flush(void) { } - /* * Called in response to VWire HOST_RST_WARN==1 from * espi_vw_evt_host_rst_warn. @@ -578,14 +576,12 @@ static void espi_pc_flush(void) void espi_vw_power_signal_interrupt(enum espi_vw_signal signal) { CPRINTS("eSPI power signal interrupt for VW %d", signal); - trace1(0, ESPI, 0, "eSPI pwr intr VW %d", (signal - VW_SIGNAL_START)); - power_signal_interrupt((enum gpio_signal) signal); + power_signal_interrupt((enum gpio_signal)signal); } /************************************************************************/ /* IC specific low-level driver */ - /** * Set eSPI Virtual-Wire signal to Host * @@ -612,7 +608,7 @@ int espi_vw_set_wire(enum espi_vw_signal signal, uint8_t level) if (level) level = 1; - if (signal == VW_SLAVE_BTLD_STATUS_DONE) { + if (signal == VW_PERIPHERAL_BTLD_STATUS_DONE) { /* SLAVE_BOOT_LOAD_STATUS */ MCHP_ESPI_VW_S2M_SRC3(ridx) = level; /* SLAVE_BOOT_LOAD_DONE after status */ @@ -622,10 +618,8 @@ int espi_vw_set_wire(enum espi_vw_signal signal, uint8_t level) } #ifdef CONFIG_MCHP_ESPI_DEBUG - CPRINTS("eSPI VW Set Wire %s = %d", - espi_vw_get_wire_name(signal), level); - trace2(0, ESPI, 0, "VW SetWire[%d] = %d", - ((uint32_t)signal - VW_SIGNAL_START), level); + CPRINTS("eSPI VW Set Wire %s = %d", espi_vw_get_wire_name(signal), + level); #endif return EC_SUCCESS; @@ -641,16 +635,14 @@ int espi_vw_set_wire(enum espi_vw_signal signal, uint8_t level) * happen quickly is bus is idle. Poll for hardware clearing change bit * until timeout. */ -static int espi_vw_s2m_set_w4m(uint32_t ridx, uint32_t src_num, - uint8_t level) +static int espi_vw_s2m_set_w4m(uint32_t ridx, uint32_t src_num, uint8_t level) { uint32_t i; MCHP_ESPI_VW_S2M_SRC(ridx, src_num) = level & 0x01; for (i = 0; i < ESPI_S2M_VW_PULSE_LOOP_CNT; i++) { - if ((MCHP_ESPI_VW_S2M_CHANGE(ridx) & - (1u << src_num)) == 0) + if ((MCHP_ESPI_VW_S2M_CHANGE(ridx) & (1u << src_num)) == 0) return EC_SUCCESS; udelay(ESPI_S2M_VW_PULSE_LOOP_DLY_US); } @@ -691,10 +683,8 @@ int espi_vw_pulse_wire(enum espi_vw_signal signal, int pulse_level) level = 1; #ifdef CONFIG_MCHP_ESPI_DEBUG - CPRINTS("eSPI VW Pulse Wire %s to %d", - espi_vw_get_wire_name(signal), level); - trace2(0, ESPI, 0, "eSPI pulse VW[%d] = %d", signal, level); - trace2(0, ESPI, 0, " S2M index=%d src=%d", ridx, src_num); + CPRINTS("eSPI VW Pulse Wire %s to %d", espi_vw_get_wire_name(signal), + level); #endif /* set requested inactive state */ @@ -702,6 +692,9 @@ int espi_vw_pulse_wire(enum espi_vw_signal signal, int pulse_level) if (rc != EC_SUCCESS) return rc; + /* Ensure a minimum pulse width is met. */ + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); + /* drive to requested active state */ rc = espi_vw_s2m_set_w4m(ridx, src_num, level); if (rc != EC_SUCCESS) @@ -732,10 +725,8 @@ int espi_vw_get_wire(enum espi_vw_signal signal) src_num = vw_info_tbl[tidx].src_num; vw = MCHP_ESPI_VW_M2S_SRC(ridx, src_num) & 0x01; #ifdef CONFIG_MCHP_ESPI_DEBUG - CPRINTS("VW GetWire %s = %d", - espi_vw_get_wire_name(signal), vw); - trace2(0, ESPI, 0, "VW GetWire[%d] = %d", - ((uint32_t)signal - VW_SIGNAL_START), vw); + CPRINTS("VW GetWire %s = %d", espi_vw_get_wire_name(signal), + vw); #endif } @@ -762,10 +753,7 @@ int espi_vw_enable_wire_int(enum espi_vw_signal signal) return EC_ERROR_PARAM1; /* signal is Slave-to-Master */ #ifdef CONFIG_MCHP_ESPI_DEBUG - CPRINTS("VW IntrEn for VW[%s]", - espi_vw_get_wire_name(signal)); - trace1(0, ESPI, 0, "VW IntrEn for VW[%d]", - ((uint32_t)signal - VW_SIGNAL_START)); + CPRINTS("VW IntrEn for VW[%s]", espi_vw_get_wire_name(signal)); #endif ridx = vw_info_tbl[tidx].reg_idx; @@ -778,7 +766,7 @@ int espi_vw_enable_wire_int(enum espi_vw_signal signal) * GIRQ25 MSVW07[0:3] through MSVW10[0:3] (bits[0:25]) */ MCHP_ESPI_VW_M2S_IRQSEL(ridx, src_num) = - MCHP_ESPI_MSVW_IRQSEL_BOTH_EDGES; + MCHP_ESPI_MSVW_IRQSEL_BOTH_EDGES; girq_num = 24; if (ridx > 6) { @@ -813,10 +801,7 @@ int espi_vw_disable_wire_int(enum espi_vw_signal signal) return EC_ERROR_PARAM1; /* signal is Slave-to-Master */ #ifdef CONFIG_MCHP_ESPI_DEBUG - CPRINTS("VW IntrDis for VW[%s]", - espi_vw_get_wire_name(signal)); - trace1(0, ESPI, 0, "VW IntrDis for VW[%d]", - (signal - VW_SIGNAL_START)); + CPRINTS("VW IntrDis for VW[%s]", espi_vw_get_wire_name(signal)); #endif ridx = vw_info_tbl[tidx].reg_idx; @@ -828,8 +813,7 @@ int espi_vw_disable_wire_int(enum espi_vw_signal signal) * GIRQ24 MSVW00[0:3] through MSVW06[0:3] (bits[0:27]) * GIRQ25 MSVW07[0:3] through MSVW10[0:3] (bits[0:25]) */ - MCHP_ESPI_VW_M2S_IRQSEL(ridx, src_num) = - MCHP_ESPI_MSVW_IRQSEL_DISABLED; + MCHP_ESPI_VW_M2S_IRQSEL(ridx, src_num) = MCHP_ESPI_MSVW_IRQSEL_DISABLED; if (ridx < 7) { bpos = (ridx << 2) + src_num; @@ -850,37 +834,33 @@ int espi_vw_disable_wire_int(enum espi_vw_signal signal) static void espi_chipset_reset(void) { hook_notify(HOOK_CHIPSET_RESET); + update_ap_boot_time(ESPIRST); } DECLARE_DEFERRED(espi_chipset_reset); #endif - /* SLP_Sx event handler */ void espi_vw_evt_slp_s3_n(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW SLP_S3: %d", wire_state); - trace1(0, ESPI, 0, "VW_SLP_S3_L change to %d", wire_state); espi_vw_power_signal_interrupt(VW_SLP_S3_L); } void espi_vw_evt_slp_s4_n(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW SLP_S4: %d", wire_state); - trace1(0, ESPI, 0, "VW_SLP_S4_L change to %d", wire_state); espi_vw_power_signal_interrupt(VW_SLP_S4_L); } void espi_vw_evt_slp_s5_n(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW SLP_S5: %d", wire_state); - trace1(0, ESPI, 0, "VW_SLP_S5_L change to %d", wire_state); espi_vw_power_signal_interrupt(VW_SLP_S5_L); } void espi_vw_evt_sus_stat_n(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW SUS_STAT: %d", wire_state); - trace1(0, ESPI, 0, "VW_SUS_STAT change to %d", wire_state); espi_vw_power_signal_interrupt(VW_SUS_STAT_L); } @@ -888,22 +868,22 @@ void espi_vw_evt_sus_stat_n(uint32_t wire_state, uint32_t bpos) void espi_vw_evt_pltrst_n(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW PLTRST#: %d", wire_state); - trace1(0, ESPI, 0, "VW_PLTRST# change to %d", wire_state); - if (wire_state) /* Platform Reset de-assertion */ + if (wire_state) { /* Platform Reset de-assertion */ espi_host_init(); - else /* assertion */ + update_ap_boot_time(PLTRST_HIGH); + } else { /* assertion */ #ifdef CONFIG_CHIPSET_RESET_HOOK hook_call_deferred(&espi_chipset_reset_data, MSEC); #endif - + update_ap_boot_time(PLTRST_LOW); + } } /* OOB Reset Warn event handler */ void espi_vw_evt_oob_rst_warn(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW OOB_RST_WARN: %d", wire_state); - trace1(0, ESPI, 0, "VW_OOB_RST_WARN change to %d", wire_state); espi_oob_flush(); @@ -914,7 +894,6 @@ void espi_vw_evt_oob_rst_warn(uint32_t wire_state, uint32_t bpos) void espi_vw_evt_sus_warn_n(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW SUS_WARN#: %d", wire_state); - trace1(0, ESPI, 0, "VW_SUS_WARN# change to %d", wire_state); udelay(100); @@ -938,7 +917,6 @@ void espi_vw_evt_sus_warn_n(uint32_t wire_state, uint32_t bpos) */ void espi_vw_evt_sus_pwrdn_ack(uint32_t wire_state, uint32_t bpos) { - trace1(0, ESPI, 0, "VW_SUS_PWRDN_ACK change to %d", wire_state); CPRINTS("VW SUS_PWRDN_ACK: %d", wire_state); } @@ -946,7 +924,6 @@ void espi_vw_evt_sus_pwrdn_ack(uint32_t wire_state, uint32_t bpos) void espi_vw_evt_slp_a_n(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW SLP_A: %d", wire_state); - trace1(0, ESPI, 0, "VW_SLP_A# change to %d", wire_state); /* Put handling of ASW well devices here, if any */ } @@ -955,7 +932,6 @@ void espi_vw_evt_slp_a_n(uint32_t wire_state, uint32_t bpos) void espi_vw_evt_host_rst_warn(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW HOST_RST_WARN: %d", wire_state); - trace1(0, ESPI, 0, "VW_HOST_RST_WARN change to %d", wire_state); espi_pc_flush(); @@ -967,32 +943,27 @@ void espi_vw_evt_host_rst_warn(uint32_t wire_state, uint32_t bpos) void espi_vw_evt_slp_lan_n(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW SLP_LAN: %d", wire_state); - trace1(0, ESPI, 0, "VW_SLP_LAN# change to %d", wire_state); } /* SLP_WLAN# */ void espi_vw_evt_slp_wlan_n(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW SLP_WLAN: %d", wire_state); - trace1(0, ESPI, 0, "VW_SLP_WLAN# change to %d", wire_state); } void espi_vw_evt_host_c10(uint32_t wire_state, uint32_t bpos) { CPRINTS("VW HOST_C10: %d", wire_state); - trace1(0, ESPI, 0, "VW_HOST_C10 change to %d", wire_state); } void espi_vw_evt1_dflt(uint32_t wire_state, uint32_t bpos) { CPRINTS("Unknown M2S VW: state=%d GIRQ24 bitpos=%d", wire_state, bpos); - MCHP_INT_DISABLE(24) = (1ul << bpos); } void espi_vw_evt2_dflt(uint32_t wire_state, uint32_t bpos) { CPRINTS("Unknown M2S VW: state=%d GIRQ25 bitpos=%d", wire_state, bpos); - MCHP_INT_DISABLE(25) = (1ul << bpos); } /************************************************************************/ @@ -1035,13 +1006,13 @@ void espi_vw_evt2_dflt(uint32_t wire_state, uint32_t bpos) typedef void (*FPVW)(uint32_t, uint32_t); -#define MCHP_GIRQ24_NUM_M2S (7 * 4) +#define MCHP_GIRQ24_NUM_M2S (7 * 4) const FPVW girq24_vw_handlers[MCHP_GIRQ24_NUM_M2S] = { - espi_vw_evt_slp_s3_n, /* MSVW00, Host M2S 02h */ + espi_vw_evt_slp_s3_n, /* MSVW00, Host M2S 02h */ espi_vw_evt_slp_s4_n, espi_vw_evt_slp_s5_n, espi_vw_evt1_dflt, - espi_vw_evt_sus_stat_n, /* MSVW01, Host M2S 03h */ + espi_vw_evt_sus_stat_n, /* MSVW01, Host M2S 03h */ espi_vw_evt_pltrst_n, espi_vw_evt_oob_rst_warn, espi_vw_evt1_dflt, @@ -1049,46 +1020,38 @@ const FPVW girq24_vw_handlers[MCHP_GIRQ24_NUM_M2S] = { espi_vw_evt1_dflt, espi_vw_evt1_dflt, espi_vw_evt1_dflt, - espi_vw_evt_sus_warn_n, /* MSVW03, Host M2S 41h */ + espi_vw_evt_sus_warn_n, /* MSVW03, Host M2S 41h */ espi_vw_evt_sus_pwrdn_ack, espi_vw_evt1_dflt, espi_vw_evt_slp_a_n, - espi_vw_evt_slp_lan_n, /* MSVW04, Host M2S 42h */ + espi_vw_evt_slp_lan_n, /* MSVW04, Host M2S 42h */ espi_vw_evt_slp_wlan_n, espi_vw_evt1_dflt, espi_vw_evt1_dflt, - espi_vw_evt1_dflt, /* MSVW05, Host M2S 43h */ + espi_vw_evt1_dflt, /* MSVW05, Host M2S 43h */ espi_vw_evt1_dflt, espi_vw_evt1_dflt, espi_vw_evt1_dflt, - espi_vw_evt1_dflt, /* MSVW06, Host M2S 44h */ + espi_vw_evt1_dflt, /* MSVW06, Host M2S 44h */ espi_vw_evt1_dflt, espi_vw_evt1_dflt, espi_vw_evt1_dflt }; -#define MCHP_GIRQ25_NUM_M2S (4 * 4) +#define MCHP_GIRQ25_NUM_M2S (4 * 4) const FPVW girq25_vw_handlers[MCHP_GIRQ25_NUM_M2S] = { - espi_vw_evt_host_c10, /* MSVW07, Host M2S 47h */ - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, /* MSVW08 unassigned */ - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, /* MSVW09 unassigned */ - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, /* MSVW10 unassigned */ - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, - espi_vw_evt2_dflt, + espi_vw_evt_host_c10, /* MSVW07, Host M2S 47h */ + espi_vw_evt2_dflt, espi_vw_evt2_dflt, espi_vw_evt2_dflt, + espi_vw_evt2_dflt, /* MSVW08 unassigned */ + espi_vw_evt2_dflt, espi_vw_evt2_dflt, espi_vw_evt2_dflt, + espi_vw_evt2_dflt, /* MSVW09 unassigned */ + espi_vw_evt2_dflt, espi_vw_evt2_dflt, espi_vw_evt2_dflt, + espi_vw_evt2_dflt, /* MSVW10 unassigned */ + espi_vw_evt2_dflt, espi_vw_evt2_dflt, espi_vw_evt2_dflt, }; /* Interrupt handler for eSPI virtual wires in MSVW00 - MSVW01 */ -void espi_mswv1_interrupt(void) +static void espi_mswv1_interrupt(void) { uint32_t d, girq24_result, bpos; @@ -1096,20 +1059,19 @@ void espi_mswv1_interrupt(void) girq24_result = MCHP_INT_RESULT(24); MCHP_INT_SOURCE(24) = girq24_result; - bpos = __builtin_ctz(girq24_result); /* rbit, clz sequence */ - while (bpos != 32) { - d = *(uint8_t *)(MCHP_ESPI_MSVW_BASE + 8 + - (12 * (bpos >> 2)) + (bpos & 0x03)) & 0x01; + while (girq24_result) { + bpos = __builtin_ctz(girq24_result); /* rbit, clz sequence */ + d = *(uint8_t *)(MCHP_ESPI_MSVW_BASE + 8 + (12 * (bpos >> 2)) + + (bpos & 0x03)) & + 0x01; (girq24_vw_handlers[bpos])(d, bpos); girq24_result &= ~(1ul << bpos); - bpos = __builtin_ctz(girq24_result); } } DECLARE_IRQ(MCHP_IRQ_GIRQ24, espi_mswv1_interrupt, 2); - /* Interrupt handler for eSPI virtual wires in MSVW07 - MSVW10 */ -void espi_msvw2_interrupt(void) +static void espi_msvw2_interrupt(void) { uint32_t d, girq25_result, bpos; @@ -1117,19 +1079,17 @@ void espi_msvw2_interrupt(void) girq25_result = MCHP_INT_RESULT(25); MCHP_INT_SOURCE(25) = girq25_result; - bpos = __builtin_ctz(girq25_result); /* rbit, clz sequence */ - while (bpos != 32) { + while (girq25_result) { + bpos = __builtin_ctz(girq25_result); /* rbit, clz sequence */ d = *(uint8_t *)(MCHP_ESPI_MSVW_BASE + (12 * 7) + 8 + - (12 * (bpos >> 2)) + (bpos & 0x03)) & 0x01; + (12 * (bpos >> 2)) + (bpos & 0x03)) & + 0x01; (girq25_vw_handlers[bpos])(d, bpos); girq25_result &= ~(1ul << bpos); - bpos = __builtin_ctz(girq25_result); } } DECLARE_IRQ(MCHP_IRQ_GIRQ25, espi_msvw2_interrupt, 2); - - /* * NOTES: * While ESPI_RESET# is asserted, all eSPI blocks are held in reset and @@ -1170,7 +1130,7 @@ DECLARE_IRQ(MCHP_IRQ_GIRQ25, espi_msvw2_interrupt, 2); * equivalent to eSPI Platform Reset. * */ -void espi_reset_isr(void) +static void espi_reset_isr(void) { uint8_t erst; @@ -1178,34 +1138,26 @@ void espi_reset_isr(void) MCHP_ESPI_IO_RESET_STATUS = erst; MCHP_INT_SOURCE(MCHP_ESPI_GIRQ) = MCHP_ESPI_RESET_GIRQ_BIT; if (erst & (1ul << 1)) { /* rising edge - reset de-asserted */ - MCHP_INT_ENABLE(MCHP_ESPI_GIRQ) = ( - MCHP_ESPI_PC_GIRQ_BIT + - MCHP_ESPI_OOB_TX_GIRQ_BIT + - MCHP_ESPI_FC_GIRQ_BIT + - MCHP_ESPI_VW_EN_GIRQ_BIT); + MCHP_INT_ENABLE(MCHP_ESPI_GIRQ) = + (MCHP_ESPI_PC_GIRQ_BIT + MCHP_ESPI_OOB_TX_GIRQ_BIT + + MCHP_ESPI_FC_GIRQ_BIT + MCHP_ESPI_VW_EN_GIRQ_BIT); MCHP_ESPI_OOB_TX_IEN = (1ul << 1); MCHP_ESPI_FC_IEN = (1ul << 1); MCHP_ESPI_PC_IEN = (1ul << 25); CPRINTS("eSPI Reset de-assert"); - trace0(0, ESPI, 0, "eSPI Reset de-assert"); } else { /* falling edge - reset asserted */ - MCHP_INT_SOURCE(MCHP_ESPI_GIRQ) = ( - MCHP_ESPI_PC_GIRQ_BIT + - MCHP_ESPI_OOB_TX_GIRQ_BIT + - MCHP_ESPI_FC_GIRQ_BIT + - MCHP_ESPI_VW_EN_GIRQ_BIT); - MCHP_INT_DISABLE(MCHP_ESPI_GIRQ) = ( - MCHP_ESPI_PC_GIRQ_BIT + - MCHP_ESPI_OOB_TX_GIRQ_BIT + - MCHP_ESPI_FC_GIRQ_BIT + - MCHP_ESPI_VW_EN_GIRQ_BIT); + MCHP_INT_SOURCE(MCHP_ESPI_GIRQ) = + (MCHP_ESPI_PC_GIRQ_BIT + MCHP_ESPI_OOB_TX_GIRQ_BIT + + MCHP_ESPI_FC_GIRQ_BIT + MCHP_ESPI_VW_EN_GIRQ_BIT); + MCHP_INT_DISABLE(MCHP_ESPI_GIRQ) = + (MCHP_ESPI_PC_GIRQ_BIT + MCHP_ESPI_OOB_TX_GIRQ_BIT + + MCHP_ESPI_FC_GIRQ_BIT + MCHP_ESPI_VW_EN_GIRQ_BIT); espi_channels_ready = 0; chipset_handle_espi_reset_assert(); CPRINTS("eSPI Reset assert"); - trace0(0, ESPI, 0, "eSPI Reset assert"); } } DECLARE_IRQ(MCHP_IRQ_ESPI_RESET, espi_reset_isr, 3); @@ -1214,7 +1166,7 @@ DECLARE_IRQ(MCHP_IRQ_ESPI_RESET, espi_reset_isr, 3); * eSPI Virtual Wire channel enable handler * Must disable once VW Enable is set by eSPI Master */ -void espi_vw_en_isr(void) +static void espi_vw_en_isr(void) { MCHP_INT_DISABLE(MCHP_ESPI_GIRQ) = MCHP_ESPI_VW_EN_GIRQ_BIT; MCHP_INT_SOURCE(MCHP_ESPI_GIRQ) = MCHP_ESPI_VW_EN_GIRQ_BIT; @@ -1224,18 +1176,16 @@ void espi_vw_en_isr(void) espi_channels_ready |= (1ul << 0); CPRINTS("eSPI VW Enable received, set VW Ready"); - trace0(0, ESPI, 0, "VW Enable. Set VW Ready"); if (0x03 == (espi_channels_ready & 0x03)) espi_send_boot_load_done(); } DECLARE_IRQ(MCHP_IRQ_ESPI_VW_EN, espi_vw_en_isr, 2); - /* * eSPI OOB TX and OOB channel enable change interrupt handler */ -void espi_oob_tx_isr(void) +static void espi_oob_tx_isr(void) { uint32_t sts; @@ -1249,23 +1199,19 @@ void espi_oob_tx_isr(void) MCHP_ESPI_IO_OOB_READY = 1; espi_channels_ready |= (1ul << 2); CPRINTS("eSPI OOB_UP ISR: OOB Channel Enable"); - trace0(0, ESPI, 0, "OOB_TX OOB Enable"); } else { /* no, disabled by Master */ espi_channels_ready &= ~(1ul << 2); CPRINTS("eSPI OOB_UP ISR: OOB Channel Disable"); - trace0(0, ESPI, 0, "eSPI OOB_TX OOB Disable"); } } else { /* Handle OOB Up transmit status: done and/or errors, here */ CPRINTS("eSPI OOB_UP status = 0x%x", sts); - trace11(0, ESPI, 0, "eSPI OOB_TX Status = 0x%08x", sts); } } DECLARE_IRQ(MCHP_IRQ_ESPI_OOB_UP, espi_oob_tx_isr, 2); - /* eSPI OOB RX interrupt handler */ -void espi_oob_rx_isr(void) +static void espi_oob_rx_isr(void) { uint32_t sts; @@ -1274,16 +1220,14 @@ void espi_oob_rx_isr(void) MCHP_INT_SOURCE(MCHP_ESPI_GIRQ) = MCHP_ESPI_OOB_RX_GIRQ_BIT; /* Handle OOB Up transmit status: done and/or errors, if any */ CPRINTS("eSPI OOB_DN status = 0x%x", sts); - trace11(0, ESPI, 0, "eSPI OOB_RX Status = 0x%08x", sts); } DECLARE_IRQ(MCHP_IRQ_ESPI_OOB_DN, espi_oob_rx_isr, 2); - /* * eSPI Flash Channel enable change and data transfer * interrupt handler */ -void espi_fc_isr(void) +static void espi_fc_isr(void) { uint32_t sts; @@ -1296,25 +1240,21 @@ void espi_fc_isr(void) MCHP_ESPI_IO_FC_READY = 1; espi_channels_ready |= (1ul << 1); CPRINTS("eSPI FC ISR: Enable"); - trace0(0, ESPI, 0, "eSPI FC Enable"); if (0x03 == (espi_channels_ready & 0x03)) espi_send_boot_load_done(); } else { /* no, disabled by Master */ espi_channels_ready &= ~(1ul << 1); CPRINTS("eSPI FC ISR: Disable"); - trace0(0, ESPI, 0, "eSPI FC Disable"); } } else { /* Handle FC command status: done and/or errors */ CPRINTS("eSPI FC status = 0x%x", sts); - trace11(0, ESPI, 0, "eSPI FC Status = 0x%08x", sts); } } DECLARE_IRQ(MCHP_IRQ_ESPI_FC, espi_fc_isr, 2); - /* eSPI Peripheral Channel interrupt handler */ -void espi_pc_isr(void) +static void espi_pc_isr(void) { uint32_t sts; @@ -1326,22 +1266,18 @@ void espi_pc_isr(void) MCHP_ESPI_IO_PC_READY = 1; espi_channels_ready |= (1ul << 3); CPRINTS("eSPI PC Channel Enable"); - trace0(0, ESPI, 0, "eSPI PC Enable"); } else { espi_channels_ready &= ~(1ul << 3); CPRINTS("eSPI PC Channel Disable"); - trace0(0, ESPI, 0, "eSPI PC Disable"); } } else { /* Handler PC channel errors here */ CPRINTS("eSPI PC status = 0x%x", sts); - trace11(0, ESPI, 0, "eSPI PC Status = 0x%08x", sts); } } DECLARE_IRQ(MCHP_IRQ_ESPI_PC, espi_pc_isr, 2); - /************************************************************************/ /* @@ -1352,25 +1288,21 @@ static void espi_reset_ictrl(int enable, int clr_status) { if (enable) { if (clr_status) { - MCHP_ESPI_IO_RESET_STATUS = - MCHP_ESPI_RST_CHG_STS; + MCHP_ESPI_IO_RESET_STATUS = MCHP_ESPI_RST_CHG_STS; MCHP_INT_SOURCE(MCHP_ESPI_GIRQ) = - MCHP_ESPI_RESET_GIRQ_BIT; + MCHP_ESPI_RESET_GIRQ_BIT; } MCHP_ESPI_IO_RESET_IEN |= MCHP_ESPI_RST_IEN; - MCHP_INT_ENABLE(MCHP_ESPI_GIRQ) = - MCHP_ESPI_RESET_GIRQ_BIT; + MCHP_INT_ENABLE(MCHP_ESPI_GIRQ) = MCHP_ESPI_RESET_GIRQ_BIT; task_enable_irq(MCHP_IRQ_ESPI_RESET); } else { task_disable_irq(MCHP_IRQ_ESPI_RESET); - MCHP_INT_DISABLE(MCHP_ESPI_GIRQ) = - MCHP_ESPI_RESET_GIRQ_BIT; + MCHP_INT_DISABLE(MCHP_ESPI_GIRQ) = MCHP_ESPI_RESET_GIRQ_BIT; MCHP_ESPI_IO_RESET_IEN &= ~(MCHP_ESPI_RST_IEN); if (clr_status) { - MCHP_ESPI_IO_RESET_STATUS = - MCHP_ESPI_RST_CHG_STS; + MCHP_ESPI_IO_RESET_STATUS = MCHP_ESPI_RST_CHG_STS; MCHP_INT_SOURCE(MCHP_ESPI_GIRQ) = - MCHP_ESPI_RESET_GIRQ_BIT; + MCHP_ESPI_RESET_GIRQ_BIT; } } } @@ -1383,7 +1315,6 @@ void espi_init(void) espi_channels_ready = 0; CPRINTS("eSPI - espi_init"); - trace0(0, ESPI, 0, "eSPI Init"); /* Clear PCR eSPI sleep enable */ MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_ESPI); @@ -1403,40 +1334,24 @@ void espi_init(void) */ gpio_config_module(MODULE_LPC, 1); - /* Override Boot-ROM configuration */ -#ifdef CONFIG_HOSTCMD_ESPI_EC_CHAN_BITMAP - MCHP_ESPI_IO_CAP0 = CONFIG_HOSTCMD_ESPI_EC_CHAN_BITMAP; -#endif - -#ifdef CONFIG_HOSTCMD_ESPI_EC_MAX_FREQ - MCHP_ESPI_IO_CAP1 &= ~(MCHP_ESPI_CAP1_MAX_FREQ_MASK); -#if CONFIG_HOSTCMD_ESPI_EC_MAX_FREQ == 25 - MCHP_ESPI_IO_CAP1 |= MCHP_ESPI_CAP1_MAX_FREQ_25M; -#elif CONFIG_HOSTCMD_ESPI_EC_MAX_FREQ == 33 - MCHP_ESPI_IO_CAP1 |= MCHP_ESPI_CAP1_MAX_FREQ_33M; -#elif CONFIG_HOSTCMD_ESPI_EC_MAX_FREQ == 50 - MCHP_ESPI_IO_CAP1 |= MCHP_ESPI_CAP1_MAX_FREQ_50M; -#elif CONFIG_HOSTCMD_ESPI_EC_MAX_FREQ == 66 - MCHP_ESPI_IO_CAP1 |= MCHP_ESPI_CAP1_MAX_FREQ_66M; -#else - MCHP_ESPI_IO_CAP1 |= MCHP_ESPI_CAP1_MAX_FREQ_20M; -#endif -#endif + /* Set channel */ + MCHP_ESPI_IO_CAP0 = CONFIG_HOST_INTERFACE_ESPI_EC_CHAN_BITMAP; -#ifdef CONFIG_HOSTCMD_ESPI_EC_MODE - MCHP_ESPI_IO_CAP1 &= ~(MCHP_ESPI_CAP1_IO_MASK); - MCHP_ESPI_IO_CAP1 |= ((CONFIG_HOSTCMD_ESPI_EC_MODE) - << MCHP_ESPI_CAP1_IO_BITPOS); -#endif + /* Set eSPI frequency & mode */ + MCHP_ESPI_IO_CAP1 = + (MCHP_ESPI_IO_CAP1 & + (~(MCHP_ESPI_CAP1_MAX_FREQ_MASK | MCHP_ESPI_CAP1_IO_MASK))) | + CONFIG_HOST_INTERFACE_ESPI_EC_MAX_FREQ | + (CONFIG_HOST_INTERFACE_ESPI_EC_MODE + << MCHP_ESPI_CAP1_IO_BITPOS); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI MCHP_ESPI_IO_PLTRST_SRC = MCHP_ESPI_PLTRST_SRC_VW; #else MCHP_ESPI_IO_PLTRST_SRC = MCHP_ESPI_PLTRST_SRC_PIN; #endif - MCHP_PCR_PWR_RST_CTL &= - ~(1ul << MCHP_PCR_PWR_HOST_RST_SEL_BITPOS); + MCHP_PCR_PWR_RST_CTL &= ~(1ul << MCHP_PCR_PWR_HOST_RST_SEL_BITPOS); MCHP_ESPI_ACTIVATE = 1; @@ -1462,8 +1377,8 @@ void espi_init(void) MCHP_ESPI_PC_STATUS = 0xfffffffful; MCHP_ESPI_OOB_RX_STATUS = 0xfffffffful; MCHP_ESPI_FC_STATUS = 0xfffffffful; - MCHP_INT_DISABLE(MCHP_ESPI_GIRQ) = 0x1FFul; - MCHP_INT_SOURCE(MCHP_ESPI_GIRQ) = 0x1FFul; + MCHP_INT_DISABLE(MCHP_ESPI_GIRQ) = 0xfffffffful; + MCHP_INT_SOURCE(MCHP_ESPI_GIRQ) = 0xfffffffful; task_enable_irq(MCHP_IRQ_ESPI_PC); task_enable_irq(MCHP_IRQ_ESPI_OOB_UP); @@ -1476,27 +1391,22 @@ void espi_init(void) * and will be controlled by espi_vw_enable/disable_wire_in */ CPRINTS("eSPI - enable ESPI_RESET# interrupt"); - trace0(0, ESPI, 0, "Enable ESPI_RESET# interrupt"); /* Enable ESPI_RESET# interrupt and clear status */ espi_reset_ictrl(1, 1); CPRINTS("eSPI - espi_init - done"); - trace0(0, ESPI, 0, "eSPI Init Done"); - } - #ifdef CONFIG_MCHP_ESPI_EC_CMD -/* TODO */ -static int command_espi(int argc, char **argv) +static int command_espi(int argc, const char **argv) { uint32_t chan, w0, w1, w2; char *e; if (argc == 1) { return EC_ERROR_INVAL; - /* Get value of eSPI registers */ + /* Get value of eSPI registers */ } else if (argc == 2) { int i; @@ -1514,8 +1424,8 @@ static int command_espi(int argc, char **argv) w0 = MSVW(i, 0); w1 = MSVW(i, 1); w2 = MSVW(i, 2); - ccprintf("MSVW%d: 0x%08x:%08x:%08x\n", i, - w2, w1, w0); + ccprintf("MSVW%d: 0x%08x:%08x:%08x\n", i, w2, + w1, w0); } } else if (strcasecmp(argv[1], "vms") == 0) { for (i = 0; i < SMVW_MAX; i++) { @@ -1524,9 +1434,9 @@ static int command_espi(int argc, char **argv) ccprintf("SMVW%d: 0x%08x:%08x\n", i, w1, w0); } } - /* Enable/Disable the channels of eSPI */ + /* Enable/Disable the channels of eSPI */ } else if (argc == 3) { - uint32_t m = (uint32_t) strtoi(argv[2], &e, 0); + uint32_t m = (uint32_t)strtoi(argv[2], &e, 0); if (*e) return EC_ERROR_PARAM2; @@ -1546,7 +1456,6 @@ static int command_espi(int argc, char **argv) } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(espi, command_espi, - "cfg/vms/vsm/en/dis [channel]", +DECLARE_CONSOLE_COMMAND(espi, command_espi, "cfg/vms/vsm/en/dis [channel]", "eSPI configurations"); #endif diff --git a/chip/mchp/fan.c b/chip/mchp/fan.c index dc939bb58f..c68d71bcc8 100644 --- a/chip/mchp/fan.c +++ b/chip/mchp/fan.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,8 +9,14 @@ #include "fan.h" #include "registers.h" -#include "util.h" #include "tfdp_chip.h" +#include "util.h" + +/* Maximum fan driver setting value */ +#define MAX_FAN_DRIVER_SETTING 0x3ff + +/* Fan driver setting data in bit[15:6] of hardware register */ +#define FAN_DRIVER_SETTING_SHIFT 6 /* Maximum tach reading/target value */ #define MAX_TACH 0x1fff @@ -32,7 +38,6 @@ static int rpm_setting; static int duty_setting; static int in_rpm_mode = 1; - static void clear_status(void) { /* Clear DRIVE_FAIL, FAN_SPIN, and FAN_STALL bits */ @@ -71,12 +76,15 @@ void fan_set_duty(int ch, int percent) percent = 100; duty_setting = percent; - MCHP_FAN_SETTING(0) = percent * 255 / 100; + MCHP_FAN_SETTING(0) = (percent * MAX_FAN_DRIVER_SETTING / 100) + << FAN_DRIVER_SETTING_SHIFT; clear_status(); } int fan_get_duty(int ch) { + duty_setting = (MCHP_FAN_SETTING(0) >> FAN_DRIVER_SETTING_SHIFT) * 100 / + MAX_FAN_DRIVER_SETTING; return duty_setting; } @@ -140,7 +148,8 @@ void fan_channel_setup(int ch, unsigned int flags) { /* Clear PCR sleep enable for RPM2FAN0 */ MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_RPMPWM0); - + /* Configure PWM Min drive */ + MCHP_FAN_MIN_DRV(0) = 0x0A; /* * Fan configuration 1 register: * 0x80 = bit 7 = RPM mode (0x00 if FAN_USE_RPM_MODE not set) @@ -149,16 +158,17 @@ void fan_channel_setup(int ch, unsigned int flags) * 0x03 = bits 2:0 = 400 ms update time * * Fan configuration 2 register: - * 0x00 = bit 6 = Ramp control disabled - * 0x00 = bit 5 = Glitch filter enabled - * 0x18 = bits 4:3 = Using both derivative options - * 0x02 = bits 2:1 = error range is 50 RPM - * 0x00 = bits 0 = normal polarity + * 0x00 = bit 7 = Ramp control disabled + * 0x00 = bit 6 = Glitch filter enabled + * 0x30 = bits 5:4 = Using both derivative options + * 0x04 = bits 3:2 = error range is 50 RPM + * 0x00 = bits 1 = normal polarity + * 0x00 = bit 0 = Reserved */ if (flags & FAN_USE_RPM_MODE) MCHP_FAN_CFG1(0) = 0xab; else MCHP_FAN_CFG1(0) = 0x2b; - MCHP_FAN_CFG2(0) = 0x1a; + MCHP_FAN_CFG2(0) = 0x34; clear_status(); } diff --git a/chip/mchp/flash.c b/chip/mchp/flash.c index 043e2b268f..f0f3a5575e 100644 --- a/chip/mchp/flash.c +++ b/chip/mchp/flash.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,14 +6,14 @@ #include "common.h" #include "console.h" #include "flash.h" +#include "hooks.h" #include "host_command.h" #include "shared_mem.h" #include "spi.h" #include "spi_flash.h" #include "system.h" -#include "util.h" -#include "hooks.h" #include "tfdp_chip.h" +#include "util.h" #define PAGE_SIZE 256 @@ -35,7 +35,7 @@ struct flash_wp_state { * @param size Number of bytes to write. * @param data Destination buffer for data. */ -int flash_physical_read(int offset, int size, char *data) +int crec_flash_physical_read(int offset, int size, char *data) { trace13(0, FLASH, 0, "flash_phys_read: offset=0x%08X size=0x%08X dataptr=0x%08X", @@ -52,10 +52,10 @@ int flash_physical_read(int offset, int size, char *data) * @param size Number of bytes to write. * @param data Data to write to flash. Must be 32-bit aligned. */ -int flash_physical_write(int offset, int size, const char *data) +int crec_flash_physical_write(int offset, int size, const char *data) { int ret = EC_SUCCESS; - int i, write_size; + int i, write_size; trace13(0, FLASH, 0, "flash_phys_write: offset=0x%08X size=0x%08X dataptr=0x%08X", @@ -70,8 +70,7 @@ int flash_physical_write(int offset, int size, const char *data) for (i = 0; i < size; i += write_size) { write_size = MIN((size - i), SPI_FLASH_MAX_WRITE_SIZE); - ret = spi_flash_write(offset + i, - write_size, + ret = spi_flash_write(offset + i, write_size, (uint8_t *)data + i); if (ret != EC_SUCCESS) break; @@ -87,15 +86,14 @@ int flash_physical_write(int offset, int size, const char *data) * @param offset Flash offset to erase. * @param size Number of bytes to erase. */ -int flash_physical_erase(int offset, int size) +int crec_flash_physical_erase(int offset, int size) { int ret; if (entire_flash_locked) return EC_ERROR_ACCESS_DENIED; - trace12(0, FLASH, 0, - "flash_phys_erase: offset=0x%08X size=0x%08X", + trace12(0, FLASH, 0, "flash_phys_erase: offset=0x%08X size=0x%08X", offset, size); ret = spi_flash_erase(offset, size); return ret; @@ -107,10 +105,10 @@ int flash_physical_erase(int offset, int size) * @param bank Bank index to check. * @return non-zero if bank is protected until reboot. */ -int flash_physical_get_protect(int bank) +int crec_flash_physical_get_protect(int bank) { return spi_flash_check_protect(bank * CONFIG_FLASH_BANK_SIZE, - CONFIG_FLASH_BANK_SIZE); + CONFIG_FLASH_BANK_SIZE); } /** @@ -121,7 +119,7 @@ int flash_physical_get_protect(int bank) * @param all Protect all (=1) or just read-only * @return non-zero if error. */ -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { if (all) entire_flash_locked = 1; @@ -142,7 +140,7 @@ int flash_physical_protect_now(int all) * * Uses the EC_FLASH_PROTECT_* flags from ec_commands.h */ -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { uint32_t flags = 0; @@ -162,10 +160,9 @@ uint32_t flash_physical_get_protect_flags(void) * * @return A combination of EC_FLASH_PROTECT_* flags from ec_commands.h */ -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ALL_NOW; } @@ -175,15 +172,16 @@ uint32_t flash_physical_get_valid_flags(void) * @param cur_flags The current flash protect flags. * @return A combination of EC_FLASH_PROTECT_* flags from ec_commands.h */ -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { uint32_t ret = 0; enum spi_flash_wp wp_status = SPI_WP_NONE; wp_status = spi_flash_check_wp(); - if (wp_status == SPI_WP_NONE || (wp_status == SPI_WP_HARDWARE && - !(cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED))) + if (wp_status == SPI_WP_NONE || + (wp_status == SPI_WP_HARDWARE && + !(cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED))) ret = EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW; if (!entire_flash_locked) @@ -204,7 +202,7 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) * @param range The range to protect. * @return EC_SUCCESS, or nonzero if error. */ -int flash_physical_protect_at_boot(uint32_t new_flags) +int crec_flash_physical_protect_at_boot(uint32_t new_flags) { int offset, size, ret; enum spi_flash_wp flashwp = SPI_WP_NONE; @@ -234,13 +232,13 @@ int flash_physical_protect_at_boot(uint32_t new_flags) * * Applies at-boot protection settings if necessary. */ -int flash_pre_init(void) +int crec_flash_pre_init(void) { - flash_physical_restore_state(); + crec_flash_physical_restore_state(); return EC_SUCCESS; } -int flash_physical_restore_state(void) +int crec_flash_physical_restore_state(void) { uint32_t reset_flags = system_get_reset_flags(); int version, size; @@ -253,7 +251,7 @@ int flash_physical_restore_state(void) */ if (reset_flags & EC_RESET_FLAG_SYSJUMP) { prev = (const struct flash_wp_state *)system_get_jump_tag( - FLASH_SYSJUMP_TAG, &version, &size); + FLASH_SYSJUMP_TAG, &version, &size); if (prev && version == FLASH_HOOK_VERSION && size == sizeof(*prev)) entire_flash_locked = prev->entire_flash_locked; diff --git a/chip/mchp/gpio.c b/chip/mchp/gpio.c index 1de74dafcc..3ad9d7b6e4 100644 --- a/chip/mchp/gpio.c +++ b/chip/mchp/gpio.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,18 +8,17 @@ #include "common.h" #include "gpio.h" #include "hooks.h" +#include "lpc_chip.h" #include "registers.h" #include "system.h" #include "task.h" +#include "tfdp_chip.h" #include "timer.h" #include "util.h" -#include "lpc_chip.h" -#include "tfdp_chip.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) - +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) struct gpio_int_mapping { int8_t girq_id; @@ -38,23 +37,73 @@ struct gpio_int_mapping { * 4 0200 - 0235 12 * 5 0240 - 0276 26 */ -static const struct gpio_int_mapping int_map[6] = { - { 11, 0 }, { 10, 1 }, { 9, 2 }, - { 8, 3 }, { 12, 4 }, { 26, 5 } +static const struct gpio_int_mapping int_map[] = { { 11, 0 }, { 10, 1 }, + { 9, 2 }, { 8, 3 }, + { 12, 4 }, { 26, 5 } }; +BUILD_ASSERT(ARRAY_SIZE(int_map) == MCHP_GPIO_MAX_PORT); + +/* + * These pins default to BGPO functionality. BGPO overrides GPIO Control + * register programming. If the pin is in the GPIO list the user wants to + * use the pin as GPIO and we must disable BGPIO functionality for this pin. + */ +struct bgpo_pin { + uint16_t pin; + uint8_t bgpo_pos; }; +static const struct bgpo_pin bgpo_list[] = { + { 0101, 1 }, /* GPIO 0101 */ + { 0102, 2 }, /* GPIO 0102 */ +#if defined(CHIP_FAMILY_MEC152X) + { 0253, 0 }, /* GPIO 0253 */ +#elif defined(CHIP_FAMILY_MEC170X) + { 0172, 3 }, /* GPIO 0172 */ +#endif +}; + +static const uint32_t bgpo_map[] = { +#if defined(CHIP_FAMILY_MEC152X) + 0, 0, (BIT(1) | BIT(2)), 0, 0, BIT(11) +#elif defined(CHIP_FAMILY_MEC170X) + 0, 0, (BIT(1) | BIT(2)), BIT(26), 0, 0 +#else + 0, 0, 0, 0, 0, 0 +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(bgpo_map) == MCHP_GPIO_MAX_PORT); +/* Check for BGPO capable pins on this port and disable BGPO feature */ +static void disable_bgpo(uint32_t port, uint32_t mask) +{ + int i, n; + uint32_t gpnum; + uint32_t m = bgpo_map[port] & mask; + + while (m) { + i = __builtin_ffs(m) - 1; + gpnum = (port * 32U) + i; + for (n = 0; n < ARRAY_SIZE(bgpo_list); n++) + if (gpnum == bgpo_list[n].pin) + MCHP_WKTIMER_BGPO_POWER &= + ~BIT(bgpo_list[n].bgpo_pos); + m &= ~BIT(i); + } +} /* * NOTE: GCC __builtin_ffs(val) returns (index + 1) of least significant * 1-bit of val or if val == 0 returns 0 */ void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) + enum gpio_alternate_func func) { int i; uint32_t val; + if (port >= MCHP_GPIO_MAX_PORT) + return; + while (mask) { i = __builtin_ffs(mask) - 1; val = MCHP_GPIO_CTL(port, i); @@ -98,18 +147,21 @@ void gpio_set_level(enum gpio_signal signal, int value) /* * Add support for new #ifdef CONFIG_CMD_GPIO_POWER_DOWN. - * If GPIO_POWER_DONW flag is set force GPIO Control to + * If GPIO_POWER_DOWN flag is set force GPIO Control to * GPIO input, interrupt detect disabled, power control field * in bits[3:2]=10b. * NOTE: if interrupt detect is enabled when pin is powered down * then a false edge may be detected. - * + * NOTE 2: MEC152x family implements input pad disable (bit[15]=1). */ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) { int i; uint32_t val; + if (port >= MCHP_GPIO_MAX_PORT) + return; + while (mask) { i = GPIO_MASK_TO_NUM(mask); mask &= ~BIT(i); @@ -117,15 +169,18 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) #ifdef CONFIG_GPIO_POWER_DOWN if (flags & GPIO_POWER_DOWN) { - val = (MCHP_GPIO_CTRL_PWR_OFF + - MCHP_GPIO_INTDET_DISABLED); + val = (MCHP_GPIO_CTRL_PWR_OFF | + MCHP_GPIO_INTDET_DISABLED | + MCHP_GPIO_CTRL_DIS_INPUT_BIT); + MCHP_GPIO_CTL(port, i) = val; continue; } #endif - val &= ~(MCHP_GPIO_CTRL_PWR_MASK); - val |= MCHP_GPIO_CTRL_PWR_VTR; + val &= ~(MCHP_GPIO_CTRL_PWR_MASK | + MCHP_GPIO_CTRL_DIS_INPUT_BIT); + val |= MCHP_GPIO_CTRL_PWR_VTR; /* * Select open drain first, so that we don't * glitch the signal when changing the line to @@ -190,12 +245,15 @@ void gpio_power_off_by_mask(uint32_t port, uint32_t mask) { int i; + if (port >= MCHP_GPIO_MAX_PORT) + return; + while (mask) { i = GPIO_MASK_TO_NUM(mask); mask &= ~BIT(i); - - MCHP_GPIO_CTL(port, i) = (MCHP_GPIO_CTRL_PWR_OFF + - MCHP_GPIO_INTDET_DISABLED); + MCHP_GPIO_CTL(port, i) = + (MCHP_GPIO_CTRL_PWR_OFF | MCHP_GPIO_INTDET_DISABLED | + MCHP_GPIO_CTRL_DIS_INPUT_BIT); } } @@ -208,9 +266,9 @@ int gpio_power_off(enum gpio_signal signal) i = GPIO_MASK_TO_NUM(gpio_list[signal].mask); port = gpio_list[signal].port; - - MCHP_GPIO_CTL(port, i) = (MCHP_GPIO_CTRL_PWR_OFF + - MCHP_GPIO_INTDET_DISABLED); + MCHP_GPIO_CTL(port, i) = + (MCHP_GPIO_CTRL_PWR_OFF | MCHP_GPIO_INTDET_DISABLED | + MCHP_GPIO_CTRL_DIS_INPUT_BIT); return EC_SUCCESS; } @@ -253,7 +311,6 @@ int gpio_disable_interrupt(enum gpio_signal signal) port = gpio_list[signal].port; girq_id = int_map[port].girq_id; - MCHP_INT_DISABLE(girq_id) = BIT(i); return EC_SUCCESS; @@ -309,7 +366,6 @@ void gpio_pre_init(void) int is_warm = system_is_reboot_warm(); const struct gpio_info *g = gpio_list; - for (i = 0; i < GPIO_COUNT; i++, g++) { flags = g->flags; @@ -323,11 +379,13 @@ void gpio_pre_init(void) if (is_warm) flags &= ~(GPIO_LOW | GPIO_HIGH); + disable_bgpo(g->port, g->mask); + gpio_set_flags_by_mask(g->port, g->mask, flags); /* Use as GPIO, not alternate function */ gpio_set_alternate_function(g->port, g->mask, - GPIO_ALT_FUNC_NONE); + GPIO_ALT_FUNC_NONE); } } @@ -343,14 +401,13 @@ void gpio_pre_init(void) * assumption for the GPIO's that have been enabled. * 2. Clear NVIC pending to prevent ISR firing on false edge. */ -#define ENABLE_GPIO_GIRQ(x) \ - do { \ - MCHP_INT_SOURCE(x) = 0xfffffffful; \ - task_clear_pending_irq(MCHP_IRQ_GIRQ ## x); \ - task_enable_irq(MCHP_IRQ_GIRQ ## x); \ +#define ENABLE_GPIO_GIRQ(x) \ + do { \ + MCHP_INT_SOURCE(x) = 0xfffffffful; \ + task_clear_pending_irq(MCHP_IRQ_GIRQ##x); \ + task_enable_irq(MCHP_IRQ_GIRQ##x); \ } while (0) - static void gpio_init(void) { ENABLE_GPIO_GIRQ(8); @@ -365,7 +422,6 @@ DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); /************************************************************************/ /* Interrupt handlers */ - /** * Handler for each GIRQ interrupt. This reads and clears the interrupt * bits for the GIRQ interrupt, then finds and calls the corresponding @@ -386,8 +442,8 @@ static void gpio_interrupt(int girq, int port) MCHP_INT_SOURCE(girq) = sts; trace12(0, GPIO, 0, "GPIO GIRQ %d result = 0x%08x", girq, sts); - trace12(0, GPIO, 0, "GPIO ParIn[%d] = 0x%08x", - port, MCHP_GPIO_PARIN(port)); + trace12(0, GPIO, 0, "GPIO ParIn[%d] = 0x%08x", port, + MCHP_GPIO_PARIN(port)); for (i = 0; (i < GPIO_IH_COUNT) && sts; ++i, ++g) { if (g->port != port) @@ -397,9 +453,8 @@ static void gpio_interrupt(int girq, int port) if (bit) { bit--; if (sts & BIT(bit)) { - trace12(0, GPIO, 0, - "Bit[%d]: handler @ 0x%08x", bit, - (uint32_t)gpio_irq_handlers[i]); + trace12(0, GPIO, 0, "Bit[%d]: handler @ 0x%08x", + bit, (uint32_t)gpio_irq_handlers[i]); gpio_irq_handlers[i](i); } sts &= ~BIT(bit); @@ -407,10 +462,10 @@ static void gpio_interrupt(int girq, int port) } } -#define GPIO_IRQ_FUNC(irqfunc, girq, port)\ - void irqfunc(void) \ - { \ - gpio_interrupt(girq, port);\ +#define GPIO_IRQ_FUNC(irqfunc, girq, port) \ + static void irqfunc(void) \ + { \ + gpio_interrupt(girq, port); \ } GPIO_IRQ_FUNC(__girq_8_interrupt, 8, 3); @@ -432,4 +487,3 @@ DECLARE_IRQ(MCHP_IRQ_GIRQ10, __girq_10_interrupt, 1); DECLARE_IRQ(MCHP_IRQ_GIRQ11, __girq_11_interrupt, 1); DECLARE_IRQ(MCHP_IRQ_GIRQ12, __girq_12_interrupt, 1); DECLARE_IRQ(MCHP_IRQ_GIRQ26, __girq_26_interrupt, 1); - diff --git a/chip/mchp/gpio_chip.h b/chip/mchp/gpio_chip.h index 7baaa76fa2..ec0f3d2278 100644 --- a/chip/mchp/gpio_chip.h +++ b/chip/mchp/gpio_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -13,11 +13,11 @@ #ifndef _GPIO_CHIP_H #define _GPIO_CHIP_H -#include -#include - #include "gpio.h" +#include +#include + #ifdef __cplusplus extern "C" { #endif @@ -35,4 +35,3 @@ void gpio_power_off_by_mask(uint32_t port, uint32_t mask); #endif /* #ifndef _GPIO_CHIP_H */ /** @} */ - diff --git a/chip/mchp/gpio_cmds.c b/chip/mchp/gpio_cmds.c index cbf5f4c462..a53f8cca2a 100644 --- a/chip/mchp/gpio_cmds.c +++ b/chip/mchp/gpio_cmds.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,20 +8,18 @@ #include "common.h" #include "console.h" #include "gpio.h" +#include "gpio_chip.h" #include "hooks.h" #include "registers.h" #include "system.h" -#include "util.h" -#include "gpio_chip.h" #include "tfdp_chip.h" +#include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) - - -static int cmd_gp_get_config(int argc, char **argv) +static int cmd_gp_get_config(int argc, const char **argv) { char *e; int i; @@ -43,7 +41,7 @@ static int cmd_gp_get_config(int argc, char **argv) } else { /* Otherwise print them all */ for (i = 0; i < GPIO_COUNT; i++) { if (!gpio_is_implemented(i)) - continue; /* Skip unsupported signals */ + continue; /* Skip unsupported signals */ gctrl = MCHP_GPIO_CTRL(i); @@ -56,11 +54,10 @@ static int cmd_gp_get_config(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(gpgetcfg, cmd_gp_get_config, - "[number]", +DECLARE_CONSOLE_COMMAND(gpgetcfg, cmd_gp_get_config, "[number]", "Read GPIO config"); -static int cmd_gp_set_config(int argc, char **argv) +static int cmd_gp_set_config(int argc, const char **argv) { char *e; int i; @@ -91,7 +88,5 @@ static int cmd_gp_set_config(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(gpsetcfg, cmd_gp_set_config, - "gp_num val", +DECLARE_CONSOLE_COMMAND(gpsetcfg, cmd_gp_set_config, "gp_num val", "Set GPIO config"); - diff --git a/chip/mchp/gpspi.c b/chip/mchp/gpspi.c index 4edf57ee11..a7f7b388c4 100644 --- a/chip/mchp/gpspi.c +++ b/chip/mchp/gpspi.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,18 +9,18 @@ #include "console.h" #include "dma.h" #include "gpio.h" +#include "gpspi_chip.h" +#include "hooks.h" #include "registers.h" #include "spi.h" -#include "timer.h" -#include "util.h" -#include "hooks.h" -#include "task.h" #include "spi_chip.h" -#include "gpspi_chip.h" +#include "task.h" #include "tfdp_chip.h" +#include "timer.h" +#include "util.h" #define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) #define SPI_BYTE_TRANSFER_TIMEOUT_US (3 * MSEC) /* One byte at 12 MHz full duplex = 0.67 us */ @@ -91,8 +91,8 @@ static int gpspi_tx(const int ctrl, const uint8_t *txdata, int txlen) #endif int gpspi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) { int hw_port, ctrl; int ret = EC_SUCCESS; @@ -212,7 +212,7 @@ int gpspi_transaction_wait(const struct spi_device_t *spi_device) } /** - * Enable GPSPI controller and MODULE_SPI_MASTER pins + * Enable GPSPI controller and MODULE_SPI_CONTROLLER pins * * @param hw_port b[7:4]=1 b[3:0]=0(GPSPI0), 1(GPSPI1) * @param enable @@ -227,12 +227,11 @@ int gpspi_enable(int hw_port, int enable) if ((hw_port != GPSPI0_PORT) && (hw_port != GPSPI1_PORT)) return EC_ERROR_INVAL; - gpio_config_module(MODULE_SPI_MASTER, (enable > 0)); + gpio_config_module(MODULE_SPI_CONTROLLER, (enable > 0)); ctrl = (uint32_t)hw_port & 0x0f; if (enable) { - if (ctrl) MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_GPSPI1); else @@ -264,4 +263,3 @@ int gpspi_enable(int hw_port, int enable) return EC_SUCCESS; } - diff --git a/chip/mchp/gpspi_chip.h b/chip/mchp/gpspi_chip.h index 529a727e36..16c3208410 100644 --- a/chip/mchp/gpspi_chip.h +++ b/chip/mchp/gpspi_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -13,8 +13,8 @@ #ifndef _GPSPI_CHIP_H #define _GPSPI_CHIP_H -#include #include +#include /* struct spi_device_t */ #include "spi.h" @@ -24,12 +24,11 @@ int gpspi_transaction_flush(const struct spi_device_t *spi_device); int gpspi_transaction_wait(const struct spi_device_t *spi_device); int gpspi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen); + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen); int gpspi_enable(int port, int enable); #endif /* #ifndef _GPSPI_CHIP_H */ /** @} */ - diff --git a/chip/mchp/hwtimer.c b/chip/mchp/hwtimer.c index e84f278f4a..c72140b18f 100644 --- a/chip/mchp/hwtimer.c +++ b/chip/mchp/hwtimer.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,13 +11,12 @@ #include "hwtimer.h" #include "registers.h" #include "task.h" -#include "timer.h" #include "tfdp_chip.h" +#include "timer.h" void __hw_clock_event_set(uint32_t deadline) { - MCHP_TMR32_CNT(1) = MCHP_TMR32_CNT(0) - - (0xffffffff - deadline); + MCHP_TMR32_CNT(1) = MCHP_TMR32_CNT(0) - (0xffffffff - deadline); MCHP_TMR32_CTL(1) |= BIT(5); } @@ -49,16 +48,21 @@ void __hw_clock_source_set(uint32_t ts) static void __hw_clock_source_irq(int timer_id) { MCHP_TMR32_STS(timer_id & 0x01) |= 1; - MCHP_INT_SOURCE(MCHP_TMR32_GIRQ) = - MCHP_TMR32_GIRQ_BIT(timer_id & 0x01); + MCHP_INT_SOURCE(MCHP_TMR32_GIRQ) = MCHP_TMR32_GIRQ_BIT(timer_id & 0x01); /* If IRQ is from timer 0, 32-bit timer overflowed */ process_timers(timer_id == 0); } -void __hw_clock_source_irq_0(void) { __hw_clock_source_irq(0); } +static void __hw_clock_source_irq_0(void) +{ + __hw_clock_source_irq(0); +} DECLARE_IRQ(MCHP_IRQ_TIMER32_0, __hw_clock_source_irq_0, 1); -void __hw_clock_source_irq_1(void) { __hw_clock_source_irq(1); } +static void __hw_clock_source_irq_1(void) +{ + __hw_clock_source_irq(1); +} DECLARE_IRQ(MCHP_IRQ_TIMER32_1, __hw_clock_source_irq_1, 1); static void configure_timer(int timer_id) @@ -88,7 +92,7 @@ static void configure_timer(int timer_id) int __hw_clock_source_init(uint32_t start_t) { MCHP_PCR_SLP_DIS_DEV_MASK(3, MCHP_PCR_SLP_EN3_BTMR32_0 + - MCHP_PCR_SLP_EN3_BTMR32_1); + MCHP_PCR_SLP_EN3_BTMR32_1); /* * The timer can only fire interrupt when its value reaches zero. @@ -111,8 +115,8 @@ int __hw_clock_source_init(uint32_t start_t) /* Enable interrupt */ task_enable_irq(MCHP_IRQ_TIMER32_0); task_enable_irq(MCHP_IRQ_TIMER32_1); - MCHP_INT_ENABLE(MCHP_TMR32_GIRQ) = MCHP_TMR32_GIRQ_BIT(0) + - MCHP_TMR32_GIRQ_BIT(1); + MCHP_INT_ENABLE(MCHP_TMR32_GIRQ) = + MCHP_TMR32_GIRQ_BIT(0) + MCHP_TMR32_GIRQ_BIT(1); /* * Not needed when using direct mode interrupts * MCHP_INT_BLK_EN |= BIT(MCHP_TMR32_GIRQ); diff --git a/chip/mchp/i2c.c b/chip/mchp/i2c.c index da7136a6b2..2b21d17dc4 100644 --- a/chip/mchp/i2c.c +++ b/chip/mchp/i2c.c @@ -1,50 +1,55 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* I2C port module for MCHP MEC - * TODO handle chip variants - */ +/* I2C port module for MCHP MEC */ #include "common.h" #include "console.h" #include "gpio.h" #include "hooks.h" #include "i2c.h" +#include "i2c_chip.h" #include "registers.h" #include "task.h" +#include "tfdp_chip.h" #include "timer.h" #include "util.h" -#include "tfdp_chip.h" #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) /* * MCHP I2C BAUD clock source is 16 MHz. */ -#define I2C_CLOCK 16000000 /* 16 MHz */ +#define I2C_CLOCK 16000000UL +#define MCHP_I2C_SUPPORTED_BUS_CLOCKS 6 /* SMBus Timing values for 1MHz Speed */ -#define SPEED_1MHZ_BUS_CLOCK 0x0509 -#define SPEED_1MHZ_DATA_TIMING 0x06060601 -#define SPEED_1MHZ_DATA_TIMING_2 0x06 -#define SPEED_1MHZ_IDLE_SCALING 0x01000050 -#define SPEED_1MHZ_TIMEOUT_SCALING 0x149CC2C7 +#define SPEED_1MHZ_BUS_CLOCK 0x0509ul +#define SPEED_1MHZ_DATA_TIMING 0x06060601ul +#define SPEED_1MHZ_DATA_TIMING_2 0x06ul +#define SPEED_1MHZ_IDLE_SCALING 0x01000050ul +#define SPEED_1MHZ_TIMEOUT_SCALING 0x149CC2C7ul /* SMBus Timing values for 400kHz speed */ -#define SPEED_400KHZ_BUS_CLOCK 0x0F17 -#define SPEED_400KHZ_DATA_TIMING 0x040A0F01 -#define SPEED_400KHZ_DATA_TIMING_2 0x0A -#define SPEED_400KHZ_IDLE_SCALING 0x01000050 -#define SPEED_400KHZ_TIMEOUT_SCALING 0x149CC2C7 +#define SPEED_400KHZ_BUS_CLOCK 0x0F17ul +#define SPEED_400KHZ_DATA_TIMING 0x040A0F01ul +#define SPEED_400KHZ_DATA_TIMING_2 0x0Aul +#define SPEED_400KHZ_IDLE_SCALING 0x01000050ul +#define SPEED_400KHZ_TIMEOUT_SCALING 0x149CC2C7ul /* SMBus Timing values for 100kHz speed */ -#define SPEED_100KHZ_BUS_CLOCK 0x4F4Ful -#define SPEED_100KHZ_DATA_TIMING 0x0C4D4306ul -#define SPEED_100KHZ_DATA_TIMING_2 0x4Dul -#define SPEED_100KHZ_IDLE_SCALING 0x01FC01EDul -#define SPEED_100KHZ_TIMEOUT_SCALING 0x4B9CC2C7ul +#define SPEED_100KHZ_BUS_CLOCK 0x4F4Ful +#define SPEED_100KHZ_DATA_TIMING 0x0C4D4306ul +#define SPEED_100KHZ_DATA_TIMING_2 0x4Dul +#define SPEED_100KHZ_IDLE_SCALING 0x01FC01EDul +#define SPEED_100KHZ_TIMEOUT_SCALING 0x4B9CC2C7ul +/* Bus clock dividers for 333, 80, and 40 kHz */ +#define SPEED_333KHZ_BUS_CLOCK 0x0F1Ful +#define SPEED_80KHZ_BUS_CLOCK 0x6363ul +#define SPEED_40KHZ_BUS_CLOCK 0xC7C7ul + /* Status */ #define STS_NBB BIT(0) /* Bus busy */ #define STS_LAB BIT(1) /* Arbitration lost */ @@ -59,37 +64,37 @@ #define CTRL_ESO BIT(6) /* Enable serial output */ #define CTRL_PIN BIT(7) /* Pending interrupt not */ /* Completion */ -#define COMP_DTEN BIT(2) /* enable device timeouts */ -#define COMP_MCEN BIT(3) /* enable master cumulative timeouts */ -#define COMP_SCEN BIT(4) /* enable slave cumulative timeouts */ -#define COMP_BIDEN BIT(5) /* enable Bus idle timeouts */ -#define COMP_IDLE BIT(29) /* i2c bus is idle */ +#define COMP_DTEN BIT(2) /* enable device timeouts */ +#define COMP_MCEN BIT(3) /* enable ctrl. cumulative timeouts */ +#define COMP_SCEN BIT(4) /* enable periph. cumulative timeouts */ +#define COMP_BIDEN BIT(5) /* enable Bus idle timeouts */ +#define COMP_IDLE BIT(29) /* i2c bus is idle */ #define COMP_RW_BITS_MASK 0x3C /* R/W bits mask */ /* Configuration */ -#define CFG_PORT_MASK (0x0F) /* port selection field */ -#define CFG_TCEN BIT(4) /* Enable HW bus timeouts */ -#define CFG_FEN BIT(8) /* enable input filtering */ -#define CFG_RESET BIT(9) /* reset controller */ -#define CFG_ENABLE BIT(10) /* enable controller */ -#define CFG_GC_DIS BIT(14) /* disable general call address */ -#define CFG_ENIDI BIT(29) /* Enable I2C idle interrupt */ -/* Enable network layer master done interrupt */ -#define CFG_ENMI BIT(30) -/* Enable network layer slave done interrupt */ -#define CFG_ENSI BIT(31) -/* Master Command */ -#define MCMD_MRUN BIT(0) -#define MCMD_MPROCEED BIT(1) -#define MCMD_START0 BIT(8) -#define MCMD_STARTN BIT(9) -#define MCMD_STOP BIT(10) -#define MCMD_READM BIT(12) -#define MCMD_WCNT_BITPOS (16) -#define MCMD_WCNT_MASK0 (0xFF) -#define MCMD_WCNT_MASK (0xFF << 16) -#define MCMD_RCNT_BITPOS (24) -#define MCMD_RCNT_MASK0 (0xFF) -#define MCMD_RCNT_MASK (0xFF << 24) +#define CFG_PORT_MASK (0x0F) /* port selection field */ +#define CFG_TCEN BIT(4) /* Enable HW bus timeouts */ +#define CFG_FEN BIT(8) /* enable input filtering */ +#define CFG_RESET BIT(9) /* reset controller */ +#define CFG_ENABLE BIT(10) /* enable controller */ +#define CFG_GC_DIS BIT(14) /* disable general call address */ +#define CFG_ENIDI BIT(29) /* Enable I2C idle interrupt */ +/* Enable network layer controller done interrupt */ +#define CFG_ENMI BIT(30) +/* Enable network layer peripheral done interrupt */ +#define CFG_ENSI BIT(31) +/* Controller Command */ +#define MCMD_MRUN BIT(0) +#define MCMD_MPROCEED BIT(1) +#define MCMD_START0 BIT(8) +#define MCMD_STARTN BIT(9) +#define MCMD_STOP BIT(10) +#define MCMD_READM BIT(12) +#define MCMD_WCNT_BITPOS (16) +#define MCMD_WCNT_MASK0 (0xFF) +#define MCMD_WCNT_MASK (0xFF << 16) +#define MCMD_RCNT_BITPOS (24) +#define MCMD_RCNT_MASK0 (0xFF) +#define MCMD_RCNT_MASK (0xFF << 24) /* Maximum transfer of a SMBUS block transfer */ #define SMBUS_MAX_BLOCK_SIZE 32 @@ -132,7 +137,7 @@ static struct { uint32_t i2c_complete; /* ISR write */ uint32_t flags; uint8_t port; - uint8_t slv_addr_8bit; + uint8_t periph_addr_8bit; uint8_t ctrl; uint8_t hwsts; uint8_t hwsts2; @@ -141,18 +146,62 @@ static struct { uint8_t lines; } cdata[I2C_CONTROLLER_COUNT]; -static const uint16_t i2c_controller_pcr[MCHP_I2C_CTRL_MAX] = { - MCHP_PCR_I2C0, - MCHP_PCR_I2C1, - MCHP_PCR_I2C2, - MCHP_PCR_I2C3 +static const uint16_t i2c_ctrl_nvic_id[] = { MCHP_IRQ_I2C_0, MCHP_IRQ_I2C_1, + MCHP_IRQ_I2C_2, MCHP_IRQ_I2C_3, +#if defined(CHIP_FAMILY_MEC172X) + MCHP_IRQ_I2C_4 +#elif defined(CHIP_FAMILY_MEC152X) + MCHP_IRQ_I2C_4, MCHP_IRQ_I2C_5, + MCHP_IRQ_I2C_6, MCHP_IRQ_I2C_7 +#endif }; +BUILD_ASSERT(ARRAY_SIZE(i2c_ctrl_nvic_id) == MCHP_I2C_CTRL_MAX); + +static const uint16_t i2c_controller_pcr[] = { MCHP_PCR_I2C0, MCHP_PCR_I2C1, + MCHP_PCR_I2C2, MCHP_PCR_I2C3, +#if defined(CHIP_FAMILY_MEC172X) + MCHP_PCR_I2C4 +#elif defined(CHIP_FAMILY_MEC152X) + MCHP_PCR_I2C4, MCHP_PCR_I2C5, MCHP_PCR_I2C6, MCHP_PCR_I2C7, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_controller_pcr) == MCHP_I2C_CTRL_MAX); + +static uintptr_t i2c_ctrl_base_addr[] = { MCHP_I2C0_BASE, MCHP_I2C1_BASE, + MCHP_I2C2_BASE, MCHP_I2C3_BASE, +#if defined(CHIP_FAMILY_MEC172X) + MCHP_I2C4_BASE +#elif defined(CHIP_FAMILY_MEC152X) + MCHP_I2C4_BASE, + /* NOTE: 5-7 do not implement network + layer hardware */ + MCHP_I2C5_BASE, MCHP_I2C6_BASE, + MCHP_I2C7_BASE +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_ctrl_base_addr) == MCHP_I2C_CTRL_MAX); -static int chip_i2c_is_controller_valid(int controller) +static bool chip_i2c_is_controller_valid(int controller) { if ((controller < 0) || (controller >= MCHP_I2C_CTRL_MAX)) + return false; + return true; +} + +static uintptr_t chip_i2c_ctrl_base(int controller) +{ + if (!chip_i2c_is_controller_valid(controller)) return 0; - return 1; + + return i2c_ctrl_base_addr[controller]; +} + +static uint32_t chip_i2c_ctrl_nvic_id(int controller) +{ + if (!chip_i2c_is_controller_valid(controller)) + return 0; + + return (uint32_t)i2c_ctrl_nvic_id[controller]; } static void i2c_ctrl_slp_en(int controller, int sleep_en) @@ -184,39 +233,38 @@ struct i2c_bus_clk { }; const struct i2c_bus_clk i2c_freq_tbl[] = { - { 40, 0xC7C7 }, - { 80, 0x6363 }, - { 100, 0x4F4F }, - { 333, 0x0F1F }, - { 400, 0x0F17 }, - { 1000, 0x0509 }, + { 40, SPEED_40KHZ_BUS_CLOCK }, { 80, SPEED_80KHZ_BUS_CLOCK }, + { 100, SPEED_100KHZ_BUS_CLOCK }, { 333, SPEED_333KHZ_BUS_CLOCK }, + { 400, SPEED_400KHZ_BUS_CLOCK }, { 1000, SPEED_1MHZ_BUS_CLOCK }, }; +BUILD_ASSERT(ARRAY_SIZE(i2c_freq_tbl) == MCHP_I2C_SUPPORTED_BUS_CLOCKS); + +/* I2C controller assignment to a port */ +static int i2c_p2c[MCHP_I2C_PORT_COUNT]; static int get_closest(int lesser, int greater, int target) { if (target - i2c_freq_tbl[lesser].freq_khz >= - i2c_freq_tbl[greater].freq_khz - target) + i2c_freq_tbl[greater].freq_khz - target) return greater; else return lesser; } /* - * Return index in i2c_freq_tbl of supported frequeny + * Return index in i2c_freq_tbl of supported frequencies * closest to requested frequency. */ static const struct i2c_bus_clk *get_supported_speed_idx(int req_kbps) { int i, limit, m, imax; - ASSERT(ARRAY_SIZE(i2c_freq_tbl) != 0); - if (req_kbps <= i2c_freq_tbl[0].freq_khz) return &i2c_freq_tbl[0]; imax = ARRAY_SIZE(i2c_freq_tbl); - if (req_kbps >= i2c_freq_tbl[imax-1].freq_khz) - return &i2c_freq_tbl[imax-1]; + if (req_kbps >= i2c_freq_tbl[imax - 1].freq_khz) + return &i2c_freq_tbl[imax - 1]; /* we only get here if ARRAY_SIZE(...) > 1 * and req_kbps is in range. @@ -229,15 +277,15 @@ static const struct i2c_bus_clk *get_supported_speed_idx(int req_kbps) break; if (req_kbps < i2c_freq_tbl[m].freq_khz) { - if (m > 0 && req_kbps > i2c_freq_tbl[m-1].freq_khz) { - m = get_closest(m-1, m, req_kbps); + if (m > 0 && req_kbps > i2c_freq_tbl[m - 1].freq_khz) { + m = get_closest(m - 1, m, req_kbps); break; } limit = m; } else { - if (m < imax-1 && - req_kbps < i2c_freq_tbl[m+1].freq_khz) { - m = get_closest(m, m+1, req_kbps); + if (m < imax - 1 && + req_kbps < i2c_freq_tbl[m + 1].freq_khz) { + m = get_closest(m, m + 1, req_kbps); break; } i = m + 1; @@ -258,25 +306,28 @@ static const struct i2c_bus_clk *get_supported_speed_idx(int req_kbps) static void configure_controller_speed(int controller, int kbps) { const struct i2c_bus_clk *p; + uintptr_t raddr; + + raddr = chip_i2c_ctrl_base(controller); p = get_supported_speed_idx(kbps); - MCHP_I2C_BUS_CLK(controller) = p->bus_clk; + MCHP_I2C_BUS_CLK(raddr) = p->bus_clk; if (p->freq_khz > 400) { /* Fast mode plus */ - MCHP_I2C_DATA_TIM(controller) = SPEED_1MHZ_DATA_TIMING; - MCHP_I2C_DATA_TIM_2(controller) = SPEED_1MHZ_DATA_TIMING_2; - MCHP_I2C_IDLE_SCALE(controller) = SPEED_1MHZ_IDLE_SCALING; - MCHP_I2C_TOUT_SCALE(controller) = SPEED_1MHZ_TIMEOUT_SCALING; + MCHP_I2C_DATA_TIM(raddr) = SPEED_1MHZ_DATA_TIMING; + MCHP_I2C_DATA_TIM_2(raddr) = SPEED_1MHZ_DATA_TIMING_2; + MCHP_I2C_IDLE_SCALE(raddr) = SPEED_1MHZ_IDLE_SCALING; + MCHP_I2C_TOUT_SCALE(raddr) = SPEED_1MHZ_TIMEOUT_SCALING; } else if (p->freq_khz > 100) { /* Fast mode */ - MCHP_I2C_DATA_TIM(controller) = SPEED_400KHZ_DATA_TIMING; - MCHP_I2C_DATA_TIM_2(controller) = SPEED_400KHZ_DATA_TIMING_2; - MCHP_I2C_IDLE_SCALE(controller) = SPEED_400KHZ_IDLE_SCALING; - MCHP_I2C_TOUT_SCALE(controller) = SPEED_400KHZ_TIMEOUT_SCALING; + MCHP_I2C_DATA_TIM(raddr) = SPEED_400KHZ_DATA_TIMING; + MCHP_I2C_DATA_TIM_2(raddr) = SPEED_400KHZ_DATA_TIMING_2; + MCHP_I2C_IDLE_SCALE(raddr) = SPEED_400KHZ_IDLE_SCALING; + MCHP_I2C_TOUT_SCALE(raddr) = SPEED_400KHZ_TIMEOUT_SCALING; } else { /* Standard mode */ - MCHP_I2C_DATA_TIM(controller) = SPEED_100KHZ_DATA_TIMING; - MCHP_I2C_DATA_TIM_2(controller) = SPEED_100KHZ_DATA_TIMING_2; - MCHP_I2C_IDLE_SCALE(controller) = SPEED_100KHZ_IDLE_SCALING; - MCHP_I2C_TOUT_SCALE(controller) = SPEED_100KHZ_TIMEOUT_SCALING; + MCHP_I2C_DATA_TIM(raddr) = SPEED_100KHZ_DATA_TIMING; + MCHP_I2C_DATA_TIM_2(raddr) = SPEED_100KHZ_DATA_TIMING_2; + MCHP_I2C_IDLE_SCALE(raddr) = SPEED_100KHZ_IDLE_SCALING; + MCHP_I2C_TOUT_SCALE(raddr) = SPEED_100KHZ_TIMEOUT_SCALING; } } @@ -286,70 +337,79 @@ static void configure_controller_speed(int controller, int kbps) */ static void enable_controller_irq(int controller) { - MCHP_INT_ENABLE(MCHP_I2C_GIRQ) = - MCHP_I2C_GIRQ_BIT(controller); - task_enable_irq(MCHP_IRQ_I2C_0 + controller); + uint32_t nvic_id = chip_i2c_ctrl_nvic_id(controller); + + MCHP_INT_ENABLE(MCHP_I2C_GIRQ) = MCHP_I2C_GIRQ_BIT(controller); + task_enable_irq(nvic_id); } static void disable_controller_irq(int controller) { - MCHP_INT_DISABLE(MCHP_I2C_GIRQ) = - MCHP_I2C_GIRQ_BIT(controller); + uint32_t nvic_id = chip_i2c_ctrl_nvic_id(controller); + + MCHP_INT_DISABLE(MCHP_I2C_GIRQ) = MCHP_I2C_GIRQ_BIT(controller); /* read back into read-only reg. to insure disable takes effect */ MCHP_INT_BLK_IRQ = MCHP_INT_DISABLE(MCHP_I2C_GIRQ); - task_disable_irq(MCHP_IRQ_I2C_0 + controller); - task_clear_pending_irq(MCHP_IRQ_I2C_0 + controller); + task_disable_irq(nvic_id); + task_clear_pending_irq(nvic_id); } /* * Do NOT enable controller's IDLE interrupt in the configuration - * register. IDLE is meant for mult-master and controller as slave. + * register. IDLE is meant for multi-controller and controller acting + * as a peripheral. */ static void configure_controller(int controller, int port, int kbps) { - if (!chip_i2c_is_controller_valid(controller)) + uintptr_t raddr = chip_i2c_ctrl_base(controller); + + if (raddr == 0) return; disable_controller_irq(controller); - MCHP_INT_SOURCE(MCHP_I2C_GIRQ) = - MCHP_I2C_GIRQ_BIT(controller); + MCHP_INT_SOURCE(MCHP_I2C_GIRQ) = MCHP_I2C_GIRQ_BIT(controller); /* set to default except for port select field b[3:0] */ - MCHP_I2C_CONFIG(controller) = (uint32_t)(port & 0xf); - MCHP_I2C_CTRL(controller) = CTRL_PIN; + MCHP_I2C_CONFIG(raddr) = (uint32_t)(port & 0xf); + MCHP_I2C_CTRL(raddr) = CTRL_PIN; - /* Set both controller slave addresses to 0 the + /* Set both controller peripheral addresses to 0 the * general call address. We disable general call * below. */ - MCHP_I2C_OWN_ADDR(controller) = 0; + MCHP_I2C_OWN_ADDR(raddr) = 0; configure_controller_speed(controller, kbps); /* Controller timings done, clear RO status, enable * output, and ACK generation. */ - MCHP_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_ACK; /* filter enable, disable General Call */ - MCHP_I2C_CONFIG(controller) |= CFG_FEN + CFG_GC_DIS; + MCHP_I2C_CONFIG(raddr) |= CFG_FEN + CFG_GC_DIS; /* enable controller */ - MCHP_I2C_CONFIG(controller) |= CFG_ENABLE; + MCHP_I2C_CONFIG(raddr) |= CFG_ENABLE; } static void reset_controller(int controller) { int i; + uintptr_t raddr; + + raddr = chip_i2c_ctrl_base(controller); + if (raddr == 0) + return; /* Reset asserted for at least one AHB clock */ - MCHP_I2C_CONFIG(controller) |= BIT(9); + MCHP_I2C_CONFIG(raddr) |= BIT(9); MCHP_EC_ID_RO = 0; - MCHP_I2C_CONFIG(controller) &= ~BIT(9); + MCHP_I2C_CONFIG(raddr) &= ~BIT(9); for (i = 0; i < i2c_ports_used; ++i) if (controller == i2c_port_to_controller(i2c_ports[i].port)) { configure_controller(controller, i2c_ports[i].port, - i2c_ports[i].kbps); + i2c_ports[i].kbps); cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; break; @@ -383,18 +443,19 @@ static int wait_for_interrupt(int controller, int timeout) static int wait_idle(int controller) { - uint8_t sts = MCHP_I2C_STATUS(controller); + uintptr_t raddr = chip_i2c_ctrl_base(controller); uint64_t block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; uint64_t task_timeout = block_timeout + cdata[controller].timeout_us; int rv = 0; + uint8_t sts = MCHP_I2C_STATUS(raddr); while (!(sts & STS_NBB)) { if (rv) return rv; if (get_time().val > block_timeout) rv = wait_for_interrupt(controller, - task_timeout - get_time().val); - sts = MCHP_I2C_STATUS(controller); + task_timeout - get_time().val); + sts = MCHP_I2C_STATUS(raddr); } if (sts & (STS_BER | STS_LAB)) @@ -406,39 +467,41 @@ static int wait_idle(int controller) * Return EC_SUCCESS on ACK of byte else EC_ERROR_UNKNOWN. * Record I2C.Status in cdata[controller] structure. * Byte transmit finished with no I2C bus error or lost arbitration. - * PIN -> 0. LRB bit contains slave ACK/NACK bit. - * Slave ACK: I2C.Status == 0x00 - * Slave NACK: I2C.Status == 0x08 + * PIN -> 0. LRB bit contains peripheral ACK/NACK bit. + * Peripheral ACK: I2C.Status == 0x00 + * Peripheral NACK: I2C.Status == 0x08 * Byte transmit finished with I2C bus errors or lost arbitration. * PIN -> 0 and BER and/or LAB set. * * Byte receive finished with no I2C bus errors or lost arbitration. * PIN -> 0. LRB=0/1 based on ACK bit in I2C.Control. - * Master receiver must NACK last byte it wants to receive. + * Controller receiver must NACK last byte it wants to receive. * How do we handle this if we don't know direction of transfer? - * I2C.Control is write-only so we can't see Master's ACK control bit. - * + * I2C.Control is write-only so we can't see Controller's ACK control + * bit. */ static int wait_byte_done(int controller, uint8_t mask, uint8_t expected) { uint64_t block_timeout; uint64_t task_timeout; + uintptr_t raddr; int rv; uint8_t sts; rv = 0; + raddr = chip_i2c_ctrl_base(controller); block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; task_timeout = block_timeout + cdata[controller].timeout_us; - sts = MCHP_I2C_STATUS(controller); + sts = MCHP_I2C_STATUS(raddr); cdata[controller].hwsts = sts; while (sts & STS_PIN) { if (rv) return rv; if (get_time().val > block_timeout) { rv = wait_for_interrupt(controller, - task_timeout - get_time().val); + task_timeout - get_time().val); } - sts = MCHP_I2C_STATUS(controller); + sts = MCHP_I2C_STATUS(raddr); cdata[controller].hwsts = sts; } @@ -452,21 +515,23 @@ static int wait_byte_done(int controller, uint8_t mask, uint8_t expected) * Select port on controller. If controller configured * for port do nothing. * Switch port by reset and reconfigure to handle cases where - * the slave on current port is driving line(s) low. + * the peripheral on current port is driving line(s) low. * NOTE: I2C hardware reset only requires one AHB clock, back to back * writes is OK but we added an extra write as insurance. */ static void select_port(int port, int controller) { uint32_t port_sel; + uintptr_t raddr; + raddr = chip_i2c_ctrl_base(controller); port_sel = (uint32_t)(port & 0x0f); - if ((MCHP_I2C_CONFIG(controller) & 0x0f) == port_sel) + if ((MCHP_I2C_CONFIG(raddr) & 0x0f) == port_sel) return; - MCHP_I2C_CONFIG(controller) |= BIT(9); + MCHP_I2C_CONFIG(raddr) |= BIT(9); MCHP_EC_ID_RO = 0; /* extra write to read-only as delay */ - MCHP_I2C_CONFIG(controller) &= ~BIT(9); + MCHP_I2C_CONFIG(raddr) &= ~BIT(9); configure_controller(controller, port_sel, i2c_ports[port].kbps); } @@ -489,17 +554,20 @@ static uint32_t get_line_level(int port) /* * Check if I2C port connected to controller has bus error or - * other signalling issues such as stuck clock/data lines. + * other issues such as stuck clock/data lines. */ static int i2c_check_recover(int port, int controller) { + uintptr_t raddr; uint32_t lines; uint8_t reg; + + raddr = chip_i2c_ctrl_base(controller); lines = get_line_level(port); - reg = MCHP_I2C_STATUS(controller); + reg = MCHP_I2C_STATUS(raddr); if ((((reg & (STS_BER | STS_LAB)) || !(reg & STS_NBB)) || - (lines != I2C_LINE_IDLE))) { + (lines != I2C_LINE_IDLE))) { cdata[controller].flags |= (1ul << 16); CPRINTS("I2C%d port%d recov status 0x%02x, SDA:SCL=0x%0x", controller, port, reg, lines); @@ -512,14 +580,15 @@ static int i2c_check_recover(int port, int controller) reset_controller(controller); select_port(port, controller); /* - * We don't know what edges the slave saw, so sleep long enough - * that the slave will see the new start condition below. + * We don't know what edges the peripheral saw, so sleep long + * enough that the peripheral will see the new start condition + * below. */ usleep(1000); - reg = MCHP_I2C_STATUS(controller); + reg = MCHP_I2C_STATUS(raddr); lines = get_line_level(port); if ((reg & (STS_BER | STS_LAB)) || !(reg & STS_NBB) || - (lines != I2C_LINE_IDLE)) + (lines != I2C_LINE_IDLE)) return EC_ERROR_UNKNOWN; } return EC_SUCCESS; @@ -534,21 +603,23 @@ static inline void push_in_buf(uint8_t **in, uint8_t val, int skip) } /* - * I2C Master transmit + * I2C Controller transmit * Caller has filled in cdata[ctrl] parameters */ static int i2c_mtx(int ctrl) { + uintptr_t raddr; int i, rv; + raddr = chip_i2c_ctrl_base(ctrl); rv = EC_SUCCESS; cdata[ctrl].flags |= (1ul << 1); if (cdata[ctrl].xflags & I2C_XFER_START) { cdata[ctrl].flags |= (1ul << 2); - MCHP_I2C_DATA(ctrl) = cdata[ctrl].slv_addr_8bit; - /* Clock out the slave address, sending START bit */ - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | CTRL_ENI | - CTRL_ACK | CTRL_STA; + MCHP_I2C_DATA(raddr) = cdata[ctrl].periph_addr_8bit; + /* Clock out the peripheral address, sending START bit */ + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_ENI | + CTRL_ACK | CTRL_STA; cdata[ctrl].transaction_state = I2C_TRANSACTION_OPEN; } @@ -556,19 +627,19 @@ static int i2c_mtx(int ctrl) rv = wait_byte_done(ctrl, 0xff, 0x00); if (rv) { cdata[ctrl].flags |= (1ul << 17); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_ENI | CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | CTRL_ENI | + CTRL_STO | CTRL_ACK; return rv; } cdata[ctrl].flags |= (1ul << 15); - MCHP_I2C_DATA(ctrl) = cdata[ctrl].outp[i]; + MCHP_I2C_DATA(raddr) = cdata[ctrl].outp[i]; } rv = wait_byte_done(ctrl, 0xff, 0x00); if (rv) { cdata[ctrl].flags |= (1ul << 18); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | CTRL_ENI | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_ENI | + CTRL_STO | CTRL_ACK; return rv; } @@ -577,17 +648,17 @@ static int i2c_mtx(int ctrl) * doesn't expect to receive data. */ if ((cdata[ctrl].xflags & I2C_XFER_STOP) && - (cdata[ctrl].in_size == 0)) { + (cdata[ctrl].in_size == 0)) { cdata[ctrl].flags |= (1ul << 3); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_STO | + CTRL_ACK; cdata[ctrl].transaction_state = I2C_TRANSACTION_STOPPED; } return rv; } /* - * I2C Master-Receive helper routine for sending START or + * I2C Controller-Receive helper routine for sending START or * Repeated-START. * This routine should only be called if a (Repeated-)START * is required. @@ -602,10 +673,9 @@ static int i2c_mtx(int ctrl) * will generate START but not transmit data. * Write read address to I2C.Data. Controller will transmit * 8-bits of data - * Endif * NOTE: Controller clocks in address on SDA as its transmitting. * Therefore 1-byte RX-FIFO will contain address plus R/nW bit. - * Controller will wait for slave to release SCL before transmitting + * Controller will wait for peripheral to release SCL before transmitting * 9th clock and latching (N)ACK on SDA. * Spin on I2C.Status PIN -> 0. Enable I2C interrupt if spin time * exceeds threshold. If a timeout occurs generate STOP and return @@ -615,39 +685,42 @@ static int i2c_mtx(int ctrl) * register we must prepare control logic. * If the caller requests STOP and read length is 1 then set * clear ACK bit in I2C.Ctrl. Set ESO=ENI=1, PIN=STA=STO=ACK=0 - * in I2C.Ctrl. Master must NACK last byte. + * in I2C.Ctrl. Controller must NACK last byte. */ static int i2c_mrx_start(int ctrl) { - uint8_t u8; + uintptr_t raddr; int rv; + uint8_t u8; + + raddr = chip_i2c_ctrl_base(ctrl); cdata[ctrl].flags |= (1ul << 4); u8 = CTRL_ESO | CTRL_ENI | CTRL_STA | CTRL_ACK; if (cdata[ctrl].transaction_state == I2C_TRANSACTION_OPEN) { cdata[ctrl].flags |= (1ul << 5); /* Repeated-START then address */ - MCHP_I2C_CTRL(ctrl) = u8; + MCHP_I2C_CTRL(raddr) = u8; } - MCHP_I2C_DATA(ctrl) = cdata[ctrl].slv_addr_8bit | 0x01; + MCHP_I2C_DATA(raddr) = cdata[ctrl].periph_addr_8bit | 0x01; if (cdata[ctrl].transaction_state == I2C_TRANSACTION_STOPPED) { cdata[ctrl].flags |= (1ul << 6); /* address then START */ - MCHP_I2C_CTRL(ctrl) = u8 | CTRL_PIN; + MCHP_I2C_CTRL(raddr) = u8 | CTRL_PIN; } cdata[ctrl].transaction_state = I2C_TRANSACTION_OPEN; /* Controller generates START, transmits data(address) capturing * 9-bits from SDA (8-bit address + (N)Ack bit). * We leave captured address in I2C.Data register. - * Master Receive data read routine assumes data is pending + * Controller receive data read routine assumes data is pending * in I2C.Data */ cdata[ctrl].flags |= (1ul << 7); rv = wait_byte_done(ctrl, 0xff, 0x00); if (rv) { cdata[ctrl].flags |= (1ul << 19); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_STO | + CTRL_ACK; return rv; } /* if STOP requested and last 1 or 2 bytes prepare controller @@ -655,29 +728,28 @@ static int i2c_mrx_start(int ctrl) * controller is setup to NACK last byte. */ cdata[ctrl].flags |= (1ul << 8); - if (cdata[ctrl].xflags & I2C_XFER_STOP && - (cdata[ctrl].in_size < 2)) { + if (cdata[ctrl].xflags & I2C_XFER_STOP && (cdata[ctrl].in_size < 2)) { cdata[ctrl].flags |= (1ul << 9); - MCHP_I2C_CTRL(ctrl) = CTRL_ESO | CTRL_ENI; + MCHP_I2C_CTRL(raddr) = CTRL_ESO | CTRL_ENI; } /* - * Read & discard slave address. + * Read & discard peripheral address. * Generates clocks for next data */ cdata[ctrl].flags |= (1ul << 10); - u8 = MCHP_I2C_DATA(ctrl); + u8 = MCHP_I2C_DATA(raddr); return rv; } /* - * I2C Master-Receive data read helper. + * I2C Controller-Receive data read helper. * Assumes I2C is in use, (Rpt-)START was previously sent. * Reading I2C.Data generates clocks for the next byte. If caller * requests STOP then we must clear I2C.Ctrl ACK before reading * second to last byte from RX-FIFO data register. Before reading * the last byte we must set I2C.Ctrl to generate a stop after * the read from RX-FIFO register. - * NOTE: I2C.Status.LRB only records the (N)ACK bit in master - * transmit mode, not in master receive mode. + * NOTE: I2C.Status.LRB only records the (N)ACK bit in controller + * transmit mode, not in controller receive mode. * NOTE2: Do not set ENI bit in I2C.Ctrl for STOP generation. */ static int i2c_mrx_data(int ctrl) @@ -686,27 +758,30 @@ static int i2c_mrx_data(int ctrl) uint32_t stop = (uint32_t)cdata[ctrl].xflags & I2C_XFER_STOP; uint8_t *pdest = cdata[ctrl].inp; int rv; + uintptr_t raddr; + + raddr = chip_i2c_ctrl_base(ctrl); cdata[ctrl].flags |= (1ul << 11); while (nrx) { rv = wait_byte_done(ctrl, 0xff, 0x00); if (rv) { cdata[ctrl].flags |= (1ul << 20); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_STO | + CTRL_ACK; return rv; } if (stop) { if (nrx == 2) { cdata[ctrl].flags |= (1ul << 12); - MCHP_I2C_CTRL(ctrl) = CTRL_ESO | CTRL_ENI; + MCHP_I2C_CTRL(raddr) = CTRL_ESO | CTRL_ENI; } else if (nrx == 1) { cdata[ctrl].flags |= (1ul << 13); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | + CTRL_STO | CTRL_ACK; } } - *pdest++ = MCHP_I2C_DATA(ctrl); + *pdest++ = MCHP_I2C_DATA(raddr); nrx--; } cdata[ctrl].flags |= (1ul << 14); @@ -714,14 +789,14 @@ static int i2c_mrx_data(int ctrl) } /* - * Called from common/i2c_master + * Called from common I2C */ -int chip_i2c_xfer(int port, uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) +int chip_i2c_xfer(int port, uint16_t periph_addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size, int flags) { int ctrl; int ret_done; + uintptr_t raddr; if (out_size == 0 && in_size == 0) return EC_SUCCESS; @@ -730,6 +805,10 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, if (ctrl < 0) return EC_ERROR_INVAL; + raddr = chip_i2c_ctrl_base(ctrl); + if (raddr == 0) + return EC_ERROR_INVAL; + cdata[ctrl].flags = (1ul << 0); disable_controller_irq(ctrl); select_port(port, ctrl); @@ -741,7 +820,7 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, cdata[ctrl].hwsts3 = 0; cdata[ctrl].hwsts4 = 0; cdata[ctrl].port = port & 0xff; - cdata[ctrl].slv_addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; + cdata[ctrl].periph_addr_8bit = I2C_STRIP_FLAGS(periph_addr_flags) << 1; cdata[ctrl].out_size = out_size; cdata[ctrl].outp = out; cdata[ctrl].in_size = in_size; @@ -749,7 +828,7 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, cdata[ctrl].xflags = flags; if ((flags & I2C_XFER_START) && - cdata[ctrl].transaction_state == I2C_TRANSACTION_STOPPED) { + cdata[ctrl].transaction_state == I2C_TRANSACTION_STOPPED) { wait_idle(ctrl); ret_done = i2c_check_recover(port, ctrl); if (ret_done) @@ -780,7 +859,7 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, wait_idle(ctrl); /* Check for error conditions */ - if (MCHP_I2C_STATUS(ctrl) & (STS_LAB | STS_BER)) { + if (MCHP_I2C_STATUS(raddr) & (STS_LAB | STS_BER)) { cdata[ctrl].flags |= (1ul << 21); goto err_chip_i2c_xfer; } @@ -789,15 +868,14 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, err_chip_i2c_xfer: cdata[ctrl].flags |= (1ul << 22); - cdata[ctrl].hwsts2 = MCHP_I2C_STATUS(ctrl); /* record status */ + cdata[ctrl].hwsts2 = MCHP_I2C_STATUS(raddr); /* record status */ /* NOTE: writing I2C.Ctrl.PIN=1 will clear all bits * except NBB in I2C.Status */ - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_STO | CTRL_ACK; cdata[ctrl].transaction_state = I2C_TRANSACTION_STOPPED; /* record status after STOP */ - cdata[ctrl].hwsts4 = MCHP_I2C_STATUS(ctrl); + cdata[ctrl].hwsts4 = MCHP_I2C_STATUS(raddr); /* record line levels. * Note line levels may reflect STOP condition @@ -855,6 +933,17 @@ int i2c_get_line_levels(int port) return rv; } +/* + * this function returns the controller for I2C + * return mod of MCHP_I2C_CTRL_MAX + */ +__overridable int board_i2c_p2c(int port) +{ + if (port < 0 || port >= I2C_PORT_COUNT) + return -1; + return i2c_p2c[port]; +} + /* * I2C port must be a zero based number. * MCHP I2C can map any port to any of the 4 controllers. @@ -868,7 +957,7 @@ int i2c_port_to_controller(int port) void i2c_set_timeout(int port, uint32_t timeout) { - /* Param is port, but timeout is stored by-controller. */ + /* Parameter is port, but timeout is stored by-controller. */ cdata[i2c_port_to_controller(port)].timeout_us = timeout ? timeout : I2C_TIMEOUT_DEFAULT_US; } @@ -893,6 +982,9 @@ void i2c_init(void) memset(cdata, 0, sizeof(cdata)); for (i = 0; i < i2c_ports_used; ++i) { + /* Assign I2C controller to I2C port */ + i2c_p2c[i2c_ports[i].port] = i % MCHP_I2C_CTRL_MAX; + controller = i2c_port_to_controller(i2c_ports[i].port); kbps = i2c_ports[i].kbps; @@ -900,10 +992,9 @@ void i2c_init(void) i2c_ctrl_slp_en(controller, 0); if (controller_kbps[controller] && - (controller_kbps[controller] != kbps)) { + (controller_kbps[controller] != kbps)) { CPRINTF("I2C[%d] init speed conflict: %d != %d\n", - controller, kbps, - controller_kbps[controller]); + controller, kbps, controller_kbps[controller]); kbps = MIN(kbps, controller_kbps[controller]); } @@ -916,7 +1007,7 @@ void i2c_init(void) controller_kbps[controller] = pbc->freq_khz; configure_controller(controller, i2c_ports[i].port, - controller_kbps[controller]); + controller_kbps[controller]); cdata[controller].task_waiting = TASK_ID_INVALID; cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; /* Use default timeout. */ @@ -934,6 +1025,7 @@ static void handle_interrupt(int controller) { uint32_t r; int id = cdata[controller].task_waiting; + uintptr_t raddr = chip_i2c_ctrl_base(controller); /* * Write to control register interferes with I2C transaction. @@ -941,24 +1033,67 @@ static void handle_interrupt(int controller) * we want to wait for STS_PIN/STS_NBB. */ disable_controller_irq(controller); - cdata[controller].hwsts3 = MCHP_I2C_STATUS(controller); + cdata[controller].hwsts3 = MCHP_I2C_STATUS(raddr); /* Clear all interrupt status */ - r = MCHP_I2C_COMPLETE(controller); - MCHP_I2C_COMPLETE(controller) = r; + r = MCHP_I2C_COMPLETE(raddr); + MCHP_I2C_COMPLETE(raddr) = r; cdata[controller].i2c_complete = r; MCHP_INT_SOURCE(MCHP_I2C_GIRQ) = MCHP_I2C_GIRQ_BIT(controller); /* Wake up the task which was waiting on the I2C interrupt, if any. */ if (id != TASK_ID_INVALID) - task_set_event(id, TASK_EVENT_I2C_IDLE, 0); + task_set_event(id, TASK_EVENT_I2C_IDLE); } -void i2c0_interrupt(void) { handle_interrupt(0); } -void i2c1_interrupt(void) { handle_interrupt(1); } -void i2c2_interrupt(void) { handle_interrupt(2); } -void i2c3_interrupt(void) { handle_interrupt(3); } +static void i2c0_interrupt(void) +{ + handle_interrupt(0); +} +static void i2c1_interrupt(void) +{ + handle_interrupt(1); +} +static void i2c2_interrupt(void) +{ + handle_interrupt(2); +} +static void i2c3_interrupt(void) +{ + handle_interrupt(3); +} +#if defined(CHIP_FAMILY_MEC172X) +static void i2c4_interrupt(void) +{ + handle_interrupt(4); +} +#elif defined(CHIP_FAMILY_MEC152X) +static void i2c4_interrupt(void) +{ + handle_interrupt(4); +} +static void i2c5_interrupt(void) +{ + handle_interrupt(5); +} +static void i2c6_interrupt(void) +{ + handle_interrupt(6); +} +static void i2c7_interrupt(void) +{ + handle_interrupt(7); +} +#endif DECLARE_IRQ(MCHP_IRQ_I2C_0, i2c0_interrupt, 2); DECLARE_IRQ(MCHP_IRQ_I2C_1, i2c1_interrupt, 2); DECLARE_IRQ(MCHP_IRQ_I2C_2, i2c2_interrupt, 2); DECLARE_IRQ(MCHP_IRQ_I2C_3, i2c3_interrupt, 2); +#if defined(CHIP_FAMILY_MEC172X) +DECLARE_IRQ(MCHP_IRQ_I2C_4, i2c4_interrupt, 2); +#elif defined(CHIP_FAMILY_MEC152X) +DECLARE_IRQ(MCHP_IRQ_I2C_4, i2c4_interrupt, 2); +DECLARE_IRQ(MCHP_IRQ_I2C_5, i2c5_interrupt, 2); +DECLARE_IRQ(MCHP_IRQ_I2C_6, i2c6_interrupt, 2); +DECLARE_IRQ(MCHP_IRQ_I2C_7, i2c7_interrupt, 2); +#endif diff --git a/chip/mchp/i2c_chip.h b/chip/mchp/i2c_chip.h new file mode 100644 index 0000000000..b7109c4c69 --- /dev/null +++ b/chip/mchp/i2c_chip.h @@ -0,0 +1,33 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* MCHP-specific I2C module for Chrome EC */ + +#ifndef _I2C_CHIP_H +#define _I2C_CHIP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Place any C interfaces here */ + +/* + * Function returns the controller for I2C. + * + * Default function assigns controller for I2C port with modulo operation. If + * the I2C ports used are greater than MCHP_I2C_CTRL_MAX, then I2C ports will + * share the controller. Typically Type-C chips need individual controller per + * port because of heavy I2C transactions. Hence, define a board specific + * controller assignment when the I2C ports used are greater than + * MCHP_I2C_CTRL_MAX. + */ +__override_proto int board_i2c_p2c(int port); + +#ifdef __cplusplus +} +#endif + +#endif /* _I2C_CHIP_H */ diff --git a/chip/mchp/keyboard_raw.c b/chip/mchp/keyboard_raw.c index 946ea1ca90..30181776fa 100644 --- a/chip/mchp/keyboard_raw.c +++ b/chip/mchp/keyboard_raw.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,8 +11,8 @@ #include "keyboard_scan.h" #include "registers.h" #include "task.h" -#include "util.h" #include "tfdp_chip.h" +#include "util.h" /* * Using direct mode interrupt, do not enable @@ -86,7 +86,7 @@ void keyboard_raw_enable_interrupt(int enable) } } -void keyboard_raw_interrupt(void) +static void keyboard_raw_interrupt(void) { /* Clear interrupt status bits */ MCHP_KS_KSI_STATUS = 0xff; diff --git a/chip/mchp/lfw/ec_lfw.c b/chip/mchp/lfw/ec_lfw.c index edd945037c..94b851cf1f 100644 --- a/chip/mchp/lfw/ec_lfw.c +++ b/chip/mchp/lfw/ec_lfw.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,23 +6,22 @@ * */ -#include - +#include "clock.h" #include "config.h" +#include "cpu.h" +#include "cros_version.h" +#include "dma.h" #include "gpio.h" +#include "hwtimer.h" +#include "registers.h" #include "spi.h" #include "spi_flash.h" -#include "util.h" -#include "timer.h" -#include "dma.h" -#include "registers.h" -#include "cpu.h" -#include "clock.h" #include "system.h" -#include "version.h" -#include "hwtimer.h" -#include "gpio_list.h" #include "tfdp_chip.h" +#include "timer.h" +#include "util.h" + +#include #ifdef CONFIG_MCHP_LFW_DEBUG #include "dma_chip.h" @@ -30,26 +29,30 @@ #include "ec_lfw.h" +/* Must come after other header files and interrupt handler declarations */ +#include "gpio_list.h" + /* * Check if LFW build is pulling in GPSPI which is not * used for EC firmware SPI flash access. */ #ifdef CONFIG_MCHP_GPSPI -#error "FORCED BUILD ERROR: CONFIG_MCHP_CMX_GPSPI is defined" +#error "FORCED BUILD ERROR: CONFIG_MCHP_GPSPI is defined" #endif #define LFW_SPI_BYTE_TRANSFER_TIMEOUT_US (1 * MSEC) #define LFW_SPI_BYTE_TRANSFER_POLL_INTERVAL_US 100 -__attribute__ ((section(".intvector"))) +__attribute__((section(".intvector"))) const struct int_vector_t hdr_int_vect = { /* init sp, unused. set by MEC ROM loader */ - (void *)lfw_stack_top, /* preserve ROM log. was (void *)0x11FA00, */ - &lfw_main, /* was &lfw_main, */ /* reset vector */ - &fault_handler, /* NMI handler */ - &fault_handler, /* HardFault handler */ - &fault_handler, /* MPU fault handler */ - &fault_handler /* Bus fault handler */ + (void *)lfw_stack_top, /* preserve ROM log. was (void *)0x11FA00, */ + &lfw_main, + /* was &lfw_main, */ /* reset vector */ + &fault_handler, /* NMI handler */ + &fault_handler, /* HardFault handler */ + &fault_handler, /* MPU fault handler */ + &fault_handler /* Bus fault handler */ }; /* SPI devices - from board.c */ @@ -62,7 +65,7 @@ const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); * At POR or EC reset MCHP Boot-ROM should only load LFW and jumps * into LFW entry point located at offset 0x04 of LFW. * Entry point is programmed into SPI Header by Python SPI image - * builder at chip/mec1701/util/pack_ec.py + * builder in chip/mchp/util. * * EC_RO/RW calling LFW should enter through this routine if you * want the vector table updated. The stack should be set to @@ -107,7 +110,7 @@ void timer_init(void) val = MCHP_TMR32_CTL(0); - /* Pre-scale = 48 -> 1MHz -> Period = 1us */ + /* Prescale = 48 -> 1MHz -> Period = 1 us */ val = (val & 0xffff) | (47 << 16); MCHP_TMR32_CTL(0) = val; @@ -123,7 +126,6 @@ void timer_init(void) /* Start counting in timer 0 */ MCHP_TMR32_CTL(0) |= BIT(5); - } /* @@ -132,16 +134,13 @@ void timer_init(void) * before starting SPI read to minimize probability of * timer wrap. */ -static int spi_flash_readloc(uint8_t *buf_usr, - unsigned int offset, - unsigned int bytes) +static int spi_flash_readloc(uint8_t *buf_usr, unsigned int offset, + unsigned int bytes) { - uint8_t cmd[4] = {SPI_FLASH_READ, - (offset >> 16) & 0xFF, - (offset >> 8) & 0xFF, - offset & 0xFF}; + uint8_t cmd[4] = { SPI_FLASH_READ, (offset >> 16) & 0xFF, + (offset >> 8) & 0xFF, offset & 0xFF }; - if (offset + bytes > CONFIG_FLASH_SIZE) + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; __hw_clock_source_set(0); /* restart free run timer */ @@ -156,8 +155,8 @@ static int spi_flash_readloc(uint8_t *buf_usr, */ int spi_image_load(uint32_t offset) { - uint8_t *buf = (uint8_t *) (CONFIG_RW_MEM_OFF + - CONFIG_PROGRAM_MEMORY_BASE); + uint8_t *buf = + (uint8_t *)(CONFIG_RW_MEM_OFF + CONFIG_PROGRAM_MEMORY_BASE); uint32_t i; #ifdef CONFIG_MCHP_LFW_DEBUG uint32_t crc_calc, crc_exp; @@ -172,13 +171,11 @@ int spi_image_load(uint32_t offset) for (i = 0; i < CONFIG_RO_SIZE; i += SPI_CHUNK_SIZE) #ifdef CONFIG_MCHP_LFW_DEBUG rc = spi_flash_readloc(&buf[i], offset + i, SPI_CHUNK_SIZE); - if (rc != EC_SUCCESS) { - trace2(0, LFW, 0, - "spi_flash_readloc block %d ret = %d", - i, rc); - while (MCHP_PCR_PROC_CLK_CTL) - MCHP_PCR_CHIP_OSC_ID &= 0x1FE; - } + if (rc != EC_SUCCESS) { + trace2(0, LFW, 0, "spi_flash_readloc block %d ret = %d", i, rc); + while (MCHP_PCR_PROC_CLK_CTL) + MCHP_PCR_CHIP_OSC_ID &= 0x1FE; + } #else spi_flash_readloc(&buf[i], offset + i, SPI_CHUNK_SIZE); #endif @@ -234,11 +231,15 @@ timestamp_t get_time(void) { timestamp_t ts; - ts.le.hi = 0; /* clksrc_high; */ + ts.le.hi = 0; /* clksrc_high; */ ts.le.lo = __hw_clock_source_read(); return ts; } +#ifdef CONFIG_UART_CONSOLE + +BUILD_ASSERT(CONFIG_UART_CONSOLE < MCHP_UART_INSTANCES); + void uart_write_c(char c) { /* Put in carriage return prior to newline to mimic uart_vprintf() */ @@ -246,9 +247,9 @@ void uart_write_c(char c) uart_write_c('\r'); /* Wait for space in transmit FIFO. */ - while (!(MCHP_UART_LSR(0) & BIT(5))) + while (!(MCHP_UART_LSR(CONFIG_UART_CONSOLE) & BIT(5))) ; - MCHP_UART_TB(0) = c; + MCHP_UART_TB(CONFIG_UART_CONSOLE) = c; } void uart_puts(const char *str) @@ -261,55 +262,72 @@ void uart_puts(const char *str) } while (*str); } -void fault_handler(void) -{ - uart_puts("EXCEPTION!\nTriggering watchdog reset\n"); - /* trigger reset in 1 ms */ - usleep(1000); - MCHP_PCR_SYS_RST = MCHP_PCR_SYS_SOFT_RESET; - while (1) - ; - -} - -void jump_to_image(uintptr_t init_addr) -{ - void (*resetvec)(void) = (void(*)(void))init_addr; - - resetvec(); -} - void uart_init(void) { - /* Set UART to reset on VCC1_RESET instaed of nSIO_RESET */ - MCHP_UART_CFG(0) &= ~BIT(1); + /* Set UART to reset on VCC1_RESET instead of nSIO_RESET */ + MCHP_UART_CFG(CONFIG_UART_CONSOLE) &= ~BIT(1); /* Baud rate = 115200. 1.8432MHz clock. Divisor = 1 */ /* Set CLK_SRC = 0 */ - MCHP_UART_CFG(0) &= ~BIT(0); + MCHP_UART_CFG(CONFIG_UART_CONSOLE) &= ~BIT(0); /* Set DLAB = 1 */ - MCHP_UART_LCR(0) |= BIT(7); + MCHP_UART_LCR(CONFIG_UART_CONSOLE) |= BIT(7); /* PBRG0/PBRG1 */ - MCHP_UART_PBRG0(0) = 1; - MCHP_UART_PBRG1(0) = 0; + MCHP_UART_PBRG0(CONFIG_UART_CONSOLE) = 1; + MCHP_UART_PBRG1(CONFIG_UART_CONSOLE) = 0; /* Set DLAB = 0 */ - MCHP_UART_LCR(0) &= ~BIT(7); + MCHP_UART_LCR(CONFIG_UART_CONSOLE) &= ~BIT(7); /* Set word length to 8-bit */ - MCHP_UART_LCR(0) |= BIT(0) | BIT(1); + MCHP_UART_LCR(CONFIG_UART_CONSOLE) |= BIT(0) | BIT(1); /* Enable FIFO */ - MCHP_UART_FCR(0) = BIT(0); + MCHP_UART_FCR(CONFIG_UART_CONSOLE) = BIT(0); /* Activate UART */ - MCHP_UART_ACT(0) |= BIT(0); + MCHP_UART_ACT(CONFIG_UART_CONSOLE) |= BIT(0); gpio_config_module(MODULE_UART, 1); } +#else +void uart_write_c(char c __attribute__((unused))) +{ +} + +void uart_puts(const char *str __attribute__((unused))) +{ +} + +void uart_init(void) +{ +} +#endif /* #ifdef CONFIG_UART_CONSOLE */ + +noreturn void watchdog_reset(void) +{ + uart_puts("EXCEPTION!\nTriggering watchdog reset\n"); + /* trigger reset in 1 ms */ + usleep(1000); + MCHP_PCR_SYS_RST = MCHP_PCR_SYS_SOFT_RESET; + while (1) + ; +} + +void fault_handler(void) +{ + asm("b watchdog_reset"); +} + +void jump_to_image(uintptr_t init_addr) +{ + void (*resetvec)(void) = (void (*)(void))init_addr; + + resetvec(); +} /* * If any of VTR POR, VBAT POR, chip resets, or WDT reset are active @@ -318,16 +336,13 @@ void uart_init(void) void system_init(void) { uint32_t wdt_sts = MCHP_VBAT_STS & MCHP_VBAT_STS_ANY_RST; - uint32_t rst_sts = MCHP_PCR_PWR_RST_STS & - MCHP_PWR_RST_STS_VTR; + uint32_t rst_sts = MCHP_PCR_PWR_RST_STS & MCHP_PWR_RST_STS_SYS; - trace12(0, LFW, 0, - "VBAT_STS = 0x%08x PCR_PWR_RST_STS = 0x%08x", + trace12(0, LFW, 0, "VBAT_STS = 0x%08x PCR_PWR_RST_STS = 0x%08x", wdt_sts, rst_sts); if (rst_sts || wdt_sts) - MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX) - = EC_IMAGE_UNKNOWN; + MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX) = EC_IMAGE_UNKNOWN; } enum ec_image system_get_image_copy(void) @@ -335,7 +350,6 @@ enum ec_image system_get_image_copy(void) return MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX); } - /* * lfw_main is entered by MEC BootROM or EC_RO/RW calling it directly. * NOTE: Based on LFW from MEC1322 @@ -349,11 +363,10 @@ enum ec_image system_get_image_copy(void) */ void lfw_main(void) { - uintptr_t init_addr; /* install vector table */ - *((uintptr_t *) 0xe000ed08) = (uintptr_t) &hdr_int_vect; + *((uintptr_t *)0xe000ed08) = (uintptr_t)&hdr_int_vect; /* Use 48 MHz processor clock to power through boot */ MCHP_PCR_PROC_CLK_CTL = 1; @@ -381,7 +394,7 @@ void lfw_main(void) uart_init(); system_init(); - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(SPI_FLASH_DEVICE, 1); uart_puts("littlefw "); uart_puts(current_image_data.version); diff --git a/chip/mchp/lfw/ec_lfw.h b/chip/mchp/lfw/ec_lfw.h index c989a3bc1b..0c677e5d0b 100644 --- a/chip/mchp/lfw/ec_lfw.h +++ b/chip/mchp/lfw/ec_lfw.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -7,6 +7,7 @@ */ #include + #include /* Why naked? This is dangerous except for @@ -30,12 +31,12 @@ void fault_handler(void) __attribute__((naked)); extern uint32_t lfw_stack_top[]; struct int_vector_t { - void *stack_ptr; - void *reset_vector; - void *nmi; - void *hard_fault; - void *bus_fault; - void *usage_fault; + void *stack_ptr; + void *reset_vector; + void *nmi; + void *hard_fault; + void *bus_fault; + void *usage_fault; }; -#define SPI_CHUNK_SIZE 1024 +#define SPI_CHUNK_SIZE 1024 diff --git a/chip/mchp/lfw/ec_lfw.ld b/chip/mchp/lfw/ec_lfw.ld index 8e8601a5ee..d178a42280 100644 --- a/chip/mchp/lfw/ec_lfw.ld +++ b/chip/mchp/lfw/ec_lfw.ld @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -79,7 +79,15 @@ SECTIONS FILL(0xFF); . = ORIGIN(SRAM) + LENGTH(SRAM) - 1; BYTE(0xFF); /* emit at least a byte to make linker happy */ - } + } >SRAM __image_size = LOADADDR(.text) + SIZEOF(.text) - ORIGIN(VECTOR); + + /* + * Discard C++ exception index table and exception table. These are + * described in more detail in "Exception Handling ABI for ARM + * Architecture": + * https://github.com/ARM-software/abi-aa/blob/60a8eb8c55e999d74dac5e368fc9d7e36e38dda4/ehabi32/ehabi32.rst#54the-object-producer-interface + */ + /DISCARD/ : { *(.ARM.*) } } diff --git a/chip/mchp/lfw/ec_lfw_416kb.ld b/chip/mchp/lfw/ec_lfw_416kb.ld new file mode 100644 index 0000000000..c7dfacada3 --- /dev/null +++ b/chip/mchp/lfw/ec_lfw_416kb.ld @@ -0,0 +1,97 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * MCHP MEC parts with 416KB SRAM SoC little FW + * + */ + +/* + * Memory Spaces Definitions + * LFW occupies first 4KB of CODE SRAM. + * First 24 bytes contain a minimal Cortex-M4 + * vector table. + */ +MEMORY +{ + VECTOR(r ) : ORIGIN = 0x0C0000, LENGTH = 0x18 + SRAM (xrw) : ORIGIN = 0x0C0018, LENGTH = 0xFE8 +} + +/* + * ld does not allow mathematical expressions in ORIGIN/LENGTH, so check the + * values here. + */ +ASSERT(ORIGIN(VECTOR) + LENGTH(VECTOR) == ORIGIN(SRAM), "Invalid SRAM origin.") +ASSERT(LENGTH(VECTOR) + LENGTH(SRAM) == 0x1000, "Invalid VECTOR+SRAM length.") + +/* + * The entry point is informative, for debuggers and simulators, + * since the Cortex-M vector points to it anyway. + */ +ENTRY(lfw_main) + +/* + * MEC172xN has 416KB total SRAM: 352KB CODE 64KB DATA + * CODE: 0x0C0000 - 0x117FFF + * DATA: 0x118000 - 0x127FFF + * Boot-ROM log is 0x11FF00 - 0x11FFFF + * MEC172x Top 1KB is not cleared if OTP customer flag enabled. + * !!! TODO !!! Does presence of PUF feature move customer area? + * Boot-ROM spec states 3.5KB from top is lost. + * 0x12_7800 - 0x12_7fff 2KB used by PUF option + * 0x12_7400 - 0x12_77ff 1KB Customer use. Not cleared by Boot-ROM + * 0x12_7200 - 0x12_73ff 512 byte Boot-ROM log + * CrOS EC puts panic data at Top of RAM. + * We must set Top of RAM to be customer region far enough to + * hold panic data. + * Set Top of SRAM to 0x12_7800. + * This requires size of SRAM = 0x127800 - 0x118000 = 0xF800 (62 KB) + */ +PROVIDE( lfw_stack_top = 0x127800 ); + +/* Sections Definitions */ + +SECTIONS +{ + + /* + * The vector table goes first + */ + .intvector : + { + . = ALIGN(4); + KEEP(*(.intvector)) + } > VECTOR + + /* + * The program code is stored in the .text section, + * which goes to FLASH. + */ + + .text : + { + *(.text .text.*) /* all remaining code */ + *(.rodata .rodata.*) /* read-only data (constants) */ + } >SRAM + + . = ALIGN(4); + + /* Padding */ + + .fill : { + FILL(0xFF); + . = ORIGIN(SRAM) + LENGTH(SRAM) - 1; + BYTE(0xFF); /* emit at least a byte to make linker happy */ + } >SRAM + + __image_size = LOADADDR(.text) + SIZEOF(.text) - ORIGIN(VECTOR); + + /* + * Discard C++ exception index table and exception table. These are + * described in more detail in "Exception Handling ABI for ARM + * Architecture": + * https://github.com/ARM-software/abi-aa/blob/60a8eb8c55e999d74dac5e368fc9d7e36e38dda4/ehabi32/ehabi32.rst#54the-object-producer-interface + */ + /DISCARD/ : { *(.ARM.*) } +} diff --git a/chip/mchp/lfw/gpio.inc b/chip/mchp/lfw/gpio.inc new file mode 100644 index 0000000000..76de618bf3 --- /dev/null +++ b/chip/mchp/lfw/gpio.inc @@ -0,0 +1,107 @@ +/* -*- mode:c -*- + * + * Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Common GPIOs needed for LFW loader and main process FW + */ + +/* SPI + * External SPI chip select must be open drain and driven high or + * internal SPI chip select must be push-pull and driven high before + * SPI controller configuration. + * QMSPI external Shared CS0# is GPIO_0055 + * QMSPI internal CS0# is GPIO_0116 + */ +#if defined(CHIP_VARIANT_MEC1727SZ) +GPIO(QMSPI_CS0, PIN(0116), GPIO_PULL_UP | GPIO_HIGH) +#else +GPIO(QMSPI_CS0, PIN(055), GPIO_ODR_HIGH) +#endif + +/* Boot-ROM loads from external or internal SPI flash. + * There are two external ports: shared(default) and private. + * NOTE: QMSPI Shared SPI Port pins are on VTR2 + * SHD_CS0# = GPIO 0055 Func 2 bank 1 b[13] + * SHD_CLK = GPIO 0056 Func 2 bank 1 b[14] + * SHD_IO0 = GPIO 0223 Func 1 bank 4 b[19] + * SHD_IO1 = GPIO 0224 Func 2 bank 4 b[20] + * Not using IO2 and IO2 as data + * SHD_IO2 = GPIO 0227 Func 1 bank 4 b[23] + * SHD_IO3 = GPIO 0016 Func 2 bank 0 b[14] + * MEC1727 variants load from internal 512KB SPI flash(internal only pins) + * INT_CS# = GPIO 0116 Func 1 bank 2 14 + * INT_SCK = GPIO 0117 Func 1 bank 2 15 + * INT_IO0 = GPIO 0074 Func 1 bank 1 28 + * INT_IO1 = GPIO 0075 Func 1 bank 1 29 + * INT_WP# = GPIO 0076 Func 0 for WP# control + * Internal flash HOLD# connected to VTR1 rail. + */ +#if defined(CHIP_VARIANT_MEC1727SZ) +/* MEC1727 variants have internal SPI flash on internal only pins */ +ALTERNATE(PIN_MASK(2, 0x4000), 1, MODULE_SPI_FLASH, GPIO_PULL_UP) +ALTERNATE(PIN_MASK(2, 0x8000), 1, MODULE_SPI_FLASH, 0) +ALTERNATE(PIN_MASK(1, 0x30000000), 1, MODULE_SPI_FLASH, 0) +#else +/* external SPI flash on QMSPI SHD_xx pins */ +ALTERNATE(PIN_MASK(1, 0x2000), 2, MODULE_SPI_FLASH, GPIO_ODR_HIGH) +ALTERNATE(PIN_MASK(1, 0x4000), 2, MODULE_SPI_FLASH, 0) +ALTERNATE(PIN_MASK(4, 0x080000), 1, MODULE_SPI_FLASH, 0) +ALTERNATE(PIN_MASK(4, 0x100000), 2, MODULE_SPI_FLASH, 0) +#endif + +/* UART + * Per CONFIG_UART_CONSOLE and chip to configure UART pins + */ +#if CONFIG_UART_CONSOLE == 0 +/* select UART0 */ +/* MEC170X, MEC152X and MEC172X support same UART0 pins and ALT function */ +/* + * UART0 + * GPIO_0105 Func 1 = UART_RX + * GPIO_0104 Func 1 = UART_TX + * Bank 2 bits[5:4] + */ +ALTERNATE(PIN_MASK(2, 0x30), 1, MODULE_UART, 0) + +#elif CONFIG_UART_CONSOLE == 1 +/* select UART1 */ +/* MEC170X, MEC152X and MEC172X support same UART1 pins + * but ALT function 2 on MEC170X, function 1 on others + */ +#if defined(CHIP_FAMILY_MEC170X) +/* + * UART1 + * GPIO_0171 Func 2 = UART_RX + * GPIO_0170 Func 2 = UART_TX + * Bank 3 bits[25:24] + */ +ALTERNATE(PIN_MASK(3, 0x03000000), 2, MODULE_UART, 0) + +#else +/* + * UART1 + * GPIO_0171 Func 1 = UART_RX + * GPIO_0170 Func 1 = UART_TX + * Bank 3 bits[25:24] + */ +ALTERNATE(PIN_MASK(3, 0x03000000), 1, MODULE_UART, 0) + +#endif /* defined(CHIP_FAMILY_MEC170X) */ + +#else +/* select UART2 */ +/* only MEC152X supports UART2 pins */ +#if defined(CHIP_FAMILY_MEC152X) +/* + * UART2 + * GPIO_0145 Func 2 = UART_RX + * GPIO_0146 Func 2 = UART_TX + * Bank 3 bits[6:5] + */ +ALTERNATE(PIN_MASK(3, 0x60), 2, MODULE_UART, 0) + +#endif /* defined(CHIP_FAMILY_MEC152X) */ + +#endif /* CONFIG_UART_CONSOLE == 0 */ diff --git a/chip/mchp/lpc.c b/chip/mchp/lpc.c index 91adb7f17c..e41e4b0c78 100644 --- a/chip/mchp/lpc.c +++ b/chip/mchp/lpc.c @@ -1,49 +1,48 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* LPC module for MCHP MEC family */ -#include "common.h" #include "acpi.h" +#include "chipset.h" +#include "common.h" #include "console.h" +#include "espi.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "keyboard_protocol.h" #include "lpc.h" #include "lpc_chip.h" -#include "espi.h" #include "port80.h" #include "registers.h" #include "system.h" #include "task.h" +#include "tfdp_chip.h" #include "timer.h" #include "util.h" -#include "chipset.h" -#include "tfdp_chip.h" /* Console output macros */ #ifdef CONFIG_MCHP_DEBUG_LPC #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) #else #define CPUTS(...) #define CPRINTS(...) #endif -static uint8_t -mem_mapped[0x200] __attribute__((section(".bss.big_align"))); +static uint8_t mem_mapped[0x200] __attribute__((section(".bss.big_align"))); static struct host_packet lpc_packet; static struct host_cmd_handler_args host_cmd_args; -static uint8_t host_cmd_flags; /* Flags from host command */ +static uint8_t host_cmd_flags; /* Flags from host command */ static uint8_t params_copy[EC_LPC_HOST_PACKET_SIZE] __aligned(4); static int init_done; -static struct ec_lpc_host_args * const lpc_host_args = +static struct ec_lpc_host_args *const lpc_host_args = (struct ec_lpc_host_args *)mem_mapped; #ifdef CONFIG_BOARD_ID_CMD_ACPI_EC1 @@ -52,13 +51,12 @@ static uint8_t custom_acpi_ec2os_cnt; static uint8_t custom_apci_ec2os[4]; #endif - static void keyboard_irq_assert(void) { #ifdef CONFIG_KEYBOARD_IRQ_GPIO /* * Enforce signal-high for long enough for the signal to be - * pulled high by the external pullup resistor. This ensures the + * pulled high by the external pull up resistor. This ensures the * host will see the following falling edge, regardless of the * line state before this function call. */ @@ -81,14 +79,14 @@ static void keyboard_irq_assert(void) * Generate SMI pulse to the host chipset via GPIO. * * If the x86 is in S0, SMI# is sampled at 33MHz, so minimum pulse length - * is 60ns. If the x86 is in S3, SMI# is sampled at 32.768KHz, so we need + * is 60 ns. If the x86 is in S3, SMI# is sampled at 32.768KHz, so we need * pulse length >61us. Both are short enough and events are infrequent, - * so just delay for 65us. + * so just delay for 65 us. */ static void lpc_generate_smi(void) { CPUTS("LPC Pulse SMI"); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI /* eSPI: pulse SMI# Virtual Wire low */ espi_vw_pulse_wire(VW_SMI_L, 0); #else @@ -106,11 +104,11 @@ static void lpc_generate_sci(void) udelay(65); gpio_set_level(CONFIG_SCI_GPIO, 1); #else -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI espi_vw_pulse_wire(VW_SCI_L, 0); #else MCHP_ACPI_PM_STS |= 1; - udelay(65); + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); MCHP_ACPI_PM_STS &= ~1; #endif #endif @@ -129,7 +127,7 @@ static void lpc_update_wake(host_event_t wake_events) */ wake_events &= ~EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI espi_vw_set_wire(VW_WAKE_L, !wake_events); #else /* Signal is asserted low when wake events is non-zero */ @@ -142,7 +140,6 @@ static uint8_t *lpc_get_hostcmd_data_range(void) return mem_mapped; } - /** * Update the host event status. * @@ -182,7 +179,7 @@ void lpc_update_host_event_status(void) /* Copy host events to mapped memory */ *(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = - lpc_get_host_events(); + lpc_get_host_events(); task_enable_irq(MCHP_IRQ_ACPIEC0_IBF); @@ -216,22 +213,20 @@ static void lpc_send_response(struct host_cmd_handler_args *args) } /* New-style response */ - lpc_host_args->flags = - (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) | - EC_HOST_ARGS_FLAG_TO_HOST; + lpc_host_args->flags = (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) | + EC_HOST_ARGS_FLAG_TO_HOST; lpc_host_args->data_size = size; csum = args->command + lpc_host_args->flags + - lpc_host_args->command_version + - lpc_host_args->data_size; + lpc_host_args->command_version + lpc_host_args->data_size; for (i = 0, out = (uint8_t *)args->response; i < size; i++, out++) csum += *out; lpc_host_args->checksum = (uint8_t)csum; - /* Fail if response doesn't fit in the param buffer */ + /* Fail if response doesn't fit in the parameter buffer */ if (size > EC_PROTO2_MAX_PARAM_SIZE) args->result = EC_RES_INVALID_RESPONSE; @@ -240,12 +235,10 @@ static void lpc_send_response(struct host_cmd_handler_args *args) /* * Clear processing flag in hardware and - * sticky status in interrupt aggregator. + * sticky status in interrupt aggregator. */ MCHP_ACPI_EC_STATUS(1) &= ~EC_LPC_STATUS_PROCESSING; - MCHP_INT_SOURCE(MCHP_ACPI_EC_GIRQ) = - MCHP_ACPI_EC_IBF_GIRQ_BIT(1); - + MCHP_INT_SOURCE(MCHP_ACPI_EC_GIRQ) = MCHP_ACPI_EC_IBF_GIRQ_BIT(1); } static void lpc_send_response_packet(struct host_packet *pkt) @@ -265,8 +258,7 @@ static void lpc_send_response_packet(struct host_packet *pkt) /* Clear the busy bit, so the host knows the EC is done. */ MCHP_ACPI_EC_STATUS(1) &= ~EC_LPC_STATUS_PROCESSING; - MCHP_INT_SOURCE(MCHP_ACPI_EC_GIRQ) = - MCHP_ACPI_EC_IBF_GIRQ_BIT(1); + MCHP_INT_SOURCE(MCHP_ACPI_EC_GIRQ) = MCHP_ACPI_EC_IBF_GIRQ_BIT(1); } uint8_t *lpc_get_memmap_range(void) @@ -276,57 +268,60 @@ uint8_t *lpc_get_memmap_range(void) void lpc_mem_mapped_init(void) { - /* We support LPC args and version 3 protocol */ + /* We support LPC arguments and version 3 protocol */ *(lpc_get_memmap_range() + EC_MEMMAP_HOST_CMD_FLAGS) = EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED | EC_HOST_CMD_FLAG_VERSION_3; } -const int acpi_ec_pcr_slp[MCHP_ACPI_EC_MAX] = { - MCHP_PCR_ACPI_EC0, - MCHP_PCR_ACPI_EC1, - MCHP_PCR_ACPI_EC2, - MCHP_PCR_ACPI_EC3, +const int acpi_ec_pcr_slp[] = { + MCHP_PCR_ACPI_EC0, MCHP_PCR_ACPI_EC1, + MCHP_PCR_ACPI_EC2, MCHP_PCR_ACPI_EC3, +#ifndef CHIP_FAMILY_MEC152X MCHP_PCR_ACPI_EC4, +#endif }; +BUILD_ASSERT(ARRAY_SIZE(acpi_ec_pcr_slp) == MCHP_ACPI_EC_INSTANCES); -const int acpi_ec_nvic_ibf[MCHP_ACPI_EC_MAX] = { - MCHP_IRQ_ACPIEC0_IBF, - MCHP_IRQ_ACPIEC1_IBF, - MCHP_IRQ_ACPIEC2_IBF, - MCHP_IRQ_ACPIEC3_IBF, +const int acpi_ec_nvic_ibf[] = { + MCHP_IRQ_ACPIEC0_IBF, MCHP_IRQ_ACPIEC1_IBF, + MCHP_IRQ_ACPIEC2_IBF, MCHP_IRQ_ACPIEC3_IBF, +#ifndef CHIP_FAMILY_MEC152X MCHP_IRQ_ACPIEC4_IBF, +#endif }; +BUILD_ASSERT(ARRAY_SIZE(acpi_ec_nvic_ibf) == MCHP_ACPI_EC_INSTANCES); -#ifdef CONFIG_HOSTCMD_ESPI -const int acpi_ec_espi_bar_id[MCHP_ACPI_EC_MAX] = { - MCHP_ESPI_IO_BAR_ID_ACPI_EC0, - MCHP_ESPI_IO_BAR_ID_ACPI_EC1, - MCHP_ESPI_IO_BAR_ID_ACPI_EC2, - MCHP_ESPI_IO_BAR_ID_ACPI_EC3, +#ifdef CONFIG_HOST_INTERFACE_ESPI +const int acpi_ec_espi_bar_id[] = { + MCHP_ESPI_IO_BAR_ID_ACPI_EC0, MCHP_ESPI_IO_BAR_ID_ACPI_EC1, + MCHP_ESPI_IO_BAR_ID_ACPI_EC2, MCHP_ESPI_IO_BAR_ID_ACPI_EC3, +#ifndef CHIP_FAMILY_MEC152X MCHP_ESPI_IO_BAR_ID_ACPI_EC4, +#endif }; +BUILD_ASSERT(ARRAY_SIZE(acpi_ec_espi_bar_id) == MCHP_ACPI_EC_INSTANCES); #endif void chip_acpi_ec_config(int instance, uint32_t io_base, uint8_t mask) { - if (instance >= MCHP_ACPI_EC_MAX) + if (instance >= MCHP_ACPI_EC_INSTANCES) { CPUTS("ACPI EC CFG invalid"); + return; + } MCHP_PCR_SLP_DIS_DEV(acpi_ec_pcr_slp[instance]); -#ifdef CONFIG_HOSTCMD_ESPI - MCHP_ESPI_IO_BAR_CTL_MASK(acpi_ec_espi_bar_id[instance]) = - mask; +#ifdef CONFIG_HOST_INTERFACE_ESPI + MCHP_ESPI_IO_BAR_CTL_MASK(acpi_ec_espi_bar_id[instance]) = mask; MCHP_ESPI_IO_BAR(acpi_ec_espi_bar_id[instance]) = - (io_base << 16) + 0x01ul; + (io_base << 16) + 0x01ul; #else - MCHP_LPC_ACPI_EC_BAR(instance) = (io_base << 16) + - (1ul << 15) + mask; + MCHP_LPC_ACPI_EC_BAR(instance) = (io_base << 16) + (1ul << 15) + mask; #endif MCHP_ACPI_EC_STATUS(instance) &= ~EC_LPC_STATUS_PROCESSING; MCHP_INT_ENABLE(MCHP_ACPI_EC_GIRQ) = - MCHP_ACPI_EC_IBF_GIRQ_BIT(instance); + MCHP_ACPI_EC_IBF_GIRQ_BIT(instance); task_enable_irq(acpi_ec_nvic_ibf[instance]); } @@ -339,21 +334,20 @@ void chip_8042_config(uint32_t io_base) { MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_8042); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_ID_8042) = 0x04; - MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_8042) = - (io_base << 16) + 0x01ul; + MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_8042) = (io_base << 16) + 0x01ul; #else /* Set up 8042 interface at 0x60/0x64 */ MCHP_LPC_8042_BAR = (io_base << 16) + (1ul << 15); #endif - /* Set up indication of Auxiliary sts */ + /* Set up indication of Auxiliary status */ MCHP_8042_KB_CTRL |= BIT(7); MCHP_8042_ACT |= 1; - MCHP_INT_ENABLE(MCHP_8042_GIRQ) = MCHP_8042_OBE_GIRQ_BIT + - MCHP_8042_IBF_GIRQ_BIT; + MCHP_INT_ENABLE(MCHP_8042_GIRQ) = + MCHP_8042_OBE_GIRQ_BIT + MCHP_8042_IBF_GIRQ_BIT; task_enable_irq(MCHP_IRQ_8042EM_IBF); task_enable_irq(MCHP_IRQ_8042EM_OBE); @@ -361,8 +355,13 @@ void chip_8042_config(uint32_t io_base) #ifndef CONFIG_KEYBOARD_IRQ_GPIO /* Set up SERIRQ for keyboard */ MCHP_8042_KB_CTRL |= BIT(5); +#ifdef CONFIG_HOST_INTERFACE_ESPI + /* Delivery 8042 keyboard interrupt as IRQ1 using eSPI SERIRQ */ + MCHP_ESPI_IO_SERIRQ_REG(MCHP_ESPI_SIRQ_8042_KB) = 1; +#else MCHP_LPC_SIRQ(1) = 0x01; #endif +#endif } /* @@ -371,15 +370,14 @@ void chip_8042_config(uint32_t io_base) * in SRAM. EMI hardware adds 16-bit offset Host programs into * EC_Address_LSB/MSB registers. * Limit EMI read / write range. First 256 bytes are RW for host - * commands. Second 256 bytes are RO for mem-mapped data. + * commands. Second 256 bytes are RO for memory-mapped data. * Hardware decodes a fixed 16 byte IO range. */ void chip_emi0_config(uint32_t io_base) { -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_ID_EMI0) = 0x0F; - MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_EMI0) = - (io_base << 16) + 0x01ul; + MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_EMI0) = (io_base << 16) + 0x01ul; #else MCHP_LPC_EMI0_BAR = (io_base << 16) + (1ul << 15); #endif @@ -393,35 +391,53 @@ void chip_emi0_config(uint32_t io_base) task_enable_irq(MCHP_IRQ_EMI0); } -/* Setup Port80 Debug Hardware ports. +/* Setup Port 80 Debug Hardware ports. * First instance for I/O 80h only. - * Clear FIFO's and timestamp. + * Clear FIFO's and time stamp. * Set FIFO interrupt threshold to maximum of 14 bytes. */ +#if defined(CHIP_FAMILY_MEC172X) +void chip_port80_config(uint32_t io_base) +{ + MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_BDP0); + + /* reset, configure, and enable */ + MCHP_BDP0_CONFIG = MCHP_BDP_CFG_SRST; + MCHP_BDP0_CONFIG = MCHP_BDP_CFG_FIFO_THRH_28; + MCHP_BDP0_INTR_EN = MCHP_BDP_IEN_THRH; + MCHP_BDP0_ACTV = 1; + + MCHP_INT_SOURCE(15) = MCHP_INT15_BDP0; + MCHP_INT_ENABLE(15) = MCHP_INT15_BDP0; + task_enable_irq(MCHP_IRQ_BDP0); + + /* Last: Enable Host access via eSPI IO BAR */ + MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_BDP0) = 0x00; + MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_BDP0) = (io_base << 16) + 0x01ul; +} +#else void chip_port80_config(uint32_t io_base) { MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_P80CAP0); - MCHP_P80_CFG(0) = MCHP_P80_FLUSH_FIFO_WO + - MCHP_P80_RESET_TIMESTAMP_WO; + MCHP_P80_CFG(0) = MCHP_P80_FLUSH_FIFO_WO + MCHP_P80_RESET_TIMESTAMP_WO; -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_P80_0) = 0x00; - MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_P80_0) = - (io_base << 16) + 0x01ul; + MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_P80_0) = (io_base << 16) + 0x01ul; #else MCHP_LPC_P80DBG0_BAR = (io_base << 16) + (1ul << 15); #endif - MCHP_P80_CFG(0) = MCHP_P80_FIFO_THRHOLD_14 + - MCHP_P80_TIMEBASE_1500KHZ + - MCHP_P80_TIMER_ENABLE; + MCHP_P80_CFG(0) = MCHP_P80_FIFO_THRHOLD_14 + MCHP_P80_TIMEBASE_1500KHZ + + MCHP_P80_TIMER_ENABLE; MCHP_P80_ACTIVATE(0) = 1; - MCHP_INT_SOURCE(15) = MCHP_INT15_P80(0); - MCHP_INT_ENABLE(15) = MCHP_INT15_P80(0); + MCHP_INT_SOURCE(15) = MCHP_P80_GIRQ_BIT(0); + MCHP_INT_ENABLE(15) = MCHP_P80_GIRQ_BIT(0); task_enable_irq(MCHP_IRQ_PORT80DBG0); } +#endif #ifdef CONFIG_MCHP_DEBUG_LPC static void chip_lpc_iobar_debug(void) @@ -438,19 +454,17 @@ static void chip_lpc_iobar_debug(void) * Most registers in LPC module are reset when the host is off. * We need to set up LPC again when the host is starting up. * MCHP LRESET# can be one of two pins - * GPIO_0052 Func 2 - * GPIO_0064 Func 1 + * GPIO_0052 Function 2 + * GPIO_0064 Function 1 * Use GPIO interrupt to detect LRESET# changes. * Use GPIO_0064 for LRESET#. Must update board/board_name/gpio.inc * * For eSPI PLATFORM_RESET# virtual wire is used as LRESET# * */ -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI static void setup_lpc(void) { - TRACE0(55, LPC, 0, "setup_lpc"); - MCHP_LPC_CFG_BAR |= (1ul << 15); /* Set up ACPI0 for 0x62/0x66 */ @@ -501,18 +515,15 @@ static void lpc_init(void) /* * Clear PCR sleep enables for peripherals we are using for * both LPC and eSPI. - * Global Config, ACPI EC0/1, 8042 Keyboard controller, - * Port80 Capture0, and EMI. + * Global Configuration, ACPI EC0/1, 8042 Keyboard controller. * NOTE: EMI doesn't have a sleep enable. */ MCHP_PCR_SLP_DIS_DEV_MASK(2, MCHP_PCR_SLP_EN2_GCFG + - MCHP_PCR_SLP_EN2_ACPI_EC0 + - MCHP_PCR_SLP_EN2_ACPI_EC0 + - MCHP_PCR_SLP_EN2_MIF8042); - - MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_P80CAP0); + MCHP_PCR_SLP_EN2_ACPI_EC0 + + MCHP_PCR_SLP_EN2_ACPI_EC0 + + MCHP_PCR_SLP_EN2_MIF8042); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI espi_init(); @@ -541,8 +552,7 @@ static void lpc_init(void) * clock stop and there are no pending SERIRQ * or LPC DMA. */ - MCHP_LPC_EC_CLK_CTRL = - (MCHP_LPC_EC_CLK_CTRL & ~(0x03ul)) | 0x01ul; + MCHP_LPC_EC_CLK_CTRL = (MCHP_LPC_EC_CLK_CTRL & ~(0x03ul)) | 0x01ul; setup_lpc(); #endif @@ -588,8 +598,8 @@ void lpc_set_init_done(int val) */ void lpcrst_interrupt(enum gpio_signal signal) { -#ifndef CONFIG_HOSTCMD_ESPI - /* Initialize LPC module when LRESET# is deasserted */ +#ifndef CONFIG_HOST_INTERFACE_ESPI + /* Initialize LPC module when LRESET# is de-asserted */ if (!lpc_get_pltrst_asserted()) { setup_lpc(); } else { @@ -602,8 +612,7 @@ void lpcrst_interrupt(enum gpio_signal signal) #endif } #ifdef CONFIG_MCHP_DEBUG_LPC - CPRINTS("LPC RESET# %sasserted", - lpc_get_pltrst_asserted() ? "" : "de"); + CPRINTS("LPC RESET# %sasserted", lpc_get_pltrst_asserted() ? "" : "de"); #endif #endif } @@ -613,7 +622,7 @@ void lpcrst_interrupt(enum gpio_signal signal) * or logging of EMI host communication? We don't observe * this ISR so Host is not writing to MCHP_EMI_H2E_MBX(0). */ -void emi0_interrupt(void) +static void emi0_interrupt(void) { uint8_t h2e; @@ -627,14 +636,24 @@ DECLARE_IRQ(MCHP_IRQ_EMI0, emi0_interrupt, 1); * ISR empties BIOS Debug 0 FIFO and * writes data to circular buffer. How can we be * sure this routine can read the last Port 80h byte? + * MEC172x BDP capture data is different. It returns a + * 16-bit value where bits [7:0] are the data and bits [15:7] + * are flags indicating if the data is part of a multi-byte + * write sequence by the host and read-only FIFO status bits. + * The capture HW in previous chips included an optional time + * stamp in bits[31:8] of the data register. */ int port_80_read(void) { - int data; + int data = PORT_80_IGNORE; - data = PORT_80_IGNORE; +#if defined(CHIP_FAMILY_MEC172X) + if (MCHP_BDP0_STATUS & MCHP_BDP_STATUS_NOT_EMPTY) + data = MCHP_BDP0_DATTR & 0xFFU; +#else if (MCHP_P80_STS(0) & MCHP_P80_STS_NOT_EMPTY) data = MCHP_P80_CAP(0) & 0xFF; +#endif return data; } @@ -642,11 +661,10 @@ int port_80_read(void) #ifdef CONFIG_BOARD_ID_CMD_ACPI_EC1 /* * Handle custom ACPI EC0 commands. - * Some chipset's CoreBoot will send read board ID command expecting + * Some chipset CoreBoot will send read board ID command expecting * a two byte response. */ -static int acpi_ec0_custom(int is_cmd, uint8_t value, - uint8_t *resultptr) +static int acpi_ec0_custom(int is_cmd, uint8_t value, uint8_t *resultptr) { int rval; @@ -656,7 +674,7 @@ static int acpi_ec0_custom(int is_cmd, uint8_t value, if (is_cmd && (value == 0x0d)) { MCHP_INT_SOURCE(MCHP_ACPI_EC_GIRQ) = - MCHP_ACPI_EC_OBE_GIRQ_BIT(0); + MCHP_ACPI_EC_OBE_GIRQ_BIT(0); /* Write two bytes sequence 0xC2, 0x04 to Host */ if (MCHP_ACPI_EC_BYTE_CTL(0) & 0x01) { /* Host enabled 4-byte mode */ @@ -672,7 +690,7 @@ static int acpi_ec0_custom(int is_cmd, uint8_t value, custom_apci_ec2os[0] = 0x04; MCHP_ACPI_EC_EC2OS(0, 0) = 0x02; MCHP_INT_ENABLE(MCHP_ACPI_EC_GIRQ) = - MCHP_ACPI_EC_OBE_GIRQ_BIT(0); + MCHP_ACPI_EC_OBE_GIRQ_BIT(0); task_enable_irq(MCHP_IRQ_ACPIEC0_OBE); } custom_acpi_cmd = 0; @@ -683,7 +701,7 @@ static int acpi_ec0_custom(int is_cmd, uint8_t value, } #endif -void acpi_0_interrupt(void) +static void acpi_0_interrupt(void) { uint8_t value, result, is_cmd; @@ -711,8 +729,7 @@ void acpi_0_interrupt(void) MCHP_ACPI_EC_STATUS(0) &= ~EC_LPC_STATUS_PROCESSING; /* Clear R/W1C status bit in Aggregator */ - MCHP_INT_SOURCE(MCHP_ACPI_EC_GIRQ) = - MCHP_ACPI_EC_IBF_GIRQ_BIT(0); + MCHP_INT_SOURCE(MCHP_ACPI_EC_GIRQ) = MCHP_ACPI_EC_IBF_GIRQ_BIT(0); /* * ACPI 5.0-12.6.1: Generate SCI for Input Buffer Empty / @@ -728,12 +745,11 @@ DECLARE_IRQ(MCHP_IRQ_ACPIEC0_IBF, acpi_0_interrupt, 1); * Used to handle custom ACPI EC0 command requiring * two byte response. */ -void acpi_0_obe_isr(void) +static void acpi_0_obe_isr(void) { uint8_t sts, data; - MCHP_INT_SOURCE(MCHP_ACPI_EC_GIRQ) = - MCHP_ACPI_EC_OBE_GIRQ_BIT(0); + MCHP_INT_SOURCE(MCHP_ACPI_EC_GIRQ) = MCHP_ACPI_EC_OBE_GIRQ_BIT(0); sts = MCHP_ACPI_EC_STATUS(0); data = MCHP_ACPI_EC_BYTE_CTL(0); @@ -745,7 +761,7 @@ void acpi_0_obe_isr(void) if (custom_acpi_ec2os_cnt == 0) { /* was last byte? */ MCHP_INT_DISABLE(MCHP_ACPI_EC_GIRQ) = - MCHP_ACPI_EC_OBE_GIRQ_BIT(0); + MCHP_ACPI_EC_OBE_GIRQ_BIT(0); } lpc_generate_sci(); @@ -753,12 +769,11 @@ void acpi_0_obe_isr(void) DECLARE_IRQ(MCHP_IRQ_ACPIEC0_OBE, acpi_0_obe_isr, 1); #endif -void acpi_1_interrupt(void) +static void acpi_1_interrupt(void) { uint8_t st = MCHP_ACPI_EC_STATUS(1); - if (!(st & EC_LPC_STATUS_FROM_HOST) || - !(st & EC_LPC_STATUS_LAST_CMD)) + if (!(st & EC_LPC_STATUS_FROM_HOST) || !(st & EC_LPC_STATUS_LAST_CMD)) return; /* Set the busy bit */ @@ -778,8 +793,7 @@ void acpi_1_interrupt(void) if (host_cmd_args.command == EC_COMMAND_PROTOCOL_3) { lpc_packet.send_response = lpc_send_response_packet; - lpc_packet.request = - (const void *)lpc_get_hostcmd_data_range(); + lpc_packet.request = (const void *)lpc_get_hostcmd_data_range(); lpc_packet.request_temp = params_copy; lpc_packet.request_max = sizeof(params_copy); /* Don't know the request size so @@ -787,8 +801,7 @@ void acpi_1_interrupt(void) */ lpc_packet.request_size = EC_LPC_HOST_PACKET_SIZE; - lpc_packet.response = - (void *)lpc_get_hostcmd_data_range(); + lpc_packet.response = (void *)lpc_get_hostcmd_data_range(); lpc_packet.response_max = EC_LPC_HOST_PACKET_SIZE; lpc_packet.response_size = 0; @@ -811,11 +824,10 @@ DECLARE_IRQ(MCHP_IRQ_ACPIEC1_IBF, acpi_1_interrupt, 1); * Reading data out of input buffer clears read-only status * in 8042EM. Next, we must clear aggregator status. */ -void kb_ibf_interrupt(void) +static void kb_ibf_interrupt(void) { if (lpc_keyboard_input_pending()) - keyboard_host_write(MCHP_8042_H2E, - MCHP_8042_STS & BIT(3)); + keyboard_host_write(MCHP_8042_H2E, MCHP_8042_STS & BIT(3)); MCHP_INT_SOURCE(MCHP_8042_GIRQ) = MCHP_8042_IBF_GIRQ_BIT; task_wake(TASK_ID_KEYPROTO); @@ -829,7 +841,7 @@ DECLARE_IRQ(MCHP_IRQ_8042EM_IBF, kb_ibf_interrupt, 1); * aggregator. Clear aggregator 8042EM OBE R/WC status bit before * invoking task. */ -void kb_obe_interrupt(void) +static void kb_obe_interrupt(void) { MCHP_INT_SOURCE(MCHP_8042_GIRQ) = MCHP_8042_OBE_GIRQ_BIT; task_wake(TASK_ID_KEYPROTO); @@ -898,10 +910,10 @@ void lpc_clear_acpi_status_mask(uint8_t mask) */ int lpc_get_pltrst_asserted(void) { -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI /* * eSPI PLTRST# a VWire or side-band signal - * Controlled by CONFIG_HOSTCMD_ESPI + * Controlled by CONFIG_HOST_INTERFACE_ESPI */ return !espi_vw_get_wire(VW_PLTRST_L); #else @@ -911,7 +923,7 @@ int lpc_get_pltrst_asserted(void) return !gpio_get_level(GPIO_PCH_PLTRST_L); #else /* assumes LPC clock is running when host changes LRESET# */ - return (MCHP_LPC_BUS_MONITOR & (1<<1)) ? 1 : 0; + return (MCHP_LPC_BUS_MONITOR & (1 << 1)) ? 1 : 0; #endif #endif } @@ -929,7 +941,7 @@ void lpc_disable_acpi_interrupts(void) } /* On boards without a host, this command is used to set up LPC */ -static int lpc_command_init(int argc, char **argv) +static int lpc_command_init(int argc, const char **argv) { lpc_init(); return EC_SUCCESS; @@ -951,14 +963,13 @@ static enum ec_status lpc_get_protocol_info(struct host_cmd_handler_args *args) args->response_size = sizeof(*r); - return EC_SUCCESS; + return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, - lpc_get_protocol_info, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, lpc_get_protocol_info, + EC_VER_MASK(0)); #ifdef CONFIG_MCHP_DEBUG_LPC -static int command_lpc(int argc, char **argv) +static int command_lpc(int argc, const char **argv) { if (argc == 1) return EC_ERROR_PARAM1; @@ -973,7 +984,5 @@ static int command_lpc(int argc, char **argv) return EC_ERROR_PARAM1; return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(lpc, command_lpc, "[sci|smi|wake]", - "Trigger SCI/SMI"); +DECLARE_CONSOLE_COMMAND(lpc, command_lpc, "[sci|smi|wake]", "Trigger SCI/SMI"); #endif - diff --git a/chip/mchp/lpc_chip.h b/chip/mchp/lpc_chip.h index dcb5577fc1..7d9965f156 100644 --- a/chip/mchp/lpc_chip.h +++ b/chip/mchp/lpc_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,11 +8,11 @@ #ifndef __CROS_EC_LPC_CHIP_H #define __CROS_EC_LPC_CHIP_H -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI #include "espi.h" -#define MCHP_HOST_IF_LPC (0) +#define MCHP_HOST_IF_LPC (0) #define MCHP_HOST_IF_ESPI (1) /* eSPI Initialization functions */ @@ -37,7 +37,7 @@ void lpc_set_init_done(int val); void lpc_mem_mapped_init(void); -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI void lpcrst_interrupt(enum gpio_signal signal); #endif diff --git a/chip/mchp/port80.c b/chip/mchp/port80.c index 8be91e9d3d..57ceaac8fa 100644 --- a/chip/mchp/port80.c +++ b/chip/mchp/port80.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,16 +14,43 @@ #include "task.h" #include "tfdp_chip.h" +#if defined(CHIP_FAMILY_MEC172X) +/* + * MEC172x family implements a new Port 0x80 capture block. + * The BDP HW can capture 8, 16, and 32 bit writes. + * Interrupt fires when BDP FIFO threshold is reached. + * Data can be read from a 16-bit register containing: + * b[7:0] data byte + * b[9:8] = byte lane + * b[11:10]= flags indicating current byte is a single byte or part of + * a multi-byte sequence. + * b[14:12] = copy of bits[2:0] of the status register + * b[15] = 0 reserved + * NOTE: The overrun bit could be used to set a flag indicating EC could + * not keep up with the host. + */ +static void port_80_interrupt(void) +{ + int d = MCHP_BDP0_DATTR; + + while (d & MCHP_BDP_DATTR_NE) { + port_80_write(d & 0xffU); + d = MCHP_BDP0_DATTR; + } + MCHP_INT_SOURCE(MCHP_BDP0_GIRQ) = MCHP_BDP0_GIRQ_BIT; +} +DECLARE_IRQ(MCHP_IRQ_BDP0, port_80_interrupt, 3); +#else /* * Interrupt fires when number of bytes written * to eSPI/LPC I/O 80h-81h exceeds Por80_0 FIFO level * Issues: * 1. eSPI will not break 16-bit I/O into two 8-bit writes - * as LPC does. This means Port80 hardware will capture + * as LPC does. This means Port 80h hardware will capture * only bits[7:0] of data. * 2. If Host performs write of 16-bit code as consecutive - * byte writes the Port80 hardware will capture both but + * byte writes the Port 80h hardware will capture both but * we do not know the order it was written. * 3. If Host sometimes writes one byte code to I/O 80h and * sometimes two byte code to I/O 80h/81h how do we determine @@ -33,13 +60,16 @@ * to I/O 80h and 90h. LSB to 0x80 and MSB to 0x90. * */ -void port_80_interrupt(void) +static void port_80_interrupt(void) { int d; while (MCHP_P80_STS(0) & MCHP_P80_STS_NOT_EMPTY) { - /* this masks off time stamp d = port_80_read(); */ - d = MCHP_P80_CAP(0); /* b[7:0] = data, b[31:8] = timestamp */ + /* + * This masks off time stamp d = port_80_read(); + * b[7:0] = data, b[32:8] = time stamp + */ + d = MCHP_P80_CAP(0); trace1(0, P80, 0, "Port80h = 0x%02x", (d & 0xff)); port_80_write(d & 0xff); } @@ -47,5 +77,4 @@ void port_80_interrupt(void) MCHP_INT_SOURCE(MCHP_P80_GIRQ) = MCHP_P80_GIRQ_BIT(0); } DECLARE_IRQ(MCHP_IRQ_PORT80DBG0, port_80_interrupt, 3); - - +#endif diff --git a/chip/mchp/pwm.c b/chip/mchp/pwm.c index 53a8c15806..706228fa53 100644 --- a/chip/mchp/pwm.c +++ b/chip/mchp/pwm.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,53 +12,34 @@ #include "pwm.h" #include "pwm_chip.h" #include "registers.h" -#include "util.h" #include "tfdp_chip.h" +#include "util.h" #define CPUTS(outstr) cputs(CC_PWM, outstr) -#define CPRINTS(format, args...) cprints(CC_PWM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_PWM, format, ##args) -/* - * PWMs that must remain active in low-power idle - - * PWM 0,1-8 are b[4,20:27] of MCHP_PCR_SLP_EN1 - * PWM 9 is b[31] of MCHP_PCR_SLP_EN3 - * PWM 10 - 11 are b[0:1] of MCHP_PCR_SLP_EN4 - * store 32-bit word with - * b[0:1] = PWM 10-11 - * b[4,20:27] = PWM 0, 1-8 - * b[31] = PWM 9 - */ +/* Bit map of PWM channels that must remain active during low power idle. */ static uint32_t pwm_keep_awake_mask; -const uint8_t pwm_slp_bitpos[12] = { - 4, 20, 21, 22, 23, 24, 25, 26, 27, 31, 0, 1 +/* Table of PWM PCR sleep enable register index and bit position. */ +static const uint16_t pwm_pcr[] = { + MCHP_PCR_PWM0, MCHP_PCR_PWM1, MCHP_PCR_PWM2, + MCHP_PCR_PWM3, MCHP_PCR_PWM4, MCHP_PCR_PWM5, + MCHP_PCR_PWM6, MCHP_PCR_PWM7, MCHP_PCR_PWM8, }; - -static uint32_t pwm_get_sleep_mask(int id) -{ - uint32_t bitpos = 32; - - if (id < 12) - bitpos = (uint32_t)pwm_slp_bitpos[id]; - - return (1ul << bitpos); -} - +BUILD_ASSERT(ARRAY_SIZE(pwm_pcr) == MCHP_PWM_ID_MAX); void pwm_enable(enum pwm_channel ch, int enabled) { int id = pwm_channels[ch].channel; - uint32_t pwm_slp_mask; - - pwm_slp_mask = pwm_get_sleep_mask(id); if (enabled) { - MCHP_PWM_CFG(id) |= 0x1; + MCHP_PWM_CFG(id) |= BIT(0); if (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP) - pwm_keep_awake_mask |= pwm_slp_mask; + pwm_keep_awake_mask |= BIT(id); } else { - MCHP_PWM_CFG(id) &= ~0x1; - pwm_keep_awake_mask &= ~pwm_slp_mask; + MCHP_PWM_CFG(id) &= ~BIT(0); + pwm_keep_awake_mask &= ~BIT(id); } } @@ -88,47 +69,25 @@ int pwm_get_duty(enum pwm_channel ch) void pwm_keep_awake(void) { if (pwm_keep_awake_mask) { - /* b[4,20:27] */ - MCHP_PCR_SLP_EN1 &= ~(pwm_keep_awake_mask & - (MCHP_PCR_SLP_EN1_PWM_ALL)); - /* b[31] */ - MCHP_PCR_SLP_EN3 &= ~(pwm_keep_awake_mask & - (MCHP_PCR_SLP_EN3_PWM_ALL)); - /* b[1:0] */ - MCHP_PCR_SLP_EN4 &= ~(pwm_keep_awake_mask & - (MCHP_PCR_SLP_EN4_PWM_ALL)); + for (uint32_t i = 0; i < MCHP_PWM_ID_MAX; i++) + if (pwm_keep_awake_mask & BIT(i)) + MCHP_PCR_SLP_DIS_DEV(pwm_pcr[i]); } else { - MCHP_PCR_SLOW_CLK_CTL &= 0xFFFFFC00; + MCHP_PCR_SLOW_CLK_CTL &= ~(MCHP_PCR_SLOW_CLK_CTL_MASK); } } - +/* + * clock_low=0 selects the 48MHz Ring Oscillator source + * clock_low=1 selects the 100kHz_Clk source + */ static void pwm_configure(int ch, int active_low, int clock_low) { - /* - * clock_low=0 selects the 48MHz Ring Oscillator source - * clock_low=1 selects the 100kHz_Clk source - */ - MCHP_PWM_CFG(ch) = (15 << 3) | /* Pre-divider = 16 */ - (active_low ? BIT(2) : 0) | - (clock_low ? BIT(1) : 0); + MCHP_PWM_CFG(ch) = (15 << 3) /* divider = 16 */ + | (active_low ? BIT(2) : 0) | + (clock_low ? BIT(1) : 0); } -static const uint16_t pwm_pcr[MCHP_PWM_ID_MAX] = { - MCHP_PCR_PWM0, - MCHP_PCR_PWM1, - MCHP_PCR_PWM2, - MCHP_PCR_PWM3, - MCHP_PCR_PWM4, - MCHP_PCR_PWM5, - MCHP_PCR_PWM6, - MCHP_PCR_PWM7, - MCHP_PCR_PWM8, - MCHP_PCR_PWM9, - MCHP_PCR_PWM10, - MCHP_PCR_PWM11, -}; - static void pwm_slp_en(int pwm_id, int sleep_en) { if ((pwm_id < 0) || (pwm_id > MCHP_PWM_ID_MAX)) diff --git a/chip/mchp/pwm_chip.h b/chip/mchp/pwm_chip.h index 85ff484f86..848656bb03 100644 --- a/chip/mchp/pwm_chip.h +++ b/chip/mchp/pwm_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,6 +7,34 @@ #ifndef __CROS_EC_PWM_CHIP_H #define __CROS_EC_PWM_CHIP_H +/* + * MEC152x SZ 144-pin has 9 PWM and 4 TACH + * MEC170x SZ 144-pin has 9 PWM and 3 TACH + * MEC172x SZ 144-pin has 9 PWM and 4 TACH + */ +enum pwm_hw_id { + PWM_HW_CH_0 = 0, + PWM_HW_CH_1, + PWM_HW_CH_2, + PWM_HW_CH_3, + PWM_HW_CH_4, + PWM_HW_CH_5, + PWM_HW_CH_6, + PWM_HW_CH_7, + PWM_HW_CH_8, + PWM_HW_CH_COUNT +}; + +enum tach_hw_id { + TACH_HW_CH_0 = 0, + TACH_HW_CH_1, + TACH_HW_CH_2, +#ifndef CHIP_FAMILY_MEC170X + TACH_HW_CH_3, +#endif + TACH_HW_CH_COUNT +}; + /* Data structure to define PWM channels. */ struct pwm_t { /* PWM Channel ID */ @@ -20,4 +48,4 @@ extern const struct pwm_t pwm_channels[]; void pwm_keep_awake(void); -#endif /* __CROS_EC_PWM_CHIP_H */ +#endif /* __CROS_EC_PWM_CHIP_H */ diff --git a/chip/mchp/qmspi.c b/chip/mchp/qmspi.c index 72eaa91d37..a0d31b72e3 100644 --- a/chip/mchp/qmspi.c +++ b/chip/mchp/qmspi.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,27 +8,25 @@ #include "common.h" #include "console.h" #include "dma.h" +#include "dma_chip.h" #include "gpio.h" +#include "hooks.h" +#include "qmspi_chip.h" #include "registers.h" #include "spi.h" -#include "timer.h" -#include "util.h" -#include "hooks.h" -#include "task.h" -#include "dma_chip.h" #include "spi_chip.h" -#include "qmspi_chip.h" +#include "task.h" #include "tfdp_chip.h" +#include "timer.h" +#include "util.h" #define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) #define QMSPI_TRANSFER_TIMEOUT (100 * MSEC) #define QMSPI_BYTE_TRANSFER_TIMEOUT_US (3 * MSEC) #define QMSPI_BYTE_TRANSFER_POLL_INTERVAL_US 20 - - #ifndef CONFIG_MCHP_QMSPI_TX_DMA #ifdef LFW /* @@ -137,8 +135,8 @@ static uint32_t qmspi_build_tx_descr(uint32_t ntx, uint32_t ndid) * value (1, 2, or 4). * Caller will apply close and last flags if applicable. */ -static uint64_t qmspi_build_rx_descr(uint32_t raddr, - uint32_t nrx, uint32_t ndid) +static uint64_t qmspi_build_rx_descr(uint32_t raddr, uint32_t nrx, + uint32_t ndid) { uint32_t d, dmau, na; uint64_t u; @@ -182,9 +180,9 @@ static uint64_t qmspi_build_rx_descr(uint32_t raddr, #ifdef CONFIG_MCHP_QMSPI_TX_DMA -#define QMSPI_ERR_ANY 0x80 -#define QMSPI_ERR_BAD_PTR 0x81 -#define QMSPI_ERR_OUT_OF_DESCR 0x85 +#define QMSPI_ERR_ANY 0x80 +#define QMSPI_ERR_BAD_PTR 0x81 +#define QMSPI_ERR_OUT_OF_DESCR 0x85 /* * bits[1:0] of word @@ -206,9 +204,9 @@ static void qmspi_descr_mode_ready(void) int i; MCHP_QMSPI0_CTRL = 0; - MCHP_QMSPI0_IEN = 0; - MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_CLR_FIFOS; - MCHP_QMSPI0_STS = 0xfffffffful; + MCHP_QMSPI0_IEN = 0; + MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_CLR_FIFOS; + MCHP_QMSPI0_STS = 0xfffffffful; MCHP_QMSPI0_CTRL = MCHP_QMSPI_C_DESCR_MODE_EN; /* clear all descriptors */ for (i = 0; i < MCHP_QMSPI_MAX_DESCR; i++) @@ -229,8 +227,7 @@ static void qmspi_descr_mode_ready(void) * and remaining < 16 bytes in byte unit descriptor until all bytes * exhausted or out of descriptors error. */ -static uint32_t qmspi_descr_alloc(uint32_t did, - uint32_t descr, uint32_t nb) +static uint32_t qmspi_descr_alloc(uint32_t did, uint32_t descr, uint32_t nb) { uint32_t nu; @@ -238,8 +235,8 @@ static uint32_t qmspi_descr_alloc(uint32_t did, if (did >= MCHP_QMSPI_MAX_DESCR) return 0xffff; - descr &= ~(MCHP_QMSPI_C_NUM_UNITS_MASK + - MCHP_QMSPI_C_XFRU_MASK); + descr &= + ~(MCHP_QMSPI_C_NUM_UNITS_MASK + MCHP_QMSPI_C_XFRU_MASK); if (nb < (MCHP_QMSPI_C_MAX_UNITS + 1)) { descr |= MCHP_QMSPI_C_XFRU_1B; @@ -252,7 +249,7 @@ static uint32_t qmspi_descr_alloc(uint32_t did, nb -= (nu << 4); } - descr |= ((did+1) << MCHP_QMSPI_C_NEXT_DESCR_BITPOS); + descr |= ((did + 1) << MCHP_QMSPI_C_NEXT_DESCR_BITPOS); MCHP_QMSPI0_DESCR(did) = descr; if (nb) did++; @@ -271,9 +268,8 @@ static uint32_t qmspi_descr_alloc(uint32_t did, * channel and configure the DMA channel for memory to device transfer. */ static uint32_t qmspi_xmit_data_descr(const struct dma_option *opdma, - uint32_t cfg, - const uint8_t *data, - uint32_t ndata) + uint32_t cfg, const uint8_t *data, + uint32_t ndata) { uint32_t d, d2, did, dma_cfg; @@ -282,7 +278,7 @@ static uint32_t qmspi_xmit_data_descr(const struct dma_option *opdma, if (ndata <= MCHP_QMSPI_TX_FIFO_LEN) { d2 = d + (ndata << MCHP_QMSPI_C_NUM_UNITS_BITPOS) + - MCHP_QMSPI_C_XFRU_1B + MCHP_QMSPI_C_TX_DATA; + MCHP_QMSPI_C_XFRU_1B + MCHP_QMSPI_C_TX_DATA; d2 += ((did + 1) << MCHP_QMSPI_C_NEXT_DESCR_BITPOS); MCHP_QMSPI0_DESCR(did) = d2; while (ndata--) @@ -290,12 +286,10 @@ static uint32_t qmspi_xmit_data_descr(const struct dma_option *opdma, } else { // TX DMA if (((uint32_t)data | ndata) & 0x03) { dma_cfg = 1; - d |= (MCHP_QMSPI_C_TX_DATA + - MCHP_QMSPI_C_TX_DMA_1B); + d |= (MCHP_QMSPI_C_TX_DATA + MCHP_QMSPI_C_TX_DMA_1B); } else { dma_cfg = 4; - d |= (MCHP_QMSPI_C_TX_DATA + - MCHP_QMSPI_C_TX_DMA_4B); + d |= (MCHP_QMSPI_C_TX_DATA + MCHP_QMSPI_C_TX_DMA_4B); } did = qmspi_descr_alloc(did, d, ndata); if (did == 0xffff) @@ -303,10 +297,9 @@ static uint32_t qmspi_xmit_data_descr(const struct dma_option *opdma, dma_clr_chan(opdma->channel); dma_cfg_buffers(opdma->channel, data, ndata, - (void *)MCHP_QMSPI0_TX_FIFO_ADDR); - dma_cfg_xfr(opdma->channel, dma_cfg, - MCHP_DMA_QMSPI0_TX_REQ_ID, - (DMA_FLAG_M2D + DMA_FLAG_INCR_MEM)); + (void *)MCHP_QMSPI0_TX_FIFO_ADDR); + dma_cfg_xfr(opdma->channel, dma_cfg, MCHP_DMA_QMSPI0_TX_REQ_ID, + (DMA_FLAG_M2D + DMA_FLAG_INCR_MEM)); dma_run(opdma->channel); } @@ -327,8 +320,8 @@ void qmspi_cfg_irq_start(uint8_t flags) MCHP_QMSPI0_IEN = 0; if (flags & (1u << 1)) { - MCHP_QMSPI0_IEN = (MCHP_QMSPI_STS_DONE + - MCHP_QMSPI_STS_PROG_ERR); + MCHP_QMSPI0_IEN = + (MCHP_QMSPI_STS_DONE + MCHP_QMSPI_STS_PROG_ERR); MCHP_INT_ENABLE(MCHP_QMSPI_GIRQ) = MCHP_QMSPI_GIRQ_BIT; } @@ -349,10 +342,9 @@ void qmspi_cfg_irq_start(uint8_t flags) * returns last descriptor 0 <= index < MCHP_QMSPI_MAX_DESCR * or error (bit[7]==1) */ -uint8_t qmspi_xfr(const struct spi_device_t *spi_device, - uint32_t np_flags, - const uint8_t *txdata, uint32_t ntx, - uint8_t *rxdata, uint32_t nrx) +uint8_t qmspi_xfr(const struct spi_device_t *spi_device, uint32_t np_flags, + const uint8_t *txdata, uint32_t ntx, uint8_t *rxdata, + uint32_t nrx) { uint32_t d, did, dma_cfg; const struct dma_option *opdma; @@ -399,10 +391,9 @@ uint8_t qmspi_xfr(const struct spi_device_t *spi_device, opdma = spi_dma_option(spi_device, SPI_DMA_OPTION_RD); dma_clr_chan(opdma->channel); dma_cfg_buffers(opdma->channel, rxdata, nrx, - (void *)MCHP_QMSPI0_RX_FIFO_ADDR); - dma_cfg_xfr(opdma->channel, dma_cfg, - MCHP_DMA_QMSPI0_RX_REQ_ID, - (DMA_FLAG_D2M + DMA_FLAG_INCR_MEM)); + (void *)MCHP_QMSPI0_RX_FIFO_ADDR); + dma_cfg_xfr(opdma->channel, dma_cfg, MCHP_DMA_QMSPI0_RX_REQ_ID, + (DMA_FLAG_D2M + DMA_FLAG_INCR_MEM)); dma_run(opdma->channel); } @@ -466,8 +457,8 @@ uint8_t qmspi_xfr(const struct spi_device_t *spi_device, */ #ifdef CONFIG_MCHP_QMSPI_TX_DMA int qmspi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) { uint32_t np_flags, ntx, nrx; int ret; @@ -482,9 +473,7 @@ int qmspi_transaction_async(const struct spi_device_t *spi_device, nrx = (uint32_t)rxlen; np_flags = 0x010105; /* b[0]=1 close on done, b[2]=1 start */ - rc = qmspi_xfr(spi_device, np_flags, - txdata, ntx, - rxdata, nrx); + rc = qmspi_xfr(spi_device, np_flags, txdata, ntx, rxdata, nrx); if (rc & QMSPI_ERR_ANY) return EC_ERROR_INVAL; @@ -498,8 +487,8 @@ int qmspi_transaction_async(const struct spi_device_t *spi_device, * Receive using DMA as above. */ int qmspi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) { const struct dma_option *opdma; uint32_t d, did, dmau; @@ -533,8 +522,7 @@ int qmspi_transaction_async(const struct spi_device_t *spi_device, if (rxdata == NULL) return EC_ERROR_PARAM4; - u = qmspi_build_rx_descr((uint32_t)rxdata, - (uint32_t)rxlen, 2); + u = qmspi_build_rx_descr((uint32_t)rxdata, (uint32_t)rxlen, 2); d = (uint32_t)u; dmau = u >> 32; @@ -547,16 +535,16 @@ int qmspi_transaction_async(const struct spi_device_t *spi_device, dma_xfr_start_rx(opdma, dmau, (uint32_t)rxlen, rxdata); } - MCHP_QMSPI0_DESCR(did) |= (MCHP_QMSPI_C_CLOSE + - MCHP_QMSPI_C_DESCR_LAST); + MCHP_QMSPI0_DESCR(did) |= + (MCHP_QMSPI_C_CLOSE + MCHP_QMSPI_C_DESCR_LAST); MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_START; while (txlen--) { if (MCHP_QMSPI0_STS & MCHP_QMSPI_STS_TX_BUFF_FULL) { if (qmspi_wait(MCHP_QMSPI_STS_TX_BUFF_EMPTY, - MCHP_QMSPI_STS_TX_BUFF_EMPTY) != - EC_SUCCESS) { + MCHP_QMSPI_STS_TX_BUFF_EMPTY) != + EC_SUCCESS) { MCHP_QMSPI0_EXE = MCHP_QMSPI_EXE_STOP; return EC_ERROR_TIMEOUT; } @@ -673,8 +661,8 @@ int qmspi_enable(int hw_port, int enable) { uint8_t unused __attribute__((unused)) = 0; - trace2(0, QMSPI, 0, "qmspi_enable: port = %d enable = %d", - hw_port, enable); + trace2(0, QMSPI, 0, "qmspi_enable: port = %d enable = %d", hw_port, + enable); if (hw_port != QMSPI0_PORT) return EC_ERROR_INVAL; @@ -685,9 +673,9 @@ int qmspi_enable(int hw_port, int enable) MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_QMSPI); MCHP_QMSPI0_MODE_ACT_SRST = MCHP_QMSPI_M_SOFT_RESET; unused = MCHP_QMSPI0_MODE_ACT_SRST; - MCHP_QMSPI0_MODE = (MCHP_QMSPI_M_ACTIVATE + - MCHP_QMSPI_M_SPI_MODE0 + - MCHP_QMSPI_M_CLKDIV_12M); + MCHP_QMSPI0_MODE = + (MCHP_QMSPI_M_ACTIVATE + MCHP_QMSPI_M_SPI_MODE0 + + MCHP_QMSPI_M_CLKDIV_12M); } else { MCHP_QMSPI0_MODE_ACT_SRST = MCHP_QMSPI_M_SOFT_RESET; unused = MCHP_QMSPI0_MODE_ACT_SRST; @@ -697,4 +685,3 @@ int qmspi_enable(int hw_port, int enable) return EC_SUCCESS; } - diff --git a/chip/mchp/qmspi_chip.h b/chip/mchp/qmspi_chip.h index 1a1d764267..899f59516f 100644 --- a/chip/mchp/qmspi_chip.h +++ b/chip/mchp/qmspi_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -13,24 +13,23 @@ #ifndef _QMSPI_CHIP_H #define _QMSPI_CHIP_H -#include #include +#include /* struct spi_device_t */ #include "spi.h" - int qmspi_transaction_flush(const struct spi_device_t *spi_device); int qmspi_transaction_wait(const struct spi_device_t *spi_device); int qmspi_transaction_sync(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen); + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen); int qmspi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen); + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen); int qmspi_enable(int port, int enable); @@ -56,12 +55,10 @@ void qmspi_cfg_irq_start(uint8_t flags); * returns last descriptor 0 <= index < MCHP_QMSPI_MAX_DESCR * or error (bit[7]==1) */ -uint8_t qmspi_xfr(const struct spi_device_t *spi_device, - uint32_t np_flags, - const uint8_t *txdata, uint32_t ntx, - uint8_t *rxdata, uint32_t nrx); +uint8_t qmspi_xfr(const struct spi_device_t *spi_device, uint32_t np_flags, + const uint8_t *txdata, uint32_t ntx, uint8_t *rxdata, + uint32_t nrx); #endif /* #ifndef _QMSPI_CHIP_H */ /** @} */ - diff --git a/chip/mchp/registers-mec152x.h b/chip/mchp/registers-mec152x.h new file mode 100644 index 0000000000..166ca63310 --- /dev/null +++ b/chip/mchp/registers-mec152x.h @@ -0,0 +1,1268 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Register map for Microchip MEC152x family controllers + */ + +#ifndef __CROS_EC_REGISTERS_H +#error "This header file should not be included directly." +#endif + +/* + * IRQ Numbers + * NOTE: GIRQ22 aggregated output and its sources are not connected to + * the NVIC. + */ +#define MCHP_IRQ_GIRQ8 0 +#define MCHP_IRQ_GIRQ9 1 +#define MCHP_IRQ_GIRQ10 2 +#define MCHP_IRQ_GIRQ11 3 +#define MCHP_IRQ_GIRQ12 4 +#define MCHP_IRQ_GIRQ13 5 +#define MCHP_IRQ_GIRQ14 6 +#define MCHP_IRQ_GIRQ15 7 +#define MCHP_IRQ_GIRQ16 8 +#define MCHP_IRQ_GIRQ17 9 +#define MCHP_IRQ_GIRQ18 10 +#define MCHP_IRQ_GIRQ19 11 +#define MCHP_IRQ_GIRQ20 12 +#define MCHP_IRQ_GIRQ21 13 +#define MCHP_IRQ_GIRQ23 14 +#define MCHP_IRQ_GIRQ24 15 +#define MCHP_IRQ_GIRQ25 16 +#define MCHP_IRQ_GIRQ26 17 +/* GIRQ13 direct sources */ +#define MCHP_IRQ_I2C_0 20 +#define MCHP_IRQ_I2C_1 21 +#define MCHP_IRQ_I2C_2 22 +#define MCHP_IRQ_I2C_3 23 +#define MCHP_IRQ_I2C_4 158 +#define MCHP_IRQ_I2C_5 168 +#define MCHP_IRQ_I2C_6 169 +#define MCHP_IRQ_I2C_7 170 +/* GIRQ14 direct sources */ +#define MCHP_IRQ_DMA_0 24 +#define MCHP_IRQ_DMA_1 25 +#define MCHP_IRQ_DMA_2 26 +#define MCHP_IRQ_DMA_3 27 +#define MCHP_IRQ_DMA_4 28 +#define MCHP_IRQ_DMA_5 29 +#define MCHP_IRQ_DMA_6 30 +#define MCHP_IRQ_DMA_7 31 +#define MCHP_IRQ_DMA_8 32 +#define MCHP_IRQ_DMA_9 33 +#define MCHP_IRQ_DMA_10 34 +#define MCHP_IRQ_DMA_11 35 +/* GIRQ15 direct sources */ +#define MCHP_IRQ_UART0 40 +#define MCHP_IRQ_UART1 41 +#define MCHP_IRQ_EMI0 42 +#define MCHP_IRQ_EMI1 43 +#define MCHP_IRQ_UART2 44 +#define MCHP_IRQ_ACPIEC0_IBF 45 +#define MCHP_IRQ_ACPIEC0_OBE 46 +#define MCHP_IRQ_ACPIEC1_IBF 47 +#define MCHP_IRQ_ACPIEC1_OBE 48 +#define MCHP_IRQ_ACPIEC2_IBF 49 +#define MCHP_IRQ_ACPIEC2_OBE 50 +#define MCHP_IRQ_ACPIEC3_IBF 51 +#define MCHP_IRQ_ACPIEC3_OBE 52 +#define MCHP_IRQ_ACPIPM1_CTL 55 +#define MCHP_IRQ_ACPIPM1_EN 56 +#define MCHP_IRQ_ACPIPM1_STS 57 +#define MCHP_IRQ_8042EM_OBE 58 +#define MCHP_IRQ_8042EM_IBF 59 +#define MCHP_IRQ_MAILBOX_DATA 60 +#define MCHP_IRQ_PORT80DBG0 62 +#define MCHP_IRQ_PORT80DBG1 63 +#define MCHP_IRQ_LASIC 64 +/* GIRQ16 direct sources */ +#define MCHP_IRQ_PKE_ERR 65 +#define MCHP_IRQ_PKE_END 66 +#define MCHP_IRQ_NDRNG 67 +#define MCHP_IRQ_AES 68 +#define MCHP_IRQ_HASH 69 +/* GIRQ17 direct sources */ +#define MCHP_IRQ_PECI_HOST 70 +#define MCHP_IRQ_TACH_0 71 +#define MCHP_IRQ_TACH_1 72 +#define MCHP_IRQ_TACH_2 73 +#define MCHP_IRQ_TACH_3 159 +#define MCHP_IRQ_HDMI_CEC 160 +#define MCHP_IRQ_ADC_SNGL 78 +#define MCHP_IRQ_ADC_RPT 79 +#define MCHP_IRQ_LED0_WDT 83 +#define MCHP_IRQ_LED1_WDT 84 +#define MCHP_IRQ_LED2_WDT 85 +#define MCHP_IRQ_PROCHOT 87 +/* GIRQ18 direct sources */ +#define MCHP_IRQ_SLAVE_SPI 90 +#define MCHP_IRQ_QMSPI0 91 +#define MCHP_IRQ_PS2_0 100 +#define MCHP_IRQ_PS2_1 101 +#define MCHP_IRQ_PSPI 155 +#define MCHP_IRQ_SGPIO_0 161 +#define MCHP_IRQ_SGPIO_1 162 +#define MCHP_IRQ_SGPIO_2 163 +#define MCHP_IRQ_SGPIO_3 164 +#define MCHP_IRQ_CCT_TMR 146 +#define MCHP_IRQ_CCT_CAP0 147 +#define MCHP_IRQ_CCT_CAP1 148 +#define MCHP_IRQ_CCT_CAP2 149 +#define MCHP_IRQ_CCT_CAP3 150 +#define MCHP_IRQ_CCT_CAP4 151 +#define MCHP_IRQ_CCT_CAP5 152 +#define MCHP_IRQ_CCT_CMP0 153 +#define MCHP_IRQ_CCT_CMP1 154 +/* GIRQ19 direct sources */ +#define MCHP_IRQ_ESPI_PC 103 +#define MCHP_IRQ_ESPI_BM1 104 +#define MCHP_IRQ_ESPI_BM2 105 +#define MCHP_IRQ_ESPI_LTR 106 +#define MCHP_IRQ_ESPI_OOB_UP 107 +#define MCHP_IRQ_ESPI_OOB_DN 108 +#define MCHP_IRQ_ESPI_FC 109 +#define MCHP_IRQ_ESPI_RESET 110 +#define MCHP_IRQ_ESPI_VW_EN 156 +/* GIRQ20 direct sources */ +#define MCHP_IRQ_OTP 173 +/* GIRQ21 direct sources */ +#define MCHP_IRQ_WDG 171 +#define MCHP_IRQ_WEEK_ALARM 114 +#define MCHP_IRQ_SUBWEEK 115 +#define MCHP_IRQ_WEEK_SEC 116 +#define MCHP_IRQ_WEEK_SUBSEC 117 +#define MCHP_IRQ_WEEK_SYSPWR 118 +#define MCHP_IRQ_RTC 119 +#define MCHP_IRQ_RTC_ALARM 120 +#define MCHP_IRQ_VCI_OVRD_IN 121 +#define MCHP_IRQ_VCI_IN0 122 +#define MCHP_IRQ_VCI_IN1 123 +#define MCHP_IRQ_VCI_IN2 124 +#define MCHP_IRQ_VCI_IN3 125 +#define MCHP_IRQ_PS20A_WAKE 129 +#define MCHP_IRQ_PS20B_WAKE 130 +#define MCHP_IRQ_PS21B_WAKE 132 +#define MCHP_IRQ_KSC_INT 135 +/* GIRQ23 direct sources */ +#define MCHP_IRQ_TIMER16_0 136 +#define MCHP_IRQ_TIMER16_1 137 +#define MCHP_IRQ_TIMER32_0 140 +#define MCHP_IRQ_TIMER32_1 141 +#define MCHP_IRQ_RTOS_TIMER 111 +#define MCHP_IRQ_HTIMER0 112 +#define MCHP_IRQ_HTIMER1 113 +/* Must match CONFIG_IRQ_COUNT in config_chip.h */ +#define MCHP_IRQ_MAX 174 + +/* Block base addresses */ +#define MCHP_WDG_BASE 0x40000400 +#define MCHP_TMR16_0_BASE 0x40000c00 +#define MCHP_TMR32_0_BASE 0x40000c80 +#define MCHP_DMA_BASE 0x40002400 +#define MCHP_PROCHOT_BASE 0x40003400 +#define MCHP_I2C0_BASE 0x40004000 +#define MCHP_I2C1_BASE 0x40004400 +#define MCHP_I2C2_BASE 0x40004800 +#define MCHP_I2C3_BASE 0x40004C00 +#define MCHP_I2C4_BASE 0x40005000 +#define MCHP_I2C5_BASE 0x40005100 +#define MCHP_I2C6_BASE 0x40005200 +#define MCHP_I2C7_BASE 0x40005300 +#define MCHP_QMSPI0_BASE 0x40070000 +#define MCHP_PWM_0_BASE 0x40005800 +#define MCHP_TACH_0_BASE 0x40006000 +#define MCHP_PECI_BASE 0x40006400 +#define MCHP_RTMR_BASE 0x40007400 +#define MCHP_ADC_BASE 0x40007c00 +#define MCHP_TFDP_BASE 0x40008c00 +#define MCHP_HTIMER_BASE 0x40009800 +#define MCHP_KEYSCAN_BASE 0x40009c00 +#define MCHP_VBAT_BASE 0x4000a400 +#define MCHP_VBAT_RAM_BASE 0x4000a800 +#define MCHP_WKTIMER_BASE 0x4000ac80 +#define MCHP_BBLED_0_BASE 0x4000B800 +#define MCHP_INT_BASE 0x4000e000 +#define MCHP_EC_BASE 0x4000fc00 + +#define MCHP_PCR_BASE 0x40080100 +#define MCHP_GPIO_BASE 0x40081000 + +#define MCHP_MBOX_BASE 0x400f0000 +#define MCHP_8042_BASE 0x400f0400 +#define MCHP_ACPI_EC_0_BASE 0x400f0800 +#define MCHP_ACPI_PM1_BASE 0x400f1c00 +#define MCHP_UART0_BASE 0x400f2400 +#define MCHP_UART1_BASE 0x400f2800 +#define MCHP_UART2_BASE 0x400f2c00 +#define MCHP_ESPI_IO_BASE 0x400f3400 +#define MCHP_ESPI_MEM_BASE 0x400f3800 +#define MCHP_EMI_0_BASE 0x400f4000 +#define MCHP_EMI_1_BASE 0x400f4400 +#define MCHP_P80CAP0_BASE 0x400f8000 +#define MCHP_P80CAP1_BASE 0x400f8400 +#define MCHP_ESPI_VW_BASE 0x400f9c00 +#define MCHP_CHIP_BASE 0x400fff00 + +#ifndef __ASSEMBLER__ + +/* + * Helper function for RAM address aliasing + * NOTE: MCHP AHB masters do NOT require aliasing. + * Cortex-M4 bit-banding does require aliasing of the + * DATA SRAM region. + */ +#define MCHP_RAM_ALIAS(x) ((x) >= 0x118000 ? (x)-0x118000 + 0x20000000 : (x)) + +/* EC Chip Configuration */ +/* 16-bit Device ID */ +#define MCHP_CHIP_DEV_ID REG16(MCHP_CHIP_BASE + 0x1E) +/* 8-bit Device Sub ID */ +#define MCHP_CHIP_DEV_SUB_ID REG8(MCHP_CHIP_BASE + 0x1D) +/* 8-bit Device Revision */ +#define MCHP_CHIP_DEV_REV REG8(MCHP_CHIP_BASE + 0x1C) +/* All in one */ +#define MCHP_CHIP_DEVRID32 REG32(MCHP_CHIP_BASE + 0x1C) +#define MCHP_CHIP_DEVID_POS 16 +#define MCHP_CHIP_DEVID_MASK (0xfffful << MCHP_CHIP_DEVID_POS) +#define MCHP_CHIP_SUBID_POS 8 +#define MCHP_CHIP_SUBID_MASK (0xfful << MCHP_CHIP_SUBID_POS) +#define MCHP_CHIP_REV_POS 0 +#define MCHP_CHIP_REV_MASK (0xfful << MCHP_CHIP_REV_POS) +#define MCHP_CHIP_EXTRACT_DEVID(d) \ + (((uint32_t)(d)&MCHP_CHIP_DEVID_MASK) >> MCHP_CHIP_DEVID_POS) +#define MCHP_CHIP_EXTRACT_SUBID(d) \ + (((uint32_t)(d)&MCHP_CHIP_SUBID_MASK) >> MCHP_CHIP_SUBID_POS) +#define MCHP_CHIP_EXTRACT_REV(d) \ + (((uint32_t)(d)&MCHP_CHIP_REV_MASK) >> MCHP_CHIP_REV_POS) + +/* PCR clock control dividers */ +#define MCHP_PCR_CLK_CTL_FASTEST 1U +#define MCHP_PCR_CLK_CTL_48MHZ 1U +#define MCHP_PCR_CLK_CTL_12MHZ 4U + +/* + * PCR Peripheral Reset Lock register + * MEC152x PCR Peripheral reset registers do not reset on + * peripheral sleep. The peripheral is reset immediately. + * Firmware must write an unlock value to this new lock + * register, write to PCR reset enable register(s), and + * write a lock value. + */ +#define MCHP_PCR_RST_LOCK REG32(MCHP_PCR_BASE + 0x84) +#define MCHP_PCR_RST_LOCK_VAL 0xa6382d4d +#define MCHP_PCR_RST_UNLOCK_VAL 0xa6382d4c + +/* Number of PCR Sleep Enable, Clock Required, and Reset registers */ +#define MCHP_PCR_SLP_RST_REG_MAX 5 + +/* MC152x new bit allow sleep entry when PLL is not locked */ +#define MCHP_PCR_SYS_SLP_NO_PLL BIT(8) + +/* Sleep 0: Sleep Enable, Clock Required, and Reset bits */ +#define MCHP_PCR_JTAG BIT(0) /* CLKREQ only */ +#define MCHP_PCR_OTP BIT(1) + +/* Command all blocks to sleep */ +#define MCHP_PCR_SLP_EN0_JTAG BIT(0) +#define MCHP_PCR_SLP_EN0_OTP BIT(1) +#define MCHP_PCR_SLP_EN0_SLEEP 0xffffffff + +/* + * Encode register number and bit position + * b[4:0] = bit number + * b[10:8] = zero based register number + */ +#define MCHP_PCR_ERB(rnum, bnum) ((((rnum)&0x0f) << 8) | ((bnum)&0x1f)) + +/* PCR Sleep 1: Sleep Enable, Clock Required, and Reset bits */ +#define MCHP_PCR_BTMR16_1 MCHP_PCR_ERB(1, 31) +#define MCHP_PCR_BTMR16_0 MCHP_PCR_ERB(1, 30) +#define MCHP_PCR_ECS MCHP_PCR_ERB(1, 29) +#define MCHP_PCR_PWM8 MCHP_PCR_ERB(1, 27) +#define MCHP_PCR_PWM7 MCHP_PCR_ERB(1, 26) +#define MCHP_PCR_PWM6 MCHP_PCR_ERB(1, 25) +#define MCHP_PCR_PWM5 MCHP_PCR_ERB(1, 24) +#define MCHP_PCR_PWM4 MCHP_PCR_ERB(1, 23) +#define MCHP_PCR_PWM3 MCHP_PCR_ERB(1, 22) +#define MCHP_PCR_PWM2 MCHP_PCR_ERB(1, 21) +#define MCHP_PCR_PWM1 MCHP_PCR_ERB(1, 20) +#define MCHP_PCR_TACH3 MCHP_PCR_ERB(1, 13) +#define MCHP_PCR_TACH2 MCHP_PCR_ERB(1, 12) +#define MCHP_PCR_TACH1 MCHP_PCR_ERB(1, 11) +#define MCHP_PCR_I2C0 MCHP_PCR_ERB(1, 10) +#define MCHP_PCR_WDT MCHP_PCR_ERB(1, 9) +#define MCHP_PCR_CPU MCHP_PCR_ERB(1, 8) +#define MCHP_PCR_TFDP MCHP_PCR_ERB(1, 7) +#define MCHP_PCR_DMA MCHP_PCR_ERB(1, 6) +#define MCHP_PCR_PMC MCHP_PCR_ERB(1, 5) +#define MCHP_PCR_PWM0 MCHP_PCR_ERB(1, 4) +#define MCHP_PCR_TACH0 MCHP_PCR_ERB(1, 2) +#define MCHP_PCR_PECI MCHP_PCR_ERB(1, 1) +#define MCHP_PCR_ECIA MCHP_PCR_ERB(1, 0) + +/* Command all blocks to sleep */ +#define MCHP_PCR_SLP_EN1_BTMR16_1 BIT(31) +#define MCHP_PCR_SLP_EN1_BTMR16_0 BIT(30) +#define MCHP_PCR_SLP_EN1_ECS BIT(29) +#define MCHP_PCR_SLP_EN1_PWM_ALL (BIT(4) + (0xff << 20)) +#define MCHP_PCR_SLP_EN1_PWM8 BIT(27) +#define MCHP_PCR_SLP_EN1_PWM7 BIT(26) +#define MCHP_PCR_SLP_EN1_PWM6 BIT(25) +#define MCHP_PCR_SLP_EN1_PWM5 BIT(24) +#define MCHP_PCR_SLP_EN1_PWM4 BIT(23) +#define MCHP_PCR_SLP_EN1_PWM3 BIT(22) +#define MCHP_PCR_SLP_EN1_PWM2 BIT(21) +#define MCHP_PCR_SLP_EN1_PWM1 BIT(20) +#define MCHP_PCR_SLP_EN1_TACH3 BIT(13) +#define MCHP_PCR_SLP_EN1_TACH2 BIT(12) +#define MCHP_PCR_SLP_EN1_TACH1 BIT(11) +#define MCHP_PCR_SLP_EN1_I2C0 BIT(10) +#define MCHP_PCR_SLP_EN1_WDT BIT(9) +#define MCHP_PCR_SLP_EN1_CPU BIT(8) +#define MCHP_PCR_SLP_EN1_TFDP BIT(7) +#define MCHP_PCR_SLP_EN1_DMA BIT(6) +#define MCHP_PCR_SLP_EN1_PMC BIT(5) +#define MCHP_PCR_SLP_EN1_PWM0 BIT(4) +#define MCHP_PCR_SLP_EN1_TACH0 BIT(2) +#define MCHP_PCR_SLP_EN1_PECI BIT(1) +#define MCHP_PCR_SLP_EN1_ECIA BIT(0) +/* all sleep enable 1 bits */ +#define MCHP_PCR_SLP_EN1_SLEEP 0xffffffff +/* + * block not used by default + * Do not sleep ECIA, PMC, CPU and ECS + */ +#define MCHP_PCR_SLP_EN1_UNUSED_BLOCKS 0xdffffede + +/* PCR Sleep 2: Sleep Enable, Clock Required 2, Reset bits */ +#define MCHP_PCR_GLUE MCHP_PCR_ERB(2, 29) +#define MCHP_PCR_UART2 MCHP_PCR_ERB(2, 28) +#define MCHP_PCR_SAF MCHP_PCR_ERB(2, 27) +#define MCHP_PCR_P80CAP1 MCHP_PCR_ERB(2, 26) +#define MCHP_PCR_P80CAP0 MCHP_PCR_ERB(2, 25) +#define MCHP_PCR_ASIF MCHP_PCR_ERB(2, 24) +#define MCHP_PCR_ACPI_EC3 MCHP_PCR_ERB(2, 22) +#define MCHP_PCR_ACPI_EC2 MCHP_PCR_ERB(2, 21) +#define MCHP_PCR_ESPI_SCR MCHP_PCR_ERB(2, 20) +#define MCHP_PCR_ESPI MCHP_PCR_ERB(2, 19) +#define MCHP_PCR_RTC MCHP_PCR_ERB(2, 18) +#define MCHP_PCR_MBOX MCHP_PCR_ERB(2, 17) +#define MCHP_PCR_8042 MCHP_PCR_ERB(2, 26) +#define MCHP_PCR_ACPI_PM1 MCHP_PCR_ERB(2, 15) +#define MCHP_PCR_ACPI_EC1 MCHP_PCR_ERB(2, 14) +#define MCHP_PCR_ACPI_EC0 MCHP_PCR_ERB(2, 13) +#define MCHP_PCR_GCFG MCHP_PCR_ERB(2, 12) +#define MCHP_PCR_UART1 MCHP_PCR_ERB(2, 2) +#define MCHP_PCR_UART0 MCHP_PCR_ERB(2, 1) +#define MCHP_PCR_EMI0 MCHP_PCR_ERB(2, 0) + +/* Command all blocks to sleep */ +#define MCHP_PCR_SLP_EN2_GLUE BIT(29) +#define MCHP_PCR_SLP_EN2_UART2 BIT(28) +#define MCHP_PCR_SLP_EN2_SAF BIT(27) +#define MCHP_PCR_SLP_EN2_P80CAP1 BIT(26) +#define MCHP_PCR_SLP_EN2_P80CAP0 BIT(25) +#define MCHP_PCR_SLP_EN2_ASIF BIT(24) +#define MCHP_PCR_SLP_EN2_ACPI_EC3 BIT(22) +#define MCHP_PCR_SLP_EN2_ACPI_EC2 BIT(21) +#define MCHP_PCR_SLP_EN2_ESPI_SCR BIT(20) +#define MCHP_PCR_SLP_EN2_ESPI BIT(19) +#define MCHP_PCR_SLP_EN2_RTC BIT(18) +#define MCHP_PCR_SLP_EN2_MAILBOX BIT(17) +#define MCHP_PCR_SLP_EN2_MIF8042 BIT(16) +#define MCHP_PCR_SLP_EN2_ACPI_PM1 BIT(15) +#define MCHP_PCR_SLP_EN2_ACPI_EC1 BIT(14) +#define MCHP_PCR_SLP_EN2_ACPI_EC0 BIT(13) +#define MCHP_PCR_SLP_EN2_GCFG BIT(12) +#define MCHP_PCR_SLP_EN2_UART1 BIT(2) +#define MCHP_PCR_SLP_EN2_UART0 BIT(1) +#define MCHP_PCR_SLP_EN2_EMI0 BIT(0) +/* all sleep enable 2 bits */ +#define MCHP_PCR_SLP_EN2_SLEEP 0xffffffff + +/* PCR Sleep 3: Sleep Enable, Clock Required, and Reset */ +#define MCHP_PCR_CCT0 MCHP_PCR_ERB(3, 30) +#define MCHP_PCR_HTMR1 MCHP_PCR_ERB(3, 29) +#define MCHP_PCR_AESHASH MCHP_PCR_ERB(3, 28) +#define MCHP_PCR_RNG MCHP_PCR_ERB(3, 27) +#define MCHP_PCR_PKE MCHP_PCR_ERB(3, 26) +#define MCHP_PCR_BTMR32_1 MCHP_PCR_ERB(3, 24) +#define MCHP_PCR_BTMR32_0 MCHP_PCR_ERB(3, 23) +#define MCHP_PCR_I2C4 MCHP_PCR_ERB(3, 20) +#define MCHP_PCR_LED2 MCHP_PCR_ERB(3, 18) +#define MCHP_PCR_LED1 MCHP_PCR_ERB(3, 17) +#define MCHP_PCR_LED0 MCHP_PCR_ERB(3, 16) +#define MCHP_PCR_I2C3 MCHP_PCR_ERB(3, 15) +#define MCHP_PCR_I2C2 MCHP_PCR_ERB(3, 14) +#define MCHP_PCR_I2C1 MCHP_PCR_ERB(3, 13) +#define MCHP_PCR_KEYSCAN MCHP_PCR_ERB(3, 11) +#define MCHP_PCR_HTMR0 MCHP_PCR_ERB(3, 10) +#define MCHP_PCR_PS2_1 MCHP_PCR_ERB(3, 6) +#define MCHP_PCR_PS2_0 MCHP_PCR_ERB(3, 5) +#define MCHP_PCR_ADC MCHP_PCR_ERB(3, 3) +#define MCHP_PCR_HDMI_CEC MCHP_PCR_ERB(3, 1) + +/* Command blocks to sleep */ +#define MCHP_PCR_SLP_EN3_CCT0 BIT(30) +#define MCHP_PCR_SLP_EN3_HTMR1 BIT(29) +#define MCHP_PCR_SLP_EN3_AESHASH BIT(28) +#define MCHP_PCR_SLP_EN3_RNG BIT(27) +#define MCHP_PCR_SLP_EN3_PKE BIT(26) +#define MCHP_PCR_SLP_EN3_BTMR32_1 BIT(24) +#define MCHP_PCR_SLP_EN3_BTMR32_0 BIT(23) +#define MCHP_PCR_SLP_EN3_I2C4 BIT(20) +#define MCHP_PCR_SLP_EN3_LED2 BIT(18) +#define MCHP_PCR_SLP_EN3_LED1 BIT(17) +#define MCHP_PCR_SLP_EN3_LED0 BIT(16) +#define MCHP_PCR_SLP_EN3_I2C3 BIT(15) +#define MCHP_PCR_SLP_EN3_I2C2 BIT(14) +#define MCHP_PCR_SLP_EN3_I2C1 BIT(13) +#define MCHP_PCR_SLP_EN3_KEYSCAN BIT(11) +#define MCHP_PCR_SLP_EN3_HTMR0 BIT(10) +#define MCHP_PCR_SLP_EN3_PS2_1 BIT(6) +#define MCHP_PCR_SLP_EN3_PS2_0 BIT(5) +#define MCHP_PCR_SLP_EN3_ADC BIT(3) +#define MCHP_PCR_SLP_EN3_HDMI_CEC BIT(1) +#define MCHP_PCR_SLP_EN3_ALL_CRYPTO (0x07 << 26) +/* all sleep enable 3 bits */ +#define MCHP_PCR_SLP_EN3_SLEEP 0xfffffffd +#define MCHP_PCR_SLP_EN3_PWM_ALL 0 + +/* PCR Sleep 4: Sleep Enable, Clock Required, Reset */ +#define MCHP_PCR_SGPIO3 MCHP_PCR_ERB(4, 20) +#define MCHP_PCR_SGPIO2 MCHP_PCR_ERB(4, 19) +#define MCHP_PCR_SGPIO1 MCHP_PCR_ERB(4, 18) +#define MCHP_PCR_SGPIO0 MCHP_PCR_ERB(4, 17) +#define MCHP_PCR_SLV_SPI MCHP_PCR_ERB(4, 16) +#define MCHP_PCR_PSPI MCHP_PCR_ERB(4, 14) +#define MCHP_PCR_PROCHOT MCHP_PCR_ERB(4, 13) +#define MCHP_PCR_I2C7 MCHP_PCR_ERB(4, 12) +#define MCHP_PCR_I2C6 MCHP_PCR_ERB(4, 11) +#define MCHP_PCR_I2C5 MCHP_PCR_ERB(4, 10) +#define MCHP_PCR_QMSPI MCHP_PCR_ERB(4, 8) +#define MCHP_PCR_RTMR MCHP_PCR_ERB(4, 6) + +/* Command blocks to sleep */ +#define MCHP_PCR_SLP_EN4_SGPIO3 BIT(20) +#define MCHP_PCR_SLP_EN4_SGPIO2 BIT(19) +#define MCHP_PCR_SLP_EN4_SGPIO1 BIT(18) +#define MCHP_PCR_SLP_EN4_SGPIO0 BIT(17) +#define MCHP_PCR_SLP_EN4_SLV_SPI BIT(16) +#define MCHP_PCR_SLP_EN4_PSPI BIT(14) +#define MCHP_PCR_SLP_EN4_PROCHOT BIT(13) +#define MCHP_PCR_SLP_EN4_I2C7 BIT(12) +#define MCHP_PCR_SLP_EN4_I2C6 BIT(11) +#define MCHP_PCR_SLP_EN4_I2C5 BIT(10) +#define MCHP_PCR_SLP_EN4_QMSPI BIT(8) +#define MCHP_PCR_SLP_EN4_RTMR BIT(6) +/* all sleep enable 4 bits */ +#define MCHP_PCR_SLP_EN4_SLEEP 0xffffffff +#define MCHP_PCR_SLP_EN4_PWM_ALL 0 + +/* Allow all blocks to request clocks */ +#define MCHP_PCR_SLP_EN0_WAKE (~(MCHP_PCR_SLP_EN0_SLEEP)) +#define MCHP_PCR_SLP_EN1_WAKE (~(MCHP_PCR_SLP_EN1_SLEEP)) +#define MCHP_PCR_SLP_EN2_WAKE (~(MCHP_PCR_SLP_EN2_SLEEP)) +#define MCHP_PCR_SLP_EN3_WAKE (~(MCHP_PCR_SLP_EN3_SLEEP)) +#define MCHP_PCR_SLP_EN4_WAKE (~(MCHP_PCR_SLP_EN4_SLEEP)) + +/* Bit defines for MCHP_PCR_PWR_RST_STS */ +#define MCHP_PWR_RST_STS_MASK_RO 0xc8c +#define MCHP_PWR_RST_STS_MASK_RWC 0x170 +#define MCHP_PWR_RST_STS_MASK \ + ((MCHP_PWR_RST_STS_MASK_RO) | (MCHP_PWR_RST_STS_MASK_RWC)) + +#define MCHP_PWR_RST_STS_ESPI_CLK_ACT BIT(11) /* RO */ +#define MCHP_PWR_RST_STS_32K_ACT BIT(10) /* RO */ +#define MCHP_PWR_RST_STS_WDT BIT(8) /* R/WC */ +#define MCHP_PWR_RST_STS_JTAG_RSTN BIT(7) /* RO */ +#define MCHP_PWR_RST_STS_SYS BIT(6) /* R/WC */ +#define MCHP_PWR_RST_STS_VBAT BIT(5) /* R/WC */ +#define MCHP_PWR_RST_STS_VTR BIT(4) /* R/WC */ +#define MCHP_PWR_RST_STS_HOST BIT(3) /* RO */ +#define MCHP_PWR_RST_STS_VCC_PWRGD BIT(2) /* RO */ + +/* Bit defines for MCHP_PCR_PWR_RST_CTL */ +#define MCHP_PCR_PWR_HOST_RST_SEL_BITPOS 8 +#define MCHP_PCR_PWR_HOST_RST_PCI_RESET BIT(8) +#define MCHP_PCR_PWR_HOST_RST_ESPI_PLTRST (0 << 8) +#define MCHP_PCR_PWR_OK_INV_BITPOS 0 + +/* Bit defines for MCHP_PCR_SYS_RST */ +#define MCHP_PCR_SYS_SOFT_RESET BIT(8) + +/* EC Subsystem */ +#define MCHP_EC_AHB_ERR REG32(MCHP_EC_BASE + 0x04) +#define MCHP_EC_ID_RO REG32(MCHP_EC_BASE + 0x10) +#define MCHP_EC_AHB_ERR_EN REG32(MCHP_EC_BASE + 0x14) +#define MCHP_EC_INT_CTRL REG32(MCHP_EC_BASE + 0x18) +#define MCHP_EC_TRACE_EN REG32(MCHP_EC_BASE + 0x1c) +#define MCHP_EC_JTAG_EN REG32(MCHP_EC_BASE + 0x20) +#define MCHP_EC_WDT_CNT REG32(MCHP_EC_BASE + 0x28) +#define MCHP_EC_AES_SHA_SWAP_CTRL REG8(MCHP_EC_BASE + 0x2c) +#define MCHP_EC_VCI_FW_OVRD REG8(MCHP_EC_BASE + 0x50) +#define MCHP_EC_CRYPTO_SRESET REG8(MCHP_EC_BASE + 0x5c) +#define MCHP_EC_GPIO_BANK_PWR REG8(MCHP_EC_BASE + 0x64) +#define MCHP_EC_SLP_STS_MIRROR REG8(MCHP_EC_BASE + 0x114) + +/* AHB ERR Enable bit[0]=0(enable), 1(disable) */ +#define MCHP_EC_AHB_ERROR_ENABLE 0 +#define MCHP_EC_AHB_ERROR_DISABLE 1 + +/* MCHP_EC_JTAG_EN bit definitions */ +#define MCHP_JTAG_ENABLE 0x01 +/* bits [2:1] */ +#define MCHP_JTAG_MODE_4PIN 0x00 +/* ARM 2-pin SWD plus 1-pin Serial Wire Viewer (ITM) */ +#define MCHP_JTAG_MODE_SWD_SWV 0x02 +/* ARM 2-pin SWD with no SWV */ +#define MCHP_JTAG_MODE_SWD 0x04 + +/* MCHP_EC_CRYPTO_SRESET bit definitions. Bits cleared by HW */ +#define MCHP_CRYPTO_NDRNG_SRST 0x01 +#define MCHP_CRYPTO_PKE_SRST 0x02 +#define MCHP_CRYPTO_AES_SHA_SRST 0x04 +#define MCHP_CRYPTO_ALL_SRST 0x07 + +/* MCHP_GPIO_BANK_PWR bit definitions */ +#define MCHP_EC_GPIO_BANK_PWR_MASK 0x86 +#define MCHP_EC_GPIO_BANK_PWR_VTR2_18 0x02 +#define MCHP_EC_GPIO_BANK_PWR_VTR3_18 0x04 +#define MCHP_EC_GPIO_BANK_PWR_LOCK 0x80 + +/* EC Interrupt aggregator (ECIA) */ +#define MCHP_INT_GIRQ_LEN 20 /* 5 32-bit registers */ +#define MCHP_INT_GIRQ_FIRST 8 +#define MCHP_INT_GIRQ_LAST 26 +#define MCHP_INT_GIRQ_NUM (26 - 8 + 1) +/* MCHP_INT_GIRQ_FIRST <= x <= MCHP_INT_GIRQ_LAST */ +#define MCHP_INTx_BASE(x) (MCHP_INT_BASE + (((x)-8) * MCHP_INT_GIRQ_LEN)) + +/* + * GPIO GIRQ's are not direct capable + * GIRQ08 GPIO 0140 - 0176 + * GIRQ09 GPIO 0100 - 0136 + * GIRQ10 GPIO 040 - 076 + * GIRQ11 GPIO 000 - 036 + * GIRQ12 GPIO 0200 - 0236 + * GIRQ26 GPIO 0240 - 0276 + * Other GIRQ's not direct capable: + * GIRQ22 wake peripheral clock only + * GIRQ24, GIRQ25 eSPI host to endpoint virtual wires + */ +#define MCHP_INT_AGGR_ONLY_BITMAP 0x07401F00U +#define MCHP_INT_DIRECT_CAPABLE_BITMAP 0x00BFE000U + +/* GIRQ13 I2C controllers. Direct capable */ +#define MCHP_INT13_I2C(x) (1ul << (x)) + +/* GIRQ14 DMA channels 0 - 11. Direct capable */ +#define MCHP_INT14_DMA(x) (1ul << (x)) + +/* GIQ15 interrupt sources. Direct capable */ +#define MCHP_INT15_UART_0 BIT(0) +#define MCHP_INT15_UART_1 BIT(1) +#define MCHP_INT15_UART_2 BIT(4) +#define MCHP_INT15_EMI_0 BIT(2) +#define MCHP_INT15_EMI_1 BIT(3) +#define MCHP_INT15_ACPI_EC0_IBF BIT(5) +#define MCHP_INT15_ACPI_EC0_OBE BIT(6) +#define MCHP_INT15_ACPI_EC1_IBF BIT(7) +#define MCHP_INT15_ACPI_EC1_OBE BIT(8) +#define MCHP_INT15_ACPI_EC2_IBF BIT(9) +#define MCHP_INT15_ACPI_EC2_OBE BIT(10) +#define MCHP_INT15_ACPI_EC3_IBF BIT(11) +#define MCHP_INT15_ACPI_EC3_OBE BIT(12) +#define MCHP_INT15_ACPI_PM1_CTL BIT(15) +#define MCHP_INT15_ACPI_PM1_EN BIT(16) +#define MCHP_INT15_ACPI_PM1_STS BIT(17) +#define MCHP_INT15_8042_OBE BIT(18) +#define MCHP_INT15_8042_IBF BIT(19) +#define MCHP_INT15_MAILBOX BIT(20) +#define MCHP_INT15_P80_0 BIT(22) +#define MCHP_INT15_P80_1 BIT(23) +#define MCHP_INT15_P80(x) BIT(22 + ((x)&0x01U)) + +/* GIRQ16 interrupt sources. Direct capable */ +#define MCHP_INT16_PKE_ERR BIT(0) +#define MCHP_INT16_PKE_DONE BIT(1) +#define MCHP_INT16_RNG_DONE BIT(2) +#define MCHP_INT16_AES_DONE BIT(3) +#define MCHP_INT16_HASH_DONE BIT(4) + +/* GIR17 interrupt sources. Direct capable */ +#define MCHP_INT17_PECI BIT(0) +#define MCHP_INT17_TACH_0 BIT(1) +#define MCHP_INT17_TACH_1 BIT(2) +#define MCHP_INT17_TACH_2 BIT(3) +#define MCHP_INT17_TACH_3 BIT(4) +#define MCHP_INT17_HDMI_CEC BIT(5) +#define MCHP_INT17_ADC_SINGLE BIT(8) +#define MCHP_INT17_ADC_REPEAT BIT(9) +#define MCHP_INT17_LED_WDT_0 BIT(13) +#define MCHP_INT17_LED_WDT_1 BIT(14) +#define MCHP_INT17_LED_WDT_2 BIT(15) +#define MCHP_INT17_PROCHOT BIT(17) + +/* GIRQ18 interrupt sources. Direct capable */ +#define MCHP_INT18_SLV_SPI BIT(0) +#define MCHP_INT18_QMSPI BIT(1) +#define MCHP_INT18_PS2_0 BIT(10) +#define MCHP_INT18_PS2_1 BIT(11) +#define MCHP_INT18_CCT BIT(20) +#define MCHP_INT18_CCT_CAP0 BIT(21) +#define MCHP_INT18_CCT_CAP1 BIT(22) +#define MCHP_INT18_CCT_CAP2 BIT(23) +#define MCHP_INT18_CCT_CAP3 BIT(24) +#define MCHP_INT18_CCT_CAP4 BIT(25) +#define MCHP_INT18_CCT_CAP6 BIT(26) +#define MCHP_INT18_CCT_CMP0 BIT(27) +#define MCHP_INT18_CCT_CMP1 BIT(28) + +/* GIRQ19 interrupt sources. Direct capable */ +#define MCHP_INT19_ESPI_PC BIT(0) +#define MCHP_INT19_ESPI_BM1 BIT(1) +#define MCHP_INT19_ESPI_BM2 BIT(2) +#define MCHP_INT19_ESPI_LTR BIT(3) +#define MCHP_INT19_ESPI_OOB_TX BIT(4) +#define MCHP_INT19_ESPI_OOB_RX BIT(5) +#define MCHP_INT19_ESPI_FC BIT(6) +#define MCHP_INT19_ESPI_RESET BIT(7) +#define MCHP_INT19_ESPI_VW_EN BIT(8) +#define MCHP_INT19_ESPI_SAF BIT(9) +#define MCHP_INT19_ESPI_SAF_ERR BIT(10) + +/* GIRQ20 interrupt sources. Direct capable */ +#define MCHP_INT20_OPT BIT(3) + +/* GIRQ21 interrupt sources. Direct capable */ +#define MCHP_INT21_WDT BIT(2) +#define MCHP_INT21_WEEK_ALARM BIT(3) +#define MCHP_INT21_WEEK_SUB BIT(4) +#define MCHP_INT21_WEEK_1SEC BIT(5) +#define MCHP_INT21_WEEK_1SEC_SUB BIT(6) +#define MCHP_INT21_WEEK_PWR_PRES BIT(7) +#define MCHP_INT21_RTC BIT(8) +#define MCHP_INT21_RTC_ALARM BIT(9) +#define MCHP_INT21_VCI_OVRD BIT(10) +#define MCHP_INT21_VCI_IN0 BIT(11) +#define MCHP_INT21_VCI_IN1 BIT(12) +#define MCHP_INT21_VCI_IN2 BIT(13) +#define MCHP_INT21_VCI_IN3 BIT(14) +#define MCHP_INT21_PS2_0A_WAKE BIT(18) +#define MCHP_INT21_PS2_0B_WAKE BIT(19) +#define MCHP_INT21_PS2_1B_WAKE BIT(21) +#define MCHP_INT21_KEYSCAN BIT(25) + +/* GIRQ22 peripheral wake only. GIRQ22 not connected to NVIC */ +#define MCHP_INT22_WAKE_ONLY_SLV_SPI BIT(0) +#define MCHP_INT22_WAKE_ONLY_I2C0 BIT(1) +#define MCHP_INT22_WAKE_ONLY_I2C1 BIT(2) +#define MCHP_INT22_WAKE_ONLY_I2C2 BIT(3) +#define MCHP_INT22_WAKE_ONLY_I2C3 BIT(4) +#define MCHP_INT22_WAKE_ONLY_I2C4 BIT(5) +#define MCHP_INT22_WAKE_ONLY_I2C5 BIT(6) +#define MCHP_INT22_WAKE_ONLY_I2C6 BIT(7) +#define MCHP_INT22_WAKE_ONLY_I2C7 BIT(8) +#define MCHP_INT22_WAKE_ONLY_ESPI BIT(9) + +/* GIRQ23 sources. Direct capable */ +#define MCHP_INT23_BTMR16_0 BIT(0) +#define MCHP_INT23_BTMR16_1 BIT(1) +#define MCHP_INT23_BTMR32_0 BIT(4) +#define MCHP_INT23_BTMR32_1 BIT(5) +#define MCHP_INT23_RTMR BIT(10) +#define MCHP_INT23_HTMR_0 BIT(16) +#define MCHP_INT23_HTMR_1 BIT(17) + +/* GIRQ24 sources. Master-to-Slave v=[0:6], Source=[0:3] */ +#define MCHP_INT24_MSVW_SRC(v, s) (1ul << ((4 * (v)) + (s))) + +/* GIRQ25 sources Master-to-Slave v=[7:10], Source=[0:3] */ +#define MCHP_INT25_MSVW_SRC(v, s) (1ul << ((4 * ((v)-7)) + (s))) + +/* UART Peripheral 0 <= x <= 2 */ +#define MCHP_UART_INSTANCES 3 +#define MCHP_UART_SPACING 0x400 +#define MCHP_UART_CFG_OFS 0x300 +#define MCHP_UART_CONFIG_BASE(x) \ + (MCHP_UART0_BASE + MCHP_UART_CFG_OFS + ((x)*MCHP_UART_SPACING)) +#define MCHP_UART_RUNTIME_BASE(x) (MCHP_UART0_BASE + ((x)*MCHP_UART_SPACING)) +#define MCHP_UART_GIRQ 15 +#define MCHP_UART0_GIRQ_BIT (MCHP_INT15_UART_0) +#define MCHP_UART1_GIRQ_BIT (MCHP_INT15_UART_1) +#define MCHP_UART2_GIRQ_BIT (MCHP_INT15_UART_2) +#define MCHP_UART_GIRQ_BIT(x) BIT(x) +/* BIT defines for MCHP_UARTx_LSR */ +#define MCHP_LSR_TX_EMPTY BIT(5) + +/* + * GPIO + * MCHP each Port contains 32 GPIO's. + * GPIO Control 1 registers are 32-bit registers starting at + * MCHP_GPIO_BASE. + * index = octal GPIO number from MCHP specification. + * port/bank = index >> 5 + * id = index & 0x1F + * + * The port/bank, id pair may also be used to access GPIO's via + * parallel I/O registers if GPIO control is configured for + * parallel I/O. + * + * From ec/chip/mec1701/config_chip.h + * #define GPIO_PIN(index) ((index) >> 5), ((index) & 0x1F) + * + * GPIO Control 1 Address = 0x40081000 + (((bank << 5) + id) << 2) + * + * Example: GPIO043, Control 1 register address = 0x4008108c + * port/bank = 0x23 >> 5 = 1 + * id = 0x23 & 0x1F = 0x03 + * Control 1 Address = 0x40081000 + ((BIT(5) + 0x03) << 2) = 0x4008108c + * + * Example: GPIO235, Control 1 register address = 0x40081274 + * port/bank = 0x9d >> 5 = 4 + * id = 0x9d & 0x1f = 0x1d + * Control 1 Address = 0x40081000 + (((4 << 5) + 0x1d) << 2) = 0x40081274 + */ +#define MCHP_GPIO_CTL(port, id) \ + REG32(MCHP_GPIO_BASE + (((port << 5) + id) << 2)) + +/* MCHP implements 6 GPIO ports */ +#define MCHP_GPIO_MAX_PORT 6 +#define UNIMPLEMENTED_GPIO_BANK MCHP_GPIO_MAX_PORT + +/* + * In MECxxxx documentation GPIO numbers are octal, each control + * register is located on a 32-bit boundary. + */ +#define MCHP_GPIO_CTRL(gpio_num) REG32(MCHP_GPIO_BASE + ((gpio_num) << 2)) + +/* + * GPIO control register bit fields + */ +#define MCHP_GPIO_CTRL_PUD_BITPOS 0 +#define MCHP_GPIO_CTRL_PUD_MASK0 0x03 +#define MCHP_GPIO_CTRL_PUD_MASK 0x03 +#define MCHP_GPIO_CTRL_PUD_NONE 0x00 +#define MCHP_GPIO_CTRL_PUD_PU 0x01 +#define MCHP_GPIO_CTRL_PUD_PD 0x02 +#define MCHP_GPIO_CTRL_PUD_KEEPER 0x03 +#define MCHP_GPIO_CTRL_PWR_BITPOS 2 +#define MCHP_GPIO_CTRL_PWR_MASK0 0x03 +#define MCHP_GPIO_CTRL_PWR_MASK (0x03 << 2) +#define MCHP_GPIO_CTRL_PWR_VTR (0x00 << 2) +#define MCHP_GPIO_CTRL_PWR_OFF (0x02 << 2) +#define MCHP_GPIO_INTDET_MASK 0xF0 +#define MCHP_GPIO_INTDET_LVL_LO 0x00 +#define MCHP_GPIO_INTDET_LVL_HI 0x10 +#define MCHP_GPIO_INTDET_DISABLED 0x40 +#define MCHP_GPIO_INTDET_EDGE_RIS 0xD0 +#define MCHP_GPIO_INTDET_EDGE_FALL 0xE0 +#define MCHP_GPIO_INTDET_EDGE_BOTH 0xF0 +#define MCHP_GPIO_INTDET_EDGE_EN BIT(7) +#define MCHP_GPIO_PUSH_PULL 0u +#define MCHP_GPIO_OPEN_DRAIN BIT(8) +#define MCHP_GPIO_INPUT 0u +#define MCHP_GPIO_OUTPUT BIT(9) +#define MCHP_GPIO_OUTSET_CTRL 0u +#define MCHP_GPIO_OUTSEL_PAR BIT(10) +#define MCHP_GPIO_POLARITY_NINV 0u +#define MCHP_GPIO_POLARITY_INV BIT(11) +#define MCHP_GPIO_CTRL_ALT_FUNC_BITPOS 12 +#define MCHP_GPIO_CTRL_ALT_FUNC_MASK0 0x0F +#define MCHP_GPIO_CTRL_ALT_FUNC_MASK (0x0F << 12) +#define MCHP_GPIO_CTRL_FUNC_GPIO (0 << 12) +#define MCHP_GPIO_CTRL_FUNC_1 (1 << 12) +#define MCHP_GPIO_CTRL_FUNC_2 (2 << 12) +#define MCHP_GPIO_CTRL_FUNC_3 (3 << 12) +#define MCHP_GPIO_CTRL_OUT_LVL BIT(16) +/* MEC15xx only */ +#define MCHP_GPIO_CTRL_DIS_INPUT_BITPOS 15 +#define MCHP_GPIO_CTRL_DIS_INPUT_BIT BIT(15) + +/* + * GPIO Parallel Input and Output registers. + * gpio_bank in [0, 5] + */ +#define MCHP_GPIO_PARIN(bank) REG32(MCHP_GPIO_BASE + 0x0300 + ((bank) << 2)) +#define MCHP_GPIO_PAROUT(bank) REG32(MCHP_GPIO_BASE + 0x0380 + ((bank) << 2)) + +/* Basic timers */ +#define MCHP_TMR_SPACING 0x20 +#define MCHP_TMR16_INSTANCES 2 +#define MCHP_TMR32_INSTANCES 2 +#define MCHP_TMR16_MAX (MCHP_TMR16_INSTANCES) +#define MCHP_TMR32_MAX (MCHP_TMR32_INSTANCES) +#define MCHP_TMR16_BASE(n) (MCHP_TMR16_0_BASE + (n)*MCHP_TMR_SPACING) +#define MCHP_TMR32_BASE(n) (MCHP_TMR32_0_BASE + (n)*MCHP_TMR_SPACING) +#define MCHP_TMR16_GIRQ 23 +#define MCHP_TMR16_GIRQ_BIT(n) BIT(0 + (n)) +#define MCHP_TMR32_GIRQ 23 +#define MCHP_TMR32_GIRQ_BIT(n) BIT(4 + (n)) + +/* RTimer */ +#define MCHP_RTMR_GIRQ 23 +#define MCHP_RTMR_GIRQ_BIT(x) BIT(10) + +/* Watchdog */ +/* MEC152x specific registers */ +#define MCHP_WDG_STATUS REG32(MCHP_WDG_BASE + 0x10) +#define MCHP_WDG_IEN REG32(MCHP_WDG_BASE + 0x14) +/* Status */ +#define MCHP_WDG_STS_IRQ BIT(0) +/* Interrupt enable */ +#define MCHP_WDG_IEN_IRQ_EN BIT(0) +#define MCHP_WDG_GIRQ 21 +#define MCHP_WDG_GIRQ_BIT BIT(2) +/* Control register has a bit to enable IRQ generation */ +#define MCHP_WDG_RESET_IRQ_EN BIT(9) + +/* VBAT */ +#define MCHP_VBAT_STS REG32(MCHP_VBAT_BASE + 0x0) +#define MCHP_VBAT_CE REG32(MCHP_VBAT_BASE + 0x8) +#define MCHP_VBAT_SHDN_DIS REG32(MCHP_VBAT_BASE + 0xC) +#define MCHP_VBAT_MONOTONIC_CTR_LO REG32(MCHP_VBAT_BASE + 0x20) +#define MCHP_VBAT_MONOTONIC_CTR_HI REG32(MCHP_VBAT_BASE + 0x24) +/* read 32-bit word at 32-bit offset x where 0 <= x <= 16 */ +#define MCHP_VBAT_RAM_SIZE 64 +#define MCHP_VBAT_RAM(wnum) REG32(MCHP_VBAT_RAM_BASE + ((wnum)*4)) +#define MCHP_VBAT_RAM8(bnum) REG8(MCHP_VBAT_RAM_BASE + (bnum)) +#define MCHP_VBAT_VWIRE_BACKUP 14 +/* + * Miscellaneous firmware control fields + * scratch pad index cannot be more than 32 as + * MEC152x has 64 bytes = 16 words of scratch pad RAM + */ +#define MCHP_IMAGETYPE_IDX 15 + +/* Bit definition for MCHP_VBAT_STS */ +#define MCHP_VBAT_STS_SOFTRESET BIT(2) +#define MCHP_VBAT_STS_RESETI BIT(4) +#define MCHP_VBAT_STS_WDT BIT(5) +#define MCHP_VBAT_STS_SYSRESETREQ BIT(6) +#define MCHP_VBAT_STS_VBAT_RST BIT(7) +#define MCHP_VBAT_STS_ANY_RST 0xF4u + +/* Bit definitions for MCHP_VBAT_CE */ +#define MCHP_VBAT_CE_XOSEL_BITPOS 3 +#define MCHP_VBAT_CE_XOSEL_MASK BIT(3) +#define MCHP_VBAT_CE_XOSEL_PAR 0 +#define MCHP_VBAT_CE_XOSEL_SE BIT(3) + +#define MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_BITPOS 2 +#define MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_MASK BIT(2) +#define MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_INT 0 +#define MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_CRYSTAL BIT(2) + +#define MCHP_VBAT_CE_32K_DOMAIN_SRC_BITPOS 1 +#define MCHP_VBAT_CE_32K_DOMAIN_SRC_MASK BIT(1) +#define MCHP_VBAT_CE_32K_DOMAIN_ALWAYS_ON 0 +#define MCHP_VBAT_CE_32K_DOMAIN_32KHZ_IN_PIN BIT(1) + +/* Blinking-Breathing LED 0 <= n <= 2 */ +#define MCHP_BBLEB_INSTANCES 3 +#define MCHP_BBLED_BASE(n) (MCHP_BBLED_0_BASE + (((n)&0x03) * 256)) + +/* EMI */ +#define MCHP_EMI_INSTANCES 2 +#define MCHP_EMI_SPACING 0x400 +#define MCHP_EMI_ECREG_OFS 0x100 +/* base of EMI registers only accessible by EC */ +#define MCHP_EMI_BASE(n) \ + (MCHP_EMI_0_BASE + MCHP_EMI_ECREG_OFS + ((n)*MCHP_EMI_SPACING)) +/* base of EMI registers accessible by EC and Host */ +#define MCHP_EMI_RT_BASE(n) (MCHP_EMI_0_BASE + ((n)*MCHP_EMI_SPACING)) +#define MCHP_EMI_GIRQ 15 +#define MCHP_EMI_GIRQ_BIT(n) BIT(2 + (n)) + +/* Mailbox */ +#define MCHP_MBX_ECREGS_OFS 0x100 +#define MCHP_MBX_RT_BASE MCHP_MBOX_BASE +#define MCHP_MBX_BASE (MCHP_MBOX_BASE + MCHP_MBX_ECREGS_OFS) +#define MCHP_MBX_GIRQ 15 +#define MCHP_MBX_GIRQ_BIT BIT(20) + +/* Port 80 Capture */ +#define MCHP_P80_SPACING 0x400 +#define MCHP_P80_BASE(n) (MCHP_P80CAP0_BASE + ((n) * (MCHP_P80_SPACING))) +#define MCHP_P80_HOST_DATA(n) REG8(MCHP_P80_BASE(n)) +/* Data capture with time stamp register */ +#define MCHP_P80_CAP(n) REG32(MCHP_P80_BASE(n) + 0x100) +#define MCHP_P80_CFG(n) REG8(MCHP_P80_BASE(n) + 0x104) +#define MCHP_P80_STS(n) REG8(MCHP_P80_BASE(n) + 0x108) +#define MCHP_P80_CNT(n) REG32(MCHP_P80_BASE(n) + 0x10c) +#define MCHP_P80_CNT_GET(n) (REG32(MCHP_P80_BASE(n) + 0x10c) >> 8) +#define MCHP_P80_CNT_SET(n, c) (REG32(MCHP_P80_BASE(n) + 0x10c) = ((c) << 8)) +#define MCHP_P80_ACTIVATE(n) REG8(MCHP_P80_BASE(n) + 0x330) +#define MCHP_P80_GIRQ 15 +#define MCHP_P80_GIRQ_BIT(n) BIT(22 + (n)) +/* + * Port 80 Data register bits + * bits[7:0] = data captured on Host write + * bits[31:8] = optional time stamp + */ +#define MCHP_P80_CAP_DATA_MASK 0xFFul +#define MCHP_P80_CAP_TS_BITPOS 8 +#define MCHP_P80_CAP_TS_MASK0 0xfffffful +#define MCHP_P80_CAP_TS_MASK \ + ((MCHP_P80_CAP_TS_MASK0) << (MCHP_P80_CAP_TS_BITPOS)) + +/* Port 80 Configuration register bits */ +#define MCHP_P80_FLUSH_FIFO_WO BIT(1) +#define MCHP_P80_RESET_TIMESTAMP_WO BIT(2) +#define MCHP_P80_TIMEBASE_BITPOS 3 +#define MCHP_P80_TIMEBASE_MASK0 0x03 +#define MCHP_P80_TIMEBASE_MASK \ + ((MCHP_P80_TIMEBASE_MASK0) << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMEBASE_750KHZ (0x03 << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMEBASE_1500KHZ (0x02 << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMEBASE_3MHZ (0x01 << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMEBASE_6MHZ (0x00 << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMER_ENABLE BIT(5) +#define MCHP_P80_FIFO_THRHOLD_MASK (3u << 6) +#define MCHP_P80_FIFO_THRHOLD_1 0u +#define MCHP_P80_FIFO_THRHOLD_4 (1u << 6) +#define MCHP_P80_FIFO_THRHOLD_8 (2u << 6) +#define MCHP_P80_FIFO_THRHOLD_14 (3u << 6) +#define MCHP_P80_FIFO_LEN 16 +/* Port 80 Status register bits, read-only */ +#define MCHP_P80_STS_NOT_EMPTY BIT(0) +#define MCHP_P80_STS_OVERRUN BIT(1) +/* Port 80 Count register bits */ +#define MCHP_P80_CNT_BITPOS 8 +#define MCHP_P80_CNT_MASK0 0xfffffful +#define MCHP_P80_CNT_MASK ((MCHP_P80_CNT_MASK0) << (MCHP_P80_CNT_BITPOS)) + +/* PWM */ +#define MCHP_PWM_INSTANCES 9 +#define MCHP_PWM_ID_MAX (MCHP_PWM_INSTANCES) +#define MCHP_PWM_SPACING 16 +#define MCHP_PWM_BASE(x) (MCHP_PWM_0_BASE + ((x)*MCHP_PWM_SPACING)) + +/* TACH */ +#define MCHP_TACH_INSTANCES 4 +#define MCHP_TACH_SPACING 16 +#define MCHP_TACH_BASE(x) (MCHP_TACH_0_BASE + ((x)*MCHP_TACH_SPACING)) +#define MCHP_TACH_GIRQ 17 +#define MCHP_TACH_GIRQ_BIT(x) BIT(1 + (x)) + +/* ACPI EC */ +#define MCHP_ACPI_EC_INSTANCES 4 +#define MCHP_ACPI_EC_MAX (ACPI_EC_INSTANCES) +#define MCHP_ACPI_EC_SPACING 0x400 +#define MCHP_ACPI_EC_BASE(x) (MCHP_ACPI_EC_0_BASE + ((x)*MCHP_ACPI_EC_SPACING)) +#define MCHP_ACPI_EC_GIRQ 15 +#define MCHP_ACPI_EC_IBF_GIRQ_BIT(x) BIT(5 + ((x)*2)) +#define MCHP_ACPI_EC_OBE_GIRQ_BIT(x) BIT(6 + ((x)*2)) + +/* ACPI PM1 */ +#define MCHP_ACPI_PM1_ECREGS_OFS 0x100 +#define MCHP_ACPI_PM_RT_BASE MCHP_ACPI_PM1_BASE +#define MCHP_ACPI_PM_EC_BASE (MCHP_ACPI_PM1_BASE + MCHP_ACPI_PM1_ECREGS_OFS) +#define MCHP_ACPI_PM1_CTL_GIRQ_BIT BIT(15) +#define MCHP_ACPI_PM1_EN_GIRQ_BIT BIT(16) +#define MCHP_ACPI_PM1_STS_GIRQ_BIT BIT(17) + +/* 8042 */ +#define MCHP_8042_ECREGS_OFS 0x100 +#define MCHP_8042_GIRQ 15 +#define MCHP_8042_OBE_GIRQ_BIT BIT(18) +#define MCHP_8042_IBF_GIRQ_BIT BIT(19) + +/* + * I2C controllers 0 - 4 include SMBus network layer functionality. + * I2C controllers 5 - 7 are I2C only and include slave mode + * promiscuous functionality. + */ +#define MCHP_I2C_CTRL0 0 +#define MCHP_I2C_CTRL1 1 +#define MCHP_I2C_CTRL2 2 +#define MCHP_I2C_CTRL3 3 +#define MCHP_I2C_CTRL4 4 +#define MCHP_I2C_CTRL5 5 +#define MCHP_I2C_CTRL6 6 +#define MCHP_I2C_CTRL7 7 +#define MCHP_I2C_CTRL_MAX 8 + +#define MCHP_I2C_SEP0 0x400 +#define MCHP_I2C_SEP1 0x100 + +/* + * MEC152xH 144-pin package has eight I2C controllers and sixteen ports. + * Any port can be mapped to any I2C controller. + * + * I2C port values must be zero based consecutive whole numbers due to + * port number used as an index for I2C mutex array, etc. + * + * Refer to chip i2c_port_to_controller function for mapping + * of port to controller. + * + * Locking must occur by-controller (not by-port). + * I2C00_SCL/SDA on GPIO004 F1, GPIO003 F1 + * I2C01_SCL/SDA on GPIO0131 F1, GPIO130 F1 + * Alternate pins: GPIO073 F2, GPIO072 F2 + * I2C02_SCL/SDA on GPIO0155 F1, GPIO0154 F1 + * I2C03_SCL/SDA on GPIO010 F1, GPIO007 F1 + * I2C04_SCL/SDA on GPIO0144 F1, GPIO0143 F1 + * I2C05_SCL/SDA on GPIO0142 F1, GPIO0141 F1 + * I2C06_SCL/SDA on GPIO0140 F1, GPIO0132 F1 + * I2C07_SCL/SDA on GPIO013 F1, GPIO012 F1 + * Alternate pins: GPIO0024 F3, GPIO0152 F3 + * I2C08_SCL/SDA on GPIO012 F1, GPIO0211 F1 + * I2C09_SCL/SDA on GPIO0146 F1, GPIO0145 F1 + * I2C10_SCL/SDA on GPIO0107 F3, GPIO030 F2 + * I2C11_SCL/SDA on GPIO062 F2, GPIO000 F3 + * I2C12_SCL/SDA on GPIO027 F3, GPIO026 F3 + * I2C13_SCL/SDA on GPIO065 F2, GPIO066 F2 + * I2C14_SCL/SDA on GPIO071 F2, GPIO070 F2 + * I2C15_SCL/SDA on GPIO0150 F1, GPIO0147 F1 + */ + +#define MCHP_MEC1521SZ_I2C_PORT_MASK 0xFEFFul +#define MCHP_MEC1523SZ_I2C_PORT_MASK 0xFFFFul + +#define MCHP_I2C_PORT_MASK MCHP_MEC1521SZ_I2C_PORT_MASK + +enum MCHP_i2c_port { + MCHP_I2C_PORT0 = 0, + MCHP_I2C_PORT1, + MCHP_I2C_PORT2, + MCHP_I2C_PORT3, + MCHP_I2C_PORT4, + MCHP_I2C_PORT5, + MCHP_I2C_PORT6, + MCHP_I2C_PORT7, + MCHP_I2C_PORT8, + MCHP_I2C_PORT9, + MCHP_I2C_PORT10, + MCHP_I2C_PORT11, + MCHP_I2C_PORT12, + MCHP_I2C_PORT13, + MCHP_I2C_PORT14, + MCHP_I2C_PORT15, + MCHP_I2C_PORT_COUNT, +}; + +/* I2C ports & Configs */ +#define I2C_CONTROLLER_COUNT MCHP_I2C_CTRL_MAX +#define I2C_PORT_COUNT MCHP_I2C_PORT_COUNT + +/* + * I2C controllers 0-4 implement network layer hardware. + * I2C controllers 5-7 do include network layer hardware. + * MEC152x has I2C promiscuous mode feature in the following + * additional registers. + */ +#define MCHP_I2C_SLAVE_ADDR(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x6c)) +#define MCHP_I2C_PROM_INTR(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x70)) +#define MCHP_I2C_PROM_INTR_EN(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x74)) +#define MCHP_I2C_PROM_CTRL(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x78)) + +/* All I2C controllers connected to GIRQ13 */ +#define MCHP_I2C_GIRQ 13 +/* I2C[0:7] -> GIRQ13 bits[0:7] */ +#define MCHP_I2C_GIRQ_BIT(n) BIT((n)) + +/* Keyboard scan matrix */ +#define MCHP_KS_GIRQ 21 +#define MCHP_KS_GIRQ_BIT BIT(25) +#define MCHP_KS_DIRECT_NVIC 135 + +/* ADC */ +#define MCHP_ADC_GIRQ 17 +#define MCHP_ADC_GIRQ_SINGLE_BIT BIT(8) +#define MCHP_ADC_GIRQ_REPEAT_BIT BIT(9) +#define MCHP_ADC_SINGLE_DIRECT_NVIC 78 +#define MCHP_ADC_REPEAT_DIRECT_NVIC 79 + +/* Hibernation timer */ +#define MCHP_HTIMER_SPACING 0x20 +#define MCHP_HTIMER_ADDR(n) (MCHP_HTIMER_BASE + ((n)*MCHP_HTIMER_SPACING)) +#define MCHP_HTIMER_GIRQ 23 +/* HTIMER[0:1] -> GIRQ23 bits[16:17] */ +#define MCHP_HTIMER_GIRQ_BIT(n) BIT(16 + (n)) +#define MCHP_HTIMER_DIRECT_NVIC(n) (112 + (n)) + +/* + * Quad Master SPI (QMSPI) + * MEC152x implements 16 descriptors, support for two chip selects, + * and additional SPI signal timing registers. + */ +#define MCHP_QMSPI_MAX_DESCR 16 +/* + * Chip select implemented in bit[13:12] of the Mode register. + * These bits are reserved in earlier chips. + */ +#define MCHP_QMSPI_M_CS_POS 12 +#define MCHP_QMSPI_M_CS_MASK0 0x03 +#define MCHP_QMSPI_M_CS_MASK (0x03 << MCHP_QMSPI_M_CS_POS) +#define MCHP_QMSPI_M_CS0 (0x00 << MCHP_QMSPI_M_CS_POS) +#define MCHP_QMSPI_M_CS1 (0x01 << MCHP_QMSPI_M_CS_POS) + +/* New QMSPI chip select timing register */ +#define MCHP_QMSPI_CS_TIMING REG32(MCHP_QMSPI0_BASE + 0x28) +#define MCHP_QMSPI_CST_DFLT_VAL 0x06060406 +#define MCHP_QMSPI_CST_ON2CLK_MASK 0x0f +#define MCHP_QMSPI_CST_ON2CLK_DFLT 0x06 +#define MCHP_QMSPI_CST_DLY_CLK2OFF_POS 8 +#define MCHP_QMSPI_CST_DLY_CLK2OFF_MASK0 0x0f +#define MCHP_QMSPI_CST_DLY_CLK2OFF_MASK 0x0f00 +#define MCHP_QMSPI_CST_DLY_CLK2OFF_DFLT 0x0400 +#define MCHP_QMSPI_CST_DLY_LDH_POS 16 +#define MCHP_QMSPI_CST_DLY_LDH_MASK0 0x0f +#define MCHP_QMSPI_CST_DLY_LDH_MASK 0xf0000 +#define MCHP_QMSPI_CST_DLY_LDH_DFLT 0x60000 +#define MCHP_QMSPI_CST_DLY_OFF2ON_POS 24 +#define MCHP_QMSPI_CST_DLY_OFF2ON_DFLT 0x06000000 +#define MCHP_QMSPI_CST_DLY_OFF2ON_MASK0 0xff +#define MCHP_QMSPI_CST_DLY_OFF2ON_MASK 0xff000000 + +#define MCHP_QMSPI_GIRQ 18 +#define MCHP_QMSPI_GIRQ_BIT BIT(1) +#define MCHP_QMSPI_DIRECT_NVIC 91 + +/* eSPI */ + +/* IO BAR defines. Use with MCHP_ESPI_IO_BAR_xxxx macros */ +#define MCHP_ESPI_IO_BAR_ID_CFG_PORT 0 +#define MCHP_ESPI_IO_BAR_ID_MEM_CMPNT 1 +#define MCHP_ESPI_IO_BAR_ID_MAILBOX 2 +#define MCHP_ESPI_IO_BAR_ID_8042 3 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC0 4 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC1 5 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC2 6 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC3 7 +#define MCHP_ESPI_IO_BAR_ID_ACPI_PM1 9 +#define MCHP_ESPI_IO_BAR_ID_P92 0xA +#define MCHP_ESPI_IO_BAR_ID_UART0 0xB +#define MCHP_ESPI_IO_BAR_ID_UART1 0xC +#define MCHP_ESPI_IO_BAR_ID_EMI0 0xD +#define MCHP_ESPI_IO_BAR_ID_EMI1 0xE +#define MCHP_ESPI_IO_BAR_P80_0 0x10 +#define MCHP_ESPI_IO_BAR_P80_1 0x11 +#define MCHP_ESPI_IO_BAR_RTC 0x12 +#define MCHP_ESPI_IO_BAR_ID_UART2 0x15 + +/* Use with MCHP_ESPI_MBAR_EC_xxxx(x) macros */ +#define MCHP_ESPI_MBAR_ID_MBOX 0 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_0 1 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_1 2 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_2 3 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_3 4 +#define MCHP_ESPI_MBAR_ID_EMI_0 6 +#define MCHP_ESPI_MBAR_ID_EMI_1 7 + +/* Use with MCHP_ESPI_IO_SERIRQ_REG(x) */ +#define MCHP_ESPI_SIRQ_MBOX 0 /* Host SIRQ */ +#define MCHP_ESPI_SIRQ_MBOX_SMI 1 /* Host SMI */ +#define MCHP_ESPI_SIRQ_8042_KB 2 /* KIRQ */ +#define MCHP_ESPI_SIRQ_8042_MS 3 /* MIRQ */ +#define MCHP_ESPI_SIRQ_ACPI_EC0_OBF 4 +#define MCHP_ESPI_SIRQ_ACPI_EC1_OBF 5 +#define MCHP_ESPI_SIRQ_ACPI_EC2_OBF 6 +#define MCHP_ESPI_SIRQ_ACPI_EC3_OBF 7 +#define MCHP_ESPI_SIRQ_UART0 9 +#define MCHP_ESPI_SIRQ_UART1 10 +#define MCHP_ESPI_SIRQ_EMI0_HEV 11 /* Host Event */ +#define MCHP_ESPI_SIRQ_EMI0_EC2H 12 /* EC to Host */ +#define MCHP_ESPI_SIRQ_EMI1_HEV 13 +#define MCHP_ESPI_SIRQ_EMI1_EC2H 14 +#define MCHP_ESPI_SIRQ_RTC 17 +#define MCHP_ESPI_SIRQ_EC 18 +#define MCHP_ESPI_SIRQ_UART2 19 + +#define MCHP_ESPI_MSVW_BASE (MCHP_ESPI_VW_BASE) +#define MCHP_ESPI_SMVW_BASE ((MCHP_ESPI_VW_BASE) + 0x200ul) + +/* + * eSPI RESET, channel enables and operations except Master-to-Slave + * WWires are all on GIRQ19 + */ +#define MCHP_ESPI_GIRQ 19 +#define MCHP_ESPI_PC_GIRQ_BIT BIT(0) +#define MCHP_ESPI_BM1_GIRQ_BIT BIT(1) +#define MCHP_ESPI_BM2_GIRQ_BIT BIT(2) +#define MCHP_ESPI_LTR_GIRQ_BIT BIT(3) +#define MCHP_ESPI_OOB_TX_GIRQ_BIT BIT(4) +#define MCHP_ESPI_OOB_RX_GIRQ_BIT BIT(5) +#define MCHP_ESPI_FC_GIRQ_BIT BIT(6) +#define MCHP_ESPI_RESET_GIRQ_BIT BIT(7) +#define MCHP_ESPI_VW_EN_GIRQ_BIT BIT(8) +#define MCHP_ESPI_SAF_DONE_GIRQ_BIT BIT(9) +#define MCHP_ESPI_SAF_ERR_GIRQ_BIT BIT(10) + +/* + * eSPI Master-to-Slave WWire interrupts are on GIRQ24 and GIRQ25 + */ +#define MCHP_ESPI_MSVW_0_6_GIRQ 24 +#define MCHP_ESPI_MSVW_7_10_GIRQ 25 +/* + * Four source bits, SRC[0:3] per Master-to-Slave register + * v = MSVW [0:10] + * n = VWire SRC bit = [0:3] + */ +#define MCHP_ESPI_MSVW_GIRQ(v) (24 + ((v) > 6 ? 1 : 0)) + +#define MCHP_ESPI_MSVW_SRC_GIRQ_BIT(v, n) \ + (((v) > 6) ? (1ul << (((v)-7) + (n))) : (1ul << ((v) + (n)))) + +/* DMA */ +#define MCHP_DMA_MAX_CHAN 12 +#define MCHP_DMA_CH_OFS 0x40 +#define MCHP_DMA_CH_OFS_BITPOS 6 +#define MCHP_DMA_CH_BASE (MCHP_DMA_BASE + MCHP_DMA_CH_OFS) + +/* + * Available DMA channels. + * On MCHP, any DMA channel may serve any device. Since we have + * 12 channels and 12 devices request signals, we make each channel + * dedicated to the device of the same number. + */ +enum dma_channel { + /* Channel numbers */ + MCHP_DMAC_I2C0_SLAVE = 0, + MCHP_DMAC_I2C0_MASTER, + MCHP_DMAC_I2C1_SLAVE, + MCHP_DMAC_I2C1_MASTER, + MCHP_DMAC_I2C2_SLAVE, + MCHP_DMAC_I2C2_MASTER, + MCHP_DMAC_I2C3_SLAVE, + MCHP_DMAC_I2C3_MASTER, + MCHP_DMAC_I2C4_SLAVE, + MCHP_DMAC_I2C4_MASTER, + MCHP_DMAC_QMSPI0_TX, + MCHP_DMAC_QMSPI0_RX, + /* Channel count */ + MCHP_DMAC_COUNT, +}; + +/* + * Peripheral device DMA Device ID's for bits [15:9] + * in DMA channel control register. + */ +#define MCHP_DMA_I2C0_SLV_REQ_ID 0 +#define MCHP_DMA_I2C0_MTR_REQ_ID 1 +#define MCHP_DMA_I2C1_SLV_REQ_ID 2 +#define MCHP_DMA_I2C1_MTR_REQ_ID 3 +#define MCHP_DMA_I2C2_SLV_REQ_ID 4 +#define MCHP_DMA_I2C2_MTR_REQ_ID 5 +#define MCHP_DMA_I2C3_SLV_REQ_ID 6 +#define MCHP_DMA_I2C3_MTR_REQ_ID 7 +#define MCHP_DMA_I2C4_SLV_REQ_ID 8 +#define MCHP_DMA_I2C4_MTR_REQ_ID 9 +#define MCHP_DMA_QMSPI0_TX_REQ_ID 10 +#define MCHP_DMA_QMSPI0_RX_REQ_ID 11 + +/* + * Hardware delay register. + * Write of 0 <= n <= 31 will stall the Cortex-M4 + * for n+1 microseconds. Interrupts will not be + * serviced during the delay period. Reads have + * no effect. + */ +#define MCHP_USEC_DELAY_REG_ADDR 0x10000000 +#define MCHP_USEC_DELAY(x) (REG8(MCHP_USEC_DELAY_REG_ADDR) = (x)) + +#endif /* #ifndef __ASSEMBLER__ */ diff --git a/chip/mchp/registers-mec1701.h b/chip/mchp/registers-mec1701.h new file mode 100644 index 0000000000..6894dc4056 --- /dev/null +++ b/chip/mchp/registers-mec1701.h @@ -0,0 +1,1334 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Register map for Microchip MEC170x family controllers + */ + +#ifndef __CROS_EC_REGISTERS_H +#error "This header file should not be included directly." +#endif + +/* + * IRQ Numbers + * NOTE: GIRQ22 aggregated output and its sources are not connected to + * the NVIC. + */ +#define MCHP_IRQ_GIRQ8 0 +#define MCHP_IRQ_GIRQ9 1 +#define MCHP_IRQ_GIRQ10 2 +#define MCHP_IRQ_GIRQ11 3 +#define MCHP_IRQ_GIRQ12 4 +#define MCHP_IRQ_GIRQ13 5 +#define MCHP_IRQ_GIRQ14 6 +#define MCHP_IRQ_GIRQ15 7 +#define MCHP_IRQ_GIRQ16 8 +#define MCHP_IRQ_GIRQ17 9 +#define MCHP_IRQ_GIRQ18 10 +#define MCHP_IRQ_GIRQ19 11 +#define MCHP_IRQ_GIRQ20 12 +#define MCHP_IRQ_GIRQ21 13 +#define MCHP_IRQ_GIRQ23 14 +#define MCHP_IRQ_GIRQ24 15 +#define MCHP_IRQ_GIRQ25 16 +#define MCHP_IRQ_GIRQ26 17 +/* GIRQ13 direct sources */ +#define MCHP_IRQ_I2C_0 20 +#define MCHP_IRQ_I2C_1 21 +#define MCHP_IRQ_I2C_2 22 +#define MCHP_IRQ_I2C_3 23 +/* GIRQ14 direct sources */ +#define MCHP_IRQ_DMA_0 24 +#define MCHP_IRQ_DMA_1 25 +#define MCHP_IRQ_DMA_2 26 +#define MCHP_IRQ_DMA_3 27 +#define MCHP_IRQ_DMA_4 28 +#define MCHP_IRQ_DMA_5 29 +#define MCHP_IRQ_DMA_6 30 +#define MCHP_IRQ_DMA_7 31 +#define MCHP_IRQ_DMA_8 32 +#define MCHP_IRQ_DMA_9 33 +#define MCHP_IRQ_DMA_10 34 +#define MCHP_IRQ_DMA_11 35 +#define MCHP_IRQ_DMA_12 36 +#define MCHP_IRQ_DMA_13 37 +/* GIRQ15 direct sources */ +#define MCHP_IRQ_UART0 40 +#define MCHP_IRQ_UART1 41 +#define MCHP_IRQ_EMI0 42 +#define MCHP_IRQ_EMI1 43 +#define MCHP_IRQ_EMI2 44 +#define MCHP_IRQ_ACPIEC0_IBF 45 +#define MCHP_IRQ_ACPIEC0_OBE 46 +#define MCHP_IRQ_ACPIEC1_IBF 47 +#define MCHP_IRQ_ACPIEC1_OBE 48 +#define MCHP_IRQ_ACPIEC2_IBF 49 +#define MCHP_IRQ_ACPIEC2_OBE 50 +#define MCHP_IRQ_ACPIEC3_IBF 51 +#define MCHP_IRQ_ACPIEC3_OBE 52 +#define MCHP_IRQ_ACPIEC4_IBF 53 +#define MCHP_IRQ_ACPIEC4_OBE 54 +#define MCHP_IRQ_ACPIPM1_CTL 55 +#define MCHP_IRQ_ACPIPM1_EN 56 +#define MCHP_IRQ_ACPIPM1_STS 57 +#define MCHP_IRQ_8042EM_OBE 58 +#define MCHP_IRQ_8042EM_IBF 59 +#define MCHP_IRQ_MAILBOX_DATA 60 +#define MCHP_IRQ_PORT80DBG0 62 +#define MCHP_IRQ_PORT80DBG1 63 +/* GIRQ16 direct sources */ +#define MCHP_IRQ_PKE_ERR 65 +#define MCHP_IRQ_PKE_END 66 +#define MCHP_IRQ_NDRNG 67 +#define MCHP_IRQ_AES 68 +#define MCHP_IRQ_HASH 69 +/* GIRQ17 direct sources */ +#define MCHP_IRQ_PECI_HOST 70 +#define MCHP_IRQ_TACH_0 71 +#define MCHP_IRQ_TACH_1 72 +#define MCHP_IRQ_TACH_2 73 +#define MCHP_IRQ_FAN0_FAIL 74 +#define MCHP_IRQ_FAN0_STALL 75 +#define MCHP_IRQ_FAN1_FAIL 76 +#define MCHP_IRQ_FAN1_STALL 77 +#define MCHP_IRQ_ADC_SNGL 78 +#define MCHP_IRQ_ADC_RPT 79 +#define MCHP_IRQ_RCID0 80 +#define MCHP_IRQ_RCID1 81 +#define MCHP_IRQ_RCID2 82 +#define MCHP_IRQ_LED0_WDT 83 +#define MCHP_IRQ_LED1_WDT 84 +#define MCHP_IRQ_LED2_WDT 85 +#define MCHP_IRQ_LED3_WDT 86 +#define MCHP_IRQ_PHOT 87 +#define MCHP_IRQ_PWRGRD0 88 +#define MCHP_IRQ_PWRGRD1 89 +/* GIRQ18 direct sources */ +#define MCHP_IRQ_LPC 90 +#define MCHP_IRQ_QMSPI0 91 +#define MCHP_IRQ_SPI0_TX 92 +#define MCHP_IRQ_SPI0_RX 93 +#define MCHP_IRQ_SPI1_TX 94 +#define MCHP_IRQ_SPI1_RX 95 +#define MCHP_IRQ_BCM0_ERR 96 +#define MCHP_IRQ_BCM0_BUSY 97 +#define MCHP_IRQ_BCM1_ERR 98 +#define MCHP_IRQ_BCM1_BUSY 99 +#define MCHP_IRQ_PS2_0 100 +#define MCHP_IRQ_PS2_1 101 +#define MCHP_IRQ_PS2_2 102 +#define MCHP_IRQ_EEPROM 155 +/* GIRQ19 direct sources */ +#define MCHP_IRQ_ESPI_PC 103 +#define MCHP_IRQ_ESPI_BM1 104 +#define MCHP_IRQ_ESPI_BM2 105 +#define MCHP_IRQ_ESPI_LTR 106 +#define MCHP_IRQ_ESPI_OOB_UP 107 +#define MCHP_IRQ_ESPI_OOB_DN 108 +#define MCHP_IRQ_ESPI_FC 109 +#define MCHP_IRQ_ESPI_RESET 110 +#define MCHP_IRQ_ESPI_VW_EN 156 +/* GIRQ21 direct sources */ +#define MCHP_IRQ_RTOS_TIMER 111 +#define MCHP_IRQ_HTIMER0 112 +#define MCHP_IRQ_HTIMER1 113 +#define MCHP_IRQ_WEEK_ALARM 114 +#define MCHP_IRQ_SUBWEEK 115 +#define MCHP_IRQ_WEEK_SEC 116 +#define MCHP_IRQ_WEEK_SUBSEC 117 +#define MCHP_IRQ_WEEK_SYSPWR 118 +#define MCHP_IRQ_RTC 119 +#define MCHP_IRQ_RTC_ALARM 120 +#define MCHP_IRQ_VCI_OVRD_IN 121 +#define MCHP_IRQ_VCI_IN0 122 +#define MCHP_IRQ_VCI_IN1 123 +#define MCHP_IRQ_VCI_IN2 124 +#define MCHP_IRQ_VCI_IN3 125 +#define MCHP_IRQ_VCI_IN4 126 +#define MCHP_IRQ_VCI_IN5 127 +#define MCHP_IRQ_VCI_IN6 128 +#define MCHP_IRQ_PS20A_WAKE 129 +#define MCHP_IRQ_PS20B_WAKE 130 +#define MCHP_IRQ_PS21A_WAKE 131 +#define MCHP_IRQ_PS21B_WAKE 132 +#define MCHP_IRQ_PS2_2_WAKE 133 +#define MCHP_IRQ_ENVMON 134 +#define MCHP_IRQ_KSC_INT 135 +/* GIRQ23 direct sources */ +#define MCHP_IRQ_TIMER16_0 136 +#define MCHP_IRQ_TIMER16_1 137 +#define MCHP_IRQ_TIMER16_2 138 +#define MCHP_IRQ_TIMER16_3 139 +#define MCHP_IRQ_TIMER32_0 140 +#define MCHP_IRQ_TIMER32_1 141 +#define MCHP_IRQ_CNTR_TM0 142 +#define MCHP_IRQ_CNTR_TM1 143 +#define MCHP_IRQ_CNTR_TM2 144 +#define MCHP_IRQ_CNTR_TM3 145 +#define MCHP_IRQ_CCT_TMR 146 +#define MCHP_IRQ_CCT_CAP0 147 +#define MCHP_IRQ_CCT_CAP1 148 +#define MCHP_IRQ_CCT_CAP2 149 +#define MCHP_IRQ_CCT_CAP3 150 +#define MCHP_IRQ_CCT_CAP4 151 +#define MCHP_IRQ_CCT_CAP5 152 +#define MCHP_IRQ_CCT_CMP0 153 +#define MCHP_IRQ_CCT_CMP1 154 +/* Must match CONFIG_IRQ_COUNT in config_chip.h */ +#define MCHP_IRQ_MAX 157 + +/* Block base addresses */ +#define MCHP_WDG_BASE 0x40000000 +#define MCHP_TMR16_0_BASE 0x40000c00 +#define MCHP_TMR32_0_BASE 0x40000c80 +#define MCHP_CNT16_0_BASE 0x40000d00 +#define MCHP_DMA_BASE 0x40002400 +#define MCHP_PROCHOT_BASE 0x40003400 +#define MCHP_I2C0_BASE 0x40004000 +#define MCHP_I2C1_BASE 0x40004400 +#define MCHP_I2C2_BASE 0x40004800 +#define MCHP_I2C3_BASE 0x40004C00 +#define MCHP_QMSPI0_BASE 0x40005400 +#define MCHP_PWM_0_BASE 0x40005800 +#define MCHP_TACH_0_BASE 0x40006000 +#define MCHP_PECI_BASE 0x40006400 +#define MCHP_RTMR_BASE 0x40007400 +#define MCHP_ADC_BASE 0x40007c00 +#define MCHP_TFDP_BASE 0x40008c00 +#define MCHP_GPSPI0_BASE 0x40009400 +#define MCHP_GPSPI1_BASE 0x40009480 +#define MCHP_HTIMER_BASE 0x40009800 +#define MCHP_KEYSCAN_BASE 0x40009c00 +#define MCHP_RPM2PWM0_BASE 0x4000a000 +#define MCHP_RPM2PWM1_BASE 0x4000a080 +#define MCHP_VBAT_BASE 0x4000a400 +#define MCHP_VBAT_RAM_BASE 0x4000a800 +#define MCHP_WKTIMER_BASE 0x4000ac80 +#define MCHP_BBLED_0_BASE 0x4000B800 +#define MCHP_INT_BASE 0x4000e000 +#define MCHP_EC_BASE 0x4000fc00 + +#define MCHP_PCR_BASE 0x40080100 +#define MCHP_GPIO_BASE 0x40081000 + +#define MCHP_MBOX_BASE 0x400f0000 +#define MCHP_8042_BASE 0x400f0400 +#define MCHP_ACPI_EC_0_BASE 0x400f0800 +#define MCHP_ACPI_PM1_BASE 0x400f1c00 +#define MCHP_UART0_BASE 0x400f2400 +#define MCHP_UART1_BASE 0x400f2800 +#define MCHP_LPC_BASE 0x400f3000 +#define MCHP_ESPI_IO_BASE 0x400f3400 +#define MCHP_ESPI_MEM_BASE 0x400f3800 +#define MCHP_EMI_0_BASE 0x400f4000 +#define MCHP_EMI_1_BASE 0x400f4400 +#define MCHP_EMI_2_BASE 0x400f4800 +#define MCHP_P80CAP0_BASE 0x400f8000 +#define MCHP_P80CAP1_BASE 0x400f8400 +#define MCHP_ESPI_VW_BASE 0x400f9c00 +#define MCHP_CHIP_BASE 0x400fff00 + +#ifndef __ASSEMBLER__ + +/* + * Helper function for RAM address aliasing + * NOTE: MCHP AHB masters do NOT require aliasing. + * Cortex-M4 bit-banding does require aliasing of the + * DATA SRAM region. + */ +#define MCHP_RAM_ALIAS(x) ((x) >= 0x118000 ? (x)-0x118000 + 0x20000000 : (x)) + +/* EC Chip Configuration */ +/* 8-bit Device ID */ +#define MCHP_CHIP_DEV_ID REG8(MCHP_CHIP_BASE + 0x20) +/* 8-bit Device Revision */ +#define MCHP_CHIP_DEV_REV REG8(MCHP_CHIP_BASE + 0x21) + +/* PCR clock control dividers */ +#define MCHP_PCR_CLK_CTL_FASTEST 1U +#define MCHP_PCR_CLK_CTL_48MHZ 1U +#define MCHP_PCR_CLK_CTL_12MHZ 4U + +/* Number of PCR Sleep Enable, Clock Required, and Reset registers */ +#define MCHP_PCR_SLP_RST_REG_MAX 5 + +/* Sleep 0: Sleep Enable, Clock Required, and Reset bits */ +#define MCHP_PCR_JTAG BIT(0) /* CLKREQ only */ +#define MCHP_PCR_OTP BIT(1) +#define MCHP_PCR_ISPI BIT(2) + +/* Command all blocks to sleep */ +#define MCHP_PCR_SLP_EN0_JTAG BIT(0) +#define MCHP_PCR_SLP_EN0_OTP BIT(1) +#define MCHP_PCR_SLP_EN0_ISPI BIT(2) +#define MCHP_PCR_SLP_EN0_SLEEP 0xffffffff + +/* + * Encode register number and bit position + * b[4:0] = bit number + * b[10:8] = zero based register number + */ +#define MCHP_PCR_ERB(rnum, bnum) ((((rnum)&0x0f) << 8) | ((bnum)&0x1f)) + +/* PCR Sleep 1: Sleep Enable, Clock Required, and Reset bits */ +#define MCHP_PCR_BTMR16_1 MCHP_PCR_ERB(1, 31) +#define MCHP_PCR_BTMR16_0 MCHP_PCR_ERB(1, 30) +#define MCHP_PCR_ECS MCHP_PCR_ERB(1, 29) +#define MCHP_PCR_PWM8 MCHP_PCR_ERB(1, 27) +#define MCHP_PCR_PWM7 MCHP_PCR_ERB(1, 26) +#define MCHP_PCR_PWM6 MCHP_PCR_ERB(1, 25) +#define MCHP_PCR_PWM5 MCHP_PCR_ERB(1, 24) +#define MCHP_PCR_PWM4 MCHP_PCR_ERB(1, 23) +#define MCHP_PCR_PWM3 MCHP_PCR_ERB(1, 22) +#define MCHP_PCR_PWM2 MCHP_PCR_ERB(1, 21) +#define MCHP_PCR_PWM1 MCHP_PCR_ERB(1, 20) +#define MCHP_PCR_TACH2 MCHP_PCR_ERB(1, 12) +#define MCHP_PCR_TACH1 MCHP_PCR_ERB(1, 11) +#define MCHP_PCR_I2C0 MCHP_PCR_ERB(1, 10) +#define MCHP_PCR_WDT MCHP_PCR_ERB(1, 9) +#define MCHP_PCR_CPU MCHP_PCR_ERB(1, 8) +#define MCHP_PCR_TFDP MCHP_PCR_ERB(1, 7) +#define MCHP_PCR_DMA MCHP_PCR_ERB(1, 6) +#define MCHP_PCR_PMC MCHP_PCR_ERB(1, 5) +#define MCHP_PCR_PWM0 MCHP_PCR_ERB(1, 4) +#define MCHP_PCR_TACH0 MCHP_PCR_ERB(1, 2) +#define MCHP_PCR_PECI MCHP_PCR_ERB(1, 1) +#define MCHP_PCR_ECIA MCHP_PCR_ERB(1, 0) + +/* Command all blocks to sleep */ +#define MCHP_PCR_SLP_EN1_BTMR16_1 BIT(31) +#define MCHP_PCR_SLP_EN1_BTMR16_0 BIT(30) +#define MCHP_PCR_SLP_EN1_ECS BIT(29) +#define MCHP_PCR_SLP_EN1_PWM_ALL (BIT(4) + (0xff << 20)) +#define MCHP_PCR_SLP_EN1_PWM8 BIT(27) +#define MCHP_PCR_SLP_EN1_PWM7 BIT(26) +#define MCHP_PCR_SLP_EN1_PWM6 BIT(25) +#define MCHP_PCR_SLP_EN1_PWM5 BIT(24) +#define MCHP_PCR_SLP_EN1_PWM4 BIT(23) +#define MCHP_PCR_SLP_EN1_PWM3 BIT(22) +#define MCHP_PCR_SLP_EN1_PWM2 BIT(21) +#define MCHP_PCR_SLP_EN1_PWM1 BIT(20) +#define MCHP_PCR_SLP_EN1_TACH2 BIT(12) +#define MCHP_PCR_SLP_EN1_TACH1 BIT(11) +#define MCHP_PCR_SLP_EN1_I2C0 BIT(10) +#define MCHP_PCR_SLP_EN1_WDT BIT(9) +#define MCHP_PCR_SLP_EN1_CPU BIT(8) +#define MCHP_PCR_SLP_EN1_TFDP BIT(7) +#define MCHP_PCR_SLP_EN1_DMA BIT(6) +#define MCHP_PCR_SLP_EN1_PMC BIT(5) +#define MCHP_PCR_SLP_EN1_PWM0 BIT(4) +#define MCHP_PCR_SLP_EN1_TACH0 BIT(2) +#define MCHP_PCR_SLP_EN1_PECI BIT(1) +#define MCHP_PCR_SLP_EN1_ECIA BIT(0) +/* all sleep enable 1 bits */ +#define MCHP_PCR_SLP_EN1_SLEEP 0xffffffff +/* + * block not used by default + * Do not sleep ECIA, PMC, CPU and ECS + */ +#define MCHP_PCR_SLP_EN1_UNUSED_BLOCKS 0xdffffede + +/* PCR Sleep 2: Sleep Enable, Clock Required 2, Reset bits */ +#define MCHP_PCR_P80CAP1 MCHP_PCR_ERB(2, 26) +#define MCHP_PCR_P80CAP0 MCHP_PCR_ERB(2, 25) +#define MCHP_PCR_ACPI_EC4 MCHP_PCR_ERB(2, 23) +#define MCHP_PCR_ACPI_EC3 MCHP_PCR_ERB(2, 22) +#define MCHP_PCR_ACPI_EC2 MCHP_PCR_ERB(2, 21) +#define MCHP_PCR_ESPI MCHP_PCR_ERB(2, 19) +#define MCHP_PCR_RTC MCHP_PCR_ERB(2, 18) +#define MCHP_PCR_MBOX MCHP_PCR_ERB(2, 17) +#define MCHP_PCR_8042 MCHP_PCR_ERB(2, 26) +#define MCHP_PCR_ACPI_PM1 MCHP_PCR_ERB(2, 15) +#define MCHP_PCR_ACPI_EC1 MCHP_PCR_ERB(2, 14) +#define MCHP_PCR_ACPI_EC0 MCHP_PCR_ERB(2, 13) +#define MCHP_PCR_GCFG MCHP_PCR_ERB(2, 12) +#define MCHP_PCR_UART1 MCHP_PCR_ERB(2, 2) +#define MCHP_PCR_UART0 MCHP_PCR_ERB(2, 1) +#define MCHP_PCR_LPC MCHP_PCR_ERB(2, 0) + +/* Command all blocks to sleep */ +#define MCHP_PCR_SLP_EN2_P80CAP1 BIT(26) +#define MCHP_PCR_SLP_EN2_P80CAP0 BIT(25) +#define MCHP_PCR_SLP_EN2_ACPI_EC4 BIT(23) +#define MCHP_PCR_SLP_EN2_ACPI_EC3 BIT(22) +#define MCHP_PCR_SLP_EN2_ACPI_EC2 BIT(21) +#define MCHP_PCR_SLP_EN2_ESPI_SCR BIT(20) +#define MCHP_PCR_SLP_EN2_ESPI BIT(19) +#define MCHP_PCR_SLP_EN2_RTC BIT(18) +#define MCHP_PCR_SLP_EN2_MAILBOX BIT(17) +#define MCHP_PCR_SLP_EN2_MIF8042 BIT(16) +#define MCHP_PCR_SLP_EN2_ACPI_PM1 BIT(15) +#define MCHP_PCR_SLP_EN2_ACPI_EC1 BIT(14) +#define MCHP_PCR_SLP_EN2_ACPI_EC0 BIT(13) +#define MCHP_PCR_SLP_EN2_GCFG BIT(12) +#define MCHP_PCR_SLP_EN2_UART1 BIT(2) +#define MCHP_PCR_SLP_EN2_UART0 BIT(1) +#define MCHP_PCR_SLP_EN2_LPC BIT(0) +/* all sleep enable 2 bits */ +#define MCHP_PCR_SLP_EN2_SLEEP 0xffffffff + +/* PCR Sleep 3: Sleep Enable, Clock Required, and Reset */ +#define MCHP_PCR_PWM9 MCHP_PCR_ERB(3, 31) +#define MCHP_PCR_CCT0 MCHP_PCR_ERB(3, 30) +#define MCHP_PCR_HTMR1 MCHP_PCR_ERB(3, 29) +#define MCHP_PCR_AESHASH MCHP_PCR_ERB(3, 28) +#define MCHP_PCR_RNG MCHP_PCR_ERB(3, 27) +#define MCHP_PCR_PKE MCHP_PCR_ERB(3, 26) +#define MCHP_PCR_LED3 MCHP_PCR_ERB(3, 25) +#define MCHP_PCR_BTMR32_1 MCHP_PCR_ERB(3, 24) +#define MCHP_PCR_BTMR32_0 MCHP_PCR_ERB(3, 23) +#define MCHP_PCR_BTMR16_3 MCHP_PCR_ERB(3, 22) +#define MCHP_PCR_BTMR16_2 MCHP_PCR_ERB(3, 21) +#define MCHP_PCR_GPSPI1 MCHP_PCR_ERB(3, 20) +#define MCHP_PCR_BCM0 MCHP_PCR_ERB(3, 19) +#define MCHP_PCR_LED2 MCHP_PCR_ERB(3, 18) +#define MCHP_PCR_LED1 MCHP_PCR_ERB(3, 17) +#define MCHP_PCR_LED0 MCHP_PCR_ERB(3, 16) +#define MCHP_PCR_I2C3 MCHP_PCR_ERB(3, 15) +#define MCHP_PCR_I2C2 MCHP_PCR_ERB(3, 14) +#define MCHP_PCR_I2C1 MCHP_PCR_ERB(3, 13) +#define MCHP_PCR_RPMPWM0 MCHP_PCR_ERB(3, 12) +#define MCHP_PCR_KEYSCAN MCHP_PCR_ERB(3, 11) +#define MCHP_PCR_HTMR0 MCHP_PCR_ERB(3, 10) +#define MCHP_PCR_GPSPI0 MCHP_PCR_ERB(3, 9) +#define MCHP_PCR_PS2_2 MCHP_PCR_ERB(3, 7) +#define MCHP_PCR_PS2_1 MCHP_PCR_ERB(3, 6) +#define MCHP_PCR_PS2_0 MCHP_PCR_ERB(3, 5) +#define MCHP_PCR_ADC MCHP_PCR_ERB(3, 3) + +/* Command blocks to sleep */ +#define MCHP_PCR_SLP_EN3_PWM9 BIT(31) +#define MCHP_PCR_SLP_EN3_CCT0 BIT(30) +#define MCHP_PCR_SLP_EN3_HTMR1 BIT(29) +#define MCHP_PCR_SLP_EN3_AESHASH BIT(28) +#define MCHP_PCR_SLP_EN3_RNG BIT(27) +#define MCHP_PCR_SLP_EN3_PKE BIT(26) +#define MCHP_PCR_SLP_EN3_LED3 BIT(25) +#define MCHP_PCR_SLP_EN3_BTMR32_1 BIT(24) +#define MCHP_PCR_SLP_EN3_BTMR32_0 BIT(23) +#define MCHP_PCR_SLP_EN3_BTMR16_3 BIT(22) +#define MCHP_PCR_SLP_EN3_BTMR16_2 BIT(21) +#define MCHP_PCR_SLP_EN3_I2C4 BIT(20) +#define MCHP_PCR_SLP_EN3_BCM0 BIT(19) +#define MCHP_PCR_SLP_EN3_LED2 BIT(18) +#define MCHP_PCR_SLP_EN3_LED1 BIT(17) +#define MCHP_PCR_SLP_EN3_LED0 BIT(16) +#define MCHP_PCR_SLP_EN3_I2C3 BIT(15) +#define MCHP_PCR_SLP_EN3_I2C2 BIT(14) +#define MCHP_PCR_SLP_EN3_I2C1 BIT(13) +#define MCHP_PCR_SLP_EN3_RPM2PWM0 BIT(12) +#define MCHP_PCR_SLP_EN3_KEYSCAN BIT(11) +#define MCHP_PCR_SLP_EN3_HTMR0 BIT(10) +#define MCHP_PCR_SLP_EN3_GPSPI0 BIT(9) +#define MCHP_PCR_SLP_EN3_PS2_2 BIT(7) +#define MCHP_PCR_SLP_EN3_PS2_1 BIT(6) +#define MCHP_PCR_SLP_EN3_PS2_0 BIT(5) +#define MCHP_PCR_SLP_EN3_ADC BIT(3) +#define MCHP_PCR_SLP_EN3_ALL_CRYPTO (0x07 << 26) +/* all sleep enable 3 bits */ +#define MCHP_PCR_SLP_EN3_SLEEP 0xffffffff +#define MCHP_PCR_SLP_EN3_PWM_ALL (MCHP_PCR_SLP_EN3_PWM9) + +/* PCR Sleep 4: Sleep Enable, Clock Required, Reset */ +#define MCHP_PCR_FJCL MCHP_PCR_ERB(4, 15) +#define MCHP_PCR_PSPI MCHP_PCR_ERB(4, 14) +#define MCHP_PCR_PROCHOT MCHP_PCR_ERB(4, 13) +#define MCHP_PCR_RCID2 MCHP_PCR_ERB(4, 12) +#define MCHP_PCR_RCID1 MCHP_PCR_ERB(4, 11) +#define MCHP_PCR_RCID0 MCHP_PCR_ERB(4, 10) +#define MCHP_PCR_BCM1 MCHP_PCR_ERB(4, 9) +#define MCHP_PCR_QMSPI MCHP_PCR_ERB(4, 8) +#define MCHP_PCR_RPMPWM1 MCHP_PCR_ERB(4, 7) +#define MCHP_PCR_RTMR MCHP_PCR_ERB(4, 6) +#define MCHP_PCR_CNT16_3 MCHP_PCR_ERB(4, 5) +#define MCHP_PCR_CNT16_2 MCHP_PCR_ERB(4, 4) +#define MCHP_PCR_CNT16_1 MCHP_PCR_ERB(4, 3) +#define MCHP_PCR_CNT16_0 MCHP_PCR_ERB(4, 2) +#define MCHP_PCR_PWM11 MCHP_PCR_ERB(4, 1) +#define MCHP_PCR_PWM10 MCHP_PCR_ERB(4, 0) + +/* Command blocks to sleep */ +#define MCHP_PCR_SLP_EN4_FJCL BIT(15) +#define MCHP_PCR_SLP_EN4_PSPI BIT(14) +#define MCHP_PCR_SLP_EN4_PROCHOT BIT(13) +#define MCHP_PCR_SLP_EN4_RCID2 BIT(12) +#define MCHP_PCR_SLP_EN4_RCID1 BIT(11) +#define MCHP_PCR_SLP_EN4_RCID0 BIT(10) +#define MCHP_PCR_SLP_EN4_QMSPI BIT(8) +#define MCHP_PCR_SLP_EN4_RPMPWM1 BIT(7) +#define MCHP_PCR_SLP_EN4_RTMR BIT(6) +#define MCHP_PCR_SLP_EN4_CNT16_3 BIT(5) +#define MCHP_PCR_SLP_EN4_CNT16_2 BIT(4) +#define MCHP_PCR_SLP_EN4_CNT16_1 BIT(3) +#define MCHP_PCR_SLP_EN4_CNT16_0 BIT(2) +#define MCHP_PCR_SLP_EN4_PWM11 BIT(1) +#define MCHP_PCR_SLP_EN4_PWM10 BIT(0) + +/* all sleep enable 4 bits */ +#define MCHP_PCR_SLP_EN4_SLEEP 0xffffffff +#define MCHP_PCR_SLP_EN4_PWM_ALL \ + (MCHP_PCR_SLP_EN4_PWM10 | MCHP_PCR_SLP_EN4_PWM11) + +/* Allow all blocks to request clocks */ +#define MCHP_PCR_SLP_EN0_WAKE (~(MCHP_PCR_SLP_EN0_SLEEP)) +#define MCHP_PCR_SLP_EN1_WAKE (~(MCHP_PCR_SLP_EN1_SLEEP)) +#define MCHP_PCR_SLP_EN2_WAKE (~(MCHP_PCR_SLP_EN2_SLEEP)) +#define MCHP_PCR_SLP_EN3_WAKE (~(MCHP_PCR_SLP_EN3_SLEEP)) +#define MCHP_PCR_SLP_EN4_WAKE (~(MCHP_PCR_SLP_EN4_SLEEP)) + +/* Bit defines for MCHP_PCR_PWR_RST_STS */ +#define MCHP_PWR_RST_STS_MASK_RO 0xc8c +#define MCHP_PWR_RST_STS_MASK_RWC 0x060 +#define MCHP_PWR_RST_STS_MASK \ + ((MCHP_PWR_RST_STS_MASK_RO) | (MCHP_PWR_RST_STS_MASK_RWC)) + +#define MCHP_PWR_RST_STS_ESPI_CLK_ACT BIT(11) /* RO */ +#define MCHP_PWR_RST_STS_32K_ACT BIT(10) /* RO */ +#define MCHP_PWR_RST_STS_JTAG_RSTN BIT(7) /* RO */ +#define MCHP_PWR_RST_STS_SYS BIT(6) /* R/WC */ +/* same function, old bit name */ +#define MCHP_PWR_RST_STS_VTR BIT(6) +#define MCHP_PWR_RST_STS_VBAT BIT(5) /* R/WC */ +#define MCHP_PWR_RST_STS_HOST BIT(3) /* RO */ +#define MCHP_PWR_RST_STS_VCC_PWRGD BIT(2) /* RO */ + +/* Bit defines for MCHP_PCR_PWR_RST_CTL */ +#define MCHP_PCR_PWR_HOST_RST_SEL_BITPOS 8 +#define MCHP_PCR_PWR_HOST_RST_PCI_RESET BIT(8) +#define MCHP_PCR_PWR_HOST_RST_ESPI_PLTRST (0 << 8) +#define MCHP_PCR_PWR_OK_INV_BITPOS 0 + +/* Bit defines for MCHP_PCR_SYS_RST */ +#define MCHP_PCR_SYS_SOFT_RESET BIT(8) + +/* EC Subsystem */ +#define MCHP_EC_AHB_ERR REG32(MCHP_EC_BASE + 0x04) +#define MCHP_EC_ID_RO REG32(MCHP_EC_BASE + 0x10) +#define MCHP_EC_AHB_ERR_EN REG32(MCHP_EC_BASE + 0x14) +#define MCHP_EC_INT_CTRL REG32(MCHP_EC_BASE + 0x18) +#define MCHP_EC_TRACE_EN REG32(MCHP_EC_BASE + 0x1c) +#define MCHP_EC_JTAG_EN REG32(MCHP_EC_BASE + 0x20) +#define MCHP_EC_WDT_CNT REG32(MCHP_EC_BASE + 0x28) +#define MCHP_EC_AES_SHA_SWAP_CTRL REG8(MCHP_EC_BASE + 0x2c) +#define MCHP_EC_PECI_DISABLE REG8(MCHP_EC_BASE + 0x40) +#define MCHP_EC_CRYPTO_SRESET REG8(MCHP_EC_BASE + 0x5c) +#define MCHP_EC_GPIO_BANK_PWR REG8(MCHP_EC_BASE + 0x64) + +/* AHB ERR Enable bit[0]=0(enable), 1(disable) */ +#define MCHP_EC_AHB_ERROR_ENABLE 0 +#define MCHP_EC_AHB_ERROR_DISABLE 1 + +/* MCHP_EC_JTAG_EN bit definitions */ +#define MCHP_JTAG_ENABLE 0x01 +/* bits [2:1] */ +#define MCHP_JTAG_MODE_4PIN 0x00 +/* ARM 2-pin SWD plus 1-pin Serial Wire Viewer (ITM) */ +#define MCHP_JTAG_MODE_SWD_SWV 0x02 +/* ARM 2-pin SWD with no SWV */ +#define MCHP_JTAG_MODE_SWD 0x04 + +/* MCHP_EC_CRYPTO_SRESET bit definitions. Bits cleared by HW */ +#define MCHP_CRYPTO_NDRNG_SRST 0x01 +#define MCHP_CRYPTO_PKE_SRST 0x02 +#define MCHP_CRYPTO_AES_SHA_SRST 0x04 +#define MCHP_CRYPTO_ALL_SRST 0x07 + +/* MCHP_GPIO_BANK_PWR bit definitions */ +#define MCHP_EC_GPIO_BANK_PWR_MASK 0x86 +#define MCHP_EC_GPIO_BANK_PWR_VTR2_18 0x02 +#define MCHP_EC_GPIO_BANK_PWR_VTR3_18 0x04 +#define MCHP_EC_GPIO_BANK_PWR_LOCK 0x80 + +/* EC Interrupt aggregator (ECIA) */ +#define MCHP_INT_GIRQ_LEN 20 /* 5 32-bit registers */ +#define MCHP_INT_GIRQ_FIRST 8 +#define MCHP_INT_GIRQ_LAST 26 +#define MCHP_INT_GIRQ_NUM (26 - 8 + 1) +/* MCHP_INT_GIRQ_FIRST <= x <= MCHP_INT_GIRQ_LAST */ +#define MCHP_INTx_BASE(x) (MCHP_INT_BASE + (((x)-8) * MCHP_INT_GIRQ_LEN)) + +/* + * GPIO GIRQ's are not direct capable + * GIRQ08 GPIO 0140 - 0176 + * GIRQ09 GPIO 0100 - 0136 + * GIRQ10 GPIO 040 - 076 + * GIRQ11 GPIO 000 - 036 + * GIRQ12 GPIO 0200 - 0236 + * GIRQ26 GPIO 0240 - 0276 + * Other GIRQ's not direct capable: + * GIRQ22 wake peripheral clock only + * GIRQ24, GIRQ25 eSPI host to endpoint virtual wires + */ +#define MCHP_INT_AGGR_ONLY_BITMAP 0x07401F00U +#define MCHP_INT_DIRECT_CAPABLE_BITMAP 0x00BFE000U + +/* GIRQ13 I2C controllers. Direct capable */ +#define MCHP_INT13_I2C(x) (1ul << (x)) + +/* GIRQ14 DMA channels 0 - 13. Direct capable */ +#define MCHP_INT14_DMA(x) (1ul << (x)) + +/* GIQ15 interrupt sources. Direct capable */ +#define MCHP_INT15_UART_0 BIT(0) +#define MCHP_INT15_UART_1 BIT(1) +#define MCHP_INT15_EMI_0 BIT(2) +#define MCHP_INT15_EMI_1 BIT(3) +#define MCHP_INT15_EMI_2 BIT(4) +#define MCHP_INT15_ACPI_EC0_IBF BIT(5) +#define MCHP_INT15_ACPI_EC0_OBE BIT(6) +#define MCHP_INT15_ACPI_EC1_IBF BIT(7) +#define MCHP_INT15_ACPI_EC1_OBE BIT(8) +#define MCHP_INT15_ACPI_EC2_IBF BIT(9) +#define MCHP_INT15_ACPI_EC2_OBE BIT(10) +#define MCHP_INT15_ACPI_EC3_IBF BIT(11) +#define MCHP_INT15_ACPI_EC3_OBE BIT(12) +#define MCHP_INT15_ACPI_EC4_IBF BIT(13) +#define MCHP_INT15_ACPI_EC4_OBE BIT(14) +#define MCHP_INT15_ACPI_PM1_CTL BIT(15) +#define MCHP_INT15_ACPI_PM1_EN BIT(16) +#define MCHP_INT15_ACPI_PM1_STS BIT(17) +#define MCHP_INT15_8042_OBE BIT(18) +#define MCHP_INT15_8042_IBF BIT(19) +#define MCHP_INT15_MAILBOX BIT(20) +#define MCHP_INT15_P80_0 BIT(22) +#define MCHP_INT15_P80_1 BIT(23) +#define MCHP_INT15_P80(x) BIT(22 + ((x)&0x01U)) + +/* GIRQ16 interrupt sources. Direct capable */ +#define MCHP_INT16_PKE_ERR BIT(0) +#define MCHP_INT16_PKE_DONE BIT(1) +#define MCHP_INT16_RNG_DONE BIT(2) +#define MCHP_INT16_AES_DONE BIT(3) +#define MCHP_INT16_HASH_DONE BIT(4) + +/* GIR17 interrupt sources. Direct capable */ +#define MCHP_INT17_PECI BIT(0) +#define MCHP_INT17_TACH_0 BIT(1) +#define MCHP_INT17_TACH_1 BIT(2) +#define MCHP_INT17_TACH_2 BIT(3) +#define MCHP_INT17_RPM2PWM0_FAIL BIT(4) +#define MCHP_INT17_RPM2PWM0_STALL BIT(5) +#define MCHP_INT17_RPM2PWM1_FAIL BIT(6) +#define MCHP_INT17_RPM2PWM1_STALL BIT(7) +#define MCHP_INT17_ADC_SINGLE BIT(8) +#define MCHP_INT17_ADC_REPEAT BIT(9) +#define MCHP_INT17_RCID_0 BIT(10) +#define MCHP_INT17_RCID_1 BIT(11) +#define MCHP_INT17_RCID_2 BIT(12) +#define MCHP_INT17_LED_WDT_0 BIT(13) +#define MCHP_INT17_LED_WDT_1 BIT(14) +#define MCHP_INT17_LED_WDT_2 BIT(15) +#define MCHP_INT17_LED_WDT_3 BIT(16) +#define MCHP_INT17_PROCHOT BIT(17) +#define MCHP_INT17_PWRGRD0 BIT(18) +#define MCHP_INT17_PWRGRD1 BIT(19) + +/* GIRQ18 interrupt sources. Direct capable */ +#define MCHP_INT18_LPC_ERR BIT(0) +#define MCHP_INT18_QMSPI BIT(1) +#define MCHP_INT18_GPSPI0_TXBE BIT(2) +#define MCHP_INT18_GPSPI0_RXBF BIT(3) +#define MCHP_INT18_GPSPI1_TXBE BIT(4) +#define MCHP_INT18_GPSPI1_RXBF BIT(5) +#define MCHP_INT18_BCM0_BUSY BIT(6) +#define MCHP_INT18_BCM0_ERR BIT(7) +#define MCHP_INT18_BCM1_BUSY BIT(8) +#define MCHP_INT18_BCM1_ERR BIT(9) +#define MCHP_INT18_PS2_0 BIT(10) +#define MCHP_INT18_PS2_1 BIT(11) +#define MCHP_INT18_PS2_2 BIT(12) +#define MCHP_INT18_PSPI BIT(13) + +/* GIRQ19 interrupt sources. Direct capable */ +#define MCHP_INT19_ESPI_PC BIT(0) +#define MCHP_INT19_ESPI_BM1 BIT(1) +#define MCHP_INT19_ESPI_BM2 BIT(2) +#define MCHP_INT19_ESPI_LTR BIT(3) +#define MCHP_INT19_ESPI_OOB_TX BIT(4) +#define MCHP_INT19_ESPI_OOB_RX BIT(5) +#define MCHP_INT19_ESPI_FC BIT(6) +#define MCHP_INT19_ESPI_RESET BIT(7) +#define MCHP_INT19_ESPI_VW_EN BIT(8) + +/* GIRQ20 interrupt sources. Direct capable */ +#define MCHP_INT20_STAP_OBF BIT(0) +#define MCHP_INT20_STAP_IBF BIT(1) +#define MCHP_INT20_STAP_WAKE BIT(2) +#define MCHP_INT20_ISPI BIT(8) + +/* GIRQ21 interrupt sources. Direct capable */ +#define MCHP_INT21_RTMR BIT(0) +#define MCHP_INT21_HTMR_0 BIT(1) +#define MCHP_INT21_HTMR_1 BIT(2) +#define MCHP_INT21_WEEK_ALARM BIT(3) +#define MCHP_INT21_WEEK_SUB BIT(4) +#define MCHP_INT21_WEEK_1SEC BIT(5) +#define MCHP_INT21_WEEK_1SEC_SUB BIT(6) +#define MCHP_INT21_WEEK_PWR_PRES BIT(7) +#define MCHP_INT21_RTC BIT(8) +#define MCHP_INT21_RTC_ALARM BIT(9) +#define MCHP_INT21_VCI_OVRD BIT(10) +#define MCHP_INT21_VCI_IN0 BIT(11) +#define MCHP_INT21_VCI_IN1 BIT(12) +#define MCHP_INT21_VCI_IN2 BIT(13) +#define MCHP_INT21_VCI_IN3 BIT(14) +#define MCHP_INT21_VCI_IN4 BIT(15) +#define MCHP_INT21_VCI_IN5 BIT(16) +#define MCHP_INT21_VCI_IN6 BIT(17) +#define MCHP_INT21_PS2_0A_WAKE BIT(18) +#define MCHP_INT21_PS2_0B_WAKE BIT(19) +#define MCHP_INT21_PS2_1A_WAKE BIT(20) +#define MCHP_INT21_PS2_1B_WAKE BIT(21) +#define MCHP_INT21_PS2_2_WAKE BIT(22) +#define MCHP_INT21_ENVMON BIT(24) +#define MCHP_INT21_KEYSCAN BIT(25) + +/* GIRQ22 peripheral wake only. GIRQ22 not connected to NVIC */ +#define MCHP_INT22_WAKE_ONLY_LPC BIT(0) +#define MCHP_INT22_WAKE_ONLY_I2C0 BIT(1) +#define MCHP_INT22_WAKE_ONLY_I2C1 BIT(2) +#define MCHP_INT22_WAKE_ONLY_I2C2 BIT(3) +#define MCHP_INT22_WAKE_ONLY_I2C3 BIT(4) +#define MCHP_INT22_WAKE_ONLY_ESPI BIT(9) + +/* GIRQ23 sources. Direct capable */ +#define MCHP_INT23_BTMR16_0 BIT(0) +#define MCHP_INT23_BTMR16_1 BIT(1) +#define MCHP_INT23_BTMR16_2 BIT(2) +#define MCHP_INT23_BTMR16_3 BIT(3) +#define MCHP_INT23_BTMR32_0 BIT(4) +#define MCHP_INT23_BTMR32_1 BIT(5) +#define MCHP_INT23_CNT16_0 BIT(6) +#define MCHP_INT23_CNT16_1 BIT(7) +#define MCHP_INT23_CNT16_2 BIT(8) +#define MCHP_INT23_CNT16_3 BIT(9) +#define MCHP_INT23_CCT BIT(10) +#define MCHP_INT23_CCT_CAP0 BIT(11) +#define MCHP_INT23_CCT_CAP1 BIT(12) +#define MCHP_INT23_CCT_CAP2 BIT(13) +#define MCHP_INT23_CCT_CAP3 BIT(14) +#define MCHP_INT23_CCT_CAP4 BIT(15) +#define MCHP_INT23_CCT_CAP6 BIT(16) +#define MCHP_INT23_CCT_CMP0 BIT(17) +#define MCHP_INT23_CCT_CMP1 BIT(18) + +/* GIRQ24 sources. Master-to-Slave v=[0:6], Source=[0:3] */ +#define MCHP_INT24_MSVW_SRC(v, s) (1ul << ((4 * (v)) + (s))) + +/* GIRQ25 sources Master-to-Slave v=[7:10], Source=[0:3] */ +#define MCHP_INT25_MSVW_SRC(v, s) (1ul << ((4 * ((v)-7)) + (s))) + +/* UART Peripheral 0 <= x <= 1 */ +#define MCHP_UART_INSTANCES 2 +#define MCHP_UART_SPACING 0x400 +#define MCHP_UART_CFG_OFS 0x300 +#define MCHP_UART_CONFIG_BASE(x) \ + (MCHP_UART0_BASE + MCHP_UART_CFG_OFS + ((x)*MCHP_UART_SPACING)) +#define MCHP_UART_RUNTIME_BASE(x) (MCHP_UART0_BASE + ((x)*MCHP_UART_SPACING)) +#define MCHP_UART_GIRQ 15 +#define MCHP_UART0_GIRQ_BIT (MCHP_INT15_UART_0) +#define MCHP_UART1_GIRQ_BIT (MCHP_INT15_UART_1) +#define MCHP_UART_GIRQ_BIT(x) BIT(x) +/* Bit defines for MCHP_UARTx_LSR */ +#define MCHP_LSR_TX_EMPTY BIT(5) + +/* + * GPIO + * MCHP each Port contains 32 GPIO's. + * GPIO Control 1 registers are 32-bit registers starting at + * MCHP_GPIO_BASE. + * index = octal GPIO number from MCHP specification. + * port/bank = index >> 5 + * id = index & 0x1F + * + * The port/bank, id pair may also be used to access GPIO's via + * parallel I/O registers if GPIO control is configured for + * parallel I/O. + * + * From ec/chip/mec1701/config_chip.h + * #define GPIO_PIN(index) ((index) >> 5), ((index) & 0x1F) + * + * GPIO Control 1 Address = 0x40081000 + (((bank << 5) + id) << 2) + * + * Example: GPIO043, Control 1 register address = 0x4008108c + * port/bank = 0x23 >> 5 = 1 + * id = 0x23 & 0x1F = 0x03 + * Control 1 Address = 0x40081000 + ((BIT(5) + 0x03) << 2) = 0x4008108c + * + * Example: GPIO235, Control 1 register address = 0x40081274 + * port/bank = 0x9d >> 5 = 4 + * id = 0x9d & 0x1f = 0x1d + * Control 1 Address = 0x40081000 + (((4 << 5) + 0x1d) << 2) = 0x40081274 + * + */ +#define MCHP_GPIO_CTL(port, id) \ + REG32(MCHP_GPIO_BASE + (((port << 5) + id) << 2)) + +/* MCHP implements 6 GPIO ports */ +#define MCHP_GPIO_MAX_PORT 6 +#define UNIMPLEMENTED_GPIO_BANK MCHP_GPIO_MAX_PORT +/* + * In MECxxxx documentation GPIO numbers are octal, each control + * register is located on a 32-bit boundary. + */ +#define MCHP_GPIO_CTRL(gpio_num) REG32(MCHP_GPIO_BASE + ((gpio_num) << 2)) + +/* + * GPIO control register bit fields + */ +#define MCHP_GPIO_CTRL_PUD_BITPOS 0 +#define MCHP_GPIO_CTRL_PUD_MASK0 0x03 +#define MCHP_GPIO_CTRL_PUD_MASK 0x03 +#define MCHP_GPIO_CTRL_PUD_NONE 0x00 +#define MCHP_GPIO_CTRL_PUD_PU 0x01 +#define MCHP_GPIO_CTRL_PUD_PD 0x02 +#define MCHP_GPIO_CTRL_PUD_KEEPER 0x03 +#define MCHP_GPIO_CTRL_PWR_BITPOS 2 +#define MCHP_GPIO_CTRL_PWR_MASK0 0x03 +#define MCHP_GPIO_CTRL_PWR_MASK (0x03 << 2) +#define MCHP_GPIO_CTRL_PWR_VTR 0 +#define MCHP_GPIO_CTRL_PWR_OFF (0x02 << 2) +#define MCHP_GPIO_INTDET_MASK 0xF0 +#define MCHP_GPIO_INTDET_LVL_LO 0x00 +#define MCHP_GPIO_INTDET_LVL_HI 0x10 +#define MCHP_GPIO_INTDET_DISABLED 0x40 +#define MCHP_GPIO_INTDET_EDGE_RIS 0xD0 +#define MCHP_GPIO_INTDET_EDGE_FALL 0xE0 +#define MCHP_GPIO_INTDET_EDGE_BOTH 0xF0 +#define MCHP_GPIO_INTDET_EDGE_EN BIT(7) +#define MCHP_GPIO_PUSH_PULL 0u +#define MCHP_GPIO_OPEN_DRAIN BIT(8) +#define MCHP_GPIO_INPUT 0u +#define MCHP_GPIO_OUTPUT BIT(9) +#define MCHP_GPIO_OUTSET_CTRL 0u +#define MCHP_GPIO_OUTSEL_PAR BIT(10) +#define MCHP_GPIO_POLARITY_NINV 0u +#define MCHP_GPIO_POLARITY_INV BIT(11) +#define MCHP_GPIO_CTRL_ALT_FUNC_BITPOS 12 +#define MCHP_GPIO_CTRL_ALT_FUNC_MASK0 0x0F +#define MCHP_GPIO_CTRL_ALT_FUNC_MASK (0x0F << 12) +#define MCHP_GPIO_CTRL_FUNC_GPIO (0 << 12) +#define MCHP_GPIO_CTRL_FUNC_1 (1 << 12) +#define MCHP_GPIO_CTRL_FUNC_2 (2 << 12) +#define MCHP_GPIO_CTRL_FUNC_3 (3 << 12) +#define MCHP_GPIO_CTRL_OUT_LVL BIT(16) +/* MEC170x reserved read-only 0 bit. Value set to 0 */ +#define MCHP_GPIO_CTRL_DIS_INPUT_BITPOS 15 +#define MCHP_GPIO_CTRL_DIS_INPUT_BIT 0 + +/* + * GPIO Parallel Input and Output registers. + * gpio_bank in [0, 5] + */ +#define MCHP_GPIO_PARIN(bank) REG32(MCHP_GPIO_BASE + 0x0300 + ((bank) << 2)) +#define MCHP_GPIO_PAROUT(bank) REG32(MCHP_GPIO_BASE + 0x0380 + ((bank) << 2)) + +/* Basic timers */ +#define MCHP_TMR_SPACING 0x20 +#define MCHP_TMR16_INSTANCES 4 +#define MCHP_TMR32_INSTANCES 2 +#define MCHP_TMR16_MAX (MCHP_TMR16_INSTANCES) +#define MCHP_TMR32_MAX (MCHP_TMR32_INSTANCES) +#define MCHP_TMR16_BASE(n) (MCHP_TMR16_0_BASE + (n)*MCHP_TMR_SPACING) +#define MCHP_TMR32_BASE(n) (MCHP_TMR32_0_BASE + (n)*MCHP_TMR_SPACING) +#define MCHP_TMR16_GIRQ 23 +#define MCHP_TMR16_GIRQ_BIT(n) BIT(0 + (n)) +#define MCHP_TMR32_GIRQ 23 +#define MCHP_TMR32_GIRQ_BIT(n) BIT(4 + (n)) + +/* 16-bit Counter/timer */ +#define MCHP_CNT16_SPACING 0x20 +#define MCHP_CNT16_INSTANCES 4 +#define MCHP_CNT16_BASE(n) (MCHP_CNT16_0_BASE + (n)*MCHP_CNT16_SPACING) +#define MCHP_CNT16_GIRQ 23 +#define MCHP_CNT16_GIRQ_BIT(x) BIT(6 + (x)) + +/* RTimer */ +#define MCHP_RTMR_GIRQ 21 +#define MCHP_RTMR_GIRQ_BIT(x) MCHP_INT21_RTMR + +/* VBAT */ +#define MCHP_VBAT_STS REG32(MCHP_VBAT_BASE + 0x0) +#define MCHP_VBAT_CE REG32(MCHP_VBAT_BASE + 0x8) +#define MCHP_VBAT_SHDN_DIS REG32(MCHP_VBAT_BASE + 0xC) +#define MCHP_VBAT_MONOTONIC_CTR_LO REG32(MCHP_VBAT_BASE + 0x20) +#define MCHP_VBAT_MONOTONIC_CTR_HI REG32(MCHP_VBAT_BASE + 0x24) +/* read 32-bit word at 32-bit offset x where 0 <= x <= 32 */ +#define MCHP_VBAT_RAM_SIZE 128 +#define MCHP_VBAT_RAM(wnum) REG32(MCHP_VBAT_RAM_BASE + ((wnum)*4)) +#define MCHP_VBAT_RAM8(bnum) REG8(MCHP_VBAT_RAM_BASE + (bnum)) +#define MCHP_VBAT_VWIRE_BACKUP 30 +/* + * Miscellaneous firmware control fields + * scratch pad index cannot be more than 32 as + * MEC152x has 64 bytes = 16 words of scratch RAM + */ +#define MCHP_IMAGETYPE_IDX 31 + +/* Bit definition for MCHP_VBAT_STS */ +#define MCHP_VBAT_STS_SOFTRESET BIT(2) +#define MCHP_VBAT_STS_RESETI BIT(4) +#define MCHP_VBAT_STS_WDT BIT(5) +#define MCHP_VBAT_STS_SYSRESETREQ BIT(6) +#define MCHP_VBAT_STS_VBAT_RST BIT(7) +#define MCHP_VBAT_STS_ANY_RST 0xF4u + +/* Bit definitions for MCHP_VBAT_CE */ +#define MCHP_VBAT_CE_XOSEL_BITPOS 3 +#define MCHP_VBAT_CE_XOSEL_MASK BIT(3) +#define MCHP_VBAT_CE_XOSEL_PAR 0 +#define MCHP_VBAT_CE_XOSEL_SE BIT(3) + +#define MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_BITPOS 2 +#define MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_MASK BIT(2) +#define MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_INT 0 +#define MCHP_VBAT_CE_ALWAYS_ON_32K_SRC_CRYSTAL BIT(2) + +#define MCHP_VBAT_CE_32K_DOMAIN_SRC_BITPOS 1 +#define MCHP_VBAT_CE_32K_DOMAIN_SRC_MASK BIT(1) +#define MCHP_VBAT_CE_32K_DOMAIN_ALWAYS_ON 0 +#define MCHP_VBAT_CE_32K_DOMAIN_32KHZ_IN_PIN BIT(1) + +/* Blinking-Breathing LED 0 <= n <= 2 */ +#define MCHP_BBLEB_INSTANCES 4 +#define MCHP_BBLED_BASE(n) (MCHP_BBLED_0_BASE + (((n)&0x03) * 256)) + +/* EMI */ +#define MCHP_EMI_INSTANCES 3 +#define MCHP_EMI_SPACING 0x400 +#define MCHP_EMI_ECREG_OFS 0x100 +/* base of EMI registers only accessible by EC */ +#define MCHP_EMI_BASE(n) \ + (MCHP_EMI_0_BASE + MCHP_EMI_ECREG_OFS + ((n)*MCHP_EMI_SPACING)) +/* base of EMI registers accessible by EC and Host */ +#define MCHP_EMI_RT_BASE(n) (MCHP_EMI_0_BASE + ((n)*MCHP_EMI_SPACING)) +#define MCHP_EMI_GIRQ 15 +#define MCHP_EMI_GIRQ_BIT(n) BIT(2 + (n)) + +/* Mailbox */ +#define MCHP_MBX_ECREGS_OFS 0x100 +#define MCHP_MBX_RT_BASE MCHP_MBOX_BASE +#define MCHP_MBX_BASE (MCHP_MBOX_BASE + MCHP_MBX_ECREGS_OFS) +#define MCHP_MBX_GIRQ 15 +#define MCHP_MBX_GIRQ_BIT BIT(20) + +/* Port 80 Capture */ +#define MCHP_P80_SPACING 0x400 +#define MCHP_P80_BASE(n) (MCHP_P80CAP0_BASE + ((n) * (MCHP_P80_SPACING))) +#define MCHP_P80_HOST_DATA(n) REG8(MCHP_P80_BASE(n)) +/* Data capture with time stamp register */ +#define MCHP_P80_CAP(n) REG32(MCHP_P80_BASE(n) + 0x100) +#define MCHP_P80_CFG(n) REG8(MCHP_P80_BASE(n) + 0x104) +#define MCHP_P80_STS(n) REG8(MCHP_P80_BASE(n) + 0x108) +#define MCHP_P80_CNT(n) REG32(MCHP_P80_BASE(n) + 0x10c) +#define MCHP_P80_CNT_GET(n) (REG32(MCHP_P80_BASE(n) + 0x10c) >> 8) +#define MCHP_P80_CNT_SET(n, c) (REG32(MCHP_P80_BASE(n) + 0x10c) = ((c) << 8)) +#define MCHP_P80_ACTIVATE(n) REG8(MCHP_P80_BASE(n) + 0x330) +#define MCHP_P80_GIRQ 15 +#define MCHP_P80_GIRQ_BIT(n) BIT(22 + (n)) +/* + * Port 80 Data register bits + * bits[7:0] = data captured on Host write + * bits[31:8] = optional time stamp + */ +#define MCHP_P80_CAP_DATA_MASK 0xFFul +#define MCHP_P80_CAP_TS_BITPOS 8 +#define MCHP_P80_CAP_TS_MASK0 0xfffffful +#define MCHP_P80_CAP_TS_MASK \ + ((MCHP_P80_CAP_TS_MASK0) << (MCHP_P80_CAP_TS_BITPOS)) + +/* Port 80 Configuration register bits */ +#define MCHP_P80_FLUSH_FIFO_WO BIT(1) +#define MCHP_P80_RESET_TIMESTAMP_WO BIT(2) +#define MCHP_P80_TIMEBASE_BITPOS 3 +#define MCHP_P80_TIMEBASE_MASK0 0x03 +#define MCHP_P80_TIMEBASE_MASK \ + ((MCHP_P80_TIMEBASE_MASK0) << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMEBASE_750KHZ (0x03 << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMEBASE_1500KHZ (0x02 << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMEBASE_3MHZ (0x01 << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMEBASE_6MHZ (0x00 << (MCHP_P80_TIMEBASE_BITPOS)) +#define MCHP_P80_TIMER_ENABLE BIT(5) +#define MCHP_P80_FIFO_THRHOLD_MASK (3u << 6) +#define MCHP_P80_FIFO_THRHOLD_1 0u +#define MCHP_P80_FIFO_THRHOLD_4 (1u << 6) +#define MCHP_P80_FIFO_THRHOLD_8 (2u << 6) +#define MCHP_P80_FIFO_THRHOLD_14 (3u << 6) +#define MCHP_P80_FIFO_LEN 16 +/* Port 80 Status register bits, read-only */ +#define MCHP_P80_STS_NOT_EMPTY BIT(0) +#define MCHP_P80_STS_OVERRUN BIT(1) +/* Port 80 Count register bits */ +#define MCHP_P80_CNT_BITPOS 8 +#define MCHP_P80_CNT_MASK0 0xfffffful +#define MCHP_P80_CNT_MASK ((MCHP_P80_CNT_MASK0) << (MCHP_P80_CNT_BITPOS)) + +/* PWM SZ 144 pin package has 9 PWM's */ +#define MCHP_PWM_INSTANCES 9 +#define MCHP_PWM_ID_MAX (MCHP_PWM_INSTANCES) +#define MCHP_PWM_SPACING 16 +#define MCHP_PWM_BASE(x) (MCHP_PWM_0_BASE + ((x)*MCHP_PWM_SPACING)) + +/* TACH */ +#define MCHP_TACH_INSTANCES 3 +#define MCHP_TACH_SPACING 16 +#define MCHP_TACH_BASE(x) (MCHP_TACH_0_BASE + ((x)*MCHP_TACH_SPACING)) +#define MCHP_TACH_GIRQ 17 +#define MCHP_TACH_GIRQ_BIT(x) BIT(1 + (x)) + +/* FAN */ +#define MCHP_FAN_INSTANCES 2 +#define MCHP_FAN_SPACING 0x80U +#define MCHP_FAN_BASE(x) (MCHP_RPM2PWM0_BASE + ((x)*MCHP_FAN_SPACING)) +#define MCHP_FAN_SETTING(x) REG16(MCHP_FAN_BASE(x) + 0x0) +#define MCHP_FAN_CFG1(x) REG8(MCHP_FAN_BASE(x) + 0x2) +#define MCHP_FAN_CFG2(x) REG8(MCHP_FAN_BASE(x) + 0x3) +#define MCHP_FAN_PWM_DIVIDE(x) REG8(MCHP_FAN_BASE(x) + 0x4) +#define MCHP_FAN_GAIN(x) REG8(MCHP_FAN_BASE(x) + 0x5) +#define MCHP_FAN_SPIN_UP(x) REG8(MCHP_FAN_BASE(x) + 0x6) +#define MCHP_FAN_STEP(x) REG8(MCHP_FAN_BASE(x) + 0x7) +#define MCHP_FAN_MIN_DRV(x) REG8(MCHP_FAN_BASE(x) + 0x8) +#define MCHP_FAN_VALID_CNT(x) REG8(MCHP_FAN_BASE(x) + 0x9) +#define MCHP_FAN_DRV_FAIL(x) REG16(MCHP_FAN_BASE(x) + 0xa) +#define MCHP_FAN_TARGET(x) REG16(MCHP_FAN_BASE(x) + 0xc) +#define MCHP_FAN_READING(x) REG16(MCHP_FAN_BASE(x) + 0xe) +#define MCHP_FAN_BASE_FREQ(x) REG8(MCHP_FAN_BASE(x) + 0x10) +#define MCHP_FAN_STATUS(x) REG8(MCHP_FAN_BASE(x) + 0x11) + +/* ACPI EC */ +#define MCHP_ACPI_EC_INSTANCES 5 +#define MCHP_ACPI_EC_MAX (MCHP_ACPI_EC_INSTANCES) +#define MCHP_ACPI_EC_SPACING 0x400 +#define MCHP_ACPI_EC_BASE(x) (MCHP_ACPI_EC_0_BASE + ((x)*MCHP_ACPI_EC_SPACING)) +#define MCHP_ACPI_EC_GIRQ 15 +#define MCHP_ACPI_EC_IBF_GIRQ_BIT(x) BIT(5 + ((x)*2)) +#define MCHP_ACPI_EC_OBE_GIRQ_BIT(x) BIT(6 + ((x)*2)) + +/* ACPI PM1 */ +#define MCHP_ACPI_PM1_ECREGS_OFS 0x100 +#define MCHP_ACPI_PM_RT_BASE MCHP_ACPI_PM1_BASE +#define MCHP_ACPI_PM_EC_BASE (MCHP_ACPI_PM1_BASE + MCHP_ACPI_PM1_ECREGS_OFS) +#define MCHP_ACPI_PM1_CTL_GIRQ_BIT BIT(15) +#define MCHP_ACPI_PM1_EN_GIRQ_BIT BIT(16) +#define MCHP_ACPI_PM1_STS_GIRQ_BIT BIT(17) + +/* 8042 */ +#define MCHP_8042_ECREGS_OFS 0x100 +#define MCHP_8042_GIRQ 15 +#define MCHP_8042_OBE_GIRQ_BIT BIT(18) +#define MCHP_8042_IBF_GIRQ_BIT BIT(19) + +/* I2C controllers 0 - 4 include SMBus network layer functionality. */ +#define MCHP_I2C_CTRL0 0 +#define MCHP_I2C_CTRL1 1 +#define MCHP_I2C_CTRL2 2 +#define MCHP_I2C_CTRL3 3 +#define MCHP_I2C_CTRL_MAX 4 + +#define MCHP_I2C_SEP0 0x400 + +/* + * MEC1701H 144-pin package has four I2C controllers and eleven ports. + * Any port can be mapped to any I2C controller. + * NOTE: 144-pin package does not implement port 1. + * + * I2C port values must be zero based consecutive whole numbers due to + * port number used as an index for I2C mutex array, etc. + * + * Refer to chip i2c_port_to_controller function for mapping + * of port to controller. + * + * Locking must occur by-controller (not by-port). + */ +#define MCHP_I2C_PORT_MASK 0x07FDul +enum MCHP_i2c_port { + MCHP_I2C_PORT0 = 0, + MCHP_I2C_PORT1, /* port 1, do not use. pins not present */ + MCHP_I2C_PORT2, + MCHP_I2C_PORT3, + MCHP_I2C_PORT4, + MCHP_I2C_PORT5, + MCHP_I2C_PORT6, + MCHP_I2C_PORT7, + MCHP_I2C_PORT8, + MCHP_I2C_PORT9, + MCHP_I2C_PORT10, + MCHP_I2C_PORT_COUNT, +}; + +/* All I2C controllers connected to GIRQ13 */ +#define MCHP_I2C_GIRQ 13 +/* I2C[0:7] -> GIRQ13 bits[0:7] */ +#define MCHP_I2C_GIRQ_BIT(n) BIT((n)) + +/* Keyboard scan matrix */ +#define MCHP_KS_GIRQ 21 +#define MCHP_KS_GIRQ_BIT BIT(25) +#define MCHP_KS_DIRECT_NVIC 135 + +/* ADC */ +#define MCHP_ADC_GIRQ 17 +#define MCHP_ADC_GIRQ_SINGLE_BIT BIT(8) +#define MCHP_ADC_GIRQ_REPEAT_BIT BIT(9) +#define MCHP_ADC_SINGLE_DIRECT_NVIC 78 +#define MCHP_ADC_REPEAT_DIRECT_NVIC 79 + +/* Hibernation timer */ +#define MCHP_HTIMER_SPACING 0x20 +#define MCHP_HTIMER_ADDR(n) (MCHP_HTIMER_BASE + ((n)*MCHP_HTIMER_SPACING)) +#define MCHP_HTIMER_GIRQ 21 +/* HTIMER[0:1] -> GIRQ21 bits[1:2] */ +#define MCHP_HTIMER_GIRQ_BIT(n) BIT(1 + (n)) +#define MCHP_HTIMER_DIRECT_NVIC(n) (112 + (n)) + +/* General Purpose SPI (GP-SPI) */ +#define MCHP_SPI_BASE(port) (MCHP_GPSPI0_BASE + ((port)*0x80)) +#define MCHP_SPI_AR(port) REG8(MCHP_SPI_BASE(port) + 0x00) +#define MCHP_SPI_CR(port) REG8(MCHP_SPI_BASE(port) + 0x04) +#define MCHP_SPI_SR(port) REG8(MCHP_SPI_BASE(port) + 0x08) +#define MCHP_SPI_TD(port) REG8(MCHP_SPI_BASE(port) + 0x0c) +#define MCHP_SPI_RD(port) REG8(MCHP_SPI_BASE(port) + 0x10) +#define MCHP_SPI_CC(port) REG8(MCHP_SPI_BASE(port) + 0x14) +#define MCHP_SPI_CG(port) REG8(MCHP_SPI_BASE(port) + 0x18) +/* Addresses of TX/RX register used in tables */ +#define MCHP_SPI_TD_ADDR(ctrl) (MCHP_SPI_BASE(ctrl) + 0x0c) +#define MCHP_SPI_RD_ADDR(ctrl) (MCHP_SPI_BASE(ctrl) + 0x10) +/* All GP-SPI controllers connected to GIRQ18 */ +#define MCHP_SPI_GIRQ 18 +#define MCHP_SPI_GIRQ_TXBE_BIT(x) BIT(2 + ((x)*2)) +#define MCHP_SPI_GIRQ_RXBF_BIT(x) BIT(3 + ((x)*2)) +#define MCHP_GPSPI0_ID 0 +#define MCHP_GPSPI1_ID 1 + +/* + * Quad Master SPI (QMSPI) + * MEC1701 implements 5 descriptors and a single chip select. + */ +#define MCHP_QMSPI_MAX_DESCR 5 +#define MCHP_QMSPI_GIRQ 18 +#define MCHP_QMSPI_GIRQ_BIT BIT(1) +#define MCHP_QMSPI_DIRECT_NVIC 91 + +/* LPC */ +#define MCHP_LPC_RT_BASE (MCHP_LPC_BASE + 0x100) +#define MCHP_LPC_CFG_BASE (MCHP_LPC_BASE + 0x300) +#define MCHP_LPC_ACT REG8(MCHP_LPC_CFG_BASE + 0x30) +#define MCHP_LPC_SIRQ(x) REG8(MCHP_LPC_CFG_BASE + 0x40 + (x)) +#define MCHP_LPC_CFG_BAR REG32(MCHP_LPC_CFG_BASE + 0x60) +#define MCHP_LPC_MAILBOX_BAR REG32(MCHP_LPC_CFG_BASE + 0x64) +#define MCHP_LPC_8042_BAR REG32(MCHP_LPC_CFG_BASE + 0x68) +#define MCHP_LPC_ACPI_EC0_BAR REG32(MCHP_LPC_CFG_BASE + 0x6C) +#define MCHP_LPC_ACPI_EC1_BAR REG32(MCHP_LPC_CFG_BASE + 0x70) +#define MCHP_LPC_ACPI_EC2_BAR REG32(MCHP_LPC_CFG_BASE + 0x74) +#define MCHP_LPC_ACPI_EC3_BAR REG32(MCHP_LPC_CFG_BASE + 0x78) +#define MCHP_LPC_ACPI_EC4_BAR REG32(MCHP_LPC_CFG_BASE + 0x7C) +#define MCHP_LPC_ACPI_PM1_BAR REG32(MCHP_LPC_CFG_BASE + 0x80) +#define MCHP_LPC_PORT92_BAR REG32(MCHP_LPC_CFG_BASE + 0x84) +#define MCHP_LPC_UART0_BAR REG32(MCHP_LPC_CFG_BASE + 0x88) +#define MCHP_LPC_UART1_BAR REG32(MCHP_LPC_CFG_BASE + 0x8C) +#define MCHP_LPC_EMI0_BAR REG32(MCHP_LPC_CFG_BASE + 0x90) +#define MCHP_LPC_EMI1_BAR REG32(MCHP_LPC_CFG_BASE + 0x94) +#define MCHP_LPC_EMI2_BAR REG32(MCHP_LPC_CFG_BASE + 0x98) +#define MCHP_LPC_P80DBG0_BAR REG32(MCHP_LPC_CFG_BASE + 0x9C) +#define MCHP_LPC_P80DBG1_BAR REG32(MCHP_LPC_CFG_BASE + 0xA0) +#define MCHP_LPC_RTC_BAR REG32(MCHP_LPC_CFG_BASE + 0xA4) +#define MCHP_LPC_ACPI_EC_BAR(x) REG32(MCHP_LPC_CFG_BASE + 0x6C + ((x) << 2)) +/* LPC BAR bits */ +#define MCHP_LPC_IO_BAR_ADDR_BITPOS (16) +#define MCHP_LPC_IO_BAR_EN (1ul << 15) +/* LPC Generic Memory BAR's, 64-bit registers */ +#define MCHP_LPC_SRAM0_BAR_LO REG32(MCHP_LPC_CFG_BASE + 0xB0) +#define MCHP_LPC_SRAM0_BAR_HI REG32(MCHP_LPC_CFG_BASE + 0xB4) +#define MCHP_LPC_SRAM1_BAR_LO REG32(MCHP_LPC_CFG_BASE + 0xB8) +#define MCHP_LPC_SRAM1_BAR_HI REG32(MCHP_LPC_CFG_BASE + 0xBC) +/* + * LPC Logical Device Memory BAR's, 48-bit registers + * Use 16-bit aligned access + */ +#define MCHP_LPC_MAILBOX_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xC0) +#define MCHP_LPC_MAILBOX_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xC2) +#define MCHP_LPC_MAILBOX_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xC4) +#define MCHP_LPC_ACPI_EC0_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xC6) +#define MCHP_LPC_ACPI_EC0_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xC8) +#define MCHP_LPC_ACPI_EC0_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xCA) +#define MCHP_LPC_ACPI_EC1_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xCC) +#define MCHP_LPC_ACPI_EC1_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xCE) +#define MCHP_LPC_ACPI_EC1_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xD0) +#define MCHP_LPC_ACPI_EC2_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xD2) +#define MCHP_LPC_ACPI_EC2_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xD4) +#define MCHP_LPC_ACPI_EC2_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xD6) +#define MCHP_LPC_ACPI_EC3_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xD8) +#define MCHP_LPC_ACPI_EC3_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xDA) +#define MCHP_LPC_ACPI_EC3_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xDC) +#define MCHP_LPC_ACPI_EC4_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xDE) +#define MCHP_LPC_ACPI_EC4_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xE0) +#define MCHP_LPC_ACPI_EC4_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xE2) +#define MCHP_LPC_ACPI_EMI0_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xE4) +#define MCHP_LPC_ACPI_EMI0_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xE6) +#define MCHP_LPC_ACPI_EMI0_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xE8) +#define MCHP_LPC_ACPI_EMI1_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xEA) +#define MCHP_LPC_ACPI_EMI1_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xEC) +#define MCHP_LPC_ACPI_EMI1_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xEE) +#define MCHP_LPC_ACPI_EMI2_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xF0) +#define MCHP_LPC_ACPI_EMI2_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xF2) +#define MCHP_LPC_ACPI_EMI2_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xF4) + +#define MCHP_LPC_BUS_MONITOR REG32(MCHP_LPC_RT_BASE + 0x4) +#define MCHP_LPC_HOST_ERROR REG32(MCHP_LPC_RT_BASE + 0x8) +#define MCHP_LPC_EC_SERIRQ REG32(MCHP_LPC_RT_BASE + 0xC) +#define MCHP_LPC_EC_CLK_CTRL REG32(MCHP_LPC_RT_BASE + 0x10) +#define MCHP_LPC_BAR_INHIBIT REG32(MCHP_LPC_RT_BASE + 0x20) +#define MCHP_LPC_BAR_INIT REG32(MCHP_LPC_RT_BASE + 0x30) +#define MCHP_LPC_SRAM0_BAR REG32(MCHP_LPC_RT_BASE + 0xf8) +#define MCHP_LPC_SRAM1_BAR REG32(MCHP_LPC_RT_BASE + 0xfc) + +/* eSPI */ +/* IO BAR defines. Use with MCHP_ESPI_IO_BAR_xxxx macros */ +#define MCHP_ESPI_IO_BAR_ID_CFG_PORT 0 +#define MCHP_ESPI_IO_BAR_ID_MEM_CMPNT 1 +#define MCHP_ESPI_IO_BAR_ID_MAILBOX 2 +#define MCHP_ESPI_IO_BAR_ID_8042 3 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC0 4 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC1 5 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC2 6 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC3 7 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC4 8 +#define MCHP_ESPI_IO_BAR_ID_ACPI_PM1 9 +#define MCHP_ESPI_IO_BAR_ID_P92 0xA +#define MCHP_ESPI_IO_BAR_ID_UART0 0xB +#define MCHP_ESPI_IO_BAR_ID_UART1 0xC +#define MCHP_ESPI_IO_BAR_ID_EMI0 0xD +#define MCHP_ESPI_IO_BAR_ID_EMI1 0xE +#define MCHP_ESPI_IO_BAR_ID_EMI2 0xF +#define MCHP_ESPI_IO_BAR_P80_0 0x10 +#define MCHP_ESPI_IO_BAR_P80_1 0x11 +#define MCHP_ESPI_IO_BAR_RTC 0x12 + +/* Use with MCHP_ESPI_MBAR_EC_xxxx(x) macros */ +#define MCHP_ESPI_MBAR_ID_MBOX 0 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_0 1 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_1 2 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_2 3 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_3 4 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_4 5 +#define MCHP_ESPI_MBAR_ID_EMI_0 6 +#define MCHP_ESPI_MBAR_ID_EMI_1 7 +#define MCHP_ESPI_MBAR_ID_EMI_2 8 + +/* Use with MCHP_ESPI_IO_SERIRQ_REG(x) */ +#define MCHP_ESPI_SIRQ_MBOX 0 /* Host SIRQ */ +#define MCHP_ESPI_SIRQ_MBOX_SMI 1 /* Host SMI */ +#define MCHP_ESPI_SIRQ_8042_KB 2 /* KIRQ */ +#define MCHP_ESPI_SIRQ_8042_MS 3 /* MIRQ */ +#define MCHP_ESPI_SIRQ_ACPI_EC0_OBF 4 +#define MCHP_ESPI_SIRQ_ACPI_EC1_OBF 5 +#define MCHP_ESPI_SIRQ_ACPI_EC2_OBF 6 +#define MCHP_ESPI_SIRQ_ACPI_EC3_OBF 7 +#define MCHP_ESPI_SIRQ_ACPI_EC4_OBF 8 +#define MCHP_ESPI_SIRQ_UART0 9 +#define MCHP_ESPI_SIRQ_UART1 10 +#define MCHP_ESPI_SIRQ_EMI0_HEV 11 /* Host Event */ +#define MCHP_ESPI_SIRQ_EMI0_EC2H 12 /* EC to Host */ +#define MCHP_ESPI_SIRQ_EMI1_HEV 13 +#define MCHP_ESPI_SIRQ_EMI1_EC2H 14 +#define MCHP_ESPI_SIRQ_EMI2_HEV 15 +#define MCHP_ESPI_SIRQ_EMI2_EC2H 16 +#define MCHP_ESPI_SIRQ_RTC 17 +#define MCHP_ESPI_SIRQ_EC 18 + +#define MCHP_ESPI_MSVW_BASE (MCHP_ESPI_VW_BASE) +#define MCHP_ESPI_SMVW_BASE ((MCHP_ESPI_VW_BASE) + 0x200ul) + +/* + * eSPI RESET, channel enables and operations except Master-to-Slave + * WWires are all on GIRQ19 + */ +#define MCHP_ESPI_GIRQ 19 +#define MCHP_ESPI_PC_GIRQ_BIT BIT(0) +#define MCHP_ESPI_BM1_GIRQ_BIT BIT(1) +#define MCHP_ESPI_BM2_GIRQ_BIT BIT(2) +#define MCHP_ESPI_LTR_GIRQ_BIT BIT(3) +#define MCHP_ESPI_OOB_TX_GIRQ_BIT BIT(4) +#define MCHP_ESPI_OOB_RX_GIRQ_BIT BIT(5) +#define MCHP_ESPI_FC_GIRQ_BIT BIT(6) +#define MCHP_ESPI_RESET_GIRQ_BIT BIT(7) +#define MCHP_ESPI_VW_EN_GIRQ_BIT BIT(8) + +/* + * eSPI Master-to-Slave WWire interrupts are on GIRQ24 and GIRQ25 + */ +#define MCHP_ESPI_MSVW_0_6_GIRQ 24 +#define MCHP_ESPI_MSVW_7_10_GIRQ 25 +/* + * Four source bits, SRC[0:3] per Master-to-Slave register + * v = MSVW [0:10] + * n = VWire SRC bit = [0:3] + */ +#define MCHP_ESPI_MSVW_GIRQ(v) (24 + ((v) > 6 ? 1 : 0)) + +#define MCHP_ESPI_MSVW_SRC_GIRQ_BIT(v, n) \ + (((v) > 6) ? (1ul << (((v)-7) + (n))) : (1ul << ((v) + (n)))) + +/* DMA */ +#define MCHP_DMA_MAX_CHAN 14 +#define MCHP_DMA_CH_OFS 0x40 +#define MCHP_DMA_CH_OFS_BITPOS 6 +#define MCHP_DMA_CH_BASE (MCHP_DMA_BASE + MCHP_DMA_CH_OFS) + +/* + * Available DMA channels. + * + * On MCHP, any DMA channel may serve any device. Since we have + * 14 channels and 14 device request signals, we make each channel + * dedicated to the device of the same number. + */ +enum dma_channel { + /* Channel numbers */ + MCHP_DMAC_I2C0_SLAVE = 0, + MCHP_DMAC_I2C0_MASTER, + MCHP_DMAC_I2C1_SLAVE, + MCHP_DMAC_I2C1_MASTER, + MCHP_DMAC_I2C2_SLAVE, + MCHP_DMAC_I2C2_MASTER, + MCHP_DMAC_I2C3_SLAVE, + MCHP_DMAC_I2C3_MASTER, + MCHP_DMAC_SPI0_TX, + MCHP_DMAC_SPI0_RX, + MCHP_DMAC_SPI1_TX, + MCHP_DMAC_SPI1_RX, + MCHP_DMAC_QMSPI0_TX, + MCHP_DMAC_QMSPI0_RX, + /* Channel count */ + MCHP_DMAC_COUNT, +}; + +/* + * Peripheral device DMA Device ID's for bits [15:9] + * in DMA channel control register. + */ +#define MCHP_DMA_I2C0_SLV_REQ_ID 0 +#define MCHP_DMA_I2C0_MTR_REQ_ID 1 +#define MCHP_DMA_I2C1_SLV_REQ_ID 2 +#define MCHP_DMA_I2C1_MTR_REQ_ID 3 +#define MCHP_DMA_I2C2_SLV_REQ_ID 4 +#define MCHP_DMA_I2C2_MTR_REQ_ID 5 +#define MCHP_DMA_I2C3_SLV_REQ_ID 6 +#define MCHP_DMA_I2C3_MTR_REQ_ID 7 +#define MCHP_DMA_SPI0_TX_REQ_ID 8 +#define MCHP_DMA_SPI0_RX_REQ_ID 9 +#define MCHP_DMA_SPI1_TX_REQ_ID 10 +#define MCHP_DMA_SPI1_RX_REQ_ID 11 +#define MCHP_DMA_QMSPI0_TX_REQ_ID 12 +#define MCHP_DMA_QMSPI0_RX_REQ_ID 13 + +/* + * Hardware delay register. + * Write of 0 <= n <= 31 will stall the Cortex-M4 + * for n+1 microseconds. Interrupts will not be + * serviced during the delay period. Reads have + * no effect. + */ +#define MCHP_USEC_DELAY_REG_ADDR 0x10000000 +#define MCHP_USEC_DELAY(x) (REG8(MCHP_USEC_DELAY_REG_ADDR) = (x)) + +#endif /* #ifndef __ASSEMBLER__ */ diff --git a/chip/mchp/registers-mec172x.h b/chip/mchp/registers-mec172x.h new file mode 100644 index 0000000000..0bd010ac05 --- /dev/null +++ b/chip/mchp/registers-mec172x.h @@ -0,0 +1,1495 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Register map for Microchip MEC172x family controllers + */ + +#ifndef __CROS_EC_REGISTERS_H +#error "This header file should not be included directly." +#endif + +/* + * IRQ Numbers + * NOTE: GIRQ22 aggregated output and its sources are not connected to + * the NVIC. + */ +#define MCHP_IRQ_GIRQ8 0 +#define MCHP_IRQ_GIRQ9 1 +#define MCHP_IRQ_GIRQ10 2 +#define MCHP_IRQ_GIRQ11 3 +#define MCHP_IRQ_GIRQ12 4 +#define MCHP_IRQ_GIRQ13 5 +#define MCHP_IRQ_GIRQ14 6 +#define MCHP_IRQ_GIRQ15 7 +#define MCHP_IRQ_GIRQ16 8 +#define MCHP_IRQ_GIRQ17 9 +#define MCHP_IRQ_GIRQ18 10 +#define MCHP_IRQ_GIRQ19 11 +#define MCHP_IRQ_GIRQ20 12 +#define MCHP_IRQ_GIRQ21 13 +#define MCHP_IRQ_GIRQ23 14 +#define MCHP_IRQ_GIRQ24 15 +#define MCHP_IRQ_GIRQ25 16 +#define MCHP_IRQ_GIRQ26 17 +/* GIRQ13 direct sources */ +#define MCHP_IRQ_I2C_0 20 +#define MCHP_IRQ_I2C_1 21 +#define MCHP_IRQ_I2C_2 22 +#define MCHP_IRQ_I2C_3 23 +#define MCHP_IRQ_I2C_4 158 +/* GIRQ14 direct sources */ +#define MCHP_IRQ_DMA_0 24 +#define MCHP_IRQ_DMA_1 25 +#define MCHP_IRQ_DMA_2 26 +#define MCHP_IRQ_DMA_3 27 +#define MCHP_IRQ_DMA_4 28 +#define MCHP_IRQ_DMA_5 29 +#define MCHP_IRQ_DMA_6 30 +#define MCHP_IRQ_DMA_7 31 +#define MCHP_IRQ_DMA_8 32 +#define MCHP_IRQ_DMA_9 33 +#define MCHP_IRQ_DMA_10 34 +#define MCHP_IRQ_DMA_11 35 +#define MCHP_IRQ_DMA_12 36 +#define MCHP_IRQ_DMA_13 37 +#define MCHP_IRQ_DMA_14 38 +#define MCHP_IRQ_DMA_15 39 +/* GIRQ15 direct sources */ +#define MCHP_IRQ_UART0 40 +#define MCHP_IRQ_UART1 41 +#define MCHP_IRQ_EMI0 42 +#define MCHP_IRQ_EMI1 43 +#define MCHP_IRQ_EMI2 44 +#define MCHP_IRQ_ACPIEC0_IBF 45 +#define MCHP_IRQ_ACPIEC0_OBE 46 +#define MCHP_IRQ_ACPIEC1_IBF 47 +#define MCHP_IRQ_ACPIEC1_OBE 48 +#define MCHP_IRQ_ACPIEC2_IBF 49 +#define MCHP_IRQ_ACPIEC2_OBE 50 +#define MCHP_IRQ_ACPIEC3_IBF 51 +#define MCHP_IRQ_ACPIEC3_OBE 52 +#define MCHP_IRQ_ACPIEC4_IBF 53 +#define MCHP_IRQ_ACPIEC4_OBE 54 +#define MCHP_IRQ_ACPIPM1_CTL 55 +#define MCHP_IRQ_ACPIPM1_EN 56 +#define MCHP_IRQ_ACPIPM1_STS 57 +#define MCHP_IRQ_8042EM_OBE 58 +#define MCHP_IRQ_8042EM_IBF 59 +#define MCHP_IRQ_MAILBOX_DATA 60 +#define MCHP_IRQ_BDP0 62 +/* GIRQ16 direct sources */ +#define MCHP_IRQ_PKE 65 +#define MCHP_IRQ_NDRNG 67 +#define MCHP_IRQ_AESH 68 +/* GIRQ17 direct sources */ +#define MCHP_IRQ_PECI_HOST 70 +#define MCHP_IRQ_TACH_0 71 +#define MCHP_IRQ_TACH_1 72 +#define MCHP_IRQ_TACH_2 73 +#define MCHP_IRQ_TACH_3 159 +#define MCHP_IRQ_FAN0_FAIL 74 +#define MCHP_IRQ_FAN0_STALL 75 +#define MCHP_IRQ_FAN1_FAIL 76 +#define MCHP_IRQ_FAN1_STALL 77 +#define MCHP_IRQ_ADC_SNGL 78 +#define MCHP_IRQ_ADC_RPT 79 +#define MCHP_IRQ_RCID0 80 +#define MCHP_IRQ_RCID1 81 +#define MCHP_IRQ_RCID2 82 +#define MCHP_IRQ_LED0_WDT 83 +#define MCHP_IRQ_LED1_WDT 84 +#define MCHP_IRQ_LED2_WDT 85 +#define MCHP_IRQ_LED3_WDT 86 +#define MCHP_IRQ_PHOT 87 +/* GIRQ18 direct sources */ +#define MCHP_IRQ_SLAVE_SPI 90 +#define MCHP_IRQ_QMSPI0 91 +#define MCHP_IRQ_SPI0_TX 92 +#define MCHP_IRQ_SPI0_RX 93 +#define MCHP_IRQ_SPI1_TX 94 +#define MCHP_IRQ_SPI1_RX 95 +#define MCHP_IRQ_BCM0_ERR 96 +#define MCHP_IRQ_BCM0_BUSY 97 +#define MCHP_IRQ_PS2_0 100 +#define MCHP_IRQ_EEPROM 155 +#define MCHP_IRQ_CCT_TMR 146 +#define MCHP_IRQ_CCT_CAP0 147 +#define MCHP_IRQ_CCT_CAP1 148 +#define MCHP_IRQ_CCT_CAP2 149 +#define MCHP_IRQ_CCT_CAP3 150 +#define MCHP_IRQ_CCT_CAP4 151 +#define MCHP_IRQ_CCT_CAP5 152 +#define MCHP_IRQ_CCT_CMP0 153 +#define MCHP_IRQ_CCT_CMP1 154 +/* GIRQ19 direct sources */ +#define MCHP_IRQ_ESPI_PC 103 +#define MCHP_IRQ_ESPI_BM1 104 +#define MCHP_IRQ_ESPI_BM2 105 +#define MCHP_IRQ_ESPI_LTR 106 +#define MCHP_IRQ_ESPI_OOB_UP 107 +#define MCHP_IRQ_ESPI_OOB_DN 108 +#define MCHP_IRQ_ESPI_FC 109 +#define MCHP_IRQ_ESPI_RESET 110 +#define MCHP_IRQ_ESPI_VW_EN 156 +#define MCHP_IRQ_ESPI_SAF_DONE 166 +#define MCHP_IRQ_ESPI_SAF_ERR 166 +#define MCHP_IRQ_ESPI_SAF_CACHE 169 +/* GIRQ20 direct sources */ +#define MCHP_IRQ_OTP 173 +#define MCHP_IRQ_CLK32K_MON 174 +/* GIRQ21 direct sources */ +#define MCHP_IRQ_WDG 171 +#define MCHP_IRQ_WEEK_ALARM 114 +#define MCHP_IRQ_SUBWEEK 115 +#define MCHP_IRQ_WEEK_SEC 116 +#define MCHP_IRQ_WEEK_SUBSEC 117 +#define MCHP_IRQ_WEEK_SYSPWR 118 +#define MCHP_IRQ_RTC 119 +#define MCHP_IRQ_RTC_ALARM 120 +#define MCHP_IRQ_VCI_OVRD_IN 121 +#define MCHP_IRQ_VCI_IN0 122 +#define MCHP_IRQ_VCI_IN1 123 +#define MCHP_IRQ_VCI_IN2 124 +#define MCHP_IRQ_VCI_IN3 125 +#define MCHP_IRQ_VCI_IN4 126 +#define MCHP_IRQ_PS20A_WAKE 129 +#define MCHP_IRQ_PS20B_WAKE 130 +#define MCHP_IRQ_KSC_INT 135 +#define MCHP_IRQ_GLUE 172 +/* GIRQ23 direct sources */ +#define MCHP_IRQ_TIMER16_0 136 +#define MCHP_IRQ_TIMER16_1 137 +#define MCHP_IRQ_TIMER16_2 138 +#define MCHP_IRQ_TIMER16_3 139 +#define MCHP_IRQ_TIMER32_0 140 +#define MCHP_IRQ_TIMER32_1 141 +#define MCHP_IRQ_CNTR_TM0 142 +#define MCHP_IRQ_CNTR_TM1 143 +#define MCHP_IRQ_CNTR_TM2 144 +#define MCHP_IRQ_CNTR_TM3 145 +#define MCHP_IRQ_RTOS_TIMER 111 +#define MCHP_IRQ_HTIMER0 112 +#define MCHP_IRQ_HTIMER1 113 +/* Must match CONFIG_IRQ_COUNT in config_chip.h */ +#define MCHP_IRQ_MAX 180 + +/* Block base addresses */ +#define MCHP_WDG_BASE 0x40000400 +#define MCHP_TMR16_0_BASE 0x40000c00 +#define MCHP_TMR32_0_BASE 0x40000c80 +#define MCHP_CNT16_0_BASE 0x40000d00 +#define MCHP_DMA_BASE 0x40002400 +#define MCHP_PROCHOT_BASE 0x40003400 +#define MCHP_I2C0_BASE 0x40004000 +#define MCHP_I2C1_BASE 0x40004400 +#define MCHP_I2C2_BASE 0x40004800 +#define MCHP_I2C3_BASE 0x40004C00 +#define MCHP_I2C4_BASE 0x40005000 +#define MCHP_CACHE_CTRL_BASE 0x40005400 +#define MCHP_PWM_0_BASE 0x40005800 +#define MCHP_TACH_0_BASE 0x40006000 +#define MCHP_PECI_BASE 0x40006400 +#define MCHP_SPIEP_BASE 0x40007000 +#define MCHP_RTMR_BASE 0x40007400 +#define MCHP_ADC_BASE 0x40007c00 +#define MCHP_ESPI_SAF_BASE 0x40008000 +#define MCHP_TFDP_BASE 0x40008c00 +#define MCHP_GPSPI0_BASE 0x40009400 +#define MCHP_GPSPI1_BASE 0x40009480 +#define MCHP_HTIMER_BASE 0x40009800 +#define MCHP_KEYSCAN_BASE 0x40009c00 +#define MCHP_RPM2PWM0_BASE 0x4000a000 +#define MCHP_RPM2PWM1_BASE 0x4000a080 +#define MCHP_VBAT_BASE 0x4000a400 +#define MCHP_VBAT_RAM_BASE 0x4000a800 +#define MCHP_WKTIMER_BASE 0x4000ac80 +#define MCHP_VCI_BASE 0x4000ae00 +#define MCHP_BBLED_0_BASE 0x4000B800 +#define MCHP_BCL_0_BASE 0x4000cd00 +#define MCHP_INT_BASE 0x4000e000 +#define MCHP_EC_BASE 0x4000fc00 + +#define MCHP_QMSPI0_BASE 0x40070000 +#define MCHP_ESPI_SAF_COMM_BASE 0x40071000 + +#define MCHP_PCR_BASE 0x40080100 +#define MCHP_GPIO_BASE 0x40081000 +#define MCHP_OTP_BASE 0x40082000 + +#define MCHP_MBOX_BASE 0x400f0000 +#define MCHP_8042_BASE 0x400f0400 +#define MCHP_ACPI_EC_0_BASE 0x400f0800 +#define MCHP_ACPI_PM1_BASE 0x400f1c00 +#define MCHP_PORT92_BASE 0x400f2000 +#define MCHP_UART0_BASE 0x400f2400 +#define MCHP_UART1_BASE 0x400f2800 +#define MCHP_LPC_BASE 0x400f3000 +#define MCHP_ESPI_IO_BASE 0x400f3400 +#define MCHP_ESPI_MEM_BASE 0x400f3800 +#define MCHP_GLUE_BASE 0x400f3c00 +#define MCHP_EMI_0_BASE 0x400f4000 +#define MCHP_EMI_1_BASE 0x400f4400 +#define MCHP_EMI_2_BASE 0x400f4800 +#define MCHP_RTC_BASE 0x400f5000 +#define MCHP_BDP0_BASE 0x400f8000 +#define MCHP_ESPI_VW_BASE 0x400f9c00 +#define MCHP_CHIP_BASE 0x400fff00 + +#ifndef __ASSEMBLER__ + +/* + * Helper function for RAM address aliasing + * NOTE: MEC17xx and MEC15xx AHB controllers do NOT require aliasing. + * Cortex-M4 bit-banding does require aliasing of the + * DATA SRAM region. + */ +#define MCHP_RAM_ALIAS(x) ((x) >= 0x118000 ? (x)-0x118000 + 0x20000000 : (x)) + +/* EC Chip Configuration */ +/* 16-bit Device ID */ +#define MCHP_CHIP_DEV_ID REG16(MCHP_CHIP_BASE + 0x1E) +/* 8-bit Device Sub ID */ +#define MCHP_CHIP_DEV_SUB_ID REG8(MCHP_CHIP_BASE + 0x1D) +/* 8-bit Device Revision */ +#define MCHP_CHIP_DEV_REV REG8(MCHP_CHIP_BASE + 0x1C) +/* All in one */ +#define MCHP_CHIP_DEVRID32 REG32(MCHP_CHIP_BASE + 0x1C) +#define MCHP_CHIP_DEVID_POS 16 +#define MCHP_CHIP_DEVID_MASK (0xfffful << MCHP_CHIP_DEVID_POS) +#define MCHP_CHIP_SUBID_POS 8 +#define MCHP_CHIP_SUBID_MASK (0xfful << MCHP_CHIP_SUBID_POS) +#define MCHP_CHIP_REV_POS 0 +#define MCHP_CHIP_REV_MASK (0xfful << MCHP_CHIP_REV_POS) +#define MCHP_CHIP_EXTRACT_DEVID(d) \ + (((uint32_t)(d)&MCHP_CHIP_DEVID_MASK) >> MCHP_CHIP_DEVID_POS) +#define MCHP_CHIP_EXTRACT_SUBID(d) \ + (((uint32_t)(d)&MCHP_CHIP_SUBID_MASK) >> MCHP_CHIP_SUBID_POS) +#define MCHP_CHIP_EXTRACT_REV(d) \ + (((uint32_t)(d)&MCHP_CHIP_REV_MASK) >> MCHP_CHIP_REV_POS) + +/* PCR clock control dividers */ +#define MCHP_PCR_CLK_CTL_FASTEST 1U +#define MCHP_PCR_CLK_CTL_96MHZ 1U +#define MCHP_PCR_CLK_CTL_48MHZ 2U +#define MCHP_PCR_CLK_CTL_24MHZ 4U +#define MCHP_PCR_CLK_CTL_12MHZ 8U + +/* Number of PCR Sleep Enable, Clock Required, and Reset registers */ +#define MCHP_PCR_SLP_RST_REG_MAX 5 + +/* Sleep 0: Sleep Enable, Clock Required, and Reset bits */ +#define MCHP_PCR_JTAG BIT(0) /* CLKREQ only */ +#define MCHP_PCR_OTP BIT(1) +#define MCHP_PCR_ISPI BIT(2) + +/* Command all blocks to sleep */ +#define MCHP_PCR_SLP_EN0_JTAG BIT(0) +#define MCHP_PCR_SLP_EN0_OTP BIT(1) +#define MCHP_PCR_SLP_EN0_ISPI BIT(2) +#define MCHP_PCR_SLP_EN0_SLEEP 0xffffffff + +/* + * Encode register number and bit position + * b[4:0] = bit number + * b[10:8] = zero based register number + */ +#define MCHP_PCR_ERB(rnum, bnum) ((((rnum)&0x0f) << 8) | ((bnum)&0x1f)) + +/* PCR Sleep 1: Sleep Enable, Clock Required, and Reset bits */ +#define MCHP_PCR_BTMR16_1 MCHP_PCR_ERB(1, 31) +#define MCHP_PCR_BTMR16_0 MCHP_PCR_ERB(1, 30) +#define MCHP_PCR_ECS MCHP_PCR_ERB(1, 29) +#define MCHP_PCR_PWM8 MCHP_PCR_ERB(1, 27) +#define MCHP_PCR_PWM7 MCHP_PCR_ERB(1, 26) +#define MCHP_PCR_PWM6 MCHP_PCR_ERB(1, 25) +#define MCHP_PCR_PWM5 MCHP_PCR_ERB(1, 24) +#define MCHP_PCR_PWM4 MCHP_PCR_ERB(1, 23) +#define MCHP_PCR_PWM3 MCHP_PCR_ERB(1, 22) +#define MCHP_PCR_PWM2 MCHP_PCR_ERB(1, 21) +#define MCHP_PCR_PWM1 MCHP_PCR_ERB(1, 20) +#define MCHP_PCR_TACH3 MCHP_PCR_ERB(1, 13) +#define MCHP_PCR_TACH2 MCHP_PCR_ERB(1, 12) +#define MCHP_PCR_TACH1 MCHP_PCR_ERB(1, 11) +#define MCHP_PCR_I2C0 MCHP_PCR_ERB(1, 10) +#define MCHP_PCR_WDT MCHP_PCR_ERB(1, 9) +#define MCHP_PCR_CPU MCHP_PCR_ERB(1, 8) +#define MCHP_PCR_TFDP MCHP_PCR_ERB(1, 7) +#define MCHP_PCR_DMA MCHP_PCR_ERB(1, 6) +#define MCHP_PCR_PMC MCHP_PCR_ERB(1, 5) +#define MCHP_PCR_PWM0 MCHP_PCR_ERB(1, 4) +#define MCHP_PCR_TACH0 MCHP_PCR_ERB(1, 2) +#define MCHP_PCR_PECI MCHP_PCR_ERB(1, 1) +#define MCHP_PCR_ECIA MCHP_PCR_ERB(1, 0) + +/* Command all blocks to sleep */ +#define MCHP_PCR_SLP_EN1_BTMR16_1 BIT(31) +#define MCHP_PCR_SLP_EN1_BTMR16_0 BIT(30) +#define MCHP_PCR_SLP_EN1_ECS BIT(29) +#define MCHP_PCR_SLP_EN1_PWM_ALL \ + (BIT(4) | BIT(20) | BIT(21) | BIT(22) | BIT(23) | BIT(24) | BIT(25) | \ + BIT(26) | BIT(27)) +#define MCHP_PCR_SLP_EN1_PWM8 BIT(27) +#define MCHP_PCR_SLP_EN1_PWM7 BIT(26) +#define MCHP_PCR_SLP_EN1_PWM6 BIT(25) +#define MCHP_PCR_SLP_EN1_PWM5 BIT(24) +#define MCHP_PCR_SLP_EN1_PWM4 BIT(23) +#define MCHP_PCR_SLP_EN1_PWM3 BIT(22) +#define MCHP_PCR_SLP_EN1_PWM2 BIT(21) +#define MCHP_PCR_SLP_EN1_PWM1 BIT(20) +#define MCHP_PCR_SLP_EN1_TACH3 BIT(13) +#define MCHP_PCR_SLP_EN1_TACH2 BIT(12) +#define MCHP_PCR_SLP_EN1_TACH1 BIT(11) +#define MCHP_PCR_SLP_EN1_I2C0 BIT(10) +#define MCHP_PCR_SLP_EN1_WDT BIT(9) +#define MCHP_PCR_SLP_EN1_CPU BIT(8) +#define MCHP_PCR_SLP_EN1_TFDP BIT(7) +#define MCHP_PCR_SLP_EN1_DMA BIT(6) +#define MCHP_PCR_SLP_EN1_PMC BIT(5) +#define MCHP_PCR_SLP_EN1_PWM0 BIT(4) +#define MCHP_PCR_SLP_EN1_TACH0 BIT(2) +#define MCHP_PCR_SLP_EN1_PECI BIT(1) +#define MCHP_PCR_SLP_EN1_ECIA BIT(0) +/* all sleep enable 1 bits */ +#define MCHP_PCR_SLP_EN1_SLEEP 0xffffffff +/* + * block not used by default + * Do not sleep ECIA, PMC, CPU and ECS + */ +#define MCHP_PCR_SLP_EN1_UNUSED_BLOCKS 0xdffffede + +/* PCR Sleep 2: Sleep Enable, Clock Required 2, Reset bits */ +#define MCHP_PCR_GLUE MCHP_PCR_ERB(2, 29) +#define MCHP_PCR_SAF MCHP_PCR_ERB(2, 27) +#define MCHP_PCR_BDP0 MCHP_PCR_ERB(2, 25) +#define MCHP_PCR_ACPI_EC4 MCHP_PCR_ERB(2, 23) +#define MCHP_PCR_ACPI_EC3 MCHP_PCR_ERB(2, 22) +#define MCHP_PCR_ACPI_EC2 MCHP_PCR_ERB(2, 21) +#define MCHP_PCR_ESPI_SCR MCHP_PCR_ERB(2, 20) +#define MCHP_PCR_ESPI MCHP_PCR_ERB(2, 19) +#define MCHP_PCR_RTC MCHP_PCR_ERB(2, 18) +#define MCHP_PCR_MBOX MCHP_PCR_ERB(2, 17) +#define MCHP_PCR_8042 MCHP_PCR_ERB(2, 16) +#define MCHP_PCR_ACPI_PM1 MCHP_PCR_ERB(2, 15) +#define MCHP_PCR_ACPI_EC1 MCHP_PCR_ERB(2, 14) +#define MCHP_PCR_ACPI_EC0 MCHP_PCR_ERB(2, 13) +#define MCHP_PCR_GCFG MCHP_PCR_ERB(2, 12) +#define MCHP_PCR_UART1 MCHP_PCR_ERB(2, 2) +#define MCHP_PCR_UART0 MCHP_PCR_ERB(2, 1) +#define MCHP_PCR_EMI0 MCHP_PCR_ERB(2, 0) + +/* Command all blocks to sleep */ +#define MCHP_PCR_SLP_EN2_GLUE BIT(29) +#define MCHP_PCR_SLP_EN2_SAF BIT(27) +#define MCHP_PCR_SLP_EN2_BDP0 BIT(25) +#define MCHP_PCR_SLP_EN2_ACPI_EC4 BIT(23) +#define MCHP_PCR_SLP_EN2_ACPI_EC3 BIT(22) +#define MCHP_PCR_SLP_EN2_ACPI_EC2 BIT(21) +#define MCHP_PCR_SLP_EN2_ESPI_SCR BIT(20) +#define MCHP_PCR_SLP_EN2_ESPI BIT(19) +#define MCHP_PCR_SLP_EN2_RTC BIT(18) +#define MCHP_PCR_SLP_EN2_MAILBOX BIT(17) +#define MCHP_PCR_SLP_EN2_MIF8042 BIT(16) +#define MCHP_PCR_SLP_EN2_ACPI_PM1 BIT(15) +#define MCHP_PCR_SLP_EN2_ACPI_EC1 BIT(14) +#define MCHP_PCR_SLP_EN2_ACPI_EC0 BIT(13) +#define MCHP_PCR_SLP_EN2_GCFG BIT(12) +#define MCHP_PCR_SLP_EN2_UART1 BIT(2) +#define MCHP_PCR_SLP_EN2_UART0 BIT(1) +#define MCHP_PCR_SLP_EN2_EMI0 BIT(0) +/* all sleep enable 2 bits */ +#define MCHP_PCR_SLP_EN2_SLEEP 0xffffffff + +/* PCR Sleep 3: Sleep Enable, Clock Required, and Reset */ +#define MCHP_PCR_PWM9 MCHP_PCR_ERB(3, 31) +#define MCHP_PCR_CCT0 MCHP_PCR_ERB(3, 30) +#define MCHP_PCR_HTMR1 MCHP_PCR_ERB(3, 29) +#define MCHP_PCR_CRYPTO MCHP_PCR_ERB(3, 26) +#define MCHP_PCR_LED3 MCHP_PCR_ERB(3, 25) +#define MCHP_PCR_BTMR32_1 MCHP_PCR_ERB(3, 24) +#define MCHP_PCR_BTMR32_0 MCHP_PCR_ERB(3, 23) +#define MCHP_PCR_BTMR16_3 MCHP_PCR_ERB(3, 22) +#define MCHP_PCR_BTMR16_2 MCHP_PCR_ERB(3, 21) +#define MCHP_PCR_I2C4 MCHP_PCR_ERB(3, 20) +#define MCHP_PCR_BCM0 MCHP_PCR_ERB(3, 19) +#define MCHP_PCR_LED2 MCHP_PCR_ERB(3, 18) +#define MCHP_PCR_LED1 MCHP_PCR_ERB(3, 17) +#define MCHP_PCR_LED0 MCHP_PCR_ERB(3, 16) +#define MCHP_PCR_I2C3 MCHP_PCR_ERB(3, 15) +#define MCHP_PCR_I2C2 MCHP_PCR_ERB(3, 14) +#define MCHP_PCR_I2C1 MCHP_PCR_ERB(3, 13) +#define MCHP_PCR_RPMPWM0 MCHP_PCR_ERB(3, 12) +#define MCHP_PCR_KEYSCAN MCHP_PCR_ERB(3, 11) +#define MCHP_PCR_HTMR0 MCHP_PCR_ERB(3, 10) +#define MCHP_PCR_GPSPI0 MCHP_PCR_ERB(3, 9) +#define MCHP_PCR_PS2_0 MCHP_PCR_ERB(3, 5) +#define MCHP_PCR_ADC MCHP_PCR_ERB(3, 3) + +/* Command blocks to sleep */ +#define MCHP_PCR_SLP_EN3_PWM9 BIT(31) +#define MCHP_PCR_SLP_EN3_CCT0 BIT(30) +#define MCHP_PCR_SLP_EN3_HTMR1 BIT(29) +#define MCHP_PCR_SLP_EN3_CRYPTO BIT(26) +#define MCHP_PCR_SLP_EN3_LED3 BIT(25) +#define MCHP_PCR_SLP_EN3_BTMR32_1 BIT(24) +#define MCHP_PCR_SLP_EN3_BTMR32_0 BIT(23) +#define MCHP_PCR_SLP_EN3_BTMR16_3 BIT(22) +#define MCHP_PCR_SLP_EN3_BTMR16_2 BIT(21) +#define MCHP_PCR_SLP_EN3_I2C4 BIT(20) +#define MCHP_PCR_SLP_EN3_BCM0 BIT(19) +#define MCHP_PCR_SLP_EN3_LED2 BIT(18) +#define MCHP_PCR_SLP_EN3_LED1 BIT(17) +#define MCHP_PCR_SLP_EN3_LED0 BIT(16) +#define MCHP_PCR_SLP_EN3_I2C3 BIT(15) +#define MCHP_PCR_SLP_EN3_I2C2 BIT(14) +#define MCHP_PCR_SLP_EN3_I2C1 BIT(13) +#define MCHP_PCR_SLP_EN3_RPM2PWM0 BIT(12) +#define MCHP_PCR_SLP_EN3_KEYSCAN BIT(11) +#define MCHP_PCR_SLP_EN3_HTMR0 BIT(10) +#define MCHP_PCR_SLP_EN3_GPSPI0 BIT(9) +#define MCHP_PCR_SLP_EN3_PS2_0 BIT(5) +#define MCHP_PCR_SLP_EN3_ADC BIT(3) +#define MCHP_PCR_SLP_EN3_ALL_CRYPTO BIT(26) +/* all sleep enable 3 bits */ +#define MCHP_PCR_SLP_EN3_SLEEP 0xffffffff +#define MCHP_PCR_SLP_EN3_PWM_ALL (MCHP_PCR_SLP_EN3_PWM9) + +/* PCR Sleep 4: Sleep Enable, Clock Required, Reset */ +#define MCHP_PCR_GPSPI1 MCHP_PCR_ERB(4, 22) +#define MCHP_PCR_PSPI MCHP_PCR_ERB(4, 14) +#define MCHP_PCR_PROCHOT MCHP_PCR_ERB(4, 13) +#define MCHP_PCR_RCID2 MCHP_PCR_ERB(4, 12) +#define MCHP_PCR_RCID1 MCHP_PCR_ERB(4, 11) +#define MCHP_PCR_RCID0 MCHP_PCR_ERB(4, 10) +#define MCHP_PCR_QMSPI MCHP_PCR_ERB(4, 8) +#define MCHP_PCR_RPMPWM1 MCHP_PCR_ERB(4, 7) +#define MCHP_PCR_RTMR MCHP_PCR_ERB(4, 6) +#define MCHP_PCR_CNT16_3 MCHP_PCR_ERB(4, 5) +#define MCHP_PCR_CNT16_2 MCHP_PCR_ERB(4, 4) +#define MCHP_PCR_CNT16_1 MCHP_PCR_ERB(4, 3) +#define MCHP_PCR_CNT16_0 MCHP_PCR_ERB(4, 2) +#define MCHP_PCR_PWM11 MCHP_PCR_ERB(4, 1) +#define MCHP_PCR_PWM10 MCHP_PCR_ERB(4, 0) + +/* Command blocks to sleep */ +#define MCHP_PCR_SLP_EN4_GPSPI1 BIT(22) +#define MCHP_PCR_SLP_EN4_PSPI BIT(14) +#define MCHP_PCR_SLP_EN4_PROCHOT BIT(13) +#define MCHP_PCR_SLP_EN4_RCID2 BIT(12) +#define MCHP_PCR_SLP_EN4_RCID1 BIT(11) +#define MCHP_PCR_SLP_EN4_RCID0 BIT(10) +#define MCHP_PCR_SLP_EN4_QMSPI BIT(8) +#define MCHP_PCR_SLP_EN4_RPMPWM1 BIT(7) +#define MCHP_PCR_SLP_EN4_RTMR BIT(6) +#define MCHP_PCR_SLP_EN4_CNT16_3 BIT(5) +#define MCHP_PCR_SLP_EN4_CNT16_2 BIT(4) +#define MCHP_PCR_SLP_EN4_CNT16_1 BIT(3) +#define MCHP_PCR_SLP_EN4_CNT16_0 BIT(2) +#define MCHP_PCR_SLP_EN4_PWM11 BIT(1) +#define MCHP_PCR_SLP_EN4_PWM10 BIT(0) + +/* all sleep enable 4 bits */ +#define MCHP_PCR_SLP_EN4_SLEEP 0xffffffff +#define MCHP_PCR_SLP_EN4_PWM_ALL \ + (MCHP_PCR_SLP_EN4_PWM10 | MCHP_PCR_SLP_EN4_PWM11) + +/* Allow all blocks to request clocks */ +#define MCHP_PCR_SLP_EN0_WAKE (~(MCHP_PCR_SLP_EN0_SLEEP)) +#define MCHP_PCR_SLP_EN1_WAKE (~(MCHP_PCR_SLP_EN1_SLEEP)) +#define MCHP_PCR_SLP_EN2_WAKE (~(MCHP_PCR_SLP_EN2_SLEEP)) +#define MCHP_PCR_SLP_EN3_WAKE (~(MCHP_PCR_SLP_EN3_SLEEP)) +#define MCHP_PCR_SLP_EN4_WAKE (~(MCHP_PCR_SLP_EN4_SLEEP)) + +/* Bit defines for MCHP_PCR_PWR_RST_STS */ +#define MCHP_PWR_RST_STS_MASK_RO 0xc8c +#define MCHP_PWR_RST_STS_MASK_RWC 0x170 +#define MCHP_PWR_RST_STS_MASK \ + ((MCHP_PWR_RST_STS_MASK_RO) | (MCHP_PWR_RST_STS_MASK_RWC)) + +#define MCHP_PWR_RST_STS_ESPI_CLK_ACT BIT(11) /* RO */ +#define MCHP_PWR_RST_STS_32K_ACT BIT(10) /* RO */ +#define MCHP_PWR_RST_STS_WDT BIT(8) /* R/WC */ +#define MCHP_PWR_RST_STS_JTAG_RSTN BIT(7) /* RO */ +#define MCHP_PWR_RST_STS_SYS BIT(6) /* R/WC */ +#define MCHP_PWR_RST_STS_VBAT BIT(5) /* R/WC */ +#define MCHP_PWR_RST_STS_VTR BIT(4) /* R/WC */ +#define MCHP_PWR_RST_STS_HOST BIT(3) /* RO */ +#define MCHP_PWR_RST_STS_VCC_PWRGD BIT(2) /* RO */ + +/* Bit defines for MCHP_PCR_PWR_RST_CTL */ +#define MCHP_PCR_PWR_HOST_RST_SEL_BITPOS 8 +#define MCHP_PCR_PWR_HOST_RST_PCI_RESET BIT(8) +#define MCHP_PCR_PWR_HOST_RST_ESPI_PLTRST 0 +#define MCHP_PCR_PWR_OK_INV_BITPOS 0 + +/* Bit defines for MCHP_PCR_SYS_RST */ +#define MCHP_PCR_SYS_SOFT_RESET BIT(8) + +/* + * PCR Peripheral Reset Lock register + * MEC152x PCR Peripheral reset registers do not reset on + * peripheral sleep. The peripheral is reset immediately. + * Firmware must write an unlock value to this new lock + * register, write to PCR reset enable register(s), and + * write a lock value. + */ +#define MCHP_PCR_RST_LOCK REG32(MCHP_PCR_BASE + 0x84) +#define MCHP_PCR_RST_LOCK_VAL 0xa6382d4d +#define MCHP_PCR_RST_UNLOCK_VAL 0xa6382d4c + +/* PCR VBAT soft reset. Trigger a VBAT reset */ +#define MCHP_PCR_VBAT_SRST REG32(MCHP_PCR_BASE + 0x88) +#define MCHP_PCR_VBAT_SRST_EN BIT(0) + +/* PCR 32KHz clock source select */ +#define MCHP_PCR_CK32_SS REG32(MCHP_PCR_BASE + 0x8c) +#define MCHP_PCR_CK32_SEL_MASK GENMASK(1, 0) +#define MCHP_PCR_CK32_SEL_SIL 0 +#define MCHP_PCR_CK32_SEL_XTAL 1 +#define MCHP_PCR_CK32_SEL_PIN 2 +#define MCHP_PCR_CK32_SEL_OFF 3 + +/* PCR 32KHz period count (RO) */ +#define MCHP_PCR_CK32_PER_CNT REG32(MCHP_PCR_BASE + 0xc0) +#define MCHP_PCR_CD32_PER_CNT_MSK GENMASK(15, 0) + +/* PCR 32KHz high pulse count (RO) */ +#define MCHP_PCR_CK32_HP_CNT REG32(MCHP_PCR_BASE + 0xc4) +#define MCHP_PCR_CK32_HP_CNT_MSK GENMASK(15, 0) + +/* PCR 32KHz minimum acceptable period count */ +#define MCHP_PCR_CK32_MIN_PER_CNT REG32(MCHP_PCR_BASE + 0xc8) +#define MCHP_PCR_CK32_MIN_PER_CNT_MSK GENMASK(15, 0) + +/* PCR 32KHz maximum acceptable period count */ +#define MCHP_PCR_CK32_MAX_PER_CNT REG32(MCHP_PCR_BASE + 0xcc) +#define MCHP_PCR_CK32_MAX_PER_CNT_MSK GENMASK(15, 0) + +/* PCR 32KHz duty cycle variation count (RO) */ +#define MCHP_PCR_CK32_DC_VAR_CNT REG32(MCHP_PCR_BASE + 0xd0) +#define MCHP_PCR_CK32_DC_VAR_CNT_MSK GENMASK(15, 0) + +/* PCR 32KHz duty cycle variation acceptable maximum */ +#define MCHP_PCR_CK32_DC_VAR_MAX REG32(MCHP_PCR_BASE + 0xd4) +#define MCHP_PCR_CK32_DC_VAR_MAX_MSK GENMASK(15, 0) + +/* PCR 32KHz valid count */ +#define MCHP_PCR_CK32_VAL_CNT REG32(MCHP_PCR_BASE + 0xd8) +#define MCHP_PCR_CK32_VAL_CNT_MSK GENMASK(7, 0) + +/* PCR 32KHz valid count minimum */ +#define MCHP_PCR_CK32_MIN_VAL_CNT REG32(MCHP_PCR_BASE + 0xdc) +#define MCHP_PCR_CK32_MIN_VAL_CNT_MSK GENMASK(7, 0) + +/* PCR 32KHz control */ +#define MCHP_PCR_CK32_CTRL REG32(MCHP_PCR_BASE + 0xe0) +#define MCHP_PCR_CK32_CTRL_MSK (GENMASK(2, 0) | BIT(4) | BIT(24)) +#define MCHP_PCR_CK32_CTRL_PER_EN BIT(0) +#define MCHP_PCR_CK32_CTRL_DC_EN BIT(1) +#define MCHP_PCR_CK32_CTRL_VAL_EN BIT(2) +#define MCHP_PCR_CK32_CTRL_SRC_SIL BIT(3) +#define MCHP_PCR_CK32_CTRL_CLR_CNT BIT(24) + +/* PCR 32KHz interrupt status */ +#define MCHP_PCR_CK32_INTR_STS REG8(MCHP_PCR_BASE + 0xe4) +/* PCR 32KHz interrupt enable */ +#define MCHP_PCR_CK32_INTR_EN REG8(MCHP_PCR_BASE + 0xe8) +#define MCHP_PCR_CK32_INTR_PULSE_RDY BIT(0) +#define MCHP_PCR_CK32_INTR_PASS_PER BIT(1) +#define MCHP_PCR_CK32_INTR_PASS_DUTY BIT(2) +#define MCHP_PCR_CK32_INTR_FAIL BIT(3) +#define MCHP_PCR_CK32_INTR_STALL BIT(4) +#define MCHP_PCR_CK32_INTR_VALID BIT(5) +#define MCHP_PCR_CK32_INTR_UNWELL BIT(6) + +/* EC Subsystem */ +#define MCHP_EC_AHB_ERR REG32(MCHP_EC_BASE + 0x04) +#define MCHP_EC_ID_RO REG32(MCHP_EC_BASE + 0x10) +#define MCHP_EC_AHB_ERR_EN REG32(MCHP_EC_BASE + 0x14) +#define MCHP_EC_INT_CTRL REG32(MCHP_EC_BASE + 0x18) +#define MCHP_EC_TRACE_EN REG32(MCHP_EC_BASE + 0x1c) +#define MCHP_EC_JTAG_EN REG32(MCHP_EC_BASE + 0x20) +#define MCHP_EC_WDT_CNT REG32(MCHP_EC_BASE + 0x28) +#define MCHP_EC_PECI_DISABLE REG8(MCHP_EC_BASE + 0x40) +#define MCHP_EC_VCI_FW_OVRD REG32(MCHP_EC_BASE + 0x50) +#define MCHP_EC_BROM_STS REG32(MCHP_EC_BASE + 0x54) +#define MCHP_EC_VW_SRC_CFG REG32(MCHP_EC_BASE + 0x90) +#define MCHP_EC_CMP_CTRL REG32(MCHP_EC_BASE + 0x94) +#define MCHP_EC_CMP_SLP_CTRL REG32(MCHP_EC_BASE + 0x98) + +/* AHB ERR Disable bit[0]=0(enable), 1(disable) */ +#define MCHP_EC_AHB_ERROR_ENABLE 0 +#define MCHP_EC_AHB_ERROR_DISABLE 1 + +/* MCHP_EC_JTAG_EN bit definitions */ +#define MCHP_JTAG_ENABLE 0x01 +/* bits [2:1] */ +#define MCHP_JTAG_MODE_4PIN 0x00 +/* ARM 2-pin SWD plus 1-pin Serial Wire Viewer (ITM) */ +#define MCHP_JTAG_MODE_SWD_SWV 0x02 +/* ARM 2-pin SWD with no SWV */ +#define MCHP_JTAG_MODE_SWD 0x04 + +/* EC Interrupt aggregator (ECIA) */ +#define MCHP_INT_GIRQ_LEN 20 /* 5 32-bit registers */ +#define MCHP_INT_GIRQ_FIRST 8 +#define MCHP_INT_GIRQ_LAST 26 +#define MCHP_INT_GIRQ_NUM (26 - 8 + 1) +/* MCHP_INT_GIRQ_FIRST <= x <= MCHP_INT_GIRQ_LAST */ +#define MCHP_INTx_BASE(x) (MCHP_INT_BASE + (((x)-8) * MCHP_INT_GIRQ_LEN)) + +/* + * GPIO GIRQ's are not direct capable + * GIRQ08 GPIO 0140 - 0176 + * GIRQ09 GPIO 0100 - 0136 + * GIRQ10 GPIO 040 - 076 + * GIRQ11 GPIO 000 - 036 + * GIRQ12 GPIO 0200 - 0236 + * GIRQ26 GPIO 0240 - 0276 + * Other GIRQ's not direct capable: + * GIRQ22 wake peripheral clock only + * GIRQ24, GIRQ25 eSPI host to endpoint virtual wires + */ +#define MCHP_INT_AGGR_ONLY_BITMAP \ + (BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(22) | BIT(24) | \ + BIT(25) | BIT(26)) + +#define MCHP_INT_DIRECT_CAPABLE_BITMAP \ + (BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) | \ + BIT(20) | BIT(21) | BIT(23)) + +/* GIRQ13 I2C controllers 0 - 4. Direct capable */ +#define MCHP_INT13_I2C(x) BIT(x) + +/* GIRQ14 DMA channels 0 - 15. Direct capable */ +#define MCHP_INT14_DMA(x) BIT(x) + +/* GIQ15 interrupt sources. Direct capable */ +#define MCHP_INT15_UART_0 BIT(0) +#define MCHP_INT15_UART_1 BIT(1) +#define MCHP_INT15_EMI_0 BIT(2) +#define MCHP_INT15_EMI_1 BIT(3) +#define MCHP_INT15_EMI_2 BIT(4) +#define MCHP_INT15_ACPI_EC0_IBF BIT(5) +#define MCHP_INT15_ACPI_EC0_OBE BIT(6) +#define MCHP_INT15_ACPI_EC1_IBF BIT(7) +#define MCHP_INT15_ACPI_EC1_OBE BIT(8) +#define MCHP_INT15_ACPI_EC2_IBF BIT(9) +#define MCHP_INT15_ACPI_EC2_OBE BIT(10) +#define MCHP_INT15_ACPI_EC3_IBF BIT(11) +#define MCHP_INT15_ACPI_EC3_OBE BIT(12) +#define MCHP_INT15_ACPI_EC4_IBF BIT(13) +#define MCHP_INT15_ACPI_EC4_OBE BIT(14) +#define MCHP_INT15_ACPI_PM1_CTL BIT(15) +#define MCHP_INT15_ACPI_PM1_EN BIT(16) +#define MCHP_INT15_ACPI_PM1_STS BIT(17) +#define MCHP_INT15_8042_OBE BIT(18) +#define MCHP_INT15_8042_IBF BIT(19) +#define MCHP_INT15_MAILBOX BIT(20) +#define MCHP_INT15_BDP0 BIT(22) + +/* GIRQ16 interrupt sources. Direct capable */ +#define MCHP_INT16_PKE_DONE BIT(0) +#define MCHP_INT16_RNG_DONE BIT(2) +#define MCHP_INT16_AESH_DONE BIT(3) + +/* GIR17 interrupt sources. Direct capable */ +#define MCHP_INT17_PECI BIT(0) +#define MCHP_INT17_TACH_0 BIT(1) +#define MCHP_INT17_TACH_1 BIT(2) +#define MCHP_INT17_TACH_2 BIT(3) +#define MCHP_INT17_TACH_3 BIT(4) +#define MCHP_INT17_ADC_SINGLE BIT(8) +#define MCHP_INT17_ADC_REPEAT BIT(9) +#define MCHP_INT17_RCID_0 BIT(10) +#define MCHP_INT17_RCID_1 BIT(11) +#define MCHP_INT17_RCID_2 BIT(12) +#define MCHP_INT17_LED_WDT_0 BIT(13) +#define MCHP_INT17_LED_WDT_1 BIT(14) +#define MCHP_INT17_LED_WDT_2 BIT(15) +#define MCHP_INT17_LED_WDT_3 BIT(16) +#define MCHP_INT17_PROCHOT BIT(17) +#define MCHP_INT17_RPM2PWM0_FAIL BIT(20) +#define MCHP_INT17_RPM2PWM0_STALL BIT(21) +#define MCHP_INT17_RPM2PWM1_FAIL BIT(22) +#define MCHP_INT17_RPM2PWM1_STALL BIT(23) + +/* GIRQ18 interrupt sources. Direct capable */ +#define MCHP_INT18_SPIEP BIT(0) +#define MCHP_INT18_QMSPI BIT(1) +#define MCHP_INT18_GPSPI0_TXBE BIT(2) +#define MCHP_INT18_GPSPI0_RXBF BIT(3) +#define MCHP_INT18_GPSPI1_TXBE BIT(4) +#define MCHP_INT18_GPSPI1_RXBF BIT(5) +#define MCHP_INT18_BCM0_BUSY BIT(6) +#define MCHP_INT18_BCM0_ERR BIT(7) +#define MCHP_INT18_PS2_0 BIT(10) +#define MCHP_INT18_PSPI BIT(13) +#define MCHP_INT18_CCT BIT(20) +#define MCHP_INT18_CCT_CAP0 BIT(21) +#define MCHP_INT18_CCT_CAP1 BIT(22) +#define MCHP_INT18_CCT_CAP2 BIT(23) +#define MCHP_INT18_CCT_CAP3 BIT(24) +#define MCHP_INT18_CCT_CAP4 BIT(25) +#define MCHP_INT18_CCT_CAP6 BIT(26) +#define MCHP_INT18_CCT_CMP0 BIT(27) +#define MCHP_INT18_CCT_CMP1 BIT(28) + +/* GIRQ19 interrupt sources. Direct capable */ +#define MCHP_INT19_ESPI_PC BIT(0) +#define MCHP_INT19_ESPI_BM1 BIT(1) +#define MCHP_INT19_ESPI_BM2 BIT(2) +#define MCHP_INT19_ESPI_LTR BIT(3) +#define MCHP_INT19_ESPI_OOB_TX BIT(4) +#define MCHP_INT19_ESPI_OOB_RX BIT(5) +#define MCHP_INT19_ESPI_FC BIT(6) +#define MCHP_INT19_ESPI_RESET BIT(7) +#define MCHP_INT19_ESPI_VW_EN BIT(8) +#define MCHP_INT19_ESPI_SAF BIT(9) +#define MCHP_INT19_ESPI_SAF_ERR BIT(10) +#define MCHP_INT19_ESPI_SAF_CACHE BIT(11) + +/* GIRQ20 interrupt sources. Direct capable */ +#define MCHP_INT20_STAP_OBF BIT(0) +#define MCHP_INT20_STAP_IBF BIT(1) +#define MCHP_INT20_STAP_WAKE BIT(2) +#define MCHP_INT20_OTP BIT(3) +#define MCHP_INT20_ISPI BIT(8) +#define MCHP_INT20_CLK32K_MON BIT(9) + +/* GIRQ21 interrupt sources. Direct capable */ +#define MCHP_INT21_WDG BIT(2) +#define MCHP_INT21_WEEK_ALARM BIT(3) +#define MCHP_INT21_WEEK_SUB BIT(4) +#define MCHP_INT21_WEEK_1SEC BIT(5) +#define MCHP_INT21_WEEK_1SEC_SUB BIT(6) +#define MCHP_INT21_WEEK_PWR_PRES BIT(7) +#define MCHP_INT21_RTC BIT(8) +#define MCHP_INT21_RTC_ALARM BIT(9) +#define MCHP_INT21_VCI_OVRD BIT(10) +#define MCHP_INT21_VCI_IN0 BIT(11) +#define MCHP_INT21_VCI_IN1 BIT(12) +#define MCHP_INT21_VCI_IN2 BIT(13) +#define MCHP_INT21_VCI_IN3 BIT(14) +#define MCHP_INT21_VCI_IN4 BIT(15) +#define MCHP_INT21_PS2_0A_WAKE BIT(18) +#define MCHP_INT21_PS2_0B_WAKE BIT(19) +#define MCHP_INT21_KEYSCAN BIT(25) +#define MCHP_INT21_GLUE BIT(26) + +/* GIRQ22 peripheral wake only. GIRQ22 not connected to NVIC */ +#define MCHP_INT22_WAKE_ONLY_SPIEP BIT(0) +#define MCHP_INT22_WAKE_ONLY_I2C0 BIT(1) +#define MCHP_INT22_WAKE_ONLY_I2C1 BIT(2) +#define MCHP_INT22_WAKE_ONLY_I2C2 BIT(3) +#define MCHP_INT22_WAKE_ONLY_I2C3 BIT(4) +#define MCHP_INT22_WAKE_ONLY_I2C4 BIT(5) +#define MCHP_INT22_WAKE_ONLY_ESPI BIT(9) +#define MCHP_INT22_WAKE_ONLY_STAP BIT(15) + +/* GIRQ23 sources. Direct capable */ +#define MCHP_INT23_BTMR16_0 BIT(0) +#define MCHP_INT23_BTMR16_1 BIT(1) +#define MCHP_INT23_BTMR16_2 BIT(2) +#define MCHP_INT23_BTMR16_3 BIT(3) +#define MCHP_INT23_BTMR32_0 BIT(4) +#define MCHP_INT23_BTMR32_1 BIT(5) +#define MCHP_INT23_CNT16_0 BIT(6) +#define MCHP_INT23_CNT16_1 BIT(7) +#define MCHP_INT23_CNT16_2 BIT(8) +#define MCHP_INT23_CNT16_3 BIT(9) +#define MCHP_INT21_RTMR BIT(10) +#define MCHP_INT21_HTMR_0 BIT(16) +#define MCHP_INT21_HTMR_1 BIT(17) + +/* GIRQ24 sources. Master-to-Slave v=[0:6], Source=[0:3] */ +#define MCHP_INT24_MSVW_SRC(v, s) (1ul << ((4 * (v)) + (s))) + +/* GIRQ25 sources Master-to-Slave v=[7:10], Source=[0:3] */ +#define MCHP_INT25_MSVW_SRC(v, s) (1ul << ((4 * ((v)-7)) + (s))) + +/* UART Peripheral 0 <= x <= 1 */ +#define MCHP_UART_INSTANCES 2 +#define MCHP_UART_SPACING 0x400 +#define MCHP_UART_CFG_OFS 0x300 +#define MCHP_UART_CONFIG_BASE(x) \ + (MCHP_UART0_BASE + MCHP_UART_CFG_OFS + ((x)*MCHP_UART_SPACING)) +#define MCHP_UART_RUNTIME_BASE(x) (MCHP_UART0_BASE + ((x)*MCHP_UART_SPACING)) +#define MCHP_UART_GIRQ 15 +#define MCHP_UART0_GIRQ_BIT (MCHP_INT15_UART_0) +#define MCHP_UART1_GIRQ_BIT (MCHP_INT15_UART_1) +#define MCHP_UART_GIRQ_BIT(x) BIT(x) +/* Bit defines for MCHP_UARTx_LSR */ +#define MCHP_LSR_TX_EMPTY BIT(5) + +/* + * GPIO + * MCHP each Port contains 32 GPIO's. + * GPIO Control 1 registers are 32-bit registers starting at + * MCHP_GPIO_BASE. + * index = octal GPIO number from MCHP specification. + * port/bank = index >> 5 + * id = index & 0x1F + * + * The port/bank, id pair may also be used to access GPIO's via + * parallel I/O registers if GPIO control is configured for + * parallel I/O. + * + * From ec/chip/mec1701/config_chip.h + * #define GPIO_PIN(index) ((index) >> 5), ((index) & 0x1F) + * + * GPIO Control 1 Address = 0x40081000 + (((bank << 5) + id) << 2) + * + * Example: GPIO043, Control 1 register address = 0x4008108c + * port/bank = 0x23 >> 5 = 1 + * id = 0x23 & 0x1F = 0x03 + * Control 1 Address = 0x40081000 + ((BIT(5) + 0x03) << 2) = 0x4008108c + * + * Example: GPIO235, Control 1 register address = 0x40081274 + * port/bank = 0x9d >> 5 = 4 + * id = 0x9d & 0x1f = 0x1d + * Control 1 Address = 0x40081000 + (((4 << 5) + 0x1d) << 2) = 0x40081274 + * + */ +#define MCHP_GPIO_CTL(port, id) \ + REG32(MCHP_GPIO_BASE + (((port << 5) + id) << 2)) + +/* MCHP implements 6 GPIO ports */ +#define MCHP_GPIO_MAX_PORT 6 +#define UNIMPLEMENTED_GPIO_BANK MCHP_GPIO_MAX_PORT +/* + * In MECxxxx documentation GPIO numbers are octal, each control + * register is located on a 32-bit boundary. + */ +#define MCHP_GPIO_CTRL(gpio_num) REG32(MCHP_GPIO_BASE + ((gpio_num) << 2)) + +/* + * GPIO control register bit fields + */ +#define MCHP_GPIO_CTRL_PUD_BITPOS 0 +#define MCHP_GPIO_CTRL_PUD_MASK0 0x03 +#define MCHP_GPIO_CTRL_PUD_MASK 0x03 +#define MCHP_GPIO_CTRL_PUD_NONE 0x00 +#define MCHP_GPIO_CTRL_PUD_PU 0x01 +#define MCHP_GPIO_CTRL_PUD_PD 0x02 +#define MCHP_GPIO_CTRL_PUD_KEEPER 0x03 +#define MCHP_GPIO_CTRL_PWR_BITPOS 2 +#define MCHP_GPIO_CTRL_PWR_MASK0 0x03 +#define MCHP_GPIO_CTRL_PWR_MASK GENMASK(2, 1) +#define MCHP_GPIO_CTRL_PWR_VTR 0 +#define MCHP_GPIO_CTRL_PWR_OFF (0x02U << 2) +#define MCHP_GPIO_INTDET_MASK 0xF0U +#define MCHP_GPIO_INTDET_LVL_LO 0x00 +#define MCHP_GPIO_INTDET_LVL_HI 0x10U +#define MCHP_GPIO_INTDET_DISABLED 0x40U +#define MCHP_GPIO_INTDET_EDGE_RIS 0xD0U +#define MCHP_GPIO_INTDET_EDGE_FALL 0xE0U +#define MCHP_GPIO_INTDET_EDGE_BOTH 0xF0U +#define MCHP_GPIO_INTDET_EDGE_EN BIT(7) +#define MCHP_GPIO_PUSH_PULL 0U +#define MCHP_GPIO_OPEN_DRAIN BIT(8) +#define MCHP_GPIO_INPUT 0U +#define MCHP_GPIO_OUTPUT BIT(9) +#define MCHP_GPIO_OUTSET_CTRL 0U +#define MCHP_GPIO_OUTSEL_PAR BIT(10) +#define MCHP_GPIO_POLARITY_NINV 0U +#define MCHP_GPIO_POLARITY_INV BIT(11) +#define MCHP_GPIO_CTRL_ALT_FUNC_BITPOS 12 +#define MCHP_GPIO_CTRL_ALT_FUNC_MASK0 0x07U +#define MCHP_GPIO_CTRL_ALT_FUNC_MASK (0x07U << 12) +#define MCHP_GPIO_CTRL_FUNC_GPIO 0 +#define MCHP_GPIO_CTRL_FUNC_1 (1U << 12) +#define MCHP_GPIO_CTRL_FUNC_2 (2U << 12) +#define MCHP_GPIO_CTRL_FUNC_3 (3U << 12) +#define MCHP_GPIO_CTRL_FUNC_4 (4U << 12) +#define MCHP_GPIO_CTRL_FUNC_5 (5U << 12) +#define MCHP_GPIO_CTRL_OUT_LVL BIT(16) +/* MEC172x implements input pad disable */ +#define MCHP_GPIO_CTRL_DIS_INPUT_BITPOS 15 +#define MCHP_GPIO_CTRL_DIS_INPUT_BIT BIT(15) + +/* + * GPIO Parallel Input and Output registers. + * gpio_bank in [0, 5] + */ +#define MCHP_GPIO_PARIN(bank) REG32(MCHP_GPIO_BASE + 0x0300 + ((bank) << 2)) +#define MCHP_GPIO_PAROUT(bank) REG32(MCHP_GPIO_BASE + 0x0380 + ((bank) << 2)) + +/* Basic timers */ +#define MCHP_TMR_SPACING 0x20 +#define MCHP_TMR16_INSTANCES 4 +#define MCHP_TMR32_INSTANCES 2 +#define MCHP_TMR16_MAX (MCHP_TMR16_INSTANCES) +#define MCHP_TMR32_MAX (MCHP_TMR32_INSTANCES) +#define MCHP_TMR16_BASE(n) (MCHP_TMR16_0_BASE + (n)*MCHP_TMR_SPACING) +#define MCHP_TMR32_BASE(n) (MCHP_TMR32_0_BASE + (n)*MCHP_TMR_SPACING) +#define MCHP_TMR16_GIRQ 23 +#define MCHP_TMR16_GIRQ_BIT(n) BIT(0 + (n)) +#define MCHP_TMR32_GIRQ 23 +#define MCHP_TMR32_GIRQ_BIT(n) BIT(4 + (n)) + +/* 16-bit Counter/timer */ +#define MCHP_CNT16_SPACING 0x20 +#define MCHP_CNT16_INSTANCES 4 +#define MCHP_CNT16_BASE(n) (MCHP_CNT16_0_BASE + (n)*MCHP_CNT16_SPACING) +#define MCHP_CNT16_GIRQ 23 +#define MCHP_CNT16_GIRQ_BIT(x) BIT(6 + (x)) + +/* RTimer */ +#define MCHP_RTMR_GIRQ 21 +#define MCHP_RTMR_GIRQ_BIT(x) MCHP_INT21_RTMR + +/* Watchdog */ +/* MEC152x specific registers */ +#define MCHP_WDG_STATUS REG32(MCHP_WDG_BASE + 0x10) +#define MCHP_WDG_IEN REG32(MCHP_WDG_BASE + 0x14) +/* Status */ +#define MCHP_WDG_STS_IRQ BIT(0) +/* Interrupt enable */ +#define MCHP_WDG_IEN_IRQ_EN BIT(0) +#define MCHP_WDG_GIRQ 21 +#define MCHP_WDG_GIRQ_BIT BIT(2) +/* Control register has a bit to enable IRQ generation */ +#define MCHP_WDG_RESET_IRQ_EN BIT(9) + +/* VBAT */ +#define MCHP_VBAT_STS REG32(MCHP_VBAT_BASE + 0x0) +#define MCHP_VBAT_CSS REG32(MCHP_VBAT_BASE + 0x8) +#define MCHP_VBAT_MONOTONIC_CTR_LO REG32(MCHP_VBAT_BASE + 0x20) +#define MCHP_VBAT_MONOTONIC_CTR_HI REG32(MCHP_VBAT_BASE + 0x24) +#define MCHP_VBAT_ROM_FEAT REG32(MCHP_VBAT_BASE + 0x28) +#define MCHP_VBAT_EMB_DEBOUNCE_EN REG32(MCHP_VBAT_BASE + 0x34) +/* read 32-bit word at 32-bit offset x where 0 <= x <= 32 */ +#define MCHP_VBAT_RAM_SIZE 128 +#define MCHP_VBAT_RAM(wnum) REG32(MCHP_VBAT_RAM_BASE + ((wnum)*4)) +#define MCHP_VBAT_RAM8(bnum) REG8(MCHP_VBAT_RAM_BASE + (bnum)) +#define MCHP_VBAT_VWIRE_BACKUP 30 +/* + * Miscellaneous firmware control fields + * scratch pad index cannot be more than 32 as + * MEC152x has 64 bytes = 16 words of scratch RAM + */ +#define MCHP_IMAGETYPE_IDX 31 + +/* Bit definition for MCHP_VBAT_STS */ +#define MCHP_VBAT_STS_SOFTRESET BIT(2) +#define MCHP_VBAT_STS_RESETI BIT(4) +#define MCHP_VBAT_STS_WDT BIT(5) +#define MCHP_VBAT_STS_SYSRESETREQ BIT(6) +#define MCHP_VBAT_STS_VBAT_RST BIT(7) +#define MCHP_VBAT_STS_ANY_RST 0xF4u + +/* Bit definitions for MCHP_VBAT_CSS */ +#define MCHP_VBAT_CSS_SIL32K_EN BIT(0) +#define MCHP_VBAT_CSS_XTAL_EN BIT(8) +#define MCHP_VBAT_CSS_XTAL_SINGLE BIT(9) +#define MCHP_VBAT_CSS_XTAL_HSC_DIS BIT(10) +#define MCHP_VBAT_CSS_XTAL_CNT_POS 11 +#define MCHP_VBAT_CSS_XTAL_CNT_MASK (0x03U << 11) +#define MCHP_VBAT_CSS_SRC_POS 16 +#define MCHP_VBAT_CSS_SRC_MASK (0x03U << 16) +#define MCHP_VBAT_CSS_SRC_SIL_OSC 0 +#define MCHP_VBAT_CSS_SRC_XTAL (1U << 16) +/* Switch from 32KHZ_IN input to silicon OSC when VTR goes down */ +#define MCHP_VBAT_CSS_SRC_SWPS (2U << 16) +/* Switch from 32KHZ_IN input to XTAL on VBAT when VTR goes down */ +#define MCHP_VBAT_CSS_SRC_SWPX (3U << 16) +/* Disable 32Khz silicon oscillator when VBAT goes off */ +#define MCHP_VBAT_CSS_NVB_SUPS BIT(18) + +/* Blinking-Breathing LED 0 <= n <= 2 */ +#define MCHP_BBLEB_INSTANCES 4 +#define MCHP_BBLED_BASE(n) (MCHP_BBLED_0_BASE + (((n)&0x03) * 256)) + +/* EMI */ +#define MCHP_EMI_INSTANCES 3 +#define MCHP_EMI_SPACING 0x400 +#define MCHP_EMI_ECREG_OFS 0x100 +/* base of EMI registers only accessible by EC */ +#define MCHP_EMI_BASE(n) \ + (MCHP_EMI_0_BASE + MCHP_EMI_ECREG_OFS + ((n)*MCHP_EMI_SPACING)) +/* base of EMI registers accessible by EC and Host */ +#define MCHP_EMI_RT_BASE(n) (MCHP_EMI_0_BASE + ((n)*MCHP_EMI_SPACING)) +#define MCHP_EMI_GIRQ 15 +#define MCHP_EMI_GIRQ_BIT(n) BIT(2 + (n)) + +/* Mailbox */ +#define MCHP_MBX_ECREGS_OFS 0x100 +#define MCHP_MBX_RT_BASE MCHP_MBOX_BASE +#define MCHP_MBX_BASE (MCHP_MBOX_BASE + MCHP_MBX_ECREGS_OFS) +#define MCHP_MBX_GIRQ 15 +#define MCHP_MBX_GIRQ_BIT BIT(20) + +/* MEC172x includes one instance of the BIOS Debug Port + * capable of capturing Host I/O port 0x80 and 0x90 writes. + * EC Data Value register: + * bits[7:0] oldest FIFO data from Host + * bits[15:16] data attributes/status + * Read with 16 or 32 access guarantees attributes/status bits + * correspond to data in bits[7:0]. + */ +#define MCHP_BDP0_HDATA REG32(MCHP_BDP0_BASE) +#define MCHP_BDP0_DATTR REG16(MCHP_BDP0_BASE + 0x100) +#define MCHP_BDP0_CONFIG REG32(MCHP_BDP0_BASE + 0x104) +#define MCHP_BDP0_STATUS REG8(MCHP_BDP0_BASE + 0x108) +#define MCHP_BDP0_INTR_EN REG8(MCHP_BDP0_BASE + 0x109) +#define MCHP_BDP0_STS_IEN REG16(MCHP_BDP0_BASE + 0x108) +#define MCHP_BDP0_SNAPSHOT REG32(MCHP_BDP0_BASE + 0x10C) +#define MCHP_BDP0_CAPTURE REG32(MCHP_BDP0_BASE + 0x110) +#define MCHP_BDP0_ACTV REG8(MCHP_BDP0_BASE + 0x330) +#define MCHP_BDP0_ALIAS_HDATA REG8(MCHP_BDP0_BASE + 0x400) +#define MCHP_BDP0_ALIAS_ACTV REG8(MCHP_BDP0_BASE + 0x730) +#define MCHP_BDP0_ALIAS_BLN REG8(MCHP_BDP0_BASE + 0x7F0) + +#define MCHP_BDP0_GIRQ 15 +#define MCHP_BDP0_GIRQ_BIT BIT(22) + +/* BDP DATATR as 16-bit value bit definitions */ +#define MCHP_BDP_DATTR_POS 0 +#define MCHP_BDP_DATTR_DATA_MASK 0xff +#define MCHP_BDP_DATTR_LANE_POS 8 +#define MCHP_BDP_DATTR_LANE_MASK GENMASK(9, 8) +#define MCHP_BDP_DATTR_LANE_0 0 +#define MCHP_BDP_DATTR_LANE_1 (1U << 8) +#define MCHP_BDP_DATTR_LANE_2 (2U << 8) +#define MCHP_BDP_DATTR_LANE_3 (3U << 8) +#define MCHP_BDP_DATTR_LEN_POS 10 +#define MCHP_BDP_DATTR_LEN_MASK GENMASK(11, 10) +#define MCHP_BDP_DATTR_LEN_1 0 +#define MCHP_BDP_DATTR_LEN_2 (1U << 10) +#define MCHP_BDP_DATTR_LEN_4 (2U << 10) +#define MCHP_BDP_DATTR_LEN_INVAL (3U << 10) +#define MCHP_BDP_DATTR_NE BIT(12) +#define MCHP_BDP_DATTR_OVR BIT(13) +#define MCHP_BDP_DATTR_THRH BIT(14) + +/* BDP Configuration */ +#define MCHP_BDP_CFG_FLUSH_FIFO BIT(0) +#define MCHP_BDP_CFG_SNAPSHOT_CLR BIT(1) +#define MCHP_BDP_CFG_FIFO_THRH_POS 8 +#define MCHP_BDP_CFG_FIFO_THRH_1 0 +#define MCHP_BDP_CFG_FIFO_THRH_4 (1U << 8) +#define MCHP_BDP_CFG_FIFO_THRH_8 (2U << 8) +#define MCHP_BDP_CFG_FIFO_THRH_16 (3U << 8) +#define MCHP_BDP_CFG_FIFO_THRH_20 (4U << 8) +#define MCHP_BDP_CFG_FIFO_THRH_24 (5U << 8) +#define MCHP_BDP_CFG_FIFO_THRH_28 (6U << 8) +#define MCHP_BDP_CFG_FIFO_THRH_30 (7U << 8) +#define MCHP_BDP_CFG_SRST BIT(31) + +/* BDP Status */ +#define MCHP_BDP_STATUS_MASK GENMASK(2, 0) +#define MCHP_BDP_STATUS_NOT_EMPTY BIT(0) +#define MCHP_BDP_STATUS_OVERRUN BIT(1) +#define MCHP_BDP_STATUS_THRH BIT(2) + +/* BDP Interrupt enable */ +#define MCHP_BDP_IEN_THRH BIT(0) + +/* PWM SZ 144 pin package has 9 PWM's */ +#define MCHP_PWM_INSTANCES 9 +#define MCHP_PWM_ID_MAX (MCHP_PWM_INSTANCES) +#define MCHP_PWM_SPACING 16 +#define MCHP_PWM_BASE(x) (MCHP_PWM_0_BASE + ((x)*MCHP_PWM_SPACING)) + +/* TACH */ +#define MCHP_TACH_INSTANCES 4 +#define MCHP_TACH_SPACING 16 +#define MCHP_TACH_BASE(x) (MCHP_TACH_0_BASE + ((x)*MCHP_TACH_SPACING)) +#define MCHP_TACH_GIRQ 17 +#define MCHP_TACH_GIRQ_BIT(x) BIT(1 + (x)) + +/* FAN */ +#define MCHP_FAN_INSTANCES 2 +#define MCHP_FAN_SPACING 0x80U +#define MCHP_FAN_BASE(x) (MCHP_RPM2PWM0_BASE + ((x)*MCHP_FAN_SPACING)) +#define MCHP_FAN_SETTING(x) REG16(MCHP_FAN_BASE(x) + 0x0) +#define MCHP_FAN_CFG1(x) REG8(MCHP_FAN_BASE(x) + 0x2) +#define MCHP_FAN_CFG2(x) REG8(MCHP_FAN_BASE(x) + 0x3) +#define MCHP_FAN_PWM_DIVIDE(x) REG8(MCHP_FAN_BASE(x) + 0x4) +#define MCHP_FAN_GAIN(x) REG8(MCHP_FAN_BASE(x) + 0x5) +#define MCHP_FAN_SPIN_UP(x) REG8(MCHP_FAN_BASE(x) + 0x6) +#define MCHP_FAN_STEP(x) REG8(MCHP_FAN_BASE(x) + 0x7) +#define MCHP_FAN_MIN_DRV(x) REG8(MCHP_FAN_BASE(x) + 0x8) +#define MCHP_FAN_VALID_CNT(x) REG8(MCHP_FAN_BASE(x) + 0x9) +#define MCHP_FAN_DRV_FAIL(x) REG16(MCHP_FAN_BASE(x) + 0xa) +#define MCHP_FAN_TARGET(x) REG16(MCHP_FAN_BASE(x) + 0xc) +#define MCHP_FAN_READING(x) REG16(MCHP_FAN_BASE(x) + 0xe) +#define MCHP_FAN_BASE_FREQ(x) REG8(MCHP_FAN_BASE(x) + 0x10) +#define MCHP_FAN_STATUS(x) REG8(MCHP_FAN_BASE(x) + 0x11) + +/* ACPI EC */ +#define MCHP_ACPI_EC_INSTANCES 5 +#define MCHP_ACPI_EC_MAX (MCHP_ACPI_EC_INSTANCES) +#define MCHP_ACPI_EC_SPACING 0x400 +#define MCHP_ACPI_EC_BASE(x) (MCHP_ACPI_EC_0_BASE + ((x)*MCHP_ACPI_EC_SPACING)) +#define MCHP_ACPI_EC_GIRQ 15 +#define MCHP_ACPI_EC_IBF_GIRQ_BIT(x) BIT(5 + ((x)*2)) +#define MCHP_ACPI_EC_OBE_GIRQ_BIT(x) BIT(6 + ((x)*2)) + +/* ACPI PM1 */ +#define MCHP_ACPI_PM1_ECREGS_OFS 0x100 +#define MCHP_ACPI_PM_RT_BASE MCHP_ACPI_PM1_BASE +#define MCHP_ACPI_PM_EC_BASE (MCHP_ACPI_PM1_BASE + MCHP_ACPI_PM1_ECREGS_OFS) +#define MCHP_ACPI_PM1_CTL_GIRQ_BIT BIT(15) +#define MCHP_ACPI_PM1_EN_GIRQ_BIT BIT(16) +#define MCHP_ACPI_PM1_STS_GIRQ_BIT BIT(17) + +/* 8042 */ +#define MCHP_8042_ECREGS_OFS 0x100 +#define MCHP_8042_GIRQ 15 +#define MCHP_8042_OBE_GIRQ_BIT BIT(18) +#define MCHP_8042_IBF_GIRQ_BIT BIT(19) + +/* I2C controllers 0 - 4 include SMBus network layer functionality. */ +#define MCHP_I2C_CTRL0 0 +#define MCHP_I2C_CTRL1 1 +#define MCHP_I2C_CTRL2 2 +#define MCHP_I2C_CTRL3 3 +#define MCHP_I2C_CTRL4 4 +#define MCHP_I2C_CTRL_MAX 5 + +#define MCHP_I2C_SEP0 0x400 + +/* + * MEC172x SZ(144-pin) package implements 15 ports. No Port 11. + * LJ(176-pin) package implements 16 ports. + * Any port can be mapped to any I2C controller. + * I2C port values must be zero based consecutive whole numbers due to + * port number used as an index for I2C the mutex list, etc. + * Refer to chip i2c_port_to_controller function for mapping + * of port to controller. + * Locking must occur by-controller (not by-port). + */ +#if (defined(CHIP_VARIANT_MEC1721LJ) || defined(CHIP_VARIANT_MEC1723LJ) || \ + defined(CHIP_VARIANT_MEC1727LJ)) +#define MCHP_I2C_PORT_MASK GENMASK(15, 0) +#else +#define MCHP_I2C_PORT_MASK (GENMASK(15, 0) & ~BIT(11)) +#endif +enum MCHP_i2c_port { + MCHP_I2C_PORT0 = 0, + MCHP_I2C_PORT1, + MCHP_I2C_PORT2, + MCHP_I2C_PORT3, + MCHP_I2C_PORT4, + MCHP_I2C_PORT5, + MCHP_I2C_PORT6, + MCHP_I2C_PORT7, + MCHP_I2C_PORT8, + MCHP_I2C_PORT9, + MCHP_I2C_PORT10, + MCHP_I2C_PORT11, + MCHP_I2C_PORT12, + MCHP_I2C_PORT13, + MCHP_I2C_PORT14, + MCHP_I2C_PORT15, + MCHP_I2C_PORT_COUNT, +}; + +/* I2C ports & Configs */ +#define I2C_CONTROLLER_COUNT MCHP_I2C_CTRL_MAX +#define I2C_PORT_COUNT MCHP_I2C_PORT_COUNT + +/* All I2C controllers connected to GIRQ13 */ +#define MCHP_I2C_GIRQ 13 +/* I2C[0:7] -> GIRQ13 bits[0:7] */ +#define MCHP_I2C_GIRQ_BIT(n) BIT((n)) + +/* Keyboard scan matrix */ +#define MCHP_KS_GIRQ 21 +#define MCHP_KS_GIRQ_BIT BIT(25) +#define MCHP_KS_DIRECT_NVIC 135 + +/* ADC */ +#if (defined(CHIP_VARIANT_MEC1721LJ) || defined(CHIP_VARIANT_MEC1723LJ) || \ + defined(CHIP_VARIANT_MEC1727LJ)) +#define MCHP_ADC_CHAN_MASK GENMASK(15, 0) +#else +#define MCHP_ADC_CHAN_MASK GENMASK(7, 0) +#endif +#define MCHP_ADC_GIRQ 17 +#define MCHP_ADC_GIRQ_SINGLE_BIT BIT(8) +#define MCHP_ADC_GIRQ_REPEAT_BIT BIT(9) +#define MCHP_ADC_SINGLE_DIRECT_NVIC 78 +#define MCHP_ADC_REPEAT_DIRECT_NVIC 79 +#define MCHP_ADC_CONFIG REG32(MCHP_ADC_BASE + 0x7c) +#define MCHP_ADC_CONFIG_DFLT 0x0101U +#define MCHP_ADC_CFG_CLK_LO_TM_MSK GENMASK(7, 0) +#define MCHP_ADC_CFG_CLK_HI_TM_MSK GENMASK(15, 8) +#define MCHP_ADC_VREF_CSEL REG32(MCHP_ADC_BASE + 0x80) +#define MCHP_ADC_VREF_CSEL_MSK(ch) (0x03U << ((ch)*2U)) +#define MCHP_ADC_VREF_CSEL_GPIO(ch) BIT((ch)*2U) +#define MCHP_ADC_VREF_CTRL REG32(MCHP_ADC_BASE + 0x84) +#define MCHP_ADC_VREF_CTRL_DFLT 0U +#define MCHP_ADC_VCTRL_CHRG_DLY_MSK GENMASK(15, 0) +#define MCHP_ADC_VCTRL_SW_DLY_MSK GENMASK(28, 16) +#define MCHP_ADC_VCTRL_DRV_UNUSED_LO BIT(29) +#define MCHP_ADC_VCTRL_SEL_STS_RO_POS 30 +#define MCHP_ADC_VCTRL_SEL_STS_RO_MSK GENMASK(31, 30) +#define MCHP_ADC_SAR_ADC_CTRL REG32(MCHP_ADC_BASE + 0x88) +#define MCHP_ADC_SAR_ADC_CTRL_DFLT ((0x202U << 7) | (0x03U << 1)) +#define MCHP_ADC_SAC_DIFF_INPUT BIT(0) +#define MCHP_ADC_SAC_RES_POS 1 +#define MCHP_ADC_SAC_RES_MSK GENMASK(2, 1) +#define MCHP_ADC_SAC_RES_10BIT (2U << 1) +#define MCHP_ADC_SAC_RES_12BIT (3U << 1) +#define MCHP_ADC_SAC_RJ_10BIT BIT(3) +#define MCHP_ADC_SAC_WU_DLY_POS 7 +#define MCHP_ADC_SAC_WU_DLY_MSK GENMASK(16, 7) +#define MCHP_ADC_SAC_WU_DLY_DLFT (0x202U << 7) + +/* Hibernation timer */ +#define MCHP_HTIMER_SPACING 0x20 +#define MCHP_HTIMER_ADDR(n) (MCHP_HTIMER_BASE + ((n)*MCHP_HTIMER_SPACING)) +#define MCHP_HTIMER_GIRQ 21 +/* HTIMER[0:1] -> GIRQ21 bits[1:2] */ +#define MCHP_HTIMER_GIRQ_BIT(n) BIT(1 + (n)) +#define MCHP_HTIMER_DIRECT_NVIC(n) (112 + (n)) + +/* General Purpose SPI (GP-SPI) */ +#define MCHP_SPI_BASE(port) (MCHP_GPSPI0_BASE + ((port)*0x80)) +#define MCHP_SPI_AR(port) REG8(MCHP_SPI_BASE(port) + 0x00) +#define MCHP_SPI_CR(port) REG8(MCHP_SPI_BASE(port) + 0x04) +#define MCHP_SPI_SR(port) REG8(MCHP_SPI_BASE(port) + 0x08) +#define MCHP_SPI_TD(port) REG8(MCHP_SPI_BASE(port) + 0x0c) +#define MCHP_SPI_RD(port) REG8(MCHP_SPI_BASE(port) + 0x10) +#define MCHP_SPI_CC(port) REG8(MCHP_SPI_BASE(port) + 0x14) +#define MCHP_SPI_CG(port) REG8(MCHP_SPI_BASE(port) + 0x18) +/* Addresses of TX/RX register used in tables */ +#define MCHP_SPI_TD_ADDR(ctrl) (MCHP_SPI_BASE(ctrl) + 0x0c) +#define MCHP_SPI_RD_ADDR(ctrl) (MCHP_SPI_BASE(ctrl) + 0x10) +/* All GP-SPI controllers connected to GIRQ18 */ +#define MCHP_SPI_GIRQ 18 +#define MCHP_SPI_GIRQ_TXBE_BIT(x) BIT(2 + ((x)*2)) +#define MCHP_SPI_GIRQ_RXBF_BIT(x) BIT(3 + ((x)*2)) +#define MCHP_GPSPI0_ID 0 +#define MCHP_GPSPI1_ID 1 + +/* + * Quad Master SPI (QMSPI) + * MEC172x implements 16 descriptors, support for two chip selects, + * chip select timing and a local DMA unit with 3 RX channels and + * 3 TX channels. It retains support of the legacy DMA block. + */ +#define MCHP_QMSPI_MAX_DESCR 16 +#define MCHP_QMSPI_GIRQ 18 +#define MCHP_QMSPI_GIRQ_BIT BIT(1) +#define MCHP_QMSPI_DIRECT_NVIC 91 +/* SAF DMA mode when QMSPI when eSPI SAF is enabled */ +#define MCHP_QMSPI_M_SAF_EN BIT(2) +/* Local DMA enables in Mode register */ +#define MCHP_QMSPI_M_LDRX_EN BIT(3) +#define MCHP_QMSPI_M_LDTX_EN BIT(4) +/* Chip select implemented in bit[13:12] of the Mode register. */ +#define MCHP_QMSPI_M_CS_POS 12 +#define MCHP_QMSPI_M_CS_MASK0 0x03 +#define MCHP_QMSPI_M_CS_MASK GENMASK(13, 12) +#define MCHP_QMSPI_M_CS0 0U +#define MCHP_QMSPI_M_CS1 BIT(12) +/* QMSPI alternate clock divider when CS1 is active. */ +#define MCHP_QMSPI0_ALTM REG32(MCHP_QMSPI0_BASE + 0xc0) +#define MCHP_QMSPI0_ALTM_EN BIT(0) +/* QMSPI taps select */ +#define MCHP_QMSPI0_TAPS REG32(MCHP_QMSPI0_BASE + 0xd0) +/* QMSPI Taps adjust */ +#define MCHP_QMSPI0_TAPS_ADJ REG32(MCHP_QMSPI0_BASE + 0xd4) +#define MCHP_QMSPI0_TAPS_SCK_POS 0 +#define MCHP_QMSPI0_TAPS_SCK_MSK GENMASK(7, 0) +#define MCHP_QMSPI0_TAPS_CTL_POS 8 +#define MCHP_QMSPI0_TAPS_CTL_MSK GENMASK(15, 8) +/* QMSPI Taps control */ +#define MCHP_QMSPI0_TAPS_CTRL REG32(MCHP_QMSPI0_BASE + 0xd4) +#define MCHP_QMSPI0_TAPS_CTRL_MODE_POS 0 +#define MCHP_QMSPI0_TAPS_CTRL_MODE_MSK GENMASK(1, 0) +#define MCHP_QMSPI0_TAPS_CTRL_UPDATE BIT(2) +#define MCHP_QMSPI0_TAPS_CTRL_GO BIT(8) +#define MCHP_QMSPI0_TAPS_CTRL_MULT_POS 16 +#define MCHP_QMSPI0_TAPS_CTRL_MULT_MSK GENMASK(18, 16) +/* QMSPI LDMA descriptor enables */ +#define MCHP_QMSPI0_LDRX_DEN REG32(MCHP_QMSPI0_BASE + 0x100) +#define MCHP_QMSPI0_LDTX_DEN REG32(MCHP_QMSPI0_BASE + 0x104) +/* + * QMSPI LDMA channel registers. + * Each channel implement 3 32-bit registers: + * control, memory base address, and transfer length. + */ +#define MCHP_QMSPI0_LDRX_CHANS 3U +#define MCHP_QMSPI0_LDTX_CHANS 3U +#define MCHP_QMSPI0_LDRX_CTRL(n) REG32(MCHP_QMSPI0_BASE + 0x110 + ((n)*16U)) +#define MCHP_QMSPI0_LDRX_MBASE(n) REG32(MCHP_QMSPI0_BASE + 0x114 + ((n)*16U)) +#define MCHP_QMSPI0_LDRX_LEN(n) REG32(MCHP_QMSPI0_BASE + 0x118 + ((n)*16U)) +#define MCHP_QMSPI0_LDTX_CTRL(n) REG32(MCHP_QMSPI0_BASE + 0x140 + ((n)*16U)) +#define MCHP_QMSPI0_LDTX_MBASE(n) REG32(MCHP_QMSPI0_BASE + 0x144 + ((n)*16U)) +#define MCHP_QMSPI0_LDTX_LEN(n) REG32(MCHP_QMSPI0_BASE + 0x148 + ((n)*16U)) +/* LDMA RX or TX channel control register */ +#define MCHP_QMSPI_LDC_MSK GENMASK(6, 0) +#define MCHP_QMSPI_LDC_EN BIT(0) +#define MCHP_QMSPI_LDC_RSTART_EN BIT(1) +#define MCHP_QMSPI_LDC_RSTART_MA_EN BIT(2) +#define MCHP_QMSPI_LDC_LEN_EN BIT(3) +#define MCHP_QMSPI_LDC_ACC_SZ_POS 4 +#define MCHP_QMSPI_LDC_ACC_SZ_MSK GENMASK(5, 4) +#define MCHP_QMSPI_LDC_ACC_1BYTE 0 +#define MCHP_QMSPI_LDC_ACC_2BYTES (1U << 4) +#define MCHP_QMSPI_LDC_ACC_4BYTES (2U << 4) +#define MCHP_QMSPI_LDC_INCR_ADDR BIT(6) + +/* eSPI */ +/* IO BAR defines. Use with MCHP_ESPI_IO_BAR_xxxx macros */ +#define MCHP_ESPI_IO_BAR_ID_CFG_PORT 0 +#define MCHP_ESPI_IO_BAR_ID_MEM_CMPNT 1 +#define MCHP_ESPI_IO_BAR_ID_MAILBOX 2 +#define MCHP_ESPI_IO_BAR_ID_8042 3 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC0 4 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC1 5 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC2 6 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC3 7 +#define MCHP_ESPI_IO_BAR_ID_ACPI_EC4 8 +#define MCHP_ESPI_IO_BAR_ID_ACPI_PM1 9 +#define MCHP_ESPI_IO_BAR_ID_P92 0xA +#define MCHP_ESPI_IO_BAR_ID_UART0 0xB +#define MCHP_ESPI_IO_BAR_ID_UART1 0xC +#define MCHP_ESPI_IO_BAR_ID_EMI0 0xD +#define MCHP_ESPI_IO_BAR_ID_EMI1 0xE +#define MCHP_ESPI_IO_BAR_ID_EMI2 0xF +#define MCHP_ESPI_IO_BAR_BDP0 0x10 +#define MCHP_ESPI_IO_BAR_BDP0_ALT 0x11 +#define MCHP_ESPI_IO_BAR_RTC 0x12 +#define MCHP_ESPI_IO_BAR_TB32 0x14 +#define MCHP_ESPI_IO_BAR_GLUE 0x16 + +/* Use with MCHP_ESPI_MBAR_EC_xxxx(x) macros */ +#define MCHP_ESPI_MBAR_ID_MBOX 0 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_0 1 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_1 2 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_2 3 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_3 4 +#define MCHP_ESPI_MBAR_ID_ACPI_EC_4 5 +#define MCHP_ESPI_MBAR_ID_EMI_0 6 +#define MCHP_ESPI_MBAR_ID_EMI_1 7 +#define MCHP_ESPI_MBAR_ID_EMI_2 8 +#define MCHP_ESPI_MBAR_ID_TB32 9 + +/* Use with MCHP_ESPI_IO_SERIRQ_REG(x) */ +#define MCHP_ESPI_SIRQ_MBOX 0 /* Host SIRQ */ +#define MCHP_ESPI_SIRQ_MBOX_SMI 1 /* Host SMI */ +#define MCHP_ESPI_SIRQ_8042_KB 2 /* KIRQ */ +#define MCHP_ESPI_SIRQ_8042_MS 3 /* MIRQ */ +#define MCHP_ESPI_SIRQ_ACPI_EC0_OBF 4 +#define MCHP_ESPI_SIRQ_ACPI_EC1_OBF 5 +#define MCHP_ESPI_SIRQ_ACPI_EC2_OBF 6 +#define MCHP_ESPI_SIRQ_ACPI_EC3_OBF 7 +#define MCHP_ESPI_SIRQ_ACPI_EC4_OBF 8 +#define MCHP_ESPI_SIRQ_UART0 9 +#define MCHP_ESPI_SIRQ_UART1 10 +#define MCHP_ESPI_SIRQ_EMI0_HEV 11 /* Host Event */ +#define MCHP_ESPI_SIRQ_EMI0_EC2H 12 /* EC to Host */ +#define MCHP_ESPI_SIRQ_EMI1_HEV 13 +#define MCHP_ESPI_SIRQ_EMI1_EC2H 14 +#define MCHP_ESPI_SIRQ_EMI2_HEV 15 +#define MCHP_ESPI_SIRQ_EMI2_EC2H 16 +#define MCHP_ESPI_SIRQ_RTC 17 +#define MCHP_ESPI_SIRQ_EC 18 + +#define MCHP_ESPI_MSVW_BASE (MCHP_ESPI_VW_BASE) +#define MCHP_ESPI_SMVW_BASE ((MCHP_ESPI_VW_BASE) + 0x200ul) + +/* + * eSPI RESET, channel enables and operations except Master-to-Slave + * WWires are all on GIRQ19 + */ +#define MCHP_ESPI_GIRQ 19 +#define MCHP_ESPI_PC_GIRQ_BIT BIT(0) +#define MCHP_ESPI_BM1_GIRQ_BIT BIT(1) +#define MCHP_ESPI_BM2_GIRQ_BIT BIT(2) +#define MCHP_ESPI_LTR_GIRQ_BIT BIT(3) +#define MCHP_ESPI_OOB_TX_GIRQ_BIT BIT(4) +#define MCHP_ESPI_OOB_RX_GIRQ_BIT BIT(5) +#define MCHP_ESPI_FC_GIRQ_BIT BIT(6) +#define MCHP_ESPI_RESET_GIRQ_BIT BIT(7) +#define MCHP_ESPI_VW_EN_GIRQ_BIT BIT(8) +#define MCHP_ESPI_SAF_DONE_GIRQ_BIT BIT(9) +#define MCHP_ESPI_SAF_ERR_GIRQ_BIT BIT(10) +#define MCHP_ESPI_SAF_CACHE_GIRQ_BIT BIT(11) + +/* eSPI Master-to-Slave WWire interrupts are on GIRQ24 and GIRQ25 */ +#define MCHP_ESPI_MSVW_0_6_GIRQ 24 +#define MCHP_ESPI_MSVW_7_10_GIRQ 25 +/* + * Four source bits, SRC[0:3] per Master-to-Slave register + * v = MSVW [0:10] + * n = VWire SRC bit = [0:3] + */ +#define MCHP_ESPI_MSVW_GIRQ(v) (24 + ((v) > 6 ? 1 : 0)) + +#define MCHP_ESPI_MSVW_SRC_GIRQ_BIT(v, n) \ + (((v) > 6) ? (1ul << (((v)-7) + (n))) : (1ul << ((v) + (n)))) + +/* DMA */ +#define MCHP_DMA_MAX_CHAN 16 +#define MCHP_DMA_CH_OFS 0x40 +#define MCHP_DMA_CH_OFS_BITPOS 6 +#define MCHP_DMA_CH_BASE (MCHP_DMA_BASE + MCHP_DMA_CH_OFS) + +/* + * Available DMA channels. + * + * On MCHP, any DMA channel may serve any device. Since we have + * 14 channels and 14 device request signals, we make each channel + * dedicated to the device of the same number. + */ +enum dma_channel { + /* Channel numbers */ + MCHP_DMAC_I2C0_SLAVE = 0, + MCHP_DMAC_I2C0_MASTER, + MCHP_DMAC_I2C1_SLAVE, + MCHP_DMAC_I2C1_MASTER, + MCHP_DMAC_I2C2_SLAVE, + MCHP_DMAC_I2C2_MASTER, + MCHP_DMAC_I2C3_SLAVE, + MCHP_DMAC_I2C3_MASTER, + MCHP_DMAC_I2C4_SLAVE, + MCHP_DMAC_I2C5_MASTER, + MCHP_DMAC_QMSPI0_TX, + MCHP_DMAC_QMSPI0_RX, + MCHP_DMAC_SPI0_TX, + MCHP_DMAC_SPI0_RX, + MCHP_DMAC_SPI1_TX, + MCHP_DMAC_SPI1_RX, + /* Channel count */ + MCHP_DMAC_COUNT, +}; + +/* + * Peripheral device DMA Device ID's for bits [15:9] + * in DMA channel control register. + */ +#define MCHP_DMA_I2C0_SLV_REQ_ID 0 +#define MCHP_DMA_I2C0_MTR_REQ_ID 1 +#define MCHP_DMA_I2C1_SLV_REQ_ID 2 +#define MCHP_DMA_I2C1_MTR_REQ_ID 3 +#define MCHP_DMA_I2C2_SLV_REQ_ID 4 +#define MCHP_DMA_I2C2_MTR_REQ_ID 5 +#define MCHP_DMA_I2C3_SLV_REQ_ID 6 +#define MCHP_DMA_I2C3_MTR_REQ_ID 7 +#define MCHP_DMA_I2C4_SLV_REQ_ID 8 +#define MCHP_DMA_I2C4_MTR_REQ_ID 9 +#define MCHP_DMA_QMSPI0_TX_REQ_ID 10 +#define MCHP_DMA_QMSPI0_RX_REQ_ID 11 +#define MCHP_DMA_SPI0_TX_REQ_ID 12 +#define MCHP_DMA_SPI0_RX_REQ_ID 13 +#define MCHP_DMA_SPI1_TX_REQ_ID 14 +#define MCHP_DMA_SPI1_RX_REQ_ID 15 + +/* + * Hardware delay register. + * Write of 0 <= n <= 31 will stall the Cortex-M4 + * for n+1 microseconds. Interrupts will not be + * serviced during the delay period. Reads have + * no effect. + */ +#define MCHP_USEC_DELAY_REG_ADDR 0x08000000 +#define MCHP_USEC_DELAY(x) (REG8(MCHP_USEC_DELAY_REG_ADDR) = (x)) + +#endif /* #ifndef __ASSEMBLER__ */ diff --git a/chip/mchp/registers.h b/chip/mchp/registers.h index 05ecb42aad..7b541b18da 100644 --- a/chip/mchp/registers.h +++ b/chip/mchp/registers.h @@ -1,1487 +1,547 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Register map for Microchip MEC family processors */ - #ifndef __CROS_EC_REGISTERS_H #define __CROS_EC_REGISTERS_H #include "common.h" +#include "compile_time_macros.h" + +#if defined(CHIP_FAMILY_MEC152X) +#include "registers-mec152x.h" +#elif defined(CHIP_FAMILY_MEC170X) +#include "registers-mec1701.h" +#elif defined(CHIP_FAMILY_MEC172X) +#include "registers-mec172x.h" +#else +#error "Unsupported chip family" +#endif -/* - * Helper function for RAM address aliasing - * NOTE: MCHP AHB masters do NOT require aliasing. - * Cortex-M4 bit-banding does require aliasing of the - * DATA SRAM region. - */ -#define MCHP_RAM_ALIAS(x) \ - ((x) >= 0x118000 ? (x) - 0x118000 + 0x20000000 : (x)) +/* Common registers */ +/* EC Interrupt aggregator (ECIA) */ +#define MCHP_INT_SOURCE(x) REG32(MCHP_INTx_BASE(x) + 0x0) +#define MCHP_INT_ENABLE(x) REG32(MCHP_INTx_BASE(x) + 0x4) +#define MCHP_INT_RESULT(x) REG32(MCHP_INTx_BASE(x) + 0x8) +#define MCHP_INT_DISABLE(x) REG32(MCHP_INTx_BASE(x) + 0xc) +#define MCHP_INT_BLK_EN REG32(MCHP_INT_BASE + 0x200) +#define MCHP_INT_BLK_DIS REG32(MCHP_INT_BASE + 0x204) +#define MCHP_INT_BLK_IRQ REG32(MCHP_INT_BASE + 0x208) /* EC Chip Configuration */ -#define MCHP_CHIP_BASE 0x400fff00 -#define MCHP_CHIP_DEV_ID REG8(MCHP_CHIP_BASE + 0x20) -#define MCHP_CHIP_DEV_REV REG8(MCHP_CHIP_BASE + 0x21) - +#define MCHP_CHIP_LEGACY_DEV_ID REG8(MCHP_CHIP_BASE + 0x20) +#define MCHP_CHIP_LEGACY_DEV_REV REG8(MCHP_CHIP_BASE + 0x21) /* Power/Clocks/Resets */ -#define MCHP_PCR_BASE 0x40080100 - -#define MCHP_PCR_SYS_SLP_CTL REG32(MCHP_PCR_BASE + 0x00) -#define MCHP_PCR_PROC_CLK_CTL REG32(MCHP_PCR_BASE + 0x04) -#define MCHP_PCR_SLOW_CLK_CTL REG32(MCHP_PCR_BASE + 0x08) -#define MCHP_PCR_CHIP_OSC_ID REG32(MCHP_PCR_BASE + 0x0C) -#define MCHP_PCR_PWR_RST_STS REG32(MCHP_PCR_BASE + 0x10) -#define MCHP_PCR_PWR_RST_CTL REG32(MCHP_PCR_BASE + 0x14) -#define MCHP_PCR_SYS_RST REG32(MCHP_PCR_BASE + 0x18) -#define MCHP_PCR_SLP_EN0 REG32(MCHP_PCR_BASE + 0x30) -#define MCHP_PCR_SLP_EN1 REG32(MCHP_PCR_BASE + 0x34) -#define MCHP_PCR_SLP_EN2 REG32(MCHP_PCR_BASE + 0x38) -#define MCHP_PCR_SLP_EN3 REG32(MCHP_PCR_BASE + 0x3C) -#define MCHP_PCR_SLP_EN4 REG32(MCHP_PCR_BASE + 0x40) -#define MCHP_PCR_CLK_REQ0 REG32(MCHP_PCR_BASE + 0x50) -#define MCHP_PCR_CLK_REQ1 REG32(MCHP_PCR_BASE + 0x54) -#define MCHP_PCR_CLK_REQ2 REG32(MCHP_PCR_BASE + 0x58) -#define MCHP_PCR_CLK_REQ3 REG32(MCHP_PCR_BASE + 0x5C) -#define MCHP_PCR_CLK_REQ4 REG32(MCHP_PCR_BASE + 0x60) -#define MCHP_PCR_RST_EN0 REG32(MCHP_PCR_BASE + 0x70) -#define MCHP_PCR_RST_EN1 REG32(MCHP_PCR_BASE + 0x74) -#define MCHP_PCR_RST_EN2 REG32(MCHP_PCR_BASE + 0x78) -#define MCHP_PCR_RST_EN3 REG32(MCHP_PCR_BASE + 0x7C) -#define MCHP_PCR_RST_EN4 REG32(MCHP_PCR_BASE + 0x80) - -#define MCHP_PCR_SLP_EN(x) REG32(MCHP_PCR_BASE + 0x30 + ((x)<<2)) -#define MCHP_PCR_CLK_REQ(x) REG32(MCHP_PCR_BASE + 0x50 + ((x)<<2)) -#define MCHP_PCR_RST_EN(x) REG32(MCHP_PCR_BASE + 0x70 + ((x)<<2)) - -#define MCHP_PCR_SLP_RST_REG_MAX (5) +#define MCHP_PCR_SYS_SLP_CTL REG32(MCHP_PCR_BASE + 0x00) +#define MCHP_PCR_PROC_CLK_CTL REG32(MCHP_PCR_BASE + 0x04) +#define MCHP_PCR_SLOW_CLK_CTL REG32(MCHP_PCR_BASE + 0x08) +#define MCHP_PCR_CHIP_OSC_ID REG32(MCHP_PCR_BASE + 0x0C) +#define MCHP_PCR_PWR_RST_STS REG32(MCHP_PCR_BASE + 0x10) +#define MCHP_PCR_PWR_RST_CTL REG32(MCHP_PCR_BASE + 0x14) +#define MCHP_PCR_SYS_RST REG32(MCHP_PCR_BASE + 0x18) +#define MCHP_PCR_SLP_EN0 REG32(MCHP_PCR_BASE + 0x30) +#define MCHP_PCR_SLP_EN1 REG32(MCHP_PCR_BASE + 0x34) +#define MCHP_PCR_SLP_EN2 REG32(MCHP_PCR_BASE + 0x38) +#define MCHP_PCR_SLP_EN3 REG32(MCHP_PCR_BASE + 0x3C) +#define MCHP_PCR_SLP_EN4 REG32(MCHP_PCR_BASE + 0x40) +#define MCHP_PCR_CLK_REQ0 REG32(MCHP_PCR_BASE + 0x50) +#define MCHP_PCR_CLK_REQ1 REG32(MCHP_PCR_BASE + 0x54) +#define MCHP_PCR_CLK_REQ2 REG32(MCHP_PCR_BASE + 0x58) +#define MCHP_PCR_CLK_REQ3 REG32(MCHP_PCR_BASE + 0x5C) +#define MCHP_PCR_CLK_REQ4 REG32(MCHP_PCR_BASE + 0x60) +#define MCHP_PCR_RST_EN0 REG32(MCHP_PCR_BASE + 0x70) +#define MCHP_PCR_RST_EN1 REG32(MCHP_PCR_BASE + 0x74) +#define MCHP_PCR_RST_EN2 REG32(MCHP_PCR_BASE + 0x78) +#define MCHP_PCR_RST_EN3 REG32(MCHP_PCR_BASE + 0x7C) +#define MCHP_PCR_RST_EN4 REG32(MCHP_PCR_BASE + 0x80) +#define MCHP_PCR_SLP_EN(x) REG32(MCHP_PCR_BASE + 0x30 + ((x) << 2)) +#define MCHP_PCR_CLK_REQ(x) REG32(MCHP_PCR_BASE + 0x50 + ((x) << 2)) +#define MCHP_PCR_RST_EN(x) REG32(MCHP_PCR_BASE + 0x70 + ((x) << 2)) /* Bit definitions for MCHP_PCR_SYS_SLP_CTL */ -#define MCHP_PCR_SYS_SLP_LIGHT (0ul << 0) -#define MCHP_PCR_SYS_SLP_HEAVY (1ul << 0) -#define MCHP_PCR_SYS_SLP_ALL (1ul << 3) - +#define MCHP_PCR_SYS_SLP_LIGHT (0ul << 0) +#define MCHP_PCR_SYS_SLP_HEAVY (1ul << 0) +#define MCHP_PCR_SYS_SLP_ALL (1ul << 3) /* * Set/clear PCR sleep enable bit for single device * d bits[10:8] = register 0 - 4 * d bits[4:0] = register bit position */ -#define MCHP_PCR_SLP_EN_DEV(d) (MCHP_PCR_SLP_EN(((d) >> 8) & 0x07) |=\ - (1ul << ((d) & 0x1f))) -#define MCHP_PCR_SLP_DIS_DEV(d) (MCHP_PCR_SLP_EN(((d) >> 8) & 0x07) &=\ - ~(1ul << ((d) & 0x1f))) - +#define MCHP_PCR_SLP_EN_DEV(d) \ + (MCHP_PCR_SLP_EN(((d) >> 8) & 0x07) |= (1ul << ((d)&0x1f))) +#define MCHP_PCR_SLP_DIS_DEV(d) \ + (MCHP_PCR_SLP_EN(((d) >> 8) & 0x07) &= ~(1ul << ((d)&0x1f))) /* * Set/clear bit pattern specified by mask in a single PCR sleep enable * register. * id = zero based ID of sleep enable register (0-4) * m = bit mask of bits to change */ -#define MCHP_PCR_SLP_EN_DEV_MASK(id, m) MCHP_PCR_SLP_EN((id)) |= (m) -#define MCHP_PCR_SLP_DIS_DEV_MASK(id, m) MCHP_PCR_SLP_EN((id)) &= ~(m) - +#define MCHP_PCR_SLP_EN_DEV_MASK(id, m) (MCHP_PCR_SLP_EN((id)) |= (m)) +#define MCHP_PCR_SLP_DIS_DEV_MASK(id, m) (MCHP_PCR_SLP_EN((id)) &= ~(m)) /* Slow Clock Control Mask */ -#define MCHP_PCR_SLOW_CLK_CTL_MASK 0x03FFul - -/* Sleep Enable, Clock Required, Reset on Sleep 0 bits */ -#define MCHP_PCR_ISPI (0x0002) -#define MCHP_PCR_EFUSE (0x0001) -#define MCHP_PCR_JTAG (0x0000) - -/* Command all blocks to sleep */ -#define MCHP_PCR_SLP_EN0_ISPI BIT(2) -#define MCHP_PCR_SLP_EN0_EFUSE BIT(1) -#define MCHP_PCR_SLP_EN0_JTAG BIT(0) -#define MCHP_PCR_SLP_EN0_SLEEP 0x07ul - -/* Sleep Enable, Clock Required, Reset on Sleep 1 bits */ -#define MCHP_PCR_BTMR16_1 (BIT(8) + 31) -#define MCHP_PCR_BTMR16_0 (BIT(8) + 30) -#define MCHP_PCR_ECS (BIT(8) + 29) -#define MCHP_PCR_PWM8 (BIT(8) + 27) -#define MCHP_PCR_PWM7 (BIT(8) + 26) -#define MCHP_PCR_PWM6 (BIT(8) + 25) -#define MCHP_PCR_PWM5 (BIT(8) + 24) -#define MCHP_PCR_PWM4 (BIT(8) + 23) -#define MCHP_PCR_PWM3 (BIT(8) + 22) -#define MCHP_PCR_PWM2 (BIT(8) + 21) -#define MCHP_PCR_PWM1 (BIT(8) + 20) -#define MCHP_PCR_TACH2 (BIT(8) + 12) -#define MCHP_PCR_TACH1 (BIT(8) + 11) -#define MCHP_PCR_I2C0 (BIT(8) + 10) -#define MCHP_PCR_WDT (BIT(8) + 9) -#define MCHP_PCR_CPU (BIT(8) + 8) -#define MCHP_PCR_TFDP (BIT(8) + 7) -#define MCHP_PCR_DMA (BIT(8) + 6) -#define MCHP_PCR_PMC (BIT(8) + 5) -#define MCHP_PCR_PWM0 (BIT(8) + 4) -#define MCHP_PCR_TACH0 (BIT(8) + 2) -#define MCHP_PCR_PECI (BIT(8) + 1) -#define MCHP_PCR_ECIA (BIT(8) + 0) - -/* Command all blocks to sleep */ -#define MCHP_PCR_SLP_EN1_BTMR16_1 BIT(31) -#define MCHP_PCR_SLP_EN1_BTMR16_0 BIT(30) -#define MCHP_PCR_SLP_EN1_ECS BIT(29) -/* bit[28] reserved */ -#define MCHP_PCR_SLP_EN1_PWM_ALL (BIT(4) + (0xff << 20)) -#define MCHP_PCR_SLP_EN1_PWM8 BIT(27) -#define MCHP_PCR_SLP_EN1_PWM7 BIT(26) -#define MCHP_PCR_SLP_EN1_PWM6 BIT(25) -#define MCHP_PCR_SLP_EN1_PWM5 BIT(24) -#define MCHP_PCR_SLP_EN1_PWM4 BIT(23) -#define MCHP_PCR_SLP_EN1_PWM3 BIT(22) -#define MCHP_PCR_SLP_EN1_PWM2 BIT(21) -#define MCHP_PCR_SLP_EN1_PWM1 BIT(20) -/* bits[19:13] reserved */ -#define MCHP_PCR_SLP_EN1_TACH2 BIT(12) -#define MCHP_PCR_SLP_EN1_TACH1 BIT(11) -#define MCHP_PCR_SLP_EN1_I2C0 BIT(10) -#define MCHP_PCR_SLP_EN1_WDT BIT(9) -#define MCHP_PCR_SLP_EN1_CPU BIT(8) -#define MCHP_PCR_SLP_EN1_TFDP BIT(7) -#define MCHP_PCR_SLP_EN1_DMA BIT(6) -#define MCHP_PCR_SLP_EN1_PMC BIT(5) -#define MCHP_PCR_SLP_EN1_PWM0 BIT(4) -/* bit[3] reserved */ -#define MCHP_PCR_SLP_EN1_TACH0 BIT(2) -#define MCHP_PCR_SLP_EN1_PECI BIT(1) -#define MCHP_PCR_SLP_EN1_ECIA BIT(0) -/* all sleep enable 1 bits */ -#define MCHP_PCR_SLP_EN1_SLEEP 0xffffffff -/* - * block not used by default - * Always use ECIA, PMC, CPU and ECS - */ -#define MCHP_PCR_SLP_EN1_UNUSED_BLOCKS 0xdffffede - -/* Sleep Enable2, Clock Required2, Reset on Sleep2 bits */ -#define MCHP_PCR_P80CAP1 ((2 << 8) + 26) -#define MCHP_PCR_P80CAP0 ((2 << 8) + 25) -#define MCHP_PCR_ACPI_EC4 ((2 << 8) + 23) -#define MCHP_PCR_ACPI_EC3 ((2 << 8) + 22) -#define MCHP_PCR_ACPI_EC2 ((2 << 8) + 21) -#define MCHP_PCR_ESPI ((2 << 8) + 19) -#define MCHP_PCR_RTC ((2 << 8) + 18) -#define MCHP_PCR_MBOX ((2 << 8) + 17) -#define MCHP_PCR_8042 ((2 << 8) + 16) -#define MCHP_PCR_ACPI_PM1 ((2 << 8) + 15) -#define MCHP_PCR_ACPI_EC1 ((2 << 8) + 14) -#define MCHP_PCR_ACPI_EC0 ((2 << 8) + 13) -#define MCHP_PCR_GCFG ((2 << 8) + 12) -#define MCHP_PCR_UART1 ((2 << 8) + 2) -#define MCHP_PCR_UART0 ((2 << 8) + 1) -#define MCHP_PCR_LPC ((2 << 8) + 0) - -/* Command all blocks to sleep */ -/* bits[31:27] reserved */ -#define MCHP_PCR_SLP_EN2_P80CAP1 BIT(26) -#define MCHP_PCR_SLP_EN2_P80CAP0 BIT(25) -/* bit[24] reserved */ -#define MCHP_PCR_SLP_EN2_ACPI_EC4 BIT(23) -#define MCHP_PCR_SLP_EN2_ACPI_EC3 BIT(22) -#define MCHP_PCR_SLP_EN2_ACPI_EC2 BIT(21) -/* bit[20] reserved */ -#define MCHP_PCR_SLP_EN2_ESPI BIT(19) -#define MCHP_PCR_SLP_EN2_RTC BIT(18) -#define MCHP_PCR_SLP_EN2_MAILBOX BIT(17) -#define MCHP_PCR_SLP_EN2_MIF8042 BIT(16) -#define MCHP_PCR_SLP_EN2_ACPI_PM1 BIT(15) -#define MCHP_PCR_SLP_EN2_ACPI_EC1 BIT(14) -#define MCHP_PCR_SLP_EN2_ACPI_EC0 BIT(13) -#define MCHP_PCR_SLP_EN2_GCFG BIT(12) -/* bits[11:3] reserved */ -#define MCHP_PCR_SLP_EN2_UART1 BIT(2) -#define MCHP_PCR_SLP_EN2_UART0 BIT(1) -#define MCHP_PCR_SLP_EN2_LPC BIT(0) -/* all sleep enable 2 bits */ -#define MCHP_PCR_SLP_EN2_SLEEP 0x07ffffff - -/* Sleep Enable3, Clock Required3, Reset on Sleep3 bits */ -#define MCHP_PCR_PWM9 ((3 << 8) + 31) -#define MCHP_PCR_CCT0 ((3 << 8) + 30) -#define MCHP_PCR_HTMR1 ((3 << 8) + 29) -#define MCHP_PCR_AESHASH ((3 << 8) + 28) -#define MCHP_PCR_RNG ((3 << 8) + 27) -#define MCHP_PCR_PKE ((3 << 8) + 26) -#define MCHP_PCR_LED3 ((3 << 8) + 25) -#define MCHP_PCR_BTMR32_1 ((3 << 8) + 24) -#define MCHP_PCR_BTMR32_0 ((3 << 8) + 23) -#define MCHP_PCR_BTMR16_3 ((3 << 8) + 22) -#define MCHP_PCR_BTMR16_2 ((3 << 8) + 21) -#define MCHP_PCR_GPSPI1 ((3 << 8) + 20) -#define MCHP_PCR_BCM0 ((3 << 8) + 19) -#define MCHP_PCR_LED2 ((3 << 8) + 18) -#define MCHP_PCR_LED1 ((3 << 8) + 17) -#define MCHP_PCR_LED0 ((3 << 8) + 16) -#define MCHP_PCR_I2C3 ((3 << 8) + 15) -#define MCHP_PCR_I2C2 ((3 << 8) + 14) -#define MCHP_PCR_I2C1 ((3 << 8) + 13) -#define MCHP_PCR_RPMPWM0 ((3 << 8) + 12) -#define MCHP_PCR_KEYSCAN ((3 << 8) + 11) -#define MCHP_PCR_HTMR0 ((3 << 8) + 10) -#define MCHP_PCR_GPSPI0 ((3 << 8) + 9) -#define MCHP_PCR_PS2_2 ((3 << 8) + 7) -#define MCHP_PCR_PS2_1 ((3 << 8) + 6) -#define MCHP_PCR_PS2_0 ((3 << 8) + 5) -#define MCHP_PCR_ADC ((3 << 8) + 3) - -/* Command all blocks to sleep */ -#define MCHP_PCR_SLP_EN3_PWM9 BIT(31) -#define MCHP_PCR_SLP_EN3_CCT0 BIT(30) -#define MCHP_PCR_SLP_EN3_HTMR1 BIT(29) -#define MCHP_PCR_SLP_EN3_AESHASH BIT(28) -#define MCHP_PCR_SLP_EN3_RNG BIT(27) -#define MCHP_PCR_SLP_EN3_PKE BIT(26) -#define MCHP_PCR_SLP_EN3_LED3 BIT(25) -#define MCHP_PCR_SLP_EN3_BTMR32_1 BIT(24) -#define MCHP_PCR_SLP_EN3_BTMR32_0 BIT(23) -#define MCHP_PCR_SLP_EN3_BTMR16_3 BIT(22) -#define MCHP_PCR_SLP_EN3_BTMR16_2 BIT(21) -#define MCHP_PCR_SLP_EN3_GPSPI1 BIT(20) -#define MCHP_PCR_SLP_EN3_BCM0 BIT(19) -#define MCHP_PCR_SLP_EN3_LED2 BIT(18) -#define MCHP_PCR_SLP_EN3_LED1 BIT(17) -#define MCHP_PCR_SLP_EN3_LED0 BIT(16) -#define MCHP_PCR_SLP_EN3_I2C3 BIT(15) -#define MCHP_PCR_SLP_EN3_I2C2 BIT(14) -#define MCHP_PCR_SLP_EN3_I2C1 BIT(13) -#define MCHP_PCR_SLP_EN3_RPMPWM0 BIT(12) -#define MCHP_PCR_SLP_EN3_KEYSCAN BIT(11) -#define MCHP_PCR_SLP_EN3_HTMR0 BIT(10) -#define MCHP_PCR_SLP_EN3_GPSPI0 BIT(9) -/* bit[8] reserved */ -#define MCHP_PCR_SLP_EN3_PS2_2 BIT(7) -#define MCHP_PCR_SLP_EN3_PS2_1 BIT(6) -#define MCHP_PCR_SLP_EN3_PS2_0 BIT(5) -/* bit[4] reserved */ -#define MCHP_PCR_SLP_EN3_ADC BIT(3) -/* bits[2:0] reserved */ -/* all sleep enable 3 bits */ -#define MCHP_PCR_SLP_EN3_SLEEP 0xfffffeed -#define MCHP_PCR_SLP_EN3_PWM_ALL (1ul << 31) - -/* Sleep Enable4, Clock Required4, Reset on Sleep4 bits */ -#define MCHP_PCR_FJCL ((4 << 8) + 15) -#define MCHP_PCR_PSPI ((4 << 8) + 14) -#define MCHP_PCR_PROCHOT ((4 << 8) + 13) -#define MCHP_PCR_RCID2 ((4 << 8) + 12) -#define MCHP_PCR_RCID1 ((4 << 8) + 11) -#define MCHP_PCR_RCID0 ((4 << 8) + 10) -#define MCHP_PCR_BCM1 ((4 << 8) + 9) -#define MCHP_PCR_QMSPI ((4 << 8) + 8) -#define MCHP_PCR_RPMPWM1 ((4 << 8) + 7) -#define MCHP_PCR_RTMR ((4 << 8) + 6) -#define MCHP_PCR_CNT16_3 ((4 << 8) + 5) -#define MCHP_PCR_CNT16_2 ((4 << 8) + 4) -#define MCHP_PCR_CNT16_1 ((4 << 8) + 3) -#define MCHP_PCR_CNT16_0 ((4 << 8) + 2) -#define MCHP_PCR_PWM11 ((4 << 8) + 1) -#define MCHP_PCR_PWM10 ((4 << 8) + 0) - -/* Command all blocks to sleep */ -#define MCHP_PCR_SLP_EN4_FJCL BIT(15) -#define MCHP_PCR_SLP_EN4_PSPI BIT(14) -#define MCHP_PCR_SLP_EN4_PROCHOT BIT(13) -#define MCHP_PCR_SLP_EN4_RCID2 BIT(12) -#define MCHP_PCR_SLP_EN4_RCID1 BIT(11) -#define MCHP_PCR_SLP_EN4_RCID0 BIT(10) -#define MCHP_PCR_SLP_EN4_BCM1 BIT(9) -#define MCHP_PCR_SLP_EN4_QMSPI BIT(8) -#define MCHP_PCR_SLP_EN4_RPMPWM1 BIT(7) -#define MCHP_PCR_SLP_EN4_RTMR BIT(6) -#define MCHP_PCR_SLP_EN4_CNT16_3 BIT(5) -#define MCHP_PCR_SLP_EN4_CNT16_2 BIT(4) -#define MCHP_PCR_SLP_EN4_CNT16_1 BIT(3) -#define MCHP_PCR_SLP_EN4_CNT16_0 BIT(2) -#define MCHP_PCR_SLP_EN4_PWM_ALL (3 << 0) -#define MCHP_PCR_SLP_EN4_PWM11 BIT(1) -#define MCHP_PCR_SLP_EN4_PWM10 BIT(0) -/* all sleep enable 4 bits */ -#define MCHP_PCR_SLP_EN4_SLEEP 0x0000ffff - -/* Allow all blocks to request clocks */ -#define MCHP_PCR_SLP_EN0_WAKE (~(MCHP_PCR_SLP_EN0_SLEEP)) -#define MCHP_PCR_SLP_EN1_WAKE (~(MCHP_PCR_SLP_EN1_SLEEP)) -#define MCHP_PCR_SLP_EN2_WAKE (~(MCHP_PCR_SLP_EN2_SLEEP)) -#define MCHP_PCR_SLP_EN3_WAKE (~(MCHP_PCR_SLP_EN3_SLEEP)) -#define MCHP_PCR_SLP_EN4_WAKE (~(MCHP_PCR_SLP_EN4_SLEEP)) - - -/* Bit definitions for MCHP_PCR_SLP_EN1/CLK_REQ1/RST_EN1 */ - -/* Bit definitions for MCHP_PCR_SLP_EN2/CLK_REQ2/RST_EN2 */ - -/* Bit definitions for MCHP_PCR_SLP_EN3/CLK_REQ3/RST_EN3 */ -#define MCHP_PCR_SLP_EN1_PKE BIT(26) -#define MCHP_PCR_SLP_EN1_NDRNG BIT(27) -#define MCHP_PCR_SLP_EN1_AES_SHA BIT(28) -#define MCHP_PCR_SLP_EN1_ALL_CRYPTO (0x07 << 26) - -/* Bit definitions for MCHP_PCR_SLP_EN4/CLK_REQ4/RST_EN4 */ - - -/* Bit defines for MCHP_PCR_PWR_RST_STS */ -#define MCHP_PWR_RST_STS_VTR BIT(6) -#define MCHP_PWR_RST_STS_VBAT BIT(5) - -/* Bit defines for MCHP_PCR_PWR_RST_CTL */ -#define MCHP_PCR_PWR_HOST_RST_SEL_BITPOS 8 -#define MCHP_PCR_PWR_HOST_RST_LRESET 1 -#define MCHP_PCR_PWR_HOST_RST_ESPI_PLTRST 0 - - -/* Bit defines for MCHP_PCR_SYS_RST */ -#define MCHP_PCR_SYS_SOFT_RESET BIT(8) - +#define MCHP_PCR_SLOW_CLK_CTL_MASK 0x03FFul /* TFDP */ -#define MCHP_TFDP_BASE 0x40008c00 -#define MCHP_TFDP_DATA REG8(MCHP_TFDP_BASE + 0x00) -#define MCHP_TFDP_CTRL REG8(MCHP_TFDP_BASE + 0x04) - - -/* EC Subsystem */ -#define MCHP_EC_BASE 0x4000fc00 -#define MCHP_EC_AHB_ERR REG32(MCHP_EC_BASE + 0x04) -#define MCHP_EC_ID_RO REG32(MCHP_EC_BASE + 0x10) -#define MCHP_EC_AHB_ERR_EN REG32(MCHP_EC_BASE + 0x14) -#define MCHP_EC_INT_CTRL REG32(MCHP_EC_BASE + 0x18) -#define MCHP_EC_TRACE_EN REG32(MCHP_EC_BASE + 0x1c) -#define MCHP_EC_JTAG_EN REG32(MCHP_EC_BASE + 0x20) -#define MCHP_EC_WDT_CNT REG32(MCHP_EC_BASE + 0x28) -#define MCHP_EC_AES_SHA_SWAP_CTRL REG8(MCHP_EC_BASE + 0x2c) -#define MCHP_EC_CRYPTO_SRESET REG8(MCHP_EC_BASE + 0x5c) -#define MCHP_EC_GPIO_BANK_PWR REG8(MCHP_EC_BASE + 0x64) - -/* MCHP_EC_JTAG_EN bit definitions */ -#define MCHP_JTAG_ENABLE 0x01 -/* bits [2:1] */ -#define MCHP_JTAG_MODE_4PIN 0x00 -/* ARM 2-pin SWD plus 1-pin Serial Wire Viewer (ITM) */ -#define MCHP_JTAG_MODE_SWD_SWV 0x02 -/* ARM 2-pin SWD with no SWV */ -#define MCHP_JTAG_MODE_SWD 0x04 - - -/* MCHP_EC_CRYPTO_SRESET bit definitions */ -#define MCHP_CRYPTO_NDRNG_SRST 0x01 -#define MCHP_CRYPTO_PKE_SRST 0x02 -#define MCHP_CRYPTO_AES_SHA_SRST 0x04 -#define MCHP_CRYPTO_ALL_SRST 0x07 - -/* MCHP_GPIO_BANK_PWR bit definitions */ -#define MCHP_EC_GPIO_BANK_PWR_VTR1_18 (0x01) -#define MCHP_EC_GPIO_BANK_PWR_VTR2_18 (0x02) -#define MCHP_EC_GPIO_BANK_PWR_VTR3_18 (0x04) - - -/* AHB ERR Enable */ -#define MCHP_EC_AHB_ERROR_ENABLE 0 -#define MCHP_EC_AHB_ERROR_DISABLE 1 - - -/* Interrupt aggregator */ -#define MCHP_INT_BASE 0x4000e000 -#define MCHP_INTx_BASE(x) (MCHP_INT_BASE + ((x)<<4) + ((x)<<2) - 160) -#define MCHP_INT_SOURCE(x) REG32(MCHP_INTx_BASE(x) + 0x0) -#define MCHP_INT_ENABLE(x) REG32(MCHP_INTx_BASE(x) + 0x4) -#define MCHP_INT_RESULT(x) REG32(MCHP_INTx_BASE(x) + 0x8) -#define MCHP_INT_DISABLE(x) REG32(MCHP_INTx_BASE(x) + 0xc) -#define MCHP_INT_BLK_EN REG32(MCHP_INT_BASE + 0x200) -#define MCHP_INT_BLK_DIS REG32(MCHP_INT_BASE + 0x204) -#define MCHP_INT_BLK_IRQ REG32(MCHP_INT_BASE + 0x208) -#define MCHP_INT_GIRQ_FIRST 8 -#define MCHP_INT_GIRQ_LAST 26 -#define MCHP_INT_GIRQ_NUM (26-8+1) - -/* - * Bits for INT=13(GIRQ13) registers - * SMBus[0:3] = bits[0:3] - */ -#define MCHP_INT13_SMB(x) (1ul << (x)) - - -/* - * Bits for INT=14(GIRQ14) registers - * DMA channels 0 - 13 - */ -#define MCHP_INT14_DMA(x) (1ul << (x)) - - -/* Bits for INT=15(GIRQ15) registers - * UART[0:1] = bits[0:1] - * EMI[0:2] = bits[2:4] - */ -#define MCHP_INT15_UART(x) (1ul << ((x) & 0x01)) -#define MCHP_INT15_EMI(x) (1ul << (2 + (x))) -/* - * ACPI_EC[0:4] IBF = bits[5,7,9,11,13] - * ACPI_EC[0:4] OBE = bits[6,8,10,12,14] - */ -#define MCHP_INT15_ACPI_EC_IBF(x) (1ul << (5 + ((x) << 1))) -#define MCHP_INT15_ACPI_EC_OBE(x) (1ul << (6 + ((x) << 1))) -#define MCHP_INT15_ACPI_PM1_CTL (1ul << 15) -#define MCHP_INT15_ACPI_PM1_EN (1ul << 16) -#define MCHP_INT15_ACPI_PM1_STS (1ul << 17) -#define MCHP_INT15_8042_OBE (1ul << 18) -#define MCHP_INT15_8042_IBF (1ul << 19) -#define MCHP_INT15_MAILBOX (1ul << 20) -#define MCHP_INT15_P80(x) (1ul << (22 + ((x) & 0x01))) - - -/* Bits for INT=16(GIRQ16) registers */ -#define MCHP_INT16_PKE_ERR (1ul << 0) -#define MCHP_INT16_PKE_DONE (1ul << 1) -#define MCHP_INT16_RNG_DONE (1ul << 2) -#define MCHP_INT16_AES_DONE (1ul << 3) -#define MCHP_INT16_HASH_DONE (1ul << 4) - - -/* Bits for INT=17(GIRQ17) registers */ -#define MCHP_INT17_PECI (1ul << 0) -/* TACH[0:2] = bits[1:3] */ -#define MCHP_INT17_TACH(x) (1ul << (1 + (x))) -/* RPMFAN_FAIL[0:1] = bits[4,6] */ -#define MCHP_INT17_RPMFAN_FAIL(x) (1ul << (4 + ((x) << 1))) -/* RPMFAN_STALL[0:1] = bits[5,7] */ -#define MCHP_INT17_RPMFAN_STALL(x) (1ul << (5 + ((x) << 1))) -#define MCHP_INT17_ADC_SINGLE (1ul << 8) -#define MCHP_INT17_ADC_REPEAT (1ul << 9) -/* RCIC[0:2] = bits[10:12] */ -#define MCHP_INT17_RCID(x) (1ul << (10 + (x))) -#define MCHP_INT17_LED_WDT(x) (1ul << (13 + (x))) - - -/* Bits for INT=18(GIRQ18) registers */ -#define MCHP_INT18_LPC (1ul << 0) -#define MCHP_INT18_QMSPI0 (1ul << 1) -/* SPI_TX[0:1] = bits[2,4] */ -#define MCHP_INT18_SPI_TX(x) (1ul << (2 + ((x) << 1))) -/* SPI_RX[0:1] = bits[3,5] */ -#define MCHP_INT18_SPI_RX(x) (1ul << (3 + ((x) << 1))) - - -/* Bits for INT=19(GIRQ19) registers */ -#define MCHP_INT19_ESPI_PC (1ul << 0) -#define MCHP_INT19_ESPI_BM1 (1ul << 1) -#define MCHP_INT19_ESPI_BM2 (1ul << 2) -#define MCHP_INT19_ESPI_LTR (1ul << 3) -#define MCHP_INT19_ESPI_OOB_TX (1ul << 4) -#define MCHP_INT19_ESPI_OOB_RX (1ul << 5) -#define MCHP_INT19_ESPI_FC (1ul << 6) -#define MCHP_INT19_ESPI_RESET (1ul << 7) -#define MCHP_INT19_ESPI_VW_EN (1ul << 8) - - -/* Bits for INT=21(GIRQ21) registers */ -#define MCHP_INT21_RTOS_TMR (1ul << 0) -/* HibernationTimer[0:1] = bits[1:2] */ -#define MCHP_INT21_HIB_TMR(x) (1ul << (1 + (x))) -#define MCHP_INT21_WEEK_ALARM (1ul << 3) -#define MCHP_INT21_WEEK_SUB (1ul << 4) -#define MCHP_INT21_WEEK_1SEC (1ul << 5) -#define MCHP_INT21_WEEK_1SEC_SUB (1ul << 6) -#define MCHP_INT21_WEEK_PWR_PRES (1ul << 7) -#define MCHP_INT21_RTC (1ul << 8) -#define MCHP_INT21_RTC_ALARM (1ul << 9) -#define MCHP_INT21_VCI_OVRD (1ul << 10) -/* VCI_IN[0:6] = bits[11:17] */ -#define MCHP_INT21_VCI_IN(x) (1ul << (11 + (x))) -/* PS2 Port Wake[0:4] =[0A,0B,1A,1B,2] = bits[18:22] */ -#define MCHP_INT21_PS2_WAKE(x) (1ul << (18 + (x))) -#define MCHP_INT21_KEYSCAN (1ul << 25) - -/* Bits for INT=22(GIRQ22) wake only registers */ -#define MCHP_INT22_WAKE_ONLY_LPC (1ul << 0) -#define MCHP_INT22_WAKE_ONLY_I2C0 (1ul << 1) -#define MCHP_INT22_WAKE_ONLY_I2C1 (1ul << 2) -#define MCHP_INT22_WAKE_ONLY_I2C2 (1ul << 3) -#define MCHP_INT22_WAKE_ONLY_I2C3 (1ul << 4) -#define MCHP_INT22_WAKE_ONLY_ESPI (1ul << 9) - -/* Bits for INT=23(GIRQ23) registers */ -/* 16-bit Basic Timers[0:3] = bits[0:3] */ -#define MCHP_INT23_BASIC_TMR16(x) (1ul << (x)) -/* 32-bit Basic Timers[0:1] = bits[4:5] */ -#define MCHP_INT23_BASIC_TMR32(x) (1ul << (4 + (x))) -/* 16-bit Counter-Timer[0:3] = bits[6:9] */ -#define MCHP_INT23_CNT(x) (1ul << (6 + (x))) -#define MCHP_INT23_CCT_TMR (1ul << 10) -/* CCT Capture events[0:5] = bits[11:16] */ -#define MCHP_INT23_CCT_CAP(x) (1ul << (11 + (x))) -/* CCT Compare events[0:1] = bits[17:18] */ -#define MCHP_INT23_CCT_CMP(x) (1ul << (17 + (x))) - - -/* Bits for INT=24(GIRQ24) registers */ -/* Master-to-Slave v=[0:6], Source=[0:3] */ -#define MCHP_INT24_MSVW_SRC(v, s) (1ul << ((4 * (v)) + (s))) - -/* Bits for INT25(GIRQ25) registers */ -/* Master-to-Slave v=[7:10], Source=[0:3] */ -#define MCHP_INT25_MSVW_SRC(v, s) (1ul << ((4 * ((v)-7)) + (s))) - -/* End MCHP_INTxy bit definitions */ - -/* UART Peripheral */ -#define MCHP_UART_CONFIG_BASE(x) (0x400f2700 + ((x) * 0x400)) -#define MCHP_UART_RUNTIME_BASE(x) (0x400f2400 + ((x) * 0x400)) - -#define MCHP_UART_ACT(x) REG8(MCHP_UART_CONFIG_BASE(x) + 0x30) -#define MCHP_UART_CFG(x) REG8(MCHP_UART_CONFIG_BASE(x) + 0xf0) +#define MCHP_TFDP_DATA REG8(MCHP_TFDP_BASE + 0x00) +#define MCHP_TFDP_CTRL REG8(MCHP_TFDP_BASE + 0x04) +/* UART */ +#define MCHP_UART_ACT(x) REG8(MCHP_UART_CONFIG_BASE(x) + 0x30) +#define MCHP_UART_CFG(x) REG8(MCHP_UART_CONFIG_BASE(x) + 0xf0) /* DLAB=0 */ #define MCHP_UART_RB(x) /*R*/ REG8(MCHP_UART_RUNTIME_BASE(x) + 0x0) #define MCHP_UART_TB(x) /*W*/ REG8(MCHP_UART_RUNTIME_BASE(x) + 0x0) -#define MCHP_UART_IER(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x1) +#define MCHP_UART_IER(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x1) /* DLAB=1 */ -#define MCHP_UART_PBRG0(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x0) -#define MCHP_UART_PBRG1(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x1) - +#define MCHP_UART_PBRG0(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x0) +#define MCHP_UART_PBRG1(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x1) #define MCHP_UART_FCR(x) /*W*/ REG8(MCHP_UART_RUNTIME_BASE(x) + 0x2) #define MCHP_UART_IIR(x) /*R*/ REG8(MCHP_UART_RUNTIME_BASE(x) + 0x2) -#define MCHP_UART_LCR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x3) -#define MCHP_UART_MCR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x4) -#define MCHP_UART_LSR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x5) -#define MCHP_UART_MSR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x6) -#define MCHP_UART_SCR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x7) -/* - * UART[0:1] connected to GIRQ15 bits[0:1] - */ -#define MCHP_UART_GIRQ 15 -#define MCHP_UART_GIRQ_BIT(x) (1ul << (x)) - +#define MCHP_UART_LCR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x3) +#define MCHP_UART_MCR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x4) +#define MCHP_UART_LSR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x5) +#define MCHP_UART_MSR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x6) +#define MCHP_UART_SCR(x) REG8(MCHP_UART_RUNTIME_BASE(x) + 0x7) /* Bit defines for MCHP_UARTx_LSR */ -#define MCHP_LSR_TX_EMPTY BIT(5) - - -/* GPIO */ -#define MCHP_GPIO_BASE 0x40081000 - - -/* MCHP each Port contains 32 GPIO's. - * GPIO Control 1 registers are 32-bit registers starting at - * MCHP_GPIO_BASE. - * index = octal GPIO number from MCHP specification. - * port/bank = index >> 5 - * id = index & 0x1F - * - * The port/bank, id pair may also be used to access GPIO's via - * parallel I/O registers if GPIO control is configured for - * parallel I/O. - * - * From ec/chip/mec1701/config_chip.h - * #define GPIO_PIN(index) ((index) >> 5), ((index) & 0x1F) - * - * GPIO Control 1 Address = 0x40081000 + (((bank << 5) + id) << 2) - * - * Example: GPIO043, Control 1 register address = 0x4008108c - * port/bank = 0x23 >> 5 = 1 - * id = 0x23 & 0x1F = 0x03 - * Control 1 Address = 0x40081000 + ((BIT(5) + 0x03) << 2) = 0x4008108c - * - * Example: GPIO235, Control 1 register address = 0x40081274 - * port/bank = 0x9d >> 5 = 4 - * id = 0x9d & 0x1f = 0x1d - * Control 1 Address = 0x40081000 + (((4 << 5) + 0x1d) << 2) = 0x40081274 - * - */ -#define MCHP_GPIO_CTL(port, id) REG32(MCHP_GPIO_BASE + \ - (((port << 5) + id) << 2)) - -/* MCHP implements 6 GPIO ports */ -#define MCHP_GPIO_MAX_PORT (7) - -#define UNIMPLEMENTED_GPIO_BANK 0 - -/* - * MEC1701 documentation GPIO numbers are octal, each control - * register is located on a 32-bit boundary. - */ -#define MCHP_GPIO_CTRL(gpio_num) REG32(MCHP_GPIO_BASE + \ - ((gpio_num) << 2)) - -/* - * GPIO control register bit fields - */ -#define MCHP_GPIO_CTRL_PUD_BITPOS 0 -#define MCHP_GPIO_CTRL_PUD_MASK0 0x03 -#define MCHP_GPIO_CTRL_PUD_MASK 0x03 -#define MCHP_GPIO_CTRL_PUD_NONE 0x00 -#define MCHP_GPIO_CTRL_PUD_PU 0x01 -#define MCHP_GPIO_CTRL_PUD_PD 0x02 -#define MCHP_GPIO_CTRL_PUD_KEEPER 0x03 -#define MCHP_GPIO_CTRL_PWR_BITPOS 2 -#define MCHP_GPIO_CTRL_PWR_MASK0 0x03 -#define MCHP_GPIO_CTRL_PWR_MASK (0x03 << 2) -#define MCHP_GPIO_CTRL_PWR_VTR (0x00 << 2) -#define MCHP_GPIO_CTRL_PWR_OFF (0x02 << 2) -#define MCHP_GPIO_INTDET_MASK (0xF0) -#define MCHP_GPIO_INTDET_LVL_LO (0x00) -#define MCHP_GPIO_INTDET_LVL_HI (0x10) -#define MCHP_GPIO_INTDET_DISABLED (0x40) -#define MCHP_GPIO_INTDET_EDGE_RIS (0xD0) -#define MCHP_GPIO_INTDET_EDGE_FALL (0xE0) -#define MCHP_GPIO_INTDET_EDGE_BOTH (0xF0) -#define MCHP_GPIO_INTDET_EDGE_EN (1u << 7) -#define MCHP_GPIO_PUSH_PULL (0u << 8) -#define MCHP_GPIO_OPEN_DRAIN (1u << 8) -#define MCHP_GPIO_INPUT (0u << 9) -#define MCHP_GPIO_OUTPUT (1u << 9) -#define MCHP_GPIO_OUTSET_CTRL (0u << 10) -#define MCHP_GPIO_OUTSEL_PAR (1u << 10) -#define MCHP_GPIO_POLARITY_NINV (0u << 11) -#define MCHP_GPIO_POLARITY_INV (1u << 11) -#define MCHP_GPIO_CTRL_ALT_FUNC_BITPOS 12 -#define MCHP_GPIO_CTRL_ALT_FUNC_MASK0 0x0F -#define MCHP_GPIO_CTRL_ALT_FUNC_MASK (0x0F << 12) -#define MCHP_GPIO_CTRL_FUNC_GPIO (0 << 12) -#define MCHP_GPIO_CTRL_FUNC_1 (1 << 12) -#define MCHP_GPIO_CTRL_FUNC_2 (2 << 12) -#define MCHP_GPIO_CTRL_FUNC_3 (3 << 12) -#define MCHP_GPIO_CTRL_OUT_LVL BIT(16) - -/* GPIO Parallel Input and Output registers. - * gpio_bank in [0, 5] - */ -#define MCHP_GPIO_PARIN(gpio_bank) REG32(MCHP_GPIO_BASE + 0x0300 +\ - ((gpio_bank) << 2)) - -#define MCHP_GPIO_PAROUT(gpio_bank) REG32(MCHP_GPIO_BASE + 0x0380 +\ - ((gpio_bank) << 2)) +#define MCHP_LSR_TX_EMPTY BIT(5) /* Timer */ -#define MCHP_TMR16_MAX (4) -#define MCHP_TMR32_MAX (2) -#define MCHP_TMR16_BASE(x) (0x40000c00 + (x) * 0x20) -#define MCHP_TMR32_BASE(x) (0x40000c80 + (x) * 0x20) - -#define MCHP_TMR16_CNT(x) REG32(MCHP_TMR16_BASE(x) + 0x0) -#define MCHP_TMR16_PRE(x) REG32(MCHP_TMR16_BASE(x) + 0x4) -#define MCHP_TMR16_STS(x) REG32(MCHP_TMR16_BASE(x) + 0x8) -#define MCHP_TMR16_IEN(x) REG32(MCHP_TMR16_BASE(x) + 0xc) -#define MCHP_TMR16_CTL(x) REG32(MCHP_TMR16_BASE(x) + 0x10) -#define MCHP_TMR32_CNT(x) REG32(MCHP_TMR32_BASE(x) + 0x0) -#define MCHP_TMR32_PRE(x) REG32(MCHP_TMR32_BASE(x) + 0x4) -#define MCHP_TMR32_STS(x) REG32(MCHP_TMR32_BASE(x) + 0x8) -#define MCHP_TMR32_IEN(x) REG32(MCHP_TMR32_BASE(x) + 0xc) -#define MCHP_TMR32_CTL(x) REG32(MCHP_TMR32_BASE(x) + 0x10) -/* 16-bit Basic Timers[0:3] = GIRQ23 bits[0:3] */ -#define MCHP_TMR16_GIRQ 23 -#define MCHP_TMR16_GIRQ_BIT(x) (1ul << (x)) -/* 32-bit Basic Timers[0:1] = GIRQ23 bits[4:5] */ -#define MCHP_TMR32_GIRQ 23 -#define MCHP_TMR32_GIRQ_BIT(x) (1ul << ((x) + 4)) +#define MCHP_TMR16_CNT(x) REG32(MCHP_TMR16_BASE(x) + 0x0) +#define MCHP_TMR16_PRE(x) REG32(MCHP_TMR16_BASE(x) + 0x4) +#define MCHP_TMR16_STS(x) REG32(MCHP_TMR16_BASE(x) + 0x8) +#define MCHP_TMR16_IEN(x) REG32(MCHP_TMR16_BASE(x) + 0xc) +#define MCHP_TMR16_CTL(x) REG32(MCHP_TMR16_BASE(x) + 0x10) +#define MCHP_TMR32_CNT(x) REG32(MCHP_TMR32_BASE(x) + 0x0) +#define MCHP_TMR32_PRE(x) REG32(MCHP_TMR32_BASE(x) + 0x4) +#define MCHP_TMR32_STS(x) REG32(MCHP_TMR32_BASE(x) + 0x8) +#define MCHP_TMR32_IEN(x) REG32(MCHP_TMR32_BASE(x) + 0xc) +#define MCHP_TMR32_CTL(x) REG32(MCHP_TMR32_BASE(x) + 0x10) /* RTimer */ -#define MCHP_RTMR_BASE (0x40007400) -#define MCHP_RTMR_COUNTER REG32(MCHP_RTMR_BASE + 0x00) -#define MCHP_RTMR_PRELOAD REG32(MCHP_RTMR_BASE + 0x04) -#define MCHP_RTMR_CONTROL REG8(MCHP_RTMR_BASE + 0x08) -#define MCHP_RTMR_SOFT_INTR REG8(MCHP_RTMR_BASE + 0x0c) -/* RTimer GIRQ21 bit[0] */ -#define MCHP_RTMR_GIRQ 21 -#define MCHP_RTMR_GIRQ_BIT(x) (1ul << 0) - -/* Watchdog */ -#define MCHP_WDG_BASE 0x40000000 -#define MCHP_WDG_LOAD REG16(MCHP_WDG_BASE + 0x0) -#define MCHP_WDG_CTL REG8(MCHP_WDG_BASE + 0x4) -#define MCHP_WDG_KICK REG8(MCHP_WDG_BASE + 0x8) -#define MCHP_WDG_CNT REG16(MCHP_WDG_BASE + 0xc) - - -/* VBAT */ -#define MCHP_VBAT_BASE 0x4000a400 -#define MCHP_VBAT_STS REG32(MCHP_VBAT_BASE + 0x0) -#define MCHP_VBAT_CE REG32(MCHP_VBAT_BASE + 0x8) -#define MCHP_VBAT_SHDN_DIS REG32(MCHP_VBAT_BASE + 0xC) -#define MCHP_VBAT_MONOTONIC_CTR_LO REG32(MCHP_VBAT_BASE + 0x20) -#define MCHP_VBAT_MONOTONIC_CTR_HI REG32(MCHP_VBAT_BASE + 0x24) -/* read 32-bit word at 32-bit offset x where 0 <= x <= 31 */ -#define MCHP_VBAT_RAM(x) REG32(MCHP_VBAT_BASE + 0x400 + ((x) * 4)) -#define MCHP_VBAT_VWIRE_BACKUP 30 - -/* Bit definition for MCHP_VBAT_STS */ -#define MCHP_VBAT_STS_SOFTRESET BIT(2) -#define MCHP_VBAT_STS_RESETI BIT(4) -#define MCHP_VBAT_STS_WDT BIT(5) -#define MCHP_VBAT_STS_SYSRESETREQ BIT(6) -#define MCHP_VBAT_STS_VBAT_RST BIT(7) -#define MCHP_VBAT_STS_ANY_RST (0xF4u) - -/* Bit definitions for MCHP_VBAT_CE */ -#define MCHP_VBAT_CE_XOSEL_BITPOS (3) -#define MCHP_VBAT_CE_XOSEL_MASK (1ul << 3) -#define MCHP_VBAT_CE_XOSEL_PAR (0ul << 3) -#define MCHP_VBAT_CE_XOSEL_SE (1ul << 3) - -#define MCHP_VBAT_CE_32K_SRC_BITPOS (2) -#define MCHP_VBAT_CE_32K_SRC_MASK (1ul << 2) -#define MCHP_VBAT_CE_32K_SRC_INT (0ul << 2) -#define MCHP_VBAT_CE_32K_SRC_CRYS (1ul << 2) - -#define MCHP_VBAT_CE_EXT_32K_BITPOS (1) -#define MCHP_VBAT_CE_EXT_32K_MASK (1ul << 1) -#define MCHP_VBAT_CE_INT_32K (0ul << 1) -#define MCHP_VBAT_CE_EXT_32K (1ul << 1) - -#define MCHP_VBAT_CE_32K_VTR_BITPOS (0) -#define MCHP_VBAT_CE_32K_VTR_MASK (1ul << 0) -#define MCHP_VBAT_CE_32K_VTR_ON (0ul << 0) -#define MCHP_VBAT_CE_32K_VTR_OFF (1ul << 0) - - -/* - * Blinking-Breathing LED - * 4 instances - */ -#define MCHP_BBLED_BASE(x) (0x4000B800 + (((x) & 0x03) << 8)) -#define MCHP_BBLEN_INSTANCES 4 - -#define MCHP_BBLED_CONFIG(x) REG32(MCHP_BBLED_BASE(x) + 0x00) -#define MCHP_BBLED_LIMITS(x) REG32(MCHP_BBLED_BASE(x) + 0x04) -#define MCHP_BBLED_LIMIT_MIN(x) REG8(MCHP_BBLED_BASE(x) + 0x04) -#define MCHP_BBLED_LIMIT_MAX(x) REG8(MCHP_BBLED_BASE(x) + 0x06) -#define MCHP_BBLED_DELAY(x) REG32(MCHP_BBLED_BASE(x) + 0x08) -#define MCHP_BBLED_UPDATE_STEP(x) REG32(MCHP_BBLED_BASE(x) + 0x0C) -#define MCHP_BBLED_UPDATE_INTV(x) REG32(MCHP_BBLED_BASE(x) + 0x10) -#define MCHP_BBLED_OUTPUT_DLY(x) REG8(MCHP_BBLED_BASE(x) + 0x14) - +#define MCHP_RTMR_COUNTER REG32(MCHP_RTMR_BASE + 0x00) +#define MCHP_RTMR_PRELOAD REG32(MCHP_RTMR_BASE + 0x04) +#define MCHP_RTMR_CONTROL REG8(MCHP_RTMR_BASE + 0x08) +#define MCHP_RTMR_SOFT_INTR REG8(MCHP_RTMR_BASE + 0x0c) + +/* Watch dog timer */ +#define MCHP_WDG_LOAD REG16(MCHP_WDG_BASE + 0x0) +#define MCHP_WDG_CTL REG16(MCHP_WDG_BASE + 0x4) +#define MCHP_WDG_KICK REG8(MCHP_WDG_BASE + 0x8) +#define MCHP_WDG_CNT REG16(MCHP_WDG_BASE + 0xc) +#define MCHP_WDT_CTL_ENABLE BIT(0) +#define MCHP_WDT_CTL_HTMR_STALL_EN BIT(2) +#define MCHP_WDT_CTL_WKTMR_STALL_EN BIT(3) +#define MCHP_WDT_CTL_JTAG_STALL_EN BIT(4) + +/* Blinking-Breathing LED */ +#define MCHP_BBLED_CONFIG(x) REG32(MCHP_BBLED_BASE(x) + 0x00) +#define MCHP_BBLED_LIMITS(x) REG32(MCHP_BBLED_BASE(x) + 0x04) +#define MCHP_BBLED_LIMIT_MIN(x) REG8(MCHP_BBLED_BASE(x) + 0x04) +#define MCHP_BBLED_LIMIT_MAX(x) REG8(MCHP_BBLED_BASE(x) + 0x06) +#define MCHP_BBLED_DELAY(x) REG32(MCHP_BBLED_BASE(x) + 0x08) +#define MCHP_BBLED_UPDATE_STEP(x) REG32(MCHP_BBLED_BASE(x) + 0x0C) +#define MCHP_BBLED_UPDATE_INTV(x) REG32(MCHP_BBLED_BASE(x) + 0x10) +#define MCHP_BBLED_OUTPUT_DLY(x) REG8(MCHP_BBLED_BASE(x) + 0x14) /* BBLED Configuration Register */ -#define MCHP_BBLED_ASYMMETRIC (1ul << 16) -#define MCHP_BBLED_WDT_RELOAD_BITPOS (8) -#define MCHP_BBLED_WDT_RELOAD_MASK0 (0xFFul) -#define MCHP_BBLED_WDT_RELOAD_MASK (0xFFul << 8) -#define MCHP_BBLED_RESET (1ul << 7) -#define MCHP_BBLED_EN_UPDATE (1ul << 6) -#define MCHP_BBLED_PWM_SIZE_BITPOS (4) -#define MCHP_BBLED_PWM_SIZE_MASK0 (0x03ul) -#define MCHP_BBLED_PWM_SIZE_MASK (0x03ul << 4) -#define MCHP_BBLED_PWM_SIZE_6BIT (0x02ul << 4) -#define MCHP_BBLED_PWM_SIZE_7BIT (0x01ul << 4) -#define MCHP_BBLED_PWM_SIZE_8BIT (0x00ul << 4) -#define MCHP_BBLED_SYNC (1ul << 3) -#define MCHP_BBLED_CLK_48M (1ul << 2) -#define MCHP_BBLED_CLK_32K (0ul << 2) -#define MCHP_BBLED_CTRL_MASK (0x03ul) -#define MCHP_BBLED_CTRL_ALWAYS_ON (0x03ul) -#define MCHP_BBLED_CTRL_BLINK (0x02ul) -#define MCHP_BBLED_CTRL_BREATHE (0x01ul) -#define MCHP_BBLED_CTRL_OFF (0x00ul) - +#define MCHP_BBLED_ASYMMETRIC BIT(16) +#define MCHP_BBLED_WDT_RELOAD_BITPOS 8 +#define MCHP_BBLED_WDT_RELOAD_MASK0 0xFFul +#define MCHP_BBLED_WDT_RELOAD_MASK (0xFFul << 8) +#define MCHP_BBLED_RESET BIT(7) +#define MCHP_BBLED_EN_UPDATE BIT(6) +#define MCHP_BBLED_PWM_SIZE_BITPOS 4 +#define MCHP_BBLED_PWM_SIZE_MASK0 0x03ul +#define MCHP_BBLED_PWM_SIZE_MASK (0x03ul << 4) +#define MCHP_BBLED_PWM_SIZE_6BIT (0x02ul << 4) +#define MCHP_BBLED_PWM_SIZE_7BIT (0x01ul << 4) +#define MCHP_BBLED_PWM_SIZE_8BIT (0x00ul << 4) +#define MCHP_BBLED_SYNC BIT(3) +#define MCHP_BBLED_CLK_48M BIT(2) +#define MCHP_BBLED_CLK_32K 0 +#define MCHP_BBLED_CTRL_MASK 0x03ul +#define MCHP_BBLED_CTRL_ALWAYS_ON 0x03ul +#define MCHP_BBLED_CTRL_BLINK 0x02ul +#define MCHP_BBLED_CTRL_BREATHE 0x01ul +#define MCHP_BBLED_CTRL_OFF 0x00ul /* BBLED Delay Register */ -#define MCHP_BBLED_DLY_MASK (0x0FFFul) -#define MCHP_BBLED_DLY_LO_BITPOS (0) -#define MCHP_BBLED_DLY_LO_MASK (0x0FFFul << 0) -#define MCHP_BBLED_DLY_HI_BITPOS (12) -#define MCHP_BBLED_DLY_HI_MASK (0x0FFFul << 12) - +#define MCHP_BBLED_DLY_MASK 0x0FFFul +#define MCHP_BBLED_DLY_LO_BITPOS 0 +#define MCHP_BBLED_DLY_LO_MASK 0x0FFFul +#define MCHP_BBLED_DLY_HI_BITPOS 12 +#define MCHP_BBLED_DLY_HI_MASK (0x0FFFul << 12) /* * BBLED Update Step Register * 8 update fields numbered 0 - 7 */ -#define MCHP_BBLED_UPD_STEP_MASK0 (0x0Ful) -#define MCHP_BBLED_UPD_STEP_MASK(u) (0x0Ful << (((u) & 0x07) + 4)) - +#define MCHP_BBLED_UPD_STEP_MASK0 0x0Ful +#define MCHP_BBLED_UPD_STEP_MASK(u) (0x0Ful << (((u)&0x07) + 4)) /* * BBLED Update Interval Register * 8 interval fields numbered 0 - 7 */ -#define MCHP_BBLED_UPD_INTV_MASK0 (0x0Ful) -#define MCHP_BBLED_UPD_INTV_MASK(i) (0x0Ful << (((i) & 0x07) + 4)) - - -/* Miscellaneous firmware control fields - * scratch pad index cannot be more than 32 as - * MCHP has 128 bytes = 32 indexes of scratchpad RAM - */ -#define MCHP_IMAGETYPE_IDX 31 - - -/* LPC */ -#define MCHP_LPC_CFG_BASE 0x400f3300 -#define MCHP_LPC_ACT REG8(MCHP_LPC_CFG_BASE + 0x30) -#define MCHP_LPC_SIRQ(x) REG8(MCHP_LPC_CFG_BASE + 0x40 + (x)) -#define MCHP_LPC_CFG_BAR REG32(MCHP_LPC_CFG_BASE + 0x60) -#define MCHP_LPC_MAILBOX_BAR REG32(MCHP_LPC_CFG_BASE + 0x64) -#define MCHP_LPC_8042_BAR REG32(MCHP_LPC_CFG_BASE + 0x68) -#define MCHP_LPC_ACPI_EC0_BAR REG32(MCHP_LPC_CFG_BASE + 0x6C) -#define MCHP_LPC_ACPI_EC1_BAR REG32(MCHP_LPC_CFG_BASE + 0x70) -#define MCHP_LPC_ACPI_EC2_BAR REG32(MCHP_LPC_CFG_BASE + 0x74) -#define MCHP_LPC_ACPI_EC3_BAR REG32(MCHP_LPC_CFG_BASE + 0x78) -#define MCHP_LPC_ACPI_EC4_BAR REG32(MCHP_LPC_CFG_BASE + 0x7C) -#define MCHP_LPC_ACPI_PM1_BAR REG32(MCHP_LPC_CFG_BASE + 0x80) -#define MCHP_LPC_PORT92_BAR REG32(MCHP_LPC_CFG_BASE + 0x84) -#define MCHP_LPC_UART0_BAR REG32(MCHP_LPC_CFG_BASE + 0x88) -#define MCHP_LPC_UART1_BAR REG32(MCHP_LPC_CFG_BASE + 0x8C) -#define MCHP_LPC_EMI0_BAR REG32(MCHP_LPC_CFG_BASE + 0x90) -#define MCHP_LPC_EMI1_BAR REG32(MCHP_LPC_CFG_BASE + 0x94) -#define MCHP_LPC_EMI2_BAR REG32(MCHP_LPC_CFG_BASE + 0x98) -#define MCHP_LPC_P80DBG0_BAR REG32(MCHP_LPC_CFG_BASE + 0x9C) -#define MCHP_LPC_P80DBG1_BAR REG32(MCHP_LPC_CFG_BASE + 0xA0) -#define MCHP_LPC_RTC_BAR REG32(MCHP_LPC_CFG_BASE + 0xA4) - -#define MCHP_LPC_ACPI_EC_BAR(x) REG32(MCHP_LPC_CFG_BASE + 0x6C + ((x)<<2)) - -/* LPC BAR bits */ -#define MCHP_LPC_IO_BAR_ADDR_BITPOS (16) -#define MCHP_LPC_IO_BAR_EN (1ul << 15) - -/* LPC Generic Memory BAR's, 64-bit registers */ -#define MCHP_LPC_SRAM0_BAR_LO REG32(MCHP_LPC_CFG_BASE + 0xB0) -#define MCHP_LPC_SRAM0_BAR_HI REG32(MCHP_LPC_CFG_BASE + 0xB4) -#define MCHP_LPC_SRAM1_BAR_LO REG32(MCHP_LPC_CFG_BASE + 0xB8) -#define MCHP_LPC_SRAM1_BAR_HI REG32(MCHP_LPC_CFG_BASE + 0xBC) - -/* - * LPC Logical Device Memory BAR's, 48-bit registers - * Use 16-bit aligned access - */ -#define MCHP_LPC_MAILBOX_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xC0) -#define MCHP_LPC_MAILBOX_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xC2) -#define MCHP_LPC_MAILBOX_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xC4) -#define MCHP_LPC_ACPI_EC0_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xC6) -#define MCHP_LPC_ACPI_EC0_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xC8) -#define MCHP_LPC_ACPI_EC0_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xCA) -#define MCHP_LPC_ACPI_EC1_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xCC) -#define MCHP_LPC_ACPI_EC1_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xCE) -#define MCHP_LPC_ACPI_EC1_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xD0) -#define MCHP_LPC_ACPI_EC2_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xD2) -#define MCHP_LPC_ACPI_EC2_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xD4) -#define MCHP_LPC_ACPI_EC2_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xD6) -#define MCHP_LPC_ACPI_EC3_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xD8) -#define MCHP_LPC_ACPI_EC3_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xDA) -#define MCHP_LPC_ACPI_EC3_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xDC) -#define MCHP_LPC_ACPI_EC4_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xDE) -#define MCHP_LPC_ACPI_EC4_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xE0) -#define MCHP_LPC_ACPI_EC4_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xE2) -#define MCHP_LPC_ACPI_EMI0_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xE4) -#define MCHP_LPC_ACPI_EMI0_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xE6) -#define MCHP_LPC_ACPI_EMI0_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xE8) -#define MCHP_LPC_ACPI_EMI1_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xEA) -#define MCHP_LPC_ACPI_EMI1_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xEC) -#define MCHP_LPC_ACPI_EMI1_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xEE) -#define MCHP_LPC_ACPI_EMI2_MEM_BAR_H0 REG32(MCHP_LPC_CFG_BASE + 0xF0) -#define MCHP_LPC_ACPI_EMI2_MEM_BAR_H1 REG32(MCHP_LPC_CFG_BASE + 0xF2) -#define MCHP_LPC_ACPI_EMI2_MEM_BAR_H2 REG32(MCHP_LPC_CFG_BASE + 0xF4) - - -#define MCHP_LPC_RT_BASE 0x400f3100 -#define MCHP_LPC_BUS_MONITOR REG32(MCHP_LPC_RT_BASE + 0x4) -#define MCHP_LPC_HOST_ERROR REG32(MCHP_LPC_RT_BASE + 0x8) -#define MCHP_LPC_EC_SERIRQ REG32(MCHP_LPC_RT_BASE + 0xC) -#define MCHP_LPC_EC_CLK_CTRL REG32(MCHP_LPC_RT_BASE + 0x10) -#define MCHP_LPC_BAR_INHIBIT REG32(MCHP_LPC_RT_BASE + 0x20) -#define MCHP_LPC_BAR_INIT REG32(MCHP_LPC_RT_BASE + 0x30) -#define MCHP_LPC_SRAM0_BAR REG32(MCHP_LPC_RT_BASE + 0xf8) -#define MCHP_LPC_SRAM1_BAR REG32(MCHP_LPC_RT_BASE + 0xfc) - +#define MCHP_BBLED_UPD_INTV_MASK0 0x0Ful +#define MCHP_BBLED_UPD_INTV_MASK(i) (0x0Ful << (((i)&0x07) + 4)) /* EMI */ -#define MCHP_EMI_BASE(x) (0x400F4100 + ((x) << 10)) -#define MCHP_EMI_H2E_MBX(x) REG8(MCHP_EMI_BASE(x) + 0x0) -#define MCHP_EMI_E2H_MBX(x) REG8(MCHP_EMI_BASE(x) + 0x1) -#define MCHP_EMI_MBA0(x) REG32(MCHP_EMI_BASE(x) + 0x4) -#define MCHP_EMI_MRL0(x) REG16(MCHP_EMI_BASE(x) + 0x8) -#define MCHP_EMI_MWL0(x) REG16(MCHP_EMI_BASE(x) + 0xa) -#define MCHP_EMI_MBA1(x) REG32(MCHP_EMI_BASE(x) + 0xc) -#define MCHP_EMI_MRL1(x) REG16(MCHP_EMI_BASE(x) + 0x10) -#define MCHP_EMI_MWL1(x) REG16(MCHP_EMI_BASE(x) + 0x12) -#define MCHP_EMI_ISR(x) REG16(MCHP_EMI_BASE(x) + 0x14) -#define MCHP_EMI_HCE(x) REG16(MCHP_EMI_BASE(x) + 0x16) - -#define MCHP_EMI_RT_BASE(x) (0x400F4000 + ((x) << 10)) -#define MCHP_EMI_ISR_B0(x) REG8(MCHP_EMI_RT_BASE(x) + 0x8) -#define MCHP_EMI_ISR_B1(x) REG8(MCHP_EMI_RT_BASE(x) + 0x9) -#define MCHP_EMI_IMR_B0(x) REG8(MCHP_EMI_RT_BASE(x) + 0xa) -#define MCHP_EMI_IMR_B1(x) REG8(MCHP_EMI_RT_BASE(x) + 0xb) -/* - * EMI[0:2] on GIRQ15 bits[2:4] - */ -#define MCHP_EMI_GIRQ 15 -#define MCHP_EMI_GIRQ_BIT(x) (1ul << ((x)+2)) - +#define MCHP_EMI_H2E_MBX(n) REG8(MCHP_EMI_BASE(n) + 0x0) +#define MCHP_EMI_E2H_MBX(n) REG8(MCHP_EMI_BASE(n) + 0x1) +#define MCHP_EMI_MBA0(n) REG32(MCHP_EMI_BASE(n) + 0x4) +#define MCHP_EMI_MRL0(n) REG16(MCHP_EMI_BASE(n) + 0x8) +#define MCHP_EMI_MWL0(n) REG16(MCHP_EMI_BASE(n) + 0xa) +#define MCHP_EMI_MBA1(n) REG32(MCHP_EMI_BASE(n) + 0xc) +#define MCHP_EMI_MRL1(n) REG16(MCHP_EMI_BASE(n) + 0x10) +#define MCHP_EMI_MWL1(n) REG16(MCHP_EMI_BASE(n) + 0x12) +#define MCHP_EMI_ISR(n) REG16(MCHP_EMI_BASE(n) + 0x14) +#define MCHP_EMI_HCE(n) REG16(MCHP_EMI_BASE(n) + 0x16) +#define MCHP_EMI_ISR_B0(n) REG8(MCHP_EMI_RT_BASE(n) + 0x8) +#define MCHP_EMI_ISR_B1(n) REG8(MCHP_EMI_RT_BASE(n) + 0x9) +#define MCHP_EMI_IMR_B0(n) REG8(MCHP_EMI_RT_BASE(n) + 0xa) +#define MCHP_EMI_IMR_B1(n) REG8(MCHP_EMI_RT_BASE(n) + 0xb) /* Mailbox */ -#define MCHP_MBX_RT_BASE 0x400f0000 -#define MCHP_MBX_INDEX REG8(MCHP_MBX_RT_BASE + 0x0) -#define MCHP_MBX_DATA REG8(MCHP_MBX_RT_BASE + 0x1) - -#define MCHP_MBX_BASE 0x400f0100 -#define MCHP_MBX_H2E_MBX REG8(MCHP_MBX_BASE + 0x0) -#define MCHP_MBX_E2H_MBX REG8(MCHP_MBX_BASE + 0x4) -#define MCHP_MBX_ISR REG8(MCHP_MBX_BASE + 0x8) -#define MCHP_MBX_IMR REG8(MCHP_MBX_BASE + 0xc) -#define MCHP_MBX_REG(x) REG8(MCHP_MBX_BASE + 0x10 + (x)) -/* - * Mailbox on GIRQ15 bit[20] - */ -#define MCHP_MBX_GIRQ 15 -#define MCHP_MBX_GIRQ_BIT (1ul << 20) - - -/* Port80 Capture */ -#define MCHP_P80_BASE(x) (0x400f8000 + ((x) << 10)) -#define MCHP_P80_HOST_DATA(x) REG8(MCHP_P80_BASE(x)) -/* Data catpure with timestamp register */ -#define MCHP_P80_CAP(x) REG32(MCHP_P80_BASE(x) + 0x100) -#define MCHP_P80_CFG(x) REG8(MCHP_P80_BASE(x) + 0x104) -#define MCHP_P80_STS(x) REG8(MCHP_P80_BASE(x) + 0x108) -#define MCHP_P80_CNT(x) REG32(MCHP_P80_BASE(x) + 0x10c) -#define MCHP_P80_CNT_GET(x) (REG32(MCHP_P80_BASE(x) + 0x10c) >> 8) -#define MCHP_P80_CNT_SET(x, c) (REG32(MCHP_P80_BASE(x) + 0x10c) = (c << 8)) -#define MCHP_P80_ACTIVATE(x) REG8(MCHP_P80_BASE(x) + 0x330) -/* - * Port80 [0:1] GIRQ15 bits[22:23] - */ -#define MCHP_P80_GIRQ 15 -#define MCHP_P80_GIRQ_BIT(x) (1ul << ((x) + 22)) - -/* Port80 Data register bits - * bits[7:0] = data captured on Host write - * bits[31:8] = optional time stamp - */ -#define MCHP_P80_CAP_DATA_MASK 0xFFul -#define MCHP_P80_CAP_TS_BITPOS 8 -#define MCHP_P80_CAP_TS_MASK0 0xfffffful -#define MCHP_P80_CAP_TS_MASK (\ - (MCHP_P80_CAP_TS_MASK0) << (MCHP_P80_CAP_TS_BITPOS)) - -/* Port80 Configuration register bits */ -#define MCHP_P80_FLUSH_FIFO_WO (1u << 1) -#define MCHP_P80_RESET_TIMESTAMP_WO (1u << 2) -#define MCHP_P80_TIMEBASE_BITPOS 3 -#define MCHP_P80_TIMEBASE_MASK0 0x03 -#define MCHP_P80_TIMEBASE_MASK (\ - (MCHP_P80_TIMEBASE_MASK0) << (MCHP_P80_TIMEBASE_BITPOS)) -#define MCHP_P80_TIMEBASE_750KHZ (\ - 0x03 << (MCHP_P80_TIMEBASE_BITPOS)) -#define MCHP_P80_TIMEBASE_1500KHZ (\ - 0x02 << (MCHP_P80_TIMEBASE_BITPOS)) -#define MCHP_P80_TIMEBASE_3MHZ (\ - 0x01 << (MCHP_P80_TIMEBASE_BITPOS)) -#define MCHP_P80_TIMEBASE_6MHZ (\ - 0x00 << (MCHP_P80_TIMEBASE_BITPOS)) -#define MCHP_P80_TIMER_ENABLE (1u << 5) -#define MCHP_P80_FIFO_THRHOLD_MASK (3u << 6) -#define MCHP_P80_FIFO_THRHOLD_1 (0u << 6) -#define MCHP_P80_FIFO_THRHOLD_4 (1u << 6) -#define MCHP_P80_FIFO_THRHOLD_8 (2u << 6) -#define MCHP_P80_FIFO_THRHOLD_14 (3u << 6) -#define MCHP_P80_FIFO_LEN 16 - -/* Port80 Status register bits, read-only */ -#define MCHP_P80_STS_NOT_EMPTY 0x01 -#define MCHP_P80_STS_OVERRUN 0x02 - -/* Port80 Count register bits */ -#define MCHP_P80_CNT_BITPOS 8 -#define MCHP_P80_CNT_MASK0 0xfffffful -#define MCHP_P80_CNT_MASK ((MCHP_P80_CNT_MASK0) <<\ - (MCHP_P80_CNT_BITPOS)) - +#define MCHP_MBX_INDEX REG8(MCHP_MBX_RT_BASE + 0x0) +#define MCHP_MBX_DATA REG8(MCHP_MBX_RT_BASE + 0x1) +#define MCHP_MBX_H2E_MBX REG8(MCHP_MBX_BASE + 0x0) +#define MCHP_MBX_E2H_MBX REG8(MCHP_MBX_BASE + 0x4) +#define MCHP_MBX_ISR REG8(MCHP_MBX_BASE + 0x8) +#define MCHP_MBX_IMR REG8(MCHP_MBX_BASE + 0xc) +#define MCHP_MBX_REG(x) REG8(MCHP_MBX_BASE + 0x10 + (x)) /* PWM */ -#define MCHP_PWM_ID_MAX (12) -#define MCHP_PWM_BASE(x) (0x40005800 + ((x) << 4)) -#define MCHP_PWM_ON(x) REG32(MCHP_PWM_BASE(x) + 0x00) -#define MCHP_PWM_OFF(x) REG32(MCHP_PWM_BASE(x) + 0x04) -#define MCHP_PWM_CFG(x) REG32(MCHP_PWM_BASE(x) + 0x08) +#define MCHP_PWM_ON(x) REG32(MCHP_PWM_BASE(x) + 0x00) +#define MCHP_PWM_OFF(x) REG32(MCHP_PWM_BASE(x) + 0x04) +#define MCHP_PWM_CFG(x) REG32(MCHP_PWM_BASE(x) + 0x08) /* TACH */ -#define MCHP_TACH_BASE(x) (0x40006000 + (x) << 4) -#define MCHP_TACH_CTRL(x) REG32(MCHP_TACH_BASE(x)) -#define MCHP_TACH_CTRL_LO(x) REG16(MCHP_TACH_BASE(x) + 0x00) -#define MCHP_TACH_CTRL_CNT(x) REG16(MCHP_TACH_BASE(x) + 0x02) -#define MCHP_TACH_STATUS(x) REG8(MCHP_TACH_BASE(x) + 0x04) -#define MCHP_TACH_LIMIT_HI(x) REG16(MCHP_TACH_BASE(x) + 0x08) -#define MCHP_TACH_LIMIT_LO(x) REG16(MCHP_TACH_BASE(x) + 0x0C) -/* - * TACH [2:0] GIRQ17 bits[3:1] - */ -#define MCHP_TACH_GIRQ 17 -#define MCHP_TACH_GIRQ_BIT(x) (1ul << ((x) + 1)) - +#define MCHP_TACH_CTRL(x) REG32(MCHP_TACH_BASE(x)) +#define MCHP_TACH_CTRL_LO(x) REG16(MCHP_TACH_BASE(x) + 0x00) +#define MCHP_TACH_CTRL_CNT(x) REG16(MCHP_TACH_BASE(x) + 0x02) +#define MCHP_TACH_STATUS(x) REG8(MCHP_TACH_BASE(x) + 0x04) +#define MCHP_TACH_LIMIT_HI(x) REG16(MCHP_TACH_BASE(x) + 0x08) +#define MCHP_TACH_LIMIT_LO(x) REG16(MCHP_TACH_BASE(x) + 0x0C) /* ACPI */ -#define MCHP_ACPI_EC_MAX (5) -#define MCHP_ACPI_EC_BASE(x) (0x400f0800 + ((x) << 10)) -#define MCHP_ACPI_EC_EC2OS(x, y) REG8(MCHP_ACPI_EC_BASE(x) +\ - 0x100 + (y)) -#define MCHP_ACPI_EC_STATUS(x) REG8(MCHP_ACPI_EC_BASE(x) + 0x104) -#define MCHP_ACPI_EC_BYTE_CTL(x) REG8(MCHP_ACPI_EC_BASE(x) + 0x105) -#define MCHP_ACPI_EC_OS2EC(x, y) REG8(MCHP_ACPI_EC_BASE(x) +\ - 0x108 + (y)) - -#define MCHP_ACPI_PM_RT_BASE 0x400f1c00 -#define MCHP_ACPI_PM1_STS1 REG8(MCHP_ACPI_PM_RT_BASE + 0x0) -#define MCHP_ACPI_PM1_STS2 REG8(MCHP_ACPI_PM_RT_BASE + 0x1) -#define MCHP_ACPI_PM1_EN1 REG8(MCHP_ACPI_PM_RT_BASE + 0x2) -#define MCHP_ACPI_PM1_EN2 REG8(MCHP_ACPI_PM_RT_BASE + 0x3) -#define MCHP_ACPI_PM1_CTL1 REG8(MCHP_ACPI_PM_RT_BASE + 0x4) -#define MCHP_ACPI_PM1_CTL2 REG8(MCHP_ACPI_PM_RT_BASE + 0x5) -#define MCHP_ACPI_PM2_CTL1 REG8(MCHP_ACPI_PM_RT_BASE + 0x6) -#define MCHP_ACPI_PM2_CTL2 REG8(MCHP_ACPI_PM_RT_BASE + 0x7) -#define MCHP_ACPI_PM_EC_BASE 0x400f1d00 -#define MCHP_ACPI_PM_STS REG8(MCHP_ACPI_PM_EC_BASE + 0x10) -/* - * All ACPI EC controllers connected to GIRQ15 - * ACPI EC[0:4] IBF = GIRQ15 bits[5,7,9,11,13] - * ACPI EC[0:4] OBE = GIRQ15 bits[6,8,10,12,14] - * ACPI PM1_CTL = GIRQ15 bit[15] - * ACPI PM1_EN = GIRQ15 bit[16] - * ACPI PM1_STS = GIRQ16 bit[17] - */ -#define MCHP_ACPI_EC_GIRQ 15 -#define MCHP_ACPI_EC_IBF_GIRQ_BIT(x) (1ul << (((x)<<1) + 5)) -#define MCHP_ACPI_EC_OBE_GIRQ_BIT(x) (1ul << (((x)<<1) + 6)) -#define MCHP_ACPI_PM1_CTL_GIRQ_BIT 15 -#define MCHP_ACPI_PM1_EN_GIRQ_BIT 16 -#define MCHP_ACPI_PM1_STS_GIRQ_BIT 17 +#define MCHP_ACPI_EC_EC2OS(x, y) REG8(MCHP_ACPI_EC_BASE(x) + 0x100 + (y)) +#define MCHP_ACPI_EC_STATUS(x) REG8(MCHP_ACPI_EC_BASE(x) + 0x104) +#define MCHP_ACPI_EC_BYTE_CTL(x) REG8(MCHP_ACPI_EC_BASE(x) + 0x105) +#define MCHP_ACPI_EC_OS2EC(x, y) REG8(MCHP_ACPI_EC_BASE(x) + 0x108 + (y)) +#define MCHP_ACPI_PM1_STS1 REG8(MCHP_ACPI_PM_RT_BASE + 0x0) +#define MCHP_ACPI_PM1_STS2 REG8(MCHP_ACPI_PM_RT_BASE + 0x1) +#define MCHP_ACPI_PM1_EN1 REG8(MCHP_ACPI_PM_RT_BASE + 0x2) +#define MCHP_ACPI_PM1_EN2 REG8(MCHP_ACPI_PM_RT_BASE + 0x3) +#define MCHP_ACPI_PM1_CTL1 REG8(MCHP_ACPI_PM_RT_BASE + 0x4) +#define MCHP_ACPI_PM1_CTL2 REG8(MCHP_ACPI_PM_RT_BASE + 0x5) +#define MCHP_ACPI_PM2_CTL1 REG8(MCHP_ACPI_PM_RT_BASE + 0x6) +#define MCHP_ACPI_PM2_CTL2 REG8(MCHP_ACPI_PM_RT_BASE + 0x7) +#define MCHP_ACPI_PM_STS REG8(MCHP_ACPI_PM_EC_BASE + 0x10) /* 8042 */ -#define MCHP_8042_BASE 0x400f0400 -#define MCHP_8042_OBF_CLR REG8(MCHP_8042_BASE + 0x0) -#define MCHP_8042_H2E REG8(MCHP_8042_BASE + 0x100) -#define MCHP_8042_E2H REG8(MCHP_8042_BASE + 0x100) -#define MCHP_8042_STS REG8(MCHP_8042_BASE + 0x104) -#define MCHP_8042_KB_CTRL REG8(MCHP_8042_BASE + 0x108) -#define MCHP_8042_PCOBF REG8(MCHP_8042_BASE + 0x114) -#define MCHP_8042_ACT REG8(MCHP_8042_BASE + 0x330) -/* - * 8042 [OBE:IBF] = GIRQ15 bits[18:19] - */ -#define MCHP_8042_GIRQ 15 -#define MCHP_8042_OBE_GIRQ_BIT (1ul << 18) -#define MCHP_8042_IBF_GIRQ_BIT (1ul << 19) - -/* FAN */ -#define MCHP_FAN_BASE(x) (0x4000a000 + ((x) << 7)) -#define MCHP_FAN_SETTING(x) REG8(MCHP_FAN_BASE(x) + 0x0) -#define MCHP_FAN_PWM_DIVIDE(x) REG8(MCHP_FAN_BASE(x) + 0x1) -#define MCHP_FAN_CFG1(x) REG8(MCHP_FAN_BASE(x) + 0x2) -#define MCHP_FAN_CFG2(x) REG8(MCHP_FAN_BASE(x) + 0x3) -#define MCHP_FAN_GAIN(x) REG8(MCHP_FAN_BASE(x) + 0x5) -#define MCHP_FAN_SPIN_UP(x) REG8(MCHP_FAN_BASE(x) + 0x6) -#define MCHP_FAN_STEP(x) REG8(MCHP_FAN_BASE(x) + 0x7) -#define MCHP_FAN_MIN_DRV(x) REG8(MCHP_FAN_BASE(x) + 0x8) -#define MCHP_FAN_VALID_CNT(x) REG8(MCHP_FAN_BASE(x) + 0x9) -#define MCHP_FAN_DRV_FAIL(x) REG16(MCHP_FAN_BASE(x) + 0xa) -#define MCHP_FAN_TARGET(x) REG16(MCHP_FAN_BASE(x) + 0xc) -#define MCHP_FAN_READING(x) REG16(MCHP_FAN_BASE(x) + 0xe) -#define MCHP_FAN_BASE_FREQ(x) REG8(MCHP_FAN_BASE(x) + 0x10) -#define MCHP_FAN_STATUS(x) REG8(MCHP_FAN_BASE(x) + 0x11) -/* - * FAN(RPM2PWM) all instances on GIRQ17 - * FAN[0:1] Fail = GIRQ17 bits[4,6] - * FAN[0:1] Stall = GIRQ17 bits[5,7] - */ -#define MCHP_FAN_GIRQ 17 -#define MCHP_FAN_FAIL_GIRQ_BIT(x) (1ul << (((x)<<1)+4)) -#define MCHP_FAN_STALL_GIRQ_BIT(x) (1ul << (((x)<<1)+5)) - - -/* I2C */ -#define MCHP_I2C_CTRL0 (0) -#define MCHP_I2C_CTRL1 (1) -#define MCHP_I2C_CTRL2 (2) -#define MCHP_I2C_CTRL3 (3) -#define MCHP_I2C_CTRL_MAX (4) - -#define MCHP_I2C_BASE(x) (0x40004000 + ((x) << 10)) -#define MCHP_I2C0_BASE 0x40004000 -#define MCHP_I2C1_BASE 0x40004400 -#define MCHP_I2C2_BASE 0x40004800 -#define MCHP_I2C3_BASE 0x40004C00 -#define MCHP_I2C_BASESEP 0x00000400 -#define MCHP_I2C_ADDR(controller, offset) \ - (offset + MCHP_I2C_BASE(controller)) - -/* - * MEC1701H 144-pin package has four I2C controller and eleven ports. - * Any port can be mapped to any I2C controller. - * This package does not implement pins for I2C01 (Port 1). - * - * I2C port values must be zero based consecutive whole numbers due to - * port number used as an index for I2C mutex array, etc. - * - * Refer to chip i2c_port_to_controller function for mapping - * of port to controller. - * - * Locking must occur by-controller (not by-port). - */ -#define MCHP_I2C_PORT_MASK 0x07FDul - -enum MCHP_i2c_port { - MCHP_I2C_PORT0 = 0, - MCHP_I2C_PORT1, /* port 1, do not use. pins not present */ - MCHP_I2C_PORT2, - MCHP_I2C_PORT3, - MCHP_I2C_PORT4, - MCHP_I2C_PORT5, - MCHP_I2C_PORT6, - MCHP_I2C_PORT7, - MCHP_I2C_PORT8, - MCHP_I2C_PORT9, - MCHP_I2C_PORT10, - - MCHP_I2C_PORT_COUNT, -}; - -#define MCHP_I2C_CTRL(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x0)) -#define MCHP_I2C_STATUS(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x0)) -#define MCHP_I2C_OWN_ADDR(ctrl) REG16(MCHP_I2C_ADDR(ctrl, 0x4)) -#define MCHP_I2C_DATA(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x8)) -#define MCHP_I2C_MASTER_CMD(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0xc)) -#define MCHP_I2C_SLAVE_CMD(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x10)) -#define MCHP_I2C_PEC(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x14)) -#define MCHP_I2C_DATA_TIM_2(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x18)) -#define MCHP_I2C_COMPLETE(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x20)) -#define MCHP_I2C_IDLE_SCALE(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x24)) -#define MCHP_I2C_CONFIG(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x28)) -#define MCHP_I2C_BUS_CLK(ctrl) REG16(MCHP_I2C_ADDR(ctrl, 0x2c)) -#define MCHP_I2C_BLK_ID(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x30)) -#define MCHP_I2C_REV(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x34)) -#define MCHP_I2C_BB_CTRL(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x38)) -#define MCHP_I2C_DATA_TIM(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x40)) -#define MCHP_I2C_TOUT_SCALE(ctrl) REG32(MCHP_I2C_ADDR(ctrl, 0x44)) -#define MCHP_I2C_SLAVE_TX_BUF(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x48)) -#define MCHP_I2C_SLAVE_RX_BUF(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x4c)) -#define MCHP_I2C_MASTER_TX_BUF(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x50)) -#define MCHP_I2C_MASTER_RX_BUF(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x54)) -#define MCHP_I2C_WAKE_STS(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x60)) -#define MCHP_I2C_WAKE_EN(ctrl) REG8(MCHP_I2C_ADDR(ctrl, 0x64)) -/* All I2C controller connected to GIRQ13 */ -#define MCHP_I2C_GIRQ 13 -/* I2C[0:3] -> GIRQ13 bits[0:3] */ -#define MCHP_I2C_GIRQ_BIT(x) (1ul << (x)) - +#define MCHP_8042_OBF_CLR REG8(MCHP_8042_BASE + 0x0) +#define MCHP_8042_H2E REG8(MCHP_8042_BASE + 0x100) +#define MCHP_8042_E2H REG8(MCHP_8042_BASE + 0x100) +#define MCHP_8042_STS REG8(MCHP_8042_BASE + 0x104) +#define MCHP_8042_KB_CTRL REG8(MCHP_8042_BASE + 0x108) +#define MCHP_8042_PCOBF REG8(MCHP_8042_BASE + 0x114) +#define MCHP_8042_ACT REG8(MCHP_8042_BASE + 0x330) + +/* PROCHOT */ +#define MCHP_PCHOT_CUM_CNT REG32(MCHP_PROCHOT_BASE + 0x00) +#define MCHP_PCHOT_DTY_CYC_CNT REG32(MCHP_PROCHOT_BASE + 0x04) +#define MCHP_PCHOT_DTY_PRD_CNT REG32(MCHP_PROCHOT_BASE + 0x08) +#define MCHP_PCHOT_STS_CTRL REG32(MCHP_PROCHOT_BASE + 0x0C) +#define MCHP_PCHOT_ASERT_CNT REG32(MCHP_PROCHOT_BASE + 0x10) +#define MCHP_PCHOT_ASERT_CNT_LMT REG32(MCHP_PROCHOT_BASE + 0x14) +#define MCHP_PCHOT_TEST REG32(MCHP_PROCHOT_BASE + 0x18) + +/* I2C registers access given controller base address */ +#define MCHP_I2C_CTRL(addr) REG8(addr) +#define MCHP_I2C_STATUS(addr) REG8(addr) +#define MCHP_I2C_OWN_ADDR(addr) REG16(addr + 0x4) +#define MCHP_I2C_DATA(addr) REG8(addr + 0x8) +#define MCHP_I2C_MASTER_CMD(addr) REG32(addr + 0xc) +#define MCHP_I2C_SLAVE_CMD(addr) REG32(addr + 0x10) +#define MCHP_I2C_PEC(addr) REG8(addr + 0x14) +#define MCHP_I2C_DATA_TIM_2(addr) REG8(addr + 0x18) +#define MCHP_I2C_COMPLETE(addr) REG32(addr + 0x20) +#define MCHP_I2C_IDLE_SCALE(addr) REG32(addr + 0x24) +#define MCHP_I2C_CONFIG(addr) REG32(addr + 0x28) +#define MCHP_I2C_BUS_CLK(addr) REG16(addr + 0x2c) +#define MCHP_I2C_BLK_ID(addr) REG8(addr + 0x30) +#define MCHP_I2C_REV(addr) REG8(addr + 0x34) +#define MCHP_I2C_BB_CTRL(addr) REG8(addr + 0x38) +#define MCHP_I2C_TST_DATA_TIM(addr) REG32(addr + 0x3c) +#define MCHP_I2C_DATA_TIM(addr) REG32(addr + 0x40) +#define MCHP_I2C_TOUT_SCALE(addr) REG32(addr + 0x44) +#define MCHP_I2C_SLAVE_TX_BUF(addr) REG8(addr + 0x48) +#define MCHP_I2C_SLAVE_RX_BUF(addr) REG8(addr + 0x4c) +#define MCHP_I2C_MASTER_TX_BUF(addr) REG8(addr + 0x50) +#define MCHP_I2C_MASTER_RX_BUF(addr) REG8(addr + 0x54) +#define MCHP_I2C_TEST_1(addr) REG32(addr + 0x58) +#define MCHP_I2C_TEST_2(addr) REG32(addr + 0x5c) +#define MCHP_I2C_WAKE_STS(addr) REG8(addr + 0x60) +#define MCHP_I2C_WAKE_EN(addr) REG8(addr + 0x64) +#define MCHP_I2C_TEST_3(addr) REG32(addr + 0x68) /* Keyboard scan matrix */ -#define MCHP_KS_BASE 0x40009c00 -#define MCHP_KS_KSO_SEL REG32(MCHP_KS_BASE + 0x4) -#define MCHP_KS_KSI_INPUT REG32(MCHP_KS_BASE + 0x8) -#define MCHP_KS_KSI_STATUS REG32(MCHP_KS_BASE + 0xc) -#define MCHP_KS_KSI_INT_EN REG32(MCHP_KS_BASE + 0x10) -#define MCHP_KS_EXT_CTRL REG32(MCHP_KS_BASE + 0x14) -#define MCHP_KS_GIRQ 21 -#define MCHP_KS_GIRQ_BIT (1ul << 25) - +#define MCHP_KS_KSO_SEL REG32(MCHP_KEYSCAN_BASE + 0x4) +#define MCHP_KS_KSI_INPUT REG32(MCHP_KEYSCAN_BASE + 0x8) +#define MCHP_KS_KSI_STATUS REG32(MCHP_KEYSCAN_BASE + 0xc) +#define MCHP_KS_KSI_INT_EN REG32(MCHP_KEYSCAN_BASE + 0x10) +#define MCHP_KS_EXT_CTRL REG32(MCHP_KEYSCAN_BASE + 0x14) /* ADC */ -#define MCHP_ADC_BASE 0x40007c00 -#define MCHP_ADC_CTRL REG32(MCHP_ADC_BASE + 0x0) -#define MCHP_ADC_DELAY REG32(MCHP_ADC_BASE + 0x4) -#define MCHP_ADC_STS REG32(MCHP_ADC_BASE + 0x8) -#define MCHP_ADC_SINGLE REG32(MCHP_ADC_BASE + 0xc) -#define MCHP_ADC_REPEAT REG32(MCHP_ADC_BASE + 0x10) -#define MCHP_ADC_READ(x) REG32(MCHP_ADC_BASE + 0x14 + ((x) * 0x4)) - -#define MCHP_ADC_GIRQ 17 -#define MCHP_ADC_GIRQ_SINGLE_BIT (1ul << 8) -#define MCHP_ADC_GIRQ_REPEAT_BIT (1ul << 9) - +#define MCHP_ADC_CTRL REG32(MCHP_ADC_BASE + 0x0) +#define MCHP_ADC_DELAY REG32(MCHP_ADC_BASE + 0x4) +#define MCHP_ADC_STS REG32(MCHP_ADC_BASE + 0x8) +#define MCHP_ADC_SINGLE REG32(MCHP_ADC_BASE + 0xc) +#define MCHP_ADC_REPEAT REG32(MCHP_ADC_BASE + 0x10) +#define MCHP_ADC_READ(x) REG32(MCHP_ADC_BASE + 0x14 + ((x)*0x4)) /* Hibernation timer */ -#define MCHP_HTIMER_BASE(x) (0x40009800 + ((x) << 5)) -#define MCHP_HTIMER_PRELOAD(x) REG16(MCHP_HTIMER_BASE(x) + 0x0) -#define MCHP_HTIMER_CONTROL(x) REG16(MCHP_HTIMER_BASE(x) + 0x4) -#define MCHP_HTIMER_COUNT(x) REG16(MCHP_HTIMER_BASE(x) + 0x8) -/* All Hibernation timers connected to GIRQ21 */ -#define MCHP_HTIMER_GIRQ 21 -/* HTIMER[0:1] -> GIRQ21 bits[1:2] */ -#define MCHP_HTIMER_GIRQ_BIT(x) (1ul << ((x) + 1)) - - -/* General Purpose SPI (GP-SPI) */ -#define MCHP_SPI_BASE(port) (0x40009400 + ((port) << 7)) -#define MCHP_SPI_AR(port) REG8(MCHP_SPI_BASE(port) + 0x00) -#define MCHP_SPI_CR(port) REG8(MCHP_SPI_BASE(port) + 0x04) -#define MCHP_SPI_SR(port) REG8(MCHP_SPI_BASE(port) + 0x08) -#define MCHP_SPI_TD(port) REG8(MCHP_SPI_BASE(port) + 0x0c) -#define MCHP_SPI_RD(port) REG8(MCHP_SPI_BASE(port) + 0x10) -#define MCHP_SPI_CC(port) REG8(MCHP_SPI_BASE(port) + 0x14) -#define MCHP_SPI_CG(port) REG8(MCHP_SPI_BASE(port) + 0x18) -/* Addresses of TX/RX register used in tables */ -#define MCHP_SPI_TD_ADDR(ctrl) (MCHP_SPI_BASE(ctrl) + 0x0c) -#define MCHP_SPI_RD_ADDR(ctrl) (MCHP_SPI_BASE(ctrl) + 0x10) -/* All GP-SPI controllers connected to GIRQ18 */ -#define MCHP_SPI_GIRQ 18 -/* - * SPI[0:1] TXBE -> GIRQ18 bits[2,4] - * SPI[0:1] RXBF -> GIRQ18 bits[3,5] - */ -#define MCHP_SPI_GIRQ_TXBE_BIT(x) (1ul << (((x) << 1) + 2)) -#define MCHP_SPI_GIRQ_RXBF_BIT(x) (1ul << (((x) << 1) + 3)) - -#define MCHP_GPSPI0_ID 0 -#define MCHP_GPSPI1_ID 1 - -#ifdef CHIP_FAMILY_MEC17XX +#define MCHP_HTIMER_PRELOAD(x) REG16(MCHP_HTIMER_ADDR(x) + 0x0) +#define MCHP_HTIMER_CONTROL(x) REG16(MCHP_HTIMER_ADDR(x) + 0x4) +#define MCHP_HTIMER_COUNT(x) REG16(MCHP_HTIMER_ADDR(x) + 0x8) + +/* Week timer and BGPO control */ +#define MCHP_WKTIMER_CTRL REG32(MCHP_WKTIMER_BASE + 0) +#define MCHP_WKTIMER_ALARM_CNT REG32(MCHP_WKTIMER_BASE + 0x04) +#define MCHP_WKTIMER_COMPARE REG32(MCHP_WKTIMER_BASE + 0x08) +#define MCHP_WKTIMER_CLK_DIV REG32(MCHP_WKTIMER_BASE + 0x0c) +#define MCHP_WKTIMER_SUBSEC_ISEL REG32(MCHP_WKTIMER_BASE + 0x10) +#define MCHP_WKTIMER_SUBWK_CTRL REG32(MCHP_WKTIMER_BASE + 0x14) +#define MCHP_WKTIMER_SUBWK_ALARM REG32(MCHP_WKTIMER_BASE + 0x18) +#define MCHP_WKTIMER_BGPO_DATA REG32(MCHP_WKTIMER_BASE + 0x1c) +#define MCHP_WKTIMER_BGPO_POWER REG32(MCHP_WKTIMER_BASE + 0x20) +#define MCHP_WKTIMER_BGPO_RESET REG32(MCHP_WKTIMER_BASE + 0x24) /* Quad Master SPI (QMSPI) */ -#define MCHP_QMSPI0_BASE 0x40005400 -#define MCHP_QMSPI0_MODE REG32(MCHP_QMSPI0_BASE + 0x00) -#define MCHP_QMSPI0_MODE_ACT_SRST REG8(MCHP_QMSPI0_BASE + 0x00) -#define MCHP_QMSPI0_MODE_SPI_MODE REG8(MCHP_QMSPI0_BASE + 0x01) -#define MCHP_QMSPI0_MODE_FDIV REG8(MCHP_QMSPI0_BASE + 0x02) -#define MCHP_QMSPI0_CTRL REG32(MCHP_QMSPI0_BASE + 0x04) -#define MCHP_QMSPI0_EXE REG8(MCHP_QMSPI0_BASE + 0x08) -#define MCHP_QMSPI0_IFCTRL REG8(MCHP_QMSPI0_BASE + 0x0C) -#define MCHP_QMSPI0_STS REG32(MCHP_QMSPI0_BASE + 0x10) -#define MCHP_QMSPI0_BUFCNT_STS REG32(MCHP_QMSPI0_BASE + 0x14) -#define MCHP_QMSPI0_IEN REG32(MCHP_QMSPI0_BASE + 0x18) -#define MCHP_QMSPI0_BUFCNT_TRIG REG32(MCHP_QMSPI0_BASE + 0x1C) -#define MCHP_QMSPI0_TX_FIFO_ADDR (MCHP_QMSPI0_BASE + 0x20) -#define MCHP_QMSPI0_TX_FIFO8 REG8(MCHP_QMSPI0_BASE + 0x20) -#define MCHP_QMSPI0_TX_FIFO16 REG16(MCHP_QMSPI0_BASE + 0x20) -#define MCHP_QMSPI0_TX_FIFO32 REG32(MCHP_QMSPI0_BASE + 0x20) -#define MCHP_QMSPI0_RX_FIFO_ADDR (MCHP_QMSPI0_BASE + 0x24) -#define MCHP_QMSPI0_RX_FIFO8 REG8(MCHP_QMSPI0_BASE + 0x24) -#define MCHP_QMSPI0_RX_FIFO16 REG16(MCHP_QMSPI0_BASE + 0x24) -#define MCHP_QMSPI0_RX_FIFO32 REG32(MCHP_QMSPI0_BASE + 0x24) -#define MCHP_QMSPI0_DESCR(x) REG32(MCHP_QMSPI0_BASE +\ - 0x30 + ((x)<<2)) -#define MCHP_QMSPI_GIRQ 18 -#define MCHP_QMSPI_GIRQ_BIT (1ul << 1) - -#define MCHP_QMSPI_MAX_DESCR 5 - +#define MCHP_QMSPI0_MODE REG32(MCHP_QMSPI0_BASE + 0x00) +#define MCHP_QMSPI0_MODE_ACT_SRST REG8(MCHP_QMSPI0_BASE + 0x00) +#define MCHP_QMSPI0_MODE_SPI_MODE REG8(MCHP_QMSPI0_BASE + 0x01) +#define MCHP_QMSPI0_MODE_FDIV REG8(MCHP_QMSPI0_BASE + 0x02) +#define MCHP_QMSPI0_CTRL REG32(MCHP_QMSPI0_BASE + 0x04) +#define MCHP_QMSPI0_EXE REG8(MCHP_QMSPI0_BASE + 0x08) +#define MCHP_QMSPI0_IFCTRL REG8(MCHP_QMSPI0_BASE + 0x0C) +#define MCHP_QMSPI0_STS REG32(MCHP_QMSPI0_BASE + 0x10) +#define MCHP_QMSPI0_BUFCNT_STS REG32(MCHP_QMSPI0_BASE + 0x14) +#define MCHP_QMSPI0_IEN REG32(MCHP_QMSPI0_BASE + 0x18) +#define MCHP_QMSPI0_BUFCNT_TRIG REG32(MCHP_QMSPI0_BASE + 0x1C) +#define MCHP_QMSPI0_TX_FIFO_ADDR (MCHP_QMSPI0_BASE + 0x20) +#define MCHP_QMSPI0_TX_FIFO8 REG8(MCHP_QMSPI0_BASE + 0x20) +#define MCHP_QMSPI0_TX_FIFO16 REG16(MCHP_QMSPI0_BASE + 0x20) +#define MCHP_QMSPI0_TX_FIFO32 REG32(MCHP_QMSPI0_BASE + 0x20) +#define MCHP_QMSPI0_RX_FIFO_ADDR (MCHP_QMSPI0_BASE + 0x24) +#define MCHP_QMSPI0_RX_FIFO8 REG8(MCHP_QMSPI0_BASE + 0x24) +#define MCHP_QMSPI0_RX_FIFO16 REG16(MCHP_QMSPI0_BASE + 0x24) +#define MCHP_QMSPI0_RX_FIFO32 REG32(MCHP_QMSPI0_BASE + 0x24) +#define MCHP_QMSPI0_DESCR(x) REG32(MCHP_QMSPI0_BASE + 0x30 + ((x)*4)) /* Bits in MCHP_QMSPI0_MODE */ -#define MCHP_QMSPI_M_ACTIVATE (1ul << 0) -#define MCHP_QMSPI_M_SOFT_RESET (1ul << 1) -#define MCHP_QMSPI_M_SPI_MODE_MASK (0x7ul << 8) -#define MCHP_QMSPI_M_SPI_MODE0 (0x0ul << 8) -#define MCHP_QMSPI_M_SPI_MODE3 (0x3ul << 8) -#define MCHP_QMSPI_M_SPI_MODE0_48M (0x4ul << 8) -#define MCHP_QMSPI_M_SPI_MODE3_48M (0x7ul << 8) +#define MCHP_QMSPI_M_ACTIVATE BIT(0) +#define MCHP_QMSPI_M_SOFT_RESET BIT(1) +#define MCHP_QMSPI_M_SPI_MODE_MASK (0x7ul << 8) +#define MCHP_QMSPI_M_SPI_MODE0 (0x0ul << 8) +#define MCHP_QMSPI_M_SPI_MODE3 (0x3ul << 8) +#define MCHP_QMSPI_M_SPI_MODE0_48M (0x4ul << 8) +#define MCHP_QMSPI_M_SPI_MODE3_48M (0x7ul << 8) /* * clock divider is 8-bit field in bits[23:16] * [1, 255] -> 48MHz / [1, 255], 0 -> 48MHz / 256 */ -#define MCHP_QMSPI_M_CLKDIV_BITPOS 16 -#define MCHP_QMSPI_M_CLKDIV_48M (1ul << 16) -#define MCHP_QMSPI_M_CLKDIV_24M (2ul << 16) -#define MCHP_QMSPI_M_CLKDIV_16M (3ul << 16) -#define MCHP_QMSPI_M_CLKDIV_12M (4ul << 16) -#define MCHP_QMSPI_M_CLKDIV_8M (6ul << 16) -#define MCHP_QMSPI_M_CLKDIV_6M (8ul << 16) -#define MCHP_QMSPI_M_CLKDIV_1M (48ul << 16) -#define MCHP_QMSPI_M_CLKDIV_188K (0x100ul << 16) - +#define MCHP_QMSPI_M_CLKDIV_BITPOS 16 +#define MCHP_QMSPI_M_CLKDIV_48M (1ul << 16) +#define MCHP_QMSPI_M_CLKDIV_24M (2ul << 16) +#define MCHP_QMSPI_M_CLKDIV_16M (3ul << 16) +#define MCHP_QMSPI_M_CLKDIV_12M (4ul << 16) +#define MCHP_QMSPI_M_CLKDIV_8M (6ul << 16) +#define MCHP_QMSPI_M_CLKDIV_6M (8ul << 16) +#define MCHP_QMSPI_M_CLKDIV_1M (48ul << 16) +#define MCHP_QMSPI_M_CLKDIV_188K (0x100ul << 16) /* Bits in MCHP_QMSPI0_CTRL and MCHP_QMSPI_DESCR(x) */ -#define MCHP_QMSPI_C_1X (0ul << 0) /* Full Duplex */ -#define MCHP_QMSPI_C_2X (1ul << 0) /* Dual IO */ -#define MCHP_QMSPI_C_4X (2ul << 0) /* Quad IO */ -#define MCHP_QMSPI_C_TX_DIS (0ul << 2) -#define MCHP_QMSPI_C_TX_DATA (1ul << 2) -#define MCHP_QMSPI_C_TX_ZEROS (2ul << 2) -#define MCHP_QMSPI_C_TX_ONES (3ul << 2) -#define MCHP_QMSPI_C_TX_DMA_DIS (0ul << 4) -#define MCHP_QMSPI_C_TX_DMA_1B (1ul << 4) -#define MCHP_QMSPI_C_TX_DMA_2B (2ul << 4) -#define MCHP_QMSPI_C_TX_DMA_4B (3ul << 4) -#define MCHP_QMSPI_C_TX_DMA_MASK (3ul << 4) -#define MCHP_QMSPI_C_RX_DIS (0ul << 6) -#define MCHP_QMSPI_C_RX_EN (1ul << 6) -#define MCHP_QMSPI_C_RX_DMA_DIS (0ul << 7) -#define MCHP_QMSPI_C_RX_DMA_1B (1ul << 7) -#define MCHP_QMSPI_C_RX_DMA_2B (2ul << 7) -#define MCHP_QMSPI_C_RX_DMA_4B (3ul << 7) -#define MCHP_QMSPI_C_RX_DMA_MASK (3ul << 7) -#define MCHP_QMSPI_C_NO_CLOSE (0ul << 9) -#define MCHP_QMSPI_C_CLOSE (1ul << 9) -#define MCHP_QMSPI_C_XFRU_BITS (0ul << 10) -#define MCHP_QMSPI_C_XFRU_1B (1ul << 10) -#define MCHP_QMSPI_C_XFRU_4B (2ul << 10) -#define MCHP_QMSPI_C_XFRU_16B (3ul << 10) -#define MCHP_QMSPI_C_XFRU_MASK (3ul << 10) +#define MCHP_QMSPI_C_1X (0ul << 0) /* Full Duplex */ +#define MCHP_QMSPI_C_2X (1ul << 0) /* Dual IO */ +#define MCHP_QMSPI_C_4X (2ul << 0) /* Quad IO */ +#define MCHP_QMSPI_C_TX_DIS (0ul << 2) +#define MCHP_QMSPI_C_TX_DATA (1ul << 2) +#define MCHP_QMSPI_C_TX_ZEROS (2ul << 2) +#define MCHP_QMSPI_C_TX_ONES (3ul << 2) +#define MCHP_QMSPI_C_TX_DMA_DIS (0ul << 4) +#define MCHP_QMSPI_C_TX_DMA_1B (1ul << 4) +#define MCHP_QMSPI_C_TX_DMA_2B (2ul << 4) +#define MCHP_QMSPI_C_TX_DMA_4B (3ul << 4) +#define MCHP_QMSPI_C_TX_DMA_MASK (3ul << 4) +#define MCHP_QMSPI_C_RX_DIS 0 +#define MCHP_QMSPI_C_RX_EN BIT(6) +#define MCHP_QMSPI_C_RX_DMA_DIS (0ul << 7) +#define MCHP_QMSPI_C_RX_DMA_1B (1ul << 7) +#define MCHP_QMSPI_C_RX_DMA_2B (2ul << 7) +#define MCHP_QMSPI_C_RX_DMA_4B (3ul << 7) +#define MCHP_QMSPI_C_RX_DMA_MASK (3ul << 7) +#define MCHP_QMSPI_C_NO_CLOSE 0 +#define MCHP_QMSPI_C_CLOSE BIT(9) +#define MCHP_QMSPI_C_XFRU_BITS (0ul << 10) +#define MCHP_QMSPI_C_XFRU_1B (1ul << 10) +#define MCHP_QMSPI_C_XFRU_4B (2ul << 10) +#define MCHP_QMSPI_C_XFRU_16B (3ul << 10) +#define MCHP_QMSPI_C_XFRU_MASK (3ul << 10) /* Control */ -#define MCHP_QMSPI_C_START_DESCR_BITPOS (12) -#define MCHP_QMSPI_C_START_DESCR_MASK (0xFul << 12) -#define MCHP_QMSPI_C_DESCR_MODE_EN (1ul << 16) +#define MCHP_QMSPI_C_START_DESCR_BITPOS 12 +#define MCHP_QMSPI_C_START_DESCR_MASK (0xFul << 12) +#define MCHP_QMSPI_C_DESCR_MODE_EN BIT(16) /* Descriptors, indicates the current descriptor is the last */ -#define MCHP_QMSPI_C_NEXT_DESCR_BITPOS 12 -#define MCHP_QMSPI_C_NEXT_DESCR_MASK0 0xFul -#define MCHP_QMSPI_C_NEXT_DESCR_MASK \ - ((MCHP_QMSPI_C_NEXT_DESCR_MASK0) << 12) -#define MCHP_QMSPI_C_NXTD(n) (n << 12) -#define MCHP_QMSPI_C_NEXTD0 (0ul << 12) -#define MCHP_QMSPI_C_NEXTD1 (1ul << 12) -#define MCHP_QMSPI_C_NEXTD2 (2ul << 12) -#define MCHP_QMSPI_C_NEXTD3 (3ul << 12) -#define MCHP_QMSPI_C_NEXTD4 (4ul << 12) -#define MCHP_QMSPI_C_DESCR_LAST (1ul << 16) +#define MCHP_QMSPI_C_NEXT_DESCR_BITPOS 12 +#define MCHP_QMSPI_C_NEXT_DESCR_MASK0 0xFul +#define MCHP_QMSPI_C_NEXT_DESCR_MASK ((MCHP_QMSPI_C_NEXT_DESCR_MASK0) << 12) +#define MCHP_QMSPI_C_NXTD(n) ((n) << 12) +#define MCHP_QMSPI_C_DESCR_LAST BIT(16) /* * Total transfer length is the count in this field * scaled by units in MCHP_QMSPI_CTRL_XFRU_xxxx */ -#define MCHP_QMSPI_C_NUM_UNITS_BITPOS (17) -#define MCHP_QMSPI_C_MAX_UNITS (0x7ffful) -#define MCHP_QMSPI_C_NUM_UNITS_MASK0 (0x7ffful) -#define MCHP_QMSPI_C_NUM_UNITS_MASK \ - ((MCHP_QMSPI_C_NUM_UNITS_MASK0) << 17) - +#define MCHP_QMSPI_C_NUM_UNITS_BITPOS 17 +#define MCHP_QMSPI_C_MAX_UNITS 0x7ffful +#define MCHP_QMSPI_C_NUM_UNITS_MASK0 0x7ffful +#define MCHP_QMSPI_C_NUM_UNITS_MASK ((MCHP_QMSPI_C_NUM_UNITS_MASK0) << 17) /* Bits in MCHP_QMSPI0_EXE */ -#define MCHP_QMSPI_EXE_START BIT(0) -#define MCHP_QMSPI_EXE_STOP BIT(1) -#define MCHP_QMSPI_EXE_CLR_FIFOS BIT(2) - +#define MCHP_QMSPI_EXE_START BIT(0) +#define MCHP_QMSPI_EXE_STOP BIT(1) +#define MCHP_QMSPI_EXE_CLR_FIFOS BIT(2) /* MCHP QMSPI FIFO Sizes */ -#define MCHP_QMSPI_TX_FIFO_LEN 8 -#define MCHP_QMSPI_RX_FIFO_LEN 8 - +#define MCHP_QMSPI_TX_FIFO_LEN 8 +#define MCHP_QMSPI_RX_FIFO_LEN 8 /* Bits in MCHP_QMSPI0_STS and MCHP_QMSPI0_IEN */ -#define MCHP_QMSPI_STS_DONE (1ul << 0) -#define MCHP_QMSPI_STS_DMA_DONE (1ul << 1) -#define MCHP_QMSPI_STS_TX_BUFF_ERR (1ul << 2) -#define MCHP_QMSPI_STS_RX_BUFF_ERR (1ul << 3) -#define MCHP_QMSPI_STS_PROG_ERR (1ul << 4) -#define MCHP_QMSPI_STS_TX_BUFF_FULL (1ul << 8) -#define MCHP_QMSPI_STS_TX_BUFF_EMPTY (1ul << 9) -#define MCHP_QMSPI_STS_TX_BUFF_REQ (1ul << 10) -#define MCHP_QMSPI_STS_TX_BUFF_STALL (1ul << 11) /* status only */ -#define MCHP_QMSPI_STS_RX_BUFF_FULL (1ul << 12) -#define MCHP_QMSPI_STS_RX_BUFF_EMPTY (1ul << 13) -#define MCHP_QMSPI_STS_RX_BUFF_REQ (1ul << 14) -#define MCHP_QMSPI_STS_RX_BUFF_STALL (1ul << 15) /* status only */ -#define MCHP_QMSPI_STS_ACTIVE (1ul << 16) /* status only */ - +#define MCHP_QMSPI_STS_DONE BIT(0) +#define MCHP_QMSPI_STS_DMA_DONE BIT(1) +#define MCHP_QMSPI_STS_TX_BUFF_ERR BIT(2) +#define MCHP_QMSPI_STS_RX_BUFF_ERR BIT(3) +#define MCHP_QMSPI_STS_PROG_ERR BIT(4) +#define MCHP_QMSPI_STS_TX_BUFF_FULL BIT(8) +#define MCHP_QMSPI_STS_TX_BUFF_EMPTY BIT(9) +#define MCHP_QMSPI_STS_TX_BUFF_REQ BIT(10) +#define MCHP_QMSPI_STS_TX_BUFF_STALL BIT(11) /* status only */ +#define MCHP_QMSPI_STS_RX_BUFF_FULL BIT(12) +#define MCHP_QMSPI_STS_RX_BUFF_EMPTY BIT(13) +#define MCHP_QMSPI_STS_RX_BUFF_REQ BIT(14) +#define MCHP_QMSPI_STS_RX_BUFF_STALL BIT(15) /* status only */ +#define MCHP_QMSPI_STS_ACTIVE BIT(16) /* status only */ /* Bits in MCHP_QMSPI0_BUFCNT (read-only) */ -#define MCHP_QMSPI_BUFCNT_TX_BITPOS (0) -#define MCHP_QMSPI_BUFCNT_TX_MASK (0xFFFFul) -#define MCHP_QMSPI_BUFCNT_RX_BITPOS (16) -#define MCHP_QMSPI_BUFCNT_RX_MASK (0xFFFFul << 16) - -#define MCHP_QMSPI0_ID 0 - -#endif /* #ifdef CHIP_FAMILY_MEC17XX */ +#define MCHP_QMSPI_BUFCNT_TX_BITPOS 0 +#define MCHP_QMSPI_BUFCNT_TX_MASK 0xFFFFul +#define MCHP_QMSPI_BUFCNT_RX_BITPOS 16 +#define MCHP_QMSPI_BUFCNT_RX_MASK (0xFFFFul << 16) +#define MCHP_QMSPI0_ID 0 /* eSPI */ - -/* eSPI IO Component Base Address */ -#define MCHP_ESPI_IO_BASE 0x400f3400 - +/* eSPI IO Component */ /* Peripheral Channel Registers */ -#define MCHP_ESPI_PC_STATUS REG32(MCHP_ESPI_IO_BASE + 0x114) -#define MCHP_ESPI_PC_IEN REG32(MCHP_ESPI_IO_BASE + 0x118) -#define MCHP_ESPI_PC_BAR_INHIBIT_LO REG32(MCHP_ESPI_IO_BASE + 0x120) -#define MCHP_ESPI_PC_BAR_INHIBIT_HI REG32(MCHP_ESPI_IO_BASE + 0x124) -#define MCHP_ESPI_PC_BAR_INIT_LD_0C REG16(MCHP_ESPI_IO_BASE + 0x128) -#define MCHP_ESPI_PC_EC_IRQ REG8(MCHP_ESPI_IO_BASE + 0x12C) - +#define MCHP_ESPI_PC_STATUS REG32(MCHP_ESPI_IO_BASE + 0x114) +#define MCHP_ESPI_PC_IEN REG32(MCHP_ESPI_IO_BASE + 0x118) +#define MCHP_ESPI_PC_BAR_INHIBIT_LO REG32(MCHP_ESPI_IO_BASE + 0x120) +#define MCHP_ESPI_PC_BAR_INHIBIT_HI REG32(MCHP_ESPI_IO_BASE + 0x124) +#define MCHP_ESPI_PC_BAR_INIT_LD_0C REG16(MCHP_ESPI_IO_BASE + 0x128) +#define MCHP_ESPI_PC_EC_IRQ REG8(MCHP_ESPI_IO_BASE + 0x12C) /* LTR Registers */ -#define MCHP_ESPI_IO_LTR_STATUS REG16(MCHP_ESPI_IO_BASE + 0x220) -#define MCHP_ESPI_IO_LTR_IEN REG8(MCHP_ESPI_IO_BASE + 0x224) -#define MCHP_ESPI_IO_LTR_CTRL REG16(MCHP_ESPI_IO_BASE + 0x228) -#define MCHP_ESPI_IO_LTR_MSG REG16(MCHP_ESPI_IO_BASE + 0x22C) - +#define MCHP_ESPI_IO_LTR_STATUS REG16(MCHP_ESPI_IO_BASE + 0x220) +#define MCHP_ESPI_IO_LTR_IEN REG8(MCHP_ESPI_IO_BASE + 0x224) +#define MCHP_ESPI_IO_LTR_CTRL REG16(MCHP_ESPI_IO_BASE + 0x228) +#define MCHP_ESPI_IO_LTR_MSG REG16(MCHP_ESPI_IO_BASE + 0x22C) /* OOB Channel Registers */ -#define MCHP_ESPI_OOB_RX_ADDR_LO REG32(MCHP_ESPI_IO_BASE + 0x240) -#define MCHP_ESPI_OOB_RX_ADDR_HI REG32(MCHP_ESPI_IO_BASE + 0x244) -#define MCHP_ESPI_OOB_TX_ADDR_LO REG32(MCHP_ESPI_IO_BASE + 0x248) -#define MCHP_ESPI_OOB_TX_ADDR_HI REG32(MCHP_ESPI_IO_BASE + 0x24C) -#define MCHP_ESPI_OOB_RX_LEN REG32(MCHP_ESPI_IO_BASE + 0x250) -#define MCHP_ESPI_OOB_TX_LEN REG32(MCHP_ESPI_IO_BASE + 0x254) -#define MCHP_ESPI_OOB_RX_CTL REG32(MCHP_ESPI_IO_BASE + 0x258) -#define MCHP_ESPI_OOB_RX_IEN REG8(MCHP_ESPI_IO_BASE + 0x25C) -#define MCHP_ESPI_OOB_RX_STATUS REG32(MCHP_ESPI_IO_BASE + 0x260) -#define MCHP_ESPI_OOB_TX_CTL REG32(MCHP_ESPI_IO_BASE + 0x264) -#define MCHP_ESPI_OOB_TX_IEN REG8(MCHP_ESPI_IO_BASE + 0x268) -#define MCHP_ESPI_OOB_TX_STATUS REG32(MCHP_ESPI_IO_BASE + 0x26C) - +#define MCHP_ESPI_OOB_RX_ADDR_LO REG32(MCHP_ESPI_IO_BASE + 0x240) +#define MCHP_ESPI_OOB_RX_ADDR_HI REG32(MCHP_ESPI_IO_BASE + 0x244) +#define MCHP_ESPI_OOB_TX_ADDR_LO REG32(MCHP_ESPI_IO_BASE + 0x248) +#define MCHP_ESPI_OOB_TX_ADDR_HI REG32(MCHP_ESPI_IO_BASE + 0x24C) +#define MCHP_ESPI_OOB_RX_LEN REG32(MCHP_ESPI_IO_BASE + 0x250) +#define MCHP_ESPI_OOB_TX_LEN REG32(MCHP_ESPI_IO_BASE + 0x254) +#define MCHP_ESPI_OOB_RX_CTL REG32(MCHP_ESPI_IO_BASE + 0x258) +#define MCHP_ESPI_OOB_RX_IEN REG8(MCHP_ESPI_IO_BASE + 0x25C) +#define MCHP_ESPI_OOB_RX_STATUS REG32(MCHP_ESPI_IO_BASE + 0x260) +#define MCHP_ESPI_OOB_TX_CTL REG32(MCHP_ESPI_IO_BASE + 0x264) +#define MCHP_ESPI_OOB_TX_IEN REG8(MCHP_ESPI_IO_BASE + 0x268) +#define MCHP_ESPI_OOB_TX_STATUS REG32(MCHP_ESPI_IO_BASE + 0x26C) /* Flash Channel Registers */ -#define MCHP_ESPI_FC_ADDR_LO REG32(MCHP_ESPI_IO_BASE + 0x280) -#define MCHP_ESPI_FC_ADDR_HI REG32(MCHP_ESPI_IO_BASE + 0x284) -#define MCHP_ESPI_FC_BUF_ADDR_LO REG32(MCHP_ESPI_IO_BASE + 0x288) -#define MCHP_ESPI_FC_BUF_ADDR_HI REG32(MCHP_ESPI_IO_BASE + 0x28C) -#define MCHP_ESPI_FC_XFR_LEN REG32(MCHP_ESPI_IO_BASE + 0x290) -#define MCHP_ESPI_FC_CTL REG32(MCHP_ESPI_IO_BASE + 0x294) -#define MCHP_ESPI_FC_IEN REG8(MCHP_ESPI_IO_BASE + 0x298) -#define MCHP_ESPI_FC_CONFIG REG32(MCHP_ESPI_IO_BASE + 0x29C) -#define MCHP_ESPI_FC_STATUS REG32(MCHP_ESPI_IO_BASE + 0x2A0) - +#define MCHP_ESPI_FC_ADDR_LO REG32(MCHP_ESPI_IO_BASE + 0x280) +#define MCHP_ESPI_FC_ADDR_HI REG32(MCHP_ESPI_IO_BASE + 0x284) +#define MCHP_ESPI_FC_BUF_ADDR_LO REG32(MCHP_ESPI_IO_BASE + 0x288) +#define MCHP_ESPI_FC_BUF_ADDR_HI REG32(MCHP_ESPI_IO_BASE + 0x28C) +#define MCHP_ESPI_FC_XFR_LEN REG32(MCHP_ESPI_IO_BASE + 0x290) +#define MCHP_ESPI_FC_CTL REG32(MCHP_ESPI_IO_BASE + 0x294) +#define MCHP_ESPI_FC_IEN REG8(MCHP_ESPI_IO_BASE + 0x298) +#define MCHP_ESPI_FC_CONFIG REG32(MCHP_ESPI_IO_BASE + 0x29C) +#define MCHP_ESPI_FC_STATUS REG32(MCHP_ESPI_IO_BASE + 0x2A0) /* VWire Channel Registers */ -#define MCHP_ESPI_VW_STATUS REG8(MCHP_ESPI_IO_BASE + 0x2B0) - +#define MCHP_ESPI_VW_STATUS REG8(MCHP_ESPI_IO_BASE + 0x2B0) /* Global Registers */ /* 32-bit register containing CAP_ID/CAP0/CAP1/PC_CAP */ -#define MCHP_ESPI_IO_REG32_A REG32(MCHP_ESPI_IO_BASE + 0x2E0) -#define MCHP_ESPI_IO_CAP_ID REG8(MCHP_ESPI_IO_BASE + 0x2E0) -#define MCHP_ESPI_IO_CAP0 REG8(MCHP_ESPI_IO_BASE + 0x2E1) -#define MCHP_ESPI_IO_CAP1 REG8(MCHP_ESPI_IO_BASE + 0x2E2) -#define MCHP_ESPI_IO_PC_CAP REG8(MCHP_ESPI_IO_BASE + 0x2E3) +#define MCHP_ESPI_IO_REG32_A REG32(MCHP_ESPI_IO_BASE + 0x2E0) +#define MCHP_ESPI_IO_CAP_ID REG8(MCHP_ESPI_IO_BASE + 0x2E0) +#define MCHP_ESPI_IO_CAP0 REG8(MCHP_ESPI_IO_BASE + 0x2E1) +#define MCHP_ESPI_IO_CAP1 REG8(MCHP_ESPI_IO_BASE + 0x2E2) +#define MCHP_ESPI_IO_PC_CAP REG8(MCHP_ESPI_IO_BASE + 0x2E3) /* 32-bit register containing VW_CAP/OOB_CAP/FC_CAP/PC_READY */ -#define MCHP_ESPI_IO_REG32_B REG32(MCHP_ESPI_IO_BASE + 0x2E4) -#define MCHP_ESPI_IO_VW_CAP REG8(MCHP_ESPI_IO_BASE + 0x2E4) -#define MCHP_ESPI_IO_OOB_CAP REG8(MCHP_ESPI_IO_BASE + 0x2E5) -#define MCHP_ESPI_IO_FC_CAP REG8(MCHP_ESPI_IO_BASE + 0x2E6) -#define MCHP_ESPI_IO_PC_READY REG8(MCHP_ESPI_IO_BASE + 0x2E7) +#define MCHP_ESPI_IO_REG32_B REG32(MCHP_ESPI_IO_BASE + 0x2E4) +#define MCHP_ESPI_IO_VW_CAP REG8(MCHP_ESPI_IO_BASE + 0x2E4) +#define MCHP_ESPI_IO_OOB_CAP REG8(MCHP_ESPI_IO_BASE + 0x2E5) +#define MCHP_ESPI_IO_FC_CAP REG8(MCHP_ESPI_IO_BASE + 0x2E6) +#define MCHP_ESPI_IO_PC_READY REG8(MCHP_ESPI_IO_BASE + 0x2E7) /* 32-bit register containing OOB_READY/FC_READY/RESET_STATUS/RESET_IEN */ -#define MCHP_ESPI_IO_REG32_C REG32(MCHP_ESPI_IO_BASE + 0x2E8) -#define MCHP_ESPI_IO_OOB_READY REG8(MCHP_ESPI_IO_BASE + 0x2E8) -#define MCHP_ESPI_IO_FC_READY REG8(MCHP_ESPI_IO_BASE + 0x2E9) -#define MCHP_ESPI_IO_RESET_STATUS REG8(MCHP_ESPI_IO_BASE + 0x2EA) -#define MCHP_ESPI_IO_RESET_IEN REG8(MCHP_ESPI_IO_BASE + 0x2EB) +#define MCHP_ESPI_IO_REG32_C REG32(MCHP_ESPI_IO_BASE + 0x2E8) +#define MCHP_ESPI_IO_OOB_READY REG8(MCHP_ESPI_IO_BASE + 0x2E8) +#define MCHP_ESPI_IO_FC_READY REG8(MCHP_ESPI_IO_BASE + 0x2E9) +#define MCHP_ESPI_IO_RESET_STATUS REG8(MCHP_ESPI_IO_BASE + 0x2EA) +#define MCHP_ESPI_IO_RESET_IEN REG8(MCHP_ESPI_IO_BASE + 0x2EB) /* 32-bit register containing PLTRST_SRC/VW_READY */ -#define MCHP_ESPI_IO_REG32_D REG32(MCHP_ESPI_IO_BASE + 0x2EC) -#define MCHP_ESPI_IO_PLTRST_SRC REG8(MCHP_ESPI_IO_BASE + 0x2EC) -#define MCHP_ESPI_IO_VW_READY REG8(MCHP_ESPI_IO_BASE + 0x2ED) - - +#define MCHP_ESPI_IO_REG32_D REG32(MCHP_ESPI_IO_BASE + 0x2EC) +#define MCHP_ESPI_IO_PLTRST_SRC REG8(MCHP_ESPI_IO_BASE + 0x2EC) +#define MCHP_ESPI_IO_VW_READY REG8(MCHP_ESPI_IO_BASE + 0x2ED) /* Bits in MCHP_ESPI_IO_CAP0 */ -#define MCHP_ESPI_CAP0_PC_SUPP 0x01 -#define MCHP_ESPI_CAP0_VW_SUPP 0x02 -#define MCHP_ESPI_CAP0_OOB_SUPP 0x04 -#define MCHP_ESPI_CAP0_FC_SUPP 0x08 -#define MCHP_ESPI_CAP0_ALL_CHAN_SUPP (MCHP_ESPI_CAP0_PC_SUPP | \ - MCHP_ESPI_CAP0_VW_SUPP | \ - MCHP_ESPI_CAP0_OOB_SUPP | \ - MCHP_ESPI_CAP0_FC_SUPP) - +#define MCHP_ESPI_CAP0_PC_SUPP 0x01 +#define MCHP_ESPI_CAP0_VW_SUPP 0x02 +#define MCHP_ESPI_CAP0_OOB_SUPP 0x04 +#define MCHP_ESPI_CAP0_FC_SUPP 0x08 +#define MCHP_ESPI_CAP0_ALL_CHAN_SUPP \ + (MCHP_ESPI_CAP0_PC_SUPP | MCHP_ESPI_CAP0_VW_SUPP | \ + MCHP_ESPI_CAP0_OOB_SUPP | MCHP_ESPI_CAP0_FC_SUPP) /* Bits in MCHP_ESPI_IO_CAP1 */ -#define MCHP_ESPI_CAP1_RW_MASK 0x37 -#define MCHP_ESPI_CAP1_MAX_FREQ_MASK 0x07 -#define MCHP_ESPI_CAP1_MAX_FREQ_20M 0x00 -#define MCHP_ESPI_CAP1_MAX_FREQ_25M 0x01 -#define MCHP_ESPI_CAP1_MAX_FREQ_33M 0x02 -#define MCHP_ESPI_CAP1_MAX_FREQ_50M 0x03 -#define MCHP_ESPI_CAP1_MAX_FREQ_66M 0x04 -#define MCHP_ESPI_CAP1_IO_BITPOS 4 -#define MCHP_ESPI_CAP1_IO_MASK0 0x03 -#define MCHP_ESPI_CAP1_IO_MASK (0x03ul << 4) -#define MCHP_ESPI_CAP1_IO1_VAL 0x00 -#define MCHP_ESPI_CAP1_IO12_VAL 0x01 -#define MCHP_ESPI_CAP1_IO24_VAL 0x02 -#define MCHP_ESPI_CAP1_IO124_VAL 0x03 -#define MCHP_ESPI_CAP1_IO1 (0x00 << 4) -#define MCHP_ESPI_CAP1_IO12 (0x01 << 4) -#define MCHP_ESPI_CAP1_IO24 (0x02 << 4) -#define MCHP_ESPI_CAP1_IO124 (0x03 << 4) - - +#define MCHP_ESPI_CAP1_RW_MASK 0x37 +#define MCHP_ESPI_CAP1_MAX_FREQ_MASK 0x07 +#define MCHP_ESPI_CAP1_MAX_FREQ_20M 0 +#define MCHP_ESPI_CAP1_MAX_FREQ_25M 1 +#define MCHP_ESPI_CAP1_MAX_FREQ_33M 2 +#define MCHP_ESPI_CAP1_MAX_FREQ_50M 3 +#define MCHP_ESPI_CAP1_MAX_FREQ_66M 4 +#define MCHP_ESPI_CAP1_SINGLE_MODE 0 +#define MCHP_ESPI_CAP1_SINGLE_DUAL_MODE BIT(0) +#define MCHP_ESPI_CAP1_SINGLE_QUAD_MODE BIT(1) +#define MCHP_ESPI_CAP1_ALL_MODE \ + (MCHP_ESPI_CAP1_SINGLE_MODE | MCHP_ESPI_CAP1_SINGLE_DUAL_MODE | \ + MCHP_ESPI_CAP1_SINGLE_QUAD_MODE) +#define MCHP_ESPI_CAP1_IO_BITPOS 4 +#define MCHP_ESPI_CAP1_IO_MASK0 0x03 +#define MCHP_ESPI_CAP1_IO_MASK (0x03ul << MCHP_ESPI_CAP1_IO_BITPOS) +#define MCHP_ESPI_CAP1_IO1_VAL 0x00 +#define MCHP_ESPI_CAP1_IO12_VAL 0x01 +#define MCHP_ESPI_CAP1_IO24_VAL 0x02 +#define MCHP_ESPI_CAP1_IO124_VAL 0x03 +#define MCHP_ESPI_CAP1_IO1 (0x00 << 4) +#define MCHP_ESPI_CAP1_IO12 (0x01 << 4) +#define MCHP_ESPI_CAP1_IO24 (0x02 << 4) +#define MCHP_ESPI_CAP1_IO124 (0x03 << 4) /* Bits in MCHP_ESPI_IO_RESET_STATUS and MCHP_ESPI_IO_RESET_IEN */ -#define MCHP_ESPI_RST_PIN_MASK 0x02 -#define MCHP_ESPI_RST_CHG_STS 1 -#define MCHP_ESPI_RST_IEN 1 - - +#define MCHP_ESPI_RST_PIN_MASK BIT(1) +#define MCHP_ESPI_RST_CHG_STS BIT(0) +#define MCHP_ESPI_RST_IEN BIT(0) /* Bits in MCHP_ESPI_IO_PLTRST_SRC */ -#define MCHP_ESPI_PLTRST_SRC_VW 0 -#define MCHP_ESPI_PLTRST_SRC_PIN 1 - - +#define MCHP_ESPI_PLTRST_SRC_VW 0 +#define MCHP_ESPI_PLTRST_SRC_PIN 1 /* * eSPI Slave Activate Register * bit[0] = 0 de-active block is clock-gates * bit[0] = 1 block is powered and functional */ -#define MCHP_ESPI_ACTIVATE REG8(MCHP_ESPI_IO_BASE + 0x330) - - +#define MCHP_ESPI_ACTIVATE REG8(MCHP_ESPI_IO_BASE + 0x330) /* * IO BAR's starting at offset 0x134 * b[16]=virtualized R/W @@ -1489,80 +549,24 @@ enum MCHP_i2c_port { * b[13:8]=Logical Device Number RO * b[7:0]=mask */ -#define MCHP_ESPI_IO_BAR_CTL(x) REG32(MCHP_ESPI_IO_BASE + \ - 0x134 + ((x) << 2)) +#define MCHP_ESPI_IO_BAR_CTL(x) REG32(MCHP_ESPI_IO_BASE + ((x)*4) + 0x134) /* access mask field of eSPI IO BAR Control register */ -#define MCHP_ESPI_IO_BAR_CTL_MASK(x) REG8(MCHP_ESPI_IO_BASE + \ - 0x134 + ((x) << 2)) - +#define MCHP_ESPI_IO_BAR_CTL_MASK(x) REG8(MCHP_ESPI_IO_BASE + ((x)*4) + 0x134) /* * IO BAR's starting at offset 0x334 * b[31:16] = I/O address * b[15:1]=0 reserved * b[0] = valid */ -#define MCHP_ESPI_IO_BAR(x) REG32(MCHP_ESPI_IO_BASE + 0x334 + ((x) << 2)) - -#define MCHP_ESPI_IO_BAR_VALID(x) REG8(MCHP_ESPI_IO_BASE + \ - 0x334 + ((x) << 2) + 0) -#define MCHP_ESPI_IO_BAR_ADDR_LSB(x) REG8(MCHP_ESPI_IO_BASE + \ - 0x334 + ((x) << 2) + 2) -#define MCHP_ESPI_IO_BAR_ADDR_MSB(x) REG8(MCHP_ESPI_IO_BASE + \ - 0x334 + ((x) << 2) + 3) -#define MCHP_ESPI_IO_BAR_ADDR(x) REG16(MCHP_ESPI_IO_BASE + \ - 0x334 + ((x) << 2) + 2) - -/* Indices for use in above macros */ -#define MCHP_ESPI_IO_BAR_ID_CFG_PORT 0 -#define MCHP_ESPI_IO_BAR_ID_MEM_CMPNT 1 -#define MCHP_ESPI_IO_BAR_ID_MAILBOX 2 -#define MCHP_ESPI_IO_BAR_ID_8042 3 -#define MCHP_ESPI_IO_BAR_ID_ACPI_EC0 4 -#define MCHP_ESPI_IO_BAR_ID_ACPI_EC1 5 -#define MCHP_ESPI_IO_BAR_ID_ACPI_EC2 6 -#define MCHP_ESPI_IO_BAR_ID_ACPI_EC3 7 -#define MCHP_ESPI_IO_BAR_ID_ACPI_EC4 8 -#define MCHP_ESPI_IO_BAR_ID_ACPI_PM1 9 -#define MCHP_ESPI_IO_BAR_ID_P92 0xA -#define MCHP_ESPI_IO_BAR_ID_UART0 0xB -#define MCHP_ESPI_IO_BAR_ID_UART1 0xC -#define MCHP_ESPI_IO_BAR_ID_EMI0 0xD -#define MCHP_ESPI_IO_BAR_ID_EMI1 0xE -#define MCHP_ESPI_IO_BAR_ID_EMI 0xF -#define MCHP_ESPI_IO_BAR_P80_0 0x10 -#define MCHP_ESPI_IO_BAR_P80_1 0x11 -#define MCHP_ESPI_IO_BAR_RTC 0x12 - +#define MCHP_ESPI_IO_BAR(x) REG32(MCHP_ESPI_IO_BASE + ((x)*4) + 0x334) +#define MCHP_ESPI_IO_BAR_VALID(x) REG8(MCHP_ESPI_IO_BASE + ((x)*4) + 0x334) +#define MCHP_ESPI_IO_BAR_ADDR_LSB(x) REG8(MCHP_ESPI_IO_BASE + ((x)*4) + 0x336) +#define MCHP_ESPI_IO_BAR_ADDR_MSB(x) REG8(MCHP_ESPI_IO_BASE + ((x)*4) + 0x337) +#define MCHP_ESPI_IO_BAR_ADDR(x) REG16(MCHP_ESPI_IO_BASE + ((x)*4) + 0x336) /* eSPI Serial IRQ registers */ -#define MCHP_ESPI_IO_SERIRQ_REG(x) REG8(MCHP_ESPI_IO_BASE + \ - 0x3ac + (x)) -#define MCHP_ESPI_MBOX_SIRQ0 0 -#define MCHP_ESPI_MBOX_SIRQ1 1 -#define MCHP_ESPI_8042_SIRQ0 2 -#define MCHP_ESPI_8042_SIRQ1 3 -#define MCHP_ESPI_ACPI_EC0_SIRQ 4 -#define MCHP_ESPI_ACPI_EC1_SIRQ 5 -#define MCHP_ESPI_ACPI_EC2_SIRQ 6 -#define MCHP_ESPI_ACPI_EC3_SIRQ 7 -#define MCHP_ESPI_ACPI_EC4_SIRQ 8 -#define MCHP_ESPI_UART0_SIRQ 9 -#define MCHP_ESPI_UART1_SIRQ 10 -#define MCHP_ESPI_EMI0_SIRQ0 11 -#define MCHP_ESPI_EMI0_SIRQ1 12 -#define MCHP_ESPI_EMI1_SIRQ0 13 -#define MCHP_ESPI_EMI1_SIRQ1 14 -#define MCHP_ESPI_EMI2_SIRQ0 15 -#define MCHP_ESPI_EMI2_SIRQ1 16 -#define MCHP_ESPI_RTC_SIRQ 17 -#define MCHP_ESPI_EC_SIRQ 18 - +#define MCHP_ESPI_IO_SERIRQ_REG(x) REG8(MCHP_ESPI_IO_BASE + 0x3ac + (x)) /* eSPI Virtual Wire Error Register */ -#define MCHP_ESPI_IO_VW_ERROR REG8(MCHP_ESPI_IO_BASE + 0x3f0) - - -/* eSPI Memory Component Base Address */ -#define MCHP_ESPI_MEM_BASE 0x400f3800 - +#define MCHP_ESPI_IO_VW_ERROR REG8(MCHP_ESPI_IO_BASE + 0x3f0) /* * eSPI Logical Device Memory Host BAR's to specify Host memory * base address and valid bit. @@ -1571,31 +575,15 @@ enum MCHP_i2c_port { * b[15:1]=0(reserved) * b[79:16]=eSPI bus memory address(Host address space) */ -#define MCHP_ESPI_MBAR_MBOX_ID 0 -#define MCHP_ESPI_MBAR_ACPI_EC0_ID 1 -#define MCHP_ESPI_MBAR_ACPI_EC1_ID 2 -#define MCHP_ESPI_MBAR_ACPI_EC2_ID 3 -#define MCHP_ESPI_MBAR_ACPI_EC3_ID 4 -#define MCHP_ESPI_MBAR_ACPI_EC4_ID 5 -#define MCHP_ESPI_MBAR_EMI0_ID 6 -#define MCHP_ESPI_MBAR_EMI1_ID 7 -#define MCHP_ESPI_MBAR_EMI2_ID 8 - -#define MCHP_ESPI_MBAR_VALID(x) \ - REG8(MCHP_ESPI_MEM_BASE + 0x130 + ((x) << 3) + ((x) << 1)) - +#define MCHP_ESPI_MBAR_VALID(x) REG8(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x130) #define MCHP_ESPI_MBAR_HOST_ADDR_0_15(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x132 + ((x) << 3) + ((x) << 1)) - + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x132) #define MCHP_ESPI_MBAR_HOST_ADDR_16_31(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x134 + ((x) << 3) + ((x) << 1)) - + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x134) #define MCHP_ESPI_MBAR_HOST_ADDR_32_47(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x136 + ((x) << 3) + ((x) << 1)) - + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x136) #define MCHP_ESPI_MBAR_HOST_ADDR_48_63(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x138 + ((x) << 3) + ((x) << 1)) - + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x138) /* * eSPI SRAM BAR's * b[0,3,8:15] = 0 reserved @@ -1603,45 +591,27 @@ enum MCHP_i2c_port { * b[7:4] = size * b[79:16] = Host address */ -#define MCHP_ESPI_SRAM_BAR_CFG(x) \ - REG8(MCHP_ESPI_MEM_BASE + 0x1ac + ((x) << 3) + ((x) << 1)) - +#define MCHP_ESPI_SRAM_BAR_CFG(x) REG8(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x1ac) #define MCHP_ESPI_SRAM_BAR_ADDR_0_15(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x1ae + ((x) << 3) + ((x) << 1)) - + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x1ae) #define MCHP_ESPI_SRAM_BAR_ADDR_16_31(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x1b0 + ((x) << 3) + ((x) << 1)) - + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x1b0) #define MCHP_ESPI_SRAM_BAR_ADDR_32_47(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x1b2 + ((x) << 3) + ((x) << 1)) - + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x1b2) #define MCHP_ESPI_SRAM_BAR_ADDR_48_63(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x1b4 + ((x) << 3) + ((x) << 1)) - + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x1b4) /* eSPI Memory Bus Master Registers */ -#define MCHP_ESPI_BM_STATUS \ - REG32(MCHP_ESPI_MEM_BASE + 0x200) -#define MCHP_ESPI_BM_IEN \ - REG32(MCHP_ESPI_MEM_BASE + 0x204) -#define MCHP_ESPI_BM_CONFIG \ - REG32(MCHP_ESPI_MEM_BASE + 0x208) -#define MCHP_ESPI_BM1_CTL \ - REG32(MCHP_ESPI_MEM_BASE + 0x210) -#define MCHP_ESPI_BM1_HOST_ADDR_LO \ - REG32(MCHP_ESPI_MEM_BASE + 0x214) -#define MCHP_ESPI_BM1_HOST_ADDR_HI \ - REG32(MCHP_ESPI_MEM_BASE + 0x218) -#define MCHP_ESPI_BM1_EC_ADDR \ - REG32(MCHP_ESPI_MEM_BASE + 0x21c) -#define MCHP_ESPI_BM2_CTL \ - REG32(MCHP_ESPI_MEM_BASE + 0x224) -#define MCHP_ESPI_BM2_HOST_ADDR_LO \ - REG32(MCHP_ESPI_MEM_BASE + 0x228) -#define MCHP_ESPI_BM2_HOST_ADDR_HI \ - REG32(MCHP_ESPI_MEM_BASE + 0x22c) -#define MCHP_ESPI_BM2_EC_ADDR \ - REG32(MCHP_ESPI_MEM_BASE + 0x230) - +#define MCHP_ESPI_BM_STATUS REG32(MCHP_ESPI_MEM_BASE + 0x200) +#define MCHP_ESPI_BM_IEN REG32(MCHP_ESPI_MEM_BASE + 0x204) +#define MCHP_ESPI_BM_CONFIG REG32(MCHP_ESPI_MEM_BASE + 0x208) +#define MCHP_ESPI_BM1_CTL REG32(MCHP_ESPI_MEM_BASE + 0x210) +#define MCHP_ESPI_BM1_HOST_ADDR_LO REG32(MCHP_ESPI_MEM_BASE + 0x214) +#define MCHP_ESPI_BM1_HOST_ADDR_HI REG32(MCHP_ESPI_MEM_BASE + 0x218) +#define MCHP_ESPI_BM1_EC_ADDR REG32(MCHP_ESPI_MEM_BASE + 0x21c) +#define MCHP_ESPI_BM2_CTL REG32(MCHP_ESPI_MEM_BASE + 0x224) +#define MCHP_ESPI_BM2_HOST_ADDR_LO REG32(MCHP_ESPI_MEM_BASE + 0x228) +#define MCHP_ESPI_BM2_HOST_ADDR_HI REG32(MCHP_ESPI_MEM_BASE + 0x22c) +#define MCHP_ESPI_BM2_EC_ADDR REG32(MCHP_ESPI_MEM_BASE + 0x230) /* * eSPI Memory BAR's for Logical Devices * b[0] = Valid @@ -1654,37 +624,29 @@ enum MCHP_i2c_port { * * BAR's start at offset 0x330 */ -#define MCHP_ESPI_MBAR_EC_VSIZE(x) \ - REG32(MCHP_ESPI_MEM_BASE + 0x330 + ((x) << 3) + ((x) << 1)) +#define MCHP_ESPI_MBAR_EC_VSIZE(x) REG32(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x330) #define MCHP_ESPI_MBAR_EC_ADDR_0_15(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x332 + ((x) << 3) + ((x) << 1)) + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x332) #define MCHP_ESPI_MBAR_EC_ADDR_16_31(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x334 + ((x) << 3) + ((x) << 1)) + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x334) #define MCHP_ESPI_MBAR_EC_ADDR_32_47(x) \ - REG16(MCHP_ESPI_MEM_BASE + 0x336 + ((x) << 3) + ((x) << 1)) - -/* eSPI Virtual Wire Component Base Address */ -#define MCHP_ESPI_VW_BASE 0x400f9c00 - -#define MCHP_ESPI_MSVW_BASE (MCHP_ESPI_VW_BASE) -#define MCHP_ESPI_SMVW_BASE ((MCHP_ESPI_VW_BASE) + 0x200ul) + REG16(MCHP_ESPI_MEM_BASE + ((x)*10) + 0x336) -#define MCHP_ESPI_MSVW_LEN 12 -#define MCHP_ESPI_SMVW_LEN 8 +/* eSPI Virtual Wire registers */ +#define MCHP_ESPI_MSVW_LEN 12 +#define MCHP_ESPI_SMVW_LEN 8 -#define MCHP_ESPI_MSVW_ADDR(n) ((MCHP_ESPI_MSVW_BASE) + \ - ((n) * (MCHP_ESPI_MSVW_LEN))) - -#define MCHP_ESPI_MSVW_MTOS_BITPOS 4 - -#define MCHP_ESPI_MSVW_IRQSEL_LEVEL_LO 0 -#define MCHP_ESPI_MSVW_IRQSEL_LEVEL_HI 1 -#define MCHP_ESPI_MSVW_IRQSEL_DISABLED 4 -#define MCHP_ESPI_MSVW_IRQSEL_RISING 0x0d -#define MCHP_ESPI_MSVW_IRQSEL_FALLING 0x0e -#define MCHP_ESPI_MSVW_IRQSEL_BOTH_EDGES 0x0f +#define MCHP_ESPI_MSVW_ADDR(n) \ + ((MCHP_ESPI_MSVW_BASE) + ((n) * (MCHP_ESPI_MSVW_LEN))) +#define MCHP_ESPI_MSVW_MTOS_BITPOS 4 +#define MCHP_ESPI_MSVW_IRQSEL_LEVEL_LO 0 +#define MCHP_ESPI_MSVW_IRQSEL_LEVEL_HI 1 +#define MCHP_ESPI_MSVW_IRQSEL_DISABLED 4 +#define MCHP_ESPI_MSVW_IRQSEL_RISING 0x0d +#define MCHP_ESPI_MSVW_IRQSEL_FALLING 0x0e +#define MCHP_ESPI_MSVW_IRQSEL_BOTH_EDGES 0x0f /* * Mapping of eSPI Master Host VWire group indices to @@ -1692,93 +654,60 @@ enum MCHP_i2c_port { * MSVW_xy where xy = PCH VWire number. * Each PCH VWire number controls 4 virtual wires. */ -#define MSVW_H02 0 -#define MSVW_H03 1 -#define MSVW_H07 2 -#define MSVW_H41 3 -#define MSVW_H42 4 -#define MSVW_H43 5 -#define MSVW_H44 6 -#define MSVW_H47 7 -#define MSVW_H4A 8 -#define MSVW_HSPARE0 9 -#define MSVW_HSPARE1 10 -#define MSVW_MAX 11 - +#define MSVW_H02 0 +#define MSVW_H03 1 +#define MSVW_H07 2 +#define MSVW_H41 3 +#define MSVW_H42 4 +#define MSVW_H43 5 +#define MSVW_H44 6 +#define MSVW_H47 7 +#define MSVW_H4A 8 +#define MSVW_HSPARE0 9 +#define MSVW_HSPARE1 10 +#define MSVW_MAX 11 /* Access 32-bit word in 96-bit MSVW register. 0 <= w <= 2 */ -#define MSVW(id, w) REG32(MCHP_ESPI_MSVW_BASE + ((id) << 3) + \ - ((id << 2)) + (((w) & 0x03) << 2)) - +#define MSVW(id, w) REG32(MCHP_ESPI_MSVW_BASE + ((id)*12) + (((w)&0x03) * 4)) /* Access index value in byte 0 */ -#define MCHP_ESPI_VW_M2S_INDEX(id) \ - REG8(MCHP_ESPI_VW_BASE + ((id) << 3) + ((id) << 2)) - +#define MCHP_ESPI_VW_M2S_INDEX(id) REG8(MCHP_ESPI_VW_BASE + ((id)*12)) /* * Access MTOS_SOURCE and MTOS_STATE in byte 1 * MTOS_SOURCE = b[1:0] specifies reset source * MTOS_STATE = b[7:4] are states loaded into SRC[0:3] on reset event */ -#define MCHP_ESPI_VW_M2S_MTOS(id) \ - REG8(MCHP_ESPI_VW_BASE + 1 + ((id) << 3) + ((id) << 2)) - +#define MCHP_ESPI_VW_M2S_MTOS(id) REG8(MCHP_ESPI_VW_BASE + 1 + ((id)*12)) /* * Access Index, MTOS Source, and MTOS State as 16-bit quantity. * Index in b[7:0] * MTOS Source in b[9:8] * MTOS State in b[15:12] */ -#define MCHP_ESPI_VW_M2S_INDEX_MTOS(id) \ - REG16(MCHP_ESPI_VW_BASE + ((id) << 3) + ((id) << 2)) - +#define MCHP_ESPI_VW_M2S_INDEX_MTOS(id) REG16(MCHP_ESPI_VW_BASE + ((id)*12)) /* Access SRCn IRQ Select bit fields */ -#define MCHP_ESPI_VW_M2S_IRQSEL0(id) \ - (REG8(MCHP_ESPI_VW_BASE + 4 + ((id) << 3) + ((id) << 2))) - -#define MCHP_ESPI_VW_M2S_IRQSEL1(id) \ - (REG8(MCHP_ESPI_VW_BASE + 5 + ((id) << 3) + ((id) << 2))) - -#define MCHP_ESPI_VW_M2S_IRQSEL2(id) \ - (REG8(MCHP_ESPI_VW_BASE + 6 + ((id) << 3) + ((id) << 2))) - -#define MCHP_ESPI_VW_M2S_IRQSEL3(id) \ - (REG8(MCHP_ESPI_VW_BASE + 7 + ((id) << 3) + ((id) << 2))) - +#define MCHP_ESPI_VW_M2S_IRQSEL0(id) REG8(MCHP_ESPI_VW_BASE + ((id)*12) + 4) +#define MCHP_ESPI_VW_M2S_IRQSEL1(id) REG8(MCHP_ESPI_VW_BASE + ((id)*12) + 5) +#define MCHP_ESPI_VW_M2S_IRQSEL2(id) REG8(MCHP_ESPI_VW_BASE + ((id)*12) + 6) +#define MCHP_ESPI_VW_M2S_IRQSEL3(id) REG8(MCHP_ESPI_VW_BASE + ((id)*12) + 7) #define MCHP_ESPI_VW_M2S_IRQSEL(id, src) \ - REG8(MCHP_ESPI_VW_BASE + 4 + ((id) << 3) + ((id) << 2) + \ - ((src) & 0x03)) - -#define MCHP_ESPI_VW_M2S_IRQSEL_ALL(id) \ - (REG32(MCHP_ESPI_VW_BASE + 4 + ((id) << 3) + ((id) << 2))) - + REG8(MCHP_ESPI_VW_BASE + ((id)*12) + 4 + ((src)&0x03)) +#define MCHP_ESPI_VW_M2S_IRQSEL_ALL(id) REG32(MCHP_ESPI_VW_BASE + ((id)*12) + 4) /* Access individual source bits */ -#define MCHP_ESPI_VW_M2S_SRC0(id) \ - REG8(MCHP_ESPI_VW_BASE + 8 + ((id) << 3) + ((id) << 2)) - -#define MCHP_ESPI_VW_M2S_SRC1(id) \ - REG8(MCHP_ESPI_VW_BASE + 9 + ((id) << 3) + ((id) << 2)) - -#define MCHP_ESPI_VW_M2S_SRC2(id) \ - REG8(MCHP_ESPI_VW_BASE + 10 + ((id) << 3) + ((id) << 2)) - -#define MCHP_ESPI_VW_M2S_SRC3(id) \ - REG8(MCHP_ESPI_VW_BASE + 11 + ((id) << 3) + ((id) << 2)) - +#define MCHP_ESPI_VW_M2S_SRC0(id) REG8(MCHP_ESPI_VW_BASE + ((id)*12) + 8) +#define MCHP_ESPI_VW_M2S_SRC1(id) REG8(MCHP_ESPI_VW_BASE + ((id)*12) + 9) +#define MCHP_ESPI_VW_M2S_SRC2(id) REG8(MCHP_ESPI_VW_BASE + ((id)*12) + 10) +#define MCHP_ESPI_VW_M2S_SRC3(id) REG8(MCHP_ESPI_VW_BASE + ((id)*12) + 11) /* * Access all four Source bits as 32-bit value, Source bits are located * at bits[0, 8, 16, 24] of 32-bit word. */ -#define MCHP_ESPI_VW_M2S_SRC_ALL(id) \ - REG32(MCHP_ESPI_VW_BASE + 8 + ((id) << 3) + ((id) << 2)) - +#define MCHP_ESPI_VW_M2S_SRC_ALL(id) REG32(MCHP_ESPI_VW_BASE + 8 + ((id)*12)) /* * Access an individual Source bit as byte where * bit[0] contains the source bit. */ #define MCHP_ESPI_VW_M2S_SRC(id, src) \ - REG8(MCHP_ESPI_VW_BASE + 8 + ((id) << 3) + ((src) & 0x03)) - - + REG8(MCHP_ESPI_VW_BASE + 8 + ((id)*8) + ((src)&0x03)) /* * Indices of Slave to Master Virtual Wire registers. @@ -1789,461 +718,141 @@ enum MCHP_i2c_port { * MCHP maps Host indices into its Slave to Master * 64-bit registers. */ -#define SMVW_H04 0 -#define SMVW_H05 1 -#define SMVW_H06 2 -#define SMVW_H40 3 -#define SMVW_H45 4 -#define SMVW_H46 5 -#define SMVW_HSPARE6 6 -#define SMVW_HSPARE7 7 -#define SMVW_HSPARE8 8 -#define SMVW_HSPARE9 9 -#define SMVW_HSPARE10 10 -#define SMVW_MAX 11 - +#define SMVW_H04 0 +#define SMVW_H05 1 +#define SMVW_H06 2 +#define SMVW_H40 3 +#define SMVW_H45 4 +#define SMVW_H46 5 +#define SMVW_HSPARE6 6 +#define SMVW_HSPARE7 7 +#define SMVW_HSPARE8 8 +#define SMVW_HSPARE9 9 +#define SMVW_HSPARE10 10 +#define SMVW_MAX 11 /* Access 32-bit word of 64-bit SMVW register, 0 <= w <= 1 */ -#define SMVW(id, w) REG32(MCHP_ESPI_VW_BASE + 0x200 + ((id) << 3) + \ - (((w) & 0x01) << 2)) - +#define SMVW(id, w) \ + REG32(MCHP_ESPI_VW_BASE + ((id)*8) + 0x200 + (((w)&0x01) * 4)) /* Access Index in b[7:0] of byte 0 */ -#define MCHP_ESPI_VW_S2M_INDEX(id) \ - REG8(MCHP_ESPI_VW_BASE + 0x200 + ((id) << 3)) - +#define MCHP_ESPI_VW_S2M_INDEX(id) REG8(MCHP_ESPI_VW_BASE + ((id)*8) + 0x200) /* Access STOM_SOURCE and STOM_STATE in byte 1 * STOM_SOURCE = b[1:0] * STOM_STATE = b[7:4] */ -#define MCHP_ESPI_VW_S2M_STOM(id) \ - REG8(MCHP_ESPI_VW_BASE + 0x201 + ((id) << 3)) - +#define MCHP_ESPI_VW_S2M_STOM(id) REG8(MCHP_ESPI_VW_BASE + ((id)*8) + 0x201) /* Access Index, STOM_SOURCE, and STOM_STATE in bytes[1:0] * Index = b[7:0] * STOM_SOURCE = b[9:8] * STOM_STATE = [15:12] */ #define MCHP_ESPI_VW_S2M_INDEX_STOM(id) \ - REG16(MCHP_ESPI_VW_BASE + 0x200 + ((id) << 3)) - + REG16(MCHP_ESPI_VW_BASE + ((id)*8) + 0x200) /* Access Change[0:3] RO bits. Set to 1 if any of SRC[0:3] change */ -#define MCHP_ESPI_VW_S2M_CHANGE(id) \ - REG8(MCHP_ESPI_VW_BASE + 0x202 + ((id) << 3)) - +#define MCHP_ESPI_VW_S2M_CHANGE(id) REG8(MCHP_ESPI_VW_BASE + ((id)*8) + 0x202) /* Access individual SRC bits * bit[0] = SRCn */ -#define MCHP_ESPI_VW_S2M_SRC0(id) \ - REG8(MCHP_ESPI_VW_BASE + 0x204 + ((id) << 3)) - -#define MCHP_ESPI_VW_S2M_SRC1(id) \ - REG8(MCHP_ESPI_VW_BASE + 0x205 + ((id) << 3)) - -#define MCHP_ESPI_VW_S2M_SRC2(id) \ - REG8(MCHP_ESPI_VW_BASE + 0x206 + ((id) << 3)) - -#define MCHP_ESPI_VW_S2M_SRC3(id) \ - REG8(MCHP_ESPI_VW_BASE + 0x206 + ((id) << 3)) - +#define MCHP_ESPI_VW_S2M_SRC0(id) REG8(MCHP_ESPI_VW_BASE + ((id)*8) + 0x204) +#define MCHP_ESPI_VW_S2M_SRC1(id) REG8(MCHP_ESPI_VW_BASE + ((id)*8) + 0x205) +#define MCHP_ESPI_VW_S2M_SRC2(id) REG8(MCHP_ESPI_VW_BASE + ((id)*8) + 0x206) +#define MCHP_ESPI_VW_S2M_SRC3(id) REG8(MCHP_ESPI_VW_BASE + ((id)*8) + 0x207) /* * Access specified source bit as byte read/write. * Source bit is in bit[0] of byte. */ #define MCHP_ESPI_VW_S2M_SRC(id, src) \ - REG8(MCHP_ESPI_VW_BASE + 0x204 + ((id) << 3) + ((src) & 0x03)) - - + REG8(MCHP_ESPI_VW_BASE + 0x204 + ((id)*8) + ((src)&0x03)) /* Access SRC[0:3] as 32-bit word * SRC0 = b[0] * SRC1 = b[8] * SRC2 = b[16] * SRC3 = b[24] */ -#define MCHP_ESPI_VW_S2M_SRC_ALL(id) \ - REG32(MCHP_ESPI_VW_BASE + 0x204 + ((id) << 3)) - - -/* - * eSPI RESET, channel enables and operations except Master-to-Slave - * WWires are all on GIRQ19 - */ -#define MCHP_ESPI_GIRQ 19 -#define MCHP_ESPI_PC_GIRQ_BIT (1ul << 0) -#define MCHP_ESPI_BM1_GIRQ_BIT (1ul << 1) -#define MCHP_ESPI_BM2_GIRQ_BIT (1ul << 2) -#define MCHP_ESPI_LTR_GIRQ_BIT (1ul << 3) -#define MCHP_ESPI_OOB_TX_GIRQ_BIT (1ul << 4) -#define MCHP_ESPI_OOB_RX_GIRQ_BIT (1ul << 5) -#define MCHP_ESPI_FC_GIRQ_BIT (1ul << 6) -#define MCHP_ESPI_RESET_GIRQ_BIT (1ul << 7) -#define MCHP_ESPI_VW_EN_GIRQ_BIT (1ul << 8) - -/* - * eSPI Master-to-Slave WWire interrupts are on GIRQ24 and GIRQ25 - */ -#define MCHP_ESPI_MSVW_0_6_GIRQ 24 -#define MCHP_ESPI_MSVW_7_10_GIRQ 25 -/* - * Four source bits, SRC[0:3] per Master-to-Slave register - * v = MSVW [0:10] - * n = VWire SRC bit = [0:3] - */ -#define MCHP_ESPI_MSVW_GIRQ(v) (24 + ((v) > 6 ? 1 : 0)) - -#define MCHP_ESPI_MSVW_SRC_GIRQ_BIT(v, n) \ - (((v) > 6) ? (1ul << (((v)-7)+(n))) : (1ul << ((v)+(n)))) - - +#define MCHP_ESPI_VW_S2M_SRC_ALL(id) REG32(MCHP_ESPI_VW_BASE + ((id)*8) + 0x204) /* DMA */ -#define MCHP_DMA_BASE 0x40002400 -#define MCHP_DMA_CH_OFS 0x40 -#define MCHP_DMA_CH_OFS_BITPOS 6 -#define MCHP_DMA_CH_BASE (MCHP_DMA_BASE + MCHP_DMA_CH_OFS) - -#define MCHP_DMA_MAIN_CTRL REG8(MCHP_DMA_BASE + 0x00) -#define MCHP_DMA_MAIN_PKT_RO REG32(MCHP_DMA_BASE + 0x04) -#define MCHP_DMA_MAIN_FSM_RO REG8(MCHP_DMA_BASE + 0x08) - +#define MCHP_DMA_MAIN_CTRL REG8(MCHP_DMA_BASE + 0x00) +#define MCHP_DMA_MAIN_PKT_RO REG32(MCHP_DMA_BASE + 0x04) +#define MCHP_DMA_MAIN_FSM_RO REG8(MCHP_DMA_BASE + 0x08) /* DMA Channel Registers */ -#define MCHP_DMA_CH_ACT(n) \ - REG8(MCHP_DMA_CH_BASE + ((n) << MCHP_DMA_CH_OFS_BITPOS)) - +#define MCHP_DMA_CH_ACT(n) REG8(MCHP_DMA_CH_BASE + ((n)*MCHP_DMA_CH_OFS)) #define MCHP_DMA_CH_MEM_START(n) \ - REG32(MCHP_DMA_CH_BASE + 0x04 + \ - ((n) << MCHP_DMA_CH_OFS_BITPOS)) - + REG32(MCHP_DMA_CH_BASE + ((n)*MCHP_DMA_CH_OFS) + 0x04) #define MCHP_DMA_CH_MEM_END(n) \ - REG32(MCHP_DMA_CH_BASE + 0x08 + \ - ((n) << MCHP_DMA_CH_OFS_BITPOS)) - + REG32(MCHP_DMA_CH_BASE + ((n)*MCHP_DMA_CH_OFS) + 0x08) #define MCHP_DMA_CH_DEV_ADDR(n) \ - REG32(MCHP_DMA_CH_BASE + 0x0c + \ - ((n) << MCHP_DMA_CH_OFS_BITPOS)) - + REG32(MCHP_DMA_CH_BASE + ((n)*MCHP_DMA_CH_OFS) + 0x0c) #define MCHP_DMA_CH_CTRL(n) \ - REG32(MCHP_DMA_CH_BASE + 0x10 + \ - ((n) << MCHP_DMA_CH_OFS_BITPOS)) - + REG32(MCHP_DMA_CH_BASE + ((n)*MCHP_DMA_CH_OFS) + 0x10) #define MCHP_DMA_CH_ISTS(n) \ - REG8(MCHP_DMA_CH_BASE + 0x14 + \ - ((n) << MCHP_DMA_CH_OFS_BITPOS)) - + REG32(MCHP_DMA_CH_BASE + ((n)*MCHP_DMA_CH_OFS) + 0x14) #define MCHP_DMA_CH_IEN(n) \ - REG8(MCHP_DMA_CH_BASE + 0x18 + \ - ((n) << MCHP_DMA_CH_OFS_BITPOS)) - + REG32(MCHP_DMA_CH_BASE + ((n)*MCHP_DMA_CH_OFS) + 0x18) #define MCHP_DMA_CH_FSM_RO(n) \ - REG16(MCHP_DMA_CH_BASE + 0x1c + \ - ((n) << MCHP_DMA_CH_OFS_BITPOS)) - + REG32(MCHP_DMA_CH_BASE + ((n)*MCHP_DMA_CH_OFS) + 0x1c) /* * DMA Channel 0 implements CRC-32 feature */ -#define MCHP_DMA_CH0_CRC32_EN REG8(MCHP_DMA_CH_BASE + 0x20) -#define MCHP_DMA_CH0_CRC32_DATA REG32(MCHP_DMA_CH_BASE + 0x24) -#define MCHP_DMA_CH0_CRC32_POST_STS REG8(MCHP_DMA_CH_BASE + 0x28) - +#define MCHP_DMA_CH0_CRC32_EN REG8(MCHP_DMA_CH_BASE + 0x20) +#define MCHP_DMA_CH0_CRC32_DATA REG32(MCHP_DMA_CH_BASE + 0x24) +#define MCHP_DMA_CH0_CRC32_POST_STS REG8(MCHP_DMA_CH_BASE + 0x28) /* * DMA Channel 1 implements memory fill feature */ -#define MCHP_DMA_CH1_FILL_EN \ - REG8(MCHP_DMA_CH_BASE + MCHP_DMA_CH_OFS + 0x20) -#define MCHP_DMA_CH1_FILL_DATA \ - REG32(MCHP_DMA_CH_BASE + MCHP_DMA_CH_OFS + 0x24) - - -/* - * Available DMA channels. - * - * On MCHP, any DMA channel may serve any device. Since we have - * 14 channels and 14 devices, we make each channel dedicated to the - * device of the same number. - */ -enum dma_channel { - /* Channel numbers */ - MCHP_DMAC_I2C0_SLAVE = 0, - MCHP_DMAC_I2C0_MASTER = 1, - MCHP_DMAC_I2C1_SLAVE = 2, - MCHP_DMAC_I2C1_MASTER = 3, - MCHP_DMAC_I2C2_SLAVE = 4, - MCHP_DMAC_I2C2_MASTER = 5, - MCHP_DMAC_I2C3_SLAVE = 6, - MCHP_DMAC_I2C3_MASTER = 7, - MCHP_DMAC_SPI0_TX = 8, - MCHP_DMAC_SPI0_RX = 9, - MCHP_DMAC_SPI1_TX = 10, - MCHP_DMAC_SPI1_RX = 11, - MCHP_DMAC_QMSPI0_TX = 12, - MCHP_DMAC_QMSPI0_RX = 13, - /* Channel count */ - MCHP_DMAC_COUNT = 14, -}; - - +#define MCHP_DMA_CH1_FILL_EN REG8(MCHP_DMA_CH_BASE + MCHP_DMA_CH_OFS + 0x20) +#define MCHP_DMA_CH1_FILL_DATA REG32(MCHP_DMA_CH_BASE + MCHP_DMA_CH_OFS + 0x24) /* Bits for DMA Main Control */ -#define MCHP_DMA_MAIN_CTRL_ACT BIT(0) -#define MCHP_DMA_MAIN_CTRL_SRST BIT(1) - +#define MCHP_DMA_MAIN_CTRL_ACT BIT(0) +#define MCHP_DMA_MAIN_CTRL_SRST BIT(1) /* Bits for DMA channel regs */ -#define MCHP_DMA_ACT_EN BIT(0) +#define MCHP_DMA_ACT_EN BIT(0) /* DMA Channel Control */ -#define MCHP_DMA_ABORT BIT(25) -#define MCHP_DMA_SW_GO BIT(24) -#define MCHP_DMA_XFER_SIZE_MASK (7ul << 20) -#define MCHP_DMA_XFER_SIZE(x) ((x) << 20) -#define MCHP_DMA_DIS_HW_FLOW BIT(19) -#define MCHP_DMA_INC_DEV BIT(17) -#define MCHP_DMA_INC_MEM BIT(16) -#define MCHP_DMA_DEV(x) ((x) << 9) -#define MCHP_DMA_DEV_MASK0 (0x7f) -#define MCHP_DMA_DEV_MASK (0x7f << 9) -#define MCHP_DMA_TO_DEV BIT(8) -#define MCHP_DMA_DONE BIT(2) -#define MCHP_DMA_RUN BIT(0) +#define MCHP_DMA_ABORT BIT(25) +#define MCHP_DMA_SW_GO BIT(24) +#define MCHP_DMA_XFER_SIZE_MASK (7ul << 20) +#define MCHP_DMA_XFER_SIZE(x) ((x) << 20) +#define MCHP_DMA_DIS_HW_FLOW BIT(19) +#define MCHP_DMA_INC_DEV BIT(17) +#define MCHP_DMA_INC_MEM BIT(16) +#define MCHP_DMA_DEV(x) ((x) << 9) +#define MCHP_DMA_DEV_MASK0 (0x7f) +#define MCHP_DMA_DEV_MASK (0x7f << 9) +#define MCHP_DMA_TO_DEV BIT(8) +#define MCHP_DMA_DONE BIT(2) +#define MCHP_DMA_RUN BIT(0) /* DMA Channel Status */ -#define MCHP_DMA_STS_ALU_DONE BIT(3) -#define MCHP_DMA_STS_DONE BIT(2) -#define MCHP_DMA_STS_HWFL_ERR BIT(1) -#define MCHP_DMA_STS_BUS_ERR BIT(0) - -/* - * Peripheral device DMA Device ID's for bits [15:9] - * in DMA channel control register. - */ -#define MCHP_DMA_I2C0_SLV_REQ_ID 0 -#define MCHP_DMA_I2C0_MTR_REQ_ID 1 -#define MCHP_DMA_I2C1_SLV_REQ_ID 2 -#define MCHP_DMA_I2C1_MTR_REQ_ID 3 -#define MCHP_DMA_I2C2_SLV_REQ_ID 4 -#define MCHP_DMA_I2C2_MTR_REQ_ID 5 -#define MCHP_DMA_I2C3_SLV_REQ_ID 6 -#define MCHP_DMA_I2C3_MTR_REQ_ID 7 -#define MCHP_DMA_GPSPI0_TX_REQ_ID 8 -#define MCHP_DMA_GPSPI0_RX_REQ_ID 9 -#define MCHP_DMA_GPSPI1_TX_REQ_ID 10 -#define MCHP_DMA_GPSPI1_RX_REQ_ID 11 -#define MCHP_DMA_QMSPI0_TX_REQ_ID 12 -#define MCHP_DMA_QMSPI0_RX_REQ_ID 13 +#define MCHP_DMA_STS_ALU_DONE BIT(3) +#define MCHP_DMA_STS_DONE BIT(2) +#define MCHP_DMA_STS_HWFL_ERR BIT(1) +#define MCHP_DMA_STS_BUS_ERR BIT(0) /* * Required structure typedef for common/dma.h interface * !!! checkpatch.pl will not like this !!! + * structure moved to chip level dma.c + * We can't remove dma_chan_t as its used in DMA API header. */ - -/* Registers for a single channel of the DMA controller */ struct MCHP_dma_chan { - uint32_t act; /* Activate */ - uint32_t mem_start; /* Memory start address */ - uint32_t mem_end; /* Memory end address */ - uint32_t dev; /* Device address */ - uint32_t ctrl; /* Control */ - uint32_t int_status; /* Interrupt status */ - uint32_t int_enabled; /* Interrupt enabled */ - uint32_t chfsm; /* channel fsm read-only */ - uint32_t alu_en; /* channels 0 & 1 only */ - uint32_t alu_data; /* channels 0 & 1 only */ - uint32_t alu_sts; /* channel 0 only */ - uint32_t alu_ro; /* channel 0 only */ - uint32_t rsvd[4]; /* 0x30 - 0x3F */ + uint32_t act; /* Activate */ + uint32_t mem_start; /* Memory start address */ + uint32_t mem_end; /* Memory end address */ + uint32_t dev; /* Device address */ + uint32_t ctrl; /* Control */ + uint32_t int_status; /* Interrupt status */ + uint32_t int_enabled; /* Interrupt enabled */ + uint32_t chfsm; /* channel fsm read-only */ + uint32_t alu_en; /* channels 0 & 1 only */ + uint32_t alu_data; /* channels 0 & 1 only */ + uint32_t alu_sts; /* channel 0 only */ + uint32_t alu_ro; /* channel 0 only */ + uint32_t rsvd[4]; /* 0x30 - 0x3F */ }; /* Common code and header file must use this */ typedef struct MCHP_dma_chan dma_chan_t; -/* - * Hardware delay register. - * Write of 0 <= n <= 31 will stall the Cortex-M4 - * for n+1 microseconds. Interrupts will not be - * serviced during the delay period. Reads have - * no effect. - */ -#define MCHP_USEC_DELAY_REG_ADDR (0x10000000) -#define MCHP_USEC_DELAY(x) (REG8(MCHP_USEC_DELAY_REG_ADDR) = (x)) - -/* IRQ Numbers */ -#ifdef CHIP_FAMILY - -#ifdef CHIP_FAMILY_MEC17XX - -#define MCHP_IRQ_GIRQ8 0 -#define MCHP_IRQ_GIRQ9 1 -#define MCHP_IRQ_GIRQ10 2 -#define MCHP_IRQ_GIRQ11 3 -#define MCHP_IRQ_GIRQ12 4 -#define MCHP_IRQ_GIRQ13 5 -#define MCHP_IRQ_GIRQ14 6 -#define MCHP_IRQ_GIRQ15 7 -#define MCHP_IRQ_GIRQ16 8 -#define MCHP_IRQ_GIRQ17 9 -#define MCHP_IRQ_GIRQ18 10 -#define MCHP_IRQ_GIRQ19 11 -#define MCHP_IRQ_GIRQ20 12 -#define MCHP_IRQ_GIRQ21 13 -/* - * GIRQ22 is not connected to NVIC, it wakes peripheral - * subsystem but not ARM core. - */ -#define MCHP_IRQ_GIRQ23 14 -#define MCHP_IRQ_GIRQ24 15 -#define MCHP_IRQ_GIRQ25 16 -#define MCHP_IRQ_GIRQ26 17 -/* 18 - 19 Not connected */ -#define MCHP_IRQ_I2C_0 20 -#define MCHP_IRQ_I2C_1 21 -#define MCHP_IRQ_I2C_2 22 -#define MCHP_IRQ_I2C_3 23 -#define MCHP_IRQ_DMA_0 24 -#define MCHP_IRQ_DMA_1 25 -#define MCHP_IRQ_DMA_2 26 -#define MCHP_IRQ_DMA_3 27 -#define MCHP_IRQ_DMA_4 28 -#define MCHP_IRQ_DMA_5 29 -#define MCHP_IRQ_DMA_6 30 -#define MCHP_IRQ_DMA_7 31 -#define MCHP_IRQ_DMA_8 32 -#define MCHP_IRQ_DMA_9 33 -#define MCHP_IRQ_DMA_10 34 -#define MCHP_IRQ_DMA_11 35 -#define MCHP_IRQ_DMA_12 36 -#define MCHP_IRQ_DMA_13 37 -/* 38 - 39 Not connected */ -#define MCHP_IRQ_UART0 40 -#define MCHP_IRQ_UART1 41 -#define MCHP_IRQ_EMI0 42 -#define MCHP_IRQ_EMI1 43 -#define MCHP_IRQ_EMI2 44 -#define MCHP_IRQ_ACPIEC0_IBF 45 -#define MCHP_IRQ_ACPIEC0_OBE 46 -#define MCHP_IRQ_ACPIEC1_IBF 47 -#define MCHP_IRQ_ACPIEC1_OBE 48 -#define MCHP_IRQ_ACPIEC2_IBF 49 -#define MCHP_IRQ_ACPIEC2_OBE 50 -#define MCHP_IRQ_ACPIEC3_IBF 51 -#define MCHP_IRQ_ACPIEC3_OBE 52 -#define MCHP_IRQ_ACPIEC4_IBF 53 -#define MCHP_IRQ_ACPIEC4_OBE 54 -#define MCHP_IRQ_ACPIPM1_CTL 55 -#define MCHP_IRQ_ACPIPM1_EN 56 -#define MCHP_IRQ_ACPIPM1_STS 57 -#define MCHP_IRQ_8042EM_OBE 58 -#define MCHP_IRQ_8042EM_IBF 59 -#define MCHP_IRQ_MAILBOX_DATA 60 -/* 61 Not connected */ -#define MCHP_IRQ_PORT80DBG0 62 -#define MCHP_IRQ_PORT80DBG1 63 -/* 64 Not connected */ -#define MCHP_IRQ_PKE_ERR 65 -#define MCHP_IRQ_PKE_END 66 -#define MCHP_IRQ_NDRNG 67 -#define MCHP_IRQ_AES 68 -#define MCHP_IRQ_HASH 69 -#define MCHP_IRQ_PECI_HOST 70 -#define MCHP_IRQ_TACH_0 71 -#define MCHP_IRQ_TACH_1 72 -#define MCHP_IRQ_TACH_2 73 -#define MCHP_IRQ_FAN0_FAIL 74 -#define MCHP_IRQ_FAN0_STALL 75 -#define MCHP_IRQ_FAN1_FAIL 76 -#define MCHP_IRQ_FAN1_STALL 77 -#define MCHP_IRQ_ADC_SNGL 78 -#define MCHP_IRQ_ADC_RPT 79 -#define MCHP_IRQ_RCID0 80 -#define MCHP_IRQ_RCID1 81 -#define MCHP_IRQ_RCID2 82 -#define MCHP_IRQ_LED0_WDT 83 -#define MCHP_IRQ_LED1_WDT 84 -#define MCHP_IRQ_LED2_WDT 85 -#define MCHP_IRQ_LED3_WDT 86 -#define MCHP_IRQ_PHOT 87 -#define MCHP_IRQ_PWRGRD0 88 -#define MCHP_IRQ_PWRGRD1 89 -#define MCHP_IRQ_LPC 90 -#define MCHP_IRQ_QMSPI0 91 -#define MCHP_IRQ_SPI0_TX 92 -#define MCHP_IRQ_SPI0_RX 93 -#define MCHP_IRQ_SPI1_TX 94 -#define MCHP_IRQ_SPI1_RX 95 -#define MCHP_IRQ_BCM0_ERR 96 -#define MCHP_IRQ_BCM0_BUSY 97 -#define MCHP_IRQ_BCM1_ERR 98 -#define MCHP_IRQ_BCM1_BUSY 99 -#define MCHP_IRQ_PS2_0 100 -#define MCHP_IRQ_PS2_1 101 -#define MCHP_IRQ_PS2_2 102 -#define MCHP_IRQ_ESPI_PC 103 -#define MCHP_IRQ_ESPI_BM1 104 -#define MCHP_IRQ_ESPI_BM2 105 -#define MCHP_IRQ_ESPI_LTR 106 -#define MCHP_IRQ_ESPI_OOB_UP 107 -#define MCHP_IRQ_ESPI_OOB_DN 108 -#define MCHP_IRQ_ESPI_FC 109 -#define MCHP_IRQ_ESPI_RESET 110 -#define MCHP_IRQ_RTOS_TIMER 111 -#define MCHP_IRQ_HTIMER0 112 -#define MCHP_IRQ_HTIMER1 113 -#define MCHP_IRQ_WEEK_ALARM 114 -#define MCHP_IRQ_SUBWEEK 115 -#define MCHP_IRQ_WEEK_SEC 116 -#define MCHP_IRQ_WEEK_SUBSEC 117 -#define MCHP_IRQ_WEEK_SYSPWR 118 -#define MCHP_IRQ_RTC 119 -#define MCHP_IRQ_RTC_ALARM 120 -#define MCHP_IRQ_VCI_OVRD_IN 121 -#define MCHP_IRQ_VCI_IN0 122 -#define MCHP_IRQ_VCI_IN1 123 -#define MCHP_IRQ_VCI_IN2 124 -#define MCHP_IRQ_VCI_IN3 125 -#define MCHP_IRQ_VCI_IN4 126 -#define MCHP_IRQ_VCI_IN5 127 -#define MCHP_IRQ_VCI_IN6 128 -#define MCHP_IRQ_PS20A_WAKE 129 -#define MCHP_IRQ_PS20B_WAKE 130 -#define MCHP_IRQ_PS21A_WAKE 131 -#define MCHP_IRQ_PS21B_WAKE 132 -#define MCHP_IRQ_PS2_2_WAKE 133 -#define MCHP_IRQ_ENVMON 134 -#define MCHP_IRQ_KSC_INT 135 -#define MCHP_IRQ_TIMER16_0 136 -#define MCHP_IRQ_TIMER16_1 137 -#define MCHP_IRQ_TIMER16_2 138 -#define MCHP_IRQ_TIMER16_3 139 -#define MCHP_IRQ_TIMER32_0 140 -#define MCHP_IRQ_TIMER32_1 141 -#define MCHP_IRQ_CNTR_TM0 142 -#define MCHP_IRQ_CNTR_TM1 143 -#define MCHP_IRQ_CNTR_TM2 144 -#define MCHP_IRQ_CNTR_TM3 145 -#define MCHP_IRQ_CCT_TMR 146 -#define MCHP_IRQ_CCT_CAP0 147 -#define MCHP_IRQ_CCT_CAP1 148 -#define MCHP_IRQ_CCT_CAP2 149 -#define MCHP_IRQ_CCT_CAP3 150 -#define MCHP_IRQ_CCT_CAP4 151 -#define MCHP_IRQ_CCT_CAP5 152 -#define MCHP_IRQ_CCT_CMP0 153 -#define MCHP_IRQ_CCT_CMP1 154 -#define MCHP_IRQ_EEPROM 155 -#define MCHP_IRQ_ESPI_VW_EN 156 - -#define MCHP_IRQ_MAX 157 - -#else -#error "BUILD ERROR: CHIP_FAMILY_MEC17XX not defined!" -#endif /* #ifdef CHIP_FAMILY_MEC17XX */ - -#else -#error "BUILD ERROR: CHIP_FAMILY not defined!" -#endif /* #ifdef CHIP_FAMILY */ - /* Wake pin definitions, defined at board-level */ -#ifndef CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC extern const enum gpio_signal hibernate_wake_pins[]; extern const int hibernate_wake_pins_used; -#else -extern enum gpio_signal hibernate_wake_pins[]; -extern int hibernate_wake_pins_used; -#endif - - #endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/mchp/spi.c b/chip/mchp/spi.c index 2d5a7e9a3f..4445666790 100644 --- a/chip/mchp/spi.c +++ b/chip/mchp/spi.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,71 +9,55 @@ #include "console.h" #include "dma.h" #include "gpio.h" +#include "hooks.h" +#include "qmspi_chip.h" #include "registers.h" #include "spi.h" +#include "spi_chip.h" +#include "task.h" #include "timer.h" #include "util.h" -#include "hooks.h" -#include "task.h" -#include "spi_chip.h" -#include "qmspi_chip.h" #if defined(CONFIG_MCHP_GPSPI) && !defined(LFW) #include "gpspi_chip.h" #endif #include "tfdp_chip.h" #define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) #define SPI_BYTE_TRANSFER_TIMEOUT_US (3 * MSEC) #define SPI_BYTE_TRANSFER_POLL_INTERVAL_US 100 - +#if defined(CONFIG_MCHP_GPSPI) && defined(CHIP_FAMILY_MEC152X) +#error "FORCED BUILD ERROR: MEC152X does not implement GPSPI!" +#endif static const struct dma_option spi_rx_option[] = { - { - MCHP_DMAC_QMSPI0_RX, - (void *)(MCHP_QMSPI0_RX_FIFO_ADDR), - MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM - }, + { MCHP_DMAC_QMSPI0_RX, (void *)(MCHP_QMSPI0_RX_FIFO_ADDR), + MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM }, #if defined(CONFIG_MCHP_GPSPI) && !defined(LFW) #if CONFIG_MCHP_GPSPI & 0x01 - { - MCHP_DMAC_SPI0_RX, - (void *)&MCHP_SPI_RD(0), - MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM - }, + { MCHP_DMAC_SPI0_RX, (void *)&MCHP_SPI_RD(0), + MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM }, #endif #if CONFIG_MCHP_GPSPI & 0x02 - { - MCHP_DMAC_SPI1_RX, - (void *)&MCHP_SPI_RD(1), - MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM - }, + { MCHP_DMAC_SPI1_RX, (void *)&MCHP_SPI_RD(1), + MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM }, #endif #endif }; static const struct dma_option spi_tx_option[] = { - { - MCHP_DMAC_QMSPI0_TX, - (void *)(MCHP_QMSPI0_TX_FIFO_ADDR), - MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM - }, + { MCHP_DMAC_QMSPI0_TX, (void *)(MCHP_QMSPI0_TX_FIFO_ADDR), + MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM }, #if defined(CONFIG_MCHP_GPSPI) && !defined(LFW) #if CONFIG_MCHP_GPSPI & 0x01 - { - MCHP_DMAC_SPI0_TX, - (void *)&MCHP_SPI_TD(0), - MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM - }, + { MCHP_DMAC_SPI0_TX, (void *)&MCHP_SPI_TD(0), + MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM }, #endif #if CONFIG_MCHP_GPSPI & 0x02 - { - MCHP_DMAC_SPI1_TX, - (void *)&MCHP_SPI_TD(1), - MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM - }, + { MCHP_DMAC_SPI1_TX, (void *)&MCHP_SPI_TD(1), + MCHP_DMA_XFER_SIZE(1) + MCHP_DMA_INC_MEM }, #endif #endif }; @@ -129,8 +113,7 @@ static void spi_mutex_unlock(uint8_t hw_port) * Public SPI interface */ -const void *spi_dma_option(const struct spi_device_t *spi_device, - int is_tx) +const void *spi_dma_option(const struct spi_device_t *spi_device, int is_tx) { uint32_t n; @@ -155,8 +138,8 @@ const void *spi_dma_option(const struct spi_device_t *spi_device, } int spi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) { int rc; @@ -167,13 +150,13 @@ int spi_transaction_async(const struct spi_device_t *spi_device, #if defined(CONFIG_MCHP_GPSPI) && !defined(LFW) case GPSPI0_PORT: case GPSPI1_PORT: - rc = gpspi_transaction_async(spi_device, txdata, - txlen, rxdata, rxlen); + rc = gpspi_transaction_async(spi_device, txdata, txlen, rxdata, + rxlen); break; #endif case QMSPI0_PORT: - rc = qmspi_transaction_async(spi_device, txdata, - txlen, rxdata, rxlen); + rc = qmspi_transaction_async(spi_device, txdata, txlen, rxdata, + rxlen); break; default: rc = EC_ERROR_INVAL; @@ -241,8 +224,8 @@ int spi_transaction_wait(const struct spi_device_t *spi_device) * without the overhead of DMA setup. */ int spi_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) { int rc; @@ -267,31 +250,26 @@ int spi_transaction(const struct spi_device_t *spi_device, /** * Enable SPI port and associated controller * - * @param port Zero based index into spi_device an array of - * struct spi_device_t + * @param spi_device SPI device * @param enable * @return EC_SUCCESS or EC_ERROR_INVAL if port is unrecognized * @note called from common/spi_flash.c * - * spi_devices[].port is defined as + * spi_device->port is defined as * bits[3:0] = controller instance * bits[7:4] = controller family 0 = QMSPI, 1 = GPSPI */ -int spi_enable(int port, int enable) +int spi_enable(const struct spi_device_t *spi_device, int enable) { int rc; - uint8_t hw_port; - + uint8_t hw_port = spi_device->port; rc = EC_ERROR_INVAL; - if (port < spi_devices_used) { - hw_port = spi_devices[port].port; - if ((hw_port & 0xF0) == QMSPI_CLASS) - rc = qmspi_enable(hw_port, enable); + + if ((hw_port & 0xF0) == QMSPI_CLASS) + rc = qmspi_enable(hw_port, enable); #if defined(CONFIG_MCHP_GPSPI) && !defined(LFW) - if ((hw_port & 0xF0) == GPSPI_CLASS) - rc = gpspi_enable(hw_port, enable); + if ((hw_port & 0xF0) == GPSPI_CLASS) + rc = gpspi_enable(hw_port, enable); #endif - } - return rc; } diff --git a/chip/mchp/spi_chip.h b/chip/mchp/spi_chip.h index 75973e4a78..e651901ea4 100644 --- a/chip/mchp/spi_chip.h +++ b/chip/mchp/spi_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -13,34 +13,33 @@ #ifndef _SPI_CHIP_H #define _SPI_CHIP_H -#include #include +#include /* struct spi_device_t */ #include "spi.h" -#define SPI_DMA_OPTION_RD 0 -#define SPI_DMA_OPTION_WR 1 +#define SPI_DMA_OPTION_RD 0 +#define SPI_DMA_OPTION_WR 1 /* * bits[3:0] = controller instance * bits[7:4] = controller family * 0 = QMSPI, 1 = GPSPI */ -#define QMSPI0_PORT 0x00 -#define GPSPI0_PORT 0x10 -#define GPSPI1_PORT 0x11 +#define QMSPI0_PORT 0x00 +#define GPSPI0_PORT 0x10 +#define GPSPI1_PORT 0x11 +#define QMSPI_CLASS0 0 +#define GPSPI_CLASS0 1 -#define QMSPI_CLASS0 0 -#define GPSPI_CLASS0 1 +#define QMSPI_CLASS (0 << 4) +#define GPSPI_CLASS BIT(4) -#define QMSPI_CLASS (0 << 4) -#define GPSPI_CLASS BIT(4) - -#define QMSPI_CTRL0 0 -#define GPSPI_CTRL0 0 -#define GPSPI_CTRL1 1 +#define QMSPI_CTRL0 0 +#define GPSPI_CTRL0 0 +#define GPSPI_CTRL1 1 /* * Encode zero based controller class and instance values @@ -51,10 +50,8 @@ /* * helper to return pointer to QMSPI or GPSPI struct dma_option */ -const void *spi_dma_option(const struct spi_device_t *spi_device, - int is_tx); +const void *spi_dma_option(const struct spi_device_t *spi_device, int is_tx); #endif /* #ifndef _QMSPI_CHIP_H */ /** @} */ - diff --git a/chip/mchp/system.c b/chip/mchp/system.c index 1d152f0b79..65470c43b9 100644 --- a/chip/mchp/system.c +++ b/chip/mchp/system.c @@ -1,81 +1,103 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* System module for Chrome EC : MCHP hardware specific implementation */ -#include - #include "clock.h" -#include "common.h" +#include "clock_chip.h" +#include "common.h" /* includes config.h and board.h */ #include "console.h" #include "cpu.h" #include "gpio.h" +#include "hooks.h" #include "host_command.h" +#include "lpc_chip.h" #include "registers.h" #include "shared_mem.h" +#include "spi.h" #include "system.h" -#include "hooks.h" #include "task.h" +#include "tfdp_chip.h" #include "timer.h" #include "util.h" -#include "spi.h" -#include "clock_chip.h" -#include "lpc_chip.h" -#include "tfdp_chip.h" +#include #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) - +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) -/* Indices for hibernate data registers (RAM backed by VBAT) */ +/* Index values for hibernate data registers (RAM backed by VBAT) */ enum hibdata_index { - HIBDATA_INDEX_SCRATCHPAD = 0, /* General-purpose scratchpad */ + HIBDATA_INDEX_SCRATCHPAD = 0, /* General-purpose scratch pad */ HIBDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */ - HIBDATA_INDEX_PD0, /* USB-PD0 saved port state */ - HIBDATA_INDEX_PD1, /* USB-PD1 saved port state */ - HIBDATA_INDEX_PD2, /* USB-PD2 saved port state */ + HIBDATA_INDEX_PD0, /* USB-PD0 saved port state */ + HIBDATA_INDEX_PD1, /* USB-PD1 saved port state */ + HIBDATA_INDEX_PD2, /* USB-PD2 saved port state */ }; +/* + * Voltage rail configuration + * MEC172x VTR1 is 3.3V only, VTR2 is auto-detected 3.3 or 1.8V, and + * VTR3 is always 1.8V. + * MEC170x and MEC152x require manual selection of VTR3 for 1.8 or 3.3V. + * The eSPI pins are on VTR3 and require 1.8V + */ +#ifdef CHIP_FAMILY_MEC172X +static void vtr3_voltage_select(int use18v) +{ + (void)use18v; +} +#else +static void vtr3_voltage_select(int use18v) +{ + if (use18v) + MCHP_EC_GPIO_BANK_PWR |= MCHP_EC_GPIO_BANK_PWR_VTR3_18; + else + MCHP_EC_GPIO_BANK_PWR &= ~(MCHP_EC_GPIO_BANK_PWR_VTR3_18); +} +#endif + +/* + * The current logic will set EC_RESET_FLAG_RESET_PIN flag + * even if the reset was caused by WDT. MEC170x/MEC152x HW RESET_SYS + * status goes active for any of the following: + * RESET_VTR: power rail change + * WDT Event: WDT timed out + * FW triggered chip reset: SYSRESETREQ or PCR sys reset bit + * The code does check WDT status in the VBAT PFR register. + * Is it correct to report both EC_RESET_FLAG_RESET_PIN and + * EC_RESET_FLAG_WATCHDOG on a WDT only reset? + */ static void check_reset_cause(void) { uint32_t status = MCHP_VBAT_STS; uint32_t flags = 0; uint32_t rst_sts = MCHP_PCR_PWR_RST_STS & - (MCHP_PWR_RST_STS_VTR | - MCHP_PWR_RST_STS_VBAT); - - trace12(0, MEC, 0, - "check_reset_cause: VBAT_PFR = 0x%08X PCR PWRST = 0x%08X", - status, rst_sts); + (MCHP_PWR_RST_STS_SYS | MCHP_PWR_RST_STS_VBAT); /* Clear the reset causes now that we've read them */ MCHP_VBAT_STS |= status; MCHP_PCR_PWR_RST_STS |= rst_sts; - trace0(0, MEC, 0, "check_reset_cause: after clear"); - trace11(0, MEC, 0, " VBAT_PFR = 0x%08X", MCHP_VBAT_STS); - trace11(0, MEC, 0, " PCR PWRST = 0x%08X", MCHP_PCR_PWR_RST_STS); - /* - * BIT[6] determine VTR reset + * BIT[6] indicates RESET_SYS asserted. + * RESET_SYS will assert on VTR reset, WDT reset, or + * firmware triggering a reset using Cortex-M4 SYSRESETREQ + * or MCHP PCR system reset register. */ - if (rst_sts & MCHP_PWR_RST_STS_VTR) + if (rst_sts & MCHP_PWR_RST_STS_SYS) flags |= EC_RESET_FLAG_RESET_PIN; - flags |= chip_read_reset_flags(); chip_save_reset_flags(0); - if ((status & MCHP_VBAT_STS_WDT) && !(flags & (EC_RESET_FLAG_SOFT | - EC_RESET_FLAG_HARD | - EC_RESET_FLAG_HIBERNATE))) + if ((status & MCHP_VBAT_STS_WDT) && + !(flags & (EC_RESET_FLAG_SOFT | EC_RESET_FLAG_HARD | + EC_RESET_FLAG_HIBERNATE))) flags |= EC_RESET_FLAG_WATCHDOG; - trace11(0, MEC, 0, "check_reset_cause: EC reset flags = 0x%08x", flags); - system_set_reset_flags(flags); } @@ -90,10 +112,10 @@ int system_is_reboot_warm(void) reset_flags = system_get_reset_flags(); if ((reset_flags & EC_RESET_FLAG_RESET_PIN) || - (reset_flags & EC_RESET_FLAG_POWER_ON) || - (reset_flags & EC_RESET_FLAG_WATCHDOG) || - (reset_flags & EC_RESET_FLAG_HARD) || - (reset_flags & EC_RESET_FLAG_SOFT)) + (reset_flags & EC_RESET_FLAG_POWER_ON) || + (reset_flags & EC_RESET_FLAG_WATCHDOG) || + (reset_flags & EC_RESET_FLAG_HARD) || + (reset_flags & EC_RESET_FLAG_SOFT)) return 0; else return 1; @@ -101,31 +123,25 @@ int system_is_reboot_warm(void) /* * Sleep unused blocks to reduce power. - * Drivers/modules will unsleep their blocks. + * Drivers/modules will clear PCR sleep enables for their blocks. * Keep sleep enables cleared for required blocks: * ECIA, PMC, CPU, ECS and optionally JTAG. * SLEEP_ALL feature will set these upon sleep entry. - * Based on CONFIG_CHIPSET_DEBUG enable or disable JTAG. - * JTAG mode (4-pin or 2-pin SWD + 1-pin SWV) was set - * by Boot-ROM. We can override Boot-ROM JTAG mode - * using - * CONFIG_MCHP_JTAG_MODE + * Based on CONFIG_CHIPSET_DEBUG enable or disable ARM SWD + * 2-pin JTAG mode. */ static void chip_periph_sleep_control(void) { uint32_t d; d = MCHP_PCR_SLP_EN0_SLEEP; -#ifdef CONFIG_CHIPSET_DEBUG - d &= ~(MCHP_PCR_SLP_EN0_JTAG); -#ifdef CONFIG_MCHP_JTAG_MODE - MCHP_EC_JTAG_EN = CONFIG_MCHP_JTAG_MODE; -#else - MCHP_EC_JTAG_EN |= 0x01; -#endif -#else - MCHP_EC_JTAG_EN &= ~0x01; -#endif + + if (IS_ENABLED(CONFIG_CHIPSET_DEBUG)) { + d &= ~(MCHP_PCR_SLP_EN0_JTAG); + MCHP_EC_JTAG_EN = MCHP_JTAG_MODE_SWD | MCHP_JTAG_ENABLE; + } else + MCHP_EC_JTAG_EN &= ~(MCHP_JTAG_ENABLE); + MCHP_PCR_SLP_EN0 = d; MCHP_PCR_SLP_EN1 = MCHP_PCR_SLP_EN1_UNUSED_BLOCKS; MCHP_PCR_SLP_EN2 = MCHP_PCR_SLP_EN2_SLEEP; @@ -136,30 +152,15 @@ static void chip_periph_sleep_control(void) #ifdef CONFIG_CHIP_PRE_INIT void chip_pre_init(void) { -#ifdef CONFIG_MCHP_TFDP - uint8_t imgtype; -#endif chip_periph_sleep_control(); -#ifdef CONFIG_MCHP_TFDP - /* - * MCHP Enable TFDP for fast debug messages - * If not defined then traceN() and TRACEN() macros are empty - */ - tfdp_power(1); - tfdp_enable(1, 1); - imgtype = MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX); - CPRINTS("chip_pre_init: Image type = 0x%02x", imgtype); - trace1(0, MEC, 0, - "chip_pre_init: Image type = 0x%02x", imgtype); - - trace11(0, MEC, 0, - "chip_pre_init: MCHP_VBAT_STS = 0x%0x", - MCHP_VBAT_STS); - trace11(0, MEC, 0, - "chip_pre_init: MCHP_PCR_PWR_RST_STS = 0x%0x", - MCHP_VBAT_STS); -#endif + if (IS_ENABLED(CONFIG_MCHP_TFDP)) { + /* MCHP Enable TFDP for fast debug messages */ + tfdp_power(1); + tfdp_enable(1, 1); + CPRINTS("chip_pre_init: Image type = 0x%02x", + MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX)); + } } #endif @@ -170,16 +171,17 @@ void system_pre_init(void) * Signals bus fault to Cortex-M4 core if an address presented * to AHB is not claimed by any HW block. */ - MCHP_EC_AHB_ERR = 0; /* write any value to clear */ + MCHP_EC_AHB_ERR = 0; /* write any value to clear */ MCHP_EC_AHB_ERR_EN = 0; /* enable capture of address on error */ -#ifdef CONFIG_HOSTCMD_ESPI - MCHP_EC_GPIO_BANK_PWR |= MCHP_EC_GPIO_BANK_PWR_VTR3_18; -#endif + /* Manual voltage selection only required for MEC170x and MEC152x */ + if (IS_ENABLED(CONFIG_HOST_INTERFACE_ESPI)) + vtr3_voltage_select(1); + else + vtr3_voltage_select(0); -#ifndef CONFIG_CHIP_PRE_INIT - chip_periph_sleep_control(); -#endif + if (!IS_ENABLED(CONFIG_CHIP_PRE_INIT)) + chip_periph_sleep_control(); /* Enable direct NVIC */ MCHP_EC_INT_CTRL |= 1; @@ -197,9 +199,9 @@ void system_pre_init(void) * NOTE: GIRQ22 wake for AHB peripherals not processor. */ MCHP_INT_BLK_DIS = 0xfffffffful; - MCHP_INT_BLK_EN = (0x1Ful << 8) + (0x07ul << 24); + MCHP_INT_BLK_EN = MCHP_INT_AGGR_ONLY_BITMAP; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(SPI_FLASH_DEVICE, 1); } uint32_t chip_read_reset_flags(void) @@ -216,13 +218,13 @@ noreturn void _system_reset(int flags, int wake_from_hibernate) { uint32_t save_flags = 0; + /* DEBUG */ + CPRINTS("MEC system reset: flag = 0x%08x wake = %d", flags, + wake_from_hibernate); + /* Disable interrupts to avoid task swaps during reboot */ interrupt_disable(); - trace12(0, MEC, 0, - "_system_reset: flags=0x%08X wake_from_hibernate=%d", - flags, wake_from_hibernate); - /* Save current reset reasons if necessary */ if (flags & SYSTEM_RESET_PRESERVE_FLAGS) save_flags = system_get_reset_flags() | EC_RESET_FLAG_PRESERVED; @@ -239,15 +241,12 @@ noreturn void _system_reset(int flags, int wake_from_hibernate) chip_save_reset_flags(save_flags); - trace11(0, MEC, 0, "_system_reset: save_flags=0x%08X", save_flags); - /* * Trigger chip reset */ -#if defined(CONFIG_CHIPSET_DEBUG) -#else - MCHP_PCR_SYS_RST |= MCHP_PCR_SYS_SOFT_RESET; -#endif + if (!IS_ENABLED(CONFIG_DEBUG_BRINGUP)) + MCHP_PCR_SYS_RST |= MCHP_PCR_SYS_SOFT_RESET; + /* Spin and wait for reboot; should never return */ while (1) ; @@ -263,6 +262,7 @@ const char *system_get_chip_vendor(void) return "mchp"; } +#ifdef CHIP_VARIANT_MEC1701 /* * MEC1701H Chip ID = 0x2D * Rev = 0x82 @@ -276,6 +276,79 @@ const char *system_get_chip_name(void) return "unknown"; } } +#endif + +#ifdef CHIP_FAMILY_MEC152X +/* + * MEC152x family implements chip ID as a 32-bit + * register where: + * b[31:16] = 16-bit Device ID + * b[15:8] = 8-bit Sub ID + * b[7:0] = Revision + * + * MEC1521-128 WFBGA 0023_33_xxh + * MEC1521-144 WFBGA 0023_34_xxh + * MEC1523-144 WFBGA 0023_B4_xxh + * MEC1527-144 WFBGA 0023_74_xxh + * MEC1527-128 WFBGA 0023_73_xxh + */ +const char *system_get_chip_name(void) +{ + switch (MCHP_CHIP_DEVRID32 & ~(MCHP_CHIP_REV_MASK)) { + case 0x00201400: /* 144 pin rev A? */ + return "mec1503_revA"; + case 0x00203400: /* 144 pin */ + return "mec1501"; + case 0x00207400: /* 144 pin */ + return "mec1507"; + case 0x00208400: /* 144 pin */ + return "mec1503"; + case 0x00233300: /* 128 pin */ + case 0x00233400: /* 144 pin */ + return "mec1521"; + case 0x0023B400: /* 144 pin */ + return "mec1523"; + case 0x00237300: /* 128 pin */ + case 0x00237400: /* 144 pin */ + return "mec1527"; + default: + return "unknown"; + } +} +#endif + +#ifdef CHIP_FAMILY_MEC172X +/* + * MEC172x family implements chip ID as a 32-bit + * register where: + * b[31:16] = 16-bit Device ID + * b[15:8] = 8-bit Sub ID + * b[7:0] = Revision + * + * MEC1723N-B0-I/SZ 144 pin: 0x0022_34_xx + * MEC1727N-B0-I/SZ 144 pin: 0x0022_74_xx + * MEC1721N-B0-I/LJ 176 pin: 0x0022_27_xx + * MEC1723N-B0-I/LJ 176 pin: 0x0022_37_xx + * MEC1727N-B0-I/LJ 176 pin: 0x0022_77_xx + */ +const char *system_get_chip_name(void) +{ + switch (MCHP_CHIP_DEVRID32 & ~(MCHP_CHIP_REV_MASK)) { + case 0x00223400: + return "MEC1723NSZ"; + case 0x00227400: + return "MEC1727NSZ"; + case 0x00222700: + return "MEC1721NLJ"; + case 0x00223700: + return "MEC1723NLJ"; + case 0x00227700: + return "MEC1727NLJ"; + default: + return "unknown"; + } +} +#endif static char to_hex(int x) { @@ -337,21 +410,62 @@ int system_set_scratchpad(uint32_t value) return EC_SUCCESS; } -uint32_t system_get_scratchpad(void) +int system_get_scratchpad(uint32_t *value) +{ + *value = MCHP_VBAT_RAM(HIBDATA_INDEX_SCRATCHPAD); + return EC_SUCCESS; +} + +/* + * Local function to disable clocks in the chip's host interface + * so the chip can enter deep sleep. Only MEC170X has LPC. + * MEC152x and MEC172x only include eSPI and SPI host interfaces. + * NOTE: we do it this way because the LPC registers are only + * defined for MEC170x and the IS_ENABLED() macro causes the + * compiler to evaluate both true and false code paths. + */ +#if defined(CONFIG_HOST_INTERFACE_ESPI) +static void disable_host_ifc_clocks(void) +{ + MCHP_ESPI_ACTIVATE &= ~0x01; +} +#else +static void disable_host_ifc_clocks(void) +{ +#ifdef CHIP_FAMILY_MEC170X + MCHP_LPC_ACT &= ~0x1; +#endif +} +#endif + +/* + * Called when hibernation timer is not used in deep sleep. + * Switch 32 KHz clock logic from external 32KHz input to + * internal silicon OSC. + * NOTE: MEC172x auto-switches from external source to silicon + * oscillator. + */ +#ifdef CHIP_FAMILY_MEC172X +static void switch_32k_pin2sil(void) +{ +} +#else +static void switch_32k_pin2sil(void) { - return MCHP_VBAT_RAM(HIBDATA_INDEX_SCRATCHPAD); + MCHP_VBAT_CE &= ~(MCHP_VBAT_CE_32K_DOMAIN_32KHZ_IN_PIN); } +#endif void system_hibernate(uint32_t seconds, uint32_t microseconds) { int i; -#ifdef CONFIG_HOSTCMD_PD - /* Inform the PD MCU that we are going to hibernate. */ - host_command_pd_request_hibernate(); - /* Wait to ensure exchange with PD before hibernating. */ - msleep(100); -#endif + if (IS_ENABLED(CONFIG_HOSTCMD_PD)) { + /* Inform the PD MCU that we are going to hibernate. */ + host_command_pd_request_hibernate(); + /* Wait to ensure exchange with PD before hibernating. */ + msleep(100); + } cflush(); @@ -367,26 +481,24 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) for (i = MCHP_INT_GIRQ_FIRST; i <= MCHP_INT_GIRQ_LAST; ++i) { MCHP_INT_DISABLE(i) = 0xffffffff; - MCHP_INT_SOURCE(i) = 0xffffffff; + MCHP_INT_SOURCE(i) = 0xffffffff; } /* Disable UART */ MCHP_UART_ACT(0) &= ~0x1; -#ifdef CONFIG_HOSTCMD_ESPI - MCHP_ESPI_ACTIVATE &= ~0x01; -#else - MCHP_LPC_ACT &= ~0x1; -#endif + + disable_host_ifc_clocks(); + /* Disable JTAG */ MCHP_EC_JTAG_EN &= ~1; /* Stop watchdog */ - MCHP_WDG_CTL &= ~1; + MCHP_WDG_CTL &= ~(MCHP_WDT_CTL_ENABLE); /* Stop timers */ MCHP_TMR32_CTL(0) &= ~1; MCHP_TMR32_CTL(1) &= ~1; - for (i = 0; i < MCHP_TMR16_MAX; i++) + for (i = 0; i < MCHP_TMR16_INSTANCES; i++) MCHP_TMR16_CTL(i) &= ~1; /* Power down ADC */ @@ -423,10 +535,8 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) htimer_init(); system_set_htimer_alarm(seconds, microseconds); interrupt_enable(); - } else { - /* Not using hibernation timer. Disable 32KHz clock */ - MCHP_VBAT_CE &= ~0x2; - } + } else + switch_32k_pin2sil(); /* * Set sleep state @@ -437,14 +547,12 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) MCHP_PCR_SYS_SLP_CTL = MCHP_PCR_SYS_SLP_ALL; asm("dsb"); - asm("wfi"); + cpu_enter_suspend_mode(); asm("isb"); asm("nop"); - /* Use 48MHz clock to speed through wake-up */ - MCHP_PCR_PROC_CLK_CTL = 1; - - trace0(0, SYS, 0, "Wake from hibernate: _system_reset[0,1]"); + /* Use fastest clock to speed through wake-up */ + MCHP_PCR_PROC_CLK_CTL = MCHP_PCR_CLK_CTL_FASTEST; /* Reboot */ _system_reset(0, 1); @@ -454,7 +562,7 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) ; } -void htimer_interrupt(void) +static void htimer_interrupt(void) { /* Time to wake up */ } @@ -467,15 +575,14 @@ enum ec_image system_get_shrspi_image_copy(void) uint32_t system_get_lfw_address(void) { - uint32_t * const lfw_vector = - (uint32_t * const)CONFIG_PROGRAM_MEMORY_BASE; + uint32_t *const lfw_vector = + (uint32_t *const)CONFIG_PROGRAM_MEMORY_BASE; return *(lfw_vector + 1); } void system_set_image_copy(enum ec_image copy) { - MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX) = (copy == EC_IMAGE_RW) ? - EC_IMAGE_RW : EC_IMAGE_RO; + MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX) = + (copy == EC_IMAGE_RW) ? EC_IMAGE_RW : EC_IMAGE_RO; } - diff --git a/chip/mchp/tfdp.c b/chip/mchp/tfdp.c index b4368b46a8..eb9b903cb5 100644 --- a/chip/mchp/tfdp.c +++ b/chip/mchp/tfdp.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,12 +17,11 @@ #ifdef CONFIG_MCHP_TFDP - static uint32_t get_disable_intr(void) { uint32_t m; - __asm__ __volatile__ ("mrs %0, primask;cpsid i" : "=r" (m)); + __asm__ __volatile__("mrs %0, primask;cpsid i" : "=r"(m)); return m; } @@ -30,10 +29,9 @@ static uint32_t get_disable_intr(void) static void restore_intr(uint32_t m) { if (!m) - __asm__ __volatile__ ("cpsie i" : : : "memory"); + __asm__ __volatile__("cpsie i" : : : "memory"); } - /** * tfdp_power - Gate clocks On/Off to TFDP block when idle * @@ -48,7 +46,6 @@ void tfdp_power(uint8_t pwr_on) MCHP_PCR_SLP_EN_DEV(MCHP_PCR_TFDP); } - /** * tfdp_enable - Init Trace FIFO Data Port * @param uint8_t non-zero=enable TFDP, false=disable TFDP @@ -57,8 +54,8 @@ void tfdp_power(uint8_t pwr_on) * Else GPIO170/171 set to GPIO input, internal pull-up enabled. * @note - */ -#define MCHP_TFDP_DATA REG8(MCHP_TFDP_BASE + 0x00) -#define MCHP_TFDP_CTRL REG8(MCHP_TFDP_BASE + 0x04) +#define MCHP_TFDP_DATA REG8(MCHP_TFDP_BASE + 0x00) +#define MCHP_TFDP_CTRL REG8(MCHP_TFDP_BASE + 0x04) void tfdp_enable(uint8_t en, uint8_t pin_cfg) { @@ -73,7 +70,6 @@ void tfdp_enable(uint8_t en, uint8_t pin_cfg) } } /* end tfdp_enable() */ - /** * TFDPTrace0 - TRACE0: transmit 16-bit trace number lsb first * over TFDP. @@ -106,7 +102,6 @@ void TFDPTrace0(uint16_t nbr) #endif } - /** * TRDPTrace1 - TRACE1: transmit 16-bit trace number lsb first * and 16-bit data lsb first over TFDP. @@ -144,7 +139,6 @@ void TFDPTrace1(uint16_t nbr, uint32_t p1) #endif } - /** * TFDPTrace2 - TRACE2: transmit 16-bit trace number lsb first * and two 16-bit data parameters lsb first over TFDP. @@ -187,7 +181,6 @@ void TFDPTrace2(uint16_t nbr, uint32_t p1, uint32_t p2) #endif } - /** * TFDPTrace3 - TRACE3: transmit 16-bit trace number lsb first * and three 16-bit data parameters lsb first over TFDP. @@ -203,8 +196,7 @@ void TFDPTrace2(uint16_t nbr, uint32_t p1, uint32_t p2) * interrupts for critical section. These may use * priviledged instructions. */ -void TFDPTrace3(uint16_t nbr, uint32_t p1, - uint32_t p2, uint32_t p3) +void TFDPTrace3(uint16_t nbr, uint32_t p1, uint32_t p2, uint32_t p3) { #ifdef MCHP_TRACE_MASK_IRQ uint32_t prim; @@ -236,7 +228,6 @@ void TFDPTrace3(uint16_t nbr, uint32_t p1, #endif } - /** * TFDPTrace4 - TRACE3: transmit 16-bit trace number lsb first * and four 16-bit data parameters lsb first over TFDP. @@ -253,8 +244,8 @@ void TFDPTrace3(uint16_t nbr, uint32_t p1, * interrupts for critical section. These may use * priviledged instructions. */ -void TFDPTrace4(uint16_t nbr, uint32_t p1, uint32_t p2, - uint32_t p3, uint32_t p4) +void TFDPTrace4(uint16_t nbr, uint32_t p1, uint32_t p2, uint32_t p3, + uint32_t p4) { #ifdef MCHP_TRACE_MASK_IRQ uint32_t prim; @@ -290,7 +281,6 @@ void TFDPTrace4(uint16_t nbr, uint32_t p1, uint32_t p2, #endif } - /** * TFDPTrace11 - Transmit one 32-bit data item over TFDP * @@ -327,7 +317,6 @@ void TFDPTrace11(uint16_t nbr, uint32_t p1) #endif } - /** * TFDPTrace12 - Transmit two 32-bit data items over TFDP * @@ -383,8 +372,7 @@ void TFDPTrace12(uint16_t nbr, uint32_t p1, uint32_t p2) * @param uint32_t p3 32-bit data3 to be transmitted * */ -void TFDPTrace13(uint16_t nbr, uint32_t p1, - uint32_t p2, uint32_t p3) +void TFDPTrace13(uint16_t nbr, uint32_t p1, uint32_t p2, uint32_t p3) { #ifdef MCHP_TRACE_MASK_IRQ uint32_t prim; @@ -438,8 +426,8 @@ void TFDPTrace13(uint16_t nbr, uint32_t p1, * @param uint32_t p3 32-bit data3 to be transmitted * @param uint32_t p4 32-bit data4 to be transmitted */ -void TFDPTrace14(uint16_t nbr, uint32_t p1, uint32_t p2, - uint32_t p3, uint32_t p4) +void TFDPTrace14(uint16_t nbr, uint32_t p1, uint32_t p2, uint32_t p3, + uint32_t p4) { #ifdef MCHP_TRACE_MASK_IRQ uint32_t prim; @@ -493,7 +481,6 @@ void TFDPTrace14(uint16_t nbr, uint32_t p1, uint32_t p2, #endif /* #ifdef CONFIG_MCHP_TFDP */ - /* end tfdp.c */ /** @} */ diff --git a/chip/mchp/tfdp_chip.h b/chip/mchp/tfdp_chip.h index 64d4d0b77e..894bfaf876 100644 --- a/chip/mchp/tfdp_chip.h +++ b/chip/mchp/tfdp_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,7 +13,6 @@ #include - #ifdef CONFIG_MCHP_TFDP #undef TRACE0 @@ -35,19 +34,19 @@ #undef trace13 #undef trace14 -#define MCHP_TFDP_BASE_ADDR (0x40008c00ul) +#define MCHP_TFDP_BASE_ADDR (0x40008c00ul) -#define TFDP_FRAME_START (0xFD) +#define TFDP_FRAME_START (0xFD) -#define TFDP_POWER_ON (1u) -#define TFDP_POWER_OFF (0u) +#define TFDP_POWER_ON (1u) +#define TFDP_POWER_OFF (0u) -#define TFDP_ENABLE (1u) -#define TFDP_DISABLE (0u) -#define TFDP_CFG_PINS (1u) -#define TFDP_NO_CFG_PINS (0u) +#define TFDP_ENABLE (1u) +#define TFDP_DISABLE (0u) +#define TFDP_CFG_PINS (1u) +#define TFDP_NO_CFG_PINS (0u) -#define MCHP_TRACE_MASK_IRQ +#define MCHP_TRACE_MASK_IRQ #define TFDP_DELAY() @@ -59,18 +58,15 @@ void tfdp_power(uint8_t pwr_on); void tfdp_enable(uint8_t en, uint8_t pin_cfg); void TFDPTrace0(uint16_t nbr); void TFDPTrace1(uint16_t nbr, uint32_t p1); -void TFDPTrace2(uint16_t nbr, uint32_t p1, - uint32_t p2); -void TFDPTrace3(uint16_t nbr, uint32_t p1, - uint32_t p2, uint32_t p3); -void TFDPTrace4(uint16_t nbr, uint32_t p1, uint32_t p2, - uint32_t p3, uint32_t p4); +void TFDPTrace2(uint16_t nbr, uint32_t p1, uint32_t p2); +void TFDPTrace3(uint16_t nbr, uint32_t p1, uint32_t p2, uint32_t p3); +void TFDPTrace4(uint16_t nbr, uint32_t p1, uint32_t p2, uint32_t p3, + uint32_t p4); void TFDPTrace11(uint16_t nbr, uint32_t p1); void TFDPTrace12(uint16_t nbr, uint32_t p1, uint32_t p2); -void TFDPTrace13(uint16_t nbr, uint32_t p1, uint32_t p2, - uint32_t p3); -void TFDPTrace14(uint16_t nbr, uint32_t p1, uint32_t p2, - uint32_t p3, uint32_t p4); +void TFDPTrace13(uint16_t nbr, uint32_t p1, uint32_t p2, uint32_t p3); +void TFDPTrace14(uint16_t nbr, uint32_t p1, uint32_t p2, uint32_t p3, + uint32_t p4); #ifdef __cplusplus } @@ -80,15 +76,13 @@ void TFDPTrace14(uint16_t nbr, uint32_t p1, uint32_t p2, #define TRACE1(nbr, cat, b, str, p1) TFDPTrace1(nbr, p1) #define TRACE2(nbr, cat, b, str, p1, p2) TFDPTrace2(nbr, p1, p2) #define TRACE3(nbr, cat, b, str, p1, p2, p3) TFDPTrace3(nbr, p1, p2, p3) -#define TRACE4(nbr, cat, b, str, p1, p2, p3, p4) TFDPTrace4(nbr, p1, p2, \ - p3, p4) +#define TRACE4(nbr, cat, b, str, p1, p2, p3, p4) TFDPTrace4(nbr, p1, p2, p3, p4) #define TRACE11(nbr, cat, b, str, p1) TFDPTrace11(nbr, p1) #define TRACE12(nbr, cat, b, str, p1, p2) TFDPTrace12(nbr, p1, p2) #define TRACE13(nbr, cat, b, str, p1, p2, p3) TFDPTrace13(nbr, p1, p2, p3) #define TRACE14(nbr, cat, b, str, p1, p2, p3, p4) \ TFDPTrace14(nbr, p1, p2, p3, p4) - #else /* #ifdef MCHP_TRACE */ /* !!! To prevent compiler warnings of unused parameters, diff --git a/chip/mchp/uart.c b/chip/mchp/uart.c index 0f8bd62db8..59ea3e1c35 100644 --- a/chip/mchp/uart.c +++ b/chip/mchp/uart.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,12 +13,47 @@ #include "registers.h" #include "system.h" #include "task.h" +#include "tfdp_chip.h" #include "uart.h" #include "util.h" -#include "tfdp_chip.h" #define TX_FIFO_SIZE 16 +BUILD_ASSERT((CONFIG_UART_CONSOLE >= 0) && + (CONFIG_UART_CONSOLE < MCHP_UART_INSTANCES)); + +#if CONFIG_UART_CONSOLE == 2 + +#define UART_IRQ MCHP_IRQ_UART2 +#define UART_IRQ_BIT MCHP_UART2_GIRQ_BIT +#define UART_PCR MCHP_PCR_UART2 +#define GPIO_UART_RX GPIO_UART2_RX +/* MEC152x only. UART2 RX Pin = GPIO 0145 GIRQ08 bit[5] */ +#define UART_RX_PIN_GIRQ 8 +#define UART_RX_PIN_BIT BIT(5) + +#elif CONFIG_UART_CONSOLE == 1 + +#define UART_IRQ MCHP_IRQ_UART1 +#define UART_IRQ_BIT MCHP_UART1_GIRQ_BIT +#define UART_PCR MCHP_PCR_UART1 +#define GPIO_UART_RX GPIO_UART1_RX +/* MEC152x and MEC170x UART1 RX Pin = GPIO 0171. GIRQ08 bit[25] */ +#define UART_RX_PIN_GIRQ 8 +#define UART_RX_PIN_BIT BIT(25) + +#else + +#define UART_IRQ MCHP_IRQ_UART0 +#define UART_IRQ_BIT MCHP_UART0_GIRQ_BIT +#define UART_PCR MCHP_PCR_UART0 +#define GPIO_UART_RX GPIO_UART0_RX +/* MEC152x and MEC170x UART0 RX Pin = GPIO 0105. GIRQ09 bit[5] */ +#define UART_RX_PIN_GIRQ 9 +#define UART_RX_PIN_BIT BIT(5) + +#endif /* CONFIG_UART_CONSOLE == 2 */ + static int init_done; static int tx_fifo_used; @@ -30,7 +65,7 @@ int uart_init_done(void) void uart_tx_start(void) { /* If interrupt is already enabled, nothing to do */ - if (MCHP_UART_IER(0) & BIT(1)) + if (MCHP_UART_IER(CONFIG_UART_CONSOLE) & BIT(1)) return; /* Do not allow deep sleep while transmit in progress */ @@ -42,13 +77,13 @@ void uart_tx_start(void) * UART where the FIFO only triggers the interrupt when its * threshold is _crossed_, not just met. */ - MCHP_UART_IER(0) |= BIT(1); - task_trigger_irq(MCHP_IRQ_UART0); + MCHP_UART_IER(CONFIG_UART_CONSOLE) |= BIT(1); + task_trigger_irq(UART_IRQ); } void uart_tx_stop(void) { - MCHP_UART_IER(0) &= ~BIT(1); + MCHP_UART_IER(CONFIG_UART_CONSOLE) &= ~BIT(1); /* Re-allow deep sleep */ enable_sleep(SLEEP_MASK_UART); @@ -57,7 +92,7 @@ void uart_tx_stop(void) void uart_tx_flush(void) { /* Wait for transmit FIFO empty */ - while (!(MCHP_UART_LSR(0) & MCHP_LSR_TX_EMPTY)) + while (!(MCHP_UART_LSR(CONFIG_UART_CONSOLE) & MCHP_LSR_TX_EMPTY)) ; } @@ -68,18 +103,18 @@ int uart_tx_ready(void) * this, we check transmit FIFO empty bit every 16 characters written. */ return tx_fifo_used != 0 || - (MCHP_UART_LSR(0) & MCHP_LSR_TX_EMPTY); + (MCHP_UART_LSR(CONFIG_UART_CONSOLE) & MCHP_LSR_TX_EMPTY); } int uart_tx_in_progress(void) { /* return 0: FIFO is empty, 1: FIFO NOT Empty */ - return !(MCHP_UART_LSR(0) & MCHP_LSR_TX_EMPTY); + return !(MCHP_UART_LSR(CONFIG_UART_CONSOLE) & MCHP_LSR_TX_EMPTY); } int uart_rx_available(void) { - return MCHP_UART_LSR(0) & BIT(0); + return MCHP_UART_LSR(CONFIG_UART_CONSOLE) & BIT(0); } void uart_write_char(char c) @@ -89,85 +124,86 @@ void uart_write_char(char c) ; tx_fifo_used = (tx_fifo_used + 1) % TX_FIFO_SIZE; - MCHP_UART_TB(0) = c; + MCHP_UART_TB(CONFIG_UART_CONSOLE) = c; } int uart_read_char(void) { - return MCHP_UART_RB(0); + return MCHP_UART_RB(CONFIG_UART_CONSOLE); } static void uart_clear_rx_fifo(int channel) { - MCHP_UART_FCR(0) = BIT(0) | BIT(1); + MCHP_UART_FCR(channel) = BIT(0) | BIT(1); } void uart_disable_interrupt(void) { - task_disable_irq(MCHP_IRQ_UART0); + task_disable_irq(UART_IRQ); } void uart_enable_interrupt(void) { - task_enable_irq(MCHP_IRQ_UART0); + task_enable_irq(UART_IRQ); } /** * Interrupt handler for UART. * Lower priority below other critical ISR's. */ -void uart_ec_interrupt(void) +static void uart_ec_interrupt(void) { /* Read input FIFO until empty, then fill output FIFO */ uart_process_input(); /* Trace statement to provide time marker for UART output? */ uart_process_output(); } -DECLARE_IRQ(MCHP_IRQ_UART0, uart_ec_interrupt, 2); +DECLARE_IRQ(UART_IRQ, uart_ec_interrupt, 2); void uart_init(void) { /* Clear UART PCR sleep enable */ - MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_UART0); + MCHP_PCR_SLP_DIS_DEV(UART_PCR); /* Set UART to reset on VCC1_RESET instead of nSIO_RESET */ - MCHP_UART_CFG(0) &= ~BIT(1); + MCHP_UART_CFG(CONFIG_UART_CONSOLE) &= ~BIT(1); /* Baud rate = 115200. 1.8432MHz clock. Divisor = 1 */ /* Set CLK_SRC = 0 */ - MCHP_UART_CFG(0) &= ~BIT(0); + MCHP_UART_CFG(CONFIG_UART_CONSOLE) &= ~BIT(0); /* Set DLAB = 1 */ - MCHP_UART_LCR(0) |= BIT(7); + MCHP_UART_LCR(CONFIG_UART_CONSOLE) |= BIT(7); /* PBRG0/PBRG1 */ - MCHP_UART_PBRG0(0) = 1; - MCHP_UART_PBRG1(0) = 0; + MCHP_UART_PBRG0(CONFIG_UART_CONSOLE) = 1; + MCHP_UART_PBRG1(CONFIG_UART_CONSOLE) = 0; /* Set DLAB = 0 */ - MCHP_UART_LCR(0) &= ~BIT(7); + MCHP_UART_LCR(CONFIG_UART_CONSOLE) &= ~BIT(7); /* Set word length to 8-bit */ - MCHP_UART_LCR(0) |= BIT(0) | BIT(1); + MCHP_UART_LCR(CONFIG_UART_CONSOLE) |= BIT(0) | BIT(1); /* Enable FIFO */ - MCHP_UART_FCR(0) = BIT(0); + MCHP_UART_FCR(CONFIG_UART_CONSOLE) = BIT(0); /* Activate UART */ - MCHP_UART_ACT(0) |= BIT(0); + MCHP_UART_ACT(CONFIG_UART_CONSOLE) |= BIT(0); gpio_config_module(MODULE_UART, 1); /* - * Enable interrupts for UART0. + * Enable interrupts for UART */ - uart_clear_rx_fifo(0); - MCHP_UART_IER(0) |= BIT(0); - MCHP_UART_MCR(0) |= BIT(3); - MCHP_INT_ENABLE(MCHP_UART_GIRQ) = MCHP_UART_GIRQ_BIT(0); + uart_clear_rx_fifo(CONFIG_UART_CONSOLE); + MCHP_UART_IER(CONFIG_UART_CONSOLE) |= BIT(0); + MCHP_UART_MCR(CONFIG_UART_CONSOLE) |= BIT(3); + + MCHP_INT_ENABLE(MCHP_UART_GIRQ) = UART_IRQ_BIT; - task_enable_irq(MCHP_IRQ_UART0); + task_enable_irq(UART_IRQ); init_done = 1; } @@ -176,28 +212,27 @@ void uart_init(void) void uart_enter_dsleep(void) { /* Disable the UART interrupt. */ - task_disable_irq(MCHP_IRQ_UART0); /* NVIC interrupt for UART=13 */ + task_disable_irq(UART_IRQ); /* NVIC interrupt for UART=13 */ /* * Set the UART0 RX pin to be a GPIO-162(fixed pin) interrupt * with the flags defined in the gpio.inc file. */ - gpio_reset(GPIO_UART0_RX); + gpio_reset(GPIO_UART_RX); - /* power-down/de-activate UART0 */ - MCHP_UART_ACT(0) &= ~BIT(0); + /* power-down/deactivate UART */ + MCHP_UART_ACT(CONFIG_UART_CONSOLE) &= ~BIT(0); - /* clear interrupt enable for UART0 */ - MCHP_INT_DISABLE(MCHP_UART_GIRQ) = MCHP_UART_GIRQ_BIT(0); + /* clear interrupt enable for UART */ + MCHP_INT_DISABLE(MCHP_UART_GIRQ) = UART_IRQ_BIT; - /* Clear pending interrupts on GPIO_UART0_RX(GPIO105, girq=9, bit=5) */ - MCHP_INT_SOURCE(9) = BIT(5); + /* Clear pending interrupts on UART RX pin */ + MCHP_INT_SOURCE(UART_RX_PIN_GIRQ) = UART_RX_PIN_BIT; /* Enable GPIO interrupts on the UART0 RX pin. */ - gpio_enable_interrupt(GPIO_UART0_RX); + gpio_enable_interrupt(GPIO_UART_RX); } - void uart_exit_dsleep(void) { /* @@ -208,19 +243,19 @@ void uart_exit_dsleep(void) * because then the IRQ will not run at all. */ if (!(BIT(5) & MCHP_INT_SOURCE(9))) /* if edge interrupt */ - gpio_disable_interrupt(GPIO_UART0_RX); + gpio_disable_interrupt(GPIO_UART_RX); /* Configure UART0 pins for use in UART peripheral. */ gpio_config_module(MODULE_UART, 1); /* Clear pending interrupts on UART peripheral and enable interrupts. */ - uart_clear_rx_fifo(0); - MCHP_INT_SOURCE(MCHP_UART_GIRQ) = MCHP_UART_GIRQ_BIT(0); - MCHP_INT_ENABLE(MCHP_UART_GIRQ) = MCHP_UART_GIRQ_BIT(0); - task_enable_irq(MCHP_IRQ_UART0); /* NVIC interrupt for UART = 40 */ + uart_clear_rx_fifo(CONFIG_UART_CONSOLE); + MCHP_INT_SOURCE(MCHP_UART_GIRQ) = UART_IRQ_BIT; + MCHP_INT_ENABLE(MCHP_UART_GIRQ) = UART_IRQ_BIT; + task_enable_irq(UART_IRQ); /* power-up/activate UART0 */ - MCHP_UART_ACT(0) |= BIT(0); + MCHP_UART_ACT(CONFIG_UART_CONSOLE) |= BIT(0); } void uart_deepsleep_interrupt(enum gpio_signal signal) @@ -233,6 +268,6 @@ void uart_deepsleep_interrupt(enum gpio_signal signal) clock_refresh_console_in_use(); /* Disable interrupts on UART0 RX pin to avoid repeated interrupts. */ - gpio_disable_interrupt(GPIO_UART0_RX); + gpio_disable_interrupt(GPIO_UART_RX); } #endif /* CONFIG_LOW_POWER_IDLE */ diff --git a/chip/mchp/util/pack_ec.py b/chip/mchp/util/pack_ec.py index 4917deee5d..8991718cf9 100755 --- a/chip/mchp/util/pack_ec.py +++ b/chip/mchp/util/pack_ec.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2013 The Chromium OS Authors. All rights reserved. +# Copyright 2013 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -12,7 +12,8 @@ import struct import subprocess import tempfile -import zlib # CRC32 +import zlib # CRC32 + # MEC1701 has 256KB SRAM from 0xE0000 - 0x120000 # SRAM is divided into contiguous CODE & DATA @@ -26,165 +27,199 @@ LOAD_ADDR_RW = 0xE1000 HEADER_SIZE = 0x40 SPI_CLOCK_LIST = [48, 24, 16, 12] -SPI_READ_CMD_LIST = [0x3, 0xb, 0x3b, 0x6b] +SPI_READ_CMD_LIST = [0x3, 0xB, 0x3B, 0x6B] + +CRC_TABLE = [ + 0x00, + 0x07, + 0x0E, + 0x09, + 0x1C, + 0x1B, + 0x12, + 0x15, + 0x38, + 0x3F, + 0x36, + 0x31, + 0x24, + 0x23, + 0x2A, + 0x2D, +] -CRC_TABLE = [0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, - 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d] def mock_print(*args, **kwargs): - pass + pass + debug_print = mock_print + def Crc8(crc, data): - """Update CRC8 value.""" - for v in data: - crc = ((crc << 4) & 0xff) ^ (CRC_TABLE[(crc >> 4) ^ (v >> 4)]); - crc = ((crc << 4) & 0xff) ^ (CRC_TABLE[(crc >> 4) ^ (v & 0xf)]); - return crc ^ 0x55 + """Update CRC8 value.""" + for v in data: + crc = ((crc << 4) & 0xFF) ^ (CRC_TABLE[(crc >> 4) ^ (v >> 4)]) + crc = ((crc << 4) & 0xFF) ^ (CRC_TABLE[(crc >> 4) ^ (v & 0xF)]) + return crc ^ 0x55 + def GetEntryPoint(payload_file): - """Read entry point from payload EC image.""" - with open(payload_file, 'rb') as f: - f.seek(4) - s = f.read(4) - return struct.unpack('> 6) & 0xff) - header.append((payload_len >> 14) & 0xff) - PadZeroTo(header, 0x14) - # bytes 0x14 - 0x17 - header.extend(struct.pack('> 6) & 0xFF) + header.append((payload_len >> 14) & 0xFF) + PadZeroTo(header, 0x14) + # bytes 0x14 - 0x17 + header.extend(struct.pack("> 6) & 0xFF) + header.append((payload_len >> 14) & 0xFF) + PadZeroTo(header, 0x14) + # bytes 0x14 - 0x17 + header.extend(struct.pack("> 6) & 0xff) - header.append((payload_len >> 14) & 0xff) - PadZeroTo(header, 0x14) - # bytes 0x14 - 0x17 - header.extend(struct.pack('> 8) & 0xff, - (args.header_loc >> 16) & 0xff, - (args.header_loc >> 24) & 0xff]) - tag.append(Crc8(0, tag)) - return tag + tag = bytearray( + [ + (args.header_loc >> 8) & 0xFF, + (args.header_loc >> 16) & 0xFF, + (args.header_loc >> 24) & 0xFF, + ] + ) + tag.append(Crc8(0, tag)) + return tag + def BuildTagFromHdrAddr(header_loc): - tag = bytearray([(header_loc >> 8) & 0xff, - (header_loc >> 16) & 0xff, - (header_loc >> 24) & 0xff]) + tag = bytearray( + [ + (header_loc >> 8) & 0xFF, + (header_loc >> 16) & 0xFF, + (header_loc >> 24) & 0xFF, + ] + ) tag.append(Crc8(0, tag)) return tag @@ -220,20 +264,21 @@ def BuildTagFromHdrAddr(header_loc): # Returns temporary file name # def PacklfwRoImage(rorw_file, loader_file, image_size): - """Create a temp file with the - first image_size bytes from the loader file and append bytes - from the rorw file. - return the filename""" - fo=tempfile.NamedTemporaryFile(delete=False) # Need to keep file around - with open(loader_file,'rb') as fin1: # read 4KB loader file - pro = fin1.read() - fo.write(pro) # write 4KB loader data to temp file - with open(rorw_file, 'rb') as fin: - ro = fin.read(image_size) - - fo.write(ro) - fo.close() - return fo.name + """Create a temp file with the + first image_size bytes from the loader file and append bytes + from the rorw file. + return the filename""" + fo = tempfile.NamedTemporaryFile(delete=False) # Need to keep file around + with open(loader_file, "rb") as fin1: # read 4KB loader file + pro = fin1.read() + fo.write(pro) # write 4KB loader data to temp file + with open(rorw_file, "rb") as fin: + ro = fin.read(image_size) + + fo.write(ro) + fo.close() + return fo.name + # # Generate a test EC_RW image of same size @@ -244,105 +289,152 @@ def PacklfwRoImage(rorw_file, loader_file, image_size): # process hash generation. # def gen_test_ecrw(pldrw): - debug_print("gen_test_ecrw: pldrw type =", type(pldrw)) - debug_print("len pldrw =", len(pldrw), " = ", hex(len(pldrw))) - cookie1_pos = pldrw.find(b'\x99\x88\x77\xce') - cookie2_pos = pldrw.find(b'\xdd\xbb\xaa\xce', cookie1_pos+4) - t = struct.unpack(" 0 and cookie2_pos > cookie1_pos: - for i in range(0, cookie1_pos): - pldrw[i] = 0xA5 - for i in range(cookie2_pos+4, len(pldrw)): - pldrw[i] = 0xA5 - - with open("ec_RW_test.bin", "wb") as fecrw: - fecrw.write(pldrw[:size]) + debug_print("gen_test_ecrw: pldrw type =", type(pldrw)) + debug_print("len pldrw =", len(pldrw), " = ", hex(len(pldrw))) + cookie1_pos = pldrw.find(b"\x99\x88\x77\xce") + cookie2_pos = pldrw.find(b"\xdd\xbb\xaa\xce", cookie1_pos + 4) + t = struct.unpack(" 0 and cookie2_pos > cookie1_pos: + for i in range(0, cookie1_pos): + pldrw[i] = 0xA5 + for i in range(cookie2_pos + 4, len(pldrw)): + pldrw[i] = 0xA5 + + with open("ec_RW_test.bin", "wb") as fecrw: + fecrw.write(pldrw[:size]) + def parseargs(): - rpath = os.path.dirname(os.path.relpath(__file__)) - - parser = argparse.ArgumentParser() - parser.add_argument("-i", "--input", - help="EC binary to pack, usually ec.bin or ec.RO.flat.", - metavar="EC_BIN", default="ec.bin") - parser.add_argument("-o", "--output", - help="Output flash binary file", - metavar="EC_SPI_FLASH", default="ec.packed.bin") - parser.add_argument("--loader_file", - help="EC loader binary", - default="ecloader.bin") - parser.add_argument("-s", "--spi_size", type=int, - help="Size of the SPI flash in KB", - default=512) - parser.add_argument("-l", "--header_loc", type=int, - help="Location of header in SPI flash", - default=0x1000) - parser.add_argument("-p", "--payload_offset", type=int, - help="The offset of payload from the start of header", - default=0x80) - parser.add_argument("-r", "--rw_loc", type=int, - help="Start offset of EC_RW. Default is -1 meaning 1/2 flash size", - default=-1) - parser.add_argument("--spi_clock", type=int, - help="SPI clock speed. 8, 12, 24, or 48 MHz.", - default=24) - parser.add_argument("--spi_read_cmd", type=int, - help="SPI read command. 0x3, 0xB, or 0x3B.", - default=0xb) - parser.add_argument("--image_size", type=int, - help="Size of a single image. Default 220KB", - default=(220 * 1024)) - parser.add_argument("--test_spi", action='store_true', - help="Test SPI data integrity by adding CRC32 in last 4-bytes of RO/RW binaries", - default=False) - parser.add_argument("--test_ecrw", action='store_true', - help="Use fixed pattern for EC_RW but preserve image_data", - default=False) - parser.add_argument("--verbose", action='store_true', - help="Enable verbose output", - default=False) - - return parser.parse_args() + rpath = os.path.dirname(os.path.relpath(__file__)) + + parser = argparse.ArgumentParser() + parser.add_argument( + "-i", + "--input", + help="EC binary to pack, usually ec.bin or ec.RO.flat.", + metavar="EC_BIN", + default="ec.bin", + ) + parser.add_argument( + "-o", + "--output", + help="Output flash binary file", + metavar="EC_SPI_FLASH", + default="ec.packed.bin", + ) + parser.add_argument( + "--loader_file", help="EC loader binary", default="ecloader.bin" + ) + parser.add_argument( + "-s", + "--spi_size", + type=int, + help="Size of the SPI flash in KB", + default=512, + ) + parser.add_argument( + "-l", + "--header_loc", + type=int, + help="Location of header in SPI flash", + default=0x1000, + ) + parser.add_argument( + "-p", + "--payload_offset", + type=int, + help="The offset of payload from the start of header", + default=0x80, + ) + parser.add_argument( + "-r", + "--rw_loc", + type=int, + help="Start offset of EC_RW. Default is -1 meaning 1/2 flash size", + default=-1, + ) + parser.add_argument( + "--spi_clock", + type=int, + help="SPI clock speed. 8, 12, 24, or 48 MHz.", + default=24, + ) + parser.add_argument( + "--spi_read_cmd", + type=int, + help="SPI read command. 0x3, 0xB, or 0x3B.", + default=0xB, + ) + parser.add_argument( + "--image_size", + type=int, + help="Size of a single image. Default 220KB", + default=(220 * 1024), + ) + parser.add_argument( + "--test_spi", + action="store_true", + help="Test SPI data integrity by adding CRC32 in last 4-bytes of RO/RW binaries", + default=False, + ) + parser.add_argument( + "--test_ecrw", + action="store_true", + help="Use fixed pattern for EC_RW but preserve image_data", + default=False, + ) + parser.add_argument( + "--verbose", + action="store_true", + help="Enable verbose output", + default=False, + ) + + return parser.parse_args() + # Debug helper routine def dumpsects(spi_list): - debug_print("spi_list has {0} entries".format(len(spi_list))) - for s in spi_list: - debug_print("0x{0:x} 0x{1:x} {2:s}".format(s[0],len(s[1]),s[2])) + debug_print("spi_list has {0} entries".format(len(spi_list))) + for s in spi_list: + debug_print("0x{0:x} 0x{1:x} {2:s}".format(s[0], len(s[1]), s[2])) + def printByteArrayAsHex(ba, title): - debug_print(title,"= ") - count = 0 - for b in ba: - count = count + 1 - debug_print("0x{0:02x}, ".format(b),end="") - if (count % 8) == 0: - debug_print("") - debug_print("\n") + debug_print(title, "= ") + count = 0 + for b in ba: + count = count + 1 + debug_print("0x{0:02x}, ".format(b), end="") + if (count % 8) == 0: + debug_print("") + debug_print("\n") + def print_args(args): - debug_print("parsed arguments:") - debug_print(".input = ", args.input) - debug_print(".output = ", args.output) - debug_print(".loader_file = ", args.loader_file) - debug_print(".spi_size (KB) = ", hex(args.spi_size)) - debug_print(".image_size = ", hex(args.image_size)) - debug_print(".header_loc = ", hex(args.header_loc)) - debug_print(".payload_offset = ", hex(args.payload_offset)) - if args.rw_loc < 0: - debug_print(".rw_loc = ", args.rw_loc) - else: - debug_print(".rw_loc = ", hex(args.rw_loc)) - debug_print(".spi_clock = ", args.spi_clock) - debug_print(".spi_read_cmd = ", args.spi_read_cmd) - debug_print(".test_spi = ", args.test_spi) - debug_print(".verbose = ", args.verbose) + debug_print("parsed arguments:") + debug_print(".input = ", args.input) + debug_print(".output = ", args.output) + debug_print(".loader_file = ", args.loader_file) + debug_print(".spi_size (KB) = ", hex(args.spi_size)) + debug_print(".image_size = ", hex(args.image_size)) + debug_print(".header_loc = ", hex(args.header_loc)) + debug_print(".payload_offset = ", hex(args.payload_offset)) + if args.rw_loc < 0: + debug_print(".rw_loc = ", args.rw_loc) + else: + debug_print(".rw_loc = ", hex(args.rw_loc)) + debug_print(".spi_clock = ", args.spi_clock) + debug_print(".spi_read_cmd = ", args.spi_read_cmd) + debug_print(".test_spi = ", args.test_spi) + debug_print(".verbose = ", args.verbose) + # # Handle quiet mode build from Makefile @@ -350,183 +442,206 @@ def print_args(args): # Verbose mode when V=1 # def main(): - global debug_print - - args = parseargs() - - if args.verbose: - debug_print = print - - debug_print("Begin MEC17xx pack_ec.py script") - - - # MEC17xx maximum 192KB each for RO & RW - # mec1701 chip Makefile sets args.spi_size = 512 - # Tags at offset 0 - # - print_args(args) - - spi_size = args.spi_size * 1024 - debug_print("SPI Flash image size in bytes =", hex(spi_size)) - - # !!! IMPORTANT !!! - # These values MUST match chip/mec1701/config_flash_layout.h - # defines. - # MEC17xx Boot-ROM TAGs are at offset 0 and 4. - # lfw + EC_RO starts at beginning of second 4KB sector - # EC_RW starts at offset 0x40000 (256KB) - - spi_list = [] - - debug_print("args.input = ",args.input) - debug_print("args.loader_file = ",args.loader_file) - debug_print("args.image_size = ",hex(args.image_size)) - - rorofile=PacklfwRoImage(args.input, args.loader_file, args.image_size) - - payload = GetPayload(rorofile) - payload_len = len(payload) - # debug - debug_print("EC_LFW + EC_RO length = ",hex(payload_len)) - - # SPI image integrity test - # compute CRC32 of EC_RO except for last 4 bytes - # skip over 4KB LFW - # Store CRC32 in last 4 bytes - if args.test_spi == True: - crc = zlib.crc32(bytes(payload[LFW_SIZE:(payload_len - 4)])) - crc_ofs = payload_len - 4 - debug_print("EC_RO CRC32 = 0x{0:08x} @ 0x{1:08x}".format(crc, crc_ofs)) - for i in range(4): - payload[crc_ofs + i] = crc & 0xff - crc = crc >> 8 - - # Chromebooks are not using MEC BootROM ECDSA. - # We implemented the ECDSA disabled case where - # the 64-byte signature contains a SHA-256 of the binary plus - # 32 zeros bytes. - payload_signature = SignByteArray(payload) - # debug - printByteArrayAsHex(payload_signature, "LFW + EC_RO payload_signature") - - # MEC17xx Header is 0x80 bytes with an 64 byte signature - # (32 byte SHA256 + 32 zero bytes) - header = BuildHeader(args, payload_len, LOAD_ADDR, rorofile) - # debug - printByteArrayAsHex(header, "Header LFW + EC_RO") - - # MEC17xx payload ECDSA not used, 64 byte signature is - # SHA256 + 32 zero bytes - header_signature = SignByteArray(header) - # debug - printByteArrayAsHex(header_signature, "header_signature") - - tag = BuildTag(args) - # MEC17xx truncate RW length to args.image_size to not overwrite LFW - # offset may be different due to Header size and other changes - # MCHP we want to append a SHA-256 to the end of the actual payload - # to test SPI read routines. - debug_print("Call to GetPayloadFromOffset") - debug_print("args.input = ", args.input) - debug_print("args.image_size = ", hex(args.image_size)) - - payload_rw = GetPayloadFromOffset(args.input, args.image_size) - debug_print("type(payload_rw) is ", type(payload_rw)) - debug_print("len(payload_rw) is ", hex(len(payload_rw))) - - # truncate to args.image_size - rw_len = args.image_size - payload_rw = payload_rw[:rw_len] - payload_rw_len = len(payload_rw) - debug_print("Truncated size of EC_RW = ", hex(payload_rw_len)) - - payload_entry_tuple = struct.unpack_from('> 8 - - payload_rw_sig = SignByteArray(payload_rw) - # debug - printByteArrayAsHex(payload_rw_sig, "payload_rw_sig") - - os.remove(rorofile) # clean up the temp file - - # MEC170x Boot-ROM Tags are located at SPI offset 0 - spi_list.append((0, tag, "tag")) - - spi_list.append((args.header_loc, header, "header(lwf + ro)")) - spi_list.append((args.header_loc + HEADER_SIZE, header_signature, - "header(lwf + ro) signature")) - spi_list.append((args.header_loc + args.payload_offset, payload, - "payload(lfw + ro)")) - - offset = args.header_loc + args.payload_offset + payload_len - - # No SPI Header for EC_RW as its not loaded by BootROM - spi_list.append((offset, payload_signature, - "payload(lfw_ro) signature")) - - # EC_RW location - rw_offset = int(spi_size // 2) - if args.rw_loc >= 0: - rw_offset = args.rw_loc - - debug_print("rw_offset = 0x{0:08x}".format(rw_offset)) - - if rw_offset < offset + len(payload_signature): - print("ERROR: EC_RW overlaps EC_RO") - - spi_list.append((rw_offset, payload_rw, "payload(rw)")) - - # don't add to EC_RW. We don't know if Google will process - # EC SPI flash binary with other tools during build of - # coreboot and OS. - #offset = rw_offset + payload_rw_len - #spi_list.append((offset, payload_rw_sig, "payload(rw) signature")) - - spi_list = sorted(spi_list) - - dumpsects(spi_list) - - # - # MEC17xx Boot-ROM locates TAG at SPI offset 0 instead of end of SPI. - # - with open(args.output, 'wb') as f: - debug_print("Write spi list to file", args.output) - addr = 0 - for s in spi_list: - if addr < s[0]: - debug_print("Offset ",hex(addr)," Length", hex(s[0]-addr), - "fill with 0xff") - f.write(b'\xff' * (s[0] - addr)) - addr = s[0] - debug_print("Offset ",hex(addr), " Length", hex(len(s[1])), "write data") - - f.write(s[1]) - addr += len(s[1]) - - if addr < spi_size: - debug_print("Offset ",hex(addr), " Length", hex(spi_size - addr), - "fill with 0xff") - f.write(b'\xff' * (spi_size - addr)) - - f.flush() - -if __name__ == '__main__': - main() + global debug_print + + args = parseargs() + + if args.verbose: + debug_print = print + + debug_print("Begin MEC17xx pack_ec.py script") + + # MEC17xx maximum 192KB each for RO & RW + # mec1701 chip Makefile sets args.spi_size = 512 + # Tags at offset 0 + # + print_args(args) + + spi_size = args.spi_size * 1024 + debug_print("SPI Flash image size in bytes =", hex(spi_size)) + + # !!! IMPORTANT !!! + # These values MUST match chip/mec1701/config_flash_layout.h + # defines. + # MEC17xx Boot-ROM TAGs are at offset 0 and 4. + # lfw + EC_RO starts at beginning of second 4KB sector + # EC_RW starts at offset 0x40000 (256KB) + + spi_list = [] + + debug_print("args.input = ", args.input) + debug_print("args.loader_file = ", args.loader_file) + debug_print("args.image_size = ", hex(args.image_size)) + + rorofile = PacklfwRoImage(args.input, args.loader_file, args.image_size) + + payload = GetPayload(rorofile) + payload_len = len(payload) + # debug + debug_print("EC_LFW + EC_RO length = ", hex(payload_len)) + + # SPI image integrity test + # compute CRC32 of EC_RO except for last 4 bytes + # skip over 4KB LFW + # Store CRC32 in last 4 bytes + if args.test_spi == True: + crc = zlib.crc32(bytes(payload[LFW_SIZE : (payload_len - 4)])) + crc_ofs = payload_len - 4 + debug_print("EC_RO CRC32 = 0x{0:08x} @ 0x{1:08x}".format(crc, crc_ofs)) + for i in range(4): + payload[crc_ofs + i] = crc & 0xFF + crc = crc >> 8 + + # Chromebooks are not using MEC BootROM ECDSA. + # We implemented the ECDSA disabled case where + # the 64-byte signature contains a SHA-256 of the binary plus + # 32 zeros bytes. + payload_signature = SignByteArray(payload) + # debug + printByteArrayAsHex(payload_signature, "LFW + EC_RO payload_signature") + + # MEC17xx Header is 0x80 bytes with an 64 byte signature + # (32 byte SHA256 + 32 zero bytes) + header = BuildHeader(args, payload_len, LOAD_ADDR, rorofile) + # debug + printByteArrayAsHex(header, "Header LFW + EC_RO") + + # MEC17xx payload ECDSA not used, 64 byte signature is + # SHA256 + 32 zero bytes + header_signature = SignByteArray(header) + # debug + printByteArrayAsHex(header_signature, "header_signature") + + tag = BuildTag(args) + # MEC17xx truncate RW length to args.image_size to not overwrite LFW + # offset may be different due to Header size and other changes + # MCHP we want to append a SHA-256 to the end of the actual payload + # to test SPI read routines. + debug_print("Call to GetPayloadFromOffset") + debug_print("args.input = ", args.input) + debug_print("args.image_size = ", hex(args.image_size)) + + payload_rw = GetPayloadFromOffset(args.input, args.image_size) + debug_print("type(payload_rw) is ", type(payload_rw)) + debug_print("len(payload_rw) is ", hex(len(payload_rw))) + + # truncate to args.image_size + rw_len = args.image_size + payload_rw = payload_rw[:rw_len] + payload_rw_len = len(payload_rw) + debug_print("Truncated size of EC_RW = ", hex(payload_rw_len)) + + payload_entry_tuple = struct.unpack_from("> 8 + + payload_rw_sig = SignByteArray(payload_rw) + # debug + printByteArrayAsHex(payload_rw_sig, "payload_rw_sig") + + os.remove(rorofile) # clean up the temp file + + # MEC170x Boot-ROM Tags are located at SPI offset 0 + spi_list.append((0, tag, "tag")) + + spi_list.append((args.header_loc, header, "header(lwf + ro)")) + spi_list.append( + ( + args.header_loc + HEADER_SIZE, + header_signature, + "header(lwf + ro) signature", + ) + ) + spi_list.append( + (args.header_loc + args.payload_offset, payload, "payload(lfw + ro)") + ) + + offset = args.header_loc + args.payload_offset + payload_len + + # No SPI Header for EC_RW as its not loaded by BootROM + spi_list.append((offset, payload_signature, "payload(lfw_ro) signature")) + + # EC_RW location + rw_offset = int(spi_size // 2) + if args.rw_loc >= 0: + rw_offset = args.rw_loc + + debug_print("rw_offset = 0x{0:08x}".format(rw_offset)) + + if rw_offset < offset + len(payload_signature): + print("ERROR: EC_RW overlaps EC_RO") + + spi_list.append((rw_offset, payload_rw, "payload(rw)")) + + # don't add to EC_RW. We don't know if Google will process + # EC SPI flash binary with other tools during build of + # coreboot and OS. + # offset = rw_offset + payload_rw_len + # spi_list.append((offset, payload_rw_sig, "payload(rw) signature")) + + spi_list = sorted(spi_list) + + dumpsects(spi_list) + + # + # MEC17xx Boot-ROM locates TAG at SPI offset 0 instead of end of SPI. + # + with open(args.output, "wb") as f: + debug_print("Write spi list to file", args.output) + addr = 0 + for s in spi_list: + if addr < s[0]: + debug_print( + "Offset ", + hex(addr), + " Length", + hex(s[0] - addr), + "fill with 0xff", + ) + f.write(b"\xff" * (s[0] - addr)) + addr = s[0] + debug_print( + "Offset ", + hex(addr), + " Length", + hex(len(s[1])), + "write data", + ) + + f.write(s[1]) + addr += len(s[1]) + + if addr < spi_size: + debug_print( + "Offset ", + hex(addr), + " Length", + hex(spi_size - addr), + "fill with 0xff", + ) + f.write(b"\xff" * (spi_size - addr)) + + f.flush() + + +if __name__ == "__main__": + main() diff --git a/chip/mchp/util/pack_ec_mec152x.py b/chip/mchp/util/pack_ec_mec152x.py new file mode 100755 index 0000000000..43721b3336 --- /dev/null +++ b/chip/mchp/util/pack_ec_mec152x.py @@ -0,0 +1,941 @@ +#!/usr/bin/env python3 + +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# A script to pack EC binary into SPI flash image for MEC152x +# Based on MEC1521/MEC1523_ROM_Description.pdf +import argparse +import hashlib +import os +import struct +import subprocess +import tempfile +import zlib # CRC32 + + +# MEC152xH has 256KB SRAM from 0xE0000 - 0x120000 +# SRAM is divided into contiguous CODE & DATA +# CODE at [0xE0000, 0x117FFF] DATA at [0x118000, 0x11FFFF] +# SPI flash size for board is 512KB +# Boot-ROM TAG is located at SPI offset 0 (two 4-byte tags) + +LFW_SIZE = 0x1000 +LOAD_ADDR = 0x0E0000 +LOAD_ADDR_RW = 0xE1000 +MEC152X_HEADER_SIZE = 0x140 +MEC152X_HEADER_VERSION = 0x02 +PAYLOAD_PAD_BYTE = b"\xff" +SPI_ERASE_BLOCK_SIZE = 0x1000 +SPI_CLOCK_LIST = [48, 24, 16, 12] +SPI_READ_CMD_LIST = [0x3, 0xB, 0x3B, 0x6B] +SPI_DRIVE_STR_DICT = {2: 0, 4: 1, 8: 2, 12: 3} +CHIP_MAX_CODE_SRAM_KB = 224 + +MEC152X_DICT = { + "HEADER_SIZE": 0x140, + "HEADER_VER": 0x02, + "PAYLOAD_OFFSET": 0x140, + "PAYLOAD_GRANULARITY": 128, + "EC_INFO_BLK_SZ": 128, + "ENCR_KEY_HDR_SZ": 128, + "COSIG_SZ": 96, + "TRAILER_SZ": 160, + "TAILER_PAD_BYTE": b"\xff", + "PAD_SIZE": 128, +} + +CRC_TABLE = [ + 0x00, + 0x07, + 0x0E, + 0x09, + 0x1C, + 0x1B, + 0x12, + 0x15, + 0x38, + 0x3F, + 0x36, + 0x31, + 0x24, + 0x23, + 0x2A, + 0x2D, +] + + +def mock_print(*args, **kwargs): + pass + + +debug_print = mock_print + +# Debug helper routine +def dumpsects(spi_list): + debug_print("spi_list has {0} entries".format(len(spi_list))) + for s in spi_list: + debug_print("0x{0:x} 0x{1:x} {2:s}".format(s[0], len(s[1]), s[2])) + + +def printByteArrayAsHex(ba, title): + debug_print(title, "= ") + if ba == None: + debug_print("None") + return + + count = 0 + for b in ba: + count = count + 1 + debug_print("0x{0:02x}, ".format(b), end="") + if (count % 8) == 0: + debug_print("") + debug_print("") + + +def Crc8(crc, data): + """Update CRC8 value.""" + for v in data: + crc = ((crc << 4) & 0xFF) ^ (CRC_TABLE[(crc >> 4) ^ (v >> 4)]) + crc = ((crc << 4) & 0xFF) ^ (CRC_TABLE[(crc >> 4) ^ (v & 0xF)]) + return crc ^ 0x55 + + +def GetEntryPoint(payload_file): + """Read entry point from payload EC image.""" + with open(payload_file, "rb") as f: + f.seek(4) + s = f.read(4) + return int.from_bytes(s, byteorder="little") + + +def GetPayloadFromOffset(payload_file, offset, padsize): + """Read payload and pad it to padsize.""" + with open(payload_file, "rb") as f: + f.seek(offset) + payload = bytearray(f.read()) + rem_len = len(payload) % padsize + debug_print( + "GetPayload: padsize={0:0x} len(payload)={1:0x} rem={2:0x}".format( + padsize, len(payload), rem_len + ) + ) + + if rem_len: + payload += PAYLOAD_PAD_BYTE * (padsize - rem_len) + debug_print( + "GetPayload: Added {0} padding bytes".format(padsize - rem_len) + ) + + return payload + + +def GetPayload(payload_file, padsize): + """Read payload and pad it to padsize""" + return GetPayloadFromOffset(payload_file, 0, padsize) + + +def GetPublicKey(pem_file): + """Extract public exponent and modulus from PEM file.""" + result = subprocess.run( + ["openssl", "rsa", "-in", pem_file, "-text", "-noout"], + stdout=subprocess.PIPE, + encoding="utf-8", + ) + modulus_raw = [] + in_modulus = False + for line in result.stdout.splitlines(): + if line.startswith("modulus"): + in_modulus = True + elif not line.startswith(" "): + in_modulus = False + elif in_modulus: + modulus_raw.extend(line.strip().strip(":").split(":")) + if line.startswith("publicExponent"): + exp = int(line.split(" ")[1], 10) + modulus_raw.reverse() + modulus = bytearray((int(x, 16) for x in modulus_raw[:256])) + return struct.pack(" header size. +# NOTE: If Authentication is enabled size includes +# the appended signature. +# MEC152x: +# header[0x18] = Authentication key select. Set to 0 for no Authentication. +# header[0x19:0x50] = 0 reserved. +# header[0x50:0x80] = ECDSA-384 public key x-coord. = 0 Auth. disabled +# header[0x80:0xB0] = ECDSA-384 public key y-coord. = 0 Auth. disabled +# header[0xB0:0xE0] = SHA-384 digest of header[0:0xB0] +# header[0xE0:0x110] = Header ECDSA-384 signature x-coord. = 0 Auth. disabled +# header[0x110:0x140] = Header ECDSA-384 signature y-coor. = 0 Auth. disabled +# +def BuildHeader2(args, chip_dict, payload_len, load_addr, payload_entry): + header_size = MEC152X_HEADER_SIZE + + # allocate zero filled header + header = bytearray(b"\x00" * header_size) + debug_print("len(header) = ", len(header)) + + # Identifier and header version + header[0:4] = b"PHCM" + header[4] = MEC152X_HEADER_VERSION + + # SPI frequency, drive strength, CPOL/CPHA encoding same for both chips + spiFreqMHz = GetSpiClockParameter(args) + header[5] = (int(spiFreqMHz // 48) - 1) & 0x03 + header[5] |= (GetEncodedSpiDriveStrength(args) & 0x03) << 2 + header[5] |= (GetSpiSlewRate(args) & 0x01) << 4 + header[5] |= (GetSpiCpol(args) & 0x01) << 5 + header[5] |= (GetSpiCphaMosi(args) & 0x01) << 6 + header[5] |= (GetSpiCphaMiso(args) & 0x01) << 7 + + # b[0]=0 VTR1 must be 3.3V + # b[1]=0(VTR2 3.3V), 1(VTR2 1.8V) + # b[2]=0(VTR3 3.3V), 1(VTR3 1.8V) + # b[5:3]=111b + # b[6]=0 No ECDSA + # b[7]=0 No encrypted FW image + header[6] = 0x7 << 3 + if args.vtr2_V18 == True: + header[6] |= 0x02 + if args.vtr3_V18 == True: + header[6] |= 0x04 + + # SPI read command set same for both chips + header[7] = GetSpiReadCmdParameter(args) & 0xFF + + # bytes 0x08 - 0x0b + header[0x08:0x0C] = load_addr.to_bytes(4, byteorder="little") + # bytes 0x0c - 0x0f + header[0x0C:0x10] = payload_entry.to_bytes(4, byteorder="little") + # bytes 0x10 - 0x11 payload length in units of 128 bytes + + payload_units = int(payload_len // chip_dict["PAYLOAD_GRANULARITY"]) + assert payload_units < 0x10000, print( + "Payload too large: len={0} units={1}".format( + payload_len, payload_units + ) + ) + + header[0x10:0x12] = payload_units.to_bytes(2, "little") + + # bytes 0x14 - 0x17 + header[0x14:0x18] = chip_dict["PAYLOAD_OFFSET"].to_bytes(4, "little") + + # MEC152x: Disable ECDSA and encryption + header[0x18] = 0 + + # header[0xB0:0xE0] = SHA384(header[0:0xB0]) + header[0xB0:0xE0] = hashlib.sha384(header[0:0xB0]).digest() + # When ECDSA authentication is disabled MCHP SPI image generator + # is filling the last 48 bytes of the Header with 0xff + header[-48:] = b"\xff" * 48 + + debug_print("After hash: len(header) = ", len(header)) + + return header + + +# +# MEC152x 128-byte EC Info Block appended to +# end of padded FW binary +# bytes 0 through 103 are undefined, we set to 0xFF +# bytes 104 through 119 are rollback permissions +# bytes 120 through 123 are key revocation permissions +# byte 124 = customer platform ID[7:0] +# byte 125 = customer platform ID[15:8] +# byte 126 = customer auto rollback flags +# byte 127 = customer current image revision +# +def GenEcInfoBlock(args, chip_dict): + ecinfo = bytearray(chip_dict["EC_INFO_BLK_SZ"]) + return ecinfo + + +# +# Generate SPI FW image co-signature. +# MEC152X cosignature is 96 bytes used by OEM FW +# developer to sign their binary with ECDSA-P384-SHA384 or +# some other signature algorithm that fits in 96 bytes. +# At this time Cros-EC is not using this field, fill with 0xFF. +# If this feature is implemented we need to read the OEM's +# generated signature from a file and extract the binary +# signature. +# +def GenCoSignature(args, chip_dict, payload): + return bytearray(b"\xff" * chip_dict["COSIG_SZ"]) + + +# +# Generate SPI FW Image trailer. +# MEC152X: Size = 160 bytes +# binary = payload || encryption_key_header || ec_info_block || cosignature +# trailer[0:48] = SHA384(binary) +# trailer[48:144] = 0xFF +# trailer[144:160] = 0xFF. Boot-ROM spec. says these bytes should be random. +# Authentication & encryption are not used therefore random data +# is not necessary. +def GenTrailer( + args, chip_dict, payload, encryption_key_header, ec_info_block, cosignature +): + trailer = bytearray(chip_dict["TAILER_PAD_BYTE"] * chip_dict["TRAILER_SZ"]) + hasher = hashlib.sha384() + hasher.update(payload) + if ec_info_block != None: + hasher.update(ec_info_block) + if encryption_key_header != None: + hasher.update(encryption_key_header) + if cosignature != None: + hasher.update(cosignature) + trailer[0:48] = hasher.digest() + trailer[-16:] = 16 * b"\xff" + + return trailer + + +# MEC152xH supports two 32-bit Tags located at offsets 0x0 and 0x4 +# in the SPI flash. +# Tag format: +# bits[23:0] correspond to bits[31:8] of the Header SPI address +# Header is always on a 256-byte boundary. +# bits[31:24] = CRC8-ITU of bits[23:0]. +# Notice there is no chip-select field in the Tag both Tag's point +# to the same flash part. +# +def BuildTag(args): + tag = bytearray( + [ + (args.header_loc >> 8) & 0xFF, + (args.header_loc >> 16) & 0xFF, + (args.header_loc >> 24) & 0xFF, + ] + ) + tag.append(Crc8(0, tag)) + return tag + + +def BuildTagFromHdrAddr(header_loc): + tag = bytearray( + [ + (header_loc >> 8) & 0xFF, + (header_loc >> 16) & 0xFF, + (header_loc >> 24) & 0xFF, + ] + ) + tag.append(Crc8(0, tag)) + return tag + + +# FlashMap is an option for MEC152x +# It is a 32 bit structure +# bits[18:0] = bits[30:12] of second SPI flash base address +# bits[23:19] = 0 reserved +# bits[31:24] = CRC8 of bits[23:0] +# Input: +# integer containing base address of second SPI flash +# This value is usually equal to the size of the first +# SPI flash and should be a multiple of 4KB +# Output: +# bytearray of length 4 +def BuildFlashMap(secondSpiFlashBaseAddr): + flashmap = bytearray(4) + flashmap[0] = (secondSpiFlashBaseAddr >> 12) & 0xFF + flashmap[1] = (secondSpiFlashBaseAddr >> 20) & 0xFF + flashmap[2] = (secondSpiFlashBaseAddr >> 28) & 0xFF + flashmap[3] = Crc8(0, flashmap) + return flashmap + + +# +# Creates temporary file for read/write +# Reads binary file containing LFW image_size (loader_file) +# Writes LFW image to temporary file +# Reads RO image at beginning of rorw_file up to image_size +# (assumes RO/RW images have been padded with 0xFF +# Returns temporary file name +# +def PacklfwRoImage(rorw_file, loader_file, image_size): + """Create a temp file with the + first image_size bytes from the loader file and append bytes + from the rorw file. + return the filename""" + fo = tempfile.NamedTemporaryFile(delete=False) # Need to keep file around + with open(loader_file, "rb") as fin1: # read 4KB loader file + pro = fin1.read() + fo.write(pro) # write 4KB loader data to temp file + with open(rorw_file, "rb") as fin: + ro = fin.read(image_size) + + fo.write(ro) + fo.close() + + return fo.name + + +# +# Generate a test EC_RW image of same size +# as original. +# Preserve image_data structure and fill all +# other bytes with 0xA5. +# useful for testing SPI read and EC build +# process hash generation. +# +def gen_test_ecrw(pldrw): + debug_print("gen_test_ecrw: pldrw type =", type(pldrw)) + debug_print("len pldrw =", len(pldrw), " = ", hex(len(pldrw))) + cookie1_pos = pldrw.find(b"\x99\x88\x77\xce") + cookie2_pos = pldrw.find(b"\xdd\xbb\xaa\xce", cookie1_pos + 4) + t = struct.unpack(" 0 and cookie2_pos > cookie1_pos: + for i in range(0, cookie1_pos): + pldrw[i] = 0xA5 + for i in range(cookie2_pos + 4, len(pldrw)): + pldrw[i] = 0xA5 + + with open("ec_RW_test.bin", "wb") as fecrw: + fecrw.write(pldrw[:size]) + + +def parseargs(): + parser = argparse.ArgumentParser() + parser.add_argument( + "-i", + "--input", + help="EC binary to pack, usually ec.bin or ec.RO.flat.", + metavar="EC_BIN", + default="ec.bin", + ) + parser.add_argument( + "-o", + "--output", + help="Output flash binary file", + metavar="EC_SPI_FLASH", + default="ec.packed.bin", + ) + parser.add_argument( + "--loader_file", help="EC loader binary", default="ecloader.bin" + ) + parser.add_argument( + "-s", + "--spi_size", + type=int, + help="Size of the SPI flash in KB", + default=512, + ) + parser.add_argument( + "-l", + "--header_loc", + type=int, + help="Location of header in SPI flash", + default=0x1000, + ) + parser.add_argument( + "-r", + "--rw_loc", + type=int, + help="Start offset of EC_RW. Default is -1 meaning 1/2 flash size", + default=-1, + ) + parser.add_argument( + "--spi_clock", + type=int, + help="SPI clock speed. 8, 12, 24, or 48 MHz.", + default=24, + ) + parser.add_argument( + "--spi_read_cmd", + type=int, + help="SPI read command. 0x3, 0xB, or 0x3B.", + default=0xB, + ) + parser.add_argument( + "--image_size", + type=int, + help="Size of a single image. Default 220KB", + default=(220 * 1024), + ) + parser.add_argument( + "--test_spi", + action="store_true", + help="Test SPI data integrity by adding CRC32 in last 4-bytes of RO/RW binaries", + default=False, + ) + parser.add_argument( + "--test_ecrw", + action="store_true", + help="Use fixed pattern for EC_RW but preserve image_data", + default=False, + ) + parser.add_argument( + "--verbose", + action="store_true", + help="Enable verbose output", + default=False, + ) + parser.add_argument( + "--tag0_loc", type=int, help="MEC152X TAG0 SPI offset", default=0 + ) + parser.add_argument( + "--tag1_loc", type=int, help="MEC152X TAG1 SPI offset", default=4 + ) + parser.add_argument( + "--spi_drive_str", + type=int, + help="Chip SPI drive strength in mA: 2, 4, 8, or 12", + default=4, + ) + parser.add_argument( + "--spi_slew_fast", + action="store_true", + help="SPI use fast slew rate. Default is False", + default=False, + ) + parser.add_argument( + "--spi_cpol", + type=int, + help="SPI clock polarity when idle. Defealt is 0(low)", + default=0, + ) + parser.add_argument( + "--spi_cpha_mosi", + type=int, + help="""SPI clock phase master drives data. + 0=Data driven on active to inactive clock edge, + 1=Data driven on inactive to active clock edge""", + default=0, + ) + parser.add_argument( + "--spi_cpha_miso", + type=int, + help="""SPI clock phase master samples data. + 0=Data sampled on inactive to active clock edge, + 1=Data sampled on active to inactive clock edge""", + default=0, + ) + + parser.add_argument( + "--vtr2_V18", + action="store_true", + help="Chip VTR2 rail is 1.8V. Default is False(3.3V)", + default=False, + ) + + parser.add_argument( + "--vtr3_V18", + action="store_true", + help="Chip VTR3 rail is 1.8V. Default is False(3.3V)", + default=False, + ) + + return parser.parse_args() + + +def print_args(args): + debug_print("parsed arguments:") + debug_print(".input = ", args.input) + debug_print(".output = ", args.output) + debug_print(".loader_file = ", args.loader_file) + debug_print(".spi_size (KB) = ", hex(args.spi_size)) + debug_print(".image_size = ", hex(args.image_size)) + debug_print(".tag0_loc = ", hex(args.tag0_loc)) + debug_print(".tag1_loc = ", hex(args.tag1_loc)) + debug_print(".header_loc = ", hex(args.header_loc)) + if args.rw_loc < 0: + debug_print(".rw_loc = ", args.rw_loc) + else: + debug_print(".rw_loc = ", hex(args.rw_loc)) + debug_print(".spi_clock (MHz) = ", args.spi_clock) + debug_print(".spi_read_cmd = ", hex(args.spi_read_cmd)) + debug_print(".test_spi = ", args.test_spi) + debug_print(".test_ecrw = ", args.test_ecrw) + debug_print(".verbose = ", args.verbose) + debug_print(".spi_drive_str = ", args.spi_drive_str) + debug_print(".spi_slew_fast = ", args.spi_slew_fast) + debug_print(".spi_cpol = ", args.spi_cpol) + debug_print(".spi_cpha_mosi = ", args.spi_cpha_mosi) + debug_print(".spi_cpha_miso = ", args.spi_cpha_miso) + debug_print(".vtr2_V18 = ", args.vtr2_V18) + debug_print(".vtr3_V18 = ", args.vtr3_V18) + + +# +# Handle quiet mode build from Makefile +# Quiet mode when V is unset or V=0 +# Verbose mode when V=1 +# +# MEC152x SPI Image Generator +# No authentication +# No payload encryption +# +# SPI Offset 0x0 = TAG0 points to Header for EC-RO FW +# SPI Offset 0x4 = TAG1 points to Header for EC-RO FW +# TAG Size = 4 bytes +# bits[23:0] = bits[31:8] of Header SPI offset +# bits[31:24] = CRC8-ITU checksum of bits[23:0]. +# +# MEC152X SPI header and payload layout for minimum size +# header offset aligned on 256 byte boundary +# header_spi_address: +# header[0:0x4F] = Header data +# header[0x50:0x80] = ECDSA-P384 public key x for Header authentication +# header[0x80:0xB0] = ECDSA-P384 public key y for Header authentication +# header[0xB0:0xE0] = SHA384 digest of header[0:0xB0] +# header[0xE0:0x110] = ECDSA-P384-SHA384 Signature.R of header[0:0xB0] +# header[0x110:0x140] = ECDSA-P384-SHA384 Signature.S of header[0:0xB0] +# payload_spi_address = header_spi_address + len(Header) +# Payload had been padded such that len(padded_payload) % 128 == 0 +# padded_payload[padded_payload_len] +# payload_signature_address = payload_spi_address + len(padded_payload) +# payload_encryption_key_header[128] Not present if encryption disabled +# payload_cosignature[96] = 0 if Authentication is disabled +# payload_trailer[160] = SHA384(padded_payload || +# optional payload_encryption_key_header) +# || 48 * [0] +# || 48 * [0] +# +def main(): + global debug_print + + args = parseargs() + + if args.verbose: + debug_print = print + + debug_print("Begin pack_ec_mec152x.py script") + + print_args(args) + + chip_dict = MEC152X_DICT + + # Boot-ROM requires header location aligned >= 256 bytes. + # CrOS EC flash image update code requires EC_RO/RW location to be aligned + # on a flash erase size boundary and EC_RO/RW size to be a multiple of + # the smallest flash erase block size. + # + assert (args.header_loc % SPI_ERASE_BLOCK_SIZE) == 0, ( + "Header location %d is not on a flash erase block boundary boundary" + % args.header_loc + ) + + max_image_size = CHIP_MAX_CODE_SRAM_KB - LFW_SIZE + if args.test_spi: + max_image_size -= 32 # SHA256 digest + + assert args.image_size > max_image_size, ( + "Image size exceeds maximum" % args.image_size + ) + + spi_size = args.spi_size * 1024 + debug_print("SPI Flash image size in bytes =", hex(spi_size)) + + # !!! IMPORTANT !!! + # These values MUST match chip/mchp/config_flash_layout.h + # defines. + # MEC152x Boot-ROM TAGs are at offset 0 and 4. + # lfw + EC_RO starts at beginning of second 4KB sector + # EC_RW starts at (flash size / 2) i.e. 0x40000 for a 512KB flash. + + spi_list = [] + + debug_print("args.input = ", args.input) + debug_print("args.loader_file = ", args.loader_file) + debug_print("args.image_size = ", hex(args.image_size)) + + rorofile = PacklfwRoImage(args.input, args.loader_file, args.image_size) + debug_print("Temporary file containing LFW + EC_RO is ", rorofile) + + lfw_ecro = GetPayload(rorofile, chip_dict["PAD_SIZE"]) + lfw_ecro_len = len(lfw_ecro) + debug_print("Padded LFW + EC_RO length = ", hex(lfw_ecro_len)) + + # SPI test mode compute CRC32 of EC_RO and store in last 4 bytes + if args.test_spi: + crc32_ecro = zlib.crc32(bytes(lfw_ecro[LFW_SIZE:-4])) + crc32_ecro_bytes = crc32_ecro.to_bytes(4, byteorder="little") + lfw_ecro[-4:] = crc32_ecro_bytes + debug_print("ecro len = ", hex(len(lfw_ecro) - LFW_SIZE)) + debug_print("CRC32(ecro-4) = ", hex(crc32_ecro)) + + # Reads entry point from offset 4 of file. + # This assumes binary has Cortex-M4 vector table at offset 0. + # 32-bit word at offset 0x0 initial stack pointer value + # 32-bit word at offset 0x4 address of reset handler + # NOTE: reset address will have bit[0]=1 to ensure thumb mode. + lfw_ecro_entry = GetEntryPoint(rorofile) + + # Chromebooks are not using MEC BootROM SPI header/payload authentication + # or payload encryption. In this case the header authentication signature + # is filled with the hash digest of the respective entity. + # BuildHeader2 computes the hash digest and stores it in the correct + # header location. + header = BuildHeader2( + args, chip_dict, lfw_ecro_len, LOAD_ADDR, lfw_ecro_entry + ) + printByteArrayAsHex(header, "Header(lfw_ecro)") + + ec_info_block = GenEcInfoBlock(args, chip_dict) + printByteArrayAsHex(ec_info_block, "EC Info Block") + + cosignature = GenCoSignature(args, chip_dict, lfw_ecro) + printByteArrayAsHex(cosignature, "LFW + EC_RO cosignature") + + trailer = GenTrailer( + args, chip_dict, lfw_ecro, None, ec_info_block, cosignature + ) + + printByteArrayAsHex(trailer, "LFW + EC_RO trailer") + + # Build TAG0. Set TAG1=TAG0 Boot-ROM is allowed to load EC-RO only. + tag0 = BuildTag(args) + tag1 = tag0 + + debug_print("Call to GetPayloadFromOffset") + debug_print("args.input = ", args.input) + debug_print("args.image_size = ", hex(args.image_size)) + + ecrw = GetPayloadFromOffset( + args.input, args.image_size, chip_dict["PAD_SIZE"] + ) + debug_print("type(ecrw) is ", type(ecrw)) + debug_print("len(ecrw) is ", hex(len(ecrw))) + + # truncate to args.image_size + ecrw_len = len(ecrw) + if ecrw_len > args.image_size: + debug_print( + "Truncate EC_RW len={0:0x} to image_size={1:0x}".format( + ecrw_len, args.image_size + ) + ) + ecrw = ecrw[: args.image_size] + ecrw_len = len(ecrw) + + debug_print("len(EC_RW) = ", hex(ecrw_len)) + + # SPI test mode compute CRC32 of EC_RW and store in last 4 bytes + if args.test_spi: + crc32_ecrw = zlib.crc32(bytes(ecrw[0:-4])) + crc32_ecrw_bytes = crc32_ecrw.to_bytes(4, byteorder="little") + ecrw[-4:] = crc32_ecrw_bytes + debug_print("ecrw len = ", hex(len(ecrw))) + debug_print("CRC32(ecrw) = ", hex(crc32_ecrw)) + + # Assume FW layout is standard Cortex-M style with vector + # table at start of binary. + # 32-bit word at offset 0x0 = Initial stack pointer + # 32-bit word at offset 0x4 = Address of reset handler + ecrw_entry_tuple = struct.unpack_from("= 0: + rw_offset = args.rw_loc + + debug_print("rw_offset = 0x{0:08x}".format(rw_offset)) + + assert rw_offset >= offset, print( + """Offset of EC_RW at {0:08x} overlaps end + of EC_RO at {1:08x}""".format( + rw_offset, offset + ) + ) + + spi_list.append((rw_offset, ecrw, "ecrw")) + offset = rw_offset + len(ecrw) + + spi_list = sorted(spi_list) + + dumpsects(spi_list) + + # + # MEC152X Boot-ROM locates TAG0/1 at SPI offset 0 + # instead of end of SPI. + # + with open(args.output, "wb") as f: + debug_print("Write spi list to file", args.output) + addr = 0 + for s in spi_list: + if addr < s[0]: + debug_print( + "Offset ", + hex(addr), + " Length", + hex(s[0] - addr), + "fill with 0xff", + ) + f.write(b"\xff" * (s[0] - addr)) + addr = s[0] + debug_print( + "Offset ", + hex(addr), + " Length", + hex(len(s[1])), + "write data", + ) + + f.write(s[1]) + addr += len(s[1]) + + if addr < spi_size: + debug_print( + "Offset ", + hex(addr), + " Length", + hex(spi_size - addr), + "fill with 0xff", + ) + f.write(b"\xff" * (spi_size - addr)) + + f.flush() + + +if __name__ == "__main__": + main() diff --git a/chip/mchp/util/pack_ec_mec172x.py b/chip/mchp/util/pack_ec_mec172x.py new file mode 100755 index 0000000000..a8e867888c --- /dev/null +++ b/chip/mchp/util/pack_ec_mec172x.py @@ -0,0 +1,1001 @@ +#!/usr/bin/env python3 + +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# A script to pack EC binary into SPI flash image for MEC172x +# Based on MEC172x_ROM_Description.pdf revision 6/8/2020 +import argparse +import hashlib +import os +import struct +import subprocess +import tempfile +import zlib # CRC32 + + +# MEC172x has 416KB SRAM from 0xC0000 - 0x127FFF +# SRAM is divided into contiguous CODE & DATA +# CODE at [0xC0000, 0x117FFF] DATA at [0x118000, 0x127FFF] +# Google EC SPI flash size for board is currently 512KB +# split into 1/2. +# EC_RO: 0 - 0x3FFFF +# EC_RW: 0x40000 - 0x7FFFF +# +SPI_ERASE_BLOCK_SIZE = 0x1000 +SPI_CLOCK_LIST = [48, 24, 16, 12, 96] +SPI_READ_CMD_LIST = [0x3, 0xB, 0x3B, 0x6B] +SPI_DRIVE_STR_DICT = {2: 0, 4: 1, 8: 2, 12: 3} +# Maximum EC_RO/EC_RW code size is based upon SPI flash erase +# sector size, MEC172x Boot-ROM TAG, Header, Footer. +# SPI Offset Description +# 0x00 - 0x07 TAG0 and TAG1 +# 0x1000 - 0x113F Boot-ROM SPI Header +# 0x1140 - 0x213F 4KB LFW +# 0x2040 - 0x3EFFF +# 0x3F000 - 0x3FFFF BootROM EC_INFO_BLK || COSIG || ENCR_KEY_HDR(optional) || TRAILER +CHIP_MAX_CODE_SRAM_KB = 256 - 12 + +MEC172X_DICT = { + "LFW_SIZE": 0x1000, + "LOAD_ADDR": 0xC0000, + "TAG_SIZE": 4, + "KEY_BLOB_SIZE": 1584, + "HEADER_SIZE": 0x140, + "HEADER_VER": 0x03, + "PAYLOAD_GRANULARITY": 128, + "PAYLOAD_PAD_BYTE": b"\xff", + "EC_INFO_BLK_SZ": 128, + "ENCR_KEY_HDR_SZ": 128, + "COSIG_SZ": 96, + "TRAILER_SZ": 160, + "TAILER_PAD_BYTE": b"\xff", + "PAD_SIZE": 128, +} + +CRC_TABLE = [ + 0x00, + 0x07, + 0x0E, + 0x09, + 0x1C, + 0x1B, + 0x12, + 0x15, + 0x38, + 0x3F, + 0x36, + 0x31, + 0x24, + 0x23, + 0x2A, + 0x2D, +] + + +def mock_print(*args, **kwargs): + pass + + +debug_print = mock_print + +# Debug helper routine +def dumpsects(spi_list): + debug_print("spi_list has {0} entries".format(len(spi_list))) + for s in spi_list: + debug_print("0x{0:x} 0x{1:x} {2:s}".format(s[0], len(s[1]), s[2])) + + +def printByteArrayAsHex(ba, title): + debug_print(title, "= ") + if ba == None: + debug_print("None") + return + + count = 0 + for b in ba: + count = count + 1 + debug_print("0x{0:02x}, ".format(b), end="") + if (count % 8) == 0: + debug_print("") + debug_print("") + + +def Crc8(crc, data): + """Update CRC8 value.""" + for v in data: + crc = ((crc << 4) & 0xFF) ^ (CRC_TABLE[(crc >> 4) ^ (v >> 4)]) + crc = ((crc << 4) & 0xFF) ^ (CRC_TABLE[(crc >> 4) ^ (v & 0xF)]) + return crc ^ 0x55 + + +def GetEntryPoint(payload_file): + """Read entry point from payload EC image.""" + with open(payload_file, "rb") as f: + f.seek(4) + s = f.read(4) + return int.from_bytes(s, byteorder="little") + + +def GetPayloadFromOffset(payload_file, offset, chip_dict): + """Read payload and pad it to chip_dict["PAD_SIZE"].""" + padsize = chip_dict["PAD_SIZE"] + with open(payload_file, "rb") as f: + f.seek(offset) + payload = bytearray(f.read()) + rem_len = len(payload) % padsize + debug_print( + "GetPayload: padsize={0:0x} len(payload)={1:0x} rem={2:0x}".format( + padsize, len(payload), rem_len + ) + ) + + if rem_len: + payload += chip_dict["PAYLOAD_PAD_BYTE"] * (padsize - rem_len) + debug_print( + "GetPayload: Added {0} padding bytes".format(padsize - rem_len) + ) + + return payload + + +def GetPayload(payload_file, chip_dict): + """Read payload and pad it to chip_dict["PAD_SIZE"]""" + return GetPayloadFromOffset(payload_file, 0, chip_dict) + + +def GetPublicKey(pem_file): + """Extract public exponent and modulus from PEM file.""" + result = subprocess.run( + ["openssl", "rsa", "-in", pem_file, "-text", "-noout"], + stdout=subprocess.PIPE, + encoding="utf-8", + ) + modulus_raw = [] + in_modulus = False + for line in result.stdout.splitlines(): + if line.startswith("modulus"): + in_modulus = True + elif not line.startswith(" "): + in_modulus = False + elif in_modulus: + modulus_raw.extend(line.strip().strip(":").split(":")) + if line.startswith("publicExponent"): + exp = int(line.split(" ")[1], 10) + modulus_raw.reverse() + modulus = bytearray((int(x, 16) for x in modulus_raw[:256])) + return struct.pack(" 0x03 1-1-1 read freq < 33MHz +# 1 -> 0x0B 1-1-1 + 8 clocks(data tri-stated) +# 2 -> 0x3B 1-1-2 + 8 clocks(data tri-stated). Data phase is dual I/O +# 3 -> 0x6B 1-1-4 + 8 clocks(data tri-stated). Data phase is Quad I/O +# NOTE: Quad requires SPI flash device QE(quad enable) bit +# to be factory set. Enabling QE disables HOLD# and WP# +# functionality of the SPI flash device. +# header[0x8:0xC] SRAM Load address little-endian format +# header[0xC:0x10] SRAM FW entry point. Boot-ROM jumps to +# this address on successful load. (little-endian) +# header[0x10:0x12] little-endian format: FW binary size in units of +# 128 bytes(MEC172x) +# header[0x12:0x14] = 0 reserved +# header[0x14:0x18] = Little-ending format: Unsigned offset from start of +# header to FW payload. +# MEC172x: Offset must be a multiple of 128 +# Offset must be >= header size. +# NOTE: If Authentication is enabled size includes +# the appended signature. +# MEC172x: +# header[0x18] = Authentication key select. Set to 0 for no Authentication. +# header[0x19] = SPI flash device(s) drive strength feature flags +# b[0]=1 SPI flash device 0 has drive strength feature +# b[1]=SPI flash 0: DrvStr Write format(0=2 bytes, 1=1 byte) +# b[2]=1 SPI flash device 1 has drive strength feature +# b[3]=SPI flash 1: DrvStr Write format(0=2 bytes, 1=1 byte) +# b[7:4] = 0 reserved +# header[0x1A:0x20] = 0 reserved +# header[0x20] = SPI opcode to read drive strength from SPI flash 0 +# header[0x21] = SPI opcode to write drive strength to SPI flash 0 +# header[0x22] = SPI flash 0: drvStr value +# header[0x23] = SPI flash 0: drvStr mask +# header[0x24] = SPI opcode to read drive strength from SPI flash 1 +# header[0x25] = SPI opcode to write drive strength to SPI flash 1 +# header[0x26] = SPI flash 1: drvStr value +# header[0x27] = SPI flash 1: drvStr mask +# header[0x28:0x48] = reserved, may be any value +# header[0x48:0x50] = reserved for customer use +# header[0x50:0x80] = ECDSA-384 public key x-coord. = 0 Auth. disabled +# header[0x80:0xB0] = ECDSA-384 public key y-coord. = 0 Auth. disabled +# header[0xB0:0xE0] = SHA-384 digest of header[0:0xB0] +# header[0xE0:0x110] = Header ECDSA-384 signature x-coord. = 0 Auth. disabled +# header[0x110:0x140] = Header ECDSA-384 signature y-coor. = 0 Auth. disabled +# +def BuildHeader2(args, chip_dict, payload_len, load_addr, payload_entry): + header_size = chip_dict["HEADER_SIZE"] + + # allocate zero filled header + header = bytearray(b"\x00" * header_size) + debug_print("len(header) = ", len(header)) + + # Identifier and header version + header[0:4] = b"PHCM" + header[4] = chip_dict["HEADER_VER"] + + # SPI frequency, drive strength, CPOL/CPHA encoding same for both chips + spiFreqIndex = GetSpiClockParameter(args) + if spiFreqIndex > 3: + header[6] |= 0x01 + else: + header[5] = spiFreqIndex + + header[5] |= (GetEncodedSpiDriveStrength(args) & 0x03) << 2 + header[5] |= (GetSpiSlewRate(args) & 0x01) << 4 + header[5] |= (GetSpiCpol(args) & 0x01) << 5 + header[5] |= (GetSpiCphaMosi(args) & 0x01) << 6 + header[5] |= (GetSpiCphaMiso(args) & 0x01) << 7 + + # header[6] + # b[0] value set above + # b[2:1] = 00b, b[5:3]=111b + # b[7]=0 No encryption of FW payload + header[6] |= 0x7 << 3 + + # SPI read command set same for both chips + header[7] = GetSpiReadCmdParameter(args) & 0xFF + + # bytes 0x08 - 0x0b + header[0x08:0x0C] = load_addr.to_bytes(4, byteorder="little") + # bytes 0x0c - 0x0f + header[0x0C:0x10] = payload_entry.to_bytes(4, byteorder="little") + + # bytes 0x10 - 0x11 payload length in units of 128 bytes + assert payload_len % chip_dict["PAYLOAD_GRANULARITY"] == 0, print( + "Payload size not a multiple of {0}".format( + chip_dict["PAYLOAD_GRANULARITY"] + ) + ) + + payload_units = int(payload_len // chip_dict["PAYLOAD_GRANULARITY"]) + assert payload_units < 0x10000, print( + "Payload too large: len={0} units={1}".format( + payload_len, payload_units + ) + ) + + header[0x10:0x12] = payload_units.to_bytes(2, "little") + + # bytes 0x14 - 0x17 TODO offset from start of payload to FW payload to be + # loaded by Boot-ROM. We ask Boot-ROM to load (LFW || EC_RO). + # LFW location provided on the command line. + assert args.lfw_loc % 4096 == 0, print( + "LFW location not on a 4KB boundary! 0x{0:0x}".format(args.lfw_loc) + ) + + assert args.lfw_loc >= (args.header_loc + chip_dict["HEADER_SIZE"]), print( + "LFW location not greater than header location + header size" + ) + + lfw_ofs = args.lfw_loc - args.header_loc + header[0x14:0x18] = lfw_ofs.to_bytes(4, "little") + + # MEC172x: authentication key select. Authentication not used, set to 0. + header[0x18] = 0 + + # header[0x19], header[0x20:0x28] + # header[0x1A:0x20] reserved 0 + # MEC172x: supports SPI flash devices with drive strength settings + # TODO leave these fields at 0 for now. We must add 6 command line + # arguments. + + # header[0x28:0x48] reserve can be any value + # header[0x48:0x50] Customer use. TODO + # authentication disabled, leave these 0. + # header[0x50:0x80] ECDSA P384 Authentication Public key Rx + # header[0x80:0xB0] ECDSA P384 Authentication Public key Ry + + # header[0xB0:0xE0] = SHA384(header[0:0xB0]) + header[0xB0:0xE0] = hashlib.sha384(header[0:0xB0]).digest() + # When ECDSA authentication is disabled MCHP SPI image generator + # is filling the last 48 bytes of the Header with 0xff + header[-48:] = b"\xff" * 48 + + debug_print("After hash: len(header) = ", len(header)) + + return header + + +# +# MEC172x 128-byte EC Info Block appended to end of padded FW binary. +# Python slice notation +# byte[0:0x64] are undefined, we set to 0xFF +# byte[0x64] = FW Build LSB +# byte[0x65] = FW Build MSB +# byte[0x66:0x68] = undefined, set to 0xFF +# byte[0x68:0x78] = Roll back permissions bit maps +# byte[0x78:0x7c] = key revocation bit maps +# byte[0x7c] = platform ID LSB +# byte[0x7d] = platform ID MSB +# byte[0x7e] = auto-rollback protection enable +# byte[0x7f] = current imeage revision +# +def GenEcInfoBlock(args, chip_dict): + # ecinfo = bytearray([0xff] * chip_dict["EC_INFO_BLK_SZ"]) + ecinfo = bytearray(chip_dict["EC_INFO_BLK_SZ"]) + return ecinfo + + +# +# Generate SPI FW image co-signature. +# MEC172x cosignature is 96 bytes used by OEM FW +# developer to sign their binary with ECDSA-P384-SHA384 or +# some other signature algorithm that fits in 96 bytes. +# At this time Cros-EC is not using this field, fill with 0xFF. +# If this feature is implemented we need to read the OEM's +# generated signature from a file and extract the binary +# signature. +# +def GenCoSignature(args, chip_dict, payload): + return bytearray(b"\xff" * chip_dict["COSIG_SZ"]) + + +# +# Generate SPI FW Image trailer. +# MEC172x: Size = 160 bytes +# binary = payload || encryption_key_header || ec_info_block || cosignature +# trailer[0:48] = SHA384(binary) +# trailer[48:144] = 0xFF +# trailer[144:160] = 0xFF. Boot-ROM spec. says these bytes should be random. +# Authentication & encryption are not used therefore random data +# is not necessary. +def GenTrailer( + args, chip_dict, payload, encryption_key_header, ec_info_block, cosignature +): + debug_print("GenTrailer SHA384 computation") + trailer = bytearray(chip_dict["TAILER_PAD_BYTE"] * chip_dict["TRAILER_SZ"]) + hasher = hashlib.sha384() + hasher.update(payload) + debug_print(" Update: payload len=0x{0:0x}".format(len(payload))) + if ec_info_block != None: + hasher.update(ec_info_block) + debug_print( + " Update: ec_info_block len=0x{0:0x}".format(len(ec_info_block)) + ) + if encryption_key_header != None: + hasher.update(encryption_key_header) + debug_print( + " Update: encryption_key_header len=0x{0:0x}".format( + len(encryption_key_header) + ) + ) + if cosignature != None: + hasher.update(cosignature) + debug_print( + " Update: cosignature len=0x{0:0x}".format(len(cosignature)) + ) + trailer[0:48] = hasher.digest() + trailer[-16:] = 16 * b"\xff" + + return trailer + + +# MEC172x supports two 32-bit Tags located at offsets 0x0 and 0x4 +# in the SPI flash. +# Tag format: +# bits[23:0] correspond to bits[31:8] of the Header SPI address +# Header is always on a 256-byte boundary. +# bits[31:24] = CRC8-ITU of bits[23:0]. +# Notice there is no chip-select field in the Tag both Tag's point +# to the same flash part. +# +def BuildTag(args): + tag = bytearray( + [ + (args.header_loc >> 8) & 0xFF, + (args.header_loc >> 16) & 0xFF, + (args.header_loc >> 24) & 0xFF, + ] + ) + tag.append(Crc8(0, tag)) + return tag + + +def BuildTagFromHdrAddr(header_loc): + tag = bytearray( + [ + (header_loc >> 8) & 0xFF, + (header_loc >> 16) & 0xFF, + (header_loc >> 24) & 0xFF, + ] + ) + tag.append(Crc8(0, tag)) + return tag + + +# FlashMap is an option for MEC172x +# It is a 32 bit structure +# bits[18:0] = bits[30:12] of second SPI flash base address +# bits[23:19] = 0 reserved +# bits[31:24] = CRC8 of bits[23:0] +# Input: +# integer containing base address of second SPI flash +# This value is usually equal to the size of the first +# SPI flash and should be a multiple of 4KB +# Output: +# bytearray of length 4 +def BuildFlashMap(secondSpiFlashBaseAddr): + flashmap = bytearray(4) + flashmap[0] = (secondSpiFlashBaseAddr >> 12) & 0xFF + flashmap[1] = (secondSpiFlashBaseAddr >> 20) & 0xFF + flashmap[2] = (secondSpiFlashBaseAddr >> 28) & 0xFF + flashmap[3] = Crc8(0, flashmap) + return flashmap + + +# +# Creates temporary file for read/write +# Reads binary file containing LFW image_size (loader_file) +# Writes LFW image to temporary file +# Reads RO image at beginning of rorw_file up to image_size +# (assumes RO/RW images have been padded with 0xFF +# Returns temporary file name +# +def PacklfwRoImage(rorw_file, loader_file, image_size): + """Create a temp file with the + first image_size bytes from the loader file and append bytes + from the rorw file. + return the filename""" + fo = tempfile.NamedTemporaryFile(delete=False) # Need to keep file around + with open(loader_file, "rb") as fin1: # read 4KB loader file + pro = fin1.read() + fo.write(pro) # write 4KB loader data to temp file + with open(rorw_file, "rb") as fin: + ro = fin.read(image_size) + + fo.write(ro) + fo.close() + + return fo.name + + +# +# Generate a test EC_RW image of same size +# as original. +# Preserve image_data structure and fill all +# other bytes with 0xA5. +# useful for testing SPI read and EC build +# process hash generation. +# +def gen_test_ecrw(pldrw): + debug_print("gen_test_ecrw: pldrw type =", type(pldrw)) + debug_print("len pldrw =", len(pldrw), " = ", hex(len(pldrw))) + cookie1_pos = pldrw.find(b"\x99\x88\x77\xce") + cookie2_pos = pldrw.find(b"\xdd\xbb\xaa\xce", cookie1_pos + 4) + t = struct.unpack(" 0 and cookie2_pos > cookie1_pos: + for i in range(0, cookie1_pos): + pldrw[i] = 0xA5 + for i in range(cookie2_pos + 4, len(pldrw)): + pldrw[i] = 0xA5 + + with open("ec_RW_test.bin", "wb") as fecrw: + fecrw.write(pldrw[:size]) + + +def parseargs(): + rpath = os.path.dirname(os.path.relpath(__file__)) + + parser = argparse.ArgumentParser() + parser.add_argument( + "-i", + "--input", + help="EC binary to pack, usually ec.bin or ec.RO.flat.", + metavar="EC_BIN", + default="ec.bin", + ) + parser.add_argument( + "-o", + "--output", + help="Output flash binary file", + metavar="EC_SPI_FLASH", + default="ec.packed.bin", + ) + parser.add_argument( + "--loader_file", help="EC loader binary", default="ecloader.bin" + ) + parser.add_argument( + "--load_addr", type=int, help="EC SRAM load address", default=0xC0000 + ) + parser.add_argument( + "-s", + "--spi_size", + type=int, + help="Size of the SPI flash in KB", + default=512, + ) + parser.add_argument( + "-l", + "--header_loc", + type=int, + help="Location of header in SPI flash. Must be on a 256 byte boundary", + default=0x0100, + ) + parser.add_argument( + "--lfw_loc", + type=int, + help="Location of LFW in SPI flash. Must be on a 4KB boundary", + default=0x1000, + ) + parser.add_argument( + "--lfw_size", type=int, help="LFW size in bytes", default=0x1000 + ) + parser.add_argument( + "-r", + "--rw_loc", + type=int, + help="Start offset of EC_RW. Default is -1 meaning 1/2 flash size", + default=-1, + ) + parser.add_argument( + "--spi_clock", + type=int, + help="SPI clock speed. 8, 12, 24, or 48 MHz.", + default=24, + ) + parser.add_argument( + "--spi_read_cmd", + type=int, + help="SPI read command. 0x3, 0xB, 0x3B, or 0x6B.", + default=0xB, + ) + parser.add_argument( + "--image_size", + type=int, + help="Size of a single image. Default 244KB", + default=(244 * 1024), + ) + parser.add_argument( + "--test_spi", + action="store_true", + help="Test SPI data integrity by adding CRC32 in last 4-bytes of RO/RW binaries", + default=False, + ) + parser.add_argument( + "--test_ecrw", + action="store_true", + help="Use fixed pattern for EC_RW but preserve image_data", + default=False, + ) + parser.add_argument( + "--verbose", + action="store_true", + help="Enable verbose output", + default=False, + ) + parser.add_argument( + "--tag0_loc", type=int, help="MEC172x TAG0 SPI offset", default=0 + ) + parser.add_argument( + "--tag1_loc", type=int, help="MEC172x TAG1 SPI offset", default=4 + ) + parser.add_argument( + "--spi_drive_str", + type=int, + help="Chip SPI drive strength in mA: 2, 4, 8, or 12", + default=4, + ) + parser.add_argument( + "--spi_slew_fast", + action="store_true", + help="SPI use fast slew rate. Default is False", + default=False, + ) + parser.add_argument( + "--spi_cpol", + type=int, + help="SPI clock polarity when idle. Defealt is 0(low)", + default=0, + ) + parser.add_argument( + "--spi_cpha_mosi", + type=int, + help="""SPI clock phase controller drives data. + 0=Data driven on active to inactive clock edge, + 1=Data driven on inactive to active clock edge""", + default=0, + ) + parser.add_argument( + "--spi_cpha_miso", + type=int, + help="""SPI clock phase controller samples data. + 0=Data sampled on inactive to active clock edge, + 1=Data sampled on active to inactive clock edge""", + default=0, + ) + + return parser.parse_args() + + +def print_args(args): + debug_print("parsed arguments:") + debug_print(".input = ", args.input) + debug_print(".output = ", args.output) + debug_print(".loader_file = ", args.loader_file) + debug_print(".spi_size (KB) = ", hex(args.spi_size)) + debug_print(".image_size = ", hex(args.image_size)) + debug_print(".load_addr", hex(args.load_addr)) + debug_print(".tag0_loc = ", hex(args.tag0_loc)) + debug_print(".tag1_loc = ", hex(args.tag1_loc)) + debug_print(".header_loc = ", hex(args.header_loc)) + debug_print(".lfw_loc = ", hex(args.lfw_loc)) + debug_print(".lfw_size = ", hex(args.lfw_size)) + if args.rw_loc < 0: + debug_print(".rw_loc = ", args.rw_loc) + else: + debug_print(".rw_loc = ", hex(args.rw_loc)) + debug_print(".spi_clock (MHz) = ", args.spi_clock) + debug_print(".spi_read_cmd = ", hex(args.spi_read_cmd)) + debug_print(".test_spi = ", args.test_spi) + debug_print(".test_ecrw = ", args.test_ecrw) + debug_print(".verbose = ", args.verbose) + debug_print(".spi_drive_str = ", args.spi_drive_str) + debug_print(".spi_slew_fast = ", args.spi_slew_fast) + debug_print(".spi_cpol = ", args.spi_cpol) + debug_print(".spi_cpha_mosi = ", args.spi_cpha_mosi) + debug_print(".spi_cpha_miso = ", args.spi_cpha_miso) + + +def spi_list_append(mylist, loc, data, description): + """Append SPI data block tuple to list""" + t = (loc, data, description) + mylist.append(t) + debug_print( + "Add SPI entry: offset=0x{0:08x} len=0x{1:0x} descr={2}".format( + loc, len(data), description + ) + ) + + +# +# Handle quiet mode build from Makefile +# Quiet mode when V is unset or V=0 +# Verbose mode when V=1 +# +# MEC172x SPI Image Generator +# No authentication +# No payload encryption +# +# SPI Offset 0x0 = TAG0 points to Header for EC-RO FW +# SPI Offset 0x4 = TAG1 points to Header for EC-RO FW +# TAG Size = 4 bytes +# bits[23:0] = bits[31:8] of Header SPI offset +# bits[31:24] = CRC8-ITU checksum of bits[23:0]. +# +# MEC172x SPI header and payload layout for minimum size +# header offset aligned on 256 byte boundary +# header_spi_address: +# header[0:0x4F] = Header data +# header[0x50:0x80] = ECDSA-P384 public key x for Header authentication +# header[0x80:0xB0] = ECDSA-P384 public key y for Header authentication +# header[0xB0:0xE0] = SHA384 digest of header[0:0xB0] +# header[0xE0:0x110] = ECDSA-P384-SHA384 Signature.R of header[0:0xB0] +# header[0x110:0x140] = ECDSA-P384-SHA384 Signature.S of header[0:0xB0] +# payload_spi_address = header_spi_address + len(Header) +# Payload had been padded such that len(padded_payload) % 128 == 0 +# padded_payload[padded_payload_len] +# payload_signature_address = payload_spi_address + len(padded_payload) +# payload_encryption_key_header[128] Not present if encryption disabled +# payload_cosignature[96] = 0 if Authentication is disabled +# payload_trailer[160] = SHA384(padded_payload || +# optional payload_encryption_key_header) +# || 48 * [0] +# || 48 * [0] +# +def main(): + global debug_print + + args = parseargs() + + if args.verbose: + debug_print = print + + debug_print("Begin pack_ec_mec172x.py script") + + print_args(args) + + chip_dict = MEC172X_DICT + + # Boot-ROM requires header location aligned >= 256 bytes. + # CrOS EC flash image update code requires EC_RO/RW location to be aligned + # on a flash erase size boundary and EC_RO/RW size to be a multiple of + # the smallest flash erase block size. + + spi_size = args.spi_size * 1024 + spi_image_size = spi_size // 2 + + rorofile = PacklfwRoImage(args.input, args.loader_file, args.image_size) + debug_print("Temporary file containing LFW + EC_RO is ", rorofile) + + lfw_ecro = GetPayload(rorofile, chip_dict) + lfw_ecro_len = len(lfw_ecro) + debug_print("Padded LFW + EC_RO length = ", hex(lfw_ecro_len)) + + # SPI test mode compute CRC32 of EC_RO and store in last 4 bytes + if args.test_spi: + crc32_ecro = zlib.crc32(bytes(lfw_ecro[args.lfw_size : -4])) + crc32_ecro_bytes = crc32_ecro.to_bytes(4, byteorder="little") + lfw_ecro[-4:] = crc32_ecro_bytes + debug_print("ecro len = ", hex(len(lfw_ecro) - args.lfw_size)) + debug_print("CRC32(ecro-4) = ", hex(crc32_ecro)) + + # Reads entry point from offset 4 of file. + # This assumes binary has Cortex-M4 vector table at offset 0. + # 32-bit word at offset 0x0 initial stack pointer value + # 32-bit word at offset 0x4 address of reset handler + # NOTE: reset address will have bit[0]=1 to ensure thumb mode. + lfw_ecro_entry = GetEntryPoint(rorofile) + debug_print( + "LFW Entry point from GetEntryPoint = 0x{0:08x}".format(lfw_ecro_entry) + ) + + # Chromebooks are not using MEC BootROM SPI header/payload authentication + # or payload encryption. In this case the header authentication signature + # is filled with the hash digest of the respective entity. + # BuildHeader2 computes the hash digest and stores it in the correct + # header location. + header = BuildHeader2( + args, chip_dict, lfw_ecro_len, args.load_addr, lfw_ecro_entry + ) + printByteArrayAsHex(header, "Header(lfw_ecro)") + + ec_info_block = GenEcInfoBlock(args, chip_dict) + printByteArrayAsHex(ec_info_block, "EC Info Block") + + cosignature = GenCoSignature(args, chip_dict, lfw_ecro) + printByteArrayAsHex(cosignature, "LFW + EC_RO cosignature") + + trailer = GenTrailer( + args, chip_dict, lfw_ecro, None, ec_info_block, cosignature + ) + + printByteArrayAsHex(trailer, "LFW + EC_RO trailer") + + # Build TAG0. Set TAG1=TAG0 Boot-ROM is allowed to load EC-RO only. + tag0 = BuildTag(args) + tag1 = tag0 + + debug_print("Call to GetPayloadFromOffset") + debug_print("args.input = ", args.input) + debug_print("args.image_size = ", hex(args.image_size)) + + ecrw = GetPayloadFromOffset(args.input, args.image_size, chip_dict) + debug_print("type(ecrw) is ", type(ecrw)) + debug_print("len(ecrw) is ", hex(len(ecrw))) + + # truncate to args.image_size + ecrw_len = len(ecrw) + if ecrw_len > args.image_size: + debug_print( + "Truncate EC_RW len={0:0x} to image_size={1:0x}".format( + ecrw_len, args.image_size + ) + ) + ecrw = ecrw[: args.image_size] + ecrw_len = len(ecrw) + + debug_print("len(EC_RW) = ", hex(ecrw_len)) + + # SPI test mode compute CRC32 of EC_RW and store in last 4 bytes + if args.test_spi: + crc32_ecrw = zlib.crc32(bytes(ecrw[0:-4])) + crc32_ecrw_bytes = crc32_ecrw.to_bytes(4, byteorder="little") + ecrw[-4:] = crc32_ecrw_bytes + debug_print("ecrw len = ", hex(len(ecrw))) + debug_print("CRC32(ecrw) = ", hex(crc32_ecrw)) + + # Assume FW layout is standard Cortex-M style with vector + # table at start of binary. + # 32-bit word at offset 0x0 = Initial stack pointer + # 32-bit word at offset 0x4 = Address of reset handler + ecrw_entry_tuple = struct.unpack_from("= 0: + rw_offset = args.rw_loc + + debug_print("rw_offset = 0x{0:08x}".format(rw_offset)) + + # spi_list.append((rw_offset, ecrw, "ecrw")) + spi_list_append(spi_list, rw_offset, ecrw, "EC_RW") + offset = rw_offset + len(ecrw) + + spi_list = sorted(spi_list) + + debug_print("Display spi_list:") + dumpsects(spi_list) + + # + # MEC172x Boot-ROM locates TAG0/1 at SPI offset 0 + # instead of end of SPI. + # + with open(args.output, "wb") as f: + debug_print("Write spi list to file", args.output) + addr = 0 + for s in spi_list: + if addr < s[0]: + debug_print( + "Offset ", + hex(addr), + " Length", + hex(s[0] - addr), + "fill with 0xff", + ) + f.write(b"\xff" * (s[0] - addr)) + addr = s[0] + debug_print( + "Offset ", + hex(addr), + " Length", + hex(len(s[1])), + "write data", + ) + + f.write(s[1]) + addr += len(s[1]) + + if addr < spi_size: + debug_print( + "Offset ", + hex(addr), + " Length", + hex(spi_size - addr), + "fill with 0xff", + ) + f.write(b"\xff" * (spi_size - addr)) + + f.flush() + + +if __name__ == "__main__": + main() diff --git a/chip/mchp/watchdog.c b/chip/mchp/watchdog.c index 0533155e08..50edda70e0 100644 --- a/chip/mchp/watchdog.c +++ b/chip/mchp/watchdog.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,86 +8,171 @@ #include "hooks.h" #include "registers.h" #include "task.h" -#include "watchdog.h" #include "tfdp_chip.h" +#include "watchdog.h" void watchdog_reload(void) { MCHP_WDG_KICK = 1; -#ifdef CONFIG_WATCHDOG_HELP - /* Reload the auxiliary timer */ - MCHP_TMR16_CTL(0) &= ~BIT(5); - MCHP_TMR16_CNT(0) = CONFIG_AUX_TIMER_PERIOD_MS; - MCHP_TMR16_CTL(0) |= BIT(5); -#endif + if (IS_ENABLED(CONFIG_WATCHDOG_HELP)) { + /* Reload the auxiliary timer */ + MCHP_TMR16_CTL(0) &= ~BIT(5); + MCHP_TMR16_CNT(0) = CONFIG_AUX_TIMER_PERIOD_MS; + MCHP_TMR16_CTL(0) |= BIT(5); + } } DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); -int watchdog_init(void) +#if defined(CHIP_FAMILY_MEC152X) || defined(CHIP_FAMILY_MEC172X) +static void wdg_intr_enable(int enable) { -#ifdef CONFIG_WATCHDOG_HELP - uint32_t val; - - /* - * Watchdog does not warn us before expiring. Let's use a 16-bit - * timer as an auxiliary timer. - */ + if (enable) { + MCHP_WDG_STATUS = MCHP_WDG_STS_IRQ; + MCHP_WDG_IEN = MCHP_WDG_IEN_IRQ_EN; + MCHP_WDG_CTL |= MCHP_WDG_RESET_IRQ_EN; + MCHP_INT_ENABLE(MCHP_WDG_GIRQ) = MCHP_WDG_GIRQ_BIT; + task_enable_irq(MCHP_IRQ_WDG); + } else { + MCHP_WDG_IEN = 0U; + MCHP_WDG_CTL &= ~(MCHP_WDG_RESET_IRQ_EN); + MCHP_INT_DISABLE(MCHP_WDG_GIRQ) = MCHP_WDG_GIRQ_BIT; + task_disable_irq(MCHP_IRQ_WDG); + } +} +#else +static void wdg_intr_enable(int enable) +{ + (void)enable; +} +#endif - /* Clear 16-bit basic timer 0 PCR sleep enable */ - MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_BTMR16_0); +/* + * MEC1701 WDG asserts chip reset on LOAD count expiration. + * WDG interrupt is simulated using a 16-bit general purpose + * timer whose period is sufficiently less that the WDG timeout + * period allowing watchdog trace data to be saved. + * + * MEC152x adds interrupt capability to the WDT. + * Enable MEC152x WDG interrupt. WDG event will assert + * IRQ and kick itself starting another LOAD timeout. + * After the new LOAD expires WDG will assert chip reset. + * The WDG ISR calls watchdog trace save API, upon return we + * enter a spin loop waiting for the LOAD period to expire. + * WDG does not have a way to trigger an immediate reset except + * by re-programming it. + */ +int watchdog_init(void) +{ + if (IS_ENABLED(CONFIG_WATCHDOG_HELP)) { + /* + * MEC170x Watchdog does not warn us before expiring. + * Let's use a 16-bit timer as an auxiliary timer. + */ - /* Stop the auxiliary timer if it's running */ - MCHP_TMR16_CTL(0) &= ~BIT(5); + /* Clear 16-bit basic timer 0 PCR sleep enable */ + MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_BTMR16_0); - /* Enable auxiliary timer */ - MCHP_TMR16_CTL(0) |= BIT(0); + /* Stop the auxiliary timer if it's running */ + MCHP_TMR16_CTL(0) &= ~BIT(5); - val = MCHP_TMR16_CTL(0); + /* Enable auxiliary timer */ + MCHP_TMR16_CTL(0) |= BIT(0); - /* Pre-scale = 48000 -> 1kHz -> Period = 1ms */ - val = (val & 0xffff) | (47999 << 16); + /* Prescaler = 48000 -> 1kHz -> Period = 1 ms */ + MCHP_TMR16_CTL(0) = (MCHP_TMR16_CTL(0) & 0xffffU) | + (47999 << 16); - /* No auto restart */ - val &= ~BIT(3); + /* No auto restart */ + MCHP_TMR16_CTL(0) &= ~BIT(3); - /* Count down */ - val &= ~BIT(2); + /* Count down */ + MCHP_TMR16_CTL(0) &= ~BIT(2); - MCHP_TMR16_CTL(0) = val; + /* Enable interrupt from auxiliary timer */ + MCHP_TMR16_IEN(0) |= BIT(0); + task_enable_irq(MCHP_IRQ_TIMER16_0); + MCHP_INT_ENABLE(MCHP_TMR16_GIRQ) = MCHP_TMR16_GIRQ_BIT(0); - /* Enable interrupt from auxiliary timer */ - MCHP_TMR16_IEN(0) |= 1; - task_enable_irq(MCHP_IRQ_TIMER16_0); - MCHP_INT_ENABLE(MCHP_TMR16_GIRQ) = MCHP_TMR16_GIRQ_BIT(0); + /* Load and start the auxiliary timer */ + MCHP_TMR16_CNT(0) = CONFIG_AUX_TIMER_PERIOD_MS; + MCHP_TMR16_CNT(0) |= BIT(5); + } - /* Load and start the auxiliary timer */ - MCHP_TMR16_CNT(0) = CONFIG_AUX_TIMER_PERIOD_MS; - MCHP_TMR16_CNT(0) |= BIT(5); -#endif + MCHP_WDG_CTL = 0; /* Clear WDT PCR sleep enable */ MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_WDT); - /* Set timeout. It takes 1007us to decrement WDG_CNT by 1. */ + /* Set timeout. It takes 1007 us to decrement WDG_CNT by 1. */ MCHP_WDG_LOAD = CONFIG_WATCHDOG_PERIOD_MS * 1000 / 1007; - /* Start watchdog */ -#ifdef CONFIG_CHIPSET_DEBUG - /* WDT will not count if JTAG TRST# is pulled high by JTAG cable */ - MCHP_WDG_CTL = BIT(4) | BIT(0); -#else - MCHP_WDG_CTL |= 1; -#endif + wdg_intr_enable(1); + + /* + * Start watchdog + * If chipset debug build enable feature to prevent watchdog from + * counting if a debug cable is attached to JTAG_RST#. + */ + if (IS_ENABLED(CONFIG_CHIPSET_DEBUG)) + MCHP_WDG_CTL |= + (MCHP_WDT_CTL_ENABLE | MCHP_WDT_CTL_JTAG_STALL_EN); + else + MCHP_WDG_CTL |= MCHP_WDT_CTL_ENABLE; return EC_SUCCESS; } -#ifdef CONFIG_WATCHDOG_HELP +/* MEC152x Watchdog can fire an interrupt to CPU before system reset */ +#if defined(CHIP_FAMILY_MEC152X) || defined(CHIP_FAMILY_MEC172X) + void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp) { - trace0(0, WDT, 0, "Watchdog check from 16-bit basic timer0 ISR"); + /* Clear WDG first then aggregator */ + MCHP_WDG_STATUS = MCHP_WDG_STS_IRQ; + MCHP_INT_SOURCE(MCHP_WDG_GIRQ) = MCHP_WDG_GIRQ_BIT; + /* Cause WDG to reload again. */ + MCHP_WDG_KICK = 1; + + watchdog_trace(excep_lr, excep_sp); + + /* Reset system by re-programing WDT to trigger after 2 32KHz clocks */ + MCHP_WDG_CTL = 0; /* clear enable to allow write to load register */ + MCHP_WDG_LOAD = 2; + MCHP_WDG_CTL |= MCHP_WDT_CTL_ENABLE; +} + +/* ISR for watchdog warning naked will keep SP & LR */ +void IRQ_HANDLER(MCHP_IRQ_WDG)(void) __keep __attribute__((naked)); +void IRQ_HANDLER(MCHP_IRQ_WDG)(void) +{ + /* Naked call so we can extract raw LR and SP */ + asm volatile("mov r0, lr\n" + "mov r1, sp\n" + /* + * Must push registers in pairs to keep 64-bit aligned + * stack for ARM EABI. This also conveniently saves + * R0=LR so we can pass it to task_resched_if_needed. + */ + "push {r0, lr}\n" + "bl watchdog_check\n" + "pop {r0, lr}\n" + "b task_resched_if_needed\n"); +} + +/* put the watchdog at the highest priority */ +const struct irq_priority __keep IRQ_PRIORITY(MCHP_IRQ_WDG) + __attribute__((section(".rodata.irqprio"))) = { MCHP_IRQ_WDG, 0 }; + +#else +/* + * MEC1701 watchdog only resets. Use a 16-bit timer to fire in interrupt + * for saving watchdog trace. + */ +#ifdef CONFIG_WATCHDOG_HELP +void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp) +{ /* Clear status */ MCHP_TMR16_STS(0) |= 1; /* clear aggregator status */ @@ -96,8 +181,7 @@ void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp) watchdog_trace(excep_lr, excep_sp); } -void -IRQ_HANDLER(MCHP_IRQ_TIMER16_0)(void) __keep __attribute__((naked)); +void IRQ_HANDLER(MCHP_IRQ_TIMER16_0)(void) __keep __attribute__((naked)); void IRQ_HANDLER(MCHP_IRQ_TIMER16_0)(void) { /* Naked call so we can extract raw LR and SP */ @@ -105,7 +189,7 @@ void IRQ_HANDLER(MCHP_IRQ_TIMER16_0)(void) "mov r1, sp\n" /* * Must push registers in pairs to keep 64-bit aligned - * stack for ARM EABI. This also conveninently saves + * stack for ARM EABI. This also conveniently saves * R0=LR so we can pass it to task_resched_if_needed. */ "push {r0, lr}\n" @@ -114,10 +198,9 @@ void IRQ_HANDLER(MCHP_IRQ_TIMER16_0)(void) "b task_resched_if_needed\n"); } -/* - * Put the watchdog at the highest interrupt priority. - */ -const struct irq_priority __keep IRQ_PRIORITY(MEC1322_IRQ_TIMER16_0) - __attribute__((section(".rodata.irqprio"))) - = {MCHP_IRQ_TIMER16_0, 0}; -#endif +/* Put the watchdog at the highest interrupt priority. */ +const struct irq_priority __keep IRQ_PRIORITY(MCHP_IRQ_TIMER16_0) + __attribute__((section(".rodata.irqprio"))) = { MCHP_IRQ_TIMER16_0, 0 }; + +#endif /* #ifdef CONFIG_WATCHDOG_HELP */ +#endif /* #if defined(CHIP_FAMILY_MEC152X) || defined(CHIP_FAMILY_MEC172X) */ diff --git a/chip/mec1322/adc.c b/chip/mec1322/adc.c deleted file mode 100644 index fd797a7f15..0000000000 --- a/chip/mec1322/adc.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "adc.h" -#include "adc_chip.h" -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* - * Conversion on a single channel takes less than 12 ms. Set timeout to - * 15 ms so that we have a 3-ms margin. - */ -#define ADC_SINGLE_READ_TIME 15000 - -struct mutex adc_lock; - -static volatile task_id_t task_waiting; - -static int start_single_and_wait(int timeout) -{ - int event; - - task_waiting = task_get_current(); - - /* Start conversion */ - MEC1322_ADC_CTRL |= BIT(1); - - /* Wait for interrupt */ - event = task_wait_event(timeout); - task_waiting = TASK_ID_INVALID; - return event != TASK_EVENT_TIMER; -} - -int adc_read_channel(enum adc_channel ch) -{ - const struct adc_t *adc = adc_channels + ch; - int value; - - mutex_lock(&adc_lock); - - MEC1322_ADC_SINGLE = 1 << adc->channel; - - if (start_single_and_wait(ADC_SINGLE_READ_TIME)) - value = MEC1322_ADC_READ(adc->channel) * adc->factor_mul / - adc->factor_div + adc->shift; - else - value = ADC_READ_ERROR; - - mutex_unlock(&adc_lock); - return value; -} - -static void adc_init(void) -{ - /* Activate ADC module */ - MEC1322_ADC_CTRL |= BIT(0); - - /* Enable interrupt */ - task_waiting = TASK_ID_INVALID; - MEC1322_INT_ENABLE(17) |= BIT(10); - MEC1322_INT_BLK_EN |= BIT(17); - task_enable_irq(MEC1322_IRQ_ADC_SNGL); -} -DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_INIT_ADC); - -void adc_interrupt(void) -{ - /* Clear interrupt status bit */ - MEC1322_ADC_CTRL |= BIT(7); - - if (task_waiting != TASK_ID_INVALID) - task_wake(task_waiting); -} -DECLARE_IRQ(MEC1322_IRQ_ADC_SNGL, adc_interrupt, 2); diff --git a/chip/mec1322/adc_chip.h b/chip/mec1322/adc_chip.h deleted file mode 100644 index bc25344b11..0000000000 --- a/chip/mec1322/adc_chip.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* MEC1322-specific ADC module for Chrome EC */ - -#ifndef __CROS_EC_ADC_CHIP_H -#define __CROS_EC_ADC_CHIP_H - -/* Data structure to define ADC channels. */ -struct adc_t { - const char *name; - int factor_mul; - int factor_div; - int shift; - int channel; -}; - -/* - * Boards must provide this list of ADC channel definitions. This must match - * the enum adc_channel list provided by the board. - */ -extern const struct adc_t adc_channels[]; - -/* Minimum and maximum values returned by adc_read_channel(). */ -#define ADC_READ_MIN 0 -#define ADC_READ_MAX 1023 - -/* Just plain id mapping for code readability */ -#define MEC1322_ADC_CH(x) (x) - -#endif /* __CROS_EC_ADC_CHIP_H */ diff --git a/chip/mec1322/build.mk b/chip/mec1322/build.mk deleted file mode 100644 index 2b0c9cc229..0000000000 --- a/chip/mec1322/build.mk +++ /dev/null @@ -1,79 +0,0 @@ -# -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# MEC1322 chip specific files build -# - -# MEC1322 SoC has a Cortex-M4 ARM core -CORE:=cortex-m -# Allow the full Cortex-M4 instruction set -CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4 - -ifeq ($(CONFIG_LTO),y) -# Re-include the core's build.mk file so we can remove the lto flag. -include core/$(CORE)/build.mk -endif - -# Required chip modules -chip-y=clock.o gpio.o hwtimer.o system.o uart.o port80.o -chip-$(CONFIG_ADC)+=adc.o -chip-$(CONFIG_FANS)+=fan.o -chip-$(CONFIG_FLASH_PHYSICAL)+=flash.o -chip-$(CONFIG_I2C)+=i2c.o -chip-$(CONFIG_HOSTCMD_LPC)+=lpc.o -chip-$(CONFIG_PWM)+=pwm.o -chip-$(CONFIG_WATCHDOG)+=watchdog.o -ifndef CONFIG_KEYBOARD_NOT_RAW -chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o -endif -chip-$(CONFIG_DMA)+=dma.o -chip-$(CONFIG_SPI)+=spi.o - -# location of the scripts and keys used to pack the SPI flash image -SCRIPTDIR:=./chip/${CHIP}/util - -# Allow SPI size to be overridden by board specific size, default to 256KB. -CHIP_SPI_SIZE_KB?=256 - -# Commands to convert $^ to $@.tmp -cmd_obj_to_bin = $(OBJCOPY) --gap-fill=0xff -O binary $< $@.tmp1 ; \ - ${SCRIPTDIR}/pack_ec.py -o $@.tmp -i $@.tmp1 \ - --loader_file $(mec1322-lfw-flat) \ - --payload_key ${SCRIPTDIR}/rsakey_sign_payload.pem \ - --header_key ${SCRIPTDIR}/rsakey_sign_header.pem \ - --spi_size ${CHIP_SPI_SIZE_KB} \ - --image_size $(_rw_size); rm -f $@.tmp1 - -mec1322-lfw = chip/mec1322/lfw/ec_lfw -mec1322-lfw-flat = $(out)/RW/$(mec1322-lfw)-lfw.flat - -# build these specifically for lfw with -lfw suffix -objs_lfw = $(patsubst %, $(out)/RW/%-lfw.o, \ - $(addprefix common/, util gpio) \ - $(addprefix chip/$(CHIP)/, spi dma gpio clock hwtimer) \ - core/$(CORE)/cpu $(mec1322-lfw)) - -# reuse version.o (and its dependencies) from main board -objs_lfw += $(out)/RW/common/version.o - -dirs-y+=chip/$(CHIP)/lfw - -# objs with -lfw suffix are to include lfw's gpio -$(out)/RW/%-lfw.o: private CC+=-I$(BDIR)/lfw -DLFW=$(EMPTY) -# Remove the lto flag for the loader. It actually causes it to bloat in size. -ifeq ($(CONFIG_LTO),y) -$(out)/RW/%-lfw.o: private CFLAGS_CPU := $(filter-out -flto, $(CFLAGS_CPU)) -endif -$(out)/RW/%-lfw.o: %.c - $(call quiet,c_to_o,CC ) - -# let lfw's elf link only with selected objects -$(out)/RW/%-lfw.elf: private objs = $(objs_lfw) -$(out)/RW/%-lfw.elf: override shlib := -$(out)/RW/%-lfw.elf: %.ld $(objs_lfw) - $(call quiet,elf,LD ) - -# final image needs lfw loader -$(out)/$(PROJECT).bin: $(mec1322-lfw-flat) diff --git a/chip/mec1322/clock.c b/chip/mec1322/clock.c deleted file mode 100644 index ce07284891..0000000000 --- a/chip/mec1322/clock.c +++ /dev/null @@ -1,484 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Clocks and power management settings */ - -#include "clock.h" -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "hooks.h" -#include "hwtimer.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "registers.h" -#include "shared_mem.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "uart.h" -#include "util.h" -#include "vboot_hash.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) - -#ifdef CONFIG_LOW_POWER_IDLE -/* Recovery time for HvySlp2 is 0 usec */ -#define HEAVY_SLEEP_RECOVER_TIME_USEC 75 - -#define SET_HTIMER_DELAY_USEC 200 - -static int idle_sleep_cnt; -static int idle_dsleep_cnt; -static uint64_t total_idle_dsleep_time_us; - -/* - * Fixed amount of time to keep the console in use flag true after boot in - * order to give a permanent window in which the heavy sleep mode is not used. - */ -#define CONSOLE_IN_USE_ON_BOOT_TIME (15*SECOND) -static int console_in_use_timeout_sec = 60; -static timestamp_t console_expire_time; -#endif /*CONFIG_LOW_POWER_IDLE */ - -static int freq = 48000000; - -void clock_wait_cycles(uint32_t cycles) -{ - asm volatile("1: subs %0, #1\n" - " bne 1b\n" : "+r"(cycles)); -} - -int clock_get_freq(void) -{ - return freq; -} - -void clock_init(void) -{ -#ifdef CONFIG_CLOCK_CRYSTAL - /* XOSEL: 0 = Parallel resonant crystal */ - MEC1322_VBAT_CE &= ~0x1; -#else - /* XOSEL: 1 = Single ended clock source */ - MEC1322_VBAT_CE |= 0x1; -#endif - - /* 32K clock enable */ - MEC1322_VBAT_CE |= 0x2; - -#ifdef CONFIG_CLOCK_CRYSTAL - /* Wait for crystal to stabilize (OSC_LOCK == 1) */ - while (!(MEC1322_PCR_CHIP_OSC_ID & 0x100)) - ; -#endif -} - -/** - * Speed through boot + vboot hash calculation, dropping our processor clock - * only after vboot hashing is completed. - */ -static void clock_turbo_disable(void); -DECLARE_DEFERRED(clock_turbo_disable); - -static void clock_turbo_disable(void) -{ -#ifdef CONFIG_VBOOT_HASH - if (vboot_hash_in_progress()) - hook_call_deferred(&clock_turbo_disable_data, 100 * MSEC); - else -#endif - /* Use 12 MHz processor clock for power savings */ - MEC1322_PCR_PROC_CLK_CTL = 4; -} -DECLARE_HOOK(HOOK_INIT, clock_turbo_disable, HOOK_PRIO_INIT_VBOOT_HASH + 1); - -#ifdef CONFIG_LOW_POWER_IDLE -/** - * initialization of Hibernation timer - */ -static void htimer_init(void) -{ - MEC1322_INT_BLK_EN |= BIT(17); - MEC1322_INT_ENABLE(17) |= BIT(20); /* GIRQ=17, aggregator bit = 20 */ - MEC1322_HTIMER_PRELOAD = 0; /* disable at beginning */ - - task_enable_irq(MEC1322_IRQ_HTIMER); -} - -/** - * Use hibernate module to set up an htimer interrupt at a given - * time from now - * - * @param seconds Number of seconds before htimer interrupt - * @param microseconds Number of microseconds before htimer interrupt - */ -static void system_set_htimer_alarm(uint32_t seconds, uint32_t microseconds) -{ - if (seconds || microseconds) { - - if (seconds > 2) { - /* count from 2 sec to 2 hrs, mec1322 sec 18.10.2 */ - ASSERT(seconds <= 0xffff / 8); - MEC1322_HTIMER_CONTROL = 1; /* 0.125(=1/8) per clock */ - /* (number of counts to be loaded) - * = seconds * ( 8 clocks per second ) - * + microseconds / 125000 - * ---> (0 if (microseconds < 125000) - */ - MEC1322_HTIMER_PRELOAD = - (seconds * 8 + microseconds / 125000); - - } else { /* count up to 2 sec. */ - - MEC1322_HTIMER_CONTROL = 0; /* 30.5(= 2/61) usec */ - - /* (number of counts to be loaded) - * = (total microseconds) / 30.5; - */ - MEC1322_HTIMER_PRELOAD = - (seconds * 1000000 + microseconds) * 2 / 61; - } - } -} - -/** - * return time slept in micro-seconds - */ -static timestamp_t system_get_htimer(void) -{ - uint16_t count; - timestamp_t time; - - count = MEC1322_HTIMER_COUNT; - - - if (MEC1322_HTIMER_CONTROL == 1) /* if > 2 sec */ - /* 0.125 sec per count */ - time.le.lo = (uint32_t)(count * 125000); - else /* if < 2 sec */ - /* 30.5(=61/2)usec per count */ - time.le.lo = (uint32_t)(count * 61 / 2); - - time.le.hi = 0; - - return time; /* in uSec */ -} - -/** - * Disable and clear hibernation timer interrupt - */ -static void system_reset_htimer_alarm(void) -{ - MEC1322_HTIMER_PRELOAD = 0; -} - -/** - * This is mec1322 specific and equivalent to ARM Cortex's - * 'DeepSleep' via system control block register, CPU_SCB_SYSCTRL - */ -static void prepare_for_deep_sleep(void) -{ - uint32_t ec_slp_en = MEC1322_PCR_EC_SLP_EN | - MEC1322_PCR_EC_SLP_EN_SLEEP; - - /* sysTick timer */ - CPU_NVIC_ST_CTRL &= ~ST_ENABLE; - CPU_NVIC_ST_CTRL &= ~ST_COUNTFLAG; - - /* Disable JTAG */ - MEC1322_EC_JTAG_EN &= ~1; - /* Power down ADC VREF, ADC_VREF overrides ADC_CTRL. */ - MEC1322_EC_ADC_VREF_PD |= 1; - - /* Stop watchdog */ - MEC1322_WDG_CTL &= ~1; - - /* Stop timers */ - MEC1322_TMR32_CTL(0) &= ~1; - MEC1322_TMR32_CTL(1) &= ~1; - MEC1322_TMR16_CTL(0) &= ~1; - - MEC1322_PCR_CHIP_SLP_EN |= 0x3; -#ifdef CONFIG_PWM - if (pwm_get_keep_awake_mask()) - ec_slp_en &= ~pwm_get_keep_awake_mask(); - else -#endif - /* Disable 100 Khz clock */ - MEC1322_PCR_SLOW_CLK_CTL &= 0xFFFFFC00; - - MEC1322_PCR_EC_SLP_EN = ec_slp_en; - MEC1322_PCR_HOST_SLP_EN |= MEC1322_PCR_HOST_SLP_EN_SLEEP; - MEC1322_PCR_EC_SLP_EN2 |= MEC1322_PCR_EC_SLP_EN2_SLEEP; - -#ifndef CONFIG_POWER_S0IX - MEC1322_LPC_ACT = 0x0; -#endif - - MEC1322_PCR_SYS_SLP_CTL = 0x2; /* heavysleep 2 */ - - CPU_NVIC_ST_CTRL &= ~ST_TICKINT; /* SYS_TICK_INT_DISABLE */ -} - -static void resume_from_deep_sleep(void) -{ - CPU_NVIC_ST_CTRL |= ST_TICKINT; /* SYS_TICK_INT_ENABLE */ - CPU_NVIC_ST_CTRL |= ST_ENABLE; - - MEC1322_EC_JTAG_EN = 1; - MEC1322_EC_ADC_VREF_PD &= ~1; - /* ADC_VREF_PD overrides ADC_CTRL ! */ - - /* Enable timer */ - MEC1322_TMR32_CTL(0) |= 1; - MEC1322_TMR32_CTL(1) |= 1; - MEC1322_TMR16_CTL(0) |= 1; - - /* Enable watchdog */ - MEC1322_WDG_CTL |= 1; - - MEC1322_PCR_SLOW_CLK_CTL |= 0x1e0; - MEC1322_PCR_CHIP_SLP_EN &= ~0x3; - MEC1322_PCR_EC_SLP_EN &= MEC1322_PCR_EC_SLP_EN_WAKE; - MEC1322_PCR_HOST_SLP_EN &= MEC1322_PCR_HOST_SLP_EN_WAKE; - MEC1322_PCR_EC_SLP_EN2 &= MEC1322_PCR_EC_SLP_EN2_WAKE; - - MEC1322_PCR_SYS_SLP_CTL = 0xF8; /* default */ - -#ifndef CONFIG_POWER_S0IX - /* Enable LPC */ - MEC1322_LPC_ACT |= 1; -#endif -} - - -void clock_refresh_console_in_use(void) -{ - disable_sleep(SLEEP_MASK_CONSOLE); - - /* Set console in use expire time. */ - console_expire_time = get_time(); - console_expire_time.val += console_in_use_timeout_sec * SECOND; -} - -/** - * Low power idle task. Executed when no tasks are ready to be scheduled. - */ -void __idle(void) -{ - timestamp_t t0; - timestamp_t t1; - timestamp_t ht_t1; - uint32_t next_delay; - uint32_t max_sleep_time; - int time_for_dsleep; - int uart_ready_for_deepsleep; - - htimer_init(); /* hibernation timer initialize */ - - disable_sleep(SLEEP_MASK_CONSOLE); - console_expire_time.val = get_time().val + CONSOLE_IN_USE_ON_BOOT_TIME; - - - /* - * Print when the idle task starts. This is the lowest priority task, - * so this only starts once all other tasks have gotten a chance to do - * their task inits and have gone to sleep. - */ - CPRINTS("low power idle task started"); - - while (1) { - /* Disable interrupts */ - interrupt_disable(); - - t0 = get_time(); /* uSec */ - - /* __hw_clock_event_get() is next programmed timer event */ - next_delay = __hw_clock_event_get() - t0.le.lo; - - time_for_dsleep = next_delay > (HEAVY_SLEEP_RECOVER_TIME_USEC + - SET_HTIMER_DELAY_USEC); - - max_sleep_time = next_delay - HEAVY_SLEEP_RECOVER_TIME_USEC; - - /* check if there enough time for deep sleep */ - if (DEEP_SLEEP_ALLOWED && time_for_dsleep) { - - - /* - * Check if the console use has expired and console - * sleep is masked by GPIO(UART-RX) interrupt. - */ - if ((sleep_mask & SLEEP_MASK_CONSOLE) && - t0.val > console_expire_time.val) { - /* allow console to sleep. */ - enable_sleep(SLEEP_MASK_CONSOLE); - - /* - * Wait one clock before checking if heavy sleep - * is allowed to give time for sleep mask - * to be updated. - */ - clock_wait_cycles(1); - - if (LOW_SPEED_DEEP_SLEEP_ALLOWED) - CPRINTS("Disable console in deepsleep"); - } - - - /* UART is not being used */ - uart_ready_for_deepsleep = LOW_SPEED_DEEP_SLEEP_ALLOWED - && !uart_tx_in_progress() - && uart_buffer_empty(); - - /* - * Since MEC1322's heavysleep modes requires all block - * to be sleepable, UART/console's readiness is final - * decision factor of heavysleep of EC. - */ - if (uart_ready_for_deepsleep) { - - idle_dsleep_cnt++; - - /* - * config UART Rx as GPIO wakeup interrupt - * source - */ - uart_enter_dsleep(); - - /* MEC1322 specific deep-sleep mode */ - prepare_for_deep_sleep(); - - /* - * 'max_sleep_time' value should be big - * enough so that hibernation timer's interrupt - * triggers only after 'wfi' completes its - * excution. - */ - max_sleep_time -= (get_time().le.lo - t0.le.lo); - - /* setup/enable htimer wakeup interrupt */ - system_set_htimer_alarm(0, max_sleep_time); - } else { - idle_sleep_cnt++; - } - - /* Wait for interrupt: goes into deep sleep. */ - asm("wfi"); - - if (uart_ready_for_deepsleep) { - - resume_from_deep_sleep(); - - /* - * Fast forward timer according to htimer - * counter: - * Since all blocks including timers will be in - * sleep mode, timers stops except hibernate - * timer. - * And system schedule timer should be corrected - * after wakeup by either hibernate timer or - * GPIO_UART_RX interrupt. - */ - ht_t1 = system_get_htimer(); - - /* disable/clear htimer wakeup interrupt */ - system_reset_htimer_alarm(); - - t1.val = t0.val + - (uint64_t)(max_sleep_time - ht_t1.le.lo); - - force_time(t1); - - /* re-eanble UART */ - uart_exit_dsleep(); - - /* Record time spent in deep sleep. */ - total_idle_dsleep_time_us += - (uint64_t)(max_sleep_time - ht_t1.le.lo); - } - - } else { /* CPU 'Sleep' mode */ - - idle_sleep_cnt++; - - asm("wfi"); - - } - - interrupt_enable(); - } /* while(1) */ -} - -#ifdef CONFIG_CMD_IDLE_STATS -/** - * Print low power idle statistics - */ -static int command_idle_stats(int argc, char **argv) -{ - timestamp_t ts = get_time(); - - ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); - ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); - - ccprintf("Total Time spent in deep-sleep(sec): %.6lld(s)\n", - total_idle_dsleep_time_us); - ccprintf("Total time on: %.6llds\n\n", ts.val); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, - "", - "Print last idle stats"); -#endif /* defined(CONFIG_CMD_IDLE_STATS) */ - -/** - * Configure deep sleep clock settings. - */ -static int command_dsleep(int argc, char **argv) -{ - int v; - - if (argc > 1) { - if (parse_bool(argv[1], &v)) { - /* - * Force deep sleep not to use heavy sleep mode or - * allow it to use the heavy sleep mode. - */ - if (v) /* 'on' */ - disable_sleep(SLEEP_MASK_FORCE_NO_LOW_SPEED); - else /* 'off' */ - enable_sleep(SLEEP_MASK_FORCE_NO_LOW_SPEED); - } else { - /* Set console in use timeout. */ - char *e; - v = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - - console_in_use_timeout_sec = v; - - /* Refresh console in use to use new timeout. */ - clock_refresh_console_in_use(); - } - } - - ccprintf("Sleep mask: %08x\n", sleep_mask); - ccprintf("Console in use timeout: %d sec\n", - console_in_use_timeout_sec); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(dsleep, command_dsleep, - "[ on | off | sec]", - "Deep sleep clock settings:\nUse 'on' to force deep " - "sleep NOT to enter heavysleep mode.\nUse 'off' to " - "allow deep sleep to use heavysleep whenever conditions" - "allow.\n" - "Give a timeout value for the console in use timeout.\n" - "See also 'sleepmask'."); -#endif /* CONFIG_LOW_POWER_IDLE */ diff --git a/chip/mec1322/config_chip.h b/chip/mec1322/config_chip.h deleted file mode 100644 index 414fb492bf..0000000000 --- a/chip/mec1322/config_chip.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_CONFIG_CHIP_H -#define __CROS_EC_CONFIG_CHIP_H - -/* CPU core BFD configuration */ -#include "core/cortex-m/config_core.h" - -/* Number of IRQ vectors on the NVIC */ -#define CONFIG_IRQ_COUNT 93 - -/* Use a bigger console output buffer */ -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 2048 - -/* Interval between HOOK_TICK notifications */ -#define HOOK_TICK_INTERVAL_MS 250 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) - -/* - * Number of I2C controllers. Controller 0 has 2 ports, so the chip has one - * additional port. - */ -#define CONFIG_I2C_MULTI_PORT_CONTROLLER - -#define I2C_CONTROLLER_COUNT 4 -#define I2C_PORT_COUNT 5 - -/****************************************************************************/ -/* Memory mapping */ - -/* - * The memory region for RAM is actually 0x00100000-0x00120000. - * RAM for RO/RW = 20k - * CODE size of the Loader is 3k - * As per the above configuartion the upper 20k - * is used to store data.The rest is for code. - * the lower 107K is flash[ 3k Loader and 104k RO/RW], - * and the higher 20K is RAM shared by loader and RO/RW. - */ - -/****************************************************************************/ -/* Define our RAM layout. */ - -#define CONFIG_MEC_SRAM_BASE_START 0x00100000 -#define CONFIG_MEC_SRAM_BASE_END 0x00120000 -#define CONFIG_MEC_SRAM_SIZE (CONFIG_MEC_SRAM_BASE_END - \ - CONFIG_MEC_SRAM_BASE_START) - -/* 20k RAM for RO / RW / loader */ -#define CONFIG_RAM_SIZE 0x00005000 -#define CONFIG_RAM_BASE (CONFIG_MEC_SRAM_BASE_END - \ - CONFIG_RAM_SIZE) - -/* System stack size */ -#define CONFIG_STACK_SIZE 1024 - -/* non-standard task stack sizes */ -#define IDLE_TASK_STACK_SIZE 512 -#define LARGER_TASK_STACK_SIZE 640 - -#define CHARGER_TASK_STACK_SIZE 640 -#define HOOKS_TASK_STACK_SIZE 640 -#define CONSOLE_TASK_STACK_SIZE 640 -#define HOST_CMD_TASK_STACK_SIZE 640 - -/* - * TODO: Large stack consumption - * https://code.google.com/p/chrome-os-partner/issues/detail?id=49245 - */ -#define PD_TASK_STACK_SIZE 800 - -/* Default task stack size */ -#define TASK_STACK_SIZE 512 - -/****************************************************************************/ -/* Define our flash layout. */ - -/* Protect bank size 4K bytes */ -#define CONFIG_FLASH_BANK_SIZE 0x00001000 -/* Sector erase size 4K bytes */ -#define CONFIG_FLASH_ERASE_SIZE 0x00001000 -/* Minimum write size */ -#define CONFIG_FLASH_WRITE_SIZE 0x00000004 - -/* One page size for write */ -#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 - -/* Program memory base address */ -#define CONFIG_PROGRAM_MEMORY_BASE 0x00100000 - -#include "config_flash_layout.h" - -/****************************************************************************/ -/* Customize the build */ -/* Optional features present on this chip */ -#if 0 -#define CONFIG_ADC -#define CONFIG_PECI -#define CONFIG_MPU -#endif -#define CONFIG_DMA -#define CONFIG_HOSTCMD_LPC -#define CONFIG_SPI -#define CONFIG_SWITCH - -#define GPIO_PIN(index) (index / 10), (1 << (index % 10)) -#define GPIO_PIN_MASK(p, m) .port = (p), .mask = (m) - -#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/mec1322/config_flash_layout.h b/chip/mec1322/config_flash_layout.h deleted file mode 100644 index 3ab249668d..0000000000 --- a/chip/mec1322/config_flash_layout.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_CONFIG_FLASH_LAYOUT_H -#define __CROS_EC_CONFIG_FLASH_LAYOUT_H - -/* - * mec1322 flash layout: - * - Non memory-mapped, external SPI. - * - RW image at the beginning of writable region. - * - Bootloader at the beginning of protected region, followed by RO image. - * - Loader + (RO | RW) loaded into program memory. - */ - -/* Non-memmapped, external SPI */ -#define CONFIG_EXTERNAL_STORAGE -#undef CONFIG_MAPPED_STORAGE -#undef CONFIG_FLASH_PSTATE -#define CONFIG_SPI_FLASH - -/* EC region of SPI resides at end of ROM, protected region follows writable */ -#define CONFIG_EC_PROTECTED_STORAGE_OFF (CONFIG_FLASH_SIZE - 0x20000) -#define CONFIG_EC_PROTECTED_STORAGE_SIZE 0x20000 -#define CONFIG_EC_WRITABLE_STORAGE_OFF (CONFIG_FLASH_SIZE - 0x40000) -#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x20000 - -/* Loader resides at the beginning of program memory */ -#define CONFIG_LOADER_MEM_OFF 0 -#define CONFIG_LOADER_SIZE 0xC00 - -/* Write protect Loader and RO Image */ -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -/* - * Write protect 128k section of 256k physical flash which contains loader - * and RO Images. - */ -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE - -/* - * RO / RW images follow the loader in program memory. Either RO or RW - * image will be loaded -- both cannot be loaded at the same time. - */ -#define CONFIG_RO_MEM_OFF (CONFIG_LOADER_MEM_OFF + \ - CONFIG_LOADER_SIZE) -#define CONFIG_RO_SIZE (97 * 1024) -#define CONFIG_RW_MEM_OFF CONFIG_RO_MEM_OFF -#define CONFIG_RW_SIZE CONFIG_RO_SIZE - -/* WP region consists of second half of SPI, and begins with the boot header */ -#define CONFIG_BOOT_HEADER_STORAGE_OFF 0 -#define CONFIG_BOOT_HEADER_STORAGE_SIZE 0x240 - -/* Loader / lfw image immediately follows the boot header on SPI */ -#define CONFIG_LOADER_STORAGE_OFF (CONFIG_BOOT_HEADER_STORAGE_OFF + \ - CONFIG_BOOT_HEADER_STORAGE_SIZE) - -/* RO image immediately follows the loader image */ -#define CONFIG_RO_STORAGE_OFF (CONFIG_LOADER_STORAGE_OFF + \ - CONFIG_LOADER_SIZE) - -/* RW image starts at the beginning of SPI */ -#define CONFIG_RW_STORAGE_OFF 0 - -#endif /* __CROS_EC_CONFIG_FLASH_LAYOUT_H */ diff --git a/chip/mec1322/dma.c b/chip/mec1322/dma.c deleted file mode 100644 index a6c6fed5ad..0000000000 --- a/chip/mec1322/dma.c +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "console.h" -#include "dma.h" -#include "hooks.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_DMA, outstr) -#define CPRINTS(format, args...) cprints(CC_DMA, format, ## args) - -mec1322_dma_chan_t *dma_get_channel(enum dma_channel channel) -{ - mec1322_dma_regs_t *dma = MEC1322_DMA_REGS; - - return &dma->chan[channel]; -} - -void dma_disable(enum dma_channel channel) -{ - mec1322_dma_chan_t *chan = dma_get_channel(channel); - - if (chan->ctrl & BIT(0)) - chan->ctrl &= ~BIT(0); - - if (chan->act == 1) - chan->act = 0; -} - -void dma_disable_all(void) -{ - int ch; - mec1322_dma_regs_t *dma; - - for (ch = 0; ch < MEC1322_DMAC_COUNT; ch++) { - mec1322_dma_chan_t *chan = dma_get_channel(ch); - /* Abort any current transfer. */ - chan->ctrl |= BIT(25); - /* Disable the channel. */ - chan->ctrl &= ~BIT(0); - chan->act = 0; - } - - /* Soft-reset the block. */ - dma = MEC1322_DMA_REGS; - dma->ctrl |= 0x2; -} - -/** - * Prepare a channel for use and start it - * - * @param chan Channel to read - * @param count Number of bytes to transfer - * @param periph Pointer to peripheral data register - * @param memory Pointer to memory address for receive/transmit - * @param flags DMA flags for the control register, normally: - * MEC1322_DMA_INC_MEM | MEC1322_DMA_TO_DEV for tx - * MEC1322_DMA_INC_MEM for rx - */ -static void prepare_channel(mec1322_dma_chan_t *chan, unsigned count, - void *periph, void *memory, unsigned flags) -{ - int xfer_size = (flags >> 20) & 0x7; - - if (chan->ctrl & BIT(0)) - chan->ctrl &= ~BIT(0); - - chan->act |= 0x1; - chan->dev = (uint32_t)periph; - chan->mem_start = MEC1322_RAM_ALIAS((uint32_t)memory); - chan->mem_end = MEC1322_RAM_ALIAS((uint32_t)memory) + xfer_size * count; - chan->ctrl = flags; -} - -void dma_go(mec1322_dma_chan_t *chan) -{ - /* Flush data in write buffer so that DMA can get the latest data */ - asm volatile("dsb;"); - - /* Fire it up */ - chan->ctrl |= MEC1322_DMA_RUN; -} - -void dma_prepare_tx(const struct dma_option *option, unsigned count, - const void *memory) -{ - mec1322_dma_chan_t *chan = dma_get_channel(option->channel); - - /* - * Cast away const for memory pointer; this is ok because we know - * we're preparing the channel for transmit. - */ - prepare_channel(chan, count, option->periph, (void *)memory, - MEC1322_DMA_INC_MEM | MEC1322_DMA_TO_DEV | - MEC1322_DMA_DEV(option->channel) | option->flags); -} - -void dma_start_rx(const struct dma_option *option, unsigned count, - void *memory) -{ - mec1322_dma_chan_t *chan; - - chan = dma_get_channel(option->channel); - - prepare_channel(chan, count, option->periph, memory, - MEC1322_DMA_INC_MEM | MEC1322_DMA_DEV(option->channel) | - option->flags); - dma_go(chan); -} - -int dma_bytes_done(mec1322_dma_chan_t *chan, int orig_count) -{ - int xfer_size = (chan->ctrl >> 20) & 0x7; - - return orig_count - (chan->mem_end - chan->mem_start) / xfer_size; -} - -bool dma_is_enabled(mec1322_dma_chan_t *chan) -{ - return (chan->ctrl & MEC1322_DMA_RUN); -} - -void dma_init(void) -{ - mec1322_dma_regs_t *dma = MEC1322_DMA_REGS; - dma->ctrl |= 0x1; -} - -int dma_wait(enum dma_channel channel) -{ - mec1322_dma_chan_t *chan = dma_get_channel(channel); - timestamp_t deadline; - - if (chan->act == 0) - return EC_SUCCESS; - - deadline.val = get_time().val + DMA_TRANSFER_TIMEOUT_US; - while (!(chan->int_status & 0x4)) { - if (deadline.val <= get_time().val) - return EC_ERROR_TIMEOUT; - - udelay(DMA_POLLING_INTERVAL_US); - } - return EC_SUCCESS; -} - -void dma_clear_isr(enum dma_channel channel) -{ - mec1322_dma_chan_t *chan = dma_get_channel(channel); - - chan->int_status |= 0x4; -} diff --git a/chip/mec1322/fan.c b/chip/mec1322/fan.c deleted file mode 100644 index 1f54389fc7..0000000000 --- a/chip/mec1322/fan.c +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* MEC1322 fan control module. */ - -/* This assumes 2-pole fan. For each rotation, 5 edges are measured. */ - -#include "fan.h" -#include "registers.h" -#include "util.h" - -/* Maximum tach reading/target value */ -#define MAX_TACH 0x1fff - -/* Tach target value for disable fan */ -#define FAN_OFF_TACH 0xfff8 - -/* - * RPM = (n - 1) * m * f * 60 / poles / TACH - * n = number of edges = 5 - * m = multiplier defined by RANGE = 2 in our case - * f = 32.768K - * poles = 2 - */ -#define RPM_TO_TACH(rpm) MIN((7864320 / MAX((rpm), 1)), MAX_TACH) -#define TACH_TO_RPM(tach) (7864320 / MAX((tach), 1)) - -static int rpm_setting; -static int duty_setting; -static int in_rpm_mode = 1; - - -static void clear_status(void) -{ - /* Clear DRIVE_FAIL, FAN_SPIN, and FAN_STALL bits */ - MEC1322_FAN_STATUS = 0x23; -} - -void fan_set_enabled(int ch, int enabled) -{ - if (in_rpm_mode) { - if (enabled) - fan_set_rpm_target(ch, rpm_setting); - else - MEC1322_FAN_TARGET = FAN_OFF_TACH; - } else { - if (enabled) - fan_set_duty(ch, duty_setting); - else - MEC1322_FAN_SETTING = 0; - } - clear_status(); -} - -int fan_get_enabled(int ch) -{ - if (in_rpm_mode) - return (MEC1322_FAN_TARGET & 0xff00) != 0xff00; - else - return !!MEC1322_FAN_SETTING; -} - -void fan_set_duty(int ch, int percent) -{ - if (percent < 0) - percent = 0; - else if (percent > 100) - percent = 100; - - duty_setting = percent; - MEC1322_FAN_SETTING = percent * 255 / 100; - clear_status(); -} - -int fan_get_duty(int ch) -{ - return duty_setting; -} - -int fan_get_rpm_mode(int ch) -{ - return !!(MEC1322_FAN_CFG1 & BIT(7)); -} - -void fan_set_rpm_mode(int ch, int rpm_mode) -{ - if (rpm_mode) - MEC1322_FAN_CFG1 |= BIT(7); - else - MEC1322_FAN_CFG1 &= ~BIT(7); - clear_status(); -} - -int fan_get_rpm_actual(int ch) -{ - if ((MEC1322_FAN_READING >> 8) == 0xff) - return 0; - else - return TACH_TO_RPM(MEC1322_FAN_READING >> 3); -} - -int fan_get_rpm_target(int ch) -{ - return rpm_setting; -} - -void fan_set_rpm_target(int ch, int rpm) -{ - rpm_setting = rpm; - MEC1322_FAN_TARGET = RPM_TO_TACH(rpm) << 3; - clear_status(); -} - -enum fan_status fan_get_status(int ch) -{ - uint8_t sts = MEC1322_FAN_STATUS; - - if (sts & (BIT(5) | BIT(1))) - return FAN_STATUS_FRUSTRATED; - if (fan_get_rpm_actual(ch) == 0) - return FAN_STATUS_STOPPED; - return FAN_STATUS_LOCKED; -} - -int fan_is_stalled(int ch) -{ - uint8_t sts = MEC1322_FAN_STATUS; - if (fan_get_rpm_actual(ch)) { - MEC1322_FAN_STATUS = 0x1; - return 0; - } - return sts & 0x1; -} - -void fan_channel_setup(int ch, unsigned int flags) -{ - /* - * Fan configuration 1 register: - * 0x80 = bit 7 = RPM mode (0x00 if FAN_USE_RPM_MODE not set) - * 0x20 = bits 6:5 = min 1000 RPM, multiplier = 2 - * 0x08 = bits 4:3 = 5 edges, 2 poles - * 0x03 = bits 2:0 = 400 ms update time - * - * Fan configuration 2 register: - * 0x00 = bit 6 = Ramp control disabled - * 0x00 = bit 5 = Glitch filter enabled - * 0x18 = bits 4:3 = Using both derivative options - * 0x02 = bits 2:1 = error range is 50 RPM - * 0x00 = bits 0 = normal polarity - */ - if (flags & FAN_USE_RPM_MODE) - MEC1322_FAN_CFG1 = 0xab; - else - MEC1322_FAN_CFG1 = 0x2b; - MEC1322_FAN_CFG2 = 0x1a; - clear_status(); -} diff --git a/chip/mec1322/flash.c b/chip/mec1322/flash.c deleted file mode 100644 index b6ab76113b..0000000000 --- a/chip/mec1322/flash.c +++ /dev/null @@ -1,268 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "console.h" -#include "flash.h" -#include "host_command.h" -#include "shared_mem.h" -#include "spi.h" -#include "spi_flash.h" -#include "system.h" -#include "util.h" -#include "hooks.h" - -#define PAGE_SIZE 256 - -#define FLASH_SYSJUMP_TAG 0x5750 /* "WP" - Write Protect */ -#define FLASH_HOOK_VERSION 1 - -static int entire_flash_locked; - -/* The previous write protect state before sys jump */ - -struct flash_wp_state { - int entire_flash_locked; -}; - -/** - * Read from physical flash. - * - * @param offset Flash offset to write. - * @param size Number of bytes to write. - * @param data Destination buffer for data. - */ -int flash_physical_read(int offset, int size, char *data) -{ - return spi_flash_read(data, offset, size); -} - -/** - * Write to physical flash. - * - * Offset and size must be a multiple of CONFIG_FLASH_WRITE_SIZE. - * - * @param offset Flash offset to write. - * @param size Number of bytes to write. - * @param data Data to write to flash. Must be 32-bit aligned. - */ -int flash_physical_write(int offset, int size, const char *data) -{ - int ret = EC_SUCCESS; - int i, write_size; - - if (entire_flash_locked) - return EC_ERROR_ACCESS_DENIED; - - /* Fail if offset, size, and data aren't at least word-aligned */ - if ((offset | size | (uint32_t)(uintptr_t)data) & 3) - return EC_ERROR_INVAL; - - for (i = 0; i < size; i += write_size) { - write_size = MIN((size - i), SPI_FLASH_MAX_WRITE_SIZE); - ret = spi_flash_write(offset + i, - write_size, - (uint8_t *)data + i); - if (ret != EC_SUCCESS) - break; - } - return ret; -} - -/** - * Erase physical flash. - * - * Offset and size must be a multiple of CONFIG_FLASH_ERASE_SIZE. - * - * @param offset Flash offset to erase. - * @param size Number of bytes to erase. - */ -int flash_physical_erase(int offset, int size) -{ - int ret; - - if (entire_flash_locked) - return EC_ERROR_ACCESS_DENIED; - - ret = spi_flash_erase(offset, size); - return ret; -} - -/** - * Read physical write protect setting for a flash bank. - * - * @param bank Bank index to check. - * @return non-zero if bank is protected until reboot. - */ -int flash_physical_get_protect(int bank) -{ - return spi_flash_check_protect(bank * CONFIG_FLASH_BANK_SIZE, - CONFIG_FLASH_BANK_SIZE); -} - -/** - * Protect flash now. - * - * This is always successful, and only emulates "now" protection - * - * @param all Protect all (=1) or just read-only - * @return non-zero if error. - */ -int flash_physical_protect_now(int all) -{ - if (all) - entire_flash_locked = 1; - - /* - * RO "now" protection is not currently implemented. If needed, it - * can be added by splitting the entire_flash_locked variable into - * and RO and RW vars, and setting + checking the appropriate var - * as required. - */ - return EC_SUCCESS; -} - -/** - * Return flash protect state flags from the physical layer. - * - * This should only be called by flash_get_protect(). - * - * Uses the EC_FLASH_PROTECT_* flags from ec_commands.h - */ -uint32_t flash_physical_get_protect_flags(void) -{ - uint32_t flags = 0; - - if (spi_flash_check_protect(CONFIG_WP_STORAGE_OFF, - CONFIG_WP_STORAGE_SIZE)) { - flags |= EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW; - } - - if (entire_flash_locked) - flags |= EC_FLASH_PROTECT_ALL_NOW; - - return flags; -} - -/** - * Return the valid flash protect flags. - * - * @return A combination of EC_FLASH_PROTECT_* flags from ec_commands.h - */ -uint32_t flash_physical_get_valid_flags(void) -{ - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | - EC_FLASH_PROTECT_ALL_NOW; -} - -/** - * Return the writable flash protect flags. - * - * @param cur_flags The current flash protect flags. - * @return A combination of EC_FLASH_PROTECT_* flags from ec_commands.h - */ -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) -{ - uint32_t ret = 0; - enum spi_flash_wp wp_status = SPI_WP_NONE; - - wp_status = spi_flash_check_wp(); - - if (wp_status == SPI_WP_NONE || (wp_status == SPI_WP_HARDWARE && - !(cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED))) - ret = EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW; - - if (!entire_flash_locked) - ret |= EC_FLASH_PROTECT_ALL_NOW; - - return ret; -} - -/** - * Enable write protect for the specified range. - * - * Once write protect is enabled, it will stay enabled until HW PIN is - * de-asserted and SRP register is unset. - * - * However, this implementation treats EC_FLASH_PROTECT_ALL_AT_BOOT as - * EC_FLASH_PROTECT_RO_AT_BOOT but tries to remember if "all" region - * is protected. - * - * @param new_flags to protect (only EC_FLASH_PROTECT_*_AT_BOOT are - * taken care of) - * @return EC_SUCCESS, or nonzero if error. - */ -int flash_physical_protect_at_boot(uint32_t new_flags) -{ - int offset, size, ret; - enum spi_flash_wp flashwp = SPI_WP_NONE; - - if ((new_flags & (EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_ALL_AT_BOOT)) == 0) { - /* Clear protection */ - offset = size = 0; - flashwp = SPI_WP_NONE; - } else { - if (new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT) - entire_flash_locked = 1; - - offset = CONFIG_WP_STORAGE_OFF; - size = CONFIG_WP_STORAGE_SIZE; - flashwp = SPI_WP_HARDWARE; - } - - ret = spi_flash_set_protect(offset, size); - if (ret == EC_SUCCESS) - ret = spi_flash_set_wp(flashwp); - return ret; -} - -/** - * Initialize the module. - * - * Applies at-boot protection settings if necessary. - */ -int flash_pre_init(void) -{ - flash_physical_restore_state(); - return EC_SUCCESS; -} - -int flash_physical_restore_state(void) -{ - uint32_t reset_flags = system_get_reset_flags(); - int version, size; - const struct flash_wp_state *prev; - - /* - * If we have already jumped between images, an earlier image could - * have applied write protection. Nothing additional needs to be done. - */ - if (reset_flags & EC_RESET_FLAG_SYSJUMP) { - prev = (const struct flash_wp_state *)system_get_jump_tag( - FLASH_SYSJUMP_TAG, &version, &size); - if (prev && version == FLASH_HOOK_VERSION && - size == sizeof(*prev)) - entire_flash_locked = prev->entire_flash_locked; - return 1; - } - - return 0; -} - -/*****************************************************************************/ -/* Hooks */ - -static void flash_preserve_state(void) -{ - struct flash_wp_state state; - - state.entire_flash_locked = entire_flash_locked; - - system_add_jump_tag(FLASH_SYSJUMP_TAG, FLASH_HOOK_VERSION, - sizeof(state), &state); -} -DECLARE_HOOK(HOOK_SYSJUMP, flash_preserve_state, HOOK_PRIO_DEFAULT); diff --git a/chip/mec1322/gpio.c b/chip/mec1322/gpio.c deleted file mode 100644 index 331022c87c..0000000000 --- a/chip/mec1322/gpio.c +++ /dev/null @@ -1,291 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* GPIO module for MEC1322 */ - -#include "common.h" -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -struct gpio_int_mapping { - int8_t girq_id; - int8_t port_offset; -}; - -/* Mapping from GPIO port to GIRQ info */ -static const struct gpio_int_mapping int_map[22] = { - {11, 0}, {11, 0}, {11, 0}, {11, 0}, - {10, 4}, {10, 4}, {10, 4}, {-1, -1}, - {-1, -1}, {-1, -1}, {9, 10}, {9, 10}, - {9, 10}, {9, 10}, {8, 14}, {8, 14}, - {8, 14}, {-1, -1}, {-1, -1}, {-1, -1}, - {20, 20}, {20, 20} -}; - -void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) -{ - int i; - uint32_t val; - - while (mask) { - i = __builtin_ffs(mask) - 1; - val = MEC1322_GPIO_CTL(port, i); - val &= ~(BIT(12) | BIT(13)); - /* mux_control = DEFAULT, indicates GPIO */ - if (func > GPIO_ALT_FUNC_DEFAULT) - val |= (func & 0x3) << 12; - MEC1322_GPIO_CTL(port, i) = val; - mask &= ~BIT(i); - } -} - -test_mockable int gpio_get_level(enum gpio_signal signal) -{ - uint32_t mask = gpio_list[signal].mask; - int i; - uint32_t val; - - if (mask == 0) - return 0; - i = GPIO_MASK_TO_NUM(mask); - val = MEC1322_GPIO_CTL(gpio_list[signal].port, i); - - return (val & BIT(24)) ? 1 : 0; -} - -void gpio_set_level(enum gpio_signal signal, int value) -{ - uint32_t mask = gpio_list[signal].mask; - int i; - - if (mask == 0) - return; - i = GPIO_MASK_TO_NUM(mask); - - if (value) - MEC1322_GPIO_CTL(gpio_list[signal].port, i) |= BIT(16); - else - MEC1322_GPIO_CTL(gpio_list[signal].port, i) &= ~BIT(16); -} - -void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) -{ - int i; - uint32_t val; - while (mask) { - i = GPIO_MASK_TO_NUM(mask); - mask &= ~BIT(i); - val = MEC1322_GPIO_CTL(port, i); - - /* - * Select open drain first, so that we don't glitch the signal - * when changing the line to an output. - */ - if (flags & GPIO_OPEN_DRAIN) - val |= BIT(8); - else - val &= ~BIT(8); - - if (flags & GPIO_OUTPUT) { - val |= BIT(9); - val &= ~BIT(10); - } else { - val &= ~BIT(9); - val |= BIT(10); - } - - /* Handle pullup / pulldown */ - if (flags & GPIO_PULL_UP) - val = (val & ~0x3) | 0x1; - else if (flags & GPIO_PULL_DOWN) - val = (val & ~0x3) | 0x2; - else - val &= ~0x3; - - /* Set up interrupt */ - if (flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING)) - val |= BIT(7); - else - val &= ~BIT(7); - - val &= ~(0x7 << 4); - - if ((flags & GPIO_INT_F_RISING) && (flags & GPIO_INT_F_FALLING)) - val |= 0x7 << 4; - else if (flags & GPIO_INT_F_RISING) - val |= 0x5 << 4; - else if (flags & GPIO_INT_F_FALLING) - val |= 0x6 << 4; - else if (flags & GPIO_INT_F_HIGH) - val |= 0x1 << 4; - else if (!(flags & GPIO_INT_F_LOW)) /* No interrupt flag set */ - val |= 0x4 << 4; - - /* Set up level */ - if (flags & GPIO_HIGH) - val |= BIT(16); - else if (flags & GPIO_LOW) - val &= ~BIT(16); - - MEC1322_GPIO_CTL(port, i) = val; - } -} - -int gpio_enable_interrupt(enum gpio_signal signal) -{ - int i, port, girq_id, bit_id; - - if (gpio_list[signal].mask == 0) - return EC_SUCCESS; - - i = GPIO_MASK_TO_NUM(gpio_list[signal].mask); - port = gpio_list[signal].port; - girq_id = int_map[port].girq_id; - bit_id = (port - int_map[port].port_offset) * 8 + i; - - MEC1322_INT_ENABLE(girq_id) |= BIT(bit_id); - MEC1322_INT_BLK_EN |= BIT(girq_id); - - return EC_SUCCESS; -} - -int gpio_disable_interrupt(enum gpio_signal signal) -{ - int i, port, girq_id, bit_id; - - if (gpio_list[signal].mask == 0) - return EC_SUCCESS; - - i = GPIO_MASK_TO_NUM(gpio_list[signal].mask); - port = gpio_list[signal].port; - girq_id = int_map[port].girq_id; - bit_id = (port - int_map[port].port_offset) * 8 + i; - - MEC1322_INT_DISABLE(girq_id) = BIT(bit_id); - - return EC_SUCCESS; -} - -int gpio_clear_pending_interrupt(enum gpio_signal signal) -{ - int i, port, girq_id, bit_id; - - if (gpio_list[signal].mask == 0) - return EC_SUCCESS; - - i = GPIO_MASK_TO_NUM(gpio_list[signal].mask); - port = gpio_list[signal].port; - girq_id = int_map[port].girq_id; - bit_id = (port - int_map[port].port_offset) * 8 + i; - - /* Clear interrupt source sticky status bit even if not enabled */ - MEC1322_INT_SOURCE(girq_id) |= 1 << bit_id; - - return EC_SUCCESS; -} - -void gpio_pre_init(void) -{ - int i; - int flags; - int is_warm = system_is_reboot_warm(); - const struct gpio_info *g = gpio_list; - - - for (i = 0; i < GPIO_COUNT; i++, g++) { - flags = g->flags; - - if (flags & GPIO_DEFAULT) - continue; - - /* - * If this is a warm reboot, don't set the output levels or - * we'll shut off the AP. - */ - if (is_warm) - flags &= ~(GPIO_LOW | GPIO_HIGH); - - gpio_set_flags_by_mask(g->port, g->mask, flags); - - /* Use as GPIO, not alternate function */ - gpio_set_alternate_function(g->port, g->mask, - GPIO_ALT_FUNC_NONE); - } -} - -/* Clear any interrupt flags before enabling GPIO interrupt */ -#define ENABLE_GPIO_GIRQ(x) \ - do { \ - MEC1322_INT_SOURCE(x) |= MEC1322_INT_RESULT(x); \ - task_enable_irq(MEC1322_IRQ_GIRQ ## x); \ - } while (0) - -static void gpio_init(void) -{ - ENABLE_GPIO_GIRQ(8); - ENABLE_GPIO_GIRQ(9); - ENABLE_GPIO_GIRQ(10); - ENABLE_GPIO_GIRQ(11); - ENABLE_GPIO_GIRQ(20); -} -DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); - -/*****************************************************************************/ -/* Interrupt handlers */ - - -/** - * Handler for each GIRQ interrupt. This reads and clears the interrupt bits for - * the GIRQ interrupt, then finds and calls the corresponding GPIO interrupt - * handlers. - * - * @param girq GIRQ index - * @param port_offset GPIO port offset for the given GIRQ - */ -static void gpio_interrupt(int girq, int port_offset) -{ - int i, bit; - const struct gpio_info *g = gpio_list; - uint32_t sts = MEC1322_INT_RESULT(girq); - - MEC1322_INT_SOURCE(girq) |= sts; - - for (i = 0; i < GPIO_IH_COUNT && sts; ++i, ++g) { - bit = (g->port - port_offset) * 8 + __builtin_ffs(g->mask) - 1; - if (sts & BIT(bit)) - gpio_irq_handlers[i](i); - sts &= ~BIT(bit); - } -} - -#define GPIO_IRQ_FUNC(irqfunc, girq, port_offset) \ - void irqfunc(void) \ - { \ - gpio_interrupt(girq, port_offset); \ - } - -GPIO_IRQ_FUNC(__girq_8_interrupt, 8, 14); -GPIO_IRQ_FUNC(__girq_9_interrupt, 9, 10); -GPIO_IRQ_FUNC(__girq_10_interrupt, 10, 4); -GPIO_IRQ_FUNC(__girq_11_interrupt, 11, 0); -GPIO_IRQ_FUNC(__girq_20_interrupt, 20, 20); - -#undef GPIO_IRQ_FUNC - -/* - * Declare IRQs. Nesting this macro inside the GPIO_IRQ_FUNC macro works - * poorly because DECLARE_IRQ() stringizes its inputs. - */ -DECLARE_IRQ(MEC1322_IRQ_GIRQ8, __girq_8_interrupt, 1); -DECLARE_IRQ(MEC1322_IRQ_GIRQ9, __girq_9_interrupt, 1); -DECLARE_IRQ(MEC1322_IRQ_GIRQ10, __girq_10_interrupt, 1); -DECLARE_IRQ(MEC1322_IRQ_GIRQ11, __girq_11_interrupt, 1); -DECLARE_IRQ(MEC1322_IRQ_GIRQ20, __girq_20_interrupt, 1); diff --git a/chip/mec1322/hwtimer.c b/chip/mec1322/hwtimer.c deleted file mode 100644 index a5c5858620..0000000000 --- a/chip/mec1322/hwtimer.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Hardware timers driver */ - -#include "clock.h" -#include "common.h" -#include "hooks.h" -#include "hwtimer.h" -#include "registers.h" -#include "task.h" -#include "timer.h" - -void __hw_clock_event_set(uint32_t deadline) -{ - MEC1322_TMR32_CNT(1) = MEC1322_TMR32_CNT(0) - - (0xffffffff - deadline); - MEC1322_TMR32_CTL(1) |= BIT(5); -} - -uint32_t __hw_clock_event_get(void) -{ - return MEC1322_TMR32_CNT(1) - MEC1322_TMR32_CNT(0) + 0xffffffff; -} - -void __hw_clock_event_clear(void) -{ - MEC1322_TMR32_CTL(1) &= ~BIT(5); -} - -uint32_t __hw_clock_source_read(void) -{ - return 0xffffffff - MEC1322_TMR32_CNT(0); -} - -void __hw_clock_source_set(uint32_t ts) -{ - MEC1322_TMR32_CTL(0) &= ~BIT(5); - MEC1322_TMR32_CNT(0) = 0xffffffff - ts; - MEC1322_TMR32_CTL(0) |= BIT(5); -} - -static void __hw_clock_source_irq(int timer_id) -{ - if (timer_id == 1) - MEC1322_TMR32_STS(1) |= 1; - /* If IRQ is from timer 0, 32-bit timer overflowed */ - process_timers(timer_id == 0); -} - -void __hw_clock_source_irq_0(void) { __hw_clock_source_irq(0); } -DECLARE_IRQ(MEC1322_IRQ_TIMER32_0, __hw_clock_source_irq_0, 1); -void __hw_clock_source_irq_1(void) { __hw_clock_source_irq(1); } -DECLARE_IRQ(MEC1322_IRQ_TIMER32_1, __hw_clock_source_irq_1, 1); - -static void configure_timer(int timer_id) -{ - uint32_t val; - - /* Ensure timer is not running */ - MEC1322_TMR32_CTL(timer_id) &= ~BIT(5); - - /* Enable timer */ - MEC1322_TMR32_CTL(timer_id) |= BIT(0); - - val = MEC1322_TMR32_CTL(timer_id); - - /* Pre-scale = 48 -> 1MHz -> Period = 1us */ - val = (val & 0xffff) | (47 << 16); - - MEC1322_TMR32_CTL(timer_id) = val; - - /* Set preload to use the full 32 bits of the timer */ - MEC1322_TMR32_PRE(timer_id) = 0xffffffff; - - /* Enable interrupt */ - MEC1322_TMR32_IEN(timer_id) |= 1; -} - -int __hw_clock_source_init(uint32_t start_t) -{ - /* - * The timer can only fire interrupt when its value reaches zero. - * Therefore we need two timers: - * - Timer 0 as free running timer - * - Timer 1 as event timer - */ - configure_timer(0); - configure_timer(1); - - /* Override the count */ - MEC1322_TMR32_CNT(0) = 0xffffffff - start_t; - - /* Auto restart */ - MEC1322_TMR32_CTL(0) |= BIT(3); - - /* Start counting in timer 0 */ - MEC1322_TMR32_CTL(0) |= BIT(5); - - /* Enable interrupt */ - task_enable_irq(MEC1322_IRQ_TIMER32_0); - task_enable_irq(MEC1322_IRQ_TIMER32_1); - MEC1322_INT_ENABLE(23) |= BIT(4) | BIT(5); - MEC1322_INT_BLK_EN |= BIT(23); - - return MEC1322_IRQ_TIMER32_1; -} diff --git a/chip/mec1322/i2c.c b/chip/mec1322/i2c.c deleted file mode 100644 index 69344d8390..0000000000 --- a/chip/mec1322/i2c.c +++ /dev/null @@ -1,531 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* I2C port module for MEC1322 */ - -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) - -#define I2C_CLOCK 16000000 /* 16 MHz */ - -/* Status */ -#define STS_NBB BIT(0) /* Bus busy */ -#define STS_LAB BIT(1) /* Arbitration lost */ -#define STS_LRB BIT(3) /* Last received bit */ -#define STS_BER BIT(4) /* Bus error */ -#define STS_PIN BIT(7) /* Pending interrupt */ - -/* Control */ -#define CTRL_ACK BIT(0) /* Acknowledge */ -#define CTRL_STO BIT(1) /* STOP */ -#define CTRL_STA BIT(2) /* START */ -#define CTRL_ENI BIT(3) /* Enable interrupt */ -#define CTRL_ESO BIT(6) /* Enable serial output */ -#define CTRL_PIN BIT(7) /* Pending interrupt not */ - -/* Completion */ -#define COMP_IDLE BIT(29) /* i2c bus is idle */ -#define COMP_RW_BITS_MASK 0x3C /* R/W bits mask */ - -/* Maximum transfer of a SMBUS block transfer */ -#define SMBUS_MAX_BLOCK_SIZE 32 - -/* - * Amount of time to blocking wait for i2c bus to finish. After this blocking - * timeout, if the bus is still not finished, then allow other tasks to run. - * Note: this is just long enough for a 400kHz bus to finish transmitting one - * byte assuming the bus isn't being held. - */ -#define I2C_WAIT_BLOCKING_TIMEOUT_US 25 - -enum i2c_transaction_state { - /* Stop condition was sent in previous transaction */ - I2C_TRANSACTION_STOPPED, - /* Stop condition was not sent in previous transaction */ - I2C_TRANSACTION_OPEN, -}; - -/* I2C controller state data */ -static struct { - /* Transaction timeout, or 0 to use default. */ - uint32_t timeout_us; - /* Task waiting on port, or TASK_ID_INVALID if none. */ - volatile task_id_t task_waiting; - enum i2c_transaction_state transaction_state; -} cdata[I2C_CONTROLLER_COUNT]; - -/* Map port number to port name in datasheet, for debug prints. */ -static const char *i2c_port_names[MEC1322_I2C_PORT_COUNT] = { - [MEC1322_I2C0_0] = "0_0", - [MEC1322_I2C0_1] = "0_1", - [MEC1322_I2C1] = "1", - [MEC1322_I2C2] = "2", - [MEC1322_I2C3] = "3", -}; - -static void configure_controller_speed(int controller, int kbps) -{ - int t_low, t_high; - const int period = I2C_CLOCK / 1000 / kbps; - - /* - * Refer to NXP UM10204 for minimum timing requirement of T_Low and - * T_High. - * http://www.nxp.com/documents/user_manual/UM10204.pdf - */ - if (kbps > 400) { - /* Fast mode plus */ - t_low = t_high = period / 2 - 1; - MEC1322_I2C_DATA_TIM(controller) = 0x06060601; - MEC1322_I2C_DATA_TIM_2(controller) = 0x06; - } else if (kbps > 100) { - /* Fast mode */ - /* By spec, clk low period is 1.3us min */ - t_low = MAX((int)(I2C_CLOCK * 1.3 / 1000000), period / 2 - 1); - t_high = period - t_low - 2; - MEC1322_I2C_DATA_TIM(controller) = 0x040a0a01; - MEC1322_I2C_DATA_TIM_2(controller) = 0x0a; - } else { - /* Standard mode */ - t_low = t_high = period / 2 - 1; - MEC1322_I2C_DATA_TIM(controller) = 0x0c4d5006; - MEC1322_I2C_DATA_TIM_2(controller) = 0x4d; - } - - /* Clock periods is one greater than the contents of these fields */ - MEC1322_I2C_BUS_CLK(controller) = ((t_high & 0xff) << 8) | - (t_low & 0xff); -} - -static void configure_controller(int controller, int kbps) -{ - MEC1322_I2C_CTRL(controller) = CTRL_PIN; - MEC1322_I2C_OWN_ADDR(controller) = 0x0; - configure_controller_speed(controller, kbps); - MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | - CTRL_ACK | CTRL_ENI; - MEC1322_I2C_CONFIG(controller) |= BIT(10); /* ENAB */ - - /* Enable interrupt */ - MEC1322_I2C_CONFIG(controller) |= BIT(29); /* ENIDI */ - MEC1322_INT_ENABLE(12) |= BIT(controller); - MEC1322_INT_BLK_EN |= BIT(12); -} - -static void reset_controller(int controller) -{ - int i; - - MEC1322_I2C_CONFIG(controller) |= BIT(9); - udelay(100); - MEC1322_I2C_CONFIG(controller) &= ~BIT(9); - - for (i = 0; i < i2c_ports_used; ++i) - if (controller == i2c_port_to_controller(i2c_ports[i].port)) { - configure_controller(controller, i2c_ports[i].kbps); - cdata[controller].transaction_state = - I2C_TRANSACTION_STOPPED; - break; - } -} - -static int wait_for_interrupt(int controller, int timeout) -{ - int event; - - if (timeout <= 0) - return EC_ERROR_TIMEOUT; - - cdata[controller].task_waiting = task_get_current(); - task_enable_irq(MEC1322_IRQ_I2C_0 + controller); - - /* Wait until I2C interrupt or timeout. */ - event = task_wait_event_mask(TASK_EVENT_I2C_IDLE, timeout); - - task_disable_irq(MEC1322_IRQ_I2C_0 + controller); - cdata[controller].task_waiting = TASK_ID_INVALID; - - return (event & TASK_EVENT_TIMER) ? EC_ERROR_TIMEOUT : EC_SUCCESS; -} - -static int wait_idle(int controller) -{ - uint8_t sts = MEC1322_I2C_STATUS(controller); - uint64_t block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; - uint64_t task_timeout = block_timeout + cdata[controller].timeout_us; - int rv = 0; - - while (!(sts & STS_NBB)) { - if (rv) - return rv; - if (get_time().val > block_timeout) - rv = wait_for_interrupt(controller, - task_timeout - get_time().val); - sts = MEC1322_I2C_STATUS(controller); - } - - if (sts & (STS_BER | STS_LAB)) - return EC_ERROR_UNKNOWN; - return EC_SUCCESS; -} - -static int wait_byte_done(int controller) -{ - uint8_t sts = MEC1322_I2C_STATUS(controller); - uint64_t block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; - uint64_t task_timeout = block_timeout + cdata[controller].timeout_us; - int rv = 0; - - while (sts & STS_PIN) { - if (rv) - return rv; - if (get_time().val > block_timeout) - rv = wait_for_interrupt(controller, - task_timeout - get_time().val); - sts = MEC1322_I2C_STATUS(controller); - } - - return sts & STS_LRB; -} - -static void select_port(int port) -{ - /* - * I2C0_1 uses port 1 of controller 0. All other I2C pin sets - * use port 0. - */ - uint8_t port_sel = (port == MEC1322_I2C0_1) ? 1 : 0; - int controller = i2c_port_to_controller(port); - - MEC1322_I2C_CONFIG(controller) &= ~0xf; - MEC1322_I2C_CONFIG(controller) |= port_sel; - -} - -static inline int get_line_level(int controller) -{ - int ret, ctrl; - /* - * We need to enable BB (Bit Bang) mode in order to read line level - * properly, othervise line levels return always idle (0x60). - */ - ctrl = MEC1322_I2C_BB_CTRL(controller); - MEC1322_I2C_BB_CTRL(controller) |= 1; - ret = (MEC1322_I2C_BB_CTRL(controller) >> 5) & 0x3; - MEC1322_I2C_BB_CTRL(controller) = ctrl; - return ret; -} - -static inline void push_in_buf(uint8_t **in, uint8_t val, int skip) -{ - if (!skip) { - **in = val; - (*in)++; - } -} - -int chip_i2c_xfer(const int port, - const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) -{ - int i; - int controller; - int send_start = flags & I2C_XFER_START; - int send_stop = flags & I2C_XFER_STOP; - int skip = 0; - int bytes_to_read; - uint8_t reg; - int ret_done; - - if (out_size == 0 && in_size == 0) - return EC_SUCCESS; - - select_port(port); - controller = i2c_port_to_controller(port); - if (send_start && - cdata[controller].transaction_state == I2C_TRANSACTION_STOPPED) - wait_idle(controller); - - reg = MEC1322_I2C_STATUS(controller); - if (send_start && - cdata[controller].transaction_state == I2C_TRANSACTION_STOPPED && - (((reg & (STS_BER | STS_LAB)) || !(reg & STS_NBB)) || - (get_line_level(controller) - != I2C_LINE_IDLE))) { - CPRINTS("i2c%s bad status 0x%02x, SCL=%d, SDA=%d", - i2c_port_names[port], reg, - get_line_level(controller) & I2C_LINE_SCL_HIGH, - get_line_level(controller) & I2C_LINE_SDA_HIGH); - - /* Attempt to unwedge the port. */ - i2c_unwedge(port); - - /* Bus error, bus busy, or arbitration lost. Try reset. */ - reset_controller(controller); - select_port(port); - - /* - * We don't know what edges the slave saw, so sleep long enough - * that the slave will see the new start condition below. - */ - usleep(1000); - } - - if (out_size) { - if (send_start) { - MEC1322_I2C_DATA(controller) = - (uint8_t)(I2C_GET_ADDR(slave_addr_flags) - << 1); - - /* Clock out the slave address, sending START bit */ - MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | - CTRL_ENI | CTRL_ACK | - CTRL_STA; - cdata[controller].transaction_state = - I2C_TRANSACTION_OPEN; - } - - for (i = 0; i < out_size; ++i) { - ret_done = wait_byte_done(controller); - if (ret_done) - goto err_chip_i2c_xfer; - MEC1322_I2C_DATA(controller) = out[i]; - } - ret_done = wait_byte_done(controller); - if (ret_done) - goto err_chip_i2c_xfer; - - /* - * Send STOP bit if the stop flag is on, and caller - * doesn't expect to receive data. - */ - if (send_stop && in_size == 0) { - MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; - cdata[controller].transaction_state = - I2C_TRANSACTION_STOPPED; - } - } - - if (in_size) { - /* Resend start bit when changing direction */ - if (out_size || send_start) { - /* Repeated start case */ - if (cdata[controller].transaction_state == - I2C_TRANSACTION_OPEN) - MEC1322_I2C_CTRL(controller) = CTRL_ESO | - CTRL_STA | - CTRL_ACK | - CTRL_ENI; - - MEC1322_I2C_DATA(controller) = - (uint8_t)(I2C_GET_ADDR(slave_addr_flags) - << 1) - | 0x01; - - /* New transaction case, clock out slave address. */ - if (cdata[controller].transaction_state == - I2C_TRANSACTION_STOPPED) - MEC1322_I2C_CTRL(controller) = CTRL_ESO | - CTRL_STA | - CTRL_ACK | - CTRL_ENI | - CTRL_PIN; - - cdata[controller].transaction_state = - I2C_TRANSACTION_OPEN; - - /* Skip over the unused byte */ - skip = 1; - in_size++; - } - - /* Special flags need to be set for last two bytes */ - bytes_to_read = send_stop ? in_size - 2 : in_size; - - for (i = 0; i < bytes_to_read; ++i) { - ret_done = wait_byte_done(controller); - if (ret_done) - goto err_chip_i2c_xfer; - push_in_buf(&in, MEC1322_I2C_DATA(controller), skip); - skip = 0; - } - ret_done = wait_byte_done(controller); - if (ret_done) - goto err_chip_i2c_xfer; - - if (send_stop) { - /* - * De-assert ACK bit before reading the next to last - * byte, so that the last byte is NACK'ed. - */ - MEC1322_I2C_CTRL(controller) = CTRL_ESO | CTRL_ENI; - push_in_buf(&in, MEC1322_I2C_DATA(controller), skip); - ret_done = wait_byte_done(controller); - if (ret_done) - goto err_chip_i2c_xfer; - - /* Send STOP */ - MEC1322_I2C_CTRL(controller) = - CTRL_PIN | CTRL_ESO | CTRL_ACK | CTRL_STO; - - cdata[controller].transaction_state = - I2C_TRANSACTION_STOPPED; - - /* - * We need to know our stop point two bytes in - * advance. If we don't know soon enough, we need - * to do an extra read (to last_addr + 1) to - * issue the stop. - */ - push_in_buf(&in, MEC1322_I2C_DATA(controller), - in_size == 1); - } - } - - /* Check for error conditions */ - if (MEC1322_I2C_STATUS(controller) & (STS_LAB | STS_BER)) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -err_chip_i2c_xfer: - /* Send STOP and return error */ - MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; - cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; - if (ret_done == STS_LRB) - return EC_ERROR_BUSY; - else if (ret_done == EC_ERROR_TIMEOUT) { - /* - * If our transaction timed out then our i2c controller - * may be wedged without showing any other outward signs - * of failure. Reset the controller so that future - * transactions have a chance of success. - */ - reset_controller(controller); - return EC_ERROR_TIMEOUT; - } - else - return EC_ERROR_UNKNOWN; -} - -int i2c_raw_get_scl(int port) -{ - enum gpio_signal g; - - /* If no SCL pin defined for this port, then return 1 to appear idle. */ - if (get_scl_from_i2c_port(port, &g) != EC_SUCCESS) - return 1; - - return gpio_get_level(g); -} - -int i2c_raw_get_sda(int port) -{ - enum gpio_signal g; - - /* If no SDA pin defined for this port, then return 1 to appear idle. */ - if (get_sda_from_i2c_port(port, &g) != EC_SUCCESS) - return 1; - - return gpio_get_level(g); -} - -int i2c_get_line_levels(int port) -{ - int rv; - - i2c_lock(port, 1); - select_port(port); - rv = get_line_level(i2c_port_to_controller(port)); - i2c_lock(port, 0); - return rv; -} - -int i2c_port_to_controller(int port) -{ - if (port < 0 || port >= MEC1322_I2C_PORT_COUNT) - return -1; - return (port == MEC1322_I2C0_0) ? 0 : port - 1; -} - -void i2c_set_timeout(int port, uint32_t timeout) -{ - /* Param is port, but timeout is stored by-controller. */ - cdata[i2c_port_to_controller(port)].timeout_us = - timeout ? timeout : I2C_TIMEOUT_DEFAULT_US; -} - -void i2c_init(void) -{ - int i; - int controller; - int controller0_kbps = -1; - - /* Configure GPIOs */ - gpio_config_module(MODULE_I2C, 1); - - for (i = 0; i < i2c_ports_used; ++i) { - /* - * If this controller has multiple ports, check if we already - * configured it. If so, ensure previously configured bitrate - * matches. - */ - controller = i2c_port_to_controller(i2c_ports[i].port); - if (controller == 0) { - if (controller0_kbps != -1) { - ASSERT(controller0_kbps == i2c_ports[i].kbps); - continue; - } - controller0_kbps = i2c_ports[i].kbps; - } - configure_controller(controller, i2c_ports[i].kbps); - cdata[controller].task_waiting = TASK_ID_INVALID; - cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; - - /* Use default timeout. */ - i2c_set_timeout(i2c_ports[i].port, 0); - } -} - -static void handle_interrupt(int controller) -{ - int id = cdata[controller].task_waiting; - - /* Clear the interrupt status */ - MEC1322_I2C_COMPLETE(controller) &= (COMP_RW_BITS_MASK | COMP_IDLE); - - /* - * Write to control register interferes with I2C transaction. - * Instead, let's disable IRQ from the core until the next time - * we want to wait for STS_PIN/STS_NBB. - */ - task_disable_irq(MEC1322_IRQ_I2C_0 + controller); - - /* Wake up the task which was waiting on the I2C interrupt, if any. */ - if (id != TASK_ID_INVALID) - task_set_event(id, TASK_EVENT_I2C_IDLE, 0); -} - -void i2c0_interrupt(void) { handle_interrupt(0); } -void i2c1_interrupt(void) { handle_interrupt(1); } -void i2c2_interrupt(void) { handle_interrupt(2); } -void i2c3_interrupt(void) { handle_interrupt(3); } - -DECLARE_IRQ(MEC1322_IRQ_I2C_0, i2c0_interrupt, 2); -DECLARE_IRQ(MEC1322_IRQ_I2C_1, i2c1_interrupt, 2); -DECLARE_IRQ(MEC1322_IRQ_I2C_2, i2c2_interrupt, 2); -DECLARE_IRQ(MEC1322_IRQ_I2C_3, i2c3_interrupt, 2); diff --git a/chip/mec1322/keyboard_raw.c b/chip/mec1322/keyboard_raw.c deleted file mode 100644 index 2c62ada9ac..0000000000 --- a/chip/mec1322/keyboard_raw.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Raw keyboard I/O layer for MEC1322 - */ - -#include "gpio.h" -#include "keyboard_config.h" -#include "keyboard_raw.h" -#include "keyboard_scan.h" -#include "registers.h" -#include "task.h" -#include "util.h" - -void keyboard_raw_init(void) -{ - keyboard_raw_enable_interrupt(0); - gpio_config_module(MODULE_KEYBOARD_SCAN, 1); - - /* Enable keyboard scan interrupt */ - MEC1322_INT_ENABLE(17) |= BIT(21); - MEC1322_INT_BLK_EN |= BIT(17); - MEC1322_KS_KSI_INT_EN = 0xff; -} - -void keyboard_raw_task_start(void) -{ - task_enable_irq(MEC1322_IRQ_KSC_INT); -} - -test_mockable void keyboard_raw_drive_column(int out) -{ - if (out == KEYBOARD_COLUMN_ALL) { - MEC1322_KS_KSO_SEL = BIT(5); /* KSEN=0, KSALL=1 */ -#ifdef CONFIG_KEYBOARD_COL2_INVERTED - gpio_set_level(GPIO_KBD_KSO2, 1); -#endif - } else if (out == KEYBOARD_COLUMN_NONE) { - MEC1322_KS_KSO_SEL = BIT(6); /* KSEN=1 */ -#ifdef CONFIG_KEYBOARD_COL2_INVERTED - gpio_set_level(GPIO_KBD_KSO2, 0); -#endif - } else { -#ifdef CONFIG_KEYBOARD_COL2_INVERTED - if (out == 2) { - MEC1322_KS_KSO_SEL = BIT(6); /* KSEN=1 */ - gpio_set_level(GPIO_KBD_KSO2, 1); - } else { - MEC1322_KS_KSO_SEL = out + CONFIG_KEYBOARD_KSO_BASE; - gpio_set_level(GPIO_KBD_KSO2, 0); - } -#else - MEC1322_KS_KSO_SEL = out + CONFIG_KEYBOARD_KSO_BASE; -#endif - } -} - -test_mockable int keyboard_raw_read_rows(void) -{ - /* Invert it so 0=not pressed, 1=pressed */ - return (MEC1322_KS_KSI_INPUT & 0xff) ^ 0xff; -} - -void keyboard_raw_enable_interrupt(int enable) -{ - if (enable) { - task_clear_pending_irq(MEC1322_IRQ_KSC_INT); - task_enable_irq(MEC1322_IRQ_KSC_INT); - } else { - task_disable_irq(MEC1322_IRQ_KSC_INT); - } -} - -void keyboard_raw_interrupt(void) -{ - /* Clear interrupt status bits */ - MEC1322_KS_KSI_STATUS = 0xff; - - /* Wake keyboard scan task to handle interrupt */ - task_wake(TASK_ID_KEYSCAN); -} -DECLARE_IRQ(MEC1322_IRQ_KSC_INT, keyboard_raw_interrupt, 1); - -int keyboard_raw_is_input_low(int port, int id) -{ - return (MEC1322_GPIO_CTL(port, id) & BIT(24)) == 0; -} diff --git a/chip/mec1322/lfw/ec_lfw.c b/chip/mec1322/lfw/ec_lfw.c deleted file mode 100644 index 39f4e378ae..0000000000 --- a/chip/mec1322/lfw/ec_lfw.c +++ /dev/null @@ -1,283 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * MEC1322 SoC little FW - * - */ - -#include - -#include "config.h" -#include "gpio.h" -#include "spi.h" -#include "spi_flash.h" -#include "util.h" -#include "timer.h" -#include "dma.h" -#include "registers.h" -#include "cpu.h" -#include "clock.h" -#include "system.h" -#include "version.h" -#include "hwtimer.h" -#include "gpio_list.h" - -#include "ec_lfw.h" - -__attribute__ ((section(".intvector"))) -const struct int_vector_t hdr_int_vect = { - (void *)0x11FA00, /* init sp, unused, - set by MEC ROM loader*/ - &lfw_main, /* reset vector */ - &fault_handler, /* NMI handler */ - &fault_handler, /* HardFault handler */ - &fault_handler, /* MPU fault handler */ - &fault_handler /* Bus fault handler */ -}; - -/* SPI devices - from glados/board.c*/ -const struct spi_device_t spi_devices[] = { - { CONFIG_SPI_FLASH_PORT, 0, GPIO_PVT_CS0}, -}; -const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); - - -void timer_init() -{ - uint32_t val = 0; - - /* Ensure timer is not running */ - MEC1322_TMR32_CTL(0) &= ~BIT(5); - - /* Enable timer */ - MEC1322_TMR32_CTL(0) |= BIT(0); - - val = MEC1322_TMR32_CTL(0); - - /* Pre-scale = 48 -> 1MHz -> Period = 1us */ - val = (val & 0xffff) | (47 << 16); - - MEC1322_TMR32_CTL(0) = val; - - /* Set preload to use the full 32 bits of the timer */ - MEC1322_TMR32_PRE(0) = 0xffffffff; - - /* Override the count */ - MEC1322_TMR32_CNT(0) = 0xffffffff; - - /* Auto restart */ - MEC1322_TMR32_CTL(0) |= BIT(3); - - /* Start counting in timer 0 */ - MEC1322_TMR32_CTL(0) |= BIT(5); - -} - -static int spi_flash_readloc(uint8_t *buf_usr, - unsigned int offset, - unsigned int bytes) -{ - uint8_t cmd[4] = {SPI_FLASH_READ, - (offset >> 16) & 0xFF, - (offset >> 8) & 0xFF, - offset & 0xFF}; - - if (offset + bytes > CONFIG_FLASH_SIZE) - return EC_ERROR_INVAL; - - return spi_transaction(SPI_FLASH_DEVICE, cmd, 4, buf_usr, bytes); -} - -int spi_image_load(uint32_t offset) -{ - uint8_t *buf = (uint8_t *) (CONFIG_RW_MEM_OFF + - CONFIG_PROGRAM_MEMORY_BASE); - uint32_t i; - - BUILD_ASSERT(CONFIG_RO_SIZE == CONFIG_RW_SIZE); - memset((void *)buf, 0xFF, (CONFIG_RO_SIZE - 4)); - - for (i = 0; i < CONFIG_RO_SIZE; i += SPI_CHUNK_SIZE) - spi_flash_readloc(&buf[i], offset + i, SPI_CHUNK_SIZE); - - return 0; - -} - -void udelay(unsigned us) -{ - uint32_t t0 = __hw_clock_source_read(); - while (__hw_clock_source_read() - t0 < us) - ; -} - -void usleep(unsigned us) -{ - udelay(us); -} - -int timestamp_expired(timestamp_t deadline, const timestamp_t *now) -{ - timestamp_t now_val; - - if (!now) { - now_val = get_time(); - now = &now_val; - } - - return now->le.lo >= deadline.le.lo; -} - - -timestamp_t get_time(void) -{ - timestamp_t ts; - - ts.le.hi = 0; - ts.le.lo = __hw_clock_source_read(); - return ts; -} - -void uart_write_c(char c) -{ - /* Put in carriage return prior to newline to mimic uart_vprintf() */ - if (c == '\n') - uart_write_c('\r'); - - /* Wait for space in transmit FIFO. */ - while (!(MEC1322_UART_LSR & BIT(5))) - ; - MEC1322_UART_TB = c; -} - -void uart_puts(const char *str) -{ - if (!str || !*str) - return; - - do { - uart_write_c(*str++); - } while (*str); -} - -void fault_handler(void) -{ - uart_puts("EXCEPTION!\nTriggering watchdog reset\n"); - /* trigger reset in 1 ms */ - MEC1322_WDG_LOAD = 1; - MEC1322_WDG_CTL |= 1; - while (1) - ; - -} - -void jump_to_image(uintptr_t init_addr) -{ - void (*resetvec)(void) = (void(*)(void))init_addr; - resetvec(); -} - -void uart_init(void) -{ - /* Set UART to reset on VCC1_RESET instaed of nSIO_RESET */ - MEC1322_UART_CFG &= ~BIT(1); - - /* Baud rate = 115200. 1.8432MHz clock. Divisor = 1 */ - - /* Set CLK_SRC = 0 */ - MEC1322_UART_CFG &= ~BIT(0); - - /* Set DLAB = 1 */ - MEC1322_UART_LCR |= BIT(7); - - /* PBRG0/PBRG1 */ - MEC1322_UART_PBRG0 = 1; - MEC1322_UART_PBRG1 = 0; - - /* Set DLAB = 0 */ - MEC1322_UART_LCR &= ~BIT(7); - - /* Set word length to 8-bit */ - MEC1322_UART_LCR |= BIT(0) | BIT(1); - - /* Enable FIFO */ - MEC1322_UART_FCR = BIT(0); - - /* Activate UART */ - MEC1322_UART_ACT |= BIT(0); - - gpio_config_module(MODULE_UART, 1); -} - -void system_init(void) -{ - - uint32_t wdt_sts = MEC1322_VBAT_STS & MEC1322_VBAT_STS_WDT; - uint32_t rst_sts = MEC1322_PCR_CHIP_PWR_RST & - MEC1322_PWR_RST_STS_VCC1; - - if (rst_sts || wdt_sts) - MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX) = EC_IMAGE_RO; -} - -enum ec_image system_get_image_copy(void) -{ - return MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX); -} - -void lfw_main() -{ - - uintptr_t init_addr; - - /* install vector table */ - *((uintptr_t *) 0xe000ed08) = (uintptr_t) &hdr_int_vect; - - /* Use 48 MHz processor clock to power through boot */ - MEC1322_PCR_PROC_CLK_CTL = 1; - -#ifdef CONFIG_WATCHDOG - /* Reload watchdog which may be running in case of sysjump */ - MEC1322_WDG_KICK = 1; -#ifdef CONFIG_WATCHDOG_HELP - /* Stop aux timer */ - MEC1322_TMR16_CTL(0) &= ~1; -#endif -#endif - - timer_init(); - clock_init(); - cpu_init(); - dma_init(); - uart_init(); - system_init(); - spi_enable(CONFIG_SPI_FLASH_PORT, 1); - - uart_puts("littlefw "); - uart_puts(current_image_data.version); - uart_puts("\n"); - - switch (system_get_image_copy()) { - case EC_IMAGE_RW: - uart_puts("lfw-RW load\n"); - init_addr = CONFIG_RW_MEM_OFF + CONFIG_PROGRAM_MEMORY_BASE; - spi_image_load(CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF); - break; - case EC_IMAGE_RO: - uart_puts("lfw-RO load\n"); - spi_image_load(CONFIG_EC_PROTECTED_STORAGE_OFF + - CONFIG_RO_STORAGE_OFF); - /* fall through */ - default: - MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX) = EC_IMAGE_RO; - init_addr = CONFIG_RO_MEM_OFF + CONFIG_PROGRAM_MEMORY_BASE; - } - - jump_to_image(*(uintptr_t *)(init_addr + 4)); - - /* should never get here */ - while (1) - ; -} diff --git a/chip/mec1322/lfw/ec_lfw.h b/chip/mec1322/lfw/ec_lfw.h deleted file mode 100644 index dd26fbd323..0000000000 --- a/chip/mec1322/lfw/ec_lfw.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * MEC1322 SoC little FW - * - */ - -#include - -noreturn void lfw_main(void) __attribute__ ((naked)); -void fault_handler(void) __attribute__((naked)); - -struct int_vector_t { - void *stack_ptr; - void *reset_vector; - void *nmi; - void *hard_fault; - void *bus_fault; - void *usage_fault; -}; - -#define SPI_CHUNK_SIZE 1024 diff --git a/chip/mec1322/lfw/ec_lfw.ld b/chip/mec1322/lfw/ec_lfw.ld deleted file mode 100644 index 65e17e4941..0000000000 --- a/chip/mec1322/lfw/ec_lfw.ld +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * MEC1322 SoC little FW - * - */ - -/* Memory Spaces Definitions */ -MEMORY -{ - VECTOR(r ) : ORIGIN = 0x100000, LENGTH = 0x18 - SRAM (xrw) : ORIGIN = 0x100018, LENGTH = 0xBE8 -} - -/* - * ld does not allow mathematical expressions in ORIGIN/LENGTH, so check the - * values here. - */ -ASSERT(ORIGIN(VECTOR) + LENGTH(VECTOR) == ORIGIN(SRAM), "Invalid SRAM origin.") -ASSERT(LENGTH(VECTOR) + LENGTH(SRAM) == 0xC00, "Invalid VECTOR+SRAM length.") - -/* - * The entry point is informative, for debuggers and simulators, - * since the Cortex-M vector points to it anyway. - */ -ENTRY(lfw_main) - -/* Sections Definitions */ - -SECTIONS -{ - - /* - * The vector table goes first - */ - .intvector : - { - . = ALIGN(4); - KEEP(*(.intvector)) - } > VECTOR - - /* - * The program code is stored in the .text section, - * which goes to FLASH. - */ - - .text : - { - *(.text .text.*) /* all remaining code */ - *(.rodata .rodata.*) /* read-only data (constants) */ - } >SRAM - - . = ALIGN(4); - - /* Padding */ - - .fill : { - FILL(0xFF); - . = ORIGIN(SRAM) + LENGTH(SRAM) - 1; - BYTE(0xFF); /* emit at least a byte to make linker happy */ - } - - __image_size = LOADADDR(.text) + SIZEOF(.text) - ORIGIN(VECTOR); -} diff --git a/chip/mec1322/lpc.c b/chip/mec1322/lpc.c deleted file mode 100644 index 020cd0e23e..0000000000 --- a/chip/mec1322/lpc.c +++ /dev/null @@ -1,520 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* LPC module for MEC1322 */ - -#include "acpi.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "keyboard_protocol.h" -#include "lpc.h" -#include "port80.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "chipset.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) - -static uint8_t mem_mapped[0x200] __attribute__((section(".bss.big_align"))); - -static struct host_packet lpc_packet; -static struct host_cmd_handler_args host_cmd_args; -static uint8_t host_cmd_flags; /* Flags from host command */ - -static uint8_t params_copy[EC_LPC_HOST_PACKET_SIZE] __aligned(4); -static int init_done; - -static struct ec_lpc_host_args * const lpc_host_args = - (struct ec_lpc_host_args *)mem_mapped; - -static void keyboard_irq_assert(void) -{ -#ifdef CONFIG_KEYBOARD_IRQ_GPIO - /* - * Enforce signal-high for long enough for the signal to be pulled high - * by the external pullup resistor. This ensures the host will see the - * following falling edge, regardless of the line state before this - * function call. - */ - gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1); - udelay(4); - /* Generate a falling edge */ - gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 0); - udelay(4); - - /* Set signal high, now that we've generated the edge */ - gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1); -#else - /* - * SERIRQ is automatically sent by KBC - */ -#endif -} - -/** - * Generate SMI pulse to the host chipset via GPIO. - * - * If the x86 is in S0, SMI# is sampled at 33MHz, so minimum pulse length is - * 60ns. If the x86 is in S3, SMI# is sampled at 32.768KHz, so we need pulse - * length >61us. Both are short enough and events are infrequent, so just - * delay for 65us. - */ -static void lpc_generate_smi(void) -{ - gpio_set_level(GPIO_PCH_SMI_L, 0); - udelay(65); - gpio_set_level(GPIO_PCH_SMI_L, 1); -} - -static void lpc_generate_sci(void) -{ -#ifdef CONFIG_SCI_GPIO - gpio_set_level(CONFIG_SCI_GPIO, 0); - udelay(65); - gpio_set_level(CONFIG_SCI_GPIO, 1); -#else - MEC1322_ACPI_PM_STS |= 1; - udelay(65); - MEC1322_ACPI_PM_STS &= ~1; -#endif -} - -/** - * Update the level-sensitive wake signal to the AP. - * - * @param wake_events Currently asserted wake events - */ -static void lpc_update_wake(host_event_t wake_events) -{ - /* - * Mask off power button event, since the AP gets that through a - * separate dedicated GPIO. - */ - wake_events &= ~EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON); - - /* Signal is asserted low when wake events is non-zero */ - gpio_set_level(GPIO_PCH_WAKE_L, !wake_events); -} - -uint8_t *lpc_get_memmap_range(void) -{ - return mem_mapped + 0x100; -} - -static uint8_t *lpc_get_hostcmd_data_range(void) -{ - return mem_mapped; -} - -/** - * Update the host event status. - * - * Sends a pulse if masked event status becomes non-zero: - * - SMI pulse via PCH_SMI_L GPIO - * - SCI pulse via PCH_SCI_L GPIO - */ -void lpc_update_host_event_status(void) -{ - int need_sci = 0; - int need_smi = 0; - - if (!init_done) - return; - - /* Disable LPC interrupt while updating status register */ - task_disable_irq(MEC1322_IRQ_ACPIEC0_IBF); - - if (lpc_get_host_events_by_type(LPC_HOST_EVENT_SMI)) { - /* Only generate SMI for first event */ - if (!(MEC1322_ACPI_EC_STATUS(0) & EC_LPC_STATUS_SMI_PENDING)) - need_smi = 1; - MEC1322_ACPI_EC_STATUS(0) |= EC_LPC_STATUS_SMI_PENDING; - } else { - MEC1322_ACPI_EC_STATUS(0) &= ~EC_LPC_STATUS_SMI_PENDING; - } - - if (lpc_get_host_events_by_type(LPC_HOST_EVENT_SCI)) { - /* Generate SCI for every event */ - need_sci = 1; - MEC1322_ACPI_EC_STATUS(0) |= EC_LPC_STATUS_SCI_PENDING; - } else { - MEC1322_ACPI_EC_STATUS(0) &= ~EC_LPC_STATUS_SCI_PENDING; - } - - /* Copy host events to mapped memory */ - *(host_event_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = - lpc_get_host_events(); - - task_enable_irq(MEC1322_IRQ_ACPIEC0_IBF); - - /* Process the wake events. */ - lpc_update_wake(lpc_get_host_events_by_type(LPC_HOST_EVENT_WAKE)); - - /* Send pulse on SMI signal if needed */ - if (need_smi) - lpc_generate_smi(); - - /* ACPI 5.0-12.6.1: Generate SCI for SCI_EVT=1. */ - if (need_sci) - lpc_generate_sci(); -} - -static void lpc_send_response_packet(struct host_packet *pkt) -{ - /* Ignore in-progress on LPC since interface is synchronous anyway */ - if (pkt->driver_result == EC_RES_IN_PROGRESS) - return; - - /* Write result to the data byte. */ - MEC1322_ACPI_EC_EC2OS(1, 0) = pkt->driver_result; - - /* Clear the busy bit, so the host knows the EC is done. */ - MEC1322_ACPI_EC_STATUS(1) &= ~EC_LPC_STATUS_PROCESSING; -} - -/* - * Most registers in LPC module are reset when the host is off. We need to - * set up LPC again when the host is starting up. - */ -static void setup_lpc(void) -{ - gpio_config_module(MODULE_LPC, 1); - - /* Set up interrupt on LRESET# deassert */ - MEC1322_INT_SOURCE(19) = BIT(1); - MEC1322_INT_ENABLE(19) |= BIT(1); - MEC1322_INT_BLK_EN |= BIT(19); - task_enable_irq(MEC1322_IRQ_GIRQ19); - - /* Set up ACPI0 for 0x62/0x66 */ - MEC1322_LPC_ACPI_EC0_BAR = 0x00628304; - MEC1322_INT_ENABLE(15) |= BIT(6); - MEC1322_INT_BLK_EN |= BIT(15); - /* Clear STATUS_PROCESSING bit in case it was set during sysjump */ - MEC1322_ACPI_EC_STATUS(0) &= ~EC_LPC_STATUS_PROCESSING; - task_enable_irq(MEC1322_IRQ_ACPIEC0_IBF); - - /* Set up ACPI1 for 0x200/0x204 */ - MEC1322_LPC_ACPI_EC1_BAR = 0x02008407; - MEC1322_INT_ENABLE(15) |= BIT(8); - MEC1322_INT_BLK_EN |= BIT(15); - MEC1322_ACPI_EC_STATUS(1) &= ~EC_LPC_STATUS_PROCESSING; - task_enable_irq(MEC1322_IRQ_ACPIEC1_IBF); - - /* Set up 8042 interface at 0x60/0x64 */ - MEC1322_LPC_8042_BAR = 0x00608104; - - /* Set up indication of Auxiliary sts */ - MEC1322_8042_KB_CTRL |= BIT(7); - - MEC1322_8042_ACT |= 1; - MEC1322_INT_ENABLE(15) |= (BIT(13) | BIT(14)); - MEC1322_INT_BLK_EN |= BIT(15); - task_enable_irq(MEC1322_IRQ_8042EM_IBF); - task_enable_irq(MEC1322_IRQ_8042EM_OBF); - -#ifndef CONFIG_KEYBOARD_IRQ_GPIO - /* Set up SERIRQ for keyboard */ - MEC1322_8042_KB_CTRL |= BIT(5); - MEC1322_LPC_SIRQ(1) = 0x01; -#endif - - /* Set up EMI module for memory mapped region, base address 0x800 */ - MEC1322_LPC_EMI_BAR = 0x0800800f; - MEC1322_INT_ENABLE(15) |= BIT(2); - MEC1322_INT_BLK_EN |= BIT(15); - task_enable_irq(MEC1322_IRQ_EMI); - - /* Access data RAM through alias address */ - MEC1322_EMI_MBA0 = (uint32_t)mem_mapped - 0x118000 + 0x20000000; - - /* - * Limit EMI read / write range. First 256 bytes are RW for host - * commands. Second 256 bytes are RO for mem-mapped data. - */ - MEC1322_EMI_MRL0 = 0x200; - MEC1322_EMI_MWL0 = 0x100; - - /* Set up Mailbox for Port80 trapping */ - MEC1322_MBX_INDEX = 0xff; - MEC1322_LPC_MAILBOX_BAR = 0x00808901; - - /* We support LPC args and version 3 protocol */ - *(lpc_get_memmap_range() + EC_MEMMAP_HOST_CMD_FLAGS) = - EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED | - EC_HOST_CMD_FLAG_VERSION_3; - - /* Sufficiently initialized */ - init_done = 1; - - /* Update host events now that we can copy them to memmap */ - lpc_update_host_event_status(); -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, setup_lpc, HOOK_PRIO_FIRST); - -static void lpc_init(void) -{ - /* Activate LPC interface */ - MEC1322_LPC_ACT |= 1; - - /* - * Ring Oscillator not permitted to shut down - * until LPC activate bit is cleared - */ - MEC1322_LPC_CLK_CTRL |= 3; - - /* Initialize host args and memory map to all zero */ - memset(lpc_host_args, 0, sizeof(*lpc_host_args)); - memset(lpc_get_memmap_range(), 0, EC_MEMMAP_SIZE); - - setup_lpc(); -} -/* - * Set prio to higher than default; this way LPC memory mapped data is ready - * before other inits try to initialize their memmap data. - */ -DECLARE_HOOK(HOOK_INIT, lpc_init, HOOK_PRIO_INIT_LPC); - -#ifdef CONFIG_CHIPSET_RESET_HOOK -static void lpc_chipset_reset(void) -{ - hook_notify(HOOK_CHIPSET_RESET); -} -DECLARE_DEFERRED(lpc_chipset_reset); -#endif - -void girq19_interrupt(void) -{ - /* Check interrupt result for LRESET# trigger */ - if (MEC1322_INT_RESULT(19) & BIT(1)) { - /* Initialize LPC module when LRESET# is deasserted */ - if (!lpc_get_pltrst_asserted()) { - setup_lpc(); - } else { - /* Store port 80 reset event */ - port_80_write(PORT_80_EVENT_RESET); - -#ifdef CONFIG_CHIPSET_RESET_HOOK - /* Notify HOOK_CHIPSET_RESET */ - hook_call_deferred(&lpc_chipset_reset_data, MSEC); -#endif - } - - CPRINTS("LPC RESET# %sasserted", - lpc_get_pltrst_asserted() ? "" : "de"); - - /* Clear interrupt source */ - MEC1322_INT_SOURCE(19) = BIT(1); - } -} -DECLARE_IRQ(MEC1322_IRQ_GIRQ19, girq19_interrupt, 1); - -void emi_interrupt(void) -{ - port_80_write(MEC1322_EMI_H2E_MBX); -} -DECLARE_IRQ(MEC1322_IRQ_EMI, emi_interrupt, 1); - -/* - * Port80 POST code polling limitation: - * - POST code 0xFF is ignored. - */ -int port_80_read(void) -{ - int data; - - /* read MBX_INDEX for POST code */ - data = MEC1322_MBX_INDEX; - - /* clear MBX_INDEX for next POST code*/ - MEC1322_MBX_INDEX = 0xff; - - /* mark POST code 0xff as invalid */ - if (data == 0xff) - data = PORT_80_IGNORE; - - return data; -} - -void acpi_0_interrupt(void) -{ - uint8_t value, result, is_cmd; - - is_cmd = MEC1322_ACPI_EC_STATUS(0) & EC_LPC_STATUS_LAST_CMD; - - /* Set the bust bi */ - MEC1322_ACPI_EC_STATUS(0) |= EC_LPC_STATUS_PROCESSING; - - /* Read command/data; this clears the FRMH bit. */ - value = MEC1322_ACPI_EC_OS2EC(0, 0); - - /* Handle whatever this was. */ - if (acpi_ap_to_ec(is_cmd, value, &result)) - MEC1322_ACPI_EC_EC2OS(0, 0) = result; - - /* Clear the busy bit */ - MEC1322_ACPI_EC_STATUS(0) &= ~EC_LPC_STATUS_PROCESSING; - - /* - * ACPI 5.0-12.6.1: Generate SCI for Input Buffer Empty / Output Buffer - * Full condition on the kernel channel. - */ - lpc_generate_sci(); -} -DECLARE_IRQ(MEC1322_IRQ_ACPIEC0_IBF, acpi_0_interrupt, 1); - -void acpi_1_interrupt(void) -{ - uint8_t st = MEC1322_ACPI_EC_STATUS(1); - if (!(st & EC_LPC_STATUS_FROM_HOST) || - !(st & EC_LPC_STATUS_LAST_CMD)) - return; - - /* Set the busy bit */ - MEC1322_ACPI_EC_STATUS(1) |= EC_LPC_STATUS_PROCESSING; - - /* - * Read the command byte. This clears the FRMH bit in - * the status byte. - */ - host_cmd_args.command = MEC1322_ACPI_EC_OS2EC(1, 0); - - host_cmd_args.result = EC_RES_SUCCESS; - host_cmd_flags = lpc_host_args->flags; - - /* We only support new style command (v3) now */ - if (host_cmd_args.command == EC_COMMAND_PROTOCOL_3) { - lpc_packet.send_response = lpc_send_response_packet; - - lpc_packet.request = (const void *)lpc_get_hostcmd_data_range(); - lpc_packet.request_temp = params_copy; - lpc_packet.request_max = sizeof(params_copy); - /* Don't know the request size so pass in the entire buffer */ - lpc_packet.request_size = EC_LPC_HOST_PACKET_SIZE; - - lpc_packet.response = (void *)lpc_get_hostcmd_data_range(); - lpc_packet.response_max = EC_LPC_HOST_PACKET_SIZE; - lpc_packet.response_size = 0; - - lpc_packet.driver_result = EC_RES_SUCCESS; - host_packet_receive(&lpc_packet); - return; - } else { - /* Old style command unsupported */ - host_cmd_args.result = EC_RES_INVALID_COMMAND; - } - - /* Hand off to host command handler */ - host_command_received(&host_cmd_args); -} -DECLARE_IRQ(MEC1322_IRQ_ACPIEC1_IBF, acpi_1_interrupt, 1); - -#ifdef HAS_TASK_KEYPROTO -void kb_ibf_interrupt(void) -{ - if (lpc_keyboard_input_pending()) - keyboard_host_write(MEC1322_8042_H2E, - MEC1322_8042_STS & BIT(3)); - task_wake(TASK_ID_KEYPROTO); -} -DECLARE_IRQ(MEC1322_IRQ_8042EM_IBF, kb_ibf_interrupt, 1); - -void kb_obf_interrupt(void) -{ - task_wake(TASK_ID_KEYPROTO); -} -DECLARE_IRQ(MEC1322_IRQ_8042EM_OBF, kb_obf_interrupt, 1); -#endif - -int lpc_keyboard_has_char(void) -{ - return (MEC1322_8042_STS & BIT(0)) ? 1 : 0; -} - -int lpc_keyboard_input_pending(void) -{ - return (MEC1322_8042_STS & BIT(1)) ? 1 : 0; -} - -void lpc_keyboard_put_char(uint8_t chr, int send_irq) -{ - MEC1322_8042_E2H = chr; - if (send_irq) - keyboard_irq_assert(); -} - -void lpc_keyboard_clear_buffer(void) -{ - volatile char unused __attribute__((unused)); - - unused = MEC1322_8042_OBF_CLR; -} - -void lpc_keyboard_resume_irq(void) -{ - if (lpc_keyboard_has_char()) - keyboard_irq_assert(); -} - -void lpc_set_acpi_status_mask(uint8_t mask) -{ - MEC1322_ACPI_EC_STATUS(0) |= mask; -} - -void lpc_clear_acpi_status_mask(uint8_t mask) -{ - MEC1322_ACPI_EC_STATUS(0) &= ~mask; -} - -int lpc_get_pltrst_asserted(void) -{ - return (MEC1322_LPC_BUS_MONITOR & (1<<1)) ? 1 : 0; -} - -/* Enable LPC ACPI-EC0 interrupts */ -void lpc_enable_acpi_interrupts(void) -{ - task_enable_irq(MEC1322_IRQ_ACPIEC0_IBF); -} - -/* Disable LPC ACPI-EC0 interrupts */ -void lpc_disable_acpi_interrupts(void) -{ - task_disable_irq(MEC1322_IRQ_ACPIEC0_IBF); -} - -/* On boards without a host, this command is used to set up LPC */ -static int lpc_command_init(int argc, char **argv) -{ - lpc_init(); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(lpcinit, lpc_command_init, NULL, NULL); - -/* Get protocol information */ -static enum ec_status lpc_get_protocol_info(struct host_cmd_handler_args *args) -{ - struct ec_response_get_protocol_info *r = args->response; - - memset(r, 0, sizeof(*r)); - r->protocol_versions = BIT(3); - r->max_request_packet_size = EC_LPC_HOST_PACKET_SIZE; - r->max_response_packet_size = EC_LPC_HOST_PACKET_SIZE; - r->flags = 0; - - args->response_size = sizeof(*r); - - return EC_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, - lpc_get_protocol_info, - EC_VER_MASK(0)); diff --git a/chip/mec1322/port80.c b/chip/mec1322/port80.c deleted file mode 100644 index df4583ed8b..0000000000 --- a/chip/mec1322/port80.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Port 80 Timer Interrupt for MEC1322 */ - -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "lpc.h" -#include "port80.h" -#include "registers.h" -#include "task.h" - -/* Fire timer interrupt every 1000 usec to check for port80 data. */ -#define POLL_PERIOD_USEC 1000 -/* After 30 seconds of no port 80 data, disable the timer interrupt. */ -#define INTERRUPT_DISABLE_TIMEOUT_SEC 30 -#define INTERRUPT_DISABLE_IDLE_COUNT (INTERRUPT_DISABLE_TIMEOUT_SEC \ - * 1000000 \ - / POLL_PERIOD_USEC) - -/* Count the number of consecutive interrupts with no port 80 data. */ -static int idle_count; - -static void port_80_interrupt_enable(void) -{ - idle_count = 0; - - /* Enable the interrupt. */ - task_enable_irq(MEC1322_IRQ_TIMER16_1); - /* Enable and start the timer. */ - MEC1322_TMR16_CTL(1) |= 1 | BIT(5); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, port_80_interrupt_enable, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_RESET, port_80_interrupt_enable, HOOK_PRIO_DEFAULT); - -static void port_80_interrupt_disable(void) -{ - /* Disable the timer block. */ - MEC1322_TMR16_CTL(1) &= ~1; - /* Disable the interrupt. */ - task_disable_irq(MEC1322_IRQ_TIMER16_1); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, port_80_interrupt_disable, - HOOK_PRIO_DEFAULT); - -/* - * The port 80 interrupt will use TIMER16 instance 1 for a 1ms countdown - * timer. This timer is on GIRQ23, bit 1. - */ -static void port_80_interrupt_init(void) -{ - uint32_t val = 0; - - /* - * The timers are driven by a 48MHz oscillator. Prescale down to - * 1MHz. 48MHz/48 -> 1MHz - */ - val = MEC1322_TMR16_CTL(1); - val = (val & 0xFFFF) | (47 << 16); - /* Automatically restart the timer. */ - val |= BIT(3); - /* The counter should decrement. */ - val &= ~BIT(2); - MEC1322_TMR16_CTL(1) = val; - - /* Set the reload value(us). */ - MEC1322_TMR16_PRE(1) = POLL_PERIOD_USEC; - - /* Clear the status if any. */ - MEC1322_TMR16_STS(1) |= 1; - - /* Clear any pending interrupt. */ - MEC1322_INT_SOURCE(23) = BIT(1); - /* Enable IRQ vector 23. */ - MEC1322_INT_BLK_EN |= BIT(23); - /* Enable the interrupt. */ - MEC1322_TMR16_IEN(1) |= 1; - MEC1322_INT_ENABLE(23) = BIT(1); - - port_80_interrupt_enable(); -} -DECLARE_HOOK(HOOK_INIT, port_80_interrupt_init, HOOK_PRIO_DEFAULT); - -void port_80_interrupt(void) -{ - int data; - - MEC1322_TMR16_STS(1) = 1; /* Ack the interrupt */ - if (BIT(1) & MEC1322_INT_RESULT(23)) { - data = port_80_read(); - - if (data != PORT_80_IGNORE) { - idle_count = 0; - port_80_write(data); - } - } - - if (++idle_count >= INTERRUPT_DISABLE_IDLE_COUNT) - port_80_interrupt_disable(); -} -DECLARE_IRQ(MEC1322_IRQ_TIMER16_1, port_80_interrupt, 2); diff --git a/chip/mec1322/pwm.c b/chip/mec1322/pwm.c deleted file mode 100644 index ce94e50e7e..0000000000 --- a/chip/mec1322/pwm.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* PWM control module for MEC1322 */ - -#include "hooks.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "registers.h" -#include "util.h" - -/* - * PWMs that must remain active in low-power idle - MEC1322_PCR_EC_SLP_EN - * bit mask. - */ -static uint32_t pwm_keep_awake_mask; - -void pwm_enable(enum pwm_channel ch, int enabled) -{ - int id = pwm_channels[ch].channel; - - if (enabled) { - MEC1322_PWM_CFG(id) |= 0x1; - if (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP) - pwm_keep_awake_mask |= - MEC1322_PCR_EC_SLP_EN_PWM(id); - } else { - MEC1322_PWM_CFG(id) &= ~0x1; - pwm_keep_awake_mask &= ~MEC1322_PCR_EC_SLP_EN_PWM(id); - } -} - -int pwm_get_enabled(enum pwm_channel ch) -{ - return MEC1322_PWM_CFG(pwm_channels[ch].channel) & 0x1; -} - -void pwm_set_duty(enum pwm_channel ch, int percent) -{ - int id = pwm_channels[ch].channel; - - if (percent < 0) - percent = 0; - else if (percent > 100) - percent = 100; - - MEC1322_PWM_ON(id) = percent; - MEC1322_PWM_OFF(id) = 100 - percent; -} - -int pwm_get_duty(enum pwm_channel ch) -{ - return MEC1322_PWM_ON(pwm_channels[ch].channel); -} - -uint32_t pwm_get_keep_awake_mask(void) -{ - return pwm_keep_awake_mask; -} - -static void pwm_configure(int ch, int active_low, int clock_low) -{ - /* - * clock_low=0 selects the 48MHz Ring Oscillator source - * clock_low=1 selects the 100kHz_Clk source - */ - MEC1322_PWM_CFG(ch) = (15 << 3) | /* Pre-divider = 16 */ - (active_low ? BIT(2) : 0) | - (clock_low ? BIT(1) : 0); -} - -static void pwm_init(void) -{ - int i; - - for (i = 0; i < PWM_CH_COUNT; ++i) { - pwm_configure(pwm_channels[i].channel, - pwm_channels[i].flags & PWM_CONFIG_ACTIVE_LOW, - pwm_channels[i].flags & PWM_CONFIG_ALT_CLOCK); - pwm_set_duty(i, 0); - } -} -DECLARE_HOOK(HOOK_INIT, pwm_init, HOOK_PRIO_INIT_PWM); diff --git a/chip/mec1322/pwm_chip.h b/chip/mec1322/pwm_chip.h deleted file mode 100644 index 9c441aaecd..0000000000 --- a/chip/mec1322/pwm_chip.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* MEC1322-specific PWM module for Chrome EC */ -#ifndef __CROS_EC_PWM_CHIP_H -#define __CROS_EC_PWM_CHIP_H - -/* Data structure to define PWM channels. */ -struct pwm_t { - /* PWM Channel ID */ - int channel; - - /* PWM channel flags. See include/pwm.h */ - uint32_t flags; -}; - -extern const struct pwm_t pwm_channels[]; - -/* - * Returns PWMs that must remain active in low-power idle - - * MEC1322_PCR_EC_SLP_EN bit mask. - */ -uint32_t pwm_get_keep_awake_mask(void); -#endif /* __CROS_EC_PWM_CHIP_H */ diff --git a/chip/mec1322/registers.h b/chip/mec1322/registers.h deleted file mode 100644 index 7bbd9fb068..0000000000 --- a/chip/mec1322/registers.h +++ /dev/null @@ -1,510 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Register map for MEC1322 processor - */ - -#ifndef __CROS_EC_REGISTERS_H -#define __CROS_EC_REGISTERS_H - -#include "common.h" - -/* Helper function for RAM address aliasing */ -#define MEC1322_RAM_ALIAS(x) \ - ((x) >= 0x118000 ? (x) - 0x118000 + 0x20000000 : (x)) - -/* EC Chip Configuration */ -#define MEC1322_CHIP_BASE 0x400fff00 -#define MEC1322_CHIP_DEV_ID REG8(MEC1322_CHIP_BASE + 0x20) -#define MEC1322_CHIP_DEV_REV REG8(MEC1322_CHIP_BASE + 0x21) - - -/* Power/Clocks/Resets */ -#define MEC1322_PCR_BASE 0x40080100 -#define MEC1322_PCR_CHIP_SLP_EN REG32(MEC1322_PCR_BASE + 0x0) -#define MEC1322_PCR_CHIP_CLK_REQ REG32(MEC1322_PCR_BASE + 0x4) -#define MEC1322_PCR_EC_SLP_EN REG32(MEC1322_PCR_BASE + 0x8) -/* Command all blocks to sleep */ -#define MEC1322_PCR_EC_SLP_EN_SLEEP 0xe0700ff7 -#define MEC1322_PCR_EC_SLP_EN_PWM(n) (1 << ((n) ? (19 + (n)) : 4)) -#define MEC1322_PCR_EC_SLP_EN_PWM3 BIT(22) -#define MEC1322_PCR_EC_SLP_EN_PWM2 BIT(21) -#define MEC1322_PCR_EC_SLP_EN_PWM1 BIT(20) -#define MEC1322_PCR_EC_SLP_EN_PWM0 BIT(4) -/* Allow all blocks to request clocks */ -#define MEC1322_PCR_EC_SLP_EN_WAKE (~0xe0700ff7) -#define MEC1322_PCR_EC_CLK_REQ REG32(MEC1322_PCR_BASE + 0xc) -#define MEC1322_PCR_HOST_SLP_EN REG32(MEC1322_PCR_BASE + 0x10) -/* Command all blocks to sleep */ -#define MEC1322_PCR_HOST_SLP_EN_SLEEP 0x5f003 -/* Allow all blocks to request clocks */ -#define MEC1322_PCR_HOST_SLP_EN_WAKE (~0x5f003) -#define MEC1322_PCR_HOST_CLK_REQ REG32(MEC1322_PCR_BASE + 0x14) -#define MEC1322_PCR_SYS_SLP_CTL REG32(MEC1322_PCR_BASE + 0x18) -#define MEC1322_PCR_PROC_CLK_CTL REG32(MEC1322_PCR_BASE + 0x20) -#define MEC1322_PCR_EC_SLP_EN2 REG32(MEC1322_PCR_BASE + 0x24) -/* Mask to command all blocks to sleep */ -#define MEC1322_PCR_EC_SLP_EN2_SLEEP 0x1ffffff8 -/* Allow all blocks to request clocks */ -#define MEC1322_PCR_EC_SLP_EN2_WAKE (~0x03fffff8) -#define MEC1322_PCR_EC_CLK_REQ2 REG32(MEC1322_PCR_BASE + 0x28) -#define MEC1322_PCR_SLOW_CLK_CTL REG32(MEC1322_PCR_BASE + 0x2c) -#define MEC1322_PCR_CHIP_OSC_ID REG32(MEC1322_PCR_BASE + 0x30) -#define MEC1322_PCR_CHIP_PWR_RST REG32(MEC1322_PCR_BASE + 0x34) -#define MEC1322_PCR_CHIP_RST_EN REG32(MEC1322_PCR_BASE + 0x38) -#define MEC1322_PCR_HOST_RST_EN REG32(MEC1322_PCR_BASE + 0x3c) -#define MEC1322_PCR_EC_RST_EN REG32(MEC1322_PCR_BASE + 0x40) -#define MEC1322_PCR_EC_RST_EN2 REG32(MEC1322_PCR_BASE + 0x44) -#define MEC1322_PCR_PWR_RST_CTL REG32(MEC1322_PCR_BASE + 0x48) - -/* Bit defines for MEC1322_PCR_CHIP_PWR_RST */ -#define MEC1322_PWR_RST_STS_VCC1 BIT(6) -#define MEC1322_PWR_RST_STS_VBAT BIT(5) - -/* EC Subsystem */ -#define MEC1322_EC_BASE 0x4000fc00 -#define MEC1322_EC_INT_CTRL REG32(MEC1322_EC_BASE + 0x18) -#define MEC1322_EC_TRACE_EN REG32(MEC1322_EC_BASE + 0x1c) -#define MEC1322_EC_JTAG_EN REG32(MEC1322_EC_BASE + 0x20) -#define MEC1322_EC_WDT_CNT REG32(MEC1322_EC_BASE + 0x28) -#define MEC1322_EC_ADC_VREF_PD REG32(MEC1322_EC_BASE + 0x38) - -/* Interrupt aggregator */ -#define MEC1322_INT_BASE 0x4000c000 -#define MEC1322_INTx_BASE(x) (MEC1322_INT_BASE + ((x) - 8) * 0x14) -#define MEC1322_INT_SOURCE(x) REG32(MEC1322_INTx_BASE(x) + 0x0) -#define MEC1322_INT_ENABLE(x) REG32(MEC1322_INTx_BASE(x) + 0x4) -#define MEC1322_INT_RESULT(x) REG32(MEC1322_INTx_BASE(x) + 0x8) -#define MEC1322_INT_DISABLE(x) REG32(MEC1322_INTx_BASE(x) + 0xc) -#define MEC1322_INT_BLK_EN REG32(MEC1322_INT_BASE + 0x200) -#define MEC1322_INT_BLK_DIS REG32(MEC1322_INT_BASE + 0x204) -#define MEC1322_INT_BLK_IRQ REG32(MEC1322_INT_BASE + 0x208) - - -/* UART */ -#define MEC1322_UART_CONFIG_BASE 0x400f1f00 -#define MEC1322_UART_RUNTIME_BASE 0x400f1c00 - -#define MEC1322_UART_ACT REG8(MEC1322_UART_CONFIG_BASE + 0x30) -#define MEC1322_UART_CFG REG8(MEC1322_UART_CONFIG_BASE + 0xf0) - -/* DLAB=0 */ -#define MEC1322_UART_RB /*R*/ REG8(MEC1322_UART_RUNTIME_BASE + 0x0) -#define MEC1322_UART_TB /*W*/ REG8(MEC1322_UART_RUNTIME_BASE + 0x0) -#define MEC1322_UART_IER REG8(MEC1322_UART_RUNTIME_BASE + 0x1) -/* DLAB=1 */ -#define MEC1322_UART_PBRG0 REG8(MEC1322_UART_RUNTIME_BASE + 0x0) -#define MEC1322_UART_PBRG1 REG8(MEC1322_UART_RUNTIME_BASE + 0x1) - -#define MEC1322_UART_FCR /*W*/ REG8(MEC1322_UART_RUNTIME_BASE + 0x2) -#define MEC1322_UART_IIR /*R*/ REG8(MEC1322_UART_RUNTIME_BASE + 0x2) -#define MEC1322_UART_LCR REG8(MEC1322_UART_RUNTIME_BASE + 0x3) -#define MEC1322_UART_MCR REG8(MEC1322_UART_RUNTIME_BASE + 0x4) -#define MEC1322_UART_LSR REG8(MEC1322_UART_RUNTIME_BASE + 0x5) -#define MEC1322_UART_MSR REG8(MEC1322_UART_RUNTIME_BASE + 0x6) -#define MEC1322_UART_SCR REG8(MEC1322_UART_RUNTIME_BASE + 0x7) - -/* Bit defines for MEC1322_UART_LSR */ -#define MEC1322_LSR_TX_EMPTY BIT(5) - -/* GPIO */ -#define MEC1322_GPIO_BASE 0x40081000 - -static inline uintptr_t gpio_port_base(int port_id) -{ - int oct = (port_id / 10) * 8 + port_id % 10; - return MEC1322_GPIO_BASE + oct * 0x20; -} -#define MEC1322_GPIO_CTL(port, id) REG32(gpio_port_base(port) + (id << 2)) - -#define UNIMPLEMENTED_GPIO_BANK 0 - - -/* Timer */ -#define MEC1322_TMR16_BASE(x) (0x40000c00 + (x) * 0x20) -#define MEC1322_TMR32_BASE(x) (0x40000c80 + (x) * 0x20) - -#define MEC1322_TMR16_CNT(x) REG32(MEC1322_TMR16_BASE(x) + 0x0) -#define MEC1322_TMR16_PRE(x) REG32(MEC1322_TMR16_BASE(x) + 0x4) -#define MEC1322_TMR16_STS(x) REG32(MEC1322_TMR16_BASE(x) + 0x8) -#define MEC1322_TMR16_IEN(x) REG32(MEC1322_TMR16_BASE(x) + 0xc) -#define MEC1322_TMR16_CTL(x) REG32(MEC1322_TMR16_BASE(x) + 0x10) -#define MEC1322_TMR32_CNT(x) REG32(MEC1322_TMR32_BASE(x) + 0x0) -#define MEC1322_TMR32_PRE(x) REG32(MEC1322_TMR32_BASE(x) + 0x4) -#define MEC1322_TMR32_STS(x) REG32(MEC1322_TMR32_BASE(x) + 0x8) -#define MEC1322_TMR32_IEN(x) REG32(MEC1322_TMR32_BASE(x) + 0xc) -#define MEC1322_TMR32_CTL(x) REG32(MEC1322_TMR32_BASE(x) + 0x10) - - -/* Watchdog */ -#define MEC1322_WDG_BASE 0x40000400 -#define MEC1322_WDG_LOAD REG16(MEC1322_WDG_BASE + 0x0) -#define MEC1322_WDG_CTL REG8(MEC1322_WDG_BASE + 0x4) -#define MEC1322_WDG_KICK REG8(MEC1322_WDG_BASE + 0x8) -#define MEC1322_WDG_CNT REG16(MEC1322_WDG_BASE + 0xc) - - -/* VBAT */ -#define MEC1322_VBAT_BASE 0x4000a400 -#define MEC1322_VBAT_STS REG32(MEC1322_VBAT_BASE + 0x0) -#define MEC1322_VBAT_CE REG32(MEC1322_VBAT_BASE + 0x8) -#define MEC1322_VBAT_RAM(x) REG32(MEC1322_VBAT_BASE + 0x400 + 4 * (x)) - -/* Bit definition for MEC1322_VBAT_STS */ -#define MEC1322_VBAT_STS_WDT BIT(5) - -/* Miscellaneous firmware control fields - * scratch pad index cannot be more than 16 as - * mec has 64 bytes = 16 indexes of scratchpad RAM - */ -#define MEC1322_IMAGETYPE_IDX 15 - -/* LPC */ -#define MEC1322_LPC_CFG_BASE 0x400f3300 -#define MEC1322_LPC_ACT REG8(MEC1322_LPC_CFG_BASE + 0x30) -#define MEC1322_LPC_SIRQ(x) REG8(MEC1322_LPC_CFG_BASE + 0x40 + (x)) -#define MEC1322_LPC_CFG_BAR REG32(MEC1322_LPC_CFG_BASE + 0x60) -#define MEC1322_LPC_EMI_BAR REG32(MEC1322_LPC_CFG_BASE + 0x64) -#define MEC1322_LPC_UART_BAR REG32(MEC1322_LPC_CFG_BASE + 0x68) -#define MEC1322_LPC_8042_BAR REG32(MEC1322_LPC_CFG_BASE + 0x78) -#define MEC1322_LPC_ACPI_EC0_BAR REG32(MEC1322_LPC_CFG_BASE + 0x88) -#define MEC1322_LPC_ACPI_EC1_BAR REG32(MEC1322_LPC_CFG_BASE + 0x8c) -#define MEC1322_LPC_ACPI_PM1_BAR REG32(MEC1322_LPC_CFG_BASE + 0x90) -#define MEC1322_LPC_PORT92_BAR REG32(MEC1322_LPC_CFG_BASE + 0x94) -#define MEC1322_LPC_MAILBOX_BAR REG32(MEC1322_LPC_CFG_BASE + 0x98) -#define MEC1322_LPC_RTC_BAR REG32(MEC1322_LPC_CFG_BASE + 0x9c) -#define MEC1322_LPC_MEM_BAR REG32(MEC1322_LPC_CFG_BASE + 0xa0) -#define MEC1322_LPC_MEM_BAR_CFG REG32(MEC1322_LPC_CFG_BASE + 0xa4) - -#define MEC1322_LPC_RT_BASE 0x400f3100 -#define MEC1322_LPC_BUS_MONITOR REG32(MEC1322_LPC_RT_BASE + 0x4) -#define MEC1322_LPC_CLK_CTRL REG32(MEC1322_LPC_RT_BASE + 0x10) -#define MEC1322_LPC_MEM_HOST_CFG REG32(MEC1322_LPC_RT_BASE + 0xfc) - - -/* EMI */ -#define MEC1322_EMI_BASE 0x400f0100 -#define MEC1322_EMI_H2E_MBX REG8(MEC1322_EMI_BASE + 0x0) -#define MEC1322_EMI_E2H_MBX REG8(MEC1322_EMI_BASE + 0x1) -#define MEC1322_EMI_MBA0 REG32(MEC1322_EMI_BASE + 0x4) -#define MEC1322_EMI_MRL0 REG16(MEC1322_EMI_BASE + 0x8) -#define MEC1322_EMI_MWL0 REG16(MEC1322_EMI_BASE + 0xa) -#define MEC1322_EMI_MBA1 REG32(MEC1322_EMI_BASE + 0xc) -#define MEC1322_EMI_MRL1 REG16(MEC1322_EMI_BASE + 0x10) -#define MEC1322_EMI_MWL1 REG16(MEC1322_EMI_BASE + 0x12) -#define MEC1322_EMI_ISR REG16(MEC1322_EMI_BASE + 0x14) -#define MEC1322_EMI_HCE REG16(MEC1322_EMI_BASE + 0x16) - -#define MEC1322_EMI_RT_BASE 0x400f0000 -#define MEC1322_EMI_ISR_B0 REG8(MEC1322_EMI_RT_BASE + 0x8) -#define MEC1322_EMI_ISR_B1 REG8(MEC1322_EMI_RT_BASE + 0x9) -#define MEC1322_EMI_IMR_B0 REG8(MEC1322_EMI_RT_BASE + 0xa) -#define MEC1322_EMI_IMR_B1 REG8(MEC1322_EMI_RT_BASE + 0xb) - - -/* Mailbox */ -#define MEC1322_MBX_RT_BASE 0x400f2400 -#define MEC1322_MBX_INDEX REG8(MEC1322_MBX_RT_BASE + 0x0) -#define MEC1322_MBX_DATA REG8(MEC1322_MBX_RT_BASE + 0x1) - -#define MEC1322_MBX_BASE 0x400f2500 -#define MEC1322_MBX_H2E_MBX REG8(MEC1322_MBX_BASE + 0x0) -#define MEC1322_MBX_E2H_MBX REG8(MEC1322_MBX_BASE + 0x4) -#define MEC1322_MBX_ISR REG8(MEC1322_MBX_BASE + 0x8) -#define MEC1322_MBX_IMR REG8(MEC1322_MBX_BASE + 0xc) -#define MEC1322_MBX_REG(x) REG8(MEC1322_MBX_BASE + 0x10 + (x)) - - -/* PWM */ -#define MEC1322_PWM_BASE(x) (0x40005800 + (x) * 0x10) -#define MEC1322_PWM_ON(x) REG32(MEC1322_PWM_BASE(x) + 0x00) -#define MEC1322_PWM_OFF(x) REG32(MEC1322_PWM_BASE(x) + 0x04) -#define MEC1322_PWM_CFG(x) REG32(MEC1322_PWM_BASE(x) + 0x08) - - -/* ACPI */ -#define MEC1322_ACPI_EC_BASE(x) (0x400f0c00 + (x) * 0x400) -#define MEC1322_ACPI_EC_EC2OS(x, y) REG8(MEC1322_ACPI_EC_BASE(x) + 0x100 + (y)) -#define MEC1322_ACPI_EC_STATUS(x) REG8(MEC1322_ACPI_EC_BASE(x) + 0x104) -#define MEC1322_ACPI_EC_BYTE_CTL(x) REG8(MEC1322_ACPI_EC_BASE(x) + 0x105) -#define MEC1322_ACPI_EC_OS2EC(x, y) REG8(MEC1322_ACPI_EC_BASE(x) + 0x108 + (y)) - -#define MEC1322_ACPI_PM_RT_BASE 0x400f1400 -#define MEC1322_ACPI_PM1_STS1 REG8(MEC1322_ACPI_PM_RT_BASE + 0x0) -#define MEC1322_ACPI_PM1_STS2 REG8(MEC1322_ACPI_PM_RT_BASE + 0x1) -#define MEC1322_ACPI_PM1_EN1 REG8(MEC1322_ACPI_PM_RT_BASE + 0x2) -#define MEC1322_ACPI_PM1_EN2 REG8(MEC1322_ACPI_PM_RT_BASE + 0x3) -#define MEC1322_ACPI_PM1_CTL1 REG8(MEC1322_ACPI_PM_RT_BASE + 0x4) -#define MEC1322_ACPI_PM1_CTL2 REG8(MEC1322_ACPI_PM_RT_BASE + 0x5) -#define MEC1322_ACPI_PM2_CTL1 REG8(MEC1322_ACPI_PM_RT_BASE + 0x6) -#define MEC1322_ACPI_PM2_CTL2 REG8(MEC1322_ACPI_PM_RT_BASE + 0x7) -#define MEC1322_ACPI_PM_EC_BASE 0x400f1500 -#define MEC1322_ACPI_PM_STS REG8(MEC1322_ACPI_PM_EC_BASE + 0x10) - - -/* 8042 */ -#define MEC1322_8042_BASE 0x400f0400 -#define MEC1322_8042_OBF_CLR REG8(MEC1322_8042_BASE + 0x0) -#define MEC1322_8042_H2E REG8(MEC1322_8042_BASE + 0x100) -#define MEC1322_8042_E2H REG8(MEC1322_8042_BASE + 0x100) -#define MEC1322_8042_STS REG8(MEC1322_8042_BASE + 0x104) -#define MEC1322_8042_KB_CTRL REG8(MEC1322_8042_BASE + 0x108) -#define MEC1322_8042_PCOBF REG8(MEC1322_8042_BASE + 0x114) -#define MEC1322_8042_ACT REG8(MEC1322_8042_BASE + 0x330) - - -/* FAN */ -#define MEC1322_FAN_BASE 0x4000a000 -#define MEC1322_FAN_SETTING REG8(MEC1322_FAN_BASE + 0x0) -#define MEC1322_FAN_PWM_DIVIDE REG8(MEC1322_FAN_BASE + 0x1) -#define MEC1322_FAN_CFG1 REG8(MEC1322_FAN_BASE + 0x2) -#define MEC1322_FAN_CFG2 REG8(MEC1322_FAN_BASE + 0x3) -#define MEC1322_FAN_GAIN REG8(MEC1322_FAN_BASE + 0x5) -#define MEC1322_FAN_SPIN_UP REG8(MEC1322_FAN_BASE + 0x6) -#define MEC1322_FAN_STEP REG8(MEC1322_FAN_BASE + 0x7) -#define MEC1322_FAN_MIN_DRV REG8(MEC1322_FAN_BASE + 0x8) -#define MEC1322_FAN_VALID_CNT REG8(MEC1322_FAN_BASE + 0x9) -#define MEC1322_FAN_DRV_FAIL REG16(MEC1322_FAN_BASE + 0xa) -#define MEC1322_FAN_TARGET REG16(MEC1322_FAN_BASE + 0xc) -#define MEC1322_FAN_READING REG16(MEC1322_FAN_BASE + 0xe) -#define MEC1322_FAN_BASE_FREQ REG8(MEC1322_FAN_BASE + 0x10) -#define MEC1322_FAN_STATUS REG8(MEC1322_FAN_BASE + 0x11) - - -/* I2C */ -#define MEC1322_I2C0_BASE 0x40001800 -#define MEC1322_I2C1_BASE 0x4000ac00 -#define MEC1322_I2C2_BASE 0x4000b000 -#define MEC1322_I2C3_BASE 0x4000b400 -#define MEC1322_I2C_BASESEP 0x00000400 -#define MEC1322_I2C_ADDR(controller, offset) \ - (offset + (controller == 0 ? MEC1322_I2C0_BASE : \ - MEC1322_I2C1_BASE + MEC1322_I2C_BASESEP * (controller - 1))) - -/* - * MEC1322 has five ports distributed among four controllers. Locking must - * occur by-controller (not by-port). - */ -enum mec1322_i2c_port { - MEC1322_I2C0_0 = 0, /* Controller 0, port 0 */ - MEC1322_I2C0_1 = 1, /* Controller 0, port 1 */ - MEC1322_I2C1 = 2, /* Controller 1 */ - MEC1322_I2C2 = 3, /* Controller 2 */ - MEC1322_I2C3 = 4, /* Controller 3 */ - MEC1322_I2C_PORT_COUNT, -}; - -#define MEC1322_I2C_CTRL(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x0)) -#define MEC1322_I2C_STATUS(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x0)) -#define MEC1322_I2C_OWN_ADDR(ctrl) REG16(MEC1322_I2C_ADDR(ctrl, 0x4)) -#define MEC1322_I2C_DATA(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x8)) -#define MEC1322_I2C_MASTER_CMD(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0xc)) -#define MEC1322_I2C_SLAVE_CMD(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x10)) -#define MEC1322_I2C_PEC(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x14)) -#define MEC1322_I2C_DATA_TIM_2(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x18)) -#define MEC1322_I2C_COMPLETE(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x20)) -#define MEC1322_I2C_IDLE_SCALE(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x24)) -#define MEC1322_I2C_CONFIG(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x28)) -#define MEC1322_I2C_BUS_CLK(ctrl) REG16(MEC1322_I2C_ADDR(ctrl, 0x2c)) -#define MEC1322_I2C_BLK_ID(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x30)) -#define MEC1322_I2C_REV(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x34)) -#define MEC1322_I2C_BB_CTRL(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x38)) -#define MEC1322_I2C_DATA_TIM(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x40)) -#define MEC1322_I2C_TOUT_SCALE(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x44)) -#define MEC1322_I2C_SLAVE_TX_BUF(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x48)) -#define MEC1322_I2C_SLAVE_RX_BUF(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x4c)) -#define MEC1322_I2C_MASTER_TX_BUF(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x50)) -#define MEC1322_I2C_MASTER_RX_BUF(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x54)) - - -/* Keyboard scan matrix */ -#define MEC1322_KS_BASE 0x40009c00 -#define MEC1322_KS_KSO_SEL REG32(MEC1322_KS_BASE + 0x4) -#define MEC1322_KS_KSI_INPUT REG32(MEC1322_KS_BASE + 0x8) -#define MEC1322_KS_KSI_STATUS REG32(MEC1322_KS_BASE + 0xc) -#define MEC1322_KS_KSI_INT_EN REG32(MEC1322_KS_BASE + 0x10) -#define MEC1322_KS_EXT_CTRL REG32(MEC1322_KS_BASE + 0x14) - - -/* ADC */ -#define MEC1322_ADC_BASE 0x40007c00 -#define MEC1322_ADC_CTRL REG32(MEC1322_ADC_BASE + 0x0) -#define MEC1322_ADC_DELAY REG32(MEC1322_ADC_BASE + 0x4) -#define MEC1322_ADC_STS REG32(MEC1322_ADC_BASE + 0x8) -#define MEC1322_ADC_SINGLE REG32(MEC1322_ADC_BASE + 0xc) -#define MEC1322_ADC_REPEAT REG32(MEC1322_ADC_BASE + 0x10) -#define MEC1322_ADC_READ(x) REG32(MEC1322_ADC_BASE + 0x14 + (x) * 0x4) - - -/* Hibernation timer */ -#define MEC1322_HTIMER_BASE 0x40009800 -#define MEC1322_HTIMER_PRELOAD REG16(MEC1322_HTIMER_BASE + 0x0) -#define MEC1322_HTIMER_CONTROL REG16(MEC1322_HTIMER_BASE + 0x4) -#define MEC1322_HTIMER_COUNT REG16(MEC1322_HTIMER_BASE + 0x8) - - -/* SPI */ -#define MEC1322_SPI_BASE(port) (0x40009400 + 0x80 * (port)) -#define MEC1322_SPI_AR(port) REG8(MEC1322_SPI_BASE(port) + 0x00) -#define MEC1322_SPI_CR(port) REG8(MEC1322_SPI_BASE(port) + 0x04) -#define MEC1322_SPI_SR(port) REG8(MEC1322_SPI_BASE(port) + 0x08) -#define MEC1322_SPI_TD(port) REG8(MEC1322_SPI_BASE(port) + 0x0c) -#define MEC1322_SPI_RD(port) REG8(MEC1322_SPI_BASE(port) + 0x10) -#define MEC1322_SPI_CC(port) REG8(MEC1322_SPI_BASE(port) + 0x14) -#define MEC1322_SPI_CG(port) REG8(MEC1322_SPI_BASE(port) + 0x18) - - -/* DMA */ -#define MEC1322_DMA_BASE 0x40002400 - -/* - * Available DMA channels. - * - * On MEC1322, any DMA channel may serve any device. Since we have - * 12 channels and 12 devices, we make each channel dedicated to the - * device of the same number. - */ -enum dma_channel { - /* Channel numbers */ - MEC1322_DMAC_I2C0_SLAVE = 0, - MEC1322_DMAC_I2C0_MASTER = 1, - MEC1322_DMAC_I2C1_SLAVE = 2, - MEC1322_DMAC_I2C1_MASTER = 3, - MEC1322_DMAC_I2C2_SLAVE = 4, - MEC1322_DMAC_I2C2_MASTER = 5, - MEC1322_DMAC_I2C3_SLAVE = 6, - MEC1322_DMAC_I2C3_MASTER = 7, - MEC1322_DMAC_SPI0_TX = 8, - MEC1322_DMAC_SPI0_RX = 9, - MEC1322_DMAC_SPI1_TX = 10, - MEC1322_DMAC_SPI1_RX = 11, - - /* Channel count */ - MEC1322_DMAC_COUNT = 12, -}; - -/* Registers for a single channel of the DMA controller */ -struct mec1322_dma_chan { - uint32_t act; /* Activate */ - uint32_t mem_start; /* Memory start address */ - uint32_t mem_end; /* Memory end address */ - uint32_t dev; /* Device address */ - uint32_t ctrl; /* Control */ - uint32_t int_status; /* Interrupt status */ - uint32_t int_enabled; /* Interrupt enabled */ - uint32_t pad; -}; - -/* Always use mec1322_dma_chan_t so volatile keyword is included! */ -typedef volatile struct mec1322_dma_chan mec1322_dma_chan_t; - -/* Common code and header file must use this */ -typedef mec1322_dma_chan_t dma_chan_t; - -/* Registers for the DMA controller */ -struct mec1322_dma_regs { - uint32_t ctrl; - uint32_t data; - uint32_t pad[2]; - mec1322_dma_chan_t chan[MEC1322_DMAC_COUNT]; -}; - -/* Always use mec1322_dma_regs_t so volatile keyword is included! */ -typedef volatile struct mec1322_dma_regs mec1322_dma_regs_t; - -#define MEC1322_DMA_REGS ((mec1322_dma_regs_t *)MEC1322_DMA_BASE) - -/* Bits for DMA channel regs */ -#define MEC1322_DMA_ACT_EN BIT(0) -#define MEC1322_DMA_XFER_SIZE(x) ((x) << 20) -#define MEC1322_DMA_INC_DEV BIT(17) -#define MEC1322_DMA_INC_MEM BIT(16) -#define MEC1322_DMA_DEV(x) ((x) << 9) -#define MEC1322_DMA_TO_DEV BIT(8) -#define MEC1322_DMA_DONE BIT(2) -#define MEC1322_DMA_RUN BIT(0) - - -/* IRQ Numbers */ -#define MEC1322_IRQ_I2C_0 0 -#define MEC1322_IRQ_I2C_1 1 -#define MEC1322_IRQ_I2C_2 2 -#define MEC1322_IRQ_I2C_3 3 -#define MEC1322_IRQ_DMA_0 4 -#define MEC1322_IRQ_DMA_1 5 -#define MEC1322_IRQ_DMA_2 6 -#define MEC1322_IRQ_DMA_3 7 -#define MEC1322_IRQ_DMA_4 8 -#define MEC1322_IRQ_DMA_5 9 -#define MEC1322_IRQ_DMA_6 10 -#define MEC1322_IRQ_DMA_7 11 -#define MEC1322_IRQ_LPC 12 -#define MEC1322_IRQ_UART 13 -#define MEC1322_IRQ_EMI 14 -#define MEC1322_IRQ_ACPIEC0_IBF 15 -#define MEC1322_IRQ_ACPIEC0_OBF 16 -#define MEC1322_IRQ_ACPIEC1_IBF 17 -#define MEC1322_IRQ_ACPIEC1_OBF 18 -#define MEC1322_IRQ_ACPIPM1_CTL 19 -#define MEC1322_IRQ_ACPIPM1_EN 20 -#define MEC1322_IRQ_ACPIPM1_STS 21 -#define MEC1322_IRQ_8042EM_OBF 22 -#define MEC1322_IRQ_8042EM_IBF 23 -#define MEC1322_IRQ_MAILBOX 24 -#define MEC1322_IRQ_PECI_HOST 25 -#define MEC1322_IRQ_TACH_0 26 -#define MEC1322_IRQ_TACH_1 27 -#define MEC1322_IRQ_ADC_SNGL 28 -#define MEC1322_IRQ_ADC_RPT 29 -#define MEC1322_IRQ_PS2_0 32 -#define MEC1322_IRQ_PS2_1 33 -#define MEC1322_IRQ_PS2_2 34 -#define MEC1322_IRQ_PS2_3 35 -#define MEC1322_IRQ_SPI0_TX 36 -#define MEC1322_IRQ_SPI0_RX 37 -#define MEC1322_IRQ_HTIMER 38 -#define MEC1322_IRQ_KSC_INT 39 -#define MEC1322_IRQ_MAILBOX_DATA 40 -#define MEC1322_IRQ_TIMER16_0 49 -#define MEC1322_IRQ_TIMER16_1 50 -#define MEC1322_IRQ_TIMER16_2 51 -#define MEC1322_IRQ_TIMER16_3 52 -#define MEC1322_IRQ_TIMER32_0 53 -#define MEC1322_IRQ_TIMER32_1 54 -#define MEC1322_IRQ_SPI1_TX 55 -#define MEC1322_IRQ_SPI1_RX 56 -#define MEC1322_IRQ_GIRQ8 57 -#define MEC1322_IRQ_GIRQ9 58 -#define MEC1322_IRQ_GIRQ10 59 -#define MEC1322_IRQ_GIRQ11 60 -#define MEC1322_IRQ_GIRQ12 61 -#define MEC1322_IRQ_GIRQ13 62 -#define MEC1322_IRQ_GIRQ14 63 -#define MEC1322_IRQ_GIRQ15 64 -#define MEC1322_IRQ_GIRQ16 65 -#define MEC1322_IRQ_GIRQ17 66 -#define MEC1322_IRQ_GIRQ18 67 -#define MEC1322_IRQ_GIRQ19 68 -#define MEC1322_IRQ_GIRQ20 69 -#define MEC1322_IRQ_GIRQ21 70 -#define MEC1322_IRQ_GIRQ22 71 -#define MEC1322_IRQ_GIRQ23 72 -#define MEC1322_IRQ_DMA_8 81 -#define MEC1322_IRQ_DMA_9 82 -#define MEC1322_IRQ_DMA_10 83 -#define MEC1322_IRQ_DMA_11 84 -#define MEC1322_IRQ_PWM_WDT3 85 -#define MEC1322_IRQ_RTC 91 -#define MEC1322_IRQ_RTC_ALARM 92 - -/* Wake pin definitions, defined at board-level */ -#ifndef CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC -extern const enum gpio_signal hibernate_wake_pins[]; -extern const int hibernate_wake_pins_used; -#else -extern enum gpio_signal hibernate_wake_pins[]; -extern int hibernate_wake_pins_used; -#endif - -#endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/mec1322/spi.c b/chip/mec1322/spi.c deleted file mode 100644 index ba58bfb0bd..0000000000 --- a/chip/mec1322/spi.c +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* SPI master module for MEC1322 */ - -#include "common.h" -#include "console.h" -#include "dma.h" -#include "gpio.h" -#include "registers.h" -#include "spi.h" -#include "timer.h" -#include "util.h" -#include "hooks.h" -#include "task.h" - -#define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) - -#define SPI_BYTE_TRANSFER_TIMEOUT_US (3 * MSEC) -#define SPI_BYTE_TRANSFER_POLL_INTERVAL_US 100 - -#define SPI_DMA_CHANNEL(port) (MEC1322_DMAC_SPI0_RX + (port) * 2) - -/* only regular image needs mutex, LFW does not have scheduling */ -/* TODO: Move SPI locking to common code */ -#ifndef LFW -static struct mutex spi_mutex; -#endif - -static const struct dma_option spi_rx_option[] = { - { - SPI_DMA_CHANNEL(0), - (void *)&MEC1322_SPI_RD(0), - MEC1322_DMA_XFER_SIZE(1) - }, - { - SPI_DMA_CHANNEL(1), - (void *)&MEC1322_SPI_RD(1), - MEC1322_DMA_XFER_SIZE(1) - }, -}; - -static int wait_byte(const int port) -{ - timestamp_t deadline; - - deadline.val = get_time().val + SPI_BYTE_TRANSFER_TIMEOUT_US; - while ((MEC1322_SPI_SR(port) & 0x3) != 0x3) { - if (timestamp_expired(deadline, NULL)) - return EC_ERROR_TIMEOUT; - usleep(SPI_BYTE_TRANSFER_POLL_INTERVAL_US); - } - return EC_SUCCESS; -} - -static int spi_tx(const int port, const uint8_t *txdata, int txlen) -{ - int i; - int ret = EC_SUCCESS; - uint8_t unused __attribute__((unused)) = 0; - - for (i = 0; i < txlen; ++i) { - MEC1322_SPI_TD(port) = txdata[i]; - ret = wait_byte(port); - if (ret != EC_SUCCESS) - return ret; - unused = MEC1322_SPI_RD(port); - } - - return ret; -} - -int spi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - int port = spi_device->port; - int ret = EC_SUCCESS; - - gpio_set_level(spi_device->gpio_cs, 0); - - /* Disable auto read */ - MEC1322_SPI_CR(port) &= ~BIT(5); - - ret = spi_tx(port, txdata, txlen); - if (ret != EC_SUCCESS) - return ret; - - /* Enable auto read */ - MEC1322_SPI_CR(port) |= BIT(5); - - if (rxlen != 0) { - dma_start_rx(&spi_rx_option[port], rxlen, rxdata); - MEC1322_SPI_TD(port) = 0; - } - return ret; -} - -int spi_transaction_flush(const struct spi_device_t *spi_device) -{ - int port = spi_device->port; - int ret = dma_wait(SPI_DMA_CHANNEL(port)); - uint8_t unused __attribute__((unused)) = 0; - - timestamp_t deadline; - - /* Disable auto read */ - MEC1322_SPI_CR(port) &= ~BIT(5); - - deadline.val = get_time().val + SPI_BYTE_TRANSFER_TIMEOUT_US; - /* Wait for FIFO empty SPISR_TXBE */ - while ((MEC1322_SPI_SR(port) & 0x01) != 0x1) { - if (timestamp_expired(deadline, NULL)) - return EC_ERROR_TIMEOUT; - usleep(SPI_BYTE_TRANSFER_POLL_INTERVAL_US); - } - - dma_disable(SPI_DMA_CHANNEL(port)); - dma_clear_isr(SPI_DMA_CHANNEL(port)); - if (MEC1322_SPI_SR(port) & 0x2) - unused = MEC1322_SPI_RD(port); - - gpio_set_level(spi_device->gpio_cs, 1); - - return ret; -} - -int spi_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - int ret; - -#ifndef LFW - mutex_lock(&spi_mutex); -#endif - ret = spi_transaction_async(spi_device, txdata, txlen, rxdata, rxlen); - if (ret) - return ret; - ret = spi_transaction_flush(spi_device); - -#ifndef LFW - mutex_unlock(&spi_mutex); -#endif - return ret; -} - -int spi_enable(int port, int enable) -{ - if (enable) { - gpio_config_module(MODULE_SPI, 1); - - /* Set enable bit in SPI_AR */ - MEC1322_SPI_AR(port) |= 0x1; - - /* Set SPDIN to 0 -> Full duplex */ - MEC1322_SPI_CR(port) &= ~(0x3 << 2); - - /* Set CLKPOL, TCLKPH, RCLKPH to 0 */ - MEC1322_SPI_CC(port) &= ~0x7; - - /* Set LSBF to 0 -> MSB first */ - MEC1322_SPI_CR(port) &= ~0x1; - } else { - /* Clear enable bit in SPI_AR */ - MEC1322_SPI_AR(port) &= ~0x1; - - gpio_config_module(MODULE_SPI, 0); - } - - return EC_SUCCESS; -} - diff --git a/chip/mec1322/system.c b/chip/mec1322/system.c deleted file mode 100644 index a3043ba46b..0000000000 --- a/chip/mec1322/system.c +++ /dev/null @@ -1,393 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* System module for Chrome EC : MEC1322 hardware specific implementation */ - -#include "clock.h" -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "gpio.h" -#include "host_command.h" -#include "registers.h" -#include "shared_mem.h" -#include "system.h" -#include "hooks.h" -#include "task.h" -#include "timer.h" -#include "usb_pd.h" -#include "util.h" -#include "spi.h" - -/* Indices for hibernate data registers (RAM backed by VBAT) */ -enum hibdata_index { - HIBDATA_INDEX_SCRATCHPAD = 0, /* General-purpose scratchpad */ - HIBDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */ - HIBDATA_INDEX_PD0, /* USB-PD0 saved port state */ - HIBDATA_INDEX_PD1, /* USB-PD1 saved port state */ - HIBDATA_INDEX_PD2, /* USB-PD2 saved port state */ -}; - -static void check_reset_cause(void) -{ - uint32_t status = MEC1322_VBAT_STS; - uint32_t flags = 0; - uint32_t rst_sts = MEC1322_PCR_CHIP_PWR_RST & - (MEC1322_PWR_RST_STS_VCC1 | - MEC1322_PWR_RST_STS_VBAT); - - /* Clear the reset causes now that we've read them */ - MEC1322_VBAT_STS |= status; - MEC1322_PCR_CHIP_PWR_RST |= rst_sts; - - /* - * BIT[6] determine VCC1 reset - */ - if (rst_sts & MEC1322_PWR_RST_STS_VCC1) - flags |= EC_RESET_FLAG_RESET_PIN; - - - flags |= MEC1322_VBAT_RAM(HIBDATA_INDEX_SAVED_RESET_FLAGS); - MEC1322_VBAT_RAM(HIBDATA_INDEX_SAVED_RESET_FLAGS) = 0; - - if ((status & MEC1322_VBAT_STS_WDT) && !(flags & (EC_RESET_FLAG_SOFT | - EC_RESET_FLAG_HARD | - EC_RESET_FLAG_HIBERNATE))) - flags |= EC_RESET_FLAG_WATCHDOG; - - system_set_reset_flags(flags); -} - -int system_is_reboot_warm(void) -{ - uint32_t reset_flags; - /* - * Check reset cause here, - * gpio_pre_init is executed faster than system_pre_init - */ - check_reset_cause(); - reset_flags = system_get_reset_flags(); - - if ((reset_flags & EC_RESET_FLAG_RESET_PIN) || - (reset_flags & EC_RESET_FLAG_POWER_ON) || - (reset_flags & EC_RESET_FLAG_WATCHDOG) || - (reset_flags & EC_RESET_FLAG_HARD) || - (reset_flags & EC_RESET_FLAG_SOFT) || - (reset_flags & EC_RESET_FLAG_HIBERNATE)) - return 0; - else - return 1; -} - -void system_pre_init(void) -{ - /* Enable direct NVIC */ - MEC1322_EC_INT_CTRL |= 1; - - /* Disable ARM TRACE debug port */ - MEC1322_EC_TRACE_EN &= ~1; - - /* Deassert nSIO_RESET */ - MEC1322_PCR_PWR_RST_CTL &= ~BIT(0); - - spi_enable(CONFIG_SPI_FLASH_PORT, 1); -} - -void chip_save_reset_flags(uint32_t flags) -{ - MEC1322_VBAT_RAM(HIBDATA_INDEX_SAVED_RESET_FLAGS) = flags; -} - -uint32_t chip_read_reset_flags(void) -{ - return MEC1322_VBAT_RAM(HIBDATA_INDEX_SAVED_RESET_FLAGS); -} - -noreturn -void _system_reset(int flags, int wake_from_hibernate) -{ - uint32_t save_flags = 0; - - /* Disable interrupts to avoid task swaps during reboot */ - interrupt_disable(); - - /* Save current reset reasons if necessary */ - if (flags & SYSTEM_RESET_PRESERVE_FLAGS) - save_flags = system_get_reset_flags() | EC_RESET_FLAG_PRESERVED; - - if (flags & SYSTEM_RESET_LEAVE_AP_OFF) - save_flags |= EC_RESET_FLAG_AP_OFF; - - if (wake_from_hibernate) - save_flags |= EC_RESET_FLAG_HIBERNATE; - else if (flags & SYSTEM_RESET_HARD) - save_flags |= EC_RESET_FLAG_HARD; - else - save_flags |= EC_RESET_FLAG_SOFT; - - chip_save_reset_flags(save_flags); - - /* Trigger watchdog in 1ms */ - MEC1322_WDG_LOAD = 1; - MEC1322_WDG_CTL |= 1; - - /* Spin and wait for reboot; should never return */ - while (1) - ; -} - -void system_reset(int flags) -{ - _system_reset(flags, 0); -} - -const char *system_get_chip_vendor(void) -{ - return "smsc"; -} - -const char *system_get_chip_name(void) -{ - switch (MEC1322_CHIP_DEV_ID) { - case 0x15: - return "mec1322"; - default: - return "unknown"; - } -} - -static char to_hex(int x) -{ - if (x >= 0 && x <= 9) - return '0' + x; - return 'a' + x - 10; -} - -const char *system_get_chip_revision(void) -{ - static char buf[3]; - uint8_t rev = MEC1322_CHIP_DEV_REV; - - buf[0] = to_hex(rev / 16); - buf[1] = to_hex(rev & 0xf); - buf[2] = '\0'; - return buf; -} - -static int bbram_idx_lookup(enum system_bbram_idx idx) -{ - switch (idx) { - case SYSTEM_BBRAM_IDX_PD0: - return HIBDATA_INDEX_PD0; - case SYSTEM_BBRAM_IDX_PD1: - return HIBDATA_INDEX_PD1; - case SYSTEM_BBRAM_IDX_PD2: - return HIBDATA_INDEX_PD2; - default: - return -1; - } -} - -int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) -{ - int hibdata = bbram_idx_lookup(idx); - - if (hibdata < 0) - return EC_ERROR_UNIMPLEMENTED; - - *value = MEC1322_VBAT_RAM(hibdata); - return EC_SUCCESS; -} - -int system_set_bbram(enum system_bbram_idx idx, uint8_t value) -{ - int hibdata = bbram_idx_lookup(idx); - - if (hibdata < 0) - return EC_ERROR_UNIMPLEMENTED; - - MEC1322_VBAT_RAM(hibdata) = value; - return EC_SUCCESS; -} - -int system_set_scratchpad(uint32_t value) -{ - MEC1322_VBAT_RAM(HIBDATA_INDEX_SCRATCHPAD) = value; - return EC_SUCCESS; -} - -uint32_t system_get_scratchpad(void) -{ - return MEC1322_VBAT_RAM(HIBDATA_INDEX_SCRATCHPAD); -} - -void system_hibernate(uint32_t seconds, uint32_t microseconds) -{ - int i; - -#ifdef CONFIG_HOSTCMD_PD - /* Inform the PD MCU that we are going to hibernate. */ - host_command_pd_request_hibernate(); - /* Wait to ensure exchange with PD before hibernating. */ - msleep(100); -#endif - - cflush(); - - if (board_hibernate) - board_hibernate(); - - /* Disable interrupts */ - interrupt_disable(); - for (i = 0; i <= 92; ++i) { - task_disable_irq(i); - task_clear_pending_irq(i); - } - - for (i = 8; i <= 23; ++i) - MEC1322_INT_DISABLE(i) = 0xffffffff; - - MEC1322_INT_BLK_DIS |= 0xffff00; - - /* Power down ADC VREF */ - MEC1322_EC_ADC_VREF_PD |= 1; - - /* Assert nSIO_RESET */ - MEC1322_PCR_PWR_RST_CTL |= 1; - - /* Disable UART */ - MEC1322_UART_ACT &= ~0x1; - MEC1322_LPC_ACT &= ~0x1; - - /* Disable JTAG */ - MEC1322_EC_JTAG_EN &= ~1; - - /* Disable 32KHz clock */ - MEC1322_VBAT_CE &= ~0x2; - - /* Stop watchdog */ - MEC1322_WDG_CTL &= ~1; - - /* Stop timers */ - MEC1322_TMR32_CTL(0) &= ~1; - MEC1322_TMR32_CTL(1) &= ~1; - MEC1322_TMR16_CTL(0) &= ~1; - - /* Power down ADC */ - MEC1322_ADC_CTRL &= ~1; - - /* Disable blocks */ - MEC1322_PCR_CHIP_SLP_EN |= 0x3; - MEC1322_PCR_EC_SLP_EN |= MEC1322_PCR_EC_SLP_EN_SLEEP; - MEC1322_PCR_HOST_SLP_EN |= MEC1322_PCR_HOST_SLP_EN_SLEEP; - MEC1322_PCR_EC_SLP_EN2 |= MEC1322_PCR_EC_SLP_EN2_SLEEP; - MEC1322_PCR_SLOW_CLK_CTL &= 0xfffffc00; - - /* Set sleep state */ - MEC1322_PCR_SYS_SLP_CTL = (MEC1322_PCR_SYS_SLP_CTL & ~0x7) | 0x2; - CPU_SCB_SYSCTRL |= 0x4; - - /* Setup GPIOs for hibernate */ - if (board_hibernate_late) - board_hibernate_late(); - -#ifdef CONFIG_USB_PD_PORT_MAX_COUNT - /* - * Leave USB-C charging enabled in hibernate, in order to - * allow wake-on-plug. 5V enable must be pulled low. - */ - switch (board_get_usb_pd_port_count()) { -#if CONFIG_USB_PD_PORT_MAX_COUNT >= 2 - case 2: - gpio_set_flags(GPIO_USB_C1_5V_EN, GPIO_PULL_DOWN | GPIO_INPUT); - gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 0); - /* Fall through */ -#endif -#if CONFIG_USB_PD_PORT_MAX_COUNT >= 1 - case 1: - gpio_set_flags(GPIO_USB_C0_5V_EN, GPIO_PULL_DOWN | GPIO_INPUT); - gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0); - /* Fall through */ -#endif - case 0: - /* Nothing to do but break */ - break; - default: - /* More ports needs to be defined */ - ASSERT(false); - break; - } -#endif /* CONFIG_USB_PD_PORT_MAX_COUNT */ - - if (hibernate_wake_pins_used > 0) { - for (i = 0; i < hibernate_wake_pins_used; ++i) { - const enum gpio_signal pin = hibernate_wake_pins[i]; - - gpio_reset(pin); - gpio_enable_interrupt(pin); - } - - interrupt_enable(); - task_enable_irq(MEC1322_IRQ_GIRQ8); - task_enable_irq(MEC1322_IRQ_GIRQ9); - task_enable_irq(MEC1322_IRQ_GIRQ10); - task_enable_irq(MEC1322_IRQ_GIRQ11); - task_enable_irq(MEC1322_IRQ_GIRQ20); - } - - if (seconds || microseconds) { - MEC1322_INT_BLK_EN |= BIT(17); - MEC1322_INT_ENABLE(17) |= BIT(20); - interrupt_enable(); - task_enable_irq(MEC1322_IRQ_HTIMER); - if (seconds > 2) { - ASSERT(seconds <= 0xffff / 8); - MEC1322_HTIMER_CONTROL = 1; - MEC1322_HTIMER_PRELOAD = - (seconds * 8 + microseconds / 125000); - } else { - MEC1322_HTIMER_CONTROL = 0; - MEC1322_HTIMER_PRELOAD = - (seconds * 1000000 + microseconds) * 2 / 71; - } - } - - asm("wfi"); - - /* Use 48MHz clock to speed through wake-up */ - MEC1322_PCR_PROC_CLK_CTL = 1; - - /* Reboot */ - _system_reset(0, 1); - - /* We should never get here. */ - while (1) - ; -} - -void htimer_interrupt(void) -{ - /* Time to wake up */ -} -DECLARE_IRQ(MEC1322_IRQ_HTIMER, htimer_interrupt, 1); - -enum ec_image system_get_shrspi_image_copy(void) -{ - return MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX); -} - -uint32_t system_get_lfw_address(void) -{ - uint32_t * const lfw_vector = - (uint32_t * const)CONFIG_PROGRAM_MEMORY_BASE; - - return *(lfw_vector + 1); -} - -void system_set_image_copy(enum ec_image copy) -{ - MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX) = (copy == EC_IMAGE_RW) ? - EC_IMAGE_RW : EC_IMAGE_RO; -} diff --git a/chip/mec1322/uart.c b/chip/mec1322/uart.c deleted file mode 100644 index 2c607d0b72..0000000000 --- a/chip/mec1322/uart.c +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* UART module for MEC1322 */ - -#include "clock.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "lpc.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "uart.h" -#include "util.h" - -#define TX_FIFO_SIZE 16 - -static int init_done; -static int tx_fifo_used; - -int uart_init_done(void) -{ - return init_done; -} - -void uart_tx_start(void) -{ - /* If interrupt is already enabled, nothing to do */ - if (MEC1322_UART_IER & BIT(1)) - return; - - /* Do not allow deep sleep while transmit in progress */ - disable_sleep(SLEEP_MASK_UART); - - /* - * Re-enable the transmit interrupt, then forcibly trigger the - * interrupt. This works around a hardware problem with the - * UART where the FIFO only triggers the interrupt when its - * threshold is _crossed_, not just met. - */ - MEC1322_UART_IER |= BIT(1); - task_trigger_irq(MEC1322_IRQ_UART); -} - -void uart_tx_stop(void) -{ - MEC1322_UART_IER &= ~BIT(1); - - /* Re-allow deep sleep */ - enable_sleep(SLEEP_MASK_UART); -} - -void uart_tx_flush(void) -{ - /* Wait for transmit FIFO empty */ - while (!(MEC1322_UART_LSR & MEC1322_LSR_TX_EMPTY)) - ; -} - -int uart_tx_ready(void) -{ - /* - * We have no indication of free space in transmit FIFO. To work around - * this, we check transmit FIFO empty bit every 16 characters written. - */ - return tx_fifo_used != 0 || (MEC1322_UART_LSR & MEC1322_LSR_TX_EMPTY); -} - -int uart_tx_in_progress(void) -{ - /* return 0: FIFO is empty, 1: FIFO NOT Empty */ - return !(MEC1322_UART_LSR & MEC1322_LSR_TX_EMPTY); -} - -int uart_rx_available(void) -{ - return MEC1322_UART_LSR & BIT(0); -} - -void uart_write_char(char c) -{ - /* Wait for space in transmit FIFO. */ - while (!uart_tx_ready()) - ; - - tx_fifo_used = (tx_fifo_used + 1) % TX_FIFO_SIZE; - MEC1322_UART_TB = c; -} - -int uart_read_char(void) -{ - return MEC1322_UART_RB; -} - -static void uart_clear_rx_fifo(int channel) -{ - MEC1322_UART_FCR = BIT(0) | BIT(1); -} - -/** - * Interrupt handler for UART - */ -void uart_ec_interrupt(void) -{ - /* Read input FIFO until empty, then fill output FIFO */ - uart_process_input(); - uart_process_output(); -} -DECLARE_IRQ(MEC1322_IRQ_UART, uart_ec_interrupt, 1); - -void uart_init(void) -{ - /* Set UART to reset on VCC1_RESET instaed of nSIO_RESET */ - MEC1322_UART_CFG &= ~BIT(1); - - /* Baud rate = 115200. 1.8432MHz clock. Divisor = 1 */ - - /* Set CLK_SRC = 0 */ - MEC1322_UART_CFG &= ~BIT(0); - - /* Set DLAB = 1 */ - MEC1322_UART_LCR |= BIT(7); - - /* PBRG0/PBRG1 */ - MEC1322_UART_PBRG0 = 1; - MEC1322_UART_PBRG1 = 0; - - /* Set DLAB = 0 */ - MEC1322_UART_LCR &= ~BIT(7); - - /* Set word length to 8-bit */ - MEC1322_UART_LCR |= BIT(0) | BIT(1); - - /* Enable FIFO */ - MEC1322_UART_FCR = BIT(0); - - /* Activate UART */ - MEC1322_UART_ACT |= BIT(0); - - /* - clock_enable_peripheral(CGC_OFFSET_UART, mask, - CGC_MODE_RUN | CGC_MODE_SLEEP);*/ - - gpio_config_module(MODULE_UART, 1); - - /* - * Enable interrupts for UART0. - */ - uart_clear_rx_fifo(0); - MEC1322_UART_IER |= BIT(0); - MEC1322_UART_MCR |= BIT(3); - MEC1322_INT_ENABLE(15) |= BIT(0); - MEC1322_INT_BLK_EN |= BIT(15); - task_enable_irq(MEC1322_IRQ_UART); - - init_done = 1; -} - -#ifdef CONFIG_LOW_POWER_IDLE -void uart_enter_dsleep(void) -{ - /* Disable the UART interrupt. */ - task_disable_irq(MEC1322_IRQ_UART); /* NVIC interrupt for UART=13 */ - - /* - * Set the UART0 RX pin to be a GPIO-162(fixed pin) interrupt - * with the flags defined in the gpio.inc file. - */ - gpio_reset(GPIO_UART0_RX); - - /* power-down/de-activate UART0 */ - MEC1322_UART_ACT &= ~BIT(0); - - /* Clear pending interrupts on GPIO_UART0_RX(GPIO162, girq=8, bit=18) */ - MEC1322_INT_SOURCE(8) = (1<<18); - - /* Enable GPIO interrupts on the UART0 RX pin. */ - gpio_enable_interrupt(GPIO_UART0_RX); -} - - -void uart_exit_dsleep(void) -{ - /* - * If the UART0 RX GPIO interrupt has not fired, then no edge has been - * detected. Disable the GPIO interrupt so that switching the pin over - * to a UART pin doesn't inadvertently cause a GPIO edge interrupt. - * Note: we can't disable this interrupt if it has already fired - * because then the IRQ will not run at all. - */ - if (!(BIT(18) & MEC1322_INT_SOURCE(8))) /* if edge interrupt */ - gpio_disable_interrupt(GPIO_UART0_RX); - - /* Configure UART0 pins for use in UART peripheral. */ - gpio_config_module(MODULE_UART, 1); - - /* Clear pending interrupts on UART peripheral and enable interrupts. */ - uart_clear_rx_fifo(0); - task_enable_irq(MEC1322_IRQ_UART); /* NVIC interrupt for UART = 13 */ - - /* power-up/activate UART0 */ - MEC1322_UART_ACT |= BIT(0); -} - -void uart_deepsleep_interrupt(enum gpio_signal signal) -{ - /* - * Activity seen on UART RX pin while UART was disabled for deep sleep. - * The console won't see that character because the UART is disabled, - * so we need to inform the clock module of UART activity ourselves. - */ - clock_refresh_console_in_use(); - - /* Disable interrupts on UART0 RX pin to avoid repeated interrupts. */ - gpio_disable_interrupt(GPIO_UART0_RX); -} -#endif /* CONFIG_LOW_POWER_IDLE */ diff --git a/chip/mec1322/util/pack_ec.py b/chip/mec1322/util/pack_ec.py deleted file mode 100755 index bec27bdcce..0000000000 --- a/chip/mec1322/util/pack_ec.py +++ /dev/null @@ -1,244 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2013 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# A script to pack EC binary into SPI flash image for MEC1322 -# Based on MEC1322_ROM_Doc_Rev0.5.pdf. - -import argparse -import hashlib -import os -import struct -import subprocess -import tempfile - -LOAD_ADDR = 0x100000 -HEADER_SIZE = 0x140 -SPI_CLOCK_LIST = [48, 24, 12, 8] -SPI_READ_CMD_LIST = [0x3, 0xb, 0x3b] - -CRC_TABLE = [0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, - 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d] - -def Crc8(crc, data): - """Update CRC8 value.""" - for v in data: - crc = ((crc << 4) & 0xff) ^ (CRC_TABLE[(crc >> 4) ^ (v >> 4)]); - crc = ((crc << 4) & 0xff) ^ (CRC_TABLE[(crc >> 4) ^ (v & 0xf)]); - return crc ^ 0x55 - -def GetEntryPoint(payload_file): - """Read entry point from payload EC image.""" - with open(payload_file, 'rb') as f: - f.seek(4) - s = f.read(4) - return struct.unpack('> 6) & 0xff) - header.append((payload_len >> 14) & 0xff) - PadZeroTo(header, 0x14) - header.extend(struct.pack('> 8) & 0xff, - (args.header_loc >> 16) & 0xff, - (args.header_loc >> 24) & 0xff]) - if args.chip_select != 0: - tag[2] |= 0x80 - tag.append(Crc8(0, tag)) - return tag - -def PacklfwRoImage(rorw_file, loader_file, image_size): - """TODO:Clean up to get rid of Temp file and just use memory - to save data""" - """Create a temp file with the - first image_size bytes from the rorw file and the - bytes from the loader_file appended - return the filename""" - fo=tempfile.NamedTemporaryFile(delete=False) # Need to keep file around - with open(loader_file,'rb') as fin1: - pro = fin1.read() - fo.write(pro) - with open(rorw_file, 'rb') as fin: - ro = fin.read(image_size) - fo.write(ro) - fo.close() - return fo.name - -def parseargs(): - parser = argparse.ArgumentParser() - parser.add_argument("-i", "--input", - help="EC binary to pack, usually ec.bin or ec.RO.flat.", - metavar="EC_BIN", default="ec.bin") - parser.add_argument("-o", "--output", - help="Output flash binary file", - metavar="EC_SPI_FLASH", default="ec.packed.bin") - parser.add_argument("--header_key", - help="PEM key file for signing header", - default="rsakey_sign_header.pem") - parser.add_argument("--payload_key", - help="PEM key file for signing payload", - default="rsakey_sign_payload.pem") - parser.add_argument("--loader_file", - help="EC loader binary", - default="ecloader.bin") - parser.add_argument("-s", "--spi_size", type=int, - help="Size of the SPI flash in MB", - default=4) - parser.add_argument("-l", "--header_loc", type=int, - help="Location of header in SPI flash", - default=0x170000) - parser.add_argument("-p", "--payload_offset", type=int, - help="The offset of payload from the header", - default=0x240) - parser.add_argument("-r", "--rwpayload_loc", type=int, - help="The offset of payload from the header", - default=0x190000) - parser.add_argument("-z", "--romstart", type=int, - help="The first location to output of the rom", - default=0) - parser.add_argument("-c", "--chip_select", type=int, - help="Chip select signal to use, either 0 or 1.", - default=0) - parser.add_argument("--spi_clock", type=int, - help="SPI clock speed. 8, 12, 24, or 48 MHz.", - default=24) - parser.add_argument("--spi_read_cmd", type=int, - help="SPI read command. 0x3, 0xB, or 0x3B.", - default=0xb) - parser.add_argument("--image_size", type=int, - help="Size of a single image.", - default=(96 * 1024)) - return parser.parse_args() - -def main(): - args = parseargs() - - spi_size = args.spi_size * 1024 - args.header_loc = spi_size - (128 * 1024) - args.rwpayload_loc = spi_size - (256 * 1024) - args.romstart = spi_size - (256 * 1024) - - spi_list = [] - - rorofile=PacklfwRoImage(args.input, args.loader_file, args.image_size) - payload = GetPayload(rorofile) - payload_len = len(payload) - payload_signature = SignByteArray(payload, args.payload_key) - header = BuildHeader(args, payload_len, rorofile) - header_signature = SignByteArray(header, args.header_key) - tag = BuildTag(args) - # truncate the RW to 128k - payloadrw = GetPayloadFromOffset(args.input,args.image_size)[:128*1024] - os.remove(rorofile) # clean up the temp file - - spi_list.append((args.header_loc, header, "header")) - spi_list.append((args.header_loc + HEADER_SIZE, header_signature, "header_signature")) - spi_list.append((args.header_loc + args.payload_offset, payload, "payload")) - spi_list.append((args.header_loc + args.payload_offset + payload_len, - payload_signature, "payload_signature")) - spi_list.append((spi_size - 256, tag, "tag")) - spi_list.append((args.rwpayload_loc, payloadrw, "payloadrw")) - - - spi_list = sorted(spi_list) - - with open(args.output, 'wb') as f: - addr = args.romstart - for s in spi_list: - assert addr <= s[0] - if addr < s[0]: - f.write(b'\xff' * (s[0] - addr)) - addr = s[0] - f.write(s[1]) - addr += len(s[1]) - if addr < spi_size: - f.write(b'\xff' * (spi_size - addr)) - -if __name__ == '__main__': - main() diff --git a/chip/mec1322/util/rsakey_sign_header.pem b/chip/mec1322/util/rsakey_sign_header.pem deleted file mode 100644 index 37799ebbec..0000000000 --- a/chip/mec1322/util/rsakey_sign_header.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCd0knJ+sVzkO40 -g7VguqpqrmwqgYPfgq3m7GHGitWgxjM/JDpKaOvq4G9O+yYUD/75V5GZJkRY0iE8 -MJCCvSkyoFHcCP0jvma9G/c13wXfLPGUunrJnV+Wzwy5+S1MXdax532gK9qeUmOB -HpIttkFRl3qhVHu9to2dbsx1S/AIA0GIPAINkcZxfRCAcheIoqK/oMqse+EDS9Zm -6frha9oS1+iRlqMPYKrOgWTKnkY3H/4M/HFj90hVzxun3qQj0mo3EdYoSrbCnyjG -JNjnuCdSEODmG5+FCTVWCfl/AolYmOWjMfCnfX7/HlfhOY+fOR91FKrgOjWHHf3a -0FhdUZDNAgMBAAECggEBAJKea6j2jXu42GP3PIk5wdrMYnb2zeHXEOJpFskR8Dem -CrQNXw4D/bC+gwo4Lv8SgUl6PiyurW5rAS9e2tJrFBwRbxthSnNrjxz/HyJwKI9W -vLT0reAikUyU3Hjl8lxxDWVH76DfPQI6/nBVS26mVHaNqQK6bx8nutbYuZ/7RWra -zatdjrl29D0E/xTva0S4AUPI7DmflwS6YbfVlTsyhnwphaEwD7eCDhD9h4nGQG8z -0WKDN2X1F7CmjrK9fy7SCHO9SKc3WNSjp2Dc0ImF2k72Mfw5jtOs81lczktztPy0 -gv4x6Tg0ws4Et9eI6Ub80tAZ+wQ5Vj+wzExMOp4K5KECgYEA0jz5IsRmie6y/WRG -6dI98nnyLoISIQue8xOA5J/OUyYfHn9CgJvGslRVg2mmSQ9GPkaMIN0dADvB6Tsh -XelAZZjnAo8pSyahz3OdcdgP6xksMjtKReXiLqu0ntfQS42nQDYNvRd2/clrYYRN -SlijT53QMqI4DSMz+0rLqUwvRskCgYEAwCyEEJ1Z/CI2ONN1tIEnJSuzZRYxlwNL -mVXx03ZSVi+L2MOMJjiCoeUZ/MVSacW+Elg6aU3U1GdOhNfQaPZJNqISACtm314Y -Xi9bMXegyQp3uBRnEah82ejm8hloOAOKZNgbqgt9o6FDrsccw3udIgzsgPY4koUK -1fNrDPJ5x+UCgYBwlEH8whr+hZnHYqkukGynqXFsQi6fD3AATlNZGdIMaH+FfzQH -VmNiHxLjmfF3cfx1YKWs+3qKI3XFBOrrNPpM7UHW9v5vxbIkOo725XIwvHwUMfel -0mH6B+ximsJpkuMa2VcmCKipYfBkecpBo5FgEuvoEUHelxlA2V6Ru8AdMQKBgQC/ -uanoiZQFIHzIJPABrfjH9Nl9uK6w4vDBgiVJu3pZ0gXLtQxV9Xse2dsbfCHEtSv0 -UWG1PZlgb9C+aDHdBhn1D6y1zpdLsizNiqGIsLkQ2gim9nP+AgLNxLbkQsTfXWjt -Q04WUHCAl5tW+/+OZ/1Uw2ARKZU3WNR+r+PVfvRQoQKBgQCjksWLe3Zx2yxnUenz -vaY09UTt42rawbUkm+xpNzOt7K1TudRODe444XG9fFgkNa5HPiAENoZ91Jv223x8 -Fi2SjfGA6/r/J1ash4cDcJLogTEP27YyJyhwXZFKtjfFeD3e2hvcMFMDG4EBHHXd -Bv/r6+6E+f30Y4bN3ZgK/rN6Tg== ------END PRIVATE KEY----- diff --git a/chip/mec1322/util/rsakey_sign_payload.pem b/chip/mec1322/util/rsakey_sign_payload.pem deleted file mode 100644 index 6845097749..0000000000 --- a/chip/mec1322/util/rsakey_sign_payload.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQaeNJ6+a/KXhs -/0Xa2coG+4d+pc+4qs4O/6caxAtzr1YP155C4QxqfZw0DETreK7K/kgSgOJ6Q1gW -Yo88Fb4foxVYJbV2Bb+mdNlaHP/o6TrvBmqdsIjP5u1FwtmjquaewL2E3T4rHCXl -QgM7AQXAFzKt2HeaMeHvC2t+x/AganhfztOpqhGTL6lHiLC55SPNkWCb3GokotbL -Ul7q+wLSTpKS0vNuigjGVBVuV7YrwWhehOoLuV5FDMXHlMTemYH6+V5j78ZtSrXm -0RmKAKXoO+HbKbgALICUw5kzxXLSAoHx2rXLlou9I00olxsWir1lokxaWa1La3wA -pr214pxXAgMBAAECggEAdsXxrz4OeaEDrXJpeAioNwR/unB6ie5lkmyl6f4R3LLu -5AZofgrNTZ8aNxtK57sWOj9iCZGEAFOCzvcKVB68BEGnt11+Ja2vBAkRmWZvfWf1 -myTX+9gQkBM144zhBYIu/ggvuZlwhZb8DcRqHOU/RrKxwhtcRfbpoJasg0skkQO0 -bU2hwSu4kM+T2diyXp4V1PR4vrxZPNQ+B8sWxWKJs58+3NdWswwe9NcFQla0QTFz -7MIlMJNlJgTXjSYC8TjDlBlevwE5HoikpfSSvFr4uouyfpfWBxNFd8Tm/yFSTUqY -XO3oyU/NLK+BN7Sxj6Cs1Fx65yhMCmsqGQqCNOz2OQKBgQD4gIF6vVduyKfPV3EE -4lhFktlFRXeR+z9LXpGth3vwNN0XpPql1jr8hYPQqpSKefZRF5r8hLjt2ZaLDbnb -iVYwHxbXRuF5P6qsaSy1uVYG4og5LV5ddSBzf+/MhDInQk/O5tdvOrgQfcJzRJRg -MSx5uzs66r8/AFKCVTB/ptNgzQKBgQDWs7qqaHNHGRRfegRhwkkDvhRAMQKWsgL7 -kTWw/qW+b8mRYhCC4JvbU+OeFkf5kejGpFgDuvB4eH+rsPRVU8jSWZXrMKjGdZN1 -T6fFa5vz1VsRNhiVU3F2jfXTY5t7qQ18jEoMQxGxdGJy52Py+3N34ZWNS4cifLNS -rYjZnQmhswKBgD3rd1foGgMmyHmnpie7ZpdfcfgKyTJ80larZ80/dyhxY63ik/oC -mYwWkLPL7Vtb7H5kTWAiihnqH9LiRq9nVyyCcqSNqt0VeiefxV46oi7w/1SP83WC -G+XruQrS3dRed5hseL3kebzSOUOTkQ0u85AZkTarC6BdKjIDnCQSo5T5AoGAKNep -087o1waTVJJOkRY3c4nOKmPoXShh3t9BunjGqNJ1Ir3n7C20GGX9783HRVeXU2ph -/9uo8RHjH5Ma97xngHRgS4xHHvGw6mkLvkd5NEpK95w10vo7pFTfBaZ2JnEDSsUZ -NPnxPLOqIreX0No6nfyAyY8rlsjoB/tRBCyWb3cCgYEAgzJCllzahDvgCbmjI9Km -h7mUVc5U2fQR5B/WRa5iTSlQd+O4TXna7ZCxKDyYlesSBAiKanX0669Iri6cu4S6 -gMc7MJmm3VrnZGXoukSv3Zyot+hkaFrZTrXAIQiuYDK6YC5OK7kqM+DqtJOWUsfg -itdiqPKeYtViDQkxqJ1nkSw= ------END PRIVATE KEY----- diff --git a/chip/mec1322/watchdog.c b/chip/mec1322/watchdog.c deleted file mode 100644 index ad93fb1240..0000000000 --- a/chip/mec1322/watchdog.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Watchdog driver */ - -#include "hooks.h" -#include "registers.h" -#include "task.h" -#include "watchdog.h" - -void watchdog_reload(void) -{ - MEC1322_WDG_KICK = 1; - -#ifdef CONFIG_WATCHDOG_HELP - /* Reload the auxiliary timer */ - MEC1322_TMR16_CTL(0) &= ~BIT(5); - MEC1322_TMR16_CNT(0) = CONFIG_AUX_TIMER_PERIOD_MS; - MEC1322_TMR16_CTL(0) |= BIT(5); -#endif -} -DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); - -int watchdog_init(void) -{ -#ifdef CONFIG_WATCHDOG_HELP - uint32_t val; - - /* - * Watchdog does not warn us before expiring. Let's use a 16-bit - * timer as an auxiliary timer. - */ - - /* Stop the auxiliary timer if it's running */ - MEC1322_TMR16_CTL(0) &= ~BIT(5); - - /* Enable auxiliary timer */ - MEC1322_TMR16_CTL(0) |= BIT(0); - - val = MEC1322_TMR16_CTL(0); - - /* Pre-scale = 48000 -> 1kHz -> Period = 1ms */ - val = (val & 0xffff) | (47999 << 16); - - /* No auto restart */ - val &= ~BIT(3); - - /* Count down */ - val &= ~BIT(2); - - MEC1322_TMR16_CTL(0) = val; - - /* Enable interrupt from auxiliary timer */ - MEC1322_TMR16_IEN(0) |= 1; - task_enable_irq(MEC1322_IRQ_TIMER16_0); - MEC1322_INT_ENABLE(23) |= BIT(0); - MEC1322_INT_BLK_EN |= BIT(23); - - /* Load and start the auxiliary timer */ - MEC1322_TMR16_CNT(0) = CONFIG_AUX_TIMER_PERIOD_MS; - MEC1322_TMR16_CNT(0) |= BIT(5); -#endif - - /* Set timeout. It takes 1007us to decrement WDG_CNT by 1. */ - MEC1322_WDG_LOAD = CONFIG_WATCHDOG_PERIOD_MS * 1000 / 1007; - - /* Start watchdog */ - MEC1322_WDG_CTL |= 1; - - return EC_SUCCESS; -} - -#ifdef CONFIG_WATCHDOG_HELP -void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp) -{ - /* Clear status */ - MEC1322_TMR16_STS(0) |= 1; - - watchdog_trace(excep_lr, excep_sp); -} - -void IRQ_HANDLER(MEC1322_IRQ_TIMER16_0)(void) __attribute__((naked)); -void IRQ_HANDLER(MEC1322_IRQ_TIMER16_0)(void) -{ - /* Naked call so we can extract raw LR and SP */ - asm volatile("mov r0, lr\n" - "mov r1, sp\n" - /* Must push registers in pairs to keep 64-bit aligned - * stack for ARM EABI. This also conveninently saves - * R0=LR so we can pass it to task_resched_if_needed. */ - "push {r0, lr}\n" - "bl watchdog_check\n" - "pop {r0, lr}\n" - "b task_resched_if_needed\n"); -} -const struct irq_priority __keep IRQ_PRIORITY(MEC1322_IRQ_TIMER16_0) - __attribute__((section(".rodata.irqprio"))) - = {MEC1322_IRQ_TIMER16_0, 0}; /* put the watchdog at the - highest priority */ -#endif diff --git a/chip/mt8192_scp/build.mk b/chip/mt8192_scp/build.mk deleted file mode 100644 index 0925ff2245..0000000000 --- a/chip/mt8192_scp/build.mk +++ /dev/null @@ -1,27 +0,0 @@ -# -*- makefile -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# SCP specific files build -# - -CORE:=riscv-rv32i - -# Required chip modules -chip-y+=clock.o -chip-y+=gpio.o -chip-y+=intc.o -chip-y+=memmap.o -chip-y+=system.o -chip-y+=uart.o - -ifeq ($(CONFIG_IPI),y) -$(out)/RW/chip/$(CHIP)/ipi_table.o: $(out)/ipi_table_gen.inc -endif - -# Optional chip modules -chip-$(CONFIG_COMMON_TIMER)+=hrtimer.o -chip-$(CONFIG_IPI)+=ipi.o ipi_table.o -chip-$(CONFIG_WATCHDOG)+=watchdog.o -chip-$(HAS_TASK_HOSTCMD)+=hostcmd.o diff --git a/chip/mt8192_scp/clock.c b/chip/mt8192_scp/clock.c deleted file mode 100644 index ee7970a71a..0000000000 --- a/chip/mt8192_scp/clock.c +++ /dev/null @@ -1,343 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Clocks, PLL and power settings */ - -#include -#include - -#include "clock_chip.h" -#include "clock.h" -#include "console.h" -#include "csr.h" -#include "registers.h" -#include "timer.h" - -#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args) - -static struct opp_ulposc_cfg { - uint32_t osc; - uint32_t div; - uint32_t fband; - uint32_t mod; - uint32_t cali; - uint32_t target_mhz; -} opp[] = { - { - .osc = 1, .target_mhz = 196, .div = 20, .fband = 10, .mod = 3, - .cali = 64, - }, - { - .osc = 0, .target_mhz = 260, .div = 14, .fband = 2, .mod = 0, - .cali = 64, - }, - { - .osc = 1, .target_mhz = 280, .div = 20, .fband = 2, .mod = 0, - .cali = 64, - }, - { - .osc = 1, .target_mhz = 360, .div = 20, .fband = 10, .mod = 0, - .cali = 64, - }, -}; - -static inline void clock_busy_udelay(int usec) -{ - /* - * Delaying by busy-looping, for place that can't use udelay because of - * the clock not configured yet. The value 28 is chosen approximately - * from experiment. - * - * `volatile' in order to avoid compiler to optimize the function out - * (otherwise, the function will be eliminated). - */ - volatile int i = usec * 28; - - while (--i) - ; -} - -static void clock_ulposc_config_default(struct opp_ulposc_cfg *opp) -{ - unsigned int val = 0; - - /* set div */ - val |= opp->div << OSC_DIV_SHIFT; - /* set F-band; I-band = 82 */ - val |= (opp->fband << OSC_FBAND_SHIFT) | (82 << OSC_IBAND_SHIFT); - /* set calibration */ - val |= opp->cali; - /* set control register 0 */ - AP_ULPOSC_CON0(opp->osc) = val; - - /* set mod */ - val = opp->mod << OSC_MOD_SHIFT; - /* rsv2 = 0, rsv1 = 41, cali_32k = 0 */ - val |= 41 << OSC_RSV1_SHIFT; - /* set control register 1 */ - AP_ULPOSC_CON1(opp->osc) = val; - - /* bias = 64 */ - AP_ULPOSC_CON2(opp->osc) = 64; -} - -static void clock_ulposc_config_cali(struct opp_ulposc_cfg *opp, - uint32_t cali_val) -{ - uint32_t val; - - val = AP_ULPOSC_CON0(opp->osc); - val &= ~OSC_CALI_MASK; - val |= cali_val; - AP_ULPOSC_CON0(opp->osc) = val; - - clock_busy_udelay(50); -} - -static uint32_t clock_ulposc_measure_freq(uint32_t osc) -{ - uint32_t result = 0; - int cnt; - - /* before select meter clock input, bit[1:0] = b00 */ - AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_MODE_MASK) | - DBG_MODE_SET_CLOCK; - - /* select source, bit[21:16] = clk_src */ - AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_BIST_SOURCE_MASK) | - (osc == 0 ? DBG_BIST_SOURCE_ULPOSC1 : - DBG_BIST_SOURCE_ULPOSC2); - - /* set meter divisor to 1, bit[31:24] = b00000000 */ - AP_CLK_MISC_CFG_0 = (AP_CLK_MISC_CFG_0 & ~MISC_METER_DIVISOR_MASK) | - MISC_METER_DIV_1; - - /* enable frequency meter, without start */ - AP_SCP_CFG_0 |= CFG_FREQ_METER_ENABLE; - - /* trigger frequency meter start */ - AP_SCP_CFG_0 |= CFG_FREQ_METER_RUN; - - /* - * Frequency meter counts cycles in 1 / (26 * 1024) second period. - * freq_in_hz = freq_counter * 26 * 1024 - * - * The hardware takes 38us to count cycles. Delay up to 100us, - * as clock_busy_udelay may not be accurate when sysclk is not 26Mhz - * (e.g. when recalibrating/measuring after boot). - */ - for (cnt = 100; cnt > 0; --cnt) { - clock_busy_udelay(1); - if (!(AP_SCP_CFG_0 & CFG_FREQ_METER_RUN)) { - result = CFG_FREQ_COUNTER(AP_SCP_CFG_1); - break; - } - } - - /* disable freq meter */ - AP_SCP_CFG_0 &= ~CFG_FREQ_METER_ENABLE; - - return result; -} - -#define CAL_MIS_RATE 40 -static int clock_ulposc_is_calibrated(struct opp_ulposc_cfg *opp) -{ - uint32_t curr, target; - - curr = clock_ulposc_measure_freq(opp->osc); - target = opp->target_mhz * 1024 / 26; - - /* check if calibrated value is in the range of target value +- 4% */ - if (curr > (target * (1000 - CAL_MIS_RATE) / 1000) && - curr < (target * (1000 + CAL_MIS_RATE) / 1000)) - return 1; - else - return 0; -} - -static uint32_t clock_ulposc_process_cali(struct opp_ulposc_cfg *opp) -{ - uint32_t current_val = 0; - uint32_t target_val = opp->target_mhz * 1024 / 26; - uint32_t middle, min = 0, max = OSC_CALI_MASK; - uint32_t diff_by_min, diff_by_max, cal_result; - - do { - middle = (min + max) / 2; - if (middle == min) - break; - - clock_ulposc_config_cali(opp, middle); - current_val = clock_ulposc_measure_freq(opp->osc); - - if (current_val > target_val) - max = middle; - else - min = middle; - } while (min <= max); - - clock_ulposc_config_cali(opp, min); - current_val = clock_ulposc_measure_freq(opp->osc); - if (current_val > target_val) - diff_by_min = current_val - target_val; - else - diff_by_min = target_val - current_val; - - clock_ulposc_config_cali(opp, max); - current_val = clock_ulposc_measure_freq(opp->osc); - if (current_val > target_val) - diff_by_max = current_val - target_val; - else - diff_by_max = target_val - current_val; - - if (diff_by_min < diff_by_max) - cal_result = min; - else - cal_result = max; - - clock_ulposc_config_cali(opp, cal_result); - if (!clock_ulposc_is_calibrated(opp)) - assert(0); - - return cal_result; -} - -static void clock_high_enable(int osc) -{ - /* enable high speed clock */ - SCP_CLK_ENABLE |= CLK_HIGH_EN; - - switch (osc) { - case 0: - /* after 150us, enable ULPOSC */ - clock_busy_udelay(150); - SCP_CLK_ENABLE |= CLK_HIGH_CG; - break; - case 1: - /* turn off ULPOSC2 high-core-disable switch */ - SCP_CLK_ON_CTRL &= ~HIGH_CORE_DIS_SUB; - /* after 150us, turn on ULPOSC2 high core clock gate */ - clock_busy_udelay(150); - SCP_CLK_HIGH_CORE_CG |= HIGH_CORE_CG; - clock_busy_udelay(50); - break; - default: - break; - } -} - -static void clock_high_disable(int osc) -{ - switch (osc) { - case 0: - SCP_CLK_ENABLE &= ~CLK_HIGH_CG; - clock_busy_udelay(50); - SCP_CLK_ENABLE &= ~CLK_HIGH_EN; - clock_busy_udelay(50); - break; - case 1: - SCP_CLK_HIGH_CORE_CG &= ~HIGH_CORE_CG; - clock_busy_udelay(50); - SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB; - clock_busy_udelay(50); - break; - default: - break; - } -} - -static void clock_calibrate_ulposc(struct opp_ulposc_cfg *opp) -{ - /* - * ULPOSC1(osc=0) is already - * - calibrated - * - enabled in coreboot - * - used by pmic wrapper - */ - if (opp->osc != 0) { - clock_high_disable(opp->osc); - clock_ulposc_config_default(opp); - clock_high_enable(opp->osc); - } - - /* Calibrate only if it is not accurate enough. */ - if (!clock_ulposc_is_calibrated(opp)) - opp->cali = clock_ulposc_process_cali(opp); - -#ifdef DEBUG - CPRINTF("osc:%u, target=%uMHz, cal:%u\n", - opp->osc, opp->target_mhz, opp->cali); -#endif -} - -void clock_select_clock(enum scp_clock_source src) -{ - /* - * DIV2 divider takes precedence over clock selection to prevent - * over-clocking. - */ - if (src == SCP_CLK_ULPOSC1) - SCP_CLK_DIV_SEL = CLK_DIV_SEL2; - - SCP_CLK_SW_SEL = src; - - if (src != SCP_CLK_ULPOSC1) - SCP_CLK_DIV_SEL = CLK_DIV_SEL1; -} - -void clock_init(void) -{ - int i; - - /* select default 26M system clock */ - clock_select_clock(SCP_CLK_26M); - - /* set VREQ to HW mode */ - SCP_CPU_VREQ_CTRL = VREQ_SEL | VREQ_DVFS_SEL; - SCP_CLK_CTRL_GENERAL_CTRL &= ~VREQ_PMIC_WRAP_SEL; - SCP_SEC_CTRL &= ~VREQ_SECURE_DIS; - - /* set DDREN to auto mode */ - SCP_SYS_CTRL |= AUTO_DDREN; - - /* set settle time */ - SCP_CLK_SYS_VAL = - (SCP_CLK_SYS_VAL & ~CLK_SYS_VAL_MASK) | CLK_SYS_VAL_VAL(1); - SCP_CLK_HIGH_VAL = - (SCP_CLK_HIGH_VAL & ~CLK_HIGH_VAL_MASK) | CLK_HIGH_VAL_VAL(1); - SCP_SLEEP_CTRL = - (SCP_SLEEP_CTRL & ~VREQ_COUNT_MASK) | VREQ_COUNT_VAL(1); - - /* turn off ULPOSC2 */ - SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB; - - /* calibrate ULPOSC */ - for (i = 0; i < ARRAY_SIZE(opp); ++i) - clock_calibrate_ulposc(&opp[i]); - - /* select ULPOSC2 high speed CPU clock */ - clock_select_clock(SCP_CLK_ULPOSC2); - - /* enable default clock gate */ - SCP_SET_CLK_CG |= CG_DMA_CH3 | CG_DMA_CH2 | CG_DMA_CH1 | CG_DMA_CH0 | - CG_I2C_MCLK | CG_MAD_MCLK | CG_AP2P_MCLK; -} - -#ifdef DEBUG -int command_ulposc(int argc, char *argv[]) -{ - int i; - - for (i = 0; i <= 1; ++i) - ccprintf("ULPOSC%u frequency: %u kHz\n", - i + 1, - clock_ulposc_measure_freq(i) * 26 * 1000 / 1024); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[ulposc]", - "Measure ULPOSC frequency"); -#endif diff --git a/chip/mt8192_scp/clock_chip.h b/chip/mt8192_scp/clock_chip.h deleted file mode 100644 index ee1c22be92..0000000000 --- a/chip/mt8192_scp/clock_chip.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Clocks, PLL and power settings */ - -#ifndef __CROS_EC_CLOCK_CHIP_H -#define __CROS_EC_CLOCK_CHIP_H - -#include "registers.h" - -enum scp_clock_source { - SCP_CLK_26M = CLK_SW_SEL_26M, - SCP_CLK_32K = CLK_SW_SEL_32K, - SCP_CLK_ULPOSC2 = CLK_SW_SEL_ULPOSC2, - SCP_CLK_ULPOSC1 = CLK_SW_SEL_ULPOSC1, -}; - -/* Switches to use 'src' clock */ -void clock_select_clock(enum scp_clock_source src); - -#endif /* __CROS_EC_CLOCK_CHIP_H */ diff --git a/chip/mt8192_scp/config_chip.h b/chip/mt8192_scp/config_chip.h deleted file mode 100644 index 2a4c5f7925..0000000000 --- a/chip/mt8192_scp/config_chip.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_CONFIG_CHIP_H -#define __CROS_EC_CONFIG_CHIP_H - -#include "core/riscv-rv32i/config_core.h" - -/* Interval between HOOK_TICK notifications */ -#define HOOK_TICK_INTERVAL_MS 500 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) - -/* RW only, no flash */ -#undef CONFIG_FW_INCLUDE_RO -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_SIZE 0 -#define CONFIG_RW_MEM_OFF 0 -#define CONFIG_RW_SIZE 0x40000 /* 256KB */ -#define CONFIG_EC_WRITABLE_STORAGE_OFF 0 -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_PROGRAM_MEMORY_BASE 0 -#define CONFIG_MAPPED_STORAGE_BASE 0 - -/* Unsupported features/commands */ -#undef CONFIG_CMD_FLASHINFO -#undef CONFIG_CMD_POWER_AP -#undef CONFIG_FLASH -#undef CONFIG_FLASH_PHYSICAL -#undef CONFIG_FMAP -#undef CONFIG_HIBERNATE -#undef CONFIG_LID_SWITCH - -/* Task stack size */ -#define CONFIG_STACK_SIZE 1024 -#define IDLE_TASK_STACK_SIZE 640 -#define SMALLER_TASK_STACK_SIZE 384 -#define TASK_STACK_SIZE 488 -#define LARGER_TASK_STACK_SIZE 640 -#define VENTI_TASK_STACK_SIZE 768 -#define ULTRA_TASK_STACK_SIZE 1056 -#define TRENTA_TASK_STACK_SIZE 1184 - -/* TODO: need to confirm, placeholder */ -#define GPIO_PIN(num) ((num) / 32), ((num) % 32) -#define GPIO_PIN_MASK(p, m) .port = (p), .mask = (m) -#undef CONFIG_TASK_PROFILING -/* TODO: not yet supported */ -#undef CONFIG_MPU -/* TODO: core/riscv-rv32i pollution */ -#define __ram_code - -#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/mt8192_scp/csr.h b/chip/mt8192_scp/csr.h deleted file mode 100644 index e9e95f3ffa..0000000000 --- a/chip/mt8192_scp/csr.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Control and status register */ - -/* TODO: move to core/riscv-rv32i? */ - -#ifndef __CROS_EC_CSR_H -#define __CROS_EC_CSR_H - -#include "common.h" - -static inline uint32_t read_csr(uint32_t reg) -{ - uint32_t val; - - asm volatile("csrr %0, %1" : "=r"(val) : "i"(reg)); - return val; -} - -static inline void write_csr(uint32_t reg, uint32_t val) -{ - asm volatile ("csrw %0, %1" :: "i"(reg), "r"(val)); -} - -static inline uint32_t set_csr(uint32_t reg, uint32_t bit) -{ - uint32_t val; - - asm volatile ("csrrs %0, %1, %2" : "=r"(val) : "i"(reg), "r"(bit)); - return val; -} - -static inline uint32_t clear_csr(uint32_t reg, uint32_t bit) -{ - uint32_t val; - - asm volatile ("csrrc %0, %1, %2" : "=r"(val) : "i"(reg), "r"(bit)); - return val; -} - -/* VIC */ -#define CSR_VIC_MICAUSE (0x5c0) -#define CSR_VIC_MIEMS (0x5c2) -#define CSR_VIC_MIPEND_G0 (0x5d0) -#define CSR_VIC_MIMASK_G0 (0x5d8) -#define CSR_VIC_MIWAKEUP_G0 (0x5e0) -#define CSR_VIC_MILSEL_G0 (0x5e8) -#define CSR_VIC_MIEMASK_G0 (0x5f0) - -/* centralized control enable */ -#define CSR_MCTREN (0x7c0) -/* I$, D$, ITCM, DTCM, BTB, RAS, VIC, CG, mpu */ -#define CSR_MCTREN_ICACHE BIT(0) -#define CSR_MCTREN_DCACHE BIT(1) -#define CSR_MCTREN_ITCM BIT(2) -#define CSR_MCTREN_DTCM BIT(3) -#define CSR_MCTREN_BTB BIT(4) -#define CSR_MCTREN_RAS BIT(5) -#define CSR_MCTREN_VIC BIT(6) -#define CSR_MCTREN_CG BIT(7) -#define CSR_MCTREN_MPU BIT(8) - -#endif /* __CROS_EC_CSR_H */ diff --git a/chip/mt8192_scp/gpio.c b/chip/mt8192_scp/gpio.c deleted file mode 100644 index 0ca3e3ac25..0000000000 --- a/chip/mt8192_scp/gpio.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* GPIO module */ - -#include "gpio.h" - -void gpio_pre_init(void) -{ -} - -test_mockable int gpio_get_level(enum gpio_signal signal) -{ - return 0; -} - -void gpio_set_level(enum gpio_signal signal, int value) -{ -} diff --git a/chip/mt8192_scp/hrtimer.c b/chip/mt8192_scp/hrtimer.c deleted file mode 100644 index a3f0ed3298..0000000000 --- a/chip/mt8192_scp/hrtimer.c +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * High-res hardware timer - * - * SCP hardware 32bit count down timer can be configured to source clock from - * 32KHz, 26MHz, BCLK or PCLK. This implementation selects BCLK (ULPOSC1/8) as a - * source, countdown mode and converts to micro second value matching common - * timer. - */ - -#include "common.h" -#include "hwtimer.h" -#include "registers.h" -#include "task.h" - -#define TIMER_SYSTEM 5 -#define TIMER_EVENT 3 -#define TIMER_CLOCK_MHZ 26 -#define OVERFLOW_TICKS (TIMER_CLOCK_MHZ * 0x100000000 - 1) - -/* High 32-bit for system timer. */ -static uint8_t sys_high; -/* High 32-bit for event timer. */ -static uint8_t event_high; - -static void timer_enable(int n) -{ - /* cannot be changed when timer is enabled */ - SCP_CORE0_TIMER_IRQ_CTRL(n) |= TIMER_IRQ_EN; - SCP_CORE0_TIMER_EN(n) |= TIMER_EN; -} - -static void timer_disable(int n) -{ - SCP_CORE0_TIMER_EN(n) &= ~TIMER_EN; - /* cannot be changed when timer is enabled */ - SCP_CORE0_TIMER_IRQ_CTRL(n) &= ~TIMER_IRQ_EN; -} - -static int timer_is_irq(int n) -{ - return SCP_CORE0_TIMER_IRQ_CTRL(n) & TIMER_IRQ_STATUS; -} - -static void timer_ack_irq(int n) -{ - SCP_CORE0_TIMER_IRQ_CTRL(n) |= TIMER_IRQ_CLR; -} - -static void timer_set_reset_value(int n, uint32_t reset_value) -{ - /* cannot be changed when timer is enabled */ - SCP_CORE0_TIMER_RST_VAL(n) = reset_value; -} - -static void timer_set_clock(int n, uint32_t clock_source) -{ - SCP_CORE0_TIMER_EN(n) = - (SCP_CORE0_TIMER_EN(n) & ~TIMER_CLK_SRC_MASK) | clock_source; -} - -static void timer_reset(int n) -{ - timer_disable(n); - timer_ack_irq(n); - timer_set_reset_value(n, 0xffffffff); - timer_set_clock(n, TIMER_CLK_SRC_32K); -} - -/* Convert hardware countdown timer to 64bit countup ticks. */ -static uint64_t timer_read_raw_system(void) -{ - uint32_t timer_ctrl = SCP_CORE0_TIMER_IRQ_CTRL(TIMER_SYSTEM); - uint32_t sys_high_adj = sys_high; - - /* - * If an IRQ is pending, but has not been serviced yet, adjust the - * sys_high value. - */ - if (timer_ctrl & TIMER_IRQ_STATUS) - sys_high_adj = sys_high ? (sys_high - 1) - : (TIMER_CLOCK_MHZ - 1); - - return OVERFLOW_TICKS - (((uint64_t)sys_high_adj << 32) | - SCP_CORE0_TIMER_CUR_VAL(TIMER_SYSTEM)); -} - -static uint64_t timer_read_raw_event(void) -{ - return OVERFLOW_TICKS - (((uint64_t)event_high << 32) | - SCP_CORE0_TIMER_CUR_VAL(TIMER_EVENT)); -} - -static void timer_reload(int n, uint32_t value) -{ - timer_disable(n); - timer_set_reset_value(n, value); - timer_enable(n); -} - -static int timer_reload_event_high(void) -{ - if (event_high) { - if (SCP_CORE0_TIMER_RST_VAL(TIMER_EVENT) == 0xffffffff) - timer_enable(TIMER_EVENT); - else - timer_reload(TIMER_EVENT, 0xffffffff); - event_high--; - return 1; - } - - timer_disable(TIMER_EVENT); - return 0; -} - -int __hw_clock_source_init(uint32_t start_t) -{ - int t; - - /* enable clock gate */ - SCP_SET_CLK_CG |= CG_TIMER_MCLK | CG_TIMER_BCLK; - - /* reset all timer, select 32768Hz clock source */ - for (t = 0; t < NUM_TIMERS; ++t) - timer_reset(t); - - /* System timestamp timer */ - timer_set_clock(TIMER_SYSTEM, TIMER_CLK_SRC_26M); - sys_high = TIMER_CLOCK_MHZ - 1; - timer_set_reset_value(TIMER_SYSTEM, 0xffffffff); - task_enable_irq(SCP_IRQ_TIMER(TIMER_SYSTEM)); - timer_enable(TIMER_SYSTEM); - - /* Event tick timer */ - timer_set_clock(TIMER_EVENT, TIMER_CLK_SRC_26M); - task_enable_irq(SCP_IRQ_TIMER(TIMER_EVENT)); - - return SCP_IRQ_TIMER(TIMER_SYSTEM); -} - -uint32_t __hw_clock_source_read(void) -{ - return timer_read_raw_system() / TIMER_CLOCK_MHZ; -} - -uint32_t __hw_clock_event_get(void) -{ - return (timer_read_raw_event() + timer_read_raw_system()) - / TIMER_CLOCK_MHZ; -} - -void __hw_clock_event_clear(void) -{ - /* c1ea4, magic number for clear state */ - timer_disable(TIMER_EVENT); - timer_set_reset_value(TIMER_EVENT, 0x0000c1ea4); - event_high = 0; -} - -void __hw_clock_event_set(uint32_t deadline) -{ - uint64_t deadline_raw = (uint64_t)deadline * TIMER_CLOCK_MHZ; - uint64_t now_raw = timer_read_raw_system(); - uint32_t event_deadline; - - if (deadline_raw > now_raw) { - deadline_raw -= now_raw; - event_deadline = (uint32_t)deadline_raw; - event_high = deadline_raw >> 32; - } else { - event_deadline = 1; - event_high = 0; - } - - if (event_deadline) - timer_reload(TIMER_EVENT, event_deadline); - else - timer_reload_event_high(); -} - -static void irq_group6_handler(void) -{ - extern volatile int ec_int; - - switch (ec_int) { - case SCP_IRQ_TIMER(TIMER_EVENT): - if (timer_is_irq(TIMER_EVENT)) { - timer_ack_irq(TIMER_EVENT); - - if (!timer_reload_event_high()) - process_timers(0); - - task_clear_pending_irq(ec_int); - } - break; - case SCP_IRQ_TIMER(TIMER_SYSTEM): - /* If this is a hardware irq, check overflow */ - if (!in_soft_interrupt_context()) { - timer_ack_irq(TIMER_SYSTEM); - - if (sys_high) { - --sys_high; - process_timers(0); - } else { - /* Overflow, reload system timer */ - sys_high = TIMER_CLOCK_MHZ - 1; - process_timers(1); - } - - task_clear_pending_irq(ec_int); - } else { - process_timers(0); - } - break; - } -} -DECLARE_IRQ(6, irq_group6_handler, 0); diff --git a/chip/mt8192_scp/intc.c b/chip/mt8192_scp/intc.c deleted file mode 100644 index bd7416c31e..0000000000 --- a/chip/mt8192_scp/intc.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* INTC control module */ - -#include "console.h" -#include "csr.h" -#include "registers.h" - -/* - * INTC_GRP_0 is reserved. See swirq of syscall_handler() in - * core/riscv-rv32i/task.c for more details. - * - * Lower group has higher priority. - */ -enum INTC_GROUP { - INTC_GRP_0 = 0x0, - INTC_GRP_1, - INTC_GRP_2, - INTC_GRP_3, - INTC_GRP_4, - INTC_GRP_5, - INTC_GRP_6, - INTC_GRP_7, - INTC_GRP_8, - INTC_GRP_9, - INTC_GRP_10, - INTC_GRP_11, - INTC_GRP_12, - INTC_GRP_13, - INTC_GRP_14, -}; - -static struct { - uint8_t group; -} irqs[SCP_INTC_IRQ_COUNT] = { - /* 0 */ - [SCP_IRQ_GIPC_IN0] = { INTC_GRP_7 }, - [SCP_IRQ_GIPC_IN1] = { INTC_GRP_0 }, - [SCP_IRQ_GIPC_IN2] = { INTC_GRP_0 }, - [SCP_IRQ_GIPC_IN3] = { INTC_GRP_0 }, - /* 4 */ - [SCP_IRQ_SPM] = { INTC_GRP_0 }, - [SCP_IRQ_AP_CIRQ] = { INTC_GRP_0 }, - [SCP_IRQ_EINT] = { INTC_GRP_0 }, - [SCP_IRQ_PMIC] = { INTC_GRP_0 }, - /* 8 */ - [SCP_IRQ_UART0_TX] = { INTC_GRP_12 }, - [SCP_IRQ_UART1_TX] = { INTC_GRP_12 }, - [SCP_IRQ_I2C0] = { INTC_GRP_0 }, - [SCP_IRQ_I2C1_0] = { INTC_GRP_0 }, - /* 12 */ - [SCP_IRQ_BUS_DBG_TRACKER] = { INTC_GRP_0 }, - [SCP_IRQ_CLK_CTRL] = { INTC_GRP_0 }, - [SCP_IRQ_VOW] = { INTC_GRP_0 }, - [SCP_IRQ_TIMER0] = { INTC_GRP_6 }, - /* 16 */ - [SCP_IRQ_TIMER1] = { INTC_GRP_6 }, - [SCP_IRQ_TIMER2] = { INTC_GRP_6 }, - [SCP_IRQ_TIMER3] = { INTC_GRP_6 }, - [SCP_IRQ_TIMER4] = { INTC_GRP_6 }, - /* 20 */ - [SCP_IRQ_TIMER5] = { INTC_GRP_6 }, - [SCP_IRQ_OS_TIMER] = { INTC_GRP_0 }, - [SCP_IRQ_UART0_RX] = { INTC_GRP_12 }, - [SCP_IRQ_UART1_RX] = { INTC_GRP_12 }, - /* 24 */ - [SCP_IRQ_GDMA] = { INTC_GRP_0 }, - [SCP_IRQ_AUDIO] = { INTC_GRP_0 }, - [SCP_IRQ_MD_DSP] = { INTC_GRP_0 }, - [SCP_IRQ_ADSP] = { INTC_GRP_0 }, - /* 28 */ - [SCP_IRQ_CPU_TICK] = { INTC_GRP_0 }, - [SCP_IRQ_SPI0] = { INTC_GRP_0 }, - [SCP_IRQ_SPI1] = { INTC_GRP_0 }, - [SCP_IRQ_SPI2] = { INTC_GRP_0 }, - /* 32 */ - [SCP_IRQ_NEW_INFRA_SYS_CIRQ] = { INTC_GRP_0 }, - [SCP_IRQ_DBG] = { INTC_GRP_0 }, - [SCP_IRQ_CCIF0] = { INTC_GRP_0 }, - [SCP_IRQ_CCIF1] = { INTC_GRP_0 }, - /* 36 */ - [SCP_IRQ_CCIF2] = { INTC_GRP_0 }, - [SCP_IRQ_WDT] = { INTC_GRP_0 }, - [SCP_IRQ_USB0] = { INTC_GRP_0 }, - [SCP_IRQ_USB1] = { INTC_GRP_0 }, - /* 40 */ - [SCP_IRQ_DPMAIF] = { INTC_GRP_0 }, - [SCP_IRQ_INFRA] = { INTC_GRP_0 }, - [SCP_IRQ_CLK_CTRL_CORE] = { INTC_GRP_0 }, - [SCP_IRQ_CLK_CTRL2_CORE] = { INTC_GRP_0 }, - /* 44 */ - [SCP_IRQ_CLK_CTRL2] = { INTC_GRP_0 }, - [SCP_IRQ_GIPC_IN4] = { INTC_GRP_0 }, - [SCP_IRQ_PERIBUS_TIMEOUT] = { INTC_GRP_0 }, - [SCP_IRQ_INFRABUS_TIMEOUT] = { INTC_GRP_0 }, - /* 48 */ - [SCP_IRQ_MET0] = { INTC_GRP_0 }, - [SCP_IRQ_MET1] = { INTC_GRP_0 }, - [SCP_IRQ_MET2] = { INTC_GRP_0 }, - [SCP_IRQ_MET3] = { INTC_GRP_0 }, - /* 52 */ - [SCP_IRQ_AP_WDT] = { INTC_GRP_0 }, - [SCP_IRQ_L2TCM_SEC_VIO] = { INTC_GRP_0 }, - [SCP_IRQ_CPU_TICK1] = { INTC_GRP_0 }, - [SCP_IRQ_MAD_DATAIN] = { INTC_GRP_0 }, - /* 56 */ - [SCP_IRQ_I3C0_IBI_WAKE] = { INTC_GRP_0 }, - [SCP_IRQ_I3C1_IBI_WAKE] = { INTC_GRP_0 }, - [SCP_IRQ_I3C2_IBI_WAKE] = { INTC_GRP_0 }, - [SCP_IRQ_APU_ENGINE] = { INTC_GRP_0 }, - /* 60 */ - [SCP_IRQ_MBOX0] = { INTC_GRP_0 }, - [SCP_IRQ_MBOX1] = { INTC_GRP_0 }, - [SCP_IRQ_MBOX2] = { INTC_GRP_0 }, - [SCP_IRQ_MBOX3] = { INTC_GRP_0 }, - /* 64 */ - [SCP_IRQ_MBOX4] = { INTC_GRP_0 }, - [SCP_IRQ_SYS_CLK_REQ] = { INTC_GRP_0 }, - [SCP_IRQ_BUS_REQ] = { INTC_GRP_0 }, - [SCP_IRQ_APSRC_REQ] = { INTC_GRP_0 }, - /* 68 */ - [SCP_IRQ_APU_MBOX] = { INTC_GRP_0 }, - [SCP_IRQ_DEVAPC_SECURE_VIO] = { INTC_GRP_0 }, - /* 72 */ - /* 76 */ - [SCP_IRQ_I2C1_2] = { INTC_GRP_0 }, - [SCP_IRQ_I2C2] = { INTC_GRP_0 }, - /* 80 */ - [SCP_IRQ_AUD2AUDIODSP] = { INTC_GRP_0 }, - [SCP_IRQ_AUD2AUDIODSP_2] = { INTC_GRP_0 }, - [SCP_IRQ_CONN2ADSP_A2DPOL] = { INTC_GRP_0 }, - [SCP_IRQ_CONN2ADSP_BTCVSD] = { INTC_GRP_0 }, - /* 84 */ - [SCP_IRQ_CONN2ADSP_BLEISO] = { INTC_GRP_0 }, - [SCP_IRQ_PCIE2ADSP] = { INTC_GRP_0 }, - [SCP_IRQ_APU2ADSP_ENGINE] = { INTC_GRP_0 }, - [SCP_IRQ_APU2ADSP_MBOX] = { INTC_GRP_0 }, - /* 88 */ - [SCP_IRQ_CCIF3] = { INTC_GRP_0 }, - [SCP_IRQ_I2C_DMA0] = { INTC_GRP_0 }, - [SCP_IRQ_I2C_DMA1] = { INTC_GRP_0 }, - [SCP_IRQ_I2C_DMA2] = { INTC_GRP_0 }, - /* 92 */ - [SCP_IRQ_I2C_DMA3] = { INTC_GRP_0 }, -}; -BUILD_ASSERT(ARRAY_SIZE(irqs) == SCP_INTC_IRQ_COUNT); - -/* - * Find current interrupt source. - * - * Lower group has higher priority. - * Higher INT number has higher priority. - */ -int chip_get_ec_int(void) -{ - extern volatile int ec_int; - unsigned int group, sta; - int word; - - if (!SCP_CORE0_INTC_IRQ_OUT) - goto error; - - group = read_csr(CSR_VIC_MICAUSE); - - for (word = SCP_INTC_GRP_LEN - 1; word >= 0; --word) { - sta = SCP_CORE0_INTC_IRQ_GRP_STA(group, word); - if (sta) { - ec_int = __fls(sta) + word * 32; - return ec_int; - } - } - -error: - /* unreachable, SCP crashes and dumps registers after returning */ - return -1; -} - -int chip_get_intc_group(int irq) -{ - return irqs[irq].group; -} - -void chip_enable_irq(int irq) -{ - unsigned int word, group, mask; - - word = SCP_INTC_WORD(irq); - group = irqs[irq].group; - mask = BIT(SCP_INTC_BIT(irq)); - - /* disable interrupt */ - SCP_CORE0_INTC_IRQ_EN(word) &= ~mask; - /* set group */ - SCP_CORE0_INTC_IRQ_GRP(group, word) |= mask; - /* set as a wakeup source */ - SCP_CORE0_INTC_SLP_WAKE_EN(word) |= mask; - /* enable interrupt */ - SCP_CORE0_INTC_IRQ_EN(word) |= mask; -} - -void chip_disable_irq(int irq) -{ - /* - * Disabling INTC IRQ in runtime is unstable in MT8192 SCP. - * See b/163682416#comment17. - * - * Ideally, this function will be removed by LTO. - */ - ccprints("WARNING: %s is unsupported", __func__); -} - -void chip_clear_pending_irq(int irq) -{ - unsigned int group = irqs[irq].group; - - /* must clear interrupt source before writing this */ - write_csr(CSR_VIC_MIEMS, group); -} - -int chip_trigger_irq(int irq) -{ - extern volatile int ec_int; - - ec_int = irq; - return irqs[irq].group; -} - -void chip_init_irqs(void) -{ - unsigned int word, group; - - /* INTC init */ - /* clear enable and wakeup settings */ - for (word = 0; word < SCP_INTC_GRP_LEN; ++word) { - SCP_CORE0_INTC_IRQ_EN(word) = 0x0; - SCP_CORE0_INTC_SLP_WAKE_EN(word) = 0x0; - - /* clear group settings */ - for (group = 0; group < SCP_INTC_GRP_COUNT; ++group) - SCP_CORE0_INTC_IRQ_GRP(group, word) = 0x0; - } - /* reset to default polarity */ - SCP_CORE0_INTC_IRQ_POL(0) = SCP_INTC_IRQ_POL0; - SCP_CORE0_INTC_IRQ_POL(1) = SCP_INTC_IRQ_POL1; - SCP_CORE0_INTC_IRQ_POL(2) = SCP_INTC_IRQ_POL2; - - /* GVIC init */ - /* enable all groups as interrupt sources */ - write_csr(CSR_VIC_MIMASK_G0, 0xffffffff); - /* use level trigger */ - write_csr(CSR_VIC_MILSEL_G0, 0xffffffff); - /* enable all groups as wakeup sources */ - write_csr(CSR_VIC_MIWAKEUP_G0, 0xffffffff); - - /* enable GVIC */ - set_csr(CSR_MCTREN, CSR_MCTREN_VIC); -} diff --git a/chip/mt8192_scp/ipi.c b/chip/mt8192_scp/ipi.c deleted file mode 100644 index a6b2028329..0000000000 --- a/chip/mt8192_scp/ipi.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "atomic.h" -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "hostcmd.h" -#include "ipi_chip.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) -#define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) - -static uint8_t init_done; - -static struct mutex ipi_lock; -static struct ipc_shared_obj *const ipi_send_buf = - (struct ipc_shared_obj *)CONFIG_IPC_SHARED_OBJ_ADDR; -static struct ipc_shared_obj *const ipi_recv_buf = - (struct ipc_shared_obj *)(CONFIG_IPC_SHARED_OBJ_ADDR + - sizeof(struct ipc_shared_obj)); - -static uint32_t disable_irq_count, saved_int_mask; - -void ipi_disable_irq(void) -{ - if (deprecated_atomic_read_add(&disable_irq_count, 1) == 0) - saved_int_mask = read_clear_int_mask(); -} - -void ipi_enable_irq(void) -{ - if (deprecated_atomic_read_sub(&disable_irq_count, 1) == 1) - set_int_mask(saved_int_mask); -} - -static int ipi_is_busy(void) -{ - return SCP_SCP2APMCU_IPC_SET & IPC_SCP2HOST; -} - -static void ipi_wake_ap(int32_t id) -{ - if (id >= IPI_COUNT) - return; - - if (*ipi_wakeup_table[id]) - SCP_SCP2SPM_IPC_SET = IPC_SCP2HOST; -} - -int ipi_send(int32_t id, const void *buf, uint32_t len, int wait) -{ - int ret; - - if (!init_done) { - CPRINTS("IPI has not initialized"); - return EC_ERROR_BUSY; - } - - if (in_interrupt_context()) { - CPRINTS("invoke %s() in ISR context", __func__); - return EC_ERROR_BUSY; - } - - if (len > sizeof(ipi_send_buf->buffer)) { - CPRINTS("data length exceeds limitation"); - return EC_ERROR_INVAL; - } - - ipi_disable_irq(); - mutex_lock(&ipi_lock); - - if (ipi_is_busy()) { - /* - * If the following conditions meet, - * 1) There is an IPI pending in AP. - * 2) The incoming IPI is a wakeup IPI. - * then it assumes that AP is in suspend state. - * Send a AP wakeup request to SPM. - * - * The incoming IPI will be checked if it's a wakeup source. - */ - ipi_wake_ap(id); - - CPRINTS("IPI busy, id=%d", id); - ret = EC_ERROR_BUSY; - goto error; - } - - ipi_send_buf->id = id; - ipi_send_buf->len = len; - memcpy(ipi_send_buf->buffer, buf, len); - - /* interrupt AP to handle the message */ - ipi_wake_ap(id); - SCP_SCP2APMCU_IPC_SET = IPC_SCP2HOST; - - if (wait) - while (ipi_is_busy()) - ; - - ret = EC_SUCCESS; -error: - mutex_unlock(&ipi_lock); - ipi_enable_irq(); - return ret; -} - -static void ipi_enable_deferred(void) -{ - struct scp_run_t scp_run; - int ret; - - init_done = 1; - - /* inform AP that SCP is up */ - scp_run.signaled = 1; - strncpy(scp_run.fw_ver, system_get_version(EC_IMAGE_RW), - SCP_FW_VERSION_LEN); - scp_run.dec_capability = VCODEC_CAPABILITY_4K_DISABLED; - scp_run.enc_capability = 0; - - ret = ipi_send(SCP_IPI_INIT, (void *)&scp_run, sizeof(scp_run), 1); - if (ret) { - CPRINTS("failed to send initialization IPC messages"); - init_done = 0; - return; - } - -#ifdef HAS_TASK_HOSTCMD - hostcmd_init(); -#endif - - task_enable_irq(SCP_IRQ_GIPC_IN0); -} -DECLARE_DEFERRED(ipi_enable_deferred); - -static void ipi_init(void) -{ - memset(ipi_send_buf, 0, sizeof(struct ipc_shared_obj)); - memset(ipi_recv_buf, 0, sizeof(struct ipc_shared_obj)); - - /* enable IRQ after all tasks are up */ - hook_call_deferred(&ipi_enable_deferred_data, 0); -} -DECLARE_HOOK(HOOK_INIT, ipi_init, HOOK_PRIO_DEFAULT); - -static void ipi_handler(void) -{ - if (ipi_recv_buf->id >= IPI_COUNT) { - CPRINTS("invalid IPI, id=%d", ipi_recv_buf->id); - return; - } - - CPRINTS("IPI %d", ipi_recv_buf->id); - - ipi_handler_table[ipi_recv_buf->id]( - ipi_recv_buf->id, ipi_recv_buf->buffer, ipi_recv_buf->len); -} - -static void irq_group7_handler(void) -{ - extern volatile int ec_int; - - if (SCP_GIPC_IN_SET & GIPC_IN(0)) { - ipi_handler(); - SCP_GIPC_IN_CLR = GIPC_IN(0); - task_clear_pending_irq(ec_int); - } -} -DECLARE_IRQ(7, irq_group7_handler, 0); diff --git a/chip/mt8192_scp/ipi_chip.h b/chip/mt8192_scp/ipi_chip.h deleted file mode 100644 index 8cc3376880..0000000000 --- a/chip/mt8192_scp/ipi_chip.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_IPI_CHIP_H -#define __CROS_EC_IPI_CHIP_H - -/* - * Length of EC version string is at most 32 byte (NULL included), which - * also aligns SCP fw_version length. - */ -#define SCP_FW_VERSION_LEN 32 - -/* - * Video decoder supported capability: - * BIT(4): 0 enable 4K - * 1 disable 4K - */ -#define VCODEC_CAPABILITY_4K_DISABLED BIT(4) - -#ifndef SCP_IPI_INIT -#error If CONFIG_IPI is enabled, SCP_IPI_INIT must be defined. -#endif - -/* - * Share buffer layout for SCP_IPI_INIT response. This structure should sync - * across kernel and EC. - */ -struct scp_run_t { - uint32_t signaled; - int8_t fw_ver[SCP_FW_VERSION_LEN]; - uint32_t dec_capability; - uint32_t enc_capability; -}; - -/* - * The layout of the IPC0 AP/SCP shared buffer. - * This should sync across kernel and EC. - */ -struct ipc_shared_obj { - /* IPI ID */ - int32_t id; - /* Length of the contents in buffer. */ - uint32_t len; - /* Shared buffer contents. */ - uint8_t buffer[CONFIG_IPC_SHARED_OBJ_BUF_SIZE]; -}; - -/* Send a IPI contents to AP. This shouldn't be used in ISR context. */ -int ipi_send(int32_t id, const void *buf, uint32_t len, int wait); - -/* - * An IPC IRQ could be shared across many IPI handlers. - * Those handlers would usually operate on disabling or enabling the IPC IRQ. - * This may disorder the actual timing to on/off the IRQ when there are many - * tasks try to operate on it. As a result, any access to the SCP_IRQ_* - * should go through ipi_{en,dis}able_irq(), which support a counter to - * enable/disable the IRQ at correct timing. - */ -/* Disable IPI IRQ. */ -void ipi_disable_irq(void); -/* Enable IPI IRQ. */ -void ipi_enable_irq(void); - -/* IPI tables */ -extern void (*const ipi_handler_table[])(int32_t, void *, uint32_t); -extern int *const ipi_wakeup_table[]; - -/* Helper macros to build the IPI handler and wakeup functions. */ -#define IPI_HANDLER(id) CONCAT3(ipi_, id, _handler) -#define IPI_WAKEUP(id) CONCAT3(ipi_, id, _wakeup) - -/* - * Macro to declare an IPI handler. - * _id: The ID of the IPI - * handler: The IPI handler function - * is_wakeup_src: Declare IPI ID as a wake-up source or not - */ -#define DECLARE_IPI(_id, handler, is_wakeup_src) \ - struct ipi_num_check##_id { \ - int tmp1[_id < IPI_COUNT ? 1 : -1]; \ - int tmp2[is_wakeup_src == 0 || is_wakeup_src == 1 ? 1 : -1]; \ - }; \ - void __keep IPI_HANDLER(_id)(int32_t id, void *buf, uint32_t len) \ - { \ - handler(id, buf, len); \ - } \ - const int __keep IPI_WAKEUP(_id) = is_wakeup_src - -#endif /* __CROS_EC_IPI_CHIP_H */ diff --git a/chip/mt8192_scp/ipi_table.c b/chip/mt8192_scp/ipi_table.c deleted file mode 100644 index 8fe3f1e598..0000000000 --- a/chip/mt8192_scp/ipi_table.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * IPI handlers declaration - */ - -#include "common.h" -#include "ipi_chip.h" - -typedef void (*ipi_handler_t)(int32_t id, void *data, uint32_t len); - -#ifndef PASS -#define PASS 1 -#endif - -#define ipi_arguments int32_t id, void *data, uint32_t len - -#if PASS == 1 -void ipi_handler_undefined(ipi_arguments) { } - -const int ipi_wakeup_undefined; - -#define table(type, name, x) x - -#define ipi_x_func(suffix, args, number) \ - extern void __attribute__( \ - (used, weak, alias(STRINGIFY(ipi_##suffix##_undefined)))) \ - ipi_##number##_##suffix(args); - -#define ipi_x_var(suffix, number) \ - extern int __attribute__( \ - (weak, alias(STRINGIFY(ipi_##suffix##_undefined)))) \ - ipi_##number##_##suffix; - -#endif /* PASS == 1 */ - -#if PASS == 2 - -#undef table -#undef ipi_x_func -#undef ipi_x_var - -#define table(type, name, x) \ - type const name[] \ - __attribute__((aligned(4), used, section(".rodata.ipi"))) = {x} - -#define ipi_x_var(suffix, number) \ - [number < IPI_COUNT ? number : -1] = &ipi_##number##_##suffix, - -#define ipi_x_func(suffix, args, number) ipi_x_var(suffix, number) - -#endif /* PASS == 2 */ - -/* - * Include generated IPI table (by util/gen_ipi_table). The contents originate - * from IPI_COUNT definition in board.h - */ -#include "ipi_table_gen.inc" - -#if PASS == 1 -#undef PASS -#define PASS 2 -#include "ipi_table.c" -BUILD_ASSERT(ARRAY_SIZE(ipi_handler_table) == IPI_COUNT); -BUILD_ASSERT(ARRAY_SIZE(ipi_wakeup_table) == IPI_COUNT); -#endif diff --git a/chip/mt8192_scp/memmap.c b/chip/mt8192_scp/memmap.c deleted file mode 100644 index 63fa4f8fc5..0000000000 --- a/chip/mt8192_scp/memmap.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "registers.h" -#include "stdint.h" - -/* - * Map SCP address (bits 31~28) to AP address - * - * SCP address AP address Note - * - * 0x0000_0000 SRAM - * 0x1000_0000 0x6000_0000 un-cached DRAM - * 0x2000_0000 0x7000_0000 un-cached DRAM - * 0x3000_0000 - * - * 0x4000_0000 - * 0x5000_0000 0x0000_0000 - * 0x6000_0000 0x1000_0000 - * 0x7000_0000 0xa000_0000 - * - * 0x8000_0000 - * 0x9000_0000 0x8000_0000 - * 0xa000_0000 0x9000_0000 - * 0xb000_0000 - * - * 0xc000_0000 0x8000_0000 - * 0xd000_0000 0x2000_0000 - * 0xe000_0000 0x3000_0000 - * 0xf000_0000 0x5000_0000 - */ - -#define REMAP_ADDR_SHIFT 28 -#define REMAP_ADDR_LSB_MASK (BIT(REMAP_ADDR_SHIFT) - 1) -#define REMAP_ADDR_MSB_MASK ((~0) << REMAP_ADDR_SHIFT) -#define MAP_INVALID 0xff - -static const uint8_t addr_map[16] = { - MAP_INVALID, /* SRAM */ - 0x6, /* ext_addr_0x1 */ - 0x7, /* ext_addr_0x2 */ - MAP_INVALID, /* no ext_addr_0x3 */ - - MAP_INVALID, /* no ext_addr_0x4 */ - 0x0, /* ext_addr_0x5 */ - 0x1, /* ext_addr_0x6 */ - 0xa, /* ext_addr_0x7 */ - - MAP_INVALID, /* no ext_addr_0x8 */ - 0x8, /* ext_addr_0x9 */ - 0x9, /* ext_addr_0xa */ - MAP_INVALID, /* no ext_addr_0xb */ - - 0x8, /* ext_addr_0xc */ - 0x2, /* ext_addr_0xd */ - 0x3, /* ext_addr_0xe */ - 0x5, /* ext_addr_0xf */ -}; - -void memmap_init(void) -{ - SCP_R_REMAP_0X0123 = - (uint32_t)addr_map[0x1] << 8 | - (uint32_t)addr_map[0x2] << 16; - - SCP_R_REMAP_0X4567 = - (uint32_t)addr_map[0x5] << 8 | - (uint32_t)addr_map[0x6] << 16 | - (uint32_t)addr_map[0x7] << 24; - - SCP_R_REMAP_0X89AB = - (uint32_t)addr_map[0x9] << 8 | - (uint32_t)addr_map[0xa] << 16; - - SCP_R_REMAP_0XCDEF = - (uint32_t)addr_map[0xc] | - (uint32_t)addr_map[0xd] << 8 | - (uint32_t)addr_map[0xe] << 16 | - (uint32_t)addr_map[0xf] << 24; -} - -int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr) -{ - int i; - uint8_t msb = ap_addr >> REMAP_ADDR_SHIFT; - - for (i = 0; i < ARRAY_SIZE(addr_map); ++i) { - if (addr_map[i] != msb) - continue; - - *scp_addr = (ap_addr & REMAP_ADDR_LSB_MASK) | - (i << REMAP_ADDR_SHIFT); - return EC_SUCCESS; - } - - return EC_ERROR_INVAL; -} - -int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr) -{ - int i = scp_addr >> REMAP_ADDR_SHIFT; - - if (addr_map[i] == MAP_INVALID) - return EC_ERROR_INVAL; - - *ap_addr = (scp_addr & REMAP_ADDR_LSB_MASK) | - (addr_map[i] << REMAP_ADDR_SHIFT); - return EC_SUCCESS; -} diff --git a/chip/mt8192_scp/memmap.h b/chip/mt8192_scp/memmap.h deleted file mode 100644 index 0857c9a89e..0000000000 --- a/chip/mt8192_scp/memmap.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_MEMMAP_H -#define __CROS_EC_MEMMAP_H - -#include "stdint.h" - -void memmap_init(void); - -/** - * Translate AP addr to SCP addr. - * - * @param ap_addr AP address to translate - * @param scp_addr Translated AP address - * @return EC_SUCCESS or EC_ERROR_INVAL - */ -int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr); - -/** - * Translate SCP addr to AP addr. - * - * @param scp_addr SCP address to translate - * @param ap_addr Translated SCP address - * @return EC_SUCCESS or EC_ERROR_INVAL - */ -int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr); - -#endif /* #ifndef __CROS_EC_MEMMAP_H */ diff --git a/chip/mt8192_scp/registers.h b/chip/mt8192_scp/registers.h deleted file mode 100644 index cde931a2ba..0000000000 --- a/chip/mt8192_scp/registers.h +++ /dev/null @@ -1,386 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Register map */ - -#ifndef __CROS_EC_REGISTERS_H -#define __CROS_EC_REGISTERS_H - -#include "common.h" -#include "compile_time_macros.h" - -#define UNIMPLEMENTED_GPIO_BANK 0 - -#define SCP_REG_BASE 0x70000000 - -/* clock control */ -#define SCP_CLK_CTRL_BASE (SCP_REG_BASE + 0x21000) -/* clock source select */ -#define SCP_CLK_SW_SEL REG32(SCP_CLK_CTRL_BASE + 0x0000) -#define CLK_SW_SEL_26M 0 -#define CLK_SW_SEL_32K 1 -#define CLK_SW_SEL_ULPOSC2 2 -#define CLK_SW_SEL_ULPOSC1 3 -#define SCP_CLK_ENABLE REG32(SCP_CLK_CTRL_BASE + 0x0004) -#define CLK_HIGH_EN BIT(1) /* ULPOSC */ -#define CLK_HIGH_CG BIT(2) -/* system clock counter value */ -#define SCP_CLK_SYS_VAL REG32(SCP_CLK_CTRL_BASE + 0x0014) -#define CLK_SYS_VAL_MASK (0x3ff << 0) -#define CLK_SYS_VAL_VAL(v) ((v) & CLK_SYS_VAL_MASK) -/* ULPOSC clock counter value */ -#define SCP_CLK_HIGH_VAL REG32(SCP_CLK_CTRL_BASE + 0x0018) -#define CLK_HIGH_VAL_MASK (0x1f << 0) -#define CLK_HIGH_VAL_VAL(v) ((v) & CLK_HIGH_VAL_MASK) -/* sleep mode control */ -#define SCP_SLEEP_CTRL REG32(SCP_CLK_CTRL_BASE + 0x0020) -#define SLP_CTRL_EN BIT(0) -#define VREQ_COUNT_MASK (0x7F << 1) -#define VREQ_COUNT_VAL(v) (((v) << 1) & VREQ_COUNT_MASK) -#define SPM_SLP_MODE BIT(8) -/* clock divider select */ -#define SCP_CLK_DIV_SEL REG32(SCP_CLK_CTRL_BASE + 0x0024) -#define CLK_DIV_SEL1 0 -#define CLK_DIV_SEL2 1 -#define CLK_DIV_SEL4 2 -#define CLK_DIV_SEL3 3 -/* clock gate */ -#define SCP_SET_CLK_CG REG32(SCP_CLK_CTRL_BASE + 0x0030) -#define CG_TIMER_MCLK BIT(0) -#define CG_TIMER_BCLK BIT(1) -#define CG_MAD_MCLK BIT(2) -#define CG_I2C_MCLK BIT(3) -#define CG_I2C_BCLK BIT(4) -#define CG_GPIO_MCLK BIT(5) -#define CG_AP2P_MCLK BIT(6) -#define CG_UART0_MCLK BIT(7) -#define CG_UART0_BCLK BIT(8) -#define CG_UART0_RST BIT(9) -#define CG_UART1_MCLK BIT(10) -#define CG_UART1_BCLK BIT(11) -#define CG_UART1_RST BIT(12) -#define CG_SPI0 BIT(13) -#define CG_SPI1 BIT(14) -#define CG_SPI2 BIT(15) -#define CG_DMA_CH0 BIT(16) -#define CG_DMA_CH1 BIT(17) -#define CG_DMA_CH2 BIT(18) -#define CG_DMA_CH3 BIT(19) -#define CG_I3C0 BIT(21) -#define CG_I3C1 BIT(22) -#define CG_DMA2_CH0 BIT(23) -#define CG_DMA2_CH1 BIT(24) -#define CG_DMA2_CH2 BIT(25) -#define CG_DMA2_CH3 BIT(26) -/* UART clock select */ -#define SCP_UART_CK_SEL REG32(SCP_CLK_CTRL_BASE + 0x0044) -#define UART0_CK_SEL_SHIFT 0 -#define UART0_CK_SEL_MASK (0x3 << UART0_CK_SEL_SHIFT) -#define UART0_CK_SEL_VAL(v) ((v) & UART0_CK_SEL_MASK) -#define UART0_CK_SW_STATUS_MASK (0xf << 8) -#define UART0_CK_SW_STATUS_VAL(v) ((v) & UART0_CK_SW_STATUS_MASK) -#define UART1_CK_SEL_SHIFT 16 -#define UART1_CK_SEL_MASK (0x3 << UART1_CK_SEL_SHIFT) -#define UART1_CK_SEL_VAL(v) ((v) & UART1_CK_SEL_MASK) -#define UART1_CK_SW_STATUS_MASK (0xf << 24) -#define UART1_CK_SW_STATUS_VAL(v) ((v) & UART1_CK_SW_STATUS_MASK) -#define UART_CK_SEL_26M 0 -#define UART_CK_SEL_32K 1 -#define UART_CK_SEL_ULPOSC 2 -#define UART_CK_SW_STATUS_26M BIT(0) -#define UART_CK_SW_STATUS_32K BIT(1) -#define UART_CK_SW_STATUS_ULPOS BIT(2) -/* VREQ control */ -#define SCP_CPU_VREQ_CTRL REG32(SCP_CLK_CTRL_BASE + 0x0054) -#define VREQ_SEL BIT(0) -#define VREQ_VALUE BIT(4) -#define VREQ_EXT_SEL BIT(8) -#define VREQ_DVFS_SEL BIT(16) -#define VREQ_DVFS_VALUE BIT(20) -#define VREQ_DVFS_EXT_SEL BIT(24) -#define VREQ_SRCLKEN_SEL BIT(27) -#define VREQ_SRCLKEN_VALUE BIT(28) -/* clock on control */ -#define SCP_CLK_HIGH_CORE_CG REG32(SCP_CLK_CTRL_BASE + 0x005C) -#define HIGH_CORE_CG BIT(1) -#define SCP_CLK_ON_CTRL REG32(SCP_CLK_CTRL_BASE + 0x006C) -#define HIGH_AO BIT(0) -#define HIGH_DIS_SUB BIT(1) -#define HIGH_CG_AO BIT(2) -#define HIGH_CORE_AO BIT(4) -#define HIGH_CORE_DIS_SUB BIT(5) -#define HIGH_CORE_CG_AO BIT(6) -/* clock general control */ -#define SCP_CLK_CTRL_GENERAL_CTRL REG32(SCP_CLK_CTRL_BASE + 0x009C) -#define VREQ_PMIC_WRAP_SEL (0x2) - -/* system control */ -#define SCP_SYS_CTRL REG32(SCP_REG_BASE + 0x24000) -#define AUTO_DDREN BIT(9) - -/* IPC */ -#define SCP_SCP2APMCU_IPC_SET REG32(SCP_REG_BASE + 0x24080) -#define SCP_SCP2SPM_IPC_SET REG32(SCP_REG_BASE + 0x24090) -#define IPC_SCP2HOST BIT(0) -#define SCP_GIPC_IN_SET REG32(SCP_REG_BASE + 0x24098) -#define SCP_GIPC_IN_CLR REG32(SCP_REG_BASE + 0x2409C) -#define GIPC_IN(n) BIT(n) - -/* UART */ -#define SCP_UART_COUNT 2 -#define UART_TX_IRQ(n) CONCAT3(SCP_IRQ_UART, n, _TX) -#define UART_RX_IRQ(n) CONCAT3(SCP_IRQ_UART, n, _RX) -#define SCP_UART0_BASE (SCP_REG_BASE + 0x26000) -#define SCP_UART1_BASE (SCP_REG_BASE + 0x27000) -#define SCP_UART_BASE(n) CONCAT3(SCP_UART, n, _BASE) -#define UART_REG(n, offset) REG32_ADDR(SCP_UART_BASE(n))[offset] - -/* WDT */ -#define SCP_CORE0_WDT_IRQ REG32(SCP_REG_BASE + 0x30030) -#define SCP_CORE0_WDT_CFG REG32(SCP_REG_BASE + 0x30034) -#define WDT_FREQ 33825 /* 0xFFFFF / 31 */ -#define WDT_MAX_PERIOD 0xFFFFF /* 31 seconds */ -#define WDT_PERIOD(ms) (WDT_FREQ * (ms) / 1000) -#define WDT_EN BIT(31) -#define SCP_CORE0_WDT_KICK REG32(SCP_REG_BASE + 0x30038) -#define SCP_CORE0_WDT_CUR_VAL REG32(SCP_REG_BASE + 0x3003C) - -/* INTC */ -#define SCP_INTC_IRQ_POL0 0xef001f20 -#define SCP_INTC_IRQ_POL1 0x0800001d -#define SCP_INTC_IRQ_POL2 0x00000020 -#define SCP_INTC_WORD(irq) ((irq) >> 5) /* word length = 2^5 */ -#define SCP_INTC_BIT(irq) ((irq) & 0x1F) /* bit shift =LSB[0:4] */ -#define SCP_INTC_GRP_COUNT 15 -#define SCP_INTC_GRP_LEN 3 -#define SCP_INTC_GRP_GAP 4 -#define SCP_INTC_IRQ_COUNT 96 -#define SCP_CORE0_INTC_IRQ_BASE (SCP_REG_BASE + 0x32000) -#define SCP_CORE0_INTC_IRQ_STA(w) \ - REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0010)[(w)] -#define SCP_CORE0_INTC_IRQ_EN(w) \ - REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0020)[(w)] -#define SCP_CORE0_INTC_IRQ_POL(w) \ - REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0040)[(w)] -#define SCP_CORE0_INTC_IRQ_GRP(g, w) \ - REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0050 + \ - ((g) << SCP_INTC_GRP_GAP))[(w)] -#define SCP_CORE0_INTC_IRQ_GRP_STA(g, w) \ - REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0150 + \ - ((g) << SCP_INTC_GRP_GAP))[(w)] -#define SCP_CORE0_INTC_SLP_WAKE_EN(w) \ - REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0240)[(w)] -#define SCP_CORE0_INTC_IRQ_OUT REG32(SCP_CORE0_INTC_IRQ_BASE + 0x0250) -/* UART */ -#define SCP_CORE0_INTC_UART0_RX_IRQ REG32(SCP_CORE0_INTC_IRQ_BASE + 0x0258) -#define SCP_CORE0_INTC_UART1_RX_IRQ REG32(SCP_CORE0_INTC_IRQ_BASE + 0x025C) -#define SCP_CORE0_INTC_UART_RX_IRQ(n) CONCAT3(SCP_CORE0_INTC_UART, n, _RX_IRQ) - -/* XGPT (general purpose timer) */ -#define NUM_TIMERS 6 -#define SCP_CORE0_TIMER_BASE(n) (SCP_REG_BASE + 0x33000 + (0x10 * (n))) -#define SCP_CORE0_TIMER_EN(n) REG32(SCP_CORE0_TIMER_BASE(n) + 0x0000) -#define TIMER_EN BIT(0) -#define TIMER_CLK_SRC_32K (0 << 4) -#define TIMER_CLK_SRC_26M (1 << 4) -#define TIMER_CLK_SRC_BCLK (2 << 4) -#define TIMER_CLK_SRC_MCLK (3 << 4) -#define TIMER_CLK_SRC_MASK (3 << 4) -#define SCP_CORE0_TIMER_RST_VAL(n) REG32(SCP_CORE0_TIMER_BASE(n) + 0x0004) -#define SCP_CORE0_TIMER_CUR_VAL(n) REG32(SCP_CORE0_TIMER_BASE(n) + 0x0008) -#define SCP_CORE0_TIMER_IRQ_CTRL(n) REG32(SCP_CORE0_TIMER_BASE(n) + 0x000C) -#define TIMER_IRQ_EN BIT(0) -#define TIMER_IRQ_STATUS BIT(4) -#define TIMER_IRQ_CLR BIT(5) -#define SCP_IRQ_TIMER(n) CONCAT2(SCP_IRQ_TIMER, n) - -/* secure control */ -#define SCP_SEC_CTRL REG32(SCP_REG_BASE + 0xA5000) -#define VREQ_SECURE_DIS BIT(4) -/* memory remap */ -#define SCP_R_REMAP_0X0123 REG32(SCP_REG_BASE + 0xA5060) -#define SCP_R_REMAP_0X4567 REG32(SCP_REG_BASE + 0xA5064) -#define SCP_R_REMAP_0X89AB REG32(SCP_REG_BASE + 0xA5068) -#define SCP_R_REMAP_0XCDEF REG32(SCP_REG_BASE + 0xA506C) - -/* external address: AP */ -#define AP_REG_BASE 0x60000000 /* 0x10000000 remap to 0x6 */ -/* OSC meter */ -#define TOPCK_BASE AP_REG_BASE -#define AP_CLK_MISC_CFG_0 REG32(TOPCK_BASE + 0x0140) -#define MISC_METER_DIVISOR_MASK 0xff000000 -#define MISC_METER_DIV_1 0 -#define AP_CLK_DBG_CFG REG32(TOPCK_BASE + 0x017C) -#define DBG_MODE_MASK 3 -#define DBG_MODE_SET_CLOCK 0 -#define DBG_BIST_SOURCE_MASK (0x3f << 16) -#define DBG_BIST_SOURCE_ULPOSC1 (0x25 << 16) -#define DBG_BIST_SOURCE_ULPOSC2 (0x24 << 16) -#define AP_SCP_CFG_0 REG32(TOPCK_BASE + 0x0220) -#define CFG_FREQ_METER_RUN BIT(4) -#define CFG_FREQ_METER_ENABLE BIT(12) -#define AP_SCP_CFG_1 REG32(TOPCK_BASE + 0x0224) -#define CFG_FREQ_COUNTER(CFG1) ((CFG1) & 0xFFFF) -/* AP GPIO */ -#define AP_GPIO_BASE (AP_REG_BASE + 0x5000) -#define AP_GPIO_MODE11_SET REG32(AP_GPIO_BASE + 0x03B4) -#define AP_GPIO_MODE11_CLR REG32(AP_GPIO_BASE + 0x03B8) -#define AP_GPIO_MODE20_SET REG32(AP_GPIO_BASE + 0x0444) -#define AP_GPIO_MODE20_CLR REG32(AP_GPIO_BASE + 0x0448) -/* - * ULPOSC - * osc: 0 for ULPOSC1, 1 for ULPOSC2. - */ -#define AP_ULPOSC_CON0_BASE (AP_REG_BASE + 0xC2B0) -#define AP_ULPOSC_CON1_BASE (AP_REG_BASE + 0xC2B4) -#define AP_ULPOSC_CON2_BASE (AP_REG_BASE + 0xC2B8) -#define AP_ULPOSC_CON0(osc) \ - REG32(AP_ULPOSC_CON0_BASE + (osc) * 0x10) -#define AP_ULPOSC_CON1(osc) \ - REG32(AP_ULPOSC_CON1_BASE + (osc) * 0x10) -#define AP_ULPOSC_CON2(osc) \ - REG32(AP_ULPOSC_CON2_BASE + (osc) * 0x10) -/* - * AP_ULPOSC_CON0 - * bit0-6: calibration - * bit7-13: iband - * bit14-17: fband - * bit18-23: div - * bit24: cp_en - * bit25-31: reserved - */ -#define OSC_CALI_MASK 0x7f -#define OSC_IBAND_SHIFT 7 -#define OSC_FBAND_SHIFT 14 -#define OSC_DIV_SHIFT 18 -#define OSC_CP_EN BIT(24) -/* AP_ULPOSC_CON1 - * bit0-7: 32K calibration - * bit 8-15: rsv1 - * bit 16-23: rsv2 - * bit 24-25: mod - * bit26: div2_en - * bit27-31: reserved - */ -#define OSC_RSV1_SHIFT 8 -#define OSC_RSV2_SHIFT 16 -#define OSC_MOD_SHIFT 24 -#define OSC_DIV2_EN BIT(26) -/* AP_ULPOSC_CON2 - * bit0-7: bias - * bit8-31: reserved - */ - -/* IRQ numbers */ -#define SCP_IRQ_GIPC_IN0 0 -#define SCP_IRQ_GIPC_IN1 1 -#define SCP_IRQ_GIPC_IN2 2 -#define SCP_IRQ_GIPC_IN3 3 -/* 4 */ -#define SCP_IRQ_SPM 4 -#define SCP_IRQ_AP_CIRQ 5 -#define SCP_IRQ_EINT 6 -#define SCP_IRQ_PMIC 7 -/* 8 */ -#define SCP_IRQ_UART0_TX 8 -#define SCP_IRQ_UART1_TX 9 -#define SCP_IRQ_I2C0 10 -#define SCP_IRQ_I2C1_0 11 -/* 12 */ -#define SCP_IRQ_BUS_DBG_TRACKER 12 -#define SCP_IRQ_CLK_CTRL 13 -#define SCP_IRQ_VOW 14 -#define SCP_IRQ_TIMER0 15 -/* 16 */ -#define SCP_IRQ_TIMER1 16 -#define SCP_IRQ_TIMER2 17 -#define SCP_IRQ_TIMER3 18 -#define SCP_IRQ_TIMER4 19 -/* 20 */ -#define SCP_IRQ_TIMER5 20 -#define SCP_IRQ_OS_TIMER 21 -#define SCP_IRQ_UART0_RX 22 -#define SCP_IRQ_UART1_RX 23 -/* 24 */ -#define SCP_IRQ_GDMA 24 -#define SCP_IRQ_AUDIO 25 -#define SCP_IRQ_MD_DSP 26 -#define SCP_IRQ_ADSP 27 -/* 28 */ -#define SCP_IRQ_CPU_TICK 28 -#define SCP_IRQ_SPI0 29 -#define SCP_IRQ_SPI1 30 -#define SCP_IRQ_SPI2 31 -/* 32 */ -#define SCP_IRQ_NEW_INFRA_SYS_CIRQ 32 -#define SCP_IRQ_DBG 33 -#define SCP_IRQ_CCIF0 34 -#define SCP_IRQ_CCIF1 35 -/* 36 */ -#define SCP_IRQ_CCIF2 36 -#define SCP_IRQ_WDT 37 -#define SCP_IRQ_USB0 38 -#define SCP_IRQ_USB1 39 -/* 40 */ -#define SCP_IRQ_DPMAIF 40 -#define SCP_IRQ_INFRA 41 -#define SCP_IRQ_CLK_CTRL_CORE 42 -#define SCP_IRQ_CLK_CTRL2_CORE 43 -/* 44 */ -#define SCP_IRQ_CLK_CTRL2 44 -#define SCP_IRQ_GIPC_IN4 45 /* HALT */ -#define SCP_IRQ_PERIBUS_TIMEOUT 46 -#define SCP_IRQ_INFRABUS_TIMEOUT 47 -/* 48 */ -#define SCP_IRQ_MET0 48 -#define SCP_IRQ_MET1 49 -#define SCP_IRQ_MET2 50 -#define SCP_IRQ_MET3 51 -/* 52 */ -#define SCP_IRQ_AP_WDT 52 -#define SCP_IRQ_L2TCM_SEC_VIO 53 -#define SCP_IRQ_CPU_TICK1 54 -#define SCP_IRQ_MAD_DATAIN 55 -/* 56 */ -#define SCP_IRQ_I3C0_IBI_WAKE 56 -#define SCP_IRQ_I3C1_IBI_WAKE 57 -#define SCP_IRQ_I3C2_IBI_WAKE 58 -#define SCP_IRQ_APU_ENGINE 59 -/* 60 */ -#define SCP_IRQ_MBOX0 60 -#define SCP_IRQ_MBOX1 61 -#define SCP_IRQ_MBOX2 62 -#define SCP_IRQ_MBOX3 63 -/* 64 */ -#define SCP_IRQ_MBOX4 64 -#define SCP_IRQ_SYS_CLK_REQ 65 -#define SCP_IRQ_BUS_REQ 66 -#define SCP_IRQ_APSRC_REQ 67 -/* 68 */ -#define SCP_IRQ_APU_MBOX 68 -#define SCP_IRQ_DEVAPC_SECURE_VIO 69 -/* 72 */ -/* 76 */ -#define SCP_IRQ_I2C1_2 78 -#define SCP_IRQ_I2C2 79 -/* 80 */ -#define SCP_IRQ_AUD2AUDIODSP 80 -#define SCP_IRQ_AUD2AUDIODSP_2 81 -#define SCP_IRQ_CONN2ADSP_A2DPOL 82 -#define SCP_IRQ_CONN2ADSP_BTCVSD 83 -/* 84 */ -#define SCP_IRQ_CONN2ADSP_BLEISO 84 -#define SCP_IRQ_PCIE2ADSP 85 -#define SCP_IRQ_APU2ADSP_ENGINE 86 -#define SCP_IRQ_APU2ADSP_MBOX 87 -/* 88 */ -#define SCP_IRQ_CCIF3 88 -#define SCP_IRQ_I2C_DMA0 89 -#define SCP_IRQ_I2C_DMA1 90 -#define SCP_IRQ_I2C_DMA2 91 -/* 92 */ -#define SCP_IRQ_I2C_DMA3 92 - -#endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/mt8192_scp/system.c b/chip/mt8192_scp/system.c deleted file mode 100644 index 8ee0cb382d..0000000000 --- a/chip/mt8192_scp/system.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* System : hardware specific implementation */ - -#include "csr.h" -#include "memmap.h" -#include "registers.h" -#include "system.h" - -void system_pre_init(void) -{ - memmap_init(); - - /* enable CPU and platform low power CG */ - /* enable CPU DCM */ - set_csr(CSR_MCTREN, CSR_MCTREN_CG); - - /* Disable jump (it has only RW) and enable MPU. */ - /* TODO: implement MPU */ - system_disable_jump(); -} - -void system_reset(int flags) -{ - while (1) - ; -} - -int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) -{ - return EC_ERROR_INVAL; -} - -const char *system_get_chip_vendor(void) -{ - return "mtk"; -} - -const char *system_get_chip_name(void) -{ - /* Support only SCP_A for now */ - return "scp_a"; -} - -const char *system_get_chip_revision(void) -{ - return ""; -} diff --git a/chip/mt8192_scp/uart.c b/chip/mt8192_scp/uart.c deleted file mode 100644 index 8b9f7452ae..0000000000 --- a/chip/mt8192_scp/uart.c +++ /dev/null @@ -1,171 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* SCP UART module */ - -#include "csr.h" -#include "system.h" -#include "uart.h" -#include "uart_regs.h" -#include "util.h" - -/* - * UARTN == 0, SCP UART0 - * UARTN == 1, SCP UART1 - * UARTN == 2, AP UART1 - */ -#define UARTN CONFIG_UART_CONSOLE -#define UART_IDLE_WAIT_US 500 -#define UART_INTC_GROUP 12 - -static uint8_t init_done, tx_started; - -void uart_init(void) -{ - const uint32_t baud_rate = CONFIG_UART_BAUD_RATE; - /* TODO: use ULPOSC1 for S3 */ - const uint32_t uart_clock = 26000000; - const uint32_t div = DIV_ROUND_NEAREST(uart_clock, baud_rate * 16); - -#if UARTN == 0 - SCP_UART_CK_SEL |= UART0_CK_SEL_VAL(UART_CK_SEL_26M); - SCP_SET_CLK_CG |= CG_UART0_MCLK | CG_UART0_BCLK | CG_UART0_RST; - - /* set AP GPIO164 and GPIO165 to alt func 3 */ - AP_GPIO_MODE20_CLR = 0x00770000; - AP_GPIO_MODE20_SET = 0x00330000; -#elif UARTN == 1 - SCP_UART_CK_SEL |= UART1_CK_SEL_VAL(UART_CK_SEL_26M); - SCP_SET_CLK_CG |= CG_UART1_MCLK | CG_UART1_BCLK | CG_UART1_RST; -#endif - - /* Clear FIFO */ - UART_FCR(UARTN) = UART_FCR_ENABLE_FIFO - | UART_FCR_CLEAR_RCVR - | UART_FCR_CLEAR_XMIT; - /* Line control: parity none, 8 bit, 1 stop bit */ - UART_LCR(UARTN) = UART_LCR_WLEN8; - /* For baud rate <= 115200 */ - UART_HIGHSPEED(UARTN) = 0; - - /* DLAB start */ - UART_LCR(UARTN) |= UART_LCR_DLAB; - UART_DLL(UARTN) = div & 0xff; - UART_DLH(UARTN) = (div >> 8) & 0xff; - UART_LCR(UARTN) &= ~UART_LCR_DLAB; - /* DLAB end */ - - /* Enable received data interrupt */ - UART_IER(UARTN) |= UART_IER_RDI; - -#if (UARTN < SCP_UART_COUNT) - task_enable_irq(UART_TX_IRQ(UARTN)); - task_enable_irq(UART_RX_IRQ(UARTN)); -#endif - - init_done = 1; -} - -int uart_init_done(void) -{ - return init_done; -} - -void uart_tx_flush(void) -{ - while (!(UART_LSR(UARTN) & UART_LSR_TEMT)) - ; -} - -int uart_tx_ready(void) -{ - return UART_LSR(UARTN) & UART_LSR_THRE; -} - -int uart_rx_available(void) -{ - return UART_LSR(UARTN) & UART_LSR_DR; -} - -void uart_write_char(char c) -{ - while (!uart_tx_ready()) - ; - - UART_THR(UARTN) = c; -} - -int uart_read_char(void) -{ - return UART_RBR(UARTN); -} - -void uart_tx_start(void) -{ - tx_started = 1; - if (UART_IER(UARTN) & UART_IER_THRI) - return; - disable_sleep(SLEEP_MASK_UART); - UART_IER(UARTN) |= UART_IER_THRI; -} - -void uart_tx_stop(void) -{ - /* - * Workaround for b/157541273. - * Don't unset the THRI flag unless we are in the UART ISR. - * - * Note: - * MICAUSE denotes current INTC group number. - */ - if (in_interrupt_context() && - read_csr(CSR_VIC_MICAUSE) != UART_INTC_GROUP) - return; - - tx_started = 0; - UART_IER(UARTN) &= ~UART_IER_THRI; - enable_sleep(SLEEP_MASK_UART); -} - -static void uart_process(void) -{ - uart_process_input(); - uart_process_output(); -} - -#if (UARTN < SCP_UART_COUNT) -static void uart_irq_handler(void) -{ - extern volatile int ec_int; - - switch (ec_int) { - case UART_TX_IRQ(UARTN): - uart_process(); - task_clear_pending_irq(ec_int); - break; - case UART_RX_IRQ(UARTN): - uart_process(); - SCP_CORE0_INTC_UART_RX_IRQ(UARTN) = BIT(0); - task_clear_pending_irq(ec_int); - break; - } -} -DECLARE_IRQ(UART_INTC_GROUP, uart_irq_handler, 0); -#else - -#ifndef HAS_TASK_APUART -#error "APUART task hasn't defined in ec.tasklist." -#endif - -void uart_task(void) -{ - while (1) { - if (uart_rx_available() || tx_started) - uart_process(); - else - task_wait_event(UART_IDLE_WAIT_US); - } -} -#endif diff --git a/chip/mt8192_scp/uart_regs.h b/chip/mt8192_scp/uart_regs.h deleted file mode 100644 index 1a421a413b..0000000000 --- a/chip/mt8192_scp/uart_regs.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* SCP UART module registers */ - -#ifndef __CROS_EC_UART_REGS_H -#define __CROS_EC_UART_REGS_H - -#include "registers.h" - -/* DLAB (Divisor Latch Access Bit) == 0 */ - -/* (Read) receiver buffer register */ -#define UART_RBR(n) UART_REG(n, 0) -/* (Write) transmitter holding register */ -#define UART_THR(n) UART_REG(n, 0) -/* (Write) interrupt enable register */ -#define UART_IER(n) UART_REG(n, 1) -#define UART_IER_RDI BIT(0) /* received data */ -#define UART_IER_THRI BIT(1) /* THR empty */ -#define UART_IER_RLSI BIT(2) /* receiver LSR change */ -#define UART_IER_MSI BIT(3) /* MSR change */ -/* (Read) interrupt identification register */ -#define UART_IIR(n) UART_REG(n, 2) -#define UART_IIR_ID_MASK 0x0e -#define UART_IIR_MSI 0x00 /* modem status change */ -#define UART_IIR_NO_INT 0x01 /* no int pending */ -#define UART_IIR_THRI 0x02 /* THR empty */ -#define UART_IIR_RDI 0x04 /* received data available */ -#define UART_IIR_RLSI 0x06 /* line status change */ -/* (Write) FIFO control register */ -#define UART_FCR(n) UART_REG(n, 2) -#define UART_FCR_ENABLE_FIFO BIT(0) /* enable FIFO */ -#define UART_FCR_CLEAR_RCVR BIT(1) /* clear receive FIFO */ -#define UART_FCR_CLEAR_XMIT BIT(2) /* clear transmit FIFO */ -#define UART_FCR_DMA_SELECT BIT(3) /* select DMA mode */ -/* (Write) line control register */ -#define UART_LCR(n) UART_REG(n, 3) -#define UART_LCR_WLEN5 0 /* word length 5 bits */ -#define UART_LCR_WLEN6 1 -#define UART_LCR_WLEN7 2 -#define UART_LCR_WLEN8 3 -#define UART_LCR_STOP BIT(2) /* stop bits: 1bit, 2bits */ -#define UART_LCR_PARITY BIT(3) /* parity enable */ -#define UART_LCR_EPAR BIT(4) /* even parity */ -#define UART_LCR_SPAR BIT(5) /* stick parity */ -#define UART_LCR_SBC BIT(6) /* set break control */ -#define UART_LCR_DLAB BIT(7) /* divisor latch access */ -/* (Write) modem control register */ -#define UART_MCR(n) UART_REG(n, 4) -/* (Read) line status register */ -#define UART_LSR(n) UART_REG(n, 5) -#define UART_LSR_DR BIT(0) /* data ready */ -#define UART_LSR_OE BIT(1) /* overrun error */ -#define UART_LSR_PE BIT(2) /* parity error */ -#define UART_LSR_FE BIT(3) /* frame error */ -#define UART_LSR_BI BIT(4) /* break interrupt */ -#define UART_LSR_THRE BIT(5) /* THR empty */ -#define UART_LSR_TEMT BIT(6) /* THR empty, line idle */ -#define UART_LSR_FIFOE BIT(7) /* FIFO error */ -/* (Read) modem status register */ -#define UART_MSR(n) UART_REG(n, 6) -/* (Read/Write) scratch register */ -#define UART_SCR(n) UART_REG(n, 7) - -/* DLAB == 1 */ - -/* (Write) divisor latch */ -#define UART_DLL(n) UART_REG(n, 0) -#define UART_DLH(n) UART_REG(n, 1) - -/* MTK extension */ -#define UART_HIGHSPEED(n) UART_REG(n, 9) - -#endif /* __CROS_EC_UART_REGS_H */ diff --git a/chip/mt8192_scp/watchdog.c b/chip/mt8192_scp/watchdog.c deleted file mode 100644 index 72ca5edad8..0000000000 --- a/chip/mt8192_scp/watchdog.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Watchdog driver */ - -#include "common.h" -#include "hooks.h" -#include "registers.h" -#include "watchdog.h" - -void watchdog_reload(void) -{ - SCP_CORE0_WDT_KICK = BIT(0); -} -DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); - -int watchdog_init(void) -{ - const uint32_t timeout = WDT_PERIOD(CONFIG_WATCHDOG_PERIOD_MS); - - /* disable watchdog */ - SCP_CORE0_WDT_CFG &= ~WDT_EN; - /* clear watchdog irq */ - SCP_CORE0_WDT_IRQ |= BIT(0); - /* enable watchdog */ - SCP_CORE0_WDT_CFG = WDT_EN | timeout; - /* reload watchdog */ - watchdog_reload(); - - return EC_SUCCESS; -} diff --git a/chip/mt_scp/build.mk b/chip/mt_scp/build.mk index fa6164056e..3f4baab128 100644 --- a/chip/mt_scp/build.mk +++ b/chip/mt_scp/build.mk @@ -1,34 +1,24 @@ # -*- makefile -*- -# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Copyright 2018 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # SCP specific files build # -CORE:=cortex-m -CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4 - # Required chip modules -chip-y=clock.o gpio.o memmap.o system.o uart.o +chip-y= -ifeq ($(CONFIG_IPI),y) -$(out)/RO/chip/$(CHIP)/ipi_table.o: $(out)/ipi_table_gen.inc -$(out)/RW/chip/$(CHIP)/ipi_table.o: $(out)/ipi_table_gen.inc +ifeq ($(CHIP_VARIANT),$(filter $(CHIP_VARIANT),mt8183 mt8186)) +CPPFLAGS+=-Ichip/$(CHIP)/mt818x +dirs-y+=chip/$(CHIP)/mt818x +include chip/$(CHIP)/mt818x/build.mk endif -ifeq ($(CONFIG_AUDIO_CODEC_WOV),y) -HOTWORD_PRIVATE_LIB:=private/libkukui_scp_google_hotword_dsp_api.a -ifneq ($(wildcard $(HOTWORD_PRIVATE_LIB)),) -LDFLAGS_EXTRA+=$(HOTWORD_PRIVATE_LIB) -HAVE_PRIVATE_AUDIO_CODEC_WOV_LIBS:=y -endif +ifeq ($(CHIP_VARIANT),$(filter $(CHIP_VARIANT),mt8192 mt8195)) +CPPFLAGS+=-Ichip/$(CHIP)/rv32i_common -Ichip/$(CHIP)/$(CHIP_VARIANT) +dirs-y+=chip/$(CHIP)/rv32i_common chip/$(CHIP)/$(CHIP_VARIANT) +include chip/$(CHIP)/rv32i_common/build.mk +# Each chip variant can provide specific build.mk if any +include chip/$(CHIP)/$(CHIP_VARIANT)/build.mk endif - -# Optional chip modules -chip-$(CONFIG_AUDIO_CODEC_WOV)+=audio_codec_wov.o -chip-$(CONFIG_COMMON_TIMER)+=hrtimer.o -chip-$(CONFIG_I2C)+=i2c.o -chip-$(CONFIG_IPI)+=ipi.o ipi_table.o -chip-$(CONFIG_SPI)+=spi.o -chip-$(CONFIG_WATCHDOG)+=watchdog.o diff --git a/chip/mt_scp/clock.c b/chip/mt_scp/clock.c deleted file mode 100644 index a6f1883d31..0000000000 --- a/chip/mt_scp/clock.c +++ /dev/null @@ -1,374 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Clocks, PLL and power settings */ - -#include "clock.h" -#include "clock_chip.h" -#include "common.h" -#include "console.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) - -#define ULPOSC_DIV_MAX (1 << OSC_DIV_BITS) -#define ULPOSC_CALI_MAX (1 << OSC_CALI_BITS) - -void clock_init(void) -{ - /* Set VREQ to HW mode */ - SCP_CPU_VREQ = CPU_VREQ_HW_MODE; - SCP_SECURE_CTRL &= ~ENABLE_SPM_MASK_VREQ; - - /* Set DDREN auto mode */ - SCP_SYS_CTRL |= AUTO_DDREN; - - /* Initialize 26MHz system clock counter reset value to 1. */ - SCP_CLK_SYS_VAL = - (SCP_CLK_SYS_VAL & ~CLK_SYS_VAL_MASK) | CLK_SYS_VAL(1); - /* Initialize high frequency ULPOSC counter reset value to 1. */ - SCP_CLK_HIGH_VAL = - (SCP_CLK_HIGH_VAL & ~CLK_HIGH_VAL_MASK) | CLK_HIGH_VAL(1); - /* Initialize sleep mode control VREQ counter. */ - SCP_CLK_SLEEP_CTRL = - (SCP_CLK_SLEEP_CTRL & ~VREQ_COUNTER_MASK) | VREQ_COUNTER_VAL(1); - - /* Set normal wake clock */ - SCP_WAKE_CKSW &= ~WAKE_CKSW_SEL_NORMAL_MASK; - - /* Enable fast wakeup support */ - SCP_CLK_SLEEP = 0; - SCP_CLK_ON_CTRL = (SCP_CLK_ON_CTRL & ~HIGH_FINAL_VAL_MASK) | - HIGH_FINAL_VAL_DEFAULT; - SCP_FAST_WAKE_CNT_END = - (SCP_FAST_WAKE_CNT_END & ~FAST_WAKE_CNT_END_MASK) | - FAST_WAKE_CNT_END_DEFAULT; - - /* Set slow wake clock */ - SCP_WAKE_CKSW = (SCP_WAKE_CKSW & ~WAKE_CKSW_SEL_SLOW_MASK) | - WAKE_CKSW_SEL_SLOW_DEFAULT; - - /* Select CLK_HIGH as wakeup clock */ - SCP_CLK_SLOW_SEL = (SCP_CLK_SLOW_SEL & - ~(CKSW_SEL_SLOW_MASK | CKSW_SEL_SLOW_DIV_MASK)) | - CKSW_SEL_SLOW_ULPOSC2_CLK; - - /* - * Set legacy wakeup - * - disable SPM sleep control - * - disable SCP sleep mode - */ - SCP_CLK_SLEEP_CTRL &= ~(EN_SLEEP_CTRL | SPM_SLEEP_MODE); - - task_enable_irq(SCP_IRQ_CLOCK); - task_enable_irq(SCP_IRQ_CLOCK2); -} - -static void scp_ulposc_config(int osc, uint32_t osc_div, uint32_t osc_cali) -{ - uint32_t val; - - /* Clear all bits */ - val = 0; - /* Enable CP */ - val |= OSC_CP_EN; - /* Set div */ - val |= osc_div << 17; - /* F-band = 0, I-band = 4 */ - val |= 4 << 6; - /* Set calibration */ - val |= osc_cali; - /* Set control register 1 */ - AP_ULPOSC_CON02(osc) = val; - /* Set control register 2, enable div2 */ - AP_ULPOSC_CON13(osc) |= OSC_DIV2_EN; -} - -static inline void busy_udelay(int usec) -{ - /* - * Delaying by busy-looping, for place that can't use udelay because of - * the clock not configured yet. The value 28 is chosen approximately - * from experiment. - */ - volatile int i = usec * 28; - - while (i--) - ; -} - -static unsigned int scp_measure_ulposc_freq(int osc) -{ - unsigned int result = 0; - int cnt; - - /* Before select meter clock input, bit[1:0] = b00 */ - AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_MODE_MASK) | - DBG_MODE_SET_CLOCK; - - /* Select source, bit[21:16] = clk_src */ - AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_BIST_SOURCE_MASK) | - (osc == 0 ? DBG_BIST_SOURCE_ULPOSC1 : - DBG_BIST_SOURCE_ULPOSC2); - - /* Set meter divisor to 1, bit[31:24] = b00000000 */ - AP_CLK_MISC_CFG_0 = (AP_CLK_MISC_CFG_0 & ~MISC_METER_DIVISOR_MASK) | - MISC_METER_DIV_1; - - /* Enable frequency meter, without start */ - AP_SCP_CFG_0 |= CFG_FREQ_METER_ENABLE; - - /* Trigger frequency meter start */ - AP_SCP_CFG_0 |= CFG_FREQ_METER_RUN; - - /* - * Frequency meter counts cycles in 1 / (26 * 1024) second period. - * freq_in_hz = freq_counter * 26 * 1024 - * - * The hardware takes 38us to count cycles. Delay up to 100us, - * as busy_udelay may not be accurate when sysclk is not 26Mhz - * (e.g. when recalibrating/measuring after boot). - */ - for (cnt = 100; cnt; cnt--) { - busy_udelay(1); - if (!(AP_SCP_CFG_0 & CFG_FREQ_METER_RUN)) { - result = CFG_FREQ_COUNTER(AP_SCP_CFG_1); - break; - } - } - - /* Disable freq meter */ - AP_SCP_CFG_0 &= ~CFG_FREQ_METER_ENABLE; - return result; -} - -static inline int signum(int v) -{ - return (v > 0) - (v < 0); -} - -static inline int abs(int v) -{ - return (v >= 0) ? v : -v; -} - -static int scp_ulposc_config_measure(int osc, int div, int cali) -{ - int freq; - - scp_ulposc_config(osc, div, cali); - freq = scp_measure_ulposc_freq(osc); - CPRINTF("ULPOSC%d: %d %d %d (%dkHz)\n", - osc + 1, div, cali, freq, - freq * 26 * 1000 / 1024); - - return freq; -} - -/** - * Calibrate ULPOSC to target frequency. - * - * @param osc 0:ULPOSC1, 1:ULPOSC2 - * @param target_mhz Target frequency to set - * @return Frequency counter output - * - */ -static int scp_calibrate_ulposc(int osc, int target_mhz) -{ - int target_freq = DIV_ROUND_NEAREST(target_mhz * 1024, 26); - struct ulposc { - int div; /* frequency divisor/multiplier */ - int cali; /* variable resistor calibrator */ - int freq; /* frequency counter measure result */ - } curr, prev = {0}; - enum { STAGE_DIV, STAGE_CALI } stage = STAGE_DIV; - int param, param_max; - - curr.div = ULPOSC_DIV_MAX / 2; - curr.cali = ULPOSC_CALI_MAX / 2; - - param = curr.div; - param_max = ULPOSC_DIV_MAX; - - /* - * In the loop below, linear search closest div value to get desired - * frequency counter value. Then adjust cali to get a better result. - * Note that this doesn't give optimal output frequency, but it's - * usually close enough. - * TODO(b:120176040): See if we can efficiently calibrate the clock with - * more precision by exploring more of the cali/div space. - * - * The frequency function follows. Note that f is positively correlated - * with both div and cali: - * f(div, cali) = k1 * (div + k2) / R(cali) * C - * Where: - * R(cali) = k3 / (1 + k4 * (cali - k4)) - */ - while (1) { - curr.freq = scp_ulposc_config_measure(osc, curr.div, curr.cali); - - if (!curr.freq) - return 0; - - /* - * If previous and current are on either side of the desired - * frequency, pick the closest one. - */ - if (prev.freq && signum(target_freq - curr.freq) != - signum(target_freq - prev.freq)) { - if (abs(target_freq - prev.freq) < - abs(target_freq - curr.freq)) - curr = prev; - - if (stage == STAGE_CALI) - break; - - /* Switch to optimizing cali */ - stage = STAGE_CALI; - param = curr.cali; - param_max = ULPOSC_CALI_MAX; - } - - prev = curr; - param += signum(target_freq - curr.freq); - - if (param < 0 || param >= param_max) - return 0; - - if (stage == STAGE_DIV) - curr.div = param; - else - curr.cali = param; - } - - /* - * It's possible we end up using prev, so reset the configuration and - * measure again. - */ - return scp_ulposc_config_measure(osc, curr.div, curr.cali); -} - -static void scp_clock_high_enable(int osc) -{ - /* Enable high speed clock */ - SCP_CLK_EN |= EN_CLK_HIGH; - - switch (osc) { - case 0: - /* After 25ms, enable ULPOSC */ - busy_udelay(25 * MSEC); - SCP_CLK_EN |= CG_CLK_HIGH; - break; - case 1: - /* Turn off ULPOSC2 high-core-disable switch */ - SCP_CLK_ON_CTRL &= ~HIGH_CORE_DIS_SUB; - /* After 25ms, turn on ULPOSC2 high core clock gate */ - busy_udelay(25 * MSEC); - SCP_CLK_HIGH_CORE |= CLK_HIGH_CORE_CG; - break; - default: - break; - } -} - -void scp_use_clock(enum scp_clock_source src) -{ - /* - * DIV2 divider takes precedence over clock selection to prevent - * over-clocking. - */ - if (src == SCP_CLK_ULPOSC1) - SCP_CLK_DIV_SEL = CLK_DIV2; - - SCP_CLK_SEL = src; - - if (src != SCP_CLK_ULPOSC1) - SCP_CLK_DIV_SEL = CLK_DIV1; -} - -void scp_enable_clock(void) -{ - /* Select default CPU clock */ - scp_use_clock(SCP_CLK_26M); - - /* VREQ */ - SCP_CPU_VREQ = 0x10001; - SCP_SECURE_CTRL &= ~ENABLE_SPM_MASK_VREQ; - - /* DDREN auto mode */ - SCP_SYS_CTRL |= AUTO_DDREN; - - /* Set settle time */ - SCP_CLK_SYS_VAL = 1; /* System clock */ - SCP_CLK_HIGH_VAL = 1; /* ULPOSC */ - SCP_CLK_SLEEP_CTRL = (SCP_CLK_SLEEP_CTRL & ~VREQ_COUNTER_MASK) | 2; - - /* Disable slow wake */ - SCP_CLK_SLEEP = SLOW_WAKE_DISABLE; - /* Disable SPM sleep control, disable sleep mode */ - SCP_CLK_SLEEP_CTRL &= ~(SPM_SLEEP_MODE | EN_SLEEP_CTRL); - - /* Turn off ULPOSC2 */ - SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB; - scp_ulposc_config(0, 12, 32); - scp_clock_high_enable(0); /* Turn on ULPOSC1 */ - scp_ulposc_config(1, 16, 32); - scp_clock_high_enable(1); /* Turn on ULPOSC2 */ - - /* Calibrate ULPOSC */ - scp_calibrate_ulposc(0, ULPOSC1_CLOCK_MHZ); - scp_calibrate_ulposc(1, ULPOSC2_CLOCK_MHZ); - - /* Select ULPOSC2 high speed CPU clock */ - scp_use_clock(SCP_CLK_ULPOSC2); - - /* Enable default clock gate */ - SCP_CLK_GATE |= CG_DMA_CH3 | CG_DMA_CH2 | CG_DMA_CH1 | CG_DMA_CH0 | - CG_I2C_M | CG_MAD_M | CG_AP2P_M; - - /* Select pwrap_ulposc */ - AP_CLK_CFG_5 = (AP_CLK_CFG_5 & ~PWRAP_ULPOSC_MASK) | OSC_D16; - - /* Enable pwrap_ulposc clock gate */ - AP_CLK_CFG_5_CLR = PWRAP_ULPOSC_CG; -} - -void clock_control_irq(void) -{ - /* Read ack CLK_IRQ */ - (SCP_CLK_IRQ_ACK); - task_clear_pending_irq(SCP_IRQ_CLOCK); -} -DECLARE_IRQ(SCP_IRQ_CLOCK, clock_control_irq, 3); - -void clock_fast_wakeup_irq(void) -{ - /* Ack fast wakeup */ - SCP_SLEEP_IRQ2 = 1; - task_clear_pending_irq(SCP_IRQ_CLOCK2); -} -DECLARE_IRQ(SCP_IRQ_CLOCK2, clock_fast_wakeup_irq, 3); - -/* Console command */ -int command_ulposc(int argc, char *argv[]) -{ - if (argc > 1 && !strncmp(argv[1], "cal", 3)) { - scp_calibrate_ulposc(0, ULPOSC1_CLOCK_MHZ); - scp_calibrate_ulposc(1, ULPOSC2_CLOCK_MHZ); - } - - /* SCP clock meter counts every (26MHz / 1024) tick */ - ccprintf("ULPOSC1 frequency: %u kHz\n", - scp_measure_ulposc_freq(0) * 26 * 1000 / 1024); - ccprintf("ULPOSC2 frequency: %u kHz\n", - scp_measure_ulposc_freq(1) * 26 * 1000 / 1024); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[calibrate]", - "Calibrate ULPOSC frequency"); diff --git a/chip/mt_scp/clock_chip.h b/chip/mt_scp/clock_chip.h deleted file mode 100644 index a16bf2e54e..0000000000 --- a/chip/mt_scp/clock_chip.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Clocks, PLL and power settings */ - -#ifndef __CROS_EC_CLOCK_CHIP_H -#define __CROS_EC_CLOCK_CHIP_H - -#include "common.h" -#include "registers.h" - -/* Default ULPOSC clock speed in MHz */ -#ifndef ULPOSC1_CLOCK_MHZ -#define ULPOSC1_CLOCK_MHZ 240 -#endif -#ifndef ULPOSC2_CLOCK_MHZ -#define ULPOSC2_CLOCK_MHZ 330 -#endif - -void scp_enable_clock(void); - -enum scp_clock_source { - SCP_CLK_26M = CLK_SEL_SYS_26M, - SCP_CLK_32K = CLK_SEL_32K, - SCP_CLK_ULPOSC2 = CLK_SEL_ULPOSC_2, - SCP_CLK_ULPOSC1 = CLK_SEL_ULPOSC_1, -}; - -/* Switches to use 'src' clock */ -void scp_use_clock(enum scp_clock_source src); - -#endif /* __CROS_EC_CLOCK_CHIP_H */ diff --git a/chip/mt_scp/config_chip.h b/chip/mt_scp/config_chip.h index 89311cda38..65d529f8e9 100644 --- a/chip/mt_scp/config_chip.h +++ b/chip/mt_scp/config_chip.h @@ -1,64 +1,12 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2021 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#ifndef __CROS_EC_CONFIG_CHIP_H -#define __CROS_EC_CONFIG_CHIP_H +#if defined(CHIP_VARIANT_MT8183) || defined(CHIP_VARIANT_MT8186) +#include "mt818x/config_chip.h" +#endif -#include "core/cortex-m/config_core.h" - -/* Interval between HOOK_TICK notifications */ -#define HOOK_TICK_INTERVAL_MS 500 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) - -/* Default to UART 2 (AP UART) for EC console */ -#define CONFIG_UART_CONSOLE 2 - -/* Number of IRQ vectors */ -#define CONFIG_IRQ_COUNT 56 - -/* - * Number of EINT can be 0 ~ 160. Change this to conditional macro - * on adding other variants. - */ -#define MAX_NUM_EINT 8 -#define MAX_EINT_PORT (MAX_NUM_EINT / 32) - -/* RW only, no flash */ -#undef CONFIG_FW_INCLUDE_RO -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_SIZE 0 -#define CONFIG_RW_MEM_OFF 0 -#define CONFIG_RW_SIZE 0x40000 /* 256KB */ -#define CONFIG_EC_WRITABLE_STORAGE_OFF 0 -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_PROGRAM_MEMORY_BASE 0 -#define CONFIG_MAPPED_STORAGE_BASE 0 -/* Enable MPU to protect code RAM from writing, and data RAM from execution.*/ -#define CONFIG_MPU - -/* Unsupported features/commands */ -#undef CONFIG_CMD_FLASHINFO -#undef CONFIG_CMD_POWER_AP -#undef CONFIG_FLASH -#undef CONFIG_FLASH_PHYSICAL -#undef CONFIG_FMAP -#undef CONFIG_HIBERNATE - -/* Task stack size */ -#define CONFIG_STACK_SIZE 1024 -#define IDLE_TASK_STACK_SIZE 256 -#define SMALLER_TASK_STACK_SIZE 384 -#define TASK_STACK_SIZE 512 -#define LARGER_TASK_STACK_SIZE 640 -#define VENTI_TASK_STACK_SIZE 768 - -#define CONFIG_CHIP_PRE_INIT - -#define GPIO_PIN(num) ((num) / 32), ((num) % 32) -#define GPIO_PIN_MASK(p, m) .port = (p), .mask = (m) - -#endif /* __CROS_EC_CONFIG_CHIP_H */ +#if defined(CHIP_VARIANT_MT8192) || defined(CHIP_VARIANT_MT8195) +#include "rv32i_common/config_chip.h" +#endif diff --git a/chip/mt_scp/gpio.c b/chip/mt_scp/gpio.c deleted file mode 100644 index a4896aae72..0000000000 --- a/chip/mt_scp/gpio.c +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* GPIO module */ - -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "util.h" - -void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) -{ - int bit, mode_reg_index, shift; - uint32_t mode_bits, mode_mask; - - /* Up to 8 alt functions per port */ - if (func > GPIO_ALT_FUNC_7) - return; - - if (func == GPIO_ALT_FUNC_NONE) - func = GPIO_ALT_FUNC_DEFAULT; - - while (mask) { - /* 32 gpio per port */ - bit = get_next_bit(&mask); - /* 8 gpio per mode reg */ - mode_reg_index = (port << 2) | (bit >> 3); - /* - * b[3] - write enable(?) - * b[2:0] - mode - */ - shift = (bit & 7) << 2; - mode_bits = func << shift; - mode_mask = ~(0xf << shift); - AP_GPIO_MODE(mode_reg_index) = (AP_GPIO_MODE(mode_reg_index) & - mode_mask) | mode_bits; - } -} - -test_mockable int gpio_get_level(enum gpio_signal signal) -{ - return !!(AP_GPIO_DIN(gpio_list[signal].port) & - gpio_list[signal].mask); -} - - -void gpio_set_level(enum gpio_signal signal, int value) -{ - if (value) - AP_GPIO_DOUT(gpio_list[signal].port) |= gpio_list[signal].mask; - else - AP_GPIO_DOUT(gpio_list[signal].port) &= ~gpio_list[signal].mask; -} - -void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) -{ - /* Set input/output mode */ - if (flags & GPIO_OUTPUT) { - /* Set level before changing to output mode */ - if (flags & GPIO_HIGH) - AP_GPIO_DOUT(port) |= mask; - if (flags & GPIO_LOW) - AP_GPIO_DOUT(port) &= ~mask; - AP_GPIO_DIR(port) |= mask; - } else { - AP_GPIO_DIR(port) &= ~mask; - } - - if (flags & (GPIO_INT_F_RISING | GPIO_INT_F_HIGH)) - SCP_EINT_POLARITY_SET[port] = mask; - - if (flags & (GPIO_INT_F_FALLING | GPIO_INT_F_LOW)) - SCP_EINT_POLARITY_CLR[port] = mask; - else - SCP_EINT_POLARITY_SET[port] = mask; - - /* Set sensitivity register on edge trigger */ - if (flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING)) - SCP_EINT_SENS_SET[port] = mask; - else - SCP_EINT_SENS_CLR[port] = mask; -} - -int gpio_get_flags_by_mask(uint32_t port, uint32_t mask) -{ - /* TODO(b/120167145): implement get flags */ - return 0; -} - -int gpio_enable_interrupt(enum gpio_signal signal) -{ - const struct gpio_info *g = gpio_list + signal; - - if (signal >= GPIO_IH_COUNT || !g->mask) - return EC_ERROR_INVAL; - - SCP_EINT_MASK_CLR[g->port] = g->mask; - - return EC_SUCCESS; -} - -int gpio_disable_interrupt(enum gpio_signal signal) -{ - const struct gpio_info *g = gpio_list + signal; - - if (signal >= GPIO_IH_COUNT || !g->mask) - return EC_ERROR_INVAL; - - SCP_EINT_MASK_SET[g->port] = g->mask; - - return EC_SUCCESS; -} - -int gpio_clear_pending_interrupt(enum gpio_signal signal) -{ - const struct gpio_info *g = gpio_list + signal; - - if (signal >= GPIO_IH_COUNT || !g->mask) - return EC_ERROR_INVAL; - - SCP_EINT_ACK[g->port] = g->mask; - - return EC_SUCCESS; -} - -void gpio_pre_init(void) -{ - const struct gpio_info *g = gpio_list; - int i; - int is_warm = system_is_reboot_warm(); - - for (i = 0; i < GPIO_COUNT; i++, g++) { - int flags = g->flags; - - if (flags & GPIO_DEFAULT) - continue; - - if (is_warm) - flags &= ~(GPIO_LOW | GPIO_HIGH); - - gpio_set_flags_by_mask(g->port, g->mask, flags); - } -} - -void gpio_init(void) -{ - /* Enable EINT IRQ */ - task_enable_irq(SCP_IRQ_EINT); -} -DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); - -/* Interrupt handler */ -void __keep gpio_interrupt(void) -{ - int bit, port; - uint32_t pending; - enum gpio_signal signal; - - for (port = 0; port <= MAX_EINT_PORT; port++) { - pending = SCP_EINT_STATUS[port]; - - while (pending) { - bit = get_next_bit(&pending); - SCP_EINT_ACK[port] = BIT(bit); - /* Skip masked gpio */ - if (SCP_EINT_MASK_GET[port] & BIT(bit)) - continue; - /* Call handler */ - signal = port * 32 + bit; - if (signal < GPIO_IH_COUNT) - gpio_irq_handlers[signal](signal); - } - } -} -DECLARE_IRQ(SCP_IRQ_EINT, gpio_interrupt, 1); diff --git a/chip/mt_scp/hrtimer.c b/chip/mt_scp/hrtimer.c deleted file mode 100644 index f970af6eb5..0000000000 --- a/chip/mt_scp/hrtimer.c +++ /dev/null @@ -1,253 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * High-res hardware timer - * - * SCP hardware 32bit count down timer can be configured to source clock from - * 32KHz, 26MHz, BCLK or PCLK. This implementation selects BCLK (ULPOSC1/8) as a - * source, countdown mode and converts to micro second value matching common - * timer. - */ - -#include "clock.h" -#include "clock_chip.h" -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "hwtimer.h" -#include "panic.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "watchdog.h" - -#define IRQ_TIMER(n) CONCAT2(SCP_IRQ_TIMER, n) - -#define TIMER_SYSTEM 5 -#define TIMER_EVENT 3 - -/* ULPOSC1 should be a multiple of 8. */ -BUILD_ASSERT((ULPOSC1_CLOCK_MHZ % 8) == 0); -#define TIMER_CLOCK_MHZ (ULPOSC1_CLOCK_MHZ / 8) - -/* Common timer overflows at 0x100000000 micro seconds */ -#define OVERFLOW_TICKS (TIMER_CLOCK_MHZ * 0x100000000 - 1) - -static uint8_t sys_high; -static uint8_t event_high; - -/* Convert hardware countdown timer to 64bit countup ticks */ -static inline uint64_t timer_read_raw_system(void) -{ - uint32_t timer_ctrl = SCP_TIMER_IRQ_CTRL(TIMER_SYSTEM); - uint32_t sys_high_adj = sys_high; - - /* - * If an IRQ is pending, but has not been serviced yet, adjust the - * sys_high value. - */ - if (timer_ctrl & TIMER_IRQ_STATUS) - sys_high_adj = sys_high ? (sys_high - 1) : (TIMER_CLOCK_MHZ-1); - - return OVERFLOW_TICKS - (((uint64_t)sys_high_adj << 32) | - SCP_TIMER_VAL(TIMER_SYSTEM)); -} - -static inline uint64_t timer_read_raw_event(void) -{ - return OVERFLOW_TICKS - (((uint64_t)event_high << 32) | - SCP_TIMER_VAL(TIMER_EVENT)); -} - -static inline void timer_set_clock(int n, uint32_t clock_source) -{ - SCP_TIMER_EN(n) = (SCP_TIMER_EN(n) & ~TIMER_CLK_MASK) | - clock_source; -} - -static inline void timer_ack_irq(int n) -{ - SCP_TIMER_IRQ_CTRL(n) |= TIMER_IRQ_CLEAR; -} - -/* Set hardware countdown value */ -static inline void timer_set_reset_value(int n, uint32_t reset_value) -{ - SCP_TIMER_RESET_VAL(n) = reset_value; -} - -static void timer_reset(int n) -{ - __hw_timer_enable_clock(n, 0); - timer_ack_irq(n); - timer_set_reset_value(n, 0xffffffff); - timer_set_clock(n, TIMER_CLK_32K); -} - -/* Reload a new 32bit countdown value */ -static void timer_reload(int n, uint32_t value) -{ - __hw_timer_enable_clock(n, 0); - timer_set_reset_value(n, value); - __hw_timer_enable_clock(n, 1); -} - -static int timer_reload_event_high(void) -{ - if (event_high) { - if (SCP_TIMER_RESET_VAL(TIMER_EVENT) == 0xffffffff) - __hw_timer_enable_clock(TIMER_EVENT, 1); - else - timer_reload(TIMER_EVENT, 0xffffffff); - event_high--; - return 1; - } - - /* Disable event timer clock when done. */ - __hw_timer_enable_clock(TIMER_EVENT, 0); - return 0; -} - -void __hw_clock_event_clear(void) -{ - __hw_timer_enable_clock(TIMER_EVENT, 0); - timer_set_reset_value(TIMER_EVENT, 0x0000c1ea4); - event_high = 0; -} - -void __hw_clock_event_set(uint32_t deadline) -{ - uint64_t deadline_raw = (uint64_t)deadline * TIMER_CLOCK_MHZ; - uint64_t now_raw = timer_read_raw_system(); - uint32_t event_deadline; - - if (deadline_raw > now_raw) { - deadline_raw -= now_raw; - event_deadline = (uint32_t)deadline_raw; - event_high = deadline_raw >> 32; - } else { - event_deadline = 1; - event_high = 0; - } - - if (event_deadline) - timer_reload(TIMER_EVENT, event_deadline); - else - timer_reload_event_high(); -} - -void __hw_timer_enable_clock(int n, int enable) -{ - if (enable) { - SCP_TIMER_IRQ_CTRL(n) |= 1; - SCP_TIMER_EN(n) |= 1; - } else { - SCP_TIMER_EN(n) &= ~1; - SCP_TIMER_IRQ_CTRL(n) &= ~1; - } -} - -int __hw_clock_source_init(uint32_t start_t) -{ - int t; - - /* - * TODO(b/120169529): check clock tree to see if we need to turn on - * MCLK and BCLK gate. - */ - SCP_CLK_GATE |= (CG_TIMER_M | CG_TIMER_B); - - /* Reset all timer, select 32768Hz clock source */ - for (t = 0; t < NUM_TIMERS; t++) - timer_reset(t); - - /* Enable timer IRQ wake source */ - SCP_INTC_IRQ_WAKEUP |= (1 << IRQ_TIMER(0)) | (1 << IRQ_TIMER(1)) | - (1 << IRQ_TIMER(2)) | (1 << IRQ_TIMER(3)) | - (1 << IRQ_TIMER(4)) | (1 << IRQ_TIMER(5)); - /* - * Timer configuration: - * OS TIMER - count up @ 13MHz, 64bit value with latch. - * SYS TICK - count down @ 26MHz - * EVENT TICK - count down @ 26MHz - */ - - /* Turn on OS TIMER, tick at 13MHz */ - SCP_OSTIMER_CON |= 1; - - /* System timestamp timer from BCLK (sourced from ULPOSC) */ - SCP_CLK_BCLK = CLK_BCLK_SEL_ULPOSC1_DIV8; - - timer_set_clock(TIMER_SYSTEM, TIMER_CLK_BCLK); - sys_high = TIMER_CLOCK_MHZ-1; - timer_set_reset_value(TIMER_SYSTEM, 0xffffffff); - __hw_timer_enable_clock(TIMER_SYSTEM, 1); - task_enable_irq(IRQ_TIMER(TIMER_SYSTEM)); - /* Event tick timer */ - timer_set_clock(TIMER_EVENT, TIMER_CLK_BCLK); - task_enable_irq(IRQ_TIMER(TIMER_EVENT)); - - return IRQ_TIMER(TIMER_SYSTEM); -} - -uint32_t __hw_clock_source_read(void) -{ - return timer_read_raw_system() / TIMER_CLOCK_MHZ; -} - -uint32_t __hw_clock_event_get(void) -{ - return (timer_read_raw_event() + timer_read_raw_system()) - / TIMER_CLOCK_MHZ; -} - -static void __hw_clock_source_irq(int n) -{ - uint32_t timer_ctrl = SCP_TIMER_IRQ_CTRL(n); - - /* Ack if we're hardware interrupt */ - if (timer_ctrl & TIMER_IRQ_STATUS) - timer_ack_irq(n); - - switch (n) { - case TIMER_EVENT: - if (timer_ctrl & TIMER_IRQ_STATUS) { - if (timer_reload_event_high()) - return; - } - process_timers(0); - break; - case TIMER_SYSTEM: - /* If this is a hardware irq, check overflow */ - if (timer_ctrl & TIMER_IRQ_STATUS) { - if (sys_high) { - sys_high--; - process_timers(0); - } else { - /* Overflow, reload system timer */ - sys_high = TIMER_CLOCK_MHZ-1; - process_timers(1); - } - } else { - process_timers(0); - } - break; - default: - return; - } - -} - -#define DECLARE_TIMER_IRQ(n) \ - void __hw_clock_source_irq_##n(void) { __hw_clock_source_irq(n); } \ - DECLARE_IRQ(IRQ_TIMER(n), __hw_clock_source_irq_##n, 2) - -DECLARE_TIMER_IRQ(0); -DECLARE_TIMER_IRQ(1); -DECLARE_TIMER_IRQ(2); -DECLARE_TIMER_IRQ(3); -DECLARE_TIMER_IRQ(4); -DECLARE_TIMER_IRQ(5); diff --git a/chip/mt_scp/ipi.c b/chip/mt_scp/ipi.c deleted file mode 100644 index db371f02b4..0000000000 --- a/chip/mt_scp/ipi.c +++ /dev/null @@ -1,394 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Inter-Processor Communication (IPC) and Inter-Processor Interrupt (IPI) - * - * IPC is a communication bridge between AP and SCP. AP/SCP sends an IPC - * interrupt to SCP/AP to inform to collect the commmunication mesesages in the - * shared buffer. - * - * There are 4 IPCs in the current architecture, from IPC0 to IPC3. The - * priority of IPC is proportional to its IPC index. IPC3 has the highest - * priority and IPC0 has the lowest one. - * - * IPC0 may contain zero or more IPIs. Each IPI represents a task or a service, - * e.g. host command, or video encoding. IPIs are recognized by IPI ID, which - * should sync across AP and SCP. Shared buffer should designated which IPI - * ID it talks to. - * - * Currently, we don't have IPC handlers for IPC1, IPC2, and IPC3. - */ - -#include "clock_chip.h" -#include "console.h" -#include "hooks.h" -#include "host_command.h" -#include "ipi_chip.h" -#include "mkbp_event.h" -#include "power.h" -#include "system.h" -#include "task.h" -#include "util.h" -#include "hwtimer.h" - -#define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) -#define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) - -#define IPI_MAX_REQUEST_SIZE CONFIG_IPC_SHARED_OBJ_BUF_SIZE -/* Reserve 1 extra byte for HOSTCMD_TYPE and 3 bytes for padding. */ -#define IPI_MAX_RESPONSE_SIZE (CONFIG_IPC_SHARED_OBJ_BUF_SIZE - 4) -#define HOSTCMD_TYPE_HOSTCMD 1 -#define HOSTCMD_TYPE_HOSTEVENT 2 - -static volatile int16_t ipc0_enabled_count; -static struct mutex ipc0_lock; -static struct mutex ipi_lock; -/* IPC0 shared objects, including send object and receive object. */ -static struct ipc_shared_obj *const scp_send_obj = - (struct ipc_shared_obj *)CONFIG_IPC_SHARED_OBJ_ADDR; -static struct ipc_shared_obj *const scp_recv_obj = - (struct ipc_shared_obj *)(CONFIG_IPC_SHARED_OBJ_ADDR + - sizeof(struct ipc_shared_obj)); -static char ipi_ready; - -#ifdef HAS_TASK_HOSTCMD -/* - * hostcmd and hostevent share the same IPI ID, and use first byte type to - * indicate its type. - */ -static struct hostcmd_data { - const uint8_t type; - /* To be compatible with CONFIG_HOSTCMD_ALIGNED */ - uint8_t response[IPI_MAX_RESPONSE_SIZE] __aligned(4); -} hc_cmd_obj = { .type = HOSTCMD_TYPE_HOSTCMD }; -BUILD_ASSERT(sizeof(struct hostcmd_data) == CONFIG_IPC_SHARED_OBJ_BUF_SIZE); - -static struct host_packet ipi_packet; -#endif - -/* Check if SCP to AP IPI is in use. */ -static inline int is_ipi_busy(void) -{ - return SCP_HOST_INT & IPC_SCP2HOST_BIT; -} - -/* If IPI is declared as a wake-up source, wake AP up. */ -static inline void try_to_wakeup_ap(int32_t id) -{ -#ifdef CONFIG_RPMSG_NAME_SERVICE - if (id == IPI_NS_SERVICE) - return; -#endif - - if (*ipi_wakeup_table[id]) - SCP_SPM_INT = SPM_INT_A2SPM; -} - -void ipi_disable_irq(int irq) -{ - /* Only support SCP_IRQ_IPC0 for now. */ - if (irq != SCP_IRQ_IPC0) - return; - - mutex_lock(&ipc0_lock); - - if ((--ipc0_enabled_count) == 0) - task_disable_irq(irq); - - mutex_unlock(&ipc0_lock); -} - -void ipi_enable_irq(int irq) -{ - /* Only support SCP_IRQ_IPC0 for now. */ - if (irq != SCP_IRQ_IPC0) - return; - - mutex_lock(&ipc0_lock); - - if ((++ipc0_enabled_count) == 1) { - int pending_ipc = SCP_GIPC_IN & SCP_GPIC_IN_CLEAR_ALL; - - task_enable_irq(irq); - - if (ipi_ready && pending_ipc) - /* - * IPC may be triggered while SCP_IRQ_IPC0 was disabled. - * AP will still updates SCP_GIPC_IN. - * Trigger the IRQ handler if it has a - * pending IPC. - */ - task_trigger_irq(irq); - } - - mutex_unlock(&ipc0_lock); -} - -__override void -power_chipset_handle_host_sleep_event(enum host_sleep_event state, - struct host_sleep_event_context *ctx) -{ - int i; - const task_id_t s3_suspend_tasks[] = { -#ifndef S3_SUSPEND_TASK_LIST -#define S3_SUSPEND_TASK_LIST -#endif -#define TASK(n, ...) TASK_ID_##n, - S3_SUSPEND_TASK_LIST - }; - - if (state == HOST_SLEEP_EVENT_S3_SUSPEND) { - ccprints("AP suspend"); - /* - * On AP suspend, Vcore is 0.6V, and we should not use ULPOSC2, - * which needs at least 0.7V. Switch to ULPOSC1 instead. - */ - scp_use_clock(SCP_CLK_ULPOSC1); - - for (i = 0; i < ARRAY_SIZE(s3_suspend_tasks); ++i) - task_disable_task(s3_suspend_tasks[i]); - } else if (state == HOST_SLEEP_EVENT_S3_RESUME) { - ccprints("AP resume"); - /* Vcore is raised to >=0.7V, switch back to ULPSOC2 */ - scp_use_clock(SCP_CLK_ULPOSC2); - - for (i = 0; i < ARRAY_SIZE(s3_suspend_tasks); ++i) - task_enable_task(s3_suspend_tasks[i]); - } -} - -/* Send data from SCP to AP. */ -int ipi_send(int32_t id, const void *buf, uint32_t len, int wait) -{ - if (!ipi_ready) - return EC_ERROR_BUSY; - - /* TODO(b:117917141): Remove this check completely. */ - if (in_interrupt_context()) { - CPRINTS("Err: invoke %s() in ISR CTX", __func__); - return EC_ERROR_BUSY; - } - - if (len > sizeof(scp_send_obj->buffer)) - return EC_ERROR_INVAL; - - ipi_disable_irq(SCP_IRQ_IPC0); - mutex_lock(&ipi_lock); - - /* Check if there is already an IPI pending in AP. */ - if (is_ipi_busy()) { - /* - * If the following conditions meet, - * 1) There is an IPI pending in AP. - * 2) The incoming IPI is a wakeup IPI. - * then it assumes that AP is in suspend state. - * Send a AP wakeup request to SPM. - * - * The incoming IPI will be checked if it's a wakeup source. - */ - try_to_wakeup_ap(id); - - mutex_unlock(&ipi_lock); - ipi_enable_irq(SCP_IRQ_IPC0); - CPRINTS("Err: IPI Busy, %d", id); - - return EC_ERROR_BUSY; - } - - - scp_send_obj->id = id; - scp_send_obj->len = len; - memcpy(scp_send_obj->buffer, buf, len); - - /* Send IPI to AP: interrutp AP to receive IPI messages. */ - try_to_wakeup_ap(id); - SCP_HOST_INT = IPC_SCP2HOST_BIT; - - while (wait && is_ipi_busy()) - ; - - mutex_unlock(&ipi_lock); - ipi_enable_irq(SCP_IRQ_IPC0); - - return EC_SUCCESS; -} - -static void ipi_handler(void) -{ - if (scp_recv_obj->id >= IPI_COUNT) { - CPRINTS("#ERR IPI %d", scp_recv_obj->id); - return; - } - - /* - * Only print IPI that is not host command channel, which will - * be printed by host command driver. - */ - if (scp_recv_obj->id != IPI_HOST_COMMAND) - CPRINTS("IPI %d", scp_recv_obj->id); - - /* - * Pass the buffer to handler. Each handler should be in charge of - * the buffer copying/reading before returning from handler. - */ - ipi_handler_table[scp_recv_obj->id]( - scp_recv_obj->id, scp_recv_obj->buffer, scp_recv_obj->len); -} - -void ipi_inform_ap(void) -{ - struct scp_run_t scp_run; - int ret; -#ifdef CONFIG_RPMSG_NAME_SERVICE - struct rpmsg_ns_msg ns_msg; -#endif - - scp_run.signaled = 1; - strncpy(scp_run.fw_ver, system_get_version(EC_IMAGE_RW), - SCP_FW_VERSION_LEN); - scp_run.dec_capability = VCODEC_CAPABILITY_4K_DISABLED; - scp_run.enc_capability = 0; - - ret = ipi_send(IPI_SCP_INIT, (void *)&scp_run, sizeof(scp_run), 1); - - if (ret) - ccprintf("Failed to send initialization IPC messages.\n"); - -#ifdef CONFIG_RPMSG_NAME_SERVICE - ns_msg.id = IPI_HOST_COMMAND; - strncpy(ns_msg.name, "cros-ec-rpmsg", RPMSG_NAME_SIZE); - ret = ipi_send(IPI_NS_SERVICE, &ns_msg, sizeof(ns_msg), 1); - if (ret) - ccprintf("Failed to announce host command channel.\n"); -#endif -} - -#ifdef HAS_TASK_HOSTCMD -#if defined(CONFIG_MKBP_USE_CUSTOM) -int mkbp_set_host_active_via_custom(int active, uint32_t *timestamp) -{ - static const uint8_t hc_evt_obj = HOSTCMD_TYPE_HOSTEVENT; - - /* This should be moved into ipi_send for more accuracy */ - if (timestamp) - *timestamp = __hw_clock_source_read(); - - if (active) - return ipi_send(IPI_HOST_COMMAND, &hc_evt_obj, - sizeof(hc_evt_obj), 1); - return EC_SUCCESS; -} -#endif - -static void ipi_send_response_packet(struct host_packet *pkt) -{ - int ret; - - ret = ipi_send(IPI_HOST_COMMAND, &hc_cmd_obj, - pkt->response_size + - offsetof(struct hostcmd_data, response), - 1); - if (ret) - CPRINTS("#ERR IPI HOSTCMD %d", ret); -} - -static void ipi_hostcmd_handler(int32_t id, void *buf, uint32_t len) -{ - uint8_t *in_msg = buf; - struct ec_host_request *r = (struct ec_host_request *)in_msg; - int i; - - if (in_msg[0] != EC_HOST_REQUEST_VERSION) { - CPRINTS("ERROR: Protocol V2 is not supported!"); - CPRINTF("in_msg=["); - for (i = 0; i < len; i++) - CPRINTF("%02x ", in_msg[i]); - CPRINTF("]\n"); - return; - } - - /* Protocol version 3 */ - - ipi_packet.send_response = ipi_send_response_packet; - - /* - * Just assign the buffer to request, host_packet_receive - * handles the buffer copy. - */ - ipi_packet.request = (void *)r; - ipi_packet.request_temp = NULL; - ipi_packet.request_max = IPI_MAX_REQUEST_SIZE; - ipi_packet.request_size = host_request_expected_size(r); - - ipi_packet.response = hc_cmd_obj.response; - /* Reserve space for the preamble and trailing byte */ - ipi_packet.response_max = IPI_MAX_RESPONSE_SIZE; - ipi_packet.response_size = 0; - - ipi_packet.driver_result = EC_RES_SUCCESS; - - host_packet_receive(&ipi_packet); -} -DECLARE_IPI(IPI_HOST_COMMAND, ipi_hostcmd_handler, 0); - -/* - * Get protocol information - */ -static enum ec_status ipi_get_protocol_info(struct host_cmd_handler_args *args) -{ - struct ec_response_get_protocol_info *r = args->response; - - memset(r, 0, sizeof(*r)); - r->protocol_versions |= BIT(3); - r->max_request_packet_size = IPI_MAX_REQUEST_SIZE; - r->max_response_packet_size = IPI_MAX_RESPONSE_SIZE; - - args->response_size = sizeof(*r); - - return EC_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, ipi_get_protocol_info, - EC_VER_MASK(0)); -#endif - -static void ipi_enable_ipc0_deferred(void) -{ - /* Clear IPC0 IRQs. */ - SCP_GIPC_IN = SCP_GPIC_IN_CLEAR_ALL; - - /* All tasks are up, we can safely enable IPC0 IRQ now. */ - SCP_INTC_IRQ_ENABLE |= IPC0_IRQ_EN; - ipi_enable_irq(SCP_IRQ_IPC0); - - ipi_ready = 1; - - /* Inform AP that SCP is inited. */ - ipi_inform_ap(); - - CPRINTS("ipi init"); -} -DECLARE_DEFERRED(ipi_enable_ipc0_deferred); - -/* Initialize IPI. */ -static void ipi_init(void) -{ - /* Clear send share buffer. */ - memset(scp_send_obj, 0, sizeof(struct ipc_shared_obj)); - - /* Enable IRQ after all tasks are up. */ - hook_call_deferred(&ipi_enable_ipc0_deferred_data, 0); -} -DECLARE_HOOK(HOOK_INIT, ipi_init, HOOK_PRIO_DEFAULT); - -void ipc_handler(void) -{ - /* TODO(b/117917141): We only support IPC_ID(0) for now. */ - if (SCP_GIPC_IN & SCP_GIPC_IN_CLEAR_IPCN(0)) { - ipi_handler(); - SCP_GIPC_IN &= SCP_GIPC_IN_CLEAR_IPCN(0); - } - - SCP_GIPC_IN &= (SCP_GPIC_IN_CLEAR_ALL & ~SCP_GIPC_IN_CLEAR_IPCN(0)); -} -DECLARE_IRQ(SCP_IRQ_IPC0, ipc_handler, 4); diff --git a/chip/mt_scp/ipi_chip.h b/chip/mt_scp/ipi_chip.h deleted file mode 100644 index 867a84c9f8..0000000000 --- a/chip/mt_scp/ipi_chip.h +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_IPI_CHIP_H -#define __CROS_EC_IPI_CHIP_H - -#include "chip/mt_scp/registers.h" -#include "common.h" - -#define IPC_MAX 1 -#define IPC_ID(n) (n) - -/* - * Length of EC version string is at most 32 byte (NULL included), which - * also aligns SCP fw_version length. - */ -#define SCP_FW_VERSION_LEN 32 - -/* - * Video decoder supported capability: - * BIT(4): 0 enable 4K - * 1 disable 4K - */ -#define VCODEC_CAPABILITY_4K_DISABLED BIT(4) - -#ifndef IPI_SCP_INIT -#error If CONFIG_IPI is enabled, IPI_SCP_INIT must be defined. -#endif - -/* - * Share buffer layout for IPI_SCP_INIT response. This structure should sync - * across kernel and EC. - */ -struct scp_run_t { - uint32_t signaled; - int8_t fw_ver[SCP_FW_VERSION_LEN]; - uint32_t dec_capability; - uint32_t enc_capability; -}; - -/* - * The layout of the IPC0 AP/SCP shared buffer. - * This should sync across kernel and EC. - */ -struct ipc_shared_obj { - /* IPI ID */ - int32_t id; - /* Length of the contents in buffer. */ - uint32_t len; - /* Shared buffer contents. */ - uint8_t buffer[CONFIG_IPC_SHARED_OBJ_BUF_SIZE]; -}; - -/* Send a IPI contents to AP. This shouldn't be used in ISR context. */ -int ipi_send(int32_t id, const void *buf, uint32_t len, int wait); - -/* Size of the rpmsg device name, should sync across kernel and EC. */ -#define RPMSG_NAME_SIZE 32 - -/* - * The layout of name service message. - * This should sync across kernel and EC. - */ -struct rpmsg_ns_msg { - /* Name of the corresponding rpmsg_driver. */ - char name[RPMSG_NAME_SIZE]; - /* IPC ID */ - uint32_t id; -}; - -/* - * IPC Handler. - */ -void ipc_handler(void); - -/* - * An IPC IRQ could be shared across many IPI handlers. - * Those handlers would usually operate on disabling or enabling the IPC IRQ. - * This may disorder the actual timing to on/off the IRQ when there are many - * tasks try to operate on it. As a result, any access to the SCP_IRQ_* - * should go through ipi_{en,dis}able_irq(), which support a counter to - * enable/disable the IRQ at correct timeing. - */ -/* Disable IPI IRQ. */ -void ipi_disable_irq(int irq); -/* Enable IPI IRQ. */ -void ipi_enable_irq(int irq); - -/* IPI tables */ -extern void (*ipi_handler_table[])(int32_t, void *, uint32_t); -extern int *ipi_wakeup_table[]; - -/* Helper macros to build the IPI handler and wakeup functions. */ -#define IPI_HANDLER(id) CONCAT3(ipi_, id, _handler) -#define IPI_WAKEUP(id) CONCAT3(ipi_, id, _wakeup) - -/* - * Macro to declare an IPI handler. - * _id: The ID of the IPI - * handler: The IPI handler function - * is_wakeup_src: Declare IPI ID as a wake-up source or not - */ -#define DECLARE_IPI(_id, handler, is_wakeup_src) \ - struct ipi_num_check##_id { \ - int tmp1[_id < IPI_COUNT ? 1 : -1]; \ - int tmp2[is_wakeup_src == 0 || is_wakeup_src == 1 ? 1 : -1]; \ - }; \ - void __keep IPI_HANDLER(_id)(int32_t id, void *buf, uint32_t len) \ - { \ - handler(id, buf, len); \ - } \ - const int __keep IPI_WAKEUP(_id) = is_wakeup_src - -#endif /* __CROS_EC_IPI_CHIP_H */ diff --git a/chip/mt_scp/ipi_table.c b/chip/mt_scp/ipi_table.c deleted file mode 100644 index 8569ab24a7..0000000000 --- a/chip/mt_scp/ipi_table.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * IPI handlers declaration - */ - -#include "common.h" -#include "ipi_chip.h" - -typedef void (*ipi_handler_t)(int32_t id, void *data, uint32_t len); - -#ifndef PASS -#define PASS 1 -#endif - -#define ipi_arguments int32_t id, void *data, uint32_t len - -#if PASS == 1 -void ipi_handler_undefined(ipi_arguments) { } - -const int ipi_wakeup_undefined; - -#define table(type, name, x) x - -#define ipi_x_func(suffix, args, number) \ - extern void __attribute__( \ - (used, weak, alias(STRINGIFY(ipi_##suffix##_undefined)))) \ - ipi_##number##_##suffix(args); - -#define ipi_x_var(suffix, number) \ - extern int __attribute__( \ - (weak, alias(STRINGIFY(ipi_##suffix##_undefined)))) \ - ipi_##number##_##suffix; - -#endif /* PASS == 1 */ - -#if PASS == 2 - -#undef table -#undef ipi_x_func -#undef ipi_x_var - -#define table(type, name, x) \ - type name[] __aligned(4) \ - __attribute__((section(".rodata.ipi, \"a\" @"))) = {x} - -#define ipi_x_var(suffix, number) \ - [number < IPI_COUNT ? number : -1] = &ipi_##number##_##suffix, - -#define ipi_x_func(suffix, args, number) ipi_x_var(suffix, number) - -#endif /* PASS == 2 */ - -/* - * Include generated IPI table (by util/gen_ipi_table). The contents originate - * from IPI_COUNT definition in board.h - */ -#include "ipi_table_gen.inc" - -#if PASS == 1 -#undef PASS -#define PASS 2 -#include "ipi_table.c" -BUILD_ASSERT(ARRAY_SIZE(ipi_handler_table) == IPI_COUNT); -BUILD_ASSERT(ARRAY_SIZE(ipi_wakeup_table) == IPI_COUNT); -#endif diff --git a/chip/mt_scp/memmap.c b/chip/mt_scp/memmap.c deleted file mode 100644 index 6d8f2b0c87..0000000000 --- a/chip/mt_scp/memmap.c +++ /dev/null @@ -1,322 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * SCP memory map - */ - -#include "common.h" -#include "compile_time_macros.h" -#include "console.h" -#include "hooks.h" -#include "memmap.h" -#include "registers.h" -#include "util.h" - -/* - * Map SCP address (bits 31~28) to AP address - * - * SCP addr : AP addr - * 0x20000000 0x40000000 - * 0x30000000 0x50000000 - * 0x60000000 0x60000000 - * 0x70000000 0x70000000 - * 0x80000000 0x80000000 - * 0x90000000 0x00000000 - * 0xA0000000 0x10000000 - * 0xB0000000 0x20000000 - * 0xC0000000 0x30000000 - * 0xD0000000 0x10000000 - * 0xE0000000 0xA0000000 - * 0xF0000000 0x90000000 - */ - -#define MAP_INVALID 0xff - -static const uint8_t addr_map[16] = { - MAP_INVALID, /* 0x0: SRAM */ - MAP_INVALID, /* 0x1: Cached access (see below) */ - 0x4, 0x5, /* 0x2-0x3 */ - MAP_INVALID, MAP_INVALID, /* 0x4-0x5 (unmapped: registers) */ - 0x6, 0x7, 0x8, /* 0x6-0x8 */ - 0x0, 0x1, 0x2, 0x3, /* 0x9-0xc */ - 0x1, 0xa, 0x9 /* 0xd-0xf */ -}; - -/* - * AP addr : SCP cache addr - * 0x50000000 0x10000000 - */ -#define CACHE_TRANS_AP_ADDR 0x50000000 -#define CACHE_TRANS_SCP_CACHE_ADDR 0x10000000 -/* FIXME: This should be configurable */ -#define CACHE_TRANS_AP_SIZE 0x00400000 - -#ifdef CONFIG_DRAM_BASE -BUILD_ASSERT(CONFIG_DRAM_BASE_LOAD == CACHE_TRANS_AP_ADDR); -BUILD_ASSERT(CONFIG_DRAM_BASE == CACHE_TRANS_SCP_CACHE_ADDR); -#endif - -static void cpu_invalidate_icache(void) -{ - SCP_CACHE_OP(CACHE_ICACHE) &= ~SCP_CACHE_OP_OP_MASK; - SCP_CACHE_OP(CACHE_ICACHE) |= - OP_INVALIDATE_ALL_LINES | SCP_CACHE_OP_EN; - asm volatile("dsb; isb"); -} - -void cpu_invalidate_dcache(void) -{ - SCP_CACHE_OP(CACHE_DCACHE) &= ~SCP_CACHE_OP_OP_MASK; - SCP_CACHE_OP(CACHE_DCACHE) |= - OP_INVALIDATE_ALL_LINES | SCP_CACHE_OP_EN; - /* Read is necessary to confirm the invalidation finish. */ - REG32(CACHE_TRANS_SCP_CACHE_ADDR); - asm volatile("dsb;"); -} - -void cpu_invalidate_dcache_range(uintptr_t base, unsigned int length) -{ - size_t pos; - uintptr_t addr; - - for (pos = 0; pos < length; pos += SCP_CACHE_LINE_SIZE) { - addr = base + pos; - SCP_CACHE_OP(CACHE_DCACHE) = addr & SCP_CACHE_OP_TADDR_MASK; - SCP_CACHE_OP(CACHE_DCACHE) |= - OP_INVALIDATE_ONE_LINE_BY_ADDRESS | SCP_CACHE_OP_EN; - /* Read necessary to confirm the invalidation finish. */ - REG32(addr); - } - asm volatile("dsb;"); -} - -void cpu_clean_invalidate_dcache(void) -{ - SCP_CACHE_OP(CACHE_DCACHE) &= ~SCP_CACHE_OP_OP_MASK; - SCP_CACHE_OP(CACHE_DCACHE) |= - OP_CACHE_FLUSH_ALL_LINES | SCP_CACHE_OP_EN; - SCP_CACHE_OP(CACHE_DCACHE) &= ~SCP_CACHE_OP_OP_MASK; - SCP_CACHE_OP(CACHE_DCACHE) |= - OP_INVALIDATE_ALL_LINES | SCP_CACHE_OP_EN; - /* Read necessary to confirm the invalidation finish. */ - REG32(CACHE_TRANS_SCP_CACHE_ADDR); - asm volatile("dsb;"); -} - -void cpu_clean_invalidate_dcache_range(uintptr_t base, unsigned int length) -{ - size_t pos; - uintptr_t addr; - - for (pos = 0; pos < length; pos += SCP_CACHE_LINE_SIZE) { - addr = base + pos; - SCP_CACHE_OP(CACHE_DCACHE) = addr & SCP_CACHE_OP_TADDR_MASK; - SCP_CACHE_OP(CACHE_DCACHE) |= - OP_CACHE_FLUSH_ONE_LINE_BY_ADDRESS | SCP_CACHE_OP_EN; - SCP_CACHE_OP(CACHE_DCACHE) = addr & SCP_CACHE_OP_TADDR_MASK; - SCP_CACHE_OP(CACHE_DCACHE) |= - OP_INVALIDATE_ONE_LINE_BY_ADDRESS | SCP_CACHE_OP_EN; - /* Read necessary to confirm the invalidation finish. */ - REG32(addr); - } - asm volatile("dsb;"); -} - -static void scp_cache_init(void) -{ - int c; - const int region = 0; - - /* First make sure all caches are disabled, and reset stats. */ - for (c = 0; c < CACHE_COUNT; c++) { - /* - * Changing cache-size config may change the SRAM logical - * address in the mean time. This may break the loaded - * memory layout, and thus break the system. Cache-size - * should only be be configured in kernel driver before - * laoding the firmware. b/137920815#comment18 - */ - SCP_CACHE_CON(c) &= (SCP_CACHE_CON_CACHESIZE_MASK | - SCP_CACHE_CON_WAYEN); - SCP_CACHE_REGION_EN(c) = 0; - SCP_CACHE_ENTRY(c, region) = 0; - SCP_CACHE_END_ENTRY(c, region) = 0; - - /* Reset statistics. */ - SCP_CACHE_HCNT0U(c) = 0; - SCP_CACHE_HCNT0L(c) = 0; - SCP_CACHE_CCNT0U(c) = 0; - SCP_CACHE_CCNT0L(c) = 0; - } - - /* No "normal" remap. */ - SCP_L1_REMAP_CFG0 = 0; - SCP_L1_REMAP_CFG1 = 0; - SCP_L1_REMAP_CFG2 = 0; - SCP_L1_REMAP_CFG3 = 0; - /* - * Setup OTHER1: Remap register for addr msb 31 to 28 equal to 0x1 and - * not overlap with L1C_EXT_ADDR0 to L1C_EXT_ADDR7. - */ - SCP_L1_REMAP_OTHER = - (CACHE_TRANS_AP_ADDR >> SCP_L1_EXT_ADDR_OTHER_SHIFT) << 8; - - /* Disable sleep protect */ - SCP_SLP_PROTECT_CFG = SCP_SLP_PROTECT_CFG & - ~(P_CACHE_SLP_PROT_EN | D_CACHE_SLP_PROT_EN); - - /* Enable region 0 for both I-cache and D-cache. */ - for (c = 0; c < CACHE_COUNT; c++) { - SCP_CACHE_ENTRY(c, region) = CACHE_TRANS_SCP_CACHE_ADDR; - SCP_CACHE_END_ENTRY(c, region) = - CACHE_TRANS_SCP_CACHE_ADDR + CACHE_TRANS_AP_SIZE; - SCP_CACHE_ENTRY(c, region) |= SCP_CACHE_ENTRY_C; - - SCP_CACHE_REGION_EN(c) |= 1 << region; - - /* - * Enable cache. Note that cache size setting should have been - * done in kernel driver. b/137920815#comment18 - */ - SCP_CACHE_CON(c) |= SCP_CACHE_CON_MCEN | SCP_CACHE_CON_CNTEN0; - } - - cpu_invalidate_icache(); - cpu_invalidate_dcache(); -} - -static int command_cacheinfo(int argc, char **argv) -{ - const char cache_name[] = {'I', 'D'}; - int c; - - for (c = 0; c < 2; c++) { - uint64_t hit = ((uint64_t)SCP_CACHE_HCNT0U(c) << 32) | - SCP_CACHE_HCNT0L(c); - uint64_t access = ((uint64_t)SCP_CACHE_CCNT0U(c) << 32) | - SCP_CACHE_CCNT0L(c); - - ccprintf("%ccache hit count: %llu\n", cache_name[c], hit); - ccprintf("%ccache access count: %llu\n", cache_name[c], access); - } - - return EC_SUCCESS; -} -DECLARE_SAFE_CONSOLE_COMMAND(cacheinfo, command_cacheinfo, - NULL, - "Dump cache info"); - -void scp_memmap_init(void) -{ - /* - * Default config, LARGE DRAM not active: - * REG32(0xA0001F00) & 0x2000 != 0 - */ - - /* - * SCP_REMAP_CFG1 - * EXT_ADDR3[29:24] remap register for addr msb 31~28 equal to 0x7 - * EXT_ADDR2[21:16] remap register for addr msb 31~28 equal to 0x6 - * EXT_ADDR1[13:8] remap register for addr msb 31~28 equal to 0x3 - * EXT_ADDR0[5:0] remap register for addr msb 31~28 equal to 0x2 - */ - SCP_REMAP_CFG1 = - (uint32_t)addr_map[0x7] << 24 | - (uint32_t)addr_map[0x6] << 16 | - (uint32_t)addr_map[0x3] << 8 | - (uint32_t)addr_map[0x2]; - - /* - * SCP_REMAP_CFG2 - * EXT_ADDR7[29:24] remap register for addr msb 31~28 equal to 0xb - * EXT_ADDR6[21:16] remap register for addr msb 31~28 equal to 0xa - * EXT_ADDR5[13:8] remap register for addr msb 31~28 equal to 0x9 - * EXT_ADDR4[5:0] remap register for addr msb 31~28 equal to 0x8 - */ - SCP_REMAP_CFG2 = - (uint32_t)addr_map[0xb] << 24 | - (uint32_t)addr_map[0xa] << 16 | - (uint32_t)addr_map[0x9] << 8 | - (uint32_t)addr_map[0x8]; - /* - * SCP_REMAP_CFG3 - * AUD_ADDR[31:28] remap register for addr msb 31~28 equal to 0xd - * EXT_ADDR10[21:16]remap register for addr msb 31~28 equal to 0xf - * EXT_ADDR9[13:8] remap register for addr msb 31~28 equal to 0xe - * EXT_ADDR8[5:0] remap register for addr msb 31~28 equal to 0xc - */ - SCP_REMAP_CFG3 = - (uint32_t)addr_map[0xd] << 28 | - (uint32_t)addr_map[0xf] << 16 | - (uint32_t)addr_map[0xe] << 8 | - (uint32_t)addr_map[0xc]; - - /* Initialize cache remapping. */ - scp_cache_init(); -} - -int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr) -{ - int i; - uint8_t msb = ap_addr >> SCP_REMAP_ADDR_SHIFT; - - for (i = 0; i < ARRAY_SIZE(addr_map); i++) { - if (addr_map[i] != msb) - continue; - - *scp_addr = (ap_addr & SCP_REMAP_ADDR_LSB_MASK) | - (i << SCP_REMAP_ADDR_SHIFT); - return EC_SUCCESS; - } - - return EC_ERROR_INVAL; -} - -int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr) -{ - int i = scp_addr >> SCP_REMAP_ADDR_SHIFT; - - if (addr_map[i] == MAP_INVALID) - return EC_ERROR_INVAL; - - *ap_addr = (scp_addr & SCP_REMAP_ADDR_LSB_MASK) | - (addr_map[i] << SCP_REMAP_ADDR_SHIFT); - return EC_SUCCESS; -} - -#ifdef CONFIG_DRAM_BASE -BUILD_ASSERT(CONFIG_DRAM_BASE_LOAD == CACHE_TRANS_AP_ADDR); -BUILD_ASSERT(CONFIG_DRAM_BASE == CACHE_TRANS_SCP_CACHE_ADDR); -#endif - -int memmap_ap_to_scp_cache(uintptr_t ap_addr, uintptr_t *scp_addr) -{ - uintptr_t lsb; - - if ((ap_addr & SCP_L1_EXT_ADDR_OTHER_MSB_MASK) != CACHE_TRANS_AP_ADDR) - return EC_ERROR_INVAL; - - lsb = ap_addr & SCP_L1_EXT_ADDR_OTHER_LSB_MASK; - if (lsb > CACHE_TRANS_AP_SIZE) - return EC_ERROR_INVAL; - - *scp_addr = CACHE_TRANS_SCP_CACHE_ADDR | lsb; - return EC_SUCCESS; -} - -int memmap_scp_cache_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr) -{ - uintptr_t lsb; - - if ((scp_addr & SCP_L1_EXT_ADDR_OTHER_MSB_MASK) != - CACHE_TRANS_SCP_CACHE_ADDR) - return EC_ERROR_INVAL; - - lsb = scp_addr & SCP_L1_EXT_ADDR_OTHER_LSB_MASK; - if (lsb >= CACHE_TRANS_AP_SIZE) - return EC_ERROR_INVAL; - - *ap_addr = CACHE_TRANS_AP_ADDR | lsb; - return EC_SUCCESS; -} diff --git a/chip/mt_scp/memmap.h b/chip/mt_scp/memmap.h deleted file mode 100644 index fbecb5e8cf..0000000000 --- a/chip/mt_scp/memmap.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * SCP memory map - */ - -#ifndef __CROS_EC_MEMMAP_H -#define __CROS_EC_MEMMAP_H - -void scp_memmap_init(void); - -/** - * Translate AP addr to SCP addr. - * - * @param ap_addr AP address to translate - * @param scp_addr Tranlated AP address - * @return EC_SUCCESS or EC_ERROR_INVAL - */ -int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr); - -/** - * Translate SCP addr to AP addr. - * - * @param scp_addr SCP address to tranlate - * @param ap_addr Translated SCP address - * @return EC_SUCCESS or EC_ERROR_INVAL - */ -int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr); - -/** - * Translate AP addr to SCP cache addr. - * - * @param ap_addr AP address to translate - * @param scp_addr Tranlated AP cache address - * @return EC_SUCCESS or EC_ERROR_INVAL - */ -int memmap_ap_to_scp_cache(uintptr_t ap_addr, uintptr_t *scp_addr); - -/** - * Translate SCP addr to AP addr. - * - * @param scp_addr SCP cache address to tranlate - * @param ap_addr Translated SCP cache address - * @return EC_SUCCESS or EC_ERROR_INVAL - */ -int memmap_scp_cache_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr); - -#endif /* #ifndef __CROS_EC_MEMMAP_H */ diff --git a/chip/mt_scp/audio_codec_wov.c b/chip/mt_scp/mt818x/audio_codec_wov.c similarity index 95% rename from chip/mt_scp/audio_codec_wov.c rename to chip/mt_scp/mt818x/audio_codec_wov.c index 0a4684f909..466494b53f 100644 --- a/chip/mt_scp/audio_codec_wov.c +++ b/chip/mt_scp/mt818x/audio_codec_wov.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -79,7 +79,7 @@ int32_t audio_codec_wov_read(void *buf, uint32_t count) while (count-- && wov_fifo_level()) { if (IS_ENABLED(CONFIG_AUDIO_CODEC_DMIC_SOFTWARE_GAIN)) *out++ = audio_codec_s16_scale_and_clip( - SCP_VIF_FIFO_DATA, gain); + SCP_VIF_FIFO_DATA, gain); else *out++ = SCP_VIF_FIFO_DATA; } diff --git a/chip/mt_scp/mt818x/build.mk b/chip/mt_scp/mt818x/build.mk new file mode 100644 index 0000000000..c44b2f0ebe --- /dev/null +++ b/chip/mt_scp/mt818x/build.mk @@ -0,0 +1,36 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +CORE:=cortex-m +CFLAGS_CPU+=-mcpu=cortex-m4 + +# Required chip modules +chip-y+=mt818x/clock_$(CHIP_VARIANT).o +chip-y+=mt818x/gpio.o +chip-y+=mt818x/memmap.o +chip-y+=mt818x/system.o +chip-y+=mt818x/uart.o +chip-y+=mt818x/video.o + +# Optional chip modules +chip-$(CONFIG_AUDIO_CODEC_WOV)+=mt818x/audio_codec_wov.o +chip-$(CONFIG_COMMON_TIMER)+=mt818x/hrtimer.o +chip-$(CONFIG_I2C)+=mt818x/i2c.o +chip-$(CONFIG_IPI)+=mt818x/ipi.o mt818x/ipi_table.o +chip-$(CONFIG_SPI)+=mt818x/spi.o +chip-$(CONFIG_WATCHDOG)+=mt818x/watchdog.o + +ifeq ($(CONFIG_IPI),y) +$(out)/RO/chip/$(CHIP)/mt818x/ipi_table.o: $(out)/ipi_table_gen.inc +$(out)/RW/chip/$(CHIP)/mt818x/ipi_table.o: $(out)/ipi_table_gen.inc +endif + +ifeq ($(CONFIG_AUDIO_CODEC_WOV),y) +HOTWORD_PRIVATE_LIB:=private/libkukui_scp_google_hotword_dsp_api.a +ifneq ($(wildcard $(HOTWORD_PRIVATE_LIB)),) +LDFLAGS_EXTRA+=$(HOTWORD_PRIVATE_LIB) +HAVE_PRIVATE_AUDIO_CODEC_WOV_LIBS:=y +endif +endif diff --git a/chip/mt_scp/mt818x/clock_chip.h b/chip/mt_scp/mt818x/clock_chip.h new file mode 100644 index 0000000000..6568999176 --- /dev/null +++ b/chip/mt_scp/mt818x/clock_chip.h @@ -0,0 +1,33 @@ +/* Copyright 2019 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Clocks, PLL and power settings */ + +#ifndef __CROS_EC_CLOCK_CHIP_H +#define __CROS_EC_CLOCK_CHIP_H + +#include "common.h" +#include "registers.h" + +/* Default ULPOSC clock speed in MHz */ +#ifndef ULPOSC1_CLOCK_MHZ +#define ULPOSC1_CLOCK_MHZ 240 +#endif +#ifndef ULPOSC2_CLOCK_MHZ +#define ULPOSC2_CLOCK_MHZ 330 +#endif +void scp_enable_clock(void); + +enum scp_clock_source { + SCP_CLK_26M = CLK_SEL_SYS_26M, + SCP_CLK_32K = CLK_SEL_32K, + SCP_CLK_ULPOSC2 = CLK_SEL_ULPOSC_2, + SCP_CLK_ULPOSC1 = CLK_SEL_ULPOSC_1, +}; + +/* Switches to use 'src' clock */ +void scp_use_clock(enum scp_clock_source src); + +#endif /* __CROS_EC_CLOCK_CHIP_H */ diff --git a/chip/mt_scp/mt818x/clock_mt8183.c b/chip/mt_scp/mt818x/clock_mt8183.c new file mode 100644 index 0000000000..5c99d7b393 --- /dev/null +++ b/chip/mt_scp/mt818x/clock_mt8183.c @@ -0,0 +1,376 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Clocks, PLL and power settings */ + +#include "clock.h" +#include "clock_chip.h" +#include "common.h" +#include "console.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args) + +#define ULPOSC_DIV_MAX (1 << OSC_DIV_BITS) +#define ULPOSC_CALI_MAX (1 << OSC_CALI_BITS) + +void clock_init(void) +{ + /* Set VREQ to HW mode */ + SCP_CPU_VREQ = CPU_VREQ_HW_MODE; + SCP_SECURE_CTRL &= ~ENABLE_SPM_MASK_VREQ; + + /* Set DDREN auto mode */ + SCP_SYS_CTRL |= AUTO_DDREN; + + /* Initialize 26MHz system clock counter reset value to 1. */ + SCP_CLK_SYS_VAL = (SCP_CLK_SYS_VAL & ~CLK_SYS_VAL_MASK) | + CLK_SYS_VAL(1); + /* Initialize high frequency ULPOSC counter reset value to 1. */ + SCP_CLK_HIGH_VAL = (SCP_CLK_HIGH_VAL & ~CLK_HIGH_VAL_MASK) | + CLK_HIGH_VAL(1); + /* Initialize sleep mode control VREQ counter. */ + SCP_CLK_SLEEP_CTRL = (SCP_CLK_SLEEP_CTRL & ~VREQ_COUNTER_MASK) | + VREQ_COUNTER_VAL(1); + + /* Set normal wake clock */ + SCP_WAKE_CKSW &= ~WAKE_CKSW_SEL_NORMAL_MASK; + + /* Enable fast wakeup support */ + SCP_CLK_SLEEP = 0; + SCP_CLK_ON_CTRL = (SCP_CLK_ON_CTRL & ~HIGH_FINAL_VAL_MASK) | + HIGH_FINAL_VAL_DEFAULT; + SCP_FAST_WAKE_CNT_END = + (SCP_FAST_WAKE_CNT_END & ~FAST_WAKE_CNT_END_MASK) | + FAST_WAKE_CNT_END_DEFAULT; + + /* Set slow wake clock */ + SCP_WAKE_CKSW = (SCP_WAKE_CKSW & ~WAKE_CKSW_SEL_SLOW_MASK) | + WAKE_CKSW_SEL_SLOW_DEFAULT; + + /* Select CLK_HIGH as wakeup clock */ + SCP_CLK_SLOW_SEL = (SCP_CLK_SLOW_SEL & + ~(CKSW_SEL_SLOW_MASK | CKSW_SEL_SLOW_DIV_MASK)) | + CKSW_SEL_SLOW_ULPOSC2_CLK; + + /* + * Set legacy wakeup + * - disable SPM sleep control + * - disable SCP sleep mode + */ + SCP_CLK_SLEEP_CTRL &= ~(EN_SLEEP_CTRL | SPM_SLEEP_MODE); + + task_enable_irq(SCP_IRQ_CLOCK); + task_enable_irq(SCP_IRQ_CLOCK2); +} + +static void scp_ulposc_config(int osc, uint32_t osc_div, uint32_t osc_cali) +{ + uint32_t val; + + /* Clear all bits */ + val = 0; + /* Enable CP */ + val |= OSC_CP_EN; + /* Set div */ + val |= osc_div << 17; + /* F-band = 0, I-band = 4 */ + val |= 4 << 6; + /* Set calibration */ + val |= osc_cali; + /* Set control register 1 */ + AP_ULPOSC_CON02(osc) = val; + /* Set control register 2, enable div2 */ + AP_ULPOSC_CON13(osc) |= OSC_DIV2_EN; +} + +static inline void busy_udelay(int usec) +{ + /* + * Delaying by busy-looping, for place that can't use udelay because of + * the clock not configured yet. The value 28 is chosen approximately + * from experiment. + */ + volatile int i = usec * 28; + + while (i--) + ; +} + +static unsigned int scp_measure_ulposc_freq(int osc) +{ + unsigned int result = 0; + int cnt; + + /* Before select meter clock input, bit[1:0] = b00 */ + AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_MODE_MASK) | DBG_MODE_SET_CLOCK; + + /* Select source, bit[21:16] = clk_src */ + AP_CLK_DBG_CFG = + (AP_CLK_DBG_CFG & ~DBG_BIST_SOURCE_MASK) | + (osc == 0 ? DBG_BIST_SOURCE_ULPOSC1 : DBG_BIST_SOURCE_ULPOSC2); + + /* Set meter divisor to 1, bit[31:24] = b00000000 */ + AP_CLK_MISC_CFG_0 = (AP_CLK_MISC_CFG_0 & ~MISC_METER_DIVISOR_MASK) | + MISC_METER_DIV_1; + + /* Enable frequency meter, without start */ + AP_SCP_CFG_0 |= CFG_FREQ_METER_ENABLE; + + /* Trigger frequency meter start */ + AP_SCP_CFG_0 |= CFG_FREQ_METER_RUN; + + /* + * Frequency meter counts cycles in 1 / (26 * 1024) second period. + * freq_in_hz = freq_counter * 26 * 1024 + * + * The hardware takes 38us to count cycles. Delay up to 100us, + * as busy_udelay may not be accurate when sysclk is not 26Mhz + * (e.g. when recalibrating/measuring after boot). + */ + for (cnt = 100; cnt; cnt--) { + busy_udelay(1); + if (!(AP_SCP_CFG_0 & CFG_FREQ_METER_RUN)) { + result = CFG_FREQ_COUNTER(AP_SCP_CFG_1); + break; + } + } + + /* Disable freq meter */ + AP_SCP_CFG_0 &= ~CFG_FREQ_METER_ENABLE; + return result; +} + +static inline int signum(int v) +{ + return (v > 0) - (v < 0); +} + +static inline int abs(int v) +{ + return (v >= 0) ? v : -v; +} + +static int scp_ulposc_config_measure(int osc, int div, int cali) +{ + int freq; + + scp_ulposc_config(osc, div, cali); + freq = scp_measure_ulposc_freq(osc); + CPRINTF("ULPOSC%d: %d %d %d (%dkHz)\n", osc + 1, div, cali, freq, + freq * 26 * 1000 / 1024); + + return freq; +} + +/** + * Calibrate ULPOSC to target frequency. + * + * @param osc 0:ULPOSC1, 1:ULPOSC2 + * @param target_mhz Target frequency to set + * @return Frequency counter output + * + */ +static int scp_calibrate_ulposc(int osc, int target_mhz) +{ + int target_freq = DIV_ROUND_NEAREST(target_mhz * 1024, 26); + struct ulposc { + int div; /* frequency divisor/multiplier */ + int cali; /* variable resistor calibrator */ + int freq; /* frequency counter measure result */ + } curr, prev = { 0 }; + enum { STAGE_DIV, STAGE_CALI } stage = STAGE_DIV; + int param, param_max; + + curr.div = ULPOSC_DIV_MAX / 2; + curr.cali = ULPOSC_CALI_MAX / 2; + + param = curr.div; + param_max = ULPOSC_DIV_MAX; + + /* + * In the loop below, linear search closest div value to get desired + * frequency counter value. Then adjust cali to get a better result. + * Note that this doesn't give optimal output frequency, but it's + * usually close enough. + * TODO(b:120176040): See if we can efficiently calibrate the clock with + * more precision by exploring more of the cali/div space. + * + * The frequency function follows. Note that f is positively correlated + * with both div and cali: + * f(div, cali) = k1 * (div + k2) / R(cali) * C + * Where: + * R(cali) = k3 / (1 + k4 * (cali - k4)) + */ + while (1) { + curr.freq = scp_ulposc_config_measure(osc, curr.div, curr.cali); + + if (!curr.freq) + return 0; + + /* + * If previous and current are on either side of the desired + * frequency, pick the closest one. + */ + if (prev.freq && signum(target_freq - curr.freq) != + signum(target_freq - prev.freq)) { + if (abs(target_freq - prev.freq) < + abs(target_freq - curr.freq)) + curr = prev; + + if (stage == STAGE_CALI) + break; + + /* Switch to optimizing cali */ + stage = STAGE_CALI; + param = curr.cali; + param_max = ULPOSC_CALI_MAX; + } + + prev = curr; + param += signum(target_freq - curr.freq); + + if (param < 0 || param >= param_max) + return 0; + + if (stage == STAGE_DIV) + curr.div = param; + else + curr.cali = param; + } + + /* + * It's possible we end up using prev, so reset the configuration and + * measure again. + */ + return scp_ulposc_config_measure(osc, curr.div, curr.cali); +} + +static void scp_clock_high_enable(int osc) +{ + /* Enable high speed clock */ + SCP_CLK_EN |= EN_CLK_HIGH; + + switch (osc) { + case 0: + /* After 25ms, enable ULPOSC */ + busy_udelay(25 * MSEC); + SCP_CLK_EN |= CG_CLK_HIGH; + break; + case 1: + /* Turn off ULPOSC2 high-core-disable switch */ + SCP_CLK_ON_CTRL &= ~HIGH_CORE_DIS_SUB; + /* After 25ms, turn on ULPOSC2 high core clock gate */ + busy_udelay(25 * MSEC); + SCP_CLK_HIGH_CORE |= CLK_HIGH_CORE_CG; + break; + default: + break; + } +} + +void scp_use_clock(enum scp_clock_source src) +{ + /* + * DIV2 divider takes precedence over clock selection to prevent + * over-clocking. + */ + if (src == SCP_CLK_ULPOSC1) + SCP_CLK_DIV_SEL = CLK_DIV2; + + SCP_CLK_SEL = src; + + if (src != SCP_CLK_ULPOSC1) + SCP_CLK_DIV_SEL = CLK_DIV1; +} + +void scp_enable_clock(void) +{ + /* Select default CPU clock */ + scp_use_clock(SCP_CLK_26M); + + /* VREQ */ + SCP_CPU_VREQ = 0x10001; + SCP_SECURE_CTRL &= ~ENABLE_SPM_MASK_VREQ; + + /* DDREN auto mode */ + SCP_SYS_CTRL |= AUTO_DDREN; + + /* Set settle time */ + SCP_CLK_SYS_VAL = 1; /* System clock */ + SCP_CLK_HIGH_VAL = 1; /* ULPOSC */ + SCP_CLK_SLEEP_CTRL = (SCP_CLK_SLEEP_CTRL & ~VREQ_COUNTER_MASK) | 2; + + /* Disable slow wake */ + SCP_CLK_SLEEP = SLOW_WAKE_DISABLE; + /* Disable SPM sleep control, disable sleep mode */ + SCP_CLK_SLEEP_CTRL &= ~(SPM_SLEEP_MODE | EN_SLEEP_CTRL); + + /* Turn off ULPOSC2 */ + SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB; + scp_ulposc_config(0, 12, 32); + scp_clock_high_enable(0); /* Turn on ULPOSC1 */ + scp_ulposc_config(1, 16, 32); + scp_clock_high_enable(1); /* Turn on ULPOSC2 */ + + /* Calibrate ULPOSC */ + scp_calibrate_ulposc(0, ULPOSC1_CLOCK_MHZ); + scp_calibrate_ulposc(1, ULPOSC2_CLOCK_MHZ); + + /* Select ULPOSC2 high speed CPU clock */ + scp_use_clock(SCP_CLK_ULPOSC2); + + /* Enable default clock gate */ + SCP_CLK_GATE |= CG_DMA_CH3 | CG_DMA_CH2 | CG_DMA_CH1 | CG_DMA_CH0 | + CG_I2C_M | CG_MAD_M | CG_AP2P_M; + + /* Select pwrap_ulposc */ + AP_CLK_CFG_5 = (AP_CLK_CFG_5 & ~PWRAP_ULPOSC_MASK) | OSC_D16; + + /* Enable pwrap_ulposc clock gate */ + AP_CLK_CFG_5_CLR = PWRAP_ULPOSC_CG; +} + +DECLARE_IRQ(SCP_IRQ_CLOCK, clock_control_irq, 3); +static void clock_control_irq(void) +{ + /* Read ack CLK_IRQ */ + (SCP_CLK_IRQ_ACK); + task_clear_pending_irq(SCP_IRQ_CLOCK); +} + +DECLARE_IRQ(SCP_IRQ_CLOCK2, clock_fast_wakeup_irq, 3); +static void clock_fast_wakeup_irq(void) +{ + /* Ack fast wakeup */ + SCP_SLEEP_IRQ2 = 1; + task_clear_pending_irq(SCP_IRQ_CLOCK2); +} + +/* Console command */ +static int command_ulposc(int argc, const char *argv[]) +{ + if (argc > 1 && !strncmp(argv[1], "cal", 3)) { + scp_calibrate_ulposc(0, ULPOSC1_CLOCK_MHZ); + scp_calibrate_ulposc(1, ULPOSC2_CLOCK_MHZ); + } + + /* SCP clock meter counts every (26MHz / 1024) tick */ + ccprintf("ULPOSC1 frequency: %u kHz\n", + scp_measure_ulposc_freq(0) * 26 * 1000 / 1024); + ccprintf("ULPOSC2 frequency: %u kHz\n", + scp_measure_ulposc_freq(1) * 26 * 1000 / 1024); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[calibrate]", + "Calibrate ULPOSC frequency"); + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mt_scp/mt818x/clock_mt8186.c b/chip/mt_scp/mt818x/clock_mt8186.c new file mode 100644 index 0000000000..a31ab6059c --- /dev/null +++ b/chip/mt_scp/mt818x/clock_mt8186.c @@ -0,0 +1,382 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Clocks, PLL and power settings */ + +#include "builtin/assert.h" +#include "clock.h" +#include "clock_chip.h" +#include "common.h" +#include "console.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args) + +#define ULPOSC_CAL_MIN_VALUE 3 +#define ULPOSC_CAL_MAX_VALUE 60 +#define ULPOSC_CAL_START_VALUE \ + ((ULPOSC_CAL_MIN_VALUE + ULPOSC_CAL_MAX_VALUE) / 2) + +static struct opp_ulposc_cfg { + uint32_t osc; + uint32_t div; + uint32_t iband; + uint32_t mod; + uint32_t cali; + uint32_t target_mhz; +} opp[] = { + { + .osc = 1, + .target_mhz = ULPOSC2_CLOCK_MHZ, + .div = 16, + .iband = 4, + .mod = 1, + .cali = ULPOSC_CAL_START_VALUE, + }, + { + .osc = 0, + .target_mhz = ULPOSC1_CLOCK_MHZ, + .div = 12, + .iband = 4, + .mod = 1, + .cali = ULPOSC_CAL_START_VALUE, + }, +}; + +static inline void clock_busy_udelay(int usec) +{ + /* + * Delaying by busy-looping, for place that can't use udelay because of + * the clock not configured yet. The value 28 is chosen approximately + * from experiment. + * + * `volatile' in order to avoid compiler to optimize the function out + * (otherwise, the function will be eliminated). + */ + volatile int i = usec * 28; + + while (--i) + ; +} + +static void clock_ulposc_config_default(struct opp_ulposc_cfg *opp) +{ + unsigned int val = 0; + + /* Enable CP */ + val |= OSC_CP_EN; + /* set div */ + val |= opp->div << OSC_DIV_SHIFT; + /* set I-band */ + val |= (opp->iband << OSC_IBAND_SHIFT); + /* set calibration */ + val |= opp->cali; + /* set control register */ + AP_ULPOSC_CON02(opp->osc) = val; + + /* OSC_DIV2_EN = 1 */ + AP_ULPOSC_CON13(opp->osc) |= OSC_DIV2_EN; + /* OSC_MOD = 00 */ + AP_ULPOSC_CON13(opp->osc) &= ~OSC_MOD_MASK; +} + +static void clock_ulposc_config_cali(struct opp_ulposc_cfg *opp, + uint32_t cali_val) +{ + uint32_t val; + + val = AP_ULPOSC_CON02(opp->osc); + val &= ~OSC_CALI_MASK; + val |= cali_val; + AP_ULPOSC_CON02(opp->osc) = val; + + clock_busy_udelay(50); +} + +static unsigned int clock_ulposc_measure_freq(int osc) +{ + unsigned int clk_dbg_cfg, clk_misc_cfg_0, clk26cali_0, clk26cali_1, + result = 0; + int cnt; + + /* backup */ + clk_dbg_cfg = AP_CLK_DBG_CFG; + clk_misc_cfg_0 = AP_CLK_MISC_CFG_0; + clk26cali_0 = AP_SCP_CFG_0; + clk26cali_1 = AP_SCP_CFG_1; + + /* Before select meter clock input, bit[1:0] = b00 */ + AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_MODE_MASK) | DBG_MODE_SET_CLOCK; + + /* Select source, bit[21:16] = clk_src */ + AP_CLK_DBG_CFG = + (AP_CLK_DBG_CFG & ~DBG_BIST_SOURCE_MASK) | + (osc == 0 ? DBG_BIST_SOURCE_ULPOSC1 : DBG_BIST_SOURCE_ULPOSC2); + + /* Set meter divisor to 1, bit[31:24] = b00000000 */ + AP_CLK_MISC_CFG_0 = (AP_CLK_MISC_CFG_0 & ~MISC_METER_DIVISOR_MASK) | + MISC_METER_DIV_1; + + /* Enable frequency meter, without start */ + AP_SCP_CFG_0 |= CFG_FREQ_METER_ENABLE; + + /* Trigger frequency meter start */ + AP_SCP_CFG_0 |= CFG_FREQ_METER_RUN; + /* + * Frequency meter counts cycles in 1 / (26 * 1024) second period. + * freq_in_hz = freq_counter * 26 * 1024 + * + * The hardware takes 38us to count cycles. Delay up to 100us, + * as clock_busy_udelay may not be accurate when sysclk is not 26Mhz + * (e.g. when recalibrating/measuring after boot). + */ + for (cnt = 100; cnt; cnt--) { + clock_busy_udelay(1); + if (!(AP_SCP_CFG_0 & CFG_FREQ_METER_RUN)) { + result = CFG_FREQ_COUNTER(AP_SCP_CFG_1); + break; + } + } + + /* Disable freq meter */ + AP_SCP_CFG_0 &= ~CFG_FREQ_METER_ENABLE; + + /* restore */ + AP_CLK_DBG_CFG = clk_dbg_cfg; + AP_CLK_MISC_CFG_0 = clk_misc_cfg_0; + AP_SCP_CFG_0 = clk26cali_0; + AP_SCP_CFG_1 = clk26cali_1; + + return result; +} + +#define CAL_MIS_RATE 40 +static int clock_ulposc_is_calibrated(struct opp_ulposc_cfg *opp) +{ + uint32_t curr, target; + + curr = clock_ulposc_measure_freq(opp->osc); + target = opp->target_mhz * 1024 / 26; + + /* check if calibrated value is in the range of target value +- 4% */ + if (curr > (target * (1000 - CAL_MIS_RATE) / 1000) && + curr < (target * (1000 + CAL_MIS_RATE) / 1000)) + return 1; + else + return 0; +} + +static uint32_t clock_ulposc_process_cali(struct opp_ulposc_cfg *opp) +{ + uint32_t current_val = 0; + uint32_t target_val = opp->target_mhz * 1024 / 26; + uint32_t middle, min = 0, max = OSC_CALI_MASK; + uint32_t diff_by_min, diff_by_max, cal_result; + + do { + middle = (min + max) / 2; + if (middle == min) + break; + + clock_ulposc_config_cali(opp, middle); + current_val = clock_ulposc_measure_freq(opp->osc); + + if (current_val > target_val) + max = middle; + else + min = middle; + } while (min <= max); + + clock_ulposc_config_cali(opp, min); + current_val = clock_ulposc_measure_freq(opp->osc); + if (current_val > target_val) + diff_by_min = current_val - target_val; + else + diff_by_min = target_val - current_val; + + clock_ulposc_config_cali(opp, max); + current_val = clock_ulposc_measure_freq(opp->osc); + if (current_val > target_val) + diff_by_max = current_val - target_val; + else + diff_by_max = target_val - current_val; + + if (diff_by_min < diff_by_max) + cal_result = min; + else + cal_result = max; + + clock_ulposc_config_cali(opp, cal_result); + if (!clock_ulposc_is_calibrated(opp)) + assert(0); + + return cal_result; +} + +static void clock_high_enable(int osc) +{ + /* Enable high speed clock */ + SCP_CLK_EN |= EN_CLK_HIGH; + + switch (osc) { + case 0: + /* After 25ms, enable ULPOSC */ + clock_busy_udelay(25 * MSEC); + SCP_CLK_EN |= CG_CLK_HIGH; + break; + case 1: + /* Turn off ULPOSC2 high-core-disable switch */ + SCP_CLK_ON_CTRL &= ~HIGH_CORE_DIS_SUB; + /* After 25ms, turn on ULPOSC2 high core clock gate */ + clock_busy_udelay(25 * MSEC); + SCP_CLK_HIGH_CORE |= CLK_HIGH_CORE_CG; + break; + default: + break; + } + clock_busy_udelay(25 * MSEC); +} + +static void clock_calibrate_ulposc(struct opp_ulposc_cfg *opp) +{ + /* + * TODO: Check ULPOSC1(osc=0) is already ? + * - calibrated + * - enabled in coreboot + * - used by pmic wrapper + */ + + clock_ulposc_config_default(opp); + clock_high_enable(opp->osc); + + /* Calibrate only if it is not accurate enough. */ + if (!clock_ulposc_is_calibrated(opp)) + opp->cali = clock_ulposc_process_cali(opp); + + CPRINTF("osc:%u, target=%uMHz, cal:%u\n", opp->osc, opp->target_mhz, + opp->cali); +} + +void scp_use_clock(enum scp_clock_source src) +{ + /* + * DIV2 divider takes precedence over clock selection to prevent + * over-clocking. + */ + if (src == SCP_CLK_ULPOSC1) + SCP_CLK_DIV_SEL = CLK_DIV2; + + SCP_CLK_SEL = src; + + if (src != SCP_CLK_ULPOSC1) + SCP_CLK_DIV_SEL = CLK_DIV1; +} + +void clock_init(void) +{ + /* Enable fast wakeup support */ + SCP_CLK_ON_CTRL = (SCP_CLK_ON_CTRL & ~HIGH_FINAL_VAL_MASK) | + HIGH_FINAL_VAL_DEFAULT; + SCP_FAST_WAKE_CNT_END = + (SCP_FAST_WAKE_CNT_END & ~FAST_WAKE_CNT_END_MASK) | + FAST_WAKE_CNT_END_DEFAULT; + + /* Set slow wake clock */ + SCP_WAKE_CKSW = (SCP_WAKE_CKSW & ~WAKE_CKSW_SEL_SLOW_MASK) | + WAKE_CKSW_SEL_SLOW_DEFAULT; + + /* Select CLK_HIGH as wakeup clock */ + SCP_CLK_SLOW_SEL = (SCP_CLK_SLOW_SEL & + (CKSW_SEL_SLOW_MASK | CKSW_SEL_SLOW_DIV_MASK)) | + CKSW_SEL_SLOW_ULPOSC2_CLK; +} + +void scp_enable_clock(void) +{ + int i; + + /* Select default CPU clock */ + scp_use_clock(SCP_CLK_26M); + + /* VREQ */ + SCP_CPU_VREQ = VREQ_DVFS_SEL; + SCP_SECURE_CTRL |= ENABLE_SPM_MASK_VREQ; + SCP_CLK_CTRL_GENERAL_CTRL &= ~VREQ_PMIC_WRAP_SEL; + + /* DDREN auto mode */ + SCP_SYS_CTRL |= AUTO_DDREN; + + /* Set settle time */ + SCP_CLK_SYS_VAL = (SCP_CLK_SYS_VAL & ~CLK_SYS_VAL_MASK) | + CLK_SYS_VAL(1); + SCP_CLK_HIGH_VAL = (SCP_CLK_HIGH_VAL & ~CLK_HIGH_VAL_MASK) | + CLK_HIGH_VAL(1); + SCP_CLK_SLEEP_CTRL = (SCP_CLK_SLEEP_CTRL & ~VREQ_COUNTER_MASK) | + VREQ_COUNTER_VAL(1); + + /* Disable slow wake */ + SCP_CLK_SLEEP = SLOW_WAKE_DISABLE; + /* Disable SPM sleep control, disable sleep mode */ + SCP_CLK_SLEEP_CTRL &= ~(SPM_SLEEP_MODE | EN_SLEEP_CTRL); + + /* Set RG MUX to SW mode */ + AP_PLL_CON0 = LTECLKSQ_EN | LTECLKSQ_LPF_EN | LTECLKSQ_HYS_EN | + LTECLKSQ_VOD_EN | LTECLKSQ_HYS_SEL | CLKSQ_RESERVE | + SSUSB26M_CK2_EN | SSUSB26M_CK_EN | XTAL26M_CK_EN | + ULPOSC_CTRL_SEL; + + /* Turn off ULPOSC2 */ + SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB; + + /* calibrate ULPOSC1 & ULPOSC2 */ + for (i = 0; i < ARRAY_SIZE(opp); ++i) + clock_calibrate_ulposc(&opp[i]); + + /* Select ULPOSC2 high speed CPU clock */ + scp_use_clock(SCP_CLK_ULPOSC2); + + /* Enable default clock gate */ + SCP_CLK_GATE |= CG_DMA_CH3 | CG_DMA_CH2 | CG_DMA_CH1 | CG_DMA_CH0 | + CG_I2C_M | CG_MAD_M | CG_AP2P_M; + + task_enable_irq(SCP_IRQ_CLOCK); + task_enable_irq(SCP_IRQ_CLOCK2); +} + +DECLARE_IRQ(SCP_IRQ_CLOCK, clock_control_irq, 3); +void clock_control_irq(void) +{ + /* Read ack CLK_IRQ */ + (SCP_CLK_IRQ_ACK); + task_clear_pending_irq(SCP_IRQ_CLOCK); +} + +DECLARE_IRQ(SCP_IRQ_CLOCK2, clock_fast_wakeup_irq, 3); +void clock_fast_wakeup_irq(void) +{ + /* Ack fast wakeup */ + SCP_SLEEP_IRQ2 = 1; + task_clear_pending_irq(SCP_IRQ_CLOCK2); +} + +/* Console command */ +static int command_ulposc(int argc, const char *argv[]) +{ + int i; + + for (i = 0; i <= 1; ++i) + ccprintf("ULPOSC%u frequency: %u kHz\n", i + 1, + clock_ulposc_measure_freq(i) * 26 * 1000 / 1024); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[calibrate]", + "Calibrate ULPOSC frequency"); + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mt_scp/mt818x/config_chip.h b/chip/mt_scp/mt818x/config_chip.h new file mode 100644 index 0000000000..e0222e33fa --- /dev/null +++ b/chip/mt_scp/mt818x/config_chip.h @@ -0,0 +1,75 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_CONFIG_CHIP_H +#define __CROS_EC_CONFIG_CHIP_H + +#include "core/cortex-m/config_core.h" + +/* Interval between HOOK_TICK notifications */ +#define HOOK_TICK_INTERVAL_MS 500 +#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) + +#ifdef CHIP_VARIANT_MT8186 +/* Default to UART 1 (AP UART) for EC console */ +#define CONFIG_UART_CONSOLE 1 +#else +/* Default to UART 2 (AP UART) for EC console */ +#define CONFIG_UART_CONSOLE 2 +#endif + +/* Number of IRQ vectors */ +#define CONFIG_IRQ_COUNT 56 + +/* + * Number of EINT can be 0 ~ 160. Change this to conditional macro + * on adding other variants. + */ +#define MAX_NUM_EINT 8 +#define MAX_EINT_PORT (MAX_NUM_EINT / 32) + +/* RW only, no flash */ +#undef CONFIG_FW_INCLUDE_RO +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_SIZE 0 +#define CONFIG_RW_MEM_OFF 0 + +#ifdef CHIP_VARIANT_MT8186 +#define CONFIG_RW_SIZE 0x20000 /* 128KB */ +#else +#define CONFIG_RW_SIZE 0x40000 /* 256KB */ +#endif + +#define CONFIG_EC_WRITABLE_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_PROGRAM_MEMORY_BASE 0 +#define CONFIG_MAPPED_STORAGE_BASE 0 +/* Enable MPU to protect code RAM from writing, and data RAM from execution.*/ +#define CONFIG_MPU + +/* Unsupported features/commands */ +#undef CONFIG_CMD_FLASHINFO +#undef CONFIG_CMD_POWER_AP +#undef CONFIG_FLASH_CROS +#undef CONFIG_FLASH_PHYSICAL +#undef CONFIG_FMAP +#undef CONFIG_HIBERNATE + +/* Task stack size */ +#define CONFIG_STACK_SIZE 1024 +#define IDLE_TASK_STACK_SIZE 256 +#define SMALLER_TASK_STACK_SIZE 384 +#define TASK_STACK_SIZE 512 +#define LARGER_TASK_STACK_SIZE 640 +#define VENTI_TASK_STACK_SIZE 768 + +#define CONFIG_CHIP_PRE_INIT + +#define GPIO_PIN(num) ((num) / 32), ((num) % 32) +#define GPIO_PIN_MASK(p, m) .port = (p), .mask = (m) + +#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/mt_scp/mt818x/gpio.c b/chip/mt_scp/mt818x/gpio.c new file mode 100644 index 0000000000..6d9a3b8418 --- /dev/null +++ b/chip/mt_scp/mt818x/gpio.c @@ -0,0 +1,178 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* GPIO module */ + +#include "gpio.h" +#include "hooks.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "util.h" + +void gpio_set_alternate_function(uint32_t port, uint32_t mask, + enum gpio_alternate_func func) +{ + int bit, mode_reg_index, shift; + uint32_t mode_bits, mode_mask; + + /* Up to 8 alt functions per port */ + if (func > GPIO_ALT_FUNC_7) + return; + + if (func == GPIO_ALT_FUNC_NONE) + func = GPIO_ALT_FUNC_DEFAULT; + + while (mask) { + /* 32 gpio per port */ + bit = get_next_bit(&mask); + /* 8 gpio per mode reg */ + mode_reg_index = (port << 2) | (bit >> 3); + /* + * b[3] - write enable(?) + * b[2:0] - mode + */ + shift = (bit & 7) << 2; + mode_bits = func << shift; + mode_mask = ~(0xf << shift); + AP_GPIO_MODE(mode_reg_index) = + (AP_GPIO_MODE(mode_reg_index) & mode_mask) | mode_bits; + } +} + +test_mockable int gpio_get_level(enum gpio_signal signal) +{ + return !!(AP_GPIO_DIN(gpio_list[signal].port) & gpio_list[signal].mask); +} + +void gpio_set_level(enum gpio_signal signal, int value) +{ + if (value) + AP_GPIO_DOUT(gpio_list[signal].port) |= gpio_list[signal].mask; + else + AP_GPIO_DOUT(gpio_list[signal].port) &= ~gpio_list[signal].mask; +} + +void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) +{ + /* Set input/output mode */ + if (flags & GPIO_OUTPUT) { + /* Set level before changing to output mode */ + if (flags & GPIO_HIGH) + AP_GPIO_DOUT(port) |= mask; + if (flags & GPIO_LOW) + AP_GPIO_DOUT(port) &= ~mask; + AP_GPIO_DIR(port) |= mask; + } else { + AP_GPIO_DIR(port) &= ~mask; + } + + if (flags & (GPIO_INT_F_RISING | GPIO_INT_F_HIGH)) + SCP_EINT_POLARITY_SET[port] = mask; + + if (flags & (GPIO_INT_F_FALLING | GPIO_INT_F_LOW)) + SCP_EINT_POLARITY_CLR[port] = mask; + else + SCP_EINT_POLARITY_SET[port] = mask; + + /* Set sensitivity register on edge trigger */ + if (flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING)) + SCP_EINT_SENS_SET[port] = mask; + else + SCP_EINT_SENS_CLR[port] = mask; +} + +int gpio_get_flags_by_mask(uint32_t port, uint32_t mask) +{ + /* TODO(b/120167145): implement get flags */ + return 0; +} + +int gpio_enable_interrupt(enum gpio_signal signal) +{ + const struct gpio_info *g = gpio_list + signal; + + if (signal >= GPIO_IH_COUNT || !g->mask) + return EC_ERROR_INVAL; + + SCP_EINT_MASK_CLR[g->port] = g->mask; + + return EC_SUCCESS; +} + +int gpio_disable_interrupt(enum gpio_signal signal) +{ + const struct gpio_info *g = gpio_list + signal; + + if (signal >= GPIO_IH_COUNT || !g->mask) + return EC_ERROR_INVAL; + + SCP_EINT_MASK_SET[g->port] = g->mask; + + return EC_SUCCESS; +} + +int gpio_clear_pending_interrupt(enum gpio_signal signal) +{ + const struct gpio_info *g = gpio_list + signal; + + if (signal >= GPIO_IH_COUNT || !g->mask) + return EC_ERROR_INVAL; + + SCP_EINT_ACK[g->port] = g->mask; + + return EC_SUCCESS; +} + +void gpio_pre_init(void) +{ + const struct gpio_info *g = gpio_list; + int i; + int is_warm = system_is_reboot_warm(); + + for (i = 0; i < GPIO_COUNT; i++, g++) { + int flags = g->flags; + + if (flags & GPIO_DEFAULT) + continue; + + if (is_warm) + flags &= ~(GPIO_LOW | GPIO_HIGH); + + gpio_set_flags_by_mask(g->port, g->mask, flags); + } +} + +void gpio_init(void) +{ + /* Enable EINT IRQ */ + task_enable_irq(SCP_IRQ_EINT); +} +DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); + +/* Interrupt handler */ +static void __attribute__((used)) gpio_interrupt(void) +{ + int bit, port; + uint32_t pending; + enum gpio_signal signal; + + for (port = 0; port <= MAX_EINT_PORT; port++) { + pending = SCP_EINT_STATUS[port]; + + while (pending) { + bit = get_next_bit(&pending); + SCP_EINT_ACK[port] = BIT(bit); + /* Skip masked gpio */ + if (SCP_EINT_MASK_GET[port] & BIT(bit)) + continue; + /* Call handler */ + signal = port * 32 + bit; + if (signal < GPIO_IH_COUNT) + gpio_irq_handlers[signal](signal); + } + } +} +DECLARE_IRQ(SCP_IRQ_EINT, gpio_interrupt, 1); diff --git a/chip/mt_scp/mt818x/hrtimer.c b/chip/mt_scp/mt818x/hrtimer.c new file mode 100644 index 0000000000..e68c3e48e7 --- /dev/null +++ b/chip/mt_scp/mt818x/hrtimer.c @@ -0,0 +1,255 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * High-res hardware timer + * + * SCP hardware 32bit count down timer can be configured to source clock from + * 32KHz, 26MHz, BCLK or PCLK. This implementation selects BCLK (ULPOSC1/8) as a + * source, countdown mode and converts to micro second value matching common + * timer. + */ + +#include "clock.h" +#include "clock_chip.h" +#include "common.h" +#include "console.h" +#include "hooks.h" +#include "hwtimer.h" +#include "panic.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "watchdog.h" + +#define IRQ_TIMER(n) CONCAT2(SCP_IRQ_TIMER, n) + +#define TIMER_SYSTEM 5 +#define TIMER_EVENT 3 + +/* ULPOSC1 should be a multiple of 8. */ +BUILD_ASSERT((ULPOSC1_CLOCK_MHZ % 8) == 0); +#define TIMER_CLOCK_MHZ (ULPOSC1_CLOCK_MHZ / 8) + +/* Common timer overflows at 0x100000000 micro seconds */ +#define OVERFLOW_TICKS (TIMER_CLOCK_MHZ * 0x100000000 - 1) + +static uint8_t sys_high; +static uint8_t event_high; + +/* Convert hardware countdown timer to 64bit countup ticks */ +static inline uint64_t timer_read_raw_system(void) +{ + uint32_t timer_ctrl = SCP_TIMER_IRQ_CTRL(TIMER_SYSTEM); + uint32_t sys_high_adj = sys_high; + + /* + * If an IRQ is pending, but has not been serviced yet, adjust the + * sys_high value. + */ + if (timer_ctrl & TIMER_IRQ_STATUS) + sys_high_adj = sys_high ? (sys_high - 1) : + (TIMER_CLOCK_MHZ - 1); + + return OVERFLOW_TICKS - + (((uint64_t)sys_high_adj << 32) | SCP_TIMER_VAL(TIMER_SYSTEM)); +} + +static inline uint64_t timer_read_raw_event(void) +{ + return OVERFLOW_TICKS - + (((uint64_t)event_high << 32) | SCP_TIMER_VAL(TIMER_EVENT)); +} + +static inline void timer_set_clock(int n, uint32_t clock_source) +{ + SCP_TIMER_EN(n) = (SCP_TIMER_EN(n) & ~TIMER_CLK_MASK) | clock_source; +} + +static inline void timer_ack_irq(int n) +{ + SCP_TIMER_IRQ_CTRL(n) |= TIMER_IRQ_CLEAR; +} + +/* Set hardware countdown value */ +static inline void timer_set_reset_value(int n, uint32_t reset_value) +{ + SCP_TIMER_RESET_VAL(n) = reset_value; +} + +static void timer_reset(int n) +{ + __hw_timer_enable_clock(n, 0); + timer_ack_irq(n); + timer_set_reset_value(n, 0xffffffff); + timer_set_clock(n, TIMER_CLK_32K); +} + +/* Reload a new 32bit countdown value */ +static void timer_reload(int n, uint32_t value) +{ + __hw_timer_enable_clock(n, 0); + timer_set_reset_value(n, value); + __hw_timer_enable_clock(n, 1); +} + +static int timer_reload_event_high(void) +{ + if (event_high) { + if (SCP_TIMER_RESET_VAL(TIMER_EVENT) == 0xffffffff) + __hw_timer_enable_clock(TIMER_EVENT, 1); + else + timer_reload(TIMER_EVENT, 0xffffffff); + event_high--; + return 1; + } + + /* Disable event timer clock when done. */ + __hw_timer_enable_clock(TIMER_EVENT, 0); + return 0; +} + +void __hw_clock_event_clear(void) +{ + __hw_timer_enable_clock(TIMER_EVENT, 0); + timer_set_reset_value(TIMER_EVENT, 0x0000c1ea4); + event_high = 0; +} + +void __hw_clock_event_set(uint32_t deadline) +{ + uint64_t deadline_raw = (uint64_t)deadline * TIMER_CLOCK_MHZ; + uint64_t now_raw = timer_read_raw_system(); + uint32_t event_deadline; + + if (deadline_raw > now_raw) { + deadline_raw -= now_raw; + event_deadline = (uint32_t)deadline_raw; + event_high = deadline_raw >> 32; + } else { + event_deadline = 1; + event_high = 0; + } + + if (event_deadline) + timer_reload(TIMER_EVENT, event_deadline); + else + timer_reload_event_high(); +} + +void __hw_timer_enable_clock(int n, int enable) +{ + if (enable) { + SCP_TIMER_IRQ_CTRL(n) |= 1; + SCP_TIMER_EN(n) |= 1; + } else { + SCP_TIMER_EN(n) &= ~1; + SCP_TIMER_IRQ_CTRL(n) &= ~1; + } +} + +int __hw_clock_source_init(uint32_t start_t) +{ + int t; + + /* + * TODO(b/120169529): check clock tree to see if we need to turn on + * MCLK and BCLK gate. + */ + SCP_CLK_GATE |= (CG_TIMER_M | CG_TIMER_B); + + /* Reset all timer, select 32768Hz clock source */ + for (t = 0; t < NUM_TIMERS; t++) + timer_reset(t); + + /* Enable timer IRQ wake source */ + SCP_INTC_IRQ_WAKEUP |= (1 << IRQ_TIMER(0)) | (1 << IRQ_TIMER(1)) | + (1 << IRQ_TIMER(2)) | (1 << IRQ_TIMER(3)) | + (1 << IRQ_TIMER(4)) | (1 << IRQ_TIMER(5)); + /* + * Timer configuration: + * OS TIMER - count up @ 13MHz, 64bit value with latch. + * SYS TICK - count down @ 26MHz + * EVENT TICK - count down @ 26MHz + */ + + /* Turn on OS TIMER, tick at 13MHz */ + SCP_OSTIMER_CON |= 1; + + /* System timestamp timer from BCLK (sourced from ULPOSC) */ + SCP_CLK_BCLK = CLK_BCLK_SEL_ULPOSC1_DIV8; + + timer_set_clock(TIMER_SYSTEM, TIMER_CLK_BCLK); + sys_high = TIMER_CLOCK_MHZ - 1; + timer_set_reset_value(TIMER_SYSTEM, 0xffffffff); + __hw_timer_enable_clock(TIMER_SYSTEM, 1); + task_enable_irq(IRQ_TIMER(TIMER_SYSTEM)); + /* Event tick timer */ + timer_set_clock(TIMER_EVENT, TIMER_CLK_BCLK); + task_enable_irq(IRQ_TIMER(TIMER_EVENT)); + + return IRQ_TIMER(TIMER_SYSTEM); +} + +uint32_t __hw_clock_source_read(void) +{ + return timer_read_raw_system() / TIMER_CLOCK_MHZ; +} + +uint32_t __hw_clock_event_get(void) +{ + return (timer_read_raw_event() + timer_read_raw_system()) / + TIMER_CLOCK_MHZ; +} + +static void __hw_clock_source_irq(int n) +{ + uint32_t timer_ctrl = SCP_TIMER_IRQ_CTRL(n); + + /* Ack if we're hardware interrupt */ + if (timer_ctrl & TIMER_IRQ_STATUS) + timer_ack_irq(n); + + switch (n) { + case TIMER_EVENT: + if (timer_ctrl & TIMER_IRQ_STATUS) { + if (timer_reload_event_high()) + return; + } + process_timers(0); + break; + case TIMER_SYSTEM: + /* If this is a hardware irq, check overflow */ + if (timer_ctrl & TIMER_IRQ_STATUS) { + if (sys_high) { + sys_high--; + process_timers(0); + } else { + /* Overflow, reload system timer */ + sys_high = TIMER_CLOCK_MHZ - 1; + process_timers(1); + } + } else { + process_timers(0); + } + break; + default: + return; + } +} + +#define DECLARE_TIMER_IRQ(n) \ + DECLARE_IRQ(IRQ_TIMER(n), __hw_clock_source_irq_##n, 2); \ + static void __hw_clock_source_irq_##n(void) \ + { \ + __hw_clock_source_irq(n); \ + } + +DECLARE_TIMER_IRQ(0); +DECLARE_TIMER_IRQ(1); +DECLARE_TIMER_IRQ(2); +DECLARE_TIMER_IRQ(3); +DECLARE_TIMER_IRQ(4); +DECLARE_TIMER_IRQ(5); diff --git a/chip/mt_scp/mt818x/ipi.c b/chip/mt_scp/mt818x/ipi.c new file mode 100644 index 0000000000..d0d9292fd1 --- /dev/null +++ b/chip/mt_scp/mt818x/ipi.c @@ -0,0 +1,398 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Inter-Processor Communication (IPC) and Inter-Processor Interrupt (IPI) + * + * IPC is a communication bridge between AP and SCP. AP/SCP sends an IPC + * interrupt to SCP/AP to inform to collect the commmunication mesesages in the + * shared buffer. + * + * There are 4 IPCs in the current architecture, from IPC0 to IPC3. The + * priority of IPC is proportional to its IPC index. IPC3 has the highest + * priority and IPC0 has the lowest one. + * + * IPC0 may contain zero or more IPIs. Each IPI represents a task or a service, + * e.g. host command, or video encoding. IPIs are recognized by IPI ID, which + * should sync across AP and SCP. Shared buffer should designated which IPI + * ID it talks to. + * + * Currently, we don't have IPC handlers for IPC1, IPC2, and IPC3. + */ + +#include "clock_chip.h" +#include "console.h" +#include "hooks.h" +#include "host_command.h" +#include "hwtimer.h" +#include "ipi_chip.h" +#include "mkbp_event.h" +#include "power.h" +#include "system.h" +#include "task.h" +#include "util.h" +#include "video.h" + +#define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) +#define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) + +#define IPI_MAX_REQUEST_SIZE CONFIG_IPC_SHARED_OBJ_BUF_SIZE +/* Reserve 1 extra byte for HOSTCMD_TYPE and 3 bytes for padding. */ +#define IPI_MAX_RESPONSE_SIZE (CONFIG_IPC_SHARED_OBJ_BUF_SIZE - 4) +#define HOSTCMD_TYPE_HOSTCMD 1 +#define HOSTCMD_TYPE_HOSTEVENT 2 + +static volatile int16_t ipc0_enabled_count; +static struct mutex ipc0_lock; +static struct mutex ipi_lock; +/* IPC0 shared objects, including send object and receive object. */ +static struct ipc_shared_obj *const scp_send_obj = + (struct ipc_shared_obj *)CONFIG_IPC_SHARED_OBJ_ADDR; +static struct ipc_shared_obj *const scp_recv_obj = + (struct ipc_shared_obj *)(CONFIG_IPC_SHARED_OBJ_ADDR + + sizeof(struct ipc_shared_obj)); +static char ipi_ready; + +#ifdef HAS_TASK_HOSTCMD +/* + * hostcmd and hostevent share the same IPI ID, and use first byte type to + * indicate its type. + */ +static struct hostcmd_data { + const uint8_t type; + /* To be compatible with CONFIG_HOSTCMD_ALIGNED */ + uint8_t response[IPI_MAX_RESPONSE_SIZE] __aligned(4); +} hc_cmd_obj = { .type = HOSTCMD_TYPE_HOSTCMD }; +BUILD_ASSERT(sizeof(struct hostcmd_data) == CONFIG_IPC_SHARED_OBJ_BUF_SIZE); + +static struct host_packet ipi_packet; +#endif + +/* Check if SCP to AP IPI is in use. */ +static inline int is_ipi_busy(void) +{ + return SCP_HOST_INT & IPC_SCP2HOST_BIT; +} + +/* If IPI is declared as a wake-up source, wake AP up. */ +static inline void try_to_wakeup_ap(int32_t id) +{ +#ifdef CONFIG_RPMSG_NAME_SERVICE + if (id == IPI_NS_SERVICE) + return; +#endif + + if (*ipi_wakeup_table[id]) + SCP_SPM_INT = SPM_INT_A2SPM; +} + +void ipi_disable_irq(int irq) +{ + /* Only support SCP_IRQ_IPC0 for now. */ + if (irq != SCP_IRQ_IPC0) + return; + + mutex_lock(&ipc0_lock); + + if ((--ipc0_enabled_count) == 0) + task_disable_irq(irq); + + mutex_unlock(&ipc0_lock); +} + +void ipi_enable_irq(int irq) +{ + /* Only support SCP_IRQ_IPC0 for now. */ + if (irq != SCP_IRQ_IPC0) + return; + + mutex_lock(&ipc0_lock); + + if ((++ipc0_enabled_count) == 1) { + int pending_ipc = SCP_GIPC_IN & SCP_GPIC_IN_CLEAR_ALL; + + task_enable_irq(irq); + + if (ipi_ready && pending_ipc) + /* + * IPC may be triggered while SCP_IRQ_IPC0 was disabled. + * AP will still updates SCP_GIPC_IN. + * Trigger the IRQ handler if it has a + * pending IPC. + */ + task_trigger_irq(irq); + } + + mutex_unlock(&ipc0_lock); +} + +__override void +power_chipset_handle_host_sleep_event(enum host_sleep_event state, + struct host_sleep_event_context *ctx) +{ + int i; + const task_id_t s3_suspend_tasks[] = { +#ifndef S3_SUSPEND_TASK_LIST +#define S3_SUSPEND_TASK_LIST +#endif +#define TASK(n, ...) TASK_ID_##n, + S3_SUSPEND_TASK_LIST + }; + + if (state == HOST_SLEEP_EVENT_S3_SUSPEND) { + ccprints("AP suspend"); + /* + * On AP suspend, Vcore is 0.6V, and we should not use ULPOSC2, + * which needs at least 0.7V. Switch to ULPOSC1 instead. + */ + scp_use_clock(SCP_CLK_ULPOSC1); + + for (i = 0; i < ARRAY_SIZE(s3_suspend_tasks); ++i) + task_disable_task(s3_suspend_tasks[i]); + } else if (state == HOST_SLEEP_EVENT_S3_RESUME) { + ccprints("AP resume"); + /* Vcore is raised to >=0.7V, switch back to ULPSOC2 */ + scp_use_clock(SCP_CLK_ULPOSC2); + + for (i = 0; i < ARRAY_SIZE(s3_suspend_tasks); ++i) + task_enable_task(s3_suspend_tasks[i]); + } +} + +/* Send data from SCP to AP. */ +int ipi_send(int32_t id, const void *buf, uint32_t len, int wait) +{ + if (!ipi_ready) + return EC_ERROR_BUSY; + + /* TODO(b:117917141): Remove this check completely. */ + if (in_interrupt_context()) { + CPRINTS("Err: invoke %s() in ISR CTX", __func__); + return EC_ERROR_BUSY; + } + + if (len > sizeof(scp_send_obj->buffer)) + return EC_ERROR_INVAL; + + ipi_disable_irq(SCP_IRQ_IPC0); + mutex_lock(&ipi_lock); + + /* Check if there is already an IPI pending in AP. */ + if (is_ipi_busy()) { + /* + * If the following conditions meet, + * 1) There is an IPI pending in AP. + * 2) The incoming IPI is a wakeup IPI. + * then it assumes that AP is in suspend state. + * Send a AP wakeup request to SPM. + * + * The incoming IPI will be checked if it's a wakeup source. + */ + try_to_wakeup_ap(id); + + mutex_unlock(&ipi_lock); + ipi_enable_irq(SCP_IRQ_IPC0); + CPRINTS("Err: IPI Busy, %d", id); + + return EC_ERROR_BUSY; + } + + scp_send_obj->id = id; + scp_send_obj->len = len; + memcpy(scp_send_obj->buffer, buf, len); + + /* Send IPI to AP: interrutp AP to receive IPI messages. */ + try_to_wakeup_ap(id); + SCP_HOST_INT = IPC_SCP2HOST_BIT; + + while (wait && is_ipi_busy()) + ; + + mutex_unlock(&ipi_lock); + ipi_enable_irq(SCP_IRQ_IPC0); + + return EC_SUCCESS; +} + +static void ipi_handler(void) +{ + if (scp_recv_obj->id >= IPI_COUNT) { + CPRINTS("#ERR IPI %d", scp_recv_obj->id); + return; + } + + /* + * Only print IPI that is not host command channel, which will + * be printed by host command driver. + */ + if (scp_recv_obj->id != IPI_HOST_COMMAND) + CPRINTS("IPI %d", scp_recv_obj->id); + + /* + * Pass the buffer to handler. Each handler should be in charge of + * the buffer copying/reading before returning from handler. + */ + ipi_handler_table[scp_recv_obj->id]( + scp_recv_obj->id, scp_recv_obj->buffer, scp_recv_obj->len); +} + +void ipi_inform_ap(void) +{ + struct scp_run_t scp_run; + int ret; +#ifdef CONFIG_RPMSG_NAME_SERVICE + struct rpmsg_ns_msg ns_msg; +#endif + + scp_run.signaled = 1; + strncpy(scp_run.fw_ver, system_get_version(EC_IMAGE_RW), + SCP_FW_VERSION_LEN); +#ifdef HAVE_PRIVATE_MT8183 + scp_run.dec_capability = VCODEC_CAPABILITY_4K_DISABLED; +#else + scp_run.dec_capability = video_get_dec_capability(); +#endif + scp_run.enc_capability = 0; + + ret = ipi_send(IPI_SCP_INIT, (void *)&scp_run, sizeof(scp_run), 1); + + if (ret) + ccprintf("Failed to send initialization IPC messages.\n"); + +#ifdef CONFIG_RPMSG_NAME_SERVICE + ns_msg.id = IPI_HOST_COMMAND; + strncpy(ns_msg.name, "cros-ec-rpmsg", RPMSG_NAME_SIZE); + ret = ipi_send(IPI_NS_SERVICE, &ns_msg, sizeof(ns_msg), 1); + if (ret) + ccprintf("Failed to announce host command channel.\n"); +#endif +} + +#ifdef HAS_TASK_HOSTCMD +#if defined(CONFIG_MKBP_USE_CUSTOM) +int mkbp_set_host_active_via_custom(int active, uint32_t *timestamp) +{ + static const uint8_t hc_evt_obj = HOSTCMD_TYPE_HOSTEVENT; + + /* This should be moved into ipi_send for more accuracy */ + if (timestamp) + *timestamp = __hw_clock_source_read(); + + if (active) + return ipi_send(IPI_HOST_COMMAND, &hc_evt_obj, + sizeof(hc_evt_obj), 1); + return EC_SUCCESS; +} +#endif + +static void ipi_send_response_packet(struct host_packet *pkt) +{ + int ret; + + ret = ipi_send(IPI_HOST_COMMAND, &hc_cmd_obj, + pkt->response_size + + offsetof(struct hostcmd_data, response), + 1); + if (ret) + CPRINTS("#ERR IPI HOSTCMD %d", ret); +} + +static void ipi_hostcmd_handler(int32_t id, void *buf, uint32_t len) +{ + uint8_t *in_msg = buf; + struct ec_host_request *r = (struct ec_host_request *)in_msg; + int i; + + if (in_msg[0] != EC_HOST_REQUEST_VERSION) { + CPRINTS("ERROR: Protocol V2 is not supported!"); + CPRINTF("in_msg=["); + for (i = 0; i < len; i++) + CPRINTF("%02x ", in_msg[i]); + CPRINTF("]\n"); + return; + } + + /* Protocol version 3 */ + + ipi_packet.send_response = ipi_send_response_packet; + + /* + * Just assign the buffer to request, host_packet_receive + * handles the buffer copy. + */ + ipi_packet.request = (void *)r; + ipi_packet.request_temp = NULL; + ipi_packet.request_max = IPI_MAX_REQUEST_SIZE; + ipi_packet.request_size = host_request_expected_size(r); + + ipi_packet.response = hc_cmd_obj.response; + /* Reserve space for the preamble and trailing byte */ + ipi_packet.response_max = IPI_MAX_RESPONSE_SIZE; + ipi_packet.response_size = 0; + + ipi_packet.driver_result = EC_RES_SUCCESS; + + host_packet_receive(&ipi_packet); +} +DECLARE_IPI(IPI_HOST_COMMAND, ipi_hostcmd_handler, 0); + +/* + * Get protocol information + */ +static enum ec_status ipi_get_protocol_info(struct host_cmd_handler_args *args) +{ + struct ec_response_get_protocol_info *r = args->response; + + memset(r, 0, sizeof(*r)); + r->protocol_versions |= BIT(3); + r->max_request_packet_size = IPI_MAX_REQUEST_SIZE; + r->max_response_packet_size = IPI_MAX_RESPONSE_SIZE; + + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, ipi_get_protocol_info, + EC_VER_MASK(0)); +#endif + +static void ipi_enable_ipc0_deferred(void) +{ + /* Clear IPC0 IRQs. */ + SCP_GIPC_IN = SCP_GPIC_IN_CLEAR_ALL; + + /* All tasks are up, we can safely enable IPC0 IRQ now. */ + SCP_INTC_IRQ_ENABLE |= IPC0_IRQ_EN; + ipi_enable_irq(SCP_IRQ_IPC0); + + ipi_ready = 1; + + /* Inform AP that SCP is inited. */ + ipi_inform_ap(); + + CPRINTS("ipi init"); +} +DECLARE_DEFERRED(ipi_enable_ipc0_deferred); + +/* Initialize IPI. */ +static void ipi_init(void) +{ + /* Clear send share buffer. */ + memset(scp_send_obj, 0, sizeof(struct ipc_shared_obj)); + + /* Enable IRQ after all tasks are up. */ + hook_call_deferred(&ipi_enable_ipc0_deferred_data, 0); +} +DECLARE_HOOK(HOOK_INIT, ipi_init, HOOK_PRIO_DEFAULT); + +DECLARE_IRQ(SCP_IRQ_IPC0, ipc_handler, 4); +static void ipc_handler(void) +{ + /* TODO(b/117917141): We only support IPC_ID(0) for now. */ + if (SCP_GIPC_IN & SCP_GIPC_IN_CLEAR_IPCN(0)) { + ipi_handler(); + SCP_GIPC_IN &= SCP_GIPC_IN_CLEAR_IPCN(0); + } + + SCP_GIPC_IN &= (SCP_GPIC_IN_CLEAR_ALL & ~SCP_GIPC_IN_CLEAR_IPCN(0)); +} diff --git a/chip/mt_scp/mt818x/ipi_chip.h b/chip/mt_scp/mt818x/ipi_chip.h new file mode 100644 index 0000000000..37be00dabb --- /dev/null +++ b/chip/mt_scp/mt818x/ipi_chip.h @@ -0,0 +1,111 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_IPI_CHIP_H +#define __CROS_EC_IPI_CHIP_H + +#include "common.h" +#include "registers.h" + +#define IPC_MAX 1 +#define IPC_ID(n) (n) + +/* + * Length of EC version string is at most 32 byte (NULL included), which + * also aligns SCP fw_version length. + */ +#define SCP_FW_VERSION_LEN 32 + +/* + * Video decoder supported capability: + * BIT(4): 0 enable 4K + * 1 disable 4K + */ +#define VCODEC_CAPABILITY_4K_DISABLED BIT(4) + +#ifndef IPI_SCP_INIT +#error If CONFIG_IPI is enabled, IPI_SCP_INIT must be defined. +#endif + +/* + * Share buffer layout for IPI_SCP_INIT response. This structure should sync + * across kernel and EC. + */ +struct scp_run_t { + uint32_t signaled; + int8_t fw_ver[SCP_FW_VERSION_LEN]; + uint32_t dec_capability; + uint32_t enc_capability; +}; + +/* + * The layout of the IPC0 AP/SCP shared buffer. + * This should sync across kernel and EC. + */ +struct ipc_shared_obj { + /* IPI ID */ + int32_t id; + /* Length of the contents in buffer. */ + uint32_t len; + /* Shared buffer contents. */ + uint8_t buffer[CONFIG_IPC_SHARED_OBJ_BUF_SIZE]; +}; + +/* Send a IPI contents to AP. This shouldn't be used in ISR context. */ +int ipi_send(int32_t id, const void *buf, uint32_t len, int wait); + +/* Size of the rpmsg device name, should sync across kernel and EC. */ +#define RPMSG_NAME_SIZE 32 + +/* + * The layout of name service message. + * This should sync across kernel and EC. + */ +struct rpmsg_ns_msg { + /* Name of the corresponding rpmsg_driver. */ + char name[RPMSG_NAME_SIZE]; + /* IPC ID */ + uint32_t id; +}; + +/* + * An IPC IRQ could be shared across many IPI handlers. + * Those handlers would usually operate on disabling or enabling the IPC IRQ. + * This may disorder the actual timing to on/off the IRQ when there are many + * tasks try to operate on it. As a result, any access to the SCP_IRQ_* + * should go through ipi_{en,dis}able_irq(), which support a counter to + * enable/disable the IRQ at correct timeing. + */ +/* Disable IPI IRQ. */ +void ipi_disable_irq(int irq); +/* Enable IPI IRQ. */ +void ipi_enable_irq(int irq); + +/* IPI tables */ +extern void (*ipi_handler_table[])(int32_t, void *, uint32_t); +extern int *ipi_wakeup_table[]; + +/* Helper macros to build the IPI handler and wakeup functions. */ +#define IPI_HANDLER(id) CONCAT3(ipi_, id, _handler) +#define IPI_WAKEUP(id) CONCAT3(ipi_, id, _wakeup) + +/* + * Macro to declare an IPI handler. + * _id: The ID of the IPI + * handler: The IPI handler function + * is_wakeup_src: Declare IPI ID as a wake-up source or not + */ +#define DECLARE_IPI(_id, handler, is_wakeup_src) \ + struct ipi_num_check##_id { \ + int tmp1[_id < IPI_COUNT ? 1 : -1]; \ + int tmp2[is_wakeup_src == 0 || is_wakeup_src == 1 ? 1 : -1]; \ + }; \ + void __keep IPI_HANDLER(_id)(int32_t id, void *buf, uint32_t len) \ + { \ + handler(id, buf, len); \ + } \ + const int __keep IPI_WAKEUP(_id) = is_wakeup_src + +#endif /* __CROS_EC_IPI_CHIP_H */ diff --git a/chip/mt_scp/mt818x/ipi_table.c b/chip/mt_scp/mt818x/ipi_table.c new file mode 100644 index 0000000000..153b8b8dbc --- /dev/null +++ b/chip/mt_scp/mt818x/ipi_table.c @@ -0,0 +1,70 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * IPI handlers declaration + */ + +#include "common.h" +#include "ipi_chip.h" + +typedef void (*ipi_handler_t)(int32_t id, void *data, uint32_t len); + +#ifndef PASS +#define PASS 1 +#endif + +#define ipi_arguments int32_t id, void *data, uint32_t len + +#if PASS == 1 +void ipi_handler_undefined(ipi_arguments) +{ +} + +const int ipi_wakeup_undefined; + +#define table(type, name, x) x + +#define ipi_x_func(suffix, args, number) \ + extern void \ + __attribute__((used, weak, \ + alias(STRINGIFY(ipi_##suffix##_undefined)))) \ + ipi_##number##_##suffix(args); + +#define ipi_x_var(suffix, number) \ + extern int __attribute__((weak, \ + alias(STRINGIFY(ipi_##suffix##_undefined)))) \ + ipi_##number##_##suffix; + +#endif /* PASS == 1 */ + +#if PASS == 2 + +#undef table +#undef ipi_x_func +#undef ipi_x_var + +#define table(type, name, x) \ + type name[] __aligned(4) \ + __attribute__((section(".rodata.ipi, \"a\" @"))) = { x } + +#define ipi_x_var(suffix, number) \ + [number < IPI_COUNT ? number : -1] = &ipi_##number##_##suffix, + +#define ipi_x_func(suffix, args, number) ipi_x_var(suffix, number) + +#endif /* PASS == 2 */ + +/* + * Include generated IPI table (by util/gen_ipi_table). The contents originate + * from IPI_COUNT definition in board.h + */ +#include "ipi_table_gen.inc" + +#if PASS == 1 +#undef PASS +#define PASS 2 +#include "ipi_table.c" +BUILD_ASSERT(ARRAY_SIZE(ipi_handler_table) == IPI_COUNT); +BUILD_ASSERT(ARRAY_SIZE(ipi_wakeup_table) == IPI_COUNT); +#endif diff --git a/chip/mt_scp/mt818x/memmap.c b/chip/mt_scp/mt818x/memmap.c new file mode 100644 index 0000000000..24c0fd8f7a --- /dev/null +++ b/chip/mt_scp/mt818x/memmap.c @@ -0,0 +1,318 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * SCP memory map + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "console.h" +#include "hooks.h" +#include "memmap.h" +#include "registers.h" +#include "task.h" +#include "util.h" + +/* + * Map SCP address (bits 31~28) to AP address + * + * SCP addr : AP addr + * 0x20000000 0x40000000 + * 0x30000000 0x50000000 + * 0x60000000 0x60000000 + * 0x70000000 0x70000000 + * 0x80000000 0x80000000 + * 0x90000000 0x00000000 + * 0xA0000000 0x10000000 + * 0xB0000000 0x20000000 + * 0xC0000000 0x30000000 + * 0xD0000000 0x10000000 + * 0xE0000000 0xA0000000 + * 0xF0000000 0x90000000 + */ + +#define MAP_INVALID 0xff + +static const uint8_t addr_map[16] = { + MAP_INVALID, /* 0x0: SRAM */ + MAP_INVALID, /* 0x1: Cached access (see below) */ + 0x4, 0x5, /* 0x2-0x3 */ + MAP_INVALID, MAP_INVALID, /* 0x4-0x5 (unmapped: registers) */ + 0x6, 0x7, 0x8, /* 0x6-0x8 */ + 0x0, 0x1, 0x2, 0x3, /* 0x9-0xc */ + 0x1, 0xa, 0x9 /* 0xd-0xf */ +}; + +/* + * AP addr : SCP cache addr + * 0x50000000 0x10000000 + */ +#define CACHE_TRANS_AP_ADDR 0x50000000 +#define CACHE_TRANS_SCP_CACHE_ADDR 0x10000000 + +#ifdef CONFIG_DRAM_BASE +BUILD_ASSERT(CONFIG_DRAM_BASE_LOAD == CACHE_TRANS_AP_ADDR); +BUILD_ASSERT(CONFIG_DRAM_BASE == CACHE_TRANS_SCP_CACHE_ADDR); +#endif + +static void cpu_invalidate_icache(void) +{ + SCP_CACHE_OP(CACHE_ICACHE) &= ~SCP_CACHE_OP_OP_MASK; + SCP_CACHE_OP(CACHE_ICACHE) |= OP_INVALIDATE_ALL_LINES | SCP_CACHE_OP_EN; + asm volatile("dsb; isb"); +} + +void cpu_invalidate_dcache(void) +{ + SCP_CACHE_OP(CACHE_DCACHE) &= ~SCP_CACHE_OP_OP_MASK; + SCP_CACHE_OP(CACHE_DCACHE) |= OP_INVALIDATE_ALL_LINES | SCP_CACHE_OP_EN; + /* Read is necessary to confirm the invalidation finish. */ + REG32(CACHE_TRANS_SCP_CACHE_ADDR); + asm volatile("dsb;"); +} + +void cpu_invalidate_dcache_range(uintptr_t base, unsigned int length) +{ + size_t pos; + uintptr_t addr; + + interrupt_disable(); + + for (pos = 0; pos < length; pos += SCP_CACHE_LINE_SIZE) { + addr = base + pos; + SCP_CACHE_OP(CACHE_DCACHE) = addr & SCP_CACHE_OP_TADDR_MASK; + SCP_CACHE_OP(CACHE_DCACHE) |= + OP_INVALIDATE_ONE_LINE_BY_ADDRESS | SCP_CACHE_OP_EN; + /* Read necessary to confirm the invalidation finish. */ + REG32(addr); + } + + asm volatile("dsb;"); + interrupt_enable(); +} + +void cpu_clean_invalidate_dcache(void) +{ + SCP_CACHE_OP(CACHE_DCACHE) &= ~SCP_CACHE_OP_OP_MASK; + SCP_CACHE_OP(CACHE_DCACHE) |= OP_CACHE_FLUSH_ALL_LINES | + SCP_CACHE_OP_EN; + SCP_CACHE_OP(CACHE_DCACHE) &= ~SCP_CACHE_OP_OP_MASK; + SCP_CACHE_OP(CACHE_DCACHE) |= OP_INVALIDATE_ALL_LINES | SCP_CACHE_OP_EN; + /* Read necessary to confirm the invalidation finish. */ + REG32(CACHE_TRANS_SCP_CACHE_ADDR); + asm volatile("dsb;"); +} + +void cpu_clean_invalidate_dcache_range(uintptr_t base, unsigned int length) +{ + size_t pos; + uintptr_t addr; + + interrupt_disable(); + for (pos = 0; pos < length; pos += SCP_CACHE_LINE_SIZE) { + addr = base + pos; + SCP_CACHE_OP(CACHE_DCACHE) = addr & SCP_CACHE_OP_TADDR_MASK; + SCP_CACHE_OP(CACHE_DCACHE) |= + OP_CACHE_FLUSH_ONE_LINE_BY_ADDRESS | SCP_CACHE_OP_EN; + SCP_CACHE_OP(CACHE_DCACHE) = addr & SCP_CACHE_OP_TADDR_MASK; + SCP_CACHE_OP(CACHE_DCACHE) |= + OP_INVALIDATE_ONE_LINE_BY_ADDRESS | SCP_CACHE_OP_EN; + /* Read necessary to confirm the invalidation finish. */ + REG32(addr); + } + + asm volatile("dsb;"); + interrupt_enable(); +} + +static void scp_cache_init(void) +{ + int c; + const int region = 0; + + /* First make sure all caches are disabled, and reset stats. */ + for (c = 0; c < CACHE_COUNT; c++) { + /* + * Changing cache-size config may change the SRAM logical + * address in the mean time. This may break the loaded + * memory layout, and thus break the system. Cache-size + * should only be be configured in kernel driver before + * laoding the firmware. b/137920815#comment18 + */ + SCP_CACHE_CON(c) &= + (SCP_CACHE_CON_CACHESIZE_MASK | SCP_CACHE_CON_WAYEN); + SCP_CACHE_REGION_EN(c) = 0; + SCP_CACHE_ENTRY(c, region) = 0; + SCP_CACHE_END_ENTRY(c, region) = 0; + + /* Reset statistics. */ + SCP_CACHE_HCNT0U(c) = 0; + SCP_CACHE_HCNT0L(c) = 0; + SCP_CACHE_CCNT0U(c) = 0; + SCP_CACHE_CCNT0L(c) = 0; + } + + /* No "normal" remap. */ + SCP_L1_REMAP_CFG0 = 0; + SCP_L1_REMAP_CFG1 = 0; + SCP_L1_REMAP_CFG2 = 0; + SCP_L1_REMAP_CFG3 = 0; + /* + * Setup OTHER1: Remap register for addr msb 31 to 28 equal to 0x1 and + * not overlap with L1C_EXT_ADDR0 to L1C_EXT_ADDR7. + */ + SCP_L1_REMAP_OTHER = + (CACHE_TRANS_AP_ADDR >> SCP_L1_EXT_ADDR_OTHER_SHIFT) << 8; + + /* Disable sleep protect */ + SCP_SLP_PROTECT_CFG = SCP_SLP_PROTECT_CFG & + ~(P_CACHE_SLP_PROT_EN | D_CACHE_SLP_PROT_EN); + + /* Enable region 0 for both I-cache and D-cache. */ + for (c = 0; c < CACHE_COUNT; c++) { + SCP_CACHE_ENTRY(c, region) = CACHE_TRANS_SCP_CACHE_ADDR; + SCP_CACHE_END_ENTRY(c, region) = + CACHE_TRANS_SCP_CACHE_ADDR + CACHE_TRANS_AP_SIZE; + SCP_CACHE_ENTRY(c, region) |= SCP_CACHE_ENTRY_C; + + SCP_CACHE_REGION_EN(c) |= 1 << region; + + /* + * Enable cache. Note that cache size setting should have been + * done in kernel driver. b/137920815#comment18 + */ + SCP_CACHE_CON(c) |= SCP_CACHE_CON_MCEN | SCP_CACHE_CON_CNTEN0; + } + + cpu_invalidate_icache(); + cpu_invalidate_dcache(); +} + +static int command_cacheinfo(int argc, const char **argv) +{ + const char cache_name[] = { 'I', 'D' }; + int c; + + for (c = 0; c < 2; c++) { + uint64_t hit = ((uint64_t)SCP_CACHE_HCNT0U(c) << 32) | + SCP_CACHE_HCNT0L(c); + uint64_t access = ((uint64_t)SCP_CACHE_CCNT0U(c) << 32) | + SCP_CACHE_CCNT0L(c); + + ccprintf("%ccache hit count: %llu\n", cache_name[c], hit); + ccprintf("%ccache access count: %llu\n", cache_name[c], access); + } + + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(cacheinfo, command_cacheinfo, NULL, + "Dump cache info"); + +void scp_memmap_init(void) +{ + /* + * Default config, LARGE DRAM not active: + * REG32(0xA0001F00) & 0x2000 != 0 + */ + + /* + * SCP_REMAP_CFG1 + * EXT_ADDR3[29:24] remap register for addr msb 31~28 equal to 0x7 + * EXT_ADDR2[21:16] remap register for addr msb 31~28 equal to 0x6 + * EXT_ADDR1[13:8] remap register for addr msb 31~28 equal to 0x3 + * EXT_ADDR0[5:0] remap register for addr msb 31~28 equal to 0x2 + */ + SCP_REMAP_CFG1 = (uint32_t)addr_map[0x7] << 24 | + (uint32_t)addr_map[0x6] << 16 | + (uint32_t)addr_map[0x3] << 8 | (uint32_t)addr_map[0x2]; + + /* + * SCP_REMAP_CFG2 + * EXT_ADDR7[29:24] remap register for addr msb 31~28 equal to 0xb + * EXT_ADDR6[21:16] remap register for addr msb 31~28 equal to 0xa + * EXT_ADDR5[13:8] remap register for addr msb 31~28 equal to 0x9 + * EXT_ADDR4[5:0] remap register for addr msb 31~28 equal to 0x8 + */ + SCP_REMAP_CFG2 = (uint32_t)addr_map[0xb] << 24 | + (uint32_t)addr_map[0xa] << 16 | + (uint32_t)addr_map[0x9] << 8 | (uint32_t)addr_map[0x8]; + /* + * SCP_REMAP_CFG3 + * AUD_ADDR[31:28] remap register for addr msb 31~28 equal to 0xd + * EXT_ADDR10[21:16]remap register for addr msb 31~28 equal to 0xf + * EXT_ADDR9[13:8] remap register for addr msb 31~28 equal to 0xe + * EXT_ADDR8[5:0] remap register for addr msb 31~28 equal to 0xc + */ + SCP_REMAP_CFG3 = (uint32_t)addr_map[0xd] << 28 | + (uint32_t)addr_map[0xf] << 16 | + (uint32_t)addr_map[0xe] << 8 | (uint32_t)addr_map[0xc]; + + /* Initialize cache remapping. */ + scp_cache_init(); +} + +int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr) +{ + int i; + uint8_t msb = ap_addr >> SCP_REMAP_ADDR_SHIFT; + + for (i = 0; i < ARRAY_SIZE(addr_map); i++) { + if (addr_map[i] != msb) + continue; + + *scp_addr = (ap_addr & SCP_REMAP_ADDR_LSB_MASK) | + (i << SCP_REMAP_ADDR_SHIFT); + return EC_SUCCESS; + } + + return EC_ERROR_INVAL; +} + +int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr) +{ + int i = scp_addr >> SCP_REMAP_ADDR_SHIFT; + + if (addr_map[i] == MAP_INVALID) + return EC_ERROR_INVAL; + + *ap_addr = (scp_addr & SCP_REMAP_ADDR_LSB_MASK) | + (addr_map[i] << SCP_REMAP_ADDR_SHIFT); + return EC_SUCCESS; +} + +#ifdef CONFIG_DRAM_BASE +BUILD_ASSERT(CONFIG_DRAM_BASE_LOAD == CACHE_TRANS_AP_ADDR); +BUILD_ASSERT(CONFIG_DRAM_BASE == CACHE_TRANS_SCP_CACHE_ADDR); +#endif + +int memmap_ap_to_scp_cache(uintptr_t ap_addr, uintptr_t *scp_addr) +{ + uintptr_t lsb; + + if ((ap_addr & SCP_L1_EXT_ADDR_OTHER_MSB_MASK) != CACHE_TRANS_AP_ADDR) + return EC_ERROR_INVAL; + + lsb = ap_addr & SCP_L1_EXT_ADDR_OTHER_LSB_MASK; + if (lsb > CACHE_TRANS_AP_SIZE) + return EC_ERROR_INVAL; + + *scp_addr = CACHE_TRANS_SCP_CACHE_ADDR | lsb; + return EC_SUCCESS; +} + +int memmap_scp_cache_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr) +{ + uintptr_t lsb; + + if ((scp_addr & SCP_L1_EXT_ADDR_OTHER_MSB_MASK) != + CACHE_TRANS_SCP_CACHE_ADDR) + return EC_ERROR_INVAL; + + lsb = scp_addr & SCP_L1_EXT_ADDR_OTHER_LSB_MASK; + if (lsb >= CACHE_TRANS_AP_SIZE) + return EC_ERROR_INVAL; + + *ap_addr = CACHE_TRANS_AP_ADDR | lsb; + return EC_SUCCESS; +} diff --git a/chip/mt_scp/mt818x/memmap.h b/chip/mt_scp/mt818x/memmap.h new file mode 100644 index 0000000000..a3dee1710a --- /dev/null +++ b/chip/mt_scp/mt818x/memmap.h @@ -0,0 +1,51 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * SCP memory map + */ + +#ifndef __CROS_EC_MEMMAP_H +#define __CROS_EC_MEMMAP_H + +#include "stdint.h" + +void scp_memmap_init(void); + +/** + * Translate AP addr to SCP addr. + * + * @param ap_addr AP address to translate + * @param scp_addr Tranlated AP address + * @return EC_SUCCESS or EC_ERROR_INVAL + */ +int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr); + +/** + * Translate SCP addr to AP addr. + * + * @param scp_addr SCP address to tranlate + * @param ap_addr Translated SCP address + * @return EC_SUCCESS or EC_ERROR_INVAL + */ +int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr); + +/** + * Translate AP addr to SCP cache addr. + * + * @param ap_addr AP address to translate + * @param scp_addr Tranlated AP cache address + * @return EC_SUCCESS or EC_ERROR_INVAL + */ +int memmap_ap_to_scp_cache(uintptr_t ap_addr, uintptr_t *scp_addr); + +/** + * Translate SCP addr to AP addr. + * + * @param scp_addr SCP cache address to tranlate + * @param ap_addr Translated SCP cache address + * @return EC_SUCCESS or EC_ERROR_INVAL + */ +int memmap_scp_cache_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr); + +#endif /* #ifndef __CROS_EC_MEMMAP_H */ diff --git a/chip/mt_scp/mt818x/registers.h b/chip/mt_scp/mt818x/registers.h new file mode 100644 index 0000000000..7bfcf184af --- /dev/null +++ b/chip/mt_scp/mt818x/registers.h @@ -0,0 +1,735 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Register map for SCP + */ + +#ifndef __CROS_EC_REGISTERS_H +#define __CROS_EC_REGISTERS_H + +#include "common.h" +#include "compile_time_macros.h" + +/* IRQ numbers */ +#define SCP_IRQ_IPC0 0 +#define SCP_IRQ_IPC1 1 +#define SCP_IRQ_IPC2 2 +#define SCP_IRQ_IPC3 3 +#define SCP_IRQ_SPM 4 +#define SCP_IRQ_CIRQ 5 +#define SCP_IRQ_EINT 6 +#define SCP_IRQ_PMIC 7 +#define SCP_IRQ_UART0 8 +#define SCP_IRQ_UART1 9 +#define SCP_IRQ_I2C0 10 +#define SCP_IRQ_I2C1 11 +#define SCP_IRQ_I2C2 12 +#define SCP_IRQ_CLOCK 13 +#define SCP_IRQ_MAD_FIFO 14 +#define SCP_IRQ_TIMER0 15 +#define SCP_IRQ_TIMER1 16 +#define SCP_IRQ_TIMER2 17 +#define SCP_IRQ_TIMER3 18 +#define SCP_IRQ_TIMER4 19 +#define SCP_IRQ_TIMER5 20 +#define SCP_IRQ_TIMER_STATUS 21 +#define SCP_IRQ_UART0_RX 22 +#define SCP_IRQ_UART1_RX 23 +#define SCP_IRQ_DMA 24 +#define SCP_IRQ_AUDIO 25 +#define SCP_IRQ_MD1_F216 26 +#define SCP_IRQ_MD1 27 +#define SCP_IRQ_C2K 28 +#define SCP_IRQ_SPI0 29 +#define SCP_IRQ_SPI1 30 +#define SCP_IRQ_SPI2 31 +#define SCP_IRQ_AP_EINT 32 +#define SCP_IRQ_DEBUG 33 +#define SCP_CCIF0 34 +#define SCP_CCIF1 35 +#define SCP_CCIF2 36 +#define SCP_IRQ_WDT 37 +#define SCP_IRQ_USB0 38 +#define SCP_IRQ_USB1 39 +#define SCP_IRQ_TWAM 40 +#define SCP_IRQ_INFRA 41 +#define SCP_IRQ_HWDVFS_HIGH 42 +#define SCP_IRQ_HWDVFS_LOW 43 +#define SCP_IRQ_CLOCK2 44 +/* RESERVED 45-52 */ +#define SCP_IRQ_AP_EINT2 53 +#define SCP_IRQ_AP_EINT_EVT 54 +#define SCP_IRQ_MAD_DATA 55 + +#define SCP_CFG_BASE 0x405C0000 + +#define SCP_AP_RESOURCE REG32(SCP_CFG_BASE + 0x04) +#define SCP_BUS_RESOURCE REG32(SCP_CFG_BASE + 0x08) + +#ifdef CHIP_VARIANT_MT8186 +#define SCP_TCM_LOCK_CFG (CFGREG_BASE + 0x10) +#endif + +/* SCP to host interrupt */ +#define SCP_HOST_INT REG32(SCP_CFG_BASE + 0x1C) +#define IPC_SCP2HOST_SSHUB 0xff0000 +#define WDT_INT 0x100 +#define IPC_SCP2HOST 0xff +#define IPC_SCP2HOST_BIT 0x1 + +/* SCP to SPM interrupt */ +#define SCP_SPM_INT REG32(SCP_CFG_BASE + 0x20) +#define SPM_INT_A2SPM BIT(0) +#define SPM_INT_B2SPM BIT(1) +#define SCP_SPM_INT2 REG32(SCP_CFG_BASE + 0x24) + +/* + * AP side to SCP IPC + * APMCU writes 1 bit to trigger ith IPC to SCP. + * SCP writes 1 bit to ith bit to clear ith IPC. + */ +#define SCP_GIPC_IN REG32(SCP_CFG_BASE + 0x28) +#define SCP_GIPC_IN_CLEAR_IPCN(n) (1 << (n)) +#define SCP_GPIC_IN_CLEAR_ALL 0x7FFFF +#define SCP_CONN_INT REG32(SCP_CFG_BASE + 0x2C) + +/* 8 general purpose registers, 0 ~ 7 */ +#define SCP_GPR REG32_ADDR(SCP_CFG_BASE + 0x50) +/* + * SCP_GPR[0] + * b15-b0 : scratchpad + * b31-b16 : saved flags + * SCP_GPR[1] + * b15-b0 : power on state + */ +#define SCP_PWRON_STATE SCP_GPR[1] +#define PWRON_DEFAULT 0xdee80000 +#define PWRON_WATCHDOG BIT(0) +#define PWRON_RESET BIT(1) +/* AP defined features */ +#define SCP_EXPECTED_FREQ SCP_GPR[3] +#define SCP_CURRENT_FREQ SCP_GPR[4] +#define SCP_REBOOT SCP_GPR[5] +#define READY_TO_REBOOT 0x34 +#define REBOOT_OK 1 + +/* Miscellaneous */ +#define SCP_SEMAPHORE REG32(SCP_CFG_BASE + 0x90) +#define CORE_CONTROL REG32(SCP_CFG_BASE + 0xA0) +#define CORE_FPU_FLAGS REG32(SCP_CFG_BASE + 0xA4) +#define CORE_REG_SP REG32(SCP_CFG_BASE + 0xA8) +#define CORE_REG_LR REG32(SCP_CFG_BASE + 0xAC) +#define CORE_REG_PSP REG32(SCP_CFG_BASE + 0xB0) +#define CORE_REG_PC REG32(SCP_CFG_BASE + 0xB4) +#define SCP_SLP_PROTECT_CFG REG32(SCP_CFG_BASE + 0xC8) +#define P_CACHE_SLP_PROT_EN BIT(3) +#define D_CACHE_SLP_PROT_EN BIT(4) +#define SCP_ONE_TIME_LOCK REG32(SCP_CFG_BASE + 0xDC) +#define SCP_SECURE_CTRL REG32(SCP_CFG_BASE + 0xE0) + +#ifdef CHIP_VARIANT_MT8186 +#define JTAG_DBG_REQ_BIT BIT(3) +#define DISABLE_REMAP BIT(31) +#else +#define DISABLE_REMAP BIT(22) +#endif + +#define ENABLE_SPM_MASK_VREQ BIT(28) +#define DISABLE_JTAG BIT(21) +#define DISABLE_AP_TCM BIT(20) +#define SCP_SYS_CTRL REG32(SCP_CFG_BASE + 0xE4) +#define DDREN_FIX_VALUE BIT(28) +#define AUTO_DDREN BIT(18) + +/* Memory remap control */ +/* + * EXT_ADDR3[29:24] remap register for addr msb 31~28 equal to 0x7 + * EXT_ADDR2[21:16] remap register for addr msb 31~28 equal to 0x6 + * EXT_ADDR1[13:8] remap register for addr msb 31~28 equal to 0x3 + * EXT_ADDR0[5:0] remap register for addr msb 31~28 equal to 0x2 + */ +#define SCP_REMAP_CFG1 REG32(SCP_CFG_BASE + 0x120) +/* + * EXT_ADDR7[29:24] remap register for addr msb 31~28 equal to 0xb + * EXT_ADDR6[21:16] remap register for addr msb 31~28 equal to 0xa + * EXT_ADDR5[13:8] remap register for addr msb 31~28 equal to 0x9 + * EXT_ADDR4[5:0] remap register for addr msb 31~28 equal to 0x8 + */ +#define SCP_REMAP_CFG2 REG32(SCP_CFG_BASE + 0x124) +/* + * AUD_ADDR[31:28] remap register for addr msb 31~28 equal to 0xd + * EXT_ADDR10[21:16]remap register for addr msb 31~28 equal to 0xf + * EXT_ADDR9[13:8] remap register for addr msb 31~28 equal to 0xe + * EXT_ADDR8[5:0] remap register for addr msb 31~28 equal to 0xc + */ +#define SCP_REMAP_CFG3 REG32(SCP_CFG_BASE + 0x128) + +#define SCP_REMAP_ADDR_SHIFT 28 +#define SCP_REMAP_ADDR_LSB_MASK (BIT(SCP_REMAP_ADDR_SHIFT) - 1) +#define SCP_REMAP_ADDR_MSB_MASK ((~0) << SCP_REMAP_ADDR_SHIFT) + +/* Cached memory remap control */ +#define SCP_L1_REMAP_CFG0 REG32(SCP_CFG_BASE + 0x12C) +/* + * L1C_EXT_ADDR1[29:16] remap register for addr msb 31~20 equal to 0x401 + * L1C_EXT_ADDR0[13:0] remap register for addr msb 31~20 equal to 0x400 + */ +#define SCP_L1_REMAP_CFG1 REG32(SCP_CFG_BASE + 0x130) +/* + * L1C_EXT_ADDR3[29:16] remap register for addr msb 31~20 equal to 0x403 + * L1C_EXT_ADDR2[13:0] remap register for addr msb 31~20 equal to 0x402 + */ +#define SCP_L1_REMAP_CFG2 REG32(SCP_CFG_BASE + 0x134) +/* + * L1C_EXT_ADDR5[29:16] remap register for addr msb 31~20 equal to 0x405 + * L1C_EXT_ADDR4[13:0] remap register for addr msb 31~20 equal to 0x404 + */ +#define SCP_L1_REMAP_CFG3 REG32(SCP_CFG_BASE + 0x138) +/* + * L1C_EXT_ADDR_OTHER1[13:8] Remap register for addr msb 31 to 28 equal to 0x1 + * L1C_EXT_ADDR_OTHER0[5:0] Remap register for addr msb 31 to 28 equal to 0x0 + * and not overlap with L1C_EXT_ADDR0 to L1C_EXT_ADDR7 + */ +#define SCP_L1_REMAP_OTHER REG32(SCP_CFG_BASE + 0x13C) + +#define SCP_L1_EXT_ADDR_SHIFT 20 +#define SCP_L1_EXT_ADDR_OTHER_SHIFT 28 +#define SCP_L1_EXT_ADDR_OTHER_LSB_MASK (BIT(SCP_REMAP_ADDR_SHIFT) - 1) +#define SCP_L1_EXT_ADDR_OTHER_MSB_MASK ((~0) << SCP_REMAP_ADDR_SHIFT) + +/* Audio/voice FIFO */ +#define SCP_AUDIO_BASE (SCP_CFG_BASE + 0x1000) +#define SCP_VIF_FIFO_EN REG32(SCP_AUDIO_BASE) +#define VIF_FIFO_RSTN (1 << 0) +#define VIF_FIFO_IRQ_EN (1 << 1) +#define VIF_FIFO_SRAM_PWR (1 << 2) +#define VIF_FIFO_RSTN_STATUS (1 << 4) +#define SCP_VIF_FIFO_STATUS REG32(SCP_AUDIO_BASE + 0x04) +#define VIF_FIFO_VALID (1 << 0) +#define VIF_FIFO_FULL (1 << 4) +#define VIF_FIFO_LEVEL(status) (((status) >> 16) & 0xff) +#define VIF_FIFO_MAX 256 +#define SCP_VIF_FIFO_DATA REG32(SCP_AUDIO_BASE + 0x08) +#define SCP_VIF_FIFO_DATA_THRE REG32(SCP_AUDIO_BASE + 0x0C) +/* VIF IRQ status clears on read! */ +#define SCP_VIF_FIFO_IRQ_STATUS REG32(SCP_AUDIO_BASE + 0x10) +/* Audio/voice serial interface */ +#define SCP_RXIF_CFG0 REG32(SCP_AUDIO_BASE + 0x14) +#define RXIF_CFG0_RESET_VAL 0x2A130001 +#define RXIF_AFE_ON (1 << 0) +#define RXIF_SCKINV (1 << 1) +#define RXIF_RG_DL_2_IN_MODE(mode) (((mode)&0xf) << 8) +#define RXIF_RGDL2_AMIC_16K (0x1 << 8) +#define RXIF_RGDL2_DMIC_16K (0x2 << 8) +#define RXIF_RGDL2_DMIC_LP_16K (0x3 << 8) +#define RXIF_RGDL2_AMIC_32K (0x5 << 8) +#define RXIF_RGDL2_MASK (0xf << 8) +#define RXIF_UP8X_RSP(p) (((p)&0x7) << 16) +#define RXIF_RG_RX_READEN (1 << 19) +#define RXIF_MONO (1 << 20) +#define RXIF_RG_CLK_A16P7K_EN(cnt) (((cnt)&0xff) << 24) +#define SCP_RXIF_CFG1 REG32(SCP_AUDIO_BASE + 0x18) +#define RXIF_CFG1_RESET_VAL 0x33180014 +#define RXIF_RG_SYNC_CNT_TBL(t) ((t)&0x1ff) +#define RXIF_RG_SYNC_SEARCH_TBL(t) (((t)&0x1f) << 16) +#define RXIF_RG_SYNC_CHECK_ROUND(r) (((r)&0xf) << 24) +#define RXIF_RG_INSYNC_CHECK_ROUND(r) (((r)&0xf) << 28) +#define SCP_RXIF_CFG2 REG32(SCP_AUDIO_BASE + 0x1C) +#define RXIF_SYNC_WORD(w) ((w)&0xffff) +#define SCP_RXIF_OUT REG32(SCP_AUDIO_BASE + 0x20) +#define SCP_RXIF_STATUS REG32(SCP_AUDIO_BASE + 0x24) +#define SCP_RXIF_IRQ_EN REG32(SCP_AUDIO_BASE + 0x28) + +/* INTC control */ +#define SCP_INTC_BASE (SCP_CFG_BASE + 0x2000) +#define SCP_INTC_IRQ_STATUS REG32(SCP_INTC_BASE) +#define SCP_INTC_IRQ_ENABLE REG32(SCP_INTC_BASE + 0x04) +#define IPC0_IRQ_EN BIT(0) +#define SCP_INTC_IRQ_OUTPUT REG32(SCP_INTC_BASE + 0x08) +#define SCP_INTC_IRQ_WAKEUP REG32(SCP_INTC_BASE + 0x0C) +#define SCP_INTC_NMI REG32(SCP_INTC_BASE + 0x10) +#define SCP_INTC_SPM_WAKEUP REG32(SCP_INTC_BASE + 0x14) +#define SCP_INTC_SPM_WAKEUP_MSB REG32(SCP_INTC_BASE + 0x18) +#define SCP_INTC_UART_RX_IRQ REG32(SCP_INTC_BASE + 0x1C) +#define SCP_INTC_IRQ_STATUS_MSB REG32(SCP_INTC_BASE + 0x80) +#define SCP_INTC_IRQ_ENABLE_MSB REG32(SCP_INTC_BASE + 0x84) +#define SCP_INTC_IRQ_OUTPUT_MSB REG32(SCP_INTC_BASE + 0x88) +#define SCP_INTC_IRQ_WAKEUP_MSB REG32(SCP_INTC_BASE + 0x8C) + +/* Timer */ +#define NUM_TIMERS 6 +#define SCP_TIMER_BASE(n) (SCP_CFG_BASE + 0x3000 + (0x10 * (n))) +#define SCP_TIMER_EN(n) REG32(SCP_TIMER_BASE(n)) +#define SCP_TIMER_RESET_VAL(n) REG32(SCP_TIMER_BASE(n) + 0x04) +#define SCP_TIMER_VAL(n) REG32(SCP_TIMER_BASE(n) + 0x08) +#define SCP_TIMER_IRQ_CTRL(n) REG32(SCP_TIMER_BASE(n) + 0x0C) +#define TIMER_IRQ_ENABLE BIT(0) +#define TIMER_IRQ_STATUS BIT(4) +#define TIMER_IRQ_CLEAR BIT(5) +#define SCP_TIMER_CLK_SEL(n) REG32(SCP_TIMER_BASE(n) + 0x40) +#define TIMER_CLK_32K (0 << 4) +#define TIMER_CLK_26M BIT(4) +#define TIMER_CLK_BCLK (2 << 4) +#define TIMER_CLK_PCLK (3 << 4) +#define TIMER_CLK_MASK (3 << 4) +/* OS timer */ +#define SCP_OSTIMER_BASE (SCP_CFG_BASE + 0x3080) +#define SCP_OSTIMER_CON REG32(SCP_OSTIMER_BASE) +#define SCP_OSTIMER_INIT_L REG32(SCP_OSTIMER_BASE + 0x04) +#define SCP_OSTIMER_INIT_H REG32(SCP_OSTIMER_BASE + 0x08) +#define SCP_OSTIMER_VAL_L REG32(SCP_OSTIMER_BASE + 0x0C) +#define SCP_OSTIMER_VAL_H REG32(SCP_OSTIMER_BASE + 0x10) +#define SCP_OSTIMER_TVAL REG32(SCP_OSTIMER_BASE + 0x14) +#define SCP_OSTIMER_IRQ_ACK REG32(SCP_OSTIMER_BASE + 0x18) +#define OSTIMER_LATCH0_EN BIT(5) +#define OSTIMER_LATCH1_EN BIT(13) +#define OSTIMER_LATCH2_EN BIT(21) +#define SCP_OSTIMER_LATCH_CTRL REG32(SCP_OSTIMER_BASE + 0x20) +#define SCP_OSTIMER_LATCH0_L REG32(SCP_OSTIMER_BASE + 0x24) +#define SCP_OSTIMER_LATCH0_H REG32(SCP_OSTIMER_BASE + 0x28) +#define SCP_OSTIMER_LATCH1_L REG32(SCP_OSTIMER_BASE + 0x2C) +#define SCP_OSTIMER_LATCH1_H REG32(SCP_OSTIMER_BASE + 0x30) +#define SCP_OSTIMER_LATCH2_L REG32(SCP_OSTIMER_BASE + 0x34) +#define SCP_OSTIMER_LATCH2_H REG32(SCP_OSTIMER_BASE + 0x38) + +/* Clock, PMIC wrapper, etc. */ +#define SCP_CLK_BASE (SCP_CFG_BASE + 0x4000) +#define SCP_CLK_SEL REG32(SCP_CLK_BASE) +#define CLK_SEL_SYS_26M 0 +#define CLK_SEL_32K 1 +#define CLK_SEL_ULPOSC_2 2 +#define CLK_SEL_ULPOSC_1 3 + +#define SCP_CLK_EN REG32(SCP_CLK_BASE + 0x04) +#define EN_CLK_SYS BIT(0) /* System clock */ +#define EN_CLK_HIGH BIT(1) /* ULPOSC */ +#define CG_CLK_HIGH BIT(2) +#define EN_SYS_IRQ BIT(16) +#define EN_HIGH_IRQ BIT(17) +#define SCP_CLK_SAFE_ACK REG32(SCP_CLK_BASE + 0x08) +#define SCP_CLK_ACK REG32(SCP_CLK_BASE + 0x0C) +#define SCP_CLK_IRQ_ACK REG32(SCP_CLK_BASE + 0x10) +/* + * System clock counter value. + * CLK_SYS_VAL[9:0] System clock counter initial/reset value. + */ +#define SCP_CLK_SYS_VAL REG32(SCP_CLK_BASE + 0x14) +#define CLK_SYS_VAL_MASK 0x3ff /* 10 bits */ +#define CLK_SYS_VAL(n) ((n)&CLK_SYS_VAL_MASK) +/* + * ULPOSC clock counter value. + * CLK_HIGH_VAL[9:0] ULPOSC clock counter initial/reset value. + */ +#define SCP_CLK_HIGH_VAL REG32(SCP_CLK_BASE + 0x18) +#define CLK_HIGH_VAL_MASK 0x3ff /* 10 bits */ +#define CLK_HIGH_VAL(n) ((n)&CLK_HIGH_VAL_MASK) +#define SCP_CLK_SLOW_SEL REG32(SCP_CLK_BASE + 0x1C) +#define CKSW_SEL_SLOW_MASK 0x3 +#define CKSW_SEL_SLOW_DIV_MASK 0x30 +#define CKSW_SEL_SLOW_SYS_CLK 0 +#define CKSW_SEL_SLOW_32K_CLK 1 +#define CKSW_SEL_SLOW_ULPOSC2_CLK 2 +#define CKSW_SEL_SLOW_ULPOSC1_CLK 3 +/* + * Sleep mode control. + * VREQ_COUNT[7:1] Number of cycles to wait when requesting PMIC to raise the + * voltage after returning from sleep mode. + */ +#define SCP_CLK_SLEEP_CTRL REG32(SCP_CLK_BASE + 0x20) +#define EN_SLEEP_CTRL BIT(0) + +#ifdef CHIP_VARIANT_MT8186 +#define VREQ_COUNTER_MASK 0x7F +#else +#define VREQ_COUNTER_MASK 0xfe +#endif + +#define VREQ_COUNTER_VAL(v) (((v) << 1) & VREQ_COUNTER_MASK) +#define SPM_SLEEP_MODE BIT(8) +#define SPM_SLEEP_MODE_CLK_AO BIT(9) +#define SCP_CLK_DIV_SEL REG32(SCP_CLK_BASE + 0x24) +#define CLK_DIV1 0 +#define CLK_DIV2 1 +#define CLK_DIV4 2 +#define CLK_DIV8 3 +#define SCP_CLK_DEBUG REG32(SCP_CLK_BASE + 0x28) +#define SCP_CLK_SRAM_POWERDOWN REG32(SCP_CLK_BASE + 0x2C) +#define SCP_CLK_GATE REG32(SCP_CLK_BASE + 0x30) +#define CG_TIMER_M BIT(0) +#define CG_TIMER_B BIT(1) +#define CG_MAD_M BIT(2) +#define CG_I2C_M BIT(3) +#define CG_I2C_B BIT(4) +#define CG_GPIO_M BIT(5) +#define CG_AP2P_M BIT(6) +#define CG_UART_M BIT(7) +#define CG_UART_B BIT(8) +#define CG_UART_RSTN BIT(9) +#define CG_UART1_M BIT(10) +#define CG_UART1_B BIT(11) +#define CG_UART1_RSTN BIT(12) +#define CG_SPI0 BIT(13) +#define CG_SPI1 BIT(14) +#define CG_SPI2 BIT(15) +#define CG_DMA_CH0 BIT(16) +#define CG_DMA_CH1 BIT(17) +#define CG_DMA_CH2 BIT(18) +#define CG_DMA_CH3 BIT(19) +#define CG_TWAM BIT(20) +#define CG_CACHE_I_CTRL BIT(21) +#define CG_CACHE_D_CTRL BIT(22) +#define SCP_PMICW_CTRL REG32(SCP_CLK_BASE + 0x34) +#define PMICW_SLEEP_REQ BIT(0) +#define PMICW_SLEEP_ACK BIT(4) +#define PMICW_CLK_MUX BIT(8) +#define PMICW_DCM BIT(9) +#define SCP_SLEEP_WAKE_DEBUG REG32(SCP_CLK_BASE + 0x38) +#define SCP_DCM_EN REG32(SCP_CLK_BASE + 0x3C) +#define SCP_WAKE_CKSW REG32(SCP_CLK_BASE + 0x40) + +#define WAKE_CKSW_SEL_SLOW_MASK 0x30 +#define WAKE_CKSW_SEL_SLOW_DEFAULT 0x10 + +#define WAKE_CKSW_SEL_NORMAL_MASK 0x3 +#define SCP_CLK_UART REG32(SCP_CLK_BASE + 0x44) +#define CLK_UART_SEL_MASK 0x3 +#define CLK_UART_SEL_26M 0x0 +#define CLK_UART_SEL_32K 0x1 +/* This is named ulposc_div_to_26m in datasheet */ +#define CLK_UART_SEL_ULPOSC1_DIV10 0x2 +#define CLK_UART1_SEL_MASK (0x3 << 16) +#define CLK_UART1_SEL_26M (0x0 << 16) +#define CLK_UART1_SEL_32K (0x1 << 16) +/* This is named ulposc_div_to_26m in datasheet */ +#define CLK_UART1_SEL_ULPOSC1_DIV10 (0x2 << 16) +#define SCP_CLK_BCLK REG32(SCP_CLK_BASE + 0x48) +#define CLK_BCLK_SEL_MASK 0x3 +#define CLK_BCLK_SEL_SYS_DIV8 0x0 +#define CLK_BCLK_SEL_32K 0x1 +#define CLK_BCLK_SEL_ULPOSC1_DIV8 0x2 +#define SCP_CLK_SPI_BCK REG32(SCP_CLK_BASE + 0x4C) +#define SCP_CLK_DIV_CNT REG32(SCP_CLK_BASE + 0x50) +#define SCP_CPU_VREQ REG32(SCP_CLK_BASE + 0x54) +#define CPU_VREQ_HW_MODE 0x10001 + +#ifdef CHIP_VARIANT_MT8186 +#define VREQ_SEL BIT(0) +#define VREQ_PMIC_WRAP_SEL BIT(1) +#define VREQ_VALUE BIT(4) +#define VREQ_EXT_SEL BIT(8) +#define VREQ_DVFS_SEL BIT(16) +#define VREQ_DVFS_VALUE BIT(20) +#define VREQ_DVFS_EXT_SEL BIT(24) +#define VREQ_SRCLKEN_SEL BIT(27) +#define VREQ_SRCLKEN_VALUE BIT(28) +#endif + +#define SCP_CLK_CLEAR REG32(SCP_CLK_BASE + 0x58) +#define SCP_CLK_HIGH_CORE REG32(SCP_CLK_BASE + 0x5C) +#define CLK_HIGH_CORE_CG (1 << 1) +#define SCP_SLEEP_IRQ2 REG32(SCP_CLK_BASE + 0x64) +#define SCP_CLK_ON_CTRL REG32(SCP_CLK_BASE + 0x6C) +#define HIGH_AO BIT(0) +#define HIGH_CG_AO BIT(2) +#define HIGH_CORE_AO BIT(4) +#define HIGH_CORE_DIS_SUB BIT(5) +#define HIGH_CORE_CG_AO BIT(6) +#define HIGH_FINAL_VAL_MASK 0x1f00 +#define HIGH_FINAL_VAL_DEFAULT 0x300 +#define SCP_CLK_L1_SRAM_PD REG32(SCP_CLK_BASE + 0x80) +#define SCP_CLK_TCM_TAIL_SRAM_PD REG32(SCP_CLK_BASE + 0x94) + +#ifdef CHIP_VARIANT_MT8186 +#define SCP_CLK_CTRL_GENERAL_CTRL REG32(SCP_CLK_BASE + 0x9C) +#endif + +#define SCP_CLK_SLEEP REG32(SCP_CLK_BASE + 0xA0) +#define SLOW_WAKE_DISABLE 1 +#define SCP_FAST_WAKE_CNT_END REG32(SCP_CLK_BASE + 0xA4) +#define FAST_WAKE_CNT_END_MASK 0xfff +#define FAST_WAKE_CNT_END_DEFAULT 0x18 +#define MEM_CK_CS_ISO_CNT_END_MASK 0x7f0000 + +/* Peripherals */ +#define SCP_I2C0_BASE (SCP_CFG_BASE + 0x5000) +#define SCP_I2C1_BASE (SCP_CFG_BASE + 0x6000) +#define SCP_I2C2_BASE (SCP_CFG_BASE + 0x7000) + +#define SCP_GPIO_BASE (SCP_CFG_BASE + 0x8000) +#define SCP_UART0_BASE (SCP_CFG_BASE + 0x9000) +#define SCP_UART1_BASE (SCP_CFG_BASE + 0xE000) +#define SCP_UART_COUNT 2 + +/* External GPIO interrupt */ +#define SCP_EINT_BASE (SCP_CFG_BASE + 0xA000) +#define SCP_EINT_STATUS REG32_ADDR(SCP_EINT_BASE) +#define SCP_EINT_ACK REG32_ADDR(SCP_EINT_BASE + 0x040) +#define SCP_EINT_MASK_GET REG32_ADDR(SCP_EINT_BASE + 0x080) +#define SCP_EINT_MASK_SET REG32_ADDR(SCP_EINT_BASE + 0x0C0) +#define SCP_EINT_MASK_CLR REG32_ADDR(SCP_EINT_BASE + 0x100) +#define SCP_EINT_SENS_GET REG32_ADDR(SCP_EINT_BASE + 0x140) +#define SCP_EINT_SENS_SET REG32_ADDR(SCP_EINT_BASE + 0x180) +#define SCP_EINT_SENS_CLR REG32_ADDR(SCP_EINT_BASE + 0x1C0) +#define SCP_EINT_SOFT_GET REG32_ADDR(SCP_EINT_BASE + 0x200) +#define SCP_EINT_SOFT_SET REG32_ADDR(SCP_EINT_BASE + 0x240) +#define SCP_EINT_SOFT_CLR REG32_ADDR(SCP_EINT_BASE + 0x280) +#define SCP_EINT_POLARITY_GET REG32_ADDR(SCP_EINT_BASE + 0x300) +#define SCP_EINT_POLARITY_SET REG32_ADDR(SCP_EINT_BASE + 0x340) +#define SCP_EINT_POLARITY_CLR REG32_ADDR(SCP_EINT_BASE + 0x380) +#define SCP_EINT_D0_EN REG32_ADDR(SCP_EINT_BASE + 0x400) +#define SCP_EINT_D1_EN REG32_ADDR(SCP_EINT_BASE + 0x420) +#define SCP_EINT_DBNC_GET REG32_ADDR(SCP_EINT_BASE + 0x500) +#define SCP_EINT_DBNC_SET REG32_ADDR(SCP_EINT_BASE + 0x600) +#define SCP_EINT_DBNC_CLR REG32_ADDR(SCP_EINT_BASE + 0x700) + +#define SCP_PMICWP2P_BASE (SCP_CFG_BASE + 0xB000) +#define PMICW_WACS_CMD REG32(SCP_PMICWP2P_BASE + 0x200) +#define PMICW_WACS_RDATA REG32(SCP_PMICWP2P_BASE + 0x204) +#define PMICW_WACS_VLDCLR REG32(SCP_PMICWP2P_BASE + 0x208) +#define SCP_SPMP2P_BASE (SCP_CFG_BASE + 0xC000) +#define SCP_DMA_BASE (SCP_CFG_BASE + 0xD000) +#define DMA_ACKINT_CHX REG32(SCP_DMA_BASE + 0x20) +#define SCP_SPI0_BASE (SCP_CFG_BASE + 0xF000) +#define SCP_SPI1_BASE (SCP_CFG_BASE + 0x10000) +#define SCP_SPI2_BASE (SCP_CFG_BASE + 0x11000) + +#define CACHE_ICACHE 0 +#define CACHE_DCACHE 1 +#define CACHE_COUNT 2 +#define SCP_CACHE_BASE (SCP_CFG_BASE + 0x14000) +#define SCP_CACHE_SEL(x) (SCP_CACHE_BASE + (x)*0x3000) +#define SCP_CACHE_CON(x) REG32(SCP_CACHE_SEL(x)) +#define SCP_CACHE_CON_MCEN BIT(0) +#define SCP_CACHE_CON_CNTEN0 BIT(2) +#define SCP_CACHE_CON_CNTEN1 BIT(3) +#define SCP_CACHE_CON_CACHESIZE_SHIFT 8 +#define SCP_CACHE_CON_CACHESIZE_MASK (0x3 << SCP_CACHE_CON_CACHESIZE_SHIFT) +#define SCP_CACHE_CON_CACHESIZE_0KB (0x0 << SCP_CACHE_CON_CACHESIZE_SHIFT) +#define SCP_CACHE_CON_CACHESIZE_8KB (0x1 << SCP_CACHE_CON_CACHESIZE_SHIFT) +#define SCP_CACHE_CON_CACHESIZE_16KB (0x2 << SCP_CACHE_CON_CACHESIZE_SHIFT) +#define SCP_CACHE_CON_CACHESIZE_32KB (0x3 << SCP_CACHE_CON_CACHESIZE_SHIFT) +#define SCP_CACHE_CON_WAYEN BIT(10) + +#define SCP_CACHE_OP(x) REG32(SCP_CACHE_SEL(x) + 0x04) +#define SCP_CACHE_OP_EN BIT(0) +#define SCP_CACHE_OP_OP_SHIFT 1 +#define SCP_CACHE_OP_OP_MASK (0xf << SCP_CACHE_OP_OP_SHIFT) + +#define OP_INVALIDATE_ALL_LINES (0x1 << SCP_CACHE_OP_OP_SHIFT) +#define OP_INVALIDATE_ONE_LINE_BY_ADDRESS (0x2 << SCP_CACHE_OP_OP_SHIFT) +#define OP_INVALIDATE_ONE_LINE_BY_SET_WAY (0x4 << SCP_CACHE_OP_OP_SHIFT) +#define OP_CACHE_FLUSH_ALL_LINES (0x9 << SCP_CACHE_OP_OP_SHIFT) +#define OP_CACHE_FLUSH_ONE_LINE_BY_ADDRESS (0xa << SCP_CACHE_OP_OP_SHIFT) +#define OP_CACHE_FLUSH_ONE_LINE_BY_SET_WAY (0xc << SCP_CACHE_OP_OP_SHIFT) + +#define SCP_CACHE_OP_TADDR_SHIFT 5 +#define SCP_CACHE_OP_TADDR_MASK (0x7ffffff << SCP_CACHE_OP_TADDR_SHIFT) +#define SCP_CACHE_LINE_SIZE BIT(SCP_CACHE_OP_TADDR_SHIFT) + +/* Cache statistics */ +#define SCP_CACHE_HCNT0L(x) REG32(SCP_CACHE_SEL(x) + 0x08) +#define SCP_CACHE_HCNT0U(x) REG32(SCP_CACHE_SEL(x) + 0x0c) +#define SCP_CACHE_CCNT0L(x) REG32(SCP_CACHE_SEL(x) + 0x10) +#define SCP_CACHE_CCNT0U(x) REG32(SCP_CACHE_SEL(x) + 0x14) +#define SCP_CACHE_HCNT1L(x) REG32(SCP_CACHE_SEL(x) + 0x18) +#define SCP_CACHE_HCNT1U(x) REG32(SCP_CACHE_SEL(x) + 0x1c) +#define SCP_CACHE_CCNT1L(x) REG32(SCP_CACHE_SEL(x) + 0x20) +#define SCP_CACHE_CCNT1U(x) REG32(SCP_CACHE_SEL(x) + 0x24) + +#define SCP_CACHE_REGION_EN(x) REG32(SCP_CACHE_SEL(x) + 0x2c) + +#define SCP_CACHE_ENTRY_BASE(x) (SCP_CACHE_SEL(x) + 0x2000) +#define SCP_CACHE_ENTRY(x, reg) REG32(SCP_CACHE_ENTRY_BASE(x) + (reg)*4) +#define SCP_CACHE_END_ENTRY_BASE(x) (SCP_CACHE_SEL(x) + 0x2040) +#define SCP_CACHE_END_ENTRY(x, reg) REG32(SCP_CACHE_END_ENTRY_BASE(x) + (reg)*4) +#define SCP_CACHE_ENTRY_C BIT(8) +#define SCP_CACHE_ENTRY_BASEADDR_MASK (0xfffff << 12) + +/* ARMV7 regs */ +#define ARM_SCB_SCR REG32(0xE000ED10) +#define SCR_DEEPSLEEP BIT(2) + +/* AP regs */ +#define AP_BASE 0xA0000000 +#define TOPCK_BASE AP_BASE /* Top clock */ +#define SCP_UART2_BASE (AP_BASE + 0x01002000) /* AP UART0 */ + +/* CLK_CFG_5 regs */ +#define AP_CLK_CFG_5 REG32(TOPCK_BASE + 0x0090) +#define PWRAP_ULPOSC_MASK (0x3000000) +#define CLK26M (0 << 24) +#define OSC_D16 (1 << 24) +#define OSC_D4 (2 << 24) +#define OSC_D8 (3 << 24) +#define AP_CLK_CFG_5_CLR REG32(TOPCK_BASE + 0x0098) +#define PWRAP_ULPOSC_CG BIT(31) + +#ifdef CHIP_VARIANT_MT8186 +/* SCP PLL MUX RG */ +#define CLK_CFG_UPDATE (TOPCK_BASE + 0x0004) +#define SCP_CK_UPDATE_SHFT 1 +#define CLK_CFG_0 (TOPCK_BASE + 0x0040) +#define CLK_CFG_0_SET (TOPCK_BASE + 0x0044) +#define CLK_CFG_0_CLR (TOPCK_BASE + 0x0048) +#define CLK_SCP_SEL_MSK 0x7 +#define CLK_SCP_SEL_SHFT 8 +#endif + +/* OSC meter */ +#ifdef CHIP_VARIANT_MT8186 +#define AP_CLK_MISC_CFG_0 REG32(TOPCK_BASE + 0x0140) +#define AP_CLK_DBG_CFG REG32(TOPCK_BASE + 0x017C) +#else +#define AP_CLK_MISC_CFG_0 REG32(TOPCK_BASE + 0x0104) +#define AP_CLK_DBG_CFG REG32(TOPCK_BASE + 0x010C) +#endif + +#define MISC_METER_DIVISOR_MASK 0xff000000 +#define MISC_METER_DIV_1 0 +#define DBG_MODE_MASK 3 +#define DBG_MODE_SET_CLOCK 0 +#define DBG_BIST_SOURCE_MASK (0x3f << 16) + +#ifdef CHIP_VARIANT_MT8186 +#define DBG_BIST_SOURCE_ULPOSC1 (35 << 16) +#define DBG_BIST_SOURCE_ULPOSC2 (34 << 16) +#else +#define DBG_BIST_SOURCE_ULPOSC1 (0x26 << 16) +#define DBG_BIST_SOURCE_ULPOSC2 (0x25 << 16) +#endif + +#define AP_SCP_CFG_0 REG32(TOPCK_BASE + 0x0220) +#define CFG_FREQ_METER_RUN (1 << 4) +#define CFG_FREQ_METER_ENABLE (1 << 12) +#define AP_SCP_CFG_1 REG32(TOPCK_BASE + 0x0224) +#define CFG_FREQ_COUNTER(CFG1) ((CFG1)&0xFFFF) + +/* GPIO */ +#define AP_GPIO_BASE (AP_BASE + 0x00005000) +/* + * AP_GPIO_DIR + * GPIO input/out direction, 1 bit per pin. + * 0:input 1:output + */ +#define AP_GPIO_DIR(n) REG32(AP_GPIO_BASE + ((n) << 4)) +/* + * AP_GPIO_DOUT, n in [0..5] + * GPIO output level, 1 bit per pin + * 0:low 1:high + */ +#define AP_GPIO_DOUT(n) REG32(AP_GPIO_BASE + 0x100 + ((n) << 4)) +/* + * AP_GPIO_DIN, n in [0..5] + * GPIO input level, 1 bit per pin + * 0:low 1:high + */ +#define AP_GPIO_DIN(n) REG32(AP_GPIO_BASE + 0x200 + ((n) << 4)) +/* + * AP_GPIO_MODE, n in [0..22] + * Pin mode selection, 4 bit per pin + * bit3 - write enable, set to 1 for hw to fetch bit2,1,0. + * bit2-0 - mode 0 ~ 7 + */ +#define AP_GPIO_MODE(n) REG32(AP_GPIO_BASE + 0x300 + ((n) << 4)) +#define AP_GPIO_TRAP REG32(AP_GPIO_BASE + 0x6B0) +#define AP_GPIO_UNIMPLEMENTED REG32(AP_GPIO_BASE + 0x6C0) +#define AP_GPIO_DBG REG32(AP_GPIO_BASE + 0x6D0) +#define AP_GPIO_BANK REG32(AP_GPIO_BASE + 0x6E0) +/* AP_GPIO_SEC, n in [0..5] */ +#define AP_GPIO_SEC(n) REG32(AP_GPIO_BASE + 0xF00 + ((n) << 4)) + +#ifdef CHIP_VARIANT_MT8186 +#define AP_PLL_CON0 REG32(AP_BASE + 0xC000) +#define LTECLKSQ_EN BIT(0) +#define LTECLKSQ_LPF_EN BIT(1) +#define LTECLKSQ_HYS_EN BIT(2) +#define LTECLKSQ_VOD_EN BIT(3) +#define LTECLKSQ_HYS_SEL (0x1 << 4) +#define CLKSQ_RESERVE (0x1 << 10) +#define SSUSB26M_CK2_EN BIT(13) +#define SSUSB26M_CK_EN BIT(14) +#define XTAL26M_CK_EN BIT(15) +#define ULPOSC_CTRL_SEL (0xf << 16) +#endif + +/* + * PLL ULPOSC + * ULPOSC1: AP_ULPOSC_CON[0] AP_ULPOSC_CON[1] + * ULPOSC2: AP_ULPOSC_CON[2] AP_ULPOSC_CON[3] + * osc: 0 for ULPOSC1, 1 for ULPSOC2. + */ +#ifdef CHIP_VARIANT_MT8186 +#define AP_ULPOSC_BASE0 (AP_BASE + 0xC500) +#define AP_ULPOSC_BASE1 (AP_BASE + 0xC504) +#define AP_ULPOSC_CON02(osc) REG32(AP_ULPOSC_BASE0 + (osc)*0x80) +#define AP_ULPOSC_CON13(osc) REG32(AP_ULPOSC_BASE1 + (osc)*0x80) +#else +#define AP_ULPOSC_BASE0 (AP_BASE + 0xC700) +#define AP_ULPOSC_BASE1 (AP_BASE + 0xC704) +#define AP_ULPOSC_CON02(osc) REG32(AP_ULPOSC_BASE0 + (osc)*0x8) +#define AP_ULPOSC_CON13(osc) REG32(AP_ULPOSC_BASE1 + (osc)*0x8) +#endif +/* + * AP_ULPOSC_CON[0,2] + * bit0-5: calibration + * bit6-12: I-band + * bit13-16: F-band + * bit17-22: div + * bit23: CP_EN + * bit24-31: reserved + */ +#ifdef CHIP_VARIANT_MT8186 +#define OSC_CALI_MASK 0x3f +#define OSC_IBAND_SHIFT 6 +#define OSC_FBAND_MASK 0xf +#define OSC_FBAND_SHIFT 13 +#define OSC_DIV_SHIFT 17 +#else +#define OSC_CALI_MSK (0x3f << 0) +#define OSC_CALI_BITS 6 +#define OSC_IBAND_MASK (0x7f << 6) +#define OSC_FBAND_MASK (0x0f << 13) +#define OSC_DIV_MASK (0x1f << 17) +#define OSC_DIV_BITS 5 +#define OSC_RESERVED_MASK (0xff << 24) +#endif + +#define OSC_CP_EN BIT(23) +/* AP_ULPOSC_CON[1,3] */ +#define OSC_MOD_MASK (0x03 << 0) +#define OSC_DIV2_EN BIT(2) + +#define UNIMPLEMENTED_GPIO_BANK 0 + +#ifndef __ASSEMBLER__ + +/* + * Cortex-M4 mod + * Available power saving features: + * 1. FPU freeze - freeze FPU operand when FPU is not used + * 2. LSU gating - gate LSU clock when not LSU operation + * 3. Trace clk disable - gate trace clock + * 4. DCM for CPU stall - gate CPU clock when CPU stall + */ +#define CM4_MODIFICATION REG32(0xE00FE000) +#define CM4_DCM_FEATURE REG32(0xE00FE004) +/* UART, 16550 compatible */ +#define SCP_UART_BASE(n) CONCAT3(SCP_UART, n, _BASE) +#define UART_REG(n, offset) REG32_ADDR(SCP_UART_BASE(n))[offset] +#define UART_IRQ(n) CONCAT2(SCP_IRQ_UART, n) +#define UART_RX_IRQ(n) CONCAT3(SCP_IRQ_UART, n, _RX) + +/* Watchdog */ +#define SCP_WDT_BASE (SCP_CFG_BASE + 0x84) +#define SCP_WDT_REG(offset) REG32(SCP_WDT_BASE + offset) +#define SCP_WDT_CFG SCP_WDT_REG(0) +#define SCP_WDT_FREQ 33825 +#define SCP_WDT_MAX_PERIOD 0xFFFFF /* 31 seconds */ +#define SCP_WDT_PERIOD(ms) (SCP_WDT_FREQ * (ms) / 1000) +#define SCP_WDT_ENABLE BIT(31) +#define SCP_WDT_RELOAD SCP_WDT_REG(4) +#define SCP_WDT_RELOAD_VALUE 1 + +#endif /* !__ASSEMBLER__ */ +#endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/mt_scp/mt818x/serial_reg.h b/chip/mt_scp/mt818x/serial_reg.h new file mode 100644 index 0000000000..8dd2864a98 --- /dev/null +++ b/chip/mt_scp/mt818x/serial_reg.h @@ -0,0 +1,90 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * UART register map + */ + +#ifndef __CROS_EC_SERIAL_REG_H +#define __CROS_EC_SERIAL_REG_H + +#include "registers.h" + +/* Number of hardware ports */ +#define HW_UART_PORTS 2 + +/* DLAB (Divisor Latch Access Bit) == 0 */ + +/* Data register + * (Read) Rcvr buffer register + * (Write) Xmit holding register + */ +#define UART_DATA(n) UART_REG(n, 0) +/* (Write) Interrupt enable register */ +#define UART_IER(n) UART_REG(n, 1) +#define UART_IER_RDI BIT(0) /* Recv data int */ +#define UART_IER_THRI BIT(1) /* Xmit holding register int */ +#define UART_IER_RLSI BIT(2) /* Rcvr line status int */ +#define UART_IER_MSI BIT(3) /* Modem status int */ +/* (Read) Interrupt ID register */ +#define UART_IIR(n) UART_REG(n, 2) +#define UART_IIR_NO_INT BIT(0) /* No int pending */ +#define UART_IIR_ID_MASK 0x0e /* Interrupt ID mask */ +#define UART_IIR_MSI 0x00 +#define UART_IIR_THRI 0x02 +#define UART_IIR_RDI 0x04 +#define UART_IIR_RLSI 0x06 +#define UART_IIR_BUSY 0x07 /* DW APB busy */ +/* (Write) FIFO control register */ +#define UART_FCR(n) UART_REG(n, 2) +#define UART_FCR_ENABLE_FIFO BIT(0) /* Enable FIFO */ +#define UART_FCR_CLEAR_RCVR BIT(1) /* Clear rcvr FIFO */ +#define UART_FCR_CLEAR_XMIT BIT(2) /* Clear xmit FIFO */ +#define UART_FCR_DMA_SELECT BIT(3) +/* FIFO trigger levels */ +#define UART_FCR_T_TRIG_00 0x00 +#define UART_FCR_T_TRIG_01 0x10 +#define UART_FCR_T_TRIG_10 0x20 +#define UART_FCR_T_TRIG_11 0x30 +#define UART_FCR_R_TRIG_00 0x00 +#define UART_FCR_R_TRIG_01 0x40 +#define UART_FCR_R_TRIG_10 0x80 +#define UART_FCR_R_TRIG_11 0x80 +/* (Write) Line control register */ +#define UART_LCR(n) UART_REG(n, 3) +#define UART_LCR_WLEN5 0 /* Word length 5 bits */ +#define UART_LCR_WLEN6 1 +#define UART_LCR_WLEN7 2 +#define UART_LCR_WLEN8 3 +#define UART_LCR_STOP BIT(2) /* Stop bits: 1bit, 2bits */ +#define UART_LCR_PARITY BIT(3) /* Parity enable */ +#define UART_LCR_EPAR BIT(4) /* Even parity */ +#define UART_LCR_SPAR BIT(5) /* Stick parity */ +#define UART_LCR_SBC BIT(6) /* Set break control */ +#define UART_LCR_DLAB BIT(7) /* Divisor latch access */ +/* (Write) Modem control register */ +#define UART_MCR(n) UART_REG(n, 4) +/* (Read) Line status register */ +#define UART_LSR(n) UART_REG(n, 5) +#define UART_LSR_DR BIT(0) /* Data ready */ +#define UART_LSR_OE BIT(1) /* Overrun error */ +#define UART_LSR_PE BIT(2) /* Parity error */ +#define UART_LSR_FE BIT(3) /* Frame error */ +#define UART_LSR_BI BIT(4) /* Break interrupt */ +#define UART_LSR_THRE BIT(5) /* Xmit-hold-register empty */ +#define UART_LSR_TEMT BIT(6) /* Xmit empty */ +#define UART_LSR_FIFOE BIT(7) /* FIFO error */ + +/* DLAB == 1 */ + +/* (Write) Divisor latch */ +#define UART_DLL(n) UART_REG(n, 0) /* Low */ +#define UART_DLH(n) UART_REG(n, 1) /* High */ + +/* MTK extension */ +#define UART_HIGHSPEED(n) UART_REG(n, 9) +#define UART_SAMPLE_COUNT(n) UART_REG(n, 10) +#define UART_SAMPLE_POINT(n) UART_REG(n, 11) +#define UART_RATE_FIX(n) UART_REG(n, 13) + +#endif /* __CROS_EC_SERIAL_REG_H */ diff --git a/chip/mt_scp/mt818x/system.c b/chip/mt_scp/mt818x/system.c new file mode 100644 index 0000000000..8bf523c0f7 --- /dev/null +++ b/chip/mt_scp/mt818x/system.c @@ -0,0 +1,177 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* System : hardware specific implementation */ + +#include "builtin/assert.h" +#include "clock_chip.h" +#include "console.h" +#include "cpu.h" +#include "cros_version.h" +#include "flash.h" +#include "hooks.h" +#include "host_command.h" +#include "memmap.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "util.h" +#include "watchdog.h" + +/* + * SCP_GPR[0] b15-b0 - scratchpad + * SCP_GPR[0] b31-b16 - saved_flags + */ + +int system_set_scratchpad(uint32_t value) +{ + /* Check if value fits in 16 bits */ + if (value & 0xffff0000) + return EC_ERROR_INVAL; + + SCP_GPR[0] = (SCP_GPR[0] & 0xffff0000) | value; + + return EC_SUCCESS; +} + +int system_get_scratchpad(uint32_t *value) +{ + *value = SCP_GPR[0] & 0xffff; + return EC_SUCCESS; +} + +const char *system_get_chip_vendor(void) +{ + return "mtk"; +} + +const char *system_get_chip_name(void) +{ + /* Support only SCP_A for now */ + return "scp_a"; +} + +const char *system_get_chip_revision(void) +{ + return ""; +} + +void chip_pre_init(void) +{ +} + +static void scp_cm4_mod(void) +{ + CM4_MODIFICATION = 3; + CM4_DCM_FEATURE = 3; +} + +static void scp_enable_pirq(void) +{ + /* Enable all peripheral to SCP IRQ, except IPC0. */ + SCP_INTC_IRQ_ENABLE = 0xFFFFFFFE; + SCP_INTC_IRQ_ENABLE_MSB = 0xFFFFFFFF; +} + +void system_pre_init(void) +{ + /* CM4 Modification */ + scp_cm4_mod(); + + /* Clock */ + scp_enable_clock(); + + /* Peripheral IRQ */ + scp_enable_pirq(); + /* Init dram mapping (and cache) */ + scp_memmap_init(); + /* Disable jump (mt_scp has only RW) and enable MPU. */ + system_disable_jump(); +} + +void system_reset(int flags) +{ + uint32_t save_flags = 0; + + /* Disable interrupts to avoid task swaps during reboot */ + interrupt_disable(); + + /* Save current reset reasons if necessary */ + if (flags & SYSTEM_RESET_PRESERVE_FLAGS) + save_flags = system_get_reset_flags() | EC_RESET_FLAG_PRESERVED; + + if (flags & SYSTEM_RESET_LEAVE_AP_OFF) + save_flags |= EC_RESET_FLAG_AP_OFF; + + /* Remember that the software asked us to hard reboot */ + if (flags & SYSTEM_RESET_HARD) + save_flags |= EC_RESET_FLAG_HARD; + + /* Reset flags are 32-bits, but save only 16 bits. */ + ASSERT(!(save_flags >> 16)); + SCP_GPR[0] = (save_flags << 16) | (SCP_GPR[0] & 0xffff); + + /* SCP can not hard reset itself */ + ASSERT(!(flags & SYSTEM_RESET_HARD)); + + if (flags & SYSTEM_RESET_WAIT_EXT) { + int i; + + /* Wait 10 seconds for external reset */ + for (i = 0; i < 1000; i++) { + watchdog_reload(); + udelay(10000); + } + } + + /* Set watchdog timer to small value, and spin wait for watchdog reset + */ + SCP_WDT_CFG = 0; + SCP_WDT_CFG = SCP_WDT_ENABLE | SCP_WDT_PERIOD(1); + watchdog_reload(); + while (1) + ; +} + +static void check_reset_cause(void) +{ + uint32_t flags = 0; + uint32_t raw_reset_cause = SCP_GPR[1]; + + /* Set state to power-on */ + SCP_PWRON_STATE = PWRON_DEFAULT; + + if ((raw_reset_cause & 0xffff0000) == PWRON_DEFAULT) { + /* Reboot */ + if (raw_reset_cause & PWRON_WATCHDOG) + flags |= EC_RESET_FLAG_WATCHDOG; + else if (raw_reset_cause & PWRON_RESET) + flags |= EC_RESET_FLAG_POWER_ON; + else + flags |= EC_RESET_FLAG_OTHER; + } else { + /* Power lost restart */ + flags |= EC_RESET_FLAG_POWER_ON; + } + system_set_reset_flags(SCP_GPR[0] >> 16); + SCP_GPR[0] &= 0xffff; +} + +int system_is_reboot_warm(void) +{ + const uint32_t cold_flags = + EC_RESET_FLAG_RESET_PIN | EC_RESET_FLAG_POWER_ON | + EC_RESET_FLAG_WATCHDOG | EC_RESET_FLAG_HARD | + EC_RESET_FLAG_SOFT | EC_RESET_FLAG_HIBERNATE; + + check_reset_cause(); + + return !(system_get_reset_flags() & cold_flags); +} + +int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) +{ + return EC_ERROR_INVAL; +} diff --git a/chip/mt_scp/mt818x/uart.c b/chip/mt_scp/mt818x/uart.c new file mode 100644 index 0000000000..6bcfa89d9b --- /dev/null +++ b/chip/mt_scp/mt818x/uart.c @@ -0,0 +1,178 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SCP UART module */ + +#include "clock_chip.h" +#include "console.h" +#include "gpio.h" +#include "registers.h" +#include "serial_reg.h" +#include "system.h" +#include "task.h" +#include "uart.h" +#include "util.h" + +/* Console UART index */ +#define UARTN CONFIG_UART_CONSOLE +#define UART_IDLE_WAIT_US 500 + +static uint8_t uart_done, tx_started; + +int uart_init_done(void) +{ + /* + * TODO: AP UART support + * When access AP UART port, wait for AP peripheral clock + */ + return uart_done; +} + +void uart_tx_start(void) +{ + tx_started = 1; + + /* AP UART mode doesn't support interrupt */ + if (UARTN >= SCP_UART_COUNT) + return; + + if (UART_IER(UARTN) & UART_IER_THRI) + return; + disable_sleep(SLEEP_MASK_UART); + UART_IER(UARTN) |= UART_IER_THRI; +} + +void uart_tx_stop(void) +{ + tx_started = 0; + + /* AP UART mode doesn't support interrupt */ + if (UARTN >= SCP_UART_COUNT) + return; + + UART_IER(UARTN) &= ~UART_IER_THRI; + enable_sleep(SLEEP_MASK_UART); +} + +void uart_tx_flush(void) +{ + while (!(UART_LSR(UARTN) & UART_LSR_TEMT)) + ; +} + +int uart_tx_ready(void) +{ + /* Check xmit FIFO empty */ + return UART_LSR(UARTN) & UART_LSR_THRE; +} + +int uart_rx_available(void) +{ + /* Check rcvr data ready */ + return UART_LSR(UARTN) & UART_LSR_DR; +} + +void uart_write_char(char c) +{ + while (!uart_tx_ready()) + ; + + UART_DATA(UARTN) = c; +} + +int uart_read_char(void) +{ + return UART_DATA(UARTN); +} + +void uart_process(void) +{ + uart_process_input(); + uart_process_output(); +} + +#if (UARTN < SCP_UART_COUNT) +DECLARE_IRQ(UART_IRQ(UARTN), uart_interrupt, 2); +static void uart_interrupt(void) +{ + uint8_t ier; + + task_clear_pending_irq(UART_IRQ(UARTN)); + uart_process(); + ier = UART_IER(UARTN); + UART_IER(UARTN) = 0; + UART_IER(UARTN) = ier; +} + +DECLARE_IRQ(UART_RX_IRQ(UARTN), uart_rx_interrupt, 2); +static void uart_rx_interrupt(void) +{ + uint8_t ier; + + task_clear_pending_irq(UART_RX_IRQ(UARTN)); + SCP_INTC_UART_RX_IRQ &= ~BIT(UARTN); + uart_process(); + ier = UART_IER(UARTN); + UART_IER(UARTN) = 0; + UART_IER(UARTN) = ier; + SCP_INTC_UART_RX_IRQ |= 1 << UARTN; +} +#endif + +void uart_task(void) +{ +#if (UARTN >= SCP_UART_COUNT) + while (1) { + if (uart_rx_available() || tx_started) + uart_process(); + else + task_wait_event(UART_IDLE_WAIT_US); + } +#endif +} + +void uart_init(void) +{ + const uint32_t baud_rate = CONFIG_UART_BAUD_RATE; + /* + * UART clock source is set to ULPOSC1 / 10 below. + * + * TODO(b:134035444): We could get slightly more precise frequency by + * using the _measured_ ULPOSC1 frequency (instead of the target). + */ + const uint32_t uart_clock = ULPOSC1_CLOCK_MHZ * 1000 / 10 * 1000; + const uint32_t div = DIV_ROUND_NEAREST(uart_clock, baud_rate * 16); + + /* Init clock */ +#if UARTN == 0 + SCP_CLK_UART = CLK_UART_SEL_ULPOSC1_DIV10; + SCP_CLK_GATE |= CG_UART_M | CG_UART_B | CG_UART_RSTN; +#elif UARTN == 1 + SCP_CLK_UART = CLK_UART1_SEL_ULPOSC1_DIV10; + SCP_CLK_GATE |= CG_UART1_M | CG_UART1_B | CG_UART1_RSTN; +#endif + + /* Init and clear FIFO */ + UART_FCR(UARTN) = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT; + /* Line control: parity none, 8 bit, 1 stop bit */ + UART_LCR(UARTN) = UART_LCR_WLEN8; + /* For baud rate <= 115200 */ + UART_HIGHSPEED(UARTN) = 0; + /* DLAB = 1 and update DLL DLH */ + UART_LCR(UARTN) |= UART_LCR_DLAB; + UART_DLL(UARTN) = div & 0xff; + UART_DLH(UARTN) = (div >> 8) & 0xff; + UART_LCR(UARTN) &= ~UART_LCR_DLAB; + UART_IER(UARTN) |= UART_IER_RDI; + +#if (UARTN < SCP_UART_COUNT) + task_enable_irq(UART_IRQ(UARTN)); + task_enable_irq(UART_RX_IRQ(UARTN)); + /* UART RX IRQ needs an extra enable */ + SCP_INTC_UART_RX_IRQ |= 1 << UARTN; +#endif + uart_done = 1; +} diff --git a/chip/mt_scp/mt818x/video.c b/chip/mt_scp/mt818x/video.c new file mode 100644 index 0000000000..10ea586575 --- /dev/null +++ b/chip/mt_scp/mt818x/video.c @@ -0,0 +1,19 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "video.h" + +uint32_t video_get_enc_capability(void) +{ + /* not support 4K */ + return 0; +} + +uint32_t video_get_dec_capability(void) +{ + return VDEC_CAP_MM21 | VDEC_CAP_4K_DISABLED | VDEC_CAP_H264_SLICE | + VDEC_CAP_VP8_FRAME | VDEC_CAP_VP9_FRAME; +} diff --git a/chip/mt_scp/mt818x/video.h b/chip/mt_scp/mt818x/video.h new file mode 100644 index 0000000000..feb2215cfd --- /dev/null +++ b/chip/mt_scp/mt818x/video.h @@ -0,0 +1,31 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_VIDEO_H +#define __CROS_EC_VIDEO_H + +#include "common.h" + +/* + * Video decoder supported capability + */ +#define VDEC_CAP_4K_DISABLED BIT(4) +#define VDEC_CAP_MM21 BIT(5) +#define VDEC_CAP_MT21C BIT(6) +#define VDEC_CAP_H264_SLICE BIT(8) +#define VDEC_CAP_VP8_FRAME BIT(9) +#define VDEC_CAP_VP9_FRAME BIT(10) +#define VDEC_CAP_IRQ_IN_SCP BIT(16) + +/* + * Video encoder supported capability: + * BIT(0): enable 4K + */ +#define VENC_CAP_4K BIT(0) + +uint32_t video_get_enc_capability(void); +uint32_t video_get_dec_capability(void); + +#endif /* #ifndef __CROS_EC_VIDEO_H */ diff --git a/chip/mt_scp/mt818x/watchdog.c b/chip/mt_scp/mt818x/watchdog.c new file mode 100644 index 0000000000..efadeab0fd --- /dev/null +++ b/chip/mt_scp/mt818x/watchdog.c @@ -0,0 +1,33 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Watchdog driver */ + +#include "common.h" +#include "hooks.h" +#include "panic.h" +#include "registers.h" +#include "watchdog.h" + +void watchdog_reload(void) +{ + SCP_WDT_RELOAD = SCP_WDT_RELOAD_VALUE; +} +DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); + +int watchdog_init(void) +{ + const uint32_t watchdog_timeout = + SCP_WDT_PERIOD(CONFIG_WATCHDOG_PERIOD_MS); + + /* Disable watchdog */ + SCP_WDT_CFG = 0; + /* Enable watchdog */ + SCP_WDT_CFG = SCP_WDT_ENABLE | watchdog_timeout; + /* Reload watchdog */ + watchdog_reload(); + + return EC_SUCCESS; +} diff --git a/chip/mt_scp/mt8192/build.mk b/chip/mt_scp/mt8192/build.mk new file mode 100644 index 0000000000..c188ea6d17 --- /dev/null +++ b/chip/mt_scp/mt8192/build.mk @@ -0,0 +1,9 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Required chip modules +chip-y+=$(CHIP_VARIANT)/uart.o +chip-y+=$(CHIP_VARIANT)/clock.o +chip-y+=$(CHIP_VARIANT)/video.o diff --git a/chip/mt_scp/mt8192/clock.c b/chip/mt_scp/mt8192/clock.c new file mode 100644 index 0000000000..62339dae5f --- /dev/null +++ b/chip/mt_scp/mt8192/clock.c @@ -0,0 +1,387 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Clocks, PLL and power settings */ + +#include "clock.h" +#include "common.h" +#include "console.h" +#include "csr.h" +#include "ec_commands.h" +#include "power.h" +#include "registers.h" +#include "timer.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) + +enum scp_clock_source { + SCP_CLK_26M = CLK_SW_SEL_26M, + SCP_CLK_32K = CLK_SW_SEL_32K, + SCP_CLK_ULPOSC2 = CLK_SW_SEL_ULPOSC2, + SCP_CLK_ULPOSC1 = CLK_SW_SEL_ULPOSC1, +}; + +static struct opp_ulposc_cfg { + uint32_t osc; + uint32_t div; + uint32_t fband; + uint32_t mod; + uint32_t cali; + uint32_t target_mhz; +} opp[] = { + { + .osc = 1, + .target_mhz = 196, + .div = 20, + .fband = 10, + .mod = 3, + .cali = 64, + }, + { + .osc = 0, + .target_mhz = 260, + .div = 14, + .fband = 2, + .mod = 0, + .cali = 64, + }, + { + .osc = 1, + .target_mhz = 280, + .div = 20, + .fband = 2, + .mod = 0, + .cali = 64, + }, + { + .osc = 1, + .target_mhz = 360, + .div = 20, + .fband = 10, + .mod = 0, + .cali = 64, + }, +}; + +static inline void clock_busy_udelay(int usec) +{ + /* + * Delaying by busy-looping, for place that can't use udelay because of + * the clock not configured yet. The value 28 is chosen approximately + * from experiment. + * + * `volatile' in order to avoid compiler to optimize the function out + * (otherwise, the function will be eliminated). + */ + volatile int i = usec * 28; + + while (--i) + ; +} + +static void clock_ulposc_config_default(struct opp_ulposc_cfg *opp) +{ + unsigned int val = 0; + + /* set div */ + val |= opp->div << OSC_DIV_SHIFT; + /* set F-band; I-band = 82 */ + val |= (opp->fband << OSC_FBAND_SHIFT) | (82 << OSC_IBAND_SHIFT); + /* set calibration */ + val |= opp->cali; + /* set control register 0 */ + AP_ULPOSC_CON0(opp->osc) = val; + + /* set mod */ + val = opp->mod << OSC_MOD_SHIFT; + /* rsv2 = 0, rsv1 = 41, cali_32k = 0 */ + val |= 41 << OSC_RSV1_SHIFT; + /* set control register 1 */ + AP_ULPOSC_CON1(opp->osc) = val; + + /* bias = 64 */ + AP_ULPOSC_CON2(opp->osc) = 64; +} + +static void clock_ulposc_config_cali(struct opp_ulposc_cfg *opp, + uint32_t cali_val) +{ + uint32_t val; + + val = AP_ULPOSC_CON0(opp->osc); + val &= ~OSC_CALI_MASK; + val |= cali_val; + AP_ULPOSC_CON0(opp->osc) = val; + + clock_busy_udelay(50); +} + +static uint32_t clock_ulposc_measure_freq(uint32_t osc) +{ + uint32_t result = 0; + int cnt; + + /* before select meter clock input, bit[1:0] = b00 */ + AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_MODE_MASK) | DBG_MODE_SET_CLOCK; + + /* select source, bit[21:16] = clk_src */ + AP_CLK_DBG_CFG = + (AP_CLK_DBG_CFG & ~DBG_BIST_SOURCE_MASK) | + (osc == 0 ? DBG_BIST_SOURCE_ULPOSC1 : DBG_BIST_SOURCE_ULPOSC2); + + /* set meter divisor to 1, bit[31:24] = b00000000 */ + AP_CLK_MISC_CFG_0 = (AP_CLK_MISC_CFG_0 & ~MISC_METER_DIVISOR_MASK) | + MISC_METER_DIV_1; + + /* enable frequency meter, without start */ + AP_SCP_CFG_0 |= CFG_FREQ_METER_ENABLE; + + /* trigger frequency meter start */ + AP_SCP_CFG_0 |= CFG_FREQ_METER_RUN; + + /* + * Frequency meter counts cycles in 1 / (26 * 1024) second period. + * freq_in_hz = freq_counter * 26 * 1024 + * + * The hardware takes 38us to count cycles. Delay up to 100us, + * as clock_busy_udelay may not be accurate when sysclk is not 26Mhz + * (e.g. when recalibrating/measuring after boot). + */ + for (cnt = 100; cnt > 0; --cnt) { + clock_busy_udelay(1); + if (!(AP_SCP_CFG_0 & CFG_FREQ_METER_RUN)) { + result = CFG_FREQ_COUNTER(AP_SCP_CFG_1); + break; + } + } + + /* disable freq meter */ + AP_SCP_CFG_0 &= ~CFG_FREQ_METER_ENABLE; + + return result; +} + +#define CAL_MIS_RATE 40 +static int clock_ulposc_is_calibrated(struct opp_ulposc_cfg *opp) +{ + uint32_t curr, target; + + curr = clock_ulposc_measure_freq(opp->osc); + target = opp->target_mhz * 1024 / 26; + + /* check if calibrated value is in the range of target value +- 4% */ + if (curr > (target * (1000 - CAL_MIS_RATE) / 1000) && + curr < (target * (1000 + CAL_MIS_RATE) / 1000)) + return 1; + else + return 0; +} + +static uint32_t clock_ulposc_process_cali(struct opp_ulposc_cfg *opp) +{ + uint32_t current_val = 0; + uint32_t target_val = opp->target_mhz * 1024 / 26; + uint32_t middle, min = 0, max = OSC_CALI_MASK; + uint32_t diff_by_min, diff_by_max, cal_result; + + do { + middle = (min + max) / 2; + if (middle == min) + break; + + clock_ulposc_config_cali(opp, middle); + current_val = clock_ulposc_measure_freq(opp->osc); + + if (current_val > target_val) + max = middle; + else + min = middle; + } while (min <= max); + + clock_ulposc_config_cali(opp, min); + current_val = clock_ulposc_measure_freq(opp->osc); + if (current_val > target_val) + diff_by_min = current_val - target_val; + else + diff_by_min = target_val - current_val; + + clock_ulposc_config_cali(opp, max); + current_val = clock_ulposc_measure_freq(opp->osc); + if (current_val > target_val) + diff_by_max = current_val - target_val; + else + diff_by_max = target_val - current_val; + + if (diff_by_min < diff_by_max) + cal_result = min; + else + cal_result = max; + + clock_ulposc_config_cali(opp, cal_result); + if (!clock_ulposc_is_calibrated(opp)) + assert(0); + + return cal_result; +} + +static void clock_high_enable(int osc) +{ + /* enable high speed clock */ + SCP_CLK_ENABLE |= CLK_HIGH_EN; + + switch (osc) { + case 0: + /* after 150us, enable ULPOSC */ + clock_busy_udelay(150); + SCP_CLK_ENABLE |= CLK_HIGH_CG; + break; + case 1: + /* turn off ULPOSC2 high-core-disable switch */ + SCP_CLK_ON_CTRL &= ~HIGH_CORE_DIS_SUB; + /* after 150us, turn on ULPOSC2 high core clock gate */ + clock_busy_udelay(150); + SCP_CLK_HIGH_CORE_CG |= HIGH_CORE_CG; + clock_busy_udelay(50); + break; + default: + break; + } +} + +static void clock_high_disable(int osc) +{ + switch (osc) { + case 0: + SCP_CLK_ENABLE &= ~CLK_HIGH_CG; + clock_busy_udelay(50); + SCP_CLK_ENABLE &= ~CLK_HIGH_EN; + clock_busy_udelay(50); + break; + case 1: + SCP_CLK_HIGH_CORE_CG &= ~HIGH_CORE_CG; + clock_busy_udelay(50); + SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB; + clock_busy_udelay(50); + break; + default: + break; + } +} + +static void clock_calibrate_ulposc(struct opp_ulposc_cfg *opp) +{ + /* + * ULPOSC1(osc=0) is already + * - calibrated + * - enabled in coreboot + * - used by pmic wrapper + */ + if (opp->osc != 0) { + clock_high_disable(opp->osc); + clock_ulposc_config_default(opp); + clock_high_enable(opp->osc); + } + + /* Calibrate only if it is not accurate enough. */ + if (!clock_ulposc_is_calibrated(opp)) + opp->cali = clock_ulposc_process_cali(opp); + +#ifdef DEBUG + CPRINTF("osc:%u, target=%uMHz, cal:%u\n", opp->osc, opp->target_mhz, + opp->cali); +#endif +} + +static void clock_select_clock(enum scp_clock_source src) +{ + /* + * DIV2 divider takes precedence over clock selection to prevent + * over-clocking. + */ + if (src == SCP_CLK_ULPOSC1) + SCP_CLK_DIV_SEL = CLK_DIV_SEL2; + + SCP_CLK_SW_SEL = src; + + if (src != SCP_CLK_ULPOSC1) + SCP_CLK_DIV_SEL = CLK_DIV_SEL1; +} + +__override void +power_chipset_handle_host_sleep_event(enum host_sleep_event state, + struct host_sleep_event_context *ctx) +{ + if (state == HOST_SLEEP_EVENT_S3_SUSPEND) { + CPRINTS("AP suspend"); + clock_select_clock(SCP_CLK_ULPOSC1); + } else if (state == HOST_SLEEP_EVENT_S3_RESUME) { + CPRINTS("AP resume"); + clock_select_clock(SCP_CLK_ULPOSC2); + } +} + +void clock_init(void) +{ + int i; + + /* select default 26M system clock */ + clock_select_clock(SCP_CLK_26M); + + /* set VREQ to HW mode */ + SCP_CPU_VREQ_CTRL = VREQ_SEL | VREQ_DVFS_SEL; + SCP_CLK_CTRL_GENERAL_CTRL &= ~VREQ_PMIC_WRAP_SEL; + SCP_SEC_CTRL &= ~VREQ_SECURE_DIS; + + /* set DDREN to auto mode */ + SCP_SYS_CTRL |= AUTO_DDREN; + + /* set settle time */ + SCP_CLK_SYS_VAL = (SCP_CLK_SYS_VAL & ~CLK_SYS_VAL_MASK) | + CLK_SYS_VAL_VAL(1); + SCP_CLK_HIGH_VAL = (SCP_CLK_HIGH_VAL & ~CLK_HIGH_VAL_MASK) | + CLK_HIGH_VAL_VAL(1); + SCP_SLEEP_CTRL = (SCP_SLEEP_CTRL & ~VREQ_COUNT_MASK) | + VREQ_COUNT_VAL(1); + + /* turn off ULPOSC2 */ + SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB; + + /* calibrate ULPOSC */ + for (i = 0; i < ARRAY_SIZE(opp); ++i) + clock_calibrate_ulposc(&opp[i]); + + /* select ULPOSC2 high speed CPU clock */ + clock_select_clock(SCP_CLK_ULPOSC2); + + /* select BCLK to use ULPOSC1 / 8 = 260MHz / 8 = 32.5MHz */ + SCP_BCLK_CK_SEL = BCLK_CK_SEL_ULPOSC_DIV8; + + /* enable default clock gate */ + SCP_SET_CLK_CG |= CG_DMA_CH3 | CG_DMA_CH2 | CG_DMA_CH1 | CG_DMA_CH0 | + CG_I2C_MCLK | CG_MAD_MCLK | CG_AP2P_MCLK; +} + +#ifdef DEBUG +int command_ulposc(int argc, const char *argv[]) +{ + int i; + + for (i = 0; i <= 1; ++i) + ccprintf("ULPOSC%u frequency: %u kHz\n", i + 1, + clock_ulposc_measure_freq(i) * 26 * 1000 / 1024); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[ulposc]", + "Measure ULPOSC frequency"); +#endif + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mt_scp/mt8192/clock_regs.h b/chip/mt_scp/mt8192/clock_regs.h new file mode 100644 index 0000000000..7e1f77e92d --- /dev/null +++ b/chip/mt_scp/mt8192/clock_regs.h @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SCP clock module registers */ + +#ifndef __CROS_EC_CLOCK_REGS_H +#define __CROS_EC_CLOCK_REGS_H + +/* clock source select */ +#define SCP_CLK_SW_SEL REG32(SCP_CLK_CTRL_BASE + 0x0000) +#define CLK_SW_SEL_26M 0 +#define CLK_SW_SEL_32K 1 +#define CLK_SW_SEL_ULPOSC2 2 +#define CLK_SW_SEL_ULPOSC1 3 +#define SCP_CLK_ENABLE REG32(SCP_CLK_CTRL_BASE + 0x0004) +#define CLK_HIGH_EN BIT(1) /* ULPOSC */ +#define CLK_HIGH_CG BIT(2) +/* clock general control */ +#define SCP_CLK_CTRL_GENERAL_CTRL REG32(SCP_CLK_CTRL_BASE + 0x009C) +#define VREQ_PMIC_WRAP_SEL (0x2) + +/* TOPCK clk */ +#define TOPCK_BASE AP_REG_BASE +#define AP_CLK_MISC_CFG_0 REG32(TOPCK_BASE + 0x0140) +#define MISC_METER_DIVISOR_MASK 0xff000000 +#define MISC_METER_DIV_1 0 +/* OSC meter */ +#define AP_CLK_DBG_CFG REG32(TOPCK_BASE + 0x017C) +#define DBG_MODE_MASK 3 +#define DBG_MODE_SET_CLOCK 0 +#define DBG_BIST_SOURCE_MASK (0x3f << 16) +#define DBG_BIST_SOURCE_ULPOSC1 (0x25 << 16) +#define DBG_BIST_SOURCE_ULPOSC2 (0x24 << 16) +#define AP_SCP_CFG_0 REG32(TOPCK_BASE + 0x0220) +#define CFG_FREQ_METER_RUN BIT(4) +#define CFG_FREQ_METER_ENABLE BIT(12) +#define AP_SCP_CFG_1 REG32(TOPCK_BASE + 0x0224) +#define CFG_FREQ_COUNTER(CFG1) ((CFG1)&0xFFFF) +/* + * ULPOSC + * osc: 0 for ULPOSC1, 1 for ULPOSC2. + */ +#define AP_ULPOSC_CON0_BASE (AP_REG_BASE + 0xC2B0) +#define AP_ULPOSC_CON1_BASE (AP_REG_BASE + 0xC2B4) +#define AP_ULPOSC_CON2_BASE (AP_REG_BASE + 0xC2B8) +#define AP_ULPOSC_CON0(osc) REG32(AP_ULPOSC_CON0_BASE + (osc)*0x10) +#define AP_ULPOSC_CON1(osc) REG32(AP_ULPOSC_CON1_BASE + (osc)*0x10) +#define AP_ULPOSC_CON2(osc) REG32(AP_ULPOSC_CON2_BASE + (osc)*0x10) +/* + * AP_ULPOSC_CON0 + * bit0-6: calibration + * bit7-13: iband + * bit14-17: fband + * bit18-23: div + * bit24: cp_en + * bit25-31: reserved + */ +#define OSC_CALI_MASK 0x7f +#define OSC_IBAND_SHIFT 7 +#define OSC_FBAND_SHIFT 14 +#define OSC_DIV_SHIFT 18 +#define OSC_CP_EN BIT(24) +/* AP_ULPOSC_CON1 + * bit0-7: 32K calibration + * bit 8-15: rsv1 + * bit 16-23: rsv2 + * bit 24-25: mod + * bit26: div2_en + * bit27-31: reserved + */ +#define OSC_RSV1_SHIFT 8 +#define OSC_RSV2_SHIFT 16 +#define OSC_MOD_SHIFT 24 +#define OSC_DIV2_EN BIT(26) +/* AP_ULPOSC_CON2 + * bit0-7: bias + * bit8-31: reserved + */ + +#endif /* __CROS_EC_CLOCK_REGS_H */ diff --git a/chip/mt_scp/mt8192/intc.h b/chip/mt_scp/mt8192/intc.h new file mode 100644 index 0000000000..6c1d3c549c --- /dev/null +++ b/chip/mt_scp/mt8192/intc.h @@ -0,0 +1,126 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_INTC_H +#define __CROS_EC_INTC_H + +/* INTC */ +#define SCP_INTC_IRQ_POL0 0xef001f20 +#define SCP_INTC_IRQ_POL1 0x0800001d +#define SCP_INTC_IRQ_POL2 0x00000020 +#define SCP_INTC_GRP_LEN 3 +#define SCP_INTC_IRQ_COUNT 96 + +/* IRQ numbers */ +#define SCP_IRQ_GIPC_IN0 0 +#define SCP_IRQ_GIPC_IN1 1 +#define SCP_IRQ_GIPC_IN2 2 +#define SCP_IRQ_GIPC_IN3 3 +/* 4 */ +#define SCP_IRQ_SPM 4 +#define SCP_IRQ_AP_CIRQ 5 +#define SCP_IRQ_EINT 6 +#define SCP_IRQ_PMIC 7 +/* 8 */ +#define SCP_IRQ_UART0_TX 8 +#define SCP_IRQ_UART1_TX 9 +#define SCP_IRQ_I2C0 10 +#define SCP_IRQ_I2C1_0 11 +/* 12 */ +#define SCP_IRQ_BUS_DBG_TRACKER 12 +#define SCP_IRQ_CLK_CTRL 13 +#define SCP_IRQ_VOW 14 +#define SCP_IRQ_TIMER0 15 +/* 16 */ +#define SCP_IRQ_TIMER1 16 +#define SCP_IRQ_TIMER2 17 +#define SCP_IRQ_TIMER3 18 +#define SCP_IRQ_TIMER4 19 +/* 20 */ +#define SCP_IRQ_TIMER5 20 +#define SCP_IRQ_OS_TIMER 21 +#define SCP_IRQ_UART0_RX 22 +#define SCP_IRQ_UART1_RX 23 +/* 24 */ +#define SCP_IRQ_GDMA 24 +#define SCP_IRQ_AUDIO 25 +#define SCP_IRQ_MD_DSP 26 +#define SCP_IRQ_ADSP 27 +/* 28 */ +#define SCP_IRQ_CPU_TICK 28 +#define SCP_IRQ_SPI0 29 +#define SCP_IRQ_SPI1 30 +#define SCP_IRQ_SPI2 31 +/* 32 */ +#define SCP_IRQ_NEW_INFRA_SYS_CIRQ 32 +#define SCP_IRQ_DBG 33 +#define SCP_IRQ_CCIF0 34 +#define SCP_IRQ_CCIF1 35 +/* 36 */ +#define SCP_IRQ_CCIF2 36 +#define SCP_IRQ_WDT 37 +#define SCP_IRQ_USB0 38 +#define SCP_IRQ_USB1 39 +/* 40 */ +#define SCP_IRQ_DPMAIF 40 +#define SCP_IRQ_INFRA 41 +#define SCP_IRQ_CLK_CTRL_CORE 42 +#define SCP_IRQ_CLK_CTRL2_CORE 43 +/* 44 */ +#define SCP_IRQ_CLK_CTRL2 44 +#define SCP_IRQ_GIPC_IN4 45 /* HALT */ +#define SCP_IRQ_PERIBUS_TIMEOUT 46 +#define SCP_IRQ_INFRABUS_TIMEOUT 47 +/* 48 */ +#define SCP_IRQ_MET0 48 +#define SCP_IRQ_MET1 49 +#define SCP_IRQ_MET2 50 +#define SCP_IRQ_MET3 51 +/* 52 */ +#define SCP_IRQ_AP_WDT 52 +#define SCP_IRQ_L2TCM_SEC_VIO 53 +#define SCP_IRQ_CPU_TICK1 54 +#define SCP_IRQ_MAD_DATAIN 55 +/* 56 */ +#define SCP_IRQ_I3C0_IBI_WAKE 56 +#define SCP_IRQ_I3C1_IBI_WAKE 57 +#define SCP_IRQ_I3C2_IBI_WAKE 58 +#define SCP_IRQ_APU_ENGINE 59 +/* 60 */ +#define SCP_IRQ_MBOX0 60 +#define SCP_IRQ_MBOX1 61 +#define SCP_IRQ_MBOX2 62 +#define SCP_IRQ_MBOX3 63 +/* 64 */ +#define SCP_IRQ_MBOX4 64 +#define SCP_IRQ_SYS_CLK_REQ 65 +#define SCP_IRQ_BUS_REQ 66 +#define SCP_IRQ_APSRC_REQ 67 +/* 68 */ +#define SCP_IRQ_APU_MBOX 68 +#define SCP_IRQ_DEVAPC_SECURE_VIO 69 +/* 72 */ +/* 76 */ +#define SCP_IRQ_I2C1_2 78 +#define SCP_IRQ_I2C2 79 +/* 80 */ +#define SCP_IRQ_AUD2AUDIODSP 80 +#define SCP_IRQ_AUD2AUDIODSP_2 81 +#define SCP_IRQ_CONN2ADSP_A2DPOL 82 +#define SCP_IRQ_CONN2ADSP_BTCVSD 83 +/* 84 */ +#define SCP_IRQ_CONN2ADSP_BLEISO 84 +#define SCP_IRQ_PCIE2ADSP 85 +#define SCP_IRQ_APU2ADSP_ENGINE 86 +#define SCP_IRQ_APU2ADSP_MBOX 87 +/* 88 */ +#define SCP_IRQ_CCIF3 88 +#define SCP_IRQ_I2C_DMA0 89 +#define SCP_IRQ_I2C_DMA1 90 +#define SCP_IRQ_I2C_DMA2 91 +/* 92 */ +#define SCP_IRQ_I2C_DMA3 92 + +#endif /* __CROS_EC_INTC_H */ diff --git a/chip/mt_scp/mt8192/uart.c b/chip/mt_scp/mt8192/uart.c new file mode 100644 index 0000000000..da17857edf --- /dev/null +++ b/chip/mt_scp/mt8192/uart.c @@ -0,0 +1,26 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SCP UART module for MT8192 specific */ + +#include "uart_regs.h" + +/* + * UARTN == 0, SCP UART0 + * UARTN == 1, SCP UART1 + * UARTN == 2, AP UART1 + */ +#define UARTN CONFIG_UART_CONSOLE + +void uart_init_pinmux(void) +{ +#if UARTN == 0 + SCP_UART_CK_SEL |= UART0_CK_SEL_VAL(UART_CK_SEL_ULPOSC); + SCP_SET_CLK_CG |= CG_UART0_MCLK | CG_UART0_BCLK | CG_UART0_RST; +#elif UARTN == 1 + SCP_UART_CK_SEL |= UART1_CK_SEL_VAL(UART_CK_SEL_ULPOSC); + SCP_SET_CLK_CG |= CG_UART1_MCLK | CG_UART1_BCLK | CG_UART1_RST; +#endif +} diff --git a/chip/mt_scp/mt8192/video.c b/chip/mt_scp/mt8192/video.c new file mode 100644 index 0000000000..8cb4f9588e --- /dev/null +++ b/chip/mt_scp/mt8192/video.c @@ -0,0 +1,18 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "video.h" + +uint32_t video_get_enc_capability(void) +{ + return VENC_CAP_4K; +} + +uint32_t video_get_dec_capability(void) +{ + return VDEC_CAP_4K_DISABLED | VDEC_CAP_MM21 | VDEC_CAP_H264_SLICE | + VDEC_CAP_VP8_FRAME | VDEC_CAP_VP9_FRAME; +} diff --git a/chip/mt_scp/mt8195/build.mk b/chip/mt_scp/mt8195/build.mk new file mode 100644 index 0000000000..c188ea6d17 --- /dev/null +++ b/chip/mt_scp/mt8195/build.mk @@ -0,0 +1,9 @@ +# -*- makefile -*- +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Required chip modules +chip-y+=$(CHIP_VARIANT)/uart.o +chip-y+=$(CHIP_VARIANT)/clock.o +chip-y+=$(CHIP_VARIANT)/video.o diff --git a/chip/mt_scp/mt8195/clock.c b/chip/mt_scp/mt8195/clock.c new file mode 100644 index 0000000000..9a0b978929 --- /dev/null +++ b/chip/mt_scp/mt8195/clock.c @@ -0,0 +1,507 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Clocks, PLL and power settings */ + +#include "clock.h" +#include "common.h" +#include "console.h" +#include "csr.h" +#include "ec_commands.h" +#include "power.h" +#include "registers.h" +#include "scp_timer.h" +#include "scp_watchdog.h" +#include "task.h" +#include "timer.h" + +#include +#include + +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) + +#define TASK_EVENT_SUSPEND TASK_EVENT_CUSTOM_BIT(4) +#define TASK_EVENT_RESUME TASK_EVENT_CUSTOM_BIT(5) +#define CHECK_26M_PERIOD_US 50000 + +enum scp_sr_state { + SR_S0, + SR_S02S3, + SR_S3, +}; + +enum scp_clock_source { + SCP_CLK_SYSTEM, + SCP_CLK_32K, + SCP_CLK_ULPOSC1, + SCP_CLK_ULPOSC2_LOW_SPEED, + SCP_CLK_ULPOSC2_HIGH_SPEED, +}; + +enum { + OPP_ULPOSC2_LOW_SPEED, + OPP_ULPOSC2_HIGH_SPEED, +}; + +static struct opp_ulposc_cfg { + uint32_t osc; + uint32_t div; + uint32_t fband; + uint32_t mod; + uint32_t cali; + uint32_t target_mhz; + uint32_t clk_div; +} opp[] = { + [OPP_ULPOSC2_LOW_SPEED] = { + .osc = 1, .target_mhz = 326, .clk_div = CLK_DIV_SEL2, .div = 19, + .fband = 10, .mod = 0, .cali = 64, /* 326MHz / 2 = 163MHz */ + }, + [OPP_ULPOSC2_HIGH_SPEED] = { + .osc = 1, .target_mhz = 360, .clk_div = CLK_DIV_SEL1, .div = 21, + .fband = 10, .mod = 0, .cali = 64, /* 360MHz / 1 = 360MHz */ + }, +}; + +static inline void clock_busy_udelay(int usec) +{ + /* + * Delaying by busy-looping, for place that can't use udelay because of + * the clock not configured yet. The value 28 is chosen approximately + * from experiment. + * + * `volatile' in order to avoid compiler to optimize the function out + * (otherwise, the function will be eliminated). + */ + volatile int i = usec * 28; + + while (--i) + ; +} + +static void clock_ulposc_config_default(struct opp_ulposc_cfg *opp) +{ + uint32_t val = 0; + + /* set mod, div2_en = 0, cp_en = 0 */ + val |= opp->mod << OSC_MOD_SHIFT; + /* set div */ + val |= opp->div << OSC_DIV_SHIFT; + /* set F-band, I-band = 82 */ + val |= (opp->fband << OSC_FBAND_SHIFT) | (82 << OSC_IBAND_SHIFT); + /* set calibration */ + val |= opp->cali; + /* set control register 0 */ + AP_ULPOSC_CON0(opp->osc) = val; + + clock_busy_udelay(50); + + /* bias = 65 */ + val = 65 << OSC_BIAS_SHIFT; + /* rsv2 = 0, rsv1 = 41, cali_32k = 0 */ + val |= 41 << OSC_RSV1_SHIFT; + /* set control register 1 */ + AP_ULPOSC_CON1(opp->osc) = val; + + /* set settle time */ + SCP_CLK_HIGH_VAL = (SCP_CLK_HIGH_VAL & ~CLK_HIGH_VAL_MASK) | + CLK_HIGH_VAL_VAL(2); +} + +static void clock_ulposc_config_cali(struct opp_ulposc_cfg *opp, + uint32_t cali_val) +{ + uint32_t val; + + val = AP_ULPOSC_CON0(opp->osc); + val &= ~OSC_CALI_MASK; + val |= cali_val; + AP_ULPOSC_CON0(opp->osc) = val; + opp->cali = cali_val; + + clock_busy_udelay(50); +} + +static uint32_t clock_ulposc_measure_freq(uint32_t osc) +{ + uint32_t result = 0; + int cnt; + uint32_t cali_0 = AP_CLK26CALI_0; + uint32_t cali_1 = AP_CLK26CALI_1; + uint32_t dbg_cfg = AP_CLK_DBG_CFG; + uint32_t misc_cfg = AP_CLK_MISC_CFG_0; + + /* Set ckgen_load_cnt: CLK26CALI_1[25:16] */ + AP_CLK26CALI_1 = CFG_CKGEN_LOAD_CNT; + + /* before select meter clock input, bit[1:0] = b00 */ + AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_MODE_MASK) | DBG_MODE_SET_CLOCK; + + /* select monclk_ext2fqmtr_sel: AP_CLK_DBG_CFG[14:8] */ + AP_CLK_DBG_CFG = + (AP_CLK_DBG_CFG & ~DBG_BIST_SOURCE_MASK) | + (osc == 0 ? DBG_BIST_SOURCE_ULPOSC1 : DBG_BIST_SOURCE_ULPOSC2); + + /* set meter divisor to 1, bit[31:24] = b00000000 */ + AP_CLK_MISC_CFG_0 = (AP_CLK_MISC_CFG_0 & ~MISC_METER_DIVISOR_MASK) | + MISC_METER_DIV_1; + + /* enable frequency meter, without start */ + AP_CLK26CALI_0 |= CFG_FREQ_METER_ENABLE; + + /* trigger frequency meter start */ + AP_CLK26CALI_0 |= CFG_FREQ_METER_RUN; + + clock_busy_udelay(45); + + for (cnt = 10000; cnt > 0; --cnt) { + clock_busy_udelay(10); + if (!(AP_CLK26CALI_0 & CFG_FREQ_METER_RUN)) { + result = CFG_FREQ_COUNTER(AP_CLK26CALI_1); + break; + } + } + + AP_CLK26CALI_0 = cali_0; + AP_CLK26CALI_1 = cali_1; + AP_CLK_DBG_CFG = dbg_cfg; + AP_CLK_MISC_CFG_0 = misc_cfg; + + /* disable freq meter */ + AP_CLK26CALI_0 &= ~CFG_FREQ_METER_ENABLE; + + return result; +} + +#define CAL_MIS_RATE 40 +static int clock_ulposc_is_calibrated(struct opp_ulposc_cfg *opp) +{ + uint32_t curr, target; + + curr = clock_ulposc_measure_freq(opp->osc); + target = opp->target_mhz * 512 / 26; + +#ifdef DEBUG + CPRINTF("osc:%u, target=%uMHz, curr=%uMHz, cali:%u\n", opp->osc, + opp->target_mhz, (curr * 26) / 512, opp->cali); +#endif + + /* check if calibrated value is in the range of target value +- 4% */ + if (curr > (target * (1000 - CAL_MIS_RATE) / 1000) && + curr < (target * (1000 + CAL_MIS_RATE) / 1000)) + return 1; + else + return 0; +} + +static uint32_t clock_ulposc_process_cali(struct opp_ulposc_cfg *opp) +{ + uint32_t current_val = 0; + uint32_t target_val = opp->target_mhz * 512 / 26; + uint32_t middle, min = 0, max = OSC_CALI_MASK; + uint32_t diff_by_min, diff_by_max, cal_result; + + do { + middle = (min + max) / 2; + if (middle == min) + break; + + clock_ulposc_config_cali(opp, middle); + current_val = clock_ulposc_measure_freq(opp->osc); + + if (current_val > target_val) + max = middle; + else + min = middle; + } while (min <= max); + + clock_ulposc_config_cali(opp, min); + current_val = clock_ulposc_measure_freq(opp->osc); + if (current_val > target_val) + diff_by_min = current_val - target_val; + else + diff_by_min = target_val - current_val; + + clock_ulposc_config_cali(opp, max); + current_val = clock_ulposc_measure_freq(opp->osc); + if (current_val > target_val) + diff_by_max = current_val - target_val; + else + diff_by_max = target_val - current_val; + + if (diff_by_min < diff_by_max) + cal_result = min; + else + cal_result = max; + + clock_ulposc_config_cali(opp, cal_result); + if (!clock_ulposc_is_calibrated(opp)) + assert(0); + + return cal_result; +} + +static void clock_high_enable(int osc) +{ + /* enable high speed clock */ + SCP_CLK_ENABLE |= CLK_HIGH_EN; + + switch (osc) { + case 0: + /* after 150us, enable ULPOSC */ + clock_busy_udelay(150); + SCP_CLK_ENABLE |= CLK_HIGH_CG | CLK_HIGH_EN; + + /* topck ulposc1 clk gating off */ + AP_CLK_CFG_29_CLR = PDN_F_ULPOSC_CK; + /* select topck ulposc1 as scp clk parent */ + AP_CLK_CFG_29_CLR = ULPOSC1_CLK_SEL; + + AP_CLK_CFG_UPDATE3 = F_ULPOSC_CK_UPDATE; + clock_busy_udelay(50); + break; + case 1: + /* turn off ULPOSC2 high-core-disable switch */ + SCP_CLK_ON_CTRL &= ~HIGH_CORE_DIS_SUB; + /* after 150us, scp requests ULPOSC2 high core clock */ + clock_busy_udelay(150); + SCP_CLK_HIGH_CORE_CG |= HIGH_CORE_CG; + SCP_CLK_ENABLE &= ~CLK_HIGH_CG; + clock_busy_udelay(50); + + /* topck ulposc2 clk gating off */ + AP_CLK_CFG_29_CLR = PDN_F_ULPOSC_CORE_CK; + /* select topck ulposc2 as scp clk parent */ + AP_CLK_CFG_29_CLR = ULPOSC2_CLK_SEL; + + AP_CLK_CFG_UPDATE3 = F_ULPOSC_CORE_CK_UPDATE; + clock_busy_udelay(50); + break; + default: + break; + } +} + +static void clock_high_disable(int osc) +{ + switch (osc) { + case 0: + /* topck ulposc1 clk gating on */ + AP_CLK_CFG_29_SET = PDN_F_ULPOSC_CK; + AP_CLK_CFG_UPDATE3 = F_ULPOSC_CK_UPDATE; + clock_busy_udelay(50); + + /* scp doesn't request ulposc1 clk */ + SCP_CLK_ENABLE &= ~CLK_HIGH_CG; + clock_busy_udelay(50); + SCP_CLK_ENABLE &= ~CLK_HIGH_EN; + clock_busy_udelay(50); + break; + case 1: + /* topck ulposc2 clk gating on */ + AP_CLK_CFG_29_SET = PDN_F_ULPOSC_CORE_CK; + AP_CLK_CFG_UPDATE3 = F_ULPOSC_CORE_CK_UPDATE; + clock_busy_udelay(50); + + /* scp doesn't request ulposc2 clk */ + SCP_CLK_HIGH_CORE_CG &= ~HIGH_CORE_CG; + clock_busy_udelay(50); + SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB; + clock_busy_udelay(50); + break; + default: + break; + } +} + +static void clock_calibrate_ulposc(struct opp_ulposc_cfg *opp) +{ + /* + * ULPOSC1(osc=0) is already + * - calibrated + * - enabled in coreboot + * - used by pmic wrapper + */ + if (opp->osc != 0) { + clock_high_disable(opp->osc); + clock_ulposc_config_default(opp); + clock_high_enable(opp->osc); + } + + /* Calibrate only if it is not accurate enough. */ + if (!clock_ulposc_is_calibrated(opp)) + opp->cali = clock_ulposc_process_cali(opp); +} + +static void clock_select_clock(enum scp_clock_source src) +{ + uint32_t sel; + uint32_t div; + + switch (src) { + case SCP_CLK_SYSTEM: + div = CLK_DIV_SEL1; + sel = CLK_SW_SEL_SYSTEM; + break; + case SCP_CLK_32K: + div = CLK_DIV_SEL1; + sel = CLK_SW_SEL_32K; + break; + case SCP_CLK_ULPOSC1: + div = CLK_DIV_SEL1; + sel = CLK_SW_SEL_ULPOSC1; + break; + case SCP_CLK_ULPOSC2_LOW_SPEED: + /* parking at scp system clk until ulposc clk is ready */ + clock_select_clock(SCP_CLK_SYSTEM); + + clock_ulposc_config_cali(&opp[OPP_ULPOSC2_LOW_SPEED], + opp[OPP_ULPOSC2_LOW_SPEED].cali); + div = opp[OPP_ULPOSC2_LOW_SPEED].clk_div; + + sel = CLK_SW_SEL_ULPOSC2; + break; + case SCP_CLK_ULPOSC2_HIGH_SPEED: + /* parking at scp system clk until ulposc clk is ready */ + clock_select_clock(SCP_CLK_SYSTEM); + + clock_ulposc_config_cali(&opp[OPP_ULPOSC2_HIGH_SPEED], + opp[OPP_ULPOSC2_HIGH_SPEED].cali); + div = opp[OPP_ULPOSC2_HIGH_SPEED].clk_div; + + sel = CLK_SW_SEL_ULPOSC2; + break; + default: + div = CLK_DIV_SEL1; + sel = CLK_SW_SEL_SYSTEM; + break; + } + + SCP_CLK_DIV_SEL = div; + SCP_CLK_SW_SEL = sel; +} + +__override void +power_chipset_handle_host_sleep_event(enum host_sleep_event state, + struct host_sleep_event_context *ctx) +{ + if (state == HOST_SLEEP_EVENT_S3_SUSPEND) { + task_set_event(TASK_ID_SR, TASK_EVENT_SUSPEND); + } else if (state == HOST_SLEEP_EVENT_S3_RESUME) { + task_set_event(TASK_ID_SR, TASK_EVENT_RESUME); + } +} + +void sr_task(void *u) +{ + enum scp_sr_state state = SR_S0; + uint32_t event; + uint32_t prev, now; + + while (1) { + switch (state) { + case SR_S0: + event = task_wait_event(-1); + if (event & TASK_EVENT_SUSPEND) { + timer_enable(TIMER_SR); + prev = timer_read_raw_sr(); + state = SR_S02S3; + } + break; + case SR_S02S3: + event = task_wait_event(CHECK_26M_PERIOD_US); + if (event & TASK_EVENT_RESUME) { + /* suspend is aborted */ + timer_disable(TIMER_SR); + state = SR_S0; + } else if (event & TASK_EVENT_TIMER) { + now = timer_read_raw_sr(); + if (now != prev) { + /* 26M is still on */ + prev = now; + } else { + /* 26M is off */ + state = SR_S3; + } + } + break; + case SR_S3: + interrupt_disable(); + watchdog_disable(); + + /* change to 26M to stop core at here */ + clock_select_clock(SCP_CLK_SYSTEM); + + /* 26M is back */ + clock_select_clock(SCP_CLK_ULPOSC2_HIGH_SPEED); + + watchdog_enable(); + interrupt_enable(); + timer_disable(TIMER_SR); + state = SR_S0; + break; + } + } +} + +void clock_init(void) +{ + uint32_t i; + + /* select scp system clock (default 26MHz) */ + clock_select_clock(SCP_CLK_SYSTEM); + + /* set VREQ to HW mode */ + SCP_CPU_VREQ_CTRL = VREQ_SEL | VREQ_DVFS_SEL; + SCP_CLK_CTRL_GENERAL_CTRL &= ~VREQ_PMIC_WRAP_SEL; + SCP_SEC_CTRL &= ~VREQ_SECURE_DIS; + + /* set DDREN to auto mode */ + SCP_SYS_CTRL |= AUTO_DDREN; + + /* set settle time */ + SCP_CLK_SYS_VAL = (SCP_CLK_SYS_VAL & ~CLK_SYS_VAL_MASK) | + CLK_SYS_VAL_VAL(1); + SCP_CLK_HIGH_VAL = (SCP_CLK_HIGH_VAL & ~CLK_HIGH_VAL_MASK) | + CLK_HIGH_VAL_VAL(1); + SCP_SLEEP_CTRL = (SCP_SLEEP_CTRL & ~VREQ_COUNT_MASK) | + VREQ_COUNT_VAL(1); + + /* turn off ULPOSC2 */ + SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB; + + /* calibrate ULPOSC2 */ + for (i = 0; i < ARRAY_SIZE(opp); ++i) + clock_calibrate_ulposc(&opp[i]); + + /* select ULPOSC2 high speed SCP clock */ + clock_select_clock(SCP_CLK_ULPOSC2_HIGH_SPEED); + + /* select BCLK to use ULPOSC / 8 */ + SCP_BCLK_CK_SEL = BCLK_CK_SEL_ULPOSC_DIV8; + + /* enable default clock gate */ + SCP_SET_CLK_CG |= CG_DMA_CH3 | CG_DMA_CH2 | CG_DMA_CH1 | CG_DMA_CH0 | + CG_I2C_MCLK | CG_MAD_MCLK | CG_AP2P_MCLK; +} + +#ifdef DEBUG +int command_ulposc(int argc, const char *argv[]) +{ + uint32_t osc; + + for (osc = 0; osc <= OPP_ULPOSC2_HIGH_SPEED; ++osc) + ccprintf("ULPOSC%u frequency: %u kHz\n", osc + 1, + clock_ulposc_measure_freq(osc) * 26 * 1000 / 512); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[ulposc]", + "Measure ULPOSC frequency"); +#endif + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mt_scp/mt8195/clock_regs.h b/chip/mt_scp/mt8195/clock_regs.h new file mode 100644 index 0000000000..7744c3df54 --- /dev/null +++ b/chip/mt_scp/mt8195/clock_regs.h @@ -0,0 +1,90 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SCP clock module registers */ + +#ifndef __CROS_EC_CLOCK_REGS_H +#define __CROS_EC_CLOCK_REGS_H + +/* clock source select */ +#define SCP_CLK_SW_SEL REG32(SCP_CLK_CTRL_BASE + 0x0000) +#define CLK_SW_SEL_SYSTEM 0 +#define CLK_SW_SEL_32K 1 +#define CLK_SW_SEL_ULPOSC2 2 +#define CLK_SW_SEL_ULPOSC1 3 +#define SCP_CLK_ENABLE REG32(SCP_CLK_CTRL_BASE + 0x0004) +#define CLK_HIGH_EN BIT(1) /* ULPOSC */ +#define CLK_HIGH_CG BIT(2) +/* clock general control */ +#define SCP_CLK_CTRL_GENERAL_CTRL REG32(SCP_CLK_CTRL_BASE + 0x009C) +#define VREQ_PMIC_WRAP_SEL (0x3) + +/* TOPCK clk */ +#define TOPCK_BASE AP_REG_BASE +#define AP_CLK_CFG_UPDATE3 REG32(TOPCK_BASE + 0x0010) +#define F_ULPOSC_CK_UPDATE BIT(21) +#define F_ULPOSC_CORE_CK_UPDATE BIT(22) +#define AP_CLK_CFG_29_SET REG32(TOPCK_BASE + 0x0180) +#define AP_CLK_CFG_29_CLR REG32(TOPCK_BASE + 0x0184) +#define ULPOSC1_CLK_SEL (0x3 << 8) +#define PDN_F_ULPOSC_CK BIT(15) +#define ULPOSC2_CLK_SEL (0x3 << 16) +#define PDN_F_ULPOSC_CORE_CK BIT(23) +/* OSC meter */ +#define AP_CLK_DBG_CFG REG32(TOPCK_BASE + 0x020C) +#define DBG_MODE_MASK 3 +#define DBG_MODE_SET_CLOCK 0 +#define DBG_BIST_SOURCE_MASK (0x7f << 8) +#define DBG_BIST_SOURCE_ULPOSC1 (0x30 << 8) +#define DBG_BIST_SOURCE_ULPOSC2 (0x32 << 8) +#define AP_CLK26CALI_0 REG32(TOPCK_BASE + 0x0218) +#define CFG_FREQ_METER_RUN BIT(4) +#define CFG_FREQ_METER_ENABLE BIT(7) +#define AP_CLK26CALI_1 REG32(TOPCK_BASE + 0x021C) +#define CFG_CKGEN_LOAD_CNT 0x01ff0000 +#define CFG_FREQ_COUNTER(CFG1) ((CFG1)&0xFFFF) +#define AP_CLK_MISC_CFG_0 REG32(TOPCK_BASE + 0x022C) +#define MISC_METER_DIVISOR_MASK 0xff000000 +#define MISC_METER_DIV_1 0 +/* + * ULPOSC + * osc: 0 for ULPOSC1, 1 for ULPOSC2. + */ +#define AP_ULPOSC_CON0_BASE (AP_REG_BASE + 0xC2B0) +#define AP_ULPOSC_CON1_BASE (AP_REG_BASE + 0xC2B4) +#define AP_ULPOSC_CON0(osc) REG32(AP_ULPOSC_CON0_BASE + (osc)*0x10) +#define AP_ULPOSC_CON1(osc) REG32(AP_ULPOSC_CON1_BASE + (osc)*0x10) +/* + * AP_ULPOSC_CON0 + * bit0-6: calibration + * bit7-13: iband + * bit14-17: fband + * bit18-23: div + * bit24: cp_en + * bit25-26: mod + * bit27: div2_en + * bit28-31: reserved + */ +#define OSC_CALI_SHIFT 0 +#define OSC_CALI_MASK 0x7f +#define OSC_IBAND_SHIFT 7 +#define OSC_FBAND_SHIFT 14 +#define OSC_DIV_SHIFT 18 +#define OSC_CP_EN BIT(24) +#define OSC_MOD_SHIFT 25 +#define OSC_DIV2_EN BIT(27) +/* + * AP_ULPOSC_CON1 + * bit0-7: rsv1 + * bit8-15: rsv2 + * bit16-23: 32K calibration + * bit24-31: bias + */ +#define OSC_RSV1_SHIFT 0 +#define OSC_RSV2_SHIFT 8 +#define OSC_32KCALI_SHIFT 16 +#define OSC_BIAS_SHIFT 24 + +#endif /* __CROS_EC_CLOCK_REGS_H */ diff --git a/chip/mt_scp/mt8195/intc.h b/chip/mt_scp/mt8195/intc.h new file mode 100644 index 0000000000..dd3874718e --- /dev/null +++ b/chip/mt_scp/mt8195/intc.h @@ -0,0 +1,166 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_INTC_H +#define __CROS_EC_INTC_H + +/* INTC */ +#define SCP_INTC_IRQ_POL0 0xef001f20 +#define SCP_INTC_IRQ_POL1 0x044001dd +#define SCP_INTC_IRQ_POL2 0xffffdfe0 +#define SCP_INTC_IRQ_POL3 0xfffffff3 +#define SCP_INTC_GRP_LEN 4 +#define SCP_INTC_IRQ_COUNT 127 + +/* IRQ numbers */ +#define SCP_IRQ_GIPC_IN0 0 +#define SCP_IRQ_GIPC_IN1 1 +#define SCP_IRQ_GIPC_IN2 2 +#define SCP_IRQ_GIPC_IN3 3 +/* 4 */ +#define SCP_IRQ_SPM 4 +#define SCP_IRQ_AP_CIRQ 5 +#define SCP_IRQ_EINT 6 +#define SCP_IRQ_PMIC 7 +/* 8 */ +#define SCP_IRQ_UART0_TX 8 +#define SCP_IRQ_UART1_TX 9 +#define SCP_IRQ_I2C0 10 +#define SCP_IRQ_I2C1_0 11 +/* 12 */ +#define SCP_IRQ_BUS_DBG_TRACKER 12 +#define SCP_IRQ_CLK_CTRL 13 +#define SCP_IRQ_VOW 14 +#define SCP_IRQ_TIMER0 15 +/* 16 */ +#define SCP_IRQ_TIMER1 16 +#define SCP_IRQ_TIMER2 17 +#define SCP_IRQ_TIMER3 18 +#define SCP_IRQ_TIMER4 19 +/* 20 */ +#define SCP_IRQ_TIMER5 20 +#define SCP_IRQ_OS_TIMER 21 +#define SCP_IRQ_UART0_RX 22 +#define SCP_IRQ_UART1_RX 23 +/* 24 */ +#define SCP_IRQ_GDMA 24 +#define SCP_IRQ_AUDIO 25 +#define SCP_IRQ_MD_DSP 26 +#define SCP_IRQ_ADSP 27 +/* 28 */ +#define SCP_IRQ_CPU_TICK 28 +#define SCP_IRQ_SPI0 29 +#define SCP_IRQ_SPI1 30 +#define SCP_IRQ_SPI2 31 +/* 32 */ +#define SCP_IRQ_NEW_INFRA_SYS_CIRQ 32 +#define SCP_IRQ_DBG 33 +#define SCP_IRQ_GCE 34 +#define SCP_IRQ_MDP_GCE 35 +/* 36 */ +#define SCP_IRQ_VDEC 36 +#define SCP_IRQ_WDT 37 +#define SCP_IRQ_VDEC_LAT 38 +#define SCP_IRQ_VDEC1 39 +/* 40 */ +#define SCP_IRQ_VDEC1_LAT 40 +#define SCP_IRQ_INFRA 41 +#define SCP_IRQ_CLK_CTRL_CORE 42 +#define SCP_IRQ_CLK_CTRL2_CORE 43 +/* 44 */ +#define SCP_IRQ_CLK_CTRL2 44 +#define SCP_IRQ_GIPC_IN4 45 /* HALT */ +#define SCP_IRQ_PERIBUS_TIMEOUT 46 +#define SCP_IRQ_INFRABUS_TIMEOUT 47 +/* 48 */ +#define SCP_IRQ_MET0 48 +#define SCP_IRQ_MET1 49 +#define SCP_IRQ_MET2 50 +#define SCP_IRQ_MET3 51 +/* 52 */ +#define SCP_IRQ_AP_WDT 52 +#define SCP_IRQ_L2TCM_SEC_VIO 53 +#define SCP_IRQ_VDEC_INT_LINE_CNT 54 +#define SCP_IRQ_VOW_DATAIN 55 +/* 56 */ +#define SCP_IRQ_I3C0_IBI_WAKE 56 +#define SCP_IRQ_I3C1_IBI_WAKE 57 +#define SCP_IRQ_VENC 58 +#define SCP_IRQ_APU_ENGINE 59 +/* 60 */ +#define SCP_IRQ_MBOX0 60 +#define SCP_IRQ_MBOX1 61 +#define SCP_IRQ_MBOX2 62 +#define SCP_IRQ_MBOX3 63 +/* 64 */ +#define SCP_IRQ_MBOX4 64 +#define SCP_IRQ_SYS_CLK_REQ 65 +#define SCP_IRQ_BUS_REQ 66 +#define SCP_IRQ_APSRC_REQ 67 +/* 68 */ +#define SCP_IRQ_APU_MBOX 68 +#define SCP_IRQ_DEVAPC_SECURE_VIO 69 +#define SCP_IRQ_APDMA0 70 +#define SCP_IRQ_APDMA1 71 +/* 72 */ +#define SCP_IRQ_APDMA2 72 +#define SCP_IRQ_APDMA3 73 +#define SCP_IRQ_APDMA4 74 +#define SCP_IRQ_APDMA5 75 +/* 76 */ +#define SCP_IRQ_HDMIRX_PM_DVI_SQH 76 +#define SCP_IRQ_HDMIRX_RESERVED 77 +#define SCP_IRQ_NNA0_0 78 +#define SCP_IRQ_NNA0_1 79 +/* 80 */ +#define SCP_IRQ_NNA0_2 80 +#define SCP_IRQ_NNA1_0 81 +#define SCP_IRQ_NNA1_1 82 +#define SCP_IRQ_NNA1_2 83 +/* 84 */ +#define SCP_IRQ_JPEGENC 84 +#define SCP_IRQ_JPEGDEC 85 +#define SCP_IRQ_JPEGDEC_C2 86 +#define SCP_IRQ_VENC_C1 87 +/* 88 */ +#define SCP_IRQ_JPEGENC_C1 88 +#define SCP_IRQ_JPEGDEC_C1 89 +#define SCP_IRQ_HDMITX 90 +#define SCP_IRQ_HDMI2 91 +/* 92 */ +#define SCP_IRQ_EARC 92 +#define SCP_IRQ_CEC 93 +#define SCP_IRQ_HDMI_DEV_DET 94 +#define SCP_IRQ_HDMIRX_OUT_ARM_PHY 95 +/* 96 */ +#define SCP_IRQ_I2C2 96 +#define SCP_IRQ_I2C3 97 +#define SCP_IRQ_I3C2_IBI_WAKE 98 +#define SCP_IRQ_I3C3_IBI_WAKE 99 +/* 100 */ +#define SCP_IRQ_SYS_I2C_0 100 +#define SCP_IRQ_SYS_I2C_1 101 +#define SCP_IRQ_SYS_I2C_2 102 +#define SCP_IRQ_SYS_I2C_3 103 +/* 104 */ +#define SCP_IRQ_SYS_I2C_4 104 +#define SCP_IRQ_SYS_I2C_5 105 +#define SCP_IRQ_SYS_I2C_6 106 +#define SCP_IRQ_SYS_I2C_7 107 +/* 108 */ +#define SCP_IRQ_DISP2ADSP_0 108 +#define SCP_IRQ_DISP2ADSP_1 109 +#define SCP_IRQ_DISP2ADSP_2 110 +#define SCP_IRQ_DISP2ADSP_3 111 +/* 112 */ +#define SCP_IRQ_DISP2ADSP_4 112 +#define SCP_IRQ_VDO1_DISP_MON2ADSP_0 113 +#define SCP_IRQ_VDO1_DISP_MON2ADSP_1 114 +#define SCP_IRQ_VDO1_DISP_MON2ADSP_2 115 +/* 116 */ +#define SCP_IRQ_GCE1_SECURE 116 +#define SCP_IRQ_GCE_SECURE 117 + +#endif /* __CROS_EC_INTC_H */ diff --git a/chip/mt_scp/mt8195/uart.c b/chip/mt_scp/mt8195/uart.c new file mode 100644 index 0000000000..faad1a41a4 --- /dev/null +++ b/chip/mt_scp/mt8195/uart.c @@ -0,0 +1,23 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SCP UART module for MT8195 specific */ + +#include "uart_regs.h" + +/* + * UARTN == 0, SCP UART0 + * UARTN == 1, SCP UART1 + * UARTN == 2, AP UART1 + */ +#define UARTN CONFIG_UART_CONSOLE + +void uart_init_pinmux(void) +{ +#if UARTN == 0 + SCP_UART_CK_SEL |= UART0_CK_SEL_VAL(UART_CK_SEL_ULPOSC); + SCP_SET_CLK_CG |= CG_UART0_MCLK | CG_UART0_BCLK | CG_UART0_RST; +#endif +} diff --git a/chip/mt_scp/mt8195/video.c b/chip/mt_scp/mt8195/video.c new file mode 100644 index 0000000000..1b70f56b4a --- /dev/null +++ b/chip/mt_scp/mt8195/video.c @@ -0,0 +1,19 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "video.h" + +uint32_t video_get_enc_capability(void) +{ + return VENC_CAP_4K; +} + +uint32_t video_get_dec_capability(void) +{ + return VDEC_CAP_INNER_RACING | VDEC_CAP_MM21 | VDEC_CAP_H264_SLICE | + VDEC_CAP_VP8_FRAME | VDEC_CAP_VP9_FRAME | VDEC_CAP_AV1_FRAME | + VDEC_CAP_HEVC_SLICE; +} diff --git a/chip/mt_scp/registers.h b/chip/mt_scp/registers.h deleted file mode 100644 index 21270b452d..0000000000 --- a/chip/mt_scp/registers.h +++ /dev/null @@ -1,645 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Register map for SCP - */ - -#ifndef __CROS_EC_REGISTERS_H -#define __CROS_EC_REGISTERS_H - -#include "common.h" -#include "compile_time_macros.h" - -/* IRQ numbers */ -#define SCP_IRQ_IPC0 0 -#define SCP_IRQ_IPC1 1 -#define SCP_IRQ_IPC2 2 -#define SCP_IRQ_IPC3 3 -#define SCP_IRQ_SPM 4 -#define SCP_IRQ_CIRQ 5 -#define SCP_IRQ_EINT 6 -#define SCP_IRQ_PMIC 7 -#define SCP_IRQ_UART0 8 -#define SCP_IRQ_UART1 9 -#define SCP_IRQ_I2C0 10 -#define SCP_IRQ_I2C1 11 -#define SCP_IRQ_I2C2 12 -#define SCP_IRQ_CLOCK 13 -#define SCP_IRQ_MAD_FIFO 14 -#define SCP_IRQ_TIMER0 15 -#define SCP_IRQ_TIMER1 16 -#define SCP_IRQ_TIMER2 17 -#define SCP_IRQ_TIMER3 18 -#define SCP_IRQ_TIMER4 19 -#define SCP_IRQ_TIMER5 20 -#define SCP_IRQ_TIMER_STATUS 21 -#define SCP_IRQ_UART0_RX 22 -#define SCP_IRQ_UART1_RX 23 -#define SCP_IRQ_DMA 24 -#define SCP_IRQ_AUDIO 25 -#define SCP_IRQ_MD1_F216 26 -#define SCP_IRQ_MD1 27 -#define SCP_IRQ_C2K 28 -#define SCP_IRQ_SPI0 29 -#define SCP_IRQ_SPI1 30 -#define SCP_IRQ_SPI2 31 -#define SCP_IRQ_AP_EINT 32 -#define SCP_IRQ_DEBUG 33 -#define SCP_CCIF0 34 -#define SCP_CCIF1 35 -#define SCP_CCIF2 36 -#define SCP_IRQ_WDT 37 -#define SCP_IRQ_USB0 38 -#define SCP_IRQ_USB1 39 -#define SCP_IRQ_TWAM 40 -#define SCP_IRQ_INFRA 41 -#define SCP_IRQ_HWDVFS_HIGH 42 -#define SCP_IRQ_HWDVFS_LOW 43 -#define SCP_IRQ_CLOCK2 44 -/* RESERVED 45-52 */ -#define SCP_IRQ_AP_EINT2 53 -#define SCP_IRQ_AP_EINT_EVT 54 -#define SCP_IRQ_MAD_DATA 55 - -#define SCP_CFG_BASE 0x405C0000 - -#define SCP_AP_RESOURCE REG32(SCP_CFG_BASE + 0x04) -#define SCP_BUS_RESOURCE REG32(SCP_CFG_BASE + 0x08) - -/* SCP to host interrupt */ -#define SCP_HOST_INT REG32(SCP_CFG_BASE + 0x1C) -#define IPC_SCP2HOST_SSHUB 0xff0000 -#define WDT_INT 0x100 -#define IPC_SCP2HOST 0xff -#define IPC_SCP2HOST_BIT 0x1 - -/* SCP to SPM interrupt */ -#define SCP_SPM_INT REG32(SCP_CFG_BASE + 0x20) -#define SPM_INT_A2SPM BIT(0) -#define SPM_INT_B2SPM BIT(1) -#define SCP_SPM_INT2 REG32(SCP_CFG_BASE + 0x24) - -/* - * AP side to SCP IPC - * APMCU writes 1 bit to trigger ith IPC to SCP. - * SCP writes 1 bit to ith bit to clear ith IPC. - */ -#define SCP_GIPC_IN REG32(SCP_CFG_BASE + 0x28) - #define SCP_GIPC_IN_CLEAR_IPCN(n) (1 << (n)) - #define SCP_GPIC_IN_CLEAR_ALL 0x7FFFF -#define SCP_CONN_INT REG32(SCP_CFG_BASE + 0x2C) - -/* 8 general purpose registers, 0 ~ 7 */ -#define SCP_GPR REG32_ADDR(SCP_CFG_BASE + 0x50) -/* - * SCP_GPR[0] - * b15-b0 : scratchpad - * b31-b16 : saved flags - * SCP_GPR[1] - * b15-b0 : power on state - */ -#define SCP_PWRON_STATE SCP_GPR[1] -#define PWRON_DEFAULT 0xdee80000 -#define PWRON_WATCHDOG BIT(0) -#define PWRON_RESET BIT(1) -/* AP defined features */ -#define SCP_EXPECTED_FREQ SCP_GPR[3] -#define SCP_CURRENT_FREQ SCP_GPR[4] -#define SCP_REBOOT SCP_GPR[5] -#define READY_TO_REBOOT 0x34 -#define REBOOT_OK 1 - -/* Miscellaneous */ -#define SCP_SEMAPHORE REG32(SCP_CFG_BASE + 0x90) -#define CORE_CONTROL REG32(SCP_CFG_BASE + 0xA0) -#define CORE_FPU_FLAGS REG32(SCP_CFG_BASE + 0xA4) -#define CORE_REG_SP REG32(SCP_CFG_BASE + 0xA8) -#define CORE_REG_LR REG32(SCP_CFG_BASE + 0xAC) -#define CORE_REG_PSP REG32(SCP_CFG_BASE + 0xB0) -#define CORE_REG_PC REG32(SCP_CFG_BASE + 0xB4) -#define SCP_SLP_PROTECT_CFG REG32(SCP_CFG_BASE + 0xC8) -#define P_CACHE_SLP_PROT_EN BIT(3) -#define D_CACHE_SLP_PROT_EN BIT(4) -#define SCP_ONE_TIME_LOCK REG32(SCP_CFG_BASE + 0xDC) -#define SCP_SECURE_CTRL REG32(SCP_CFG_BASE + 0xE0) -#define ENABLE_SPM_MASK_VREQ BIT(28) -#define DISABLE_REMAP BIT(22) -#define DISABLE_JTAG BIT(21) -#define DISABLE_AP_TCM BIT(20) -#define SCP_SYS_CTRL REG32(SCP_CFG_BASE + 0xE4) -#define DDREN_FIX_VALUE BIT(28) -#define AUTO_DDREN BIT(18) - -/* Memory remap control */ -/* - * EXT_ADDR3[29:24] remap register for addr msb 31~28 equal to 0x7 - * EXT_ADDR2[21:16] remap register for addr msb 31~28 equal to 0x6 - * EXT_ADDR1[13:8] remap register for addr msb 31~28 equal to 0x3 - * EXT_ADDR0[5:0] remap register for addr msb 31~28 equal to 0x2 - */ -#define SCP_REMAP_CFG1 REG32(SCP_CFG_BASE + 0x120) -/* - * EXT_ADDR7[29:24] remap register for addr msb 31~28 equal to 0xb - * EXT_ADDR6[21:16] remap register for addr msb 31~28 equal to 0xa - * EXT_ADDR5[13:8] remap register for addr msb 31~28 equal to 0x9 - * EXT_ADDR4[5:0] remap register for addr msb 31~28 equal to 0x8 - */ -#define SCP_REMAP_CFG2 REG32(SCP_CFG_BASE + 0x124) -/* - * AUD_ADDR[31:28] remap register for addr msb 31~28 equal to 0xd - * EXT_ADDR10[21:16]remap register for addr msb 31~28 equal to 0xf - * EXT_ADDR9[13:8] remap register for addr msb 31~28 equal to 0xe - * EXT_ADDR8[5:0] remap register for addr msb 31~28 equal to 0xc - */ -#define SCP_REMAP_CFG3 REG32(SCP_CFG_BASE + 0x128) - -#define SCP_REMAP_ADDR_SHIFT 28 -#define SCP_REMAP_ADDR_LSB_MASK (BIT(SCP_REMAP_ADDR_SHIFT) - 1) -#define SCP_REMAP_ADDR_MSB_MASK ((~0) << SCP_REMAP_ADDR_SHIFT) - -/* Cached memory remap control */ -#define SCP_L1_REMAP_CFG0 REG32(SCP_CFG_BASE + 0x12C) -/* - * L1C_EXT_ADDR1[29:16] remap register for addr msb 31~20 equal to 0x401 - * L1C_EXT_ADDR0[13:0] remap register for addr msb 31~20 equal to 0x400 - */ -#define SCP_L1_REMAP_CFG1 REG32(SCP_CFG_BASE + 0x130) -/* - * L1C_EXT_ADDR3[29:16] remap register for addr msb 31~20 equal to 0x403 - * L1C_EXT_ADDR2[13:0] remap register for addr msb 31~20 equal to 0x402 - */ -#define SCP_L1_REMAP_CFG2 REG32(SCP_CFG_BASE + 0x134) -/* - * L1C_EXT_ADDR5[29:16] remap register for addr msb 31~20 equal to 0x405 - * L1C_EXT_ADDR4[13:0] remap register for addr msb 31~20 equal to 0x404 - */ -#define SCP_L1_REMAP_CFG3 REG32(SCP_CFG_BASE + 0x138) -/* - * L1C_EXT_ADDR_OTHER1[13:8] Remap register for addr msb 31 to 28 equal to 0x1 - * L1C_EXT_ADDR_OTHER0[5:0] Remap register for addr msb 31 to 28 equal to 0x0 - * and not overlap with L1C_EXT_ADDR0 to L1C_EXT_ADDR7 - */ -#define SCP_L1_REMAP_OTHER REG32(SCP_CFG_BASE + 0x13C) - -#define SCP_L1_EXT_ADDR_SHIFT 20 -#define SCP_L1_EXT_ADDR_OTHER_SHIFT 28 -#define SCP_L1_EXT_ADDR_OTHER_LSB_MASK (BIT(SCP_REMAP_ADDR_SHIFT) - 1) -#define SCP_L1_EXT_ADDR_OTHER_MSB_MASK ((~0) << SCP_REMAP_ADDR_SHIFT) - -/* Audio/voice FIFO */ -#define SCP_AUDIO_BASE (SCP_CFG_BASE + 0x1000) -#define SCP_VIF_FIFO_EN REG32(SCP_AUDIO_BASE) -#define VIF_FIFO_RSTN (1 << 0) -#define VIF_FIFO_IRQ_EN (1 << 1) -#define VIF_FIFO_SRAM_PWR (1 << 2) -#define VIF_FIFO_RSTN_STATUS (1 << 4) -#define SCP_VIF_FIFO_STATUS REG32(SCP_AUDIO_BASE + 0x04) -#define VIF_FIFO_VALID (1 << 0) -#define VIF_FIFO_FULL (1 << 4) -#define VIF_FIFO_LEVEL(status) (((status) >> 16) & 0xff) -#define VIF_FIFO_MAX 256 -#define SCP_VIF_FIFO_DATA REG32(SCP_AUDIO_BASE + 0x08) -#define SCP_VIF_FIFO_DATA_THRE REG32(SCP_AUDIO_BASE + 0x0C) -/* VIF IRQ status clears on read! */ -#define SCP_VIF_FIFO_IRQ_STATUS REG32(SCP_AUDIO_BASE + 0x10) -/* Audio/voice serial interface */ -#define SCP_RXIF_CFG0 REG32(SCP_AUDIO_BASE + 0x14) -#define RXIF_CFG0_RESET_VAL 0x2A130001 -#define RXIF_AFE_ON (1 << 0) -#define RXIF_SCKINV (1 << 1) -#define RXIF_RG_DL_2_IN_MODE(mode) (((mode) & 0xf) << 8) -#define RXIF_RGDL2_AMIC_16K (0x1 << 8) -#define RXIF_RGDL2_DMIC_16K (0x2 << 8) -#define RXIF_RGDL2_DMIC_LP_16K (0x3 << 8) -#define RXIF_RGDL2_AMIC_32K (0x5 << 8) -#define RXIF_RGDL2_MASK (0xf << 8) -#define RXIF_UP8X_RSP(p) (((p) & 0x7) << 16) -#define RXIF_RG_RX_READEN (1 << 19) -#define RXIF_MONO (1 << 20) -#define RXIF_RG_CLK_A16P7K_EN(cnt) (((cnt) & 0xff) << 24) -#define SCP_RXIF_CFG1 REG32(SCP_AUDIO_BASE + 0x18) -#define RXIF_CFG1_RESET_VAL 0x33180014 -#define RXIF_RG_SYNC_CNT_TBL(t) ((t) & 0x1ff) -#define RXIF_RG_SYNC_SEARCH_TBL(t) (((t) & 0x1f) << 16) -#define RXIF_RG_SYNC_CHECK_ROUND(r) (((r) & 0xf) << 24) -#define RXIF_RG_INSYNC_CHECK_ROUND(r) (((r) & 0xf) << 28) -#define SCP_RXIF_CFG2 REG32(SCP_AUDIO_BASE + 0x1C) -#define RXIF_SYNC_WORD(w) ((w) & 0xffff) -#define SCP_RXIF_OUT REG32(SCP_AUDIO_BASE + 0x20) -#define SCP_RXIF_STATUS REG32(SCP_AUDIO_BASE + 0x24) -#define SCP_RXIF_IRQ_EN REG32(SCP_AUDIO_BASE + 0x28) - -/* INTC control */ -#define SCP_INTC_BASE (SCP_CFG_BASE + 0x2000) -#define SCP_INTC_IRQ_STATUS REG32(SCP_INTC_BASE) -#define SCP_INTC_IRQ_ENABLE REG32(SCP_INTC_BASE + 0x04) -#define IPC0_IRQ_EN BIT(0) -#define SCP_INTC_IRQ_OUTPUT REG32(SCP_INTC_BASE + 0x08) -#define SCP_INTC_IRQ_WAKEUP REG32(SCP_INTC_BASE + 0x0C) -#define SCP_INTC_NMI REG32(SCP_INTC_BASE + 0x10) -#define SCP_INTC_SPM_WAKEUP REG32(SCP_INTC_BASE + 0x14) -#define SCP_INTC_SPM_WAKEUP_MSB REG32(SCP_INTC_BASE + 0x18) -#define SCP_INTC_UART_RX_IRQ REG32(SCP_INTC_BASE + 0x1C) -#define SCP_INTC_IRQ_STATUS_MSB REG32(SCP_INTC_BASE + 0x80) -#define SCP_INTC_IRQ_ENABLE_MSB REG32(SCP_INTC_BASE + 0x84) -#define SCP_INTC_IRQ_OUTPUT_MSB REG32(SCP_INTC_BASE + 0x88) -#define SCP_INTC_IRQ_WAKEUP_MSB REG32(SCP_INTC_BASE + 0x8C) - -/* Timer */ -#define NUM_TIMERS 6 -#define SCP_TIMER_BASE(n) (SCP_CFG_BASE + 0x3000 + (0x10 * (n))) -#define SCP_TIMER_EN(n) REG32(SCP_TIMER_BASE(n)) -#define SCP_TIMER_RESET_VAL(n) REG32(SCP_TIMER_BASE(n) + 0x04) -#define SCP_TIMER_VAL(n) REG32(SCP_TIMER_BASE(n) + 0x08) -#define SCP_TIMER_IRQ_CTRL(n) REG32(SCP_TIMER_BASE(n) + 0x0C) -#define TIMER_IRQ_ENABLE BIT(0) -#define TIMER_IRQ_STATUS BIT(4) -#define TIMER_IRQ_CLEAR BIT(5) -#define SCP_TIMER_CLK_SEL(n) REG32(SCP_TIMER_BASE(n) + 0x40) -#define TIMER_CLK_32K (0 << 4) -#define TIMER_CLK_26M BIT(4) -#define TIMER_CLK_BCLK (2 << 4) -#define TIMER_CLK_PCLK (3 << 4) -#define TIMER_CLK_MASK (3 << 4) -/* OS timer */ -#define SCP_OSTIMER_BASE (SCP_CFG_BASE + 0x3080) -#define SCP_OSTIMER_CON REG32(SCP_OSTIMER_BASE) -#define SCP_OSTIMER_INIT_L REG32(SCP_OSTIMER_BASE + 0x04) -#define SCP_OSTIMER_INIT_H REG32(SCP_OSTIMER_BASE + 0x08) -#define SCP_OSTIMER_VAL_L REG32(SCP_OSTIMER_BASE + 0x0C) -#define SCP_OSTIMER_VAL_H REG32(SCP_OSTIMER_BASE + 0x10) -#define SCP_OSTIMER_TVAL REG32(SCP_OSTIMER_BASE + 0x14) -#define SCP_OSTIMER_IRQ_ACK REG32(SCP_OSTIMER_BASE + 0x18) -#define OSTIMER_LATCH0_EN BIT(5) -#define OSTIMER_LATCH1_EN BIT(13) -#define OSTIMER_LATCH2_EN BIT(21) -#define SCP_OSTIMER_LATCH_CTRL REG32(SCP_OSTIMER_BASE + 0x20) -#define SCP_OSTIMER_LATCH0_L REG32(SCP_OSTIMER_BASE + 0x24) -#define SCP_OSTIMER_LATCH0_H REG32(SCP_OSTIMER_BASE + 0x28) -#define SCP_OSTIMER_LATCH1_L REG32(SCP_OSTIMER_BASE + 0x2C) -#define SCP_OSTIMER_LATCH1_H REG32(SCP_OSTIMER_BASE + 0x30) -#define SCP_OSTIMER_LATCH2_L REG32(SCP_OSTIMER_BASE + 0x34) -#define SCP_OSTIMER_LATCH2_H REG32(SCP_OSTIMER_BASE + 0x38) - -/* Clock, PMIC wrapper, etc. */ -#define SCP_CLK_BASE (SCP_CFG_BASE + 0x4000) -#define SCP_CLK_SEL REG32(SCP_CLK_BASE) -#define CLK_SEL_SYS_26M 0 -#define CLK_SEL_32K 1 -#define CLK_SEL_ULPOSC_2 2 -#define CLK_SEL_ULPOSC_1 3 - -#define SCP_CLK_EN REG32(SCP_CLK_BASE + 0x04) -#define EN_CLK_SYS BIT(0) /* System clock */ -#define EN_CLK_HIGH BIT(1) /* ULPOSC */ -#define CG_CLK_HIGH BIT(2) -#define EN_SYS_IRQ BIT(16) -#define EN_HIGH_IRQ BIT(17) -#define SCP_CLK_SAFE_ACK REG32(SCP_CLK_BASE + 0x08) -#define SCP_CLK_ACK REG32(SCP_CLK_BASE + 0x0C) -#define SCP_CLK_IRQ_ACK REG32(SCP_CLK_BASE + 0x10) -/* - * System clock counter value. - * CLK_SYS_VAL[9:0] System clock counter initial/reset value. - */ -#define SCP_CLK_SYS_VAL REG32(SCP_CLK_BASE + 0x14) -#define CLK_SYS_VAL_MASK 0x3ff /* 10 bits */ -#define CLK_SYS_VAL(n) ((n) & CLK_SYS_VAL_MASK) -/* - * ULPOSC clock counter value. - * CLK_HIGH_VAL[9:0] ULPOSC clock counter initial/reset value. - */ -#define SCP_CLK_HIGH_VAL REG32(SCP_CLK_BASE + 0x18) -#define CLK_HIGH_VAL_MASK 0x3ff /* 10 bits */ -#define CLK_HIGH_VAL(n) ((n) & CLK_HIGH_VAL_MASK) -#define SCP_CLK_SLOW_SEL REG32(SCP_CLK_BASE + 0x1C) -#define CKSW_SEL_SLOW_MASK 0x3 -#define CKSW_SEL_SLOW_DIV_MASK 0x30 -#define CKSW_SEL_SLOW_SYS_CLK 0 -#define CKSW_SEL_SLOW_32K_CLK 1 -#define CKSW_SEL_SLOW_ULPOSC2_CLK 2 -#define CKSW_SEL_SLOW_ULPOSC1_CLK 3 -/* - * Sleep mode control. - * VREQ_COUNT[7:1] Number of cycles to wait when requesting PMIC to raise the - * voltage after returning from sleep mode. - */ -#define SCP_CLK_SLEEP_CTRL REG32(SCP_CLK_BASE + 0x20) -#define EN_SLEEP_CTRL BIT(0) -#define VREQ_COUNTER_MASK 0xfe -#define VREQ_COUNTER_VAL(v) (((v) << 1) & VREQ_COUNTER_MASK) -#define SPM_SLEEP_MODE BIT(8) -#define SPM_SLEEP_MODE_CLK_AO BIT(9) -#define SCP_CLK_DIV_SEL REG32(SCP_CLK_BASE + 0x24) -#define CLK_DIV1 0 -#define CLK_DIV2 1 -#define CLK_DIV4 2 -#define CLK_DIV8 3 -#define SCP_CLK_DEBUG REG32(SCP_CLK_BASE + 0x28) -#define SCP_CLK_SRAM_POWERDOWN REG32(SCP_CLK_BASE + 0x2C) -#define SCP_CLK_GATE REG32(SCP_CLK_BASE + 0x30) -#define CG_TIMER_M BIT(0) -#define CG_TIMER_B BIT(1) -#define CG_MAD_M BIT(2) -#define CG_I2C_M BIT(3) -#define CG_I2C_B BIT(4) -#define CG_GPIO_M BIT(5) -#define CG_AP2P_M BIT(6) -#define CG_UART_M BIT(7) -#define CG_UART_B BIT(8) -#define CG_UART_RSTN BIT(9) -#define CG_UART1_M BIT(10) -#define CG_UART1_B BIT(11) -#define CG_UART1_RSTN BIT(12) -#define CG_SPI0 BIT(13) -#define CG_SPI1 BIT(14) -#define CG_SPI2 BIT(15) -#define CG_DMA_CH0 BIT(16) -#define CG_DMA_CH1 BIT(17) -#define CG_DMA_CH2 BIT(18) -#define CG_DMA_CH3 BIT(19) -#define CG_TWAM BIT(20) -#define CG_CACHE_I_CTRL BIT(21) -#define CG_CACHE_D_CTRL BIT(22) -#define SCP_PMICW_CTRL REG32(SCP_CLK_BASE + 0x34) -#define PMICW_SLEEP_REQ BIT(0) -#define PMICW_SLEEP_ACK BIT(4) -#define PMICW_CLK_MUX BIT(8) -#define PMICW_DCM BIT(9) -#define SCP_SLEEP_WAKE_DEBUG REG32(SCP_CLK_BASE + 0x38) -#define SCP_DCM_EN REG32(SCP_CLK_BASE + 0x3C) -#define SCP_WAKE_CKSW REG32(SCP_CLK_BASE + 0x40) -#define WAKE_CKSW_SEL_NORMAL_MASK 0x3 -#define WAKE_CKSW_SEL_SLOW_MASK 0x30 -#define WAKE_CKSW_SEL_SLOW_DEFAULT 0x10 -#define SCP_CLK_UART REG32(SCP_CLK_BASE + 0x44) -#define CLK_UART_SEL_MASK 0x3 -#define CLK_UART_SEL_26M 0x0 -#define CLK_UART_SEL_32K 0x1 -/* This is named ulposc_div_to_26m in datasheet */ -#define CLK_UART_SEL_ULPOSC1_DIV10 0x2 -#define CLK_UART1_SEL_MASK (0x3 << 16) -#define CLK_UART1_SEL_26M (0x0 << 16) -#define CLK_UART1_SEL_32K (0x1 << 16) -/* This is named ulposc_div_to_26m in datasheet */ -#define CLK_UART1_SEL_ULPOSC1_DIV10 (0x2 << 16) -#define SCP_CLK_BCLK REG32(SCP_CLK_BASE + 0x48) -#define CLK_BCLK_SEL_MASK 0x3 -#define CLK_BCLK_SEL_SYS_DIV8 0x0 -#define CLK_BCLK_SEL_32K 0x1 -#define CLK_BCLK_SEL_ULPOSC1_DIV8 0x2 -#define SCP_CLK_SPI_BCK REG32(SCP_CLK_BASE + 0x4C) -#define SCP_CLK_DIV_CNT REG32(SCP_CLK_BASE + 0x50) -#define SCP_CPU_VREQ REG32(SCP_CLK_BASE + 0x54) -#define CPU_VREQ_HW_MODE 0x10001 -#define SCP_CLK_CLEAR REG32(SCP_CLK_BASE + 0x58) -#define SCP_CLK_HIGH_CORE REG32(SCP_CLK_BASE + 0x5C) -#define CLK_HIGH_CORE_CG (1 << 1) -#define SCP_SLEEP_IRQ2 REG32(SCP_CLK_BASE + 0x64) -#define SCP_CLK_ON_CTRL REG32(SCP_CLK_BASE + 0x6C) -#define HIGH_AO BIT(0) -#define HIGH_CG_AO BIT(2) -#define HIGH_CORE_AO BIT(4) -#define HIGH_CORE_DIS_SUB BIT(5) -#define HIGH_CORE_CG_AO BIT(6) -#define HIGH_FINAL_VAL_MASK 0x1f00 -#define HIGH_FINAL_VAL_DEFAULT 0x300 -#define SCP_CLK_L1_SRAM_PD REG32(SCP_CLK_BASE + 0x80) -#define SCP_CLK_TCM_TAIL_SRAM_PD REG32(SCP_CLK_BASE + 0x94) -#define SCP_CLK_SLEEP REG32(SCP_CLK_BASE + 0xA0) -#define SLOW_WAKE_DISABLE 1 -#define SCP_FAST_WAKE_CNT_END REG32(SCP_CLK_BASE + 0xA4) -#define FAST_WAKE_CNT_END_MASK 0xfff -#define FAST_WAKE_CNT_END_DEFAULT 0x18 -#define MEM_CK_CS_ISO_CNT_END_MASK 0x7f0000 - -/* Peripherals */ -#define SCP_I2C0_BASE (SCP_CFG_BASE + 0x5000) -#define SCP_I2C1_BASE (SCP_CFG_BASE + 0x6000) -#define SCP_I2C2_BASE (SCP_CFG_BASE + 0x7000) - -#define SCP_GPIO_BASE (SCP_CFG_BASE + 0x8000) -#define SCP_UART0_BASE (SCP_CFG_BASE + 0x9000) -#define SCP_UART1_BASE (SCP_CFG_BASE + 0xE000) -#define SCP_UART_COUNT 2 - -/* External GPIO interrupt */ -#define SCP_EINT_BASE (SCP_CFG_BASE + 0xA000) -#define SCP_EINT_STATUS REG32_ADDR(SCP_EINT_BASE) -#define SCP_EINT_ACK REG32_ADDR(SCP_EINT_BASE + 0x040) -#define SCP_EINT_MASK_GET REG32_ADDR(SCP_EINT_BASE + 0x080) -#define SCP_EINT_MASK_SET REG32_ADDR(SCP_EINT_BASE + 0x0C0) -#define SCP_EINT_MASK_CLR REG32_ADDR(SCP_EINT_BASE + 0x100) -#define SCP_EINT_SENS_GET REG32_ADDR(SCP_EINT_BASE + 0x140) -#define SCP_EINT_SENS_SET REG32_ADDR(SCP_EINT_BASE + 0x180) -#define SCP_EINT_SENS_CLR REG32_ADDR(SCP_EINT_BASE + 0x1C0) -#define SCP_EINT_SOFT_GET REG32_ADDR(SCP_EINT_BASE + 0x200) -#define SCP_EINT_SOFT_SET REG32_ADDR(SCP_EINT_BASE + 0x240) -#define SCP_EINT_SOFT_CLR REG32_ADDR(SCP_EINT_BASE + 0x280) -#define SCP_EINT_POLARITY_GET REG32_ADDR(SCP_EINT_BASE + 0x300) -#define SCP_EINT_POLARITY_SET REG32_ADDR(SCP_EINT_BASE + 0x340) -#define SCP_EINT_POLARITY_CLR REG32_ADDR(SCP_EINT_BASE + 0x380) -#define SCP_EINT_D0_EN REG32_ADDR(SCP_EINT_BASE + 0x400) -#define SCP_EINT_D1_EN REG32_ADDR(SCP_EINT_BASE + 0x420) -#define SCP_EINT_DBNC_GET REG32_ADDR(SCP_EINT_BASE + 0x500) -#define SCP_EINT_DBNC_SET REG32_ADDR(SCP_EINT_BASE + 0x600) -#define SCP_EINT_DBNC_CLR REG32_ADDR(SCP_EINT_BASE + 0x700) - -#define SCP_PMICWP2P_BASE (SCP_CFG_BASE + 0xB000) -#define PMICW_WACS_CMD REG32(SCP_PMICWP2P_BASE + 0x200) -#define PMICW_WACS_RDATA REG32(SCP_PMICWP2P_BASE + 0x204) -#define PMICW_WACS_VLDCLR REG32(SCP_PMICWP2P_BASE + 0x208) -#define SCP_SPMP2P_BASE (SCP_CFG_BASE + 0xC000) -#define SCP_DMA_BASE (SCP_CFG_BASE + 0xD000) -#define DMA_ACKINT_CHX REG32(SCP_DMA_BASE + 0x20) -#define SCP_SPI0_BASE (SCP_CFG_BASE + 0xF000) -#define SCP_SPI1_BASE (SCP_CFG_BASE + 0x10000) -#define SCP_SPI2_BASE (SCP_CFG_BASE + 0x11000) - -#define CACHE_ICACHE 0 -#define CACHE_DCACHE 1 -#define CACHE_COUNT 2 -#define SCP_CACHE_BASE (SCP_CFG_BASE + 0x14000) -#define SCP_CACHE_SEL(x) (SCP_CACHE_BASE + (x)*0x3000) -#define SCP_CACHE_CON(x) REG32(SCP_CACHE_SEL(x)) -#define SCP_CACHE_CON_MCEN BIT(0) -#define SCP_CACHE_CON_CNTEN0 BIT(2) -#define SCP_CACHE_CON_CNTEN1 BIT(3) -#define SCP_CACHE_CON_CACHESIZE_SHIFT 8 -#define SCP_CACHE_CON_CACHESIZE_MASK (0x3 << SCP_CACHE_CON_CACHESIZE_SHIFT) -#define SCP_CACHE_CON_CACHESIZE_0KB (0x0 << SCP_CACHE_CON_CACHESIZE_SHIFT) -#define SCP_CACHE_CON_CACHESIZE_8KB (0x1 << SCP_CACHE_CON_CACHESIZE_SHIFT) -#define SCP_CACHE_CON_CACHESIZE_16KB (0x2 << SCP_CACHE_CON_CACHESIZE_SHIFT) -#define SCP_CACHE_CON_CACHESIZE_32KB (0x3 << SCP_CACHE_CON_CACHESIZE_SHIFT) -#define SCP_CACHE_CON_WAYEN BIT(10) - -#define SCP_CACHE_OP(x) REG32(SCP_CACHE_SEL(x) + 0x04) -#define SCP_CACHE_OP_EN BIT(0) -#define SCP_CACHE_OP_OP_SHIFT 1 -#define SCP_CACHE_OP_OP_MASK (0xf << SCP_CACHE_OP_OP_SHIFT) - -#define OP_INVALIDATE_ALL_LINES (0x1 << SCP_CACHE_OP_OP_SHIFT) -#define OP_INVALIDATE_ONE_LINE_BY_ADDRESS (0x2 << SCP_CACHE_OP_OP_SHIFT) -#define OP_INVALIDATE_ONE_LINE_BY_SET_WAY (0x4 << SCP_CACHE_OP_OP_SHIFT) -#define OP_CACHE_FLUSH_ALL_LINES (0x9 << SCP_CACHE_OP_OP_SHIFT) -#define OP_CACHE_FLUSH_ONE_LINE_BY_ADDRESS (0xa << SCP_CACHE_OP_OP_SHIFT) -#define OP_CACHE_FLUSH_ONE_LINE_BY_SET_WAY (0xc << SCP_CACHE_OP_OP_SHIFT) - -#define SCP_CACHE_OP_TADDR_SHIFT 5 -#define SCP_CACHE_OP_TADDR_MASK (0x7ffffff << SCP_CACHE_OP_TADDR_SHIFT) -#define SCP_CACHE_LINE_SIZE BIT(SCP_CACHE_OP_TADDR_SHIFT) - -/* Cache statistics */ -#define SCP_CACHE_HCNT0L(x) REG32(SCP_CACHE_SEL(x) + 0x08) -#define SCP_CACHE_HCNT0U(x) REG32(SCP_CACHE_SEL(x) + 0x0c) -#define SCP_CACHE_CCNT0L(x) REG32(SCP_CACHE_SEL(x) + 0x10) -#define SCP_CACHE_CCNT0U(x) REG32(SCP_CACHE_SEL(x) + 0x14) -#define SCP_CACHE_HCNT1L(x) REG32(SCP_CACHE_SEL(x) + 0x18) -#define SCP_CACHE_HCNT1U(x) REG32(SCP_CACHE_SEL(x) + 0x1c) -#define SCP_CACHE_CCNT1L(x) REG32(SCP_CACHE_SEL(x) + 0x20) -#define SCP_CACHE_CCNT1U(x) REG32(SCP_CACHE_SEL(x) + 0x24) - -#define SCP_CACHE_REGION_EN(x) REG32(SCP_CACHE_SEL(x) + 0x2c) - -#define SCP_CACHE_ENTRY_BASE(x) (SCP_CACHE_SEL(x) + 0x2000) -#define SCP_CACHE_ENTRY(x, reg) REG32(SCP_CACHE_ENTRY_BASE(x) + (reg)*4) -#define SCP_CACHE_END_ENTRY_BASE(x) (SCP_CACHE_SEL(x) + 0x2040) -#define SCP_CACHE_END_ENTRY(x, reg) REG32(SCP_CACHE_END_ENTRY_BASE(x) + \ - (reg)*4) -#define SCP_CACHE_ENTRY_C BIT(8) -#define SCP_CACHE_ENTRY_BASEADDR_MASK (0xfffff << 12) - -/* ARMV7 regs */ -#define ARM_SCB_SCR REG32(0xE000ED10) -#define SCR_DEEPSLEEP BIT(2) - -/* AP regs */ -#define AP_BASE 0xA0000000 -#define TOPCK_BASE AP_BASE /* Top clock */ -#define SCP_UART2_BASE (AP_BASE + 0x01002000) /* AP UART0 */ - -/* CLK_CFG_5 regs */ -#define AP_CLK_CFG_5 REG32(TOPCK_BASE + 0x0090) -#define PWRAP_ULPOSC_MASK (0x3000000) -#define CLK26M (0 << 24) -#define OSC_D16 (1 << 24) -#define OSC_D4 (2 << 24) -#define OSC_D8 (3 << 24) -#define AP_CLK_CFG_5_CLR REG32(TOPCK_BASE + 0x0098) -#define PWRAP_ULPOSC_CG BIT(31) - -/* OSC meter */ -#define AP_CLK_MISC_CFG_0 REG32(TOPCK_BASE + 0x0104) -#define MISC_METER_DIVISOR_MASK 0xff000000 -#define MISC_METER_DIV_1 0 -#define AP_CLK_DBG_CFG REG32(TOPCK_BASE + 0x010C) -#define DBG_MODE_MASK 3 -#define DBG_MODE_SET_CLOCK 0 -#define DBG_BIST_SOURCE_MASK (0x3f << 16) -#define DBG_BIST_SOURCE_ULPOSC1 (0x26 << 16) -#define DBG_BIST_SOURCE_ULPOSC2 (0x25 << 16) -#define AP_SCP_CFG_0 REG32(TOPCK_BASE + 0x0220) -#define CFG_FREQ_METER_RUN (1 << 4) -#define CFG_FREQ_METER_ENABLE (1 << 12) -#define AP_SCP_CFG_1 REG32(TOPCK_BASE + 0x0224) -#define CFG_FREQ_COUNTER(CFG1) ((CFG1) & 0xFFFF) - -/* GPIO */ -#define AP_GPIO_BASE (AP_BASE + 0x00005000) -/* - * AP_GPIO_DIR - * GPIO input/out direction, 1 bit per pin. - * 0:input 1:output - */ -#define AP_GPIO_DIR(n) REG32(AP_GPIO_BASE + ((n) << 4)) -/* - * AP_GPIO_DOUT, n in [0..5] - * GPIO output level, 1 bit per pin - * 0:low 1:high - */ -#define AP_GPIO_DOUT(n) REG32(AP_GPIO_BASE + 0x100 + ((n) << 4)) -/* - * AP_GPIO_DIN, n in [0..5] - * GPIO input level, 1 bit per pin - * 0:low 1:high - */ -#define AP_GPIO_DIN(n) REG32(AP_GPIO_BASE + 0x200 + ((n) << 4)) -/* - * AP_GPIO_MODE, n in [0..22] - * Pin mode selection, 4 bit per pin - * bit3 - write enable, set to 1 for hw to fetch bit2,1,0. - * bit2-0 - mode 0 ~ 7 - */ -#define AP_GPIO_MODE(n) REG32(AP_GPIO_BASE + 0x300 + ((n) << 4)) -#define AP_GPIO_TRAP REG32(AP_GPIO_BASE + 0x6B0) -#define AP_GPIO_UNIMPLEMENTED REG32(AP_GPIO_BASE + 0x6C0) -#define AP_GPIO_DBG REG32(AP_GPIO_BASE + 0x6D0) -#define AP_GPIO_BANK REG32(AP_GPIO_BASE + 0x6E0) -/* AP_GPIO_SEC, n in [0..5] */ -#define AP_GPIO_SEC(n) REG32(AP_GPIO_BASE + 0xF00 + ((n) << 4)) - -/* - * PLL ULPOSC - * ULPOSC1: AP_ULPOSC_CON[0] AP_ULPOSC_CON[1] - * ULPOSC2: AP_ULPOSC_CON[2] AP_ULPOSC_CON[3] - * osc: 0 for ULPOSC1, 1 for ULPSOC2. - */ -#define AP_ULPOSC_BASE0 (AP_BASE + 0xC700) -#define AP_ULPOSC_BASE1 (AP_BASE + 0xC704) -#define AP_ULPOSC_CON02(osc) REG32(AP_ULPOSC_BASE0 + (osc) * 0x8) -#define AP_ULPOSC_CON13(osc) REG32(AP_ULPOSC_BASE1 + (osc) * 0x8) -/* - * AP_ULPOSC_CON[0,2] - * bit0-5: calibration - * bit6-12: I-band - * bit13-16: F-band - * bit17-22: div - * bit23: CP_EN - * bit24-31: reserved - */ -#define OSC_CALI_MSK (0x3f << 0) -#define OSC_CALI_BITS 6 -#define OSC_IBAND_MASK (0x7f << 6) -#define OSC_FBAND_MASK (0x0f << 13) -#define OSC_DIV_MASK (0x1f << 17) -#define OSC_DIV_BITS 5 -#define OSC_CP_EN BIT(23) -#define OSC_RESERVED_MASK (0xff << 24) -/* AP_ULPOSC_CON[1,3] */ -#define OSC_MOD_MASK (0x03 << 0) -#define OSC_DIV2_EN BIT(2) - -#define UNIMPLEMENTED_GPIO_BANK 0 - -#ifndef __ASSEMBLER__ - -/* - * Cortex-M4 mod - * Available power saving features: - * 1. FPU freeze - freeze FPU operand when FPU is not used - * 2. LSU gating - gate LSU clock when not LSU operation - * 3. Trace clk disable - gate trace clock - * 4. DCM for CPU stall - gate CPU clock when CPU stall - */ -#define CM4_MODIFICATION REG32(0xE00FE000) -#define CM4_DCM_FEATURE REG32(0xE00FE004) -/* UART, 16550 compatible */ -#define SCP_UART_BASE(n) CONCAT3(SCP_UART, n, _BASE) -#define UART_REG(n, offset) REG32_ADDR(SCP_UART_BASE(n))[offset] -#define UART_IRQ(n) CONCAT2(SCP_IRQ_UART, n) -#define UART_RX_IRQ(n) CONCAT3(SCP_IRQ_UART, n, _RX) - -/* Watchdog */ -#define SCP_WDT_BASE (SCP_CFG_BASE + 0x84) -#define SCP_WDT_REG(offset) REG32(SCP_WDT_BASE + offset) -#define SCP_WDT_CFG SCP_WDT_REG(0) -#define SCP_WDT_FREQ 33825 -#define SCP_WDT_MAX_PERIOD 0xFFFFF /* 31 seconds */ -#define SCP_WDT_PERIOD(ms) (SCP_WDT_FREQ * (ms) / 1000) -#define SCP_WDT_ENABLE BIT(31) -#define SCP_WDT_RELOAD SCP_WDT_REG(4) -#define SCP_WDT_RELOAD_VALUE 1 - -#endif /* !__ASSEMBLER__ */ -#endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/mt_scp/rv32i_common/build.mk b/chip/mt_scp/rv32i_common/build.mk new file mode 100644 index 0000000000..eff299f98d --- /dev/null +++ b/chip/mt_scp/rv32i_common/build.mk @@ -0,0 +1,27 @@ +# -*- makefile -*- +# Copyright 2020 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# SCP specific files build +# + +CORE:=riscv-rv32i + +# Required chip modules +chip-y+=rv32i_common/cache.o +chip-y+=rv32i_common/gpio.o +chip-y+=rv32i_common/intc.o +chip-y+=rv32i_common/memmap.o +chip-y+=rv32i_common/system.o +chip-y+=rv32i_common/uart.o + +ifeq ($(CONFIG_IPI),y) +$(out)/RW/chip/$(CHIP)/rv32i_common/ipi_table.o: $(out)/ipi_table_gen.inc +endif + +# Optional chip modules +chip-$(CONFIG_COMMON_TIMER)+=rv32i_common/hrtimer.o +chip-$(CONFIG_IPI)+=rv32i_common/ipi.o rv32i_common/ipi_table.o +chip-$(CONFIG_WATCHDOG)+=rv32i_common/watchdog.o +chip-$(HAS_TASK_HOSTCMD)+=rv32i_common/hostcmd.o diff --git a/chip/mt_scp/rv32i_common/cache.c b/chip/mt_scp/rv32i_common/cache.c new file mode 100644 index 0000000000..b04f28ebae --- /dev/null +++ b/chip/mt_scp/rv32i_common/cache.c @@ -0,0 +1,205 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cache.h" +#include "console.h" +#include "csr.h" + +extern struct mpu_entry mpu_entries[]; + +void cache_init(void) +{ + int i; + uint32_t mpu_en = 0; + + /* disable mpu */ + clear_csr(CSR_MCTREN, CSR_MCTREN_MPU); + + /* enable i$, d$ */ + set_csr(CSR_MCTREN, CSR_MCTREN_ICACHE); + set_csr(CSR_MCTREN, CSR_MCTREN_DCACHE); + + /* invalidate icache and dcache */ + cache_invalidate_icache(); + cache_invalidate_dcache(); + + /* set mpu entries + * + * The pragma is for force GCC unrolls the following loop. + * See b/172886808 + */ +#pragma GCC unroll 16 + for (i = 0; i < NR_MPU_ENTRIES; ++i) { + if (mpu_entries[i].end_addr - mpu_entries[i].start_addr) { + write_csr(CSR_MPU_L(i), + mpu_entries[i].start_addr | + mpu_entries[i].attribute); + write_csr(CSR_MPU_H(i), mpu_entries[i].end_addr); + mpu_en |= BIT(i); + } + } + + /* enable mpu entries */ + write_csr(CSR_MPU_ENTRY_EN, mpu_en); + + /* enable mpu */ + set_csr(CSR_MCTREN, CSR_MCTREN_MPU); + + /* fence */ + asm volatile("fence.i" ::: "memory"); +} + +#ifdef DEBUG +/* + * I for I-cache + * D for D-cache + * C for control transfer instructions (branch, jump, ret, interrupt, ...) + */ +static enum { PMU_SELECT_I = 0, PMU_SELECT_D, PMU_SELECT_C } pmu_select; + +int command_enable_pmu(int argc, const char **argv) +{ + static const char *const selectors[] = { + [PMU_SELECT_I] = "I", + [PMU_SELECT_D] = "D", + [PMU_SELECT_C] = "C", + }; + int i; + + if (argc != 2) + return EC_ERROR_PARAM1; + + for (i = 0; i < ARRAY_SIZE(selectors); ++i) { + if (strcasecmp(argv[1], selectors[i]) == 0) { + pmu_select = i; + break; + } + } + if (i >= ARRAY_SIZE(selectors)) + return EC_ERROR_PARAM1; + + ccprintf("select \"%s\"\n", selectors[pmu_select]); + + /* disable all PMU */ + clear_csr(CSR_PMU_MPMUCTR, + CSR_PMU_MPMUCTR_C | CSR_PMU_MPMUCTR_I | CSR_PMU_MPMUCTR_H3 | + CSR_PMU_MPMUCTR_H4 | CSR_PMU_MPMUCTR_H5); + + /* reset cycle count */ + write_csr(CSR_PMU_MCYCLE, 0); + write_csr(CSR_PMU_MCYCLEH, 0); + /* reset retired-instruction count */ + write_csr(CSR_PMU_MINSTRET, 0); + write_csr(CSR_PMU_MINSTRETH, 0); + /* reset counter{3,4,5} */ + write_csr(CSR_PMU_MHPMCOUNTER3, 0); + write_csr(CSR_PMU_MHPMCOUNTER3H, 0); + write_csr(CSR_PMU_MHPMCOUNTER4, 0); + write_csr(CSR_PMU_MHPMCOUNTER4H, 0); + write_csr(CSR_PMU_MHPMCOUNTER5, 0); + write_csr(CSR_PMU_MHPMCOUNTER5H, 0); + + /* select different event IDs for counter{3,4,5} */ + switch (pmu_select) { + case PMU_SELECT_I: + /* I-cache access count */ + write_csr(CSR_PMU_MHPMEVENT3, 1); + /* I-cache miss count */ + write_csr(CSR_PMU_MHPMEVENT4, 3); + /* noncacheable I-AXI access count */ + write_csr(CSR_PMU_MHPMEVENT5, 5); + break; + case PMU_SELECT_D: + /* D-cache access count */ + write_csr(CSR_PMU_MHPMEVENT3, 11); + /* D-cache miss count */ + write_csr(CSR_PMU_MHPMEVENT4, 12); + /* noncacheable D-AXI access count */ + write_csr(CSR_PMU_MHPMEVENT5, 14); + break; + case PMU_SELECT_C: + /* control transfer instruction count */ + write_csr(CSR_PMU_MHPMEVENT3, 27); + /* control transfer miss-predict count */ + write_csr(CSR_PMU_MHPMEVENT4, 28); + /* interrupt count */ + write_csr(CSR_PMU_MHPMEVENT5, 29); + break; + } + + cache_invalidate_icache(); + cache_flush_dcache(); + + /* enable all PMU */ + set_csr(CSR_PMU_MPMUCTR, + CSR_PMU_MPMUCTR_C | CSR_PMU_MPMUCTR_I | CSR_PMU_MPMUCTR_H3 | + CSR_PMU_MPMUCTR_H4 | CSR_PMU_MPMUCTR_H5); + + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(enable_pmu, command_enable_pmu, "[I | D | C]", + "Enable PMU"); + +int command_disable_pmu(int argc, const char **argv) +{ + clear_csr(CSR_PMU_MPMUCTR, + CSR_PMU_MPMUCTR_C | CSR_PMU_MPMUCTR_I | CSR_PMU_MPMUCTR_H3 | + CSR_PMU_MPMUCTR_H4 | CSR_PMU_MPMUCTR_H5); + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(disable_pmu, command_disable_pmu, NULL, + "Disable PMU"); + +int command_show_pmu(int argc, const char **argv) +{ + uint64_t val3, val4, val5; + uint32_t p; + + val3 = ((uint64_t)read_csr(CSR_PMU_MCYCLEH) << 32) | + read_csr(CSR_PMU_MCYCLE); + ccprintf("cycles: %lld\n", val3); + + val3 = ((uint64_t)read_csr(CSR_PMU_MINSTRETH) << 32) | + read_csr(CSR_PMU_MINSTRET); + ccprintf("retired instructions: %lld\n", val3); + + val3 = ((uint64_t)read_csr(CSR_PMU_MHPMCOUNTER3H) << 32) | + read_csr(CSR_PMU_MHPMCOUNTER3); + val4 = ((uint64_t)read_csr(CSR_PMU_MHPMCOUNTER4H) << 32) | + read_csr(CSR_PMU_MHPMCOUNTER4); + val5 = ((uint64_t)read_csr(CSR_PMU_MHPMCOUNTER5H) << 32) | + read_csr(CSR_PMU_MHPMCOUNTER5); + + if (val3) + p = val4 * 10000 / val3; + else + p = 0; + + switch (pmu_select) { + case PMU_SELECT_I: + ccprintf("I-cache:\n"); + ccprintf(" access: %lld\n", val3); + ccprintf(" miss: %lld (%d.%d%%)\n", val4, p / 100, p % 100); + ccprintf("non-cacheable I: %lld\n", val5); + break; + case PMU_SELECT_D: + ccprintf("D-cache:\n"); + ccprintf(" access: %lld\n", val3); + ccprintf(" miss: %lld (%d.%d%%)\n", val4, p / 100, p % 100); + ccprintf("non-cacheable D: %lld\n", val5); + break; + case PMU_SELECT_C: + ccprintf("control transfer instruction:\n"); + ccprintf(" total: %lld\n", val3); + ccprintf(" miss-predict: %lld (%d.%d%%)\n", val4, p / 100, + p % 100); + ccprintf("interrupts: %lld\n", val5); + break; + } + + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(show_pmu, command_show_pmu, NULL, "Show PMU"); +#endif diff --git a/chip/mt_scp/rv32i_common/cache.h b/chip/mt_scp/rv32i_common/cache.h new file mode 100644 index 0000000000..15572962ac --- /dev/null +++ b/chip/mt_scp/rv32i_common/cache.h @@ -0,0 +1,140 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_CACHE_H +#define __CROS_EC_CACHE_H + +#include "common.h" +#include "csr.h" +#include "stdint.h" +#include "util.h" + +/* rs1 0~31 register X0~X31 */ +#define COP(rs1) (((rs1) << 15) | 0x400f) + +#define COP_OP_BARRIER_ICACHE 0x0 +#define COP_OP_INVALIDATE_ICACHE 0x8 +#define COP_OP_INVALIDATE_ICACHE_ADDR 0x9 + +#define COP_OP_BARRIER_DCACHE 0x10 +#define COP_OP_WRITEBACK_DCACHE 0x14 +#define COP_OP_WRITEBACK_DCACHE_ADDR 0x15 +#define COP_OP_INVALIDATE_DCACHE 0x18 +#define COP_OP_INVALIDATE_DCACHE_ADDR 0x19 +/* FLUSH = WRITEBACK + INVALIDATE */ +#define COP_OP_FLUSH_DCACHE 0x1C +#define COP_OP_FLUSH_DCACHE_ADDR 0x1D + +static inline void cache_op_all(uint32_t op) +{ + register int t0 asm("t0") = op; + asm volatile(".word " STRINGIFY(COP(5))::"r"(t0)); +} + +static inline int cache_op_addr(uintptr_t addr, uint32_t length, uint32_t op) +{ + size_t offset; + register int t0 asm("t0"); + + /* NOTE: cache operations must use 32 byte aligned address */ + if (addr & GENMASK(3, 0)) + return EC_ERROR_INVAL; + + for (offset = 0; offset < length; offset += 4) { + t0 = addr + offset + op; + asm volatile(".word " STRINGIFY(COP(5))::"r"(t0)); + } + + return EC_SUCCESS; +} + +/* memory barrier of I$ */ +static inline void cache_barrier_icache(void) +{ + cache_op_all(COP_OP_BARRIER_ICACHE); +} + +/* invalidate all I$ */ +static inline void cache_invalidate_icache(void) +{ + cache_op_all(COP_OP_INVALIDATE_ICACHE); +} + +/* invalidate a range of I$ */ +static inline int cache_invalidate_icache_range(uintptr_t addr, uint32_t length) +{ + return cache_op_addr(addr, length, COP_OP_INVALIDATE_ICACHE_ADDR); +} + +/* memory barrier of D$ */ +static inline void cache_barrier_dcache(void) +{ + cache_op_all(COP_OP_BARRIER_DCACHE); +} + +/* writeback all D$ */ +static inline void cache_writeback_dcache(void) +{ + cache_op_all(COP_OP_WRITEBACK_DCACHE); + cache_barrier_icache(); + cache_barrier_dcache(); +} + +/* writeback a range of D$ */ +static inline int cache_writeback_dcache_range(uintptr_t addr, uint32_t length) +{ + int ret = cache_op_addr(addr, length, COP_OP_WRITEBACK_DCACHE_ADDR); + cache_barrier_icache(); + cache_barrier_dcache(); + return ret; +} + +/* invalidate all D$ */ +static inline void cache_invalidate_dcache(void) +{ + cache_op_all(COP_OP_INVALIDATE_DCACHE); +} + +/* invalidate a range of D$ */ +static inline int cache_invalidate_dcache_range(uintptr_t addr, uint32_t length) +{ + return cache_op_addr(addr, length, COP_OP_INVALIDATE_DCACHE_ADDR); +} + +/* writeback and invalidate all D$ */ +static inline void cache_flush_dcache(void) +{ + cache_op_all(COP_OP_FLUSH_DCACHE); + cache_barrier_icache(); + cache_barrier_dcache(); +} + +/* writeback and invalidate a range of D$ */ +static inline int cache_flush_dcache_range(uintptr_t addr, uint32_t length) +{ + int ret = cache_op_addr(addr, length, COP_OP_FLUSH_DCACHE_ADDR); + cache_barrier_icache(); + cache_barrier_dcache(); + return ret; +} + +struct mpu_entry { + /* 1k alignment and the address is inclusive */ + uintptr_t start_addr; + /* 1k alignment in 4GB boundary and non-inclusive */ + uintptr_t end_addr; + /* MPU_ATTR */ + uint32_t attribute; +}; + +void cache_init(void); + +#ifdef DEBUG +int command_enable_pmu(int argc, const char **argv); +int command_disable_pmu(int argc, const char **argv); +int command_show_pmu(int argc, const char **argv); +#endif + +#endif /* #ifndef __CROS_EC_CACHE_H */ diff --git a/chip/mt_scp/rv32i_common/config_chip.h b/chip/mt_scp/rv32i_common/config_chip.h new file mode 100644 index 0000000000..775dd02461 --- /dev/null +++ b/chip/mt_scp/rv32i_common/config_chip.h @@ -0,0 +1,57 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_CONFIG_CHIP_H +#define __CROS_EC_CONFIG_CHIP_H + +#include "core/riscv-rv32i/config_core.h" + +/* Interval between HOOK_TICK notifications */ +#define HOOK_TICK_INTERVAL_MS 500 +#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) + +/* RW only, no flash */ +#undef CONFIG_FW_INCLUDE_RO +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_SIZE 0 +#define CONFIG_RW_MEM_OFF 0 +#define CONFIG_RW_SIZE 0x40000 /* 256KB */ +#define CONFIG_EC_WRITABLE_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_PROGRAM_MEMORY_BASE 0 +#define CONFIG_PROGRAM_MEMORY_BASE_LOAD 0x10500000 +#define CONFIG_MAPPED_STORAGE_BASE 0 + +/* Unsupported features/commands */ +#undef CONFIG_CMD_FLASHINFO +#undef CONFIG_CMD_POWER_AP +#undef CONFIG_FLASH_CROS +#undef CONFIG_FLASH_PHYSICAL +#undef CONFIG_FMAP +#undef CONFIG_HIBERNATE +#undef CONFIG_LID_SWITCH + +/* Task stack size */ +#define CONFIG_STACK_SIZE 1024 +#define IDLE_TASK_STACK_SIZE 640 +#define SMALLER_TASK_STACK_SIZE 384 +#define TASK_STACK_SIZE 488 +#define LARGER_TASK_STACK_SIZE 640 +#define VENTI_TASK_STACK_SIZE 768 +#define ULTRA_TASK_STACK_SIZE 1056 +#define TRENTA_TASK_STACK_SIZE 1184 + +/* TODO: need to confirm, placeholder */ +#define GPIO_PIN(num) ((num) / 32), ((num) % 32) +#define GPIO_PIN_MASK(p, m) .port = (p), .mask = (m) +#undef CONFIG_TASK_PROFILING +/* TODO: not yet supported */ +#undef CONFIG_MPU +/* TODO: core/riscv-rv32i pollution */ +#define __ram_code + +#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/mt_scp/rv32i_common/csr.h b/chip/mt_scp/rv32i_common/csr.h new file mode 100644 index 0000000000..88ea869cbd --- /dev/null +++ b/chip/mt_scp/rv32i_common/csr.h @@ -0,0 +1,111 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Control and status register */ + +/* TODO: move to core/riscv-rv32i? */ + +#ifndef __CROS_EC_CSR_H +#define __CROS_EC_CSR_H + +#include "common.h" + +static inline uint32_t read_csr(uint32_t reg) +{ + uint32_t val; + + asm volatile("csrr %0, %1" : "=r"(val) : "i"(reg)); + return val; +} + +static inline void write_csr(uint32_t reg, uint32_t val) +{ + asm volatile("csrw %0, %1" ::"i"(reg), "r"(val)); +} + +static inline uint32_t set_csr(uint32_t reg, uint32_t bit) +{ + uint32_t val; + + asm volatile("csrrs %0, %1, %2" : "=r"(val) : "i"(reg), "r"(bit)); + return val; +} + +static inline uint32_t clear_csr(uint32_t reg, uint32_t bit) +{ + uint32_t val; + + asm volatile("csrrc %0, %1, %2" : "=r"(val) : "i"(reg), "r"(bit)); + return val; +} + +/* VIC */ +#define CSR_VIC_MICAUSE (0x5c0) +#define CSR_VIC_MIEMS (0x5c2) +#define CSR_VIC_MIPEND_G0 (0x5d0) +#define CSR_VIC_MIMASK_G0 (0x5d8) +#define CSR_VIC_MIWAKEUP_G0 (0x5e0) +#define CSR_VIC_MILSEL_G0 (0x5e8) +#define CSR_VIC_MIEMASK_G0 (0x5f0) + +/* centralized control enable */ +#define CSR_MCTREN (0x7c0) +/* I$, D$, ITCM, DTCM, BTB, RAS, VIC, CG, mpu */ +#define CSR_MCTREN_ICACHE BIT(0) +#define CSR_MCTREN_DCACHE BIT(1) +#define CSR_MCTREN_ITCM BIT(2) +#define CSR_MCTREN_DTCM BIT(3) +#define CSR_MCTREN_BTB BIT(4) +#define CSR_MCTREN_RAS BIT(5) +#define CSR_MCTREN_VIC BIT(6) +#define CSR_MCTREN_CG BIT(7) +#define CSR_MCTREN_MPU BIT(8) + +/* MPU */ +#define CSR_MPU_ENTRY_EN (0x9c0) +#define CSR_MPU_LITCM (0x9dc) +#define CSR_MPU_LDTCM (0x9dd) +#define CSR_MPU_HITCM (0x9de) +#define CSR_MPU_HDTCM (0x9df) +#define CSR_MPU_L(n) (0x9e0 + (n)) +#define CSR_MPU_H(n) (0x9f0 + (n)) +/* MPU attributes: set if permitted */ +/* Privilege, machine mode in RISC-V. We don't use the flag because + * we don't separate user / machine mode in EC OS. */ +#define MPU_ATTR_P BIT(5) +/* Readable */ +#define MPU_ATTR_R BIT(6) +/* Writable */ +#define MPU_ATTR_W BIT(7) +/* Cacheable */ +#define MPU_ATTR_C BIT(8) +/* Bufferable */ +#define MPU_ATTR_B BIT(9) + +/* PMU */ +#define CSR_PMU_MPMUCTR (0xbc0) +#define CSR_PMU_MPMUCTR_C BIT(0) +#define CSR_PMU_MPMUCTR_I BIT(1) +#define CSR_PMU_MPMUCTR_H3 BIT(2) +#define CSR_PMU_MPMUCTR_H4 BIT(3) +#define CSR_PMU_MPMUCTR_H5 BIT(4) + +#define CSR_PMU_MCYCLE (0xb00) +#define CSR_PMU_MINSTRET (0xb02) +#define CSR_PMU_MHPMCOUNTER3 (0xb03) +#define CSR_PMU_MHPMCOUNTER4 (0xb04) +#define CSR_PMU_MHPMCOUNTER5 (0xb05) + +#define CSR_PMU_MCYCLEH (0xb80) +#define CSR_PMU_MINSTRETH (0xb82) +#define CSR_PMU_MHPMCOUNTER3H (0xb83) +#define CSR_PMU_MHPMCOUNTER4H (0xb84) +#define CSR_PMU_MHPMCOUNTER5H (0xb85) + +#define CSR_PMU_MHPMEVENT3 (0x323) +#define CSR_PMU_MHPMEVENT4 (0x324) +#define CSR_PMU_MHPMEVENT5 (0x325) + +#endif /* __CROS_EC_CSR_H */ diff --git a/chip/mt_scp/rv32i_common/gpio.c b/chip/mt_scp/rv32i_common/gpio.c new file mode 100644 index 0000000000..d56cff97fb --- /dev/null +++ b/chip/mt_scp/rv32i_common/gpio.c @@ -0,0 +1,21 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* GPIO module */ + +#include "gpio.h" + +void gpio_pre_init(void) +{ +} + +test_mockable int gpio_get_level(enum gpio_signal signal) +{ + return 0; +} + +void gpio_set_level(enum gpio_signal signal, int value) +{ +} diff --git a/chip/mt8192_scp/hostcmd.c b/chip/mt_scp/rv32i_common/hostcmd.c similarity index 95% rename from chip/mt8192_scp/hostcmd.c rename to chip/mt_scp/rv32i_common/hostcmd.c index 42a463ee56..fee1ce110a 100644 --- a/chip/mt8192_scp/hostcmd.c +++ b/chip/mt_scp/rv32i_common/hostcmd.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -97,7 +97,8 @@ DECLARE_IPI(SCP_IPI_HOST_COMMAND, hostcmd_handler, 0); /* * Get protocol information */ -static enum ec_status hostcmd_get_protocol_info(struct host_cmd_handler_args *args) +static enum ec_status +hostcmd_get_protocol_info(struct host_cmd_handler_args *args) { struct ec_response_get_protocol_info *r = args->response; diff --git a/chip/mt8192_scp/hostcmd.h b/chip/mt_scp/rv32i_common/hostcmd.h similarity index 79% rename from chip/mt8192_scp/hostcmd.h rename to chip/mt_scp/rv32i_common/hostcmd.h index b93f1e725d..067a4c14ab 100644 --- a/chip/mt8192_scp/hostcmd.h +++ b/chip/mt_scp/rv32i_common/hostcmd.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/mt_scp/rv32i_common/hrtimer.c b/chip/mt_scp/rv32i_common/hrtimer.c new file mode 100644 index 0000000000..fff5fb6436 --- /dev/null +++ b/chip/mt_scp/rv32i_common/hrtimer.c @@ -0,0 +1,231 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * High-res hardware timer + * + * SCP hardware 32bit count down timer can be configured to source clock from + * 32KHz, 26MHz, BCLK or PCLK. This implementation selects BCLK (ULPOSC1/8) as a + * source, countdown mode and converts to micro second value matching common + * timer. + */ + +#include "common.h" +#include "hwtimer.h" +#include "registers.h" +#include "scp_timer.h" +#include "task.h" + +#define TIMER_SYSTEM 5 +#define TIMER_EVENT 3 +#define TIMER_CLOCK_MHZ 32.5 +#define OVERFLOW_TICKS (TIMER_CLOCK_MHZ * 0x100000000 - 1) + +/* High 32-bit for system timer. */ +static uint8_t sys_high; +/* High 32-bit for event timer. */ +static uint8_t event_high; + +void timer_enable(int n) +{ + /* cannot be changed when timer is enabled */ + SCP_CORE0_TIMER_IRQ_CTRL(n) |= TIMER_IRQ_EN; + SCP_CORE0_TIMER_EN(n) |= TIMER_EN; +} + +void timer_disable(int n) +{ + SCP_CORE0_TIMER_EN(n) &= ~TIMER_EN; + /* cannot be changed when timer is enabled */ + SCP_CORE0_TIMER_IRQ_CTRL(n) &= ~TIMER_IRQ_EN; +} + +uint32_t timer_read_raw_sr(void) +{ + return SCP_CORE0_TIMER_CUR_VAL(TIMER_SR); +} + +static int timer_is_irq(int n) +{ + return SCP_CORE0_TIMER_IRQ_CTRL(n) & TIMER_IRQ_STATUS; +} + +static void timer_ack_irq(int n) +{ + SCP_CORE0_TIMER_IRQ_CTRL(n) |= TIMER_IRQ_CLR; +} + +static void timer_set_reset_value(int n, uint32_t reset_value) +{ + /* cannot be changed when timer is enabled */ + SCP_CORE0_TIMER_RST_VAL(n) = reset_value; +} + +static void timer_set_clock(int n, uint32_t clock_source) +{ + SCP_CORE0_TIMER_EN(n) = (SCP_CORE0_TIMER_EN(n) & ~TIMER_CLK_SRC_MASK) | + clock_source; +} + +static void timer_reset(int n) +{ + timer_disable(n); + timer_ack_irq(n); + timer_set_reset_value(n, 0xffffffff); + timer_set_clock(n, TIMER_CLK_SRC_32K); +} + +/* Convert hardware countdown timer to 64bit countup ticks. */ +static uint64_t timer_read_raw_system(void) +{ + uint32_t timer_ctrl = SCP_CORE0_TIMER_IRQ_CTRL(TIMER_SYSTEM); + uint32_t sys_high_adj = sys_high; + + /* + * If an IRQ is pending, but has not been serviced yet, adjust the + * sys_high value. + */ + if (timer_ctrl & TIMER_IRQ_STATUS) + sys_high_adj = sys_high ? (sys_high - 1) : + (TIMER_CLOCK_MHZ - 1); + + return OVERFLOW_TICKS - (((uint64_t)sys_high_adj << 32) | + SCP_CORE0_TIMER_CUR_VAL(TIMER_SYSTEM)); +} + +static uint64_t timer_read_raw_event(void) +{ + return OVERFLOW_TICKS - (((uint64_t)event_high << 32) | + SCP_CORE0_TIMER_CUR_VAL(TIMER_EVENT)); +} + +static void timer_reload(int n, uint32_t value) +{ + timer_disable(n); + timer_set_reset_value(n, value); + timer_enable(n); +} + +static int timer_reload_event_high(void) +{ + if (event_high) { + if (SCP_CORE0_TIMER_RST_VAL(TIMER_EVENT) == 0xffffffff) + timer_enable(TIMER_EVENT); + else + timer_reload(TIMER_EVENT, 0xffffffff); + event_high--; + return 1; + } + + timer_disable(TIMER_EVENT); + return 0; +} + +int __hw_clock_source_init(uint32_t start_t) +{ + int t; + + /* enable clock gate */ + SCP_SET_CLK_CG |= CG_TIMER_MCLK | CG_TIMER_BCLK; + + /* reset all timer, select 32768Hz clock source */ + for (t = 0; t < NUM_TIMERS; ++t) + timer_reset(t); + + /* System timestamp timer */ + timer_set_clock(TIMER_SYSTEM, TIMER_CLK_SRC_BCLK); + sys_high = TIMER_CLOCK_MHZ - 1; + timer_set_reset_value(TIMER_SYSTEM, 0xffffffff); + task_enable_irq(SCP_IRQ_TIMER(TIMER_SYSTEM)); + timer_enable(TIMER_SYSTEM); + + /* Event tick timer */ + timer_set_clock(TIMER_EVENT, TIMER_CLK_SRC_BCLK); + task_enable_irq(SCP_IRQ_TIMER(TIMER_EVENT)); + + /* SR timer */ + timer_set_clock(TIMER_SR, TIMER_CLK_SRC_26M); + task_disable_irq(SCP_IRQ_TIMER(TIMER_SR)); + + return SCP_IRQ_TIMER(TIMER_SYSTEM); +} + +uint32_t __hw_clock_source_read(void) +{ + return timer_read_raw_system() / TIMER_CLOCK_MHZ; +} + +uint32_t __hw_clock_event_get(void) +{ + return (timer_read_raw_event() + timer_read_raw_system()) / + TIMER_CLOCK_MHZ; +} + +void __hw_clock_event_clear(void) +{ + /* c1ea4, magic number for clear state */ + timer_disable(TIMER_EVENT); + timer_set_reset_value(TIMER_EVENT, 0x0000c1ea4); + event_high = 0; +} + +void __hw_clock_event_set(uint32_t deadline) +{ + uint64_t deadline_raw = (uint64_t)deadline * TIMER_CLOCK_MHZ; + uint64_t now_raw = timer_read_raw_system(); + uint32_t event_deadline; + + if (deadline_raw > now_raw) { + deadline_raw -= now_raw; + event_deadline = (uint32_t)deadline_raw; + event_high = deadline_raw >> 32; + } else { + event_deadline = 1; + event_high = 0; + } + + if (event_deadline) + timer_reload(TIMER_EVENT, event_deadline); + else + timer_reload_event_high(); +} + +static void irq_group6_handler(void) +{ + extern volatile int ec_int; + + switch (ec_int) { + case SCP_IRQ_TIMER(TIMER_EVENT): + if (timer_is_irq(TIMER_EVENT)) { + timer_ack_irq(TIMER_EVENT); + + if (!timer_reload_event_high()) + process_timers(0); + + task_clear_pending_irq(ec_int); + } + break; + case SCP_IRQ_TIMER(TIMER_SYSTEM): + /* If this is a hardware irq, check overflow */ + if (!in_soft_interrupt_context()) { + timer_ack_irq(TIMER_SYSTEM); + + if (sys_high) { + --sys_high; + process_timers(0); + } else { + /* Overflow, reload system timer */ + sys_high = TIMER_CLOCK_MHZ - 1; + process_timers(1); + } + + task_clear_pending_irq(ec_int); + } else { + process_timers(0); + } + break; + } +} +DECLARE_IRQ(6, irq_group6_handler, 0); diff --git a/chip/mt_scp/rv32i_common/intc.c b/chip/mt_scp/rv32i_common/intc.c new file mode 100644 index 0000000000..641d0cf516 --- /dev/null +++ b/chip/mt_scp/rv32i_common/intc.c @@ -0,0 +1,425 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* INTC control module */ + +#include "console.h" +#include "csr.h" +#include "intc.h" +#include "registers.h" + +/* + * INTC_GRP_0 is reserved. See swirq of syscall_handler() in + * core/riscv-rv32i/task.c for more details. + * + * Lower group has higher priority. Group 0 has highest priority. + */ +enum INTC_GROUP { + INTC_GRP_0 = 0x0, + INTC_GRP_1, + INTC_GRP_2, + INTC_GRP_3, + INTC_GRP_4, + INTC_GRP_5, + INTC_GRP_6, + INTC_GRP_7, + INTC_GRP_8, + INTC_GRP_9, + INTC_GRP_10, + INTC_GRP_11, + INTC_GRP_12, + INTC_GRP_13, + INTC_GRP_14, +}; + +#ifdef BOARD_ASURADA_SCP +static struct { + uint8_t group; +} irqs[SCP_INTC_IRQ_COUNT] = { + /* 0 */ + [SCP_IRQ_GIPC_IN0] = { INTC_GRP_7 }, + [SCP_IRQ_GIPC_IN1] = { INTC_GRP_0 }, + [SCP_IRQ_GIPC_IN2] = { INTC_GRP_0 }, + [SCP_IRQ_GIPC_IN3] = { INTC_GRP_0 }, + /* 4 */ + [SCP_IRQ_SPM] = { INTC_GRP_0 }, + [SCP_IRQ_AP_CIRQ] = { INTC_GRP_0 }, + [SCP_IRQ_EINT] = { INTC_GRP_0 }, + [SCP_IRQ_PMIC] = { INTC_GRP_0 }, + /* 8 */ + [SCP_IRQ_UART0_TX] = { INTC_GRP_12 }, + [SCP_IRQ_UART1_TX] = { INTC_GRP_12 }, + [SCP_IRQ_I2C0] = { INTC_GRP_0 }, + [SCP_IRQ_I2C1_0] = { INTC_GRP_0 }, + /* 12 */ + [SCP_IRQ_BUS_DBG_TRACKER] = { INTC_GRP_0 }, + [SCP_IRQ_CLK_CTRL] = { INTC_GRP_0 }, + [SCP_IRQ_VOW] = { INTC_GRP_0 }, + [SCP_IRQ_TIMER0] = { INTC_GRP_6 }, + /* 16 */ + [SCP_IRQ_TIMER1] = { INTC_GRP_6 }, + [SCP_IRQ_TIMER2] = { INTC_GRP_6 }, + [SCP_IRQ_TIMER3] = { INTC_GRP_6 }, + [SCP_IRQ_TIMER4] = { INTC_GRP_6 }, + /* 20 */ + [SCP_IRQ_TIMER5] = { INTC_GRP_6 }, + [SCP_IRQ_OS_TIMER] = { INTC_GRP_0 }, + [SCP_IRQ_UART0_RX] = { INTC_GRP_12 }, + [SCP_IRQ_UART1_RX] = { INTC_GRP_12 }, + /* 24 */ + [SCP_IRQ_GDMA] = { INTC_GRP_0 }, + [SCP_IRQ_AUDIO] = { INTC_GRP_0 }, + [SCP_IRQ_MD_DSP] = { INTC_GRP_0 }, + [SCP_IRQ_ADSP] = { INTC_GRP_0 }, + /* 28 */ + [SCP_IRQ_CPU_TICK] = { INTC_GRP_0 }, + [SCP_IRQ_SPI0] = { INTC_GRP_0 }, + [SCP_IRQ_SPI1] = { INTC_GRP_0 }, + [SCP_IRQ_SPI2] = { INTC_GRP_0 }, + /* 32 */ + [SCP_IRQ_NEW_INFRA_SYS_CIRQ] = { INTC_GRP_0 }, + [SCP_IRQ_DBG] = { INTC_GRP_0 }, + [SCP_IRQ_CCIF0] = { INTC_GRP_0 }, + [SCP_IRQ_CCIF1] = { INTC_GRP_0 }, + /* 36 */ + [SCP_IRQ_CCIF2] = { INTC_GRP_0 }, + [SCP_IRQ_WDT] = { INTC_GRP_0 }, + [SCP_IRQ_USB0] = { INTC_GRP_0 }, + [SCP_IRQ_USB1] = { INTC_GRP_0 }, + /* 40 */ + [SCP_IRQ_DPMAIF] = { INTC_GRP_0 }, + [SCP_IRQ_INFRA] = { INTC_GRP_0 }, + [SCP_IRQ_CLK_CTRL_CORE] = { INTC_GRP_0 }, + [SCP_IRQ_CLK_CTRL2_CORE] = { INTC_GRP_0 }, + /* 44 */ + [SCP_IRQ_CLK_CTRL2] = { INTC_GRP_0 }, + [SCP_IRQ_GIPC_IN4] = { INTC_GRP_0 }, + [SCP_IRQ_PERIBUS_TIMEOUT] = { INTC_GRP_0 }, + [SCP_IRQ_INFRABUS_TIMEOUT] = { INTC_GRP_0 }, + /* 48 */ + [SCP_IRQ_MET0] = { INTC_GRP_0 }, + [SCP_IRQ_MET1] = { INTC_GRP_0 }, + [SCP_IRQ_MET2] = { INTC_GRP_0 }, + [SCP_IRQ_MET3] = { INTC_GRP_0 }, + /* 52 */ + [SCP_IRQ_AP_WDT] = { INTC_GRP_0 }, + [SCP_IRQ_L2TCM_SEC_VIO] = { INTC_GRP_0 }, + [SCP_IRQ_CPU_TICK1] = { INTC_GRP_0 }, + [SCP_IRQ_MAD_DATAIN] = { INTC_GRP_0 }, + /* 56 */ + [SCP_IRQ_I3C0_IBI_WAKE] = { INTC_GRP_0 }, + [SCP_IRQ_I3C1_IBI_WAKE] = { INTC_GRP_0 }, + [SCP_IRQ_I3C2_IBI_WAKE] = { INTC_GRP_0 }, + [SCP_IRQ_APU_ENGINE] = { INTC_GRP_0 }, + /* 60 */ + [SCP_IRQ_MBOX0] = { INTC_GRP_0 }, + [SCP_IRQ_MBOX1] = { INTC_GRP_0 }, + [SCP_IRQ_MBOX2] = { INTC_GRP_0 }, + [SCP_IRQ_MBOX3] = { INTC_GRP_0 }, + /* 64 */ + [SCP_IRQ_MBOX4] = { INTC_GRP_0 }, + [SCP_IRQ_SYS_CLK_REQ] = { INTC_GRP_0 }, + [SCP_IRQ_BUS_REQ] = { INTC_GRP_0 }, + [SCP_IRQ_APSRC_REQ] = { INTC_GRP_0 }, + /* 68 */ + [SCP_IRQ_APU_MBOX] = { INTC_GRP_0 }, + [SCP_IRQ_DEVAPC_SECURE_VIO] = { INTC_GRP_0 }, + /* 72 */ + /* 76 */ + [SCP_IRQ_I2C1_2] = { INTC_GRP_0 }, + [SCP_IRQ_I2C2] = { INTC_GRP_0 }, + /* 80 */ + [SCP_IRQ_AUD2AUDIODSP] = { INTC_GRP_0 }, + [SCP_IRQ_AUD2AUDIODSP_2] = { INTC_GRP_0 }, + [SCP_IRQ_CONN2ADSP_A2DPOL] = { INTC_GRP_0 }, + [SCP_IRQ_CONN2ADSP_BTCVSD] = { INTC_GRP_0 }, + /* 84 */ + [SCP_IRQ_CONN2ADSP_BLEISO] = { INTC_GRP_0 }, + [SCP_IRQ_PCIE2ADSP] = { INTC_GRP_0 }, + [SCP_IRQ_APU2ADSP_ENGINE] = { INTC_GRP_0 }, + [SCP_IRQ_APU2ADSP_MBOX] = { INTC_GRP_0 }, + /* 88 */ + [SCP_IRQ_CCIF3] = { INTC_GRP_0 }, + [SCP_IRQ_I2C_DMA0] = { INTC_GRP_0 }, + [SCP_IRQ_I2C_DMA1] = { INTC_GRP_0 }, + [SCP_IRQ_I2C_DMA2] = { INTC_GRP_0 }, + /* 92 */ + [SCP_IRQ_I2C_DMA3] = { INTC_GRP_0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(irqs) == SCP_INTC_IRQ_COUNT); +#endif + +#ifdef BOARD_CHERRY_SCP +static struct { + uint8_t group; +} irqs[SCP_INTC_IRQ_COUNT] = { + /* 0 */ + [SCP_IRQ_GIPC_IN0] = { INTC_GRP_7 }, + [SCP_IRQ_GIPC_IN1] = { INTC_GRP_0 }, + [SCP_IRQ_GIPC_IN2] = { INTC_GRP_0 }, + [SCP_IRQ_GIPC_IN3] = { INTC_GRP_0 }, + /* 4 */ + [SCP_IRQ_SPM] = { INTC_GRP_0 }, + [SCP_IRQ_AP_CIRQ] = { INTC_GRP_0 }, + [SCP_IRQ_EINT] = { INTC_GRP_0 }, + [SCP_IRQ_PMIC] = { INTC_GRP_0 }, + /* 8 */ + [SCP_IRQ_UART0_TX] = { INTC_GRP_12 }, + [SCP_IRQ_UART1_TX] = { INTC_GRP_12 }, + [SCP_IRQ_I2C0] = { INTC_GRP_0 }, + [SCP_IRQ_I2C1_0] = { INTC_GRP_0 }, + /* 12 */ + [SCP_IRQ_BUS_DBG_TRACKER] = { INTC_GRP_0 }, + [SCP_IRQ_CLK_CTRL] = { INTC_GRP_0 }, + [SCP_IRQ_VOW] = { INTC_GRP_0 }, + [SCP_IRQ_TIMER0] = { INTC_GRP_6 }, + /* 16 */ + [SCP_IRQ_TIMER1] = { INTC_GRP_6 }, + [SCP_IRQ_TIMER2] = { INTC_GRP_6 }, + [SCP_IRQ_TIMER3] = { INTC_GRP_6 }, + [SCP_IRQ_TIMER4] = { INTC_GRP_6 }, + /* 20 */ + [SCP_IRQ_TIMER5] = { INTC_GRP_6 }, + [SCP_IRQ_OS_TIMER] = { INTC_GRP_0 }, + [SCP_IRQ_UART0_RX] = { INTC_GRP_12 }, + [SCP_IRQ_UART1_RX] = { INTC_GRP_12 }, + /* 24 */ + [SCP_IRQ_GDMA] = { INTC_GRP_0 }, + [SCP_IRQ_AUDIO] = { INTC_GRP_0 }, + [SCP_IRQ_MD_DSP] = { INTC_GRP_0 }, + [SCP_IRQ_ADSP] = { INTC_GRP_0 }, + /* 28 */ + [SCP_IRQ_CPU_TICK] = { INTC_GRP_0 }, + [SCP_IRQ_SPI0] = { INTC_GRP_0 }, + [SCP_IRQ_SPI1] = { INTC_GRP_0 }, + [SCP_IRQ_SPI2] = { INTC_GRP_0 }, + /* 32 */ + [SCP_IRQ_NEW_INFRA_SYS_CIRQ] = { INTC_GRP_0 }, + [SCP_IRQ_DBG] = { INTC_GRP_0 }, + [SCP_IRQ_GCE] = { INTC_GRP_0 }, + [SCP_IRQ_MDP_GCE] = { INTC_GRP_0 }, + /* 36 */ + [SCP_IRQ_VDEC] = { INTC_GRP_8 }, + [SCP_IRQ_WDT] = { INTC_GRP_0 }, + [SCP_IRQ_VDEC_LAT] = { INTC_GRP_8 }, + [SCP_IRQ_VDEC1] = { INTC_GRP_8 }, + /* 40 */ + [SCP_IRQ_VDEC1_LAT] = { INTC_GRP_8 }, + [SCP_IRQ_INFRA] = { INTC_GRP_0 }, + [SCP_IRQ_CLK_CTRL_CORE] = { INTC_GRP_0 }, + [SCP_IRQ_CLK_CTRL2_CORE] = { INTC_GRP_0 }, + /* 44 */ + [SCP_IRQ_CLK_CTRL2] = { INTC_GRP_0 }, + [SCP_IRQ_GIPC_IN4] = { INTC_GRP_0 }, + [SCP_IRQ_PERIBUS_TIMEOUT] = { INTC_GRP_0 }, + [SCP_IRQ_INFRABUS_TIMEOUT] = { INTC_GRP_0 }, + /* 48 */ + [SCP_IRQ_MET0] = { INTC_GRP_0 }, + [SCP_IRQ_MET1] = { INTC_GRP_0 }, + [SCP_IRQ_MET2] = { INTC_GRP_0 }, + [SCP_IRQ_MET3] = { INTC_GRP_0 }, + /* 52 */ + [SCP_IRQ_AP_WDT] = { INTC_GRP_0 }, + [SCP_IRQ_L2TCM_SEC_VIO] = { INTC_GRP_0 }, + [SCP_IRQ_VDEC_INT_LINE_CNT] = { INTC_GRP_0 }, + [SCP_IRQ_VOW_DATAIN] = { INTC_GRP_0 }, + /* 56 */ + [SCP_IRQ_I3C0_IBI_WAKE] = { INTC_GRP_0 }, + [SCP_IRQ_I3C1_IBI_WAKE] = { INTC_GRP_0 }, + [SCP_IRQ_VENC] = { INTC_GRP_8 }, + [SCP_IRQ_APU_ENGINE] = { INTC_GRP_0 }, + /* 60 */ + [SCP_IRQ_MBOX0] = { INTC_GRP_0 }, + [SCP_IRQ_MBOX1] = { INTC_GRP_0 }, + [SCP_IRQ_MBOX2] = { INTC_GRP_0 }, + [SCP_IRQ_MBOX3] = { INTC_GRP_0 }, + /* 64 */ + [SCP_IRQ_MBOX4] = { INTC_GRP_0 }, + [SCP_IRQ_SYS_CLK_REQ] = { INTC_GRP_0 }, + [SCP_IRQ_BUS_REQ] = { INTC_GRP_0 }, + [SCP_IRQ_APSRC_REQ] = { INTC_GRP_0 }, + /* 68 */ + [SCP_IRQ_APU_MBOX] = { INTC_GRP_0 }, + [SCP_IRQ_DEVAPC_SECURE_VIO] = { INTC_GRP_0 }, + [SCP_IRQ_APDMA0] = { INTC_GRP_0 }, + [SCP_IRQ_APDMA1] = { INTC_GRP_0 }, + /* 72 */ + [SCP_IRQ_APDMA2] = { INTC_GRP_0 }, + [SCP_IRQ_APDMA3] = { INTC_GRP_0 }, + [SCP_IRQ_APDMA4] = { INTC_GRP_0 }, + [SCP_IRQ_APDMA5] = { INTC_GRP_0 }, + /* 76 */ + [SCP_IRQ_HDMIRX_PM_DVI_SQH] = { INTC_GRP_0 }, + [SCP_IRQ_HDMIRX_RESERVED] = { INTC_GRP_0 }, + [SCP_IRQ_NNA0_0] = { INTC_GRP_0 }, + [SCP_IRQ_NNA0_1] = { INTC_GRP_0 }, + /* 80 */ + [SCP_IRQ_NNA0_2] = { INTC_GRP_0 }, + [SCP_IRQ_NNA1_0] = { INTC_GRP_0 }, + [SCP_IRQ_NNA1_1] = { INTC_GRP_0 }, + [SCP_IRQ_NNA1_2] = { INTC_GRP_0 }, + /* 84 */ + [SCP_IRQ_JPEGENC] = { INTC_GRP_0 }, + [SCP_IRQ_JPEGDEC] = { INTC_GRP_0 }, + [SCP_IRQ_JPEGDEC_C2] = { INTC_GRP_0 }, + [SCP_IRQ_VENC_C1] = { INTC_GRP_8 }, + /* 88 */ + [SCP_IRQ_JPEGENC_C1] = { INTC_GRP_0 }, + [SCP_IRQ_JPEGDEC_C1] = { INTC_GRP_0 }, + [SCP_IRQ_HDMITX] = { INTC_GRP_0 }, + [SCP_IRQ_HDMI2] = { INTC_GRP_0 }, + /* 92 */ + [SCP_IRQ_EARC] = { INTC_GRP_0 }, + [SCP_IRQ_CEC] = { INTC_GRP_0 }, + [SCP_IRQ_HDMI_DEV_DET] = { INTC_GRP_0 }, + [SCP_IRQ_HDMIRX_OUT_ARM_PHY] = { INTC_GRP_0 }, + /* 96 */ + [SCP_IRQ_I2C2] = { INTC_GRP_0 }, + [SCP_IRQ_I2C3] = { INTC_GRP_0 }, + [SCP_IRQ_I3C2_IBI_WAKE] = { INTC_GRP_0 }, + [SCP_IRQ_I3C3_IBI_WAKE] = { INTC_GRP_0 }, + /* 100 */ + [SCP_IRQ_SYS_I2C_0] = { INTC_GRP_0 }, + [SCP_IRQ_SYS_I2C_1] = { INTC_GRP_0 }, + [SCP_IRQ_SYS_I2C_2] = { INTC_GRP_0 }, + [SCP_IRQ_SYS_I2C_3] = { INTC_GRP_0 }, + /* 104 */ + [SCP_IRQ_SYS_I2C_4] = { INTC_GRP_0 }, + [SCP_IRQ_SYS_I2C_5] = { INTC_GRP_0 }, + [SCP_IRQ_SYS_I2C_6] = { INTC_GRP_0 }, + [SCP_IRQ_SYS_I2C_7] = { INTC_GRP_0 }, + /* 108 */ + [SCP_IRQ_DISP2ADSP_0] = { INTC_GRP_0 }, + [SCP_IRQ_DISP2ADSP_1] = { INTC_GRP_0 }, + [SCP_IRQ_DISP2ADSP_2] = { INTC_GRP_0 }, + [SCP_IRQ_DISP2ADSP_3] = { INTC_GRP_0 }, + /* 112 */ + [SCP_IRQ_DISP2ADSP_4] = { INTC_GRP_0 }, + [SCP_IRQ_VDO1_DISP_MON2ADSP_0] = { INTC_GRP_0 }, + [SCP_IRQ_VDO1_DISP_MON2ADSP_1] = { INTC_GRP_0 }, + [SCP_IRQ_VDO1_DISP_MON2ADSP_2] = { INTC_GRP_0 }, + /* 116 */ + [SCP_IRQ_GCE1_SECURE] = { INTC_GRP_0 }, + [SCP_IRQ_GCE_SECURE] = { INTC_GRP_0 }, +}; +BUILD_ASSERT(ARRAY_SIZE(irqs) == SCP_INTC_IRQ_COUNT); +#endif + +/* + * Find current interrupt source. + * + * Lower group has higher priority. + * Higher INT number has higher priority. + */ +#define EC_INT_MAGIC_DUMP_GROUP BIT(15) +int chip_get_ec_int(void) +{ + extern volatile int ec_int; + unsigned int group, sta; + int word; + + group = read_csr(CSR_VIC_MICAUSE); + + if (!SCP_CORE0_INTC_IRQ_OUT) { + ec_int = EC_INT_MAGIC_DUMP_GROUP | group; + goto error; + } + + for (word = SCP_INTC_GRP_LEN - 1; word >= 0; --word) { + sta = SCP_CORE0_INTC_IRQ_GRP_STA(group, word); + if (sta) { + ec_int = __fls(sta) + word * 32; + return ec_int; + } + } + +error: + /* unreachable, SCP crashes and dumps registers after returning */ + return -1; +} + +int chip_get_intc_group(int irq) +{ + return irqs[irq].group; +} + +void chip_enable_irq(int irq) +{ + unsigned int word, group, mask; + + word = SCP_INTC_WORD(irq); + group = irqs[irq].group; + mask = BIT(SCP_INTC_BIT(irq)); + + /* disable interrupt */ + SCP_CORE0_INTC_IRQ_EN(word) &= ~mask; + /* set group */ + SCP_CORE0_INTC_IRQ_GRP(group, word) |= mask; + /* set as a wakeup source */ + SCP_CORE0_INTC_SLP_WAKE_EN(word) |= mask; + /* enable interrupt */ + SCP_CORE0_INTC_IRQ_EN(word) |= mask; +} + +void chip_disable_irq(int irq) +{ + /* + * Disabling INTC IRQ in runtime is unstable in MT8192 SCP. + * See b/163682416#comment17. + * + * Ideally, this function will be removed by LTO. + */ + ccprints("WARNING: %s is unsupported", __func__); +} + +void chip_clear_pending_irq(int irq) +{ + unsigned int group = irqs[irq].group; + + /* must clear interrupt source before writing this */ + write_csr(CSR_VIC_MIEMS, group); +} + +int chip_trigger_irq(int irq) +{ + extern volatile int ec_int; + + ec_int = irq; + return irqs[irq].group; +} + +void chip_init_irqs(void) +{ + unsigned int word, group; + + /* INTC init */ + /* clear enable and wakeup settings */ + for (word = 0; word < SCP_INTC_GRP_LEN; ++word) { + SCP_CORE0_INTC_IRQ_EN(word) = 0x0; + SCP_CORE0_INTC_SLP_WAKE_EN(word) = 0x0; + + /* clear group settings */ + for (group = 0; group < SCP_INTC_GRP_COUNT; ++group) + SCP_CORE0_INTC_IRQ_GRP(group, word) = 0x0; + } + /* reset to default polarity */ + SCP_CORE0_INTC_IRQ_POL(0) = SCP_INTC_IRQ_POL0; + SCP_CORE0_INTC_IRQ_POL(1) = SCP_INTC_IRQ_POL1; + SCP_CORE0_INTC_IRQ_POL(2) = SCP_INTC_IRQ_POL2; +#if SCP_INTC_GRP_LEN > 3 + SCP_CORE0_INTC_IRQ_POL(3) = SCP_INTC_IRQ_POL3; +#endif + + /* GVIC init */ + /* enable all groups as interrupt sources */ + write_csr(CSR_VIC_MIMASK_G0, 0xffffffff); + /* use level trigger */ + write_csr(CSR_VIC_MILSEL_G0, 0xffffffff); + /* enable all groups as wakeup sources */ + write_csr(CSR_VIC_MIWAKEUP_G0, 0xffffffff); + + /* enable GVIC */ + set_csr(CSR_MCTREN, CSR_MCTREN_VIC); +} diff --git a/chip/mt_scp/rv32i_common/ipi.c b/chip/mt_scp/rv32i_common/ipi.c new file mode 100644 index 0000000000..b8db16b9ea --- /dev/null +++ b/chip/mt_scp/rv32i_common/ipi.c @@ -0,0 +1,184 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "atomic.h" +#include "cache.h" +#include "common.h" +#include "console.h" +#include "hooks.h" +#include "hostcmd.h" +#include "ipi_chip.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "util.h" +#include "video.h" + +#define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) +#define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) + +static uint8_t init_done; + +static struct mutex ipi_lock; +static struct ipc_shared_obj *const ipi_send_buf = + (struct ipc_shared_obj *)CONFIG_IPC_SHARED_OBJ_ADDR; +static struct ipc_shared_obj *const ipi_recv_buf = + (struct ipc_shared_obj *)(CONFIG_IPC_SHARED_OBJ_ADDR + + sizeof(struct ipc_shared_obj)); + +static atomic_t disable_irq_count, saved_int_mask; + +void ipi_disable_irq(void) +{ + if (atomic_read_add(&disable_irq_count, 1) == 0) + saved_int_mask = read_clear_int_mask(); +} + +void ipi_enable_irq(void) +{ + if (atomic_read_sub(&disable_irq_count, 1) == 1) + set_int_mask(saved_int_mask); +} + +static int ipi_is_busy(void) +{ + return SCP_SCP2APMCU_IPC_SET & IPC_SCP2HOST; +} + +static void ipi_wake_ap(int32_t id) +{ + if (id >= IPI_COUNT) + return; + + if (*ipi_wakeup_table[id]) + SCP_SCP2SPM_IPC_SET = IPC_SCP2HOST; +} + +int ipi_send(int32_t id, const void *buf, uint32_t len, int wait) +{ + int ret; + + if (!init_done) { + CPRINTS("IPI has not initialized"); + return EC_ERROR_BUSY; + } + + if (in_interrupt_context()) { + CPRINTS("invoke %s() in ISR context", __func__); + return EC_ERROR_BUSY; + } + + if (len > sizeof(ipi_send_buf->buffer)) { + CPRINTS("data length exceeds limitation"); + return EC_ERROR_INVAL; + } + + ipi_disable_irq(); + mutex_lock(&ipi_lock); + + if (ipi_is_busy()) { + /* + * If the following conditions meet, + * 1) There is an IPI pending in AP. + * 2) The incoming IPI is a wakeup IPI. + * then it assumes that AP is in suspend state. + * Send a AP wakeup request to SPM. + * + * The incoming IPI will be checked if it's a wakeup source. + */ + ipi_wake_ap(id); + + CPRINTS("IPI busy, id=%d", id); + ret = EC_ERROR_BUSY; + goto error; + } + + ipi_send_buf->id = id; + ipi_send_buf->len = len; + memcpy(ipi_send_buf->buffer, buf, len); + + /* flush memory cache (if any) */ + cache_flush_dcache_range((uintptr_t)ipi_send_buf, + sizeof(*ipi_send_buf)); + + /* interrupt AP to handle the message */ + ipi_wake_ap(id); + SCP_SCP2APMCU_IPC_SET = IPC_SCP2HOST; + + if (wait) + while (ipi_is_busy()) + ; + + ret = EC_SUCCESS; +error: + mutex_unlock(&ipi_lock); + ipi_enable_irq(); + return ret; +} + +static void ipi_enable_deferred(void) +{ + struct scp_run_t scp_run; + int ret; + + init_done = 1; + + /* inform AP that SCP is up */ + scp_run.signaled = 1; + strncpy(scp_run.fw_ver, system_get_version(EC_IMAGE_RW), + SCP_FW_VERSION_LEN); + scp_run.dec_capability = video_get_dec_capability(); + scp_run.enc_capability = video_get_enc_capability(); + + ret = ipi_send(SCP_IPI_INIT, (void *)&scp_run, sizeof(scp_run), 1); + if (ret) { + CPRINTS("failed to send initialization IPC messages"); + init_done = 0; + return; + } + +#ifdef HAS_TASK_HOSTCMD + hostcmd_init(); +#endif + + task_enable_irq(SCP_IRQ_GIPC_IN0); +} +DECLARE_DEFERRED(ipi_enable_deferred); + +static void ipi_init(void) +{ + memset(ipi_send_buf, 0, sizeof(struct ipc_shared_obj)); + memset(ipi_recv_buf, 0, sizeof(struct ipc_shared_obj)); + + /* enable IRQ after all tasks are up */ + hook_call_deferred(&ipi_enable_deferred_data, 0); +} +DECLARE_HOOK(HOOK_INIT, ipi_init, HOOK_PRIO_DEFAULT); + +static void ipi_handler(void) +{ + if (ipi_recv_buf->id >= IPI_COUNT) { + CPRINTS("invalid IPI, id=%d", ipi_recv_buf->id); + return; + } + + CPRINTS("IPI %d", ipi_recv_buf->id); + + ipi_handler_table[ipi_recv_buf->id]( + ipi_recv_buf->id, ipi_recv_buf->buffer, ipi_recv_buf->len); +} + +static void irq_group7_handler(void) +{ + extern volatile int ec_int; + + if (SCP_GIPC_IN_SET & GIPC_IN(0)) { + ipi_handler(); + SCP_GIPC_IN_CLR = GIPC_IN(0); + asm volatile("fence.i" ::: "memory"); + task_clear_pending_irq(ec_int); + } +} +DECLARE_IRQ(7, irq_group7_handler, 0); diff --git a/chip/mt_scp/rv32i_common/ipi_chip.h b/chip/mt_scp/rv32i_common/ipi_chip.h new file mode 100644 index 0000000000..22ab85b39e --- /dev/null +++ b/chip/mt_scp/rv32i_common/ipi_chip.h @@ -0,0 +1,86 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_IPI_CHIP_H +#define __CROS_EC_IPI_CHIP_H + +#include "common.h" + +/* + * Length of EC version string is at most 32 byte (NULL included), which + * also aligns SCP fw_version length. + */ +#define SCP_FW_VERSION_LEN 32 + +#ifndef SCP_IPI_INIT +#error If CONFIG_IPI is enabled, SCP_IPI_INIT must be defined. +#endif + +/* + * Share buffer layout for SCP_IPI_INIT response. This structure should sync + * across kernel and EC. + */ +struct scp_run_t { + uint32_t signaled; + int8_t fw_ver[SCP_FW_VERSION_LEN]; + uint32_t dec_capability; + uint32_t enc_capability; +}; + +/* + * The layout of the IPC0 AP/SCP shared buffer. + * This should sync across kernel and EC. + */ +struct ipc_shared_obj { + /* IPI ID */ + int32_t id; + /* Length of the contents in buffer. */ + uint32_t len; + /* Shared buffer contents. */ + uint8_t buffer[CONFIG_IPC_SHARED_OBJ_BUF_SIZE]; +}; + +/* Send a IPI contents to AP. This shouldn't be used in ISR context. */ +int ipi_send(int32_t id, const void *buf, uint32_t len, int wait); + +/* + * An IPC IRQ could be shared across many IPI handlers. + * Those handlers would usually operate on disabling or enabling the IPC IRQ. + * This may disorder the actual timing to on/off the IRQ when there are many + * tasks try to operate on it. As a result, any access to the SCP_IRQ_* + * should go through ipi_{en,dis}able_irq(), which support a counter to + * enable/disable the IRQ at correct timing. + */ +/* Disable IPI IRQ. */ +void ipi_disable_irq(void); +/* Enable IPI IRQ. */ +void ipi_enable_irq(void); + +/* IPI tables */ +extern void (*const ipi_handler_table[])(int32_t, void *, uint32_t); +extern int *const ipi_wakeup_table[]; + +/* Helper macros to build the IPI handler and wakeup functions. */ +#define IPI_HANDLER(id) CONCAT3(ipi_, id, _handler) +#define IPI_WAKEUP(id) CONCAT3(ipi_, id, _wakeup) + +/* + * Macro to declare an IPI handler. + * _id: The ID of the IPI + * handler: The IPI handler function + * is_wakeup_src: Declare IPI ID as a wake-up source or not + */ +#define DECLARE_IPI(_id, handler, is_wakeup_src) \ + struct ipi_num_check##_id { \ + int tmp1[_id < IPI_COUNT ? 1 : -1]; \ + int tmp2[is_wakeup_src == 0 || is_wakeup_src == 1 ? 1 : -1]; \ + }; \ + void __keep IPI_HANDLER(_id)(int32_t id, void *buf, uint32_t len) \ + { \ + handler(id, buf, len); \ + } \ + const int __keep IPI_WAKEUP(_id) = is_wakeup_src + +#endif /* __CROS_EC_IPI_CHIP_H */ diff --git a/chip/mt_scp/rv32i_common/ipi_table.c b/chip/mt_scp/rv32i_common/ipi_table.c new file mode 100644 index 0000000000..3a6411d4d2 --- /dev/null +++ b/chip/mt_scp/rv32i_common/ipi_table.c @@ -0,0 +1,70 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * IPI handlers declaration + */ + +#include "common.h" +#include "ipi_chip.h" + +typedef void (*ipi_handler_t)(int32_t id, void *data, uint32_t len); + +#ifndef PASS +#define PASS 1 +#endif + +#define ipi_arguments int32_t id, void *data, uint32_t len + +#if PASS == 1 +void ipi_handler_undefined(ipi_arguments) +{ +} + +const int ipi_wakeup_undefined; + +#define table(type, name, x) x + +#define ipi_x_func(suffix, args, number) \ + extern void \ + __attribute__((used, weak, \ + alias(STRINGIFY(ipi_##suffix##_undefined)))) \ + ipi_##number##_##suffix(args); + +#define ipi_x_var(suffix, number) \ + extern int __attribute__((weak, \ + alias(STRINGIFY(ipi_##suffix##_undefined)))) \ + ipi_##number##_##suffix; + +#endif /* PASS == 1 */ + +#if PASS == 2 + +#undef table +#undef ipi_x_func +#undef ipi_x_var + +#define table(type, name, x) \ + type const name[] __attribute__((aligned(4), used, \ + section(".rodata.ipi"))) = { x } + +#define ipi_x_var(suffix, number) \ + [number < IPI_COUNT ? number : -1] = &ipi_##number##_##suffix, + +#define ipi_x_func(suffix, args, number) ipi_x_var(suffix, number) + +#endif /* PASS == 2 */ + +/* + * Include generated IPI table (by util/gen_ipi_table). The contents originate + * from IPI_COUNT definition in board.h + */ +#include "ipi_table_gen.inc" + +#if PASS == 1 +#undef PASS +#define PASS 2 +#include "ipi_table.c" +BUILD_ASSERT(ARRAY_SIZE(ipi_handler_table) == IPI_COUNT); +BUILD_ASSERT(ARRAY_SIZE(ipi_wakeup_table) == IPI_COUNT); +#endif diff --git a/chip/mt_scp/rv32i_common/memmap.c b/chip/mt_scp/rv32i_common/memmap.c new file mode 100644 index 0000000000..8ae64cf585 --- /dev/null +++ b/chip/mt_scp/rv32i_common/memmap.c @@ -0,0 +1,109 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cache.h" +#include "registers.h" +#include "stdint.h" + +/* + * Map SCP address (bits 31~28) to AP address + * + * SCP address AP address Note + * + * 0x0000_0000 SRAM + * 0x1000_0000 0x5000_0000 CPU DRAM + * 0x2000_0000 0x7000_0000 + * 0x3000_0000 + * + * 0x4000_0000 + * 0x5000_0000 0x0000_0000 + * 0x6000_0000 0x1000_0000 + * 0x7000_0000 0xa000_0000 + * + * 0x8000_0000 + * 0x9000_0000 0x8000_0000 + * 0xa000_0000 0x9000_0000 + * 0xb000_0000 + * + * 0xc000_0000 0x8000_0000 + * 0xd000_0000 0x2000_0000 + * 0xe000_0000 0x3000_0000 + * 0xf000_0000 0x6000_0000 + */ + +#define REMAP_ADDR_SHIFT 28 +#define REMAP_ADDR_LSB_MASK (BIT(REMAP_ADDR_SHIFT) - 1) +#define REMAP_ADDR_MSB_MASK ((~0) << REMAP_ADDR_SHIFT) +#define MAP_INVALID 0xff + +static const uint8_t addr_map[16] = { + MAP_INVALID, /* SRAM */ + 0x5, /* ext_addr_0x1 */ + 0x7, /* ext_addr_0x2 */ + MAP_INVALID, /* no ext_addr_0x3 */ + + MAP_INVALID, /* no ext_addr_0x4 */ + 0x0, /* ext_addr_0x5 */ + 0x1, /* ext_addr_0x6 */ + 0xa, /* ext_addr_0x7 */ + + MAP_INVALID, /* no ext_addr_0x8 */ + 0x8, /* ext_addr_0x9 */ + 0x9, /* ext_addr_0xa */ + MAP_INVALID, /* no ext_addr_0xb */ + + 0x8, /* ext_addr_0xc */ + 0x2, /* ext_addr_0xd */ + 0x3, /* ext_addr_0xe */ + 0x6, /* ext_addr_0xf */ +}; + +void memmap_init(void) +{ + SCP_R_REMAP_0X0123 = (uint32_t)addr_map[0x1] << 8 | + (uint32_t)addr_map[0x2] << 16; + + SCP_R_REMAP_0X4567 = (uint32_t)addr_map[0x5] << 8 | + (uint32_t)addr_map[0x6] << 16 | + (uint32_t)addr_map[0x7] << 24; + + SCP_R_REMAP_0X89AB = (uint32_t)addr_map[0x9] << 8 | + (uint32_t)addr_map[0xa] << 16; + + SCP_R_REMAP_0XCDEF = + (uint32_t)addr_map[0xc] | (uint32_t)addr_map[0xd] << 8 | + (uint32_t)addr_map[0xe] << 16 | (uint32_t)addr_map[0xf] << 24; + + cache_init(); +} + +int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr) +{ + int i; + uint8_t msb = ap_addr >> REMAP_ADDR_SHIFT; + + for (i = 0; i < ARRAY_SIZE(addr_map); ++i) { + if (addr_map[i] != msb) + continue; + + *scp_addr = (ap_addr & REMAP_ADDR_LSB_MASK) | + (i << REMAP_ADDR_SHIFT); + return EC_SUCCESS; + } + + return EC_ERROR_INVAL; +} + +int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr) +{ + int i = scp_addr >> REMAP_ADDR_SHIFT; + + if (addr_map[i] == MAP_INVALID) + return EC_ERROR_INVAL; + + *ap_addr = (scp_addr & REMAP_ADDR_LSB_MASK) | + (addr_map[i] << REMAP_ADDR_SHIFT); + return EC_SUCCESS; +} diff --git a/chip/mt_scp/rv32i_common/memmap.h b/chip/mt_scp/rv32i_common/memmap.h new file mode 100644 index 0000000000..2c043fbe9c --- /dev/null +++ b/chip/mt_scp/rv32i_common/memmap.h @@ -0,0 +1,31 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_MEMMAP_H +#define __CROS_EC_MEMMAP_H + +#include "stdint.h" + +void memmap_init(void); + +/** + * Translate AP addr to SCP addr. + * + * @param ap_addr AP address to translate + * @param scp_addr Translated AP address + * @return EC_SUCCESS or EC_ERROR_INVAL + */ +int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr); + +/** + * Translate SCP addr to AP addr. + * + * @param scp_addr SCP address to translate + * @param ap_addr Translated SCP address + * @return EC_SUCCESS or EC_ERROR_INVAL + */ +int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr); + +#endif /* #ifndef __CROS_EC_MEMMAP_H */ diff --git a/chip/mt_scp/rv32i_common/registers.h b/chip/mt_scp/rv32i_common/registers.h new file mode 100644 index 0000000000..8688bbc033 --- /dev/null +++ b/chip/mt_scp/rv32i_common/registers.h @@ -0,0 +1,216 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Register map */ + +#ifndef __CROS_EC_REGISTERS_H +#define __CROS_EC_REGISTERS_H + +#include "common.h" +#include "compile_time_macros.h" +#include "intc.h" + +#define UNIMPLEMENTED_GPIO_BANK 0 + +#define SCP_REG_BASE 0x70000000 + +/* clock control */ +#define SCP_CLK_CTRL_BASE (SCP_REG_BASE + 0x21000) +/* system clock counter value */ +#define SCP_CLK_SYS_VAL REG32(SCP_CLK_CTRL_BASE + 0x0014) +#define CLK_SYS_VAL_MASK (0x3ff << 0) +#define CLK_SYS_VAL_VAL(v) ((v)&CLK_SYS_VAL_MASK) +/* ULPOSC clock counter value */ +#define SCP_CLK_HIGH_VAL REG32(SCP_CLK_CTRL_BASE + 0x0018) +#define CLK_HIGH_VAL_MASK (0x1f << 0) +#define CLK_HIGH_VAL_VAL(v) ((v)&CLK_HIGH_VAL_MASK) +/* sleep mode control */ +#define SCP_SLEEP_CTRL REG32(SCP_CLK_CTRL_BASE + 0x0020) +#define SLP_CTRL_EN BIT(0) +#define VREQ_COUNT_MASK (0x7F << 1) +#define VREQ_COUNT_VAL(v) (((v) << 1) & VREQ_COUNT_MASK) +#define SPM_SLP_MODE BIT(8) +/* clock divider select */ +#define SCP_CLK_DIV_SEL REG32(SCP_CLK_CTRL_BASE + 0x0024) +#define CLK_DIV_SEL1 0 +#define CLK_DIV_SEL2 1 +#define CLK_DIV_SEL4 2 +#define CLK_DIV_SEL3 3 +/* clock gate */ +#define SCP_SET_CLK_CG REG32(SCP_CLK_CTRL_BASE + 0x0030) +#define CG_TIMER_MCLK BIT(0) +#define CG_TIMER_BCLK BIT(1) +#define CG_MAD_MCLK BIT(2) +#define CG_I2C_MCLK BIT(3) +#define CG_I2C_BCLK BIT(4) +#define CG_GPIO_MCLK BIT(5) +#define CG_AP2P_MCLK BIT(6) +#define CG_UART0_MCLK BIT(7) +#define CG_UART0_BCLK BIT(8) +#define CG_UART0_RST BIT(9) +#define CG_UART1_MCLK BIT(10) +#define CG_UART1_BCLK BIT(11) +#define CG_UART1_RST BIT(12) +#define CG_SPI0 BIT(13) +#define CG_SPI1 BIT(14) +#define CG_SPI2 BIT(15) +#define CG_DMA_CH0 BIT(16) +#define CG_DMA_CH1 BIT(17) +#define CG_DMA_CH2 BIT(18) +#define CG_DMA_CH3 BIT(19) +#define CG_I3C0 BIT(21) +#define CG_I3C1 BIT(22) +#define CG_DMA2_CH0 BIT(23) +#define CG_DMA2_CH1 BIT(24) +#define CG_DMA2_CH2 BIT(25) +#define CG_DMA2_CH3 BIT(26) +/* UART clock select */ +#define SCP_UART_CK_SEL REG32(SCP_CLK_CTRL_BASE + 0x0044) +#define UART0_CK_SEL_SHIFT 0 +#define UART0_CK_SEL_MASK (0x3 << UART0_CK_SEL_SHIFT) +#define UART0_CK_SEL_VAL(v) ((v)&UART0_CK_SEL_MASK) +#define UART0_CK_SW_STATUS_MASK (0xf << 8) +#define UART0_CK_SW_STATUS_VAL(v) ((v)&UART0_CK_SW_STATUS_MASK) +#define UART1_CK_SEL_SHIFT 16 +#define UART1_CK_SEL_MASK (0x3 << UART1_CK_SEL_SHIFT) +#define UART1_CK_SEL_VAL(v) ((v)&UART1_CK_SEL_MASK) +#define UART1_CK_SW_STATUS_MASK (0xf << 24) +#define UART1_CK_SW_STATUS_VAL(v) ((v)&UART1_CK_SW_STATUS_MASK) +#define UART_CK_SEL_26M 0 +#define UART_CK_SEL_32K 1 +#define UART_CK_SEL_ULPOSC 2 +#define UART_CK_SW_STATUS_26M BIT(0) +#define UART_CK_SW_STATUS_32K BIT(1) +#define UART_CK_SW_STATUS_ULPOS BIT(2) +/* BCLK clock select */ +#define SCP_BCLK_CK_SEL REG32(SCP_CLK_CTRL_BASE + 0x0048) +#define BCLK_CK_SEL_SYS_DIV8 0 +#define BCLK_CK_SEL_32K 1 +#define BCLK_CK_SEL_ULPOSC_DIV8 2 +/* VREQ control */ +#define SCP_CPU_VREQ_CTRL REG32(SCP_CLK_CTRL_BASE + 0x0054) +#define VREQ_SEL BIT(0) +#define VREQ_VALUE BIT(4) +#define VREQ_EXT_SEL BIT(8) +#define VREQ_DVFS_SEL BIT(16) +#define VREQ_DVFS_VALUE BIT(20) +#define VREQ_DVFS_EXT_SEL BIT(24) +#define VREQ_SRCLKEN_SEL BIT(27) +#define VREQ_SRCLKEN_VALUE BIT(28) +/* clock on control */ +#define SCP_CLK_HIGH_CORE_CG REG32(SCP_CLK_CTRL_BASE + 0x005C) +#define HIGH_CORE_CG BIT(1) +#define SCP_CLK_ON_CTRL REG32(SCP_CLK_CTRL_BASE + 0x006C) +#define HIGH_AO BIT(0) +#define HIGH_DIS_SUB BIT(1) +#define HIGH_CG_AO BIT(2) +#define HIGH_CORE_AO BIT(4) +#define HIGH_CORE_DIS_SUB BIT(5) +#define HIGH_CORE_CG_AO BIT(6) + +/* system control */ +#define SCP_SYS_CTRL REG32(SCP_REG_BASE + 0x24000) +#define AUTO_DDREN BIT(9) + +/* IPC */ +#define SCP_SCP2APMCU_IPC_SET REG32(SCP_REG_BASE + 0x24080) +#define SCP_SCP2SPM_IPC_SET REG32(SCP_REG_BASE + 0x24090) +#define IPC_SCP2HOST BIT(0) +#define SCP_GIPC_IN_SET REG32(SCP_REG_BASE + 0x24098) +#define SCP_GIPC_IN_CLR REG32(SCP_REG_BASE + 0x2409C) +#define GIPC_IN(n) BIT(n) + +/* UART */ +#define SCP_UART_COUNT 2 +#define UART_TX_IRQ(n) CONCAT3(SCP_IRQ_UART, n, _TX) +#define UART_RX_IRQ(n) CONCAT3(SCP_IRQ_UART, n, _RX) +#define SCP_UART0_BASE (SCP_REG_BASE + 0x26000) +#define SCP_UART1_BASE (SCP_REG_BASE + 0x27000) +#define SCP_UART_BASE(n) CONCAT3(SCP_UART, n, _BASE) +#define UART_REG(n, offset) REG32_ADDR(SCP_UART_BASE(n))[offset] + +/* WDT */ +#define SCP_CORE0_WDT_IRQ REG32(SCP_REG_BASE + 0x30030) +#define SCP_CORE0_WDT_CFG REG32(SCP_REG_BASE + 0x30034) +#define WDT_FREQ 33825 /* 0xFFFFF / 31 */ +#define WDT_MAX_PERIOD 0xFFFFF /* 31 seconds */ +#define WDT_PERIOD(ms) (WDT_FREQ * (ms) / 1000) +#define WDT_EN BIT(31) +#define SCP_CORE0_WDT_KICK REG32(SCP_REG_BASE + 0x30038) +#define SCP_CORE0_WDT_CUR_VAL REG32(SCP_REG_BASE + 0x3003C) +#define SCP_CORE0_MON_PC_LATCH REG32(SCP_REG_BASE + 0x300D0) +#define SCP_CORE0_MON_LR_LATCH REG32(SCP_REG_BASE + 0x300D4) +#define SCP_CORE0_MON_SP_LATCH REG32(SCP_REG_BASE + 0x300D8) + +/* INTC */ +#define SCP_INTC_WORD(irq) ((irq) >> 5) /* word length = 2^5 */ +#define SCP_INTC_BIT(irq) ((irq)&0x1F) /* bit shift =LSB[0:4] */ +#define SCP_INTC_GRP_COUNT 15 +#define SCP_INTC_GRP_GAP 4 + +#define SCP_CORE0_INTC_IRQ_BASE (SCP_REG_BASE + 0x32000) +#define SCP_CORE0_INTC_IRQ_STA(w) \ + REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0010)[(w)] +#define SCP_CORE0_INTC_IRQ_EN(w) \ + REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0020)[(w)] +#define SCP_CORE0_INTC_IRQ_POL(w) \ + REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0040)[(w)] +#define SCP_CORE0_INTC_IRQ_GRP(g, w) \ + REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0050 + \ + ((g) << SCP_INTC_GRP_GAP)) \ + [(w)] +#define SCP_CORE0_INTC_IRQ_GRP_STA(g, w) \ + REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0150 + \ + ((g) << SCP_INTC_GRP_GAP)) \ + [(w)] +#define SCP_CORE0_INTC_SLP_WAKE_EN(w) \ + REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0240)[(w)] +#define SCP_CORE0_INTC_IRQ_OUT REG32(SCP_CORE0_INTC_IRQ_BASE + 0x0250) +/* UART */ +#define SCP_CORE0_INTC_UART0_RX_IRQ REG32(SCP_CORE0_INTC_IRQ_BASE + 0x0258) +#define SCP_CORE0_INTC_UART1_RX_IRQ REG32(SCP_CORE0_INTC_IRQ_BASE + 0x025C) +#define SCP_CORE0_INTC_UART_RX_IRQ(n) CONCAT3(SCP_CORE0_INTC_UART, n, _RX_IRQ) + +/* XGPT (general purpose timer) */ +#define NUM_TIMERS 6 +#define SCP_CORE0_TIMER_BASE(n) (SCP_REG_BASE + 0x33000 + (0x10 * (n))) +#define SCP_CORE0_TIMER_EN(n) REG32(SCP_CORE0_TIMER_BASE(n) + 0x0000) +#define TIMER_EN BIT(0) +#define TIMER_CLK_SRC_32K (0 << 4) +#define TIMER_CLK_SRC_26M (1 << 4) +#define TIMER_CLK_SRC_BCLK (2 << 4) +#define TIMER_CLK_SRC_MCLK (3 << 4) +#define TIMER_CLK_SRC_MASK (3 << 4) +#define SCP_CORE0_TIMER_RST_VAL(n) REG32(SCP_CORE0_TIMER_BASE(n) + 0x0004) +#define SCP_CORE0_TIMER_CUR_VAL(n) REG32(SCP_CORE0_TIMER_BASE(n) + 0x0008) +#define SCP_CORE0_TIMER_IRQ_CTRL(n) REG32(SCP_CORE0_TIMER_BASE(n) + 0x000C) +#define TIMER_IRQ_EN BIT(0) +#define TIMER_IRQ_STATUS BIT(4) +#define TIMER_IRQ_CLR BIT(5) +#define SCP_IRQ_TIMER(n) CONCAT2(SCP_IRQ_TIMER, n) + +/* secure control */ +#define SCP_SEC_CTRL REG32(SCP_REG_BASE + 0xA5000) +#define VREQ_SECURE_DIS BIT(4) +/* memory remap */ +#define SCP_R_REMAP_0X0123 REG32(SCP_REG_BASE + 0xA5060) +#define SCP_R_REMAP_0X4567 REG32(SCP_REG_BASE + 0xA5064) +#define SCP_R_REMAP_0X89AB REG32(SCP_REG_BASE + 0xA5068) +#define SCP_R_REMAP_0XCDEF REG32(SCP_REG_BASE + 0xA506C) + +/* external address: AP */ +#define AP_REG_BASE 0x60000000 /* 0x10000000 remap to 0x6 */ +/* AP GPIO */ +#define AP_GPIO_BASE (AP_REG_BASE + 0x5000) +#define AP_GPIO_MODE11_SET REG32(AP_GPIO_BASE + 0x03B4) +#define AP_GPIO_MODE11_CLR REG32(AP_GPIO_BASE + 0x03B8) +#define AP_GPIO_MODE12_SET REG32(AP_GPIO_BASE + 0x03C4) +#define AP_GPIO_MODE12_CLR REG32(AP_GPIO_BASE + 0x03C8) +#define AP_GPIO_MODE20_SET REG32(AP_GPIO_BASE + 0x0444) +#define AP_GPIO_MODE20_CLR REG32(AP_GPIO_BASE + 0x0448) + +#include "clock_regs.h" + +#endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/mt_scp/rv32i_common/scp_timer.h b/chip/mt_scp/rv32i_common/scp_timer.h new file mode 100644 index 0000000000..1eed1d7792 --- /dev/null +++ b/chip/mt_scp/rv32i_common/scp_timer.h @@ -0,0 +1,16 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __SCP_TIMER_H +#define __SCP_TIMER_H + +/* detect existance of 26m clock in S3 stage */ +#define TIMER_SR 4 + +void timer_enable(int n); +void timer_disable(int n); +uint32_t timer_read_raw_sr(void); + +#endif /* __SCP_TIMER_H */ diff --git a/chip/mt_scp/rv32i_common/scp_watchdog.h b/chip/mt_scp/rv32i_common/scp_watchdog.h new file mode 100644 index 0000000000..2a8225c047 --- /dev/null +++ b/chip/mt_scp/rv32i_common/scp_watchdog.h @@ -0,0 +1,15 @@ + +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __SCP_WATCHDOG_H +#define __SCP_WATCHDOG_H + +#include "watchdog.h" + +void watchdog_disable(void); +void watchdog_enable(void); + +#endif /* __SCP_WATCHDOG_H */ diff --git a/chip/mt_scp/rv32i_common/system.c b/chip/mt_scp/rv32i_common/system.c new file mode 100644 index 0000000000..0eed2ae3ff --- /dev/null +++ b/chip/mt_scp/rv32i_common/system.c @@ -0,0 +1,50 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* System : hardware specific implementation */ + +#include "csr.h" +#include "memmap.h" +#include "registers.h" +#include "system.h" + +void system_pre_init(void) +{ + memmap_init(); + + /* enable CPU and platform low power CG */ + /* enable CPU DCM */ + set_csr(CSR_MCTREN, CSR_MCTREN_CG); + + /* Disable jump (it has only RW) */ + system_disable_jump(); +} + +void system_reset(int flags) +{ + while (1) + ; +} + +int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) +{ + return EC_ERROR_INVAL; +} + +const char *system_get_chip_vendor(void) +{ + return "mtk"; +} + +const char *system_get_chip_name(void) +{ + /* Support only SCP_A for now */ + return "scp_a"; +} + +const char *system_get_chip_revision(void) +{ + return ""; +} diff --git a/chip/mt_scp/rv32i_common/uart.c b/chip/mt_scp/rv32i_common/uart.c new file mode 100644 index 0000000000..a67a0bb276 --- /dev/null +++ b/chip/mt_scp/rv32i_common/uart.c @@ -0,0 +1,160 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SCP UART module */ + +#include "csr.h" +#include "system.h" +#include "uart.h" +#include "uart_regs.h" +#include "util.h" + +/* + * UARTN == 0, SCP UART0 + * UARTN == 1, SCP UART1 + * UARTN == 2, AP UART1 + */ +#define UARTN CONFIG_UART_CONSOLE +#define UART_IDLE_WAIT_US 500 +#define UART_INTC_GROUP 12 + +static uint8_t init_done, tx_started; + +void uart_init(void) +{ + const uint32_t baud_rate = CONFIG_UART_BAUD_RATE; + const uint32_t uart_clock = 26000000; + const uint32_t div = DIV_ROUND_NEAREST(uart_clock, baud_rate * 16); + + uart_init_pinmux(); + + /* Clear FIFO */ + UART_FCR(UARTN) = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT; + /* Line control: parity none, 8 bit, 1 stop bit */ + UART_LCR(UARTN) = UART_LCR_WLEN8; + /* For baud rate <= 115200 */ + UART_HIGHSPEED(UARTN) = 0; + + /* DLAB start */ + UART_LCR(UARTN) |= UART_LCR_DLAB; + UART_DLL(UARTN) = div & 0xff; + UART_DLH(UARTN) = (div >> 8) & 0xff; + UART_LCR(UARTN) &= ~UART_LCR_DLAB; + /* DLAB end */ + + /* Enable received data interrupt */ + UART_IER(UARTN) |= UART_IER_RDI; + +#if (UARTN < SCP_UART_COUNT) + task_enable_irq(UART_TX_IRQ(UARTN)); + task_enable_irq(UART_RX_IRQ(UARTN)); +#endif + + init_done = 1; +} + +int uart_init_done(void) +{ + return init_done; +} + +void uart_tx_flush(void) +{ + while (!(UART_LSR(UARTN) & UART_LSR_TEMT)) + ; +} + +int uart_tx_ready(void) +{ + return UART_LSR(UARTN) & UART_LSR_THRE; +} + +int uart_rx_available(void) +{ + return UART_LSR(UARTN) & UART_LSR_DR; +} + +void uart_write_char(char c) +{ + while (!uart_tx_ready()) + ; + + UART_THR(UARTN) = c; +} + +int uart_read_char(void) +{ + return UART_RBR(UARTN); +} + +void uart_tx_start(void) +{ + tx_started = 1; + if (UART_IER(UARTN) & UART_IER_THRI) + return; + disable_sleep(SLEEP_MASK_UART); + UART_IER(UARTN) |= UART_IER_THRI; +} + +void uart_tx_stop(void) +{ + /* + * Workaround for b/157541273. + * Don't unset the THRI flag unless we are in the UART ISR. + * + * Note: + * MICAUSE denotes current INTC group number. + */ + if (in_interrupt_context() && + read_csr(CSR_VIC_MICAUSE) != UART_INTC_GROUP) + return; + + tx_started = 0; + UART_IER(UARTN) &= ~UART_IER_THRI; + enable_sleep(SLEEP_MASK_UART); +} + +static void uart_process(void) +{ + uart_process_input(); + uart_process_output(); +} + +#if (UARTN < SCP_UART_COUNT) +static void uart_irq_handler(void) +{ + extern volatile int ec_int; + + switch (ec_int) { + case UART_TX_IRQ(UARTN): + uart_process(); + task_clear_pending_irq(ec_int); + break; + case UART_RX_IRQ(UARTN): + uart_process(); + SCP_CORE0_INTC_UART_RX_IRQ(UARTN) = BIT(0); + asm volatile("fence.i" ::: "memory"); + task_clear_pending_irq(ec_int); + break; + } +} +DECLARE_IRQ(UART_INTC_GROUP, uart_irq_handler, 0); +#else + +#ifndef HAS_TASK_APUART +#error "APUART task hasn't defined in ec.tasklist." +#endif + +void uart_task(void) +{ + while (1) { + if (uart_rx_available() || tx_started) + uart_process(); + else + task_wait_event(UART_IDLE_WAIT_US); + } +} +#endif diff --git a/chip/mt_scp/rv32i_common/uart_regs.h b/chip/mt_scp/rv32i_common/uart_regs.h new file mode 100644 index 0000000000..d0eeaa81c2 --- /dev/null +++ b/chip/mt_scp/rv32i_common/uart_regs.h @@ -0,0 +1,80 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SCP UART module registers */ + +#ifndef __CROS_EC_UART_REGS_H +#define __CROS_EC_UART_REGS_H + +#include "registers.h" + +/* Chip specific function for setting UART pinmux. */ +void uart_init_pinmux(void); + +/* DLAB (Divisor Latch Access Bit) == 0 */ + +/* (Read) receiver buffer register */ +#define UART_RBR(n) UART_REG(n, 0) +/* (Write) transmitter holding register */ +#define UART_THR(n) UART_REG(n, 0) +/* (Write) interrupt enable register */ +#define UART_IER(n) UART_REG(n, 1) +#define UART_IER_RDI BIT(0) /* received data */ +#define UART_IER_THRI BIT(1) /* THR empty */ +#define UART_IER_RLSI BIT(2) /* receiver LSR change */ +#define UART_IER_MSI BIT(3) /* MSR change */ +/* (Read) interrupt identification register */ +#define UART_IIR(n) UART_REG(n, 2) +#define UART_IIR_ID_MASK 0x0e +#define UART_IIR_MSI 0x00 /* modem status change */ +#define UART_IIR_NO_INT 0x01 /* no int pending */ +#define UART_IIR_THRI 0x02 /* THR empty */ +#define UART_IIR_RDI 0x04 /* received data available */ +#define UART_IIR_RLSI 0x06 /* line status change */ +/* (Write) FIFO control register */ +#define UART_FCR(n) UART_REG(n, 2) +#define UART_FCR_ENABLE_FIFO BIT(0) /* enable FIFO */ +#define UART_FCR_CLEAR_RCVR BIT(1) /* clear receive FIFO */ +#define UART_FCR_CLEAR_XMIT BIT(2) /* clear transmit FIFO */ +#define UART_FCR_DMA_SELECT BIT(3) /* select DMA mode */ +/* (Write) line control register */ +#define UART_LCR(n) UART_REG(n, 3) +#define UART_LCR_WLEN5 0 /* word length 5 bits */ +#define UART_LCR_WLEN6 1 +#define UART_LCR_WLEN7 2 +#define UART_LCR_WLEN8 3 +#define UART_LCR_STOP BIT(2) /* stop bits: 1bit, 2bits */ +#define UART_LCR_PARITY BIT(3) /* parity enable */ +#define UART_LCR_EPAR BIT(4) /* even parity */ +#define UART_LCR_SPAR BIT(5) /* stick parity */ +#define UART_LCR_SBC BIT(6) /* set break control */ +#define UART_LCR_DLAB BIT(7) /* divisor latch access */ +/* (Write) modem control register */ +#define UART_MCR(n) UART_REG(n, 4) +/* (Read) line status register */ +#define UART_LSR(n) UART_REG(n, 5) +#define UART_LSR_DR BIT(0) /* data ready */ +#define UART_LSR_OE BIT(1) /* overrun error */ +#define UART_LSR_PE BIT(2) /* parity error */ +#define UART_LSR_FE BIT(3) /* frame error */ +#define UART_LSR_BI BIT(4) /* break interrupt */ +#define UART_LSR_THRE BIT(5) /* THR empty */ +#define UART_LSR_TEMT BIT(6) /* THR empty, line idle */ +#define UART_LSR_FIFOE BIT(7) /* FIFO error */ +/* (Read) modem status register */ +#define UART_MSR(n) UART_REG(n, 6) +/* (Read/Write) scratch register */ +#define UART_SCR(n) UART_REG(n, 7) + +/* DLAB == 1 */ + +/* (Write) divisor latch */ +#define UART_DLL(n) UART_REG(n, 0) +#define UART_DLH(n) UART_REG(n, 1) + +/* MTK extension */ +#define UART_HIGHSPEED(n) UART_REG(n, 9) + +#endif /* __CROS_EC_UART_REGS_H */ diff --git a/chip/mt_scp/rv32i_common/video.h b/chip/mt_scp/rv32i_common/video.h new file mode 100644 index 0000000000..d2a4384e80 --- /dev/null +++ b/chip/mt_scp/rv32i_common/video.h @@ -0,0 +1,34 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_VIDEO_H +#define __CROS_EC_VIDEO_H + +#include "common.h" + +/* + * Video decoder supported capability + */ +#define VDEC_CAP_4K_DISABLED BIT(4) +#define VDEC_CAP_MM21 BIT(5) +#define VDEC_CAP_MT21C BIT(6) +#define VDEC_CAP_H264_SLICE BIT(8) +#define VDEC_CAP_VP8_FRAME BIT(9) +#define VDEC_CAP_VP9_FRAME BIT(10) +#define VDEC_CAP_AV1_FRAME BIT(11) +#define VDEC_CAP_HEVC_SLICE BIT(12) +#define VDEC_CAP_IRQ_IN_SCP BIT(16) +#define VDEC_CAP_INNER_RACING BIT(17) + +/* + * Video encoder supported capability: + * BIT(0): enable 4K + */ +#define VENC_CAP_4K BIT(0) + +uint32_t video_get_enc_capability(void); +uint32_t video_get_dec_capability(void); + +#endif /* #ifndef __CROS_EC_VIDEO_H */ diff --git a/chip/mt_scp/rv32i_common/watchdog.c b/chip/mt_scp/rv32i_common/watchdog.c new file mode 100644 index 0000000000..e8f5b5c3f9 --- /dev/null +++ b/chip/mt_scp/rv32i_common/watchdog.c @@ -0,0 +1,47 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Watchdog driver */ + +#include "common.h" +#include "hooks.h" +#include "registers.h" +#include "scp_watchdog.h" +#include "watchdog.h" + +void watchdog_reload(void) +{ + SCP_CORE0_WDT_KICK = BIT(0); +} +DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); + +void watchdog_disable(void) +{ + /* disable watchdog */ + SCP_CORE0_WDT_CFG &= ~WDT_EN; + /* clear watchdog irq */ + SCP_CORE0_WDT_IRQ |= BIT(0); +} + +void watchdog_enable(void) +{ + const uint32_t timeout = WDT_PERIOD(CONFIG_WATCHDOG_PERIOD_MS); + + /* disable watchdog */ + SCP_CORE0_WDT_CFG &= ~WDT_EN; + /* clear watchdog irq */ + SCP_CORE0_WDT_IRQ |= BIT(0); + /* enable watchdog */ + SCP_CORE0_WDT_CFG = WDT_EN | timeout; + /* reload watchdog */ + watchdog_reload(); +} + +int watchdog_init(void) +{ + watchdog_enable(); + + return EC_SUCCESS; +} diff --git a/chip/mt_scp/serial_reg.h b/chip/mt_scp/serial_reg.h deleted file mode 100644 index 5344566272..0000000000 --- a/chip/mt_scp/serial_reg.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * UART register map - */ - -#ifndef __CROS_EC_SERIAL_REG_H -#define __CROS_EC_SERIAL_REG_H - -#include "registers.h" - -/* Number of hardware ports */ -#define HW_UART_PORTS 2 - -/* DLAB (Divisor Latch Access Bit) == 0 */ - -/* Data register - * (Read) Rcvr buffer register - * (Write) Xmit holding register - */ -#define UART_DATA(n) UART_REG(n, 0) -/* (Write) Interrupt enable register */ -#define UART_IER(n) UART_REG(n, 1) -#define UART_IER_RDI BIT(0) /* Recv data int */ -#define UART_IER_THRI BIT(1) /* Xmit holding register int */ -#define UART_IER_RLSI BIT(2) /* Rcvr line status int */ -#define UART_IER_MSI BIT(3) /* Modem status int */ -/* (Read) Interrupt ID register */ -#define UART_IIR(n) UART_REG(n, 2) -#define UART_IIR_NO_INT BIT(0) /* No int pending */ -#define UART_IIR_ID_MASK 0x0e /* Interrupt ID mask */ -#define UART_IIR_MSI 0x00 -#define UART_IIR_THRI 0x02 -#define UART_IIR_RDI 0x04 -#define UART_IIR_RLSI 0x06 -#define UART_IIR_BUSY 0x07 /* DW APB busy */ -/* (Write) FIFO control register */ -#define UART_FCR(n) UART_REG(n, 2) -#define UART_FCR_ENABLE_FIFO BIT(0) /* Enable FIFO */ -#define UART_FCR_CLEAR_RCVR BIT(1) /* Clear rcvr FIFO */ -#define UART_FCR_CLEAR_XMIT BIT(2) /* Clear xmit FIFO */ -#define UART_FCR_DMA_SELECT BIT(3) -/* FIFO trigger levels */ -#define UART_FCR_T_TRIG_00 0x00 -#define UART_FCR_T_TRIG_01 0x10 -#define UART_FCR_T_TRIG_10 0x20 -#define UART_FCR_T_TRIG_11 0x30 -#define UART_FCR_R_TRIG_00 0x00 -#define UART_FCR_R_TRIG_01 0x40 -#define UART_FCR_R_TRIG_10 0x80 -#define UART_FCR_R_TRIG_11 0x80 -/* (Write) Line control register */ -#define UART_LCR(n) UART_REG(n, 3) -#define UART_LCR_WLEN5 0 /* Word length 5 bits */ -#define UART_LCR_WLEN6 1 -#define UART_LCR_WLEN7 2 -#define UART_LCR_WLEN8 3 -#define UART_LCR_STOP BIT(2) /* Stop bits: 1bit, 2bits */ -#define UART_LCR_PARITY BIT(3) /* Parity enable */ -#define UART_LCR_EPAR BIT(4) /* Even parity */ -#define UART_LCR_SPAR BIT(5) /* Stick parity */ -#define UART_LCR_SBC BIT(6) /* Set break control */ -#define UART_LCR_DLAB BIT(7) /* Divisor latch access */ -/* (Write) Modem control register */ -#define UART_MCR(n) UART_REG(n, 4) -/* (Read) Line status register */ -#define UART_LSR(n) UART_REG(n, 5) -#define UART_LSR_DR BIT(0) /* Data ready */ -#define UART_LSR_OE BIT(1) /* Overrun error */ -#define UART_LSR_PE BIT(2) /* Parity error */ -#define UART_LSR_FE BIT(3) /* Frame error */ -#define UART_LSR_BI BIT(4) /* Break interrupt */ -#define UART_LSR_THRE BIT(5) /* Xmit-hold-register empty */ -#define UART_LSR_TEMT BIT(6) /* Xmit empty */ -#define UART_LSR_FIFOE BIT(7) /* FIFO error */ - -/* DLAB == 1 */ - -/* (Write) Divisor latch */ -#define UART_DLL(n) UART_REG(n, 0) /* Low */ -#define UART_DLH(n) UART_REG(n, 1) /* High */ - -/* MTK extension */ -#define UART_HIGHSPEED(n) UART_REG(n, 9) -#define UART_SAMPLE_COUNT(n) UART_REG(n, 10) -#define UART_SAMPLE_POINT(n) UART_REG(n, 11) -#define UART_RATE_FIX(n) UART_REG(n, 13) - -#endif /* __CROS_EC_SERIAL_REG_H */ diff --git a/chip/mt_scp/system.c b/chip/mt_scp/system.c deleted file mode 100644 index 6bd2e76644..0000000000 --- a/chip/mt_scp/system.c +++ /dev/null @@ -1,175 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* System : hardware specific implementation */ - -#include "clock_chip.h" -#include "console.h" -#include "cpu.h" -#include "flash.h" -#include "hooks.h" -#include "host_command.h" -#include "memmap.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "util.h" -#include "version.h" -#include "watchdog.h" - -/* - * SCP_GPR[0] b15-b0 - scratchpad - * SCP_GPR[0] b31-b16 - saved_flags - */ - -int system_set_scratchpad(uint32_t value) -{ - /* Check if value fits in 16 bits */ - if (value & 0xffff0000) - return EC_ERROR_INVAL; - - SCP_GPR[0] = (SCP_GPR[0] & 0xffff0000) | value; - - return EC_SUCCESS; -} - -uint32_t system_get_scratchpad(void) -{ - return SCP_GPR[0] & 0xffff; -} - -const char *system_get_chip_vendor(void) -{ - return "mtk"; -} - -const char *system_get_chip_name(void) -{ - /* Support only SCP_A for now */ - return "scp_a"; -} - -const char *system_get_chip_revision(void) -{ - return ""; -} - -void chip_pre_init(void) -{ -} - -static void scp_cm4_mod(void) -{ - CM4_MODIFICATION = 3; - CM4_DCM_FEATURE = 3; -} - -static void scp_enable_pirq(void) -{ - /* Enable all peripheral to SCP IRQ, except IPC0. */ - SCP_INTC_IRQ_ENABLE = 0xFFFFFFFE; - SCP_INTC_IRQ_ENABLE_MSB = 0xFFFFFFFF; -} - -void system_pre_init(void) -{ - /* CM4 Modification */ - scp_cm4_mod(); - /* Clock */ - scp_enable_clock(); - /* Peripheral IRQ */ - scp_enable_pirq(); - /* Init dram mapping (and cache) */ - scp_memmap_init(); - /* Disable jump (mt_scp has only RW) and enable MPU. */ - system_disable_jump(); -} - -void system_reset(int flags) -{ - uint32_t save_flags = 0; - - /* Disable interrupts to avoid task swaps during reboot */ - interrupt_disable(); - - /* Save current reset reasons if necessary */ - if (flags & SYSTEM_RESET_PRESERVE_FLAGS) - save_flags = system_get_reset_flags() | EC_RESET_FLAG_PRESERVED; - - if (flags & SYSTEM_RESET_LEAVE_AP_OFF) - save_flags |= EC_RESET_FLAG_AP_OFF; - - /* Remember that the software asked us to hard reboot */ - if (flags & SYSTEM_RESET_HARD) - save_flags |= EC_RESET_FLAG_HARD; - - /* Reset flags are 32-bits, but save only 16 bits. */ - ASSERT(!(save_flags >> 16)); - SCP_GPR[0] = (save_flags << 16) | (SCP_GPR[0] & 0xffff); - - /* SCP can not hard reset itself */ - ASSERT(!(flags & SYSTEM_RESET_HARD)); - - if (flags & SYSTEM_RESET_WAIT_EXT) { - int i; - - /* Wait 10 seconds for external reset */ - for (i = 0; i < 1000; i++) { - watchdog_reload(); - udelay(10000); - } - } - - /* Set watchdog timer to small value, and spin wait for watchdog reset */ - SCP_WDT_CFG = 0; - SCP_WDT_CFG = SCP_WDT_ENABLE | SCP_WDT_PERIOD(1); - watchdog_reload(); - while (1) - ; -} - -static void check_reset_cause(void) -{ - uint32_t flags = 0; - uint32_t raw_reset_cause = SCP_GPR[1]; - - /* Set state to power-on */ - SCP_PWRON_STATE = PWRON_DEFAULT; - - if ((raw_reset_cause & 0xffff0000) == PWRON_DEFAULT) { - /* Reboot */ - if (raw_reset_cause & PWRON_WATCHDOG) - flags |= EC_RESET_FLAG_WATCHDOG; - else if (raw_reset_cause & PWRON_RESET) - flags |= EC_RESET_FLAG_POWER_ON; - else - flags |= EC_RESET_FLAG_OTHER; - } else { - /* Power lost restart */ - flags |= EC_RESET_FLAG_POWER_ON; - } - system_set_reset_flags(SCP_GPR[0] >> 16); - SCP_GPR[0] &= 0xffff; -} - -int system_is_reboot_warm(void) -{ - const uint32_t cold_flags = - EC_RESET_FLAG_RESET_PIN | - EC_RESET_FLAG_POWER_ON | - EC_RESET_FLAG_WATCHDOG | - EC_RESET_FLAG_HARD | - EC_RESET_FLAG_SOFT | - EC_RESET_FLAG_HIBERNATE; - - check_reset_cause(); - - return !(system_get_reset_flags() & cold_flags); -} - -int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) -{ - return EC_ERROR_INVAL; -} diff --git a/chip/mt_scp/uart.c b/chip/mt_scp/uart.c deleted file mode 100644 index 78ea594c6b..0000000000 --- a/chip/mt_scp/uart.c +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* SCP UART module */ - -#include "clock_chip.h" -#include "console.h" -#include "registers.h" -#include "serial_reg.h" -#include "system.h" -#include "task.h" -#include "uart.h" -#include "util.h" - -/* Console UART index */ -#define UARTN CONFIG_UART_CONSOLE -#define UART_IDLE_WAIT_US 500 - -static uint8_t uart_done, tx_started; - -int uart_init_done(void) -{ - /* - * TODO: AP UART support - * When access AP UART port, wait for AP peripheral clock - */ - return uart_done; -} - -void uart_tx_start(void) -{ - tx_started = 1; - - /* AP UART mode doesn't support interrupt */ - if (UARTN >= SCP_UART_COUNT) - return; - - if (UART_IER(UARTN) & UART_IER_THRI) - return; - disable_sleep(SLEEP_MASK_UART); - UART_IER(UARTN) |= UART_IER_THRI; -} - -void uart_tx_stop(void) -{ - tx_started = 0; - - /* AP UART mode doesn't support interrupt */ - if (UARTN >= SCP_UART_COUNT) - return; - - UART_IER(UARTN) &= ~UART_IER_THRI; - enable_sleep(SLEEP_MASK_UART); -} - -void uart_tx_flush(void) -{ - while (!(UART_LSR(UARTN) & UART_LSR_TEMT)) - ; -} - -int uart_tx_ready(void) -{ - /* Check xmit FIFO empty */ - return UART_LSR(UARTN) & UART_LSR_THRE; -} - -int uart_rx_available(void) -{ - /* Check rcvr data ready */ - return UART_LSR(UARTN) & UART_LSR_DR; -} - -void uart_write_char(char c) -{ - while (!uart_tx_ready()) - ; - - UART_DATA(UARTN) = c; -} - -int uart_read_char(void) -{ - return UART_DATA(UARTN); -} - -void uart_process(void) -{ - uart_process_input(); - uart_process_output(); -} - -#if (UARTN < SCP_UART_COUNT) -void uart_interrupt(void) -{ - uint8_t ier; - - task_clear_pending_irq(UART_IRQ(UARTN)); - uart_process(); - ier = UART_IER(UARTN); - UART_IER(UARTN) = 0; - UART_IER(UARTN) = ier; -} -DECLARE_IRQ(UART_IRQ(UARTN), uart_interrupt, 2); - -void uart_rx_interrupt(void) -{ - uint8_t ier; - - task_clear_pending_irq(UART_RX_IRQ(UARTN)); - SCP_INTC_UART_RX_IRQ &= ~BIT(UARTN); - uart_process(); - ier = UART_IER(UARTN); - UART_IER(UARTN) = 0; - UART_IER(UARTN) = ier; - SCP_INTC_UART_RX_IRQ |= 1 << UARTN; -} -DECLARE_IRQ(UART_RX_IRQ(UARTN), uart_rx_interrupt, 2); -#endif - -void uart_task(void) -{ -#if (UARTN >= SCP_UART_COUNT) - while (1) { - if (uart_rx_available() || tx_started) - uart_process(); - else - task_wait_event(UART_IDLE_WAIT_US); - } -#endif -} - -void uart_init(void) -{ - const uint32_t baud_rate = CONFIG_UART_BAUD_RATE; - /* - * UART clock source is set to ULPOSC1 / 10 below. - * - * TODO(b:134035444): We could get slightly more precise frequency by - * using the _measured_ ULPOSC1 frequency (instead of the target). - */ - const uint32_t uart_clock = ULPOSC1_CLOCK_MHZ * 1000 / 10 * 1000; - const uint32_t div = DIV_ROUND_NEAREST(uart_clock, baud_rate * 16); - - /* Init clock */ -#if UARTN == 0 - SCP_CLK_UART = CLK_UART_SEL_ULPOSC1_DIV10; - SCP_CLK_GATE |= CG_UART_M | CG_UART_B | CG_UART_RSTN; -#elif UARTN == 1 - SCP_CLK_UART = CLK_UART1_SEL_ULPOSC1_DIV10; - SCP_CLK_GATE |= CG_UART1_M | CG_UART1_B | CG_UART1_RSTN; -#endif - - /* Init and clear FIFO */ - UART_FCR(UARTN) = UART_FCR_ENABLE_FIFO - | UART_FCR_CLEAR_RCVR - | UART_FCR_CLEAR_XMIT; - /* Line control: parity none, 8 bit, 1 stop bit */ - UART_LCR(UARTN) = UART_LCR_WLEN8; - /* For baud rate <= 115200 */ - UART_HIGHSPEED(UARTN) = 0; - /* DLAB = 1 and update DLL DLH */ - UART_LCR(UARTN) |= UART_LCR_DLAB; - UART_DLL(UARTN) = div & 0xff; - UART_DLH(UARTN) = (div >> 8) & 0xff; - UART_LCR(UARTN) &= ~UART_LCR_DLAB; - UART_IER(UARTN) |= UART_IER_RDI; - -#if (UARTN < SCP_UART_COUNT) - task_enable_irq(UART_IRQ(UARTN)); - task_enable_irq(UART_RX_IRQ(UARTN)); - /* UART RX IRQ needs an extra enable */ - SCP_INTC_UART_RX_IRQ |= 1 << UARTN; -#endif - gpio_config_module(MODULE_UART, 1); - uart_done = 1; -} diff --git a/chip/mt_scp/watchdog.c b/chip/mt_scp/watchdog.c deleted file mode 100644 index 74e2cad8e5..0000000000 --- a/chip/mt_scp/watchdog.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Watchdog driver */ - -#include "common.h" -#include "hooks.h" -#include "panic.h" -#include "registers.h" -#include "watchdog.h" - -void watchdog_reload(void) -{ - SCP_WDT_RELOAD = SCP_WDT_RELOAD_VALUE; -} -DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); - -int watchdog_init(void) -{ - const uint32_t watchdog_timeout = - SCP_WDT_PERIOD(CONFIG_WATCHDOG_PERIOD_MS); - - /* Disable watchdog */ - SCP_WDT_CFG = 0; - /* Enable watchdog */ - SCP_WDT_CFG = SCP_WDT_ENABLE | watchdog_timeout; - /* Reload watchdog */ - watchdog_reload(); - - return EC_SUCCESS; -} diff --git a/chip/npcx/adc.c b/chip/npcx/adc.c index 365b401b87..73d4ec48b3 100644 --- a/chip/npcx/adc.c +++ b/chip/npcx/adc.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,12 +6,11 @@ /* NPCX-specific ADC module for Chrome EC */ #include "adc.h" -#include "adc_chip.h" #include "atomic.h" #include "clock.h" #include "clock_chip.h" -#include "console.h" #include "common.h" +#include "console.h" #include "gpio.h" #include "hooks.h" #include "registers.h" @@ -20,21 +19,38 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) /* Maximum time we allow for an ADC conversion */ -#define ADC_TIMEOUT_US SECOND -#define ADC_CLK 2000000 -#define ADC_REGULAR_DLY 0x11 -#define ADC_REGULAR_ADCCNF2 0x8B07 -#define ADC_REGULAR_GENDLY 0x0100 -#define ADC_REGULAR_MEAST 0x0001 +#define ADC_TIMEOUT_US SECOND +/* + * ADC basic clock is from APB1. + * In npcx5, APB1 clock frequency is (15 MHz / 4). + * Configure ADC clock divider and speed parameters to set the ADC clock to + * ~2 MHz. + * In npcx7 and later chips, APB1 clock frequency is 15 MHz. + * Configure ADC clock divider and speed parameters to set the ADC clock to + * 7.5 MHz. + */ +#if defined(CHIP_FAMILY_NPCX5) +#define ADC_CLK 2000000 +#define ADC_DLY 0x03 +#define ADC_ADCCNF2 0x8B07 +#define ADC_GENDLY 0x0100 +#define ADC_MEAST 0x0001 +#else +#define ADC_CLK 7500000 +#define ADC_DLY 0x02 +#define ADC_ADCCNF2 0x8901 +#define ADC_GENDLY 0x0100 +#define ADC_MEAST 0x0405 +#endif /* ADC conversion mode */ enum npcx_adc_conversion_mode { - ADC_CHN_CONVERSION_MODE = 0, - ADC_SCAN_CONVERSION_MODE = 1 + ADC_CHN_CONVERSION_MODE = 0, + ADC_SCAN_CONVERSION_MODE = 1 }; /* Global variables */ @@ -42,6 +58,8 @@ static volatile task_id_t task_waiting; struct mutex adc_lock; +static volatile bool adc_done; + /** * Preset ADC operation clock. * @@ -51,7 +69,7 @@ struct mutex adc_lock; */ void adc_freq_changed(void) { - uint8_t prescaler_divider = 0; + uint8_t prescaler_divider = 0; /* Set clock prescaler divider to ADC module*/ prescaler_divider = (uint8_t)(clock_get_apb1_freq() / ADC_CLK); @@ -73,19 +91,23 @@ DECLARE_HOOK(HOOK_FREQ_CHANGE, adc_freq_changed, HOOK_PRIO_DEFAULT); * @return TRUE/FALSE success/fail * @notes set SW-triggered interrupt conversion and one-shot mode in npcx chip */ -static int start_single_and_wait(enum npcx_adc_input_channel input_ch - , int timeout) +static int start_single_and_wait(enum npcx_adc_input_channel input_ch, + int timeout) { int event; - task_waiting = task_get_current(); + if (IS_ENABLED(CONFIG_KEYBOARD_SCAN_ADC)) { + if (task_start_called()) + task_waiting = task_get_current(); + } else + task_waiting = task_get_current(); /* Stop ADC conversion first */ SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_STOP); /* Set ADC conversion code to SW conversion mode */ SET_FIELD(NPCX_ADCCNF, NPCX_ADCCNF_ADCMD_FIELD, - ADC_CHN_CONVERSION_MODE); + ADC_CHN_CONVERSION_MODE); /* Set conversion type to one-shot type */ CLEAR_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCRPTC); @@ -102,13 +124,35 @@ static int start_single_and_wait(enum npcx_adc_input_channel input_ch /* Start conversion */ SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_START); - /* Wait for interrupt */ - event = task_wait_event_mask(TASK_EVENT_ADC_DONE, timeout); + /* + * If tasks have started, we can suspend to the task that called us. + * If not, we need to busy poll for adc to finish before proceeding + */ + if (IS_ENABLED(CONFIG_KEYBOARD_SCAN_ADC)) { + if (!task_start_called()) { + /* Wait for the ADC interrupt to set the flag */ + do { + usleep(10); + } while (adc_done == false); - task_waiting = TASK_ID_INVALID; + adc_done = false; - return (event == TASK_EVENT_ADC_DONE); + event = TASK_EVENT_ADC_DONE; + } else { + /* Wait for interrupt */ + event = task_wait_event_mask(TASK_EVENT_ADC_DONE, + timeout); + + task_waiting = TASK_ID_INVALID; + } + } else { + /* Wait for interrupt */ + event = task_wait_event_mask(TASK_EVENT_ADC_DONE, timeout); + task_waiting = TASK_ID_INVALID; + } + + return (event == TASK_EVENT_ADC_DONE); } static uint16_t repetitive_enabled; @@ -168,8 +212,9 @@ int adc_read_data(enum npcx_adc_input_channel input_ch) uint16_t chn_data; chn_data = NPCX_CHNDAT(adc->input_ch); - value = GET_FIELD(chn_data, NPCX_CHNDAT_CHDAT_FIELD) * - adc->factor_mul / adc->factor_div + adc->shift; + value = GET_FIELD(chn_data, NPCX_CHNDAT_CHDAT_FIELD) * adc->factor_mul / + adc->factor_div + + adc->shift; return value; } @@ -196,11 +241,11 @@ int adc_read_channel(enum adc_channel ch) if (start_single_and_wait(adc->input_ch, ADC_TIMEOUT_US)) { chn_data = NPCX_CHNDAT(adc->input_ch); if ((adc->input_ch == - GET_FIELD(NPCX_ASCADD, NPCX_ASCADD_SADDR_FIELD)) - && (IS_BIT_SET(chn_data, - NPCX_CHNDAT_NEW))) { + GET_FIELD(NPCX_ASCADD, NPCX_ASCADD_SADDR_FIELD)) && + (IS_BIT_SET(chn_data, NPCX_CHNDAT_NEW))) { value = GET_FIELD(chn_data, NPCX_CHNDAT_CHDAT_FIELD) * - adc->factor_mul / adc->factor_div + adc->shift; + adc->factor_mul / adc->factor_div + + adc->shift; } else { value = ADC_READ_ERROR; } @@ -216,7 +261,7 @@ int adc_read_channel(enum adc_channel ch) } else { /* Set ADC conversion code to SW conversion mode */ SET_FIELD(NPCX_ADCCNF, NPCX_ADCCNF_ADCMD_FIELD, - ADC_SCAN_CONVERSION_MODE); + ADC_SCAN_CONVERSION_MODE); /* Set conversion type to repetitive (runs continuously) */ SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCRPTC); /* Start conversion */ @@ -238,8 +283,7 @@ void npcx_adc_thresh_int_enable(int threshold_idx, int enable) enable = !!enable; if ((threshold_idx < 1) || (threshold_idx > NPCX_ADC_THRESH_CNT)) { - CPRINTS("Invalid ADC thresh index! (%d)", - threshold_idx); + CPRINTS("Invalid ADC thresh index! (%d)", threshold_idx); return; } threshold_idx--; /* convert to 0-based */ @@ -268,24 +312,21 @@ void npcx_adc_register_thresh_irq(int threshold_idx, int shift; if ((threshold_idx < 1) || (threshold_idx > NPCX_ADC_THRESH_CNT)) { - CPRINTS("Invalid ADC thresh index! (%d)", - threshold_idx); + CPRINTS("Invalid ADC thresh index! (%d)", threshold_idx); return; } npcx_adc_ch = adc_channels[thresh_cfg->adc_ch].input_ch; if (!thresh_cfg->adc_thresh_cb) { - CPRINTS("No callback for ADC Threshold %d!", - threshold_idx); + CPRINTS("No callback for ADC Threshold %d!", threshold_idx); return; } /* Fill in the table */ - adc_thresh_irqs[threshold_idx-1] = thresh_cfg->adc_thresh_cb; + adc_thresh_irqs[threshold_idx - 1] = thresh_cfg->adc_thresh_cb; /* Select the channel */ - SET_FIELD(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_CHNSEL, - npcx_adc_ch); + SET_FIELD(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_CHNSEL, npcx_adc_ch); if (thresh_cfg->lower_or_higher) SET_BIT(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_L_H); @@ -300,8 +341,7 @@ void npcx_adc_register_thresh_irq(int threshold_idx, raw_val = (thresh_cfg->thresh_assert - shift) * div / mul; CPRINTS("ADC THR%d: Setting THRVAL = %d, L_H: %d", threshold_idx, raw_val, thresh_cfg->lower_or_higher); - SET_FIELD(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_THRVAL, - raw_val); + SET_FIELD(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_THRVAL, raw_val); #if NPCX_FAMILY_VERSION <= NPCX_FAMILY_NPCX7 /* Disable deassertion threshold function */ @@ -319,7 +359,7 @@ void npcx_adc_register_thresh_irq(int threshold_idx, * @return none * @notes Only handle SW-triggered conversion in npcx chip */ -void adc_interrupt(void) +static void adc_interrupt(void) { int i; uint16_t thrcts; @@ -338,7 +378,12 @@ void adc_interrupt(void) /* Wake up the task which was waiting for the interrupt */ if (task_waiting != TASK_ID_INVALID) - task_set_event(task_waiting, TASK_EVENT_ADC_DONE, 0); + task_set_event(task_waiting, TASK_EVENT_ADC_DONE); + + if (IS_ENABLED(CONFIG_KEYBOARD_SCAN_ADC)) { + if (!task_start_called()) + adc_done = true; + } } for (i = NPCX_THRCTS_THR1_STS; i < NPCX_ADC_THRESH_CNT; i++) { @@ -346,7 +391,7 @@ void adc_interrupt(void) IS_BIT_SET(NPCX_THRCTS, i)) { /* avoid clearing other threshold status */ thrcts = NPCX_THRCTS & - ~GENMASK(NPCX_ADC_THRESH_CNT - 1, 0); + ~GENMASK(NPCX_ADC_THRESH_CNT - 1, 0); /* Clear threshold status */ SET_BIT(thrcts, i); NPCX_THRCTS = thrcts; @@ -357,35 +402,47 @@ void adc_interrupt(void) } DECLARE_IRQ(NPCX_IRQ_ADC, adc_interrupt, 4); +/* + * For Antighost keyboard, we need to initialize adc from + * main before keyboard_scan_init is called in order to + * detect boot keys + */ + /** * ADC initial. * * @param none * @return none */ +#ifndef CONFIG_KEYBOARD_SCAN_ADC static void adc_init(void) +#else +void adc_init(void) +#endif { /* Configure pins from GPIOs to ADCs */ gpio_config_module(MODULE_ADC, 1); /* Enable ADC clock (bit4 mask = 0x10) */ clock_enable_peripheral(CGC_OFFSET_ADC, CGC_ADC_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); + CGC_MODE_RUN | CGC_MODE_SLEEP); /* Set Core Clock Division Factor in order to obtain the ADC clock */ adc_freq_changed(); /* Set regular speed */ - SET_FIELD(NPCX_ATCTL, NPCX_ATCTL_DLY_FIELD, (ADC_REGULAR_DLY - 1)); + SET_FIELD(NPCX_ATCTL, NPCX_ATCTL_DLY_FIELD, ADC_DLY); /* Set the other ADC settings */ - NPCX_ADCCNF2 = ADC_REGULAR_ADCCNF2; - NPCX_GENDLY = ADC_REGULAR_GENDLY; - NPCX_MEAST = ADC_REGULAR_MEAST; + NPCX_ADCCNF2 = ADC_ADCCNF2; + NPCX_GENDLY = ADC_GENDLY; + NPCX_MEAST = ADC_MEAST; task_waiting = TASK_ID_INVALID; /* Enable IRQs */ task_enable_irq(NPCX_IRQ_ADC); } +#ifndef CONFIG_KEYBOARD_SCAN_ADC DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_INIT_ADC); +#endif diff --git a/chip/npcx/adc_chip.h b/chip/npcx/adc_chip.h index 9c2de3000d..5f3862829a 100644 --- a/chip/npcx/adc_chip.h +++ b/chip/npcx/adc_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,7 +8,7 @@ #ifndef __CROS_EC_ADC_CHIP_H #define __CROS_EC_ADC_CHIP_H -#include "adc.h" +#include "common.h" /* Minimum and maximum values returned by raw ADC read. */ #define ADC_READ_MIN 0 @@ -32,7 +32,7 @@ enum npcx_adc_input_channel { #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 NPCX_ADC_CH10, NPCX_ADC_CH11, - #endif +#endif NPCX_ADC_CH_COUNT }; @@ -45,12 +45,6 @@ struct adc_t { int shift; }; -/* - * Boards must provide this list of ADC channel definitions. This must match - * the enum adc_channel list provided by the board. - */ -extern const struct adc_t adc_channels[]; - /* * Boards may configure a ADC channel for use with thershold interrupts. * The threshold levels may be set from 0 to ADC_MAX_VOLT inclusive. diff --git a/chip/npcx/apm.c b/chip/npcx/apm.c index 4ab64774c1..b66a77a276 100644 --- a/chip/npcx/apm.c +++ b/chip/npcx/apm.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,13 +12,12 @@ #include "wov_chip.h" static struct apm_config apm_conf; -static struct apm_auto_gain_config apm_gain_conf; - +static struct apm_auto_gain_config apm_gain_conf; static uint32_t apm_indirect_reg[][3] = { - {(NPCX_APM_BASE_ADDR + 0x034), (NPCX_APM_BASE_ADDR + 0x038)}, - {(NPCX_APM_BASE_ADDR + 0x04C), (NPCX_APM_BASE_ADDR + 0x050)}, - {(NPCX_APM_BASE_ADDR + 0x05C), (NPCX_APM_BASE_ADDR + 0x060)} + { (NPCX_APM_BASE_ADDR + 0x034), (NPCX_APM_BASE_ADDR + 0x038) }, + { (NPCX_APM_BASE_ADDR + 0x04C), (NPCX_APM_BASE_ADDR + 0x050) }, + { (NPCX_APM_BASE_ADDR + 0x05C), (NPCX_APM_BASE_ADDR + 0x060) } }; #define APM_CNTRL_REG 0 @@ -37,11 +36,11 @@ static uint8_t apm_read_indirect_data(enum apm_indirect_reg_offset reg_offset, { /* Set the indirect access address. */ SET_FIELD(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_ADD, indirect_addr); + NPCX_APM_CONTROL_ADD, indirect_addr); /* Read command. */ CLEAR_BIT(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_LOAD); + NPCX_APM_CONTROL_LOAD); /* Get the data. */ return REG8(apm_indirect_reg[reg_offset][APM_DATA_REG]); @@ -57,20 +56,20 @@ static uint8_t apm_read_indirect_data(enum apm_indirect_reg_offset reg_offset, * @return None */ static void apm_write_indirect_data(enum apm_indirect_reg_offset reg_offset, - uint8_t indirect_addr, uint8_t value) + uint8_t indirect_addr, uint8_t value) { /* Set the data. */ REG8(apm_indirect_reg[reg_offset][APM_DATA_REG]) = value; /* Set the indirect access address. */ SET_FIELD(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_ADD, indirect_addr); + NPCX_APM_CONTROL_ADD, indirect_addr); /* Write command. */ SET_BIT(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_LOAD); + NPCX_APM_CONTROL_LOAD); CLEAR_BIT(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_LOAD); + NPCX_APM_CONTROL_LOAD); } /** @@ -83,13 +82,13 @@ void apm_set_adc_dmic_config_l(enum apm_dmic_rate rate) { if (rate == APM_DMIC_RATE_0_75) SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_RATE, - APM_DMIC_RATE_3_0); + APM_DMIC_RATE_3_0); else if (rate == APM_DMIC_RATE_1_2) SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_RATE, - APM_DMIC_RATE_2_4); + APM_DMIC_RATE_2_4); else SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_RATE, - rate); + rate); } /** @@ -108,7 +107,7 @@ void apm_set_vad_dmic_rate_l(enum apm_dmic_rate rate) /* Set VAD_0 register. */ if (rate == APM_DMIC_RATE_0_75) SET_FIELD(vad_data, NPCX_VAD_0_VAD_DMIC_FREQ, - APM_DMIC_RATE_3_0); + APM_DMIC_RATE_3_0); else if (rate == APM_DMIC_RATE_1_2) SET_FIELD(vad_data, NPCX_VAD_0_VAD_DMIC_FREQ, APM_DMIC_RATE_2_4); @@ -172,15 +171,15 @@ void apm_init(void) apm_conf.left_chan_gain = 0; apm_conf.right_chan_gain = 0; - apm_gain_conf.stereo_enable = 0; - apm_gain_conf.agc_target = APM_ADC_MAX_TARGET_LEVEL_19_5; - apm_gain_conf.nois_gate_en = 0; + apm_gain_conf.stereo_enable = 0; + apm_gain_conf.agc_target = APM_ADC_MAX_TARGET_LEVEL_19_5; + apm_gain_conf.nois_gate_en = 0; apm_gain_conf.nois_gate_thold = APM_MIN_NOISE_GET_THRESHOLD; - apm_gain_conf.hold_time = APM_HOLD_TIME_128; - apm_gain_conf.attack_time = APM_GAIN_RAMP_TIME_160; - apm_gain_conf.decay_time = APM_GAIN_RAMP_TIME_160; - apm_gain_conf.gain_max = APM_GAIN_VALUE_42_5; - apm_gain_conf.gain_min = APM_GAIN_VALUE_0_0; + apm_gain_conf.hold_time = APM_HOLD_TIME_128; + apm_gain_conf.attack_time = APM_GAIN_RAMP_TIME_160; + apm_gain_conf.decay_time = APM_GAIN_RAMP_TIME_160; + apm_gain_conf.gain_max = APM_GAIN_VALUE_42_5; + apm_gain_conf.gain_min = APM_GAIN_VALUE_0_0; } /** @@ -226,11 +225,11 @@ void apm_enable_vad_interrupt(int enable) void apm_adc_wov_enable(int enable) { if (enable) { - SET_FIELD(NPCX_APM_AICR_ADC, - NPCX_APM_AICR_ADC_ADC_AUDIOIF, 0x00); + SET_FIELD(NPCX_APM_AICR_ADC, NPCX_APM_AICR_ADC_ADC_AUDIOIF, + 0x00); } else { - SET_FIELD(NPCX_APM_AICR_ADC, - NPCX_APM_AICR_ADC_ADC_AUDIOIF, 0x03); + SET_FIELD(NPCX_APM_AICR_ADC, NPCX_APM_AICR_ADC_ADC_AUDIOIF, + 0x03); } } @@ -244,12 +243,12 @@ void apm_adc_enable(int enable) { if (enable) { CLEAR_BIT(NPCX_APM_AICR_ADC, NPCX_APM_AICR_ADC_PD_AICR_ADC); - SET_FIELD(NPCX_APM_AICR_ADC, - NPCX_APM_AICR_ADC_ADC_AUDIOIF, 0x00); + SET_FIELD(NPCX_APM_AICR_ADC, NPCX_APM_AICR_ADC_ADC_AUDIOIF, + 0x00); } else { SET_BIT(NPCX_APM_AICR_ADC, NPCX_APM_AICR_ADC_PD_AICR_ADC); - SET_FIELD(NPCX_APM_AICR_ADC, - NPCX_APM_AICR_ADC_ADC_AUDIOIF, 0x03); + SET_FIELD(NPCX_APM_AICR_ADC, NPCX_APM_AICR_ADC_ADC_AUDIOIF, + 0x03); } } @@ -273,8 +272,8 @@ void apm_adc_set_freq(enum apm_adc_frequency adc_freq) * @return None */ void apm_adc_config(int hpf_enable, - enum apm_adc_wind_noise_filter_mode filter_mode, - enum apm_adc_frequency adc_freq) + enum apm_adc_wind_noise_filter_mode filter_mode, + enum apm_adc_frequency adc_freq) { if (hpf_enable) SET_BIT(NPCX_APM_FCR_ADC, NPCX_APM_FCR_ADC_ADC_HPF); @@ -491,7 +490,8 @@ void apm_vad_restart(void) * @return EC_ERROR_INVAL or EC_SUCCESS */ enum ec_error_list apm_adc_gain_config(enum apm_adc_gain_coupling gain_coupling, - uint8_t left_chan_gain, uint8_t right_chan_gain) + uint8_t left_chan_gain, + uint8_t right_chan_gain) { /* Check parameters validity. */ if ((left_chan_gain > 0x2B) || (right_chan_gain > 0x2B)) @@ -538,8 +538,8 @@ void apm_auto_gain_cntrl_enable(int enable) * @param gain_cfg - struct of apm auto gain config * @return EC_ERROR_INVAL or EC_SUCCESS */ -enum ec_error_list apm_adc_auto_gain_config( - struct apm_auto_gain_config *gain_cfg) +enum ec_error_list +apm_adc_auto_gain_config(struct apm_auto_gain_config *gain_cfg) { uint8_t gain_data = 0; @@ -668,9 +668,8 @@ void apm_set_mode(enum wov_modes wov_mode) break; } - apm_adc_gain_config(apm_conf.gain_coupling, - apm_conf.left_chan_gain, - apm_conf.right_chan_gain); + apm_adc_gain_config(apm_conf.gain_coupling, apm_conf.left_chan_gain, + apm_conf.right_chan_gain); apm_adc_auto_gain_config(&apm_gain_conf); diff --git a/chip/npcx/apm_chip.h b/chip/npcx/apm_chip.h index ad62538374..9b330321ea 100644 --- a/chip/npcx/apm_chip.h +++ b/chip/npcx/apm_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,31 +9,27 @@ #include "common.h" /* MIX indirect registers. */ -#define APM_INDIRECT_MIX_2_REG 0x02 +#define APM_INDIRECT_MIX_2_REG 0x02 /* ADC_AGC indirect registers. */ -#define APM_INDIRECT_ADC_AGC_0_REG 0x00 -#define APM_INDIRECT_ADC_AGC_1_REG 0x01 -#define APM_INDIRECT_ADC_AGC_2_REG 0x02 -#define APM_INDIRECT_ADC_AGC_3_REG 0x03 -#define APM_INDIRECT_ADC_AGC_4_REG 0x04 +#define APM_INDIRECT_ADC_AGC_0_REG 0x00 +#define APM_INDIRECT_ADC_AGC_1_REG 0x01 +#define APM_INDIRECT_ADC_AGC_2_REG 0x02 +#define APM_INDIRECT_ADC_AGC_3_REG 0x03 +#define APM_INDIRECT_ADC_AGC_4_REG 0x04 /* APM_VAD_REG indirect registers. */ -#define APM_INDIRECT_VAD_0_REG 0x00 -#define APM_INDIRECT_VAD_1_REG 0x01 +#define APM_INDIRECT_VAD_0_REG 0x00 +#define APM_INDIRECT_VAD_1_REG 0x01 /* APM macros. */ -#define APM_IS_IRQ_PENDING IS_BIT_SET(NPCX_APM_SR, NPCX_APM_SR_IRQ_PEND) +#define APM_IS_IRQ_PENDING IS_BIT_SET(NPCX_APM_SR, NPCX_APM_SR_IRQ_PEND) #define APM_IS_VOICE_ACTIVITY_DETECTED \ IS_BIT_SET(NPCX_APM_IFR, NPCX_APM_IFR_VAD_DTC) -#define APM_CLEAR_VAD_INTERRUPT SET_BIT(NPCX_APM_IFR, NPCX_APM_IFR_VAD_DTC) +#define APM_CLEAR_VAD_INTERRUPT SET_BIT(NPCX_APM_IFR, NPCX_APM_IFR_VAD_DTC) /* Indirect registers. */ -enum apm_indirect_reg_offset { - APM_MIX_REG = 0, - APM_ADC_AGC_REG, - APM_VAD_REG -}; +enum apm_indirect_reg_offset { APM_MIX_REG = 0, APM_ADC_AGC_REG, APM_VAD_REG }; /* ADC wind noise filter modes. */ enum apm_adc_wind_noise_filter_mode { @@ -60,22 +56,22 @@ enum apm_adc_frequency { /* DMIC source. */ enum apm_dmic_src { APM_CURRENT_DMIC_CHANNEL = 0x01, /* Current channel, left or rigth. */ - APM_AVERAGE_DMIC_CHANNEL = 0x02 /* Average between left & right. */ + APM_AVERAGE_DMIC_CHANNEL = 0x02 /* Average between left & right. */ }; /* ADC digital microphone rate. */ enum apm_dmic_rate { /* 3.0, 2.4 & 1.0 must be 0, 1 & 2 respectively */ - APM_DMIC_RATE_3_0 = 0, /* 3.0 -3.25 MHz (default). */ - APM_DMIC_RATE_2_4, /* 2.4 -2.6 MHz. */ - APM_DMIC_RATE_1_0, /* 1.0 -1.08 MHz. */ - APM_DMIC_RATE_1_2, /* 1.2 MHz. */ - APM_DMIC_RATE_0_75 /* 750 KHz. */ + APM_DMIC_RATE_3_0 = 0, /* 3.0 -3.25 MHz (default). */ + APM_DMIC_RATE_2_4, /* 2.4 -2.6 MHz. */ + APM_DMIC_RATE_1_0, /* 1.0 -1.08 MHz. */ + APM_DMIC_RATE_1_2, /* 1.2 MHz. */ + APM_DMIC_RATE_0_75 /* 750 KHz. */ }; /* Digitla mixer output. */ enum apm_dig_mix { - APM_OUT_MIX_NORMAL_INPUT = 0, /* Default. */ + APM_OUT_MIX_NORMAL_INPUT = 0, /* Default. */ APM_OUT_MIX_CROSS_INPUT, APM_OUT_MIX_MIXED_INPUT, APM_OUT_MIX_NO_INPUT @@ -341,8 +337,8 @@ void apm_adc_set_freq(enum apm_adc_frequency adc_freq); * @return None */ void apm_adc_config(int hpf_enable, - enum apm_adc_wind_noise_filter_mode filter_mode, - enum apm_adc_frequency adc_freq); + enum apm_adc_wind_noise_filter_mode filter_mode, + enum apm_adc_frequency adc_freq); /** * Enables/Disables Digital Microphone. @@ -360,7 +356,7 @@ void apm_dmic_enable(int enable); * @return None */ void apm_digital_mixer_config(enum apm_dig_mix mix_left, - enum apm_dig_mix mix_right); + enum apm_dig_mix mix_right); /** * Enables/Disables the VAD functionality. @@ -422,7 +418,8 @@ void apm_vad_restart(void); * @return EC_ERROR_INVAL or EC_SUCCESS */ enum ec_error_list apm_adc_gain_config(enum apm_adc_gain_coupling gain_coupling, - uint8_t left_chan_gain, uint8_t right_chan_gain); + uint8_t left_chan_gain, + uint8_t right_chan_gain); /** * Enables/Disables the automatic gain. @@ -438,8 +435,8 @@ void apm_auto_gain_cntrl_enable(int enable); * @param gain_cfg - struct of apm auto gain config * @return EC_ERROR_INVAL or EC_SUCCESS */ -enum ec_error_list apm_adc_auto_gain_config( - struct apm_auto_gain_config *gain_cfg); +enum ec_error_list +apm_adc_auto_gain_config(struct apm_auto_gain_config *gain_cfg); /** * Sets APM mode (enables & disables APN sub modules accordingly diff --git a/chip/npcx/audio_codec_dmic.c b/chip/npcx/audio_codec_dmic.c index e242a8b2d2..7e1bfa9bce 100644 --- a/chip/npcx/audio_codec_dmic.c +++ b/chip/npcx/audio_codec_dmic.c @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/npcx/audio_codec_i2s_rx.c b/chip/npcx/audio_codec_i2s_rx.c index 12c4173048..02224be437 100644 --- a/chip/npcx/audio_codec_i2s_rx.c +++ b/chip/npcx/audio_codec_i2s_rx.c @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,7 +8,7 @@ #include "ec_commands.h" #include "wov_chip.h" -#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ##args) int audio_codec_i2s_rx_enable(void) { diff --git a/chip/npcx/build.mk b/chip/npcx/build.mk index 4409c33c5d..cbedd2bf68 100644 --- a/chip/npcx/build.mk +++ b/chip/npcx/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -9,7 +9,10 @@ # NPCX SoC has a Cortex-M4F ARM core CORE:=cortex-m # Allow the full Cortex-M4 instruction set -CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4 +CFLAGS_CPU+=-mcpu=cortex-m4 + +# Disable overlapping section warning that linker emits due to NPCX_RO_HEADER. +LDFLAGS_EXTRA+=-Wl,--no-check-sections # Assign default CHIP_FAMILY as npcx5 for old boards used npcx5 series ifeq ($(CHIP_FAMILY),) @@ -30,15 +33,16 @@ chip-$(CONFIG_FANS)+=fan.o chip-$(CONFIG_FLASH_PHYSICAL)+=flash.o chip-$(CONFIG_I2C)+=i2c.o i2c-$(CHIP_FAMILY).o chip-$(CONFIG_HOSTCMD_X86)+=lpc.o -chip-$(CONFIG_HOSTCMD_ESPI)+=espi.o +chip-$(CONFIG_HOST_INTERFACE_ESPI)+=espi.o chip-$(CONFIG_PECI)+=peci.o -chip-$(CONFIG_HOSTCMD_SPS)+=shi.o -chip-$(CONFIG_CEC)+=cec.o +chip-$(CONFIG_HOST_INTERFACE_SHI)+=shi.o +chip-$(CONFIG_CEC_BITBANG)+=cec_bitbang.o # pwm functions are implemented with the fan functions chip-$(CONFIG_PWM)+=pwm.o chip-$(CONFIG_SPI)+=spi.o +chip-$(CONFIG_RNG)+=trng.o chip-$(CONFIG_WATCHDOG)+=watchdog.o -ifndef CONFIG_KEYBOARD_NOT_RAW +ifndef CONFIG_KEYBOARD_DISCRETE chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o endif @@ -48,6 +52,8 @@ ifneq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),npcx5 npcx7)) chip-y+=lct.o endif +chip-$(CONFIG_SHA256_HW_ACCELERATE)+=sha256_chip.o + # spi monitor program fw for openocd and UUT(UART Update Tool) npcx-monitor-fw=chip/npcx/spiflashfw/npcx_monitor npcx-monitor-fw-bin=${out}/$(npcx-monitor-fw).bin @@ -67,13 +73,13 @@ show_esct_cmd=$(if $(V),,echo ' ECST ' $(subst $(out)/,,$@) ; ) # size when the CONFIG_CHIP_INIT_ROM_REGION is used. Note that the -fwlen # parameter for the ecst utility must be in hex. cmd_fwlen=$(shell awk '\ - /__flash_used =/ {flash_used = strtonum($$1)} \ + /__flash_used/ {flash_used = strtonum("0x" $$1)} \ END {printf ("%x", flash_used)}' $(1)) # ECST options for header bld_ecst=${out}/util/ecst -chip $(CHIP_VARIANT) \ -usearmrst -mode bt -ph -i $(1) -o $(2) -nohcrc -nofcrc -flashsize 8 \ - -fwlen $(call cmd_fwlen, $(patsubst %.flat,%.map,$(2))) \ + -fwlen $(call cmd_fwlen, $(patsubst %.flat,%.smap,$(2))) \ -spimaxclk 50 -spireadmode dual 1> /dev/null # Replace original one with the flat file including header @@ -86,5 +92,5 @@ cmd_ecst=$(show_esct_cmd)$(call moveflat,$@,$@.tmp);$(call bld_ecst,$@.tmp,$@) cmd_org_ec_elf_to_flat = $(OBJCOPY) --set-section-flags .roshared=share \ -O binary $(patsubst %.flat,%.elf,$@) $@ cmd_npcx_ro_elf_to_flat=$(cmd_org_ec_elf_to_flat);$(cmd_ecst) -cmd_ec_elf_to_flat = $(if $(filter $(out)/RO/ec.RO.flat, $@), \ +cmd_ec_elf_to_flat = $(if $(filter %.RO.flat, $@), \ $(cmd_npcx_ro_elf_to_flat), $(cmd_org_ec_elf_to_flat) ) diff --git a/chip/npcx/cec.c b/chip/npcx/cec.c deleted file mode 100644 index 76fbf8279f..0000000000 --- a/chip/npcx/cec.c +++ /dev/null @@ -1,1040 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "atomic.h" -#include "cec.h" -#include "clock_chip.h" -#include "console.h" -#include "ec_commands.h" -#include "fan_chip.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "mkbp_event.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#if !(DEBUG_CEC) -#define CPRINTF(...) -#define CPRINTS(...) -#else -#define CPRINTF(format, args...) cprintf(CC_CEC, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CEC, format, ## args) -#endif - -/* Time in us to timer clock ticks */ -#define APB1_TICKS(t) ((t) * apb1_freq_div_10k / 100) -#if DEBUG_CEC -/* Timer clock ticks to us */ -#define APB1_US(ticks) (100*(ticks)/apb1_freq_div_10k) -#endif - -/* Notification from interrupt to CEC task that data has been received */ -#define TASK_EVENT_RECEIVED_DATA TASK_EVENT_CUSTOM_BIT(0) - -/* CEC broadcast address. Also the highest possible CEC address */ -#define CEC_BROADCAST_ADDR 15 - -/* Address to indicate that no logical address has been set */ -#define CEC_UNREGISTERED_ADDR 255 - -/* - * The CEC specification requires at least one and a maximum of - * five resends attempts - */ -#define CEC_MAX_RESENDS 5 - -/* - * Free time timing (us). Our free-time is calculated from the end of - * the last bit (not from the start). We compensate by having one - * free-time period less than in the spec. - */ -#define NOMINAL_BIT_TICKS APB1_TICKS(2400) - /* Resend */ -#define FREE_TIME_RS_TICKS (2 * (NOMINAL_BIT_TICKS)) -/* New initiator */ -#define FREE_TIME_NI_TICKS (4 * (NOMINAL_BIT_TICKS)) -/* Present initiator */ -#define FREE_TIME_PI_TICKS (6 * (NOMINAL_BIT_TICKS)) - -/* Start bit timing */ -#define START_BIT_LOW_TICKS APB1_TICKS(3700) -#define START_BIT_MIN_LOW_TICKS APB1_TICKS(3500) -#define START_BIT_MAX_LOW_TICKS APB1_TICKS(3900) -#define START_BIT_HIGH_TICKS APB1_TICKS(800) -#define START_BIT_MIN_DURATION_TICKS APB1_TICKS(4300) -#define START_BIT_MAX_DURATION_TICKS APB1_TICKS(5700) - -/* Data bit timing */ -#define DATA_ZERO_LOW_TICKS APB1_TICKS(1500) -#define DATA_ZERO_MIN_LOW_TICKS APB1_TICKS(1300) -#define DATA_ZERO_MAX_LOW_TICKS APB1_TICKS(1700) -#define DATA_ZERO_HIGH_TICKS APB1_TICKS(900) -#define DATA_ZERO_MIN_DURATION_TICKS APB1_TICKS(2050) -#define DATA_ZERO_MAX_DURATION_TICKS APB1_TICKS(2750) - -#define DATA_ONE_LOW_TICKS APB1_TICKS(600) -#define DATA_ONE_MIN_LOW_TICKS APB1_TICKS(400) -#define DATA_ONE_MAX_LOW_TICKS APB1_TICKS(800) -#define DATA_ONE_HIGH_TICKS APB1_TICKS(1800) -#define DATA_ONE_MIN_DURATION_TICKS APB1_TICKS(2050) -#define DATA_ONE_MAX_DURATION_TICKS APB1_TICKS(2750) - -/* Time from low that it should be safe to sample an ACK */ -#define NOMINAL_SAMPLE_TIME_TICKS APB1_TICKS(1050) - -#define DATA_TIME(type, data) ((data) ? (DATA_ONE_ ## type ## _TICKS) : \ - (DATA_ZERO_ ## type ## _TICKS)) -#define DATA_HIGH(data) DATA_TIME(HIGH, data) -#define DATA_LOW(data) DATA_TIME(LOW, data) - -/* - * Number of short pulses seen before the debounce logic goes into ignoring - * the bus for DEBOUNCE_WAIT_LONG instead of DEBOUNCE_WAIT_SHORT - */ -#define DEBOUNCE_CUTOFF 3 - -/* The limit how short a start-bit can be to trigger debounce logic */ -#define DEBOUNCE_LIMIT_TICKS APB1_TICKS(200) -/* The time we ignore the bus for the first three debounce cases */ -#define DEBOUNCE_WAIT_SHORT_TICKS APB1_TICKS(100) -/* The time we ignore the bus after the three initial debounce cases */ -#define DEBOUNCE_WAIT_LONG_TICKS APB1_TICKS(500) - -/* - * The variance in timing we allow outside of the CEC specification for - * incoming signals. Our measurements aren't 100% accurate either, so this - * gives some robustness. - */ -#define VALID_TOLERANCE_TICKS APB1_TICKS(100) - -/* - * Defines used for setting capture timers to a point where we are - * sure that if we get a timeout, something is wrong. - */ -#define CAP_START_LOW_TICKS (START_BIT_MAX_LOW_TICKS + VALID_TOLERANCE_TICKS) -#define CAP_START_HIGH_TICKS (START_BIT_MAX_DURATION_TICKS - \ - START_BIT_MIN_LOW_TICKS + \ - VALID_TOLERANCE_TICKS) -#define CAP_DATA_LOW_TICKS (DATA_ZERO_MAX_LOW_TICKS + VALID_TOLERANCE_TICKS) -#define CAP_DATA_HIGH_TICKS (DATA_ONE_MAX_DURATION_TICKS - \ - DATA_ONE_MIN_LOW_TICKS + \ - VALID_TOLERANCE_TICKS) - -#define VALID_TIME(type, bit, t) \ - ((t) >= ((bit ## _MIN_ ## type ## _TICKS) - (VALID_TOLERANCE_TICKS)) \ - && (t) <= (bit ##_MAX_ ## type ## _TICKS) + (VALID_TOLERANCE_TICKS)) -#define VALID_LOW(bit, t) VALID_TIME(LOW, bit, t) -#define VALID_HIGH(bit, low_time, high_time) \ - (((low_time) + (high_time) <= \ - bit ## _MAX_DURATION_TICKS + VALID_TOLERANCE_TICKS) && \ - ((low_time) + (high_time) >= \ - bit ## _MIN_DURATION_TICKS - VALID_TOLERANCE_TICKS)) -#define VALID_DATA_HIGH(data, low_time, high_time) ((data) ? \ - VALID_HIGH(DATA_ONE, low_time, high_time) : \ - VALID_HIGH(DATA_ZERO, low_time, high_time)) - -/* - * CEC state machine states. Each state typically takes action on entry and - * timeouts. INITIATIOR states are used for sending, FOLLOWER states are used - * for receiving. - */ -enum cec_state { - CEC_STATE_DISABLED = 0, - CEC_STATE_IDLE, - CEC_STATE_INITIATOR_FREE_TIME, - CEC_STATE_INITIATOR_START_LOW, - CEC_STATE_INITIATOR_START_HIGH, - CEC_STATE_INITIATOR_HEADER_INIT_LOW, - CEC_STATE_INITIATOR_HEADER_INIT_HIGH, - CEC_STATE_INITIATOR_HEADER_DEST_LOW, - CEC_STATE_INITIATOR_HEADER_DEST_HIGH, - CEC_STATE_INITIATOR_DATA_LOW, - CEC_STATE_INITIATOR_DATA_HIGH, - CEC_STATE_INITIATOR_EOM_LOW, - CEC_STATE_INITIATOR_EOM_HIGH, - CEC_STATE_INITIATOR_ACK_LOW, - CEC_STATE_INITIATOR_ACK_HIGH, - CEC_STATE_INITIATOR_ACK_VERIFY, - CEC_STATE_FOLLOWER_START_LOW, - CEC_STATE_FOLLOWER_START_HIGH, - CEC_STATE_FOLLOWER_DEBOUNCE, - CEC_STATE_FOLLOWER_HEADER_INIT_LOW, - CEC_STATE_FOLLOWER_HEADER_INIT_HIGH, - CEC_STATE_FOLLOWER_HEADER_DEST_LOW, - CEC_STATE_FOLLOWER_HEADER_DEST_HIGH, - CEC_STATE_FOLLOWER_EOM_LOW, - CEC_STATE_FOLLOWER_EOM_HIGH, - CEC_STATE_FOLLOWER_ACK_LOW, - CEC_STATE_FOLLOWER_ACK_VERIFY, - CEC_STATE_FOLLOWER_ACK_FINISH, - CEC_STATE_FOLLOWER_DATA_LOW, - CEC_STATE_FOLLOWER_DATA_HIGH, -}; - -/* Edge to trigger capture timer interrupt on */ -enum cap_edge { - CAP_EDGE_FALLING, - CAP_EDGE_RISING -}; - -/* Receive buffer and states */ -struct cec_rx { - /* - * The current incoming message being parsed. Copied to - * receive queue upon completion - */ - struct cec_msg_transfer transfer; - /* End of Message received from source? */ - uint8_t eom; - /* A follower NAK:ed a broadcast transfer */ - uint8_t broadcast_nak; - /* - * Keep track of pulse low time to be able to verify - * pulse duration - */ - int low_ticks; - /* Number of too short pulses seen in a row */ - int debounce_count; -}; - -/* Transfer buffer and states */ -struct cec_tx { - /* Outgoing message */ - struct cec_msg_transfer transfer; - /* Message length */ - uint8_t len; - /* Number of resends attempted in current send */ - uint8_t resends; - /* Acknowledge received from sink? */ - uint8_t ack; - /* - * When sending multiple concurrent frames, - * the free-time is slightly higher - */ - int present_initiator; -}; - -/* Single state for CEC. We are INITIATOR, FOLLOWER or IDLE */ -static enum cec_state cec_state; - -/* Parameters and buffers for follower (receiver) state */ -static struct cec_rx cec_rx; - -/* Queue of completed incoming CEC messages */ -static struct cec_rx_queue cec_rx_queue; - -/* Parameters and buffer for initiator (sender) state */ -static struct cec_tx cec_tx; - -/* - * Time between interrupt triggered and the next timer was - * set when measuring pulse width - */ -static int cap_delay; - -/* Value charged into the capture timer on last capture start */ -static int cap_charge; - -/* - * CEC address of ourself. We ack incoming packages on this address. - * However, the AP is responsible for writing the initiator address - * on writes. UINT32_MAX means means that the address hasn't been - * set by the AP yet. - */ -static uint8_t cec_addr = UINT8_MAX; - -/* Events to send to AP */ -static uint32_t cec_events; - -/* APB1 frequency. Store divided by 10k to avoid some runtime divisions */ -static uint32_t apb1_freq_div_10k; - -static void send_mkbp_event(uint32_t event) -{ - deprecated_atomic_or(&cec_events, event); - mkbp_send_event(EC_MKBP_EVENT_CEC_EVENT); -} - -static void tmr_cap_start(enum cap_edge edge, int timeout) -{ - int mdl = NPCX_MFT_MODULE_1; - - /* Select edge to trigger capture on */ - UPDATE_BIT(NPCX_TMCTRL(mdl), NPCX_TMCTRL_TAEDG, - edge == CAP_EDGE_RISING); - - /* - * Set capture timeout. If we don't have a timeout, we - * turn the timeout interrupt off and only care about - * the edge change. - */ - if (timeout > 0) { - /* - * Store the time it takes from the interrupts starts to when we - * actually get here. This part of the pulse-width needs to be - * taken into account - */ - cap_delay = (0xffff - NPCX_TCNT1(mdl)); - cap_charge = timeout - cap_delay; - NPCX_TCNT1(mdl) = cap_charge; - SET_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TCIEN); - } else { - CLEAR_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TCIEN); - NPCX_TCNT1(mdl) = 0; - } - - /* Clear out old events */ - SET_BIT(NPCX_TECLR(mdl), NPCX_TECLR_TACLR); - SET_BIT(NPCX_TECLR(mdl), NPCX_TECLR_TCCLR); - NPCX_TCRA(mdl) = 0; - /* Start the capture timer */ - SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C1CSEL_FIELD, 1); -} - -static void tmr_cap_stop(void) -{ - int mdl = NPCX_MFT_MODULE_1; - - CLEAR_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TCIEN); - SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C1CSEL_FIELD, 0); -} - -static int tmr_cap_get(void) -{ - int mdl = NPCX_MFT_MODULE_1; - - return (cap_charge + cap_delay - NPCX_TCRA(mdl)); -} - -static void tmr_oneshot_start(int timeout) -{ - int mdl = NPCX_MFT_MODULE_1; - - NPCX_TCNT1(mdl) = timeout; - SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C1CSEL_FIELD, 1); -} - -static void tmr2_start(int timeout) -{ - int mdl = NPCX_MFT_MODULE_1; - - NPCX_TCNT2(mdl) = timeout; - SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C2CSEL_FIELD, 1); -} - -static void tmr2_stop(void) -{ - int mdl = NPCX_MFT_MODULE_1; - - SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C2CSEL_FIELD, 0); -} - -void enter_state(enum cec_state new_state) -{ - int gpio = -1, timeout = -1; - enum cap_edge cap_edge = -1; - uint8_t addr; - - cec_state = new_state; - switch (new_state) { - case CEC_STATE_DISABLED: - gpio = 1; - memset(&cec_rx, 0, sizeof(struct cec_rx)); - memset(&cec_tx, 0, sizeof(struct cec_tx)); - memset(&cec_rx_queue, 0, sizeof(struct cec_rx_queue)); - cap_charge = 0; - cap_delay = 0; - cec_events = 0; - break; - case CEC_STATE_IDLE: - cec_tx.transfer.bit = 0; - cec_tx.transfer.byte = 0; - cec_rx.transfer.bit = 0; - cec_rx.transfer.byte = 0; - if (cec_tx.len > 0) { - /* Execute a postponed send */ - enter_state(CEC_STATE_INITIATOR_FREE_TIME); - } else { - /* Wait for incoming command */ - gpio = 1; - cap_edge = CAP_EDGE_FALLING; - timeout = 0; - } - break; - case CEC_STATE_INITIATOR_FREE_TIME: - gpio = 1; - cap_edge = CAP_EDGE_FALLING; - if (cec_tx.resends) - timeout = FREE_TIME_RS_TICKS; - else if (cec_tx.present_initiator) - timeout = FREE_TIME_PI_TICKS; - else - timeout = FREE_TIME_NI_TICKS; - break; - case CEC_STATE_INITIATOR_START_LOW: - cec_tx.present_initiator = 1; - cec_tx.transfer.bit = 0; - cec_tx.transfer.byte = 0; - gpio = 0; - timeout = START_BIT_LOW_TICKS; - break; - case CEC_STATE_INITIATOR_START_HIGH: - gpio = 1; - cap_edge = CAP_EDGE_FALLING; - timeout = START_BIT_HIGH_TICKS; - break; - case CEC_STATE_INITIATOR_HEADER_INIT_LOW: - case CEC_STATE_INITIATOR_HEADER_DEST_LOW: - case CEC_STATE_INITIATOR_DATA_LOW: - gpio = 0; - timeout = DATA_LOW(cec_transfer_get_bit(&cec_tx.transfer)); - break; - case CEC_STATE_INITIATOR_HEADER_INIT_HIGH: - gpio = 1; - cap_edge = CAP_EDGE_FALLING; - timeout = DATA_HIGH(cec_transfer_get_bit(&cec_tx.transfer)); - break; - case CEC_STATE_INITIATOR_HEADER_DEST_HIGH: - case CEC_STATE_INITIATOR_DATA_HIGH: - gpio = 1; - timeout = DATA_HIGH(cec_transfer_get_bit(&cec_tx.transfer)); - break; - case CEC_STATE_INITIATOR_EOM_LOW: - gpio = 0; - timeout = DATA_LOW(cec_transfer_is_eom(&cec_tx.transfer, - cec_tx.len)); - break; - case CEC_STATE_INITIATOR_EOM_HIGH: - gpio = 1; - timeout = DATA_HIGH(cec_transfer_is_eom(&cec_tx.transfer, - cec_tx.len)); - break; - case CEC_STATE_INITIATOR_ACK_LOW: - gpio = 0; - timeout = DATA_LOW(1); - break; - case CEC_STATE_INITIATOR_ACK_HIGH: - gpio = 1; - /* Aim for the middle of the safe sample time */ - timeout = (DATA_ONE_LOW_TICKS + DATA_ZERO_LOW_TICKS)/2 - - DATA_ONE_LOW_TICKS; - break; - case CEC_STATE_INITIATOR_ACK_VERIFY: - cec_tx.ack = !gpio_get_level(CEC_GPIO_OUT); - if ((cec_tx.transfer.buf[0] & 0x0f) == CEC_BROADCAST_ADDR) { - /* - * We are sending a broadcast. Any follower can - * can NAK a broadcast message the same way they - * would ACK a direct message - */ - cec_tx.ack = !cec_tx.ack; - } - /* - * We are at the safe sample time. Wait - * until the end of this bit - */ - timeout = NOMINAL_BIT_TICKS - NOMINAL_SAMPLE_TIME_TICKS; - break; - case CEC_STATE_FOLLOWER_START_LOW: - cec_tx.present_initiator = 0; - cap_edge = CAP_EDGE_RISING; - timeout = CAP_START_LOW_TICKS; - break; - case CEC_STATE_FOLLOWER_START_HIGH: - cec_rx.debounce_count = 0; - cap_edge = CAP_EDGE_FALLING; - timeout = CAP_START_HIGH_TICKS; - break; - case CEC_STATE_FOLLOWER_DEBOUNCE: - if (cec_rx.debounce_count >= DEBOUNCE_CUTOFF) { - timeout = DEBOUNCE_WAIT_LONG_TICKS; - } else { - timeout = DEBOUNCE_WAIT_SHORT_TICKS; - cec_rx.debounce_count++; - } - break; - case CEC_STATE_FOLLOWER_HEADER_INIT_LOW: - case CEC_STATE_FOLLOWER_HEADER_DEST_LOW: - case CEC_STATE_FOLLOWER_EOM_LOW: - cap_edge = CAP_EDGE_RISING; - timeout = CAP_DATA_LOW_TICKS; - break; - case CEC_STATE_FOLLOWER_HEADER_INIT_HIGH: - case CEC_STATE_FOLLOWER_HEADER_DEST_HIGH: - case CEC_STATE_FOLLOWER_EOM_HIGH: - cap_edge = CAP_EDGE_FALLING; - timeout = CAP_DATA_HIGH_TICKS; - break; - case CEC_STATE_FOLLOWER_ACK_LOW: - addr = cec_rx.transfer.buf[0] & 0x0f; - if (addr == cec_addr) { - /* Destination is our address */ - gpio = 0; - timeout = NOMINAL_SAMPLE_TIME_TICKS; - } else if (addr == CEC_BROADCAST_ADDR) { - /* Don't ack broadcast or packets which destination - * are us, but continue reading - */ - timeout = NOMINAL_SAMPLE_TIME_TICKS; - } - break; - case CEC_STATE_FOLLOWER_ACK_VERIFY: - /* - * We are at safe sample time. A broadcast frame is considered - * lost if any follower pulls the line low - */ - if ((cec_rx.transfer.buf[0] & 0x0f) == CEC_BROADCAST_ADDR) - cec_rx.broadcast_nak = !gpio_get_level(CEC_GPIO_OUT); - else - cec_rx.broadcast_nak = 0; - - /* - * We release the ACK at the end of data zero low - * period (ACK is technically a zero). - */ - timeout = DATA_ZERO_LOW_TICKS - NOMINAL_SAMPLE_TIME_TICKS; - break; - case CEC_STATE_FOLLOWER_ACK_FINISH: - gpio = 1; - if (cec_rx.eom || cec_rx.transfer.byte >= MAX_CEC_MSG_LEN) { - addr = cec_rx.transfer.buf[0] & 0x0f; - if (addr == cec_addr || addr == CEC_BROADCAST_ADDR) { - task_set_event(TASK_ID_CEC, - TASK_EVENT_RECEIVED_DATA, 0); - } - timeout = DATA_ZERO_HIGH_TICKS; - } else { - cap_edge = CAP_EDGE_FALLING; - timeout = CAP_DATA_HIGH_TICKS; - } - break; - case CEC_STATE_FOLLOWER_DATA_LOW: - cap_edge = CAP_EDGE_RISING; - timeout = CAP_DATA_LOW_TICKS; - break; - case CEC_STATE_FOLLOWER_DATA_HIGH: - cap_edge = CAP_EDGE_FALLING; - timeout = CAP_DATA_HIGH_TICKS; - break; - /* No default case, since all states must be handled explicitly */ - } - - if (gpio >= 0) - gpio_set_level(CEC_GPIO_OUT, gpio); - if (timeout >= 0) { - if (cap_edge >= 0) - tmr_cap_start(cap_edge, timeout); - else - tmr_oneshot_start(timeout); - } -} - -static void cec_event_timeout(void) -{ - switch (cec_state) { - case CEC_STATE_DISABLED: - case CEC_STATE_IDLE: - break; - case CEC_STATE_INITIATOR_FREE_TIME: - enter_state(CEC_STATE_INITIATOR_START_LOW); - break; - case CEC_STATE_INITIATOR_START_LOW: - enter_state(CEC_STATE_INITIATOR_START_HIGH); - break; - case CEC_STATE_INITIATOR_START_HIGH: - enter_state(CEC_STATE_INITIATOR_HEADER_INIT_LOW); - break; - case CEC_STATE_INITIATOR_HEADER_INIT_LOW: - enter_state(CEC_STATE_INITIATOR_HEADER_INIT_HIGH); - break; - case CEC_STATE_INITIATOR_HEADER_INIT_HIGH: - cec_transfer_inc_bit(&cec_tx.transfer); - if (cec_tx.transfer.bit == 4) - enter_state(CEC_STATE_INITIATOR_HEADER_DEST_LOW); - else - enter_state(CEC_STATE_INITIATOR_HEADER_INIT_LOW); - break; - case CEC_STATE_INITIATOR_HEADER_DEST_LOW: - enter_state(CEC_STATE_INITIATOR_HEADER_DEST_HIGH); - break; - case CEC_STATE_INITIATOR_HEADER_DEST_HIGH: - cec_transfer_inc_bit(&cec_tx.transfer); - if (cec_tx.transfer.byte == 1) - enter_state(CEC_STATE_INITIATOR_EOM_LOW); - else - enter_state(CEC_STATE_INITIATOR_HEADER_DEST_LOW); - break; - case CEC_STATE_INITIATOR_EOM_LOW: - enter_state(CEC_STATE_INITIATOR_EOM_HIGH); - break; - case CEC_STATE_INITIATOR_EOM_HIGH: - enter_state(CEC_STATE_INITIATOR_ACK_LOW); - break; - case CEC_STATE_INITIATOR_ACK_LOW: - enter_state(CEC_STATE_INITIATOR_ACK_HIGH); - break; - case CEC_STATE_INITIATOR_ACK_HIGH: - enter_state(CEC_STATE_INITIATOR_ACK_VERIFY); - break; - case CEC_STATE_INITIATOR_ACK_VERIFY: - if (cec_tx.ack) { - if (!cec_transfer_is_eom(&cec_tx.transfer, - cec_tx.len)) { - /* More data in this frame */ - enter_state(CEC_STATE_INITIATOR_DATA_LOW); - } else { - /* Transfer completed successfully */ - cec_tx.len = 0; - cec_tx.resends = 0; - enter_state(CEC_STATE_IDLE); - send_mkbp_event(EC_MKBP_CEC_SEND_OK); - } - } else { - if (cec_tx.resends < CEC_MAX_RESENDS) { - /* Resend */ - cec_tx.resends++; - enter_state(CEC_STATE_INITIATOR_FREE_TIME); - } else { - /* Transfer failed */ - cec_tx.len = 0; - cec_tx.resends = 0; - enter_state(CEC_STATE_IDLE); - send_mkbp_event(EC_MKBP_CEC_SEND_FAILED); - } - } - break; - case CEC_STATE_INITIATOR_DATA_LOW: - enter_state(CEC_STATE_INITIATOR_DATA_HIGH); - break; - case CEC_STATE_INITIATOR_DATA_HIGH: - cec_transfer_inc_bit(&cec_tx.transfer); - if (cec_tx.transfer.bit == 0) - enter_state(CEC_STATE_INITIATOR_EOM_LOW); - else - enter_state(CEC_STATE_INITIATOR_DATA_LOW); - break; - case CEC_STATE_FOLLOWER_ACK_LOW: - enter_state(CEC_STATE_FOLLOWER_ACK_VERIFY); - break; - case CEC_STATE_FOLLOWER_ACK_VERIFY: - if (cec_rx.broadcast_nak) - enter_state(CEC_STATE_IDLE); - else - enter_state(CEC_STATE_FOLLOWER_ACK_FINISH); - break; - case CEC_STATE_FOLLOWER_START_LOW: - case CEC_STATE_FOLLOWER_START_HIGH: - case CEC_STATE_FOLLOWER_DEBOUNCE: - case CEC_STATE_FOLLOWER_HEADER_INIT_LOW: - case CEC_STATE_FOLLOWER_HEADER_INIT_HIGH: - case CEC_STATE_FOLLOWER_HEADER_DEST_LOW: - case CEC_STATE_FOLLOWER_HEADER_DEST_HIGH: - case CEC_STATE_FOLLOWER_EOM_LOW: - case CEC_STATE_FOLLOWER_EOM_HIGH: - case CEC_STATE_FOLLOWER_ACK_FINISH: - case CEC_STATE_FOLLOWER_DATA_LOW: - case CEC_STATE_FOLLOWER_DATA_HIGH: - enter_state(CEC_STATE_IDLE); - break; - - } -} - -static void cec_event_cap(void) -{ - int t; - int data; - - switch (cec_state) { - case CEC_STATE_IDLE: - /* A falling edge during idle, likely a start bit */ - enter_state(CEC_STATE_FOLLOWER_START_LOW); - break; - case CEC_STATE_INITIATOR_FREE_TIME: - case CEC_STATE_INITIATOR_START_HIGH: - case CEC_STATE_INITIATOR_HEADER_INIT_HIGH: - /* - * A falling edge during free-time, postpone - * this send and listen - */ - cec_tx.transfer.bit = 0; - cec_tx.transfer.byte = 0; - enter_state(CEC_STATE_FOLLOWER_START_LOW); - break; - case CEC_STATE_FOLLOWER_START_LOW: - /* Rising edge of start bit, validate low time */ - t = tmr_cap_get(); - if (VALID_LOW(START_BIT, t)) { - cec_rx.low_ticks = t; - enter_state(CEC_STATE_FOLLOWER_START_HIGH); - } else if (t < DEBOUNCE_LIMIT_TICKS) { - /* Wait a bit if start-pulses are really short */ - enter_state(CEC_STATE_FOLLOWER_DEBOUNCE); - } else { - enter_state(CEC_STATE_IDLE); - } - break; - case CEC_STATE_FOLLOWER_START_HIGH: - if (VALID_HIGH(START_BIT, cec_rx.low_ticks, tmr_cap_get())) - enter_state(CEC_STATE_FOLLOWER_HEADER_INIT_LOW); - else - enter_state(CEC_STATE_IDLE); - break; - case CEC_STATE_FOLLOWER_HEADER_INIT_LOW: - case CEC_STATE_FOLLOWER_HEADER_DEST_LOW: - case CEC_STATE_FOLLOWER_DATA_LOW: - t = tmr_cap_get(); - if (VALID_LOW(DATA_ZERO, t)) { - cec_rx.low_ticks = t; - cec_transfer_set_bit(&cec_rx.transfer, 0); - enter_state(cec_state + 1); - } else if (VALID_LOW(DATA_ONE, t)) { - cec_rx.low_ticks = t; - cec_transfer_set_bit(&cec_rx.transfer, 1); - enter_state(cec_state + 1); - } else { - enter_state(CEC_STATE_IDLE); - } - break; - case CEC_STATE_FOLLOWER_HEADER_INIT_HIGH: - t = tmr_cap_get(); - data = cec_transfer_get_bit(&cec_rx.transfer); - if (VALID_DATA_HIGH(data, cec_rx.low_ticks, t)) { - cec_transfer_inc_bit(&cec_rx.transfer); - if (cec_rx.transfer.bit == 4) - enter_state(CEC_STATE_FOLLOWER_HEADER_DEST_LOW); - else - enter_state(CEC_STATE_FOLLOWER_HEADER_INIT_LOW); - } else { - enter_state(CEC_STATE_IDLE); - } - break; - case CEC_STATE_FOLLOWER_HEADER_DEST_HIGH: - t = tmr_cap_get(); - data = cec_transfer_get_bit(&cec_rx.transfer); - if (VALID_DATA_HIGH(data, cec_rx.low_ticks, t)) { - cec_transfer_inc_bit(&cec_rx.transfer); - if (cec_rx.transfer.bit == 0) - enter_state(CEC_STATE_FOLLOWER_EOM_LOW); - else - enter_state(CEC_STATE_FOLLOWER_HEADER_DEST_LOW); - } else { - enter_state(CEC_STATE_IDLE); - } - break; - case CEC_STATE_FOLLOWER_EOM_LOW: - t = tmr_cap_get(); - if (VALID_LOW(DATA_ZERO, t)) { - cec_rx.low_ticks = t; - cec_rx.eom = 0; - enter_state(CEC_STATE_FOLLOWER_EOM_HIGH); - } else if (VALID_LOW(DATA_ONE, t)) { - cec_rx.low_ticks = t; - cec_rx.eom = 1; - enter_state(CEC_STATE_FOLLOWER_EOM_HIGH); - } else { - enter_state(CEC_STATE_IDLE); - } - break; - case CEC_STATE_FOLLOWER_EOM_HIGH: - t = tmr_cap_get(); - data = cec_rx.eom; - if (VALID_DATA_HIGH(data, cec_rx.low_ticks, t)) - enter_state(CEC_STATE_FOLLOWER_ACK_LOW); - else - enter_state(CEC_STATE_IDLE); - break; - case CEC_STATE_FOLLOWER_ACK_LOW: - enter_state(CEC_STATE_FOLLOWER_ACK_FINISH); - break; - case CEC_STATE_FOLLOWER_ACK_FINISH: - enter_state(CEC_STATE_FOLLOWER_DATA_LOW); - break; - case CEC_STATE_FOLLOWER_DATA_HIGH: - t = tmr_cap_get(); - data = cec_transfer_get_bit(&cec_rx.transfer); - if (VALID_DATA_HIGH(data, cec_rx.low_ticks, t)) { - cec_transfer_inc_bit(&cec_rx.transfer); - if (cec_rx.transfer.bit == 0) - enter_state(CEC_STATE_FOLLOWER_EOM_LOW); - else - enter_state(CEC_STATE_FOLLOWER_DATA_LOW); - } else { - enter_state(CEC_STATE_IDLE); - } - break; - default: - break; - } -} - -static void cec_event_tx(void) -{ - /* - * If we have an ongoing receive, this transfer - * will start when transitioning to IDLE - */ - if (cec_state == CEC_STATE_IDLE) - enter_state(CEC_STATE_INITIATOR_FREE_TIME); -} - -void cec_isr(void) -{ - int mdl = NPCX_MFT_MODULE_1; - uint8_t events; - - /* Retrieve events NPCX_TECTRL_TAXND */ - events = GET_FIELD(NPCX_TECTRL(mdl), FIELD(0, 4)); - - if (events & BIT(NPCX_TECTRL_TAPND)) { - /* Capture event */ - cec_event_cap(); - } else { - /* - * Capture timeout - * We only care about this if the capture event is not - * happening, since we will get both events in the - * edge-trigger case - */ - if (events & BIT(NPCX_TECTRL_TCPND)) - cec_event_timeout(); - } - /* Oneshot timer, a transfer has been initiated from AP */ - if (events & BIT(NPCX_TECTRL_TDPND)) { - tmr2_stop(); - cec_event_tx(); - } - - /* Clear handled events */ - SET_FIELD(NPCX_TECLR(mdl), FIELD(0, 4), events); -} -DECLARE_IRQ(NPCX_IRQ_MFT_1, cec_isr, 4); - -static int cec_send(const uint8_t *msg, uint8_t len) -{ - int i; - - if (cec_tx.len != 0) - return -1; - - cec_tx.len = len; - - CPRINTS("Send CEC:"); - for (i = 0; i < len && i < MAX_CEC_MSG_LEN; i++) - CPRINTS(" 0x%02x", msg[i]); - - memcpy(cec_tx.transfer.buf, msg, len); - - /* Elevate to interrupt context */ - tmr2_start(0); - - return 0; -} - -static enum ec_status hc_cec_write(struct host_cmd_handler_args *args) -{ - const struct ec_params_cec_write *params = args->params; - - if (cec_state == CEC_STATE_DISABLED) - return EC_RES_UNAVAILABLE; - - if (args->params_size == 0 || args->params_size > MAX_CEC_MSG_LEN) - return EC_RES_INVALID_PARAM; - - if (cec_send(params->msg, args->params_size) != 0) - return EC_RES_BUSY; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_CEC_WRITE_MSG, hc_cec_write, EC_VER_MASK(0)); - -static int cec_set_enable(uint8_t enable) -{ - int mdl = NPCX_MFT_MODULE_1; - - if (enable != 0 && enable != 1) - return EC_RES_INVALID_PARAM; - - /* Enabling when already enabled? */ - if (enable && cec_state != CEC_STATE_DISABLED) - return EC_RES_SUCCESS; - - /* Disabling when already disabled? */ - if (!enable && cec_state == CEC_STATE_DISABLED) - return EC_RES_SUCCESS; - - if (enable) { - /* Configure GPIO40/TA1 as capture timer input (TA1) */ - CLEAR_BIT(NPCX_DEVALT(0xC), NPCX_DEVALTC_TA1_SL2); - SET_BIT(NPCX_DEVALT(3), NPCX_DEVALT3_TA1_SL1); - - enter_state(CEC_STATE_IDLE); - - /* - * Capture falling edge of first start - * bit to get things going - */ - tmr_cap_start(CAP_EDGE_FALLING, 0); - - /* Enable timer interrupts */ - SET_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TAIEN); - SET_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TDIEN); - - /* Enable multifunction timer interrupt */ - task_enable_irq(NPCX_IRQ_MFT_1); - - CPRINTF("CEC enabled\n"); - } else { - /* Disable timer interrupts */ - CLEAR_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TAIEN); - CLEAR_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TDIEN); - - tmr2_stop(); - tmr_cap_stop(); - - task_disable_irq(NPCX_IRQ_MFT_1); - - /* Configure GPIO40/TA1 back to GPIO */ - CLEAR_BIT(NPCX_DEVALT(3), NPCX_DEVALT3_TA1_SL1); - SET_BIT(NPCX_DEVALT(0xC), NPCX_DEVALTC_TA1_SL2); - - enter_state(CEC_STATE_DISABLED); - - CPRINTF("CEC disabled\n"); - } - - return EC_RES_SUCCESS; -} - -static int cec_set_logical_addr(uint8_t logical_addr) -{ - if (logical_addr >= CEC_BROADCAST_ADDR && - logical_addr != CEC_UNREGISTERED_ADDR) - return EC_RES_INVALID_PARAM; - - cec_addr = logical_addr; - CPRINTF("CEC address set to: %u\n", cec_addr); - - return EC_RES_SUCCESS; -} - -static enum ec_status hc_cec_set(struct host_cmd_handler_args *args) -{ - const struct ec_params_cec_set *params = args->params; - - switch (params->cmd) { - case CEC_CMD_ENABLE: - return cec_set_enable(params->val); - case CEC_CMD_LOGICAL_ADDRESS: - return cec_set_logical_addr(params->val); - } - - return EC_RES_INVALID_PARAM; -} -DECLARE_HOST_COMMAND(EC_CMD_CEC_SET, hc_cec_set, EC_VER_MASK(0)); - - -static enum ec_status hc_cec_get(struct host_cmd_handler_args *args) -{ - struct ec_response_cec_get *response = args->response; - const struct ec_params_cec_get *params = args->params; - - switch (params->cmd) { - case CEC_CMD_ENABLE: - response->val = cec_state == CEC_STATE_DISABLED ? 0 : 1; - break; - case CEC_CMD_LOGICAL_ADDRESS: - response->val = cec_addr; - break; - default: - return EC_RES_INVALID_PARAM; - } - - args->response_size = sizeof(*response); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_CEC_GET, hc_cec_get, EC_VER_MASK(0)); - -static int cec_get_next_event(uint8_t *out) -{ - uint32_t event_out = deprecated_atomic_read_clear(&cec_events); - - memcpy(out, &event_out, sizeof(event_out)); - - return sizeof(event_out); -} -DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_CEC_EVENT, cec_get_next_event); - -static int cec_get_next_msg(uint8_t *out) -{ - int rv; - uint8_t msg_len, msg[MAX_CEC_MSG_LEN]; - - rv = cec_rx_queue_pop(&cec_rx_queue, msg, &msg_len); - if (rv != 0) - return EC_RES_UNAVAILABLE; - - memcpy(out, msg, msg_len); - - return msg_len; -} -DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_CEC_MESSAGE, cec_get_next_msg); - - -static void cec_init(void) -{ - int mdl = NPCX_MFT_MODULE_1; - - /* APB1 is the clock we base the timers on */ - apb1_freq_div_10k = clock_get_apb1_freq()/10000; - - /* Ensure Multi-Function timer is powered up. */ - CLEAR_BIT(NPCX_PWDWN_CTL(mdl), NPCX_PWDWN_CTL1_MFT1_PD); - - /* Mode 2 - Dual-input capture */ - SET_FIELD(NPCX_TMCTRL(mdl), NPCX_TMCTRL_MDSEL_FIELD, NPCX_MFT_MDSEL_2); - - /* Enable capture TCNT1 into TCRA and preset TCNT1. */ - SET_BIT(NPCX_TMCTRL(mdl), NPCX_TMCTRL_TAEN); - - /* If RO doesn't set it, RW needs to set it explicitly. */ - gpio_set_level(CEC_GPIO_PULL_UP, 1); - - /* Ensure the CEC bus is not pulled low by default on startup. */ - gpio_set_level(CEC_GPIO_OUT, 1); - - CPRINTS("CEC initialized"); -} -DECLARE_HOOK(HOOK_INIT, cec_init, HOOK_PRIO_LAST); - -void cec_task(void *unused) -{ - int rv; - uint32_t events; - - CPRINTF("CEC task starting\n"); - - while (1) { - events = task_wait_event(-1); - if (events & TASK_EVENT_RECEIVED_DATA) { - rv = cec_rx_queue_push(&cec_rx_queue, - cec_rx.transfer.buf, - cec_rx.transfer.byte); - if (rv == EC_ERROR_OVERFLOW) { - /* Queue full, prefer the most recent msg */ - cec_rx_queue_flush(&cec_rx_queue); - rv = cec_rx_queue_push(&cec_rx_queue, - cec_rx.transfer.buf, - cec_rx.transfer.byte); - } - if (rv == EC_SUCCESS) - mkbp_send_event(EC_MKBP_EVENT_CEC_MESSAGE); - } - } -} diff --git a/chip/npcx/cec_bitbang.c b/chip/npcx/cec_bitbang.c new file mode 100644 index 0000000000..2d75edccc2 --- /dev/null +++ b/chip/npcx/cec_bitbang.c @@ -0,0 +1,200 @@ +/* Copyright 2018 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cec.h" +#include "clock_chip.h" +#include "console.h" +#include "driver/cec/bitbang.h" +#include "fan_chip.h" +#include "registers.h" +#include "task.h" +#include "util.h" + +#if !(DEBUG_CEC) +#define CPRINTF(...) +#define CPRINTS(...) +#else +#define CPRINTF(format, args...) cprintf(CC_CEC, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CEC, format, ##args) +#endif + +/* + * Time between interrupt triggered and the next timer was + * set when measuring pulse width + */ +static int cap_delay; + +/* Value charged into the capture timer on last capture start */ +static int cap_charge; + +/* APB1 frequency. Store divided by 10k to avoid some runtime divisions */ +uint32_t apb1_freq_div_10k; + +void cec_tmr_cap_start(enum cec_cap_edge edge, int timeout) +{ + int mdl = NPCX_MFT_MODULE_1; + + if (edge == CEC_CAP_EDGE_NONE) { + /* + * If edge is NONE, disable capture interrupts and wait for a + * timeout only. + */ + CLEAR_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TAIEN); + } else { + /* Select edge to trigger capture on */ + UPDATE_BIT(NPCX_TMCTRL(mdl), NPCX_TMCTRL_TAEDG, + edge == CEC_CAP_EDGE_RISING); + SET_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TAIEN); + } + + /* + * Set capture timeout. If we don't have a timeout, we + * turn the timeout interrupt off and only care about + * the edge change. + */ + if (timeout > 0) { + /* + * Store the time it takes from the interrupts starts to when we + * actually get here. This part of the pulse-width needs to be + * taken into account + */ + cap_delay = (0xffff - NPCX_TCNT1(mdl)); + cap_charge = timeout - cap_delay; + NPCX_TCNT1(mdl) = cap_charge; + SET_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TCIEN); + } else { + CLEAR_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TCIEN); + NPCX_TCNT1(mdl) = 0; + } + + /* Clear out old events */ + SET_BIT(NPCX_TECLR(mdl), NPCX_TECLR_TACLR); + SET_BIT(NPCX_TECLR(mdl), NPCX_TECLR_TCCLR); + NPCX_TCRA(mdl) = 0; + /* Start the capture timer */ + SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C1CSEL_FIELD, 1); +} + +void cec_tmr_cap_stop(void) +{ + int mdl = NPCX_MFT_MODULE_1; + + CLEAR_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TCIEN); + SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C1CSEL_FIELD, 0); +} + +int cec_tmr_cap_get(void) +{ + int mdl = NPCX_MFT_MODULE_1; + + return (cap_charge + cap_delay - NPCX_TCRA(mdl)); +} + +static void tmr2_start(int timeout) +{ + int mdl = NPCX_MFT_MODULE_1; + + NPCX_TCNT2(mdl) = timeout; + SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C2CSEL_FIELD, 1); +} + +static void tmr2_stop(void) +{ + int mdl = NPCX_MFT_MODULE_1; + + SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C2CSEL_FIELD, 0); +} + +static void cec_isr(void) +{ + int mdl = NPCX_MFT_MODULE_1; + uint8_t events; + + /* Retrieve events NPCX_TECTRL_TAXND */ + events = GET_FIELD(NPCX_TECTRL(mdl), FIELD(0, 4)); + + if (events & BIT(NPCX_TECTRL_TAPND)) { + /* Capture event */ + cec_event_cap(); + } else { + /* + * Capture timeout + * We only care about this if the capture event is not + * happening, since we will get both events in the + * edge-trigger case + */ + if (events & BIT(NPCX_TECTRL_TCPND)) + cec_event_timeout(); + } + /* Oneshot timer, a transfer has been initiated from AP */ + if (events & BIT(NPCX_TECTRL_TDPND)) { + tmr2_stop(); + cec_event_tx(); + } + + /* Clear handled events */ + SET_FIELD(NPCX_TECLR(mdl), FIELD(0, 4), events); +} +DECLARE_IRQ(NPCX_IRQ_MFT_1, cec_isr, 4); + +void cec_trigger_send(void) +{ + /* Elevate to interrupt context */ + tmr2_start(0); +} + +void cec_enable_timer(void) +{ + int mdl = NPCX_MFT_MODULE_1; + + /* Configure GPIO40/TA1 as capture timer input (TA1) */ + CLEAR_BIT(NPCX_DEVALT(0xC), NPCX_DEVALTC_TA1_SL2); + SET_BIT(NPCX_DEVALT(3), NPCX_DEVALT3_TA1_SL1); + + /* Enable timer interrupts */ + SET_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TAIEN); + SET_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TDIEN); + + /* Enable multifunction timer interrupt */ + task_enable_irq(NPCX_IRQ_MFT_1); +} + +void cec_disable_timer(void) +{ + int mdl = NPCX_MFT_MODULE_1; + + /* Disable timer interrupts */ + CLEAR_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TAIEN); + CLEAR_BIT(NPCX_TIEN(mdl), NPCX_TIEN_TDIEN); + + tmr2_stop(); + cec_tmr_cap_stop(); + + task_disable_irq(NPCX_IRQ_MFT_1); + + /* Configure GPIO40/TA1 back to GPIO */ + CLEAR_BIT(NPCX_DEVALT(3), NPCX_DEVALT3_TA1_SL1); + SET_BIT(NPCX_DEVALT(0xC), NPCX_DEVALTC_TA1_SL2); + + cap_charge = 0; + cap_delay = 0; +} + +void cec_init_timer(void) +{ + int mdl = NPCX_MFT_MODULE_1; + + /* APB1 is the clock we base the timers on */ + apb1_freq_div_10k = clock_get_apb1_freq() / 10000; + + /* Ensure Multi-Function timer is powered up. */ + CLEAR_BIT(NPCX_PWDWN_CTL(mdl), NPCX_PWDWN_CTL1_MFT1_PD); + + /* Mode 2 - Dual-input capture */ + SET_FIELD(NPCX_TMCTRL(mdl), NPCX_TMCTRL_MDSEL_FIELD, NPCX_MFT_MDSEL_2); + + /* Enable capture TCNT1 into TCRA and preset TCNT1. */ + SET_BIT(NPCX_TMCTRL(mdl), NPCX_TMCTRL_TAEN); +} diff --git a/chip/npcx/cec_bitbang_chip.h b/chip/npcx/cec_bitbang_chip.h new file mode 100644 index 0000000000..91a3cbdd56 --- /dev/null +++ b/chip/npcx/cec_bitbang_chip.h @@ -0,0 +1,19 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_CEC_CHIP_H +#define __CROS_EC_CEC_CHIP_H + +/* APB1 frequency. Store divided by 10k to avoid some runtime divisions */ +extern uint32_t apb1_freq_div_10k; + +/* Time in us to timer clock ticks */ +#define CEC_US_TO_TICKS(t) ((t)*apb1_freq_div_10k / 100) +#if DEBUG_CEC +/* Timer clock ticks to us */ +#define CEC_TICKS_TO_US(ticks) (100 * (ticks) / apb1_freq_div_10k) +#endif + +#endif /* __CROS_EC_CEC_CHIP_H */ diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c index 0f8f737401..8b47d847e8 100644 --- a/chip/npcx/clock.c +++ b/chip/npcx/clock.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -26,10 +26,10 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) -#define WAKE_INTERVAL 61 /* Unit: 61 usec */ -#define IDLE_PARAMS 0x7 /* Support deep idle, instant wake-up */ +#define WAKE_INTERVAL 61 /* Unit: 61 usec */ +#define IDLE_PARAMS 0x7 /* Support deep idle, instant wake-up */ /* Low power idle statistics */ #ifdef CONFIG_LOW_POWER_IDLE @@ -40,7 +40,7 @@ static uint64_t idle_dsleep_time_us; * Fixed amount of time to keep the console in use flag true after boot in * order to give a permanent window in which the low speed clock is not used. */ -#define CONSOLE_IN_USE_ON_BOOT_TIME (15*SECOND) +#define CONSOLE_IN_USE_ON_BOOT_TIME (15 * SECOND) static int console_in_use_timeout_sec = 15; static timestamp_t console_expire_time; #endif @@ -79,7 +79,6 @@ void clock_disable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) /* Set PD bit to 1 */ NPCX_PWDWN_CTL(offset) |= reg_mask; - } /*****************************************************************************/ @@ -100,13 +99,13 @@ void clock_init(void) * unstable for a little which can affect peripheral communication like * eSPI. Skip this if not needed (e.g. RW jump) */ - if (NPCX_HFCGN != HFCGN || NPCX_HFCGML != HFCGML - || NPCX_HFCGMH != HFCGMH) { + if (NPCX_HFCGN != HFCGN || NPCX_HFCGML != HFCGML || + NPCX_HFCGMH != HFCGMH) { /* * Configure frequency multiplier M/N values according to * the requested OSC_CLK (Unit:Hz). */ - NPCX_HFCGN = HFCGN; + NPCX_HFCGN = HFCGN; NPCX_HFCGML = HFCGML; NPCX_HFCGMH = HFCGMH; @@ -119,11 +118,11 @@ void clock_init(void) /* Set all clock prescalers of core and peripherals. */ #if defined(CHIP_FAMILY_NPCX5) - NPCX_HFCGP = (FPRED << 4); + NPCX_HFCGP = (FPRED << 4); NPCX_HFCBCD = (NPCX_HFCBCD & 0xF0) | (APB1DIV | (APB2DIV << 2)); #elif NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 - NPCX_HFCGP = ((FPRED << 4) | AHB6DIV); - NPCX_HFCBCD = (FIUDIV << 4); + NPCX_HFCGP = ((FPRED << 4) | AHB6DIV); + NPCX_HFCBCD = (FIUDIV << 4); NPCX_HFCBCD1 = (APB1DIV | (APB2DIV << 4)); #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 NPCX_HFCBCD2 = (APB3DIV | (APB4DIV << 4)); @@ -143,7 +142,7 @@ void clock_init(void) void clock_turbo(void) { /* Configure Frequency multiplier values to 50MHz */ - NPCX_HFCGN = 0x02; + NPCX_HFCGN = 0x02; NPCX_HFCGML = 0xEC; NPCX_HFCGMH = 0x0B; @@ -163,14 +162,28 @@ void clock_turbo(void) */ NPCX_HFCBCD = NPCX_HFCBCD & 0xF3; } + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} + #elif NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 void clock_turbo(void) { - /* +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 + /* For NPCX9: + * Increase CORE_CLK (CPU) as the same as OSC_CLK. Since + * CORE_CLK > 66MHz, we also need to set FIUDIV as 1 but + * can keep AHB6DIV to 0. + */ + NPCX_HFCGP = 0x00; +#else + /* For NPCX7: * Increase CORE_CLK (CPU) as the same as OSC_CLK. Since * CORE_CLK > 66MHz, we also need to set AHB6DIV and FIUDIV as 1. */ NPCX_HFCGP = 0x01; +#endif NPCX_HFCBCD = BIT(4); } @@ -181,7 +194,7 @@ void clock_normal(void) NPCX_HFCBCD = (FIUDIV << 4); } -void clock_enable_module(enum module_id module, int enable) +test_mockable void clock_enable_module(enum module_id module, int enable) { /* Assume we have a single task using MODULE_FAST_CPU */ if (module == MODULE_FAST_CPU) { @@ -192,6 +205,12 @@ void clock_enable_module(enum module_id module, int enable) } } +#else + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ +} + #endif /** @@ -246,7 +265,8 @@ int clock_get_apb3_freq(void) void clock_wait_cycles(uint32_t cycles) { asm volatile("1: subs %0, #1\n" - " bne 1b\n" : "+r"(cycles)); + " bne 1b\n" + : "+r"(cycles)); } #ifdef CONFIG_LOW_POWER_IDLE @@ -369,12 +389,11 @@ void __idle(void) * more detail. * Workaround: Apply the same bypass of idle. */ - asm ("push {r0-r5}\n" - "wfi\n" - "ldm %0, {r0-r5}\n" - "pop {r0-r5}\n" - "isb\n" :: "r" (0x100A8000) - ); + asm("push {r0-r5}\n" + "wfi\n" + "ldm %0, {r0-r5}\n" + "pop {r0-r5}\n" + "isb\n" ::"r"(0x100A8000)); /* Get time delay cause of deep idle */ next_evt_us = __hw_clock_get_sleep_time(evt_count); @@ -413,7 +432,7 @@ void __idle(void) * CSAE bit is set. Please notice this symptom only * occurs at npcx5. */ -#if defined(CHIP_FAMILY_NPCX5) && defined(CONFIG_HOSTCMD_ESPI) +#if defined(CHIP_FAMILY_NPCX5) && defined(CONFIG_HOST_INTERFACE_ESPI) /* Enable Host access wakeup */ SET_BIT(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6); #endif @@ -422,12 +441,11 @@ void __idle(void) * TODO (ML): Workaround method for wfi issue. * Please see task.c for more detail */ - asm ("push {r0-r5}\n" - "wfi\n" - "ldm %0, {r0-r5}\n" - "pop {r0-r5}\n" - "isb\n" :: "r" (0x100A8000) - ); + asm("push {r0-r5}\n" + "wfi\n" + "ldm %0, {r0-r5}\n" + "pop {r0-r5}\n" + "isb\n" ::"r"(0x100A8000)); } /* @@ -439,30 +457,28 @@ void __idle(void) } #endif /* CONFIG_LOW_POWER_IDLE */ - #ifdef CONFIG_LOW_POWER_IDLE /** * Print low power idle statistics */ -static int command_idle_stats(int argc, char **argv) +static int command_idle_stats(int argc, const char **argv) { timestamp_t ts = get_time(); ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); ccprintf("Time spent in deep-sleep: %.6llds\n", - idle_dsleep_time_us); + idle_dsleep_time_us); ccprintf("Total time on: %.6llds\n", ts.val); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, - "", - "Print last idle stats"); +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", + "Print last idle stats"); /** * Configure deep sleep clock settings. */ -static int command_dsleep(int argc, char **argv) +static int command_dsleep(int argc, const char **argv) { int v; @@ -490,19 +506,18 @@ static int command_dsleep(int argc, char **argv) } } - ccprintf("Sleep mask: %08x\n", sleep_mask); + ccprintf("Sleep mask: %08x\n", (int)sleep_mask); ccprintf("Console in use timeout: %d sec\n", - console_in_use_timeout_sec); + console_in_use_timeout_sec); ccprintf("PMCSR register: 0x%02x\n", NPCX_PMCSR); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(dsleep, command_dsleep, - "[ on | off | sec]", - "Deep sleep clock settings:\nUse 'on' to force deep " - "sleep not to use low speed clock.\nUse 'off' to " - "allow deep sleep to auto-select using the low speed " - "clock.\n" - "Give a timeout value for the console in use timeout.\n" - "See also 'sleepmask'."); +DECLARE_CONSOLE_COMMAND(dsleep, command_dsleep, "[ on | off | sec]", + "Deep sleep clock settings:\nUse 'on' to force deep " + "sleep not to use low speed clock.\nUse 'off' to " + "allow deep sleep to auto-select using the low speed " + "clock.\n" + "Give a timeout value for the console in use timeout.\n" + "See also 'sleepmask'."); #endif /* CONFIG_LOW_POWER_IDLE */ diff --git a/chip/npcx/clock_chip.h b/chip/npcx/clock_chip.h index 702b55c52a..c105194fdf 100644 --- a/chip/npcx/clock_chip.h +++ b/chip/npcx/clock_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -95,40 +95,40 @@ * OSC_CLK (Unit:Hz). */ #if (OSC_CLK > 80000000) -#define HFCGN 0x82 /* Set XF_RANGE as 1 if OSC_CLK >= 80MHz */ +#define HFCGN 0x82 /* Set XF_RANGE as 1 if OSC_CLK >= 80MHz */ #else -#define HFCGN 0x02 +#define HFCGN 0x02 #endif -#if (OSC_CLK == 100000000) -#define HFCGMH 0x0B -#define HFCGML 0xEC +#if (OSC_CLK == 100000000) +#define HFCGMH 0x0B +#define HFCGML 0xEC #elif (OSC_CLK == 90000000) -#define HFCGMH 0x0A -#define HFCGML 0xBA +#define HFCGMH 0x0A +#define HFCGML 0xBA #elif (OSC_CLK == 80000000) -#define HFCGMH 0x09 -#define HFCGML 0x89 +#define HFCGMH 0x09 +#define HFCGML 0x89 #elif (OSC_CLK == 66000000) -#define HFCGMH 0x0F -#define HFCGML 0xBC +#define HFCGMH 0x0F +#define HFCGML 0xBC #elif (OSC_CLK == 50000000) -#define HFCGMH 0x0B -#define HFCGML 0xEC +#define HFCGMH 0x0B +#define HFCGML 0xEC #elif (OSC_CLK == 48000000) -#define HFCGMH 0x0B -#define HFCGML 0x72 +#define HFCGMH 0x0B +#define HFCGML 0x72 #elif (OSC_CLK == 40000000) -#define HFCGMH 0x09 -#define HFCGML 0x89 +#define HFCGMH 0x09 +#define HFCGML 0x89 #elif (OSC_CLK == 33000000) -#define HFCGMH 0x07 -#define HFCGML 0xDE +#define HFCGMH 0x07 +#define HFCGML 0xDE #elif (OSC_CLK == 30000000) -#define HFCGMH 0x07 -#define HFCGML 0x27 +#define HFCGMH 0x07 +#define HFCGML 0x27 #elif (OSC_CLK == 26000000) -#define HFCGMH 0x06 -#define HFCGML 0x33 +#define HFCGMH 0x06 +#define HFCGML 0x33 #else #error "Unsupported OSC_CLK Frequency" #endif diff --git a/chip/npcx/config_chip-npcx5.h b/chip/npcx/config_chip-npcx5.h index 331b5e5474..53713b2dfb 100644 --- a/chip/npcx/config_chip-npcx5.h +++ b/chip/npcx/config_chip-npcx5.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,10 +14,10 @@ */ /* Chip ID for all variants */ -#define NPCX585G_CHIP_ID 0x12 -#define NPCX575G_CHIP_ID 0x13 -#define NPCX586G_CHIP_ID 0x16 -#define NPCX576G_CHIP_ID 0x17 +#define NPCX585G_CHIP_ID 0x12 +#define NPCX575G_CHIP_ID 0x13 +#define NPCX586G_CHIP_ID 0x16 +#define NPCX576G_CHIP_ID 0x17 /*****************************************************************************/ /* Hardware features */ @@ -25,24 +25,30 @@ /* Number of UART modules. */ #define UART_MODULE_COUNT 1 +/* + * For NPCX5, PS2_3 pins also support other alternate functions (e.g., TA2). + * PS2_3 should be Explicit defined. + */ +#undef NPCX_PS2_MODULE_3 + /* * Number of I2C controllers. Controller 0 has 2 ports, so the chip has one * additional port. */ #define CONFIG_I2C_MULTI_PORT_CONTROLLER /* Number of I2C controllers */ -#define I2C_CONTROLLER_COUNT 4 +#define I2C_CONTROLLER_COUNT 4 /* Number of I2C ports */ -#define I2C_PORT_COUNT 5 +#define I2C_PORT_COUNT 5 /*****************************************************************************/ /* Memory mapping */ -#define NPCX_BTRAM_SIZE 0x800 /* 2KB data ram used by booter. */ -#define CONFIG_RAM_BASE 0x200C0000 /* memory address of data ram */ -#define CONFIG_DATA_RAM_SIZE 0x00008000 /* Size of data RAM */ -#define CONFIG_RAM_SIZE (CONFIG_DATA_RAM_SIZE - NPCX_BTRAM_SIZE) -#define CONFIG_LPRAM_BASE 0x40001600 /* memory address of lpwr ram */ -#define CONFIG_LPRAM_SIZE 0x00000620 /* 1568B low power ram */ +#define NPCX_BTRAM_SIZE 0x800 /* 2KB data ram used by booter. */ +#define CONFIG_RAM_BASE 0x200C0000 /* memory address of data ram */ +#define CONFIG_DATA_RAM_SIZE 0x00008000 /* Size of data RAM */ +#define CONFIG_RAM_SIZE (CONFIG_DATA_RAM_SIZE - NPCX_BTRAM_SIZE) +#define CONFIG_LPRAM_BASE 0x40001600 /* memory address of lpwr ram */ +#define CONFIG_LPRAM_SIZE 0x00000620 /* 1568B low power ram */ /* Use chip variant to specify the size and start address of program memory */ #if defined(CHIP_VARIANT_NPCX5M5G) diff --git a/chip/npcx/config_chip-npcx7.h b/chip/npcx/config_chip-npcx7.h index 5919f69af8..e44aebe6cf 100644 --- a/chip/npcx/config_chip-npcx7.h +++ b/chip/npcx/config_chip-npcx7.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,26 +16,27 @@ */ /* Chip ID for all variants */ -#define NPCX787G_CHIP_ID 0x1F -#define NPCX796F_A_B_CHIP_ID 0x21 -#define NPCX796F_C_CHIP_ID 0x29 -#define NPCX797F_C_CHIP_ID 0x20 -#define NPCX797W_B_CHIP_ID 0x24 -#define NPCX797W_C_CHIP_ID 0x2C +#define NPCX787G_CHIP_ID 0x1F +#define NPCX796F_A_B_CHIP_ID 0x21 +#define NPCX796F_C_CHIP_ID 0x29 +#define NPCX797F_C_CHIP_ID 0x20 +#define NPCX797W_B_CHIP_ID 0x24 +#define NPCX797W_C_CHIP_ID 0x2C /*****************************************************************************/ /* Hardware features */ /* The optional hardware features depend on chip variant */ -#if defined(CHIP_VARIANT_NPCX7M6F) || defined(CHIP_VARIANT_NPCX7M6FB) || \ +#if defined(CHIP_VARIANT_NPCX7M6F) || defined(CHIP_VARIANT_NPCX7M6FB) || \ defined(CHIP_VARIANT_NPCX7M6FC) || defined(CHIP_VARIANT_NPCX7M7FC) || \ defined(CHIP_VARIANT_NPCX7M7WB) || defined(CHIP_VARIANT_NPCX7M7WC) #define NPCX_INT_FLASH_SUPPORT /* Internal flash support */ -#define NPCX_PSL_MODE_SUPPORT /* Power switch logic mode for ultra-low power */ +#define NPCX_PSL_MODE_SUPPORT /* Power switch logic mode for ultra-low power \ + */ #define NPCX_EXT32K_OSC_SUPPORT /* External 32KHz crytal osc. input support */ #endif -#if defined(CHIP_VARIANT_NPCX7M6FB) || defined(CHIP_VARIANT_NPCX7M6FC) || \ +#if defined(CHIP_VARIANT_NPCX7M6FB) || defined(CHIP_VARIANT_NPCX7M6FC) || \ defined(CHIP_VARIANT_NPCX7M7FC) || defined(CHIP_VARIANT_NPCX7M7WB) || \ defined(CHIP_VARIANT_NPCX7M7WC) #define NPCX_UART_FIFO_SUPPORT @@ -43,8 +44,24 @@ #define NPCX_SECOND_UART #define UART_MODULE_COUNT 2 +/* + * For NPCX7, PS2_2 & PS2_3 pins also support other alternate functions + * (e.g., ADC5, ADC6, TA2). PS2_2 & PS2_3 should be Explicit defined. + */ +#undef NPCX_PS2_MODULE_2 +#undef NPCX_PS2_MODULE_3 + /* 64-bit timer support */ #define NPCX_ITIM64_SUPPORT + +/* + * Workaound the issue 3.10 in the NPCX99nF errata rev1.2 + * Enabling an eSPI channel (e.g. Peripheral Channel, Virtual Wire Channel, etc. + * ) during an eSPI transaction might (with low probability) cause the eSPI_SIF + * module to transition to a wrong state and therefore response with FATAL_ERROR + * on an incoming transaction. + */ +#define NPCX_ESPI_BYPASS_CH_ENABLE_FATAL_ERROR #else #define UART_MODULE_COUNT 1 #endif @@ -74,68 +91,68 @@ /*****************************************************************************/ /* Memory mapping */ -#define NPCX_BTRAM_SIZE 0x800 /* 2KB data ram used by booter. */ +#define NPCX_BTRAM_SIZE 0x800 /* 2KB data ram used by booter. */ #define NPCX_RAM_SIZE (CONFIG_DATA_RAM_SIZE + NPCX_PROGRAM_MEMORY_SIZE) #if defined(CHIP_VARIANT_NPCX7M6F) || defined(CHIP_VARIANT_NPCX7M6FB) || \ defined(CHIP_VARIANT_NPCX7M6FC) || defined(CHIP_VARIANT_NPCX7M6G) - /* 192KB RAM for FW code */ -# define NPCX_PROGRAM_MEMORY_SIZE (192 * 1024) - /* program memory base address for Code RAM (0x100C0000 - 192KB) */ -# define CONFIG_PROGRAM_MEMORY_BASE 0x10090000 -# define CONFIG_RAM_BASE 0x200C0000 /* memory address of data ram */ - /* 62 KB data RAM + 2 KB BT RAM size */ -# define CONFIG_DATA_RAM_SIZE 0x00010000 +/* 192KB RAM for FW code */ +#define NPCX_PROGRAM_MEMORY_SIZE (192 * 1024) +/* program memory base address for Code RAM (0x100C0000 - 192KB) */ +#define CONFIG_PROGRAM_MEMORY_BASE 0x10090000 +#define CONFIG_RAM_BASE 0x200C0000 /* memory address of data ram */ +/* 62 KB data RAM + 2 KB BT RAM size */ +#define CONFIG_DATA_RAM_SIZE 0x00010000 #elif defined(CHIP_VARIANT_NPCX7M7WB) - /* 256KB RAM for FW code */ -# define NPCX_PROGRAM_MEMORY_SIZE (256 * 1024) - /* program memory base address for Code RAM (0x100B0000 - 256KB) */ -# define CONFIG_PROGRAM_MEMORY_BASE 0x10070000 -# define CONFIG_RAM_BASE 0x200B0000 /* memory address of data ram */ - /* 126 KB data RAM + 2 KB BT RAM size */ -# define CONFIG_DATA_RAM_SIZE 0x00020000 +/* 256KB RAM for FW code */ +#define NPCX_PROGRAM_MEMORY_SIZE (256 * 1024) +/* program memory base address for Code RAM (0x100B0000 - 256KB) */ +#define CONFIG_PROGRAM_MEMORY_BASE 0x10070000 +#define CONFIG_RAM_BASE 0x200B0000 /* memory address of data ram */ +/* 126 KB data RAM + 2 KB BT RAM size */ +#define CONFIG_DATA_RAM_SIZE 0x00020000 #elif defined(CHIP_VARIANT_NPCX7M7FC) || defined(CHIP_VARIANT_NPCX7M7WC) - /* - * Code RAM is normally assumed to be same as image size, but since - * we exclude 4k from the image (see NPCX_PROGRAM_MEMORY_SIZE) we - * need to explicitly configure it. This is the actual size of code - * RAM on-chip. - */ -# define CONFIG_CODE_RAM_SIZE (256 * 1024) - /* - * In npcx797wc and npcx797fc, the code RAM size is limited by the - * internal flash size (i.e. 512 KB/2=256 KB.) The driver has to - * re-organize the memory to: - * 1. the overall memory (RAM) layout is re-organized against the - * datasheet: - * In datasheet: 320 KB code RAM + 64 KB data RAM - * After re-organization: 256 KB code RAM + 128 KB data RAM. - * 2. 256KB program RAM, but only 512K of Flash (vs 1M for the - * -WB). After the boot header is added, a 256K image would be - * too large to fit in either RO or RW sections of Flash (each - * of which is half of it). Because other code assumes that - * image size is a multiple of Flash erase granularity, we - * sacrifice a whole sector. - */ -# define NPCX_PROGRAM_MEMORY_SIZE (CONFIG_CODE_RAM_SIZE - 0x1000) - /* program memory base address for Code RAM (0x100B0000 - 256KB) */ -# define CONFIG_PROGRAM_MEMORY_BASE 0x10070000 -# define CONFIG_RAM_BASE 0x200B0000 /* memory address of data ram */ - /* 126 KB data RAM + 2 KB BT RAM size */ -# define CONFIG_DATA_RAM_SIZE 0x00020000 - - /* - * Override default NPCX_RAM_SIZE because NPCX_PROGRAM_MEMORY_SIZE - * is not the actual size of code RAM. - */ -# undef NPCX_RAM_SIZE -# define NPCX_RAM_SIZE (CONFIG_DATA_RAM_SIZE + CONFIG_CODE_RAM_SIZE) +/* + * Code RAM is normally assumed to be same as image size, but since + * we exclude 4k from the image (see NPCX_PROGRAM_MEMORY_SIZE) we + * need to explicitly configure it. This is the actual size of code + * RAM on-chip. + */ +#define CONFIG_CODE_RAM_SIZE (256 * 1024) +/* + * In npcx797wc and npcx797fc, the code RAM size is limited by the + * internal flash size (i.e. 512 KB/2=256 KB.) The driver has to + * re-organize the memory to: + * 1. the overall memory (RAM) layout is re-organized against the + * datasheet: + * In datasheet: 320 KB code RAM + 64 KB data RAM + * After re-organization: 256 KB code RAM + 128 KB data RAM. + * 2. 256KB program RAM, but only 512K of Flash (vs 1M for the + * -WB). After the boot header is added, a 256K image would be + * too large to fit in either RO or RW sections of Flash (each + * of which is half of it). Because other code assumes that + * image size is a multiple of Flash erase granularity, we + * sacrifice a whole sector. + */ +#define NPCX_PROGRAM_MEMORY_SIZE (CONFIG_CODE_RAM_SIZE - 0x1000) +/* program memory base address for Code RAM (0x100B0000 - 256KB) */ +#define CONFIG_PROGRAM_MEMORY_BASE 0x10070000 +#define CONFIG_RAM_BASE 0x200B0000 /* memory address of data ram */ +/* 126 KB data RAM + 2 KB BT RAM size */ +#define CONFIG_DATA_RAM_SIZE 0x00020000 + +/* + * Override default NPCX_RAM_SIZE because NPCX_PROGRAM_MEMORY_SIZE + * is not the actual size of code RAM. + */ +#undef NPCX_RAM_SIZE +#define NPCX_RAM_SIZE (CONFIG_DATA_RAM_SIZE + CONFIG_CODE_RAM_SIZE) #else -# error "Unsupported chip variant" +#error "Unsupported chip variant" #endif -#define CONFIG_RAM_SIZE (CONFIG_DATA_RAM_SIZE - NPCX_BTRAM_SIZE) +#define CONFIG_RAM_SIZE (CONFIG_DATA_RAM_SIZE - NPCX_BTRAM_SIZE) /* no low power ram in npcx7 series */ #endif /* __CROS_EC_CONFIG_CHIP_NPCX7_H */ diff --git a/chip/npcx/config_chip-npcx9.h b/chip/npcx/config_chip-npcx9.h index 9f7b0f52d0..137611007e 100644 --- a/chip/npcx/config_chip-npcx9.h +++ b/chip/npcx/config_chip-npcx9.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,8 +16,8 @@ */ /* Chip ID for all variants */ -#define NPCX996F_CHIP_ID 0x21 -#define NPCX993F_CHIP_ID 0x25 +#define NPCX996F_CHIP_ID 0x21 +#define NPCX993F_CHIP_ID 0x25 /*****************************************************************************/ /* Hardware features */ @@ -25,13 +25,21 @@ #define NPCX_EXT32K_OSC_SUPPORT /* External 32KHz crytal osc. input support */ #define NPCX_INT_FLASH_SUPPORT /* Internal flash support */ #define NPCX_LCT_SUPPORT /* Long Countdown Timer support */ -#define NPCX_PSL_MODE_SUPPORT /* Power switch logic mode for ultra-low power */ +#define NPCX_PSL_MODE_SUPPORT /* Power switch logic mode for ultra-low power \ + */ #define NPCX_UART_FIFO_SUPPORT /* Number of UART modules. */ #define NPCX_SECOND_UART #define UART_MODULE_COUNT 2 +/* + * For NPCX9, PS2_2 & PS2_3 pins also support other alternate functions + * (e.g., ADC5, ADC6, TA2). PS2_2 & PS2_3 should be Explicit defined. + */ +#undef NPCX_PS2_MODULE_2 +#undef NPCX_PS2_MODULE_3 + /* * Number of I2C controllers. Controller 5/6 has 2 ports, so the chip has * two additional ports. @@ -48,61 +56,86 @@ /* PSL_OUT optional configuration */ /* Set PSL_OUT mode to pulse mode */ -#define NPCX_PSL_CFG_PSL_OUT_PULSE BIT(0) +#define NPCX_PSL_CFG_PSL_OUT_PULSE BIT(0) /* set PSL_OUT to open-drain */ -#define NPCX_PSL_CFG_PSL_OUT_OD BIT(1) -#define CONFIG_HIBERNATE_PSL_OUT_FLAGS 0 +#define NPCX_PSL_CFG_PSL_OUT_OD BIT(1) +#define CONFIG_HIBERNATE_PSL_OUT_FLAGS 0 +/* + * Workaound the issue 3.10 in the NPCX99nF errata rev1.2 + * Enabling an eSPI channel (e.g. Peripheral Channel, Virtual Wire Channel, etc. + * ) during an eSPI transaction might (with low probability) cause the eSPI_SIF + * module to transition to a wrong state and therefore response with FATAL_ERROR + * on an incoming transaction. + */ +#define NPCX_ESPI_BYPASS_CH_ENABLE_FATAL_ERROR -#define CONFIG_WORKAROUND_FLASH_DOWNLOAD_API /*****************************************************************************/ /* Memory mapping */ -#ifdef CONFIG_WORKAROUND_FLASH_DOWNLOAD_API -#define CONFIG_LPRAM_BASE 0x40001400 /* memory address of lpwr ram */ -#define CONFIG_LPRAM_SIZE 0x00000620 /* 1568B low power ram */ -#endif #define NPCX_RAM_SIZE (CONFIG_DATA_RAM_SIZE + NPCX_PROGRAM_MEMORY_SIZE) #if defined(CHIP_VARIANT_NPCX9M3F) - /* - * 256KB program RAM, but only 512K of Flash. After the boot header is - * added, a 256K image would be too large to fit in either RO or RW - * sections of Flash (each of which is half of it). Because other code - * assumes that image size is a multiple of Flash erase granularity, we - * sacrifice a whole sector. - */ -# define NPCX_PROGRAM_MEMORY_SIZE (256 * 1024 - 0x1000) - /* program memory base address for Code RAM (0x100C0000 - 256KB) */ -# define CONFIG_PROGRAM_MEMORY_BASE 0x10080000 -# define CONFIG_RAM_BASE 0x200C0000 /* memory address of data ram */ - /* Two blocks of data RAM - total size is 64KB */ -# define CONFIG_DATA_RAM_SIZE 0x00010000 -# define CONFIG_RAM_SIZE CONFIG_DATA_RAM_SIZE - - /* Override default NPCX_RAM_SIZE because we're excluding a block. */ -# undef NPCX_RAM_SIZE -# define NPCX_RAM_SIZE (CONFIG_DATA_RAM_SIZE + \ - NPCX_PROGRAM_MEMORY_SIZE + 0x1000) +/* + * 256KB program RAM, but only 512K of Flash. After the boot header is + * added, a 256K image would be too large to fit in either RO or RW + * sections of Flash (each of which is half of it). Because other code + * assumes that image size is a multiple of Flash erase granularity, we + * sacrifice a whole sector. + */ +#define NPCX_PROGRAM_MEMORY_SIZE (256 * 1024 - 0x1000) +/* program memory base address for Code RAM (0x100C0000 - 256KB) */ +#define CONFIG_PROGRAM_MEMORY_BASE 0x10080000 +#define CONFIG_RAM_BASE 0x200C0000 /* memory address of data ram */ +/* Two blocks of data RAM - total size is 64KB */ +#define CONFIG_DATA_RAM_SIZE 0x00010000 +#define CONFIG_RAM_SIZE CONFIG_DATA_RAM_SIZE + +/* Override default NPCX_RAM_SIZE because we're excluding a block. */ +#undef NPCX_RAM_SIZE +#define NPCX_RAM_SIZE (CONFIG_DATA_RAM_SIZE + NPCX_PROGRAM_MEMORY_SIZE + 0x1000) #elif defined(CHIP_VARIANT_NPCX9M6F) - /* 192KB RAM for FW code */ -# define NPCX_PROGRAM_MEMORY_SIZE (192 * 1024) - /* program memory base address for Code RAM (0x100C0000 - 192KB) */ -# define CONFIG_PROGRAM_MEMORY_BASE 0x10090000 -# define CONFIG_RAM_BASE 0x200C0000 /* memory address of data ram */ - /* Two blocks of data RAM - total size is 64KB */ -# define CONFIG_DATA_RAM_SIZE 0x00010000 -# define CONFIG_RAM_SIZE CONFIG_DATA_RAM_SIZE +/* 192KB RAM for FW code */ +#define NPCX_PROGRAM_MEMORY_SIZE (192 * 1024) +/* program memory base address for Code RAM (0x100C0000 - 192KB) */ +#define CONFIG_PROGRAM_MEMORY_BASE 0x10090000 +#define CONFIG_RAM_BASE 0x200C0000 /* memory address of data ram */ +/* Two blocks of data RAM - total size is 64KB */ +#define CONFIG_DATA_RAM_SIZE 0x00010000 +#define CONFIG_RAM_SIZE CONFIG_DATA_RAM_SIZE +#elif defined(CHIP_VARIANT_NPCX9M8S) +/* + * 416KB program RAM, 1MB of Flash. + */ +#define NPCX_PROGRAM_MEMORY_SIZE (416 * 1024) +/* program memory base address for Code RAM (0x100C0000 - 416KB) */ +#define CONFIG_PROGRAM_MEMORY_BASE 0x10058000 +#define CONFIG_RAM_BASE 0x200C0000 /* memory address of data ram */ +/* + * Three blocks of data RAM - reserve 4KB for ROM utilities and + *data ram size is 92KB + */ +#define CONFIG_DATA_RAM_SIZE (96 * 1024 - 0x1000) +#define CONFIG_RAM_SIZE CONFIG_DATA_RAM_SIZE + +/* Override default NPCX_RAM_SIZE because we're excluding a block. */ +#undef NPCX_RAM_SIZE +#define NPCX_RAM_SIZE (CONFIG_DATA_RAM_SIZE + NPCX_PROGRAM_MEMORY_SIZE + 0x1000) #else -# error "Unsupported chip variant" +#error "Unsupported chip variant" #endif /* Internal spi-flash setting */ -#define CONFIG_SPI_FLASH_PORT 0 -#define CONFIG_SPI_FLASH #define CONFIG_SPI_FLASH_REGS +#if defined(CHIP_VARIANT_NPCX9M8S) +#define CONFIG_SPI_FLASH_W25Q80 /* Internal spi flash type */ +#define CONFIG_FLASH_SIZE_BYTES 0x00100000 /* 1 MB internal spi flash */ +#else #define CONFIG_SPI_FLASH_W25Q40 /* Internal spi flash type */ -#define CONFIG_FLASH_SIZE 0x00080000 /* 512 KB internal spi flash */ +#define CONFIG_FLASH_SIZE_BYTES 0x00080000 /* 512 KB internal spi flash */ +#endif +/* All NPCX9 variants support SHA256 accelerator. */ +#define CONFIG_SHA256_HW_ACCELERATE #endif /* __CROS_EC_CONFIG_CHIP_NPCX9_H */ diff --git a/chip/npcx/config_chip.h b/chip/npcx/config_chip.h index cee339206c..d0bfe0a767 100644 --- a/chip/npcx/config_chip.h +++ b/chip/npcx/config_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,20 +13,20 @@ * Set the chip family version to 4 digits to keep the flexibility in case * we need the minor version for chip variants in a family. */ -#define NPCX_FAMILY_NPCX5 5000 -#define NPCX_FAMILY_NPCX7 7000 -#define NPCX_FAMILY_NPCX9 9000 +#define NPCX_FAMILY_NPCX5 5000 +#define NPCX_FAMILY_NPCX7 7000 +#define NPCX_FAMILY_NPCX9 9000 /* Features depend on chip family */ #if defined(CHIP_FAMILY_NPCX5) #include "config_chip-npcx5.h" -#define NPCX_FAMILY_VERSION NPCX_FAMILY_NPCX5 +#define NPCX_FAMILY_VERSION NPCX_FAMILY_NPCX5 #elif defined(CHIP_FAMILY_NPCX7) #include "config_chip-npcx7.h" -#define NPCX_FAMILY_VERSION NPCX_FAMILY_NPCX7 +#define NPCX_FAMILY_VERSION NPCX_FAMILY_NPCX7 #elif defined(CHIP_FAMILY_NPCX9) #include "config_chip-npcx9.h" -#define NPCX_FAMILY_VERSION NPCX_FAMILY_NPCX9 +#define NPCX_FAMILY_VERSION NPCX_FAMILY_NPCX9 #else #error "Unsupported chip family" #endif @@ -46,27 +46,27 @@ * Notice instant wake-up from deep-idle cannot exceed 200 ms */ #define HOOK_TICK_INTERVAL_MS 200 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) +#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) /* System stack size */ -#define CONFIG_STACK_SIZE 1024 +#define CONFIG_STACK_SIZE 1024 /* non-standard task stack sizes */ -#define IDLE_TASK_STACK_SIZE 672 -#define LARGER_TASK_STACK_SIZE 800 -#define VENTI_TASK_STACK_SIZE 928 -#define ULTRA_TASK_STACK_SIZE 1056 -#define TRENTA_TASK_STACK_SIZE 1184 +#define IDLE_TASK_STACK_SIZE 672 +#define LARGER_TASK_STACK_SIZE 800 +#define VENTI_TASK_STACK_SIZE 928 +#define ULTRA_TASK_STACK_SIZE 1056 +#define TRENTA_TASK_STACK_SIZE 1184 -#define CHARGER_TASK_STACK_SIZE 800 -#define HOOKS_TASK_STACK_SIZE 800 -#define CONSOLE_TASK_STACK_SIZE 800 +#define CHARGER_TASK_STACK_SIZE 800 +#define HOOKS_TASK_STACK_SIZE 800 +#define CONSOLE_TASK_STACK_SIZE 800 /* Default task stack size */ -#define TASK_STACK_SIZE 672 +#define TASK_STACK_SIZE 672 /* Address of RAM log used by Booter */ -#define ADDR_BOOT_RAMLOG 0x100C7FC0 +#define ADDR_BOOT_RAMLOG 0x100C7FC0 #include "config_flash_layout.h" @@ -79,9 +79,13 @@ /* Chip needs to do custom pre-init */ #define CONFIG_CHIP_PRE_INIT /* Default use UART1 as console */ -#define CONFIG_CONSOLE_UART 0 +#define CONFIG_CONSOLE_UART 0 #define GPIO_PIN(port, index) GPIO_##port, BIT(index) #define GPIO_PIN_MASK(p, m) .port = GPIO_##p, .mask = (m) -#endif /* __CROS_EC_CONFIG_CHIP_H */ +#if !defined(HAS_TASK_KEYSCAN) +#define NPCX_SELECT_KSI_TO_GPIO +#endif + +#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/npcx/config_flash_layout.h b/chip/npcx/config_flash_layout.h index c45f4c53fd..ca2e909031 100644 --- a/chip/npcx/config_flash_layout.h +++ b/chip/npcx/config_flash_layout.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,56 +18,61 @@ #define CONFIG_MAPPED_STORAGE /* Storage is memory-mapped, but program runs from SRAM */ #define CONFIG_MAPPED_STORAGE_BASE 0x64000000 -#undef CONFIG_FLASH_PSTATE +#undef CONFIG_FLASH_PSTATE #if defined(CHIP_VARIANT_NPCX5M5G) -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 #define CONFIG_EC_PROTECTED_STORAGE_SIZE 0x20000 -#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x20000 -#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x20000 +#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x20000 +#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x20000 #elif defined(CHIP_VARIANT_NPCX5M6G) -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 #define CONFIG_EC_PROTECTED_STORAGE_SIZE 0x40000 -#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x40000 -#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x40000 -#elif defined(CHIP_VARIANT_NPCX7M6F) || defined(CHIP_VARIANT_NPCX7M6FB) || \ +#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x40000 +#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x40000 +#elif defined(CHIP_VARIANT_NPCX7M6F) || defined(CHIP_VARIANT_NPCX7M6FB) || \ defined(CHIP_VARIANT_NPCX7M6FC) || defined(CHIP_VARIANT_NPCX7M6G) || \ defined(CHIP_VARIANT_NPCX7M7FC) || defined(CHIP_VARIANT_NPCX7M7WC) -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 #define CONFIG_EC_PROTECTED_STORAGE_SIZE 0x40000 -#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x40000 -#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x40000 +#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x40000 +#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x40000 #elif defined(CHIP_VARIANT_NPCX7M7WB) -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 #define CONFIG_EC_PROTECTED_STORAGE_SIZE 0x80000 -#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x80000 -#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x80000 +#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x80000 +#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x80000 #elif defined(CHIP_VARIANT_NPCX9M3F) || defined(CHIP_VARIANT_NPCX9M6F) -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 #define CONFIG_EC_PROTECTED_STORAGE_SIZE 0x40000 -#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x40000 -#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x40000 +#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x40000 +#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x40000 +#elif defined(CHIP_VARIANT_NPCX9M8S) +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_SIZE 0x80000 +#define CONFIG_EC_WRITABLE_STORAGE_OFF 0x80000 +#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0x80000 #else #error "Unsupported chip variant" #endif /* Header support which is used by booter to copy FW from flash to code ram */ #define NPCX_RO_HEADER -#define CONFIG_RO_HDR_MEM_OFF 0x0 -#define CONFIG_RO_HDR_SIZE 0x40 +#define CONFIG_RO_HDR_MEM_OFF 0x0 +#define CONFIG_RO_HDR_SIZE 0x40 -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* RO firmware in program memory - use all of program memory */ -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_SIZE NPCX_PROGRAM_MEMORY_SIZE +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_SIZE NPCX_PROGRAM_MEMORY_SIZE /* * ROM resident area in flash used to store data objects that are not copied * into code RAM. Enable using the CONFIG_CHIP_INIT_ROM_REGION option. */ -#define CONFIG_RO_ROM_RESIDENT_MEM_OFF CONFIG_RO_SIZE +#define CONFIG_RO_ROM_RESIDENT_MEM_OFF CONFIG_RO_SIZE #define CONFIG_RO_ROM_RESIDENT_SIZE \ (CONFIG_EC_PROTECTED_STORAGE_SIZE - CONFIG_RO_SIZE) @@ -75,10 +80,10 @@ * RW firmware in program memory - Identical to RO, only one image loaded at * a time. */ -#define CONFIG_RW_MEM_OFF CONFIG_RO_MEM_OFF -#define CONFIG_RW_SIZE CONFIG_RO_SIZE +#define CONFIG_RW_MEM_OFF CONFIG_RO_MEM_OFF +#define CONFIG_RW_SIZE CONFIG_RO_SIZE -#define CONFIG_RW_ROM_RESIDENT_MEM_OFF CONFIG_RW_SIZE +#define CONFIG_RW_ROM_RESIDENT_MEM_OFF CONFIG_RW_SIZE #define CONFIG_RW_ROM_RESIDENT_SIZE \ (CONFIG_EC_WRITABLE_STORAGE_SIZE - CONFIG_RW_SIZE) @@ -91,36 +96,49 @@ #endif /* - * CONFIG_FLASH_ERASE_SIZE is set to maximum possible out of 64k, 32k and 4k - * depending upon alignment of CONFIG_RO_SIZE. There are two assumptions here: - * 1. CONFIG_RO_MEM_OFF is always 0 i.e. RO starts at 0. - * 2. CONFIG_RO_SIZE and CONFIG_RW_SIZE are the same. + * The common flash support requires that the CONFIG_WP_STORAGE_SIZE and + * CONFIG_EC_WRITABLE_STORAGE_SIZE are both a multiple of + * CONFIG_FLASH_ERASE_SIZE. * - * If above assumptions are not true, then additional checks would be required - * to ensure that erase block size is selected based on the alignment of both - * CONFIG_RO_SIZE and CONFIG_RW_SIZE and the offset of RO. + * THE NPCX supports erase sizes of 64 KiB, 32 KiB, and 4 KiB. The NPCX flash + * driver does not currently support CONFIG_FLASH_MULTIPLE_REGION, so set + * the erase size to the maximum (64 KiB) for the best performance. + * Using smaller erase sizes increases boot time. If write protected and + * writable flash regions are not a multiple of 64 KiB, then support + * for CONFIG_FLASH_MULTIPLE_REGION must be added. */ -#if ((CONFIG_RO_SIZE & (0x10000 - 1)) == 0) -#define CONFIG_FLASH_ERASE_SIZE 0x10000 -#define NPCX_ERASE_COMMAND CMD_BLOCK_64K_ERASE -#elif ((CONFIG_RO_SIZE & (0x8000 - 1)) == 0) -#define CONFIG_FLASH_ERASE_SIZE 0x8000 -#define NPCX_ERASE_COMMAND CMD_BLOCK_32K_ERASE -#else -#define CONFIG_FLASH_ERASE_SIZE 0x1000 -#define NPCX_ERASE_COMMAND CMD_SECTOR_ERASE +#define CONFIG_FLASH_ERASE_SIZE 0x10000 +#define NPCX_ERASE_COMMAND CMD_BLOCK_64K_ERASE + +#if (CONFIG_WP_STORAGE_SIZE != CONFIG_EC_WRITABLE_STORAGE_SIZE) +#error "NPCX flash support assumes CONFIG_WP_STORAGE_SIZE and " \ + "CONFIG_EC_WRITABLE_STORAGE_SIZE are the same." #endif -#define CONFIG_FLASH_BANK_SIZE CONFIG_FLASH_ERASE_SIZE -#define CONFIG_FLASH_WRITE_SIZE 0x1 /* minimum write size */ -#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 /* one page size for write */ +/* + * If the total flash size is not a multiple of 64k, this slows the boot + * time. CONFIG_FLASH_MULTIPLE_REGION should be enabled in this case to + * optimize the erase block handling. + */ +#if ((CONFIG_WP_STORAGE_SIZE % CONFIG_FLASH_ERASE_SIZE) != 0) +#error "CONFIG_WP_STORAGE_SIZE is not a multiple of 64K. Correct the flash " \ + "size or add support for CONFIG_FLASH_MULTIPLE_REGION." +#endif + +/* + * The smallest protection bank size is 1/8 of 512 KB or 1/16 of 1M flash, + * i.e. 64KB. + */ +#define CONFIG_FLASH_BANK_SIZE 0x10000 +#define CONFIG_FLASH_WRITE_SIZE 0x1 /* minimum write size */ +#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 /* one page size for write */ /* Use 4k sector erase for NPCX monitor flash erase operations. */ -#define NPCX_MONITOR_FLASH_ERASE_SIZE 0x1000 +#define NPCX_MONITOR_FLASH_ERASE_SIZE 0x1000 /* RO image resides at start of protected region, right after header */ -#define CONFIG_RO_STORAGE_OFF CONFIG_RO_HDR_SIZE +#define CONFIG_RO_STORAGE_OFF CONFIG_RO_HDR_SIZE /* RW image resides at start of writable region */ -#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_STORAGE_OFF 0 #endif /* __CROS_EC_CONFIG_FLASH_LAYOUT_H */ diff --git a/chip/npcx/espi.c b/chip/npcx/espi.c index 9073838bd6..3bed4f4564 100644 --- a/chip/npcx/espi.c +++ b/chip/npcx/espi.c @@ -1,22 +1,23 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* ESPI module for Chrome EC */ -#include "registers.h" -#include "system.h" -#include "task.h" #include "chipset.h" #include "console.h" -#include "uart.h" -#include "util.h" -#include "power.h" #include "espi.h" -#include "lpc_chip.h" #include "hooks.h" +#include "lpc_chip.h" +#include "power.h" +#include "registers.h" +#include "system.h" +#include "system_boot_time.h" +#include "task.h" #include "timer.h" +#include "uart.h" +#include "util.h" /* Console output macros */ #if !(DEBUG_ESPI) @@ -24,113 +25,117 @@ #define CPRINTS(...) #else #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) #endif /* Default eSPI configuration for VW events */ struct vwevms_config_t { - uint8_t idx; /* VW index */ - uint8_t idx_en; /* Index enable */ - uint8_t pltrst_en; /* Enable reset by PLTRST assert */ + uint8_t idx; /* VW index */ + uint8_t idx_en; /* Index enable */ + uint8_t pltrst_en; /* Enable reset by PLTRST assert */ uint8_t espirst_en; /* Enable reset by eSPI_RST assert */ - uint8_t int_en; /* Interrupt/Wake-up enable */ + uint8_t int_en; /* Interrupt/Wake-up enable */ }; struct vwevsm_config_t { - uint8_t idx; /* VW index */ - uint8_t idx_en; /* Index enable */ - uint8_t pltrst_en; /* Enable reset by PLTRST assert */ - uint8_t cdrst_en; /* Enable cold reset */ - uint8_t valid; /* Valid VW mask */ + uint8_t idx; /* VW index */ + uint8_t idx_en; /* Index enable */ + uint8_t pltrst_en; /* Enable reset by PLTRST assert */ + uint8_t cdrst_en; /* Enable cold reset */ + uint8_t valid; /* Valid VW mask */ }; /* Default MIWU configurations for VW events */ struct host_wui_item { uint16_t table : 2; /* MIWU table 0-2 */ uint16_t group : 3; /* MIWU group 0-7 */ - uint16_t num : 3; /* MIWU bit 0-7 */ - uint16_t edge : 4; /* MIWU edge trigger type rising/falling/any */ + uint16_t num : 3; /* MIWU bit 0-7 */ + uint16_t edge : 4; /* MIWU edge trigger type rising/falling/any */ }; /* Mapping item between VW signal, index and value */ struct vw_event_t { - uint16_t name; /* Name of signal */ - uint8_t evt_idx; /* VW index of signal */ - uint8_t evt_val; /* VW value of signal */ + uint16_t name; /* Name of signal */ + uint8_t evt_idx; /* VW index of signal */ + uint8_t evt_val; /* VW value of signal */ }; /* Default settings of VWEVMS registers (Please refer Table.43/44) */ static const struct vwevms_config_t espi_in_list[] = { - /* IDX EN ENPL ENESP IE/WE VW Event Bit 0 - 3 (M->S) */ - {0x02, 1, 0, 0, 1}, /* SLP_S3#, SLP_S4#, SLP_S5#, Reserve */ - {0x03, 1, 0, 1, 1}, /* SUS_STAT#, PLTRST#, ORST_WARN, Reserve */ - {0x07, 1, 1, 1, 1}, /* HRST_WARN, SMIOUT#, NMIOUT#, Reserve */ - {0x41, 1, 0, 1, 1}, /* SUS_WARN#, SPWRDN_ACK, Reserve, SLP_A# */ - {0x42, 1, 0, 0, 1}, /* SLP_LAN#, SLP_WAN#, Reserve, Reserve */ - {0x47, 1, 1, 1, 1}, /* HOST_C10, Reserve, Reserve, Reserve */ +/* IDX EN ENPL ENESP IE/WE VW Event Bit 0 - 3 (M->S) */ +#ifdef CONFIG_HOST_INTERFACE_ESPI_RESET_SLP_SX_VW_ON_ESPI_RST + { 0x02, 1, 0, 1, 1 }, /* SLP_S3#, SLP_S4#, SLP_S5#, Reserve */ +#else + { 0x02, 1, 0, 0, 1 }, /* SLP_S3#, SLP_S4#, SLP_S5#, Reserve */ +#endif + { 0x03, 1, 0, 1, 1 }, /* SUS_STAT#, PLTRST#, ORST_WARN, Reserve */ + { 0x07, 1, 1, 1, 1 }, /* HRST_WARN, SMIOUT#, NMIOUT#, Reserve */ + { 0x41, 1, 0, 1, 1 }, /* SUS_WARN#, SPWRDN_ACK, Reserve, SLP_A# */ + { 0x42, 1, 0, 0, 1 }, /* SLP_LAN#, SLP_WAN#, Reserve, Reserve */ + { 0x47, 1, 1, 1, 1 }, /* HOST_C10, Reserve, Reserve, Reserve */ }; /* Default settings of VWEVSM registers (Please refer Table.43/44) */ static const struct vwevsm_config_t espi_out_list[] = { /* IDX EN ENPL ENCDR VDMASK VW Event Bit 0 - 3 (S->M) */ - {0x04, 1, 0, 0, 0x0D}, /* ORST_ACK, Reserve, WAKE#, PME# */ - {0x05, 1, 0, 0, 0x0F}, /* SLV_BL_DNE, ERR_F, ERR_NF, SLV_BL_STS */ + { 0x04, 1, 0, 0, 0x0D }, /* ORST_ACK, Reserve, WAKE#, PME# */ + { 0x05, 1, 0, 0, 0x0F }, /* SLV_BL_DNE, ERR_F, ERR_NF, SLV_BL_STS */ #ifdef CONFIG_SCI_GPIO - {0x06, 1, 1, 0, 0x0C}, /* SCI#, SMI#, RCIN#, HRST_ACK */ + { 0x06, 1, 1, 0, 0x0C }, /* SCI#, SMI#, RCIN#, HRST_ACK */ #else - {0x06, 1, 1, 0, 0x0F}, /* SCI#, SMI#, RCIN#, HRST_ACK */ + { 0x06, 1, 1, 0, 0x0F }, /* SCI#, SMI#, RCIN#, HRST_ACK */ #endif - {0x40, 1, 0, 0, 0x01}, /* SUS_ACK, Reserve, Reserve, Reserve */ + { 0x40, 1, 0, 0, 0x01 }, /* SUS_ACK, Reserve, Reserve, Reserve */ }; /* eSPI interrupts used in MIWU */ static const struct host_wui_item espi_vw_int_list[] = { /* ESPI_RESET */ - {MIWU_TABLE_0, MIWU_GROUP_5, 5, MIWU_EDGE_FALLING}, + { MIWU_TABLE_0, MIWU_GROUP_5, 5, MIWU_EDGE_FALLING }, /* SLP_S3 */ - {MIWU_TABLE_2, MIWU_GROUP_1, 0, MIWU_EDGE_ANYING}, + { MIWU_TABLE_2, MIWU_GROUP_1, 0, MIWU_EDGE_ANYING }, /* SLP_S4 */ - {MIWU_TABLE_2, MIWU_GROUP_1, 1, MIWU_EDGE_ANYING}, + { MIWU_TABLE_2, MIWU_GROUP_1, 1, MIWU_EDGE_ANYING }, /* SLP_S5 */ - {MIWU_TABLE_2, MIWU_GROUP_1, 2, MIWU_EDGE_ANYING}, + { MIWU_TABLE_2, MIWU_GROUP_1, 2, MIWU_EDGE_ANYING }, /* VW_WIRE_PLTRST */ - {MIWU_TABLE_2, MIWU_GROUP_1, 5, MIWU_EDGE_ANYING}, + { MIWU_TABLE_2, MIWU_GROUP_1, 5, MIWU_EDGE_ANYING }, /* VW_WIRE_OOB_RST_WARN */ - {MIWU_TABLE_2, MIWU_GROUP_1, 6, MIWU_EDGE_ANYING}, + { MIWU_TABLE_2, MIWU_GROUP_1, 6, MIWU_EDGE_ANYING }, /* VW_WIRE_HOST_RST_WARN */ - {MIWU_TABLE_2, MIWU_GROUP_2, 0, MIWU_EDGE_ANYING}, + { MIWU_TABLE_2, MIWU_GROUP_2, 0, MIWU_EDGE_ANYING }, /* VW_WIRE_SUS_WARN */ - {MIWU_TABLE_2, MIWU_GROUP_2, 4, MIWU_EDGE_ANYING}, + { MIWU_TABLE_2, MIWU_GROUP_2, 4, MIWU_EDGE_ANYING }, }; /* VW signals used in eSPI */ static const struct vw_event_t vw_events_list[] = { - {VW_SLP_S3_L, 0x02, 0x01}, /* index 02h (In) */ - {VW_SLP_S4_L, 0x02, 0x02}, - {VW_SLP_S5_L, 0x02, 0x04}, - {VW_SUS_STAT_L, 0x03, 0x01}, /* index 03h (In) */ - {VW_PLTRST_L, 0x03, 0x02}, - {VW_OOB_RST_WARN, 0x03, 0x04}, - {VW_OOB_RST_ACK, 0x04, 0x01}, /* index 04h (Out) */ - {VW_WAKE_L, 0x04, 0x04}, - {VW_PME_L, 0x04, 0x08}, - {VW_ERROR_FATAL, 0x05, 0x02}, /* index 05h (Out) */ - {VW_ERROR_NON_FATAL, 0x05, 0x04}, - {VW_SLAVE_BTLD_STATUS_DONE, 0x05, 0x09}, - {VW_SCI_L, 0x06, 0x01}, /* index 06h (Out) */ - {VW_SMI_L, 0x06, 0x02}, - {VW_RCIN_L, 0x06, 0x04}, - {VW_HOST_RST_ACK, 0x06, 0x08}, - {VW_HOST_RST_WARN, 0x07, 0x01}, /* index 07h (In) */ - {VW_SUS_ACK, 0x40, 0x01}, /* index 40h (Out) */ - {VW_SUS_WARN_L, 0x41, 0x01}, /* index 41h (In) */ - {VW_SUS_PWRDN_ACK_L, 0x41, 0x02}, - {VW_SLP_A_L, 0x41, 0x08}, - {VW_SLP_LAN, 0x42, 0x01}, /* index 42h (In) */ - {VW_SLP_WLAN, 0x42, 0x02}, + { VW_SLP_S3_L, 0x02, 0x01 }, /* index 02h (In) */ + { VW_SLP_S4_L, 0x02, 0x02 }, + { VW_SLP_S5_L, 0x02, 0x04 }, + { VW_SUS_STAT_L, 0x03, 0x01 }, /* index 03h (In) */ + { VW_PLTRST_L, 0x03, 0x02 }, + { VW_OOB_RST_WARN, 0x03, 0x04 }, + { VW_OOB_RST_ACK, 0x04, 0x01 }, /* index 04h (Out) */ + { VW_WAKE_L, 0x04, 0x04 }, + { VW_PME_L, 0x04, 0x08 }, + { VW_ERROR_FATAL, 0x05, 0x02 }, /* index 05h (Out) */ + { VW_ERROR_NON_FATAL, 0x05, 0x04 }, + { VW_PERIPHERAL_BTLD_STATUS_DONE, 0x05, 0x09 }, + { VW_SCI_L, 0x06, 0x01 }, /* index 06h (Out) */ + { VW_SMI_L, 0x06, 0x02 }, + { VW_RCIN_L, 0x06, 0x04 }, + { VW_HOST_RST_ACK, 0x06, 0x08 }, + { VW_HOST_RST_WARN, 0x07, 0x01 }, /* index 07h (In) */ + { VW_SUS_ACK, 0x40, 0x01 }, /* index 40h (Out) */ + { VW_SUS_WARN_L, 0x41, 0x01 }, /* index 41h (In) */ + { VW_SUS_PWRDN_ACK_L, 0x41, 0x02 }, + { VW_SLP_A_L, 0x41, 0x08 }, + { VW_SLP_LAN, 0x42, 0x01 }, /* index 42h (In) */ + { VW_SLP_WLAN, 0x42, 0x02 }, }; -/* Flag for SLAVE_BOOT_LOAD siganls */ +/* Flag for boot load signals */ static uint8_t boot_load_done; /*****************************************************************************/ @@ -145,11 +150,11 @@ static void espi_reset_recovery(void) boot_load_done = 0; } -/* Configure Master-to-Slave virtual wire inputs */ +/* Configure Controller-to-Peripheral virtual wire inputs */ static void espi_vw_config_in(const struct vwevms_config_t *config) { uint32_t val; - uint8_t i, index; + uint8_t i, index; switch (VM_TYPE(config->idx)) { case ESPI_VW_TYPE_SYS_EV: @@ -160,11 +165,10 @@ static void espi_vw_config_in(const struct vwevms_config_t *config) if (index == config->idx) { /* Get Wire field */ val = NPCX_VWEVMS(i) & 0x0F; - val |= VWEVMS_FIELD(config->idx, - config->idx_en, - config->pltrst_en, - config->int_en, - config->espirst_en); + val |= VWEVMS_FIELD(config->idx, config->idx_en, + config->pltrst_en, + config->int_en, + config->espirst_en); NPCX_VWEVMS(i) = val; return; } @@ -177,7 +181,7 @@ static void espi_vw_config_in(const struct vwevms_config_t *config) } } -/* Configure Slave-to-Master virtual wire outputs */ +/* Configure Peripheral-to-Controller virtual wire outputs */ static void espi_vw_config_out(const struct vwevsm_config_t *config) { uint32_t val; @@ -192,11 +196,10 @@ static void espi_vw_config_out(const struct vwevsm_config_t *config) if (index == config->idx) { /* Preserve WIRE(3-0) and HW_WIRE (27-24). */ val = NPCX_VWEVSM(i) & 0x0F00000F; - val |= VWEVSM_FIELD(config->idx, - config->idx_en, - config->valid, - config->pltrst_en, - config->cdrst_en); + val |= VWEVSM_FIELD(config->idx, config->idx_en, + config->valid, + config->pltrst_en, + config->cdrst_en); NPCX_VWEVSM(i) = val; return; } @@ -209,13 +212,13 @@ static void espi_vw_config_out(const struct vwevsm_config_t *config) } } -/* Config Master-to-Slave VWire interrupt edge type and enable it */ +/* Config Controller-to-Peripheral VWire interrupt edge type and enable it */ static void espi_enable_vw_int(const struct host_wui_item *vwire_int) { uint8_t table = vwire_int->table; uint8_t group = vwire_int->group; - uint8_t num = vwire_int->num; - uint8_t edge = vwire_int->edge; + uint8_t num = vwire_int->num; + uint8_t edge = vwire_int->edge; /* Set detection mode to edge */ CLEAR_BIT(NPCX_WKMOD(table, group), num); @@ -262,7 +265,35 @@ void espi_vw_power_signal_interrupt(enum espi_vw_signal signal) { if (IS_ENABLED(CONFIG_HOST_ESPI_VW_POWER_SIGNAL)) /* TODO: Add VW handler in power/common.c */ - power_signal_interrupt((enum gpio_signal) signal); + power_signal_interrupt((enum gpio_signal)signal); +} + +void espi_wait_vw_not_dirty(enum espi_vw_signal signal, unsigned int timeout_us) +{ + int sig_idx; + uint8_t offset; + uint64_t timeout; + + sig_idx = espi_vw_get_signal_index(signal); + /* Cannot find signal index */ + if (sig_idx < 0) + return; + + for (offset = 0; offset < ESPI_VWEVSM_NUM; offset++) { + uint8_t vw_idx = VWEVSM_IDX_GET(NPCX_VWEVSM(offset)); + + if (vw_idx == vw_events_list[sig_idx].evt_idx) + break; + } + + if (offset == ESPI_VWEVSM_NUM) + return; + + timeout = get_time().val + (uint64_t)timeout_us; + while ((NPCX_VWEVSM(offset) & VWEVSM_DIRTY(1)) && + (get_time().val < timeout)) { + udelay(10); + } } /*****************************************************************************/ @@ -408,22 +439,35 @@ void espi_vw_evt_pltrst(void) if (pltrst) { /* PLTRST# deasserted */ +#if defined(CHIP_FAMILY_NPCX5) + /* See errata 2.22 */ + /* Disable eSPI peripheral channel support first */ CLEAR_BIT(NPCX_ESPICFG, NPCX_ESPICFG_PCCHN_SUPP); + /* Initialize host settings */ + host_register_init(); + /* Enable eSPI peripheral channel */ SET_BIT(NPCX_ESPICFG, NPCX_ESPICFG_PCHANEN); + /* Re-enable eSPI peripheral channel support */ + SET_BIT(NPCX_ESPICFG, NPCX_ESPICFG_PCCHN_SUPP); +#else /* Initialize host settings */ host_register_init(); - /* Re-enable eSPI peripheral channel support */ - SET_BIT(NPCX_ESPICFG, NPCX_ESPICFG_PCCHN_SUPP); + /* Enable eSPI peripheral channel */ + SET_BIT(NPCX_ESPICFG, NPCX_ESPICFG_PCHANEN); +#endif + update_ap_boot_time(PLTRST_HIGH); + } else { /* PLTRST# asserted */ #ifdef CONFIG_CHIPSET_RESET_HOOK hook_call_deferred(&espi_chipset_reset_data, MSEC); #endif + update_ap_boot_time(PLTRST_LOW); } } @@ -484,11 +528,13 @@ void espi_espirst_handler(void) /* Clear pending bit of WUI */ SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_5), 5); + update_ap_boot_time(ESPIRST); + CPRINTS("eSPI RST issued!"); } /* Handle eSPI virtual wire interrupt 1 */ -void __espi_wk2a_interrupt(void) +static void __espi_wk2a_interrupt(void) { uint8_t pending_bits = NPCX_WKPND(MIWU_TABLE_2, MIWU_GROUP_1); @@ -510,7 +556,7 @@ void __espi_wk2a_interrupt(void) DECLARE_IRQ(NPCX_IRQ_WKINTA_2, __espi_wk2a_interrupt, 3); /* Handle eSPI virtual wire interrupt 2 */ -void __espi_wk2b_interrupt(void) +static void __espi_wk2b_interrupt(void) { uint8_t pending_bits = NPCX_WKPND(MIWU_TABLE_2, MIWU_GROUP_2); @@ -526,7 +572,7 @@ void __espi_wk2b_interrupt(void) DECLARE_IRQ(NPCX_IRQ_WKINTB_2, __espi_wk2b_interrupt, 3); /* Interrupt handler for eSPI status changed */ -void espi_interrupt(void) +static void espi_interrupt(void) { int chan; uint32_t mask, status; @@ -547,7 +593,8 @@ void espi_interrupt(void) NPCX_ESPISTS = status; if (IS_BIT_SET(status, NPCX_ESPISTS_BERR)) - CPRINTS("eSPI Bus Error"); + /* Always print eSPI Bus Errors */ + cprints(CC_LPC, "eSPI Bus Error"); /* eSPI inband reset(from VW) */ if (IS_BIT_SET(status, NPCX_ESPISTS_IBRST)) { @@ -569,24 +616,24 @@ void espi_interrupt(void) * handled by PLTRST separately. */ for (chan = NPCX_ESPI_CH_VW; chan < NPCX_ESPI_CH_COUNT; - chan++) { - if (!IS_SLAVE_CHAN_ENABLE(chan) && - IS_HOST_CHAN_EN(chan)) + chan++) { + if (!IS_PERIPHERAL_CHAN_ENABLE(chan) && + IS_HOST_CHAN_EN(chan)) ENABLE_ESPI_CHAN(chan); - else if (IS_SLAVE_CHAN_ENABLE(chan) && - !IS_HOST_CHAN_EN(chan)) + else if (IS_PERIPHERAL_CHAN_ENABLE(chan) && + !IS_HOST_CHAN_EN(chan)) DISABLE_ESPI_CHAN(chan); } /* - * Send SLAVE_BOOTLOAD_DONE and SLAVE_BOOTLOAD_STATUS + * Send BOOTLOAD_DONE and BOOTLOAD_STATUS * events to host simultaneously. To indicate the * completion of EC firmware code loading. */ if (boot_load_done == 0 && - IS_SLAVE_CHAN_ENABLE(NPCX_ESPI_CH_VW)) { - - espi_vw_set_wire(VW_SLAVE_BTLD_STATUS_DONE, 1); + IS_PERIPHERAL_CHAN_ENABLE(NPCX_ESPI_CH_VW)) { + espi_vw_set_wire(VW_PERIPHERAL_BTLD_STATUS_DONE, + 1); boot_load_done = 1; } } @@ -607,22 +654,31 @@ void espi_init(void) { int i; + if (IS_ENABLED(NPCX_ESPI_BYPASS_CH_ENABLE_FATAL_ERROR)) { + /* Enable the access to the NPCX_ONLY_ESPI_REG2 register */ + NPCX_ONLY_ESPI_REG1 = NPCX_ONLY_ESPI_REG1_UNLOCK_REG2; + CLEAR_BIT(NPCX_ONLY_ESPI_REG2, + NPCX_ONLY_ESPI_REG2_TRANS_END_CONFIG); + /* Disable the access to the NPCX_ONLY_ESPI_REG2 register */ + NPCX_ONLY_ESPI_REG1 = NPCX_ONLY_ESPI_REG1_LOCK_REG2; + } + /* Support all channels */ NPCX_ESPICFG |= ESPI_SUPP_CH_ALL; /* Support all I/O modes */ SET_FIELD(NPCX_ESPICFG, NPCX_ESPICFG_IOMODE_FIELD, - NPCX_ESPI_IO_MODE_ALL); + NPCX_ESPI_IO_MODE_ALL); /* Set eSPI speed to max supported */ SET_FIELD(NPCX_ESPICFG, NPCX_ESPICFG_MAXFREQ_FIELD, NPCX_ESPI_MAXFREQ_MAX); - /* Configure Master-to-Slave Virtual Wire indexes (Inputs) */ + /* Configure Controller-to-Peripheral Virtual Wire indexes (Inputs) */ for (i = 0; i < ARRAY_SIZE(espi_in_list); i++) espi_vw_config_in(&espi_in_list[i]); - /* Configure Slave-to-Master Virtual Wire indexes (Outputs) */ + /* Configure Peripheral-to-Controller Virtual Wire indexes (Outputs) */ for (i = 0; i < ARRAY_SIZE(espi_out_list); i++) espi_vw_config_out(&espi_out_list[i]); @@ -631,14 +687,14 @@ void espi_init(void) espi_enable_vw_int(&espi_vw_int_list[i]); } -static int command_espi(int argc, char **argv) +static int command_espi(int argc, const char **argv) { uint32_t chan; char *e; if (argc == 1) { return EC_ERROR_INVAL; - /* Get value of eSPI registers */ + /* Get value of eSPI registers */ } else if (argc == 2) { int i; @@ -647,23 +703,23 @@ static int command_espi(int argc, char **argv) } else if (strcasecmp(argv[1], "vsm") == 0) { for (i = 0; i < ESPI_VWEVSM_NUM; i++) { uint32_t val = NPCX_VWEVSM(i); - uint8_t idx = VWEVSM_IDX_GET(val); + uint8_t idx = VWEVSM_IDX_GET(val); ccprintf("VWEVSM%d: %02x [0x%08x]\n", i, idx, - val); + val); } } else if (strcasecmp(argv[1], "vms") == 0) { for (i = 0; i < ESPI_VWEVMS_NUM; i++) { uint32_t val = NPCX_VWEVMS(i); - uint8_t idx = VWEVMS_IDX_GET(val); + uint8_t idx = VWEVMS_IDX_GET(val); ccprintf("VWEVMS%d: %02x [0x%08x]\n", i, idx, - val); + val); } } - /* Enable/Disable the channels of eSPI */ + /* Enable/Disable the channels of eSPI */ } else if (argc == 3) { - uint32_t m = (uint32_t) strtoi(argv[2], &e, 0); + uint32_t m = (uint32_t)strtoi(argv[2], &e, 0); if (*e) return EC_ERROR_PARAM2; @@ -683,6 +739,5 @@ static int command_espi(int argc, char **argv) } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(espi, command_espi, - "cfg/vms/vsm/en/dis [channel]", +DECLARE_CONSOLE_COMMAND(espi, command_espi, "cfg/vms/vsm/en/dis [channel]", "eSPI configurations"); diff --git a/chip/npcx/fan.c b/chip/npcx/fan.c index f0b3215ce0..9ceccaba33 100644 --- a/chip/npcx/fan.c +++ b/chip/npcx/fan.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,25 +7,24 @@ #include "clock.h" #include "clock_chip.h" +#include "console.h" #include "fan.h" #include "fan_chip.h" #include "gpio.h" #include "hooks.h" -#include "registers.h" -#include "util.h" +#include "math_util.h" #include "pwm.h" #include "pwm_chip.h" -#include "console.h" -#include "timer.h" -#include "task.h" -#include "hooks.h" +#include "registers.h" #include "system.h" -#include "math_util.h" +#include "task.h" +#include "timer.h" +#include "util.h" #if !(DEBUG_FAN) #define CPRINTS(...) #else -#define CPRINTS(format, args...) cprints(CC_PWM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_PWM, format, ##args) #endif /* Tacho measurement state */ @@ -92,7 +91,7 @@ static int rpm_pre[FAN_CH_COUNT]; #define TACHO_MAX_CNT (BIT(16) - 1) /* Margin of target rpm */ -#define RPM_MARGIN(rpm_target) (((rpm_target) * RPM_DEVIATION) / 100) +#define RPM_MARGIN(rpm_target) (((rpm_target)*RPM_DEVIATION) / 100) /** * MFT get fan rpm value @@ -144,7 +143,7 @@ static int mft_fan_rpm(int ch) /** * Set fan prescaler based on apb1 clock * - * @param none + * @param ch operation channel * @return none * @notes changed when initial or HOOK_FREQ_CHANGE command */ @@ -154,14 +153,14 @@ void mft_set_apb1_prescaler(int ch) uint16_t prescaler_divider = 0; /* Set clock prescaler divider to MFT module*/ - prescaler_divider = (uint16_t)(clock_get_apb1_freq() - / fan_status[ch].mft_freq); + prescaler_divider = + (uint16_t)(clock_get_apb1_freq() / fan_status[ch].mft_freq); if (prescaler_divider >= 1) prescaler_divider = prescaler_divider - 1; if (prescaler_divider > 0xFF) prescaler_divider = 0xFF; - NPCX_TPRSC(mdl) = (uint8_t) prescaler_divider; + NPCX_TPRSC(mdl) = (uint8_t)prescaler_divider; } /** @@ -184,7 +183,6 @@ static void fan_config(int ch, int enable_mft_read_rpm) /* Need to initialize MFT or not */ if (enable_mft_read_rpm) { - /* Initialize tacho sampling rate */ if (clk_src == TCKC_LFCLK) p_status->mft_freq = INT_32K_CLOCK; @@ -195,7 +193,7 @@ static void fan_config(int ch, int enable_mft_read_rpm) /* Set mode 5 to MFT module */ SET_FIELD(NPCX_TMCTRL(mdl), NPCX_TMCTRL_MDSEL_FIELD, - NPCX_MFT_MDSEL_5); + NPCX_MFT_MDSEL_5); /* Set MFT operation frequency */ if (clk_src == TCKC_PRESCALE_APB1_CLK) @@ -203,11 +201,11 @@ static void fan_config(int ch, int enable_mft_read_rpm) /* Set the low power mode or not. */ UPDATE_BIT(NPCX_TCKC(mdl), NPCX_TCKC_LOW_PWR, - clk_src == TCKC_LFCLK); + clk_src == TCKC_LFCLK); /* Set the default count-down timer. */ NPCX_TCNT1(mdl) = TACHO_MAX_CNT; - NPCX_TCRA(mdl) = TACHO_MAX_CNT; + NPCX_TCRA(mdl) = TACHO_MAX_CNT; /* Set the edge polarity to rising. */ SET_BIT(NPCX_TMCTRL(mdl), NPCX_TMCTRL_TAEDG); @@ -293,11 +291,22 @@ enum fan_status fan_smart_control(int ch, int rpm_actual, int rpm_target) return FAN_STATUS_CHANGING; } + /* + * A specific type of fan needs a longer time to output the TACH + * signal to EC after EC outputs the PWM signal to the fan. + * During this period, the driver will read two consecutive RPM = 0. + * In this case, don't step the PWM duty too aggressively. + * See b:225208265 for more detail. + */ + if (rpm_pre[ch] == 0 && rpm_actual == 0 && + IS_ENABLED(CONFIG_FAN_BYPASS_SLOW_RESPONSE)) { + rpm_diff = RPM_MARGIN(rpm_target) + 1; + } else { + rpm_diff = rpm_target - rpm_actual; + } + /* Record previous rpm */ rpm_pre[ch] = rpm_actual; - - /* Adjust PWM duty */ - rpm_diff = rpm_target - rpm_actual; duty = fan_get_duty(ch); if (duty == 0 && rpm_target == 0) return FAN_STATUS_STOPPED; @@ -309,7 +318,7 @@ enum fan_status fan_smart_control(int ch, int rpm_actual, int rpm_target) fan_adjust_duty(ch, rpm_diff, duty); return FAN_STATUS_CHANGING; - /* Decrease PWM duty */ + /* Decrease PWM duty */ } else if (rpm_diff < -RPM_MARGIN(rpm_target)) { if (duty == 1 && rpm_target != 0) return FAN_STATUS_FRUSTRATED; @@ -330,11 +339,12 @@ void fan_tick_func(void) { int ch; - for (ch = 0; ch < FAN_CH_COUNT ; ch++) { + for (ch = 0; ch < FAN_CH_COUNT; ch++) { volatile struct fan_status_t *p_status = fan_status + ch; /* Make sure rpm mode is enabled */ if (p_status->fan_mode != TACHO_FAN_RPM) { - /* Fan in duty mode still want rpm_actual being updated. */ + /* Fan in duty mode still want rpm_actual being updated. + */ p_status->rpm_actual = mft_fan_rpm(ch); if (p_status->rpm_actual > 0) p_status->auto_status = FAN_STATUS_LOCKED; @@ -347,8 +357,8 @@ void fan_tick_func(void) /* Get actual rpm */ p_status->rpm_actual = mft_fan_rpm(ch); /* Do smart fan stuff */ - p_status->auto_status = fan_smart_control(ch, - p_status->rpm_actual, p_status->rpm_target); + p_status->auto_status = fan_smart_control( + ch, p_status->rpm_actual, p_status->rpm_target); } } DECLARE_HOOK(HOOK_TICK, fan_tick_func, HOOK_PRIO_DEFAULT); @@ -520,7 +530,7 @@ enum fan_status fan_get_status(int ch) int fan_is_stalled(int ch) { return fan_get_enabled(ch) && fan_get_duty(ch) && - fan_status[ch].cur_state == TACHO_UNDERFLOW; + fan_status[ch].cur_state == TACHO_UNDERFLOW; } /** diff --git a/chip/npcx/fan_chip.h b/chip/npcx/fan_chip.h index bc97011895..36eb13f4cb 100644 --- a/chip/npcx/fan_chip.h +++ b/chip/npcx/fan_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -32,7 +32,7 @@ enum npcx_mft_module { enum npcx_mft_clk_src { TCKC_NOCLK = 0, TCKC_PRESCALE_APB1_CLK = 1, - TCKC_LFCLK = 5, + TCKC_LFCLK = 4, }; /* Data structure to define MFT channels. */ diff --git a/chip/npcx/flash.c b/chip/npcx/flash.c index 7afb413c2c..dc8de6e3ee 100644 --- a/chip/npcx/flash.c +++ b/chip/npcx/flash.c @@ -1,27 +1,27 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Flash memory module for Chrome EC */ +#include "builtin/assert.h" +#include "console.h" #include "flash.h" #include "host_command.h" +#include "hwtimer_chip.h" #include "registers.h" #include "spi_flash_reg.h" #include "switch.h" #include "system.h" +#include "task.h" #include "timer.h" #include "util.h" -#include "task.h" #include "watchdog.h" -#include "console.h" -#include "hwtimer_chip.h" static int all_protected; /* Has all-flash protection been requested? */ static int addr_prot_start; static int addr_prot_length; -static uint8_t flag_prot_inconsistent; /* SR regs aren't readable when UMA lock is on, so save a copy */ static uint8_t saved_sr1; @@ -69,7 +69,7 @@ static void flash_execute_cmd(uint8_t code, uint8_t cts) /* set UMA_CODE */ NPCX_UMA_CODE = code; /* execute UMA flash transaction */ - NPCX_UMA_CTS = cts; + NPCX_UMA_CTS = cts; while (IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) ; } @@ -95,7 +95,7 @@ static int flash_wait_ready(void) flash_execute_cmd(CMD_READ_STATUS_REG, MASK_CMD_ONLY); do { /* Read status register */ - NPCX_UMA_CTS = MASK_RD_1BYTE; + NPCX_UMA_CTS = MASK_RD_1BYTE; while (IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) ; /* Busy bit is clear */ @@ -145,54 +145,70 @@ static void flash_set_address(uint32_t dest_addr) NPCX_UMA_AB0 = addr[0]; } -static uint8_t flash_get_status1(void) +static void flash_get_status(uint8_t *sr1, uint8_t *sr2) { - uint8_t ret; - - if (all_protected) - return saved_sr1; + if (all_protected) { + *sr1 = saved_sr1; + *sr2 = saved_sr2; + return; + } /* Lock physical flash operations */ - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); /* Disable tri-state */ TRISTATE_FLASH(0); /* Read status register1 */ flash_execute_cmd(CMD_READ_STATUS_REG, MASK_CMD_RD_1BYTE); + *sr1 = NPCX_UMA_DB0; + /* Read status register2 */ + flash_execute_cmd(CMD_READ_STATUS_REG2, MASK_CMD_RD_1BYTE); + *sr2 = NPCX_UMA_DB0; /* Enable tri-state */ TRISTATE_FLASH(1); - ret = NPCX_UMA_DB0; - /* Unlock physical flash operations */ - flash_lock_mapped_storage(0); - - return ret; + crec_flash_lock_mapped_storage(0); } -static uint8_t flash_get_status2(void) +static void flash_set_status(uint8_t sr1, uint8_t sr2) { - uint8_t ret; - - if (all_protected) - return saved_sr2; - /* Lock physical flash operations */ - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); /* Disable tri-state */ TRISTATE_FLASH(0); - /* Read status register2 */ - flash_execute_cmd(CMD_READ_STATUS_REG2, MASK_CMD_RD_1BYTE); + /* Enable write */ + flash_write_enable(); + + NPCX_UMA_DB0 = sr1; + NPCX_UMA_DB1 = sr2; + + /* Write status register 1/2 */ + flash_execute_cmd(CMD_WRITE_STATUS_REG, MASK_CMD_WR_2BYTE); /* Enable tri-state */ TRISTATE_FLASH(1); - ret = NPCX_UMA_DB0; - /* Unlock physical flash operations */ - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); +} - return ret; +static void flash_set_quad_enable(int enable) +{ + uint8_t sr1, sr2; + + flash_get_status(&sr1, &sr2); + + /* If QE is the same value, return directly. */ + if (!!(sr2 & SPI_FLASH_SR2_QE) == enable) + return; + + if (enable) + sr2 |= SPI_FLASH_SR2_QE; + else + sr2 &= ~SPI_FLASH_SR2_QE; + + flash_set_status(sr1, sr2); } #ifdef NPCX_INT_FLASH_SUPPORT @@ -217,7 +233,7 @@ static void flash_protect_int_flash(int enable) void flash_get_mfr_dev_id(uint8_t *dest) { /* Lock physical flash operations */ - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); /* Disable tri-state */ TRISTATE_FLASH(0); @@ -232,7 +248,7 @@ void flash_get_mfr_dev_id(uint8_t *dest) dest[1] = NPCX_UMA_DB1; /* Unlock physical flash operations */ - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); } #endif /* CONFIG_HOSTCMD_FLASH_SPI_INFO */ @@ -240,7 +256,7 @@ void flash_get_mfr_dev_id(uint8_t *dest) void flash_get_jedec_id(uint8_t *dest) { /* Lock physical flash operations */ - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); /* Disable tri-state */ TRISTATE_FLASH(0); @@ -254,7 +270,7 @@ void flash_get_jedec_id(uint8_t *dest) dest[2] = NPCX_UMA_DB2; /* Unlock physical flash operations */ - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); } static void flash_uma_lock(int enable) @@ -264,8 +280,7 @@ static void flash_uma_lock(int enable) * Store SR1 / SR2 for later use since we're about to lock * out all access (including read access) to these regs. */ - saved_sr1 = flash_get_status1(); - saved_sr2 = flash_get_status2(); + flash_get_status(&saved_sr1, &saved_sr2); } all_protected = enable; @@ -284,7 +299,7 @@ static int flash_set_status_for_prot(int reg1, int reg2) return EC_ERROR_ACCESS_DENIED; #endif - if (flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) + if (crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) return EC_ERROR_ACCESS_DENIED; flash_uma_lock(0); } @@ -300,28 +315,10 @@ static int flash_set_status_for_prot(int reg1, int reg2) flash_protect_int_flash(!gpio_get_level(GPIO_WP_L)); #endif /*_CONFIG_WP_ACTIVE_HIGH_*/ #endif + flash_set_status(reg1, reg2); - /* Lock physical flash operations */ - flash_lock_mapped_storage(1); - - /* Disable tri-state */ - TRISTATE_FLASH(0); - /* Enable write */ - flash_write_enable(); - - NPCX_UMA_DB0 = reg1; - NPCX_UMA_DB1 = reg2; - - /* Write status register 1/2 */ - flash_execute_cmd(CMD_WRITE_STATUS_REG, MASK_CMD_WR_2BYTE); - /* Enable tri-state */ - TRISTATE_FLASH(1); - - /* Unlock physical flash operations */ - flash_lock_mapped_storage(0); - - spi_flash_reg_to_protect(reg1, reg2, - &addr_prot_start, &addr_prot_length); + spi_flash_reg_to_protect(reg1, reg2, &addr_prot_start, + &addr_prot_length); return EC_SUCCESS; } @@ -329,11 +326,11 @@ static int flash_set_status_for_prot(int reg1, int reg2) static int flash_check_prot_range(unsigned int offset, unsigned int bytes) { /* Invalid value */ - if (offset + bytes > CONFIG_FLASH_SIZE) + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; /* Check if ranges overlap */ - if (MAX(addr_prot_start, offset) < MIN(addr_prot_start + - addr_prot_length, offset + bytes)) + if (MAX(addr_prot_start, offset) < + MIN(addr_prot_start + addr_prot_length, offset + bytes)) return EC_ERROR_ACCESS_DENIED; return EC_SUCCESS; @@ -358,14 +355,12 @@ static int flash_check_prot_reg(unsigned int offset, unsigned int bytes) #endif /* CONFIG_WP_ACTIVE_HIGH */ #endif - sr1 = flash_get_status1(); - sr2 = flash_get_status2(); - /* Invalid value */ - if (offset + bytes > CONFIG_FLASH_SIZE) + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; /* Compute current protect range */ + flash_get_status(&sr1, &sr2); rv = spi_flash_reg_to_protect(sr1, sr2, &start, &len); if (rv) return rv; @@ -375,21 +370,20 @@ static int flash_check_prot_reg(unsigned int offset, unsigned int bytes) return EC_ERROR_ACCESS_DENIED; return EC_SUCCESS; - } static int flash_write_prot_reg(unsigned int offset, unsigned int bytes, int hw_protect) { int rv; - uint8_t sr1 = flash_get_status1(); - uint8_t sr2 = flash_get_status2(); + uint8_t sr1, sr2; /* Invalid values */ - if (offset + bytes > CONFIG_FLASH_SIZE) + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; /* Compute desired protect range */ + flash_get_status(&sr1, &sr2); rv = spi_flash_protect_to_reg(offset, bytes, &sr1, &sr2); if (rv) return rv; @@ -401,7 +395,7 @@ static int flash_write_prot_reg(unsigned int offset, unsigned int bytes, } static void flash_burst_write(unsigned int dest_addr, unsigned int bytes, - const char *data) + const char *data) { unsigned int i; /* Chip Select down */ @@ -419,15 +413,17 @@ static void flash_burst_write(unsigned int dest_addr, unsigned int bytes, } static int flash_program_bytes(uint32_t offset, uint32_t bytes, - const uint8_t *data) + const uint8_t *data) { int write_size; int rv; while (bytes > 0) { /* Write length can not go beyond the end of the flash page */ - write_size = MIN(bytes, CONFIG_FLASH_WRITE_IDEAL_SIZE - - (offset & (CONFIG_FLASH_WRITE_IDEAL_SIZE - 1))); + write_size = MIN(bytes, + CONFIG_FLASH_WRITE_IDEAL_SIZE - + (offset & + (CONFIG_FLASH_WRITE_IDEAL_SIZE - 1))); /* Enable write */ rv = flash_write_enable(); @@ -442,9 +438,9 @@ static int flash_program_bytes(uint32_t offset, uint32_t bytes, if (rv) return rv; - data += write_size; + data += write_size; offset += write_size; - bytes -= write_size; + bytes -= write_size; } return rv; @@ -452,13 +448,13 @@ static int flash_program_bytes(uint32_t offset, uint32_t bytes, /*****************************************************************************/ -int flash_physical_read(int offset, int size, char *data) +int crec_flash_physical_read(int offset, int size, char *data) { int dest_addr = offset; uint32_t idx; /* Lock physical flash operations */ - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); /* Disable tri-state */ TRISTATE_FLASH(0); @@ -473,7 +469,7 @@ int flash_physical_read(int offset, int size, char *data) /* Burst read transaction */ for (idx = 0; idx < size; idx++) { /* 1101 0101 - EXEC, RD, NO CMD, NO ADDR, 4 bytes */ - NPCX_UMA_CTS = MASK_RD_1BYTE; + NPCX_UMA_CTS = MASK_RD_1BYTE; /* wait for UMA to complete */ while (IS_BIT_SET(NPCX_UMA_CTS, EXEC_DONE)) ; @@ -487,20 +483,20 @@ int flash_physical_read(int offset, int size, char *data) TRISTATE_FLASH(1); /* Unlock physical flash operations */ - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); return EC_SUCCESS; } -int flash_physical_write(int offset, int size, const char *data) +int crec_flash_physical_write(int offset, int size, const char *data) { int dest_addr = offset; int write_len; int rv; /* Fail if offset, size, and data aren't at least word-aligned */ - if ((offset | size - | (uint32_t)(uintptr_t)data) & (CONFIG_FLASH_WRITE_SIZE - 1)) + if ((offset | size | (uint32_t)(uintptr_t)data) & + (CONFIG_FLASH_WRITE_SIZE - 1)) return EC_ERROR_INVAL; /* check protection */ @@ -508,7 +504,7 @@ int flash_physical_write(int offset, int size, const char *data) return EC_ERROR_ACCESS_DENIED; /* Lock physical flash operations */ - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); /* Disable tri-state */ TRISTATE_FLASH(0); @@ -516,7 +512,8 @@ int flash_physical_write(int offset, int size, const char *data) while (size > 0) { /* First write multiples of 256, then (size % 256) last */ write_len = ((size % CONFIG_FLASH_WRITE_IDEAL_SIZE) == size) ? - size : CONFIG_FLASH_WRITE_IDEAL_SIZE; + size : + CONFIG_FLASH_WRITE_IDEAL_SIZE; /* check protection */ if (flash_check_prot_range(dest_addr, write_len)) { @@ -528,21 +525,21 @@ int flash_physical_write(int offset, int size, const char *data) if (rv) break; - data += write_len; + data += write_len; dest_addr += write_len; - size -= write_len; + size -= write_len; } /* Enable tri-state */ TRISTATE_FLASH(1); /* Unlock physical flash operations */ - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); return rv; } -int flash_physical_erase(int offset, int size) +int crec_flash_physical_erase(int offset, int size) { int rv = EC_SUCCESS; /* check protection */ @@ -550,14 +547,14 @@ int flash_physical_erase(int offset, int size) return EC_ERROR_ACCESS_DENIED; /* Lock physical flash operations */ - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); /* Disable tri-state */ TRISTATE_FLASH(0); /* Alignment has been checked in upper layer */ for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE, - offset += CONFIG_FLASH_ERASE_SIZE) { + offset += CONFIG_FLASH_ERASE_SIZE) { /* check protection */ if (flash_check_prot_range(offset, CONFIG_FLASH_ERASE_SIZE)) { rv = EC_ERROR_ACCESS_DENIED; @@ -591,32 +588,42 @@ int flash_physical_erase(int offset, int size) TRISTATE_FLASH(1); /* Unlock physical flash operations */ - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); return rv; } -int flash_physical_get_protect(int bank) +int crec_flash_physical_get_protect(int bank) { uint32_t addr = bank * CONFIG_FLASH_BANK_SIZE; return flash_check_prot_reg(addr, CONFIG_FLASH_BANK_SIZE); } -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { uint32_t flags = 0; + uint8_t sr1, sr2; + unsigned int start, len; + int rv; /* Check if WP region is protected in status register */ - if (flash_check_prot_reg(WP_BANK_OFFSET*CONFIG_FLASH_BANK_SIZE, - WP_BANK_COUNT*CONFIG_FLASH_BANK_SIZE)) + rv = flash_check_prot_reg(WP_BANK_OFFSET * CONFIG_FLASH_BANK_SIZE, + WP_BANK_COUNT * CONFIG_FLASH_BANK_SIZE); + if (rv == EC_ERROR_ACCESS_DENIED) flags |= EC_FLASH_PROTECT_RO_AT_BOOT; + else if (rv) + return EC_FLASH_PROTECT_ERROR_UNKNOWN; /* - * TODO: If status register protects a range, but SRP0 is not set, - * flags should indicate EC_FLASH_PROTECT_ERROR_INCONSISTENT. + * If the status register protects a range, but SRP0 is not set, or QE + * is set, flags should indicate EC_FLASH_PROTECT_ERROR_INCONSISTENT. */ - if (flag_prot_inconsistent) + flash_get_status(&sr1, &sr2); + rv = spi_flash_reg_to_protect(sr1, sr2, &start, &len); + if (rv) + return EC_FLASH_PROTECT_ERROR_UNKNOWN; + if (len && (!(sr1 & SPI_FLASH_SR1_SRP0) || (sr2 & SPI_FLASH_SR2_QE))) flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT; /* Read all-protected state from our shadow copy */ @@ -626,7 +633,7 @@ uint32_t flash_physical_get_protect_flags(void) return flags; } -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { if (all) { /* @@ -641,8 +648,7 @@ int flash_physical_protect_now(int all) return EC_SUCCESS; } - -int flash_physical_protect_at_boot(uint32_t new_flags) +int crec_flash_physical_protect_at_boot(uint32_t new_flags) { int ret; @@ -653,8 +659,7 @@ int flash_physical_protect_at_boot(uint32_t new_flags) } ret = flash_write_prot_reg(CONFIG_WP_STORAGE_OFF, - CONFIG_WP_STORAGE_SIZE, - 1); + CONFIG_WP_STORAGE_SIZE, 1); /* * Set UMA_LOCK bit for locking all UMA transaction. @@ -666,14 +671,13 @@ int flash_physical_protect_at_boot(uint32_t new_flags) return ret; } -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | - EC_FLASH_PROTECT_ALL_NOW; + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | + EC_FLASH_PROTECT_ALL_NOW; } -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { uint32_t ret = 0; @@ -686,7 +690,7 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) * the WP GPIO is asserted. */ if (!(cur_flags & EC_FLASH_PROTECT_ALL_NOW) && - (cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED)) + (cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED)) ret |= EC_FLASH_PROTECT_ALL_NOW; return ret; @@ -695,20 +699,8 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) /*****************************************************************************/ /* High-level APIs */ -int flash_pre_init(void) +int crec_flash_pre_init(void) { - /* - * Protect status registers of internal spi-flash if WP# is active - * during ec initialization. - */ -#ifdef NPCX_INT_FLASH_SUPPORT -#ifdef CONFIG_WP_ACTIVE_HIGH - flash_protect_int_flash(gpio_get_level(GPIO_WP)); -#else - flash_protect_int_flash(!gpio_get_level(GPIO_WP_L)); -#endif /*CONFIG_WP_ACTIVE_HIGH */ -#endif - #if !defined(NPCX_INT_FLASH_SUPPORT) /* Enable FIU interface */ flash_pinmux(1); @@ -721,10 +713,27 @@ int flash_pre_init(void) /* Initialize UMA to unlocked */ flash_uma_lock(0); + + /* + * Disable flash quad enable to avoid /WP pin function is not + * available. */ + flash_set_quad_enable(0); + + /* + * Protect status registers of internal spi-flash if WP# is active + * during ec initialization. + */ +#ifdef NPCX_INT_FLASH_SUPPORT +#ifdef CONFIG_WP_ACTIVE_HIGH + flash_protect_int_flash(gpio_get_level(GPIO_WP)); +#else + flash_protect_int_flash(!gpio_get_level(GPIO_WP_L)); +#endif /*CONFIG_WP_ACTIVE_HIGH */ +#endif return EC_SUCCESS; } -void flash_lock_mapped_storage(int lock) +void crec_flash_lock_mapped_storage(int lock) { if (lock) mutex_lock(&flash_lock); @@ -745,14 +754,12 @@ static enum ec_status flash_command_spi_info(struct host_cmd_handler_args *args) flash_get_jedec_id(r->jedec); r->reserved0 = 0; flash_get_mfr_dev_id(r->mfr_dev_id); - r->sr1 = flash_get_status1(); - r->sr2 = flash_get_status2(); + flash_get_status(&r->sr1, &r->sr2); args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_FLASH_SPI_INFO, - flash_command_spi_info, +DECLARE_HOST_COMMAND(EC_CMD_FLASH_SPI_INFO, flash_command_spi_info, EC_VER_MASK(0)); #endif @@ -780,7 +787,7 @@ static int flash_spi_sel_lock(int enable) /*****************************************************************************/ /* Console commands */ -static int command_flash_spi_sel_lock(int argc, char **argv) +static int command_flash_spi_sel_lock(int argc, const char **argv) { int ena; @@ -793,10 +800,9 @@ static int command_flash_spi_sel_lock(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(flash_spi_lock, command_flash_spi_sel_lock, - "[on | off]", - "Lock spi flash interface selection"); + "[on | off]", "Lock spi flash interface selection"); -static int command_flash_tristate(int argc, char **argv) +static int command_flash_tristate(int argc, const char **argv) { int ena; @@ -809,24 +815,23 @@ static int command_flash_tristate(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(flash_tristate, command_flash_tristate, - "[on | off]", +DECLARE_CONSOLE_COMMAND(flash_tristate, command_flash_tristate, "[on | off]", "Tristate spi flash pins"); #endif /* CONFIG_CMD_FLASH_TRISTATE */ -static int command_flash_chip(int argc, char **argv) +static int command_flash_chip(int argc, const char **argv) { uint8_t jedec_id[3]; + uint8_t sr1, sr2; - ccprintf("Status 1: 0x%02x, Status 2: 0x%02x\n", flash_get_status1(), - flash_get_status2()); + flash_get_status(&sr1, &sr2); + ccprintf("Status 1: 0x%02x, Status 2: 0x%02x\n", sr1, sr2); flash_get_jedec_id(jedec_id); ccprintf("Manufacturer: 0x%02x, DID: 0x%02x%02x\n", jedec_id[0], - jedec_id[1], jedec_id[2]); + jedec_id[1], jedec_id[2]); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(flashchip, command_flash_chip, - NULL, +DECLARE_CONSOLE_COMMAND(flashchip, command_flash_chip, NULL, "Print flash chip info"); diff --git a/chip/npcx/gpio-npcx5.c b/chip/npcx/gpio-npcx5.c index d6a28300ba..2201bb65c2 100644 --- a/chip/npcx/gpio-npcx5.c +++ b/chip/npcx/gpio-npcx5.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -29,7 +29,7 @@ static void gpio_init(void) task_enable_irq(NPCX_IRQ_TWD_WKINTB_0); task_enable_irq(NPCX_IRQ_WKINTA_1); task_enable_irq(NPCX_IRQ_WKINTB_1); -#ifndef HAS_TASK_KEYSCAN +#ifdef NPCX_SELECT_KSI_TO_GPIO task_enable_irq(NPCX_IRQ_KSI_WKINTC_1); #endif task_enable_irq(NPCX_IRQ_WKINTD_1); @@ -48,36 +48,38 @@ DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); * the port, then call the master handler above. */ -#define GPIO_IRQ_FUNC(_irq_func, wui_int) \ -void _irq_func(void) \ -{ \ - gpio_interrupt(wui_int); \ -} +#define GPIO_IRQ_FUNC(_irq_func, wui_int) \ + static void _irq_func(void) \ + { \ + gpio_interrupt(wui_int); \ + } /* If we need to handle the other type interrupts except GPIO, add code here */ -void __gpio_wk0efgh_interrupt(void) +static void __gpio_wk0efgh_interrupt(void) { if (IS_ENABLED(CONFIG_HOSTCMD_X86)) { /* Pending bit 7 or 6 or 5? */ if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6) && - IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 6)) { + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 6)) { /* Disable host wake-up */ CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6); /* Clear pending bit of WUI */ SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_5), 6); return; } - if (IS_ENABLED(CONFIG_HOSTCMD_ESPI)) { - if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 5) - && - IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 5)) { + if (IS_ENABLED(CONFIG_HOST_INTERFACE_ESPI)) { + if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), + 5) && + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), + 5)) { espi_espirst_handler(); return; } } else { - if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 7) - && - IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 7)) { + if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), + 7) && + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), + 7)) { lpc_lreset_pltrst_handler(); return; } @@ -97,7 +99,7 @@ static void set_rtc_host_event(void) DECLARE_DEFERRED(set_rtc_host_event); #endif -void __gpio_rtc_interrupt(void) +static void __gpio_rtc_interrupt(void) { /* Check pending bit 7 */ #ifdef CONFIG_HOSTCMD_RTC @@ -130,7 +132,7 @@ void __gpio_rtc_interrupt(void) gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_4)); } -void __gpio_wk1h_interrupt(void) +static void __gpio_wk1h_interrupt(void) { #if defined(CHIP_FAMILY_NPCX7) && defined(CONFIG_LOW_POWER_IDLE) && \ (CONFIG_CONSOLE_UART == 0) @@ -156,7 +158,7 @@ GPIO_IRQ_FUNC(__gpio_wk0b_interrupt, WUI_INT(MIWU_TABLE_0, MIWU_GROUP_2)); GPIO_IRQ_FUNC(__gpio_wk0c_interrupt, WUI_INT(MIWU_TABLE_0, MIWU_GROUP_3)); GPIO_IRQ_FUNC(__gpio_wk1a_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_1)); GPIO_IRQ_FUNC(__gpio_wk1b_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_2)); -#ifndef HAS_TASK_KEYSCAN +#ifdef NPCX_SELECT_KSI_TO_GPIO /* Declare GPIO irq functions for KSI pins if there's no keyboard scan task, */ GPIO_IRQ_FUNC(__gpio_wk1c_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_3)); #endif @@ -169,30 +171,30 @@ GPIO_IRQ_FUNC(__gpio_wk2fg_interrupt, WUI_INT(MIWU_TABLE_2, MIWU_GROUP_6)); #endif DECLARE_IRQ(NPCX_IRQ_MTC_WKINTAD_0, __gpio_rtc_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_TWD_WKINTB_0, __gpio_wk0b_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTC_0, __gpio_wk0c_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTEFGH_0, __gpio_wk0efgh_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTA_1, __gpio_wk1a_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTB_1, __gpio_wk1b_interrupt, 3); -#ifndef HAS_TASK_KEYSCAN -DECLARE_IRQ(NPCX_IRQ_KSI_WKINTC_1, __gpio_wk1c_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_TWD_WKINTB_0, __gpio_wk0b_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTC_0, __gpio_wk0c_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTEFGH_0, __gpio_wk0efgh_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTA_1, __gpio_wk1a_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTB_1, __gpio_wk1b_interrupt, 3); +#ifdef NPCX_SELECT_KSI_TO_GPIO +DECLARE_IRQ(NPCX_IRQ_KSI_WKINTC_1, __gpio_wk1c_interrupt, 3); #endif -DECLARE_IRQ(NPCX_IRQ_WKINTD_1, __gpio_wk1d_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTE_1, __gpio_wk1e_interrupt, 3); -#ifdef CONFIG_HOSTCMD_SPS +DECLARE_IRQ(NPCX_IRQ_WKINTD_1, __gpio_wk1d_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTE_1, __gpio_wk1e_interrupt, 3); +#ifdef CONFIG_HOST_INTERFACE_SHI /* * HACK: Make CS GPIO P2 to improve SHI reliability. * TODO: Increase CS-assertion-to-transaction-start delay on host to * accommodate P3 CS interrupt. */ -DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 2); +DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 2); #else -DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 3); #endif -DECLARE_IRQ(NPCX_IRQ_WKINTG_1, __gpio_wk1g_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTH_1, __gpio_wk1h_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTG_1, __gpio_wk1g_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTH_1, __gpio_wk1h_interrupt, 3); #if defined(CHIP_FAMILY_NPCX7) -DECLARE_IRQ(NPCX_IRQ_WKINTFG_2, __gpio_wk2fg_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTFG_2, __gpio_wk2fg_interrupt, 3); #endif #undef GPIO_IRQ_FUNC diff --git a/chip/npcx/gpio-npcx7.c b/chip/npcx/gpio-npcx7.c deleted file mode 120000 index 39b939f44c..0000000000 --- a/chip/npcx/gpio-npcx7.c +++ /dev/null @@ -1 +0,0 @@ -gpio-npcx5.c \ No newline at end of file diff --git a/chip/npcx/gpio-npcx7.c b/chip/npcx/gpio-npcx7.c new file mode 100644 index 0000000000..2201bb65c2 --- /dev/null +++ b/chip/npcx/gpio-npcx7.c @@ -0,0 +1,200 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* GPIO module for Chrome EC */ + +#include "clock.h" +#include "common.h" +#include "ec_commands.h" +#include "gpio_chip.h" +#include "hooks.h" +#include "host_command.h" +#include "lpc_chip.h" +#include "registers.h" +#include "task.h" + +/* + * List of GPIO IRQs to enable. Don't automatically enable interrupts for + * the keyboard input GPIO bank - that's handled separately. Of course the + * bank is different for different systems. + */ +static void gpio_init(void) +{ + /* Enable IRQs now that pins are set up */ + task_enable_irq(NPCX_IRQ_MTC_WKINTAD_0); + task_enable_irq(NPCX_IRQ_WKINTEFGH_0); + task_enable_irq(NPCX_IRQ_WKINTC_0); + task_enable_irq(NPCX_IRQ_TWD_WKINTB_0); + task_enable_irq(NPCX_IRQ_WKINTA_1); + task_enable_irq(NPCX_IRQ_WKINTB_1); +#ifdef NPCX_SELECT_KSI_TO_GPIO + task_enable_irq(NPCX_IRQ_KSI_WKINTC_1); +#endif + task_enable_irq(NPCX_IRQ_WKINTD_1); + task_enable_irq(NPCX_IRQ_WKINTE_1); + task_enable_irq(NPCX_IRQ_WKINTF_1); + task_enable_irq(NPCX_IRQ_WKINTG_1); + task_enable_irq(NPCX_IRQ_WKINTH_1); +#if defined(CHIP_FAMILY_NPCX7) + task_enable_irq(NPCX_IRQ_WKINTFG_2); +#endif +} +DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); + +/** + * Handlers for each GPIO port. These read and clear the interrupt bits for + * the port, then call the master handler above. + */ + +#define GPIO_IRQ_FUNC(_irq_func, wui_int) \ + static void _irq_func(void) \ + { \ + gpio_interrupt(wui_int); \ + } + +/* If we need to handle the other type interrupts except GPIO, add code here */ +static void __gpio_wk0efgh_interrupt(void) +{ + if (IS_ENABLED(CONFIG_HOSTCMD_X86)) { + /* Pending bit 7 or 6 or 5? */ + if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6) && + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 6)) { + /* Disable host wake-up */ + CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6); + /* Clear pending bit of WUI */ + SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_5), 6); + return; + } + if (IS_ENABLED(CONFIG_HOST_INTERFACE_ESPI)) { + if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), + 5) && + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), + 5)) { + espi_espirst_handler(); + return; + } + } else { + if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), + 7) && + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), + 7)) { + lpc_lreset_pltrst_handler(); + return; + } + } + } + gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_5)); + gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_6)); + gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_7)); + gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_8)); +} + +#ifdef CONFIG_HOSTCMD_RTC +static void set_rtc_host_event(void) +{ + host_set_single_event(EC_HOST_EVENT_RTC); +} +DECLARE_DEFERRED(set_rtc_host_event); +#endif + +static void __gpio_rtc_interrupt(void) +{ + /* Check pending bit 7 */ +#ifdef CONFIG_HOSTCMD_RTC + if (NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_4) & 0x80) { + /* Clear pending bit for WUI */ + SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_4), 7); + hook_call_deferred(&set_rtc_host_event_data, 0); + return; + } +#endif +#if defined(CHIP_FAMILY_NPCX7) && defined(CONFIG_LOW_POWER_IDLE) && \ + (CONFIG_CONSOLE_UART == 1) + /* Handle the interrupt from UART wakeup event */ + if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_1), 6) && + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_1), 6)) { + /* + * Disable WKEN bit to avoid the other unnecessary interrupts + * from the coming data bits after the start bit. (Pending bit + * of CR_SIN is set when a high-to-low transaction occurs.) + */ + CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_1), 6); + /* Clear pending bit for WUI */ + SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_1), 6); + /* Notify the clock module that the console is in use. */ + clock_refresh_console_in_use(); + return; + } +#endif + gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_1)); + gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_4)); +} + +static void __gpio_wk1h_interrupt(void) +{ +#if defined(CHIP_FAMILY_NPCX7) && defined(CONFIG_LOW_POWER_IDLE) && \ + (CONFIG_CONSOLE_UART == 0) + /* Handle the interrupt from UART wakeup event */ + if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_1, MIWU_GROUP_8), 7) && + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_1, MIWU_GROUP_8), 7)) { + /* + * Disable WKEN bit to avoid the other unnecessary interrupts + * from the coming data bits after the start bit. (Pending bit + * of CR_SIN is set when a high-to-low transaction occurs.) + */ + CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_1, MIWU_GROUP_8), 7); + /* Clear pending bit for WUI */ + SET_BIT(NPCX_WKPCL(MIWU_TABLE_1, MIWU_GROUP_8), 7); + /* Notify the clock module that the console is in use. */ + clock_refresh_console_in_use(); + } else +#endif + gpio_interrupt(WUI_INT(MIWU_TABLE_1, MIWU_GROUP_8)); +} + +GPIO_IRQ_FUNC(__gpio_wk0b_interrupt, WUI_INT(MIWU_TABLE_0, MIWU_GROUP_2)); +GPIO_IRQ_FUNC(__gpio_wk0c_interrupt, WUI_INT(MIWU_TABLE_0, MIWU_GROUP_3)); +GPIO_IRQ_FUNC(__gpio_wk1a_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_1)); +GPIO_IRQ_FUNC(__gpio_wk1b_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_2)); +#ifdef NPCX_SELECT_KSI_TO_GPIO +/* Declare GPIO irq functions for KSI pins if there's no keyboard scan task, */ +GPIO_IRQ_FUNC(__gpio_wk1c_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_3)); +#endif +GPIO_IRQ_FUNC(__gpio_wk1d_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_4)); +GPIO_IRQ_FUNC(__gpio_wk1e_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_5)); +GPIO_IRQ_FUNC(__gpio_wk1f_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_6)); +GPIO_IRQ_FUNC(__gpio_wk1g_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_7)); +#if defined(CHIP_FAMILY_NPCX7) +GPIO_IRQ_FUNC(__gpio_wk2fg_interrupt, WUI_INT(MIWU_TABLE_2, MIWU_GROUP_6)); +#endif + +DECLARE_IRQ(NPCX_IRQ_MTC_WKINTAD_0, __gpio_rtc_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_TWD_WKINTB_0, __gpio_wk0b_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTC_0, __gpio_wk0c_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTEFGH_0, __gpio_wk0efgh_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTA_1, __gpio_wk1a_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTB_1, __gpio_wk1b_interrupt, 3); +#ifdef NPCX_SELECT_KSI_TO_GPIO +DECLARE_IRQ(NPCX_IRQ_KSI_WKINTC_1, __gpio_wk1c_interrupt, 3); +#endif +DECLARE_IRQ(NPCX_IRQ_WKINTD_1, __gpio_wk1d_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTE_1, __gpio_wk1e_interrupt, 3); +#ifdef CONFIG_HOST_INTERFACE_SHI +/* + * HACK: Make CS GPIO P2 to improve SHI reliability. + * TODO: Increase CS-assertion-to-transaction-start delay on host to + * accommodate P3 CS interrupt. + */ +DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 2); +#else +DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 3); +#endif +DECLARE_IRQ(NPCX_IRQ_WKINTG_1, __gpio_wk1g_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTH_1, __gpio_wk1h_interrupt, 3); +#if defined(CHIP_FAMILY_NPCX7) +DECLARE_IRQ(NPCX_IRQ_WKINTFG_2, __gpio_wk2fg_interrupt, 3); +#endif + +#undef GPIO_IRQ_FUNC diff --git a/chip/npcx/gpio-npcx9.c b/chip/npcx/gpio-npcx9.c index 441924d89e..3a7378083c 100644 --- a/chip/npcx/gpio-npcx9.c +++ b/chip/npcx/gpio-npcx9.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -34,7 +34,7 @@ static void gpio_init(void) task_enable_irq(NPCX_IRQ_WKINTH_0); task_enable_irq(NPCX_IRQ_WKINTA_1); task_enable_irq(NPCX_IRQ_WKINTB_1); -#ifndef HAS_TASK_KEYSCAN +#ifdef NPCX_SELECT_KSI_TO_GPIO task_enable_irq(NPCX_IRQ_KSI_WKINTC_1); #endif task_enable_irq(NPCX_IRQ_WKINTD_1); @@ -51,36 +51,38 @@ DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); * the port, then call the master handler above. */ -#define GPIO_IRQ_FUNC(_irq_func, wui_int) \ -void _irq_func(void) \ -{ \ - gpio_interrupt(wui_int); \ -} +#define GPIO_IRQ_FUNC(_irq_func, wui_int) \ + static void _irq_func(void) \ + { \ + gpio_interrupt(wui_int); \ + } /* If we need to handle the other type interrupts except GPIO, add code here */ -void __gpio_host_interrupt(void) +static void __gpio_host_interrupt(void) { if (IS_ENABLED(CONFIG_HOSTCMD_X86)) { /* Pending bit 7 or 6 or 5? */ if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6) && - IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 6)) { + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 6)) { /* Disable host wake-up */ CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6); /* Clear pending bit of WUI */ SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_5), 6); return; } - if (IS_ENABLED(CONFIG_HOSTCMD_ESPI)) { - if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 5) - && - IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 5)) { + if (IS_ENABLED(CONFIG_HOST_INTERFACE_ESPI)) { + if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), + 5) && + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), + 5)) { espi_espirst_handler(); return; } } else { - if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 7) - && - IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 7)) { + if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), + 7) && + IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), + 7)) { lpc_lreset_pltrst_handler(); return; } @@ -97,7 +99,7 @@ static void set_rtc_host_event(void) DECLARE_DEFERRED(set_rtc_host_event); #endif -void __gpio_rtc_interrupt(void) +static void __gpio_rtc_interrupt(void) { /* Check pending bit 7 */ #ifdef CONFIG_HOSTCMD_RTC @@ -110,7 +112,7 @@ void __gpio_rtc_interrupt(void) #endif gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_4)); } -void __gpio_cr_sin2_interrupt(void) +static void __gpio_cr_sin2_interrupt(void) { #if defined(CONFIG_LOW_POWER_IDLE) && (CONFIG_CONSOLE_UART == 1) /* Handle the interrupt from UART wakeup event */ @@ -130,10 +132,9 @@ void __gpio_cr_sin2_interrupt(void) } #endif gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_1)); - } -void __gpio_wk1h_interrupt(void) +static void __gpio_wk1h_interrupt(void) { #if defined(CONFIG_LOW_POWER_IDLE) && (CONFIG_CONSOLE_UART == 0) /* Handle the interrupt from UART wakeup event */ @@ -154,7 +155,7 @@ void __gpio_wk1h_interrupt(void) gpio_interrupt(WUI_INT(MIWU_TABLE_1, MIWU_GROUP_8)); } -void __gpio_lct_interrupt(void) +static void __gpio_lct_interrupt(void) { if (NPCX_WKPND(MIWU_TABLE_2, MIWU_GROUP_6) & LCT_WUI_MASK) { NPCX_WKPCL(MIWU_TABLE_2, MIWU_GROUP_6) |= LCT_WUI_MASK; @@ -171,7 +172,7 @@ GPIO_IRQ_FUNC(__gpio_wk0g_interrupt, WUI_INT(MIWU_TABLE_0, MIWU_GROUP_7)); GPIO_IRQ_FUNC(__gpio_wk0h_interrupt, WUI_INT(MIWU_TABLE_0, MIWU_GROUP_8)); GPIO_IRQ_FUNC(__gpio_wk1a_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_1)); GPIO_IRQ_FUNC(__gpio_wk1b_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_2)); -#ifndef HAS_TASK_KEYSCAN +#ifdef NPCX_SELECT_KSI_TO_GPIO /* Declare GPIO irq functions for KSI pins if there's no keyboard scan task, */ GPIO_IRQ_FUNC(__gpio_wk1c_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_3)); #endif @@ -179,35 +180,35 @@ GPIO_IRQ_FUNC(__gpio_wk1d_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_4)); GPIO_IRQ_FUNC(__gpio_wk1e_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_5)); GPIO_IRQ_FUNC(__gpio_wk1f_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_6)); GPIO_IRQ_FUNC(__gpio_wk1g_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_7)); -GPIO_IRQ_FUNC(__gpio_wk2fg_interrupt, WUI_INT(MIWU_TABLE_2, MIWU_GROUP_6)); -DECLARE_IRQ(NPCX_IRQ_CR_SIN2_WKINTA_0, __gpio_cr_sin2_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_TWD_WKINTB_0, __gpio_wk0b_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTC_0, __gpio_wk0c_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_MTC_WKINTD_0, __gpio_rtc_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTE_0, __gpio_host_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTF_0, __gpio_wk0f_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTG_0, __gpio_wk0g_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTH_0, __gpio_wk0h_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTA_1, __gpio_wk1a_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTB_1, __gpio_wk1b_interrupt, 3); -#ifndef HAS_TASK_KEYSCAN -DECLARE_IRQ(NPCX_IRQ_KSI_WKINTC_1, __gpio_wk1c_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_CR_SIN2_WKINTA_0, __gpio_cr_sin2_interrupt, + NPCX_MIWU0_GROUP_A); +DECLARE_IRQ(NPCX_IRQ_TWD_WKINTB_0, __gpio_wk0b_interrupt, NPCX_MIWU0_GROUP_B); +DECLARE_IRQ(NPCX_IRQ_WKINTC_0, __gpio_wk0c_interrupt, NPCX_MIWU0_GROUP_C); +DECLARE_IRQ(NPCX_IRQ_MTC_WKINTD_0, __gpio_rtc_interrupt, NPCX_MIWU0_GROUP_D); +DECLARE_IRQ(NPCX_IRQ_WKINTE_0, __gpio_host_interrupt, NPCX_MIWU0_GROUP_E); +DECLARE_IRQ(NPCX_IRQ_WKINTF_0, __gpio_wk0f_interrupt, NPCX_MIWU0_GROUP_F); +DECLARE_IRQ(NPCX_IRQ_WKINTG_0, __gpio_wk0g_interrupt, NPCX_MIWU0_GROUP_G); +DECLARE_IRQ(NPCX_IRQ_WKINTH_0, __gpio_wk0h_interrupt, NPCX_MIWU0_GROUP_H); +DECLARE_IRQ(NPCX_IRQ_WKINTA_1, __gpio_wk1a_interrupt, NPCX_MIWU1_GROUP_A); +DECLARE_IRQ(NPCX_IRQ_WKINTB_1, __gpio_wk1b_interrupt, NPCX_MIWU1_GROUP_B); +#ifdef NPCX_SELECT_KSI_TO_GPIO +DECLARE_IRQ(NPCX_IRQ_KSI_WKINTC_1, __gpio_wk1c_interrupt, NPCX_MIWU1_GROUP_C); #endif -DECLARE_IRQ(NPCX_IRQ_WKINTD_1, __gpio_wk1d_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTE_1, __gpio_wk1e_interrupt, 3); -#ifdef CONFIG_HOSTCMD_SPS +DECLARE_IRQ(NPCX_IRQ_WKINTD_1, __gpio_wk1d_interrupt, NPCX_MIWU1_GROUP_D); +DECLARE_IRQ(NPCX_IRQ_WKINTE_1, __gpio_wk1e_interrupt, NPCX_MIWU1_GROUP_E); +#ifdef CONFIG_HOST_INTERFACE_SHI /* * HACK: Make CS GPIO P2 to improve SHI reliability. * TODO: Increase CS-assertion-to-transaction-start delay on host to * accommodate P3 CS interrupt. */ -DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 2); +DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 2); #else -DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, NPCX_MIWU1_GROUP_F); #endif -DECLARE_IRQ(NPCX_IRQ_WKINTG_1, __gpio_wk1g_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_WKINTH_1, __gpio_wk1h_interrupt, 3); -DECLARE_IRQ(NPCX_IRQ_LCT_WKINTF_2, __gpio_lct_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_WKINTG_1, __gpio_wk1g_interrupt, NPCX_MIWU1_GROUP_G); +DECLARE_IRQ(NPCX_IRQ_WKINTH_1, __gpio_wk1h_interrupt, NPCX_MIWU1_GROUP_H); +DECLARE_IRQ(NPCX_IRQ_LCT_WKINTF_2, __gpio_lct_interrupt, 3); #undef GPIO_IRQ_FUNC diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c index 75c8142d63..a976b3b122 100644 --- a/chip/npcx/gpio.c +++ b/chip/npcx/gpio.c @@ -1,31 +1,32 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* GPIO module for Chrome EC */ +#include "builtin/assert.h" #include "common.h" +#include "ec_commands.h" #include "gpio.h" #include "gpio_chip.h" -#include "i2c.h" #include "hooks.h" +#include "host_command.h" +#include "hwtimer_chip.h" +#include "i2c.h" #include "registers.h" +#include "system.h" +#include "system_chip.h" #include "task.h" #include "timer.h" #include "util.h" -#include "system.h" -#include "system_chip.h" -#include "ec_commands.h" -#include "host_command.h" -#include "hwtimer_chip.h" #if !(DEBUG_GPIO) #define CPUTS(...) #define CPRINTS(...) #else #define CPUTS(outstr) cputs(CC_GPIO, outstr) -#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args) +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) #endif /* Constants for GPIO interrupt mapping */ @@ -40,12 +41,12 @@ #define UNIMPLEMENTED(name) #endif static const struct npcx_wui gpio_wui_table[] = { - #include "gpio.wrap" +#include "gpio.wrap" }; struct npcx_gpio { - uint8_t port : 4; - uint8_t bit : 3; + uint8_t port : 4; + uint8_t bit : 3; uint8_t valid : 1; }; @@ -54,21 +55,21 @@ BUILD_ASSERT(sizeof(struct npcx_gpio) == 1); #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 struct npcx_alt { uint8_t group; - uint8_t bit : 3; - uint8_t inverted : 1; - uint8_t reserved : 4; + uint8_t bit : 3; + uint8_t inverted : 1; + uint8_t reserved : 4; }; #else struct npcx_alt { - uint8_t group : 4; - uint8_t bit : 3; - uint8_t inverted : 1; + uint8_t group : 4; + uint8_t bit : 3; + uint8_t inverted : 1; }; #endif struct gpio_alt_map { struct npcx_gpio gpio; - struct npcx_alt alt; + struct npcx_alt alt; }; #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 @@ -78,7 +79,7 @@ BUILD_ASSERT(sizeof(struct gpio_alt_map) == 2); #endif /* Constants for GPIO alternative mapping */ -const struct gpio_alt_map gpio_alt_table[] = NPCX_ALT_TABLE; +const __const_data struct gpio_alt_map gpio_alt_table[] = NPCX_ALT_TABLE; struct gpio_lvol_item { struct npcx_gpio lvol_gpio[8]; @@ -101,8 +102,7 @@ static uint8_t gpio_is_alt_sel(uint8_t port, uint8_t bit) struct gpio_alt_map const *map; uint8_t alt_mask, devalt; - for (map = ARRAY_BEGIN(gpio_alt_table); - map < ARRAY_END(gpio_alt_table); + for (map = ARRAY_BEGIN(gpio_alt_table); map < ARRAY_END(gpio_alt_table); map++) { if (gpio_match(port, bit, map->gpio)) { alt_mask = 1 << map->alt.bit; @@ -127,8 +127,7 @@ static int gpio_alt_sel(uint8_t port, uint8_t bit, { struct gpio_alt_map const *map; - for (map = ARRAY_BEGIN(gpio_alt_table); - map < ARRAY_END(gpio_alt_table); + for (map = ARRAY_BEGIN(gpio_alt_table); map < ARRAY_END(gpio_alt_table); map++) { if (gpio_match(port, bit, map->gpio)) { uint8_t alt_mask = 1 << map->alt.bit; @@ -140,7 +139,7 @@ static int gpio_alt_sel(uint8_t port, uint8_t bit, if ((func < GPIO_ALT_FUNC_DEFAULT) ^ map->alt.inverted) NPCX_DEVALT(map->alt.group) &= ~alt_mask; else - NPCX_DEVALT(map->alt.group) |= alt_mask; + NPCX_DEVALT(map->alt.group) |= alt_mask; return 1; } @@ -183,7 +182,7 @@ static void gpio_interrupt_type_sel(enum gpio_signal signal, uint32_t flags) NPCX_WKMOD(table, group) &= ~pmask; /* Handle interrupting on both edges */ if ((flags & GPIO_INT_F_RISING) && - (flags & GPIO_INT_F_FALLING)) { + (flags & GPIO_INT_F_FALLING)) { /* Enable any edge */ NPCX_WKAEDG(table, group) |= pmask; } @@ -252,7 +251,7 @@ void gpio_low_voltage_level_sel(uint8_t port, uint8_t bit, uint8_t low_voltage) if (low_voltage) CPRINTS("Warn! No low voltage support in port:0x%x, bit:%d", - port, bit); + port, bit); } /* Set the low voltage detection level by mask */ @@ -290,7 +289,7 @@ static void gpio_enable_wake_up_input(enum gpio_signal signal, int enable) SET_BIT(NPCX_WKINEN(wui->table, wui->group), wui->bit); else CLEAR_BIT(NPCX_WKINEN(wui->table, wui->group), - wui->bit); + wui->bit); } } @@ -317,9 +316,9 @@ BUILD_ASSERT(ARRAY_SIZE(gpio_lvol_table[0].lvol_gpio) == 8); /* IC specific low-level driver */ void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) + enum gpio_alternate_func func) { - /* Enable alternative pins by func*/ + /* Enable alternative pins by func */ int pin; /* check each bit from mask */ @@ -340,7 +339,7 @@ void gpio_set_level(enum gpio_signal signal, int value) ASSERT(signal_is_gpio(signal)); if (value) - NPCX_PDOUT(gpio_list[signal].port) |= gpio_list[signal].mask; + NPCX_PDOUT(gpio_list[signal].port) |= gpio_list[signal].mask; else NPCX_PDOUT(gpio_list[signal].port) &= ~gpio_list[signal].mask; } @@ -355,10 +354,12 @@ int gpio_get_flags_by_mask(uint32_t port, uint32_t mask) else flags |= GPIO_INPUT; - if (NPCX_PDIN(port) & mask) - flags |= GPIO_HIGH; - else - flags |= GPIO_LOW; + if (flags & GPIO_OUTPUT) { + if (NPCX_PDOUT(port) & mask) + flags |= GPIO_HIGH; + else + flags |= GPIO_LOW; + } if (NPCX_PTYPE(port) & mask) flags |= GPIO_OPEN_DRAIN; @@ -410,14 +411,14 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) if (flags & GPIO_PULL_UP) { if (flags & GPIO_SEL_1P8V) { CPRINTS("Warn! enable internal PU and low voltage mode" - " at the same time is illegal. port 0x%x, mask 0x%x", - port, mask); + " at the same time is illegal. port 0x%x, mask 0x%x", + port, mask); } else { - NPCX_PPUD(port) &= ~mask; + NPCX_PPUD(port) &= ~mask; NPCX_PPULL(port) |= mask; /* enable pull down/up */ } } else if (flags & GPIO_PULL_DOWN) { - NPCX_PPUD(port) |= mask; + NPCX_PPUD(port) |= mask; NPCX_PPULL(port) |= mask; /* enable pull down/up */ } else { /* No pull up/down */ @@ -455,7 +456,7 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) if (flags & GPIO_OUTPUT) NPCX_PDIR(port) |= mask; - /* Lock GPIO output and configuration if need */ + /* Lock GPIO output and configuration if need */ #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 if (flags & GPIO_LOCKED) NPCX_PLOCK_CTL(port) |= mask; @@ -508,6 +509,7 @@ int gpio_clear_pending_interrupt(enum gpio_signal signal) void gpio_pre_init(void) { const struct gpio_info *g = gpio_list; + const struct unused_pin_info *u = unused_pin_list; int is_warm; int flags; int i, j; @@ -559,7 +561,7 @@ void gpio_pre_init(void) #endif /* Pin_Mux for LPC & SHI */ -#ifdef CONFIG_HOSTCMD_SPS +#ifdef CONFIG_HOST_INTERFACE_SHI /* Switching to eSPI mode for SHI interface */ NPCX_DEVCNT |= 0x08; /* Alternate Intel bus interface LPC/eSPI to GPIOs first */ @@ -597,7 +599,7 @@ void gpio_pre_init(void) * which may or may not be as a GPIO. */ gpio_set_alternate_function(g->port, g->mask, - GPIO_ALT_FUNC_NONE); + GPIO_ALT_FUNC_NONE); } /* The bypass of low voltage IOs for better power consumption */ @@ -614,6 +616,14 @@ void gpio_pre_init(void) gpio_enable_wake_up_input(i, 0); } #endif + + /* Configure unused pins as GPIO INPUT with PU to save power. */ + for (i = 0; i < unused_pin_count; i++, u++) { + gpio_set_flags_by_mask(u->port, u->mask, + GPIO_INPUT | GPIO_PULL_UP); + gpio_set_alternate_function(g->port, g->mask, + GPIO_ALT_FUNC_NONE); + } } /*****************************************************************************/ @@ -640,8 +650,8 @@ void gpio_interrupt(struct npcx_wui wui_int) uint8_t pin_mask = 1 << gpio_wui_table[i].bit; if ((gpio_wui_table[i].table == table) && - (gpio_wui_table[i].group == group) && - (wui_mask & pin_mask)) { + (gpio_wui_table[i].group == group) && + (wui_mask & pin_mask)) { /* Clear pending bit of GPIO */ NPCX_WKPCL(table, group) = pin_mask; /* Execute GPIO's ISR */ @@ -662,7 +672,7 @@ void gpio_interrupt(struct npcx_wui wui_int) * Command used to disable input buffer of gpios one by one to * investigate power consumption */ -static int command_gpiodisable(int argc, char **argv) +static int command_gpiodisable(int argc, const char **argv) { uint8_t i; uint8_t offset; @@ -682,7 +692,7 @@ static int command_gpiodisable(int argc, char **argv) ccprintf("Total GPIO declaration: %d\n", GPIO_COUNT); ccprintf("Total Non-ISR GPIO declaration: %d\n", - non_isr_gpio_num); + non_isr_gpio_num); ccprintf("Next GPIO Num to check by "); ccprintf("\"gpiodisable next\"\n"); ccprintf(" offset: %d\n", offset); @@ -705,8 +715,8 @@ static int command_gpiodisable(int argc, char **argv) offset = idx + GPIO_IH_COUNT; g_list = gpio_list + offset; flags = g_list->flags; - ccprintf("current GPIO : %d %s --> ", - offset, g_list->name); + ccprintf("current GPIO : %d %s --> ", offset, + g_list->name); if (gpio_is_i2c_pin(offset)) { ccprintf("Ignore I2C pin!\n"); idx++; @@ -717,10 +727,10 @@ static int command_gpiodisable(int argc, char **argv) continue; } else { if ((flags & GPIO_INPUT) || - (flags & GPIO_OPEN_DRAIN)) { + (flags & GPIO_OPEN_DRAIN)) { ccprintf("Disable WKINEN!\n"); gpio_enable_wake_up_input( - offset, 0); + offset, 0); idx++; break; } @@ -750,7 +760,7 @@ static int command_gpiodisable(int argc, char **argv) } return EC_ERROR_INVAL; } -DECLARE_CONSOLE_COMMAND(gpiodisable, command_gpiodisable, - "info/list/next/ on|off", - "Disable GPIO input buffer to investigate power consumption"); +DECLARE_CONSOLE_COMMAND( + gpiodisable, command_gpiodisable, "info/list/next/ on|off", + "Disable GPIO input buffer to investigate power consumption"); #endif diff --git a/chip/npcx/gpio_chip-npcx5.h b/chip/npcx/gpio_chip-npcx5.h index ee113aea44..81ef957236 100644 --- a/chip/npcx/gpio_chip-npcx5.h +++ b/chip/npcx/gpio_chip-npcx5.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -206,7 +206,7 @@ /* MFT Module */ #define NPCX_ALT_GPIO_9_3 ALT(9, 3, NPCX_ALT(C, TA1_SL2)) /* TA1_SEL2 */ -#ifdef CONFIG_PS2 +#if defined(CONFIG_PS2) && defined(NPCX_PS2_MODULE_3) #define NPCX_ALT_GPIO_A_6 ALT(A, 6, NPCX_ALT(C, PS2_3_SL2)) /* PS2_CLK3 */ #else #define NPCX_ALT_GPIO_A_6 ALT(A, 6, NPCX_ALT(C, TA2_SL2)) /* TA2_SEL2 */ @@ -245,7 +245,7 @@ #define NPCX_ALT_GPIO_B_1 ALT(B, 1, NPCX_ALT_INV(A, NO_KSO17_SL)) /* KSO17 */ /* Clock module */ -#define NPCX_ALT_GPIO_7_5 ALT(7, 5, NPCX_ALT(A, 32K_OUT_SL)) /* 32KHZ_OUT */ +#define NPCX_ALT_GPIO_7_5 ALT(7, 5, NPCX_ALT(A, 32K_OUT_SL)) /* 32KHZ_OUT */ #define NPCX_ALT_GPIO_E_7 ALT(E, 7, NPCX_ALT(A, 32KCLKIN_SL)) /* 32KCLKIN */ /* PS/2 module */ @@ -255,8 +255,13 @@ #define NPCX_ALT_GPIO_6_3 ALT(6, 3, NPCX_ALT(3, PS2_1_SL)) /* PS2_DATA1 */ #define NPCX_ALT_GPIO_3_7 ALT(3, 7, NPCX_ALT(3, PS2_2_SL)) /* PS2_CLK2 */ #define NPCX_ALT_GPIO_3_4 ALT(3, 4, NPCX_ALT(3, PS2_2_SL)) /* PS2_DATA2 */ +#if defined(CONFIG_PS2) && defined(NPCX_PS2_MODULE_3) #define NPCX_ALT_GPIO_A_7 ALT(A, 7, NPCX_ALT(C, PS2_3_SL2)) /* PS2_DAT3 */ +#else +#define NPCX_ALT_GPIO_A_7 +#endif +/* clang-format off */ #define NPCX_ALT_TABLE { \ NPCX_ALT_GPIO_0_3 /* KSO16 */ \ NPCX_ALT_GPIO_0_4 /* KSO13 */ \ @@ -327,54 +332,66 @@ NPCX_ALT_GPIO_D_1 /* SMB3SCL */ \ NPCX_ALT_GPIO_E_7 /* 32KCLKIN */ \ } +/* clang-format on */ /*****************************************************************************/ /* Macro functions for Low-Voltage mapping table */ /* Low-Voltage GPIO Control 0 */ -#define NPCX_LVOL_CTRL_0_0 NPCX_GPIO(B, 5) -#define NPCX_LVOL_CTRL_0_1 NPCX_GPIO(B, 4) -#define NPCX_LVOL_CTRL_0_2 NPCX_GPIO(B, 3) -#define NPCX_LVOL_CTRL_0_3 NPCX_GPIO(B, 2) -#define NPCX_LVOL_CTRL_0_4 NPCX_GPIO(9, 0) -#define NPCX_LVOL_CTRL_0_5 NPCX_GPIO(8, 7) -#define NPCX_LVOL_CTRL_0_6 NPCX_GPIO(0, 0) -#define NPCX_LVOL_CTRL_0_7 NPCX_GPIO(3, 3) +#define NPCX_LVOL_CTRL_0_0 NPCX_GPIO(B, 5) +#define NPCX_LVOL_CTRL_0_1 NPCX_GPIO(B, 4) +#define NPCX_LVOL_CTRL_0_2 NPCX_GPIO(B, 3) +#define NPCX_LVOL_CTRL_0_3 NPCX_GPIO(B, 2) +#define NPCX_LVOL_CTRL_0_4 NPCX_GPIO(9, 0) +#define NPCX_LVOL_CTRL_0_5 NPCX_GPIO(8, 7) +#define NPCX_LVOL_CTRL_0_6 NPCX_GPIO(0, 0) +#define NPCX_LVOL_CTRL_0_7 NPCX_GPIO(3, 3) /* Low-Voltage GPIO Control 1 */ -#define NPCX_LVOL_CTRL_1_0 NPCX_GPIO(9, 2) -#define NPCX_LVOL_CTRL_1_1 NPCX_GPIO(9, 1) -#define NPCX_LVOL_CTRL_1_2 NPCX_GPIO(D, 1) -#define NPCX_LVOL_CTRL_1_3 NPCX_GPIO(D, 0) -#define NPCX_LVOL_CTRL_1_4 NPCX_GPIO(3, 6) -#define NPCX_LVOL_CTRL_1_5 NPCX_GPIO(6, 4) -#define NPCX_LVOL_CTRL_1_6 NPCX_GPIO(6, 5) -#define NPCX_LVOL_CTRL_1_7 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_1_0 NPCX_GPIO(9, 2) +#define NPCX_LVOL_CTRL_1_1 NPCX_GPIO(9, 1) +#define NPCX_LVOL_CTRL_1_2 NPCX_GPIO(D, 1) +#define NPCX_LVOL_CTRL_1_3 NPCX_GPIO(D, 0) +#define NPCX_LVOL_CTRL_1_4 NPCX_GPIO(3, 6) +#define NPCX_LVOL_CTRL_1_5 NPCX_GPIO(6, 4) +#define NPCX_LVOL_CTRL_1_6 NPCX_GPIO(6, 5) +#define NPCX_LVOL_CTRL_1_7 NPCX_GPIO_NONE /* Low-Voltage GPIO Control 2 */ -#define NPCX_LVOL_CTRL_2_0 NPCX_GPIO(7, 4) -#define NPCX_LVOL_CTRL_2_1 NPCX_GPIO(8, 4) -#define NPCX_LVOL_CTRL_2_2 NPCX_GPIO(8, 5) -#define NPCX_LVOL_CTRL_2_3 NPCX_GPIO(7, 3) -#define NPCX_LVOL_CTRL_2_4 NPCX_GPIO(C, 1) -#define NPCX_LVOL_CTRL_2_5 NPCX_GPIO(C, 7) -#define NPCX_LVOL_CTRL_2_6 NPCX_GPIO(E, 7) -#define NPCX_LVOL_CTRL_2_7 NPCX_GPIO(3, 4) +#define NPCX_LVOL_CTRL_2_0 NPCX_GPIO(7, 4) +#define NPCX_LVOL_CTRL_2_1 NPCX_GPIO(8, 4) +#define NPCX_LVOL_CTRL_2_2 NPCX_GPIO(8, 5) +#define NPCX_LVOL_CTRL_2_3 NPCX_GPIO(7, 3) +#define NPCX_LVOL_CTRL_2_4 NPCX_GPIO(C, 1) +#define NPCX_LVOL_CTRL_2_5 NPCX_GPIO(C, 7) +#define NPCX_LVOL_CTRL_2_6 NPCX_GPIO(E, 7) +#define NPCX_LVOL_CTRL_2_7 NPCX_GPIO(3, 4) /* Low-Voltage GPIO Control 3 */ -#define NPCX_LVOL_CTRL_3_0 NPCX_GPIO(C, 6) -#define NPCX_LVOL_CTRL_3_1 NPCX_GPIO(3, 7) -#define NPCX_LVOL_CTRL_3_2 NPCX_GPIO(4, 0) -#define NPCX_LVOL_CTRL_3_3 NPCX_GPIO(7, 1) -#define NPCX_LVOL_CTRL_3_4 NPCX_GPIO(8, 2) -#define NPCX_LVOL_CTRL_3_5 NPCX_GPIO(7, 5) -#define NPCX_LVOL_CTRL_3_6 NPCX_GPIO(8, 0) -#define NPCX_LVOL_CTRL_3_7 NPCX_GPIO(C, 5) +#define NPCX_LVOL_CTRL_3_0 NPCX_GPIO(C, 6) +#define NPCX_LVOL_CTRL_3_1 NPCX_GPIO(3, 7) +#define NPCX_LVOL_CTRL_3_2 NPCX_GPIO(4, 0) +#define NPCX_LVOL_CTRL_3_3 NPCX_GPIO(7, 1) +#define NPCX_LVOL_CTRL_3_4 NPCX_GPIO(8, 2) +#define NPCX_LVOL_CTRL_3_5 NPCX_GPIO(7, 5) +#define NPCX_LVOL_CTRL_3_6 NPCX_GPIO(8, 0) +#define NPCX_LVOL_CTRL_3_7 NPCX_GPIO(C, 5) /* 4 Low-Voltage Control Groups on npcx5 */ -#define NPCX_LVOL_TABLE { { NPCX_LVOL_CTRL_ITEMS(0), }, \ - { NPCX_LVOL_CTRL_ITEMS(1), }, \ - { NPCX_LVOL_CTRL_ITEMS(2), }, \ - { NPCX_LVOL_CTRL_ITEMS(3), }, } +#define NPCX_LVOL_TABLE \ + { \ + { \ + NPCX_LVOL_CTRL_ITEMS(0), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(1), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(2), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(3), \ + }, \ + } #endif /* __CROS_EC_GPIO_CHIP_NPCX5_H */ diff --git a/chip/npcx/gpio_chip-npcx7.h b/chip/npcx/gpio_chip-npcx7.h index 2f6337d896..39654bc09e 100644 --- a/chip/npcx/gpio_chip-npcx7.h +++ b/chip/npcx/gpio_chip-npcx7.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -82,7 +82,9 @@ #define NPCX_WUI_GPIO_F_0 WUI(0, MIWU_GROUP_8, 5) #define NPCX_WUI_GPIO_F_3 WUI(0, MIWU_GROUP_8, 6) #ifndef NPCX_EXT32K_OSC_SUPPORT -#define NPCX_WUI_GPIO_E_7 WUI(0, MIWU_GROUP_8, 7) /* Used as CLKIN if support */ +#define NPCX_WUI_GPIO_E_7 \ + WUI(0, MIWU_GROUP_8, 7) /* Used as CLKIN if support \ + */ #endif /* MIWU1 */ @@ -151,7 +153,9 @@ #define NPCX_WUI_GPIO_6_3 WUI(1, MIWU_GROUP_7, 3) #define NPCX_WUI_GPIO_6_4 WUI(1, MIWU_GROUP_7, 4) #ifndef NPCX_EXT32K_OSC_SUPPORT -#define NPCX_WUI_GPIO_7_1 WUI(1, MIWU_GROUP_7, 7) /* Used as CLKOUT if support*/ +#define NPCX_WUI_GPIO_7_1 \ + WUI(1, MIWU_GROUP_7, 7) /* Used as CLKOUT if \ + support*/ #endif /* Group H: NPCX_IRQ_WKINTH_1 */ @@ -194,7 +198,7 @@ /* Pin-Mux for PSL/UART2/SMB4_0 */ #ifdef NPCX_PSL_MODE_SUPPORT #if defined(NPCX_SECOND_UART) && (CONFIG_CONSOLE_UART == 1) -#define NPCX_ALT_GPIO_8_6 ALT(8, 6, NPCX_ALT(A, UART2_SL)) /* CR_SOUT2 */ +#define NPCX_ALT_GPIO_8_6 ALT(8, 6, NPCX_ALT(A, UART2_SL)) /* CR_SOUT2 */ #define NPCX_ALT_GPIO_8_5 /* Used as PSL_OUT */ #else #define NPCX_ALT_GPIO_8_6 /* No I2CSDA since GPIO85 used as PSL_OUT */ @@ -214,7 +218,7 @@ /* Pin-Mux for PWM1/SMB6_0 */ #if NPCX7_PWM1_SEL #define NPCX_ALT_GPIO_C_1 /* No I2CSDA since GPIOC2 used as PWM1 */ -#define NPCX_ALT_GPIO_C_2 ALT(C, 2, NPCX_ALT(4, PWM1_SL)) /* PWM1 */ +#define NPCX_ALT_GPIO_C_2 ALT(C, 2, NPCX_ALT(4, PWM1_SL)) /* PWM1 */ #else #define NPCX_ALT_GPIO_C_1 ALT(C, 1, NPCX_ALT(2, I2C6_0_SL)) /* SMB6SDA0 */ #define NPCX_ALT_GPIO_C_2 ALT(C, 2, NPCX_ALT(2, I2C6_0_SL)) /* SMB6SCL0 */ @@ -230,7 +234,7 @@ #define NPCX_ALT_GPIO_4_3 ALT(4, 3, NPCX_ALT(6, ADC2_SL)) /* ADC2 */ #define NPCX_ALT_GPIO_4_2 ALT(4, 2, NPCX_ALT(6, ADC3_SL)) /* ADC3 */ #define NPCX_ALT_GPIO_4_1 ALT(4, 1, NPCX_ALT(6, ADC4_SL)) /* ADC4 */ -#ifdef CONFIG_PS2 +#if defined(CONFIG_PS2) && defined(NPCX_PS2_MODULE_2) #define NPCX_ALT_GPIO_3_7 ALT(3, 7, NPCX_ALT(3, PS2_2_SL)) /* PS2_CLK2 */ #define NPCX_ALT_GPIO_3_4 ALT(3, 4, NPCX_ALT(3, PS2_2_SL)) /* PS2_DATA2 */ #else @@ -264,7 +268,7 @@ #define NPCX_ALT_GPIO_4_0 ALT(4, 0, NPCX_ALT(3, TA1_SL1)) /* TA1_SEL1 */ #define NPCX_ALT_GPIO_7_3 ALT(7, 3, NPCX_ALT(3, TA2_SL1)) /* TA2_SEL1 */ #define NPCX_ALT_GPIO_9_3 ALT(9, 3, NPCX_ALT(C, TA1_SL2)) /* TA1_SEL2 */ -#ifdef CONFIG_PS2 +#if defined(CONFIG_PS2) && defined(NPCX_PS2_MODULE_3) #define NPCX_ALT_GPIO_A_6 ALT(A, 6, NPCX_ALT(C, PS2_3_SL2)) /* PS2_CLK3 */ #else #define NPCX_ALT_GPIO_A_6 ALT(A, 6, NPCX_ALT(C, TA2_SL2)) /* TA2_SEL2 */ @@ -289,7 +293,7 @@ #define NPCX_ALT_GPIO_1_2 ALT(1, 2, NPCX_ALT_INV(8, NO_KSO07_SL)) /* KSO07 */ /* KSO08 & CR_SOUT */ #define NPCX_ALT_GPIO_1_1 ALT(1, 1, NPCX_ALT_INV(9, NO_KSO08_SL)) - /* KSO09 & CR_SIN */ +/* KSO09 & CR_SIN */ #define NPCX_ALT_GPIO_1_0 ALT(1, 0, NPCX_ALT_INV(9, NO_KSO09_SL)) #define NPCX_ALT_GPIO_0_7 ALT(0, 7, NPCX_ALT_INV(9, NO_KSO10_SL)) /* KSO10 */ #define NPCX_ALT_GPIO_0_6 ALT(0, 6, NPCX_ALT_INV(9, NO_KSO11_SL)) /* KSO11 */ @@ -309,17 +313,21 @@ /* Pin-Mux for UART2/32KHZ_OUT */ #if defined(NPCX_SECOND_UART) && (CONFIG_CONSOLE_UART == 1) -#define NPCX_ALT_GPIO_7_5 ALT(7, 5, NPCX_ALT(A, UART2_SL)) /* CR_SIN2 */ +#define NPCX_ALT_GPIO_7_5 ALT(7, 5, NPCX_ALT(A, UART2_SL)) /* CR_SIN2 */ #else -#define NPCX_ALT_GPIO_7_5 ALT(7, 5, NPCX_ALT(A, 32K_OUT_SL)) /* 32KHZ_OUT */ +#define NPCX_ALT_GPIO_7_5 ALT(7, 5, NPCX_ALT(A, 32K_OUT_SL)) /* 32KHZ_OUT */ #endif /* PSL module (Optional) */ #ifdef NPCX_PSL_MODE_SUPPORT -#define NPCX_ALT_GPIO_D_2 ALT(D, 2, NPCX_ALT_INV(D, NPSL_IN1_SL)) /* PSL_IN1 */ -#define NPCX_ALT_GPIO_0_0 ALT(0, 0, NPCX_ALT_INV(D, NPSL_IN2_SL)) /* PSL_IN2 */ -#define NPCX_ALT_GPIO_0_1 ALT(0, 1, NPCX_ALT(D, PSL_IN3_SL)) /* PSL_IN3 */ -#define NPCX_ALT_GPIO_0_2 ALT(0, 2, NPCX_ALT(D, PSL_IN4_SL)) /* PSL_IN4 */ +#define NPCX_ALT_GPIO_D_2 \ + ALT(D, 2, NPCX_ALT_INV(D, NPSL_IN1_SL)) /* PSL_IN1 \ + */ +#define NPCX_ALT_GPIO_0_0 \ + ALT(0, 0, NPCX_ALT_INV(D, NPSL_IN2_SL)) /* PSL_IN2 \ + */ +#define NPCX_ALT_GPIO_0_1 ALT(0, 1, NPCX_ALT(D, PSL_IN3_SL)) /* PSL_IN3 */ +#define NPCX_ALT_GPIO_0_2 ALT(0, 2, NPCX_ALT(D, PSL_IN4_SL)) /* PSL_IN4 */ #else #define NPCX_ALT_GPIO_D_2 /* NO PSL in NPCX7mnG series */ #define NPCX_ALT_GPIO_0_0 /* NO PSL in NPCX7mnG series */ @@ -328,8 +336,8 @@ #endif /* WOV module (Optional) */ -#if defined(NPCX_WOV_SUPPORT) && \ - (defined(CONFIG_AUDIO_CODEC_I2S_RX) || defined(CONFIG_AUDIO_CODEC_WOV)) +#if defined(NPCX_WOV_SUPPORT) && (defined(CONFIG_AUDIO_CODEC_I2S_RX) || \ + defined(CONFIG_AUDIO_CODEC_WOV)) #define NPCX_ALT_GPIO_9_5 /* Disable SPIP module if WOV is supported */ #define NPCX_ALT_GPIO_A_3 /* Disable SPIP module if WOV is supported */ #define NPCX_ALT_GPIO_A_1 /* Disable SPIP module if WOV is supported */ @@ -346,7 +354,7 @@ #define NPCX_ALT_GPIO_A_3 ALT(A, 3, NPCX_ALT(0, SPIP_SL)) /* SPIP_MOSI */ #define NPCX_ALT_GPIO_A_1 ALT(A, 1, NPCX_ALT(0, SPIP_SL)) /* SPIP_SCLK */ -#ifdef CONFIG_PS2 +#if defined(CONFIG_PS2) && defined(NPCX_PS2_MODULE_3) #define NPCX_ALT_GPIO_A_7 ALT(A, 7, NPCX_ALT(C, PS2_3_SL2)) /* PS2_DAT3 */ #else #define NPCX_ALT_GPIO_A_7 @@ -356,6 +364,7 @@ #define NPCX_ALT_GPIO_9_7 #endif +/* clang-format off */ #define NPCX_ALT_TABLE { \ NPCX_ALT_GPIO_0_0 /* PSL_IN2 */ \ NPCX_ALT_GPIO_0_1 /* PSL_IN3 */ \ @@ -447,90 +456,110 @@ NPCX_ALT_GPIO_F_4 /* SMB5SDA1 */ \ NPCX_ALT_GPIO_F_5 /* SMB5SCL1 */ \ } +/* clang-format on */ /*****************************************************************************/ /* Macro functions for Low-Voltage mapping table */ /* Low-Voltage GPIO Control 0 */ -#define NPCX_LVOL_CTRL_0_0 NPCX_GPIO(B, 5) -#define NPCX_LVOL_CTRL_0_1 NPCX_GPIO(B, 4) -#define NPCX_LVOL_CTRL_0_2 NPCX_GPIO(B, 3) -#define NPCX_LVOL_CTRL_0_3 NPCX_GPIO(B, 2) -#define NPCX_LVOL_CTRL_0_4 NPCX_GPIO(9, 0) -#define NPCX_LVOL_CTRL_0_5 NPCX_GPIO(8, 7) -#define NPCX_LVOL_CTRL_0_6 NPCX_GPIO(0, 0) -#define NPCX_LVOL_CTRL_0_7 NPCX_GPIO(3, 3) +#define NPCX_LVOL_CTRL_0_0 NPCX_GPIO(B, 5) +#define NPCX_LVOL_CTRL_0_1 NPCX_GPIO(B, 4) +#define NPCX_LVOL_CTRL_0_2 NPCX_GPIO(B, 3) +#define NPCX_LVOL_CTRL_0_3 NPCX_GPIO(B, 2) +#define NPCX_LVOL_CTRL_0_4 NPCX_GPIO(9, 0) +#define NPCX_LVOL_CTRL_0_5 NPCX_GPIO(8, 7) +#define NPCX_LVOL_CTRL_0_6 NPCX_GPIO(0, 0) +#define NPCX_LVOL_CTRL_0_7 NPCX_GPIO(3, 3) /* Low-Voltage GPIO Control 1 */ -#define NPCX_LVOL_CTRL_1_0 NPCX_GPIO(9, 2) -#define NPCX_LVOL_CTRL_1_1 NPCX_GPIO(9, 1) -#define NPCX_LVOL_CTRL_1_2 NPCX_GPIO(D, 1) -#define NPCX_LVOL_CTRL_1_3 NPCX_GPIO(D, 0) -#define NPCX_LVOL_CTRL_1_4 NPCX_GPIO(3, 6) -#define NPCX_LVOL_CTRL_1_5 NPCX_GPIO(6, 4) -#define NPCX_LVOL_CTRL_1_6 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_1_7 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_1_0 NPCX_GPIO(9, 2) +#define NPCX_LVOL_CTRL_1_1 NPCX_GPIO(9, 1) +#define NPCX_LVOL_CTRL_1_2 NPCX_GPIO(D, 1) +#define NPCX_LVOL_CTRL_1_3 NPCX_GPIO(D, 0) +#define NPCX_LVOL_CTRL_1_4 NPCX_GPIO(3, 6) +#define NPCX_LVOL_CTRL_1_5 NPCX_GPIO(6, 4) +#define NPCX_LVOL_CTRL_1_6 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_1_7 NPCX_GPIO_NONE /* Low-Voltage GPIO Control 2 */ -#define NPCX_LVOL_CTRL_2_0 NPCX_GPIO(7, 4) +#define NPCX_LVOL_CTRL_2_0 NPCX_GPIO(7, 4) #ifdef NPCX_PSL_MODE_SUPPORT -#define NPCX_LVOL_CTRL_2_1 NPCX_GPIO_NONE /* Remove 1.8V support since PSL */ -#define NPCX_LVOL_CTRL_2_2 NPCX_GPIO_NONE /* Remove 1.8V support since PSL */ +#define NPCX_LVOL_CTRL_2_1 NPCX_GPIO_NONE /* Remove 1.8V support since PSL */ +#define NPCX_LVOL_CTRL_2_2 NPCX_GPIO_NONE /* Remove 1.8V support since PSL */ #else -#define NPCX_LVOL_CTRL_2_1 NPCX_GPIO(8, 4) -#define NPCX_LVOL_CTRL_2_2 NPCX_GPIO(8, 5) +#define NPCX_LVOL_CTRL_2_1 NPCX_GPIO(8, 4) +#define NPCX_LVOL_CTRL_2_2 NPCX_GPIO(8, 5) #endif -#define NPCX_LVOL_CTRL_2_3 NPCX_GPIO(7, 3) -#define NPCX_LVOL_CTRL_2_4 NPCX_GPIO(C, 1) -#define NPCX_LVOL_CTRL_2_5 NPCX_GPIO(C, 7) +#define NPCX_LVOL_CTRL_2_3 NPCX_GPIO(7, 3) +#define NPCX_LVOL_CTRL_2_4 NPCX_GPIO(C, 1) +#define NPCX_LVOL_CTRL_2_5 NPCX_GPIO(C, 7) #ifdef NPCX_EXT32K_OSC_SUPPORT -#define NPCX_LVOL_CTRL_2_6 NPCX_GPIO_NONE /* Remove 1.8V support since CLKIN */ +#define NPCX_LVOL_CTRL_2_6 \ + NPCX_GPIO_NONE /* Remove 1.8V support since CLKIN \ + */ #else -#define NPCX_LVOL_CTRL_2_6 NPCX_GPIO(E, 7) +#define NPCX_LVOL_CTRL_2_6 NPCX_GPIO(E, 7) #endif -#define NPCX_LVOL_CTRL_2_7 NPCX_GPIO(3, 4) +#define NPCX_LVOL_CTRL_2_7 NPCX_GPIO(3, 4) /* Low-Voltage GPIO Control 3 */ -#define NPCX_LVOL_CTRL_3_0 NPCX_GPIO(C, 6) -#define NPCX_LVOL_CTRL_3_1 NPCX_GPIO(3, 7) -#define NPCX_LVOL_CTRL_3_2 NPCX_GPIO(4, 0) +#define NPCX_LVOL_CTRL_3_0 NPCX_GPIO(C, 6) +#define NPCX_LVOL_CTRL_3_1 NPCX_GPIO(3, 7) +#define NPCX_LVOL_CTRL_3_2 NPCX_GPIO(4, 0) #ifdef NPCX_EXT32K_OSC_SUPPORT -#define NPCX_LVOL_CTRL_3_3 NPCX_GPIO_NONE /* Remove 1.8V support since CLKOUT*/ +#define NPCX_LVOL_CTRL_3_3 \ + NPCX_GPIO_NONE /* Remove 1.8V support since \ + CLKOUT*/ #else -#define NPCX_LVOL_CTRL_3_3 NPCX_GPIO(7, 1) +#define NPCX_LVOL_CTRL_3_3 NPCX_GPIO(7, 1) #endif -#define NPCX_LVOL_CTRL_3_4 NPCX_GPIO(8, 2) -#define NPCX_LVOL_CTRL_3_5 NPCX_GPIO(7, 5) -#define NPCX_LVOL_CTRL_3_6 NPCX_GPIO(8, 0) -#define NPCX_LVOL_CTRL_3_7 NPCX_GPIO(C, 5) +#define NPCX_LVOL_CTRL_3_4 NPCX_GPIO(8, 2) +#define NPCX_LVOL_CTRL_3_5 NPCX_GPIO(7, 5) +#define NPCX_LVOL_CTRL_3_6 NPCX_GPIO(8, 0) +#define NPCX_LVOL_CTRL_3_7 NPCX_GPIO(C, 5) /* Low-Voltage GPIO Control 4 */ -#define NPCX_LVOL_CTRL_4_0 NPCX_GPIO(8, 6) -#define NPCX_LVOL_CTRL_4_1 NPCX_GPIO(C, 2) -#define NPCX_LVOL_CTRL_4_2 NPCX_GPIO(F, 3) -#define NPCX_LVOL_CTRL_4_3 NPCX_GPIO(F, 2) -#define NPCX_LVOL_CTRL_4_4 NPCX_GPIO(F, 5) -#define NPCX_LVOL_CTRL_4_5 NPCX_GPIO(F, 4) -#define NPCX_LVOL_CTRL_4_6 NPCX_GPIO(E, 4) -#define NPCX_LVOL_CTRL_4_7 NPCX_GPIO(E, 3) +#define NPCX_LVOL_CTRL_4_0 NPCX_GPIO(8, 6) +#define NPCX_LVOL_CTRL_4_1 NPCX_GPIO(C, 2) +#define NPCX_LVOL_CTRL_4_2 NPCX_GPIO(F, 3) +#define NPCX_LVOL_CTRL_4_3 NPCX_GPIO(F, 2) +#define NPCX_LVOL_CTRL_4_4 NPCX_GPIO(F, 5) +#define NPCX_LVOL_CTRL_4_5 NPCX_GPIO(F, 4) +#define NPCX_LVOL_CTRL_4_6 NPCX_GPIO(E, 4) +#define NPCX_LVOL_CTRL_4_7 NPCX_GPIO(E, 3) /* Low-Voltage GPIO Control 5 */ -#define NPCX_LVOL_CTRL_5_0 NPCX_GPIO(7, 2) -#define NPCX_LVOL_CTRL_5_1 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_2 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_3 NPCX_GPIO(5, 0) -#define NPCX_LVOL_CTRL_5_4 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_5 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_6 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_7 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_0 NPCX_GPIO(7, 2) +#define NPCX_LVOL_CTRL_5_1 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_2 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_3 NPCX_GPIO(5, 0) +#define NPCX_LVOL_CTRL_5_4 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_5 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_6 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_7 NPCX_GPIO_NONE /* 6 Low-Voltage Control Groups on npcx7 */ -#define NPCX_LVOL_TABLE { { NPCX_LVOL_CTRL_ITEMS(0), }, \ - { NPCX_LVOL_CTRL_ITEMS(1), }, \ - { NPCX_LVOL_CTRL_ITEMS(2), }, \ - { NPCX_LVOL_CTRL_ITEMS(3), }, \ - { NPCX_LVOL_CTRL_ITEMS(4), }, \ - { NPCX_LVOL_CTRL_ITEMS(5), }, } +#define NPCX_LVOL_TABLE \ + { \ + { \ + NPCX_LVOL_CTRL_ITEMS(0), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(1), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(2), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(3), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(4), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(5), \ + }, \ + } #endif /* __CROS_EC_GPIO_CHIP_NPCX7_H */ diff --git a/chip/npcx/gpio_chip-npcx9.h b/chip/npcx/gpio_chip-npcx9.h index a80a1b899a..aef2f4f044 100644 --- a/chip/npcx/gpio_chip-npcx9.h +++ b/chip/npcx/gpio_chip-npcx9.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,10 @@ #ifndef __CROS_EC_GPIO_CHIP_NPCX9_H #define __CROS_EC_GPIO_CHIP_NPCX9_H +#ifndef NPCX9_PWM1_SEL +#define NPCX9_PWM1_SEL 0 +#endif /* NPCX9_PWM1_SEL */ + /*****************************************************************************/ /* Macro functions for MIWU mapping table */ @@ -196,7 +200,7 @@ /* Pin-Mux for PWM1/SMB6_0 */ #if NPCX9_PWM1_SEL #define NPCX_ALT_GPIO_C_1 /* No I2CSDA since GPIOC2 used as PWM1 */ -#define NPCX_ALT_GPIO_C_2 ALT(C, 2, NPCX_ALT(4, PWM1_SL)) /* PWM1 */ +#define NPCX_ALT_GPIO_C_2 ALT(C, 2, NPCX_ALT(4, PWM1_SL)) /* PWM1 */ #else #define NPCX_ALT_GPIO_C_1 ALT(C, 1, NPCX_ALT(2, I2C6_0_SL)) /* SMB6SDA0 */ #define NPCX_ALT_GPIO_C_2 ALT(C, 2, NPCX_ALT(2, I2C6_0_SL)) /* SMB6SCL0 */ @@ -208,33 +212,44 @@ #define NPCX_ALT_GPIO_4_3 ALT(4, 3, NPCX_ALT(6, ADC2_SL)) /* ADC2 */ #define NPCX_ALT_GPIO_4_2 ALT(4, 2, NPCX_ALT(6, ADC3_SL)) /* ADC3 */ #define NPCX_ALT_GPIO_4_1 ALT(4, 1, NPCX_ALT(6, ADC4_SL)) /* ADC4 */ -#ifdef CONFIG_PS2 +#if defined(CONFIG_PS2) && defined(NPCX_PS2_MODULE_2) #define NPCX_ALT_GPIO_3_7 ALT(3, 7, NPCX_ALT(3, PS2_2_SL)) /* PS2_CLK2 */ #define NPCX_ALT_GPIO_3_4 ALT(3, 4, NPCX_ALT(3, PS2_2_SL)) /* PS2_DATA2 */ #else #define NPCX_ALT_GPIO_3_7 ALT(3, 7, NPCX_ALT(F, ADC5_SL)) /* ADC5 */ #define NPCX_ALT_GPIO_3_4 ALT(3, 4, NPCX_ALT(F, ADC6_SL)) /* ADC6 */ #endif -#define NPCX_ALT_GPIO_F_1 ALT(F, 1, NPCX_ALT(F, ADC8_SL)) /* ADC8 */ -#define NPCX_ALT_GPIO_E_1 ALT(E, 1, NPCX_ALT(F, ADC7_SL)) /* ADC7 */ -#define NPCX_ALT_GPIO_F_0 ALT(F, 0, NPCX_ALT(F, ADC9_SL)) /* ADC9 */ +#define NPCX_ALT_GPIO_F_1 ALT(F, 1, NPCX_ALT(F, ADC8_SL)) /* ADC8 */ +#define NPCX_ALT_GPIO_E_1 ALT(E, 1, NPCX_ALT(F, ADC7_SL)) /* ADC7 */ +#define NPCX_ALT_GPIO_F_0 ALT(F, 0, NPCX_ALT(F, ADC9_SL)) /* ADC9 */ #define NPCX_ALT_GPIO_E_0 ALT(E, 0, NPCX_ALT(F, ADC10_SL)) /* AD10 */ #define NPCX_ALT_GPIO_C_7 ALT(C, 7, NPCX_ALT(F, ADC11_SL)) /* AD11 */ /* PS/2 Module */ -#define NPCX_ALT_GPIO_6_7 ALT(6, 7, NPCX_ALT(3, PS2_0_SL)) /* PS2_CLK0 */ -#define NPCX_ALT_GPIO_7_0 ALT(7, 0, NPCX_ALT(3, PS2_0_SL)) /* PS2_DATA0 */ -#define NPCX_ALT_GPIO_6_2 ALT(6, 2, NPCX_ALT(3, PS2_1_SL)) /* PS2_CLK1 */ -#define NPCX_ALT_GPIO_6_3 ALT(6, 3, NPCX_ALT(3, PS2_1_SL)) /* PS2_DATA1 */ +#define NPCX_ALT_GPIO_6_7 ALT(6, 7, NPCX_ALT(3, PS2_0_SL)) /* PS2_CLK0 */ +#define NPCX_ALT_GPIO_7_0 ALT(7, 0, NPCX_ALT(3, PS2_0_SL)) /* PS2_DATA0 */ +#define NPCX_ALT_GPIO_6_2 ALT(6, 2, NPCX_ALT(3, PS2_1_SL)) /* PS2_CLK1 */ +#define NPCX_ALT_GPIO_6_3 ALT(6, 3, NPCX_ALT(3, PS2_1_SL)) /* PS2_DATA1 */ +#if defined(CONFIG_PS2) && defined(NPCX_PS2_MODULE_3) #define NPCX_ALT_GPIO_A_7 ALT(A, 7, NPCX_ALT(C, PS2_3_SL2)) /* PS2_DAT3 */ +#else +#define NPCX_ALT_GPIO_A_7 +#endif /* UART Module */ -#define NPCX_ALT_GPIO_6_4 ALT(6, 4, NPCX_ALT(J, CR_SIN1_SL2)) /* CR_SIN1_SL2 */ -#define NPCX_ALT_GPIO_6_5 ALT(6, 5, NPCX_ALT(J, CR_SOUT1_SL2))/* CR_SOUT1_SL2 */ -#define NPCX_ALT_GPIO_7_5 ALT(7, 5, NPCX_ALT(J, CR_SIN2_SL)) /* CR_SIN2_SL */ -#define NPCX_ALT_GPIO_8_6 ALT(8, 6, NPCX_ALT(J, CR_SOUT2_SL)) /* CR_SOUT2_SL */ -#define NPCX_ALT_GPIO_D_4 ALT(D, 4, NPCX_ALT(J, CR_SIN3_SL)) /* CR_SIN3_SL */ -#define NPCX_ALT_GPIO_D_6 ALT(D, 6, NPCX_ALT(J, CR_SOUT3_SL)) /* CR_SOUT3_SL */ +#define NPCX_ALT_GPIO_6_4 \ + ALT(6, 4, NPCX_ALT(J, CR_SIN1_SL2)) /* CR_SIN1_SL2 \ + */ +#define NPCX_ALT_GPIO_6_5 \ + ALT(6, 5, NPCX_ALT(J, CR_SOUT1_SL2)) /* CR_SOUT1_SL2 */ +#define NPCX_ALT_GPIO_7_5 ALT(7, 5, NPCX_ALT(J, CR_SIN2_SL)) /* CR_SIN2_SL */ +#define NPCX_ALT_GPIO_8_6 \ + ALT(8, 6, NPCX_ALT(J, CR_SOUT2_SL)) /* CR_SOUT2_SL \ + */ +#define NPCX_ALT_GPIO_D_4 ALT(D, 4, NPCX_ALT(J, CR_SIN3_SL)) /* CR_SIN3_SL */ +#define NPCX_ALT_GPIO_D_6 \ + ALT(D, 6, NPCX_ALT(J, CR_SOUT3_SL)) /* CR_SOUT3_SL \ + */ /* PWM Module */ #define NPCX_ALT_GPIO_C_3 ALT(C, 3, NPCX_ALT(4, PWM0_SL)) /* PWM0 */ @@ -249,7 +264,7 @@ #define NPCX_ALT_GPIO_4_0 ALT(4, 0, NPCX_ALT(3, TA1_SL1)) /* TA1_SEL1 */ #define NPCX_ALT_GPIO_7_3 ALT(7, 3, NPCX_ALT(3, TA2_SL1)) /* TA2_SEL1 */ #define NPCX_ALT_GPIO_9_3 ALT(9, 3, NPCX_ALT(C, TA1_SL2)) /* TA1_SEL2 */ -#ifdef CONFIG_PS2 +#if defined(CONFIG_PS2) && defined(NPCX_PS2_MODULE_3) #define NPCX_ALT_GPIO_A_6 ALT(A, 6, NPCX_ALT(C, PS2_3_SL2)) /* PS2_CLK3 */ #else #define NPCX_ALT_GPIO_A_6 ALT(A, 6, NPCX_ALT(C, TA2_SL2)) /* TA2_SEL2 */ @@ -274,7 +289,7 @@ #define NPCX_ALT_GPIO_1_2 ALT(1, 2, NPCX_ALT_INV(8, NO_KSO07_SL)) /* KSO07 */ /* KSO08 & CR_SOUT */ #define NPCX_ALT_GPIO_1_1 ALT(1, 1, NPCX_ALT_INV(9, NO_KSO08_SL)) - /* KSO09 & CR_SIN */ +/* KSO09 & CR_SIN */ #define NPCX_ALT_GPIO_1_0 ALT(1, 0, NPCX_ALT_INV(9, NO_KSO09_SL)) #define NPCX_ALT_GPIO_0_7 ALT(0, 7, NPCX_ALT_INV(9, NO_KSO10_SL)) /* KSO10 */ #define NPCX_ALT_GPIO_0_6 ALT(0, 6, NPCX_ALT_INV(9, NO_KSO11_SL)) /* KSO11 */ @@ -286,17 +301,22 @@ #define NPCX_ALT_GPIO_B_1 ALT(B, 1, NPCX_ALT_INV(A, NO_KSO17_SL)) /* KSO17 */ /* PSL module */ -#define NPCX_ALT_GPIO_D_2 ALT(D, 2, NPCX_ALT_INV(D, NPSL_IN1_SL)) /* PSL_IN1 */ -#define NPCX_ALT_GPIO_0_0 ALT(0, 0, NPCX_ALT_INV(D, NPSL_IN2_SL)) /* PSL_IN2 */ -#define NPCX_ALT_GPIO_0_1 ALT(0, 1, NPCX_ALT(D, PSL_IN3_SL)) /* PSL_IN3 */ -#define NPCX_ALT_GPIO_0_2 ALT(0, 2, NPCX_ALT(D, PSL_IN4_SL)) /* PSL_IN4 */ -#define NPCX_ALT_GPIO_D_7 ALT(D, 7, NPCX_ALT(G, PSL_GPO_SL)) /* PSL_GPO */ +#define NPCX_ALT_GPIO_D_2 \ + ALT(D, 2, NPCX_ALT_INV(D, NPSL_IN1_SL)) /* PSL_IN1 \ + */ +#define NPCX_ALT_GPIO_0_0 \ + ALT(0, 0, NPCX_ALT_INV(D, NPSL_IN2_SL)) /* PSL_IN2 \ + */ +#define NPCX_ALT_GPIO_0_1 ALT(0, 1, NPCX_ALT(D, PSL_IN3_SL)) /* PSL_IN3 */ +#define NPCX_ALT_GPIO_0_2 ALT(0, 2, NPCX_ALT(D, PSL_IN4_SL)) /* PSL_IN4 */ +#define NPCX_ALT_GPIO_D_7 ALT(D, 7, NPCX_ALT(G, PSL_GPO_SL)) /* PSL_GPO */ /* SPI Module */ #define NPCX_ALT_GPIO_9_5 ALT(9, 5, NPCX_ALT(0, SPIP_SL)) /* SPIP_MISO */ #define NPCX_ALT_GPIO_A_3 ALT(A, 3, NPCX_ALT(0, SPIP_SL)) /* SPIP_MOSI */ #define NPCX_ALT_GPIO_A_1 ALT(A, 1, NPCX_ALT(0, SPIP_SL)) /* SPIP_SCLK */ +/* clang-format off */ #define NPCX_ALT_TABLE { \ NPCX_ALT_GPIO_0_0 /* PSL_IN2 */ \ NPCX_ALT_GPIO_0_1 /* PSL_IN3 */ \ @@ -387,76 +407,92 @@ NPCX_ALT_GPIO_F_4 /* SMB5SDA1 */ \ NPCX_ALT_GPIO_F_5 /* SMB5SCL1 */ \ } +/* clang-format on */ /*****************************************************************************/ /* Macro functions for Low-Voltage mapping table */ /* Low-Voltage GPIO Control 0 */ -#define NPCX_LVOL_CTRL_0_0 NPCX_GPIO(B, 5) -#define NPCX_LVOL_CTRL_0_1 NPCX_GPIO(B, 4) -#define NPCX_LVOL_CTRL_0_2 NPCX_GPIO(B, 3) -#define NPCX_LVOL_CTRL_0_3 NPCX_GPIO(B, 2) -#define NPCX_LVOL_CTRL_0_4 NPCX_GPIO(9, 0) -#define NPCX_LVOL_CTRL_0_5 NPCX_GPIO(8, 7) -#define NPCX_LVOL_CTRL_0_6 NPCX_GPIO(0, 0) -#define NPCX_LVOL_CTRL_0_7 NPCX_GPIO(3, 3) +#define NPCX_LVOL_CTRL_0_0 NPCX_GPIO(B, 5) +#define NPCX_LVOL_CTRL_0_1 NPCX_GPIO(B, 4) +#define NPCX_LVOL_CTRL_0_2 NPCX_GPIO(B, 3) +#define NPCX_LVOL_CTRL_0_3 NPCX_GPIO(B, 2) +#define NPCX_LVOL_CTRL_0_4 NPCX_GPIO(9, 0) +#define NPCX_LVOL_CTRL_0_5 NPCX_GPIO(8, 7) +#define NPCX_LVOL_CTRL_0_6 NPCX_GPIO(0, 0) +#define NPCX_LVOL_CTRL_0_7 NPCX_GPIO(3, 3) /* Low-Voltage GPIO Control 1 */ -#define NPCX_LVOL_CTRL_1_0 NPCX_GPIO(9, 2) -#define NPCX_LVOL_CTRL_1_1 NPCX_GPIO(9, 1) -#define NPCX_LVOL_CTRL_1_2 NPCX_GPIO(D, 1) -#define NPCX_LVOL_CTRL_1_3 NPCX_GPIO(D, 0) -#define NPCX_LVOL_CTRL_1_4 NPCX_GPIO(3, 6) -#define NPCX_LVOL_CTRL_1_5 NPCX_GPIO(6, 4) -#define NPCX_LVOL_CTRL_1_6 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_1_7 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_1_0 NPCX_GPIO(9, 2) +#define NPCX_LVOL_CTRL_1_1 NPCX_GPIO(9, 1) +#define NPCX_LVOL_CTRL_1_2 NPCX_GPIO(D, 1) +#define NPCX_LVOL_CTRL_1_3 NPCX_GPIO(D, 0) +#define NPCX_LVOL_CTRL_1_4 NPCX_GPIO(3, 6) +#define NPCX_LVOL_CTRL_1_5 NPCX_GPIO(6, 4) +#define NPCX_LVOL_CTRL_1_6 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_1_7 NPCX_GPIO_NONE /* Low-Voltage GPIO Control 2 */ -#define NPCX_LVOL_CTRL_2_0 NPCX_GPIO(7, 4) -#define NPCX_LVOL_CTRL_2_1 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_2_2 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_2_3 NPCX_GPIO(7, 3) -#define NPCX_LVOL_CTRL_2_4 NPCX_GPIO(C, 1) -#define NPCX_LVOL_CTRL_2_5 NPCX_GPIO(C, 7) -#define NPCX_LVOL_CTRL_2_6 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_2_7 NPCX_GPIO(3, 4) +#define NPCX_LVOL_CTRL_2_0 NPCX_GPIO(7, 4) +#define NPCX_LVOL_CTRL_2_1 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_2_2 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_2_3 NPCX_GPIO(7, 3) +#define NPCX_LVOL_CTRL_2_4 NPCX_GPIO(C, 1) +#define NPCX_LVOL_CTRL_2_5 NPCX_GPIO(C, 7) +#define NPCX_LVOL_CTRL_2_6 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_2_7 NPCX_GPIO(3, 4) /* Low-Voltage GPIO Control 3 */ -#define NPCX_LVOL_CTRL_3_0 NPCX_GPIO(C, 6) -#define NPCX_LVOL_CTRL_3_1 NPCX_GPIO(3, 7) -#define NPCX_LVOL_CTRL_3_2 NPCX_GPIO(4, 0) -#define NPCX_LVOL_CTRL_3_3 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_3_4 NPCX_GPIO(8, 2) -#define NPCX_LVOL_CTRL_3_5 NPCX_GPIO(7, 5) -#define NPCX_LVOL_CTRL_3_6 NPCX_GPIO(8, 0) -#define NPCX_LVOL_CTRL_3_7 NPCX_GPIO(C, 5) +#define NPCX_LVOL_CTRL_3_0 NPCX_GPIO(C, 6) +#define NPCX_LVOL_CTRL_3_1 NPCX_GPIO(3, 7) +#define NPCX_LVOL_CTRL_3_2 NPCX_GPIO(4, 0) +#define NPCX_LVOL_CTRL_3_3 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_3_4 NPCX_GPIO(8, 2) +#define NPCX_LVOL_CTRL_3_5 NPCX_GPIO(7, 5) +#define NPCX_LVOL_CTRL_3_6 NPCX_GPIO(8, 0) +#define NPCX_LVOL_CTRL_3_7 NPCX_GPIO(C, 5) /* Low-Voltage GPIO Control 4 */ -#define NPCX_LVOL_CTRL_4_0 NPCX_GPIO(8, 6) -#define NPCX_LVOL_CTRL_4_1 NPCX_GPIO(C, 2) -#define NPCX_LVOL_CTRL_4_2 NPCX_GPIO(F, 3) -#define NPCX_LVOL_CTRL_4_3 NPCX_GPIO(F, 2) -#define NPCX_LVOL_CTRL_4_4 NPCX_GPIO(F, 5) -#define NPCX_LVOL_CTRL_4_5 NPCX_GPIO(F, 4) -#define NPCX_LVOL_CTRL_4_6 NPCX_GPIO(E, 4) -#define NPCX_LVOL_CTRL_4_7 NPCX_GPIO(E, 3) +#define NPCX_LVOL_CTRL_4_0 NPCX_GPIO(8, 6) +#define NPCX_LVOL_CTRL_4_1 NPCX_GPIO(C, 2) +#define NPCX_LVOL_CTRL_4_2 NPCX_GPIO(F, 3) +#define NPCX_LVOL_CTRL_4_3 NPCX_GPIO(F, 2) +#define NPCX_LVOL_CTRL_4_4 NPCX_GPIO(F, 5) +#define NPCX_LVOL_CTRL_4_5 NPCX_GPIO(F, 4) +#define NPCX_LVOL_CTRL_4_6 NPCX_GPIO(E, 4) +#define NPCX_LVOL_CTRL_4_7 NPCX_GPIO(E, 3) /* Low-Voltage GPIO Control 5 */ -#define NPCX_LVOL_CTRL_5_0 NPCX_GPIO(7, 2) -#define NPCX_LVOL_CTRL_5_1 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_2 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_3 NPCX_GPIO(5, 0) -#define NPCX_LVOL_CTRL_5_4 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_5 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_6 NPCX_GPIO_NONE -#define NPCX_LVOL_CTRL_5_7 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_0 NPCX_GPIO(7, 2) +#define NPCX_LVOL_CTRL_5_1 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_2 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_3 NPCX_GPIO(5, 0) +#define NPCX_LVOL_CTRL_5_4 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_5 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_6 NPCX_GPIO_NONE +#define NPCX_LVOL_CTRL_5_7 NPCX_GPIO_NONE /* 6 Low-Voltage Control Groups on npcx7 */ -#define NPCX_LVOL_TABLE { { NPCX_LVOL_CTRL_ITEMS(0), }, \ - { NPCX_LVOL_CTRL_ITEMS(1), }, \ - { NPCX_LVOL_CTRL_ITEMS(2), }, \ - { NPCX_LVOL_CTRL_ITEMS(3), }, \ - { NPCX_LVOL_CTRL_ITEMS(4), }, \ - { NPCX_LVOL_CTRL_ITEMS(5), }, } +#define NPCX_LVOL_TABLE \ + { \ + { \ + NPCX_LVOL_CTRL_ITEMS(0), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(1), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(2), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(3), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(4), \ + }, \ + { \ + NPCX_LVOL_CTRL_ITEMS(5), \ + }, \ + } #endif /* __CROS_EC_GPIO_CHIP_NPCX9_H */ diff --git a/chip/npcx/gpio_chip.h b/chip/npcx/gpio_chip.h index 2d0b2b4e9b..5f60cdfb40 100644 --- a/chip/npcx/gpio_chip.h +++ b/chip/npcx/gpio_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,37 +9,40 @@ struct npcx_wui { uint8_t table : 2; uint8_t group : 3; - uint8_t bit : 3; + uint8_t bit : 3; }; /* Macros to initialize the MIWU mapping table. */ #define NPCX_WUI_GPIO_PIN(port, index) NPCX_WUI_GPIO_##port##_##index -#define WUI(tbl, grp, idx) ((struct npcx_wui) { .table = tbl, .group = grp, \ - .bit = idx }) -#define WUI_INT(tbl, grp) WUI(tbl, grp, 0) -#define WUI_NONE ((struct npcx_wui) { .table = MIWU_TABLE_COUNT, .group = 0, \ - .bit = 0 }) +#define WUI(tbl, grp, idx) \ + ((struct npcx_wui){ .table = tbl, .group = grp, .bit = idx }) +#define WUI_INT(tbl, grp) WUI(tbl, grp, 0) +#define WUI_NONE \ + ((struct npcx_wui){ .table = MIWU_TABLE_COUNT, .group = 0, .bit = 0 }) /* Macros to initialize the alternative and low voltage mapping table. */ -#define NPCX_GPIO_NONE ((struct npcx_gpio) {.port = 0, .bit = 0, .valid = 0}) -#define NPCX_GPIO(grp, pin) ((struct npcx_gpio) {.port = GPIO_PORT_##grp, \ - .bit = pin, .valid = 1}) +#define NPCX_GPIO_NONE ((struct npcx_gpio){ .port = 0, .bit = 0, .valid = 0 }) +#define NPCX_GPIO(grp, pin) \ + ((struct npcx_gpio){ .port = GPIO_PORT_##grp, .bit = pin, .valid = 1 }) -#define NPCX_ALT(grp, pin) ((struct npcx_alt) {.group = ALT_GROUP_##grp, \ - .bit = NPCX_DEVALT##grp##_##pin, .inverted = 0 }) -#define NPCX_ALT_INV(grp, pin) ((struct npcx_alt) {.group = ALT_GROUP_##grp, \ - .bit = NPCX_DEVALT##grp##_##pin, .inverted = 1 }) -#define ALT(port, index, _alt) { .gpio = NPCX_GPIO(port, index), \ - .alt = (_alt) }, +#define NPCX_ALT(grp, pin) \ + ((struct npcx_alt){ .group = ALT_GROUP_##grp, \ + .bit = NPCX_DEVALT##grp##_##pin, \ + .inverted = 0 }) +#define NPCX_ALT_INV(grp, pin) \ + ((struct npcx_alt){ .group = ALT_GROUP_##grp, \ + .bit = NPCX_DEVALT##grp##_##pin, \ + .inverted = 1 }) +#define ALT(port, index, _alt) \ + { .gpio = NPCX_GPIO(port, index), .alt = (_alt) }, -#define NPCX_LVOL_CTRL_ITEMS(ctrl) { NPCX_LVOL_CTRL_##ctrl##_0, \ - NPCX_LVOL_CTRL_##ctrl##_1, \ - NPCX_LVOL_CTRL_##ctrl##_2, \ - NPCX_LVOL_CTRL_##ctrl##_3, \ - NPCX_LVOL_CTRL_##ctrl##_4, \ - NPCX_LVOL_CTRL_##ctrl##_5, \ - NPCX_LVOL_CTRL_##ctrl##_6, \ - NPCX_LVOL_CTRL_##ctrl##_7, } +#define NPCX_LVOL_CTRL_ITEMS(ctrl) \ + { \ + NPCX_LVOL_CTRL_##ctrl##_0, NPCX_LVOL_CTRL_##ctrl##_1, \ + NPCX_LVOL_CTRL_##ctrl##_2, NPCX_LVOL_CTRL_##ctrl##_3, \ + NPCX_LVOL_CTRL_##ctrl##_4, NPCX_LVOL_CTRL_##ctrl##_5, \ + NPCX_LVOL_CTRL_##ctrl##_6, NPCX_LVOL_CTRL_##ctrl##_7, \ + } /** * Switch NPCX UART pins back to normal GPIOs. diff --git a/chip/npcx/header.c b/chip/npcx/header.c index 0ba3ee59d6..81e5e986af 100644 --- a/chip/npcx/header.c +++ b/chip/npcx/header.c @@ -1,5 +1,5 @@ /* - * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,65 +10,66 @@ * This header is used by Nuvoton EC Booter. */ -#include - #include "config.h" #include "registers.h" +#include + /* Signature used by fw header */ -#define SIG_FW_EC 0x2A3B4D5E +#define SIG_FW_EC 0x2A3B4D5E /* Definition used by error detection configuration */ -#define CHECK_CRC 0x00 -#define CHECK_CHECKSUM 0x01 -#define ERROR_DETECTION_EN 0x02 +#define CHECK_CRC 0x00 +#define CHECK_CHECKSUM 0x01 +#define ERROR_DETECTION_EN 0x02 #define ERROR_DETECTION_DIS 0x00 /* Code RAM addresses use by header */ /* Put FW at the begin of CODE RAM */ -#define FW_START_ADDR CONFIG_PROGRAM_MEMORY_BASE +#define FW_START_ADDR CONFIG_PROGRAM_MEMORY_BASE /* TODO: It will be filled automatically by ECST */ /* The entry point of reset handler (filled by ECST tool)*/ -#define FW_ENTRY_ADDR 0x100A8169 +#define FW_ENTRY_ADDR 0x100A8169 /* Error detection addresses use by header (A offset relative to flash image) */ -#define ERRCHK_START_ADDR 0x0 -#define ERRCHK_END_ADDR 0x0 +#define ERRCHK_START_ADDR 0x0 +#define ERRCHK_END_ADDR 0x0 /* Firmware Size -> Booter loads RO region after hard reset (16 bytes aligned)*/ -#define FW_SIZE CONFIG_RO_SIZE +#define FW_SIZE CONFIG_RO_SIZE /* FW Header used by NPCX5M5G Booter */ struct __packed fw_header_t { - uint32_t anchor; /* A constant used to verify FW header */ - uint16_t ext_anchor; /* Enable/disable firmware header CRC check */ - uint8_t spi_max_freq; /* Spi maximum allowable clock frequency */ - uint8_t spi_read_mode; /* Spi read mode used for firmware loading */ - uint8_t cfg_err_detect; /* FW load error detection configuration */ - uint32_t fw_load_addr; /* Firmware load start address */ - uint32_t fw_entry; /* Firmware entry point */ + uint32_t anchor; /* A constant used to verify FW header */ + uint16_t ext_anchor; /* Enable/disable firmware header CRC check */ + uint8_t spi_max_freq; /* Spi maximum allowable clock frequency */ + uint8_t spi_read_mode; /* Spi read mode used for firmware loading */ + uint8_t cfg_err_detect; /* FW load error detection configuration */ + uint32_t fw_load_addr; /* Firmware load start address */ + uint32_t fw_entry; /* Firmware entry point */ uint32_t err_detect_start_addr; /* FW error detect start address */ - uint32_t err_detect_end_addr; /* FW error detect end address */ - uint32_t fw_length; /* Firmware length in bytes */ - uint8_t flash_size; /* Indicate SPI flash size */ - uint8_t reserved[26]; /* Reserved bytes */ - uint32_t sig_header; /* The CRC signature of the firmware header */ - uint32_t sig_fw_image; /* The CRC or Checksum of the firmware image */ + uint32_t err_detect_end_addr; /* FW error detect end address */ + uint32_t fw_length; /* Firmware length in bytes */ + uint8_t flash_size; /* Indicate SPI flash size */ + uint8_t reserved[26]; /* Reserved bytes */ + uint32_t sig_header; /* The CRC signature of the firmware header */ + uint32_t sig_fw_image; /* The CRC or Checksum of the firmware image */ } __aligned(1); -__keep __attribute__ ((section(".header"))) +__keep __attribute__((section(".header"))) const struct fw_header_t fw_header = { /* 00 */ SIG_FW_EC, /* 04 */ 0x54E1, /* Header CRC check Enable/Disable -> AB1Eh/54E1h */ - /* 06 */ 0x04, /* 20/25/33/40/50 MHz -> 00/01/02/03/04h */ - /* 07 */ 0x03, /* Normal/Fast/Rev/D_IO/Q_IO Mode -> 00/01/02/03/04h */ - /* 08 */ 0x00, /* Disable CRC check functionality */ + /* 06 */ 0x04, /* 20/25/33/40/50 MHz -> 00/01/02/03/04h */ + /* 07 */ 0x03, /* Normal/Fast/Rev/D_IO/Q_IO Mode -> 00/01/02/03/04h */ + /* 08 */ 0x00, /* Disable CRC check functionality */ /* 09 */ FW_START_ADDR, - /* 0D */ FW_ENTRY_ADDR,/* Filling by ECST tool with -usearmrst option */ + /* 0D */ FW_ENTRY_ADDR, /* Filling by ECST tool with -usearmrst option + */ /* 11 */ ERRCHK_START_ADDR, /* 15 */ ERRCHK_END_ADDR, - /* 19 */ FW_SIZE,/* Filling by ECST tool */ - /* 1D */ 0x0F, /* Flash Size 1/2/4/8/16 Mbytes -> 01/03/07/0F/1Fh */ + /* 19 */ FW_SIZE, /* Filling by ECST tool */ + /* 1D */ 0x0F, /* Flash Size 1/2/4/8/16 Mbytes -> 01/03/07/0F/1Fh */ /* 1E-3F Other fields are filled by ECST tool or reserved */ }; diff --git a/chip/npcx/hwtimer.c b/chip/npcx/hwtimer.c index 92f9843d09..e2e2fe4b19 100644 --- a/chip/npcx/hwtimer.c +++ b/chip/npcx/hwtimer.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,21 +8,21 @@ #include "clock.h" #include "clock_chip.h" #include "common.h" +#include "console.h" #include "hooks.h" #include "hwtimer.h" #include "hwtimer_chip.h" #include "math_util.h" #include "registers.h" -#include "console.h" #include "task.h" #include "timer.h" #include "util.h" /* Depth of event timer */ -#define TICK_EVT_DEPTH 16 /* Depth of event timer Unit: bits */ -#define TICK_EVT_INTERVAL BIT(TICK_EVT_DEPTH) /* Unit: us */ +#define TICK_EVT_DEPTH 16 /* Depth of event timer Unit: bits */ +#define TICK_EVT_INTERVAL BIT(TICK_EVT_DEPTH) /* Unit: us */ #define TICK_EVT_INTERVAL_MASK (TICK_EVT_INTERVAL - 1) /* Mask of interval */ -#define TICK_EVT_MAX_CNT (TICK_EVT_INTERVAL - 1) /* Maximum event counter */ +#define TICK_EVT_MAX_CNT (TICK_EVT_INTERVAL - 1) /* Maximum event counter */ /* Time when event will be expired unit:us */ static volatile uint32_t evt_expired_us; @@ -39,7 +39,7 @@ static volatile uint32_t cur_cnt_us_dbg; #define CPRINTS(...) #else #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) #endif /*****************************************************************************/ @@ -48,7 +48,7 @@ void init_hw_timer(int itim_no, enum ITIM_SOURCE_CLOCK_T source) { /* Select which clock to use for this timer */ UPDATE_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_CKSEL, - source != ITIM_SOURCE_CLOCK_APB2); + source != ITIM_SOURCE_CLOCK_APB2); /* Clear timeout status */ SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_STS); @@ -64,8 +64,8 @@ void init_hw_timer(int itim_no, enum ITIM_SOURCE_CLOCK_T source) /* HWTimer event handlers */ void __hw_clock_event_set(uint32_t deadline) { - fp_t inv_evt_tick = FLOAT_TO_FP(INT_32K_CLOCK/(float)SECOND); - int32_t evt_cnt_us; + fp_t inv_evt_tick = FLOAT_TO_FP(INT_32K_CLOCK / (float)SECOND); + int32_t evt_cnt_us; /* Is deadline min value? */ if (evt_expired_us != 0 && evt_expired_us < deadline) return; @@ -87,10 +87,10 @@ void __hw_clock_event_set(uint32_t deadline) * ITIM count down : event expired : Unit: 1/32768 sec * It must exceed evt_expired_us for process_timers function */ - evt_cnt = FP_TO_INT((fp_inter_t)(evt_cnt_us) * inv_evt_tick); + evt_cnt = FP_TO_INT((fp_inter_t)(evt_cnt_us)*inv_evt_tick); if (evt_cnt > TICK_EVT_MAX_CNT) { - CPRINTS("Event overflow! 0x%08x, us is %d", - evt_cnt, evt_cnt_us); + CPRINTS("Event overflow! 0x%08x, us is %d", evt_cnt, + evt_cnt_us); evt_cnt = TICK_EVT_MAX_CNT; } @@ -136,16 +136,17 @@ uint16_t __hw_clock_event_count(void) /* Returns time delay cause of deep idle */ uint32_t __hw_clock_get_sleep_time(uint16_t pre_evt_cnt) { - fp_t evt_tick = FLOAT_TO_FP(SECOND/(float)INT_32K_CLOCK); + fp_t evt_tick = FLOAT_TO_FP(SECOND / (float)INT_32K_CLOCK); uint32_t sleep_time; uint16_t cnt = __hw_clock_event_count(); /* Event has been triggered but timer ISR doesn't handle it */ if (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_TO_STS)) - sleep_time = FP_TO_INT((fp_inter_t)(pre_evt_cnt+1) * evt_tick); + sleep_time = + FP_TO_INT((fp_inter_t)(pre_evt_cnt + 1) * evt_tick); /* Event hasn't been triggered */ else - sleep_time = FP_TO_INT((fp_inter_t)(pre_evt_cnt+1 - cnt) * + sleep_time = FP_TO_INT((fp_inter_t)(pre_evt_cnt + 1 - cnt) * evt_tick); return sleep_time; @@ -166,7 +167,7 @@ void __hw_clock_event_clear(void) } /* Irq for hwtimer event */ -void __hw_clock_event_irq(void) +static void __hw_clock_event_irq(void) { /* ITIM event module disable */ CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN); @@ -194,7 +195,6 @@ void __hw_clock_event_irq(void) if (evt_expired_us == 0) __hw_clock_event_set(EVT_MAX_EXPIRED_US); #endif - } DECLARE_IRQ(ITIM_INT(ITIM_EVENT_NO), __hw_clock_event_irq, 3); @@ -246,7 +246,7 @@ void __hw_clock_source_set(uint32_t ts) } /* Irq for hwtimer tick */ -void __hw_clock_source_irq(void) +static void __hw_clock_source_irq(void) { /* Is timeout trigger trigger? */ if (IS_BIT_SET(NPCX_ITCTS(ITIM_SYSTEM_NO), NPCX_ITCTS_TO_STS)) { @@ -295,10 +295,9 @@ static void update_prescaler(void) * Ttick_unit = (PRE_8+1) * Tapb2_clk * PRE_8 = (Ttick_unit/Tapb2_clk) -1 */ - NPCX_ITPRE(ITIM_SYSTEM_NO) = (clock_get_apb2_freq() / SECOND) - 1; + NPCX_ITPRE(ITIM_SYSTEM_NO) = (clock_get_apb2_freq() / SECOND) - 1; /* Set event tick unit = 1/32768 sec */ NPCX_ITPRE(ITIM_EVENT_NO) = 0; - } DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT); @@ -311,10 +310,10 @@ void __hw_early_init_hwtimer(uint32_t start_t) /* Enable clock for ITIM peripheral */ clock_enable_peripheral(CGC_OFFSET_TIMER, CGC_TIMER_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); + CGC_MODE_RUN | CGC_MODE_SLEEP); /* init tick & event timer first */ - init_hw_timer(ITIM_SYSTEM_NO, ITIM_SOURCE_CLOCK_APB2); + init_hw_timer(ITIM_SYSTEM_NO, ITIM_SOURCE_CLOCK_APB2); init_hw_timer(ITIM_EVENT_NO, ITIM_SOURCE_CLOCK_32K); /* Set initial prescaler */ diff --git a/chip/npcx/hwtimer_chip.h b/chip/npcx/hwtimer_chip.h index 987f3b52bd..7964d9619b 100644 --- a/chip/npcx/hwtimer_chip.h +++ b/chip/npcx/hwtimer_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,14 +9,14 @@ #define __CROS_EC_HWTIMER_CHIP_H /* Use ITIM32 as main hardware timer */ -#define TICK_ITIM32_MAX_CNT 0xFFFFFFFF +#define TICK_ITIM32_MAX_CNT 0xFFFFFFFF /* Maximum deadline of event */ -#define EVT_MAX_EXPIRED_US TICK_ITIM32_MAX_CNT +#define EVT_MAX_EXPIRED_US TICK_ITIM32_MAX_CNT /* Clock source for ITIM16 */ enum ITIM_SOURCE_CLOCK_T { ITIM_SOURCE_CLOCK_APB2 = 0, - ITIM_SOURCE_CLOCK_32K = 1, + ITIM_SOURCE_CLOCK_32K = 1, }; /** diff --git a/chip/npcx/i2c-npcx5.c b/chip/npcx/i2c-npcx5.c index 6b78fd53f9..ef04b447c6 100644 --- a/chip/npcx/i2c-npcx5.c +++ b/chip/npcx/i2c-npcx5.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -32,7 +32,7 @@ void i2c_select_port(int port) /* Select IO pins for multi-ports I2C controllers */ UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB0SEL, - (port == NPCX_I2C_PORT0_1)); + (port == NPCX_I2C_PORT0_1)); } int i2c_is_raw_mode(int port) @@ -44,4 +44,3 @@ int i2c_is_raw_mode(int port) else return 1; } - diff --git a/chip/npcx/i2c-npcx7.c b/chip/npcx/i2c-npcx7.c index 3f27aff49e..427b9cae9f 100644 --- a/chip/npcx/i2c-npcx7.c +++ b/chip/npcx/i2c-npcx7.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -37,13 +37,13 @@ void i2c_select_port(int port) /* Select I2C ports for the same controller */ else if (port <= NPCX_I2C_PORT4_1) { UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB4SEL, - (port == NPCX_I2C_PORT4_1)); + (port == NPCX_I2C_PORT4_1)); } else if (port <= NPCX_I2C_PORT5_1) { UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB5SEL, - (port == NPCX_I2C_PORT5_1)); + (port == NPCX_I2C_PORT5_1)); } else { UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB6SEL, - (port == NPCX_I2C_PORT6_1)); + (port == NPCX_I2C_PORT6_1)); } } @@ -52,7 +52,7 @@ int i2c_is_raw_mode(int port) int group, bit; if (port == NPCX_I2C_PORT4_1 || port == NPCX_I2C_PORT5_1 || - port == NPCX_I2C_PORT6_1) { + port == NPCX_I2C_PORT6_1) { group = 6; bit = 7 - (port - NPCX_I2C_PORT4_1) / 2; } else { diff --git a/chip/npcx/i2c-npcx9.c b/chip/npcx/i2c-npcx9.c deleted file mode 120000 index b1b16a3198..0000000000 --- a/chip/npcx/i2c-npcx9.c +++ /dev/null @@ -1 +0,0 @@ -i2c-npcx7.c \ No newline at end of file diff --git a/chip/npcx/i2c-npcx9.c b/chip/npcx/i2c-npcx9.c new file mode 100644 index 0000000000..427b9cae9f --- /dev/null +++ b/chip/npcx/i2c-npcx9.c @@ -0,0 +1,70 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* I2C module driver depends on chip series for Chrome EC */ + +#include "common.h" +#include "i2c.h" +#include "i2c_chip.h" +#include "registers.h" +#include "util.h" + +/*****************************************************************************/ +/* IC specific low-level driver depends on chip series */ + +int i2c_port_to_controller(int port) +{ + if (port < 0 || port >= I2C_PORT_COUNT) + return -1; + + if (port <= NPCX_I2C_PORT3_0) + return port; +#ifndef NPCX_PSL_MODE_SUPPORT + else if (port == NPCX_I2C_PORT4_0) + return 4; +#endif + else /* If port >= NPCX_I2C_PORT4_1 */ + return 4 + ((port - NPCX_I2C_PORT4_1 + 1) / 2); +} + +void i2c_select_port(int port) +{ + /* Only I2C 4/5/6 have multiple ports in series npcx7 */ + if (port <= NPCX_I2C_PORT3_0 || port >= NPCX_I2C_PORT7_0) + return; + /* Select I2C ports for the same controller */ + else if (port <= NPCX_I2C_PORT4_1) { + UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB4SEL, + (port == NPCX_I2C_PORT4_1)); + } else if (port <= NPCX_I2C_PORT5_1) { + UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB5SEL, + (port == NPCX_I2C_PORT5_1)); + } else { + UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB6SEL, + (port == NPCX_I2C_PORT6_1)); + } +} + +int i2c_is_raw_mode(int port) +{ + int group, bit; + + if (port == NPCX_I2C_PORT4_1 || port == NPCX_I2C_PORT5_1 || + port == NPCX_I2C_PORT6_1) { + group = 6; + bit = 7 - (port - NPCX_I2C_PORT4_1) / 2; + } else { + group = 2; + if (port <= NPCX_I2C_PORT3_0) + bit = 2 * port; + else + bit = I2C_PORT_COUNT - port; + } + + if (IS_BIT_SET(NPCX_DEVALT(group), bit)) + return 0; + else + return 1; +} diff --git a/chip/npcx/i2c.c b/chip/npcx/i2c.c index 9d72c80c71..ebfba26c58 100644 --- a/chip/npcx/i2c.c +++ b/chip/npcx/i2c.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -24,14 +24,14 @@ #define CPRINTF(...) #else #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) #endif /* Timeout for device should be available after reset (SMBus spec. unit:ms) */ #define I2C_MAX_TIMEOUT 35 /* - * Timeout for SCL held to low by slave device . (SMBus spec. unit:ms). + * Timeout for SCL held to low by peripheral device. (SMBus spec. unit:ms). * Some I2C devices may violate this timing and clock stretch for longer. * TODO: Consider increasing this timeout. */ @@ -41,53 +41,54 @@ * I2C module that supports FIFO mode has 32 bytes Tx FIFO and * 32 bytes Rx FIFO. */ -#define NPCX_I2C_FIFO_MAX_SIZE 32 +#define NPCX_I2C_FIFO_MAX_SIZE 32 /* Macro functions of I2C */ #define I2C_START(ctrl) SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_START) -#define I2C_STOP(ctrl) SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_STOP) -#define I2C_NACK(ctrl) SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_ACK) -/* I2C moudule automatically stall bus after sending slave address */ +#define I2C_STOP(ctrl) SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_STOP) +#define I2C_NACK(ctrl) SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_ACK) +/* I2C module automatically stall bus after sending peripheral address */ #define I2C_STALL(ctrl) SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_STASTRE) #define I2C_WRITE_BYTE(ctrl, data) (NPCX_SMBSDA(ctrl) = data) -#define I2C_READ_BYTE(ctrl, data) (data = NPCX_SMBSDA(ctrl)) +#define I2C_READ_BYTE(ctrl, data) (data = NPCX_SMBSDA(ctrl)) #define I2C_TX_FIFO_OCCUPIED(ctrl) (NPCX_SMBTXF_STS(ctrl) & 0x3F) #define I2C_TX_FIFO_AVAILABLE(ctrl) \ - (NPCX_I2C_FIFO_MAX_SIZE - I2C_TX_FIFO_OCCUPIED(ctrl)) + (NPCX_I2C_FIFO_MAX_SIZE - I2C_TX_FIFO_OCCUPIED(ctrl)) #define I2C_RX_FIFO_OCCUPIED(ctrl) (NPCX_SMBRXF_STS(ctrl) & 0x3F) #define I2C_RX_FIFO_AVAILABLE(ctrl) \ - (NPCX_I2C_FIFO_MAX_SIZE - I2C_RX_FIFO_OCCUPIED(ctrl)) + (NPCX_I2C_FIFO_MAX_SIZE - I2C_RX_FIFO_OCCUPIED(ctrl)) /* Drive the SCL signal to low */ -#define I2C_SCL_STALL(ctrl) \ - (NPCX_SMBCTL3(ctrl) = \ - (NPCX_SMBCTL3(ctrl) & ~BIT(NPCX_SMBCTL3_SCL_LVL)) | \ - BIT(NPCX_SMBCTL3_SDA_LVL)) +#define I2C_SCL_STALL(ctrl) \ + (NPCX_SMBCTL3(ctrl) = \ + (NPCX_SMBCTL3(ctrl) & ~BIT(NPCX_SMBCTL3_SCL_LVL)) | \ + BIT(NPCX_SMBCTL3_SDA_LVL)) /* * Release the SCL signal to be pulled up to high level. * Note: The SCL might be still driven low either by I2C module or external * devices connected to ths bus. */ -#define I2C_SCL_FREE(ctrl) \ - (NPCX_SMBCTL3(ctrl) |= BIT(NPCX_SMBCTL3_SCL_LVL) | \ - BIT(NPCX_SMBCTL3_SDA_LVL)) +#define I2C_SCL_FREE(ctrl) \ + (NPCX_SMBCTL3(ctrl) |= BIT(NPCX_SMBCTL3_SCL_LVL) | \ + BIT(NPCX_SMBCTL3_SDA_LVL)) /* Error values that functions can return */ enum smb_error { - SMB_OK = 0, /* No error */ - SMB_CH_OCCUPIED, /* Channel is already occupied */ - SMB_MEM_POOL_INIT_ERROR, /* Memory pool initialization error */ - SMB_BUS_FREQ_ERROR, /* SMbus freq was not valid */ - SMB_INVLAID_REGVALUE, /* Invalid SMbus register value */ - SMB_UNEXIST_CH_ERROR, /* Channel does not exist */ - SMB_NO_SUPPORT_PTL, /* Not support SMBus Protocol */ - SMB_BUS_ERROR, /* Encounter bus error */ - SMB_MASTER_NO_ADDRESS_MATCH,/* No slave address match (Master Mode)*/ - SMB_READ_DATA_ERROR, /* Read data for SDA error */ - SMB_READ_OVERFLOW_ERROR, /* Read data over than we predict */ - SMB_TIMEOUT_ERROR, /* Timeout expired */ - SMB_MODULE_ISBUSY, /* Module is occupied by other device */ - SMB_BUS_BUSY, /* SMBus is occupied by other device */ + SMB_OK = 0, /* No error */ + SMB_CH_OCCUPIED, /* Channel is already occupied */ + SMB_MEM_POOL_INIT_ERROR, /* Memory pool initialization error */ + SMB_BUS_FREQ_ERROR, /* SMbus freq was not valid */ + SMB_INVLAID_REGVALUE, /* Invalid SMbus register value */ + SMB_UNEXIST_CH_ERROR, /* Channel does not exist */ + SMB_NO_SUPPORT_PTL, /* Not support SMBus Protocol */ + SMB_BUS_ERROR, /* Encounter bus error */ + SMB_NO_ADDRESS_MATCH, /* No peripheral address match */ + /* (Controller Mode) */ + SMB_READ_DATA_ERROR, /* Read data for SDA error */ + SMB_READ_OVERFLOW_ERROR, /* Read data over than we predict */ + SMB_TIMEOUT_ERROR, /* Timeout expired */ + SMB_MODULE_ISBUSY, /* Module is occupied by other device */ + SMB_BUS_BUSY, /* SMBus is occupied by other device */ }; /* @@ -96,7 +97,7 @@ enum smb_error { */ enum smb_oper_state_t { SMB_IDLE, - SMB_MASTER_START, + SMB_CONTROLLER_START, SMB_WRITE_OPER, SMB_READ_OPER, SMB_FAKE_READ_OPER, @@ -107,17 +108,18 @@ enum smb_oper_state_t { /* I2C controller state data */ struct i2c_status { - int flags; /* Flags (I2C_XFER_*) */ - const uint8_t *tx_buf; /* Entry pointer of transmit buffer */ - uint8_t *rx_buf; /* Entry pointer of receive buffer */ - uint16_t sz_txbuf; /* Size of Tx buffer in bytes */ - uint16_t sz_rxbuf; /* Size of rx buffer in bytes */ - uint16_t idx_buf; /* Current index of Tx/Rx buffer */ - uint16_t slave_addr_flags;/* Target slave address */ - enum smb_oper_state_t oper_state;/* Smbus operation state */ - enum smb_error err_code; /* Error code */ - int task_waiting; /* Task waiting on controller */ - uint32_t timeout_us;/* Transaction timeout */ + int flags; /* Flags (I2C_XFER_*) */ + const uint8_t *tx_buf; /* Entry pointer of transmit buffer */ + uint8_t *rx_buf; /* Entry pointer of receive buffer */ + uint16_t sz_txbuf; /* Size of Tx buffer in bytes */ + uint16_t sz_rxbuf; /* Size of rx buffer in bytes */ + uint16_t idx_buf; /* Current index of Tx/Rx buffer */ + uint16_t addr_flags; /* Target address */ + enum smb_oper_state_t oper_state; /* Smbus operation state */ + enum smb_error err_code; /* Error code */ + int task_waiting; /* Task waiting on controller */ + uint32_t timeout_us; /* Transaction timeout */ + uint16_t kbps; /* Speed */ }; /* I2C controller state data array */ static struct i2c_status i2c_stsobjs[I2C_CONTROLLER_COUNT]; @@ -125,27 +127,29 @@ static struct i2c_status i2c_stsobjs[I2C_CONTROLLER_COUNT]; /* I2C timing setting */ struct i2c_timing { uint8_t clock; /* I2C source clock. (Unit: MHz)*/ - uint8_t HLDT; /* I2C hold-time. (Unit: clocks) */ - uint8_t k1; /* k1 = SCL low-time (Unit: clocks) */ - uint8_t k2; /* k2 = SCL high-time (Unit: clocks) */ + uint8_t HLDT; /* I2C hold-time. (Unit: clocks) */ + uint8_t k1; /* k1 = SCL low-time (Unit: clocks) */ + uint8_t k2; /* k2 = SCL high-time (Unit: clocks) */ }; /* I2C timing setting array of 400K & 1M Hz */ static const struct i2c_timing i2c_400k_timings[] = { - {20, 7, 32, 22}, - {15, 7, 24, 18},}; + { 20, 7, 32, 22 }, + { 15, 7, 24, 18 }, +}; const unsigned int i2c_400k_timing_used = ARRAY_SIZE(i2c_400k_timings); static const struct i2c_timing i2c_1m_timings[] = { - {20, 7, 16, 10}, - {15, 7, 14, 10},}; + { 20, 7, 16, 10 }, + { 15, 7, 14, 10 }, +}; const unsigned int i2c_1m_timing_used = ARRAY_SIZE(i2c_1m_timings); /* IRQ for each port */ const uint32_t i2c_irqs[I2C_CONTROLLER_COUNT] = { - NPCX_IRQ_SMB1, NPCX_IRQ_SMB2, NPCX_IRQ_SMB3, NPCX_IRQ_SMB4, + NPCX_IRQ_SMB1, NPCX_IRQ_SMB2, NPCX_IRQ_SMB3, NPCX_IRQ_SMB4, #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 - NPCX_IRQ_SMB5, NPCX_IRQ_SMB6, NPCX_IRQ_SMB7, NPCX_IRQ_SMB8, + NPCX_IRQ_SMB5, NPCX_IRQ_SMB6, NPCX_IRQ_SMB7, NPCX_IRQ_SMB8, #endif }; BUILD_ASSERT(ARRAY_SIZE(i2c_irqs) == I2C_CONTROLLER_COUNT); @@ -196,8 +200,8 @@ static void i2c_abort_data(int controller) SET_BIT(NPCX_SMBST(controller), NPCX_SMBST_NEGACK); /* Wait till STOP condition is generated */ - if (i2c_wait_stop_completed(controller, I2C_MAX_TIMEOUT) - != EC_SUCCESS) { + if (i2c_wait_stop_completed(controller, I2C_MAX_TIMEOUT) != + EC_SUCCESS) { cprintf(CC_I2C, "Abort i2c %02x fail!\n", controller); /* Clear BB (BUS BUSY) bit */ SET_BIT(NPCX_SMBCST(controller), NPCX_SMBCST_BB); @@ -211,13 +215,15 @@ static void i2c_abort_data(int controller) static int i2c_reset(int controller) { uint16_t timeout = I2C_MAX_TIMEOUT; + /* Disable the SMB module */ CLEAR_BIT(NPCX_SMBCTL2(controller), NPCX_SMBCTL2_ENABLE); while (--timeout) { /* WAIT FOR SCL & SDA IS HIGH */ - if (IS_BIT_SET(NPCX_SMBCTL3(controller), NPCX_SMBCTL3_SCL_LVL) - && IS_BIT_SET(NPCX_SMBCTL3(controller), NPCX_SMBCTL3_SDA_LVL)) + if (IS_BIT_SET(NPCX_SMBCTL3(controller), + NPCX_SMBCTL3_SCL_LVL) && + IS_BIT_SET(NPCX_SMBCTL3(controller), NPCX_SMBCTL3_SDA_LVL)) break; msleep(1); } @@ -303,14 +309,13 @@ static void i2c_fifo_write_data(int controller) } for (i = 0; i < len; i++) { I2C_WRITE_BYTE(controller, - p_status->tx_buf[p_status->idx_buf++]); - CPRINTF("%02x ", - p_status->tx_buf[p_status->idx_buf - 1]); + p_status->tx_buf[p_status->idx_buf++]); + CPRINTF("%02x ", p_status->tx_buf[p_status->idx_buf - 1]); } CPRINTF("\n"); } -enum smb_error i2c_master_transaction(int controller) +enum smb_error i2c_controller_transaction(int controller) { /* Set i2c mode to object */ int events = 0; @@ -323,7 +328,7 @@ enum smb_error i2c_master_transaction(int controller) /* Assign current SMB status of controller */ if (p_status->oper_state == SMB_IDLE) { /* New transaction */ - p_status->oper_state = SMB_MASTER_START; + p_status->oper_state = SMB_CONTROLLER_START; /* Clear FIFO and status bit */ if (IS_ENABLED(NPCX_I2C_FIFO_SUPPORT)) { NPCX_SMBFIF_CTS(controller) = @@ -352,13 +357,13 @@ enum smb_error i2c_master_transaction(int controller) * is set simultaneously. */ if (p_status->sz_rxbuf == 1 && - (p_status->flags & I2C_XFER_STOP)) { + (p_status->flags & I2C_XFER_STOP)) { /* * Since SCL is released after reading last * byte from previous transaction, adding a * extra byte for next transaction which let * ec sets NACK bit in time is necessary. - * Or i2c master cannot generate STOP + * Or i2c controller cannot generate STOP * when the last byte is ACK during receiving. */ p_status->sz_rxbuf++; @@ -372,30 +377,30 @@ enum smb_error i2c_master_transaction(int controller) } } else cprintf(CC_I2C, "Unexpected i2c state machine! %d\n", - p_status->oper_state); + p_status->oper_state); if (IS_ENABLED(NPCX_I2C_FIFO_SUPPORT)) { if (p_status->sz_rxbuf > 0) { if (p_status->sz_rxbuf > NPCX_I2C_FIFO_MAX_SIZE) { /* Set RX threshold = FIFO_MAX_SIZE */ SET_FIELD(NPCX_SMBRXF_CTL(controller), - NPCX_SMBRXF_CTL_RX_THR, - NPCX_I2C_FIFO_MAX_SIZE); + NPCX_SMBRXF_CTL_RX_THR, + NPCX_I2C_FIFO_MAX_SIZE); } else { /* * set RX threshold = remaining data bytes * (it should be <= FIFO_MAX_SIZE) */ SET_FIELD(NPCX_SMBRXF_CTL(controller), - NPCX_SMBRXF_CTL_RX_THR, - p_status->sz_rxbuf); + NPCX_SMBRXF_CTL_RX_THR, + p_status->sz_rxbuf); /* * Set LAST bit generate the NACK at the * last byte of the data group in FIFO */ if (p_status->flags & I2C_XFER_STOP) { SET_BIT(NPCX_SMBRXF_CTL(controller), - NPCX_SMBRXF_CTL_LAST); + NPCX_SMBRXF_CTL_LAST); } } @@ -408,8 +413,8 @@ enum smb_error i2c_master_transaction(int controller) } /* Generate a START condition */ - if (p_status->oper_state == SMB_MASTER_START || - p_status->oper_state == SMB_REPEAT_START) { + if (p_status->oper_state == SMB_CONTROLLER_START || + p_status->oper_state == SMB_REPEAT_START) { I2C_START(controller); CPUTS("ST"); } @@ -418,8 +423,8 @@ enum smb_error i2c_master_transaction(int controller) task_enable_irq(i2c_irqs[controller]); /* Wait for transfer complete or timeout */ - events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, - p_status->timeout_us); + events = + task_wait_event_mask(TASK_EVENT_I2C_IDLE, p_status->timeout_us); /* Disable event and error interrupts */ task_disable_irq(i2c_irqs[controller]); @@ -449,8 +454,9 @@ enum smb_error i2c_master_transaction(int controller) i2c_recovery(controller, p_status); /* Wait till STOP condition is generated for normal transaction */ - if (p_status->err_code == SMB_OK && i2c_wait_stop_completed(controller, - I2C_MIN_TIMEOUT) != EC_SUCCESS) { + if (p_status->err_code == SMB_OK && + i2c_wait_stop_completed(controller, I2C_MIN_TIMEOUT) != + EC_SUCCESS) { cprintf(CC_I2C, "STOP fail! scl %02x is held by slave device!\n", controller); @@ -473,7 +479,7 @@ void i2c_done(int controller) /* Clear RXF_TXE bit (RX FIFO full/TX FIFO empty) */ if (IS_ENABLED(NPCX_I2C_FIFO_SUPPORT)) NPCX_SMBFIF_CTS(controller) = - BIT(NPCX_SMBFIF_CTS_RXF_TXE); + BIT(NPCX_SMBFIF_CTS_RXF_TXE); /* Clear SDAST by writing mock byte */ I2C_WRITE_BYTE(controller, 0xFF); @@ -482,10 +488,11 @@ void i2c_done(int controller) /* Set error code */ p_status->err_code = SMB_OK; /* Set SMB status if we need stall bus */ - p_status->oper_state = (p_status->flags & I2C_XFER_STOP) - ? SMB_IDLE : SMB_WRITE_SUSPEND; + p_status->oper_state = (p_status->flags & I2C_XFER_STOP) ? + SMB_IDLE : + SMB_WRITE_SUSPEND; /* - * Disable interrupt for i2c master stall SCL + * Disable interrupt for i2c controller stall SCL * and forbid SDAST generate interrupt * until common layer start other transactions */ @@ -493,8 +500,7 @@ void i2c_done(int controller) task_disable_irq(i2c_irqs[controller]); /* Notify upper layer */ - task_set_event(p_status->task_waiting, - TASK_EVENT_I2C_IDLE, 0); + task_set_event(p_status->task_waiting, TASK_EVENT_I2C_IDLE); CPUTS("-END"); } @@ -512,7 +518,7 @@ static void i2c_handle_receive(int controller) CPUTS("-SP"); } else { /* - * Disable interrupt before i2c master read SDA + * Disable interrupt before i2c controller read SDA * reg (stall SCL) and forbid SDAST generate * interrupt until starting other transactions */ @@ -538,7 +544,7 @@ static void i2c_handle_receive(int controller) /* Read to buf. Skip last byte if meet SMB_FAKE_READ_OPER */ if (p_status->oper_state == SMB_FAKE_READ_OPER && - p_status->idx_buf == (p_status->sz_rxbuf - 1)) + p_status->idx_buf == (p_status->sz_rxbuf - 1)) p_status->idx_buf++; else p_status->rx_buf[p_status->idx_buf++] = data; @@ -546,13 +552,13 @@ static void i2c_handle_receive(int controller) /* last byte is read - end of transaction */ if (p_status->idx_buf == p_status->sz_rxbuf) { /* Set current status */ - p_status->oper_state = (p_status->flags & I2C_XFER_STOP) - ? SMB_IDLE : SMB_READ_SUSPEND; + p_status->oper_state = (p_status->flags & I2C_XFER_STOP) ? + SMB_IDLE : + SMB_READ_SUSPEND; /* Set error code */ p_status->err_code = SMB_OK; /* Notify upper layer of missing data */ - task_set_event(p_status->task_waiting, - TASK_EVENT_I2C_IDLE, 0); + task_set_event(p_status->task_waiting, TASK_EVENT_I2C_IDLE); CPUTS("-END"); } } @@ -622,53 +628,50 @@ static void i2c_fifo_handle_receive(int controller) if (remaining_bytes > 0) { if (remaining_bytes > NPCX_I2C_FIFO_MAX_SIZE) { SET_FIELD(NPCX_SMBRXF_CTL(controller), - NPCX_SMBRXF_CTL_RX_THR, - NPCX_I2C_FIFO_MAX_SIZE); + NPCX_SMBRXF_CTL_RX_THR, + NPCX_I2C_FIFO_MAX_SIZE); } else { SET_FIELD(NPCX_SMBRXF_CTL(controller), - NPCX_SMBRXF_CTL_RX_THR, - remaining_bytes); + NPCX_SMBRXF_CTL_RX_THR, + remaining_bytes); if (p_status->flags & I2C_XFER_STOP) { SET_BIT(NPCX_SMBRXF_CTL(controller), - NPCX_SMBRXF_CTL_LAST); + NPCX_SMBRXF_CTL_LAST); CPRINTS("-FGNA"); } } - } i2c_stall_bus(controller, 0); - } /* last byte is read - end of transaction */ if (p_status->idx_buf == p_status->sz_rxbuf) { /* Set current status */ - p_status->oper_state = (p_status->flags & I2C_XFER_STOP) - ? SMB_IDLE : SMB_READ_SUSPEND; + p_status->oper_state = (p_status->flags & I2C_XFER_STOP) ? + SMB_IDLE : + SMB_READ_SUSPEND; /* Set error code */ p_status->err_code = SMB_OK; /* Notify upper layer of missing data */ - task_set_event(p_status->task_waiting, - TASK_EVENT_I2C_IDLE, 0); + task_set_event(p_status->task_waiting, TASK_EVENT_I2C_IDLE); CPUTS("-END"); } - } static void i2c_handle_sda_irq(int controller) { volatile struct i2c_status *p_status = i2c_stsobjs + controller; - uint8_t addr_8bit = I2C_GET_ADDR(p_status->slave_addr_flags) << 1; + uint8_t addr_8bit = I2C_STRIP_FLAGS(p_status->addr_flags) << 1; /* 1 Issue Start is successful ie. write address byte */ - if (p_status->oper_state == SMB_MASTER_START - || p_status->oper_state == SMB_REPEAT_START) { + if (p_status->oper_state == SMB_CONTROLLER_START || + p_status->oper_state == SMB_REPEAT_START) { /* Prepare address byte */ - if (p_status->sz_txbuf == 0) {/* Receive mode */ + if (p_status->sz_txbuf == 0) { /* Receive mode */ p_status->oper_state = SMB_READ_OPER; /* - * Receiving one or zero bytes - stall bus after START - * condition. If there's no slave devices on bus, FW - * needn't to set ACK bit. + * Receiving one or zero bytes - stall bus after + * START condition. If there's no peripheral + * devices on bus, FW needn't to set ACK bit. */ if (p_status->sz_rxbuf < 2) I2C_STALL(controller); @@ -676,7 +679,7 @@ static void i2c_handle_sda_irq(int controller) /* Write the address to the bus R bit*/ I2C_WRITE_BYTE(controller, (addr_8bit | 0x1)); CPRINTS("-ARR-0x%02x", addr_8bit); - } else {/* Transmit mode */ + } else { /* Transmit mode */ p_status->oper_state = SMB_WRITE_OPER; /* Write the address to the bus W bit*/ I2C_WRITE_BYTE(controller, addr_8bit); @@ -685,14 +688,17 @@ static void i2c_handle_sda_irq(int controller) /* Completed handling START condition */ return; } - /* 2 Handle master write operation */ + /* 2 Handle controller write operation */ else if (p_status->oper_state == SMB_WRITE_OPER) { /* all bytes have been written, in a pure write operation */ if (p_status->idx_buf == p_status->sz_txbuf) { /* no more message */ if (p_status->sz_rxbuf == 0) i2c_done(controller); - /* need to restart & send slave address immediately */ + /* + * need to restart & send peripheral address + * immediately + */ else { /* * Prepare address byte @@ -717,18 +723,20 @@ static void i2c_handle_sda_irq(int controller) * in the SMBnTXF_CTL register. */ if (p_status->sz_rxbuf == 1 && - (p_status->flags & I2C_XFER_STOP) && - !IS_ENABLED(NPCX_I2C_FIFO_SUPPORT)) { + (p_status->flags & I2C_XFER_STOP) && + !IS_ENABLED(NPCX_I2C_FIFO_SUPPORT)) { I2C_NACK(controller); CPUTS("-GNA"); } /* Write the address to the bus R bit*/ - I2C_WRITE_BYTE(controller, - (addr_8bit | 0x1)); + I2C_WRITE_BYTE(controller, (addr_8bit | 0x1)); CPUTS("-ARR"); } } - /* write next byte (not last byte and not slave address */ + /* + * write next byte (not last byte and not peripheral + * address) + */ else { /* * This function can be called in either single-byte @@ -738,9 +746,12 @@ static void i2c_handle_sda_irq(int controller) i2c_fifo_write_data(controller); } } - /* 3 Handle master read operation (read or after a write operation) */ + /* + * 3 Handle controller read operation (read or after a write + * operation) + */ else if (p_status->oper_state == SMB_READ_OPER || - p_status->oper_state == SMB_FAKE_READ_OPER) { + p_status->oper_state == SMB_FAKE_READ_OPER) { if (IS_ENABLED(NPCX_I2C_FIFO_SUPPORT)) i2c_fifo_handle_receive(controller); else @@ -748,7 +759,7 @@ static void i2c_handle_sda_irq(int controller) } } -void i2c_master_int_handler (int controller) +static void i2c_controller_int_handler(int controller) { volatile struct i2c_status *p_status = i2c_stsobjs + controller; @@ -760,14 +771,14 @@ void i2c_master_int_handler (int controller) CPUTS("-SP"); /* Clear BER Bit */ SET_BIT(NPCX_SMBST(controller), NPCX_SMBST_BER); - /* Make sure slave doesn't hold bus by reading */ + /* Make sure peripheral doesn't hold bus by reading */ I2C_READ_BYTE(controller, data); /* Set error code */ p_status->err_code = SMB_BUS_ERROR; /* Notify upper layer */ p_status->oper_state = SMB_IDLE; - task_set_event(p_status->task_waiting, TASK_EVENT_I2C_IDLE, 0); + task_set_event(p_status->task_waiting, TASK_EVENT_I2C_IDLE); CPUTS("-BER"); /* @@ -788,10 +799,10 @@ void i2c_master_int_handler (int controller) /* Clear NEGACK Bit */ SET_BIT(NPCX_SMBST(controller), NPCX_SMBST_NEGACK); /* Set error code */ - p_status->err_code = SMB_MASTER_NO_ADDRESS_MATCH; + p_status->err_code = SMB_NO_ADDRESS_MATCH; /* Notify upper layer */ p_status->oper_state = SMB_IDLE; - task_set_event(p_status->task_waiting, TASK_EVENT_I2C_IDLE, 0); + task_set_event(p_status->task_waiting, TASK_EVENT_I2C_IDLE); CPUTS("-NA"); } @@ -817,7 +828,7 @@ void i2c_master_int_handler (int controller) * register. */ else if ((p_status->flags & I2C_XFER_STOP) && - !IS_ENABLED(NPCX_I2C_FIFO_SUPPORT)) { + !IS_ENABLED(NPCX_I2C_FIFO_SUPPORT)) { I2C_NACK(controller); } @@ -831,9 +842,10 @@ void i2c_master_int_handler (int controller) #if DEBUG_I2C /* SDAST still issued with unexpected state machine */ if (IS_BIT_SET(NPCX_SMBST(controller), NPCX_SMBST_SDAST) && - p_status->oper_state != SMB_WRITE_SUSPEND) { + p_status->oper_state != SMB_WRITE_SUSPEND) { cprints(CC_I2C, "i2c %d unknown state %d, error %d\n", - controller, p_status->oper_state, p_status->err_code); + controller, p_status->oper_state, + p_status->err_code); } #endif } @@ -846,18 +858,42 @@ void i2c_master_int_handler (int controller) */ void handle_interrupt(int controller) { - i2c_master_int_handler(controller); + i2c_controller_int_handler(controller); } -void i2c0_interrupt(void) { handle_interrupt(0); } -void i2c1_interrupt(void) { handle_interrupt(1); } -void i2c2_interrupt(void) { handle_interrupt(2); } -void i2c3_interrupt(void) { handle_interrupt(3); } +static void i2c0_interrupt(void) +{ + handle_interrupt(0); +} +static void i2c1_interrupt(void) +{ + handle_interrupt(1); +} +static void i2c2_interrupt(void) +{ + handle_interrupt(2); +} +static void i2c3_interrupt(void) +{ + handle_interrupt(3); +} #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 -void i2c4_interrupt(void) { handle_interrupt(4); } -void i2c5_interrupt(void) { handle_interrupt(5); } -void i2c6_interrupt(void) { handle_interrupt(6); } -void i2c7_interrupt(void) { handle_interrupt(7); } +static void i2c4_interrupt(void) +{ + handle_interrupt(4); +} +static void i2c5_interrupt(void) +{ + handle_interrupt(5); +} +static void i2c6_interrupt(void) +{ + handle_interrupt(6); +} +static void i2c7_interrupt(void) +{ + handle_interrupt(7); +} #endif DECLARE_IRQ(NPCX_IRQ_SMB1, i2c0_interrupt, 4); @@ -883,14 +919,12 @@ void i2c_set_timeout(int port, uint32_t timeout) return; /* Param is port, but timeout is stored by-controller. */ - i2c_stsobjs[ctrl].timeout_us = - timeout ? timeout : I2C_TIMEOUT_DEFAULT_US; + i2c_stsobjs[ctrl].timeout_us = timeout ? timeout : + I2C_TIMEOUT_DEFAULT_US; } -int chip_i2c_xfer(const int port, - const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) +int chip_i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size, int flags) { volatile struct i2c_status *p_status; int ctrl = i2c_port_to_controller(port); @@ -912,23 +946,23 @@ int chip_i2c_xfer(const int port, i2c_select_port(port); /* Copy data to controller struct */ - p_status->flags = flags; - p_status->tx_buf = out; - p_status->sz_txbuf = out_size; - p_status->rx_buf = in; - p_status->sz_rxbuf = in_size; - p_status->slave_addr_flags = slave_addr_flags; + p_status->flags = flags; + p_status->tx_buf = out; + p_status->sz_txbuf = out_size; + p_status->rx_buf = in; + p_status->sz_rxbuf = in_size; + p_status->addr_flags = addr_flags; /* Reset index & error */ - p_status->idx_buf = 0; - p_status->err_code = SMB_OK; + p_status->idx_buf = 0; + p_status->err_code = SMB_OK; /* Make sure we're in a good state to start */ if ((flags & I2C_XFER_START) && - /* Ignore busy bus for repeated start */ - p_status->oper_state != SMB_WRITE_SUSPEND && - (i2c_bus_busy(ctrl) - || (i2c_get_line_levels(port) != I2C_LINE_IDLE))) { + /* Ignore busy bus for repeated start */ + p_status->oper_state != SMB_WRITE_SUSPEND && + (i2c_bus_busy(ctrl) || + (i2c_get_line_levels(port) != I2C_LINE_IDLE))) { int ret; /* Attempt to unwedge the i2c port */ @@ -944,8 +978,8 @@ int chip_i2c_xfer(const int port, CPUTS("\n"); - /* Start master transaction */ - i2c_master_transaction(ctrl); + /* Start controller transaction */ + i2c_controller_transaction(ctrl); /* Reset task ID */ p_status->task_waiting = TASK_ID_INVALID; @@ -965,7 +999,7 @@ int chip_i2c_xfer(const int port, int i2c_get_line_levels(int port) { return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) | - (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); + (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); } int i2c_raw_get_scl(int port) @@ -980,8 +1014,9 @@ int i2c_raw_get_scl(int port) if (i2c_is_raw_mode(port)) return gpio_get_level(g); else - return IS_BIT_SET(NPCX_SMBCTL3( - i2c_port_to_controller(port)), NPCX_SMBCTL3_SCL_LVL); + return IS_BIT_SET( + NPCX_SMBCTL3(i2c_port_to_controller(port)), + NPCX_SMBCTL3_SCL_LVL); } /* If no SCL pin defined for this port, then return 1 to appear idle */ @@ -1000,102 +1035,175 @@ int i2c_raw_get_sda(int port) if (i2c_is_raw_mode(port)) return gpio_get_level(g); else - return IS_BIT_SET(NPCX_SMBCTL3( - i2c_port_to_controller(port)), NPCX_SMBCTL3_SDA_LVL); + return IS_BIT_SET( + NPCX_SMBCTL3(i2c_port_to_controller(port)), + NPCX_SMBCTL3_SDA_LVL); } - /* If no SDA pin defined for this port, then return 1 to appear idle */ return 1; } /*****************************************************************************/ -/* Hooks */ -static void i2c_freq_changed(void) -{ - int freq, i, j; - for (i = 0; i < i2c_ports_used; i++) { - int bus_freq = i2c_ports[i].kbps; - int ctrl = i2c_port_to_controller(i2c_ports[i].port); - int scl_freq; +static void i2c_port_set_freq(const int ctrl, const int bus_freq_kbps) +{ + int freq, j; + int scl_freq; + const struct i2c_timing *pTiming; + int i2c_timing_used; #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 - /* - * SMB0/1/4/5/6/7 use APB3 clock - * SMB2/3 use APB2 clock - */ - freq = (ctrl < 2 || ctrl > 3) ? - clock_get_apb3_freq() : clock_get_apb2_freq(); + /* + * SMB0/1/4/5/6/7 use APB3 clock + * SMB2/3 use APB2 clock + */ + freq = (ctrl < 2 || ctrl > 3) ? clock_get_apb3_freq() : + clock_get_apb2_freq(); #else /* CHIP_FAMILY_NPCX5 */ - /* - * SMB0/1 use core clock - * SMB2/3 use APB2 clock - */ - freq = (ctrl < 2) ? clock_get_freq() : clock_get_apb2_freq(); + /* + * SMB0/1 use core clock + * SMB2/3 use APB2 clock + */ + freq = (ctrl < 2) ? clock_get_freq() : clock_get_apb2_freq(); #endif - /* - * Set SCL frequency by formula: - * tSCL = 4 * SCLFRQ * tCLK - * fSCL = fCLK / (4*SCLFRQ) - * SCLFRQ = ceil(fCLK/(4*fSCL)) - */ - scl_freq = DIV_ROUND_UP(freq, bus_freq*4000); /* Unit in bps */ - - /* Normal mode if i2c freq is under 100kHz */ - if (bus_freq <= 100) { - /* Set divider value of SCL */ - SET_FIELD(NPCX_SMBCTL2(ctrl), NPCX_SMBCTL2_SCLFRQ7_FIELD - , (scl_freq & 0x7F)); - SET_FIELD(NPCX_SMBCTL3(ctrl), NPCX_SMBCTL3_SCLFRQ2_FIELD - , (scl_freq >> 7)); - } else { - const struct i2c_timing *pTiming; - int i2c_timing_used; + if (bus_freq_kbps == i2c_stsobjs[ctrl].kbps) + return; - /* use Fast Mode */ - SET_BIT(NPCX_SMBCTL3(ctrl), NPCX_SMBCTL3_400K); - /* - * Set SCLH(L)T and hold-time directly for best i2c - * timing condition for all source clocks. Please refer - * Section 7.5.9 "SMBus Timing - Fast Mode" for detail. - */ - if (bus_freq == 400) { - pTiming = i2c_400k_timings; - i2c_timing_used = i2c_400k_timing_used; - } else if (bus_freq == 1000) { - pTiming = i2c_1m_timings; - i2c_timing_used = i2c_1m_timing_used; - } else { - /* Set value from formula */ - NPCX_SMBSCLLT(ctrl) = scl_freq; - NPCX_SMBSCLHT(ctrl) = scl_freq; - cprints(CC_I2C, - "Warning: Use 400K or 1MHz for better timing of I2c %d", - ctrl); - continue; - } + /* + * Set SCL frequency by formula: + * tSCL = 4 * SCLFRQ * tCLK + * fSCL = fCLK / (4*SCLFRQ) + * SCLFRQ = ceil(fCLK/(4*fSCL)) + */ + scl_freq = DIV_ROUND_UP(freq, bus_freq_kbps * 4000); /* Unit in bps */ + + /* Normal mode if I2C freq is under 100kHz */ + if (bus_freq_kbps <= 100) { + i2c_stsobjs[ctrl].kbps = bus_freq_kbps; + /* Set divider value of SCL */ + SET_FIELD(NPCX_SMBCTL2(ctrl), NPCX_SMBCTL2_SCLFRQ7_FIELD, + (scl_freq & 0x7F)); + SET_FIELD(NPCX_SMBCTL3(ctrl), NPCX_SMBCTL3_SCLFRQ2_FIELD, + (scl_freq >> 7)); + return; + } - for (j = 0; j < i2c_timing_used; j++, pTiming++) { - if (pTiming->clock == (freq/SECOND)) { - /* Set SCLH(L)T and hold-time */ - NPCX_SMBSCLLT(ctrl) = pTiming->k1/2; - NPCX_SMBSCLHT(ctrl) = pTiming->k2/2; - SET_FIELD(NPCX_SMBCTL4(ctrl), - NPCX_SMBCTL4_HLDT_FIELD, pTiming->HLDT); - break; - } - } - if (j == i2c_timing_used) - cprints(CC_I2C, - "Error: Please make sure src clock of i2c %d is supported", - ctrl); + /* use Fast Mode */ + SET_BIT(NPCX_SMBCTL3(ctrl), NPCX_SMBCTL3_400K); + /* + * Set SCLH(L)T and hold-time directly for best I2C + * timing condition for all source clocks. Please refer + * Section 7.5.9 "SMBus Timing - Fast Mode" for detail. + */ + if (bus_freq_kbps == 400) { + pTiming = i2c_400k_timings; + i2c_timing_used = i2c_400k_timing_used; + } else if (bus_freq_kbps == 1000) { + pTiming = i2c_1m_timings; + i2c_timing_used = i2c_1m_timing_used; + } else { + i2c_stsobjs[ctrl].kbps = bus_freq_kbps; + /* Set value from formula */ + NPCX_SMBSCLLT(ctrl) = scl_freq; + NPCX_SMBSCLHT(ctrl) = scl_freq; + cprints(CC_I2C, + "Warning: I2C %d: Use 400kHz or 1MHz for better timing", + ctrl); + return; + } + + for (j = 0; j < i2c_timing_used; j++, pTiming++) { + if (pTiming->clock == (freq / SECOND)) { + i2c_stsobjs[ctrl].kbps = bus_freq_kbps; + /* Set SCLH(L)T and hold-time */ + NPCX_SMBSCLLT(ctrl) = pTiming->k1 / 2; + NPCX_SMBSCLHT(ctrl) = pTiming->k2 / 2; + SET_FIELD(NPCX_SMBCTL4(ctrl), NPCX_SMBCTL4_HLDT_FIELD, + pTiming->HLDT); + break; } } + if (j == i2c_timing_used) + cprints(CC_I2C, "Error: I2C %d: src clk %d not supported", ctrl, + freq / SECOND); +} + +/* Hooks */ + +static void i2c_freq_changed(void) +{ + int i; + + for (i = 0; i < I2C_CONTROLLER_COUNT; ++i) { + /* No bus speed configured */ + i2c_stsobjs[i].kbps = 0; + } + + for (i = 0; i < i2c_ports_used; i++) { + const struct i2c_port_t *p; + int ctrl; + + p = &i2c_ports[i]; + ctrl = i2c_port_to_controller(p->port); + if (ctrl < 0) + continue; + i2c_port_set_freq(ctrl, p->kbps); + } } + DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_changed, HOOK_PRIO_DEFAULT); +enum i2c_freq chip_i2c_get_freq(int chip_i2c_port) +{ + int ctrl; + int kbps; + + ctrl = i2c_port_to_controller(chip_i2c_port); + if (ctrl < 0) + return I2C_FREQ_COUNT; + + kbps = i2c_stsobjs[ctrl].kbps; + + if (kbps > 400) + return I2C_FREQ_1000KHZ; + if (kbps > 100) + return I2C_FREQ_400KHZ; + + if (kbps == 100) + return I2C_FREQ_100KHZ; + + return I2C_FREQ_COUNT; +} + +int chip_i2c_set_freq(int chip_i2c_port, enum i2c_freq freq) +{ + int ctrl; + int bus_freq_kbps; + + ctrl = i2c_port_to_controller(chip_i2c_port); + if (ctrl < 0) + return EC_ERROR_INVAL; + + switch (freq) { + case I2C_FREQ_100KHZ: + bus_freq_kbps = 100; + break; + case I2C_FREQ_400KHZ: + bus_freq_kbps = 400; + break; + case I2C_FREQ_1000KHZ: + bus_freq_kbps = 1000; + break; + default: + return EC_ERROR_INVAL; + } + + i2c_port_set_freq(ctrl, bus_freq_kbps); + return EC_SUCCESS; +} + void i2c_init(void) { int i; @@ -1105,10 +1213,10 @@ void i2c_init(void) /* Enable clock for I2C peripheral */ clock_enable_peripheral(CGC_OFFSET_I2C, CGC_I2C_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); + CGC_MODE_RUN | CGC_MODE_SLEEP); #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 clock_enable_peripheral(CGC_OFFSET_I2C2, CGC_I2C_MASK2, - CGC_MODE_RUN | CGC_MODE_SLEEP); + CGC_MODE_RUN | CGC_MODE_SLEEP); #endif /* Set I2C freq */ @@ -1140,4 +1248,3 @@ void i2c_init(void) i2c_init_bus(ctrl); } } - diff --git a/chip/npcx/i2c_chip.h b/chip/npcx/i2c_chip.h index 014e6cddf2..d1a7cf6851 100644 --- a/chip/npcx/i2c_chip.h +++ b/chip/npcx/i2c_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/npcx/keyboard_raw.c b/chip/npcx/keyboard_raw.c index e6b8cad7bd..1774e7353d 100644 --- a/chip/npcx/keyboard_raw.c +++ b/chip/npcx/keyboard_raw.c @@ -1,15 +1,15 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Functions needed by keyboard scanner module for Chrome EC */ +#include "clock.h" #include "common.h" +#include "gpio.h" #include "keyboard_raw.h" #include "keyboard_scan.h" -#include "clock.h" -#include "gpio.h" #include "registers.h" #include "task.h" @@ -20,7 +20,7 @@ void keyboard_raw_init(void) { /* Enable clock for KBS peripheral */ clock_enable_peripheral(CGC_OFFSET_KBS, CGC_KBS_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); + CGC_MODE_RUN | CGC_MODE_SLEEP); /* Ensure top-level interrupt is disabled */ keyboard_raw_enable_interrupt(0); @@ -52,7 +52,7 @@ void keyboard_raw_init(void) gpio_config_module(MODULE_KEYBOARD_SCAN, 1); /* - * Enable interrupts for the inputs. The top-level interrupt is still + * Enable interrupts for the inputs. The top-level interrupt is still * masked off, so this won't trigger interrupts yet. */ @@ -63,7 +63,7 @@ void keyboard_raw_init(void) NPCX_WKEN(MIWU_TABLE_WKKEY, MIWU_GROUP_WKKEY) = 0xFF; /* Select high to low transition (falling edge) */ - NPCX_WKEDG(MIWU_TABLE_WKKEY, MIWU_GROUP_WKKEY) = 0xFF; + NPCX_WKEDG(MIWU_TABLE_WKKEY, MIWU_GROUP_WKKEY) = 0xFF; /* Enable interrupt of WK KBS */ keyboard_raw_enable_interrupt(1); @@ -72,6 +72,7 @@ void keyboard_raw_init(void) /** * Finish initialization after task scheduling has started. */ +#if !defined(CONFIG_KEYBOARD_SCAN_ADC) void keyboard_raw_task_start(void) { /* Enable MIWU to trigger KBS interrupt */ @@ -138,6 +139,7 @@ test_mockable int keyboard_raw_read_rows(void) return (~NPCX_KBSIN) & KB_ROW_MASK; } +#ifndef NPCX_SELECT_KSI_TO_GPIO /** * Enable or disable keyboard interrupts. */ @@ -152,7 +154,7 @@ void keyboard_raw_enable_interrupt(int enable) /* * Interrupt handler for the entire GPIO bank of keyboard rows. */ -void keyboard_raw_interrupt(void) +static void keyboard_raw_interrupt(void) { /* Clear pending input sources used by scanner */ NPCX_WKPCL(MIWU_TABLE_WKKEY, MIWU_GROUP_WKKEY) = 0xFF; @@ -161,9 +163,81 @@ void keyboard_raw_interrupt(void) task_wake(TASK_ID_KEYSCAN); } DECLARE_IRQ(NPCX_IRQ_KSI_WKINTC_1, keyboard_raw_interrupt, 5); +#endif + +#else +void keyboard_raw_task_start(void) +{ + /* Enable interrupts for keyboard matrix inputs */ + keyboard_raw_enable_interrupt(1); +} + +static void set_kb_columns(int level) +{ + gpio_set_level(GPIO_KSO_00, level & BIT(0)); + gpio_set_level(GPIO_KSO_01, level & BIT(1)); + gpio_set_level(GPIO_KSO_02, level & BIT(2)); + gpio_set_level(GPIO_KSO_03, level & BIT(3)); + gpio_set_level(GPIO_KSO_04, level & BIT(4)); + gpio_set_level(GPIO_KSO_05, level & BIT(5)); + gpio_set_level(GPIO_KSO_06, level & BIT(6)); + gpio_set_level(GPIO_KSO_07, level & BIT(7)); + gpio_set_level(GPIO_KSO_08, level & BIT(8)); + gpio_set_level(GPIO_KSO_09, level & BIT(9)); + gpio_set_level(GPIO_KSO_10, level & BIT(10)); + gpio_set_level(GPIO_KSO_11, level & BIT(11)); + gpio_set_level(GPIO_KSO_12, level & BIT(12)); + gpio_set_level(GPIO_KSO_13, level & BIT(13)); + gpio_set_level(GPIO_KSO_14, level & BIT(14)); +} + +void keyboard_raw_drive_column(int col) +{ + if (col == KEYBOARD_COLUMN_NONE) + /* Drive all lines to low */ + set_kb_columns(0); + + else if (col == KEYBOARD_COLUMN_ALL) + /* Drive all lines to high to detect any key press */ + set_kb_columns(0xFFFF); + + else + set_kb_columns(BIT(col)); +} + +void keyboard_raw_enable_interrupt(int enable) +{ + if (enable) { + gpio_enable_interrupt(GPIO_KSI_00); + gpio_enable_interrupt(GPIO_KSI_01); + gpio_enable_interrupt(GPIO_KSI_02); + gpio_enable_interrupt(GPIO_KSI_03); + gpio_enable_interrupt(GPIO_KSI_04); + gpio_enable_interrupt(GPIO_KSI_05); + gpio_enable_interrupt(GPIO_KSI_06); + gpio_enable_interrupt(GPIO_KSI_07); + gpio_enable_interrupt(GPIO_RFR_KEY_L); + } else { + gpio_disable_interrupt(GPIO_KSI_00); + gpio_disable_interrupt(GPIO_KSI_01); + gpio_disable_interrupt(GPIO_KSI_02); + gpio_disable_interrupt(GPIO_KSI_03); + gpio_disable_interrupt(GPIO_KSI_04); + gpio_disable_interrupt(GPIO_KSI_05); + gpio_disable_interrupt(GPIO_KSI_06); + gpio_disable_interrupt(GPIO_KSI_07); + gpio_disable_interrupt(GPIO_RFR_KEY_L); + } +} + +void keyboard_raw_gpio_interrupt(enum gpio_signal signal) +{ + /* Wake the scan task */ + task_wake(TASK_ID_KEYSCAN); +} +#endif int keyboard_raw_is_input_low(int port, int id) { return (NPCX_PDIN(port) & BIT(id)) == 0; } - diff --git a/chip/npcx/lct.c b/chip/npcx/lct.c index 1df2628c4f..8f720e1376 100644 --- a/chip/npcx/lct.c +++ b/chip/npcx/lct.c @@ -1,23 +1,22 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* LCT (Long Countdown Timer) module for Chrome EC */ -#include "lct_chip.h" #include "console.h" #include "hooks.h" +#include "lct_chip.h" #include "registers.h" #include "rtc.h" #include "task.h" #include "timer.h" #include "util.h" -#define LCT_CLK_ENABLE_DELAY_USEC 150 -#define LCT_WEEKS_MAX 15 +#define LCT_CLK_ENABLE_DELAY_USEC 150 -#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) void npcx_lct_sel_power_src(enum NPCX_LCT_PWR_SRC pwr_src) { @@ -68,7 +67,7 @@ void npcx_lct_config(int seconds, int psl_ena, int int_ena) } /* LCT can count max to (16 weeks - 1 second) */ - if (seconds >= (LCT_WEEKS_MAX + 1) * SECS_PER_WEEK) { + if (seconds > NPCX_LCT_MAX) { CPRINTS("LCT time is out of range"); return; } @@ -94,7 +93,27 @@ void npcx_lct_config(int seconds, int psl_ena, int int_ena) if (int_ena) SET_BIT(NPCX_LCTCONT, NPCX_LCTCONT_EVEN); +} +uint32_t npcx_lct_get_time(void) +{ + uint32_t second; + uint8_t week, day, hour, minute; + + do { + week = NPCX_LCTWEEK; + day = NPCX_LCTDAY; + hour = NPCX_LCTHOUR; + minute = NPCX_LCTMINUTE; + second = NPCX_LCTSECOND; + } while (week != NPCX_LCTWEEK || day != NPCX_LCTDAY || + hour != NPCX_LCTHOUR || minute != NPCX_LCTMINUTE || + second != NPCX_LCTSECOND); + + second += minute * SECS_PER_MINUTE + hour * SECS_PER_HOUR + + day * SECS_PER_DAY + week * SECS_PER_WEEK; + + return second; } void npcx_lct_clear_event(void) @@ -124,7 +143,7 @@ static void npcx_lct_init(void) DECLARE_HOOK(HOOK_INIT, npcx_lct_init, HOOK_PRIO_DEFAULT); #ifdef CONFIG_CMD_RTC_ALARM -static int command_lctalarm(int argc, char **argv) +static int command_lctalarm(int argc, const char **argv) { char *e; int seconds; @@ -140,9 +159,9 @@ static int command_lctalarm(int argc, char **argv) npcx_lct_config(seconds, 0, 1); task_disable_irq(NPCX_IRQ_LCT_WKINTF_2); /* Enable wake-up input sources & clear pending bit */ - NPCX_WKPCL(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + NPCX_WKPCL(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; NPCX_WKINEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; - NPCX_WKEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + NPCX_WKEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; task_enable_irq(NPCX_IRQ_LCT_WKINTF_2); npcx_lct_enable(1); diff --git a/chip/npcx/lct_chip.h b/chip/npcx/lct_chip.h index 9e612f9e53..8b4ee804cf 100644 --- a/chip/npcx/lct_chip.h +++ b/chip/npcx/lct_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,11 +6,11 @@ #ifndef __CROS_EC_LCT_CHIP_H #define __CROS_EC_LCT_CHIP_H #include "registers.h" +#include "rtc.h" -enum NPCX_LCT_PWR_SRC { - NPCX_LCT_PWR_SRC_VCC1, - NPCX_LCT_PWR_SRC_VSBY -}; +#define NPCX_LCT_MAX (16 * SECS_PER_WEEK - 1) + +enum NPCX_LCT_PWR_SRC { NPCX_LCT_PWR_SRC_VCC1, NPCX_LCT_PWR_SRC_VSBY }; void npcx_lct_config(int seconds, int psl_ena, int int_ena); void npcx_lct_enable(uint8_t enable); @@ -19,4 +19,7 @@ void npcx_lct_sel_power_src(enum NPCX_LCT_PWR_SRC pwr_src); void npcx_lct_clear_event(void); int npcx_lct_is_event_set(void); -#endif /* __CROS_EC_LCT_CHIP_H */ +/* return the current time of LCT in second */ +uint32_t npcx_lct_get_time(void); + +#endif /* __CROS_EC_LCT_CHIP_H */ diff --git a/chip/npcx/lfw/ec_lfw.h b/chip/npcx/lfw/ec_lfw.h index 88c0a9ed83..3b7e4da459 100644 --- a/chip/npcx/lfw/ec_lfw.h +++ b/chip/npcx/lfw/ec_lfw.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/chip/npcx/lpc.c b/chip/npcx/lpc.c index d614c1788b..b44420e025 100644 --- a/chip/npcx/lpc.c +++ b/chip/npcx/lpc.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,6 +10,7 @@ #include "clock.h" #include "common.h" #include "console.h" +#include "espi.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" @@ -19,12 +20,12 @@ #include "lpc_chip.h" #include "port80.h" #include "registers.h" -#include "system.h" #include "sib_chip.h" +#include "system.h" +#include "system_chip.h" #include "task.h" #include "uart.h" #include "util.h" -#include "system_chip.h" /* Console output macros */ #if !(DEBUG_LPC) @@ -32,24 +33,30 @@ #define CPRINTS(...) #else #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) #endif /* PM channel definitions */ -#define PMC_ACPI PM_CHAN_1 +#define PMC_ACPI PM_CHAN_1 #define PMC_HOST_CMD PM_CHAN_2 -static struct host_packet lpc_packet; -static struct host_cmd_handler_args host_cmd_args; -static uint8_t host_cmd_flags; /* Flags from host command */ -static uint8_t shm_mem_host_cmd[256] __aligned(8); -static uint8_t shm_memmap[256] __aligned(8); +/* Microseconds to wait for eSPI VW changes to propagate */ +#define ESPI_DIRTY_WAIT_TIME_US 150 + +#define PORT80_MAX_BUF_SIZE 16 +static uint16_t port80_buf[PORT80_MAX_BUF_SIZE]; + +static struct host_packet lpc_packet; +static struct host_cmd_handler_args host_cmd_args; +static uint8_t host_cmd_flags; /* Flags from host command */ +static uint8_t shm_mem_host_cmd[256] __aligned(8); +static uint8_t shm_memmap[256] __aligned(8); /* Params must be 32-bit aligned */ static uint8_t params_copy[EC_LPC_HOST_PACKET_SIZE] __aligned(4); static int init_done; -static struct ec_lpc_host_args * const lpc_host_args = - (struct ec_lpc_host_args *)shm_mem_host_cmd; +static struct ec_lpc_host_args *const lpc_host_args = + (struct ec_lpc_host_args *)shm_mem_host_cmd; /*****************************************************************************/ /* IC specific low-level driver */ @@ -83,7 +90,7 @@ static void lpc_task_enable_irq(void) #endif task_enable_irq(NPCX_IRQ_PM_CHAN_IBF); task_enable_irq(NPCX_IRQ_PORT80); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI task_enable_irq(NPCX_IRQ_ESPI); /* Virtual Wire: SLP_S3/4/5, SUS_STAT, PLTRST, OOB_RST_WARN */ task_enable_irq(NPCX_IRQ_WKINTA_2); @@ -102,7 +109,7 @@ static void lpc_task_disable_irq(void) #endif task_disable_irq(NPCX_IRQ_PM_CHAN_IBF); task_disable_irq(NPCX_IRQ_PORT80); -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI task_disable_irq(NPCX_IRQ_ESPI); /* Virtual Wire: SLP_S3/4/5, SUS_STAT, PLTRST, OOB_RST_WARN */ task_disable_irq(NPCX_IRQ_WKINTA_2); @@ -134,7 +141,7 @@ static void lpc_generate_smi(void) udelay(65); /* Set signal high, now that we've generated the edge */ gpio_set_level(GPIO_PCH_SMI_L, 1); -#elif defined(CONFIG_HOSTCMD_ESPI) +#elif defined(CONFIG_HOST_INTERFACE_ESPI) /* * Don't use SET_BIT/CLEAR_BIT macro to toggle SMIB/SCIB to generate * virtual wire. Use NPCX_VW_SMI/NPCX_VW_SCI macro instead. @@ -142,20 +149,21 @@ static void lpc_generate_smi(void) * from SMIB/SCIB doesn't really reflect the SMI/SCI status. SMI/SCI * status should be read from bit 1/0 in eSPI VMEVSM(2) register. */ - NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SMI(1); - udelay(65); /* Generate a falling edge */ + espi_wait_vw_not_dirty(VW_SMI_L, ESPI_DIRTY_WAIT_TIME_US); NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SMI(0); - udelay(65); + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); + espi_wait_vw_not_dirty(VW_SMI_L, ESPI_DIRTY_WAIT_TIME_US); + /* Set signal high */ NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SMI(1); #else /* SET SMIB bit to pull SMI_L to high.*/ SET_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SMIB); - udelay(65); + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); /* Generate a falling edge */ CLEAR_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SMIB); - udelay(65); + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); /* Set signal high */ SET_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SMIB); #endif @@ -180,7 +188,7 @@ static void lpc_generate_sci(void) udelay(65); /* Set signal high, now that we've generated the edge */ gpio_set_level(CONFIG_SCI_GPIO, 1); -#elif defined(CONFIG_HOSTCMD_ESPI) +#elif defined(CONFIG_HOST_INTERFACE_ESPI) /* * Don't use SET_BIT/CLEAR_BIT macro to toggle SMIB/SCIB to generate * virtual wire. Use NPCX_VW_SMI/NPCX_VW_SCI macro instead. @@ -188,20 +196,21 @@ static void lpc_generate_sci(void) * from SMIB/SCIB doesn't really reflect the SMI/SCI status. SMI/SCI * status should be read from bit 1/0 in eSPI VMEVSM(2) register. */ - NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SCI(1); - udelay(65); /* Generate a falling edge */ + espi_wait_vw_not_dirty(VW_SCI_L, ESPI_DIRTY_WAIT_TIME_US); NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SCI(0); - udelay(65); + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); + espi_wait_vw_not_dirty(VW_SCI_L, ESPI_DIRTY_WAIT_TIME_US); + /* Set signal high */ NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SCI(1); #else /* Set SCIB bit to pull SCI_L to high.*/ SET_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SCIB); - udelay(65); + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); /* Generate a falling edge */ CLEAR_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SCIB); - udelay(65); + udelay(CONFIG_HOST_INTERFACE_ESPI_DEFAULT_VW_WIDTH_US); /* Set signal high */ SET_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SCIB); #endif @@ -251,15 +260,13 @@ static void lpc_send_response(struct host_cmd_handler_args *args) } /* New-style response */ - lpc_host_args->flags = - (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) | - EC_HOST_ARGS_FLAG_TO_HOST; + lpc_host_args->flags = (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) | + EC_HOST_ARGS_FLAG_TO_HOST; lpc_host_args->data_size = size; csum = args->command + lpc_host_args->flags + - lpc_host_args->command_version + - lpc_host_args->data_size; + lpc_host_args->command_version + lpc_host_args->data_size; for (i = 0, out = (uint8_t *)args->response; i < size; i++, out++) csum += *out; @@ -291,13 +298,13 @@ static void lpc_send_response_packet(struct host_packet *pkt) int lpc_keyboard_has_char(void) { /* if OBF bit is '1', that mean still have a data in DBBOUT */ - return (NPCX_HIKMST&0x01) ? 1 : 0; + return (NPCX_HIKMST & 0x01) ? 1 : 0; } int lpc_keyboard_input_pending(void) { /* if IBF bit is '1', that mean still have a data in DBBIN */ - return (NPCX_HIKMST&0x02) ? 1 : 0; + return (NPCX_HIKMST & 0x02) ? 1 : 0; } /* Put a char to host buffer by HIKDO and send IRQ if specified. */ @@ -398,7 +405,7 @@ void lpc_update_host_event_status(void) /* Copy host events to mapped memory */ *(host_event_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = - lpc_get_host_events(); + lpc_get_host_events(); lpc_task_enable_irq(); @@ -516,7 +523,7 @@ static void handle_host_write(int is_cmd) /* Interrupt handlers */ #ifdef HAS_TASK_KEYPROTO /* KB controller input buffer full ISR */ -void lpc_kbc_ibf_interrupt(void) +static void lpc_kbc_ibf_interrupt(void) { uint8_t status; uint8_t ibf; @@ -540,7 +547,7 @@ void lpc_kbc_ibf_interrupt(void) DECLARE_IRQ(NPCX_IRQ_KBC_IBF, lpc_kbc_ibf_interrupt, 4); /* KB controller output buffer empty ISR */ -void lpc_kbc_obe_interrupt(void) +static void lpc_kbc_obe_interrupt(void) { /* Disable KBC OBE interrupt */ CLEAR_BIT(NPCX_HICTRL, NPCX_HICTRL_OBECIE); @@ -556,38 +563,70 @@ DECLARE_IRQ(NPCX_IRQ_KBC_OBE, lpc_kbc_obe_interrupt, 4); #endif /* PM channel input buffer full ISR */ -void lpc_pmc_ibf_interrupt(void) +static void lpc_pmc_ibf_interrupt(void) { /* Channel-1 for ACPI usage*/ /* Channel-2 for Host Command usage , so the argument data had been * put on the share memory firstly*/ if (NPCX_HIPMST(PMC_ACPI) & 0x02) - handle_acpi_write((NPCX_HIPMST(PMC_ACPI)&0x08) ? 1 : 0); + handle_acpi_write((NPCX_HIPMST(PMC_ACPI) & 0x08) ? 1 : 0); else if (NPCX_HIPMST(PMC_HOST_CMD) & 0x02) - handle_host_write((NPCX_HIPMST(PMC_HOST_CMD)&0x08) ? 1 : 0); + handle_host_write((NPCX_HIPMST(PMC_HOST_CMD) & 0x08) ? 1 : 0); } DECLARE_IRQ(NPCX_IRQ_PM_CHAN_IBF, lpc_pmc_ibf_interrupt, 4); /* PM channel output buffer empty ISR */ -void lpc_pmc_obe_interrupt(void) +static void lpc_pmc_obe_interrupt(void) { } DECLARE_IRQ(NPCX_IRQ_PM_CHAN_OBE, lpc_pmc_obe_interrupt, 4); -void lpc_port80_interrupt(void) +static void lpc_port80_interrupt(void) { - /* Send port 80 data to UART continuously if FIFO is not empty */ - while (IS_BIT_SET(NPCX_DP80STS, 6)) - port_80_write(NPCX_DP80BUF); + uint8_t i; + uint8_t count = 0; + uint32_t code = 0; + + /* buffer Port80 data to the local buffer if FIFO is not empty */ + while (IS_BIT_SET(NPCX_DP80STS, NPCX_DP80STS_FNE) && + (count < ARRAY_SIZE(port80_buf))) + port80_buf[count++] = NPCX_DP80BUF; + + for (i = 0; i < count; i++) { + uint8_t offset; + uint32_t buf_data; + + buf_data = port80_buf[i]; + offset = GET_FIELD(buf_data, NPCX_DP80BUF_OFFS_FIELD); + code |= (buf_data & 0xFF) << (8 * offset); + + if (i == count - 1) { + port_80_write(code); + break; + } + + /* peek the offset of the next byte */ + buf_data = port80_buf[i + 1]; + offset = GET_FIELD(buf_data, NPCX_DP80BUF_OFFS_FIELD); + /* + * If the peeked next byte's offset is 0 means it is the start + * of the new code. Pass the current code to Port80 + * common layer. + */ + if (offset == 0) { + port_80_write(code); + code = 0; + } + } /* If FIFO is overflow */ - if (IS_BIT_SET(NPCX_DP80STS, 7)) { - SET_BIT(NPCX_DP80STS, 7); + if (IS_BIT_SET(NPCX_DP80STS, NPCX_DP80STS_FOR)) { + SET_BIT(NPCX_DP80STS, NPCX_DP80STS_FOR); CPRINTS("DP80 FIFO Overflow!"); } /* Clear pending bit of host writing */ - SET_BIT(NPCX_DP80STS, 5); + SET_BIT(NPCX_DP80STS, NPCX_DP80STS_FWR); } DECLARE_IRQ(NPCX_IRQ_PORT80, lpc_port80_interrupt, 4); @@ -649,19 +688,26 @@ void host_register_init(void) /* LDN register = 0x0F(SHM) */ sib_write_reg(SIO_OFFSET, 0x07, 0x0F); /* WIN1&2 mapping to IO */ - sib_write_reg(SIO_OFFSET, 0xF1, - sib_read_reg(SIO_OFFSET, 0xF1) | 0x30); + sib_write_reg(SIO_OFFSET, 0xF1, sib_read_reg(SIO_OFFSET, 0xF1) | 0x30); /* WIN1 as Host Command on the IO:0x0800 */ sib_write_reg(SIO_OFFSET, 0xF5, 0x08); sib_write_reg(SIO_OFFSET, 0xF4, 0x00); /* WIN2 as MEMMAP on the IO:0x900 */ sib_write_reg(SIO_OFFSET, 0xF9, 0x09); sib_write_reg(SIO_OFFSET, 0xF8, 0x00); + + /* + * eSPI allows sending 4 bytes of Port80 code in a single PUT_IOWR_SHORT + * transaction. When setting OFS0_SEL~OFS3_SEL in DPAR1 register to 1, + * EC hardware will put those 4 bytes of Port80 code to DP80BUF FIFO. + * This is only supported when CHIP_FAMILY >= NPCX9. + */ + if (IS_ENABLED(CONFIG_HOST_INTERFACE_ESPI)) + sib_write_reg(SIO_OFFSET, 0xFD, 0x0F); /* enable SHM */ sib_write_reg(SIO_OFFSET, 0x30, 0x01); CPRINTS("Host settings are done!"); - } #ifdef CONFIG_CHIPSET_RESET_HOOK @@ -678,14 +724,14 @@ int lpc_get_pltrst_asserted(void) return IS_BIT_SET(NPCX_MSWCTL1, NPCX_MSWCTL1_PLTRST_ACT); } -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI /* Initialize host settings by interrupt */ void lpc_lreset_pltrst_handler(void) { int pltrst_asserted; /* Clear pending bit of WUI */ - SET_BIT(NPCX_WKPCL(MIWU_TABLE_0 , MIWU_GROUP_5), 7); + SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_5), 7); /* Ignore PLTRST# from SOC if it is not valid */ if (chipset_pltrst_is_valid && !chipset_pltrst_is_valid()) @@ -720,7 +766,7 @@ static void lpc_init(void) { /* Enable clock for LPC peripheral */ clock_enable_peripheral(CGC_OFFSET_LPC, CGC_LPC_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); + CGC_MODE_RUN | CGC_MODE_SLEEP); /* * In npcx5/7, the host interface type (HIF_TYP_SEL in the DEVCNT * register) is updated by booter after VCC1 Power-Up reset according to @@ -728,7 +774,7 @@ static void lpc_init(void) * In npcx9, the booter will not do this anymore. The HIF_TYP_SEL * field should be set by firmware. */ -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI /* Initialize eSPI module */ NPCX_DEVCNT |= 0x08; espi_init(); @@ -744,7 +790,7 @@ static void lpc_init(void) /* Clear Host Access Hold state */ NPCX_SMC_CTL = 0xC0; -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI /* * Set alternative pin from GPIO to CLKRUN no matter SERIRQ is under * continuous or quiet mode. @@ -757,7 +803,7 @@ static void lpc_init(void) * valid if CONFIG_SCI_GPIO isn't defined. eSPI sends SMI/SCI through VW * automatically by toggling them, too. It's unnecessary to set pin mux. */ -#if !defined(CONFIG_SCI_GPIO) && !defined(CONFIG_HOSTCMD_ESPI) +#if !defined(CONFIG_SCI_GPIO) && !defined(CONFIG_HOST_INTERFACE_ESPI) SET_BIT(NPCX_DEVALT(1), NPCX_DEVALT1_EC_SCI_SL); SET_BIT(NPCX_DEVALT(1), NPCX_DEVALT1_SMI_SL); #endif @@ -789,8 +835,8 @@ static void lpc_init(void) /* We support LPC args and version 3 protocol */ *(lpc_get_memmap_range() + EC_MEMMAP_HOST_CMD_FLAGS) = - EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED | - EC_HOST_CMD_FLAG_VERSION_3; + EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED | + EC_HOST_CMD_FLAG_VERSION_3; /* * Clear processing flag before enabling lpc's interrupts in case @@ -804,7 +850,7 @@ static void lpc_init(void) /* * Set required control value (avoid setting HOSTWAIT bit at this stage) */ - NPCX_SMC_CTL = NPCX_SMC_CTL&~0x7F; + NPCX_SMC_CTL = NPCX_SMC_CTL & ~0x7F; /* Clear status */ NPCX_SMC_STS = NPCX_SMC_STS; @@ -833,7 +879,7 @@ static void lpc_init(void) * Init PORT80 * Enable Port80, Enable Port80 function & Interrupt & Read auto */ -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI NPCX_DP80CTL = 0x2b; #else NPCX_DP80CTL = 0x29; @@ -853,8 +899,8 @@ static void lpc_init(void) CLEAR_BIT(NPCX_HIPMCTL(PMC_ACPI), NPCX_HIPMCTL_SCIPOL); CLEAR_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SMIPOL); /* Set SMIB/SCIB to make sure SMI/SCI are high at init */ - NPCX_HIPMIC(PMC_ACPI) = NPCX_HIPMIC(PMC_ACPI) - | BIT(NPCX_HIPMIC_SMIB) | BIT(NPCX_HIPMIC_SCIB); + NPCX_HIPMIC(PMC_ACPI) = NPCX_HIPMIC(PMC_ACPI) | BIT(NPCX_HIPMIC_SMIB) | + BIT(NPCX_HIPMIC_SCIB); #ifndef CONFIG_SCI_GPIO /* * Allow SMI/SCI generated from PM module. @@ -883,7 +929,7 @@ static void lpc_init(void) /* initial IO port address via SIB-write modules */ host_register_init(); #else -#ifndef CONFIG_HOSTCMD_ESPI +#ifndef CONFIG_HOST_INTERFACE_ESPI /* * Initialize LRESET# interrupt only in case of LPC. For eSPI, there is * no dedicated GPIO pin for LRESET/PLTRST. PLTRST is indicated as a VW @@ -921,14 +967,13 @@ static enum ec_status lpc_get_protocol_info(struct host_cmd_handler_args *args) args->response_size = sizeof(*r); - return EC_SUCCESS; + return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, - lpc_get_protocol_info, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, lpc_get_protocol_info, + EC_VER_MASK(0)); #if DEBUG_LPC -static int command_lpc(int argc, char **argv) +static int command_lpc(int argc, const char **argv) { if (argc == 1) return EC_ERROR_PARAM1; diff --git a/chip/npcx/lpc_chip.h b/chip/npcx/lpc_chip.h index 607fdde5fa..872b20f915 100644 --- a/chip/npcx/lpc_chip.h +++ b/chip/npcx/lpc_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/npcx/peci.c b/chip/npcx/peci.c index f3145bd2a7..8a4372f7bd 100644 --- a/chip/npcx/peci.c +++ b/chip/npcx/peci.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,35 +15,33 @@ #include "peci.h" #include "registers.h" #include "task.h" -#include "timer.h" #include "temp_sensor.h" +#include "timer.h" #include "util.h" - /* Initial PECI baud rate */ -#define PECI_BAUD_RATE 750000 - -#define TEMP_AVG_LENGTH 4 /* Should be power of 2 */ +#define PECI_BAUD_RATE 750000 +#define TEMP_AVG_LENGTH 4 /* Should be power of 2 */ /* PECI Time-out */ -#define PECI_DONE_TIMEOUT_US (10*MSEC) +#define PECI_DONE_TIMEOUT_US (10 * MSEC) -#define NULL_PENDING_TASK_ID 0xFFFFFFFF -#define PECI_MAX_FIFO_SIZE 16 -#define PROC_SOCKET 0x30 +#define NULL_PENDING_TASK_ID 0xFFFFFFFF +#define PECI_MAX_FIFO_SIZE 16 +#define PROC_SOCKET 0x30 /* PECI Command Code */ enum peci_command_t { - PECI_COMMAND_PING = 0x00, - PECI_COMMAND_GET_DIB = 0xF7, - PECI_COMMAND_GET_TEMP = 0x01, - PECI_COMMAND_RD_PKG_CFG = 0xA1, - PECI_COMMAND_WR_PKG_CFG = 0xA5, - PECI_COMMAND_RD_IAMSR = 0xB1, - PECI_COMMAND_RD_PCI_CFG = 0x61, - PECI_COMMAND_RD_PCI_CFG_LOCAL = 0xE1, - PECI_COMMAND_WR_PCI_CFG_LOCAL = 0xE5, - PECI_COMMAND_NONE = 0xFF + PECI_COMMAND_PING = 0x00, + PECI_COMMAND_GET_DIB = 0xF7, + PECI_COMMAND_GET_TEMP = 0x01, + PECI_COMMAND_RD_PKG_CFG = 0xA1, + PECI_COMMAND_WR_PKG_CFG = 0xA5, + PECI_COMMAND_RD_IAMSR = 0xB1, + PECI_COMMAND_RD_PCI_CFG = 0x61, + PECI_COMMAND_RD_PCI_CFG_LOCAL = 0xE1, + PECI_COMMAND_WR_PCI_CFG_LOCAL = 0xE5, + PECI_COMMAND_NONE = 0xFF }; #define PECI_COMMAND_GET_TEMP_WR_LENS 0x00 @@ -68,12 +66,8 @@ static int peci_pending_task_id; * @param *wr_data Buffer pointer of write data * @return TASK_EVENT_PECI_DONE that mean slave had a response */ -static uint32_t peci_trans( - uint8_t wr_length, - uint8_t rd_length, - enum peci_command_t cmd_code, - uint8_t *wr_data -) +static uint32_t peci_trans(uint8_t wr_length, uint8_t rd_length, + enum peci_command_t cmd_code, uint8_t *wr_data) { uint32_t events; /* Ensure no PECI transaction is in progress */ @@ -100,7 +94,7 @@ static uint32_t peci_trans( /* Write-Length */ if (cmd_code != PECI_COMMAND_PING) { if ((cmd_code == PECI_COMMAND_WR_PKG_CFG) || - (cmd_code == PECI_COMMAND_WR_PCI_CFG_LOCAL)) { + (cmd_code == PECI_COMMAND_WR_PCI_CFG_LOCAL)) { /*CMD+AWFCS*/ NPCX_PECI_WR_LENGTH = wr_length + 2; /* Enable AWFCS */ @@ -110,7 +104,7 @@ static uint32_t peci_trans( NPCX_PECI_WR_LENGTH = wr_length + 1; /* Enable AWFCS */ CLEAR_BIT(NPCX_PECI_CTL_STS, - NPCX_PECI_CTL_STS_AWFCS_EN); + NPCX_PECI_CTL_STS_AWFCS_EN); } } @@ -119,9 +113,7 @@ static uint32_t peci_trans( /* It should be using a interrupt , don't waste cpu computing power */ peci_pending_task_id = task_get_current(); - return task_wait_event_mask(TASK_EVENT_PECI_DONE, - PECI_DONE_TIMEOUT_US); - + return task_wait_event_mask(TASK_EVENT_PECI_DONE, PECI_DONE_TIMEOUT_US); } /** @@ -143,8 +135,8 @@ int peci_get_cpu_temp(void) /* Start PECI trans */ events = peci_trans(PECI_COMMAND_GET_TEMP_WR_LENS, - PECI_COMMAND_GET_TEMP_RD_LENS, - PECI_COMMAND_GET_TEMP, NULL); + PECI_COMMAND_GET_TEMP_RD_LENS, + PECI_COMMAND_GET_TEMP, NULL); /* if return DONE , that mean slave had a PECI response */ if ((events & TASK_EVENT_PECI_DONE) == TASK_EVENT_PECI_DONE) { /* check CRC & ABRT */ @@ -223,7 +215,7 @@ static void peci_freq_changed(void) * Maximum bit rate should not extend the field's boundaries. */ if (freq != 0) { - baud = (uint8_t)(freq / (4 * PECI_BAUD_RATE)) - 1; + baud = (uint8_t)(freq / (4 * PECI_BAUD_RATE)) - 1; /* Set maximum PECI baud rate (bit0 - bit4) */ if (baud > 0x1F) baud = 0x1F; @@ -247,7 +239,7 @@ static void peci_init(void) /* Enable clock for PECI peripheral */ clock_enable_peripheral(CGC_OFFSET_PECI, CGC_PECI_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); + CGC_MODE_RUN | CGC_MODE_SLEEP); /* Set PECI freq */ peci_freq_changed(); @@ -269,9 +261,10 @@ static void peci_init(void) DECLARE_HOOK(HOOK_INIT, peci_init, HOOK_PRIO_DEFAULT); /* If received a PECI DONE interrupt, post the event to PECI task */ -void peci_done_interrupt(void){ +static void peci_done_interrupt(void) +{ if (peci_pending_task_id != NULL_PENDING_TASK_ID) - task_set_event(peci_pending_task_id, TASK_EVENT_PECI_DONE, 0); + task_set_event(peci_pending_task_id, TASK_EVENT_PECI_DONE); peci_sts = NPCX_PECI_CTL_STS & 0x18; /* no matter what, clear status bit again */ SET_BIT(NPCX_PECI_CTL_STS, NPCX_PECI_CTL_STS_DONE); @@ -283,7 +276,7 @@ DECLARE_IRQ(NPCX_IRQ_PECI, peci_done_interrupt, 4); /*****************************************************************************/ /* Console commands */ -static int command_peci_temp(int argc, char **argv) +static int command_peci_temp(int argc, const char **argv) { int t = peci_get_cpu_temp(); if (t == -1) { @@ -293,6 +286,5 @@ static int command_peci_temp(int argc, char **argv) ccprintf("CPU temp = %d K = %d\n", t, K_TO_C(t)); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp, - NULL, - "Print CPU temperature"); +DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp, NULL, + "Print CPU temperature"); diff --git a/chip/npcx/ps2.c b/chip/npcx/ps2.c index c470bbe68d..5fc91ef241 100644 --- a/chip/npcx/ps2.c +++ b/chip/npcx/ps2.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,33 +8,33 @@ #include "atomic.h" #include "clock.h" #include "console.h" -#include "hooks.h" #include "gpio.h" +#include "hooks.h" #include "ps2_chip.h" -#include "task.h" #include "registers.h" +#include "task.h" #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_PS2, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_PS2, format, ## args) +#define CPRINTS(format, args...) cprints(CC_PS2, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_PS2, format, ##args) #if !(DEBUG_PS2) #define DEBUG_CPRINTS(...) #define DEBUG_CPRINTF(...) #else -#define DEBUG_CPRINTS(format, args...) cprints(CC_PS2, format, ## args) -#define DEBUG_CPRINTF(format, args...) cprintf(CC_PS2, format, ## args) +#define DEBUG_CPRINTS(format, args...) cprints(CC_PS2, format, ##args) +#define DEBUG_CPRINTF(format, args...) cprintf(CC_PS2, format, ##args) #endif /* * Set WDAT3-0 and clear CLK3-0 in the PSOSIG register to * reset the shift mechanism. */ -#define PS2_SHIFT_MECH_RESET 0x47 +#define PS2_SHIFT_MECH_RESET 0x47 -#define PS2_TRANSACTION_TIMEOUT (20 * MSEC) -#define PS2_BUSY_RETRY 10 +#define PS2_TRANSACTION_TIMEOUT (20 * MSEC) +#define PS2_BUSY_RETRY 10 enum ps2_input_debounce_cycle { PS2_IDB_1_CYCLE, @@ -60,7 +60,7 @@ struct ps2_data { void (*rx_handler_cb)(uint8_t data); }; static struct ps2_data ps2_ch_data[NPCX_PS2_CH_COUNT] = { - [0 ... (NPCX_PS2_CH_COUNT - 1)] = { PS2_RX_MODE, NULL } + [0 ...(NPCX_PS2_CH_COUNT - 1)] = { PS2_RX_MODE, NULL } }; /* @@ -76,7 +76,7 @@ static void ps2_init(void) { /* Disable the power down bit of PS/2 */ clock_enable_peripheral(CGC_OFFSET_PS2, CGC_PS2_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); + CGC_MODE_RUN | CGC_MODE_SLEEP); /* Disable shift mechanism and configure PS/2 to received mode. */ NPCX_PS2_PSCON = 0x0; @@ -90,10 +90,9 @@ static void ps2_init(void) * [4] - : WUE = 1: Wake-Up Enable * [7] - : CLK_SEL = 1: Select Free-Run clock as the basic clock */ - NPCX_PS2_PSIEN = BIT(NPCX_PS2_PSIEN_SOTIE) | - BIT(NPCX_PS2_PSIEN_EOTIE) | - BIT(NPCX_PS2_PSIEN_PS2_WUE) | - BIT(NPCX_PS2_PSIEN_PS2_CLK_SEL); + NPCX_PS2_PSIEN = BIT(NPCX_PS2_PSIEN_SOTIE) | BIT(NPCX_PS2_PSIEN_EOTIE) | + BIT(NPCX_PS2_PSIEN_PS2_WUE) | + BIT(NPCX_PS2_PSIEN_PS2_CLK_SEL); /* Enable weak internal pull-up */ SET_BIT(NPCX_PS2_PSCON, NPCX_PS2_PSCON_WPUED); @@ -106,8 +105,7 @@ static void ps2_init(void) } DECLARE_HOOK(HOOK_INIT, ps2_init, HOOK_PRIO_DEFAULT); -void ps2_enable_channel(int channel, int enable, - void (*callback)(uint8_t data)) +void ps2_enable_channel(int channel, int enable, void (*callback)(uint8_t data)) { if (channel >= NPCX_PS2_CH_COUNT) { CPRINTS("Err:PS/2 CH exceed %d", NPCX_PS2_CH_COUNT); @@ -125,7 +123,7 @@ void ps2_enable_channel(int channel, int enable, /* Enable the relevant channel clock */ SET_BIT(NPCX_PS2_PSOSIG, NPCX_PS2_PSOSIG_CLK(channel)); } else { - channel_enabled_mask &= ~BIT(NPCX_PS2_PSOSIG_CLK(channel)); + channel_enabled_mask &= ~BIT(NPCX_PS2_PSOSIG_CLK(channel)); /* Disable the relevant channel clock */ CLEAR_BIT(NPCX_PS2_PSOSIG, NPCX_PS2_PSOSIG_CLK(channel)); ps2_ch_data[channel].rx_handler_cb = NULL; @@ -144,7 +142,9 @@ static int ps2_is_busy(void) * (due to Shift Mechanism is reset) */ return (IS_BIT_SET(NPCX_PS2_PSTAT, NPCX_PS2_PSTAT_SOT) | - IS_BIT_SET(NPCX_PS2_PSTAT, NPCX_PS2_PSTAT_EOT)) ? 1 : 0; + IS_BIT_SET(NPCX_PS2_PSTAT, NPCX_PS2_PSTAT_EOT)) ? + 1 : + 0; } int ps2_transmit_byte(int channel, uint8_t data) @@ -194,7 +194,7 @@ int ps2_transmit_byte(int channel, uint8_t data) /* Wait for interrupt */ event = task_wait_event_mask(TASK_EVENT_PS2_DONE, - PS2_TRANSACTION_TIMEOUT); + PS2_TRANSACTION_TIMEOUT); task_waiting = TASK_ID_INVALID; if (event == TASK_EVENT_TIMER) { @@ -216,7 +216,6 @@ int ps2_transmit_byte(int channel, uint8_t data) DEBUG_CPRINTF("Evt:0x%08x\n", event); return (event == TASK_EVENT_PS2_DONE) ? EC_SUCCESS : EC_ERROR_TIMEOUT; - } static void ps2_stop_inactive_ch_clk(uint8_t active_ch) @@ -224,20 +223,17 @@ static void ps2_stop_inactive_ch_clk(uint8_t active_ch) uint8_t mask; mask = ~NPCX_PS2_PSOSIG_CLK_MASK_ALL | - BIT(NPCX_PS2_PSOSIG_CLK(active_ch)); + BIT(NPCX_PS2_PSOSIG_CLK(active_ch)); NPCX_PS2_PSOSIG &= mask; - } static int ps2_is_rx_error(uint8_t ch) { - uint8_t status; + uint8_t status; status = NPCX_PS2_PSTAT & - (BIT(NPCX_PS2_PSTAT_PERR) | - BIT(NPCX_PS2_PSTAT_RFERR)); + (BIT(NPCX_PS2_PSTAT_PERR) | BIT(NPCX_PS2_PSTAT_RFERR)); if (status) { - if (status & BIT(NPCX_PS2_PSTAT_PERR)) CPRINTF("PS2 CH %d RX parity error\n", ch); if (status & BIT(NPCX_PS2_PSTAT_RFERR)) @@ -247,7 +243,7 @@ static int ps2_is_rx_error(uint8_t ch) return 0; } -void ps2_int_handler(void) +static void ps2_int_handler(void) { uint8_t active_ch; @@ -270,7 +266,7 @@ void ps2_int_handler(void) /* PS/2 Start of Transaction */ if (IS_BIT_SET(NPCX_PS2_PSTAT, NPCX_PS2_PSTAT_SOT) && - IS_BIT_SET(NPCX_PS2_PSIEN, NPCX_PS2_PSIEN_SOTIE)) { + IS_BIT_SET(NPCX_PS2_PSIEN, NPCX_PS2_PSIEN_SOTIE)) { DEBUG_CPRINTF("SOT-"); /* * Once set, SOT is not cleared until the shift mechanism @@ -278,7 +274,7 @@ void ps2_int_handler(void) * first occurrence of an SOT interrupt. */ CLEAR_BIT(NPCX_PS2_PSIEN, NPCX_PS2_PSIEN_SOTIE); - /* PS/2 End of Transaction */ + /* PS/2 End of Transaction */ } else if (IS_BIT_SET(NPCX_PS2_PSTAT, NPCX_PS2_PSTAT_EOT)) { DEBUG_CPRINTF("EOT-"); CLEAR_BIT(NPCX_PS2_PSIEN, NPCX_PS2_PSIEN_EOTIE); @@ -293,12 +289,12 @@ void ps2_int_handler(void) /* Change the PS/2 module to receive mode */ CLEAR_BIT(NPCX_PS2_PSCON, NPCX_PS2_PSCON_XMT); ps2_ch_data[active_ch].opr_mode = PS2_RX_MODE; - task_set_event(task_waiting, TASK_EVENT_PS2_DONE, 0); + task_set_event(task_waiting, TASK_EVENT_PS2_DONE); } else { if (!ps2_is_rx_error(active_ch)) { uint8_t data_read = NPCX_PS2_PSDAT; struct ps2_data *ps2_ptr = - &ps2_ch_data[active_ch]; + &ps2_ch_data[active_ch]; DEBUG_CPRINTF("Recv:0x%02x", data_read); if (ps2_ptr->rx_handler_cb) @@ -316,12 +312,11 @@ void ps2_int_handler(void) SET_BIT(NPCX_PS2_PSIEN, NPCX_PS2_PSIEN_EOTIE); } DEBUG_CPRINTF("\n"); - } DECLARE_IRQ(NPCX_IRQ_PS2, ps2_int_handler, 5); #ifdef CONFIG_CMD_PS2 -static int command_ps2ench(int argc, char **argv) +static int command_ps2ench(int argc, const char **argv) { uint8_t ch; uint8_t enable; @@ -341,11 +336,10 @@ static int command_ps2ench(int argc, char **argv) return 0; } -DECLARE_CONSOLE_COMMAND(ps2ench, command_ps2ench, - "ps2_ench channel 1|0", +DECLARE_CONSOLE_COMMAND(ps2ench, command_ps2ench, "ps2_ench channel 1|0", "Enable/Disable PS/2 channel"); -static int command_ps2write(int argc, char **argv) +static int command_ps2write(int argc, const char **argv) { uint8_t ch, data; char *e; @@ -360,7 +354,6 @@ static int command_ps2write(int argc, char **argv) ps2_transmit_byte(ch, data); return 0; } -DECLARE_CONSOLE_COMMAND(ps2write, command_ps2write, - "ps2_write channel data", - "Write data byte to PS/2 channel "); +DECLARE_CONSOLE_COMMAND(ps2write, command_ps2write, "ps2_write channel data", + "Write data byte to PS/2 channel "); #endif diff --git a/chip/npcx/ps2_chip.h b/chip/npcx/ps2_chip.h index d88e6791ad..871b1ab6e5 100644 --- a/chip/npcx/ps2_chip.h +++ b/chip/npcx/ps2_chip.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -21,4 +21,4 @@ void ps2_enable_channel(int channel, int enable, void (*callback)(uint8_t data)); int ps2_transmit_byte(int channel, uint8_t data); -#endif /* __CROS_EC_PS2_CHIP_H */ +#endif /* __CROS_EC_PS2_CHIP_H */ diff --git a/chip/npcx/pwm.c b/chip/npcx/pwm.c index 541c29de99..53a278a0ba 100644 --- a/chip/npcx/pwm.c +++ b/chip/npcx/pwm.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,7 +8,7 @@ * On this chip, the PWM logic is implemented by the hardware FAN modules. */ -#include "assert.h" +#include "builtin/assert.h" #include "clock.h" #include "clock_chip.h" #include "console.h" @@ -23,7 +23,7 @@ #if !(DEBUG_PWM) #define CPRINTS(...) #else -#define CPRINTS(format, args...) cprints(CC_PWM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_PWM, format, ##args) #endif /* pwm resolution for each channel */ @@ -31,20 +31,20 @@ static uint32_t pwm_res[PWM_CH_COUNT]; /* PWM clock source */ enum npcx_pwm_source_clock { - NPCX_PWM_CLOCK_APB2_LFCLK = 0, - NPCX_PWM_CLOCK_FX = 1, - NPCX_PWM_CLOCK_FR = 2, - NPCX_PWM_CLOCK_RESERVED = 3, - NPCX_PWM_CLOCK_UNDEF = 0xFF + NPCX_PWM_CLOCK_APB2_LFCLK = 0, + NPCX_PWM_CLOCK_FX = 1, + NPCX_PWM_CLOCK_FR = 2, + NPCX_PWM_CLOCK_RESERVED = 3, + NPCX_PWM_CLOCK_UNDEF = 0xFF }; /* PWM heartbeat mode */ enum npcx_pwm_heartbeat_mode { - NPCX_PWM_HBM_NORMAL = 0, - NPCX_PWM_HBM_25 = 1, - NPCX_PWM_HBM_50 = 2, - NPCX_PWM_HBM_100 = 3, - NPCX_PWM_HBM_UNDEF = 0xFF + NPCX_PWM_HBM_NORMAL = 0, + NPCX_PWM_HBM_25 = 1, + NPCX_PWM_HBM_50 = 2, + NPCX_PWM_HBM_100 = 3, + NPCX_PWM_HBM_UNDEF = 0xFF }; /** @@ -127,7 +127,7 @@ int pwm_get_enabled(enum pwm_channel ch) */ void pwm_set_duty(enum pwm_channel ch, int percent) { - /* Convert 16 bit duty to percent on [0, 100] */ + /* Convert percent on [0, 100] to 16 bit duty */ pwm_set_raw_duty(ch, (percent * EC_PWM_MAX_DUTY) / 100); } @@ -146,7 +146,7 @@ void pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty) /* Assume the fan control is active high and invert it ourselves */ UPDATE_BIT(NPCX_PWMCTL(mdl), NPCX_PWMCTL_INVP, - (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW)); + (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW)); CPRINTS("initial freq=0x%x", pwm_channels[ch].freq); CPRINTS("duty_cycle_cnt=%d", duty); @@ -189,7 +189,7 @@ uint16_t pwm_get_raw_duty(enum pwm_channel ch) * so scale to 0 - 0xffff */ return DIV_ROUND_NEAREST(NPCX_DCR(mdl) * EC_PWM_MAX_DUTY, - pwm_res[ch]); + pwm_res[ch]); } /** @@ -206,22 +206,22 @@ void pwm_config(enum pwm_channel ch) /* Set PWM heartbeat mode is no heartbeat */ SET_FIELD(NPCX_PWMCTL(mdl), NPCX_PWMCTL_HB_DC_CTL_FIELD, - NPCX_PWM_HBM_NORMAL); + NPCX_PWM_HBM_NORMAL); /* Select default CLK or LFCLK clock input to PWM module */ SET_FIELD(NPCX_PWMCTLEX(mdl), NPCX_PWMCTLEX_FCK_SEL_FIELD, - NPCX_PWM_CLOCK_APB2_LFCLK); + NPCX_PWM_CLOCK_APB2_LFCLK); /* Set PWM polarity normal first */ CLEAR_BIT(NPCX_PWMCTL(mdl), NPCX_PWMCTL_INVP); /* Select PWM clock source */ UPDATE_BIT(NPCX_PWMCTL(mdl), NPCX_PWMCTL_CKSEL, - (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP)); + (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP)); /* Select PWM IO type */ UPDATE_BIT(NPCX_PWMCTLEX(mdl), NPCX_PWMCTLEX_OD_OUT, - (pwm_channels[ch].flags & PWM_CONFIG_OPEN_DRAIN)); + (pwm_channels[ch].flags & PWM_CONFIG_OPEN_DRAIN)); /* Set PWM operation frequency */ pwm_set_freq(ch, pwm_channels[ch].freq); diff --git a/chip/npcx/pwm_chip.h b/chip/npcx/pwm_chip.h index 7acfef81e5..714ecfb4a3 100644 --- a/chip/npcx/pwm_chip.h +++ b/chip/npcx/pwm_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/npcx/registers-npcx5.h b/chip/npcx/registers-npcx5.h index da0f215d0a..b7302bdd13 100644 --- a/chip/npcx/registers-npcx5.h +++ b/chip/npcx/registers-npcx5.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,79 +19,87 @@ #endif /* NPCX-IRQ numbers */ -#define NPCX_IRQ0_NOUSED NPCX_IRQ_0 -#define NPCX_IRQ1_NOUSED NPCX_IRQ_1 -#define NPCX_IRQ_KBSCAN NPCX_IRQ_2 -#define NPCX_IRQ_PM_CHAN_OBE NPCX_IRQ_3 -#define NPCX_IRQ_PECI NPCX_IRQ_4 -#define NPCX_IRQ5_NOUSED NPCX_IRQ_5 -#define NPCX_IRQ_PORT80 NPCX_IRQ_6 -#define NPCX_IRQ_MTC_WKINTAD_0 NPCX_IRQ_7 -#define NPCX_IRQ_MTC NPCX_IRQ_MTC_WKINTAD_0 -#define NPCX_IRQ8_NOUSED NPCX_IRQ_8 -#define NPCX_IRQ_MFT_1 NPCX_IRQ_9 -#define NPCX_IRQ_ADC NPCX_IRQ_10 -#define NPCX_IRQ_WKINTEFGH_0 NPCX_IRQ_11 -#define NPCX_IRQ_GDMA NPCX_IRQ_12 -#define NPCX_IRQ_SMB1 NPCX_IRQ_13 -#define NPCX_IRQ_SMB2 NPCX_IRQ_14 -#define NPCX_IRQ_WKINTC_0 NPCX_IRQ_15 -#define NPCX_IRQ16_NOUSED NPCX_IRQ_16 -#define NPCX_IRQ_ITIM16_3 NPCX_IRQ_17 -#define NPCX_IRQ_SHI NPCX_IRQ_18 -#define NPCX_IRQ_ESPI NPCX_IRQ_18 -#define NPCX_IRQ19_NOUSED NPCX_IRQ_19 -#define NPCX_IRQ20_NOUSED NPCX_IRQ_20 -#define NPCX_IRQ_PS2 NPCX_IRQ_21 -#define NPCX_IRQ22_NOUSED NPCX_IRQ_22 -#define NPCX_IRQ_MFT_2 NPCX_IRQ_23 -#define NPCX_IRQ_SHM NPCX_IRQ_24 -#define NPCX_IRQ_KBC_IBF NPCX_IRQ_25 -#define NPCX_IRQ_PM_CHAN_IBF NPCX_IRQ_26 -#define NPCX_IRQ_ITIM16_2 NPCX_IRQ_27 -#define NPCX_IRQ_ITIM16_1 NPCX_IRQ_28 -#define NPCX_IRQ29_NOUSED NPCX_IRQ_29 -#define NPCX_IRQ30_NOUSED NPCX_IRQ_30 -#define NPCX_IRQ_TWD_WKINTB_0 NPCX_IRQ_31 -#define NPCX_IRQ32_NOUSED NPCX_IRQ_32 -#define NPCX_IRQ_UART NPCX_IRQ_33 -#define NPCX_IRQ34_NOUSED NPCX_IRQ_34 -#define NPCX_IRQ35_NOUSED NPCX_IRQ_35 -#define NPCX_IRQ_SMB3 NPCX_IRQ_36 -#define NPCX_IRQ_SMB4 NPCX_IRQ_37 -#define NPCX_IRQ38_NOUSED NPCX_IRQ_38 -#define NPCX_IRQ39_NOUSED NPCX_IRQ_39 -#define NPCX_IRQ40_NOUSED NPCX_IRQ_40 -#define NPCX_IRQ_MFT_3 NPCX_IRQ_41 -#define NPCX_IRQ42_NOUSED NPCX_IRQ_42 -#define NPCX_IRQ_ITIM16_4 NPCX_IRQ_43 -#define NPCX_IRQ_ITIM16_5 NPCX_IRQ_44 -#define NPCX_IRQ_ITIM16_6 NPCX_IRQ_45 -#define NPCX_IRQ_ITIM32 NPCX_IRQ_46 -#define NPCX_IRQ_WKINTA_1 NPCX_IRQ_47 -#define NPCX_IRQ_WKINTB_1 NPCX_IRQ_48 -#define NPCX_IRQ_KSI_WKINTC_1 NPCX_IRQ_49 -#define NPCX_IRQ_WKINTD_1 NPCX_IRQ_50 -#define NPCX_IRQ_WKINTE_1 NPCX_IRQ_51 -#define NPCX_IRQ_WKINTF_1 NPCX_IRQ_52 -#define NPCX_IRQ_WKINTG_1 NPCX_IRQ_53 -#define NPCX_IRQ_WKINTH_1 NPCX_IRQ_54 -#define NPCX_IRQ55_NOUSED NPCX_IRQ_55 -#define NPCX_IRQ_KBC_OBE NPCX_IRQ_56 -#define NPCX_IRQ_SPI NPCX_IRQ_57 -#define NPCX_IRQ58_NOUSED NPCX_IRQ_58 -#define NPCX_IRQ_WKINTFG_2 NPCX_IRQ_59 -#define NPCX_IRQ_WKINTA_2 NPCX_IRQ_60 -#define NPCX_IRQ_WKINTB_2 NPCX_IRQ_61 -#define NPCX_IRQ_WKINTC_2 NPCX_IRQ_62 -#define NPCX_IRQ_WKINTD_2 NPCX_IRQ_63 +#define NPCX_IRQ0_NOUSED NPCX_IRQ_0 +#define NPCX_IRQ1_NOUSED NPCX_IRQ_1 +#define NPCX_IRQ_KBSCAN NPCX_IRQ_2 +#define NPCX_IRQ_PM_CHAN_OBE NPCX_IRQ_3 +#define NPCX_IRQ_PECI NPCX_IRQ_4 +#define NPCX_IRQ5_NOUSED NPCX_IRQ_5 +#define NPCX_IRQ_PORT80 NPCX_IRQ_6 +#define NPCX_IRQ_MTC_WKINTAD_0 NPCX_IRQ_7 +#define NPCX_IRQ_MTC NPCX_IRQ_MTC_WKINTAD_0 +#define NPCX_IRQ8_NOUSED NPCX_IRQ_8 +#define NPCX_IRQ_MFT_1 NPCX_IRQ_9 +#define NPCX_IRQ_ADC NPCX_IRQ_10 +#define NPCX_IRQ_WKINTEFGH_0 NPCX_IRQ_11 +#define NPCX_IRQ_GDMA NPCX_IRQ_12 +#define NPCX_IRQ_SMB1 NPCX_IRQ_13 +#define NPCX_IRQ_SMB2 NPCX_IRQ_14 +#define NPCX_IRQ_WKINTC_0 NPCX_IRQ_15 +#define NPCX_IRQ16_NOUSED NPCX_IRQ_16 +#define NPCX_IRQ_ITIM16_3 NPCX_IRQ_17 +#define NPCX_IRQ_SHI NPCX_IRQ_18 +#define NPCX_IRQ_ESPI NPCX_IRQ_18 +#define NPCX_IRQ19_NOUSED NPCX_IRQ_19 +#define NPCX_IRQ20_NOUSED NPCX_IRQ_20 +#define NPCX_IRQ_PS2 NPCX_IRQ_21 +#define NPCX_IRQ22_NOUSED NPCX_IRQ_22 +#define NPCX_IRQ_MFT_2 NPCX_IRQ_23 +#define NPCX_IRQ_SHM NPCX_IRQ_24 +#define NPCX_IRQ_KBC_IBF NPCX_IRQ_25 +#define NPCX_IRQ_PM_CHAN_IBF NPCX_IRQ_26 +#define NPCX_IRQ_ITIM16_2 NPCX_IRQ_27 +#define NPCX_IRQ_ITIM16_1 NPCX_IRQ_28 +#define NPCX_IRQ29_NOUSED NPCX_IRQ_29 +#define NPCX_IRQ30_NOUSED NPCX_IRQ_30 +#define NPCX_IRQ_TWD_WKINTB_0 NPCX_IRQ_31 +#define NPCX_IRQ32_NOUSED NPCX_IRQ_32 +#define NPCX_IRQ_UART NPCX_IRQ_33 +#define NPCX_IRQ34_NOUSED NPCX_IRQ_34 +#define NPCX_IRQ35_NOUSED NPCX_IRQ_35 +#define NPCX_IRQ_SMB3 NPCX_IRQ_36 +#define NPCX_IRQ_SMB4 NPCX_IRQ_37 +#define NPCX_IRQ38_NOUSED NPCX_IRQ_38 +#define NPCX_IRQ39_NOUSED NPCX_IRQ_39 +#define NPCX_IRQ40_NOUSED NPCX_IRQ_40 +#define NPCX_IRQ_MFT_3 NPCX_IRQ_41 +#define NPCX_IRQ42_NOUSED NPCX_IRQ_42 +#define NPCX_IRQ_ITIM16_4 NPCX_IRQ_43 +#define NPCX_IRQ_ITIM16_5 NPCX_IRQ_44 +#define NPCX_IRQ_ITIM16_6 NPCX_IRQ_45 +#define NPCX_IRQ_ITIM32 NPCX_IRQ_46 +#define NPCX_IRQ_WKINTA_1 NPCX_IRQ_47 +#define NPCX_IRQ_WKINTB_1 NPCX_IRQ_48 +#define NPCX_IRQ_KSI_WKINTC_1 NPCX_IRQ_49 +#define NPCX_IRQ_WKINTD_1 NPCX_IRQ_50 +#define NPCX_IRQ_WKINTE_1 NPCX_IRQ_51 +#define NPCX_IRQ_WKINTF_1 NPCX_IRQ_52 +#define NPCX_IRQ_WKINTG_1 NPCX_IRQ_53 +#define NPCX_IRQ_WKINTH_1 NPCX_IRQ_54 +#define NPCX_IRQ55_NOUSED NPCX_IRQ_55 +#define NPCX_IRQ_KBC_OBE NPCX_IRQ_56 +#define NPCX_IRQ_SPI NPCX_IRQ_57 +#define NPCX_IRQ58_NOUSED NPCX_IRQ_58 +#define NPCX_IRQ_WKINTFG_2 NPCX_IRQ_59 +#define NPCX_IRQ_WKINTA_2 NPCX_IRQ_60 +#define NPCX_IRQ_WKINTB_2 NPCX_IRQ_61 +#define NPCX_IRQ_WKINTC_2 NPCX_IRQ_62 +#define NPCX_IRQ_WKINTD_2 NPCX_IRQ_63 /* Modules Map */ -#define NPCX_ITIM32_BASE_ADDR 0x400BC000 -#define NPCX_CR_UART_BASE_ADDR(mdl) (0x400C4000 + ((mdl) * 0x2000L)) -#define NPCX_SMB_BASE_ADDR(mdl) (((mdl) < 2) ? \ - (0x40009000 + ((mdl) * 0x2000L)) : \ - (0x400C0000 + (((mdl) - 2) * 0x2000L))) + +/* Miscellaneous Device Control (MDC) registers */ +#define NPCX_FWCTRL REG8(NPCX_MDC_BASE_ADDR + 0x007) + +/* MDC register fields */ +#define NPCX_FWCTRL_RO_REGION 0 +#define NPCX_FWCTRL_FW_SLOT 1 + +#define NPCX_ITIM32_BASE_ADDR 0x400BC000 +#define NPCX_CR_UART_BASE_ADDR(mdl) (0x400C4000 + ((mdl)*0x2000L)) +#define NPCX_SMB_BASE_ADDR(mdl) \ + (((mdl) < 2) ? (0x40009000 + ((mdl)*0x2000L)) : \ + (0x400C0000 + (((mdl)-2) * 0x2000L))) enum { NPCX_UART_PORT0 = 0, /* UART port 0 */ @@ -121,35 +129,39 @@ enum { ALT_GROUP_COUNT }; -#define NPCX_DEVALT(n) REG8(NPCX_SCFG_BASE_ADDR + 0x010 + (n)) +#define NPCX_DEVALT(n) REG8(NPCX_SCFG_BASE_ADDR + 0x010 + (n)) + +#define NPCX_LV_GPIO_CTL(n) REG8(NPCX_SCFG_BASE_ADDR + 0x02A + (n)) -#define NPCX_LV_GPIO_CTL(n) REG8(NPCX_SCFG_BASE_ADDR + 0x02A + (n)) +/* pin-mux for JTAG */ +#define NPCX_DEVALT5_NJEN1_EN 1 +#define NPCX_DEVALT5_NJEN0_EN 2 /* pin-mux for I2C */ -#define NPCX_DEVALT2_I2C0_0_SL 0 -#define NPCX_DEVALT2_I2C0_1_SL 1 -#define NPCX_DEVALT2_I2C1_0_SL 2 -#define NPCX_DEVALT2_I2C2_0_SL 4 -#define NPCX_DEVALT2_I2C3_0_SL 6 +#define NPCX_DEVALT2_I2C0_0_SL 0 +#define NPCX_DEVALT2_I2C0_1_SL 1 +#define NPCX_DEVALT2_I2C1_0_SL 2 +#define NPCX_DEVALT2_I2C2_0_SL 4 +#define NPCX_DEVALT2_I2C3_0_SL 6 /* pin-mux for UART */ -#define NPCX_DEVALTA_UART_SL1 7 -#define NPCX_DEVALTC_UART_SL2 0 +#define NPCX_DEVALTA_UART_SL1 7 +#define NPCX_DEVALTC_UART_SL2 0 /* pin-mux for Misc. */ /* External 32KHz crytal osc. input support */ -#define NPCX_DEVALTA_32KCLKIN_SL 3 +#define NPCX_DEVALTA_32KCLKIN_SL 3 /* SMBus register fields */ -#define NPCX_SMBSEL_SMB0SEL 0 +#define NPCX_SMBSEL_SMB0SEL 0 /* SMB enumeration: I2C port definitions. */ enum { - NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0 */ - NPCX_I2C_PORT0_1, /* I2C port 0, bus 1 */ - NPCX_I2C_PORT1, /* I2C port 1 */ - NPCX_I2C_PORT2, /* I2C port 2 */ - NPCX_I2C_PORT3, /* I2C port 3 */ + NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0 */ + NPCX_I2C_PORT0_1, /* I2C port 0, bus 1 */ + NPCX_I2C_PORT1, /* I2C port 1 */ + NPCX_I2C_PORT2, /* I2C port 2 */ + NPCX_I2C_PORT3, /* I2C port 3 */ NPCX_I2C_COUNT, }; @@ -183,32 +195,31 @@ enum NPCX_PMC_PWDWN_CTL_T { NPCX_PMC_PWDWN_CNT, }; -#define CGC_I2C_MASK (BIT(NPCX_PWDWN_CTL3_SMB0_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB1_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB2_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB3_PD)) +#define CGC_I2C_MASK \ + (BIT(NPCX_PWDWN_CTL3_SMB0_PD) | BIT(NPCX_PWDWN_CTL3_SMB1_PD) | \ + BIT(NPCX_PWDWN_CTL3_SMB2_PD) | BIT(NPCX_PWDWN_CTL3_SMB3_PD)) /* BBRAM register fields */ #define NPCX_BKUP_STS_ALL_MASK BIT(NPCX_BKUP_STS_IBBR) -#define NPCX_BBRAM_SIZE 64 /* Size of BBRAM */ +#define NPCX_BBRAM_SIZE 64 /* Size of BBRAM */ /* ITIM registers */ -#define NPCX_ITCNT8(n) REG8(NPCX_ITIM_BASE_ADDR(n) + 0x000) -#define NPCX_ITCNT16(n) REG16(NPCX_ITIM_BASE_ADDR(n) + 0x002) +#define NPCX_ITCNT8(n) REG8(NPCX_ITIM_BASE_ADDR(n) + 0x000) +#define NPCX_ITCNT16(n) REG16(NPCX_ITIM_BASE_ADDR(n) + 0x002) /* ITIM32 registers */ -#define NPCX_ITCNT32 REG32(NPCX_ITIM32_BASE_ADDR + 0x008) +#define NPCX_ITCNT32 REG32(NPCX_ITIM32_BASE_ADDR + 0x008) /* Timer counter register used for 1 micro-second system tick */ -#define NPCX_ITCNT_SYSTEM NPCX_ITCNT32 +#define NPCX_ITCNT_SYSTEM NPCX_ITCNT32 /* Timer counter register used for others */ -#define NPCX_ITCNT NPCX_ITCNT16 +#define NPCX_ITCNT NPCX_ITCNT16 /* ITIM module No. used for event */ -#define ITIM_EVENT_NO ITIM16_1 +#define ITIM_EVENT_NO ITIM16_1 /* ITIM module No. used for watchdog */ -#define ITIM_WDG_NO ITIM16_5 +#define ITIM_WDG_NO ITIM16_5 /* ITIM module No. used for 1 micro-second system tick */ -#define ITIM_SYSTEM_NO ITIM32 +#define ITIM_SYSTEM_NO ITIM32 /* ITIM enumeration */ enum ITIM_MODULE_T { @@ -223,11 +234,11 @@ enum ITIM_MODULE_T { }; /* Serial Host Interface (SHI) Registers */ -#define NPCX_OBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x020 + (n)) -#define NPCX_IBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x060 + (n)) +#define NPCX_OBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x020 + (n)) +#define NPCX_IBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x060 + (n)) /* Bit field manipulation for VWEVMS Value */ -#define VWEVMS_INTWK_EN VWEVMS_INT_EN +#define VWEVMS_INTWK_EN VWEVMS_INT_EN /* eSPI max supported frequency */ enum { @@ -241,35 +252,35 @@ enum { /* eSPI max frequency support per FMCLK */ #if (FMCLK <= 33000000) -#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_33 +#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_33 #elif (FMCLK <= 48000000) -#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_50 +#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_50 #else -#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_66 +#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_66 #endif /* MIWU registers */ -#define NPCX_WKEDG_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x00 + \ - ((n) * 2L) + ((n) < 5 ? 0 : 0x1E)) -#define NPCX_WKAEDG_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x01 + \ - ((n) * 2L) + ((n) < 5 ? 0 : 0x1E)) -#define NPCX_WKPND_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x0A + \ - ((n) * 4L) + ((n) < 5 ? 0 : 0x10)) -#define NPCX_WKPCL_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x0C + \ - ((n) * 4L) + ((n) < 5 ? 0 : 0x10)) -#define NPCX_WKEN_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x1E + \ - ((n) * 2L) + ((n) < 5 ? 0 : 0x12)) -#define NPCX_WKINEN_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x1F + \ - ((n) * 2L) + ((n) < 5 ? 0 : 0x12)) -#define NPCX_WKMOD_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x70 + (n)) - -#define NPCX_WKEDG(port, n) REG8(NPCX_WKEDG_ADDR(port, n)) -#define NPCX_WKAEDG(port, n) REG8(NPCX_WKAEDG_ADDR(port, n)) -#define NPCX_WKPND(port, n) REG8(NPCX_WKPND_ADDR(port, n)) -#define NPCX_WKPCL(port, n) REG8(NPCX_WKPCL_ADDR(port, n)) -#define NPCX_WKEN(port, n) REG8(NPCX_WKEN_ADDR(port, n)) -#define NPCX_WKINEN(port, n) REG8(NPCX_WKINEN_ADDR(port, n)) -#define NPCX_WKMOD(port, n) REG8(NPCX_WKMOD_ADDR(port, n)) +#define NPCX_WKEDG_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x00 + ((n)*2L) + ((n) < 5 ? 0 : 0x1E)) +#define NPCX_WKAEDG_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x01 + ((n)*2L) + ((n) < 5 ? 0 : 0x1E)) +#define NPCX_WKPND_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x0A + ((n)*4L) + ((n) < 5 ? 0 : 0x10)) +#define NPCX_WKPCL_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x0C + ((n)*4L) + ((n) < 5 ? 0 : 0x10)) +#define NPCX_WKEN_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x1E + ((n)*2L) + ((n) < 5 ? 0 : 0x12)) +#define NPCX_WKINEN_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x1F + ((n)*2L) + ((n) < 5 ? 0 : 0x12)) +#define NPCX_WKMOD_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x70 + (n)) + +#define NPCX_WKEDG(port, n) REG8(NPCX_WKEDG_ADDR(port, n)) +#define NPCX_WKAEDG(port, n) REG8(NPCX_WKAEDG_ADDR(port, n)) +#define NPCX_WKPND(port, n) REG8(NPCX_WKPND_ADDR(port, n)) +#define NPCX_WKPCL(port, n) REG8(NPCX_WKPCL_ADDR(port, n)) +#define NPCX_WKEN(port, n) REG8(NPCX_WKEN_ADDR(port, n)) +#define NPCX_WKINEN(port, n) REG8(NPCX_WKINEN_ADDR(port, n)) +#define NPCX_WKMOD(port, n) REG8(NPCX_WKMOD_ADDR(port, n)) /* UART registers and functions */ #if NPCX_UART_MODULE2 @@ -277,22 +288,22 @@ enum { * To be used as 2nd parameter to NPCX_WK*() macro, table (1st parameter) is * always 1 == MIWU_TABLE_1. */ -#define NPCX_UART_WK_GROUP 6 -#define NPCX_UART_WK_BIT 4 -#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTG_1 -#define NPCX_UART_DEVALT NPCX_DEVALT(0x0C) -#define NPCX_UART_DEVALT_SL NPCX_DEVALTC_UART_SL2 -#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0A) -#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTA_UART_SL1 +#define NPCX_UART_WK_GROUP 6 +#define NPCX_UART_WK_BIT 4 +#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTG_1 +#define NPCX_UART_DEVALT NPCX_DEVALT(0x0C) +#define NPCX_UART_DEVALT_SL NPCX_DEVALTC_UART_SL2 +#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0A) +#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTA_UART_SL1 #else /* !NPCX_UART_MODULE2 */ -#define NPCX_UART_WK_GROUP 1 -#define NPCX_UART_WK_BIT 0 -#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTB_1 -#define NPCX_UART_DEVALT NPCX_DEVALT(0x0A) -#define NPCX_UART_DEVALT_SL NPCX_DEVALTA_UART_SL1 -#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0C) -#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTC_UART_SL2 +#define NPCX_UART_WK_GROUP 1 +#define NPCX_UART_WK_BIT 0 +#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTB_1 +#define NPCX_UART_DEVALT NPCX_DEVALT(0x0A) +#define NPCX_UART_DEVALT_SL NPCX_DEVALTA_UART_SL1 +#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0C) +#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTC_UART_SL2 #endif /* NPCX_UART_MODULE2 */ /* This routine checks pending bit of GPIO wake-up functionality */ @@ -316,8 +327,7 @@ static inline void uart_clear_pending_wakeup(void) /* This routine enables wake-up functionality from GPIO on UART rx pin */ static inline void uart_enable_wakeup(int enable) { - UPDATE_BIT(NPCX_WKEN(1, NPCX_UART_WK_GROUP), NPCX_UART_WK_BIT, - enable); + UPDATE_BIT(NPCX_WKEN(1, NPCX_UART_WK_GROUP), NPCX_UART_WK_BIT, enable); } /* This routine checks functionality is UART rx or not */ @@ -327,50 +337,50 @@ static inline int npcx_is_uart(void) } /* ADC Registers */ -#define NPCX_ADCSTS REG16(NPCX_ADC_BASE_ADDR + 0x000) -#define NPCX_ADCCNF REG16(NPCX_ADC_BASE_ADDR + 0x002) -#define NPCX_ATCTL REG16(NPCX_ADC_BASE_ADDR + 0x004) -#define NPCX_ASCADD REG16(NPCX_ADC_BASE_ADDR + 0x006) -#define NPCX_ADCCS REG16(NPCX_ADC_BASE_ADDR + 0x008) +#define NPCX_ADCSTS REG16(NPCX_ADC_BASE_ADDR + 0x000) +#define NPCX_ADCCNF REG16(NPCX_ADC_BASE_ADDR + 0x002) +#define NPCX_ATCTL REG16(NPCX_ADC_BASE_ADDR + 0x004) +#define NPCX_ASCADD REG16(NPCX_ADC_BASE_ADDR + 0x006) +#define NPCX_ADCCS REG16(NPCX_ADC_BASE_ADDR + 0x008) /* NOTE: These are 1-based for the threshold detectors. */ -#define NPCX_THRCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x012 + (2L*(n))) -#define NPCX_THRCTS REG16(NPCX_ADC_BASE_ADDR + 0x01A) -#define NPCX_THR_DCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x038 + (2L*(n))) +#define NPCX_THRCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x012 + (2L * (n))) +#define NPCX_THRCTS REG16(NPCX_ADC_BASE_ADDR + 0x01A) +#define NPCX_THR_DCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x038 + (2L * (n))) /* NOTE: This is 0-based for the ADC channels. */ -#define NPCX_CHNDAT(n) REG16(NPCX_ADC_BASE_ADDR + 0x040 + (2L*(n))) -#define NPCX_ADCCNF2 REG16(NPCX_ADC_BASE_ADDR + 0x020) -#define NPCX_GENDLY REG16(NPCX_ADC_BASE_ADDR + 0x022) -#define NPCX_MEAST REG16(NPCX_ADC_BASE_ADDR + 0x026) +#define NPCX_CHNDAT(n) REG16(NPCX_ADC_BASE_ADDR + 0x040 + (2L * (n))) +#define NPCX_ADCCNF2 REG16(NPCX_ADC_BASE_ADDR + 0x020) +#define NPCX_GENDLY REG16(NPCX_ADC_BASE_ADDR + 0x022) +#define NPCX_MEAST REG16(NPCX_ADC_BASE_ADDR + 0x026) /* ADC register fields */ -#define NPCX_ATCTL_SCLKDIV_FIELD FIELD(0, 6) -#define NPCX_ATCTL_DLY_FIELD FIELD(8, 3) -#define NPCX_ASCADD_SADDR_FIELD FIELD(0, 5) -#define NPCX_ADCSTS_EOCEV 0 -#define NPCX_ADCCNF_ADCMD_FIELD FIELD(1, 2) -#define NPCX_ADCCNF_ADCRPTC 3 -#define NPCX_ADCCNF_INTECEN 6 -#define NPCX_ADCCNF_START 4 -#define NPCX_ADCCNF_ADCEN 0 -#define NPCX_ADCCNF_STOP 11 -#define NPCX_CHNDAT_CHDAT_FIELD FIELD(0, 10) -#define NPCX_CHNDAT_NEW 15 -#define NPCX_THRCTL_THEN 15 -#define NPCX_THRCTL_L_H 14 -#define NPCX_THRCTL_CHNSEL FIELD(10, 4) -#define NPCX_THRCTL_THRVAL FIELD(0, 10) -#define NPCX_THRCTS_ADC_WKEN 15 -#define NPCX_THRCTS_THR3_IEN 10 -#define NPCX_THRCTS_THR2_IEN 9 -#define NPCX_THRCTS_THR1_IEN 8 -#define NPCX_THRCTS_ADC_EVENT 7 -#define NPCX_THRCTS_THR3_STS 2 -#define NPCX_THRCTS_THR2_STS 1 -#define NPCX_THRCTS_THR1_STS 0 -#define NPCX_THR_DCTL_THRD_EN 15 -#define NPCX_THR_DCTL_THR_DVAL FIELD(0, 10) - -#define NPCX_ADC_THRESH1 1 -#define NPCX_ADC_THRESH2 2 -#define NPCX_ADC_THRESH3 3 -#define NPCX_ADC_THRESH_CNT 3 +#define NPCX_ATCTL_SCLKDIV_FIELD FIELD(0, 6) +#define NPCX_ATCTL_DLY_FIELD FIELD(8, 3) +#define NPCX_ASCADD_SADDR_FIELD FIELD(0, 5) +#define NPCX_ADCSTS_EOCEV 0 +#define NPCX_ADCCNF_ADCMD_FIELD FIELD(1, 2) +#define NPCX_ADCCNF_ADCRPTC 3 +#define NPCX_ADCCNF_INTECEN 6 +#define NPCX_ADCCNF_START 4 +#define NPCX_ADCCNF_ADCEN 0 +#define NPCX_ADCCNF_STOP 11 +#define NPCX_CHNDAT_CHDAT_FIELD FIELD(0, 10) +#define NPCX_CHNDAT_NEW 15 +#define NPCX_THRCTL_THEN 15 +#define NPCX_THRCTL_L_H 14 +#define NPCX_THRCTL_CHNSEL FIELD(10, 4) +#define NPCX_THRCTL_THRVAL FIELD(0, 10) +#define NPCX_THRCTS_ADC_WKEN 15 +#define NPCX_THRCTS_THR3_IEN 10 +#define NPCX_THRCTS_THR2_IEN 9 +#define NPCX_THRCTS_THR1_IEN 8 +#define NPCX_THRCTS_ADC_EVENT 7 +#define NPCX_THRCTS_THR3_STS 2 +#define NPCX_THRCTS_THR2_STS 1 +#define NPCX_THRCTS_THR1_STS 0 +#define NPCX_THR_DCTL_THRD_EN 15 +#define NPCX_THR_DCTL_THR_DVAL FIELD(0, 10) + +#define NPCX_ADC_THRESH1 1 +#define NPCX_ADC_THRESH2 2 +#define NPCX_ADC_THRESH3 3 +#define NPCX_ADC_THRESH_CNT 3 diff --git a/chip/npcx/registers-npcx7.h b/chip/npcx/registers-npcx7.h index 6fa10f5430..2a4334149f 100644 --- a/chip/npcx/registers-npcx7.h +++ b/chip/npcx/registers-npcx7.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -24,98 +24,104 @@ #endif /* NPCX-IRQ numbers */ -#define NPCX_IRQ0_NOUSED NPCX_IRQ_0 -#define NPCX_IRQ1_NOUSED NPCX_IRQ_1 -#define NPCX_IRQ_KBSCAN NPCX_IRQ_2 -#define NPCX_IRQ_PM_CHAN_OBE NPCX_IRQ_3 +#define NPCX_IRQ0_NOUSED NPCX_IRQ_0 +#define NPCX_IRQ1_NOUSED NPCX_IRQ_1 +#define NPCX_IRQ_KBSCAN NPCX_IRQ_2 +#define NPCX_IRQ_PM_CHAN_OBE NPCX_IRQ_3 #ifdef NPCX_WOV_SUPPORT -#define NPCX_IRQ4_NOUSED NPCX_IRQ_4 +#define NPCX_IRQ4_NOUSED NPCX_IRQ_4 #else -#define NPCX_IRQ_PECI NPCX_IRQ_4 +#define NPCX_IRQ_PECI NPCX_IRQ_4 #endif -#define NPCX_IRQ5_NOUSED NPCX_IRQ_5 -#define NPCX_IRQ_PORT80 NPCX_IRQ_6 -#define NPCX_IRQ_MTC_WKINTAD_0 NPCX_IRQ_7 -#define NPCX_IRQ_MTC NPCX_IRQ_MTC_WKINTAD_0 -#define NPCX_IRQ_SMB8 NPCX_IRQ_8 -#define NPCX_IRQ_MFT_1 NPCX_IRQ_9 -#define NPCX_IRQ_ADC NPCX_IRQ_10 -#define NPCX_IRQ_WKINTEFGH_0 NPCX_IRQ_11 -#define NPCX_IRQ_GDMA NPCX_IRQ_12 -#define NPCX_IRQ_SMB1 NPCX_IRQ_13 -#define NPCX_IRQ_SMB2 NPCX_IRQ_14 -#define NPCX_IRQ_WKINTC_0 NPCX_IRQ_15 -#define NPCX_IRQ_SMB7 NPCX_IRQ_16 -#define NPCX_IRQ_ITIM16_3 NPCX_IRQ_17 -#define NPCX_IRQ_SHI NPCX_IRQ_18 -#define NPCX_IRQ_ESPI NPCX_IRQ_18 -#define NPCX_IRQ_SMB5 NPCX_IRQ_19 -#define NPCX_IRQ_SMB6 NPCX_IRQ_20 -#define NPCX_IRQ_PS2 NPCX_IRQ_21 +#define NPCX_IRQ5_NOUSED NPCX_IRQ_5 +#define NPCX_IRQ_PORT80 NPCX_IRQ_6 +#define NPCX_IRQ_MTC_WKINTAD_0 NPCX_IRQ_7 +#define NPCX_IRQ_MTC NPCX_IRQ_MTC_WKINTAD_0 +#define NPCX_IRQ_SMB8 NPCX_IRQ_8 +#define NPCX_IRQ_MFT_1 NPCX_IRQ_9 +#define NPCX_IRQ_ADC NPCX_IRQ_10 +#define NPCX_IRQ_WKINTEFGH_0 NPCX_IRQ_11 +#define NPCX_IRQ_GDMA NPCX_IRQ_12 +#define NPCX_IRQ_SMB1 NPCX_IRQ_13 +#define NPCX_IRQ_SMB2 NPCX_IRQ_14 +#define NPCX_IRQ_WKINTC_0 NPCX_IRQ_15 +#define NPCX_IRQ_SMB7 NPCX_IRQ_16 +#define NPCX_IRQ_ITIM16_3 NPCX_IRQ_17 +#define NPCX_IRQ_SHI NPCX_IRQ_18 +#define NPCX_IRQ_ESPI NPCX_IRQ_18 +#define NPCX_IRQ_SMB5 NPCX_IRQ_19 +#define NPCX_IRQ_SMB6 NPCX_IRQ_20 +#define NPCX_IRQ_PS2 NPCX_IRQ_21 #ifdef NPCX_WOV_SUPPORT -#define NPCX_IRQ_WOV NPCX_IRQ_22 +#define NPCX_IRQ_WOV NPCX_IRQ_22 #else -#define NPCX_IRQ22_NOUSED NPCX_IRQ_22 +#define NPCX_IRQ22_NOUSED NPCX_IRQ_22 #endif -#define NPCX_IRQ_MFT_2 NPCX_IRQ_23 -#define NPCX_IRQ_SHM NPCX_IRQ_24 -#define NPCX_IRQ_KBC_IBF NPCX_IRQ_25 -#define NPCX_IRQ_PM_CHAN_IBF NPCX_IRQ_26 -#define NPCX_IRQ_ITIM16_2 NPCX_IRQ_27 -#define NPCX_IRQ_ITIM16_1 NPCX_IRQ_28 -#define NPCX_IRQ29_NOUSED NPCX_IRQ_29 -#define NPCX_IRQ30_NOUSED NPCX_IRQ_30 -#define NPCX_IRQ_TWD_WKINTB_0 NPCX_IRQ_31 -#define NPCX_IRQ_UART2 NPCX_IRQ_32 -#define NPCX_IRQ_UART NPCX_IRQ_33 -#define NPCX_IRQ34_NOUSED NPCX_IRQ_34 -#define NPCX_IRQ35_NOUSED NPCX_IRQ_35 -#define NPCX_IRQ_SMB3 NPCX_IRQ_36 -#define NPCX_IRQ_SMB4 NPCX_IRQ_37 -#define NPCX_IRQ38_NOUSED NPCX_IRQ_38 -#define NPCX_IRQ39_NOUSED NPCX_IRQ_39 -#define NPCX_IRQ40_NOUSED NPCX_IRQ_40 -#define NPCX_IRQ_MFT_3 NPCX_IRQ_41 -#define NPCX_IRQ42_NOUSED NPCX_IRQ_42 -#define NPCX_IRQ_ITIM16_4 NPCX_IRQ_43 -#define NPCX_IRQ_ITIM16_5 NPCX_IRQ_44 -#define NPCX_IRQ_ITIM16_6 NPCX_IRQ_45 -#define NPCX_IRQ_ITIM32 NPCX_IRQ_46 -#define NPCX_IRQ_WKINTA_1 NPCX_IRQ_47 -#define NPCX_IRQ_WKINTB_1 NPCX_IRQ_48 -#define NPCX_IRQ_KSI_WKINTC_1 NPCX_IRQ_49 -#define NPCX_IRQ_WKINTD_1 NPCX_IRQ_50 -#define NPCX_IRQ_WKINTE_1 NPCX_IRQ_51 -#define NPCX_IRQ_WKINTF_1 NPCX_IRQ_52 -#define NPCX_IRQ_WKINTG_1 NPCX_IRQ_53 -#define NPCX_IRQ_WKINTH_1 NPCX_IRQ_54 -#define NPCX_IRQ55_NOUSED NPCX_IRQ_55 -#define NPCX_IRQ_KBC_OBE NPCX_IRQ_56 -#define NPCX_IRQ_SPI NPCX_IRQ_57 +#define NPCX_IRQ_MFT_2 NPCX_IRQ_23 +#define NPCX_IRQ_SHM NPCX_IRQ_24 +#define NPCX_IRQ_KBC_IBF NPCX_IRQ_25 +#define NPCX_IRQ_PM_CHAN_IBF NPCX_IRQ_26 +#define NPCX_IRQ_ITIM16_2 NPCX_IRQ_27 +#define NPCX_IRQ_ITIM16_1 NPCX_IRQ_28 +#define NPCX_IRQ29_NOUSED NPCX_IRQ_29 +#define NPCX_IRQ30_NOUSED NPCX_IRQ_30 +#define NPCX_IRQ_TWD_WKINTB_0 NPCX_IRQ_31 +#define NPCX_IRQ_UART2 NPCX_IRQ_32 +#define NPCX_IRQ_UART NPCX_IRQ_33 +#define NPCX_IRQ34_NOUSED NPCX_IRQ_34 +#define NPCX_IRQ35_NOUSED NPCX_IRQ_35 +#define NPCX_IRQ_SMB3 NPCX_IRQ_36 +#define NPCX_IRQ_SMB4 NPCX_IRQ_37 +#define NPCX_IRQ38_NOUSED NPCX_IRQ_38 +#define NPCX_IRQ39_NOUSED NPCX_IRQ_39 +#define NPCX_IRQ40_NOUSED NPCX_IRQ_40 +#define NPCX_IRQ_MFT_3 NPCX_IRQ_41 +#define NPCX_IRQ42_NOUSED NPCX_IRQ_42 +#define NPCX_IRQ_ITIM16_4 NPCX_IRQ_43 +#define NPCX_IRQ_ITIM16_5 NPCX_IRQ_44 +#define NPCX_IRQ_ITIM16_6 NPCX_IRQ_45 +#define NPCX_IRQ_ITIM32 NPCX_IRQ_46 +#define NPCX_IRQ_WKINTA_1 NPCX_IRQ_47 +#define NPCX_IRQ_WKINTB_1 NPCX_IRQ_48 +#define NPCX_IRQ_KSI_WKINTC_1 NPCX_IRQ_49 +#define NPCX_IRQ_WKINTD_1 NPCX_IRQ_50 +#define NPCX_IRQ_WKINTE_1 NPCX_IRQ_51 +#define NPCX_IRQ_WKINTF_1 NPCX_IRQ_52 +#define NPCX_IRQ_WKINTG_1 NPCX_IRQ_53 +#define NPCX_IRQ_WKINTH_1 NPCX_IRQ_54 +#define NPCX_IRQ55_NOUSED NPCX_IRQ_55 +#define NPCX_IRQ_KBC_OBE NPCX_IRQ_56 +#define NPCX_IRQ_SPI NPCX_IRQ_57 #ifdef NPCX_ITIM64_SUPPORT -#define NPCX_IRQ_ITIM64 NPCX_IRQ_58 +#define NPCX_IRQ_ITIM64 NPCX_IRQ_58 #else -#define NPCX_IRQ58_NOUSED NPCX_IRQ_58 +#define NPCX_IRQ58_NOUSED NPCX_IRQ_58 #endif -#define NPCX_IRQ_WKINTFG_2 NPCX_IRQ_59 -#define NPCX_IRQ_WKINTA_2 NPCX_IRQ_60 -#define NPCX_IRQ_WKINTB_2 NPCX_IRQ_61 -#define NPCX_IRQ_WKINTC_2 NPCX_IRQ_62 -#define NPCX_IRQ_WKINTD_2 NPCX_IRQ_63 +#define NPCX_IRQ_WKINTFG_2 NPCX_IRQ_59 +#define NPCX_IRQ_WKINTA_2 NPCX_IRQ_60 +#define NPCX_IRQ_WKINTB_2 NPCX_IRQ_61 +#define NPCX_IRQ_WKINTC_2 NPCX_IRQ_62 +#define NPCX_IRQ_WKINTD_2 NPCX_IRQ_63 /* Modules Map */ -#define NPCX_ITIM32_BASE_ADDR 0x400BC000 -#define NPCX_CR_UART_BASE_ADDR(mdl) (0x400C4000 + ((mdl) * 0x2000L)) -#define NPCX_SMB_BASE_ADDR(mdl) (((mdl) < 2) ? \ - (0x40009000 + ((mdl) * 0x2000L)) : \ - ((mdl) < 4) ? \ - (0x400C0000 + (((mdl) - 2) * 0x2000L)) : \ - ((mdl) == 4) ? \ - (0x40008000) : \ - (0x40017000 + (((mdl) - 5) * 0x1000L))) - -#define NPCX_HFCBCD1 REG8(NPCX_HFCG_BASE_ADDR + 0x012) -#define NPCX_HFCBCD2 REG8(NPCX_HFCG_BASE_ADDR + 0x014) + +/* Miscellaneous Device Control (MDC) registers */ +#define NPCX_FWCTRL REG8(NPCX_MDC_BASE_ADDR + 0x007) + +/* MDC register fields */ +#define NPCX_FWCTRL_RO_REGION 0 +#define NPCX_FWCTRL_FW_SLOT 1 + +#define NPCX_ITIM32_BASE_ADDR 0x400BC000 +#define NPCX_CR_UART_BASE_ADDR(mdl) (0x400C4000 + ((mdl)*0x2000L)) +#define NPCX_SMB_BASE_ADDR(mdl) \ + (((mdl) < 2) ? (0x40009000 + ((mdl)*0x2000L)) : \ + ((mdl) < 4) ? (0x400C0000 + (((mdl)-2) * 0x2000L)) : \ + ((mdl) == 4) ? (0x40008000) : \ + (0x40017000 + (((mdl)-5) * 0x1000L))) + +#define NPCX_HFCBCD1 REG8(NPCX_HFCG_BASE_ADDR + 0x012) +#define NPCX_HFCBCD2 REG8(NPCX_HFCG_BASE_ADDR + 0x014) enum { NPCX_UART_PORT0 = 0, /* UART port 0 */ @@ -127,44 +133,44 @@ enum { #ifdef NPCX_UART_FIFO_SUPPORT /* UART registers only used for FIFO mode */ -#define NPCX_UFTSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x020) -#define NPCX_UFRSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x022) -#define NPCX_UFTCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x024) -#define NPCX_UFRCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x026) +#define NPCX_UFTSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x020) +#define NPCX_UFRSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x022) +#define NPCX_UFTCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x024) +#define NPCX_UFRCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x026) /* UART FIFO register fields */ -#define NPCX_UMDSL_FIFO_MD 0 - -#define NPCX_UFTSTS_TEMPTY_LVL FIELD(0, 5) -#define NPCX_UFTSTS_TEMPTY_LVL_STS 5 -#define NPCX_UFTSTS_TFIFO_EMPTY_STS 6 -#define NPCX_UFTSTS_NXMIP 7 - -#define NPCX_UFRSTS_RFULL_LVL_STS 5 -#define NPCX_UFRSTS_RFIFO_NEMPTY_STS 6 -#define NPCX_UFRSTS_ERR 7 - -#define NPCX_UFTCTL_TEMPTY_LVL_SEL FIELD(0, 5) -#define NPCX_UFTCTL_TEMPTY_LVL_EN 5 -#define NPCX_UFTCTL_TEMPTY_EN 6 -#define NPCX_UFTCTL_NXMIPEN 7 - -#define NPCX_UFRCTL_RFULL_LVL_SEL FIELD(0, 5) -#define NPCX_UFRCTL_RFULL_LVL_EN 5 -#define NPCX_UFRCTL_RNEMPTY_EN 6 -#define NPCX_UFRCTL_ERR_EN 7 +#define NPCX_UMDSL_FIFO_MD 0 + +#define NPCX_UFTSTS_TEMPTY_LVL FIELD(0, 5) +#define NPCX_UFTSTS_TEMPTY_LVL_STS 5 +#define NPCX_UFTSTS_TFIFO_EMPTY_STS 6 +#define NPCX_UFTSTS_NXMIP 7 + +#define NPCX_UFRSTS_RFULL_LVL_STS 5 +#define NPCX_UFRSTS_RFIFO_NEMPTY_STS 6 +#define NPCX_UFRSTS_ERR 7 + +#define NPCX_UFTCTL_TEMPTY_LVL_SEL FIELD(0, 5) +#define NPCX_UFTCTL_TEMPTY_LVL_EN 5 +#define NPCX_UFTCTL_TEMPTY_EN 6 +#define NPCX_UFTCTL_NXMIPEN 7 + +#define NPCX_UFRCTL_RFULL_LVL_SEL FIELD(0, 5) +#define NPCX_UFRCTL_RFULL_LVL_EN 5 +#define NPCX_UFRCTL_RNEMPTY_EN 6 +#define NPCX_UFRCTL_ERR_EN 7 #endif /* KBSCAN register fields */ -#define NPCX_KBHDRV_FIELD FIELD(6, 2) +#define NPCX_KBHDRV_FIELD FIELD(6, 2) /* GLUE registers */ #ifdef NPCX_PSL_MODE_SUPPORT -#define NPCX_GLUE_PSL_CTS REG8(NPCX_GLUE_REGS_BASE + 0x027) +#define NPCX_GLUE_PSL_CTS REG8(NPCX_GLUE_REGS_BASE + 0x027) #endif /* GPIO registers */ -#define NPCX_PLOCK_CTL(n) REG8(NPCX_GPIO_BASE_ADDR(n) + 0x007) +#define NPCX_PLOCK_CTL(n) REG8(NPCX_GPIO_BASE_ADDR(n) + 0x007) /* System Configuration (SCFG) Registers */ @@ -189,108 +195,112 @@ enum { ALT_GROUP_COUNT }; -#define NPCX_DEVALT(n) REG8(NPCX_SCFG_BASE_ADDR + 0x010 + (n)) +#define NPCX_DEVALT(n) REG8(NPCX_SCFG_BASE_ADDR + 0x010 + (n)) -#define NPCX_LV_GPIO_CTL_ADDR(n) (((n) < 5) ? \ - (NPCX_SCFG_BASE_ADDR + 0x02A + (n)) :\ - (NPCX_SCFG_BASE_ADDR + 0x026)) -#define NPCX_LV_GPIO_CTL(n) REG8(NPCX_LV_GPIO_CTL_ADDR(n)) +#define NPCX_LV_GPIO_CTL_ADDR(n) \ + (((n) < 5) ? (NPCX_SCFG_BASE_ADDR + 0x02A + (n)) : \ + (NPCX_SCFG_BASE_ADDR + 0x026)) +#define NPCX_LV_GPIO_CTL(n) REG8(NPCX_LV_GPIO_CTL_ADDR(n)) /* pin-mux for I2C */ -#define NPCX_DEVALT2_I2C0_0_SL 0 -#define NPCX_DEVALT2_I2C7_0_SL 1 -#define NPCX_DEVALT2_I2C1_0_SL 2 -#define NPCX_DEVALT2_I2C6_0_SL 3 -#define NPCX_DEVALT2_I2C2_0_SL 4 -#define NPCX_DEVALT2_I2C5_0_SL 5 -#define NPCX_DEVALT2_I2C3_0_SL 6 -#define NPCX_DEVALT2_I2C4_0_SL 7 -#define NPCX_DEVALT6_I2C6_1_SL 5 -#define NPCX_DEVALT6_I2C5_1_SL 6 -#define NPCX_DEVALT6_I2C4_1_SL 7 +#define NPCX_DEVALT2_I2C0_0_SL 0 +#define NPCX_DEVALT2_I2C7_0_SL 1 +#define NPCX_DEVALT2_I2C1_0_SL 2 +#define NPCX_DEVALT2_I2C6_0_SL 3 +#define NPCX_DEVALT2_I2C2_0_SL 4 +#define NPCX_DEVALT2_I2C5_0_SL 5 +#define NPCX_DEVALT2_I2C3_0_SL 6 +#define NPCX_DEVALT2_I2C4_0_SL 7 +#define NPCX_DEVALT6_I2C6_1_SL 5 +#define NPCX_DEVALT6_I2C5_1_SL 6 +#define NPCX_DEVALT6_I2C4_1_SL 7 + +/* pin-mux for JTAG */ +#define NPCX_DEVALT5_NJEN1_EN 1 +#define NPCX_DEVALT5_NJEN0_EN 2 /* pin-mux for ADC */ -#define NPCX_DEVALTF_ADC5_SL 0 -#define NPCX_DEVALTF_ADC6_SL 1 -#define NPCX_DEVALTF_ADC7_SL 2 -#define NPCX_DEVALTF_ADC8_SL 3 -#define NPCX_DEVALTF_ADC9_SL 4 +#define NPCX_DEVALTF_ADC5_SL 0 +#define NPCX_DEVALTF_ADC6_SL 1 +#define NPCX_DEVALTF_ADC7_SL 2 +#define NPCX_DEVALTF_ADC8_SL 3 +#define NPCX_DEVALTF_ADC9_SL 4 /* pin-mux for PSL */ #ifdef NPCX_PSL_MODE_SUPPORT -#define NPCX_DEVALTD_PSL_IN1_AHI 0 -#define NPCX_DEVALTD_NPSL_IN1_SL 1 -#define NPCX_DEVALTD_PSL_IN2_AHI 2 -#define NPCX_DEVALTD_NPSL_IN2_SL 3 -#define NPCX_DEVALTD_PSL_IN3_AHI 4 -#define NPCX_DEVALTD_PSL_IN3_SL 5 -#define NPCX_DEVALTD_PSL_IN4_AHI 6 -#define NPCX_DEVALTD_PSL_IN4_SL 7 +#define NPCX_DEVALTD_PSL_IN1_AHI 0 +#define NPCX_DEVALTD_NPSL_IN1_SL 1 +#define NPCX_DEVALTD_PSL_IN2_AHI 2 +#define NPCX_DEVALTD_NPSL_IN2_SL 3 +#define NPCX_DEVALTD_PSL_IN3_AHI 4 +#define NPCX_DEVALTD_PSL_IN3_SL 5 +#define NPCX_DEVALTD_PSL_IN4_AHI 6 +#define NPCX_DEVALTD_PSL_IN4_SL 7 #endif #ifdef CHIP_VARIANT_NPCX7M6G /* External 32KHz crytal osc. input support */ -#define NPCX_DEVALTA_32KCLKIN_SL 3 +#define NPCX_DEVALTA_32KCLKIN_SL 3 #endif /* pin-mux for UART */ -#define NPCX_DEVALTA_UART_SL1 7 -#define NPCX_DEVALTC_UART_SL2 0 +#define NPCX_DEVALTA_UART_SL1 7 +#define NPCX_DEVALTC_UART_SL2 0 #ifdef NPCX_SECOND_UART /* Secondary UART selection */ -#define NPCX_DEVALTA_UART2_SL 5 +#define NPCX_DEVALTA_UART2_SL 5 #endif /* SHI module version 2 enable bit */ -#define NPCX_DEVALTF_SHI_NEW 7 +#define NPCX_DEVALTF_SHI_NEW 7 #ifdef NPCX_WOV_SUPPORT /* pin-mux for WoV */ -#define NPCX_DEVALTE_WOV_SL 0 -#define NPCX_DEVALTE_I2S_SL 1 -#define NPCX_DEVALTE_DMCLK_FAST 2 +#define NPCX_DEVALTE_WOV_SL 0 +#define NPCX_DEVALTE_I2S_SL 1 +#define NPCX_DEVALTE_DMCLK_FAST 2 #endif /* SMBus register fields */ -#define NPCX_SMBSEL_SMB4SEL 4 -#define NPCX_SMBSEL_SMB5SEL 5 -#define NPCX_SMBSEL_SMB6SEL 6 +#define NPCX_SMBSEL_SMB4SEL 4 +#define NPCX_SMBSEL_SMB5SEL 5 +#define NPCX_SMBSEL_SMB6SEL 6 -/* SMB enumeration: I2C port definitions. */ +/* SMB enumeration: I2C port definitions */ enum { - NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0 */ - NPCX_I2C_PORT1_0, /* I2C port 1, bus 0 */ - NPCX_I2C_PORT2_0, /* I2C port 2, bus 0 */ - NPCX_I2C_PORT3_0, /* I2C port 3, bus 0 */ + NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0 */ + NPCX_I2C_PORT1_0, /* I2C port 1, bus 0 */ + NPCX_I2C_PORT2_0, /* I2C port 2, bus 0 */ + NPCX_I2C_PORT3_0, /* I2C port 3, bus 0 */ #ifdef CHIP_VARIANT_NPCX7M6G - NPCX_I2C_PORT4_0, /* I2C port 4, bus 0 */ + NPCX_I2C_PORT4_0, /* I2C port 4, bus 0 */ #endif - NPCX_I2C_PORT4_1, /* I2C port 4, bus 1 */ - NPCX_I2C_PORT5_0, /* I2C port 5, bus 0 */ - NPCX_I2C_PORT5_1, /* I2C port 5, bus 1 */ - NPCX_I2C_PORT6_0, /* I2C port 6, bus 0 */ - NPCX_I2C_PORT6_1, /* I2C port 6, bus 1 */ - NPCX_I2C_PORT7_0, /* I2C port 7, bus 0 */ + NPCX_I2C_PORT4_1, /* I2C port 4, bus 1 */ + NPCX_I2C_PORT5_0, /* I2C port 5, bus 0 */ + NPCX_I2C_PORT5_1, /* I2C port 5, bus 1 */ + NPCX_I2C_PORT6_0, /* I2C port 6, bus 0 */ + NPCX_I2C_PORT6_1, /* I2C port 6, bus 1 */ + NPCX_I2C_PORT7_0, /* I2C port 7, bus 0 */ NPCX_I2C_COUNT, }; /* Power Management Controller (PMC) Registers */ -#define NPCX_FMUL_WIN_DLY REG8(NPCX_PMC_BASE_ADDR + 0x010) -#define NPCX_RAM_PD(offset) REG8(NPCX_PMC_BASE_ADDR + 0x020 + (offset)) +#define NPCX_FMUL_WIN_DLY REG8(NPCX_PMC_BASE_ADDR + 0x010) +#define NPCX_RAM_PD(offset) REG8(NPCX_PMC_BASE_ADDR + 0x020 + (offset)) /* PMC register fields */ -#define NPCX_PWDWN_CTL3_SMB4_PD 4 -#define NPCX_PWDWN_CTL7_SMB5_PD 0 -#define NPCX_PWDWN_CTL7_SMB6_PD 1 -#define NPCX_PWDWN_CTL7_SMB7_PD 2 +#define NPCX_PWDWN_CTL3_SMB4_PD 4 +#define NPCX_PWDWN_CTL7_SMB5_PD 0 +#define NPCX_PWDWN_CTL7_SMB6_PD 1 +#define NPCX_PWDWN_CTL7_SMB7_PD 2 #ifdef NPCX_ITIM64_SUPPORT -#define NPCX_PWDWN_CTL7_ITIM64_PD 5 +#define NPCX_PWDWN_CTL7_ITIM64_PD 5 #endif #ifdef NPCX_SECOND_UART -#define NPCX_PWDWN_CTL7_UART2_PD 6 +#define NPCX_PWDWN_CTL7_UART2_PD 6 #endif #ifdef NPCX_WOV_SUPPORT -#define NPCX_PWDWN_CTL7_WOV_PD 7 +#define NPCX_PWDWN_CTL7_WOV_PD 7 #endif /* @@ -316,7 +326,7 @@ enum { CGC_OFFSET_UART2 = 6, #endif #ifdef NPCX_WOV_SUPPORT - CGC_OFFSET_WOV = 6, + CGC_OFFSET_WOV = 6, #endif }; @@ -331,53 +341,52 @@ enum NPCX_PMC_PWDWN_CTL_T { NPCX_PMC_PWDWN_CNT, }; -#define CGC_I2C_MASK (BIT(NPCX_PWDWN_CTL3_SMB0_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB1_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB2_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB3_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB4_PD)) -#define CGC_I2C_MASK2 (BIT(NPCX_PWDWN_CTL7_SMB5_PD) | \ - BIT(NPCX_PWDWN_CTL7_SMB6_PD) | \ - BIT(NPCX_PWDWN_CTL7_SMB7_PD)) +#define CGC_I2C_MASK \ + (BIT(NPCX_PWDWN_CTL3_SMB0_PD) | BIT(NPCX_PWDWN_CTL3_SMB1_PD) | \ + BIT(NPCX_PWDWN_CTL3_SMB2_PD) | BIT(NPCX_PWDWN_CTL3_SMB3_PD) | \ + BIT(NPCX_PWDWN_CTL3_SMB4_PD)) +#define CGC_I2C_MASK2 \ + (BIT(NPCX_PWDWN_CTL7_SMB5_PD) | BIT(NPCX_PWDWN_CTL7_SMB6_PD) | \ + BIT(NPCX_PWDWN_CTL7_SMB7_PD)) #ifdef NPCX_SECOND_UART -#define CGC_UART2_MASK BIT(NPCX_PWDWN_CTL7_UART2_PD) +#define CGC_UART2_MASK BIT(NPCX_PWDWN_CTL7_UART2_PD) #endif #ifdef NPCX_WOV_SUPPORT -#define CGC_WOV_MASK BIT(NPCX_PWDWN_CTL7_WOV_PD) +#define CGC_WOV_MASK BIT(NPCX_PWDWN_CTL7_WOV_PD) #endif /* BBRAM register fields */ -#if defined(CHIP_VARIANT_NPCX7M6FB) || defined(CHIP_VARIANT_NPCX7M6FC) || \ +#if defined(CHIP_VARIANT_NPCX7M6FB) || defined(CHIP_VARIANT_NPCX7M6FC) || \ defined(CHIP_VARIANT_NPCX7M7FC) || defined(CHIP_VARIANT_NPCX7M7WB) || \ defined(CHIP_VARIANT_NPCX7M7WC) -#define NPCX_BKUP_STS_VSBY_STS 1 -#define NPCX_BKUP_STS_VCC1_STS 0 -#define NPCX_BKUP_STS_ALL_MASK \ +#define NPCX_BKUP_STS_VSBY_STS 1 +#define NPCX_BKUP_STS_VCC1_STS 0 +#define NPCX_BKUP_STS_ALL_MASK \ (BIT(NPCX_BKUP_STS_IBBR) | BIT(NPCX_BKUP_STS_VSBY_STS) | \ - BIT(NPCX_BKUP_STS_VCC1_STS)) -#define NPCX_BBRAM_SIZE 128 /* Size of BBRAM */ + BIT(NPCX_BKUP_STS_VCC1_STS)) +#define NPCX_BBRAM_SIZE 128 /* Size of BBRAM */ #else #define NPCX_BKUP_STS_ALL_MASK BIT(NPCX_BKUP_STS_IBBR) -#define NPCX_BBRAM_SIZE 64 /* Size of BBRAM */ +#define NPCX_BBRAM_SIZE 64 /* Size of BBRAM */ #endif /* ITIM16 registers */ -#define NPCX_ITCNT8(n) REG8(NPCX_ITIM_BASE_ADDR(n) + 0x000) -#define NPCX_ITCNT16(n) REG16(NPCX_ITIM_BASE_ADDR(n) + 0x002) +#define NPCX_ITCNT8(n) REG8(NPCX_ITIM_BASE_ADDR(n) + 0x000) +#define NPCX_ITCNT16(n) REG16(NPCX_ITIM_BASE_ADDR(n) + 0x002) /* ITIM32 registers */ -#define NPCX_ITCNT32 REG32(NPCX_ITIM32_BASE_ADDR + 0x008) +#define NPCX_ITCNT32 REG32(NPCX_ITIM32_BASE_ADDR + 0x008) /* Timer counter register used for 1 micro-second system tick */ -#define NPCX_ITCNT_SYSTEM NPCX_ITCNT32 +#define NPCX_ITCNT_SYSTEM NPCX_ITCNT32 /* Timer counter register used for others */ -#define NPCX_ITCNT NPCX_ITCNT16 +#define NPCX_ITCNT NPCX_ITCNT16 /* ITIM module No. used for event */ -#define ITIM_EVENT_NO ITIM16_1 +#define ITIM_EVENT_NO ITIM16_1 /* ITIM module No. used for watchdog */ -#define ITIM_WDG_NO ITIM16_5 +#define ITIM_WDG_NO ITIM16_5 /* ITIM module No. used for 1 micro-second system tick */ -#define ITIM_SYSTEM_NO ITIM32 +#define ITIM_SYSTEM_NO ITIM32 /* ITIM enumeration */ enum ITIM_MODULE_T { @@ -392,56 +401,56 @@ enum ITIM_MODULE_T { }; /* Serial Host Interface (SHI) Registers - only available on SHI Version 2 */ -#define NPCX_SHICFG3 REG8(NPCX_SHI_BASE_ADDR + 0x00C) -#define NPCX_SHICFG4 REG8(NPCX_SHI_BASE_ADDR + 0x00D) -#define NPCX_SHICFG5 REG8(NPCX_SHI_BASE_ADDR + 0x00E) -#define NPCX_EVSTAT2 REG8(NPCX_SHI_BASE_ADDR + 0x00F) -#define NPCX_EVENABLE2 REG8(NPCX_SHI_BASE_ADDR + 0x010) -#define NPCX_OBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x020 + (n)) -#define NPCX_IBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x0A0 + (n)) +#define NPCX_SHICFG3 REG8(NPCX_SHI_BASE_ADDR + 0x00C) +#define NPCX_SHICFG4 REG8(NPCX_SHI_BASE_ADDR + 0x00D) +#define NPCX_SHICFG5 REG8(NPCX_SHI_BASE_ADDR + 0x00E) +#define NPCX_EVSTAT2 REG8(NPCX_SHI_BASE_ADDR + 0x00F) +#define NPCX_EVENABLE2 REG8(NPCX_SHI_BASE_ADDR + 0x010) +#define NPCX_OBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x020 + (n)) +#define NPCX_IBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x0A0 + (n)) /* SHI register fields */ -#define NPCX_SHICFG3_OBUFLVLDIS 7 -#define NPCX_SHICFG4_IBUFLVLDIS 7 -#define NPCX_SHICFG5_IBUFLVL2 FIELD(0, 6) -#define NPCX_SHICFG5_IBUFLVL2DIS 7 -#define NPCX_EVSTAT2_IBHF2 0 -#define NPCX_EVSTAT2_CSNRE 1 -#define NPCX_EVSTAT2_CSNFE 2 -#define NPCX_EVENABLE2_IBHF2EN 0 -#define NPCX_EVENABLE2_CSNREEN 1 -#define NPCX_EVENABLE2_CSNFEEN 2 +#define NPCX_SHICFG3_OBUFLVLDIS 7 +#define NPCX_SHICFG4_IBUFLVLDIS 7 +#define NPCX_SHICFG5_IBUFLVL2 FIELD(0, 6) +#define NPCX_SHICFG5_IBUFLVL2DIS 7 +#define NPCX_EVSTAT2_IBHF2 0 +#define NPCX_EVSTAT2_CSNRE 1 +#define NPCX_EVSTAT2_CSNFE 2 +#define NPCX_EVENABLE2_IBHF2EN 0 +#define NPCX_EVENABLE2_CSNREEN 1 +#define NPCX_EVENABLE2_CSNFEEN 2 /* eSPI register fields */ -#define NPCX_ESPIIE_BMTXDONEIE 19 -#define NPCX_ESPIIE_PBMRXIE 20 -#define NPCX_ESPIIE_PMSGRXIE 21 -#define NPCX_ESPIIE_BMBURSTERRIE 22 -#define NPCX_ESPIIE_BMBURSTDONEIE 23 - -#define NPCX_ESPIWE_PBMRXWE 20 -#define NPCX_ESPIWE_PMSGRXWE 21 - -#define NPCX_ESPISTS_VWUPDW 17 -#define NPCX_ESPISTS_BMTXDONE 19 -#define NPCX_ESPISTS_PBMRX 20 -#define NPCX_ESPISTS_PMSGRX 21 -#define NPCX_ESPISTS_BMBURSTERR 22 -#define NPCX_ESPISTS_BMBURSTDONE 23 -#define NPCX_ESPISTS_ESPIRST_LVL 24 - -#define ESPIIE_BMTXDONE BIT(NPCX_ESPIIE_BMTXDONEIE) -#define ESPIIE_PBMRX BIT(NPCX_ESPIIE_PBMRXIE) -#define ESPIIE_PMSGRX BIT(NPCX_ESPIIE_PMSGRXIE) -#define ESPIIE_BMBURSTERR BIT(NPCX_ESPIIE_BMBURSTERRIE) -#define ESPIIE_BMBURSTDONE BIT(NPCX_ESPIIE_BMBURSTDONEIE) - -#define ESPIWE_PBMRX BIT(NPCX_ESPIWE_PBMRXWE) -#define ESPIWE_PMSGRX BIT(NPCX_ESPIWE_PMSGRXWE) +#define NPCX_ESPIIE_BMTXDONEIE 19 +#define NPCX_ESPIIE_PBMRXIE 20 +#define NPCX_ESPIIE_PMSGRXIE 21 +#define NPCX_ESPIIE_BMBURSTERRIE 22 +#define NPCX_ESPIIE_BMBURSTDONEIE 23 + +#define NPCX_ESPIWE_PBMRXWE 20 +#define NPCX_ESPIWE_PMSGRXWE 21 + +#define NPCX_ESPISTS_VWUPDW 17 +#define NPCX_ESPISTS_BMTXDONE 19 +#define NPCX_ESPISTS_PBMRX 20 +#define NPCX_ESPISTS_PMSGRX 21 +#define NPCX_ESPISTS_BMBURSTERR 22 +#define NPCX_ESPISTS_BMBURSTDONE 23 +#define NPCX_ESPISTS_ESPIRST_LVL 24 + +#define ESPIIE_BMTXDONE BIT(NPCX_ESPIIE_BMTXDONEIE) +#define ESPIIE_PBMRX BIT(NPCX_ESPIIE_PBMRXIE) +#define ESPIIE_PMSGRX BIT(NPCX_ESPIIE_PMSGRXIE) +#define ESPIIE_BMBURSTERR BIT(NPCX_ESPIIE_BMBURSTERRIE) +#define ESPIIE_BMBURSTDONE BIT(NPCX_ESPIIE_BMBURSTDONEIE) + +#define ESPIWE_PBMRX BIT(NPCX_ESPIWE_PBMRXWE) +#define ESPIWE_PMSGRX BIT(NPCX_ESPIWE_PMSGRXWE) /* Bit field manipulation for VWEVMS Value */ -#define VWEVMS_WK_EN(e) (((e)<<20) & 0x00100000) -#define VWEVMS_INTWK_EN(e) (VWEVMS_INT_EN(e) | VWEVMS_WK_EN(e)) +#define VWEVMS_WK_EN(e) (((e) << 20) & 0x00100000) +#define VWEVMS_INTWK_EN(e) (VWEVMS_INT_EN(e) | VWEVMS_WK_EN(e)) /* eSPI max supported frequency */ enum { @@ -454,41 +463,41 @@ enum { /* eSPI max frequency support per FMCLK */ #if (FMCLK <= 33000000) -#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_33 +#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_33 #else -#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_50 +#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_50 #endif /* UART registers */ -#define NPCX_UART_WK_GROUP MIWU_GROUP_8 -#define NPCX_UART_WK_BIT 7 +#define NPCX_UART_WK_GROUP MIWU_GROUP_8 +#define NPCX_UART_WK_BIT 7 #ifdef NPCX_SECOND_UART -#define NPCX_UART2_WK_GROUP MIWU_GROUP_1 -#define NPCX_UART2_WK_BIT 6 +#define NPCX_UART2_WK_GROUP MIWU_GROUP_1 +#define NPCX_UART2_WK_BIT 6 #endif /* MIWU registers */ -#define NPCX_WKEDG_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x00 + \ - ((n) * 2L) + ((n) < 5 ? 0 : 0x1E)) -#define NPCX_WKAEDG_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x01 + \ - ((n) * 2L) + ((n) < 5 ? 0 : 0x1E)) -#define NPCX_WKPND_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x0A + \ - ((n) * 4L) + ((n) < 5 ? 0 : 0x10)) -#define NPCX_WKPCL_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x0C + \ - ((n) * 4L) + ((n) < 5 ? 0 : 0x10)) -#define NPCX_WKEN_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x1E + \ - ((n) * 2L) + ((n) < 5 ? 0 : 0x12)) -#define NPCX_WKINEN_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x1F + \ - ((n) * 2L) + ((n) < 5 ? 0 : 0x12)) -#define NPCX_WKMOD_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x70 + (n)) - -#define NPCX_WKEDG(port, n) REG8(NPCX_WKEDG_ADDR(port, n)) -#define NPCX_WKAEDG(port, n) REG8(NPCX_WKAEDG_ADDR(port, n)) -#define NPCX_WKPND(port, n) REG8(NPCX_WKPND_ADDR(port, n)) -#define NPCX_WKPCL(port, n) REG8(NPCX_WKPCL_ADDR(port, n)) -#define NPCX_WKEN(port, n) REG8(NPCX_WKEN_ADDR(port, n)) -#define NPCX_WKINEN(port, n) REG8(NPCX_WKINEN_ADDR(port, n)) -#define NPCX_WKMOD(port, n) REG8(NPCX_WKMOD_ADDR(port, n)) +#define NPCX_WKEDG_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x00 + ((n)*2L) + ((n) < 5 ? 0 : 0x1E)) +#define NPCX_WKAEDG_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x01 + ((n)*2L) + ((n) < 5 ? 0 : 0x1E)) +#define NPCX_WKPND_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x0A + ((n)*4L) + ((n) < 5 ? 0 : 0x10)) +#define NPCX_WKPCL_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x0C + ((n)*4L) + ((n) < 5 ? 0 : 0x10)) +#define NPCX_WKEN_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x1E + ((n)*2L) + ((n) < 5 ? 0 : 0x12)) +#define NPCX_WKINEN_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x1F + ((n)*2L) + ((n) < 5 ? 0 : 0x12)) +#define NPCX_WKMOD_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x70 + (n)) + +#define NPCX_WKEDG(port, n) REG8(NPCX_WKEDG_ADDR(port, n)) +#define NPCX_WKAEDG(port, n) REG8(NPCX_WKAEDG_ADDR(port, n)) +#define NPCX_WKPND(port, n) REG8(NPCX_WKPND_ADDR(port, n)) +#define NPCX_WKPCL(port, n) REG8(NPCX_WKPCL_ADDR(port, n)) +#define NPCX_WKEN(port, n) REG8(NPCX_WKEN_ADDR(port, n)) +#define NPCX_WKINEN(port, n) REG8(NPCX_WKINEN_ADDR(port, n)) +#define NPCX_WKMOD(port, n) REG8(NPCX_WKMOD_ADDR(port, n)) /* UART registers and functions */ #if NPCX_UART_MODULE2 @@ -496,64 +505,64 @@ enum { * To be used as 2nd parameter to NPCX_WK*() macro, table (1st parameter) is * always 1 == MIWU_TABLE_1. */ -#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTG_1 -#define NPCX_UART_DEVALT NPCX_DEVALT(0x0C) -#define NPCX_UART_DEVALT_SL NPCX_DEVALTC_UART_SL2 -#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0A) -#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTA_UART_SL1 +#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTG_1 +#define NPCX_UART_DEVALT NPCX_DEVALT(0x0C) +#define NPCX_UART_DEVALT_SL NPCX_DEVALTC_UART_SL2 +#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0A) +#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTA_UART_SL1 #else /* !NPCX_UART_MODULE2 */ -#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTB_1 -#define NPCX_UART_DEVALT NPCX_DEVALT(0x0A) -#define NPCX_UART_DEVALT_SL NPCX_DEVALTA_UART_SL1 -#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0C) -#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTC_UART_SL2 +#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTB_1 +#define NPCX_UART_DEVALT NPCX_DEVALT(0x0A) +#define NPCX_UART_DEVALT_SL NPCX_DEVALTA_UART_SL1 +#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0C) +#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTC_UART_SL2 #endif /* NPCX_UART_MODULE2 */ /* ADC Registers */ -#define NPCX_ADCSTS REG16(NPCX_ADC_BASE_ADDR + 0x000) -#define NPCX_ADCCNF REG16(NPCX_ADC_BASE_ADDR + 0x002) -#define NPCX_ATCTL REG16(NPCX_ADC_BASE_ADDR + 0x004) -#define NPCX_ASCADD REG16(NPCX_ADC_BASE_ADDR + 0x006) -#define NPCX_ADCCS REG16(NPCX_ADC_BASE_ADDR + 0x008) +#define NPCX_ADCSTS REG16(NPCX_ADC_BASE_ADDR + 0x000) +#define NPCX_ADCCNF REG16(NPCX_ADC_BASE_ADDR + 0x002) +#define NPCX_ATCTL REG16(NPCX_ADC_BASE_ADDR + 0x004) +#define NPCX_ASCADD REG16(NPCX_ADC_BASE_ADDR + 0x006) +#define NPCX_ADCCS REG16(NPCX_ADC_BASE_ADDR + 0x008) /* NOTE: These are 1-based for the threshold detectors. */ -#define NPCX_THRCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x012 + (2L*(n))) -#define NPCX_THRCTS REG16(NPCX_ADC_BASE_ADDR + 0x01A) -#define NPCX_THR_DCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x038 + (2L*(n))) +#define NPCX_THRCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x012 + (2L * (n))) +#define NPCX_THRCTS REG16(NPCX_ADC_BASE_ADDR + 0x01A) +#define NPCX_THR_DCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x038 + (2L * (n))) /* NOTE: This is 0-based for the ADC channels. */ -#define NPCX_CHNDAT(n) REG16(NPCX_ADC_BASE_ADDR + 0x040 + (2L*(n))) -#define NPCX_ADCCNF2 REG16(NPCX_ADC_BASE_ADDR + 0x020) -#define NPCX_GENDLY REG16(NPCX_ADC_BASE_ADDR + 0x022) -#define NPCX_MEAST REG16(NPCX_ADC_BASE_ADDR + 0x026) +#define NPCX_CHNDAT(n) REG16(NPCX_ADC_BASE_ADDR + 0x040 + (2L * (n))) +#define NPCX_ADCCNF2 REG16(NPCX_ADC_BASE_ADDR + 0x020) +#define NPCX_GENDLY REG16(NPCX_ADC_BASE_ADDR + 0x022) +#define NPCX_MEAST REG16(NPCX_ADC_BASE_ADDR + 0x026) /* ADC register fields */ -#define NPCX_ATCTL_SCLKDIV_FIELD FIELD(0, 6) -#define NPCX_ATCTL_DLY_FIELD FIELD(8, 3) -#define NPCX_ASCADD_SADDR_FIELD FIELD(0, 5) -#define NPCX_ADCSTS_EOCEV 0 -#define NPCX_ADCCNF_ADCMD_FIELD FIELD(1, 2) -#define NPCX_ADCCNF_ADCRPTC 3 -#define NPCX_ADCCNF_INTECEN 6 -#define NPCX_ADCCNF_START 4 -#define NPCX_ADCCNF_ADCEN 0 -#define NPCX_ADCCNF_STOP 11 -#define NPCX_CHNDAT_CHDAT_FIELD FIELD(0, 10) -#define NPCX_CHNDAT_NEW 15 -#define NPCX_THRCTL_THEN 15 -#define NPCX_THRCTL_L_H 14 -#define NPCX_THRCTL_CHNSEL FIELD(10, 4) -#define NPCX_THRCTL_THRVAL FIELD(0, 10) -#define NPCX_THRCTS_ADC_WKEN 15 -#define NPCX_THRCTS_THR3_IEN 10 -#define NPCX_THRCTS_THR2_IEN 9 -#define NPCX_THRCTS_THR1_IEN 8 -#define NPCX_THRCTS_ADC_EVENT 7 -#define NPCX_THRCTS_THR3_STS 2 -#define NPCX_THRCTS_THR2_STS 1 -#define NPCX_THRCTS_THR1_STS 0 -#define NPCX_THR_DCTL_THRD_EN 15 -#define NPCX_THR_DCTL_THR_DVAL FIELD(0, 10) - -#define NPCX_ADC_THRESH1 1 -#define NPCX_ADC_THRESH2 2 -#define NPCX_ADC_THRESH3 3 -#define NPCX_ADC_THRESH_CNT 3 +#define NPCX_ATCTL_SCLKDIV_FIELD FIELD(0, 6) +#define NPCX_ATCTL_DLY_FIELD FIELD(8, 3) +#define NPCX_ASCADD_SADDR_FIELD FIELD(0, 5) +#define NPCX_ADCSTS_EOCEV 0 +#define NPCX_ADCCNF_ADCMD_FIELD FIELD(1, 2) +#define NPCX_ADCCNF_ADCRPTC 3 +#define NPCX_ADCCNF_INTECEN 6 +#define NPCX_ADCCNF_START 4 +#define NPCX_ADCCNF_ADCEN 0 +#define NPCX_ADCCNF_STOP 11 +#define NPCX_CHNDAT_CHDAT_FIELD FIELD(0, 10) +#define NPCX_CHNDAT_NEW 15 +#define NPCX_THRCTL_THEN 15 +#define NPCX_THRCTL_L_H 14 +#define NPCX_THRCTL_CHNSEL FIELD(10, 4) +#define NPCX_THRCTL_THRVAL FIELD(0, 10) +#define NPCX_THRCTS_ADC_WKEN 15 +#define NPCX_THRCTS_THR3_IEN 10 +#define NPCX_THRCTS_THR2_IEN 9 +#define NPCX_THRCTS_THR1_IEN 8 +#define NPCX_THRCTS_ADC_EVENT 7 +#define NPCX_THRCTS_THR3_STS 2 +#define NPCX_THRCTS_THR2_STS 1 +#define NPCX_THRCTS_THR1_STS 0 +#define NPCX_THR_DCTL_THRD_EN 15 +#define NPCX_THR_DCTL_THR_DVAL FIELD(0, 10) + +#define NPCX_ADC_THRESH1 1 +#define NPCX_ADC_THRESH2 2 +#define NPCX_ADC_THRESH3 3 +#define NPCX_ADC_THRESH_CNT 3 diff --git a/chip/npcx/registers-npcx9.h b/chip/npcx/registers-npcx9.h index 93236cb977..11cac561d7 100644 --- a/chip/npcx/registers-npcx9.h +++ b/chip/npcx/registers-npcx9.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,149 +19,155 @@ #endif /* NPCX-IRQ numbers */ -#define NPCX_IRQ0_NOUSED NPCX_IRQ_0 -#define NPCX_IRQ1_NOUSED NPCX_IRQ_1 -#define NPCX_IRQ_KBSCAN NPCX_IRQ_2 -#define NPCX_IRQ_PM_CHAN_OBE NPCX_IRQ_3 -#define NPCX_IRQ_PECI NPCX_IRQ_4 -#define NPCX_IRQ_MTC_WKINTD_0 NPCX_IRQ_5 -#define NPCX_IRQ_MTC NPCX_IRQ_MTC_WKINTD_0 -#define NPCX_IRQ_PORT80 NPCX_IRQ_6 -#define NPCX_IRQ_CR_SIN2_WKINTA_0 NPCX_IRQ_7 -#define NPCX_IRQ_SMB8 NPCX_IRQ_8 -#define NPCX_IRQ_MFT_1 NPCX_IRQ_9 -#define NPCX_IRQ_ADC NPCX_IRQ_10 -#define NPCX_IRQ_WKINTE_0 NPCX_IRQ_11 -#define NPCX_IRQ_GDMA NPCX_IRQ_12 -#define NPCX_IRQ_SMB1 NPCX_IRQ_13 -#define NPCX_IRQ_SMB2 NPCX_IRQ_14 -#define NPCX_IRQ_WKINTC_0 NPCX_IRQ_15 -#define NPCX_IRQ_SMB7 NPCX_IRQ_16 -#define NPCX_IRQ_ITIM32_3 NPCX_IRQ_17 -#define NPCX_IRQ_SHI NPCX_IRQ_18 -#define NPCX_IRQ_ESPI NPCX_IRQ_18 -#define NPCX_IRQ_SMB5 NPCX_IRQ_19 -#define NPCX_IRQ_SMB6 NPCX_IRQ_20 -#define NPCX_IRQ_PS2 NPCX_IRQ_21 -#define NPCX_IRQ22_NOUSED NPCX_IRQ_22 -#define NPCX_IRQ_MFT_2 NPCX_IRQ_23 -#define NPCX_IRQ_SHM NPCX_IRQ_24 -#define NPCX_IRQ_KBC_IBF NPCX_IRQ_25 -#define NPCX_IRQ_PM_CHAN_IBF NPCX_IRQ_26 -#define NPCX_IRQ_ITIM32_2 NPCX_IRQ_27 -#define NPCX_IRQ_ITIM32_1 NPCX_IRQ_28 -#define NPCX_I3C_MDMA5 NPCX_IRQ_29 -#define NPCX_IRQ30_NOUSED NPCX_IRQ_30 -#define NPCX_IRQ_TWD_WKINTB_0 NPCX_IRQ_31 -#define NPCX_IRQ_UART2 NPCX_IRQ_32 -#define NPCX_IRQ_UART NPCX_IRQ_33 -#define NPCX_IRQ34_NOUSED NPCX_IRQ_34 -#define NPCX_IRQ_WKINTF_0 NPCX_IRQ_35 -#define NPCX_IRQ_SMB3 NPCX_IRQ_36 -#define NPCX_IRQ_SMB4 NPCX_IRQ_37 -#define NPCX_IRQ_UART3 NPCX_IRQ_38 -#define NPCX_IRQ_UART4 NPCX_IRQ_39 -#define NPCX_IRQ40_NOUSED NPCX_IRQ_40 -#define NPCX_IRQ_MFT_3 NPCX_IRQ_41 -#define NPCX_IRQ_WKINTG_0 NPCX_IRQ_42 -#define NPCX_IRQ_ITIM32_4 NPCX_IRQ_43 -#define NPCX_IRQ_ITIM32_5 NPCX_IRQ_44 -#define NPCX_IRQ_ITIM32_6 NPCX_IRQ_45 -#define NPCX_IRQ_WKINTH_0 NPCX_IRQ_46 -#define NPCX_IRQ_WKINTA_1 NPCX_IRQ_47 -#define NPCX_IRQ_WKINTB_1 NPCX_IRQ_48 -#define NPCX_IRQ_KSI_WKINTC_1 NPCX_IRQ_49 -#define NPCX_IRQ_WKINTD_1 NPCX_IRQ_50 -#define NPCX_IRQ_WKINTE_1 NPCX_IRQ_51 -#define NPCX_IRQ_WKINTF_1 NPCX_IRQ_52 -#define NPCX_IRQ_WKINTG_1 NPCX_IRQ_53 -#define NPCX_IRQ_WKINTH_1 NPCX_IRQ_54 -#define NPCX_WKINTG_2 NPCX_IRQ_55 -#define NPCX_IRQ_KBC_OBE NPCX_IRQ_56 -#define NPCX_IRQ_SPI NPCX_IRQ_57 -#define NPCX_IRQ_ITIM64 NPCX_IRQ_58 -#define NPCX_IRQ_LCT_WKINTF_2 NPCX_IRQ_59 -#define NPCX_IRQ_WKINTA_2 NPCX_IRQ_60 -#define NPCX_IRQ_WKINTB_2 NPCX_IRQ_61 -#define NPCX_IRQ_WKINTC_2 NPCX_IRQ_62 -#define NPCX_IRQ_WKINTD_2 NPCX_IRQ_63 +#define NPCX_IRQ0_NOUSED NPCX_IRQ_0 +#define NPCX_IRQ1_NOUSED NPCX_IRQ_1 +#define NPCX_IRQ_KBSCAN NPCX_IRQ_2 +#define NPCX_IRQ_PM_CHAN_OBE NPCX_IRQ_3 +#define NPCX_IRQ_PECI NPCX_IRQ_4 +#define NPCX_IRQ_MTC_WKINTD_0 NPCX_IRQ_5 +#define NPCX_IRQ_MTC NPCX_IRQ_MTC_WKINTD_0 +#define NPCX_IRQ_PORT80 NPCX_IRQ_6 +#define NPCX_IRQ_CR_SIN2_WKINTA_0 NPCX_IRQ_7 +#define NPCX_IRQ_SMB8 NPCX_IRQ_8 +#define NPCX_IRQ_MFT_1 NPCX_IRQ_9 +#define NPCX_IRQ_ADC NPCX_IRQ_10 +#define NPCX_IRQ_WKINTE_0 NPCX_IRQ_11 +#define NPCX_IRQ_GDMA NPCX_IRQ_12 +#define NPCX_IRQ_SMB1 NPCX_IRQ_13 +#define NPCX_IRQ_SMB2 NPCX_IRQ_14 +#define NPCX_IRQ_WKINTC_0 NPCX_IRQ_15 +#define NPCX_IRQ_SMB7 NPCX_IRQ_16 +#define NPCX_IRQ_ITIM32_3 NPCX_IRQ_17 +#define NPCX_IRQ_SHI NPCX_IRQ_18 +#define NPCX_IRQ_ESPI NPCX_IRQ_18 +#define NPCX_IRQ_SMB5 NPCX_IRQ_19 +#define NPCX_IRQ_SMB6 NPCX_IRQ_20 +#define NPCX_IRQ_PS2 NPCX_IRQ_21 +#define NPCX_IRQ22_NOUSED NPCX_IRQ_22 +#define NPCX_IRQ_MFT_2 NPCX_IRQ_23 +#define NPCX_IRQ_SHM NPCX_IRQ_24 +#define NPCX_IRQ_KBC_IBF NPCX_IRQ_25 +#define NPCX_IRQ_PM_CHAN_IBF NPCX_IRQ_26 +#define NPCX_IRQ_ITIM32_2 NPCX_IRQ_27 +#define NPCX_IRQ_ITIM32_1 NPCX_IRQ_28 +#define NPCX_I3C_MDMA5 NPCX_IRQ_29 +#define NPCX_IRQ30_NOUSED NPCX_IRQ_30 +#define NPCX_IRQ_TWD_WKINTB_0 NPCX_IRQ_31 +#define NPCX_IRQ_UART2 NPCX_IRQ_32 +#define NPCX_IRQ_UART NPCX_IRQ_33 +#define NPCX_IRQ34_NOUSED NPCX_IRQ_34 +#define NPCX_IRQ_WKINTF_0 NPCX_IRQ_35 +#define NPCX_IRQ_SMB3 NPCX_IRQ_36 +#define NPCX_IRQ_SMB4 NPCX_IRQ_37 +#define NPCX_IRQ_UART3 NPCX_IRQ_38 +#define NPCX_IRQ_UART4 NPCX_IRQ_39 +#define NPCX_IRQ40_NOUSED NPCX_IRQ_40 +#define NPCX_IRQ_MFT_3 NPCX_IRQ_41 +#define NPCX_IRQ_WKINTG_0 NPCX_IRQ_42 +#define NPCX_IRQ_ITIM32_4 NPCX_IRQ_43 +#define NPCX_IRQ_ITIM32_5 NPCX_IRQ_44 +#define NPCX_IRQ_ITIM32_6 NPCX_IRQ_45 +#define NPCX_IRQ_WKINTH_0 NPCX_IRQ_46 +#define NPCX_IRQ_WKINTA_1 NPCX_IRQ_47 +#define NPCX_IRQ_WKINTB_1 NPCX_IRQ_48 +#define NPCX_IRQ_KSI_WKINTC_1 NPCX_IRQ_49 +#define NPCX_IRQ_WKINTD_1 NPCX_IRQ_50 +#define NPCX_IRQ_WKINTE_1 NPCX_IRQ_51 +#define NPCX_IRQ_WKINTF_1 NPCX_IRQ_52 +#define NPCX_IRQ_WKINTG_1 NPCX_IRQ_53 +#define NPCX_IRQ_WKINTH_1 NPCX_IRQ_54 +#define NPCX_WKINTG_2 NPCX_IRQ_55 +#define NPCX_IRQ_KBC_OBE NPCX_IRQ_56 +#define NPCX_IRQ_SPI NPCX_IRQ_57 +#define NPCX_IRQ_ITIM64 NPCX_IRQ_58 +#define NPCX_IRQ_LCT_WKINTF_2 NPCX_IRQ_59 +#define NPCX_IRQ_WKINTA_2 NPCX_IRQ_60 +#define NPCX_IRQ_WKINTB_2 NPCX_IRQ_61 +#define NPCX_IRQ_WKINTC_2 NPCX_IRQ_62 +#define NPCX_IRQ_WKINTD_2 NPCX_IRQ_63 /* MIWU definition */ -#define LCT_WUI_GROUP MIWU_GROUP_6 -#define LCT_WUI_MASK MASK_PIN7 +#define LCT_WUI_GROUP MIWU_GROUP_6 +#define LCT_WUI_MASK MASK_PIN7 /* Modules Map */ -#define NPCX_CR_UART_BASE_ADDR(mdl) (0x400E0000 + ((mdl) * 0x2000L)) -#define NPCX_LCT_BASE_ADDR 0x400D7000 -#define NPCX_SMB_BASE_ADDR(mdl) (((mdl) < 2) ? \ - (0x40009000 + ((mdl) * 0x2000L)) : \ - ((mdl) < 4) ? \ - (0x400C0000 + (((mdl) - 2) * 0x2000L)) : \ - ((mdl) == 4) ? \ - (0x40008000) : \ - (0x40017000 + (((mdl) - 5) * 0x1000L))) - -#define NPCX_HFCBCD1 REG8(NPCX_HFCG_BASE_ADDR + 0x012) -#define NPCX_HFCBCD2 REG8(NPCX_HFCG_BASE_ADDR + 0x014) + +/* Miscellaneous Device Control (MDC) registers */ +#define NPCX_FWCTRL REG8(NPCX_MDC_BASE_ADDR + 0x009) + +/* MDC register fields */ +#define NPCX_FWCTRL_RO_REGION 6 +#define NPCX_FWCTRL_FW_SLOT 7 + +#define NPCX_CR_UART_BASE_ADDR(mdl) (0x400E0000 + ((mdl)*0x2000L)) +#define NPCX_LCT_BASE_ADDR 0x400D7000 +#define NPCX_SMB_BASE_ADDR(mdl) \ + (((mdl) < 2) ? (0x40009000 + ((mdl)*0x2000L)) : \ + ((mdl) < 4) ? (0x400C0000 + (((mdl)-2) * 0x2000L)) : \ + ((mdl) == 4) ? (0x40008000) : \ + (0x40017000 + (((mdl)-5) * 0x1000L))) + +#define NPCX_HFCBCD1 REG8(NPCX_HFCG_BASE_ADDR + 0x012) +#define NPCX_HFCBCD2 REG8(NPCX_HFCG_BASE_ADDR + 0x014) enum { - NPCX_UART_PORT0 = 0, /* UART port 0 */ - NPCX_UART_PORT1 = 1, /* UART port 1 */ - NPCX_UART_PORT2 = 2, /* UART port 2 */ - NPCX_UART_PORT3 = 3, /* UART port 3 */ + NPCX_UART_PORT0 = 0, /* UART port 0 */ + NPCX_UART_PORT1 = 1, /* UART port 1 */ + NPCX_UART_PORT2 = 2, /* UART port 2 */ + NPCX_UART_PORT3 = 3, /* UART port 3 */ NPCX_UART_COUNT }; - /* UART registers only used for FIFO mode */ -#define NPCX_UFTSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x020) -#define NPCX_UFRSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x022) -#define NPCX_UFTCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x024) -#define NPCX_UFRCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x026) +/* UART registers only used for FIFO mode */ +#define NPCX_UFTSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x020) +#define NPCX_UFRSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x022) +#define NPCX_UFTCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x024) +#define NPCX_UFRCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x026) /* UART FIFO register fields */ -#define NPCX_UMDSL_FIFO_MD 0 +#define NPCX_UMDSL_FIFO_MD 0 -#define NPCX_UFTSTS_TEMPTY_LVL FIELD(0, 5) -#define NPCX_UFTSTS_TEMPTY_LVL_STS 5 -#define NPCX_UFTSTS_TFIFO_EMPTY_STS 6 -#define NPCX_UFTSTS_NXMIP 7 +#define NPCX_UFTSTS_TEMPTY_LVL FIELD(0, 5) +#define NPCX_UFTSTS_TEMPTY_LVL_STS 5 +#define NPCX_UFTSTS_TFIFO_EMPTY_STS 6 +#define NPCX_UFTSTS_NXMIP 7 -#define NPCX_UFRSTS_RFULL_LVL_STS 5 -#define NPCX_UFRSTS_RFIFO_NEMPTY_STS 6 -#define NPCX_UFRSTS_ERR 7 +#define NPCX_UFRSTS_RFULL_LVL_STS 5 +#define NPCX_UFRSTS_RFIFO_NEMPTY_STS 6 +#define NPCX_UFRSTS_ERR 7 -#define NPCX_UFTCTL_TEMPTY_LVL_SEL FIELD(0, 5) -#define NPCX_UFTCTL_TEMPTY_LVL_EN 5 -#define NPCX_UFTCTL_TEMPTY_EN 6 -#define NPCX_UFTCTL_NXMIPEN 7 +#define NPCX_UFTCTL_TEMPTY_LVL_SEL FIELD(0, 5) +#define NPCX_UFTCTL_TEMPTY_LVL_EN 5 +#define NPCX_UFTCTL_TEMPTY_EN 6 +#define NPCX_UFTCTL_NXMIPEN 7 -#define NPCX_UFRCTL_RFULL_LVL_SEL FIELD(0, 5) -#define NPCX_UFRCTL_RFULL_LVL_EN 5 -#define NPCX_UFRCTL_RNEMPTY_EN 6 -#define NPCX_UFRCTL_ERR_EN 7 +#define NPCX_UFRCTL_RFULL_LVL_SEL FIELD(0, 5) +#define NPCX_UFRCTL_RFULL_LVL_EN 5 +#define NPCX_UFRCTL_RNEMPTY_EN 6 +#define NPCX_UFRCTL_ERR_EN 7 /* KBSCAN register fields */ -#define NPCX_KBHDRV_FIELD FIELD(6, 2) +#define NPCX_KBHDRV_FIELD FIELD(6, 2) /* GLUE registers */ -#define NPCX_GLUE_PSL_CTS REG8(NPCX_GLUE_REGS_BASE + 0x027) -#define NPCX_GLUE_PSL_MCTL1 REG8(NPCX_GLUE_REGS_BASE + 0x034) -#define NPCX_GLUE_PSL_MCTL2 REG8(NPCX_GLUE_REGS_BASE + 0x038) +#define NPCX_GLUE_PSL_CTS REG8(NPCX_GLUE_REGS_BASE + 0x027) +#define NPCX_GLUE_PSL_MCTL1 REG8(NPCX_GLUE_REGS_BASE + 0x034) +#define NPCX_GLUE_PSL_MCTL2 REG8(NPCX_GLUE_REGS_BASE + 0x038) /* PSL register fields */ -#define NPCX_GLUE_PSL_MCTL1_VCC1_RST_PSL 7 -#define NPCX_GLUE_PSL_MCTL1_PSL_GPO_CTL 6 -#define NPCX_GLUE_PSL_MCTL1_LCT_EV 4 -#define NPCX_GLUE_PSL_MCTL1_VCC1_RST_EV 3 -#define NPCX_GLUE_PSL_MCTL1_PLS_EN 1 -#define NPCX_GLUE_PSL_MCTL1_OD_EN 0 - -#define NPCX_GLUE_PSL_MCTL2_VCC1_RST_PSL_LK 7 -#define NPCX_GLUE_PSL_MCTL2_PSL_GP_EN 6 -#define NPCX_GLUE_PSL_MCTL2_AC_IN_BLOCK_EN 3 -#define NPCX_GLUE_PSL_MCTL2_AC_IN_SEL FIELD(0, 1) +#define NPCX_GLUE_PSL_MCTL1_VCC1_RST_PSL 7 +#define NPCX_GLUE_PSL_MCTL1_PSL_GPO_CTL 6 +#define NPCX_GLUE_PSL_MCTL1_LCT_EV 4 +#define NPCX_GLUE_PSL_MCTL1_VCC1_RST_EV 3 +#define NPCX_GLUE_PSL_MCTL1_PLS_EN 1 +#define NPCX_GLUE_PSL_MCTL1_OD_EN 0 + +#define NPCX_GLUE_PSL_MCTL2_VCC1_RST_PSL_LK 7 +#define NPCX_GLUE_PSL_MCTL2_PSL_GP_EN 6 +#define NPCX_GLUE_PSL_MCTL2_AC_IN_BLOCK_EN 3 +#define NPCX_GLUE_PSL_MCTL2_AC_IN_SEL FIELD(0, 1) /* GPIO registers */ -#define NPCX_PLOCK_CTL(n) REG8(NPCX_GPIO_BASE_ADDR(n) + 0x007) +#define NPCX_PLOCK_CTL(n) REG8(NPCX_GPIO_BASE_ADDR(n) + 0x007) /* System Configuration (SCFG) Registers */ @@ -189,99 +195,105 @@ enum { ALT_GROUP_COUNT }; -#define NPCX_DEVALT(n) REG8(NPCX_SCFG_BASE_ADDR + 0x010 + (n)) +#define NPCX_DEVALT(n) REG8(NPCX_SCFG_BASE_ADDR + 0x010 + (n)) -#define NPCX_LV_GPIO_CTL_ADDR(n) (((n) < 5) ? \ - (NPCX_SCFG_BASE_ADDR + 0x02A + (n)) :\ - (NPCX_SCFG_BASE_ADDR + 0x026)) -#define NPCX_LV_GPIO_CTL(n) REG8(NPCX_LV_GPIO_CTL_ADDR(n)) +#define NPCX_LV_GPIO_CTL_ADDR(n) \ + (((n) < 5) ? (NPCX_SCFG_BASE_ADDR + 0x02A + (n)) : \ + (NPCX_SCFG_BASE_ADDR + 0x026)) +#define NPCX_LV_GPIO_CTL(n) REG8(NPCX_LV_GPIO_CTL_ADDR(n)) /* Device Alternate Function Lock */ -#define NPCX_DEVALT_LK(n) REG8(NPCX_SCFG_BASE_ADDR + 0x210 + (n)) +#define NPCX_DEVALT_LK(n) REG8(NPCX_SCFG_BASE_ADDR + 0x210 + (n)) /* pin-mux for I2C */ -#define NPCX_DEVALT2_I2C0_0_SL 0 -#define NPCX_DEVALT2_I2C7_0_SL 1 -#define NPCX_DEVALT2_I2C1_0_SL 2 -#define NPCX_DEVALT2_I2C6_0_SL 3 -#define NPCX_DEVALT2_I2C2_0_SL 4 -#define NPCX_DEVALT2_I2C5_0_SL 5 -#define NPCX_DEVALT2_I2C3_0_SL 6 -#define NPCX_DEVALT6_I2C6_1_SL 5 -#define NPCX_DEVALT6_I2C5_1_SL 6 -#define NPCX_DEVALT6_I2C4_1_SL 7 +#define NPCX_DEVALT2_I2C0_0_SL 0 +#define NPCX_DEVALT2_I2C7_0_SL 1 +#define NPCX_DEVALT2_I2C1_0_SL 2 +#define NPCX_DEVALT2_I2C6_0_SL 3 +#define NPCX_DEVALT2_I2C2_0_SL 4 +#define NPCX_DEVALT2_I2C5_0_SL 5 +#define NPCX_DEVALT2_I2C3_0_SL 6 +#define NPCX_DEVALT6_I2C6_1_SL 5 +#define NPCX_DEVALT6_I2C5_1_SL 6 +#define NPCX_DEVALT6_I2C4_1_SL 7 /* pin-mux for ADC */ -#define NPCX_DEVALTF_ADC5_SL 0 -#define NPCX_DEVALTF_ADC6_SL 1 -#define NPCX_DEVALTF_ADC7_SL 2 -#define NPCX_DEVALTF_ADC8_SL 3 -#define NPCX_DEVALTF_ADC9_SL 4 -#define NPCX_DEVALTF_ADC10_SL 5 -#define NPCX_DEVALTF_ADC11_SL 6 +#define NPCX_DEVALTF_ADC5_SL 0 +#define NPCX_DEVALTF_ADC6_SL 1 +#define NPCX_DEVALTF_ADC7_SL 2 +#define NPCX_DEVALTF_ADC8_SL 3 +#define NPCX_DEVALTF_ADC9_SL 4 +#define NPCX_DEVALTF_ADC10_SL 5 +#define NPCX_DEVALTF_ADC11_SL 6 /* pin-mux for PSL */ -#define NPCX_DEVALTD_PSL_IN1_AHI 0 -#define NPCX_DEVALTD_NPSL_IN1_SL 1 -#define NPCX_DEVALTD_PSL_IN2_AHI 2 -#define NPCX_DEVALTD_NPSL_IN2_SL 3 -#define NPCX_DEVALTD_PSL_IN3_AHI 4 -#define NPCX_DEVALTD_PSL_IN3_SL 5 -#define NPCX_DEVALTD_PSL_IN4_AHI 6 -#define NPCX_DEVALTD_PSL_IN4_SL 7 +#define NPCX_DEVALTD_PSL_IN1_AHI 0 +#define NPCX_DEVALTD_NPSL_IN1_SL 1 +#define NPCX_DEVALTD_PSL_IN2_AHI 2 +#define NPCX_DEVALTD_NPSL_IN2_SL 3 +#define NPCX_DEVALTD_PSL_IN3_AHI 4 +#define NPCX_DEVALTD_PSL_IN3_SL 5 +#define NPCX_DEVALTD_PSL_IN4_AHI 6 +#define NPCX_DEVALTD_PSL_IN4_SL 7 /* pin-mux for Misc. */ /* pin-mux for UART */ -#define NPCX_DEVALTJ_CR_SIN1_SL1 0 -#define NPCX_DEVALTJ_CR_SOUT1_SL1 1 -#define NPCX_DEVALTJ_CR_SIN1_SL2 2 -#define NPCX_DEVALTJ_CR_SOUT1_SL2 3 -#define NPCX_DEVALTJ_CR_SIN2_SL 4 -#define NPCX_DEVALTJ_CR_SOUT2_SL 5 -#define NPCX_DEVALTJ_CR_SIN3_SL 6 -#define NPCX_DEVALTJ_CR_SOUT3_SL 7 -#define NPCX_DEVALTE_CR_SIN4_SL 6 -#define NPCX_DEVALTE_CR_SOUT4_SL 7 +#define NPCX_DEVALTJ_CR_SIN1_SL1 0 +#define NPCX_DEVALTJ_CR_SOUT1_SL1 1 +#define NPCX_DEVALTJ_CR_SIN1_SL2 2 +#define NPCX_DEVALTJ_CR_SOUT1_SL2 3 +#define NPCX_DEVALTJ_CR_SIN2_SL 4 +#define NPCX_DEVALTJ_CR_SOUT2_SL 5 +#define NPCX_DEVALTJ_CR_SIN3_SL 6 +#define NPCX_DEVALTJ_CR_SOUT3_SL 7 +#define NPCX_DEVALTE_CR_SIN4_SL 6 +#define NPCX_DEVALTE_CR_SOUT4_SL 7 /* SHI module version 2 enable bit */ -#define NPCX_DEVALTF_SHI_NEW 7 +#define NPCX_DEVALTF_SHI_NEW 7 /* VCC_RST Pull-Up Disable */ -#define NPCX_DEVALTG_VCC1_RST_PUD 5 -#define NPCX_DEVALTG_PSL_OUT_SL 6 -#define NPCX_DEVALTG_PSL_GPO_SL 7 +#define NPCX_DEVALTG_VCC1_RST_PUD 5 +#define NPCX_DEVALTG_PSL_OUT_SL 6 +#define NPCX_DEVALTG_PSL_GPO_SL 7 /* SMBus register fields */ -#define NPCX_SMBSEL_SMB4SEL 4 -#define NPCX_SMBSEL_SMB5SEL 5 -#define NPCX_SMBSEL_SMB6SEL 6 +#define NPCX_SMBSEL_SMB4SEL 4 +#define NPCX_SMBSEL_SMB5SEL 5 +#define NPCX_SMBSEL_SMB6SEL 6 + +/* pin-mux for JTAG */ +#define NPCX_JEN_CTL1 REG8(NPCX_SCFG_BASE_ADDR + 0x120) +#define NPCX_JEN_CTL1_JEN_EN_FIELD FIELD(0, 4) +#define NPCX_JEN_CTL1_JEN_EN_DIS 0x06 +#define NPCX_JEN_CTL1_JEN_EN_ENA 0x09 /* SMB enumeration: I2C port definitions. */ enum { - NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0 */ - NPCX_I2C_PORT1_0, /* I2C port 1, bus 0 */ - NPCX_I2C_PORT2_0, /* I2C port 2, bus 0 */ - NPCX_I2C_PORT3_0, /* I2C port 3, bus 0 */ - NPCX_I2C_PORT4_1, /* I2C port 4, bus 1 */ - NPCX_I2C_PORT5_0, /* I2C port 5, bus 0 */ - NPCX_I2C_PORT5_1, /* I2C port 5, bus 1 */ - NPCX_I2C_PORT6_0, /* I2C port 6, bus 0 */ - NPCX_I2C_PORT6_1, /* I2C port 6, bus 1 */ - NPCX_I2C_PORT7_0, /* I2C port 7, bus 0 */ + NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0 */ + NPCX_I2C_PORT1_0, /* I2C port 1, bus 0 */ + NPCX_I2C_PORT2_0, /* I2C port 2, bus 0 */ + NPCX_I2C_PORT3_0, /* I2C port 3, bus 0 */ + NPCX_I2C_PORT4_1, /* I2C port 4, bus 1 */ + NPCX_I2C_PORT5_0, /* I2C port 5, bus 0 */ + NPCX_I2C_PORT5_1, /* I2C port 5, bus 1 */ + NPCX_I2C_PORT6_0, /* I2C port 6, bus 0 */ + NPCX_I2C_PORT6_1, /* I2C port 6, bus 1 */ + NPCX_I2C_PORT7_0, /* I2C port 7, bus 0 */ NPCX_I2C_COUNT, }; /* Power Management Controller (PMC) Registers */ -#define NPCX_FMUL_WIN_DLY REG8(NPCX_PMC_BASE_ADDR + 0x010) -#define NPCX_RAM_PD(offset) REG8(NPCX_PMC_BASE_ADDR + 0x020 + (offset)) +#define NPCX_FMUL_WIN_DLY REG8(NPCX_PMC_BASE_ADDR + 0x010) +#define NPCX_RAM_PD(offset) REG8(NPCX_PMC_BASE_ADDR + 0x020 + (offset)) /* PMC register fields */ -#define NPCX_PWDWN_CTL3_SMB4_PD 4 -#define NPCX_PWDWN_CTL7_SMB5_PD 0 -#define NPCX_PWDWN_CTL7_SMB6_PD 1 -#define NPCX_PWDWN_CTL7_SMB7_PD 2 -#define NPCX_PWDWN_CTL7_ITIM64_PD 5 -#define NPCX_PWDWN_CTL7_UART2_PD 6 +#define NPCX_PWDWN_CTL3_SMB4_PD 4 +#define NPCX_PWDWN_CTL7_SMB5_PD 0 +#define NPCX_PWDWN_CTL7_SMB6_PD 1 +#define NPCX_PWDWN_CTL7_SMB7_PD 2 +#define NPCX_PWDWN_CTL7_ITIM64_PD 5 +#define NPCX_PWDWN_CTL7_UART2_PD 6 /* * PMC enumeration: @@ -313,41 +325,41 @@ enum NPCX_PMC_PWDWN_CTL_T { NPCX_PMC_PWDWN_5 = 4, NPCX_PMC_PWDWN_6 = 5, NPCX_PMC_PWDWN_7 = 6, + NPCX_PMC_PWDWN_8 = 7, NPCX_PMC_PWDWN_CNT, }; -#define CGC_I2C_MASK (BIT(NPCX_PWDWN_CTL3_SMB0_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB1_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB2_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB3_PD) | \ - BIT(NPCX_PWDWN_CTL3_SMB4_PD)) -#define CGC_I2C_MASK2 (BIT(NPCX_PWDWN_CTL7_SMB5_PD) | \ - BIT(NPCX_PWDWN_CTL7_SMB6_PD) | \ - BIT(NPCX_PWDWN_CTL7_SMB7_PD)) -#define CGC_UART2_MASK BIT(NPCX_PWDWN_CTL7_UART2_PD) +#define CGC_I2C_MASK \ + (BIT(NPCX_PWDWN_CTL3_SMB0_PD) | BIT(NPCX_PWDWN_CTL3_SMB1_PD) | \ + BIT(NPCX_PWDWN_CTL3_SMB2_PD) | BIT(NPCX_PWDWN_CTL3_SMB3_PD) | \ + BIT(NPCX_PWDWN_CTL3_SMB4_PD)) +#define CGC_I2C_MASK2 \ + (BIT(NPCX_PWDWN_CTL7_SMB5_PD) | BIT(NPCX_PWDWN_CTL7_SMB6_PD) | \ + BIT(NPCX_PWDWN_CTL7_SMB7_PD)) +#define CGC_UART2_MASK BIT(NPCX_PWDWN_CTL7_UART2_PD) /* BBRAM register fields */ -#define NPCX_BKUP_STS_VSBY_STS 1 -#define NPCX_BKUP_STS_VCC1_STS 0 -#define NPCX_BKUP_STS_ALL_MASK \ +#define NPCX_BKUP_STS_VSBY_STS 1 +#define NPCX_BKUP_STS_VCC1_STS 0 +#define NPCX_BKUP_STS_ALL_MASK \ (BIT(NPCX_BKUP_STS_IBBR) | BIT(NPCX_BKUP_STS_VSBY_STS) | \ - BIT(NPCX_BKUP_STS_VCC1_STS)) -#define NPCX_BBRAM_SIZE 128 /* Size of BBRAM */ + BIT(NPCX_BKUP_STS_VCC1_STS)) +#define NPCX_BBRAM_SIZE 128 /* Size of BBRAM */ /* ITIM registers */ -#define NPCX_ITCNT32(n) REG32(NPCX_ITIM_BASE_ADDR(n) + 0x008) +#define NPCX_ITCNT32(n) REG32(NPCX_ITIM_BASE_ADDR(n) + 0x008) /* Timer counter register used for 1 micro-second system tick */ -#define NPCX_ITCNT_SYSTEM NPCX_ITCNT32(ITIM32_6) +#define NPCX_ITCNT_SYSTEM NPCX_ITCNT32(ITIM32_6) /* Timer counter register used for others */ -#define NPCX_ITCNT NPCX_ITCNT32 +#define NPCX_ITCNT NPCX_ITCNT32 /* ITIM module No. used for event */ -#define ITIM_EVENT_NO ITIM32_1 +#define ITIM_EVENT_NO ITIM32_1 /* ITIM module No. used for watchdog */ -#define ITIM_WDG_NO ITIM32_5 +#define ITIM_WDG_NO ITIM32_5 /* ITIM module No. used for 1 micro-second system tick */ -#define ITIM_SYSTEM_NO ITIM32_6 +#define ITIM_SYSTEM_NO ITIM32_6 /* ITIM enumeration */ enum ITIM_MODULE_T { @@ -361,56 +373,56 @@ enum ITIM_MODULE_T { }; /* Serial Host Interface (SHI) Registers - only available on SHI Version 2 */ -#define NPCX_SHICFG3 REG8(NPCX_SHI_BASE_ADDR + 0x00C) -#define NPCX_SHICFG4 REG8(NPCX_SHI_BASE_ADDR + 0x00D) -#define NPCX_SHICFG5 REG8(NPCX_SHI_BASE_ADDR + 0x00E) -#define NPCX_EVSTAT2 REG8(NPCX_SHI_BASE_ADDR + 0x00F) -#define NPCX_EVENABLE2 REG8(NPCX_SHI_BASE_ADDR + 0x010) -#define NPCX_OBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x020 + (n)) -#define NPCX_IBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x0A0 + (n)) +#define NPCX_SHICFG3 REG8(NPCX_SHI_BASE_ADDR + 0x00C) +#define NPCX_SHICFG4 REG8(NPCX_SHI_BASE_ADDR + 0x00D) +#define NPCX_SHICFG5 REG8(NPCX_SHI_BASE_ADDR + 0x00E) +#define NPCX_EVSTAT2 REG8(NPCX_SHI_BASE_ADDR + 0x00F) +#define NPCX_EVENABLE2 REG8(NPCX_SHI_BASE_ADDR + 0x010) +#define NPCX_OBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x020 + (n)) +#define NPCX_IBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x0A0 + (n)) /* SHI register fields */ -#define NPCX_SHICFG3_OBUFLVLDIS 7 -#define NPCX_SHICFG4_IBUFLVLDIS 7 -#define NPCX_SHICFG5_IBUFLVL2 FIELD(0, 6) -#define NPCX_SHICFG5_IBUFLVL2DIS 7 -#define NPCX_EVSTAT2_IBHF2 0 -#define NPCX_EVSTAT2_CSNRE 1 -#define NPCX_EVSTAT2_CSNFE 2 -#define NPCX_EVENABLE2_IBHF2EN 0 -#define NPCX_EVENABLE2_CSNREEN 1 -#define NPCX_EVENABLE2_CSNFEEN 2 +#define NPCX_SHICFG3_OBUFLVLDIS 7 +#define NPCX_SHICFG4_IBUFLVLDIS 7 +#define NPCX_SHICFG5_IBUFLVL2 FIELD(0, 6) +#define NPCX_SHICFG5_IBUFLVL2DIS 7 +#define NPCX_EVSTAT2_IBHF2 0 +#define NPCX_EVSTAT2_CSNRE 1 +#define NPCX_EVSTAT2_CSNFE 2 +#define NPCX_EVENABLE2_IBHF2EN 0 +#define NPCX_EVENABLE2_CSNREEN 1 +#define NPCX_EVENABLE2_CSNFEEN 2 /* eSPI register fields */ -#define NPCX_ESPIIE_BMTXDONEIE 19 -#define NPCX_ESPIIE_PBMRXIE 20 -#define NPCX_ESPIIE_PMSGRXIE 21 -#define NPCX_ESPIIE_BMBURSTERRIE 22 -#define NPCX_ESPIIE_BMBURSTDONEIE 23 - -#define NPCX_ESPIWE_PBMRXWE 20 -#define NPCX_ESPIWE_PMSGRXWE 21 - -#define NPCX_ESPISTS_VWUPDW 17 -#define NPCX_ESPISTS_BMTXDONE 19 -#define NPCX_ESPISTS_PBMRX 20 -#define NPCX_ESPISTS_PMSGRX 21 -#define NPCX_ESPISTS_BMBURSTERR 22 -#define NPCX_ESPISTS_BMBURSTDONE 23 -#define NPCX_ESPISTS_ESPIRST_LVL 24 - -#define ESPIIE_BMTXDONE BIT(NPCX_ESPIIE_BMTXDONEIE) -#define ESPIIE_PBMRX BIT(NPCX_ESPIIE_PBMRXIE) -#define ESPIIE_PMSGRX BIT(NPCX_ESPIIE_PMSGRXIE) -#define ESPIIE_BMBURSTERR BIT(NPCX_ESPIIE_BMBURSTERRIE) -#define ESPIIE_BMBURSTDONE BIT(NPCX_ESPIIE_BMBURSTDONEIE) - -#define ESPIWE_PBMRX BIT(NPCX_ESPIWE_PBMRXWE) -#define ESPIWE_PMSGRX BIT(NPCX_ESPIWE_PMSGRXWE) +#define NPCX_ESPIIE_BMTXDONEIE 19 +#define NPCX_ESPIIE_PBMRXIE 20 +#define NPCX_ESPIIE_PMSGRXIE 21 +#define NPCX_ESPIIE_BMBURSTERRIE 22 +#define NPCX_ESPIIE_BMBURSTDONEIE 23 + +#define NPCX_ESPIWE_PBMRXWE 20 +#define NPCX_ESPIWE_PMSGRXWE 21 + +#define NPCX_ESPISTS_VWUPDW 17 +#define NPCX_ESPISTS_BMTXDONE 19 +#define NPCX_ESPISTS_PBMRX 20 +#define NPCX_ESPISTS_PMSGRX 21 +#define NPCX_ESPISTS_BMBURSTERR 22 +#define NPCX_ESPISTS_BMBURSTDONE 23 +#define NPCX_ESPISTS_ESPIRST_LVL 24 + +#define ESPIIE_BMTXDONE BIT(NPCX_ESPIIE_BMTXDONEIE) +#define ESPIIE_PBMRX BIT(NPCX_ESPIIE_PBMRXIE) +#define ESPIIE_PMSGRX BIT(NPCX_ESPIIE_PMSGRXIE) +#define ESPIIE_BMBURSTERR BIT(NPCX_ESPIIE_BMBURSTERRIE) +#define ESPIIE_BMBURSTDONE BIT(NPCX_ESPIIE_BMBURSTDONEIE) + +#define ESPIWE_PBMRX BIT(NPCX_ESPIWE_PBMRXWE) +#define ESPIWE_PMSGRX BIT(NPCX_ESPIWE_PMSGRXWE) /* Bit field manipulation for VWEVMS Value */ -#define VWEVMS_WK_EN(e) (((e)<<20) & 0x00100000) -#define VWEVMS_INTWK_EN(e) (VWEVMS_INT_EN(e) | VWEVMS_WK_EN(e)) +#define VWEVMS_WK_EN(e) (((e) << 20) & 0x00100000) +#define VWEVMS_INTWK_EN(e) (VWEVMS_INT_EN(e) | VWEVMS_WK_EN(e)) /* eSPI max supported frequency */ enum { @@ -418,66 +430,71 @@ enum { NPCX_ESPI_MAXFREQ_25 = 1, NPCX_ESPI_MAXFREQ_33 = 2, NPCX_ESPI_MAXFREQ_50 = 3, + NPCX_ESPI_MAXFREQ_66 = 4, NPCX_ESPI_MAXFREQ_NONE = 0xFF }; +/* eSPI Operating Frequency */ +enum { + NPCX_ESPI_OPFREQ_20 = 0, + NPCX_ESPI_OPFREQ_25 = 1, + NPCX_ESPI_OPFREQ_33 = 2, + NPCX_ESPI_OPFREQ_50 = 3, + NPCX_ESPI_OPFREQ_66 = 4, + NPCX_ESPI_OPFREQ_NONE = 0xFF +}; + /* eSPI max frequency support per FMCLK */ #if (FMCLK <= 33000000) -#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_33 +#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_33 #else -#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_50 +#define NPCX_ESPI_MAXFREQ_MAX NPCX_ESPI_MAXFREQ_50 #endif /* UART registers */ -#define NPCX_UART_WK_GROUP MIWU_GROUP_8 -#define NPCX_UART_WK_BIT 7 -#define NPCX_UART2_WK_GROUP MIWU_GROUP_1 -#define NPCX_UART2_WK_BIT 6 +#define NPCX_UART_WK_GROUP MIWU_GROUP_8 +#define NPCX_UART_WK_BIT 7 +#define NPCX_UART2_WK_GROUP MIWU_GROUP_1 +#define NPCX_UART2_WK_BIT 6 /* MIWU registers */ -#define NPCX_WKEDG_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x00 + \ - ((n) * 0x10)) -#define NPCX_WKAEDG_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x01 + \ - ((n) * 0x10)) -#define NPCX_WKMOD_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x02 + \ - ((n) * 0x10)) -#define NPCX_WKPND_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x03 + \ - ((n) * 0x10)) -#define NPCX_WKPCL_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x04 + \ - ((n) * 0x10)) -#define NPCX_WKEN_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x05 + \ - ((n) * 0x10)) -#define NPCX_WKST_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x06 + \ - ((n) * 0x10)) -#define NPCX_WKINEN_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x07 + \ - ((n) * 0x10)) - -#define NPCX_WKEDG(port, n) REG8(NPCX_WKEDG_ADDR(port, n)) -#define NPCX_WKAEDG(port, n) REG8(NPCX_WKAEDG_ADDR(port, n)) -#define NPCX_WKPND(port, n) REG8(NPCX_WKPND_ADDR(port, n)) -#define NPCX_WKPCL(port, n) REG8(NPCX_WKPCL_ADDR(port, n)) -#define NPCX_WKEN(port, n) REG8(NPCX_WKEN_ADDR(port, n)) -#define NPCX_WKST(port, n) REG8(NPCX_WKST_ADDR(port, n)) -#define NPCX_WKINEN(port, n) REG8(NPCX_WKINEN_ADDR(port, n)) -#define NPCX_WKMOD(port, n) REG8(NPCX_WKMOD_ADDR(port, n)) +#define NPCX_WKEDG_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x00 + ((n)*0x10)) +#define NPCX_WKAEDG_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x01 + ((n)*0x10)) +#define NPCX_WKMOD_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x02 + ((n)*0x10)) +#define NPCX_WKPND_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x03 + ((n)*0x10)) +#define NPCX_WKPCL_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x04 + ((n)*0x10)) +#define NPCX_WKEN_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x05 + ((n)*0x10)) +#define NPCX_WKST_ADDR(port, n) (NPCX_MIWU_BASE_ADDR(port) + 0x06 + ((n)*0x10)) +#define NPCX_WKINEN_ADDR(port, n) \ + (NPCX_MIWU_BASE_ADDR(port) + 0x07 + ((n)*0x10)) + +#define NPCX_WKEDG(port, n) REG8(NPCX_WKEDG_ADDR(port, n)) +#define NPCX_WKAEDG(port, n) REG8(NPCX_WKAEDG_ADDR(port, n)) +#define NPCX_WKPND(port, n) REG8(NPCX_WKPND_ADDR(port, n)) +#define NPCX_WKPCL(port, n) REG8(NPCX_WKPCL_ADDR(port, n)) +#define NPCX_WKEN(port, n) REG8(NPCX_WKEN_ADDR(port, n)) +#define NPCX_WKST(port, n) REG8(NPCX_WKST_ADDR(port, n)) +#define NPCX_WKINEN(port, n) REG8(NPCX_WKINEN_ADDR(port, n)) +#define NPCX_WKMOD(port, n) REG8(NPCX_WKMOD_ADDR(port, n)) /* LCT register */ -#define NPCX_LCTCONT REG8(NPCX_LCT_BASE_ADDR + 0x002) -#define NPCX_LCTSTAT REG8(NPCX_LCT_BASE_ADDR + 0x004) -#define NPCX_LCTSECOND REG8(NPCX_LCT_BASE_ADDR + 0x005) -#define NPCX_LCTMINUTE REG8(NPCX_LCT_BASE_ADDR + 0x006) -#define NPCX_LCTHOUR REG8(NPCX_LCT_BASE_ADDR + 0x008) -#define NPCX_LCTDAY REG8(NPCX_LCT_BASE_ADDR + 0x00A) -#define NPCX_LCTWEEK REG8(NPCX_LCT_BASE_ADDR + 0x00C) +#define NPCX_LCTCONT REG8(NPCX_LCT_BASE_ADDR + 0x002) +#define NPCX_LCTSTAT REG8(NPCX_LCT_BASE_ADDR + 0x004) +#define NPCX_LCTSECOND REG8(NPCX_LCT_BASE_ADDR + 0x005) +#define NPCX_LCTMINUTE REG8(NPCX_LCT_BASE_ADDR + 0x006) +#define NPCX_LCTHOUR REG8(NPCX_LCT_BASE_ADDR + 0x008) +#define NPCX_LCTDAY REG8(NPCX_LCT_BASE_ADDR + 0x00A) +#define NPCX_LCTWEEK REG8(NPCX_LCT_BASE_ADDR + 0x00C) /* LCTCONT fields */ -#define NPCX_LCTCONT_EN 0 -#define NPCX_LCTCONT_EN_FIELD FIELD(0, 1) -#define NPCX_LCTCONT_EVEN 1 -#define NPCX_LCTCONT_PSL_EN 2 -#define NPCX_LCTCONT_CLK_EN 6 -#define NPCX_LCTCONT_VSBY_PWR 7 +#define NPCX_LCTCONT_EN 0 +#define NPCX_LCTCONT_EN_FIELD FIELD(0, 1) +#define NPCX_LCTCONT_EVEN 1 +#define NPCX_LCTCONT_PSL_EN 2 +#define NPCX_LCTCONT_CLK_EN 6 +#define NPCX_LCTCONT_VSBY_PWR 7 /* LCTSTAT fields */ -#define NPCX_LCTSTAT_EVST 0 +#define NPCX_LCTSTAT_EVST 0 /* UART registers and functions */ #if NPCX_UART_MODULE2 @@ -486,73 +503,73 @@ enum { * always 1 == MIWU_TABLE_1. */ #define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTG_1 -#define NPCX_UART_DEVALT NPCX_DEVALT(ALT_GROUP_J) -#define NPCX_UART_DEVALT_SIN_SL NPCX_DEVALTJ_CR_SIN1_SL2 -#define NPCX_UART_DEVALT_SOUT_SL NPCX_DEVALTJ_CR_SOUT1_SL2 -#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(ALT_GROUP_J) -#define NPCX_UART_ALT_DEVALT_SIN_SL NPCX_DEVALTJ_CR_SIN1_SL1 -#define NPCX_UART_ALT_DEVALT_SOUT_SL NPCX_DEVALTJ_CR_SOUT1_SL1 +#define NPCX_UART_DEVALT NPCX_DEVALT(ALT_GROUP_J) +#define NPCX_UART_DEVALT_SIN_SL NPCX_DEVALTJ_CR_SIN1_SL2 +#define NPCX_UART_DEVALT_SOUT_SL NPCX_DEVALTJ_CR_SOUT1_SL2 +#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(ALT_GROUP_J) +#define NPCX_UART_ALT_DEVALT_SIN_SL NPCX_DEVALTJ_CR_SIN1_SL1 +#define NPCX_UART_ALT_DEVALT_SOUT_SL NPCX_DEVALTJ_CR_SOUT1_SL1 #else /* !NPCX_UART_MODULE2 */ -#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTB_1 -#define NPCX_UART_DEVALT NPCX_DEVALT(ALT_GROUP_J) -#define NPCX_UART_DEVALT_SIN_SL NPCX_DEVALTJ_CR_SIN1_SL1 -#define NPCX_UART_DEVALT_SOUT_SL NPCX_DEVALTJ_CR_SOUT1_SL1 -#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(ALT_GROUP_J) -#define NPCX_UART_ALT_DEVALT_SIN_SL NPCX_DEVALTJ_CR_SIN1_SL2 -#define NPCX_UART_ALT_DEVALT_SOUT_SL NPCX_DEVALTJ_CR_SOUT1_SL2 +#define NPCX_UART_MIWU_IRQ NPCX_IRQ_WKINTB_1 +#define NPCX_UART_DEVALT NPCX_DEVALT(ALT_GROUP_J) +#define NPCX_UART_DEVALT_SIN_SL NPCX_DEVALTJ_CR_SIN1_SL1 +#define NPCX_UART_DEVALT_SOUT_SL NPCX_DEVALTJ_CR_SOUT1_SL1 +#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(ALT_GROUP_J) +#define NPCX_UART_ALT_DEVALT_SIN_SL NPCX_DEVALTJ_CR_SIN1_SL2 +#define NPCX_UART_ALT_DEVALT_SOUT_SL NPCX_DEVALTJ_CR_SOUT1_SL2 #endif /* NPCX_UART_MODULE2 */ /* ADC register */ -#define NPCX_ADCSTS REG16(NPCX_ADC_BASE_ADDR + 0x000) -#define NPCX_ADCCNF REG16(NPCX_ADC_BASE_ADDR + 0x002) -#define NPCX_ATCTL REG16(NPCX_ADC_BASE_ADDR + 0x004) -#define NPCX_ASCADD REG16(NPCX_ADC_BASE_ADDR + 0x006) -#define NPCX_ADCCS REG16(NPCX_ADC_BASE_ADDR + 0x008) -#define NPCX_THRCTS REG16(NPCX_ADC_BASE_ADDR + 0x01A) -#define NPCX_ADCCNF2 REG16(NPCX_ADC_BASE_ADDR + 0x020) -#define NPCX_GENDLY REG16(NPCX_ADC_BASE_ADDR + 0x022) -#define NPCX_MEAST REG16(NPCX_ADC_BASE_ADDR + 0x026) +#define NPCX_ADCSTS REG16(NPCX_ADC_BASE_ADDR + 0x000) +#define NPCX_ADCCNF REG16(NPCX_ADC_BASE_ADDR + 0x002) +#define NPCX_ATCTL REG16(NPCX_ADC_BASE_ADDR + 0x004) +#define NPCX_ASCADD REG16(NPCX_ADC_BASE_ADDR + 0x006) +#define NPCX_ADCCS REG16(NPCX_ADC_BASE_ADDR + 0x008) +#define NPCX_THRCTS REG16(NPCX_ADC_BASE_ADDR + 0x01A) +#define NPCX_ADCCNF2 REG16(NPCX_ADC_BASE_ADDR + 0x020) +#define NPCX_GENDLY REG16(NPCX_ADC_BASE_ADDR + 0x022) +#define NPCX_MEAST REG16(NPCX_ADC_BASE_ADDR + 0x026) /* NOTE: This is 0-based for the ADC channels. */ -#define NPCX_CHNDAT(n) REG16(NPCX_ADC_BASE_ADDR + 0x040 + (2L*(n))) +#define NPCX_CHNDAT(n) REG16(NPCX_ADC_BASE_ADDR + 0x040 + (2L * (n))) /* NOTE: These are 1-based for the threshold detectors. */ -#define NPCX_THRCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x05E + (2L*(n))) +#define NPCX_THRCTL(n) REG16(NPCX_ADC_BASE_ADDR + 0x05E + (2L * (n))) /* ADC register fields */ -#define NPCX_ADCSTS_EOCEV 0 -#define NPCX_ADCCNF_ADCMD_FIELD FIELD(1, 2) -#define NPCX_ADCCNF_ADCRPTC 3 -#define NPCX_ADCCNF_INTECEN 6 -#define NPCX_ADCCNF_START 4 -#define NPCX_ADCCNF_ADCEN 0 -#define NPCX_ADCCNF_STOP 11 -#define NPCX_ATCTL_SCLKDIV_FIELD FIELD(0, 6) -#define NPCX_ATCTL_DLY_FIELD FIELD(8, 3) -#define NPCX_ASCADD_SADDR_FIELD FIELD(0, 5) -#define NPCX_THRCTS_ADC_WKEN 15 -#define NPCX_THRCTS_THR6_IEN 13 -#define NPCX_THRCTS_THR5_IEN 12 -#define NPCX_THRCTS_THR4_IEN 11 -#define NPCX_THRCTS_THR3_IEN 10 -#define NPCX_THRCTS_THR2_IEN 9 -#define NPCX_THRCTS_THR1_IEN 8 -#define NPCX_THRCTS_ADC_EVENT 7 -#define NPCX_THRCTS_THR6_STS 5 -#define NPCX_THRCTS_THR5_STS 4 -#define NPCX_THRCTS_THR4_STS 3 -#define NPCX_THRCTS_THR3_STS 2 -#define NPCX_THRCTS_THR2_STS 1 -#define NPCX_THRCTS_THR1_STS 0 -#define NPCX_CHNDAT_CHDAT_FIELD FIELD(0, 10) -#define NPCX_CHNDAT_NEW 15 -#define NPCX_THRCTL_THEN 15 -#define NPCX_THRCTL_L_H 14 -#define NPCX_THRCTL_CHNSEL FIELD(10, 4) -#define NPCX_THRCTL_THRVAL FIELD(0, 10) - -#define NPCX_ADC_THRESH1 1 -#define NPCX_ADC_THRESH2 2 -#define NPCX_ADC_THRESH3 3 -#define NPCX_ADC_THRESH4 4 -#define NPCX_ADC_THRESH5 5 -#define NPCX_ADC_THRESH6 6 -#define NPCX_ADC_THRESH_CNT 6 +#define NPCX_ADCSTS_EOCEV 0 +#define NPCX_ADCCNF_ADCMD_FIELD FIELD(1, 2) +#define NPCX_ADCCNF_ADCRPTC 3 +#define NPCX_ADCCNF_INTECEN 6 +#define NPCX_ADCCNF_START 4 +#define NPCX_ADCCNF_ADCEN 0 +#define NPCX_ADCCNF_STOP 11 +#define NPCX_ATCTL_SCLKDIV_FIELD FIELD(0, 6) +#define NPCX_ATCTL_DLY_FIELD FIELD(8, 3) +#define NPCX_ASCADD_SADDR_FIELD FIELD(0, 5) +#define NPCX_THRCTS_ADC_WKEN 15 +#define NPCX_THRCTS_THR6_IEN 13 +#define NPCX_THRCTS_THR5_IEN 12 +#define NPCX_THRCTS_THR4_IEN 11 +#define NPCX_THRCTS_THR3_IEN 10 +#define NPCX_THRCTS_THR2_IEN 9 +#define NPCX_THRCTS_THR1_IEN 8 +#define NPCX_THRCTS_ADC_EVENT 7 +#define NPCX_THRCTS_THR6_STS 5 +#define NPCX_THRCTS_THR5_STS 4 +#define NPCX_THRCTS_THR4_STS 3 +#define NPCX_THRCTS_THR3_STS 2 +#define NPCX_THRCTS_THR2_STS 1 +#define NPCX_THRCTS_THR1_STS 0 +#define NPCX_CHNDAT_CHDAT_FIELD FIELD(0, 10) +#define NPCX_CHNDAT_NEW 15 +#define NPCX_THRCTL_THEN 15 +#define NPCX_THRCTL_L_H 14 +#define NPCX_THRCTL_CHNSEL FIELD(10, 4) +#define NPCX_THRCTL_THRVAL FIELD(0, 10) + +#define NPCX_ADC_THRESH1 1 +#define NPCX_ADC_THRESH2 2 +#define NPCX_ADC_THRESH3 3 +#define NPCX_ADC_THRESH4 4 +#define NPCX_ADC_THRESH5 5 +#define NPCX_ADC_THRESH6 6 +#define NPCX_ADC_THRESH_CNT 6 diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h index 403d40b4a3..c99fb76bf3 100644 --- a/chip/npcx/registers.h +++ b/chip/npcx/registers.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,37 +8,41 @@ #ifndef __CROS_EC_REGISTERS_H #define __CROS_EC_REGISTERS_H +#include "clock_chip.h" #include "common.h" #include "compile_time_macros.h" -#include "clock_chip.h" /******************************************************************************/ /* * Macro Functions */ /* Bit functions */ -#define SET_BIT(reg, bit) ((reg) |= (0x1 << (bit))) -#define CLEAR_BIT(reg, bit) ((reg) &= (~(0x1 << (bit)))) -#define IS_BIT_SET(reg, bit) (((reg) >> (bit)) & (0x1)) -#define UPDATE_BIT(reg, bit, cond) { if (cond) \ - SET_BIT(reg, bit); \ - else \ - CLEAR_BIT(reg, bit); } +#define SET_BIT(reg, bit) ((reg) |= (0x1 << (bit))) +#define CLEAR_BIT(reg, bit) ((reg) &= (~(0x1 << (bit)))) +#define IS_BIT_SET(reg, bit) (((reg) >> (bit)) & (0x1)) +#define UPDATE_BIT(reg, bit, cond) \ + { \ + if (cond) \ + SET_BIT(reg, bit); \ + else \ + CLEAR_BIT(reg, bit); \ + } /* Field functions */ -#define GET_POS_FIELD(pos, size) pos -#define GET_SIZE_FIELD(pos, size) size -#define FIELD_POS(field) GET_POS_##field -#define FIELD_SIZE(field) GET_SIZE_##field +#define GET_POS_FIELD(pos, size) pos +#define GET_SIZE_FIELD(pos, size) size +#define FIELD_POS(field) GET_POS_##field +#define FIELD_SIZE(field) GET_SIZE_##field /* Read field functions */ #define GET_FIELD(reg, field) \ _GET_FIELD_(reg, FIELD_POS(field), FIELD_SIZE(field)) -#define _GET_FIELD_(reg, f_pos, f_size) (((reg)>>(f_pos)) & ((1<<(f_size))-1)) +#define _GET_FIELD_(reg, f_pos, f_size) \ + (((reg) >> (f_pos)) & ((1 << (f_size)) - 1)) /* Write field functions */ #define SET_FIELD(reg, field, value) \ _SET_FIELD_(reg, FIELD_POS(field), FIELD_SIZE(field), value) -#define _SET_FIELD_(reg, f_pos, f_size, value) \ - ((reg) = ((reg) & (~(((1 << (f_size))-1) << (f_pos)))) \ - | ((value) << (f_pos))) +#define _SET_FIELD_(reg, f_pos, f_size, value) \ + ((reg) = ((reg) & (~(((1 << (f_size)) - 1) << (f_pos)))) | \ + ((value) << (f_pos))) /******************************************************************************/ /* @@ -46,224 +50,212 @@ */ /* Global Definition */ -#define I2C_7BITS_ADDR 0 +#define I2C_7BITS_ADDR 0 /* Switcher of features */ -#define SUPPORT_LCT 1 -#define SUPPORT_WDG 1 -#define SUPPORT_P80_SEG 0 /* Note: it uses KSO10 & KSO11 */ +#define SUPPORT_LCT 1 +#define SUPPORT_WDG 1 +#define SUPPORT_P80_SEG 0 /* Note: it uses KSO10 & KSO11 */ /* Switcher of debugging */ -#define DEBUG_GPIO 0 -#define DEBUG_I2C 0 -#define DEBUG_TMR 0 -#define DEBUG_WDG 0 -#define DEBUG_FAN 0 -#define DEBUG_PWM 0 -#define DEBUG_SPI 0 -#define DEBUG_FLH 0 -#define DEBUG_PECI 0 -#define DEBUG_SHI 0 -#define DEBUG_CLK 0 -#define DEBUG_LPC 0 -#define DEBUG_ESPI 0 -#define DEBUG_CEC 0 -#define DEBUG_SIB 0 -#define DEBUG_PS2 0 +#define DEBUG_GPIO 0 +#define DEBUG_I2C 0 +#define DEBUG_TMR 0 +#define DEBUG_WDG 0 +#define DEBUG_FAN 0 +#define DEBUG_PWM 0 +#define DEBUG_SPI 0 +#define DEBUG_FLH 0 +#define DEBUG_PECI 0 +#define DEBUG_SHI 0 +#define DEBUG_CLK 0 +#define DEBUG_LPC 0 +#define DEBUG_ESPI 0 +#define DEBUG_CEC 0 +#define DEBUG_SIB 0 +#define DEBUG_PS2 0 /* Modules Map */ -#define NPCX_ESPI_BASE_ADDR 0x4000A000 -#define NPCX_MDC_BASE_ADDR 0x4000C000 -#define NPCX_PMC_BASE_ADDR 0x4000D000 -#define NPCX_SIB_BASE_ADDR 0x4000E000 -#define NPCX_SHI_BASE_ADDR 0x4000F000 -#define NPCX_SHM_BASE_ADDR 0x40010000 -#define NPCX_GDMA_BASE_ADDR 0x40011000 -#define NPCX_FIU_BASE_ADDR 0x40020000 -#define NPCX_KBSCAN_REGS_BASE 0x400A3000 -#define NPCX_WOV_BASE_ADDR 0x400A4000 -#define NPCX_APM_BASE_ADDR 0x400A4800 -#define NPCX_GLUE_REGS_BASE 0x400A5000 -#define NPCX_BBRAM_BASE_ADDR 0x400AF000 -#define NPCX_PS2_BASE_ADDR 0x400B1000 -#define NPCX_HFCG_BASE_ADDR 0x400B5000 -#define NPCX_LFCG_BASE_ADDR 0x400B5100 -#define NPCX_FMUL2_BASE_ADDR 0x400B5200 -#define NPCX_MTC_BASE_ADDR 0x400B7000 -#define NPCX_MSWC_BASE_ADDR 0x400C1000 -#define NPCX_SCFG_BASE_ADDR 0x400C3000 -#define NPCX_KBC_BASE_ADDR 0x400C7000 -#define NPCX_ADC_BASE_ADDR 0x400D1000 -#define NPCX_SPI_BASE_ADDR 0x400D2000 -#define NPCX_PECI_BASE_ADDR 0x400D4000 -#define NPCX_TWD_BASE_ADDR 0x400D8000 +#define NPCX_ESPI_BASE_ADDR 0x4000A000 +#define NPCX_MDC_BASE_ADDR 0x4000C000 +#define NPCX_PMC_BASE_ADDR 0x4000D000 +#define NPCX_SIB_BASE_ADDR 0x4000E000 +#define NPCX_SHI_BASE_ADDR 0x4000F000 +#define NPCX_SHM_BASE_ADDR 0x40010000 +#define NPCX_GDMA_BASE_ADDR 0x40011000 +#define NPCX_FIU_BASE_ADDR 0x40020000 +#define NPCX_KBSCAN_REGS_BASE 0x400A3000 +#define NPCX_WOV_BASE_ADDR 0x400A4000 +#define NPCX_APM_BASE_ADDR 0x400A4800 +#define NPCX_GLUE_REGS_BASE 0x400A5000 +#define NPCX_BBRAM_BASE_ADDR 0x400AF000 +#define NPCX_PS2_BASE_ADDR 0x400B1000 +#define NPCX_HFCG_BASE_ADDR 0x400B5000 +#define NPCX_LFCG_BASE_ADDR 0x400B5100 +#define NPCX_FMUL2_BASE_ADDR 0x400B5200 +#define NPCX_MTC_BASE_ADDR 0x400B7000 +#define NPCX_MSWC_BASE_ADDR 0x400C1000 +#define NPCX_SCFG_BASE_ADDR 0x400C3000 +#define NPCX_KBC_BASE_ADDR 0x400C7000 +#define NPCX_ADC_BASE_ADDR 0x400D1000 +#define NPCX_SPI_BASE_ADDR 0x400D2000 +#define NPCX_PECI_BASE_ADDR 0x400D4000 +#define NPCX_TWD_BASE_ADDR 0x400D8000 /* Multi-Modules Map */ -#define NPCX_PWM_BASE_ADDR(mdl) (0x40080000 + ((mdl) * 0x2000L)) -#define NPCX_GPIO_BASE_ADDR(mdl) (0x40081000 + ((mdl) * 0x2000L)) -#define NPCX_ITIM_BASE_ADDR(mdl) (0x400B0000 + ((mdl) * 0x2000L)) -#define NPCX_MIWU_BASE_ADDR(mdl) (0x400BB000 + ((mdl) * 0x2000L)) -#define NPCX_MFT_BASE_ADDR(mdl) (0x400E1000 + ((mdl) * 0x2000L)) -#define NPCX_PM_CH_BASE_ADDR(mdl) (0x400C9000 + ((mdl) * 0x2000L)) +#define NPCX_PWM_BASE_ADDR(mdl) (0x40080000 + ((mdl)*0x2000L)) +#define NPCX_GPIO_BASE_ADDR(mdl) (0x40081000 + ((mdl)*0x2000L)) +#define NPCX_ITIM_BASE_ADDR(mdl) (0x400B0000 + ((mdl)*0x2000L)) +#define NPCX_MIWU_BASE_ADDR(mdl) (0x400BB000 + ((mdl)*0x2000L)) +#define NPCX_MFT_BASE_ADDR(mdl) (0x400E1000 + ((mdl)*0x2000L)) +#define NPCX_PM_CH_BASE_ADDR(mdl) (0x400C9000 + ((mdl)*0x2000L)) /* * NPCX-IRQ numbers */ -#define NPCX_IRQ_0 0 -#define NPCX_IRQ_1 1 -#define NPCX_IRQ_2 2 -#define NPCX_IRQ_3 3 -#define NPCX_IRQ_4 4 -#define NPCX_IRQ_5 5 -#define NPCX_IRQ_6 6 -#define NPCX_IRQ_7 7 -#define NPCX_IRQ_8 8 -#define NPCX_IRQ_9 9 -#define NPCX_IRQ_10 10 -#define NPCX_IRQ_11 11 -#define NPCX_IRQ_12 12 -#define NPCX_IRQ_13 13 -#define NPCX_IRQ_14 14 -#define NPCX_IRQ_15 15 -#define NPCX_IRQ_16 16 -#define NPCX_IRQ_17 17 -#define NPCX_IRQ_18 18 -#define NPCX_IRQ_19 19 -#define NPCX_IRQ_20 20 -#define NPCX_IRQ_21 21 -#define NPCX_IRQ_22 22 -#define NPCX_IRQ_23 23 -#define NPCX_IRQ_24 24 -#define NPCX_IRQ_25 25 -#define NPCX_IRQ_26 26 -#define NPCX_IRQ_27 27 -#define NPCX_IRQ_28 28 -#define NPCX_IRQ_29 29 -#define NPCX_IRQ_30 30 -#define NPCX_IRQ_31 31 -#define NPCX_IRQ_32 32 -#define NPCX_IRQ_33 33 -#define NPCX_IRQ_34 34 -#define NPCX_IRQ_35 35 -#define NPCX_IRQ_36 36 -#define NPCX_IRQ_37 37 -#define NPCX_IRQ_38 38 -#define NPCX_IRQ_39 39 -#define NPCX_IRQ_40 40 -#define NPCX_IRQ_41 41 -#define NPCX_IRQ_42 42 -#define NPCX_IRQ_43 43 -#define NPCX_IRQ_44 44 -#define NPCX_IRQ_45 45 -#define NPCX_IRQ_46 46 -#define NPCX_IRQ_47 47 -#define NPCX_IRQ_48 48 -#define NPCX_IRQ_49 49 -#define NPCX_IRQ_50 50 -#define NPCX_IRQ_51 51 -#define NPCX_IRQ_52 52 -#define NPCX_IRQ_53 53 -#define NPCX_IRQ_54 54 -#define NPCX_IRQ_55 55 -#define NPCX_IRQ_56 56 -#define NPCX_IRQ_57 57 -#define NPCX_IRQ_58 58 -#define NPCX_IRQ_59 59 -#define NPCX_IRQ_60 60 -#define NPCX_IRQ_61 61 -#define NPCX_IRQ_62 62 -#define NPCX_IRQ_63 63 - -#define NPCX_IRQ_COUNT 64 - -/******************************************************************************/ -/* Miscellaneous Device Control (MDC) registers */ -#define NPCX_FWCTRL REG8(NPCX_MDC_BASE_ADDR + 0x007) - -/* MDC register fields */ -#define NPCX_FWCTRL_RO_REGION 0 -#define NPCX_FWCTRL_FW_SLOT 1 +#define NPCX_IRQ_0 0 +#define NPCX_IRQ_1 1 +#define NPCX_IRQ_2 2 +#define NPCX_IRQ_3 3 +#define NPCX_IRQ_4 4 +#define NPCX_IRQ_5 5 +#define NPCX_IRQ_6 6 +#define NPCX_IRQ_7 7 +#define NPCX_IRQ_8 8 +#define NPCX_IRQ_9 9 +#define NPCX_IRQ_10 10 +#define NPCX_IRQ_11 11 +#define NPCX_IRQ_12 12 +#define NPCX_IRQ_13 13 +#define NPCX_IRQ_14 14 +#define NPCX_IRQ_15 15 +#define NPCX_IRQ_16 16 +#define NPCX_IRQ_17 17 +#define NPCX_IRQ_18 18 +#define NPCX_IRQ_19 19 +#define NPCX_IRQ_20 20 +#define NPCX_IRQ_21 21 +#define NPCX_IRQ_22 22 +#define NPCX_IRQ_23 23 +#define NPCX_IRQ_24 24 +#define NPCX_IRQ_25 25 +#define NPCX_IRQ_26 26 +#define NPCX_IRQ_27 27 +#define NPCX_IRQ_28 28 +#define NPCX_IRQ_29 29 +#define NPCX_IRQ_30 30 +#define NPCX_IRQ_31 31 +#define NPCX_IRQ_32 32 +#define NPCX_IRQ_33 33 +#define NPCX_IRQ_34 34 +#define NPCX_IRQ_35 35 +#define NPCX_IRQ_36 36 +#define NPCX_IRQ_37 37 +#define NPCX_IRQ_38 38 +#define NPCX_IRQ_39 39 +#define NPCX_IRQ_40 40 +#define NPCX_IRQ_41 41 +#define NPCX_IRQ_42 42 +#define NPCX_IRQ_43 43 +#define NPCX_IRQ_44 44 +#define NPCX_IRQ_45 45 +#define NPCX_IRQ_46 46 +#define NPCX_IRQ_47 47 +#define NPCX_IRQ_48 48 +#define NPCX_IRQ_49 49 +#define NPCX_IRQ_50 50 +#define NPCX_IRQ_51 51 +#define NPCX_IRQ_52 52 +#define NPCX_IRQ_53 53 +#define NPCX_IRQ_54 54 +#define NPCX_IRQ_55 55 +#define NPCX_IRQ_56 56 +#define NPCX_IRQ_57 57 +#define NPCX_IRQ_58 58 +#define NPCX_IRQ_59 59 +#define NPCX_IRQ_60 60 +#define NPCX_IRQ_61 61 +#define NPCX_IRQ_62 62 +#define NPCX_IRQ_63 63 + +#define NPCX_IRQ_COUNT 64 /******************************************************************************/ /* High Frequency Clock Generator (HFCG) registers */ -#define NPCX_HFCGCTRL REG8(NPCX_HFCG_BASE_ADDR + 0x000) -#define NPCX_HFCGML REG8(NPCX_HFCG_BASE_ADDR + 0x002) -#define NPCX_HFCGMH REG8(NPCX_HFCG_BASE_ADDR + 0x004) -#define NPCX_HFCGN REG8(NPCX_HFCG_BASE_ADDR + 0x006) -#define NPCX_HFCGP REG8(NPCX_HFCG_BASE_ADDR + 0x008) -#define NPCX_HFCBCD REG8(NPCX_HFCG_BASE_ADDR + 0x010) +#define NPCX_HFCGCTRL REG8(NPCX_HFCG_BASE_ADDR + 0x000) +#define NPCX_HFCGML REG8(NPCX_HFCG_BASE_ADDR + 0x002) +#define NPCX_HFCGMH REG8(NPCX_HFCG_BASE_ADDR + 0x004) +#define NPCX_HFCGN REG8(NPCX_HFCG_BASE_ADDR + 0x006) +#define NPCX_HFCGP REG8(NPCX_HFCG_BASE_ADDR + 0x008) +#define NPCX_HFCBCD REG8(NPCX_HFCG_BASE_ADDR + 0x010) /* HFCG register fields */ -#define NPCX_HFCGCTRL_LOAD 0 -#define NPCX_HFCGCTRL_LOCK 2 -#define NPCX_HFCGCTRL_CLK_CHNG 7 +#define NPCX_HFCGCTRL_LOAD 0 +#define NPCX_HFCGCTRL_LOCK 2 +#define NPCX_HFCGCTRL_CLK_CHNG 7 /******************************************************************************/ /* Low Frequency Clock Generator (LFCG) registers */ -#define NPCX_LFCGCTL REG8(NPCX_LFCG_BASE_ADDR + 0x000) -#define NPCX_HFRDI REG16(NPCX_LFCG_BASE_ADDR + 0x002) -#define NPCX_HFRDF REG16(NPCX_LFCG_BASE_ADDR + 0x004) -#define NPCX_FRCDIV REG16(NPCX_LFCG_BASE_ADDR + 0x006) -#define NPCX_DIVCOR1 REG16(NPCX_LFCG_BASE_ADDR + 0x008) -#define NPCX_DIVCOR2 REG16(NPCX_LFCG_BASE_ADDR + 0x00A) -#define NPCX_LFCGCTL2 REG8(NPCX_LFCG_BASE_ADDR + 0x014) +#define NPCX_LFCGCTL REG8(NPCX_LFCG_BASE_ADDR + 0x000) +#define NPCX_HFRDI REG16(NPCX_LFCG_BASE_ADDR + 0x002) +#define NPCX_HFRDF REG16(NPCX_LFCG_BASE_ADDR + 0x004) +#define NPCX_FRCDIV REG16(NPCX_LFCG_BASE_ADDR + 0x006) +#define NPCX_DIVCOR1 REG16(NPCX_LFCG_BASE_ADDR + 0x008) +#define NPCX_DIVCOR2 REG16(NPCX_LFCG_BASE_ADDR + 0x00A) +#define NPCX_LFCGCTL2 REG8(NPCX_LFCG_BASE_ADDR + 0x014) /* LFCG register fields */ -#define NPCX_LFCGCTL_XTCLK_VAL 7 -#define NPCX_LFCGCTL2_XT_OSC_SL_EN 6 +#define NPCX_LFCGCTL_XTCLK_VAL 7 +#define NPCX_LFCGCTL2_XT_OSC_SL_EN 6 /******************************************************************************/ /* CR UART Register */ -#define NPCX_UTBUF(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x000) -#define NPCX_URBUF(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x002) -#define NPCX_UICTRL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x004) -#define NPCX_USTAT(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x006) -#define NPCX_UFRS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x008) -#define NPCX_UMDSL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x00A) -#define NPCX_UBAUD(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x00C) -#define NPCX_UPSR(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x00E) +#define NPCX_UTBUF(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x000) +#define NPCX_URBUF(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x002) +#define NPCX_UICTRL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x004) +#define NPCX_USTAT(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x006) +#define NPCX_UFRS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x008) +#define NPCX_UMDSL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x00A) +#define NPCX_UBAUD(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x00C) +#define NPCX_UPSR(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x00E) /******************************************************************************/ /* KBSCAN registers */ -#define NPCX_KBSIN REG8(NPCX_KBSCAN_REGS_BASE + 0x04) -#define NPCX_KBSINPU REG8(NPCX_KBSCAN_REGS_BASE + 0x05) -#define NPCX_KBSOUT0 REG16(NPCX_KBSCAN_REGS_BASE + 0x06) -#define NPCX_KBSOUT1 REG16(NPCX_KBSCAN_REGS_BASE + 0x08) -#define NPCX_KBS_BUF_INDX REG8(NPCX_KBSCAN_REGS_BASE + 0x0A) -#define NPCX_KBS_BUF_DATA REG8(NPCX_KBSCAN_REGS_BASE + 0x0B) -#define NPCX_KBSEVT REG8(NPCX_KBSCAN_REGS_BASE + 0x0C) -#define NPCX_KBSCTL REG8(NPCX_KBSCAN_REGS_BASE + 0x0D) -#define NPCX_KBS_CFG_INDX REG8(NPCX_KBSCAN_REGS_BASE + 0x0E) -#define NPCX_KBS_CFG_DATA REG8(NPCX_KBSCAN_REGS_BASE + 0x0F) +#define NPCX_KBSIN REG8(NPCX_KBSCAN_REGS_BASE + 0x04) +#define NPCX_KBSINPU REG8(NPCX_KBSCAN_REGS_BASE + 0x05) +#define NPCX_KBSOUT0 REG16(NPCX_KBSCAN_REGS_BASE + 0x06) +#define NPCX_KBSOUT1 REG16(NPCX_KBSCAN_REGS_BASE + 0x08) +#define NPCX_KBS_BUF_INDX REG8(NPCX_KBSCAN_REGS_BASE + 0x0A) +#define NPCX_KBS_BUF_DATA REG8(NPCX_KBSCAN_REGS_BASE + 0x0B) +#define NPCX_KBSEVT REG8(NPCX_KBSCAN_REGS_BASE + 0x0C) +#define NPCX_KBSCTL REG8(NPCX_KBSCAN_REGS_BASE + 0x0D) +#define NPCX_KBS_CFG_INDX REG8(NPCX_KBSCAN_REGS_BASE + 0x0E) +#define NPCX_KBS_CFG_DATA REG8(NPCX_KBSCAN_REGS_BASE + 0x0F) /* KBSCAN register fields */ -#define NPCX_KBSBUFINDX 0 -#define NPCX_KBSDONE 0 -#define NPCX_KBSERR 1 -#define NPCX_KBSSTART 0 -#define NPCX_KBSMODE 1 -#define NPCX_KBSIEN 2 -#define NPCX_KBSINC 3 -#define NPCX_KBSCFGINDX 0 +#define NPCX_KBSBUFINDX 0 +#define NPCX_KBSDONE 0 +#define NPCX_KBSERR 1 +#define NPCX_KBSSTART 0 +#define NPCX_KBSMODE 1 +#define NPCX_KBSIEN 2 +#define NPCX_KBSINC 3 +#define NPCX_KBSCFGINDX 0 /* KBSCAN definitions */ -#define KB_ROW_NUM 8 /* Rows numbers of keyboard matrix */ -#define KB_COL_NUM 18 /* Columns numbers of keyboard matrix */ -#define KB_ROW_MASK ((1<= 0 && i <= 1) ? ESPI_VW_TYPE_INT_EV : \ - (i >= 2 && i <= 7) ? ESPI_VW_TYPE_SYS_EV : \ - (i >= 64 && i <= 127) ? ESPI_VW_TYPE_PLT : \ - (i >= 128 && i <= 255) ? ESPI_VW_TYPE_GPIO : \ - ESPI_VW_TYPE_NONE) +#define VM_TYPE(i) \ + ((i >= 0 && i <= 1) ? ESPI_VW_TYPE_INT_EV : \ + (i >= 2 && i <= 7) ? ESPI_VW_TYPE_SYS_EV : \ + (i >= 64 && i <= 127) ? ESPI_VW_TYPE_PLT : \ + (i >= 128 && i <= 255) ? ESPI_VW_TYPE_GPIO : \ + ESPI_VW_TYPE_NONE) /* Bit field manipulation for VWEVMS Value */ -#define VWEVMS_INX(i) ((i<<8) & 0x00007F00) -#define VWEVMS_INX_EN(n) ((n<<15) & 0x00008000) -#define VWEVMS_PLTRST_EN(p) ((p<<17) & 0x00020000) -#define VWEVMS_INT_EN(e) ((e<<18) & 0x00040000) -#define VWEVMS_ESPIRST_EN(r) ((r<<19) & 0x00080000) -#define VWEVMS_FIELD(i, n, p, e, r) (VWEVMS_INX(i) | VWEVMS_INX_EN(n) | \ - VWEVMS_PLTRST_EN(p) | VWEVMS_INTWK_EN(e) | \ - VWEVMS_ESPIRST_EN(r)) -#define VWEVMS_IDX_GET(reg) (((reg & 0x00007F00)>>8)) +#define VWEVMS_INX(i) ((i << 8) & 0x00007F00) +#define VWEVMS_INX_EN(n) ((n << 15) & 0x00008000) +#define VWEVMS_PLTRST_EN(p) ((p << 17) & 0x00020000) +#define VWEVMS_INT_EN(e) ((e << 18) & 0x00040000) +#define VWEVMS_ESPIRST_EN(r) ((r << 19) & 0x00080000) +#define VWEVMS_FIELD(i, n, p, e, r) \ + (VWEVMS_INX(i) | VWEVMS_INX_EN(n) | VWEVMS_PLTRST_EN(p) | \ + VWEVMS_INTWK_EN(e) | VWEVMS_ESPIRST_EN(r)) +#define VWEVMS_IDX_GET(reg) (((reg & 0x00007F00) >> 8)) /* Bit field manipulation for VWEVSM Value */ -#define VWEVSM_VALID_N(v) ((v<<4) & 0x000000F0) -#define VWEVSM_INX(i) ((i<<8) & 0x00007F00) -#define VWEVSM_INX_EN(n) ((n<<15) & 0x00008000) -#define VWEVSM_DIRTY(d) ((d<<16) & 0x00010000) -#define VWEVSM_PLTRST_EN(p) ((p<<17) & 0x00020000) -#define VWEVSM_CDRST_EN(c) ((c<<19) & 0x00080000) -#define VWEVSM_FIELD(i, n, v, p, c) (VWEVSM_INX(i) | VWEVSM_INX_EN(n) | \ - VWEVSM_VALID_N(v) | VWEVSM_PLTRST_EN(p) |\ - VWEVSM_CDRST_EN(c)) -#define VWEVSM_IDX_GET(reg) (((reg & 0x00007F00)>>8)) +#define VWEVSM_VALID_N(v) ((v << 4) & 0x000000F0) +#define VWEVSM_INX(i) ((i << 8) & 0x00007F00) +#define VWEVSM_INX_EN(n) ((n << 15) & 0x00008000) +#define VWEVSM_DIRTY(d) ((d << 16) & 0x00010000) +#define VWEVSM_PLTRST_EN(p) ((p << 17) & 0x00020000) +#define VWEVSM_CDRST_EN(c) ((c << 19) & 0x00080000) +#define VWEVSM_FIELD(i, n, v, p, c) \ + (VWEVSM_INX(i) | VWEVSM_INX_EN(n) | VWEVSM_VALID_N(v) | \ + VWEVSM_PLTRST_EN(p) | VWEVSM_CDRST_EN(c)) +#define VWEVSM_IDX_GET(reg) (((reg & 0x00007F00) >> 8)) /* define macro to handle SMI/SCI Virtual Wire */ /* Read SMI VWire status from VWEVSM(offset 2) register. */ -#define SMI_STATUS_MASK ((uint8_t) (NPCX_VWEVSM(2) & 0x00000002)) +#define SMI_STATUS_MASK ((uint8_t)(NPCX_VWEVSM(2) & 0x00000002)) /* * Read SCI VWire status from VWEVSM(offset 2) register. * Left shift 2 to meet the SCIB field in HIPMIC register. */ -#define SCI_STATUS_MASK (((uint8_t) (NPCX_VWEVSM(2) & 0x00000001)) << 2) -#define SCIB_MASK(v) (v << NPCX_HIPMIC_SCIB) -#define SMIB_MASK(v) (v << NPCX_HIPMIC_SMIB) -#define NPCX_VW_SCI(level) ((NPCX_HIPMIC(PM_CHAN_1) & 0xF9) | \ - SMI_STATUS_MASK | SCIB_MASK(level)) -#define NPCX_VW_SMI(level) ((NPCX_HIPMIC(PM_CHAN_1) & 0xF9) | \ - SCI_STATUS_MASK | SMIB_MASK(level)) +#define SCI_STATUS_MASK (((uint8_t)(NPCX_VWEVSM(2) & 0x00000001)) << 2) +#define SCIB_MASK(v) (v << NPCX_HIPMIC_SCIB) +#define SMIB_MASK(v) (v << NPCX_HIPMIC_SMIB) +#define NPCX_VW_SCI(level) \ + ((NPCX_HIPMIC(PM_CHAN_1) & 0xF9) | SMI_STATUS_MASK | SCIB_MASK(level)) +#define NPCX_VW_SMI(level) \ + ((NPCX_HIPMIC(PM_CHAN_1) & 0xF9) | SCI_STATUS_MASK | SMIB_MASK(level)) /* eSPI enumeration */ /* eSPI channels */ @@ -1287,366 +1351,367 @@ enum { /* eSPI IO modes */ enum { NPCX_ESPI_IO_MODE_SINGLE = 0, - NPCX_ESPI_IO_MODE_DUAL = 1, - NPCX_ESPI_IO_MODE_Quad = 2, - NPCX_ESPI_IO_MODE_ALL = 3, - NPCX_ESPI_IO_MODE_NONE = 0xFF + NPCX_ESPI_IO_MODE_DUAL = 1, + NPCX_ESPI_IO_MODE_QUAD = 2, + NPCX_ESPI_IO_MODE_ALL = 3, + NPCX_ESPI_IO_MODE_NONE = 0xFF +}; + +/* eSPI IO mode selected */ +enum { + NPCX_ESPI_IO_MODE_SEL_SINGLE = 0, + NPCX_ESPI_IO_MODE_SEL_DUAL = 1, + NPCX_ESPI_IO_MODE_SEL_QUARD = 2, + NPCX_ESPI_IO_MODE_SEL_NONE = 0xFF }; /* VW types */ enum { - ESPI_VW_TYPE_INT_EV, /* Interrupt event */ - ESPI_VW_TYPE_SYS_EV, /* System Event */ - ESPI_VW_TYPE_PLT, /* Platform specific */ - ESPI_VW_TYPE_GPIO, /* General Purpose I/O Expander */ + ESPI_VW_TYPE_INT_EV, /* Interrupt event */ + ESPI_VW_TYPE_SYS_EV, /* System Event */ + ESPI_VW_TYPE_PLT, /* Platform specific */ + ESPI_VW_TYPE_GPIO, /* General Purpose I/O Expander */ ESPI_VW_TYPE_NUM, ESPI_VW_TYPE_NONE = 0xFF }; /******************************************************************************/ /* GDMA (General DMA) Registers */ -#define NPCX_GDMA_CTL REG32(NPCX_GDMA_BASE_ADDR + 0x000) -#define NPCX_GDMA_SRCB REG32(NPCX_GDMA_BASE_ADDR + 0x004) -#define NPCX_GDMA_DSTB REG32(NPCX_GDMA_BASE_ADDR + 0x008) -#define NPCX_GDMA_TCNT REG32(NPCX_GDMA_BASE_ADDR + 0x00C) -#define NPCX_GDMA_CSRC REG32(NPCX_GDMA_BASE_ADDR + 0x010) -#define NPCX_GDMA_CDST REG32(NPCX_GDMA_BASE_ADDR + 0x014) -#define NPCX_GDMA_CTCNT REG32(NPCX_GDMA_BASE_ADDR + 0x018) - +#define NPCX_GDMA_CTL REG32(NPCX_GDMA_BASE_ADDR + 0x000) +#define NPCX_GDMA_SRCB REG32(NPCX_GDMA_BASE_ADDR + 0x004) +#define NPCX_GDMA_DSTB REG32(NPCX_GDMA_BASE_ADDR + 0x008) +#define NPCX_GDMA_TCNT REG32(NPCX_GDMA_BASE_ADDR + 0x00C) +#define NPCX_GDMA_CSRC REG32(NPCX_GDMA_BASE_ADDR + 0x010) +#define NPCX_GDMA_CDST REG32(NPCX_GDMA_BASE_ADDR + 0x014) +#define NPCX_GDMA_CTCNT REG32(NPCX_GDMA_BASE_ADDR + 0x018) /******************************************************************************/ /* GDMA register fields */ -#define NPCX_GDMA_CTL_GDMAEN 0 -#define NPCX_GDMA_CTL_GDMAMS FIELD(2, 2) -#define NPCX_GDMA_CTL_DADIR 4 -#define NPCX_GDMA_CTL_SADIR 5 -#define NPCX_GDMA_CTL_SAFIX 7 -#define NPCX_GDMA_CTL_SIEN 8 -#define NPCX_GDMA_CTL_BME 9 -#define NPCX_GDMA_CTL_SBMS 11 -#define NPCX_GDMA_CTL_TWS FIELD(12, 2) -#define NPCX_GDMA_CTL_DM 15 -#define NPCX_GDMA_CTL_SOFTREQ 16 -#define NPCX_GDMA_CTL_TC 18 -#define NPCX_GDMA_CTL_GDMAERR 20 -#define NPCX_GDMA_CTL_BLOCK_BUG_CORRECTION_DISABLE 26 +#define NPCX_GDMA_CTL_GDMAEN 0 +#define NPCX_GDMA_CTL_GDMAMS FIELD(2, 2) +#define NPCX_GDMA_CTL_DADIR 4 +#define NPCX_GDMA_CTL_SADIR 5 +#define NPCX_GDMA_CTL_SAFIX 7 +#define NPCX_GDMA_CTL_SIEN 8 +#define NPCX_GDMA_CTL_BME 9 +#define NPCX_GDMA_CTL_SBMS 11 +#define NPCX_GDMA_CTL_TWS FIELD(12, 2) +#define NPCX_GDMA_CTL_DM 15 +#define NPCX_GDMA_CTL_SOFTREQ 16 +#define NPCX_GDMA_CTL_TC 18 +#define NPCX_GDMA_CTL_GDMAERR 20 +#define NPCX_GDMA_CTL_BLOCK_BUG_CORRECTION_DISABLE 26 /******************************************************************************/ /* Nuvoton internal used only registers */ -#define NPCX_INTERNAL_CTRL1 REG8(0x400DB000) -#define NPCX_INTERNAL_CTRL2 REG8(0x400DD000) -#define NPCX_INTERNAL_CTRL3 REG8(0x400DF000) +#define NPCX_INTERNAL_CTRL1 REG8(0x400DB000) +#define NPCX_INTERNAL_CTRL2 REG8(0x400DD000) +#define NPCX_INTERNAL_CTRL3 REG8(0x400DF000) /******************************************************************************/ /* Optional M4 Registers */ -#define CPU_DHCSR REG32(0xE000EDF0) -#define CPU_MPU_CTRL REG32(0xE000ED94) -#define CPU_MPU_RNR REG32(0xE000ED98) -#define CPU_MPU_RBAR REG32(0xE000ED9C) -#define CPU_MPU_RASR REG32(0xE000EDA0) - +#define CPU_DHCSR REG32(0xE000EDF0) +#define CPU_MPU_CTRL REG32(0xE000ED94) +#define CPU_MPU_RNR REG32(0xE000ED98) +#define CPU_MPU_RBAR REG32(0xE000ED9C) +#define CPU_MPU_RASR REG32(0xE000EDA0) /******************************************************************************/ /* Flash Utiltiy definition */ /* * Flash commands for the W25Q16CV SPI flash */ -#define CMD_READ_ID 0x9F -#define CMD_READ_MAN_DEV_ID 0x90 -#define CMD_WRITE_EN 0x06 -#define CMD_WRITE_STATUS 0x50 -#define CMD_READ_STATUS_REG 0x05 -#define CMD_READ_STATUS_REG2 0x35 -#define CMD_WRITE_STATUS_REG 0x01 -#define CMD_FLASH_PROGRAM 0x02 -#define CMD_SECTOR_ERASE 0x20 -#define CMD_BLOCK_32K_ERASE 0x52 -#define CMD_BLOCK_64K_ERASE 0xd8 -#define CMD_PROGRAM_UINT_SIZE 0x08 -#define CMD_PAGE_SIZE 0x00 -#define CMD_READ_ID_TYPE 0x47 -#define CMD_FAST_READ 0x0B +#define CMD_READ_ID 0x9F +#define CMD_READ_MAN_DEV_ID 0x90 +#define CMD_WRITE_EN 0x06 +#define CMD_WRITE_STATUS 0x50 +#define CMD_READ_STATUS_REG 0x05 +#define CMD_READ_STATUS_REG2 0x35 +#define CMD_WRITE_STATUS_REG 0x01 +#define CMD_FLASH_PROGRAM 0x02 +#define CMD_SECTOR_ERASE 0x20 +#define CMD_BLOCK_32K_ERASE 0x52 +#define CMD_BLOCK_64K_ERASE 0xd8 +#define CMD_PROGRAM_UINT_SIZE 0x08 +#define CMD_PAGE_SIZE 0x00 +#define CMD_READ_ID_TYPE 0x47 +#define CMD_FAST_READ 0x0B /* * Status registers for the W25Q16CV SPI flash */ -#define SPI_FLASH_SR2_SUS BIT(7) -#define SPI_FLASH_SR2_CMP BIT(6) -#define SPI_FLASH_SR2_LB3 BIT(5) -#define SPI_FLASH_SR2_LB2 BIT(4) -#define SPI_FLASH_SR2_LB1 BIT(3) -#define SPI_FLASH_SR2_QE BIT(1) -#define SPI_FLASH_SR2_SRP1 BIT(0) -#define SPI_FLASH_SR1_SRP0 BIT(7) -#define SPI_FLASH_SR1_SEC BIT(6) -#define SPI_FLASH_SR1_TB BIT(5) -#define SPI_FLASH_SR1_BP2 BIT(4) -#define SPI_FLASH_SR1_BP1 BIT(3) -#define SPI_FLASH_SR1_BP0 BIT(2) -#define SPI_FLASH_SR1_WEL BIT(1) -#define SPI_FLASH_SR1_BUSY BIT(0) - +#define SPI_FLASH_SR2_SUS BIT(7) +#define SPI_FLASH_SR2_CMP BIT(6) +#define SPI_FLASH_SR2_LB3 BIT(5) +#define SPI_FLASH_SR2_LB2 BIT(4) +#define SPI_FLASH_SR2_LB1 BIT(3) +#define SPI_FLASH_SR2_QE BIT(1) +#define SPI_FLASH_SR2_SRP1 BIT(0) +#define SPI_FLASH_SR1_SRP0 BIT(7) +#define SPI_FLASH_SR1_SEC BIT(6) +#define SPI_FLASH_SR1_TB BIT(5) +#define SPI_FLASH_SR1_BP2 BIT(4) +#define SPI_FLASH_SR1_BP1 BIT(3) +#define SPI_FLASH_SR1_BP0 BIT(2) +#define SPI_FLASH_SR1_WEL BIT(1) +#define SPI_FLASH_SR1_BUSY BIT(0) /* 0: F_CS0 1: F_CS1_1(GPIO86) 2:F_CS1_2(GPIOA6) */ -#define FIU_CHIP_SELECT 0 +#define FIU_CHIP_SELECT 0 /* Create UMA control mask */ -#define MASK(bit) (0x1 << (bit)) -#define A_SIZE 0x03 /* 0: No ADR field 1: 3-bytes ADR field */ -#define C_SIZE 0x04 /* 0: 1-Byte CMD field 1:No CMD field */ -#define RD_WR 0x05 /* 0: Read 1: Write */ -#define DEV_NUM 0x06 /* 0: PVT is used 1: SHD is used */ -#define EXEC_DONE 0x07 -#define D_SIZE_1 0x01 -#define D_SIZE_2 0x02 -#define D_SIZE_3 0x03 -#define D_SIZE_4 0x04 -#define FLASH_SEL MASK(DEV_NUM) - -#define MASK_CMD_ONLY (MASK(EXEC_DONE) | FLASH_SEL) -#define MASK_CMD_ADR (MASK(EXEC_DONE) | FLASH_SEL | MASK(A_SIZE)) -#define MASK_CMD_ADR_WR (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \ - |MASK(A_SIZE) | D_SIZE_1) -#define MASK_RD_1BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_1) -#define MASK_RD_2BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_2) -#define MASK_RD_3BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_3) -#define MASK_RD_4BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_4) -#define MASK_CMD_RD_1BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_1) -#define MASK_CMD_RD_2BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_2) -#define MASK_CMD_RD_3BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_3) -#define MASK_CMD_RD_4BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_4) -#define MASK_CMD_WR_ONLY (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR)) -#define MASK_CMD_WR_1BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \ - | MASK(C_SIZE) | D_SIZE_1) -#define MASK_CMD_WR_2BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \ - | MASK(C_SIZE) | D_SIZE_2) -#define MASK_CMD_WR_ADR (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \ - | MASK(A_SIZE)) +#define MASK(bit) (0x1 << (bit)) +#define A_SIZE 0x03 /* 0: No ADR field 1: 3-bytes ADR field */ +#define C_SIZE 0x04 /* 0: 1-Byte CMD field 1:No CMD field */ +#define RD_WR 0x05 /* 0: Read 1: Write */ +#define DEV_NUM 0x06 /* 0: PVT is used 1: SHD is used */ +#define EXEC_DONE 0x07 +#define D_SIZE_1 0x01 +#define D_SIZE_2 0x02 +#define D_SIZE_3 0x03 +#define D_SIZE_4 0x04 +#define FLASH_SEL MASK(DEV_NUM) + +#define MASK_CMD_ONLY (MASK(EXEC_DONE) | FLASH_SEL) +#define MASK_CMD_ADR (MASK(EXEC_DONE) | FLASH_SEL | MASK(A_SIZE)) +#define MASK_CMD_ADR_WR \ + (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) | MASK(A_SIZE) | D_SIZE_1) +#define MASK_RD_1BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_1) +#define MASK_RD_2BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_2) +#define MASK_RD_3BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_3) +#define MASK_RD_4BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_4) +#define MASK_CMD_RD_1BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_1) +#define MASK_CMD_RD_2BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_2) +#define MASK_CMD_RD_3BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_3) +#define MASK_CMD_RD_4BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_4) +#define MASK_CMD_WR_ONLY (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR)) +#define MASK_CMD_WR_1BYTE \ + (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) | MASK(C_SIZE) | D_SIZE_1) +#define MASK_CMD_WR_2BYTE \ + (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) | MASK(C_SIZE) | D_SIZE_2) +#define MASK_CMD_WR_ADR \ + (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) | MASK(A_SIZE)) /******************************************************************************/ /* APM (Audio Processing Module) Registers */ -#define NPCX_APM_SR REG8(NPCX_APM_BASE_ADDR + 0x000) -#define NPCX_APM_SR2 REG8(NPCX_APM_BASE_ADDR + 0x004) -#define NPCX_APM_ICR REG8(NPCX_APM_BASE_ADDR + 0x008) -#define NPCX_APM_IMR REG8(NPCX_APM_BASE_ADDR + 0x00C) -#define NPCX_APM_IFR REG8(NPCX_APM_BASE_ADDR + 0x010) -#define NPCX_APM_CR_APM REG8(NPCX_APM_BASE_ADDR + 0x014) -#define NPCX_APM_CR_CK REG8(NPCX_APM_BASE_ADDR + 0x018) -#define NPCX_APM_AICR_ADC REG8(NPCX_APM_BASE_ADDR + 0x01C) -#define NPCX_APM_FCR_ADC REG8(NPCX_APM_BASE_ADDR + 0x020) -#define NPCX_APM_CR_DMIC REG8(NPCX_APM_BASE_ADDR + 0x02C) -#define NPCX_APM_CR_ADC REG8(NPCX_APM_BASE_ADDR + 0x030) -#define NPCX_APM_CR_MIX REG8(NPCX_APM_BASE_ADDR + 0x034) -#define NPCX_APM_DR_MIX REG8(NPCX_APM_BASE_ADDR + 0x038) -#define NPCX_APM_GCR_ADCL REG8(NPCX_APM_BASE_ADDR + 0x03C) -#define NPCX_APM_GCR_ADCR REG8(NPCX_APM_BASE_ADDR + 0x040) -#define NPCX_APM_GCR_MIXADCL REG8(NPCX_APM_BASE_ADDR + 0x044) -#define NPCX_APM_GCR_MIXADCR REG8(NPCX_APM_BASE_ADDR + 0x048) -#define NPCX_APM_CR_ADC_AGC REG8(NPCX_APM_BASE_ADDR + 0x04C) -#define NPCX_APM_DR_ADC_AGC REG8(NPCX_APM_BASE_ADDR + 0x050) -#define NPCX_APM_SR_ADC_AGCDGL REG8(NPCX_APM_BASE_ADDR + 0x054) -#define NPCX_APM_SR_ADC_AGCDGR REG8(NPCX_APM_BASE_ADDR + 0x058) -#define NPCX_APM_CR_VAD REG8(NPCX_APM_BASE_ADDR + 0x05C) -#define NPCX_APM_DR_VAD REG8(NPCX_APM_BASE_ADDR + 0x060) -#define NPCX_APM_CR_VAD_CMD REG8(NPCX_APM_BASE_ADDR + 0x064) -#define NPCX_APM_CR_TR REG8(NPCX_APM_BASE_ADDR + 0x068) -#define NPCX_APM_DR_TR REG8(NPCX_APM_BASE_ADDR + 0x06C) -#define NPCX_APM_SR_TR1 REG8(NPCX_APM_BASE_ADDR + 0x070) -#define NPCX_APM_SR_TR_SRCADC REG8(NPCX_APM_BASE_ADDR + 0x074) +#define NPCX_APM_SR REG8(NPCX_APM_BASE_ADDR + 0x000) +#define NPCX_APM_SR2 REG8(NPCX_APM_BASE_ADDR + 0x004) +#define NPCX_APM_ICR REG8(NPCX_APM_BASE_ADDR + 0x008) +#define NPCX_APM_IMR REG8(NPCX_APM_BASE_ADDR + 0x00C) +#define NPCX_APM_IFR REG8(NPCX_APM_BASE_ADDR + 0x010) +#define NPCX_APM_CR_APM REG8(NPCX_APM_BASE_ADDR + 0x014) +#define NPCX_APM_CR_CK REG8(NPCX_APM_BASE_ADDR + 0x018) +#define NPCX_APM_AICR_ADC REG8(NPCX_APM_BASE_ADDR + 0x01C) +#define NPCX_APM_FCR_ADC REG8(NPCX_APM_BASE_ADDR + 0x020) +#define NPCX_APM_CR_DMIC REG8(NPCX_APM_BASE_ADDR + 0x02C) +#define NPCX_APM_CR_ADC REG8(NPCX_APM_BASE_ADDR + 0x030) +#define NPCX_APM_CR_MIX REG8(NPCX_APM_BASE_ADDR + 0x034) +#define NPCX_APM_DR_MIX REG8(NPCX_APM_BASE_ADDR + 0x038) +#define NPCX_APM_GCR_ADCL REG8(NPCX_APM_BASE_ADDR + 0x03C) +#define NPCX_APM_GCR_ADCR REG8(NPCX_APM_BASE_ADDR + 0x040) +#define NPCX_APM_GCR_MIXADCL REG8(NPCX_APM_BASE_ADDR + 0x044) +#define NPCX_APM_GCR_MIXADCR REG8(NPCX_APM_BASE_ADDR + 0x048) +#define NPCX_APM_CR_ADC_AGC REG8(NPCX_APM_BASE_ADDR + 0x04C) +#define NPCX_APM_DR_ADC_AGC REG8(NPCX_APM_BASE_ADDR + 0x050) +#define NPCX_APM_SR_ADC_AGCDGL REG8(NPCX_APM_BASE_ADDR + 0x054) +#define NPCX_APM_SR_ADC_AGCDGR REG8(NPCX_APM_BASE_ADDR + 0x058) +#define NPCX_APM_CR_VAD REG8(NPCX_APM_BASE_ADDR + 0x05C) +#define NPCX_APM_DR_VAD REG8(NPCX_APM_BASE_ADDR + 0x060) +#define NPCX_APM_CR_VAD_CMD REG8(NPCX_APM_BASE_ADDR + 0x064) +#define NPCX_APM_CR_TR REG8(NPCX_APM_BASE_ADDR + 0x068) +#define NPCX_APM_DR_TR REG8(NPCX_APM_BASE_ADDR + 0x06C) +#define NPCX_APM_SR_TR1 REG8(NPCX_APM_BASE_ADDR + 0x070) +#define NPCX_APM_SR_TR_SRCADC REG8(NPCX_APM_BASE_ADDR + 0x074) /******************************************************************************/ /* APM register fields */ -#define NPCX_APM_SR_IRQ_PEND 6 -#define NPCX_APM_SR2_SMUTEIP 6 -#define NPCX_APM_ICR_INTR_MODE FIELD(6, 2) -#define NPCX_APM_IMR_VAD_DTC_MASK 6 -#define NPCX_APM_IFR_VAD_DTC 6 -#define NPCX_APM_CR_APM_PD 0 -#define NPCX_APM_CR_APM_AGC_DIS FIELD(1, 2) -#define NPCX_APM_CR_CK_MCLK_FREQ FIELD(0, 2) -#define NPCX_APM_AICR_ADC_ADC_AUDIOIF FIELD(0, 2) -#define NPCX_APM_AICR_ADC_PD_AICR_ADC 4 -#define NPCX_APM_AICR_ADC_ADC_ADWL FIELD(6, 2) -#define NPCX_APM_FCR_ADC_ADC_FREQ FIELD(0, 4) -#define NPCX_APM_FCR_ADC_ADC_WNF FIELD(4, 2) -#define NPCX_APM_FCR_ADC_ADC_HPF 6 -#define NPCX_APM_CR_DMIC_ADC_DMIC_SEL_RIGHT FIELD(0, 2) -#define NPCX_APM_CR_DMIC_ADC_DMIC_SEL_LEFT FIELD(2, 2) -#define NPCX_APM_CR_DMIC_ADC_DMIC_RATE FIELD(4, 3) -#define NPCX_APM_CR_DMIC_PD_DMIC 7 -#define NPCX_APM_CR_ADC_ADC_SOFT_MUTE 7 -#define NPCX_APM_CR_MIX_MIX_ADD FIELD(0, 6) -#define NPCX_APM_CR_MIX_MIX_LOAD 6 -#define NPCX_APM_DR_MIX_MIX_DATA FIELD(0, 8) -#define NPCX_APM_MIX_2_AIADCR_SEL FIELD(4, 2) -#define NPCX_APM_MIX_2_AIADCL_SEL FIELD(6, 2) -#define NPCX_APM_GCR_ADCL_GIDL FIELD(0, 6) -#define NPCX_APM_GCR_ADCL_LRGID 7 -#define NPCX_APM_GCR_ADCR_GIDR FIELD(0, 6) -#define NPCX_APM_GCR_MIXADCL_GIMIXL FIELD(0, 6) -#define NPCX_APM_GCR_MIXADCR_GIMIXR FIELD(0, 6) -#define NPCX_APM_CR_ADC_AGC_ADC_AGC_ADD FIELD(0, 6) -#define NPCX_APM_CR_ADC_AGC_ADC_AGC_LOAD 6 -#define NPCX_APM_CR_ADC_AGC_ADC_AGC_EN 7 -#define NPCX_APM_DR_ADC_AGC_ADC_AGC_DATA FIELD(0, 8) -#define NPCX_ADC_AGC_0_AGC_TARGET FIELD(2, 4) -#define NPCX_ADC_AGC_0_AGC_STEREO 6 -#define NPCX_ADC_AGC_1_HOLD FIELD(0, 4) -#define NPCX_ADC_AGC_1_NG_THR FIELD(4, 3) -#define NPCX_ADC_AGC_1_NG_EN 7 -#define NPCX_ADC_AGC_2_DCY FIELD(0, 4) -#define NPCX_ADC_AGC_2_ATK FIELD(4, 4) -#define NPCX_ADC_AGC_3_AGC_MAX FIELD(0, 5) -#define NPCX_ADC_AGC_4_AGC_MIN FIELD(0, 5) -#define NPCX_APM_CR_VAD_VAD_ADD FIELD(0, 6) -#define NPCX_APM_CR_VAD_VAD_LOAD 6 -#define NPCX_APM_CR_VAD_VAD_EN 7 -#define NPCX_APM_DR_VAD_VAD_DATA FIELD(0, 8) -#define NPCX_APM_CR_VAD_CMD_VAD_RESTART 0 -#define NPCX_APM_CR_TR_FAST_ON 7 -#define NPCX_VAD_0_VAD_INSEL FIELD(0, 2) -#define NPCX_VAD_0_VAD_DMIC_FREQ FIELD(2, 3) -#define NPCX_VAD_0_VAD_ADC_WAKEUP 5 -#define NPCX_VAD_0_ZCD_EN 6 -#define NPCX_VAD_1_VAD_POWER_SENS FIELD(0, 5) -#define NPCX_APM_CONTROL_ADD FIELD(0, 6) -#define NPCX_APM_CONTROL_LOAD 6 +#define NPCX_APM_SR_IRQ_PEND 6 +#define NPCX_APM_SR2_SMUTEIP 6 +#define NPCX_APM_ICR_INTR_MODE FIELD(6, 2) +#define NPCX_APM_IMR_VAD_DTC_MASK 6 +#define NPCX_APM_IFR_VAD_DTC 6 +#define NPCX_APM_CR_APM_PD 0 +#define NPCX_APM_CR_APM_AGC_DIS FIELD(1, 2) +#define NPCX_APM_CR_CK_MCLK_FREQ FIELD(0, 2) +#define NPCX_APM_AICR_ADC_ADC_AUDIOIF FIELD(0, 2) +#define NPCX_APM_AICR_ADC_PD_AICR_ADC 4 +#define NPCX_APM_AICR_ADC_ADC_ADWL FIELD(6, 2) +#define NPCX_APM_FCR_ADC_ADC_FREQ FIELD(0, 4) +#define NPCX_APM_FCR_ADC_ADC_WNF FIELD(4, 2) +#define NPCX_APM_FCR_ADC_ADC_HPF 6 +#define NPCX_APM_CR_DMIC_ADC_DMIC_SEL_RIGHT FIELD(0, 2) +#define NPCX_APM_CR_DMIC_ADC_DMIC_SEL_LEFT FIELD(2, 2) +#define NPCX_APM_CR_DMIC_ADC_DMIC_RATE FIELD(4, 3) +#define NPCX_APM_CR_DMIC_PD_DMIC 7 +#define NPCX_APM_CR_ADC_ADC_SOFT_MUTE 7 +#define NPCX_APM_CR_MIX_MIX_ADD FIELD(0, 6) +#define NPCX_APM_CR_MIX_MIX_LOAD 6 +#define NPCX_APM_DR_MIX_MIX_DATA FIELD(0, 8) +#define NPCX_APM_MIX_2_AIADCR_SEL FIELD(4, 2) +#define NPCX_APM_MIX_2_AIADCL_SEL FIELD(6, 2) +#define NPCX_APM_GCR_ADCL_GIDL FIELD(0, 6) +#define NPCX_APM_GCR_ADCL_LRGID 7 +#define NPCX_APM_GCR_ADCR_GIDR FIELD(0, 6) +#define NPCX_APM_GCR_MIXADCL_GIMIXL FIELD(0, 6) +#define NPCX_APM_GCR_MIXADCR_GIMIXR FIELD(0, 6) +#define NPCX_APM_CR_ADC_AGC_ADC_AGC_ADD FIELD(0, 6) +#define NPCX_APM_CR_ADC_AGC_ADC_AGC_LOAD 6 +#define NPCX_APM_CR_ADC_AGC_ADC_AGC_EN 7 +#define NPCX_APM_DR_ADC_AGC_ADC_AGC_DATA FIELD(0, 8) +#define NPCX_ADC_AGC_0_AGC_TARGET FIELD(2, 4) +#define NPCX_ADC_AGC_0_AGC_STEREO 6 +#define NPCX_ADC_AGC_1_HOLD FIELD(0, 4) +#define NPCX_ADC_AGC_1_NG_THR FIELD(4, 3) +#define NPCX_ADC_AGC_1_NG_EN 7 +#define NPCX_ADC_AGC_2_DCY FIELD(0, 4) +#define NPCX_ADC_AGC_2_ATK FIELD(4, 4) +#define NPCX_ADC_AGC_3_AGC_MAX FIELD(0, 5) +#define NPCX_ADC_AGC_4_AGC_MIN FIELD(0, 5) +#define NPCX_APM_CR_VAD_VAD_ADD FIELD(0, 6) +#define NPCX_APM_CR_VAD_VAD_LOAD 6 +#define NPCX_APM_CR_VAD_VAD_EN 7 +#define NPCX_APM_DR_VAD_VAD_DATA FIELD(0, 8) +#define NPCX_APM_CR_VAD_CMD_VAD_RESTART 0 +#define NPCX_APM_CR_TR_FAST_ON 7 +#define NPCX_VAD_0_VAD_INSEL FIELD(0, 2) +#define NPCX_VAD_0_VAD_DMIC_FREQ FIELD(2, 3) +#define NPCX_VAD_0_VAD_ADC_WAKEUP 5 +#define NPCX_VAD_0_ZCD_EN 6 +#define NPCX_VAD_1_VAD_POWER_SENS FIELD(0, 5) +#define NPCX_APM_CONTROL_ADD FIELD(0, 6) +#define NPCX_APM_CONTROL_LOAD 6 /******************************************************************************/ /* FMUL2 (Frequency Multiplier Module 2) Registers */ -#define NPCX_FMUL2_FM2CTRL REG8(NPCX_FMUL2_BASE_ADDR + 0x000) -#define NPCX_FMUL2_FM2ML REG8(NPCX_FMUL2_BASE_ADDR + 0x002) -#define NPCX_FMUL2_FM2MH REG8(NPCX_FMUL2_BASE_ADDR + 0x004) -#define NPCX_FMUL2_FM2N REG8(NPCX_FMUL2_BASE_ADDR + 0x006) -#define NPCX_FMUL2_FM2P REG8(NPCX_FMUL2_BASE_ADDR + 0x008) -#define NPCX_FMUL2_FM2_VER REG8(NPCX_FMUL2_BASE_ADDR + 0x00A) +#define NPCX_FMUL2_FM2CTRL REG8(NPCX_FMUL2_BASE_ADDR + 0x000) +#define NPCX_FMUL2_FM2ML REG8(NPCX_FMUL2_BASE_ADDR + 0x002) +#define NPCX_FMUL2_FM2MH REG8(NPCX_FMUL2_BASE_ADDR + 0x004) +#define NPCX_FMUL2_FM2N REG8(NPCX_FMUL2_BASE_ADDR + 0x006) +#define NPCX_FMUL2_FM2P REG8(NPCX_FMUL2_BASE_ADDR + 0x008) +#define NPCX_FMUL2_FM2_VER REG8(NPCX_FMUL2_BASE_ADDR + 0x00A) /******************************************************************************/ /* FMUL2 register fields */ -#define NPCX_FMUL2_FM2CTRL_LOAD2 0 -#define NPCX_FMUL2_FM2CTRL_LOCK2 2 -#define NPCX_FMUL2_FM2CTRL_FMUL2_DIS 5 -#define NPCX_FMUL2_FM2CTRL_TUNE_DIS 6 -#define NPCX_FMUL2_FM2CTRL_CLK2_CHNG 7 -#define NPCX_FMUL2_FM2N_FM2N FIELD(0, 6) -#define NPCX_FMUL2_FM2P_WFPRED FIELD(4, 4) +#define NPCX_FMUL2_FM2CTRL_LOAD2 0 +#define NPCX_FMUL2_FM2CTRL_LOCK2 2 +#define NPCX_FMUL2_FM2CTRL_FMUL2_DIS 5 +#define NPCX_FMUL2_FM2CTRL_TUNE_DIS 6 +#define NPCX_FMUL2_FM2CTRL_CLK2_CHNG 7 +#define NPCX_FMUL2_FM2N_FM2N FIELD(0, 6) +#define NPCX_FMUL2_FM2P_WFPRED FIELD(4, 4) /******************************************************************************/ /* WOV (Wake-on-Voice) Registers */ -#define NPCX_WOV_CLOCK_CNTL REG32(NPCX_WOV_BASE_ADDR + 0x000) -#define NPCX_WOV_PLL_CNTL1 REG32(NPCX_WOV_BASE_ADDR + 0x004) -#define NPCX_WOV_PLL_CNTL2 REG32(NPCX_WOV_BASE_ADDR + 0x008) -#define NPCX_WOV_FIFO_CNT REG32(NPCX_WOV_BASE_ADDR + 0x00C) -#define NPCX_WOV_FIFO_OUT REG32(NPCX_WOV_BASE_ADDR + 0x010) -#define NPCX_WOV_STATUS REG32(NPCX_WOV_BASE_ADDR + 0x014) -#define NPCX_WOV_WOV_INTEN REG32(NPCX_WOV_BASE_ADDR + 0x018) -#define NPCX_WOV_APM_CTRL REG32(NPCX_WOV_BASE_ADDR + 0x01C) -#define NPCX_WOV_I2S_CNTL(n) REG32(NPCX_WOV_BASE_ADDR + 0x020 + (4*n)) -#define NPCX_WOV_VERSION REG32(NPCX_WOV_BASE_ADDR + 0x030) +#define NPCX_WOV_CLOCK_CNTL REG32(NPCX_WOV_BASE_ADDR + 0x000) +#define NPCX_WOV_PLL_CNTL1 REG32(NPCX_WOV_BASE_ADDR + 0x004) +#define NPCX_WOV_PLL_CNTL2 REG32(NPCX_WOV_BASE_ADDR + 0x008) +#define NPCX_WOV_FIFO_CNT REG32(NPCX_WOV_BASE_ADDR + 0x00C) +#define NPCX_WOV_FIFO_OUT REG32(NPCX_WOV_BASE_ADDR + 0x010) +#define NPCX_WOV_STATUS REG32(NPCX_WOV_BASE_ADDR + 0x014) +#define NPCX_WOV_WOV_INTEN REG32(NPCX_WOV_BASE_ADDR + 0x018) +#define NPCX_WOV_APM_CTRL REG32(NPCX_WOV_BASE_ADDR + 0x01C) +#define NPCX_WOV_I2S_CNTL(n) REG32(NPCX_WOV_BASE_ADDR + 0x020 + (4 * n)) +#define NPCX_WOV_VERSION REG32(NPCX_WOV_BASE_ADDR + 0x030) /******************************************************************************/ /* WOV register fields */ -#define NPCX_WOV_CLOCK_CNT_CLK_SEL 0 -#define NPCX_WOV_CLOCK_CNT_DMIC_EN 3 -#define NPCX_WOV_CLOCK_CNT_PLL_EDIV_SEL 7 -#define NPCX_WOV_CLOCK_CNT_PLL_EDIV FIELD(8, 7) -#define NPCX_WOV_CLOCK_CNT_PLL_EDIV_DC FIELD(16, 7) -#define NPCX_WOV_CLOCK_CNT_DMIC_CKDIV_EN 24 -#define NPCX_WOV_CLOCK_CNT_DMIC_CKDIV_SEL 25 -#define NPCX_WOV_FIFO_CNT_FIFO_ITHRSH FIELD(0, 6) -#define NPCX_WOV_FIFO_CNT_FIFO_WTHRSH FIELD(6, 6) -#define NPCX_WOV_FIFO_CNT_I2S_FFRST 13 -#define NPCX_WOV_FIFO_CNT_CORE_FFRST 14 -#define NPCX_WOV_FIFO_CNT_CFIFO_ISEL FIELD(16, 3) -#define NPCX_WOV_STATUS_CFIFO_CNT FIELD(0, 8) -#define NPCX_WOV_STATUS_CFIFO_NE 8 -#define NPCX_WOV_STATUS_CFIFO_OIT 9 -#define NPCX_WOV_STATUS_CFIFO_OWT 10 -#define NPCX_WOV_STATUS_CFIFO_OVRN 11 -#define NPCX_WOV_STATUS_I2S_FIFO_OVRN 12 -#define NPCX_WOV_STATUS_I2S_FIFO_UNDRN 13 -#define NPCX_WOV_STATUS_BITS FIELD(9, 6) -#define NPCX_WOV_INTEN_VAD_INTEN 0 -#define NPCX_WOV_INTEN_VAD_WKEN 1 -#define NPCX_WOV_INTEN_CFIFO_NE_IE 8 -#define NPCX_WOV_INTEN_CFIFO_OIT_IE 9 -#define NPCX_WOV_INTEN_CFIFO_OWT_WE 10 -#define NPCX_WOV_INTEN_CFIFO_OVRN_IE 11 -#define NPCX_WOV_INTEN_I2S_FIFO_OVRN_IE 12 -#define NPCX_WOV_INTEN_I2S_FIFO_UNDRN_IE 13 -#define NPCX_WOV_APM_CTRL_APM_RST 0 -#define NPCX_WOV_PLL_CNTL1_PLL_PWDEN 0 -#define NPCX_WOV_PLL_CNTL1_PLL_OTDV1 FIELD(4, 4) -#define NPCX_WOV_PLL_CNTL1_PLL_OTDV2 FIELD(8, 4) -#define NPCX_WOV_PLL_CNTL1_PLL_LOCKI 15 -#define NPCX_WOV_PLL_CNTL2_PLL_FBDV FIELD(0, 12) -#define NPCX_WOV_PLL_CNTL2_PLL_INDV FIELD(12, 4) -#define NPCX_WOV_I2S_CNTL_I2S_BCNT FIELD(0, 5) -#define NPCX_WOV_I2S_CNTL_I2S_TRIG 5 -#define NPCX_WOV_I2S_CNTL_I2S_LBHIZ 6 -#define NPCX_WOV_I2S_CNTL_I2S_ST_DEL FIELD(7, 9) -#define NPCX_WOV_I2S_CNTL_I2S_CHAN FIELD(0, 16) -#define NPCX_WOV_I2S_CNTL0_I2S_HIZD 16 -#define NPCX_WOV_I2S_CNTL0_I2S_HIZ 17 -#define NPCX_WOV_I2S_CNTL0_I2S_SCLK_INV 18 -#define NPCX_WOV_I2S_CNTL0_I2S_OPS 19 -#define NPCX_WOV_I2S_CNTL0_I2S_OPE 20 -#define NPCX_WOV_I2S_CNTL0_I2S_IPS 21 -#define NPCX_WOV_I2S_CNTL0_I2S_IPE 22 -#define NPCX_WOV_I2S_CNTL0_I2S_TST 23 -#define NPCX_WOV_I2S_CNTL1_I2S_CHN1_DIS 24 +#define NPCX_WOV_CLOCK_CNT_CLK_SEL 0 +#define NPCX_WOV_CLOCK_CNT_DMIC_EN 3 +#define NPCX_WOV_CLOCK_CNT_PLL_EDIV_SEL 7 +#define NPCX_WOV_CLOCK_CNT_PLL_EDIV FIELD(8, 7) +#define NPCX_WOV_CLOCK_CNT_PLL_EDIV_DC FIELD(16, 7) +#define NPCX_WOV_CLOCK_CNT_DMIC_CKDIV_EN 24 +#define NPCX_WOV_CLOCK_CNT_DMIC_CKDIV_SEL 25 +#define NPCX_WOV_FIFO_CNT_FIFO_ITHRSH FIELD(0, 6) +#define NPCX_WOV_FIFO_CNT_FIFO_WTHRSH FIELD(6, 6) +#define NPCX_WOV_FIFO_CNT_I2S_FFRST 13 +#define NPCX_WOV_FIFO_CNT_CORE_FFRST 14 +#define NPCX_WOV_FIFO_CNT_CFIFO_ISEL FIELD(16, 3) +#define NPCX_WOV_STATUS_CFIFO_CNT FIELD(0, 8) +#define NPCX_WOV_STATUS_CFIFO_NE 8 +#define NPCX_WOV_STATUS_CFIFO_OIT 9 +#define NPCX_WOV_STATUS_CFIFO_OWT 10 +#define NPCX_WOV_STATUS_CFIFO_OVRN 11 +#define NPCX_WOV_STATUS_I2S_FIFO_OVRN 12 +#define NPCX_WOV_STATUS_I2S_FIFO_UNDRN 13 +#define NPCX_WOV_STATUS_BITS FIELD(9, 6) +#define NPCX_WOV_INTEN_VAD_INTEN 0 +#define NPCX_WOV_INTEN_VAD_WKEN 1 +#define NPCX_WOV_INTEN_CFIFO_NE_IE 8 +#define NPCX_WOV_INTEN_CFIFO_OIT_IE 9 +#define NPCX_WOV_INTEN_CFIFO_OWT_WE 10 +#define NPCX_WOV_INTEN_CFIFO_OVRN_IE 11 +#define NPCX_WOV_INTEN_I2S_FIFO_OVRN_IE 12 +#define NPCX_WOV_INTEN_I2S_FIFO_UNDRN_IE 13 +#define NPCX_WOV_APM_CTRL_APM_RST 0 +#define NPCX_WOV_PLL_CNTL1_PLL_PWDEN 0 +#define NPCX_WOV_PLL_CNTL1_PLL_OTDV1 FIELD(4, 4) +#define NPCX_WOV_PLL_CNTL1_PLL_OTDV2 FIELD(8, 4) +#define NPCX_WOV_PLL_CNTL1_PLL_LOCKI 15 +#define NPCX_WOV_PLL_CNTL2_PLL_FBDV FIELD(0, 12) +#define NPCX_WOV_PLL_CNTL2_PLL_INDV FIELD(12, 4) +#define NPCX_WOV_I2S_CNTL_I2S_BCNT FIELD(0, 5) +#define NPCX_WOV_I2S_CNTL_I2S_TRIG 5 +#define NPCX_WOV_I2S_CNTL_I2S_LBHIZ 6 +#define NPCX_WOV_I2S_CNTL_I2S_ST_DEL FIELD(7, 9) +#define NPCX_WOV_I2S_CNTL_I2S_CHAN FIELD(0, 16) +#define NPCX_WOV_I2S_CNTL0_I2S_HIZD 16 +#define NPCX_WOV_I2S_CNTL0_I2S_HIZ 17 +#define NPCX_WOV_I2S_CNTL0_I2S_SCLK_INV 18 +#define NPCX_WOV_I2S_CNTL0_I2S_OPS 19 +#define NPCX_WOV_I2S_CNTL0_I2S_OPE 20 +#define NPCX_WOV_I2S_CNTL0_I2S_IPS 21 +#define NPCX_WOV_I2S_CNTL0_I2S_IPE 22 +#define NPCX_WOV_I2S_CNTL0_I2S_TST 23 +#define NPCX_WOV_I2S_CNTL1_I2S_CHN1_DIS 24 /******************************************************************************/ /* PS/2 registers */ -#define NPCX_PS2_PSDAT REG8(NPCX_PS2_BASE_ADDR + 0x000) -#define NPCX_PS2_PSTAT REG8(NPCX_PS2_BASE_ADDR + 0x002) -#define NPCX_PS2_PSCON REG8(NPCX_PS2_BASE_ADDR + 0x004) -#define NPCX_PS2_PSOSIG REG8(NPCX_PS2_BASE_ADDR + 0x006) -#define NPCX_PS2_PSISIG REG8(NPCX_PS2_BASE_ADDR + 0x008) -#define NPCX_PS2_PSIEN REG8(NPCX_PS2_BASE_ADDR + 0x00A) +#define NPCX_PS2_PSDAT REG8(NPCX_PS2_BASE_ADDR + 0x000) +#define NPCX_PS2_PSTAT REG8(NPCX_PS2_BASE_ADDR + 0x002) +#define NPCX_PS2_PSCON REG8(NPCX_PS2_BASE_ADDR + 0x004) +#define NPCX_PS2_PSOSIG REG8(NPCX_PS2_BASE_ADDR + 0x006) +#define NPCX_PS2_PSISIG REG8(NPCX_PS2_BASE_ADDR + 0x008) +#define NPCX_PS2_PSIEN REG8(NPCX_PS2_BASE_ADDR + 0x00A) /* PS/2 register field */ -#define NPCX_PS2_PSTAT_SOT 0 -#define NPCX_PS2_PSTAT_EOT 1 -#define NPCX_PS2_PSTAT_PERR 2 -#define NPCX_PS2_PSTAT_ACH FIELD(3, 3) -#define NPCX_PS2_PSTAT_RFERR 6 - -#define NPCX_PS2_PSCON_EN 0 -#define NPCX_PS2_PSCON_XMT 1 -#define NPCX_PS2_PSCON_HDRV FIELD(2, 2) -#define NPCX_PS2_PSCON_IDB FIELD(4, 3) -#define NPCX_PS2_PSCON_WPUED 7 - -#define NPCX_PS2_PSOSIG_WDAT0 0 -#define NPCX_PS2_PSOSIG_WDAT1 1 -#define NPCX_PS2_PSOSIG_WDAT2 2 -#define NPCX_PS2_PSOSIG_CLK0 3 -#define NPCX_PS2_PSOSIG_CLK1 4 -#define NPCX_PS2_PSOSIG_CLK2 5 -#define NPCX_PS2_PSOSIG_WDAT3 6 -#define NPCX_PS2_PSOSIG_CLK3 7 -#define NPCX_PS2_PSOSIG_CLK(n) (((n) < NPCX_PS2_CH3) ? \ - ((n) + 3) : 7) -#define NPCX_PS2_PSOSIG_WDAT(n) (((n) < NPCX_PS2_CH3) ? \ - ((n) + 0) : 6) -#define NPCX_PS2_PSOSIG_CLK_MASK_ALL \ - (BIT(NPCX_PS2_PSOSIG_CLK0) | \ - BIT(NPCX_PS2_PSOSIG_CLK1) | \ - BIT(NPCX_PS2_PSOSIG_CLK2) | \ - BIT(NPCX_PS2_PSOSIG_CLK3)) - -#define NPCX_PS2_PSISIG_RDAT0 0 -#define NPCX_PS2_PSISIG_RDAT1 1 -#define NPCX_PS2_PSISIG_RDAT2 2 -#define NPCX_PS2_PSISIG_RCLK0 3 -#define NPCX_PS2_PSISIG_RCLK1 4 -#define NPCX_PS2_PSISIG_RCLK2 5 -#define NPCX_PS2_PSISIG_RDAT3 6 -#define NPCX_PS2_PSISIG_RCLK3 7 -#define NPCX_PS2_PSIEN_SOTIE 0 -#define NPCX_PS2_PSIEN_EOTIE 1 -#define NPCX_PS2_PSIEN_PS2_WUE 4 -#define NPCX_PS2_PSIEN_PS2_CLK_SEL 7 +#define NPCX_PS2_PSTAT_SOT 0 +#define NPCX_PS2_PSTAT_EOT 1 +#define NPCX_PS2_PSTAT_PERR 2 +#define NPCX_PS2_PSTAT_ACH FIELD(3, 3) +#define NPCX_PS2_PSTAT_RFERR 6 + +#define NPCX_PS2_PSCON_EN 0 +#define NPCX_PS2_PSCON_XMT 1 +#define NPCX_PS2_PSCON_HDRV FIELD(2, 2) +#define NPCX_PS2_PSCON_IDB FIELD(4, 3) +#define NPCX_PS2_PSCON_WPUED 7 + +#define NPCX_PS2_PSOSIG_WDAT0 0 +#define NPCX_PS2_PSOSIG_WDAT1 1 +#define NPCX_PS2_PSOSIG_WDAT2 2 +#define NPCX_PS2_PSOSIG_CLK0 3 +#define NPCX_PS2_PSOSIG_CLK1 4 +#define NPCX_PS2_PSOSIG_CLK2 5 +#define NPCX_PS2_PSOSIG_WDAT3 6 +#define NPCX_PS2_PSOSIG_CLK3 7 +#define NPCX_PS2_PSOSIG_CLK(n) (((n) < NPCX_PS2_CH3) ? ((n) + 3) : 7) +#define NPCX_PS2_PSOSIG_WDAT(n) (((n) < NPCX_PS2_CH3) ? ((n) + 0) : 6) +#define NPCX_PS2_PSOSIG_CLK_MASK_ALL \ + (BIT(NPCX_PS2_PSOSIG_CLK0) | BIT(NPCX_PS2_PSOSIG_CLK1) | \ + BIT(NPCX_PS2_PSOSIG_CLK2) | BIT(NPCX_PS2_PSOSIG_CLK3)) + +#define NPCX_PS2_PSISIG_RDAT0 0 +#define NPCX_PS2_PSISIG_RDAT1 1 +#define NPCX_PS2_PSISIG_RDAT2 2 +#define NPCX_PS2_PSISIG_RCLK0 3 +#define NPCX_PS2_PSISIG_RCLK1 4 +#define NPCX_PS2_PSISIG_RCLK2 5 +#define NPCX_PS2_PSISIG_RDAT3 6 +#define NPCX_PS2_PSISIG_RCLK3 7 +#define NPCX_PS2_PSIEN_SOTIE 0 +#define NPCX_PS2_PSIEN_EOTIE 1 +#define NPCX_PS2_PSIEN_PS2_WUE 4 +#define NPCX_PS2_PSIEN_PS2_CLK_SEL 7 #ifndef CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC extern const enum gpio_signal hibernate_wake_pins[]; @@ -1656,6 +1721,10 @@ extern enum gpio_signal hibernate_wake_pins[]; extern int hibernate_wake_pins_used; #endif +#ifndef NPCX_UART_MODULE2 +#define NPCX_UART_MODULE2 0 +#endif /* NPCX_UART_MODULE2 */ + #if defined(CHIP_FAMILY_NPCX5) #include "registers-npcx5.h" #elif defined(CHIP_FAMILY_NPCX7) diff --git a/chip/npcx/rom_chip.h b/chip/npcx/rom_chip.h index bb66f95e88..44c9c1a2a4 100644 --- a/chip/npcx/rom_chip.h +++ b/chip/npcx/rom_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -42,25 +42,23 @@ enum API_RETURN_STATUS_T { /* * Macro functions of ROM api functions */ -#define ADDR_DOWNLOAD_FROM_FLASH (*(volatile uint32_t *) 0x40) +#define ADDR_DOWNLOAD_FROM_FLASH (*(volatile uint32_t *)0x40) #define download_from_flash(src_offset, dest_addr, size, sign, exe_addr, \ - status) \ - (((download_from_flash_ptr) ADDR_DOWNLOAD_FROM_FLASH) \ - (src_offset, dest_addr, size, sign, exe_addr, status)) + status) \ + (((download_from_flash_ptr)ADDR_DOWNLOAD_FROM_FLASH)( \ + src_offset, dest_addr, size, sign, exe_addr, status)) /******************************************************************************/ /* * Declarations of ROM api functions */ -typedef void (*download_from_flash_ptr) ( +typedef void (*download_from_flash_ptr)( uint32_t src_offset, /* The offset of the data to be downloaded */ - uint32_t dest_addr, /* The address of the downloaded data in the RAM*/ - uint32_t size, /* Number of bytes to download */ + uint32_t dest_addr, /* The address of the downloaded data in the RAM*/ + uint32_t size, /* Number of bytes to download */ enum API_SIGN_OPTIONS_T sign, /* Need CRC check or not */ uint32_t exe_addr, /* jump to this address after download if not zero */ enum API_RETURN_STATUS_T *status /* Status fo download */ ); - - #endif /* __CROS_EC_ROM_CHIP_H_ */ diff --git a/chip/npcx/sha256_chip.c b/chip/npcx/sha256_chip.c new file mode 100644 index 0000000000..0f64279c3b --- /dev/null +++ b/chip/npcx/sha256_chip.c @@ -0,0 +1,143 @@ +/* + * Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SHA256 module for Chrome EC */ +#include "builtin/assert.h" +#include "common.h" +#include "sha256.h" +#include "util.h" + +enum ncl_status { + NCL_STATUS_OK = 0xA5A5, + NCL_STATUS_FAIL = 0x5A5A, + NCL_STATUS_INVALID_PARAM = 0x02, + NCL_STATUS_PARAM_NOT_SUPPORTED, + NCL_STATUS_SYSTEM_BUSY, + NCL_STATUS_AUTHENTICATION_FAIL, + NCL_STATUS_NO_RESPONSE, + NCL_STATUS_HARDWARE_ERROR, +}; + +enum ncl_sha_type { + NCL_SHA_TYPE_2_256 = 0, + NCL_SHA_TYPE_2_384 = 1, + NCL_SHA_TYPE_2_512 = 2, + NCL_SHA_TYPE_NUM +}; + +/* + * The base address of the table that holds the function pointer for each + * SHA256 API in ROM. + */ +#define NCL_SHA_BASE_ADDR 0x0000013CUL +struct ncl_sha { + /* Get the SHA context size required by SHA APIs. */ + uint32_t (*get_context_size)(void); + /* Initial SHA context. */ + enum ncl_status (*init_context)(void *ctx); + /* Finalize SHA context. */ + enum ncl_status (*finalize_context)(void *ctx); + /* Initiate the SHA hardware module and setups needed parameters. */ + enum ncl_status (*init)(void *ctx); + /* + * Prepare the context buffer for a SHA calculation - by loading the + * initial SHA-256/384/512 parameters. + */ + enum ncl_status (*start)(void *ctx, enum ncl_sha_type type); + /* + * Updates the SHA calculation with the additional data. When the + * function returns, the hardware and memory buffer shall be ready to + * accept new data * buffers for SHA calculation and changes to the data + * in data buffer should no longer effect the SHA calculation. + */ + enum ncl_status (*update)(void *ctx, const uint8_t *data, uint32_t Len); + /* Return the SHA result (digest.) */ + enum ncl_status (*finish)(void *ctx, uint8_t *hashDigest); + /* Perform a complete SHA calculation */ + enum ncl_status (*calc)(void *ctx, enum ncl_sha_type type, + const uint8_t *data, uint32_t Len, + uint8_t *hashDigest); + /* Power on/off the SHA module. */ + enum ncl_status (*power)(void *ctx, uint8_t enable); + /* Reset the SHA hardware and terminate any in-progress operations. */ + enum ncl_status (*reset)(void *ctx); +}; + +#define NCL_SHA ((const struct ncl_sha *)NCL_SHA_BASE_ADDR) + +void SHA256_init(struct sha256_ctx *ctx) +{ + NCL_SHA->init_context(ctx->handle); + NCL_SHA->power(ctx->handle, 1); + NCL_SHA->init(ctx->handle); + NCL_SHA->reset(ctx->handle); + NCL_SHA->start(ctx->handle, NCL_SHA_TYPE_2_256); +} + +void SHA256_update(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len) +{ + NCL_SHA->update(ctx->handle, data, len); +} + +void SHA256_abort(struct sha256_ctx *ctx) +{ + NCL_SHA->reset(ctx->handle); + NCL_SHA->power(ctx->handle, 0); + NCL_SHA->finalize_context(ctx->handle); +} + +uint8_t *SHA256_final(struct sha256_ctx *ctx) +{ + NCL_SHA->finish(ctx->handle, ctx->buf); + NCL_SHA->power(ctx->handle, 0); + NCL_SHA->finalize_context(ctx->handle); + return ctx->buf; +} + +static void hmac_SHA256_step(uint8_t *output, uint8_t mask, const uint8_t *key, + const int key_len, const uint8_t *data, + const int data_len) +{ + struct sha256_ctx hmac_ctx; + uint8_t *key_pad = hmac_ctx.buf; + uint8_t *tmp; + int i; + + memset(key_pad, mask, SHA256_BLOCK_SIZE); + for (i = 0; i < key_len; i++) + key_pad[i] ^= key[i]; + + SHA256_init(&hmac_ctx); + SHA256_update(&hmac_ctx, key_pad, SHA256_BLOCK_SIZE); + SHA256_update(&hmac_ctx, data, data_len); + tmp = SHA256_final(&hmac_ctx); + memcpy(output, tmp, SHA256_DIGEST_SIZE); +} +/* + * Note: When the API is called, it will consume about half of TASK_STACK_SIZE + * because a variable of structure sha256_ctx is declared in the function + * hmac_SHA256_step. + */ +void hmac_SHA256(uint8_t *output, const uint8_t *key, const int key_len, + const uint8_t *message, const int message_len) +{ + /* This code does not support key_len > block_size. */ + ASSERT(key_len <= SHA256_BLOCK_SIZE); + + /* + * i_key_pad = key (zero-padded) ^ 0x36 + * output = hash(i_key_pad || message) + * (Use output as temporary buffer) + */ + hmac_SHA256_step(output, 0x36, key, key_len, message, message_len); + + /* + * o_key_pad = key (zero-padded) ^ 0x5c + * output = hash(o_key_pad || output) + */ + hmac_SHA256_step(output, 0x5c, key, key_len, output, + SHA256_DIGEST_SIZE); +} diff --git a/chip/npcx/sha256_chip.h b/chip/npcx/sha256_chip.h new file mode 100644 index 0000000000..3c7773d112 --- /dev/null +++ b/chip/npcx/sha256_chip.h @@ -0,0 +1,25 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_SHA256_CHIP_H +#define __CROS_EC_SHA256_CHIP_H + +#include "common.h" + +#define NPCX_SHA256_HANDLE_SIZE 212 +struct sha256_ctx { + /* the context handle required for SHA256 API */ + uint8_t handle[NPCX_SHA256_HANDLE_SIZE]; + /* + * This is used to buffer: + * 1. the result (digest) of the SHA256 computation. + * 2. the 1st block input data (the key padding) for hmac_SHA256_step. + */ + uint8_t buf[SHA256_BLOCK_SIZE]; +} __aligned(4); + +void SHA256_abort(struct sha256_ctx *ctx); + +#endif /* __CROS_EC_SHA256_CHIP_H */ diff --git a/chip/npcx/shi.c b/chip/npcx/shi.c index bb2696acae..dde2243462 100644 --- a/chip/npcx/shi.c +++ b/chip/npcx/shi.c @@ -1,5 +1,5 @@ /* - * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,22 +10,23 @@ * This uses Input/Output buffer to handle SPI transmission and reception. */ +#include "builtin/assert.h" #include "chipset.h" #include "clock.h" #include "console.h" #include "gpio.h" -#include "task.h" #include "hooks.h" #include "host_command.h" #include "registers.h" #include "spi.h" #include "system.h" +#include "task.h" #include "timer.h" #include "util.h" #define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SPI, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SPI, format, ##args) #if !(DEBUG_SHI) #define DEBUG_CPUTS(...) @@ -33,48 +34,51 @@ #define DEBUG_CPRINTF(...) #else #define DEBUG_CPUTS(outstr) cputs(CC_SPI, outstr) -#define DEBUG_CPRINTS(format, args...) cprints(CC_SPI, format, ## args) -#define DEBUG_CPRINTF(format, args...) cprintf(CC_SPI, format, ## args) +#define DEBUG_CPRINTS(format, args...) cprints(CC_SPI, format, ##args) +#define DEBUG_CPRINTF(format, args...) cprintf(CC_SPI, format, ##args) #endif /* SHI Bus definition */ #ifdef NPCX_SHI_V2 -#define SHI_OBUF_FULL_SIZE 128 /* Full output buffer size */ -#define SHI_IBUF_FULL_SIZE 128 /* Full input buffer size */ +#define SHI_OBUF_FULL_SIZE 128 /* Full output buffer size */ +#define SHI_IBUF_FULL_SIZE 128 /* Full input buffer size */ /* Configure the IBUFLVL2 = the size of V3 protocol header */ #define SHI_IBUFLVL2_THRESHOLD (sizeof(struct ec_host_request)) #else -#define SHI_OBUF_FULL_SIZE 64 /* Full output buffer size */ -#define SHI_IBUF_FULL_SIZE 64 /* Full input buffer size */ +#define SHI_OBUF_FULL_SIZE 64 /* Full output buffer size */ +#define SHI_IBUF_FULL_SIZE 64 /* Full input buffer size */ #endif -#define SHI_OBUF_HALF_SIZE (SHI_OBUF_FULL_SIZE/2) /* Half output buffer size */ -#define SHI_IBUF_HALF_SIZE (SHI_IBUF_FULL_SIZE/2) /* Half input buffer size */ +#define SHI_OBUF_HALF_SIZE \ + (SHI_OBUF_FULL_SIZE / 2) /* Half output buffer size */ +#define SHI_IBUF_HALF_SIZE \ + (SHI_IBUF_FULL_SIZE / 2) /* Half input buffer size */ /* Start address of SHI output buffer */ -#define SHI_OBUF_START_ADDR (volatile uint8_t *)(NPCX_SHI_BASE_ADDR + 0x020) +#define SHI_OBUF_START_ADDR (volatile uint8_t *)(NPCX_SHI_BASE_ADDR + 0x020) /* Middle address of SHI output buffer */ -#define SHI_OBUF_HALF_ADDR (SHI_OBUF_START_ADDR + SHI_OBUF_HALF_SIZE) +#define SHI_OBUF_HALF_ADDR (SHI_OBUF_START_ADDR + SHI_OBUF_HALF_SIZE) /* Top address of SHI output buffer */ -#define SHI_OBUF_FULL_ADDR (SHI_OBUF_START_ADDR + SHI_IBUF_FULL_SIZE) +#define SHI_OBUF_FULL_ADDR (SHI_OBUF_START_ADDR + SHI_IBUF_FULL_SIZE) /* * Valid offset of SHI output buffer to write. * When SIMUL bit is set, IBUFPTR can be used instead of OBUFPTR */ -#define SHI_OBUF_VALID_OFFSET ((shi_read_buf_pointer() + \ - SHI_OUT_PREAMBLE_LENGTH) % SHI_OBUF_FULL_SIZE) +#define SHI_OBUF_VALID_OFFSET \ + ((shi_read_buf_pointer() + SHI_OUT_PREAMBLE_LENGTH) % \ + SHI_OBUF_FULL_SIZE) /* Start address of SHI input buffer */ -#define SHI_IBUF_START_ADDR (&NPCX_IBUF(0)) +#define SHI_IBUF_START_ADDR (&NPCX_IBUF(0)) /* Current address of SHI input buffer */ -#define SHI_IBUF_CUR_ADDR (SHI_IBUF_START_ADDR + shi_read_buf_pointer()) +#define SHI_IBUF_CUR_ADDR (SHI_IBUF_START_ADDR + shi_read_buf_pointer()) /* * Timeout to wait for SHI request packet * - * This affects the slowest SPI clock we can support. A delay of 8192 us - * permits a 512-byte request at 500 KHz, assuming the master starts sending - * bytes as soon as it asserts chip select. That's as slow as we would - * practically want to run the SHI interface, since running it slower - * significantly impacts firmware update times. + * This affects the slowest SPI clock we can support. A delay of 8192 + * us permits a 512-byte request at 500 KHz, assuming the controller + * starts sending bytes as soon as it asserts chip select. That's as + * slow as we would practically want to run the SHI interface, since + * running it slower significantly impacts firmware update times. */ #define SHI_CMD_RX_TIMEOUT_US 8192 @@ -106,12 +110,11 @@ */ #define SHI_PROTO3_OVERHEAD (EC_SPI_PAST_END_LENGTH + EC_SPI_FRAME_START_LENGTH) - #ifdef NPCX_SHI_BYPASS_OVER_256B /* The boundary which SHI will output invalid data on MISO. */ #define SHI_BYPASS_BOUNDARY 256 /* Increase FRAME_START_LENGTH in case shi outputs invalid FRAME_START byte */ -#undef EC_SPI_FRAME_START_LENGTH +#undef EC_SPI_FRAME_START_LENGTH #define EC_SPI_FRAME_START_LENGTH 2 #endif @@ -141,10 +144,9 @@ BUILD_ASSERT(SHI_MAX_RESPONSE_SIZE <= SHI_BYPASS_BOUNDARY); */ #define SHI_OUT_START_PAD (4 * (EC_SPI_FRAME_START_LENGTH / 4 + 1)) #define SHI_OUT_END_PAD (4 * (EC_SPI_PAST_END_LENGTH / 4 + 1)) -static uint8_t out_msg_padded[SHI_OUT_START_PAD + - SHI_MAX_RESPONSE_SIZE + +static uint8_t out_msg_padded[SHI_OUT_START_PAD + SHI_MAX_RESPONSE_SIZE + SHI_OUT_END_PAD] __aligned(4); -static uint8_t * const out_msg = +static uint8_t *const out_msg = out_msg_padded + SHI_OUT_START_PAD - EC_SPI_FRAME_START_LENGTH; static uint8_t in_msg[SHI_MAX_REQUEST_SIZE] __aligned(4); @@ -176,18 +178,18 @@ volatile enum shi_state state; /* SHI bus parameters */ struct shi_bus_parameters { - uint8_t *rx_msg; /* Entry pointer of msg rx buffer */ - uint8_t *tx_msg; /* Entry pointer of msg tx buffer */ + uint8_t *rx_msg; /* Entry pointer of msg rx buffer */ + uint8_t *tx_msg; /* Entry pointer of msg tx buffer */ volatile uint8_t *rx_buf; /* Entry pointer of receive buffer */ volatile uint8_t *tx_buf; /* Entry pointer of transmit buffer */ - uint16_t sz_received; /* Size of received data in bytes */ - uint16_t sz_sending; /* Size of sending data in bytes */ - uint16_t sz_request; /* request bytes need to receive */ - uint16_t sz_response; /* response bytes need to receive */ - timestamp_t rx_deadline; /* deadline of receiving */ - uint8_t pre_ibufstat; /* Previous IBUFSTAT value */ + uint16_t sz_received; /* Size of received data in bytes */ + uint16_t sz_sending; /* Size of sending data in bytes */ + uint16_t sz_request; /* request bytes need to receive */ + uint16_t sz_response; /* response bytes need to receive */ + timestamp_t rx_deadline; /* deadline of receiving */ + uint8_t pre_ibufstat; /* Previous IBUFSTAT value */ #ifdef NPCX_SHI_BYPASS_OVER_256B - uint16_t bytes_in_256b; /* Sent bytes in 256 bytes boundary */ + uint16_t bytes_in_256b; /* Sent bytes in 256 bytes boundary */ #endif } shi_params; @@ -222,7 +224,7 @@ static void shi_send_response_packet(struct host_packet *pkt) interrupt_disable(); if (state == SHI_STATE_PROCESSING) { /* Append our past-end byte, which we reserved space for. */ - ((uint8_t *) pkt->response)[pkt->response_size + 0] = + ((uint8_t *)pkt->response)[pkt->response_size + 0] = EC_SPI_PAST_END; /* Computing sending bytes of response */ @@ -266,8 +268,8 @@ void shi_handle_host_package(void) /* Need to receive data from buffer */ return; else { - uint16_t remain_bytes = shi_params.sz_request - - shi_params.sz_received; + uint16_t remain_bytes = + shi_params.sz_request - shi_params.sz_received; /* Read remaining bytes from input buffer directly */ if (!shi_read_inbuf_wait(remain_bytes)) @@ -287,7 +289,6 @@ void shi_handle_host_package(void) shi_packet.request_max = sizeof(in_msg); shi_packet.request_size = shi_params.sz_request; - #ifdef NPCX_SHI_BYPASS_OVER_256B /* Move FRAME_START to second byte */ out_msg[0] = EC_SPI_PROCESSING; @@ -324,7 +325,7 @@ static void shi_parse_header(void) if (in_msg[0] == EC_HOST_REQUEST_VERSION) { /* Protocol version 3 */ - struct ec_host_request *r = (struct ec_host_request *) in_msg; + struct ec_host_request *r = (struct ec_host_request *)in_msg; int pkt_size; /* * If request is over 32 bytes, @@ -357,42 +358,48 @@ static void shi_parse_header(void) /* This routine fills out all SHI output buffer with status byte */ static void shi_fill_out_status(uint8_t status) { - uint8_t offset; - uint8_t *obuf_ptr; + uint8_t start, end; + uint8_t *fill_ptr; + uint8_t *fill_end; uint8_t *obuf_end; /* Disable interrupts in case the interfere by the other interrupts */ interrupt_disable(); - offset = SHI_OBUF_VALID_OFFSET; + /* + * Fill out output buffer with status byte and leave a gap for PREAMBLE. + * The gap guarantees the synchronization. The critical section should + * be done within this gap. No racing happens. + */ + start = SHI_OBUF_VALID_OFFSET; + end = ((start + SHI_OBUF_FULL_SIZE - SHI_OUT_PREAMBLE_LENGTH) % + SHI_OBUF_FULL_SIZE); - /* Fill out all output buffer with status byte */ - obuf_ptr = (uint8_t *)SHI_OBUF_START_ADDR + offset; + fill_ptr = (uint8_t *)SHI_OBUF_START_ADDR + start; + fill_end = (uint8_t *)SHI_OBUF_START_ADDR + end; obuf_end = (uint8_t *)SHI_OBUF_START_ADDR + SHI_OBUF_FULL_SIZE; - while (obuf_ptr != obuf_end) - *(obuf_ptr++) = status; - - obuf_ptr = (uint8_t *)SHI_OBUF_START_ADDR; - obuf_end = (uint8_t *)SHI_OBUF_START_ADDR + offset; - while (obuf_ptr != obuf_end) - *(obuf_ptr++) = status; + while (fill_ptr != fill_end) { + *(fill_ptr++) = status; + if (fill_ptr == obuf_end) + fill_ptr = (uint8_t *)SHI_OBUF_START_ADDR; + } /* End of critical section */ interrupt_enable(); } #ifdef NPCX_SHI_V2 - /* - * This routine configures at which level the Input Buffer Half Full 2(IBHF2)) - * event triggers an interrupt to core. - */ +/* + * This routine configures at which level the Input Buffer Half Full 2(IBHF2)) + * event triggers an interrupt to core. + */ static void shi_sec_ibf_int_enable(int enable) { if (enable) { /* Setup IBUFLVL2 threshold and enable it */ SET_BIT(NPCX_SHICFG5, NPCX_SHICFG5_IBUFLVL2DIS); SET_FIELD(NPCX_SHICFG5, NPCX_SHICFG5_IBUFLVL2, - SHI_IBUFLVL2_THRESHOLD); + SHI_IBUFLVL2_THRESHOLD); CLEAR_BIT(NPCX_SHICFG5, NPCX_SHICFG5_IBUFLVL2DIS); /* Enable IBHF2 event */ SET_BIT(NPCX_EVENABLE2, NPCX_EVENABLE2_IBHF2EN); @@ -430,9 +437,9 @@ static int shi_is_cs_glitch(void) */ static void shi_write_half_outbuf(void) { - const uint8_t size = MIN(SHI_OBUF_HALF_SIZE, - shi_params.sz_response - - shi_params.sz_sending); + const uint8_t size = + MIN(SHI_OBUF_HALF_SIZE, + shi_params.sz_response - shi_params.sz_sending); uint8_t *obuf_ptr = (uint8_t *)shi_params.tx_buf; const uint8_t *obuf_end = obuf_ptr + size; uint8_t *msg_ptr = shi_params.tx_msg; @@ -462,8 +469,8 @@ static void shi_write_first_pkg_outbuf(uint16_t szbytes) * If response package is across 256 bytes boundary, * bypass needs to extend PROCESSING bytes after reaching the boundary. */ - if (shi_params.bytes_in_256b + SHI_OBUF_FULL_SIZE + szbytes - > SHI_BYPASS_BOUNDARY) { + if (shi_params.bytes_in_256b + SHI_OBUF_FULL_SIZE + szbytes > + SHI_BYPASS_BOUNDARY) { state = SHI_STATE_WAIT_ALIGNMENT; /* Set pointer of output buffer to the start address */ shi_params.tx_buf = SHI_OBUF_START_ADDR; @@ -479,7 +486,7 @@ static void shi_write_first_pkg_outbuf(uint16_t szbytes) /* Fill up to OBUF mid point, or OBUF end */ size = MIN(SHI_OBUF_HALF_SIZE - (offset % SHI_OBUF_HALF_SIZE), - szbytes - shi_params.sz_sending); + szbytes - shi_params.sz_sending); obuf_end = obuf_ptr + size; while (obuf_ptr != obuf_end) *(obuf_ptr++) = *(msg_ptr++); @@ -514,8 +521,8 @@ static void shi_read_half_inbuf(void) /* Restore data to msg buffer */ *(shi_params.rx_msg++) = *(shi_params.rx_buf++); shi_params.sz_received++; - } while (shi_params.sz_received % SHI_IBUF_HALF_SIZE - && shi_params.sz_received != shi_params.sz_request); + } while (shi_params.sz_received % SHI_IBUF_HALF_SIZE && + shi_params.sz_received != shi_params.sz_request); } /* @@ -595,7 +602,7 @@ static void shi_handle_cs_assert(void) if (state == SHI_STATE_DISABLED) return; - /* SHI V2 module filters cs glitch by hardware automatically */ + /* SHI V2 module filters cs glitch by hardware automatically */ #ifndef NPCX_SHI_V2 /* * IBUFSTAT resets on the 7th clock cycle after CS assertion, which @@ -645,7 +652,7 @@ static void shi_handle_cs_assert(void) } /* This routine handles all interrupts of this module */ -void shi_int_handler(void) +static void shi_int_handler(void) { uint8_t stat_reg; #ifdef NPCX_SHI_V2 @@ -719,7 +726,7 @@ void shi_int_handler(void) DEBUG_CPRINTF("CNL-"); return; - /* Next transaction but we're not ready */ + /* Next transaction but we're not ready */ } else if (state == SHI_STATE_CNL_RESP_NOT_RDY) return; @@ -748,8 +755,8 @@ void shi_int_handler(void) return shi_handle_host_package(); } else if (state == SHI_STATE_SENDING) { /* Write data from msg buffer to output buffer */ - if (shi_params.tx_buf == SHI_OBUF_START_ADDR + - SHI_OBUF_FULL_SIZE) { + if (shi_params.tx_buf == + SHI_OBUF_START_ADDR + SHI_OBUF_FULL_SIZE) { /* Write data from bottom address again */ shi_params.tx_buf = SHI_OBUF_START_ADDR; return shi_write_half_outbuf(); @@ -764,8 +771,8 @@ void shi_int_handler(void) * If pointer of output buffer will reach 256 bytes * boundary soon, start to fill response data. */ - if (shi_params.bytes_in_256b == SHI_BYPASS_BOUNDARY - - SHI_OBUF_FULL_SIZE) { + if (shi_params.bytes_in_256b == + SHI_BYPASS_BOUNDARY - SHI_OBUF_FULL_SIZE) { state = SHI_STATE_SENDING; DEBUG_CPRINTF("SND-"); return shi_write_half_outbuf(); @@ -799,8 +806,9 @@ void shi_int_handler(void) if (IS_BIT_SET(stat_reg, NPCX_EVSTAT_IBF)) { #ifdef NPCX_SHI_BYPASS_OVER_256B /* Record the sent bytes within 256B boundary */ - shi_params.bytes_in_256b = (shi_params.bytes_in_256b + - SHI_OBUF_FULL_SIZE) % SHI_BYPASS_BOUNDARY; + shi_params.bytes_in_256b = + (shi_params.bytes_in_256b + SHI_OBUF_FULL_SIZE) % + SHI_BYPASS_BOUNDARY; #endif if (state == SHI_STATE_RECEIVING) { /* read data from input to msg buffer */ @@ -810,16 +818,16 @@ void shi_int_handler(void) return shi_handle_host_package(); } else if (state == SHI_STATE_SENDING) /* Write data from msg buffer to output buffer */ - if (shi_params.tx_buf == SHI_OBUF_START_ADDR + - SHI_OBUF_HALF_SIZE) + if (shi_params.tx_buf == + SHI_OBUF_START_ADDR + SHI_OBUF_HALF_SIZE) return shi_write_half_outbuf(); else /* ignore it */ return; else if (state == SHI_STATE_PROCESSING #ifdef NPCX_SHI_BYPASS_OVER_256B - || state == SHI_STATE_WAIT_ALIGNMENT + || state == SHI_STATE_WAIT_ALIGNMENT #endif - ) + ) /* Wait for host handles request */ return; else @@ -844,7 +852,6 @@ void shi_cs_event(enum gpio_signal signal) #else shi_handle_cs_assert(); #endif - } /*****************************************************************************/ @@ -885,7 +892,7 @@ static void shi_reset_prepare(void) */ for (i = 1; i < SHI_OBUF_FULL_SIZE; i++) NPCX_OBUF(i) = EC_SPI_RECEIVING; - NPCX_OBUF(0) = EC_SPI_OLD_READY; + NPCX_OBUF(0) = EC_SPI_RX_READY; /* Enable SHI & WEN functionality */ NPCX_SHICFG1 = 0x85; @@ -954,9 +961,7 @@ static void shi_reenable_on_sysjump(void) shi_enable(); } /* Call hook after chipset sets initial power state */ -DECLARE_HOOK(HOOK_INIT, - shi_reenable_on_sysjump, - HOOK_PRIO_INIT_CHIPSET + 1); +DECLARE_HOOK(HOOK_INIT, shi_reenable_on_sysjump, HOOK_PRIO_POST_CHIPSET); /* Disable SHI bus */ static void shi_disable(void) @@ -1070,7 +1075,7 @@ static enum ec_status shi_get_protocol_info(struct host_cmd_handler_args *args) args->response_size = sizeof(*r); - return EC_SUCCESS; + return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, shi_get_protocol_info, -EC_VER_MASK(0)); + EC_VER_MASK(0)); diff --git a/chip/npcx/shi_chip.h b/chip/npcx/shi_chip.h index f701067715..9d41a2dcab 100644 --- a/chip/npcx/shi_chip.h +++ b/chip/npcx/shi_chip.h @@ -1,14 +1,13 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* NPCX-specific SHI module for Chrome EC */ -#ifndef SHI_CHIP_H_ -#define SHI_CHIP_H_ +#ifndef __CROS_EC_SHI_CHIP_H_ +#define __CROS_EC_SHI_CHIP_H_ -#ifdef CONFIG_HOSTCMD_SPS /** * Called when the NSS level changes, signalling the start of a SHI * transaction. @@ -19,6 +18,5 @@ void shi_cs_event(enum gpio_signal signal); #ifdef NPCX_SHI_V2 void shi_cs_gpio_int(enum gpio_signal signal); #endif -#endif -#endif /* SHI_CHIP_H_ */ +#endif /* __CROS_EC_SHI_CHIP_H_ */ diff --git a/chip/npcx/sib.c b/chip/npcx/sib.c index b8e2e17955..e8dbd5039d 100644 --- a/chip/npcx/sib.c +++ b/chip/npcx/sib.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,7 +19,7 @@ * For eSPI - it is 200 us. * For LPC - it is 5 us. */ -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI #define HOST_TRANSACTION_TIMEOUT_US 200 #else #define HOST_TRANSACTION_TIMEOUT_US 5 @@ -28,7 +28,7 @@ /* Console output macros */ #ifdef DEBUG_SIB #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) #else #define CPUTS(...) #define CPRINTS(...) @@ -110,8 +110,7 @@ uint8_t sib_read_kbc_reg(uint8_t io_offset) } /* Super-IO read/write function */ -void sib_write_reg(uint8_t io_offset, uint8_t index_value, - uint8_t io_data) +void sib_write_reg(uint8_t io_offset, uint8_t index_value, uint8_t io_data) { /* Disable interrupts */ interrupt_disable(); @@ -132,7 +131,7 @@ void sib_write_reg(uint8_t io_offset, uint8_t index_value, sib_wait_host_write_done(); /* Specify the io_offset A0 = 1. the data register is accessed */ - NPCX_IHIOA = io_offset+1; + NPCX_IHIOA = io_offset + 1; /* Write the data. This starts the write access to the host module */ NPCX_IHD = io_data; /* Wait while Core write operation is in progress */ @@ -170,7 +169,7 @@ uint8_t sib_read_reg(uint8_t io_offset, uint8_t index_value) sib_wait_host_write_done(); /* Specify the io_offset A0 = 1. the data register is accessed */ - NPCX_IHIOA = io_offset+1; + NPCX_IHIOA = io_offset + 1; /* Start a Core read from host module */ SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD); /* Wait while Core read operation is in progress */ @@ -188,4 +187,3 @@ uint8_t sib_read_reg(uint8_t io_offset, uint8_t index_value) return data_value; } - diff --git a/chip/npcx/sib_chip.h b/chip/npcx/sib_chip.h index 2341f219b4..570fe6b0ec 100644 --- a/chip/npcx/sib_chip.h +++ b/chip/npcx/sib_chip.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,17 +7,15 @@ /* NPCX-specific SIB module for Chrome EC */ /* Super-IO index and register definitions */ -#define INDEX_SID 0x20 -#define INDEX_CHPREV 0x24 -#define INDEX_SRID 0x27 +#define INDEX_SID 0x20 +#define INDEX_CHPREV 0x24 +#define INDEX_SRID 0x27 -#define SIO_OFFSET 0x4E +#define SIO_OFFSET 0x4E /* Super-IO register write function */ -void sib_write_reg(uint8_t io_offset, uint8_t index_value, - uint8_t io_data); +void sib_write_reg(uint8_t io_offset, uint8_t index_value, uint8_t io_data); /* Super-IO register read function */ uint8_t sib_read_reg(uint8_t io_offset, uint8_t index_value); /* Emulate host to read Keyboard I/O */ uint8_t sib_read_kbc_reg(uint8_t io_offset); - diff --git a/chip/npcx/spi.c b/chip/npcx/spi.c index 6ac8fe1b9e..f33dfae028 100644 --- a/chip/npcx/spi.c +++ b/chip/npcx/spi.c @@ -1,15 +1,15 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* SPI module for Chrome EC */ +#include "clock.h" +#include "clock_chip.h" #include "console.h" #include "gpio.h" #include "hooks.h" -#include "clock.h" -#include "clock_chip.h" #include "registers.h" #include "spi.h" #include "task.h" @@ -22,11 +22,14 @@ #define CPRINTS(...) #else #define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) #endif -/* SPI IP as SPI master */ -#define SPI_CLK 8000000 +/* SPI IP as SPI controller */ +#define SPI_CLK 8000000 + +static struct mutex spi_lock; + /** * Clear SPI data buffer. * @@ -49,32 +52,32 @@ static void clear_databuf(void) */ void spi_freq_changed(void) { - uint8_t prescaler_divider = 0; + uint8_t prescaler_divider = 0; /* Set clock prescaler divider to SPI module*/ - prescaler_divider = (uint8_t)((uint32_t)clock_get_apb2_freq() - / 2 / SPI_CLK); + prescaler_divider = + (uint8_t)((uint32_t)clock_get_apb2_freq() / 2 / SPI_CLK); if (prescaler_divider >= 1) prescaler_divider = prescaler_divider - 1; if (prescaler_divider > 0x7F) prescaler_divider = 0x7F; /* Set core clock division factor in order to obtain the SPI clock */ - NPCX_SPI_CTL1 = (NPCX_SPI_CTL1&(~(((1<<7)-1)<gpio_cs; + /* Make sure CS# is in GPIO output mode. */ + gpio_set_flags(gpio, GPIO_OUTPUT); + /* Make sure CS# is deselected */ + gpio_set_level(gpio, 1); + /* Enabling spi module */ SET_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_SPIEN); } else { /* Disabling spi module */ CLEAR_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_SPIEN); - for (i = 0; i < spi_devices_used; i++) { - if (spi_devices[i].port != port) - continue; - gpio = spi_devices[i].gpio_cs; - /* Make sure CS# is deselected */ - gpio_set_level(gpio, 1); - gpio_set_flags(gpio, GPIO_ODR_HIGH); - } + gpio = spi_device->gpio_cs; + /* Make sure CS# is deselected */ + gpio_set_level(gpio, 1); + gpio_set_flags(gpio, GPIO_ODR_HIGH); /* Disabling spi module for gpio configuration */ gpio_config_module(MODULE_SPI, 0); /* GPIO No SPI Select */ @@ -113,31 +109,13 @@ int spi_enable(int port, int enable) return EC_SUCCESS; } - -/** - * Flush an SPI transaction and receive data from slave. - * - * @param spi_device device to talk to - * @param txdata transfer data - * @param txlen transfer length - * @param rxdata receive data - * @param rxlen receive length - * @return success - * @notes set master transaction mode in npcx chip - */ -int spi_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) +int spi_transaction_async(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) { int i = 0; enum gpio_signal gpio = spi_device->gpio_cs; - static struct mutex spi_lock; - mutex_lock(&spi_lock); - /* Make sure CS# is a GPIO output mode. */ - gpio_set_flags(gpio, GPIO_OUTPUT); - /* Make sure CS# is deselected */ - gpio_set_level(gpio, 1); /* Cleaning junk data in the buffer */ clear_databuf(); /* Assert CS# to start transaction */ @@ -151,14 +129,24 @@ int spi_transaction(const struct spi_device_t *spi_device, while (IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_BSY)) ; /* Write the data */ - NPCX_SPI_DATA = txdata[i]; + NPCX_SPI_DATA = txdata[i]; CPRINTS("txdata[i]=%x", txdata[i]); /* Waiting till reading is finished */ while (!IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_RBF)) ; - /* Reading the (unused) data */ - clear_databuf(); + + if (rxlen == SPI_READBACK_ALL) { + rxdata[i] = (uint8_t)NPCX_SPI_DATA; + CPRINTS("rxdata[i]=%x", rxdata[i]); + } else { + /* Reading the (unused) data to empty the read buffer */ + clear_databuf(); + } } + + if (rxlen == SPI_READBACK_ALL) + return EC_SUCCESS; + CPRINTS("write end"); /* Reading the data */ for (i = 0; i < rxlen; ++i) { @@ -166,7 +154,7 @@ int spi_transaction(const struct spi_device_t *spi_device, while (IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_BSY)) ; /* Write the (unused) data */ - NPCX_SPI_DATA = 0; + NPCX_SPI_DATA = 0; /* Wait till reading is finished */ while (!IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_RBF)) ; @@ -174,13 +162,53 @@ int spi_transaction(const struct spi_device_t *spi_device, rxdata[i] = (uint8_t)NPCX_SPI_DATA; CPRINTS("rxdata[i]=%x", rxdata[i]); } + + return EC_SUCCESS; +} + +int spi_transaction_flush(const struct spi_device_t *spi_device) +{ + enum gpio_signal gpio = spi_device->gpio_cs; + + /* Making sure if the SPI transaction already finishes */ + while (IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_BSY)) + ; /* Deassert CS# (high) to end transaction */ gpio_set_level(gpio, 1); - mutex_unlock(&spi_lock); return EC_SUCCESS; } +int spi_transaction_wait(const struct spi_device_t *spi_device) +{ + return EC_SUCCESS; +} + +/** + * Flush an SPI transaction and receive data from peripheral. + * + * @param spi_device device to talk to + * @param txdata transfer data + * @param txlen transfer length + * @param rxdata receive data + * @param rxlen receive length + * @return success + * @notes set controller transaction mode in npcx chip + */ +int spi_transaction(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) +{ + int rv; + + mutex_lock(&spi_lock); + rv = spi_transaction_async(spi_device, txdata, txlen, rxdata, rxlen); + rv |= spi_transaction_flush(spi_device); + mutex_unlock(&spi_lock); + + return rv; +} + /** * SPI initial. * @@ -192,11 +220,11 @@ static void spi_init(void) int i; /* Enable clock for SPI peripheral */ clock_enable_peripheral(CGC_OFFSET_SPI, CGC_SPI_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); + CGC_MODE_RUN | CGC_MODE_SLEEP); /* Disabling spi module */ for (i = 0; i < spi_devices_used; i++) - spi_enable(spi_devices[i].port, 0); + spi_enable(&spi_devices[i], 0); /* Disabling spi irq */ CLEAR_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_EIR); @@ -213,8 +241,8 @@ static void spi_init(void) CLEAR_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_SCIDL); CPRINTS("nSPI_COMP=%x", IS_BIT_SET(NPCX_STRPST, NPCX_STRPST_SPI_COMP)); - CPRINTS("SPI_SP_SEL=%x", IS_BIT_SET(NPCX_DEV_CTL4, - NPCX_DEV_CTL4_SPI_SP_SEL)); + CPRINTS("SPI_SP_SEL=%x", + IS_BIT_SET(NPCX_DEV_CTL4, NPCX_DEV_CTL4_SPI_SP_SEL)); /* Cleaning junk data in the buffer */ clear_databuf(); } @@ -224,7 +252,7 @@ DECLARE_HOOK(HOOK_INIT, spi_init, HOOK_PRIO_INIT_SPI); /* Console commands */ #ifdef CONFIG_CMD_SPI_FLASH static int printrx(const char *desc, const uint8_t *txdata, int txlen, - int rxlen) + int rxlen) { uint8_t rxdata[32]; int rv; @@ -241,15 +269,15 @@ static int printrx(const char *desc, const uint8_t *txdata, int txlen, return EC_SUCCESS; } -static int command_spirom(int argc, char **argv) +static int command_spirom(int argc, const char **argv) { - uint8_t txmandev[] = {0x90, 0x00, 0x00, 0x00}; - uint8_t txjedec[] = {0x9f}; - uint8_t txunique[] = {0x4b, 0x00, 0x00, 0x00, 0x00}; - uint8_t txsr1[] = {0x05}; - uint8_t txsr2[] = {0x35}; + uint8_t txmandev[] = { 0x90, 0x00, 0x00, 0x00 }; + uint8_t txjedec[] = { 0x9f }; + uint8_t txunique[] = { 0x4b, 0x00, 0x00, 0x00, 0x00 }; + uint8_t txsr1[] = { 0x05 }; + uint8_t txsr2[] = { 0x35 }; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(SPI_FLASH_DEVICE, 1); printrx("Man/Dev ID", txmandev, sizeof(txmandev), 2); printrx("JEDEC ID", txjedec, sizeof(txjedec), 3); @@ -257,11 +285,10 @@ static int command_spirom(int argc, char **argv) printrx("Status reg 1", txsr1, sizeof(txsr1), 1); printrx("Status reg 2", txsr2, sizeof(txsr2), 1); - spi_enable(CONFIG_SPI_FLASH_PORT, 0); + spi_enable(SPI_FLASH_DEVICE, 0); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(spirom, command_spirom, - NULL, - "Test reading SPI EEPROM"); +DECLARE_CONSOLE_COMMAND(spirom, command_spirom, NULL, + "Test reading SPI EEPROM"); #endif diff --git a/chip/npcx/spiflashfw/monitor_hdr.c b/chip/npcx/spiflashfw/monitor_hdr.c index 219a037d27..09606c4c31 100644 --- a/chip/npcx/spiflashfw/monitor_hdr.c +++ b/chip/npcx/spiflashfw/monitor_hdr.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -20,7 +20,7 @@ const struct monitor_header_tag monitor_hdr = { * programed into the SPI flash. */ CONFIG_PROGRAM_MEMORY_BASE, - /* 0x0C:The Flash start address to be programmed*/ +/* 0x0C:The Flash start address to be programmed*/ #ifdef SECTION_IS_RO /* Default: RO image is programed from the start of SPI flash */ CONFIG_EC_PROTECTED_STORAGE_OFF, diff --git a/chip/npcx/spiflashfw/npcx_monitor.c b/chip/npcx/spiflashfw/npcx_monitor.c index cd52e7a80f..0d8530a456 100644 --- a/chip/npcx/spiflashfw/npcx_monitor.c +++ b/chip/npcx/spiflashfw/npcx_monitor.c @@ -1,16 +1,17 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * NPCX SoC spi flash update tool - monitor firmware */ -#include #include "config.h" #include "npcx_monitor.h" #include "registers.h" #include "util.h" +#include + /*****************************************************************************/ /* spi flash internal functions */ void sspi_flash_pinmux(int enable) @@ -49,7 +50,7 @@ void sspi_flash_execute_cmd(uint8_t code, uint8_t cts) /* set UMA_CODE */ NPCX_UMA_CODE = code; /* execute UMA flash transaction */ - NPCX_UMA_CTS = cts; + NPCX_UMA_CTS = cts; while (IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) ; } @@ -76,7 +77,7 @@ void sspi_flash_wait_ready(void) sspi_flash_execute_cmd(CMD_READ_STATUS_REG, MASK_CMD_ONLY); do { /* Read status register */ - NPCX_UMA_CTS = MASK_RD_1BYTE; + NPCX_UMA_CTS = MASK_RD_1BYTE; while (IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) ; } while (NPCX_UMA_DB0 & mask); /* Wait for Busy clear */ @@ -108,7 +109,7 @@ void sspi_flash_set_address(uint32_t dest_addr) } void sspi_flash_burst_write(unsigned int dest_addr, unsigned int bytes, - const char *data) + const char *data) { unsigned int i; /* Chip Select down. */ @@ -197,7 +198,7 @@ void sspi_flash_physical_erase(int offset, int size) /* Alignment has been checked in upper layer */ for (; size > 0; size -= NPCX_MONITOR_FLASH_ERASE_SIZE, - offset += NPCX_MONITOR_FLASH_ERASE_SIZE) { + offset += NPCX_MONITOR_FLASH_ERASE_SIZE) { /* Enable write */ sspi_flash_write_enable(); /* Set erase address */ @@ -221,7 +222,7 @@ int sspi_flash_verify(int offset, int size, const char *data) uint8_t cmp_data; ptr_flash = (uint8_t *)(CONFIG_MAPPED_STORAGE_BASE + offset); - ptr_mram = (uint8_t *)data; + ptr_mram = (uint8_t *)data; result = 1; /* Disable tri-state */ @@ -255,12 +256,11 @@ int sspi_flash_get_image_used(const char *fw_base) for (size--; size > 0 && image[size] != 0xea; size--) ; - return size ? size + 1 : 0; /* 0xea byte IS part of the image */ - + return size ? size + 1 : 0; /* 0xea byte IS part of the image */ } /* Entry function of spi upload function */ -uint32_t __attribute__ ((section(".startup_text"))) +uint32_t __attribute__((section(".startup_text"))) sspi_flash_upload(int spi_offset, int spi_size) { /* @@ -315,7 +315,7 @@ sspi_flash_upload(int spi_offset, int spi_size) /* Start to write */ if (image_base != NULL) sspi_flash_physical_write(spi_offset, sz_image, - image_base); + image_base); /* Verify data */ if (sspi_flash_verify(spi_offset, sz_image, image_base)) *flag_upload |= 0x02; @@ -335,4 +335,3 @@ sspi_flash_upload(int spi_offset, int spi_size) for (;;) ; } - diff --git a/chip/npcx/spiflashfw/npcx_monitor.h b/chip/npcx/spiflashfw/npcx_monitor.h index f4f30454d2..54303958d6 100644 --- a/chip/npcx/spiflashfw/npcx_monitor.h +++ b/chip/npcx/spiflashfw/npcx_monitor.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,11 +7,11 @@ #include -#define NPCX_MONITOR_UUT_TAG 0xA5075001 -#define NPCX_MONITOR_HEADER_ADDR 0x200C3000 +#define NPCX_MONITOR_UUT_TAG 0xA5075001 +#define NPCX_MONITOR_HEADER_ADDR 0x200C3000 /* Flag to record the progress of programming SPI flash */ -#define SPI_PROGRAMMING_FLAG 0x200C4000 +#define SPI_PROGRAMMING_FLAG 0x200C4000 struct monitor_header_tag { /* offset 0x00: TAG NPCX_MONITOR_TAG */ @@ -23,9 +23,9 @@ struct monitor_header_tag { /* offset 0x0C: The Flash address to be programmed (Absolute address) */ uint32_t dest_addr; /* offset 0x10: Maximum allowable flash clock frequency */ - uint8_t max_clock; + uint8_t max_clock; /* offset 0x11: SPI Flash read mode */ - uint8_t read_mode; + uint8_t read_mode; /* offset 0x12: Reserved */ uint16_t reserved; } __packed; diff --git a/chip/npcx/spiflashfw/npcx_monitor.ld b/chip/npcx/spiflashfw/npcx_monitor.ld index 03e38b0609..434945b04c 100644 --- a/chip/npcx/spiflashfw/npcx_monitor.ld +++ b/chip/npcx/spiflashfw/npcx_monitor.ld @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -49,4 +49,5 @@ SECTIONS */ _sidata = _etext; + /DISCARD/ : { *(.ARM.*) } } diff --git a/chip/npcx/system-npcx5.c b/chip/npcx/system-npcx5.c index 4dd12fbae2..08aafe422d 100644 --- a/chip/npcx/system-npcx5.c +++ b/chip/npcx/system-npcx5.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,7 @@ #include /* System module driver depends on chip series for Chrome EC */ +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "cpu.h" @@ -39,9 +40,9 @@ void system_mpu_config(void) CPU_MPU_CTRL = 0x7; /* Create a new MPU Region to allow execution from low-power ram */ - CPU_MPU_RNR = REGION_CHIP_RESERVED; + CPU_MPU_RNR = REGION_CHIP_RESERVED; CPU_MPU_RASR = CPU_MPU_RASR & 0xFFFFFFFE; /* Disable region */ - CPU_MPU_RBAR = CONFIG_LPRAM_BASE; /* Set region base address */ + CPU_MPU_RBAR = CONFIG_LPRAM_BASE; /* Set region base address */ /* * Set region size & attribute and enable region * [31:29] - Reserved. @@ -61,7 +62,7 @@ void system_mpu_config(void) /** * hibernate function in low power ram for npcx5 series. */ -noreturn void __keep __attribute__ ((section(".lowpower_ram"))) +noreturn void __keep __attribute__((section(".lowpower_ram"))) __enter_hibernate_in_lpram(void) { /* @@ -69,10 +70,8 @@ __enter_hibernate_in_lpram(void) * Our bypass needs stack instructions but FW will turn off main ram * later for better power consumption. */ - asm ( - "ldr r0, =0x40001800\n" - "mov sp, r0\n" - ); + asm("ldr r0, =0x40001800\n" + "mov sp, r0\n"); /* Disable Code RAM first */ SET_BIT(NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_5), NPCX_PWDWN_CTL5_MRFSH_DIS); @@ -88,13 +87,12 @@ __enter_hibernate_in_lpram(void) * wake-up from deep idle. * Workaround: Apply the same bypass of idle but don't enable interrupt. */ - asm ( - "push {r0-r5}\n" /* Save needed registers */ - "ldr r0, =0x40001600\n" /* Set r0 to Suspend RAM addr */ - "wfi\n" /* Wait for int to enter idle */ - "ldm r0, {r0-r5}\n" /* Add a delay after WFI */ - "pop {r0-r5}\n" /* Restore regs before enabling ints */ - "isb\n" /* Flush the cpu pipeline */ + asm("push {r0-r5}\n" /* Save needed registers */ + "ldr r0, =0x40001600\n" /* Set r0 to Suspend RAM addr */ + "wfi\n" /* Wait for int to enter idle */ + "ldm r0, {r0-r5}\n" /* Add a delay after WFI */ + "pop {r0-r5}\n" /* Restore regs before enabling ints */ + "isb\n" /* Flush the cpu pipeline */ ); /* RTC wake-up */ @@ -129,7 +127,7 @@ void __hibernate_npcx_series(void) { int i; void (*__hibernate_in_lpram)(void) = - (void(*)(void))(__lpram_fw_start | 0x01); + (void (*)(void))(__lpram_fw_start | 0x01); /* Enable power for the Low Power RAM */ CLEAR_BIT(NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_6), 6); @@ -140,7 +138,7 @@ void __hibernate_npcx_series(void) /* Copy the __enter_hibernate_in_lpram instructions to LPRAM */ for (i = 0; i < &__flash_lpfw_end - &__flash_lpfw_start; i++) *((uint32_t *)__lpram_fw_start + i) = - *(&__flash_lpfw_start + i); + *(&__flash_lpfw_start + i); /* execute hibernate func in LPRAM */ __hibernate_in_lpram(); @@ -148,7 +146,7 @@ void __hibernate_npcx_series(void) #ifdef CONFIG_EXTERNAL_STORAGE /* Sysjump utilities in low power ram for npcx5 series. */ -noreturn void __keep __attribute__ ((section(".lowpower_ram2"))) +noreturn void __keep __attribute__((section(".lowpower_ram2"))) __start_gdma(uint32_t exeAddr) { /* Enable GDMA now */ @@ -159,7 +157,7 @@ __start_gdma(uint32_t exeAddr) /* Wait for transfer to complete/fail */ while (!IS_BIT_SET(NPCX_GDMA_CTL, NPCX_GDMA_CTL_TC) && - !IS_BIT_SET(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAERR)) + !IS_BIT_SET(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAERR)) ; /* Disable GDMA now */ @@ -186,7 +184,7 @@ __start_gdma(uint32_t exeAddr) /* Bypass for GMDA issue of ROM api utilities only on npcx5 series. */ void system_download_from_flash(uint32_t srcAddr, uint32_t dstAddr, - uint32_t size, uint32_t exeAddr) + uint32_t size, uint32_t exeAddr) { int i; uint8_t chunkSize = 16; /* 4 data burst mode. ie.16 bytes */ @@ -195,7 +193,7 @@ void system_download_from_flash(uint32_t srcAddr, uint32_t dstAddr, * it's a thumb branch for cortex-m series CPU. */ void (*__start_gdma_in_lpram)(uint32_t) = - (void(*)(uint32_t))(__lpram_lfw_start | 0x01); + (void (*)(uint32_t))(__lpram_lfw_start | 0x01); /* * Before enabling burst mode for better performance of GDMA, it's @@ -203,7 +201,7 @@ void system_download_from_flash(uint32_t srcAddr, uint32_t dstAddr, * are 16 bytes aligned in case failure occurs. */ ASSERT((size % chunkSize) == 0 && (srcAddr % chunkSize) == 0 && - (dstAddr % chunkSize) == 0); + (dstAddr % chunkSize) == 0); /* Check valid address for jumpiing */ ASSERT(exeAddr != 0x0); @@ -253,7 +251,7 @@ void system_download_from_flash(uint32_t srcAddr, uint32_t dstAddr, /* Copy the __start_gdma_in_lpram instructions to LPRAM */ for (i = 0; i < &__flash_lplfw_end - &__flash_lplfw_start; i++) *((uint32_t *)__lpram_lfw_start + i) = - *(&__flash_lplfw_start + i); + *(&__flash_lplfw_start + i); /* Start GDMA in Suspend RAM */ __start_gdma_in_lpram(exeAddr); diff --git a/chip/npcx/system-npcx7.c b/chip/npcx/system-npcx7.c index 89b3e25e9b..386544ed04 100644 --- a/chip/npcx/system-npcx7.c +++ b/chip/npcx/system-npcx7.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,73 +6,35 @@ #include /* System module driver depends on chip series for Chrome EC */ +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "cpu.h" #include "ec_commands.h" +#include "gpio.h" #include "hooks.h" +#include "hwtimer_chip.h" #include "lct_chip.h" #include "registers.h" +#include "rom_chip.h" #include "system.h" +#include "system_chip.h" #include "task.h" #include "util.h" -#include "gpio.h" -#include "hwtimer_chip.h" -#include "mpu.h" -#include "system_chip.h" -#include "rom_chip.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) /* Macros for last 32K ram block */ #define LAST_RAM_BLK ((NPCX_RAM_SIZE / (32 * 1024)) - 1) /* Higher bits are reserved and need to be masked */ -#define RAM_PD_MASK (~BIT(LAST_RAM_BLK)) +#define RAM_PD_MASK (~BIT(LAST_RAM_BLK)) -#ifdef CONFIG_WORKAROUND_FLASH_DOWNLOAD_API -#define LFW_OFFSET 0x160 -/* Begin address of Suspend RAM for little FW (GDMA utilities). */ -uintptr_t __lpram_lfw_start = CONFIG_LPRAM_BASE + LFW_OFFSET; -#endif /*****************************************************************************/ /* IC specific low-level driver depends on chip series */ -/* - * Configure address 0x40001600 (Low Power RAM) in the the MPU - * (Memory Protection Unit) as a "regular" memory - */ void system_mpu_config(void) { -#ifdef CONFIG_WORKAROUND_FLASH_DOWNLOAD_API - /* - * npcx9 Rev.1 has the problem for download_from_flash API. - * Workwaroud it by by the system_download_from_flash function - * in the suspend RAM like npcx5. - * TODO: Remove this when A2 chip is available - */ - /* Enable MPU */ - CPU_MPU_CTRL = 0x7; - - /* Create a new MPU Region to allow execution from low-power ram */ - CPU_MPU_RNR = REGION_CHIP_RESERVED; - CPU_MPU_RASR = CPU_MPU_RASR & 0xFFFFFFFE; /* Disable region */ - CPU_MPU_RBAR = CONFIG_LPRAM_BASE; /* Set region base address */ - /* - * Set region size & attribute and enable region - * [31:29] - Reserved. - * [28] - XN (Execute Never) = 0 - * [27] - Reserved. - * [26:24] - AP = 011 (Full access) - * [23:22] - Reserved. - * [21:19,18,17,16] - TEX,S,C,B = 001000 (Normal memory) - * [15:8] - SRD = 0 (Subregions enabled) - * [7:6] - Reserved. - * [5:1] - SIZE = 01001 (1K) - * [0] - ENABLE = 1 (enabled) - */ - CPU_MPU_RASR = 0x03080013; -#endif } #ifdef CONFIG_HIBERNATE_PSL @@ -122,11 +84,11 @@ void system_enter_psl_mode(void) NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_PSL; #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 - /* - * If pulse mode is enabled, the VCC power is turned off by the - * external component (Ex: PMIC) but PSL_OUT. So we can just return - * here. - */ + /* + * If pulse mode is enabled, the VCC power is turned off by the + * external component (Ex: PMIC) but PSL_OUT. So we can just return + * here. + */ if (IS_BIT_SET(NPCX_GLUE_PSL_MCTL1, NPCX_GLUE_PSL_MCTL1_PLS_EN)) return; #endif @@ -152,8 +114,7 @@ static void system_psl_type_sel(enum psl_pin_t psl_pin, uint32_t flags) /* Set PSL input events' type as level or edge trigger */ if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) CLEAR_BIT(NPCX_GLUE_PSL_CTS, psl_pin + 4); - else if ((flags & GPIO_INT_F_RISING) || - (flags & GPIO_INT_F_FALLING)) + else if ((flags & GPIO_INT_F_RISING) || (flags & GPIO_INT_F_FALLING)) SET_BIT(NPCX_GLUE_PSL_CTS, psl_pin + 4); /* @@ -184,7 +145,7 @@ int system_config_psl_mode(enum gpio_signal signal) * Hibernate function in last 32K ram block for npcx7 series. * Do not use global variable since we also turn off data ram. */ -noreturn void __keep __attribute__ ((section(".after_init"))) +noreturn void __keep __attribute__((section(".after_init"))) __enter_hibernate_in_last_block(void) { /* @@ -203,7 +164,7 @@ __enter_hibernate_in_last_block(void) NPCX_PMCSR = 0x6; /* Enter deep idle, wake-up by GPIOs or RTC */ - asm volatile ("wfi"); + asm volatile("wfi"); /* RTC wake-up */ if (IS_BIT_SET(NPCX_WTC, NPCX_WTC_PTO)) @@ -247,8 +208,8 @@ void __hibernate_npcx_series(void) __enter_hibernate_in_psl(); #else /* Make sure this is located in the last 32K code RAM block */ - ASSERT((uint32_t)(&__after_init_end) - CONFIG_PROGRAM_MEMORY_BASE - < (32*1024)); + ASSERT((uint32_t)(&__after_init_end) - CONFIG_PROGRAM_MEMORY_BASE < + (32 * 1024)); /* Execute hibernate func in last 32K block */ __enter_hibernate_in_last_block(); @@ -268,125 +229,3 @@ static void report_psl_wake_source(void) } DECLARE_HOOK(HOOK_INIT, report_psl_wake_source, HOOK_PRIO_DEFAULT); #endif - -/* - * npcx9 Rev.1 has the problem for download_from_flash API. - * Workwaroud it by executing the system_download_from_flash function - * in the suspend RAM like npcx5. - * TODO: Removing npcx9 when Rev.2 is available. - */ -#ifdef CONFIG_WORKAROUND_FLASH_DOWNLOAD_API -#ifdef CONFIG_EXTERNAL_STORAGE -/* Sysjump utilities in low power ram for npcx9 series. */ -noreturn void __keep __attribute__ ((section(".lowpower_ram2"))) -__start_gdma(uint32_t exeAddr) -{ - /* Enable GDMA now */ - SET_BIT(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAEN); - - /* Start GDMA */ - SET_BIT(NPCX_GDMA_CTL, NPCX_GDMA_CTL_SOFTREQ); - - /* Wait for transfer to complete/fail */ - while (!IS_BIT_SET(NPCX_GDMA_CTL, NPCX_GDMA_CTL_TC) && - !IS_BIT_SET(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAERR)) - ; - - /* Disable GDMA now */ - CLEAR_BIT(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAEN); - - /* - * Failure occurs during GMDA transaction. Let watchdog issue and - * boot from RO region again. - */ - if (IS_BIT_SET(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAERR)) - while (1) - ; - - /* - * Jump to the exeAddr address if needed. Setting bit 0 of address to - * indicate it's a thumb branch for cortex-m series CPU. - */ - ((void (*)(void))(exeAddr | 0x01))(); - - /* Should never get here */ - while (1) - ; -} - -/* Bypass for GMDA issue of ROM api utilities only on npcx5 series. */ -void system_download_from_flash(uint32_t srcAddr, uint32_t dstAddr, - uint32_t size, uint32_t exeAddr) -{ - int i; - uint8_t chunkSize = 16; /* 4 data burst mode. ie.16 bytes */ - /* - * GDMA utility in Suspend RAM. Setting bit 0 of address to indicate - * it's a thumb branch for cortex-m series CPU. - */ - void (*__start_gdma_in_lpram)(uint32_t) = - (void(*)(uint32_t))(__lpram_lfw_start | 0x01); - - /* - * Before enabling burst mode for better performance of GDMA, it's - * important to make sure srcAddr, dstAddr and size of transactions - * are 16 bytes aligned in case failure occurs. - */ - ASSERT((size % chunkSize) == 0 && (srcAddr % chunkSize) == 0 && - (dstAddr % chunkSize) == 0); - - /* Check valid address for jumpiing */ - ASSERT(exeAddr != 0x0); - - /* Enable power for the Low Power RAM */ - CLEAR_BIT(NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_6), 6); - - /* Enable Low Power RAM */ - NPCX_LPRAM_CTRL = 1; - - /* - * Initialize GDMA for flash reading. - * [31:21] - Reserved. - * [20] - GDMAERR = 0 (Indicate GMDA transfer error) - * [19] - Reserved. - * [18] - TC = 0 (Terminal Count. Indicate operation is end.) - * [17] - Reserved. - * [16] - SOFTREQ = 0 (Don't trigger here) - * [15] - DM = 0 (Set normal demand mode) - * [14] - Reserved. - * [13:12] - TWS. = 10 (One double-word for every GDMA transaction) - * [11:10] - Reserved. - * [9] - BME = 1 (4-data ie.16 bytes - Burst mode enable) - * [8] - SIEN = 0 (Stop interrupt disable) - * [7] - SAFIX = 0 (Fixed source address) - * [6] - Reserved. - * [5] - SADIR = 0 (Source address incremented) - * [4] - DADIR = 0 (Destination address incremented) - * [3:2] - GDMAMS = 00 (Software mode) - * [1] - Reserved. - * [0] - ENABLE = 0 (Don't enable yet) - */ - NPCX_GDMA_CTL = 0x00002200; - - /* Set source base address */ - NPCX_GDMA_SRCB = CONFIG_MAPPED_STORAGE_BASE + srcAddr; - - /* Set destination base address */ - NPCX_GDMA_DSTB = dstAddr; - - /* Set number of transfers */ - NPCX_GDMA_TCNT = (size / chunkSize); - - /* Clear Transfer Complete event */ - SET_BIT(NPCX_GDMA_CTL, NPCX_GDMA_CTL_TC); - - /* Copy the __start_gdma_in_lpram instructions to LPRAM */ - for (i = 0; i < &__flash_lplfw_end - &__flash_lplfw_start; i++) - *((uint32_t *)__lpram_lfw_start + i) = - *(&__flash_lplfw_start + i); - - /* Start GDMA in Suspend RAM */ - __start_gdma_in_lpram(exeAddr); -} -#endif /* CONFIG_EXTERNAL_STORAGE */ -#endif diff --git a/chip/npcx/system-npcx9.c b/chip/npcx/system-npcx9.c deleted file mode 120000 index 48088614a0..0000000000 --- a/chip/npcx/system-npcx9.c +++ /dev/null @@ -1 +0,0 @@ -system-npcx7.c \ No newline at end of file diff --git a/chip/npcx/system-npcx9.c b/chip/npcx/system-npcx9.c new file mode 100644 index 0000000000..386544ed04 --- /dev/null +++ b/chip/npcx/system-npcx9.c @@ -0,0 +1,231 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include + +/* System module driver depends on chip series for Chrome EC */ +#include "builtin/assert.h" +#include "common.h" +#include "console.h" +#include "cpu.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "hwtimer_chip.h" +#include "lct_chip.h" +#include "registers.h" +#include "rom_chip.h" +#include "system.h" +#include "system_chip.h" +#include "task.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +/* Macros for last 32K ram block */ +#define LAST_RAM_BLK ((NPCX_RAM_SIZE / (32 * 1024)) - 1) +/* Higher bits are reserved and need to be masked */ +#define RAM_PD_MASK (~BIT(LAST_RAM_BLK)) + +/*****************************************************************************/ +/* IC specific low-level driver depends on chip series */ + +void system_mpu_config(void) +{ +} + +#ifdef CONFIG_HIBERNATE_PSL +#ifndef NPCX_PSL_MODE_SUPPORT +#error "Do not enable CONFIG_HIBERNATE_PSL if npcx ec doesn't support PSL mode!" +#endif + +static enum psl_pin_t system_gpio_to_psl(enum gpio_signal signal) +{ + enum psl_pin_t psl_no; + const struct gpio_info *g = gpio_list + signal; + + if (g->port == GPIO_PORT_D && g->mask == MASK_PIN2) /* GPIOD2 */ + psl_no = PSL_IN1; + else if (g->port == GPIO_PORT_0 && (g->mask & 0x07)) /* GPIO00/01/02 */ + psl_no = GPIO_MASK_TO_NUM(g->mask) + 1; + else + psl_no = PSL_NONE; + + return psl_no; +} + +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 +void system_set_psl_gpo(int level) +{ + if (level) + SET_BIT(NPCX_GLUE_PSL_MCTL1, NPCX_GLUE_PSL_MCTL1_PSL_GPO_CTL); + else + CLEAR_BIT(NPCX_GLUE_PSL_MCTL1, NPCX_GLUE_PSL_MCTL1_PSL_GPO_CTL); +} +#endif + +void system_enter_psl_mode(void) +{ + /* Configure pins from GPIOs to PSL which rely on VSBY power rail. */ + gpio_config_module(MODULE_PMU, 1); + + /* + * In npcx7, only physical PSL_IN pins can pull PSL_OUT to high and + * reboot ec. + * In npcx9, LCT timeout event can also pull PSL_OUT. + * We won't decide the wake cause now but only mark we are entering + * hibernation via PSL. + * The actual wakeup cause will be checked by the PSL input event bits + * when ec reboots. + */ + NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_PSL; + +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 + /* + * If pulse mode is enabled, the VCC power is turned off by the + * external component (Ex: PMIC) but PSL_OUT. So we can just return + * here. + */ + if (IS_BIT_SET(NPCX_GLUE_PSL_MCTL1, NPCX_GLUE_PSL_MCTL1_PLS_EN)) + return; +#endif + + /* + * Pull PSL_OUT (GPIO85) to low to cut off ec's VCC power rail by + * setting bit 5 of PDOUT(8). + */ + SET_BIT(NPCX_PDOUT(GPIO_PORT_8), 5); +} + +/* Hibernate function implemented by PSL (Power Switch Logic) mode. */ +noreturn void __keep __enter_hibernate_in_psl(void) +{ + system_enter_psl_mode(); + /* Spin and wait for PSL cuts power; should never return */ + while (1) + ; +} + +static void system_psl_type_sel(enum psl_pin_t psl_pin, uint32_t flags) +{ + /* Set PSL input events' type as level or edge trigger */ + if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) + CLEAR_BIT(NPCX_GLUE_PSL_CTS, psl_pin + 4); + else if ((flags & GPIO_INT_F_RISING) || (flags & GPIO_INT_F_FALLING)) + SET_BIT(NPCX_GLUE_PSL_CTS, psl_pin + 4); + + /* + * Set PSL input events' polarity is low (high-to-low) active or + * high (low-to-high) active + */ + if (flags & GPIO_HIB_WAKE_HIGH) + SET_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_pin); + else + CLEAR_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_pin); +} + +int system_config_psl_mode(enum gpio_signal signal) +{ + enum psl_pin_t psl_no; + const struct gpio_info *g = gpio_list + signal; + + psl_no = system_gpio_to_psl(signal); + if (psl_no == PSL_NONE) + return 0; + + system_psl_type_sel(psl_no, g->flags); + return 1; +} + +#else +/** + * Hibernate function in last 32K ram block for npcx7 series. + * Do not use global variable since we also turn off data ram. + */ +noreturn void __keep __attribute__((section(".after_init"))) +__enter_hibernate_in_last_block(void) +{ + /* + * The hibernate utility is located in the last block of RAM. The size + * of each RAM block is 32KB. We turn off all blocks except last one + * for better power consumption. + */ + NPCX_RAM_PD(0) = RAM_PD_MASK & 0xFF; +#if defined(CHIP_FAMILY_NPCX7) + NPCX_RAM_PD(1) = (RAM_PD_MASK >> 8) & 0x0F; +#elif defined(CHIP_FAMILY_NPCX9) + NPCX_RAM_PD(1) = (RAM_PD_MASK >> 8) & 0x7F; +#endif + + /* Set deep idle mode */ + NPCX_PMCSR = 0x6; + + /* Enter deep idle, wake-up by GPIOs or RTC */ + asm volatile("wfi"); + + /* RTC wake-up */ + if (IS_BIT_SET(NPCX_WTC, NPCX_WTC_PTO)) + /* + * Mark wake-up reason for hibernate + * Do not call bbram_data_write directly cause of + * no stack. + */ + NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_MTC; +#ifdef NPCX_LCT_SUPPORT + else if (IS_BIT_SET(NPCX_LCTSTAT, NPCX_LCTSTAT_EVST)) { + NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_LCT; + /* Clear LCT event */ + NPCX_LCTSTAT = BIT(NPCX_LCTSTAT_EVST); + } +#endif + else + /* Otherwise, we treat it as GPIOs wake-up */ + NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_PIN; + + /* Start a watchdog reset */ + NPCX_WDCNT = 0x01; + /* Reload and restart Timer 0 */ + SET_BIT(NPCX_T0CSR, NPCX_T0CSR_RST); + /* Wait for timer is loaded and restart */ + while (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_RST)) + ; + + /* Spin and wait for reboot; should never return */ + while (1) + ; +} +#endif + +/** + * Hibernate function for different Nuvoton chip series. + */ +void __hibernate_npcx_series(void) +{ +#ifdef CONFIG_HIBERNATE_PSL + __enter_hibernate_in_psl(); +#else + /* Make sure this is located in the last 32K code RAM block */ + ASSERT((uint32_t)(&__after_init_end) - CONFIG_PROGRAM_MEMORY_BASE < + (32 * 1024)); + + /* Execute hibernate func in last 32K block */ + __enter_hibernate_in_last_block(); +#endif +} + +#if defined(CONFIG_HIBERNATE_PSL) +static void report_psl_wake_source(void) +{ + if (!(system_get_reset_flags() & EC_RESET_FLAG_HIBERNATE)) + return; + + CPRINTS("PSL_CTS: 0x%x", NPCX_GLUE_PSL_CTS & 0xf); +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 + CPRINTS("PSL_MCTL1 event: 0x%x", NPCX_GLUE_PSL_MCTL1 & 0x18); +#endif +} +DECLARE_HOOK(HOOK_INIT, report_psl_wake_source, HOOK_PRIO_DEFAULT); +#endif diff --git a/chip/npcx/system.c b/chip/npcx/system.c index e74ae65d58..9ce043354f 100644 --- a/chip/npcx/system.c +++ b/chip/npcx/system.c @@ -1,10 +1,11 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* System module for Chrome EC : NPCX hardware specific implementation */ +#include "builtin/assert.h" #include "clock.h" #include "clock_chip.h" #include "common.h" @@ -15,6 +16,7 @@ #include "host_command.h" #include "hwtimer_chip.h" #include "lct_chip.h" +#include "panic.h" #include "registers.h" #include "rom_chip.h" #include "sib_chip.h" @@ -27,23 +29,32 @@ /* Delay after writing TTC for value to latch */ #define MTC_TTC_LOAD_DELAY_US 250 -#define MTC_ALARM_MASK (BIT(25) - 1) -#define MTC_WUI_GROUP MIWU_GROUP_4 -#define MTC_WUI_MASK MASK_PIN7 +#define MTC_ALARM_MASK (BIT(25) - 1) +#define MTC_WUI_GROUP MIWU_GROUP_4 +#define MTC_WUI_MASK MASK_PIN7 /* ROM address of chip revision */ #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 -#define CHIP_REV_ADDR 0x0000FFFC -#define CHIP_REV_STR_SIZE 12 +#define CHIP_REV_ADDR 0x0000FFFC +#define CHIP_REV_STR_SIZE 12 +#define PWDWN_8_RESERVED_SET_MASK 0x30 #else -#define CHIP_REV_ADDR 0x00007FFC -#define CHIP_REV_STR_SIZE 6 +#define CHIP_REV_ADDR 0x00007FFC +#define CHIP_REV_STR_SIZE 6 #endif +/* Legacy SuperI/O Configuration D register offset */ +#define SIOCFD_REG_OFFSET 0x2D + /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) + +#if defined(NPCX_LCT_SUPPORT) +/* A flag for waking up from hibernate mode by RTC overflow event */ +static int is_rtc_overflow_event; +#endif /*****************************************************************************/ /* Internal functions */ @@ -82,13 +93,9 @@ void system_watchdog_reset(void) /* Return true if index is stored as a single byte in bbram */ static int bbram_is_byte_access(enum bbram_data_index index) { - return (index >= BBRM_DATA_INDEX_VBNVCNTXT && - index < BBRM_DATA_INDEX_RAMLOG) - || index == BBRM_DATA_INDEX_PD0 - || index == BBRM_DATA_INDEX_PD1 - || index == BBRM_DATA_INDEX_PD2 - || index == BBRM_DATA_INDEX_PANIC_FLAGS - ; + return index == BBRM_DATA_INDEX_PD0 || index == BBRM_DATA_INDEX_PD1 || + index == BBRM_DATA_INDEX_PD2 || + index == BBRM_DATA_INDEX_PANIC_FLAGS; } /* Check and clear BBRAM status on any reset */ @@ -100,7 +107,7 @@ void system_check_bbram_on_reset(void) * dropped, print a warning message. */ if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_SCRATCH) || - IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS)) + IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS)) CPRINTF("VBAT drop!\n"); /* @@ -171,7 +178,7 @@ static int bbram_data_write(enum bbram_data_index index, uint32_t value) /* Write BBRAM */ NPCX_BBRAM(index) = value & 0xFF; if (bytes == 4) { - NPCX_BBRAM(index + 1) = (value >> 8) & 0xFF; + NPCX_BBRAM(index + 1) = (value >> 8) & 0xFF; NPCX_BBRAM(index + 2) = (value >> 16) & 0xFF; NPCX_BBRAM(index + 3) = (value >> 24) & 0xFF; } @@ -183,10 +190,6 @@ static int bbram_data_write(enum bbram_data_index index, uint32_t value) /* Map idx to a returned BBRM_DATA_INDEX_*, or return -1 on invalid idx */ static int bbram_idx_lookup(enum system_bbram_idx idx) { - if (idx >= SYSTEM_BBRAM_IDX_VBNVBLOCK0 && - idx <= SYSTEM_BBRAM_IDX_VBNVBLOCK15) - return BBRM_DATA_INDEX_VBNVCNTXT + - idx - SYSTEM_BBRAM_IDX_VBNVBLOCK0; if (idx == SYSTEM_BBRAM_IDX_PD0) return BBRM_DATA_INDEX_PD0; if (idx == SYSTEM_BBRAM_IDX_PD1) @@ -258,14 +261,14 @@ void system_set_rtc(uint32_t seconds) * 2. LREG1, LREG3 and LREG4 store exception, reason and info in case of * software panic. */ -#define BKUP_CFSR (BBRM_DATA_INDEX_PANIC_BKUP + 0) -#define BKUP_HFSR (BBRM_DATA_INDEX_PANIC_BKUP + 4) -#define BKUP_BFAR (BBRM_DATA_INDEX_PANIC_BKUP + 8) -#define BKUP_LREG1 (BBRM_DATA_INDEX_PANIC_BKUP + 12) -#define BKUP_LREG3 (BBRM_DATA_INDEX_PANIC_BKUP + 16) -#define BKUP_LREG4 (BBRM_DATA_INDEX_PANIC_BKUP + 20) +#define BKUP_CFSR (BBRM_DATA_INDEX_PANIC_BKUP + 0) +#define BKUP_HFSR (BBRM_DATA_INDEX_PANIC_BKUP + 4) +#define BKUP_BFAR (BBRM_DATA_INDEX_PANIC_BKUP + 8) +#define BKUP_LREG1 (BBRM_DATA_INDEX_PANIC_BKUP + 12) +#define BKUP_LREG3 (BBRM_DATA_INDEX_PANIC_BKUP + 16) +#define BKUP_LREG4 (BBRM_DATA_INDEX_PANIC_BKUP + 20) -#define BKUP_PANIC_DATA_VALID BIT(0) +#define BKUP_PANIC_DATA_VALID BIT(0) void chip_panic_data_backup(void) { @@ -334,27 +337,35 @@ static void chip_set_hib_flag(uint32_t *flags, uint32_t hib_wake_flags) #ifdef NPCX_LCT_SUPPORT if (npcx_lct_is_event_set()) { *flags |= EC_RESET_FLAG_RTC_ALARM | - EC_RESET_FLAG_HIBERNATE; + EC_RESET_FLAG_HIBERNATE; + /* Is RTC overflow event? */ + if (bbram_data_read(BBRM_DATA_INDEX_LCT_TIME) == + NPCX_LCT_MAX) { + /* + * Mark it as RTC overflow event and handle it + * in hook init function later for logging info. + */ + is_rtc_overflow_event = 1; + } npcx_lct_clear_event(); return; } #endif - *flags |= EC_RESET_FLAG_WAKE_PIN | - EC_RESET_FLAG_HIBERNATE; + *flags |= EC_RESET_FLAG_WAKE_PIN | EC_RESET_FLAG_HIBERNATE; } else { /* Hibernate via non-PSL */ #ifdef NPCX_LCT_SUPPORT if (hib_wake_flags & HIBERNATE_WAKE_LCT) { *flags |= EC_RESET_FLAG_RTC_ALARM | - EC_RESET_FLAG_HIBERNATE; + EC_RESET_FLAG_HIBERNATE; return; } #endif if (hib_wake_flags & HIBERNATE_WAKE_PIN) { *flags |= EC_RESET_FLAG_WAKE_PIN | - EC_RESET_FLAG_HIBERNATE; + EC_RESET_FLAG_HIBERNATE; } else if (hib_wake_flags & HIBERNATE_WAKE_MTC) { *flags |= EC_RESET_FLAG_RTC_ALARM | - EC_RESET_FLAG_HIBERNATE; + EC_RESET_FLAG_HIBERNATE; } } } @@ -378,6 +389,8 @@ static void check_reset_cause(void) /* Clear saved hibernate wake flag in bbram , too */ bbram_data_write(BBRM_DATA_INDEX_WAKE, 0); + chip_set_hib_flag(&flags, hib_wake_flags); + /* Use scratch bit to check power on reset or VCC1_RST reset */ if (!IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_SCRATCH)) { #ifdef CONFIG_BOARD_FORCE_RESET_PIN @@ -407,9 +420,9 @@ static void check_reset_cause(void) * clear the flag so later code will * not wait for the second reset. */ - flags = - (flags & ~EC_RESET_FLAG_INITIAL_PWR) - | EC_RESET_FLAG_POWER_ON; + flags = (flags & + ~EC_RESET_FLAG_INITIAL_PWR) | + EC_RESET_FLAG_POWER_ON; else /* * No previous power-on flag, @@ -419,23 +432,28 @@ static void check_reset_cause(void) */ flags |= EC_RESET_FLAG_RESET_PIN; } else { + flags |= EC_RESET_FLAG_POWER_ON; + /* * Power-on restart, so set a flag and save it * for the next imminent reset. Later code * will check for this flag and wait for the - * second reset. + * second reset. Waking from PSL hibernate is + * power-on for EC but not for H1, so do not + * wait for the second reset. */ - flags |= EC_RESET_FLAG_POWER_ON - | EC_RESET_FLAG_INITIAL_PWR; - chip_flags |= EC_RESET_FLAG_INITIAL_PWR; + if (!(flags & EC_RESET_FLAG_HIBERNATE)) { + flags |= EC_RESET_FLAG_INITIAL_PWR; + chip_flags |= EC_RESET_FLAG_INITIAL_PWR; + } } } else /* * No second reset after power-on, so * set the flags according to the restart reason. */ - flags |= reset ? EC_RESET_FLAG_RESET_PIN - : EC_RESET_FLAG_POWER_ON; + flags |= reset ? EC_RESET_FLAG_RESET_PIN : + EC_RESET_FLAG_POWER_ON; #endif } chip_save_reset_flags(chip_flags); @@ -454,8 +472,6 @@ static void check_reset_cause(void) SET_BIT(NPCX_RSTCTL, NPCX_RSTCTL_DBGRST_STS); } - chip_set_hib_flag(&flags, hib_wake_flags); - /* Watchdog Reset */ if (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS)) { /* @@ -464,7 +480,7 @@ static void check_reset_cause(void) * cause is panic reason or not. */ if (!(flags & (EC_RESET_FLAG_SOFT | EC_RESET_FLAG_HARD | - EC_RESET_FLAG_HIBERNATE))) + EC_RESET_FLAG_HIBERNATE))) flags |= EC_RESET_FLAG_WATCHDOG; /* Clear watchdog reset status initially*/ @@ -483,10 +499,10 @@ static void system_set_gpios_and_wakeup_inputs_hibernate(void) int table, i; /* Disable all MIWU inputs before entering hibernate */ - for (table = MIWU_TABLE_0 ; table < MIWU_TABLE_2 ; table++) { - for (i = 0 ; i < 8 ; i++) { + for (table = MIWU_TABLE_0; table < MIWU_TABLE_2; table++) { + for (i = 0; i < 8; i++) { /* Disable all wake-ups */ - NPCX_WKEN(table, i) = 0x00; + NPCX_WKEN(table, i) = 0x00; /* Clear all pending bits of wake-ups */ NPCX_WKPCL(table, i) = 0xFF; /* @@ -499,7 +515,7 @@ static void system_set_gpios_and_wakeup_inputs_hibernate(void) #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 /* Disable MIWU 2 group 6 inputs which used for the additional GPIOs */ - NPCX_WKEN(MIWU_TABLE_2, MIWU_GROUP_6) = 0x00; + NPCX_WKEN(MIWU_TABLE_2, MIWU_GROUP_6) = 0x00; NPCX_WKPCL(MIWU_TABLE_2, MIWU_GROUP_6) = 0xFF; NPCX_WKINEN(MIWU_TABLE_2, MIWU_GROUP_6) = 0x00; #endif @@ -529,14 +545,17 @@ static void system_set_lct_alarm(uint32_t seconds, uint32_t microseconds) #ifdef CONFIG_HIBERNATE_PSL /* Enable LCT event to PSL */ npcx_lct_config(seconds, 1, 0); + /* save the start time of LCT */ + if (IS_ENABLED(CONFIG_HOSTCMD_RTC) || IS_ENABLED(CONFIG_CMD_RTC)) + bbram_data_write(BBRM_DATA_INDEX_LCT_TIME, seconds); #else /* Enable LCT event interrupt and MIWU */ npcx_lct_config(seconds, 0, 1); task_disable_irq(NPCX_IRQ_LCT_WKINTF_2); /* Enable wake-up input sources & clear pending bit */ - NPCX_WKPCL(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + NPCX_WKPCL(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; NPCX_WKINEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; - NPCX_WKEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + NPCX_WKEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; task_enable_irq(NPCX_IRQ_LCT_WKINTF_2); #endif npcx_lct_enable(1); @@ -609,24 +628,51 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds) board_hibernate_late(); /* Clear all pending IRQ otherwise wfi will have no affect */ - for (i = NPCX_IRQ_0 ; i < NPCX_IRQ_COUNT ; i++) + for (i = NPCX_IRQ_0; i < NPCX_IRQ_COUNT; i++) task_clear_pending_irq(i); - /* - * Set RTC interrupt in time to wake up before - * next event. - */ - if (seconds || microseconds) + /* Set the timer interrupt for wake up. */ #ifdef NPCX_LCT_SUPPORT + if (seconds || microseconds) { system_set_lct_alarm(seconds, microseconds); + } else if (IS_ENABLED(CONFIG_HIBERNATE_PSL_COMPENSATE_RTC)) { + system_set_lct_alarm(NPCX_LCT_MAX, 0); + } #else + if (seconds || microseconds) system_set_rtc_alarm(seconds, microseconds); #endif /* execute hibernate func depend on chip series */ __hibernate_npcx_series(); +} + +#ifdef CONFIG_HIBERNATE_PSL_COMPENSATE_RTC +#ifndef NPCX_LCT_SUPPORT +#error "Do not enable CONFIG_HIBERNATE_PSL_COMPENSATE_RTC if npcx ec doesn't \ +support LCT!" +#endif +/* + * The function uses the LCT counter value to compensate for RTC after hibernate + * wake-up. Because system_set_rtc() will invoke udelay(), the function should + * execute after timer_init(). The function also should execute before + * npcx_lct_init() which will clear all LCT register. + */ +void system_compensate_rtc(void) +{ + uint32_t rtc_time, ltc_start_time; + + ltc_start_time = bbram_data_read(BBRM_DATA_INDEX_LCT_TIME); + if (ltc_start_time == 0) + return; + rtc_time = system_get_rtc_sec(); + rtc_time += ltc_start_time - npcx_lct_get_time(); + system_set_rtc(rtc_time); + /* Clear BBRAM data to avoid compensating again. */ + bbram_data_write(BBRM_DATA_INDEX_LCT_TIME, 0); } +#endif #endif /* CONFIG_SUPPORT_CHIP_HIBERNATION */ static char system_to_hex(uint8_t val) @@ -680,9 +726,9 @@ void system_set_rtc_alarm(uint32_t seconds, uint32_t microseconds) task_enable_irq(NPCX_IRQ_MTC); /* Enable wake-up input sources & clear pending bit */ - NPCX_WKPCL(MIWU_TABLE_0, MTC_WUI_GROUP) |= MTC_WUI_MASK; + NPCX_WKPCL(MIWU_TABLE_0, MTC_WUI_GROUP) |= MTC_WUI_MASK; NPCX_WKINEN(MIWU_TABLE_0, MTC_WUI_GROUP) |= MTC_WUI_MASK; - NPCX_WKEN(MIWU_TABLE_0, MTC_WUI_GROUP) |= MTC_WUI_MASK; + NPCX_WKEN(MIWU_TABLE_0, MTC_WUI_GROUP) |= MTC_WUI_MASK; } void system_reset_rtc_alarm(void) @@ -739,6 +785,22 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) #endif } +#ifndef CONFIG_ENABLE_JTAG_SELECTION +static void system_disable_host_sel_jtag(void) +{ + int data; + + /* Enable Core-to-Host Modules Access */ + SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE); + /* Clear SIOCFD.JEN0_HSL to disable JTAG0 */ + data = sib_read_reg(SIO_OFFSET, SIOCFD_REG_OFFSET); + data &= ~0x80; + sib_write_reg(SIO_OFFSET, SIOCFD_REG_OFFSET, data); + /* Disable Core-to-Host Modules Access */ + CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE); +} +#endif + void chip_pre_init(void) { /* Setting for fixing JTAG issue */ @@ -765,21 +827,21 @@ void chip_pre_init(void) * This is the workaround to disable the JTAG0 which is enabled * accidentally by a special key combination. */ +#if NPCX_FAMILY_VERSION < NPCX_FAMILY_NPCX9 if (!IS_BIT_SET(NPCX_DEVALT(5), NPCX_DEVALT5_NJEN0_EN)) { - int data; /* Set DEVALT5.nJEN0_EN to disable JTAG0 */ SET_BIT(NPCX_DEVALT(5), NPCX_DEVALT5_NJEN0_EN); - /* Enable Core-to-Host Modules Access */ - SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE); - /* Clear SIOCFD.JEN0_HSL to disable JTAG0 */ - data = sib_read_reg(SIO_OFFSET, 0x2D); - data &= ~0x80; - sib_write_reg(SIO_OFFSET, 0x2D, data); - /* Disable Core-to-Host Modules Access */ - CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE); + system_disable_host_sel_jtag(); + } +#else + if (GET_FIELD(NPCX_JEN_CTL1, NPCX_JEN_CTL1_JEN_EN_FIELD) == + NPCX_JEN_CTL1_JEN_EN_ENA) { + SET_FIELD(NPCX_JEN_CTL1, NPCX_JEN_CTL1_JEN_EN_FIELD, + NPCX_JEN_CTL1_JEN_EN_DIS); + system_disable_host_sel_jtag(); } #endif - +#endif } void system_pre_init(void) @@ -791,42 +853,52 @@ void system_pre_init(void) * EC should be initialized in Booter */ - /* Power-down the modules we don't need */ - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_1) = 0xF9; /* Skip SDP_PD FIU_PD */ + /* Power down KBS, SDP, PS2, UART1, and MFT1-3 */ + NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_1) = 0xFB; + /* Power down PWM0-7 */ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_2) = 0xFF; #if defined(CHIP_FAMILY_NPCX5) - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_3) = 0x0F; /* Skip GDMA */ + /* Power down SMB0-3 */ + NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_3) = 0x0F; #elif NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_3) = 0x3F; /* Skip GDMA */ + /* Power down SMB0-4 */ + NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_3) = 0x3F; #endif - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_4) = 0xF4; /* Skip ITIM2/1_PD */ + /* Power down ITIM3, ADC, PECI, SPIP */ + NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_4) = 0xF4; + /* Power down C2HACC, SHM_REG, SHM, Port80, and MSWC */ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_5) = 0xF8; pwdwn6 = 0x70 | #if NPCX_FAMILY_VERSION <= NPCX_FAMILY_NPCX7 - /* - * Don't set PD of ITIM6 for NPCX9 and later chips because - * they use it as the system timer. - */ - BIT(NPCX_PWDWN_CTL6_ITIM6_PD) | + /* + * Don't set PD of ITIM6 for NPCX9 and later chips because + * they use it as the system timer. + */ + BIT(NPCX_PWDWN_CTL6_ITIM6_PD) | #endif - BIT(NPCX_PWDWN_CTL6_ITIM4_PD); /* Skip ITIM5_PD */ -#if !defined(CONFIG_HOSTCMD_ESPI) + BIT(NPCX_PWDWN_CTL6_ITIM4_PD); +#if !defined(CONFIG_HOST_INTERFACE_ESPI) pwdwn6 |= 1 << NPCX_PWDWN_CTL6_ESPI_PD; #endif NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_6) = pwdwn6; #if defined(CHIP_FAMILY_NPCX7) -#if defined(CHIP_VARIANT_NPCX7M6FB) || defined(CHIP_VARIANT_NPCX7M6FC) || \ +#if defined(CHIP_VARIANT_NPCX7M6FB) || defined(CHIP_VARIANT_NPCX7M6FC) || \ defined(CHIP_VARIANT_NPCX7M7FC) || defined(CHIP_VARIANT_NPCX7M7WB) || \ defined(CHIP_VARIANT_NPCX7M7WC) + /* Power down UART2, SMB5-7, ITIM64, and WoV */ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_7) = 0xE7; #else + /* Power down SMB5-7 */ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_7) = 0x07; #endif #endif #if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 + /* Power down UART2-4, SMB5-7, and ITIM64 */ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_7) = 0xFF; + /* Power down I3C */ + NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_8) = PWDWN_8_RESERVED_SET_MASK | 0x01; #endif /* Following modules can be powered down automatically in npcx7 */ @@ -877,34 +949,34 @@ void system_pre_init(void) * hibernation. */ SET_BIT(NPCX_GLUE_PSL_MCTL1, - NPCX_GLUE_PSL_MCTL1_VCC1_RST_PSL); + NPCX_GLUE_PSL_MCTL1_VCC1_RST_PSL); /* Disable VCC_RST Pull-Up */ SET_BIT(NPCX_DEVALT(ALT_GROUP_G), - NPCX_DEVALTG_VCC1_RST_PUD); + NPCX_DEVALTG_VCC1_RST_PUD); /* * Lock this bit itself and VCC1_RST_PSL in the * PSL_MCTL1 register to read-only. */ SET_BIT(NPCX_GLUE_PSL_MCTL2, - NPCX_GLUE_PSL_MCTL2_VCC1_RST_PSL_LK); + NPCX_GLUE_PSL_MCTL2_VCC1_RST_PSL_LK); } /* Don't set PSL_OUT to open-drain if it is the level mode */ ASSERT((opt_flag & NPCX_PSL_CFG_PSL_OUT_PULSE) || - !(opt_flag & NPCX_PSL_CFG_PSL_OUT_OD)); + !(opt_flag & NPCX_PSL_CFG_PSL_OUT_OD)); if (opt_flag & NPCX_PSL_CFG_PSL_OUT_OD) SET_BIT(NPCX_GLUE_PSL_MCTL1, NPCX_GLUE_PSL_MCTL1_OD_EN); else CLEAR_BIT(NPCX_GLUE_PSL_MCTL1, - NPCX_GLUE_PSL_MCTL1_OD_EN); + NPCX_GLUE_PSL_MCTL1_OD_EN); if (opt_flag & NPCX_PSL_CFG_PSL_OUT_PULSE) SET_BIT(NPCX_GLUE_PSL_MCTL1, - NPCX_GLUE_PSL_MCTL1_PLS_EN); + NPCX_GLUE_PSL_MCTL1_PLS_EN); else CLEAR_BIT(NPCX_GLUE_PSL_MCTL1, - NPCX_GLUE_PSL_MCTL1_PLS_EN); + NPCX_GLUE_PSL_MCTL1_PLS_EN); } #endif } @@ -955,7 +1027,7 @@ const char *system_get_chip_vendor(void) case 0x20: return "Nuvoton"; default: - *p = system_to_hex(fam_id >> 4); + *p = system_to_hex(fam_id >> 4); *(p + 1) = system_to_hex(fam_id); *(p + 2) = '\0'; return str; @@ -998,7 +1070,7 @@ const char *system_get_chip_name(void) return "NPCX993F"; #endif default: - *p = system_to_hex(chip_id >> 4); + *p = system_to_hex(chip_id >> 4); *(p + 1) = system_to_hex(chip_id); *(p + 2) = '\0'; return str; @@ -1021,6 +1093,7 @@ const char *system_get_chip_revision(void) #ifdef CHIP_FAMILY_NPCX7 uint8_t chip_id = NPCX_DEVICE_ID_CR; #endif + int s; switch (chip_gen) { #if defined(CHIP_FAMILY_NPCX5) @@ -1033,7 +1106,7 @@ const char *system_get_chip_revision(void) break; case 0x07: if (chip_id == NPCX796F_A_B_CHIP_ID || - chip_id == NPCX797W_B_CHIP_ID) + chip_id == NPCX797W_B_CHIP_ID) *p++ = 'B'; else *p++ = 'C'; @@ -1054,7 +1127,7 @@ const char *system_get_chip_revision(void) * For npcx5/npcx7, the revision number is 1 byte. * For NPCX9 and later chips, the revision number is 4 bytes. */ - for (int s = sizeof(rev_num) - 1; s >= 0; s--) { + for (s = sizeof(rev_num) - 1; s >= 0; s--) { uint8_t r = rev_num >> (s * 8); *p++ = system_to_hex(r >> 4); @@ -1065,8 +1138,6 @@ const char *system_get_chip_revision(void) return rev; } -BUILD_ASSERT(BBRM_DATA_INDEX_VBNVCNTXT + EC_VBNV_BLOCK_SIZE <= NPCX_BBRAM_SIZE); - /** * Set a scratchpad register to the specified value. * @@ -1081,9 +1152,10 @@ int system_set_scratchpad(uint32_t value) return bbram_data_write(BBRM_DATA_INDEX_SCRATCHPAD, value); } -uint32_t system_get_scratchpad(void) +int system_get_scratchpad(uint32_t *value) { - return bbram_data_read(BBRM_DATA_INDEX_SCRATCHPAD); + *value = bbram_data_read(BBRM_DATA_INDEX_SCRATCHPAD); + return EC_SUCCESS; } int system_is_reboot_warm(void) @@ -1108,6 +1180,23 @@ int system_is_reboot_warm(void) return 1; } +#if defined(CONFIG_HIBERNATE_PSL) && defined(NPCX_LCT_SUPPORT) +static void system_init_check_rtc_wakeup_event(void) +{ + /* + * If platform uses PSL (Power Switch Logic) for hibernating and RTC is + * also supported, determine whether ec is woken up by RTC with overflow + * event (16 weeks). If so, let it go to hibernate mode immediately. + */ + if (is_rtc_overflow_event) { + CPRINTS("Hibernate due to RTC overflow event"); + system_hibernate(0, 0); + } +} +DECLARE_HOOK(HOOK_INIT, system_init_check_rtc_wakeup_event, + HOOK_PRIO_DEFAULT - 1); +#endif + /*****************************************************************************/ /* Console commands */ void print_system_rtc(enum console_channel ch) @@ -1118,7 +1207,7 @@ void print_system_rtc(enum console_channel ch) } #ifdef CONFIG_CMD_RTC -static int command_system_rtc(int argc, char **argv) +static int command_system_rtc(int argc, const char **argv) { if (argc == 3 && !strcasecmp(argv[1], "set")) { char *e; @@ -1135,15 +1224,14 @@ static int command_system_rtc(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(rtc, command_system_rtc, - "[set ]", - "Get/set real-time clock"); +DECLARE_CONSOLE_COMMAND(rtc, command_system_rtc, "[set ]", + "Get/set real-time clock"); #ifdef CONFIG_CMD_RTC_ALARM /** * Test the RTC alarm by setting an interrupt on RTC match. */ -static int command_rtc_alarm_test(int argc, char **argv) +static int command_rtc_alarm_test(int argc, const char **argv) { int s = 1, us = 0; char *e; @@ -1155,13 +1243,11 @@ static int command_rtc_alarm_test(int argc, char **argv) s = strtoi(argv[1], &e, 10); if (*e) return EC_ERROR_PARAM1; - } if (argc > 2) { us = strtoi(argv[2], &e, 10); if (*e) return EC_ERROR_PARAM2; - } system_set_rtc_alarm(s, us); @@ -1169,8 +1255,7 @@ static int command_rtc_alarm_test(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(rtc_alarm, command_rtc_alarm_test, - "[seconds [microseconds]]", - "Test alarm"); + "[seconds [microseconds]]", "Test alarm"); #endif /* CONFIG_CMD_RTC_ALARM */ #endif /* CONFIG_CMD_RTC */ @@ -1187,9 +1272,8 @@ static enum ec_status system_rtc_get_value(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_VALUE, - system_rtc_get_value, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_VALUE, system_rtc_get_value, + EC_VER_MASK(0)); static enum ec_status system_rtc_set_value(struct host_cmd_handler_args *args) { @@ -1198,9 +1282,8 @@ static enum ec_status system_rtc_set_value(struct host_cmd_handler_args *args) system_set_rtc(p->time); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_VALUE, - system_rtc_set_value, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_VALUE, system_rtc_set_value, + EC_VER_MASK(0)); static enum ec_status system_rtc_set_alarm(struct host_cmd_handler_args *args) { @@ -1209,9 +1292,8 @@ static enum ec_status system_rtc_set_alarm(struct host_cmd_handler_args *args) system_set_rtc_alarm(p->time, 0); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_ALARM, - system_rtc_set_alarm, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_ALARM, system_rtc_set_alarm, + EC_VER_MASK(0)); static enum ec_status system_rtc_get_alarm(struct host_cmd_handler_args *args) { @@ -1222,9 +1304,8 @@ static enum ec_status system_rtc_get_alarm(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_ALARM, - system_rtc_get_alarm, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_ALARM, system_rtc_get_alarm, + EC_VER_MASK(0)); #endif /* CONFIG_HOSTCMD_RTC */ #ifdef CONFIG_EXTERNAL_STORAGE @@ -1241,28 +1322,28 @@ void system_jump_to_booter(void) */ switch (system_get_shrspi_image_copy()) { case EC_IMAGE_RW: - flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF; + flash_offset = + CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF; flash_used = CONFIG_RW_SIZE; break; #ifdef CONFIG_RW_B case EC_IMAGE_RW_B: flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_B_STORAGE_OFF; + CONFIG_RW_B_STORAGE_OFF; flash_used = CONFIG_RW_SIZE; break; #endif case EC_IMAGE_RO: default: /* Jump to RO by default */ - flash_offset = CONFIG_EC_PROTECTED_STORAGE_OFF + - CONFIG_RO_STORAGE_OFF; + flash_offset = + CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_RO_STORAGE_OFF; flash_used = CONFIG_RO_SIZE; break; } /* Make sure the reset vector is inside the destination image */ - addr_entry = *(uintptr_t *)(flash_offset + - CONFIG_MAPPED_STORAGE_BASE + 4); + addr_entry = + *(uintptr_t *)(flash_offset + CONFIG_MAPPED_STORAGE_BASE + 4); /* * Speed up FW download time by increasing clock freq of EC. It will @@ -1270,33 +1351,32 @@ void system_jump_to_booter(void) */ clock_turbo(); -/* - * npcx9 Rev.1 has the problem for download_from_flash API. - * Workwaroud it by executing the system_download_from_flash function - * in the suspend RAM like npcx5. - * TODO: Removing npcx9 when Rev.2 is available. - */ /* Bypass for GMDA issue of ROM api utilities */ -#if defined(CHIP_FAMILY_NPCX5) || defined(CONFIG_WORKAROUND_FLASH_DOWNLOAD_API) - system_download_from_flash( - flash_offset, /* The offset of the data in spi flash */ - CONFIG_PROGRAM_MEMORY_BASE, /* RAM Addr of downloaded data */ - flash_used, /* Number of bytes to download */ - addr_entry /* jump to this address after download */ +#if defined(CHIP_FAMILY_NPCX5) + system_download_from_flash(flash_offset, /* The offset of the data in + spi flash */ + CONFIG_PROGRAM_MEMORY_BASE, /* RAM Addr of + downloaded + data */ + flash_used, /* Number of bytes to download */ + addr_entry /* jump to this address after + download */ ); #else - download_from_flash( - flash_offset, /* The offset of the data in spi flash */ - CONFIG_PROGRAM_MEMORY_BASE, /* RAM Addr of downloaded data */ - flash_used, /* Number of bytes to download */ - SIGN_NO_CHECK, /* Need CRC check or not */ - addr_entry, /* jump to this address after download */ - &status /* Status fo download */ + download_from_flash(flash_offset, /* The offset of the data in spi flash + */ + CONFIG_PROGRAM_MEMORY_BASE, /* RAM Addr of + downloaded data */ + flash_used, /* Number of bytes to download */ + SIGN_NO_CHECK, /* Need CRC check or not */ + addr_entry, /* jump to this address after download + */ + &status /* Status fo download */ ); #endif } -uint32_t system_get_lfw_address() +uint32_t system_get_lfw_address(void) { /* * In A3 version, we don't use little FW anymore @@ -1327,8 +1407,10 @@ void system_set_image_copy(enum ec_image copy) #endif default: CPRINTS("Invalid copy (%d) is requested as a jump destination. " - "Change it to %d.", copy, EC_IMAGE_RO); + "Change it to %d.", + copy, EC_IMAGE_RO); /* Fall through to EC_IMAGE_RO */ + __fallthrough; case EC_IMAGE_RO: SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT); diff --git a/chip/npcx/system_chip.h b/chip/npcx/system_chip.h index c084cd04a6..2ee5f8aff0 100644 --- a/chip/npcx/system_chip.h +++ b/chip/npcx/system_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,32 +9,34 @@ #define __CROS_EC_SYSTEM_CHIP_H /* Flags for BBRM_DATA_INDEX_WAKE */ -#define HIBERNATE_WAKE_MTC BIT(0) /* MTC alarm */ -#define HIBERNATE_WAKE_PIN BIT(1) /* Wake pin */ -#define HIBERNATE_WAKE_LCT BIT(2) /* LCT alarm */ +#define HIBERNATE_WAKE_MTC BIT(0) /* MTC alarm */ +#define HIBERNATE_WAKE_PIN BIT(1) /* Wake pin */ +#define HIBERNATE_WAKE_LCT BIT(2) /* LCT alarm */ /* * Indicate that EC enters hibernation via PSL. When EC wakes up from * hibernation and this flag is set, it will check the related status bit to * know the actual wake up source. (From LCT or physical wakeup pins) */ -#define HIBERNATE_WAKE_PSL BIT(3) +#define HIBERNATE_WAKE_PSL BIT(3) /* Indices for battery-backed ram (BBRAM) data position */ enum bbram_data_index { - BBRM_DATA_INDEX_SCRATCHPAD = 0, /* General-purpose scratchpad */ + BBRM_DATA_INDEX_SCRATCHPAD = 0, /* General-purpose scratchpad */ BBRM_DATA_INDEX_SAVED_RESET_FLAGS = 4, /* Saved reset flags */ - BBRM_DATA_INDEX_WAKE = 8, /* Wake reasons for hibernate */ - BBRM_DATA_INDEX_PD0 = 12, /* USB-PD saved port0 state */ - BBRM_DATA_INDEX_PD1 = 13, /* USB-PD saved port1 state */ - BBRM_DATA_INDEX_TRY_SLOT = 14, /* Vboot EC try slot */ - BBRM_DATA_INDEX_PD2 = 15, /* USB-PD saved port2 state */ - BBRM_DATA_INDEX_VBNVCNTXT = 16, /* VbNvContext for ARM arch */ - BBRM_DATA_INDEX_RAMLOG = 32, /* RAM log for Booter */ - BBRM_DATA_INDEX_PANIC_FLAGS = 35, /* Flag to indicate validity of - * panic data starting at index - * 36. - */ - BBRM_DATA_INDEX_PANIC_BKUP = 36, /* Panic data (index 35-63)*/ + BBRM_DATA_INDEX_WAKE = 8, /* Wake reasons for hibernate */ + BBRM_DATA_INDEX_PD0 = 12, /* USB-PD saved port0 state */ + BBRM_DATA_INDEX_PD1 = 13, /* USB-PD saved port1 state */ + BBRM_DATA_INDEX_TRY_SLOT = 14, /* Vboot EC try slot */ + BBRM_DATA_INDEX_PD2 = 15, /* USB-PD saved port2 state */ + /* Index 16-31 available for future use */ + BBRM_DATA_INDEX_RAMLOG = 32, /* RAM log for Booter */ + BBRM_DATA_INDEX_PANIC_FLAGS = 35, /* Flag to indicate validity of + * panic data starting at index + * 36. + */ + BBRM_DATA_INDEX_PANIC_BKUP = 36, /* Panic data (index 35-63)*/ + BBRM_DATA_INDEX_LCT_TIME = 64, /* The start time of LCT(4 bytes) + */ }; enum psl_pin_t { @@ -64,10 +66,10 @@ void __hibernate_npcx_series(void); void system_check_bbram_on_reset(void); /* The utilities and variables depend on npcx chip family */ -#if defined(CHIP_FAMILY_NPCX5) || defined(CONFIG_WORKAROUND_FLASH_DOWNLOAD_API) +#if defined(CHIP_FAMILY_NPCX5) /* Bypass for GMDA issue of ROM api utilities only on npcx5 series */ void system_download_from_flash(uint32_t srcAddr, uint32_t dstAddr, - uint32_t size, uint32_t exeAddr); + uint32_t size, uint32_t exeAddr); /* Begin address for hibernate utility; defined in linker script */ extern unsigned int __flash_lpfw_start; diff --git a/chip/npcx/trng.c b/chip/npcx/trng.c new file mode 100644 index 0000000000..a2d7920c14 --- /dev/null +++ b/chip/npcx/trng.c @@ -0,0 +1,251 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Hardware Random Number Generator */ + +#include "common.h" +#include "console.h" +#include "host_command.h" +#include "panic.h" +#include "printf.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "trng.h" +#include "util.h" + +#define DRBG_CONTEXT_SIZE 240 + +struct drbg_ctx { + union { + uint8_t buffer[DRBG_CONTEXT_SIZE]; + uint32_t buffer32[DRBG_CONTEXT_SIZE / 4]; + uint64_t buffer64[DRBG_CONTEXT_SIZE / 8]; + }; +} __aligned(16); + +struct drbg_ctx ctx; +struct drbg_ctx *ctx_p = &ctx; + +enum ncl_status { + NCL_STATUS_OK = 0xA5A5, + NCL_STATUS_FAIL = 0x5A5A, + NCL_STATUS_INVALID_PARAM = 0x02, + NCL_STATUS_PARAM_NOT_SUPPORTED, + NCL_STATUS_SYSTEM_BUSY, + NCL_STATUS_AUTHENTICATION_FAIL, + NCL_STATUS_NO_RESPONSE, + NCL_STATUS_HARDWARE_ERROR, +}; + +/* + * This enum defines the security strengths supported by this DRBG mechanism. + * The internally generated entropy and nonce sizes are derived from these + * values. The supported actual sizes: + * Security strength (bits) 112 128 192 256 128_Test 256_Test + * + * Entropy size (Bytes) 32 48 64 96 111 128 + * Nonce size (Bytes) 16 16 24 32 16 0 + */ +enum ncl_drbg_security_strength { + NCL_DRBG_SECURITY_STRENGTH_112b = 0, + NCL_DRBG_SECURITY_STRENGTH_128b, + NCL_DRBG_SECURITY_STRENGTH_192b, + NCL_DRBG_SECURITY_STRENGTH_256b, + NCL_DRBG_SECURITY_STRENGTH_128b_TEST, + NCL_DRBG_SECURITY_STRENGTH_256b_TEST, + NCL_DRBG_MAX_SECURITY_STRENGTH +}; + +/* The actual base address is 13C but we only need the SHA power function */ +#define NCL_SHA_BASE_ADDR 0x0000015CUL +struct ncl_sha { + /* Power on/off SHA module. */ + enum ncl_status (*power)(void *ctx, uint8_t on); +}; +#define NCL_SHA ((const struct ncl_sha *)NCL_SHA_BASE_ADDR) + +/* + * The base address of the table that holds the function pointer for each + * DRBG API in ROM. + */ +#define NCL_DRBG_BASE_ADDR 0x00000110UL +struct ncl_drbg { + /* Get the DRBG context size required by DRBG APIs. */ + uint32_t (*get_context_size)(void); + /* Initialize DRBG context. */ + enum ncl_status (*init_context)(void *ctx); + /* Power on/off DRBG module. */ + enum ncl_status (*power)(void *ctx, uint8_t on); + /* Finalize DRBG context. */ + enum ncl_status (*finalize_context)(void *ctx); + /* Initialize the DRBG hardware module and enable interrupts. */ + enum ncl_status (*init)(void *ctx, bool int_enable); + /* + * Configure DRBG, pres_resistance enables/disables (1/0) prediction + * resistance + */ + enum ncl_status (*config)(void *ctx, uint32_t reseed_interval, + uint8_t pred_resistance); + /* + * This routine creates a first instantiation of the DRBG mechanism + * parameters. The routine pulls an initial seed from the HW RNG module + * and resets the reseed counter. DRBG and SHA modules should be + * activated prior to the this operation. + */ + enum ncl_status (*instantiate)( + void *ctx, enum ncl_drbg_security_strength sec_strength, + const uint8_t *pers_string, uint32_t pers_string_len); + /* Uninstantiate DRBG module */ + enum ncl_status (*uninstantiate)(void *ctx); + /* Reseeds the internal state of the given instantce */ + enum ncl_status (*reseed)(void *ctc, uint8_t *add_data, + uint32_t add_data_len); + /* Generates a random number from the current internal state. */ + enum ncl_status (*generate)(void *ctx, const uint8_t *add_data, + uint32_t add_data_len, uint8_t *out_buff, + uint32_t out_buff_len); + /* Clear all DRBG SSPs (Sensitive Security Parameters) in HW & driver */ + enum ncl_status (*clear)(void *ctx); +}; +#define NCL_DRBG ((const struct ncl_drbg *)NCL_DRBG_BASE_ADDR) + +struct npcx_trng_state { + enum ncl_status trng_init; +}; +struct npcx_trng_state trng_state; +struct npcx_trng_state *state_p = &trng_state; + +test_mockable void trng_init(void) +{ +#ifndef CHIP_VARIANT_NPCX9M8S +#error "Please add support for CONFIG_RNG on this chip family." +#endif + + uint32_t context_size = 0; + + state_p->trng_init = NCL_STATUS_FAIL; + + context_size = NCL_DRBG->get_context_size(); + if (context_size != DRBG_CONTEXT_SIZE) + ccprintf("ERROR! Unexpected NCL DRBG context_size = %d\n", + context_size); + + state_p->trng_init = NCL_DRBG->power(ctx_p, true); + if (state_p->trng_init != NCL_STATUS_OK) { + ccprintf("ERROR! DRBG power returned %x\n", state_p->trng_init); + return; + } + + state_p->trng_init = NCL_SHA->power(ctx_p, true); + if (state_p->trng_init != NCL_STATUS_OK) { + ccprintf("ERROR! SHA power returned %x\n", state_p->trng_init); + return; + } + + state_p->trng_init = NCL_DRBG->init_context(ctx_p); + if (state_p->trng_init != NCL_STATUS_OK) { + ccprintf("ERROR! DRBG init_context returned %x\r", + state_p->trng_init); + return; + } + + state_p->trng_init = NCL_DRBG->init(ctx_p, 0); + if (state_p->trng_init != NCL_STATUS_OK) { + ccprintf("ERROR! DRBG init returned %x\r", state_p->trng_init); + return; + } + + state_p->trng_init = NCL_DRBG->config(ctx_p, 100, false); + if (state_p->trng_init != NCL_STATUS_OK) { + ccprintf("ERROR! DRBG config returned %x\r", + state_p->trng_init); + return; + } + + state_p->trng_init = NCL_DRBG->instantiate( + ctx_p, NCL_DRBG_SECURITY_STRENGTH_128b, NULL, 0); + if (state_p->trng_init != NCL_STATUS_OK) { + ccprintf("ERROR! DRBG instantiate returned %x\r", + state_p->trng_init); + return; + } + + state_p->trng_init = NCL_DRBG->power(ctx_p, false); + if (state_p->trng_init != NCL_STATUS_OK) { + ccprintf("ERROR! DRBG power returned %x\n", state_p->trng_init); + return; + } + + state_p->trng_init = NCL_SHA->power(ctx_p, false); + if (state_p->trng_init != NCL_STATUS_OK) { + ccprintf("ERROR! SHA power returned %x\n", state_p->trng_init); + return; + } +} + +uint32_t trng_rand(void) +{ + uint32_t return_value; + enum ncl_status status = NCL_STATUS_FAIL; + + /* Don't attempt generate and panic if initialization failed */ + if (state_p->trng_init != NCL_STATUS_OK) + software_panic(PANIC_SW_BAD_RNG, task_get_current()); + + status = NCL_DRBG->power(ctx_p, true); + if (status != NCL_STATUS_OK) { + ccprintf("ERROR! DRBG power returned %x\n", status); + software_panic(PANIC_SW_BAD_RNG, task_get_current()); + } + + status = NCL_SHA->power(ctx_p, true); + if (status != NCL_STATUS_OK) { + ccprintf("ERROR! SHA power returned %x\n", status); + software_panic(PANIC_SW_BAD_RNG, task_get_current()); + } + + status = NCL_DRBG->generate(NULL, NULL, 0, (uint8_t *)&return_value, 4); + if (status != NCL_STATUS_OK) { + ccprintf("ERROR! DRBG generate returned %x\r", status); + software_panic(PANIC_SW_BAD_RNG, task_get_current()); + } + + /* + * Failing to turn off the blocks has power implications but wouldn't + * result in feeding the caller a bad result, hence no panics enabled + * for failing to turn off the hardware + */ + status = NCL_DRBG->power(ctx_p, false); + if (status != NCL_STATUS_OK) + ccprintf("ERROR! DRBG power returned %x\n", status); + + status = NCL_SHA->power(ctx_p, false); + if (status != NCL_STATUS_OK) + ccprintf("ERROR! SHA power returned %x\n", status); + + return return_value; +} + +test_mockable void trng_exit(void) +{ + enum ncl_status status = NCL_STATUS_FAIL; + + status = NCL_DRBG->clear(ctx_p); + if (status != NCL_STATUS_OK) + ccprintf("ERROR! DRBG clear returned %x\r", status); + + status = NCL_DRBG->uninstantiate(ctx_p); + if (status != NCL_STATUS_OK) + ccprintf("ERROR! DRBG uninstantiate returned %x\r", status); + + status = NCL_DRBG->power(ctx_p, false); + if (status != NCL_STATUS_OK) + ccprintf("ERROR! DRBG power returned %x\n", status); + + status = NCL_SHA->power(ctx_p, false); + if (status != NCL_STATUS_OK) + ccprintf("ERROR! SHA power returned %x\n", status); +} diff --git a/chip/npcx/uart.c b/chip/npcx/uart.c index efe991ec0b..d77c3579c5 100644 --- a/chip/npcx/uart.c +++ b/chip/npcx/uart.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,7 @@ /* UART module for Chrome EC */ #include "clock.h" +#include "clock_chip.h" #include "common.h" #include "console.h" #include "gpio.h" @@ -13,7 +14,6 @@ #include "hwtimer_chip.h" #include "lpc.h" #include "registers.h" -#include "clock_chip.h" #include "system.h" #include "task.h" #include "timer.h" @@ -21,12 +21,12 @@ #include "uartn.h" #include "util.h" -#define CONSOLE_UART CONFIG_CONSOLE_UART +#define CONSOLE_UART CONFIG_CONSOLE_UART #if CONSOLE_UART -#define CONSOLE_UART_IRQ NPCX_IRQ_UART2 +#define CONSOLE_UART_IRQ NPCX_IRQ_UART2 #else -#define CONSOLE_UART_IRQ NPCX_IRQ_UART +#define CONSOLE_UART_IRQ NPCX_IRQ_UART #endif static int init_done; @@ -54,7 +54,7 @@ static int altpad_tx_len; */ static timestamp_t last_default_pad_rx_time; -static const uint32_t block_alt_timeout_us = 500*MSEC; +static const uint32_t block_alt_timeout_us = 500 * MSEC; #else @@ -197,7 +197,7 @@ int uart_read_char(void) } /* Interrupt handler for Console UART */ -void uart_ec_interrupt(void) +static void uart_ec_interrupt(void) { #ifdef CONFIG_UART_PAD_SWITCH if (pad == UART_ALTERNATE_PAD) { @@ -209,7 +209,8 @@ void uart_ec_interrupt(void) } if (uartn_tx_ready(NPCX_UART_PORT0)) { if (altpad_tx_pos < altpad_tx_len) - uartn_write_char(NPCX_UART_PORT0, + uartn_write_char( + NPCX_UART_PORT0, altpad_tx_buf[altpad_tx_pos++]); else uart_tx_stop(); @@ -319,8 +320,8 @@ int uart_alt_pad_write_read(uint8_t *tx, int tx_len, uint8_t *rx, int rx_len, uint32_t start = __hw_clock_source_read(); int ret = 0; - if ((get_time().val - last_default_pad_rx_time.val) - < block_alt_timeout_us) + if ((get_time().val - last_default_pad_rx_time.val) < + block_alt_timeout_us) return -EC_ERROR_BUSY; cflush(); @@ -381,7 +382,6 @@ int uart_alt_pad_write_read(uint8_t *tx, int tx_len, uint8_t *rx, int rx_len, #endif void uart_init(void) { - uartn_init(CONSOLE_UART); init_done = 1; } diff --git a/chip/npcx/uartn.c b/chip/npcx/uartn.c index 2269e11e7c..66cb30062b 100644 --- a/chip/npcx/uartn.c +++ b/chip/npcx/uartn.c @@ -1,76 +1,75 @@ /* - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* UART module for Chrome EC */ -#include #include "common.h" -#include -#include #include "registers.h" #include "system.h" #include "task.h" #include "util.h" +#include +#include +#include + #ifdef NPCX_UART_FIFO_SUPPORT /* Enable UART Tx FIFO empty interrupt */ -#define NPCX_UART_TX_EMPTY_INT_EN(n) \ - (SET_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_TEMPTY_EN)) +#define NPCX_UART_TX_EMPTY_INT_EN(n) \ + (SET_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_TEMPTY_EN)) /* True if UART Tx FIFO empty interrupt is enabled */ -#define NPCX_UART_TX_EMPTY_INT_IS_EN(n) \ - (IS_BIT_SET(NPCX_UFTCTL(n), NPCX_UFTCTL_TEMPTY_EN)) +#define NPCX_UART_TX_EMPTY_INT_IS_EN(n) \ + (IS_BIT_SET(NPCX_UFTCTL(n), NPCX_UFTCTL_TEMPTY_EN)) /* Disable UART Tx FIFO empty interrupt */ -#define NPCX_UART_TX_EMPTY_INT_DIS(n) \ - (CLEAR_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_TEMPTY_EN)) +#define NPCX_UART_TX_EMPTY_INT_DIS(n) \ + (CLEAR_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_TEMPTY_EN)) /* True if the Tx FIFO is not completely full */ -#define NPCX_UART_TX_IS_READY(n) \ - (!(GET_FIELD(NPCX_UFTSTS(n), NPCX_UFTSTS_TEMPTY_LVL) == 0)) +#define NPCX_UART_TX_IS_READY(n) \ + (!(GET_FIELD(NPCX_UFTSTS(n), NPCX_UFTSTS_TEMPTY_LVL) == 0)) /* Enable UART Tx "not" in transmission interrupt */ -#define NPCX_UART_TX_NXMIP_INT_EN(n) \ - (SET_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_NXMIPEN)) +#define NPCX_UART_TX_NXMIP_INT_EN(n) \ + (SET_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_NXMIPEN)) /* Disable UART Tx "not" in transmission interrupt */ -#define NPCX_UART_TX_NXMIP_INT_DIS(n) \ - (CLEAR_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_NXMIPEN)) +#define NPCX_UART_TX_NXMIP_INT_DIS(n) \ + (CLEAR_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_NXMIPEN)) /* * True if Tx is in progress * (i.e. FIFO is not empty or last byte in TSFT (Transmit Shift register) * is not sent) */ -#define NPCX_UART_TX_IN_XMIT(n) \ - (!IS_BIT_SET(NPCX_UFTSTS(n), NPCX_UFTSTS_NXMIP)) +#define NPCX_UART_TX_IN_XMIT(n) (!IS_BIT_SET(NPCX_UFTSTS(n), NPCX_UFTSTS_NXMIP)) /* * Enable to generate interrupt when there is at least one byte * in the receive FIFO */ -#define NPCX_UART_RX_INT_EN(n) \ - (SET_BIT(NPCX_UFRCTL(n), NPCX_UFRCTL_RNEMPTY_EN)) +#define NPCX_UART_RX_INT_EN(n) (SET_BIT(NPCX_UFRCTL(n), NPCX_UFRCTL_RNEMPTY_EN)) /* True if at least one byte is in the receive FIFO */ -#define NPCX_UART_RX_IS_AVAILABLE(n) \ - (IS_BIT_SET(NPCX_UFRSTS(n), NPCX_UFRSTS_RFIFO_NEMPTY_STS)) +#define NPCX_UART_RX_IS_AVAILABLE(n) \ + (IS_BIT_SET(NPCX_UFRSTS(n), NPCX_UFRSTS_RFIFO_NEMPTY_STS)) #else /* Enable UART Tx buffer empty interrupt */ -#define NPCX_UART_TX_EMPTY_INT_EN(n) (NPCX_UICTRL(n) |= 0x20) +#define NPCX_UART_TX_EMPTY_INT_EN(n) (NPCX_UICTRL(n) |= 0x20) /* True if UART Tx buffer empty interrupt is enabled */ -#define NPCX_UART_TX_EMPTY_INT_IS_EN(n) (NPCX_UICTRL(n) & 0x20) +#define NPCX_UART_TX_EMPTY_INT_IS_EN(n) (NPCX_UICTRL(n) & 0x20) /* Disable UART Tx buffer empty interrupt */ -#define NPCX_UART_TX_EMPTY_INT_DIS(n) (NPCX_UICTRL(n) &= ~0x20) +#define NPCX_UART_TX_EMPTY_INT_DIS(n) (NPCX_UICTRL(n) &= ~0x20) /* True if 1-byte Tx buffer is empty */ -#define NPCX_UART_TX_IS_READY(n) (NPCX_UICTRL(n) & 0x01) +#define NPCX_UART_TX_IS_READY(n) (NPCX_UICTRL(n) & 0x01) /* * True if Tx is in progress * (i.e. Tx buffer is not empty or last byte in TSFT (Transmit Shift register) * is not sent) */ -#define NPCX_UART_TX_IN_XMIT(n) (NPCX_USTAT(n) & 0x40) - /* Enable to generate interrupt when there is data in the receive buffer */ -#define NPCX_UART_RX_INT_EN(n) (NPCX_UICTRL(n) = 0x40) +#define NPCX_UART_TX_IN_XMIT(n) (NPCX_USTAT(n) & 0x40) +/* Enable to generate interrupt when there is data in the receive buffer */ +#define NPCX_UART_RX_INT_EN(n) (NPCX_UICTRL(n) = 0x40) /* True if there is data in the 1-byte Receive buffer */ -#define NPCX_UART_RX_IS_AVAILABLE(n) (NPCX_UICTRL(n) & 0x02) +#define NPCX_UART_RX_IS_AVAILABLE(n) (NPCX_UICTRL(n) & 0x02) #endif struct uart_configs { @@ -79,9 +78,9 @@ struct uart_configs { uint32_t clk_en_msk; }; static const struct uart_configs uart_cfg[] = { - {NPCX_IRQ_UART, CGC_OFFSET_UART, CGC_UART_MASK}, + { NPCX_IRQ_UART, CGC_OFFSET_UART, CGC_UART_MASK }, #ifdef NPCX_SECOND_UART - {NPCX_IRQ_UART2, CGC_OFFSET_UART2, CGC_UART2_MASK}, + { NPCX_IRQ_UART2, CGC_OFFSET_UART2, CGC_UART2_MASK }, #endif }; BUILD_ASSERT(ARRAY_SIZE(uart_cfg) == UART_MODULE_COUNT); @@ -144,7 +143,7 @@ void uartn_tx_start(uint8_t uart_num) void uartn_enable_tx_complete_int(uint8_t uart_num, uint8_t enable) { enable ? NPCX_UART_TX_NXMIP_INT_EN(uart_num) : - NPCX_UART_TX_NXMIP_INT_DIS(uart_num); + NPCX_UART_TX_NXMIP_INT_DIS(uart_num); } #endif @@ -198,7 +197,7 @@ int uartn_read_char(uint8_t uart_num) void uartn_clear_rx_fifo(int channel) { - int scratch __attribute__ ((unused)); + int scratch __attribute__((unused)); /* If '1', that means there is RX data on the FIFO register */ while (NPCX_UART_RX_IS_AVAILABLE(channel)) @@ -211,9 +210,9 @@ static void uartn_set_fifo_mode(uint8_t uart_num) /* Enable the UART FIFO mode */ SET_BIT(NPCX_UMDSL(uart_num), NPCX_UMDSL_FIFO_MD); /* Disable all Tx interrupts */ - NPCX_UFTCTL(uart_num) &= ~(BIT(NPCX_UFTCTL_TEMPTY_LVL_EN) | - BIT(NPCX_UFTCTL_TEMPTY_EN) | - BIT(NPCX_UFTCTL_NXMIPEN)); + NPCX_UFTCTL(uart_num) &= + ~(BIT(NPCX_UFTCTL_TEMPTY_LVL_EN) | BIT(NPCX_UFTCTL_TEMPTY_EN) | + BIT(NPCX_UFTCTL_NXMIPEN)); } #endif diff --git a/chip/npcx/uartn.h b/chip/npcx/uartn.h index e5326f72b8..ce111f11d9 100644 --- a/chip/npcx/uartn.h +++ b/chip/npcx/uartn.h @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Chromium OS Authors. All rights reserved. + * Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,7 +22,7 @@ void uartn_init(uint8_t uart_num); */ void uartn_tx_start(uint8_t uart_num); - /* Disable the UART transmit interrupt. */ +/* Disable the UART transmit interrupt. */ void uartn_tx_stop(uint8_t uart_num, uint8_t sleep_ena); /* Flush the transmit FIFO. */ @@ -62,4 +62,4 @@ void uartn_rx_int_en(uint8_t uart_num); void uartn_wui_en(uint8_t uart_num); /* Enable/disable Tx NXMIP (No Transmit In Progress) interrupt */ void uartn_enable_tx_complete_int(uint8_t uart_num, uint8_t enable); -#endif /* __CROS_EC_UARTN_H */ +#endif /* __CROS_EC_UARTN_H */ diff --git a/chip/npcx/watchdog.c b/chip/npcx/watchdog.c index ec94babe6d..1172f3ac12 100644 --- a/chip/npcx/watchdog.c +++ b/chip/npcx/watchdog.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,20 +8,19 @@ #include "clock.h" #include "common.h" #include "console.h" -#include "registers.h" -#include "hwtimer_chip.h" #include "gpio.h" #include "hooks.h" -#include "timer.h" +#include "hwtimer_chip.h" +#include "registers.h" +#include "system_chip.h" #include "task.h" +#include "timer.h" #include "util.h" -#include "system_chip.h" #include "watchdog.h" /* WDCNT value for watchdog period */ -#define WDCNT_VALUE ((CONFIG_WATCHDOG_PERIOD_MS*INT_32K_CLOCK) / (1024*1000)) -/* Delay time for warning timer to print watchdog info through UART */ -#define WDCNT_DELAY WDCNT_VALUE +#define WDCNT_VALUE \ + ((CONFIG_WATCHDOG_PERIOD_MS * INT_32K_CLOCK) / (1024 * 1000)) void watchdog_init_warning_timer(void) { @@ -34,30 +33,19 @@ void watchdog_init_warning_timer(void) * PRE_8 = (Ttick_unit/T32K) - 1 * Unit: 1 msec */ - NPCX_ITPRE(ITIM_WDG_NO) = DIV_ROUND_NEAREST(1000*INT_32K_CLOCK, - SECOND) - 1; + NPCX_ITPRE(ITIM_WDG_NO) = + DIV_ROUND_NEAREST(1000 * INT_32K_CLOCK, SECOND) - 1; /* Event module disable */ CLEAR_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN); - /* ITIM count down : event expired*/ - NPCX_ITCNT(ITIM_WDG_NO) = CONFIG_AUX_TIMER_PERIOD_MS - 1; + /* ITIM count down : event expired */ + NPCX_ITCNT(ITIM_WDG_NO) = CONFIG_AUX_TIMER_PERIOD_MS; /* Event module enable */ SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN); /* Enable interrupt of ITIM */ task_enable_irq(ITIM_INT(ITIM_WDG_NO)); } -static uint8_t watchdog_count(void) -{ - uint8_t cnt; - /* Wait for two consecutive equal values are read */ - do { - cnt = NPCX_TWMWD; - } while (cnt != NPCX_TWMWD); - - return cnt; -} - static timestamp_t last_watchdog_touch; void watchdog_stop_and_unlock(void) { @@ -79,10 +67,26 @@ static void touch_watchdog_count(void) last_watchdog_touch = get_time(); } -void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp) +static void watchdog_reload_warning_timer(void) { - int wd_cnt; + /* Disable warning timer module */ + CLEAR_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN); + /* Wait for module disable to take effect before updating count */ + while (IS_BIT_SET(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN)) + ; + /* Reload the warning timer count */ + NPCX_ITCNT(ITIM_WDG_NO) = CONFIG_AUX_TIMER_PERIOD_MS; + + /* enable warning timer module */ + SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN); + /* Wait for module enable */ + while (!IS_BIT_SET(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN)) + ; +} + +void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp) +{ #ifdef CONFIG_TASK_PROFILING /* * Perform IRQ profiling accounting. This is normally done by @@ -94,25 +98,8 @@ void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp) /* Clear timeout status for event */ SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_TO_STS); - /* Read watchdog counter from TWMWD */ - wd_cnt = watchdog_count(); -#if DEBUG_WDG - panic_printf("WD (%d)\r\n", wd_cnt); -#endif - if (wd_cnt <= WDCNT_DELAY) { - /* - * Touch watchdog to let UART have enough time - * to print panic info - */ - touch_watchdog_count(); - - /* Print panic info */ - watchdog_trace(excep_lr, excep_sp); - cflush(); - - /* Trigger watchdog immediately */ - system_watchdog_reset(); - } + /* Print panic info */ + watchdog_trace(excep_lr, excep_sp); } /* ISR for watchdog warning naked will keep SP & LR */ @@ -121,18 +108,18 @@ void IRQ_HANDLER(ITIM_INT(ITIM_WDG_NO))(void) { /* Naked call so we can extract raw LR and SP */ asm volatile("mov r0, lr\n" - "mov r1, sp\n" - /* Must push registers in pairs to keep 64-bit aligned - * stack for ARM EABI. This also conveninently saves - * R0=LR so we can pass it to task_resched_if_needed. */ - "push {r0, lr}\n" - "bl watchdog_check\n" - "pop {r0, lr}\n" - "b task_resched_if_needed\n"); + "mov r1, sp\n" + /* Must push registers in pairs to keep 64-bit aligned + * stack for ARM EABI. This also conveninently saves + * R0=LR so we can pass it to task_resched_if_needed. */ + "push {r0, lr}\n" + "bl watchdog_check\n" + "pop {r0, lr}\n" + "b task_resched_if_needed\n"); } const struct irq_priority __keep IRQ_PRIORITY(ITIM_INT(ITIM_WDG_NO)) -__attribute__((section(".rodata.irqprio"))) -= {ITIM_INT(ITIM_WDG_NO), 0}; + __attribute__((section(".rodata.irqprio"))) = { ITIM_INT(ITIM_WDG_NO), + 0 }; /* put the watchdog at the highest priority */ void watchdog_reload(void) @@ -140,6 +127,8 @@ void watchdog_reload(void) /* Disable watchdog interrupt */ task_disable_irq(ITIM_INT(ITIM_WDG_NO)); + watchdog_reload_warning_timer(); + #if 1 /* mark this for testing watchdog */ /* Touch watchdog & reset software counter */ touch_watchdog_count(); @@ -153,14 +142,14 @@ DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); int watchdog_init(void) { #if SUPPORT_WDG + const uint32_t pre_wdcnt = WDCNT_VALUE; + /* Touch watchdog before init if it is already running */ if (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WD_RUN)) touch_watchdog_count(); /* Keep prescaler ratio timer0 clock to 1:1024 */ NPCX_TWCP = 0x0A; - /* Keep prescaler ratio watchdog clock to 1:1 */ - NPCX_WDCP = 0; /* Clear watchdog reset status initially*/ SET_BIT(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS); @@ -175,13 +164,30 @@ int watchdog_init(void) SET_BIT(NPCX_T0CSR, NPCX_T0CSR_TESDIS); /* - * Set WDCNT initial reload value and T0OUT timeout period - * 1. Watchdog clock source is 32768/1024 Hz and disable T0OUT. - * 2. ITIM16 will be issued to check WDCNT is under WDCNT_DELAY or not - * 3. Set RST to upload TWDT0 & WDCNT + * Calculate and set WDCNT initial reload value and T0OUT timeout + * period + * When WDCNT counts down to 0: generate watchdog reset */ - /* Set WDCNT --> WDCNT=0 will generate watchdog reset */ - NPCX_WDCNT = WDCNT_VALUE + WDCNT_DELAY; + if (pre_wdcnt <= 255) { + /* Keep prescaler ratio watchdog clock to 1:1 */ + NPCX_WDCP = 0; + NPCX_WDCNT = pre_wdcnt; + } else { + uint8_t wdcp; + uint8_t pre_scal; + + pre_scal = DIV_ROUND_UP(pre_wdcnt, 255); + + /* + * Find the smallest power of 2 greater than or equal to the + * prescaler + */ + wdcp = __fls(pre_scal - 1) + 1; + pre_scal = 1 << wdcp; + + NPCX_WDCP = wdcp; + NPCX_WDCNT = pre_wdcnt / pre_scal; + } /* Disable interrupt */ interrupt_disable(); diff --git a/chip/npcx/wov.c b/chip/npcx/wov.c index c4f68f5369..8616cdd001 100644 --- a/chip/npcx/wov.c +++ b/chip/npcx/wov.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -26,7 +26,7 @@ #define CPRINTS(...) #else #define CPUTS(outstr) cputs(CC_AUDIO_CODEC, outstr) -#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ##args) #endif /* WOV FIFO status. */ @@ -64,106 +64,106 @@ #define WOV_FMUL2_CLK_TUNING_DELAY_TIME (4 * 1000) /* The size of RAM buffer to store the voice data */ -#define VOICE_BUF_SIZE 16000 +#define VOICE_BUF_SIZE 16000 /* PLL setting options. */ struct wov_pll_set_options_val { - uint8_t pll_indv; /* Input Divider */ - uint16_t pll_fbdv; /* Feedback Divider */ - uint8_t pll_otdv1; /* Output devide 1. */ - uint8_t pll_otdv2; /* Output devide 2. */ + uint8_t pll_indv; /* Input Divider */ + uint16_t pll_fbdv; /* Feedback Divider */ + uint8_t pll_otdv1; /* Output devide 1. */ + uint8_t pll_otdv2; /* Output devide 2. */ uint32_t pll_ext_div; /* Index for the table pll_ext_div */ }; /* PLL External Divider Load Values. */ struct wov_pll_ext_div_val { - uint8_t pll_ediv; /* Required PLL external divider */ + uint8_t pll_ediv; /* Required PLL external divider */ uint8_t pll_ediv_dc; /* Required PLL external divider DC */ }; static const struct wov_pll_ext_div_val pll_ext_div[] = { - {0x2F, 0x78}, /* 12 */ - {0x57, 0x7C}, /* 13 */ - {0x2B, 0x7C}, /* 14 */ - {0x55, 0x7E}, /* 15 */ - {0x2A, 0x7E}, /* 16 */ - {0x15, 0x7F}, /* 17 */ - {0x4A, 0x7F}, /* 18 */ - {0x65, 0x3F}, /* 19 */ - {0x32, 0x3F}, /* 20 */ - {0x19, 0x5F}, /* 21 */ - {0x4C, 0x5F}, /* 22 */ - {0x66, 0x2F}, /* 23 */ - {0x73, 0x2F}, /* 24 */ - {0x39, 0x57}, /* 25 */ - {0x5C, 0x57}, /* 26 */ - {0x6E, 0x2B}, /* 27 */ - {0x77, 0x2B}, /* 28 */ - {0x3B, 0x55}, /* 29 */ - {0x5D, 0x55}, /* 30 */ - {0x2E, 0x2A}, /* 31 */ - {0x17, 0x2A}, /* 32 */ - {0x4B, 0x15}, /* 33 */ - {0x25, 0x15}, /* 34 */ - {0x52, 0x4A}, /* 35 */ - {0x69, 0x4A}, /* 36 */ - {0x34, 0x65}, /* 37 */ - {0x1A, 0x65}, /* 38 */ - {0x0D, 0x32}, /* 39 */ - {0x46, 0x32}, /* 40 */ - {0x63, 0x19}, /* 41 */ - {0x31, 0x19}, /* 42 */ - {0x58, 0x4C}, /* 43 */ - {0x6C, 0x4C}, /* 44 */ - {0x76, 0x66}, /* 45 */ - {0x7B, 0x66}, /* 46 */ - {0x3D, 0x73}, /* 47 */ - {0x5E, 0x73}, /* 48 */ - {0x6F, 0x39}, /* 49 */ - {0x37, 0x39}, /* 50 */ - {0x5B, 0x5C}, /* 51 */ - {0x2D, 0x5C}, /* 52 */ - {0x56, 0x6E}, /* 53 */ - {0x6B, 0x6E}, /* 54 */ - {0x35, 0x77}, /* 55 */ - {0x5A, 0x77}, /* 56 */ - {0x6D, 0x3B}, /* 57 */ - {0x36, 0x3B}, /* 58 */ - {0x1B, 0x5D}, /* 59 */ - {0x4D, 0x5D}, /* 60 */ - {0x26, 0x2E}, /* 61 */ - {0x13, 0x2E}, /* 62 */ - {0x49, 0x17}, /* 63 */ - {0x24, 0x17}, /* 64 */ - {0x12, 0x4B}, /* 65 */ - {0x09, 0x4B}, /* 66 */ - {0x44, 0x25} /* 67 */ + { 0x2F, 0x78 }, /* 12 */ + { 0x57, 0x7C }, /* 13 */ + { 0x2B, 0x7C }, /* 14 */ + { 0x55, 0x7E }, /* 15 */ + { 0x2A, 0x7E }, /* 16 */ + { 0x15, 0x7F }, /* 17 */ + { 0x4A, 0x7F }, /* 18 */ + { 0x65, 0x3F }, /* 19 */ + { 0x32, 0x3F }, /* 20 */ + { 0x19, 0x5F }, /* 21 */ + { 0x4C, 0x5F }, /* 22 */ + { 0x66, 0x2F }, /* 23 */ + { 0x73, 0x2F }, /* 24 */ + { 0x39, 0x57 }, /* 25 */ + { 0x5C, 0x57 }, /* 26 */ + { 0x6E, 0x2B }, /* 27 */ + { 0x77, 0x2B }, /* 28 */ + { 0x3B, 0x55 }, /* 29 */ + { 0x5D, 0x55 }, /* 30 */ + { 0x2E, 0x2A }, /* 31 */ + { 0x17, 0x2A }, /* 32 */ + { 0x4B, 0x15 }, /* 33 */ + { 0x25, 0x15 }, /* 34 */ + { 0x52, 0x4A }, /* 35 */ + { 0x69, 0x4A }, /* 36 */ + { 0x34, 0x65 }, /* 37 */ + { 0x1A, 0x65 }, /* 38 */ + { 0x0D, 0x32 }, /* 39 */ + { 0x46, 0x32 }, /* 40 */ + { 0x63, 0x19 }, /* 41 */ + { 0x31, 0x19 }, /* 42 */ + { 0x58, 0x4C }, /* 43 */ + { 0x6C, 0x4C }, /* 44 */ + { 0x76, 0x66 }, /* 45 */ + { 0x7B, 0x66 }, /* 46 */ + { 0x3D, 0x73 }, /* 47 */ + { 0x5E, 0x73 }, /* 48 */ + { 0x6F, 0x39 }, /* 49 */ + { 0x37, 0x39 }, /* 50 */ + { 0x5B, 0x5C }, /* 51 */ + { 0x2D, 0x5C }, /* 52 */ + { 0x56, 0x6E }, /* 53 */ + { 0x6B, 0x6E }, /* 54 */ + { 0x35, 0x77 }, /* 55 */ + { 0x5A, 0x77 }, /* 56 */ + { 0x6D, 0x3B }, /* 57 */ + { 0x36, 0x3B }, /* 58 */ + { 0x1B, 0x5D }, /* 59 */ + { 0x4D, 0x5D }, /* 60 */ + { 0x26, 0x2E }, /* 61 */ + { 0x13, 0x2E }, /* 62 */ + { 0x49, 0x17 }, /* 63 */ + { 0x24, 0x17 }, /* 64 */ + { 0x12, 0x4B }, /* 65 */ + { 0x09, 0x4B }, /* 66 */ + { 0x44, 0x25 } /* 67 */ }; /* WOV interrupts */ static const uint8_t wov_interupts[] = { - 0, /* VAD_INTEN */ - 1, /* VAD_WKEN */ - 8, /* CFIFO_NE_IE */ - 9, /* CFIFO_OIT_IE */ + 0, /* VAD_INTEN */ + 1, /* VAD_WKEN */ + 8, /* CFIFO_NE_IE */ + 9, /* CFIFO_OIT_IE */ 10, /* CFIFO_OWT_WE */ 11, /* CFIFO_OVRN_IE */ 12, /* I2S_FIFO_OVRN_IE */ - 13 /* I2S_FIFO_UNDRN_IE */ + 13 /* I2S_FIFO_UNDRN_IE */ }; struct wov_ppl_divider { uint16_t pll_frame_len; /* PLL frame length. */ - uint16_t pll_fbdv; /* PLL feedback divider. */ - uint8_t pll_indv; /* PLL Input Divider. */ - uint8_t pll_otdv1; /* PLL Output Divider 1. */ - uint8_t pll_otdv2; /* PLL Output Divider 2. */ - uint8_t pll_ediv; /* PLL External Divide Factor. */ + uint16_t pll_fbdv; /* PLL feedback divider. */ + uint8_t pll_indv; /* PLL Input Divider. */ + uint8_t pll_otdv1; /* PLL Output Divider 1. */ + uint8_t pll_otdv2; /* PLL Output Divider 2. */ + uint8_t pll_ediv; /* PLL External Divide Factor. */ }; struct wov_cfifo_buf { uint32_t *buf; /* Pointer to a buffer. */ - int size; /* Buffer size in words. */ + int size; /* Buffer size in words. */ }; struct wov_config wov_conf; @@ -205,11 +205,11 @@ void wov_cfifo_read_handler_l(uint32_t num_elements) cfifo_buf.size -= num_elements; } -static enum ec_error_list wov_calc_pll_div_s(int32_t d_in, - int32_t total_div, int32_t vco_freq, - struct wov_ppl_divider *pll_div) +static enum ec_error_list wov_calc_pll_div_s(int32_t d_in, int32_t total_div, + int32_t vco_freq, + struct wov_ppl_divider *pll_div) { - int32_t d_1, d_2, d_e; + int32_t d_1, d_2, d_e; /* * Please see comments in wov_calc_pll_div_l function below. @@ -221,10 +221,10 @@ static enum ec_error_list wov_calc_pll_div_s(int32_t d_in, continue; if (total_div == (d_in * d_e * d_1 * d_2)) { - pll_div->pll_indv = d_in; + pll_div->pll_indv = d_in; pll_div->pll_otdv1 = d_1; pll_div->pll_otdv2 = d_2; - pll_div->pll_ediv = d_e; + pll_div->pll_ediv = d_e; return EC_SUCCESS; } } @@ -243,7 +243,8 @@ static enum ec_error_list wov_calc_pll_div_s(int32_t d_in, * @return None */ static enum ec_error_list wov_calc_pll_div_l(uint32_t i2s_clk_freq, - uint32_t sample_rate, struct wov_ppl_divider *pll_div) + uint32_t sample_rate, + struct wov_ppl_divider *pll_div) { int32_t d_f; int32_t total_div; @@ -292,12 +293,11 @@ static enum ec_error_list wov_calc_pll_div_l(uint32_t i2s_clk_freq, if ((vco_freq < 500) || (vco_freq > 1600)) continue; if (wov_calc_pll_div_s(d_in, total_div, - vco_freq, pll_div) == - EC_SUCCESS) { - pll_div->pll_fbdv = d_f; + vco_freq, + pll_div) == EC_SUCCESS) { + pll_div->pll_fbdv = d_f; return EC_SUCCESS; } - } } } @@ -340,12 +340,13 @@ static enum ec_error_list wov_set_i2s_config_l(void) int32_t start_delay_0, start_delay_1; ret_code = wov_calc_pll_div_l(wov_conf.i2s_clock, - wov_conf.sample_per_sec, &pll_div); + wov_conf.sample_per_sec, &pll_div); if (ret_code == EC_SUCCESS) { /* Configure the PLL. */ - ret_code = wov_pll_clk_div_config( - pll_div.pll_otdv1, pll_div.pll_otdv2, pll_div.pll_fbdv, - pll_div.pll_indv); + ret_code = wov_pll_clk_div_config(pll_div.pll_otdv1, + pll_div.pll_otdv2, + pll_div.pll_fbdv, + pll_div.pll_indv); if (ret_code != EC_SUCCESS) return ret_code; @@ -414,10 +415,10 @@ static enum ec_error_list wov_set_i2s_config_l(void) udelay(100); ret_code = wov_i2s_channel_config(0, wov_conf.bit_depth, - trigger_0, start_delay_0); + trigger_0, start_delay_0); ret_code = wov_i2s_channel_config(1, wov_conf.bit_depth, - trigger_1, start_delay_1); + trigger_1, start_delay_1); } return EC_SUCCESS; @@ -471,14 +472,14 @@ static enum ec_error_list wov_set_mic_source_l(void) case WOV_SRC_LEFT: if (wov_conf.bit_depth == 16) SET_FIELD(NPCX_WOV_FIFO_CNT, - NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x00); + NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x00); else SET_FIELD(NPCX_WOV_FIFO_CNT, - NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x02); + NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x02); SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_SEL_LEFT, - 0x01); + 0x01); SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_SEL_RIGHT, - 0x01); + 0x01); apm_digital_mixer_config(APM_OUT_MIX_NORMAL_INPUT, APM_OUT_MIX_NO_INPUT); apm_set_vad_input_channel(APM_IN_LEFT); @@ -493,11 +494,11 @@ static enum ec_error_list wov_set_mic_source_l(void) SET_FIELD(NPCX_WOV_FIFO_CNT, NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x02); SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_SEL_LEFT, - 0x01); + 0x01); SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_SEL_RIGHT, - 0x01); + 0x01); apm_digital_mixer_config(APM_OUT_MIX_CROSS_INPUT, - APM_OUT_MIX_NO_INPUT); + APM_OUT_MIX_NO_INPUT); apm_set_vad_input_channel(APM_IN_RIGHT); wov_i2s_channel1_disable(1); break; @@ -505,16 +506,16 @@ static enum ec_error_list wov_set_mic_source_l(void) case WOV_SRC_MONO: if (wov_conf.bit_depth == 16) SET_FIELD(NPCX_WOV_FIFO_CNT, - NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x01); + NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x01); else SET_FIELD(NPCX_WOV_FIFO_CNT, - NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x03); + NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x03); SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_SEL_LEFT, - 0x02); + 0x02); SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_SEL_RIGHT, - 0x02); + 0x02); apm_digital_mixer_config(APM_OUT_MIX_NORMAL_INPUT, - APM_OUT_MIX_NORMAL_INPUT); + APM_OUT_MIX_NORMAL_INPUT); apm_set_vad_input_channel(APM_IN_AVERAGE_LEFT_RIGHT); wov_i2s_channel1_disable(0); break; @@ -522,14 +523,14 @@ static enum ec_error_list wov_set_mic_source_l(void) case WOV_SRC_STEREO: if (wov_conf.bit_depth == 16) SET_FIELD(NPCX_WOV_FIFO_CNT, - NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x01); + NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x01); else SET_FIELD(NPCX_WOV_FIFO_CNT, - NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x03); + NPCX_WOV_FIFO_CNT_CFIFO_ISEL, 0x03); SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_SEL_LEFT, - 0x01); + 0x01); SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_SEL_RIGHT, - 0x01); + 0x01); apm_digital_mixer_config(APM_OUT_MIX_NORMAL_INPUT, APM_OUT_MIX_NORMAL_INPUT); wov_i2s_channel1_disable(0); @@ -579,14 +580,14 @@ static void wov_under_over_error_handler(int *count, uint32_t *last_time) * * @return None */ -void wov_interrupt_handler(void) +static void wov_interrupt_handler(void) { uint32_t wov_status; uint32_t wov_inten; wov_inten = GET_FIELD(NPCX_WOV_WOV_INTEN, NPCX_WOV_STATUS_BITS); wov_status = wov_inten & - GET_FIELD(NPCX_WOV_STATUS, NPCX_WOV_STATUS_BITS); + GET_FIELD(NPCX_WOV_STATUS, NPCX_WOV_STATUS_BITS); /* * Voice activity detected. @@ -602,7 +603,7 @@ void wov_interrupt_handler(void) WOV_CALLBACK(WOV_EVENT_ERROR_CORE_FIFO_OVERRUN); wov_core_fifo_reset(); } else if (WOV_IS_CFIFO_INT_THRESHOLD(wov_status) && - (cfifo_buf.buf != NULL)) { + (cfifo_buf.buf != NULL)) { /* * Core FIFO threshold or FIFO not empty event occurred. * - Read data from core FIFO to the buffer. @@ -635,7 +636,6 @@ void wov_interrupt_handler(void) wov_i2s_fifo_reset(); } - /* Clear the WoV status register. */ SET_FIELD(NPCX_WOV_STATUS, NPCX_WOV_STATUS_BITS, wov_status); } @@ -651,19 +651,17 @@ DECLARE_IRQ(NPCX_IRQ_WOV, wov_interrupt_handler, 4); static void wov_fmul2_enable(int enable) { if (enable) { - /* If clock disabled, then enable it. */ if (IS_BIT_SET(NPCX_FMUL2_FM2CTRL, - NPCX_FMUL2_FM2CTRL_FMUL2_DIS)) { + NPCX_FMUL2_FM2CTRL_FMUL2_DIS)) { /* Enable clock tuning. */ CLEAR_BIT(NPCX_FMUL2_FM2CTRL, - NPCX_FMUL2_FM2CTRL_TUNE_DIS); + NPCX_FMUL2_FM2CTRL_TUNE_DIS); /* Enable clock. */ CLEAR_BIT(NPCX_FMUL2_FM2CTRL, - NPCX_FMUL2_FM2CTRL_FMUL2_DIS); + NPCX_FMUL2_FM2CTRL_FMUL2_DIS); udelay(WOV_FMUL2_CLK_TUNING_DELAY_TIME); - } } else SET_BIT(NPCX_FMUL2_FM2CTRL, NPCX_FMUL2_FM2CTRL_FMUL2_DIS); @@ -688,7 +686,7 @@ void wov_fmul2_conf_tuning(void) { /* Check if FMUL2 is enabled, then do nothing. */ if (IS_BIT_SET(NPCX_FMUL2_FM2CTRL, NPCX_FMUL2_FM2CTRL_FMUL2_DIS) == - 0x00) + 0x00) return; /* Enable clock tuning. */ @@ -838,6 +836,7 @@ enum ec_error_list wov_set_mode(enum wov_modes wov_mode) case WOV_MODE_RAM_AND_I2S: if ((wov_conf.bit_depth != 16) && (wov_conf.bit_depth != 24)) return EC_ERROR_INVAL; + __fallthrough; case WOV_MODE_I2S: if (apm_get_adc_i2s_dmic_rate() == APM_DMIC_RATE_0_75) wov_dmic_clk_config(1, WOV_DMIC_DIV_BY_4); @@ -968,7 +967,6 @@ void wov_set_clk_selection(enum wov_clk_src_sel clk_src) wov_fmul2_enable(0); else wov_pll_enable(0); - } /** @@ -981,9 +979,9 @@ void wov_set_clk_selection(enum wov_clk_src_sel clk_src) * PLL External Divider Load Values table. * @return EC_ERROR_INVAL or EC_SUCCESS */ -enum ec_error_list wov_pll_clk_ext_div_config( - enum wov_pll_ext_div_sel ext_div_sel, - uint32_t div_factor) +enum ec_error_list +wov_pll_clk_ext_div_config(enum wov_pll_ext_div_sel ext_div_sel, + uint32_t div_factor) { /* Sets the clock division factor for the PLL external divider. * The divide factor should be in the range of 2 to 67. @@ -1045,13 +1043,13 @@ void wov_pll_enable(int enable) * @return EC_ERROR_INVAL or EC_SUCCESS */ enum ec_error_list wov_pll_clk_div_config(uint32_t out_div_1, - uint32_t out_div_2, - uint32_t feedback_div, - uint32_t in_div) + uint32_t out_div_2, + uint32_t feedback_div, + uint32_t in_div) { /* Parameter check. */ - if ((out_div_1 < 1) || (out_div_1 > 7) || - (out_div_2 < 1) || (out_div_2 > 7)) + if ((out_div_1 < 1) || (out_div_1 > 7) || (out_div_2 < 1) || + (out_div_2 > 7)) return EC_ERROR_INVAL; /* @@ -1255,7 +1253,7 @@ int wov_set_buffer(uint32_t *buf, int size_in_words) cfifo_threshold = wov_get_cfifo_threshold_l(); if (size_in_words != - ((size_in_words / cfifo_threshold) * cfifo_threshold)) + ((size_in_words / cfifo_threshold) * cfifo_threshold)) return EC_ERROR_INVAL; cfifo_buf.buf = buf; @@ -1298,21 +1296,17 @@ void wov_apm_active(int enable) * @return EC_ERROR_INVAL or EC_SUCCESS */ enum ec_error_list wov_i2s_global_config( - enum wov_floating_mode i2s_hiz_data, - enum wov_floating_mode i2s_hiz, - enum wov_clk_inverted_mode clk_invert, - int out_pull_en, - enum wov_pull_upd_down_sel out_pull_mode, - int in_pull_en, - enum wov_pull_upd_down_sel in_pull_mode, - enum wov_test_mode test_mode) + enum wov_floating_mode i2s_hiz_data, enum wov_floating_mode i2s_hiz, + enum wov_clk_inverted_mode clk_invert, int out_pull_en, + enum wov_pull_upd_down_sel out_pull_mode, int in_pull_en, + enum wov_pull_upd_down_sel in_pull_mode, enum wov_test_mode test_mode) { /* Check the parameters correctness. */ if ((i2s_hiz_data == WOV_FLOATING) && - ((GET_FIELD(NPCX_WOV_I2S_CNTL(0), - NPCX_WOV_I2S_CNTL_I2S_ST_DEL) == 0) || - (GET_FIELD(NPCX_WOV_I2S_CNTL(1), - NPCX_WOV_I2S_CNTL_I2S_ST_DEL) == 0))) + ((GET_FIELD(NPCX_WOV_I2S_CNTL(0), NPCX_WOV_I2S_CNTL_I2S_ST_DEL) == + 0) || + (GET_FIELD(NPCX_WOV_I2S_CNTL(1), NPCX_WOV_I2S_CNTL_I2S_ST_DEL) == + 0))) return EC_ERROR_INVAL; /* Set the parameters. */ @@ -1375,9 +1369,9 @@ enum ec_error_list wov_i2s_global_config( * @return EC_ERROR_INVAL or EC_SUCCESS */ enum ec_error_list wov_i2s_channel_config(uint32_t channel_num, - uint32_t bit_count, - enum wov_i2s_chan_trigger trigger, - int32_t start_delay) + uint32_t bit_count, + enum wov_i2s_chan_trigger trigger, + int32_t start_delay) { /* Check the parameters correctnes. */ if ((channel_num != 0) && (channel_num != 1)) @@ -1392,7 +1386,7 @@ enum ec_error_list wov_i2s_channel_config(uint32_t channel_num, /* Set the parameters. */ SET_FIELD(NPCX_WOV_I2S_CNTL(channel_num), NPCX_WOV_I2S_CNTL_I2S_BCNT, - (bit_count - 1)); + (bit_count - 1)); if (trigger == WOV_I2S_SAMPLED_1_AFTER_0) CLEAR_BIT(NPCX_WOV_I2S_CNTL(channel_num), @@ -1459,8 +1453,8 @@ int wov_set_sample_depth(int bits_num) if (wov_conf.mode != WOV_MODE_OFF) return EC_ERROR_INVALID_CONFIG; - if ((bits_num != 16) && (bits_num != 18) && - (bits_num != 20) && (bits_num != 24)) + if ((bits_num != 16) && (bits_num != 18) && (bits_num != 20) && + (bits_num != 24)) return EC_ERROR_INVAL; wov_conf.bit_depth = bits_num; @@ -1529,8 +1523,8 @@ void wov_set_gain(int left_chan_gain, int right_chan_gain) wov_conf.left_chan_gain = left_chan_gain; wov_conf.right_chan_gain = right_chan_gain; - (void) apm_adc_gain_config(APM_ADC_CHAN_GAINS_INDEPENDENT, - left_chan_gain, right_chan_gain); + (void)apm_adc_gain_config(APM_ADC_CHAN_GAINS_INDEPENDENT, + left_chan_gain, right_chan_gain); } /** @@ -1571,10 +1565,10 @@ void wov_enable_agc(int enable) * @param min_applied_gain - Minimum Gain Value to apply to the ADC path. * @return EC_ERROR_INVAL or EC_SUCCESS */ -enum ec_error_list wov_set_agc_config(int stereo, float target, - int noise_gate_threshold, uint8_t hold_time, - uint16_t attack_time, uint16_t decay_time, - float max_applied_gain, float min_applied_gain) +enum ec_error_list +wov_set_agc_config(int stereo, float target, int noise_gate_threshold, + uint8_t hold_time, uint16_t attack_time, uint16_t decay_time, + float max_applied_gain, float min_applied_gain) { int target_code; int ngth_code; @@ -1607,7 +1601,7 @@ enum ec_error_list wov_set_agc_config(int stereo, float target, return EC_ERROR_INVAL; for (attack_time_code = 0; attack_time_code <= 0x0F; - attack_time_code++) { + attack_time_code++) { if (((attack_time_code + 1) * 32) == attack_time) break; } @@ -1622,15 +1616,15 @@ enum ec_error_list wov_set_agc_config(int stereo, float target, return EC_ERROR_INVAL; for (max_applied_gain_code = 0; max_applied_gain_code < 16; - max_applied_gain_code++) { + max_applied_gain_code++) { if ((max_applied_gain_code * 1.5) == max_applied_gain) break; } if (max_applied_gain_code == 16) { for (max_applied_gain_code = 18; max_applied_gain_code < 32; - max_applied_gain_code++) { + max_applied_gain_code++) { if (((max_applied_gain_code * 1.5) - 4) == - max_applied_gain) + max_applied_gain) break; } } @@ -1638,15 +1632,15 @@ enum ec_error_list wov_set_agc_config(int stereo, float target, return EC_ERROR_INVAL; for (min_applied_gain_code = 0; min_applied_gain_code < 16; - min_applied_gain_code++) { + min_applied_gain_code++) { if ((min_applied_gain_code * 1.5) == min_applied_gain) break; } if (min_applied_gain_code == 16) { for (min_applied_gain_code = 18; min_applied_gain_code < 32; - min_applied_gain_code++) { + min_applied_gain_code++) { if (((min_applied_gain_code * 1.5) - 4) == - min_applied_gain) + min_applied_gain) break; } } @@ -1654,14 +1648,14 @@ enum ec_error_list wov_set_agc_config(int stereo, float target, return EC_ERROR_INVAL; gain_cfg.stereo_enable = stereo, - gain_cfg.agc_target = (enum apm_adc_target_out_level) target_code; + gain_cfg.agc_target = (enum apm_adc_target_out_level)target_code; gain_cfg.nois_gate_en = (noise_gate_threshold != 0); - gain_cfg.nois_gate_thold = (enum apm_noise_gate_threshold) ngth_code; - gain_cfg.hold_time = (enum apm_agc_adj_hold_time) hold_time; - gain_cfg.attack_time = (enum apm_gain_ramp_time) attack_time_code; - gain_cfg.decay_time = (enum apm_gain_ramp_time) decay_time_code; - gain_cfg.gain_max = (enum apm_gain_values) max_applied_gain_code; - gain_cfg.gain_min = (enum apm_gain_values) min_applied_gain_code; + gain_cfg.nois_gate_thold = (enum apm_noise_gate_threshold)ngth_code; + gain_cfg.hold_time = (enum apm_agc_adj_hold_time)hold_time; + gain_cfg.attack_time = (enum apm_gain_ramp_time)attack_time_code; + gain_cfg.decay_time = (enum apm_gain_ramp_time)decay_time_code; + gain_cfg.gain_max = (enum apm_gain_values)max_applied_gain_code; + gain_cfg.gain_min = (enum apm_gain_values)min_applied_gain_code; ret_code = apm_adc_auto_gain_config(&gain_cfg); @@ -1676,7 +1670,6 @@ enum ec_error_list wov_set_agc_config(int stereo, float target, */ int wov_set_vad_sensitivity(int sensitivity_db) { - if ((sensitivity_db < 0) || (sensitivity_db > 31)) return EC_ERROR_INVAL; @@ -1752,27 +1745,27 @@ void wov_set_i2s_bclk(uint32_t i2s_clock) * @return EC error code. */ enum ec_error_list wov_set_i2s_tdm_config(int ch0_delay, int ch1_delay, - uint32_t flags) + uint32_t flags) { if (wov_conf.mode != WOV_MODE_OFF) return EC_ERROR_INVALID_CONFIG; - if ((ch0_delay < 0) || (ch0_delay > 496) || - (ch1_delay < -1) || (ch1_delay > 496)) + if ((ch0_delay < 0) || (ch0_delay > 496) || (ch1_delay < -1) || + (ch1_delay > 496)) return EC_ERROR_INVAL; wov_conf.i2s_start_delay_0 = ch0_delay; wov_conf.i2s_start_delay_1 = ch1_delay; SET_FIELD(NPCX_WOV_I2S_CNTL(0), NPCX_WOV_I2S_CNTL_I2S_ST_DEL, - ch0_delay); + ch0_delay); if (ch1_delay == -1) wov_i2s_channel1_disable(1); else { wov_i2s_channel1_disable(0); SET_FIELD(NPCX_WOV_I2S_CNTL(1), NPCX_WOV_I2S_CNTL_I2S_ST_DEL, - ch1_delay); + ch1_delay); } if (flags & 0x0001) @@ -1820,10 +1813,10 @@ void wov_handle_event(enum wov_events event) } #ifdef DEBUG_AUDIO_CODEC -static uint32_t voice_buffer[VOICE_BUF_SIZE] = {0}; +static uint32_t voice_buffer[VOICE_BUF_SIZE] = { 0 }; /* voice data 16Khz 2ch 16bit 1s */ -static int command_wov(int argc, char **argv) +static int command_wov(int argc, const char **argv) { static int bit_clk; static enum wov_dai_format i2s_fmt; @@ -1845,8 +1838,9 @@ static int command_wov(int argc, char **argv) /* Start to capature voice data and store in RAM buffer */ if (strcasecmp(argv[1], "capram") == 0) { if (wov_set_buffer((uint32_t *)voice_buffer, - sizeof(voice_buffer) / sizeof(uint32_t)) - == EC_SUCCESS) { + sizeof(voice_buffer) / + sizeof(uint32_t)) == + EC_SUCCESS) { CPRINTS("Start RAM Catpure..."); wov_start_ram_capture(); return EC_SUCCESS; @@ -1980,8 +1974,9 @@ static int command_wov(int argc, char **argv) wov_set_mode(WOV_MODE_VAD); } else if (strcasecmp(argv[2], "ram") == 0) { if (wov_set_buffer((uint32_t *)voice_buffer, - sizeof(voice_buffer) / sizeof(uint32_t)) - == EC_SUCCESS) + sizeof(voice_buffer) / + sizeof(uint32_t)) == + EC_SUCCESS) wov_set_mode(WOV_MODE_RAM); else return EC_ERROR_INVAL; @@ -1989,8 +1984,9 @@ static int command_wov(int argc, char **argv) wov_set_mode(WOV_MODE_I2S); } else if (strcasecmp(argv[2], "rami2s") == 0) { if (wov_set_buffer((uint32_t *)voice_buffer, - sizeof(voice_buffer) / sizeof(uint32_t)) - == EC_SUCCESS) + sizeof(voice_buffer) / + sizeof(uint32_t)) == + EC_SUCCESS) wov_set_mode(WOV_MODE_RAM_AND_I2S); else return EC_ERROR_INVAL; @@ -2013,7 +2009,7 @@ static int command_wov(int argc, char **argv) if (strcasecmp(argv[1], "fmul2") == 0) { if (strcasecmp(argv[2], "enable") == 0) { CLEAR_BIT(NPCX_FMUL2_FM2CTRL, - NPCX_FMUL2_FM2CTRL_TUNE_DIS); + NPCX_FMUL2_FM2CTRL_TUNE_DIS); return EC_SUCCESS; } if (strcasecmp(argv[2], "disable") == 0) { @@ -2050,22 +2046,22 @@ static int command_wov(int argc, char **argv) } DECLARE_CONSOLE_COMMAND(wov, command_wov, - "init\n" - "mute \n" - "capram\n" - "cfgsrc \n" - "cfgbit <16|18|20|24>\n" - "cfgsfs <8000|12000|16000|24000|32000|48000>\n" - "cfgbck <32fs|48fs|64fs|128fs|256fs>\n" - "cfgfmt \n" - "cfgmod \n" - "cfgtdm [0~496 0~496 0~3]>\n" - "cfgdckV <0.75|1.0|1.2|2.4|3.0>\n" - "cfgdckR <0.75|1.0|1.2|2.4|3.0>\n" - "cfgdckI <0.75|1.0|1.2|2.4|3.0>\n" - "cfgget\n" - "fmul2 \n" - "vadsens <0~31>\n" - "gain <0~31>", - "wov configuration"); + "init\n" + "mute \n" + "capram\n" + "cfgsrc \n" + "cfgbit <16|18|20|24>\n" + "cfgsfs <8000|12000|16000|24000|32000|48000>\n" + "cfgbck <32fs|48fs|64fs|128fs|256fs>\n" + "cfgfmt \n" + "cfgmod \n" + "cfgtdm [0~496 0~496 0~3]>\n" + "cfgdckV <0.75|1.0|1.2|2.4|3.0>\n" + "cfgdckR <0.75|1.0|1.2|2.4|3.0>\n" + "cfgdckI <0.75|1.0|1.2|2.4|3.0>\n" + "cfgget\n" + "fmul2 \n" + "vadsens <0~31>\n" + "gain <0~31>", + "wov configuration"); #endif diff --git a/chip/npcx/wov_chip.h b/chip/npcx/wov_chip.h index dce534c501..b0da9128e1 100644 --- a/chip/npcx/wov_chip.h +++ b/chip/npcx/wov_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -34,10 +34,7 @@ enum wov_mic_source { }; /* Clock source for APM. */ -enum wov_clk_src_sel { - WOV_FMUL2_CLK_SRC = 0, - WOV_PLL_CLK_SRC = 1 -}; +enum wov_clk_src_sel { WOV_FMUL2_CLK_SRC = 0, WOV_PLL_CLK_SRC = 1 }; /* FMUL clock division factore. */ enum wov_fmul_div { @@ -48,10 +45,7 @@ enum wov_fmul_div { }; /* Lock state. */ -enum wov_lock_state { - WOV_UNLOCK = 0, - WOV_LOCK = 1 -}; +enum wov_lock_state { WOV_UNLOCK = 0, WOV_LOCK = 1 }; /* Reference clock source select. */ enum wov_ref_clk_src_sel { @@ -60,10 +54,7 @@ enum wov_ref_clk_src_sel { }; /* PLL external divider select. */ -enum wov_ext_div_sel { - WOV_EXT_DIV_BINARY_CNT = 0, - WOV_EXT_DIV_LFSR_DIV = 1 -}; +enum wov_ext_div_sel { WOV_EXT_DIV_BINARY_CNT = 0, WOV_EXT_DIV_LFSR_DIV = 1 }; /* FMUL output frequency. */ enum wov_fmul_out_freq { @@ -117,10 +108,7 @@ enum wov_interrupt_index { }; /* FIFO DMA request selection. */ -enum wov_dma_req_sel { - WOV_DFLT_ESPI_DMA_REQ = 0, - WOV_FROM_FIFO_DMA_REQUEST -}; +enum wov_dma_req_sel { WOV_DFLT_ESPI_DMA_REQ = 0, WOV_FROM_FIFO_DMA_REQUEST }; /* Core FIFO input select. */ enum wov_core_fifo_in_sel { @@ -131,10 +119,7 @@ enum wov_core_fifo_in_sel { }; /* PLL external divider selector. */ -enum wov_pll_ext_div_sel { - WOV_PLL_EXT_DIV_BIN_CNT = 0, - WOV_PLL_EXT_DIV_LFSR -}; +enum wov_pll_ext_div_sel { WOV_PLL_EXT_DIV_BIN_CNT = 0, WOV_PLL_EXT_DIV_LFSR }; /* Code for events for call back function. */ enum wov_events { @@ -144,7 +129,7 @@ enum wov_events { * need to call to wov_set_buffer to update the buffer * pointer */ WOV_EVENT_DATA_READY = 1, - WOV_EVENT_VAD, /* Voice activity detected */ + WOV_EVENT_VAD, /* Voice activity detected */ WOV_EVENT_ERROR_FIRST = 128, WOV_EVENT_ERROR_CORE_FIFO_OVERRUN = 128, @@ -158,8 +143,8 @@ enum wov_events { enum wov_fifo_errors { WOV_FIFO_NO_ERROR = 0, WOV_CORE_FIFO_OVERRUN = 1, /* 2 : I2S FIFO is underrun. */ - WOV_I2S_FIFO_OVERRUN = 2, /* 3 : I2S FIFO is overrun. */ - WOV_I2S_FIFO_UNDERRUN = 3 /* 4 : I2S FIFO is underrun. */ + WOV_I2S_FIFO_OVERRUN = 2, /* 3 : I2S FIFO is overrun. */ + WOV_I2S_FIFO_UNDERRUN = 3 /* 4 : I2S FIFO is underrun. */ }; @@ -191,12 +176,12 @@ enum wov_modes { /* DAI format. */ enum wov_dai_format { - WOV_DAI_FMT_I2S, /* I2S mode */ + WOV_DAI_FMT_I2S, /* I2S mode */ WOV_DAI_FMT_RIGHT_J, /* Right Justified mode */ - WOV_DAI_FMT_LEFT_J, /* Left Justified mode */ - WOV_DAI_FMT_PCM_A, /* PCM A Audio */ - WOV_DAI_FMT_PCM_B, /* PCM B Audio */ - WOV_DAI_FMT_PCM_TDM /* Time Division Multiplexing */ + WOV_DAI_FMT_LEFT_J, /* Left Justified mode */ + WOV_DAI_FMT_PCM_A, /* PCM A Audio */ + WOV_DAI_FMT_PCM_B, /* PCM B Audio */ + WOV_DAI_FMT_PCM_TDM /* Time Division Multiplexing */ }; struct wov_config { @@ -375,10 +360,10 @@ void wov_enable_agc(int enable); * @param min_applied_gain - Minimum Gain Value to apply to the ADC path. * @return EC_ERROR_INVAL or EC_SUCCESS */ -enum ec_error_list wov_set_agc_config(int stereo, float target, - int noise_gate_threshold, uint8_t hold_time, - uint16_t attack_time, uint16_t decay_time, - float max_applied_gain, float min_applied_gain); +enum ec_error_list +wov_set_agc_config(int stereo, float target, int noise_gate_threshold, + uint8_t hold_time, uint16_t attack_time, uint16_t decay_time, + float max_applied_gain, float min_applied_gain); /** * Sets VAD sensitivity. @@ -438,7 +423,7 @@ void wov_set_i2s_bclk(uint32_t i2s_clock); * @return EC error code. */ enum ec_error_list wov_set_i2s_tdm_config(int ch0_delay, int ch1_delay, - uint32_t flags); + uint32_t flags); /** * Configure FMUL2 clock tunning. @@ -477,8 +462,9 @@ extern void wov_set_clk_selection(enum wov_clk_src_sel clk_src); * PLL External Divider Load Values table. * @return EC_ERROR_INVAL or EC_SUCCESS */ -enum ec_error_list wov_pll_clk_ext_div_config( - enum wov_pll_ext_div_sel ext_div_sel, uint32_t div_factor); +enum ec_error_list +wov_pll_clk_ext_div_config(enum wov_pll_ext_div_sel ext_div_sel, + uint32_t div_factor); /** * PLL power down. @@ -498,9 +484,9 @@ void wov_pll_enable(int enable); * @return EC_ERROR_INVAL or EC_SUCCESS */ enum ec_error_list wov_pll_clk_div_config(uint32_t out_div_1, - uint32_t out_div_2, - uint32_t feedback_div, - uint32_t in_div); + uint32_t out_div_2, + uint32_t feedback_div, + uint32_t in_div); /** * Enables/Disables WoV interrupt. @@ -521,7 +507,7 @@ void wov_interrupt_enable(enum wov_interrupt_index int_index, int enable); * @return None */ void wov_cfifo_config(enum wov_core_fifo_in_sel in_sel, - enum wov_fifo_threshold threshold); + enum wov_fifo_threshold threshold); /** * Start the actual capturing of the Voice data to the RAM. @@ -632,13 +618,10 @@ void wov_handle_event(enum wov_events event); * @return EC_ERROR_INVAL or EC_SUCCESS */ enum ec_error_list wov_i2s_global_config( - enum wov_floating_mode i2s_hiz_data, - enum wov_floating_mode i2s_hiz, - enum wov_clk_inverted_mode clk_invert, - int out_pull_en, enum wov_pull_upd_down_sel out_pull_mode, - int in_pull_en, - enum wov_pull_upd_down_sel in_pull_mode, - enum wov_test_mode test_mode); + enum wov_floating_mode i2s_hiz_data, enum wov_floating_mode i2s_hiz, + enum wov_clk_inverted_mode clk_invert, int out_pull_en, + enum wov_pull_upd_down_sel out_pull_mode, int in_pull_en, + enum wov_pull_upd_down_sel in_pull_mode, enum wov_test_mode test_mode); /** * I2S channel configuration @@ -652,7 +635,8 @@ enum ec_error_list wov_i2s_global_config( * @return EC_ERROR_INVAL or EC_SUCCESS */ enum ec_error_list wov_i2s_channel_config(uint32_t channel_num, - uint32_t bit_count, enum wov_i2s_chan_trigger trigger, - int32_t start_delay); + uint32_t bit_count, + enum wov_i2s_chan_trigger trigger, + int32_t start_delay); #endif /* __CROS_EC_WOV_CHIP_H */ diff --git a/chip/nrf51/bluetooth_le.c b/chip/nrf51/bluetooth_le.c deleted file mode 100644 index 89eb117efd..0000000000 --- a/chip/nrf51/bluetooth_le.c +++ /dev/null @@ -1,537 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "bluetooth_le.h" -#include "include/bluetooth_le.h" -#include "console.h" -#include "ppi.h" -#include "radio.h" -#include "registers.h" -#include "timer.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_BLUETOOTH_LE, outstr) -#define CPRINTS(format, args...) cprints(CC_BLUETOOTH_LE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_LE, format, ## args) - -static void ble2nrf_packet(struct ble_pdu *ble_p, - struct nrf51_ble_packet_t *radio_p) -{ - if (ble_p->header_type_adv) { - radio_p->s0 = ble_p->header.adv.type & 0xf; - radio_p->s0 |= (ble_p->header.adv.txaddr ? - 1 << BLE_ADV_HEADER_TXADD_SHIFT : 0); - radio_p->s0 |= (ble_p->header.adv.rxaddr ? - 1 << BLE_ADV_HEADER_RXADD_SHIFT : 0); - radio_p->length = ble_p->header.adv.length & 0x3f; /* 6 bits */ - } else { - radio_p->s0 = ble_p->header.data.llid & 0x3; - radio_p->s0 |= (ble_p->header.data.nesn ? - 1 << BLE_DATA_HEADER_NESN_SHIFT : 0); - radio_p->s0 |= (ble_p->header.data.sn ? - 1 << BLE_DATA_HEADER_SN_SHIFT : 0); - radio_p->s0 |= (ble_p->header.data.md ? - 1 << BLE_DATA_HEADER_MD_SHIFT : 0); - radio_p->length = ble_p->header.data.length & 0x1f; /* 5 bits */ - } - - if (radio_p->length > 0) - memcpy(radio_p->payload, ble_p->payload, radio_p->length); -} - -static void nrf2ble_packet(struct ble_pdu *ble_p, - struct nrf51_ble_packet_t *radio_p, int type_adv) -{ - if (type_adv) { - ble_p->header_type_adv = 1; - ble_p->header.adv.type = radio_p->s0 & 0xf; - ble_p->header.adv.txaddr = (radio_p->s0 & - BIT(BLE_ADV_HEADER_TXADD_SHIFT)) != 0; - ble_p->header.adv.rxaddr = (radio_p->s0 & - BIT(BLE_ADV_HEADER_RXADD_SHIFT)) != 0; - /* Length check? 6-37 Bytes */ - ble_p->header.adv.length = radio_p->length; - } else { - ble_p->header_type_adv = 0; - ble_p->header.data.llid = radio_p->s0 & 0x3; - ble_p->header.data.nesn = (radio_p->s0 & - BIT(BLE_DATA_HEADER_NESN_SHIFT)) != 0; - ble_p->header.data.sn = (radio_p->s0 & - BIT(BLE_DATA_HEADER_SN_SHIFT)) != 0; - ble_p->header.data.md = (radio_p->s0 & - BIT(BLE_DATA_HEADER_MD_SHIFT)) != 0; - /* Length check? 0-31 Bytes */ - ble_p->header.data.length = radio_p->length; - } - - if (radio_p->length > 0) - memcpy(ble_p->payload, radio_p->payload, radio_p->length); -} - -struct ble_pdu adv_packet; -struct nrf51_ble_packet_t on_air_packet; - -struct ble_pdu rcv_packet; - -int ble_radio_init(uint32_t access_address, uint32_t crc_init_val) -{ - int rv = radio_init(BLE_1MBIT); - - if (rv) - return rv; - NRF51_RADIO_CRCCNF = 3 | NRF51_RADIO_CRCCNF_SKIP_ADDR; /* 3-byte CRC */ - /* x^24 + x^10 + x^9 + x^6 + x^4 + x^3 + x + 1 */ - /* 0x1_0000_0000_0000_0110_0101_1011 */ - NRF51_RADIO_CRCPOLY = 0x100065B; - - NRF51_RADIO_CRCINIT = crc_init_val; - - NRF51_RADIO_TXPOWER = NRF51_RADIO_TXPOWER_0_DBM; - - NRF51_RADIO_BASE0 = access_address << 8; - NRF51_RADIO_PREFIX0 = access_address >> 24; - - if (access_address != BLE_ADV_ACCESS_ADDRESS) - CPRINTF("Initializing radio for data packet.\n"); - - NRF51_RADIO_TXADDRESS = 0; - NRF51_RADIO_RXADDRESSES = 1; - NRF51_RADIO_PCNF0 = NRF51_RADIO_PCNF0_ADV_DATA; - NRF51_RADIO_PCNF1 = NRF51_RADIO_PCNF1_ADV_DATA; - - return rv; - -} - -static struct nrf51_ble_packet_t tx_packet; - -static uint32_t tx_end, rsp_end; - -void ble_tx(struct ble_pdu *pdu) -{ - uint32_t timeout_time; - - ble2nrf_packet(pdu, &tx_packet); - - NRF51_RADIO_PACKETPTR = (uint32_t)&tx_packet; - NRF51_RADIO_END = NRF51_RADIO_PAYLOAD = NRF51_RADIO_ADDRESS = 0; - NRF51_RADIO_RXEN = 0; - NRF51_RADIO_TXEN = 1; - - timeout_time = get_time().val + RADIO_SETUP_TIMEOUT; - while (!NRF51_RADIO_READY) { - if (get_time().val > timeout_time) { - CPRINTF("ERROR DURING RADIO TX SETUP. TRY AGAIN.\n"); - return; - } - } - - timeout_time = get_time().val + RADIO_SETUP_TIMEOUT; - while (!NRF51_RADIO_END) { - if (get_time().val > timeout_time) { - CPRINTF("RADIO DID NOT SHUT DOWN AFTER TX. " - "RECOMMEND REBOOT.\n"); - return; - } - } - NRF51_RADIO_DISABLE = 1; -} - -static struct nrf51_ble_packet_t rx_packet; -int ble_rx(struct ble_pdu *pdu, int timeout, int adv) -{ - uint32_t done; - uint32_t timeout_time; - int ppi_channel_requested; - - /* Prevent illegal wait times */ - if (timeout <= 0) { - NRF51_RADIO_DISABLE = 1; - return EC_ERROR_TIMEOUT; - } - - NRF51_RADIO_PACKETPTR = (uint32_t)&rx_packet; - NRF51_RADIO_END = NRF51_RADIO_PAYLOAD = NRF51_RADIO_ADDRESS = 0; - /* - * These shortcuts cause packet transmission 150 microseconds after - * packet receive, as is the BTLE standard. See NRF51 manual: - * section 17.1.12 - */ - NRF51_RADIO_SHORTS = NRF51_RADIO_SHORTS_READY_START | - NRF51_RADIO_SHORTS_DISABLED_TXEN | - NRF51_RADIO_SHORTS_END_DISABLE; - - /* - * This creates a shortcut that marks the time - * that the payload was received by the radio - * in NRF51_TIMER_CC(0,1) - */ - ppi_channel_requested = NRF51_PPI_CH_RADIO_ADDR__TIMER0CC1; - if (ppi_request_channel(&ppi_channel_requested) == EC_SUCCESS) { - NRF51_PPI_CHEN |= BIT(ppi_channel_requested); - NRF51_PPI_CHENSET |= BIT(ppi_channel_requested); - } - - - NRF51_RADIO_RXEN = 1; - - timeout_time = get_time().val + RADIO_SETUP_TIMEOUT; - while (!NRF51_RADIO_READY) { - if (get_time().val > timeout_time) { - CPRINTF("RADIO NOT SET UP IN TIME. TIMING OUT.\n"); - return EC_ERROR_TIMEOUT; - } - } - - timeout_time = get_time().val + timeout; - do { - if (get_time().val >= timeout_time) { - NRF51_RADIO_DISABLE = 1; - return EC_ERROR_TIMEOUT; - } - done = NRF51_RADIO_END; - } while (!done); - - rsp_end = get_time().le.lo; - - if (NRF51_RADIO_CRCSTATUS == 0) { - CPRINTF("INVALID CRC\n"); - return EC_ERROR_CRC; - } - - nrf2ble_packet(pdu, &rx_packet, adv); - - /* - * Throw error if radio not yet disabled. Something has - * gone wrong. May be in an unexpected state. - */ - if (NRF51_RADIO_DISABLED != 1) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -/* Allow list handling */ -int ble_radio_clear_allow_list(void) -{ - NRF51_RADIO_DACNF = 0; - return EC_SUCCESS; -} - -int ble_radio_read_allow_list_size(uint8_t *ret_size) -{ - int i, size = 0; - uint32_t dacnf = NRF51_RADIO_DACNF; - - /* Count the bits that are set */ - for (i = 0; i < NRF51_RADIO_DACNF_MAX; i++) - if (dacnf & NRF51_RADIO_DACNF_ENA(i)) - size++; - - *ret_size = size; - - return EC_SUCCESS; -} - -int ble_radio_add_device_to_allow_list(const uint8_t *addr_ptr, uint8_t rand) -{ - uint32_t dacnf = NRF51_RADIO_DACNF; - int i; - uint32_t aligned; - - /* Check for duplicates using ble_radio_remove_device? */ - - /* Find a free entry */ - for (i = 0; i < NRF51_RADIO_DACNF_MAX && - (dacnf & NRF51_RADIO_DACNF_ENA(i)); i++) - ; - - if (i == NRF51_RADIO_DACNF_MAX) - return EC_ERROR_OVERFLOW; - - memcpy(&aligned, addr_ptr, 4); - NRF51_RADIO_DAB(i) = aligned; - memcpy(&aligned, addr_ptr + 4, 2); - NRF51_RADIO_DAP(i) = aligned; - - NRF51_RADIO_DACNF = dacnf | NRF51_RADIO_DACNF_ENA(i) | - (rand ? NRF51_RADIO_DACNF_TXADD(i) : 0); - - return EC_SUCCESS; -} - -int ble_radio_remove_device_from_allow_list(const uint8_t *addr_ptr, - uint8_t rand) -{ - int i, dacnf = NRF51_RADIO_DACNF; - - /* Find a matching entry */ - for (i = 0; i < NRF51_RADIO_DACNF_MAX; i++) { - uint32_t dab = NRF51_RADIO_DAB(i), dap = NRF51_RADIO_DAP(i); - - if ((dacnf & NRF51_RADIO_DACNF_ENA(i)) && /* Enabled */ - /* Rand flag matches */ - (rand == ((dacnf & NRF51_RADIO_DACNF_TXADD(i)) != 0)) && - /* Address matches */ - (!memcmp(addr_ptr, &dab, 4)) && - (!memcmp(addr_ptr + 4, &dap, 2))) - break; - } - - if (i == NRF51_RADIO_DACNF_MAX) /* Not found is successfully removed */ - return EC_SUCCESS; - - NRF51_RADIO_DACNF = dacnf & ~((NRF51_RADIO_DACNF_ENA(i)) | - (rand ? NRF51_RADIO_DACNF_TXADD(i) : 0)); - - return EC_SUCCESS; -} - - -int ble_adv_packet(struct ble_pdu *adv_packet, int chan) -{ - int done; - int rv; - - /* Change channel */ - NRF51_RADIO_FREQUENCY = NRF51_RADIO_FREQUENCY_VAL(chan2freq(chan)); - NRF51_RADIO_DATAWHITEIV = chan; - - ble_tx(adv_packet); - - do { - done = NRF51_RADIO_END; - } while (!done); - - tx_end = get_time().le.lo; - - if (adv_packet->header.adv.type == - BLE_ADV_HEADER_PDU_TYPE_ADV_NONCONN_IND) - return EC_SUCCESS; - - rv = ble_rx(&rcv_packet, 16000, 1); - - if (rv != EC_SUCCESS) - return rv; - - /* Check for valid responses */ - switch (rcv_packet.header.adv.type) { - case BLE_ADV_HEADER_PDU_TYPE_SCAN_REQ: - /* Scan requests are only allowed for ADV_IND and SCAN_IND */ - if (adv_packet->header.adv.type != - BLE_ADV_HEADER_PDU_TYPE_ADV_IND && - adv_packet->header.adv.type != - BLE_ADV_HEADER_PDU_TYPE_ADV_SCAN_IND) - return rv; - /* The advertising address needs to match */ - if (memcmp(&rcv_packet.payload[BLUETOOTH_ADDR_OCTETS], - &adv_packet->payload[0], BLUETOOTH_ADDR_OCTETS)) - return rv; - break; - case BLE_ADV_HEADER_PDU_TYPE_CONNECT_REQ: - /* Connections are only allowed for two types of advertising */ - if (adv_packet->header.adv.type != - BLE_ADV_HEADER_PDU_TYPE_ADV_IND && - adv_packet->header.adv.type != - BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND) - return rv; - /* The advertising address needs to match */ - if (memcmp(&rcv_packet.payload[BLUETOOTH_ADDR_OCTETS], - &adv_packet->payload[0], BLUETOOTH_ADDR_OCTETS)) - return rv; - /* The InitAddr needs to match for Directed advertising */ - if (adv_packet->header.adv.type == - BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND && - memcmp(&adv_packet->payload[BLUETOOTH_ADDR_OCTETS], - &rcv_packet.payload[0], BLUETOOTH_ADDR_OCTETS)) - return rv; - break; - default: /* Unhandled response packet */ - return rv; - break; - } - - dump_ble_packet(&rcv_packet); - CPRINTF("tx_end %u Response %u\n", tx_end, rsp_end); - - return rv; -} - -int ble_adv_event(struct ble_pdu *adv_packet) -{ - int chan; - int rv; - - for (chan = 37; chan < 40; chan++) { - rv = ble_adv_packet(adv_packet, chan); - if (rv != EC_SUCCESS) - return rv; - } - - return rv; -} - -static void fill_header(struct ble_pdu *adv, int type, int txaddr, int rxaddr) -{ - adv->header_type_adv = 1; - adv->header.adv.type = type; - adv->header.adv.txaddr = txaddr ? - BLE_ADV_HEADER_RANDOM_ADDR : BLE_ADV_HEADER_PUBLIC_ADDR; - adv->header.adv.rxaddr = rxaddr ? - BLE_ADV_HEADER_RANDOM_ADDR : BLE_ADV_HEADER_PUBLIC_ADDR; - adv->header.adv.length = 0; -} - -static int fill_payload(uint8_t *payload, uint64_t addr, int name_length) -{ - uint8_t *curr; - - curr = pack_adv_addr(payload, addr); - curr = pack_adv(curr, name_length, GAP_COMPLETE_NAME, - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs"); - curr = pack_adv_int(curr, 2, GAP_APPEARANCE, - GAP_APPEARANCE_HID_KEYBOARD); - curr = pack_adv_int(curr, 1, GAP_FLAGS, - GAP_FLAGS_LE_LIM_DISC | GAP_FLAGS_LE_NO_BR_EDR); - curr = pack_adv_int(curr, 2, GAP_COMP_16_BIT_UUID, - GATT_SERVICE_HID_UUID); - - return curr - payload; -} - -static void fill_packet(struct ble_pdu *adv, uint64_t addr, int type, - int name_length) -{ - fill_header(adv, type, BLE_ADV_HEADER_RANDOM_ADDR, - BLE_ADV_HEADER_PUBLIC_ADDR); - - adv->header.adv.length = fill_payload(adv->payload, addr, name_length); -} - -static int command_ble_adv(int argc, char **argv) -{ - int type, length, reps, interval; - uint64_t addr; - char *e; - int i; - int rv; - - if (argc < 3 || argc > 5) - return EC_ERROR_PARAM_COUNT; - - type = strtoi(argv[1], &e, 0); - if (*e || type < 0 || (type > 2 && type != 6)) - return EC_ERROR_PARAM1; - - length = strtoi(argv[2], &e, 0); - if (*e || length > 32) - return EC_ERROR_PARAM2; - - if (argc >= 4) { - reps = strtoi(argv[3], &e, 0); - if (*e || reps < 0) - return EC_ERROR_PARAM3; - } else { - reps = 1; - } - - if (argc >= 5) { - interval = strtoi(argv[4], &e, 0); - if (*e || interval < 0) - return EC_ERROR_PARAM4; - } else { - interval = 100000; - } - - if (type == BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND && length != 12) { - length = 12; - CPRINTS("type DIRECT needs to have a length of 12"); - } - - rv = ble_radio_init(BLE_ADV_ACCESS_ADDRESS, BLE_ADV_CRCINIT); - - - CPRINTS("ADV @%pP", &adv_packet); - - ((uint32_t *)&addr)[0] = 0xA3A2A1A0 | type; - ((uint32_t *)&addr)[1] = BLE_RANDOM_ADDR_MSBS_STATIC << 8 | 0x5A4; - - fill_packet(&adv_packet, addr, type, length); - - for (i = 0; i < reps; i++) { - ble_adv_event(&adv_packet); - usleep(interval); - } - - return rv; -} -DECLARE_CONSOLE_COMMAND(ble_adv, command_ble_adv, - "type len [reps] [interval = 100000 (100ms)]", - "Send a BLE packet of type type of length len"); - -static int command_ble_adv_scan(int argc, char **argv) -{ - int chan, packets, i; - int addr_lsbyte; - char *e; - int rv; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - chan = strtoi(argv[1], &e, 0); - if (*e || chan < 37 || chan > 39) - return EC_ERROR_PARAM1; - - chan = strtoi(argv[1], &e, 0); - if (*e || chan < 37 || chan > 39) - return EC_ERROR_PARAM1; - - if (argc >= 3) { - packets = strtoi(argv[2], &e, 0); - if (*e || packets < 0) - return EC_ERROR_PARAM2; - } else { - packets = 1; - } - - if (argc >= 4) { - addr_lsbyte = strtoi(argv[3], &e, 0); - if (*e || addr_lsbyte > 255) - return EC_ERROR_PARAM3; - } else { - addr_lsbyte = -1; - } - - rv = ble_radio_init(BLE_ADV_ACCESS_ADDRESS, BLE_ADV_CRCINIT); - - /* Change channel */ - NRF51_RADIO_FREQUENCY = NRF51_RADIO_FREQUENCY_VAL(chan2freq(chan)); - NRF51_RADIO_DATAWHITEIV = chan; - - CPRINTS("ADV Listen"); - if (addr_lsbyte != -1) - CPRINTS("filtered (%x)", addr_lsbyte); - - for (i = 0; i < packets; i++) { - rv = ble_rx(&rcv_packet, 1000000, 1); - - if (rv == EC_ERROR_TIMEOUT) - continue; - - if (addr_lsbyte == -1 || rcv_packet.payload[0] == addr_lsbyte) - dump_ble_packet(&rcv_packet); - } - - rv = radio_disable(); - - CPRINTS("on_air payload rcvd %pP", &rx_packet); - - return rv; -} -DECLARE_CONSOLE_COMMAND(ble_scan, command_ble_adv_scan, - "chan [num] [addr0]", - "Scan for [num] BLE packets on channel chan"); - diff --git a/chip/nrf51/bluetooth_le.h b/chip/nrf51/bluetooth_le.h deleted file mode 100644 index dbb3bccd6e..0000000000 --- a/chip/nrf51/bluetooth_le.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __NRF51_BLUETOOTH_LE_H -#define __NRF51_BLUETOOTH_LE_H - -#include "common.h" -#include "include/bluetooth_le.h" - -#define NRF51_BLE_LENGTH_BITS 8 -#define NRF51_BLE_S0_BYTES 1 -#define NRF51_BLE_S1_BITS 0 /* no s1 field */ - -#define BLE_ACCESS_ADDRESS_BYTES 4 -#define EXTRA_RECEIVE_BYTES 0 -#define BLE_ADV_WHITEN 1 - -#define RADIO_SETUP_TIMEOUT 1000 - -/* Data and Advertisements have the same PCNF values */ -#define NRF51_RADIO_PCNF0_ADV_DATA \ - NRF51_RADIO_PCNF0_VAL(NRF51_BLE_LENGTH_BITS, \ - NRF51_BLE_S0_BYTES, \ - NRF51_BLE_S1_BITS) - -#define NRF51_RADIO_PCNF1_ADV_DATA \ - NRF51_RADIO_PCNF1_VAL(BLE_MAX_ADV_PAYLOAD_OCTETS, \ - EXTRA_RECEIVE_BYTES, \ - BLE_ACCESS_ADDRESS_BYTES - 1, \ - BLE_ADV_WHITEN) - -struct nrf51_ble_packet_t { - uint8_t s0; /* First byte */ - uint8_t length; /* Length field */ - uint8_t payload[BLE_MAX_DATA_PAYLOAD_OCTETS]; -} __packed; - -struct nrf51_ble_config_t { - uint8_t channel; - uint8_t address; - uint32_t crc_init; -}; - -/* Initialize the nRF51 radio for BLE */ -int ble_radio_init(uint32_t access_address, uint32_t crc_init_val); - -/* Transmit pdu on the radio */ -void ble_tx(struct ble_pdu *pdu); - -/* Receive a packet into pdu if one comes before the timeout */ -int ble_rx(struct ble_pdu *pdu, int timeout, int adv); - -/* Allow list handling */ - -/* Clear the allow list */ -int ble_radio_clear_allow_list(void); - -/* Read the size of the allow list and assign it to ret_size */ -int ble_radio_read_allow_list_size(uint8_t *ret_size); - -/* Add the device with the address specified by addr_ptr and type */ -int ble_radio_add_device_to_allow_list(const uint8_t *addr_ptr, uint8_t type); - -/* Remove the device with the address specified by addr_ptr and type */ -int ble_radio_remove_device_from_allow_list(const uint8_t *addr_ptr, - uint8_t type); - -#endif /* __NRF51_BLUETOOTH_LE_H */ diff --git a/chip/nrf51/build.mk b/chip/nrf51/build.mk deleted file mode 100644 index 7a7a33d402..0000000000 --- a/chip/nrf51/build.mk +++ /dev/null @@ -1,26 +0,0 @@ -# -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# nRF51822 chip specific files build -# - -CORE:=cortex-m0 -# Force ARMv6-M ISA used by the Cortex-M0 -# For historical reasons gcc calls it armv6s-m: ARM used to have ARMv6-M -# without "svc" instruction, but that was short-lived. ARMv6S-M was the option -# with "svc". GCC kept that naming scheme even though the distinction is long -# gone. -CFLAGS_CPU+=-march=armv6s-m -mcpu=cortex-m0 - -chip-y+=gpio.o system.o uart.o -chip-y+=watchdog.o ppi.o - -chip-$(CONFIG_BLUETOOTH_LE)+=radio.o bluetooth_le.o -chip-$(CONFIG_BLUETOOTH_LE_RADIO_TEST)+=radio_test.o -chip-$(CONFIG_COMMON_TIMER)+=hwtimer.o clock.o -chip-$(CONFIG_I2C)+=i2c.o -ifndef CONFIG_KEYBOARD_NOT_RAW -chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o -endif diff --git a/chip/nrf51/clock.c b/chip/nrf51/clock.c deleted file mode 100644 index fe56140175..0000000000 --- a/chip/nrf51/clock.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Clocks and power management settings */ - -void clock_init(void) -{ -} - -int clock_get_freq(void) -{ - /* constant 16 MHz clock */ - return 16000000; -} diff --git a/chip/nrf51/config_chip.h b/chip/nrf51/config_chip.h deleted file mode 100644 index 7295ab9360..0000000000 --- a/chip/nrf51/config_chip.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __CROS_EC_CONFIG_CHIP_H -#define __CROS_EC_CONFIG_CHIP_H - -#include "core/cortex-m0/config_core.h" - -/* System stack size */ -#define CONFIG_STACK_SIZE 1024 - -/* Idle task stack size */ -#define IDLE_TASK_STACK_SIZE 256 - -/* Default task stack size */ -#define TASK_STACK_SIZE 512 - -/* Larger task stack size, for hook task */ -#define LARGER_TASK_STACK_SIZE 640 - -/* Interval between HOOK_TICK notifications */ -#define HOOK_TICK_INTERVAL_MS 500 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) - -/* Number of I2C ports */ -#define I2C_PORT_COUNT 2 - -/* - * --- chip variant settings --- - */ - -/* RAM mapping */ -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00004000 - -/* Flash mapping */ -#define CONFIG_PROGRAM_MEMORY_BASE 0x00000000 -#define CONFIG_FLASH_SIZE 0x00040000 -#define CONFIG_FLASH_BANK_SIZE 0x1000 - -/* Memory-mapped internal flash */ -#define CONFIG_INTERNAL_STORAGE -#define CONFIG_MAPPED_STORAGE - -/* Program is run directly from storage */ -#define CONFIG_MAPPED_STORAGE_BASE CONFIG_PROGRAM_MEMORY_BASE - -/* Compute the rest of the flash params from these */ -#include "config_std_internal_flash.h" - -/* Number of IRQ vectors on the NVIC */ -#define CONFIG_IRQ_COUNT 32 - -/* Not that much RAM, set to smaller */ -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 1024 - -#define GPIO_PIN(port, index) GPIO_##port, BIT(index) -#define GPIO_PIN_MASK(p, m) .port = GPIO_##p, .mask = (m) - -#endif /* __CROS_EC_CONFIG_CHIP_H */ - diff --git a/chip/nrf51/gpio.c b/chip/nrf51/gpio.c deleted file mode 100644 index 53694b5a74..0000000000 --- a/chip/nrf51/gpio.c +++ /dev/null @@ -1,311 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "task.h" -#include "util.h" - -/* - * For each interrupt (INT0-INT3, PORT), record which GPIO entry uses it. - */ - -static const struct gpio_info *gpio_ints[NRF51_GPIOTE_IN_COUNT]; -static const struct gpio_info *gpio_int_port; - -volatile uint32_t * const nrf51_alt_funcs[] = { - /* UART */ - &NRF51_UART_PSELRTS, - &NRF51_UART_PSELTXD, - &NRF51_UART_PSELCTS, - &NRF51_UART_PSELRXD, - /* SPI1 (SPI Master) */ - &NRF51_SPI0_PSELSCK, - &NRF51_SPI0_PSELMOSI, - &NRF51_SPI0_PSELMISO, - /* TWI0 (I2C) */ - &NRF51_TWI0_PSELSCL, - &NRF51_TWI0_PSELSDA, - /* SPI1 (SPI Master) */ - &NRF51_SPI1_PSELSCK, - &NRF51_SPI1_PSELMOSI, - &NRF51_SPI1_PSELMISO, - /* TWI1 (I2C) */ - &NRF51_TWI1_PSELSCL, - &NRF51_TWI1_PSELSDA, - /* SPIS1 (SPI SLAVE) */ - &NRF51_SPIS1_PSELSCK, - &NRF51_SPIS1_PSELMISO, - &NRF51_SPIS1_PSELMOSI, - &NRF51_SPIS1_PSELCSN, - /* QDEC (ROTARY DECODER) */ - &NRF51_QDEC_PSELLED, - &NRF51_QDEC_PSELA, - &NRF51_QDEC_PSELB, - /* LPCOMP (Low Power Comparator) */ - &NRF51_LPCOMP_PSEL, -}; - -const unsigned int nrf51_alt_func_count = ARRAY_SIZE(nrf51_alt_funcs); - -/* Make sure the function table and defines stay in sync */ -BUILD_ASSERT(ARRAY_SIZE(nrf51_alt_funcs) == NRF51_MAX_ALT_FUNCS && - NRF51_MAX_ALT_FUNCS <= GPIO_ALT_FUNC_MAX); - -void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) -{ - uint32_t val = 0; - uint32_t bit = GPIO_MASK_TO_NUM(mask); - - if (flags & GPIO_OUTPUT) - val |= NRF51_PIN_CNF_DIR_OUTPUT; - else if (flags & GPIO_INPUT) - val |= NRF51_PIN_CNF_DIR_INPUT; - - if (flags & GPIO_PULL_DOWN) - val |= NRF51_PIN_CNF_PULLDOWN; - else if (flags & GPIO_PULL_UP) - val |= NRF51_PIN_CNF_PULLUP; - - /* TODO: Drive strength? H0D1? */ - if (flags & GPIO_OPEN_DRAIN) - val |= NRF51_PIN_CNF_DRIVE_S0D1; - - if (flags & GPIO_OUTPUT) { - if (flags & GPIO_HIGH) - NRF51_GPIO0_OUTSET = mask; - else if (flags & GPIO_LOW) - NRF51_GPIO0_OUTCLR = mask; - } - - /* Interrupt levels */ - if (flags & GPIO_INT_SHARED) { - /* - * There are no shared edge-triggered interrupts; - * they're either high or low. - */ - ASSERT((flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING)) == 0); - ASSERT((flags & GPIO_INT_LEVEL) != GPIO_INT_LEVEL); - if (flags & GPIO_INT_F_LOW) - val |= NRF51_PIN_CNF_SENSE_LOW; - else if (flags & GPIO_INT_F_HIGH) - val |= NRF51_PIN_CNF_SENSE_HIGH; - } - - NRF51_PIN_CNF(bit) = val; -} - - -static void gpio_init(void) -{ - task_enable_irq(NRF51_PERID_GPIOTE); -} -DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); - - -test_mockable int gpio_get_level(enum gpio_signal signal) -{ - return !!(NRF51_GPIO0_IN & gpio_list[signal].mask); -} - -void gpio_set_level(enum gpio_signal signal, int value) -{ - if (value) - NRF51_GPIO0_OUTSET = gpio_list[signal].mask; - else - NRF51_GPIO0_OUTCLR = gpio_list[signal].mask; -} - - -void gpio_pre_init(void) -{ - const struct gpio_info *g = gpio_list; - int is_warm = 0; - int i; - - if (NRF51_POWER_RESETREAS & - (NRF51_POWER_RESETREAS_OFF | /* GPIO Wake */ - NRF51_POWER_RESETREAS_LPCOMP)) { - /* This is a warm reboot */ - is_warm = 1; - } - - /* Initialize Interrupt configuration */ - for (i = 0; i < NRF51_GPIOTE_IN_COUNT; i++) - gpio_ints[i] = NULL; - gpio_int_port = NULL; - - /* Set all GPIOs to defaults */ - for (i = 0; i < GPIO_COUNT; i++, g++) { - int flags = g->flags; - - if (flags & GPIO_DEFAULT) - continue; - - /* - * If this is a warm reboot, don't set the output levels again. - */ - if (is_warm) - flags &= ~(GPIO_LOW | GPIO_HIGH); - - /* Set up GPIO based on flags */ - gpio_set_flags_by_mask(g->port, g->mask, flags); - } -} - -/* - * NRF51 doesn't have an alternate function table. - * Use the pin select registers in place of the function number. - */ -void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) -{ - uint32_t bit = GPIO_MASK_TO_NUM(mask); - - ASSERT((~mask & BIT(bit)) == 0); /* Only one bit set. */ - ASSERT(port == GPIO_0); - ASSERT((func >= GPIO_ALT_FUNC_DEFAULT && func < nrf51_alt_func_count) || - func == GPIO_ALT_FUNC_NONE); - - /* Remove the previous setting(s) */ - if (func == GPIO_ALT_FUNC_NONE) { - int i; - for (i = 0; i < nrf51_alt_func_count; i++) { - if (*(nrf51_alt_funcs[i]) == bit) - *(nrf51_alt_funcs[i]) = 0xffffffff; - } - } else { - *(nrf51_alt_funcs[func]) = bit; - } -} - - -/* - * Enable the interrupt associated with the "signal" - * The architecture has one general (PORT) - * and NRF51_GPIOTE_IN_COUNT single-pin (IN0, IN1, ...) interrupts. - * - */ -int gpio_enable_interrupt(enum gpio_signal signal) -{ - int pin; - const struct gpio_info *g = gpio_list + signal; - - /* Fail if not implemented or no interrupt handler */ - if (!g->mask || signal >= GPIO_IH_COUNT) - return EC_ERROR_INVAL; - - /* If it's not shared, use INT0-INT3, otherwise use PORT. */ - if (!(g->flags & GPIO_INT_SHARED)) { - int int_num, free_slot = -1; - uint32_t event_config = 0; - - for (int_num = 0; int_num < NRF51_GPIOTE_IN_COUNT; int_num++) { - if (gpio_ints[int_num] == g) - return EC_SUCCESS; /* This is already set up. */ - - if (gpio_ints[int_num] == NULL && free_slot == -1) - free_slot = int_num; - } - - ASSERT(free_slot != -1); - - gpio_ints[free_slot] = g; - pin = GPIO_MASK_TO_NUM(g->mask); - event_config = (pin << NRF51_GPIOTE_PSEL_POS) | - NRF51_GPIOTE_MODE_EVENT; - - ASSERT(g->flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING)); - - /* RISING | FALLING = TOGGLE */ - if (g->flags & GPIO_INT_F_RISING) - event_config |= NRF51_GPIOTE_POLARITY_LOTOHI; - if (g->flags & GPIO_INT_F_FALLING) - event_config |= NRF51_GPIOTE_POLARITY_HITOLO; - - NRF51_GPIOTE_CONFIG(free_slot) = event_config; - - /* Enable the IN[] interrupt. */ - NRF51_GPIOTE_INTENSET = 1 << free_slot; - - } else { - /* The first handler for the shared interrupt wins. */ - if (gpio_int_port == NULL) { - gpio_int_port = g; - - /* Enable the PORT interrupt. */ - NRF51_GPIOTE_INTENSET = 1 << NRF51_GPIOTE_PORT_BIT; - } - } - - return EC_SUCCESS; -} - -/* - * Disable the interrupt associated with the "signal" - * The architecture has one general (PORT) - * and NRF51_GPIOTE_IN_COUNT single-pin (IN0, IN1, ...) interrupts. - */ -int gpio_disable_interrupt(enum gpio_signal signal) -{ - const struct gpio_info *g = gpio_list + signal; - int i; - - /* Fail if not implemented or no interrupt handler */ - if (!g->mask || signal >= GPIO_IH_COUNT) - return EC_ERROR_INVAL; - - /* If it's not shared, use INT0-INT3, otherwise use PORT. */ - if (!(g->flags & GPIO_INT_SHARED)) { - for (i = 0; i < NRF51_GPIOTE_IN_COUNT; i++) { - /* Remove matching handler. */ - if (gpio_ints[i] == g) { - /* Disable the interrupt */ - NRF51_GPIOTE_INTENCLR = - 1 << NRF51_GPIOTE_IN_BIT(i); - /* Zero the handler */ - gpio_ints[i] = NULL; - } - } - } else { - /* Disable the interrupt */ - NRF51_GPIOTE_INTENCLR = 1 << NRF51_GPIOTE_PORT_BIT; - /* Zero the shared handler */ - gpio_int_port = NULL; - } - - return EC_SUCCESS; -} - -/* - * Clear interrupt and run handler. - */ -void gpio_interrupt(void) -{ - const struct gpio_info *g; - int i; - int signal; - - for (i = 0; i < NRF51_GPIOTE_IN_COUNT; i++) { - if (NRF51_GPIOTE_IN(i)) { - NRF51_GPIOTE_IN(i) = 0; - g = gpio_ints[i]; - signal = g - gpio_list; - if (g && signal < GPIO_IH_COUNT) - gpio_irq_handlers[signal](signal); - } - } - - if (NRF51_GPIOTE_PORT) { - NRF51_GPIOTE_PORT = 0; - g = gpio_int_port; - signal = g - gpio_list; - if (g && signal < GPIO_IH_COUNT) - gpio_irq_handlers[signal](signal); - } -} -DECLARE_IRQ(NRF51_PERID_GPIOTE, gpio_interrupt, 1); diff --git a/chip/nrf51/hwtimer.c b/chip/nrf51/hwtimer.c deleted file mode 100644 index 980a889657..0000000000 --- a/chip/nrf51/hwtimer.c +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * Hardware timers driver. - * - * nRF51x has one fully functional hardware counter, but 4 stand-alone - * capture/compare (CC) registers. - */ - -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "hwtimer.h" -#include "registers.h" -#include "task.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) - -/* - * capture/compare (CC) registers: - * CC_INTERRUPT -- used to interrupt next clock event. - * CC_CURRENT -- used to capture the current value. - * CC_OVERFLOW -- used to detect overflow on virtual timer (not hardware). - */ - -#define CC_INTERRUPT 0 -#define CC_CURRENT 1 -#define CC_OVERFLOW 2 - -/* The nRF51 has 3 timers, use HWTIMER to specify which one is used here. */ -#define HWTIMER 0 - -static uint32_t last_deadline; /* cache of event set */ - -/* - * The nRF51x timer cannot be set to a specified value (reset to zero only). - * Thus, we have to use a variable "shift" to maintain the offset between the - * hardware value and virtual clock value. - * - * Once __hw_clock_source_set(ts) is called, the shift will be like: - * - * virtual time ------------------------------------------------ - * <----------> ^ - * shift | ts - * 0 | | - * hardware v - * counter time ------------------------------------------------ - * - * - * Below diagram shows what it is when overflow happens. - * - * | now | prev_read - * v v - * virtual time ------------------------------------------------ - * ----> <------ - * shift shift - * | - * hardware v - * counter time ------------------------------------------------ - * - */ -static uint32_t shift; - -void __hw_clock_event_set(uint32_t deadline) -{ - last_deadline = deadline; - NRF51_TIMER_CC(HWTIMER, CC_INTERRUPT) = deadline - shift; - - /* enable interrupt */ - NRF51_TIMER_INTENSET(HWTIMER) = - 1 << NRF51_TIMER_COMPARE_BIT(CC_INTERRUPT); -} - -uint32_t __hw_clock_event_get(void) -{ - return last_deadline; -} - -void __hw_clock_event_clear(void) -{ - /* disable interrupt */ - NRF51_TIMER_INTENCLR(HWTIMER) = - 1 << NRF51_TIMER_COMPARE_BIT(CC_INTERRUPT); -} - -uint32_t __hw_clock_source_read(void) -{ - /* to capture the current value */ - NRF51_TIMER_CAPTURE(HWTIMER, CC_CURRENT) = 1; - return NRF51_TIMER_CC(HWTIMER, CC_CURRENT) + shift; -} - -void __hw_clock_source_set(uint32_t ts) -{ - shift = ts; - - /* reset counter to zero */ - NRF51_TIMER_STOP(HWTIMER) = 1; - NRF51_TIMER_CLEAR(HWTIMER) = 1; - - /* So that no interrupt until next __hw_clock_event_set() */ - NRF51_TIMER_CC(HWTIMER, CC_INTERRUPT) = ts - 1; - - /* Update the overflow point */ - NRF51_TIMER_CC(HWTIMER, CC_OVERFLOW) = 0 - shift; - - /* Start the timer again */ - NRF51_TIMER_START(HWTIMER) = 1; -} - - -/* Interrupt handler for timer */ -void timer_irq(void) -{ - int overflow = 0; - - /* clear status */ - NRF51_TIMER_COMPARE(HWTIMER, CC_INTERRUPT) = 0; - - if (NRF51_TIMER_COMPARE(HWTIMER, CC_OVERFLOW)) { - NRF51_TIMER_COMPARE(HWTIMER, CC_OVERFLOW) = 0; - overflow = 1; - } - - process_timers(overflow); -} - -/* DECLARE_IRQ doesn't like the NRF51_PERID_TIMER(n) macro */ -BUILD_ASSERT(NRF51_PERID_TIMER(HWTIMER) == NRF51_PERID_TIMER0); -DECLARE_IRQ(NRF51_PERID_TIMER0, timer_irq, 1); - -int __hw_clock_source_init(uint32_t start_t) -{ - - /* Start the high freq crystal oscillator */ - NRF51_CLOCK_HFCLKSTART = 1; - /* TODO: check if the crystal oscillator is running (HFCLKSTAT) */ - - /* 32-bit timer mode */ - NRF51_TIMER_MODE(HWTIMER) = NRF51_TIMER_MODE_TIMER; - NRF51_TIMER_BITMODE(HWTIMER) = NRF51_TIMER_BITMODE_32; - - /* - * The external crystal oscillator is 16MHz (HFCLK). - * Set the prescaler to 16 so that the timer counter is increasing - * every micro-second (us). - */ - NRF51_TIMER_PRESCALER(HWTIMER) = 4; /* actual value is 2**4 = 16 */ - - /* Not to trigger interrupt until __hw_clock_event_set() is called. */ - NRF51_TIMER_CC(HWTIMER, CC_INTERRUPT) = 0xffffffff; - - /* Set to 0 so that the next overflow can trigger timer_irq(). */ - NRF51_TIMER_CC(HWTIMER, CC_OVERFLOW) = 0; - NRF51_TIMER_INTENSET(HWTIMER) = - 1 << NRF51_TIMER_COMPARE_BIT(CC_OVERFLOW); - - /* Clear the timer counter */ - NRF51_TIMER_CLEAR(HWTIMER) = 1; - - /* Override the count with the start value now that counting has - * started. */ - __hw_clock_source_set(start_t); - - /* Enable interrupt */ - task_enable_irq(NRF51_PERID_TIMER(HWTIMER)); - - /* Start the timer */ - NRF51_TIMER_START(HWTIMER) = 1; - - return NRF51_PERID_TIMER(HWTIMER); -} - diff --git a/chip/nrf51/i2c.c b/chip/nrf51/i2c.c deleted file mode 100644 index 09a4a210e6..0000000000 --- a/chip/nrf51/i2c.c +++ /dev/null @@ -1,304 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "clock.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "ppi.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) - -#define I2C_TIMEOUT 20000 - -/* Keep track of the PPI channel used for each port */ -static int i2c_ppi_chan[] = {-1, -1}; - -static void i2c_init_port(unsigned int port); - -/* board-specific setup for post-I2C module init */ -void __board_i2c_post_init(int port) -{ -} - -void board_i2c_post_init(int port) - __attribute__((weak, alias("__board_i2c_post_init"))); - -static void i2c_init_port(unsigned int port) -{ - NRF51_TWI_RXDRDY(port) = 0; - NRF51_TWI_TXDSENT(port) = 0; - - NRF51_TWI_PSELSCL(port) = NRF51_TWI_SCL_PIN(port); - NRF51_TWI_PSELSDA(port) = NRF51_TWI_SDA_PIN(port); - NRF51_TWI_FREQUENCY(port) = NRF51_TWI_FREQ(port); - - NRF51_PPI_CHENCLR = 1 << i2c_ppi_chan[port]; - - NRF51_PPI_EEP(i2c_ppi_chan[port]) = (uint32_t)&NRF51_TWI_BB(port); - NRF51_PPI_TEP(i2c_ppi_chan[port]) = - (uint32_t)&NRF51_TWI_SUSPEND(port); - - /* Master enable */ - NRF51_TWI_ENABLE(port) = NRF51_TWI_ENABLE_VAL; - - if (!(i2c_raw_get_scl(port) && (i2c_raw_get_sda(port)))) - CPRINTF("port %d could be wedged\n", port); -} - -void i2c_init(void) -{ - int i, rv; - - gpio_config_module(MODULE_I2C, 1); - - for (i = 0; i < i2c_ports_used; i++) { - if (i2c_ppi_chan[i] == -1) { - rv = ppi_request_channel(&i2c_ppi_chan[i]); - ASSERT(rv == EC_SUCCESS); - - i2c_init_port(i); - } - } -} - -static void dump_i2c_reg(int port) -{ -#ifdef CONFIG_I2C_DEBUG - CPRINTF("port : %01d\n", port); - CPRINTF("Regs :\n"); - CPRINTF(" 1: INTEN : %08x\n", NRF51_TWI_INTEN(port)); - CPRINTF(" 2: ERRORSRC : %08x\n", NRF51_TWI_ERRORSRC(port)); - CPRINTF(" 3: ENABLE : %08x\n", NRF51_TWI_ENABLE(port)); - CPRINTF(" 4: PSELSCL : %08x\n", NRF51_TWI_PSELSCL(port)); - CPRINTF(" 5: PSELSDA : %08x\n", NRF51_TWI_PSELSDA(port)); - CPRINTF(" 6: RXD : %08x\n", NRF51_TWI_RXD(port)); - CPRINTF(" 7: TXD : %08x\n", NRF51_TWI_TXD(port)); - CPRINTF(" 8: FREQUENCY : %08x\n", NRF51_TWI_FREQUENCY(port)); - CPRINTF(" 9: ADDRESS : %08x\n", NRF51_TWI_ADDRESS(port)); - CPRINTF("Events :\n"); - CPRINTF(" STOPPED : %08x\n", NRF51_TWI_STOPPED(port)); - CPRINTF(" RXDRDY : %08x\n", NRF51_TWI_RXDRDY(port)); - CPRINTF(" TXDSENT : %08x\n", NRF51_TWI_TXDSENT(port)); - CPRINTF(" ERROR : %08x\n", NRF51_TWI_ERROR(port)); - CPRINTF(" BB : %08x\n", NRF51_TWI_BB(port)); -#endif /* CONFIG_I2C_DEBUG */ -} - -static void i2c_recover(int port) -{ - /* - * Recovery of the TWI peripheral: - * To recover a TWI peripheral that has been locked up you must use - * the following code. - * After the recover function it is important to reconfigure all - * relevant TWI registers explicitly to ensure that it operates - * correctly. - * TWI0: - * NRF_TWI0->ENABLE = - * TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; - * *(uint32_t *)(NRF_TWI0_BASE + 0xFFC) = 0; - * nrf_delay_us(5); - * *(uint32_t *)(NRF_TWI0_BASE + 0xFFC) = 1; - * NRF_TWI0->ENABLE = - * TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos; - */ - NRF51_TWI_ENABLE(port) = NRF51_TWI_DISABLE_VAL; - NRF51_TWI_POWER(port) = 0; - udelay(5); - NRF51_TWI_POWER(port) = 1; - - i2c_init_port(port); -} - -static void handle_i2c_error(int port, int rv) -{ - if (rv == EC_SUCCESS) - return; - -#ifdef CONFIG_I2C_DEBUG - if (rv != EC_ERROR_TIMEOUT) - CPRINTF("handle_i2c_error %d\n", rv); - else - CPRINTF("handle_i2c_error: Timeout\n"); - - dump_i2c_reg(port); -#endif - - /* This may be a little too heavy handed. */ - i2c_recover(port); -} - -static int i2c_master_write(const int port, const uint16_t slave_addr_flags, - const uint8_t *data, int size, int stop) -{ - int bytes_sent; - int timeout = I2C_TIMEOUT; - - NRF51_TWI_ADDRESS(port) = I2C_GET_ADDR(slave_addr_flags); - - /* Clear the sent bit */ - NRF51_TWI_TXDSENT(port) = 0; - - for (bytes_sent = 0; bytes_sent < size; bytes_sent++) { - /*Send a byte */ - NRF51_TWI_TXD(port) = data[bytes_sent]; - - /* Only send a start for the first byte */ - if (bytes_sent == 0) - NRF51_TWI_STARTTX(port) = 1; - - /* Wait for ACK/NACK */ - timeout = I2C_TIMEOUT; - while (timeout > 0 && NRF51_TWI_TXDSENT(port) == 0 && - NRF51_TWI_ERROR(port) == 0) - timeout--; - - if (timeout == 0) - return EC_ERROR_TIMEOUT; - - if (NRF51_TWI_ERROR(port)) - return EC_ERROR_UNKNOWN; - - /* Clear the sent bit */ - NRF51_TWI_TXDSENT(port) = 0; - } - - if (stop) { - NRF51_TWI_STOPPED(port) = 0; - NRF51_TWI_STOP(port) = 1; - timeout = 10; - while (NRF51_TWI_STOPPED(port) == 0 && timeout > 0) - timeout--; - } - - return EC_SUCCESS; -} - -static int i2c_master_read(const int port, const uint16_t slave_addr_flags, - uint8_t *data, int size) -{ - int curr_byte; - int timeout = I2C_TIMEOUT; - - NRF51_TWI_ADDRESS(port) = I2C_GET_ADDR(slave_addr_flags); - - if (size == 1) /* Last byte: stop after this one. */ - NRF51_PPI_TEP(i2c_ppi_chan[port]) = - (uint32_t)&NRF51_TWI_STOP(port); - else - NRF51_PPI_TEP(i2c_ppi_chan[port]) = - (uint32_t)&NRF51_TWI_SUSPEND(port); - NRF51_PPI_CHENSET = 1 << i2c_ppi_chan[port]; - - NRF51_TWI_RXDRDY(port) = 0; - NRF51_TWI_STARTRX(port) = 1; - - for (curr_byte = 0; curr_byte < size; curr_byte++) { - - /* Wait for data */ - while (timeout > 0 && NRF51_TWI_RXDRDY(port) == 0 && - NRF51_TWI_ERROR(port) == 0) - timeout--; - - if (timeout == 0) - return EC_ERROR_TIMEOUT; - - if (NRF51_TWI_ERROR(port)) - return EC_ERROR_UNKNOWN; - - data[curr_byte] = NRF51_TWI_RXD(port); - NRF51_TWI_RXDRDY(port) = 0; - - /* Second to the last byte: stop next time. */ - if (curr_byte == size-2) - NRF51_PPI_TEP(i2c_ppi_chan[port]) = - (uint32_t)&NRF51_TWI_STOP(port); - - /* - * According to nRF51822-PAN v2.4 (Product Anomaly Notice), - * the I2C locks up when RESUME is triggered too soon. - * "the firmware should ensure that the time between receiving - * the RXDRDY event and trigging the RESUME task is at least - * two times the TWI clock period (i.e. 20 μs at 100 kbps). - * Provided the TWI slave doesn’t do clock stretching during - * the ACK bit, this will be enough to avoid the RESUME task - * hit the end of the ACK bit. If this fails, a recovery of - * the peripheral will be necessary, see i2c_recover. - */ - udelay(20); - NRF51_TWI_RESUME(port) = 1; - } - - timeout = I2C_TIMEOUT; - while (NRF51_TWI_STOPPED(port) == 0 && timeout > 0) - timeout--; - - NRF51_TWI_STOP(port) = 0; - - NRF51_PPI_CHENCLR = 1 << i2c_ppi_chan[port]; - - return EC_SUCCESS; -} - -int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, - const uint8_t *out, int out_bytes, - uint8_t *in, int in_bytes, int flags) -{ - int rv = EC_SUCCESS; - - ASSERT(out || !out_bytes); - ASSERT(in || !in_bytes); - - if (out_bytes) - rv = i2c_master_write(port, slave_addr_flags, - out, out_bytes, - in_bytes ? 0 : 1); - if (rv == EC_SUCCESS && in_bytes) - rv = i2c_master_read(port, slave_addr_flags, - in, in_bytes); - - handle_i2c_error(port, rv); - - return rv; -} - -int i2c_raw_get_scl(int port) -{ - enum gpio_signal g; - - if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS) - return gpio_get_level(g); - - /* If no SCL pin defined for this port, then return 1 to appear idle. */ - return 1; -} - -int i2c_raw_get_sda(int port) -{ - enum gpio_signal g; - - if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS) - return gpio_get_level(g); - - /* If no SDA pin defined for this port, then return 1 to appear idle. */ - return 1; -} - -int i2c_get_line_levels(int port) -{ - return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) | - (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); -} - diff --git a/chip/nrf51/keyboard_raw.c b/chip/nrf51/keyboard_raw.c deleted file mode 100644 index 779c68454c..0000000000 --- a/chip/nrf51/keyboard_raw.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Raw keyboard I/O layer for nRF51 - * - * To make this code portable, we rely heavily on looping over the keyboard - * input and output entries in the board's gpio_list[]. Each set of inputs or - * outputs must be listed in consecutive, increasing order so that scan loops - * can iterate beginning at KB_IN00 or KB_OUT00 for however many GPIOs are - * utilized (KEYBOARD_ROWS or KEYBOARD_COLS_MAX). - */ - -#include "gpio.h" -#include "keyboard_config.h" -#include "keyboard_raw.h" -#include "keyboard_scan.h" -#include "registers.h" -#include "task.h" -#include "util.h" - -/* Mask of output pins for driving. */ -static unsigned int col_mask; - -void keyboard_raw_init(void) -{ - int i; - - /* Initialize col_mask */ - col_mask = 0; - for (i = 0; i < keyboard_cols; i++) - col_mask |= gpio_list[GPIO_KB_OUT00 + i].mask; - - /* Ensure interrupts are disabled */ - keyboard_raw_enable_interrupt(0); -} - -void keyboard_raw_task_start(void) -{ - /* - * Enable the interrupt for keyboard matrix inputs. - * One is enough, since they are shared. - */ - gpio_enable_interrupt(GPIO_KB_IN00); -} - -test_mockable void keyboard_raw_drive_column(int out) -{ - /* tri-state all first */ - NRF51_GPIO0_OUTSET = col_mask; - - /* drive low for specified pin(s) */ - if (out == KEYBOARD_COLUMN_ALL) - NRF51_GPIO0_OUTCLR = col_mask; - else if (out != KEYBOARD_COLUMN_NONE) - NRF51_GPIO0_OUTCLR = gpio_list[GPIO_KB_OUT00 + out].mask; -} - -test_mockable int keyboard_raw_read_rows(void) -{ - int i; - int state = 0; - - for (i = 0; i < KEYBOARD_ROWS; i++) { - if (NRF51_GPIO0_IN & gpio_list[GPIO_KB_IN00 + i].mask) - state |= 1 << i; - } - - /* Invert it so 0=not pressed, 1=pressed */ - return state ^ 0xff; -} - -void keyboard_raw_enable_interrupt(int enable) -{ - if (enable) { - /* - * Clear the PORT event before enabling the interrupt. - */ - NRF51_GPIOTE_PORT = 0; - NRF51_GPIOTE_INTENSET = 1 << NRF51_GPIOTE_PORT_BIT; - } else { - NRF51_GPIOTE_INTENCLR = 1 << NRF51_GPIOTE_PORT_BIT; - } -} - -void keyboard_raw_gpio_interrupt(enum gpio_signal signal) -{ - task_wake(TASK_ID_KEYSCAN); -} diff --git a/chip/nrf51/ppi.c b/chip/nrf51/ppi.c deleted file mode 100644 index 016cbf3008..0000000000 --- a/chip/nrf51/ppi.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "ppi.h" -#include "registers.h" -#include "util.h" - -#define NRF51_PPI_FIRST_PP_CH NRF51_PPI_CH_TIMER0_CC0__RADIO_TXEN -#define NRF51_PPI_LAST_PP_CH NRF51_PPI_CH_RTC0_COMPARE0__TIMER0_START - -static uint32_t channels_in_use; -static uint32_t channel_groups_in_use; - -int ppi_request_pre_programmed_channel(int ppi_chan) -{ - ASSERT(ppi_chan >= NRF51_PPI_FIRST_PP_CH && - ppi_chan <= NRF51_PPI_LAST_PP_CH); - - if (channels_in_use & BIT(ppi_chan)) - return EC_ERROR_BUSY; - - channels_in_use |= BIT(ppi_chan); - - return EC_SUCCESS; -} - -int ppi_request_channel(int *ppi_chan) -{ - int chan; - - for (chan = 0; chan < NRF51_PPI_NUM_PROGRAMMABLE_CHANNELS; chan++) - if ((channels_in_use & BIT(chan)) == 0) - break; - - if (chan == NRF51_PPI_NUM_PROGRAMMABLE_CHANNELS) - return EC_ERROR_BUSY; - - channels_in_use |= BIT(chan); - *ppi_chan = chan; - return EC_SUCCESS; -} - -void ppi_release_channel(int ppi_chan) -{ - channels_in_use &= ~BIT(ppi_chan); -} - -void ppi_release_group(int ppi_group) -{ - channel_groups_in_use &= ~BIT(ppi_group); -} - -int ppi_request_group(int *ppi_group) -{ - int group; - - for (group = 0; group < NRF51_PPI_NUM_GROUPS; group++) - if ((channel_groups_in_use & BIT(group)) == 0) - break; - - if (group == NRF51_PPI_NUM_GROUPS) - return EC_ERROR_BUSY; - - channel_groups_in_use |= BIT(group); - *ppi_group = group; - return EC_SUCCESS; -} diff --git a/chip/nrf51/ppi.h b/chip/nrf51/ppi.h deleted file mode 100644 index bbb74a2cf0..0000000000 --- a/chip/nrf51/ppi.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * PPI channels are a way to connect NRF51 EVENTs to TASKs without software - * involvement. They are like SHORTs, except between peripherals. - * - * PPI groups are user-defined sets of channels that can be enabled and disabled - * together. - */ - -/* - * Reserve a pre-programmed PPI channel. - * - * Return EC_SUCCESS if ppi_chan is a pre-programmed channel that was not in - * use, otherwise returns EC_ERROR_BUSY. - */ -int ppi_request_pre_programmed_channel(int ppi_chan); - -/* - * Reserve an available PPI channel. - * - * Return EC_SUCCESS and set the value of ppi_chan to an available PPI - * channel. If no channel is available, return EC_ERROR_BUSY. - */ -int ppi_request_channel(int *ppi_chan); - -/* Release a PPI channel which was reserved with ppi_request_*_channel. */ -void ppi_release_channel(int ppi_chan); - -/* - * Reserve a PPI group. - * - * Return EC_SUCCESS and set the value of ppi_group to an available PPI - * group. If no group is available, return EC_ERROR_BUSY. - */ -int ppi_request_group(int *ppi_group); - -/* Release a PPI channel which was reserved with ppi_request_*_channel. */ -void ppi_release_group(int ppi_group); diff --git a/chip/nrf51/radio.c b/chip/nrf51/radio.c deleted file mode 100644 index af9d029a0d..0000000000 --- a/chip/nrf51/radio.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "radio.h" - -int radio_disable(void) -{ - int timeout = 10000; - - NRF51_RADIO_DISABLED = 0; - NRF51_RADIO_DISABLE = 1; - - while (!NRF51_RADIO_DISABLED && timeout > 0) - timeout--; - - if (timeout == 0) - return EC_ERROR_TIMEOUT; - - return EC_SUCCESS; -} - -int radio_init(enum nrf51_radio_mode_t mode) -{ - int err_code = radio_disable(); - - if (mode == BLE_1MBIT) { - NRF51_RADIO_MODE = NRF51_RADIO_MODE_BLE_1MBIT; - - NRF51_RADIO_TIFS = 150; /* Bluetooth 4.1 Vol 6 pg 58 4.1 */ - - /* - * BLE never sends or receives two packets in a row. - * Enabling the radio means we want to transmit or receive. - * After transmission, disable as quickly as possible. - */ - NRF51_RADIO_SHORTS = NRF51_RADIO_SHORTS_READY_START | - NRF51_RADIO_SHORTS_END_DISABLE; - - /* Use factory parameters if available */ - if (!(NRF51_FICR_OVERRIDEEN & NRF51_FICR_OVERRIDEEN_BLE_BIT_N) - ) { - int i; - - for (i = 0; i < 4; i++) { - NRF51_RADIO_OVERRIDE(i) = - NRF51_FICR_BLE_1MBIT(i); - } - NRF51_RADIO_OVERRIDE(4) = NRF51_FICR_BLE_1MBIT(4) | - NRF51_RADIO_OVERRIDE_EN; - } - } else { - return EC_ERROR_UNIMPLEMENTED; - } - - return err_code; -} - diff --git a/chip/nrf51/radio.h b/chip/nrf51/radio.h deleted file mode 100644 index 5b7e764fb9..0000000000 --- a/chip/nrf51/radio.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Radio interface for Chrome EC */ - -#ifndef __NRF51_RADIO_H -#define __NRF51_RADIO_H - -#include "common.h" -#include "compile_time_macros.h" -#include "registers.h" - -#ifndef NRF51_RADIO_MAX_PAYLOAD - #define NRF51_RADIO_MAX_PAYLOAD 253 -#endif - -#define RADIO_DONE (NRF51_RADIO_END == 1) - -enum nrf51_radio_mode_t { - BLE_1MBIT = NRF51_RADIO_MODE_BLE_1MBIT, -}; - -struct nrf51_radio_packet_t { - uint8_t s0; /* First byte */ - uint8_t length; /* Length field */ - uint8_t s1; /* Bits after length */ - uint8_t payload[NRF51_RADIO_MAX_PAYLOAD]; -} __packed; - -int radio_init(enum nrf51_radio_mode_t mode); - -int radio_disable(void); - -#endif /* __NRF51_RADIO_H */ diff --git a/chip/nrf51/radio_test.c b/chip/nrf51/radio_test.c deleted file mode 100644 index 6c20874f4e..0000000000 --- a/chip/nrf51/radio_test.c +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "bluetooth_le.h" /* chan2freq */ -#include "btle_hci_int.h" -#include "console.h" -#include "radio.h" -#include "radio_test.h" -#include "registers.h" -#include "timer.h" -#include "util.h" - -#define BLE_TEST_TYPE_PRBS9 0 -#define BLE_TEST_TYPE_F0 1 -#define BLE_TEST_TYPE_AA 2 -#define BLE_TEST_TYPE_PRBS15 3 -#define BLE_TEST_TYPE_FF 4 -#define BLE_TEST_TYPE_00 5 -#define BLE_TEST_TYPE_0F 6 -#define BLE_TEST_TYPE_55 7 - -#define BLE_TEST_TYPES_IMPLEMENTED 0xf6 /* No PRBS yet */ - -static struct nrf51_ble_packet_t rx_packet; -static struct nrf51_ble_packet_t tx_packet; -static uint32_t rx_end; - -static int test_in_progress; - -void ble_test_stop(void) -{ - test_in_progress = 0; -} - -static uint32_t prbs_lfsr; -static uint32_t prbs_poly; - -/* - * This is a Galois LFSR, the polynomial is the counterpart of the Fibonacci - * LFSR in the doc. It requires fewer XORs to implement in software. - * This also means that the initial value is different. - */ -static uint8_t prbs_next_byte(void) -{ - int i; - int lsb; - uint8_t rv = 0; - - for (i = 0; i < 8; i++) { - lsb = prbs_lfsr & 1; - rv |= lsb << i; - prbs_lfsr = prbs_lfsr >> 1; - if (lsb) - prbs_lfsr ^= prbs_poly; - } - return rv; -} - -void ble_test_fill_tx_packet(int type, int len) -{ - int i; - - tx_packet.s0 = type & 0xf; - tx_packet.length = len; - - switch (type) { - case BLE_TEST_TYPE_PRBS9: - prbs_lfsr = 0xf; - prbs_poly = 0x108; - for (i = 0; i < len; i++) - tx_packet.payload[i] = prbs_next_byte(); - break; - case BLE_TEST_TYPE_PRBS15: - prbs_lfsr = 0xf; - prbs_poly = 0x6000; - for (i = 0; i < len; i++) - tx_packet.payload[i] = prbs_next_byte(); - break; - case BLE_TEST_TYPE_F0: - memset(tx_packet.payload, 0xF0, len); - break; - case BLE_TEST_TYPE_AA: - memset(tx_packet.payload, 0xAA, len); - break; - case BLE_TEST_TYPE_FF: - memset(tx_packet.payload, 0xFF, len); - break; - case BLE_TEST_TYPE_00: - memset(tx_packet.payload, 0x00, len); - break; - case BLE_TEST_TYPE_0F: - memset(tx_packet.payload, 0x0F, len); - break; - case BLE_TEST_TYPE_55: - memset(tx_packet.payload, 0x55, len); - break; - default: - break; - } -} - -static int ble_test_init(int chan) -{ - int rv = radio_init(BLE_1MBIT); - - if (rv) - return HCI_ERR_Hardware_Failure; - - if (chan > BLE_MAX_TEST_CHANNEL || chan < BLE_MIN_TEST_CHANNEL) - return HCI_ERR_Invalid_HCI_Command_Parameters; - - NRF51_RADIO_CRCCNF = 3 | BIT(8); /* 3-byte, skip address */ - /* x^24 + x^10 + x^9 + x^6 + x^4 + x^3 + x + 1 */ - /* 0x1_0000_0000_0000_0110_0101_1011 */ - NRF51_RADIO_CRCPOLY = 0x100065B; - NRF51_RADIO_CRCINIT = 0x555555; - - NRF51_RADIO_TXPOWER = NRF51_RADIO_TXPOWER_0_DBM; - - /* The testing address is the inverse of the advertising address. */ - NRF51_RADIO_BASE0 = (~BLE_ADV_ACCESS_ADDRESS) << 8; - - NRF51_RADIO_PREFIX0 = (~BLE_ADV_ACCESS_ADDRESS) >> 24; - - NRF51_RADIO_TXADDRESS = 0; - NRF51_RADIO_RXADDRESSES = 1; - - NRF51_RADIO_PCNF0 = NRF51_RADIO_PCNF0_TEST; - - NRF51_RADIO_PCNF1 = NRF51_RADIO_PCNF1_TEST; - - NRF51_RADIO_FREQUENCY = NRF51_RADIO_FREQUENCY_VAL(2*chan + 2402); - - test_in_progress = 1; - return rv; -} - -int ble_test_rx_init(int chan) -{ - NRF51_RADIO_PACKETPTR = (uint32_t)&rx_packet; - return ble_test_init(chan); -} - -int ble_test_tx_init(int chan, int len, int type) -{ - if ((BIT(type) & BLE_TEST_TYPES_IMPLEMENTED) == 0 || - (len < 0 || len > BLE_MAX_TEST_PAYLOAD_OCTETS)) - return HCI_ERR_Invalid_HCI_Command_Parameters; - - ble_test_fill_tx_packet(type, len); - NRF51_RADIO_PACKETPTR = (uint32_t)&tx_packet; - - return ble_test_init(chan); -} - -void ble_test_tx(void) -{ - NRF51_RADIO_END = 0; - NRF51_RADIO_TXEN = 1; -} - -int ble_test_rx(void) -{ - int retries = 100; - - NRF51_RADIO_END = 0; - NRF51_RADIO_RXEN = 1; - - do { - retries--; - if (retries <= 0) { - radio_disable(); - return EC_ERROR_TIMEOUT; - } - usleep(100); - } while (!NRF51_RADIO_END); - - rx_end = get_time().le.lo; - - return EC_SUCCESS; -} - diff --git a/chip/nrf51/radio_test.h b/chip/nrf51/radio_test.h deleted file mode 100644 index 591b78a78c..0000000000 --- a/chip/nrf51/radio_test.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * Radio test interface for NRF51 - * - * These functions implement parts of the Direct Test Mode functionality in - * the Bluetooth Spec. - */ - -#ifndef __NRF51_RADIO_TEST_H -#define __NRF51_RADIO_TEST_H - -#define BLE_MAX_TEST_PAYLOAD_OCTETS 37 -#define BLE_MAX_TEST_CHANNEL 39 -#define BLE_MIN_TEST_CHANNEL 0 - -#define NRF51_RADIO_PCNF0_TEST NRF51_RADIO_PCNF0_ADV_DATA - -#define BLE_TEST_WHITEN 0 - -#define NRF51_RADIO_PCNF1_TEST \ - NRF51_RADIO_PCNF1_VAL(BLE_MAX_TEST_PAYLOAD_OCTETS, \ - EXTRA_RECEIVE_BYTES, \ - BLE_ACCESS_ADDRESS_BYTES - 1, \ - BLE_TEST_WHITEN) - -/* - * Prepare the radio for transmitting packets. The value of chan must be - * between 0 and 39 inclusive. The maximum length is 37. - */ - -int ble_test_tx_init(int chan, int type, int len); -int ble_test_rx_init(int chan); -void ble_test_tx(void); -int ble_test_rx(void); -void ble_test_stop(void); - -#endif /* __NRF51_RADIO_TEST_H */ diff --git a/chip/nrf51/registers.h b/chip/nrf51/registers.h deleted file mode 100644 index daf014df72..0000000000 --- a/chip/nrf51/registers.h +++ /dev/null @@ -1,720 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Register map for STM32 processor - */ - -#ifndef __CROS_EC_REGISTERS_H -#define __CROS_EC_REGISTERS_H - -#include "common.h" - -/* - * Peripheral IDs - * - * nRF51 has very good design that the peripheral IDs is actually the IRQ#. - * Thus, the following numbers are used in DECLARE_IRQ(), task_enable_irq() - * and task_disable_irq(). - */ -#define NRF51_PERID_POWER 0 -#define NRF51_PERID_CLOCK 0 -#define NRF51_PERID_RADIO 1 -#define NRF51_PERID_USART 2 -#define NRF51_PERID_SPI0 3 -#define NRF51_PERID_TWI0 3 -#define NRF51_PERID_SPI1 4 -#define NRF51_PERID_TWI1 4 -#define NRF51_PERID_SPIS 4 -#define NRF51_PERID_GPIOTE 6 -#define NRF51_PERID_ADC 7 -#define NRF51_PERID_TIMER0 8 -#define NRF51_PERID_TIMER1 9 -#define NRF51_PERID_TIMER2 10 -#define NRF51_PERID_RTC 11 -#define NRF51_PERID_TEMP 12 -#define NRF51_PERID_RNG 13 -#define NRF51_PERID_ECB 14 -#define NRF51_PERID_CCM 15 -#define NRF51_PERID_AAR 16 -#define NRF51_PERID_WDT 17 -#define NRF51_PERID_QDEC 18 -#define NRF51_PERID_LPCOMP 19 -#define NRF51_PERID_NVMC 30 -#define NRF51_PERID_PPI 31 - -/* - * The nRF51 allows any pin to be mapped to any function. This - * doesn't fit well with the notion of the alternate function table. - * Implement an alternate function table. See ./gpio.c. - */ - - /* UART */ -#define NRF51_UART_ALT_FUNC_RTS 0 -#define NRF51_UART_ALT_FUNC_TXD 1 -#define NRF51_UART_ALT_FUNC_CTS 2 -#define NRF51_UART_ALT_FUNC_RXD 3 - /* SPI1 (SPI Master) */ -#define NRF51_SPI0_ALT_FUNC_SCK 4 -#define NRF51_SPI0_ALT_FUNC_MOSI 5 -#define NRF51_SPI0_ALT_FUNC_MISO 6 - /* TWI0 (I2C) */ -#define NRF51_TWI0_ALT_FUNC_SCL 7 -#define NRF51_TWI0_ALT_FUNC_SDA 8 - /* SPI1 (SPI Master) */ -#define NRF51_SPI1_ALT_FUNC_SCK 9 -#define NRF51_SPI1_ALT_FUNC_MOSI 10 -#define NRF51_SPI1_ALT_FUNC_MISO 11 - /* TWI1 (I2C) */ -#define NRF51_TWI1_ALT_FUNC_SCL 12 -#define NRF51_TWI1_ALT_FUNC_SDA 13 - /* SPIS1 (SPI SLAVE) */ -#define NRF51_SPIS1_ALT_FUNC_SCK 14 -#define NRF51_SPIS1_ALT_FUNC_MISO 15 -#define NRF51_SPIS1_ALT_FUNC_MOSI 16 -#define NRF51_SPIS1_ALT_FUNC_CSN 17 - /* QDEC (ROTARY DECODER) */ -#define NRF51_QDEC_ALT_FUNC_LED 18 -#define NRF51_QDEC_ALT_FUNC_A 19 -#define NRF51_QDEC_ALT_FUNC_B 20 - /* LPCOMP (Low Power Comparator) */ -#define NRF51_LPCOMP_ALT_FUNC 21 -#define NRF51_MAX_ALT_FUNCS 22 - -/* - * Configuration Registers - */ - -/* - * FICR - */ -#define NRF51_FICR_BASE 0x10000000 -#define NRF51_FICR_CODEPAGESIZE REG32(NRF51_FICR_BASE + 0x010) -#define NRF51_FICR_CLENR0 REG32(NRF51_FICR_BASE + 0x014) -#define NRF51_FICR_PPFC REG32(NRF51_FICR_BASE + 0x028) -#define NRF51_FICR_NUMRAMBLOCK REG32(NRF51_FICR_BASE + 0x02C) -#define NRF51_FICR_SIZERAMBLOCK(n) REG32(NRF51_FICR_BASE + 0x034 + ((n)*4)) -#define NRF51_FICR_CONFIGID REG32(NRF51_FICR_BASE + 0x05C) -#define NRF51_FICR_DEVICEID(n) REG32(NRF51_FICR_BASE + 0x060 + ((n)*4)) -#define NRF51_FICR_ER(n) REG32(NRF51_FICR_BASE + 0x080 + ((n)*4)) -#define NRF51_FICR_IR(n) REG32(NRF51_FICR_BASE + 0x090 + ((n)*4)) -#define NRF51_FICR_DEVICEADDRTYPE REG32(NRF51_FICR_BASE + 0x0A0) -#define NRF51_FICR_DEVICEADDR(n) REG32(NRF51_FICR_BASE + 0x0A4 + ((n)*4)) -#define NRF51_FICR_OVERRIDEEN REG32(NRF51_FICR_BASE + 0x0AC) -#define NRF51_FICR_BLE_1MBIT(n) REG32(NRF51_FICR_BASE + 0x0EC + ((n)*4)) - -/* DEVICEADDRTYPE */ -#define NRF51_FICR_DEVICEADDRTYPE_RANDOM 1 - -/* OVERRIDEEN */ -#define NRF51_FICR_OVERRIDEEN_NRF_BIT_N 1 -#define NRF51_FICR_OVERRIDEEN_BLE_BIT_N 8 - -/* - * UICR - */ -#define NRF51_UICR_BASE 0x10001000 -#define NRF51_UICR_CLENR0 REG32(NRF51_UICR_BASE + 0x000) -#define NRF51_UICR_RBPCONF REG32(NRF51_UICR_BASE + 0x004) -#define NRF51_UICR_XTALFREQ REG32(NRF51_UICR_BASE + 0x008) -#define NRF51_UICR_FWID REG32(NRF51_UICR_BASE + 0x010) -#define NRF51_UICR_FWID_CUSTOMER(n) REG32(NRF51_UICR_BASE + 0x080 + ((n)*4)) - -#define NRF51_UICR_XTALFREQ_16MHZ 0xFF -#define NRF51_UICR_XTALFREQ_32MHZ 0x00 - -/* - * Devices - */ - -/* - * Power - */ -#define NRF51_POWER_BASE 0x40000000 -/* Tasks */ -#define NRF51_POWER_CONSTLAT REG32(NRF51_POWER_BASE + 0x078) -#define NRF51_POWER_LOWPWR REG32(NRF51_POWER_BASE + 0x07C) -/* Events */ -#define NRF51_POWER_POFWARN REG32(NRF51_POWER_BASE + 0x108) -/* Registers */ -#define NRF51_POWER_INTENSET REG32(NRF51_POWER_BASE + 0x304) -#define NRF51_POWER_INTENCLR REG32(NRF51_POWER_BASE + 0x308) -#define NRF51_POWER_RESETREAS REG32(NRF51_POWER_BASE + 0x400) -#define NRF51_POWER_SYSTEMOFF REG32(NRF51_POWER_BASE + 0x500) -#define NRF51_POWER_POFCON REG32(NRF51_POWER_BASE + 0x510) -#define NRF51_POWER_GPREGRET REG32(NRF51_POWER_BASE + 0x51C) -#define NRF51_POWER_RAMON REG32(NRF51_POWER_BASE + 0x524) -#define NRF51_POWER_RESET REG32(NRF51_POWER_BASE + 0x544) -#define NRF51_POWER_DCDCEN REG32(NRF51_POWER_BASE + 0x578) - -#define NRF51_POWER_RESETREAS_RESETPIN 0x00001 -#define NRF51_POWER_RESETREAS_DOG 0x00002 -#define NRF51_POWER_RESETREAS_SREQ 0x00004 -#define NRF51_POWER_RESETREAS_LOCKUP 0x00008 -#define NRF51_POWER_RESETREAS_OFF 0x10000 -#define NRF51_POWER_RESETREAS_LPCOMP 0x20000 -#define NRF51_POWER_RESETREAS_DIF 0x40000 - - -/* - * Clock - */ -#define NRF51_CLOCK_BASE 0x40000000 -/* Tasks */ -#define NRF51_CLOCK_HFCLKSTART REG32(NRF51_CLOCK_BASE + 0x000) -#define NRF51_CLOCK_HFCLKSTOP REG32(NRF51_CLOCK_BASE + 0x004) -#define NRF51_CLOCK_LFCLKSTART REG32(NRF51_CLOCK_BASE + 0x008) -#define NRF51_CLOCK_LFCLKSTOP REG32(NRF51_CLOCK_BASE + 0x00C) -#define NRF51_CLOCK_CAL REG32(NRF51_CLOCK_BASE + 0x010) -#define NRF51_CLOCK_CTSTART REG32(NRF51_CLOCK_BASE + 0x014) -#define NRF51_CLOCK_CTSTOP REG32(NRF51_CLOCK_BASE + 0x018) -/* Events */ -#define NRF51_CLOCK_HFCLKSTARTED REG32(NRF51_CLOCK_BASE + 0x100) -#define NRF51_CLOCK_LFCLKSTARTED REG32(NRF51_CLOCK_BASE + 0x104) -#define NRF51_CLOCK_DONE REG32(NRF51_CLOCK_BASE + 0x10C) -#define NRF51_CLOCK_CCTO REG32(NRF51_CLOCK_BASE + 0x110) -/* Registers */ -#define NRF51_CLOCK_INTENSET REG32(NRF51_CLOCK_BASE + 0x304) -#define NRF51_CLOCK_INTENCLR REG32(NRF51_CLOCK_BASE + 0x308) -#define NRF51_CLOCK_HFCLKSTAT REG32(NRF51_CLOCK_BASE + 0x40C) -#define NRF51_CLOCK_LFCLKSTAT REG32(NRF51_CLOCK_BASE + 0x418) -#define NRF51_CLOCK_LFCLKSRC REG32(NRF51_CLOCK_BASE + 0x518) -#define NRF51_CLOCK_CTIV REG32(NRF51_CLOCK_BASE + 0x538) -#define NRF51_CLOCK_XTALFREQ REG32(NRF51_CLOCK_BASE + 0x550) - -/* - * Radio - */ -#define NRF51_RADIO_BASE 0x40001000 -/* Tasks */ -#define NRF51_RADIO_TXEN REG32(NRF51_RADIO_BASE + 0x000) -#define NRF51_RADIO_RXEN REG32(NRF51_RADIO_BASE + 0x004) -#define NRF51_RADIO_START REG32(NRF51_RADIO_BASE + 0x008) -#define NRF51_RADIO_STOP REG32(NRF51_RADIO_BASE + 0x00C) -#define NRF51_RADIO_DISABLE REG32(NRF51_RADIO_BASE + 0x010) -#define NRF51_RADIO_RSSISTART REG32(NRF51_RADIO_BASE + 0x014) -#define NRF51_RADIO_RSSISTOP REG32(NRF51_RADIO_BASE + 0x018) -#define NRF51_RADIO_BCSTART REG32(NRF51_RADIO_BASE + 0x01C) -#define NRF51_RADIO_BCSTOP REG32(NRF51_RADIO_BASE + 0x020) -/* Events */ -#define NRF51_RADIO_READY REG32(NRF51_RADIO_BASE + 0x100) -#define NRF51_RADIO_ADDRESS REG32(NRF51_RADIO_BASE + 0x104) -#define NRF51_RADIO_PAYLOAD REG32(NRF51_RADIO_BASE + 0x108) -#define NRF51_RADIO_END REG32(NRF51_RADIO_BASE + 0x10C) -#define NRF51_RADIO_DISABLED REG32(NRF51_RADIO_BASE + 0x110) -#define NRF51_RADIO_DEVMATCH REG32(NRF51_RADIO_BASE + 0x114) -#define NRF51_RADIO_DEVMISS REG32(NRF51_RADIO_BASE + 0x118) -#define NRF51_RADIO_RSSIEND REG32(NRF51_RADIO_BASE + 0x11C) -#define NRF51_RADIO_BCMATCH REG32(NRF51_RADIO_BASE + 0x128) -/* Registers */ -#define NRF51_RADIO_SHORTS REG32(NRF51_RADIO_BASE + 0x200) -#define NRF51_RADIO_INTENSET REG32(NRF51_RADIO_BASE + 0x304) -#define NRF51_RADIO_INTENCLR REG32(NRF51_RADIO_BASE + 0x308) -#define NRF51_RADIO_CRCSTATUS REG32(NRF51_RADIO_BASE + 0x400) -#define NRF51_RADIO_RXMATCH REG32(NRF51_RADIO_BASE + 0x408) -#define NRF51_RADIO_RXCRC REG32(NRF51_RADIO_BASE + 0x40C) -#define NRF51_RADIO_DAI REG32(NRF51_RADIO_BASE + 0x410) -#define NRF51_RADIO_PACKETPTR REG32(NRF51_RADIO_BASE + 0x504) -#define NRF51_RADIO_FREQUENCY REG32(NRF51_RADIO_BASE + 0x508) -#define NRF51_RADIO_TXPOWER REG32(NRF51_RADIO_BASE + 0x50C) -#define NRF51_RADIO_MODE REG32(NRF51_RADIO_BASE + 0x510) -#define NRF51_RADIO_PCNF0 REG32(NRF51_RADIO_BASE + 0x514) -#define NRF51_RADIO_PCNF1 REG32(NRF51_RADIO_BASE + 0x518) -#define NRF51_RADIO_BASE0 REG32(NRF51_RADIO_BASE + 0x51C) -#define NRF51_RADIO_BASE1 REG32(NRF51_RADIO_BASE + 0x520) -#define NRF51_RADIO_PREFIX0 REG32(NRF51_RADIO_BASE + 0x524) -#define NRF51_RADIO_PREFIX1 REG32(NRF51_RADIO_BASE + 0x528) -#define NRF51_RADIO_TXADDRESS REG32(NRF51_RADIO_BASE + 0x52C) -#define NRF51_RADIO_RXADDRESSES REG32(NRF51_RADIO_BASE + 0x530) -#define NRF51_RADIO_CRCCNF REG32(NRF51_RADIO_BASE + 0x534) -#define NRF51_RADIO_CRCPOLY REG32(NRF51_RADIO_BASE + 0x538) -#define NRF51_RADIO_CRCINIT REG32(NRF51_RADIO_BASE + 0x53C) -#define NRF51_RADIO_TEST REG32(NRF51_RADIO_BASE + 0x540) -#define NRF51_RADIO_TIFS REG32(NRF51_RADIO_BASE + 0x544) -#define NRF51_RADIO_RSSISAMPLE REG32(NRF51_RADIO_BASE + 0x548) -/* NRF51_RADIO_STATE (0x550) is Broken (PAN 2.4) */ -#define NRF51_RADIO_DATAWHITEIV REG32(NRF51_RADIO_BASE + 0x554) -#define NRF51_RADIO_BCC REG32(NRF51_RADIO_BASE + 0x560) -#define NRF51_RADIO_DAB(n) REG32(NRF51_RADIO_BASE + 0x600 + ((n) * 4)) -#define NRF51_RADIO_DAP(n) REG32(NRF51_RADIO_BASE + 0x620 + ((n) * 4)) -#define NRF51_RADIO_DACNF REG32(NRF51_RADIO_BASE + 0x640) -#define NRF51_RADIO_OVERRIDE(n) REG32(NRF51_RADIO_BASE + 0x724 + ((n) * 4)) -#define NRF51_RADIO_POWER REG32(NRF51_RADIO_BASE + 0xFFC) - -/* Shorts */ -#define NRF51_RADIO_SHORTS_READY_START 0x001 -#define NRF51_RADIO_SHORTS_END_DISABLE 0x002 -#define NRF51_RADIO_SHORTS_DISABLED_TXEN 0x004 -#define NRF51_RADIO_SHORTS_DISABLED_RXEN 0x008 -#define NRF51_RADIO_SHORTS_ADDRESS_RSSISTART 0x010 -/* NRF51_RADIO_SHORTS_END_START (0x20) is Broken (PAN 2.4) */ -#define NRF51_RADIO_SHORTS_ADDRESS_BCSTART 0x040 -#define NRF51_RADIO_SHORTS_DISABLED_RSSISTOP 0x100 - -/* For RADIO.INTEN bits */ -#define NRF51_RADIO_READY_BIT 0 -#define NRF51_RADIO_ADDRESS_BIT 1 -#define NRF51_RADIO_PAYLOAD_BIT 2 -#define NRF51_RADIO_END_BIT 3 -#define NRF51_RADIO_DISABLED_BIT 4 -#define NRF51_RADIO_DEVMATCH_BIT 5 -#define NRF51_RADIO_DEVMISS_BIT 6 -#define NRF51_RADIO_RSSIEND_BIT 7 -#define NRF51_RADIO_BCMATCH_BIT 10 - -/* CRC Status */ -#define NRF51_RADIO_CRCSTATUS_OK 0x1 - -/* Frequency (in MHz) */ -#define NRF51_RADIO_FREQUENCY_VAL(x) ((x) - 2400) - -/* TX Power */ -#define NRF51_RADIO_TXPOWER_POS_4_DBM 0x04 -#define NRF51_RADIO_TXPOWER_0_DBM 0x00 -#define NRF51_RADIO_TXPOWER_NEG_8_DBM 0xFC -#define NRF51_RADIO_TXPOWER_NEG_12_DBM 0xF8 -#define NRF51_RADIO_TXPOWER_NEG_16_DBM 0xF4 -#define NRF51_RADIO_TXPOWER_NEG_20_DBM 0xEC -#define NRF51_RADIO_TXPOWER_NEG_30_DBM 0xD8 - -/* TX Mode */ -#define NRF51_RADIO_MODE_BLE_1MBIT 0x03 - -/* - * PCNF0 and PCNF1 Packet Configuration - * - * The radio unpacks the packet for you according to these settings. - * - * The on-air format is: - * - * |_Preamble_|___Base___|_Prefix_|___S0____|_Length_,_S1_|__Payload__|___| - * 0 <1 byte> <1 byte> - * - * The in-memory format is - * - * uint8_t s0[s0_bytes]; - * uint8_t length; - * uint8_t s1; - * uint8_t payload[max_bytes]; - * - * lf_bits is how many bits to store in length - * s1_bits is how many bits to store in s1 - * - * If any one of these lengths are set to zero, the field is omitted in memory. - */ - -#define NRF51_RADIO_PCNF0_LFLEN_SHIFT 0 -#define NRF51_RADIO_PCNF0_S0LEN_SHIFT 8 -#define NRF51_RADIO_PCNF0_S1LEN_SHIFT 16 - -#define NRF51_RADIO_PCNF0_VAL(lf_bits, s0_bytes, s1_bits) \ - ((lf_bits) << NRF51_RADIO_PCNF0_LFLEN_SHIFT | \ - (s0_bytes) << NRF51_RADIO_PCNF0_S0LEN_SHIFT | \ - (s1_bits) << NRF51_RADIO_PCNF0_S1LEN_SHIFT) - -#define NRF51_RADIO_PCNF1_MAXLEN_SHIFT 0 -#define NRF51_RADIO_PCNF1_STATLEN_SHIFT 8 -#define NRF51_RADIO_PCNF1_BALEN_SHIFT 16 -#define NRF51_RADIO_PCNF1_ENDIAN_BIG 0x1000000 -#define NRF51_RADIO_PCNF1_WHITEEN 0x2000000 - -#define NRF51_RADIO_PCNF1_VAL(max_bytes, extra_bytes, ba_bytes, whiten) \ - ((max_bytes) << NRF51_RADIO_PCNF1_MAXLEN_SHIFT | \ - (extra_bytes) << NRF51_RADIO_PCNF1_STATLEN_SHIFT | \ - (ba_bytes) << NRF51_RADIO_PCNF1_BALEN_SHIFT | \ - ((whiten) ? NRF51_RADIO_PCNF1_WHITEEN : 0)) - -/* PREFIX0 */ -#define NRF51_RADIO_PREFIX0_AP0_SHIFT 0 -#define NRF51_RADIO_PREFIX0_AP1_SHIFT 8 -#define NRF51_RADIO_PREFIX0_AP2_SHIFT 16 -#define NRF51_RADIO_PREFIX0_AP3_SHIFT 24 - -/* PREFIX1 */ -#define NRF51_RADIO_PREFIX1_AP4_SHIFT 0 -#define NRF51_RADIO_PREFIX1_AP5_SHIFT 8 -#define NRF51_RADIO_PREFIX1_AP6_SHIFT 16 -#define NRF51_RADIO_PREFIX1_AP7_SHIFT 24 - -/* CRCCNF */ -#define NRF51_RADIO_CRCCNF_SKIP_ADDR 0x100 - -/* TEST */ -#define NRF51_RADIO_TEST_CONST_CARRIER_EN 0x01 -#define NRF51_RADIO_TEST_PLL_LOCK_EN 0x02 - -/* STATE */ -#define NRF51_RADIO_STATE_DISABLED 0 -#define NRF51_RADIO_STATE_RXRU 1 -#define NRF51_RADIO_STATE_RXIDLE 2 -#define NRF51_RADIO_STATE_RX 3 -#define NRF51_RADIO_STATE_RXDISABLE 4 -#define NRF51_RADIO_STATE_TXRU 9 -#define NRF51_RADIO_STATE_TXIDLE 10 -#define NRF51_RADIO_STATE_TX 11 -#define NRF51_RADIO_STATE_TXDISABLE 12 - -/* DACNF */ -#define NRF51_RADIO_DACNF_ENA(n) (1 << (n)) -#define NRF51_RADIO_DACNF_MAX 8 -#define NRF51_RADIO_DACNF_TXADD(n) (1 << ((n)+8)) -#define NRF51_RADIO_TXADD_MAX 8 - -/* OVERRIDE4 */ -#define NRF51_RADIO_OVERRIDE_EN BIT(31) - - -/* - * UART - */ -#define NRF51_UART_BASE 0x40002000 -/* Tasks */ -#define NRF51_UART_STARTRX REG32(NRF51_UART_BASE + 0x000) -#define NRF51_UART_STOPRX REG32(NRF51_UART_BASE + 0x004) -#define NRF51_UART_STARTTX REG32(NRF51_UART_BASE + 0x008) -#define NRF51_UART_STOPTX REG32(NRF51_UART_BASE + 0x00C) -/* Events */ -#define NRF51_UART_RXDRDY REG32(NRF51_UART_BASE + 0x108) -#define NRF51_UART_TXDRDY REG32(NRF51_UART_BASE + 0x11C) -#define NRF51_UART_ERROR REG32(NRF51_UART_BASE + 0x124) -#define NRF51_UART_RXTO REG32(NRF51_UART_BASE + 0x144) -/* Registers */ -#define NRF51_UART_INTENSET REG32(NRF51_UART_BASE + 0x304) -#define NRF51_UART_INTENCLR REG32(NRF51_UART_BASE + 0x308) -#define NRF51_UART_ERRORSRC REG32(NRF51_UART_BASE + 0x480) -#define NRF51_UART_ENABLE REG32(NRF51_UART_BASE + 0x500) -#define NRF51_UART_PSELRTS REG32(NRF51_UART_BASE + 0x508) -#define NRF51_UART_PSELTXD REG32(NRF51_UART_BASE + 0x50C) -#define NRF51_UART_PSELCTS REG32(NRF51_UART_BASE + 0x510) -#define NRF51_UART_PSELRXD REG32(NRF51_UART_BASE + 0x514) -#define NRF51_UART_RXD REG32(NRF51_UART_BASE + 0x518) -#define NRF51_UART_TXD REG32(NRF51_UART_BASE + 0x51C) -#define NRF51_UART_BAUDRATE REG32(NRF51_UART_BASE + 0x524) -#define NRF51_UART_CONFIG REG32(NRF51_UART_BASE + 0x56C) -/* For UART.INTEN bits */ -#define NRF55_UART_RXDRDY_BIT ((0x108 - 0x100) / 4) -#define NRF55_UART_TXDRDY_BIT ((0x11C - 0x100) / 4) - -/* - * TWI (I2C) Instances - */ -#define NRF51_TWI_BASE(port) (0x40003000 + ((port == 0) ? 0 : 0x1000)) -/* Tasks */ -#define NRF51_TWI_STARTRX(port) REG32(NRF51_TWI_BASE(port) + 0x000) -#define NRF51_TWI_STARTTX(port) REG32(NRF51_TWI_BASE(port) + 0x008) -#define NRF51_TWI_STOP(port) REG32(NRF51_TWI_BASE(port) + 0x014) -#define NRF51_TWI_SUSPEND(port) REG32(NRF51_TWI_BASE(port) + 0x01C) -#define NRF51_TWI_RESUME(port) REG32(NRF51_TWI_BASE(port) + 0x020) -/* Events */ -#define NRF51_TWI_STOPPED(port) REG32(NRF51_TWI_BASE(port) + 0x104) -#define NRF51_TWI_RXDRDY(port) REG32(NRF51_TWI_BASE(port) + 0x108) -#define NRF51_TWI_TXDSENT(port) REG32(NRF51_TWI_BASE(port) + 0x11C) -#define NRF51_TWI_ERROR(port) REG32(NRF51_TWI_BASE(port) + 0x124) -#define NRF51_TWI_BB(port) REG32(NRF51_TWI_BASE(port) + 0x138) -/* Registers */ -/* SHORTS not implemented for TWI (See nRF51822-PAN v2.4) */ -#define NRF51_TWI_INTEN(port) REG32(NRF51_TWI_BASE(port) + 0x300) -#define NRF51_TWI_INTENSET(port) REG32(NRF51_TWI_BASE(port) + 0x304) -#define NRF51_TWI_INTENCLR(port) REG32(NRF51_TWI_BASE(port) + 0x308) -#define NRF51_TWI_ERRORSRC(port) REG32(NRF51_TWI_BASE(port) + 0x4C4) -#define NRF51_TWI_ENABLE(port) REG32(NRF51_TWI_BASE(port) + 0x500) -#define NRF51_TWI_PSELSCL(port) REG32(NRF51_TWI_BASE(port) + 0x508) -#define NRF51_TWI_PSELSDA(port) REG32(NRF51_TWI_BASE(port) + 0x50C) -#define NRF51_TWI_RXD(port) REG32(NRF51_TWI_BASE(port) + 0x518) -#define NRF51_TWI_TXD(port) REG32(NRF51_TWI_BASE(port) + 0x51C) -#define NRF51_TWI_FREQUENCY(port) REG32(NRF51_TWI_BASE(port) + 0x524) -#define NRF51_TWI_ADDRESS(port) REG32(NRF51_TWI_BASE(port) + 0x588) -#define NRF51_TWI_POWER(port) REG32(NRF51_TWI_BASE(port) + 0xFFC) - -#define NRF51_TWI_100KBPS 0x01980000 -#define NRF51_TWI_250KBPS 0x40000000 -#define NRF51_TWI_400KBPS 0x06680000 - -#define NRF51_TWI_ENABLE_VAL 0x5 -#define NRF51_TWI_DISABLE_VAL 0x0 - -#define NRF51_TWI_ERRORSRC_ANACK BIT(1) /* Address NACK */ -#define NRF51_TWI_ERRORSRC_DNACK BIT(2) /* Data NACK */ - -/* - * TWI (I2C) Instance 0 - */ -#define NRF51_TWI0_BASE 0x40003000 -/* Tasks */ -#define NRF51_TWI0_STARTRX REG32(NRF51_TWI0_BASE + 0x000) -#define NRF51_TWI0_STARTTX REG32(NRF51_TWI0_BASE + 0x008) -#define NRF51_TWI0_STOP REG32(NRF51_TWI0_BASE + 0x014) -#define NRF51_TWI0_SUSPEND REG32(NRF51_TWI0_BASE + 0x01C) -#define NRF51_TWI0_RESUME REG32(NRF51_TWI0_BASE + 0x020) -/* Events */ -#define NRF51_TWI0_STOPPED REG32(NRF51_TWI0_BASE + 0x104) -#define NRF51_TWI0_RXDRDY REG32(NRF51_TWI0_BASE + 0x108) -#define NRF51_TWI0_TXDSENT REG32(NRF51_TWI0_BASE + 0x11C) -#define NRF51_TWI0_ERROR REG32(NRF51_TWI0_BASE + 0x124) -#define NRF51_TWI0_BB REG32(NRF51_TWI0_BASE + 0x138) -/* Registers */ -/* SHORTS not implemented for TWI (See nRF51822-PAN v2.4) */ -#define NRF51_TWI0_INTENSET REG32(NRF51_TWI0_BASE + 0x304) -#define NRF51_TWI0_INTENCLR REG32(NRF51_TWI0_BASE + 0x308) -#define NRF51_TWI0_ERRORSRC REG32(NRF51_TWI0_BASE + 0x4C4) -#define NRF51_TWI0_ENABLE REG32(NRF51_TWI0_BASE + 0x500) -#define NRF51_TWI0_PSELSCL REG32(NRF51_TWI0_BASE + 0x508) -#define NRF51_TWI0_PSELSDA REG32(NRF51_TWI0_BASE + 0x50C) -#define NRF51_TWI0_RXD REG32(NRF51_TWI0_BASE + 0x518) -#define NRF51_TWI0_TXD REG32(NRF51_TWI0_BASE + 0x51C) -#define NRF51_TWI0_FREQUENCY REG32(NRF51_TWI0_BASE + 0x524) -#define NRF51_TWI0_ADDRESS REG32(NRF51_TWI0_BASE + 0x588) - -/* For TWI0.INTEN bits */ -#define NRF55_TWI0_RXDRDY_BIT ((0x108 - 0x100) / 4) -#define NRF55_TWI0_TXDRDY_BIT ((0x11C - 0x100) / 4) - -/* - * TWI (I2C) Instance 1 - */ -#define NRF51_TWI1_BASE 0x40004000 -/* Tasks */ -#define NRF51_TWI1_STARTRX REG32(NRF51_TWI1_BASE + 0x000) -#define NRF51_TWI1_STARTTX REG32(NRF51_TWI1_BASE + 0x008) -#define NRF51_TWI1_STOP REG32(NRF51_TWI1_BASE + 0x014) -#define NRF51_TWI1_SUSPEND REG32(NRF51_TWI1_BASE + 0x01C) -#define NRF51_TWI1_RESUME REG32(NRF51_TWI1_BASE + 0x020) -/* Events */ -#define NRF51_TWI1_STOPPED REG32(NRF51_TWI1_BASE + 0x104) -#define NRF51_TWI1_RXDRDY REG32(NRF51_TWI1_BASE + 0x108) -#define NRF51_TWI1_TXDSENT REG32(NRF51_TWI1_BASE + 0x11C) -#define NRF51_TWI1_ERROR REG32(NRF51_TWI1_BASE + 0x124) -#define NRF51_TWI1_BB REG32(NRF51_TWI1_BASE + 0x138) -/* Registers */ -/* SHORTS not implemented for TWI (See nRF51822-PAN v2.4) */ -#define NRF51_TWI1_INTENSET REG32(NRF51_TWI1_BASE + 0x304) -#define NRF51_TWI1_INTENCLR REG32(NRF51_TWI1_BASE + 0x308) -#define NRF51_TWI1_ERRORSRC REG32(NRF51_TWI1_BASE + 0x4C4) -#define NRF51_TWI1_ENABLE REG32(NRF51_TWI1_BASE + 0x500) -#define NRF51_TWI1_PSELSCL REG32(NRF51_TWI1_BASE + 0x508) -#define NRF51_TWI1_PSELSDA REG32(NRF51_TWI1_BASE + 0x50C) -#define NRF51_TWI1_RXD REG32(NRF51_TWI1_BASE + 0x518) -#define NRF51_TWI1_TXD REG32(NRF51_TWI1_BASE + 0x51C) -#define NRF51_TWI1_FREQUENCY REG32(NRF51_TWI1_BASE + 0x524) -#define NRF51_TWI1_ADDRESS REG32(NRF51_TWI1_BASE + 0x588) - -/* For TWI1.INTEN bits */ -#define NRF55_TWI1_RXDRDY_BIT ((0x108 - 0x100) / 4) -#define NRF55_TWI1_TXDRDY_BIT ((0x11C - 0x100) / 4) - -/* - * GPIOTE - GPIO Tasks and Events - */ -#define NRF51_GPIOTE_BASE 0x40006000 -/* Tasks */ -#define NRF51_GPIOTE_OUT(n) REG32(NRF51_GPIOTE_BASE + ((n) * 4)) -/* Events */ -#define NRF51_GPIOTE_IN(n) REG32(NRF51_GPIOTE_BASE + 0x100 + ((n) * 4)) -#define NRF51_GPIOTE_PORT REG32(NRF51_GPIOTE_BASE + 0x17C) -/* Registers */ -#define NRF51_GPIOTE_INTENSET REG32(NRF51_GPIOTE_BASE + 0x304) -#define NRF51_GPIOTE_INTENCLR REG32(NRF51_GPIOTE_BASE + 0x308) -#define NRF51_GPIOTE_CONFIG(n) REG32(NRF51_GPIOTE_BASE + 0x510 + ((n) * 4)) -#define NRF51_GPIOTE_POWER REG32(NRF51_GPIOTE_BASE + 0xFFC) - -/* Number of IN events */ -#define NRF51_GPIOTE_IN_COUNT 4 - -/* Bits */ -/* For GPIOTE.INTEN */ -#define NRF51_GPIOTE_IN_BIT(n) (n) -#define NRF51_GPIOTE_PORT_BIT 31 -/* For GPIOTE.CONFIG */ -#define NRF51_GPIOTE_MODE_DISABLED (0<<0) -#define NRF51_GPIOTE_MODE_EVENT BIT(0) -#define NRF51_GPIOTE_MODE_TASK (3<<0) -#define NRF51_GPIOTE_PSEL_POS (8) -#define NRF51_GPIOTE_POLARITY_LOTOHI BIT(16) -#define NRF51_GPIOTE_POLARITY_HITOLO (2<<16) -#define NRF51_GPIOTE_POLARITY_TOGGLE (3<<16) -#define NRF51_GPIOTE_OUTINIT_LOW (0<<20) -#define NRF51_GPIOTE_OUTINIT_HIGH BIT(20) - -/* - * Timer / Counter - */ -#define NRF51_TIMER0_BASE 0x40008000 -#define NRF51_TIMER_BASE(n) (NRF51_TIMER0_BASE + (n) * 0x1000) -#define NRF51_PERID_TIMER(n) (NRF51_PERID_TIMER0 + (n)) -/* Tasks */ -#define NRF51_TIMER_START(n) REG32(NRF51_TIMER_BASE(n) + 0x000) -#define NRF51_TIMER_STOP(n) REG32(NRF51_TIMER_BASE(n) + 0x004) -#define NRF51_TIMER_COUNT(n) REG32(NRF51_TIMER_BASE(n) + 0x008) -#define NRF51_TIMER_CLEAR(n) REG32(NRF51_TIMER_BASE(n) + 0x00C) -#define NRF51_TIMER_CAPTURE(n, c) REG32(NRF51_TIMER_BASE(n) + 0x040 + 4 * (c)) -/* Events */ -#define NRF51_TIMER_COMPARE(n, c) REG32(NRF51_TIMER_BASE(n) + 0x140 + 4 * (c)) -/* Registers */ -#define NRF51_TIMER_SHORTCUT(n) REG32(NRF51_TIMER_BASE(n) + 0x200) -#define NRF51_TIMER_INTENSET(n) REG32(NRF51_TIMER_BASE(n) + 0x304) -#define NRF51_TIMER_INTENCLR(n) REG32(NRF51_TIMER_BASE(n) + 0x308) -#define NRF51_TIMER_MODE(n) REG32(NRF51_TIMER_BASE(n) + 0x504) -#define NRF51_TIMER_BITMODE(n) REG32(NRF51_TIMER_BASE(n) + 0x508) -#define NRF51_TIMER_PRESCALER(n) REG32(NRF51_TIMER_BASE(n) + 0x510) -#define NRF51_TIMER_CC(n, c) REG32(NRF51_TIMER_BASE(n) + 0x540 + 4 * (c)) -/* For Timer.INTEN bits */ -#define NRF51_TIMER_COMPARE_BIT(n) (((0x140 - 0x100) / 4) + (n)) -/* For Timer Shortcuts */ -#define NRF51_TIMER_COMPARE_CLEAR(n) (1 << (n)) -#define NRF51_TIMER_COMPARE_STOP(n) (1 << (8 + (n))) -/* Timer Mode (NRF51_TIMER_MODE) */ -#define NRF51_TIMER_MODE_TIMER 0 /* reset default */ -#define NRF51_TIMER_MODE_COUNTER 1 -/* Prescaler */ -#define NRF51_TIMER_PRESCALER_MASK (0xf) /* range: 0-9, reset default: 4 */ -/* Bit length (NRF51_TIMER_BITMODE) */ -#define NRF51_TIMER_BITMODE_16 0 /* reset default */ -#define NRF51_TIMER_BITMODE_8 1 -#define NRF51_TIMER_BITMODE_24 2 -#define NRF51_TIMER_BITMODE_32 3 - - -/* - * Random Number Generator (RNG) - */ -#define NRF51_RNG_BASE 0x4000D000 -/* Tasks */ -#define NRF51_RNG_START REG32(NRF51_RNG_BASE + 0x000) -#define NRF51_RNG_STOP REG32(NRF51_RNG_BASE + 0x004) -/* Events */ -#define NRF51_RNG_VALRDY REG32(NRF51_RNG_BASE + 0x100) -/* Registers */ -#define NRF51_RNG_SHORTS REG32(NRF51_RNG_BASE + 0x200) -#define NRF51_RNG_INTENSET REG32(NRF51_RNG_BASE + 0x304) -#define NRF51_RNG_INTENCLR REG32(NRF51_RNG_BASE + 0x308) -#define NRF51_RNG_CONFIG REG32(NRF51_RNG_BASE + 0x504) -#define NRF51_RNG_VALUE REG32(NRF51_RNG_BASE + 0x508) -/* For RNG Shortcuts */ -#define NRF51_RNG_SHORTS_VALRDY_STOP BIT(0) -/* For RNG Config */ -#define NRF51_RNG_DERCEN BIT(0) - - -/* - * Watchdog Timer (WDT) - */ -#define NRF51_WDT_BASE 0x40010000 -/* Tasks */ -#define NRF51_WDT_START REG32(NRF51_WDT_BASE + 0x000) -/* Events */ -#define NRF51_WDT_TIMEOUT REG32(NRF51_WDT_BASE + 0x100) -/* Registers */ -#define NRF51_WDT_INTENSET REG32(NRF51_WDT_BASE + 0x304) -#define NRF51_WDT_INTENCLR REG32(NRF51_WDT_BASE + 0x308) -#define NRF51_WDT_RUNSTATUS REG32(NRF51_WDT_BASE + 0x400) -#define NRF51_WDT_REQSTATUS REG32(NRF51_WDT_BASE + 0x404) -#define NRF51_WDT_CRV REG32(NRF51_WDT_BASE + 0x504) -#define NRF51_WDT_RREN REG32(NRF51_WDT_BASE + 0x508) -#define NRF51_WDT_CONFIG REG32(NRF51_WDT_BASE + 0x50C) -#define NRF51_WDT_RR(n) REG32(NRF51_WDT_BASE + 0x600 + ((n) * 4)) -#define NRF51_WDT_POWER REG32(NRF51_WDT_BASE + 0xFFC) -/* Bitfields */ -#define NRF51_WDT_RUNSTATUS_RUNNING 1 -#define NRF51_WDT_REQSTATUS_BIT(n) (1<<(n)) -#define NRF51_WDT_RREN_BIT(n) (1<<(n)) -#define NRF51_WDT_CONFIG_SLEEP_PAUSE 0 -#define NRF51_WDT_CONFIG_SLEEP_RUN 1 -#define NRF51_WDT_CONFIG_HALT_PAUSE (0<<4) -#define NRF51_WDT_CONFIG_HALT_RUN BIT(4) - -#define NRF51_WDT_RELOAD_VAL 0x6E524635 - - -/* - * GPIO - */ -#define NRF51_GPIO_BASE 0x50000000 -#define NRF51_GPIO0_BASE (NRF51_GPIO_BASE + 0x500) -#define NRF51_GPIO0_OUT REG32(NRF51_GPIO0_BASE + 0x004) -#define NRF51_GPIO0_OUTSET REG32(NRF51_GPIO0_BASE + 0x008) -#define NRF51_GPIO0_OUTCLR REG32(NRF51_GPIO0_BASE + 0x00C) -#define NRF51_GPIO0_IN REG32(NRF51_GPIO0_BASE + 0x010) -#define NRF51_GPIO0_DIR REG32(NRF51_GPIO0_BASE + 0x014) /* 1 for output */ -#define NRF51_GPIO0_DIRSET REG32(NRF51_GPIO0_BASE + 0x018) -#define NRF51_GPIO0_DIRCLR REG32(NRF51_GPIO0_BASE + 0x01C) -#define NRF51_PIN_BASE (NRF51_GPIO_BASE + 0x700) -#define NRF51_PIN_CNF(n) REG32(NRF51_PIN_BASE + ((n) * 4)) -#define GPIO_0 NRF51_GPIO0_BASE - -#define NRF51_PIN_CNF_DIR_INPUT (0) -#define NRF51_PIN_CNF_DIR_OUTPUT (1) -#define NRF51_PIN_CNF_INPUT_CONNECT (0<<1) -#define NRF51_PIN_CNF_INPUT_DISCONNECT BIT(1) -#define NRF51_PIN_CNF_PULL_DISABLED (0<<2) -#define NRF51_PIN_CNF_PULLDOWN BIT(2) -#define NRF51_PIN_CNF_PULLUP (3<<2) -/* - * Logic levels 0 and 1, strengths S=Standard, H=High D=Disconnect - * for example, S0D1 = Standard drive 0, disconnect on 1 - */ -#define NRF51_PIN_CNF_DRIVE_S0S1 (0<<8) -#define NRF51_PIN_CNF_DRIVE_H0S1 BIT(8) -#define NRF51_PIN_CNF_DRIVE_S0H1 (2<<8) -#define NRF51_PIN_CNF_DRIVE_H0H1 (3<<8) -#define NRF51_PIN_CNF_DRIVE_D0S1 (4<<8) -#define NRF51_PIN_CNF_DRIVE_D0H1 (5<<8) -#define NRF51_PIN_CNF_DRIVE_S0D1 (6<<8) -#define NRF51_PIN_CNF_DRIVE_H0D1 (7<<8) - -#define NRF51_PIN_CNF_SENSE_DISABLED (0<<16) -#define NRF51_PIN_CNF_SENSE_HIGH (2<<16) -#define NRF51_PIN_CNF_SENSE_LOW (3<<16) - -#define UNIMPLEMENTED_GPIO_BANK GPIO_0 /* for UNIMPLEMENTED() macro */ - -#define NRF51_PPI_BASE 0x4001F000 -#define NRF51_PPI_CHEN REG32(NRF51_PPI_BASE + 0x500) -#define NRF51_PPI_CHENSET REG32(NRF51_PPI_BASE + 0x504) -#define NRF51_PPI_CHENCLR REG32(NRF51_PPI_BASE + 0x508) -#define NRF51_PPI_EEP(channel) REG32(NRF51_PPI_BASE + 0x510 + channel*8) -#define NRF51_PPI_TEP(channel) REG32(NRF51_PPI_BASE + 0x514 + channel*8) -#define NRF51_PPI_CHG(group) REG32(NRF51_PPI_BASE + 0x800 + group*4) - -#define NRF51_PPI_NUM_PROGRAMMABLE_CHANNELS 16 -#define NRF51_PPI_NUM_GROUPS 4 - -#define NRF51_PPI_CH_TIMER0_CC0__RADIO_TXEN 20 -#define NRF51_PPI_CH_TIMER0_CC0__RADIO_RXEN 21 -#define NRF51_PPI_CH_TIMER0_CC1__RADIO_DISABLE 22 -#define NRF51_PPI_CH_RADIO_BCMATCH__AAR_START 23 -#define NRF51_PPI_CH_RADIO_READY__CCM_KSGEN 24 -#define NRF51_PPI_CH_RADIO_ADDR__CCM_CRYPT 25 -#define NRF51_PPI_CH_RADIO_ADDR__TIMER0CC1 26 -#define NRF51_PPI_CH_RADIO_END_TIMER0CC2 27 -#define NRF51_PPI_CH_RTC0_COMPARE0__RADIO_TXEN 28 -#define NRF51_PPI_CH_RTC0_COMPARE0__RADIO_RXEN 29 -#define NRF51_PPI_CH_RTC0_COMPARE0__TIMER0_CLEAR 30 -#define NRF51_PPI_CH_RTC0_COMPARE0__TIMER0_START 31 - -#define NRF51_PPI_CH_FIRST NRF51_PPI_CH_TIMER0_CC0__RADIO_TXEN -#define NRF51_PPI_CH_LAST NRF51_PPI_CH_RTC0_COMPARE0__TIMER0_START - - -/* These will be defined in their respective functions if/when they are used. */ -#define NRF51_SPI0_BASE 0x40003000 -#define NRF51_SPI0_PSELSCK REG32(NRF51_SPI0_BASE + 0x508) -#define NRF51_SPI0_PSELMOSI REG32(NRF51_SPI0_BASE + 0x50C) -#define NRF51_SPI0_PSELMISO REG32(NRF51_SPI0_BASE + 0x510) -#define NRF51_SPI1_BASE 0x40004000 -#define NRF51_SPI1_PSELSCK REG32(NRF51_SPI1_BASE + 0x508) -#define NRF51_SPI1_PSELMOSI REG32(NRF51_SPI1_BASE + 0x50C) -#define NRF51_SPI1_PSELMISO REG32(NRF51_SPI1_BASE + 0x510) -#define NRF51_SPIS1_BASE 0x40004000 -#define NRF51_SPIS1_PSELSCK REG32(NRF51_SPIS1_BASE + 0x508) -#define NRF51_SPIS1_PSELMISO REG32(NRF51_SPIS1_BASE + 0x50C) -#define NRF51_SPIS1_PSELMOSI REG32(NRF51_SPIS1_BASE + 0x510) -#define NRF51_SPIS1_PSELCSN REG32(NRF51_SPIS1_BASE + 0x514) -#define NRF51_QDEC_BASE 0x40012000 -#define NRF51_QDEC_PSELLED REG32(NRF51_QDEC_BASE + 0x51C) -#define NRF51_QDEC_PSELA REG32(NRF51_QDEC_BASE + 0x520) -#define NRF51_QDEC_PSELB REG32(NRF51_QDEC_BASE + 0x524) -#define NRF51_LPCOMP_BASE 0x40013000 -#define NRF51_LPCOMP_PSEL REG32(NRF51_LPCOMP_BASE + 0x504) - -#endif /* __CROS_EC_REGISTERS_H */ - diff --git a/chip/nrf51/system.c b/chip/nrf51/system.c deleted file mode 100644 index dc7bff2059..0000000000 --- a/chip/nrf51/system.c +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* System module for Chrome EC : hardware specific implementation */ - -#include "common.h" -#include "console.h" -#include "ec_commands.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "cpu.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) - -const char *system_get_chip_vendor(void) -{ - return "nrf"; -} - -const char *system_get_chip_name(void) -{ - return "nrf51822"; -} - -const char *system_get_chip_revision(void) -{ - return ""; -} - -void system_hibernate(uint32_t seconds, uint32_t microseconds) -{ - /* Flush console before hibernating */ - cflush(); - - if (board_hibernate) - board_hibernate(); - - /* chip specific standby mode */ - CPRINTS("TODO: implement %s()", __func__); -} - - -static void check_reset_cause(void) -{ - uint32_t flags = 0; - uint32_t raw_cause = NRF51_POWER_RESETREAS; - - if (raw_cause & NRF51_POWER_RESETREAS_RESETPIN) - flags |= EC_RESET_FLAG_RESET_PIN; - - if (raw_cause & NRF51_POWER_RESETREAS_DOG) - flags |= EC_RESET_FLAG_WATCHDOG; - - /* Note that the programmer uses a soft reset in debug mode. */ - if (raw_cause & NRF51_POWER_RESETREAS_SREQ) - flags |= EC_RESET_FLAG_SOFT; - - if (raw_cause & (NRF51_POWER_RESETREAS_OFF | - NRF51_POWER_RESETREAS_LPCOMP)) - flags |= EC_RESET_FLAG_WAKE_PIN; - - if (raw_cause & (NRF51_POWER_RESETREAS_LOCKUP | - NRF51_POWER_RESETREAS_DIF)) - flags |= EC_RESET_FLAG_OTHER; - - system_set_reset_flags(flags); - - /* clear it by writing 1's */ - NRF51_POWER_RESETREAS = raw_cause; -} - -static void system_watchdog_reset(void) -{ - if (NRF51_WDT_TIMEOUT != 0) { - /* Hard reset the WDT */ - NRF51_WDT_POWER = 0; - NRF51_WDT_POWER = 1; - } - - /* NRF51_WDT_CONFIG_HALT_RUN breaks this */ - NRF51_WDT_CONFIG = NRF51_WDT_CONFIG_SLEEP_RUN; - - NRF51_WDT_RREN = NRF51_WDT_RREN_BIT(0); - NRF51_WDT_CRV = 3; /* @32KHz */ - NRF51_WDT_START = 1; -} - -void system_reset(int flags) -{ - /* Disable interrupts to avoid task swaps during reboot */ - interrupt_disable(); - - if (flags & SYSTEM_RESET_HARD) - /* Ask the watchdog to trigger a hard reboot */ - system_watchdog_reset(); - else { - /* Use SYSRESETREQ to trigger a soft reboot */ - CPU_NVIC_APINT = 0x05fa0004; - } - - /* Spin and wait for reboot; should never return */ - while (1) - ; -} - -int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) -{ - CPRINTS("TODO: implement %s()", __func__); - return EC_ERROR_UNIMPLEMENTED; -} - -int system_set_bbram(enum system_bbram_idx idx, uint8_t value) -{ - CPRINTS("TODO: implement %s()", __func__); - return EC_ERROR_UNIMPLEMENTED; -} - -void system_pre_init(void) -{ - check_reset_cause(); -} diff --git a/chip/nrf51/uart.c b/chip/nrf51/uart.c deleted file mode 100644 index 1f546a2b79..0000000000 --- a/chip/nrf51/uart.c +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* USART driver for Chrome EC */ - -#include "clock.h" -#include "console.h" -#include "common.h" -#include "dma.h" -#include "hooks.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "uart.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) - - -static int ever_sent; /* if we ever sent byte to TXD? */ -static int init_done; /* Initialization done? */ -static int should_stop; /* Last TX control action */ - -int uart_init_done(void) -{ - return init_done; -} - -void uart_tx_start(void) -{ - disable_sleep(SLEEP_MASK_UART); - should_stop = 0; - NRF51_UART_INTENSET = BIT(NRF55_UART_TXDRDY_BIT); - task_trigger_irq(NRF51_PERID_USART); -} - -void uart_tx_stop(void) -{ - NRF51_UART_INTENCLR = BIT(NRF55_UART_TXDRDY_BIT); - should_stop = 1; - enable_sleep(SLEEP_MASK_UART); -} - -int uart_tx_ready(void) -{ - /* - * nRF51 design is NOT tx-empty style. Instead, it is if a byte is - * ever transmitted from TxD. This means NRF51_UART_TXDRDY is always - * 0 after reset. So, we use 'ever_sent' to send the first byte. - */ - return NRF51_UART_TXDRDY || (!ever_sent); -} - -int uart_rx_available(void) -{ - return NRF51_UART_RXDRDY; -} - -void uart_tx_flush(void) -{ - while (!uart_tx_ready()) - ; -} - -void uart_write_char(char c) -{ - ever_sent = 1; - NRF51_UART_TXDRDY = 0; - NRF51_UART_TXD = c; - NRF51_UART_STARTTX = 1; -} - -int uart_read_char(void) -{ - NRF51_UART_RXDRDY = 0; - return NRF51_UART_RXD; -} - -/* Interrupt handler for console USART */ -void uart_interrupt(void) -{ -#ifndef CONFIG_UART_RX_DMA - /* - * Read input FIFO until empty. DMA-based receive does this from a - * hook in the UART buffering module. - */ - uart_process_input(); -#endif - - /* Fill output FIFO */ - uart_process_output(); - -#ifndef CONFIG_UART_TX_DMA - if (!should_stop) - NRF51_UART_INTENSET = BIT(NRF55_UART_TXDRDY_BIT); -#endif /* CONFIG_UART_TX_DMA */ - -} -DECLARE_IRQ(NRF51_PERID_USART, uart_interrupt, 2); - - -void uart_init(void) -{ - NRF51_UART_PSELTXD = NRF51_UART_TX_PIN; /* GPIO Port for Tx */ - NRF51_UART_PSELRXD = NRF51_UART_RX_PIN; /* GPIO Port for Rx */ - NRF51_UART_CONFIG = 0; /* disable HW flow control, no parity bit */ - NRF51_UART_BAUDRATE = 0x01d7e000; /* 115200 */ - NRF51_UART_ENABLE = 0x4; /* Enable UART */ - - task_enable_irq(NRF51_PERID_USART); - - NRF51_UART_INTENSET = BIT(NRF55_UART_RXDRDY_BIT); - NRF51_UART_STARTRX = 1; - - init_done = 1; -} diff --git a/chip/nrf51/watchdog.c b/chip/nrf51/watchdog.c deleted file mode 100644 index da947df48e..0000000000 --- a/chip/nrf51/watchdog.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Watchdog driver */ - -#include "common.h" -#include "console.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) - - -int watchdog_init(void) -{ - CPRINTS("TODO: implement %s()", __func__); - return EC_ERROR_UNIMPLEMENTED; -} diff --git a/chip/stm32/adc-stm32f0.c b/chip/stm32/adc-stm32f0.c index d900cbc514..597861cb33 100644 --- a/chip/stm32/adc-stm32f0.c +++ b/chip/stm32/adc-stm32f0.c @@ -1,10 +1,9 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "clock.h" #include "common.h" #include "console.h" @@ -22,7 +21,7 @@ struct adc_profile_t { /* Register values. */ uint32_t cfgr1_reg; uint32_t cfgr2_reg; - uint32_t smpr_reg; /* Default Sampling Rate */ + uint32_t smpr_reg; /* Default Sampling Rate */ uint32_t ier_reg; /* DMA config. */ const struct dma_option *dma_option; @@ -32,7 +31,8 @@ struct adc_profile_t { #ifdef CONFIG_ADC_PROFILE_SINGLE static const struct dma_option dma_single = { - STM32_DMAC_ADC, (void *)&STM32_ADC_DR, + STM32_DMAC_ADC, + (void *)&STM32_ADC_DR, STM32_DMA_CCR_MSIZE_32_BIT | STM32_DMA_CCR_PSIZE_32_BIT, }; @@ -42,12 +42,9 @@ static const struct dma_option dma_single = { static const struct adc_profile_t profile = { /* Sample all channels once using DMA */ - .cfgr1_reg = STM32_ADC_CFGR1_OVRMOD, - .cfgr2_reg = 0, - .smpr_reg = CONFIG_ADC_SAMPLE_TIME, - .ier_reg = 0, - .dma_option = &dma_single, - .dma_buffer_size = 1, + .cfgr1_reg = STM32_ADC_CFGR1_OVRMOD, .cfgr2_reg = 0, + .smpr_reg = CONFIG_ADC_SAMPLE_TIME, .ier_reg = 0, + .dma_option = &dma_single, .dma_buffer_size = 1, }; #endif @@ -58,15 +55,15 @@ static const struct adc_profile_t profile = { #endif static const struct dma_option dma_continuous = { - STM32_DMAC_ADC, (void *)&STM32_ADC_DR, + STM32_DMAC_ADC, + (void *)&STM32_ADC_DR, STM32_DMA_CCR_MSIZE_32_BIT | STM32_DMA_CCR_PSIZE_32_BIT | - STM32_DMA_CCR_CIRC, + STM32_DMA_CCR_CIRC, }; static const struct adc_profile_t profile = { /* Sample all channels continuously using DMA */ - .cfgr1_reg = STM32_ADC_CFGR1_OVRMOD | - STM32_ADC_CFGR1_CONT | + .cfgr1_reg = STM32_ADC_CFGR1_OVRMOD | STM32_ADC_CFGR1_CONT | STM32_ADC_CFGR1_DMACFG, .cfgr2_reg = 0, .smpr_reg = CONFIG_ADC_SAMPLE_TIME, @@ -111,14 +108,14 @@ static void adc_init(const struct adc_t *adc) STM32_ADC_CR = STM32_ADC_CR_ADEN; } -static void adc_configure(int ain_id, enum stm32_adc_smpr sample_rate) +static void adc_configure(int ain_id, enum stm32_adc_smpr sample_time) { /* Sampling time */ - if (sample_rate == STM32_ADC_SMPR_DEFAULT || - sample_rate >= STM32_ADC_SMPR_COUNT) + if (sample_time == STM32_ADC_SMPR_DEFAULT || + sample_time >= STM32_ADC_SMPR_COUNT) STM32_ADC_SMPR = profile.smpr_reg; else - STM32_ADC_SMPR = STM32_ADC_SMPR_SMP(sample_rate); + STM32_ADC_SMPR = STM32_ADC_SMPR_SMP(sample_time); /* Select channel to convert */ STM32_ADC_CHSELR = BIT(ain_id); @@ -161,12 +158,12 @@ static void adc_interval_read(int ain_id, int interval_ms) adc_configure(ain_id, STM32_ADC_SMPR_DEFAULT); /* EXTEN=01 -> hardware trigger detection on rising edge */ - STM32_ADC_CFGR1 = (STM32_ADC_CFGR1 & ~STM32_ADC_CFGR1_EXTEN_MASK) - | STM32_ADC_CFGR1_EXTEN_RISE; + STM32_ADC_CFGR1 = (STM32_ADC_CFGR1 & ~STM32_ADC_CFGR1_EXTEN_MASK) | + STM32_ADC_CFGR1_EXTEN_RISE; /* EXTSEL=TRG3 -> Trigger on TIM3_TRGO */ STM32_ADC_CFGR1 = (STM32_ADC_CFGR1 & ~STM32_ADC_CFGR1_TRG_MASK) | - STM32_ADC_CFGR1_TRG3; + STM32_ADC_CFGR1_TRG3; __hw_timer_enable_clock(TIM_ADC, 1); @@ -294,9 +291,18 @@ int adc_set_watchdog_delay(int delay_ms) #else /* CONFIG_ADC_WATCHDOG */ -static int adc_watchdog_enabled(void) { return 0; } -static int adc_enable_watchdog_no_lock(void) { return 0; } -static int adc_disable_watchdog_no_lock(void) { return 0; } +static int adc_watchdog_enabled(void) +{ + return 0; +} +static int adc_enable_watchdog_no_lock(void) +{ + return 0; +} +static int adc_disable_watchdog_no_lock(void) +{ + return 0; +} #endif /* CONFIG_ADC_WATCHDOG */ @@ -315,7 +321,7 @@ int adc_read_channel(enum adc_channel ch) adc_disable_watchdog_no_lock(); } - adc_configure(adc->channel, adc->sample_rate); + adc_configure(adc->channel, adc->sample_time); /* Clear flags */ STM32_ADC_ISR = 0xe; diff --git a/chip/stm32/adc-stm32f3.c b/chip/stm32/adc-stm32f3.c index fb3e4604a8..605bb14b69 100644 --- a/chip/stm32/adc-stm32f3.c +++ b/chip/stm32/adc-stm32f3.c @@ -1,10 +1,9 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" #include "clock.h" #include "common.h" #include "console.h" @@ -17,9 +16,9 @@ #define ADC_SINGLE_READ_TIMEOUT 3000 /* 3 ms */ -#define SMPR1_EXPAND(v) ((v) | ((v) << 3) | ((v) << 6) | ((v) << 9) | \ - ((v) << 12) | ((v) << 15) | ((v) << 18) | \ - ((v) << 21)) +#define SMPR1_EXPAND(v) \ + ((v) | ((v) << 3) | ((v) << 6) | ((v) << 9) | ((v) << 12) | \ + ((v) << 15) | ((v) << 18) | ((v) << 21)) #define SMPR2_EXPAND(v) (SMPR1_EXPAND(v) | ((v) << 24) | ((v) << 27)) /* Default ADC sample time = 13.5 cycles */ @@ -216,8 +215,9 @@ int adc_read_channel(enum adc_channel ch) adc_enable_watchdog_no_lock(); mutex_unlock(&adc_lock); - return (value == ADC_READ_ERROR) ? ADC_READ_ERROR : - value * adc->factor_mul / adc->factor_div + adc->shift; + return (value == ADC_READ_ERROR) ? + ADC_READ_ERROR : + value * adc->factor_mul / adc->factor_div + adc->shift; } static void adc_init(void) diff --git a/chip/stm32/adc-stm32f4.c b/chip/stm32/adc-stm32f4.c deleted file mode 120000 index 5e375b9dbf..0000000000 --- a/chip/stm32/adc-stm32f4.c +++ /dev/null @@ -1 +0,0 @@ -adc-stm32f3.c \ No newline at end of file diff --git a/chip/stm32/adc-stm32f4.c b/chip/stm32/adc-stm32f4.c new file mode 100644 index 0000000000..605bb14b69 --- /dev/null +++ b/chip/stm32/adc-stm32f4.c @@ -0,0 +1,260 @@ +/* Copyright 2012 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" +#include "clock.h" +#include "common.h" +#include "console.h" +#include "dma.h" +#include "hooks.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#define ADC_SINGLE_READ_TIMEOUT 3000 /* 3 ms */ + +#define SMPR1_EXPAND(v) \ + ((v) | ((v) << 3) | ((v) << 6) | ((v) << 9) | ((v) << 12) | \ + ((v) << 15) | ((v) << 18) | ((v) << 21)) +#define SMPR2_EXPAND(v) (SMPR1_EXPAND(v) | ((v) << 24) | ((v) << 27)) + +/* Default ADC sample time = 13.5 cycles */ +#ifndef CONFIG_ADC_SAMPLE_TIME +#define CONFIG_ADC_SAMPLE_TIME 2 +#endif + +struct mutex adc_lock; + +static int watchdog_ain_id; + +static inline void adc_set_channel(int sample_id, int channel) +{ + uint32_t mask, val; + volatile uint32_t *sqr_reg; + + if (sample_id < 6) { + mask = 0x1f << (sample_id * 5); + val = channel << (sample_id * 5); + sqr_reg = &STM32_ADC_SQR3; + } else if (sample_id < 12) { + mask = 0x1f << ((sample_id - 6) * 5); + val = channel << ((sample_id - 6) * 5); + sqr_reg = &STM32_ADC_SQR2; + } else { + mask = 0x1f << ((sample_id - 12) * 5); + val = channel << ((sample_id - 12) * 5); + sqr_reg = &STM32_ADC_SQR1; + } + + *sqr_reg = (*sqr_reg & ~mask) | val; +} + +static void adc_configure(int ain_id) +{ + /* Set ADC channel */ + adc_set_channel(0, ain_id); + + /* Disable DMA */ + STM32_ADC_CR2 &= ~BIT(8); + + /* Disable scan mode */ + STM32_ADC_CR1 &= ~BIT(8); +} + +static void __attribute__((unused)) adc_configure_all(void) +{ + int i; + + /* Set ADC channels */ + STM32_ADC_SQR1 = (ADC_CH_COUNT - 1) << 20; + for (i = 0; i < ADC_CH_COUNT; ++i) + adc_set_channel(i, adc_channels[i].channel); + + /* Enable DMA */ + STM32_ADC_CR2 |= BIT(8); + + /* Enable scan mode */ + STM32_ADC_CR1 |= BIT(8); +} + +static inline int adc_powered(void) +{ + return STM32_ADC_CR2 & BIT(0); +} + +static inline int adc_conversion_ended(void) +{ + return STM32_ADC_SR & BIT(1); +} + +static int adc_watchdog_enabled(void) +{ + return STM32_ADC_CR1 & BIT(23); +} + +static int adc_enable_watchdog_no_lock(void) +{ + /* Fail if watchdog already enabled */ + if (adc_watchdog_enabled()) + return EC_ERROR_UNKNOWN; + + /* Set channel */ + STM32_ADC_SQR3 = watchdog_ain_id; + STM32_ADC_SQR1 = 0; + STM32_ADC_CR1 = (STM32_ADC_CR1 & ~0x1f) | watchdog_ain_id; + + /* Clear interrupt bit */ + STM32_ADC_SR &= ~0x1; + + /* AWDSGL=1, SCAN=1, AWDIE=1, AWDEN=1 */ + STM32_ADC_CR1 |= BIT(9) | BIT(8) | BIT(6) | BIT(23); + + /* Disable DMA */ + STM32_ADC_CR2 &= ~BIT(8); + + /* CONT=1 */ + STM32_ADC_CR2 |= BIT(1); + + /* Start conversion */ + STM32_ADC_CR2 |= BIT(0); + + return EC_SUCCESS; +} + +int adc_enable_watchdog(int ain_id, int high, int low) +{ + int ret; + + if (!adc_powered()) + return EC_ERROR_UNKNOWN; + + mutex_lock(&adc_lock); + + watchdog_ain_id = ain_id; + + /* Set thresholds */ + STM32_ADC_HTR = high & 0xfff; + STM32_ADC_LTR = low & 0xfff; + + ret = adc_enable_watchdog_no_lock(); + mutex_unlock(&adc_lock); + return ret; +} + +static int adc_disable_watchdog_no_lock(void) +{ + /* Fail if watchdog not running */ + if (!adc_watchdog_enabled()) + return EC_ERROR_UNKNOWN; + + /* AWDEN=0, AWDIE=0 */ + STM32_ADC_CR1 &= ~BIT(23) & ~BIT(6); + + /* CONT=0 */ + STM32_ADC_CR2 &= ~BIT(1); + + return EC_SUCCESS; +} + +int adc_disable_watchdog(void) +{ + int ret; + + if (!adc_powered()) + return EC_ERROR_UNKNOWN; + + mutex_lock(&adc_lock); + ret = adc_disable_watchdog_no_lock(); + mutex_unlock(&adc_lock); + return ret; +} + +int adc_read_channel(enum adc_channel ch) +{ + const struct adc_t *adc = adc_channels + ch; + int value; + int restore_watchdog = 0; + timestamp_t deadline; + + if (!adc_powered()) + return EC_ERROR_UNKNOWN; + + mutex_lock(&adc_lock); + + if (adc_watchdog_enabled()) { + restore_watchdog = 1; + adc_disable_watchdog_no_lock(); + } + + adc_configure(adc->channel); + + /* Clear EOC bit */ + STM32_ADC_SR &= ~BIT(1); + + /* Start conversion (Note: For now only confirmed on F4) */ +#if defined(CHIP_FAMILY_STM32F4) + STM32_ADC_CR2 |= STM32_ADC_CR2_ADON | STM32_ADC_CR2_SWSTART; +#else + STM32_ADC_CR2 |= STM32_ADC_CR2_ADON; +#endif + + /* Wait for EOC bit set */ + deadline.val = get_time().val + ADC_SINGLE_READ_TIMEOUT; + value = ADC_READ_ERROR; + do { + if (adc_conversion_ended()) { + value = STM32_ADC_DR & ADC_READ_MAX; + break; + } + } while (!timestamp_expired(deadline, NULL)); + + if (restore_watchdog) + adc_enable_watchdog_no_lock(); + + mutex_unlock(&adc_lock); + return (value == ADC_READ_ERROR) ? + ADC_READ_ERROR : + value * adc->factor_mul / adc->factor_div + adc->shift; +} + +static void adc_init(void) +{ + /* + * Enable ADC clock. + * APB2 clock is 16MHz. ADC clock prescaler is /2. + * So the ADC clock is 8MHz. + */ + clock_enable_module(MODULE_ADC, 1); + + /* + * ADC clock is divided with respect to AHB, so no delay needed + * here. If ADC clock is the same as AHB, a read on ADC + * register is needed here. + */ + + if (!adc_powered()) { + /* Power on ADC module */ + STM32_ADC_CR2 |= STM32_ADC_CR2_ADON; + + /* Reset calibration */ + STM32_ADC_CR2 |= STM32_ADC_CR2_RSTCAL; + while (STM32_ADC_CR2 & STM32_ADC_CR2_RSTCAL) + ; + + /* A/D Calibrate */ + STM32_ADC_CR2 |= STM32_ADC_CR2_CAL; + while (STM32_ADC_CR2 & STM32_ADC_CR2_CAL) + ; + } + + /* Set right alignment */ + STM32_ADC_CR2 &= ~STM32_ADC_CR2_ALIGN; + + /* Set sample time of all channels */ + STM32_ADC_SMPR1 = SMPR1_EXPAND(CONFIG_ADC_SAMPLE_TIME); + STM32_ADC_SMPR2 = SMPR2_EXPAND(CONFIG_ADC_SAMPLE_TIME); +} +DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_INIT_ADC); diff --git a/chip/stm32/adc-stm32l.c b/chip/stm32/adc-stm32l.c index 199b64c81f..06b16224f7 100644 --- a/chip/stm32/adc-stm32l.c +++ b/chip/stm32/adc-stm32l.c @@ -1,13 +1,12 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" -#include "adc_chip.h" +#include "clock.h" #include "common.h" #include "console.h" -#include "clock.h" #include "dma.h" #include "hooks.h" #include "registers.h" @@ -92,7 +91,7 @@ static void adc_init(void) if (!adc_powered()) /* Power on ADC module */ - STM32_ADC_CR2 |= BIT(0); /* ADON */ + STM32_ADC_CR2 |= BIT(0); /* ADON */ /* Set right alignment */ STM32_ADC_CR2 &= ~BIT(11); @@ -166,6 +165,7 @@ int adc_read_channel(enum adc_channel ch) adc_release(); mutex_unlock(&adc_lock); - return (value == ADC_READ_ERROR) ? ADC_READ_ERROR : - value * adc->factor_mul / adc->factor_div + adc->shift; + return (value == ADC_READ_ERROR) ? + ADC_READ_ERROR : + value * adc->factor_mul / adc->factor_div + adc->shift; } diff --git a/chip/stm32/adc-stm32l4.c b/chip/stm32/adc-stm32l4.c new file mode 100644 index 0000000000..c81978d6ce --- /dev/null +++ b/chip/stm32/adc-stm32l4.c @@ -0,0 +1,245 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* ADC drivers for STM32L4xx as well as STM32L5xx. */ + +#include "adc.h" +#include "clock.h" +#include "common.h" +#include "console.h" +#include "dma.h" +#include "hooks.h" +#include "hwtimer.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +struct mutex adc_lock; + +struct adc_profile_t { + /* Register values. */ + uint32_t cfgr1_reg; + uint32_t cfgr2_reg; + uint32_t smpr_reg; /* Default Sampling Rate */ + uint32_t ier_reg; + /* DMA config. */ + const struct dma_option *dma_option; + /* Size of DMA buffer, in units of ADC_CH_COUNT. */ + int dma_buffer_size; +}; + +#ifdef CONFIG_ADC_PROFILE_SINGLE +#ifndef CONFIG_ADC_SAMPLE_TIME +#define CONFIG_ADC_SAMPLE_TIME STM32_ADC_SMPR_12_5_CY +#endif +#endif + +#define ADC_CALIBRATION_TIMEOUT_US 100000U +#define ADC_ENABLE_TIMEOUT_US 200000U +#define ADC_CONVERSION_TIMEOUT_US 200000U + +static uint8_t adc1_initialized; + +#ifdef CONFIG_ADC_PROFILE_FAST_CONTINUOUS +#error "Continuous ADC sampling not implemented for STM32L4/5" + +#ifndef CONFIG_ADC_SAMPLE_TIME +#define CONFIG_ADC_SAMPLE_TIME STM32_ADC_SMPR_1_5_CY +#endif + +static const struct dma_option dma_continuous = { + STM32_DMAC_ADC, + (void *)&STM32_ADC_DR, + STM32_DMA_CCR_MSIZE_32_BIT | STM32_DMA_CCR_PSIZE_32_BIT | + STM32_DMA_CCR_CIRC, +}; + +static const struct adc_profile_t profile = { + /* Sample all channels continuously using DMA */ + .cfgr1_reg = STM32_ADC_CFGR1_OVRMOD | STM32_ADC_CFGR1_CONT | + STM32_ADC_CFGR1_DMACFG, + .cfgr2_reg = 0, + .smpr_reg = CONFIG_ADC_SAMPLE_TIME, + /* Fire interrupt at end of sequence. */ + .ier_reg = STM32_ADC_IER_EOSEQIE, + .dma_option = &dma_continuous, + /* Double-buffer our samples. */ + .dma_buffer_size = 2, +}; +#endif + +static void adc_init(void) +{ + /* + * If clock is already enabled, and ADC module is enabled + * then this is a warm reboot and ADC is already initialized. + */ + + if (STM32_RCC_AHB2ENR & STM32_RCC_AHB2ENR_ADCEN && + (STM32_ADC1_CR & STM32_ADC1_CR_ADEN)) + return; + + /* Enable ADC clock */ + clock_enable_module(MODULE_ADC, 1); + + /* set ADC clock to 20MHz */ + STM32_ADC1_CCR &= ~0x003C0000; + STM32_ADC1_CCR |= 0x00080000; + + STM32_RCC_AHB2ENR |= STM32_RCC_HB2_GPIOA; + STM32_RCC_AHB2ENR |= STM32_RCC_HB2_GPIOB; + + /* Set ADC data resolution */ + STM32_ADC1_CFGR &= ~STM32_ADC1_CFGR_CONT; + /* Set ADC conversion data alignment */ + STM32_ADC1_CFGR &= ~STM32_ADC1_CFGR_ALIGN; + /* Set ADC delayed conversion mode */ + STM32_ADC1_CFGR &= ~STM32_ADC1_CFGR_AUTDLY; +} + +BUILD_ASSERT(CONFIG_ADC_SAMPLE_TIME > 0 && CONFIG_ADC_SAMPLE_TIME <= 8); + +static void adc_configure_channel(int ain_id, enum stm32_adc_smpr sample_time) +{ + /* Select Sampling time for channel to convert */ + if (sample_time == STM32_ADC_SMPR_DEFAULT) + sample_time = CONFIG_ADC_SAMPLE_TIME; + + if (ain_id <= 10) { + STM32_ADC1_SMPR1 &= ~(7 << ((ain_id - 1) * 3)); + STM32_ADC1_SMPR1 |= ((sample_time - 1) << ((ain_id - 1) * 3)); + } else { + STM32_ADC1_SMPR2 &= ~(7 << ((ain_id - 11) * 3)); + STM32_ADC1_SMPR2 |= ((sample_time - 1) << ((ain_id - 11) * 3)); + } +} + +static void adc_select_channel(int ain_id) +{ + /* Setup an "injected sequence" consisting of only this one channel. */ + STM32_ADC1_JSQR = ain_id << 8; +} + +static void stm32_adc1_isr_clear(uint32_t bitmask) +{ + /* Write 1 to clear */ + STM32_ADC1_ISR = bitmask; +} + +int adc_read_channel(enum adc_channel ch) +{ + const struct adc_t *adc = adc_channels + ch; + + int value = 0; + uint32_t wait_loop_index; + + mutex_lock(&adc_lock); + + if (adc1_initialized == 0) { + adc_init(); + + /* Configure Channel N */ + for (uint8_t i = 0; i < ADC_CH_COUNT; i++) { + const struct adc_t *adc = adc_channels + i; + + adc_configure_channel(adc->channel, adc->sample_time); + } + + /* Disable DMA */ + STM32_ADC1_CFGR &= ~STM32_ADC1_CFGR_DMAEN; + + if ((STM32_ADC1_CR & STM32_ADC1_CR_ADEN) != + STM32_ADC1_CR_ADEN) { + /* Disable ADC deep power down (enabled by default after + * reset state) + */ + STM32_ADC1_CR &= ~STM32_ADC1_CR_DEEPPWD; + /* Enable ADC internal voltage regulator */ + STM32_ADC1_CR |= STM32_ADC1_CR_ADVREGEN; + } + + /* + * Delay for ADC internal voltage regulator stabilization. + * Compute number of CPU cycles to wait for, from delay in us. + * + * Note: Variable divided by 2 to compensate partially + * CPU processing cycles (depends on compilation optimization). + * + * Note: If system core clock frequency is below 200kHz, wait + * time is only a few CPU processing cycles. + */ + wait_loop_index = ((20 * (80000000 / (100000 * 2))) / 10); + while (wait_loop_index-- != 0) + ; + + /* Run ADC self calibration */ + STM32_ADC1_CR |= STM32_ADC1_CR_ADCAL; + + /* wait for the end of calibration */ + wait_loop_index = ((ADC_CALIBRATION_TIMEOUT_US * + (CPU_CLOCK / (100000 * 2))) / + 10); + while (STM32_ADC1_CR & STM32_ADC1_CR_ADCAL) { + if (wait_loop_index-- == 0) + break; + } + + /* Enable ADC */ + stm32_adc1_isr_clear(STM32_ADC1_ISR_ADRDY); + STM32_ADC1_CR |= STM32_ADC1_CR_ADEN; + wait_loop_index = + ((ADC_ENABLE_TIMEOUT_US * (CPU_CLOCK / (100000 * 2))) / + 10); + while (!(STM32_ADC1_ISR & STM32_ADC1_ISR_ADRDY)) { + wait_loop_index--; + if (wait_loop_index == 0) + break; + } + stm32_adc1_isr_clear(STM32_ADC1_ISR_ADRDY); + + adc1_initialized = 1; + } + + /* Configure Injected Channel N */ + adc_select_channel(adc->channel); + + /* Start injected conversion */ + STM32_ADC1_CR |= BIT(3); /* JADSTART */ + + /* Wait for end of injected conversion */ + wait_loop_index = + ((ADC_CONVERSION_TIMEOUT_US * (CPU_CLOCK / (100000 * 2))) / 10); + while (!(STM32_ADC1_ISR & BIT(6))) { + if (wait_loop_index-- == 0) + break; + } + + /* Clear JEOS bit */ + stm32_adc1_isr_clear(BIT(6)); + + /* read converted value */ + value = STM32_ADC1_JDR1; + + mutex_unlock(&adc_lock); + + return value * adc->factor_mul / adc->factor_div + adc->shift; +} + +void adc_disable(void) +{ + /* Disable ADC */ + /* Do not Set ADDIS when ADC is disabled */ + adc1_initialized = 0; + + if (STM32_ADC1_CR & STM32_ADC1_CR_ADEN) + STM32_ADC1_CR |= STM32_ADC1_CR_ADDIS; + + /* + * Note that the ADC is not in OFF state immediately. + * Once the ADC is effectively put into OFF state, + * STM32_ADC_CR_ADDIS bit will be cleared by hardware. + */ +} diff --git a/chip/stm32/adc-stm32l5.c b/chip/stm32/adc-stm32l5.c new file mode 100644 index 0000000000..94a85fb70b --- /dev/null +++ b/chip/stm32/adc-stm32l5.c @@ -0,0 +1,6 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc-stm32l4.c" diff --git a/chip/stm32/adc_chip.h b/chip/stm32/adc_chip.h index 413653e4d7..2677f1d9cc 100644 --- a/chip/stm32/adc_chip.h +++ b/chip/stm32/adc_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,8 +8,20 @@ #ifndef __CROS_EC_ADC_CHIP_H #define __CROS_EC_ADC_CHIP_H -#include "stdint.h" - +#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) +enum stm32_adc_smpr { + STM32_ADC_SMPR_DEFAULT = 0, + STM32_ADC_SMPR_2_5_CY, + STM32_ADC_SMPR_6_5_CY, + STM32_ADC_SMPR_12_5_CY, + STM32_ADC_SMPR_24_5_CY, + STM32_ADC_SMPR_47_5_CY, + STM32_ADC_SMPR_92_5_CY, + STM32_ADC_SMPR_247_5_CY, + STM32_ADC_SMPR_640_5_CY, + STM32_ADC_SMPR_COUNT, +}; +#else enum stm32_adc_smpr { STM32_ADC_SMPR_DEFAULT = 0, STM32_ADC_SMPR_1_5_CY, @@ -22,6 +34,7 @@ enum stm32_adc_smpr { STM32_ADC_SMPR_239_5_CY, STM32_ADC_SMPR_COUNT, }; +#endif /* Data structure to define ADC channels. */ struct adc_t { @@ -30,18 +43,13 @@ struct adc_t { int factor_div; int shift; int channel; -#ifdef CHIP_FAMILY_STM32F0 - enum stm32_adc_smpr sample_rate; /* Sampling Rate of the channel */ + +#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32L4) || \ + defined(CHIP_FAMILY_STM32L5) + enum stm32_adc_smpr sample_time; /* Sampling Time of the channel */ #endif }; -/* - * Boards must provide this list of ADC channel definitions. This must match - * the enum adc_channel list provided by the board. Also, for STM32F0, this - * must be ordered by AIN ID. - */ -extern const struct adc_t adc_channels[]; - /* Disable ADC module when we don't need it anymore. */ void adc_disable(void); diff --git a/chip/stm32/bkpdata.c b/chip/stm32/bkpdata.c index 2b26ace7ea..ef5729d118 100644 --- a/chip/stm32/bkpdata.c +++ b/chip/stm32/bkpdata.c @@ -1,15 +1,15 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include - #include "bkpdata.h" #include "registers.h" #include "system.h" /* enum system_bbram_idx */ #include "task.h" +#include + uint16_t bkpdata_read(enum bkpdata_index index) { if (index < 0 || index >= STM32_BKP_ENTRIES) @@ -24,6 +24,7 @@ uint16_t bkpdata_read(enum bkpdata_index index) int bkpdata_write(enum bkpdata_index index, uint16_t value) { static struct mutex bkpdata_write_mutex; + int use_mutex = !in_interrupt_context(); if (index < 0 || index >= STM32_BKP_ENTRIES) return EC_ERROR_INVAL; @@ -32,7 +33,8 @@ int bkpdata_write(enum bkpdata_index index, uint16_t value) * Two entries share a single 32-bit register, lock mutex to prevent * read/mask/write races. */ - mutex_lock(&bkpdata_write_mutex); + if (use_mutex) + mutex_lock(&bkpdata_write_mutex); if (index & 1) { uint32_t val = STM32_BKP_DATA(index >> 1); val = (val & 0x0000FFFF) | (value << 16); @@ -42,7 +44,8 @@ int bkpdata_write(enum bkpdata_index index, uint16_t value) val = (val & 0xFFFF0000) | value; STM32_BKP_DATA(index >> 1) = val; } - mutex_unlock(&bkpdata_write_mutex); + if (use_mutex) + mutex_unlock(&bkpdata_write_mutex); return EC_SUCCESS; } @@ -51,14 +54,6 @@ int bkpdata_index_lookup(enum system_bbram_idx idx, int *msb) { *msb = 0; -#ifdef CONFIG_HOSTCMD_VBNV_CONTEXT - if (idx >= SYSTEM_BBRAM_IDX_VBNVBLOCK0 && - idx <= SYSTEM_BBRAM_IDX_VBNVBLOCK15) { - *msb = (idx - SYSTEM_BBRAM_IDX_VBNVBLOCK0) % 2; - return BKPDATA_INDEX_VBNV_CONTEXT0 + - (idx - SYSTEM_BBRAM_IDX_VBNVBLOCK0) / 2; - } -#endif #ifdef CONFIG_USB_PD_DUAL_ROLE if (idx == SYSTEM_BBRAM_IDX_PD0) return BKPDATA_INDEX_PD0; @@ -70,24 +65,21 @@ int bkpdata_index_lookup(enum system_bbram_idx idx, int *msb) return -1; } -uint32_t bkpdata_read_reset_flags() +uint32_t bkpdata_read_reset_flags(void) { uint32_t flags = bkpdata_read(BKPDATA_INDEX_SAVED_RESET_FLAGS); -#ifdef CONFIG_STM32_RESET_FLAGS_EXTENDED + +#ifdef CONFIG_STM32_EXTENDED_RESET_FLAGS flags |= bkpdata_read(BKPDATA_INDEX_SAVED_RESET_FLAGS_2) << 16; #endif + return flags; } -__overridable -void bkpdata_write_reset_flags(uint32_t save_flags) +__overridable void bkpdata_write_reset_flags(uint32_t save_flags) { -#ifdef CONFIG_STM32_RESET_FLAGS_EXTENDED bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS, save_flags & 0xffff); +#ifdef CONFIG_STM32_EXTENDED_RESET_FLAGS bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS_2, save_flags >> 16); -#else - /* Reset flags are 32-bits, but BBRAM entry is only 16 bits. */ - ASSERT(!(save_flags >> 16)); - bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS, save_flags); #endif } diff --git a/chip/stm32/bkpdata.h b/chip/stm32/bkpdata.h index 07f20aed49..5b656b16dc 100644 --- a/chip/stm32/bkpdata.h +++ b/chip/stm32/bkpdata.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,45 +16,28 @@ #define STM32_BKP_ENTRIES (STM32_BKP_BYTES / 2) /* - * Use 32-bit for reset flags, if we have space for it: - * - 2 indexes are used unconditionally (SCRATCHPAD and SAVED_RESET_FLAGS) - * - VBNV_CONTEXT requires 8 indexes, so a total of 10 (which is the total - * number of entries on some STM32 variants). - * - Other config options are not a problem (they only take a few entries) - * - * Given this, we can only add an extra entry for the top 16-bit of reset flags - * if VBNV_CONTEXT is not enabled, or if we have more than 10 entries. + * Add new entries at the end of the enum. Otherwise you will break RO/RW + * compatibility. */ -#if !defined(CONFIG_HOSTCMD_VBNV_CONTEXT) || STM32_BKP_ENTRIES > 10 -#define CONFIG_STM32_RESET_FLAGS_EXTENDED -#endif - enum bkpdata_index { - BKPDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */ - BKPDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */ -#ifdef CONFIG_STM32_RESET_FLAGS_EXTENDED - BKPDATA_INDEX_SAVED_RESET_FLAGS_2, /* Saved reset flags (cont) */ + BKPDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */ + BKPDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */ +#ifdef CONFIG_STM32_EXTENDED_RESET_FLAGS + BKPDATA_INDEX_SAVED_RESET_FLAGS_2, /* Saved reset flags (cont) */ #endif -#ifdef CONFIG_HOSTCMD_VBNV_CONTEXT - BKPDATA_INDEX_VBNV_CONTEXT0, - BKPDATA_INDEX_VBNV_CONTEXT1, - BKPDATA_INDEX_VBNV_CONTEXT2, - BKPDATA_INDEX_VBNV_CONTEXT3, - BKPDATA_INDEX_VBNV_CONTEXT4, - BKPDATA_INDEX_VBNV_CONTEXT5, - BKPDATA_INDEX_VBNV_CONTEXT6, - BKPDATA_INDEX_VBNV_CONTEXT7, -#endif -#ifdef CONFIG_SOFTWARE_PANIC - BKPDATA_INDEX_SAVED_PANIC_REASON, /* Saved panic reason */ - BKPDATA_INDEX_SAVED_PANIC_INFO, /* Saved panic data */ + BKPDATA_INDEX_SAVED_PANIC_REASON, /* Saved panic reason */ + BKPDATA_INDEX_SAVED_PANIC_INFO, /* Saved panic data */ BKPDATA_INDEX_SAVED_PANIC_EXCEPTION, /* Saved panic exception code */ -#endif #ifdef CONFIG_USB_PD_DUAL_ROLE - BKPDATA_INDEX_PD0, /* USB-PD saved port0 state */ - BKPDATA_INDEX_PD1, /* USB-PD saved port1 state */ - BKPDATA_INDEX_PD2, /* USB-PD saved port2 state */ + BKPDATA_INDEX_PD0, /* USB-PD saved port0 state */ + BKPDATA_INDEX_PD1, /* USB-PD saved port1 state */ + BKPDATA_INDEX_PD2, /* USB-PD saved port2 state */ #endif + /** + * Saving the panic flags in case that AP thinks the panic is new + * after a hard reset. + */ + BKPDATA_INDEX_SAVED_PANIC_FLAGS, /* Saved panic flags */ BKPDATA_COUNT }; BUILD_ASSERT(STM32_BKP_ENTRIES >= BKPDATA_COUNT); diff --git a/chip/stm32/build.mk b/chip/stm32/build.mk index f2d5720961..41ceaeb12c 100644 --- a/chip/stm32/build.mk +++ b/chip/stm32/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. +# Copyright 2013 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -9,45 +9,44 @@ ifeq ($(CHIP_FAMILY),stm32f0) # STM32F0xx sub-family has a Cortex-M0 ARM core CORE:=cortex-m0 -# Force ARMv6-M ISA used by the Cortex-M0 -# For historical reasons gcc calls it armv6s-m: ARM used to have ARMv6-M -# without "svc" instruction, but that was short-lived. ARMv6S-M was the option -# with "svc". GCC kept that naming scheme even though the distinction is long -# gone. -CFLAGS_CPU+=-march=armv6s-m -mcpu=cortex-m0 +CFLAGS_CPU+=-mcpu=cortex-m0 else ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),stm32f3 stm32l4 stm32f4 \ stm32g4)) # STM32F3xx and STM32L4xx sub-family has a Cortex-M4 ARM core CORE:=cortex-m # Allow the full Cortex-M4 instruction set -CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4 +CFLAGS_CPU+=-mcpu=cortex-m4 else ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),stm32h7)) # STM32FH7xx family has a Cortex-M7 ARM core CORE:=cortex-m -# Allow the full Cortex-M4 instruction set (identical to M7) -CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4 +# Allow the full Cortex-M7 instruction set. +CFLAGS_CPU+=-mcpu=cortex-m7 +else ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),stm32l5)) +# STM32FL5xx family has a Cortex-M33 ARM core +CORE:=cortex-m +# Allow the full Cortex-M33 instruction set +CFLAGS_CPU+=-mcpu=cortex-m33 else # other STM32 SoCs have a Cortex-M3 ARM core CORE:=cortex-m # Force Cortex-M3 subset of instructions -CFLAGS_CPU+=-march=armv7-m -mcpu=cortex-m3 +CFLAGS_CPU+=-mcpu=cortex-m3 endif -# Select between 16-bit and 32-bit timer for clock source -TIMER_TYPE=$(if $(CONFIG_STM_HWTIMER32),32,) DMA_TYPE=$(if $(CHIP_FAMILY_STM32F4)$(CHIP_FAMILY_STM32H7),-stm32f4,) SPI_TYPE=$(if $(CHIP_FAMILY_STM32H7),-stm32h7,) -chip-$(CONFIG_DMA)+=dma$(DMA_TYPE).o +chip-$(CONFIG_DMA_CROS)+=dma$(DMA_TYPE).o chip-$(CONFIG_COMMON_RUNTIME)+=bkpdata.o system.o chip-y+=clock-$(CHIP_FAMILY).o ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),stm32f0 stm32f3 stm32f4)) chip-y+=clock-f.o endif +chip-$(CONFIG_FPU)+=fpu.o chip-$(CONFIG_SPI)+=spi.o -chip-$(CONFIG_SPI_MASTER)+=spi_master$(SPI_TYPE).o +chip-$(CONFIG_SPI_CONTROLLER)+=spi_controller$(SPI_TYPE).o chip-$(CONFIG_COMMON_GPIO)+=gpio.o gpio-$(CHIP_FAMILY).o -chip-$(CONFIG_COMMON_TIMER)+=hwtimer$(TIMER_TYPE).o +chip-$(CONFIG_COMMON_TIMER)+=hwtimer32.o chip-$(CONFIG_I2C)+=i2c-$(CHIP_FAMILY).o chip-$(CONFIG_ITE_FLASH_SUPPORT)+=i2c_ite_flash_support.o chip-$(CONFIG_STREAM_USART)+=usart.o usart-$(CHIP_FAMILY).o @@ -56,15 +55,15 @@ chip-$(CONFIG_STREAM_USART)+=usart_tx_interrupt.o chip-$(CONFIG_STREAM_USART)+=usart_rx_dma.o usart_tx_dma.o chip-$(CONFIG_USART_HOST_COMMAND)+=usart_host_command.o chip-$(CONFIG_CMD_USART_INFO)+=usart_info_command.o -chip-$(HAS_TASK_CONSOLE)+=host_command_common.o +chip-$(CONFIG_FINGERPRINT_MCU)+=host_command_common.o chip-$(CONFIG_WATCHDOG)+=watchdog.o chip-$(HAS_TASK_CONSOLE)+=uart.o -ifndef CONFIG_KEYBOARD_NOT_RAW +ifndef CONFIG_KEYBOARD_DISCRETE chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o endif chip-$(HAS_TASK_POWERLED)+=power_led.o -ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),stm32g4 stm32l4)) -# STM32G4 and STM32L4 use the same flash IP block +ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),stm32g4 stm32l4 stm32l5)) +# STM32G4, STM32L4 and STM32L5 use the same flash IP block chip-y+=flash-stm32g4-l4.o else chip-$(CONFIG_FLASH_PHYSICAL)+=flash-$(CHIP_FAMILY).o @@ -75,6 +74,9 @@ chip-$(CHIP_FAMILY_STM32F3)+=flash-f.o chip-$(CHIP_FAMILY_STM32F4)+=flash-f.o endif chip-$(CONFIG_ADC)+=adc-$(CHIP_FAMILY).o +chip-$(CONFIG_DFU_BOOTMANAGER_MAIN)+=dfu_bootmanager_main.o +chip-$(CONFIG_DFU_BOOTMANAGER_SHARED)+=dfu_bootmanager_shared.o +chip-$(CONFIG_DFU_RUNTIME)+=usb_dfu_runtime.o chip-$(CONFIG_STM32_CHARGER_DETECT)+=charger_detect.o chip-$(CONFIG_DEBUG_PRINTF)+=debug_printf.o chip-$(CONFIG_OTP)+=otp-$(CHIP_FAMILY).o diff --git a/chip/stm32/charger_detect.c b/chip/stm32/charger_detect.c index b32b9f3ac0..c404fc827a 100644 --- a/chip/stm32/charger_detect.c +++ b/chip/stm32/charger_detect.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -33,7 +33,6 @@ static uint16_t detect_type(uint16_t det_type) return STM32_USB_BCDR; } - int charger_detect_get_device_type(void) { uint16_t pdet_result; diff --git a/chip/stm32/clock-f.c b/chip/stm32/clock-f.c index 0be765476d..0aad58ab00 100644 --- a/chip/stm32/clock-f.c +++ b/chip/stm32/clock-f.c @@ -1,13 +1,14 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Clocks and power management settings */ +#include "builtin/assert.h" #include "chipset.h" -#include "clock.h" #include "clock-f.h" +#include "clock.h" #include "common.h" #include "console.h" #include "cpu.h" @@ -23,7 +24,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) /* Convert decimal to BCD */ static uint8_t u8_to_bcd(uint8_t val) @@ -41,8 +42,8 @@ static uint32_t rtc_tr_to_sec(uint32_t rtc_tr) uint32_t sec; /* convert the hours field */ - sec = (((rtc_tr & 0x300000) >> 20) * 10 + - ((rtc_tr & 0xf0000) >> 16)) * 3600; + sec = (((rtc_tr & 0x300000) >> 20) * 10 + ((rtc_tr & 0xf0000) >> 16)) * + 3600; /* convert the minutes field */ sec += (((rtc_tr & 0x7000) >> 12) * 10 + ((rtc_tr & 0xf00) >> 8)) * 60; /* convert the seconds field */ @@ -122,10 +123,9 @@ static uint32_t rtc_dr_to_sec(uint32_t rtc_dr) struct calendar_date time; uint32_t sec; - time.year = (((rtc_dr & 0xf00000) >> 20) * 10 + - ((rtc_dr & 0xf0000) >> 16)); - time.month = (((rtc_dr & 0x1000) >> 12) * 10 + - ((rtc_dr & 0xf00) >> 8)); + time.year = + (((rtc_dr & 0xf00000) >> 20) * 10 + ((rtc_dr & 0xf0000) >> 16)); + time.month = (((rtc_dr & 0x1000) >> 12) * 10 + ((rtc_dr & 0xf00) >> 8)); time.day = ((rtc_dr & 0x30) >> 4) * 10 + (rtc_dr & 0xf); sec = date_to_sec(time); @@ -258,8 +258,8 @@ void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us, * If the caller doesn't specify subsecond delay (e.g. host command), * just align the alarm time to second. */ - STM32_RTC_ALRMASSR = delay_us ? - (us_to_rtcss(alarm_us) | 0x0f000000) : 0; + STM32_RTC_ALRMASSR = delay_us ? (us_to_rtcss(alarm_us) | 0x0f000000) : + 0; #ifdef CONFIG_HOSTCMD_RTC /* @@ -321,8 +321,7 @@ static void set_rtc_host_event(void) DECLARE_DEFERRED(set_rtc_host_event); #endif -test_mockable_static -void __rtc_alarm_irq(void) +test_mockable void rtc_alarm_irq(void) { struct rtc_time_reg rtc; reset_rtc_alarm(&rtc); @@ -335,10 +334,14 @@ void __rtc_alarm_irq(void) } #endif } + +static void __rtc_alarm_irq(void) +{ + rtc_alarm_irq(); +} DECLARE_IRQ(STM32_IRQ_RTC_ALARM, __rtc_alarm_irq, 1); -__attribute__((weak)) -int clock_get_timer_freq(void) +__attribute__((weak)) int clock_get_timer_freq(void) { return clock_get_freq(); } @@ -394,7 +397,7 @@ void print_system_rtc(enum console_channel ch) } #ifdef CONFIG_CMD_RTC -static int command_system_rtc(int argc, char **argv) +static int command_system_rtc(int argc, const char **argv) { char *e; uint32_t t; @@ -411,12 +414,11 @@ static int command_system_rtc(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(rtc, command_system_rtc, - "[set ]", - "Get/set real-time clock"); +DECLARE_CONSOLE_COMMAND(rtc, command_system_rtc, "[set ]", + "Get/set real-time clock"); #ifdef CONFIG_CMD_RTC_ALARM -static int command_rtc_alarm_test(int argc, char **argv) +static int command_rtc_alarm_test(int argc, const char **argv) { int s = 1, us = 0; struct rtc_time_reg rtc; @@ -428,7 +430,6 @@ static int command_rtc_alarm_test(int argc, char **argv) s = strtoi(argv[1], &e, 10); if (*e) return EC_ERROR_PARAM1; - } if (argc > 2) { us = strtoi(argv[2], &e, 10); @@ -440,8 +441,7 @@ static int command_rtc_alarm_test(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(rtc_alarm, command_rtc_alarm_test, - "[seconds [microseconds]]", - "Test alarm"); + "[seconds [microseconds]]", "Test alarm"); #endif /* CONFIG_CMD_RTC_ALARM */ #endif /* CONFIG_CMD_RTC */ @@ -460,9 +460,8 @@ static enum ec_status system_rtc_get_value(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_VALUE, - system_rtc_get_value, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_VALUE, system_rtc_get_value, + EC_VER_MASK(0)); static enum ec_status system_rtc_set_value(struct host_cmd_handler_args *args) { @@ -471,9 +470,8 @@ static enum ec_status system_rtc_set_value(struct host_cmd_handler_args *args) rtc_set(p->time); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_VALUE, - system_rtc_set_value, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_VALUE, system_rtc_set_value, + EC_VER_MASK(0)); static enum ec_status system_rtc_set_alarm(struct host_cmd_handler_args *args) { @@ -487,9 +485,8 @@ static enum ec_status system_rtc_set_alarm(struct host_cmd_handler_args *args) set_rtc_alarm(p->time, 0, &rtc, 1); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_ALARM, - system_rtc_set_alarm, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_ALARM, system_rtc_set_alarm, + EC_VER_MASK(0)); static enum ec_status system_rtc_get_alarm(struct host_cmd_handler_args *args) { @@ -500,8 +497,7 @@ static enum ec_status system_rtc_get_alarm(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_ALARM, - system_rtc_get_alarm, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_ALARM, system_rtc_get_alarm, + EC_VER_MASK(0)); #endif /* CONFIG_HOSTCMD_RTC */ diff --git a/chip/stm32/clock-f.h b/chip/stm32/clock-f.h index 4662b043cb..5ed302bf78 100644 --- a/chip/stm32/clock-f.h +++ b/chip/stm32/clock-f.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -100,4 +100,4 @@ int is_host_wake_alarm_expired(timestamp_t ts); /* Set RTC wakeup based on the value saved in host_wake_time */ void restore_host_wake_alarm(void); -#endif /* __CROS_EC_CLOCK_F_H */ +#endif /* __CROS_EC_CLOCK_F_H */ diff --git a/chip/stm32/clock-l4.h b/chip/stm32/clock-l4.h new file mode 100644 index 0000000000..975d952b9f --- /dev/null +++ b/chip/stm32/clock-l4.h @@ -0,0 +1,110 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Clocks and power management settings */ + +#ifndef __CROS_EC_CLOCK_L4_H +#define __CROS_EC_CLOCK_L4_H + +#include "chipset.h" +#include "clock.h" +#include "common.h" +#include "console.h" +#include "cpu.h" +#include "hooks.h" +#include "hwtimer.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#define STM32L4_RTC_REQ 1000000 +#define STM32L4_LSI_CLOCK 32000 + +/* Lock and unlock RTC write access */ +static inline void rtc_lock_regs(void) +{ + STM32_RTC_WPR = 0xff; +} +static inline void rtc_unlock_regs(void) +{ + STM32_RTC_WPR = 0xca; + STM32_RTC_WPR = 0x53; +} + +struct rtc_time_reg { + uint32_t rtc_ssr; /* subseconds */ + uint32_t rtc_tr; /* hours, minutes, seconds */ + uint32_t rtc_dr; /* years, months, dates, week days */ +}; + +/* Save the RTC alarm wake time */ +struct wake_time { + timestamp_t ts; + uint32_t rtc_alrmar; /* the value of register STM32_RTC_ALRMAR */ +}; + +/* Convert between RTC regs in BCD and seconds */ +uint32_t rtc_to_sec(const struct rtc_time_reg *rtc); + +/* Convert between seconds and RTC regs */ +void sec_to_rtc(uint32_t sec, struct rtc_time_reg *rtc); + +/* Calculate microseconds from rtc sub-second register. */ +uint32_t rtcss_to_us(uint32_t rtcss); + +/* Calculate rtc sub-second register value from microseconds. */ +uint32_t us_to_rtcss(uint32_t us); + +/* Return sub-10-sec time diff between two rtc readings */ +uint32_t get_rtc_diff(const struct rtc_time_reg *rtc0, + const struct rtc_time_reg *rtc1); + +/* Read RTC values */ +void rtc_read(struct rtc_time_reg *rtc); + +/* Set RTC value */ +void rtc_set(uint32_t sec); + +/* Set RTC wakeup, save alarm wakeup time when save_alarm != 0 */ +void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us, + struct rtc_time_reg *rtc, uint8_t save_alarm); + +/* Clear RTC wakeup */ +void reset_rtc_alarm(struct rtc_time_reg *rtc); + +/* + * Return the remaining seconds before the RTC alarm goes off. + * Sub-seconds are ignored. Returns 0 if alarm is not set. + */ +uint32_t get_rtc_alarm(void); + +/* RTC init */ +void rtc_init(void); + +/* Init clock blocks and functionality */ +void clock_init(void); + +/* Init high speed clock config */ +void config_hispeed_clock(void); + +/* Get timer clock frequency (for STM32 only) */ +int clock_get_timer_freq(void); + +/* + * Return 1 if host_wake_time is nonzero and the saved host_wake_time + * is expired at a given time, ts. + */ +bool is_host_wake_alarm_expired(timestamp_t ts); + +/* Set RTC wakeup based on the value saved in host_wake_time */ +void restore_host_wake_alarm(void); + +#ifdef CONFIG_LOW_POWER_IDLE +void low_power_init(void); +#endif + +#endif /* __CROS_EC_CLOCK_L4_H */ diff --git a/chip/stm32/clock-stm32f0.c b/chip/stm32/clock-stm32f0.c index 8cfbaef111..64b0b45e50 100644 --- a/chip/stm32/clock-stm32f0.c +++ b/chip/stm32/clock-stm32f0.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,8 +6,8 @@ /* Clocks and power management settings */ #include "chipset.h" -#include "clock.h" #include "clock-f.h" +#include "clock.h" #include "common.h" #include "console.h" #include "cpu.h" @@ -22,7 +22,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) /* use 48Mhz USB-synchronized High-speed oscillator */ #define HSI48_CLOCK 48000000 @@ -54,13 +54,13 @@ static int dsleep_recovery_margin_us = 1000000; * we won't miss the host alarm. */ #ifdef CHIP_VARIANT_STM32F373 -#define STOP_MODE_LATENCY 500 /* us */ +#define STOP_MODE_LATENCY 500 /* us */ #elif defined(CHIP_VARIANT_STM32F05X) -#define STOP_MODE_LATENCY 300 /* us */ +#define STOP_MODE_LATENCY 300 /* us */ #elif (CPU_CLOCK == PLL_CLOCK) -#define STOP_MODE_LATENCY 300 /* us */ +#define STOP_MODE_LATENCY 300 /* us */ #else -#define STOP_MODE_LATENCY 50 /* us */ +#define STOP_MODE_LATENCY 50 /* us */ #endif #define SET_RTC_MATCH_DELAY 200 /* us */ @@ -137,9 +137,8 @@ void config_hispeed_clock(void) while ((STM32_RCC_CFGR & 0xc) != 0x8) ; /* F03X and F05X and F070 don't have HSI48 */ -#elif defined(CHIP_VARIANT_STM32F03X) || \ -defined(CHIP_VARIANT_STM32F05X) || \ -defined(CHIP_VARIANT_STM32F070) +#elif defined(CHIP_VARIANT_STM32F03X) || defined(CHIP_VARIANT_STM32F05X) || \ + defined(CHIP_VARIANT_STM32F070) /* If PLL is the clock source, PLL has already been set up. */ if ((STM32_RCC_CFGR & 0xc) == 0x8) return; @@ -259,7 +258,7 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds) set_rtc_alarm(seconds, microseconds, &rtc, 0); /* interrupts off now */ - asm volatile("cpsid i"); + interrupt_disable(); #ifdef CONFIG_HIBERNATE_WAKEUP_PINS /* enable the wake up pins */ @@ -268,7 +267,7 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds) STM32_PWR_CR |= 0xe; CPU_SCB_SYSCTRL |= 0x4; /* go to Standby mode */ - asm("wfi"); + cpu_enter_suspend_mode(); /* we should never reach that point */ while (1) @@ -298,7 +297,7 @@ void __idle(void) struct rtc_time_reg rtc0, rtc1; while (1) { - asm volatile("cpsid i"); + interrupt_disable(); t0 = get_time(); next_delay = __hw_clock_event_get() - t0.le.lo; @@ -319,8 +318,8 @@ void __idle(void) * EC exits deep sleep mode. */ !is_host_wake_alarm_expired( - (timestamp_t)(next_delay + t0.val + SECOND + - RESTORE_HOST_ALARM_LATENCY)) && + (timestamp_t)(next_delay + t0.val + SECOND + + RESTORE_HOST_ALARM_LATENCY)) && #endif (next_delay > (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY))) { /* Deep-sleep in STOP mode */ @@ -331,9 +330,9 @@ void __idle(void) /* Set deep sleep bit */ CPU_SCB_SYSCTRL |= 0x4; - set_rtc_alarm(0, next_delay - STOP_MODE_LATENCY, - &rtc0, 0); - asm("wfi"); + set_rtc_alarm(0, next_delay - STOP_MODE_LATENCY, &rtc0, + 0); + cpu_enter_suspend_mode(); CPU_SCB_SYSCTRL &= ~0x4; @@ -371,12 +370,12 @@ void __idle(void) idle_sleep_cnt++; /* Normal idle : only CPU clock stopped */ - asm("wfi"); + cpu_enter_suspend_mode(); } #ifdef CONFIG_LOW_POWER_IDLE_LIMITED -en_int: + en_int: #endif - asm volatile("cpsie i"); + interrupt_enable(); } } #endif /* CONFIG_LOW_POWER_IDLE */ @@ -399,7 +398,7 @@ void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles) } } -void clock_enable_module(enum module_id module, int enable) +test_mockable void clock_enable_module(enum module_id module, int enable) { if (module == MODULE_ADC) { if (enable) @@ -407,9 +406,23 @@ void clock_enable_module(enum module_id module, int enable) else STM32_RCC_APB2ENR &= ~STM32_RCC_APB2ENR_ADCEN; return; + } else if (module == MODULE_USB) { + if (enable) + STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB; + else + STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB; } } +int clock_is_module_enabled(enum module_id module) +{ + if (module == MODULE_ADC) + return !!(STM32_RCC_APB2ENR & STM32_RCC_APB2ENR_ADCEN); + else if (module == MODULE_USB) + return !!(STM32_RCC_APB1ENR & STM32_RCC_PB1_USB); + return 0; +} + void rtc_init(void) { rtc_unlock_regs(); @@ -468,22 +481,21 @@ void rtc_set(uint32_t sec) /** * Print low power idle statistics */ -static int command_idle_stats(int argc, char **argv) +static int command_idle_stats(int argc, const char **argv) { timestamp_t ts = get_time(); ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); ccprintf("Time spent in deep-sleep: %.6llds\n", - idle_dsleep_time_us); + idle_dsleep_time_us); ccprintf("Total time on: %.6llds\n", ts.val); ccprintf("Deep-sleep closest to wake deadline: %dus\n", - dsleep_recovery_margin_us); + dsleep_recovery_margin_us); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, - "", +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", "Print last idle stats"); #endif /* CONFIG_CMD_IDLE_STATS */ #endif diff --git a/chip/stm32/clock-stm32f3.c b/chip/stm32/clock-stm32f3.c deleted file mode 120000 index be91154e52..0000000000 --- a/chip/stm32/clock-stm32f3.c +++ /dev/null @@ -1 +0,0 @@ -clock-stm32f0.c \ No newline at end of file diff --git a/chip/stm32/clock-stm32f3.c b/chip/stm32/clock-stm32f3.c new file mode 100644 index 0000000000..0a63b27a06 --- /dev/null +++ b/chip/stm32/clock-stm32f3.c @@ -0,0 +1,501 @@ +/* Copyright 2014 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Clocks and power management settings */ + +#include "chipset.h" +#include "clock-f.h" +#include "clock.h" +#include "common.h" +#include "console.h" +#include "cpu.h" +#include "hooks.h" +#include "hwtimer.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "timer.h" +#include "uart.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_CLOCK, outstr) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) + +/* use 48Mhz USB-synchronized High-speed oscillator */ +#define HSI48_CLOCK 48000000 + +/* use PLL at 38.4MHz as system clock. */ +#define PLL_CLOCK 38400000 + +/* Low power idle statistics */ +#ifdef CONFIG_LOW_POWER_IDLE +static int idle_sleep_cnt; +static int idle_dsleep_cnt; +static uint64_t idle_dsleep_time_us; +static int dsleep_recovery_margin_us = 1000000; + +/* + * minimum delay to enter stop mode + * + * STOP_MODE_LATENCY: max time to wake up from STOP mode with regulator in low + * power mode is 5 us + PLL locking time is 200us. + * + * SET_RTC_MATCH_DELAY: max time to set RTC match alarm. If we set the alarm + * in the past, it will never wake up and cause a watchdog. + * For STM32F3, we are using HSE, which requires additional time to start up. + * Therefore, the latency for STM32F3 is set longer. + * + * RESTORE_HOST_ALARM_LATENCY: max latency between the deferred routine is + * called and the host alarm is actually restored. In practice, the max latency + * is measured as ~600us. 1000us should be conservative enough to guarantee + * we won't miss the host alarm. + */ +#ifdef CHIP_VARIANT_STM32F373 +#define STOP_MODE_LATENCY 500 /* us */ +#elif defined(CHIP_VARIANT_STM32F05X) +#define STOP_MODE_LATENCY 300 /* us */ +#elif (CPU_CLOCK == PLL_CLOCK) +#define STOP_MODE_LATENCY 300 /* us */ +#else +#define STOP_MODE_LATENCY 50 /* us */ +#endif +#define SET_RTC_MATCH_DELAY 200 /* us */ + +#ifdef CONFIG_HOSTCMD_RTC +#define RESTORE_HOST_ALARM_LATENCY 1000 /* us */ +#endif + +#endif /* CONFIG_LOW_POWER_IDLE */ + +/* + * RTC clock frequency (By default connected to LSI clock) + * + * The LSI on any given chip can be between 30 kHz to 60 kHz. + * Without calibration, LSI frequency may be off by as much as 50%. + * + * Set synchronous clock freq to (RTC clock source / 2) to maximize + * subsecond resolution. Set asynchronous clock to 1 Hz. + */ + +#define RTC_PREDIV_A 1 +#ifdef CONFIG_STM32_CLOCK_LSE +#define RTC_FREQ (32768 / (RTC_PREDIV_A + 1)) /* Hz */ +/* GCD(RTC_FREQ, 1000000) */ +#define RTC_GCD 64 +#else /* LSI clock, 40kHz-ish */ +#define RTC_FREQ (40000 / (RTC_PREDIV_A + 1)) /* Hz */ +/* GCD(RTC_FREQ, 1000000) */ +#define RTC_GCD 20000 +#endif +#define RTC_PREDIV_S (RTC_FREQ - 1) + +/* + * There are (1000000 / RTC_FREQ) us per RTC tick, take GCD of both terms + * for conversion calculations to fit in 32 bits. + */ +#define US_GCD (1000000 / RTC_GCD) +#define RTC_FREQ_GCD (RTC_FREQ / RTC_GCD) + +int32_t rtcss_to_us(uint32_t rtcss) +{ + return ((RTC_PREDIV_S - (rtcss & 0x7fff)) * US_GCD) / RTC_FREQ_GCD; +} + +uint32_t us_to_rtcss(int32_t us) +{ + return RTC_PREDIV_S - us * RTC_FREQ_GCD / US_GCD; +} + +void config_hispeed_clock(void) +{ +#ifdef CHIP_FAMILY_STM32F3 + /* Ensure that HSE is ON */ + wait_for_ready(&STM32_RCC_CR, BIT(16), BIT(17)); + + /* + * HSE = 24MHz, no prescalar, no MCO, with PLL *2 => 48MHz SYSCLK + * HCLK = SYSCLK, PCLK = HCLK / 2 = 24MHz + * ADCCLK = PCLK / 6 = 4MHz + * USB uses SYSCLK = 48MHz + */ + STM32_RCC_CFGR = 0x0041a400; + + /* Enable the PLL */ + STM32_RCC_CR |= 0x01000000; + + /* Wait until the PLL is ready */ + while (!(STM32_RCC_CR & 0x02000000)) + ; + + /* Switch SYSCLK to PLL */ + STM32_RCC_CFGR |= 0x2; + + /* Wait until the PLL is the clock source */ + while ((STM32_RCC_CFGR & 0xc) != 0x8) + ; +/* F03X and F05X and F070 don't have HSI48 */ +#elif defined(CHIP_VARIANT_STM32F03X) || defined(CHIP_VARIANT_STM32F05X) || \ + defined(CHIP_VARIANT_STM32F070) + /* If PLL is the clock source, PLL has already been set up. */ + if ((STM32_RCC_CFGR & 0xc) == 0x8) + return; + + /* Ensure that HSI is ON */ + wait_for_ready(&STM32_RCC_CR, BIT(0), BIT(1)); + + /* + * HSI = 8MHz, HSI/2 with PLL *12 = ~48 MHz + * therefore PCLK = FCLK = SYSCLK = 48MHz + */ + /* Switch the PLL source to HSI/2 */ + STM32_RCC_CFGR &= ~(0x00018000); + + /* + * Specify HSI/2 clock as input clock to PLL and set PLL (*12). + */ + STM32_RCC_CFGR |= 0x00280000; + + /* Enable the PLL. */ + STM32_RCC_CR |= 0x01000000; + + /* Wait until PLL is ready. */ + while (!(STM32_RCC_CR & 0x02000000)) + ; + + /* Switch SYSCLK to PLL. */ + STM32_RCC_CFGR |= 0x2; + + /* wait until the PLL is the clock source */ + while ((STM32_RCC_CFGR & 0xc) != 0x8) + ; +#else + /* Ensure that HSI48 is ON */ + wait_for_ready(&STM32_RCC_CR2, BIT(16), BIT(17)); + +#if (CPU_CLOCK == HSI48_CLOCK) + /* + * HSI48 = 48MHz, no prescaler, no MCO, no PLL + * therefore PCLK = FCLK = SYSCLK = 48MHz + * USB uses HSI48 = 48MHz + */ + +#ifdef CONFIG_USB + /* + * Configure and enable Clock Recovery System + * + * Since we are running from the internal RC HSI48 clock, the CSR + * is needed to guarantee an accurate 48MHz clock for USB. + * + * The default values configure the CRS to use the periodic USB SOF + * as the SYNC signal for calibrating the HSI48. + * + */ + + /* Enable Clock Recovery System */ + STM32_RCC_APB1ENR |= STM32_RCC_PB1_CRS; + + /* Enable automatic trimming */ + STM32_CRS_CR |= STM32_CRS_CR_AUTOTRIMEN; + + /* Enable oscillator clock for the frequency error counter */ + STM32_CRS_CR |= STM32_CRS_CR_CEN; +#endif + + /* switch SYSCLK to HSI48 */ + STM32_RCC_CFGR = 0x00000003; + + /* wait until the HSI48 is the clock source */ + while ((STM32_RCC_CFGR & 0xc) != 0xc) + ; + +#elif (CPU_CLOCK == PLL_CLOCK) + /* + * HSI48 = 48MHz, no prescalar, no MCO, with PLL *4/5 => 38.4MHz SYSCLK + * therefore PCLK = FCLK = SYSCLK = 38.4MHz + * USB uses HSI48 = 48MHz + */ + + /* If PLL is the clock source, PLL has already been set up. */ + if ((STM32_RCC_CFGR & 0xc) == 0x8) + return; + + /* + * Specify HSI48 clock as input clock to PLL and set PLL multiplier + * and divider. + */ + STM32_RCC_CFGR = 0x00098000; + STM32_RCC_CFGR2 = 0x4; + + /* Enable the PLL. */ + STM32_RCC_CR |= 0x01000000; + + /* Wait until PLL is ready. */ + while (!(STM32_RCC_CR & 0x02000000)) + ; + + /* Switch SYSCLK to PLL. */ + STM32_RCC_CFGR |= 0x2; + + /* wait until the PLL is the clock source */ + while ((STM32_RCC_CFGR & 0xc) != 0x8) + ; + +#else +#error "CPU_CLOCK must be either 48MHz or 38.4MHz" +#endif +#endif +} + +#ifdef CONFIG_HIBERNATE +void __enter_hibernate(uint32_t seconds, uint32_t microseconds) +{ + struct rtc_time_reg rtc; + + if (seconds || microseconds) + set_rtc_alarm(seconds, microseconds, &rtc, 0); + + /* interrupts off now */ + interrupt_disable(); + +#ifdef CONFIG_HIBERNATE_WAKEUP_PINS + /* enable the wake up pins */ + STM32_PWR_CSR |= CONFIG_HIBERNATE_WAKEUP_PINS; +#endif + STM32_PWR_CR |= 0xe; + CPU_SCB_SYSCTRL |= 0x4; + /* go to Standby mode */ + asm("wfi"); + + /* we should never reach that point */ + while (1) + ; +} +#endif + +#ifdef CONFIG_HOSTCMD_RTC +static void restore_host_wake_alarm_deferred(void) +{ + restore_host_wake_alarm(); +} +DECLARE_DEFERRED(restore_host_wake_alarm_deferred); +#endif + +#ifdef CONFIG_LOW_POWER_IDLE + +void clock_refresh_console_in_use(void) +{ +} + +void __idle(void) +{ + timestamp_t t0; + uint32_t rtc_diff; + int next_delay, margin_us; + struct rtc_time_reg rtc0, rtc1; + + while (1) { + interrupt_disable(); + + t0 = get_time(); + next_delay = __hw_clock_event_get() - t0.le.lo; + +#ifdef CONFIG_LOW_POWER_IDLE_LIMITED + if (idle_is_disabled()) + goto en_int; +#endif + + if (DEEP_SLEEP_ALLOWED && +#ifdef CONFIG_HOSTCMD_RTC + /* + * Don't go to deep sleep mode if we might miss the + * wake alarm that the host requested. Note that the + * host alarm always aligns to second. Considering the + * worst case, we have to ensure alarm won't go off + * within RESTORE_HOST_ALARM_LATENCY + 1 second after + * EC exits deep sleep mode. + */ + !is_host_wake_alarm_expired( + (timestamp_t)(next_delay + t0.val + SECOND + + RESTORE_HOST_ALARM_LATENCY)) && +#endif + (next_delay > (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY))) { + /* Deep-sleep in STOP mode */ + idle_dsleep_cnt++; + + uart_enable_wakeup(1); + + /* Set deep sleep bit */ + CPU_SCB_SYSCTRL |= 0x4; + + set_rtc_alarm(0, next_delay - STOP_MODE_LATENCY, &rtc0, + 0); + asm("wfi"); + + CPU_SCB_SYSCTRL &= ~0x4; + + uart_enable_wakeup(0); + + /* + * By default only HSI 8MHz is enabled here. Re-enable + * high-speed clock if in use. + */ + config_hispeed_clock(); + + /* Fast forward timer according to RTC counter */ + reset_rtc_alarm(&rtc1); + rtc_diff = get_rtc_diff(&rtc0, &rtc1); + t0.val = t0.val + rtc_diff; + force_time(t0); + +#ifdef CONFIG_HOSTCMD_RTC + hook_call_deferred( + &restore_host_wake_alarm_deferred_data, 0); +#endif + /* Record time spent in deep sleep. */ + idle_dsleep_time_us += rtc_diff; + + /* Calculate how close we were to missing deadline */ + margin_us = next_delay - rtc_diff; + if (margin_us < 0) + /* Use CPUTS to save stack space */ + CPUTS("Idle overslept!\n"); + + /* Record the closest to missing a deadline. */ + if (margin_us < dsleep_recovery_margin_us) + dsleep_recovery_margin_us = margin_us; + } else { + idle_sleep_cnt++; + + /* Normal idle : only CPU clock stopped */ + asm("wfi"); + } +#ifdef CONFIG_LOW_POWER_IDLE_LIMITED + en_int: +#endif + interrupt_enable(); + } +} +#endif /* CONFIG_LOW_POWER_IDLE */ + +int clock_get_freq(void) +{ + return CPU_CLOCK; +} + +void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles) +{ + volatile uint32_t unused __attribute__((unused)); + + if (bus == BUS_AHB) { + while (cycles--) + unused = STM32_DMA1_REGS->isr; + } else { /* APB */ + while (cycles--) + unused = STM32_USART_BRR(STM32_USART1_BASE); + } +} + +test_mockable void clock_enable_module(enum module_id module, int enable) +{ + if (module == MODULE_ADC) { + if (enable) + STM32_RCC_APB2ENR |= STM32_RCC_APB2ENR_ADCEN; + else + STM32_RCC_APB2ENR &= ~STM32_RCC_APB2ENR_ADCEN; + return; + } else if (module == MODULE_USB) { + if (enable) + STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB; + else + STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB; + } +} + +int clock_is_module_enabled(enum module_id module) +{ + if (module == MODULE_ADC) + return !!(STM32_RCC_APB2ENR & STM32_RCC_APB2ENR_ADCEN); + else if (module == MODULE_USB) + return !!(STM32_RCC_APB1ENR & STM32_RCC_PB1_USB); + return 0; +} + +void rtc_init(void) +{ + rtc_unlock_regs(); + + /* Enter RTC initialize mode */ + STM32_RTC_ISR |= STM32_RTC_ISR_INIT; + while (!(STM32_RTC_ISR & STM32_RTC_ISR_INITF)) + ; + + /* Set clock prescalars */ + STM32_RTC_PRER = (RTC_PREDIV_A << 16) | RTC_PREDIV_S; + + /* Start RTC timer */ + STM32_RTC_ISR &= ~STM32_RTC_ISR_INIT; + while (STM32_RTC_ISR & STM32_RTC_ISR_INITF) + ; + + /* Enable RTC alarm interrupt */ + STM32_RTC_CR |= STM32_RTC_CR_ALRAIE | STM32_RTC_CR_BYPSHAD; + STM32_EXTI_RTSR |= EXTI_RTC_ALR_EVENT; + task_enable_irq(STM32_IRQ_RTC_ALARM); + + rtc_lock_regs(); +} + +#if defined(CONFIG_CMD_RTC) || defined(CONFIG_HOSTCMD_RTC) +void rtc_set(uint32_t sec) +{ + struct rtc_time_reg rtc; + + sec_to_rtc(sec, &rtc); + rtc_unlock_regs(); + + /* Disable alarm */ + STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE; + + /* Enter RTC initialize mode */ + STM32_RTC_ISR |= STM32_RTC_ISR_INIT; + while (!(STM32_RTC_ISR & STM32_RTC_ISR_INITF)) + ; + + /* Set clock prescalars */ + STM32_RTC_PRER = (RTC_PREDIV_A << 16) | RTC_PREDIV_S; + + STM32_RTC_TR = rtc.rtc_tr; + STM32_RTC_DR = rtc.rtc_dr; + /* Start RTC timer */ + STM32_RTC_ISR &= ~STM32_RTC_ISR_INIT; + + rtc_lock_regs(); +} +#endif + +#if defined(CONFIG_LOW_POWER_IDLE) && defined(CONFIG_COMMON_RUNTIME) +#ifdef CONFIG_CMD_IDLE_STATS +/** + * Print low power idle statistics + */ +static int command_idle_stats(int argc, const char **argv) +{ + timestamp_t ts = get_time(); + + ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); + ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); + ccprintf("Time spent in deep-sleep: %.6llds\n", + idle_dsleep_time_us); + ccprintf("Total time on: %.6llds\n", ts.val); + ccprintf("Deep-sleep closest to wake deadline: %dus\n", + dsleep_recovery_margin_us); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", + "Print last idle stats"); +#endif /* CONFIG_CMD_IDLE_STATS */ +#endif diff --git a/chip/stm32/clock-stm32f4.c b/chip/stm32/clock-stm32f4.c index 7b83b8507e..c64afdd278 100644 --- a/chip/stm32/clock-stm32f4.c +++ b/chip/stm32/clock-stm32f4.c @@ -1,13 +1,14 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Clocks and power management settings */ +#include "builtin/assert.h" #include "chipset.h" -#include "clock.h" #include "clock-f.h" +#include "clock.h" #include "common.h" #include "console.h" #include "cpu.h" @@ -21,39 +22,209 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) + +enum clock_osc { + OSC_HSI = 0, /* High-speed internal oscillator */ + OSC_HSE, /* High-speed external oscillator */ + OSC_PLL, /* PLL */ +}; + +/* + * NOTE: Sweetberry requires MCO2 <- HSE @ 24MHz + * MCO outputs are selected here but are not changeable later. + * A CONFIG may be needed if other boards have different MCO + * requirements. + */ +#define RCC_CFGR_MCO_CONFIG \ + ((2 << 30) | /* MCO2 <- HSE */ \ + (0 << 27) | /* MCO2 div / 4 */ \ + (6 << 24) | /* MCO1 div / 4 */ \ + (3 << 21)) /* MCO1 <- PLL */ #ifdef CONFIG_STM32_CLOCK_HSE_HZ -#define RTC_PREDIV_A 39 -#define RTC_FREQ ((STM32F4_RTC_REQ) / (RTC_PREDIV_A + 1)) /* Hz */ -#else -/* LSI clock is 40kHz-ish */ -#define RTC_PREDIV_A 1 -#define RTC_FREQ (40000 / (RTC_PREDIV_A + 1)) /* Hz */ -#endif -#define RTC_PREDIV_S (RTC_FREQ - 1) -#define US_PER_RTC_TICK (1000000 / RTC_FREQ) +/* RTC clock must 1 Mhz when derived from HSE */ +#define RTC_DIV DIV_ROUND_NEAREST(CONFIG_STM32_CLOCK_HSE_HZ, STM32F4_RTC_REQ) +#else /* !CONFIG_STM32_CLOCK_HSE_HZ */ +/* RTC clock not derived from HSE, turn it off */ +#define RTC_DIV 0 +#endif /* CONFIG_STM32_CLOCK_HSE_HZ */ + +/* Bus clocks dividers depending on the configuration */ +/* + * max speed configuration with the PLL ON + * as defined in the registers file. + * For STM32F446: max 45 MHz + * For STM32F412: max AHB 100 MHz / APB2 100 Mhz / APB1 50 Mhz + */ +#define RCC_CFGR_DIVIDERS_WITH_PLL \ + (RCC_CFGR_MCO_CONFIG | CFGR_RTCPRE(RTC_DIV) | \ + CFGR_PPRE2(STM32F4_APB2_PRE) | CFGR_PPRE1(STM32F4_APB1_PRE) | \ + CFGR_HPRE(STM32F4_AHB_PRE)) +/* + * lower power configuration without the PLL + * the frequency will be low (8-24Mhz), we don't want dividers to the + * peripheral clocks, put /1 everywhere. + */ +#define RCC_CFGR_DIVIDERS_NO_PLL \ + (RCC_CFGR_MCO_CONFIG | CFGR_RTCPRE(0) | CFGR_PPRE2(0) | \ + CFGR_PPRE1(0) | CFGR_HPRE(0)) -int32_t rtcss_to_us(uint32_t rtcss) +/* PLL output frequency */ +#define STM32F4_PLL_CLOCK (STM32F4_VCO_CLOCK / STM32F4_PLLP_DIV) + +/* current clock settings (PLL is initialized at startup) */ +static int current_osc = OSC_PLL; +static int current_io_freq = STM32F4_IO_CLOCK; +static int current_timer_freq = STM32F4_TIMER_CLOCK; + +/* the EC code expects to get the USART/I2C clock frequency here (APB clock) */ +int clock_get_freq(void) { - return ((RTC_PREDIV_S - rtcss) * US_PER_RTC_TICK); + return current_io_freq; } -uint32_t us_to_rtcss(int32_t us) +int clock_get_timer_freq(void) { - return (RTC_PREDIV_S - (us / US_PER_RTC_TICK)); + return current_timer_freq; } -void config_hispeed_clock(void) +static void clock_enable_osc(enum clock_osc osc, bool enabled) +{ + uint32_t ready; + uint32_t on; + + switch (osc) { + case OSC_HSI: + ready = STM32_RCC_CR_HSIRDY; + on = STM32_RCC_CR_HSION; + break; + case OSC_HSE: + ready = STM32_RCC_CR_HSERDY; + on = STM32_RCC_CR_HSEON; + break; + case OSC_PLL: + ready = STM32_RCC_CR_PLLRDY; + on = STM32_RCC_CR_PLLON; + break; + default: + ASSERT(0); + return; + } + + /* Turn off the oscillator, but don't wait for shutdown */ + if (!enabled) { + STM32_RCC_CR &= ~on; + return; + } + + /* Turn on the oscillator if not already on */ + wait_for_ready(&STM32_RCC_CR, on, ready); +} + +static void clock_switch_osc(enum clock_osc osc) +{ + uint32_t sw; + uint32_t sws; + + switch (osc) { + case OSC_HSI: + sw = STM32_RCC_CFGR_SW_HSI | RCC_CFGR_DIVIDERS_NO_PLL; + sws = STM32_RCC_CFGR_SWS_HSI; + break; + case OSC_HSE: + sw = STM32_RCC_CFGR_SW_HSE | RCC_CFGR_DIVIDERS_NO_PLL; + sws = STM32_RCC_CFGR_SWS_HSE; + break; + case OSC_PLL: + sw = STM32_RCC_CFGR_SW_PLL | RCC_CFGR_DIVIDERS_WITH_PLL; + sws = STM32_RCC_CFGR_SWS_PLL; + break; + default: + return; + } + + STM32_RCC_CFGR = sw; + while ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) != sws) + ; +} + +void clock_set_osc(enum clock_osc osc) +{ + volatile uint32_t unused __attribute__((unused)); + + if (osc == current_osc) + return; + + hook_notify(HOOK_PRE_FREQ_CHANGE); + + switch (osc) { + default: + case OSC_HSI: + /* new clock settings: no dividers */ + current_io_freq = STM32F4_HSI_CLOCK; + current_timer_freq = STM32F4_HSI_CLOCK; + /* Switch to HSI */ + clock_switch_osc(OSC_HSI); + /* optimized flash latency settings for <30Mhz clock (0-WS) */ + STM32_FLASH_ACR = + (STM32_FLASH_ACR & ~STM32_FLASH_ACR_LAT_MASK) | + STM32_FLASH_ACR_LATENCY_SLOW; + /* read-back the latency as advised by the Reference Manual */ + unused = STM32_FLASH_ACR; + /* Turn off the PLL1 to save power */ + clock_enable_osc(OSC_PLL, false); + break; + +#ifdef CONFIG_STM32_CLOCK_HSE_HZ + case OSC_HSE: + /* new clock settings: no dividers */ + current_io_freq = CONFIG_STM32_CLOCK_HSE_HZ; + current_timer_freq = CONFIG_STM32_CLOCK_HSE_HZ; + /* Switch to HSE */ + clock_switch_osc(OSC_HSE); + /* optimized flash latency settings for <30Mhz clock (0-WS) */ + STM32_FLASH_ACR = + (STM32_FLASH_ACR & ~STM32_FLASH_ACR_LAT_MASK) | + STM32_FLASH_ACR_LATENCY_SLOW; + /* read-back the latency as advised by the Reference Manual */ + unused = STM32_FLASH_ACR; + /* Turn off the PLL1 to save power */ + clock_enable_osc(OSC_PLL, false); + break; +#endif /* CONFIG_STM32_CLOCK_HSE_HZ */ + + case OSC_PLL: + /* new clock settings */ + current_io_freq = STM32F4_IO_CLOCK; + current_timer_freq = STM32F4_TIMER_CLOCK; + /* turn on PLL and wait until it's ready */ + clock_enable_osc(OSC_PLL, true); + /* + * Increase flash latency before transition the clock + * Use the minimum Wait States value optimized for the platform. + */ + STM32_FLASH_ACR = + (STM32_FLASH_ACR & ~STM32_FLASH_ACR_LAT_MASK) | + STM32_FLASH_ACR_LATENCY; + /* read-back the latency as advised by the Reference Manual */ + unused = STM32_FLASH_ACR; + /* Switch to PLL */ + clock_switch_osc(OSC_PLL); + + break; + } + + current_osc = osc; + hook_notify(HOOK_FREQ_CHANGE); +} + +static void clock_pll_configure(void) { #ifdef CONFIG_STM32_CLOCK_HSE_HZ int srcclock = CONFIG_STM32_CLOCK_HSE_HZ; - int clk_check_mask = STM32_RCC_CR_HSERDY; - int clk_enable_mask = STM32_RCC_CR_HSEON; #else int srcclock = STM32F4_HSI_CLOCK; - int clk_check_mask = STM32_RCC_CR_HSIRDY; - int clk_enable_mask = STM32_RCC_CR_HSION; #endif int plldiv, pllinputclock; int pllmult, vcoclock; @@ -61,17 +232,6 @@ void config_hispeed_clock(void) int usbdiv; int i2sdiv; - int ahbpre, apb1pre, apb2pre; - int rtcdiv = 0; - - /* If PLL is the clock source, PLL has already been set up. */ - if ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) == - STM32_RCC_CFGR_SWS_PLL) - return; - - /* Ensure that HSE/HSI is ON */ - wait_for_ready(&(STM32_RCC_CR), clk_enable_mask, clk_check_mask); - /* PLL input must be between 1-2MHz, near 2 */ /* Valid values 2-63 */ plldiv = (srcclock + STM32F4_PLL_REQ - 1) / STM32F4_PLL_REQ; @@ -90,86 +250,36 @@ void config_hispeed_clock(void) /* SYSTEM/I2S: same system clock */ i2sdiv = (vcoclock + (systemclock / 2)) / systemclock; - /* All IO clocks at STM32F4_IO_CLOCK - * For STM32F446: max 45 MHz - * For STM32F412: max 50 MHz - */ - /* AHB Prescalar */ - ahbpre = STM32F4_AHB_PRE; - /* NOTE: If apbXpre is not 0, timers are x2 clocked. RM0390 Fig. 13 - * One should define STM32F4_TIMER_CLOCK when apbXpre is not 0. - * STM32F4_TIMER_CLOCK is used for hwtimer in EC. */ - apb1pre = STM32F4_APB1_PRE; - apb2pre = STM32F4_APB2_PRE; - -#ifdef CONFIG_STM32_CLOCK_HSE_HZ - /* RTC clock = 1MHz */ - rtcdiv = (CONFIG_STM32_CLOCK_HSE_HZ + (STM32F4_RTC_REQ / 2)) - / STM32F4_RTC_REQ; -#endif - /* Switch SYSCLK to PLL, setup prescalars. - * EC codebase doesn't understand multiple clock domains - * so we enforce a clock config that keeps AHB = APB1 = APB2 - * allowing ec codebase assumptions about consistent clock - * rates to remain true. - * - * NOTE: Sweetberry requires MCO2 <- HSE @ 24MHz - * MCO outputs are selected here but are not changeable later. - * A CONFIG may be needed if other boards have different MCO - * requirements. - */ - STM32_RCC_CFGR = - (2 << 30) | /* MCO2 <- HSE */ - (0 << 27) | /* MCO2 div / 4 */ - (6 << 24) | /* MCO1 div / 4 */ - (3 << 21) | /* MCO1 <- PLL */ - CFGR_RTCPRE(rtcdiv) | - CFGR_PPRE2(apb2pre) | - CFGR_PPRE1(apb1pre) | - CFGR_HPRE(ahbpre) | - STM32_RCC_CFGR_SW_PLL; - /* Set up PLL */ - STM32_RCC_PLLCFGR = - PLLCFGR_PLLM(plldiv) | - PLLCFGR_PLLN(pllmult) | - PLLCFGR_PLLP(STM32F4_PLLP_DIV / 2 - 1) | + STM32_RCC_PLLCFGR = PLLCFGR_PLLM(plldiv) | PLLCFGR_PLLN(pllmult) | + PLLCFGR_PLLP(STM32F4_PLLP_DIV / 2 - 1) | #if defined(CONFIG_STM32_CLOCK_HSE_HZ) - PLLCFGR_PLLSRC_HSE | + PLLCFGR_PLLSRC_HSE | #else - PLLCFGR_PLLSRC_HSI | + PLLCFGR_PLLSRC_HSI | #endif - PLLCFGR_PLLQ(usbdiv) | - PLLCFGR_PLLR(i2sdiv); - - wait_for_ready(&(STM32_RCC_CR), - STM32_RCC_CR_PLLON, STM32_RCC_CR_PLLRDY); + PLLCFGR_PLLQ(usbdiv) | PLLCFGR_PLLR(i2sdiv); +} - /* Wait until the PLL is the clock source */ - if ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) == - STM32_RCC_CFGR_SWS_PLL) - ; +void low_power_init(void); - /* Setup RTC Clock input */ +void config_hispeed_clock(void) +{ #ifdef CONFIG_STM32_CLOCK_HSE_HZ - STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC_HSE); -#else - /* Ensure that LSI is ON */ - wait_for_ready(&(STM32_RCC_CSR), - STM32_RCC_CSR_LSION, STM32_RCC_CSR_LSIRDY); - - STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC_LSI); + /* Ensure that HSE is ON */ + clock_enable_osc(OSC_HSE, true); #endif -} -int clock_get_timer_freq(void) -{ - return STM32F4_TIMER_CLOCK; -} + /* Put the PLL settings, they are never changing */ + clock_pll_configure(); + clock_enable_osc(OSC_PLL, true); -int clock_get_freq(void) -{ - return STM32F4_IO_CLOCK; + /* Switch SYSCLK to PLL, setup bus prescalers. */ + clock_switch_osc(OSC_PLL); + +#ifdef CONFIG_LOW_POWER_IDLE + low_power_init(); +#endif } void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles) @@ -185,28 +295,29 @@ void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles) } } -void clock_enable_module(enum module_id module, int enable) +test_mockable void clock_enable_module(enum module_id module, int enable) { if (module == MODULE_USB) { if (enable) { STM32_RCC_AHB2ENR |= STM32_RCC_AHB2ENR_OTGFSEN; STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_OTGHSEN | - STM32_RCC_AHB1ENR_OTGHSULPIEN; + STM32_RCC_AHB1ENR_OTGHSULPIEN; } else { STM32_RCC_AHB2ENR &= ~STM32_RCC_AHB2ENR_OTGFSEN; STM32_RCC_AHB1ENR &= ~STM32_RCC_AHB1ENR_OTGHSEN & - ~STM32_RCC_AHB1ENR_OTGHSULPIEN; + ~STM32_RCC_AHB1ENR_OTGHSULPIEN; } return; } else if (module == MODULE_I2C) { if (enable) { /* Enable clocks to I2C modules if necessary */ STM32_RCC_APB1ENR |= - STM32_RCC_I2C1EN | STM32_RCC_I2C2EN - | STM32_RCC_I2C3EN | STM32_RCC_FMPI2C4EN; + STM32_RCC_I2C1EN | STM32_RCC_I2C2EN | + STM32_RCC_I2C3EN | STM32_RCC_FMPI2C4EN; STM32_RCC_DCKCFGR2 = - (STM32_RCC_DCKCFGR2 & ~DCKCFGR2_FMPI2C1SEL_MASK) - | DCKCFGR2_FMPI2C1SEL(FMPI2C1SEL_APB); + (STM32_RCC_DCKCFGR2 & + ~DCKCFGR2_FMPI2C1SEL_MASK) | + DCKCFGR2_FMPI2C1SEL(FMPI2C1SEL_APB); } else { STM32_RCC_APB1ENR &= ~(STM32_RCC_I2C1EN | STM32_RCC_I2C2EN | @@ -222,8 +333,48 @@ void clock_enable_module(enum module_id module, int enable) } } +/* Real Time Clock (RTC) */ + +#ifdef CONFIG_STM32_CLOCK_HSE_HZ +#define RTC_PREDIV_A 39 +#define RTC_FREQ ((STM32F4_RTC_REQ) / (RTC_PREDIV_A + 1)) /* Hz */ +#else /* from LSI clock */ +#define RTC_PREDIV_A 1 +#define RTC_FREQ (STM32F4_LSI_CLOCK / (RTC_PREDIV_A + 1)) /* Hz */ +#endif +#define RTC_PREDIV_S (RTC_FREQ - 1) +/* + * Scaling factor to ensure that the intermediate values computed from/to the + * RTC frequency are fitting in a 32-bit integer. + */ +#define SCALING 1000 + +int32_t rtcss_to_us(uint32_t rtcss) +{ + return ((RTC_PREDIV_S - rtcss) * (SECOND / SCALING) / + (RTC_FREQ / SCALING)); +} + +uint32_t us_to_rtcss(int32_t us) +{ + return (RTC_PREDIV_S - + (us * (RTC_FREQ / SCALING) / (SECOND / SCALING))); +} + void rtc_init(void) { + /* Setup RTC Clock input */ +#ifdef CONFIG_STM32_CLOCK_HSE_HZ + /* RTC clocked from the HSE */ + STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC_HSE); +#else + /* RTC clocked from the LSI, ensure first it is ON */ + wait_for_ready(&(STM32_RCC_CSR), STM32_RCC_CSR_LSION, + STM32_RCC_CSR_LSIRDY); + + STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC_LSI); +#endif + rtc_unlock_regs(); /* Enter RTC initialize mode */ @@ -232,11 +383,10 @@ void rtc_init(void) ; /* Set clock prescalars: Needs two separate writes. */ - STM32_RTC_PRER = - (STM32_RTC_PRER & ~STM32_RTC_PRER_S_MASK) | RTC_PREDIV_S; - STM32_RTC_PRER = - (STM32_RTC_PRER & ~STM32_RTC_PRER_A_MASK) - | (RTC_PREDIV_A << 16); + STM32_RTC_PRER = (STM32_RTC_PRER & ~STM32_RTC_PRER_S_MASK) | + RTC_PREDIV_S; + STM32_RTC_PRER = (STM32_RTC_PRER & ~STM32_RTC_PRER_A_MASK) | + (RTC_PREDIV_A << 16); /* Start RTC timer */ STM32_RTC_ISR &= ~STM32_RTC_ISR_INIT; @@ -278,3 +428,178 @@ void rtc_set(uint32_t sec) rtc_lock_regs(); } #endif + +#ifdef CONFIG_LOW_POWER_IDLE +/* Low power idle statistics */ +static int idle_sleep_cnt; +static int idle_dsleep_cnt; +static uint64_t idle_dsleep_time_us; +static int idle_sleep_prevented_cnt; +static int dsleep_recovery_margin_us = 1000000; + +/* STOP_MODE_LATENCY: delay to wake up from STOP mode with main regulator off */ +#define STOP_MODE_LATENCY 50 /* us */ +/* PLL_LOCK_LATENCY: delay to switch from HSI to PLL */ +#define PLL_LOCK_LATENCY 150 /* us */ + +void low_power_init(void) +{ + /* Turn off the main regulator during stop mode */ + STM32_PWR_CR |= STM32_PWR_CR_LPSDSR /* aka LPDS */; +} + +void clock_refresh_console_in_use(void) +{ +} + +static bool timer_interrupt_pending(void) +{ + return task_is_irq_pending(IRQ_TIM(TIM_CLOCK32)); +} + +void __idle(void) +{ + timestamp_t t0; + uint32_t rtc_diff; + int next_delay, margin_us; + struct rtc_time_reg rtc0, rtc1, rtc_sleep; + + while (1) { + interrupt_disable(); + + /* + * Get timestamp with interrupts disabled. + * This value is used as a base to calculate timestamp after + * wake from deep sleep. In combination with next_delay it gives + * information how long the CPU can sleep. The timestamp can + * point to the previous "epoch" when timer overflowed after + * interrupts were disabled, since clksrc_high (which keeps + * higher 32 bits of the timestamp) will not be updated. + */ + rtc_read(&rtc0); + t0 = get_time(); + + /* + * Get time to next event. + * After disabling interrupts, event timestamp + * (__hw_clock_event_get()) is frozen, because + * process_timers(), responsible for updating the + * next event value with __hw_clock_event_set(), + * can't be called. There is a risk that timer overflow + * occurred after interrupts were disabled and obtained + * event timestamp points to previous "epoch". We will + * check that later. + */ + next_delay = __hw_clock_event_get() - t0.le.lo; + + /* + * Repeat idle enter procedure when timer interrupt is pending + * (eg. overflow occurred after disabling interrupts). To work + * properly, this code assumes that timer interrupt is enabled + * in NVIC and interrupt is generated on timer overflow. + */ + if (timer_interrupt_pending()) { + idle_sleep_prevented_cnt++; + + /* Enable interrupts to handle detected overflow. */ + interrupt_enable(); + + /* Repeat idle enter procedure. */ + continue; + } + + if (DEEP_SLEEP_ALLOWED && + (next_delay > (STOP_MODE_LATENCY + PLL_LOCK_LATENCY + + SET_RTC_MATCH_DELAY))) { + /* + * Sleep time MUST be smaller than watchdog period. + * Otherwise watchdog will wake us from deep sleep + * which is not what we want. Please note that this + * assert won't fire if we are already part way through + * the watchdog period. + */ + ASSERT(next_delay < CONFIG_WATCHDOG_PERIOD_MS * MSEC); + + /* Deep-sleep in STOP mode */ + idle_dsleep_cnt++; + + /* + * TODO(b/174337385) no support for wake-up on USART + * uart_enable_wakeup(1); + */ + + /* Set deep sleep bit */ + CPU_SCB_SYSCTRL |= 0x4; + + set_rtc_alarm(0, + next_delay - STOP_MODE_LATENCY - + PLL_LOCK_LATENCY, + &rtc_sleep, 0); + + /* Switch to HSI */ + clock_switch_osc(OSC_HSI); + /* Turn off the PLL1 to save power */ + clock_enable_osc(OSC_PLL, false); + + /* ensure outstanding memory transactions complete */ + asm volatile("dsb"); + + cpu_enter_suspend_mode(); + + CPU_SCB_SYSCTRL &= ~0x4; + + /* turn on PLL and wait until it's ready */ + clock_enable_osc(OSC_PLL, true); + /* Switch to PLL */ + clock_switch_osc(OSC_PLL); + + /*uart_enable_wakeup(0);*/ + + /* Fast forward timer according to RTC counter */ + reset_rtc_alarm(&rtc1); + rtc_diff = get_rtc_diff(&rtc0, &rtc1); + t0.val = t0.val + rtc_diff; + force_time(t0); + + /* Record time spent in deep sleep. */ + idle_dsleep_time_us += get_rtc_diff(&rtc_sleep, &rtc1); + + /* Calculate how close we were to missing deadline */ + margin_us = next_delay - rtc_diff; + if (margin_us < 0) + /* Use CPUTS to save stack space */ + CPUTS("Idle overslept!\n"); + + /* Record the closest to missing a deadline. */ + if (margin_us < dsleep_recovery_margin_us) + dsleep_recovery_margin_us = margin_us; + } else { + idle_sleep_cnt++; + + /* Normal idle : only CPU clock stopped */ + cpu_enter_suspend_mode(); + } + interrupt_enable(); + } +} + +/* Print low power idle statistics. */ +static int command_idle_stats(int argc, const char **argv) +{ + timestamp_t ts = get_time(); + + ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); + ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); + ccprintf("Time spent in deep-sleep: %.6llds\n", + idle_dsleep_time_us); + ccprintf("Num of prevented sleep: %d\n", + idle_sleep_prevented_cnt); + ccprintf("Total time on: %.6llds\n", ts.val); + ccprintf("Deep-sleep closest to wake deadline: %dus\n", + dsleep_recovery_margin_us); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", + "Print last idle stats"); +#endif /* CONFIG_LOW_POWER_IDLE */ diff --git a/chip/stm32/clock-stm32g4.c b/chip/stm32/clock-stm32g4.c index 941cb94327..6b186e9c09 100644 --- a/chip/stm32/clock-stm32g4.c +++ b/chip/stm32/clock-stm32g4.c @@ -1,13 +1,14 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Clocks configuration routines */ +#include "builtin/assert.h" #include "chipset.h" -#include "clock.h" #include "clock-f.h" +#include "clock.h" #include "common.h" #include "console.h" #include "cpu.h" @@ -21,14 +22,14 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) -#define MHZ(x) ((x) * 1000000) -#define WAIT_STATE_FREQ_STEP_HZ MHZ(20) +#define MHZ(x) ((x)*1000000) +#define WAIT_STATE_FREQ_STEP_HZ MHZ(20) /* PLL configuration constants */ -#define STM32G4_SYSCLK_MAX_HZ MHZ(170) -#define STM32G4_HSI_CLK_HZ MHZ(16) -#define STM32G4_PLL_IN_FREQ_HZ MHZ(4) +#define STM32G4_SYSCLK_MAX_HZ MHZ(170) +#define STM32G4_HSI_CLK_HZ MHZ(16) +#define STM32G4_PLL_IN_FREQ_HZ MHZ(4) #define STM32G4_PLL_R 2 #define STM32G4_AHB_PRE 1 #define STM32G4_APB1_PRE 1 @@ -42,7 +43,7 @@ enum rcc_clksrc { }; static void stm32g4_config_pll(uint32_t hclk_hz, uint32_t pll_src, - uint32_t pll_clk_in_hz) + uint32_t pll_clk_in_hz) { /* * The pll output frequency (Fhclkc) is determined by: @@ -81,20 +82,16 @@ static void stm32g4_config_pll(uint32_t hclk_hz, uint32_t pll_src, ASSERT(pll_m && (pll_m <= 16)); ASSERT((pll_n >= 8) && (pll_n <= 127)); - hclk_freq = pll_clk_in_hz * pll_n / (pll_m * - STM32G4_PLL_R * STM32G4_AHB_PRE); + hclk_freq = pll_clk_in_hz * pll_n / + (pll_m * STM32G4_PLL_R * STM32G4_AHB_PRE); /* Ensure that there aren't any integer rounding errors */ ASSERT(hclk_freq == hclk_hz); /* Program PLL config register */ - STM32_RCC_PLLCFGR = PLLCFGR_PLLP(0) | - PLLCFGR_PLLR(STM32G4_PLL_R / 2 - 1) | - PLLCFGR_PLLR_EN | - PLLCFGR_PLLQ(0) | - PLLCFGR_PLLQ_EN | - PLLCFGR_PLLN(pll_n) | - PLLCFGR_PLLM(pll_m - 1) | - pll_src; + STM32_RCC_PLLCFGR = + PLLCFGR_PLLP(0) | PLLCFGR_PLLR(STM32G4_PLL_R / 2 - 1) | + PLLCFGR_PLLR_EN | PLLCFGR_PLLQ(0) | PLLCFGR_PLLQ_EN | + PLLCFGR_PLLN(pll_n) | PLLCFGR_PLLM(pll_m - 1) | pll_src; /* Wait until PLL is locked */ wait_for_ready(&(STM32_RCC_CR), STM32_RCC_CR_PLLON, @@ -116,9 +113,11 @@ static void stm32g4_config_pll(uint32_t hclk_hz, uint32_t pll_src, static void stm32g4_config_low_speed_clock(void) { /* Ensure that LSI is ON */ - wait_for_ready(&(STM32_RCC_CSR), - STM32_RCC_CSR_LSION, STM32_RCC_CSR_LSIRDY); + wait_for_ready(&(STM32_RCC_CSR), STM32_RCC_CSR_LSION, + STM32_RCC_CSR_LSIRDY); + /* Setup RTC Clock input */ + STM32_RCC_BDCR |= STM32_RCC_BDCR_BDRST; STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC_LSI); } @@ -161,10 +160,10 @@ void stm32g4_set_flash_ws(uint32_t freq_hz) * found in Table 9 of RM0440 - STM32G4 technical reference manual. A * table lookup is not required though as WS = HCLK (MHz) / 20 */ - ws = freq_hz / WAIT_STATE_FREQ_STEP_HZ; + ws = freq_hz / WAIT_STATE_FREQ_STEP_HZ; /* Enable data and instruction cache */ STM32_FLASH_ACR |= STM32_FLASH_ACR_DCEN | STM32_FLASH_ACR_ICEN | - STM32_FLASH_ACR_PRFTEN | ws; + STM32_FLASH_ACR_PRFTEN | ws; } void clock_init(void) @@ -240,26 +239,27 @@ void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles) } } -void clock_enable_module(enum module_id module, int enable) +test_mockable void clock_enable_module(enum module_id module, int enable) { if (module == MODULE_USB) { - if (enable) + if (enable) { + STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB; STM32_RCC_CRRCR |= RCC_CRRCR_HSI48O; - else + } else { STM32_RCC_CRRCR &= ~RCC_CRRCR_HSI48O; + STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB; + } } else if (module == MODULE_I2C) { if (enable) { /* Enable clocks to I2C modules if necessary */ - STM32_RCC_APB1ENR1 |= - STM32_RCC_APB1ENR1_I2C1EN | - STM32_RCC_APB1ENR1_I2C2EN | - STM32_RCC_APB1ENR1_I2C3EN; + STM32_RCC_APB1ENR1 |= STM32_RCC_APB1ENR1_I2C1EN | + STM32_RCC_APB1ENR1_I2C2EN | + STM32_RCC_APB1ENR1_I2C3EN; STM32_RCC_APB1ENR2 |= STM32_RCC_APB1ENR2_I2C4EN; } else { - STM32_RCC_APB1ENR1 &= - ~(STM32_RCC_APB1ENR1_I2C1EN | - STM32_RCC_APB1ENR1_I2C2EN | - STM32_RCC_APB1ENR1_I2C3EN); + STM32_RCC_APB1ENR1 &= ~(STM32_RCC_APB1ENR1_I2C1EN | + STM32_RCC_APB1ENR1_I2C2EN | + STM32_RCC_APB1ENR1_I2C3EN); STM32_RCC_APB1ENR2 &= ~STM32_RCC_APB1ENR2_I2C4EN; } } else if (module == MODULE_ADC) { @@ -269,9 +269,20 @@ void clock_enable_module(enum module_id module, int enable) STM32_RCC_APB2ENR_ADC345EN); else STM32_RCC_AHB2ENR &= ~(STM32_RCC_AHB2ENR_ADC12EN | - STM32_RCC_APB2ENR_ADC345EN); + STM32_RCC_APB2ENR_ADC345EN); } else { CPRINTS("stm32g4: enable clock module %d not supported", module); } } + +int clock_is_module_enabled(enum module_id module) +{ + if (module == MODULE_USB) + return !!(STM32_RCC_APB1ENR & STM32_RCC_PB1_USB); + else if (module == MODULE_I2C) + return !!(STM32_RCC_APB1ENR1 & STM32_RCC_APB1ENR1_I2C1EN); + else if (module == MODULE_ADC) + return !!(STM32_RCC_AHB2ENR & STM32_RCC_AHB2ENR_ADC12EN); + return 0; +} diff --git a/chip/stm32/clock-stm32h7.c b/chip/stm32/clock-stm32h7.c index ba233dbd76..1128626e06 100644 --- a/chip/stm32/clock-stm32h7.c +++ b/chip/stm32/clock-stm32h7.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,9 +13,7 @@ * but at least yields predictable behavior. */ - -#include - +#include "builtin/assert.h" #include "chipset.h" #include "clock.h" #include "common.h" @@ -29,9 +27,11 @@ #include "uart.h" #include "util.h" +#include + /* Check chip family and variant for compatibility */ #ifndef CHIP_FAMILY_STM32H7 -#error Source clock-stm32h7.c does not support this chip family. +#error Source clock-stm32h7.c does not support this chip family. #endif #ifndef CHIP_VARIANT_STM32H7X3 #error Unsupported chip variant. @@ -39,13 +39,13 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args) enum clock_osc { - OSC_HSI = 0, /* High-speed internal oscillator */ - OSC_CSI, /* Multi-speed internal oscillator: NOT IMPLEMENTED */ - OSC_HSE, /* High-speed external oscillator: NOT IMPLEMENTED */ - OSC_PLL, /* PLL */ + OSC_HSI = 0, /* High-speed internal oscillator */ + OSC_CSI, /* Multi-speed internal oscillator: NOT IMPLEMENTED */ + OSC_HSE, /* High-speed external oscillator: NOT IMPLEMENTED */ + OSC_PLL, /* PLL */ }; enum voltage_scale { @@ -57,12 +57,12 @@ enum voltage_scale { }; enum freq { - FREQ_1KHZ = 1000, - FREQ_32KHZ = 32 * FREQ_1KHZ, - FREQ_1MHZ = 1000000, - FREQ_2MHZ = 2 * FREQ_1MHZ, - FREQ_16MHZ = 16 * FREQ_1MHZ, - FREQ_64MHZ = 64 * FREQ_1MHZ, + FREQ_1KHZ = 1000, + FREQ_32KHZ = 32 * FREQ_1KHZ, + FREQ_1MHZ = 1000000, + FREQ_2MHZ = 2 * FREQ_1MHZ, + FREQ_16MHZ = 16 * FREQ_1MHZ, + FREQ_64MHZ = 64 * FREQ_1MHZ, FREQ_140MHZ = 140 * FREQ_1MHZ, FREQ_200MHZ = 200 * FREQ_1MHZ, FREQ_280MHZ = 280 * FREQ_1MHZ, @@ -144,13 +144,13 @@ static void clock_flash_latency(enum freq axi_freq, enum voltage_scale vos) * * @param output_freq The target output frequency. */ -static void clock_pll1_configure(enum freq output_freq) { +static void clock_pll1_configure(enum freq output_freq) +{ uint32_t divm = 4; // Input prescaler (16MHz max for PLL -- 64/4 ==> 16) - uint32_t divn; // Pll multiplier - uint32_t divp; // Output 1 prescaler + uint32_t divn; // Pll multiplier + uint32_t divp; // Output 1 prescaler - switch (output_freq) - { + switch (output_freq) { case FREQ_400MHZ: /* * PLL1 configuration: @@ -190,8 +190,8 @@ static void clock_pll1_configure(enum freq output_freq) { * Using VCO wide-range setting, STM32_RCC_PLLCFG_PLL1VCOSEL_WIDE, * requires input frequency to be between 2MHz and 16MHz. */ - ASSERT(FREQ_2MHZ <= (STM32_HSI_CLOCK/divm)); - ASSERT((STM32_HSI_CLOCK/divm) <= FREQ_16MHZ); + ASSERT(FREQ_2MHZ <= (STM32_HSI_CLOCK / divm)); + ASSERT((STM32_HSI_CLOCK / divm) <= FREQ_16MHZ); /* * Ensure that we actually reach the target frequency. @@ -199,14 +199,14 @@ static void clock_pll1_configure(enum freq output_freq) { ASSERT((STM32_HSI_CLOCK / divm * divn / divp) == output_freq); /* Configure PLL1 using 64 Mhz HSI as input */ - STM32_RCC_PLLCKSELR = STM32_RCC_PLLCKSEL_PLLSRC_HSI - | STM32_RCC_PLLCKSEL_DIVM1(divm); + STM32_RCC_PLLCKSELR = STM32_RCC_PLLCKSEL_PLLSRC_HSI | + STM32_RCC_PLLCKSEL_DIVM1(divm); /* in integer mode, wide range VCO with 16Mhz input, use divP */ - STM32_RCC_PLLCFGR = STM32_RCC_PLLCFG_PLL1VCOSEL_WIDE - | STM32_RCC_PLLCFG_PLL1RGE_8M_16M - | STM32_RCC_PLLCFG_DIVP1EN; - STM32_RCC_PLL1DIVR = STM32_RCC_PLLDIV_DIVP(divp) - | STM32_RCC_PLLDIV_DIVN(divn); + STM32_RCC_PLLCFGR = STM32_RCC_PLLCFG_PLL1VCOSEL_WIDE | + STM32_RCC_PLLCFG_PLL1RGE_8M_16M | + STM32_RCC_PLLCFG_DIVP1EN; + STM32_RCC_PLL1DIVR = STM32_RCC_PLLDIV_DIVP(divp) | + STM32_RCC_PLLDIV_DIVN(divn); } /** @@ -215,22 +215,22 @@ static void clock_pll1_configure(enum freq output_freq) { * @param sysclk The input system clock, after the system clock prescaler. * @return The bus clock speed selected and configured */ -static enum freq clock_peripheral_configure(enum freq sysclk) { - switch (sysclk) - { +static enum freq clock_peripheral_configure(enum freq sysclk) +{ + switch (sysclk) { case FREQ_64MHZ: /* Restore /1 HPRE (AHB prescaler) */ /* Disable downstream prescalers */ - STM32_RCC_D1CFGR = STM32_RCC_D1CFGR_HPRE_DIV1 - | STM32_RCC_D1CFGR_D1PPRE_DIV1 - | STM32_RCC_D1CFGR_D1CPRE_DIV1; + STM32_RCC_D1CFGR = STM32_RCC_D1CFGR_HPRE_DIV1 | + STM32_RCC_D1CFGR_D1PPRE_DIV1 | + STM32_RCC_D1CFGR_D1CPRE_DIV1; /* TODO(b/149512910): Adjust more peripheral prescalers */ return FREQ_64MHZ; case FREQ_400MHZ: /* Put /2 on HPRE (AHB prescaler) to keep at the 200MHz max */ - STM32_RCC_D1CFGR = STM32_RCC_D1CFGR_HPRE_DIV2 - | STM32_RCC_D1CFGR_D1PPRE_DIV1 - | STM32_RCC_D1CFGR_D1CPRE_DIV1; + STM32_RCC_D1CFGR = STM32_RCC_D1CFGR_HPRE_DIV2 | + STM32_RCC_D1CFGR_D1PPRE_DIV1 | + STM32_RCC_D1CFGR_D1CPRE_DIV1; /* TODO(b/149512910): Adjust more peripheral prescalers */ return FREQ_200MHZ; default: @@ -293,16 +293,16 @@ static void clock_switch_osc(enum clock_osc osc) static void switch_voltage_scale(enum voltage_scale vos) { - volatile uint32_t *const vos_reg = &STM32_PWR_D3CR; - const uint32_t vos_ready = STM32_PWR_D3CR_VOSRDY; - const uint32_t vos_mask = STM32_PWR_D3CR_VOSMASK; - const uint32_t vos_values[] = { - /* See note below about VOS0. */ - STM32_PWR_D3CR_VOS1, - STM32_PWR_D3CR_VOS1, - STM32_PWR_D3CR_VOS2, - STM32_PWR_D3CR_VOS3, - }; + volatile uint32_t *const vos_reg = &STM32_PWR_D3CR; + const uint32_t vos_ready = STM32_PWR_D3CR_VOSRDY; + const uint32_t vos_mask = STM32_PWR_D3CR_VOSMASK; + const uint32_t vos_values[] = { + /* See note below about VOS0. */ + STM32_PWR_D3CR_VOS1, + STM32_PWR_D3CR_VOS1, + STM32_PWR_D3CR_VOS2, + STM32_PWR_D3CR_VOS3, + }; BUILD_ASSERT(ARRAY_SIZE(vos_values) == VOLTAGE_SCALE_COUNT); /* @@ -344,7 +344,8 @@ static void clock_set_osc(enum clock_osc osc) case OSC_HSI: /* Switch to HSI */ clock_switch_osc(osc); - current_bus_freq = clock_peripheral_configure(target_sysclk_freq); + current_bus_freq = + clock_peripheral_configure(target_sysclk_freq); /* Use more optimized flash latency settings for 64-MHz ACLK */ clock_flash_latency(current_bus_freq, target_voltage_scale); /* Turn off the PLL1 to save power */ @@ -368,7 +369,8 @@ static void clock_set_osc(enum clock_osc osc) clock_pll1_configure(target_sysclk_freq); /* turn on PLL1 and wait until it's ready */ clock_enable_osc(OSC_PLL, true); - current_bus_freq = clock_peripheral_configure(target_sysclk_freq); + current_bus_freq = + clock_peripheral_configure(target_sysclk_freq); /* Increase flash latency before transition the clock */ clock_flash_latency(current_bus_freq, target_voltage_scale); @@ -381,7 +383,7 @@ static void clock_set_osc(enum clock_osc osc) hook_notify(HOOK_FREQ_CHANGE); } -void clock_enable_module(enum module_id module, int enable) +test_mockable void clock_enable_module(enum module_id module, int enable) { /* Assume we have a single task using MODULE_FAST_CPU */ if (module == MODULE_FAST_CPU) { @@ -399,6 +401,7 @@ void clock_enable_module(enum module_id module, int enable) static int idle_sleep_cnt; static int idle_dsleep_cnt; static uint64_t idle_dsleep_time_us; +static int idle_sleep_prevented_cnt; static int dsleep_recovery_margin_us = 1000000; /* STOP_MODE_LATENCY: delay to wake up from STOP mode with flash off in SVOS5 */ @@ -407,9 +410,9 @@ static int dsleep_recovery_margin_us = 1000000; static void low_power_init(void) { /* Clock LPTIM1 on the 32-kHz LSI for STOP mode time keeping */ - STM32_RCC_D2CCIP2R = (STM32_RCC_D2CCIP2R & - ~STM32_RCC_D2CCIP2_LPTIM1SEL_MASK) - | STM32_RCC_D2CCIP2_LPTIM1SEL_LSI; + STM32_RCC_D2CCIP2R = + (STM32_RCC_D2CCIP2R & ~STM32_RCC_D2CCIP2_LPTIM1SEL_MASK) | + STM32_RCC_D2CCIP2_LPTIM1SEL_LSI; /* configure LPTIM1 as our 1-Khz low power timer in STOP mode */ STM32_RCC_APB1LENR |= STM32_RCC_PB1_LPTIM1; @@ -427,16 +430,15 @@ static void low_power_init(void) STM32_EXTI_CPUIMR2 |= BIT(15); /* [15] wkup47: LPTIM1 wake-up */ /* optimize power vs latency in STOP mode */ - STM32_PWR_CR = (STM32_PWR_CR & ~STM32_PWR_CR_SVOS_MASK) - | STM32_PWR_CR_SVOS5 - | STM32_PWR_CR_FLPS; + STM32_PWR_CR = (STM32_PWR_CR & ~STM32_PWR_CR_SVOS_MASK) | + STM32_PWR_CR_SVOS5 | STM32_PWR_CR_FLPS; } void clock_refresh_console_in_use(void) { } -void lptim_interrupt(void) +static void lptim_interrupt(void) { STM32_LPTIM_ICR(1) = STM32_LPTIM_INT_CMPM; } @@ -463,6 +465,11 @@ static void set_lptim_event(int delay_us, uint16_t *lptim_cnt) *lptim_cnt = cnt; } +static bool timer_interrupt_pending(void) +{ + return task_is_irq_pending(IRQ_TIM(TIM_CLOCK32)); +} + void __idle(void) { timestamp_t t0; @@ -471,13 +478,59 @@ void __idle(void) uint16_t lptim0; while (1) { - asm volatile("cpsid i"); + interrupt_disable(); + /* + * Get timestamp with interrupts disabled. + * This value is used as a base to calculate timestamp after + * wake from deep sleep. In combination with next_delay it gives + * information how long the CPU can sleep. The timestamp can + * point to the previous "epoch" when timer overflowed after + * interrupts were disabled, since clksrc_high (which keeps + * higher 32 bits of the timestamp) will not be updated. + */ t0 = get_time(); + + /* + * Get time to next event. + * After disabling interrupts, event timestamp + * (__hw_clock_event_get()) is frozen, because + * process_timers(), responsible for updating the + * next event value with __hw_clock_event_set(), + * can't be called. There is a risk that timer overflow + * occurred after interrupts were disabled and obtained + * event timestamp points to previous "epoch". We will + * check that later. + */ next_delay = __hw_clock_event_get() - t0.le.lo; + /* + * Repeat idle enter procedure when timer interrupt is pending + * (eg. overflow occurred after disabling interrupts). To work + * properly, this code assumes that timer interrupt is enabled + * in NVIC and interrupt is generated on timer overflow. + */ + if (timer_interrupt_pending()) { + idle_sleep_prevented_cnt++; + + /* Enable interrupts to handle detected overflow. */ + interrupt_enable(); + + /* Repeat idle enter procedure. */ + continue; + } + if (DEEP_SLEEP_ALLOWED && next_delay > LPTIM_PERIOD_US + STOP_MODE_LATENCY) { + /* + * Sleep time MUST be smaller than watchdog period. + * Otherwise watchdog will wake us from deep sleep + * which is not what we want. Please note that this + * assert won't fire if we are already part way through + * the watchdog period. + */ + ASSERT(next_delay < CONFIG_WATCHDOG_PERIOD_MS * MSEC); + /* deep-sleep in STOP mode */ idle_dsleep_cnt++; @@ -492,7 +545,7 @@ void __idle(void) /* ensure outstanding memory transactions complete */ asm volatile("dsb"); - asm("wfi"); + cpu_enter_suspend_mode(); CPU_SCB_SYSCTRL &= ~0x4; @@ -527,9 +580,9 @@ void __idle(void) idle_sleep_cnt++; /* normal idle : only CPU clock stopped */ - asm("wfi"); + cpu_enter_suspend_mode(); } - asm volatile("cpsie i"); + interrupt_enable(); } } @@ -537,22 +590,23 @@ void __idle(void) /** * Print low power idle statistics */ -static int command_idle_stats(int argc, char **argv) +static int command_idle_stats(int argc, const char **argv) { timestamp_t ts = get_time(); ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); ccprintf("Time spent in deep-sleep: %.6llds\n", - idle_dsleep_time_us); + idle_dsleep_time_us); + ccprintf("Num of prevented sleep: %d\n", + idle_sleep_prevented_cnt); ccprintf("Total time on: %.6llds\n", ts.val); ccprintf("Deep-sleep closest to wake deadline: %dus\n", - dsleep_recovery_margin_us); + dsleep_recovery_margin_us); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, - "", +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", "Print last idle stats"); #endif /* CONFIG_CMD_IDLE_STATS */ #endif /* CONFIG_LOW_POWER_IDLE */ @@ -584,11 +638,11 @@ void clock_init(void) * by putting it on the fixed 64-Mhz HSI clock. * per_ck is clocked directly by the HSI (as per the default settings). */ - STM32_RCC_D2CCIP1R = (STM32_RCC_D2CCIP1R & - ~(STM32_RCC_D2CCIP1R_SPI123SEL_MASK | - STM32_RCC_D2CCIP1R_SPI45SEL_MASK)) - | STM32_RCC_D2CCIP1R_SPI123SEL_PERCK - | STM32_RCC_D2CCIP1R_SPI45SEL_HSI; + STM32_RCC_D2CCIP1R = + (STM32_RCC_D2CCIP1R & ~(STM32_RCC_D2CCIP1R_SPI123SEL_MASK | + STM32_RCC_D2CCIP1R_SPI45SEL_MASK)) | + STM32_RCC_D2CCIP1R_SPI123SEL_PERCK | + STM32_RCC_D2CCIP1R_SPI45SEL_HSI; /* Use more optimized flash latency settings for ACLK = HSI = 64 Mhz */ clock_flash_latency(FREQ_64MHZ, VOLTAGE_SCALE3); @@ -603,7 +657,7 @@ void clock_init(void) #endif } -static int command_clock(int argc, char **argv) +static int command_clock(int argc, const char **argv) { if (argc >= 2) { if (!strcasecmp(argv[1], "hsi")) @@ -616,5 +670,5 @@ static int command_clock(int argc, char **argv) ccprintf("Clock frequency is now %d Hz\n", clock_get_freq()); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(clock, command_clock, - "hsi | pll", "Set clock frequency"); +DECLARE_CONSOLE_COMMAND(clock, command_clock, "hsi | pll", + "Set clock frequency"); diff --git a/chip/stm32/clock-stm32l.c b/chip/stm32/clock-stm32l.c index a4e9dd7cdf..f4e69e4dad 100644 --- a/chip/stm32/clock-stm32l.c +++ b/chip/stm32/clock-stm32l.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -37,9 +37,9 @@ static int fake_hibernate; #define MSI_1MHZ_CLOCK BIT(20) enum clock_osc { - OSC_INIT = 0, /* Uninitialized */ - OSC_HSI, /* High-speed oscillator */ - OSC_MSI, /* Med-speed oscillator @ 1 MHz */ + OSC_INIT = 0, /* Uninitialized */ + OSC_HSI, /* High-speed oscillator */ + OSC_MSI, /* Med-speed oscillator @ 1 MHz */ }; static int freq; @@ -86,8 +86,8 @@ static void clock_set_osc(enum clock_osc osc) switch (osc) { case OSC_HSI: /* Ensure that HSI is ON */ - wait_for_ready(&STM32_RCC_CR, - STM32_RCC_CR_HSION, STM32_RCC_CR_HSIRDY); + wait_for_ready(&STM32_RCC_CR, STM32_RCC_CR_HSION, + STM32_RCC_CR_HSIRDY); /* Disable LPSDSR */ STM32_PWR_CR &= ~STM32_PWR_CR_LPSDSR; @@ -122,7 +122,7 @@ static void clock_set_osc(enum clock_osc osc) STM32_RCC_CFGR = STM32_RCC_CFGR_SW_HSI; /* RM says to check SWS bits to make sure HSI is the sysclock */ while ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) != - STM32_RCC_CFGR_SWS_HSI) + STM32_RCC_CFGR_SWS_HSI) ; /* Disable MSI */ @@ -137,14 +137,14 @@ static void clock_set_osc(enum clock_osc osc) (STM32_RCC_ICSCR & ~STM32_RCC_ICSCR_MSIRANGE_MASK) | STM32_RCC_ICSCR_MSIRANGE_1MHZ; /* Ensure that MSI is ON */ - wait_for_ready(&STM32_RCC_CR, - STM32_RCC_CR_MSION, STM32_RCC_CR_MSIRDY); + wait_for_ready(&STM32_RCC_CR, STM32_RCC_CR_MSION, + STM32_RCC_CR_MSIRDY); /* Switch to MSI */ STM32_RCC_CFGR = STM32_RCC_CFGR_SW_MSI; /* RM says to check SWS bits to make sure MSI is the sysclock */ while ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) != - STM32_RCC_CFGR_SWS_MSI) + STM32_RCC_CFGR_SWS_MSI) ; /* @@ -195,28 +195,40 @@ static void clock_set_osc(enum clock_osc osc) } } -void clock_enable_module(enum module_id module, int enable) +static uint64_t clock_mask; + +test_mockable void clock_enable_module(enum module_id module, int enable) { - static uint32_t clock_mask; - int new_mask; + uint64_t new_mask; if (enable) - new_mask = clock_mask | BIT(module); + new_mask = clock_mask | BIT_ULL(module); else - new_mask = clock_mask & ~BIT(module); + new_mask = clock_mask & ~BIT_ULL(module); /* Only change clock if needed */ if ((!!new_mask) != (!!clock_mask)) { - /* Flush UART before switching clock speed */ cflush(); clock_set_osc(new_mask ? OSC_HSI : OSC_MSI); } + if (module == MODULE_USB) { + if (enable) + STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB; + else + STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB; + } + clock_mask = new_mask; } +int clock_is_module_enabled(enum module_id module) +{ + return !!(clock_mask & BIT_ULL(module)); +} + #ifdef CONFIG_STM32L_FAKE_HIBERNATE /* * This is for NOT having enough hibernate (more precisely, the stand-by mode) @@ -301,7 +313,7 @@ static void fake_hibernate_power_button_hook(void) } } DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, fake_hibernate_power_button_hook, - HOOK_PRIO_DEFAULT); + HOOK_PRIO_DEFAULT); static void fake_hibernate_lid_hook(void) { @@ -352,7 +364,7 @@ static void clock_chipset_shutdown(void) DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, clock_chipset_shutdown, HOOK_PRIO_DEFAULT); DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, clock_chipset_shutdown, HOOK_PRIO_DEFAULT); -static int command_clock(int argc, char **argv) +static int command_clock(int argc, const char **argv) { if (argc >= 2) { if (!strcasecmp(argv[1], "hsi")) @@ -366,6 +378,5 @@ static int command_clock(int argc, char **argv) ccprintf("Clock frequency is now %d Hz\n", freq); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(clock, command_clock, - "hsi | msi", +DECLARE_CONSOLE_COMMAND(clock, command_clock, "hsi | msi", "Set clock frequency"); diff --git a/chip/stm32/clock-stm32l4.c b/chip/stm32/clock-stm32l4.c index 1bba787779..fd59d2aa3a 100644 --- a/chip/stm32/clock-stm32l4.c +++ b/chip/stm32/clock-stm32l4.c @@ -1,32 +1,58 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -/* Clocks and power management settings */ +/* Clocks and power management settings for STM32L4xx as well as STM32L5xx. */ +#include "builtin/assert.h" #include "chipset.h" +#include "clock-l4.h" #include "clock.h" #include "common.h" #include "console.h" #include "cpu.h" #include "hooks.h" +#include "host_command.h" #include "registers.h" +#include "rtc.h" +#include "timer.h" +#include "uart.h" #include "util.h" +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_CLOCK, outstr) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args) + /* High-speed oscillator is 16 MHz */ #define STM32_HSI_CLOCK 16000000 /* Multi-speed oscillator is 4 MHz by default */ #define STM32_MSI_CLOCK 4000000 +/* Real Time Clock (RTC) */ + +#ifdef CONFIG_STM32_CLOCK_HSE_HZ +#define RTC_PREDIV_A 39 +#define RTC_FREQ ((STM32L4_RTC_REQ) / (RTC_PREDIV_A + 1)) /* Hz */ +#else /* from LSI clock */ +#define RTC_PREDIV_A 1 +#define RTC_FREQ (STM32L4_LSI_CLOCK / (RTC_PREDIV_A + 1)) /* Hz */ +#endif +#define RTC_PREDIV_S (RTC_FREQ - 1) +/* + * Scaling factor to ensure that the intermediate values computed from/to the + * RTC frequency are fitting in a 32-bit integer. + */ +#define SCALING 1000 + enum clock_osc { - OSC_INIT = 0, /* Uninitialized */ - OSC_HSI, /* High-speed internal oscillator */ - OSC_MSI, /* Multi-speed internal oscillator */ -#ifdef STM32_HSE_CLOCK /* Allows us to catch absence of HSE at comiple time */ - OSC_HSE, /* High-speed external oscillator */ + OSC_INIT = 0, /* Uninitialized */ + OSC_HSI, /* High-speed internal oscillator */ + OSC_MSI, /* Multi-speed internal oscillator */ +#ifdef STM32_HSE_CLOCK /* Allows us to catch absence of HSE at comiple time */ + OSC_HSE, /* High-speed external oscillator */ #endif - OSC_PLL, /* PLL */ + OSC_PLL, /* PLL */ }; static int freq = STM32_MSI_CLOCK; @@ -71,6 +97,9 @@ static void clock_enable_osc(enum clock_osc osc) break; #ifdef STM32_HSE_CLOCK case OSC_HSE: +#ifdef STM32_HSE_BYP + STM32_RCC_CR |= STM32_RCC_CR_HSEBYP; +#endif ready = STM32_RCC_CR_HSERDY; on = STM32_RCC_CR_HSEON; break; @@ -92,6 +121,7 @@ static void clock_switch_osc(enum clock_osc osc) { uint32_t sw; uint32_t sws; + uint32_t val; switch (osc) { case OSC_HSI: @@ -115,9 +145,11 @@ static void clock_switch_osc(enum clock_osc osc) default: return; } - - STM32_RCC_CFGR = sw; - while ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) != sws) + val = STM32_RCC_CFGR; + val &= ~STM32_RCC_CFGR_SW; + val |= sw; + STM32_RCC_CFGR = val; + while ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MSK) != sws) ; } @@ -131,12 +163,61 @@ static void clock_switch_osc(enum clock_osc osc) * 5. Enable the desired PLL outputs by configuring PLLPEN, PLLQEN, PLLREN * in RCC_PLLCFGR. */ -static int stm32_configure_pll(enum clock_osc osc, - uint8_t m, uint8_t n, uint8_t r) +static int stm32_configure_pll(enum clock_osc osc, uint8_t m, uint8_t n, + uint8_t r) { uint32_t val; + bool pll_unchanged; int f; + val = STM32_RCC_PLLCFGR; + pll_unchanged = true; + + if (osc == OSC_HSI) + if ((val & STM32_RCC_PLLCFGR_PLLSRC_MSK) != + STM32_RCC_PLLCFGR_PLLSRC_HSI) + pll_unchanged = false; + + if (osc == OSC_MSI) + if ((val & STM32_RCC_PLLCFGR_PLLSRC_MSK) != + STM32_RCC_PLLCFGR_PLLSRC_MSI) + pll_unchanged = false; + +#ifdef STM32_HSE_CLOCK + if (osc == OSC_HSE) + if ((val & STM32_RCC_PLLCFGR_PLLSRC_MSK) != + STM32_RCC_PLLCFGR_PLLSRC_HSE) + pll_unchanged = false; +#endif + + if ((val & STM32_RCC_PLLCFGR_PLLM_MSK) != + ((m - 1) << STM32_RCC_PLLCFGR_PLLM_POS)) + pll_unchanged = false; + + if ((val & STM32_RCC_PLLCFGR_PLLN_MSK) != + (n << STM32_RCC_PLLCFGR_PLLN_POS)) + pll_unchanged = false; + + if ((val & STM32_RCC_PLLCFGR_PLLR_MSK) != + (((r >> 1) - 1) << STM32_RCC_PLLCFGR_PLLR_POS)) + pll_unchanged = false; + + if (pll_unchanged == true) { + if (osc == OSC_HSI) + f = STM32_HSI_CLOCK; + else + f = STM32_MSI_CLOCK; + + if (!(STM32_RCC_CR & STM32_RCC_CR_PLLRDY)) { + STM32_RCC_CR |= STM32_RCC_CR_PLLON; + STM32_RCC_PLLCFGR |= STM32_RCC_PLLCFGR_PLLREN; + + while ((STM32_RCC_CR & STM32_RCC_CR_PLLRDY) == 0) + ; + } + /* (f * n) shouldn't overflow based on their max values */ + return (f * n / m / r); + } /* 1 */ STM32_RCC_CR &= ~STM32_RCC_CR_PLLON; @@ -147,7 +228,7 @@ static int stm32_configure_pll(enum clock_osc osc, /* 3 */ val = STM32_RCC_PLLCFGR; - val &= ~STM32_RCC_PLLCFGR_PLLSRC_MASK; + val &= ~STM32_RCC_PLLCFGR_PLLSRC_MSK; switch (osc) { case OSC_HSI: val |= STM32_RCC_PLLCFGR_PLLSRC_HSI; @@ -168,27 +249,27 @@ static int stm32_configure_pll(enum clock_osc osc, } ASSERT(m > 0 && m < 9); - val &= ~STM32_RCC_PLLCFGR_PLLM_MASK; - val |= (m - 1) << STM32_RCC_PLLCFGR_PLLM_SHIFT; + val &= ~STM32_RCC_PLLCFGR_PLLM_MSK; + val |= (m - 1) << STM32_RCC_PLLCFGR_PLLM_POS; /* Max and min values are from TRM */ ASSERT(n > 7 && n < 87); - val &= ~STM32_RCC_PLLCFGR_PLLN_MASK; - val |= n << STM32_RCC_PLLCFGR_PLLN_SHIFT; + val &= ~STM32_RCC_PLLCFGR_PLLN_MSK; + val |= n << STM32_RCC_PLLCFGR_PLLN_POS; - val &= ~STM32_RCC_PLLCFGR_PLLR_MASK; + val &= ~STM32_RCC_PLLCFGR_PLLR_MSK; switch (r) { case 2: - val |= 0 << STM32_RCC_PLLCFGR_PLLR_SHIFT; + val |= 0 << STM32_RCC_PLLCFGR_PLLR_POS; break; case 4: - val |= 1 << STM32_RCC_PLLCFGR_PLLR_SHIFT; + val |= 1 << STM32_RCC_PLLCFGR_PLLR_POS; break; case 6: - val |= 2 << STM32_RCC_PLLCFGR_PLLR_SHIFT; + val |= 2 << STM32_RCC_PLLCFGR_PLLR_POS; break; case 8: - val |= 3 << STM32_RCC_PLLCFGR_PLLR_SHIFT; + val |= 3 << STM32_RCC_PLLCFGR_PLLR_POS; break; default: return -1; @@ -201,7 +282,7 @@ static int stm32_configure_pll(enum clock_osc osc, /* 5 */ val = STM32_RCC_PLLCFGR; - val |= 1 << STM32_RCC_PLLCFGR_PLLREN_SHIFT; + val |= 1 << STM32_RCC_PLLCFGR_PLLREN_POS; STM32_RCC_PLLCFGR = val; /* (f * n) shouldn't overflow based on their max values */ @@ -229,8 +310,8 @@ static void clock_set_osc(enum clock_osc osc, enum clock_osc pll_osc) /* Ensure that HSI is ON */ clock_enable_osc(osc); - /* Disable LPSDSR */ - STM32_PWR_CR &= ~STM32_PWR_CR_LPSDSR; + /* Set HSI as system clock after exiting stop mode */ + STM32_RCC_CFGR |= STM32_RCC_CFGR_STOPWUCK; /* Switch to HSI */ clock_switch_osc(osc); @@ -243,21 +324,22 @@ static void clock_set_osc(enum clock_osc osc, enum clock_osc pll_osc) case OSC_MSI: /* Switch to MSI @ 1MHz */ - STM32_RCC_ICSCR = - (STM32_RCC_ICSCR & ~STM32_RCC_ICSCR_MSIRANGE_MASK) | - STM32_RCC_ICSCR_MSIRANGE_1MHZ; + STM32_RCC_CR = (STM32_RCC_CR & ~STM32_RCC_ICSCR_MSIRANGE_MASK) | + STM32_RCC_ICSCR_MSIRANGE_1MHZ; /* Ensure that MSI is ON */ clock_enable_osc(osc); + /* + * Set MSI as system clock after exiting stop mode + */ + STM32_RCC_CFGR &= ~STM32_RCC_CFGR_STOPWUCK; + /* Switch to MSI */ clock_switch_osc(osc); /* Disable HSI */ STM32_RCC_CR &= ~STM32_RCC_CR_HSION; - /* Enable LPSDSR */ - STM32_PWR_CR |= STM32_PWR_CR_LPSDSR; - freq = STM32_MSI_CLOCK; break; @@ -271,7 +353,7 @@ static void clock_set_osc(enum clock_osc osc, enum clock_osc pll_osc) /* Disable other clock sources */ STM32_RCC_CR &= ~(STM32_RCC_CR_MSION | STM32_RCC_CR_HSION | - STM32_RCC_CR_PLLON); + STM32_RCC_CR_PLLON); freq = STM32_HSE_CLOCK; @@ -279,20 +361,76 @@ static void clock_set_osc(enum clock_osc osc, enum clock_osc pll_osc) #endif case OSC_PLL: /* Ensure that source clock is stable */ - clock_enable_osc(pll_osc); - - /* Configure PLLCFGR */ - freq = stm32_configure_pll(pll_osc, STM32_PLLM, - STM32_PLLN, STM32_PLLR); + if (pll_osc == OSC_INIT) { + if ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MSK) != + STM32_RCC_CFGR_SWS_PLL) { + STM32_RCC_CFGR |= STM32_RCC_CFGR_STOPWUCK; + clock_enable_osc(OSC_HSI); + freq = stm32_configure_pll(OSC_HSI, STM32_PLLM, + STM32_PLLN, + STM32_PLLR); + } else { + /* already set PLL, skip */ + freq = STM32_HSI_CLOCK * STM32_PLLN / + STM32_PLLM / STM32_PLLR; + break; + } + } else { + clock_enable_osc(pll_osc); + /* Configure PLLCFGR */ + freq = stm32_configure_pll(pll_osc, STM32_PLLM, + STM32_PLLN, STM32_PLLR); + } ASSERT(freq > 0); - /* Adjust flash latency as instructed in TRM */ - val = STM32_FLASH_ACR; - val &= ~STM32_FLASH_ACR_LATENCY_MASK; - /* Flash 4 wait state. TODO: Should depend on freq. */ - val |= 4 << STM32_FLASH_ACR_LATENCY_SHIFT; - STM32_FLASH_ACR = val; - while (STM32_FLASH_ACR != val) + /* Change to Range 1 if Freq > 26MHz */ + if (freq > 26000000U) { + /* Set VCO range 1 */ + val = STM32_RCC_CR; + val &= ~PWR_CR1_VOS_MSK; + val |= PWR_CR1_VOS_0; + STM32_RCC_CR = val; + + /* + * Set Flash latency according to frequency + */ + val = STM32_FLASH_ACR; + val &= ~STM32_FLASH_ACR_LATENCY_MASK; + if (freq <= 16000000U) { + /* nothing */ + } else if (freq <= 32000000U) { + val |= 1; + } else if (freq <= 48000000U) { + val |= 2; + } else if (freq <= 64000000U) { + val |= 3; + } else if (freq <= 80000000U) { + val |= 4; + } else { + val |= 4; + CPUTS("Incorrect Frequency setting in VOS1!\n"); + } + STM32_FLASH_ACR = val; + } else { + val = STM32_FLASH_ACR; + val &= ~STM32_FLASH_ACR_LATENCY_MASK; + + if (freq <= 6000000U) { + /* nothing */ + } else if (freq <= 12000000U) { + val |= 1; + } else if (freq <= 18000000U) { + val |= 2; + } else if (freq <= 26000000U) { + val |= 3; + } else { + val |= 4; + CPUTS("Incorrect Frequency setting in VOS2!\n"); + } + STM32_FLASH_ACR = val; + } + + while (val != STM32_FLASH_ACR) ; /* Switch to PLL */ @@ -313,35 +451,158 @@ static void clock_set_osc(enum clock_osc osc, enum clock_osc pll_osc) } } -void clock_enable_module(enum module_id module, int enable) +static uint64_t clock_mask; + +test_mockable void clock_enable_module(enum module_id module, int enable) { - static uint32_t clock_mask; - int new_mask; + uint64_t new_mask; if (enable) - new_mask = clock_mask | BIT(module); + new_mask = clock_mask | BIT_ULL(module); else - new_mask = clock_mask & ~BIT(module); + new_mask = clock_mask & ~BIT_ULL(module); /* Only change clock if needed */ - if ((!!new_mask) != (!!clock_mask)) { + if (new_mask == clock_mask) + return; + + if (module == MODULE_ADC) { + STM32_RCC_APB2ENR |= STM32_RCC_PB2_SYSCFGEN; + STM32_RCC_APB1ENR1 |= STM32_RCC_PB1_PWREN; + + /* ADC select bit 28/29 */ + STM32_RCC_CCIPR &= ~STM32_RCC_CCIPR_ADCSEL_MSK; + STM32_RCC_CCIPR |= + (STM32_RCC_CCIPR_ADCSEL_0 | STM32_RCC_CCIPR_ADCSEL_1); + /* ADC clock enable */ + if (enable) + STM32_RCC_AHB2ENR |= STM32_RCC_HB2_ADC1; + else + STM32_RCC_AHB2ENR &= ~STM32_RCC_HB2_ADC1; + } else if (module == MODULE_SPI_FLASH) { + if (enable) + STM32_RCC_APB1ENR1 |= STM32_RCC_PB1_SPI2; + else + STM32_RCC_APB1ENR1 &= ~STM32_RCC_PB1_SPI2; + } else if (module == MODULE_SPI || module == MODULE_SPI_CONTROLLER) { + if (enable) + STM32_RCC_APB2ENR |= STM32_RCC_APB2ENR_SPI1EN; + else if ((new_mask & + (BIT(MODULE_SPI) | BIT(MODULE_SPI_CONTROLLER))) == 0) + STM32_RCC_APB2ENR &= ~STM32_RCC_APB2ENR_SPI1EN; + } else if (module == MODULE_USB) { +#ifdef CHIP_FAMILY_STM32L5 + if (enable) { + /* Keep USB subsystem under reset for now. */ + STM32_RCC_APB1RSTR2 |= STM32_RCC_APB1RSTR2_USBFSRST; + + /* Enable power to the USB domain. */ + STM32_PWR_CR2 |= STM32_PWR_CR2_USV; + + /* Enable internal 48 MHz RC oscillator. */ + wait_for_ready(&STM32_RCC_CRRCR, + STM32_RCC_CRRCR_HSI48ON, + STM32_RCC_CRRCR_HSI48RDY); + + /* Enable USB device clock. */ + STM32_RCC_APB1ENR2 |= STM32_RCC_APB1ENR2_USBFSEN; - /* Flush UART before switching clock speed */ - cflush(); + /* 48 MHz clock is stable, release USB reset. */ + STM32_RCC_APB1RSTR2 &= ~STM32_RCC_APB1RSTR2_USBFSRST; - clock_set_osc(new_mask ? OSC_HSI : OSC_MSI, OSC_INIT); + } else { + STM32_RCC_APB1ENR2 &= ~STM32_RCC_APB1ENR2_USBFSEN; + STM32_CRS_CR &= + ~(STM32_CRS_CR_CEN | STM32_CRS_CR_AUTOTRIMEN); + STM32_RCC_CRRCR &= ~STM32_RCC_CRRCR_HSI48ON; + STM32_PWR_CR2 &= ~STM32_PWR_CR2_USV; + } +#endif } clock_mask = new_mask; } +int clock_is_module_enabled(enum module_id module) +{ + return !!(clock_mask & BIT_ULL(module)); +} + +void rtc_init(void) +{ + /* Enable RTC Alarm in EXTI */ + STM32_EXTI_RTSR |= EXTI_RTC_ALR_EVENT; + task_enable_irq(STM32_IRQ_RTC_ALARM); + + /* RTC was initilized, avoid initialization again */ + if (STM32_RTC_ISR & STM32_RTC_ISR_INITS) + return; + + rtc_unlock_regs(); + + /* Enter RTC initialize mode */ + STM32_RTC_ISR |= STM32_RTC_ISR_INIT; + while (!(STM32_RTC_ISR & STM32_RTC_ISR_INITF)) + ; + + /* Set clock prescalars */ + STM32_RTC_PRER = (RTC_PREDIV_A << 16) | RTC_PREDIV_S; + + /* Start RTC timer */ + STM32_RTC_ISR &= ~STM32_RTC_ISR_INIT; + while (STM32_RTC_ISR & STM32_RTC_ISR_INITF) + ; + + /* Enable RTC alarm interrupt */ + STM32_RTC_CR |= STM32_RTC_CR_ALRAIE | STM32_RTC_CR_BYPSHAD; + + rtc_lock_regs(); +} + +#if defined(CONFIG_CMD_RTC) || defined(CONFIG_HOSTCMD_RTC) +void rtc_set(uint32_t sec) +{ + struct rtc_time_reg rtc; + + sec_to_rtc(sec, &rtc); + rtc_unlock_regs(); + + /* Disable alarm */ + STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE; + + /* Enter RTC initialize mode */ + STM32_RTC_ISR |= STM32_RTC_ISR_INIT; + while (!(STM32_RTC_ISR & STM32_RTC_ISR_INITF)) + ; + + /* Set clock prescalars */ + STM32_RTC_PRER = (RTC_PREDIV_A << 16) | RTC_PREDIV_S; + + STM32_RTC_TR = rtc.rtc_tr; + STM32_RTC_DR = rtc.rtc_dr; + /* Start RTC timer */ + STM32_RTC_ISR &= ~STM32_RTC_ISR_INIT; + + rtc_lock_regs(); +} +#endif + void clock_init(void) { #ifdef STM32_HSE_CLOCK clock_set_osc(OSC_PLL, OSC_HSE); +#else +#ifdef STM32_USE_PLL + clock_set_osc(OSC_PLL, OSC_INIT); #else clock_set_osc(OSC_HSI, OSC_INIT); #endif +#endif + +#ifdef CONFIG_LOW_POWER_IDLE + low_power_init(); + rtc_init(); +#endif } static void clock_chipset_startup(void) @@ -360,7 +621,7 @@ static void clock_chipset_shutdown(void) DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, clock_chipset_shutdown, HOOK_PRIO_DEFAULT); DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, clock_chipset_shutdown, HOOK_PRIO_DEFAULT); -static int command_clock(int argc, char **argv) +static int command_clock(int argc, const char **argv) { if (argc >= 2) { if (!strcasecmp(argv[1], "hsi")) @@ -386,7 +647,491 @@ static int command_clock(int argc, char **argv) DECLARE_CONSOLE_COMMAND(clock, command_clock, "hsi | msi" #ifdef STM32_HSE_CLOCK - " | hse | pll" + " | hse" #endif - , + " | pll", "Set clock frequency"); + +uint32_t rtcss_to_us(uint32_t rtcss) +{ + return ((RTC_PREDIV_S - (rtcss & 0x7FFF)) * (SECOND / SCALING) / + (RTC_FREQ / SCALING)); +} + +uint32_t us_to_rtcss(uint32_t us) +{ + return (RTC_PREDIV_S - + (us * (RTC_FREQ / SCALING) / (SECOND / SCALING))); +} + +/* Convert decimal to BCD */ +static uint8_t u8_to_bcd(uint8_t val) +{ + /* Fast division by 10 (when lacking HW div) */ + uint32_t quot = ((uint32_t)val * 0xCCCD) >> 19; + uint32_t rem = val - quot * 10; + + return rem | (quot << 4); +} + +/* Convert between RTC regs in BCD and seconds */ +static uint32_t rtc_tr_to_sec(uint32_t rtc_tr) +{ + uint32_t sec; + + /* convert the hours field */ + sec = (((rtc_tr & RTC_TR_HT) >> RTC_TR_HT_POS) * 10 + + ((rtc_tr & RTC_TR_HU) >> RTC_TR_HU_POS)) * + 3600; + /* convert the minutes field */ + sec += (((rtc_tr & RTC_TR_MNT) >> RTC_TR_MNT_POS) * 10 + + ((rtc_tr & RTC_TR_MNU) >> RTC_TR_MNU_POS)) * + 60; + /* convert the seconds field */ + sec += ((rtc_tr & RTC_TR_ST) >> RTC_TR_ST_POS) * 10 + + (rtc_tr & RTC_TR_SU); + return sec; +} + +static uint32_t sec_to_rtc_tr(uint32_t sec) +{ + uint32_t rtc_tr; + uint8_t hour; + uint8_t min; + + sec %= SECS_PER_DAY; + /* convert the hours field */ + hour = sec / 3600; + rtc_tr = u8_to_bcd(hour) << 16; + /* convert the minutes field */ + sec -= hour * 3600; + min = sec / 60; + rtc_tr |= u8_to_bcd(min) << 8; + /* convert the seconds field */ + sec -= min * 60; + rtc_tr |= u8_to_bcd(sec); + + return rtc_tr; +} + +/* Register setup before RTC alarm is allowed for update */ +static void pre_work_set_rtc_alarm(void) +{ + rtc_unlock_regs(); + + /* Make sure alarm is disabled */ + STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE; + while (!(STM32_RTC_ISR & STM32_RTC_ISR_ALRAWF)) + ; + STM32_RTC_ISR &= ~STM32_RTC_ISR_ALRAF; +#ifdef STM32_EXTI_RPR + /* Separate rising and falling edge pending registers. */ + STM32_EXTI_RPR = BIT(18); + STM32_EXTI_FPR = BIT(18); +#else + /* One combined rising/falling edge pending registers. */ + STM32_EXTI_PR = BIT(18); +#endif +} + +/* Register setup after RTC alarm is updated */ +static void post_work_set_rtc_alarm(void) +{ + /* Enable alarm and alarm interrupt */ + STM32_EXTI_IMR |= BIT(18); + STM32_EXTI_RTSR |= BIT(18); + STM32_RTC_CR |= (STM32_RTC_CR_ALRAE); + + rtc_lock_regs(); +} + +#ifdef CONFIG_HOSTCMD_RTC +static struct wake_time host_wake_time; + +bool is_host_wake_alarm_expired(timestamp_t ts) +{ + return host_wake_time.ts.val && + timestamp_expired(host_wake_time.ts, &ts); +} + +void restore_host_wake_alarm(void) +{ + if (!host_wake_time.ts.val) + return; + + pre_work_set_rtc_alarm(); + + /* Set alarm time */ + STM32_RTC_ALRMAR = host_wake_time.rtc_alrmar; + + post_work_set_rtc_alarm(); +} + +static uint32_t rtc_dr_to_sec(uint32_t rtc_dr) +{ + struct calendar_date time; + uint32_t sec; + + time.year = + (((rtc_dr & 0xf00000) >> 20) * 10 + ((rtc_dr & 0xf0000) >> 16)); + time.month = (((rtc_dr & 0x1000) >> 12) * 10 + ((rtc_dr & 0xf00) >> 8)); + time.day = ((rtc_dr & 0x30) >> 4) * 10 + (rtc_dr & 0xf); + + sec = date_to_sec(time); + + return sec; +} + +static uint32_t sec_to_rtc_dr(uint32_t sec) +{ + struct calendar_date time; + uint32_t rtc_dr; + + time = sec_to_date(sec); + + rtc_dr = u8_to_bcd(time.year) << 16; + rtc_dr |= u8_to_bcd(time.month) << 8; + rtc_dr |= u8_to_bcd(time.day); + + return rtc_dr; +} +#endif + +uint32_t rtc_to_sec(const struct rtc_time_reg *rtc) +{ + uint32_t sec = 0; + +#ifdef CONFIG_HOSTCMD_RTC + sec = rtc_dr_to_sec(rtc->rtc_dr); +#endif + return sec + (rtcss_to_us(rtc->rtc_ssr) / SECOND) + + rtc_tr_to_sec(rtc->rtc_tr); +} + +void sec_to_rtc(uint32_t sec, struct rtc_time_reg *rtc) +{ + rtc->rtc_dr = 0; +#ifdef CONFIG_HOSTCMD_RTC + rtc->rtc_dr = sec_to_rtc_dr(sec); +#endif + rtc->rtc_tr = sec_to_rtc_tr(sec); + rtc->rtc_ssr = 0; +} + +/* Return sub-10-sec time diff between two rtc readings + * + * Note: this function assumes rtc0 was sampled before rtc1. + * Additionally, this function only looks at the difference mod 10 + * seconds. + */ +uint32_t get_rtc_diff(const struct rtc_time_reg *rtc0, + const struct rtc_time_reg *rtc1) +{ + uint32_t rtc0_val, rtc1_val, diff; + + rtc0_val = (rtc0->rtc_tr & RTC_TR_SU) * SECOND + + rtcss_to_us(rtc0->rtc_ssr); + rtc1_val = (rtc1->rtc_tr & RTC_TR_SU) * SECOND + + rtcss_to_us(rtc1->rtc_ssr); + diff = rtc1_val; + if (rtc1_val < rtc0_val) { + /* rtc_ssr has wrapped, since we assume rtc0 < rtc1, add + * 10 seconds to get the correct value + */ + diff += 10 * SECOND; + } + diff -= rtc0_val; + return diff; +} + +void rtc_read(struct rtc_time_reg *rtc) +{ + /* + * Read current time synchronously. Each register must be read + * twice with identical values because glitches may occur for reads + * close to the RTCCLK edge. + */ + do { + rtc->rtc_dr = STM32_RTC_DR; + + do { + rtc->rtc_tr = STM32_RTC_TR; + + do { + rtc->rtc_ssr = STM32_RTC_SSR; + } while (rtc->rtc_ssr != STM32_RTC_SSR); + + } while (rtc->rtc_tr != STM32_RTC_TR); + + } while (rtc->rtc_dr != STM32_RTC_DR); +} + +void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us, + struct rtc_time_reg *rtc, uint8_t save_alarm) +{ + uint32_t alarm_sec = 0; + uint32_t alarm_us = 0; + + if (delay_s == EC_RTC_ALARM_CLEAR && !delay_us) { + reset_rtc_alarm(rtc); + return; + } + + /* Alarm timeout must be within 1 day (86400 seconds) */ + ASSERT((delay_s + delay_us / SECOND) < SECS_PER_DAY); + + pre_work_set_rtc_alarm(); + rtc_read(rtc); + + /* Calculate alarm time */ + alarm_sec = rtc_tr_to_sec(rtc->rtc_tr) + delay_s; + + if (delay_us) { + alarm_us = rtcss_to_us(rtc->rtc_ssr) + delay_us; + alarm_sec = alarm_sec + alarm_us / SECOND; + alarm_us = alarm_us % SECOND; + } + + /* + * If seconds is greater than 1 day, subtract by 1 day to deal with + * 24-hour rollover. + */ + if (alarm_sec >= SECS_PER_DAY) + alarm_sec -= SECS_PER_DAY; + + /* + * Set alarm time in seconds and check for match on + * hours, minutes, and seconds. + */ + STM32_RTC_ALRMAR = sec_to_rtc_tr(alarm_sec) | 0xc0000000; + + /* + * Set alarm time in subseconds and check for match on subseconds. + * If the caller doesn't specify subsecond delay (e.g. host command), + * just align the alarm time to second. + */ + STM32_RTC_ALRMASSR = delay_us ? (us_to_rtcss(alarm_us) | 0x0f000000) : + 0; + +#ifdef CONFIG_HOSTCMD_RTC + /* + * If alarm is set by the host, preserve the wake time timestamp + * and alarm registers. + */ + if (save_alarm) { + host_wake_time.ts.val = delay_s * SECOND + get_time().val; + host_wake_time.rtc_alrmar = STM32_RTC_ALRMAR; + } +#endif + post_work_set_rtc_alarm(); +} + +uint32_t get_rtc_alarm(void) +{ + struct rtc_time_reg now; + uint32_t now_sec; + uint32_t alarm_sec; + + if (!(STM32_RTC_CR & STM32_RTC_CR_ALRAE)) + return 0; + + rtc_read(&now); + + now_sec = rtc_tr_to_sec(now.rtc_tr); + alarm_sec = rtc_tr_to_sec(STM32_RTC_ALRMAR & 0x3fffff); + + return ((alarm_sec < now_sec) ? SECS_PER_DAY : 0) + + (alarm_sec - now_sec); +} + +void reset_rtc_alarm(struct rtc_time_reg *rtc) +{ + rtc_unlock_regs(); + + /* Disable alarm */ + STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE; + STM32_RTC_ISR &= ~STM32_RTC_ISR_ALRAF; + + /* Disable RTC alarm interrupt */ + STM32_EXTI_IMR &= ~BIT(18); +#ifdef STM32_EXTI_RPR + /* Separate rising and falling edge pending registers. */ + STM32_EXTI_RPR = BIT(18); + STM32_EXTI_FPR = BIT(18); +#else + /* One combined rising/falling edge pending registers. */ + STM32_EXTI_PR = BIT(18); +#endif + + /* Clear the pending RTC alarm IRQ in NVIC */ + task_clear_pending_irq(STM32_IRQ_RTC_ALARM); + + /* Read current time */ + rtc_read(rtc); + + rtc_lock_regs(); +} + +#ifdef CONFIG_HOSTCMD_RTC +static void set_rtc_host_event(void) +{ + host_set_single_event(EC_HOST_EVENT_RTC); +} +DECLARE_DEFERRED(set_rtc_host_event); +#endif + +test_mockable_static void __rtc_alarm_irq(void) +{ + struct rtc_time_reg rtc; + + reset_rtc_alarm(&rtc); + +#ifdef CONFIG_HOSTCMD_RTC + /* Wake up the host if there is a saved rtc wake alarm. */ + if (host_wake_time.ts.val) { + host_wake_time.ts.val = 0; + hook_call_deferred(&set_rtc_host_event_data, 0); + } +#endif +} +DECLARE_IRQ(STM32_IRQ_RTC_ALARM, __rtc_alarm_irq, 1); + +void print_system_rtc(enum console_channel ch) +{ + uint32_t sec; + struct rtc_time_reg rtc; + + rtc_read(&rtc); + sec = rtc_to_sec(&rtc); + + cprintf(ch, "RTC: 0x%08x (%d.00 s)\n", sec, sec); +} + +#ifdef CONFIG_LOW_POWER_IDLE +/* Low power idle statistics */ +static int idle_sleep_cnt; +static int idle_dsleep_cnt; +static uint64_t idle_dsleep_time_us; +static int dsleep_recovery_margin_us = 1000000; + +/* STOP_MODE_LATENCY: delay to wake up from STOP mode with main regulator off */ +#define STOP_MODE_LATENCY 50 /* us */ +/* PLL_LOCK_LATENCY: delay to switch from HSI to PLL */ +#define PLL_LOCK_LATENCY 150 /* us */ +/* + * SET_RTC_MATCH_DELAY: max time to set RTC match alarm. If we set the alarm + * in the past, it will never wake up and cause a watchdog. + */ +#define SET_RTC_MATCH_DELAY 120 /* us */ + +void low_power_init(void) +{ + /* Enter stop1 mode */ + uint32_t val; + + val = STM32_PWR_CR1; + val &= ~PWR_CR1_LPMS_MSK; + val |= PWR_CR1_LPMS_STOP1; + STM32_PWR_CR1 = val; +} + +void clock_refresh_console_in_use(void) +{ +} + +void __idle(void) +{ + timestamp_t t0; + uint32_t rtc_diff; + int next_delay, margin_us; + struct rtc_time_reg rtc0, rtc1; + + while (1) { + interrupt_disable(); + + t0 = get_time(); + next_delay = __hw_clock_event_get() - t0.le.lo; + + if (DEEP_SLEEP_ALLOWED && + (next_delay > (STOP_MODE_LATENCY + PLL_LOCK_LATENCY + + SET_RTC_MATCH_DELAY))) { + /* Deep-sleep in STOP mode */ + idle_dsleep_cnt++; + + uart_enable_wakeup(1); + + /* Set deep sleep bit */ + CPU_SCB_SYSCTRL |= 0x4; + + set_rtc_alarm(0, + next_delay - STOP_MODE_LATENCY - + PLL_LOCK_LATENCY, + &rtc0, 0); + + /* ensure outstanding memory transactions complete */ + asm volatile("dsb"); + + cpu_enter_suspend_mode(); + + CPU_SCB_SYSCTRL &= ~0x4; + + /* turn on PLL and wait until it's ready */ + STM32_RCC_APB1ENR1 |= STM32_RCC_APB1ENR1_PWREN; + clock_wait_bus_cycles(BUS_APB, 2); + + stm32_configure_pll(OSC_HSI, STM32_PLLM, STM32_PLLN, + STM32_PLLR); + + /* Switch to PLL */ + clock_switch_osc(OSC_PLL); + + uart_enable_wakeup(0); + + /* Fast forward timer according to RTC counter */ + reset_rtc_alarm(&rtc1); + rtc_diff = get_rtc_diff(&rtc0, &rtc1); + t0.val = t0.val + rtc_diff; + force_time(t0); + + /* Record time spent in deep sleep. */ + idle_dsleep_time_us += rtc_diff; + + /* Calculate how close we were to missing deadline */ + margin_us = next_delay - rtc_diff; + if (margin_us < 0) + /* Use CPUTS to save stack space */ + CPUTS("Idle overslept!\n"); + + /* Record the closest to missing a deadline. */ + if (margin_us < dsleep_recovery_margin_us) + dsleep_recovery_margin_us = margin_us; + } else { + idle_sleep_cnt++; + + /* Normal idle : only CPU clock stopped */ + cpu_enter_suspend_mode(); + } + interrupt_enable(); + } +} + +/*****************************************************************************/ +/* Console commands */ +/* Print low power idle statistics. */ +static int command_idle_stats(int argc, const char **argv) +{ + timestamp_t ts = get_time(); + + ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); + ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); + ccprintf("Time spent in deep-sleep: %.6llus\n", + idle_dsleep_time_us); + ccprintf("Total time on: %.6llus\n", ts.val); + ccprintf("Deep-sleep closest to wake deadline: %dus\n", + dsleep_recovery_margin_us); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", + "Print last idle stats"); +#endif /* CONFIG_LOW_POWER_IDLE */ diff --git a/chip/stm32/clock-stm32l5.c b/chip/stm32/clock-stm32l5.c new file mode 100644 index 0000000000..a4cf34f7b8 --- /dev/null +++ b/chip/stm32/clock-stm32l5.c @@ -0,0 +1,6 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "clock-stm32l4.c" diff --git a/chip/stm32/config-stm32f03x.h b/chip/stm32/config-stm32f03x.h index 84266cdbfc..695b16f0b3 100644 --- a/chip/stm32/config-stm32f03x.h +++ b/chip/stm32/config-stm32f03x.h @@ -1,25 +1,25 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifdef CHIP_VARIANT_STM32F03X8 -#define CONFIG_FLASH_SIZE 0x00010000 -#define CONFIG_RAM_SIZE 0x00002000 +#define CONFIG_FLASH_SIZE_BYTES 0x00010000 +#define CONFIG_RAM_SIZE 0x00002000 #else -#define CONFIG_FLASH_SIZE 0x00008000 -#define CONFIG_RAM_SIZE 0x00001000 +#define CONFIG_FLASH_SIZE_BYTES 0x00008000 +#define CONFIG_RAM_SIZE 0x00001000 #endif /* Memory mapping */ -#define CONFIG_FLASH_BANK_SIZE 0x1000 -#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */ -#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ +#define CONFIG_FLASH_BANK_SIZE 0x1000 +#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */ +#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ /* No page mode on STM32F, so no benefit to larger write sizes */ #define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002 -#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_BASE 0x20000000 /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 32 diff --git a/chip/stm32/config-stm32f05x.h b/chip/stm32/config-stm32f05x.h index cab7b62d50..7f083b0eb2 100644 --- a/chip/stm32/config-stm32f05x.h +++ b/chip/stm32/config-stm32f05x.h @@ -1,19 +1,19 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ -#define CONFIG_FLASH_SIZE (64 * 1024) -#define CONFIG_FLASH_BANK_SIZE 0x1000 -#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */ -#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ +#define CONFIG_FLASH_SIZE_BYTES (64 * 1024) +#define CONFIG_FLASH_BANK_SIZE 0x1000 +#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */ +#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ /* No page mode on STM32F, so no benefit to larger write sizes */ #define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002 -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00002000 +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00002000 /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 32 diff --git a/chip/stm32/config-stm32f07x.h b/chip/stm32/config-stm32f07x.h index 199aef3361..31468f656e 100644 --- a/chip/stm32/config-stm32f07x.h +++ b/chip/stm32/config-stm32f07x.h @@ -1,19 +1,19 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ -#define CONFIG_FLASH_SIZE (128 * 1024) -#define CONFIG_FLASH_BANK_SIZE 0x1000 -#define CONFIG_FLASH_ERASE_SIZE 0x0800 /* erase bank size */ -#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ +#define CONFIG_FLASH_SIZE_BYTES (128 * 1024) +#define CONFIG_FLASH_BANK_SIZE 0x1000 +#define CONFIG_FLASH_ERASE_SIZE 0x0800 /* erase bank size */ +#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ /* No page mode on STM32F, so no benefit to larger write sizes */ #define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002 -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00004000 +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00004000 /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 32 @@ -23,7 +23,10 @@ #define CONFIG_CONSOLE_HISTORY 3 /* USB packet ram config */ -#define CONFIG_USB_RAM_BASE 0x40006000 -#define CONFIG_USB_RAM_SIZE 1024 +#define CONFIG_USB_RAM_BASE 0x40006000 +#define CONFIG_USB_RAM_SIZE 1024 #define CONFIG_USB_RAM_ACCESS_TYPE uint16_t #define CONFIG_USB_RAM_ACCESS_SIZE 2 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1fffC800 diff --git a/chip/stm32/config-stm32f09x.h b/chip/stm32/config-stm32f09x.h index 3da8a342f2..405c63f3ec 100644 --- a/chip/stm32/config-stm32f09x.h +++ b/chip/stm32/config-stm32f09x.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,16 +8,16 @@ * Flash physical size: 256KB * Write protect sectors: 31 4KB sectors, one 132KB sector */ -#define CONFIG_FLASH_SIZE 0x00040000 -#define CONFIG_FLASH_BANK_SIZE 0x1000 -#define CONFIG_FLASH_ERASE_SIZE 0x0800 /* erase bank size */ -#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ +#define CONFIG_FLASH_SIZE_BYTES 0x00040000 +#define CONFIG_FLASH_BANK_SIZE 0x1000 +#define CONFIG_FLASH_ERASE_SIZE 0x0800 /* erase bank size */ +#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ /* No page mode on STM32F, so no benefit to larger write sizes */ #define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002 -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00008000 +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00008000 /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 32 @@ -43,34 +43,33 @@ * */ -#define _SECTOR_4KB (4 * 1024) -#define _SECTOR_132KB (132 * 1024) +#define _SECTOR_4KB (4 * 1024) +#define _SECTOR_132KB (132 * 1024) /* The EC uses one sector to emulate persistent state */ #define CONFIG_FLASH_PSTATE -#define CONFIG_FW_PSTATE_SIZE _SECTOR_4KB -#define CONFIG_FW_PSTATE_OFF (30 * _SECTOR_4KB) +#define CONFIG_FW_PSTATE_SIZE _SECTOR_4KB +#define CONFIG_FW_PSTATE_OFF (30 * _SECTOR_4KB) -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RO_SIZE (30 * _SECTOR_4KB) -#define CONFIG_RW_MEM_OFF (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE + \ - CONFIG_FW_PSTATE_SIZE) -#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_RW_SIZE _SECTOR_132KB +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (30 * _SECTOR_4KB) +#define CONFIG_RW_MEM_OFF \ + (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE + CONFIG_FW_PSTATE_SIZE) +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_SIZE _SECTOR_132KB -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 #define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE (CONFIG_FLASH_SIZE - \ - CONFIG_EC_WRITABLE_STORAGE_OFF) +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - CONFIG_EC_WRITABLE_STORAGE_OFF) -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE /* We map each write protect sector to a bank */ -#define PHYSICAL_BANKS 32 -#define WP_BANK_COUNT 31 -#define PSTATE_BANK 30 -#define PSTATE_BANK_COUNT 1 - +#define PHYSICAL_BANKS 32 +#define WP_BANK_COUNT 31 +#define PSTATE_BANK 30 +#define PSTATE_BANK_COUNT 1 diff --git a/chip/stm32/config-stm32f373.h b/chip/stm32/config-stm32f373.h index b77b1d98a6..f57350a17c 100644 --- a/chip/stm32/config-stm32f373.h +++ b/chip/stm32/config-stm32f373.h @@ -1,25 +1,28 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ -#define CONFIG_FLASH_SIZE 0x00040000 -#define CONFIG_FLASH_BANK_SIZE 0x2000 -#define CONFIG_FLASH_ERASE_SIZE 0x0800 /* erase bank size */ -#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ +#define CONFIG_FLASH_SIZE_BYTES 0x00040000 +#define CONFIG_FLASH_BANK_SIZE 0x2000 +#define CONFIG_FLASH_ERASE_SIZE 0x0800 /* erase bank size */ +#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ /* No page mode on STM32F, so no benefit to larger write sizes */ #define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002 -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00008000 +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00008000 /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 81 /* STM32F3 uses the older 4 byte aligned access mechanism */ -#define CONFIG_USB_RAM_BASE 0x40006000 -#define CONFIG_USB_RAM_SIZE 512 +#define CONFIG_USB_RAM_BASE 0x40006000 +#define CONFIG_USB_RAM_SIZE 512 #define CONFIG_USB_RAM_ACCESS_TYPE uint32_t #define CONFIG_USB_RAM_ACCESS_SIZE 4 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1fffd800 diff --git a/chip/stm32/config-stm32f4.h b/chip/stm32/config-stm32f4.h index c64cc3089a..d7ef668886 100644 --- a/chip/stm32/config-stm32f4.h +++ b/chip/stm32/config-stm32f4.h @@ -1,13 +1,13 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ #ifdef CHIP_VARIANT_STM32F412 -# define CONFIG_FLASH_SIZE (1 * 1024 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (1 * 1024 * 1024) #else -# define CONFIG_FLASH_SIZE (512 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (512 * 1024) #endif /* 3 regions type: 16K, 64K and 128K */ @@ -16,7 +16,7 @@ #define SIZE_128KB (128 * 1024) #define CONFIG_FLASH_REGION_TYPE_COUNT 3 #define CONFIG_FLASH_MULTIPLE_REGION \ - (5 + (CONFIG_FLASH_SIZE - SIZE_128KB) / SIZE_128KB) + (5 + (CONFIG_FLASH_SIZE_BYTES - SIZE_128KB) / SIZE_128KB) /* Erasing 128K can take up to 2s, need to defer erase. */ #define CONFIG_FLASH_DEFERRED_ERASE @@ -31,33 +31,32 @@ #define CONFIG_FLASH_WRITE_IDEAL_SIZE CONFIG_FLASH_WRITE_SIZE #ifdef CHIP_VARIANT_STM32F412 -# define CONFIG_RAM_BASE 0x20000000 -# define CONFIG_RAM_SIZE 0x00040000 /* 256 KB */ +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00040000 /* 256 KB */ #else -# define CONFIG_RAM_BASE 0x20000000 -# define CONFIG_RAM_SIZE 0x00020000 /* 128 KB */ +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00020000 /* 128 KB */ #endif -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_SIZE (256 * 1024) -#define CONFIG_RW_MEM_OFF (256 * 1024) -#define CONFIG_RW_SIZE (256 * 1024) +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_SIZE (256 * 1024) +#define CONFIG_RW_MEM_OFF (256 * 1024) +#define CONFIG_RW_SIZE (256 * 1024) -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE \ - (CONFIG_FLASH_SIZE - CONFIG_EC_WRITABLE_STORAGE_OFF) - -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - CONFIG_EC_WRITABLE_STORAGE_OFF) +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE #undef I2C_PORT_COUNT -#define I2C_PORT_COUNT 4 +#define I2C_PORT_COUNT 4 /* Use PSTATE embedded in the RO image, not in its own erase block */ #define CONFIG_FLASH_PSTATE @@ -67,4 +66,20 @@ #define CONFIG_OTP /* Number of IRQ vectors on the NVIC */ -#define CONFIG_IRQ_COUNT 97 +#define CONFIG_IRQ_COUNT 97 + +#undef CONFIG_CMD_CHARGEN + +/* DFU Address */ +#define STM32_DFU_BASE 0x1fff0000 + +/* + * SET_RTC_MATCH_DELAY: max time to set RTC match alarm. If we set the alarm + * in the past, it will never wake up and cause a watchdog. + * + * This value is minimal time for which we can set RTC match alarm. It was + * obtained by setting the alarm and checking if the alarm interrupt was + * triggered. Unit test test_rtc_match_delay is responsible for verifying if + * setting the RTC match alarm with this value will generate the interrupt. + */ +#define SET_RTC_MATCH_DELAY 200 /* us */ diff --git a/chip/stm32/config-stm32f76x.h b/chip/stm32/config-stm32f76x.h index 665bec36bf..e7380118f0 100644 --- a/chip/stm32/config-stm32f76x.h +++ b/chip/stm32/config-stm32f76x.h @@ -1,10 +1,10 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ -#define CONFIG_FLASH_SIZE (2048 * 1024) +#define CONFIG_FLASH_SIZE_BYTES (2048 * 1024) /* 3 regions type: 32K, 128K and 256K */ #define SIZE_32KB (32 * 1024) @@ -12,7 +12,7 @@ #define SIZE_256KB (256 * 1024) #define CONFIG_FLASH_REGION_TYPE_COUNT 3 #define CONFIG_FLASH_MULTIPLE_REGION \ - (5 + (CONFIG_FLASH_SIZE - SIZE_256KB) / SIZE_256KB) + (5 + (CONFIG_FLASH_SIZE_BYTES - SIZE_256KB) / SIZE_256KB) /* Erasing 256K can take up to 2s, need to defer erase. */ #define CONFIG_FLASH_DEFERRED_ERASE @@ -29,32 +29,35 @@ /* DTCM-RAM: 128kB 0x20000000 - 0x2001FFFF*/ /* SRAM1: 368kB 0x20020000 - 0x2007BFFF */ /* SRAM2: 16kB 0x2007C000 - 0x2007FFFF */ -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00080000 +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00080000 -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_SIZE (1024 * 1024) -#define CONFIG_RW_MEM_OFF (1024 * 1024) -#define CONFIG_RW_SIZE (1024 * 1024) +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_SIZE (1024 * 1024) +#define CONFIG_RW_MEM_OFF (1024 * 1024) +#define CONFIG_RW_SIZE (1024 * 1024) -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE \ - (CONFIG_FLASH_SIZE - CONFIG_EC_WRITABLE_STORAGE_OFF) +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - CONFIG_EC_WRITABLE_STORAGE_OFF) -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE #undef I2C_PORT_COUNT -#define I2C_PORT_COUNT 4 +#define I2C_PORT_COUNT 4 /* Use PSTATE embedded in the RO image, not in its own erase block */ #define CONFIG_FLASH_PSTATE #undef CONFIG_FLASH_PSTATE_BANK /* Number of IRQ vectors on the NVIC */ -#define CONFIG_IRQ_COUNT 109 +#define CONFIG_IRQ_COUNT 109 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1ff00000 diff --git a/chip/stm32/config-stm32g41xb.h b/chip/stm32/config-stm32g41xb.h index ab8642b9e6..97e9d21d25 100644 --- a/chip/stm32/config-stm32g41xb.h +++ b/chip/stm32/config-stm32g41xb.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,17 +16,12 @@ * The minimum write size for STM32G4 is 8 bytes. Cros-EC does not support * PSTATE in single bank memories with a write size > 4 bytes. */ -/* - * TODO(b/167462264): This is a temporary change to allow for platform bringup - * without being constrained by flash space issue. Currently only using RO image - * flashed with STM32 debugger. - */ -#define CONFIG_FLASH_SIZE (256 * 1024) + +#define CONFIG_FLASH_SIZE_BYTES (128 * 1024) #define CONFIG_FLASH_WRITE_SIZE 0x0004 #define CONFIG_FLASH_BANK_SIZE (2 * 1024) #define CONFIG_FLASH_ERASE_SIZE CONFIG_FLASH_BANK_SIZE - /* Erasing 128K can take up to 2s, need to defer erase. */ #define CONFIG_FLASH_DEFERRED_ERASE @@ -41,11 +36,11 @@ * • 10 Kbytes mapped at address 0x1000 0000 (CCM SRAM). It is also aliased * at 0x2000 5800 address to be accessed by all bus controllers. */ -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00008000 +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00008000 #undef I2C_PORT_COUNT -#define I2C_PORT_COUNT 3 +#define I2C_PORT_COUNT 3 /* Number of DMA channels supported (6 channels each for DMA1 and DMA2) */ #define DMAC_COUNT 12 @@ -55,4 +50,13 @@ #undef CONFIG_FLASH_PSTATE_BANK /* Number of IRQ vectors on the NVIC */ -#define CONFIG_IRQ_COUNT 101 +#define CONFIG_IRQ_COUNT 101 + +/* USB packet ram config */ +#define CONFIG_USB_RAM_BASE 0x40006000 +#define CONFIG_USB_RAM_SIZE 1024 +#define CONFIG_USB_RAM_ACCESS_TYPE uint16_t +#define CONFIG_USB_RAM_ACCESS_SIZE 2 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1fff0000 diff --git a/chip/stm32/config-stm32g473xc.h b/chip/stm32/config-stm32g473xc.h new file mode 100644 index 0000000000..63f4c73ea0 --- /dev/null +++ b/chip/stm32/config-stm32g473xc.h @@ -0,0 +1,68 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Memory mapping for STM32G473xc. The STM32G473xc is a category 1 device within + * the STM32G4 chip family. Category 1 devices have either 128, 256, or 512 kB + * of internal flash. 'xc' indicates 256 kB of internal flash. + * + * STM32G473xc can be configured via option bytes as either a single bank or + * dual bank device. Dual bank is the default selection. + * CONFIG_FLASH_BANK_SIZE is consistent with page size as defined in RM0440 TRM + * for the STM32G4 chip family. In dual bank mode, the flash is organized in 2 + * kB pages, with 64 pages per bank for this variant. + * + * The minimum write size for STM32G4 is 8 bytes. Cros-EC does not support + * PSTATE in single bank memories with a write size > 4 bytes. + * + * TODO(b/181874494): Verify that dual bank mode should be used, or add support + * for enabling single bank mode on STM32G473xc. + */ +#define CONFIG_FLASH_SIZE_BYTES (256 * 1024) +#define CONFIG_FLASH_WRITE_SIZE 0x0004 +#define CONFIG_FLASH_BANK_SIZE (2 * 1024) +#define CONFIG_FLASH_ERASE_SIZE CONFIG_FLASH_BANK_SIZE + +/* Dual-bank (DBANK) mode is enabled by default for this chip */ +#define STM32_FLASH_DBANK_MODE + +/* Erasing 128K can take up to 2s, need to defer erase. */ +#define CONFIG_FLASH_DEFERRED_ERASE + +/* No page mode on STM32G4, so no benefit to larger write sizes */ +#define CONFIG_FLASH_WRITE_IDEAL_SIZE CONFIG_FLASH_WRITE_SIZE + +/* + * STM32G473xc is a category 3 SRAM device featuring 128 Kbytes of embedded + * SRAM. This SRAM is split into three blocks: + * • 80 Kbytes mapped at address 0x2000 0000 (SRAM1). + * • 16 Kbytes mapped at address 0x2001 4000 (SRAM2). + * • 32 Kbytes mapped at address 0x1000 0000 (CCM SRAM). It is also aliased + * at 0x2001 8000 address to be accessed by all bus controllers. + */ +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00020000 + +#undef I2C_PORT_COUNT +#define I2C_PORT_COUNT 4 + +/* Number of DMA channels supported (6 channels each for DMA1 and DMA2) */ +#define DMAC_COUNT 12 + +/* Use PSTATE embedded in the RO image, not in its own erase block */ +#define CONFIG_FLASH_PSTATE +#undef CONFIG_FLASH_PSTATE_BANK + +/* Number of IRQ vectors on the NVIC */ +#define CONFIG_IRQ_COUNT 101 + +/* USB packet ram config */ +#define CONFIG_USB_RAM_BASE 0x40006000 +#define CONFIG_USB_RAM_SIZE 1024 +#define CONFIG_USB_RAM_ACCESS_TYPE uint16_t +#define CONFIG_USB_RAM_ACCESS_SIZE 2 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1fff0000 diff --git a/chip/stm32/config-stm32h7x3.h b/chip/stm32/config-stm32h7x3.h index 399e6a6f1a..31f1d3c720 100644 --- a/chip/stm32/config-stm32h7x3.h +++ b/chip/stm32/config-stm32h7x3.h @@ -1,20 +1,20 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ -#define CONFIG_FLASH_SIZE (2048 * 1024) -#define CONFIG_FLASH_ERASE_SIZE (128 * 1024) /* erase bank size */ +#define CONFIG_FLASH_SIZE_BYTES (2048 * 1024) +#define CONFIG_FLASH_ERASE_SIZE (128 * 1024) /* erase bank size */ /* always use 256-bit writes due to ECC */ -#define CONFIG_FLASH_WRITE_SIZE 32 /* minimum write size */ -#define CONFIG_FLASH_WRITE_IDEAL_SIZE 32 +#define CONFIG_FLASH_WRITE_SIZE 32 /* minimum write size */ +#define CONFIG_FLASH_WRITE_IDEAL_SIZE 32 /* * What the code is calling 'bank' is really the size of the block used for * write-protected, here it's 128KB sector (same as erase size). */ -#define CONFIG_FLASH_BANK_SIZE (128 * 1024) +#define CONFIG_FLASH_BANK_SIZE (128 * 1024) /* Erasing 128K can take up to 2s, need to defer erase. */ #define CONFIG_FLASH_DEFERRED_ERASE @@ -27,28 +27,28 @@ /* (D2) AHB-SRAM3: 32kB 0x30040000 - 0x30047FFF */ /* (D3) AHB-SRAM4: 64kB 0x38000000 - 0x3800FFFF */ /* (D3) backup RAM: 4kB 0x38800000 - 0x38800FFF */ -#define CONFIG_RAM_BASE 0x24000000 -#define CONFIG_RAM_SIZE 0x00080000 +#define CONFIG_RAM_BASE 0x24000000 +#define CONFIG_RAM_SIZE 0x00080000 -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_SIZE (128 * 1024) -#define CONFIG_RW_MEM_OFF (CONFIG_FLASH_SIZE / 2) -#define CONFIG_RW_SIZE (512 * 1024) +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_SIZE (128 * 1024) +#define CONFIG_RW_MEM_OFF (CONFIG_FLASH_SIZE_BYTES / 2) +#define CONFIG_RW_SIZE (512 * 1024) -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE \ - (CONFIG_FLASH_SIZE - CONFIG_EC_WRITABLE_STORAGE_OFF) +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - CONFIG_EC_WRITABLE_STORAGE_OFF) -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE #undef I2C_PORT_COUNT -#define I2C_PORT_COUNT 4 +#define I2C_PORT_COUNT 4 /* * Cannot use PSTATE: @@ -58,7 +58,7 @@ #undef CONFIG_FLASH_PSTATE_BANK /* Number of IRQ vectors on the NVIC */ -#define CONFIG_IRQ_COUNT 150 +#define CONFIG_IRQ_COUNT 150 /* the Cortex-M7 core has 'standard' ARMv7-M caches */ #define CONFIG_ARMV7M_CACHE @@ -68,6 +68,9 @@ #define CONFIG_CHIP_UNCACHED_REGION ahb4 /* Override MPU attribute settings to match the chip requirements */ /* Code is Normal memory type / non-shareable / write-through */ -#define MPU_ATTR_FLASH_MEMORY 0x02 +#define MPU_ATTR_FLASH_MEMORY 0x02 /* SRAM Data is Normal memory type / non-shareable / write-back, write-alloc */ #define MPU_ATTR_INTERNAL_SRAM 0x0B + +/* DFU Address */ +#define STM32_DFU_BASE 0x1ff00000 diff --git a/chip/stm32/config-stm32l100.h b/chip/stm32/config-stm32l100.h index 579e31cb5b..ec28815525 100644 --- a/chip/stm32/config-stm32l100.h +++ b/chip/stm32/config-stm32l100.h @@ -1,12 +1,12 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ -#define CONFIG_FLASH_SIZE 0x00020000 -#define CONFIG_FLASH_BANK_SIZE 0x1000 -#define CONFIG_FLASH_ERASE_SIZE 0x0100 /* erase bank size */ +#define CONFIG_FLASH_SIZE_BYTES 0x00020000 +#define CONFIG_FLASH_BANK_SIZE 0x1000 +#define CONFIG_FLASH_ERASE_SIZE 0x0100 /* erase bank size */ /* * TODO(crosbug.com/p/23805): Technically we can write in word-mode (4 bytes at @@ -21,8 +21,8 @@ /* Ideal write size in page-mode */ #define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0080 -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00002800 +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00002800 /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 45 @@ -37,7 +37,10 @@ #define CONFIG_STM32L_FAKE_HIBERNATE /* USB packet ram config */ -#define CONFIG_USB_RAM_BASE 0x40006000 -#define CONFIG_USB_RAM_SIZE 512 +#define CONFIG_USB_RAM_BASE 0x40006000 +#define CONFIG_USB_RAM_SIZE 512 #define CONFIG_USB_RAM_ACCESS_TYPE uint32_t #define CONFIG_USB_RAM_ACCESS_SIZE 4 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1ff00000 diff --git a/chip/stm32/config-stm32l15x.h b/chip/stm32/config-stm32l15x.h index afdc241e96..d35b3ccbcf 100644 --- a/chip/stm32/config-stm32l15x.h +++ b/chip/stm32/config-stm32l15x.h @@ -1,12 +1,12 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ -#define CONFIG_FLASH_SIZE 0x00020000 -#define CONFIG_FLASH_BANK_SIZE 0x1000 -#define CONFIG_FLASH_ERASE_SIZE 0x0100 /* erase bank size */ +#define CONFIG_FLASH_SIZE_BYTES 0x00020000 +#define CONFIG_FLASH_BANK_SIZE 0x1000 +#define CONFIG_FLASH_ERASE_SIZE 0x0100 /* erase bank size */ /* * TODO(crosbug.com/p/23805): Technically we can write in word-mode (4 bytes at @@ -21,11 +21,22 @@ /* Ideal write size in page-mode */ #define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0080 -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00004000 - -/* Number of IRQ vectors on the NVIC */ -#define CONFIG_IRQ_COUNT 45 +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00004000 + +/* Number of IRQ vectors on the NVIC + * + * Section 10.1 "Nested vectored interrupt controller (NVIC)" states: + * 45 maskable interrupt channels in Cat.1 and Cat.2 devices (see Table 49) + * 54 maskable interrupt channels in Cat.3 devices (see Table 50) and 57 + * channels in Cat.4, Cat.5 and Cat.6 devices (see Table 51). + * + * The only STM32L15 that we support is the "discovery" board is a "Category + * 3" device. See Section 1.5 "Product Category definition". + * + * https://www.st.com/resource/en/reference_manual/cd00240193-stm32l100xx-stm32l151xx-stm32l152xx-and-stm32l162xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf + */ +#define CONFIG_IRQ_COUNT 54 /* Lots of RAM, so use bigger UART buffer */ #undef CONFIG_UART_TX_BUF_SIZE @@ -38,7 +49,10 @@ #define CONFIG_FLASH_ERASED_VALUE32 0 /* USB packet ram config */ -#define CONFIG_USB_RAM_BASE 0x40006000 -#define CONFIG_USB_RAM_SIZE 512 +#define CONFIG_USB_RAM_BASE 0x40006000 +#define CONFIG_USB_RAM_SIZE 512 #define CONFIG_USB_RAM_ACCESS_TYPE uint32_t #define CONFIG_USB_RAM_ACCESS_SIZE 4 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1ff00000 diff --git a/chip/stm32/config-stm32l431.h b/chip/stm32/config-stm32l431.h new file mode 100644 index 0000000000..de3204945a --- /dev/null +++ b/chip/stm32/config-stm32l431.h @@ -0,0 +1,78 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Memory mapping */ +#define CONFIG_FLASH_SIZE_BYTES 0x00040000 /* 256 kB */ +#define CONFIG_FLASH_BANK_SIZE \ + 0x800 /* 2 kB. NOTE: BANK in chrome-ec means page */ +#define CONFIG_FLASH_ERASE_SIZE 0x800 /* 2 KB */ +#define CONFIG_FLASH_WRITE_SIZE 0x8 /* 64 bits */ + +/* Ideal write size in page-mode */ +#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x100 /* 256 (32 double words) */ + +/* + * SRAM1 (48kB) at 0x20000000 + * SRAM2 (16kB) at 0x10000000 (and aliased at 0x2000C000) + * so they are contiguous. + */ +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00010000 /* 64 kB */ + +/* Number of IRQ vectors on the NVIC */ +#define CONFIG_IRQ_COUNT 82 + +/* + * STM32L431 flash layout: + * - RO image starts at the beginning of flash: sector 0 ~ 61 + * - PSTATE immediately follows the RO image: sector 62 + * - RW image starts at 0x1f800: sector 63 + * - Protected region consists of the RO image + PSTATE: sector 0 ~ 62 + * - Unprotected region consists of second half of RW image + * + * PSTATE(2KB) + * | + * (126KB) v (130KB) + * |<-----Protected Region------>|<------Unprotected Region----->| + * |<--------RO image--------->| |<----------RW image----------->| + * 0 (124KB) ^ ^ + * | | + * | 63(2KB sector) + * | + * 62 + * + */ + +/* The EC uses one sector to emulate persistent state */ +#define CONFIG_FLASH_PSTATE +#define CONFIG_FW_PSTATE_SIZE CONFIG_FLASH_BANK_SIZE +#define CONFIG_FW_PSTATE_OFF (62 * CONFIG_FLASH_BANK_SIZE) + +#define CONFIG_RO_MEM_OFF 0 +#define CONFIG_RO_STORAGE_OFF 0 +#define CONFIG_RO_SIZE (62 * CONFIG_FLASH_BANK_SIZE) +#define CONFIG_RW_MEM_OFF \ + (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE + CONFIG_FW_PSTATE_SIZE) +#define CONFIG_RW_STORAGE_OFF 0 +#define CONFIG_RW_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - CONFIG_RW_MEM_OFF - CONFIG_RW_STORAGE_OFF) + +#define CONFIG_EC_PROTECTED_STORAGE_OFF 0 +#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF +#define CONFIG_EC_WRITABLE_STORAGE_SIZE \ + (CONFIG_FLASH_SIZE_BYTES - CONFIG_EC_WRITABLE_STORAGE_OFF) + +#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF +#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE + +/* We map each write protect sector to a bank */ +#define PHYSICAL_BANKS 128 +#define WP_BANK_COUNT 63 +#define PSTATE_BANK 62 +#define PSTATE_BANK_COUNT 1 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1fff0000 diff --git a/chip/stm32/config-stm32l442.h b/chip/stm32/config-stm32l442.h index e9f3e04c53..b85e9b1454 100644 --- a/chip/stm32/config-stm32l442.h +++ b/chip/stm32/config-stm32l442.h @@ -1,24 +1,27 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ -#define CONFIG_FLASH_SIZE 0x00040000 /* 256 kB */ -#define CONFIG_FLASH_BANK_SIZE 0x800 /* 2 kB */ -#define CONFIG_FLASH_ERASE_SIZE 0x800 /* 2 KB */ -#define CONFIG_FLASH_WRITE_SIZE 0x8 /* 64 bits */ +#define CONFIG_FLASH_SIZE_BYTES 0x00040000 /* 256 kB */ +#define CONFIG_FLASH_BANK_SIZE 0x800 /* 2 kB */ +#define CONFIG_FLASH_ERASE_SIZE 0x800 /* 2 KB */ +#define CONFIG_FLASH_WRITE_SIZE 0x8 /* 64 bits */ /* Ideal write size in page-mode */ -#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x100 /* 256 (32 double words) */ +#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x100 /* 256 (32 double words) */ /* * SRAM1 (48kB) at 0x20000000 * SRAM2 (16kB) at 0x10000000 (and aliased at 0x2000C000) * so they are contiguous. */ -#define CONFIG_RAM_BASE 0x20000000 -#define CONFIG_RAM_SIZE 0x00010000 /* 64 kB */ +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00010000 /* 64 kB */ /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 82 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1fff0000 diff --git a/chip/stm32/config-stm32l476.h b/chip/stm32/config-stm32l476.h index 9f6b35b8b1..00a02e0ff9 100644 --- a/chip/stm32/config-stm32l476.h +++ b/chip/stm32/config-stm32l476.h @@ -1,20 +1,23 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Memory mapping */ -#define CONFIG_FLASH_SIZE 0x00100000 /* 1 MB */ -#define CONFIG_FLASH_BANK_SIZE 0x800 /* 2 kB */ -#define CONFIG_FLASH_ERASE_SIZE 0x800 /* 2 KB */ -#define CONFIG_FLASH_WRITE_SIZE 0x8 /* 64 bits (without 8 bits ECC) */ +#define CONFIG_FLASH_SIZE_BYTES 0x00100000 /* 1 MB */ +#define CONFIG_FLASH_BANK_SIZE 0x800 /* 2 kB */ +#define CONFIG_FLASH_ERASE_SIZE 0x800 /* 2 KB */ +#define CONFIG_FLASH_WRITE_SIZE 0x8 /* 64 bits (without 8 bits ECC) */ /* Ideal write size in page-mode */ -#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x100 /* 256 (32 double words) */ +#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x100 /* 256 (32 double words) */ -#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_BASE 0x20000000 /* Only using SRAM1. SRAM2 (32 KB) is ignored. */ -#define CONFIG_RAM_SIZE 0x00018000 /* 96 kB */ +#define CONFIG_RAM_SIZE 0x00018000 /* 96 kB */ /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 82 + +/* DFU Address */ +#define STM32_DFU_BASE 0x1fff0000 diff --git a/chip/stm32/config-stm32l552xe.h b/chip/stm32/config-stm32l552xe.h new file mode 100644 index 0000000000..ba11b7f098 --- /dev/null +++ b/chip/stm32/config-stm32l552xe.h @@ -0,0 +1,39 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Memory mapping */ +#define CONFIG_FLASH_SIZE_BYTES 0x00080000 /* 512 kB */ +#define CONFIG_FLASH_BANK_SIZE 0x800 /* 2 kB */ +#define CONFIG_FLASH_ERASE_SIZE 0x800 /* 2 KB */ +#define CONFIG_FLASH_WRITE_SIZE 0x8 /* 64 bits */ + +/* Ideal write size in page-mode */ +#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x100 /* 256 (32 double words) */ + +/* + * SRAM1 (48kB) at 0x20000000 + * SRAM2 (16kB) at 0x10000000 (and aliased at 0x2000C000) + * so they are contiguous. + */ +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00010000 /* 64 kB */ + +/* Number of IRQ vectors on the NVIC */ +#define CONFIG_IRQ_COUNT 109 + +/* USB packet ram config */ +#define CONFIG_USB_RAM_BASE 0x4000D800 +#define CONFIG_USB_RAM_SIZE 1024 +#define CONFIG_USB_RAM_ACCESS_TYPE uint16_t +#define CONFIG_USB_RAM_ACCESS_SIZE 2 + +#undef I2C_PORT_COUNT +#define I2C_PORT_COUNT 4 + +/* Number of DMA channels supported (8 channels each for DMA1 and DMA2) */ +#define DMAC_COUNT 16 + +/* DFU Address */ +#define STM32_DFU_BASE 0x0bf90000 diff --git a/chip/stm32/config_chip.h b/chip/stm32/config_chip.h index 35acf94c82..f6f211f4a5 100644 --- a/chip/stm32/config_chip.h +++ b/chip/stm32/config_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,12 +10,19 @@ /* CPU core BFD configuration */ #include "core/cortex-m0/config_core.h" /* IRQ priorities */ -#define STM32_IRQ_EXT0_1_PRIORITY 1 -#define STM32_IRQ_EXT2_3_PRIORITY 1 -#define STM32_IRQ_EXTI4_15_PRIORITY 1 +#define STM32_IRQ_EXT0_1_PRIORITY 1 +#define STM32_IRQ_EXT2_3_PRIORITY 1 +#define STM32_IRQ_EXTI4_15_PRIORITY 1 #else /* CPU core BFD configuration */ #include "core/cortex-m/config_core.h" +#define STM32_IRQ_EXTI0_PRIORITY 1 +#define STM32_IRQ_EXTI1_PRIORITY 1 +#define STM32_IRQ_EXTI2_PRIORITY 1 +#define STM32_IRQ_EXTI3_PRIORITY 1 +#define STM32_IRQ_EXTI4_PRIORITY 1 +#define STM32_IRQ_EXTI9_5_PRIORITY 1 +#define STM32_IRQ_EXTI15_10_PRIORITY 1 #endif /* Default to UART 1 for EC console */ @@ -38,6 +45,8 @@ #include "config-stm32l100.h" #elif defined(CHIP_VARIANT_STM32L442) #include "config-stm32l442.h" +#elif defined(CHIP_VARIANT_STM32L552XE) +#include "config-stm32l552xe.h" #elif defined(CHIP_VARIANT_STM32F76X) #include "config-stm32f76x.h" #elif defined(CHIP_FAMILY_STM32F4) @@ -61,6 +70,10 @@ #include "config-stm32h7x3.h" #elif defined(CHIP_VARIANT_STM32G431XB) #include "config-stm32g41xb.h" +#elif defined(CHIP_VARIANT_STM32G473XC) +#include "config-stm32g473xc.h" +#elif defined(CHIP_VARIANT_STM32L431X) +#include "config-stm32l431.h" #else #error "Unsupported chip variant" #endif @@ -74,10 +87,9 @@ /* Program is run directly from storage */ #define CONFIG_MAPPED_STORAGE_BASE CONFIG_PROGRAM_MEMORY_BASE -#if !defined(CHIP_FAMILY_STM32F4) && \ - !defined(CHIP_FAMILY_STM32F7) && \ - !defined(CHIP_FAMILY_STM32H7) && \ - !defined(CHIP_VARIANT_STM32F09X) +#if !defined(CHIP_FAMILY_STM32F4) && !defined(CHIP_FAMILY_STM32F7) && \ + !defined(CHIP_FAMILY_STM32H7) && !defined(CHIP_VARIANT_STM32F09X) && \ + !defined(CHIP_VARIANT_STM32L431X) /* Compute the rest of the flash params from these */ #include "config_std_internal_flash.h" #endif @@ -118,7 +130,7 @@ /* Interval between HOOK_TICK notifications */ #define HOOK_TICK_INTERVAL_MS 500 -#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) +#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) /* * Use a timer to print a watchdog warning event before the actual watchdog @@ -128,13 +140,13 @@ #define CONFIG_WATCHDOG_HELP /* Use DMA */ -#define CONFIG_DMA +#define CONFIG_DMA_CROS /* STM32 features RTC (optional feature) */ #define CONFIG_RTC /* Number of peripheral request signals per DMA channel */ -#define STM32_DMA_PERIPHERALS_PER_CHANNEL 4 +#define STM32_DMA_PERIPHERALS_PER_CHANNEL 4 /* * Use DMA for UART transmit for all platforms. DMA for UART receive is @@ -151,13 +163,13 @@ /* Chip needs to do custom pre-init */ #define CONFIG_CHIP_PRE_INIT -#define GPIO_NAME_BY_PIN(port, index) #port#index +#define GPIO_NAME_BY_PIN(port, index) #port #index #define GPIO_PIN(port, index) GPIO_##port, BIT(index) #define GPIO_PIN_MASK(p, m) .port = GPIO_##p, .mask = (m) -/* Prescaler values for PLL. Currently used only by STM32L476. */ -#define STM32_PLLM 0 -#define STM32_PLLN 0 -#define STM32_PLLR 0 +/* Prescaler values for PLL. Currently used only by STM32L476 and STM32L431. */ +#define STM32_PLLM 1 +#define STM32_PLLN 1 +#define STM32_PLLR 1 #endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/stm32/crc_hw.h b/chip/stm32/crc_hw.h index 2a50d5760e..495af2fb98 100644 --- a/chip/stm32/crc_hw.h +++ b/chip/stm32/crc_hw.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,8 +17,8 @@ static inline void crc32_init(void) /* Delay 1 AHB clock cycle after the clock is enabled */ clock_wait_bus_cycles(BUS_AHB, 1); /* reset CRC state */ - STM32_CRC_CR = STM32_CRC_CR_RESET | STM32_CRC_CR_REV_OUT - | STM32_CRC_CR_REV_IN_WORD; + STM32_CRC_CR = STM32_CRC_CR_RESET | STM32_CRC_CR_REV_OUT | + STM32_CRC_CR_REV_IN_WORD; while (STM32_CRC_CR & 1) ; } diff --git a/chip/stm32/debug_printf.c b/chip/stm32/debug_printf.c index c4e151692c..3713d28d26 100644 --- a/chip/stm32/debug_printf.c +++ b/chip/stm32/debug_printf.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -27,8 +27,6 @@ static int debug_txchar(void *context, int c) return 0; } - - void debug_printf(const char *format, ...) { va_list args; @@ -102,8 +100,8 @@ void uart_init(void) STM32_USART_BRR(UARTN_BASE) = DIV_ROUND_NEAREST(CPU_CLOCK, CONFIG_UART_BAUD_RATE); /* UART enabled, 8 Data bits, oversampling x16, no parity */ - STM32_USART_CR1(UARTN_BASE) = - STM32_USART_CR1_UE | STM32_USART_CR1_TE | STM32_USART_CR1_RE; + STM32_USART_CR1(UARTN_BASE) = STM32_USART_CR1_UE | STM32_USART_CR1_TE | + STM32_USART_CR1_RE; /* 1 stop bit, no fancy stuff */ STM32_USART_CR2(UARTN_BASE) = 0x0000; /* DMA disabled, special modes disabled, error interrupt disabled */ diff --git a/chip/stm32/debug_printf.h b/chip/stm32/debug_printf.h index 6091cfc7fc..efd74d40b9 100644 --- a/chip/stm32/debug_printf.h +++ b/chip/stm32/debug_printf.h @@ -1,17 +1,17 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Synchronous UART debug printf */ -#ifndef __CROS_EC_DEBUG_H -#define __CROS_EC_DEBUG_H +#ifndef __CROS_EC_DEBUG_PRINTF_H +#define __CROS_EC_DEBUG_PRINTF_H #ifdef CONFIG_DEBUG_PRINTF -__attribute__((__format__(__printf__, 1, 2))) -void debug_printf(const char *format, ...); +__attribute__((__format__(__printf__, 1, 2))) void +debug_printf(const char *format, ...); #else #define debug_printf(...) #endif -#endif /* __CROS_EC_DEBUG_H */ +#endif /* __CROS_EC_DEBUG_PRINTF_H */ diff --git a/chip/stm32/dfu_bootmanager_main.c b/chip/stm32/dfu_bootmanager_main.c new file mode 100644 index 0000000000..cec747e762 --- /dev/null +++ b/chip/stm32/dfu_bootmanager_main.c @@ -0,0 +1,212 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * DFU Boot Manager Main for STM32 + * + * When the Boot Manager Main is enabled, the RO application skips the + * common runtime and setup. This reduces the flash size and avoids clock, + * interrupt, and setup steps which conflict with the built in Boot Loaders + * while minimizing the Flash Size. + * + * The Boot Manager Main will perform self checks of the Flash and backup + * memory. Based on these results it will boot into the DFU or RW Application. + */ + +#include "clock.h" +#include "dfu_bootmanager_shared.h" +#include "flash.h" +#include "registers.h" +#include "task.h" + +#ifdef CONFIG_DFU_BOOTMANAGER_MAX_REBOOT_COUNT +#if CONFIG_DFU_BOOTMANAGER_MAX_REBOOT_COUNT <= 0 || \ + CONFIG_DFU_BOOTMANAGER_MAX_REBOOT_COUNT > DFU_BOOTMANAGER_VALUE_DFU +#error "Max reboot count is out of range" +#endif +#endif /* CONFIG_DFU_BOOTMANAGER_MAX_REBOOT_COUNT */ + +/* + * Checks if the RW region is valid by reading the first 8 bytes of flash, it + * should not start with an erased block. + * + * The DFU boot manager should not jump into the RW region if it contains + * invalid code as the EC is be unstable. A check will be performed to validate + * the start of the RW region to verify that it contains valid data. + * DFU programmers should erase this section of flash first and at this point, + * the EC will no longer be able to jump into the RW application. + * + * The normal DFU programming sequence programming will work, but by + * splitting into the following sequence we can protect against additional + * failures. + * + * 1. Erase the first RW flash section. This will lock the EC out of RW. + * 2. Update the remaining flash. Erase, program, and read back flash to + * to verify the operation was successful. Regions of the flash which + * are difficult to repair if an error occurs should be programmed next. + * 3. Program the first RW flash section and exit DFU mode if verification is + * successful. + * + * @return 1 if erased, 0 if not erased + */ +static int rw_is_empty(void) +{ + if (IS_ENABLED(CONFIG_FLASH_CROS)) + return crec_flash_is_erased(CONFIG_RW_MEM_OFF, 8); + /* No flash support, we cannot tell. Assume not empty. */ + return 0; +} + +/* + * Reads the backup registers. This will trigger a jump to DFU if either + * the application has requested it or if the reboot counter indicates + * the device is likely in a bad state. A counter recording the number + * of reboots will be incremented. + * + * @returns True if the backup memory region indicates we should boot into DFU. + */ +static bool backup_boot_checks(void) +{ + uint8_t value; + + if (dfu_bootmanager_backup_read(&value)) { + /* Value stored is not valid, set it to a valid value. */ + dfu_bootmanager_backup_write(DFU_BOOTMANAGER_VALUE_CLEAR); + return false; + } + if (value == DFU_BOOTMANAGER_VALUE_DFU) + return true; +#ifdef CONFIG_DFU_BOOTMANAGER_MAX_REBOOT_COUNT + if (value >= CONFIG_DFU_BOOTMANAGER_MAX_REBOOT_COUNT) + return true; + /* Increment the reboot loop counter. */ + value++; + dfu_bootmanager_backup_write(value); +#endif /* CONFIG_DFU_BOOTMANAGER_MAX_REBOOT_COUNT */ + return false; +} + +/* + * Performs the minimal set of initialization required for the boot manager. + * The main application region or DFU boot loader have different prerequisites, + * any configurations that are enabled either need to be benign with both + * images or disabled prior to the jumps. + */ +static void dfu_bootmanager_init(void) +{ + /* enable clock on Power module */ +#ifndef CHIP_FAMILY_STM32H7 +#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) + STM32_RCC_APB1ENR1 |= STM32_RCC_PWREN; +#else + STM32_RCC_APB1ENR |= STM32_RCC_PWREN; +#endif +#endif +#if defined(CHIP_FAMILY_STM32F4) + /* enable backup registers */ + STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_BKPSRAMEN; +#elif defined(CHIP_FAMILY_STM32H7) + /* enable backup registers */ + STM32_RCC_AHB4ENR |= BIT(28); +#elif defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) + /* enable RTC APB clock */ + STM32_RCC_APB1ENR1 |= STM32_RCC_APB1ENR1_RTCAPBEN; +#else + /* enable backup registers */ + STM32_RCC_APB1ENR |= BIT(27); +#endif + /* Delay 1 APB clock cycle after the clock is enabled */ + clock_wait_bus_cycles(BUS_APB, 1); + /* Enable access to RCC CSR register and RTC backup registers */ + STM32_PWR_CR |= BIT(8); +} + +/* + * Load stack pointer and reset vector from an ARM vector table, and jump. + */ +static void jump_to_arm_reset_vector(uint32_t addr) +{ + /* + * The first 32-bit entry ARM vector table is the initial value of the + * stack pointer, the second entry is the reset vector. + */ + asm("mov r1, %0\n" + /* Load stack pointer */ + "ldr r0, [r1, 0]\n" + "msr msp, r0\n" + /* + * Memory barrier to ensure subsequent instructions uses modified + * stack pointer. + */ + "isb\n" + /* Load reset vector */ + "ldr r0, [r1, 4]\n" + /* Jump without saving return address (would modify msp) */ + "bx r0\n" + : /* no outputs */ + : "r"(addr) + :); +} + +static void jump_to_rw(void) +{ + jump_to_arm_reset_vector(CONFIG_PROGRAM_MEMORY_BASE + + CONFIG_RW_MEM_OFF); +} + +static void jump_to_dfu(void) +{ + /* Clear the scratchpad. */ + dfu_bootmanager_backup_write(DFU_BOOTMANAGER_VALUE_CLEAR); + + jump_to_arm_reset_vector(STM32_DFU_BASE); +} + +/* + * DFU Boot Manager main. It'll check if the RW region is not fully programmed + * or if the backup memory indicates we should reboot into DFU. + */ +int main(void) +{ + dfu_bootmanager_init(); + + if (rw_is_empty() || backup_boot_checks()) + jump_to_dfu(); + jump_to_rw(); + + return 0; +} + +/* + * The RW application will replace the vector table and exception handlers + * shortly after the jump. If the application is corrupt and fails before + * this, the only action that can be done is jumping into DFU mode. + */ +void __keep exception_panic(void) +{ + dfu_bootmanager_enter_dfu(); +} + +/* + * Function stubs which are required by bkpdata.c and system.c: + * Interrupts are always disabled in the Boot Manager so we do not + * need to worry about concurrent access. + */ + +void task_clear_pending_irq(int irq) +{ +} +void interrupt_disable(void) +{ +} +void mutex_lock(mutex_t *mtx) +{ +} +void mutex_unlock(mutex_t *mtx) +{ +} + +bool in_interrupt_context(void) +{ + return false; +} diff --git a/chip/stm32/dfu_bootmanager_shared.c b/chip/stm32/dfu_bootmanager_shared.c new file mode 100644 index 0000000000..de8edcff5d --- /dev/null +++ b/chip/stm32/dfu_bootmanager_shared.c @@ -0,0 +1,52 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * DFU Boot Manager shared utilities for STM32 + */ + +#include "bkpdata.h" +#include "clock.h" +#include "dfu_bootmanager_shared.h" +#include "flash.h" +#include "registers.h" +#include "task.h" + +/* + * The Servo platforms do not have any free backup regions. The scratchpad + * is only with the console command scratchpad and on some of the tests so + * we'll use the scratchpad region. + */ +#ifdef CONFIG_CMD_SCRATCHPAD +#error "The scratchpad is used, define a backup region for the DFU fields." +#endif /* CONFIG_CMD_SCRATCHPAD */ + +int dfu_bootmanager_enter_dfu(void) +{ + dfu_bootmanager_backup_write(DFU_BOOTMANAGER_VALUE_DFU); + system_reset(0); + return 0; +} + +void dfu_bootmanager_clear(void) +{ + dfu_bootmanager_backup_write(DFU_BOOTMANAGER_VALUE_CLEAR); +} + +void dfu_bootmanager_backup_write(uint8_t value) +{ + uint16_t data = DFU_BOOTMANAGER_VALID_CHECK | value; + + bkpdata_write(BKPDATA_INDEX_SCRATCHPAD, data); +} + +int dfu_bootmanager_backup_read(uint8_t *value) +{ + uint16_t data = bkpdata_read(BKPDATA_INDEX_SCRATCHPAD); + uint16_t valid_check = data & DFU_BOOTMANAGER_VALID_MASK; + + *value = (uint8_t)(data & DFU_BOOTMANAGER_VALUE_MASK); + if (valid_check != DFU_BOOTMANAGER_VALID_CHECK) + return EC_ERROR_UNKNOWN; + return EC_SUCCESS; +} diff --git a/chip/stm32/dfu_bootmanager_shared.h b/chip/stm32/dfu_bootmanager_shared.h new file mode 100644 index 0000000000..df920f16a5 --- /dev/null +++ b/chip/stm32/dfu_bootmanager_shared.h @@ -0,0 +1,62 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * DFU Boot Manager shared utilities for STM32 + * + * These of utilities required by the Boot Manager Main and RW Application. + * These allow the systems to start the sequence to enter DFU, clear the + * state, and access the backup registers. + */ + +#ifndef __DFU_BOOTMANAGER_SHARED_H +#define __DFU_BOOTMANAGER_SHARED_H + +#include "common.h" + +/* Registers to validate the backup memory region. */ +#define DFU_BOOTMANAGER_VALUE_MASK 0x00FF +#define DFU_BOOTMANAGER_VALID_MASK 0xFF00 +#define DFU_BOOTMANAGER_VALID_CHECK 0xAA00 + +#define DFU_BOOTMANAGER_VALUE_CLEAR 0 +#define DFU_BOOTMANAGER_VALUE_DFU UINT8_MAX + +/* + * Reset and enter the DFU mode. + * + * The system will set flags to the backup memory to enter DFU and issue + * a reset. The Boot Manager will send the system to DFU mode. + * + * @return EC_SUCCESS, or non-zero if error. + */ +int dfu_bootmanager_enter_dfu(void); + +/* + * Clear the DFU Boot Manager backup memory state. + * + * If the CONFIG_DFU_BOOTMANAGER_MAX_REBOOT_COUNT setting is enabled, this + * allows the RW application to clear the counter to indicate the application + * is working as expected. + */ +void dfu_bootmanager_clear(void); + +/* + * Write the value to the backup registers and sets the bitmasks + * indicating the field is valid. + * + * @param value New value to store. + */ +void dfu_bootmanager_backup_write(uint8_t value); + +/* + * Reads the backup registers and performs validation. The value stored + * within the VALUE_MASK is returned and the status code indicates + * if the valid check passed. + * + * @param value[out] Value stored within the DFU_BOOTMANAGER_VALUE_MASK + * @return EC_SUCCESS, or non-zero if validation failed. + */ +int dfu_bootmanager_backup_read(uint8_t *value); + +#endif /* __DFU_BOOTMANAGER_SHARED_H */ diff --git a/chip/stm32/dma-stm32f4.c b/chip/stm32/dma-stm32f4.c index abb33befda..15fb0f28ef 100644 --- a/chip/stm32/dma-stm32f4.c +++ b/chip/stm32/dma-stm32f4.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,15 +14,15 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_DMA, outstr) -#define CPRINTF(format, args...) cprintf(CC_DMA, format, ## args) -#define CPRINTS(format, args...) cprints(CC_DMA, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_DMA, format, ##args) +#define CPRINTS(format, args...) cprints(CC_DMA, format, ##args) stm32_dma_regs_t *STM32_DMA_REGS[] = { STM32_DMA1_REGS, STM32_DMA2_REGS }; /* Callback data to use when IRQ fires */ static struct { - void (*cb)(void *); /* Callback function to call */ - void *cb_data; /* Callback data for callback function */ + void (*cb)(void *); /* Callback function to call */ + void *cb_data; /* Callback data for callback function */ } dma_irq[STM32_DMAS_TOTAL_COUNT]; /** @@ -90,8 +90,8 @@ void dma_disable_all(void) * @param memory Pointer to memory address for receive/transmit * @param flags DMA flags for the control register. */ -static void prepare_stream(enum dma_channel stream, unsigned count, - void *periph, void *memory, unsigned flags) +static void prepare_stream(enum dma_channel stream, unsigned int count, + void *periph, void *memory, unsigned int flags) { stm32_dma_stream_t *dma_stream = dma_get_channel(stream); uint32_t ccr = STM32_DMA_CCR_PL_VERY_HIGH; @@ -120,7 +120,7 @@ void dma_go(stm32_dma_stream_t *stream) stream->scr |= STM32_DMA_CCR_EN; } -void dma_prepare_tx(const struct dma_option *option, unsigned count, +void dma_prepare_tx(const struct dma_option *option, unsigned int count, const void *memory) { /* @@ -128,18 +128,18 @@ void dma_prepare_tx(const struct dma_option *option, unsigned count, * we're preparing the stream for transmit. */ prepare_stream(option->channel, count, option->periph, (void *)memory, - STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR_M2P | - option->flags); + STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR_M2P | + option->flags); } -void dma_start_rx(const struct dma_option *option, unsigned count, +void dma_start_rx(const struct dma_option *option, unsigned int count, void *memory) { stm32_dma_stream_t *stream = dma_get_channel(option->channel); prepare_stream(option->channel, count, option->periph, memory, - STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR_P2M | - option->flags); + STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR_P2M | + option->flags); dma_go(stream); } @@ -176,10 +176,8 @@ void dma_dump(enum dma_channel stream) CPRINTF("scr=%x, sndtr=%x, spar=%x, sm0ar=%x, sfcr=%x\n", dma_stream->scr, dma_stream->sndtr, dma_stream->spar, dma_stream->sm0ar, dma_stream->sfcr); - CPRINTF("stream %d, isr=%x, ifcr=%x\n", - stream, - STM32_DMA_GET_ISR(stream), - STM32_DMA_GET_IFCR(stream)); + CPRINTF("stream %d, isr=%x, ifcr=%x\n", stream, + STM32_DMA_GET_ISR(stream), STM32_DMA_GET_IFCR(stream)); } void dma_check(enum dma_channel stream, char *buf) @@ -206,7 +204,7 @@ void dma_test(enum dma_channel stream) stm32_dma_stream_t *dma_stream = dma_get_channel(stream); uint32_t ctrl; char periph[32], memory[32]; - unsigned count = sizeof(periph); + unsigned int count = sizeof(periph); int i; memset(memory, '\0', sizeof(memory)); @@ -218,7 +216,7 @@ void dma_test(enum dma_channel stream) dma_stream->spar = (uint32_t)periph; dma_stream->sm0ar = (uint32_t)memory; dma_stream->sndtr = count; - dma_stream->sfcr &= ~STM32_DMA_SFCR_DMDIS; + dma_stream->sfcr &= ~STM32_DMA_SFCR_DMDIS; ctrl = STM32_DMA_CCR_PL_MEDIUM; dma_stream->scr = ctrl; @@ -261,7 +259,7 @@ static inline void _dma_wake_callback(void *cb_data) task_id_t id = (task_id_t)(int)cb_data; if (id != TASK_ID_INVALID) - task_set_event(id, TASK_EVENT_DMA_TC, 0); + task_set_event(id, TASK_EVENT_DMA_TC); } void dma_enable_tc_interrupt(enum dma_channel stream) @@ -300,17 +298,17 @@ void dma_clear_isr(enum dma_channel stream) } #ifdef CONFIG_DMA_DEFAULT_HANDLERS -#define STM32_DMA_IDX(dma, x) CONCAT4(STM32_DMA, dma, _STREAM, x) -#define STM32_DMA_FCT(dma, x) CONCAT4(dma_, dma, _event_interrupt_stream_, x) -#define DECLARE_DMA_IRQ(dma, x) \ - void STM32_DMA_FCT(dma, x)(void) \ - { \ - dma_clear_isr(STM32_DMA_IDX(dma, x)); \ - if (dma_irq[STM32_DMA_IDX(dma, x)].cb != NULL) \ - (*dma_irq[STM32_DMA_IDX(dma, x)].cb) \ - (dma_irq[STM32_DMA_IDX(dma, x)].cb_data); \ - } \ - DECLARE_IRQ(CONCAT4(STM32_IRQ_DMA, dma, _STREAM, x), \ +#define STM32_DMA_IDX(dma, x) CONCAT4(STM32_DMA, dma, _STREAM, x) +#define STM32_DMA_FCT(dma, x) CONCAT4(dma_, dma, _event_interrupt_stream_, x) +#define DECLARE_DMA_IRQ(dma, x) \ + static void STM32_DMA_FCT(dma, x)(void) \ + { \ + dma_clear_isr(STM32_DMA_IDX(dma, x)); \ + if (dma_irq[STM32_DMA_IDX(dma, x)].cb != NULL) \ + (*dma_irq[STM32_DMA_IDX(dma, x)].cb)( \ + dma_irq[STM32_DMA_IDX(dma, x)].cb_data); \ + } \ + DECLARE_IRQ(CONCAT4(STM32_IRQ_DMA, dma, _STREAM, x), \ STM32_DMA_FCT(dma, x), 1); DECLARE_DMA_IRQ(1, 0); @@ -331,4 +329,3 @@ DECLARE_DMA_IRQ(2, 6); DECLARE_DMA_IRQ(2, 7); #endif /* CONFIG_DMA_DEFAULT_HANDLERS */ - diff --git a/chip/stm32/dma.c b/chip/stm32/dma.c index a2ed6ca3cb..fbf0d59627 100644 --- a/chip/stm32/dma.c +++ b/chip/stm32/dma.c @@ -1,8 +1,9 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "clock.h" #include "common.h" #include "console.h" @@ -15,15 +16,14 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_DMA, outstr) -#define CPRINTF(format, args...) cprintf(CC_DMA, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_DMA, format, ##args) /* Callback data to use when IRQ fires */ static struct { - void (*cb)(void *); /* Callback function to call */ - void *cb_data; /* Callback data for callback function */ + void (*cb)(void *); /* Callback function to call */ + void *cb_data; /* Callback data for callback function */ } dma_irq[STM32_DMAC_COUNT]; - /** * Return the IRQ for the DMA channel * @@ -36,15 +36,25 @@ static int dma_get_irq(enum dma_channel channel) if (channel == STM32_DMAC_CH1) return STM32_IRQ_DMA_CHANNEL_1; - return channel > STM32_DMAC_CH3 ? - STM32_IRQ_DMA_CHANNEL_4_7 : - STM32_IRQ_DMA_CHANNEL_2_3; + return channel > STM32_DMAC_CH3 ? STM32_IRQ_DMA_CHANNEL_4_7 : + STM32_IRQ_DMA_CHANNEL_2_3; +#elif defined(CHIP_FAMILY_STM32L4) + if (channel < STM32_DMAC_PER_CTLR) + return STM32_IRQ_DMA_CHANNEL_1 + channel; + else { + if (channel <= STM32_DMAC_CH13) + return STM32_IRQ_DMA2_CHANNEL1 + + (channel - STM32_DMAC_PER_CTLR); + else + return STM32_IRQ_DMA2_CHANNEL6 + + (channel - STM32_DMAC_PER_CTLR - 5); + } #else if (channel < STM32_DMAC_PER_CTLR) return STM32_IRQ_DMA_CHANNEL_1 + channel; else return STM32_IRQ_DMA2_CHANNEL1 + - (channel - STM32_DMAC_PER_CTLR); + (channel - STM32_DMAC_PER_CTLR); #endif } @@ -99,6 +109,7 @@ void dma_disable_all(void) for (ch = 0; ch < STM32_DMAC_COUNT; ch++) { stm32_dma_chan_t *chan = dma_get_channel(ch); + chan->ccr &= ~STM32_DMA_CCR_EN; } } @@ -114,8 +125,8 @@ void dma_disable_all(void) * STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR for tx * 0 for rx */ -static void prepare_channel(enum dma_channel channel, unsigned count, - void *periph, void *memory, unsigned flags) +static void prepare_channel(enum dma_channel channel, unsigned int count, + void *periph, void *memory, unsigned int flags) { stm32_dma_chan_t *chan = dma_get_channel(channel); uint32_t ccr = STM32_DMA_CCR_PL_VERY_HIGH; @@ -141,7 +152,7 @@ void dma_go(stm32_dma_chan_t *chan) chan->ccr |= STM32_DMA_CCR_EN; } -void dma_prepare_tx(const struct dma_option *option, unsigned count, +void dma_prepare_tx(const struct dma_option *option, unsigned int count, const void *memory) { /* @@ -149,14 +160,14 @@ void dma_prepare_tx(const struct dma_option *option, unsigned count, * we're preparing the channel for transmit. */ prepare_channel(option->channel, count, option->periph, (void *)memory, - STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR | - option->flags); + STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR | option->flags); } -void dma_start_rx(const struct dma_option *option, unsigned count, +void dma_start_rx(const struct dma_option *option, unsigned int count, void *memory) { stm32_dma_chan_t *chan = dma_get_channel(option->channel); + prepare_channel(option->channel, count, option->periph, memory, STM32_DMA_CCR_MINC | option->flags); dma_go(chan); @@ -178,10 +189,9 @@ void dma_dump(enum dma_channel channel) stm32_dma_regs_t *dma = STM32_DMA_REGS(channel); stm32_dma_chan_t *chan = dma_get_channel(channel); - CPRINTF("ccr=%x, cndtr=%x, cpar=%x, cmar=%x\n", chan->ccr, - chan->cndtr, chan->cpar, chan->cmar); - CPRINTF("chan %d, isr=%x, ifcr=%x\n", - channel, + CPRINTF("ccr=%x, cndtr=%x, cpar=%x, cmar=%x\n", chan->ccr, chan->cndtr, + chan->cpar, chan->cmar); + CPRINTF("chan %d, isr=%x, ifcr=%x\n", channel, (dma->isr >> ((channel % STM32_DMAC_PER_CTLR) * 4)) & 0xf, (dma->ifcr >> ((channel % STM32_DMAC_PER_CTLR) * 4)) & 0xf); } @@ -211,7 +221,7 @@ void dma_test(enum dma_channel channel) stm32_dma_chan_t *chan = dma_get_channel(channel); uint32_t ctrl; char periph[16], memory[16]; - unsigned count = sizeof(periph); + unsigned int count = sizeof(periph); int i; memset(memory, '\0', sizeof(memory)); @@ -225,11 +235,12 @@ void dma_test(enum dma_channel channel) ctrl = STM32_DMA_CCR_PL_MEDIUM; chan->ccr = ctrl; - ctrl |= STM32_DMA_CCR_MINC; /* | STM32_DMA_CCR_DIR */; + ctrl |= STM32_DMA_CCR_MINC; /* | STM32_DMA_CCR_DIR */ + ; ctrl |= STM32_DMA_CCR_MEM2MEM; ctrl |= STM32_DMA_CCR_PINC; -/* ctrl |= STM32_DMA_CCR_MSIZE_32_BIT; */ -/* ctrl |= STM32_DMA_CCR_PSIZE_32_BIT; */ + /* ctrl |= STM32_DMA_CCR_MSIZE_32_BIT; */ + /* ctrl |= STM32_DMA_CCR_PSIZE_32_BIT; */ chan->ccr = ctrl; chan->ccr = ctrl | STM32_DMA_CCR_EN; @@ -242,10 +253,12 @@ void dma_test(enum dma_channel channel) void dma_init(void) { #if defined(CHIP_FAMILY_STM32L4) - STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_DMA1EN|STM32_RCC_AHB1ENR_DMA2EN; -#elif defined(CHIP_FAMILY_STM32G4) - STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_DMA1EN|STM32_RCC_AHB1ENR_DMA2EN | - STM32_RCC_AHB1ENR_DMAMUXEN; + STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_DMA1EN | + STM32_RCC_AHB1ENR_DMA2EN; +#elif defined(CHIP_FAMILY_STM32G4) || defined(CHIP_FAMILY_STM32L5) + STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_DMA1EN | + STM32_RCC_AHB1ENR_DMA2EN | + STM32_RCC_AHB1ENR_DMAMUXEN; #else STM32_RCC_AHBENR |= STM32_RCC_HB_DMA1; #endif @@ -275,8 +288,9 @@ int dma_wait(enum dma_channel channel) static inline void _dma_wake_callback(void *cb_data) { task_id_t id = (task_id_t)(int)cb_data; + if (id != TASK_ID_INVALID) - task_set_event(id, TASK_EVENT_DMA_TC, 0); + task_set_event(id, TASK_EVENT_DMA_TC); } void dma_enable_tc_interrupt(enum dma_channel channel) @@ -318,18 +332,18 @@ void dma_clear_isr(enum dma_channel channel) #ifdef CONFIG_DMA_DEFAULT_HANDLERS #ifdef CHIP_FAMILY_STM32F0 -void dma_event_interrupt_channel_1(void) +static void dma_event_interrupt_channel_1(void) { if (STM32_DMA1_REGS->isr & STM32_DMA_ISR_TCIF(STM32_DMAC_CH1)) { dma_clear_isr(STM32_DMAC_CH1); if (dma_irq[STM32_DMAC_CH1].cb != NULL) - (*dma_irq[STM32_DMAC_CH1].cb) - (dma_irq[STM32_DMAC_CH1].cb_data); + (*dma_irq[STM32_DMAC_CH1].cb)( + dma_irq[STM32_DMAC_CH1].cb_data); } } DECLARE_IRQ(STM32_IRQ_DMA_CHANNEL_1, dma_event_interrupt_channel_1, 1); -void dma_event_interrupt_channel_2_3(void) +static void dma_event_interrupt_channel_2_3(void) { int i; @@ -343,12 +357,10 @@ void dma_event_interrupt_channel_2_3(void) } DECLARE_IRQ(STM32_IRQ_DMA_CHANNEL_2_3, dma_event_interrupt_channel_2_3, 1); -void dma_event_interrupt_channel_4_7(void) +static void dma_event_interrupt_channel_4_7(void) { int i; - const unsigned int max_chan = MIN(STM32_DMAC_CH7, STM32_DMAC_COUNT); - - for (i = STM32_DMAC_CH4; i <= max_chan; i++) { + for (i = STM32_DMAC_CH4; i < STM32_DMAC_COUNT; i++) { if (STM32_DMA1_REGS->isr & STM32_DMA_ISR_TCIF(i)) { dma_clear_isr(i); if (dma_irq[i].cb != NULL) @@ -360,16 +372,16 @@ DECLARE_IRQ(STM32_IRQ_DMA_CHANNEL_4_7, dma_event_interrupt_channel_4_7, 1); #else /* !CHIP_FAMILY_STM32F0 */ -#define DECLARE_DMA_IRQ(x) \ - void CONCAT2(dma_event_interrupt_channel_, x)(void) \ - { \ - dma_clear_isr(CONCAT2(STM32_DMAC_CH, x)); \ - if (dma_irq[CONCAT2(STM32_DMAC_CH, x)].cb != NULL) \ - (*dma_irq[CONCAT2(STM32_DMAC_CH, x)].cb) \ - (dma_irq[CONCAT2(STM32_DMAC_CH, x)].cb_data); \ - } \ - DECLARE_IRQ(CONCAT2(STM32_IRQ_DMA_CHANNEL_, x), \ - CONCAT2(dma_event_interrupt_channel_, x), 1); +#define DECLARE_DMA_IRQ(x) \ + static void CONCAT2(dma_event_interrupt_channel_, x)(void) \ + { \ + dma_clear_isr(CONCAT2(STM32_DMAC_CH, x)); \ + if (dma_irq[CONCAT2(STM32_DMAC_CH, x)].cb != NULL) \ + (*dma_irq[CONCAT2(STM32_DMAC_CH, x)].cb)( \ + dma_irq[CONCAT2(STM32_DMAC_CH, x)].cb_data); \ + } \ + DECLARE_IRQ(CONCAT2(STM32_IRQ_DMA_CHANNEL_, x), \ + CONCAT2(dma_event_interrupt_channel_, x), 1) DECLARE_DMA_IRQ(1); DECLARE_DMA_IRQ(2); @@ -382,6 +394,15 @@ DECLARE_DMA_IRQ(7); DECLARE_DMA_IRQ(9); DECLARE_DMA_IRQ(10); #endif +#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) +DECLARE_DMA_IRQ(9); +DECLARE_DMA_IRQ(10); +DECLARE_DMA_IRQ(11); +DECLARE_DMA_IRQ(12); +DECLARE_DMA_IRQ(13); +DECLARE_DMA_IRQ(14); +DECLARE_DMA_IRQ(15); +#endif #endif /* CHIP_FAMILY_STM32F0 */ #endif /* CONFIG_DMA_DEFAULT_HANDLERS */ diff --git a/chip/stm32/flash-f.c b/chip/stm32/flash-f.c index b192d44255..2673201472 100644 --- a/chip/stm32/flash-f.c +++ b/chip/stm32/flash-f.c @@ -1,27 +1,29 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Common flash memory module for STM32F and STM32F0 */ -#include #include "battery.h" -#include "console.h" +#include "builtin/assert.h" #include "clock.h" -#include "flash.h" +#include "console.h" #include "flash-f.h" +#include "flash.h" #include "hooks.h" -#include "registers.h" #include "panic.h" +#include "registers.h" #include "system.h" #include "task.h" #include "timer.h" #include "util.h" #include "watchdog.h" -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#include + +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /* * Approximate number of CPU cycles per iteration of the loop when polling @@ -49,14 +51,15 @@ /* Forward declarations */ #if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE) -static enum flash_rdp_level flash_physical_get_rdp_level(void); + static enum flash_rdp_level + flash_physical_get_rdp_level(void); static int flash_physical_set_rdp_level(enum flash_rdp_level level); #endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */ static inline int calculate_flash_timeout(void) { - return (FLASH_WRITE_TIMEOUT_US * - (clock_get_freq() / SECOND) / CYCLE_PER_FLASH_LOOP); + return (FLASH_WRITE_TIMEOUT_US * (clock_get_freq() / SECOND) / + CYCLE_PER_FLASH_LOOP); } static int wait_busy(void) @@ -67,7 +70,6 @@ static int wait_busy(void) return (timeout > 0) ? EC_SUCCESS : EC_ERROR_TIMEOUT; } - void unlock_flash_control_register(void) { STM32_FLASH_KEYR = FLASH_KEYR_KEY1; @@ -134,7 +136,7 @@ bool flash_control_register_locked(void) * We at least unlock the control register lock. * We may also unlock other locks. */ -enum extra_lock_type { +enum extra_lock_type { NO_EXTRA_LOCK = 0, OPT_LOCK = 1, }; @@ -341,7 +343,7 @@ bool is_flash_rdp_enabled(void) /*****************************************************************************/ /* Physical layer APIs */ -int flash_physical_write(int offset, int size, const char *data) +int crec_flash_physical_write(int offset, int size, const char *data) { #if CONFIG_FLASH_WRITE_SIZE == 1 uint8_t *address = (uint8_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset); @@ -382,9 +384,7 @@ int flash_physical_write(int offset, int size, const char *data) watchdog_reload(); /* wait to be ready */ - for (i = 0; - (STM32_FLASH_SR & FLASH_SR_BUSY) && - (i < timeout); + for (i = 0; (STM32_FLASH_SR & FLASH_SR_BUSY) && (i < timeout); i++) ; @@ -392,9 +392,7 @@ int flash_physical_write(int offset, int size, const char *data) *address++ = quantum; /* Wait for writes to complete */ - for (i = 0; - (STM32_FLASH_SR & FLASH_SR_BUSY) && - (i < timeout); + for (i = 0; (STM32_FLASH_SR & FLASH_SR_BUSY) && (i < timeout); i++) ; @@ -420,16 +418,16 @@ int flash_physical_write(int offset, int size, const char *data) return res; } -int flash_physical_erase(int offset, int size) +int crec_flash_physical_erase(int offset, int size) { int res = EC_SUCCESS; int sector_size; int timeout_us; #ifdef CHIP_FAMILY_STM32F4 - int sector = flash_bank_index(offset); + int sector = crec_flash_bank_index(offset); /* we take advantage of sector_size == erase_size */ - if ((sector < 0) || (flash_bank_index(offset + size) < 0)) - return EC_ERROR_INVAL; /* Invalid range */ + if ((sector < 0) || (crec_flash_bank_index(offset + size) < 0)) + return EC_ERROR_INVAL; /* Invalid range */ #endif if (unlock(NO_EXTRA_LOCK) != EC_SUCCESS) @@ -444,7 +442,7 @@ int flash_physical_erase(int offset, int size) while (size > 0) { timestamp_t deadline; #ifdef CHIP_FAMILY_STM32F4 - sector_size = flash_bank_size(sector); + sector_size = crec_flash_bank_size(sector); /* Timeout: from spec, proportional to the size * inversely proportional to the write size. */ @@ -454,12 +452,12 @@ int flash_physical_erase(int offset, int size) timeout_us = FLASH_ERASE_TIMEOUT_US; #endif /* Do nothing if already erased */ - if (flash_is_erased(offset, sector_size)) + if (crec_flash_is_erased(offset, sector_size)) goto next_sector; #ifdef CHIP_FAMILY_STM32F4 /* select page to erase */ STM32_FLASH_CR = (STM32_FLASH_CR & ~STM32_FLASH_CR_SNB_MASK) | - (sector << STM32_FLASH_CR_SNB_OFFSET); + (sector << STM32_FLASH_CR_SNB_OFFSET); #else /* select page to erase */ STM32_FLASH_AR = CONFIG_PROGRAM_MEMORY_BASE + offset; @@ -472,7 +470,7 @@ int flash_physical_erase(int offset, int size) watchdog_reload(); while ((STM32_FLASH_SR & FLASH_SR_BUSY) && (get_time().val < deadline.val)) { - usleep(timeout_us/100); + usleep(timeout_us / 100); } if (STM32_FLASH_SR & FLASH_SR_BUSY) { res = EC_ERROR_TIMEOUT; @@ -487,7 +485,7 @@ int flash_physical_erase(int offset, int size) res = EC_ERROR_UNKNOWN; goto exit_er; } -next_sector: + next_sector: size -= sector_size; offset += sector_size; #ifdef CHIP_FAMILY_STM32F4 @@ -533,15 +531,14 @@ static int flash_physical_protect_at_boot_update_rdp_pstate(uint32_t new_flags) #endif } -int flash_physical_protect_at_boot(uint32_t new_flags) +int crec_flash_physical_protect_at_boot(uint32_t new_flags) { int block; int original_val, val; original_val = val = STM32_OPTB_WP & STM32_OPTB_nWRP_ALL; - for (block = WP_BANK_OFFSET; - block < WP_BANK_OFFSET + PHYSICAL_BANKS; + for (block = WP_BANK_OFFSET; block < WP_BANK_OFFSET + PHYSICAL_BANKS; block++) { int protect = new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT; @@ -573,14 +570,14 @@ static void unprotect_all_blocks(void) write_optb(STM32_FLASH_nWRP_ALL, STM32_FLASH_nWRP_ALL); } -#else /* CHIP_FAMILY_STM32F4 */ +#else /* CHIP_FAMILY_STM32F4 */ static int flash_physical_get_protect_at_boot(int block) { - uint8_t val = read_optb(STM32_OPTB_WRP_OFF(block/8)); + uint8_t val = read_optb(STM32_OPTB_WRP_OFF(block / 8)); return (!(val & (1 << (block % 8)))) ? 1 : 0; } -int flash_physical_protect_at_boot(uint32_t new_flags) +int crec_flash_physical_protect_at_boot(uint32_t new_flags) { int block; int i; @@ -589,11 +586,10 @@ int flash_physical_protect_at_boot(uint32_t new_flags) for (i = 0; i < 4; ++i) original_val[i] = val[i] = read_optb(i * 2 + 8); - for (block = WP_BANK_OFFSET; - block < WP_BANK_OFFSET + PHYSICAL_BANKS; + for (block = WP_BANK_OFFSET; block < WP_BANK_OFFSET + PHYSICAL_BANKS; block++) { int protect = new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT; - int byte_off = STM32_OPTB_WRP_OFF(block/8) / 2 - 4; + int byte_off = STM32_OPTB_WRP_OFF(block / 8) / 2 - 4; if (block >= WP_BANK_OFFSET && block < WP_BANK_OFFSET + WP_BANK_COUNT) @@ -601,7 +597,8 @@ int flash_physical_protect_at_boot(uint32_t new_flags) #ifdef CONFIG_ROLLBACK else if (block >= ROLLBACK_BANK_OFFSET && block < ROLLBACK_BANK_OFFSET + ROLLBACK_BANK_COUNT) - protect |= new_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT; + protect |= new_flags & + EC_FLASH_PROTECT_ROLLBACK_AT_BOOT; #endif #ifdef CONFIG_FLASH_PROTECT_RW else @@ -646,7 +643,7 @@ static void unprotect_all_blocks(void) */ static int registers_need_reset(void) { - uint32_t flags = flash_get_protect(); + uint32_t flags = crec_flash_get_protect(); int i; int ro_at_boot = (flags & EC_FLASH_PROTECT_RO_AT_BOOT) ? 1 : 0; int ro_wp_region_start = WP_BANK_OFFSET; @@ -723,22 +720,21 @@ enum flash_rdp_level flash_physical_get_rdp_level(void) /*****************************************************************************/ /* High-level APIs */ -int flash_pre_init(void) +int crec_flash_pre_init(void) { uint32_t reset_flags = system_get_reset_flags(); - uint32_t prot_flags = flash_get_protect(); + uint32_t prot_flags = crec_flash_get_protect(); int need_reset = 0; - #ifdef CHIP_FAMILY_STM32F4 unlock(NO_EXTRA_LOCK); /* Set the proper write size */ STM32_FLASH_CR = (STM32_FLASH_CR & ~STM32_FLASH_CR_PSIZE_MASK) | - (31 - __builtin_clz(CONFIG_FLASH_WRITE_SIZE)) << - STM32_FLASH_CR_PSIZE_OFFSET; + (31 - __builtin_clz(CONFIG_FLASH_WRITE_SIZE)) + << STM32_FLASH_CR_PSIZE_OFFSET; lock(); #endif - if (flash_physical_restore_state()) + if (crec_flash_physical_restore_state()) return EC_SUCCESS; /* @@ -751,7 +747,7 @@ int flash_pre_init(void) if (prot_flags & EC_FLASH_PROTECT_GPIO_ASSERTED) { if (prot_flags & EC_FLASH_PROTECT_RO_NOW) { /* Enable physical protection for RO (0 means RO). */ - flash_physical_protect_now(0); + crec_flash_physical_protect_now(0); } if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) && @@ -762,7 +758,7 @@ int flash_pre_init(void) * update to the write protect register and reboot so * it takes effect. */ - flash_physical_protect_at_boot( + crec_flash_physical_protect_at_boot( EC_FLASH_PROTECT_RO_AT_BOOT); need_reset = 1; } @@ -776,8 +772,8 @@ int flash_pre_init(void) * to the check above. One of them should be able to * go away. */ - flash_protect_at_boot( - prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT); + crec_flash_protect_at_boot(prot_flags & + EC_FLASH_PROTECT_RO_AT_BOOT); need_reset = 1; } } else { @@ -791,7 +787,8 @@ int flash_pre_init(void) } } - if ((flash_physical_get_valid_flags() & EC_FLASH_PROTECT_ALL_AT_BOOT) && + if ((crec_flash_physical_get_valid_flags() & + EC_FLASH_PROTECT_ALL_AT_BOOT) && (!!(prot_flags & EC_FLASH_PROTECT_ALL_AT_BOOT) != !!(prot_flags & EC_FLASH_PROTECT_ALL_NOW))) { /* @@ -806,7 +803,8 @@ int flash_pre_init(void) } #ifdef CONFIG_FLASH_PROTECT_RW - if ((flash_physical_get_valid_flags() & EC_FLASH_PROTECT_RW_AT_BOOT) && + if ((crec_flash_physical_get_valid_flags() & + EC_FLASH_PROTECT_RW_AT_BOOT) && (!!(prot_flags & EC_FLASH_PROTECT_RW_AT_BOOT) != !!(prot_flags & EC_FLASH_PROTECT_RW_NOW))) { /* RW_AT_BOOT and RW_NOW do not match. */ @@ -815,7 +813,8 @@ int flash_pre_init(void) #endif #ifdef CONFIG_ROLLBACK - if ((flash_physical_get_valid_flags() & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) && + if ((crec_flash_physical_get_valid_flags() & + EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) && (!!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) != !!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_NOW))) { /* ROLLBACK_AT_BOOT and ROLLBACK_NOW do not match. */ diff --git a/chip/stm32/flash-f.h b/chip/stm32/flash-f.h index 8d2b8e1fae..507ded32f1 100644 --- a/chip/stm32/flash-f.h +++ b/chip/stm32/flash-f.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,108 +9,18 @@ #include enum flash_rdp_level { - FLASH_RDP_LEVEL_INVALID = -1, /**< Error occurred. */ - FLASH_RDP_LEVEL_0, /**< No read protection. */ - FLASH_RDP_LEVEL_1, /**< Reading flash is disabled while in - * bootloader mode or JTAG attached. - * Changing to Level 0 from this level - * triggers mass erase. - */ - FLASH_RDP_LEVEL_2, /**< Same as Level 1, but is permanent - * and can never be disabled. - */ + FLASH_RDP_LEVEL_INVALID = -1, /**< Error occurred. */ + FLASH_RDP_LEVEL_0, /**< No read protection. */ + FLASH_RDP_LEVEL_1, /**< Reading flash is disabled while in + * bootloader mode or JTAG attached. + * Changing to Level 0 from this level + * triggers mass erase. + */ + FLASH_RDP_LEVEL_2, /**< Same as Level 1, but is permanent + * and can never be disabled. + */ }; bool is_flash_rdp_enabled(void); -/** - * Unlock the flash control register using the unlock sequence. - * - * If the flash control register has been disabled since the last reset when - * this function is called, a bus fault will be generated. - * - * See "3.5.1 Unlocking the Flash control register" in RM0402. - */ -void unlock_flash_control_register(void); - -/** - * Unlock the flash option bytes register using the unlock sequence. - * - * If the flash option bytes register has been disabled since the last reset - * when this function is called, a bus fault will be generated. - * - * See "3.6.2 Programming user option bytes" in RM0402. - */ -void unlock_flash_option_bytes(void); - -/** - * Lock the flash control register. - * - * If the flash control register has been disabled since the last reset when - * this function is called, a bus fault will be generated. - * - * See "3.5.1 Unlocking the Flash control register" in RM0402. - */ -void lock_flash_control_register(void); - -/** - * Lock the flash option bytes register. - * - * If the flash option bytes register has been disabled since the last reset - * when this function is called, a bus fault will be generated. - * - * See "3.6.2 Programming user option bytes" in RM0402. - */ -void lock_flash_option_bytes(void); - -/** - * Disable the flash option bytes register. - * - * This function expects that bus faults have not already been ignored when - * called. - * - * Once this function is called any attempt at accessing the flash option - * bytes register will generate a bus fault until the next reset. - * - * See "3.6.2 Programming user option bytes" in RM0402. - */ -void disable_flash_option_bytes(void); - -/** - * Disable the flash control register. - * - * This function expects that bus faults have not already been ignored when - * called. - * - * Once this function is called any attempt at accessing the flash control - * register will generate a bus fault until the next reset. - * - * See "3.5.1 Unlocking the Flash control register" in RM0402. - */ -void disable_flash_control_register(void); - -/** - * Check if the flash option bytes are locked. - * - * If the flash option bytes register has been disabled since the last reset - * when this function is called, a bus fault will be generated. - - * See "3.6.2 Programming user option bytes" in RM0402. - * - * @return true if option bytes are locked, false otherwise - */ -bool flash_option_bytes_locked(void); - -/** - * Check if the flash control register is locked. - * - * If the flash control register has been disabled since the last reset - * when this function is called, a bus fault will be generated. - * - * See "3.5.1 Unlocking the Flash control register" in RM0402. - * - * @return true if register is locked, false otherwise - */ -bool flash_control_register_locked(void); - #endif /* __CROS_EC_STM32_FLASH_F_H */ diff --git a/chip/stm32/flash-regs.h b/chip/stm32/flash-regs.h new file mode 100644 index 0000000000..9456c03963 --- /dev/null +++ b/chip/stm32/flash-regs.h @@ -0,0 +1,109 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_STM32_FLASH_REGS_H +#define __CROS_EC_STM32_FLASH_REGS_H + +#include + +/** + * Unlock the flash control register using the unlock sequence. + * + * If the flash control register has been disabled since the last reset when + * this function is called, a bus fault will be generated. + * + * See "3.5.1 Unlocking the Flash control register" in RM0402. + * See "4.9.2 FLASH key register for bank 1" in RM0433. + */ +void unlock_flash_control_register(void); + +/** + * Unlock the flash option bytes register using the unlock sequence. + * + * If the flash option bytes register has been disabled since the last reset + * when this function is called, a bus fault will be generated. + * + * See "3.6.2 Programming user option bytes" in RM0402. + * See "4.9.3 FLASH option key register" in RM0433. + */ +void unlock_flash_option_bytes(void); + +/** + * Lock the flash control register. + * + * If the flash control register has been disabled since the last reset when + * this function is called, a bus fault will be generated. + * + * See "3.5.1 Unlocking the Flash control register" in RM0402. + * See "4.9.4 Flash control register for bank 1" in RM0433. + */ +void lock_flash_control_register(void); + +/** + * Lock the flash option bytes register. + * + * If the flash option bytes register has been disabled since the last reset + * when this function is called, a bus fault will be generated. + * + * See "3.6.2 Programming user option bytes" in RM0402. + * See "4.9.7 FLASH option control register" in RM0433. + */ +void lock_flash_option_bytes(void); + +/** + * Disable the flash option bytes register. + * + * This function expects that bus faults have not already been ignored when + * called. + * + * Once this function is called any attempt at accessing the flash option + * bytes register will generate a bus fault until the next reset. + * + * See "3.6.2 Programming user option bytes" in RM0402. + * See "4.9.7 FLASH option control register" in RM0433. + */ +void disable_flash_option_bytes(void); + +/** + * Disable the flash control register. + * + * This function expects that bus faults have not already been ignored when + * called. + * + * Once this function is called any attempt at accessing the flash control + * register will generate a bus fault until the next reset. + * + * See "3.5.1 Unlocking the Flash control register" in RM0402. + * See "4.9.4 Flash control register for bank 1" in RM0433. + */ +void disable_flash_control_register(void); + +/** + * Check if the flash option bytes are locked. + * + * If the flash option bytes register has been disabled since the last reset + * when this function is called, a bus fault will be generated. + + * See "3.6.2 Programming user option bytes" in RM0402. + * See "4.9.7 FLASH option control register" in RM0433. + * + * @return true if option bytes are locked, false otherwise + */ +bool flash_option_bytes_locked(void); + +/** + * Check if the flash control register is locked. + * + * If the flash control register has been disabled since the last reset + * when this function is called, a bus fault will be generated. + * + * See "3.5.1 Unlocking the Flash control register" in RM0402. + * See "4.9.4 Flash control register for bank 1" in RM0433. + * + * @return true if register is locked, false otherwise + */ +bool flash_control_register_locked(void); + +#endif /* __CROS_EC_STM32_FLASH_REGS_H */ diff --git a/chip/stm32/flash-stm32f0.c b/chip/stm32/flash-stm32f0.c index e2ff2c779c..058a8afc46 100644 --- a/chip/stm32/flash-stm32f0.c +++ b/chip/stm32/flash-stm32f0.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,7 +13,7 @@ /*****************************************************************************/ /* Physical layer APIs */ -int flash_physical_get_protect(int block) +int crec_flash_physical_get_protect(int block) { return !(STM32_FLASH_WRPR & BIT(block)); } @@ -22,11 +22,11 @@ int flash_physical_get_protect(int block) * Note: This does not need to update _NOW flags, as get_protect_flags * in common code already does so. */ -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { uint32_t flags = 0; uint32_t wrp01 = REG32(STM32_OPTB_BASE + STM32_OPTB_WRP01); -#if CONFIG_FLASH_SIZE > 64 * 1024 +#if CONFIG_FLASH_SIZE_BYTES > 64 * 1024 uint32_t wrp23 = REG32(STM32_OPTB_BASE + STM32_OPTB_WRP23); #endif @@ -65,8 +65,7 @@ uint32_t flash_physical_get_protect_flags(void) /* Default: RW. */ int region = FLASH_REGION_RW; - if (i >= WP_BANK_OFFSET && - i < WP_BANK_OFFSET + WP_BANK_COUNT) + if (i >= WP_BANK_OFFSET && i < WP_BANK_OFFSET + WP_BANK_COUNT) region = FLASH_REGION_RO; #ifdef CONFIG_ROLLBACK if (i >= ROLLBACK_BANK_OFFSET && @@ -76,12 +75,12 @@ uint32_t flash_physical_get_protect_flags(void) switch (i) { case 8: -#if CONFIG_FLASH_SIZE > 64 * 1024 +#if CONFIG_FLASH_SIZE_BYTES > 64 * 1024 case 24: #endif shift += 8; break; -#if CONFIG_FLASH_SIZE > 64 * 1024 +#if CONFIG_FLASH_SIZE_BYTES > 64 * 1024 case 16: reg = 1; shift = 0; @@ -95,18 +94,18 @@ uint32_t flash_physical_get_protect_flags(void) for (i = 0; i < FLASH_REGION_COUNT; i++) { if (!(wrp01 & wrp_mask[i][0]) && - (wrp01 & wrp_mask[i][0] << 8) == (wrp_mask[i][0] << 8)) -#if CONFIG_FLASH_SIZE > 64 * 1024 + (wrp01 & wrp_mask[i][0] << 8) == (wrp_mask[i][0] << 8)) +#if CONFIG_FLASH_SIZE_BYTES > 64 * 1024 if (!(wrp23 & wrp_mask[i][1]) && - (wrp23 & wrp_mask[i][1] << 8) == - (wrp_mask[i][1] << 8)) + (wrp23 & wrp_mask[i][1] << 8) == + (wrp_mask[i][1] << 8)) #endif flags |= mask_flags[i]; } #endif /* CONFIG_FLASH_PROTECT_RW || CONFIG_ROLLBACK */ if (wrp01 == 0xff00ff00) -#if CONFIG_FLASH_SIZE > 64 * 1024 +#if CONFIG_FLASH_SIZE_BYTES > 64 * 1024 if (wrp23 == 0xff00ff00) #endif flags |= EC_FLASH_PROTECT_ALL_AT_BOOT; @@ -114,34 +113,31 @@ uint32_t flash_physical_get_protect_flags(void) return flags; } -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { return EC_ERROR_INVAL; } -int flash_physical_restore_state(void) +int crec_flash_physical_restore_state(void) { /* Nothing to restore */ return 0; } -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | #ifdef CONFIG_FLASH_PROTECT_RW - EC_FLASH_PROTECT_RW_AT_BOOT | - EC_FLASH_PROTECT_RW_NOW | + EC_FLASH_PROTECT_RW_AT_BOOT | EC_FLASH_PROTECT_RW_NOW | #endif #ifdef CONFIG_ROLLBACK EC_FLASH_PROTECT_ROLLBACK_AT_BOOT | EC_FLASH_PROTECT_ROLLBACK_NOW | #endif - EC_FLASH_PROTECT_ALL_AT_BOOT | - EC_FLASH_PROTECT_ALL_NOW; + EC_FLASH_PROTECT_ALL_AT_BOOT | EC_FLASH_PROTECT_ALL_NOW; } -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { uint32_t ret = 0; @@ -153,13 +149,13 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) * ALL/RW at-boot state can be set if WP GPIO is asserted and can always * be cleared. */ - if (cur_flags & (EC_FLASH_PROTECT_ALL_AT_BOOT | - EC_FLASH_PROTECT_GPIO_ASSERTED)) + if (cur_flags & + (EC_FLASH_PROTECT_ALL_AT_BOOT | EC_FLASH_PROTECT_GPIO_ASSERTED)) ret |= EC_FLASH_PROTECT_ALL_AT_BOOT; #ifdef CONFIG_FLASH_PROTECT_RW - if (cur_flags & (EC_FLASH_PROTECT_RW_AT_BOOT | - EC_FLASH_PROTECT_GPIO_ASSERTED)) + if (cur_flags & + (EC_FLASH_PROTECT_RW_AT_BOOT | EC_FLASH_PROTECT_GPIO_ASSERTED)) ret |= EC_FLASH_PROTECT_RW_AT_BOOT; #endif diff --git a/chip/stm32/flash-stm32f3.c b/chip/stm32/flash-stm32f3.c index ea5ba1a1b6..c41f9c526d 100644 --- a/chip/stm32/flash-stm32f3.c +++ b/chip/stm32/flash-stm32f3.c @@ -1,18 +1,20 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Flash memory module for stm32f3 and stm32f4 */ -#include #include "common.h" -#include "flash.h" #include "flash-f.h" +#include "flash-regs.h" +#include "flash.h" #include "hooks.h" +#include "panic.h" #include "registers.h" #include "system.h" -#include "panic.h" + +#include /*****************************************************************************/ /* Physical layer APIs */ @@ -36,7 +38,7 @@ struct ec_flash_bank const flash_bank_array[] = { .protect_size_exp = __fls(SIZE_128KB), }, { - .count = (CONFIG_FLASH_SIZE - SIZE_256KB) / SIZE_256KB, + .count = (CONFIG_FLASH_SIZE_BYTES - SIZE_256KB) / SIZE_256KB, .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE), .size_exp = __fls(SIZE_256KB), .erase_size_exp = __fls(SIZE_256KB), @@ -70,7 +72,7 @@ struct ec_flash_bank const flash_bank_array[] = { .protect_size_exp = __fls(SIZE_64KB), }, { - .count = (CONFIG_FLASH_SIZE - SIZE_128KB) / SIZE_128KB, + .count = (CONFIG_FLASH_SIZE_BYTES - SIZE_128KB) / SIZE_128KB, .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE), .size_exp = __fls(SIZE_128KB), .erase_size_exp = __fls(SIZE_128KB), @@ -93,7 +95,7 @@ struct flash_wp_state { /*****************************************************************************/ /* Physical layer APIs */ -int flash_physical_get_protect(int block) +int crec_flash_physical_get_protect(int block) { return (entire_flash_locked || #if defined(CHIP_FAMILY_STM32F3) @@ -101,10 +103,10 @@ int flash_physical_get_protect(int block) #elif defined(CHIP_FAMILY_STM32F4) !(STM32_OPTB_WP & STM32_OPTB_nWRP(block)) #endif - ); + ); } -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { uint32_t flags = 0; @@ -120,7 +122,7 @@ uint32_t flash_physical_get_protect_flags(void) return flags; } -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { if (all) { disable_flash_control_register(); @@ -134,14 +136,13 @@ int flash_physical_protect_now(int all) return EC_SUCCESS; } -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ALL_NOW; } -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { uint32_t ret = 0; @@ -160,7 +161,7 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) return ret; } -int flash_physical_restore_state(void) +int crec_flash_physical_restore_state(void) { uint32_t reset_flags = system_get_reset_flags(); int version, size; @@ -172,7 +173,7 @@ int flash_physical_restore_state(void) */ if (reset_flags & EC_RESET_FLAG_SYSJUMP) { prev = (const struct flash_wp_state *)system_get_jump_tag( - FLASH_SYSJUMP_TAG, &version, &size); + FLASH_SYSJUMP_TAG, &version, &size); if (prev && version == FLASH_HOOK_VERSION && size == sizeof(*prev)) entire_flash_locked = prev->entire_flash_locked; diff --git a/chip/stm32/flash-stm32f4.c b/chip/stm32/flash-stm32f4.c deleted file mode 120000 index 6ff8130e17..0000000000 --- a/chip/stm32/flash-stm32f4.c +++ /dev/null @@ -1 +0,0 @@ -flash-stm32f3.c \ No newline at end of file diff --git a/chip/stm32/flash-stm32f4.c b/chip/stm32/flash-stm32f4.c new file mode 100644 index 0000000000..c41f9c526d --- /dev/null +++ b/chip/stm32/flash-stm32f4.c @@ -0,0 +1,198 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Flash memory module for stm32f3 and stm32f4 */ + +#include "common.h" +#include "flash-f.h" +#include "flash-regs.h" +#include "flash.h" +#include "hooks.h" +#include "panic.h" +#include "registers.h" +#include "system.h" + +#include + +/*****************************************************************************/ +/* Physical layer APIs */ +#ifdef CHIP_VARIANT_STM32F76X +/* + * 8 "erase" sectors : 32KB/32KB/32KB/32KB/128KB/256KB/256KB/256KB + */ +struct ec_flash_bank const flash_bank_array[] = { + { + .count = 4, + .size_exp = __fls(SIZE_32KB), + .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE), + .erase_size_exp = __fls(SIZE_32KB), + .protect_size_exp = __fls(SIZE_32KB), + }, + { + .count = 1, + .size_exp = __fls(SIZE_128KB), + .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE), + .erase_size_exp = __fls(SIZE_128KB), + .protect_size_exp = __fls(SIZE_128KB), + }, + { + .count = (CONFIG_FLASH_SIZE_BYTES - SIZE_256KB) / SIZE_256KB, + .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE), + .size_exp = __fls(SIZE_256KB), + .erase_size_exp = __fls(SIZE_256KB), + .protect_size_exp = __fls(SIZE_256KB), + }, +}; +#elif defined(CHIP_FAMILY_STM32F4) +/* + * STM32F412xE has 512 KB flash + * 8 "erase" sectors (512 KB) : 16KB/16KB/16KB/16KB/64KB/128KB/128KB/128KB + * + * STM32F412xG has 1 MB flash + * 12 "erase" sectors (1024 KB) : + * 16KB/16KB/16KB/16KB/64KB/128KB/128KB/128KB/128KB/128KB/128KB/128KB + * + * https://www.st.com/resource/en/datasheet/stm32f412cg.pdf + */ +struct ec_flash_bank const flash_bank_array[] = { + { + .count = 4, + .size_exp = __fls(SIZE_16KB), + .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE), + .erase_size_exp = __fls(SIZE_16KB), + .protect_size_exp = __fls(SIZE_16KB), + }, + { + .count = 1, + .size_exp = __fls(SIZE_64KB), + .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE), + .erase_size_exp = __fls(SIZE_64KB), + .protect_size_exp = __fls(SIZE_64KB), + }, + { + .count = (CONFIG_FLASH_SIZE_BYTES - SIZE_128KB) / SIZE_128KB, + .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE), + .size_exp = __fls(SIZE_128KB), + .erase_size_exp = __fls(SIZE_128KB), + .protect_size_exp = __fls(SIZE_128KB), + }, +}; +#endif + +/* Flag indicating whether we have locked down entire flash */ +static int entire_flash_locked; + +#define FLASH_SYSJUMP_TAG 0x5750 /* "WP" - Write Protect */ +#define FLASH_HOOK_VERSION 1 + +/* The previous write protect state before sys jump */ +struct flash_wp_state { + int entire_flash_locked; +}; + +/*****************************************************************************/ +/* Physical layer APIs */ + +int crec_flash_physical_get_protect(int block) +{ + return (entire_flash_locked || +#if defined(CHIP_FAMILY_STM32F3) + !(STM32_FLASH_WRPR & BIT(block)) +#elif defined(CHIP_FAMILY_STM32F4) + !(STM32_OPTB_WP & STM32_OPTB_nWRP(block)) +#endif + ); +} + +uint32_t crec_flash_physical_get_protect_flags(void) +{ + uint32_t flags = 0; + + /* Read all-protected state from our shadow copy */ + if (entire_flash_locked) + flags |= EC_FLASH_PROTECT_ALL_NOW; + +#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE) + if (is_flash_rdp_enabled()) + flags |= EC_FLASH_PROTECT_RO_AT_BOOT; +#endif + + return flags; +} + +int crec_flash_physical_protect_now(int all) +{ + if (all) { + disable_flash_control_register(); + entire_flash_locked = 1; + + return EC_SUCCESS; + } + + disable_flash_option_bytes(); + + return EC_SUCCESS; +} + +uint32_t crec_flash_physical_get_valid_flags(void) +{ + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | + EC_FLASH_PROTECT_ALL_NOW; +} + +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) +{ + uint32_t ret = 0; + + /* If RO protection isn't enabled, its at-boot state can be changed. */ + if (!(cur_flags & EC_FLASH_PROTECT_RO_NOW)) + ret |= EC_FLASH_PROTECT_RO_AT_BOOT; + + /* + * If entire flash isn't protected at this boot, it can be enabled if + * the WP GPIO is asserted. + */ + if (!(cur_flags & EC_FLASH_PROTECT_ALL_NOW) && + (cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED)) + ret |= EC_FLASH_PROTECT_ALL_NOW; + + return ret; +} + +int crec_flash_physical_restore_state(void) +{ + uint32_t reset_flags = system_get_reset_flags(); + int version, size; + const struct flash_wp_state *prev; + + /* + * If we have already jumped between images, an earlier image could + * have applied write protection. Nothing additional needs to be done. + */ + if (reset_flags & EC_RESET_FLAG_SYSJUMP) { + prev = (const struct flash_wp_state *)system_get_jump_tag( + FLASH_SYSJUMP_TAG, &version, &size); + if (prev && version == FLASH_HOOK_VERSION && + size == sizeof(*prev)) + entire_flash_locked = prev->entire_flash_locked; + return 1; + } + + return 0; +} + +/*****************************************************************************/ +/* Hooks */ + +static void flash_preserve_state(void) +{ + struct flash_wp_state state; + + state.entire_flash_locked = entire_flash_locked; + + system_add_jump_tag(FLASH_SYSJUMP_TAG, FLASH_HOOK_VERSION, + sizeof(state), &state); +} +DECLARE_HOOK(HOOK_SYSJUMP, flash_preserve_state, HOOK_PRIO_DEFAULT); diff --git a/chip/stm32/flash-stm32g4-l4.c b/chip/stm32/flash-stm32g4-l4.c index 27092a1156..ad08047c23 100644 --- a/chip/stm32/flash-stm32g4-l4.c +++ b/chip/stm32/flash-stm32g4-l4.c @@ -1,15 +1,15 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Flash memory module for STM32L4 family */ -#include "common.h" #include "clock.h" +#include "common.h" #include "flash.h" #include "hooks.h" -#include "registers.h" #include "panic.h" +#include "registers.h" #include "system.h" #include "task.h" #include "timer.h" @@ -30,47 +30,55 @@ * used in the STM32 TRMs. Redifining macros here in terms of pages in order to * match STM32 documentation for write protect computations in this file. * - * Two write protect (WRP) regions can be defined in the option bytes. The - * assumption is that 1st WRP area is for RO and the 2nd WRP is for RW if RW WRP - * config is selected. If RW is being write-protected, it is assume to be the - * 1st page following the RO section until the last flash page. WRP areas are - * specified in terms of page indices with a start index and an end index. - * start == end means a single page is protected. - * - * WRP1a_start = WRP1a_end --> WRP1a_start page is protected - * WRP1a_start > WRP1a_end --> No WRP area is specified - * WRP1a_start < WRP1a_end --> Pages WRP1a_start to WRP1a_end protected - * * These macros are from the common flash API and mean the following: * WP_BANK_OFFSET -> index of first RO page * CONFIG_WP_STORAGE_SIZE -> size of RO region in bytes */ #define FLASH_PAGE_SIZE CONFIG_FLASH_BANK_SIZE -#define FLASH_PAGE_MAX_COUNT (CONFIG_FLASH_SIZE / FLASH_PAGE_SIZE) +#define FLASH_PAGE_MAX_COUNT (CONFIG_FLASH_SIZE_BYTES / FLASH_PAGE_SIZE) #define FLASH_RO_FIRST_PAGE_IDX WP_BANK_OFFSET -#define FLASH_RO_LAST_PAGE_IDX ((CONFIG_WP_STORAGE_SIZE / FLASH_PAGE_SIZE) \ - + FLASH_RO_FIRST_PAGE_IDX - 1) +#define FLASH_RO_LAST_PAGE_IDX \ + ((CONFIG_WP_STORAGE_SIZE / FLASH_PAGE_SIZE) + \ + FLASH_RO_FIRST_PAGE_IDX - 1) #define FLASH_RW_FIRST_PAGE_IDX (FLASH_RO_LAST_PAGE_IDX + 1) #define FLASH_RW_LAST_PAGE_IDX (FLASH_PAGE_MAX_COUNT - 1) - #define FLASH_PAGE_ROLLBACK_COUNT ROLLBACK_BANK_COUNT #define FLASH_PAGE_ROLLBACK_FIRST_IDX ROLLBACK_BANK_OFFSET -#define FLASH_PAGE_ROLLBACK_LAST_IDX (FLASH_PAGE_ROLLBACK_FIRST_IDX +\ - FLASH_PAGE_ROLLBACK_COUNT -1) - -#define FLASH_WRP_MASK (FLASH_PAGE_MAX_COUNT - 1) -#define FLASH_WRP_START(val) ((val) & FLASH_WRP_MASK) -#define FLASH_WRP_END(val) (((val) >> 16) & FLASH_WRP_MASK) -#define FLASH_WRP_RANGE(start, end) (((start) & FLASH_WRP_MASK) | \ - (((end) & FLASH_WRP_MASK) << 16)) -#define FLASH_WRP_RANGE_DISABLED FLASH_WRP_RANGE(FLASH_WRP_MASK, 0x00) +#define FLASH_PAGE_ROLLBACK_LAST_IDX \ + (FLASH_PAGE_ROLLBACK_FIRST_IDX + FLASH_PAGE_ROLLBACK_COUNT - 1) + +#ifdef STM32_FLASH_DBANK_MODE +#define FLASH_WRP_MASK (FLASH_PAGE_MAX_COUNT - 1) +#else +#ifdef CHIP_FAMILY_STM32L4 +#define FLASH_WRP_MASK 0xFF +#else +#define FLASH_WRP_MASK ((FLASH_PAGE_MAX_COUNT) / 2 - 1) +#endif +#endif /* CONFIG_FLASH_DBANK_MODE */ +#define FLASH_WRP_START(val) ((val)&FLASH_WRP_MASK) +#define FLASH_WRP_END(val) (((val) >> 16) & FLASH_WRP_MASK) +#define FLASH_WRP_RANGE(start, end) \ + (((start)&FLASH_WRP_MASK) | (((end)&FLASH_WRP_MASK) << 16)) +#define FLASH_WRP_RANGE_DISABLED FLASH_WRP_RANGE(FLASH_WRP_MASK, 0x00) #define FLASH_WRP1X_MASK FLASH_WRP_RANGE(FLASH_WRP_MASK, FLASH_WRP_MASK) +enum wrp_region { + WRP_RO, + WRP_RW, +}; + +struct wrp_info { + int enable; + int start; + int end; +}; + static inline int calculate_flash_timeout(void) { - return (FLASH_TIMEOUT_US * - (clock_get_freq() / SECOND) / CYCLE_PER_FLASH_LOOP); + return (FLASH_TIMEOUT_US * (clock_get_freq() / SECOND) / + CYCLE_PER_FLASH_LOOP); } static int wait_while_busy(void) @@ -96,8 +104,7 @@ static int unlock(int locks) STM32_FLASH_KEYR = FLASH_KEYR_KEY2; } /* unlock option memory if required */ - if ((locks & FLASH_CR_OPTLOCK) && - (STM32_FLASH_CR & FLASH_CR_OPTLOCK)) { + if ((locks & FLASH_CR_OPTLOCK) && (STM32_FLASH_CR & FLASH_CR_OPTLOCK)) { STM32_FLASH_OPTKEYR = FLASH_OPTKEYR_KEY1; STM32_FLASH_OPTKEYR = FLASH_OPTKEYR_KEY2; } @@ -105,13 +112,18 @@ static int unlock(int locks) /* Re-enable bus fault handler */ ignore_bus_fault(0); - return (STM32_FLASH_CR & (locks | FLASH_CR_LOCK)) ? EC_ERROR_UNKNOWN - : EC_SUCCESS; + return (STM32_FLASH_CR & (locks | FLASH_CR_LOCK)) ? EC_ERROR_UNKNOWN : + EC_SUCCESS; } static void lock(void) { - STM32_FLASH_CR = FLASH_CR_LOCK; + STM32_FLASH_CR |= FLASH_CR_LOCK; +} + +static void ob_lock(void) +{ + STM32_FLASH_CR |= FLASH_CR_OPTLOCK; } /* @@ -156,41 +168,214 @@ static int commit_optb(void) { int rv; + /* + * Wait for last operation. + */ + rv = wait_while_busy(); + if (rv) + return rv; + STM32_FLASH_CR |= FLASH_CR_OPTSTRT; rv = wait_while_busy(); if (rv) return rv; + + ob_lock(); lock(); return EC_SUCCESS; } +/* + * There are a minimum of 2 WRP regions that can be set. The STM32G4 + * family has both category 2, and category 3 devices. Category 2 + * devices have only 2 WRP regions, but category 3 devices have 4 WRP + * regions that can be configured. Category 3 devices also support dual + * flash banks, and this mode is the default setting. When DB mode is enabled, + * then each WRP register can only protect up to 64 2kB pages. This means that + * one WRP register is needed per bank. + * + * 1. WRP1A -> used always for RO + * 2. WRP1B -> used always for RW + * 3. WRP2A -> may be used for RW if dual-bank (DB) mode is enabled + * 4. WRP2B -> currently never used + * + * WRP areas are specified in terms of page indices with a start index + * and an end index. start == end means a single page is protected. + * + * WRPnx_start = WRPnx_end --> WRPnx_start page is protected + * WRPnx_start > WRPnx_end --> No WRP area is specified + * WRPnx_start < WRPnx_end --> Pages WRPnx_start to WRPnx_end + */ +static void optb_get_wrp(enum wrp_region region, struct wrp_info *wrp) +{ +#ifdef STM32_FLASH_DBANK_MODE + int start; + int end; +#endif + /* Assume WRP regions are not configured */ + wrp->start = FLASH_WRP_MASK; + wrp->end = 0; + wrp->enable = 0; + + if (region == WRP_RO) { + /* + * RO write protect is fully described by WRP1AR. Get the + * start/end indices. If end >= start, then RO write protect is + * enabled. + */ + wrp->start = FLASH_WRP_START(STM32_OPTB_WRP1AR); + wrp->end = FLASH_WRP_END(STM32_OPTB_WRP1AR); + wrp->enable = wrp->end >= wrp->start; + } else if (region == WRP_RW) { + /* + * RW write always uses WRP1BR. If dual-bank mode is being used, + * then WRP2AR must also be check to determine the full range of + * flash page indices being protected. + */ + wrp->start = FLASH_WRP_START(STM32_OPTB_WRP1BR); + wrp->end = FLASH_WRP_END(STM32_OPTB_WRP1BR); + wrp->enable = wrp->end >= wrp->start; +#ifdef STM32_FLASH_DBANK_MODE + start = FLASH_WRP_START(STM32_FLASH_WRP2AR); + end = FLASH_WRP_END(STM32_FLASH_WRP2AR); + /* + * If WRP2AR protection is enabled, then need to adjust either + * the start, end, or both indices. + */ + if (end >= start) { + if (wrp->enable) { + /* WRP1BR is active, only need to adjust end */ + wrp->end += end; + } else { + /* + * WRP1BR is not active, so RW protection, if + * enabled, is fully controlled by WRP2AR. + */ + wrp->start = start; + wrp->end = end; + wrp->enable = 1; + } + } +#endif + } +} + +static void optb_set_wrp(enum wrp_region region, struct wrp_info *wrp) +{ + int start = wrp->start; + int end = wrp->end; + + if (!wrp->enable) { + /* + * If enable is not set, then ignore the passed in start/end + * values and set start/end to the default not protected range + * which satisfies start > end + */ + start = FLASH_WRP_MASK; + end = 0; + } + + if (region == WRP_RO) { + /* For RO can always use start/end directly */ + STM32_FLASH_WRP1AR = FLASH_WRP_RANGE(start, end); + } else if (region == WRP_RW) { +#ifdef STM32_FLASH_DBANK_MODE + /* + * In the dual-bank flash case (STM32G4 Category 3 devices with + * DB bit set), RW write protect can use both WRP1BR and WRP2AR + * registers in order to span the full flash memory range. + */ + if (wrp->enable) { + int rw_end; + + /* + * If the 1st RW flash page is in the 1st half of + * memory, then at least one block will be protected by + * WRP1BR. If the end flash page is in the 2nd half of + * memory, then cap the end for WRP1BR to its max + * value. Otherwise, can use end passed in directly. + */ + if (start <= FLASH_WRP_MASK) { + rw_end = end > FLASH_WRP_MASK ? FLASH_WRP_MASK : + end; + STM32_FLASH_WRP1BR = + FLASH_WRP_RANGE(start, rw_end); + } + /* + * If the last RW flash page is in the 2nd half of + * memory, then at least one block will be protected by + * WRP2AR. If the start flash page is in the 2nd half of + * memory, can use start directly. Otherwise, start + * needs to be set to 0 here. + */ + if (end > FLASH_WRP_MASK) { + rw_end = end & FLASH_WRP_MASK; + STM32_FLASH_WRP2AR = FLASH_WRP_RANGE(0, rw_end); + } + } else { + /* + * RW write protect is being disabled. Set both WRP1BR + * and WRP2AR to default start > end not protected + * state. + */ + STM32_FLASH_WRP1BR = FLASH_WRP_RANGE(start, end); + STM32_FLASH_WRP2AR = FLASH_WRP_RANGE(start, end); + } +#else + /* Single bank case, WRP1BR can cover the full memory range */ + STM32_FLASH_WRP1BR = FLASH_WRP_RANGE(start, end); +#endif + } +} + static void unprotect_all_blocks(void) { + struct wrp_info wrp; + + /* Set info values to unprotected */ + wrp.start = FLASH_WRP_MASK; + wrp.end = 0; + wrp.enable = 0; + unlock_optb(); - STM32_FLASH_WRP1AR = FLASH_WRP_RANGE_DISABLED; - STM32_FLASH_WRP1BR = FLASH_WRP_RANGE_DISABLED; + /* Disable RO WRP */ + optb_set_wrp(WRP_RO, &wrp); + /* Disable RW WRP */ + optb_set_wrp(WRP_RW, &wrp); commit_optb(); } -int flash_physical_protect_at_boot(uint32_t new_flags) +int crec_flash_physical_protect_at_boot(uint32_t new_flags) { - uint32_t ro_range = FLASH_WRP_RANGE_DISABLED; - uint32_t rb_rw_range = FLASH_WRP_RANGE_DISABLED; + struct wrp_info wrp_ro; + struct wrp_info wrp_rw; + + wrp_ro.start = FLASH_WRP_MASK; + wrp_ro.end = 0; + wrp_ro.enable = 0; + + wrp_rw.start = FLASH_WRP_MASK; + wrp_rw.end = 0; + wrp_rw.enable = 0; + /* - * WRP1AR is storing the write-protection range for the RO region. - * WRP1BR is storing the write-protection range for the - * rollback and RW regions. + * Default operation for this function is to disable both RO and RW + * write protection in the option bytes. Based on new_flags either RO or + * RW or both regions write protect may be set. */ - if (new_flags & (EC_FLASH_PROTECT_ALL_AT_BOOT | - EC_FLASH_PROTECT_RO_AT_BOOT)) - ro_range = FLASH_WRP_RANGE(FLASH_RO_FIRST_PAGE_IDX, - FLASH_RO_LAST_PAGE_IDX); + if (new_flags & + (EC_FLASH_PROTECT_ALL_AT_BOOT | EC_FLASH_PROTECT_RO_AT_BOOT)) { + wrp_ro.start = FLASH_RO_FIRST_PAGE_IDX; + wrp_ro.end = FLASH_RO_LAST_PAGE_IDX; + wrp_ro.enable = 1; + } if (new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT) { - rb_rw_range = FLASH_WRP_RANGE(FLASH_RW_FIRST_PAGE_IDX, - FLASH_RW_LAST_PAGE_IDX); + wrp_rw.start = FLASH_RW_FIRST_PAGE_IDX; + wrp_rw.end = FLASH_RW_LAST_PAGE_IDX; + wrp_rw.enable = 1; } else { /* * Start index will be 1st index following RO region index. The @@ -199,7 +384,7 @@ int flash_physical_protect_at_boot(uint32_t new_flags) * the 2nd memory protection area get written in option bytes. */ int start = FLASH_RW_FIRST_PAGE_IDX; - int end = FLASH_WRP_END(FLASH_WRP_RANGE_DISABLED); + int end = 0; #ifdef CONFIG_ROLLBACK if (new_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) { start = FLASH_PAGE_ROLLBACK_FIRST_IDX; @@ -213,8 +398,11 @@ int flash_physical_protect_at_boot(uint32_t new_flags) end = FLASH_RW_LAST_PAGE_IDX; #endif /* CONFIG_FLASH_PROTECT_RW */ - if (end != FLASH_WRP_END(FLASH_WRP_RANGE_DISABLED)) - rb_rw_range = FLASH_WRP_RANGE(start, end); + if (end) { + wrp_rw.start = start; + wrp_rw.end = end; + wrp_rw.enable = 1; + } } unlock_optb(); @@ -225,8 +413,8 @@ int flash_physical_protect_at_boot(uint32_t new_flags) */ STM32_FLASH_OPTR = (STM32_FLASH_OPTR & ~0xff) | 0x11; #endif - STM32_FLASH_WRP1AR = ro_range; - STM32_FLASH_WRP1BR = rb_rw_range; + optb_set_wrp(WRP_RO, &wrp_ro); + optb_set_wrp(WRP_RW, &wrp_rw); commit_optb(); return EC_SUCCESS; @@ -240,14 +428,14 @@ int flash_physical_protect_at_boot(uint32_t new_flags) */ static int registers_need_reset(void) { - uint32_t flags = flash_get_protect(); + uint32_t flags = crec_flash_get_protect(); int ro_at_boot = (flags & EC_FLASH_PROTECT_RO_AT_BOOT) ? 1 : 0; /* The RO region is write-protected by the WRP1AR range. */ uint32_t wrp1ar = STM32_OPTB_WRP1AR; uint32_t ro_range = ro_at_boot ? - FLASH_WRP_RANGE(FLASH_RO_FIRST_PAGE_IDX, - FLASH_RO_LAST_PAGE_IDX) - : FLASH_WRP_RANGE_DISABLED; + FLASH_WRP_RANGE(FLASH_RO_FIRST_PAGE_IDX, + FLASH_RO_LAST_PAGE_IDX) : + FLASH_WRP_RANGE_DISABLED; return ro_range != (wrp1ar & FLASH_WRP1X_MASK); } @@ -255,7 +443,7 @@ static int registers_need_reset(void) /*****************************************************************************/ /* Physical layer APIs */ -int flash_physical_write(int offset, int size, const char *data) +int crec_flash_physical_write(int offset, int size, const char *data) { uint32_t *address = (void *)(CONFIG_PROGRAM_MEMORY_BASE + offset); int res = EC_SUCCESS; @@ -264,6 +452,10 @@ int flash_physical_write(int offset, int size, const char *data) int unaligned = (uint32_t)data & (STM32_FLASH_MIN_WRITE_SIZE - 1); uint32_t *data32 = (void *)data; + /* Check Flash offset */ + if (offset % STM32_FLASH_MIN_WRITE_SIZE) + return EC_ERROR_MEMORY_ALLOCATION; + if (unlock(FLASH_CR_LOCK) != EC_SUCCESS) return EC_ERROR_UNKNOWN; @@ -291,10 +483,10 @@ int flash_physical_write(int offset, int size, const char *data) /* write the 2 words */ if (unaligned) { - *address++ = (uint32_t)data[0] | (data[1] << 8) - | (data[2] << 16) | (data[3] << 24); - *address++ = (uint32_t)data[4] | (data[5] << 8) - | (data[6] << 16) | (data[7] << 24); + *address++ = (uint32_t)data[0] | (data[1] << 8) | + (data[2] << 16) | (data[3] << 24); + *address++ = (uint32_t)data[4] | (data[5] << 8) | + (data[6] << 16) | (data[7] << 24); data += STM32_FLASH_MIN_WRITE_SIZE; } else { *address++ = *data32++; @@ -330,7 +522,7 @@ int flash_physical_write(int offset, int size, const char *data) return res; } -int flash_physical_erase(int offset, int size) +int crec_flash_physical_erase(int offset, int size) { int res = EC_SUCCESS; int pg; @@ -347,8 +539,8 @@ int flash_physical_erase(int offset, int size) timestamp_t deadline; /* select page to erase and PER bit */ - STM32_FLASH_CR = (STM32_FLASH_CR & ~FLASH_CR_PNB_MASK) - | FLASH_CR_PER | FLASH_CR_PNB(pg); + STM32_FLASH_CR = (STM32_FLASH_CR & ~FLASH_CR_PNB_MASK) | + FLASH_CR_PER | FLASH_CR_PNB(pg); /* set STRT bit : start erase */ STM32_FLASH_CR |= FLASH_CR_STRT; @@ -389,47 +581,48 @@ int flash_physical_erase(int offset, int size) return res; } -int flash_physical_get_protect(int block) +int crec_flash_physical_get_protect(int block) { - uint32_t wrp1ar = STM32_FLASH_WRP1AR; - uint32_t wrp1br = STM32_FLASH_WRP1BR; + struct wrp_info wrp_ro; + struct wrp_info wrp_rw; + + optb_get_wrp(WRP_RO, &wrp_ro); + optb_get_wrp(WRP_RW, &wrp_rw); - return ((block >= FLASH_WRP_START(wrp1ar)) && - (block <= FLASH_WRP_END(wrp1ar))) || - ((block >= FLASH_WRP_START(wrp1br)) && - (block <= FLASH_WRP_END(wrp1br))); + return ((block >= wrp_ro.start) && (block <= wrp_ro.end)) || + ((block >= wrp_rw.start) && (block <= wrp_rw.end)); } /* * Note: This does not need to update _NOW flags, as get_protect_flags * in common code already does so. */ -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { uint32_t flags = 0; - uint32_t wrp1ar = STM32_OPTB_WRP1AR; - uint32_t wrp1br = STM32_OPTB_WRP1BR; + struct wrp_info wrp_ro; + struct wrp_info wrp_rw; - /* RO region protection range is in WRP1AR range */ - if (wrp1ar == FLASH_WRP_RANGE(FLASH_RO_FIRST_PAGE_IDX, - FLASH_RO_LAST_PAGE_IDX)) + optb_get_wrp(WRP_RO, &wrp_ro); + optb_get_wrp(WRP_RW, &wrp_rw); + + /* Check if RO is fully protected */ + if (wrp_ro.start == FLASH_RO_FIRST_PAGE_IDX && + wrp_ro.end == FLASH_RO_LAST_PAGE_IDX) flags |= EC_FLASH_PROTECT_RO_AT_BOOT; - /* Rollback and RW regions protection range is in WRP1BR range */ - if (wrp1br != FLASH_WRP_RANGE_DISABLED) { - int end = FLASH_WRP_END(wrp1br); - int strt = FLASH_WRP_START(wrp1br); + if (wrp_rw.enable) { #ifdef CONFIG_ROLLBACK - if (strt <= FLASH_PAGE_ROLLBACK_FIRST_IDX && - end >= FLASH_PAGE_ROLLBACK_LAST_IDX) + if (wrp_rw.start <= FLASH_PAGE_ROLLBACK_FIRST_IDX && + wrp_rw.end >= FLASH_PAGE_ROLLBACK_LAST_IDX) flags |= EC_FLASH_PROTECT_ROLLBACK_AT_BOOT; #endif /* CONFIG_ROLLBACK */ #ifdef CONFIG_FLASH_PROTECT_RW - if (end == PHYSICAL_BANKS) + if (wrp_rw.end == PHYSICAL_BANKS) flags |= EC_FLASH_PROTECT_RW_AT_BOOT; #endif /* CONFIG_FLASH_PROTECT_RW */ - if (end == PHYSICAL_BANKS && - strt == WP_BANK_OFFSET + WP_BANK_COUNT && + if (wrp_rw.end == PHYSICAL_BANKS && + wrp_rw.start == WP_BANK_OFFSET + WP_BANK_COUNT && flags & EC_FLASH_PROTECT_RO_AT_BOOT) flags |= EC_FLASH_PROTECT_ALL_AT_BOOT; } @@ -437,28 +630,25 @@ uint32_t flash_physical_get_protect_flags(void) return flags; } -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { return EC_ERROR_INVAL; } -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | #ifdef CONFIG_FLASH_PROTECT_RW - EC_FLASH_PROTECT_RW_AT_BOOT | - EC_FLASH_PROTECT_RW_NOW | + EC_FLASH_PROTECT_RW_AT_BOOT | EC_FLASH_PROTECT_RW_NOW | #endif #ifdef CONFIG_ROLLBACK EC_FLASH_PROTECT_ROLLBACK_AT_BOOT | EC_FLASH_PROTECT_ROLLBACK_NOW | #endif - EC_FLASH_PROTECT_ALL_AT_BOOT | - EC_FLASH_PROTECT_ALL_NOW; + EC_FLASH_PROTECT_ALL_AT_BOOT | EC_FLASH_PROTECT_ALL_NOW; } -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { uint32_t ret = 0; @@ -470,13 +660,13 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) * ALL/RW at-boot state can be set if WP GPIO is asserted and can always * be cleared. */ - if (cur_flags & (EC_FLASH_PROTECT_ALL_AT_BOOT | - EC_FLASH_PROTECT_GPIO_ASSERTED)) + if (cur_flags & + (EC_FLASH_PROTECT_ALL_AT_BOOT | EC_FLASH_PROTECT_GPIO_ASSERTED)) ret |= EC_FLASH_PROTECT_ALL_AT_BOOT; #ifdef CONFIG_FLASH_PROTECT_RW - if (cur_flags & (EC_FLASH_PROTECT_RW_AT_BOOT | - EC_FLASH_PROTECT_GPIO_ASSERTED)) + if (cur_flags & + (EC_FLASH_PROTECT_RW_AT_BOOT | EC_FLASH_PROTECT_GPIO_ASSERTED)) ret |= EC_FLASH_PROTECT_RW_AT_BOOT; #endif @@ -489,10 +679,25 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) return ret; } -int flash_pre_init(void) +int crec_flash_physical_force_reload(void) +{ + int rv = unlock(FLASH_CR_OPTLOCK); + + if (rv) + return rv; + + /* Force a reboot; this should never return. */ + STM32_FLASH_CR = FLASH_CR_OBL_LAUNCH; + while (1) + ; + + return EC_ERROR_UNKNOWN; +} + +int crec_flash_pre_init(void) { uint32_t reset_flags = system_get_reset_flags(); - uint32_t prot_flags = flash_get_protect(); + uint32_t prot_flags = crec_flash_get_protect(); int need_reset = 0; /* @@ -511,7 +716,7 @@ int flash_pre_init(void) * update to the write protect register and reboot so * it takes effect. */ - flash_physical_protect_at_boot( + crec_flash_physical_protect_at_boot( EC_FLASH_PROTECT_RO_AT_BOOT); need_reset = 1; } @@ -525,8 +730,8 @@ int flash_pre_init(void) * to the check above. One of them should be able to * go away. */ - flash_protect_at_boot( - prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT); + crec_flash_protect_at_boot(prot_flags & + EC_FLASH_PROTECT_RO_AT_BOOT); need_reset = 1; } } else { @@ -540,7 +745,8 @@ int flash_pre_init(void) } } - if ((flash_physical_get_valid_flags() & EC_FLASH_PROTECT_ALL_AT_BOOT) && + if ((crec_flash_physical_get_valid_flags() & + EC_FLASH_PROTECT_ALL_AT_BOOT) && (!!(prot_flags & EC_FLASH_PROTECT_ALL_AT_BOOT) != !!(prot_flags & EC_FLASH_PROTECT_ALL_NOW))) { /* @@ -555,7 +761,8 @@ int flash_pre_init(void) } #ifdef CONFIG_FLASH_PROTECT_RW - if ((flash_physical_get_valid_flags() & EC_FLASH_PROTECT_RW_AT_BOOT) && + if ((crec_flash_physical_get_valid_flags() & + EC_FLASH_PROTECT_RW_AT_BOOT) && (!!(prot_flags & EC_FLASH_PROTECT_RW_AT_BOOT) != !!(prot_flags & EC_FLASH_PROTECT_RW_NOW))) { /* RW_AT_BOOT and RW_NOW do not match. */ @@ -564,7 +771,7 @@ int flash_pre_init(void) #endif #ifdef CONFIG_ROLLBACK - if ((flash_physical_get_valid_flags() & + if ((crec_flash_physical_get_valid_flags() & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) && (!!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) != !!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_NOW))) { diff --git a/chip/stm32/flash-stm32h7.c b/chip/stm32/flash-stm32h7.c index a541b962d2..2b9b594938 100644 --- a/chip/stm32/flash-stm32h7.c +++ b/chip/stm32/flash-stm32h7.c @@ -1,16 +1,17 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Flash memory module for STM32H7 family */ -#include "common.h" #include "clock.h" +#include "common.h" #include "cpu.h" +#include "flash-regs.h" #include "flash.h" #include "hooks.h" -#include "registers.h" #include "panic.h" +#include "registers.h" #include "system.h" #include "task.h" #include "timer.h" @@ -44,7 +45,7 @@ * not what is called 'bank' in the common code (ie Write-Protect sectors) * both have the same number of 128KB blocks. */ -#define HWBANK_SIZE (CONFIG_FLASH_SIZE / 2) +#define HWBANK_SIZE (CONFIG_FLASH_SIZE_BYTES / 2) #define BLOCKS_PER_HWBANK (HWBANK_SIZE / CONFIG_FLASH_ERASE_SIZE) #define BLOCKS_HWBANK_MASK (BIT(BLOCKS_PER_HWBANK) - 1) @@ -73,8 +74,8 @@ struct flash_wp_state { static inline int calculate_flash_timeout(void) { - return (FLASH_TIMEOUT_US * - (clock_get_freq() / SECOND) / CYCLE_PER_FLASH_LOOP); + return (FLASH_TIMEOUT_US * (clock_get_freq() / SECOND) / + CYCLE_PER_FLASH_LOOP); } static int unlock(int bank) @@ -90,12 +91,11 @@ static int unlock(int bank) STM32_FLASH_KEYR(bank) = FLASH_KEYR_KEY1; STM32_FLASH_KEYR(bank) = FLASH_KEYR_KEY2; - asm volatile("dsb; isb"); ignore_bus_fault(0); } - return (STM32_FLASH_CR(bank) & FLASH_CR_LOCK) ? EC_ERROR_UNKNOWN - : EC_SUCCESS; + return (STM32_FLASH_CR(bank) & FLASH_CR_LOCK) ? EC_ERROR_UNKNOWN : + EC_SUCCESS; } static void lock(int bank) @@ -111,11 +111,7 @@ static int unlock_optb(void) if (unlock(0)) return EC_ERROR_UNKNOWN; - /* - * Always use bank 0 flash controller as there is only one option bytes - * set for both banks. - */ - if (STM32_FLASH_OPTCR(0) & FLASH_OPTCR_OPTLOCK) { + if (flash_option_bytes_locked()) { /* * We may have already locked the flash module and get a bus * fault in the attempt to unlock. Need to disable bus fault @@ -123,28 +119,25 @@ static int unlock_optb(void) */ ignore_bus_fault(1); - STM32_FLASH_OPTKEYR(0) = FLASH_OPTKEYR_KEY1; - STM32_FLASH_OPTKEYR(0) = FLASH_OPTKEYR_KEY2; - asm volatile("dsb; isb"); + unlock_flash_option_bytes(); ignore_bus_fault(0); } - return STM32_FLASH_OPTCR(0) & FLASH_OPTCR_OPTLOCK ? EC_ERROR_UNKNOWN - : EC_SUCCESS; + return flash_option_bytes_locked() ? EC_ERROR_UNKNOWN : EC_SUCCESS; } static int commit_optb(void) { /* might use this before timer_init, cannot use get_time/usleep */ - int timeout = (FLASH_OPT_PRG_TIMEOUT_US * - (clock_get_freq() / SECOND) / CYCLE_PER_FLASH_LOOP); + int timeout = (FLASH_OPT_PRG_TIMEOUT_US * (clock_get_freq() / SECOND) / + CYCLE_PER_FLASH_LOOP); STM32_FLASH_OPTCR(0) |= FLASH_OPTCR_OPTSTART; while (STM32_FLASH_OPTSR_CUR(0) & FLASH_OPTSR_BUSY && timeout-- > 0) ; - STM32_FLASH_OPTCR(0) |= FLASH_OPTCR_OPTLOCK; + lock_flash_option_bytes(); lock(0); return (timeout > 0) ? EC_SUCCESS : EC_ERROR_TIMEOUT; @@ -155,11 +148,91 @@ static void protect_blocks(uint32_t blocks) if (unlock_optb()) return; STM32_FLASH_WPSN_PRG(0) &= ~(blocks & BLOCKS_HWBANK_MASK); - STM32_FLASH_WPSN_PRG(1) &= ~((blocks >> BLOCKS_PER_HWBANK) - & BLOCKS_HWBANK_MASK); + STM32_FLASH_WPSN_PRG(1) &= + ~((blocks >> BLOCKS_PER_HWBANK) & BLOCKS_HWBANK_MASK); commit_optb(); } +/* + * Helper function definitions for consistency with F4 to enable flash + * physical unitesting + */ +void unlock_flash_control_register(void) +{ + unlock(0); + unlock(1); +} + +void unlock_flash_option_bytes(void) +{ + /* + * Always use bank 0 flash controller as there is only one option bytes + * set for both banks. See http://b/181130245 + * + * Consecutively program values. Ref: RM0433:4.9.2 + */ + STM32_FLASH_OPTKEYR(0) = FLASH_OPTKEYR_KEY1; + STM32_FLASH_OPTKEYR(0) = FLASH_OPTKEYR_KEY2; +} + +void disable_flash_option_bytes(void) +{ + ignore_bus_fault(1); + /* + * Always use bank 0 flash controller as there is only one option bytes + * set for both banks. See http://b/181130245 + * + * Writing anything other than the pre-defined keys to the option key + * register results in a bus fault and the register being locked until + * reboot (even with a further correct key write). + */ + STM32_FLASH_OPTKEYR(0) = 0xffffffff; + ignore_bus_fault(0); +} + +void disable_flash_control_register(void) +{ + ignore_bus_fault(1); + /* + * Writing anything other than the pre-defined keys to a key + * register results in a bus fault and the register being locked until + * reboot (even with a further correct key write). + */ + STM32_FLASH_KEYR(0) = 0xffffffff; + STM32_FLASH_KEYR(1) = 0xffffffff; + ignore_bus_fault(0); +} + +void lock_flash_control_register(void) +{ + lock(0); + lock(1); +} + +void lock_flash_option_bytes(void) +{ + /* + * Always use bank 0 flash controller as there is only one option bytes + * set for both banks. See http://b/181130245 + */ + STM32_FLASH_OPTCR(0) |= FLASH_OPTCR_OPTLOCK; +} + +bool flash_option_bytes_locked(void) +{ + /* + * Always use bank 0 flash controller as there is only one option bytes + * set for both banks. See http://b/181130245 + */ + return !!(STM32_FLASH_OPTCR(0) & FLASH_OPTCR_OPTLOCK); +} + +bool flash_control_register_locked(void) +{ + return !!(STM32_FLASH_CR(0) & FLASH_CR_LOCK) && + !!(STM32_FLASH_CR(1) & FLASH_CR_LOCK); +} + /* * If RDP as PSTATE option is defined, use that as 'Write Protect enabled' flag: * it makes no sense to be able to unlock RO, as that'd allow flashing @@ -177,8 +250,8 @@ static void protect_blocks(uint32_t blocks) static int is_wp_enabled(void) { #ifdef CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE - return (STM32_FLASH_OPTSR_CUR(0) & FLASH_OPTSR_RDP_MASK) - != FLASH_OPTSR_RDP_LEVEL_0; + return (STM32_FLASH_OPTSR_CUR(0) & FLASH_OPTSR_RDP_MASK) != + FLASH_OPTSR_RDP_LEVEL_0; #else return !!(STM32_FLASH_OPTSR_CUR(0) & FLASH_OPTSR_RSS1); #endif @@ -212,7 +285,7 @@ static int set_wp(int enabled) /*****************************************************************************/ /* Physical layer APIs */ -int flash_physical_write(int offset, int size, const char *data) +int crec_flash_physical_write(int offset, int size, const char *data) { int res = EC_SUCCESS; int bank = offset / HWBANK_SIZE; @@ -236,8 +309,8 @@ int flash_physical_write(int offset, int size, const char *data) STM32_FLASH_CCR(bank) = FLASH_CCR_ERR_MASK; /* select write parallelism */ - STM32_FLASH_CR(bank) = (STM32_FLASH_CR(bank) & ~FLASH_CR_PSIZE_MASK) - | DEFAULT_PSIZE; + STM32_FLASH_CR(bank) = (STM32_FLASH_CR(bank) & ~FLASH_CR_PSIZE_MASK) | + DEFAULT_PSIZE; /* set PG bit */ STM32_FLASH_CR(bank) |= FLASH_CR_PG; @@ -251,18 +324,21 @@ int flash_physical_write(int offset, int size, const char *data) /* write a 256-bit flash word */ if (unaligned) { - for (i = 0; i < CONFIG_FLASH_WRITE_SIZE / 4; i++, - data += 4) - *address++ = (uint32_t)data[0] | (data[1] << 8) - | (data[2] << 16) | (data[3] << 24); + for (i = 0; i < CONFIG_FLASH_WRITE_SIZE / 4; + i++, data += 4) + *address++ = (uint32_t)data[0] | + (data[1] << 8) | (data[2] << 16) | + (data[3] << 24); } else { for (i = 0; i < CONFIG_FLASH_WRITE_SIZE / 4; i++) *address++ = *data32++; } /* Wait for writes to complete */ - for (i = 0; (STM32_FLASH_SR(bank) & - (FLASH_SR_WBNE | FLASH_SR_QW)) && (i < timeout); i++) + for (i = 0; + (STM32_FLASH_SR(bank) & (FLASH_SR_WBNE | FLASH_SR_QW)) && + (i < timeout); + i++) ; if (STM32_FLASH_SR(bank) & (FLASH_SR_WBNE | FLASH_SR_QW)) { @@ -290,7 +366,7 @@ int flash_physical_write(int offset, int size, const char *data) return res; } -int flash_physical_erase(int offset, int size) +int crec_flash_physical_erase(int offset, int size) { int res = EC_SUCCESS; int bank = offset / HWBANK_SIZE; @@ -311,16 +387,16 @@ int flash_physical_erase(int offset, int size) STM32_FLASH_CCR(bank) = FLASH_CCR_ERR_MASK; /* select erase parallelism */ - STM32_FLASH_CR(bank) = (STM32_FLASH_CR(bank) & ~FLASH_CR_PSIZE_MASK) - | DEFAULT_PSIZE; + STM32_FLASH_CR(bank) = (STM32_FLASH_CR(bank) & ~FLASH_CR_PSIZE_MASK) | + DEFAULT_PSIZE; for (sect = offset / CONFIG_FLASH_ERASE_SIZE; sect < last; sect++) { timestamp_t deadline; /* select page to erase and PER bit */ - STM32_FLASH_CR(bank) = (STM32_FLASH_CR(bank) - & ~FLASH_CR_SNB_MASK) - | FLASH_CR_SER | FLASH_CR_SNB(sect); + STM32_FLASH_CR(bank) = + (STM32_FLASH_CR(bank) & ~FLASH_CR_SNB_MASK) | + FLASH_CR_SER | FLASH_CR_SNB(sect); /* set STRT bit : start erase */ STM32_FLASH_CR(bank) |= FLASH_CR_STRT; @@ -335,7 +411,12 @@ int flash_physical_erase(int offset, int size) /* Wait for erase to complete */ while ((STM32_FLASH_SR(bank) & FLASH_SR_BUSY) && (get_time().val < deadline.val)) { - usleep(5000); + /* + * Interrupts may not be enabled, so we are using + * udelay() instead of usleep() which can trigger + * Forced Hard Fault (see b/180761547). + */ + udelay(5000); } if (STM32_FLASH_SR(bank) & FLASH_SR_BUSY) { res = EC_ERROR_TIMEOUT; @@ -366,7 +447,7 @@ int flash_physical_erase(int offset, int size) return res; } -int flash_physical_get_protect(int block) +int crec_flash_physical_get_protect(int block) { int bank = block / BLOCKS_PER_HWBANK; int index = block % BLOCKS_PER_HWBANK; @@ -378,7 +459,7 @@ int flash_physical_get_protect(int block) * Note: This does not need to update _NOW flags, as flash_get_protect * in common code already does so. */ -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { uint32_t flags = 0; @@ -398,7 +479,7 @@ uint32_t flash_physical_get_protect_flags(void) #define WP_RANGE(start, count) (((1 << (count)) - 1) << (start)) #define RO_WP_RANGE WP_RANGE(WP_BANK_OFFSET, WP_BANK_COUNT) -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { protect_blocks(RO_WP_RANGE); @@ -411,24 +492,20 @@ int flash_physical_protect_now(int all) * permanently locked until reset, a correct keyring write * will not unlock it. */ - ignore_bus_fault(1); if (all) { /* cannot do any write/erase access until next reboot */ - STM32_FLASH_KEYR(0) = 0xffffffff; - STM32_FLASH_KEYR(1) = 0xffffffff; + disable_flash_control_register(); access_disabled = 1; } /* cannot modify the WP bits in the option bytes until reboot */ - STM32_FLASH_OPTKEYR(0) = 0xffffffff; + disable_flash_option_bytes(); option_disabled = 1; - asm volatile("dsb; isb"); - ignore_bus_fault(0); return EC_SUCCESS; } -int flash_physical_protect_at_boot(uint32_t new_flags) +int crec_flash_physical_protect_at_boot(uint32_t new_flags) { int new_wp_enable = !!(new_flags & EC_FLASH_PROTECT_RO_AT_BOOT); @@ -438,14 +515,13 @@ int flash_physical_protect_at_boot(uint32_t new_flags) return EC_SUCCESS; } -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ALL_NOW; } -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { uint32_t ret = 0; @@ -464,7 +540,7 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) return ret; } -int flash_physical_restore_state(void) +int crec_flash_physical_restore_state(void) { uint32_t reset_flags = system_get_reset_flags(); int version, size; @@ -473,11 +549,11 @@ int flash_physical_restore_state(void) /* * If we have already jumped between images, an earlier image could * have applied write protection. We simply need to represent these - * irreversible flags to other components. + * irreversible flags to other components. */ if (reset_flags & EC_RESET_FLAG_SYSJUMP) { prev = (const struct flash_wp_state *)system_get_jump_tag( - FLASH_SYSJUMP_TAG, &version, &size); + FLASH_SYSJUMP_TAG, &version, &size); if (prev && version == FLASH_HOOK_VERSION && size == sizeof(*prev)) { access_disabled = prev->access_disabled; @@ -490,14 +566,14 @@ int flash_physical_restore_state(void) return 0; } -int flash_pre_init(void) +int crec_flash_pre_init(void) { uint32_t reset_flags = system_get_reset_flags(); - uint32_t prot_flags = flash_get_protect(); + uint32_t prot_flags = crec_flash_get_protect(); uint32_t unwanted_prot_flags = EC_FLASH_PROTECT_ALL_NOW | - EC_FLASH_PROTECT_ERROR_INCONSISTENT; + EC_FLASH_PROTECT_ERROR_INCONSISTENT; - if (flash_physical_restore_state()) + if (crec_flash_physical_restore_state()) return EC_SUCCESS; /* @@ -516,13 +592,13 @@ int flash_pre_init(void) !(prot_flags & EC_FLASH_PROTECT_RO_NOW)) { int rv; - rv = flash_set_protect(EC_FLASH_PROTECT_RO_NOW, - EC_FLASH_PROTECT_RO_NOW); + rv = crec_flash_set_protect(EC_FLASH_PROTECT_RO_NOW, + EC_FLASH_PROTECT_RO_NOW); if (rv) return rv; /* Re-read flags */ - prot_flags = flash_get_protect(); + prot_flags = crec_flash_get_protect(); } } else { /* Don't want RO flash protected */ diff --git a/chip/stm32/flash-stm32l.c b/chip/stm32/flash-stm32l.c index a151a26cf8..b83f8961af 100644 --- a/chip/stm32/flash-stm32l.c +++ b/chip/stm32/flash-stm32l.c @@ -1,13 +1,15 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Flash memory module for Chrome EC */ +#include "builtin/assert.h" #include "clock.h" #include "console.h" #include "flash.h" +#include "panic.h" #include "registers.h" #include "system.h" #include "task.h" @@ -34,7 +36,8 @@ static void lock(void) ignore_bus_fault(1); STM32_FLASH_PECR = STM32_FLASH_PECR_PE_LOCK | - STM32_FLASH_PECR_PRG_LOCK | STM32_FLASH_PECR_OPT_LOCK; + STM32_FLASH_PECR_PRG_LOCK | + STM32_FLASH_PECR_OPT_LOCK; ignore_bus_fault(0); } @@ -105,8 +108,8 @@ static uint16_t read_optb(int offset) */ static void write_optb(int offset, uint16_t value) { - REG32(STM32_OPTB_BASE + offset) = - (uint32_t)value | ((uint32_t)(~value) << 16); + REG32(STM32_OPTB_BASE + offset) = (uint32_t)value | + ((uint32_t)(~value) << 16); } /** @@ -115,7 +118,7 @@ static void write_optb(int offset, uint16_t value) static uint32_t read_optb_wrp(void) { return read_optb(STM32_OPTB_WRP1L) | - ((uint32_t)read_optb(STM32_OPTB_WRP1H) << 16); + ((uint32_t)read_optb(STM32_OPTB_WRP1H) << 16); } /** @@ -133,8 +136,8 @@ static void write_optb_wrp(uint32_t value) * This function lives in internal RAM, as we cannot read flash during writing. * You must not call other functions from this one or declare it static. */ -void __attribute__((section(".iram.text"))) - iram_flash_write(uint32_t *addr, uint32_t *data) +void __attribute__((section(".iram.text"))) +iram_flash_write(uint32_t *addr, uint32_t *data) { int i; @@ -158,7 +161,7 @@ void __attribute__((section(".iram.text"))) STM32_FLASH_PECR &= ~(STM32_FLASH_PECR_PROG | STM32_FLASH_PECR_FPRG); } -int flash_physical_write(int offset, int size, const char *data) +int crec_flash_physical_write(int offset, int size, const char *data) { uint32_t *data32 = (uint32_t *)data; uint32_t *address = (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset); @@ -189,7 +192,7 @@ int flash_physical_write(int offset, int size, const char *data) /* Update flash timeout based on current clock speed */ flash_timeout_loop = FLASH_TIMEOUT_MS * (clock_get_freq() / MSEC) / - CYCLE_PER_FLASH_LOOP; + CYCLE_PER_FLASH_LOOP; while (size > 0) { /* @@ -204,7 +207,8 @@ int flash_physical_write(int offset, int size, const char *data) /* Wait for writes to complete */ for (i = 0; ((STM32_FLASH_SR & 9) != 8) && - (i < flash_timeout_loop); i++) + (i < flash_timeout_loop); + i++) ; size -= sizeof(uint32_t); @@ -240,7 +244,7 @@ int flash_physical_write(int offset, int size, const char *data) return res; } -int flash_physical_erase(int offset, int size) +int crec_flash_physical_erase(int offset, int size) { uint32_t *address; int res = EC_SUCCESS; @@ -257,13 +261,13 @@ int flash_physical_erase(int offset, int size) for (address = (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset); size > 0; size -= CONFIG_FLASH_ERASE_SIZE, - address += CONFIG_FLASH_ERASE_SIZE / sizeof(uint32_t)) { + address += CONFIG_FLASH_ERASE_SIZE / sizeof(uint32_t)) { timestamp_t deadline; /* Do nothing if already erased */ - if (flash_is_erased((uint32_t)address - - CONFIG_PROGRAM_MEMORY_BASE, - CONFIG_FLASH_ERASE_SIZE)) + if (crec_flash_is_erased((uint32_t)address - + CONFIG_PROGRAM_MEMORY_BASE, + CONFIG_FLASH_ERASE_SIZE)) continue; /* Start erase */ @@ -304,20 +308,20 @@ int flash_physical_erase(int offset, int size) return res; } -int flash_physical_get_protect(int block) +int crec_flash_physical_get_protect(int block) { /* * If the entire flash interface is locked, then all blocks are * protected until reboot. */ - if (flash_physical_get_protect_flags() & EC_FLASH_PROTECT_ALL_NOW) + if (crec_flash_physical_get_protect_flags() & EC_FLASH_PROTECT_ALL_NOW) return 1; /* Check the active write protect status */ return STM32_FLASH_WRPR & BIT(block); } -int flash_physical_protect_at_boot(uint32_t new_flags) +int crec_flash_physical_protect_at_boot(uint32_t new_flags) { uint32_t prot; uint32_t mask = (BIT(WP_BANK_COUNT) - 1) << WP_BANK_OFFSET; @@ -336,7 +340,7 @@ int flash_physical_protect_at_boot(uint32_t new_flags) prot &= ~mask; if (prot == read_optb_wrp()) - return EC_SUCCESS; /* No bits changed */ + return EC_SUCCESS; /* No bits changed */ /* Unlock option bytes */ rv = unlock(STM32_FLASH_PECR_OPT_LOCK); @@ -352,7 +356,7 @@ int flash_physical_protect_at_boot(uint32_t new_flags) return EC_SUCCESS; } -int flash_physical_force_reload(void) +int crec_flash_physical_force_reload(void) { int rv = unlock(STM32_FLASH_PECR_OPT_LOCK); @@ -367,7 +371,7 @@ int flash_physical_force_reload(void) return EC_ERROR_UNKNOWN; } -uint32_t flash_physical_get_protect_flags(void) +uint32_t crec_flash_physical_get_protect_flags(void) { uint32_t flags = 0; @@ -382,7 +386,7 @@ uint32_t flash_physical_get_protect_flags(void) return flags; } -int flash_physical_protect_now(int all) +int crec_flash_physical_protect_now(int all) { if (all) { /* Re-lock the registers if they're unlocked */ @@ -400,14 +404,13 @@ int flash_physical_protect_now(int all) } } -uint32_t flash_physical_get_valid_flags(void) +uint32_t crec_flash_physical_get_valid_flags(void) { - return EC_FLASH_PROTECT_RO_AT_BOOT | - EC_FLASH_PROTECT_RO_NOW | + return EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ALL_NOW; } -uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) +uint32_t crec_flash_physical_get_writable_flags(uint32_t cur_flags) { uint32_t ret = 0; @@ -426,10 +429,10 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) return ret; } -int flash_pre_init(void) +int crec_flash_pre_init(void) { uint32_t reset_flags = system_get_reset_flags(); - uint32_t prot_flags = flash_get_protect(); + uint32_t prot_flags = crec_flash_get_protect(); int need_reset = 0; /* @@ -448,7 +451,7 @@ int flash_pre_init(void) * update to the write protect register and reboot so * it takes effect. */ - flash_protect_at_boot(EC_FLASH_PROTECT_RO_AT_BOOT); + crec_flash_protect_at_boot(EC_FLASH_PROTECT_RO_AT_BOOT); need_reset = 1; } @@ -457,8 +460,8 @@ int flash_pre_init(void) * Write protect register was in an inconsistent state. * Set it back to a good state and reboot. */ - flash_protect_at_boot(prot_flags & - EC_FLASH_PROTECT_RO_AT_BOOT); + crec_flash_protect_at_boot(prot_flags & + EC_FLASH_PROTECT_RO_AT_BOOT); need_reset = 1; } } else if (prot_flags & (EC_FLASH_PROTECT_RO_NOW | diff --git a/chip/stm32/fpu.c b/chip/stm32/fpu.c new file mode 100644 index 0000000000..2bf0a0b803 --- /dev/null +++ b/chip/stm32/fpu.c @@ -0,0 +1,43 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "hooks.h" +#include "registers.h" +#include "task.h" + +static void fpu_init(void) +{ + task_enable_irq(STM32_IRQ_FPU); +} +DECLARE_HOOK(HOOK_INIT, fpu_init, HOOK_PRIO_DEFAULT); + +__attribute__((naked)) void IRQ_HANDLER(STM32_IRQ_FPU)(void) +{ + /* Naked call so we can extract raw LR and SP */ + asm volatile("mov r0, lr\n" + "mov r1, sp\n" + /* + * By default Floating-point context control register + * (FPCCR) have ASPEN and LSPEN bits enabled (see reset + * value in PM0214, 4.6.2 Floating-point context control + * register (FPCCR)). This means that lazy floating-point + * context save and restore is enabled. To save context on + * stack it's necessary to perform read access from FPU + * (see PM0214 4.6.7 Enabling and clearing FPU exception + * interrupts). + */ + "vmrs r2, fpscr\n" + /* + * Must push registers in pairs to keep 64-bit aligned + * stack for ARM EABI. + */ + "push {r0, lr}\n" + "bl fpu_irq\n" + "pop {r0, pc}\n"); +} +const struct irq_priority __keep IRQ_PRIORITY(STM32_IRQ_FPU) + __attribute__((section(".rodata.irqprio"))) = { STM32_IRQ_FPU, + 0 }; /* highest priority + */ diff --git a/chip/stm32/gpio-f0-l.c b/chip/stm32/gpio-f0-l.c index 55628cb6d4..3482a8a552 100644 --- a/chip/stm32/gpio-f0-l.c +++ b/chip/stm32/gpio-f0-l.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,6 +9,7 @@ * These functions are shared by the STM32F0 and STM32L variants. */ +#include "builtin/assert.h" #include "common.h" #include "gpio_chip.h" #include "registers.h" @@ -62,11 +63,10 @@ int gpio_get_flags_by_mask(uint32_t port, uint32_t mask) flags |= GPIO_LOW; } - - if (STM32_EXTI_RTSR & mask) - flags |= GPIO_INT_F_RISING; if (STM32_EXTI_RTSR & mask) flags |= GPIO_INT_F_RISING; + if (STM32_EXTI_FTSR & mask) + flags |= GPIO_INT_F_FALLING; return flags; } @@ -80,9 +80,9 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) /* Set up pullup / pulldown */ val = STM32_GPIO_PUPDR(port) & ~mask2; if (flags & GPIO_PULL_UP) - val |= 0x55555555 & mask2; /* Pull Up = 01 */ + val |= 0x55555555 & mask2; /* Pull Up = 01 */ else if (flags & GPIO_PULL_DOWN) - val |= 0xaaaaaaaa & mask2; /* Pull Down = 10 */ + val |= 0xaaaaaaaa & mask2; /* Pull Down = 10 */ STM32_GPIO_PUPDR(port) = val; /* @@ -133,10 +133,10 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) } void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) + enum gpio_alternate_func func) { /* Ensure that the func parameter isn't overflowed */ - BUILD_ASSERT((int) MODULE_COUNT <= (int) GPIO_ALT_FUNC_MAX); + BUILD_ASSERT((int)MODULE_COUNT <= (int)GPIO_ALT_FUNC_MAX); int bit; uint32_t half; diff --git a/chip/stm32/gpio-stm32f0.c b/chip/stm32/gpio-stm32f0.c index d7e7aa4391..8fbc77a85c 100644 --- a/chip/stm32/gpio-stm32f0.c +++ b/chip/stm32/gpio-stm32f0.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/stm32/gpio-stm32f3.c b/chip/stm32/gpio-stm32f3.c index bfc2631de8..113aadc1e6 100644 --- a/chip/stm32/gpio-stm32f3.c +++ b/chip/stm32/gpio-stm32f3.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #include "clock.h" #include "common.h" #include "gpio.h" +#include "gpio_chip.h" #include "hooks.h" #include "registers.h" #include "task.h" @@ -40,12 +41,17 @@ static void gpio_init(void) } DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); -DECLARE_IRQ(STM32_IRQ_EXTI0, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI1, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI2, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI3, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI4, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI9_5, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI15_10, gpio_interrupt, 1); +static void _gpio_interrupt(void) +{ + gpio_interrupt(); +} + +DECLARE_IRQ(STM32_IRQ_EXTI0, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI1, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI2, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI3, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI4, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI9_5, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI15_10, _gpio_interrupt, 1); #include "gpio-f0-l.c" diff --git a/chip/stm32/gpio-stm32f4.c b/chip/stm32/gpio-stm32f4.c index 4a4e095a71..8e8658b7f9 100644 --- a/chip/stm32/gpio-stm32f4.c +++ b/chip/stm32/gpio-stm32f4.c @@ -1,13 +1,15 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* GPIO module for Chrome EC */ +#include "builtin/assert.h" #include "clock.h" #include "common.h" #include "gpio.h" +#include "gpio_chip.h" #include "hooks.h" #include "registers.h" #include "task.h" @@ -16,12 +18,12 @@ int gpio_required_clocks(void) { const int gpio_ports_used = (0 -# define GPIO(name, pin, flags) pin -# define GPIO_INT(name, pin, flags, signal) pin -# define ALTERNATE(pinmask, function, module, flagz) pinmask -# define PIN(port, index) | STM32_RCC_AHB1ENR_GPIO_PORT ## port -# define PIN_MASK(port, mask) PIN(port, 0) -# include "gpio.wrap" +#define GPIO(name, pin, flags) pin +#define GPIO_INT(name, pin, flags, signal) pin +#define ALTERNATE(pinmask, function, module, flagz) pinmask +#define PIN(port, index) | STM32_RCC_AHB1ENR_GPIO_PORT##port +#define PIN_MASK(port, mask) PIN(port, 0) +#include "gpio.wrap" ); /* @@ -55,12 +57,17 @@ static void gpio_init(void) } DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); -DECLARE_IRQ(STM32_IRQ_EXTI0, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI1, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI2, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI3, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI4, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI9_5, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI15_10, gpio_interrupt, 1); +static void _gpio_interrupt(void) +{ + gpio_interrupt(); +} + +DECLARE_IRQ(STM32_IRQ_EXTI0, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI1, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI2, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI3, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI4, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI9_5, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI15_10, _gpio_interrupt, 1); #include "gpio-f0-l.c" diff --git a/chip/stm32/gpio-stm32g4.c b/chip/stm32/gpio-stm32g4.c index 55b2c11e7b..8d1529a7ad 100644 --- a/chip/stm32/gpio-stm32g4.c +++ b/chip/stm32/gpio-stm32g4.c @@ -1,13 +1,15 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* GPIO module for Chrome EC */ +#include "builtin/assert.h" #include "clock.h" #include "common.h" #include "gpio.h" +#include "gpio_chip.h" #include "hooks.h" #include "registers.h" #include "task.h" @@ -16,12 +18,12 @@ int gpio_required_clocks(void) { const int gpio_ports_used = (0 -# define GPIO(name, pin, flags) pin -# define GPIO_INT(name, pin, flags, signal) pin -# define ALTERNATE(pinmask, function, module, flagz) pinmask -# define PIN(port, index) | STM32_RCC_AHB2ENR_GPIO_PORT ## port -# define PIN_MASK(port, mask) PIN(port, 0) -# include "gpio.wrap" +#define GPIO(name, pin, flags) pin +#define GPIO_INT(name, pin, flags, signal) pin +#define ALTERNATE(pinmask, function, module, flagz) pinmask +#define PIN(port, index) | STM32_RCC_AHB2ENR_GPIO_PORT##port +#define PIN_MASK(port, mask) PIN(port, 0) +#include "gpio.wrap" ); /* @@ -55,12 +57,17 @@ static void gpio_init(void) } DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); -DECLARE_IRQ(STM32_IRQ_EXTI0, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI1, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI2, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI3, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI4, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI9_5, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI15_10, gpio_interrupt, 1); +static void _gpio_interrupt(void) +{ + gpio_interrupt(); +} + +DECLARE_IRQ(STM32_IRQ_EXTI0, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI1, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI2, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI3, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI4, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI9_5, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI15_10, _gpio_interrupt, 1); #include "gpio-f0-l.c" diff --git a/chip/stm32/gpio-stm32h7.c b/chip/stm32/gpio-stm32h7.c index a2fb97225d..66c696e836 100644 --- a/chip/stm32/gpio-stm32h7.c +++ b/chip/stm32/gpio-stm32h7.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #include "clock.h" #include "common.h" #include "gpio.h" +#include "gpio_chip.h" #include "hooks.h" #include "registers.h" #include "task.h" @@ -32,16 +33,20 @@ static void gpio_init(void) task_enable_irq(STM32_IRQ_EXTI4); task_enable_irq(STM32_IRQ_EXTI9_5); task_enable_irq(STM32_IRQ_EXTI15_10); - } DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); -DECLARE_IRQ(STM32_IRQ_EXTI0, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI1, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI2, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI3, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI4, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI9_5, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI15_10, gpio_interrupt, 1); +static void _gpio_interrupt(void) +{ + gpio_interrupt(); +} + +DECLARE_IRQ(STM32_IRQ_EXTI0, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI1, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI2, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI3, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI4, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI9_5, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI15_10, _gpio_interrupt, 1); #include "gpio-f0-l.c" diff --git a/chip/stm32/gpio-stm32l.c b/chip/stm32/gpio-stm32l.c index 52c424eea0..920cb382b0 100644 --- a/chip/stm32/gpio-stm32l.c +++ b/chip/stm32/gpio-stm32l.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #include "clock.h" #include "common.h" #include "gpio.h" +#include "gpio_chip.h" #include "hooks.h" #include "registers.h" #include "task.h" @@ -40,12 +41,17 @@ static void gpio_init(void) } DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); -DECLARE_IRQ(STM32_IRQ_EXTI0, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI1, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI2, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI3, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI4, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI9_5, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI15_10, gpio_interrupt, 1); +static void _gpio_interrupt(void) +{ + gpio_interrupt(); +} + +DECLARE_IRQ(STM32_IRQ_EXTI0, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI1, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI2, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI3, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI4, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI9_5, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI15_10, _gpio_interrupt, 1); #include "gpio-f0-l.c" diff --git a/chip/stm32/gpio-stm32l4.c b/chip/stm32/gpio-stm32l4.c index b5c4940454..1ef83a188a 100644 --- a/chip/stm32/gpio-stm32l4.c +++ b/chip/stm32/gpio-stm32l4.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #include "clock.h" #include "common.h" #include "gpio.h" +#include "gpio_chip.h" #include "hooks.h" #include "registers.h" #include "task.h" @@ -37,16 +38,20 @@ static void gpio_init(void) task_enable_irq(STM32_IRQ_EXTI4); task_enable_irq(STM32_IRQ_EXTI9_5); task_enable_irq(STM32_IRQ_EXTI15_10); - } DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); -DECLARE_IRQ(STM32_IRQ_EXTI0, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI1, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI2, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI3, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI4, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI9_5, gpio_interrupt, 1); -DECLARE_IRQ(STM32_IRQ_EXTI15_10, gpio_interrupt, 1); +static void _gpio_interrupt(void) +{ + gpio_interrupt(); +} + +DECLARE_IRQ(STM32_IRQ_EXTI0, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI1, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI2, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI3, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI4, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI9_5, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI15_10, _gpio_interrupt, 1); #include "gpio-f0-l.c" diff --git a/chip/stm32/gpio-stm32l5.c b/chip/stm32/gpio-stm32l5.c new file mode 100644 index 0000000000..e714164650 --- /dev/null +++ b/chip/stm32/gpio-stm32l5.c @@ -0,0 +1,73 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "clock.h" +#include "common.h" +#include "gpio.h" +#include "gpio_chip.h" +#include "hooks.h" +#include "registers.h" +#include "task.h" +#include "util.h" + +void gpio_enable_clocks(void) +{ + /* + * Enable all GPIOs clocks + * + * TODO(crosbug.com/p/23770): only enable the banks we need to, + * and support disabling some of them in low-power idle. + */ + STM32_RCC_AHB2ENR |= STM32_RCC_AHB2ENR_GPIOMASK; + + /* Delay 1 AHB clock cycle after the clock is enabled */ + clock_wait_bus_cycles(BUS_AHB, 1); +} + +static void gpio_init(void) +{ + /* Enable IRQs now that pins are set up */ + task_enable_irq(STM32_IRQ_EXTI0); + task_enable_irq(STM32_IRQ_EXTI1); + task_enable_irq(STM32_IRQ_EXTI2); + task_enable_irq(STM32_IRQ_EXTI3); + task_enable_irq(STM32_IRQ_EXTI4); + task_enable_irq(STM32_IRQ_EXTI5); + task_enable_irq(STM32_IRQ_EXTI6); + task_enable_irq(STM32_IRQ_EXTI7); + task_enable_irq(STM32_IRQ_EXTI8); + task_enable_irq(STM32_IRQ_EXTI9); + task_enable_irq(STM32_IRQ_EXTI10); + task_enable_irq(STM32_IRQ_EXTI11); + task_enable_irq(STM32_IRQ_EXTI12); + task_enable_irq(STM32_IRQ_EXTI13); + task_enable_irq(STM32_IRQ_EXTI14); + task_enable_irq(STM32_IRQ_EXTI15); +} +DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); + +static void _gpio_interrupt(void) +{ + gpio_interrupt(); +} + +DECLARE_IRQ(STM32_IRQ_EXTI0, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI1, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI2, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI3, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI4, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI5, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI6, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI7, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI8, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI9, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI10, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI11, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI12, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI13, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI14, _gpio_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI15, _gpio_interrupt, 1); + +#include "gpio-f0-l.c" diff --git a/chip/stm32/gpio.c b/chip/stm32/gpio.c index ccfd3399e2..ade662d9d8 100644 --- a/chip/stm32/gpio.c +++ b/chip/stm32/gpio.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,7 +16,7 @@ #include "util.h" /* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args) +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) /* For each EXTI bit, record which GPIO entry is using it */ static uint8_t exti_events[16]; @@ -83,8 +83,8 @@ test_mockable int gpio_get_level(enum gpio_signal signal) void gpio_set_level(enum gpio_signal signal, int value) { - STM32_GPIO_BSRR(gpio_list[signal].port) = - gpio_list[signal].mask << (value ? 0 : 16); + STM32_GPIO_BSRR(gpio_list[signal].port) = gpio_list[signal].mask + << (value ? 0 : 16); } int gpio_enable_interrupt(enum gpio_signal signal) @@ -103,17 +103,26 @@ int gpio_enable_interrupt(enum gpio_signal signal) g_old += exti_events[bit]; if ((exti_events[bit]) && (exti_events[bit] != signal)) { - CPRINTS("Overriding %s with %s on EXTI%d", - g_old->name, g->name, bit); + CPRINTS("Overriding %s with %s on EXTI%d", g_old->name, g->name, + bit); } exti_events[bit] = signal; group = bit / 4; - shift = (bit % 4) * 4; + shift = bit % 4; bank = (g->port - STM32_GPIOA_BASE) / 0x400; - STM32_SYSCFG_EXTICR(group) = (STM32_SYSCFG_EXTICR(group) & - ~(0xF << shift)) | (bank << shift); +#ifdef STM32_EXTI_EXTICR + /* STM32L5 has 8-bit fields as part of EXTI registers. */ + STM32_EXTI_EXTICR(group) = + (STM32_EXTI_EXTICR(group) & ~(0xFF << (shift * 8))) | + (bank << (shift * 8)); +#else + /* Other STM chips have 4-bit fields as part of SYSCFG registers. */ + STM32_SYSCFG_EXTICR(group) = + (STM32_SYSCFG_EXTICR(group) & ~(0xF << (shift * 4))) | + (bank << (shift * 4)); +#endif STM32_EXTI_IMR |= g->mask; return EC_SUCCESS; @@ -141,11 +150,19 @@ int gpio_clear_pending_interrupt(enum gpio_signal signal) { const struct gpio_info *g = gpio_list + signal; - if (!g->mask || signal >= GPIO_IH_COUNT) + if (!g->mask || signal >= GPIO_IH_COUNT) { return EC_ERROR_INVAL; + } /* Write 1 to clear interrupt */ +#ifdef STM32_EXTI_RPR + /* Separate rising and falling edge pending registers. */ + STM32_EXTI_RPR = g->mask; + STM32_EXTI_FPR = g->mask; +#else + /* One combined rising/falling edge pending registers. */ STM32_EXTI_PR = g->mask; +#endif return EC_SUCCESS; } @@ -156,12 +173,21 @@ int gpio_clear_pending_interrupt(enum gpio_signal signal) void __keep gpio_interrupt(void) { int bit; + uint8_t signal; +#ifdef STM32_EXTI_RPR + /* process only GPIO EXTINTs (EXTINT0..15) not other EXTINTs */ + uint32_t pending_r = STM32_EXTI_RPR & 0xFFFF; + uint32_t pending_f = STM32_EXTI_FPR & 0xFFFF; + uint32_t pending = pending_r | pending_f; + /* Write 1 to clear interrupt */ + STM32_EXTI_RPR = pending_r; + STM32_EXTI_FPR = pending_f; +#else /* process only GPIO EXTINTs (EXTINT0..15) not other EXTINTs */ uint32_t pending = STM32_EXTI_PR & 0xFFFF; - uint8_t signal; - /* Write 1 to clear interrupt */ STM32_EXTI_PR = pending; +#endif while (pending) { bit = get_next_bit(&pending); @@ -171,7 +197,11 @@ void __keep gpio_interrupt(void) } } #ifdef CHIP_FAMILY_STM32F0 -DECLARE_IRQ(STM32_IRQ_EXTI0_1, gpio_interrupt, STM32_IRQ_EXT0_1_PRIORITY); -DECLARE_IRQ(STM32_IRQ_EXTI2_3, gpio_interrupt, STM32_IRQ_EXT2_3_PRIORITY); -DECLARE_IRQ(STM32_IRQ_EXTI4_15, gpio_interrupt, STM32_IRQ_EXTI4_15_PRIORITY); +static void _gpio_interrupt(void) +{ + gpio_interrupt(); +} +DECLARE_IRQ(STM32_IRQ_EXTI0_1, _gpio_interrupt, STM32_IRQ_EXT0_1_PRIORITY); +DECLARE_IRQ(STM32_IRQ_EXTI2_3, _gpio_interrupt, STM32_IRQ_EXT2_3_PRIORITY); +DECLARE_IRQ(STM32_IRQ_EXTI4_15, _gpio_interrupt, STM32_IRQ_EXTI4_15_PRIORITY); #endif diff --git a/chip/stm32/gpio_chip.h b/chip/stm32/gpio_chip.h index a5b642fb05..0a52fe9191 100644 --- a/chip/stm32/gpio_chip.h +++ b/chip/stm32/gpio_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,4 +19,5 @@ void gpio_enable_clocks(void); */ int gpio_required_clocks(void); -#endif /* __CROS_EC_CHIP_STM32_GPIO_CHIP_H */ +void __keep gpio_interrupt(void); +#endif /* __CROS_EC_CHIP_STM32_GPIO_CHIP_H */ diff --git a/chip/stm32/host_command_common.c b/chip/stm32/host_command_common.c index f1d5a0f103..10653a0711 100644 --- a/chip/stm32/host_command_common.c +++ b/chip/stm32/host_command_common.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,7 +9,7 @@ #include "spi.h" #include "usart_host_command.h" -#ifndef CONFIG_I2C_SLAVE +#ifndef CONFIG_I2C_PERIPHERAL /* Store current transport type */ static enum fp_transport_type curr_transport_type = FP_TRANSPORT_TYPE_UNKNOWN; @@ -17,40 +17,29 @@ static enum fp_transport_type curr_transport_type = FP_TRANSPORT_TYPE_UNKNOWN; /* * Get protocol information */ -static enum ec_status host_command_protocol_info(struct host_cmd_handler_args - *args) +static enum ec_status +host_command_protocol_info(struct host_cmd_handler_args *args) { enum ec_status ret_status = EC_RES_INVALID_COMMAND; /* - * If FP sensor task is enabled, read transport type from TRANSPORT_SEL - * bootstrap pin for the first time this function is called. + * Read transport type from TRANSPORT_SEL bootstrap pin the first + * time this function is called. */ - if ((IS_ENABLED(HAS_TASK_FPSENSOR)) && - (curr_transport_type == FP_TRANSPORT_TYPE_UNKNOWN)) { + if (IS_ENABLED(CONFIG_FINGERPRINT_MCU) && + (curr_transport_type == FP_TRANSPORT_TYPE_UNKNOWN)) curr_transport_type = get_fp_transport_type(); - } - /* - * Transport select is only enabled on boards with fp sensor tasks. - * If fp sensor task is enabled, transport is USART and - * host command layer is present, call usart_get_protocol. - * If fp sensor task is enabled and transport is SPI or else if only - * spi layer is enabled on non fp boards, call spi_get_protocol_info. - */ - if (IS_ENABLED(HAS_TASK_FPSENSOR) && - IS_ENABLED(CONFIG_USART_HOST_COMMAND) && + if (IS_ENABLED(CONFIG_USART_HOST_COMMAND) && curr_transport_type == FP_TRANSPORT_TYPE_UART) ret_status = usart_get_protocol_info(args); - else if (IS_ENABLED(CONFIG_SPI) || - (IS_ENABLED(HAS_TASK_FPSENSOR) && - curr_transport_type == FP_TRANSPORT_TYPE_SPI)) - ret_status = spi_get_protocol_info(args); + else if (IS_ENABLED(CONFIG_SPI) && + curr_transport_type == FP_TRANSPORT_TYPE_SPI) + ret_status = spi_get_protocol_info(args); return ret_status; } -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, - host_command_protocol_info, +DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, host_command_protocol_info, EC_VER_MASK(0)); -#endif /* CONFIG_I2C_SLAVE */ +#endif /* CONFIG_I2C_PERIPHERAL */ diff --git a/chip/stm32/hwtimer.c b/chip/stm32/hwtimer.c deleted file mode 100644 index 953110017f..0000000000 --- a/chip/stm32/hwtimer.c +++ /dev/null @@ -1,454 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Hardware timers driver */ - -#include "clock.h" -#include "clock-f.h" -#include "common.h" -#include "hooks.h" -#include "hwtimer.h" -#include "panic.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "watchdog.h" - -/* - * Trigger select mapping for slave timer from master timer. This is - * unfortunately not very straightforward; there's no tidy way to do this - * algorithmically. To avoid burning memory for a lookup table, use macros to - * compute the offset. This also has the benefit that compilation will fail if - * an unsupported master/slave pairing is used. - */ -#ifdef CHIP_FAMILY_STM32F0 -/* - * Slave Master - * 1 15 2 3 17 - * 2 1 15 3 14 - * 3 1 2 15 14 - * 15 2 3 16 17 - * -------------------- - * ts = 0 1 2 3 - */ -#define STM32_TIM_TS_SLAVE_1_MASTER_15 0 -#define STM32_TIM_TS_SLAVE_1_MASTER_2 1 -#define STM32_TIM_TS_SLAVE_1_MASTER_3 2 -#define STM32_TIM_TS_SLAVE_1_MASTER_17 3 -#define STM32_TIM_TS_SLAVE_2_MASTER_1 0 -#define STM32_TIM_TS_SLAVE_2_MASTER_15 1 -#define STM32_TIM_TS_SLAVE_2_MASTER_3 2 -#define STM32_TIM_TS_SLAVE_2_MASTER_14 3 -#define STM32_TIM_TS_SLAVE_3_MASTER_1 0 -#define STM32_TIM_TS_SLAVE_3_MASTER_2 1 -#define STM32_TIM_TS_SLAVE_3_MASTER_15 2 -#define STM32_TIM_TS_SLAVE_3_MASTER_14 3 -#define STM32_TIM_TS_SLAVE_15_MASTER_2 0 -#define STM32_TIM_TS_SLAVE_15_MASTER_3 1 -#define STM32_TIM_TS_SLAVE_15_MASTER_16 2 -#define STM32_TIM_TS_SLAVE_15_MASTER_17 3 -#elif defined(CHIP_FAMILY_STM32F3) -/* - * Slave Master - * 2 19 15 3 14 - * 3 19 2 5 14 - * 4 19 2 3 15 - * 5 2 3 4 15 - * 12 4 5 13 14 - * 19 2 3 15 16 - * --------------------- - * ts = 0 1 2 3 - */ -#define STM32_TIM_TS_SLAVE_2_MASTER_19 0 -#define STM32_TIM_TS_SLAVE_2_MASTER_15 1 -#define STM32_TIM_TS_SLAVE_2_MASTER_3 2 -#define STM32_TIM_TS_SLAVE_2_MASTER_14 3 -#define STM32_TIM_TS_SLAVE_3_MASTER_19 0 -#define STM32_TIM_TS_SLAVE_3_MASTER_2 1 -#define STM32_TIM_TS_SLAVE_3_MASTER_5 2 -#define STM32_TIM_TS_SLAVE_3_MASTER_14 3 -#define STM32_TIM_TS_SLAVE_4_MASTER_19 0 -#define STM32_TIM_TS_SLAVE_4_MASTER_2 1 -#define STM32_TIM_TS_SLAVE_4_MASTER_3 2 -#define STM32_TIM_TS_SLAVE_4_MASTER_15 3 -#define STM32_TIM_TS_SLAVE_5_MASTER_2 0 -#define STM32_TIM_TS_SLAVE_5_MASTER_3 1 -#define STM32_TIM_TS_SLAVE_5_MASTER_4 2 -#define STM32_TIM_TS_SLAVE_5_MASTER_15 3 -#define STM32_TIM_TS_SLAVE_12_MASTER_4 0 -#define STM32_TIM_TS_SLAVE_12_MASTER_5 1 -#define STM32_TIM_TS_SLAVE_12_MASTER_13 2 -#define STM32_TIM_TS_SLAVE_12_MASTER_14 3 -#define STM32_TIM_TS_SLAVE_19_MASTER_2 0 -#define STM32_TIM_TS_SLAVE_19_MASTER_3 1 -#define STM32_TIM_TS_SLAVE_19_MASTER_15 2 -#define STM32_TIM_TS_SLAVE_19_MASTER_16 3 -#else /* !CHIP_FAMILY_STM32F0 && !CHIP_FAMILY_STM32F3 */ -/* - * Slave Master - * 1 15 2 3 4 (STM32F100 only) - * 2 9 10 3 4 - * 3 9 2 11 4 - * 4 10 2 3 9 - * 9 2 3 10 11 (STM32L15x only) - * -------------------- - * ts = 0 1 2 3 - */ -#define STM32_TIM_TS_SLAVE_1_MASTER_15 0 -#define STM32_TIM_TS_SLAVE_1_MASTER_2 1 -#define STM32_TIM_TS_SLAVE_1_MASTER_3 2 -#define STM32_TIM_TS_SLAVE_1_MASTER_4 3 -#define STM32_TIM_TS_SLAVE_2_MASTER_9 0 -#define STM32_TIM_TS_SLAVE_2_MASTER_10 1 -#define STM32_TIM_TS_SLAVE_2_MASTER_3 2 -#define STM32_TIM_TS_SLAVE_2_MASTER_4 3 -#define STM32_TIM_TS_SLAVE_3_MASTER_9 0 -#define STM32_TIM_TS_SLAVE_3_MASTER_2 1 -#define STM32_TIM_TS_SLAVE_3_MASTER_11 2 -#define STM32_TIM_TS_SLAVE_3_MASTER_4 3 -#define STM32_TIM_TS_SLAVE_4_MASTER_10 0 -#define STM32_TIM_TS_SLAVE_4_MASTER_2 1 -#define STM32_TIM_TS_SLAVE_4_MASTER_3 2 -#define STM32_TIM_TS_SLAVE_4_MASTER_9 3 -#define STM32_TIM_TS_SLAVE_9_MASTER_2 0 -#define STM32_TIM_TS_SLAVE_9_MASTER_3 1 -#define STM32_TIM_TS_SLAVE_9_MASTER_10 2 -#define STM32_TIM_TS_SLAVE_9_MASTER_11 3 -#endif /* !CHIP_FAMILY_STM32F0 */ -#define TSMAP(slave, master) \ - CONCAT4(STM32_TIM_TS_SLAVE_, slave, _MASTER_, master) - -/* - * Timers are defined per board. This gives us flexibility to work around - * timers which are dedicated to board-specific PWM sources. - */ -#define IRQ_TIM(n) CONCAT2(STM32_IRQ_TIM, n) -#define IRQ_MSB IRQ_TIM(TIM_CLOCK_MSB) -#define IRQ_LSB IRQ_TIM(TIM_CLOCK_LSB) -#define IRQ_WD IRQ_TIM(TIM_WATCHDOG) - -/* TIM1 has fancy names for its IRQs; remap count-up IRQ for the macro above */ -#if defined TIM_WATCHDOG && (TIM_WATCHDOG == 1) -#define STM32_IRQ_TIM1 STM32_IRQ_TIM1_BRK_UP_TRG -#else /* !(TIM_WATCHDOG == 1) */ -#define STM32_IRQ_TIM1 STM32_IRQ_TIM1_CC -#endif /* !(TIM_WATCHDOG == 1) */ - -#define TIM_BASE(n) CONCAT3(STM32_TIM, n, _BASE) -#define TIM_WD_BASE TIM_BASE(TIM_WATCHDOG) - -static uint32_t last_deadline; - -void __hw_clock_event_set(uint32_t deadline) -{ - last_deadline = deadline; - - if ((deadline >> 16) > STM32_TIM_CNT(TIM_CLOCK_MSB)) { - /* first set a match on the MSB */ - STM32_TIM_CCR1(TIM_CLOCK_MSB) = deadline >> 16; - /* disable LSB match */ - STM32_TIM_DIER(TIM_CLOCK_LSB) &= ~2; - /* Clear the match flags */ - STM32_TIM_SR(TIM_CLOCK_MSB) = ~2; - STM32_TIM_SR(TIM_CLOCK_LSB) = ~2; - /* Set the match interrupt */ - STM32_TIM_DIER(TIM_CLOCK_MSB) |= 2; - } - /* - * In the unlikely case where the MSB has increased and matched - * the deadline MSB before we set the match interrupt, as the STM - * hardware timer won't trigger an interrupt, we fall back to the - * following LSB event code to set another interrupt. - */ - if ((deadline >> 16) == STM32_TIM_CNT(TIM_CLOCK_MSB)) { - /* we can set a match on the LSB only */ - STM32_TIM_CCR1(TIM_CLOCK_LSB) = deadline & 0xffff; - /* disable MSB match */ - STM32_TIM_DIER(TIM_CLOCK_MSB) &= ~2; - /* Clear the match flags */ - STM32_TIM_SR(TIM_CLOCK_MSB) = ~2; - STM32_TIM_SR(TIM_CLOCK_LSB) = ~2; - /* Set the match interrupt */ - STM32_TIM_DIER(TIM_CLOCK_LSB) |= 2; - } - /* - * If the LSB deadline is already in the past and won't trigger an - * interrupt, the common code in process_timers will deal with the - * expired timer and automatically set the next deadline, we don't need - * to do anything here. - */ -} - -uint32_t __hw_clock_event_get(void) -{ - return last_deadline; -} - -void __hw_clock_event_clear(void) -{ - /* Disable the match interrupts */ - STM32_TIM_DIER(TIM_CLOCK_LSB) &= ~2; - STM32_TIM_DIER(TIM_CLOCK_MSB) &= ~2; -} - -uint32_t __hw_clock_source_read(void) -{ - uint32_t hi; - uint32_t lo; - - /* Ensure the two half-words are coherent */ - do { - hi = STM32_TIM_CNT(TIM_CLOCK_MSB); - lo = STM32_TIM_CNT(TIM_CLOCK_LSB); - } while (hi != STM32_TIM_CNT(TIM_CLOCK_MSB)); - - return (hi << 16) | lo; -} - -void __hw_clock_source_set(uint32_t ts) -{ - STM32_TIM_CNT(TIM_CLOCK_MSB) = ts >> 16; - STM32_TIM_CNT(TIM_CLOCK_LSB) = ts & 0xffff; -} - -void __hw_clock_source_irq(void) -{ - uint32_t stat_tim_msb = STM32_TIM_SR(TIM_CLOCK_MSB); - - /* Clear status */ - STM32_TIM_SR(TIM_CLOCK_LSB) = 0; - STM32_TIM_SR(TIM_CLOCK_MSB) = 0; - - /* - * Find expired timers and set the new timer deadline - * signal overflow if the 16-bit MSB counter has overflowed. - */ - process_timers(stat_tim_msb & 0x01); -} -DECLARE_IRQ(IRQ_MSB, __hw_clock_source_irq, 1); -DECLARE_IRQ(IRQ_LSB, __hw_clock_source_irq, 1); - -void __hw_timer_enable_clock(int n, int enable) -{ - volatile uint32_t *reg; - uint32_t mask = 0; - - /* - * Mapping of timers to reg/mask is split into a few different ranges, - * some specific to individual chips. - */ -#if defined(CHIP_FAMILY_STM32F0) - if (n == 1) { - reg = &STM32_RCC_APB2ENR; - mask = STM32_RCC_PB2_TIM1; - } -#elif defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32F4) - if (n >= 9 && n <= 11) { - reg = &STM32_RCC_APB2ENR; - mask = STM32_RCC_PB2_TIM9 << (n - 9); - } -#endif - -#if defined(CHIP_FAMILY_STM32F0) - if (n >= 15 && n <= 17) { - reg = &STM32_RCC_APB2ENR; - mask = STM32_RCC_PB2_TIM15 << (n - 15); - } -#endif - -#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) - if (n == 14) { - reg = &STM32_RCC_APB1ENR; - mask = STM32_RCC_PB1_TIM14; - } -#endif - -#if defined(CHIP_FAMILY_STM32F3) - if (n == 12 || n == 13) { - reg = &STM32_RCC_APB1ENR; - mask = STM32_RCC_PB1_TIM12 << (n - 12); - } - if (n == 18) { - reg = &STM32_RCC_APB1ENR; - mask = STM32_RCC_PB1_TIM18; - } - if (n == 19) { - reg = &STM32_RCC_APB2ENR; - mask = STM32_RCC_PB2_TIM19; - } -#endif - - if (n >= 2 && n <= 7) { - reg = &STM32_RCC_APB1ENR; - mask = STM32_RCC_PB1_TIM2 << (n - 2); - } - - if (!mask) - return; - - if (enable) - *reg |= mask; - else - *reg &= ~mask; -} - -static void update_prescaler(void) -{ - /* - * Pre-scaler value : - * TIM_CLOCK_LSB is counting microseconds; - * TIM_CLOCK_MSB is counting every TIM_CLOCK_LSB overflow. - * - * This will take effect at the next update event (when the current - * prescaler counter ticks down, or if forced via EGR). - */ - STM32_TIM_PSC(TIM_CLOCK_MSB) = 0; - STM32_TIM_PSC(TIM_CLOCK_LSB) = (clock_get_timer_freq() / SECOND) - 1; -} -DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT); - -int __hw_clock_source_init(uint32_t start_t) -{ - /* - * we use 2 chained 16-bit counters to emulate a 32-bit one : - * TIM_CLOCK_MSB is the MSB (Slave) - * TIM_CLOCK_LSB is the LSB (Master) - */ - - /* Enable TIM_CLOCK_MSB and TIM_CLOCK_LSB clocks */ - __hw_timer_enable_clock(TIM_CLOCK_MSB, 1); - __hw_timer_enable_clock(TIM_CLOCK_LSB, 1); - - /* Delay 1 APB clock cycle after the clock is enabled */ - clock_wait_bus_cycles(BUS_APB, 1); - - /* - * Timer configuration : Upcounter, counter disabled, update event only - * on overflow. - */ - STM32_TIM_CR1(TIM_CLOCK_MSB) = 0x0004; - STM32_TIM_CR1(TIM_CLOCK_LSB) = 0x0004; - /* - * TIM_CLOCK_LSB (master mode) generates a periodic trigger signal on - * each UEV - */ - STM32_TIM_CR2(TIM_CLOCK_MSB) = 0x0000; - STM32_TIM_CR2(TIM_CLOCK_LSB) = 0x0020; - - STM32_TIM_SMCR(TIM_CLOCK_MSB) = 0x0007 | - (TSMAP(TIM_CLOCK_MSB, TIM_CLOCK_LSB) << 4); - STM32_TIM_SMCR(TIM_CLOCK_LSB) = 0x0000; - - /* Auto-reload value : 16-bit free-running counters */ - STM32_TIM_ARR(TIM_CLOCK_MSB) = 0xffff; - STM32_TIM_ARR(TIM_CLOCK_LSB) = 0xffff; - - /* Update prescaler */ - update_prescaler(); - - /* Reload the pre-scaler */ - STM32_TIM_EGR(TIM_CLOCK_MSB) = 0x0001; - STM32_TIM_EGR(TIM_CLOCK_LSB) = 0x0001; - - /* Set up the overflow interrupt on TIM_CLOCK_MSB */ - STM32_TIM_DIER(TIM_CLOCK_MSB) = 0x0001; - STM32_TIM_DIER(TIM_CLOCK_LSB) = 0x0000; - - /* Start counting */ - STM32_TIM_CR1(TIM_CLOCK_MSB) |= 1; - STM32_TIM_CR1(TIM_CLOCK_LSB) |= 1; - - /* Override the count with the start value now that counting has - * started. */ - __hw_clock_source_set(start_t); - - /* Enable timer interrupts */ - task_enable_irq(IRQ_MSB); - task_enable_irq(IRQ_LSB); - - return IRQ_LSB; -} - -#ifdef CONFIG_WATCHDOG_HELP - -void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp) -{ - struct timer_ctlr *timer = (struct timer_ctlr *)TIM_WD_BASE; - - /* clear status */ - timer->sr = 0; - - watchdog_trace(excep_lr, excep_sp); -} - -void IRQ_HANDLER(IRQ_WD)(void) __attribute__((naked)); -void IRQ_HANDLER(IRQ_WD)(void) -{ - /* Naked call so we can extract raw LR and SP */ - asm volatile("mov r0, lr\n" - "mov r1, sp\n" - /* Must push registers in pairs to keep 64-bit aligned - * stack for ARM EABI. */ - "push {r0, lr}\n" - "bl watchdog_check\n" - "pop {r0,pc}\n"); -} -const struct irq_priority __keep IRQ_PRIORITY(IRQ_WD) - __attribute__((section(".rodata.irqprio"))) - = {IRQ_WD, 0}; /* put the watchdog at the highest - priority */ - -void hwtimer_setup_watchdog(void) -{ - struct timer_ctlr *timer = (struct timer_ctlr *)TIM_WD_BASE; - - /* Enable clock */ - __hw_timer_enable_clock(TIM_WATCHDOG, 1); - - /* Delay 1 APB clock cycle after the clock is enabled */ - clock_wait_bus_cycles(BUS_APB, 1); - - /* - * Timer configuration : Down counter, counter disabled, update - * event only on overflow. - */ - timer->cr1 = 0x0014 | BIT(7); - - /* TIM (slave mode) uses TIM_CLOCK_LSB as internal trigger */ - timer->smcr = 0x0007 | (TSMAP(TIM_WATCHDOG, TIM_CLOCK_LSB) << 4); - - /* - * The auto-reload value is based on the period between rollovers for - * TIM_CLOCK_LSB. Since TIM_CLOCK_LSB runs at 1MHz, it will overflow - * in 65.536ms. We divide our required watchdog period by this amount - * to obtain the number of times TIM_CLOCK_LSB can overflow before we - * generate an interrupt. - */ - timer->arr = timer->cnt = CONFIG_AUX_TIMER_PERIOD_MS * MSEC / BIT(16); - - /* count on every TIM_CLOCK_LSB overflow */ - timer->psc = 0; - - /* Reload the pre-scaler from arr when it goes below zero */ - timer->egr = 0x0000; - - /* setup the overflow interrupt */ - timer->dier = 0x0001; - - /* Start counting */ - timer->cr1 |= 1; - - /* Enable timer interrupts */ - task_enable_irq(IRQ_WD); -} - -void hwtimer_reset_watchdog(void) -{ - struct timer_ctlr *timer = (struct timer_ctlr *)TIM_WD_BASE; - - timer->cnt = timer->arr; -} - -#endif /* defined(CONFIG_WATCHDOG_HELP) */ diff --git a/chip/stm32/hwtimer32.c b/chip/stm32/hwtimer32.c index 12057ad762..ebe46d8316 100644 --- a/chip/stm32/hwtimer32.c +++ b/chip/stm32/hwtimer32.c @@ -1,12 +1,13 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Hardware 32-bit timer driver */ -#include "clock.h" +#include "builtin/assert.h" #include "clock-f.h" +#include "clock.h" #include "common.h" #include "hooks.h" #include "hwtimer.h" @@ -16,8 +17,6 @@ #include "timer.h" #include "watchdog.h" -#define IRQ_TIM(n) CONCAT2(STM32_IRQ_TIM, n) - void __hw_clock_event_set(uint32_t deadline) { /* set the match on the deadline */ @@ -46,10 +45,34 @@ uint32_t __hw_clock_source_read(void) void __hw_clock_source_set(uint32_t ts) { + ASSERT(!is_interrupt_enabled()); + + /* + * Stop counter to avoid race between setting counter value + * and clearing status. + */ + STM32_TIM_CR1(TIM_CLOCK32) &= ~1; + + /* Set counter value */ STM32_TIM32_CNT(TIM_CLOCK32) = ts; + + /* + * Clear status. We may clear information other than timer overflow + * (eg. event timestamp was matched) but: + * - Bits other than overflow are unused (see __hw_clock_source_irq()) + * - After setting timestamp software will trigger timer interrupt using + * task_trigger_irq() (see force_time() in common/timer.c). + * process_timers() is called from timer interrupt, so if "match" bit + * was present in status (think: some task timers are expired) + * process_timers() will handle that correctly. + */ + STM32_TIM_SR(TIM_CLOCK32) = 0; + + /* Start counting */ + STM32_TIM_CR1(TIM_CLOCK32) |= 1; } -void __hw_clock_source_irq(void) +static void __hw_clock_source_irq(void) { uint32_t stat_tim = STM32_TIM_SR(TIM_CLOCK32); @@ -93,7 +116,7 @@ void __hw_timer_enable_clock(int n, int enable) #endif #if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \ -defined(CHIP_FAMILY_STM32H7) + defined(CHIP_FAMILY_STM32H7) if (n == 14) { reg = &STM32_RCC_APB1ENR; mask = STM32_RCC_PB1_TIM14; @@ -127,10 +150,22 @@ defined(CHIP_FAMILY_STM32H7) else if (n >= 15 && n <= 17) mask = STM32_RCC_APB2ENR_TIM15 << (n - 15); #endif +#if defined(CHIP_FAMILY_STM32L4) + if (n >= 2 && n <= 7) { + reg = &STM32_RCC_APB1ENR1; + mask = STM32_RCC_PB1_TIM2 << (n - 2); + } else if (n == 1 || n == 15 || n == 16) { + reg = &STM32_RCC_APB2ENR; + mask = (n == 1) ? STM32_RCC_APB2ENR_TIM1EN : + (n == 15) ? STM32_RCC_APB2ENR_TIM15EN : + STM32_RCC_APB2ENR_TIM16EN; + } +#else if (n >= 2 && n <= 7) { reg = &STM32_RCC_APB1ENR; mask = STM32_RCC_PB1_TIM2 << (n - 2); } +#endif if (!mask) return; @@ -142,7 +177,7 @@ defined(CHIP_FAMILY_STM32H7) } #if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32L4) || \ - defined(CHIP_FAMILY_STM32H7) + defined(CHIP_FAMILY_STM32F4) || defined(CHIP_FAMILY_STM32H7) /* for families using a variable clock feeding the timer */ static void update_prescaler(void) { @@ -179,11 +214,12 @@ static void update_prescaler(void) #ifdef CONFIG_WATCHDOG_HELP /* Watchdog timer runs at 1KHz */ STM32_TIM_PSC(TIM_WATCHDOG) = - (clock_get_timer_freq() / SECOND * MSEC)- 1; -#endif /* CONFIG_WATCHDOG_HELP */ + (clock_get_timer_freq() / SECOND * MSEC) - 1; +#endif /* CONFIG_WATCHDOG_HELP */ } DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT); -#endif /* CHIP_FAMILY_STM32L || CHIP_FAMILY_STM32L4 || CHIP_FAMILY_STM32H7 */ +#endif /* CHIP_FAMILY_STM32L || CHIP_FAMILY_STM32L4 || */ +/* CHIP_FAMILY_STM32F4 || CHIP_FAMILY_STM32H7 */ int __hw_clock_source_init(uint32_t start_t) { @@ -213,13 +249,12 @@ int __hw_clock_source_init(uint32_t start_t) /* Set up the overflow interrupt */ STM32_TIM_DIER(TIM_CLOCK32) = 0x0001; + /* Override the count with the start value */ + STM32_TIM32_CNT(TIM_CLOCK32) = start_t; + /* Start counting */ STM32_TIM_CR1(TIM_CLOCK32) |= 1; - /* Override the count with the start value now that counting has - * started. */ - __hw_clock_source_set(start_t); - /* Enable timer interrupts */ task_enable_irq(IRQ_TIM(TIM_CLOCK32)); @@ -251,12 +286,17 @@ void IRQ_HANDLER(IRQ_WD)(void) "pop {r0,pc}\n"); } const struct irq_priority __keep IRQ_PRIORITY(IRQ_WD) - __attribute__((section(".rodata.irqprio"))) - = {IRQ_WD, 0}; /* put the watchdog at the highest - priority */ + __attribute__((section(".rodata.irqprio"))) = { + IRQ_WD, 0 + }; /* put the watchdog + at the highest + priority + */ void hwtimer_setup_watchdog(void) { + int freq; + /* Enable clock */ __hw_timer_enable_clock(TIM_WATCHDOG, 1); /* Delay 1 APB clock cycle after the clock is enabled */ @@ -271,13 +311,30 @@ void hwtimer_setup_watchdog(void) STM32_TIM_CR2(TIM_WATCHDOG) = 0x0000; STM32_TIM_SMCR(TIM_WATCHDOG) = 0x0000; - /* AUto-reload value */ - STM32_TIM_ARR(TIM_WATCHDOG) = CONFIG_AUX_TIMER_PERIOD_MS; + /* + * all timers has 16-bit prescale. + * For clock freq > 64MHz, 16bit prescale cannot meet 1KHz. + * set prescale as 10KHz and 10 times arr value instead. + * For clock freq < 64MHz, timer runs at 1KHz. + */ + freq = clock_get_timer_freq(); - /* Update prescaler: watchdog timer runs at 1KHz */ - STM32_TIM_PSC(TIM_WATCHDOG) = - (clock_get_timer_freq() / SECOND * MSEC) - 1; + if (freq <= 64000000 || !IS_ENABLED(CHIP_FAMILY_STM32L4)) { + /* AUto-reload value */ + STM32_TIM_ARR(TIM_WATCHDOG) = CONFIG_AUX_TIMER_PERIOD_MS; + /* Update prescaler: watchdog timer runs at 1KHz */ + STM32_TIM_PSC(TIM_WATCHDOG) = (freq / SECOND * MSEC) - 1; + } +#ifdef CHIP_FAMILY_STM32L4 + else { + /* 10 times ARR value with 10KHz timer */ + STM32_TIM_ARR(TIM_WATCHDOG) = CONFIG_AUX_TIMER_PERIOD_MS * 10; + + /* Update prescaler: watchdog timer runs at 10KHz */ + STM32_TIM_PSC(TIM_WATCHDOG) = (freq / SECOND / 10 * MSEC) - 1; + } +#endif /* Reload the pre-scaler */ STM32_TIM_EGR(TIM_WATCHDOG) = 0x0001; @@ -297,4 +354,4 @@ void hwtimer_reset_watchdog(void) STM32_TIM_CNT(TIM_WATCHDOG) = 0x0000; } -#endif /* CONFIG_WATCHDOG_HELP */ +#endif /* CONFIG_WATCHDOG_HELP */ diff --git a/chip/stm32/i2c-stm32f0.c b/chip/stm32/i2c-stm32f0.c index f722de2b54..acd4d3aca6 100644 --- a/chip/stm32/i2c-stm32f0.c +++ b/chip/stm32/i2c-stm32f0.c @@ -1,8 +1,9 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "chipset.h" #include "clock.h" #include "common.h" @@ -23,37 +24,36 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) /* Transmit timeout in microseconds */ -#define I2C_TX_TIMEOUT_MASTER (10 * MSEC) +#define I2C_TX_TIMEOUT_CONTROLLER (10 * MSEC) -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS #if (I2C_PORT_EC == STM32_I2C1_PORT) -#define IRQ_SLAVE STM32_IRQ_I2C1 +#define IRQ_PERIPHERAL STM32_IRQ_I2C1 #else -#define IRQ_SLAVE STM32_IRQ_I2C2 +#define IRQ_PERIPHERAL STM32_IRQ_I2C2 #endif #endif - /* I2C port state data */ struct i2c_port_data { - uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ - enum i2c_freq freq; /* Port clock speed */ + uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ + enum i2c_freq freq; /* Port clock speed */ }; static struct i2c_port_data pdata[I2C_PORT_COUNT]; void i2c_set_timeout(int port, uint32_t timeout) { - pdata[port].timeout_us = timeout ? timeout : I2C_TX_TIMEOUT_MASTER; + pdata[port].timeout_us = timeout ? timeout : I2C_TX_TIMEOUT_CONTROLLER; } /* timingr register values for supported input clks / i2c clk rates */ static const uint32_t busyloop_us[I2C_FREQ_COUNT] = { [I2C_FREQ_1000KHZ] = 16, /* Enough for 2 bytes */ - [I2C_FREQ_400KHZ] = 40, /* Enough for 2 bytes */ - [I2C_FREQ_100KHZ] = 0, /* No busy looping at 100kHz (bus is slow) */ + [I2C_FREQ_400KHZ] = 40, /* Enough for 2 bytes */ + [I2C_FREQ_100KHZ] = 0, /* No busy looping at 100kHz (bus is slow) */ }; /** @@ -72,7 +72,7 @@ static int wait_isr(int port, int mask) /* Check for errors */ if (isr & (STM32_I2C_ISR_ARLO | STM32_I2C_ISR_BERR | - STM32_I2C_ISR_NACK)) + STM32_I2C_ISR_NACK)) return EC_ERROR_UNKNOWN; /* Check for desired mask */ @@ -117,9 +117,8 @@ int chip_i2c_set_freq(int port, enum i2c_freq freq) { enum stm32_i2c_clk_src src = I2C_CLK_SRC_48MHZ; -#if defined(CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS) && \ - defined(CONFIG_LOW_POWER_IDLE) && \ - (I2C_PORT_EC == STM32_I2C1_PORT) +#if defined(CONFIG_HOSTCMD_I2C_ADDR_FLAGS) && \ + defined(CONFIG_LOW_POWER_IDLE) && (I2C_PORT_EC == STM32_I2C1_PORT) if (port == STM32_I2C1_PORT) { /* * Use HSI (8MHz) for i2c clock. This allows smooth wakeup @@ -164,9 +163,8 @@ static int i2c_init_port(const struct i2c_port_t *p) STM32_RCC_APB1ENR |= 1 << (21 + port); if (port == STM32_I2C1_PORT) { -#if defined(CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS) && \ - defined(CONFIG_LOW_POWER_IDLE) && \ - (I2C_PORT_EC == STM32_I2C1_PORT) +#if defined(CONFIG_HOSTCMD_I2C_ADDR_FLAGS) && \ + defined(CONFIG_LOW_POWER_IDLE) && (I2C_PORT_EC == STM32_I2C1_PORT) /* * Use HSI (8MHz) for i2c clock. This allows smooth wakeup * from STOP mode since HSI is only clock running immediately @@ -209,8 +207,8 @@ static int i2c_init_port(const struct i2c_port_t *p) } /*****************************************************************************/ -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS -/* Host command slave */ +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS +/* Host command peripheral */ /* * Buffer for received host command packets (including prefix byte on request, * and result/size on response). After any protocol-specific headers, the @@ -218,7 +216,7 @@ static int i2c_init_port(const struct i2c_port_t *p) */ static uint8_t host_buffer_padded[I2C_MAX_HOST_PACKET_SIZE + 4 + CONFIG_I2C_EXTRA_PACKET_SIZE] __aligned(4); -static uint8_t * const host_buffer = host_buffer_padded + 2; +static uint8_t *const host_buffer = host_buffer_padded + 2; static uint8_t params_copy[I2C_MAX_HOST_PACKET_SIZE] __aligned(4); static int host_i2c_resp_port; static int tx_pending; @@ -244,7 +242,7 @@ static void i2c_send_response_packet(struct host_packet *pkt) /* * Set the transmitter to be in 'not full' state to keep sending - * '0xec' in the event loop. Because of this, the master i2c + * '0xec' in the event loop. Because of this, the controller i2c * doesn't need to snoop the response stream to abort transaction. */ STM32_I2C_CR1(host_i2c_resp_port) |= STM32_I2C_CR1_TXIE; @@ -288,7 +286,7 @@ static void i2c_process_command(void) host_packet_receive(&i2c_packet); } -#ifdef TCPCI_I2C_SLAVE +#ifdef TCPCI_I2C_PERIPHERAL static void i2c_send_tcpc_response(int len) { /* host_buffer data range, beyond this length, will return 0xec */ @@ -310,7 +308,7 @@ static void i2c_event_handler(int port) { int i2c_isr; static int rx_pending, buf_idx; -#ifdef TCPCI_I2C_SLAVE +#ifdef TCPCI_I2C_PERIPHERAL int addr; #endif @@ -318,7 +316,7 @@ static void i2c_event_handler(int port) /* * Check for error conditions. Note, arbitration loss and bus error - * are the only two errors we can get as a slave allowing clock + * are the only two errors we can get as a peripheral allowing clock * stretching and in non-SMBus mode. */ if (i2c_isr & (STM32_I2C_ISR_ARLO | STM32_I2C_ISR_BERR)) { @@ -330,20 +328,20 @@ static void i2c_event_handler(int port) /* Clear error status bits */ STM32_I2C_ICR(port) |= STM32_I2C_ICR_BERRCF | - STM32_I2C_ICR_ARLOCF; + STM32_I2C_ICR_ARLOCF; } - /* Transfer matched our slave address */ + /* Transfer matched our peripheral address */ if (i2c_isr & STM32_I2C_ISR_ADDR) { if (i2c_isr & STM32_I2C_ISR_DIR) { - /* Transmitter slave */ + /* Transmitter peripheral */ /* Clear transmit buffer */ STM32_I2C_ISR(port) |= STM32_I2C_ISR_TXE; /* Enable txis interrupt to start response */ STM32_I2C_CR1(port) |= STM32_I2C_CR1_TXIE; } else { - /* Receiver slave */ + /* Receiver peripheral */ buf_idx = 0; rx_pending = 1; } @@ -351,7 +349,7 @@ static void i2c_event_handler(int port) /* Clear ADDR bit by writing to ADDRCF bit */ STM32_I2C_ICR(port) |= STM32_I2C_ICR_ADDRCF; /* Inhibit sleep mode when addressed until STOPF flag is set */ - disable_sleep(SLEEP_MASK_I2C_SLAVE); + disable_sleep(SLEEP_MASK_I2C_PERIPHERAL); } /* Receiver full event */ @@ -360,7 +358,7 @@ static void i2c_event_handler(int port) /* Stop condition on bus */ if (i2c_isr & STM32_I2C_ISR_STOP) { -#ifdef TCPCI_I2C_SLAVE +#ifdef TCPCI_I2C_PERIPHERAL /* * if tcpc is being addressed, and we received a stop * while rx is pending, then this is a write only to @@ -380,10 +378,10 @@ static void i2c_event_handler(int port) STM32_I2C_ICR(port) |= STM32_I2C_ICR_STOPCF; /* No longer inhibit deep sleep after stop condition */ - enable_sleep(SLEEP_MASK_I2C_SLAVE); + enable_sleep(SLEEP_MASK_I2C_PERIPHERAL); } - /* Master requested STOP or RESTART */ + /* Controller requested STOP or RESTART */ if (i2c_isr & STM32_I2C_ISR_NACK) { /* Make sure TXIS interrupt is disabled */ STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; @@ -420,7 +418,7 @@ static void i2c_event_handler(int port) */ STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; -#ifdef TCPCI_I2C_SLAVE +#ifdef TCPCI_I2C_PERIPHERAL addr = STM32_I2C_ISR_ADDCODE( STM32_I2C_ISR(port)); if (ADDR_IS_TCPC(addr)) @@ -439,18 +437,20 @@ static void i2c_event_handler(int port) } } } -void i2c2_event_interrupt(void) { i2c_event_handler(I2C_PORT_EC); } -DECLARE_IRQ(IRQ_SLAVE, i2c2_event_interrupt, 2); +static void i2c2_event_interrupt(void) +{ + i2c_event_handler(I2C_PORT_EC); +} +DECLARE_IRQ(IRQ_PERIPHERAL, i2c2_event_interrupt, 2); #endif /*****************************************************************************/ /* Interface */ -int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, - const uint8_t *out, int out_bytes, - uint8_t *in, int in_bytes, int flags) +int chip_i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_bytes, uint8_t *in, int in_bytes, int flags) { - int addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; + int addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; int rv = EC_SUCCESS; int i; int xfer_start = flags & I2C_XFER_START; @@ -458,7 +458,7 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, #if defined(CONFIG_I2C_SCL_GATE_ADDR) && defined(CONFIG_I2C_SCL_GATE_PORT) if (port == CONFIG_I2C_SCL_GATE_PORT && - slave_addr_flags == CONFIG_I2C_SCL_GATE_ADDR_FLAGS) + addr_flags == CONFIG_I2C_SCL_GATE_ADDR_FLAGS) gpio_set_level(CONFIG_I2C_SCL_GATE_GPIO, 1); #endif @@ -495,13 +495,13 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, * if we are not stopping, set RELOAD bit so that we can load * NBYTES again. if we are starting, then set START bit. */ - STM32_I2C_CR2(port) = ((out_bytes & 0xFF) << 16) - | addr_8bit - | ((in_bytes == 0 && xfer_stop) ? - STM32_I2C_CR2_AUTOEND : 0) - | ((in_bytes == 0 && !xfer_stop) ? - STM32_I2C_CR2_RELOAD : 0) - | (xfer_start ? STM32_I2C_CR2_START : 0); + STM32_I2C_CR2(port) = + ((out_bytes & 0xFF) << 16) | addr_8bit | + ((in_bytes == 0 && xfer_stop) ? STM32_I2C_CR2_AUTOEND : + 0) | + ((in_bytes == 0 && !xfer_stop) ? STM32_I2C_CR2_RELOAD : + 0) | + (xfer_start ? STM32_I2C_CR2_START : 0); for (i = 0; i < out_bytes; i++) { rv = wait_isr(port, STM32_I2C_ISR_TXIS); @@ -524,11 +524,11 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, * NBYTES again. if we were just transmitting, we need to * set START bit to send (re)start and begin read transaction. */ - STM32_I2C_CR2(port) = ((in_bytes & 0xFF) << 16) - | STM32_I2C_CR2_RD_WRN | addr_8bit - | (xfer_stop ? STM32_I2C_CR2_AUTOEND : 0) - | (!xfer_stop ? STM32_I2C_CR2_RELOAD : 0) - | (out_bytes || xfer_start ? STM32_I2C_CR2_START : 0); + STM32_I2C_CR2(port) = + ((in_bytes & 0xFF) << 16) | STM32_I2C_CR2_RD_WRN | + addr_8bit | (xfer_stop ? STM32_I2C_CR2_AUTOEND : 0) | + (!xfer_stop ? STM32_I2C_CR2_RELOAD : 0) | + (out_bytes || xfer_start ? STM32_I2C_CR2_START : 0); for (i = 0; i < in_bytes; i++) { /* Wait for receive buffer not empty */ @@ -569,7 +569,7 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, /* * Allow bus to idle for at least one 100KHz clock = 10 us. - * This allows slaves on the bus to detect bus-idle before + * This allows peripherals on the bus to detect bus-idle before * the next start condition. */ udelay(10); @@ -582,7 +582,7 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, #ifdef CONFIG_I2C_SCL_GATE_ADDR if (port == CONFIG_I2C_SCL_GATE_PORT && - slave_addr_flags == CONFIG_I2C_SCL_GATE_ADDR_FLAGS) + addr_flags == CONFIG_I2C_SCL_GATE_ADDR_FLAGS) gpio_set_level(CONFIG_I2C_SCL_GATE_GPIO, 0); #endif @@ -614,7 +614,7 @@ int i2c_raw_get_sda(int port) int i2c_get_line_levels(int port) { return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) | - (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); + (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); } void i2c_init(void) @@ -625,10 +625,11 @@ void i2c_init(void) for (i = 0; i < i2c_ports_used; i++, p++) i2c_init_port(p); -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS - STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE - | STM32_I2C_CR1_ADDRIE | STM32_I2C_CR1_STOPIE - | STM32_I2C_CR1_NACKIE; +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS + STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE | + STM32_I2C_CR1_ADDRIE | + STM32_I2C_CR1_STOPIE | + STM32_I2C_CR1_NACKIE; #if defined(CONFIG_LOW_POWER_IDLE) && (I2C_PORT_EC == STM32_I2C1_PORT) /* * If using low power idle and EC port is I2C1, then set I2C1 to wake @@ -637,17 +638,17 @@ void i2c_init(void) */ STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_WUPEN; #endif - STM32_I2C_OAR1(I2C_PORT_EC) = 0x8000 - | (I2C_GET_ADDR(CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS) << 1); -#ifdef TCPCI_I2C_SLAVE + STM32_I2C_OAR1(I2C_PORT_EC) = + 0x8000 | (I2C_STRIP_FLAGS(CONFIG_HOSTCMD_I2C_ADDR_FLAGS) << 1); +#ifdef TCPCI_I2C_PERIPHERAL /* * Configure TCPC address with OA2[1] masked so that we respond * to CONFIG_TCPC_I2C_BASE_ADDR and CONFIG_TCPC_I2C_BASE_ADDR + 2. */ - STM32_I2C_OAR2(I2C_PORT_EC) = 0x8100 - | (I2C_GET_ADDR(CONFIG_TCPC_I2C_BASE_ADDR_FLAGS) << 1); + STM32_I2C_OAR2(I2C_PORT_EC) = + 0x8100 | + (I2C_STRIP_FLAGS(CONFIG_TCPC_I2C_BASE_ADDR_FLAGS) << 1); #endif - task_enable_irq(IRQ_SLAVE); + task_enable_irq(IRQ_PERIPHERAL); #endif } - diff --git a/chip/stm32/i2c-stm32f3.c b/chip/stm32/i2c-stm32f3.c deleted file mode 120000 index ce8523ea90..0000000000 --- a/chip/stm32/i2c-stm32f3.c +++ /dev/null @@ -1 +0,0 @@ -i2c-stm32f0.c \ No newline at end of file diff --git a/chip/stm32/i2c-stm32f3.c b/chip/stm32/i2c-stm32f3.c new file mode 100644 index 0000000000..acd4d3aca6 --- /dev/null +++ b/chip/stm32/i2c-stm32f3.c @@ -0,0 +1,654 @@ +/* Copyright 2013 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "builtin/assert.h" +#include "chipset.h" +#include "clock.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "hwtimer.h" +#include "i2c.h" +#include "i2c_private.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "timer.h" +#include "usb_pd_tcpc.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_I2C, outstr) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) + +/* Transmit timeout in microseconds */ +#define I2C_TX_TIMEOUT_CONTROLLER (10 * MSEC) + +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS +#if (I2C_PORT_EC == STM32_I2C1_PORT) +#define IRQ_PERIPHERAL STM32_IRQ_I2C1 +#else +#define IRQ_PERIPHERAL STM32_IRQ_I2C2 +#endif +#endif + +/* I2C port state data */ +struct i2c_port_data { + uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ + enum i2c_freq freq; /* Port clock speed */ +}; +static struct i2c_port_data pdata[I2C_PORT_COUNT]; + +void i2c_set_timeout(int port, uint32_t timeout) +{ + pdata[port].timeout_us = timeout ? timeout : I2C_TX_TIMEOUT_CONTROLLER; +} + +/* timingr register values for supported input clks / i2c clk rates */ +static const uint32_t busyloop_us[I2C_FREQ_COUNT] = { + [I2C_FREQ_1000KHZ] = 16, /* Enough for 2 bytes */ + [I2C_FREQ_400KHZ] = 40, /* Enough for 2 bytes */ + [I2C_FREQ_100KHZ] = 0, /* No busy looping at 100kHz (bus is slow) */ +}; + +/** + * Wait for ISR register to contain the specified mask. + * + * Returns EC_SUCCESS, EC_ERROR_TIMEOUT if timed out waiting, or + * EC_ERROR_UNKNOWN if an error bit appeared in the status register. + */ +static int wait_isr(int port, int mask) +{ + uint32_t start = __hw_clock_source_read(); + uint32_t delta = 0; + + do { + int isr = STM32_I2C_ISR(port); + + /* Check for errors */ + if (isr & (STM32_I2C_ISR_ARLO | STM32_I2C_ISR_BERR | + STM32_I2C_ISR_NACK)) + return EC_ERROR_UNKNOWN; + + /* Check for desired mask */ + if ((isr & mask) == mask) + return EC_SUCCESS; + + delta = __hw_clock_source_read() - start; + + /** + * Depending on the bus speed, busy loop for a while before + * sleeping and letting other things run. + */ + if (delta >= busyloop_us[pdata[port].freq]) + usleep(100); + } while (delta < pdata[port].timeout_us); + + return EC_ERROR_TIMEOUT; +} + +/* Supported i2c input clocks */ +enum stm32_i2c_clk_src { + I2C_CLK_SRC_48MHZ = 0, + I2C_CLK_SRC_8MHZ = 1, + I2C_CLK_SRC_COUNT, +}; + +/* timingr register values for supported input clks / i2c clk rates */ +static const uint32_t timingr_regs[I2C_CLK_SRC_COUNT][I2C_FREQ_COUNT] = { + [I2C_CLK_SRC_48MHZ] = { + [I2C_FREQ_1000KHZ] = 0x50100103, + [I2C_FREQ_400KHZ] = 0x50330609, + [I2C_FREQ_100KHZ] = 0xB0421214, + }, + [I2C_CLK_SRC_8MHZ] = { + [I2C_FREQ_1000KHZ] = 0x00100306, + [I2C_FREQ_400KHZ] = 0x00310309, + [I2C_FREQ_100KHZ] = 0x10420f13, + }, +}; + +int chip_i2c_set_freq(int port, enum i2c_freq freq) +{ + enum stm32_i2c_clk_src src = I2C_CLK_SRC_48MHZ; + +#if defined(CONFIG_HOSTCMD_I2C_ADDR_FLAGS) && \ + defined(CONFIG_LOW_POWER_IDLE) && (I2C_PORT_EC == STM32_I2C1_PORT) + if (port == STM32_I2C1_PORT) { + /* + * Use HSI (8MHz) for i2c clock. This allows smooth wakeup + * from STOP mode since HSI is only clock running immediately + * upon exit from STOP mode. + */ + src = I2C_CLK_SRC_8MHZ; + } +#endif + + /* Disable port */ + STM32_I2C_CR1(port) = 0; + STM32_I2C_CR2(port) = 0; + /* Set clock frequency */ + STM32_I2C_TIMINGR(port) = timingr_regs[src][freq]; + /* Enable port */ + STM32_I2C_CR1(port) = STM32_I2C_CR1_PE; + + pdata[port].freq = freq; + + return EC_SUCCESS; +} + +enum i2c_freq chip_i2c_get_freq(int port) +{ + return pdata[port].freq; +} + +/** + * Initialize on the specified I2C port. + * + * @param p the I2c port + */ +static int i2c_init_port(const struct i2c_port_t *p) +{ + int port = p->port; + int ret = EC_SUCCESS; + enum i2c_freq freq; + + /* Enable clocks to I2C modules if necessary */ + if (!(STM32_RCC_APB1ENR & (1 << (21 + port)))) + STM32_RCC_APB1ENR |= 1 << (21 + port); + + if (port == STM32_I2C1_PORT) { +#if defined(CONFIG_HOSTCMD_I2C_ADDR_FLAGS) && \ + defined(CONFIG_LOW_POWER_IDLE) && (I2C_PORT_EC == STM32_I2C1_PORT) + /* + * Use HSI (8MHz) for i2c clock. This allows smooth wakeup + * from STOP mode since HSI is only clock running immediately + * upon exit from STOP mode. + */ + STM32_RCC_CFGR3 &= ~0x10; +#else + /* Use SYSCLK for i2c clock. */ + STM32_RCC_CFGR3 |= 0x10; +#endif + } + + /* Configure GPIOs */ + gpio_config_module(MODULE_I2C, 1); + + /* Set clock frequency */ + switch (p->kbps) { + case 1000: + freq = I2C_FREQ_1000KHZ; + break; + case 400: + freq = I2C_FREQ_400KHZ; + break; + case 100: + freq = I2C_FREQ_100KHZ; + break; + default: /* unknown speed, defaults to 100kBps */ + CPRINTS("I2C bad speed %d kBps", p->kbps); + freq = I2C_FREQ_100KHZ; + ret = EC_ERROR_INVAL; + } + + /* Set up initial bus frequencies */ + chip_i2c_set_freq(p->port, freq); + + /* Set up default timeout */ + i2c_set_timeout(port, 0); + + return ret; +} + +/*****************************************************************************/ +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS +/* Host command peripheral */ +/* + * Buffer for received host command packets (including prefix byte on request, + * and result/size on response). After any protocol-specific headers, the + * buffers must be 32-bit aligned. + */ +static uint8_t host_buffer_padded[I2C_MAX_HOST_PACKET_SIZE + 4 + + CONFIG_I2C_EXTRA_PACKET_SIZE] __aligned(4); +static uint8_t *const host_buffer = host_buffer_padded + 2; +static uint8_t params_copy[I2C_MAX_HOST_PACKET_SIZE] __aligned(4); +static int host_i2c_resp_port; +static int tx_pending; +static int tx_index, tx_end; +static struct host_packet i2c_packet; + +static void i2c_send_response_packet(struct host_packet *pkt) +{ + int size = pkt->response_size; + uint8_t *out = host_buffer; + + /* Ignore host command in-progress */ + if (pkt->driver_result == EC_RES_IN_PROGRESS) + return; + + /* Write result and size to first two bytes. */ + *out++ = pkt->driver_result; + *out++ = size; + + /* host_buffer data range */ + tx_index = 0; + tx_end = size + 2; + + /* + * Set the transmitter to be in 'not full' state to keep sending + * '0xec' in the event loop. Because of this, the controller i2c + * doesn't need to snoop the response stream to abort transaction. + */ + STM32_I2C_CR1(host_i2c_resp_port) |= STM32_I2C_CR1_TXIE; +} + +/* Process the command in the i2c host buffer */ +static void i2c_process_command(void) +{ + char *buff = host_buffer; + + /* + * TODO(crosbug.com/p/29241): Combine this functionality with the + * i2c_process_command function in chip/stm32/i2c-stm32f.c to make one + * host command i2c process function which handles all protocol + * versions. + */ + i2c_packet.send_response = i2c_send_response_packet; + + i2c_packet.request = (const void *)(&buff[1]); + i2c_packet.request_temp = params_copy; + i2c_packet.request_max = sizeof(params_copy); + /* Don't know the request size so pass in the entire buffer */ + i2c_packet.request_size = I2C_MAX_HOST_PACKET_SIZE; + + /* + * Stuff response at buff[2] to leave the first two bytes of + * buffer available for the result and size to send over i2c. Note + * that this 2-byte offset and the 2-byte offset from host_buffer + * add up to make the response buffer 32-bit aligned. + */ + i2c_packet.response = (void *)(&buff[2]); + i2c_packet.response_max = I2C_MAX_HOST_PACKET_SIZE; + i2c_packet.response_size = 0; + + if (*buff >= EC_COMMAND_PROTOCOL_3) { + i2c_packet.driver_result = EC_RES_SUCCESS; + } else { + /* Only host command protocol 3 is supported. */ + i2c_packet.driver_result = EC_RES_INVALID_HEADER; + } + host_packet_receive(&i2c_packet); +} + +#ifdef TCPCI_I2C_PERIPHERAL +static void i2c_send_tcpc_response(int len) +{ + /* host_buffer data range, beyond this length, will return 0xec */ + tx_index = 0; + tx_end = len; + + /* enable transmit interrupt and use irq to send data back */ + STM32_I2C_CR1(host_i2c_resp_port) |= STM32_I2C_CR1_TXIE; +} + +static void i2c_process_tcpc_command(int read, int addr, int len) +{ + tcpc_i2c_process(read, TCPC_ADDR_TO_PORT(addr), len, &host_buffer[0], + i2c_send_tcpc_response); +} +#endif + +static void i2c_event_handler(int port) +{ + int i2c_isr; + static int rx_pending, buf_idx; +#ifdef TCPCI_I2C_PERIPHERAL + int addr; +#endif + + i2c_isr = STM32_I2C_ISR(port); + + /* + * Check for error conditions. Note, arbitration loss and bus error + * are the only two errors we can get as a peripheral allowing clock + * stretching and in non-SMBus mode. + */ + if (i2c_isr & (STM32_I2C_ISR_ARLO | STM32_I2C_ISR_BERR)) { + rx_pending = 0; + tx_pending = 0; + + /* Make sure TXIS interrupt is disabled */ + STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; + + /* Clear error status bits */ + STM32_I2C_ICR(port) |= STM32_I2C_ICR_BERRCF | + STM32_I2C_ICR_ARLOCF; + } + + /* Transfer matched our peripheral address */ + if (i2c_isr & STM32_I2C_ISR_ADDR) { + if (i2c_isr & STM32_I2C_ISR_DIR) { + /* Transmitter peripheral */ + /* Clear transmit buffer */ + STM32_I2C_ISR(port) |= STM32_I2C_ISR_TXE; + + /* Enable txis interrupt to start response */ + STM32_I2C_CR1(port) |= STM32_I2C_CR1_TXIE; + } else { + /* Receiver peripheral */ + buf_idx = 0; + rx_pending = 1; + } + + /* Clear ADDR bit by writing to ADDRCF bit */ + STM32_I2C_ICR(port) |= STM32_I2C_ICR_ADDRCF; + /* Inhibit sleep mode when addressed until STOPF flag is set */ + disable_sleep(SLEEP_MASK_I2C_PERIPHERAL); + } + + /* Receiver full event */ + if (i2c_isr & STM32_I2C_ISR_RXNE) + host_buffer[buf_idx++] = STM32_I2C_RXDR(port); + + /* Stop condition on bus */ + if (i2c_isr & STM32_I2C_ISR_STOP) { +#ifdef TCPCI_I2C_PERIPHERAL + /* + * if tcpc is being addressed, and we received a stop + * while rx is pending, then this is a write only to + * the tcpc. + */ + addr = STM32_I2C_ISR_ADDCODE(STM32_I2C_ISR(port)); + if (rx_pending && ADDR_IS_TCPC(addr)) + i2c_process_tcpc_command(0, addr, buf_idx); +#endif + rx_pending = 0; + tx_pending = 0; + + /* Make sure TXIS interrupt is disabled */ + STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; + + /* Clear STOPF bit by writing to STOPCF bit */ + STM32_I2C_ICR(port) |= STM32_I2C_ICR_STOPCF; + + /* No longer inhibit deep sleep after stop condition */ + enable_sleep(SLEEP_MASK_I2C_PERIPHERAL); + } + + /* Controller requested STOP or RESTART */ + if (i2c_isr & STM32_I2C_ISR_NACK) { + /* Make sure TXIS interrupt is disabled */ + STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; + /* Clear NACK */ + STM32_I2C_ICR(port) |= STM32_I2C_ICR_NACKCF; + /* Resend last byte on RESTART */ + if (port == I2C_PORT_EC && tx_index) + tx_index--; + } + + /* Transmitter empty event */ + if (i2c_isr & STM32_I2C_ISR_TXIS) { + if (port == I2C_PORT_EC) { /* host is waiting for PD response */ + if (tx_pending) { + if (tx_index < tx_end) { + STM32_I2C_TXDR(port) = + host_buffer[tx_index++]; + } else { + STM32_I2C_TXDR(port) = 0xec; + /* + * Set tx_index = 0 to prevent NACK + * handler resending last buffer byte. + */ + tx_index = 0; + tx_end = 0; + /* No pending data */ + tx_pending = 0; + } + } else if (rx_pending) { + host_i2c_resp_port = port; + /* + * Disable TXIS interrupt, transmission will + * be prepared by host command task. + */ + STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; + +#ifdef TCPCI_I2C_PERIPHERAL + addr = STM32_I2C_ISR_ADDCODE( + STM32_I2C_ISR(port)); + if (ADDR_IS_TCPC(addr)) + i2c_process_tcpc_command(1, addr, + buf_idx); + else +#endif + i2c_process_command(); + + /* Reset host buffer after end of transfer */ + rx_pending = 0; + tx_pending = 1; + } else { + STM32_I2C_TXDR(port) = 0xec; + } + } + } +} +static void i2c2_event_interrupt(void) +{ + i2c_event_handler(I2C_PORT_EC); +} +DECLARE_IRQ(IRQ_PERIPHERAL, i2c2_event_interrupt, 2); +#endif + +/*****************************************************************************/ +/* Interface */ + +int chip_i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_bytes, uint8_t *in, int in_bytes, int flags) +{ + int addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; + int rv = EC_SUCCESS; + int i; + int xfer_start = flags & I2C_XFER_START; + int xfer_stop = flags & I2C_XFER_STOP; + +#if defined(CONFIG_I2C_SCL_GATE_ADDR) && defined(CONFIG_I2C_SCL_GATE_PORT) + if (port == CONFIG_I2C_SCL_GATE_PORT && + addr_flags == CONFIG_I2C_SCL_GATE_ADDR_FLAGS) + gpio_set_level(CONFIG_I2C_SCL_GATE_GPIO, 1); +#endif + + ASSERT(out || !out_bytes); + ASSERT(in || !in_bytes); + + /* Clear status */ + if (xfer_start) { + uint32_t cr2 = STM32_I2C_CR2(port); + + STM32_I2C_ICR(port) = STM32_I2C_ICR_ALL; + STM32_I2C_CR2(port) = 0; + if (cr2 & STM32_I2C_CR2_RELOAD) { + /* + * If I2C_XFER_START flag is on and we've set RELOAD=1 + * in previous chip_i2c_xfer() call. Then we are + * probably in the middle of an i2c transaction. + * + * In this case, we need to clear the RELOAD bit and + * wait for Transfer Complete (TC) flag, to make sure + * the chip is not expecting another NBYTES data, And + * send repeated-start correctly. + */ + rv = wait_isr(port, STM32_I2C_ISR_TC); + if (rv) + goto xfer_exit; + } + } + + if (out_bytes || !in_bytes) { + /* + * Configure the write transfer: if we are stopping then set + * AUTOEND bit to automatically set STOP bit after NBYTES. + * if we are not stopping, set RELOAD bit so that we can load + * NBYTES again. if we are starting, then set START bit. + */ + STM32_I2C_CR2(port) = + ((out_bytes & 0xFF) << 16) | addr_8bit | + ((in_bytes == 0 && xfer_stop) ? STM32_I2C_CR2_AUTOEND : + 0) | + ((in_bytes == 0 && !xfer_stop) ? STM32_I2C_CR2_RELOAD : + 0) | + (xfer_start ? STM32_I2C_CR2_START : 0); + + for (i = 0; i < out_bytes; i++) { + rv = wait_isr(port, STM32_I2C_ISR_TXIS); + if (rv) + goto xfer_exit; + /* Write next data byte */ + STM32_I2C_TXDR(port) = out[i]; + } + } + if (in_bytes) { + if (out_bytes) { /* wait for completion of the write */ + rv = wait_isr(port, STM32_I2C_ISR_TC); + if (rv) + goto xfer_exit; + } + /* + * Configure the read transfer: if we are stopping then set + * AUTOEND bit to automatically set STOP bit after NBYTES. + * if we are not stopping, set RELOAD bit so that we can load + * NBYTES again. if we were just transmitting, we need to + * set START bit to send (re)start and begin read transaction. + */ + STM32_I2C_CR2(port) = + ((in_bytes & 0xFF) << 16) | STM32_I2C_CR2_RD_WRN | + addr_8bit | (xfer_stop ? STM32_I2C_CR2_AUTOEND : 0) | + (!xfer_stop ? STM32_I2C_CR2_RELOAD : 0) | + (out_bytes || xfer_start ? STM32_I2C_CR2_START : 0); + + for (i = 0; i < in_bytes; i++) { + /* Wait for receive buffer not empty */ + rv = wait_isr(port, STM32_I2C_ISR_RXNE); + if (rv) + goto xfer_exit; + + in[i] = STM32_I2C_RXDR(port); + } + } + + /* + * If we are stopping, then we already set AUTOEND and we should + * wait for the stop bit to be transmitted. Otherwise, we set + * the RELOAD bit and we should wait for transfer complete + * reload (TCR). + */ + rv = wait_isr(port, xfer_stop ? STM32_I2C_ISR_STOP : STM32_I2C_ISR_TCR); + if (rv) + goto xfer_exit; + +xfer_exit: + /* clear status */ + if (xfer_stop) + STM32_I2C_ICR(port) = STM32_I2C_ICR_ALL; + + /* On error, queue a stop condition */ + if (rv) { + /* queue a STOP condition */ + STM32_I2C_CR2(port) |= STM32_I2C_CR2_STOP; + /* wait for it to take effect */ + /* Wait up to 100 us for bus idle */ + for (i = 0; i < 10; i++) { + if (!(STM32_I2C_ISR(port) & STM32_I2C_ISR_BUSY)) + break; + udelay(10); + } + + /* + * Allow bus to idle for at least one 100KHz clock = 10 us. + * This allows peripherals on the bus to detect bus-idle before + * the next start condition. + */ + udelay(10); + /* re-initialize the controller */ + STM32_I2C_CR2(port) = 0; + STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_PE; + udelay(10); + STM32_I2C_CR1(port) |= STM32_I2C_CR1_PE; + } + +#ifdef CONFIG_I2C_SCL_GATE_ADDR + if (port == CONFIG_I2C_SCL_GATE_PORT && + addr_flags == CONFIG_I2C_SCL_GATE_ADDR_FLAGS) + gpio_set_level(CONFIG_I2C_SCL_GATE_GPIO, 0); +#endif + + return rv; +} + +int i2c_raw_get_scl(int port) +{ + enum gpio_signal g; + + if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS) + return gpio_get_level(g); + + /* If no SCL pin defined for this port, then return 1 to appear idle. */ + return 1; +} + +int i2c_raw_get_sda(int port) +{ + enum gpio_signal g; + + if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS) + return gpio_get_level(g); + + /* If no SCL pin defined for this port, then return 1 to appear idle. */ + return 1; +} + +int i2c_get_line_levels(int port) +{ + return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) | + (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); +} + +void i2c_init(void) +{ + const struct i2c_port_t *p = i2c_ports; + int i; + + for (i = 0; i < i2c_ports_used; i++, p++) + i2c_init_port(p); + +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS + STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE | + STM32_I2C_CR1_ADDRIE | + STM32_I2C_CR1_STOPIE | + STM32_I2C_CR1_NACKIE; +#if defined(CONFIG_LOW_POWER_IDLE) && (I2C_PORT_EC == STM32_I2C1_PORT) + /* + * If using low power idle and EC port is I2C1, then set I2C1 to wake + * from STOP mode on address match. Note, this only works on I2C1 and + * only if the clock to I2C1 is HSI 8MHz. + */ + STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_WUPEN; +#endif + STM32_I2C_OAR1(I2C_PORT_EC) = + 0x8000 | (I2C_STRIP_FLAGS(CONFIG_HOSTCMD_I2C_ADDR_FLAGS) << 1); +#ifdef TCPCI_I2C_PERIPHERAL + /* + * Configure TCPC address with OA2[1] masked so that we respond + * to CONFIG_TCPC_I2C_BASE_ADDR and CONFIG_TCPC_I2C_BASE_ADDR + 2. + */ + STM32_I2C_OAR2(I2C_PORT_EC) = + 0x8100 | + (I2C_STRIP_FLAGS(CONFIG_TCPC_I2C_BASE_ADDR_FLAGS) << 1); +#endif + task_enable_irq(IRQ_PERIPHERAL); +#endif +} diff --git a/chip/stm32/i2c-stm32f4.c b/chip/stm32/i2c-stm32f4.c index 515aed20eb..9f4d799912 100644 --- a/chip/stm32/i2c-stm32f4.c +++ b/chip/stm32/i2c-stm32f4.c @@ -1,13 +1,16 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. + +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "chipset.h" #include "clock.h" #include "common.h" #include "console.h" #include "dma.h" +#include "gpio.h" #include "hooks.h" #include "i2c.h" #include "registers.h" @@ -18,20 +21,20 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) #define I2C_ERROR_FAILED_START EC_ERROR_INTERNAL_FIRST /* Transmit timeout in microseconds */ -#define I2C_TX_TIMEOUT_MASTER (10 * MSEC) +#define I2C_TX_TIMEOUT_CONTROLLER (10 * MSEC) -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS #if (I2C_PORT_EC == STM32_I2C1_PORT) -#define IRQ_SLAVE_EV STM32_IRQ_I2C1_EV -#define IRQ_SLAVE_ER STM32_IRQ_I2C1_ER +#define IRQ_PERIPHERAL_EV STM32_IRQ_I2C1_EV +#define IRQ_PERIPHERAL_ER STM32_IRQ_I2C1_ER #else -#define IRQ_SLAVE_EV STM32_IRQ_I2C2_EV -#define IRQ_SLAVE_ER STM32_IRQ_I2C2_ER +#define IRQ_PERIPHERAL_EV STM32_IRQ_I2C2_EV +#define IRQ_PERIPHERAL_ER STM32_IRQ_I2C2_ER #endif #endif @@ -41,36 +44,36 @@ * two sets of functions to handle this for stm32f4. In stm32f446, we * only have one FMP block so we'll hardcode its port number. */ -#define STM32F4_FMPI2C_PORT 3 +#define STM32F4_FMPI2C_PORT 3 static const __unused struct dma_option dma_tx_option[I2C_PORT_COUNT] = { - {STM32_DMAC_I2C1_TX, (void *)&STM32_I2C_DR(STM32_I2C1_PORT), - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CHANNEL(STM32_I2C1_TX_REQ_CH)}, - {STM32_DMAC_I2C2_TX, (void *)&STM32_I2C_DR(STM32_I2C2_PORT), - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CHANNEL(STM32_I2C2_TX_REQ_CH)}, - {STM32_DMAC_I2C3_TX, (void *)&STM32_I2C_DR(STM32_I2C3_PORT), - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CHANNEL(STM32_I2C3_TX_REQ_CH)}, - {STM32_DMAC_FMPI2C4_TX, (void *)&STM32_FMPI2C_TXDR(STM32_FMPI2C4_PORT), - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CHANNEL(STM32_FMPI2C4_TX_REQ_CH)}, + { STM32_DMAC_I2C1_TX, (void *)&STM32_I2C_DR(STM32_I2C1_PORT), + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + STM32_DMA_CCR_CHANNEL(STM32_I2C1_TX_REQ_CH) }, + { STM32_DMAC_I2C2_TX, (void *)&STM32_I2C_DR(STM32_I2C2_PORT), + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + STM32_DMA_CCR_CHANNEL(STM32_I2C2_TX_REQ_CH) }, + { STM32_DMAC_I2C3_TX, (void *)&STM32_I2C_DR(STM32_I2C3_PORT), + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + STM32_DMA_CCR_CHANNEL(STM32_I2C3_TX_REQ_CH) }, + { STM32_DMAC_FMPI2C4_TX, (void *)&STM32_FMPI2C_TXDR(STM32_FMPI2C4_PORT), + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + STM32_DMA_CCR_CHANNEL(STM32_FMPI2C4_TX_REQ_CH) }, }; static const struct dma_option dma_rx_option[I2C_PORT_COUNT] = { - {STM32_DMAC_I2C1_RX, (void *)&STM32_I2C_DR(STM32_I2C1_PORT), - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CHANNEL(STM32_I2C1_RX_REQ_CH)}, - {STM32_DMAC_I2C2_RX, (void *)&STM32_I2C_DR(STM32_I2C2_PORT), - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CHANNEL(STM32_I2C2_RX_REQ_CH)}, - {STM32_DMAC_I2C3_RX, (void *)&STM32_I2C_DR(STM32_I2C3_PORT), - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CHANNEL(STM32_I2C3_RX_REQ_CH)}, - {STM32_DMAC_FMPI2C4_RX, (void *)&STM32_FMPI2C_RXDR(STM32_FMPI2C4_PORT), - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CHANNEL(STM32_FMPI2C4_RX_REQ_CH)}, + { STM32_DMAC_I2C1_RX, (void *)&STM32_I2C_DR(STM32_I2C1_PORT), + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + STM32_DMA_CCR_CHANNEL(STM32_I2C1_RX_REQ_CH) }, + { STM32_DMAC_I2C2_RX, (void *)&STM32_I2C_DR(STM32_I2C2_PORT), + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + STM32_DMA_CCR_CHANNEL(STM32_I2C2_RX_REQ_CH) }, + { STM32_DMAC_I2C3_RX, (void *)&STM32_I2C_DR(STM32_I2C3_PORT), + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + STM32_DMA_CCR_CHANNEL(STM32_I2C3_RX_REQ_CH) }, + { STM32_DMAC_FMPI2C4_RX, (void *)&STM32_FMPI2C_RXDR(STM32_FMPI2C4_PORT), + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + STM32_DMA_CCR_CHANNEL(STM32_FMPI2C4_RX_REQ_CH) }, }; /* Callback for ISR to wake task on DMA complete. */ @@ -79,7 +82,7 @@ static inline void _i2c_dma_wake_callback(void *cb_data, int port) task_id_t id = (task_id_t)(int)cb_data; if (id != TASK_ID_INVALID) - task_set_event(id, TASK_EVENT_I2C_COMPLETION(port), 0); + task_set_event(id, TASK_EVENT_I2C_COMPLETION(port)); } /* Each callback is hardcoded to an I2C channel. */ @@ -133,7 +136,7 @@ void i2c_dma_enable_tc_interrupt(enum dma_channel stream, int port) #define UNSET 0 static int wait_sr1_poll(int port, int mask, int val, int poll) { - uint64_t timeout = get_time().val + I2C_TX_TIMEOUT_MASTER; + uint64_t timeout = get_time().val + I2C_TX_TIMEOUT_CONTROLLER; while (get_time().val < timeout) { int sr1 = STM32_I2C_SR1(port); @@ -162,16 +165,15 @@ static int wait_sr1(int port, int mask) return wait_sr1_poll(port, mask, SET, 100); } - /** - * Send a start condition and slave address on the specified port. + * Send a start condition and peripheral address on the specified port. * * @param port I2C port - * @param slave_addr Slave address, with LSB set for receive-mode + * @param addr_8bit I2C address, with LSB set for receive-mode * * @return Non-zero if error. */ -static int send_start(const int port, const uint16_t slave_addr_8bit) +static int send_start(const int port, const uint16_t addr_8bit) { int rv; @@ -181,8 +183,8 @@ static int send_start(const int port, const uint16_t slave_addr_8bit) if (rv) return I2C_ERROR_FAILED_START; - /* Write slave address */ - STM32_I2C_DR(port) = slave_addr_8bit; + /* Write peripheral address */ + STM32_I2C_DR(port) = addr_8bit; rv = wait_sr1_poll(port, STM32_I2C_SR1_ADDR, SET, 1); if (rv) return rv; @@ -224,14 +226,14 @@ static const struct i2c_port_t *find_port(int port) */ static int wait_fmpi2c_isr_poll(int port, int mask, int val, int poll) { - uint64_t timeout = get_time().val + I2C_TX_TIMEOUT_MASTER; + uint64_t timeout = get_time().val + I2C_TX_TIMEOUT_CONTROLLER; while (get_time().val < timeout) { int isr = STM32_FMPI2C_ISR(port); /* Check for errors */ - if (isr & (FMPI2C_ISR_ARLO | FMPI2C_ISR_BERR | - FMPI2C_ISR_NACKF)) { + if (isr & + (FMPI2C_ISR_ARLO | FMPI2C_ISR_BERR | FMPI2C_ISR_NACKF)) { return EC_ERROR_UNKNOWN; } @@ -254,28 +256,27 @@ static int wait_fmpi2c_isr(int port, int mask) } /** - * Send a start condition and slave address on the specified port. + * Send a start condition and peripheral address on the specified port. * * @param port I2C port - * @param slave_addr Slave address + * @param addr_8bit I2C address * @param size bytes to transfer * @param is_read read, or write? * * @return Non-zero if error. */ -static int send_fmpi2c_start(const int port, const uint16_t slave_addr_8bit, - int size, int is_read) +static int send_fmpi2c_start(const int port, const uint16_t addr_8bit, int size, + int is_read) { uint32_t reg; /* Send start bit */ reg = STM32_FMPI2C_CR2(port); reg &= ~(FMPI2C_CR2_SADD_MASK | FMPI2C_CR2_SIZE_MASK | - FMPI2C_CR2_RELOAD | FMPI2C_CR2_AUTOEND | - FMPI2C_CR2_RD_WRN | FMPI2C_CR2_START | FMPI2C_CR2_STOP); - reg |= FMPI2C_CR2_START | FMPI2C_CR2_AUTOEND | - slave_addr_8bit | FMPI2C_CR2_SIZE(size) | - (is_read ? FMPI2C_CR2_RD_WRN : 0); + FMPI2C_CR2_RELOAD | FMPI2C_CR2_AUTOEND | FMPI2C_CR2_RD_WRN | + FMPI2C_CR2_START | FMPI2C_CR2_STOP); + reg |= FMPI2C_CR2_START | FMPI2C_CR2_AUTOEND | addr_8bit | + FMPI2C_CR2_SIZE(size) | (is_read ? FMPI2C_CR2_RD_WRN : 0); STM32_FMPI2C_CR2(port) = reg; return EC_SUCCESS; @@ -298,17 +299,17 @@ static void i2c_set_freq_port(const struct i2c_port_t *p) /* FMP I2C clock set. */ STM32_FMPI2C_CR1(port) &= ~FMPI2C_CR1_PE; - prescalar = (freq / (p->kbps * 1000 * - (0x12 + 1 + 0xe + 1 + 1))) - 1; + prescalar = + (freq / (p->kbps * 1000 * (0x12 + 1 + 0xe + 1 + 1))) - + 1; actual = freq / ((prescalar + 1) * (0x12 + 1 + 0xe + 1 + 1)); - reg = FMPI2C_TIMINGR_SCLL(0x12) | - FMPI2C_TIMINGR_SCLH(0xe) | - FMPI2C_TIMINGR_PRESC(prescalar); + reg = FMPI2C_TIMINGR_SCLL(0x12) | FMPI2C_TIMINGR_SCLH(0xe) | + FMPI2C_TIMINGR_PRESC(prescalar); STM32_FMPI2C_TIMINGR(port) = reg; - CPRINTS("port %d target %d, pre %d, act %d, reg 0x%08x", - port, p->kbps, prescalar, actual, reg); + CPRINTS("port %d target %d, pre %d, act %d, reg 0x%08x", port, + p->kbps, prescalar, actual, reg); STM32_FMPI2C_CR1(port) |= FMPI2C_CR1_PE; udelay(10); @@ -321,9 +322,9 @@ static void i2c_set_freq_port(const struct i2c_port_t *p) if (p->kbps > 100) { STM32_I2C_CCR(port) = freq / (2 * MSEC * p->kbps); } else { - STM32_I2C_CCR(port) = STM32_I2C_CCR_FM - | STM32_I2C_CCR_DUTY - | (freq / (16 + 9 * MSEC * p->kbps)); + STM32_I2C_CCR(port) = + STM32_I2C_CCR_FM | STM32_I2C_CCR_DUTY | + (freq / (16 + 9 * MSEC * p->kbps)); } STM32_I2C_CR2(port) = freq / SECOND; STM32_I2C_TRISE(port) = freq / SECOND + 1; @@ -382,17 +383,17 @@ static void fmpi2c_clear_regs(int port) STM32_FMPI2C_ICR(port) = 0xffffffff; /* Clear start, stop, NACK, etc. bits to get us in a known state */ - STM32_FMPI2C_CR2(port) &= ~(FMPI2C_CR2_START | FMPI2C_CR2_STOP | - FMPI2C_CR2_RD_WRN | FMPI2C_CR2_NACK | - FMPI2C_CR2_AUTOEND | - FMPI2C_CR2_SADD_MASK | FMPI2C_CR2_SIZE_MASK); + STM32_FMPI2C_CR2(port) &= + ~(FMPI2C_CR2_START | FMPI2C_CR2_STOP | FMPI2C_CR2_RD_WRN | + FMPI2C_CR2_NACK | FMPI2C_CR2_AUTOEND | FMPI2C_CR2_SADD_MASK | + FMPI2C_CR2_SIZE_MASK); } /** * Perform an i2c transaction * * @param port i2c port to use - * @param slave_addr the i2c slave addr + * @param addr_8bit the i2c address * @param out source buffer for data * @param out_bytes bytes of data to write * @param in destination buffer for data @@ -401,9 +402,9 @@ static void fmpi2c_clear_regs(int port) * * @return EC_SUCCESS on success. */ -static int chip_fmpi2c_xfer(const int port, const uint16_t slave_addr_8bit, - const uint8_t *out, int out_bytes, - uint8_t *in, int in_bytes, int flags) +static int chip_fmpi2c_xfer(const int port, const uint16_t addr_8bit, + const uint8_t *out, int out_bytes, uint8_t *in, + int in_bytes, int flags) { int started = (flags & I2C_XFER_START) ? 0 : 1; int rv = EC_SUCCESS; @@ -422,8 +423,8 @@ static int chip_fmpi2c_xfer(const int port, const uint16_t slave_addr_8bit, /* No out bytes and no in bytes means just check for active */ if (out_bytes || !in_bytes) { - rv = send_fmpi2c_start( - port, slave_addr_8bit, out_bytes, FMPI2C_WRITE); + rv = send_fmpi2c_start(port, addr_8bit, out_bytes, + FMPI2C_WRITE); if (rv) goto xfer_exit; @@ -448,8 +449,8 @@ static int chip_fmpi2c_xfer(const int port, const uint16_t slave_addr_8bit, dma_start_rx(dma, in_bytes, in); i2c_dma_enable_tc_interrupt(dma->channel, port); - rv_start = send_fmpi2c_start( - port, slave_addr_8bit, in_bytes, FMPI2C_READ); + rv_start = send_fmpi2c_start(port, addr_8bit, in_bytes, + FMPI2C_READ); if (rv_start) goto xfer_exit; @@ -458,9 +459,8 @@ static int chip_fmpi2c_xfer(const int port, const uint16_t slave_addr_8bit, goto xfer_exit; STM32_FMPI2C_CR1(port) |= FMPI2C_CR1_RXDMAEN; - rv = task_wait_event_mask( - TASK_EVENT_I2C_COMPLETION(port), - DMA_TRANSFER_TIMEOUT_US); + rv = task_wait_event_mask(TASK_EVENT_I2C_COMPLETION(port), + DMA_TRANSFER_TIMEOUT_US); if (rv & TASK_EVENT_I2C_COMPLETION(port)) rv = EC_SUCCESS; else @@ -476,7 +476,7 @@ static int chip_fmpi2c_xfer(const int port, const uint16_t slave_addr_8bit, STM32_FMPI2C_CR1(port) &= ~FMPI2C_CR1_RXDMAEN; } - xfer_exit: +xfer_exit: /* On error, queue a stop condition */ if (rv) { flags |= I2C_XFER_STOP; @@ -490,7 +490,8 @@ static int chip_fmpi2c_xfer(const int port, const uint16_t slave_addr_8bit, const struct i2c_port_t *p; CPRINTS("chip_fmpi2c_xfer start error; " - "unwedging and resetting i2c %d", port); + "unwedging and resetting i2c %d", + port); p = find_port(port); i2c_unwedge(port); @@ -509,7 +510,7 @@ static int chip_fmpi2c_xfer(const int port, const uint16_t slave_addr_8bit, /* * Allow bus to idle for at least one 100KHz clock = 10 us. - * This allows slaves on the bus to detect bus-idle before + * This allows peripherals on the bus to detect bus-idle before * the next start condition. */ STM32_FMPI2C_CR1(port) &= ~FMPI2C_CR1_PE; @@ -520,7 +521,6 @@ static int chip_fmpi2c_xfer(const int port, const uint16_t slave_addr_8bit, return rv; } - /** * Clear status regs on the specified I2C port. * @@ -537,10 +537,8 @@ static void i2c_clear_regs(int port) STM32_I2C_SR1(port) = 0; /* Clear start, stop, POS, ACK bits to get us in a known state */ - STM32_I2C_CR1(port) &= ~(STM32_I2C_CR1_START | - STM32_I2C_CR1_STOP | - STM32_I2C_CR1_POS | - STM32_I2C_CR1_ACK); + STM32_I2C_CR1(port) &= ~(STM32_I2C_CR1_START | STM32_I2C_CR1_STOP | + STM32_I2C_CR1_POS | STM32_I2C_CR1_ACK); } /***************************************************************************** @@ -548,11 +546,10 @@ static void i2c_clear_regs(int port) */ /* Perform an i2c transaction. */ -int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, - const uint8_t *out, int out_bytes, - uint8_t *in, int in_bytes, int flags) +int chip_i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_bytes, uint8_t *in, int in_bytes, int flags) { - int addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; + int addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; int started = (flags & I2C_XFER_START) ? 0 : 1; int rv = EC_SUCCESS; int i; @@ -563,9 +560,8 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, ASSERT(!started); if (p->port == STM32F4_FMPI2C_PORT) { - return chip_fmpi2c_xfer(port, addr_8bit, - out, out_bytes, - in, in_bytes, flags); + return chip_fmpi2c_xfer(port, addr_8bit, out, out_bytes, in, + in_bytes, flags); } i2c_clear_regs(port); @@ -642,7 +638,7 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, STM32_I2C_CR2(port) &= ~STM32_I2C_CR2_DMAEN; } - xfer_exit: +xfer_exit: /* On error, queue a stop condition */ if (rv) { flags |= I2C_XFER_STOP; @@ -656,7 +652,8 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, const struct i2c_port_t *p; CPRINTS("chip_i2c_xfer start error; " - "unwedging and resetting i2c %d", port); + "unwedging and resetting i2c %d", + port); p = find_port(port); i2c_unwedge(port); @@ -675,7 +672,7 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, /* * Allow bus to idle for at least one 100KHz clock = 10 us. - * This allows slaves on the bus to detect bus-idle before + * This allows peripherals on the bus to detect bus-idle before * the next start condition. */ usleep(10); @@ -709,13 +706,13 @@ int i2c_raw_get_sda(int port) int i2c_get_line_levels(int port) { return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) | - (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); + (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); } /*****************************************************************************/ /* Hooks */ -#ifdef CONFIG_I2C_MASTER +#ifdef CONFIG_I2C_CONTROLLER /* Handle CPU clock changing frequency */ static void i2c_freq_change(void) { @@ -754,9 +751,9 @@ DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_change_hook, HOOK_PRIO_DEFAULT); #endif /*****************************************************************************/ -/* Slave */ -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS -/* Host command slave */ +/* Peripheral */ +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS +/* Host command peripheral */ /* * Buffer for received host command packets (including prefix byte on request, * and result/size on response). After any protocol-specific headers, the @@ -764,7 +761,7 @@ DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_change_hook, HOOK_PRIO_DEFAULT); */ static uint8_t host_buffer_padded[I2C_MAX_HOST_PACKET_SIZE + 4 + CONFIG_I2C_EXTRA_PACKET_SIZE] __aligned(4); -static uint8_t * const host_buffer = host_buffer_padded + 2; +static uint8_t *const host_buffer = host_buffer_padded + 2; static uint8_t params_copy[I2C_MAX_HOST_PACKET_SIZE] __aligned(4); static int host_i2c_resp_port; static int tx_pending; @@ -790,7 +787,7 @@ static void i2c_send_response_packet(struct host_packet *pkt) /* * Set the transmitter to be in 'not full' state to keep sending - * '0xec' in the event loop. Because of this, the master i2c + * '0xec' in the event loop. Because of this, the controller i2c * doesn't need to snoop the response stream to abort transaction. */ STM32_I2C_CR2(host_i2c_resp_port) |= STM32_I2C_CR2_ITBUFEN; @@ -834,7 +831,7 @@ static void i2c_process_command(void) host_packet_receive(&i2c_packet); } -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS static void i2c_send_board_response(int len) { /* host_buffer data range, beyond this length, will return 0xec */ @@ -868,7 +865,7 @@ static void i2c_event_handler(int port) /* * Check for error conditions. Note, arbitration loss and bus error - * are the only two errors we can get as a slave allowing clock + * are the only two errors we can get as a peripheral allowing clock * stretching and in non-SMBus mode. */ if (i2c_sr1 & (STM32_I2C_SR1_ARLO | STM32_I2C_SR1_BERR)) { @@ -877,25 +874,27 @@ static void i2c_event_handler(int port) /* Disable buffer interrupt */ STM32_I2C_CR2(port) &= ~STM32_I2C_CR2_ITBUFEN; /* Clear error status bits */ - STM32_I2C_SR1(port) &= ~(STM32_I2C_SR1_ARLO | - STM32_I2C_SR1_BERR); + STM32_I2C_SR1(port) &= + ~(STM32_I2C_SR1_ARLO | STM32_I2C_SR1_BERR); } - /* Transfer matched our slave address */ + /* Transfer matched our peripheral address */ if (i2c_sr1 & STM32_I2C_SR1_ADDR) { addr_8bit = ((i2c_sr2 & STM32_I2C_SR2_DUALF) ? - STM32_I2C_OAR2(port) : STM32_I2C_OAR1(port)) & 0xfe; + STM32_I2C_OAR2(port) : + STM32_I2C_OAR1(port)) & + 0xfe; if (i2c_sr2 & STM32_I2C_SR2_TRA) { - /* Transmitter slave */ + /* Transmitter peripheral */ i2c_sr1 |= STM32_I2C_SR1_TXE; -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS if (!rx_pending && !tx_pending) { tx_pending = 1; i2c_process_board_command(1, addr_8bit, 0); } #endif } else { - /* Receiver slave */ + /* Receiver peripheral */ buf_idx = 0; rx_pending = 1; } @@ -906,10 +905,10 @@ static void i2c_event_handler(int port) unused = STM32_I2C_SR1(port); unused = STM32_I2C_SR2(port); /* Inhibit stop mode when addressed until STOPF flag is set */ - disable_sleep(SLEEP_MASK_I2C_SLAVE); + disable_sleep(SLEEP_MASK_I2C_PERIPHERAL); } - /* I2C in slave transmitter */ + /* I2C in peripheral transmitter */ if (i2c_sr2 & STM32_I2C_SR2_TRA) { if (i2c_sr1 & (STM32_I2C_SR1_BTF | STM32_I2C_SR1_TXE)) { if (tx_pending) { @@ -926,10 +925,10 @@ static void i2c_event_handler(int port) host_i2c_resp_port = port; /* Disable buffer interrupt */ STM32_I2C_CR2(port) &= ~STM32_I2C_CR2_ITBUFEN; -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS if ((addr_8bit >> 1) == - I2C_GET_ADDR( - CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS)) + I2C_STRIP_FLAGS( + CONFIG_BOARD_I2C_ADDR_FLAGS)) i2c_process_board_command(1, addr_8bit, buf_idx); else @@ -942,7 +941,7 @@ static void i2c_event_handler(int port) STM32_I2C_DR(port) = 0xec; } } - } else { /* I2C in slave receiver */ + } else { /* I2C in peripheral receiver */ if (i2c_sr1 & (STM32_I2C_SR1_BTF | STM32_I2C_SR1_RXNE)) host_buffer[buf_idx++] = STM32_I2C_DR(port); } @@ -952,10 +951,10 @@ static void i2c_event_handler(int port) /* Disable buffer interrupt */ STM32_I2C_CR2(port) &= ~STM32_I2C_CR2_ITBUFEN; -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS if (rx_pending && (addr_8b >> 1) == - I2C_GET_ADDR(CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS)) + I2C_STRIP_FLAGS(CONFIG_BOARD_I2C_ADDR_FLAGS)) i2c_process_board_command(0, addr_8bit, buf_idx); #endif rx_pending = 0; @@ -968,19 +967,21 @@ static void i2c_event_handler(int port) STM32_I2C_CR1(port) = i2c_cr1 | STM32_I2C_CR1_PE; /* No longer inhibit deep sleep after stop condition */ - enable_sleep(SLEEP_MASK_I2C_SLAVE); + enable_sleep(SLEEP_MASK_I2C_PERIPHERAL); } /* Enable again */ if (!(i2c_cr1 & STM32_I2C_CR1_PE)) STM32_I2C_CR1(port) |= STM32_I2C_CR1_PE; } -void i2c_event_interrupt(void) { i2c_event_handler(I2C_PORT_EC); } -DECLARE_IRQ(IRQ_SLAVE_EV, i2c_event_interrupt, 2); -DECLARE_IRQ(IRQ_SLAVE_ER, i2c_event_interrupt, 2); +static void i2c_event_interrupt(void) +{ + i2c_event_handler(I2C_PORT_EC); +} +DECLARE_IRQ(IRQ_PERIPHERAL_EV, i2c_event_interrupt, 2); +DECLARE_IRQ(IRQ_PERIPHERAL_ER, i2c_event_interrupt, 2); #endif - /* Init all available i2c ports */ void i2c_init(void) { @@ -990,21 +991,22 @@ void i2c_init(void) for (i = 0; i < i2c_ports_used; i++, p++) i2c_init_port(p); - -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS /* Enable ACK */ STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_ACK; /* Enable interrupts */ - STM32_I2C_CR2(I2C_PORT_EC) |= STM32_I2C_CR2_ITEVTEN - | STM32_I2C_CR2_ITERREN; - /* Setup host command slave */ - STM32_I2C_OAR1(I2C_PORT_EC) = STM32_I2C_OAR1_B14 - | (I2C_GET_ADDR(CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS) << 1); -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS - STM32_I2C_OAR2(I2C_PORT_EC) = STM32_I2C_OAR2_ENDUAL - | (I2C_GET_ADDR(CONFIG_BOARD_I2C_SLAVE_ADDR_FLAGS) << 1); + STM32_I2C_CR2(I2C_PORT_EC) |= STM32_I2C_CR2_ITEVTEN | + STM32_I2C_CR2_ITERREN; + /* Setup host command peripheral */ + STM32_I2C_OAR1(I2C_PORT_EC) = + STM32_I2C_OAR1_B14 | + (I2C_STRIP_ADDR(CONFIG_HOSTCMD_I2C_ADDR_FLAGS) << 1); +#ifdef CONFIG_BOARD_I2C_ADDR_FLAGS + STM32_I2C_OAR2(I2C_PORT_EC) = + STM32_I2C_OAR2_ENDUAL | + (I2C_STRIP_FLAGS(CONFIG_BOARD_I2C_ADDR_FLAGS) << 1); #endif - task_enable_irq(IRQ_SLAVE_EV); - task_enable_irq(IRQ_SLAVE_ER); + task_enable_irq(IRQ_PERIPHERAL_EV); + task_enable_irq(IRQ_PERIPHERAL_ER); #endif } diff --git a/chip/stm32/i2c-stm32g4.c b/chip/stm32/i2c-stm32g4.c index de6937ab28..66ec8173d8 100644 --- a/chip/stm32/i2c-stm32g4.c +++ b/chip/stm32/i2c-stm32g4.c @@ -1,8 +1,9 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "chipset.h" #include "clock.h" #include "common.h" @@ -20,12 +21,12 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) #define I2C_ERROR_FAILED_START EC_ERROR_INTERNAL_FIRST /* Transmit timeout in microseconds */ -#define I2C_TX_TIMEOUT_MASTER (10 * MSEC) +#define I2C_TX_TIMEOUT_MASTER (10 * MSEC) enum i2c_freq_khz { freq_100 = 100, @@ -44,8 +45,8 @@ struct i2c_timing { /* timing register values for supported input clks / i2c clk rates */ static const uint32_t busyloop_us[I2C_FREQ_COUNT] = { [I2C_FREQ_1000KHZ] = 16, /* Enough for 2 bytes */ - [I2C_FREQ_400KHZ] = 40, /* Enough for 2 bytes */ - [I2C_FREQ_100KHZ] = 0, /* No busy looping at 100kHz (bus is slow) */ + [I2C_FREQ_400KHZ] = 40, /* Enough for 2 bytes */ + [I2C_FREQ_100KHZ] = 0, /* No busy looping at 100kHz (bus is slow) */ }; /* @@ -94,8 +95,8 @@ static const uint32_t i2c_regs_base[] = { /* I2C port state data */ struct i2c_port_data { - uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ - enum i2c_freq freq; /* Port clock speed */ + uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ + enum i2c_freq freq; /* Port clock speed */ }; static struct i2c_port_data pdata[I2C_PORT_COUNT]; @@ -145,10 +146,10 @@ static void i2c_set_timingr_port(const struct i2c_port_t *p) } /* Assemble write value for timingr register */ timingr = (i2c_timingr[index].scll << STM32_I2C_TIMINGR_SCLL_OFF) | - (i2c_timingr[index].sclh << STM32_I2C_TIMINGR_SCLH_OFF) | - (i2c_timingr[index].sdadel << STM32_I2C_TIMINGR_SDADEL_OFF) | - (i2c_timingr[index].scldel << STM32_I2C_TIMINGR_SCLDEL_OFF) | - (i2c_timingr[index].presc << STM32_I2C_TIMINGR_PRESC_OFF); + (i2c_timingr[index].sclh << STM32_I2C_TIMINGR_SCLH_OFF) | + (i2c_timingr[index].sdadel << STM32_I2C_TIMINGR_SDADEL_OFF) | + (i2c_timingr[index].scldel << STM32_I2C_TIMINGR_SCLDEL_OFF) | + (i2c_timingr[index].presc << STM32_I2C_TIMINGR_PRESC_OFF); /* Write timingr value */ STM32_I2C_TIMINGR(base) = timingr; @@ -189,8 +190,8 @@ static void i2c_init_port(const struct i2c_port_t *p) mask = STM32_RCC_CCIPR_I2CNSEL_MASK << shift; clksel = STM32_RCC_CCIPR; clksel &= ~mask; - STM32_RCC_CCIPR = clksel | (STM32_RCC_CCIPR_I2CNSEL_HSI - << shift); + STM32_RCC_CCIPR = clksel | + (STM32_RCC_CCIPR_I2CNSEL_HSI << shift); } else if (port == 3) { /* i2c4sel is bits 1:0, no shift required */ STM32_RCC_CCIPR2 &= ~STM32_RCC_CCIPR2_I2C4SEL_MASK; @@ -260,11 +261,10 @@ static int wait_isr(int port, int mask) * Exported functions declared in i2c.h */ /* Perform an i2c transaction. */ -int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, - const uint8_t *out, int out_bytes, - uint8_t *in, int in_bytes, int flags) +int chip_i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_bytes, uint8_t *in, int in_bytes, int flags) { - int addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; + int addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; int rv = EC_SUCCESS; int i; int xfer_start = flags & I2C_XFER_START; @@ -290,13 +290,13 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, * if we are not stopping, set RELOAD bit so that we can load * NBYTES again. if we are starting, then set START bit. */ - STM32_I2C_CR2(base) = ((out_bytes & 0xFF) << 16) - | addr_8bit - | ((in_bytes == 0 && xfer_stop) ? - STM32_I2C_CR2_AUTOEND : 0) - | ((in_bytes == 0 && !xfer_stop) ? - STM32_I2C_CR2_RELOAD : 0) - | (xfer_start ? STM32_I2C_CR2_START : 0); + STM32_I2C_CR2(base) = + ((out_bytes & 0xFF) << 16) | addr_8bit | + ((in_bytes == 0 && xfer_stop) ? STM32_I2C_CR2_AUTOEND : + 0) | + ((in_bytes == 0 && !xfer_stop) ? STM32_I2C_CR2_RELOAD : + 0) | + (xfer_start ? STM32_I2C_CR2_START : 0); for (i = 0; i < out_bytes; i++) { rv = wait_isr(port, STM32_I2C_ISR_TXIS); @@ -319,11 +319,11 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, * NBYTES again. if we were just transmitting, we need to * set START bit to send (re)start and begin read transaction. */ - STM32_I2C_CR2(base) = ((in_bytes & 0xFF) << 16) - | STM32_I2C_CR2_RD_WRN | addr_8bit - | (xfer_stop ? STM32_I2C_CR2_AUTOEND : 0) - | (!xfer_stop ? STM32_I2C_CR2_RELOAD : 0) - | (out_bytes || xfer_start ? STM32_I2C_CR2_START : 0); + STM32_I2C_CR2(base) = + ((in_bytes & 0xFF) << 16) | STM32_I2C_CR2_RD_WRN | + addr_8bit | (xfer_stop ? STM32_I2C_CR2_AUTOEND : 0) | + (!xfer_stop ? STM32_I2C_CR2_RELOAD : 0) | + (out_bytes || xfer_start ? STM32_I2C_CR2_START : 0); for (i = 0; i < in_bytes; i++) { /* Wait for receive buffer not empty */ @@ -402,13 +402,13 @@ int i2c_raw_get_sda(int port) int i2c_get_line_levels(int port) { return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) | - (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); + (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); } /*****************************************************************************/ /* Hooks */ -#ifdef CONFIG_I2C_MASTER +#ifdef CONFIG_I2C_CONTROLLER /* Handle an upcoming frequency change. */ static void i2c_pre_freq_change_hook(void) { diff --git a/chip/stm32/i2c-stm32l.c b/chip/stm32/i2c-stm32l.c index 80d3434c74..f18374281a 100644 --- a/chip/stm32/i2c-stm32l.c +++ b/chip/stm32/i2c-stm32l.c @@ -1,8 +1,9 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "chipset.h" #include "clock.h" #include "common.h" @@ -19,7 +20,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) #define I2C_ERROR_FAILED_START EC_ERROR_INTERNAL_FIRST @@ -35,23 +36,20 @@ * flips out. The battery may flip out and hold lines low for up to * 25ms. If we just wait it will eventually let them go. */ -#define I2C_TX_TIMEOUT_MASTER (30 * MSEC) +#define I2C_TX_TIMEOUT_MASTER (30 * MSEC) /* * Delay 5us in bitbang mode. That gives us roughly 5us low and 5us high or * a frequency of 100kHz. */ -#define I2C_BITBANG_HALF_CYCLE_US 5 +#define I2C_BITBANG_HALF_CYCLE_US 5 #ifdef CONFIG_I2C_DEBUG static void dump_i2c_reg(int port, const char *what) { CPRINTS("i2c CR1=%04x CR2=%04x SR1=%04x SR2=%04x %s", - STM32_I2C_CR1(port), - STM32_I2C_CR2(port), - STM32_I2C_SR1(port), - STM32_I2C_SR2(port), - what); + STM32_I2C_CR1(port), STM32_I2C_CR2(port), STM32_I2C_SR1(port), + STM32_I2C_SR2(port), what); } #else static inline void dump_i2c_reg(int port, const char *what) @@ -164,12 +162,10 @@ static void i2c_init_port(const struct i2c_port_t *p) /*****************************************************************************/ /* Interface */ -int chip_i2c_xfer(const int port, - const uint16_t slave_addr_flags, - const uint8_t *out, int out_bytes, - uint8_t *in, int in_bytes, int flags) +int chip_i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_bytes, uint8_t *in, int in_bytes, int flags) { - int addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; + int addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; int started = (flags & I2C_XFER_START) ? 0 : 1; int rv = EC_SUCCESS; int i; @@ -188,10 +184,8 @@ int chip_i2c_xfer(const int port, STM32_I2C_SR1(port) = 0; /* Clear start, stop, POS, ACK bits to get us in a known state */ - STM32_I2C_CR1(port) &= ~(STM32_I2C_CR1_START | - STM32_I2C_CR1_STOP | - STM32_I2C_CR1_POS | - STM32_I2C_CR1_ACK); + STM32_I2C_CR1(port) &= ~(STM32_I2C_CR1_START | STM32_I2C_CR1_STOP | + STM32_I2C_CR1_POS | STM32_I2C_CR1_ACK); /* No out bytes and no in bytes means just check for active */ if (out_bytes || !in_bytes) { @@ -291,7 +285,7 @@ int chip_i2c_xfer(const int port, } } - xfer_exit: +xfer_exit: /* On error, queue a stop condition */ if (rv) { flags |= I2C_XFER_STOP; @@ -305,7 +299,8 @@ int chip_i2c_xfer(const int port, if (rv == I2C_ERROR_FAILED_START) { const struct i2c_port_t *p = i2c_ports; CPRINTS("chip_i2c_xfer start error; " - "unwedging and resetting i2c %d", port); + "unwedging and resetting i2c %d", + port); i2c_unwedge(port); @@ -363,7 +358,7 @@ int i2c_raw_get_sda(int port) int i2c_get_line_levels(int port) { return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) | - (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); + (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); } /*****************************************************************************/ @@ -414,11 +409,9 @@ void i2c_init(void) /*****************************************************************************/ /* Console commands */ -static int command_i2cdump(int argc, char **argv) +static int command_i2cdump(int argc, const char **argv) { dump_i2c_reg(I2C_PORT_MASTER, "dump"); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(i2cdump, command_i2cdump, - NULL, - "Dump I2C regs"); +DECLARE_CONSOLE_COMMAND(i2cdump, command_i2cdump, NULL, "Dump I2C regs"); diff --git a/chip/stm32/i2c-stm32l4.c b/chip/stm32/i2c-stm32l4.c index 66bd063499..5d4e51e92e 100644 --- a/chip/stm32/i2c-stm32l4.c +++ b/chip/stm32/i2c-stm32l4.c @@ -1,9 +1,11 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "printf.h" +/* I2C drivers for STM32L4xx as well as STM32L5xx. */ + +#include "builtin/assert.h" #include "chipset.h" #include "clock.h" #include "common.h" @@ -12,8 +14,8 @@ #include "hooks.h" #include "hwtimer.h" #include "i2c.h" +#include "printf.h" #include "registers.h" - #include "system.h" #include "task.h" #include "timer.h" @@ -21,13 +23,13 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) /* Transmit timeout in microseconds */ -#define I2C_TX_TIMEOUT_MASTER (10 * MSEC) +#define I2C_TX_TIMEOUT_MASTER (10 * MSEC) -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS -#define I2C_SLAVE_ERROR_CODE 0xec +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS +#define I2C_SLAVE_ERROR_CODE 0xec #if (I2C_PORT_EC == STM32_I2C1_PORT) #define IRQ_SLAVE STM32_IRQ_I2C1 #else @@ -37,8 +39,8 @@ /* I2C port state data */ struct i2c_port_data { - uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ - enum i2c_freq freq; /* Port clock speed */ + uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ + enum i2c_freq freq; /* Port clock speed */ }; static struct i2c_port_data pdata[I2C_PORT_COUNT]; @@ -50,8 +52,8 @@ void i2c_set_timeout(int port, uint32_t timeout) /* timing register values for supported input clks / i2c clk rates */ static const uint32_t busyloop_us[I2C_FREQ_COUNT] = { [I2C_FREQ_1000KHZ] = 16, /* Enough for 2 bytes */ - [I2C_FREQ_400KHZ] = 40, /* Enough for 2 bytes */ - [I2C_FREQ_100KHZ] = 0, /* No busy looping at 100kHz (bus is slow) */ + [I2C_FREQ_400KHZ] = 40, /* Enough for 2 bytes */ + [I2C_FREQ_100KHZ] = 0, /* No busy looping at 100kHz (bus is slow) */ }; /** @@ -70,7 +72,7 @@ static int wait_isr(int port, int mask) /* Check for errors */ if (isr & (STM32_I2C_ISR_ARLO | STM32_I2C_ISR_BERR | - STM32_I2C_ISR_NACK)) + STM32_I2C_ISR_NACK)) return EC_ERROR_UNKNOWN; /* Check for desired mask */ @@ -90,9 +92,10 @@ static int wait_isr(int port, int mask) return EC_ERROR_TIMEOUT; } -/* We are only using sysclk, which is 40MHZ */ +/* Supported i2c input clocks */ enum stm32_i2c_clk_src { - I2C_CLK_SRC_40MHZ = 0, + I2C_CLK_SRC_48MHZ = 0, + I2C_CLK_SRC_16MHZ = 1, I2C_CLK_SRC_COUNT, }; @@ -101,29 +104,38 @@ enum stm32_i2c_clk_src { * These values are calculated using ST's STM32cubeMX tool */ static const uint32_t timingr_regs[I2C_CLK_SRC_COUNT][I2C_FREQ_COUNT] = { - [I2C_CLK_SRC_40MHZ] = { - [I2C_FREQ_1000KHZ] = 0x00100618, - [I2C_FREQ_400KHZ] = 0x00301347, - [I2C_FREQ_100KHZ] = 0x003087FF, + [I2C_CLK_SRC_48MHZ] = { + [I2C_FREQ_1000KHZ] = 0x20000209, + [I2C_FREQ_400KHZ] = 0x2010091A, + [I2C_FREQ_100KHZ] = 0x20303E5D, + }, + [I2C_CLK_SRC_16MHZ] = { + [I2C_FREQ_1000KHZ] = 0x00000107, + [I2C_FREQ_400KHZ] = 0x00100B15, + [I2C_FREQ_100KHZ] = 0x00303D5B, }, }; -static void i2c_set_freq_port(const struct i2c_port_t *p, - enum stm32_i2c_clk_src src, - enum i2c_freq freq) +int chip_i2c_set_freq(int port, enum i2c_freq freq) { - int port = p->port; - const uint32_t *regs = timingr_regs[src]; + enum stm32_i2c_clk_src src = I2C_CLK_SRC_16MHZ; /* Disable port */ STM32_I2C_CR1(port) = 0; STM32_I2C_CR2(port) = 0; /* Set clock frequency */ - STM32_I2C_TIMINGR(port) = regs[freq]; + STM32_I2C_TIMINGR(port) = timingr_regs[src][freq]; /* Enable port */ STM32_I2C_CR1(port) = STM32_I2C_CR1_PE; pdata[port].freq = freq; + + return EC_SUCCESS; +} + +enum i2c_freq chip_i2c_get_freq(int port) +{ + return pdata[port].freq; } /** @@ -134,20 +146,30 @@ static void i2c_set_freq_port(const struct i2c_port_t *p, static void i2c_init_port(const struct i2c_port_t *p) { int port = p->port; - uint32_t mask; - uint8_t shift; - enum stm32_i2c_clk_src src = I2C_CLK_SRC_40MHZ; + uint32_t val; enum i2c_freq freq; - /* Enable clocks to I2C modules if necessary */ - if (!(STM32_RCC_APB1ENR & (1 << (21 + port)))) - STM32_RCC_APB1ENR |= 1 << (21 + port); + /* Enable I2C clock */ + if (port == 3) { + STM32_RCC_APB1ENR2 |= STM32_RCC_APB1ENR2_I2C4EN; + } else { + STM32_RCC_APB1ENR1 |= 1 << (21 + port); + } - /* Select sysclk as source */ - mask = STM32_RCC_CCIPR_I2C1SEL_MASK << (port * 2); - shift = STM32_RCC_CCIPR_I2C1SEL_SHIFT + (port * 2); - STM32_RCC_CCIPR &= ~mask; - STM32_RCC_CCIPR |= STM32_RCC_CCIPR_I2C_SYSCLK << shift; + /* Select HSI 16MHz as I2C clock source */ + if (port == 3) { + val = STM32_RCC_CCIPR2; + val &= ~STM32_RCC_CCIPR2_I2C4SEL_MSK; + val |= STM32_RCC_CCIPR_I2C_HSI16 + << STM32_RCC_CCIPR2_I2C4SEL_POS; + STM32_RCC_CCIPR2 = val; + } else { + val = STM32_RCC_CCIPR; + val &= ~(STM32_RCC_CCIPR_I2C1SEL_MASK << (port * 2)); + val |= STM32_RCC_CCIPR_I2C_HSI16 + << (STM32_RCC_CCIPR_I2C1SEL_SHIFT + port * 2); + STM32_RCC_CCIPR = val; + } /* Configure GPIOs */ gpio_config_module(MODULE_I2C, 1); @@ -155,6 +177,7 @@ static void i2c_init_port(const struct i2c_port_t *p) /* Set clock frequency */ switch (p->kbps) { case 1000: + STM32_SYSCFG_CFGR1 |= STM32_SYSCFG_I2CFMP(port); freq = I2C_FREQ_1000KHZ; break; case 400: @@ -169,7 +192,7 @@ static void i2c_init_port(const struct i2c_port_t *p) } /* Set up initial bus frequencies */ - i2c_set_freq_port(p, src, freq); + chip_i2c_set_freq(p->port, freq); /* Set up default timeout */ i2c_set_timeout(port, 0); @@ -177,7 +200,7 @@ static void i2c_init_port(const struct i2c_port_t *p) /*****************************************************************************/ -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS static void i2c_event_handler(int port) { @@ -203,8 +226,8 @@ static void i2c_event_handler(int port) STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE; /* Clear error status bits */ - STM32_I2C_ICR(port) |= STM32_I2C_ICR_BERRCF - | STM32_I2C_ICR_ARLOCF; + STM32_I2C_ICR(port) |= STM32_I2C_ICR_BERRCF | + STM32_I2C_ICR_ARLOCF; } /* Transfer matched our slave address */ @@ -234,7 +257,7 @@ static void i2c_event_handler(int port) /* Clear ADDR bit by writing to ADDRCF bit */ STM32_I2C_ICR(port) |= STM32_I2C_ICR_ADDRCF; /* Inhibit stop mode when addressed until STOPF flag is set */ - disable_sleep(SLEEP_MASK_I2C_SLAVE); + disable_sleep(SLEEP_MASK_I2C_PERIPHERAL); } /* @@ -262,7 +285,7 @@ static void i2c_event_handler(int port) STM32_I2C_ICR(port) |= STM32_I2C_ICR_STOPCF; /* No longer inhibit deep sleep after stop condition */ - enable_sleep(SLEEP_MASK_I2C_SLAVE); + enable_sleep(SLEEP_MASK_I2C_PERIPHERAL); } if (isr & STM32_I2C_ISR_NACK) { @@ -280,8 +303,8 @@ static void i2c_event_handler(int port) STM32_I2C_TXDR(port) = slave_buffer[tx_idx++]; } else { - STM32_I2C_TXDR(port) - = I2C_SLAVE_ERROR_CODE; + STM32_I2C_TXDR(port) = + I2C_SLAVE_ERROR_CODE; tx_idx = 0; tx_end = 0; tx_pending = 0; @@ -293,7 +316,7 @@ static void i2c_event_handler(int port) } } -void i2c_event_interrupt(void) +static void i2c_event_interrupt(void) { i2c_event_handler(I2C_PORT_EC); } @@ -303,11 +326,10 @@ DECLARE_IRQ(IRQ_SLAVE, i2c_event_interrupt, 2); /*****************************************************************************/ /* Interface */ -int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, - const uint8_t *out, int out_bytes, - uint8_t *in, int in_bytes, int flags) +int chip_i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_bytes, uint8_t *in, int in_bytes, int flags) { - int addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; + int addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; int rv = EC_SUCCESS; int i; int xfer_start = flags & I2C_XFER_START; @@ -329,13 +351,13 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, * if we are not stopping, set RELOAD bit so that we can load * NBYTES again. if we are starting, then set START bit. */ - STM32_I2C_CR2(port) = ((out_bytes & 0xFF) << 16) - | addr_8bit - | ((in_bytes == 0 && xfer_stop) ? - STM32_I2C_CR2_AUTOEND : 0) - | ((in_bytes == 0 && !xfer_stop) ? - STM32_I2C_CR2_RELOAD : 0) - | (xfer_start ? STM32_I2C_CR2_START : 0); + STM32_I2C_CR2(port) = + ((out_bytes & 0xFF) << 16) | addr_8bit | + ((in_bytes == 0 && xfer_stop) ? STM32_I2C_CR2_AUTOEND : + 0) | + ((in_bytes == 0 && !xfer_stop) ? STM32_I2C_CR2_RELOAD : + 0) | + (xfer_start ? STM32_I2C_CR2_START : 0); for (i = 0; i < out_bytes; i++) { rv = wait_isr(port, STM32_I2C_ISR_TXIS); @@ -358,11 +380,11 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, * NBYTES again. if we were just transmitting, we need to * set START bit to send (re)start and begin read transaction. */ - STM32_I2C_CR2(port) = ((in_bytes & 0xFF) << 16) - | STM32_I2C_CR2_RD_WRN | addr_8bit - | (xfer_stop ? STM32_I2C_CR2_AUTOEND : 0) - | (!xfer_stop ? STM32_I2C_CR2_RELOAD : 0) - | (out_bytes || xfer_start ? STM32_I2C_CR2_START : 0); + STM32_I2C_CR2(port) = + ((in_bytes & 0xFF) << 16) | STM32_I2C_CR2_RD_WRN | + addr_8bit | (xfer_stop ? STM32_I2C_CR2_AUTOEND : 0) | + (!xfer_stop ? STM32_I2C_CR2_RELOAD : 0) | + (out_bytes || xfer_start ? STM32_I2C_CR2_START : 0); for (i = 0; i < in_bytes; i++) { /* Wait for receive buffer not empty */ @@ -442,7 +464,7 @@ int i2c_raw_get_sda(int port) int i2c_get_line_levels(int port) { return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) | - (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); + (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); } void i2c_init(void) @@ -453,12 +475,13 @@ void i2c_init(void) for (i = 0; i < i2c_ports_used; i++, p++) i2c_init_port(p); -#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS - STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE - | STM32_I2C_CR1_ADDRIE | STM32_I2C_CR1_STOPIE - | STM32_I2C_CR1_NACKIE; - STM32_I2C_OAR1(I2C_PORT_EC) = 0x8000 - | (I2C_GET_ADDR(CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS) << 1); +#ifdef CONFIG_HOSTCMD_I2C_ADDR_FLAGS + STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE | + STM32_I2C_CR1_ADDRIE | + STM32_I2C_CR1_STOPIE | + STM32_I2C_CR1_NACKIE; + STM32_I2C_OAR1(I2C_PORT_EC) = + 0x8000 | (I2C_STRIP_FLAGS(CONFIG_HOSTCMD_I2C_ADDR_FLAGS) << 1); task_enable_irq(IRQ_SLAVE); #endif } diff --git a/chip/stm32/i2c-stm32l5.c b/chip/stm32/i2c-stm32l5.c new file mode 100644 index 0000000000..3c7cb170bc --- /dev/null +++ b/chip/stm32/i2c-stm32l5.c @@ -0,0 +1,6 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "i2c-stm32l4.c" diff --git a/chip/stm32/i2c_ite_flash_support.c b/chip/stm32/i2c_ite_flash_support.c index eca3c999af..335064572b 100644 --- a/chip/stm32/i2c_ite_flash_support.c +++ b/chip/stm32/i2c_ite_flash_support.c @@ -1,11 +1,11 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* STM implementation for flashing ITE-based ECs over i2c */ -#include "i2c_ite_flash_support.h" #include "i2c.h" +#include "i2c_ite_flash_support.h" #include "registers.h" #include "time.h" @@ -33,20 +33,20 @@ * (1<<9)-6 reads, leaving 6012 bytes of RAM available, down from 7356 bytes of * RAM available with the default 60 byte limits. */ -#if CONFIG_USB_I2C_MAX_WRITE_COUNT != ((1<<9) - 4) +#if CONFIG_USB_I2C_MAX_WRITE_COUNT != ((1 << 9) - 4) #error Must set CONFIG_USB_I2C_MAX_WRITE_COUNT to ((1<<9) - 4) #endif -#if CONFIG_USB_I2C_MAX_READ_COUNT != ((1<<9) - 6) +#if CONFIG_USB_I2C_MAX_READ_COUNT != ((1 << 9) - 6) #error Must set CONFIG_USB_I2C_MAX_WRITE_COUNT to ((1<<9) - 6) #endif /* * iteflash requires 256 byte reads for verifying ITE EC firmware. Without this - * the limit is CONFIG_I2C_CHIP_MAX_READ_SIZE which is 255 for STM32F0 due to an - * 8 bit field, per src/platform/ec/include/config.h comment. + * the limit is CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE which is 255 for STM32F0 due + * to an 8 bit field, per src/platform/ec/include/config.h comment. */ -#ifndef CONFIG_I2C_XFER_LARGE_READ -#error Must define CONFIG_I2C_XFER_LARGE_READ +#ifndef CONFIG_I2C_XFER_LARGE_TRANSFER +#error Must define CONFIG_I2C_XFER_LARGE_TRANSFER #endif #define KHz 1000 @@ -97,16 +97,15 @@ static int ite_i2c_read_register(uint8_t register_offset, uint8_t *output) int ret; /* Tell the ITE EC which register we want to read. */ ret = i2c_xfer_unlocked(ite_dfu_config.i2c_port, - ITE_DFU_I2C_CMD_ADDR_FLAGS, - ®ister_offset, sizeof(register_offset), - NULL, 0, I2C_XFER_SINGLE); + ITE_DFU_I2C_CMD_ADDR_FLAGS, ®ister_offset, + sizeof(register_offset), NULL, 0, + I2C_XFER_SINGLE); if (ret != EC_SUCCESS) return ret; /* Read in the 1 byte register value. */ ret = i2c_xfer_unlocked(ite_dfu_config.i2c_port, - ITE_DFU_I2C_DATA_ADDR_FLAGS, - NULL, 0, - output, sizeof(*output), I2C_XFER_SINGLE); + ITE_DFU_I2C_DATA_ADDR_FLAGS, NULL, 0, output, + sizeof(*output), I2C_XFER_SINGLE); return ret; } @@ -212,7 +211,7 @@ static int cprint_ite_chip_id(void) } ccprintf("ITE EC info: CHIPID1=0x%02X CHIPID2=0x%02X CHIPVER=0x%02X ", - chipid1[0], chipid2[0], chipver[0]); + chipid1[0], chipid2[0], chipver[0]); ccprintf("version=%d flash_bytes=%d\n", chip_version, flash_kb << 10); /* @@ -226,7 +225,7 @@ static int cprint_ite_chip_id(void) } /* Enable ITE direct firmware update (DFU) mode. */ -static int command_enable_ite_dfu(int argc, char **argv) +static int command_enable_ite_dfu(int argc, const char **argv) { if (argc > 1) return EC_ERROR_PARAM_COUNT; @@ -236,8 +235,8 @@ static int command_enable_ite_dfu(int argc, char **argv) return EC_ERROR_ACCESS_DENIED; /* Enable peripheral clocks. */ - STM32_RCC_APB2ENR |= - STM32_RCC_APB2ENR_TIM16EN | STM32_RCC_APB2ENR_TIM17EN; + STM32_RCC_APB2ENR |= STM32_RCC_APB2ENR_TIM16EN | + STM32_RCC_APB2ENR_TIM17EN; /* Reset timer registers which are not otherwise set below. */ STM32_TIM_CR2(16) = 0x0000; @@ -265,10 +264,10 @@ static int command_enable_ite_dfu(int argc, char **argv) STM32_TIM_ARR(17) = (MHz / SMDAT_WAVEFORM_PERIOD_HZ) - 1; /* Set output compare 1 mode to PWM mode 1 and enable preload. */ - STM32_TIM_CCMR1(16) = - STM32_TIM_CCMR1_OC1M_PWM_MODE_1 | STM32_TIM_CCMR1_OC1PE; - STM32_TIM_CCMR1(17) = - STM32_TIM_CCMR1_OC1M_PWM_MODE_1 | STM32_TIM_CCMR1_OC1PE; + STM32_TIM_CCMR1(16) = STM32_TIM_CCMR1_OC1M_PWM_MODE_1 | + STM32_TIM_CCMR1_OC1PE; + STM32_TIM_CCMR1(17) = STM32_TIM_CCMR1_OC1M_PWM_MODE_1 | + STM32_TIM_CCMR1_OC1PE; /* * Enable output compare 1 (or its N counterpart). Note that if only @@ -335,12 +334,11 @@ static int command_enable_ite_dfu(int argc, char **argv) return cprint_ite_chip_id(); } -DECLARE_CONSOLE_COMMAND( - enable_ite_dfu, command_enable_ite_dfu, "", - "Enable ITE Direct Firmware Update (DFU) mode"); +DECLARE_CONSOLE_COMMAND(enable_ite_dfu, command_enable_ite_dfu, "", + "Enable ITE Direct Firmware Update (DFU) mode"); /* Read ITE chip ID. Can be used to verify ITE DFU mode. */ -static int command_get_ite_chipid(int argc, char **argv) +static int command_get_ite_chipid(int argc, const char **argv) { if (argc > 1) return EC_ERROR_PARAM_COUNT; diff --git a/chip/stm32/keyboard_raw.c b/chip/stm32/keyboard_raw.c index 219676968a..c3244c19f7 100644 --- a/chip/stm32/keyboard_raw.c +++ b/chip/stm32/keyboard_raw.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -86,12 +86,12 @@ test_mockable void keyboard_raw_drive_column(int out) } } - #ifdef CONFIG_KEYBOARD_COL2_INVERTED +#ifdef CONFIG_KEYBOARD_COL2_INVERTED if (bsrr & (gpio_list[GPIO_KB_OUT02].mask << 16 | - gpio_list[GPIO_KB_OUT02].mask)) + gpio_list[GPIO_KB_OUT02].mask)) bsrr ^= (gpio_list[GPIO_KB_OUT02].mask << 16 | gpio_list[GPIO_KB_OUT02].mask); - #endif +#endif if (bsrr) STM32_GPIO_BSRR(kb_out_ports[i]) = bsrr; @@ -131,9 +131,9 @@ void keyboard_raw_enable_interrupt(int enable) * Clear them before enable interrupt. */ STM32_EXTI_PR |= irq_mask; - STM32_EXTI_IMR |= irq_mask; /* 1: unmask interrupt */ + STM32_EXTI_IMR |= irq_mask; /* 1: unmask interrupt */ } else { - STM32_EXTI_IMR &= ~irq_mask; /* 0: mask interrupts */ + STM32_EXTI_IMR &= ~irq_mask; /* 0: mask interrupts */ } } diff --git a/chip/stm32/memory_regions.inc b/chip/stm32/memory_regions.inc index 2381c511f2..8c8e666f71 100644 --- a/chip/stm32/memory_regions.inc +++ b/chip/stm32/memory_regions.inc @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/stm32/otp-stm32f4.c b/chip/stm32/otp-stm32f4.c index a993af7042..ff6280ed20 100644 --- a/chip/stm32/otp-stm32f4.c +++ b/chip/stm32/otp-stm32f4.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,8 +18,7 @@ #ifdef CONFIG_SERIALNO_LEN /* Which block to use */ #define OTP_SERIAL_BLOCK 0 -#define OTP_SERIAL_ADDR \ - REG32_ADDR(STM32_OTP_BLOCK_DATA(OTP_SERIAL_BLOCK, 0)) +#define OTP_SERIAL_ADDR REG32_ADDR(STM32_OTP_BLOCK_DATA(OTP_SERIAL_BLOCK, 0)) /* Number of word used in the block */ #define OTP_SERIAL_BLOCK_SIZE (CONFIG_SERIALNO_LEN / sizeof(uint32_t)) @@ -39,9 +38,9 @@ static int otp_write(uint8_t block, int size, const char *data) return EC_ERROR_PARAM1; if (size >= STM32_OTP_BLOCK_SIZE) return EC_ERROR_PARAM2; - return flash_physical_write(STM32_OTP_BLOCK_DATA(block, 0) - - CONFIG_PROGRAM_MEMORY_BASE, - size * sizeof(uint32_t), data); + return crec_flash_physical_write(STM32_OTP_BLOCK_DATA(block, 0) - + CONFIG_PROGRAM_MEMORY_BASE, + size * sizeof(uint32_t), data); } /* @@ -73,9 +72,9 @@ static int otp_set_protect(uint8_t block) lock = REG32(STM32_OTP_LOCK(block)); lock &= ~STM32_OPT_LOCK_MASK(block); - rv = flash_physical_write(STM32_OTP_LOCK(block) - - CONFIG_PROGRAM_MEMORY_BASE, - sizeof(uint32_t), (char *)&lock); + rv = crec_flash_physical_write(STM32_OTP_LOCK(block) - + CONFIG_PROGRAM_MEMORY_BASE, + sizeof(uint32_t), (char *)&lock); if (rv) return rv; else diff --git a/chip/stm32/power_led.c b/chip/stm32/power_led.c index 508745199f..579925fff9 100644 --- a/chip/stm32/power_led.c +++ b/chip/stm32/power_led.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,6 +15,7 @@ * results in a breathing effect. It takes about 2sec for a full cycle. */ +#include "builtin/assert.h" #include "clock.h" #include "console.h" #include "gpio.h" @@ -28,9 +29,9 @@ #include "timer.h" #include "util.h" -#define LED_STATE_TIMEOUT_MIN (15 * MSEC) /* Minimum of 15ms per step */ -#define LED_HOLD_TIME (330 * MSEC) /* Hold for 330ms at min/max */ -#define LED_STEP_PERCENT 4 /* Incremental value of each step */ +#define LED_STATE_TIMEOUT_MIN (15 * MSEC) /* Minimum of 15ms per step */ +#define LED_HOLD_TIME (330 * MSEC) /* Hold for 330ms at min/max */ +#define LED_STEP_PERCENT 4 /* Incremental value of each step */ static enum powerled_state led_state = POWERLED_STATE_ON; static int power_led_percent = 100; @@ -86,7 +87,8 @@ static int power_led_step(void) * Decreases timeout as duty cycle percentage approaches * 0%, increase as it approaches 100%. */ - state_timeout = LED_STATE_TIMEOUT_MIN + + state_timeout = + LED_STATE_TIMEOUT_MIN + LED_STATE_TIMEOUT_MIN * (power_led_percent / 33); } @@ -137,7 +139,7 @@ void power_led_task(void) #define CONFIG_CMD_POWERLED #ifdef CONFIG_CMD_POWERLED -static int command_powerled(int argc, char **argv) +static int command_powerled(int argc, const char **argv) { enum powerled_state state; @@ -156,7 +158,6 @@ static int command_powerled(int argc, char **argv) powerled_set_state(state); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(powerled, command_powerled, - "[off | on | suspend]", - "Change power LED state"); +DECLARE_CONSOLE_COMMAND(powerled, command_powerled, "[off | on | suspend]", + "Change power LED state"); #endif diff --git a/chip/stm32/pwm.c b/chip/stm32/pwm.c index ce9c4ae04b..bf32793c64 100644 --- a/chip/stm32/pwm.c +++ b/chip/stm32/pwm.c @@ -1,12 +1,13 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* PWM control module for STM32 */ -#include "clock.h" +#include "builtin/assert.h" #include "clock-f.h" +#include "clock.h" #include "gpio.h" #include "hooks.h" #include "hwtimer.h" @@ -17,7 +18,7 @@ #include "util.h" /* Bitmap of currently active PWM channels. 1 bit per channel. */ -static uint32_t using_pwm; +static atomic_t using_pwm; void pwm_set_duty(enum pwm_channel ch, int percent) { @@ -39,7 +40,7 @@ static void pwm_configure(enum pwm_channel ch) { const struct pwm_t *pwm = pwm_channels + ch; timer_ctlr_t *tim = (timer_ctlr_t *)(pwm->tim.base); - volatile unsigned *ccmr = NULL; + volatile unsigned int *ccmr = NULL; /* Default frequency = 100 Hz */ int frequency = pwm->frequency ? pwm->frequency : 100; uint16_t ccer; @@ -99,7 +100,7 @@ static void pwm_configure(enum pwm_channel ch) /* Enable auto-reload preload, start counting */ tim->cr1 |= BIT(7) | BIT(0); - deprecated_atomic_or(&using_pwm, 1 << ch); + atomic_or(&using_pwm, 1 << ch); /* Prevent sleep */ disable_sleep(SLEEP_MASK_PWM); @@ -125,7 +126,7 @@ static void pwm_disable(enum pwm_channel ch) /* Allow sleep */ enable_sleep(SLEEP_MASK_PWM); - deprecated_atomic_clear_bits(&using_pwm, 1 << ch); + atomic_clear_bits(&using_pwm, 1 << ch); /* Unless another PWM is active... Then prevent sleep */ if (using_pwm) @@ -147,7 +148,7 @@ int pwm_get_enabled(enum pwm_channel ch) static void pwm_reconfigure(enum pwm_channel ch) { - deprecated_atomic_clear_bits(&using_pwm, 1 << ch); + atomic_clear_bits(&using_pwm, 1 << ch); pwm_configure(ch); } diff --git a/chip/stm32/pwm_chip.h b/chip/stm32/pwm_chip.h index baa793090a..7269072ac2 100644 --- a/chip/stm32/pwm_chip.h +++ b/chip/stm32/pwm_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -29,7 +29,10 @@ struct pwm_t { extern const struct pwm_t pwm_channels[]; /* Macro to fill in both timer ID and register base */ -#define STM32_TIM(x) {x, STM32_TIM_BASE(x)} +#define STM32_TIM(x) \ + { \ + x, STM32_TIM_BASE(x) \ + } /* Plain ID mapping for readability */ #define STM32_TIM_CH(x) (x) diff --git a/chip/stm32/registers-stm32f0.h b/chip/stm32/registers-stm32f0.h index 442edaed9a..6d1907e48a 100644 --- a/chip/stm32/registers-stm32f0.h +++ b/chip/stm32/registers-stm32f0.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -23,407 +23,402 @@ #endif /* --- IRQ numbers --- */ -#define STM32_IRQ_WWDG 0 -#define STM32_IRQ_PVD 1 -#define STM32_IRQ_RTC_WAKEUP 2 -#define STM32_IRQ_RTC_ALARM 2 -#define STM32_IRQ_FLASH 3 -#define STM32_IRQ_RCC 4 -#define STM32_IRQ_EXTI0_1 5 -#define STM32_IRQ_EXTI2_3 6 -#define STM32_IRQ_EXTI4_15 7 -#define STM32_IRQ_TSC 8 -#define STM32_IRQ_DMA_CHANNEL_1 9 +#define STM32_IRQ_WWDG 0 +#define STM32_IRQ_PVD 1 +#define STM32_IRQ_RTC_WAKEUP 2 +#define STM32_IRQ_RTC_ALARM 2 +#define STM32_IRQ_FLASH 3 +#define STM32_IRQ_RCC 4 +#define STM32_IRQ_EXTI0_1 5 +#define STM32_IRQ_EXTI2_3 6 +#define STM32_IRQ_EXTI4_15 7 +#define STM32_IRQ_TSC 8 +#define STM32_IRQ_DMA_CHANNEL_1 9 #define STM32_IRQ_DMA_CHANNEL_2_3 10 #define STM32_IRQ_DMA_CHANNEL_4_7 11 -#define STM32_IRQ_ADC_COMP 12 +#define STM32_IRQ_ADC_COMP 12 #define STM32_IRQ_TIM1_BRK_UP_TRG 13 -#define STM32_IRQ_TIM1_CC 14 -#define STM32_IRQ_TIM2 15 -#define STM32_IRQ_TIM3 16 -#define STM32_IRQ_TIM6_DAC 17 -#define STM32_IRQ_TIM7 18 -#define STM32_IRQ_TIM14 19 -#define STM32_IRQ_TIM15 20 -#define STM32_IRQ_TIM16 21 -#define STM32_IRQ_TIM17 22 -#define STM32_IRQ_I2C1 23 -#define STM32_IRQ_I2C2 24 -#define STM32_IRQ_SPI1 25 -#define STM32_IRQ_SPI2 26 -#define STM32_IRQ_USART1 27 -#define STM32_IRQ_USART2 28 -#define STM32_IRQ_USART3_4 29 -#define STM32_IRQ_CEC_CAN 30 -#define STM32_IRQ_USB 31 +#define STM32_IRQ_TIM1_CC 14 +#define STM32_IRQ_TIM2 15 +#define STM32_IRQ_TIM3 16 +#define STM32_IRQ_TIM6_DAC 17 +#define STM32_IRQ_TIM7 18 +#define STM32_IRQ_TIM14 19 +#define STM32_IRQ_TIM15 20 +#define STM32_IRQ_TIM16 21 +#define STM32_IRQ_TIM17 22 +#define STM32_IRQ_I2C1 23 +#define STM32_IRQ_I2C2 24 +#define STM32_IRQ_SPI1 25 +#define STM32_IRQ_SPI2 26 +#define STM32_IRQ_USART1 27 +#define STM32_IRQ_USART2 28 +#define STM32_IRQ_USART3_4 29 +#define STM32_IRQ_CEC_CAN 30 +#define STM32_IRQ_USB 31 /* aliases for easier code sharing */ #define STM32_IRQ_COMP STM32_IRQ_ADC_COMP #define STM32_IRQ_USB_LP STM32_IRQ_USB - - /* Peripheral base addresses */ -#define STM32_ADC1_BASE 0x40012400 -#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */ +#define STM32_ADC1_BASE 0x40012400 +#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */ -#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ -#define STM32_CRC_BASE 0x40023000 -#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ -#define STM32_DAC_BASE 0x40007400 +#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ +#define STM32_CRC_BASE 0x40023000 +#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ +#define STM32_DAC_BASE 0x40007400 -#define STM32_COMP_BASE 0x40010000 +#define STM32_COMP_BASE 0x40010000 -#define STM32_DBGMCU_BASE 0x40015800 +#define STM32_DBGMCU_BASE 0x40015800 -#define STM32_DMA1_BASE 0x40020000 -#define STM32_DMA2_BASE 0x40020400 +#define STM32_DMA1_BASE 0x40020000 +#define STM32_DMA2_BASE 0x40020400 -#define STM32_EXTI_BASE 0x40010400 +#define STM32_EXTI_BASE 0x40010400 -#define STM32_FLASH_REGS_BASE 0x40022000 +#define STM32_FLASH_REGS_BASE 0x40022000 -#define STM32_GPIOA_BASE 0x48000000 -#define STM32_GPIOB_BASE 0x48000400 -#define STM32_GPIOC_BASE 0x48000800 -#define STM32_GPIOD_BASE 0x48000C00 -#define STM32_GPIOE_BASE 0x48001000 -#define STM32_GPIOF_BASE 0x48001400 -#define STM32_GPIOG_BASE 0x48001800 /* only for stm32l4x6 */ -#define STM32_GPIOH_BASE 0x48001C00 /* only for stm32l4 */ +#define STM32_GPIOA_BASE 0x48000000 +#define STM32_GPIOB_BASE 0x48000400 +#define STM32_GPIOC_BASE 0x48000800 +#define STM32_GPIOD_BASE 0x48000C00 +#define STM32_GPIOE_BASE 0x48001000 +#define STM32_GPIOF_BASE 0x48001400 +#define STM32_GPIOG_BASE 0x48001800 /* only for stm32l4x6 */ +#define STM32_GPIOH_BASE 0x48001C00 /* only for stm32l4 */ -#define STM32_I2C1_BASE 0x40005400 -#define STM32_I2C2_BASE 0x40005800 -#define STM32_I2C3_BASE 0x40005C00 -#define STM32_I2C4_BASE 0x40006000 +#define STM32_I2C1_BASE 0x40005400 +#define STM32_I2C2_BASE 0x40005800 +#define STM32_I2C3_BASE 0x40005C00 +#define STM32_I2C4_BASE 0x40006000 -#define STM32_IWDG_BASE 0x40003000 -#define STM32_LCD_BASE 0x40002400 +#define STM32_IWDG_BASE 0x40003000 +#define STM32_LCD_BASE 0x40002400 -#define STM32_OPTB_BASE 0x1FFFF800 +#define STM32_OPTB_BASE 0x1FFFF800 -#define STM32_PMSE_BASE 0x40013400 -#define STM32_PWR_BASE 0x40007000 +#define STM32_PMSE_BASE 0x40013400 +#define STM32_PWR_BASE 0x40007000 -#define STM32_RCC_BASE 0x40021000 +#define STM32_RCC_BASE 0x40021000 -#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ -#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ -#define STM32_RTC_BASE 0x40002800 +#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ +#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ +#define STM32_RTC_BASE 0x40002800 -#define STM32_SPI1_BASE 0x40013000 -#define STM32_SPI2_BASE 0x40003800 -#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ +#define STM32_SPI1_BASE 0x40013000 +#define STM32_SPI2_BASE 0x40003800 +#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ -#define STM32_SYSCFG_BASE 0x40010000 +#define STM32_SYSCFG_BASE 0x40010000 -#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ -#define STM32_TIM2_BASE 0x40000000 -#define STM32_TIM3_BASE 0x40000400 -#define STM32_TIM4_BASE 0x40000800 -#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ -#define STM32_TIM6_BASE 0x40001000 -#define STM32_TIM7_BASE 0x40001400 -#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ -#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ -#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ -#define STM32_TIM15_BASE 0x40014000 -#define STM32_TIM16_BASE 0x40014400 -#define STM32_TIM17_BASE 0x40014800 -#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ -#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ +#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ +#define STM32_TIM2_BASE 0x40000000 +#define STM32_TIM3_BASE 0x40000400 +#define STM32_TIM4_BASE 0x40000800 +#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ +#define STM32_TIM6_BASE 0x40001000 +#define STM32_TIM7_BASE 0x40001400 +#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ +#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ +#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ +#define STM32_TIM15_BASE 0x40014000 +#define STM32_TIM16_BASE 0x40014400 +#define STM32_TIM17_BASE 0x40014800 +#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ +#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ -#define STM32_UNIQUE_ID_BASE 0x1ffff7ac +#define STM32_UNIQUE_ID_BASE 0x1ffff7ac -#define STM32_USART1_BASE 0x40013800 -#define STM32_USART2_BASE 0x40004400 -#define STM32_USART3_BASE 0x40004800 -#define STM32_USART4_BASE 0x40004c00 -#define STM32_USART9_BASE 0x40008000 /* LPUART */ +#define STM32_USART1_BASE 0x40013800 +#define STM32_USART2_BASE 0x40004400 +#define STM32_USART3_BASE 0x40004800 +#define STM32_USART4_BASE 0x40004c00 +#define STM32_USART9_BASE 0x40008000 /* LPUART */ -#define STM32_USB_CAN_SRAM_BASE 0x40006000 -#define STM32_USB_FS_BASE 0x40005C00 - -#define STM32_WWDG_BASE 0x40002C00 +#define STM32_USB_CAN_SRAM_BASE 0x40006000 +#define STM32_USB_FS_BASE 0x40005C00 +#define STM32_WWDG_BASE 0x40002C00 #ifndef __ASSEMBLER__ /* Register definitions */ /* --- USART --- */ -#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) -#define STM32_USART_CR1_UE BIT(0) -#define STM32_USART_CR1_UESM BIT(1) -#define STM32_USART_CR1_RE BIT(2) -#define STM32_USART_CR1_TE BIT(3) -#define STM32_USART_CR1_RXNEIE BIT(5) -#define STM32_USART_CR1_TCIE BIT(6) -#define STM32_USART_CR1_TXEIE BIT(7) -#define STM32_USART_CR1_PS BIT(9) -#define STM32_USART_CR1_PCE BIT(10) -#define STM32_USART_CR1_M BIT(12) -#define STM32_USART_CR1_OVER8 BIT(15) -#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) -#define STM32_USART_CR2_SWAP BIT(15) -#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) -#define STM32_USART_CR3_EIE BIT(0) -#define STM32_USART_CR3_DMAR BIT(6) -#define STM32_USART_CR3_DMAT BIT(7) -#define STM32_USART_CR3_ONEBIT BIT(11) -#define STM32_USART_CR3_OVRDIS BIT(12) -#define STM32_USART_CR3_WUS_START_BIT (2 << 20) -#define STM32_USART_CR3_WUFIE BIT(22) -#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) -#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) -#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) -#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) -#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) -#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) -#define STM32_USART_ICR_ORECF BIT(3) -#define STM32_USART_ICR_TCCF BIT(6) -#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) -#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) -#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) +#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) +#define STM32_USART_CR1_UE BIT(0) +#define STM32_USART_CR1_UESM BIT(1) +#define STM32_USART_CR1_RE BIT(2) +#define STM32_USART_CR1_TE BIT(3) +#define STM32_USART_CR1_RXNEIE BIT(5) +#define STM32_USART_CR1_TCIE BIT(6) +#define STM32_USART_CR1_TXEIE BIT(7) +#define STM32_USART_CR1_PS BIT(9) +#define STM32_USART_CR1_PCE BIT(10) +#define STM32_USART_CR1_M BIT(12) +#define STM32_USART_CR1_OVER8 BIT(15) +#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) +#define STM32_USART_CR2_SWAP BIT(15) +#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) +#define STM32_USART_CR3_EIE BIT(0) +#define STM32_USART_CR3_DMAR BIT(6) +#define STM32_USART_CR3_DMAT BIT(7) +#define STM32_USART_CR3_ONEBIT BIT(11) +#define STM32_USART_CR3_OVRDIS BIT(12) +#define STM32_USART_CR3_WUS_START_BIT (2 << 20) +#define STM32_USART_CR3_WUFIE BIT(22) +#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) +#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) +#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) +#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) +#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) +#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) +#define STM32_USART_ICR_ORECF BIT(3) +#define STM32_USART_ICR_TCCF BIT(6) +#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) +#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) +#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) /* register alias */ -#define STM32_USART_SR(base) STM32_USART_ISR(base) -#define STM32_USART_SR_ORE BIT(3) -#define STM32_USART_SR_RXNE BIT(5) -#define STM32_USART_SR_TC BIT(6) -#define STM32_USART_SR_TXE BIT(7) +#define STM32_USART_SR(base) STM32_USART_ISR(base) +#define STM32_USART_SR_ORE BIT(3) +#define STM32_USART_SR_RXNE BIT(5) +#define STM32_USART_SR_TC BIT(6) +#define STM32_USART_SR_TXE BIT(7) /* --- GPIO --- */ -#define STM32_GPIO_MODER(b) REG32((b) + 0x00) -#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) -#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) -#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) -#define STM32_GPIO_IDR(b) REG16((b) + 0x10) -#define STM32_GPIO_ODR(b) REG16((b) + 0x14) -#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) -#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) -#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) -#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) -#define STM32_GPIO_BRR(b) REG32((b) + 0x28) -#define STM32_GPIO_ASCR(b) REG32((b) + 0x2C) /* only for stm32l4 */ - -#define GPIO_ALT_F0 0x0 -#define GPIO_ALT_F1 0x1 -#define GPIO_ALT_F2 0x2 -#define GPIO_ALT_F3 0x3 -#define GPIO_ALT_F4 0x4 -#define GPIO_ALT_F5 0x5 -#define GPIO_ALT_F6 0x6 -#define GPIO_ALT_F7 0x7 -#define GPIO_ALT_F8 0x8 -#define GPIO_ALT_F9 0x9 -#define GPIO_ALT_FA 0xA -#define GPIO_ALT_FB 0xB -#define GPIO_ALT_FC 0xC -#define GPIO_ALT_FD 0xD -#define GPIO_ALT_FE 0xE -#define GPIO_ALT_FF 0xF +#define STM32_GPIO_MODER(b) REG32((b) + 0x00) +#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) +#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) +#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) +#define STM32_GPIO_IDR(b) REG16((b) + 0x10) +#define STM32_GPIO_ODR(b) REG16((b) + 0x14) +#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) +#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) +#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) +#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) +#define STM32_GPIO_BRR(b) REG32((b) + 0x28) +#define STM32_GPIO_ASCR(b) REG32((b) + 0x2C) /* only for stm32l4 */ + +#define GPIO_ALT_F0 0x0 +#define GPIO_ALT_F1 0x1 +#define GPIO_ALT_F2 0x2 +#define GPIO_ALT_F3 0x3 +#define GPIO_ALT_F4 0x4 +#define GPIO_ALT_F5 0x5 +#define GPIO_ALT_F6 0x6 +#define GPIO_ALT_F7 0x7 +#define GPIO_ALT_F8 0x8 +#define GPIO_ALT_F9 0x9 +#define GPIO_ALT_FA 0xA +#define GPIO_ALT_FB 0xB +#define GPIO_ALT_FC 0xC +#define GPIO_ALT_FD 0xD +#define GPIO_ALT_FE 0xE +#define GPIO_ALT_FF 0xF /* --- I2C --- */ -#define STM32_I2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) -#define STM32_I2C_CR1_PE BIT(0) -#define STM32_I2C_CR1_TXIE BIT(1) -#define STM32_I2C_CR1_RXIE BIT(2) -#define STM32_I2C_CR1_ADDRIE BIT(3) -#define STM32_I2C_CR1_NACKIE BIT(4) -#define STM32_I2C_CR1_STOPIE BIT(5) -#define STM32_I2C_CR1_ERRIE BIT(7) -#define STM32_I2C_CR1_WUPEN BIT(18) -#define STM32_I2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) -#define STM32_I2C_CR2_RD_WRN BIT(10) -#define STM32_I2C_CR2_START BIT(13) -#define STM32_I2C_CR2_STOP BIT(14) -#define STM32_I2C_CR2_NACK BIT(15) -#define STM32_I2C_CR2_RELOAD BIT(24) -#define STM32_I2C_CR2_AUTOEND BIT(25) -#define STM32_I2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) -#define STM32_I2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) -#define STM32_I2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) -#define STM32_I2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) -#define STM32_I2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) -#define STM32_I2C_ISR_TXE BIT(0) -#define STM32_I2C_ISR_TXIS BIT(1) -#define STM32_I2C_ISR_RXNE BIT(2) -#define STM32_I2C_ISR_ADDR BIT(3) -#define STM32_I2C_ISR_NACK BIT(4) -#define STM32_I2C_ISR_STOP BIT(5) -#define STM32_I2C_ISR_TC BIT(6) -#define STM32_I2C_ISR_TCR BIT(7) -#define STM32_I2C_ISR_BERR BIT(8) -#define STM32_I2C_ISR_ARLO BIT(9) -#define STM32_I2C_ISR_OVR BIT(10) -#define STM32_I2C_ISR_PECERR BIT(11) -#define STM32_I2C_ISR_TIMEOUT BIT(12) -#define STM32_I2C_ISR_ALERT BIT(13) -#define STM32_I2C_ISR_BUSY BIT(15) -#define STM32_I2C_ISR_DIR BIT(16) -#define STM32_I2C_ISR_ADDCODE(isr) (((isr) >> 16) & 0xfe) -#define STM32_I2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) -#define STM32_I2C_ICR_ADDRCF BIT(3) -#define STM32_I2C_ICR_NACKCF BIT(4) -#define STM32_I2C_ICR_STOPCF BIT(5) -#define STM32_I2C_ICR_BERRCF BIT(8) -#define STM32_I2C_ICR_ARLOCF BIT(9) -#define STM32_I2C_ICR_OVRCF BIT(10) -#define STM32_I2C_ICR_TIMEOUTCF BIT(12) -#define STM32_I2C_ICR_ALL 0x3F38 -#define STM32_I2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) -#define STM32_I2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) -#define STM32_I2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) - +#define STM32_I2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) +#define STM32_I2C_CR1_PE BIT(0) +#define STM32_I2C_CR1_TXIE BIT(1) +#define STM32_I2C_CR1_RXIE BIT(2) +#define STM32_I2C_CR1_ADDRIE BIT(3) +#define STM32_I2C_CR1_NACKIE BIT(4) +#define STM32_I2C_CR1_STOPIE BIT(5) +#define STM32_I2C_CR1_ERRIE BIT(7) +#define STM32_I2C_CR1_WUPEN BIT(18) +#define STM32_I2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) +#define STM32_I2C_CR2_RD_WRN BIT(10) +#define STM32_I2C_CR2_START BIT(13) +#define STM32_I2C_CR2_STOP BIT(14) +#define STM32_I2C_CR2_NACK BIT(15) +#define STM32_I2C_CR2_RELOAD BIT(24) +#define STM32_I2C_CR2_AUTOEND BIT(25) +#define STM32_I2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) +#define STM32_I2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) +#define STM32_I2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) +#define STM32_I2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) +#define STM32_I2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) +#define STM32_I2C_ISR_TXE BIT(0) +#define STM32_I2C_ISR_TXIS BIT(1) +#define STM32_I2C_ISR_RXNE BIT(2) +#define STM32_I2C_ISR_ADDR BIT(3) +#define STM32_I2C_ISR_NACK BIT(4) +#define STM32_I2C_ISR_STOP BIT(5) +#define STM32_I2C_ISR_TC BIT(6) +#define STM32_I2C_ISR_TCR BIT(7) +#define STM32_I2C_ISR_BERR BIT(8) +#define STM32_I2C_ISR_ARLO BIT(9) +#define STM32_I2C_ISR_OVR BIT(10) +#define STM32_I2C_ISR_PECERR BIT(11) +#define STM32_I2C_ISR_TIMEOUT BIT(12) +#define STM32_I2C_ISR_ALERT BIT(13) +#define STM32_I2C_ISR_BUSY BIT(15) +#define STM32_I2C_ISR_DIR BIT(16) +#define STM32_I2C_ISR_ADDCODE(isr) (((isr) >> 16) & 0xfe) +#define STM32_I2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) +#define STM32_I2C_ICR_ADDRCF BIT(3) +#define STM32_I2C_ICR_NACKCF BIT(4) +#define STM32_I2C_ICR_STOPCF BIT(5) +#define STM32_I2C_ICR_BERRCF BIT(8) +#define STM32_I2C_ICR_ARLOCF BIT(9) +#define STM32_I2C_ICR_OVRCF BIT(10) +#define STM32_I2C_ICR_TIMEOUTCF BIT(12) +#define STM32_I2C_ICR_ALL 0x3F38 +#define STM32_I2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) +#define STM32_I2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) +#define STM32_I2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) /* --- Power / Reset / Clocks --- */ -#define STM32_PWR_CR REG32(STM32_PWR_BASE + 0x00) -#define STM32_PWD_PVD_LS_MASK (0x07 << 5) -#define STM32_PWD_PVD_LS(n) ((n & 0x07) << 5) -#define STM32_PWR_PVDE BIT(4) - -#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) - -#define STM32_PWR_CSR_EWUP1 BIT(8) -#define STM32_PWR_CSR_EWUP2 BIT(9) -#define STM32_PWR_CSR_EWUP3 BIT(10) -#define STM32_PWR_CSR_EWUP4 BIT(11) /* STM32F0xx only */ -#define STM32_PWR_CSR_EWUP5 BIT(12) /* STM32F0xx only */ -#define STM32_PWR_CSR_EWUP6 BIT(13) /* STM32F0xx only */ -#define STM32_PWR_CSR_EWUP7 BIT(14) /* STM32F0xx only */ -#define STM32_PWR_CSR_EWUP8 BIT(15) /* STM32F0xx only */ - -#define STM32_CRS_CR REG32(STM32_CRS_BASE + 0x00) /* STM32F0XX */ -#define STM32_CRS_CR_SYNCOKIE BIT(0) -#define STM32_CRS_CR_SYNCWARNIE BIT(1) -#define STM32_CRS_CR_ERRIE BIT(2) -#define STM32_CRS_CR_ESYNCIE BIT(3) -#define STM32_CRS_CR_CEN BIT(5) -#define STM32_CRS_CR_AUTOTRIMEN BIT(6) -#define STM32_CRS_CR_SWSYNC BIT(7) -#define STM32_CRS_CR_TRIM(n) (((n) & 0x3f) << 8) - -#define STM32_CRS_CFGR REG32(STM32_CRS_BASE + 0x04) /* STM32F0XX */ -#define STM32_CRS_CFGR_RELOAD(n) (((n) & 0xffff) << 0) -#define STM32_CRS_CFGR_FELIM(n) (((n) & 0xff) << 16) -#define STM32_CRS_CFGR_SYNCDIV(n) (((n) & 7) << 24) -#define STM32_CRS_CFGR_SYNCSRC(n) (((n) & 3) << 28) -#define STM32_CRS_CFGR_SYNCPOL BIT(31) - -#define STM32_CRS_ISR REG32(STM32_CRS_BASE + 0x08) /* STM32F0XX */ -#define STM32_CRS_ISR_SYNCOKF BIT(0) -#define STM32_CRS_ISR_SYNCWARNF BIT(1) -#define STM32_CRS_ISR_ERRF BIT(2) -#define STM32_CRS_ISR_ESYNCF BIT(3) -#define STM32_CRS_ISR_SYNCERR BIT(8) -#define STM32_CRS_ISR_SYNCMISS BIT(9) -#define STM32_CRS_ISR_TRIMOVF BIT(10) -#define STM32_CRS_ISR_FEDIR BIT(15) -#define STM32_CRS_ISR_FECAP (0xffff << 16) - -#define STM32_CRS_ICR REG32(STM32_CRS_BASE + 0x0c) /* STM32F0XX */ -#define STM32_CRS_ICR_SYNCOKC BIT(0) -#define STM32_CRS_ICR_SYNCWARINC BIT(1) -#define STM32_CRS_ICR_ERRC BIT(2) -#define STM32_CRS_ICR_ESYNCC BIT(3) - -#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) -#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x04) -#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x08) -#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x0c) -#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x10) -#define STM32_RCC_AHBENR REG32(STM32_RCC_BASE + 0x14) -#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x18) -#define STM32_RCC_APB2ENR_ADCEN BIT(9) /* STM32F3/F0 */ -#define STM32_RCC_APB2ENR_TIM16EN BIT(17) -#define STM32_RCC_APB2ENR_TIM17EN BIT(18) -#define STM32_RCC_DBGMCUEN BIT(22) -#define STM32_RCC_SYSCFGEN BIT(0) - -#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x1c) -#define STM32_RCC_DACEN BIT(29) -#define STM32_RCC_PWREN BIT(28) - -#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x20) -#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x24) +#define STM32_PWR_CR REG32(STM32_PWR_BASE + 0x00) +#define STM32_PWD_PVD_LS_MASK (0x07 << 5) +#define STM32_PWD_PVD_LS(n) ((n & 0x07) << 5) +#define STM32_PWR_PVDE BIT(4) + +#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) + +#define STM32_PWR_CSR_EWUP1 BIT(8) +#define STM32_PWR_CSR_EWUP2 BIT(9) +#define STM32_PWR_CSR_EWUP3 BIT(10) +#define STM32_PWR_CSR_EWUP4 BIT(11) /* STM32F0xx only */ +#define STM32_PWR_CSR_EWUP5 BIT(12) /* STM32F0xx only */ +#define STM32_PWR_CSR_EWUP6 BIT(13) /* STM32F0xx only */ +#define STM32_PWR_CSR_EWUP7 BIT(14) /* STM32F0xx only */ +#define STM32_PWR_CSR_EWUP8 BIT(15) /* STM32F0xx only */ + +#define STM32_CRS_CR REG32(STM32_CRS_BASE + 0x00) /* STM32F0XX */ +#define STM32_CRS_CR_SYNCOKIE BIT(0) +#define STM32_CRS_CR_SYNCWARNIE BIT(1) +#define STM32_CRS_CR_ERRIE BIT(2) +#define STM32_CRS_CR_ESYNCIE BIT(3) +#define STM32_CRS_CR_CEN BIT(5) +#define STM32_CRS_CR_AUTOTRIMEN BIT(6) +#define STM32_CRS_CR_SWSYNC BIT(7) +#define STM32_CRS_CR_TRIM(n) (((n)&0x3f) << 8) + +#define STM32_CRS_CFGR REG32(STM32_CRS_BASE + 0x04) /* STM32F0XX */ +#define STM32_CRS_CFGR_RELOAD(n) (((n)&0xffff) << 0) +#define STM32_CRS_CFGR_FELIM(n) (((n)&0xff) << 16) +#define STM32_CRS_CFGR_SYNCDIV(n) (((n)&7) << 24) +#define STM32_CRS_CFGR_SYNCSRC(n) (((n)&3) << 28) +#define STM32_CRS_CFGR_SYNCPOL BIT(31) + +#define STM32_CRS_ISR REG32(STM32_CRS_BASE + 0x08) /* STM32F0XX */ +#define STM32_CRS_ISR_SYNCOKF BIT(0) +#define STM32_CRS_ISR_SYNCWARNF BIT(1) +#define STM32_CRS_ISR_ERRF BIT(2) +#define STM32_CRS_ISR_ESYNCF BIT(3) +#define STM32_CRS_ISR_SYNCERR BIT(8) +#define STM32_CRS_ISR_SYNCMISS BIT(9) +#define STM32_CRS_ISR_TRIMOVF BIT(10) +#define STM32_CRS_ISR_FEDIR BIT(15) +#define STM32_CRS_ISR_FECAP (0xffff << 16) + +#define STM32_CRS_ICR REG32(STM32_CRS_BASE + 0x0c) /* STM32F0XX */ +#define STM32_CRS_ICR_SYNCOKC BIT(0) +#define STM32_CRS_ICR_SYNCWARINC BIT(1) +#define STM32_CRS_ICR_ERRC BIT(2) +#define STM32_CRS_ICR_ESYNCC BIT(3) + +#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) +#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x04) +#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x08) +#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x0c) +#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x10) +#define STM32_RCC_AHBENR REG32(STM32_RCC_BASE + 0x14) +#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x18) +#define STM32_RCC_APB2ENR_ADCEN BIT(9) /* STM32F3/F0 */ +#define STM32_RCC_APB2ENR_TIM16EN BIT(17) +#define STM32_RCC_APB2ENR_TIM17EN BIT(18) +#define STM32_RCC_DBGMCUEN BIT(22) +#define STM32_RCC_SYSCFGEN BIT(0) + +#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x1c) +#define STM32_RCC_DACEN BIT(29) +#define STM32_RCC_PWREN BIT(28) + +#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x20) +#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x24) /* STM32F373 */ -#define STM32_RCC_CFGR2 REG32(STM32_RCC_BASE + 0x2c) +#define STM32_RCC_CFGR2 REG32(STM32_RCC_BASE + 0x2c) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_CFGR3 REG32(STM32_RCC_BASE + 0x30) -#define STM32_RCC_CR2 REG32(STM32_RCC_BASE + 0x34) /* STM32F0XX */ +#define STM32_RCC_CFGR3 REG32(STM32_RCC_BASE + 0x30) +#define STM32_RCC_CR2 REG32(STM32_RCC_BASE + 0x34) /* STM32F0XX */ -#define STM32_RCC_HB_DMA1 BIT(0) +#define STM32_RCC_HB_DMA1 BIT(0) /* STM32F373 */ -#define STM32_RCC_HB_DMA2 BIT(1) -#define STM32_RCC_PB2_TIM1 BIT(11) /* Except STM32F373 */ -#define STM32_RCC_PB2_TIM15 BIT(16) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_PB2_TIM16 BIT(17) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_PB2_TIM17 BIT(18) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_PB2_TIM19 BIT(19) /* STM32F373 */ -#define STM32_RCC_PB2_PMAD BIT(11) /* STM32TS */ -#define STM32_RCC_PB2_PMSE BIT(13) /* STM32TS */ -#define STM32_RCC_PB1_TIM12 BIT(6) /* STM32F373 */ -#define STM32_RCC_PB1_TIM13 BIT(7) /* STM32F373 */ -#define STM32_RCC_PB1_TIM14 BIT(8) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_PB1_TIM18 BIT(9) /* STM32F373 */ -#define STM32_RCC_PB1_USB BIT(23) -#define STM32_RCC_PB1_CRS BIT(27) - -#define STM32_SYSCFG_CFGR1 REG32(STM32_SYSCFG_BASE + 0x00) -#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) -#define STM32_SYSCFG_CFGR2 REG32(STM32_SYSCFG_BASE + 0x18) - +#define STM32_RCC_HB_DMA2 BIT(1) +#define STM32_RCC_PB2_TIM1 BIT(11) /* Except STM32F373 */ +#define STM32_RCC_PB2_TIM15 BIT(16) /* STM32F0XX and STM32F373 */ +#define STM32_RCC_PB2_TIM16 BIT(17) /* STM32F0XX and STM32F373 */ +#define STM32_RCC_PB2_TIM17 BIT(18) /* STM32F0XX and STM32F373 */ +#define STM32_RCC_PB2_TIM19 BIT(19) /* STM32F373 */ +#define STM32_RCC_PB2_PMAD BIT(11) /* STM32TS */ +#define STM32_RCC_PB2_PMSE BIT(13) /* STM32TS */ +#define STM32_RCC_PB1_TIM12 BIT(6) /* STM32F373 */ +#define STM32_RCC_PB1_TIM13 BIT(7) /* STM32F373 */ +#define STM32_RCC_PB1_TIM14 BIT(8) /* STM32F0XX and STM32F373 */ +#define STM32_RCC_PB1_TIM18 BIT(9) /* STM32F373 */ +#define STM32_RCC_PB1_USB BIT(23) +#define STM32_RCC_PB1_CRS BIT(27) + +#define STM32_SYSCFG_CFGR1 REG32(STM32_SYSCFG_BASE + 0x00) +#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) +#define STM32_SYSCFG_CFGR2 REG32(STM32_SYSCFG_BASE + 0x18) /* Peripheral bits for RCC_APB/AHB and DBGMCU regs */ -#define STM32_RCC_PB2_USART1 BIT(14) +#define STM32_RCC_PB2_USART1 BIT(14) /* Reset causes definitions */ /* Reset causes in RCC CSR register */ #define STM32_RCC_RESET_CAUSE STM32_RCC_CSR -#define RESET_CAUSE_WDG 0x60000000 -#define RESET_CAUSE_SFT 0x10000000 -#define RESET_CAUSE_POR 0x08000000 -#define RESET_CAUSE_PIN 0x04000000 -#define RESET_CAUSE_OTHER 0xfe000000 -#define RESET_CAUSE_RMVF 0x01000000 +#define RESET_CAUSE_WDG 0x60000000 +#define RESET_CAUSE_SFT 0x10000000 +#define RESET_CAUSE_POR 0x08000000 +#define RESET_CAUSE_PIN 0x04000000 +#define RESET_CAUSE_OTHER 0xfe000000 +#define RESET_CAUSE_RMVF 0x01000000 /* Power cause in PWR CSR register */ -#define STM32_PWR_RESET_CAUSE STM32_PWR_CSR -#define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CR -#define RESET_CAUSE_SBF 0x00000002 -#define RESET_CAUSE_SBF_CLR 0x00000004 +#define STM32_PWR_RESET_CAUSE STM32_PWR_CSR +#define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CR +#define RESET_CAUSE_SBF 0x00000002 +#define RESET_CAUSE_SBF_CLR 0x00000004 /* --- Watchdogs --- */ /* --- Real-Time Clock --- */ -#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) -#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) -#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) -#define STM32_RTC_CR_BYPSHAD BIT(5) -#define STM32_RTC_CR_ALRAE BIT(8) -#define STM32_RTC_CR_ALRAIE BIT(12) -#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) -#define STM32_RTC_ISR_ALRAWF BIT(0) -#define STM32_RTC_ISR_RSF BIT(5) -#define STM32_RTC_ISR_INITF BIT(6) -#define STM32_RTC_ISR_INIT BIT(7) -#define STM32_RTC_ISR_ALRAF BIT(8) -#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) -#define STM32_RTC_PRER_A_MASK (0x7f << 16) -#define STM32_RTC_PRER_S_MASK (0x7fff << 0) -#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) -#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) -#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) -#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) -#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) -#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) -#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) -#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) -#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) -#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) -#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) - -#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) -#define STM32_BKP_BYTES 20 +#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) +#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) +#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) +#define STM32_RTC_CR_BYPSHAD BIT(5) +#define STM32_RTC_CR_ALRAE BIT(8) +#define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) +#define STM32_RTC_ISR_ALRAWF BIT(0) +#define STM32_RTC_ISR_RSF BIT(5) +#define STM32_RTC_ISR_INITF BIT(6) +#define STM32_RTC_ISR_INIT BIT(7) +#define STM32_RTC_ISR_ALRAF BIT(8) +#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) +#define STM32_RTC_PRER_A_MASK (0x7f << 16) +#define STM32_RTC_PRER_S_MASK (0x7fff << 0) +#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) +#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) +#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) +#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) +#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) +#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) +#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) +#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) +#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) +#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) +#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) + +#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) +#define STM32_BKP_BYTES 20 /* --- SPI --- */ @@ -433,15 +428,15 @@ struct stm32_spi_regs { uint16_t _pad0; uint16_t cr2; uint16_t _pad1; - unsigned sr; + unsigned int sr; uint8_t dr; uint8_t _pad2; uint16_t _pad3; - unsigned crcpr; - unsigned rxcrcr; - unsigned txcrcr; - unsigned i2scfgr; /* STM32L only */ - unsigned i2spr; /* STM32L only */ + unsigned int crcpr; + unsigned int rxcrcr; + unsigned int txcrcr; + unsigned int i2scfgr; /* STM32L only */ + unsigned int i2spr; /* STM32L only */ }; /* Must be volatile, or compiler optimizes out repeated accesses */ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; @@ -451,155 +446,154 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_SPI3_REGS ((stm32_spi_regs_t *)STM32_SPI3_BASE) #define STM32_SPI4_REGS ((stm32_spi_regs_t *)STM32_SPI4_BASE) -#define STM32_SPI_CR1_BIDIMODE BIT(15) -#define STM32_SPI_CR1_BIDIOE BIT(14) -#define STM32_SPI_CR1_CRCEN BIT(13) -#define STM32_SPI_CR1_SSM BIT(9) -#define STM32_SPI_CR1_SSI BIT(8) -#define STM32_SPI_CR1_LSBFIRST BIT(7) -#define STM32_SPI_CR1_SPE BIT(6) -#define STM32_SPI_CR1_BR_DIV64R (5 << 3) -#define STM32_SPI_CR1_BR_DIV4R BIT(3) -#define STM32_SPI_CR1_MSTR BIT(2) -#define STM32_SPI_CR1_CPOL BIT(1) -#define STM32_SPI_CR1_CPHA BIT(0) -#define STM32_SPI_CR2_FRXTH BIT(12) -#define STM32_SPI_CR2_DATASIZE(n) (((n) - 1) << 8) -#define STM32_SPI_CR2_TXEIE BIT(7) -#define STM32_SPI_CR2_RXNEIE BIT(6) -#define STM32_SPI_CR2_NSSP BIT(3) -#define STM32_SPI_CR2_SSOE BIT(2) -#define STM32_SPI_CR2_TXDMAEN BIT(1) -#define STM32_SPI_CR2_RXDMAEN BIT(0) - -#define STM32_SPI_SR_RXNE BIT(0) -#define STM32_SPI_SR_TXE BIT(1) -#define STM32_SPI_SR_CRCERR BIT(4) -#define STM32_SPI_SR_BSY BIT(7) -#define STM32_SPI_SR_FRLVL (3 << 9) -#define STM32_SPI_SR_FTLVL (3 << 11) +#define STM32_SPI_CR1_BIDIMODE BIT(15) +#define STM32_SPI_CR1_BIDIOE BIT(14) +#define STM32_SPI_CR1_CRCEN BIT(13) +#define STM32_SPI_CR1_SSM BIT(9) +#define STM32_SPI_CR1_SSI BIT(8) +#define STM32_SPI_CR1_LSBFIRST BIT(7) +#define STM32_SPI_CR1_SPE BIT(6) +#define STM32_SPI_CR1_BR_DIV64R (5 << 3) +#define STM32_SPI_CR1_BR_DIV4R BIT(3) +#define STM32_SPI_CR1_MSTR BIT(2) +#define STM32_SPI_CR1_CPOL BIT(1) +#define STM32_SPI_CR1_CPHA BIT(0) +#define STM32_SPI_CR2_FRXTH BIT(12) +#define STM32_SPI_CR2_DATASIZE(n) (((n)-1) << 8) +#define STM32_SPI_CR2_TXEIE BIT(7) +#define STM32_SPI_CR2_RXNEIE BIT(6) +#define STM32_SPI_CR2_NSSP BIT(3) +#define STM32_SPI_CR2_SSOE BIT(2) +#define STM32_SPI_CR2_TXDMAEN BIT(1) +#define STM32_SPI_CR2_RXDMAEN BIT(0) + +#define STM32_SPI_SR_RXNE BIT(0) +#define STM32_SPI_SR_TXE BIT(1) +#define STM32_SPI_SR_CRCERR BIT(4) +#define STM32_SPI_SR_BSY BIT(7) +#define STM32_SPI_SR_FRLVL (3 << 9) +#define STM32_SPI_SR_FTLVL (3 << 11) /* --- Debug --- */ -#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) -#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) +#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) +#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) /* --- Flash --- */ -#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) +#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) #define STM32_FLASH_ACR_LATENCY_SHIFT (0) -#define STM32_FLASH_ACR_LATENCY_MASK (7 << STM32_FLASH_ACR_LATENCY_SHIFT) -#define STM32_FLASH_ACR_LATENCY BIT(0) -#define STM32_FLASH_ACR_PRFTEN BIT(4) -#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x04) -#define FLASH_KEYR_KEY1 0x45670123 -#define FLASH_KEYR_KEY2 0xCDEF89AB - -#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) -#define FLASH_OPTKEYR_KEY1 FLASH_KEYR_KEY1 -#define FLASH_OPTKEYR_KEY2 FLASH_KEYR_KEY2 -#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x0c) -#define FLASH_SR_BUSY BIT(0) -#define FLASH_SR_PGERR BIT(2) -#define FLASH_SR_WRPRTERR BIT(4) -#define FLASH_SR_ALL_ERR \ - (FLASH_SR_PGERR | FLASH_SR_WRPRTERR) -#define FLASH_SR_EOP BIT(5) -#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x10) -#define FLASH_CR_PG BIT(0) -#define FLASH_CR_PER BIT(1) -#define FLASH_CR_OPTPG BIT(4) -#define FLASH_CR_OPTER BIT(5) -#define FLASH_CR_STRT BIT(6) -#define FLASH_CR_LOCK BIT(7) -#define FLASH_CR_OPTWRE BIT(9) -#define FLASH_CR_OBL_LAUNCH BIT(13) -#define STM32_FLASH_OPT_LOCKED (!(STM32_FLASH_CR & FLASH_CR_OPTWRE)) -#define STM32_FLASH_AR REG32(STM32_FLASH_REGS_BASE + 0x14) -#define STM32_FLASH_OBR REG32(STM32_FLASH_REGS_BASE + 0x1c) -#define STM32_FLASH_OBR_RDP_MASK (3 << 1) -#define STM32_FLASH_WRPR REG32(STM32_FLASH_REGS_BASE + 0x20) - -#define STM32_OPTB_RDP_OFF 0x00 -#define STM32_OPTB_USER_OFF 0x02 -#define STM32_OPTB_WRP_OFF(n) (0x08 + (n&3) * 2) -#define STM32_OPTB_WRP01 0x08 -#define STM32_OPTB_WRP23 0x0c - -#define STM32_OPTB_COMPL_SHIFT 8 +#define STM32_FLASH_ACR_LATENCY_MASK (7 << STM32_FLASH_ACR_LATENCY_SHIFT) +#define STM32_FLASH_ACR_LATENCY BIT(0) +#define STM32_FLASH_ACR_PRFTEN BIT(4) +#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x04) +#define FLASH_KEYR_KEY1 0x45670123 +#define FLASH_KEYR_KEY2 0xCDEF89AB + +#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) +#define FLASH_OPTKEYR_KEY1 FLASH_KEYR_KEY1 +#define FLASH_OPTKEYR_KEY2 FLASH_KEYR_KEY2 +#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x0c) +#define FLASH_SR_BUSY BIT(0) +#define FLASH_SR_PGERR BIT(2) +#define FLASH_SR_WRPRTERR BIT(4) +#define FLASH_SR_ALL_ERR (FLASH_SR_PGERR | FLASH_SR_WRPRTERR) +#define FLASH_SR_EOP BIT(5) +#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x10) +#define FLASH_CR_PG BIT(0) +#define FLASH_CR_PER BIT(1) +#define FLASH_CR_OPTPG BIT(4) +#define FLASH_CR_OPTER BIT(5) +#define FLASH_CR_STRT BIT(6) +#define FLASH_CR_LOCK BIT(7) +#define FLASH_CR_OPTWRE BIT(9) +#define FLASH_CR_OBL_LAUNCH BIT(13) +#define STM32_FLASH_OPT_LOCKED (!(STM32_FLASH_CR & FLASH_CR_OPTWRE)) +#define STM32_FLASH_AR REG32(STM32_FLASH_REGS_BASE + 0x14) +#define STM32_FLASH_OBR REG32(STM32_FLASH_REGS_BASE + 0x1c) +#define STM32_FLASH_OBR_RDP_MASK (3 << 1) +#define STM32_FLASH_WRPR REG32(STM32_FLASH_REGS_BASE + 0x20) + +#define STM32_OPTB_RDP_OFF 0x00 +#define STM32_OPTB_USER_OFF 0x02 +#define STM32_OPTB_WRP_OFF(n) (0x08 + (n & 3) * 2) +#define STM32_OPTB_WRP01 0x08 +#define STM32_OPTB_WRP23 0x0c + +#define STM32_OPTB_COMPL_SHIFT 8 /* --- External Interrupts --- */ -#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) -#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) -#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) -#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) -#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) -#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) +#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) +#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) +#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) +#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) +#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) +#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) -#define EXTI_PVD_EVENT BIT(16) -#define EXTI_RTC_ALR_EVENT BIT(17) -#define EXTI_COMP2_EVENT BIT(22) +#define EXTI_PVD_EVENT BIT(16) +#define EXTI_RTC_ALR_EVENT BIT(17) +#define EXTI_COMP2_EVENT BIT(22) /* --- ADC --- */ -#define STM32_ADC_ISR REG32(STM32_ADC1_BASE + 0x00) -#define STM32_ADC_ISR_ADRDY BIT(0) -#define STM32_ADC_IER REG32(STM32_ADC1_BASE + 0x04) -#define STM32_ADC_IER_AWDIE BIT(7) -#define STM32_ADC_IER_OVRIE BIT(4) -#define STM32_ADC_IER_EOSEQIE BIT(3) -#define STM32_ADC_IER_EOCIE BIT(2) -#define STM32_ADC_IER_EOSMPIE BIT(1) -#define STM32_ADC_IER_ADRDYIE BIT(0) - -#define STM32_ADC_CR REG32(STM32_ADC1_BASE + 0x08) -#define STM32_ADC_CR_ADEN BIT(0) -#define STM32_ADC_CR_ADDIS BIT(1) -#define STM32_ADC_CR_ADCAL BIT(31) -#define STM32_ADC_CFGR1 REG32(STM32_ADC1_BASE + 0x0C) +#define STM32_ADC_ISR REG32(STM32_ADC1_BASE + 0x00) +#define STM32_ADC_ISR_ADRDY BIT(0) +#define STM32_ADC_IER REG32(STM32_ADC1_BASE + 0x04) +#define STM32_ADC_IER_AWDIE BIT(7) +#define STM32_ADC_IER_OVRIE BIT(4) +#define STM32_ADC_IER_EOSEQIE BIT(3) +#define STM32_ADC_IER_EOCIE BIT(2) +#define STM32_ADC_IER_EOSMPIE BIT(1) +#define STM32_ADC_IER_ADRDYIE BIT(0) + +#define STM32_ADC_CR REG32(STM32_ADC1_BASE + 0x08) +#define STM32_ADC_CR_ADEN BIT(0) +#define STM32_ADC_CR_ADDIS BIT(1) +#define STM32_ADC_CR_ADCAL BIT(31) +#define STM32_ADC_CFGR1 REG32(STM32_ADC1_BASE + 0x0C) /* Analog watchdog channel selection */ #define STM32_ADC_CFGR1_AWDCH_MASK (0x1f << 26) -#define STM32_ADC_CFGR1_AWDEN BIT(23) -#define STM32_ADC_CFGR1_AWDSGL BIT(22) +#define STM32_ADC_CFGR1_AWDEN BIT(23) +#define STM32_ADC_CFGR1_AWDSGL BIT(22) /* Selects single vs continuous */ -#define STM32_ADC_CFGR1_CONT BIT(13) +#define STM32_ADC_CFGR1_CONT BIT(13) /* Selects ADC_DR overwrite vs preserve */ -#define STM32_ADC_CFGR1_OVRMOD BIT(12) +#define STM32_ADC_CFGR1_OVRMOD BIT(12) /* External trigger polarity selection */ -#define STM32_ADC_CFGR1_EXTEN_DIS (0 << 10) +#define STM32_ADC_CFGR1_EXTEN_DIS (0 << 10) #define STM32_ADC_CFGR1_EXTEN_RISE (1 << 10) #define STM32_ADC_CFGR1_EXTEN_FALL (2 << 10) #define STM32_ADC_CFGR1_EXTEN_BOTH (3 << 10) #define STM32_ADC_CFGR1_EXTEN_MASK (3 << 10) /* External trigger selection */ -#define STM32_ADC_CFGR1_TRG0 (0 << 6) -#define STM32_ADC_CFGR1_TRG1 (1 << 6) -#define STM32_ADC_CFGR1_TRG2 (2 << 6) -#define STM32_ADC_CFGR1_TRG3 (3 << 6) -#define STM32_ADC_CFGR1_TRG4 (4 << 6) -#define STM32_ADC_CFGR1_TRG5 (5 << 6) -#define STM32_ADC_CFGR1_TRG6 (6 << 6) -#define STM32_ADC_CFGR1_TRG7 (7 << 6) -#define STM32_ADC_CFGR1_TRG_MASK (7 << 6) +#define STM32_ADC_CFGR1_TRG0 (0 << 6) +#define STM32_ADC_CFGR1_TRG1 (1 << 6) +#define STM32_ADC_CFGR1_TRG2 (2 << 6) +#define STM32_ADC_CFGR1_TRG3 (3 << 6) +#define STM32_ADC_CFGR1_TRG4 (4 << 6) +#define STM32_ADC_CFGR1_TRG5 (5 << 6) +#define STM32_ADC_CFGR1_TRG6 (6 << 6) +#define STM32_ADC_CFGR1_TRG7 (7 << 6) +#define STM32_ADC_CFGR1_TRG_MASK (7 << 6) /* Selects circular vs one-shot */ -#define STM32_ADC_CFGR1_DMACFG BIT(1) -#define STM32_ADC_CFGR1_DMAEN BIT(0) -#define STM32_ADC_CFGR2 REG32(STM32_ADC1_BASE + 0x10) +#define STM32_ADC_CFGR1_DMACFG BIT(1) +#define STM32_ADC_CFGR1_DMAEN BIT(0) +#define STM32_ADC_CFGR2 REG32(STM32_ADC1_BASE + 0x10) /* Sampling time selection - 1.5 ADC cycles min, 239.5 cycles max */ -#define STM32_ADC_SMPR REG32(STM32_ADC1_BASE + 0x14) +#define STM32_ADC_SMPR REG32(STM32_ADC1_BASE + 0x14) /* Macro to convert enum stm32_adc_smpr to SMP bits of the ADC_SMPR register */ -#define STM32_ADC_SMPR_SMP(s) ((s) - 1) -#define STM32_ADC_TR REG32(STM32_ADC1_BASE + 0x20) -#define STM32_ADC_CHSELR REG32(STM32_ADC1_BASE + 0x28) -#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x40) -#define STM32_ADC_CCR REG32(STM32_ADC1_BASE + 0x308) +#define STM32_ADC_SMPR_SMP(s) ((s)-1) +#define STM32_ADC_TR REG32(STM32_ADC1_BASE + 0x20) +#define STM32_ADC_CHSELR REG32(STM32_ADC1_BASE + 0x28) +#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x40) +#define STM32_ADC_CCR REG32(STM32_ADC1_BASE + 0x308) /* --- Comparators --- */ -#define STM32_COMP_CSR REG32(STM32_COMP_BASE + 0x1C) +#define STM32_COMP_CSR REG32(STM32_COMP_BASE + 0x1C) -#define STM32_COMP_CMP2LOCK BIT(31) -#define STM32_COMP_CMP2OUT BIT(30) -#define STM32_COMP_CMP2HYST_HI (3 << 28) -#define STM32_COMP_CMP2HYST_MED (2 << 28) -#define STM32_COMP_CMP2HYST_LOW (1 << 28) -#define STM32_COMP_CMP2HYST_NO (0 << 28) -#define STM32_COMP_CMP2POL BIT(27) +#define STM32_COMP_CMP2LOCK BIT(31) +#define STM32_COMP_CMP2OUT BIT(30) +#define STM32_COMP_CMP2HYST_HI (3 << 28) +#define STM32_COMP_CMP2HYST_MED (2 << 28) +#define STM32_COMP_CMP2HYST_LOW (1 << 28) +#define STM32_COMP_CMP2HYST_NO (0 << 28) +#define STM32_COMP_CMP2POL BIT(27) #define STM32_COMP_CMP2OUTSEL_TIM3_OCR (7 << 24) #define STM32_COMP_CMP2OUTSEL_TIM3_IC1 (6 << 24) @@ -608,32 +602,32 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_COMP_CMP2OUTSEL_TIM1_OCR (3 << 24) #define STM32_COMP_CMP2OUTSEL_TIM1_IC1 (2 << 24) #define STM32_COMP_CMP2OUTSEL_TIM1_BRK (1 << 24) -#define STM32_COMP_CMP2OUTSEL_NONE (0 << 24) -#define STM32_COMP_WNDWEN BIT(23) - -#define STM32_COMP_CMP2INSEL_MASK (7 << 20) -#define STM32_COMP_CMP2INSEL_INM7 (6 << 20) /* STM32F373 only */ -#define STM32_COMP_CMP2INSEL_INM6 (6 << 20) -#define STM32_COMP_CMP2INSEL_INM5 (5 << 20) -#define STM32_COMP_CMP2INSEL_INM4 (4 << 20) -#define STM32_COMP_CMP2INSEL_VREF (3 << 20) -#define STM32_COMP_CMP2INSEL_VREF34 (2 << 20) -#define STM32_COMP_CMP2INSEL_VREF12 (1 << 20) -#define STM32_COMP_CMP2INSEL_VREF14 (0 << 20) - -#define STM32_COMP_CMP2MODE_VLSPEED (3 << 18) -#define STM32_COMP_CMP2MODE_LSPEED (2 << 18) -#define STM32_COMP_CMP2MODE_MSPEED (1 << 18) -#define STM32_COMP_CMP2MODE_HSPEED (0 << 18) -#define STM32_COMP_CMP2EN BIT(16) - -#define STM32_COMP_CMP1LOCK BIT(15) -#define STM32_COMP_CMP1OUT BIT(14) -#define STM32_COMP_CMP1HYST_HI (3 << 12) -#define STM32_COMP_CMP1HYST_MED (2 << 12) -#define STM32_COMP_CMP1HYST_LOW (1 << 12) -#define STM32_COMP_CMP1HYST_NO (0 << 12) -#define STM32_COMP_CMP1POL BIT(11) +#define STM32_COMP_CMP2OUTSEL_NONE (0 << 24) +#define STM32_COMP_WNDWEN BIT(23) + +#define STM32_COMP_CMP2INSEL_MASK (7 << 20) +#define STM32_COMP_CMP2INSEL_INM7 (6 << 20) /* STM32F373 only */ +#define STM32_COMP_CMP2INSEL_INM6 (6 << 20) +#define STM32_COMP_CMP2INSEL_INM5 (5 << 20) +#define STM32_COMP_CMP2INSEL_INM4 (4 << 20) +#define STM32_COMP_CMP2INSEL_VREF (3 << 20) +#define STM32_COMP_CMP2INSEL_VREF34 (2 << 20) +#define STM32_COMP_CMP2INSEL_VREF12 (1 << 20) +#define STM32_COMP_CMP2INSEL_VREF14 (0 << 20) + +#define STM32_COMP_CMP2MODE_VLSPEED (3 << 18) +#define STM32_COMP_CMP2MODE_LSPEED (2 << 18) +#define STM32_COMP_CMP2MODE_MSPEED (1 << 18) +#define STM32_COMP_CMP2MODE_HSPEED (0 << 18) +#define STM32_COMP_CMP2EN BIT(16) + +#define STM32_COMP_CMP1LOCK BIT(15) +#define STM32_COMP_CMP1OUT BIT(14) +#define STM32_COMP_CMP1HYST_HI (3 << 12) +#define STM32_COMP_CMP1HYST_MED (2 << 12) +#define STM32_COMP_CMP1HYST_LOW (1 << 12) +#define STM32_COMP_CMP1HYST_NO (0 << 12) +#define STM32_COMP_CMP1POL BIT(11) #define STM32_COMP_CMP1OUTSEL_TIM3_OCR (7 << 8) #define STM32_COMP_CMP1OUTSEL_TIM3_IC1 (6 << 8) @@ -642,25 +636,24 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_COMP_CMP1OUTSEL_TIM1_OCR (3 << 8) #define STM32_COMP_CMP1OUTSEL_TIM1_IC1 (2 << 8) #define STM32_COMP_CMP1OUTSEL_TIM1_BRK (1 << 8) -#define STM32_COMP_CMP1OUTSEL_NONE (0 << 8) - -#define STM32_COMP_CMP1INSEL_MASK (7 << 4) -#define STM32_COMP_CMP1INSEL_INM7 (7 << 4) /* STM32F373 only */ -#define STM32_COMP_CMP1INSEL_INM6 (6 << 4) -#define STM32_COMP_CMP1INSEL_INM5 (5 << 4) -#define STM32_COMP_CMP1INSEL_INM4 (4 << 4) -#define STM32_COMP_CMP1INSEL_VREF (3 << 4) -#define STM32_COMP_CMP1INSEL_VREF34 (2 << 4) -#define STM32_COMP_CMP1INSEL_VREF12 (1 << 4) -#define STM32_COMP_CMP1INSEL_VREF14 (0 << 4) - -#define STM32_COMP_CMP1MODE_VLSPEED (3 << 2) -#define STM32_COMP_CMP1MODE_LSPEED (2 << 2) -#define STM32_COMP_CMP1MODE_MSPEED (1 << 2) -#define STM32_COMP_CMP1MODE_HSPEED (0 << 2) -#define STM32_COMP_CMP1SW1 BIT(1) -#define STM32_COMP_CMP1EN BIT(0) - +#define STM32_COMP_CMP1OUTSEL_NONE (0 << 8) + +#define STM32_COMP_CMP1INSEL_MASK (7 << 4) +#define STM32_COMP_CMP1INSEL_INM7 (7 << 4) /* STM32F373 only */ +#define STM32_COMP_CMP1INSEL_INM6 (6 << 4) +#define STM32_COMP_CMP1INSEL_INM5 (5 << 4) +#define STM32_COMP_CMP1INSEL_INM4 (4 << 4) +#define STM32_COMP_CMP1INSEL_VREF (3 << 4) +#define STM32_COMP_CMP1INSEL_VREF34 (2 << 4) +#define STM32_COMP_CMP1INSEL_VREF12 (1 << 4) +#define STM32_COMP_CMP1INSEL_VREF14 (0 << 4) + +#define STM32_COMP_CMP1MODE_VLSPEED (3 << 2) +#define STM32_COMP_CMP1MODE_LSPEED (2 << 2) +#define STM32_COMP_CMP1MODE_MSPEED (1 << 2) +#define STM32_COMP_CMP1MODE_HSPEED (0 << 2) +#define STM32_COMP_CMP1SW1 BIT(1) +#define STM32_COMP_CMP1EN BIT(0) /* --- DMA --- */ @@ -682,19 +675,19 @@ enum dma_channel { STM32_DMAC_CH3 = 2, STM32_DMAC_CH4 = 3, STM32_DMAC_CH5 = 4, +#if defined(CHIP_VARIANT_STM32F07X) || defined(CHIP_VARIANT_STM32F09X) STM32_DMAC_CH6 = 5, STM32_DMAC_CH7 = 6, - /* - * Skip CH8, it should belong to DMA engine 1. - * Sharing code with STM32s that have 16 engines will be easier. - */ +#endif +/* STM32F09 has two DMAs with 7 & 5 channels, respectively */ +#ifdef CHIP_VARIANT_STM32F09X STM32_DMAC_CH9 = 8, STM32_DMAC_CH10 = 9, STM32_DMAC_CH11 = 10, STM32_DMAC_CH12 = 11, STM32_DMAC_CH13 = 12, STM32_DMAC_CH14 = 13, - +#endif /* Channel functions */ STM32_DMAC_ADC = STM32_DMAC_CH1, STM32_DMAC_SPI1_RX = STM32_DMAC_CH2, @@ -722,16 +715,19 @@ enum dma_channel { STM32_DMAC_COUNT = 5, #endif }; - +/* + * TODO(b/233369173): This file was originally shared by many MCUs, + * 8 is assumed to be the max number of channels for all chips. + */ #define STM32_DMAC_PER_CTLR 8 /* Registers for a single channel of the DMA controller */ struct stm32_dma_chan { - uint32_t ccr; /* Control */ - uint32_t cndtr; /* Number of data to transfer */ - uint32_t cpar; /* Peripheral address */ - uint32_t cmar; /* Memory address */ - uint32_t reserved; + uint32_t ccr; /* Control */ + uint32_t cndtr; /* Number of data to transfer */ + uint32_t cpar; /* Peripheral address */ + uint32_t cmar; /* Memory address */ + uint32_t reserved; }; /* Always use stm32_dma_chan_t so volatile keyword is included! */ @@ -742,8 +738,8 @@ typedef stm32_dma_chan_t dma_chan_t; /* Registers for the DMA controller */ struct stm32_dma_regs { - uint32_t isr; - uint32_t ifcr; + uint32_t isr; + uint32_t ifcr; stm32_dma_chan_t chan[STM32_DMAC_COUNT]; }; @@ -752,183 +748,106 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_DMA1_REGS ((stm32_dma_regs_t *)STM32_DMA1_BASE) - -#define STM32_DMA_CCR_CHANNEL(channel) (0) +#define STM32_DMA_CCR_CHANNEL(channel) (0) #ifdef CHIP_VARIANT_STM32F09X #define STM32_DMA2_REGS ((stm32_dma_regs_t *)STM32_DMA2_BASE) #define STM32_DMA_REGS(channel) \ ((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_REGS : STM32_DMA2_REGS) -#define STM32_DMA_CSELR(channel) \ - REG32(((channel) < STM32_DMAC_PER_CTLR ? \ - STM32_DMA1_BASE : STM32_DMA2_BASE) + 0xA8) +#define STM32_DMA_CSELR(channel) \ + REG32(((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_BASE : \ + STM32_DMA2_BASE) + \ + 0xA8) #else #define STM32_DMA_REGS(channel) STM32_DMA1_REGS #endif /* Bits for DMA controller regs (isr and ifcr) */ -#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) +#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) #define STM32_DMA_ISR_MASK(channel, mask) \ ((mask) << STM32_DMA_CH_OFFSET(channel)) -#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) -#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) -#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) -#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) -#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) - -#define STM32_DMA_GIF BIT(0) -#define STM32_DMA_TCIF BIT(1) -#define STM32_DMA_HTIF BIT(2) -#define STM32_DMA_TEIF BIT(3) -#define STM32_DMA_ALL 0xf - -#define STM32_DMA_GET_ISR(channel) \ - ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_ISR(channel, val) \ - (STM32_DMA_REGS(channel)->isr = \ - ((STM32_DMA_REGS(channel)->isr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) -#define STM32_DMA_GET_IFCR(channel) \ - ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_IFCR(channel, val) \ - (STM32_DMA_REGS(channel)->ifcr = \ - ((STM32_DMA_REGS(channel)->ifcr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) - +#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) +#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) +#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) +#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) +#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) + +#define STM32_DMA_GIF BIT(0) +#define STM32_DMA_TCIF BIT(1) +#define STM32_DMA_HTIF BIT(2) +#define STM32_DMA_TEIF BIT(3) +#define STM32_DMA_ALL 0xf + +#define STM32_DMA_GET_ISR(channel) \ + ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_ISR(channel, val) \ + (STM32_DMA_REGS(channel)->isr = \ + ((STM32_DMA_REGS(channel)->isr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) +#define STM32_DMA_GET_IFCR(channel) \ + ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_IFCR(channel, val) \ + (STM32_DMA_REGS(channel)->ifcr = \ + ((STM32_DMA_REGS(channel)->ifcr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) /* Bits for DMA channel regs */ -#define STM32_DMA_CCR_EN BIT(0) -#define STM32_DMA_CCR_TCIE BIT(1) -#define STM32_DMA_CCR_HTIE BIT(2) -#define STM32_DMA_CCR_TEIE BIT(3) -#define STM32_DMA_CCR_DIR BIT(4) -#define STM32_DMA_CCR_CIRC BIT(5) -#define STM32_DMA_CCR_PINC BIT(6) -#define STM32_DMA_CCR_MINC BIT(7) -#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) -#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) -#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) -#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) -#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) -#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) -#define STM32_DMA_CCR_PL_LOW (0 << 12) -#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) -#define STM32_DMA_CCR_PL_HIGH (2 << 12) -#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) -#define STM32_DMA_CCR_MEM2MEM BIT(14) - +#define STM32_DMA_CCR_EN BIT(0) +#define STM32_DMA_CCR_TCIE BIT(1) +#define STM32_DMA_CCR_HTIE BIT(2) +#define STM32_DMA_CCR_TEIE BIT(3) +#define STM32_DMA_CCR_DIR BIT(4) +#define STM32_DMA_CCR_CIRC BIT(5) +#define STM32_DMA_CCR_PINC BIT(6) +#define STM32_DMA_CCR_MINC BIT(7) +#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) +#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) +#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) +#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) +#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) +#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) +#define STM32_DMA_CCR_PL_LOW (0 << 12) +#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) +#define STM32_DMA_CCR_PL_HIGH (2 << 12) +#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) +#define STM32_DMA_CCR_MEM2MEM BIT(14) /* --- CRC --- */ -#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) - -#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) -#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) -#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) -#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) - -#define STM32_CRC_CR_RESET BIT(0) -#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) -#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) -#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) -#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) -#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) -#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) -#define STM32_CRC_CR_REV_IN_WORD (3 << 5) -#define STM32_CRC_CR_REV_OUT BIT(7) - -/* --- PMSE --- */ -#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) -#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) -#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) -#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) -#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) -#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) -#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) -#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x) * 4) -#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) -#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) -#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) -#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) -#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) -#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) -#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) -#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) -#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) -#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) -#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) - -/* --- USB --- */ -#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n) * 4) - -#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) - -#define STM32_USB_CNTR_FRES BIT(0) -#define STM32_USB_CNTR_PDWN BIT(1) -#define STM32_USB_CNTR_LP_MODE BIT(2) -#define STM32_USB_CNTR_FSUSP BIT(3) -#define STM32_USB_CNTR_RESUME BIT(4) -#define STM32_USB_CNTR_L1RESUME BIT(5) -#define STM32_USB_CNTR_L1REQM BIT(7) -#define STM32_USB_CNTR_ESOFM BIT(8) -#define STM32_USB_CNTR_SOFM BIT(9) -#define STM32_USB_CNTR_RESETM BIT(10) -#define STM32_USB_CNTR_SUSPM BIT(11) -#define STM32_USB_CNTR_WKUPM BIT(12) -#define STM32_USB_CNTR_ERRM BIT(13) -#define STM32_USB_CNTR_PMAOVRM BIT(14) -#define STM32_USB_CNTR_CTRM BIT(15) - -#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) - -#define STM32_USB_ISTR_EP_ID_MASK (0x000f) -#define STM32_USB_ISTR_DIR BIT(4) -#define STM32_USB_ISTR_L1REQ BIT(7) -#define STM32_USB_ISTR_ESOF BIT(8) -#define STM32_USB_ISTR_SOF BIT(9) -#define STM32_USB_ISTR_RESET BIT(10) -#define STM32_USB_ISTR_SUSP BIT(11) -#define STM32_USB_ISTR_WKUP BIT(12) -#define STM32_USB_ISTR_ERR BIT(13) -#define STM32_USB_ISTR_PMAOVR BIT(14) -#define STM32_USB_ISTR_CTR BIT(15) - -#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) - -#define STM32_USB_FNR_RXDP_RXDM_SHIFT (14) -#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) - -#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) -#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) -#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) -#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) - -#define STM32_USB_BCDR_BCDEN BIT(0) -#define STM32_USB_BCDR_DCDEN BIT(1) -#define STM32_USB_BCDR_PDEN BIT(2) -#define STM32_USB_BCDR_SDEN BIT(3) -#define STM32_USB_BCDR_DCDET BIT(4) -#define STM32_USB_BCDR_PDET BIT(5) -#define STM32_USB_BCDR_SDET BIT(6) -#define STM32_USB_BCDR_PS2DET BIT(7) - -#define EP_MASK 0x0F0F -#define EP_TX_DTOG 0x0040 -#define EP_TX_MASK 0x0030 +#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) + +#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) +#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) +#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) +#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) + +#define STM32_CRC_CR_RESET BIT(0) +#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) +#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) +#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) +#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) +#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) +#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) +#define STM32_CRC_CR_REV_IN_WORD (3 << 5) +#define STM32_CRC_CR_REV_OUT BIT(7) + +#define EP_MASK 0x0F0F +#define EP_TX_DTOG 0x0040 +#define EP_TX_MASK 0x0030 #define EP_TX_VALID 0x0030 -#define EP_TX_NAK 0x0020 +#define EP_TX_NAK 0x0020 #define EP_TX_STALL 0x0010 #define EP_TX_DISAB 0x0000 -#define EP_RX_DTOG 0x4000 -#define EP_RX_MASK 0x3000 +#define EP_RX_DTOG 0x4000 +#define EP_RX_MASK 0x3000 #define EP_RX_VALID 0x3000 -#define EP_RX_NAK 0x2000 +#define EP_RX_NAK 0x2000 #define EP_RX_STALL 0x1000 #define EP_RX_DISAB 0x0000 @@ -938,28 +857,27 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define EP_TX_RX_VALID (EP_TX_VALID | EP_RX_VALID) #define STM32_TOGGLE_EP(n, mask, val, flags) \ - STM32_USB_EP(n) = (((STM32_USB_EP(n) & (EP_MASK | (mask))) \ - ^ (val)) | (flags)) + STM32_USB_EP(n) = \ + (((STM32_USB_EP(n) & (EP_MASK | (mask))) ^ (val)) | (flags)) /* --- TRNG --- */ -#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) -#define STM32_RNG_CR_RNGEN BIT(2) -#define STM32_RNG_CR_IE BIT(3) -#define STM32_RNG_CR_CED BIT(5) -#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) -#define STM32_RNG_SR_DRDY BIT(0) -#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) +#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) +#define STM32_RNG_CR_RNGEN BIT(2) +#define STM32_RNG_CR_IE BIT(3) +#define STM32_RNG_CR_CED BIT(5) +#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) +#define STM32_RNG_SR_DRDY BIT(0) +#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) /* --- AXI interconnect --- */ /* STM32H7: AXI_TARGx_FN_MOD exists for masters x = 1, 2 and 7 */ -#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + \ - 0x1000 * (x)) -#define WRITE_ISS_OVERRIDE BIT(1) -#define READ_ISS_OVERRIDE BIT(0) +#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + 0x1000 * (x)) +#define WRITE_ISS_OVERRIDE BIT(1) +#define READ_ISS_OVERRIDE BIT(0) /* --- MISC --- */ -#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) -#define STM32_UNIQUE_ID_LENGTH (3 * 4) +#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) +#define STM32_UNIQUE_ID_LENGTH (3 * 4) #endif /* !__ASSEMBLER__ */ diff --git a/chip/stm32/registers-stm32f3.h b/chip/stm32/registers-stm32f3.h index b7e3cfc8af..82880accdc 100644 --- a/chip/stm32/registers-stm32f3.h +++ b/chip/stm32/registers-stm32f3.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,473 +19,467 @@ #endif /* --- IRQ numbers --- */ -#define STM32_IRQ_WWDG 0 -#define STM32_IRQ_PVD 1 -#define STM32_IRQ_TAMPER_STAMP 2 -#define STM32_IRQ_RTC_WAKEUP 3 -#define STM32_IRQ_FLASH 4 -#define STM32_IRQ_RCC 5 -#define STM32_IRQ_EXTI0 6 -#define STM32_IRQ_EXTI1 7 -#define STM32_IRQ_EXTI2 8 -#define STM32_IRQ_EXTI3 9 -#define STM32_IRQ_EXTI4 10 -#define STM32_IRQ_DMA_CHANNEL_1 11 -#define STM32_IRQ_DMA_CHANNEL_2 12 -#define STM32_IRQ_DMA_CHANNEL_3 13 -#define STM32_IRQ_DMA_CHANNEL_4 14 -#define STM32_IRQ_DMA_CHANNEL_5 15 -#define STM32_IRQ_DMA_CHANNEL_6 16 -#define STM32_IRQ_DMA_CHANNEL_7 17 +#define STM32_IRQ_WWDG 0 +#define STM32_IRQ_PVD 1 +#define STM32_IRQ_TAMPER_STAMP 2 +#define STM32_IRQ_RTC_WAKEUP 3 +#define STM32_IRQ_FLASH 4 +#define STM32_IRQ_RCC 5 +#define STM32_IRQ_EXTI0 6 +#define STM32_IRQ_EXTI1 7 +#define STM32_IRQ_EXTI2 8 +#define STM32_IRQ_EXTI3 9 +#define STM32_IRQ_EXTI4 10 +#define STM32_IRQ_DMA_CHANNEL_1 11 +#define STM32_IRQ_DMA_CHANNEL_2 12 +#define STM32_IRQ_DMA_CHANNEL_3 13 +#define STM32_IRQ_DMA_CHANNEL_4 14 +#define STM32_IRQ_DMA_CHANNEL_5 15 +#define STM32_IRQ_DMA_CHANNEL_6 16 +#define STM32_IRQ_DMA_CHANNEL_7 17 #ifdef CHIP_VARIANT_STM32F373 -#define STM32_IRQ_USB_HP 74 -#define STM32_IRQ_USB_LP 75 +#define STM32_IRQ_USB_HP 74 +#define STM32_IRQ_USB_LP 75 #else -#define STM32_IRQ_USB_HP 19 -#define STM32_IRQ_USB_LP 20 +#define STM32_IRQ_USB_HP 19 +#define STM32_IRQ_USB_LP 20 #endif -#define STM32_IRQ_ADC1 18 /* STM32L4 only */ -#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ -#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ -#define STM32_IRQ_DAC 21 -#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ +#define STM32_IRQ_ADC1 18 /* STM32L4 only */ +#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ +#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ +#define STM32_IRQ_DAC 21 +#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ #ifdef CHIP_VARIANT_STM32F373 -#define STM32_IRQ_COMP 64 +#define STM32_IRQ_COMP 64 #else -#define STM32_IRQ_COMP 22 +#define STM32_IRQ_COMP 22 #endif -#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ -#define STM32_IRQ_EXTI9_5 23 -#define STM32_IRQ_LCD 24 /* STM32L15X only */ -#define STM32_IRQ_TIM15 24 /* STM32F373 only */ -#define STM32_IRQ_TIM9 25 /* STM32L15X only */ -#define STM32_IRQ_TIM16 25 /* STM32F373 only */ -#define STM32_IRQ_TIM10 26 /* STM32L15X only */ -#define STM32_IRQ_TIM17 26 /* STM32F373 only */ -#define STM32_IRQ_TIM11 27 /* STM32L15X only */ -#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */ -#define STM32_IRQ_TIM2 28 -#define STM32_IRQ_TIM3 29 -#define STM32_IRQ_TIM4 30 -#define STM32_IRQ_I2C1_EV 31 -#define STM32_IRQ_I2C1_ER 32 -#define STM32_IRQ_I2C2_EV 33 -#define STM32_IRQ_I2C2_ER 34 -#define STM32_IRQ_SPI1 35 -#define STM32_IRQ_SPI2 36 -#define STM32_IRQ_USART1 37 -#define STM32_IRQ_USART2 38 -#define STM32_IRQ_USART3 39 -#define STM32_IRQ_EXTI15_10 40 -#define STM32_IRQ_RTC_ALARM 41 -#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ -#define STM32_IRQ_CEC 42 /* STM32F373 only */ -#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ -#define STM32_IRQ_TIM12 43 /* STM32F373 only */ -#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ -#define STM32_IRQ_TIM13 44 /* STM32F373 only */ -#define STM32_IRQ_TIM14 45 /* STM32F373 only */ -#define STM32_IRQ_TIM5 50 /* STM32F373 */ -#define STM32_IRQ_SPI3 51 /* STM32F373 */ -#define STM32_IRQ_USART4 52 /* STM32F446 only */ -#define STM32_IRQ_USART5 53 /* STM32F446 only */ -#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ -#define STM32_IRQ_TIM7 55 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ +#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ +#define STM32_IRQ_EXTI9_5 23 +#define STM32_IRQ_LCD 24 /* STM32L15X only */ +#define STM32_IRQ_TIM15 24 /* STM32F373 only */ +#define STM32_IRQ_TIM9 25 /* STM32L15X only */ +#define STM32_IRQ_TIM16 25 /* STM32F373 only */ +#define STM32_IRQ_TIM10 26 /* STM32L15X only */ +#define STM32_IRQ_TIM17 26 /* STM32F373 only */ +#define STM32_IRQ_TIM11 27 /* STM32L15X only */ +#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */ +#define STM32_IRQ_TIM2 28 +#define STM32_IRQ_TIM3 29 +#define STM32_IRQ_TIM4 30 +#define STM32_IRQ_I2C1_EV 31 +#define STM32_IRQ_I2C1_ER 32 +#define STM32_IRQ_I2C2_EV 33 +#define STM32_IRQ_I2C2_ER 34 +#define STM32_IRQ_SPI1 35 +#define STM32_IRQ_SPI2 36 +#define STM32_IRQ_USART1 37 +#define STM32_IRQ_USART2 38 +#define STM32_IRQ_USART3 39 +#define STM32_IRQ_EXTI15_10 40 +#define STM32_IRQ_RTC_ALARM 41 +#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ +#define STM32_IRQ_CEC 42 /* STM32F373 only */ +#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ +#define STM32_IRQ_TIM12 43 /* STM32F373 only */ +#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ +#define STM32_IRQ_TIM13 44 /* STM32F373 only */ +#define STM32_IRQ_TIM14 45 /* STM32F373 only */ +#define STM32_IRQ_TIM5 50 /* STM32F373 */ +#define STM32_IRQ_SPI3 51 /* STM32F373 */ +#define STM32_IRQ_USART4 52 /* STM32F446 only */ +#define STM32_IRQ_USART5 53 /* STM32F446 only */ +#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ +#define STM32_IRQ_TIM7 55 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ /* if MISC_REMAP bits are set */ -#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ -#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ -#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ -#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ -#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ -#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ -#define STM32_IRQ_LPUART 70 /* STM32L4 only */ -#define STM32_IRQ_USART9 70 /* STM32L4 only */ -#define STM32_IRQ_USART6 71 /* STM32F446 only */ -#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ -#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ -#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ -#define STM32_IRQ_TIM19 78 /* STM32F373 only */ -#define STM32_IRQ_AES 79 /* STM32L4 only */ -#define STM32_IRQ_RNG 80 /* STM32L4 only */ -#define STM32_IRQ_FPU 81 /* STM32F373 only */ - +#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ +#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ +#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ +#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ +#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ +#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ +#define STM32_IRQ_LPUART 70 /* STM32L4 only */ +#define STM32_IRQ_USART9 70 /* STM32L4 only */ +#define STM32_IRQ_USART6 71 /* STM32F446 only */ +#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ +#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ +#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ +#define STM32_IRQ_TIM19 78 /* STM32F373 only */ +#define STM32_IRQ_AES 79 /* STM32L4 only */ +#define STM32_IRQ_RNG 80 /* STM32L4 only */ +#define STM32_IRQ_FPU 81 /* STM32F373 only */ /* To simplify code generation, define DMA channel 9..10 */ -#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 -#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 -#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 -#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 +#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 +#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 +#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 +#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 /* aliases for easier code sharing */ #define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV #define STM32_IRQ_I2C2 STM32_IRQ_I2C2_EV #define STM32_IRQ_I2C3 STM32_IRQ_I2C3_EV - - /* Peripheral base addresses */ -#define STM32_ADC1_BASE 0x40012400 -#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */ +#define STM32_ADC1_BASE 0x40012400 +#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */ -#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ -#define STM32_CRC_BASE 0x40023000 -#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ -#define STM32_DAC_BASE 0x40007400 +#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ +#define STM32_CRC_BASE 0x40023000 +#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ +#define STM32_DAC_BASE 0x40007400 -#define STM32_COMP_BASE 0x40010000 +#define STM32_COMP_BASE 0x40010000 -#define STM32_DBGMCU_BASE 0xE0042000 +#define STM32_DBGMCU_BASE 0xE0042000 -#define STM32_DMA1_BASE 0x40020000 -#define STM32_DMA2_BASE 0x40020400 +#define STM32_DMA1_BASE 0x40020000 +#define STM32_DMA2_BASE 0x40020400 -#define STM32_EXTI_BASE 0x40010400 +#define STM32_EXTI_BASE 0x40010400 -#define STM32_FLASH_REGS_BASE 0x40022000 +#define STM32_FLASH_REGS_BASE 0x40022000 -#define STM32_GPIOA_BASE 0x48000000 -#define STM32_GPIOB_BASE 0x48000400 -#define STM32_GPIOC_BASE 0x48000800 -#define STM32_GPIOD_BASE 0x48000C00 -#define STM32_GPIOE_BASE 0x48001000 -#define STM32_GPIOF_BASE 0x48001400 -#define STM32_GPIOG_BASE 0x48001800 /* only for stm32l4x6 */ -#define STM32_GPIOH_BASE 0x48001C00 /* only for stm32l4 */ +#define STM32_GPIOA_BASE 0x48000000 +#define STM32_GPIOB_BASE 0x48000400 +#define STM32_GPIOC_BASE 0x48000800 +#define STM32_GPIOD_BASE 0x48000C00 +#define STM32_GPIOE_BASE 0x48001000 +#define STM32_GPIOF_BASE 0x48001400 +#define STM32_GPIOG_BASE 0x48001800 /* only for stm32l4x6 */ +#define STM32_GPIOH_BASE 0x48001C00 /* only for stm32l4 */ -#define STM32_I2C1_BASE 0x40005400 -#define STM32_I2C2_BASE 0x40005800 -#define STM32_I2C3_BASE 0x40005C00 -#define STM32_I2C4_BASE 0x40006000 +#define STM32_I2C1_BASE 0x40005400 +#define STM32_I2C2_BASE 0x40005800 +#define STM32_I2C3_BASE 0x40005C00 +#define STM32_I2C4_BASE 0x40006000 -#define STM32_IWDG_BASE 0x40003000 -#define STM32_LCD_BASE 0x40002400 +#define STM32_IWDG_BASE 0x40003000 +#define STM32_LCD_BASE 0x40002400 -#define STM32_OPTB_BASE 0x1FFFF800 +#define STM32_OPTB_BASE 0x1FFFF800 -#define STM32_PMSE_BASE 0x40013400 -#define STM32_PWR_BASE 0x40007000 +#define STM32_PMSE_BASE 0x40013400 +#define STM32_PWR_BASE 0x40007000 -#define STM32_RCC_BASE 0x40021000 +#define STM32_RCC_BASE 0x40021000 -#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ -#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ -#define STM32_RTC_BASE 0x40002800 +#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ +#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ +#define STM32_RTC_BASE 0x40002800 -#define STM32_SPI1_BASE 0x40013000 -#define STM32_SPI2_BASE 0x40003800 -#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ +#define STM32_SPI1_BASE 0x40013000 +#define STM32_SPI2_BASE 0x40003800 +#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ -#define STM32_SYSCFG_BASE 0x40010000 +#define STM32_SYSCFG_BASE 0x40010000 -#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ -#define STM32_TIM2_BASE 0x40000000 -#define STM32_TIM3_BASE 0x40000400 -#define STM32_TIM4_BASE 0x40000800 -#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ -#define STM32_TIM6_BASE 0x40001000 -#define STM32_TIM7_BASE 0x40001400 -#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ -#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ -#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ -#define STM32_TIM15_BASE 0x40014000 -#define STM32_TIM16_BASE 0x40014400 -#define STM32_TIM17_BASE 0x40014800 -#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ -#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ +#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ +#define STM32_TIM2_BASE 0x40000000 +#define STM32_TIM3_BASE 0x40000400 +#define STM32_TIM4_BASE 0x40000800 +#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ +#define STM32_TIM6_BASE 0x40001000 +#define STM32_TIM7_BASE 0x40001400 +#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ +#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ +#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ +#define STM32_TIM15_BASE 0x40014000 +#define STM32_TIM16_BASE 0x40014400 +#define STM32_TIM17_BASE 0x40014800 +#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ +#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ -#define STM32_UNIQUE_ID_BASE 0x1ffff7ac +#define STM32_UNIQUE_ID_BASE 0x1ffff7ac -#define STM32_USART1_BASE 0x40013800 -#define STM32_USART2_BASE 0x40004400 -#define STM32_USART3_BASE 0x40004800 -#define STM32_USART4_BASE 0x40004c00 -#define STM32_USART9_BASE 0x40008000 /* LPUART */ +#define STM32_USART1_BASE 0x40013800 +#define STM32_USART2_BASE 0x40004400 +#define STM32_USART3_BASE 0x40004800 +#define STM32_USART4_BASE 0x40004c00 +#define STM32_USART9_BASE 0x40008000 /* LPUART */ -#define STM32_USB_CAN_SRAM_BASE 0x40006000 -#define STM32_USB_FS_BASE 0x40005C00 - -#define STM32_WWDG_BASE 0x40002C00 +#define STM32_USB_CAN_SRAM_BASE 0x40006000 +#define STM32_USB_FS_BASE 0x40005C00 +#define STM32_WWDG_BASE 0x40002C00 #ifndef __ASSEMBLER__ /* Register definitions */ /* --- USART --- */ -#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) -#define STM32_USART_CR1_UE BIT(0) -#define STM32_USART_CR1_UESM BIT(1) -#define STM32_USART_CR1_RE BIT(2) -#define STM32_USART_CR1_TE BIT(3) -#define STM32_USART_CR1_RXNEIE BIT(5) -#define STM32_USART_CR1_TCIE BIT(6) -#define STM32_USART_CR1_TXEIE BIT(7) -#define STM32_USART_CR1_PS BIT(9) -#define STM32_USART_CR1_PCE BIT(10) -#define STM32_USART_CR1_M BIT(12) -#define STM32_USART_CR1_OVER8 BIT(15) -#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) -#define STM32_USART_CR2_SWAP BIT(15) -#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) -#define STM32_USART_CR3_EIE BIT(0) -#define STM32_USART_CR3_DMAR BIT(6) -#define STM32_USART_CR3_DMAT BIT(7) -#define STM32_USART_CR3_ONEBIT BIT(11) -#define STM32_USART_CR3_OVRDIS BIT(12) -#define STM32_USART_CR3_WUS_START_BIT (2 << 20) -#define STM32_USART_CR3_WUFIE BIT(22) -#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) -#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) -#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) -#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) -#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) -#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) -#define STM32_USART_ICR_ORECF BIT(3) -#define STM32_USART_ICR_TCCF BIT(6) -#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) -#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) -#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) +#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) +#define STM32_USART_CR1_UE BIT(0) +#define STM32_USART_CR1_UESM BIT(1) +#define STM32_USART_CR1_RE BIT(2) +#define STM32_USART_CR1_TE BIT(3) +#define STM32_USART_CR1_RXNEIE BIT(5) +#define STM32_USART_CR1_TCIE BIT(6) +#define STM32_USART_CR1_TXEIE BIT(7) +#define STM32_USART_CR1_PS BIT(9) +#define STM32_USART_CR1_PCE BIT(10) +#define STM32_USART_CR1_M BIT(12) +#define STM32_USART_CR1_OVER8 BIT(15) +#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) +#define STM32_USART_CR2_SWAP BIT(15) +#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) +#define STM32_USART_CR3_EIE BIT(0) +#define STM32_USART_CR3_DMAR BIT(6) +#define STM32_USART_CR3_DMAT BIT(7) +#define STM32_USART_CR3_ONEBIT BIT(11) +#define STM32_USART_CR3_OVRDIS BIT(12) +#define STM32_USART_CR3_WUS_START_BIT (2 << 20) +#define STM32_USART_CR3_WUFIE BIT(22) +#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) +#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) +#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) +#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) +#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) +#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) +#define STM32_USART_ICR_ORECF BIT(3) +#define STM32_USART_ICR_TCCF BIT(6) +#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) +#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) +#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) /* register alias */ -#define STM32_USART_SR(base) STM32_USART_ISR(base) -#define STM32_USART_SR_ORE BIT(3) -#define STM32_USART_SR_RXNE BIT(5) -#define STM32_USART_SR_TC BIT(6) -#define STM32_USART_SR_TXE BIT(7) +#define STM32_USART_SR(base) STM32_USART_ISR(base) +#define STM32_USART_SR_ORE BIT(3) +#define STM32_USART_SR_RXNE BIT(5) +#define STM32_USART_SR_TC BIT(6) +#define STM32_USART_SR_TXE BIT(7) /* --- GPIO --- */ -#define STM32_GPIO_MODER(b) REG32((b) + 0x00) -#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) -#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) -#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) -#define STM32_GPIO_IDR(b) REG16((b) + 0x10) -#define STM32_GPIO_ODR(b) REG16((b) + 0x14) -#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) -#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) -#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) -#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) -#define STM32_GPIO_BRR(b) REG32((b) + 0x28) -#define STM32_GPIO_ASCR(b) REG32((b) + 0x2C) /* only for stm32l4 */ - -#define GPIO_ALT_F0 0x0 -#define GPIO_ALT_F1 0x1 -#define GPIO_ALT_F2 0x2 -#define GPIO_ALT_F3 0x3 -#define GPIO_ALT_F4 0x4 -#define GPIO_ALT_F5 0x5 -#define GPIO_ALT_F6 0x6 -#define GPIO_ALT_F7 0x7 -#define GPIO_ALT_F8 0x8 -#define GPIO_ALT_F9 0x9 -#define GPIO_ALT_FA 0xA -#define GPIO_ALT_FB 0xB -#define GPIO_ALT_FC 0xC -#define GPIO_ALT_FD 0xD -#define GPIO_ALT_FE 0xE -#define GPIO_ALT_FF 0xF +#define STM32_GPIO_MODER(b) REG32((b) + 0x00) +#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) +#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) +#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) +#define STM32_GPIO_IDR(b) REG16((b) + 0x10) +#define STM32_GPIO_ODR(b) REG16((b) + 0x14) +#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) +#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) +#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) +#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) +#define STM32_GPIO_BRR(b) REG32((b) + 0x28) +#define STM32_GPIO_ASCR(b) REG32((b) + 0x2C) /* only for stm32l4 */ + +#define GPIO_ALT_F0 0x0 +#define GPIO_ALT_F1 0x1 +#define GPIO_ALT_F2 0x2 +#define GPIO_ALT_F3 0x3 +#define GPIO_ALT_F4 0x4 +#define GPIO_ALT_F5 0x5 +#define GPIO_ALT_F6 0x6 +#define GPIO_ALT_F7 0x7 +#define GPIO_ALT_F8 0x8 +#define GPIO_ALT_F9 0x9 +#define GPIO_ALT_FA 0xA +#define GPIO_ALT_FB 0xB +#define GPIO_ALT_FC 0xC +#define GPIO_ALT_FD 0xD +#define GPIO_ALT_FE 0xE +#define GPIO_ALT_FF 0xF /* --- I2C --- */ -#define STM32_I2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) -#define STM32_I2C_CR1_PE BIT(0) -#define STM32_I2C_CR1_TXIE BIT(1) -#define STM32_I2C_CR1_RXIE BIT(2) -#define STM32_I2C_CR1_ADDRIE BIT(3) -#define STM32_I2C_CR1_NACKIE BIT(4) -#define STM32_I2C_CR1_STOPIE BIT(5) -#define STM32_I2C_CR1_ERRIE BIT(7) -#define STM32_I2C_CR1_WUPEN BIT(18) -#define STM32_I2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) -#define STM32_I2C_CR2_RD_WRN BIT(10) -#define STM32_I2C_CR2_START BIT(13) -#define STM32_I2C_CR2_STOP BIT(14) -#define STM32_I2C_CR2_NACK BIT(15) -#define STM32_I2C_CR2_RELOAD BIT(24) -#define STM32_I2C_CR2_AUTOEND BIT(25) -#define STM32_I2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) -#define STM32_I2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) -#define STM32_I2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) -#define STM32_I2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) -#define STM32_I2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) -#define STM32_I2C_ISR_TXE BIT(0) -#define STM32_I2C_ISR_TXIS BIT(1) -#define STM32_I2C_ISR_RXNE BIT(2) -#define STM32_I2C_ISR_ADDR BIT(3) -#define STM32_I2C_ISR_NACK BIT(4) -#define STM32_I2C_ISR_STOP BIT(5) -#define STM32_I2C_ISR_TC BIT(6) -#define STM32_I2C_ISR_TCR BIT(7) -#define STM32_I2C_ISR_BERR BIT(8) -#define STM32_I2C_ISR_ARLO BIT(9) -#define STM32_I2C_ISR_OVR BIT(10) -#define STM32_I2C_ISR_PECERR BIT(11) -#define STM32_I2C_ISR_TIMEOUT BIT(12) -#define STM32_I2C_ISR_ALERT BIT(13) -#define STM32_I2C_ISR_BUSY BIT(15) -#define STM32_I2C_ISR_DIR BIT(16) -#define STM32_I2C_ISR_ADDCODE(isr) (((isr) >> 16) & 0xfe) -#define STM32_I2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) -#define STM32_I2C_ICR_ADDRCF BIT(3) -#define STM32_I2C_ICR_NACKCF BIT(4) -#define STM32_I2C_ICR_STOPCF BIT(5) -#define STM32_I2C_ICR_BERRCF BIT(8) -#define STM32_I2C_ICR_ARLOCF BIT(9) -#define STM32_I2C_ICR_OVRCF BIT(10) -#define STM32_I2C_ICR_TIMEOUTCF BIT(12) -#define STM32_I2C_ICR_ALL 0x3F38 -#define STM32_I2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) -#define STM32_I2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) -#define STM32_I2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) - +#define STM32_I2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) +#define STM32_I2C_CR1_PE BIT(0) +#define STM32_I2C_CR1_TXIE BIT(1) +#define STM32_I2C_CR1_RXIE BIT(2) +#define STM32_I2C_CR1_ADDRIE BIT(3) +#define STM32_I2C_CR1_NACKIE BIT(4) +#define STM32_I2C_CR1_STOPIE BIT(5) +#define STM32_I2C_CR1_ERRIE BIT(7) +#define STM32_I2C_CR1_WUPEN BIT(18) +#define STM32_I2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) +#define STM32_I2C_CR2_RD_WRN BIT(10) +#define STM32_I2C_CR2_START BIT(13) +#define STM32_I2C_CR2_STOP BIT(14) +#define STM32_I2C_CR2_NACK BIT(15) +#define STM32_I2C_CR2_RELOAD BIT(24) +#define STM32_I2C_CR2_AUTOEND BIT(25) +#define STM32_I2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) +#define STM32_I2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) +#define STM32_I2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) +#define STM32_I2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) +#define STM32_I2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) +#define STM32_I2C_ISR_TXE BIT(0) +#define STM32_I2C_ISR_TXIS BIT(1) +#define STM32_I2C_ISR_RXNE BIT(2) +#define STM32_I2C_ISR_ADDR BIT(3) +#define STM32_I2C_ISR_NACK BIT(4) +#define STM32_I2C_ISR_STOP BIT(5) +#define STM32_I2C_ISR_TC BIT(6) +#define STM32_I2C_ISR_TCR BIT(7) +#define STM32_I2C_ISR_BERR BIT(8) +#define STM32_I2C_ISR_ARLO BIT(9) +#define STM32_I2C_ISR_OVR BIT(10) +#define STM32_I2C_ISR_PECERR BIT(11) +#define STM32_I2C_ISR_TIMEOUT BIT(12) +#define STM32_I2C_ISR_ALERT BIT(13) +#define STM32_I2C_ISR_BUSY BIT(15) +#define STM32_I2C_ISR_DIR BIT(16) +#define STM32_I2C_ISR_ADDCODE(isr) (((isr) >> 16) & 0xfe) +#define STM32_I2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) +#define STM32_I2C_ICR_ADDRCF BIT(3) +#define STM32_I2C_ICR_NACKCF BIT(4) +#define STM32_I2C_ICR_STOPCF BIT(5) +#define STM32_I2C_ICR_BERRCF BIT(8) +#define STM32_I2C_ICR_ARLOCF BIT(9) +#define STM32_I2C_ICR_OVRCF BIT(10) +#define STM32_I2C_ICR_TIMEOUTCF BIT(12) +#define STM32_I2C_ICR_ALL 0x3F38 +#define STM32_I2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) +#define STM32_I2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) +#define STM32_I2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) /* --- Power / Reset / Clocks --- */ -#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) - -#define STM32_PWR_CSR_EWUP1 BIT(8) -#define STM32_PWR_CSR_EWUP2 BIT(9) -#define STM32_PWR_CSR_EWUP3 BIT(10) -#define STM32_PWR_CSR_EWUP4 BIT(11) /* STM32F0xx only */ -#define STM32_PWR_CSR_EWUP5 BIT(12) /* STM32F0xx only */ -#define STM32_PWR_CSR_EWUP6 BIT(13) /* STM32F0xx only */ -#define STM32_PWR_CSR_EWUP7 BIT(14) /* STM32F0xx only */ -#define STM32_PWR_CSR_EWUP8 BIT(15) /* STM32F0xx only */ - -#define STM32_CRS_CR REG32(STM32_CRS_BASE + 0x00) /* STM32F0XX */ -#define STM32_CRS_CR_SYNCOKIE BIT(0) -#define STM32_CRS_CR_SYNCWARNIE BIT(1) -#define STM32_CRS_CR_ERRIE BIT(2) -#define STM32_CRS_CR_ESYNCIE BIT(3) -#define STM32_CRS_CR_CEN BIT(5) -#define STM32_CRS_CR_AUTOTRIMEN BIT(6) -#define STM32_CRS_CR_SWSYNC BIT(7) -#define STM32_CRS_CR_TRIM(n) (((n) & 0x3f) << 8) - -#define STM32_CRS_CFGR REG32(STM32_CRS_BASE + 0x04) /* STM32F0XX */ -#define STM32_CRS_CFGR_RELOAD(n) (((n) & 0xffff) << 0) -#define STM32_CRS_CFGR_FELIM(n) (((n) & 0xff) << 16) -#define STM32_CRS_CFGR_SYNCDIV(n) (((n) & 7) << 24) -#define STM32_CRS_CFGR_SYNCSRC(n) (((n) & 3) << 28) -#define STM32_CRS_CFGR_SYNCPOL BIT(31) - -#define STM32_CRS_ISR REG32(STM32_CRS_BASE + 0x08) /* STM32F0XX */ -#define STM32_CRS_ISR_SYNCOKF BIT(0) -#define STM32_CRS_ISR_SYNCWARNF BIT(1) -#define STM32_CRS_ISR_ERRF BIT(2) -#define STM32_CRS_ISR_ESYNCF BIT(3) -#define STM32_CRS_ISR_SYNCERR BIT(8) -#define STM32_CRS_ISR_SYNCMISS BIT(9) -#define STM32_CRS_ISR_TRIMOVF BIT(10) -#define STM32_CRS_ISR_FEDIR BIT(15) -#define STM32_CRS_ISR_FECAP (0xffff << 16) - -#define STM32_CRS_ICR REG32(STM32_CRS_BASE + 0x0c) /* STM32F0XX */ -#define STM32_CRS_ICR_SYNCOKC BIT(0) -#define STM32_CRS_ICR_SYNCWARINC BIT(1) -#define STM32_CRS_ICR_ERRC BIT(2) -#define STM32_CRS_ICR_ESYNCC BIT(3) - -#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) -#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x04) -#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x08) -#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x0c) -#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x10) -#define STM32_RCC_AHBENR REG32(STM32_RCC_BASE + 0x14) -#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x18) -#define STM32_RCC_APB2ENR_ADCEN BIT(9) /* STM32F3/F0 */ -#define STM32_RCC_APB2ENR_TIM16EN BIT(17) -#define STM32_RCC_APB2ENR_TIM17EN BIT(18) -#define STM32_RCC_DBGMCUEN BIT(22) -#define STM32_RCC_SYSCFGEN BIT(0) - -#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x1c) -#define STM32_RCC_PWREN BIT(28) - -#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x20) -#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x24) +#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) + +#define STM32_PWR_CSR_EWUP1 BIT(8) +#define STM32_PWR_CSR_EWUP2 BIT(9) +#define STM32_PWR_CSR_EWUP3 BIT(10) +#define STM32_PWR_CSR_EWUP4 BIT(11) /* STM32F0xx only */ +#define STM32_PWR_CSR_EWUP5 BIT(12) /* STM32F0xx only */ +#define STM32_PWR_CSR_EWUP6 BIT(13) /* STM32F0xx only */ +#define STM32_PWR_CSR_EWUP7 BIT(14) /* STM32F0xx only */ +#define STM32_PWR_CSR_EWUP8 BIT(15) /* STM32F0xx only */ + +#define STM32_CRS_CR REG32(STM32_CRS_BASE + 0x00) /* STM32F0XX */ +#define STM32_CRS_CR_SYNCOKIE BIT(0) +#define STM32_CRS_CR_SYNCWARNIE BIT(1) +#define STM32_CRS_CR_ERRIE BIT(2) +#define STM32_CRS_CR_ESYNCIE BIT(3) +#define STM32_CRS_CR_CEN BIT(5) +#define STM32_CRS_CR_AUTOTRIMEN BIT(6) +#define STM32_CRS_CR_SWSYNC BIT(7) +#define STM32_CRS_CR_TRIM(n) (((n)&0x3f) << 8) + +#define STM32_CRS_CFGR REG32(STM32_CRS_BASE + 0x04) /* STM32F0XX */ +#define STM32_CRS_CFGR_RELOAD(n) (((n)&0xffff) << 0) +#define STM32_CRS_CFGR_FELIM(n) (((n)&0xff) << 16) +#define STM32_CRS_CFGR_SYNCDIV(n) (((n)&7) << 24) +#define STM32_CRS_CFGR_SYNCSRC(n) (((n)&3) << 28) +#define STM32_CRS_CFGR_SYNCPOL BIT(31) + +#define STM32_CRS_ISR REG32(STM32_CRS_BASE + 0x08) /* STM32F0XX */ +#define STM32_CRS_ISR_SYNCOKF BIT(0) +#define STM32_CRS_ISR_SYNCWARNF BIT(1) +#define STM32_CRS_ISR_ERRF BIT(2) +#define STM32_CRS_ISR_ESYNCF BIT(3) +#define STM32_CRS_ISR_SYNCERR BIT(8) +#define STM32_CRS_ISR_SYNCMISS BIT(9) +#define STM32_CRS_ISR_TRIMOVF BIT(10) +#define STM32_CRS_ISR_FEDIR BIT(15) +#define STM32_CRS_ISR_FECAP (0xffff << 16) + +#define STM32_CRS_ICR REG32(STM32_CRS_BASE + 0x0c) /* STM32F0XX */ +#define STM32_CRS_ICR_SYNCOKC BIT(0) +#define STM32_CRS_ICR_SYNCWARINC BIT(1) +#define STM32_CRS_ICR_ERRC BIT(2) +#define STM32_CRS_ICR_ESYNCC BIT(3) + +#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) +#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x04) +#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x08) +#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x0c) +#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x10) +#define STM32_RCC_AHBENR REG32(STM32_RCC_BASE + 0x14) +#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x18) +#define STM32_RCC_APB2ENR_ADCEN BIT(9) /* STM32F3/F0 */ +#define STM32_RCC_APB2ENR_TIM16EN BIT(17) +#define STM32_RCC_APB2ENR_TIM17EN BIT(18) +#define STM32_RCC_DBGMCUEN BIT(22) +#define STM32_RCC_SYSCFGEN BIT(0) + +#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x1c) +#define STM32_RCC_PWREN BIT(28) + +#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x20) +#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x24) /* STM32F373 */ -#define STM32_RCC_CFGR2 REG32(STM32_RCC_BASE + 0x2c) +#define STM32_RCC_CFGR2 REG32(STM32_RCC_BASE + 0x2c) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_CFGR3 REG32(STM32_RCC_BASE + 0x30) -#define STM32_RCC_CR2 REG32(STM32_RCC_BASE + 0x34) /* STM32F0XX */ +#define STM32_RCC_CFGR3 REG32(STM32_RCC_BASE + 0x30) +#define STM32_RCC_CR2 REG32(STM32_RCC_BASE + 0x34) /* STM32F0XX */ -#define STM32_RCC_HB_DMA1 BIT(0) +#define STM32_RCC_HB_DMA1 BIT(0) /* STM32F373 */ -#define STM32_RCC_HB_DMA2 BIT(1) -#define STM32_RCC_PB2_TIM1 BIT(11) /* Except STM32F373 */ -#define STM32_RCC_PB2_TIM15 BIT(16) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_PB2_TIM16 BIT(17) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_PB2_TIM17 BIT(18) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_PB2_TIM19 BIT(19) /* STM32F373 */ -#define STM32_RCC_PB2_PMAD BIT(11) /* STM32TS */ -#define STM32_RCC_PB2_PMSE BIT(13) /* STM32TS */ -#define STM32_RCC_PB1_TIM12 BIT(6) /* STM32F373 */ -#define STM32_RCC_PB1_TIM13 BIT(7) /* STM32F373 */ -#define STM32_RCC_PB1_TIM14 BIT(8) /* STM32F0XX and STM32F373 */ -#define STM32_RCC_PB1_TIM18 BIT(9) /* STM32F373 */ -#define STM32_RCC_PB1_USB BIT(23) -#define STM32_RCC_PB1_CRS BIT(27) - -#define STM32_SYSCFG_CFGR1 REG32(STM32_SYSCFG_BASE + 0x00) -#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) -#define STM32_SYSCFG_CFGR2 REG32(STM32_SYSCFG_BASE + 0x18) - +#define STM32_RCC_HB_DMA2 BIT(1) +#define STM32_RCC_PB2_TIM1 BIT(11) /* Except STM32F373 */ +#define STM32_RCC_PB2_TIM15 BIT(16) /* STM32F0XX and STM32F373 */ +#define STM32_RCC_PB2_TIM16 BIT(17) /* STM32F0XX and STM32F373 */ +#define STM32_RCC_PB2_TIM17 BIT(18) /* STM32F0XX and STM32F373 */ +#define STM32_RCC_PB2_TIM19 BIT(19) /* STM32F373 */ +#define STM32_RCC_PB2_PMAD BIT(11) /* STM32TS */ +#define STM32_RCC_PB2_PMSE BIT(13) /* STM32TS */ +#define STM32_RCC_PB1_TIM12 BIT(6) /* STM32F373 */ +#define STM32_RCC_PB1_TIM13 BIT(7) /* STM32F373 */ +#define STM32_RCC_PB1_TIM14 BIT(8) /* STM32F0XX and STM32F373 */ +#define STM32_RCC_PB1_TIM18 BIT(9) /* STM32F373 */ +#define STM32_RCC_PB1_USB BIT(23) +#define STM32_RCC_PB1_CRS BIT(27) + +#define STM32_SYSCFG_CFGR1 REG32(STM32_SYSCFG_BASE + 0x00) +#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) +#define STM32_SYSCFG_CFGR2 REG32(STM32_SYSCFG_BASE + 0x18) /* Peripheral bits for RCC_APB/AHB and DBGMCU regs */ -#define STM32_RCC_PB2_USART1 BIT(14) +#define STM32_RCC_PB2_USART1 BIT(14) /* Reset causes definitions */ /* Reset causes in RCC CSR register */ #define STM32_RCC_RESET_CAUSE STM32_RCC_CSR -#define RESET_CAUSE_WDG 0x60000000 -#define RESET_CAUSE_SFT 0x10000000 -#define RESET_CAUSE_POR 0x08000000 -#define RESET_CAUSE_PIN 0x04000000 -#define RESET_CAUSE_OTHER 0xfe000000 -#define RESET_CAUSE_RMVF 0x01000000 +#define RESET_CAUSE_WDG 0x60000000 +#define RESET_CAUSE_SFT 0x10000000 +#define RESET_CAUSE_POR 0x08000000 +#define RESET_CAUSE_PIN 0x04000000 +#define RESET_CAUSE_OTHER 0xfe000000 +#define RESET_CAUSE_RMVF 0x01000000 /* Power cause in PWR CSR register */ #define STM32_PWR_RESET_CAUSE STM32_PWR_CSR #define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CR -#define RESET_CAUSE_SBF 0x00000002 -#define RESET_CAUSE_SBF_CLR 0x00000004 +#define RESET_CAUSE_SBF 0x00000002 +#define RESET_CAUSE_SBF_CLR 0x00000004 /* --- Watchdogs --- */ /* --- Real-Time Clock --- */ -#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) -#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) -#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) -#define STM32_RTC_CR_BYPSHAD BIT(5) -#define STM32_RTC_CR_ALRAE BIT(8) -#define STM32_RTC_CR_ALRAIE BIT(12) -#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) -#define STM32_RTC_ISR_ALRAWF BIT(0) -#define STM32_RTC_ISR_RSF BIT(5) -#define STM32_RTC_ISR_INITF BIT(6) -#define STM32_RTC_ISR_INIT BIT(7) -#define STM32_RTC_ISR_ALRAF BIT(8) -#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) -#define STM32_RTC_PRER_A_MASK (0x7f << 16) -#define STM32_RTC_PRER_S_MASK (0x7fff << 0) -#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) -#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) -#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) -#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) -#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) -#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) -#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) -#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) -#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) -#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) -#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) - -#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) -#define STM32_BKP_BYTES 64 +#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) +#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) +#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) +#define STM32_RTC_CR_BYPSHAD BIT(5) +#define STM32_RTC_CR_ALRAE BIT(8) +#define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) +#define STM32_RTC_ISR_ALRAWF BIT(0) +#define STM32_RTC_ISR_RSF BIT(5) +#define STM32_RTC_ISR_INITF BIT(6) +#define STM32_RTC_ISR_INIT BIT(7) +#define STM32_RTC_ISR_ALRAF BIT(8) +#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) +#define STM32_RTC_PRER_A_MASK (0x7f << 16) +#define STM32_RTC_PRER_S_MASK (0x7fff << 0) +#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) +#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) +#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) +#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) +#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) +#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) +#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) +#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) +#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) +#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) +#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) + +#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) +#define STM32_BKP_BYTES 64 /* --- SPI --- */ @@ -495,15 +489,15 @@ struct stm32_spi_regs { uint16_t _pad0; uint16_t cr2; uint16_t _pad1; - unsigned sr; + unsigned int sr; uint8_t dr; uint8_t _pad2; uint16_t _pad3; - unsigned crcpr; - unsigned rxcrcr; - unsigned txcrcr; - unsigned i2scfgr; /* STM32L only */ - unsigned i2spr; /* STM32L only */ + unsigned int crcpr; + unsigned int rxcrcr; + unsigned int txcrcr; + unsigned int i2scfgr; /* STM32L only */ + unsigned int i2spr; /* STM32L only */ }; /* Must be volatile, or compiler optimizes out repeated accesses */ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; @@ -513,125 +507,124 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_SPI3_REGS ((stm32_spi_regs_t *)STM32_SPI3_BASE) #define STM32_SPI4_REGS ((stm32_spi_regs_t *)STM32_SPI4_BASE) -#define STM32_SPI_CR1_BIDIMODE BIT(15) -#define STM32_SPI_CR1_BIDIOE BIT(14) -#define STM32_SPI_CR1_CRCEN BIT(13) -#define STM32_SPI_CR1_SSM BIT(9) -#define STM32_SPI_CR1_SSI BIT(8) -#define STM32_SPI_CR1_LSBFIRST BIT(7) -#define STM32_SPI_CR1_SPE BIT(6) -#define STM32_SPI_CR1_BR_DIV64R (5 << 3) -#define STM32_SPI_CR1_BR_DIV4R BIT(3) -#define STM32_SPI_CR1_MSTR BIT(2) -#define STM32_SPI_CR1_CPOL BIT(1) -#define STM32_SPI_CR1_CPHA BIT(0) -#define STM32_SPI_CR2_FRXTH BIT(12) -#define STM32_SPI_CR2_DATASIZE(n) (((n) - 1) << 8) -#define STM32_SPI_CR2_TXEIE BIT(7) -#define STM32_SPI_CR2_RXNEIE BIT(6) -#define STM32_SPI_CR2_NSSP BIT(3) -#define STM32_SPI_CR2_SSOE BIT(2) -#define STM32_SPI_CR2_TXDMAEN BIT(1) -#define STM32_SPI_CR2_RXDMAEN BIT(0) - -#define STM32_SPI_SR_RXNE BIT(0) -#define STM32_SPI_SR_TXE BIT(1) -#define STM32_SPI_SR_CRCERR BIT(4) -#define STM32_SPI_SR_BSY BIT(7) -#define STM32_SPI_SR_FRLVL (3 << 9) -#define STM32_SPI_SR_FTLVL (3 << 11) +#define STM32_SPI_CR1_BIDIMODE BIT(15) +#define STM32_SPI_CR1_BIDIOE BIT(14) +#define STM32_SPI_CR1_CRCEN BIT(13) +#define STM32_SPI_CR1_SSM BIT(9) +#define STM32_SPI_CR1_SSI BIT(8) +#define STM32_SPI_CR1_LSBFIRST BIT(7) +#define STM32_SPI_CR1_SPE BIT(6) +#define STM32_SPI_CR1_BR_DIV64R (5 << 3) +#define STM32_SPI_CR1_BR_DIV4R BIT(3) +#define STM32_SPI_CR1_MSTR BIT(2) +#define STM32_SPI_CR1_CPOL BIT(1) +#define STM32_SPI_CR1_CPHA BIT(0) +#define STM32_SPI_CR2_FRXTH BIT(12) +#define STM32_SPI_CR2_DATASIZE(n) (((n)-1) << 8) +#define STM32_SPI_CR2_TXEIE BIT(7) +#define STM32_SPI_CR2_RXNEIE BIT(6) +#define STM32_SPI_CR2_NSSP BIT(3) +#define STM32_SPI_CR2_SSOE BIT(2) +#define STM32_SPI_CR2_TXDMAEN BIT(1) +#define STM32_SPI_CR2_RXDMAEN BIT(0) + +#define STM32_SPI_SR_RXNE BIT(0) +#define STM32_SPI_SR_TXE BIT(1) +#define STM32_SPI_SR_CRCERR BIT(4) +#define STM32_SPI_SR_BSY BIT(7) +#define STM32_SPI_SR_FRLVL (3 << 9) +#define STM32_SPI_SR_FTLVL (3 << 11) /* --- Debug --- */ -#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) -#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) +#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) +#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) /* --- Flash --- */ -#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) +#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) #define STM32_FLASH_ACR_LATENCY_SHIFT (0) -#define STM32_FLASH_ACR_LATENCY_MASK (7 << STM32_FLASH_ACR_LATENCY_SHIFT) -#define STM32_FLASH_ACR_LATENCY BIT(0) -#define STM32_FLASH_ACR_PRFTEN BIT(4) -#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x04) -#define FLASH_KEYR_KEY1 0x45670123 -#define FLASH_KEYR_KEY2 0xCDEF89AB - -#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) -#define FLASH_OPTKEYR_KEY1 FLASH_KEYR_KEY1 -#define FLASH_OPTKEYR_KEY2 FLASH_KEYR_KEY2 -#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x0c) -#define FLASH_SR_BUSY BIT(0) -#define FLASH_SR_PGERR BIT(2) -#define FLASH_SR_WRPRTERR BIT(4) -#define FLASH_SR_ALL_ERR \ - (FLASH_SR_PGERR | FLASH_SR_WRPRTERR) -#define FLASH_SR_EOP BIT(5) -#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x10) -#define FLASH_CR_PG BIT(0) -#define FLASH_CR_PER BIT(1) -#define FLASH_CR_OPTPG BIT(4) -#define FLASH_CR_OPTER BIT(5) -#define FLASH_CR_STRT BIT(6) -#define FLASH_CR_LOCK BIT(7) -#define FLASH_CR_OPTWRE BIT(9) -#define FLASH_CR_OBL_LAUNCH BIT(13) -#define STM32_FLASH_OPT_LOCKED (!(STM32_FLASH_CR & FLASH_CR_OPTWRE)) -#define STM32_FLASH_AR REG32(STM32_FLASH_REGS_BASE + 0x14) -#define STM32_FLASH_OBR REG32(STM32_FLASH_REGS_BASE + 0x1c) -#define STM32_FLASH_OBR_RDP_MASK (3 << 1) -#define STM32_FLASH_WRPR REG32(STM32_FLASH_REGS_BASE + 0x20) - -#define STM32_OPTB_RDP_OFF 0x00 -#define STM32_OPTB_USER_OFF 0x02 -#define STM32_OPTB_WRP_OFF(n) (0x08 + (n&3) * 2) -#define STM32_OPTB_WRP01 0x08 -#define STM32_OPTB_WRP23 0x0c - -#define STM32_OPTB_COMPL_SHIFT 8 +#define STM32_FLASH_ACR_LATENCY_MASK (7 << STM32_FLASH_ACR_LATENCY_SHIFT) +#define STM32_FLASH_ACR_LATENCY BIT(0) +#define STM32_FLASH_ACR_PRFTEN BIT(4) +#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x04) +#define FLASH_KEYR_KEY1 0x45670123 +#define FLASH_KEYR_KEY2 0xCDEF89AB + +#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) +#define FLASH_OPTKEYR_KEY1 FLASH_KEYR_KEY1 +#define FLASH_OPTKEYR_KEY2 FLASH_KEYR_KEY2 +#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x0c) +#define FLASH_SR_BUSY BIT(0) +#define FLASH_SR_PGERR BIT(2) +#define FLASH_SR_WRPRTERR BIT(4) +#define FLASH_SR_ALL_ERR (FLASH_SR_PGERR | FLASH_SR_WRPRTERR) +#define FLASH_SR_EOP BIT(5) +#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x10) +#define FLASH_CR_PG BIT(0) +#define FLASH_CR_PER BIT(1) +#define FLASH_CR_OPTPG BIT(4) +#define FLASH_CR_OPTER BIT(5) +#define FLASH_CR_STRT BIT(6) +#define FLASH_CR_LOCK BIT(7) +#define FLASH_CR_OPTWRE BIT(9) +#define FLASH_CR_OBL_LAUNCH BIT(13) +#define STM32_FLASH_OPT_LOCKED (!(STM32_FLASH_CR & FLASH_CR_OPTWRE)) +#define STM32_FLASH_AR REG32(STM32_FLASH_REGS_BASE + 0x14) +#define STM32_FLASH_OBR REG32(STM32_FLASH_REGS_BASE + 0x1c) +#define STM32_FLASH_OBR_RDP_MASK (3 << 1) +#define STM32_FLASH_WRPR REG32(STM32_FLASH_REGS_BASE + 0x20) + +#define STM32_OPTB_RDP_OFF 0x00 +#define STM32_OPTB_USER_OFF 0x02 +#define STM32_OPTB_WRP_OFF(n) (0x08 + (n & 3) * 2) +#define STM32_OPTB_WRP01 0x08 +#define STM32_OPTB_WRP23 0x0c + +#define STM32_OPTB_COMPL_SHIFT 8 /* --- External Interrupts --- */ -#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) -#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) -#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) -#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) -#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) -#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) +#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) +#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) +#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) +#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) +#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) +#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) #define EXTI_RTC_ALR_EVENT BIT(17) /* --- ADC --- */ #ifdef CHIP_VARIANT_STM32F373 -#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00) -#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04) -#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08) -#define STM32_ADC_CR2_ADON BIT(0) -#define STM32_ADC_CR2_CONT BIT(1) -#define STM32_ADC_CR2_CAL BIT(2) -#define STM32_ADC_CR2_RSTCAL BIT(3) -#define STM32_ADC_CR2_ALIGN BIT(11) -#define STM32_ADC_CR2_SWSTART BIT(30) -#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x0C) -#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x10) -#define STM32_ADC_JOFR(n) REG32(STM32_ADC1_BASE + 0x14 + ((n)&3) * 4) -#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x24) -#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x28) -#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x28 + ((n)&3) * 4) -#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x2C) -#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x30) -#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x34) -#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x38) -#define STM32_ADC_JDR(n) REG32(STM32_ADC1_BASE + 0x3C + ((n)&3) * 4) -#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x4C) +#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00) +#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04) +#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08) +#define STM32_ADC_CR2_ADON BIT(0) +#define STM32_ADC_CR2_CONT BIT(1) +#define STM32_ADC_CR2_CAL BIT(2) +#define STM32_ADC_CR2_RSTCAL BIT(3) +#define STM32_ADC_CR2_ALIGN BIT(11) +#define STM32_ADC_CR2_SWSTART BIT(30) +#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x0C) +#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x10) +#define STM32_ADC_JOFR(n) REG32(STM32_ADC1_BASE + 0x14 + ((n)&3) * 4) +#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x24) +#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x28) +#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x28 + ((n)&3) * 4) +#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x2C) +#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x30) +#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x34) +#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x38) +#define STM32_ADC_JDR(n) REG32(STM32_ADC1_BASE + 0x3C + ((n)&3) * 4) +#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x4C) #endif /* --- Comparators --- */ -#define STM32_COMP_CSR REG32(STM32_COMP_BASE + 0x1C) +#define STM32_COMP_CSR REG32(STM32_COMP_BASE + 0x1C) -#define STM32_COMP_CMP2LOCK BIT(31) -#define STM32_COMP_CMP2OUT BIT(30) -#define STM32_COMP_CMP2HYST_HI (3 << 28) -#define STM32_COMP_CMP2HYST_MED (2 << 28) -#define STM32_COMP_CMP2HYST_LOW (1 << 28) -#define STM32_COMP_CMP2HYST_NO (0 << 28) -#define STM32_COMP_CMP2POL BIT(27) +#define STM32_COMP_CMP2LOCK BIT(31) +#define STM32_COMP_CMP2OUT BIT(30) +#define STM32_COMP_CMP2HYST_HI (3 << 28) +#define STM32_COMP_CMP2HYST_MED (2 << 28) +#define STM32_COMP_CMP2HYST_LOW (1 << 28) +#define STM32_COMP_CMP2HYST_NO (0 << 28) +#define STM32_COMP_CMP2POL BIT(27) #define STM32_COMP_CMP2OUTSEL_TIM3_OCR (7 << 24) #define STM32_COMP_CMP2OUTSEL_TIM3_IC1 (6 << 24) @@ -646,32 +639,32 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_COMP_CMP2OUTSEL_TIM1_IC1 (2 << 24) #define STM32_COMP_CMP2OUTSEL_TIM1_BRK (1 << 24) #endif -#define STM32_COMP_CMP2OUTSEL_NONE (0 << 24) -#define STM32_COMP_WNDWEN BIT(23) - -#define STM32_COMP_CMP2INSEL_MASK (7 << 20) -#define STM32_COMP_CMP2INSEL_INM7 (6 << 20) /* STM32F373 only */ -#define STM32_COMP_CMP2INSEL_INM6 (6 << 20) -#define STM32_COMP_CMP2INSEL_INM5 (5 << 20) -#define STM32_COMP_CMP2INSEL_INM4 (4 << 20) -#define STM32_COMP_CMP2INSEL_VREF (3 << 20) -#define STM32_COMP_CMP2INSEL_VREF34 (2 << 20) -#define STM32_COMP_CMP2INSEL_VREF12 (1 << 20) -#define STM32_COMP_CMP2INSEL_VREF14 (0 << 20) - -#define STM32_COMP_CMP2MODE_VLSPEED (3 << 18) -#define STM32_COMP_CMP2MODE_LSPEED (2 << 18) -#define STM32_COMP_CMP2MODE_MSPEED (1 << 18) -#define STM32_COMP_CMP2MODE_HSPEED (0 << 18) -#define STM32_COMP_CMP2EN BIT(16) - -#define STM32_COMP_CMP1LOCK BIT(15) -#define STM32_COMP_CMP1OUT BIT(14) -#define STM32_COMP_CMP1HYST_HI (3 << 12) -#define STM32_COMP_CMP1HYST_MED (2 << 12) -#define STM32_COMP_CMP1HYST_LOW (1 << 12) -#define STM32_COMP_CMP1HYST_NO (0 << 12) -#define STM32_COMP_CMP1POL BIT(11) +#define STM32_COMP_CMP2OUTSEL_NONE (0 << 24) +#define STM32_COMP_WNDWEN BIT(23) + +#define STM32_COMP_CMP2INSEL_MASK (7 << 20) +#define STM32_COMP_CMP2INSEL_INM7 (6 << 20) /* STM32F373 only */ +#define STM32_COMP_CMP2INSEL_INM6 (6 << 20) +#define STM32_COMP_CMP2INSEL_INM5 (5 << 20) +#define STM32_COMP_CMP2INSEL_INM4 (4 << 20) +#define STM32_COMP_CMP2INSEL_VREF (3 << 20) +#define STM32_COMP_CMP2INSEL_VREF34 (2 << 20) +#define STM32_COMP_CMP2INSEL_VREF12 (1 << 20) +#define STM32_COMP_CMP2INSEL_VREF14 (0 << 20) + +#define STM32_COMP_CMP2MODE_VLSPEED (3 << 18) +#define STM32_COMP_CMP2MODE_LSPEED (2 << 18) +#define STM32_COMP_CMP2MODE_MSPEED (1 << 18) +#define STM32_COMP_CMP2MODE_HSPEED (0 << 18) +#define STM32_COMP_CMP2EN BIT(16) + +#define STM32_COMP_CMP1LOCK BIT(15) +#define STM32_COMP_CMP1OUT BIT(14) +#define STM32_COMP_CMP1HYST_HI (3 << 12) +#define STM32_COMP_CMP1HYST_MED (2 << 12) +#define STM32_COMP_CMP1HYST_LOW (1 << 12) +#define STM32_COMP_CMP1HYST_NO (0 << 12) +#define STM32_COMP_CMP1POL BIT(11) #ifdef CHIP_VARIANT_STM32F373 #define STM32_COMP_CMP1OUTSEL_TIM5_OCR (7 << 8) @@ -690,25 +683,24 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_COMP_CMP1OUTSEL_TIM1_IC1 (2 << 8) #define STM32_COMP_CMP1OUTSEL_TIM1_BRK (1 << 8) #endif -#define STM32_COMP_CMP1OUTSEL_NONE (0 << 8) - -#define STM32_COMP_CMP1INSEL_MASK (7 << 4) -#define STM32_COMP_CMP1INSEL_INM7 (7 << 4) /* STM32F373 only */ -#define STM32_COMP_CMP1INSEL_INM6 (6 << 4) -#define STM32_COMP_CMP1INSEL_INM5 (5 << 4) -#define STM32_COMP_CMP1INSEL_INM4 (4 << 4) -#define STM32_COMP_CMP1INSEL_VREF (3 << 4) -#define STM32_COMP_CMP1INSEL_VREF34 (2 << 4) -#define STM32_COMP_CMP1INSEL_VREF12 (1 << 4) -#define STM32_COMP_CMP1INSEL_VREF14 (0 << 4) - -#define STM32_COMP_CMP1MODE_VLSPEED (3 << 2) -#define STM32_COMP_CMP1MODE_LSPEED (2 << 2) -#define STM32_COMP_CMP1MODE_MSPEED (1 << 2) -#define STM32_COMP_CMP1MODE_HSPEED (0 << 2) -#define STM32_COMP_CMP1SW1 BIT(1) -#define STM32_COMP_CMP1EN BIT(0) - +#define STM32_COMP_CMP1OUTSEL_NONE (0 << 8) + +#define STM32_COMP_CMP1INSEL_MASK (7 << 4) +#define STM32_COMP_CMP1INSEL_INM7 (7 << 4) /* STM32F373 only */ +#define STM32_COMP_CMP1INSEL_INM6 (6 << 4) +#define STM32_COMP_CMP1INSEL_INM5 (5 << 4) +#define STM32_COMP_CMP1INSEL_INM4 (4 << 4) +#define STM32_COMP_CMP1INSEL_VREF (3 << 4) +#define STM32_COMP_CMP1INSEL_VREF34 (2 << 4) +#define STM32_COMP_CMP1INSEL_VREF12 (1 << 4) +#define STM32_COMP_CMP1INSEL_VREF14 (0 << 4) + +#define STM32_COMP_CMP1MODE_VLSPEED (3 << 2) +#define STM32_COMP_CMP1MODE_LSPEED (2 << 2) +#define STM32_COMP_CMP1MODE_MSPEED (1 << 2) +#define STM32_COMP_CMP1MODE_HSPEED (0 << 2) +#define STM32_COMP_CMP1SW1 BIT(1) +#define STM32_COMP_CMP1EN BIT(0) /* --- DMA --- */ @@ -779,11 +771,11 @@ enum dma_channel { /* Registers for a single channel of the DMA controller */ struct stm32_dma_chan { - uint32_t ccr; /* Control */ - uint32_t cndtr; /* Number of data to transfer */ - uint32_t cpar; /* Peripheral address */ - uint32_t cmar; /* Memory address */ - uint32_t reserved; + uint32_t ccr; /* Control */ + uint32_t cndtr; /* Number of data to transfer */ + uint32_t cpar; /* Peripheral address */ + uint32_t cmar; /* Memory address */ + uint32_t reserved; }; /* Always use stm32_dma_chan_t so volatile keyword is included! */ @@ -794,8 +786,8 @@ typedef stm32_dma_chan_t dma_chan_t; /* Registers for the DMA controller */ struct stm32_dma_regs { - uint32_t isr; - uint32_t ifcr; + uint32_t isr; + uint32_t ifcr; stm32_dma_chan_t chan[STM32_DMAC_COUNT]; }; @@ -804,210 +796,130 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_DMA1_REGS ((stm32_dma_regs_t *)STM32_DMA1_BASE) - -#define STM32_DMA_CCR_CHANNEL(channel) (0) +#define STM32_DMA_CCR_CHANNEL(channel) (0) #define STM32_DMA2_REGS ((stm32_dma_regs_t *)STM32_DMA2_BASE) #define STM32_DMA_REGS(channel) \ ((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_REGS : STM32_DMA2_REGS) -#define STM32_DMA_CSELR(channel) \ - REG32(((channel) < STM32_DMAC_PER_CTLR ? \ - STM32_DMA1_BASE : STM32_DMA2_BASE) + 0xA8) +#define STM32_DMA_CSELR(channel) \ + REG32(((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_BASE : \ + STM32_DMA2_BASE) + \ + 0xA8) /* Bits for DMA controller regs (isr and ifcr) */ -#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) +#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) #define STM32_DMA_ISR_MASK(channel, mask) \ ((mask) << STM32_DMA_CH_OFFSET(channel)) -#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) -#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) -#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) -#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) -#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) - -#define STM32_DMA_GIF BIT(0) -#define STM32_DMA_TCIF BIT(1) -#define STM32_DMA_HTIF BIT(2) -#define STM32_DMA_TEIF BIT(3) -#define STM32_DMA_ALL 0xf - -#define STM32_DMA_GET_ISR(channel) \ - ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_ISR(channel, val) \ - (STM32_DMA_REGS(channel)->isr = \ - ((STM32_DMA_REGS(channel)->isr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) -#define STM32_DMA_GET_IFCR(channel) \ - ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_IFCR(channel, val) \ - (STM32_DMA_REGS(channel)->ifcr = \ - ((STM32_DMA_REGS(channel)->ifcr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) - +#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) +#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) +#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) +#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) +#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) + +#define STM32_DMA_GIF BIT(0) +#define STM32_DMA_TCIF BIT(1) +#define STM32_DMA_HTIF BIT(2) +#define STM32_DMA_TEIF BIT(3) +#define STM32_DMA_ALL 0xf + +#define STM32_DMA_GET_ISR(channel) \ + ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_ISR(channel, val) \ + (STM32_DMA_REGS(channel)->isr = \ + ((STM32_DMA_REGS(channel)->isr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) +#define STM32_DMA_GET_IFCR(channel) \ + ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_IFCR(channel, val) \ + (STM32_DMA_REGS(channel)->ifcr = \ + ((STM32_DMA_REGS(channel)->ifcr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) /* Bits for DMA channel regs */ -#define STM32_DMA_CCR_EN BIT(0) -#define STM32_DMA_CCR_TCIE BIT(1) -#define STM32_DMA_CCR_HTIE BIT(2) -#define STM32_DMA_CCR_TEIE BIT(3) -#define STM32_DMA_CCR_DIR BIT(4) -#define STM32_DMA_CCR_CIRC BIT(5) -#define STM32_DMA_CCR_PINC BIT(6) -#define STM32_DMA_CCR_MINC BIT(7) -#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) -#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) -#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) -#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) -#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) -#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) -#define STM32_DMA_CCR_PL_LOW (0 << 12) -#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) -#define STM32_DMA_CCR_PL_HIGH (2 << 12) -#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) -#define STM32_DMA_CCR_MEM2MEM BIT(14) - +#define STM32_DMA_CCR_EN BIT(0) +#define STM32_DMA_CCR_TCIE BIT(1) +#define STM32_DMA_CCR_HTIE BIT(2) +#define STM32_DMA_CCR_TEIE BIT(3) +#define STM32_DMA_CCR_DIR BIT(4) +#define STM32_DMA_CCR_CIRC BIT(5) +#define STM32_DMA_CCR_PINC BIT(6) +#define STM32_DMA_CCR_MINC BIT(7) +#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) +#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) +#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) +#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) +#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) +#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) +#define STM32_DMA_CCR_PL_LOW (0 << 12) +#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) +#define STM32_DMA_CCR_PL_HIGH (2 << 12) +#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) +#define STM32_DMA_CCR_MEM2MEM BIT(14) /* --- CRC --- */ -#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) - -#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) -#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) -#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) -#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) - -#define STM32_CRC_CR_RESET BIT(0) -#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) -#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) -#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) -#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) -#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) -#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) -#define STM32_CRC_CR_REV_IN_WORD (3 << 5) -#define STM32_CRC_CR_REV_OUT BIT(7) +#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) + +#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) +#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) +#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) +#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) + +#define STM32_CRC_CR_RESET BIT(0) +#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) +#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) +#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) +#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) +#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) +#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) +#define STM32_CRC_CR_REV_IN_WORD (3 << 5) +#define STM32_CRC_CR_REV_OUT BIT(7) /* --- PMSE --- */ -#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) -#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) -#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) -#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) -#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) -#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) -#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) -#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x) * 4) -#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) -#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) -#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) -#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) -#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) -#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) -#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) -#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) -#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) -#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) -#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) - -/* --- USB --- */ -#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n) * 4) - -#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) - -#define STM32_USB_CNTR_FRES BIT(0) -#define STM32_USB_CNTR_PDWN BIT(1) -#define STM32_USB_CNTR_LP_MODE BIT(2) -#define STM32_USB_CNTR_FSUSP BIT(3) -#define STM32_USB_CNTR_RESUME BIT(4) -#define STM32_USB_CNTR_L1RESUME BIT(5) -#define STM32_USB_CNTR_L1REQM BIT(7) -#define STM32_USB_CNTR_ESOFM BIT(8) -#define STM32_USB_CNTR_SOFM BIT(9) -#define STM32_USB_CNTR_RESETM BIT(10) -#define STM32_USB_CNTR_SUSPM BIT(11) -#define STM32_USB_CNTR_WKUPM BIT(12) -#define STM32_USB_CNTR_ERRM BIT(13) -#define STM32_USB_CNTR_PMAOVRM BIT(14) -#define STM32_USB_CNTR_CTRM BIT(15) - -#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) - -#define STM32_USB_ISTR_EP_ID_MASK (0x000f) -#define STM32_USB_ISTR_DIR BIT(4) -#define STM32_USB_ISTR_L1REQ BIT(7) -#define STM32_USB_ISTR_ESOF BIT(8) -#define STM32_USB_ISTR_SOF BIT(9) -#define STM32_USB_ISTR_RESET BIT(10) -#define STM32_USB_ISTR_SUSP BIT(11) -#define STM32_USB_ISTR_WKUP BIT(12) -#define STM32_USB_ISTR_ERR BIT(13) -#define STM32_USB_ISTR_PMAOVR BIT(14) -#define STM32_USB_ISTR_CTR BIT(15) - -#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) - -#define STM32_USB_FNR_RXDP_RXDM_SHIFT (14) -#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) - -#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) -#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) -#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) -#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) - -#define STM32_USB_BCDR_BCDEN BIT(0) -#define STM32_USB_BCDR_DCDEN BIT(1) -#define STM32_USB_BCDR_PDEN BIT(2) -#define STM32_USB_BCDR_SDEN BIT(3) -#define STM32_USB_BCDR_DCDET BIT(4) -#define STM32_USB_BCDR_PDET BIT(5) -#define STM32_USB_BCDR_SDET BIT(6) -#define STM32_USB_BCDR_PS2DET BIT(7) - -#define EP_MASK 0x0F0F -#define EP_TX_DTOG 0x0040 -#define EP_TX_MASK 0x0030 -#define EP_TX_VALID 0x0030 -#define EP_TX_NAK 0x0020 -#define EP_TX_STALL 0x0010 -#define EP_TX_DISAB 0x0000 -#define EP_RX_DTOG 0x4000 -#define EP_RX_MASK 0x3000 -#define EP_RX_VALID 0x3000 -#define EP_RX_NAK 0x2000 -#define EP_RX_STALL 0x1000 -#define EP_RX_DISAB 0x0000 - -#define EP_STATUS_OUT 0x0100 - -#define EP_TX_RX_MASK (EP_TX_MASK | EP_RX_MASK) -#define EP_TX_RX_VALID (EP_TX_VALID | EP_RX_VALID) - -#define STM32_TOGGLE_EP(n, mask, val, flags) \ - STM32_USB_EP(n) = (((STM32_USB_EP(n) & (EP_MASK | (mask))) \ - ^ (val)) | (flags)) +#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) +#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) +#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) +#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) +#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) +#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) +#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) +#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x)*4) +#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) +#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) +#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) +#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) +#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) +#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) +#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) +#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) +#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) +#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) +#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) /* --- TRNG --- */ -#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) -#define STM32_RNG_CR_RNGEN BIT(2) -#define STM32_RNG_CR_IE BIT(3) -#define STM32_RNG_CR_CED BIT(5) -#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) -#define STM32_RNG_SR_DRDY BIT(0) -#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) +#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) +#define STM32_RNG_CR_RNGEN BIT(2) +#define STM32_RNG_CR_IE BIT(3) +#define STM32_RNG_CR_CED BIT(5) +#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) +#define STM32_RNG_SR_DRDY BIT(0) +#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) /* --- AXI interconnect --- */ /* STM32H7: AXI_TARGx_FN_MOD exists for masters x = 1, 2 and 7 */ -#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + \ - 0x1000 * (x)) -#define WRITE_ISS_OVERRIDE BIT(1) -#define READ_ISS_OVERRIDE BIT(0) +#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + 0x1000 * (x)) +#define WRITE_ISS_OVERRIDE BIT(1) +#define READ_ISS_OVERRIDE BIT(0) /* --- MISC --- */ -#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) -#define STM32_UNIQUE_ID_LENGTH (3 * 4) +#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) +#define STM32_UNIQUE_ID_LENGTH (3 * 4) #endif /* !__ASSEMBLER__ */ diff --git a/chip/stm32/registers-stm32f4.h b/chip/stm32/registers-stm32f4.h index 4e81c11226..5db9b5b9e6 100644 --- a/chip/stm32/registers-stm32f4.h +++ b/chip/stm32/registers-stm32f4.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,104 +22,103 @@ #endif /* --- IRQ numbers --- */ -#define STM32_IRQ_WWDG 0 -#define STM32_IRQ_PVD 1 -#define STM32_IRQ_TAMPER_STAMP 2 -#define STM32_IRQ_RTC_WAKEUP 3 -#define STM32_IRQ_FLASH 4 -#define STM32_IRQ_RCC 5 -#define STM32_IRQ_EXTI0 6 -#define STM32_IRQ_EXTI1 7 -#define STM32_IRQ_EXTI2 8 -#define STM32_IRQ_EXTI3 9 -#define STM32_IRQ_EXTI4 10 -#define STM32_IRQ_DMA_CHANNEL_1 11 -#define STM32_IRQ_DMA_CHANNEL_2 12 -#define STM32_IRQ_DMA_CHANNEL_3 13 -#define STM32_IRQ_DMA_CHANNEL_4 14 -#define STM32_IRQ_DMA_CHANNEL_5 15 -#define STM32_IRQ_DMA_CHANNEL_6 16 -#define STM32_IRQ_DMA_CHANNEL_7 17 -#define STM32_IRQ_USB_HP 19 -#define STM32_IRQ_USB_LP 20 - -#define STM32_IRQ_ADC1 18 /* STM32L4 only */ -#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ -#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ -#define STM32_IRQ_DAC 21 -#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ - -#define STM32_IRQ_COMP 22 - -#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ -#define STM32_IRQ_EXTI9_5 23 -#define STM32_IRQ_LCD 24 /* STM32L15X only */ -#define STM32_IRQ_TIM15 24 /* STM32F373 only */ +#define STM32_IRQ_WWDG 0 +#define STM32_IRQ_PVD 1 +#define STM32_IRQ_TAMPER_STAMP 2 +#define STM32_IRQ_RTC_WAKEUP 3 +#define STM32_IRQ_FLASH 4 +#define STM32_IRQ_RCC 5 +#define STM32_IRQ_EXTI0 6 +#define STM32_IRQ_EXTI1 7 +#define STM32_IRQ_EXTI2 8 +#define STM32_IRQ_EXTI3 9 +#define STM32_IRQ_EXTI4 10 +#define STM32_IRQ_DMA_CHANNEL_1 11 +#define STM32_IRQ_DMA_CHANNEL_2 12 +#define STM32_IRQ_DMA_CHANNEL_3 13 +#define STM32_IRQ_DMA_CHANNEL_4 14 +#define STM32_IRQ_DMA_CHANNEL_5 15 +#define STM32_IRQ_DMA_CHANNEL_6 16 +#define STM32_IRQ_DMA_CHANNEL_7 17 +#define STM32_IRQ_USB_HP 19 +#define STM32_IRQ_USB_LP 20 + +#define STM32_IRQ_ADC1 18 /* STM32L4 only */ +#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ +#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ +#define STM32_IRQ_DAC 21 +#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ + +#define STM32_IRQ_COMP 22 + +#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ +#define STM32_IRQ_EXTI9_5 23 +#define STM32_IRQ_LCD 24 /* STM32L15X only */ +#define STM32_IRQ_TIM15 24 /* STM32F373 only */ #if defined(CHIP_VARIANT_STM32F412) -#define STM32_IRQ_TIM9 24 /* STM32F412 only */ +#define STM32_IRQ_TIM9 24 /* STM32F412 only */ #else -#define STM32_IRQ_TIM9 25 /* STM32L15X only */ +#define STM32_IRQ_TIM9 25 /* STM32L15X only */ #endif -#define STM32_IRQ_TIM16 25 /* STM32F373 only */ -#define STM32_IRQ_TIM10 26 /* STM32L15X only */ -#define STM32_IRQ_TIM17 26 /* STM32F373 only */ -#define STM32_IRQ_TIM11 27 /* STM32L15X only */ -#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */ -#define STM32_IRQ_TIM2 28 -#define STM32_IRQ_TIM3 29 -#define STM32_IRQ_TIM4 30 -#define STM32_IRQ_I2C1_EV 31 -#define STM32_IRQ_I2C1_ER 32 -#define STM32_IRQ_I2C2_EV 33 -#define STM32_IRQ_I2C2_ER 34 -#define STM32_IRQ_SPI1 35 -#define STM32_IRQ_SPI2 36 -#define STM32_IRQ_USART1 37 -#define STM32_IRQ_USART2 38 -#define STM32_IRQ_USART3 39 -#define STM32_IRQ_EXTI15_10 40 -#define STM32_IRQ_RTC_ALARM 41 -#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ -#define STM32_IRQ_CEC 42 /* STM32F373 only */ -#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ -#define STM32_IRQ_TIM12 43 /* STM32F373 only */ -#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ -#define STM32_IRQ_TIM13 44 /* STM32F373 only */ -#define STM32_IRQ_TIM14 45 /* STM32F373 only */ -#define STM32_IRQ_TIM5 50 /* STM32F373 */ -#define STM32_IRQ_SPI3 51 /* STM32F373 */ -#define STM32_IRQ_USART4 52 /* STM32F446 only */ -#define STM32_IRQ_USART5 53 /* STM32F446 only */ -#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ -#define STM32_IRQ_TIM7 55 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ +#define STM32_IRQ_TIM16 25 /* STM32F373 only */ +#define STM32_IRQ_TIM10 26 /* STM32L15X only */ +#define STM32_IRQ_TIM17 26 /* STM32F373 only */ +#define STM32_IRQ_TIM11 27 /* STM32L15X only */ +#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */ +#define STM32_IRQ_TIM2 28 +#define STM32_IRQ_TIM3 29 +#define STM32_IRQ_TIM4 30 +#define STM32_IRQ_I2C1_EV 31 +#define STM32_IRQ_I2C1_ER 32 +#define STM32_IRQ_I2C2_EV 33 +#define STM32_IRQ_I2C2_ER 34 +#define STM32_IRQ_SPI1 35 +#define STM32_IRQ_SPI2 36 +#define STM32_IRQ_USART1 37 +#define STM32_IRQ_USART2 38 +#define STM32_IRQ_USART3 39 +#define STM32_IRQ_EXTI15_10 40 +#define STM32_IRQ_RTC_ALARM 41 +#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ +#define STM32_IRQ_CEC 42 /* STM32F373 only */ +#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ +#define STM32_IRQ_TIM12 43 /* STM32F373 only */ +#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ +#define STM32_IRQ_TIM13 44 /* STM32F373 only */ +#define STM32_IRQ_TIM14 45 /* STM32F373 only */ +#define STM32_IRQ_TIM5 50 /* STM32F373 */ +#define STM32_IRQ_SPI3 51 /* STM32F373 */ +#define STM32_IRQ_USART4 52 /* STM32F446 only */ +#define STM32_IRQ_USART5 53 /* STM32F446 only */ +#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ +#define STM32_IRQ_TIM7 55 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ /* if MISC_REMAP bits are set */ -#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ -#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ -#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ -#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ -#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ -#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ -#define STM32_IRQ_LPUART 70 /* STM32L4 only */ -#define STM32_IRQ_USART9 70 /* STM32L4 only */ -#define STM32_IRQ_USART6 71 /* STM32F446 only */ -#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ -#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ -#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ -#define STM32_IRQ_TIM19 78 /* STM32F373 only */ -#define STM32_IRQ_AES 79 /* STM32L4 only */ -#define STM32_IRQ_RNG 80 /* STM32L4 only */ -#define STM32_IRQ_FPU 81 /* STM32F373 only */ - +#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ +#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ +#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ +#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ +#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ +#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ +#define STM32_IRQ_LPUART 70 /* STM32L4 only */ +#define STM32_IRQ_USART9 70 /* STM32L4 only */ +#define STM32_IRQ_USART6 71 /* STM32F446 only */ +#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ +#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ +#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ +#define STM32_IRQ_TIM19 78 /* STM32F373 only */ +#define STM32_IRQ_AES 79 /* STM32L4 only */ +#define STM32_IRQ_RNG 80 /* STM32L4 only */ +#define STM32_IRQ_FPU 81 /* STM32F373 only */ /* To simplify code generation, define DMA channel 9..10 */ -#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 -#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 -#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 -#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 +#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 +#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 +#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 +#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 /* aliases for easier code sharing */ #define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV @@ -134,279 +133,276 @@ * STM32F4 introduces a concept of DMA stream to allow * fine allocation of a stream to a channel. */ -#define STM32_IRQ_DMA1_STREAM0 11 -#define STM32_IRQ_DMA1_STREAM1 12 -#define STM32_IRQ_DMA1_STREAM2 13 -#define STM32_IRQ_DMA1_STREAM3 14 -#define STM32_IRQ_DMA1_STREAM4 15 -#define STM32_IRQ_DMA1_STREAM5 16 -#define STM32_IRQ_DMA1_STREAM6 17 -#define STM32_IRQ_DMA1_STREAM7 47 -#define STM32_IRQ_DMA2_STREAM0 56 -#define STM32_IRQ_DMA2_STREAM1 57 -#define STM32_IRQ_DMA2_STREAM2 58 -#define STM32_IRQ_DMA2_STREAM3 59 -#define STM32_IRQ_DMA2_STREAM4 60 -#define STM32_IRQ_DMA2_STREAM5 68 -#define STM32_IRQ_DMA2_STREAM6 69 -#define STM32_IRQ_DMA2_STREAM7 70 - -#define STM32_IRQ_OTG_HS_WKUP 76 -#define STM32_IRQ_OTG_HS_EP1_IN 75 -#define STM32_IRQ_OTG_HS_EP1_OUT 74 -#define STM32_IRQ_OTG_HS 77 -#define STM32_IRQ_OTG_FS 67 -#define STM32_IRQ_OTG_FS_WKUP 42 +#define STM32_IRQ_DMA1_STREAM0 11 +#define STM32_IRQ_DMA1_STREAM1 12 +#define STM32_IRQ_DMA1_STREAM2 13 +#define STM32_IRQ_DMA1_STREAM3 14 +#define STM32_IRQ_DMA1_STREAM4 15 +#define STM32_IRQ_DMA1_STREAM5 16 +#define STM32_IRQ_DMA1_STREAM6 17 +#define STM32_IRQ_DMA1_STREAM7 47 +#define STM32_IRQ_DMA2_STREAM0 56 +#define STM32_IRQ_DMA2_STREAM1 57 +#define STM32_IRQ_DMA2_STREAM2 58 +#define STM32_IRQ_DMA2_STREAM3 59 +#define STM32_IRQ_DMA2_STREAM4 60 +#define STM32_IRQ_DMA2_STREAM5 68 +#define STM32_IRQ_DMA2_STREAM6 69 +#define STM32_IRQ_DMA2_STREAM7 70 + +#define STM32_IRQ_OTG_HS_WKUP 76 +#define STM32_IRQ_OTG_HS_EP1_IN 75 +#define STM32_IRQ_OTG_HS_EP1_OUT 74 +#define STM32_IRQ_OTG_HS 77 +#define STM32_IRQ_OTG_FS 67 +#define STM32_IRQ_OTG_FS_WKUP 42 /* Peripheral base addresses */ -#define STM32_ADC1_BASE 0x40012000 -#define STM32_ADC_BASE 0x40012300 - -#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ -#define STM32_CRC_BASE 0x40023000 -#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ -#define STM32_DAC_BASE 0x40007400 - - -#define STM32_DBGMCU_BASE 0xE0042000 - -#define STM32_DMA1_BASE 0x40026000 -#define STM32_DMA2_BASE 0x40026400 - -#define STM32_EXTI_BASE 0x40013C00 - -#define STM32_FLASH_REGS_BASE 0x40023c00 - -#define STM32_GPIOA_BASE 0x40020000 -#define STM32_GPIOB_BASE 0x40020400 -#define STM32_GPIOC_BASE 0x40020800 -#define STM32_GPIOD_BASE 0x40020C00 -#define STM32_GPIOE_BASE 0x40021000 -#define STM32_GPIOF_BASE 0x40021400 /* see RM0402/0390 table 1 */ -#define STM32_GPIOG_BASE 0x40021800 -#define STM32_GPIOH_BASE 0x40021C00 - -#define STM32_I2C1_BASE 0x40005400 -#define STM32_I2C2_BASE 0x40005800 -#define STM32_I2C3_BASE 0x40005C00 -#define STM32_I2C4_BASE 0x40006000 - -#define STM32_IWDG_BASE 0x40003000 -#define STM32_LCD_BASE 0x40002400 - -#define STM32_OPTB_BASE 0x1FFFC000 -#define STM32_OTP_BASE 0x1FFF7800 - -#define STM32_PMSE_BASE 0x40013400 -#define STM32_PWR_BASE 0x40007000 - -#define STM32_RCC_BASE 0x40023800 - -#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ -#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ -#define STM32_RTC_BASE 0x40002800 - -#define STM32_SPI1_BASE 0x40013000 -#define STM32_SPI2_BASE 0x40003800 -#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ - -#define STM32_SYSCFG_BASE 0x40013800 - -#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ -#define STM32_TIM2_BASE 0x40000000 -#define STM32_TIM3_BASE 0x40000400 -#define STM32_TIM4_BASE 0x40000800 -#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ -#define STM32_TIM6_BASE 0x40001000 -#define STM32_TIM7_BASE 0x40001400 -#define STM32_TIM9_BASE 0x40014000 /* STM32F41x only */ -#define STM32_TIM10_BASE 0x40014400 /* STM32F41x only */ -#define STM32_TIM11_BASE 0x40014800 /* STM32F41x only */ -#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ -#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ -#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ -#define STM32_TIM15_BASE 0x40014000 -#define STM32_TIM16_BASE 0x40014400 -#define STM32_TIM17_BASE 0x40014800 -#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ -#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ - -#define STM32_UNIQUE_ID_BASE 0x1fff7a10 - -#define STM32_USART1_BASE 0x40011000 -#define STM32_USART2_BASE 0x40004400 -#define STM32_USART3_BASE 0x40004800 -#define STM32_USART4_BASE 0x40004c00 -#define STM32_USART5_BASE 0x40005000 -#define STM32_USART6_BASE 0x40011400 - -#define STM32_USB_CAN_SRAM_BASE 0x40006000 -#define STM32_USB_FS_BASE 0x40005C00 - -#define STM32_WWDG_BASE 0x40002C00 - +#define STM32_ADC1_BASE 0x40012000 +#define STM32_ADC_BASE 0x40012300 + +#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ +#define STM32_CRC_BASE 0x40023000 +#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ +#define STM32_DAC_BASE 0x40007400 + +#define STM32_DBGMCU_BASE 0xE0042000 + +#define STM32_DMA1_BASE 0x40026000 +#define STM32_DMA2_BASE 0x40026400 + +#define STM32_EXTI_BASE 0x40013C00 + +#define STM32_FLASH_REGS_BASE 0x40023c00 + +#define STM32_GPIOA_BASE 0x40020000 +#define STM32_GPIOB_BASE 0x40020400 +#define STM32_GPIOC_BASE 0x40020800 +#define STM32_GPIOD_BASE 0x40020C00 +#define STM32_GPIOE_BASE 0x40021000 +#define STM32_GPIOF_BASE 0x40021400 /* see RM0402/0390 table 1 */ +#define STM32_GPIOG_BASE 0x40021800 +#define STM32_GPIOH_BASE 0x40021C00 + +#define STM32_I2C1_BASE 0x40005400 +#define STM32_I2C2_BASE 0x40005800 +#define STM32_I2C3_BASE 0x40005C00 +#define STM32_I2C4_BASE 0x40006000 + +#define STM32_IWDG_BASE 0x40003000 +#define STM32_LCD_BASE 0x40002400 + +#define STM32_OPTB_BASE 0x1FFFC000 +#define STM32_OTP_BASE 0x1FFF7800 + +#define STM32_PMSE_BASE 0x40013400 +#define STM32_PWR_BASE 0x40007000 + +#define STM32_RCC_BASE 0x40023800 + +#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ +#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ +#define STM32_RTC_BASE 0x40002800 + +#define STM32_SPI1_BASE 0x40013000 +#define STM32_SPI2_BASE 0x40003800 +#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ + +#define STM32_SYSCFG_BASE 0x40013800 + +#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ +#define STM32_TIM2_BASE 0x40000000 +#define STM32_TIM3_BASE 0x40000400 +#define STM32_TIM4_BASE 0x40000800 +#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ +#define STM32_TIM6_BASE 0x40001000 +#define STM32_TIM7_BASE 0x40001400 +#define STM32_TIM9_BASE 0x40014000 /* STM32F41x only */ +#define STM32_TIM10_BASE 0x40014400 /* STM32F41x only */ +#define STM32_TIM11_BASE 0x40014800 /* STM32F41x only */ +#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ +#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ +#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ +#define STM32_TIM15_BASE 0x40014000 +#define STM32_TIM16_BASE 0x40014400 +#define STM32_TIM17_BASE 0x40014800 +#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ +#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ + +#define STM32_UNIQUE_ID_BASE 0x1fff7a10 + +#define STM32_USART1_BASE 0x40011000 +#define STM32_USART2_BASE 0x40004400 +#define STM32_USART3_BASE 0x40004800 +#define STM32_USART4_BASE 0x40004c00 +#define STM32_USART5_BASE 0x40005000 +#define STM32_USART6_BASE 0x40011400 + +#define STM32_USB_CAN_SRAM_BASE 0x40006000 +#define STM32_USB_FS_BASE 0x40005C00 + +#define STM32_WWDG_BASE 0x40002C00 #ifndef __ASSEMBLER__ /* Register definitions */ /* --- USART --- */ -#define STM32_USART_SR(base) STM32_USART_REG(base, 0x00) -#define STM32_USART_SR_ORE BIT(3) -#define STM32_USART_SR_RXNE BIT(5) -#define STM32_USART_SR_TC BIT(6) -#define STM32_USART_SR_TXE BIT(7) -#define STM32_USART_DR(base) STM32_USART_REG(base, 0x04) -#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x08) -#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x0C) -#define STM32_USART_CR1_RE BIT(2) -#define STM32_USART_CR1_TE BIT(3) -#define STM32_USART_CR1_RXNEIE BIT(5) -#define STM32_USART_CR1_TCIE BIT(6) -#define STM32_USART_CR1_TXEIE BIT(7) -#define STM32_USART_CR1_PS BIT(9) -#define STM32_USART_CR1_PCE BIT(10) -#define STM32_USART_CR1_M BIT(12) -#define STM32_USART_CR1_UE BIT(13) -#define STM32_USART_CR1_OVER8 BIT(15) /* STM32L only */ -#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x10) -#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x14) -#define STM32_USART_CR3_EIE BIT(0) -#define STM32_USART_CR3_DMAR BIT(6) -#define STM32_USART_CR3_DMAT BIT(7) -#define STM32_USART_CR3_ONEBIT BIT(11) /* STM32L only */ -#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x18) +#define STM32_USART_SR(base) STM32_USART_REG(base, 0x00) +#define STM32_USART_SR_ORE BIT(3) +#define STM32_USART_SR_RXNE BIT(5) +#define STM32_USART_SR_TC BIT(6) +#define STM32_USART_SR_TXE BIT(7) +#define STM32_USART_DR(base) STM32_USART_REG(base, 0x04) +#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x08) +#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x0C) +#define STM32_USART_CR1_RE BIT(2) +#define STM32_USART_CR1_TE BIT(3) +#define STM32_USART_CR1_RXNEIE BIT(5) +#define STM32_USART_CR1_TCIE BIT(6) +#define STM32_USART_CR1_TXEIE BIT(7) +#define STM32_USART_CR1_PS BIT(9) +#define STM32_USART_CR1_PCE BIT(10) +#define STM32_USART_CR1_M BIT(12) +#define STM32_USART_CR1_UE BIT(13) +#define STM32_USART_CR1_OVER8 BIT(15) /* STM32L only */ +#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x10) +#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x14) +#define STM32_USART_CR3_EIE BIT(0) +#define STM32_USART_CR3_DMAR BIT(6) +#define STM32_USART_CR3_DMAT BIT(7) +#define STM32_USART_CR3_ONEBIT BIT(11) /* STM32L only */ +#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x18) /* register aliases */ -#define STM32_USART_TDR(base) STM32_USART_DR(base) -#define STM32_USART_RDR(base) STM32_USART_DR(base) +#define STM32_USART_TDR(base) STM32_USART_DR(base) +#define STM32_USART_RDR(base) STM32_USART_DR(base) /* --- GPIO --- */ -#define STM32_GPIO_MODER(b) REG32((b) + 0x00) -#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) -#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) -#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) -#define STM32_GPIO_IDR(b) REG16((b) + 0x10) -#define STM32_GPIO_ODR(b) REG16((b) + 0x14) -#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) -#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) -#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) -#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) - -#define GPIO_ALT_SYS 0x0 -#define GPIO_ALT_TIM2 0x1 -#define GPIO_ALT_TIM3_4 0x2 -#define GPIO_ALT_TIM9_11 0x3 -#define GPIO_ALT_I2C 0x4 -#define GPIO_ALT_SPI 0x5 -#define GPIO_ALT_SPI3 0x6 -#define GPIO_ALT_USART 0x7 -#define GPIO_ALT_I2C_23 0x9 -#define GPIO_ALT_USB 0xA -#define GPIO_ALT_LCD 0xB -#define GPIO_ALT_RI 0xE -#define GPIO_ALT_EVENTOUT 0xF +#define STM32_GPIO_MODER(b) REG32((b) + 0x00) +#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) +#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) +#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) +#define STM32_GPIO_IDR(b) REG16((b) + 0x10) +#define STM32_GPIO_ODR(b) REG16((b) + 0x14) +#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) +#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) +#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) +#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) + +#define GPIO_ALT_SYS 0x0 +#define GPIO_ALT_TIM2 0x1 +#define GPIO_ALT_TIM3_4 0x2 +#define GPIO_ALT_TIM9_11 0x3 +#define GPIO_ALT_I2C 0x4 +#define GPIO_ALT_SPI 0x5 +#define GPIO_ALT_SPI3 0x6 +#define GPIO_ALT_USART 0x7 +#define GPIO_ALT_I2C_23 0x9 +#define GPIO_ALT_USB 0xA +#define GPIO_ALT_LCD 0xB +#define GPIO_ALT_RI 0xE +#define GPIO_ALT_EVENTOUT 0xF /* --- I2C --- */ -#define STM32_I2C_CR1(n) REG16(stm32_i2c_reg(n, 0x00)) -#define STM32_I2C_CR1_PE BIT(0) -#define STM32_I2C_CR1_START BIT(8) -#define STM32_I2C_CR1_STOP BIT(9) -#define STM32_I2C_CR1_ACK BIT(10) -#define STM32_I2C_CR1_POS BIT(11) -#define STM32_I2C_CR1_SWRST BIT(15) -#define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04)) -#define STM32_I2C_CR2_ITERREN BIT(8) -#define STM32_I2C_CR2_ITEVTEN BIT(9) -#define STM32_I2C_CR2_ITBUFEN BIT(10) -#define STM32_I2C_CR2_DMAEN BIT(11) -#define STM32_I2C_CR2_LAST BIT(12) -#define STM32_I2C_OAR1(n) REG16(stm32_i2c_reg(n, 0x08)) -#define STM32_I2C_OAR1_B14 BIT(14) -#define STM32_I2C_OAR2(n) REG16(stm32_i2c_reg(n, 0x0C)) -#define STM32_I2C_OAR2_ENDUAL BIT(0) -#define STM32_I2C_DR(n) REG16(stm32_i2c_reg(n, 0x10)) -#define STM32_I2C_SR1(n) REG16(stm32_i2c_reg(n, 0x14)) -#define STM32_I2C_SR1_SB BIT(0) -#define STM32_I2C_SR1_ADDR BIT(1) -#define STM32_I2C_SR1_BTF BIT(2) -#define STM32_I2C_SR1_STOPF BIT(4) -#define STM32_I2C_SR1_RXNE BIT(6) -#define STM32_I2C_SR1_TXE BIT(7) -#define STM32_I2C_SR1_BERR BIT(8) -#define STM32_I2C_SR1_ARLO BIT(9) -#define STM32_I2C_SR1_AF BIT(10) - -#define STM32_I2C_SR2(n) REG16(stm32_i2c_reg(n, 0x18)) -#define STM32_I2C_SR2_BUSY BIT(1) -#define STM32_I2C_SR2_TRA BIT(2) -#define STM32_I2C_SR2_DUALF BIT(7) - -#define STM32_I2C_CCR(n) REG16(stm32_i2c_reg(n, 0x1C)) -#define STM32_I2C_CCR_DUTY BIT(14) -#define STM32_I2C_CCR_FM BIT(15) -#define STM32_I2C_TRISE(n) REG16(stm32_i2c_reg(n, 0x20)) - -#define STM32_FMPI2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) -#define FMPI2C_CR1_PE BIT(0) -#define FMPI2C_CR1_TXDMAEN BIT(14) -#define FMPI2C_CR1_RXDMAEN BIT(15) -#define STM32_FMPI2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) -#define FMPI2C_CR2_RD_WRN BIT(10) -#define FMPI2C_READ 1 -#define FMPI2C_WRITE 0 -#define FMPI2C_CR2_START BIT(13) -#define FMPI2C_CR2_STOP BIT(14) -#define FMPI2C_CR2_NACK BIT(15) -#define FMPI2C_CR2_RELOAD BIT(24) -#define FMPI2C_CR2_AUTOEND BIT(25) -#define FMPI2C_CR2_SADD(addr) ((addr) & 0x3ff) -#define FMPI2C_CR2_SADD_MASK FMPI2C_CR2_SADD(0x3ff) -#define FMPI2C_CR2_SIZE(size) (((size) & 0xff) << 16) -#define FMPI2C_CR2_SIZE_MASK FMPI2C_CR2_SIZE(0xf) -#define STM32_FMPI2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) -#define STM32_FMPI2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) -#define STM32_FMPI2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) -#define TIMINGR_THE_RIGHT_VALUE 0xC0000E12 -#define FMPI2C_TIMINGR_PRESC(val) (((val) & 0xf) << 28) -#define FMPI2C_TIMINGR_SCLDEL(val) (((val) & 0xf) << 20) -#define FMPI2C_TIMINGR_SDADEL(val) (((val) & 0xf) << 16) -#define FMPI2C_TIMINGR_SCLH(val) (((val) & 0xff) << 8) -#define FMPI2C_TIMINGR_SCLL(val) (((val) & 0xff) << 0) -#define STM32_FMPI2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) - -#define STM32_FMPI2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) -#define FMPI2C_ISR_TXE BIT(0) -#define FMPI2C_ISR_TXIS BIT(1) -#define FMPI2C_ISR_RXNE BIT(2) -#define FMPI2C_ISR_ADDR BIT(3) -#define FMPI2C_ISR_NACKF BIT(4) -#define FMPI2C_ISR_STOPF BIT(5) -#define FMPI2C_ISR_BERR BIT(8) -#define FMPI2C_ISR_ARLO BIT(9) -#define FMPI2C_ISR_BUSY BIT(15) -#define STM32_FMPI2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) - -#define STM32_FMPI2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) -#define STM32_FMPI2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) -#define STM32_FMPI2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) +#define STM32_I2C_CR1(n) REG16(stm32_i2c_reg(n, 0x00)) +#define STM32_I2C_CR1_PE BIT(0) +#define STM32_I2C_CR1_START BIT(8) +#define STM32_I2C_CR1_STOP BIT(9) +#define STM32_I2C_CR1_ACK BIT(10) +#define STM32_I2C_CR1_POS BIT(11) +#define STM32_I2C_CR1_SWRST BIT(15) +#define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04)) +#define STM32_I2C_CR2_ITERREN BIT(8) +#define STM32_I2C_CR2_ITEVTEN BIT(9) +#define STM32_I2C_CR2_ITBUFEN BIT(10) +#define STM32_I2C_CR2_DMAEN BIT(11) +#define STM32_I2C_CR2_LAST BIT(12) +#define STM32_I2C_OAR1(n) REG16(stm32_i2c_reg(n, 0x08)) +#define STM32_I2C_OAR1_B14 BIT(14) +#define STM32_I2C_OAR2(n) REG16(stm32_i2c_reg(n, 0x0C)) +#define STM32_I2C_OAR2_ENDUAL BIT(0) +#define STM32_I2C_DR(n) REG16(stm32_i2c_reg(n, 0x10)) +#define STM32_I2C_SR1(n) REG16(stm32_i2c_reg(n, 0x14)) +#define STM32_I2C_SR1_SB BIT(0) +#define STM32_I2C_SR1_ADDR BIT(1) +#define STM32_I2C_SR1_BTF BIT(2) +#define STM32_I2C_SR1_STOPF BIT(4) +#define STM32_I2C_SR1_RXNE BIT(6) +#define STM32_I2C_SR1_TXE BIT(7) +#define STM32_I2C_SR1_BERR BIT(8) +#define STM32_I2C_SR1_ARLO BIT(9) +#define STM32_I2C_SR1_AF BIT(10) + +#define STM32_I2C_SR2(n) REG16(stm32_i2c_reg(n, 0x18)) +#define STM32_I2C_SR2_BUSY BIT(1) +#define STM32_I2C_SR2_TRA BIT(2) +#define STM32_I2C_SR2_DUALF BIT(7) + +#define STM32_I2C_CCR(n) REG16(stm32_i2c_reg(n, 0x1C)) +#define STM32_I2C_CCR_DUTY BIT(14) +#define STM32_I2C_CCR_FM BIT(15) +#define STM32_I2C_TRISE(n) REG16(stm32_i2c_reg(n, 0x20)) + +#define STM32_FMPI2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) +#define FMPI2C_CR1_PE BIT(0) +#define FMPI2C_CR1_TXDMAEN BIT(14) +#define FMPI2C_CR1_RXDMAEN BIT(15) +#define STM32_FMPI2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) +#define FMPI2C_CR2_RD_WRN BIT(10) +#define FMPI2C_READ 1 +#define FMPI2C_WRITE 0 +#define FMPI2C_CR2_START BIT(13) +#define FMPI2C_CR2_STOP BIT(14) +#define FMPI2C_CR2_NACK BIT(15) +#define FMPI2C_CR2_RELOAD BIT(24) +#define FMPI2C_CR2_AUTOEND BIT(25) +#define FMPI2C_CR2_SADD(addr) ((addr)&0x3ff) +#define FMPI2C_CR2_SADD_MASK FMPI2C_CR2_SADD(0x3ff) +#define FMPI2C_CR2_SIZE(size) (((size)&0xff) << 16) +#define FMPI2C_CR2_SIZE_MASK FMPI2C_CR2_SIZE(0xf) +#define STM32_FMPI2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) +#define STM32_FMPI2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) +#define STM32_FMPI2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) +#define TIMINGR_THE_RIGHT_VALUE 0xC0000E12 +#define FMPI2C_TIMINGR_PRESC(val) (((val)&0xf) << 28) +#define FMPI2C_TIMINGR_SCLDEL(val) (((val)&0xf) << 20) +#define FMPI2C_TIMINGR_SDADEL(val) (((val)&0xf) << 16) +#define FMPI2C_TIMINGR_SCLH(val) (((val)&0xff) << 8) +#define FMPI2C_TIMINGR_SCLL(val) (((val)&0xff) << 0) +#define STM32_FMPI2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) + +#define STM32_FMPI2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) +#define FMPI2C_ISR_TXE BIT(0) +#define FMPI2C_ISR_TXIS BIT(1) +#define FMPI2C_ISR_RXNE BIT(2) +#define FMPI2C_ISR_ADDR BIT(3) +#define FMPI2C_ISR_NACKF BIT(4) +#define FMPI2C_ISR_STOPF BIT(5) +#define FMPI2C_ISR_BERR BIT(8) +#define FMPI2C_ISR_ARLO BIT(9) +#define FMPI2C_ISR_BUSY BIT(15) +#define STM32_FMPI2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) + +#define STM32_FMPI2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) +#define STM32_FMPI2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) +#define STM32_FMPI2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) /* --- Power / Reset / Clocks --- */ -#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) - +#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) -#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) -#define STM32_RCC_CR_HSION BIT(0) -#define STM32_RCC_CR_HSIRDY BIT(1) -#define STM32_RCC_CR_HSEON BIT(16) -#define STM32_RCC_CR_HSERDY BIT(17) -#define STM32_RCC_CR_PLLON BIT(24) -#define STM32_RCC_CR_PLLRDY BIT(25) +#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) +#define STM32_RCC_CR_HSION BIT(0) +#define STM32_RCC_CR_HSIRDY BIT(1) +#define STM32_RCC_CR_HSEON BIT(16) +#define STM32_RCC_CR_HSERDY BIT(17) +#define STM32_RCC_CR_PLLON BIT(24) +#define STM32_RCC_CR_PLLRDY BIT(25) #if defined(CHIP_VARIANT_STM32F446) /* Required or recommended clocks for stm32f446 */ #define STM32F4_PLL_REQ 2000000 #define STM32F4_RTC_REQ 1000000 -#define STM32F4_IO_CLOCK 42000000 +#define STM32F4_IO_CLOCK 42000000 #define STM32F4_USB_REQ 48000000 #define STM32F4_VCO_CLOCK 336000000 #define STM32F4_HSI_CLOCK 16000000 @@ -416,13 +412,15 @@ #define STM32F4_AHB_PRE 0x8 #define STM32F4_APB1_PRE 0x0 #define STM32F4_APB2_PRE 0x0 -#define STM32_FLASH_ACR_LATENCY BIT(0) +#define STM32_FLASH_ACR_LATENCY BIT(0) +/* optimized flash latency for < 30Mhz clock (0-WS) e.g. HSI/HSE */ +#define STM32_FLASH_ACR_LATENCY_SLOW 0 #elif defined(CHIP_VARIANT_STM32F412) /* Required or recommended clocks for stm32f412 */ #define STM32F4_PLL_REQ 2000000 #define STM32F4_RTC_REQ 1000000 -#define STM32F4_IO_CLOCK 48000000 +#define STM32F4_IO_CLOCK 48000000 #define STM32F4_USB_REQ 48000000 #define STM32F4_VCO_CLOCK 384000000 #define STM32F4_HSI_CLOCK 16000000 @@ -432,13 +430,15 @@ #define STM32F4_AHB_PRE 0x0 #define STM32F4_APB1_PRE 0x4 #define STM32F4_APB2_PRE 0x4 -#define STM32_FLASH_ACR_LATENCY (3 << 0) +#define STM32_FLASH_ACR_LATENCY (3 << 0) +/* optimized flash latency for < 30Mhz clock (0-WS) e.g. HSI/HSE */ +#define STM32_FLASH_ACR_LATENCY_SLOW 0 #elif defined(CHIP_VARIANT_STM32F411) /* Required or recommended clocks for stm32f411 */ #define STM32F4_PLL_REQ 2000000 #define STM32F4_RTC_REQ 1000000 -#define STM32F4_IO_CLOCK 48000000 +#define STM32F4_IO_CLOCK 48000000 #define STM32F4_USB_REQ 48000000 #define STM32F4_VCO_CLOCK 384000000 #define STM32F4_HSI_CLOCK 16000000 @@ -448,200 +448,205 @@ #define STM32F4_AHB_PRE 0x8 #define STM32F4_APB1_PRE 0x0 #define STM32F4_APB2_PRE 0x0 -#define STM32_FLASH_ACR_LATENCY BIT(0) +#define STM32_FLASH_ACR_LATENCY BIT(0) +/* optimized flash latency for < 30Mhz clock (0-WS) e.g. HSI/HSE */ +#define STM32_FLASH_ACR_LATENCY_SLOW 0 #elif defined(CHIP_VARIANT_STM32F76X) /* Required or recommended clocks for stm32f767/769 */ #define STM32F4_PLL_REQ 2000000 #define STM32F4_RTC_REQ 1000000 #define STM32F4_IO_CLOCK 45000000 -#define STM32F4_USB_REQ 45000000 /* not compatible with USB, will use PLLSAI */ +#define STM32F4_USB_REQ \ + 45000000 /* not compatible with USB, will use PLLSAI \ + */ #define STM32F4_VCO_CLOCK 360000000 #define STM32F4_HSI_CLOCK 16000000 #define STM32F4_LSI_CLOCK 32000 #define STM32F4_TIMER_CLOCK (STM32F4_IO_CLOCK * 2) -#define STM32F4_PLLP_DIV 2 /* sys = VCO/2 = 180 Mhz */ -#define STM32F4_AHB_PRE 0x0 /* AHB = sysclk = 180 Mhz */ +#define STM32F4_PLLP_DIV 2 /* sys = VCO/2 = 180 Mhz */ +#define STM32F4_AHB_PRE 0x0 /* AHB = sysclk = 180 Mhz */ #define STM32F4_APB1_PRE 0x5 /* APB1 = AHB /4 = 45 Mhz */ #define STM32F4_APB2_PRE 0x5 /* APB2 = AHB /4 = 45 Mhz */ -#define STM32_FLASH_ACR_LATENCY (5 << 0) +#define STM32_FLASH_ACR_LATENCY (5 << 0) +/* optimized flash latency for < 30Mhz clock (0-WS) e.g. HSI/HSE */ +#define STM32_FLASH_ACR_LATENCY_SLOW 0 #else #error "No valid clocks defined" #endif -#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x04) +#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x04) /* PLL Division factor */ -#define PLLCFGR_PLLM_OFF 0 -#define PLLCFGR_PLLM(val) (((val) & 0x1f) << PLLCFGR_PLLM_OFF) +#define PLLCFGR_PLLM_OFF 0 +#define PLLCFGR_PLLM(val) (((val)&0x1f) << PLLCFGR_PLLM_OFF) /* PLL Multiplication factor */ -#define PLLCFGR_PLLN_OFF 6 -#define PLLCFGR_PLLN(val) (((val) & 0x1ff) << PLLCFGR_PLLN_OFF) +#define PLLCFGR_PLLN_OFF 6 +#define PLLCFGR_PLLN(val) (((val)&0x1ff) << PLLCFGR_PLLN_OFF) /* Main CPU Clock */ -#define PLLCFGR_PLLP_OFF 16 -#define PLLCFGR_PLLP(val) (((val) & 0x3) << PLLCFGR_PLLP_OFF) +#define PLLCFGR_PLLP_OFF 16 +#define PLLCFGR_PLLP(val) (((val)&0x3) << PLLCFGR_PLLP_OFF) -#define PLLCFGR_PLLSRC_HSI (0 << 22) -#define PLLCFGR_PLLSRC_HSE BIT(22) +#define PLLCFGR_PLLSRC_HSI (0 << 22) +#define PLLCFGR_PLLSRC_HSE BIT(22) /* USB OTG FS: Must equal 48MHz */ -#define PLLCFGR_PLLQ_OFF 24 -#define PLLCFGR_PLLQ(val) (((val) & 0xf) << PLLCFGR_PLLQ_OFF) +#define PLLCFGR_PLLQ_OFF 24 +#define PLLCFGR_PLLQ(val) (((val)&0xf) << PLLCFGR_PLLQ_OFF) /* SYSTEM */ -#define PLLCFGR_PLLR_OFF 28 -#define PLLCFGR_PLLR(val) (((val) & 0x7) << PLLCFGR_PLLR_OFF) - -#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) -#define STM32_RCC_CFGR_SW_HSI (0 << 0) -#define STM32_RCC_CFGR_SW_HSE (1 << 0) -#define STM32_RCC_CFGR_SW_PLL (2 << 0) -#define STM32_RCC_CFGR_SW_PLL_R (3 << 0) -#define STM32_RCC_CFGR_SW_MASK (3 << 0) -#define STM32_RCC_CFGR_SWS_HSI (0 << 2) -#define STM32_RCC_CFGR_SWS_HSE (1 << 2) -#define STM32_RCC_CFGR_SWS_PLL (2 << 2) -#define STM32_RCC_CFGR_SWS_PLL_R (3 << 2) -#define STM32_RCC_CFGR_SWS_MASK (3 << 2) +#define PLLCFGR_PLLR_OFF 28 +#define PLLCFGR_PLLR(val) (((val)&0x7) << PLLCFGR_PLLR_OFF) + +#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) +#define STM32_RCC_CFGR_SW_HSI (0 << 0) +#define STM32_RCC_CFGR_SW_HSE (1 << 0) +#define STM32_RCC_CFGR_SW_PLL (2 << 0) +#define STM32_RCC_CFGR_SW_PLL_R (3 << 0) +#define STM32_RCC_CFGR_SW_MASK (3 << 0) +#define STM32_RCC_CFGR_SWS_HSI (0 << 2) +#define STM32_RCC_CFGR_SWS_HSE (1 << 2) +#define STM32_RCC_CFGR_SWS_PLL (2 << 2) +#define STM32_RCC_CFGR_SWS_PLL_R (3 << 2) +#define STM32_RCC_CFGR_SWS_MASK (3 << 2) /* AHB Prescalar: nonlinear values, look up in RM0390 */ -#define CFGR_HPRE_OFF 4 -#define CFGR_HPRE(val) (((val) & 0xf) << CFGR_HPRE_OFF) +#define CFGR_HPRE_OFF 4 +#define CFGR_HPRE(val) (((val)&0xf) << CFGR_HPRE_OFF) /* APB1 Low Speed Prescalar < 45MHz */ -#define CFGR_PPRE1_OFF 10 -#define CFGR_PPRE1(val) (((val) & 0x7) << CFGR_PPRE1_OFF) +#define CFGR_PPRE1_OFF 10 +#define CFGR_PPRE1(val) (((val)&0x7) << CFGR_PPRE1_OFF) /* APB2 High Speed Prescalar < 90MHz */ -#define CFGR_PPRE2_OFF 13 -#define CFGR_PPRE2(val) (((val) & 0x7) << CFGR_PPRE2_OFF) +#define CFGR_PPRE2_OFF 13 +#define CFGR_PPRE2(val) (((val)&0x7) << CFGR_PPRE2_OFF) /* RTC CLock: Must equal 1MHz */ -#define CFGR_RTCPRE_OFF 16 -#define CFGR_RTCPRE(val) (((val) & 0x1f) << CFGR_RTCPRE_OFF) - -#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x0C) -#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x10) -#define RCC_AHB1RSTR_OTGHSRST BIT(29) - -#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x14) -#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x18) - -#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x20) -#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x24) - -#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x30) -#define STM32_RCC_AHB1ENR_GPIO_PORTA BIT(0) -#define STM32_RCC_AHB1ENR_GPIO_PORTB BIT(1) -#define STM32_RCC_AHB1ENR_GPIO_PORTC BIT(2) -#define STM32_RCC_AHB1ENR_GPIO_PORTD BIT(3) -#define STM32_RCC_AHB1ENR_GPIO_PORTE BIT(4) -#define STM32_RCC_AHB1ENR_GPIO_PORTF BIT(5) -#define STM32_RCC_AHB1ENR_GPIO_PORTG BIT(6) -#define STM32_RCC_AHB1ENR_GPIO_PORTH BIT(7) -#define STM32_RCC_AHB1ENR_GPIOMASK (0xff << 0) -#define STM32_RCC_AHB1ENR_BKPSRAMEN BIT(18) -#define STM32_RCC_AHB1ENR_DMA1EN BIT(21) -#define STM32_RCC_AHB1ENR_DMA2EN BIT(22) +#define CFGR_RTCPRE_OFF 16 +#define CFGR_RTCPRE(val) (((val)&0x1f) << CFGR_RTCPRE_OFF) + +#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x0C) +#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x10) +#define RCC_AHB1RSTR_OTGHSRST BIT(29) + +#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x14) +#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x18) + +#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x20) +#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x24) + +#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x30) +#define STM32_RCC_AHB1ENR_GPIO_PORTA BIT(0) +#define STM32_RCC_AHB1ENR_GPIO_PORTB BIT(1) +#define STM32_RCC_AHB1ENR_GPIO_PORTC BIT(2) +#define STM32_RCC_AHB1ENR_GPIO_PORTD BIT(3) +#define STM32_RCC_AHB1ENR_GPIO_PORTE BIT(4) +#define STM32_RCC_AHB1ENR_GPIO_PORTF BIT(5) +#define STM32_RCC_AHB1ENR_GPIO_PORTG BIT(6) +#define STM32_RCC_AHB1ENR_GPIO_PORTH BIT(7) +#define STM32_RCC_AHB1ENR_GPIOMASK (0xff << 0) +#define STM32_RCC_AHB1ENR_BKPSRAMEN BIT(18) +#define STM32_RCC_AHB1ENR_DMA1EN BIT(21) +#define STM32_RCC_AHB1ENR_DMA2EN BIT(22) /* TODO(nsanders): normalize naming.*/ -#define STM32_RCC_HB1_DMA1 BIT(21) -#define STM32_RCC_HB1_DMA2 BIT(22) -#define STM32_RCC_AHB1ENR_OTGHSEN BIT(29) -#define STM32_RCC_AHB1ENR_OTGHSULPIEN BIT(30) - -#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x34) -#define STM32_RCC_AHB2ENR_RNGEN BIT(6) -#define STM32_RCC_AHB2ENR_OTGFSEN BIT(7) -#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x38) - -#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x40) -#define STM32_RCC_PWREN BIT(28) -#define STM32_RCC_I2C1EN BIT(21) -#define STM32_RCC_I2C2EN BIT(22) -#define STM32_RCC_I2C3EN BIT(23) -#define STM32_RCC_FMPI2C4EN BIT(24) - -#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x44) -#define STM32_RCC_APB2ENR_ADC1EN BIT(8) /* STM32F4 */ - -#define STM32_RCC_PB2_USART6 BIT(5) -#define STM32_RCC_SYSCFGEN BIT(14) - -#define STM32_RCC_AHB1LPENR REG32(STM32_RCC_BASE + 0x50) -#define STM32_RCC_AHB2LPENR REG32(STM32_RCC_BASE + 0x54) -#define STM32_RCC_AHB3LPENR REG32(STM32_RCC_BASE + 0x58) -#define STM32_RCC_APB1LPENR REG32(STM32_RCC_BASE + 0x60) -#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x64) - -#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x70) -#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x74) -#define STM32_RCC_CSR_LSION BIT(0) -#define STM32_RCC_CSR_LSIRDY BIT(1) - -#define STM32_RCC_PB2_TIM1 BIT(0) -#define STM32_RCC_PB2_TIM8 BIT(1) -#define STM32_RCC_PB2_TIM9 BIT(16) -#define STM32_RCC_PB2_TIM10 BIT(17) -#define STM32_RCC_PB2_TIM11 BIT(18) - -#define STM32_RCC_DCKCFGR2 REG32(STM32_RCC_BASE + 0x94) -#define DCKCFGR2_FMPI2C1SEL(val) (((val) & 0x3) << 22) -#define DCKCFGR2_FMPI2C1SEL_MASK (0x3 << 22) -#define FMPI2C1SEL_APB 0x0 - -#define STM32_SYSCFG_MEMRMP REG32(STM32_SYSCFG_BASE + 0x00) -#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04) -#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) -#define STM32_SYSCFG_CMPCR REG32(STM32_SYSCFG_BASE + 0x20) -#define STM32_SYSCFG_CFGR REG32(STM32_SYSCFG_BASE + 0x2C) - +#define STM32_RCC_HB1_DMA1 BIT(21) +#define STM32_RCC_HB1_DMA2 BIT(22) +#define STM32_RCC_AHB1ENR_OTGHSEN BIT(29) +#define STM32_RCC_AHB1ENR_OTGHSULPIEN BIT(30) + +#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x34) +#define STM32_RCC_AHB2ENR_RNGEN BIT(6) +#define STM32_RCC_AHB2ENR_OTGFSEN BIT(7) +#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x38) + +#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x40) +#define STM32_RCC_PWREN BIT(28) +#define STM32_RCC_I2C1EN BIT(21) +#define STM32_RCC_I2C2EN BIT(22) +#define STM32_RCC_I2C3EN BIT(23) +#define STM32_RCC_FMPI2C4EN BIT(24) + +#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x44) +#define STM32_RCC_APB2ENR_ADC1EN BIT(8) /* STM32F4 */ + +#define STM32_RCC_PB2_USART6 BIT(5) +#define STM32_RCC_SYSCFGEN BIT(14) + +#define STM32_RCC_AHB1LPENR REG32(STM32_RCC_BASE + 0x50) +#define STM32_RCC_AHB2LPENR REG32(STM32_RCC_BASE + 0x54) +#define STM32_RCC_AHB3LPENR REG32(STM32_RCC_BASE + 0x58) +#define STM32_RCC_APB1LPENR REG32(STM32_RCC_BASE + 0x60) +#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x64) + +#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x70) +#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x74) +#define STM32_RCC_CSR_LSION BIT(0) +#define STM32_RCC_CSR_LSIRDY BIT(1) + +#define STM32_RCC_PB2_TIM1 BIT(0) +#define STM32_RCC_PB2_TIM8 BIT(1) +#define STM32_RCC_PB2_TIM9 BIT(16) +#define STM32_RCC_PB2_TIM10 BIT(17) +#define STM32_RCC_PB2_TIM11 BIT(18) + +#define STM32_RCC_DCKCFGR2 REG32(STM32_RCC_BASE + 0x94) +#define DCKCFGR2_FMPI2C1SEL(val) (((val)&0x3) << 22) +#define DCKCFGR2_FMPI2C1SEL_MASK (0x3 << 22) +#define FMPI2C1SEL_APB 0x0 + +#define STM32_SYSCFG_MEMRMP REG32(STM32_SYSCFG_BASE + 0x00) +#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04) +#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) +#define STM32_SYSCFG_CMPCR REG32(STM32_SYSCFG_BASE + 0x20) +#define STM32_SYSCFG_CFGR REG32(STM32_SYSCFG_BASE + 0x2C) /* Peripheral bits for RCC_APB/AHB regs */ -#define STM32_RCC_PB2_USART1 BIT(4) +#define STM32_RCC_PB2_USART1 BIT(4) /* Reset causes definitions */ /* Reset causes in RCC CSR register */ #define STM32_RCC_RESET_CAUSE STM32_RCC_CSR -#define RESET_CAUSE_WDG (BIT(30)|BIT(29)) -#define RESET_CAUSE_SFT BIT(28) -#define RESET_CAUSE_POR BIT(27) -#define RESET_CAUSE_PIN BIT(26) -#define RESET_CAUSE_OTHER (BIT(31)|BIT(30)|BIT(29)|BIT(28)| \ - BIT(27)|BIT(26)|BIT(25)) -#define RESET_CAUSE_RMVF BIT(24) +#define RESET_CAUSE_WDG (BIT(30) | BIT(29)) +#define RESET_CAUSE_SFT BIT(28) +#define RESET_CAUSE_POR BIT(27) +#define RESET_CAUSE_PIN BIT(26) +#define RESET_CAUSE_OTHER \ + (BIT(31) | BIT(30) | BIT(29) | BIT(28) | BIT(27) | BIT(26) | BIT(25)) +#define RESET_CAUSE_RMVF BIT(24) /* Power cause in PWR CSR register */ #define STM32_PWR_RESET_CAUSE STM32_PWR_CSR -#define RESET_CAUSE_SBF BIT(1) +#define RESET_CAUSE_SBF BIT(1) #define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CR -#define RESET_CAUSE_SBF_CLR BIT(3) +#define RESET_CAUSE_SBF_CLR BIT(3) /* --- Watchdogs --- */ /* --- Real-Time Clock --- */ -#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) -#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) -#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) -#define STM32_RTC_CR_BYPSHAD BIT(5) -#define STM32_RTC_CR_ALRAE BIT(8) -#define STM32_RTC_CR_ALRAIE BIT(12) -#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) -#define STM32_RTC_ISR_ALRAWF BIT(0) -#define STM32_RTC_ISR_RSF BIT(5) -#define STM32_RTC_ISR_INITF BIT(6) -#define STM32_RTC_ISR_INIT BIT(7) -#define STM32_RTC_ISR_ALRAF BIT(8) -#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) -#define STM32_RTC_PRER_A_MASK (0x7f << 16) -#define STM32_RTC_PRER_S_MASK (0x7fff << 0) -#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) -#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) -#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) -#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) -#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) -#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) -#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) -#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) -#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) -#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) -#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) - -#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) -#define STM32_BKP_BYTES 80 +#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) +#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) +#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) +#define STM32_RTC_CR_BYPSHAD BIT(5) +#define STM32_RTC_CR_ALRAE BIT(8) +#define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) +#define STM32_RTC_ISR_ALRAWF BIT(0) +#define STM32_RTC_ISR_RSF BIT(5) +#define STM32_RTC_ISR_INITF BIT(6) +#define STM32_RTC_ISR_INIT BIT(7) +#define STM32_RTC_ISR_ALRAF BIT(8) +#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) +#define STM32_RTC_PRER_A_MASK (0x7f << 16) +#define STM32_RTC_PRER_S_MASK (0x7fff << 0) +#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) +#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) +#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) +#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) +#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) +#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) +#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) +#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) +#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) +#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) +#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) + +#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) +#define STM32_BKP_BYTES 80 /* --- SPI --- */ @@ -651,15 +656,15 @@ struct stm32_spi_regs { uint16_t _pad0; uint16_t cr2; uint16_t _pad1; - unsigned sr; + unsigned int sr; uint8_t dr; uint8_t _pad2; uint16_t _pad3; - unsigned crcpr; - unsigned rxcrcr; - unsigned txcrcr; - unsigned i2scfgr; /* STM32L only */ - unsigned i2spr; /* STM32L only */ + unsigned int crcpr; + unsigned int rxcrcr; + unsigned int txcrcr; + unsigned int i2scfgr; /* STM32L only */ + unsigned int i2spr; /* STM32L only */ }; /* Must be volatile, or compiler optimizes out repeated accesses */ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; @@ -669,185 +674,181 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_SPI3_REGS ((stm32_spi_regs_t *)STM32_SPI3_BASE) #define STM32_SPI4_REGS ((stm32_spi_regs_t *)STM32_SPI4_BASE) -#define STM32_SPI_CR1_BIDIMODE BIT(15) -#define STM32_SPI_CR1_BIDIOE BIT(14) -#define STM32_SPI_CR1_CRCEN BIT(13) -#define STM32_SPI_CR1_SSM BIT(9) -#define STM32_SPI_CR1_SSI BIT(8) -#define STM32_SPI_CR1_LSBFIRST BIT(7) -#define STM32_SPI_CR1_SPE BIT(6) -#define STM32_SPI_CR1_BR_DIV64R (5 << 3) -#define STM32_SPI_CR1_BR_DIV4R BIT(3) -#define STM32_SPI_CR1_MSTR BIT(2) -#define STM32_SPI_CR1_CPOL BIT(1) -#define STM32_SPI_CR1_CPHA BIT(0) -#define STM32_SPI_CR2_FRXTH BIT(12) -#define STM32_SPI_CR2_DATASIZE(n) (((n) - 1) << 8) -#define STM32_SPI_CR2_TXEIE BIT(7) -#define STM32_SPI_CR2_RXNEIE BIT(6) -#define STM32_SPI_CR2_NSSP BIT(3) -#define STM32_SPI_CR2_SSOE BIT(2) -#define STM32_SPI_CR2_TXDMAEN BIT(1) -#define STM32_SPI_CR2_RXDMAEN BIT(0) - -#define STM32_SPI_SR_RXNE BIT(0) -#define STM32_SPI_SR_TXE BIT(1) -#define STM32_SPI_SR_CRCERR BIT(4) -#define STM32_SPI_SR_BSY BIT(7) -#define STM32_SPI_SR_FRLVL (3 << 9) -#define STM32_SPI_SR_FTLVL (3 << 11) +#define STM32_SPI_CR1_BIDIMODE BIT(15) +#define STM32_SPI_CR1_BIDIOE BIT(14) +#define STM32_SPI_CR1_CRCEN BIT(13) +#define STM32_SPI_CR1_SSM BIT(9) +#define STM32_SPI_CR1_SSI BIT(8) +#define STM32_SPI_CR1_LSBFIRST BIT(7) +#define STM32_SPI_CR1_SPE BIT(6) +#define STM32_SPI_CR1_BR_DIV64R (5 << 3) +#define STM32_SPI_CR1_BR_DIV4R BIT(3) +#define STM32_SPI_CR1_MSTR BIT(2) +#define STM32_SPI_CR1_CPOL BIT(1) +#define STM32_SPI_CR1_CPHA BIT(0) +#define STM32_SPI_CR2_FRXTH BIT(12) +#define STM32_SPI_CR2_DATASIZE(n) (((n)-1) << 8) +#define STM32_SPI_CR2_TXEIE BIT(7) +#define STM32_SPI_CR2_RXNEIE BIT(6) +#define STM32_SPI_CR2_NSSP BIT(3) +#define STM32_SPI_CR2_SSOE BIT(2) +#define STM32_SPI_CR2_TXDMAEN BIT(1) +#define STM32_SPI_CR2_RXDMAEN BIT(0) + +#define STM32_SPI_SR_RXNE BIT(0) +#define STM32_SPI_SR_TXE BIT(1) +#define STM32_SPI_SR_CRCERR BIT(4) +#define STM32_SPI_SR_BSY BIT(7) +#define STM32_SPI_SR_FRLVL (3 << 9) +#define STM32_SPI_SR_FTLVL (3 << 11) /* --- Debug --- */ -#define STM32_DBGMCU_CR_SLEEP BIT(0) -#define STM32_DBGMCU_CR_STOP BIT(1) -#define STM32_DBGMCU_CR_STBY BIT(2) -#define STM32_DBGMCU_CR_TRACE_MASK (BIT(5)|BIT(6)|BIT(7)) -#define STM32_DBGMCU_CR_TRACE_EN BIT(5) -#define STM32_DBGMCU_CR_TRACE_MODE_ASYNC 0 -#define STM32_DBGMCU_CR_TRACE_MODE_SYNC1 BIT(6) -#define STM32_DBGMCU_CR_TRACE_MODE_SYNC2 BIT(7) -#define STM32_DBGMCU_CR_TRACE_MODE_SYNC4 (BIT(6)|BIT(7)) -#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) -#define STM32_DBGMCU_APB1FZ_TIM2 BIT(0) -#define STM32_DBGMCU_APB1FZ_TIM3 BIT(1) -#define STM32_DBGMCU_APB1FZ_TIM4 BIT(2) -#define STM32_DBGMCU_APB1FZ_TIM5 BIT(3) -#define STM32_DBGMCU_APB1FZ_TIM6 BIT(4) -#define STM32_DBGMCU_APB1FZ_TIM7 BIT(5) -#define STM32_DBGMCU_APB1FZ_TIM12 BIT(6) -#define STM32_DBGMCU_APB1FZ_TIM13 BIT(7) -#define STM32_DBGMCU_APB1FZ_TIM14 BIT(8) -#define STM32_DBGMCU_APB1FZ_RTC BIT(10) -#define STM32_DBGMCU_APB1FZ_WWDG BIT(11) -#define STM32_DBGMCU_APB1FZ_IWDG BIT(12) -#define STM32_DBGMCU_APB1FZ_I2C1_SMBUS_TIMEOUT BIT(21) -#define STM32_DBGMCU_APB1FZ_I2C2_SMBUS_TIMEOUT BIT(22) -#define STM32_DBGMCU_APB1FZ_I2C3_SMBUS_TIMEOUT BIT(23) -#define STM32_DBGMCU_APB1FZ_I2CFMP_SMBUS_TIMEOUT BIT(24) -#define STM32_DBGMCU_APB1FZ_CAN1 BIT(25) -#define STM32_DBGMCU_APB1FZ_CAN2 BIT(26) -#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) -#define STM32_DBGMCU_APB2FZ_TIM1 BIT(0) -#define STM32_DBGMCU_APB2FZ_TIM8 BIT(1) -#define STM32_DBGMCU_APB2FZ_TIM9 BIT(16) -#define STM32_DBGMCU_APB2FZ_TIM10 BIT(17) -#define STM32_DBGMCU_APB2FZ_TIM11 BIT(18) +#define STM32_DBGMCU_CR_SLEEP BIT(0) +#define STM32_DBGMCU_CR_STOP BIT(1) +#define STM32_DBGMCU_CR_STBY BIT(2) +#define STM32_DBGMCU_CR_TRACE_MASK (BIT(5) | BIT(6) | BIT(7)) +#define STM32_DBGMCU_CR_TRACE_EN BIT(5) +#define STM32_DBGMCU_CR_TRACE_MODE_ASYNC 0 +#define STM32_DBGMCU_CR_TRACE_MODE_SYNC1 BIT(6) +#define STM32_DBGMCU_CR_TRACE_MODE_SYNC2 BIT(7) +#define STM32_DBGMCU_CR_TRACE_MODE_SYNC4 (BIT(6) | BIT(7)) +#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) +#define STM32_DBGMCU_APB1FZ_TIM2 BIT(0) +#define STM32_DBGMCU_APB1FZ_TIM3 BIT(1) +#define STM32_DBGMCU_APB1FZ_TIM4 BIT(2) +#define STM32_DBGMCU_APB1FZ_TIM5 BIT(3) +#define STM32_DBGMCU_APB1FZ_TIM6 BIT(4) +#define STM32_DBGMCU_APB1FZ_TIM7 BIT(5) +#define STM32_DBGMCU_APB1FZ_TIM12 BIT(6) +#define STM32_DBGMCU_APB1FZ_TIM13 BIT(7) +#define STM32_DBGMCU_APB1FZ_TIM14 BIT(8) +#define STM32_DBGMCU_APB1FZ_RTC BIT(10) +#define STM32_DBGMCU_APB1FZ_WWDG BIT(11) +#define STM32_DBGMCU_APB1FZ_IWDG BIT(12) +#define STM32_DBGMCU_APB1FZ_I2C1_SMBUS_TIMEOUT BIT(21) +#define STM32_DBGMCU_APB1FZ_I2C2_SMBUS_TIMEOUT BIT(22) +#define STM32_DBGMCU_APB1FZ_I2C3_SMBUS_TIMEOUT BIT(23) +#define STM32_DBGMCU_APB1FZ_I2CFMP_SMBUS_TIMEOUT BIT(24) +#define STM32_DBGMCU_APB1FZ_CAN1 BIT(25) +#define STM32_DBGMCU_APB1FZ_CAN2 BIT(26) +#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) +#define STM32_DBGMCU_APB2FZ_TIM1 BIT(0) +#define STM32_DBGMCU_APB2FZ_TIM8 BIT(1) +#define STM32_DBGMCU_APB2FZ_TIM9 BIT(16) +#define STM32_DBGMCU_APB2FZ_TIM10 BIT(17) +#define STM32_DBGMCU_APB2FZ_TIM11 BIT(18) /* --- Flash --- */ -#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) -#define STM32_FLASH_ACR_SHIFT 0 -#define STM32_FLASH_ACR_LAT_MASK 0xf -#define STM32_FLASH_ACR_PRFTEN BIT(8) -#define STM32_FLASH_ACR_ICEN BIT(9) -#define STM32_FLASH_ACR_DCEN BIT(10) -#define STM32_FLASH_ACR_ICRST BIT(11) -#define STM32_FLASH_ACR_DCRST BIT(12) -#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x04) -#define FLASH_KEYR_KEY1 0x45670123 -#define FLASH_KEYR_KEY2 0xCDEF89AB -#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) -#define FLASH_OPTKEYR_KEY1 0x08192A3B -#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F -#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x0c) -#define FLASH_SR_EOP BIT(0) -#define FLASH_SR_OPERR BIT(1) -#define FLASH_SR_WRPERR BIT(4) -#define FLASH_SR_PGAERR BIT(5) -#define FLASH_SR_PGPERR BIT(6) -#define FLASH_SR_PGSERR BIT(7) -#define FLASH_SR_RDERR BIT(8) -#define FLASH_SR_ALL_ERR \ +#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) +#define STM32_FLASH_ACR_SHIFT 0 +#define STM32_FLASH_ACR_LAT_MASK 0xf +#define STM32_FLASH_ACR_PRFTEN BIT(8) +#define STM32_FLASH_ACR_ICEN BIT(9) +#define STM32_FLASH_ACR_DCEN BIT(10) +#define STM32_FLASH_ACR_ICRST BIT(11) +#define STM32_FLASH_ACR_DCRST BIT(12) +#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x04) +#define FLASH_KEYR_KEY1 0x45670123 +#define FLASH_KEYR_KEY2 0xCDEF89AB +#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) +#define FLASH_OPTKEYR_KEY1 0x08192A3B +#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F +#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x0c) +#define FLASH_SR_EOP BIT(0) +#define FLASH_SR_OPERR BIT(1) +#define FLASH_SR_WRPERR BIT(4) +#define FLASH_SR_PGAERR BIT(5) +#define FLASH_SR_PGPERR BIT(6) +#define FLASH_SR_PGSERR BIT(7) +#define FLASH_SR_RDERR BIT(8) +#define FLASH_SR_ALL_ERR \ (FLASH_SR_OPERR | FLASH_SR_WRPERR | FLASH_SR_PGAERR | \ FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_RDERR) -#define FLASH_SR_BUSY BIT(16) -#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x10) -#define FLASH_CR_PG BIT(0) -#define FLASH_CR_PER BIT(1) -#define FLASH_CR_MER BIT(2) -#define STM32_FLASH_CR_SNB_OFFSET (3) -#define STM32_FLASH_CR_SNB(sec) \ - (((sec) & 0xf) << STM32_FLASH_CR_SNB_OFFSET) -#define STM32_FLASH_CR_SNB_MASK (STM32_FLASH_CR_SNB(0xf)) -#define STM32_FLASH_CR_PSIZE_OFFSET (8) -#define STM32_FLASH_CR_PSIZE(size) \ - (((size) & 0x3) << STM32_FLASH_CR_PSIZE_OFFSET) -#define STM32_FLASH_CR_PSIZE_MASK (STM32_FLASH_CR_PSIZE(0x3)) -#define FLASH_CR_STRT BIT(16) -#define FLASH_CR_LOCK BIT(31) -#define STM32_FLASH_OPTCR REG32(STM32_FLASH_REGS_BASE + 0x14) -#define FLASH_OPTLOCK BIT(0) -#define FLASH_OPTSTRT BIT(1) -#define STM32_FLASH_BOR_LEV_OFFSET (2) -#define FLASH_OPTCR_RDP_SHIFT (8) -#define FLASH_OPTCR_RDP_MASK (0xFF << FLASH_OPTCR_RDP_SHIFT) -#define FLASH_OPTCR_RDP_LEVEL_0 (0xAA << FLASH_OPTCR_RDP_SHIFT) +#define FLASH_SR_BUSY BIT(16) +#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x10) +#define FLASH_CR_PG BIT(0) +#define FLASH_CR_PER BIT(1) +#define FLASH_CR_MER BIT(2) +#define STM32_FLASH_CR_SNB_OFFSET (3) +#define STM32_FLASH_CR_SNB(sec) (((sec)&0xf) << STM32_FLASH_CR_SNB_OFFSET) +#define STM32_FLASH_CR_SNB_MASK (STM32_FLASH_CR_SNB(0xf)) +#define STM32_FLASH_CR_PSIZE_OFFSET (8) +#define STM32_FLASH_CR_PSIZE(size) (((size)&0x3) << STM32_FLASH_CR_PSIZE_OFFSET) +#define STM32_FLASH_CR_PSIZE_MASK (STM32_FLASH_CR_PSIZE(0x3)) +#define FLASH_CR_STRT BIT(16) +#define FLASH_CR_LOCK BIT(31) +#define STM32_FLASH_OPTCR REG32(STM32_FLASH_REGS_BASE + 0x14) +#define FLASH_OPTLOCK BIT(0) +#define FLASH_OPTSTRT BIT(1) +#define STM32_FLASH_BOR_LEV_OFFSET (2) +#define FLASH_OPTCR_RDP_SHIFT (8) +#define FLASH_OPTCR_RDP_MASK (0xFF << FLASH_OPTCR_RDP_SHIFT) +#define FLASH_OPTCR_RDP_LEVEL_0 (0xAA << FLASH_OPTCR_RDP_SHIFT) /* RDP Level 1: Anything but 0xAA/0xCC */ -#define FLASH_OPTCR_RDP_LEVEL_1 (0x00 << FLASH_OPTCR_RDP_SHIFT) -#define FLASH_OPTCR_RDP_LEVEL_2 (0xCC << FLASH_OPTCR_RDP_SHIFT) -#define STM32_FLASH_nWRP_OFFSET (16) -#define STM32_FLASH_nWRP(_bank) BIT(_bank + STM32_FLASH_nWRP_OFFSET) -#define STM32_FLASH_nWRP_ALL (0xFF << STM32_FLASH_nWRP_OFFSET) -#define STM32_FLASH_OPT_LOCKED (STM32_FLASH_OPTCR & FLASH_OPTLOCK) - -#define STM32_OPTB_RDP_USER REG32(STM32_OPTB_BASE + 0x00) -#define STM32_OPTB_RDP_OFF 0x00 -#define STM32_OPTB_USER_OFF 0x02 -#define STM32_OPTB_WRP_OFF(n) (0x08 + (n&3) * 2) -#define STM32_OPTB_WP REG32(STM32_OPTB_BASE + 0x08) -#define STM32_OPTB_nWRP(_bank) BIT(_bank) -#define STM32_OPTB_nWRP_ALL (0xFF) - -#define STM32_OPTB_COMPL_SHIFT 8 - -#define STM32_OTP_BLOCK_NB 16 -#define STM32_OTP_BLOCK_SIZE 32 +#define FLASH_OPTCR_RDP_LEVEL_1 (0x00 << FLASH_OPTCR_RDP_SHIFT) +#define FLASH_OPTCR_RDP_LEVEL_2 (0xCC << FLASH_OPTCR_RDP_SHIFT) +#define STM32_FLASH_nWRP_OFFSET (16) +#define STM32_FLASH_nWRP(_bank) BIT(_bank + STM32_FLASH_nWRP_OFFSET) +#define STM32_FLASH_nWRP_ALL (0xFF << STM32_FLASH_nWRP_OFFSET) +#define STM32_FLASH_OPT_LOCKED (STM32_FLASH_OPTCR & FLASH_OPTLOCK) + +#define STM32_OPTB_RDP_USER REG32(STM32_OPTB_BASE + 0x00) +#define STM32_OPTB_RDP_OFF 0x00 +#define STM32_OPTB_USER_OFF 0x02 +#define STM32_OPTB_WRP_OFF(n) (0x08 + (n & 3) * 2) +#define STM32_OPTB_WP REG32(STM32_OPTB_BASE + 0x08) +#define STM32_OPTB_nWRP(_bank) BIT(_bank) +#define STM32_OPTB_nWRP_ALL (0xFF) + +#define STM32_OPTB_COMPL_SHIFT 8 + +#define STM32_OTP_BLOCK_NB 16 +#define STM32_OTP_BLOCK_SIZE 32 #define STM32_OTP_BLOCK_DATA(_block, _offset) \ - (STM32_OTP_BASE + STM32_OTP_BLOCK_SIZE * (_block) + (_offset) * 4) -#define STM32_OTP_UNLOCK_BYTE 0x00 -#define STM32_OTP_LOCK_BYTE 0xFF -#define STM32_OTP_LOCK_BASE \ + (STM32_OTP_BASE + STM32_OTP_BLOCK_SIZE * (_block) + (_offset)*4) +#define STM32_OTP_UNLOCK_BYTE 0x00 +#define STM32_OTP_LOCK_BYTE 0xFF +#define STM32_OTP_LOCK_BASE \ (STM32_OTP_BASE + STM32_OTP_BLOCK_NB * STM32_OTP_BLOCK_SIZE) -#define STM32_OTP_LOCK(_block) \ - (STM32_OTP_LOCK_BASE + ((_block) / 4) * 4) -#define STM32_OPT_LOCK_MASK(_block) ((0xFF << ((_block) % 4) * 8)) +#define STM32_OTP_LOCK(_block) (STM32_OTP_LOCK_BASE + ((_block) / 4) * 4) +#define STM32_OPT_LOCK_MASK(_block) ((0xFF << ((_block) % 4) * 8)) /* --- External Interrupts --- */ -#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) -#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) -#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) -#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) -#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) -#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) +#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) +#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) +#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) +#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) +#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) +#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) #define EXTI_RTC_ALR_EVENT BIT(17) /* --- ADC --- */ -#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00) -#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04) -#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08) -#define STM32_ADC_CR2_ADON BIT(0) -#define STM32_ADC_CR2_CONT BIT(1) -#define STM32_ADC_CR2_CAL BIT(2) -#define STM32_ADC_CR2_RSTCAL BIT(3) -#define STM32_ADC_CR2_ALIGN BIT(11) -#define STM32_ADC_CR2_SWSTART BIT(30) -#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x0C) -#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x10) -#define STM32_ADC_JOFR(n) REG32(STM32_ADC1_BASE + 0x14 + ((n)&3) * 4) -#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x24) -#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x28) -#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x28 + ((n)&3) * 4) -#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x2C) -#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x30) -#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x34) -#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x38) -#define STM32_ADC_JDR(n) REG32(STM32_ADC1_BASE + 0x3C + ((n)&3) * 4) -#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x4C) +#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00) +#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04) +#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08) +#define STM32_ADC_CR2_ADON BIT(0) +#define STM32_ADC_CR2_CONT BIT(1) +#define STM32_ADC_CR2_CAL BIT(2) +#define STM32_ADC_CR2_RSTCAL BIT(3) +#define STM32_ADC_CR2_ALIGN BIT(11) +#define STM32_ADC_CR2_SWSTART BIT(30) +#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x0C) +#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x10) +#define STM32_ADC_JOFR(n) REG32(STM32_ADC1_BASE + 0x14 + ((n)&3) * 4) +#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x24) +#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x28) +#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x28 + ((n)&3) * 4) +#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x2C) +#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x30) +#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x34) +#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x38) +#define STM32_ADC_JDR(n) REG32(STM32_ADC1_BASE + 0x3C + ((n)&3) * 4) +#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x4C) /* --- Comparators --- */ - /* --- DMA --- */ /* * Available DMA streams, numbered from 0. @@ -915,7 +916,7 @@ enum dma_channel { STM32_DMAC_FMPI2C4_TX = STM32_DMA1_STREAM5, STM32_DMAC_FMPI2C4_RX = STM32_DMA1_STREAM2, - /* Legacy naming for spi_master.c */ + /* Legacy naming for spi_controller.c */ STM32_DMAC_SPI1_TX = STM32_DMA2_STREAM3, /* REQ 3 */ STM32_DMAC_SPI1_RX = STM32_DMA2_STREAM0, /* REQ 3 */ STM32_DMAC_SPI2_TX = STM32_DMA1_STREAM4, /* REQ 0 */ @@ -955,12 +956,12 @@ enum dma_channel { /* Registers for a single stream of a DMA controller */ struct stm32_dma_stream { - uint32_t scr; /* Control */ - uint32_t sndtr; /* Number of data to transfer */ - uint32_t spar; /* Peripheral address */ - uint32_t sm0ar; /* Memory address 0 */ - uint32_t sm1ar; /* address 1 for double buffer */ - uint32_t sfcr; /* FIFO control */ + uint32_t scr; /* Control */ + uint32_t sndtr; /* Number of data to transfer */ + uint32_t spar; /* Peripheral address */ + uint32_t sm0ar; /* Memory address 0 */ + uint32_t sm1ar; /* address 1 for double buffer */ + uint32_t sfcr; /* FIFO control */ }; /* Always use stm32_dma_stream_t so volatile keyword is included! */ @@ -969,12 +970,11 @@ typedef volatile struct stm32_dma_stream stm32_dma_stream_t; /* Common code and header file must use this */ typedef stm32_dma_stream_t dma_chan_t; struct stm32_dma_regs { - uint32_t isr[2]; - uint32_t ifcr[2]; + uint32_t isr[2]; + uint32_t ifcr[2]; stm32_dma_stream_t stream[STM32_DMAS_COUNT]; }; - /* Always use stm32_dma_regs_t so volatile keyword is included! */ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; @@ -985,184 +985,106 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_DMA_REGS(channel) \ ((channel) < STM32_DMAS_COUNT ? STM32_DMA1_REGS : STM32_DMA2_REGS) -#define STM32_DMA_CCR_EN BIT(0) -#define STM32_DMA_CCR_DMEIE BIT(1) -#define STM32_DMA_CCR_TEIE BIT(2) -#define STM32_DMA_CCR_HTIE BIT(3) -#define STM32_DMA_CCR_TCIE BIT(4) -#define STM32_DMA_CCR_PFCTRL BIT(5) -#define STM32_DMA_CCR_DIR_P2M (0 << 6) -#define STM32_DMA_CCR_DIR_M2P (1 << 6) -#define STM32_DMA_CCR_DIR_M2M (2 << 6) -#define STM32_DMA_CCR_CIRC BIT(8) -#define STM32_DMA_CCR_PINC BIT(9) -#define STM32_DMA_CCR_MINC BIT(10) -#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 11) -#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 11) -#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 11) -#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 13) -#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 13) -#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 13) -#define STM32_DMA_CCR_PINCOS BIT(15) -#define STM32_DMA_CCR_PL_LOW (0 << 16) -#define STM32_DMA_CCR_PL_MEDIUM (1 << 16) -#define STM32_DMA_CCR_PL_HIGH (2 << 16) -#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 16) -#define STM32_DMA_CCR_DBM BIT(18) -#define STM32_DMA_CCR_CT BIT(19) -#define STM32_DMA_CCR_PBURST(b_len) ((((b_len) - 4) / 4) << 21) -#define STM32_DMA_CCR_MBURST(b_len) ((((b_len) - 4) / 4) << 21) -#define STM32_DMA_CCR_CHANNEL_MASK (0x7 << 25) -#define STM32_DMA_CCR_CHANNEL(channel) ((channel) << 25) -#define STM32_DMA_CCR_RSVD_MASK (0xF0100000) - - -#define STM32_DMA_SFCR_DMDIS BIT(2) -#define STM32_DMA_SFCR_FTH(level) (((level) - 1) << 0) - - -#define STM32_DMA_CH_LOCAL(channel) ((channel) % STM32_DMAS_COUNT) -#define STM32_DMA_CH_LH(channel) \ - ((STM32_DMA_CH_LOCAL(channel) < 4) ? 0 : 1) -#define STM32_DMA_CH_OFFSET(channel) \ +#define STM32_DMA_CCR_EN BIT(0) +#define STM32_DMA_CCR_DMEIE BIT(1) +#define STM32_DMA_CCR_TEIE BIT(2) +#define STM32_DMA_CCR_HTIE BIT(3) +#define STM32_DMA_CCR_TCIE BIT(4) +#define STM32_DMA_CCR_PFCTRL BIT(5) +#define STM32_DMA_CCR_DIR_P2M (0 << 6) +#define STM32_DMA_CCR_DIR_M2P (1 << 6) +#define STM32_DMA_CCR_DIR_M2M (2 << 6) +#define STM32_DMA_CCR_CIRC BIT(8) +#define STM32_DMA_CCR_PINC BIT(9) +#define STM32_DMA_CCR_MINC BIT(10) +#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 11) +#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 11) +#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 11) +#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 13) +#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 13) +#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 13) +#define STM32_DMA_CCR_PINCOS BIT(15) +#define STM32_DMA_CCR_PL_LOW (0 << 16) +#define STM32_DMA_CCR_PL_MEDIUM (1 << 16) +#define STM32_DMA_CCR_PL_HIGH (2 << 16) +#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 16) +#define STM32_DMA_CCR_DBM BIT(18) +#define STM32_DMA_CCR_CT BIT(19) +#define STM32_DMA_CCR_PBURST(b_len) ((((b_len)-4) / 4) << 21) +#define STM32_DMA_CCR_MBURST(b_len) ((((b_len)-4) / 4) << 21) +#define STM32_DMA_CCR_CHANNEL_MASK (0x7 << 25) +#define STM32_DMA_CCR_CHANNEL(channel) ((channel) << 25) +#define STM32_DMA_CCR_RSVD_MASK (0xF0100000) + +#define STM32_DMA_SFCR_DMDIS BIT(2) +#define STM32_DMA_SFCR_FTH(level) (((level)-1) << 0) + +#define STM32_DMA_CH_LOCAL(channel) ((channel) % STM32_DMAS_COUNT) +#define STM32_DMA_CH_LH(channel) ((STM32_DMA_CH_LOCAL(channel) < 4) ? 0 : 1) +#define STM32_DMA_CH_OFFSET(channel) \ (((STM32_DMA_CH_LOCAL(channel) % 4) * 6) + \ - (((STM32_DMA_CH_LOCAL(channel) % 4) >= 2) ? 4 : 0)) + (((STM32_DMA_CH_LOCAL(channel) % 4) >= 2) ? 4 : 0)) #define STM32_DMA_CH_GETBITS(channel, val) \ (((val) >> STM32_DMA_CH_OFFSET(channel)) & 0x3f) -#define STM32_DMA_GET_IFCR(channel) \ - (STM32_DMA_CH_GETBITS(channel, \ - STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)])) -#define STM32_DMA_GET_ISR(channel) \ - (STM32_DMA_CH_GETBITS(channel, \ - STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)])) - -#define STM32_DMA_SET_IFCR(channel, val) \ - (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] = \ - (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] & \ - ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & 0x3f) << STM32_DMA_CH_OFFSET(channel))) -#define STM32_DMA_SET_ISR(channel, val) \ - (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] = \ - (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] & \ - ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & 0x3f) << STM32_DMA_CH_OFFSET(channel))) - -#define STM32_DMA_FEIF BIT(0) -#define STM32_DMA_DMEIF BIT(2) -#define STM32_DMA_TEIF BIT(3) -#define STM32_DMA_HTIF BIT(4) -#define STM32_DMA_TCIF BIT(5) -#define STM32_DMA_ALL 0x3d - - +#define STM32_DMA_GET_IFCR(channel) \ + (STM32_DMA_CH_GETBITS( \ + channel, \ + STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)])) +#define STM32_DMA_GET_ISR(channel) \ + (STM32_DMA_CH_GETBITS( \ + channel, \ + STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)])) + +#define STM32_DMA_SET_IFCR(channel, val) \ + (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] = \ + (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] & \ + ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&0x3f) << STM32_DMA_CH_OFFSET(channel))) +#define STM32_DMA_SET_ISR(channel, val) \ + (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] = \ + (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] & \ + ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&0x3f) << STM32_DMA_CH_OFFSET(channel))) + +#define STM32_DMA_FEIF BIT(0) +#define STM32_DMA_DMEIF BIT(2) +#define STM32_DMA_TEIF BIT(3) +#define STM32_DMA_HTIF BIT(4) +#define STM32_DMA_TCIF BIT(5) +#define STM32_DMA_ALL 0x3d /* --- CRC --- */ -#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) - -#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) -#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) -#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) -#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) - -#define STM32_CRC_CR_RESET BIT(0) -#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) -#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) -#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) -#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) -#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) -#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) -#define STM32_CRC_CR_REV_IN_WORD (3 << 5) -#define STM32_CRC_CR_REV_OUT BIT(7) - -/* --- PMSE --- */ -#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) -#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) -#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) -#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) -#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) -#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) -#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) -#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x) * 4) -#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) -#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) -#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) -#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) -#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) -#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) -#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) -#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) -#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) -#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) -#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) - -/* --- USB --- */ -#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n) * 4) - -#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) - -#define STM32_USB_CNTR_FRES BIT(0) -#define STM32_USB_CNTR_PDWN BIT(1) -#define STM32_USB_CNTR_LP_MODE BIT(2) -#define STM32_USB_CNTR_FSUSP BIT(3) -#define STM32_USB_CNTR_RESUME BIT(4) -#define STM32_USB_CNTR_L1RESUME BIT(5) -#define STM32_USB_CNTR_L1REQM BIT(7) -#define STM32_USB_CNTR_ESOFM BIT(8) -#define STM32_USB_CNTR_SOFM BIT(9) -#define STM32_USB_CNTR_RESETM BIT(10) -#define STM32_USB_CNTR_SUSPM BIT(11) -#define STM32_USB_CNTR_WKUPM BIT(12) -#define STM32_USB_CNTR_ERRM BIT(13) -#define STM32_USB_CNTR_PMAOVRM BIT(14) -#define STM32_USB_CNTR_CTRM BIT(15) - -#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) - -#define STM32_USB_ISTR_EP_ID_MASK (0x000f) -#define STM32_USB_ISTR_DIR BIT(4) -#define STM32_USB_ISTR_L1REQ BIT(7) -#define STM32_USB_ISTR_ESOF BIT(8) -#define STM32_USB_ISTR_SOF BIT(9) -#define STM32_USB_ISTR_RESET BIT(10) -#define STM32_USB_ISTR_SUSP BIT(11) -#define STM32_USB_ISTR_WKUP BIT(12) -#define STM32_USB_ISTR_ERR BIT(13) -#define STM32_USB_ISTR_PMAOVR BIT(14) -#define STM32_USB_ISTR_CTR BIT(15) - -#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) - -#define STM32_USB_FNR_RXDP_RXDM_SHIFT (14) -#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) - -#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) -#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) -#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) -#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) - -#define STM32_USB_BCDR_BCDEN BIT(0) -#define STM32_USB_BCDR_DCDEN BIT(1) -#define STM32_USB_BCDR_PDEN BIT(2) -#define STM32_USB_BCDR_SDEN BIT(3) -#define STM32_USB_BCDR_DCDET BIT(4) -#define STM32_USB_BCDR_PDET BIT(5) -#define STM32_USB_BCDR_SDET BIT(6) -#define STM32_USB_BCDR_PS2DET BIT(7) - -#define EP_MASK 0x0F0F -#define EP_TX_DTOG 0x0040 -#define EP_TX_MASK 0x0030 +#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) + +#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) +#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) +#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) +#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) + +#define STM32_CRC_CR_RESET BIT(0) +#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) +#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) +#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) +#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) +#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) +#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) +#define STM32_CRC_CR_REV_IN_WORD (3 << 5) +#define STM32_CRC_CR_REV_OUT BIT(7) + +#define EP_MASK 0x0F0F +#define EP_TX_DTOG 0x0040 +#define EP_TX_MASK 0x0030 #define EP_TX_VALID 0x0030 -#define EP_TX_NAK 0x0020 +#define EP_TX_NAK 0x0020 #define EP_TX_STALL 0x0010 #define EP_TX_DISAB 0x0000 -#define EP_RX_DTOG 0x4000 -#define EP_RX_MASK 0x3000 +#define EP_RX_DTOG 0x4000 +#define EP_RX_MASK 0x3000 #define EP_RX_VALID 0x3000 -#define EP_RX_NAK 0x2000 +#define EP_RX_NAK 0x2000 #define EP_RX_STALL 0x1000 #define EP_RX_DISAB 0x0000 @@ -1172,28 +1094,27 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define EP_TX_RX_VALID (EP_TX_VALID | EP_RX_VALID) #define STM32_TOGGLE_EP(n, mask, val, flags) \ - STM32_USB_EP(n) = (((STM32_USB_EP(n) & (EP_MASK | (mask))) \ - ^ (val)) | (flags)) + STM32_USB_EP(n) = \ + (((STM32_USB_EP(n) & (EP_MASK | (mask))) ^ (val)) | (flags)) /* --- TRNG --- */ -#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) -#define STM32_RNG_CR_RNGEN BIT(2) -#define STM32_RNG_CR_IE BIT(3) -#define STM32_RNG_CR_CED BIT(5) -#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) -#define STM32_RNG_SR_DRDY BIT(0) -#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) +#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) +#define STM32_RNG_CR_RNGEN BIT(2) +#define STM32_RNG_CR_IE BIT(3) +#define STM32_RNG_CR_CED BIT(5) +#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) +#define STM32_RNG_SR_DRDY BIT(0) +#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) /* --- AXI interconnect --- */ /* STM32H7: AXI_TARGx_FN_MOD exists for masters x = 1, 2 and 7 */ -#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + \ - 0x1000 * (x)) -#define WRITE_ISS_OVERRIDE BIT(1) -#define READ_ISS_OVERRIDE BIT(0) +#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + 0x1000 * (x)) +#define WRITE_ISS_OVERRIDE BIT(1) +#define READ_ISS_OVERRIDE BIT(0) /* --- MISC --- */ -#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) -#define STM32_UNIQUE_ID_LENGTH (3 * 4) +#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) +#define STM32_UNIQUE_ID_LENGTH (3 * 4) #endif /* !__ASSEMBLER__ */ diff --git a/chip/stm32/registers-stm32f7.h b/chip/stm32/registers-stm32f7.h index 2245d6775f..37c89bbe07 100644 --- a/chip/stm32/registers-stm32f7.h +++ b/chip/stm32/registers-stm32f7.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,100 +19,99 @@ #endif /* --- IRQ numbers --- */ -#define STM32_IRQ_WWDG 0 -#define STM32_IRQ_PVD 1 -#define STM32_IRQ_TAMPER_STAMP 2 -#define STM32_IRQ_RTC_WAKEUP 3 -#define STM32_IRQ_FLASH 4 -#define STM32_IRQ_RCC 5 -#define STM32_IRQ_EXTI0 6 -#define STM32_IRQ_EXTI1 7 -#define STM32_IRQ_EXTI2 8 -#define STM32_IRQ_EXTI3 9 -#define STM32_IRQ_EXTI4 10 -#define STM32_IRQ_DMA_CHANNEL_1 11 -#define STM32_IRQ_DMA_CHANNEL_2 12 -#define STM32_IRQ_DMA_CHANNEL_3 13 -#define STM32_IRQ_DMA_CHANNEL_4 14 -#define STM32_IRQ_DMA_CHANNEL_5 15 -#define STM32_IRQ_DMA_CHANNEL_6 16 -#define STM32_IRQ_DMA_CHANNEL_7 17 -#define STM32_IRQ_USB_HP 19 -#define STM32_IRQ_USB_LP 20 - -#define STM32_IRQ_ADC1 18 /* STM32L4 only */ -#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ -#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ -#define STM32_IRQ_DAC 21 -#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ - -#define STM32_IRQ_COMP 22 - -#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ -#define STM32_IRQ_EXTI9_5 23 -#define STM32_IRQ_LCD 24 /* STM32L15X only */ -#define STM32_IRQ_TIM15 24 /* STM32F373 only */ -#define STM32_IRQ_TIM9 25 /* STM32L15X only */ -#define STM32_IRQ_TIM16 25 /* STM32F373 only */ -#define STM32_IRQ_TIM10 26 /* STM32L15X only */ -#define STM32_IRQ_TIM17 26 /* STM32F373 only */ -#define STM32_IRQ_TIM11 27 /* STM32L15X only */ -#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */ -#define STM32_IRQ_TIM2 28 -#define STM32_IRQ_TIM3 29 -#define STM32_IRQ_TIM4 30 -#define STM32_IRQ_I2C1_EV 31 -#define STM32_IRQ_I2C1_ER 32 -#define STM32_IRQ_I2C2_EV 33 -#define STM32_IRQ_I2C2_ER 34 -#define STM32_IRQ_SPI1 35 -#define STM32_IRQ_SPI2 36 -#define STM32_IRQ_USART1 37 -#define STM32_IRQ_USART2 38 -#define STM32_IRQ_USART3 39 -#define STM32_IRQ_EXTI15_10 40 -#define STM32_IRQ_RTC_ALARM 41 -#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ -#define STM32_IRQ_CEC 42 /* STM32F373 only */ -#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ -#define STM32_IRQ_TIM12 43 /* STM32F373 only */ -#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ -#define STM32_IRQ_TIM13 44 /* STM32F373 only */ -#define STM32_IRQ_TIM14 45 /* STM32F373 only */ -#define STM32_IRQ_TIM5 50 /* STM32F373 */ -#define STM32_IRQ_SPI3 51 /* STM32F373 */ -#define STM32_IRQ_USART4 52 /* STM32F446 only */ -#define STM32_IRQ_USART5 53 /* STM32F446 only */ -#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ -#define STM32_IRQ_TIM7 55 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ +#define STM32_IRQ_WWDG 0 +#define STM32_IRQ_PVD 1 +#define STM32_IRQ_TAMPER_STAMP 2 +#define STM32_IRQ_RTC_WAKEUP 3 +#define STM32_IRQ_FLASH 4 +#define STM32_IRQ_RCC 5 +#define STM32_IRQ_EXTI0 6 +#define STM32_IRQ_EXTI1 7 +#define STM32_IRQ_EXTI2 8 +#define STM32_IRQ_EXTI3 9 +#define STM32_IRQ_EXTI4 10 +#define STM32_IRQ_DMA_CHANNEL_1 11 +#define STM32_IRQ_DMA_CHANNEL_2 12 +#define STM32_IRQ_DMA_CHANNEL_3 13 +#define STM32_IRQ_DMA_CHANNEL_4 14 +#define STM32_IRQ_DMA_CHANNEL_5 15 +#define STM32_IRQ_DMA_CHANNEL_6 16 +#define STM32_IRQ_DMA_CHANNEL_7 17 +#define STM32_IRQ_USB_HP 19 +#define STM32_IRQ_USB_LP 20 + +#define STM32_IRQ_ADC1 18 /* STM32L4 only */ +#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ +#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ +#define STM32_IRQ_DAC 21 +#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ + +#define STM32_IRQ_COMP 22 + +#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ +#define STM32_IRQ_EXTI9_5 23 +#define STM32_IRQ_LCD 24 /* STM32L15X only */ +#define STM32_IRQ_TIM15 24 /* STM32F373 only */ +#define STM32_IRQ_TIM9 25 /* STM32L15X only */ +#define STM32_IRQ_TIM16 25 /* STM32F373 only */ +#define STM32_IRQ_TIM10 26 /* STM32L15X only */ +#define STM32_IRQ_TIM17 26 /* STM32F373 only */ +#define STM32_IRQ_TIM11 27 /* STM32L15X only */ +#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */ +#define STM32_IRQ_TIM2 28 +#define STM32_IRQ_TIM3 29 +#define STM32_IRQ_TIM4 30 +#define STM32_IRQ_I2C1_EV 31 +#define STM32_IRQ_I2C1_ER 32 +#define STM32_IRQ_I2C2_EV 33 +#define STM32_IRQ_I2C2_ER 34 +#define STM32_IRQ_SPI1 35 +#define STM32_IRQ_SPI2 36 +#define STM32_IRQ_USART1 37 +#define STM32_IRQ_USART2 38 +#define STM32_IRQ_USART3 39 +#define STM32_IRQ_EXTI15_10 40 +#define STM32_IRQ_RTC_ALARM 41 +#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ +#define STM32_IRQ_CEC 42 /* STM32F373 only */ +#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ +#define STM32_IRQ_TIM12 43 /* STM32F373 only */ +#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ +#define STM32_IRQ_TIM13 44 /* STM32F373 only */ +#define STM32_IRQ_TIM14 45 /* STM32F373 only */ +#define STM32_IRQ_TIM5 50 /* STM32F373 */ +#define STM32_IRQ_SPI3 51 /* STM32F373 */ +#define STM32_IRQ_USART4 52 /* STM32F446 only */ +#define STM32_IRQ_USART5 53 /* STM32F446 only */ +#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ +#define STM32_IRQ_TIM7 55 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ /* if MISC_REMAP bits are set */ -#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ -#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ -#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ -#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ -#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ -#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ -#define STM32_IRQ_LPUART 70 /* STM32L4 only */ -#define STM32_IRQ_USART9 70 /* STM32L4 only */ -#define STM32_IRQ_USART6 71 /* STM32F446 only */ -#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ -#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ -#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ -#define STM32_IRQ_TIM19 78 /* STM32F373 only */ -#define STM32_IRQ_AES 79 /* STM32L4 only */ -#define STM32_IRQ_RNG 80 /* STM32L4 only */ -#define STM32_IRQ_FPU 81 /* STM32F373 only */ - +#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ +#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ +#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ +#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ +#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ +#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ +#define STM32_IRQ_LPUART 70 /* STM32L4 only */ +#define STM32_IRQ_USART9 70 /* STM32L4 only */ +#define STM32_IRQ_USART6 71 /* STM32F446 only */ +#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ +#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ +#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ +#define STM32_IRQ_TIM19 78 /* STM32F373 only */ +#define STM32_IRQ_AES 79 /* STM32L4 only */ +#define STM32_IRQ_RNG 80 /* STM32L4 only */ +#define STM32_IRQ_FPU 81 /* STM32F373 only */ /* To simplify code generation, define DMA channel 9..10 */ -#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 -#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 -#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 -#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 +#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 +#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 +#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 +#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 /* aliases for easier code sharing */ #define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV @@ -123,464 +122,462 @@ * STM32F4 introduces a concept of DMA stream to allow * fine allocation of a stream to a channel. */ -#define STM32_IRQ_DMA1_STREAM0 11 -#define STM32_IRQ_DMA1_STREAM1 12 -#define STM32_IRQ_DMA1_STREAM2 13 -#define STM32_IRQ_DMA1_STREAM3 14 -#define STM32_IRQ_DMA1_STREAM4 15 -#define STM32_IRQ_DMA1_STREAM5 16 -#define STM32_IRQ_DMA1_STREAM6 17 -#define STM32_IRQ_DMA1_STREAM7 47 -#define STM32_IRQ_DMA2_STREAM0 56 -#define STM32_IRQ_DMA2_STREAM1 57 -#define STM32_IRQ_DMA2_STREAM2 58 -#define STM32_IRQ_DMA2_STREAM3 59 -#define STM32_IRQ_DMA2_STREAM4 60 -#define STM32_IRQ_DMA2_STREAM5 68 -#define STM32_IRQ_DMA2_STREAM6 69 -#define STM32_IRQ_DMA2_STREAM7 70 - -#define STM32_IRQ_OTG_HS_WKUP 76 -#define STM32_IRQ_OTG_HS_EP1_IN 75 -#define STM32_IRQ_OTG_HS_EP1_OUT 74 -#define STM32_IRQ_OTG_HS 77 -#define STM32_IRQ_OTG_FS 67 -#define STM32_IRQ_OTG_FS_WKUP 42 +#define STM32_IRQ_DMA1_STREAM0 11 +#define STM32_IRQ_DMA1_STREAM1 12 +#define STM32_IRQ_DMA1_STREAM2 13 +#define STM32_IRQ_DMA1_STREAM3 14 +#define STM32_IRQ_DMA1_STREAM4 15 +#define STM32_IRQ_DMA1_STREAM5 16 +#define STM32_IRQ_DMA1_STREAM6 17 +#define STM32_IRQ_DMA1_STREAM7 47 +#define STM32_IRQ_DMA2_STREAM0 56 +#define STM32_IRQ_DMA2_STREAM1 57 +#define STM32_IRQ_DMA2_STREAM2 58 +#define STM32_IRQ_DMA2_STREAM3 59 +#define STM32_IRQ_DMA2_STREAM4 60 +#define STM32_IRQ_DMA2_STREAM5 68 +#define STM32_IRQ_DMA2_STREAM6 69 +#define STM32_IRQ_DMA2_STREAM7 70 + +#define STM32_IRQ_OTG_HS_WKUP 76 +#define STM32_IRQ_OTG_HS_EP1_IN 75 +#define STM32_IRQ_OTG_HS_EP1_OUT 74 +#define STM32_IRQ_OTG_HS 77 +#define STM32_IRQ_OTG_FS 67 +#define STM32_IRQ_OTG_FS_WKUP 42 /* Peripheral base addresses */ -#define STM32_ADC1_BASE 0x40012000 -#define STM32_ADC_BASE 0x40012300 - -#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ -#define STM32_CRC_BASE 0x40023000 -#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ -#define STM32_DAC_BASE 0x40007400 - - -#define STM32_DBGMCU_BASE 0xE0042000 - -#define STM32_DMA1_BASE 0x40026000 -#define STM32_DMA2_BASE 0x40026400 - -#define STM32_EXTI_BASE 0x40013C00 - -#define STM32_FLASH_REGS_BASE 0x40023c00 - -#define STM32_GPIOA_BASE 0x40020000 -#define STM32_GPIOB_BASE 0x40020400 -#define STM32_GPIOC_BASE 0x40020800 -#define STM32_GPIOD_BASE 0x40020C00 -#define STM32_GPIOE_BASE 0x40021000 -#define STM32_GPIOF_BASE 0x40021400 /* see RM0402/0390 table 1 */ -#define STM32_GPIOG_BASE 0x40021800 -#define STM32_GPIOH_BASE 0x40021C00 - -#define STM32_I2C1_BASE 0x40005400 -#define STM32_I2C2_BASE 0x40005800 -#define STM32_I2C3_BASE 0x40005C00 -#define STM32_I2C4_BASE 0x40006000 - -#define STM32_IWDG_BASE 0x40003000 -#define STM32_LCD_BASE 0x40002400 - -#define STM32_OPTB_BASE 0x1FFFC000 -#define STM32_OTP_BASE 0x1FFF7800 - -#define STM32_PMSE_BASE 0x40013400 -#define STM32_PWR_BASE 0x40007000 - -#define STM32_RCC_BASE 0x40023800 - -#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ -#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ -#define STM32_RTC_BASE 0x40002800 - -#define STM32_SPI1_BASE 0x40013000 -#define STM32_SPI2_BASE 0x40003800 -#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ - -#define STM32_SYSCFG_BASE 0x40013800 - -#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ -#define STM32_TIM2_BASE 0x40000000 -#define STM32_TIM3_BASE 0x40000400 -#define STM32_TIM4_BASE 0x40000800 -#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ -#define STM32_TIM6_BASE 0x40001000 -#define STM32_TIM7_BASE 0x40001400 -#define STM32_TIM9_BASE 0x40014000 /* STM32F41x only */ -#define STM32_TIM10_BASE 0x40014400 /* STM32F41x only */ -#define STM32_TIM11_BASE 0x40014800 /* STM32F41x only */ -#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ -#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ -#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ -#define STM32_TIM15_BASE 0x40014000 -#define STM32_TIM16_BASE 0x40014400 -#define STM32_TIM17_BASE 0x40014800 -#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ -#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ - -#define STM32_UNIQUE_ID_BASE 0x1fff7a10 - -#define STM32_USART1_BASE 0x40011000 -#define STM32_USART2_BASE 0x40004400 -#define STM32_USART3_BASE 0x40004800 -#define STM32_USART4_BASE 0x40004c00 -#define STM32_USART5_BASE 0x40005000 -#define STM32_USART6_BASE 0x40011400 - -#define STM32_USB_CAN_SRAM_BASE 0x40006000 -#define STM32_USB_FS_BASE 0x40005C00 - -#define STM32_WWDG_BASE 0x40002C00 - +#define STM32_ADC1_BASE 0x40012000 +#define STM32_ADC_BASE 0x40012300 + +#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ +#define STM32_CRC_BASE 0x40023000 +#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ +#define STM32_DAC_BASE 0x40007400 + +#define STM32_DBGMCU_BASE 0xE0042000 + +#define STM32_DMA1_BASE 0x40026000 +#define STM32_DMA2_BASE 0x40026400 + +#define STM32_EXTI_BASE 0x40013C00 + +#define STM32_FLASH_REGS_BASE 0x40023c00 + +#define STM32_GPIOA_BASE 0x40020000 +#define STM32_GPIOB_BASE 0x40020400 +#define STM32_GPIOC_BASE 0x40020800 +#define STM32_GPIOD_BASE 0x40020C00 +#define STM32_GPIOE_BASE 0x40021000 +#define STM32_GPIOF_BASE 0x40021400 /* see RM0402/0390 table 1 */ +#define STM32_GPIOG_BASE 0x40021800 +#define STM32_GPIOH_BASE 0x40021C00 + +#define STM32_I2C1_BASE 0x40005400 +#define STM32_I2C2_BASE 0x40005800 +#define STM32_I2C3_BASE 0x40005C00 +#define STM32_I2C4_BASE 0x40006000 + +#define STM32_IWDG_BASE 0x40003000 +#define STM32_LCD_BASE 0x40002400 + +#define STM32_OPTB_BASE 0x1FFFC000 +#define STM32_OTP_BASE 0x1FFF7800 + +#define STM32_PMSE_BASE 0x40013400 +#define STM32_PWR_BASE 0x40007000 + +#define STM32_RCC_BASE 0x40023800 + +#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ +#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ +#define STM32_RTC_BASE 0x40002800 + +#define STM32_SPI1_BASE 0x40013000 +#define STM32_SPI2_BASE 0x40003800 +#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ + +#define STM32_SYSCFG_BASE 0x40013800 + +#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ +#define STM32_TIM2_BASE 0x40000000 +#define STM32_TIM3_BASE 0x40000400 +#define STM32_TIM4_BASE 0x40000800 +#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ +#define STM32_TIM6_BASE 0x40001000 +#define STM32_TIM7_BASE 0x40001400 +#define STM32_TIM9_BASE 0x40014000 /* STM32F41x only */ +#define STM32_TIM10_BASE 0x40014400 /* STM32F41x only */ +#define STM32_TIM11_BASE 0x40014800 /* STM32F41x only */ +#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ +#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ +#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ +#define STM32_TIM15_BASE 0x40014000 +#define STM32_TIM16_BASE 0x40014400 +#define STM32_TIM17_BASE 0x40014800 +#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ +#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ + +#define STM32_UNIQUE_ID_BASE 0x1fff7a10 + +#define STM32_USART1_BASE 0x40011000 +#define STM32_USART2_BASE 0x40004400 +#define STM32_USART3_BASE 0x40004800 +#define STM32_USART4_BASE 0x40004c00 +#define STM32_USART5_BASE 0x40005000 +#define STM32_USART6_BASE 0x40011400 + +#define STM32_USB_CAN_SRAM_BASE 0x40006000 +#define STM32_USB_FS_BASE 0x40005C00 + +#define STM32_WWDG_BASE 0x40002C00 #ifndef __ASSEMBLER__ /* Register definitions */ /* --- USART --- */ -#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) -#define STM32_USART_CR1_UE BIT(0) -#define STM32_USART_CR1_UESM BIT(1) -#define STM32_USART_CR1_RE BIT(2) -#define STM32_USART_CR1_TE BIT(3) -#define STM32_USART_CR1_RXNEIE BIT(5) -#define STM32_USART_CR1_TCIE BIT(6) -#define STM32_USART_CR1_TXEIE BIT(7) -#define STM32_USART_CR1_PS BIT(9) -#define STM32_USART_CR1_PCE BIT(10) -#define STM32_USART_CR1_M BIT(12) -#define STM32_USART_CR1_OVER8 BIT(15) -#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) -#define STM32_USART_CR2_SWAP BIT(15) -#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) -#define STM32_USART_CR3_EIE BIT(0) -#define STM32_USART_CR3_DMAR BIT(6) -#define STM32_USART_CR3_DMAT BIT(7) -#define STM32_USART_CR3_ONEBIT BIT(11) -#define STM32_USART_CR3_OVRDIS BIT(12) -#define STM32_USART_CR3_WUS_START_BIT (2 << 20) -#define STM32_USART_CR3_WUFIE BIT(22) -#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) -#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) -#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) -#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) -#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) -#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) -#define STM32_USART_ICR_ORECF BIT(3) -#define STM32_USART_ICR_TCCF BIT(6) -#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) -#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) -#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) +#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) +#define STM32_USART_CR1_UE BIT(0) +#define STM32_USART_CR1_UESM BIT(1) +#define STM32_USART_CR1_RE BIT(2) +#define STM32_USART_CR1_TE BIT(3) +#define STM32_USART_CR1_RXNEIE BIT(5) +#define STM32_USART_CR1_TCIE BIT(6) +#define STM32_USART_CR1_TXEIE BIT(7) +#define STM32_USART_CR1_PS BIT(9) +#define STM32_USART_CR1_PCE BIT(10) +#define STM32_USART_CR1_M BIT(12) +#define STM32_USART_CR1_OVER8 BIT(15) +#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) +#define STM32_USART_CR2_SWAP BIT(15) +#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) +#define STM32_USART_CR3_EIE BIT(0) +#define STM32_USART_CR3_DMAR BIT(6) +#define STM32_USART_CR3_DMAT BIT(7) +#define STM32_USART_CR3_ONEBIT BIT(11) +#define STM32_USART_CR3_OVRDIS BIT(12) +#define STM32_USART_CR3_WUS_START_BIT (2 << 20) +#define STM32_USART_CR3_WUFIE BIT(22) +#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) +#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) +#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) +#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) +#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) +#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) +#define STM32_USART_ICR_ORECF BIT(3) +#define STM32_USART_ICR_TCCF BIT(6) +#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) +#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) +#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) /* register alias */ -#define STM32_USART_SR(base) STM32_USART_ISR(base) -#define STM32_USART_SR_ORE BIT(3) -#define STM32_USART_SR_RXNE BIT(5) -#define STM32_USART_SR_TC BIT(6) -#define STM32_USART_SR_TXE BIT(7) +#define STM32_USART_SR(base) STM32_USART_ISR(base) +#define STM32_USART_SR_ORE BIT(3) +#define STM32_USART_SR_RXNE BIT(5) +#define STM32_USART_SR_TC BIT(6) +#define STM32_USART_SR_TXE BIT(7) /* --- GPIO --- */ -#define STM32_GPIO_MODER(b) REG32((b) + 0x00) -#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) -#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) -#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) -#define STM32_GPIO_IDR(b) REG16((b) + 0x10) -#define STM32_GPIO_ODR(b) REG16((b) + 0x14) -#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) -#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) -#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) -#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) - -#define GPIO_ALT_SYS 0x0 -#define GPIO_ALT_TIM2 0x1 -#define GPIO_ALT_TIM3_4 0x2 -#define GPIO_ALT_TIM9_11 0x3 -#define GPIO_ALT_I2C 0x4 -#define GPIO_ALT_SPI 0x5 -#define GPIO_ALT_SPI3 0x6 -#define GPIO_ALT_USART 0x7 -#define GPIO_ALT_I2C_23 0x9 -#define GPIO_ALT_USB 0xA -#define GPIO_ALT_LCD 0xB -#define GPIO_ALT_RI 0xE -#define GPIO_ALT_EVENTOUT 0xF +#define STM32_GPIO_MODER(b) REG32((b) + 0x00) +#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) +#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) +#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) +#define STM32_GPIO_IDR(b) REG16((b) + 0x10) +#define STM32_GPIO_ODR(b) REG16((b) + 0x14) +#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) +#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) +#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) +#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) + +#define GPIO_ALT_SYS 0x0 +#define GPIO_ALT_TIM2 0x1 +#define GPIO_ALT_TIM3_4 0x2 +#define GPIO_ALT_TIM9_11 0x3 +#define GPIO_ALT_I2C 0x4 +#define GPIO_ALT_SPI 0x5 +#define GPIO_ALT_SPI3 0x6 +#define GPIO_ALT_USART 0x7 +#define GPIO_ALT_I2C_23 0x9 +#define GPIO_ALT_USB 0xA +#define GPIO_ALT_LCD 0xB +#define GPIO_ALT_RI 0xE +#define GPIO_ALT_EVENTOUT 0xF /* --- I2C --- */ -#define STM32_I2C_CR1(n) REG16(stm32_i2c_reg(n, 0x00)) -#define STM32_I2C_CR1_PE BIT(0) -#define STM32_I2C_CR1_START BIT(8) -#define STM32_I2C_CR1_STOP BIT(9) -#define STM32_I2C_CR1_ACK BIT(10) -#define STM32_I2C_CR1_POS BIT(11) -#define STM32_I2C_CR1_SWRST BIT(15) -#define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04)) -#define STM32_I2C_CR2_ITERREN BIT(8) -#define STM32_I2C_CR2_ITEVTEN BIT(9) -#define STM32_I2C_CR2_ITBUFEN BIT(10) -#define STM32_I2C_CR2_DMAEN BIT(11) -#define STM32_I2C_CR2_LAST BIT(12) -#define STM32_I2C_OAR1(n) REG16(stm32_i2c_reg(n, 0x08)) -#define STM32_I2C_OAR1_B14 BIT(14) -#define STM32_I2C_OAR2(n) REG16(stm32_i2c_reg(n, 0x0C)) -#define STM32_I2C_OAR2_ENDUAL BIT(0) -#define STM32_I2C_DR(n) REG16(stm32_i2c_reg(n, 0x10)) -#define STM32_I2C_SR1(n) REG16(stm32_i2c_reg(n, 0x14)) -#define STM32_I2C_SR1_SB BIT(0) -#define STM32_I2C_SR1_ADDR BIT(1) -#define STM32_I2C_SR1_BTF BIT(2) -#define STM32_I2C_SR1_STOPF BIT(4) -#define STM32_I2C_SR1_RXNE BIT(6) -#define STM32_I2C_SR1_TXE BIT(7) -#define STM32_I2C_SR1_BERR BIT(8) -#define STM32_I2C_SR1_ARLO BIT(9) -#define STM32_I2C_SR1_AF BIT(10) - -#define STM32_I2C_SR2(n) REG16(stm32_i2c_reg(n, 0x18)) -#define STM32_I2C_SR2_BUSY BIT(1) -#define STM32_I2C_SR2_TRA BIT(2) -#define STM32_I2C_SR2_DUALF BIT(7) - -#define STM32_I2C_CCR(n) REG16(stm32_i2c_reg(n, 0x1C)) -#define STM32_I2C_CCR_DUTY BIT(14) -#define STM32_I2C_CCR_FM BIT(15) -#define STM32_I2C_TRISE(n) REG16(stm32_i2c_reg(n, 0x20)) - -#define STM32_FMPI2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) -#define FMPI2C_CR1_PE BIT(0) -#define FMPI2C_CR1_TXDMAEN BIT(14) -#define FMPI2C_CR1_RXDMAEN BIT(15) -#define STM32_FMPI2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) -#define FMPI2C_CR2_RD_WRN BIT(10) -#define FMPI2C_READ 1 -#define FMPI2C_WRITE 0 -#define FMPI2C_CR2_START BIT(13) -#define FMPI2C_CR2_STOP BIT(14) -#define FMPI2C_CR2_NACK BIT(15) -#define FMPI2C_CR2_RELOAD BIT(24) -#define FMPI2C_CR2_AUTOEND BIT(25) -#define FMPI2C_CR2_SADD(addr) ((addr) & 0x3ff) -#define FMPI2C_CR2_SADD_MASK FMPI2C_CR2_SADD(0x3ff) -#define FMPI2C_CR2_SIZE(size) (((size) & 0xff) << 16) -#define FMPI2C_CR2_SIZE_MASK FMPI2C_CR2_SIZE(0xf) -#define STM32_FMPI2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) -#define STM32_FMPI2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) -#define STM32_FMPI2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) -#define TIMINGR_THE_RIGHT_VALUE 0xC0000E12 -#define FMPI2C_TIMINGR_PRESC(val) (((val) & 0xf) << 28) -#define FMPI2C_TIMINGR_SCLDEL(val) (((val) & 0xf) << 20) -#define FMPI2C_TIMINGR_SDADEL(val) (((val) & 0xf) << 16) -#define FMPI2C_TIMINGR_SCLH(val) (((val) & 0xff) << 8) -#define FMPI2C_TIMINGR_SCLL(val) (((val) & 0xff) << 0) -#define STM32_FMPI2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) - -#define STM32_FMPI2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) -#define FMPI2C_ISR_TXE BIT(0) -#define FMPI2C_ISR_TXIS BIT(1) -#define FMPI2C_ISR_RXNE BIT(2) -#define FMPI2C_ISR_ADDR BIT(3) -#define FMPI2C_ISR_NACKF BIT(4) -#define FMPI2C_ISR_STOPF BIT(5) -#define FMPI2C_ISR_BERR BIT(8) -#define FMPI2C_ISR_ARLO BIT(9) -#define FMPI2C_ISR_BUSY BIT(15) -#define STM32_FMPI2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) - -#define STM32_FMPI2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) -#define STM32_FMPI2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) -#define STM32_FMPI2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) +#define STM32_I2C_CR1(n) REG16(stm32_i2c_reg(n, 0x00)) +#define STM32_I2C_CR1_PE BIT(0) +#define STM32_I2C_CR1_START BIT(8) +#define STM32_I2C_CR1_STOP BIT(9) +#define STM32_I2C_CR1_ACK BIT(10) +#define STM32_I2C_CR1_POS BIT(11) +#define STM32_I2C_CR1_SWRST BIT(15) +#define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04)) +#define STM32_I2C_CR2_ITERREN BIT(8) +#define STM32_I2C_CR2_ITEVTEN BIT(9) +#define STM32_I2C_CR2_ITBUFEN BIT(10) +#define STM32_I2C_CR2_DMAEN BIT(11) +#define STM32_I2C_CR2_LAST BIT(12) +#define STM32_I2C_OAR1(n) REG16(stm32_i2c_reg(n, 0x08)) +#define STM32_I2C_OAR1_B14 BIT(14) +#define STM32_I2C_OAR2(n) REG16(stm32_i2c_reg(n, 0x0C)) +#define STM32_I2C_OAR2_ENDUAL BIT(0) +#define STM32_I2C_DR(n) REG16(stm32_i2c_reg(n, 0x10)) +#define STM32_I2C_SR1(n) REG16(stm32_i2c_reg(n, 0x14)) +#define STM32_I2C_SR1_SB BIT(0) +#define STM32_I2C_SR1_ADDR BIT(1) +#define STM32_I2C_SR1_BTF BIT(2) +#define STM32_I2C_SR1_STOPF BIT(4) +#define STM32_I2C_SR1_RXNE BIT(6) +#define STM32_I2C_SR1_TXE BIT(7) +#define STM32_I2C_SR1_BERR BIT(8) +#define STM32_I2C_SR1_ARLO BIT(9) +#define STM32_I2C_SR1_AF BIT(10) + +#define STM32_I2C_SR2(n) REG16(stm32_i2c_reg(n, 0x18)) +#define STM32_I2C_SR2_BUSY BIT(1) +#define STM32_I2C_SR2_TRA BIT(2) +#define STM32_I2C_SR2_DUALF BIT(7) + +#define STM32_I2C_CCR(n) REG16(stm32_i2c_reg(n, 0x1C)) +#define STM32_I2C_CCR_DUTY BIT(14) +#define STM32_I2C_CCR_FM BIT(15) +#define STM32_I2C_TRISE(n) REG16(stm32_i2c_reg(n, 0x20)) + +#define STM32_FMPI2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) +#define FMPI2C_CR1_PE BIT(0) +#define FMPI2C_CR1_TXDMAEN BIT(14) +#define FMPI2C_CR1_RXDMAEN BIT(15) +#define STM32_FMPI2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) +#define FMPI2C_CR2_RD_WRN BIT(10) +#define FMPI2C_READ 1 +#define FMPI2C_WRITE 0 +#define FMPI2C_CR2_START BIT(13) +#define FMPI2C_CR2_STOP BIT(14) +#define FMPI2C_CR2_NACK BIT(15) +#define FMPI2C_CR2_RELOAD BIT(24) +#define FMPI2C_CR2_AUTOEND BIT(25) +#define FMPI2C_CR2_SADD(addr) ((addr)&0x3ff) +#define FMPI2C_CR2_SADD_MASK FMPI2C_CR2_SADD(0x3ff) +#define FMPI2C_CR2_SIZE(size) (((size)&0xff) << 16) +#define FMPI2C_CR2_SIZE_MASK FMPI2C_CR2_SIZE(0xf) +#define STM32_FMPI2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) +#define STM32_FMPI2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) +#define STM32_FMPI2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) +#define TIMINGR_THE_RIGHT_VALUE 0xC0000E12 +#define FMPI2C_TIMINGR_PRESC(val) (((val)&0xf) << 28) +#define FMPI2C_TIMINGR_SCLDEL(val) (((val)&0xf) << 20) +#define FMPI2C_TIMINGR_SDADEL(val) (((val)&0xf) << 16) +#define FMPI2C_TIMINGR_SCLH(val) (((val)&0xff) << 8) +#define FMPI2C_TIMINGR_SCLL(val) (((val)&0xff) << 0) +#define STM32_FMPI2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) + +#define STM32_FMPI2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) +#define FMPI2C_ISR_TXE BIT(0) +#define FMPI2C_ISR_TXIS BIT(1) +#define FMPI2C_ISR_RXNE BIT(2) +#define FMPI2C_ISR_ADDR BIT(3) +#define FMPI2C_ISR_NACKF BIT(4) +#define FMPI2C_ISR_STOPF BIT(5) +#define FMPI2C_ISR_BERR BIT(8) +#define FMPI2C_ISR_ARLO BIT(9) +#define FMPI2C_ISR_BUSY BIT(15) +#define STM32_FMPI2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) + +#define STM32_FMPI2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) +#define STM32_FMPI2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) +#define STM32_FMPI2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) /* --- Power / Reset / Clocks --- */ -#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) - +#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) -#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) -#define STM32_RCC_CR_HSION BIT(0) -#define STM32_RCC_CR_HSIRDY BIT(1) -#define STM32_RCC_CR_HSEON BIT(16) -#define STM32_RCC_CR_HSERDY BIT(17) -#define STM32_RCC_CR_PLLON BIT(24) -#define STM32_RCC_CR_PLLRDY BIT(25) +#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) +#define STM32_RCC_CR_HSION BIT(0) +#define STM32_RCC_CR_HSIRDY BIT(1) +#define STM32_RCC_CR_HSEON BIT(16) +#define STM32_RCC_CR_HSERDY BIT(17) +#define STM32_RCC_CR_PLLON BIT(24) +#define STM32_RCC_CR_PLLRDY BIT(25) #ifdef CHIP_VARIANT_STM32F76X /* Required or recommended clocks for stm32f767/769 */ #define STM32F4_PLL_REQ 2000000 #define STM32F4_RTC_REQ 1000000 #define STM32F4_IO_CLOCK 45000000 -#define STM32F4_USB_REQ 45000000 /* not compatible with USB, will use PLLSAI */ +#define STM32F4_USB_REQ \ + 45000000 /* not compatible with USB, will use PLLSAI \ + */ #define STM32F4_VCO_CLOCK 360000000 #define STM32F4_HSI_CLOCK 16000000 #define STM32F4_LSI_CLOCK 32000 #define STM32F4_TIMER_CLOCK (STM32F4_IO_CLOCK * 2) -#define STM32F4_PLLP_DIV 2 /* sys = VCO/2 = 180 Mhz */ -#define STM32F4_AHB_PRE 0x0 /* AHB = sysclk = 180 Mhz */ +#define STM32F4_PLLP_DIV 2 /* sys = VCO/2 = 180 Mhz */ +#define STM32F4_AHB_PRE 0x0 /* AHB = sysclk = 180 Mhz */ #define STM32F4_APB1_PRE 0x5 /* APB1 = AHB /4 = 45 Mhz */ #define STM32F4_APB2_PRE 0x5 /* APB2 = AHB /4 = 45 Mhz */ -#define STM32_FLASH_ACR_LATENCY (5 << 0) +#define STM32_FLASH_ACR_LATENCY (5 << 0) #else #error "No valid clocks defined" #endif -#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x04) +#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x04) /* PLL Division factor */ -#define PLLCFGR_PLLM_OFF 0 -#define PLLCFGR_PLLM(val) (((val) & 0x1f) << PLLCFGR_PLLM_OFF) +#define PLLCFGR_PLLM_OFF 0 +#define PLLCFGR_PLLM(val) (((val)&0x1f) << PLLCFGR_PLLM_OFF) /* PLL Multiplication factor */ -#define PLLCFGR_PLLN_OFF 6 -#define PLLCFGR_PLLN(val) (((val) & 0x1ff) << PLLCFGR_PLLN_OFF) +#define PLLCFGR_PLLN_OFF 6 +#define PLLCFGR_PLLN(val) (((val)&0x1ff) << PLLCFGR_PLLN_OFF) /* Main CPU Clock */ -#define PLLCFGR_PLLP_OFF 16 -#define PLLCFGR_PLLP(val) (((val) & 0x3) << PLLCFGR_PLLP_OFF) +#define PLLCFGR_PLLP_OFF 16 +#define PLLCFGR_PLLP(val) (((val)&0x3) << PLLCFGR_PLLP_OFF) -#define PLLCFGR_PLLSRC_HSI (0 << 22) -#define PLLCFGR_PLLSRC_HSE BIT(22) +#define PLLCFGR_PLLSRC_HSI (0 << 22) +#define PLLCFGR_PLLSRC_HSE BIT(22) /* USB OTG FS: Must equal 48MHz */ -#define PLLCFGR_PLLQ_OFF 24 -#define PLLCFGR_PLLQ(val) (((val) & 0xf) << PLLCFGR_PLLQ_OFF) +#define PLLCFGR_PLLQ_OFF 24 +#define PLLCFGR_PLLQ(val) (((val)&0xf) << PLLCFGR_PLLQ_OFF) /* SYSTEM */ -#define PLLCFGR_PLLR_OFF 28 -#define PLLCFGR_PLLR(val) (((val) & 0x7) << PLLCFGR_PLLR_OFF) - -#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) -#define STM32_RCC_CFGR_SW_HSI (0 << 0) -#define STM32_RCC_CFGR_SW_HSE (1 << 0) -#define STM32_RCC_CFGR_SW_PLL (2 << 0) -#define STM32_RCC_CFGR_SW_PLL_R (3 << 0) -#define STM32_RCC_CFGR_SW_MASK (3 << 0) -#define STM32_RCC_CFGR_SWS_HSI (0 << 2) -#define STM32_RCC_CFGR_SWS_HSE (1 << 2) -#define STM32_RCC_CFGR_SWS_PLL (2 << 2) -#define STM32_RCC_CFGR_SWS_PLL_R (3 << 2) -#define STM32_RCC_CFGR_SWS_MASK (3 << 2) +#define PLLCFGR_PLLR_OFF 28 +#define PLLCFGR_PLLR(val) (((val)&0x7) << PLLCFGR_PLLR_OFF) + +#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) +#define STM32_RCC_CFGR_SW_HSI (0 << 0) +#define STM32_RCC_CFGR_SW_HSE (1 << 0) +#define STM32_RCC_CFGR_SW_PLL (2 << 0) +#define STM32_RCC_CFGR_SW_PLL_R (3 << 0) +#define STM32_RCC_CFGR_SW_MASK (3 << 0) +#define STM32_RCC_CFGR_SWS_HSI (0 << 2) +#define STM32_RCC_CFGR_SWS_HSE (1 << 2) +#define STM32_RCC_CFGR_SWS_PLL (2 << 2) +#define STM32_RCC_CFGR_SWS_PLL_R (3 << 2) +#define STM32_RCC_CFGR_SWS_MASK (3 << 2) /* AHB Prescalar: nonlinear values, look up in RM0390 */ -#define CFGR_HPRE_OFF 4 -#define CFGR_HPRE(val) (((val) & 0xf) << CFGR_HPRE_OFF) +#define CFGR_HPRE_OFF 4 +#define CFGR_HPRE(val) (((val)&0xf) << CFGR_HPRE_OFF) /* APB1 Low Speed Prescalar < 45MHz */ -#define CFGR_PPRE1_OFF 10 -#define CFGR_PPRE1(val) (((val) & 0x7) << CFGR_PPRE1_OFF) +#define CFGR_PPRE1_OFF 10 +#define CFGR_PPRE1(val) (((val)&0x7) << CFGR_PPRE1_OFF) /* APB2 High Speed Prescalar < 90MHz */ -#define CFGR_PPRE2_OFF 13 -#define CFGR_PPRE2(val) (((val) & 0x7) << CFGR_PPRE2_OFF) +#define CFGR_PPRE2_OFF 13 +#define CFGR_PPRE2(val) (((val)&0x7) << CFGR_PPRE2_OFF) /* RTC CLock: Must equal 1MHz */ -#define CFGR_RTCPRE_OFF 16 -#define CFGR_RTCPRE(val) (((val) & 0x1f) << CFGR_RTCPRE_OFF) +#define CFGR_RTCPRE_OFF 16 +#define CFGR_RTCPRE(val) (((val)&0x1f) << CFGR_RTCPRE_OFF) -#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x0C) -#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x10) -#define RCC_AHB1RSTR_OTGHSRST BIT(29) +#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x0C) +#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x10) +#define RCC_AHB1RSTR_OTGHSRST BIT(29) -#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x14) -#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x18) +#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x14) +#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x18) -#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x20) -#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x24) +#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x20) +#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x24) -#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x30) -#define STM32_RCC_AHB1ENR_GPIOMASK (0xff << 0) -#define STM32_RCC_AHB1ENR_BKPSRAMEN BIT(18) -#define STM32_RCC_AHB1ENR_DMA1EN BIT(21) -#define STM32_RCC_AHB1ENR_DMA2EN BIT(22) +#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x30) +#define STM32_RCC_AHB1ENR_GPIOMASK (0xff << 0) +#define STM32_RCC_AHB1ENR_BKPSRAMEN BIT(18) +#define STM32_RCC_AHB1ENR_DMA1EN BIT(21) +#define STM32_RCC_AHB1ENR_DMA2EN BIT(22) /* TODO(nsanders): normalize naming.*/ -#define STM32_RCC_HB1_DMA1 BIT(21) -#define STM32_RCC_HB1_DMA2 BIT(22) -#define STM32_RCC_AHB1ENR_OTGHSEN BIT(29) -#define STM32_RCC_AHB1ENR_OTGHSULPIEN BIT(30) - -#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x34) -#define STM32_RCC_AHB2ENR_RNGEN BIT(6) -#define STM32_RCC_AHB2ENR_OTGFSEN BIT(7) -#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x38) - -#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x40) -#define STM32_RCC_PWREN BIT(28) -#define STM32_RCC_I2C1EN BIT(21) -#define STM32_RCC_I2C2EN BIT(22) -#define STM32_RCC_I2C3EN BIT(23) -#define STM32_RCC_FMPI2C4EN BIT(24) - -#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x44) -#define STM32_RCC_APB2ENR_ADC1EN BIT(8) /* STM32F4 */ - -#define STM32_RCC_PB2_USART6 BIT(5) -#define STM32_RCC_SYSCFGEN BIT(14) - -#define STM32_RCC_AHB1LPENR REG32(STM32_RCC_BASE + 0x50) -#define STM32_RCC_AHB2LPENR REG32(STM32_RCC_BASE + 0x54) -#define STM32_RCC_AHB3LPENR REG32(STM32_RCC_BASE + 0x58) -#define STM32_RCC_APB1LPENR REG32(STM32_RCC_BASE + 0x60) -#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x64) - -#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x70) -#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x74) -#define STM32_RCC_CSR_LSION BIT(0) -#define STM32_RCC_CSR_LSIRDY BIT(1) - -#define STM32_RCC_PB2_TIM9 BIT(16) -#define STM32_RCC_PB2_TIM10 BIT(17) -#define STM32_RCC_PB2_TIM11 BIT(18) - -#define STM32_RCC_DCKCFGR2 REG32(STM32_RCC_BASE + 0x94) -#define DCKCFGR2_FMPI2C1SEL(val) (((val) & 0x3) << 22) -#define DCKCFGR2_FMPI2C1SEL_MASK (0x3 << 22) -#define FMPI2C1SEL_APB 0x0 - -#define STM32_SYSCFG_MEMRMP REG32(STM32_SYSCFG_BASE + 0x00) -#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04) -#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) -#define STM32_SYSCFG_CMPCR REG32(STM32_SYSCFG_BASE + 0x20) -#define STM32_SYSCFG_CFGR REG32(STM32_SYSCFG_BASE + 0x2C) - +#define STM32_RCC_HB1_DMA1 BIT(21) +#define STM32_RCC_HB1_DMA2 BIT(22) +#define STM32_RCC_AHB1ENR_OTGHSEN BIT(29) +#define STM32_RCC_AHB1ENR_OTGHSULPIEN BIT(30) + +#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x34) +#define STM32_RCC_AHB2ENR_RNGEN BIT(6) +#define STM32_RCC_AHB2ENR_OTGFSEN BIT(7) +#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x38) + +#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x40) +#define STM32_RCC_PWREN BIT(28) +#define STM32_RCC_I2C1EN BIT(21) +#define STM32_RCC_I2C2EN BIT(22) +#define STM32_RCC_I2C3EN BIT(23) +#define STM32_RCC_FMPI2C4EN BIT(24) + +#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x44) +#define STM32_RCC_APB2ENR_ADC1EN BIT(8) /* STM32F4 */ + +#define STM32_RCC_PB2_USART6 BIT(5) +#define STM32_RCC_SYSCFGEN BIT(14) + +#define STM32_RCC_AHB1LPENR REG32(STM32_RCC_BASE + 0x50) +#define STM32_RCC_AHB2LPENR REG32(STM32_RCC_BASE + 0x54) +#define STM32_RCC_AHB3LPENR REG32(STM32_RCC_BASE + 0x58) +#define STM32_RCC_APB1LPENR REG32(STM32_RCC_BASE + 0x60) +#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x64) + +#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x70) +#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x74) +#define STM32_RCC_CSR_LSION BIT(0) +#define STM32_RCC_CSR_LSIRDY BIT(1) + +#define STM32_RCC_PB2_TIM9 BIT(16) +#define STM32_RCC_PB2_TIM10 BIT(17) +#define STM32_RCC_PB2_TIM11 BIT(18) + +#define STM32_RCC_DCKCFGR2 REG32(STM32_RCC_BASE + 0x94) +#define DCKCFGR2_FMPI2C1SEL(val) (((val)&0x3) << 22) +#define DCKCFGR2_FMPI2C1SEL_MASK (0x3 << 22) +#define FMPI2C1SEL_APB 0x0 + +#define STM32_SYSCFG_MEMRMP REG32(STM32_SYSCFG_BASE + 0x00) +#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04) +#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) +#define STM32_SYSCFG_CMPCR REG32(STM32_SYSCFG_BASE + 0x20) +#define STM32_SYSCFG_CFGR REG32(STM32_SYSCFG_BASE + 0x2C) /* Peripheral bits for RCC_APB/AHB and DBGMCU regs */ -#define STM32_RCC_PB2_USART1 BIT(4) +#define STM32_RCC_PB2_USART1 BIT(4) /* Reset causes definitions */ /* Reset causes in RCC CSR register */ #define STM32_RCC_RESET_CAUSE STM32_RCC_CSR -#define RESET_CAUSE_WDG 0x60000000 -#define RESET_CAUSE_SFT 0x10000000 -#define RESET_CAUSE_POR 0x08000000 -#define RESET_CAUSE_PIN 0x04000000 -#define RESET_CAUSE_OTHER 0xfe000000 -#define RESET_CAUSE_RMVF 0x01000000 +#define RESET_CAUSE_WDG 0x60000000 +#define RESET_CAUSE_SFT 0x10000000 +#define RESET_CAUSE_POR 0x08000000 +#define RESET_CAUSE_PIN 0x04000000 +#define RESET_CAUSE_OTHER 0xfe000000 +#define RESET_CAUSE_RMVF 0x01000000 /* Power cause in PWR CSR register */ #define STM32_PWR_RESET_CAUSE STM32_PWR_CSR #define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CR -#define RESET_CAUSE_SBF 0x00000002 -#define RESET_CAUSE_SBF_CLR 0x00000004 +#define RESET_CAUSE_SBF 0x00000002 +#define RESET_CAUSE_SBF_CLR 0x00000004 /* --- Watchdogs --- */ /* --- Real-Time Clock --- */ -#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) -#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) -#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) -#define STM32_RTC_CR_BYPSHAD BIT(5) -#define STM32_RTC_CR_ALRAE BIT(8) -#define STM32_RTC_CR_ALRAIE BIT(12) -#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) -#define STM32_RTC_ISR_ALRAWF BIT(0) -#define STM32_RTC_ISR_RSF BIT(5) -#define STM32_RTC_ISR_INITF BIT(6) -#define STM32_RTC_ISR_INIT BIT(7) -#define STM32_RTC_ISR_ALRAF BIT(8) -#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) -#define STM32_RTC_PRER_A_MASK (0x7f << 16) -#define STM32_RTC_PRER_S_MASK (0x7fff << 0) -#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) -#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) -#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) -#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) -#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) -#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) -#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) -#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) -#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) -#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) -#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) - -#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) -#define STM32_BKP_BYTES 80 +#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) +#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) +#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) +#define STM32_RTC_CR_BYPSHAD BIT(5) +#define STM32_RTC_CR_ALRAE BIT(8) +#define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) +#define STM32_RTC_ISR_ALRAWF BIT(0) +#define STM32_RTC_ISR_RSF BIT(5) +#define STM32_RTC_ISR_INITF BIT(6) +#define STM32_RTC_ISR_INIT BIT(7) +#define STM32_RTC_ISR_ALRAF BIT(8) +#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) +#define STM32_RTC_PRER_A_MASK (0x7f << 16) +#define STM32_RTC_PRER_S_MASK (0x7fff << 0) +#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) +#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) +#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) +#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) +#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) +#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) +#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) +#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) +#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) +#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) +#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) + +#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) +#define STM32_BKP_BYTES 80 /* --- SPI --- */ @@ -590,15 +587,15 @@ struct stm32_spi_regs { uint16_t _pad0; uint16_t cr2; uint16_t _pad1; - unsigned sr; + unsigned int sr; uint8_t dr; uint8_t _pad2; uint16_t _pad3; - unsigned crcpr; - unsigned rxcrcr; - unsigned txcrcr; - unsigned i2scfgr; /* STM32L only */ - unsigned i2spr; /* STM32L only */ + unsigned int crcpr; + unsigned int rxcrcr; + unsigned int txcrcr; + unsigned int i2scfgr; /* STM32L only */ + unsigned int i2spr; /* STM32L only */ }; /* Must be volatile, or compiler optimizes out repeated accesses */ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; @@ -608,146 +605,142 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_SPI3_REGS ((stm32_spi_regs_t *)STM32_SPI3_BASE) #define STM32_SPI4_REGS ((stm32_spi_regs_t *)STM32_SPI4_BASE) -#define STM32_SPI_CR1_BIDIMODE BIT(15) -#define STM32_SPI_CR1_BIDIOE BIT(14) -#define STM32_SPI_CR1_CRCEN BIT(13) -#define STM32_SPI_CR1_SSM BIT(9) -#define STM32_SPI_CR1_SSI BIT(8) -#define STM32_SPI_CR1_LSBFIRST BIT(7) -#define STM32_SPI_CR1_SPE BIT(6) -#define STM32_SPI_CR1_BR_DIV64R (5 << 3) -#define STM32_SPI_CR1_BR_DIV4R BIT(3) -#define STM32_SPI_CR1_MSTR BIT(2) -#define STM32_SPI_CR1_CPOL BIT(1) -#define STM32_SPI_CR1_CPHA BIT(0) -#define STM32_SPI_CR2_FRXTH BIT(12) -#define STM32_SPI_CR2_DATASIZE(n) (((n) - 1) << 8) -#define STM32_SPI_CR2_TXEIE BIT(7) -#define STM32_SPI_CR2_RXNEIE BIT(6) -#define STM32_SPI_CR2_NSSP BIT(3) -#define STM32_SPI_CR2_SSOE BIT(2) -#define STM32_SPI_CR2_TXDMAEN BIT(1) -#define STM32_SPI_CR2_RXDMAEN BIT(0) - -#define STM32_SPI_SR_RXNE BIT(0) -#define STM32_SPI_SR_TXE BIT(1) -#define STM32_SPI_SR_CRCERR BIT(4) -#define STM32_SPI_SR_BSY BIT(7) -#define STM32_SPI_SR_FRLVL (3 << 9) -#define STM32_SPI_SR_FTLVL (3 << 11) +#define STM32_SPI_CR1_BIDIMODE BIT(15) +#define STM32_SPI_CR1_BIDIOE BIT(14) +#define STM32_SPI_CR1_CRCEN BIT(13) +#define STM32_SPI_CR1_SSM BIT(9) +#define STM32_SPI_CR1_SSI BIT(8) +#define STM32_SPI_CR1_LSBFIRST BIT(7) +#define STM32_SPI_CR1_SPE BIT(6) +#define STM32_SPI_CR1_BR_DIV64R (5 << 3) +#define STM32_SPI_CR1_BR_DIV4R BIT(3) +#define STM32_SPI_CR1_MSTR BIT(2) +#define STM32_SPI_CR1_CPOL BIT(1) +#define STM32_SPI_CR1_CPHA BIT(0) +#define STM32_SPI_CR2_FRXTH BIT(12) +#define STM32_SPI_CR2_DATASIZE(n) (((n)-1) << 8) +#define STM32_SPI_CR2_TXEIE BIT(7) +#define STM32_SPI_CR2_RXNEIE BIT(6) +#define STM32_SPI_CR2_NSSP BIT(3) +#define STM32_SPI_CR2_SSOE BIT(2) +#define STM32_SPI_CR2_TXDMAEN BIT(1) +#define STM32_SPI_CR2_RXDMAEN BIT(0) + +#define STM32_SPI_SR_RXNE BIT(0) +#define STM32_SPI_SR_TXE BIT(1) +#define STM32_SPI_SR_CRCERR BIT(4) +#define STM32_SPI_SR_BSY BIT(7) +#define STM32_SPI_SR_FRLVL (3 << 9) +#define STM32_SPI_SR_FTLVL (3 << 11) /* --- Debug --- */ -#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) -#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) +#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) +#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) /* --- Flash --- */ -#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) -#define STM32_FLASH_ACR_SHIFT 0 -#define STM32_FLASH_ACR_LAT_MASK 0xf -#define STM32_FLASH_ACR_PRFTEN BIT(8) -#define STM32_FLASH_ACR_ICEN BIT(9) -#define STM32_FLASH_ACR_DCEN BIT(10) -#define STM32_FLASH_ACR_ICRST BIT(11) -#define STM32_FLASH_ACR_DCRST BIT(12) -#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x04) -#define FLASH_KEYR_KEY1 0x45670123 -#define FLASH_KEYR_KEY2 0xCDEF89AB -#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) -#define FLASH_OPTKEYR_KEY1 0x08192A3B -#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F -#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x0c) -#define FLASH_SR_EOP BIT(0) -#define FLASH_SR_OPERR BIT(1) -#define FLASH_SR_WRPERR BIT(4) -#define FLASH_SR_PGAERR BIT(5) -#define FLASH_SR_PGPERR BIT(6) -#define FLASH_SR_PGSERR BIT(7) -#define FLASH_SR_RDERR BIT(8) -#define FLASH_SR_ALL_ERR \ +#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) +#define STM32_FLASH_ACR_SHIFT 0 +#define STM32_FLASH_ACR_LAT_MASK 0xf +#define STM32_FLASH_ACR_PRFTEN BIT(8) +#define STM32_FLASH_ACR_ICEN BIT(9) +#define STM32_FLASH_ACR_DCEN BIT(10) +#define STM32_FLASH_ACR_ICRST BIT(11) +#define STM32_FLASH_ACR_DCRST BIT(12) +#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x04) +#define FLASH_KEYR_KEY1 0x45670123 +#define FLASH_KEYR_KEY2 0xCDEF89AB +#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) +#define FLASH_OPTKEYR_KEY1 0x08192A3B +#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F +#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x0c) +#define FLASH_SR_EOP BIT(0) +#define FLASH_SR_OPERR BIT(1) +#define FLASH_SR_WRPERR BIT(4) +#define FLASH_SR_PGAERR BIT(5) +#define FLASH_SR_PGPERR BIT(6) +#define FLASH_SR_PGSERR BIT(7) +#define FLASH_SR_RDERR BIT(8) +#define FLASH_SR_ALL_ERR \ (FLASH_SR_OPERR | FLASH_SR_WRPERR | FLASH_SR_PGAERR | \ FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_RDERR) -#define FLASH_SR_BUSY BIT(16) -#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x10) -#define FLASH_CR_PG BIT(0) -#define FLASH_CR_PER BIT(1) -#define FLASH_CR_MER BIT(2) -#define STM32_FLASH_CR_SNB_OFFSET (3) -#define STM32_FLASH_CR_SNB(sec) \ - (((sec) & 0xf) << STM32_FLASH_CR_SNB_OFFSET) -#define STM32_FLASH_CR_SNB_MASK (STM32_FLASH_CR_SNB(0xf)) -#define STM32_FLASH_CR_PSIZE_OFFSET (8) -#define STM32_FLASH_CR_PSIZE(size) \ - (((size) & 0x3) << STM32_FLASH_CR_PSIZE_OFFSET) -#define STM32_FLASH_CR_PSIZE_MASK (STM32_FLASH_CR_PSIZE(0x3)) -#define FLASH_CR_STRT BIT(16) -#define FLASH_CR_LOCK BIT(31) -#define STM32_FLASH_OPTCR REG32(STM32_FLASH_REGS_BASE + 0x14) -#define FLASH_OPTLOCK BIT(0) -#define FLASH_OPTSTRT BIT(1) -#define STM32_FLASH_BOR_LEV_OFFSET (2) -#define STM32_FLASH_RDP_MASK (0xFF << 8) -#define STM32_FLASH_nWRP_OFFSET (16) -#define STM32_FLASH_nWRP(_bank) BIT(_bank + STM32_FLASH_nWRP_OFFSET) -#define STM32_FLASH_nWRP_ALL (0xFF << STM32_FLASH_nWRP_OFFSET) -#define STM32_FLASH_OPT_LOCKED (STM32_FLASH_OPTCR & FLASH_OPTLOCK) - -#define STM32_OPTB_RDP_USER REG32(STM32_OPTB_BASE + 0x00) -#define STM32_OPTB_RDP_OFF 0x00 -#define STM32_OPTB_USER_OFF 0x02 -#define STM32_OPTB_WRP_OFF(n) (0x08 + (n&3) * 2) -#define STM32_OPTB_WP REG32(STM32_OPTB_BASE + 0x08) -#define STM32_OPTB_nWRP(_bank) BIT(_bank) -#define STM32_OPTB_nWRP_ALL (0xFF) - -#define STM32_OPTB_COMPL_SHIFT 8 - -#define STM32_OTP_BLOCK_NB 16 -#define STM32_OTP_BLOCK_SIZE 32 +#define FLASH_SR_BUSY BIT(16) +#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x10) +#define FLASH_CR_PG BIT(0) +#define FLASH_CR_PER BIT(1) +#define FLASH_CR_MER BIT(2) +#define STM32_FLASH_CR_SNB_OFFSET (3) +#define STM32_FLASH_CR_SNB(sec) (((sec)&0xf) << STM32_FLASH_CR_SNB_OFFSET) +#define STM32_FLASH_CR_SNB_MASK (STM32_FLASH_CR_SNB(0xf)) +#define STM32_FLASH_CR_PSIZE_OFFSET (8) +#define STM32_FLASH_CR_PSIZE(size) (((size)&0x3) << STM32_FLASH_CR_PSIZE_OFFSET) +#define STM32_FLASH_CR_PSIZE_MASK (STM32_FLASH_CR_PSIZE(0x3)) +#define FLASH_CR_STRT BIT(16) +#define FLASH_CR_LOCK BIT(31) +#define STM32_FLASH_OPTCR REG32(STM32_FLASH_REGS_BASE + 0x14) +#define FLASH_OPTLOCK BIT(0) +#define FLASH_OPTSTRT BIT(1) +#define STM32_FLASH_BOR_LEV_OFFSET (2) +#define STM32_FLASH_RDP_MASK (0xFF << 8) +#define STM32_FLASH_nWRP_OFFSET (16) +#define STM32_FLASH_nWRP(_bank) BIT(_bank + STM32_FLASH_nWRP_OFFSET) +#define STM32_FLASH_nWRP_ALL (0xFF << STM32_FLASH_nWRP_OFFSET) +#define STM32_FLASH_OPT_LOCKED (STM32_FLASH_OPTCR & FLASH_OPTLOCK) + +#define STM32_OPTB_RDP_USER REG32(STM32_OPTB_BASE + 0x00) +#define STM32_OPTB_RDP_OFF 0x00 +#define STM32_OPTB_USER_OFF 0x02 +#define STM32_OPTB_WRP_OFF(n) (0x08 + (n & 3) * 2) +#define STM32_OPTB_WP REG32(STM32_OPTB_BASE + 0x08) +#define STM32_OPTB_nWRP(_bank) BIT(_bank) +#define STM32_OPTB_nWRP_ALL (0xFF) + +#define STM32_OPTB_COMPL_SHIFT 8 + +#define STM32_OTP_BLOCK_NB 16 +#define STM32_OTP_BLOCK_SIZE 32 #define STM32_OTP_BLOCK_DATA(_block, _offset) \ - (STM32_OTP_BASE + STM32_OTP_BLOCK_SIZE * (_block) + (_offset) * 4) -#define STM32_OTP_UNLOCK_BYTE 0x00 -#define STM32_OTP_LOCK_BYTE 0xFF -#define STM32_OTP_LOCK_BASE \ + (STM32_OTP_BASE + STM32_OTP_BLOCK_SIZE * (_block) + (_offset)*4) +#define STM32_OTP_UNLOCK_BYTE 0x00 +#define STM32_OTP_LOCK_BYTE 0xFF +#define STM32_OTP_LOCK_BASE \ (STM32_OTP_BASE + STM32_OTP_BLOCK_NB * STM32_OTP_BLOCK_SIZE) -#define STM32_OTP_LOCK(_block) \ - (STM32_OTP_LOCK_BASE + ((_block) / 4) * 4) -#define STM32_OPT_LOCK_MASK(_block) ((0xFF << ((_block) % 4) * 8)) +#define STM32_OTP_LOCK(_block) (STM32_OTP_LOCK_BASE + ((_block) / 4) * 4) +#define STM32_OPT_LOCK_MASK(_block) ((0xFF << ((_block) % 4) * 8)) /* --- External Interrupts --- */ -#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) -#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) -#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) -#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) -#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) -#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) +#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) +#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) +#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) +#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) +#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) +#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) #define EXTI_RTC_ALR_EVENT BIT(17) /* --- ADC --- */ -#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00) -#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04) -#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08) -#define STM32_ADC_CR2_ADON BIT(0) -#define STM32_ADC_CR2_CONT BIT(1) -#define STM32_ADC_CR2_CAL BIT(2) -#define STM32_ADC_CR2_RSTCAL BIT(3) -#define STM32_ADC_CR2_ALIGN BIT(11) -#define STM32_ADC_CR2_SWSTART BIT(30) -#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x0C) -#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x10) -#define STM32_ADC_JOFR(n) REG32(STM32_ADC1_BASE + 0x14 + ((n)&3) * 4) -#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x24) -#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x28) -#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x28 + ((n)&3) * 4) -#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x2C) -#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x30) -#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x34) -#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x38) -#define STM32_ADC_JDR(n) REG32(STM32_ADC1_BASE + 0x3C + ((n)&3) * 4) -#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x4C) +#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00) +#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04) +#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08) +#define STM32_ADC_CR2_ADON BIT(0) +#define STM32_ADC_CR2_CONT BIT(1) +#define STM32_ADC_CR2_CAL BIT(2) +#define STM32_ADC_CR2_RSTCAL BIT(3) +#define STM32_ADC_CR2_ALIGN BIT(11) +#define STM32_ADC_CR2_SWSTART BIT(30) +#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x0C) +#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x10) +#define STM32_ADC_JOFR(n) REG32(STM32_ADC1_BASE + 0x14 + ((n)&3) * 4) +#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x24) +#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x28) +#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x28 + ((n)&3) * 4) +#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x2C) +#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x30) +#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x34) +#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x38) +#define STM32_ADC_JDR(n) REG32(STM32_ADC1_BASE + 0x3C + ((n)&3) * 4) +#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x4C) /* --- Comparators --- */ - /* --- DMA --- */ /* * Available DMA streams, numbered from 0. @@ -798,7 +791,7 @@ enum dma_channel { STM32_DMAC_FMPI2C4_TX = STM32_DMA1_STREAM5, STM32_DMAC_FMPI2C4_RX = STM32_DMA1_STREAM2, - /* Legacy naming for spi_master.c */ + /* Legacy naming for spi_controller.c */ STM32_DMAC_SPI1_TX = STM32_DMA2_STREAM3, /* REQ 3 */ STM32_DMAC_SPI1_RX = STM32_DMA2_STREAM0, /* REQ 3 */ STM32_DMAC_SPI2_TX = STM32_DMA1_STREAM4, /* REQ 0 */ @@ -838,12 +831,12 @@ enum dma_channel { /* Registers for a single stream of a DMA controller */ struct stm32_dma_stream { - uint32_t scr; /* Control */ - uint32_t sndtr; /* Number of data to transfer */ - uint32_t spar; /* Peripheral address */ - uint32_t sm0ar; /* Memory address 0 */ - uint32_t sm1ar; /* address 1 for double buffer */ - uint32_t sfcr; /* FIFO control */ + uint32_t scr; /* Control */ + uint32_t sndtr; /* Number of data to transfer */ + uint32_t spar; /* Peripheral address */ + uint32_t sm0ar; /* Memory address 0 */ + uint32_t sm1ar; /* address 1 for double buffer */ + uint32_t sfcr; /* FIFO control */ }; /* Always use stm32_dma_stream_t so volatile keyword is included! */ @@ -852,12 +845,11 @@ typedef volatile struct stm32_dma_stream stm32_dma_stream_t; /* Common code and header file must use this */ typedef stm32_dma_stream_t dma_chan_t; struct stm32_dma_regs { - uint32_t isr[2]; - uint32_t ifcr[2]; + uint32_t isr[2]; + uint32_t ifcr[2]; stm32_dma_stream_t stream[STM32_DMAS_COUNT]; }; - /* Always use stm32_dma_regs_t so volatile keyword is included! */ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; @@ -868,215 +860,134 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_DMA_REGS(channel) \ ((channel) < STM32_DMAS_COUNT ? STM32_DMA1_REGS : STM32_DMA2_REGS) -#define STM32_DMA_CCR_EN BIT(0) -#define STM32_DMA_CCR_DMEIE BIT(1) -#define STM32_DMA_CCR_TEIE BIT(2) -#define STM32_DMA_CCR_HTIE BIT(3) -#define STM32_DMA_CCR_TCIE BIT(4) -#define STM32_DMA_CCR_PFCTRL BIT(5) -#define STM32_DMA_CCR_DIR_P2M (0 << 6) -#define STM32_DMA_CCR_DIR_M2P (1 << 6) -#define STM32_DMA_CCR_DIR_M2M (2 << 6) -#define STM32_DMA_CCR_CIRC BIT(8) -#define STM32_DMA_CCR_PINC BIT(9) -#define STM32_DMA_CCR_MINC BIT(10) -#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 11) -#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 11) -#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 11) -#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 13) -#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 13) -#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 13) -#define STM32_DMA_CCR_PINCOS BIT(15) -#define STM32_DMA_CCR_PL_LOW (0 << 16) -#define STM32_DMA_CCR_PL_MEDIUM (1 << 16) -#define STM32_DMA_CCR_PL_HIGH (2 << 16) -#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 16) -#define STM32_DMA_CCR_DBM BIT(18) -#define STM32_DMA_CCR_CT BIT(19) -#define STM32_DMA_CCR_PBURST(b_len) ((((b_len) - 4) / 4) << 21) -#define STM32_DMA_CCR_MBURST(b_len) ((((b_len) - 4) / 4) << 21) -#define STM32_DMA_CCR_CHANNEL_MASK (0x7 << 25) -#define STM32_DMA_CCR_CHANNEL(channel) ((channel) << 25) -#define STM32_DMA_CCR_RSVD_MASK (0xF0100000) - - -#define STM32_DMA_SFCR_DMDIS BIT(2) -#define STM32_DMA_SFCR_FTH(level) (((level) - 1) << 0) - - -#define STM32_DMA_CH_LOCAL(channel) ((channel) % STM32_DMAS_COUNT) -#define STM32_DMA_CH_LH(channel) \ - ((STM32_DMA_CH_LOCAL(channel) < 4) ? 0 : 1) -#define STM32_DMA_CH_OFFSET(channel) \ +#define STM32_DMA_CCR_EN BIT(0) +#define STM32_DMA_CCR_DMEIE BIT(1) +#define STM32_DMA_CCR_TEIE BIT(2) +#define STM32_DMA_CCR_HTIE BIT(3) +#define STM32_DMA_CCR_TCIE BIT(4) +#define STM32_DMA_CCR_PFCTRL BIT(5) +#define STM32_DMA_CCR_DIR_P2M (0 << 6) +#define STM32_DMA_CCR_DIR_M2P (1 << 6) +#define STM32_DMA_CCR_DIR_M2M (2 << 6) +#define STM32_DMA_CCR_CIRC BIT(8) +#define STM32_DMA_CCR_PINC BIT(9) +#define STM32_DMA_CCR_MINC BIT(10) +#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 11) +#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 11) +#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 11) +#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 13) +#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 13) +#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 13) +#define STM32_DMA_CCR_PINCOS BIT(15) +#define STM32_DMA_CCR_PL_LOW (0 << 16) +#define STM32_DMA_CCR_PL_MEDIUM (1 << 16) +#define STM32_DMA_CCR_PL_HIGH (2 << 16) +#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 16) +#define STM32_DMA_CCR_DBM BIT(18) +#define STM32_DMA_CCR_CT BIT(19) +#define STM32_DMA_CCR_PBURST(b_len) ((((b_len)-4) / 4) << 21) +#define STM32_DMA_CCR_MBURST(b_len) ((((b_len)-4) / 4) << 21) +#define STM32_DMA_CCR_CHANNEL_MASK (0x7 << 25) +#define STM32_DMA_CCR_CHANNEL(channel) ((channel) << 25) +#define STM32_DMA_CCR_RSVD_MASK (0xF0100000) + +#define STM32_DMA_SFCR_DMDIS BIT(2) +#define STM32_DMA_SFCR_FTH(level) (((level)-1) << 0) + +#define STM32_DMA_CH_LOCAL(channel) ((channel) % STM32_DMAS_COUNT) +#define STM32_DMA_CH_LH(channel) ((STM32_DMA_CH_LOCAL(channel) < 4) ? 0 : 1) +#define STM32_DMA_CH_OFFSET(channel) \ (((STM32_DMA_CH_LOCAL(channel) % 4) * 6) + \ - (((STM32_DMA_CH_LOCAL(channel) % 4) >= 2) ? 4 : 0)) + (((STM32_DMA_CH_LOCAL(channel) % 4) >= 2) ? 4 : 0)) #define STM32_DMA_CH_GETBITS(channel, val) \ (((val) >> STM32_DMA_CH_OFFSET(channel)) & 0x3f) -#define STM32_DMA_GET_IFCR(channel) \ - (STM32_DMA_CH_GETBITS(channel, \ - STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)])) -#define STM32_DMA_GET_ISR(channel) \ - (STM32_DMA_CH_GETBITS(channel, \ - STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)])) - -#define STM32_DMA_SET_IFCR(channel, val) \ - (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] = \ - (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] & \ - ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & 0x3f) << STM32_DMA_CH_OFFSET(channel))) -#define STM32_DMA_SET_ISR(channel, val) \ - (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] = \ - (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] & \ - ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & 0x3f) << STM32_DMA_CH_OFFSET(channel))) - -#define STM32_DMA_FEIF BIT(0) -#define STM32_DMA_DMEIF BIT(2) -#define STM32_DMA_TEIF BIT(3) -#define STM32_DMA_HTIF BIT(4) -#define STM32_DMA_TCIF BIT(5) -#define STM32_DMA_ALL 0x3d - - +#define STM32_DMA_GET_IFCR(channel) \ + (STM32_DMA_CH_GETBITS( \ + channel, \ + STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)])) +#define STM32_DMA_GET_ISR(channel) \ + (STM32_DMA_CH_GETBITS( \ + channel, \ + STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)])) + +#define STM32_DMA_SET_IFCR(channel, val) \ + (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] = \ + (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] & \ + ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&0x3f) << STM32_DMA_CH_OFFSET(channel))) +#define STM32_DMA_SET_ISR(channel, val) \ + (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] = \ + (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] & \ + ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&0x3f) << STM32_DMA_CH_OFFSET(channel))) + +#define STM32_DMA_FEIF BIT(0) +#define STM32_DMA_DMEIF BIT(2) +#define STM32_DMA_TEIF BIT(3) +#define STM32_DMA_HTIF BIT(4) +#define STM32_DMA_TCIF BIT(5) +#define STM32_DMA_ALL 0x3d /* --- CRC --- */ -#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) - -#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) -#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) -#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) -#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) - -#define STM32_CRC_CR_RESET BIT(0) -#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) -#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) -#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) -#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) -#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) -#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) -#define STM32_CRC_CR_REV_IN_WORD (3 << 5) -#define STM32_CRC_CR_REV_OUT BIT(7) +#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) + +#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) +#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) +#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) +#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) + +#define STM32_CRC_CR_RESET BIT(0) +#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) +#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) +#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) +#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) +#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) +#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) +#define STM32_CRC_CR_REV_IN_WORD (3 << 5) +#define STM32_CRC_CR_REV_OUT BIT(7) /* --- PMSE --- */ -#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) -#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) -#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) -#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) -#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) -#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) -#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) -#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x) * 4) -#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) -#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) -#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) -#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) -#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) -#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) -#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) -#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) -#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) -#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) -#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) - -/* --- USB --- */ -#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n) * 4) - -#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) - -#define STM32_USB_CNTR_FRES BIT(0) -#define STM32_USB_CNTR_PDWN BIT(1) -#define STM32_USB_CNTR_LP_MODE BIT(2) -#define STM32_USB_CNTR_FSUSP BIT(3) -#define STM32_USB_CNTR_RESUME BIT(4) -#define STM32_USB_CNTR_L1RESUME BIT(5) -#define STM32_USB_CNTR_L1REQM BIT(7) -#define STM32_USB_CNTR_ESOFM BIT(8) -#define STM32_USB_CNTR_SOFM BIT(9) -#define STM32_USB_CNTR_RESETM BIT(10) -#define STM32_USB_CNTR_SUSPM BIT(11) -#define STM32_USB_CNTR_WKUPM BIT(12) -#define STM32_USB_CNTR_ERRM BIT(13) -#define STM32_USB_CNTR_PMAOVRM BIT(14) -#define STM32_USB_CNTR_CTRM BIT(15) - -#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) - -#define STM32_USB_ISTR_EP_ID_MASK (0x000f) -#define STM32_USB_ISTR_DIR BIT(4) -#define STM32_USB_ISTR_L1REQ BIT(7) -#define STM32_USB_ISTR_ESOF BIT(8) -#define STM32_USB_ISTR_SOF BIT(9) -#define STM32_USB_ISTR_RESET BIT(10) -#define STM32_USB_ISTR_SUSP BIT(11) -#define STM32_USB_ISTR_WKUP BIT(12) -#define STM32_USB_ISTR_ERR BIT(13) -#define STM32_USB_ISTR_PMAOVR BIT(14) -#define STM32_USB_ISTR_CTR BIT(15) - -#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) - -#define STM32_USB_FNR_RXDP_RXDM_SHIFT (14) -#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) - -#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) -#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) -#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) -#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) - -#define STM32_USB_BCDR_BCDEN BIT(0) -#define STM32_USB_BCDR_DCDEN BIT(1) -#define STM32_USB_BCDR_PDEN BIT(2) -#define STM32_USB_BCDR_SDEN BIT(3) -#define STM32_USB_BCDR_DCDET BIT(4) -#define STM32_USB_BCDR_PDET BIT(5) -#define STM32_USB_BCDR_SDET BIT(6) -#define STM32_USB_BCDR_PS2DET BIT(7) - -#define EP_MASK 0x0F0F -#define EP_TX_DTOG 0x0040 -#define EP_TX_MASK 0x0030 -#define EP_TX_VALID 0x0030 -#define EP_TX_NAK 0x0020 -#define EP_TX_STALL 0x0010 -#define EP_TX_DISAB 0x0000 -#define EP_RX_DTOG 0x4000 -#define EP_RX_MASK 0x3000 -#define EP_RX_VALID 0x3000 -#define EP_RX_NAK 0x2000 -#define EP_RX_STALL 0x1000 -#define EP_RX_DISAB 0x0000 - -#define EP_STATUS_OUT 0x0100 - -#define EP_TX_RX_MASK (EP_TX_MASK | EP_RX_MASK) -#define EP_TX_RX_VALID (EP_TX_VALID | EP_RX_VALID) - -#define STM32_TOGGLE_EP(n, mask, val, flags) \ - STM32_USB_EP(n) = (((STM32_USB_EP(n) & (EP_MASK | (mask))) \ - ^ (val)) | (flags)) +#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) +#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) +#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) +#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) +#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) +#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) +#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) +#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x)*4) +#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) +#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) +#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) +#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) +#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) +#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) +#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) +#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) +#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) +#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) +#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) /* --- TRNG --- */ -#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) -#define STM32_RNG_CR_RNGEN BIT(2) -#define STM32_RNG_CR_IE BIT(3) -#define STM32_RNG_CR_CED BIT(5) -#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) -#define STM32_RNG_SR_DRDY BIT(0) -#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) +#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) +#define STM32_RNG_CR_RNGEN BIT(2) +#define STM32_RNG_CR_IE BIT(3) +#define STM32_RNG_CR_CED BIT(5) +#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) +#define STM32_RNG_SR_DRDY BIT(0) +#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) /* --- AXI interconnect --- */ /* STM32H7: AXI_TARGx_FN_MOD exists for masters x = 1, 2 and 7 */ -#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + \ - 0x1000 * (x)) -#define WRITE_ISS_OVERRIDE BIT(1) -#define READ_ISS_OVERRIDE BIT(0) +#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + 0x1000 * (x)) +#define WRITE_ISS_OVERRIDE BIT(1) +#define READ_ISS_OVERRIDE BIT(0) /* --- MISC --- */ -#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) -#define STM32_UNIQUE_ID_LENGTH (3 * 4) +#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) +#define STM32_UNIQUE_ID_LENGTH (3 * 4) #endif /* !__ASSEMBLER__ */ diff --git a/chip/stm32/registers-stm32g4.h b/chip/stm32/registers-stm32g4.h index 4fe97e4c29..a19aa942b0 100644 --- a/chip/stm32/registers-stm32g4.h +++ b/chip/stm32/registers-stm32g4.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,87 +19,87 @@ #endif /* --- IRQ numbers --- */ -#define STM32_IRQ_WWDG 0 -#define STM32_IRQ_PVD 1 -#define STM32_IRQ_TAMPER_STAMP 2 -#define STM32_IRQ_RTC_WAKEUP 3 -#define STM32_IRQ_FLASH 4 -#define STM32_IRQ_RCC 5 -#define STM32_IRQ_EXTI0 6 -#define STM32_IRQ_EXTI1 7 -#define STM32_IRQ_EXTI2 8 -#define STM32_IRQ_EXTI3 9 -#define STM32_IRQ_EXTI4 10 -#define STM32_IRQ_DMA_CHANNEL_1 11 -#define STM32_IRQ_DMA_CHANNEL_2 12 -#define STM32_IRQ_DMA_CHANNEL_3 13 -#define STM32_IRQ_DMA_CHANNEL_4 14 -#define STM32_IRQ_DMA_CHANNEL_5 15 -#define STM32_IRQ_DMA_CHANNEL_6 16 -#define STM32_IRQ_DMA_CHANNEL_7 17 -#define STM32_IRQ_ADC1 18 -#define STM32_IRQ_USB_HP 19 -#define STM32_IRQ_USB_LP 20 -#define STM32_IRQ_FDCAN_IT0 21 -#define STM32_IRQ_FDCAN_IT1 22 -#define STM32_IRQ_EXTI9_5 23 -#define STM32_IRQ_TIM15 24 -#define STM32_IRQ_TIM16 25 -#define STM32_IRQ_TIM17 26 -#define STM32_IRQ_TIM1_CC 27 -#define STM32_IRQ_TIM2 28 -#define STM32_IRQ_TIM3 29 -#define STM32_IRQ_TIM4 30 -#define STM32_IRQ_I2C1_EV 31 -#define STM32_IRQ_I2C1_ER 32 -#define STM32_IRQ_I2C2_EV 33 -#define STM32_IRQ_I2C2_ER 34 -#define STM32_IRQ_SPI1 35 -#define STM32_IRQ_SPI2 36 -#define STM32_IRQ_USART1 37 -#define STM32_IRQ_USART2 38 -#define STM32_IRQ_USART3 39 -#define STM32_IRQ_EXTI15_10 40 -#define STM32_IRQ_RTC_ALARM 41 -#define STM32_IRQ_USB_FS_WAKEUP 42 -#define STM32_IRQ_TIM8_BREAK 43 -#define STM32_IRQ_TIM8_UP 44 -#define STM32_IRQ_TIM8_TRG_COM 45 -#define STM32_IRQ_TIM8_CC 46 -#define STM32_IRQ_LPTIM1 49 -#define STM32_IRQ_SPI3 51 -#define STM32_IRQ_USART4 52 -#define STM32_IRQ_TIM6_DAC 54 -#define STM32_IRQ_TIM7 55 -#define STM32_IRQ_DMA2_CHANNEL1 56 -#define STM32_IRQ_DMA2_CHANNEL2 57 -#define STM32_IRQ_DMA2_CHANNEL3 58 -#define STM32_IRQ_DMA2_CHANNEL4 59 -#define STM32_IRQ_DMA2_CHANNEL5 60 -#define STM32_IRQ_UCPD1 63 -#define STM32_IRQ_COMP_1_2_3 64 -#define STM32_IRQ_COMP_4 65 -#define STM32_IRQ_CRS 75 -#define STM32_IRQ_SAI1 76 -#define STM32_IRQ_FPU 81 -#define STM32_IRQ_RNG 90 -#define STM32_IRQ_LPUART 91 -#define STM32_IRQ_I2C3_EV 92 -#define STM32_IRQ_I2C3_ER 93 -#define STM32_IRQ_DMAMUX_OVR 94 -#define STM32_IRQ_DMA1_CHANNEL8 96 -#define STM32_IRQ_DMA2_CHANNEL6 97 -#define STM32_IRQ_DMA2_CHANNEL7 98 -#define STM32_IRQ_DMA2_CHANNEL8 99 -#define STM32_IRQ_CORDIC 100 -#define STM32_IRQ_FMAC 101 +#define STM32_IRQ_WWDG 0 +#define STM32_IRQ_PVD 1 +#define STM32_IRQ_TAMPER_STAMP 2 +#define STM32_IRQ_RTC_WAKEUP 3 +#define STM32_IRQ_FLASH 4 +#define STM32_IRQ_RCC 5 +#define STM32_IRQ_EXTI0 6 +#define STM32_IRQ_EXTI1 7 +#define STM32_IRQ_EXTI2 8 +#define STM32_IRQ_EXTI3 9 +#define STM32_IRQ_EXTI4 10 +#define STM32_IRQ_DMA_CHANNEL_1 11 +#define STM32_IRQ_DMA_CHANNEL_2 12 +#define STM32_IRQ_DMA_CHANNEL_3 13 +#define STM32_IRQ_DMA_CHANNEL_4 14 +#define STM32_IRQ_DMA_CHANNEL_5 15 +#define STM32_IRQ_DMA_CHANNEL_6 16 +#define STM32_IRQ_DMA_CHANNEL_7 17 +#define STM32_IRQ_ADC1 18 +#define STM32_IRQ_USB_HP 19 +#define STM32_IRQ_USB_LP 20 +#define STM32_IRQ_FDCAN_IT0 21 +#define STM32_IRQ_FDCAN_IT1 22 +#define STM32_IRQ_EXTI9_5 23 +#define STM32_IRQ_TIM15 24 +#define STM32_IRQ_TIM16 25 +#define STM32_IRQ_TIM17 26 +#define STM32_IRQ_TIM1_CC 27 +#define STM32_IRQ_TIM2 28 +#define STM32_IRQ_TIM3 29 +#define STM32_IRQ_TIM4 30 +#define STM32_IRQ_I2C1_EV 31 +#define STM32_IRQ_I2C1_ER 32 +#define STM32_IRQ_I2C2_EV 33 +#define STM32_IRQ_I2C2_ER 34 +#define STM32_IRQ_SPI1 35 +#define STM32_IRQ_SPI2 36 +#define STM32_IRQ_USART1 37 +#define STM32_IRQ_USART2 38 +#define STM32_IRQ_USART3 39 +#define STM32_IRQ_EXTI15_10 40 +#define STM32_IRQ_RTC_ALARM 41 +#define STM32_IRQ_USB_FS_WAKEUP 42 +#define STM32_IRQ_TIM8_BREAK 43 +#define STM32_IRQ_TIM8_UP 44 +#define STM32_IRQ_TIM8_TRG_COM 45 +#define STM32_IRQ_TIM8_CC 46 +#define STM32_IRQ_LPTIM1 49 +#define STM32_IRQ_SPI3 51 +#define STM32_IRQ_USART4 52 +#define STM32_IRQ_TIM6_DAC 54 +#define STM32_IRQ_TIM7 55 +#define STM32_IRQ_DMA2_CHANNEL1 56 +#define STM32_IRQ_DMA2_CHANNEL2 57 +#define STM32_IRQ_DMA2_CHANNEL3 58 +#define STM32_IRQ_DMA2_CHANNEL4 59 +#define STM32_IRQ_DMA2_CHANNEL5 60 +#define STM32_IRQ_UCPD1 63 +#define STM32_IRQ_COMP_1_2_3 64 +#define STM32_IRQ_COMP_4 65 +#define STM32_IRQ_CRS 75 +#define STM32_IRQ_SAI1 76 +#define STM32_IRQ_FPU 81 +#define STM32_IRQ_RNG 90 +#define STM32_IRQ_LPUART 91 +#define STM32_IRQ_I2C3_EV 92 +#define STM32_IRQ_I2C3_ER 93 +#define STM32_IRQ_DMAMUX_OVR 94 +#define STM32_IRQ_DMA1_CHANNEL8 96 +#define STM32_IRQ_DMA2_CHANNEL6 97 +#define STM32_IRQ_DMA2_CHANNEL7 98 +#define STM32_IRQ_DMA2_CHANNEL8 99 +#define STM32_IRQ_CORDIC 100 +#define STM32_IRQ_FMAC 101 /* LPUART gets accessed as UART9 in STM32 uart driver */ #define STM32_IRQ_USART9 STM32_IRQ_LPUART /* To simplify code generation, define DMA channel 13 - 14 */ -#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 -#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 +#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 +#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 /* aliases for easier code sharing */ #define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV @@ -111,142 +111,144 @@ #endif /* Embedded flash option bytes base address */ -#define STM32_OPTB_BASE 0x1FFF7800 +#define STM32_OPTB_BANK1_BASE 0x1FFF7800UL +#define STM32_OPTB_BANK2_BASE 0x1FFF8000UL /* Peripheral base addresses */ -#define STM32_PERIPH_BASE (0x40000000UL) +#define STM32_PERIPH_BASE (0x40000000UL) /* Peripheral memory map */ -#define STM32_APB1PERIPH_BASE (STM32_PERIPH_BASE + 0x00000000UL) -#define STM32_APB2PERIPH_BASE (STM32_PERIPH_BASE + 0x00010000UL) -#define STM32_AHB1PERIPH_BASE (STM32_PERIPH_BASE + 0x00020000UL) -#define STM32_AHB2PERIPH_BASE (STM32_PERIPH_BASE + 0x08000000UL) +#define STM32_APB1PERIPH_BASE (STM32_PERIPH_BASE + 0x00000000UL) +#define STM32_APB2PERIPH_BASE (STM32_PERIPH_BASE + 0x00010000UL) +#define STM32_AHB1PERIPH_BASE (STM32_PERIPH_BASE + 0x00020000UL) +#define STM32_AHB2PERIPH_BASE (STM32_PERIPH_BASE + 0x08000000UL) /* APB1 peripherals */ -#define STM32_APB1PERIPH(offset) (STM32_APB1PERIPH_BASE + offset) -#define STM32_TIM2_BASE STM32_APB1PERIPH(0x0000UL) -#define STM32_TIM3_BASE STM32_APB1PERIPH(0x0400UL) -#define STM32_TIM4_BASE STM32_APB1PERIPH(0x0800UL) -#define STM32_TIM6_BASE STM32_APB1PERIPH(0x1000UL) -#define STM32_TIM7_BASE STM32_APB1PERIPH(0x1400UL) -#define STM32_CRS_BASE STM32_APB1PERIPH(0x2000UL) -#define STM32_TAMP_BASE STM32_APB1PERIPH(0x2400UL) -#define STM32_RTC_BASE STM32_APB1PERIPH(0x2800UL) -#define STM32_WWDG_BASE STM32_APB1PERIPH(0x2C00UL) -#define STM32_IWDG_BASE STM32_APB1PERIPH(0x3000UL) -#define STM32_SPI2_BASE STM32_APB1PERIPH(0x3800UL) -#define STM32_SPI3_BASE STM32_APB1PERIPH(0x3C00UL) -#define STM32_USART2_BASE STM32_APB1PERIPH(0x4400UL) -#define STM32_USART3_BASE STM32_APB1PERIPH(0x4800UL) -#define STM32_UART4_BASE STM32_APB1PERIPH(0x4C00UL) -#define STM32_I2C1_BASE STM32_APB1PERIPH(0x5400UL) -#define STM32_I2C2_BASE STM32_APB1PERIPH(0x5800UL) +#define STM32_APB1PERIPH(offset) (STM32_APB1PERIPH_BASE + offset) +#define STM32_TIM2_BASE STM32_APB1PERIPH(0x0000UL) +#define STM32_TIM3_BASE STM32_APB1PERIPH(0x0400UL) +#define STM32_TIM4_BASE STM32_APB1PERIPH(0x0800UL) +#define STM32_TIM6_BASE STM32_APB1PERIPH(0x1000UL) +#define STM32_TIM7_BASE STM32_APB1PERIPH(0x1400UL) +#define STM32_CRS_BASE STM32_APB1PERIPH(0x2000UL) +#define STM32_TAMP_BASE STM32_APB1PERIPH(0x2400UL) +#define STM32_RTC_BASE STM32_APB1PERIPH(0x2800UL) +#define STM32_WWDG_BASE STM32_APB1PERIPH(0x2C00UL) +#define STM32_IWDG_BASE STM32_APB1PERIPH(0x3000UL) +#define STM32_SPI2_BASE STM32_APB1PERIPH(0x3800UL) +#define STM32_SPI3_BASE STM32_APB1PERIPH(0x3C00UL) +#define STM32_USART2_BASE STM32_APB1PERIPH(0x4400UL) +#define STM32_USART3_BASE STM32_APB1PERIPH(0x4800UL) +#define STM32_UART4_BASE STM32_APB1PERIPH(0x4C00UL) +#define STM32_I2C1_BASE STM32_APB1PERIPH(0x5400UL) +#define STM32_I2C2_BASE STM32_APB1PERIPH(0x5800UL) /* USB_IP Peripheral Registers base address */ -#define STM32_USB_BASE STM32_APB1PERIPH(0x5C00UL) +#define STM32_USB_FS_BASE STM32_APB1PERIPH(0x5C00UL) /* USB_IP Packet Memory Area base address */ -#define STM32_USB_PMAADDR STM32_APB1PERIPH(0x6000UL) -#define STM32_FDCAN1_BASE STM32_APB1PERIPH(0x6400UL) +#define STM32_USB_PMAADDR STM32_APB1PERIPH(0x6000UL) +#define STM32_FDCAN1_BASE STM32_APB1PERIPH(0x6400UL) /* FDCAN configuration registers base address */ -#define STM32_FDCAN_CONFIG_BASE STM32_APB1PERIPH(0x6500UL) -#define STM32_PWR_BASE STM32_APB1PERIPH(0x7000UL) -#define STM32_I2C3_BASE STM32_APB1PERIPH(0x7800UL) -#define STM32_LPTIM1_BASE STM32_APB1PERIPH(0x7C00UL) -#define STM32_LPUART1_BASE STM32_APB1PERIPH(0x8000UL) -#define STM32_I2C4_BASE STM32_APB1PERIPH(0x8400UL) +#define STM32_FDCAN_CONFIG_BASE STM32_APB1PERIPH(0x6500UL) +#define STM32_PWR_BASE STM32_APB1PERIPH(0x7000UL) +#define STM32_I2C3_BASE STM32_APB1PERIPH(0x7800UL) +#define STM32_LPTIM1_BASE STM32_APB1PERIPH(0x7C00UL) +#define STM32_LPUART1_BASE STM32_APB1PERIPH(0x8000UL) +#define STM32_I2C4_BASE STM32_APB1PERIPH(0x8400UL) /* UART9 is used as link to LPUART in STM32 uart.c implementation */ -#define STM32_USART9_BASE STM32_APB1PERIPH(0x8000UL) -#define STM32_UCPD1_BASE STM32_APB1PERIPH(0xA000UL) -#define STM32_SRAMCAN_BASE STM32_APB1PERIPH(0xA400UL) +#define STM32_USART9_BASE STM32_APB1PERIPH(0x8000UL) +#define STM32_I2C4_BASE STM32_APB1PERIPH(0x8400UL) +#define STM32_UCPD1_BASE STM32_APB1PERIPH(0xA000UL) +#define STM32_SRAMCAN_BASE STM32_APB1PERIPH(0xA400UL) /* APB2 peripherals */ -#define STM32_APB2PERIPH(offset) (STM32_APB2PERIPH_BASE + offset) -#define STM32_SYSCFG_BASE STM32_APB2PERIPH(0x0000UL) -#define STM32_VREFBUF_BASE STM32_APB2PERIPH(0x0030UL) -#define STM32_COMP1_BASE STM32_APB2PERIPH(0x0200UL) -#define STM32_COMP2_BASE STM32_APB2PERIPH(0x0204UL) -#define STM32_COMP3_BASE STM32_APB2PERIPH(0x0208UL) -#define STM32_COMP4_BASE STM32_APB2PERIPH(0x020CUL) -#define STM32_OPAMP_BASE STM32_APB2PERIPH(0x0300UL) -#define STM32_OPAMP1_BASE STM32_APB2PERIPH(0x0300UL) -#define STM32_OPAMP2_BASE STM32_APB2PERIPH(0x0304UL) -#define STM32_OPAMP3_BASE STM32_APB2PERIPH(0x0308UL) -#define STM32_EXTI_BASE STM32_APB2PERIPH(0x0400UL) -#define STM32_TIM1_BASE STM32_APB2PERIPH(0x2C00UL) -#define STM32_SPI1_BASE STM32_APB2PERIPH(0x3000UL) -#define STM32_TIM8_BASE STM32_APB2PERIPH(0x3400UL) -#define STM32_USART1_BASE STM32_APB2PERIPH(0x3800UL) -#define STM32_TIM15_BASE STM32_APB2PERIPH(0x4000UL) -#define STM32_TIM16_BASE STM32_APB2PERIPH(0x4400UL) -#define STM32_TIM17_BASE STM32_APB2PERIPH(0x4800UL) -#define STM32_SAI1_BASE STM32_APB2PERIPH(0x5400UL) -#define STM32_SAI1_Block_A_BASE (SAI1_BASE + 0x0004UL) -#define STM32_SAI1_Block_B_BASE (SAI1_BASE + 0x0024UL) +#define STM32_APB2PERIPH(offset) (STM32_APB2PERIPH_BASE + offset) +#define STM32_SYSCFG_BASE STM32_APB2PERIPH(0x0000UL) +#define STM32_VREFBUF_BASE STM32_APB2PERIPH(0x0030UL) +#define STM32_COMP1_BASE STM32_APB2PERIPH(0x0200UL) +#define STM32_COMP2_BASE STM32_APB2PERIPH(0x0204UL) +#define STM32_COMP3_BASE STM32_APB2PERIPH(0x0208UL) +#define STM32_COMP4_BASE STM32_APB2PERIPH(0x020CUL) +#define STM32_OPAMP_BASE STM32_APB2PERIPH(0x0300UL) +#define STM32_OPAMP1_BASE STM32_APB2PERIPH(0x0300UL) +#define STM32_OPAMP2_BASE STM32_APB2PERIPH(0x0304UL) +#define STM32_OPAMP3_BASE STM32_APB2PERIPH(0x0308UL) +#define STM32_EXTI_BASE STM32_APB2PERIPH(0x0400UL) +#define STM32_TIM1_BASE STM32_APB2PERIPH(0x2C00UL) +#define STM32_SPI1_BASE STM32_APB2PERIPH(0x3000UL) +#define STM32_TIM8_BASE STM32_APB2PERIPH(0x3400UL) +#define STM32_USART1_BASE STM32_APB2PERIPH(0x3800UL) +#define STM32_TIM15_BASE STM32_APB2PERIPH(0x4000UL) +#define STM32_TIM16_BASE STM32_APB2PERIPH(0x4400UL) +#define STM32_TIM17_BASE STM32_APB2PERIPH(0x4800UL) +#define STM32_SAI1_BASE STM32_APB2PERIPH(0x5400UL) +#define STM32_SAI1_Block_A_BASE (SAI1_BASE + 0x0004UL) +#define STM32_SAI1_Block_B_BASE (SAI1_BASE + 0x0024UL) /* AHB1 peripherals */ -#define STM32_AHB1PERIPH(offset) (STM32_AHB1PERIPH_BASE + offset) -#define STM32_DMA1_BASE STM32_AHB1PERIPH(0x0000UL) -#define STM32_DMA2_BASE STM32_AHB1PERIPH(0x0400UL) -#define STM32_DMAMUX_BASE STM32_AHB1PERIPH(0x0800UL) -#define STM32_CORDIC_BASE STM32_AHB1PERIPH(0x0C00UL) -#define STM32_RCC_BASE STM32_AHB1PERIPH(0x1000UL) -#define STM32_FMAC_BASE STM32_AHB1PERIPH(0x1400UL) -#define STM32_FLASH_REGS_BASE STM32_AHB1PERIPH(0x2000UL) -#define STM32_CRC_BASE STM32_AHB1PERIPH(0x3000UL) - -#define STM32_DMA1_CHAN(offset) (STM32_DMA1_BASE + offset) -#define STM32_DMA1_Channel1_BASE STM32_DMA1_CHAN(0x0008UL) -#define STM32_DMA1_Channel2_BASE STM32_DMA1_CHAN(0x001CUL) -#define STM32_DMA1_Channel3_BASE STM32_DMA1_CHAN(0x0030UL) -#define STM32_DMA1_Channel4_BASE STM32_DMA1_CHAN(0x0044UL) -#define STM32_DMA1_Channel5_BASE STM32_DMA1_CHAN(0x0058UL) -#define STM32_DMA1_Channel6_BASE STM32_DMA1_CHAN(0x006CUL) - -#define STM32_DMA2_CHAN(offset) (STM32_DMA2_BASE + offset) -#define STM32_DMA2_Channel1_BASE STM32_DMA2_CHAN(0x0008UL) -#define STM32_DMA2_Channel2_BASE STM32_DMA2_CHAN(0x001CUL) -#define STM32_DMA2_Channel3_BASE STM32_DMA2_CHAN(0x0030UL) -#define STM32_DMA2_Channel4_BASE STM32_DMA2_CHAN(0x0044UL) -#define STM32_DMA2_Channel5_BASE STM32_DMA2_CHAN(0x0058UL) -#define STM32_DMA2_Channel6_BASE STM32_DMA2_CHAN(0x006CUL) - -#define STM32_DMAMUX(offset) (STM32_DMAMUX_BASE + offset) -#define STM32_DMAMUX_Channel0_BASE STM32_DMAMUX(0x0000UL) -#define STM32_DMAMUX_Channel1_BASE STM32_DMAMUX(0x0004UL) -#define STM32_DMAMUX_Channel2_BASE STM32_DMAMUX(0x0008UL) -#define STM32_DMAMUX_Channel3_BASE STM32_DMAMUX(0x000CUL) -#define STM32_DMAMUX_Channel4_BASE STM32_DMAMUX(0x0010UL) -#define STM32_DMAMUX_Channel5_BASE STM32_DMAMUX(0x0014UL) -#define STM32_DMAMUX_Channel6_BASE STM32_DMAMUX(0x0020UL) -#define STM32_DMAMUX_Channel7_BASE STM32_DMAMUX(0x0024UL) -#define STM32_DMAMUX_Channel8_BASE STM32_DMAMUX(0x0028UL) -#define STM32_DMAMUX_Channel9_BASE STM32_DMAMUX(0x002CUL) -#define STM32_DMAMUX_Channel10_BASE STM32_DMAMUX(0x0030UL) -#define STM32_DMAMUX_Channel11_BASE STM32_DMAMUX(0x0034UL) -#define STM32_DMAMUX_RequestGenerator0_BASE STM32_DMAMUX(0x0100UL) -#define STM32_DMAMUX_RequestGenerator1_BASE STM32_DMAMUX(0x0104UL) -#define STM32_DMAMUX_RequestGenerator2_BASE STM32_DMAMUX(0x0108UL) -#define STM32_DMAMUX_RequestGenerator3_BASE STM32_DMAMUX(0x010CUL) -#define STM32_DMAMUX_ChannelStatus_BASE STM32_DMAMUX(0x0080UL) -#define STM32_DMAMUX_RequestGenStatus_BASE STM32_DMAMUX(0x0140UL) +#define STM32_AHB1PERIPH(offset) (STM32_AHB1PERIPH_BASE + offset) +#define STM32_DMA1_BASE STM32_AHB1PERIPH(0x0000UL) +#define STM32_DMA2_BASE STM32_AHB1PERIPH(0x0400UL) +#define STM32_DMAMUX_BASE STM32_AHB1PERIPH(0x0800UL) +#define STM32_CORDIC_BASE STM32_AHB1PERIPH(0x0C00UL) +#define STM32_RCC_BASE STM32_AHB1PERIPH(0x1000UL) +#define STM32_FMAC_BASE STM32_AHB1PERIPH(0x1400UL) +#define STM32_FLASH_REGS_BASE STM32_AHB1PERIPH(0x2000UL) +#define STM32_CRC_BASE STM32_AHB1PERIPH(0x3000UL) + +#define STM32_DMA1_CHAN(offset) (STM32_DMA1_BASE + offset) +#define STM32_DMA1_Channel1_BASE STM32_DMA1_CHAN(0x0008UL) +#define STM32_DMA1_Channel2_BASE STM32_DMA1_CHAN(0x001CUL) +#define STM32_DMA1_Channel3_BASE STM32_DMA1_CHAN(0x0030UL) +#define STM32_DMA1_Channel4_BASE STM32_DMA1_CHAN(0x0044UL) +#define STM32_DMA1_Channel5_BASE STM32_DMA1_CHAN(0x0058UL) +#define STM32_DMA1_Channel6_BASE STM32_DMA1_CHAN(0x006CUL) + +#define STM32_DMA2_CHAN(offset) (STM32_DMA2_BASE + offset) +#define STM32_DMA2_Channel1_BASE STM32_DMA2_CHAN(0x0008UL) +#define STM32_DMA2_Channel2_BASE STM32_DMA2_CHAN(0x001CUL) +#define STM32_DMA2_Channel3_BASE STM32_DMA2_CHAN(0x0030UL) +#define STM32_DMA2_Channel4_BASE STM32_DMA2_CHAN(0x0044UL) +#define STM32_DMA2_Channel5_BASE STM32_DMA2_CHAN(0x0058UL) +#define STM32_DMA2_Channel6_BASE STM32_DMA2_CHAN(0x006CUL) + +#define STM32_DMAMUX(offset) (STM32_DMAMUX_BASE + offset) +#define STM32_DMAMUX_Channel0_BASE STM32_DMAMUX(0x0000UL) +#define STM32_DMAMUX_Channel1_BASE STM32_DMAMUX(0x0004UL) +#define STM32_DMAMUX_Channel2_BASE STM32_DMAMUX(0x0008UL) +#define STM32_DMAMUX_Channel3_BASE STM32_DMAMUX(0x000CUL) +#define STM32_DMAMUX_Channel4_BASE STM32_DMAMUX(0x0010UL) +#define STM32_DMAMUX_Channel5_BASE STM32_DMAMUX(0x0014UL) +#define STM32_DMAMUX_Channel6_BASE STM32_DMAMUX(0x0020UL) +#define STM32_DMAMUX_Channel7_BASE STM32_DMAMUX(0x0024UL) +#define STM32_DMAMUX_Channel8_BASE STM32_DMAMUX(0x0028UL) +#define STM32_DMAMUX_Channel9_BASE STM32_DMAMUX(0x002CUL) +#define STM32_DMAMUX_Channel10_BASE STM32_DMAMUX(0x0030UL) +#define STM32_DMAMUX_Channel11_BASE STM32_DMAMUX(0x0034UL) +#define STM32_DMAMUX_RequestGenerator0_BASE STM32_DMAMUX(0x0100UL) +#define STM32_DMAMUX_RequestGenerator1_BASE STM32_DMAMUX(0x0104UL) +#define STM32_DMAMUX_RequestGenerator2_BASE STM32_DMAMUX(0x0108UL) +#define STM32_DMAMUX_RequestGenerator3_BASE STM32_DMAMUX(0x010CUL) +#define STM32_DMAMUX_ChannelStatus_BASE STM32_DMAMUX(0x0080UL) +#define STM32_DMAMUX_RequestGenStatus_BASE STM32_DMAMUX(0x0140UL) /* AHB2 peripherals */ -#define STM32_AHB2PERIPH(offset) (STM32_AHB2PERIPH_BASE + offset) -#define STM32_GPIOA_BASE STM32_AHB2PERIPH(0x0000UL) -#define STM32_GPIOB_BASE STM32_AHB2PERIPH(0x0400UL) -#define STM32_GPIOC_BASE STM32_AHB2PERIPH(0x0800UL) -#define STM32_GPIOD_BASE STM32_AHB2PERIPH(0x0C00UL) -#define STM32_GPIOE_BASE STM32_AHB2PERIPH(0x1000UL) -#define STM32_GPIOF_BASE STM32_AHB2PERIPH(0x1400UL) -#define STM32_GPIOG_BASE STM32_AHB2PERIPH(0x1800UL) -#define STM32_ADC1_BASE STM32_AHB2PERIPH(0x08000000UL) -#define STM32_ADC2_BASE STM32_AHB2PERIPH(0x08000100UL) -#define STM32_ADC12_COMMON_BASE STM32_AHB2PERIPH(0x08000300UL) -#define STM32_DAC_BASE STM32_AHB2PERIPH(0x08000800UL) -#define STM32_DAC1_BASE STM32_AHB2PERIPH(0x08000800UL) -#define STM32_DAC3_BASE STM32_AHB2PERIPH(0x08001000UL) -#define STM32_RNG_BASE STM32_AHB2PERIPH(0x08060800UL) - -#define STM32_UNIQUE_ID_BASE 0x1FFF7590 -#define STM32_DBGMCU_BASE 0xE0042000 +#define STM32_AHB2PERIPH(offset) (STM32_AHB2PERIPH_BASE + offset) +#define STM32_GPIOA_BASE STM32_AHB2PERIPH(0x0000UL) +#define STM32_GPIOB_BASE STM32_AHB2PERIPH(0x0400UL) +#define STM32_GPIOC_BASE STM32_AHB2PERIPH(0x0800UL) +#define STM32_GPIOD_BASE STM32_AHB2PERIPH(0x0C00UL) +#define STM32_GPIOE_BASE STM32_AHB2PERIPH(0x1000UL) +#define STM32_GPIOF_BASE STM32_AHB2PERIPH(0x1400UL) +#define STM32_GPIOG_BASE STM32_AHB2PERIPH(0x1800UL) +#define STM32_ADC1_BASE STM32_AHB2PERIPH(0x08000000UL) +#define STM32_ADC2_BASE STM32_AHB2PERIPH(0x08000100UL) +#define STM32_ADC12_COMMON_BASE STM32_AHB2PERIPH(0x08000300UL) +#define STM32_DAC_BASE STM32_AHB2PERIPH(0x08000800UL) +#define STM32_DAC1_BASE STM32_AHB2PERIPH(0x08000800UL) +#define STM32_DAC3_BASE STM32_AHB2PERIPH(0x08001000UL) +#define STM32_RNG_BASE STM32_AHB2PERIPH(0x08060800UL) + +#define STM32_UNIQUE_ID_BASE 0x1FFF7590 +#define STM32_DBGMCU_BASE 0xE0042000 #ifndef __ASSEMBLER__ @@ -254,314 +256,299 @@ /* --- UCPD --- */ #define STM32_UCPD_REG(port, offset) \ - REG32(((STM32_UCPD1_BASE + ((port) * 0x400)) + (offset))) - -#define STM32_UCPD_CFGR1(port) STM32_UCPD_REG(port, 0x00) -#define STM32_UCPD_CFGR2(port) STM32_UCPD_REG(port, 0x04) -#define STM32_UCPD_CR(port) STM32_UCPD_REG(port, 0x0c) -#define STM32_UCPD_IMR(port) STM32_UCPD_REG(port, 0x10) -#define STM32_UCPD_SR(port) STM32_UCPD_REG(port, 0x14) -#define STM32_UCPD_ICR(port) STM32_UCPD_REG(port, 0x18) -#define STM32_UCPD_TX_ORDSETR(port) STM32_UCPD_REG(port, 0x1c) -#define STM32_UCPD_TX_PAYSZR(port) STM32_UCPD_REG(port, 0x20) -#define STM32_UCPD_TXDR(port) STM32_UCPD_REG(port, 0x24) -#define STM32_UCPD_RX_ORDSETR(port) STM32_UCPD_REG(port, 0x28) -#define STM32_UCPD_RX_PAYSZR(port) STM32_UCPD_REG(port, 0x2c) -#define STM32_UCPD_RXDR(port) STM32_UCPD_REG(port, 0x30) -#define STM32_UCPD_RX_ORDEXTR1(port) STM32_UCPD_REG(port, 0x34) -#define STM32_UCPD_RX_ORDEXTR2(port) STM32_UCPD_REG(port, 0x38) + REG32(((STM32_UCPD1_BASE + ((port)*0x400)) + (offset))) + +#define STM32_UCPD_CFGR1(port) STM32_UCPD_REG(port, 0x00) +#define STM32_UCPD_CFGR2(port) STM32_UCPD_REG(port, 0x04) +#define STM32_UCPD_CR(port) STM32_UCPD_REG(port, 0x0c) +#define STM32_UCPD_IMR(port) STM32_UCPD_REG(port, 0x10) +#define STM32_UCPD_SR(port) STM32_UCPD_REG(port, 0x14) +#define STM32_UCPD_ICR(port) STM32_UCPD_REG(port, 0x18) +#define STM32_UCPD_TX_ORDSETR(port) STM32_UCPD_REG(port, 0x1c) +#define STM32_UCPD_TX_PAYSZR(port) STM32_UCPD_REG(port, 0x20) +#define STM32_UCPD_TXDR(port) STM32_UCPD_REG(port, 0x24) +#define STM32_UCPD_RX_ORDSETR(port) STM32_UCPD_REG(port, 0x28) +#define STM32_UCPD_RX_PAYSZR(port) STM32_UCPD_REG(port, 0x2c) +#define STM32_UCPD_RXDR(port) STM32_UCPD_REG(port, 0x30) +#define STM32_UCPD_RX_ORDEXTR1(port) STM32_UCPD_REG(port, 0x34) +#define STM32_UCPD_RX_ORDEXTR2(port) STM32_UCPD_REG(port, 0x38) /* --- UCPD CFGR1 Bit Definitions --- */ -#define STM32_UCPD_CFGR1_HBITCLKD_SHIFT 0 -#define STM32_UCPD_CFGR1_HBITCLKD_MASK ((0x3f) << \ - (STM32_UCPD_CFGR1_HBITCLKD_SHIFT)) -#define STM32_UCPD_CFGR1_HBITCLKD_VAL(x) ((x) << \ - STM32_UCPD_CFGR1_HBITCLKD_SHIFT) -#define STM32_UCPD_CFGR1_IFRGAP_SHIFT 6 -#define STM32_UCPD_CFGR1_IFRGAP_MASK ((0x1f) << \ - (STM32_UCPD_CFGR1_IFRGAP_SHIFT)) -#define STM32_UCPD_CFGR1_IFRGAP_VAL(x) ((x) << \ - STM32_UCPD_CFGR1_IFRGAP_SHIFT) -#define STM32_UCPD_CFGR1_TRANSWIN_SHIFT 11 -#define STM32_UCPD_CFGR1_TRANSWIN_MASK ((0x1f) << \ - (STM32_UCPD_CFGR1_TRANSWIN_SHIFT)) -#define STM32_UCPD_CFGR1_TRANSWIN_VAL(x) ((x) << \ - STM32_UCPD_CFGR1_TRANSWIN_SHIFT) -#define STM32_UCPD_CFGR1_PSC_CLK_SHIFT 17 -#define STM32_UCPD_CFGR1_PSC_CLK_MASK ((0x7) << \ - STM32_UCPD_CFGR1_PSC_CLK_SHIFT) -#define STM32_UCPD_CFGR1_PSC_CLK_VAL(x) ((x) << \ - STM32_UCPD_CFGR1_PSC_CLK_SHIFT) -#define STM32_UCPD_CFGR1_RXORDSETEN_SHIFT 20 -#define STM32_UCPD_CFGR1_RXORDSETEN_MASK ((0x1ff) << \ - STM32_UCPD_CFGR1_RXORDSETEN_SHIFT) -#define STM32_UCPD_CFGR1_RXORDSETEN_VAL(x) ((x) << \ - STM32_UCPD_CFGR1_RXORDSETEN_SHIFT) -#define STM32_UCPD_CFGR1_TXDMAEN BIT(29) -#define STM32_UCPD_CFGR1_RXDMAEN BIT(30) -#define STM32_UCPD_CFGR1_UCPDEN BIT(31) +#define STM32_UCPD_CFGR1_HBITCLKD_SHIFT 0 +#define STM32_UCPD_CFGR1_HBITCLKD_MASK \ + ((0x3f) << (STM32_UCPD_CFGR1_HBITCLKD_SHIFT)) +#define STM32_UCPD_CFGR1_HBITCLKD_VAL(x) \ + ((x) << STM32_UCPD_CFGR1_HBITCLKD_SHIFT) +#define STM32_UCPD_CFGR1_IFRGAP_SHIFT 6 +#define STM32_UCPD_CFGR1_IFRGAP_MASK ((0x1f) << (STM32_UCPD_CFGR1_IFRGAP_SHIFT)) +#define STM32_UCPD_CFGR1_IFRGAP_VAL(x) ((x) << STM32_UCPD_CFGR1_IFRGAP_SHIFT) +#define STM32_UCPD_CFGR1_TRANSWIN_SHIFT 11 +#define STM32_UCPD_CFGR1_TRANSWIN_MASK \ + ((0x1f) << (STM32_UCPD_CFGR1_TRANSWIN_SHIFT)) +#define STM32_UCPD_CFGR1_TRANSWIN_VAL(x) \ + ((x) << STM32_UCPD_CFGR1_TRANSWIN_SHIFT) +#define STM32_UCPD_CFGR1_PSC_CLK_SHIFT 17 +#define STM32_UCPD_CFGR1_PSC_CLK_MASK ((0x7) << STM32_UCPD_CFGR1_PSC_CLK_SHIFT) +#define STM32_UCPD_CFGR1_PSC_CLK_VAL(x) ((x) << STM32_UCPD_CFGR1_PSC_CLK_SHIFT) +#define STM32_UCPD_CFGR1_RXORDSETEN_SHIFT 20 +#define STM32_UCPD_CFGR1_RXORDSETEN_MASK \ + ((0x1ff) << STM32_UCPD_CFGR1_RXORDSETEN_SHIFT) +#define STM32_UCPD_CFGR1_RXORDSETEN_VAL(x) \ + ((x) << STM32_UCPD_CFGR1_RXORDSETEN_SHIFT) +#define STM32_UCPD_CFGR1_TXDMAEN BIT(29) +#define STM32_UCPD_CFGR1_RXDMAEN BIT(30) +#define STM32_UCPD_CFGR1_UCPDEN BIT(31) /* --- UCPD CFGR2 Bit Definitions --- */ -#define STM32_UCPD_CFGR2_RXFILTDIS BIT(0) -#define STM32_UCPD_CFGR2_RXFILT2N3 BIT(1) -#define STM32_UCPD_CFGR2_FORCECLK BIT(2) -#define STM32_UCPD_CFGR2_WUPEN BIT(3) +#define STM32_UCPD_CFGR2_RXFILTDIS BIT(0) +#define STM32_UCPD_CFGR2_RXFILT2N3 BIT(1) +#define STM32_UCPD_CFGR2_FORCECLK BIT(2) +#define STM32_UCPD_CFGR2_WUPEN BIT(3) /* --- UCPD CR Bit Definitions --- */ -#define STM32_UCPD_CR_TXMODE_SHIFT 0 -#define STM32_UCPD_CR_TXMODE_MASK ((0x3) << \ - (STM32_UCPD_CR_TXMODE_SHIFT)) -#define STM32_UCPD_CR_TXMODE_VAL(x) ((x) << STM32_UCPD_CR_TXMODE_SHIFT) -#define STM32_UCPD_CR_TXSEND BIT(2) -#define STM32_UCPD_CR_TXHRST BIT(3) -#define STM32_UCPD_CR_RXMODE BIT(4) -#define STM32_UCPD_CR_PHYRXEN BIT(5) -#define STM32_UCPD_CR_PHYCCSEL BIT(6) -#define STM32_UCPD_CR_ANASUBMODE_SHIFT 7 -#define STM32_UCPD_CR_ANASUBMODE_MASK ((0x3) << \ - (STM32_UCPD_CR_ANASUBMODE_SHIFT)) -#define STM32_UCPD_CR_ANASUBMODE_VAL(x) ((x) << \ - STM32_UCPD_CR_ANASUBMODE_SHIFT) -#define STM32_UCPD_CR_ANAMODE BIT(9) -#define STM32_UCPD_CR_CCENABLE_SHIFT 10 -#define STM32_UCPD_CR_CCENABLE_MASK ((0x3) << \ - (STM32_UCPD_CR_CCENABLE_SHIFT)) -#define STM32_UCPD_CR_CCENABLE_VAL(x) ((x) << \ - STM32_UCPD_CR_CCENABLE_SHIFT) -#define STM32_UCPD_CR_FRSRXEN BIT(16) -#define STM32_UCPD_CR_FRSTX BIT(17) -#define STM32_UCPD_CR_RDCH BIT(18) -#define STM32_UCPD_CR_CC1TCDIS BIT(20) -#define STM32_UCPD_CR_CC2TCDIS BIT(21) +#define STM32_UCPD_CR_TXMODE_SHIFT 0 +#define STM32_UCPD_CR_TXMODE_MASK ((0x3) << (STM32_UCPD_CR_TXMODE_SHIFT)) +#define STM32_UCPD_CR_TXMODE_VAL(x) ((x) << STM32_UCPD_CR_TXMODE_SHIFT) +#define STM32_UCPD_CR_TXSEND BIT(2) +#define STM32_UCPD_CR_TXHRST BIT(3) +#define STM32_UCPD_CR_RXMODE BIT(4) +#define STM32_UCPD_CR_PHYRXEN BIT(5) +#define STM32_UCPD_CR_PHYCCSEL BIT(6) +#define STM32_UCPD_CR_ANASUBMODE_SHIFT 7 +#define STM32_UCPD_CR_ANASUBMODE_MASK \ + ((0x3) << (STM32_UCPD_CR_ANASUBMODE_SHIFT)) +#define STM32_UCPD_CR_ANASUBMODE_VAL(x) ((x) << STM32_UCPD_CR_ANASUBMODE_SHIFT) +#define STM32_UCPD_CR_ANAMODE BIT(9) +#define STM32_UCPD_CR_CCENABLE_SHIFT 10 +#define STM32_UCPD_CR_CCENABLE_MASK ((0x3) << (STM32_UCPD_CR_CCENABLE_SHIFT)) +#define STM32_UCPD_CR_CCENABLE_VAL(x) ((x) << STM32_UCPD_CR_CCENABLE_SHIFT) +#define STM32_UCPD_CR_FRSRXEN BIT(16) +#define STM32_UCPD_CR_FRSTX BIT(17) +#define STM32_UCPD_CR_RDCH BIT(18) +#define STM32_UCPD_CR_CC1TCDIS BIT(20) +#define STM32_UCPD_CR_CC2TCDIS BIT(21) + +/* TX mode message types */ +#define STM32_UCPD_CR_TXMODE_DEF 0 +#define STM32_UCPD_CR_TXMODE_CBL_RST 1 +#define STM32_UCPD_CR_TXMODE_BIST 2 /* --- UCPD IMR Bit Definitions --- */ -#define STM32_UCPD_IMR_TXISIE BIT(0) -#define STM32_UCPD_IMR_TXMSGDISCIE BIT(1) -#define STM32_UCPD_IMR_TXMSGSENTIE BIT(2) -#define STM32_UCPD_IMR_TXMSGABTIE BIT(3) -#define STM32_UCPD_IMR_HRSTDISCIE BIT(4) -#define STM32_UCPD_IMR_HRSTSENTIE BIT(5) -#define STM32_UCPD_IMR_TXUNDIE BIT(6) -#define STM32_UCPD_IMR_RXNEIE BIT(8) -#define STM32_UCPD_IMR_RXORDDETIE BIT(9) -#define STM32_UCPD_IMR_RXHRSTDETIE BIT(10) -#define STM32_UCPD_IMR_RXOVRIE BIT(11) -#define STM32_UCPD_IMR_RXMSGENDIE BIT(12) -#define STM32_UCPD_IMR_TYPECEVT1IE BIT(14) -#define STM32_UCPD_IMR_TYPECEVT2IE BIT(15) -#define STM32_UCPD_IMR_FRSEVTIE BIT(20) +#define STM32_UCPD_IMR_TXISIE BIT(0) +#define STM32_UCPD_IMR_TXMSGDISCIE BIT(1) +#define STM32_UCPD_IMR_TXMSGSENTIE BIT(2) +#define STM32_UCPD_IMR_TXMSGABTIE BIT(3) +#define STM32_UCPD_IMR_HRSTDISCIE BIT(4) +#define STM32_UCPD_IMR_HRSTSENTIE BIT(5) +#define STM32_UCPD_IMR_TXUNDIE BIT(6) +#define STM32_UCPD_IMR_RXNEIE BIT(8) +#define STM32_UCPD_IMR_RXORDDETIE BIT(9) +#define STM32_UCPD_IMR_RXHRSTDETIE BIT(10) +#define STM32_UCPD_IMR_RXOVRIE BIT(11) +#define STM32_UCPD_IMR_RXMSGENDIE BIT(12) +#define STM32_UCPD_IMR_TYPECEVT1IE BIT(14) +#define STM32_UCPD_IMR_TYPECEVT2IE BIT(15) +#define STM32_UCPD_IMR_FRSEVTIE BIT(20) /* --- UCPD SR Bit Definitions --- */ -#define STM32_UCPD_SR_TXIS BIT(0) -#define STM32_UCPD_SR_TXMSGDISC BIT(1) -#define STM32_UCPD_SR_TXMSGSENT BIT(2) -#define STM32_UCPD_SR_TXMSGABT BIT(3) -#define STM32_UCPD_SR_HRSTDISC BIT(4) -#define STM32_UCPD_SR_HRSTSENT BIT(5) -#define STM32_UCPD_SR_TXUND BIT(6) -#define STM32_UCPD_SR_RXNE BIT(8) -#define STM32_UCPD_SR_RXORDDET BIT(9) -#define STM32_UCPD_SR_RXHRSTDET BIT(10) -#define STM32_UCPD_SR_RXOVR BIT(11) -#define STM32_UCPD_SR_RXMSGEND BIT(12) -#define STM32_UCPD_SR_RXERR BIT(13) -#define STM32_UCPD_SR_TYPECEVT1 BIT(14) -#define STM32_UCPD_SR_TYPECEVT2 BIT(15) -#define STM32_UCPD_SR_VSTATE_CC1_SHIFT 16 -#define STM32_UCPD_SR_VSTATE_CC1_MASK ((0x3) << \ - (STM32_UCPD_SR_VSTATE_CC1_SHIFT)) -#define STM32_UCPD_SR_VSTATE_CC1_VAL(x) ((x) << \ - STM32_UCPD_SR_VSTATE_CC1_SHIFT) -#define STM32_UCPD_SR_VSTATE_CC2_SHIFT 18 -#define STM32_UCPD_SR_VSTATE_CC2_MASK ((0x3) << \ - (STM32_UCPD_SR_VSTATE_CC2_SHIFT)) -#define STM32_UCPD_SR_VSTATE_CC2_VAL(x) ((x) << \ - STM32_UCPD_SR_VSTATE_CC2_SHIFT) -#define STM32_UCPD_SR_FRSEVT BIT(20) - -#define STM32_UCPD_SR_VSTATE_OPEN 3 -#define STM32_UCPD_SR_VSTATE_RA 0 +#define STM32_UCPD_SR_TXIS BIT(0) +#define STM32_UCPD_SR_TXMSGDISC BIT(1) +#define STM32_UCPD_SR_TXMSGSENT BIT(2) +#define STM32_UCPD_SR_TXMSGABT BIT(3) +#define STM32_UCPD_SR_HRSTDISC BIT(4) +#define STM32_UCPD_SR_HRSTSENT BIT(5) +#define STM32_UCPD_SR_TXUND BIT(6) +#define STM32_UCPD_SR_RXNE BIT(8) +#define STM32_UCPD_SR_RXORDDET BIT(9) +#define STM32_UCPD_SR_RXHRSTDET BIT(10) +#define STM32_UCPD_SR_RXOVR BIT(11) +#define STM32_UCPD_SR_RXMSGEND BIT(12) +#define STM32_UCPD_SR_RXERR BIT(13) +#define STM32_UCPD_SR_TYPECEVT1 BIT(14) +#define STM32_UCPD_SR_TYPECEVT2 BIT(15) +#define STM32_UCPD_SR_VSTATE_CC1_SHIFT 16 +#define STM32_UCPD_SR_VSTATE_CC1_MASK \ + ((0x3) << (STM32_UCPD_SR_VSTATE_CC1_SHIFT)) +#define STM32_UCPD_SR_VSTATE_CC1_VAL(x) ((x) << STM32_UCPD_SR_VSTATE_CC1_SHIFT) +#define STM32_UCPD_SR_VSTATE_CC2_SHIFT 18 +#define STM32_UCPD_SR_VSTATE_CC2_MASK \ + ((0x3) << (STM32_UCPD_SR_VSTATE_CC2_SHIFT)) +#define STM32_UCPD_SR_VSTATE_CC2_VAL(x) ((x) << STM32_UCPD_SR_VSTATE_CC2_SHIFT) +#define STM32_UCPD_SR_FRSEVT BIT(20) + +#define STM32_UCPD_SR_VSTATE_OPEN 3 +#define STM32_UCPD_SR_VSTATE_RA 0 /* --- UCPD ICR Bit Definitions --- */ -#define STM32_UCPD_ICR_TXMSGDISCCF BIT(1) -#define STM32_UCPD_ICR_TXMSGSENTCF BIT(2) -#define STM32_UCPD_ICR_TXMSGABTCF BIT(3) -#define STM32_UCPD_ICR_HRSTDISCCF BIT(4) -#define STM32_UCPD_ICR_HRSTSENTCF BIT(5) -#define STM32_UCPD_ICR_TXUNDCF BIT(6) -#define STM32_UCPD_ICR_RXORDDETCF BIT(9) -#define STM32_UCPD_ICR_RXHRSTDETCF BIT(10) -#define STM32_UCPD_ICR_RXOVRCF BIT(11) -#define STM32_UCPD_ICR_RXMSGENDCF BIT(12) -#define STM32_UCPD_ICR_TYPECEVT1CF BIT(14) -#define STM32_UCPD_ICR_TYPECEVT2CF BIT(15) -#define STM32_UCPD_ICR_FRSEVTCF BIT(20) - +#define STM32_UCPD_ICR_TXMSGDISCCF BIT(1) +#define STM32_UCPD_ICR_TXMSGSENTCF BIT(2) +#define STM32_UCPD_ICR_TXMSGABTCF BIT(3) +#define STM32_UCPD_ICR_HRSTDISCCF BIT(4) +#define STM32_UCPD_ICR_HRSTSENTCF BIT(5) +#define STM32_UCPD_ICR_TXUNDCF BIT(6) +#define STM32_UCPD_ICR_RXORDDETCF BIT(9) +#define STM32_UCPD_ICR_RXHRSTDETCF BIT(10) +#define STM32_UCPD_ICR_RXOVRCF BIT(11) +#define STM32_UCPD_ICR_RXMSGENDCF BIT(12) +#define STM32_UCPD_ICR_TYPECEVT1CF BIT(14) +#define STM32_UCPD_ICR_TYPECEVT2CF BIT(15) +#define STM32_UCPD_ICR_FRSEVTCF BIT(20) /* --- UCPD TX_ORDSETR Bit Definitions --- */ -#define STM32_UCPD_TX_ORDSETR_SHIFT 0 -#define STM32_UCPD_TX_ORDSETR_MASK ((0xfffff) << \ - (STM32_UCPD_TX_ORDSETR_SHIFT)) -#define STM32_UCPD_TX_ORDSETR_VAL(x) ((x) << STM32_UCPD_TX_ORDSETR_SHIFT) +#define STM32_UCPD_TX_ORDSETR_SHIFT 0 +#define STM32_UCPD_TX_ORDSETR_MASK ((0xfffff) << (STM32_UCPD_TX_ORDSETR_SHIFT)) +#define STM32_UCPD_TX_ORDSETR_VAL(x) ((x) << STM32_UCPD_TX_ORDSETR_SHIFT) /* --- UCPD TX_PAYSZR Bit Definitions --- */ -#define STM32_UCPD_TX_PAYSZR_SHIFT 0 -#define STM32_UCPD_TX_PAYSZR_MASK ((0x3ff) << \ - (STM32_UCPD_TX_PAYSZR_SHIFT)) -#define STM32_UCPD_TX_PAYSZR_VAL(x) ((x) << STM32_UCPD_TX_PAYSZR_SHIFT) +#define STM32_UCPD_TX_PAYSZR_SHIFT 0 +#define STM32_UCPD_TX_PAYSZR_MASK ((0x3ff) << (STM32_UCPD_TX_PAYSZR_SHIFT)) +#define STM32_UCPD_TX_PAYSZR_VAL(x) ((x) << STM32_UCPD_TX_PAYSZR_SHIFT) /* --- UCPD TXDR Bit Definitions --- */ -#define STM32_UCPD_TXDR_SHIFT 0 -#define STM32_UCPD_TXDR_MASK ((0xff) << \ - (STM32_UCPD_TXDR_SHIFT)) -#define STM32_UCPD_TXDR_VAL(x) ((x) << STM32_UCPD_TXDR_SHIFT) +#define STM32_UCPD_TXDR_SHIFT 0 +#define STM32_UCPD_TXDR_MASK ((0xff) << (STM32_UCPD_TXDR_SHIFT)) +#define STM32_UCPD_TXDR_VAL(x) ((x) << STM32_UCPD_TXDR_SHIFT) /* --- UCPD RX_ORDSETR Bit Definitions --- */ -#define STM32_UCPD_RXORDSETR_SHIFT 0 -#define STM32_UCPD_RXORDSETR_MASK ((0x7) << \ - (STM32_UCPD_RXORDSETR_SHIFT)) -#define STM32_UCPD_RXORDSETR_VAL(x) ((x) << STM32_UCPD_RXORDSETR_SHIFT) -#define STM32_UCPD_RXSOP3OF4 BIT(3) -#define STM32_UCPD_RXSOPKINVALID_SHIFT 4 -#define STM32_UCPD_RXSOPKINVALID_MASK ((0x7) << \ - (STM32_UCPD_RXSOPKINVALID_SHIFT)) -#define STM32_UCPD_RXSOPKINVALID_VAL(x) ((x) << \ - STM32_UCPD_RXSOPKINVALID_SHIFT) +#define STM32_UCPD_RXORDSETR_SHIFT 0 +#define STM32_UCPD_RXORDSETR_MASK ((0x7) << (STM32_UCPD_RXORDSETR_SHIFT)) +#define STM32_UCPD_RXORDSETR_VAL(x) ((x) << STM32_UCPD_RXORDSETR_SHIFT) +#define STM32_UCPD_RXSOP3OF4 BIT(3) +#define STM32_UCPD_RXSOPKINVALID_SHIFT 4 +#define STM32_UCPD_RXSOPKINVALID_MASK \ + ((0x7) << (STM32_UCPD_RXSOPKINVALID_SHIFT)) +#define STM32_UCPD_RXSOPKINVALID_VAL(x) ((x) << STM32_UCPD_RXSOPKINVALID_SHIFT) /* --- UCPD RX_PAYSZR Bit Definitions --- */ -#define STM32_UCPD_RX_PAYSZR_SHIFT 0 -#define STM32_UCPD_RX_PAYSZR_MASK ((0x3ff) << \ - (STM32_UCPD_RX_PAYSZR_SHIFT)) -#define STM32_UCPD_RX_PAYSZR_VAL(x) ((x) << STM32_UCPD_RX_PAYSZR_SHIFT) +#define STM32_UCPD_RX_PAYSZR_SHIFT 0 +#define STM32_UCPD_RX_PAYSZR_MASK ((0x3ff) << (STM32_UCPD_RX_PAYSZR_SHIFT)) +#define STM32_UCPD_RX_PAYSZR_VAL(x) ((x) << STM32_UCPD_RX_PAYSZR_SHIFT) /* --- UCPD TXDR Bit Definitions --- */ -#define STM32_UCPD_RXDR_SHIFT 0 -#define STM32_UCPD_RXDR_MASK ((0xff) << \ - (STM32_UCPD_RXDR_SHIFT)) -#define STM32_UCPD_RXDR_VAL(x) ((x) << STM32_UCPD_RXDR_SHIFT) - +#define STM32_UCPD_RXDR_SHIFT 0 +#define STM32_UCPD_RXDR_MASK ((0xff) << (STM32_UCPD_RXDR_SHIFT)) +#define STM32_UCPD_RXDR_VAL(x) ((x) << STM32_UCPD_RXDR_SHIFT) /* --- USART --- */ -#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) -#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) -#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) -#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) -#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) -#define STM32_USART_SR(base) STM32_USART_REG(base, 0x1C) -#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) -#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) +#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) +#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) +#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) +#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) +#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) +#define STM32_USART_SR(base) STM32_USART_REG(base, 0x1C) +#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) +#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) /* --- USART bit definitions -- */ -#define STM32_USART_SR_ORE BIT(3) -#define STM32_USART_SR_RXNE BIT(5) -#define STM32_USART_SR_TC BIT(6) -#define STM32_USART_SR_TXE BIT(7) - -#define STM32_USART_CR1_UE BIT(0) -#define STM32_USART_CR1_RE BIT(2) -#define STM32_USART_CR1_TE BIT(3) -#define STM32_USART_CR1_RXNEIE BIT(5) -#define STM32_USART_CR1_TCIE BIT(6) -#define STM32_USART_CR1_TXEIE BIT(7) -#define STM32_USART_CR1_PS BIT(9) -#define STM32_USART_CR1_PCE BIT(10) -#define STM32_USART_CR1_M BIT(12) -#define STM32_USART_CR1_OVER8 BIT(15) - -#define STM32_USART_CR3_EIE BIT(0) -#define STM32_USART_CR3_DMAR BIT(6) -#define STM32_USART_CR3_DMAT BIT(7) -#define STM32_USART_CR3_ONEBIT BIT(11) - +#define STM32_USART_SR_ORE BIT(3) +#define STM32_USART_SR_RXNE BIT(5) +#define STM32_USART_SR_TC BIT(6) +#define STM32_USART_SR_TXE BIT(7) + +#define STM32_USART_CR1_UE BIT(0) +#define STM32_USART_CR1_RE BIT(2) +#define STM32_USART_CR1_TE BIT(3) +#define STM32_USART_CR1_RXNEIE BIT(5) +#define STM32_USART_CR1_TCIE BIT(6) +#define STM32_USART_CR1_TXEIE BIT(7) +#define STM32_USART_CR1_PS BIT(9) +#define STM32_USART_CR1_PCE BIT(10) +#define STM32_USART_CR1_M BIT(12) +#define STM32_USART_CR1_OVER8 BIT(15) + +#define STM32_USART_CR3_EIE BIT(0) +#define STM32_USART_CR3_DMAR BIT(6) +#define STM32_USART_CR3_DMAT BIT(7) +#define STM32_USART_CR3_ONEBIT BIT(11) /* --- GPIO --- */ -#define STM32_GPIO_MODER(b) REG32((b) + 0x00) -#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) -#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) -#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) -#define STM32_GPIO_IDR(b) REG16((b) + 0x10) -#define STM32_GPIO_ODR(b) REG16((b) + 0x14) -#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) -#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) -#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) -#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) - -#define GPIO_ALT_SYS 0x0 -#define GPIO_ALT_TIM2 0x1 -#define GPIO_ALT_I2C3 0x2 -#define GPIO_ALT_TIM9_11 0x3 -#define GPIO_ALT_I2C 0x4 -#define GPIO_ALT_SPI 0x5 -#define GPIO_ALT_SPI3 0x6 -#define GPIO_ALT_USART 0x7 -#define GPIO_ALT_I2C_23 0x9 -#define GPIO_ALT_USB 0xA -#define GPIO_ALT_LCD 0xB -#define GPIO_ALT_LPUART 0xC -#define GPIO_ALT_SAI1 0xD -#define GPIO_ALT_RI 0xE -#define GPIO_ALT_EVENTOUT 0xF +#define STM32_GPIO_MODER(b) REG32((b) + 0x00) +#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) +#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) +#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) +#define STM32_GPIO_IDR(b) REG16((b) + 0x10) +#define STM32_GPIO_ODR(b) REG16((b) + 0x14) +#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) +#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) +#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) +#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) + +#define GPIO_ALT_SYS 0x0 +#define GPIO_ALT_TIM2 0x1 +#define GPIO_ALT_I2C3 0x2 +#define GPIO_ALT_TIM9_11 0x3 +#define GPIO_ALT_I2C 0x4 +#define GPIO_ALT_SPI 0x5 +#define GPIO_ALT_SPI3 0x6 +#define GPIO_ALT_USART 0x7 +#define GPIO_ALT_I2C_23 0x9 +#define GPIO_ALT_USB 0xA +#define GPIO_ALT_LCD 0xB +#define GPIO_ALT_LPUART 0xC +#define GPIO_ALT_SAI1 0xD +#define GPIO_ALT_RI 0xE +#define GPIO_ALT_EVENTOUT 0xF /* --- I2C --- */ #define stm32g4_i2c_reg(base, offset) ((uint16_t *)((base) + (offset))) -#define STM32_I2C_CR1(base) REG32(stm32g4_i2c_reg(base, 0x00)) -#define STM32_I2C_CR2(base) REG32(stm32g4_i2c_reg(base, 0x04)) -#define STM32_I2C_OAR1(base) REG16(stm32g4_i2c_reg(base, 0x08)) -#define STM32_I2C_OAR2(base) REG16(stm32g4_i2c_reg(base, 0x0C)) -#define STM32_I2C_TIMINGR(base) REG32(stm32g4_i2c_reg(base, 0x10)) -#define STM32_I2C_TIMEOUTR(base) REG32(stm32g4_i2c_reg(base, 0x14)) -#define STM32_I2C_ISR(base) REG32(stm32g4_i2c_reg(base, 0x18)) -#define STM32_I2C_ICR(base) REG32(stm32g4_i2c_reg(base, 0x1C)) -#define STM32_I2C_PECR(base) REG32(stm32g4_i2c_reg(base, 0x20)) -#define STM32_I2C_RXDR(base) REG32(stm32g4_i2c_reg(base, 0x24)) -#define STM32_I2C_TXDR(base) REG32(stm32g4_i2c_reg(base, 0x28)) +#define STM32_I2C_CR1(base) REG32(stm32g4_i2c_reg(base, 0x00)) +#define STM32_I2C_CR2(base) REG32(stm32g4_i2c_reg(base, 0x04)) +#define STM32_I2C_OAR1(base) REG16(stm32g4_i2c_reg(base, 0x08)) +#define STM32_I2C_OAR2(base) REG16(stm32g4_i2c_reg(base, 0x0C)) +#define STM32_I2C_TIMINGR(base) REG32(stm32g4_i2c_reg(base, 0x10)) +#define STM32_I2C_TIMEOUTR(base) REG32(stm32g4_i2c_reg(base, 0x14)) +#define STM32_I2C_ISR(base) REG32(stm32g4_i2c_reg(base, 0x18)) +#define STM32_I2C_ICR(base) REG32(stm32g4_i2c_reg(base, 0x1C)) +#define STM32_I2C_PECR(base) REG32(stm32g4_i2c_reg(base, 0x20)) +#define STM32_I2C_RXDR(base) REG32(stm32g4_i2c_reg(base, 0x24)) +#define STM32_I2C_TXDR(base) REG32(stm32g4_i2c_reg(base, 0x28)) /* --- I2C CR1 Bit Definitions --- */ -#define STM32_I2C_CR1_PE BIT(0) -#define STM32_I2C_CR1_TXIE BIT(1) -#define STM32_I2C_CR1_RXIE BIT(2) -#define STM32_I2C_CR1_ADDRIE BIT(3) -#define STM32_I2C_CR1_NACKIE BIT(4) -#define STM32_I2C_CR1_STOPIE BIT(5) -#define STM32_I2C_CR1_ERRIE BIT(7) -#define STM32_I2C_CR1_WUPEN BIT(18) +#define STM32_I2C_CR1_PE BIT(0) +#define STM32_I2C_CR1_TXIE BIT(1) +#define STM32_I2C_CR1_RXIE BIT(2) +#define STM32_I2C_CR1_ADDRIE BIT(3) +#define STM32_I2C_CR1_NACKIE BIT(4) +#define STM32_I2C_CR1_STOPIE BIT(5) +#define STM32_I2C_CR1_ERRIE BIT(7) +#define STM32_I2C_CR1_WUPEN BIT(18) /* --- I2C CR2 Bit Definitions --- */ -#define STM32_I2C_CR2_RD_WRN BIT(10) -#define STM32_I2C_CR2_START BIT(13) -#define STM32_I2C_CR2_STOP BIT(14) -#define STM32_I2C_CR2_NACK BIT(15) -#define STM32_I2C_CR2_RELOAD BIT(24) -#define STM32_I2C_CR2_AUTOEND BIT(25) +#define STM32_I2C_CR2_RD_WRN BIT(10) +#define STM32_I2C_CR2_START BIT(13) +#define STM32_I2C_CR2_STOP BIT(14) +#define STM32_I2C_CR2_NACK BIT(15) +#define STM32_I2C_CR2_RELOAD BIT(24) +#define STM32_I2C_CR2_AUTOEND BIT(25) /* --- I2C ISR Bit Definitions --- */ -#define STM32_I2C_ISR_TXE BIT(0) -#define STM32_I2C_ISR_TXIS BIT(1) -#define STM32_I2C_ISR_RXNE BIT(2) -#define STM32_I2C_ISR_ADDR BIT(3) -#define STM32_I2C_ISR_NACK BIT(4) -#define STM32_I2C_ISR_STOP BIT(5) -#define STM32_I2C_ISR_TC BIT(6) -#define STM32_I2C_ISR_TCR BIT(7) -#define STM32_I2C_ISR_BERR BIT(8) -#define STM32_I2C_ISR_ARLO BIT(9) -#define STM32_I2C_ISR_OVR BIT(10) -#define STM32_I2C_ISR_PECERR BIT(11) -#define STM32_I2C_ISR_TIMEOUT BIT(12) -#define STM32_I2C_ISR_ALERT BIT(13) -#define STM32_I2C_ISR_BUSY BIT(15) -#define STM32_I2C_ISR_DIR BIT(16) +#define STM32_I2C_ISR_TXE BIT(0) +#define STM32_I2C_ISR_TXIS BIT(1) +#define STM32_I2C_ISR_RXNE BIT(2) +#define STM32_I2C_ISR_ADDR BIT(3) +#define STM32_I2C_ISR_NACK BIT(4) +#define STM32_I2C_ISR_STOP BIT(5) +#define STM32_I2C_ISR_TC BIT(6) +#define STM32_I2C_ISR_TCR BIT(7) +#define STM32_I2C_ISR_BERR BIT(8) +#define STM32_I2C_ISR_ARLO BIT(9) +#define STM32_I2C_ISR_OVR BIT(10) +#define STM32_I2C_ISR_PECERR BIT(11) +#define STM32_I2C_ISR_TIMEOUT BIT(12) +#define STM32_I2C_ISR_ALERT BIT(13) +#define STM32_I2C_ISR_BUSY BIT(15) +#define STM32_I2C_ISR_DIR BIT(16) /* --- I2C ICR Bit Definitions --- */ -#define STM32_I2C_ICR_ADDRCF BIT(3) -#define STM32_I2C_ICR_NACKCF BIT(4) -#define STM32_I2C_ICR_STOPCF BIT(5) -#define STM32_I2C_ICR_BERRCF BIT(8) -#define STM32_I2C_ICR_ARLOCF BIT(9) -#define STM32_I2C_ICR_OVRCF BIT(10) -#define STM32_I2C_ICR_TIMEOUTCF BIT(12) -#define STM32_I2C_ICR_ALL 0x3F38 +#define STM32_I2C_ICR_ADDRCF BIT(3) +#define STM32_I2C_ICR_NACKCF BIT(4) +#define STM32_I2C_ICR_STOPCF BIT(5) +#define STM32_I2C_ICR_BERRCF BIT(8) +#define STM32_I2C_ICR_ARLOCF BIT(9) +#define STM32_I2C_ICR_OVRCF BIT(10) +#define STM32_I2C_ICR_TIMEOUTCF BIT(12) +#define STM32_I2C_ICR_ALL 0x3F38 /* --- I2C TIMINGR bit Definitions --- */ #define STM32_I2C_TIMINGR_SCLL_OFF 0 @@ -572,269 +559,271 @@ /* --- Power / Reset / Clocks --- */ -#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) -#define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x04) -#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) -#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x0C) -#define STM32_RCC_CIER REG32(STM32_RCC_BASE + 0x18) -#define STM32_RCC_CIFR REG32(STM32_RCC_BASE + 0x1C) -#define STM32_RCC_CICR REG32(STM32_RCC_BASE + 0x20) -#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x28) -#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x2C) -#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x30) -#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x38) -#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x40) -#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x48) -#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x4C) -#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x50) -#define STM32_RCC_APB1ENR1 REG32(STM32_RCC_BASE + 0x58) -#define STM32_RCC_APB1ENR2 REG32(STM32_RCC_BASE + 0x5C) -#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x60) -#define STM32_RCC_AHB1SMENR REG32(STM32_RCC_BASE + 0x68) -#define STM32_RCC_AHB2SMENR REG32(STM32_RCC_BASE + 0x6C) -#define STM32_RCC_AHB3SMENR REG32(STM32_RCC_BASE + 0x70) -#define STM32_RCC_APB1SMENR1 REG32(STM32_RCC_BASE + 0x78) -#define STM32_RCC_APB1SMENR2 REG32(STM32_RCC_BASE + 0x7C) -#define STM32_RCC_APB2SMENR REG32(STM32_RCC_BASE + 0x80) -#define STM32_RCC_CCIPR REG32(STM32_RCC_BASE + 0x88) -#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x90) -#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x94) -#define STM32_RCC_CRRCR REG32(STM32_RCC_BASE + 0x98) -#define STM32_RCC_CCIPR2 REG32(STM32_RCC_BASE + 0x9C) +#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) +#define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x04) +#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) +#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x0C) +#define STM32_RCC_CIER REG32(STM32_RCC_BASE + 0x18) +#define STM32_RCC_CIFR REG32(STM32_RCC_BASE + 0x1C) +#define STM32_RCC_CICR REG32(STM32_RCC_BASE + 0x20) +#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x28) +#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x2C) +#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x30) +#define STM32_RCC_APB1RSTR1 REG32(STM32_RCC_BASE + 0x38) +#define STM32_RCC_APB1RSTR2 REG32(STM32_RCC_BASE + 0x3C) +#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x40) +#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x48) +#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x4C) +#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x50) +#define STM32_RCC_APB1ENR1 REG32(STM32_RCC_BASE + 0x58) +#define STM32_RCC_APB1ENR2 REG32(STM32_RCC_BASE + 0x5C) +#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x60) +#define STM32_RCC_AHB1SMENR REG32(STM32_RCC_BASE + 0x68) +#define STM32_RCC_AHB2SMENR REG32(STM32_RCC_BASE + 0x6C) +#define STM32_RCC_AHB3SMENR REG32(STM32_RCC_BASE + 0x70) +#define STM32_RCC_APB1SMENR1 REG32(STM32_RCC_BASE + 0x78) +#define STM32_RCC_APB1SMENR2 REG32(STM32_RCC_BASE + 0x7C) +#define STM32_RCC_APB2SMENR REG32(STM32_RCC_BASE + 0x80) +#define STM32_RCC_CCIPR REG32(STM32_RCC_BASE + 0x88) +#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x90) +#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x94) +#define STM32_RCC_CRRCR REG32(STM32_RCC_BASE + 0x98) +#define STM32_RCC_CCIPR2 REG32(STM32_RCC_BASE + 0x9C) #define STM32_RCC_APB1ENR STM32_RCC_APB1ENR1 #define STM32_RCC_AHBENR STM32_RCC_APB1ENR /* --- RCC CR Bit Definitions --- */ -#define STM32_RCC_CR_HSION BIT(8) -#define STM32_RCC_CR_HSIRDY BIT(10) -#define STM32_RCC_CR_HSEON BIT(16) -#define STM32_RCC_CR_HSERDY BIT(17) -#define STM32_RCC_CR_PLLON BIT(24) -#define STM32_RCC_CR_PLLRDY BIT(25) +#define STM32_RCC_CR_HSION BIT(8) +#define STM32_RCC_CR_HSIRDY BIT(10) +#define STM32_RCC_CR_HSEON BIT(16) +#define STM32_RCC_CR_HSERDY BIT(17) +#define STM32_RCC_CR_PLLON BIT(24) +#define STM32_RCC_CR_PLLRDY BIT(25) /* --- RCC PLLCFGR Bit Definitions --- */ -#define PLLCFGR_PLLSRC_OFF 0 -#define PLLCFGR_PLLSRC(val) (((val) & 0x3) << PLLCFGR_PLLSRC_OFF) -#define PLLCFGR_PLLSRC_HSI 2 -#define PLLCFGR_PLLSRC_HSE 3 +#define PLLCFGR_PLLSRC_OFF 0 +#define PLLCFGR_PLLSRC(val) (((val)&0x3) << PLLCFGR_PLLSRC_OFF) +#define PLLCFGR_PLLSRC_HSI 2 +#define PLLCFGR_PLLSRC_HSE 3 /* PLL Division factor */ -#define PLLCFGR_PLLM_OFF 4 -#define PLLCFGR_PLLM(val) (((val) & 0x1f) << PLLCFGR_PLLM_OFF) +#define PLLCFGR_PLLM_OFF 4 +#define PLLCFGR_PLLM(val) (((val)&0x1f) << PLLCFGR_PLLM_OFF) /* PLL Multiplication factor */ -#define PLLCFGR_PLLN_OFF 8 -#define PLLCFGR_PLLN(val) (((val) & 0x7f) << PLLCFGR_PLLN_OFF) -#define PLLCFGR_PLLQ_EN BIT(20) -#define PLLCFGR_PLLQ_OFF 21 -#define PLLCFGR_PLLQ(val) (((val) & 0x3) << PLLCFGR_PLLQ_OFF) +#define PLLCFGR_PLLN_OFF 8 +#define PLLCFGR_PLLN(val) (((val)&0x7f) << PLLCFGR_PLLN_OFF) +#define PLLCFGR_PLLQ_EN BIT(20) +#define PLLCFGR_PLLQ_OFF 21 +#define PLLCFGR_PLLQ(val) (((val)&0x3) << PLLCFGR_PLLQ_OFF) /* System and main CPU clock */ -#define PLLCFGR_PLLR_EN BIT(24) -#define PLLCFGR_PLLR_OFF 25 -#define PLLCFGR_PLLR(val) (((val) & 0x3) << PLLCFGR_PLLR_OFF) -#define PLLCFGR_PLLP_OFF 27 -#define PLLCFGR_PLLP(val) (((val) & 0x1f) << PLLCFGR_PLLP_OFF) +#define PLLCFGR_PLLR_EN BIT(24) +#define PLLCFGR_PLLR_OFF 25 +#define PLLCFGR_PLLR(val) (((val)&0x3) << PLLCFGR_PLLR_OFF) +#define PLLCFGR_PLLP_OFF 27 +#define PLLCFGR_PLLP(val) (((val)&0x1f) << PLLCFGR_PLLP_OFF) /* --- RCC CFGR Bit Definitions --- */ -#define STM32_RCC_CFGR_SW_HSI (1 << 0) -#define STM32_RCC_CFGR_SW_HSE (2 << 0) -#define STM32_RCC_CFGR_SW_PLL (3 << 0) -#define STM32_RCC_CFGR_SW_MASK (3 << 0) -#define STM32_RCC_CFGR_SWS_HSI (1 << 2) -#define STM32_RCC_CFGR_SWS_HSE (2 << 2) -#define STM32_RCC_CFGR_SWS_PLL (3 << 2) -#define STM32_RCC_CFGR_SWS_MASK (3 << 2) +#define STM32_RCC_CFGR_SW_HSI (1 << 0) +#define STM32_RCC_CFGR_SW_HSE (2 << 0) +#define STM32_RCC_CFGR_SW_PLL (3 << 0) +#define STM32_RCC_CFGR_SW_MASK (3 << 0) +#define STM32_RCC_CFGR_SWS_HSI (1 << 2) +#define STM32_RCC_CFGR_SWS_HSE (2 << 2) +#define STM32_RCC_CFGR_SWS_PLL (3 << 2) +#define STM32_RCC_CFGR_SWS_MASK (3 << 2) /* AHB Prescalar: */ -#define CFGR_HPRE_OFF 4 -#define CFGR_HPRE(val) (((val) & 0xf) << CFGR_HPRE_OFF) +#define CFGR_HPRE_OFF 4 +#define CFGR_HPRE(val) (((val)&0xf) << CFGR_HPRE_OFF) /* APB1 Low Speed Prescalar < 45MHz */ -#define CFGR_PPRE1_OFF 8 -#define CFGR_PPRE1(val) (((val) & 0x7) << CFGR_PPRE1_OFF) +#define CFGR_PPRE1_OFF 8 +#define CFGR_PPRE1(val) (((val)&0x7) << CFGR_PPRE1_OFF) /* APB2 High Speed Prescalar < 90MHz */ -#define CFGR_PPRE2_OFF 11 -#define CFGR_PPRE2(val) (((val) & 0x7) << CFGR_PPRE2_OFF) +#define CFGR_PPRE2_OFF 11 +#define CFGR_PPRE2(val) (((val)&0x7) << CFGR_PPRE2_OFF) /* RTC CLock: Must equal 1MHz */ -#define CFGR_RTCPRE_OFF 16 -#define CFGR_RTCPRE(val) (((val) & 0x1f) << CFGR_RTCPRE_OFF) +#define CFGR_RTCPRE_OFF 16 +#define CFGR_RTCPRE(val) (((val)&0x1f) << CFGR_RTCPRE_OFF) /* --- RCC AHB1ENR Bit Definitions --- */ -#define STM32_RCC_AHB1ENR_DMA1EN BIT(0) -#define STM32_RCC_AHB1ENR_DMA2EN BIT(1) -#define STM32_RCC_AHB1ENR_DMAMUXEN BIT(2) +#define STM32_RCC_AHB1ENR_DMA1EN BIT(0) +#define STM32_RCC_AHB1ENR_DMA2EN BIT(1) +#define STM32_RCC_AHB1ENR_DMAMUXEN BIT(2) /* --- RCC AHB2ENR Bit Definitions --- */ -#define STM32_RCC_AHB2ENR_GPIO_PORTA BIT(0) -#define STM32_RCC_AHB2ENR_GPIO_PORTB BIT(1) -#define STM32_RCC_AHB2ENR_GPIO_PORTC BIT(2) -#define STM32_RCC_AHB2ENR_GPIO_PORTD BIT(3) -#define STM32_RCC_AHB2ENR_GPIO_PORTE BIT(4) -#define STM32_RCC_AHB2ENR_GPIO_PORTF BIT(5) -#define STM32_RCC_AHB2ENR_GPIO_PORTG BIT(6) -#define STM32_RCC_AHB2ENR_GPIOMASK (0x7f << 0) -#define STM32_RCC_AHB2ENR_ADC12EN BIT(13) -#define STM32_RCC_APB2ENR_ADC345EN BIT(14) -#define STM32_RCC_AHB2ENR_RNGEN BIT(26) +#define STM32_RCC_AHB2ENR_GPIO_PORTA BIT(0) +#define STM32_RCC_AHB2ENR_GPIO_PORTB BIT(1) +#define STM32_RCC_AHB2ENR_GPIO_PORTC BIT(2) +#define STM32_RCC_AHB2ENR_GPIO_PORTD BIT(3) +#define STM32_RCC_AHB2ENR_GPIO_PORTE BIT(4) +#define STM32_RCC_AHB2ENR_GPIO_PORTF BIT(5) +#define STM32_RCC_AHB2ENR_GPIO_PORTG BIT(6) +#define STM32_RCC_AHB2ENR_GPIOMASK (0x7f << 0) +#define STM32_RCC_AHB2ENR_ADC12EN BIT(13) +#define STM32_RCC_APB2ENR_ADC345EN BIT(14) +#define STM32_RCC_AHB2ENR_RNGEN BIT(26) /* --- RCC APB1ENR1 Bit Definitions --- */ -#define STM32_RCC_APB1ENR1_TIM2EN BIT(0) -#define STM32_RCC_APB1ENR1_TIM3EN BIT(1) -#define STM32_RCC_APB1ENR1_TIM4EN BIT(2) -#define STM32_RCC_APB1ENR1_TIM5EN BIT(3) -#define STM32_RCC_APB1ENR1_TIM6EN BIT(4) -#define STM32_RCC_APB1ENR1_TIM7EN BIT(5) -#define STM32_RCC_APB1ENR1_WWDGEN BIT(11) -#define STM32_RCC_APB1ENR1_USART2 BIT(17) -#define STM32_RCC_APB1ENR1_USART3 BIT(18) -#define STM32_RCC_APB1ENR1_UART4 BIT(19) -#define STM32_RCC_APB1ENR1_UART5 BIT(20) -#define STM32_RCC_APB1ENR1_I2C1EN BIT(21) -#define STM32_RCC_APB1ENR1_I2C2EN BIT(22) -#define STM32_RCC_APB1ENR1_USBEN BIT(23) -#define STM32_RCC_APB1ENR1_PWREN BIT(28) -#define STM32_RCC_APB1ENR1_I2C3EN BIT(30) +#define STM32_RCC_APB1ENR1_TIM2EN BIT(0) +#define STM32_RCC_APB1ENR1_TIM3EN BIT(1) +#define STM32_RCC_APB1ENR1_TIM4EN BIT(2) +#define STM32_RCC_APB1ENR1_TIM5EN BIT(3) +#define STM32_RCC_APB1ENR1_TIM6EN BIT(4) +#define STM32_RCC_APB1ENR1_TIM7EN BIT(5) +#define STM32_RCC_APB1ENR1_WWDGEN BIT(11) +#define STM32_RCC_APB1ENR1_USART2 BIT(17) +#define STM32_RCC_APB1ENR1_USART3 BIT(18) +#define STM32_RCC_APB1ENR1_UART4 BIT(19) +#define STM32_RCC_APB1ENR1_UART5 BIT(20) +#define STM32_RCC_APB1ENR1_I2C1EN BIT(21) +#define STM32_RCC_APB1ENR1_I2C2EN BIT(22) +#define STM32_RCC_APB1ENR1_USBEN BIT(23) +#define STM32_RCC_APB1ENR1_PWREN BIT(28) +#define STM32_RCC_APB1ENR1_I2C3EN BIT(30) #define STM32_RCC_PWREN STM32_RCC_APB1ENR1_PWREN /* --- RCC APB1ENR2 Bit Definitions --- */ -#define STM32_RCC_APB1ENR2_LPUART1EN BIT(0) -#define STM32_RCC_APB1ENR2_I2C4EN BIT(1) -#define STM32_RCC_APB1ENR2_UPCD1EN BIT(8) +#define STM32_RCC_APB1ENR2_LPUART1EN BIT(0) +#define STM32_RCC_APB1ENR2_I2C4EN BIT(1) +#define STM32_RCC_APB1ENR2_UPCD1EN BIT(8) /* --- RCC APB2ENR Bit Definitions --- */ -#define STM32_RCC_APB2ENR_SYSCFGEN BIT(0) -#define STM32_RCC_APB2ENR_TIM1 BIT(11) -#define STM32_RCC_APB2ENR_SPI1EN BIT(12) -#define STM32_RCC_APB2ENR_TIM8 BIT(13) -#define STM32_RCC_APB2ENR_USART1 BIT(14) -#define STM32_RCC_APB2ENR_SPI4EN BIT(15) -#define STM32_RCC_APB2ENR_TIM15 BIT(16) -#define STM32_RCC_APB2ENR_TIM16 BIT(17) -#define STM32_RCC_APB2ENR_TIM17 BIT(18) -#define STM32_RCC_APB2ENR_TIM20 BIT(20) - -#define STM32_RCC_PB2_USART1 STM32_RCC_APB2ENR_USART1 +#define STM32_RCC_APB2ENR_SYSCFGEN BIT(0) +#define STM32_RCC_APB2ENR_TIM1 BIT(11) +#define STM32_RCC_APB2ENR_SPI1EN BIT(12) +#define STM32_RCC_APB2ENR_TIM8 BIT(13) +#define STM32_RCC_APB2ENR_USART1 BIT(14) +#define STM32_RCC_APB2ENR_SPI4EN BIT(15) +#define STM32_RCC_APB2ENR_TIM15 BIT(16) +#define STM32_RCC_APB2ENR_TIM16 BIT(17) +#define STM32_RCC_APB2ENR_TIM17 BIT(18) +#define STM32_RCC_APB2ENR_TIM20 BIT(20) + +#define STM32_RCC_PB2_USART1 STM32_RCC_APB2ENR_USART1 /* gpio.c needs STM32_RCC_SYSCFGEN */ #define STM32_RCC_SYSCFGEN STM32_RCC_APB2ENR_SYSCFGEN +/* --- RCC APB1RSTR1 Bit Definitions --- */ +#define STM32_RCC_APB1RSTR1_USB_RST BIT(23) +#define STM32_RCC_APB1RSTR STM32_RCC_APB1RSTR1 +#define STM32_RCC_PB1_USB STM32_RCC_APB1RSTR1_USB_RST + /* --- RCC CSR Bit Definitions --- */ -#define STM32_RCC_CSR_LSION BIT(0) -#define STM32_RCC_CSR_LSIRDY BIT(1) +#define STM32_RCC_CSR_LSION BIT(0) +#define STM32_RCC_CSR_LSIRDY BIT(1) /* --- RCC CCIPR Bit Definitions --- */ -#define STM32_RCC_CCIPR_UART_SYSCLK 0x1 -#define STM32_RCC_CCIPR_USART1SEL_MASK 0x3 -#define STM32_RCC_CCIPR_USART1SEL_SHIFT 0 -#define STM32_RCC_CCIPR_LPUART1SEL_MASK 0x3 +#define STM32_RCC_CCIPR_UART_SYSCLK 0x1 +#define STM32_RCC_CCIPR_USART1SEL_MASK 0x3 +#define STM32_RCC_CCIPR_USART1SEL_SHIFT 0 +#define STM32_RCC_CCIPR_LPUART1SEL_MASK 0x3 #define STM32_RCC_CCIPR_LPUART1SEL_SHIFT 10 -#define STM32_RCC_CCIPR_I2C1SEL_MASK 0x3 -#define STM32_RCC_CCIPR_I2C1SEL_SHIFT 12 -#define STM32_RCC_CCIPR_I2C2SEL_MASK 0x3 -#define STM32_RCC_CCIPR_I2C2SEL_SHIFT 14 -#define STM32_RCC_CCIPR_I2C3SEL_MASK 0x3 -#define STM32_RCC_CCIPR_I2C3SEL_SHIFT 16 +#define STM32_RCC_CCIPR_I2C1SEL_MASK 0x3 +#define STM32_RCC_CCIPR_I2C1SEL_SHIFT 12 +#define STM32_RCC_CCIPR_I2C2SEL_MASK 0x3 +#define STM32_RCC_CCIPR_I2C2SEL_SHIFT 14 +#define STM32_RCC_CCIPR_I2C3SEL_MASK 0x3 +#define STM32_RCC_CCIPR_I2C3SEL_SHIFT 16 -#define STM32_RCC_CCIPR2_I2C4SEL_MASK 0x3 +#define STM32_RCC_CCIPR2_I2C4SEL_MASK 0x3 -#define STM32_RCC_CCIPR_I2CNSEL_MASK 0x3 +#define STM32_RCC_CCIPR_I2CNSEL_MASK 0x3 #define STM32_RCC_CCIPR_I2CNSEL_SHIFT(n) (STM32_RCC_CCIPR_I2C1SEL_SHIFT + n * 2) -#define STM32_RCC_CCIPR_I2CNSEL_HSI 0x2 +#define STM32_RCC_CCIPR_I2CNSEL_HSI 0x2 /* --- RCC CRRCR Bit Definitions */ -#define RCC_CRRCR_HSI48O BIT(0) -#define RCC_CRRCR_HSIRDY BIT(1) +#define RCC_CRRCR_HSI48O BIT(0) +#define RCC_CRRCR_HSIRDY BIT(1) /* Reset causes definitions */ /* * Reset causes in RCC CSR register. The generic names are required */ #define STM32_RCC_RESET_CAUSE STM32_RCC_CSR -#define STM32_RCC_CSR_RMVF BIT(24) -#define STM32_RCC_CSR_BORRS BIT(25) -#define STM32_RCC_CSR_PIN BIT(26) -#define STM32_RCC_CSR_POR BIT(27) -#define STM32_RCC_CSR_SFT BIT(28) -#define STM32_RCC_CSR_IWDG BIT(29) -#define STM32_RCC_CSR_WWDG BIT(30) -#define STM32_RCC_CSR_LPWR BIT(31) - - -#define RESET_CAUSE_WDG (STM32_RCC_CSR_WWDG | \ - STM32_RCC_CSR_IWDG) -#define RESET_CAUSE_SFT STM32_RCC_CSR_SFT -#define RESET_CAUSE_POR STM32_RCC_CSR_POR -#define RESET_CAUSE_PIN STM32_RCC_CSR_PIN -#define RESET_CAUSE_RMVF STM32_RCC_CSR_RMVF -#define RESET_CAUSE_OTHER (STM32_RCC_CSR_LPWR | \ - STM32_RCC_CSR_BORRS) +#define STM32_RCC_CSR_RMVF BIT(24) +#define STM32_RCC_CSR_BORRS BIT(25) +#define STM32_RCC_CSR_PIN BIT(26) +#define STM32_RCC_CSR_POR BIT(27) +#define STM32_RCC_CSR_SFT BIT(28) +#define STM32_RCC_CSR_IWDG BIT(29) +#define STM32_RCC_CSR_WWDG BIT(30) +#define STM32_RCC_CSR_LPWR BIT(31) + +#define RESET_CAUSE_WDG (STM32_RCC_CSR_WWDG | STM32_RCC_CSR_IWDG) +#define RESET_CAUSE_SFT STM32_RCC_CSR_SFT +#define RESET_CAUSE_POR STM32_RCC_CSR_POR +#define RESET_CAUSE_PIN STM32_RCC_CSR_PIN +#define RESET_CAUSE_RMVF STM32_RCC_CSR_RMVF +#define RESET_CAUSE_OTHER (STM32_RCC_CSR_LPWR | STM32_RCC_CSR_BORRS) /* Power cause in PWR CSR register */ -#define STM32_PWR_CR1 REG32(STM32_PWR_BASE + 0x00) -#define STM32_PWR_CR2 REG32(STM32_PWR_BASE + 0x04) -#define STM32_PWR_CR3 REG32(STM32_PWR_BASE + 0x08) -#define STM32_PWR_CR4 REG32(STM32_PWR_BASE + 0x0C) -#define STM32_PWR_SR1 REG32(STM32_PWR_BASE + 0x10) -#define STM32_PWR_SR2 REG32(STM32_PWR_BASE + 0x14) -#define STM32_PWR_SCR REG32(STM32_PWR_BASE + 0x18) -#define STM32_PWR_SCR_CSBF BIT(8) -#define STM32_PWR_SR1_SBF BIT(8) +#define STM32_PWR_CR1 REG32(STM32_PWR_BASE + 0x00) +#define STM32_PWR_CR2 REG32(STM32_PWR_BASE + 0x04) +#define STM32_PWR_CR3 REG32(STM32_PWR_BASE + 0x08) +#define STM32_PWR_CR4 REG32(STM32_PWR_BASE + 0x0C) +#define STM32_PWR_SR1 REG32(STM32_PWR_BASE + 0x10) +#define STM32_PWR_SR2 REG32(STM32_PWR_BASE + 0x14) +#define STM32_PWR_SCR REG32(STM32_PWR_BASE + 0x18) +#define STM32_PWR_SCR_CSBF BIT(8) +#define STM32_PWR_SR1_SBF BIT(8) #define STM32_PWR_RESET_CAUSE STM32_PWR_SR1 -#define RESET_CAUSE_SBF STM32_PWR_SR1_SBF +#define RESET_CAUSE_SBF STM32_PWR_SR1_SBF #define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_SCR -#define RESET_CAUSE_SBF_CLR STM32_PWR_SCR_CSBF +#define RESET_CAUSE_SBF_CLR STM32_PWR_SCR_CSBF + +#define STM32_PWR_CR1_DBP BIT(8) -#define STM32_PWR_CR3_UCPD1_STDBY BIT(13) -#define STM32_PWR_CR3_UCPD1_DBDIS BIT(14) +#define STM32_PWR_CR3_UCPD1_STDBY BIT(13) +#define STM32_PWR_CR3_UCPD1_DBDIS BIT(14) /* --- System Config Registers --- */ -#define STM32_SYSCFG_MEMRMP REG32(STM32_SYSCFG_BASE + 0x00) -#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04) -#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) -#define STM32_SYSCFG_CMPCR REG32(STM32_SYSCFG_BASE + 0x20) -#define STM32_SYSCFG_CFGR REG32(STM32_SYSCFG_BASE + 0x2C) +#define STM32_SYSCFG_MEMRMP REG32(STM32_SYSCFG_BASE + 0x00) +#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04) +#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) +#define STM32_SYSCFG_CMPCR REG32(STM32_SYSCFG_BASE + 0x20) +#define STM32_SYSCFG_CFGR REG32(STM32_SYSCFG_BASE + 0x2C) /* --- Watchdogs --- */ /* --- Real-Time Clock --- */ -#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) -#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) -#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x08) -#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) -#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) -#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) -#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x18) - - -#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) -#define STM32_RTC_CALR REG32(STM32_RTC_BASE + 0x28) -#define STM32_RTC_SHIFTR REG32(STM32_RTC_BASE + 0x2C) -#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) -#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) -#define STM32_RTC_TSSSR REG32(STM32_RTC_BASE + 0x38) - -#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x40) -#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) -#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x48) -#define STM32_RTC_ALRMBSSR REG32(STM32_RTC_BASE + 0x44) +#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) +#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) +#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x08) +#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) +#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) +#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) +#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x18) + +#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) +#define STM32_RTC_CALR REG32(STM32_RTC_BASE + 0x28) +#define STM32_RTC_SHIFTR REG32(STM32_RTC_BASE + 0x2C) +#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) +#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) +#define STM32_RTC_TSSSR REG32(STM32_RTC_BASE + 0x38) + +#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x40) +#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) +#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x48) +#define STM32_RTC_ALRMBSSR REG32(STM32_RTC_BASE + 0x44) /* --- RTC CR Bit Definitions --- */ -#define STM32_RTC_CR_BYPSHAD BIT(5) -#define STM32_RTC_CR_ALRAE BIT(8) -#define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_CR_BYPSHAD BIT(5) +#define STM32_RTC_CR_ALRAE BIT(8) +#define STM32_RTC_CR_ALRAIE BIT(12) /* --- RTC ICSR Bit Definitions --- */ -#define STM32_RTC_ISR_ALRAWF BIT(0) -#define STM32_RTC_ISR_RSF BIT(5) -#define STM32_RTC_ISR_INITF BIT(6) -#define STM32_RTC_ISR_INIT BIT(7) -#define STM32_RTC_ISR_ALRAF BIT(8) +#define STM32_RTC_ISR_ALRAWF BIT(0) +#define STM32_RTC_ISR_RSF BIT(5) +#define STM32_RTC_ISR_INITF BIT(6) +#define STM32_RTC_ISR_INIT BIT(7) +#define STM32_RTC_ISR_ALRAF BIT(8) /* --- RTC PRER Bit Definitions --- */ -#define STM32_RTC_PRER_A_MASK (0x7f << 16) -#define STM32_RTC_PRER_S_MASK (0x7fff << 0) - +#define STM32_RTC_PRER_A_MASK (0x7f << 16) +#define STM32_RTC_PRER_S_MASK (0x7fff << 0) /* --- Tamper and Backup --- */ -#define STM32_TAMP_BKPxR(n) REG32(STM32_TAMP_BASE + 0x100 + 4 * (n)) -#define STM32_BKP_DATA(n) STM32_TAMP_BKPxR(n) -#define STM32_BKP_BYTES 128 - +#define STM32_TAMP_BKPxR(n) REG32(STM32_TAMP_BASE + 0x100 + 4 * (n)) +#define STM32_BKP_DATA(n) STM32_TAMP_BKPxR(n) +#define STM32_BKP_BYTES 64 /* --- SPI --- */ @@ -844,7 +833,7 @@ struct stm32_spi_regs { uint16_t _pad0; uint16_t cr2; uint16_t _pad1; - unsigned sr; + unsigned int sr; uint8_t dr; uint8_t _pad2; uint16_t _pad3; @@ -862,196 +851,222 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_SPI3_REGS ((stm32_spi_regs_t *)STM32_SPI3_BASE) #define STM32_SPI4_REGS ((stm32_spi_regs_t *)STM32_SPI4_BASE) -#define STM32_SPI_CR1_BIDIMODE BIT(15) -#define STM32_SPI_CR1_BIDIOE BIT(14) -#define STM32_SPI_CR1_CRCEN BIT(13) -#define STM32_SPI_CR1_SSM BIT(9) -#define STM32_SPI_CR1_SSI BIT(8) -#define STM32_SPI_CR1_LSBFIRST BIT(7) -#define STM32_SPI_CR1_SPE BIT(6) -#define STM32_SPI_CR1_BR_DIV64R (5 << 3) -#define STM32_SPI_CR1_BR_DIV4R BIT(3) -#define STM32_SPI_CR1_MSTR BIT(2) -#define STM32_SPI_CR1_CPOL BIT(1) -#define STM32_SPI_CR1_CPHA BIT(0) -#define STM32_SPI_CR2_FRXTH BIT(12) -#define STM32_SPI_CR2_DATASIZE(n) (((n) - 1) << 8) -#define STM32_SPI_CR2_TXEIE BIT(7) -#define STM32_SPI_CR2_RXNEIE BIT(6) -#define STM32_SPI_CR2_NSSP BIT(3) -#define STM32_SPI_CR2_SSOE BIT(2) -#define STM32_SPI_CR2_TXDMAEN BIT(1) -#define STM32_SPI_CR2_RXDMAEN BIT(0) - -#define STM32_SPI_SR_RXNE BIT(0) -#define STM32_SPI_SR_TXE BIT(1) -#define STM32_SPI_SR_CRCERR BIT(4) -#define STM32_SPI_SR_BSY BIT(7) -#define STM32_SPI_SR_FRLVL (3 << 9) -#define STM32_SPI_SR_FTLVL (3 << 11) +#define STM32_SPI_CR1_BIDIMODE BIT(15) +#define STM32_SPI_CR1_BIDIOE BIT(14) +#define STM32_SPI_CR1_CRCEN BIT(13) +#define STM32_SPI_CR1_SSM BIT(9) +#define STM32_SPI_CR1_SSI BIT(8) +#define STM32_SPI_CR1_LSBFIRST BIT(7) +#define STM32_SPI_CR1_SPE BIT(6) +#define STM32_SPI_CR1_BR_DIV64R (5 << 3) +#define STM32_SPI_CR1_BR_DIV4R BIT(3) +#define STM32_SPI_CR1_MSTR BIT(2) +#define STM32_SPI_CR1_CPOL BIT(1) +#define STM32_SPI_CR1_CPHA BIT(0) +#define STM32_SPI_CR2_FRXTH BIT(12) +#define STM32_SPI_CR2_DATASIZE(n) (((n)-1) << 8) +#define STM32_SPI_CR2_TXEIE BIT(7) +#define STM32_SPI_CR2_RXNEIE BIT(6) +#define STM32_SPI_CR2_NSSP BIT(3) +#define STM32_SPI_CR2_SSOE BIT(2) +#define STM32_SPI_CR2_TXDMAEN BIT(1) +#define STM32_SPI_CR2_RXDMAEN BIT(0) + +#define STM32_SPI_SR_RXNE BIT(0) +#define STM32_SPI_SR_TXE BIT(1) +#define STM32_SPI_SR_CRCERR BIT(4) +#define STM32_SPI_SR_BSY BIT(7) +#define STM32_SPI_SR_FRLVL (3 << 9) +#define STM32_SPI_SR_FTLVL (3 << 11) /* --- Debug --- */ -#define STM32_DBGMCU_CR REG32(STM32_DBGMCU_BASE + 0x04) -#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) -#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) +#define STM32_DBGMCU_IDCODE REG32(STM32_DBGMCU_BASE + 0x00) +#define STM32_DBGMCU_CR REG32(STM32_DBGMCU_BASE + 0x04) +#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) +#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) /* --- DBGMCU CR Bit Definitions --- */ -#define STM32_DBGMCU_CR_SLEEP BIT(0) -#define STM32_DBGMCU_CR_STOP BIT(1) -#define STM32_DBGMCU_CR_STBY BIT(2) -#define STM32_DBGMCU_CR_TRACE_MASK (BIT(5)|BIT(6)|BIT(7)) -#define STM32_DBGMCU_CR_TRACE_EN BIT(5) -#define STM32_DBGMCU_CR_TRACE_MODE_ASYNC 0 -#define STM32_DBGMCU_CR_TRACE_MODE_SYNC1 BIT(6) -#define STM32_DBGMCU_CR_TRACE_MODE_SYNC2 BIT(7) -#define STM32_DBGMCU_CR_TRACE_MODE_SYNC4 (BIT(6)|BIT(7)) +#define STM32_DBGMCU_CR_SLEEP BIT(0) +#define STM32_DBGMCU_CR_STOP BIT(1) +#define STM32_DBGMCU_CR_STBY BIT(2) +#define STM32_DBGMCU_CR_TRACE_MASK (BIT(5) | BIT(6) | BIT(7)) +#define STM32_DBGMCU_CR_TRACE_EN BIT(5) +#define STM32_DBGMCU_CR_TRACE_MODE_ASYNC 0 +#define STM32_DBGMCU_CR_TRACE_MODE_SYNC1 BIT(6) +#define STM32_DBGMCU_CR_TRACE_MODE_SYNC2 BIT(7) +#define STM32_DBGMCU_CR_TRACE_MODE_SYNC4 (BIT(6) | BIT(7)) /* --- DBGMCU APB1FZ Bit Definitions --- */ -#define STM32_DBGMCU_APB1FZ_TIM2 BIT(0) -#define STM32_DBGMCU_APB1FZ_TIM3 BIT(1) -#define STM32_DBGMCU_APB1FZ_TIM4 BIT(2) -#define STM32_DBGMCU_APB1FZ_TIM5 BIT(3) -#define STM32_DBGMCU_APB1FZ_TIM6 BIT(4) -#define STM32_DBGMCU_APB1FZ_TIM7 BIT(5) -#define STM32_DBGMCU_APB1FZ_RTC BIT(10) -#define STM32_DBGMCU_APB1FZ_WWDG BIT(11) -#define STM32_DBGMCU_APB1FZ_IWDG BIT(12) -#define STM32_DBGMCU_APB1FZ_I2C1_SMBUS_TIMEOUT BIT(21) -#define STM32_DBGMCU_APB1FZ_I2C2_SMBUS_TIMEOUT BIT(22) -#define STM32_DBGMCU_APB1FZ_I2C3_SMBUS_TIMEOUT BIT(30) +#define STM32_DBGMCU_APB1FZ_TIM2 BIT(0) +#define STM32_DBGMCU_APB1FZ_TIM3 BIT(1) +#define STM32_DBGMCU_APB1FZ_TIM4 BIT(2) +#define STM32_DBGMCU_APB1FZ_TIM5 BIT(3) +#define STM32_DBGMCU_APB1FZ_TIM6 BIT(4) +#define STM32_DBGMCU_APB1FZ_TIM7 BIT(5) +#define STM32_DBGMCU_APB1FZ_RTC BIT(10) +#define STM32_DBGMCU_APB1FZ_WWDG BIT(11) +#define STM32_DBGMCU_APB1FZ_IWDG BIT(12) +#define STM32_DBGMCU_APB1FZ_I2C1_SMBUS_TIMEOUT BIT(21) +#define STM32_DBGMCU_APB1FZ_I2C2_SMBUS_TIMEOUT BIT(22) +#define STM32_DBGMCU_APB1FZ_I2C3_SMBUS_TIMEOUT BIT(30) /* --- DBGMCU APB2FZ Bit Definitions --- */ -#define STM32_DBGMCU_APB2FZ_TIM1 BIT(11) -#define STM32_DBGMCU_APB2FZ_TIM8 BIT(13) -#define STM32_DBGMCU_APB2FZ_TIM15 BIT(16) -#define STM32_DBGMCU_APB2FZ_TIM16 BIT(17) -#define STM32_DBGMCU_APB2FZ_TIM17 BIT(18) -#define STM32_DBGMCU_APB2FZ_TIM20 BIT(20) +#define STM32_DBGMCU_APB2FZ_TIM1 BIT(11) +#define STM32_DBGMCU_APB2FZ_TIM8 BIT(13) +#define STM32_DBGMCU_APB2FZ_TIM15 BIT(16) +#define STM32_DBGMCU_APB2FZ_TIM16 BIT(17) +#define STM32_DBGMCU_APB2FZ_TIM17 BIT(18) +#define STM32_DBGMCU_APB2FZ_TIM20 BIT(20) /* --- Flash --- */ -#define STM32_FLASH_REG(off) REG32(STM32_FLASH_REGS_BASE + (off)) -#define STM32_FLASH_ACR STM32_FLASH_REG(0x00) -#define STM32_FLASH_PDKEYR STM32_FLASH_REG(0x04) -#define STM32_FLASH_KEYR STM32_FLASH_REG(0x08) -#define STM32_FLASH_OPTKEYR STM32_FLASH_REG(0x0c) -#define STM32_FLASH_SR STM32_FLASH_REG(0x10) -#define STM32_FLASH_CR STM32_FLASH_REG(0x14) -#define STM32_FLASH_ECCR STM32_FLASH_REG(0x18) -#define STM32_FLASH_OPTR STM32_FLASH_REG(0x20) -#define STM32_FLASH_PCROP1SR STM32_FLASH_REG(0x24) -#define STM32_FLASH_PCROP1ER STM32_FLASH_REG(0x28) -#define STM32_FLASH_WRP1AR STM32_FLASH_REG(0x2C) -#define STM32_FLASH_WRP1BR STM32_FLASH_REG(0x30) +#define STM32_FLASH_REG(off) REG32(STM32_FLASH_REGS_BASE + (off)) +#define STM32_FLASH_ACR STM32_FLASH_REG(0x00) +#define STM32_FLASH_PDKEYR STM32_FLASH_REG(0x04) +#define STM32_FLASH_KEYR STM32_FLASH_REG(0x08) +#define STM32_FLASH_OPTKEYR STM32_FLASH_REG(0x0c) +#define STM32_FLASH_SR STM32_FLASH_REG(0x10) +#define STM32_FLASH_CR STM32_FLASH_REG(0x14) +#define STM32_FLASH_ECCR STM32_FLASH_REG(0x18) +/* + * Bank 1 Option Byte Copy Registers. These registers are loaded from the option + * bytes location in flash at reset, assuming that option byte loading has not + * been disabled. + */ +#define STM32_FLASH_OPTR STM32_FLASH_REG(0x20) +#define STM32_FLASH_PCROP1SR STM32_FLASH_REG(0x24) +#define STM32_FLASH_PCROP1ER STM32_FLASH_REG(0x28) +#define STM32_FLASH_WRP1AR STM32_FLASH_REG(0x2C) +#define STM32_FLASH_WRP1BR STM32_FLASH_REG(0x30) +/* + * Bank 2 Option Byte Copy Registers. These will only exist for category 3 + * devices. + */ +#define STM32_FLASH_PCROP2SR STM32_FLASH_REG(0x44) +#define STM32_FLASH_PCROP2ER STM32_FLASH_REG(0x48) +#define STM32_FLASH_WRP2AR STM32_FLASH_REG(0x4C) +#define STM32_FLASH_WRP2BR STM32_FLASH_REG(0x50) + +#define STM32_FLASH_SEC_SIZE1 STM32_FLASH_REG(0x70) +#define STM32_FLASH_SEC_SIZE2 STM32_FLASH_REG(0x74) /* --- FLASH CR Bit Definitions --- */ #define STM32_FLASH_ACR_LATENCY_SHIFT (0) -#define STM32_FLASH_ACR_LATENCY_MASK (0xf << STM32_FLASH_ACR_LATENCY_SHIFT) -#define STM32_FLASH_ACR_PRFTEN BIT(8) -#define STM32_FLASH_ACR_ICEN BIT(9) -#define STM32_FLASH_ACR_DCEN BIT(10) -#define STM32_FLASH_ACR_ICRST BIT(11) -#define STM32_FLASH_ACR_DCRST BIT(12) +#define STM32_FLASH_ACR_LATENCY_MASK (0xf << STM32_FLASH_ACR_LATENCY_SHIFT) +#define STM32_FLASH_ACR_PRFTEN BIT(8) +#define STM32_FLASH_ACR_ICEN BIT(9) +#define STM32_FLASH_ACR_DCEN BIT(10) +#define STM32_FLASH_ACR_ICRST BIT(11) +#define STM32_FLASH_ACR_DCRST BIT(12) /* --- FLASH KEYR Bit Definitions --- */ -#define FLASH_KEYR_KEY1 0x45670123 -#define FLASH_KEYR_KEY2 0xCDEF89AB +#define FLASH_KEYR_KEY1 0x45670123 +#define FLASH_KEYR_KEY2 0xCDEF89AB /* --- FLASH OPTKEYR Bit Definitions --- */ -#define FLASH_OPTKEYR_KEY1 0x08192A3B -#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F +#define FLASH_OPTKEYR_KEY1 0x08192A3B +#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F /* --- FLASH SR Bit Definitions --- */ -#define FLASH_SR_BUSY BIT(16) -#define FLASH_SR_OPTVERR BIT(15) -#define FLASH_SR_RDERR BIT(14) -#define FLASH_SR_FASTERR BIT(9) -#define FLASH_SR_MISERR BIT(8) -#define FLASH_SR_PGSERR BIT(7) -#define FLASH_SR_SIZERR BIT(6) -#define FLASH_SR_PGAERR BIT(5) -#define FLASH_SR_WRPERR BIT(4) -#define FLASH_SR_PROGERR BIT(3) -#define FLASH_SR_OPERR BIT(1) -#define FLASH_SR_ERR_MASK (FLASH_SR_OPTVERR | FLASH_SR_RDERR | \ - FLASH_SR_FASTERR | FLASH_SR_PGSERR | \ - FLASH_SR_SIZERR | FLASH_SR_PGAERR | \ - FLASH_SR_WRPERR | FLASH_SR_PROGERR | \ - FLASH_SR_OPERR) +#define FLASH_SR_BUSY BIT(16) +#define FLASH_SR_OPTVERR BIT(15) +#define FLASH_SR_RDERR BIT(14) +#define FLASH_SR_FASTERR BIT(9) +#define FLASH_SR_MISERR BIT(8) +#define FLASH_SR_PGSERR BIT(7) +#define FLASH_SR_SIZERR BIT(6) +#define FLASH_SR_PGAERR BIT(5) +#define FLASH_SR_WRPERR BIT(4) +#define FLASH_SR_PROGERR BIT(3) +#define FLASH_SR_OPERR BIT(1) +#define FLASH_SR_ERR_MASK \ + (FLASH_SR_OPTVERR | FLASH_SR_RDERR | FLASH_SR_FASTERR | \ + FLASH_SR_PGSERR | FLASH_SR_SIZERR | FLASH_SR_PGAERR | \ + FLASH_SR_WRPERR | FLASH_SR_PROGERR | FLASH_SR_OPERR) /* --- FLASH CR Bit Definitions --- */ -#define FLASH_CR_PG BIT(0) -#define FLASH_CR_PER BIT(1) -#define FLASH_CR_STRT BIT(16) -#define FLASH_CR_OPTSTRT BIT(17) -#define FLASH_CR_OBL_LAUNCH BIT(27) -#define FLASH_CR_OPTLOCK BIT(30) -#define FLASH_CR_LOCK BIT(31) -#define FLASH_CR_PNB(sec) (((sec) & 0x7f) << 3) -#define FLASH_CR_PNB_MASK FLASH_CR_PNB(0x7f) - -#define STM32_FLASH_MIN_WRITE_SIZE (CONFIG_FLASH_WRITE_SIZE * 2) +#define FLASH_CR_PG BIT(0) +#define FLASH_CR_PER BIT(1) +#define FLASH_CR_STRT BIT(16) +#define FLASH_CR_OPTSTRT BIT(17) +#define FLASH_CR_OBL_LAUNCH BIT(27) +#define FLASH_CR_OPTLOCK BIT(30) +#define FLASH_CR_LOCK BIT(31) +#define FLASH_CR_PNB(sec) (((sec)&0x7f) << 3) +#define FLASH_CR_PNB_MASK FLASH_CR_PNB(0x7f) + +#define STM32_FLASH_MIN_WRITE_SIZE (CONFIG_FLASH_WRITE_SIZE * 2) /* --- FLASH Option bytes --- */ -#define STM32_OPTB_USER_RDP REG32(STM32_OPTB_BASE + 0x00) -#define STM32_OPTB_PCROP1_START REG32(STM32_OPTB_BASE + 0x08) -#define STM32_OPTB_PCROP1_END REG32(STM32_OPTB_BASE + 0x10) -#define STM32_OPTB_WRP1AR REG32(STM32_OPTB_BASE + 0x18) -#define STM32_OPTB_WRP1BR REG32(STM32_OPTB_BASE + 0x20) -#define STM32_OPTB_SECURE_MEM REG32(STM32_OPTB_BASE + 0x28) - -#define STM32_OPTB_REG_READ(n) REG32(STM32_FLASH_REG(0x20) + (n * 4)) -#define STM32_OPTB_READ(n) REG32(STM32_OPTB_BASE + ((n) * 8)) -#define STM32_OPTB_COMP_READ(n) REG32(STM32_OPTB_BASE + ((n) * 8) + 0x4) - -#define STM32_OPTB_USER_nBOOT1 BIT(23) -#define STM32_OPTB_USER_nSWBOOT0 BIT(26) -#define STM32_OPTB_USER_nBOOT0 BIT(27) +#define STM32_OPTB_USER_RDP REG32(STM32_OPTB_BANK1_BASE + 0x00) +#define STM32_OPTB_PCROP1_START REG32(STM32_OPTB_BANK1_BASE + 0x08) +#define STM32_OPTB_PCROP1_END REG32(STM32_OPTB_BANK1_BASE + 0x10) +#define STM32_OPTB_WRP1AR REG32(STM32_OPTB_BANK1_BASE + 0x18) +#define STM32_OPTB_WRP1BR REG32(STM32_OPTB_BANK1_BASE + 0x20) +#define STM32_OPTB_SECURE1_MEM REG32(STM32_OPTB_BANK1_BASE + 0x28) + +#define STM32_OPTB_UNUSED REG32(STM32_OPTB_BANK2_BASE + 0x00) +#define STM32_OPTB_PCROP2_START REG32(STM32_OPTB_BANK2_BASE + 0x08) +#define STM32_OPTB_PCROP2_END REG32(STM32_OPTB_BANK2_BASE + 0x10) +#define STM32_OPTB_WRP2AR REG32(STM32_OPTB_BANK2_BASE + 0x18) +#define STM32_OPTB_WRP2BR REG32(STM32_OPTB_BANK2_BASE + 0x20) +#define STM32_OPTB_SECURE2_MEM REG32(STM32_OPTB_BANK2_BASE + 0x28) + +/* Read option bytes from flash memory for Bank 1 */ +#define STM32_OPTB_BANK1_READ(n) REG32(STM32_OPTB_BANK1_BASE + ((n)*8)) +#define STM32_OPTB_BANK1_COMP_READ(n) \ + REG32(STM32_OPTB_BANK1_BASE + ((n)*8) + 0x4) +#define STM32_OPTB_BANK2_READ(n) REG32(STM32_OPTB_BANK2_BASE + ((n)*8)) +#define STM32_OPTB_BANK2_COMP_READ(n) \ + REG32(STM32_OPTB_BANK2_BASE + ((n)*8) + 0x4) + +#define STM32_OPTB_USER_DBANK BIT(22) +#define STM32_OPTB_USER_nBOOT1 BIT(23) +#define STM32_OPTB_USER_nSWBOOT0 BIT(26) +#define STM32_OPTB_USER_nBOOT0 BIT(27) #define STM32_OPTB_ENTRY_NUM 6 /* --- External Interrupts --- */ -#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) -#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) -#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) -#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) -#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) -#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) +#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) +#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) +#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) +#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) +#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) +#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) #define EXTI_RTC_ALR_EVENT BIT(17) /* --- ADC --- */ -#define STM32_ADC_ISR REG32(STM32_ADC1_BASE + 0x00) -#define STM32_ADC_IER REG32(STM32_ADC1_BASE + 0x04) -#define STM32_ADC_CR REG32(STM32_ADC1_BASE + 0x08) -#define STM32_ADC_CFGR REG32(STM32_ADC1_BASE + 0x0C) -#define STM32_ADC_CFGR2 REG32(STM32_ADC1_BASE + 0x10) -#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x14) -#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x18) -#define STM32_ADC_TR1 REG32(STM32_ADC1_BASE + 0x20) -#define STM32_ADC_TR2 REG32(STM32_ADC1_BASE + 0x24) -#define STM32_ADC_TR3 REG32(STM32_ADC1_BASE + 0x28) -#define STM32_ADC_JOFR(n) REG32(STM32_ADC1_BASE + 0x14 + ((n)&3) * 4) -#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x24) -#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x28) -#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x30 + ((n)&3) * 4) -#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x30) -#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x34) -#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x38) -#define STM32_ADC_SQR4 REG32(STM32_ADC1_BASE + 0x3C) -#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x40) -#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x4C) -#define STM32_ADC_JDR(n) REG32(STM32_ADC1_BASE + 0x80 + ((n)&3) * 4) - +#define STM32_ADC_ISR REG32(STM32_ADC1_BASE + 0x00) +#define STM32_ADC_IER REG32(STM32_ADC1_BASE + 0x04) +#define STM32_ADC_CR REG32(STM32_ADC1_BASE + 0x08) +#define STM32_ADC_CFGR REG32(STM32_ADC1_BASE + 0x0C) +#define STM32_ADC_CFGR2 REG32(STM32_ADC1_BASE + 0x10) +#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x14) +#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x18) +#define STM32_ADC_TR1 REG32(STM32_ADC1_BASE + 0x20) +#define STM32_ADC_TR2 REG32(STM32_ADC1_BASE + 0x24) +#define STM32_ADC_TR3 REG32(STM32_ADC1_BASE + 0x28) +#define STM32_ADC_JOFR(n) REG32(STM32_ADC1_BASE + 0x14 + ((n)&3) * 4) +#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x24) +#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x28) +#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x30 + ((n)&3) * 4) +#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x30) +#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x34) +#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x38) +#define STM32_ADC_SQR4 REG32(STM32_ADC1_BASE + 0x3C) +#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x40) +#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x4C) +#define STM32_ADC_JDR(n) REG32(STM32_ADC1_BASE + 0x80 + ((n)&3) * 4) /* --- ADC CR Bit Definitions --- */ -#define STM32_ADC_CR_ADEN BIT(0) -#define STM32_ADC_CR_ADSTART BIT(2) -#define STM32_ADC_CR_ADVREGEN BIT(28) -#define STM32_ADC_CR_CAL BIT(31) +#define STM32_ADC_CR_ADEN BIT(0) +#define STM32_ADC_CR_ADSTART BIT(2) +#define STM32_ADC_CR_ADVREGEN BIT(28) +#define STM32_ADC_CR_CAL BIT(31) -#define STM32_ADC_CFGR_CONT BIT(13) -#define STM32_ADC_CR2_ALIGN BIT(15) +#define STM32_ADC_CFGR_CONT BIT(13) +#define STM32_ADC_CR2_ALIGN BIT(15) /* --- Comparators --- */ - /* --- DMA --- */ /* * Available DMA streams, numbered from 0. @@ -1133,11 +1148,11 @@ enum dma_channel { /* Registers for a single channel of the DMA controller */ struct stm32_dma_chan { - uint32_t ccr; /* Control */ - uint32_t cndtr; /* Number of data to transfer */ - uint32_t cpar; /* Peripheral address */ - uint32_t cmar; /* Memory address */ - uint32_t reserved; + uint32_t ccr; /* Control */ + uint32_t cndtr; /* Number of data to transfer */ + uint32_t cpar; /* Peripheral address */ + uint32_t cmar; /* Memory address */ + uint32_t reserved; }; /* Always use stm32_dma_chan_t so volatile keyword is included! */ @@ -1148,8 +1163,8 @@ typedef stm32_dma_chan_t dma_chan_t; /* Registers for the DMA controller */ struct stm32_dma_regs { - uint32_t isr; - uint32_t ifcr; + uint32_t isr; + uint32_t ifcr; stm32_dma_chan_t chan[STM32_DMAC_COUNT]; }; @@ -1158,78 +1173,77 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_DMA1_REGS ((stm32_dma_regs_t *)STM32_DMA1_BASE) - -#define STM32_DMA_CCR_CHANNEL(channel) (0) +#define STM32_DMA_CCR_CHANNEL(channel) (0) #define STM32_DMA2_REGS ((stm32_dma_regs_t *)STM32_DMA2_BASE) #define STM32_DMA_REGS(channel) \ ((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_REGS : STM32_DMA2_REGS) -#define STM32_DMA_CSELR(channel) \ - REG32(((channel) < STM32_DMAC_PER_CTLR ? \ - STM32_DMA1_BASE : STM32_DMA2_BASE) + 0xA8) +#define STM32_DMA_CSELR(channel) \ + REG32(((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_BASE : \ + STM32_DMA2_BASE) + \ + 0xA8) /* Bits for DMA controller regs (isr and ifcr) */ -#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) +#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) #define STM32_DMA_ISR_MASK(channel, mask) \ ((mask) << STM32_DMA_CH_OFFSET(channel)) -#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) -#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) -#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) -#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) -#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) - -#define STM32_DMA_GIF BIT(0) -#define STM32_DMA_TCIF BIT(1) -#define STM32_DMA_HTIF BIT(2) -#define STM32_DMA_TEIF BIT(3) -#define STM32_DMA_ALL 0xf - -#define STM32_DMA_GET_ISR(channel) \ - ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_ISR(channel, val) \ - (STM32_DMA_REGS(channel)->isr = \ - ((STM32_DMA_REGS(channel)->isr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) -#define STM32_DMA_GET_IFCR(channel) \ - ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_IFCR(channel, val) \ - (STM32_DMA_REGS(channel)->ifcr = \ - ((STM32_DMA_REGS(channel)->ifcr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) - +#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) +#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) +#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) +#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) +#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) + +#define STM32_DMA_GIF BIT(0) +#define STM32_DMA_TCIF BIT(1) +#define STM32_DMA_HTIF BIT(2) +#define STM32_DMA_TEIF BIT(3) +#define STM32_DMA_ALL 0xf + +#define STM32_DMA_GET_ISR(channel) \ + ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_ISR(channel, val) \ + (STM32_DMA_REGS(channel)->isr = \ + ((STM32_DMA_REGS(channel)->isr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) +#define STM32_DMA_GET_IFCR(channel) \ + ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_IFCR(channel, val) \ + (STM32_DMA_REGS(channel)->ifcr = \ + ((STM32_DMA_REGS(channel)->ifcr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) /* Bits for DMA channel regs */ -#define STM32_DMA_CCR_EN BIT(0) -#define STM32_DMA_CCR_TCIE BIT(1) -#define STM32_DMA_CCR_HTIE BIT(2) -#define STM32_DMA_CCR_TEIE BIT(3) -#define STM32_DMA_CCR_DIR BIT(4) -#define STM32_DMA_CCR_CIRC BIT(5) -#define STM32_DMA_CCR_PINC BIT(6) -#define STM32_DMA_CCR_MINC BIT(7) -#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) -#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) -#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) -#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) -#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) -#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) -#define STM32_DMA_CCR_PL_LOW (0 << 12) -#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) -#define STM32_DMA_CCR_PL_HIGH (2 << 12) -#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) -#define STM32_DMA_CCR_MEM2MEM BIT(14) +#define STM32_DMA_CCR_EN BIT(0) +#define STM32_DMA_CCR_TCIE BIT(1) +#define STM32_DMA_CCR_HTIE BIT(2) +#define STM32_DMA_CCR_TEIE BIT(3) +#define STM32_DMA_CCR_DIR BIT(4) +#define STM32_DMA_CCR_CIRC BIT(5) +#define STM32_DMA_CCR_PINC BIT(6) +#define STM32_DMA_CCR_MINC BIT(7) +#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) +#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) +#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) +#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) +#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) +#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) +#define STM32_DMA_CCR_PL_LOW (0 << 12) +#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) +#define STM32_DMA_CCR_PL_HIGH (2 << 12) +#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) +#define STM32_DMA_CCR_MEM2MEM BIT(14) /* The requests for the DMA1/DMA2 controllers are routed through DMAMUX. */ /* DMAMUX registers */ -#define STM32_DMAMUX_CxCR(x) REG32(STM32_DMAMUX_BASE + 4 * (x)) -#define STM32_DMAMUX_CSR REG32(STM32_DMAMUX_BASE + 0x80) -#define STM32_DMAMUX_CFR REG32(STM32_DMAMUX_BASE + 0x84) -#define STM32_DMAMUX_RGxCR(x) REG32(STM32_DMAMUX_BASE + 0x100 + 4 * (x)) -#define STM32_DMAMUX_RGSR REG32(STM32_DMAMUX_BASE + 0x140) -#define STM32_DMAMUX_RGCFR REG32(STM32_DMAMUX_BASE + 0x144) +#define STM32_DMAMUX_CxCR(x) REG32(STM32_DMAMUX_BASE + 4 * (x)) +#define STM32_DMAMUX_CSR REG32(STM32_DMAMUX_BASE + 0x80) +#define STM32_DMAMUX_CFR REG32(STM32_DMAMUX_BASE + 0x84) +#define STM32_DMAMUX_RGxCR(x) REG32(STM32_DMAMUX_BASE + 0x100 + 4 * (x)) +#define STM32_DMAMUX_RGSR REG32(STM32_DMAMUX_BASE + 0x140) +#define STM32_DMAMUX_RGCFR REG32(STM32_DMAMUX_BASE + 0x144) enum dmamux1_request { DMAMUX_REQ_ADC1 = 5, @@ -1336,93 +1350,41 @@ enum dmamux1_request { #define DMAMUX_REQ_UART9_TX DMAMUX_REQ_LPUART1_TX /* --- CRC --- */ -#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) - -#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) -#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) -#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) -#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) - -#define STM32_CRC_CR_RESET BIT(0) -#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) -#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) -#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) -#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) -#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) -#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) -#define STM32_CRC_CR_REV_IN_WORD (3 << 5) -#define STM32_CRC_CR_REV_OUT BIT(7) - +#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) + +#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) +#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) +#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) +#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) + +#define STM32_CRC_CR_RESET BIT(0) +#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) +#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) +#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) +#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) +#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) +#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) +#define STM32_CRC_CR_REV_IN_WORD (3 << 5) +#define STM32_CRC_CR_REV_OUT BIT(7) /* --- USB --- */ -#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n) * 4) - -#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) - -#define STM32_USB_CNTR_FRES BIT(0) -#define STM32_USB_CNTR_PDWN BIT(1) -#define STM32_USB_CNTR_LP_MODE BIT(2) -#define STM32_USB_CNTR_FSUSP BIT(3) -#define STM32_USB_CNTR_RESUME BIT(4) -#define STM32_USB_CNTR_L1RESUME BIT(5) -#define STM32_USB_CNTR_L1REQM BIT(7) -#define STM32_USB_CNTR_ESOFM BIT(8) -#define STM32_USB_CNTR_SOFM BIT(9) -#define STM32_USB_CNTR_RESETM BIT(10) -#define STM32_USB_CNTR_SUSPM BIT(11) -#define STM32_USB_CNTR_WKUPM BIT(12) -#define STM32_USB_CNTR_ERRM BIT(13) -#define STM32_USB_CNTR_PMAOVRM BIT(14) -#define STM32_USB_CNTR_CTRM BIT(15) - -#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) - -#define STM32_USB_ISTR_EP_ID_MASK (0x000f) -#define STM32_USB_ISTR_DIR BIT(4) -#define STM32_USB_ISTR_L1REQ BIT(7) -#define STM32_USB_ISTR_ESOF BIT(8) -#define STM32_USB_ISTR_SOF BIT(9) -#define STM32_USB_ISTR_RESET BIT(10) -#define STM32_USB_ISTR_SUSP BIT(11) -#define STM32_USB_ISTR_WKUP BIT(12) -#define STM32_USB_ISTR_ERR BIT(13) -#define STM32_USB_ISTR_PMAOVR BIT(14) -#define STM32_USB_ISTR_CTR BIT(15) - -#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) - -#define STM32_USB_FNR_RXDP_RXDM_SHIFT (14) -#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) - -#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) -#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) -#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) -#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) - -#define STM32_USB_BCDR_BCDEN BIT(0) -#define STM32_USB_BCDR_DCDEN BIT(1) -#define STM32_USB_BCDR_PDEN BIT(2) -#define STM32_USB_BCDR_SDEN BIT(3) -#define STM32_USB_BCDR_DCDET BIT(4) -#define STM32_USB_BCDR_PDET BIT(5) -#define STM32_USB_BCDR_SDET BIT(6) -#define STM32_USB_BCDR_PS2DET BIT(7) +#define STM32_USB_BCDR_DPPU BIT(15) /* --- USB Endpoint bit definitions --- */ -#define EP_MASK 0x0F0F -#define EP_TX_DTOG 0x0040 -#define EP_TX_MASK 0x0030 +#define EP_MASK 0x0F0F +#define EP_TX_DTOG 0x0040 +#define EP_TX_MASK 0x0030 #define EP_TX_VALID 0x0030 -#define EP_TX_NAK 0x0020 +#define EP_TX_NAK 0x0020 #define EP_TX_STALL 0x0010 #define EP_TX_DISAB 0x0000 -#define EP_RX_DTOG 0x4000 -#define EP_RX_MASK 0x3000 +#define EP_RX_DTOG 0x4000 +#define EP_RX_MASK 0x3000 #define EP_RX_VALID 0x3000 -#define EP_RX_NAK 0x2000 +#define EP_RX_NAK 0x2000 #define EP_RX_STALL 0x1000 #define EP_RX_DISAB 0x0000 @@ -1432,32 +1394,30 @@ enum dmamux1_request { #define EP_TX_RX_VALID (EP_TX_VALID | EP_RX_VALID) #define STM32_TOGGLE_EP(n, mask, val, flags) \ - STM32_USB_EP(n) = (((STM32_USB_EP(n) & (EP_MASK | (mask))) \ - ^ (val)) | (flags)) + STM32_USB_EP(n) = \ + (((STM32_USB_EP(n) & (EP_MASK | (mask))) ^ (val)) | (flags)) /* --- TRNG --- */ -#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) -#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) -#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) +#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) +#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) +#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) /* --- RNG CR Bit Definitions --- */ -#define STM32_RNG_CR_RNGEN BIT(2) -#define STM32_RNG_CR_IE BIT(3) -#define STM32_RNG_CR_CED BIT(5) +#define STM32_RNG_CR_RNGEN BIT(2) +#define STM32_RNG_CR_IE BIT(3) +#define STM32_RNG_CR_CED BIT(5) /* --- RNG SR_DRDY Bit Definitions --- */ -#define STM32_RNG_SR_DRDY BIT(0) +#define STM32_RNG_SR_DRDY BIT(0) /* --- AXI interconnect --- */ /* STM32H7: AXI_TARGx_FN_MOD exists for masters x = 1, 2 and 7 */ -#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + \ - 0x1000 * (x)) -#define WRITE_ISS_OVERRIDE BIT(1) -#define READ_ISS_OVERRIDE BIT(0) +#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + 0x1000 * (x)) +#define WRITE_ISS_OVERRIDE BIT(1) +#define READ_ISS_OVERRIDE BIT(0) /* --- MISC --- */ -#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) -#define STM32_UNIQUE_ID_LENGTH (3 * 4) +#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) +#define STM32_UNIQUE_ID_LENGTH (3 * 4) #endif /* !__ASSEMBLER__ */ - diff --git a/chip/stm32/registers-stm32h7.h b/chip/stm32/registers-stm32h7.h index d02aaf1249..f4178d17f0 100644 --- a/chip/stm32/registers-stm32h7.h +++ b/chip/stm32/registers-stm32h7.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,591 +19,586 @@ #endif /* --- IRQ numbers --- */ -#define STM32_IRQ_WWDG 0 -#define STM32_IRQ_PVD 1 -#define STM32_IRQ_TAMPER_STAMP 2 -#define STM32_IRQ_RTC_WAKEUP 3 -#define STM32_IRQ_FLASH 4 -#define STM32_IRQ_RCC 5 -#define STM32_IRQ_EXTI0 6 -#define STM32_IRQ_EXTI1 7 -#define STM32_IRQ_EXTI2 8 -#define STM32_IRQ_EXTI3 9 -#define STM32_IRQ_EXTI4 10 -#define STM32_IRQ_DMA_CHANNEL_1 11 -#define STM32_IRQ_DMA_CHANNEL_2 12 -#define STM32_IRQ_DMA_CHANNEL_3 13 -#define STM32_IRQ_DMA_CHANNEL_4 14 -#define STM32_IRQ_DMA_CHANNEL_5 15 -#define STM32_IRQ_DMA_CHANNEL_6 16 -#define STM32_IRQ_DMA_CHANNEL_7 17 -#define STM32_IRQ_USB_HP 19 -#define STM32_IRQ_USB_LP 20 - -#define STM32_IRQ_ADC1 18 /* STM32L4 only */ -#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ -#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ -#define STM32_IRQ_DAC 21 -#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ - -#define STM32_IRQ_COMP 22 - -#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ -#define STM32_IRQ_EXTI9_5 23 -#define STM32_IRQ_TIM2 28 -#define STM32_IRQ_TIM3 29 -#define STM32_IRQ_TIM4 30 -#define STM32_IRQ_I2C1_EV 31 -#define STM32_IRQ_I2C1_ER 32 -#define STM32_IRQ_I2C2_EV 33 -#define STM32_IRQ_I2C2_ER 34 -#define STM32_IRQ_SPI1 35 -#define STM32_IRQ_SPI2 36 -#define STM32_IRQ_USART1 37 -#define STM32_IRQ_USART2 38 -#define STM32_IRQ_USART3 39 -#define STM32_IRQ_EXTI15_10 40 -#define STM32_IRQ_RTC_ALARM 41 -#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ -#define STM32_IRQ_CEC 42 /* STM32F373 only */ -#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ -#define STM32_IRQ_TIM12 43 /* STM32F373 only */ -#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ -#define STM32_IRQ_TIM13 44 /* STM32F373 only */ -#define STM32_IRQ_TIM14 45 /* STM32F373 only */ -#define STM32_IRQ_TIM5 50 /* STM32F373 */ -#define STM32_IRQ_SPI3 51 /* STM32F373 */ -#define STM32_IRQ_USART4 52 /* STM32F446 only */ -#define STM32_IRQ_USART5 53 /* STM32F446 only */ -#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ -#define STM32_IRQ_TIM7 55 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ +#define STM32_IRQ_WWDG 0 +#define STM32_IRQ_PVD 1 +#define STM32_IRQ_TAMPER_STAMP 2 +#define STM32_IRQ_RTC_WAKEUP 3 +#define STM32_IRQ_FLASH 4 +#define STM32_IRQ_RCC 5 +#define STM32_IRQ_EXTI0 6 +#define STM32_IRQ_EXTI1 7 +#define STM32_IRQ_EXTI2 8 +#define STM32_IRQ_EXTI3 9 +#define STM32_IRQ_EXTI4 10 +#define STM32_IRQ_DMA_CHANNEL_1 11 +#define STM32_IRQ_DMA_CHANNEL_2 12 +#define STM32_IRQ_DMA_CHANNEL_3 13 +#define STM32_IRQ_DMA_CHANNEL_4 14 +#define STM32_IRQ_DMA_CHANNEL_5 15 +#define STM32_IRQ_DMA_CHANNEL_6 16 +#define STM32_IRQ_DMA_CHANNEL_7 17 +#define STM32_IRQ_USB_HP 19 +#define STM32_IRQ_USB_LP 20 + +#define STM32_IRQ_ADC1 18 /* STM32L4 only */ +#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ +#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ +#define STM32_IRQ_DAC 21 +#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ + +#define STM32_IRQ_COMP 22 + +#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ +#define STM32_IRQ_EXTI9_5 23 +#define STM32_IRQ_TIM2 28 +#define STM32_IRQ_TIM3 29 +#define STM32_IRQ_TIM4 30 +#define STM32_IRQ_I2C1_EV 31 +#define STM32_IRQ_I2C1_ER 32 +#define STM32_IRQ_I2C2_EV 33 +#define STM32_IRQ_I2C2_ER 34 +#define STM32_IRQ_SPI1 35 +#define STM32_IRQ_SPI2 36 +#define STM32_IRQ_USART1 37 +#define STM32_IRQ_USART2 38 +#define STM32_IRQ_USART3 39 +#define STM32_IRQ_EXTI15_10 40 +#define STM32_IRQ_RTC_ALARM 41 +#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ +#define STM32_IRQ_CEC 42 /* STM32F373 only */ +#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ +#define STM32_IRQ_TIM12 43 /* STM32F373 only */ +#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ +#define STM32_IRQ_TIM13 44 /* STM32F373 only */ +#define STM32_IRQ_TIM14 45 /* STM32F373 only */ +#define STM32_IRQ_TIM5 50 /* STM32F373 */ +#define STM32_IRQ_SPI3 51 /* STM32F373 */ +#define STM32_IRQ_USART4 52 /* STM32F446 only */ +#define STM32_IRQ_USART5 53 /* STM32F446 only */ +#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ +#define STM32_IRQ_TIM7 55 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ /* if MISC_REMAP bits are set */ -#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ -#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ -#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ -#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ -#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ -#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ -#define STM32_IRQ_LPUART 70 /* STM32L4 only */ -#define STM32_IRQ_USART9 70 /* STM32L4 only */ -#define STM32_IRQ_USART6 71 /* STM32F446 only */ -#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ -#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ -#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ -#define STM32_IRQ_TIM19 78 /* STM32F373 only */ -#define STM32_IRQ_AES 79 /* STM32L4 only */ -#define STM32_IRQ_RNG 80 /* STM32L4 only */ -#define STM32_IRQ_FPU 81 /* STM32F373 only */ - -#define STM32_IRQ_LPTIM1 93 -#define STM32_IRQ_TIM15 116 -#define STM32_IRQ_TIM16 117 -#define STM32_IRQ_TIM17 118 -#define STM32_IRQ_LPTIM2 138 -#define STM32_IRQ_LPTIM3 139 -#define STM32_IRQ_LPTIM4 140 -#define STM32_IRQ_LPTIM5 141 +#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ +#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ +#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ +#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ +#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ +#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ +#define STM32_IRQ_LPUART 70 /* STM32L4 only */ +#define STM32_IRQ_USART9 70 /* STM32L4 only */ +#define STM32_IRQ_USART6 71 /* STM32F446 only */ +#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ +#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ +#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ +#define STM32_IRQ_TIM19 78 /* STM32F373 only */ +#define STM32_IRQ_AES 79 /* STM32L4 only */ +#define STM32_IRQ_RNG 80 /* STM32L4 only */ +#define STM32_IRQ_FPU 81 /* STM32F373 only */ + +#define STM32_IRQ_LPTIM1 93 +#define STM32_IRQ_TIM15 116 +#define STM32_IRQ_TIM16 117 +#define STM32_IRQ_TIM17 118 +#define STM32_IRQ_LPTIM2 138 +#define STM32_IRQ_LPTIM3 139 +#define STM32_IRQ_LPTIM4 140 +#define STM32_IRQ_LPTIM5 141 /* To simplify code generation, define DMA channel 9..10 */ -#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 -#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 -#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 -#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 +#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 +#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 +#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 +#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 /* aliases for easier code sharing */ #define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV #define STM32_IRQ_I2C2 STM32_IRQ_I2C2_EV #define STM32_IRQ_I2C3 STM32_IRQ_I2C3_EV - /* * STM32F4 introduces a concept of DMA stream to allow * fine allocation of a stream to a channel. */ -#define STM32_IRQ_DMA1_STREAM0 11 -#define STM32_IRQ_DMA1_STREAM1 12 -#define STM32_IRQ_DMA1_STREAM2 13 -#define STM32_IRQ_DMA1_STREAM3 14 -#define STM32_IRQ_DMA1_STREAM4 15 -#define STM32_IRQ_DMA1_STREAM5 16 -#define STM32_IRQ_DMA1_STREAM6 17 -#define STM32_IRQ_DMA1_STREAM7 47 -#define STM32_IRQ_DMA2_STREAM0 56 -#define STM32_IRQ_DMA2_STREAM1 57 -#define STM32_IRQ_DMA2_STREAM2 58 -#define STM32_IRQ_DMA2_STREAM3 59 -#define STM32_IRQ_DMA2_STREAM4 60 -#define STM32_IRQ_DMA2_STREAM5 68 -#define STM32_IRQ_DMA2_STREAM6 69 -#define STM32_IRQ_DMA2_STREAM7 70 - -#define STM32_IRQ_OTG_HS_WKUP 76 -#define STM32_IRQ_OTG_HS_EP1_IN 75 -#define STM32_IRQ_OTG_HS_EP1_OUT 74 -#define STM32_IRQ_OTG_HS 77 -#define STM32_IRQ_OTG_FS 67 -#define STM32_IRQ_OTG_FS_WKUP 42 +#define STM32_IRQ_DMA1_STREAM0 11 +#define STM32_IRQ_DMA1_STREAM1 12 +#define STM32_IRQ_DMA1_STREAM2 13 +#define STM32_IRQ_DMA1_STREAM3 14 +#define STM32_IRQ_DMA1_STREAM4 15 +#define STM32_IRQ_DMA1_STREAM5 16 +#define STM32_IRQ_DMA1_STREAM6 17 +#define STM32_IRQ_DMA1_STREAM7 47 +#define STM32_IRQ_DMA2_STREAM0 56 +#define STM32_IRQ_DMA2_STREAM1 57 +#define STM32_IRQ_DMA2_STREAM2 58 +#define STM32_IRQ_DMA2_STREAM3 59 +#define STM32_IRQ_DMA2_STREAM4 60 +#define STM32_IRQ_DMA2_STREAM5 68 +#define STM32_IRQ_DMA2_STREAM6 69 +#define STM32_IRQ_DMA2_STREAM7 70 + +#define STM32_IRQ_OTG_HS_WKUP 76 +#define STM32_IRQ_OTG_HS_EP1_IN 75 +#define STM32_IRQ_OTG_HS_EP1_OUT 74 +#define STM32_IRQ_OTG_HS 77 +#define STM32_IRQ_OTG_FS 67 +#define STM32_IRQ_OTG_FS_WKUP 42 /* Peripheral base addresses */ -#define STM32_GPV_BASE 0x51000000 - -#define STM32_DBGMCU_BASE 0x5C001000 - -#define STM32_BDMA_BASE 0x58025400 -#define STM32_DMA1_BASE 0x40020000 -#define STM32_DMA2_BASE 0x40020400 -#define STM32_DMA2D_BASE 0x52001000 -#define STM32_DMAMUX1_BASE 0x40020800 -#define STM32_DMAMUX2_BASE 0x58025800 -#define STM32_MDMA_BASE 0x52000000 - -#define STM32_EXTI_BASE 0x58000000 - -#define STM32_FLASH_REGS_BASE 0x52002000 - -#define STM32_GPIOA_BASE 0x58020000 -#define STM32_GPIOB_BASE 0x58020400 -#define STM32_GPIOC_BASE 0x58020800 -#define STM32_GPIOD_BASE 0x58020C00 -#define STM32_GPIOE_BASE 0x58021000 -#define STM32_GPIOF_BASE 0x58021400 -#define STM32_GPIOG_BASE 0x58021800 -#define STM32_GPIOH_BASE 0x58021C00 -#define STM32_GPIOI_BASE 0x58022000 -#define STM32_GPIOJ_BASE 0x58022400 -#define STM32_GPIOK_BASE 0x58022800 - -#define STM32_IWDG_BASE 0x58004800 - -#define STM32_LPTIM1_BASE 0x40002400 -#define STM32_LPTIM2_BASE 0x58002400 -#define STM32_LPTIM3_BASE 0x58002800 -#define STM32_LPTIM4_BASE 0x58002C00 -#define STM32_LPTIM5_BASE 0x58003000 - -#define STM32_PWR_BASE 0x58024800 -#define STM32_RCC_BASE 0x58024400 -#define STM32_RNG_BASE 0x48021800 -#define STM32_RTC_BASE 0x58004000 - -#define STM32_SYSCFG_BASE 0x58000400 - -#define STM32_SPI1_BASE 0x40013000 -#define STM32_SPI2_BASE 0x40003800 -#define STM32_SPI3_BASE 0x40003c00 -#define STM32_SPI4_BASE 0x40013400 -#define STM32_SPI5_BASE 0x40015000 - -#define STM32_TIM1_BASE 0x40010000 -#define STM32_TIM2_BASE 0x40000000 -#define STM32_TIM3_BASE 0x40000400 -#define STM32_TIM4_BASE 0x40000800 -#define STM32_TIM5_BASE 0x40000c00 -#define STM32_TIM6_BASE 0x40001000 -#define STM32_TIM7_BASE 0x40001400 -#define STM32_TIM8_BASE 0x40010400 -#define STM32_TIM12_BASE 0x40001800 -#define STM32_TIM13_BASE 0x40001c00 -#define STM32_TIM14_BASE 0x40002000 -#define STM32_TIM15_BASE 0x40014000 -#define STM32_TIM16_BASE 0x40014400 -#define STM32_TIM17_BASE 0x40014800 - -#define STM32_UNIQUE_ID_BASE 0x1ff1e800 - -#define STM32_USART1_BASE 0x40011000 -#define STM32_USART2_BASE 0x40004400 -#define STM32_USART3_BASE 0x40004800 -#define STM32_USART4_BASE 0x40004c00 -#define STM32_USART5_BASE 0x40005000 -#define STM32_USART6_BASE 0x40011400 -#define STM32_USART7_BASE 0x40007800 -#define STM32_USART8_BASE 0x40007C00 +#define STM32_GPV_BASE 0x51000000 + +#define STM32_DBGMCU_BASE 0x5C001000 + +#define STM32_BDMA_BASE 0x58025400 +#define STM32_DMA1_BASE 0x40020000 +#define STM32_DMA2_BASE 0x40020400 +#define STM32_DMA2D_BASE 0x52001000 +#define STM32_DMAMUX1_BASE 0x40020800 +#define STM32_DMAMUX2_BASE 0x58025800 +#define STM32_MDMA_BASE 0x52000000 + +#define STM32_EXTI_BASE 0x58000000 + +#define STM32_FLASH_REGS_BASE 0x52002000 + +#define STM32_GPIOA_BASE 0x58020000 +#define STM32_GPIOB_BASE 0x58020400 +#define STM32_GPIOC_BASE 0x58020800 +#define STM32_GPIOD_BASE 0x58020C00 +#define STM32_GPIOE_BASE 0x58021000 +#define STM32_GPIOF_BASE 0x58021400 +#define STM32_GPIOG_BASE 0x58021800 +#define STM32_GPIOH_BASE 0x58021C00 +#define STM32_GPIOI_BASE 0x58022000 +#define STM32_GPIOJ_BASE 0x58022400 +#define STM32_GPIOK_BASE 0x58022800 + +#define STM32_IWDG_BASE 0x58004800 + +#define STM32_LPTIM1_BASE 0x40002400 +#define STM32_LPTIM2_BASE 0x58002400 +#define STM32_LPTIM3_BASE 0x58002800 +#define STM32_LPTIM4_BASE 0x58002C00 +#define STM32_LPTIM5_BASE 0x58003000 + +#define STM32_PWR_BASE 0x58024800 +#define STM32_RCC_BASE 0x58024400 +#define STM32_RNG_BASE 0x48021800 +#define STM32_RTC_BASE 0x58004000 + +#define STM32_SYSCFG_BASE 0x58000400 + +#define STM32_SPI1_BASE 0x40013000 +#define STM32_SPI2_BASE 0x40003800 +#define STM32_SPI3_BASE 0x40003c00 +#define STM32_SPI4_BASE 0x40013400 +#define STM32_SPI5_BASE 0x40015000 + +#define STM32_TIM1_BASE 0x40010000 +#define STM32_TIM2_BASE 0x40000000 +#define STM32_TIM3_BASE 0x40000400 +#define STM32_TIM4_BASE 0x40000800 +#define STM32_TIM5_BASE 0x40000c00 +#define STM32_TIM6_BASE 0x40001000 +#define STM32_TIM7_BASE 0x40001400 +#define STM32_TIM8_BASE 0x40010400 +#define STM32_TIM12_BASE 0x40001800 +#define STM32_TIM13_BASE 0x40001c00 +#define STM32_TIM14_BASE 0x40002000 +#define STM32_TIM15_BASE 0x40014000 +#define STM32_TIM16_BASE 0x40014400 +#define STM32_TIM17_BASE 0x40014800 + +#define STM32_UNIQUE_ID_BASE 0x1ff1e800 + +#define STM32_USART1_BASE 0x40011000 +#define STM32_USART2_BASE 0x40004400 +#define STM32_USART3_BASE 0x40004800 +#define STM32_USART4_BASE 0x40004c00 +#define STM32_USART5_BASE 0x40005000 +#define STM32_USART6_BASE 0x40011400 +#define STM32_USART7_BASE 0x40007800 +#define STM32_USART8_BASE 0x40007C00 #ifndef __ASSEMBLER__ /* Register definitions */ /* --- USART --- */ -#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) -#define STM32_USART_CR1_UE BIT(0) -#define STM32_USART_CR1_UESM BIT(1) -#define STM32_USART_CR1_RE BIT(2) -#define STM32_USART_CR1_TE BIT(3) -#define STM32_USART_CR1_RXNEIE BIT(5) -#define STM32_USART_CR1_TCIE BIT(6) -#define STM32_USART_CR1_TXEIE BIT(7) -#define STM32_USART_CR1_PS BIT(9) -#define STM32_USART_CR1_PCE BIT(10) -#define STM32_USART_CR1_M BIT(12) -#define STM32_USART_CR1_OVER8 BIT(15) -#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) -#define STM32_USART_CR2_SWAP BIT(15) -#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) -#define STM32_USART_CR3_EIE BIT(0) -#define STM32_USART_CR3_DMAR BIT(6) -#define STM32_USART_CR3_DMAT BIT(7) -#define STM32_USART_CR3_ONEBIT BIT(11) -#define STM32_USART_CR3_OVRDIS BIT(12) -#define STM32_USART_CR3_WUS_START_BIT (2 << 20) -#define STM32_USART_CR3_WUFIE BIT(22) -#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) -#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) -#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) -#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) -#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) -#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) -#define STM32_USART_ICR_ORECF BIT(3) -#define STM32_USART_ICR_TCCF BIT(6) -#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) -#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) -#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) +#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) +#define STM32_USART_CR1_UE BIT(0) +#define STM32_USART_CR1_UESM BIT(1) +#define STM32_USART_CR1_RE BIT(2) +#define STM32_USART_CR1_TE BIT(3) +#define STM32_USART_CR1_RXNEIE BIT(5) +#define STM32_USART_CR1_TCIE BIT(6) +#define STM32_USART_CR1_TXEIE BIT(7) +#define STM32_USART_CR1_PS BIT(9) +#define STM32_USART_CR1_PCE BIT(10) +#define STM32_USART_CR1_M BIT(12) +#define STM32_USART_CR1_OVER8 BIT(15) +#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) +#define STM32_USART_CR2_SWAP BIT(15) +#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) +#define STM32_USART_CR3_EIE BIT(0) +#define STM32_USART_CR3_DMAR BIT(6) +#define STM32_USART_CR3_DMAT BIT(7) +#define STM32_USART_CR3_ONEBIT BIT(11) +#define STM32_USART_CR3_OVRDIS BIT(12) +#define STM32_USART_CR3_WUS_START_BIT (2 << 20) +#define STM32_USART_CR3_WUFIE BIT(22) +#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) +#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) +#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) +#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) +#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) +#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) +#define STM32_USART_ICR_ORECF BIT(3) +#define STM32_USART_ICR_TCCF BIT(6) +#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) +#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) +#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) /* register alias */ -#define STM32_USART_SR(base) STM32_USART_ISR(base) -#define STM32_USART_SR_ORE BIT(3) -#define STM32_USART_SR_RXNE BIT(5) -#define STM32_USART_SR_TC BIT(6) -#define STM32_USART_SR_TXE BIT(7) +#define STM32_USART_SR(base) STM32_USART_ISR(base) +#define STM32_USART_SR_ORE BIT(3) +#define STM32_USART_SR_RXNE BIT(5) +#define STM32_USART_SR_TC BIT(6) +#define STM32_USART_SR_TXE BIT(7) /* --- GPIO --- */ - -#define STM32_GPIO_MODER(b) REG32((b) + 0x00) -#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) -#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) -#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) -#define STM32_GPIO_IDR(b) REG16((b) + 0x10) -#define STM32_GPIO_ODR(b) REG16((b) + 0x14) -#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) -#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) -#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) -#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) - -#define GPIO_ALT_SYS 0x0 -#define GPIO_ALT_TIM2 0x1 -#define GPIO_ALT_TIM3_4 0x2 -#define GPIO_ALT_TIM9_11 0x3 -#define GPIO_ALT_I2C 0x4 -#define GPIO_ALT_SPI 0x5 -#define GPIO_ALT_SPI3 0x6 -#define GPIO_ALT_USART 0x7 -#define GPIO_ALT_I2C_23 0x9 -#define GPIO_ALT_USB 0xA -#define GPIO_ALT_LCD 0xB -#define GPIO_ALT_RI 0xE -#define GPIO_ALT_EVENTOUT 0xF +#define STM32_GPIO_MODER(b) REG32((b) + 0x00) +#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) +#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) +#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) +#define STM32_GPIO_IDR(b) REG16((b) + 0x10) +#define STM32_GPIO_ODR(b) REG16((b) + 0x14) +#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) +#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) +#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) +#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) + +#define GPIO_ALT_SYS 0x0 +#define GPIO_ALT_TIM2 0x1 +#define GPIO_ALT_TIM3_4 0x2 +#define GPIO_ALT_TIM9_11 0x3 +#define GPIO_ALT_I2C 0x4 +#define GPIO_ALT_SPI 0x5 +#define GPIO_ALT_SPI3 0x6 +#define GPIO_ALT_USART 0x7 +#define GPIO_ALT_I2C_23 0x9 +#define GPIO_ALT_USB 0xA +#define GPIO_ALT_LCD 0xB +#define GPIO_ALT_RI 0xE +#define GPIO_ALT_EVENTOUT 0xF /* --- I2C --- */ -#define STM32_I2C_CR1(n) REG16(stm32_i2c_reg(n, 0x00)) -#define STM32_I2C_CR1_PE BIT(0) -#define STM32_I2C_CR1_START BIT(8) -#define STM32_I2C_CR1_STOP BIT(9) -#define STM32_I2C_CR1_ACK BIT(10) -#define STM32_I2C_CR1_POS BIT(11) -#define STM32_I2C_CR1_SWRST BIT(15) -#define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04)) -#define STM32_I2C_CR2_ITERREN BIT(8) -#define STM32_I2C_CR2_ITEVTEN BIT(9) -#define STM32_I2C_CR2_ITBUFEN BIT(10) -#define STM32_I2C_CR2_DMAEN BIT(11) -#define STM32_I2C_CR2_LAST BIT(12) -#define STM32_I2C_OAR1(n) REG16(stm32_i2c_reg(n, 0x08)) -#define STM32_I2C_OAR1_B14 BIT(14) -#define STM32_I2C_OAR2(n) REG16(stm32_i2c_reg(n, 0x0C)) -#define STM32_I2C_OAR2_ENDUAL BIT(0) -#define STM32_I2C_DR(n) REG16(stm32_i2c_reg(n, 0x10)) -#define STM32_I2C_SR1(n) REG16(stm32_i2c_reg(n, 0x14)) -#define STM32_I2C_SR1_SB BIT(0) -#define STM32_I2C_SR1_ADDR BIT(1) -#define STM32_I2C_SR1_BTF BIT(2) -#define STM32_I2C_SR1_STOPF BIT(4) -#define STM32_I2C_SR1_RXNE BIT(6) -#define STM32_I2C_SR1_TXE BIT(7) -#define STM32_I2C_SR1_BERR BIT(8) -#define STM32_I2C_SR1_ARLO BIT(9) -#define STM32_I2C_SR1_AF BIT(10) - -#define STM32_I2C_SR2(n) REG16(stm32_i2c_reg(n, 0x18)) -#define STM32_I2C_SR2_BUSY BIT(1) -#define STM32_I2C_SR2_TRA BIT(2) -#define STM32_I2C_SR2_DUALF BIT(7) - -#define STM32_I2C_CCR(n) REG16(stm32_i2c_reg(n, 0x1C)) -#define STM32_I2C_CCR_DUTY BIT(14) -#define STM32_I2C_CCR_FM BIT(15) -#define STM32_I2C_TRISE(n) REG16(stm32_i2c_reg(n, 0x20)) - +#define STM32_I2C_CR1(n) REG16(stm32_i2c_reg(n, 0x00)) +#define STM32_I2C_CR1_PE BIT(0) +#define STM32_I2C_CR1_START BIT(8) +#define STM32_I2C_CR1_STOP BIT(9) +#define STM32_I2C_CR1_ACK BIT(10) +#define STM32_I2C_CR1_POS BIT(11) +#define STM32_I2C_CR1_SWRST BIT(15) +#define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04)) +#define STM32_I2C_CR2_ITERREN BIT(8) +#define STM32_I2C_CR2_ITEVTEN BIT(9) +#define STM32_I2C_CR2_ITBUFEN BIT(10) +#define STM32_I2C_CR2_DMAEN BIT(11) +#define STM32_I2C_CR2_LAST BIT(12) +#define STM32_I2C_OAR1(n) REG16(stm32_i2c_reg(n, 0x08)) +#define STM32_I2C_OAR1_B14 BIT(14) +#define STM32_I2C_OAR2(n) REG16(stm32_i2c_reg(n, 0x0C)) +#define STM32_I2C_OAR2_ENDUAL BIT(0) +#define STM32_I2C_DR(n) REG16(stm32_i2c_reg(n, 0x10)) +#define STM32_I2C_SR1(n) REG16(stm32_i2c_reg(n, 0x14)) +#define STM32_I2C_SR1_SB BIT(0) +#define STM32_I2C_SR1_ADDR BIT(1) +#define STM32_I2C_SR1_BTF BIT(2) +#define STM32_I2C_SR1_STOPF BIT(4) +#define STM32_I2C_SR1_RXNE BIT(6) +#define STM32_I2C_SR1_TXE BIT(7) +#define STM32_I2C_SR1_BERR BIT(8) +#define STM32_I2C_SR1_ARLO BIT(9) +#define STM32_I2C_SR1_AF BIT(10) + +#define STM32_I2C_SR2(n) REG16(stm32_i2c_reg(n, 0x18)) +#define STM32_I2C_SR2_BUSY BIT(1) +#define STM32_I2C_SR2_TRA BIT(2) +#define STM32_I2C_SR2_DUALF BIT(7) + +#define STM32_I2C_CCR(n) REG16(stm32_i2c_reg(n, 0x1C)) +#define STM32_I2C_CCR_DUTY BIT(14) +#define STM32_I2C_CCR_FM BIT(15) +#define STM32_I2C_TRISE(n) REG16(stm32_i2c_reg(n, 0x20)) /* --- Power / Reset / Clocks --- */ -#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) -#define STM32_PWR_CR2 REG32(STM32_PWR_BASE + 0x08) -#define STM32_PWR_CR3 REG32(STM32_PWR_BASE + 0x0C) -#define STM32_PWR_CR3_BYPASS BIT(0) -#define STM32_PWR_CR3_LDOEN BIT(1) -#define STM32_PWR_CR3_SCUEN BIT(2) -#define STM32_PWR_CR3_VBE BIT(8) -#define STM32_PWR_CR3_VBRS BIT(9) -#define STM32_PWR_CR3_USB33DEN BIT(24) -#define STM32_PWR_CR3_USBREGEN BIT(25) -#define STM32_PWR_CR3_USB33RDY BIT(26) -#define STM32_PWR_CPUCR REG32(STM32_PWR_BASE + 0x10) -#define STM32_PWR_CPUCR_PDDS_D1 BIT(0) -#define STM32_PWR_CPUCR_PDDS_D2 BIT(1) -#define STM32_PWR_CPUCR_PDDS_D3 BIT(2) -#define STM32_PWR_CPUCR_STOPF BIT(5) -#define STM32_PWR_CPUCR_SBF BIT(6) -#define STM32_PWR_CPUCR_SBF_D1 BIT(7) -#define STM32_PWR_CPUCR_SBF_D2 BIT(8) -#define STM32_PWR_CPUCR_CSSF BIT(9) -#define STM32_PWR_CPUCR_RUN_D3 BIT(11) -#define STM32_PWR_D3CR REG32(STM32_PWR_BASE + 0x18) -#define STM32_PWR_D3CR_VOS1 (3 << 14) -#define STM32_PWR_D3CR_VOS2 (2 << 14) -#define STM32_PWR_D3CR_VOS3 (1 << 14) -#define STM32_PWR_D3CR_VOSMASK (3 << 14) -#define STM32_PWR_D3CR_VOSRDY (1 << 13) -#define STM32_PWR_WKUPCR REG32(STM32_PWR_BASE + 0x20) -#define STM32_PWR_WKUPFR REG32(STM32_PWR_BASE + 0x24) -#define STM32_PWR_WKUPEPR REG32(STM32_PWR_BASE + 0x28) - - -#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x000) -#define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x004) -#define STM32_RCC_CRRCR REG32(STM32_RCC_BASE + 0x008) -#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x010) -#define STM32_RCC_D1CFGR REG32(STM32_RCC_BASE + 0x018) -#define STM32_RCC_D2CFGR REG32(STM32_RCC_BASE + 0x01C) -#define STM32_RCC_D3CFGR REG32(STM32_RCC_BASE + 0x020) -#define STM32_RCC_PLLCKSELR REG32(STM32_RCC_BASE + 0x028) -#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x02C) -#define STM32_RCC_PLL1DIVR REG32(STM32_RCC_BASE + 0x030) -#define STM32_RCC_PLL1FRACR REG32(STM32_RCC_BASE + 0x034) -#define STM32_RCC_PLL2DIVR REG32(STM32_RCC_BASE + 0x038) -#define STM32_RCC_PLL2FRACR REG32(STM32_RCC_BASE + 0x03C) -#define STM32_RCC_PLL3DIVR REG32(STM32_RCC_BASE + 0x040) -#define STM32_RCC_PLL3FRACR REG32(STM32_RCC_BASE + 0x044) -#define STM32_RCC_D1CCIPR REG32(STM32_RCC_BASE + 0x04C) -#define STM32_RCC_D2CCIP1R REG32(STM32_RCC_BASE + 0x050) -#define STM32_RCC_D2CCIP2R REG32(STM32_RCC_BASE + 0x054) -#define STM32_RCC_D3CCIPR REG32(STM32_RCC_BASE + 0x058) -#define STM32_RCC_CIER REG32(STM32_RCC_BASE + 0x060) -#define STM32_RCC_CIFR REG32(STM32_RCC_BASE + 0x064) -#define STM32_RCC_CICR REG32(STM32_RCC_BASE + 0x068) -#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x070) -#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x074) - -#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x098) - -#define STM32_RCC_RSR REG32(STM32_RCC_BASE + 0x0D0) -#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x0D4) -#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x0D8) -#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x0DC) -#define STM32_RCC_AHB2ENR_RNGEN BIT(6) -#define STM32_RCC_AHB2ENR_HASHEN BIT(5) -#define STM32_RCC_AHB2ENR_CRYPTEN BIT(4) -#define STM32_RCC_AHB4ENR REG32(STM32_RCC_BASE + 0x0E0) -#define STM32_RCC_AHB4ENR_GPIOMASK 0x3ff -#define STM32_RCC_APB3ENR REG32(STM32_RCC_BASE + 0x0E4) -#define STM32_RCC_APB1LENR REG32(STM32_RCC_BASE + 0x0E8) -#define STM32_RCC_APB1HENR REG32(STM32_RCC_BASE + 0x0EC) -#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x0F0) -#define STM32_RCC_APB4ENR REG32(STM32_RCC_BASE + 0x0F4) -#define STM32_RCC_SYSCFGEN BIT(1) -#define STM32_RCC_AHB3LPENR REG32(STM32_RCC_BASE + 0x0FC) -#define STM32_RCC_AHB1LPENR REG32(STM32_RCC_BASE + 0x100) -#define STM32_RCC_AHB2LPENR REG32(STM32_RCC_BASE + 0x104) -#define STM32_RCC_AHB4LPENR REG32(STM32_RCC_BASE + 0x108) -#define STM32_RCC_APB3LPENR REG32(STM32_RCC_BASE + 0x10C) -#define STM32_RCC_APB1LLPENR REG32(STM32_RCC_BASE + 0x110) -#define STM32_RCC_APB1HLPENR REG32(STM32_RCC_BASE + 0x114) -#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x118) -#define STM32_RCC_APB4LPENR REG32(STM32_RCC_BASE + 0x11C) +#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) +#define STM32_PWR_CR2 REG32(STM32_PWR_BASE + 0x08) +#define STM32_PWR_CR3 REG32(STM32_PWR_BASE + 0x0C) +#define STM32_PWR_CR3_BYPASS BIT(0) +#define STM32_PWR_CR3_LDOEN BIT(1) +#define STM32_PWR_CR3_SCUEN BIT(2) +#define STM32_PWR_CR3_VBE BIT(8) +#define STM32_PWR_CR3_VBRS BIT(9) +#define STM32_PWR_CR3_USB33DEN BIT(24) +#define STM32_PWR_CR3_USBREGEN BIT(25) +#define STM32_PWR_CR3_USB33RDY BIT(26) +#define STM32_PWR_CPUCR REG32(STM32_PWR_BASE + 0x10) +#define STM32_PWR_CPUCR_PDDS_D1 BIT(0) +#define STM32_PWR_CPUCR_PDDS_D2 BIT(1) +#define STM32_PWR_CPUCR_PDDS_D3 BIT(2) +#define STM32_PWR_CPUCR_STOPF BIT(5) +#define STM32_PWR_CPUCR_SBF BIT(6) +#define STM32_PWR_CPUCR_SBF_D1 BIT(7) +#define STM32_PWR_CPUCR_SBF_D2 BIT(8) +#define STM32_PWR_CPUCR_CSSF BIT(9) +#define STM32_PWR_CPUCR_RUN_D3 BIT(11) +#define STM32_PWR_D3CR REG32(STM32_PWR_BASE + 0x18) +#define STM32_PWR_D3CR_VOS1 (3 << 14) +#define STM32_PWR_D3CR_VOS2 (2 << 14) +#define STM32_PWR_D3CR_VOS3 (1 << 14) +#define STM32_PWR_D3CR_VOSMASK (3 << 14) +#define STM32_PWR_D3CR_VOSRDY (1 << 13) +#define STM32_PWR_WKUPCR REG32(STM32_PWR_BASE + 0x20) +#define STM32_PWR_WKUPFR REG32(STM32_PWR_BASE + 0x24) +#define STM32_PWR_WKUPEPR REG32(STM32_PWR_BASE + 0x28) + +#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x000) +#define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x004) +#define STM32_RCC_CRRCR REG32(STM32_RCC_BASE + 0x008) +#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x010) +#define STM32_RCC_D1CFGR REG32(STM32_RCC_BASE + 0x018) +#define STM32_RCC_D2CFGR REG32(STM32_RCC_BASE + 0x01C) +#define STM32_RCC_D3CFGR REG32(STM32_RCC_BASE + 0x020) +#define STM32_RCC_PLLCKSELR REG32(STM32_RCC_BASE + 0x028) +#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x02C) +#define STM32_RCC_PLL1DIVR REG32(STM32_RCC_BASE + 0x030) +#define STM32_RCC_PLL1FRACR REG32(STM32_RCC_BASE + 0x034) +#define STM32_RCC_PLL2DIVR REG32(STM32_RCC_BASE + 0x038) +#define STM32_RCC_PLL2FRACR REG32(STM32_RCC_BASE + 0x03C) +#define STM32_RCC_PLL3DIVR REG32(STM32_RCC_BASE + 0x040) +#define STM32_RCC_PLL3FRACR REG32(STM32_RCC_BASE + 0x044) +#define STM32_RCC_D1CCIPR REG32(STM32_RCC_BASE + 0x04C) +#define STM32_RCC_D2CCIP1R REG32(STM32_RCC_BASE + 0x050) +#define STM32_RCC_D2CCIP2R REG32(STM32_RCC_BASE + 0x054) +#define STM32_RCC_D3CCIPR REG32(STM32_RCC_BASE + 0x058) +#define STM32_RCC_CIER REG32(STM32_RCC_BASE + 0x060) +#define STM32_RCC_CIFR REG32(STM32_RCC_BASE + 0x064) +#define STM32_RCC_CICR REG32(STM32_RCC_BASE + 0x068) +#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x070) +#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x074) + +#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x098) + +#define STM32_RCC_RSR REG32(STM32_RCC_BASE + 0x0D0) +#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x0D4) +#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x0D8) +#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x0DC) +#define STM32_RCC_AHB2ENR_RNGEN BIT(6) +#define STM32_RCC_AHB2ENR_HASHEN BIT(5) +#define STM32_RCC_AHB2ENR_CRYPTEN BIT(4) +#define STM32_RCC_AHB4ENR REG32(STM32_RCC_BASE + 0x0E0) +#define STM32_RCC_AHB4ENR_GPIOMASK 0x3ff +#define STM32_RCC_APB3ENR REG32(STM32_RCC_BASE + 0x0E4) +#define STM32_RCC_APB1LENR REG32(STM32_RCC_BASE + 0x0E8) +#define STM32_RCC_APB1HENR REG32(STM32_RCC_BASE + 0x0EC) +#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x0F0) +#define STM32_RCC_APB4ENR REG32(STM32_RCC_BASE + 0x0F4) +#define STM32_RCC_SYSCFGEN BIT(1) +#define STM32_RCC_AHB3LPENR REG32(STM32_RCC_BASE + 0x0FC) +#define STM32_RCC_AHB1LPENR REG32(STM32_RCC_BASE + 0x100) +#define STM32_RCC_AHB2LPENR REG32(STM32_RCC_BASE + 0x104) +#define STM32_RCC_AHB4LPENR REG32(STM32_RCC_BASE + 0x108) +#define STM32_RCC_APB3LPENR REG32(STM32_RCC_BASE + 0x10C) +#define STM32_RCC_APB1LLPENR REG32(STM32_RCC_BASE + 0x110) +#define STM32_RCC_APB1HLPENR REG32(STM32_RCC_BASE + 0x114) +#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x118) +#define STM32_RCC_APB4LPENR REG32(STM32_RCC_BASE + 0x11C) /* Aliases */ -#define STM32_RCC_APB1ENR STM32_RCC_APB1LENR - -#define STM32_RCC_CR_HSION BIT(0) -#define STM32_RCC_CR_HSIRDY BIT(2) -#define STM32_RCC_CR_CSION BIT(7) -#define STM32_RCC_CR_CSIRDY BIT(8) -#define STM32_RCC_CR_HSI48ON BIT(12) -#define STM32_RCC_CR_HSI48RDY BIT(13) -#define STM32_RCC_CR_PLL1ON BIT(24) -#define STM32_RCC_CR_PLL1RDY BIT(25) -#define STM32_RCC_CR_PLL2ON BIT(26) -#define STM32_RCC_CR_PLL2RDY BIT(27) -#define STM32_RCC_CR_PLL3ON BIT(28) -#define STM32_RCC_CR_PLL3RDY BIT(29) -#define STM32_RCC_CFGR_SW_HSI (0 << 0) -#define STM32_RCC_CFGR_SW_CSI (1 << 0) -#define STM32_RCC_CFGR_SW_HSE (2 << 0) -#define STM32_RCC_CFGR_SW_PLL1 (3 << 0) -#define STM32_RCC_CFGR_SW_MASK (3 << 0) -#define STM32_RCC_CFGR_SWS_HSI (0 << 3) -#define STM32_RCC_CFGR_SWS_CSI (1 << 3) -#define STM32_RCC_CFGR_SWS_HSE (2 << 3) -#define STM32_RCC_CFGR_SWS_PLL1 (3 << 3) -#define STM32_RCC_CFGR_SWS_MASK (3 << 3) -#define STM32_RCC_D1CFGR_HPRE_DIV1 (0 << 0) -#define STM32_RCC_D1CFGR_HPRE_DIV2 (8 << 0) -#define STM32_RCC_D1CFGR_HPRE_DIV4 (9 << 0) -#define STM32_RCC_D1CFGR_HPRE_DIV8 (10 << 0) -#define STM32_RCC_D1CFGR_HPRE_DIV16 (11 << 0) -#define STM32_RCC_D1CFGR_D1PPRE_DIV1 (0 << 4) -#define STM32_RCC_D1CFGR_D1PPRE_DIV2 (4 << 4) -#define STM32_RCC_D1CFGR_D1PPRE_DIV4 (5 << 4) -#define STM32_RCC_D1CFGR_D1PPRE_DIV8 (6 << 4) -#define STM32_RCC_D1CFGR_D1PPRE_DIV16 (7 << 4) -#define STM32_RCC_D1CFGR_D1CPRE_DIV1 (0 << 8) -#define STM32_RCC_D1CFGR_D1CPRE_DIV2 (8 << 8) -#define STM32_RCC_D1CFGR_D1CPRE_DIV4 (9 << 8) -#define STM32_RCC_D1CFGR_D1CPRE_DIV8 (10 << 8) -#define STM32_RCC_D1CFGR_D1CPRE_DIV16 (1BIT(8)) -#define STM32_RCC_PLLCKSEL_PLLSRC_HSI (0 << 0) -#define STM32_RCC_PLLCKSEL_PLLSRC_CSI (1 << 0) -#define STM32_RCC_PLLCKSEL_PLLSRC_HSE (2 << 0) -#define STM32_RCC_PLLCKSEL_PLLSRC_NONE (3 << 0) -#define STM32_RCC_PLLCKSEL_PLLSRC_MASK (3 << 0) -#define STM32_RCC_PLLCKSEL_DIVM1(m) ((m) << 4) -#define STM32_RCC_PLLCKSEL_DIVM2(m) ((m) << 12) -#define STM32_RCC_PLLCKSEL_DIVM3(m) ((m) << 20) -#define STM32_RCC_PLLCFG_PLL1VCOSEL_FRACEN BIT(0) -#define STM32_RCC_PLLCFG_PLL1VCOSEL_WIDE (0 << 1) -#define STM32_RCC_PLLCFG_PLL1VCOSEL_MEDIUM BIT(1) -#define STM32_RCC_PLLCFG_PLL1RGE_1M_2M (0 << 2) -#define STM32_RCC_PLLCFG_PLL1RGE_2M_4M (1 << 2) -#define STM32_RCC_PLLCFG_PLL1RGE_4M_8M (2 << 2) -#define STM32_RCC_PLLCFG_PLL1RGE_8M_16M (3 << 2) -#define STM32_RCC_PLLCFG_DIVP1EN BIT(16) -#define STM32_RCC_PLLCFG_DIVQ1EN BIT(17) -#define STM32_RCC_PLLCFG_DIVR1EN BIT(18) -#define STM32_RCC_PLLDIV_DIVN(n) (((n) - 1) << 0) -#define STM32_RCC_PLLDIV_DIVP(p) (((p) - 1) << 9) -#define STM32_RCC_PLLDIV_DIVQ(q) (((q) - 1) << 16) -#define STM32_RCC_PLLDIV_DIVR(r) (((r) - 1) << 24) -#define STM32_RCC_PLLFRAC(n) ((n) << 3) -#define STM32_RCC_D2CCIP1R_SPI123SEL_PLL1Q (0 << 12) -#define STM32_RCC_D2CCIP1R_SPI123SEL_PLL2P (1 << 12) -#define STM32_RCC_D2CCIP1R_SPI123SEL_PLL3P (2 << 12) -#define STM32_RCC_D2CCIP1R_SPI123SEL_I2SCKIN (3 << 12) -#define STM32_RCC_D2CCIP1R_SPI123SEL_PERCK (4 << 12) -#define STM32_RCC_D2CCIP1R_SPI123SEL_MASK (7 << 12) -#define STM32_RCC_D2CCIP1R_SPI45SEL_APB (0 << 16) -#define STM32_RCC_D2CCIP1R_SPI45SEL_PLL2Q (1 << 16) -#define STM32_RCC_D2CCIP1R_SPI45SEL_PLL3Q (2 << 16) -#define STM32_RCC_D2CCIP1R_SPI45SEL_HSI (3 << 16) -#define STM32_RCC_D2CCIP1R_SPI45SEL_CSI (4 << 16) -#define STM32_RCC_D2CCIP1R_SPI45SEL_HSE (5 << 16) -#define STM32_RCC_D2CCIP1R_SPI45SEL_MASK (7 << 16) -#define STM32_RCC_D2CCIP2_USART234578SEL_PCLK (0 << 0) +#define STM32_RCC_APB1ENR STM32_RCC_APB1LENR + +#define STM32_RCC_CR_HSION BIT(0) +#define STM32_RCC_CR_HSIRDY BIT(2) +#define STM32_RCC_CR_CSION BIT(7) +#define STM32_RCC_CR_CSIRDY BIT(8) +#define STM32_RCC_CR_HSI48ON BIT(12) +#define STM32_RCC_CR_HSI48RDY BIT(13) +#define STM32_RCC_CR_PLL1ON BIT(24) +#define STM32_RCC_CR_PLL1RDY BIT(25) +#define STM32_RCC_CR_PLL2ON BIT(26) +#define STM32_RCC_CR_PLL2RDY BIT(27) +#define STM32_RCC_CR_PLL3ON BIT(28) +#define STM32_RCC_CR_PLL3RDY BIT(29) +#define STM32_RCC_CFGR_SW_HSI (0 << 0) +#define STM32_RCC_CFGR_SW_CSI (1 << 0) +#define STM32_RCC_CFGR_SW_HSE (2 << 0) +#define STM32_RCC_CFGR_SW_PLL1 (3 << 0) +#define STM32_RCC_CFGR_SW_MASK (3 << 0) +#define STM32_RCC_CFGR_SWS_HSI (0 << 3) +#define STM32_RCC_CFGR_SWS_CSI (1 << 3) +#define STM32_RCC_CFGR_SWS_HSE (2 << 3) +#define STM32_RCC_CFGR_SWS_PLL1 (3 << 3) +#define STM32_RCC_CFGR_SWS_MASK (3 << 3) +#define STM32_RCC_D1CFGR_HPRE_DIV1 (0 << 0) +#define STM32_RCC_D1CFGR_HPRE_DIV2 (8 << 0) +#define STM32_RCC_D1CFGR_HPRE_DIV4 (9 << 0) +#define STM32_RCC_D1CFGR_HPRE_DIV8 (10 << 0) +#define STM32_RCC_D1CFGR_HPRE_DIV16 (11 << 0) +#define STM32_RCC_D1CFGR_D1PPRE_DIV1 (0 << 4) +#define STM32_RCC_D1CFGR_D1PPRE_DIV2 (4 << 4) +#define STM32_RCC_D1CFGR_D1PPRE_DIV4 (5 << 4) +#define STM32_RCC_D1CFGR_D1PPRE_DIV8 (6 << 4) +#define STM32_RCC_D1CFGR_D1PPRE_DIV16 (7 << 4) +#define STM32_RCC_D1CFGR_D1CPRE_DIV1 (0 << 8) +#define STM32_RCC_D1CFGR_D1CPRE_DIV2 (8 << 8) +#define STM32_RCC_D1CFGR_D1CPRE_DIV4 (9 << 8) +#define STM32_RCC_D1CFGR_D1CPRE_DIV8 (10 << 8) +#define STM32_RCC_D1CFGR_D1CPRE_DIV16 (1BIT(8)) +#define STM32_RCC_PLLCKSEL_PLLSRC_HSI (0 << 0) +#define STM32_RCC_PLLCKSEL_PLLSRC_CSI (1 << 0) +#define STM32_RCC_PLLCKSEL_PLLSRC_HSE (2 << 0) +#define STM32_RCC_PLLCKSEL_PLLSRC_NONE (3 << 0) +#define STM32_RCC_PLLCKSEL_PLLSRC_MASK (3 << 0) +#define STM32_RCC_PLLCKSEL_DIVM1(m) ((m) << 4) +#define STM32_RCC_PLLCKSEL_DIVM2(m) ((m) << 12) +#define STM32_RCC_PLLCKSEL_DIVM3(m) ((m) << 20) +#define STM32_RCC_PLLCFG_PLL1VCOSEL_FRACEN BIT(0) +#define STM32_RCC_PLLCFG_PLL1VCOSEL_WIDE (0 << 1) +#define STM32_RCC_PLLCFG_PLL1VCOSEL_MEDIUM BIT(1) +#define STM32_RCC_PLLCFG_PLL1RGE_1M_2M (0 << 2) +#define STM32_RCC_PLLCFG_PLL1RGE_2M_4M (1 << 2) +#define STM32_RCC_PLLCFG_PLL1RGE_4M_8M (2 << 2) +#define STM32_RCC_PLLCFG_PLL1RGE_8M_16M (3 << 2) +#define STM32_RCC_PLLCFG_DIVP1EN BIT(16) +#define STM32_RCC_PLLCFG_DIVQ1EN BIT(17) +#define STM32_RCC_PLLCFG_DIVR1EN BIT(18) +#define STM32_RCC_PLLDIV_DIVN(n) (((n)-1) << 0) +#define STM32_RCC_PLLDIV_DIVP(p) (((p)-1) << 9) +#define STM32_RCC_PLLDIV_DIVQ(q) (((q)-1) << 16) +#define STM32_RCC_PLLDIV_DIVR(r) (((r)-1) << 24) +#define STM32_RCC_PLLFRAC(n) ((n) << 3) +#define STM32_RCC_D2CCIP1R_SPI123SEL_PLL1Q (0 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_PLL2P (1 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_PLL3P (2 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_I2SCKIN (3 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_PERCK (4 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_MASK (7 << 12) +#define STM32_RCC_D2CCIP1R_SPI45SEL_APB (0 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_PLL2Q (1 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_PLL3Q (2 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_HSI (3 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_CSI (4 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_HSE (5 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_MASK (7 << 16) +#define STM32_RCC_D2CCIP2_USART234578SEL_PCLK (0 << 0) #define STM32_RCC_D2CCIP2_USART234578SEL_PLL2Q (1 << 0) #define STM32_RCC_D2CCIP2_USART234578SEL_PLL3Q (2 << 0) -#define STM32_RCC_D2CCIP2_USART234578SEL_HSI (3 << 0) -#define STM32_RCC_D2CCIP2_USART234578SEL_CSI (4 << 0) -#define STM32_RCC_D2CCIP2_USART234578SEL_LSE (5 << 0) -#define STM32_RCC_D2CCIP2_USART234578SEL_MASK (7 << 0) -#define STM32_RCC_D2CCIP2_USART16SEL_PCLK (0 << 3) -#define STM32_RCC_D2CCIP2_USART16SEL_PLL2Q (1 << 3) -#define STM32_RCC_D2CCIP2_USART16SEL_PLL3Q (2 << 3) -#define STM32_RCC_D2CCIP2_USART16SEL_HSI (3 << 3) -#define STM32_RCC_D2CCIP2_USART16SEL_CSI (4 << 3) -#define STM32_RCC_D2CCIP2_USART16SEL_LSE (5 << 3) -#define STM32_RCC_D2CCIP2_USART16SEL_MASK (7 << 3) -#define STM32_RCC_D2CCIP2_RNGSEL_HSI48 (0 << 8) -#define STM32_RCC_D2CCIP2_RNGSEL_PLL1Q (1 << 8) -#define STM32_RCC_D2CCIP2_RNGSEL_LSE (2 << 8) -#define STM32_RCC_D2CCIP2_RNGSEL_LSI (3 << 8) -#define STM32_RCC_D2CCIP2_RNGSEL_MASK (3 << 8) -#define STM32_RCC_D2CCIP2_LPTIM1SEL_PCLK (0 << 28) -#define STM32_RCC_D2CCIP2_LPTIM1SEL_PLL2 (1 << 28) -#define STM32_RCC_D2CCIP2_LPTIM1SEL_PLL3 (2 << 28) -#define STM32_RCC_D2CCIP2_LPTIM1SEL_LSE (3 << 28) -#define STM32_RCC_D2CCIP2_LPTIM1SEL_LSI (4 << 28) -#define STM32_RCC_D2CCIP2_LPTIM1SEL_PER (5 << 28) -#define STM32_RCC_D2CCIP2_LPTIM1SEL_MASK (7 << 28) -#define STM32_RCC_CSR_LSION BIT(0) -#define STM32_RCC_CSR_LSIRDY BIT(1) - -#define STM32_SYSCFG_PMCR REG32(STM32_SYSCFG_BASE + 0x04) -#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) +#define STM32_RCC_D2CCIP2_USART234578SEL_HSI (3 << 0) +#define STM32_RCC_D2CCIP2_USART234578SEL_CSI (4 << 0) +#define STM32_RCC_D2CCIP2_USART234578SEL_LSE (5 << 0) +#define STM32_RCC_D2CCIP2_USART234578SEL_MASK (7 << 0) +#define STM32_RCC_D2CCIP2_USART16SEL_PCLK (0 << 3) +#define STM32_RCC_D2CCIP2_USART16SEL_PLL2Q (1 << 3) +#define STM32_RCC_D2CCIP2_USART16SEL_PLL3Q (2 << 3) +#define STM32_RCC_D2CCIP2_USART16SEL_HSI (3 << 3) +#define STM32_RCC_D2CCIP2_USART16SEL_CSI (4 << 3) +#define STM32_RCC_D2CCIP2_USART16SEL_LSE (5 << 3) +#define STM32_RCC_D2CCIP2_USART16SEL_MASK (7 << 3) +#define STM32_RCC_D2CCIP2_RNGSEL_HSI48 (0 << 8) +#define STM32_RCC_D2CCIP2_RNGSEL_PLL1Q (1 << 8) +#define STM32_RCC_D2CCIP2_RNGSEL_LSE (2 << 8) +#define STM32_RCC_D2CCIP2_RNGSEL_LSI (3 << 8) +#define STM32_RCC_D2CCIP2_RNGSEL_MASK (3 << 8) +#define STM32_RCC_D2CCIP2_LPTIM1SEL_PCLK (0 << 28) +#define STM32_RCC_D2CCIP2_LPTIM1SEL_PLL2 (1 << 28) +#define STM32_RCC_D2CCIP2_LPTIM1SEL_PLL3 (2 << 28) +#define STM32_RCC_D2CCIP2_LPTIM1SEL_LSE (3 << 28) +#define STM32_RCC_D2CCIP2_LPTIM1SEL_LSI (4 << 28) +#define STM32_RCC_D2CCIP2_LPTIM1SEL_PER (5 << 28) +#define STM32_RCC_D2CCIP2_LPTIM1SEL_MASK (7 << 28) +#define STM32_RCC_CSR_LSION BIT(0) +#define STM32_RCC_CSR_LSIRDY BIT(1) + +#define STM32_SYSCFG_PMCR REG32(STM32_SYSCFG_BASE + 0x04) +#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) /* Peripheral bits for APB1ENR regs */ -#define STM32_RCC_PB1_LPTIM1 BIT(9) +#define STM32_RCC_PB1_LPTIM1 BIT(9) /* Peripheral bits for APB2ENR regs */ -#define STM32_RCC_PB2_TIM1 BIT(0) -#define STM32_RCC_PB2_TIM2 BIT(1) -#define STM32_RCC_PB2_USART1 BIT(4) -#define STM32_RCC_PB2_SPI1 BIT(12) -#define STM32_RCC_PB2_SPI4 BIT(13) -#define STM32_RCC_PB2_TIM15 BIT(16) -#define STM32_RCC_PB2_TIM16 BIT(17) -#define STM32_RCC_PB2_TIM17 BIT(18) +#define STM32_RCC_PB2_TIM1 BIT(0) +#define STM32_RCC_PB2_TIM2 BIT(1) +#define STM32_RCC_PB2_USART1 BIT(4) +#define STM32_RCC_PB2_SPI1 BIT(12) +#define STM32_RCC_PB2_SPI4 BIT(13) +#define STM32_RCC_PB2_TIM15 BIT(16) +#define STM32_RCC_PB2_TIM16 BIT(17) +#define STM32_RCC_PB2_TIM17 BIT(18) /* Peripheral bits for AHB1/2/3/4ENR regs */ -#define STM32_RCC_HB1_DMA1 BIT(0) -#define STM32_RCC_HB1_DMA2 BIT(1) -#define STM32_RCC_HB3_MDMA BIT(0) -#define STM32_RCC_HB4_BDMA BIT(21) - +#define STM32_RCC_HB1_DMA1 BIT(0) +#define STM32_RCC_HB1_DMA2 BIT(1) +#define STM32_RCC_HB3_MDMA BIT(0) +#define STM32_RCC_HB4_BDMA BIT(21) /* Peripheral bits for RCC_APB/AHB and DBGMCU regs */ -#define STM32_RCC_PB2_USART1 BIT(4) +#define STM32_RCC_PB2_USART1 BIT(4) /* Reset causes definitions */ #define STM32_RCC_RESET_CAUSE STM32_RCC_RSR -#define RESET_CAUSE_WDG (BIT(28)|BIT(26)) -#define RESET_CAUSE_SFT BIT(24) -#define RESET_CAUSE_POR BIT(23) -#define RESET_CAUSE_PIN BIT(22) -#define RESET_CAUSE_OTHER (BIT(31)|BIT(30)|BIT(29)|BIT(28)| \ - BIT(27)|BIT(26)|BIT(25)|BIT(24)| \ - BIT(23)|BIT(22)|BIT(21)|BIT(20)| \ - BIT(19)|BIT(18)|BIT(17)) -#define RESET_CAUSE_RMVF BIT(16) +#define RESET_CAUSE_WDG (BIT(28) | BIT(26)) +#define RESET_CAUSE_SFT BIT(24) +#define RESET_CAUSE_POR BIT(23) +#define RESET_CAUSE_PIN BIT(22) +#define RESET_CAUSE_OTHER \ + (BIT(31) | BIT(30) | BIT(29) | BIT(28) | BIT(27) | BIT(26) | BIT(25) | \ + BIT(24) | BIT(23) | BIT(22) | BIT(21) | BIT(20) | BIT(19) | BIT(18) | \ + BIT(17)) +#define RESET_CAUSE_RMVF BIT(16) /* Power cause in PWR CPUCR register (Standby&Stop modes) */ #define STM32_PWR_RESET_CAUSE STM32_PWR_CPUCR #define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CPUCR -#define RESET_CAUSE_SBF BIT(6) -#define RESET_CAUSE_SBF_CLR BIT(9) +#define RESET_CAUSE_SBF BIT(6) +#define RESET_CAUSE_SBF_CLR BIT(9) /* --- Watchdogs --- */ /* --- Real-Time Clock --- */ -#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) -#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) -#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) -#define STM32_RTC_CR_BYPSHAD BIT(5) -#define STM32_RTC_CR_ALRAE BIT(8) -#define STM32_RTC_CR_ALRAIE BIT(12) -#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) -#define STM32_RTC_ISR_ALRAWF BIT(0) -#define STM32_RTC_ISR_RSF BIT(5) -#define STM32_RTC_ISR_INITF BIT(6) -#define STM32_RTC_ISR_INIT BIT(7) -#define STM32_RTC_ISR_ALRAF BIT(8) -#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) -#define STM32_RTC_PRER_A_MASK (0x7f << 16) -#define STM32_RTC_PRER_S_MASK (0x7fff << 0) -#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) -#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) -#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) -#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) -#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) -#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) -#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) -#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) -#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) -#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) -#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) - -#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) -#define STM32_BKP_BYTES 128 +#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) +#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) +#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) +#define STM32_RTC_CR_BYPSHAD BIT(5) +#define STM32_RTC_CR_ALRAE BIT(8) +#define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) +#define STM32_RTC_ISR_ALRAWF BIT(0) +#define STM32_RTC_ISR_RSF BIT(5) +#define STM32_RTC_ISR_INITF BIT(6) +#define STM32_RTC_ISR_INIT BIT(7) +#define STM32_RTC_ISR_ALRAF BIT(8) +#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) +#define STM32_RTC_PRER_A_MASK (0x7f << 16) +#define STM32_RTC_PRER_S_MASK (0x7fff << 0) +#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) +#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) +#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) +#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) +#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) +#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) +#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) +#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) +#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) +#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) +#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) + +#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) +#define STM32_BKP_BYTES 128 /* --- SPI --- */ @@ -634,163 +629,160 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_SPI3_REGS ((stm32_spi_regs_t *)STM32_SPI3_BASE) #define STM32_SPI4_REGS ((stm32_spi_regs_t *)STM32_SPI4_BASE) -#define STM32_SPI_CR1_SPE BIT(0) -#define STM32_SPI_CR1_CSTART BIT(9) -#define STM32_SPI_CR1_SSI BIT(12) -#define STM32_SPI_CR1_DIV(div) ((div) << 28) -#define STM32_SPI_CFG1_DATASIZE(n) (((n) - 1) << 0) -#define STM32_SPI_CFG1_FTHLV(n) (((n) - 1) << 5) -#define STM32_SPI_CFG1_UDRCFG_CONST (0 << 9) -#define STM32_SPI_CFG1_UDRCFG_LAST_RX (1 << 9) -#define STM32_SPI_CFG1_UDRCFG_LAST_TX (2 << 9) -#define STM32_SPI_CFG1_UDRDET_BEGIN_FRM (0 << 11) -#define STM32_SPI_CFG1_UDRDET_END_FRM (1 << 11) -#define STM32_SPI_CFG1_UDRDET_BEGIN_SS (2 << 11) -#define STM32_SPI_CFG1_RXDMAEN BIT(14) -#define STM32_SPI_CFG1_TXDMAEN BIT(15) -#define STM32_SPI_CFG1_CRCSIZE(n) (((n) - 1) << 16) -#define STM32_SPI_CFG2_MSTR BIT(22) -#define STM32_SPI_CFG2_SSM BIT(26) -#define STM32_SPI_CFG2_AFCNTR BIT(31) - -#define STM32_SPI_SR_RXNE BIT(0) -#define STM32_SPI_SR_UDR BIT(5) -#define STM32_SPI_SR_FRLVL (3 << 13) -#define STM32_SPI_SR_TXC BIT(12) +#define STM32_SPI_CR1_SPE BIT(0) +#define STM32_SPI_CR1_CSTART BIT(9) +#define STM32_SPI_CR1_SSI BIT(12) +#define STM32_SPI_CR1_DIV(div) ((div) << 28) +#define STM32_SPI_CFG1_DATASIZE(n) (((n)-1) << 0) +#define STM32_SPI_CFG1_FTHLV(n) (((n)-1) << 5) +#define STM32_SPI_CFG1_UDRCFG_CONST (0 << 9) +#define STM32_SPI_CFG1_UDRCFG_LAST_RX (1 << 9) +#define STM32_SPI_CFG1_UDRCFG_LAST_TX (2 << 9) +#define STM32_SPI_CFG1_UDRDET_BEGIN_FRM (0 << 11) +#define STM32_SPI_CFG1_UDRDET_END_FRM (1 << 11) +#define STM32_SPI_CFG1_UDRDET_BEGIN_SS (2 << 11) +#define STM32_SPI_CFG1_RXDMAEN BIT(14) +#define STM32_SPI_CFG1_TXDMAEN BIT(15) +#define STM32_SPI_CFG1_CRCSIZE(n) (((n)-1) << 16) +#define STM32_SPI_CFG2_MSTR BIT(22) +#define STM32_SPI_CFG2_SSM BIT(26) +#define STM32_SPI_CFG2_AFCNTR BIT(31) + +#define STM32_SPI_SR_RXNE BIT(0) +#define STM32_SPI_SR_UDR BIT(5) +#define STM32_SPI_SR_FRLVL (3 << 13) +#define STM32_SPI_SR_TXC BIT(12) /* --- Debug --- */ -#define STM32_DBGMCU_APB3FZ REG32(STM32_DBGMCU_BASE + 0x34) -#define STM32_DBGMCU_APB1LFZ REG32(STM32_DBGMCU_BASE + 0x3C) -#define STM32_DBGMCU_APB1HFZ REG32(STM32_DBGMCU_BASE + 0x44) -#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x4C) -#define STM32_DBGMCU_APB4FZ REG32(STM32_DBGMCU_BASE + 0x54) +#define STM32_DBGMCU_APB3FZ REG32(STM32_DBGMCU_BASE + 0x34) +#define STM32_DBGMCU_APB1LFZ REG32(STM32_DBGMCU_BASE + 0x3C) +#define STM32_DBGMCU_APB1HFZ REG32(STM32_DBGMCU_BASE + 0x44) +#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x4C) +#define STM32_DBGMCU_APB4FZ REG32(STM32_DBGMCU_BASE + 0x54) /* Alias */ -#define STM32_DBGMCU_APB1FZ STM32_DBGMCU_APB1LFZ +#define STM32_DBGMCU_APB1FZ STM32_DBGMCU_APB1LFZ /* --- Flash --- */ -#define STM32_FLASH_REG(bank, offset) REG32(((bank) ? 0x100 : 0) + \ - STM32_FLASH_REGS_BASE + (offset)) +#define STM32_FLASH_REG(bank, offset) \ + REG32(((bank) ? 0x100 : 0) + STM32_FLASH_REGS_BASE + (offset)) -#define STM32_FLASH_ACR(bank) STM32_FLASH_REG(bank, 0x00) +#define STM32_FLASH_ACR(bank) STM32_FLASH_REG(bank, 0x00) #define STM32_FLASH_ACR_LATENCY_SHIFT (0) -#define STM32_FLASH_ACR_LATENCY_MASK (7 << STM32_FLASH_ACR_LATENCY_SHIFT) -#define STM32_FLASH_ACR_WRHIGHFREQ_85MHZ (0 << 4) +#define STM32_FLASH_ACR_LATENCY_MASK (7 << STM32_FLASH_ACR_LATENCY_SHIFT) +#define STM32_FLASH_ACR_WRHIGHFREQ_85MHZ (0 << 4) #define STM32_FLASH_ACR_WRHIGHFREQ_185MHZ (1 << 4) #define STM32_FLASH_ACR_WRHIGHFREQ_285MHZ (2 << 4) #define STM32_FLASH_ACR_WRHIGHFREQ_385MHZ (3 << 4) -#define STM32_FLASH_KEYR(bank) STM32_FLASH_REG(bank, 0x04) -#define FLASH_KEYR_KEY1 0x45670123 -#define FLASH_KEYR_KEY2 0xCDEF89AB -#define STM32_FLASH_OPTKEYR(bank) STM32_FLASH_REG(bank, 0x08) -#define FLASH_OPTKEYR_KEY1 0x08192A3B -#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F -#define STM32_FLASH_CR(bank) STM32_FLASH_REG(bank, 0x0C) -#define FLASH_CR_LOCK BIT(0) -#define FLASH_CR_PG BIT(1) -#define FLASH_CR_SER BIT(2) -#define FLASH_CR_BER BIT(3) -#define FLASH_CR_PSIZE_BYTE (0 << 4) -#define FLASH_CR_PSIZE_HWORD (1 << 4) -#define FLASH_CR_PSIZE_WORD (2 << 4) -#define FLASH_CR_PSIZE_DWORD (3 << 4) -#define FLASH_CR_PSIZE_MASK (3 << 4) -#define FLASH_CR_FW BIT(6) -#define FLASH_CR_STRT BIT(7) -#define FLASH_CR_SNB(sec) (((sec) & 0x7) << 8) -#define FLASH_CR_SNB_MASK FLASH_CR_SNB(0x7) -#define STM32_FLASH_SR(bank) STM32_FLASH_REG(bank, 0x10) -#define FLASH_SR_BUSY BIT(0) -#define FLASH_SR_WBNE BIT(1) -#define FLASH_SR_QW BIT(2) -#define FLASH_SR_CRC_BUSY BIT(3) -#define FLASH_SR_EOP BIT(16) -#define FLASH_SR_WRPERR BIT(17) -#define FLASH_SR_PGSERR BIT(18) -#define FLASH_SR_STRBERR BIT(19) -#define FLASH_SR_INCERR BIT(21) -#define FLASH_SR_OPERR BIT(22) -#define FLASH_SR_RDPERR BIT(23) -#define FLASH_SR_RDSERR BIT(24) -#define FLASH_SR_SNECCERR BIT(25) -#define FLASH_SR_DBECCERR BIT(26) -#define FLASH_SR_CRCEND BIT(27) -#define STM32_FLASH_CCR(bank) STM32_FLASH_REG(bank, 0x14) -#define FLASH_CCR_ERR_MASK (FLASH_SR_WRPERR | FLASH_SR_PGSERR \ - | FLASH_SR_STRBERR | FLASH_SR_INCERR \ - | FLASH_SR_OPERR | FLASH_SR_RDPERR \ - | FLASH_SR_RDSERR | FLASH_SR_SNECCERR \ - | FLASH_SR_DBECCERR) -#define STM32_FLASH_OPTCR(bank) STM32_FLASH_REG(bank, 0x18) -#define FLASH_OPTCR_OPTLOCK BIT(0) -#define FLASH_OPTCR_OPTSTART BIT(1) -#define STM32_FLASH_OPTSR_CUR(bank) STM32_FLASH_REG(bank, 0x1C) -#define STM32_FLASH_OPTSR_PRG(bank) STM32_FLASH_REG(bank, 0x20) -#define FLASH_OPTSR_BUSY BIT(0) /* only in OPTSR_CUR */ -#define FLASH_OPTSR_RDP_MASK (0xFF << 8) -#define FLASH_OPTSR_RDP_LEVEL_0 (0xAA << 8) +#define STM32_FLASH_KEYR(bank) STM32_FLASH_REG(bank, 0x04) +#define FLASH_KEYR_KEY1 0x45670123 +#define FLASH_KEYR_KEY2 0xCDEF89AB +#define STM32_FLASH_OPTKEYR(bank) STM32_FLASH_REG(bank, 0x08) +#define FLASH_OPTKEYR_KEY1 0x08192A3B +#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F +#define STM32_FLASH_CR(bank) STM32_FLASH_REG(bank, 0x0C) +#define FLASH_CR_LOCK BIT(0) +#define FLASH_CR_PG BIT(1) +#define FLASH_CR_SER BIT(2) +#define FLASH_CR_BER BIT(3) +#define FLASH_CR_PSIZE_BYTE (0 << 4) +#define FLASH_CR_PSIZE_HWORD (1 << 4) +#define FLASH_CR_PSIZE_WORD (2 << 4) +#define FLASH_CR_PSIZE_DWORD (3 << 4) +#define FLASH_CR_PSIZE_MASK (3 << 4) +#define FLASH_CR_FW BIT(6) +#define FLASH_CR_STRT BIT(7) +#define FLASH_CR_SNB(sec) (((sec)&0x7) << 8) +#define FLASH_CR_SNB_MASK FLASH_CR_SNB(0x7) +#define STM32_FLASH_SR(bank) STM32_FLASH_REG(bank, 0x10) +#define FLASH_SR_BUSY BIT(0) +#define FLASH_SR_WBNE BIT(1) +#define FLASH_SR_QW BIT(2) +#define FLASH_SR_CRC_BUSY BIT(3) +#define FLASH_SR_EOP BIT(16) +#define FLASH_SR_WRPERR BIT(17) +#define FLASH_SR_PGSERR BIT(18) +#define FLASH_SR_STRBERR BIT(19) +#define FLASH_SR_INCERR BIT(21) +#define FLASH_SR_OPERR BIT(22) +#define FLASH_SR_RDPERR BIT(23) +#define FLASH_SR_RDSERR BIT(24) +#define FLASH_SR_SNECCERR BIT(25) +#define FLASH_SR_DBECCERR BIT(26) +#define FLASH_SR_CRCEND BIT(27) +#define STM32_FLASH_CCR(bank) STM32_FLASH_REG(bank, 0x14) +#define FLASH_CCR_ERR_MASK \ + (FLASH_SR_WRPERR | FLASH_SR_PGSERR | FLASH_SR_STRBERR | \ + FLASH_SR_INCERR | FLASH_SR_OPERR | FLASH_SR_RDPERR | \ + FLASH_SR_RDSERR | FLASH_SR_SNECCERR | FLASH_SR_DBECCERR) +#define STM32_FLASH_OPTCR(bank) STM32_FLASH_REG(bank, 0x18) +#define FLASH_OPTCR_OPTLOCK BIT(0) +#define FLASH_OPTCR_OPTSTART BIT(1) +#define STM32_FLASH_OPTSR_CUR(bank) STM32_FLASH_REG(bank, 0x1C) +#define STM32_FLASH_OPTSR_PRG(bank) STM32_FLASH_REG(bank, 0x20) +#define FLASH_OPTSR_BUSY BIT(0) /* only in OPTSR_CUR */ +#define FLASH_OPTSR_RDP_MASK (0xFF << 8) +#define FLASH_OPTSR_RDP_LEVEL_0 (0xAA << 8) /* RDP Level 1: Anything but 0xAA/0xCC */ -#define FLASH_OPTSR_RDP_LEVEL_1 (0x00 << 8) -#define FLASH_OPTSR_RDP_LEVEL_2 (0xCC << 8) -#define FLASH_OPTSR_RSS1 BIT(26) -#define FLASH_OPTSR_RSS2 BIT(27) -#define STM32_FLASH_OPTCCR(bank) STM32_FLASH_REG(bank, 0x24) -#define STM32_FLASH_PRAR_CUR(bank) STM32_FLASH_REG(bank, 0x28) -#define STM32_FLASH_PRAR_PRG(bank) STM32_FLASH_REG(bank, 0x2C) -#define STM32_FLASH_SCAR_CUR(bank) STM32_FLASH_REG(bank, 0x30) -#define STM32_FLASH_SCAR_PRG(bank) STM32_FLASH_REG(bank, 0x34) -#define STM32_FLASH_WPSN_CUR(bank) STM32_FLASH_REG(bank, 0x38) -#define STM32_FLASH_WPSN_PRG(bank) STM32_FLASH_REG(bank, 0x3C) -#define STM32_FLASH_BOOT_CUR(bank) STM32_FLASH_REG(bank, 0x40) -#define STM32_FLASH_BOOT_PRG(bank) STM32_FLASH_REG(bank, 0x44) -#define STM32_FLASH_CRC_CR(bank) STM32_FLASH_REG(bank, 0x50) -#define STM32_FLASH_CRC_SADDR(bank) STM32_FLASH_REG(bank, 0x54) -#define STM32_FLASH_CRC_EADDR(bank) STM32_FLASH_REG(bank, 0x58) -#define STM32_FLASH_CRC_DATA(bank) STM32_FLASH_REG(bank, 0x5C) -#define STM32_FLASH_ECC_FA(bank) STM32_FLASH_REG(bank, 0x60) +#define FLASH_OPTSR_RDP_LEVEL_1 (0x00 << 8) +#define FLASH_OPTSR_RDP_LEVEL_2 (0xCC << 8) +#define FLASH_OPTSR_RSS1 BIT(26) +#define FLASH_OPTSR_RSS2 BIT(27) +#define STM32_FLASH_OPTCCR(bank) STM32_FLASH_REG(bank, 0x24) +#define STM32_FLASH_PRAR_CUR(bank) STM32_FLASH_REG(bank, 0x28) +#define STM32_FLASH_PRAR_PRG(bank) STM32_FLASH_REG(bank, 0x2C) +#define STM32_FLASH_SCAR_CUR(bank) STM32_FLASH_REG(bank, 0x30) +#define STM32_FLASH_SCAR_PRG(bank) STM32_FLASH_REG(bank, 0x34) +#define STM32_FLASH_WPSN_CUR(bank) STM32_FLASH_REG(bank, 0x38) +#define STM32_FLASH_WPSN_PRG(bank) STM32_FLASH_REG(bank, 0x3C) +#define STM32_FLASH_BOOT_CUR(bank) STM32_FLASH_REG(bank, 0x40) +#define STM32_FLASH_BOOT_PRG(bank) STM32_FLASH_REG(bank, 0x44) +#define STM32_FLASH_CRC_CR(bank) STM32_FLASH_REG(bank, 0x50) +#define STM32_FLASH_CRC_SADDR(bank) STM32_FLASH_REG(bank, 0x54) +#define STM32_FLASH_CRC_EADDR(bank) STM32_FLASH_REG(bank, 0x58) +#define STM32_FLASH_CRC_DATA(bank) STM32_FLASH_REG(bank, 0x5C) +#define STM32_FLASH_ECC_FA(bank) STM32_FLASH_REG(bank, 0x60) /* --- External Interrupts --- */ -#define STM32_EXTI_RTSR1 REG32(STM32_EXTI_BASE + 0x00) -#define STM32_EXTI_FTSR1 REG32(STM32_EXTI_BASE + 0x04) -#define STM32_EXTI_SWIER1 REG32(STM32_EXTI_BASE + 0x08) -#define STM32_EXTI_D3PMR1 REG32(STM32_EXTI_BASE + 0x0C) -#define STM32_EXTI_D3PCR1L REG32(STM32_EXTI_BASE + 0x10) -#define STM32_EXTI_D3PCR1H REG32(STM32_EXTI_BASE + 0x14) -#define STM32_EXTI_RTSR2 REG32(STM32_EXTI_BASE + 0x20) -#define STM32_EXTI_FTSR2 REG32(STM32_EXTI_BASE + 0x24) -#define STM32_EXTI_SWIER2 REG32(STM32_EXTI_BASE + 0x28) -#define STM32_EXTI_D3PMR2 REG32(STM32_EXTI_BASE + 0x2C) -#define STM32_EXTI_D3PCR2L REG32(STM32_EXTI_BASE + 0x30) -#define STM32_EXTI_D3PCR2H REG32(STM32_EXTI_BASE + 0x34) -#define STM32_EXTI_RTSR3 REG32(STM32_EXTI_BASE + 0x40) -#define STM32_EXTI_FTSR3 REG32(STM32_EXTI_BASE + 0x44) -#define STM32_EXTI_SWIER3 REG32(STM32_EXTI_BASE + 0x48) -#define STM32_EXTI_D3PMR3 REG32(STM32_EXTI_BASE + 0x4C) -#define STM32_EXTI_D3PCR3L REG32(STM32_EXTI_BASE + 0x50) -#define STM32_EXTI_D3PCR3H REG32(STM32_EXTI_BASE + 0x54) -#define STM32_EXTI_CPUIMR1 REG32(STM32_EXTI_BASE + 0x80) -#define STM32_EXTI_CPUIER1 REG32(STM32_EXTI_BASE + 0x84) -#define STM32_EXTI_CPUPR1 REG32(STM32_EXTI_BASE + 0x88) -#define STM32_EXTI_CPUIMR2 REG32(STM32_EXTI_BASE + 0x90) -#define STM32_EXTI_CPUIER2 REG32(STM32_EXTI_BASE + 0x94) -#define STM32_EXTI_CPUPR2 REG32(STM32_EXTI_BASE + 0x98) -#define STM32_EXTI_CPUIMR3 REG32(STM32_EXTI_BASE + 0xA0) -#define STM32_EXTI_CPUIER3 REG32(STM32_EXTI_BASE + 0xA4) -#define STM32_EXTI_CPUPR3 REG32(STM32_EXTI_BASE + 0xA8) +#define STM32_EXTI_RTSR1 REG32(STM32_EXTI_BASE + 0x00) +#define STM32_EXTI_FTSR1 REG32(STM32_EXTI_BASE + 0x04) +#define STM32_EXTI_SWIER1 REG32(STM32_EXTI_BASE + 0x08) +#define STM32_EXTI_D3PMR1 REG32(STM32_EXTI_BASE + 0x0C) +#define STM32_EXTI_D3PCR1L REG32(STM32_EXTI_BASE + 0x10) +#define STM32_EXTI_D3PCR1H REG32(STM32_EXTI_BASE + 0x14) +#define STM32_EXTI_RTSR2 REG32(STM32_EXTI_BASE + 0x20) +#define STM32_EXTI_FTSR2 REG32(STM32_EXTI_BASE + 0x24) +#define STM32_EXTI_SWIER2 REG32(STM32_EXTI_BASE + 0x28) +#define STM32_EXTI_D3PMR2 REG32(STM32_EXTI_BASE + 0x2C) +#define STM32_EXTI_D3PCR2L REG32(STM32_EXTI_BASE + 0x30) +#define STM32_EXTI_D3PCR2H REG32(STM32_EXTI_BASE + 0x34) +#define STM32_EXTI_RTSR3 REG32(STM32_EXTI_BASE + 0x40) +#define STM32_EXTI_FTSR3 REG32(STM32_EXTI_BASE + 0x44) +#define STM32_EXTI_SWIER3 REG32(STM32_EXTI_BASE + 0x48) +#define STM32_EXTI_D3PMR3 REG32(STM32_EXTI_BASE + 0x4C) +#define STM32_EXTI_D3PCR3L REG32(STM32_EXTI_BASE + 0x50) +#define STM32_EXTI_D3PCR3H REG32(STM32_EXTI_BASE + 0x54) +#define STM32_EXTI_CPUIMR1 REG32(STM32_EXTI_BASE + 0x80) +#define STM32_EXTI_CPUIER1 REG32(STM32_EXTI_BASE + 0x84) +#define STM32_EXTI_CPUPR1 REG32(STM32_EXTI_BASE + 0x88) +#define STM32_EXTI_CPUIMR2 REG32(STM32_EXTI_BASE + 0x90) +#define STM32_EXTI_CPUIER2 REG32(STM32_EXTI_BASE + 0x94) +#define STM32_EXTI_CPUPR2 REG32(STM32_EXTI_BASE + 0x98) +#define STM32_EXTI_CPUIMR3 REG32(STM32_EXTI_BASE + 0xA0) +#define STM32_EXTI_CPUIER3 REG32(STM32_EXTI_BASE + 0xA4) +#define STM32_EXTI_CPUPR3 REG32(STM32_EXTI_BASE + 0xA8) /* Aliases */ -#define STM32_EXTI_IMR STM32_EXTI_CPUIMR1 -#define STM32_EXTI_EMR STM32_EXTI_CPUIMR1 -#define STM32_EXTI_RTSR STM32_EXTI_RTSR1 -#define STM32_EXTI_FTSR STM32_EXTI_FTSR1 -#define STM32_EXTI_SWIER STM32_EXTI_SWIER1 -#define STM32_EXTI_PR STM32_EXTI_CPUPR1 - +#define STM32_EXTI_IMR STM32_EXTI_CPUIMR1 +#define STM32_EXTI_EMR STM32_EXTI_CPUIMR1 +#define STM32_EXTI_RTSR STM32_EXTI_RTSR1 +#define STM32_EXTI_FTSR STM32_EXTI_FTSR1 +#define STM32_EXTI_SWIER STM32_EXTI_SWIER1 +#define STM32_EXTI_PR STM32_EXTI_CPUPR1 /* --- ADC --- */ /* --- Comparators --- */ - /* --- DMA --- */ /* * Available DMA streams, numbered from 0. @@ -839,7 +831,7 @@ enum dma_channel { STM32_DMAC_FMPI2C4_TX = STM32_DMA1_STREAM5, STM32_DMAC_FMPI2C4_RX = STM32_DMA1_STREAM2, - /* Legacy naming for spi_master.c */ + /* Legacy naming for spi_controller.c */ STM32_DMAC_SPI1_TX = STM32_DMA2_STREAM3, /* REQ 3 */ STM32_DMAC_SPI1_RX = STM32_DMA2_STREAM0, /* REQ 3 */ STM32_DMAC_SPI2_TX = STM32_DMA1_STREAM4, /* REQ 0 */ @@ -879,12 +871,12 @@ enum dma_channel { /* Registers for a single stream of a DMA controller */ struct stm32_dma_stream { - uint32_t scr; /* Control */ - uint32_t sndtr; /* Number of data to transfer */ - uint32_t spar; /* Peripheral address */ - uint32_t sm0ar; /* Memory address 0 */ - uint32_t sm1ar; /* address 1 for double buffer */ - uint32_t sfcr; /* FIFO control */ + uint32_t scr; /* Control */ + uint32_t sndtr; /* Number of data to transfer */ + uint32_t spar; /* Peripheral address */ + uint32_t sm0ar; /* Memory address 0 */ + uint32_t sm1ar; /* address 1 for double buffer */ + uint32_t sfcr; /* FIFO control */ }; /* Always use stm32_dma_stream_t so volatile keyword is included! */ @@ -893,12 +885,11 @@ typedef volatile struct stm32_dma_stream stm32_dma_stream_t; /* Common code and header file must use this */ typedef stm32_dma_stream_t dma_chan_t; struct stm32_dma_regs { - uint32_t isr[2]; - uint32_t ifcr[2]; + uint32_t isr[2]; + uint32_t ifcr[2]; stm32_dma_stream_t stream[STM32_DMAS_COUNT]; }; - /* Always use stm32_dma_regs_t so volatile keyword is included! */ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; @@ -909,87 +900,85 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_DMA_REGS(channel) \ ((channel) < STM32_DMAS_COUNT ? STM32_DMA1_REGS : STM32_DMA2_REGS) -#define STM32_DMA_CCR_EN BIT(0) -#define STM32_DMA_CCR_DMEIE BIT(1) -#define STM32_DMA_CCR_TEIE BIT(2) -#define STM32_DMA_CCR_HTIE BIT(3) -#define STM32_DMA_CCR_TCIE BIT(4) -#define STM32_DMA_CCR_PFCTRL BIT(5) -#define STM32_DMA_CCR_DIR_P2M (0 << 6) -#define STM32_DMA_CCR_DIR_M2P (1 << 6) -#define STM32_DMA_CCR_DIR_M2M (2 << 6) -#define STM32_DMA_CCR_CIRC BIT(8) -#define STM32_DMA_CCR_PINC BIT(9) -#define STM32_DMA_CCR_MINC BIT(10) -#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 11) -#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 11) -#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 11) -#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 13) -#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 13) -#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 13) -#define STM32_DMA_CCR_PINCOS BIT(15) -#define STM32_DMA_CCR_PL_LOW (0 << 16) -#define STM32_DMA_CCR_PL_MEDIUM (1 << 16) -#define STM32_DMA_CCR_PL_HIGH (2 << 16) -#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 16) -#define STM32_DMA_CCR_DBM BIT(18) -#define STM32_DMA_CCR_CT BIT(19) -#define STM32_DMA_CCR_PBURST(b_len) ((((b_len) - 4) / 4) << 21) -#define STM32_DMA_CCR_MBURST(b_len) ((((b_len) - 4) / 4) << 21) -#define STM32_DMA_CCR_CHANNEL_MASK (0 << 25) -#define STM32_DMA_CCR_CHANNEL(channel) (0) -#define STM32_DMA_CCR_RSVD_MASK (0xF0100000) -#define STM32_DMA_SFCR_DMDIS BIT(2) -#define STM32_DMA_SFCR_FTH(level) (((level) - 1) << 0) - - -#define STM32_DMA_CH_LOCAL(channel) ((channel) % STM32_DMAS_COUNT) -#define STM32_DMA_CH_LH(channel) \ - ((STM32_DMA_CH_LOCAL(channel) < 4) ? 0 : 1) -#define STM32_DMA_CH_OFFSET(channel) \ +#define STM32_DMA_CCR_EN BIT(0) +#define STM32_DMA_CCR_DMEIE BIT(1) +#define STM32_DMA_CCR_TEIE BIT(2) +#define STM32_DMA_CCR_HTIE BIT(3) +#define STM32_DMA_CCR_TCIE BIT(4) +#define STM32_DMA_CCR_PFCTRL BIT(5) +#define STM32_DMA_CCR_DIR_P2M (0 << 6) +#define STM32_DMA_CCR_DIR_M2P (1 << 6) +#define STM32_DMA_CCR_DIR_M2M (2 << 6) +#define STM32_DMA_CCR_CIRC BIT(8) +#define STM32_DMA_CCR_PINC BIT(9) +#define STM32_DMA_CCR_MINC BIT(10) +#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 11) +#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 11) +#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 11) +#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 13) +#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 13) +#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 13) +#define STM32_DMA_CCR_PINCOS BIT(15) +#define STM32_DMA_CCR_PL_LOW (0 << 16) +#define STM32_DMA_CCR_PL_MEDIUM (1 << 16) +#define STM32_DMA_CCR_PL_HIGH (2 << 16) +#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 16) +#define STM32_DMA_CCR_DBM BIT(18) +#define STM32_DMA_CCR_CT BIT(19) +#define STM32_DMA_CCR_PBURST(b_len) ((((b_len)-4) / 4) << 21) +#define STM32_DMA_CCR_MBURST(b_len) ((((b_len)-4) / 4) << 21) +#define STM32_DMA_CCR_CHANNEL_MASK (0 << 25) +#define STM32_DMA_CCR_CHANNEL(channel) (0) +#define STM32_DMA_CCR_RSVD_MASK (0xF0100000) +#define STM32_DMA_SFCR_DMDIS BIT(2) +#define STM32_DMA_SFCR_FTH(level) (((level)-1) << 0) + +#define STM32_DMA_CH_LOCAL(channel) ((channel) % STM32_DMAS_COUNT) +#define STM32_DMA_CH_LH(channel) ((STM32_DMA_CH_LOCAL(channel) < 4) ? 0 : 1) +#define STM32_DMA_CH_OFFSET(channel) \ (((STM32_DMA_CH_LOCAL(channel) % 4) * 6) + \ - (((STM32_DMA_CH_LOCAL(channel) % 4) >= 2) ? 4 : 0)) + (((STM32_DMA_CH_LOCAL(channel) % 4) >= 2) ? 4 : 0)) #define STM32_DMA_CH_GETBITS(channel, val) \ (((val) >> STM32_DMA_CH_OFFSET(channel)) & 0x3f) -#define STM32_DMA_GET_IFCR(channel) \ - (STM32_DMA_CH_GETBITS(channel, \ - STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)])) -#define STM32_DMA_GET_ISR(channel) \ - (STM32_DMA_CH_GETBITS(channel, \ - STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)])) - -#define STM32_DMA_SET_IFCR(channel, val) \ - (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] = \ - (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] & \ - ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & 0x3f) << STM32_DMA_CH_OFFSET(channel))) -#define STM32_DMA_SET_ISR(channel, val) \ - (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] = \ - (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] & \ - ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & 0x3f) << STM32_DMA_CH_OFFSET(channel))) - -#define STM32_DMA_FEIF BIT(0) -#define STM32_DMA_DMEIF BIT(2) -#define STM32_DMA_TEIF BIT(3) -#define STM32_DMA_HTIF BIT(4) -#define STM32_DMA_TCIF BIT(5) -#define STM32_DMA_ALL 0x3d - +#define STM32_DMA_GET_IFCR(channel) \ + (STM32_DMA_CH_GETBITS( \ + channel, \ + STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)])) +#define STM32_DMA_GET_ISR(channel) \ + (STM32_DMA_CH_GETBITS( \ + channel, \ + STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)])) + +#define STM32_DMA_SET_IFCR(channel, val) \ + (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] = \ + (STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] & \ + ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&0x3f) << STM32_DMA_CH_OFFSET(channel))) +#define STM32_DMA_SET_ISR(channel, val) \ + (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] = \ + (STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] & \ + ~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&0x3f) << STM32_DMA_CH_OFFSET(channel))) + +#define STM32_DMA_FEIF BIT(0) +#define STM32_DMA_DMEIF BIT(2) +#define STM32_DMA_TEIF BIT(3) +#define STM32_DMA_HTIF BIT(4) +#define STM32_DMA_TCIF BIT(5) +#define STM32_DMA_ALL 0x3d /* The requests for the DMA1/DMA2 controllers are routed through DMAMUX1. */ /* DMAMUX1/2 registers */ #define DMAMUX1 0 #define DMAMUX2 1 -#define STM32_DMAMUX_BASE(n) ((n) ? STM32_DMAMUX2_BASE \ - : STM32_DMAMUX1_BASE) -#define STM32_DMAMUX_REG32(n, off) REG32(STM32_DMAMUX_BASE(n) + (off)) -#define STM2_DMAMUX_CxCR(n, x) STM32_DMAMUX_REG32(n, 4 * (x)) -#define STM2_DMAMUX_CSR(n) STM32_DMAMUX_REG32(n, 0x80) -#define STM2_DMAMUX_CFR(n) STM32_DMAMUX_REG32(n, 0x84) -#define STM2_DMAMUX_RGxCR(n, x) STM32_DMAMUX_REG32(n, 0x100 + 4 * (x)) -#define STM2_DMAMUX_RGSR(n) STM32_DMAMUX_REG32(n, 0x140) -#define STM2_DMAMUX_RGCFR(n) STM32_DMAMUX_REG32(n, 0x144) +#define STM32_DMAMUX_BASE(n) ((n) ? STM32_DMAMUX2_BASE : STM32_DMAMUX1_BASE) +#define STM32_DMAMUX_REG32(n, off) REG32(STM32_DMAMUX_BASE(n) + (off)) +#define STM2_DMAMUX_CxCR(n, x) STM32_DMAMUX_REG32(n, 4 * (x)) +#define STM2_DMAMUX_CSR(n) STM32_DMAMUX_REG32(n, 0x80) +#define STM2_DMAMUX_CFR(n) STM32_DMAMUX_REG32(n, 0x84) +#define STM2_DMAMUX_RGxCR(n, x) STM32_DMAMUX_REG32(n, 0x100 + 4 * (x)) +#define STM2_DMAMUX_RGSR(n) STM32_DMAMUX_REG32(n, 0x140) +#define STM2_DMAMUX_RGCFR(n) STM32_DMAMUX_REG32(n, 0x144) enum dmamux1_request { DMAMUX1_REQ_ADC1 = 9, @@ -1091,138 +1080,63 @@ enum dmamux1_request { }; /* --- CRC --- */ -#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) -#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) -#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) -#define STM32_CRC_CR_RESET BIT(0) -#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) -#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) -#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) -#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) -#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) -#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) -#define STM32_CRC_CR_REV_IN_WORD (3 << 5) -#define STM32_CRC_CR_REV_OUT BIT(7) -#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) -#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) +#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) +#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) +#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) +#define STM32_CRC_CR_RESET BIT(0) +#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) +#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) +#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) +#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) +#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) +#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) +#define STM32_CRC_CR_REV_IN_WORD (3 << 5) +#define STM32_CRC_CR_REV_OUT BIT(7) +#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) +#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) /* --- PMSE --- */ -#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) -#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) -#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) -#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) -#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) -#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) -#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) -#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x) * 4) -#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) -#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) -#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) -#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) -#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) -#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) -#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) -#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) -#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) -#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) -#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) - -/* --- USB --- */ -#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n) * 4) - -#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) -#define STM32_USB_CNTR_FRES BIT(0) -#define STM32_USB_CNTR_PDWN BIT(1) -#define STM32_USB_CNTR_LP_MODE BIT(2) -#define STM32_USB_CNTR_FSUSP BIT(3) -#define STM32_USB_CNTR_RESUME BIT(4) -#define STM32_USB_CNTR_L1RESUME BIT(5) -#define STM32_USB_CNTR_L1REQM BIT(7) -#define STM32_USB_CNTR_ESOFM BIT(8) -#define STM32_USB_CNTR_SOFM BIT(9) -#define STM32_USB_CNTR_RESETM BIT(10) -#define STM32_USB_CNTR_SUSPM BIT(11) -#define STM32_USB_CNTR_WKUPM BIT(12) -#define STM32_USB_CNTR_ERRM BIT(13) -#define STM32_USB_CNTR_PMAOVRM BIT(14) -#define STM32_USB_CNTR_CTRM BIT(15) - -#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) -#define STM32_USB_ISTR_EP_ID_MASK (0x000f) -#define STM32_USB_ISTR_DIR BIT(4) -#define STM32_USB_ISTR_L1REQ BIT(7) -#define STM32_USB_ISTR_ESOF BIT(8) -#define STM32_USB_ISTR_SOF BIT(9) -#define STM32_USB_ISTR_RESET BIT(10) -#define STM32_USB_ISTR_SUSP BIT(11) -#define STM32_USB_ISTR_WKUP BIT(12) -#define STM32_USB_ISTR_ERR BIT(13) -#define STM32_USB_ISTR_PMAOVR BIT(14) -#define STM32_USB_ISTR_CTR BIT(15) - -#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) - -#define STM32_USB_FNR_RXDP_RXDM_SHIFT (14) -#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) - -#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) -#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) -#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) -#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) -#define STM32_USB_BCDR_BCDEN BIT(0) -#define STM32_USB_BCDR_DCDEN BIT(1) -#define STM32_USB_BCDR_PDEN BIT(2) -#define STM32_USB_BCDR_SDEN BIT(3) -#define STM32_USB_BCDR_DCDET BIT(4) -#define STM32_USB_BCDR_PDET BIT(5) -#define STM32_USB_BCDR_SDET BIT(6) -#define STM32_USB_BCDR_PS2DET BIT(7) - -#define EP_MASK 0x0F0F -#define EP_TX_DTOG 0x0040 -#define EP_TX_MASK 0x0030 -#define EP_TX_VALID 0x0030 -#define EP_TX_NAK 0x0020 -#define EP_TX_STALL 0x0010 -#define EP_TX_DISAB 0x0000 -#define EP_RX_DTOG 0x4000 -#define EP_RX_MASK 0x3000 -#define EP_RX_VALID 0x3000 -#define EP_RX_NAK 0x2000 -#define EP_RX_STALL 0x1000 -#define EP_RX_DISAB 0x0000 - -#define EP_STATUS_OUT 0x0100 - -#define EP_TX_RX_MASK (EP_TX_MASK | EP_RX_MASK) -#define EP_TX_RX_VALID (EP_TX_VALID | EP_RX_VALID) - -#define STM32_TOGGLE_EP(n, mask, val, flags) \ - STM32_USB_EP(n) = (((STM32_USB_EP(n) & (EP_MASK | (mask))) \ - ^ (val)) | (flags)) +#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) +#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) +#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) +#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) +#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) +#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) +#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) +#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x)*4) +#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) +#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) +#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) +#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) +#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) +#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) +#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) +#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) +#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) +#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) +#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) /* --- TRNG --- */ -#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) -#define STM32_RNG_CR_RNGEN BIT(2) -#define STM32_RNG_CR_IE BIT(3) -#define STM32_RNG_CR_CED BIT(5) -#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) -#define STM32_RNG_SR_DRDY BIT(0) -#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) +#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) +#define STM32_RNG_CR_RNGEN BIT(2) +#define STM32_RNG_CR_IE BIT(3) +#define STM32_RNG_CR_CED BIT(5) +#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) +#define STM32_RNG_SR_DRDY BIT(0) +#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) /* --- AXI interconnect --- */ /* STM32H7: AXI_TARGx_FN_MOD exists for masters x = 1, 2 and 7 */ -#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + \ - 0x1000 * (x)) -#define WRITE_ISS_OVERRIDE BIT(1) -#define READ_ISS_OVERRIDE BIT(0) +#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + 0x1000 * (x)) +#define WRITE_ISS_OVERRIDE BIT(1) +#define READ_ISS_OVERRIDE BIT(0) /* --- MISC --- */ -#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) -#define STM32_UNIQUE_ID_LENGTH (3 * 4) +#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) +#define STM32_UNIQUE_ID_LENGTH (3 * 4) #endif /* !__ASSEMBLER__ */ diff --git a/chip/stm32/registers-stm32l.h b/chip/stm32/registers-stm32l.h index 37b31ac302..57302a9d8d 100644 --- a/chip/stm32/registers-stm32l.h +++ b/chip/stm32/registers-stm32l.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -20,401 +20,393 @@ #endif /* --- IRQ numbers --- */ -#define STM32_IRQ_WWDG 0 -#define STM32_IRQ_PVD 1 -#define STM32_IRQ_TAMPER_STAMP 2 -#define STM32_IRQ_RTC_WAKEUP 3 -#define STM32_IRQ_FLASH 4 -#define STM32_IRQ_RCC 5 -#define STM32_IRQ_EXTI0 6 -#define STM32_IRQ_EXTI1 7 -#define STM32_IRQ_EXTI2 8 -#define STM32_IRQ_EXTI3 9 -#define STM32_IRQ_EXTI4 10 -#define STM32_IRQ_DMA_CHANNEL_1 11 -#define STM32_IRQ_DMA_CHANNEL_2 12 -#define STM32_IRQ_DMA_CHANNEL_3 13 -#define STM32_IRQ_DMA_CHANNEL_4 14 -#define STM32_IRQ_DMA_CHANNEL_5 15 -#define STM32_IRQ_DMA_CHANNEL_6 16 -#define STM32_IRQ_DMA_CHANNEL_7 17 -#define STM32_IRQ_USB_HP 19 -#define STM32_IRQ_USB_LP 20 - -#define STM32_IRQ_ADC1 18 /* STM32L4 only */ -#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ -#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ -#define STM32_IRQ_DAC 21 -#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ - -#define STM32_IRQ_COMP 22 - -#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ -#define STM32_IRQ_EXTI9_5 23 -#define STM32_IRQ_LCD 24 /* STM32L15X only */ -#define STM32_IRQ_TIM15 24 /* STM32F373 only */ -#define STM32_IRQ_TIM9 25 /* STM32L15X only */ -#define STM32_IRQ_TIM16 25 /* STM32F373 only */ -#define STM32_IRQ_TIM10 26 /* STM32L15X only */ -#define STM32_IRQ_TIM17 26 /* STM32F373 only */ -#define STM32_IRQ_TIM11 27 /* STM32L15X only */ -#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */ -#define STM32_IRQ_TIM2 28 -#define STM32_IRQ_TIM3 29 -#define STM32_IRQ_TIM4 30 -#define STM32_IRQ_I2C1_EV 31 -#define STM32_IRQ_I2C1_ER 32 -#define STM32_IRQ_I2C2_EV 33 -#define STM32_IRQ_I2C2_ER 34 -#define STM32_IRQ_SPI1 35 -#define STM32_IRQ_SPI2 36 -#define STM32_IRQ_USART1 37 -#define STM32_IRQ_USART2 38 -#define STM32_IRQ_USART3 39 -#define STM32_IRQ_EXTI15_10 40 -#define STM32_IRQ_RTC_ALARM 41 -#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ -#define STM32_IRQ_CEC 42 /* STM32F373 only */ -#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ -#define STM32_IRQ_TIM12 43 /* STM32F373 only */ -#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ -#define STM32_IRQ_TIM13 44 /* STM32F373 only */ -#define STM32_IRQ_TIM14 45 /* STM32F373 only */ -#define STM32_IRQ_TIM5 50 /* STM32F373 */ -#define STM32_IRQ_SPI3 51 /* STM32F373 */ -#define STM32_IRQ_USART4 52 /* STM32F446 only */ -#define STM32_IRQ_USART5 53 /* STM32F446 only */ -#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ -#define STM32_IRQ_TIM7 55 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ +#define STM32_IRQ_WWDG 0 +#define STM32_IRQ_PVD 1 +#define STM32_IRQ_TAMPER_STAMP 2 +#define STM32_IRQ_RTC_WAKEUP 3 +#define STM32_IRQ_FLASH 4 +#define STM32_IRQ_RCC 5 +#define STM32_IRQ_EXTI0 6 +#define STM32_IRQ_EXTI1 7 +#define STM32_IRQ_EXTI2 8 +#define STM32_IRQ_EXTI3 9 +#define STM32_IRQ_EXTI4 10 +#define STM32_IRQ_DMA_CHANNEL_1 11 +#define STM32_IRQ_DMA_CHANNEL_2 12 +#define STM32_IRQ_DMA_CHANNEL_3 13 +#define STM32_IRQ_DMA_CHANNEL_4 14 +#define STM32_IRQ_DMA_CHANNEL_5 15 +#define STM32_IRQ_DMA_CHANNEL_6 16 +#define STM32_IRQ_DMA_CHANNEL_7 17 +#define STM32_IRQ_USB_HP 19 +#define STM32_IRQ_USB_LP 20 + +#define STM32_IRQ_ADC1 18 /* STM32L4 only */ +#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ +#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ +#define STM32_IRQ_DAC 21 +#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ + +#define STM32_IRQ_COMP 22 + +#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ +#define STM32_IRQ_EXTI9_5 23 +#define STM32_IRQ_LCD 24 /* STM32L15X only */ +#define STM32_IRQ_TIM15 24 /* STM32F373 only */ +#define STM32_IRQ_TIM9 25 /* STM32L15X only */ +#define STM32_IRQ_TIM16 25 /* STM32F373 only */ +#define STM32_IRQ_TIM10 26 /* STM32L15X only */ +#define STM32_IRQ_TIM17 26 /* STM32F373 only */ +#define STM32_IRQ_TIM11 27 /* STM32L15X only */ +#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */ +#define STM32_IRQ_TIM2 28 +#define STM32_IRQ_TIM3 29 +#define STM32_IRQ_TIM4 30 +#define STM32_IRQ_I2C1_EV 31 +#define STM32_IRQ_I2C1_ER 32 +#define STM32_IRQ_I2C2_EV 33 +#define STM32_IRQ_I2C2_ER 34 +#define STM32_IRQ_SPI1 35 +#define STM32_IRQ_SPI2 36 +#define STM32_IRQ_USART1 37 +#define STM32_IRQ_USART2 38 +#define STM32_IRQ_USART3 39 +#define STM32_IRQ_EXTI15_10 40 +#define STM32_IRQ_RTC_ALARM 41 +#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ +#define STM32_IRQ_CEC 42 /* STM32F373 only */ +#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ +#define STM32_IRQ_TIM12 43 /* STM32F373 only */ +#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ +#define STM32_IRQ_TIM13 44 /* STM32F373 only */ +#define STM32_IRQ_TIM14 45 /* STM32F373 only */ +#define STM32_IRQ_TIM5 50 /* STM32F373 */ +#define STM32_IRQ_SPI3 51 /* STM32F373 */ +#define STM32_IRQ_USART4 52 /* STM32F446 only */ +#define STM32_IRQ_USART5 53 /* STM32F446 only */ +#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ +#define STM32_IRQ_TIM7 55 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ +#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ /* if MISC_REMAP bits are set */ -#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ -#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ -#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ -#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ -#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ -#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ -#define STM32_IRQ_LPUART 70 /* STM32L4 only */ -#define STM32_IRQ_USART9 70 /* STM32L4 only */ -#define STM32_IRQ_USART6 71 /* STM32F446 only */ -#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ -#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ -#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ -#define STM32_IRQ_TIM19 78 /* STM32F373 only */ -#define STM32_IRQ_AES 79 /* STM32L4 only */ -#define STM32_IRQ_RNG 80 /* STM32L4 only */ -#define STM32_IRQ_FPU 81 /* STM32F373 only */ - +#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ +#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ +#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ +#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ +#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ +#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ +#define STM32_IRQ_LPUART 70 /* STM32L4 only */ +#define STM32_IRQ_USART9 70 /* STM32L4 only */ +#define STM32_IRQ_USART6 71 /* STM32F446 only */ +#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ +#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ +#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ +#define STM32_IRQ_TIM19 78 /* STM32F373 only */ +#define STM32_IRQ_AES 79 /* STM32L4 only */ +#define STM32_IRQ_RNG 80 /* STM32L4 only */ +#define STM32_IRQ_FPU 81 /* STM32F373 only */ /* To simplify code generation, define DMA channel 9..10 */ -#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 -#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 -#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 -#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 +#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 +#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 +#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 +#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 /* aliases for easier code sharing */ #define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV #define STM32_IRQ_I2C2 STM32_IRQ_I2C2_EV #define STM32_IRQ_I2C3 STM32_IRQ_I2C3_EV - - /* Peripheral base addresses */ -#define STM32_ADC1_BASE 0x40012400 -#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */ - -#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ -#define STM32_CRC_BASE 0x40023000 -#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ -#define STM32_DAC_BASE 0x40007400 +#define STM32_ADC1_BASE 0x40012400 +#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */ -#define STM32_COMP_BASE 0x40007C00 +#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ +#define STM32_CRC_BASE 0x40023000 +#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ +#define STM32_DAC_BASE 0x40007400 -#define STM32_DBGMCU_BASE 0xE0042000 +#define STM32_COMP_BASE 0x40007C00 -#define STM32_DMA1_BASE 0x40026000 +#define STM32_DBGMCU_BASE 0xE0042000 -#define STM32_EXTI_BASE 0x40010400 +#define STM32_DMA1_BASE 0x40026000 -#define STM32_FLASH_REGS_BASE 0x40023c00 +#define STM32_EXTI_BASE 0x40010400 -#define STM32_GPIOA_BASE 0x40020000 -#define STM32_GPIOB_BASE 0x40020400 -#define STM32_GPIOC_BASE 0x40020800 -#define STM32_GPIOD_BASE 0x40020C00 -#define STM32_GPIOE_BASE 0x40021000 -#define STM32_GPIOF_BASE 0x40021800 /* see RM0038 table 5 */ -#define STM32_GPIOG_BASE 0x40021C00 -#define STM32_GPIOH_BASE 0x40021400 +#define STM32_FLASH_REGS_BASE 0x40023c00 -#define STM32_I2C1_BASE 0x40005400 -#define STM32_I2C2_BASE 0x40005800 -#define STM32_I2C3_BASE 0x40005C00 -#define STM32_I2C4_BASE 0x40006000 +#define STM32_GPIOA_BASE 0x40020000 +#define STM32_GPIOB_BASE 0x40020400 +#define STM32_GPIOC_BASE 0x40020800 +#define STM32_GPIOD_BASE 0x40020C00 +#define STM32_GPIOE_BASE 0x40021000 +#define STM32_GPIOF_BASE 0x40021800 /* see RM0038 table 5 */ +#define STM32_GPIOG_BASE 0x40021C00 +#define STM32_GPIOH_BASE 0x40021400 -#define STM32_IWDG_BASE 0x40003000 -#define STM32_LCD_BASE 0x40002400 +#define STM32_I2C1_BASE 0x40005400 +#define STM32_I2C2_BASE 0x40005800 +#define STM32_I2C3_BASE 0x40005C00 +#define STM32_I2C4_BASE 0x40006000 -#define STM32_OPTB_BASE 0x1ff80000 +#define STM32_IWDG_BASE 0x40003000 +#define STM32_LCD_BASE 0x40002400 -#define STM32_PMSE_BASE 0x40013400 -#define STM32_PWR_BASE 0x40007000 +#define STM32_OPTB_BASE 0x1ff80000 -#define STM32_RCC_BASE 0x40023800 +#define STM32_PMSE_BASE 0x40013400 +#define STM32_PWR_BASE 0x40007000 -#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ -#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ -#define STM32_RTC_BASE 0x40002800 +#define STM32_RCC_BASE 0x40023800 -#define STM32_SPI1_BASE 0x40013000 -#define STM32_SPI2_BASE 0x40003800 -#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ +#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ +#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ +#define STM32_RTC_BASE 0x40002800 -#define STM32_SYSCFG_BASE 0x40010000 +#define STM32_SPI1_BASE 0x40013000 +#define STM32_SPI2_BASE 0x40003800 +#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ -#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ -#define STM32_TIM2_BASE 0x40000000 -#define STM32_TIM3_BASE 0x40000400 -#define STM32_TIM4_BASE 0x40000800 -#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ -#define STM32_TIM6_BASE 0x40001000 -#define STM32_TIM7_BASE 0x40001400 -#define STM32_TIM9_BASE 0x40010800 /* STM32L15X only */ -#define STM32_TIM10_BASE 0x40010C00 /* STM32L15X only */ -#define STM32_TIM11_BASE 0x40011000 /* STM32L15X only */ -#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ -#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ -#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ -#define STM32_TIM15_BASE 0x40014000 -#define STM32_TIM16_BASE 0x40014400 -#define STM32_TIM17_BASE 0x40014800 -#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ -#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ +#define STM32_SYSCFG_BASE 0x40010000 -#define STM32_UNIQUE_ID_BASE 0x1ffff7ac +#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ +#define STM32_TIM2_BASE 0x40000000 +#define STM32_TIM3_BASE 0x40000400 +#define STM32_TIM4_BASE 0x40000800 +#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ +#define STM32_TIM6_BASE 0x40001000 +#define STM32_TIM7_BASE 0x40001400 +#define STM32_TIM9_BASE 0x40010800 /* STM32L15X only */ +#define STM32_TIM10_BASE 0x40010C00 /* STM32L15X only */ +#define STM32_TIM11_BASE 0x40011000 /* STM32L15X only */ +#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ +#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ +#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ +#define STM32_TIM15_BASE 0x40014000 +#define STM32_TIM16_BASE 0x40014400 +#define STM32_TIM17_BASE 0x40014800 +#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ +#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ -#define STM32_USART1_BASE 0x40013800 -#define STM32_USART2_BASE 0x40004400 -#define STM32_USART3_BASE 0x40004800 -#define STM32_USART4_BASE 0x40004c00 -#define STM32_USART9_BASE 0x40008000 /* LPUART */ +#define STM32_UNIQUE_ID_BASE 0x1ffff7ac -#define STM32_USB_CAN_SRAM_BASE 0x40006000 -#define STM32_USB_FS_BASE 0x40005C00 +#define STM32_USART1_BASE 0x40013800 +#define STM32_USART2_BASE 0x40004400 +#define STM32_USART3_BASE 0x40004800 +#define STM32_USART4_BASE 0x40004c00 +#define STM32_USART9_BASE 0x40008000 /* LPUART */ -#define STM32_WWDG_BASE 0x40002C00 +#define STM32_USB_CAN_SRAM_BASE 0x40006000 +#define STM32_USB_FS_BASE 0x40005C00 +#define STM32_WWDG_BASE 0x40002C00 #ifndef __ASSEMBLER__ /* Register definitions */ /* --- USART --- */ -#define STM32_USART_SR(base) STM32_USART_REG(base, 0x00) -#define STM32_USART_SR_ORE BIT(3) -#define STM32_USART_SR_RXNE BIT(5) -#define STM32_USART_SR_TC BIT(6) -#define STM32_USART_SR_TXE BIT(7) -#define STM32_USART_DR(base) STM32_USART_REG(base, 0x04) -#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x08) -#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x0C) -#define STM32_USART_CR1_RE BIT(2) -#define STM32_USART_CR1_TE BIT(3) -#define STM32_USART_CR1_RXNEIE BIT(5) -#define STM32_USART_CR1_TCIE BIT(6) -#define STM32_USART_CR1_TXEIE BIT(7) -#define STM32_USART_CR1_PS BIT(9) -#define STM32_USART_CR1_PCE BIT(10) -#define STM32_USART_CR1_M BIT(12) -#define STM32_USART_CR1_UE BIT(13) -#define STM32_USART_CR1_OVER8 BIT(15) /* STM32L only */ -#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x10) -#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x14) -#define STM32_USART_CR3_EIE BIT(0) -#define STM32_USART_CR3_DMAR BIT(6) -#define STM32_USART_CR3_DMAT BIT(7) -#define STM32_USART_CR3_ONEBIT BIT(11) /* STM32L only */ -#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x18) +#define STM32_USART_SR(base) STM32_USART_REG(base, 0x00) +#define STM32_USART_SR_ORE BIT(3) +#define STM32_USART_SR_RXNE BIT(5) +#define STM32_USART_SR_TC BIT(6) +#define STM32_USART_SR_TXE BIT(7) +#define STM32_USART_DR(base) STM32_USART_REG(base, 0x04) +#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x08) +#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x0C) +#define STM32_USART_CR1_RE BIT(2) +#define STM32_USART_CR1_TE BIT(3) +#define STM32_USART_CR1_RXNEIE BIT(5) +#define STM32_USART_CR1_TCIE BIT(6) +#define STM32_USART_CR1_TXEIE BIT(7) +#define STM32_USART_CR1_PS BIT(9) +#define STM32_USART_CR1_PCE BIT(10) +#define STM32_USART_CR1_M BIT(12) +#define STM32_USART_CR1_UE BIT(13) +#define STM32_USART_CR1_OVER8 BIT(15) /* STM32L only */ +#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x10) +#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x14) +#define STM32_USART_CR3_EIE BIT(0) +#define STM32_USART_CR3_DMAR BIT(6) +#define STM32_USART_CR3_DMAT BIT(7) +#define STM32_USART_CR3_ONEBIT BIT(11) /* STM32L only */ +#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x18) /* register aliases */ -#define STM32_USART_TDR(base) STM32_USART_DR(base) -#define STM32_USART_RDR(base) STM32_USART_DR(base) +#define STM32_USART_TDR(base) STM32_USART_DR(base) +#define STM32_USART_RDR(base) STM32_USART_DR(base) /* --- GPIO --- */ - -#define STM32_GPIO_MODER(b) REG32((b) + 0x00) -#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) -#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) -#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) -#define STM32_GPIO_IDR(b) REG16((b) + 0x10) -#define STM32_GPIO_ODR(b) REG16((b) + 0x14) -#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) -#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) -#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) -#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) - -#define GPIO_ALT_SYS 0x0 -#define GPIO_ALT_TIM2 0x1 -#define GPIO_ALT_TIM3_4 0x2 -#define GPIO_ALT_TIM9_11 0x3 -#define GPIO_ALT_I2C 0x4 -#define GPIO_ALT_SPI 0x5 -#define GPIO_ALT_SPI3 0x6 -#define GPIO_ALT_USART 0x7 -#define GPIO_ALT_I2C_23 0x9 -#define GPIO_ALT_USB 0xA -#define GPIO_ALT_LCD 0xB -#define GPIO_ALT_RI 0xE -#define GPIO_ALT_EVENTOUT 0xF +#define STM32_GPIO_MODER(b) REG32((b) + 0x00) +#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) +#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) +#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) +#define STM32_GPIO_IDR(b) REG16((b) + 0x10) +#define STM32_GPIO_ODR(b) REG16((b) + 0x14) +#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) +#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) +#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) +#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) + +#define GPIO_ALT_SYS 0x0 +#define GPIO_ALT_TIM2 0x1 +#define GPIO_ALT_TIM3_4 0x2 +#define GPIO_ALT_TIM9_11 0x3 +#define GPIO_ALT_I2C 0x4 +#define GPIO_ALT_SPI 0x5 +#define GPIO_ALT_SPI3 0x6 +#define GPIO_ALT_USART 0x7 +#define GPIO_ALT_I2C_23 0x9 +#define GPIO_ALT_USB 0xA +#define GPIO_ALT_LCD 0xB +#define GPIO_ALT_RI 0xE +#define GPIO_ALT_EVENTOUT 0xF /* --- I2C --- */ -#define STM32_I2C_CR1(n) REG16(stm32_i2c_reg(n, 0x00)) -#define STM32_I2C_CR1_PE BIT(0) -#define STM32_I2C_CR1_START BIT(8) -#define STM32_I2C_CR1_STOP BIT(9) -#define STM32_I2C_CR1_ACK BIT(10) -#define STM32_I2C_CR1_POS BIT(11) -#define STM32_I2C_CR1_SWRST BIT(15) -#define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04)) -#define STM32_I2C_CR2_ITERREN BIT(8) -#define STM32_I2C_CR2_ITEVTEN BIT(9) -#define STM32_I2C_CR2_ITBUFEN BIT(10) -#define STM32_I2C_CR2_DMAEN BIT(11) -#define STM32_I2C_CR2_LAST BIT(12) -#define STM32_I2C_OAR1(n) REG16(stm32_i2c_reg(n, 0x08)) -#define STM32_I2C_OAR1_B14 BIT(14) -#define STM32_I2C_OAR2(n) REG16(stm32_i2c_reg(n, 0x0C)) -#define STM32_I2C_OAR2_ENDUAL BIT(0) -#define STM32_I2C_DR(n) REG16(stm32_i2c_reg(n, 0x10)) -#define STM32_I2C_SR1(n) REG16(stm32_i2c_reg(n, 0x14)) -#define STM32_I2C_SR1_SB BIT(0) -#define STM32_I2C_SR1_ADDR BIT(1) -#define STM32_I2C_SR1_BTF BIT(2) -#define STM32_I2C_SR1_STOPF BIT(4) -#define STM32_I2C_SR1_RXNE BIT(6) -#define STM32_I2C_SR1_TXE BIT(7) -#define STM32_I2C_SR1_BERR BIT(8) -#define STM32_I2C_SR1_ARLO BIT(9) -#define STM32_I2C_SR1_AF BIT(10) - -#define STM32_I2C_SR2(n) REG16(stm32_i2c_reg(n, 0x18)) -#define STM32_I2C_SR2_BUSY BIT(1) -#define STM32_I2C_SR2_TRA BIT(2) -#define STM32_I2C_SR2_DUALF BIT(7) - -#define STM32_I2C_CCR(n) REG16(stm32_i2c_reg(n, 0x1C)) -#define STM32_I2C_CCR_DUTY BIT(14) -#define STM32_I2C_CCR_FM BIT(15) -#define STM32_I2C_TRISE(n) REG16(stm32_i2c_reg(n, 0x20)) - +#define STM32_I2C_CR1(n) REG16(stm32_i2c_reg(n, 0x00)) +#define STM32_I2C_CR1_PE BIT(0) +#define STM32_I2C_CR1_START BIT(8) +#define STM32_I2C_CR1_STOP BIT(9) +#define STM32_I2C_CR1_ACK BIT(10) +#define STM32_I2C_CR1_POS BIT(11) +#define STM32_I2C_CR1_SWRST BIT(15) +#define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04)) +#define STM32_I2C_CR2_ITERREN BIT(8) +#define STM32_I2C_CR2_ITEVTEN BIT(9) +#define STM32_I2C_CR2_ITBUFEN BIT(10) +#define STM32_I2C_CR2_DMAEN BIT(11) +#define STM32_I2C_CR2_LAST BIT(12) +#define STM32_I2C_OAR1(n) REG16(stm32_i2c_reg(n, 0x08)) +#define STM32_I2C_OAR1_B14 BIT(14) +#define STM32_I2C_OAR2(n) REG16(stm32_i2c_reg(n, 0x0C)) +#define STM32_I2C_OAR2_ENDUAL BIT(0) +#define STM32_I2C_DR(n) REG16(stm32_i2c_reg(n, 0x10)) +#define STM32_I2C_SR1(n) REG16(stm32_i2c_reg(n, 0x14)) +#define STM32_I2C_SR1_SB BIT(0) +#define STM32_I2C_SR1_ADDR BIT(1) +#define STM32_I2C_SR1_BTF BIT(2) +#define STM32_I2C_SR1_STOPF BIT(4) +#define STM32_I2C_SR1_RXNE BIT(6) +#define STM32_I2C_SR1_TXE BIT(7) +#define STM32_I2C_SR1_BERR BIT(8) +#define STM32_I2C_SR1_ARLO BIT(9) +#define STM32_I2C_SR1_AF BIT(10) + +#define STM32_I2C_SR2(n) REG16(stm32_i2c_reg(n, 0x18)) +#define STM32_I2C_SR2_BUSY BIT(1) +#define STM32_I2C_SR2_TRA BIT(2) +#define STM32_I2C_SR2_DUALF BIT(7) + +#define STM32_I2C_CCR(n) REG16(stm32_i2c_reg(n, 0x1C)) +#define STM32_I2C_CCR_DUTY BIT(14) +#define STM32_I2C_CCR_FM BIT(15) +#define STM32_I2C_TRISE(n) REG16(stm32_i2c_reg(n, 0x20)) /* --- Power / Reset / Clocks --- */ -#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) - - -#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) -#define STM32_RCC_CR_HSION BIT(0) -#define STM32_RCC_CR_HSIRDY BIT(1) -#define STM32_RCC_CR_MSION BIT(8) -#define STM32_RCC_CR_MSIRDY BIT(9) -#define STM32_RCC_CR_PLLON BIT(24) -#define STM32_RCC_CR_PLLRDY BIT(25) -#define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x04) -#define STM32_RCC_ICSCR_MSIRANGE(n) ((n) << 13) -#define STM32_RCC_ICSCR_MSIRANGE_1MHZ STM32_RCC_ICSCR_MSIRANGE(4) -#define STM32_RCC_ICSCR_MSIRANGE_2MHZ STM32_RCC_ICSCR_MSIRANGE(5) -#define STM32_RCC_ICSCR_MSIRANGE_MASK STM32_RCC_ICSCR_MSIRANGE(7) -#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) -#define STM32_RCC_CFGR_SW_MSI (0 << 0) -#define STM32_RCC_CFGR_SW_HSI (1 << 0) -#define STM32_RCC_CFGR_SW_HSE (2 << 0) -#define STM32_RCC_CFGR_SW_PLL (3 << 0) -#define STM32_RCC_CFGR_SW_MASK (3 << 0) -#define STM32_RCC_CFGR_SWS_MSI (0 << 2) -#define STM32_RCC_CFGR_SWS_HSI (1 << 2) -#define STM32_RCC_CFGR_SWS_HSE (2 << 2) -#define STM32_RCC_CFGR_SWS_PLL (3 << 2) -#define STM32_RCC_CFGR_SWS_MASK (3 << 2) -#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x0C) -#define STM32_RCC_AHBRSTR REG32(STM32_RCC_BASE + 0x10) -#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x14) -#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x18) -#define STM32_RCC_AHBENR REG32(STM32_RCC_BASE + 0x1C) -#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x20) -#define STM32_RCC_SYSCFGEN BIT(0) - -#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x24) -#define STM32_RCC_PWREN BIT(28) - -#define STM32_RCC_AHBLPENR REG32(STM32_RCC_BASE + 0x28) -#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x2C) -#define STM32_RCC_APB1LPENR REG32(STM32_RCC_BASE + 0x30) -#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x34) - -#define STM32_RCC_HB_DMA1 BIT(24) -#define STM32_RCC_PB2_TIM9 BIT(2) -#define STM32_RCC_PB2_TIM10 BIT(3) -#define STM32_RCC_PB2_TIM11 BIT(4) -#define STM32_RCC_PB1_USB BIT(23) - -#define STM32_SYSCFG_MEMRMP REG32(STM32_SYSCFG_BASE + 0x00) -#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04) -#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) - +#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) + +#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) +#define STM32_RCC_CR_HSION BIT(0) +#define STM32_RCC_CR_HSIRDY BIT(1) +#define STM32_RCC_CR_MSION BIT(8) +#define STM32_RCC_CR_MSIRDY BIT(9) +#define STM32_RCC_CR_PLLON BIT(24) +#define STM32_RCC_CR_PLLRDY BIT(25) +#define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x04) +#define STM32_RCC_ICSCR_MSIRANGE(n) ((n) << 13) +#define STM32_RCC_ICSCR_MSIRANGE_1MHZ STM32_RCC_ICSCR_MSIRANGE(4) +#define STM32_RCC_ICSCR_MSIRANGE_2MHZ STM32_RCC_ICSCR_MSIRANGE(5) +#define STM32_RCC_ICSCR_MSIRANGE_MASK STM32_RCC_ICSCR_MSIRANGE(7) +#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) +#define STM32_RCC_CFGR_SW_MSI (0 << 0) +#define STM32_RCC_CFGR_SW_HSI (1 << 0) +#define STM32_RCC_CFGR_SW_HSE (2 << 0) +#define STM32_RCC_CFGR_SW_PLL (3 << 0) +#define STM32_RCC_CFGR_SW_MASK (3 << 0) +#define STM32_RCC_CFGR_SWS_MSI (0 << 2) +#define STM32_RCC_CFGR_SWS_HSI (1 << 2) +#define STM32_RCC_CFGR_SWS_HSE (2 << 2) +#define STM32_RCC_CFGR_SWS_PLL (3 << 2) +#define STM32_RCC_CFGR_SWS_MASK (3 << 2) +#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x0C) +#define STM32_RCC_AHBRSTR REG32(STM32_RCC_BASE + 0x10) +#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x14) +#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x18) +#define STM32_RCC_AHBENR REG32(STM32_RCC_BASE + 0x1C) +#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x20) +#define STM32_RCC_SYSCFGEN BIT(0) + +#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x24) +#define STM32_RCC_PWREN BIT(28) + +#define STM32_RCC_AHBLPENR REG32(STM32_RCC_BASE + 0x28) +#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x2C) +#define STM32_RCC_APB1LPENR REG32(STM32_RCC_BASE + 0x30) +#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x34) + +#define STM32_RCC_HB_DMA1 BIT(24) +#define STM32_RCC_PB2_TIM9 BIT(2) +#define STM32_RCC_PB2_TIM10 BIT(3) +#define STM32_RCC_PB2_TIM11 BIT(4) +#define STM32_RCC_PB1_USB BIT(23) + +#define STM32_SYSCFG_MEMRMP REG32(STM32_SYSCFG_BASE + 0x00) +#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04) +#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) /* Peripheral bits for RCC_APB/AHB and DBGMCU regs */ -#define STM32_RCC_PB2_USART1 BIT(14) +#define STM32_RCC_PB2_USART1 BIT(14) /* Reset causes definitions */ /* Reset causes in RCC CSR register */ #define STM32_RCC_RESET_CAUSE STM32_RCC_CSR -#define RESET_CAUSE_WDG 0x60000000 -#define RESET_CAUSE_SFT 0x10000000 -#define RESET_CAUSE_POR 0x08000000 -#define RESET_CAUSE_PIN 0x04000000 -#define RESET_CAUSE_OTHER 0xfe000000 -#define RESET_CAUSE_RMVF 0x01000000 +#define RESET_CAUSE_WDG 0x60000000 +#define RESET_CAUSE_SFT 0x10000000 +#define RESET_CAUSE_POR 0x08000000 +#define RESET_CAUSE_PIN 0x04000000 +#define RESET_CAUSE_OTHER 0xfe000000 +#define RESET_CAUSE_RMVF 0x01000000 /* Power cause in PWR CSR register */ #define STM32_PWR_RESET_CAUSE STM32_PWR_CSR #define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CR -#define RESET_CAUSE_SBF 0x00000002 -#define RESET_CAUSE_SBF_CLR 0x00000004 +#define RESET_CAUSE_SBF 0x00000002 +#define RESET_CAUSE_SBF_CLR 0x00000004 /* --- Watchdogs --- */ /* --- Real-Time Clock --- */ -#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) -#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) -#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) -#define STM32_RTC_CR_BYPSHAD BIT(5) -#define STM32_RTC_CR_ALRAE BIT(8) -#define STM32_RTC_CR_ALRAIE BIT(12) -#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) -#define STM32_RTC_ISR_ALRAWF BIT(0) -#define STM32_RTC_ISR_RSF BIT(5) -#define STM32_RTC_ISR_INITF BIT(6) -#define STM32_RTC_ISR_INIT BIT(7) -#define STM32_RTC_ISR_ALRAF BIT(8) -#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) -#define STM32_RTC_PRER_A_MASK (0x7f << 16) -#define STM32_RTC_PRER_S_MASK (0x7fff << 0) -#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) -#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) -#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) -#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) -#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) -#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) -#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) -#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) -#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) -#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) -#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) - -#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) -#define STM32_BKP_BYTES 80 +#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) +#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) +#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) +#define STM32_RTC_CR_BYPSHAD BIT(5) +#define STM32_RTC_CR_ALRAE BIT(8) +#define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) +#define STM32_RTC_ISR_ALRAWF BIT(0) +#define STM32_RTC_ISR_RSF BIT(5) +#define STM32_RTC_ISR_INITF BIT(6) +#define STM32_RTC_ISR_INIT BIT(7) +#define STM32_RTC_ISR_ALRAF BIT(8) +#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) +#define STM32_RTC_PRER_A_MASK (0x7f << 16) +#define STM32_RTC_PRER_S_MASK (0x7fff << 0) +#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) +#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) +#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) +#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) +#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) +#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) +#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) +#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) +#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) +#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) +#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) + +#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) +#define STM32_BKP_BYTES 80 /* --- SPI --- */ @@ -424,15 +416,15 @@ struct stm32_spi_regs { uint16_t _pad0; uint16_t cr2; uint16_t _pad1; - unsigned sr; + unsigned int sr; uint8_t dr; uint8_t _pad2; uint16_t _pad3; - unsigned crcpr; - unsigned rxcrcr; - unsigned txcrcr; - unsigned i2scfgr; /* STM32L only */ - unsigned i2spr; /* STM32L only */ + unsigned int crcpr; + unsigned int rxcrcr; + unsigned int txcrcr; + unsigned int i2scfgr; /* STM32L only */ + unsigned int i2spr; /* STM32L only */ }; /* Must be volatile, or compiler optimizes out repeated accesses */ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; @@ -442,146 +434,144 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_SPI3_REGS ((stm32_spi_regs_t *)STM32_SPI3_BASE) #define STM32_SPI4_REGS ((stm32_spi_regs_t *)STM32_SPI4_BASE) -#define STM32_SPI_CR1_BIDIMODE BIT(15) -#define STM32_SPI_CR1_BIDIOE BIT(14) -#define STM32_SPI_CR1_CRCEN BIT(13) -#define STM32_SPI_CR1_SSM BIT(9) -#define STM32_SPI_CR1_SSI BIT(8) -#define STM32_SPI_CR1_LSBFIRST BIT(7) -#define STM32_SPI_CR1_SPE BIT(6) -#define STM32_SPI_CR1_BR_DIV64R (5 << 3) -#define STM32_SPI_CR1_BR_DIV4R BIT(3) -#define STM32_SPI_CR1_MSTR BIT(2) -#define STM32_SPI_CR1_CPOL BIT(1) -#define STM32_SPI_CR1_CPHA BIT(0) -#define STM32_SPI_CR2_FRXTH BIT(12) -#define STM32_SPI_CR2_DATASIZE(n) (((n) - 1) << 8) -#define STM32_SPI_CR2_TXEIE BIT(7) -#define STM32_SPI_CR2_RXNEIE BIT(6) -#define STM32_SPI_CR2_NSSP BIT(3) -#define STM32_SPI_CR2_SSOE BIT(2) -#define STM32_SPI_CR2_TXDMAEN BIT(1) -#define STM32_SPI_CR2_RXDMAEN BIT(0) - -#define STM32_SPI_SR_RXNE BIT(0) -#define STM32_SPI_SR_TXE BIT(1) -#define STM32_SPI_SR_CRCERR BIT(4) -#define STM32_SPI_SR_BSY BIT(7) -#define STM32_SPI_SR_FRLVL (3 << 9) -#define STM32_SPI_SR_FTLVL (3 << 11) +#define STM32_SPI_CR1_BIDIMODE BIT(15) +#define STM32_SPI_CR1_BIDIOE BIT(14) +#define STM32_SPI_CR1_CRCEN BIT(13) +#define STM32_SPI_CR1_SSM BIT(9) +#define STM32_SPI_CR1_SSI BIT(8) +#define STM32_SPI_CR1_LSBFIRST BIT(7) +#define STM32_SPI_CR1_SPE BIT(6) +#define STM32_SPI_CR1_BR_DIV64R (5 << 3) +#define STM32_SPI_CR1_BR_DIV4R BIT(3) +#define STM32_SPI_CR1_MSTR BIT(2) +#define STM32_SPI_CR1_CPOL BIT(1) +#define STM32_SPI_CR1_CPHA BIT(0) +#define STM32_SPI_CR2_FRXTH BIT(12) +#define STM32_SPI_CR2_DATASIZE(n) (((n)-1) << 8) +#define STM32_SPI_CR2_TXEIE BIT(7) +#define STM32_SPI_CR2_RXNEIE BIT(6) +#define STM32_SPI_CR2_NSSP BIT(3) +#define STM32_SPI_CR2_SSOE BIT(2) +#define STM32_SPI_CR2_TXDMAEN BIT(1) +#define STM32_SPI_CR2_RXDMAEN BIT(0) + +#define STM32_SPI_SR_RXNE BIT(0) +#define STM32_SPI_SR_TXE BIT(1) +#define STM32_SPI_SR_CRCERR BIT(4) +#define STM32_SPI_SR_BSY BIT(7) +#define STM32_SPI_SR_FRLVL (3 << 9) +#define STM32_SPI_SR_FTLVL (3 << 11) /* --- Debug --- */ -#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) -#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) +#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) +#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) /* --- Flash --- */ -#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) -#define STM32_FLASH_ACR_LATENCY BIT(0) -#define STM32_FLASH_ACR_PRFTEN BIT(1) -#define STM32_FLASH_ACR_ACC64 BIT(2) -#define STM32_FLASH_PECR REG32(STM32_FLASH_REGS_BASE + 0x04) -#define STM32_FLASH_PECR_PE_LOCK BIT(0) -#define STM32_FLASH_PECR_PRG_LOCK BIT(1) -#define STM32_FLASH_PECR_OPT_LOCK BIT(2) -#define STM32_FLASH_PECR_PROG BIT(3) -#define STM32_FLASH_PECR_ERASE BIT(9) -#define STM32_FLASH_PECR_FPRG BIT(10) -#define STM32_FLASH_PECR_OBL_LAUNCH BIT(18) -#define STM32_FLASH_PDKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) -#define STM32_FLASH_PEKEYR REG32(STM32_FLASH_REGS_BASE + 0x0c) -#define STM32_FLASH_PEKEYR_KEY1 0x89ABCDEF -#define STM32_FLASH_PEKEYR_KEY2 0x02030405 -#define STM32_FLASH_PRGKEYR REG32(STM32_FLASH_REGS_BASE + 0x10) -#define STM32_FLASH_PRGKEYR_KEY1 0x8C9DAEBF -#define STM32_FLASH_PRGKEYR_KEY2 0x13141516 -#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x14) -#define STM32_FLASH_OPTKEYR_KEY1 0xFBEAD9C8 -#define STM32_FLASH_OPTKEYR_KEY2 0x24252627 -#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x18) -#define STM32_FLASH_OBR REG32(STM32_FLASH_REGS_BASE + 0x1c) -#define STM32_FLASH_WRPR REG32(STM32_FLASH_REGS_BASE + 0x20) - -#define STM32_OPTB_RDP 0x00 -#define STM32_OPTB_USER 0x04 -#define STM32_OPTB_WRP1L 0x08 -#define STM32_OPTB_WRP1H 0x0c -#define STM32_OPTB_WRP2L 0x10 -#define STM32_OPTB_WRP2H 0x14 -#define STM32_OPTB_WRP3L 0x18 -#define STM32_OPTB_WRP3H 0x1c +#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) +#define STM32_FLASH_ACR_LATENCY BIT(0) +#define STM32_FLASH_ACR_PRFTEN BIT(1) +#define STM32_FLASH_ACR_ACC64 BIT(2) +#define STM32_FLASH_PECR REG32(STM32_FLASH_REGS_BASE + 0x04) +#define STM32_FLASH_PECR_PE_LOCK BIT(0) +#define STM32_FLASH_PECR_PRG_LOCK BIT(1) +#define STM32_FLASH_PECR_OPT_LOCK BIT(2) +#define STM32_FLASH_PECR_PROG BIT(3) +#define STM32_FLASH_PECR_ERASE BIT(9) +#define STM32_FLASH_PECR_FPRG BIT(10) +#define STM32_FLASH_PECR_OBL_LAUNCH BIT(18) +#define STM32_FLASH_PDKEYR REG32(STM32_FLASH_REGS_BASE + 0x08) +#define STM32_FLASH_PEKEYR REG32(STM32_FLASH_REGS_BASE + 0x0c) +#define STM32_FLASH_PEKEYR_KEY1 0x89ABCDEF +#define STM32_FLASH_PEKEYR_KEY2 0x02030405 +#define STM32_FLASH_PRGKEYR REG32(STM32_FLASH_REGS_BASE + 0x10) +#define STM32_FLASH_PRGKEYR_KEY1 0x8C9DAEBF +#define STM32_FLASH_PRGKEYR_KEY2 0x13141516 +#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x14) +#define STM32_FLASH_OPTKEYR_KEY1 0xFBEAD9C8 +#define STM32_FLASH_OPTKEYR_KEY2 0x24252627 +#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x18) +#define STM32_FLASH_OBR REG32(STM32_FLASH_REGS_BASE + 0x1c) +#define STM32_FLASH_WRPR REG32(STM32_FLASH_REGS_BASE + 0x20) + +#define STM32_OPTB_RDP 0x00 +#define STM32_OPTB_USER 0x04 +#define STM32_OPTB_WRP1L 0x08 +#define STM32_OPTB_WRP1H 0x0c +#define STM32_OPTB_WRP2L 0x10 +#define STM32_OPTB_WRP2H 0x14 +#define STM32_OPTB_WRP3L 0x18 +#define STM32_OPTB_WRP3H 0x1c /* --- External Interrupts --- */ -#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) -#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) -#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) -#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) -#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) -#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) - +#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) +#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) +#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) +#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) +#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) +#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) /* --- ADC --- */ -#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00) -#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04) -#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08) -#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x0C) -#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x10) -#define STM32_ADC_SMPR3 REG32(STM32_ADC1_BASE + 0x14) -#define STM32_ADC_JOFR1 REG32(STM32_ADC1_BASE + 0x18) -#define STM32_ADC_JOFR2 REG32(STM32_ADC1_BASE + 0x1C) -#define STM32_ADC_JOFR3 REG32(STM32_ADC1_BASE + 0x20) -#define STM32_ADC_JOFR4 REG32(STM32_ADC1_BASE + 0x24) -#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x28) -#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x2C) -#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x2C + (n) * 4) -#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x30) -#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x34) -#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x38) -#define STM32_ADC_SQR4 REG32(STM32_ADC1_BASE + 0x3C) -#define STM32_ADC_SQR5 REG32(STM32_ADC1_BASE + 0x40) -#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x44) -#define STM32_ADC_JDR1 REG32(STM32_ADC1_BASE + 0x48) -#define STM32_ADC_JDR2 REG32(STM32_ADC1_BASE + 0x4C) -#define STM32_ADC_JDR3 REG32(STM32_ADC1_BASE + 0x50) -#define STM32_ADC_JDR3 REG32(STM32_ADC1_BASE + 0x50) -#define STM32_ADC_JDR4 REG32(STM32_ADC1_BASE + 0x54) -#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x58) -#define STM32_ADC_SMPR0 REG32(STM32_ADC1_BASE + 0x5C) - -#define STM32_ADC_CCR REG32(STM32_ADC_BASE + 0x04) +#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00) +#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04) +#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08) +#define STM32_ADC_SMPR1 REG32(STM32_ADC1_BASE + 0x0C) +#define STM32_ADC_SMPR2 REG32(STM32_ADC1_BASE + 0x10) +#define STM32_ADC_SMPR3 REG32(STM32_ADC1_BASE + 0x14) +#define STM32_ADC_JOFR1 REG32(STM32_ADC1_BASE + 0x18) +#define STM32_ADC_JOFR2 REG32(STM32_ADC1_BASE + 0x1C) +#define STM32_ADC_JOFR3 REG32(STM32_ADC1_BASE + 0x20) +#define STM32_ADC_JOFR4 REG32(STM32_ADC1_BASE + 0x24) +#define STM32_ADC_HTR REG32(STM32_ADC1_BASE + 0x28) +#define STM32_ADC_LTR REG32(STM32_ADC1_BASE + 0x2C) +#define STM32_ADC_SQR(n) REG32(STM32_ADC1_BASE + 0x2C + (n)*4) +#define STM32_ADC_SQR1 REG32(STM32_ADC1_BASE + 0x30) +#define STM32_ADC_SQR2 REG32(STM32_ADC1_BASE + 0x34) +#define STM32_ADC_SQR3 REG32(STM32_ADC1_BASE + 0x38) +#define STM32_ADC_SQR4 REG32(STM32_ADC1_BASE + 0x3C) +#define STM32_ADC_SQR5 REG32(STM32_ADC1_BASE + 0x40) +#define STM32_ADC_JSQR REG32(STM32_ADC1_BASE + 0x44) +#define STM32_ADC_JDR1 REG32(STM32_ADC1_BASE + 0x48) +#define STM32_ADC_JDR2 REG32(STM32_ADC1_BASE + 0x4C) +#define STM32_ADC_JDR3 REG32(STM32_ADC1_BASE + 0x50) +#define STM32_ADC_JDR3 REG32(STM32_ADC1_BASE + 0x50) +#define STM32_ADC_JDR4 REG32(STM32_ADC1_BASE + 0x54) +#define STM32_ADC_DR REG32(STM32_ADC1_BASE + 0x58) +#define STM32_ADC_SMPR0 REG32(STM32_ADC1_BASE + 0x5C) + +#define STM32_ADC_CCR REG32(STM32_ADC_BASE + 0x04) /* --- Comparators --- */ -#define STM32_COMP_CSR REG32(STM32_COMP_BASE + 0x00) - -#define STM32_COMP_OUTSEL_TIM2_IC4 (0 << 21) -#define STM32_COMP_OUTSEL_TIM2_OCR (1 << 21) -#define STM32_COMP_OUTSEL_TIM3_IC4 (2 << 21) -#define STM32_COMP_OUTSEL_TIM3_OCR (3 << 21) -#define STM32_COMP_OUTSEL_TIM4_IC4 (4 << 21) -#define STM32_COMP_OUTSEL_TIM4_OCR (5 << 21) +#define STM32_COMP_CSR REG32(STM32_COMP_BASE + 0x00) + +#define STM32_COMP_OUTSEL_TIM2_IC4 (0 << 21) +#define STM32_COMP_OUTSEL_TIM2_OCR (1 << 21) +#define STM32_COMP_OUTSEL_TIM3_IC4 (2 << 21) +#define STM32_COMP_OUTSEL_TIM3_OCR (3 << 21) +#define STM32_COMP_OUTSEL_TIM4_IC4 (4 << 21) +#define STM32_COMP_OUTSEL_TIM4_OCR (5 << 21) #define STM32_COMP_OUTSEL_TIM10_IC1 (6 << 21) -#define STM32_COMP_OUTSEL_NONE (7 << 21) - -#define STM32_COMP_INSEL_NONE (0 << 18) -#define STM32_COMP_INSEL_PB3 (1 << 18) -#define STM32_COMP_INSEL_VREF (2 << 18) -#define STM32_COMP_INSEL_VREF34 (3 << 18) -#define STM32_COMP_INSEL_VREF12 (4 << 18) -#define STM32_COMP_INSEL_VREF14 (5 << 18) -#define STM32_COMP_INSEL_DAC_OUT1 (6 << 18) -#define STM32_COMP_INSEL_DAC_OUT2 (7 << 18) - -#define STM32_COMP_WNDWE BIT(17) -#define STM32_COMP_VREFOUTEN BIT(16) -#define STM32_COMP_CMP2OUT BIT(13) -#define STM32_COMP_SPEED_FAST BIT(12) - -#define STM32_COMP_CMP1OUT BIT(7) -#define STM32_COMP_CMP1EN BIT(4) - -#define STM32_COMP_400KPD BIT(3) -#define STM32_COMP_10KPD BIT(2) -#define STM32_COMP_400KPU BIT(1) -#define STM32_COMP_10KPU BIT(0) - +#define STM32_COMP_OUTSEL_NONE (7 << 21) + +#define STM32_COMP_INSEL_NONE (0 << 18) +#define STM32_COMP_INSEL_PB3 (1 << 18) +#define STM32_COMP_INSEL_VREF (2 << 18) +#define STM32_COMP_INSEL_VREF34 (3 << 18) +#define STM32_COMP_INSEL_VREF12 (4 << 18) +#define STM32_COMP_INSEL_VREF14 (5 << 18) +#define STM32_COMP_INSEL_DAC_OUT1 (6 << 18) +#define STM32_COMP_INSEL_DAC_OUT2 (7 << 18) + +#define STM32_COMP_WNDWE BIT(17) +#define STM32_COMP_VREFOUTEN BIT(16) +#define STM32_COMP_CMP2OUT BIT(13) +#define STM32_COMP_SPEED_FAST BIT(12) + +#define STM32_COMP_CMP1OUT BIT(7) +#define STM32_COMP_CMP1EN BIT(4) + +#define STM32_COMP_400KPD BIT(3) +#define STM32_COMP_10KPD BIT(2) +#define STM32_COMP_400KPU BIT(1) +#define STM32_COMP_10KPU BIT(0) /* --- DMA --- */ @@ -642,11 +632,11 @@ enum dma_channel { /* Registers for a single channel of the DMA controller */ struct stm32_dma_chan { - uint32_t ccr; /* Control */ - uint32_t cndtr; /* Number of data to transfer */ - uint32_t cpar; /* Peripheral address */ - uint32_t cmar; /* Memory address */ - uint32_t reserved; + uint32_t ccr; /* Control */ + uint32_t cndtr; /* Number of data to transfer */ + uint32_t cpar; /* Peripheral address */ + uint32_t cmar; /* Memory address */ + uint32_t reserved; }; /* Always use stm32_dma_chan_t so volatile keyword is included! */ @@ -657,8 +647,8 @@ typedef stm32_dma_chan_t dma_chan_t; /* Registers for the DMA controller */ struct stm32_dma_regs { - uint32_t isr; - uint32_t ifcr; + uint32_t isr; + uint32_t ifcr; stm32_dma_chan_t chan[STM32_DMAC_COUNT]; }; @@ -667,205 +657,124 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_DMA1_REGS ((stm32_dma_regs_t *)STM32_DMA1_BASE) - -#define STM32_DMA_CCR_CHANNEL(channel) (0) +#define STM32_DMA_CCR_CHANNEL(channel) (0) #define STM32_DMA_REGS(channel) STM32_DMA1_REGS /* Bits for DMA controller regs (isr and ifcr) */ -#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) +#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) #define STM32_DMA_ISR_MASK(channel, mask) \ ((mask) << STM32_DMA_CH_OFFSET(channel)) -#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) -#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) -#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) -#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) -#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) - -#define STM32_DMA_GIF BIT(0) -#define STM32_DMA_TCIF BIT(1) -#define STM32_DMA_HTIF BIT(2) -#define STM32_DMA_TEIF BIT(3) -#define STM32_DMA_ALL 0xf - -#define STM32_DMA_GET_ISR(channel) \ - ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_ISR(channel, val) \ - (STM32_DMA_REGS(channel)->isr = \ - ((STM32_DMA_REGS(channel)->isr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) -#define STM32_DMA_GET_IFCR(channel) \ - ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_IFCR(channel, val) \ - (STM32_DMA_REGS(channel)->ifcr = \ - ((STM32_DMA_REGS(channel)->ifcr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) - +#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) +#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) +#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) +#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) +#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) + +#define STM32_DMA_GIF BIT(0) +#define STM32_DMA_TCIF BIT(1) +#define STM32_DMA_HTIF BIT(2) +#define STM32_DMA_TEIF BIT(3) +#define STM32_DMA_ALL 0xf + +#define STM32_DMA_GET_ISR(channel) \ + ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_ISR(channel, val) \ + (STM32_DMA_REGS(channel)->isr = \ + ((STM32_DMA_REGS(channel)->isr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) +#define STM32_DMA_GET_IFCR(channel) \ + ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_IFCR(channel, val) \ + (STM32_DMA_REGS(channel)->ifcr = \ + ((STM32_DMA_REGS(channel)->ifcr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) /* Bits for DMA channel regs */ -#define STM32_DMA_CCR_EN BIT(0) -#define STM32_DMA_CCR_TCIE BIT(1) -#define STM32_DMA_CCR_HTIE BIT(2) -#define STM32_DMA_CCR_TEIE BIT(3) -#define STM32_DMA_CCR_DIR BIT(4) -#define STM32_DMA_CCR_CIRC BIT(5) -#define STM32_DMA_CCR_PINC BIT(6) -#define STM32_DMA_CCR_MINC BIT(7) -#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) -#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) -#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) -#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) -#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) -#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) -#define STM32_DMA_CCR_PL_LOW (0 << 12) -#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) -#define STM32_DMA_CCR_PL_HIGH (2 << 12) -#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) -#define STM32_DMA_CCR_MEM2MEM BIT(14) - +#define STM32_DMA_CCR_EN BIT(0) +#define STM32_DMA_CCR_TCIE BIT(1) +#define STM32_DMA_CCR_HTIE BIT(2) +#define STM32_DMA_CCR_TEIE BIT(3) +#define STM32_DMA_CCR_DIR BIT(4) +#define STM32_DMA_CCR_CIRC BIT(5) +#define STM32_DMA_CCR_PINC BIT(6) +#define STM32_DMA_CCR_MINC BIT(7) +#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) +#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) +#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) +#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) +#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) +#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) +#define STM32_DMA_CCR_PL_LOW (0 << 12) +#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) +#define STM32_DMA_CCR_PL_HIGH (2 << 12) +#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) +#define STM32_DMA_CCR_MEM2MEM BIT(14) /* --- CRC --- */ -#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) - -#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) -#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) -#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) -#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) - -#define STM32_CRC_CR_RESET BIT(0) -#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) -#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) -#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) -#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) -#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) -#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) -#define STM32_CRC_CR_REV_IN_WORD (3 << 5) -#define STM32_CRC_CR_REV_OUT BIT(7) +#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) + +#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) +#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) +#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) +#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) + +#define STM32_CRC_CR_RESET BIT(0) +#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) +#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) +#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) +#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) +#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) +#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) +#define STM32_CRC_CR_REV_IN_WORD (3 << 5) +#define STM32_CRC_CR_REV_OUT BIT(7) /* --- PMSE --- */ -#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) -#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) -#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) -#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) -#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) -#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) -#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) -#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x) * 4) -#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) -#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) -#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) -#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) -#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) -#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) -#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) -#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) -#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) -#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) -#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) - -/* --- USB --- */ -#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n) * 4) - -#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) - -#define STM32_USB_CNTR_FRES BIT(0) -#define STM32_USB_CNTR_PDWN BIT(1) -#define STM32_USB_CNTR_LP_MODE BIT(2) -#define STM32_USB_CNTR_FSUSP BIT(3) -#define STM32_USB_CNTR_RESUME BIT(4) -#define STM32_USB_CNTR_L1RESUME BIT(5) -#define STM32_USB_CNTR_L1REQM BIT(7) -#define STM32_USB_CNTR_ESOFM BIT(8) -#define STM32_USB_CNTR_SOFM BIT(9) -#define STM32_USB_CNTR_RESETM BIT(10) -#define STM32_USB_CNTR_SUSPM BIT(11) -#define STM32_USB_CNTR_WKUPM BIT(12) -#define STM32_USB_CNTR_ERRM BIT(13) -#define STM32_USB_CNTR_PMAOVRM BIT(14) -#define STM32_USB_CNTR_CTRM BIT(15) - -#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) - -#define STM32_USB_ISTR_EP_ID_MASK (0x000f) -#define STM32_USB_ISTR_DIR BIT(4) -#define STM32_USB_ISTR_L1REQ BIT(7) -#define STM32_USB_ISTR_ESOF BIT(8) -#define STM32_USB_ISTR_SOF BIT(9) -#define STM32_USB_ISTR_RESET BIT(10) -#define STM32_USB_ISTR_SUSP BIT(11) -#define STM32_USB_ISTR_WKUP BIT(12) -#define STM32_USB_ISTR_ERR BIT(13) -#define STM32_USB_ISTR_PMAOVR BIT(14) -#define STM32_USB_ISTR_CTR BIT(15) - -#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) - -#define STM32_USB_FNR_RXDP_RXDM_SHIFT (14) -#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) - -#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) -#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) -#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) -#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) - -#define STM32_USB_BCDR_BCDEN BIT(0) -#define STM32_USB_BCDR_DCDEN BIT(1) -#define STM32_USB_BCDR_PDEN BIT(2) -#define STM32_USB_BCDR_SDEN BIT(3) -#define STM32_USB_BCDR_DCDET BIT(4) -#define STM32_USB_BCDR_PDET BIT(5) -#define STM32_USB_BCDR_SDET BIT(6) -#define STM32_USB_BCDR_PS2DET BIT(7) - -#define EP_MASK 0x0F0F -#define EP_TX_DTOG 0x0040 -#define EP_TX_MASK 0x0030 -#define EP_TX_VALID 0x0030 -#define EP_TX_NAK 0x0020 -#define EP_TX_STALL 0x0010 -#define EP_TX_DISAB 0x0000 -#define EP_RX_DTOG 0x4000 -#define EP_RX_MASK 0x3000 -#define EP_RX_VALID 0x3000 -#define EP_RX_NAK 0x2000 -#define EP_RX_STALL 0x1000 -#define EP_RX_DISAB 0x0000 - -#define EP_STATUS_OUT 0x0100 - -#define EP_TX_RX_MASK (EP_TX_MASK | EP_RX_MASK) -#define EP_TX_RX_VALID (EP_TX_VALID | EP_RX_VALID) - -#define STM32_TOGGLE_EP(n, mask, val, flags) \ - STM32_USB_EP(n) = (((STM32_USB_EP(n) & (EP_MASK | (mask))) \ - ^ (val)) | (flags)) +#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) +#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) +#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) +#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) +#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) +#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) +#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) +#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x)*4) +#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) +#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) +#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) +#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) +#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) +#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) +#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) +#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) +#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) +#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) +#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) /* --- TRNG --- */ -#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) -#define STM32_RNG_CR_RNGEN BIT(2) -#define STM32_RNG_CR_IE BIT(3) -#define STM32_RNG_CR_CED BIT(5) -#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) -#define STM32_RNG_SR_DRDY BIT(0) -#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) +#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) +#define STM32_RNG_CR_RNGEN BIT(2) +#define STM32_RNG_CR_IE BIT(3) +#define STM32_RNG_CR_CED BIT(5) +#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) +#define STM32_RNG_SR_DRDY BIT(0) +#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) /* --- AXI interconnect --- */ /* STM32H7: AXI_TARGx_FN_MOD exists for masters x = 1, 2 and 7 */ -#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + \ - 0x1000 * (x)) -#define WRITE_ISS_OVERRIDE BIT(1) -#define READ_ISS_OVERRIDE BIT(0) +#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + 0x1000 * (x)) +#define WRITE_ISS_OVERRIDE BIT(1) +#define READ_ISS_OVERRIDE BIT(0) /* --- MISC --- */ -#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) -#define STM32_UNIQUE_ID_LENGTH (3 * 4) +#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) +#define STM32_UNIQUE_ID_LENGTH (3 * 4) #endif /* !__ASSEMBLER__ */ diff --git a/chip/stm32/registers-stm32l4.h b/chip/stm32/registers-stm32l4.h index 9fd6302f49..583f0a688a 100644 --- a/chip/stm32/registers-stm32l4.h +++ b/chip/stm32/registers-stm32l4.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,533 +19,1792 @@ #error "This header file should not be included directly." #endif -/* --- IRQ numbers --- */ -#define STM32_IRQ_WWDG 0 -#define STM32_IRQ_PVD 1 -#define STM32_IRQ_TAMPER_STAMP 2 -#define STM32_IRQ_RTC_WAKEUP 3 -#define STM32_IRQ_FLASH 4 -#define STM32_IRQ_RCC 5 -#define STM32_IRQ_EXTI0 6 -#define STM32_IRQ_EXTI1 7 -#define STM32_IRQ_EXTI2 8 -#define STM32_IRQ_EXTI3 9 -#define STM32_IRQ_EXTI4 10 -#define STM32_IRQ_DMA_CHANNEL_1 11 -#define STM32_IRQ_DMA_CHANNEL_2 12 -#define STM32_IRQ_DMA_CHANNEL_3 13 -#define STM32_IRQ_DMA_CHANNEL_4 14 -#define STM32_IRQ_DMA_CHANNEL_5 15 -#define STM32_IRQ_DMA_CHANNEL_6 16 -#define STM32_IRQ_DMA_CHANNEL_7 17 -#define STM32_IRQ_USB_HP 19 -#define STM32_IRQ_USB_LP 20 - -#define STM32_IRQ_ADC1 18 /* STM32L4 only */ -#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */ -#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */ -#define STM32_IRQ_DAC 21 -#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */ - -#define STM32_IRQ_COMP 22 - -#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */ -#define STM32_IRQ_EXTI9_5 23 -#define STM32_IRQ_LCD 24 /* STM32L15X only */ -#define STM32_IRQ_TIM15 24 /* STM32F373 only */ -#define STM32_IRQ_TIM9 25 /* STM32L15X only */ -#define STM32_IRQ_TIM16 25 /* STM32F373 only */ -#define STM32_IRQ_TIM10 26 /* STM32L15X only */ -#define STM32_IRQ_TIM17 26 /* STM32F373 only */ -#define STM32_IRQ_TIM11 27 /* STM32L15X only */ -#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */ -#define STM32_IRQ_TIM2 28 -#define STM32_IRQ_TIM3 29 -#define STM32_IRQ_TIM4 30 -#define STM32_IRQ_I2C1_EV 31 -#define STM32_IRQ_I2C1_ER 32 -#define STM32_IRQ_I2C2_EV 33 -#define STM32_IRQ_I2C2_ER 34 -#define STM32_IRQ_SPI1 35 -#define STM32_IRQ_SPI2 36 -#define STM32_IRQ_USART1 37 -#define STM32_IRQ_USART2 38 -#define STM32_IRQ_USART3 39 -#define STM32_IRQ_EXTI15_10 40 -#define STM32_IRQ_RTC_ALARM 41 -#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */ -#define STM32_IRQ_CEC 42 /* STM32F373 only */ -#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */ -#define STM32_IRQ_TIM12 43 /* STM32F373 only */ -#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */ -#define STM32_IRQ_TIM13 44 /* STM32F373 only */ -#define STM32_IRQ_TIM14 45 /* STM32F373 only */ -#define STM32_IRQ_TIM5 50 /* STM32F373 */ -#define STM32_IRQ_SPI3 51 /* STM32F373 */ -#define STM32_IRQ_USART4 52 /* STM32F446 only */ -#define STM32_IRQ_USART5 53 /* STM32F446 only */ -#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */ -#define STM32_IRQ_TIM7 55 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */ -#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */ -/* if MISC_REMAP bits are set */ -#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */ -#define STM32_IRQ_SDADC1 61 /* STM32F373 only */ -#define STM32_IRQ_SDADC2 62 /* STM32F373 only */ -#define STM32_IRQ_SDADC3 63 /* STM32F373 only */ -#define STM32_IRQ_DMA2_CHANNEL6 68 /* STM32L4 only */ -#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */ -#define STM32_IRQ_LPUART 70 /* STM32L4 only */ -#define STM32_IRQ_USART9 70 /* STM32L4 only */ -#define STM32_IRQ_USART6 71 /* STM32F446 only */ -#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */ -#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */ -#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */ -#define STM32_IRQ_TIM19 78 /* STM32F373 only */ -#define STM32_IRQ_AES 79 /* STM32L4 only */ -#define STM32_IRQ_RNG 80 /* STM32L4 only */ -#define STM32_IRQ_FPU 81 /* STM32F373 only */ - +/****** STM32 specific Interrupt Numbers ********/ +#define STM32_IRQ_WWDG 0 +#define STM32_IRQ_PVD_PVM 1 +#define STM32_IRQ_TAMP_STAMP 2 +#define STM32_IRQ_RTC_WKUP 3 +#define STM32_IRQ_FLASH 4 +#define STM32_IRQ_RCC 5 +#define STM32_IRQ_EXTI0 6 +#define STM32_IRQ_EXTI1 7 +#define STM32_IRQ_EXTI2 8 +#define STM32_IRQ_EXTI3 9 +#define STM32_IRQ_EXTI4 10 +#define STM32_IRQ_DMA_CHANNEL_1 11 +#define STM32_IRQ_DMA_CHANNEL_2 12 +#define STM32_IRQ_DMA_CHANNEL_3 13 +#define STM32_IRQ_DMA_CHANNEL_4 14 +#define STM32_IRQ_DMA_CHANNEL_5 15 +#define STM32_IRQ_DMA_CHANNEL_6 16 +#define STM32_IRQ_DMA_CHANNEL_7 17 +#define STM32_IRQ_ADC1 18 +#define STM32_IRQ_CAN1_TX 19 +#define STM32_IRQ_CAN1_RX0 20 +#define STM32_IRQ_CAN1_RX1 21 +#define STM32_IRQ_CAN1_SCE 22 +#define STM32_IRQ_EXTI9_5 23 +#define STM32_IRQ_TIM1_BRK_TIM15 24 +#define STM32_IRQ_TIM1_UP_TIM16 25 +#define STM32_IRQ_TIM1_TRG_COM 26 +#define STM32_IRQ_TIM1_CC 27 +#define STM32_IRQ_TIM2 28 +#define STM32_IRQ_I2C1_EV 31 +#define STM32_IRQ_I2C1_ER 32 +#define STM32_IRQ_I2C2_EV 33 +#define STM32_IRQ_I2C2_ER 34 +#define STM32_IRQ_SPI1 35 +#define STM32_IRQ_SPI2 36 +#define STM32_IRQ_USART1 37 +#define STM32_IRQ_USART2 38 +#define STM32_IRQ_USART3 39 +#define STM32_IRQ_EXTI15_10 40 +#define STM32_IRQ_RTC_ALARM 41 +#define STM32_IRQ_SDMMC1 49 +#define STM32_IRQ_TIM5 50 +#define STM32_IRQ_SPI3 51 +#define STM32_IRQ_TIM6_DAC 54 +#define STM32_IRQ_TIM7 55 +#define STM32_IRQ_DMA2_CHANNEL1 56 +#define STM32_IRQ_DMA2_CHANNEL2 57 +#define STM32_IRQ_DMA2_CHANNEL3 58 +#define STM32_IRQ_DMA2_CHANNEL4 59 +#define STM32_IRQ_DMA2_CHANNEL5 60 +#define STM32_IRQ_COMP 64 +#define LSTM32_IRQ_PTIM1 65 +#define STM32_IRQ_LPTIM2 66 +#define STM32_IRQ_DMA2_CHANNEL6 68 +#define STM32_IRQ_DMA2_CHANNEL7 69 +#define STM32_IRQ_LPUART1 70 +#define STM32_IRQ_QUADSPI 71 +#define STM32_IRQ_I2C3_EV 72 +#define STM32_IRQ_I2C3_ER 73 +#define STM32_IRQ_SAI1 74 +#define STM32_IRQ_SWPMI1 76 +#define STM32_IRQ_TSC 77 +#define STM32_IRQ_RNG 80 +#define STM32_IRQ_FPU 81 +#define STM32_IRQ_CRS 82 /* To simplify code generation, define DMA channel 9..10 */ -#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 -#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 -#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL6 -#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL7 - -/* aliases for easier code sharing */ -#define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV -#define STM32_IRQ_I2C2 STM32_IRQ_I2C2_EV -#define STM32_IRQ_I2C3 STM32_IRQ_I2C3_EV - - +#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 +#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 +#define STM32_IRQ_DMA_CHANNEL_11 STM32_IRQ_DMA2_CHANNEL3 +#define STM32_IRQ_DMA_CHANNEL_12 STM32_IRQ_DMA2_CHANNEL4 +#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL5 +#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL6 +#define STM32_IRQ_DMA_CHANNEL_15 STM32_IRQ_DMA2_CHANNEL7 +#define STM32_IRQ_USART9 STM32_IRQ_LPUART1 /* Peripheral base addresses */ -#define STM32_ADC1_BASE 0x40012400 -#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */ - -#define STM32_CEC_BASE 0x40007800 /* STM32F373 */ -#define STM32_CRC_BASE 0x40023000 -#define STM32_CRS_BASE 0x40006c00 /* STM32F0XX */ -#define STM32_DAC_BASE 0x40007400 - - -#define STM32_DBGMCU_BASE 0xE0042000 - -#define STM32_DMA1_BASE 0x40020000 -#define STM32_DMA2_BASE 0x40020400 - -#define STM32_EXTI_BASE 0x40010400 - -#define STM32_FLASH_REGS_BASE 0x40022000 - -#define STM32_GPIOA_BASE 0x48000000 -#define STM32_GPIOB_BASE 0x48000400 -#define STM32_GPIOC_BASE 0x48000800 -#define STM32_GPIOD_BASE 0x48000C00 -#define STM32_GPIOE_BASE 0x48001000 -#define STM32_GPIOF_BASE 0x48001400 -#define STM32_GPIOG_BASE 0x48001800 /* only for stm32l4x6 */ -#define STM32_GPIOH_BASE 0x48001C00 /* only for stm32l4 */ - -#define STM32_I2C1_BASE 0x40005400 -#define STM32_I2C2_BASE 0x40005800 -#define STM32_I2C3_BASE 0x40005C00 -#define STM32_I2C4_BASE 0x40006000 - -#define STM32_IWDG_BASE 0x40003000 -#define STM32_LCD_BASE 0x40002400 - -#define STM32_OPTB_BASE 0x1FFF7800 - -#define STM32_PMSE_BASE 0x40013400 -#define STM32_PWR_BASE 0x40007000 - -#define STM32_RCC_BASE 0x40021000 - -#define STM32_RI_BASE 0x40007C00 /* STM32L1xx only */ -#define STM32_RNG_BASE 0x50060800 /* STM32L4 */ -#define STM32_RTC_BASE 0x40002800 - -#define STM32_SPI1_BASE 0x40013000 -#define STM32_SPI2_BASE 0x40003800 -#define STM32_SPI3_BASE 0x40003c00 /* STM32F373, STM32L4, STM32F7 */ - -#define STM32_SYSCFG_BASE 0x40010000 - -#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */ -#define STM32_TIM2_BASE 0x40000000 -#define STM32_TIM3_BASE 0x40000400 -#define STM32_TIM4_BASE 0x40000800 -#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */ -#define STM32_TIM6_BASE 0x40001000 -#define STM32_TIM7_BASE 0x40001400 -#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */ -#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */ -#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */ -#define STM32_TIM15_BASE 0x40014000 -#define STM32_TIM16_BASE 0x40014400 -#define STM32_TIM17_BASE 0x40014800 -#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */ -#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */ - -#define STM32_UNIQUE_ID_BASE 0x1ffff7ac - -#define STM32_USART1_BASE 0x40013800 -#define STM32_USART2_BASE 0x40004400 -#define STM32_USART3_BASE 0x40004800 -#define STM32_USART4_BASE 0x40004c00 -#define STM32_USART9_BASE 0x40008000 /* LPUART */ - -#define STM32_USB_CAN_SRAM_BASE 0x40006000 -#define STM32_USB_FS_BASE 0x40005C00 - -#define STM32_WWDG_BASE 0x40002C00 - +#define FLASH_BASE 0x08000000UL +#define FLASH_END 0x0803FFFFUL +#define FLASH_BANK1_END 0x0803FFFFUL +#define SRAM1_BASE 0x20000000UL +#define SRAM2_BASE 0x10000000UL +#define PERIPH_BASE 0x40000000UL +#define QSPI_BASE 0x90000000UL +#define QSPI_R_BASE 0xA0001000UL +#define SRAM1_BB_BASE 0x22000000UL +#define PERIPH_BB_BASE 0x42000000UL + +/* Legacy defines */ +#define SRAM_BASE SRAM1_BASE +#define SRAM_BB_BASE SRAM1_BB_BASE +#define SRAM1_SIZE_MAX 0x0000C000UL +#define SRAM2_SIZE 0x00004000UL +#define FLASH_SIZE_DATA_REGISTER ((uint32_t)0x1FFF75E0) +#define FLASH_SIZE \ + (((((*((uint32_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0000FFFFU)) == \ + 0x0000FFFFU)) ? \ + (0x100U << 10U) : \ + (((*((uint32_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0000FFFFU)) \ + << 10U)) + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000UL) + +/*!< APB1 peripherals */ +#define STM32_TIM2_BASE (APB1PERIPH_BASE + 0x0000UL) +#define STM32_TIM5_BASE (APB1PERIPH_BASE + 0x0C00UL) +#define STM32_TIM6_BASE (APB1PERIPH_BASE + 0x1000UL) +#define STM32_TIM7_BASE (APB1PERIPH_BASE + 0x1400UL) +#define STM32_RTC_BASE (APB1PERIPH_BASE + 0x2800UL) +#define STM32_WWDG_BASE (APB1PERIPH_BASE + 0x2C00UL) +#define STM32_IWDG_BASE (APB1PERIPH_BASE + 0x3000UL) +#define STM32_SPI2_BASE (APB1PERIPH_BASE + 0x3800UL) +#define STM32_SPI3_BASE (APB1PERIPH_BASE + 0x3C00UL) +#define STM32_USART2_BASE (APB1PERIPH_BASE + 0x4400UL) +#define STM32_USART3_BASE (APB1PERIPH_BASE + 0x4800UL) +#define STM32_I2C1_BASE (APB1PERIPH_BASE + 0x5400UL) +#define STM32_I2C2_BASE (APB1PERIPH_BASE + 0x5800UL) +#define STM32_I2C3_BASE (APB1PERIPH_BASE + 0x5C00UL) +#define STM32_CRS_BASE (APB1PERIPH_BASE + 0x6000UL) +#define STM32_CAN1_BASE (APB1PERIPH_BASE + 0x6400UL) +#define STM32_PWR_BASE (APB1PERIPH_BASE + 0x7000UL) +#define STM32_DAC_BASE (APB1PERIPH_BASE + 0x7400UL) +#define STM32_DAC1_BASE (APB1PERIPH_BASE + 0x7400UL) +#define STM32_OPAMP_BASE (APB1PERIPH_BASE + 0x7800UL) +#define STM32_OPAMP1_BASE (APB1PERIPH_BASE + 0x7800UL) +#define STM32_LPTIM1_BASE (APB1PERIPH_BASE + 0x7C00UL) +#define STM32_LPUART1_BASE (APB1PERIPH_BASE + 0x8000UL) +#define STM32_I2C4_BASE (APB1PERIPH_BASE + 0x8400UL) +#define STM32_SWPMI1_BASE (APB1PERIPH_BASE + 0x8800UL) +#define STM32_LPTIM2_BASE (APB1PERIPH_BASE + 0x9400UL) + +#define STM32_USART9_BASE STM32_LPUART1_BASE + +/*!< APB2 peripherals */ +#define STM32_SYSCFG_BASE (APB2PERIPH_BASE + 0x0000UL) +#define STM32_VREFBUF_BASE (APB2PERIPH_BASE + 0x0030UL) +#define STM32_OMP1_BASE (APB2PERIPH_BASE + 0x0200UL) +#define STM32_COMP2_BASE (APB2PERIPH_BASE + 0x0204UL) +#define STM32_EXTI_BASE (APB2PERIPH_BASE + 0x0400UL) +#define STM32_FIREWALL_BASE (APB2PERIPH_BASE + 0x1C00UL) +#define STM32_SDMMC1_BASE (APB2PERIPH_BASE + 0x2800UL) +#define STM32_TIM1_BASE (APB2PERIPH_BASE + 0x2C00UL) +#define STM32_SPI1_BASE (APB2PERIPH_BASE + 0x3000UL) +#define STM32_USART1_BASE (APB2PERIPH_BASE + 0x3800UL) +#define STM32_TIM15_BASE (APB2PERIPH_BASE + 0x4000UL) +#define STM32_TIM16_BASE (APB2PERIPH_BASE + 0x4400UL) +#define STM32_SAI1_BASE (APB2PERIPH_BASE + 0x5400UL) +#define STM32_SAI1_Block_A_BASE (SAI1_BASE + 0x0004UL) +#define STM32_SAI1_Block_B_BASE (SAI1_BASE + 0x0024UL) + +/*!< AHB1 peripherals */ +#define STM32_DMA1_BASE (AHB1PERIPH_BASE) +#define STM32_DMA2_BASE (AHB1PERIPH_BASE + 0x0400UL) +#define STM32_RCC_BASE (AHB1PERIPH_BASE + 0x1000UL) +#define STM32_FLASH_R_BASE (AHB1PERIPH_BASE + 0x2000UL) +#define STM32_CRC_BASE (AHB1PERIPH_BASE + 0x3000UL) +#define STM32_TSC_BASE (AHB1PERIPH_BASE + 0x4000UL) +#define STM32_DMA1_Channel1_BASE (DMA1_BASE + 0x0008UL) +#define STM32_DMA1_Channel2_BASE (DMA1_BASE + 0x001CUL) +#define STM32_DMA1_Channel3_BASE (DMA1_BASE + 0x0030UL) +#define STM32_DMA1_Channel4_BASE (DMA1_BASE + 0x0044UL) +#define STM32_DMA1_Channel5_BASE (DMA1_BASE + 0x0058UL) +#define STM32_DMA1_Channel6_BASE (DMA1_BASE + 0x006CUL) +#define STM32_DMA1_Channel7_BASE (DMA1_BASE + 0x0080UL) +#define STM32_DMA1_CSELR_BASE (DMA1_BASE + 0x00A8UL) +#define STM32_DMA2_Channel1_BASE (DMA2_BASE + 0x0008UL) +#define STM32_DMA2_Channel2_BASE (DMA2_BASE + 0x001CUL) +#define STM32_DMA2_Channel3_BASE (DMA2_BASE + 0x0030UL) +#define STM32_DMA2_Channel4_BASE (DMA2_BASE + 0x0044UL) +#define STM32_DMA2_Channel5_BASE (DMA2_BASE + 0x0058UL) +#define STM32_DMA2_Channel6_BASE (DMA2_BASE + 0x006CUL) +#define STM32_DMA2_Channel7_BASE (DMA2_BASE + 0x0080UL) +#define STM32_DMA2_CSELR_BASE (DMA2_BASE + 0x00A8UL) + +/*!< AHB2 peripherals */ +#define STM32_GPIOA_BASE (AHB2PERIPH_BASE + 0x0000UL) +#define STM32_GPIOB_BASE (AHB2PERIPH_BASE + 0x0400UL) +#define STM32_GPIOC_BASE (AHB2PERIPH_BASE + 0x0800UL) +#define STM32_GPIOD_BASE (AHB2PERIPH_BASE + 0x0C00UL) +#define STM32_GPIOE_BASE (AHB2PERIPH_BASE + 0x1000UL) +#define STM32_GPIOF_BASE (AHB2PERIPH_BASE + 0x1400UL) +#define STM32_GPIOG_BASE (AHB2PERIPH_BASE + 0x1800UL) /* stm32l4x6 */ +#define STM32_GPIOH_BASE (AHB2PERIPH_BASE + 0x1C00UL) +#define STM32_ADC1_BASE (AHB2PERIPH_BASE + 0x08040000UL) +#define STM32_ADC1_COMMON_BASE (AHB2PERIPH_BASE + 0x08040300UL) +#define STM32_RNG_BASE (AHB2PERIPH_BASE + 0x08060800UL) + +/* Debug MCU registers base address */ +#define STM32_DBGMCU_BASE 0xE0042000UL +#define STM32_PACKAGE_BASE 0x1FFF7500UL +#define STM32_UID_BASE 0x1FFF7590UL +#define STM32_FLASHSIZE_BASE 0x1FFF75E0UL + +#define STM32_FLASH_REGS_BASE STM32_FLASH_R_BASE +#define STM32_UNIQUE_ID_BASE STM32_UID_BASE +#define STM32_OPTB_BASE 0x1FFF7800 #ifndef __ASSEMBLER__ /* Register definitions */ /* --- USART --- */ -#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) -#define STM32_USART_CR1_UE BIT(0) -#define STM32_USART_CR1_UESM BIT(1) -#define STM32_USART_CR1_RE BIT(2) -#define STM32_USART_CR1_TE BIT(3) -#define STM32_USART_CR1_RXNEIE BIT(5) -#define STM32_USART_CR1_TCIE BIT(6) -#define STM32_USART_CR1_TXEIE BIT(7) -#define STM32_USART_CR1_PS BIT(9) -#define STM32_USART_CR1_PCE BIT(10) -#define STM32_USART_CR1_M BIT(12) -#define STM32_USART_CR1_OVER8 BIT(15) -#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) -#define STM32_USART_CR2_SWAP BIT(15) -#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) -#define STM32_USART_CR3_EIE BIT(0) -#define STM32_USART_CR3_DMAR BIT(6) -#define STM32_USART_CR3_DMAT BIT(7) -#define STM32_USART_CR3_ONEBIT BIT(11) -#define STM32_USART_CR3_OVRDIS BIT(12) -#define STM32_USART_CR3_WUS_START_BIT (2 << 20) -#define STM32_USART_CR3_WUFIE BIT(22) -#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) -#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) -#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) -#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) -#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) -#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) -#define STM32_USART_ICR_ORECF BIT(3) -#define STM32_USART_ICR_TCCF BIT(6) -#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) -#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) -#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) +#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) +#define STM32_USART_CR1_UE BIT(0) +#define STM32_USART_CR1_UESM BIT(1) +#define STM32_USART_CR1_RE BIT(2) +#define STM32_USART_CR1_TE BIT(3) +#define STM32_USART_CR1_RXNEIE BIT(5) +#define STM32_USART_CR1_TCIE BIT(6) +#define STM32_USART_CR1_TXEIE BIT(7) +#define STM32_USART_CR1_PS BIT(9) +#define STM32_USART_CR1_PCE BIT(10) +#define STM32_USART_CR1_M BIT(12) +#define STM32_USART_CR1_OVER8 BIT(15) + +#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) +#define STM32_USART_CR2_SWAP BIT(15) + +#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) +#define STM32_USART_CR3_EIE BIT(0) +#define STM32_USART_CR3_DMAR BIT(6) +#define STM32_USART_CR3_DMAT BIT(7) +#define STM32_USART_CR3_ONEBIT BIT(11) +#define STM32_USART_CR3_OVRDIS BIT(12) +#define STM32_USART_CR3_WUS_START_BIT (2 << 20) +#define STM32_USART_CR3_WUFIE BIT(22) + +#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) +#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) +#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) +#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) +#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) +#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) +#define STM32_USART_ICR_ORECF BIT(3) +#define STM32_USART_ICR_TCCF BIT(6) +#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) +#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) +#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) /* register alias */ -#define STM32_USART_SR(base) STM32_USART_ISR(base) -#define STM32_USART_SR_ORE BIT(3) -#define STM32_USART_SR_RXNE BIT(5) -#define STM32_USART_SR_TC BIT(6) -#define STM32_USART_SR_TXE BIT(7) +#define STM32_USART_SR(base) STM32_USART_ISR(base) +#define STM32_USART_SR_ORE BIT(3) +#define STM32_USART_SR_RXNE BIT(5) +#define STM32_USART_SR_TC BIT(6) +#define STM32_USART_SR_TXE BIT(7) /* --- GPIO --- */ - -#define STM32_GPIO_MODER(b) REG32((b) + 0x00) -#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) -#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) -#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) -#define STM32_GPIO_IDR(b) REG16((b) + 0x10) -#define STM32_GPIO_ODR(b) REG16((b) + 0x14) -#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) -#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) -#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) -#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) -#define STM32_GPIO_BRR(b) REG32((b) + 0x28) -#define STM32_GPIO_ASCR(b) REG32((b) + 0x2C) /* only for stm32l4 */ - -#define GPIO_ALT_F0 0x0 -#define GPIO_ALT_F1 0x1 -#define GPIO_ALT_F2 0x2 -#define GPIO_ALT_F3 0x3 -#define GPIO_ALT_F4 0x4 -#define GPIO_ALT_F5 0x5 -#define GPIO_ALT_F6 0x6 -#define GPIO_ALT_F7 0x7 -#define GPIO_ALT_F8 0x8 -#define GPIO_ALT_F9 0x9 -#define GPIO_ALT_FA 0xA -#define GPIO_ALT_FB 0xB -#define GPIO_ALT_FC 0xC -#define GPIO_ALT_FD 0xD -#define GPIO_ALT_FE 0xE -#define GPIO_ALT_FF 0xF +#define STM32_GPIO_MODER(b) REG32((b) + 0x00) +#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) +#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) +#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) +#define STM32_GPIO_IDR(b) REG16((b) + 0x10) +#define STM32_GPIO_ODR(b) REG16((b) + 0x14) +#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) +#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) +#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) +#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) +#define STM32_GPIO_BRR(b) REG32((b) + 0x28) +#define STM32_GPIO_ASCR(b) REG32((b) + 0x2C) /* only for stm32l4x6 */ + +#define GPIO_ALT_F0 0x0 +#define GPIO_ALT_F1 0x1 +#define GPIO_ALT_F2 0x2 +#define GPIO_ALT_F3 0x3 +#define GPIO_ALT_F4 0x4 +#define GPIO_ALT_F5 0x5 +#define GPIO_ALT_F6 0x6 +#define GPIO_ALT_F7 0x7 +#define GPIO_ALT_F8 0x8 +#define GPIO_ALT_F9 0x9 +#define GPIO_ALT_FA 0xA +#define GPIO_ALT_FB 0xB +#define GPIO_ALT_FC 0xC +#define GPIO_ALT_FD 0xD +#define GPIO_ALT_FE 0xE +#define GPIO_ALT_FF 0xF /* --- I2C --- */ -#define STM32_I2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) -#define STM32_I2C_CR1_PE BIT(0) -#define STM32_I2C_CR1_TXIE BIT(1) -#define STM32_I2C_CR1_RXIE BIT(2) -#define STM32_I2C_CR1_ADDRIE BIT(3) -#define STM32_I2C_CR1_NACKIE BIT(4) -#define STM32_I2C_CR1_STOPIE BIT(5) -#define STM32_I2C_CR1_ERRIE BIT(7) -#define STM32_I2C_CR1_WUPEN BIT(18) -#define STM32_I2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) -#define STM32_I2C_CR2_RD_WRN BIT(10) -#define STM32_I2C_CR2_START BIT(13) -#define STM32_I2C_CR2_STOP BIT(14) -#define STM32_I2C_CR2_NACK BIT(15) -#define STM32_I2C_CR2_RELOAD BIT(24) -#define STM32_I2C_CR2_AUTOEND BIT(25) -#define STM32_I2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) -#define STM32_I2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) -#define STM32_I2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) -#define STM32_I2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) -#define STM32_I2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) -#define STM32_I2C_ISR_TXE BIT(0) -#define STM32_I2C_ISR_TXIS BIT(1) -#define STM32_I2C_ISR_RXNE BIT(2) -#define STM32_I2C_ISR_ADDR BIT(3) -#define STM32_I2C_ISR_NACK BIT(4) -#define STM32_I2C_ISR_STOP BIT(5) -#define STM32_I2C_ISR_TC BIT(6) -#define STM32_I2C_ISR_TCR BIT(7) -#define STM32_I2C_ISR_BERR BIT(8) -#define STM32_I2C_ISR_ARLO BIT(9) -#define STM32_I2C_ISR_OVR BIT(10) -#define STM32_I2C_ISR_PECERR BIT(11) -#define STM32_I2C_ISR_TIMEOUT BIT(12) -#define STM32_I2C_ISR_ALERT BIT(13) -#define STM32_I2C_ISR_BUSY BIT(15) -#define STM32_I2C_ISR_DIR BIT(16) -#define STM32_I2C_ISR_ADDCODE(isr) (((isr) >> 16) & 0xfe) -#define STM32_I2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) -#define STM32_I2C_ICR_ADDRCF BIT(3) -#define STM32_I2C_ICR_NACKCF BIT(4) -#define STM32_I2C_ICR_STOPCF BIT(5) -#define STM32_I2C_ICR_BERRCF BIT(8) -#define STM32_I2C_ICR_ARLOCF BIT(9) -#define STM32_I2C_ICR_OVRCF BIT(10) -#define STM32_I2C_ICR_TIMEOUTCF BIT(12) -#define STM32_I2C_ICR_ALL 0x3F38 -#define STM32_I2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) -#define STM32_I2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) -#define STM32_I2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) - +#define STM32_I2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) +#define STM32_I2C_CR1_PE BIT(0) +#define STM32_I2C_CR1_TXIE BIT(1) +#define STM32_I2C_CR1_RXIE BIT(2) +#define STM32_I2C_CR1_ADDRIE BIT(3) +#define STM32_I2C_CR1_NACKIE BIT(4) +#define STM32_I2C_CR1_STOPIE BIT(5) +#define STM32_I2C_CR1_ERRIE BIT(7) +#define STM32_I2C_CR1_WUPEN BIT(18) +#define STM32_I2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) +#define STM32_I2C_CR2_RD_WRN BIT(10) +#define STM32_I2C_CR2_START BIT(13) +#define STM32_I2C_CR2_STOP BIT(14) +#define STM32_I2C_CR2_NACK BIT(15) +#define STM32_I2C_CR2_RELOAD BIT(24) +#define STM32_I2C_CR2_AUTOEND BIT(25) +#define STM32_I2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) +#define STM32_I2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) +#define STM32_I2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) +#define STM32_I2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) +#define STM32_I2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) +#define STM32_I2C_ISR_TXE BIT(0) +#define STM32_I2C_ISR_TXIS BIT(1) +#define STM32_I2C_ISR_RXNE BIT(2) +#define STM32_I2C_ISR_ADDR BIT(3) +#define STM32_I2C_ISR_NACK BIT(4) +#define STM32_I2C_ISR_STOP BIT(5) +#define STM32_I2C_ISR_TC BIT(6) +#define STM32_I2C_ISR_TCR BIT(7) +#define STM32_I2C_ISR_BERR BIT(8) +#define STM32_I2C_ISR_ARLO BIT(9) +#define STM32_I2C_ISR_OVR BIT(10) +#define STM32_I2C_ISR_PECERR BIT(11) +#define STM32_I2C_ISR_TIMEOUT BIT(12) +#define STM32_I2C_ISR_ALERT BIT(13) +#define STM32_I2C_ISR_BUSY BIT(15) +#define STM32_I2C_ISR_DIR BIT(16) +#define STM32_I2C_ISR_ADDCODE(isr) (((isr) >> 16) & 0xfe) +#define STM32_I2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) +#define STM32_I2C_ICR_ADDRCF BIT(3) +#define STM32_I2C_ICR_NACKCF BIT(4) +#define STM32_I2C_ICR_STOPCF BIT(5) +#define STM32_I2C_ICR_BERRCF BIT(8) +#define STM32_I2C_ICR_ARLOCF BIT(9) +#define STM32_I2C_ICR_OVRCF BIT(10) +#define STM32_I2C_ICR_TIMEOUTCF BIT(12) +#define STM32_I2C_ICR_ALL 0x3F38 +#define STM32_I2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) +#define STM32_I2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) +#define STM32_I2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) /* --- Power / Reset / Clocks --- */ -#define STM32_PWR_CR2 REG32(STM32_PWR_BASE + 0x04) -#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x10) - - -#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) -#define STM32_RCC_CR_MSION BIT(0) -#define STM32_RCC_CR_MSIRDY BIT(1) -#define STM32_RCC_CR_HSION BIT(8) -#define STM32_RCC_CR_HSIRDY BIT(10) -#define STM32_RCC_CR_HSEON BIT(16) -#define STM32_RCC_CR_HSERDY BIT(17) -#define STM32_RCC_CR_PLLON BIT(24) -#define STM32_RCC_CR_PLLRDY BIT(25) - -#define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x04) -#define STM32_RCC_ICSCR_MSIRANGE(n) ((n) << 13) -#define STM32_RCC_ICSCR_MSIRANGE_1MHZ STM32_RCC_ICSCR_MSIRANGE(4) -#define STM32_RCC_ICSCR_MSIRANGE_2MHZ STM32_RCC_ICSCR_MSIRANGE(5) -#define STM32_RCC_ICSCR_MSIRANGE_MASK STM32_RCC_ICSCR_MSIRANGE(7) - -#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) -#define STM32_RCC_CFGR_SW_MSI (0 << 0) -#define STM32_RCC_CFGR_SW_HSI (1 << 0) -#define STM32_RCC_CFGR_SW_HSE (2 << 0) -#define STM32_RCC_CFGR_SW_PLL (3 << 0) -#define STM32_RCC_CFGR_SW_MASK (3 << 0) -#define STM32_RCC_CFGR_SWS_MSI (0 << 2) -#define STM32_RCC_CFGR_SWS_HSI (1 << 2) -#define STM32_RCC_CFGR_SWS_HSE (2 << 2) -#define STM32_RCC_CFGR_SWS_PLL (3 << 2) -#define STM32_RCC_CFGR_SWS_MASK (3 << 2) - -#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x0C) -#define STM32_RCC_PLLCFGR_PLLSRC_SHIFT (0) -#define STM32_RCC_PLLCFGR_PLLSRC_NONE (0 << STM32_RCC_PLLCFGR_PLLSRC_SHIFT) -#define STM32_RCC_PLLCFGR_PLLSRC_MSI (1 << STM32_RCC_PLLCFGR_PLLSRC_SHIFT) -#define STM32_RCC_PLLCFGR_PLLSRC_HSI (2 << STM32_RCC_PLLCFGR_PLLSRC_SHIFT) -#define STM32_RCC_PLLCFGR_PLLSRC_HSE (3 << STM32_RCC_PLLCFGR_PLLSRC_SHIFT) -#define STM32_RCC_PLLCFGR_PLLSRC_MASK (3 << STM32_RCC_PLLCFGR_PLLSRC_SHIFT) -#define STM32_RCC_PLLCFGR_PLLM_SHIFT (4) -#define STM32_RCC_PLLCFGR_PLLM_MASK (0x7 << STM32_RCC_PLLCFGR_PLLM_SHIFT) -#define STM32_RCC_PLLCFGR_PLLN_SHIFT (8) -#define STM32_RCC_PLLCFGR_PLLN_MASK (0x7f << STM32_RCC_PLLCFGR_PLLN_SHIFT) -#define STM32_RCC_PLLCFGR_PLLREN_SHIFT (24) -#define STM32_RCC_PLLCFGR_PLLREN_MASK (1 << STM32_RCC_PLLCFGR_PLLREN_SHIFT) -#define STM32_RCC_PLLCFGR_PLLR_SHIFT (25) -#define STM32_RCC_PLLCFGR_PLLR_MASK (3 << STM32_RCC_PLLCFGR_PLLR_SHIFT) - -#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x28) -#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x2C) -#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x30) -#define STM32_RCC_APB1RSTR1 REG32(STM32_RCC_BASE + 0x38) -#define STM32_RCC_APB1RSTR2 REG32(STM32_RCC_BASE + 0x3C) -#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x40) - -#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x48) -#define STM32_RCC_AHB1ENR_DMA1EN BIT(0) -#define STM32_RCC_AHB1ENR_DMA2EN BIT(1) - -#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x4C) -#define STM32_RCC_AHB2ENR_GPIOMASK (0xff << 0) -#define STM32_RCC_AHB2ENR_RNGEN BIT(18) - -#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x58) -#define STM32_RCC_PWREN BIT(28) - -#define STM32_RCC_APB1ENR2 REG32(STM32_RCC_BASE + 0x5C) -#define STM32_RCC_APB1ENR2_LPUART1EN BIT(0) - -#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x60) -#define STM32_RCC_SYSCFGEN BIT(0) - -#define STM32_RCC_CCIPR REG32(STM32_RCC_BASE + 0x88) +#define STM32_PWR_CR1 REG32(STM32_PWR_BASE + 0x00) +#define STM32_PWR_CR2 REG32(STM32_PWR_BASE + 0x04) +#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x10) +#define STM32_PWR_SCR REG32(STM32_PWR_BASE + 0x18) + +#define PWR_CR1_LPMS_POS 0U +#define PWR_CR1_LPMS_MSK (0x7UL << PWR_CR1_LPMS_POS) +#define PWR_CR1_LPMS PWR_CR1_LPMS_MSK +#define PWR_CR1_LPMS_STOP0 (0x00000000UL) +#define PWR_CR1_LPMS_STOP1_POS 0U +#define PWR_CR1_LPMS_STOP1_MSK (0x1UL << PWR_CR1_LPMS_STOP1_POS) +#define PWR_CR1_LPMS_STOP1 PWR_CR1_LPMS_STOP1_MSK +#define PWR_CR1_LPMS_STOP2_POS 1U +#define PWR_CR1_LPMS_STOP2_MSK (0x1UL << PWR_CR1_LPMS_STOP2_POS) +#define PWR_CR1_LPMS_STOP2 PWR_CR1_LPMS_STOP2_MSK +#define PWR_CR1_LPMS_STANDBY_POS 0U +#define PWR_CR1_LPMS_STANDBY_MSK (0x3UL << PWR_CR1_LPMS_STANDBY_POS) +#define PWR_CR1_LPMS_STANDBY PWR_CR1_LPMS_STANDBY_MSK +#define PWR_CR1_LPMS_SHUTDOWN_POS 2U +#define PWR_CR1_LPMS_SHUTDOWN_MSK (0x1UL << PWR_CR1_LPMS_SHUTDOWN_POS) +#define PWR_CR1_LPMS_SHUTDOWN PWR_CR1_LPMS_SHUTDOWN_MSK +#define PWR_CR1_VOS_POS 9U +#define PWR_CR1_VOS_MSK (0x3UL << PWR_CR1_VOS_POS) +#define PWR_CR1_VOS PWR_CR1_VOS_MSK +#define PWR_CR1_VOS_0 (0x1UL << PWR_CR1_VOS_POS) +#define PWR_CR1_VOS_1 (0x2UL << PWR_CR1_VOS_POS) + +/* --- Macro usage in ec code --- */ +#define STM32_RCC_AHB2ENR_GPIOMASK \ + (STM32_RCC_AHB2ENR_GPIOAEN | STM32_RCC_AHB2ENR_GPIOBEN | \ + STM32_RCC_AHB2ENR_GPIOCEN | STM32_RCC_AHB2ENR_GPIODEN | \ + STM32_RCC_AHB2ENR_GPIOEEN | STM32_RCC_AHB2ENR_GPIOHEN) +#define STM32_RCC_ICSCR_MSIRANGE(n) ((n) << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_ICSCR_MSIRANGE_1MHZ STM32_RCC_ICSCR_MSIRANGE(4) +#define STM32_RCC_ICSCR_MSIRANGE_2MHZ STM32_RCC_ICSCR_MSIRANGE(5) +#define STM32_RCC_ICSCR_MSIRANGE_MASK STM32_RCC_CR_MSIRANGE_MSK +#define STM32_RCC_SYSCFGEN STM32_RCC_APB2ENR_SYSCFGEN + +#define STM32_RCC_PB2_TIM1 STM32_RCC_APB2ENR_TIM1EN +#define STM32_RCC_PB2_TIM15 STM32_RCC_APB2ENR_TIM15EN +#define STM32_RCC_PB2_TIM16 STM32_RCC_APB2ENR_TIM16EN +#ifndef CHIP_VARIANT_STM32L431X +#define STM32_RCC_PB2_TIM8 BIT(13) +#endif +#define STM32_RCC_PWREN STM32_RCC_APB1ENR1_PWREN + +#define STM32_RCC_AHB2ENR_GPIO_PORTA BIT(0) +#define STM32_RCC_AHB2ENR_GPIO_PORTB BIT(1) +#define STM32_RCC_AHB2ENR_GPIO_PORTC BIT(2) +#define STM32_RCC_AHB2ENR_GPIO_PORTD BIT(3) +#define STM32_RCC_AHB2ENR_GPIO_PORTE BIT(4) +#define STM32_RCC_AHB2ENR_GPIO_PORTH BIT(7) #define STM32_RCC_CCIPR_USART1SEL_SHIFT (0) -#define STM32_RCC_CCIPR_USART1SEL_MASK (3 << STM32_RCC_CCIPR_USART1SEL_SHIFT) +#define STM32_RCC_CCIPR_USART1SEL_MASK (3 << STM32_RCC_CCIPR_USART1SEL_SHIFT) #define STM32_RCC_CCIPR_USART2SEL_SHIFT (2) -#define STM32_RCC_CCIPR_USART2SEL_MASK (3 << STM32_RCC_CCIPR_USART2SEL_SHIFT) +#define STM32_RCC_CCIPR_USART2SEL_MASK (3 << STM32_RCC_CCIPR_USART2SEL_SHIFT) #define STM32_RCC_CCIPR_USART3SEL_SHIFT (4) -#define STM32_RCC_CCIPR_USART3SEL_MASK (3 << STM32_RCC_CCIPR_USART3SEL_SHIFT) +#define STM32_RCC_CCIPR_USART3SEL_MASK (3 << STM32_RCC_CCIPR_USART3SEL_SHIFT) #define STM32_RCC_CCIPR_UART4SEL_SHIFT (6) -#define STM32_RCC_CCIPR_UART4SEL_MASK (3 << STM32_RCC_CCIPR_UART4SEL_SHIFT) +#define STM32_RCC_CCIPR_UART4SEL_MASK (3 << STM32_RCC_CCIPR_UART4SEL_SHIFT) #define STM32_RCC_CCIPR_UART5SEL_SHIFT (8) -#define STM32_RCC_CCIPR_UART5SEL_MASK (3 << STM32_RCC_CCIPR_UART5SEL_SHIFT) +#define STM32_RCC_CCIPR_UART5SEL_MASK (3 << STM32_RCC_CCIPR_UART5SEL_SHIFT) #define STM32_RCC_CCIPR_LPUART1SEL_SHIFT (10) -#define STM32_RCC_CCIPR_LPUART1SEL_MASK (3 << STM32_RCC_CCIPR_LPUART1SEL_SHIFT) +#define STM32_RCC_CCIPR_LPUART1SEL_MASK (3 << STM32_RCC_CCIPR_LPUART1SEL_SHIFT) #define STM32_RCC_CCIPR_I2C1SEL_SHIFT (12) -#define STM32_RCC_CCIPR_I2C1SEL_MASK (3 << STM32_RCC_CCIPR_I2C1SEL_SHIFT) +#define STM32_RCC_CCIPR_I2C1SEL_MASK (3 << STM32_RCC_CCIPR_I2C1SEL_SHIFT) #define STM32_RCC_CCIPR_I2C2SEL_SHIFT (14) -#define STM32_RCC_CCIPR_I2C2SEL_MASK (3 << STM32_RCC_CCIPR_I2C2SEL_SHIFT) +#define STM32_RCC_CCIPR_I2C2SEL_MASK (3 << STM32_RCC_CCIPR_I2C2SEL_SHIFT) #define STM32_RCC_CCIPR_I2C3SEL_SHIFT (16) -#define STM32_RCC_CCIPR_I2C3SEL_MASK (3 << STM32_RCC_CCIPR_I2C3SEL_SHIFT) +#define STM32_RCC_CCIPR_I2C3SEL_MASK (3 << STM32_RCC_CCIPR_I2C3SEL_SHIFT) #define STM32_RCC_CCIPR_LPTIM1SEL_SHIFT (18) -#define STM32_RCC_CCIPR_LPTIM1SEL_MASK (3 << STM32_RCC_CCIPR_LPTIM1SEL_SHIFT) +#define STM32_RCC_CCIPR_LPTIM1SEL_MASK (3 << STM32_RCC_CCIPR_LPTIM1SEL_SHIFT) #define STM32_RCC_CCIPR_LPTIM2SEL_SHIFT (20) -#define STM32_RCC_CCIPR_LPTIM2SEL_MASK (3 << STM32_RCC_CCIPR_LPTIM2SEL_SHIFT) +#define STM32_RCC_CCIPR_LPTIM2SEL_MASK (3 << STM32_RCC_CCIPR_LPTIM2SEL_SHIFT) #define STM32_RCC_CCIPR_SAI1SEL_SHIFT (22) -#define STM32_RCC_CCIPR_SAI1SEL_MASK (3 << STM32_RCC_CCIPR_SAI1SEL_SHIFT) +#define STM32_RCC_CCIPR_SAI1SEL_MASK (3 << STM32_RCC_CCIPR_SAI1SEL_SHIFT) #define STM32_RCC_CCIPR_SAI2SEL_SHIFT (24) -#define STM32_RCC_CCIPR_SAI2SEL_MASK (3 << STM32_RCC_CCIPR_SAI2SEL_SHIFT) +#define STM32_RCC_CCIPR_SAI2SEL_MASK (3 << STM32_RCC_CCIPR_SAI2SEL_SHIFT) #define STM32_RCC_CCIPR_CLK48SEL_SHIFT (26) -#define STM32_RCC_CCIPR_CLK48SEL_MASK (3 << STM32_RCC_CCIPR_CLK48SEL_SHIFT) +#define STM32_RCC_CCIPR_CLK48SEL_MASK (3 << STM32_RCC_CCIPR_CLK48SEL_SHIFT) #define STM32_RCC_CCIPR_ADCSEL_SHIFT (28) -#define STM32_RCC_CCIPR_ADCSEL_MASK (3 << STM32_RCC_CCIPR_ADCSEL_SHIFT) +#define STM32_RCC_CCIPR_ADCSEL_MASK (3 << STM32_RCC_CCIPR_ADCSEL_SHIFT) #define STM32_RCC_CCIPR_SWPMI1SEL_SHIFT (30) -#define STM32_RCC_CCIPR_SWPMI1SEL_MASK BIT(STM32_RCC_CCIPR_SWPMI1SEL_SHIFT) +#define STM32_RCC_CCIPR_SWPMI1SEL_MASK BIT(STM32_RCC_CCIPR_SWPMI1SEL_SHIFT) #define STM32_RCC_CCIPR_DFSDM1SEL_SHIFT (31) -#define STM32_RCC_CCIPR_DFSDM1SEL_MASK BIT(STM32_RCC_CCIPR_DFSDM1SEL_SHIFT) - +#define STM32_RCC_CCIPR_DFSDM1SEL_MASK BIT(STM32_RCC_CCIPR_DFSDM1SEL_SHIFT) /* Possible clock sources for each peripheral */ -#define STM32_RCC_CCIPR_UART_PCLK 0 -#define STM32_RCC_CCIPR_UART_SYSCLK 1 -#define STM32_RCC_CCIPR_UART_HSI16 2 -#define STM32_RCC_CCIPR_UART_LSE 3 - -#define STM32_RCC_CCIPR_I2C_PCLK 0 -#define STM32_RCC_CCIPR_I2C_SYSCLK 1 -#define STM32_RCC_CCIPR_I2C_HSI16 2 - -#define STM32_RCC_CCIPR_LPTIM_PCLK 0 -#define STM32_RCC_CCIPR_LPTIM_LSI 1 -#define STM32_RCC_CCIPR_LPTIM_HSI16 2 -#define STM32_RCC_CCIPR_LPTIM_LSE 3 - -#define STM32_RCC_CCIPR_SAI_PLLSAI1CLK 0 -#define STM32_RCC_CCIPR_SAI_PLLSAI2CLK 1 -#define STM32_RCC_CCIPR_SAI_PLLSAI3CLK 2 -#define STM32_RCC_CCIPR_SAI_EXTCLK 3 - -#define STM32_RCC_CCIPR_CLK48_NONE 0 -#define STM32_RCC_CCIPR_CLK48_PLL48M2CLK 1 -#define STM32_RCC_CCIPR_CLK48_PLL48M1CLK 2 -#define STM32_RCC_CCIPR_CLK48_MSI 3 - -#define STM32_RCC_CCIPR_ADC_NONE 0 -#define STM32_RCC_CCIPR_ADC_PLLADC1CLK 1 -#define STM32_RCC_CCIPR_ADC_PLLADC2CLK 2 -#define STM32_RCC_CCIPR_ADC_SYSCLK 3 - -#define STM32_RCC_CCIPR_SWPMI_PCLK 0 -#define STM32_RCC_CCIPR_SWPMI_HSI16 1 - -#define STM32_RCC_CCIPR_DFSDM_PCLK 0 -#define STM32_RCC_CCIPR_DFSDM_SYSCLK 1 - -#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x90) - -#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x94) - -#define STM32_RCC_CRRCR REG32(STM32_RCC_BASE + 0x98) - -#define STM32_RCC_CRRCR_HSI48ON BIT(0) -#define STM32_RCC_CRRCR_HSI48RDY BIT(1) -#define STM32_RCC_CRRCR_HSI48CAL_MASK (0x1ff << 7) - -#define STM32_RCC_PB2_TIM1 BIT(11) -#define STM32_RCC_PB2_TIM8 BIT(13) - -#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) - - -/* Peripheral bits for RCC_APB/AHB and DBGMCU regs */ -#define STM32_RCC_PB2_USART1 BIT(14) +#define STM32_RCC_CCIPR_UART_PCLK 0 +#define STM32_RCC_CCIPR_UART_SYSCLK 1 +#define STM32_RCC_CCIPR_UART_HSI16 2 +#define STM32_RCC_CCIPR_UART_LSE 3 + +#define STM32_RCC_CCIPR_I2C_PCLK 0 +#define STM32_RCC_CCIPR_I2C_SYSCLK 1 +#define STM32_RCC_CCIPR_I2C_HSI16 2 + +#define STM32_RCC_CCIPR_LPTIM_PCLK 0 +#define STM32_RCC_CCIPR_LPTIM_LSI 1 +#define STM32_RCC_CCIPR_LPTIM_HSI16 2 +#define STM32_RCC_CCIPR_LPTIM_LSE 3 + +#define STM32_RCC_CCIPR_SAI_PLLSAI1CLK 0 +#define STM32_RCC_CCIPR_SAI_PLLSAI2CLK 1 +#define STM32_RCC_CCIPR_SAI_PLLSAI3CLK 2 +#define STM32_RCC_CCIPR_SAI_EXTCLK 3 + +#define STM32_RCC_CCIPR_CLK48_NONE 0 +#define STM32_RCC_CCIPR_CLK48_PLL48M2CLK 1 +#define STM32_RCC_CCIPR_CLK48_PLL48M1CLK 2 +#define STM32_RCC_CCIPR_CLK48_MSI 3 + +#define STM32_RCC_CCIPR_ADC_NONE 0 +#define STM32_RCC_CCIPR_ADC_PLLADC1CLK 1 +#define STM32_RCC_CCIPR_ADC_PLLADC2CLK 2 +#define STM32_RCC_CCIPR_ADC_SYSCLK 3 + +#define STM32_RCC_CCIPR_SWPMI_PCLK 0 +#define STM32_RCC_CCIPR_SWPMI_HSI16 1 + +#define STM32_RCC_CCIPR_DFSDM_PCLK 0 +#define STM32_RCC_CCIPR_DFSDM_SYSCLK 1 + +#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) +#define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x04) +#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) +#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x0C) +#define STM32_RCC_PLLSAI1CFGR REG32(STM32_RCC_BASE + 0x10) +#define STM32_RCC_RESERVED REG32(STM32_RCC_BASE + 0x14) +#define STM32_RCC_CIER REG32(STM32_RCC_BASE + 0x18) +#define STM32_RCC_CIFR REG32(STM32_RCC_BASE + 0x1C) +#define STM32_RCC_CICR REG32(STM32_RCC_BASE + 0x20) +#define STM32_RCC_RESERVED0 REG32(STM32_RCC_BASE + 0x24) +#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x28) +#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x2C) +#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x30) +#define STM32_RCC_RESERVED1 REG32(STM32_RCC_BASE + 0x34) +#define STM32_RCC_APB1RSTR1 REG32(STM32_RCC_BASE + 0x38) +#define STM32_RCC_APB1RSTR2 REG32(STM32_RCC_BASE + 0x3C) +#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x40) +#define STM32_RCC_RESERVED2 REG32(STM32_RCC_BASE + 0x44) +#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x48) +#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x4C) +#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x50) +#define STM32_RCC_RESERVED3 REG32(STM32_RCC_BASE + 0x54) +#define STM32_RCC_APB1ENR1 REG32(STM32_RCC_BASE + 0x58) +#define STM32_RCC_APB1ENR2 REG32(STM32_RCC_BASE + 0x5C) +#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x60) +#define STM32_RCC_RESERVED4 REG32(STM32_RCC_BASE + 0x64) +#define STM32_RCC_AHB1SMENR REG32(STM32_RCC_BASE + 0x68) +#define STM32_RCC_AHB2SMENR REG32(STM32_RCC_BASE + 0x6C) +#define STM32_RCC_AHB3SMENR REG32(STM32_RCC_BASE + 0x70) +#define STM32_RCC_RESERVED5 REG32(STM32_RCC_BASE + 0x74) +#define STM32_RCC_APB1SMENR1 REG32(STM32_RCC_BASE + 0x78) +#define STM32_RCC_APB1SMENR2 REG32(STM32_RCC_BASE + 0x7C) +#define STM32_RCC_APB2SMENR REG32(STM32_RCC_BASE + 0x80) +#define STM32_RCC_RESERVED6 REG32(STM32_RCC_BASE + 0x84) +#define STM32_RCC_CCIPR REG32(STM32_RCC_BASE + 0x88) +#define STM32_RCC_RESERVED7 REG32(STM32_RCC_BASE + 0x8C) +#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x90) +#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x94) +#define STM32_RCC_CRRCR REG32(STM32_RCC_BASE + 0x98) +#define STM32_RCC_CCIPR2 REG32(STM32_RCC_BASE + 0x9C) + +#define STM32_RCC_PLLSAI1_SUPPORT +#define STM32_RCC_PLLP_SUPPORT +#define STM32_RCC_HSI48_SUPPORT +#define STM32_RCC_PLLP_DIV_2_31_SUPPORT +#define STM32_RCC_PLLSAI1P_DIV_2_31_SUPPORT + +#define STM32_RCC_APB1ENR STM32_RCC_APB1ENR1 + +/******************** BIT DEFINITION FOR STM32_RCC_CR REGISTER **************/ +#define STM32_RCC_CR_MSION_POS 0U +#define STM32_RCC_CR_MSION_MSK (0x1UL << STM32_RCC_CR_MSION_POS) +#define STM32_RCC_CR_MSION STM32_RCC_CR_MSION_MSK +#define STM32_RCC_CR_MSIRDY_POS 1U +#define STM32_RCC_CR_MSIRDY_MSK (0x1UL << STM32_RCC_CR_MSIRDY_POS) +#define STM32_RCC_CR_MSIRDY STM32_RCC_CR_MSIRDY_MSK +#define STM32_RCC_CR_MSIPLLEN_POS 2U +#define STM32_RCC_CR_MSIPLLEN_MSK (0x1UL << STM32_RCC_CR_MSIPLLEN_POS) +#define STM32_RCC_CR_MSIPLLEN STM32_RCC_CR_MSIPLLEN_MSK +#define STM32_RCC_CR_MSIRGSEL_POS 3U +#define STM32_RCC_CR_MSIRGSEL_MSK (0x1UL << STM32_RCC_CR_MSIRGSEL_POS) +#define STM32_RCC_CR_MSIRGSEL STM32_RCC_CR_MSIRGSEL_MSK + +/*!< MSIRANGE CONFIGURATION : 12 FREQUENCY RANGES AVAILABLE */ +#define STM32_RCC_CR_MSIRANGE_POS 4U +#define STM32_RCC_CR_MSIRANGE_MSK (0xFUL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE STM32_RCC_CR_MSIRANGE_MSK +#define STM32_RCC_CR_MSIRANGE_0 (0x0UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_1 (0x1UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_2 (0x2UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_3 (0x3UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_4 (0x4UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_5 (0x5UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_6 (0x6UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_7 (0x7UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_8 (0x8UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_9 (0x9UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_10 (0xAUL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_11 (0xBUL << STM32_RCC_CR_MSIRANGE_POS) + +#define STM32_RCC_CR_HSION_POS 8U +#define STM32_RCC_CR_HSION_MSK (0x1UL << STM32_RCC_CR_HSION_POS) +#define STM32_RCC_CR_HSION STM32_RCC_CR_HSION_MSK +#define STM32_RCC_CR_HSIKERON_POS 9U +#define STM32_RCC_CR_HSIKERON_MSK (0x1UL << STM32_RCC_CR_HSIKERON_POS) +#define STM32_RCC_CR_HSIKERON STM32_RCC_CR_HSIKERON_MSK +#define STM32_RCC_CR_HSIRDY_POS 10U +#define STM32_RCC_CR_HSIRDY_MSK (0x1UL << STM32_RCC_CR_HSIRDY_POS) +#define STM32_RCC_CR_HSIRDY STM32_RCC_CR_HSIRDY_MSK +#define STM32_RCC_CR_HSIASFS_POS 11U +#define STM32_RCC_CR_HSIASFS_MSK (0x1UL << STM32_RCC_CR_HSIASFS_POS) +#define STM32_RCC_CR_HSIASFS STM32_RCC_CR_HSIASFS_MSK + +#define STM32_RCC_CR_HSEON_POS 16U +#define STM32_RCC_CR_HSEON_MSK (0x1UL << STM32_RCC_CR_HSEON_POS) +#define STM32_RCC_CR_HSEON STM32_RCC_CR_HSEON_MSK +#define STM32_RCC_CR_HSERDY_POS 17U +#define STM32_RCC_CR_HSERDY_MSK (0x1UL << STM32_RCC_CR_HSERDY_POS) +#define STM32_RCC_CR_HSERDY STM32_RCC_CR_HSERDY_MSK +#define STM32_RCC_CR_HSEBYP_POS 18U +#define STM32_RCC_CR_HSEBYP_MSK (0x1UL << STM32_RCC_CR_HSEBYP_POS) +#define STM32_RCC_CR_HSEBYP STM32_RCC_CR_HSEBYP_MSK +#define STM32_RCC_CR_CSSON_POS 19U +#define STM32_RCC_CR_CSSON_MSK (0x1UL << STM32_RCC_CR_CSSON_POS) +#define STM32_RCC_CR_CSSON STM32_RCC_CR_CSSON_MSK + +#define STM32_RCC_CR_PLLON_POS 24U +#define STM32_RCC_CR_PLLON_MSK (0x1UL << STM32_RCC_CR_PLLON_POS) +#define STM32_RCC_CR_PLLON STM32_RCC_CR_PLLON_MSK +#define STM32_RCC_CR_PLLRDY_POS 25U +#define STM32_RCC_CR_PLLRDY_MSK (0x1UL << STM32_RCC_CR_PLLRDY_POS) +#define STM32_RCC_CR_PLLRDY STM32_RCC_CR_PLLRDY_MSK +#define STM32_RCC_CR_PLLSAI1ON_POS 26U +#define STM32_RCC_CR_PLLSAI1ON_MSK (0x1UL << STM32_RCC_CR_PLLSAI1ON_POS) +#define STM32_RCC_CR_PLLSAI1ON STM32_RCC_CR_PLLSAI1ON_MSK +#define STM32_RCC_CR_PLLSAI1RDY_POS 27U +#define STM32_RCC_CR_PLLSAI1RDY_MSK (0x1UL << STM32_RCC_CR_PLLSAI1RDY_POS) +#define STM32_RCC_CR_PLLSAI1RDY STM32_RCC_CR_PLLSAI1RDY_MSK + +/******************** BIT DEFINITION FOR STM32_RCC_ICSCR REGISTER ***********/ +/*!< MSICAL CONFIGURATION */ +#define STM32_RCC_ICSCR_MSICAL_POS 0U +#define STM32_RCC_ICSCR_MSICAL_MSK (0xFFUL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL STM32_RCC_ICSCR_MSICAL_MSK +#define STM32_RCC_ICSCR_MSICAL_0 (0x01UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_1 (0x02UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_2 (0x04UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_3 (0x08UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_4 (0x10UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_5 (0x20UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_6 (0x40UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_7 (0x80UL << STM32_RCC_ICSCR_MSICAL_POS) + +/*!< MSITRIM CONFIGURATION */ +#define STM32_RCC_ICSCR_MSITRIM_POS 8U +#define STM32_RCC_ICSCR_MSITRIM_MSK (0xFFUL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM STM32_RCC_ICSCR_MSITRIM_MSK +#define STM32_RCC_ICSCR_MSITRIM_0 (0x01UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_1 (0x02UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_2 (0x04UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_3 (0x08UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_4 (0x10UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_5 (0x20UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_6 (0x40UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_7 (0x80UL << STM32_RCC_ICSCR_MSITRIM_POS) + +/*!< HSICAL CONFIGURATION */ +#define STM32_RCC_ICSCR_HSICAL_POS 16U +#define STM32_RCC_ICSCR_HSICAL_MSK (0xFFUL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL STM32_RCC_ICSCR_HSICAL_MSK +#define STM32_RCC_ICSCR_HSICAL_0 (0x01UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_1 (0x02UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_2 (0x04UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_3 (0x08UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_4 (0x10UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_5 (0x20UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_6 (0x40UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_7 (0x80UL << STM32_RCC_ICSCR_HSICAL_POS) + +/*!< HSITRIM CONFIGURATION */ +#define STM32_RCC_ICSCR_HSITRIM_POS 24U +#define STM32_RCC_ICSCR_HSITRIM_MSK (0x1FUL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM STM32_RCC_ICSCR_HSITRIM_MSK +#define STM32_RCC_ICSCR_HSITRIM_0 (0x01UL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM_1 (0x02UL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM_2 (0x04UL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM_3 (0x08UL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM_4 (0x10UL << STM32_RCC_ICSCR_HSITRIM_POS) + +/**************** BIT DEFINITION FOR STM32_RCC_CFGR REGISTER **************/ +/*!< SW CONFIGURATION */ +#define STM32_RCC_CFGR_SW_POS 0U +#define STM32_RCC_CFGR_SW_MSK (0x3UL << STM32_RCC_CFGR_SW_POS) +#define STM32_RCC_CFGR_SW STM32_RCC_CFGR_SW_MSK +#define STM32_RCC_CFGR_SW_0 (0x1UL << STM32_RCC_CFGR_SW_POS) +#define STM32_RCC_CFGR_SW_1 (0x2UL << STM32_RCC_CFGR_SW_POS) + +#define STM32_RCC_CFGR_SW_MSI (0x00000000UL) +#define STM32_RCC_CFGR_SW_HSI (0x00000001UL) +#define STM32_RCC_CFGR_SW_HSE (0x00000002UL) +#define STM32_RCC_CFGR_SW_PLL (0x00000003UL) + +/*!< SWS CONFIGURATION */ +#define STM32_RCC_CFGR_SWS_POS 2U +#define STM32_RCC_CFGR_SWS_MSK (0x3UL << STM32_RCC_CFGR_SWS_POS) +#define STM32_RCC_CFGR_SWS STM32_RCC_CFGR_SWS_MSK +#define STM32_RCC_CFGR_SWS_0 (0x1UL << STM32_RCC_CFGR_SWS_POS) +#define STM32_RCC_CFGR_SWS_1 (0x2UL << STM32_RCC_CFGR_SWS_POS) + +#define STM32_RCC_CFGR_SWS_MSI (0x00000000UL) +#define STM32_RCC_CFGR_SWS_HSI (0x00000004UL) +#define STM32_RCC_CFGR_SWS_HSE (0x00000008UL) +#define STM32_RCC_CFGR_SWS_PLL (0x0000000CUL) + +/*!< HPRE CONFIGURATION */ +#define STM32_RCC_CFGR_HPRE_POS 4U +#define STM32_RCC_CFGR_HPRE_MSK (0xFUL << STM32_RCC_CFGR_HPRE_POS) +#define STM32_RCC_CFGR_HPRE STM32_RCC_CFGR_HPRE_MSK +#define STM32_RCC_CFGR_HPRE_0 (0x1UL << STM32_RCC_CFGR_HPRE_POS) +#define STM32_RCC_CFGR_HPRE_1 (0x2UL << STM32_RCC_CFGR_HPRE_POS) +#define STM32_RCC_CFGR_HPRE_2 (0x4UL << STM32_RCC_CFGR_HPRE_POS) +#define STM32_RCC_CFGR_HPRE_3 (0x8UL << STM32_RCC_CFGR_HPRE_POS) + +#define STM32_RCC_CFGR_HPRE_DIV1 (0x00000000UL) +#define STM32_RCC_CFGR_HPRE_DIV2 (0x00000080UL) +#define STM32_RCC_CFGR_HPRE_DIV4 (0x00000090UL) +#define STM32_RCC_CFGR_HPRE_DIV8 (0x000000A0UL) +#define STM32_RCC_CFGR_HPRE_DIV16 (0x000000B0UL) +#define STM32_RCC_CFGR_HPRE_DIV64 (0x000000C0UL) +#define STM32_RCC_CFGR_HPRE_DIV128 (0x000000D0UL) +#define STM32_RCC_CFGR_HPRE_DIV256 (0x000000E0UL) +#define STM32_RCC_CFGR_HPRE_DIV512 (0x000000F0UL) + +/*!< PPRE1 CONFIGURATION */ +#define STM32_RCC_CFGR_PPRE1_POS 8U +#define STM32_RCC_CFGR_PPRE1_MSK (0x7UL << STM32_RCC_CFGR_PPRE1_POS) +#define STM32_RCC_CFGR_PPRE1 STM32_RCC_CFGR_PPRE1_MSK +#define STM32_RCC_CFGR_PPRE1_0 (0x1UL << STM32_RCC_CFGR_PPRE1_POS) +#define STM32_RCC_CFGR_PPRE1_1 (0x2UL << STM32_RCC_CFGR_PPRE1_POS) +#define STM32_RCC_CFGR_PPRE1_2 (0x4UL << STM32_RCC_CFGR_PPRE1_POS) + +#define STM32_RCC_CFGR_PPRE1_DIV1 (0x00000000UL) +#define STM32_RCC_CFGR_PPRE1_DIV2 (0x00000400UL) +#define STM32_RCC_CFGR_PPRE1_DIV4 (0x00000500UL) +#define STM32_RCC_CFGR_PPRE1_DIV8 (0x00000600UL) +#define STM32_RCC_CFGR_PPRE1_DIV16 (0x00000700UL) + +/*!< PPRE2 CONFIGURATION */ +#define STM32_RCC_CFGR_PPRE2_POS 11U +#define STM32_RCC_CFGR_PPRE2_MSK (0x7UL << STM32_RCC_CFGR_PPRE2_POS) +#define STM32_RCC_CFGR_PPRE2 STM32_RCC_CFGR_PPRE2_MSK +#define STM32_RCC_CFGR_PPRE2_0 (0x1UL << STM32_RCC_CFGR_PPRE2_POS) +#define STM32_RCC_CFGR_PPRE2_1 (0x2UL << STM32_RCC_CFGR_PPRE2_POS) +#define STM32_RCC_CFGR_PPRE2_2 (0x4UL << STM32_RCC_CFGR_PPRE2_POS) + +#define STM32_RCC_CFGR_PPRE2_DIV1 (0x00000000UL) +#define STM32_RCC_CFGR_PPRE2_DIV2 (0x00002000UL) +#define STM32_RCC_CFGR_PPRE2_DIV4 (0x00002800UL) +#define STM32_RCC_CFGR_PPRE2_DIV8 (0x00003000UL) +#define STM32_RCC_CFGR_PPRE2_DIV16 (0x00003800UL) + +#define STM32_RCC_CFGR_STOPWUCK_POS 15U +#define STM32_RCC_CFGR_STOPWUCK_MSK (0x1UL << STM32_RCC_CFGR_STOPWUCK_POS) +#define STM32_RCC_CFGR_STOPWUCK STM32_RCC_CFGR_STOPWUCK_MSK + +/*!< MCOSEL CONFIGURATION */ +#define STM32_RCC_CFGR_MCOSEL_POS 24U +#define STM32_RCC_CFGR_MCOSEL_MSK (0xFUL << STM32_RCC_CFGR_MCOSEL_POS) +#define STM32_RCC_CFGR_MCOSEL STM32_RCC_CFGR_MCOSEL_MSK +#define STM32_RCC_CFGR_MCOSEL_0 (0x1UL << STM32_RCC_CFGR_MCOSEL_POS) +#define STM32_RCC_CFGR_MCOSEL_1 (0x2UL << STM32_RCC_CFGR_MCOSEL_POS) +#define STM32_RCC_CFGR_MCOSEL_2 (0x4UL << STM32_RCC_CFGR_MCOSEL_POS) +#define STM32_RCC_CFGR_MCOSEL_3 (0x8UL << STM32_RCC_CFGR_MCOSEL_POS) + +#define STM32_RCC_CFGR_MCOPRE_POS 28U +#define STM32_RCC_CFGR_MCOPRE_MSK (0x7UL << STM32_RCC_CFGR_MCOPRE_POS) +#define STM32_RCC_CFGR_MCOPRE STM32_RCC_CFGR_MCOPRE_MSK +#define STM32_RCC_CFGR_MCOPRE_0 (0x1UL << STM32_RCC_CFGR_MCOPRE_POS) +#define STM32_RCC_CFGR_MCOPRE_1 (0x2UL << STM32_RCC_CFGR_MCOPRE_POS) +#define STM32_RCC_CFGR_MCOPRE_2 (0x4UL << STM32_RCC_CFGR_MCOPRE_POS) + +#define STM32_RCC_CFGR_MCOPRE_DIV1 (0x00000000UL) +#define STM32_RCC_CFGR_MCOPRE_DIV2 (0x10000000UL) +#define STM32_RCC_CFGR_MCOPRE_DIV4 (0x20000000UL) +#define STM32_RCC_CFGR_MCOPRE_DIV8 (0x30000000UL) +#define STM32_RCC_CFGR_MCOPRE_DIV16 (0x40000000UL) + +/* LEGACY ALIASES */ +#define STM32_RCC_CFGR_MCO_PRE STM32_RCC_CFGR_MCOPRE +#define STM32_RCC_CFGR_MCO_PRE_1 STM32_RCC_CFGR_MCOPRE_DIV1 +#define STM32_RCC_CFGR_MCO_PRE_2 STM32_RCC_CFGR_MCOPRE_DIV2 +#define STM32_RCC_CFGR_MCO_PRE_4 STM32_RCC_CFGR_MCOPRE_DIV4 +#define STM32_RCC_CFGR_MCO_PRE_8 STM32_RCC_CFGR_MCOPRE_DIV8 +#define STM32_RCC_CFGR_MCO_PRE_16 STM32_RCC_CFGR_MCOPRE_DIV16 + +/**************** BIT DEFINITION FOR STM32_RCC_PLLCFGR REGISTER ***********/ +#define STM32_RCC_PLLCFGR_PLLSRC_POS 0U +#define STM32_RCC_PLLCFGR_PLLSRC_MSK (0x3UL << STM32_RCC_PLLCFGR_PLLSRC_POS) +#define STM32_RCC_PLLCFGR_PLLSRC STM32_RCC_PLLCFGR_PLLSRC_MSK + +#define STM32_RCC_PLLCFGR_PLLSRC_MSI_POS 0U +#define STM32_RCC_PLLCFGR_PLLSRC_MSI_MSK \ + (0x1UL << STM32_RCC_PLLCFGR_PLLSRC_MSI_POS) +#define STM32_RCC_PLLCFGR_PLLSRC_MSI STM32_RCC_PLLCFGR_PLLSRC_MSI_MSK +#define STM32_RCC_PLLCFGR_PLLSRC_HSI_POS 1U +#define STM32_RCC_PLLCFGR_PLLSRC_HSI_MSK \ + (0x1UL << STM32_RCC_PLLCFGR_PLLSRC_HSI_POS) +#define STM32_RCC_PLLCFGR_PLLSRC_HSI STM32_RCC_PLLCFGR_PLLSRC_HSI_MSK +#define STM32_RCC_PLLCFGR_PLLSRC_HSE_POS 0U +#define STM32_RCC_PLLCFGR_PLLSRC_HSE_MSK \ + (0x3UL << STM32_RCC_PLLCFGR_PLLSRC_HSE_POS) +#define STM32_RCC_PLLCFGR_PLLSRC_HSE STM32_RCC_PLLCFGR_PLLSRC_HSE_MSK + +#define STM32_RCC_PLLCFGR_PLLM_POS 4U +#define STM32_RCC_PLLCFGR_PLLM_MSK (0x7UL << STM32_RCC_PLLCFGR_PLLM_POS) +#define STM32_RCC_PLLCFGR_PLLM STM32_RCC_PLLCFGR_PLLM_MSK +#define STM32_RCC_PLLCFGR_PLLM_0 (0x1UL << STM32_RCC_PLLCFGR_PLLM_POS) +#define STM32_RCC_PLLCFGR_PLLM_1 (0x2UL << STM32_RCC_PLLCFGR_PLLM_POS) +#define STM32_RCC_PLLCFGR_PLLM_2 (0x4UL << STM32_RCC_PLLCFGR_PLLM_POS) + +#define STM32_RCC_PLLCFGR_PLLN_POS 8U +#define STM32_RCC_PLLCFGR_PLLN_MSK (0x7FUL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN STM32_RCC_PLLCFGR_PLLN_MSK +#define STM32_RCC_PLLCFGR_PLLN_0 (0x01UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_1 (0x02UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_2 (0x04UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_3 (0x08UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_4 (0x10UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_5 (0x20UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_6 (0x40UL << STM32_RCC_PLLCFGR_PLLN_POS) + +#define STM32_RCC_PLLCFGR_PLLPEN_POS 16U +#define STM32_RCC_PLLCFGR_PLLPEN_MSK (0x1UL << STM32_RCC_PLLCFGR_PLLPEN_POS) +#define STM32_RCC_PLLCFGR_PLLPEN STM32_RCC_PLLCFGR_PLLPEN_MSK +#define STM32_RCC_PLLCFGR_PLLP_POS 17U +#define STM32_RCC_PLLCFGR_PLLP_MSK (0x1UL << STM32_RCC_PLLCFGR_PLLP_POS) +#define STM32_RCC_PLLCFGR_PLLP STM32_RCC_PLLCFGR_PLLP_MSK +#define STM32_RCC_PLLCFGR_PLLQEN_POS 20U +#define STM32_RCC_PLLCFGR_PLLQEN_MSK (0x1UL << STM32_RCC_PLLCFGR_PLLQEN_POS) +#define STM32_RCC_PLLCFGR_PLLQEN STM32_RCC_PLLCFGR_PLLQEN_MSK + +#define STM32_RCC_PLLCFGR_PLLQ_POS 21U +#define STM32_RCC_PLLCFGR_PLLQ_MSK (0x3UL << STM32_RCC_PLLCFGR_PLLQ_POS) +#define STM32_RCC_PLLCFGR_PLLQ STM32_RCC_PLLCFGR_PLLQ_MSK +#define STM32_RCC_PLLCFGR_PLLQ_0 (0x1UL << STM32_RCC_PLLCFGR_PLLQ_POS) +#define STM32_RCC_PLLCFGR_PLLQ_1 (0x2UL << STM32_RCC_PLLCFGR_PLLQ_POS) + +#define STM32_RCC_PLLCFGR_PLLREN_POS 24U +#define STM32_RCC_PLLCFGR_PLLREN_MSK (0x1UL << STM32_RCC_PLLCFGR_PLLREN_POS) +#define STM32_RCC_PLLCFGR_PLLREN STM32_RCC_PLLCFGR_PLLREN_MSK +#define STM32_RCC_PLLCFGR_PLLR_POS 25U +#define STM32_RCC_PLLCFGR_PLLR_MSK (0x3UL << STM32_RCC_PLLCFGR_PLLR_POS) +#define STM32_RCC_PLLCFGR_PLLR STM32_RCC_PLLCFGR_PLLR_MSK +#define STM32_RCC_PLLCFGR_PLLR_0 (0x1UL << STM32_RCC_PLLCFGR_PLLR_POS) +#define STM32_RCC_PLLCFGR_PLLR_1 (0x2UL << STM32_RCC_PLLCFGR_PLLR_POS) + +#define STM32_RCC_PLLCFGR_PLLPDIV_POS 27U +#define STM32_RCC_PLLCFGR_PLLPDIV_MSK (0x1FUL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV STM32_RCC_PLLCFGR_PLLPDIV_MSK +#define STM32_RCC_PLLCFGR_PLLPDIV_0 (0x01UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV_1 (0x02UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV_2 (0x04UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV_3 (0x08UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV_4 (0x10UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) + +/**************** BIT DEFINITION FOR STM32_RCC_PLLSAI1CFGR REGISTER ********/ +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS 8U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_MSK \ + (0x7FUL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N STM32_RCC_PLLSAI1CFGR_PLLSAI1N_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_0 \ + (0x01UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_1 \ + (0x02UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_2 \ + (0x04UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_3 \ + (0x08UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_4 \ + (0x10UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_5 \ + (0x20UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_6 \ + (0x40UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) + +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN_POS 16U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN_MSK \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1P_POS 17U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1P_MSK \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1P_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1P STM32_RCC_PLLSAI1CFGR_PLLSAI1P_MSK + +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN_POS 20U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN_MSK \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_POS 21U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_MSK \ + (0x3UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_0 \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_1 \ + (0x2UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_POS) + +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1REN_POS 24U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1REN_MSK \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1REN_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1REN STM32_RCC_PLLSAI1CFGR_PLLSAI1REN_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R_POS 25U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R_MSK \ + (0x3UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1R_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R STM32_RCC_PLLSAI1CFGR_PLLSAI1R_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R_0 \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1R_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R_1 \ + (0x2UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1R_POS) + +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS 27U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_MSK \ + (0x1FUL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_0 \ + (0x01UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_1 \ + (0x02UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_2 \ + (0x04UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_3 \ + (0x08UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_4 \ + (0x10UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) + +/************** BIT DEFINITION FOR STM32_RCC_CIER REGISTER ******************/ +#define STM32_RCC_CIER_LSIRDYIE_POS 0U +#define STM32_RCC_CIER_LSIRDYIE_MSK (0x1UL << STM32_RCC_CIER_LSIRDYIE_POS) +#define STM32_RCC_CIER_LSIRDYIE STM32_RCC_CIER_LSIRDYIE_MSK +#define STM32_RCC_CIER_LSERDYIE_POS 1U +#define STM32_RCC_CIER_LSERDYIE_MSK (0x1UL << STM32_RCC_CIER_LSERDYIE_POS) +#define STM32_RCC_CIER_LSERDYIE STM32_RCC_CIER_LSERDYIE_MSK +#define STM32_RCC_CIER_MSIRDYIE_POS 2U +#define STM32_RCC_CIER_MSIRDYIE_MSK (0x1UL << STM32_RCC_CIER_MSIRDYIE_POS) +#define STM32_RCC_CIER_MSIRDYIE STM32_RCC_CIER_MSIRDYIE_MSK +#define STM32_RCC_CIER_HSIRDYIE_POS 3U +#define STM32_RCC_CIER_HSIRDYIE_MSK (0x1UL << STM32_RCC_CIER_HSIRDYIE_POS) +#define STM32_RCC_CIER_HSIRDYIE STM32_RCC_CIER_HSIRDYIE_MSK +#define STM32_RCC_CIER_HSERDYIE_POS 4U +#define STM32_RCC_CIER_HSERDYIE_MSK (0x1UL << STM32_RCC_CIER_HSERDYIE_POS) +#define STM32_RCC_CIER_HSERDYIE STM32_RCC_CIER_HSERDYIE_MSK +#define STM32_RCC_CIER_PLLRDYIE_POS 5U +#define STM32_RCC_CIER_PLLRDYIE_MSK (0x1UL << STM32_RCC_CIER_PLLRDYIE_POS) +#define STM32_RCC_CIER_PLLRDYIE STM32_RCC_CIER_PLLRDYIE_MSK +#define STM32_RCC_CIER_PLLSAI1RDYIE_POS 6U +#define STM32_RCC_CIER_PLLSAI1RDYIE_MSK \ + (0x1UL << STM32_RCC_CIER_PLLSAI1RDYIE_POS) +#define STM32_RCC_CIER_PLLSAI1RDYIE STM32_RCC_CIER_PLLSAI1RDYIE_MSK +#define STM32_RCC_CIER_LSECSSIE_POS 9U +#define STM32_RCC_CIER_LSECSSIE_MSK (0x1UL << STM32_RCC_CIER_LSECSSIE_POS) +#define STM32_RCC_CIER_LSECSSIE STM32_RCC_CIER_LSECSSIE_MSK +#define STM32_RCC_CIER_HSI48RDYIE_POS 10U +#define STM32_RCC_CIER_HSI48RDYIE_MSK (0x1UL << STM32_RCC_CIER_HSI48RDYIE_POS) +#define STM32_RCC_CIER_HSI48RDYIE STM32_RCC_CIER_HSI48RDYIE_MSK + +/************** BIT DEFINITION FOR STM32_RCC_CIFR REGISTER ******************/ +#define STM32_RCC_CIFR_LSIRDYF_POS 0U +#define STM32_RCC_CIFR_LSIRDYF_MSK (0x1UL << STM32_RCC_CIFR_LSIRDYF_POS) +#define STM32_RCC_CIFR_LSIRDYF STM32_RCC_CIFR_LSIRDYF_MSK +#define STM32_RCC_CIFR_LSERDYF_POS 1U +#define STM32_RCC_CIFR_LSERDYF_MSK (0x1UL << STM32_RCC_CIFR_LSERDYF_POS) +#define STM32_RCC_CIFR_LSERDYF STM32_RCC_CIFR_LSERDYF_MSK +#define STM32_RCC_CIFR_MSIRDYF_POS 2U +#define STM32_RCC_CIFR_MSIRDYF_MSK (0x1UL << STM32_RCC_CIFR_MSIRDYF_POS) +#define STM32_RCC_CIFR_MSIRDYF STM32_RCC_CIFR_MSIRDYF_MSK +#define STM32_RCC_CIFR_HSIRDYF_POS 3U +#define STM32_RCC_CIFR_HSIRDYF_MSK (0x1UL << STM32_RCC_CIFR_HSIRDYF_POS) +#define STM32_RCC_CIFR_HSIRDYF STM32_RCC_CIFR_HSIRDYF_MSK +#define STM32_RCC_CIFR_HSERDYF_POS 4U +#define STM32_RCC_CIFR_HSERDYF_MSK (0x1UL << STM32_RCC_CIFR_HSERDYF_POS) +#define STM32_RCC_CIFR_HSERDYF STM32_RCC_CIFR_HSERDYF_MSK +#define STM32_RCC_CIFR_PLLRDYF_POS 5U +#define STM32_RCC_CIFR_PLLRDYF_MSK (0x1UL << STM32_RCC_CIFR_PLLRDYF_POS) +#define STM32_RCC_CIFR_PLLRDYF STM32_RCC_CIFR_PLLRDYF_MSK +#define STM32_RCC_CIFR_PLLSAI1RDYF_POS 6U +#define STM32_RCC_CIFR_PLLSAI1RDYF_MSK (0x1UL << STM32_RCC_CIFR_PLLSAI1RDYF_POS) +#define STM32_RCC_CIFR_PLLSAI1RDYF STM32_RCC_CIFR_PLLSAI1RDYF_MSK +#define STM32_RCC_CIFR_CSSF_POS 8U +#define STM32_RCC_CIFR_CSSF_MSK (0x1UL << STM32_RCC_CIFR_CSSF_POS) +#define STM32_RCC_CIFR_CSSF STM32_RCC_CIFR_CSSF_MSK +#define STM32_RCC_CIFR_LSECSSF_POS 9U +#define STM32_RCC_CIFR_LSECSSF_MSK (0x1UL << STM32_RCC_CIFR_LSECSSF_POS) +#define STM32_RCC_CIFR_LSECSSF STM32_RCC_CIFR_LSECSSF_MSK +#define STM32_RCC_CIFR_HSI48RDYF_POS 10U +#define STM32_RCC_CIFR_HSI48RDYF_MSK (0x1UL << STM32_RCC_CIFR_HSI48RDYF_POS) +#define STM32_RCC_CIFR_HSI48RDYF STM32_RCC_CIFR_HSI48RDYF_MSK + +/************** BIT DEFINITION FOR STM32_RCC_CICR REGISTER ******************/ +#define STM32_RCC_CICR_LSIRDYC_POS 0U +#define STM32_RCC_CICR_LSIRDYC_MSK (0x1UL << STM32_RCC_CICR_LSIRDYC_POS) +#define STM32_RCC_CICR_LSIRDYC STM32_RCC_CICR_LSIRDYC_MSK +#define STM32_RCC_CICR_LSERDYC_POS 1U +#define STM32_RCC_CICR_LSERDYC_MSK (0x1UL << STM32_RCC_CICR_LSERDYC_POS) +#define STM32_RCC_CICR_LSERDYC STM32_RCC_CICR_LSERDYC_MSK +#define STM32_RCC_CICR_MSIRDYC_POS 2U +#define STM32_RCC_CICR_MSIRDYC_MSK (0x1UL << STM32_RCC_CICR_MSIRDYC_POS) +#define STM32_RCC_CICR_MSIRDYC STM32_RCC_CICR_MSIRDYC_MSK +#define STM32_RCC_CICR_HSIRDYC_POS 3U +#define STM32_RCC_CICR_HSIRDYC_MSK (0x1UL << STM32_RCC_CICR_HSIRDYC_POS) +#define STM32_RCC_CICR_HSIRDYC STM32_RCC_CICR_HSIRDYC_MSK +#define STM32_RCC_CICR_HSERDYC_POS 4U +#define STM32_RCC_CICR_HSERDYC_MSK (0x1UL << STM32_RCC_CICR_HSERDYC_POS) +#define STM32_RCC_CICR_HSERDYC STM32_RCC_CICR_HSERDYC_MSK +#define STM32_RCC_CICR_PLLRDYC_POS 5U +#define STM32_RCC_CICR_PLLRDYC_MSK (0x1UL << STM32_RCC_CICR_PLLRDYC_POS) +#define STM32_RCC_CICR_PLLRDYC STM32_RCC_CICR_PLLRDYC_MSK +#define STM32_RCC_CICR_PLLSAI1RDYC_POS 6U +#define STM32_RCC_CICR_PLLSAI1RDYC_MSK (0x1UL << STM32_RCC_CICR_PLLSAI1RDYC_POS) +#define STM32_RCC_CICR_PLLSAI1RDYC STM32_RCC_CICR_PLLSAI1RDYC_MSK +#define STM32_RCC_CICR_CSSC_POS 8U +#define STM32_RCC_CICR_CSSC_MSK (0x1UL << STM32_RCC_CICR_CSSC_POS) +#define STM32_RCC_CICR_CSSC STM32_RCC_CICR_CSSC_MSK +#define STM32_RCC_CICR_LSECSSC_POS 9U +#define STM32_RCC_CICR_LSECSSC_MSK (0x1UL << STM32_RCC_CICR_LSECSSC_POS) +#define STM32_RCC_CICR_LSECSSC STM32_RCC_CICR_LSECSSC_MSK +#define STM32_RCC_CICR_HSI48RDYC_POS 10U +#define STM32_RCC_CICR_HSI48RDYC_MSK (0x1UL << STM32_RCC_CICR_HSI48RDYC_POS) +#define STM32_RCC_CICR_HSI48RDYC STM32_RCC_CICR_HSI48RDYC_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB1RSTR REGISTER **************/ +#define STM32_RCC_AHB1RSTR_DMA1RST_POS 0U +#define STM32_RCC_AHB1RSTR_DMA1RST_MSK (0x1UL << STM32_RCC_AHB1RSTR_DMA1RST_POS) +#define STM32_RCC_AHB1RSTR_DMA1RST STM32_RCC_AHB1RSTR_DMA1RST_MSK +#define STM32_RCC_AHB1RSTR_DMA2RST_POS 1U +#define STM32_RCC_AHB1RSTR_DMA2RST_MSK (0x1UL << STM32_RCC_AHB1RSTR_DMA2RST_POS) +#define STM32_RCC_AHB1RSTR_DMA2RST STM32_RCC_AHB1RSTR_DMA2RST_MSK +#define STM32_RCC_AHB1RSTR_FLASHRST_POS 8U +#define STM32_RCC_AHB1RSTR_FLASHRST_MSK \ + (0x1UL << STM32_RCC_AHB1RSTR_FLASHRST_POS) +#define STM32_RCC_AHB1RSTR_FLASHRST STM32_RCC_AHB1RSTR_FLASHRST_MSK +#define STM32_RCC_AHB1RSTR_CRCRST_POS 12U +#define STM32_RCC_AHB1RSTR_CRCRST_MSK (0x1UL << STM32_RCC_AHB1RSTR_CRCRST_POS) +#define STM32_RCC_AHB1RSTR_CRCRST STM32_RCC_AHB1RSTR_CRCRST_MSK +#define STM32_RCC_AHB1RSTR_TSCRST_POS 16U +#define STM32_RCC_AHB1RSTR_TSCRST_MSK (0x1UL << STM32_RCC_AHB1RSTR_TSCRST_POS) +#define STM32_RCC_AHB1RSTR_TSCRST STM32_RCC_AHB1RSTR_TSCRST_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB2RSTR REGISTER **************/ +#define STM32_RCC_AHB2RSTR_GPIOARST_POS 0U +#define STM32_RCC_AHB2RSTR_GPIOARST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOARST_POS) +#define STM32_RCC_AHB2RSTR_GPIOARST STM32_RCC_AHB2RSTR_GPIOARST_MSK +#define STM32_RCC_AHB2RSTR_GPIOBRST_POS 1U +#define STM32_RCC_AHB2RSTR_GPIOBRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOBRST_POS) +#define STM32_RCC_AHB2RSTR_GPIOBRST STM32_RCC_AHB2RSTR_GPIOBRST_MSK +#define STM32_RCC_AHB2RSTR_GPIOCRST_POS 2U +#define STM32_RCC_AHB2RSTR_GPIOCRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOCRST_POS) +#define STM32_RCC_AHB2RSTR_GPIOCRST STM32_RCC_AHB2RSTR_GPIOCRST_MSK +#define STM32_RCC_AHB2RSTR_GPIODRST_POS 3U +#define STM32_RCC_AHB2RSTR_GPIODRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIODRST_POS) +#define STM32_RCC_AHB2RSTR_GPIODRST STM32_RCC_AHB2RSTR_GPIODRST_MSK +#define STM32_RCC_AHB2RSTR_GPIOERST_POS 4U +#define STM32_RCC_AHB2RSTR_GPIOERST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOERST_POS) +#define STM32_RCC_AHB2RSTR_GPIOERST STM32_RCC_AHB2RSTR_GPIOERST_MSK +#define STM32_RCC_AHB2RSTR_GPIOHRST_POS 7U +#define STM32_RCC_AHB2RSTR_GPIOHRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOHRST_POS) +#define STM32_RCC_AHB2RSTR_GPIOHRST STM32_RCC_AHB2RSTR_GPIOHRST_MSK +#define STM32_RCC_AHB2RSTR_ADCRST_POS 13U +#define STM32_RCC_AHB2RSTR_ADCRST_MSK (0x1UL << STM32_RCC_AHB2RSTR_ADCRST_POS) +#define STM32_RCC_AHB2RSTR_ADCRST STM32_RCC_AHB2RSTR_ADCRST_MSK +#define STM32_RCC_AHB2RSTR_AESRST_POS 16U +#define STM32_RCC_AHB2RSTR_AESRST_MSK (0x1UL << STM32_RCC_AHB2RSTR_AESRST_POS) +#define STM32_RCC_AHB2RSTR_AESRST STM32_RCC_AHB2RSTR_AESRST_MSK +#define STM32_RCC_AHB2RSTR_RNGRST_POS 18U +#define STM32_RCC_AHB2RSTR_RNGRST_MSK (0x1UL << STM32_RCC_AHB2RSTR_RNGRST_POS) +#define STM32_RCC_AHB2RSTR_RNGRST STM32_RCC_AHB2RSTR_RNGRST_MSK + +/************* BIT DEFINITION FOR STM32_RCC_AHB3RSTR REGISTER **************/ +#define STM32_RCC_AHB3RSTR_QSPIRST_POS 8U +#define STM32_RCC_AHB3RSTR_QSPIRST_MSK (0x1UL << STM32_RCC_AHB3RSTR_QSPIRST_POS) +#define STM32_RCC_AHB3RSTR_QSPIRST STM32_RCC_AHB3RSTR_QSPIRST_MSK + +/************* BIT DEFINITION FOR STM32_RCC_APB1RSTR1 REGISTER **************/ +#define STM32_RCC_APB1RSTR1_TIM2RST_POS 0U +#define STM32_RCC_APB1RSTR1_TIM2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_TIM2RST_POS) +#define STM32_RCC_APB1RSTR1_TIM2RST STM32_RCC_APB1RSTR1_TIM2RST_MSK +#define STM32_RCC_APB1RSTR1_TIM6RST_POS 4U +#define STM32_RCC_APB1RSTR1_TIM6RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_TIM6RST_POS) +#define STM32_RCC_APB1RSTR1_TIM6RST STM32_RCC_APB1RSTR1_TIM6RST_MSK +#define STM32_RCC_APB1RSTR1_TIM7RST_POS 5U +#define STM32_RCC_APB1RSTR1_TIM7RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_TIM7RST_POS) +#define STM32_RCC_APB1RSTR1_TIM7RST STM32_RCC_APB1RSTR1_TIM7RST_MSK +#define STM32_RCC_APB1RSTR1_LCDRST_POS 9U +#define STM32_RCC_APB1RSTR1_LCDRST_MSK (0x1UL << STM32_RCC_APB1RSTR1_LCDRST_POS) +#define STM32_RCC_APB1RSTR1_LCDRST STM32_RCC_APB1RSTR1_LCDRST_MSK +#define STM32_RCC_APB1RSTR1_SPI2RST_POS 14U +#define STM32_RCC_APB1RSTR1_SPI2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_SPI2RST_POS) +#define STM32_RCC_APB1RSTR1_SPI2RST STM32_RCC_APB1RSTR1_SPI2RST_MSK +#define STM32_RCC_APB1RSTR1_SPI3RST_POS 15U +#define STM32_RCC_APB1RSTR1_SPI3RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_SPI3RST_POS) +#define STM32_RCC_APB1RSTR1_SPI3RST STM32_RCC_APB1RSTR1_SPI3RST_MSK +#define STM32_RCC_APB1RSTR1_USART2RST_POS 17U +#define STM32_RCC_APB1RSTR1_USART2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_USART2RST_POS) +#define STM32_RCC_APB1RSTR1_USART2RST STM32_RCC_APB1RSTR1_USART2RST_MSK +#define STM32_RCC_APB1RSTR1_USART3RST_POS 18U +#define STM32_RCC_APB1RSTR1_USART3RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_USART3RST_POS) +#define STM32_RCC_APB1RSTR1_USART3RST STM32_RCC_APB1RSTR1_USART3RST_MSK +#define STM32_RCC_APB1RSTR1_I2C1RST_POS 21U +#define STM32_RCC_APB1RSTR1_I2C1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_I2C1RST_POS) +#define STM32_RCC_APB1RSTR1_I2C1RST STM32_RCC_APB1RSTR1_I2C1RST_MSK +#define STM32_RCC_APB1RSTR1_I2C2RST_POS 22U +#define STM32_RCC_APB1RSTR1_I2C2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_I2C2RST_POS) +#define STM32_RCC_APB1RSTR1_I2C2RST STM32_RCC_APB1RSTR1_I2C2RST_MSK +#define STM32_RCC_APB1RSTR1_I2C3RST_POS 23U +#define STM32_RCC_APB1RSTR1_I2C3RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_I2C3RST_POS) +#define STM32_RCC_APB1RSTR1_I2C3RST STM32_RCC_APB1RSTR1_I2C3RST_MSK +#define STM32_RCC_APB1RSTR1_CRSRST_POS 24U +#define STM32_RCC_APB1RSTR1_CRSRST_MSK (0x1UL << STM32_RCC_APB1RSTR1_CRSRST_POS) +#define STM32_RCC_APB1RSTR1_CRSRST STM32_RCC_APB1RSTR1_CRSRST_MSK +#define STM32_RCC_APB1RSTR1_CAN1RST_POS 25U +#define STM32_RCC_APB1RSTR1_CAN1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_CAN1RST_POS) +#define STM32_RCC_APB1RSTR1_CAN1RST STM32_RCC_APB1RSTR1_CAN1RST_MSK +#define STM32_RCC_APB1RSTR1_USBFSRST_POS 26U +#define STM32_RCC_APB1RSTR1_USBFSRST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_USBFSRST_POS) +#define STM32_RCC_APB1RSTR1_USBFSRST STM32_RCC_APB1RSTR1_USBFSRST_MSK +#define STM32_RCC_APB1RSTR1_PWRRST_POS 28U +#define STM32_RCC_APB1RSTR1_PWRRST_MSK (0x1UL << STM32_RCC_APB1RSTR1_PWRRST_POS) +#define STM32_RCC_APB1RSTR1_PWRRST STM32_RCC_APB1RSTR1_PWRRST_MSK +#define STM32_RCC_APB1RSTR1_DAC1RST_POS 29U +#define STM32_RCC_APB1RSTR1_DAC1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_DAC1RST_POS) +#define STM32_RCC_APB1RSTR1_DAC1RST STM32_RCC_APB1RSTR1_DAC1RST_MSK +#define STM32_RCC_APB1RSTR1_OPAMPRST_POS 30U +#define STM32_RCC_APB1RSTR1_OPAMPRST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_OPAMPRST_POS) +#define STM32_RCC_APB1RSTR1_OPAMPRST STM32_RCC_APB1RSTR1_OPAMPRST_MSK +#define STM32_RCC_APB1RSTR1_LPTIM1RST_POS 31U +#define STM32_RCC_APB1RSTR1_LPTIM1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_LPTIM1RST_POS) +#define STM32_RCC_APB1RSTR1_LPTIM1RST STM32_RCC_APB1RSTR1_LPTIM1RST_MSK + +/************* BIT DEFINITION FOR STM32_RCC_APB1RSTR2 REGISTER **************/ +#define STM32_RCC_APB1RSTR2_LPUART1RST_POS 0U +#define STM32_RCC_APB1RSTR2_LPUART1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_LPUART1RST_POS) +#define STM32_RCC_APB1RSTR2_LPUART1RST STM32_RCC_APB1RSTR2_LPUART1RST_MSK +#define STM32_RCC_APB1RSTR2_SWPMI1RST_POS 2U +#define STM32_RCC_APB1RSTR2_SWPMI1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_SWPMI1RST_POS) +#define STM32_RCC_APB1RSTR2_SWPMI1RST STM32_RCC_APB1RSTR2_SWPMI1RST_MSK +#define STM32_RCC_APB1RSTR2_LPTIM2RST_POS 5U +#define STM32_RCC_APB1RSTR2_LPTIM2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_LPTIM2RST_POS) +#define STM32_RCC_APB1RSTR2_LPTIM2RST STM32_RCC_APB1RSTR2_LPTIM2RST_MSK + +/************** BIT DEFINITION FOR STM32_RCC_APB2RSTR REGISTER **************/ +#define STM32_RCC_APB2RSTR_SYSCFGRST_POS 0U +#define STM32_RCC_APB2RSTR_SYSCFGRST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_SYSCFGRST_POS) +#define STM32_RCC_APB2RSTR_SYSCFGRST STM32_RCC_APB2RSTR_SYSCFGRST_MSK +#define STM32_RCC_APB2RSTR_SDMMC1RST_POS 10U +#define STM32_RCC_APB2RSTR_SDMMC1RST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_SDMMC1RST_POS) +#define STM32_RCC_APB2RSTR_SDMMC1RST STM32_RCC_APB2RSTR_SDMMC1RST_MSK +#define STM32_RCC_APB2RSTR_TIM1RST_POS 11U +#define STM32_RCC_APB2RSTR_TIM1RST_MSK (0x1UL << STM32_RCC_APB2RSTR_TIM1RST_POS) +#define STM32_RCC_APB2RSTR_TIM1RST STM32_RCC_APB2RSTR_TIM1RST_MSK +#define STM32_RCC_APB2RSTR_SPI1RST_POS 12U +#define STM32_RCC_APB2RSTR_SPI1RST_MSK (0x1UL << STM32_RCC_APB2RSTR_SPI1RST_POS) +#define STM32_RCC_APB2RSTR_SPI1RST STM32_RCC_APB2RSTR_SPI1RST_MSK +#define STM32_RCC_APB2RSTR_USART1RST_POS 14U +#define STM32_RCC_APB2RSTR_USART1RST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_USART1RST_POS) +#define STM32_RCC_APB2RSTR_USART1RST STM32_RCC_APB2RSTR_USART1RST_MSK +#define STM32_RCC_APB2RSTR_TIM15RST_POS 16U +#define STM32_RCC_APB2RSTR_TIM15RST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_TIM15RST_POS) +#define STM32_RCC_APB2RSTR_TIM15RST STM32_RCC_APB2RSTR_TIM15RST_MSK +#define STM32_RCC_APB2RSTR_TIM16RST_POS 17U +#define STM32_RCC_APB2RSTR_TIM16RST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_TIM16RST_POS) +#define STM32_RCC_APB2RSTR_TIM16RST STM32_RCC_APB2RSTR_TIM16RST_MSK +#define STM32_RCC_APB2RSTR_SAI1RST_POS 21U +#define STM32_RCC_APB2RSTR_SAI1RST_MSK (0x1UL << STM32_RCC_APB2RSTR_SAI1RST_POS) +#define STM32_RCC_APB2RSTR_SAI1RST STM32_RCC_APB2RSTR_SAI1RST_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB1ENR REGISTER ***************/ +#define STM32_RCC_AHB1ENR_DMA1EN_POS 0U +#define STM32_RCC_AHB1ENR_DMA1EN_MSK (0x1UL << STM32_RCC_AHB1ENR_DMA1EN_POS) +#define STM32_RCC_AHB1ENR_DMA1EN STM32_RCC_AHB1ENR_DMA1EN_MSK +#define STM32_RCC_AHB1ENR_DMA2EN_POS 1U +#define STM32_RCC_AHB1ENR_DMA2EN_MSK (0x1UL << STM32_RCC_AHB1ENR_DMA2EN_POS) +#define STM32_RCC_AHB1ENR_DMA2EN STM32_RCC_AHB1ENR_DMA2EN_MSK +#define STM32_RCC_AHB1ENR_FLASHEN_POS 8U +#define STM32_RCC_AHB1ENR_FLASHEN_MSK (0x1UL << STM32_RCC_AHB1ENR_FLASHEN_POS) +#define STM32_RCC_AHB1ENR_FLASHEN STM32_RCC_AHB1ENR_FLASHEN_MSK +#define STM32_RCC_AHB1ENR_CRCEN_POS 12U +#define STM32_RCC_AHB1ENR_CRCEN_MSK (0x1UL << STM32_RCC_AHB1ENR_CRCEN_POS) +#define STM32_RCC_AHB1ENR_CRCEN STM32_RCC_AHB1ENR_CRCEN_MSK +#define STM32_RCC_AHB1ENR_TSCEN_POS 16U +#define STM32_RCC_AHB1ENR_TSCEN_MSK (0x1UL << STM32_RCC_AHB1ENR_TSCEN_POS) +#define STM32_RCC_AHB1ENR_TSCEN STM32_RCC_AHB1ENR_TSCEN_MSK + +/*************** BIT DEFINITION FOR STM32_RCC_AHB2ENR REGISTER *********/ +#define STM32_RCC_AHB2ENR_GPIOAEN_POS 0U +#define STM32_RCC_AHB2ENR_GPIOAEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOAEN_POS) +#define STM32_RCC_AHB2ENR_GPIOAEN STM32_RCC_AHB2ENR_GPIOAEN_MSK +#define STM32_RCC_AHB2ENR_GPIOBEN_POS 1U +#define STM32_RCC_AHB2ENR_GPIOBEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOBEN_POS) +#define STM32_RCC_AHB2ENR_GPIOBEN STM32_RCC_AHB2ENR_GPIOBEN_MSK +#define STM32_RCC_AHB2ENR_GPIOCEN_POS 2U +#define STM32_RCC_AHB2ENR_GPIOCEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOCEN_POS) +#define STM32_RCC_AHB2ENR_GPIOCEN STM32_RCC_AHB2ENR_GPIOCEN_MSK +#define STM32_RCC_AHB2ENR_GPIODEN_POS 3U +#define STM32_RCC_AHB2ENR_GPIODEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIODEN_POS) +#define STM32_RCC_AHB2ENR_GPIODEN STM32_RCC_AHB2ENR_GPIODEN_MSK +#define STM32_RCC_AHB2ENR_GPIOEEN_POS 4U +#define STM32_RCC_AHB2ENR_GPIOEEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOEEN_POS) +#define STM32_RCC_AHB2ENR_GPIOEEN STM32_RCC_AHB2ENR_GPIOEEN_MSK +#define STM32_RCC_AHB2ENR_GPIOHEN_POS 7U +#define STM32_RCC_AHB2ENR_GPIOHEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOHEN_POS) +#define STM32_RCC_AHB2ENR_GPIOHEN STM32_RCC_AHB2ENR_GPIOHEN_MSK +#define STM32_RCC_AHB2ENR_ADCEN_POS 13U +#define STM32_RCC_AHB2ENR_ADCEN_MSK (0x1UL << STM32_RCC_AHB2ENR_ADCEN_POS) +#define STM32_RCC_AHB2ENR_ADCEN STM32_RCC_AHB2ENR_ADCEN_MSK +#define STM32_RCC_AHB2ENR_AESEN_POS 16U +#define STM32_RCC_AHB2ENR_AESEN_MSK (0x1UL << STM32_RCC_AHB2ENR_AESEN_POS) +#define STM32_RCC_AHB2ENR_AESEN STM32_RCC_AHB2ENR_AESEN_MSK +#define STM32_RCC_AHB2ENR_RNGEN_POS 18U +#define STM32_RCC_AHB2ENR_RNGEN_MSK (0x1UL << STM32_RCC_AHB2ENR_RNGEN_POS) +#define STM32_RCC_AHB2ENR_RNGEN STM32_RCC_AHB2ENR_RNGEN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB3ENR REGISTER ***************/ +#define STM32_RCC_AHB3ENR_QSPIEN_POS 8U +#define STM32_RCC_AHB3ENR_QSPIEN_MSK (0x1UL << STM32_RCC_AHB3ENR_QSPIEN_POS) +#define STM32_RCC_AHB3ENR_QSPIEN STM32_RCC_AHB3ENR_QSPIEN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_APB1ENR1 REGISTER **************/ +#define STM32_RCC_APB1ENR1_TIM2EN_POS 0U +#define STM32_RCC_APB1ENR1_TIM2EN_MSK (0x1UL << STM32_RCC_APB1ENR1_TIM2EN_POS) +#define STM32_RCC_APB1ENR1_TIM2EN STM32_RCC_APB1ENR1_TIM2EN_MSK +#define STM32_RCC_APB1ENR1_TIM6EN_POS 4U +#define STM32_RCC_APB1ENR1_TIM6EN_MSK (0x1UL << STM32_RCC_APB1ENR1_TIM6EN_POS) +#define STM32_RCC_APB1ENR1_TIM6EN STM32_RCC_APB1ENR1_TIM6EN_MSK +#define STM32_RCC_APB1ENR1_TIM7EN_POS 5U +#define STM32_RCC_APB1ENR1_TIM7EN_MSK (0x1UL << STM32_RCC_APB1ENR1_TIM7EN_POS) +#define STM32_RCC_APB1ENR1_TIM7EN STM32_RCC_APB1ENR1_TIM7EN_MSK +#define STM32_RCC_APB1ENR1_LCDEN_POS 9U +#define STM32_RCC_APB1ENR1_LCDEN_MSK (0x1UL << STM32_RCC_APB1ENR1_LCDEN_POS) +#define STM32_RCC_APB1ENR1_LCDEN STM32_RCC_APB1ENR1_LCDEN_MSK +#define STM32_RCC_APB1ENR1_RTCAPBEN_POS 10U +#define STM32_RCC_APB1ENR1_RTCAPBEN_MSK \ + (0x1UL << STM32_RCC_APB1ENR1_RTCAPBEN_POS) +#define STM32_RCC_APB1ENR1_RTCAPBEN STM32_RCC_APB1ENR1_RTCAPBEN_MSK +#define STM32_RCC_APB1ENR1_WWDGEN_POS 11U +#define STM32_RCC_APB1ENR1_WWDGEN_MSK (0x1UL << STM32_RCC_APB1ENR1_WWDGEN_POS) +#define STM32_RCC_APB1ENR1_WWDGEN STM32_RCC_APB1ENR1_WWDGEN_MSK +#define STM32_RCC_APB1ENR1_SPI2EN_POS 14U +#define STM32_RCC_APB1ENR1_SPI2EN_MSK (0x1UL << STM32_RCC_APB1ENR1_SPI2EN_POS) +#define STM32_RCC_APB1ENR1_SPI2EN STM32_RCC_APB1ENR1_SPI2EN_MSK +#define STM32_RCC_APB1ENR1_SPI3EN_POS 15U +#define STM32_RCC_APB1ENR1_SPI3EN_MSK (0x1UL << STM32_RCC_APB1ENR1_SPI3EN_POS) +#define STM32_RCC_APB1ENR1_SPI3EN STM32_RCC_APB1ENR1_SPI3EN_MSK +#define STM32_RCC_APB1ENR1_USART2EN_POS 17U +#define STM32_RCC_APB1ENR1_USART2EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR1_USART2EN_POS) +#define STM32_RCC_APB1ENR1_USART2EN STM32_RCC_APB1ENR1_USART2EN_MSK +#define STM32_RCC_APB1ENR1_USART3EN_POS 18U +#define STM32_RCC_APB1ENR1_USART3EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR1_USART3EN_POS) +#define STM32_RCC_APB1ENR1_USART3EN STM32_RCC_APB1ENR1_USART3EN_MSK +#define STM32_RCC_APB1ENR1_I2C1EN_POS 21U +#define STM32_RCC_APB1ENR1_I2C1EN_MSK (0x1UL << STM32_RCC_APB1ENR1_I2C1EN_POS) +#define STM32_RCC_APB1ENR1_I2C1EN STM32_RCC_APB1ENR1_I2C1EN_MSK +#define STM32_RCC_APB1ENR1_I2C2EN_POS 22U +#define STM32_RCC_APB1ENR1_I2C2EN_MSK (0x1UL << STM32_RCC_APB1ENR1_I2C2EN_POS) +#define STM32_RCC_APB1ENR1_I2C2EN STM32_RCC_APB1ENR1_I2C2EN_MSK +#define STM32_RCC_APB1ENR1_I2C3EN_POS 23U +#define STM32_RCC_APB1ENR1_I2C3EN_MSK (0x1UL << STM32_RCC_APB1ENR1_I2C3EN_POS) +#define STM32_RCC_APB1ENR1_I2C3EN STM32_RCC_APB1ENR1_I2C3EN_MSK +#define STM32_RCC_APB1ENR1_CRSEN_POS 24U +#define STM32_RCC_APB1ENR1_CRSEN_MSK (0x1UL << STM32_RCC_APB1ENR1_CRSEN_POS) +#define STM32_RCC_APB1ENR1_CRSEN STM32_RCC_APB1ENR1_CRSEN_MSK +#define STM32_RCC_APB1ENR1_CAN1EN_POS 25U +#define STM32_RCC_APB1ENR1_CAN1EN_MSK (0x1UL << STM32_RCC_APB1ENR1_CAN1EN_POS) +#define STM32_RCC_APB1ENR1_CAN1EN STM32_RCC_APB1ENR1_CAN1EN_MSK +#define STM32_RCC_APB1ENR1_USBFSEN_POS 26U +#define STM32_RCC_APB1ENR1_USBFSEN_MSK (0x1UL << STM32_RCC_APB1ENR1_USBFSEN_POS) +#define STM32_RCC_APB1ENR1_USBFSEN STM32_RCC_APB1ENR1_USBFSEN_MSK +#define STM32_RCC_APB1ENR1_PWREN_POS 28U +#define STM32_RCC_APB1ENR1_PWREN_MSK (0x1UL << STM32_RCC_APB1ENR1_PWREN_POS) +#define STM32_RCC_APB1ENR1_PWREN STM32_RCC_APB1ENR1_PWREN_MSK +#define STM32_RCC_APB1ENR1_DAC1EN_POS 29U +#define STM32_RCC_APB1ENR1_DAC1EN_MSK (0x1UL << STM32_RCC_APB1ENR1_DAC1EN_POS) +#define STM32_RCC_APB1ENR1_DAC1EN STM32_RCC_APB1ENR1_DAC1EN_MSK +#define STM32_RCC_APB1ENR1_OPAMPEN_POS 30U +#define STM32_RCC_APB1ENR1_OPAMPEN_MSK (0x1UL << STM32_RCC_APB1ENR1_OPAMPEN_POS) +#define STM32_RCC_APB1ENR1_OPAMPEN STM32_RCC_APB1ENR1_OPAMPEN_MSK +#define STM32_RCC_APB1ENR1_LPTIM1EN_POS 31U +#define STM32_RCC_APB1ENR1_LPTIM1EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR1_LPTIM1EN_POS) +#define STM32_RCC_APB1ENR1_LPTIM1EN STM32_RCC_APB1ENR1_LPTIM1EN_MSK + +/************ BIT DEFINITION FOR STM32_RCC_APB1RSTR2 REGISTER **************/ +#define STM32_RCC_APB1ENR2_LPUART1EN_POS 0U +#define STM32_RCC_APB1ENR2_LPUART1EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR2_LPUART1EN_POS) +#define STM32_RCC_APB1ENR2_LPUART1EN STM32_RCC_APB1ENR2_LPUART1EN_MSK +#define STM32_RCC_APB1ENR2_I2C4EN_POS 1U +#define STM32_RCC_APB1ENR2_I2C4EN_MSK (0x1UL << STM32_RCC_APB1ENR2_I2C4EN_POS) +#define STM32_RCC_APB1ENR2_I2C4EN STM32_RCC_APB1ENR2_I2C4EN_MSK +#define STM32_RCC_APB1ENR2_SWPMI1EN_POS 2U +#define STM32_RCC_APB1ENR2_SWPMI1EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR2_SWPMI1EN_POS) +#define STM32_RCC_APB1ENR2_SWPMI1EN STM32_RCC_APB1ENR2_SWPMI1EN_MSK +#define STM32_RCC_APB1ENR2_LPTIM2EN_POS 5U +#define STM32_RCC_APB1ENR2_LPTIM2EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR2_LPTIM2EN_POS) +#define STM32_RCC_APB1ENR2_LPTIM2EN STM32_RCC_APB1ENR2_LPTIM2EN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_APB2ENR REGISTER ***************/ +#define STM32_RCC_APB2ENR_SYSCFGEN_POS 0U +#define STM32_RCC_APB2ENR_SYSCFGEN_MSK (0x1UL << STM32_RCC_APB2ENR_SYSCFGEN_POS) +#define STM32_RCC_APB2ENR_SYSCFGEN STM32_RCC_APB2ENR_SYSCFGEN_MSK +#define STM32_RCC_APB2ENR_FWEN_POS 7U +#define STM32_RCC_APB2ENR_FWEN_MSK (0x1UL << STM32_RCC_APB2ENR_FWEN_POS) +#define STM32_RCC_APB2ENR_FWEN STM32_RCC_APB2ENR_FWEN_MSK +#define STM32_RCC_APB2ENR_SDMMC1EN_POS 10U +#define STM32_RCC_APB2ENR_SDMMC1EN_MSK (0x1UL << STM32_RCC_APB2ENR_SDMMC1EN_POS) +#define STM32_RCC_APB2ENR_SDMMC1EN STM32_RCC_APB2ENR_SDMMC1EN_MSK +#define STM32_RCC_APB2ENR_TIM1EN_POS 11U +#define STM32_RCC_APB2ENR_TIM1EN_MSK (0x1UL << STM32_RCC_APB2ENR_TIM1EN_POS) +#define STM32_RCC_APB2ENR_TIM1EN STM32_RCC_APB2ENR_TIM1EN_MSK +#define STM32_RCC_APB2ENR_SPI1EN_POS 12U +#define STM32_RCC_APB2ENR_SPI1EN_MSK (0x1UL << STM32_RCC_APB2ENR_SPI1EN_POS) +#define STM32_RCC_APB2ENR_SPI1EN STM32_RCC_APB2ENR_SPI1EN_MSK +#define STM32_RCC_APB2ENR_USART1EN_POS 14U +#define STM32_RCC_APB2ENR_USART1EN_MSK (0x1UL << STM32_RCC_APB2ENR_USART1EN_POS) +#define STM32_RCC_APB2ENR_USART1EN STM32_RCC_APB2ENR_USART1EN_MSK +#define STM32_RCC_APB2ENR_TIM15EN_POS 16U +#define STM32_RCC_APB2ENR_TIM15EN_MSK (0x1UL << STM32_RCC_APB2ENR_TIM15EN_POS) +#define STM32_RCC_APB2ENR_TIM15EN STM32_RCC_APB2ENR_TIM15EN_MSK +#define STM32_RCC_APB2ENR_TIM16EN_POS 17U +#define STM32_RCC_APB2ENR_TIM16EN_MSK (0x1UL << STM32_RCC_APB2ENR_TIM16EN_POS) +#define STM32_RCC_APB2ENR_TIM16EN STM32_RCC_APB2ENR_TIM16EN_MSK +#define STM32_RCC_APB2ENR_SAI1EN_POS 21U +#define STM32_RCC_APB2ENR_SAI1EN_MSK (0x1UL << STM32_RCC_APB2ENR_SAI1EN_POS) +#define STM32_RCC_APB2ENR_SAI1EN STM32_RCC_APB2ENR_SAI1EN_MSK + +/************ BIT DEFINITION FOR STM32_RCC_AHB1SMENR REGISTER ***************/ +#define STM32_RCC_AHB1SMENR_DMA1SMEN_POS 0U +#define STM32_RCC_AHB1SMENR_DMA1SMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_DMA1SMEN_POS) +#define STM32_RCC_AHB1SMENR_DMA1SMEN STM32_RCC_AHB1SMENR_DMA1SMEN_MSK +#define STM32_RCC_AHB1SMENR_DMA2SMEN_POS 1U +#define STM32_RCC_AHB1SMENR_DMA2SMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_DMA2SMEN_POS) +#define STM32_RCC_AHB1SMENR_DMA2SMEN STM32_RCC_AHB1SMENR_DMA2SMEN_MSK +#define STM32_RCC_AHB1SMENR_FLASHSMEN_POS 8U +#define STM32_RCC_AHB1SMENR_FLASHSMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_FLASHSMEN_POS) +#define STM32_RCC_AHB1SMENR_FLASHSMEN STM32_RCC_AHB1SMENR_FLASHSMEN_MSK +#define STM32_RCC_AHB1SMENR_SRAM1SMEN_POS 9U +#define STM32_RCC_AHB1SMENR_SRAM1SMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_SRAM1SMEN_POS) +#define STM32_RCC_AHB1SMENR_SRAM1SMEN STM32_RCC_AHB1SMENR_SRAM1SMEN_MSK +#define STM32_RCC_AHB1SMENR_CRCSMEN_POS 12U +#define STM32_RCC_AHB1SMENR_CRCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_CRCSMEN_POS) +#define STM32_RCC_AHB1SMENR_CRCSMEN STM32_RCC_AHB1SMENR_CRCSMEN_MSK +#define STM32_RCC_AHB1SMENR_TSCSMEN_POS 16U +#define STM32_RCC_AHB1SMENR_TSCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_TSCSMEN_POS) +#define STM32_RCC_AHB1SMENR_TSCSMEN STM32_RCC_AHB1SMENR_TSCSMEN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB2SMENR REGISTER *************/ +#define STM32_RCC_AHB2SMENR_GPIOASMEN_POS 0U +#define STM32_RCC_AHB2SMENR_GPIOASMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOASMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOASMEN STM32_RCC_AHB2SMENR_GPIOASMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOBSMEN_POS 1U +#define STM32_RCC_AHB2SMENR_GPIOBSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOBSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOBSMEN STM32_RCC_AHB2SMENR_GPIOBSMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOCSMEN_POS 2U +#define STM32_RCC_AHB2SMENR_GPIOCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOCSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOCSMEN STM32_RCC_AHB2SMENR_GPIOCSMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIODSMEN_POS 3U +#define STM32_RCC_AHB2SMENR_GPIODSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIODSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIODSMEN STM32_RCC_AHB2SMENR_GPIODSMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOESMEN_POS 4U +#define STM32_RCC_AHB2SMENR_GPIOESMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOESMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOESMEN STM32_RCC_AHB2SMENR_GPIOESMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOHSMEN_POS 7U +#define STM32_RCC_AHB2SMENR_GPIOHSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOHSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOHSMEN STM32_RCC_AHB2SMENR_GPIOHSMEN_MSK +#define STM32_RCC_AHB2SMENR_SRAM2SMEN_POS 9U +#define STM32_RCC_AHB2SMENR_SRAM2SMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_SRAM2SMEN_POS) +#define STM32_RCC_AHB2SMENR_SRAM2SMEN STM32_RCC_AHB2SMENR_SRAM2SMEN_MSK +#define STM32_RCC_AHB2SMENR_ADCSMEN_POS 13U +#define STM32_RCC_AHB2SMENR_ADCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_ADCSMEN_POS) +#define STM32_RCC_AHB2SMENR_ADCSMEN STM32_RCC_AHB2SMENR_ADCSMEN_MSK +#define STM32_RCC_AHB2SMENR_AESSMEN_POS 16U +#define STM32_RCC_AHB2SMENR_AESSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_AESSMEN_POS) +#define STM32_RCC_AHB2SMENR_AESSMEN STM32_RCC_AHB2SMENR_AESSMEN_MSK +#define STM32_RCC_AHB2SMENR_RNGSMEN_POS 18U +#define STM32_RCC_AHB2SMENR_RNGSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_RNGSMEN_POS) +#define STM32_RCC_AHB2SMENR_RNGSMEN STM32_RCC_AHB2SMENR_RNGSMEN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB3SMENR REGISTER *************/ +#define STM32_RCC_AHB3SMENR_QSPISMEN_POS 8U +#define STM32_RCC_AHB3SMENR_QSPISMEN_MSK \ + (0x1UL << STM32_RCC_AHB3SMENR_QSPISMEN_POS) +#define STM32_RCC_AHB3SMENR_QSPISMEN STM32_RCC_AHB3SMENR_QSPISMEN_MSK + +/************* BIT DEFINITION FOR STM32_RCC_APB1SMENR1 REGISTER *************/ +#define STM32_RCC_APB1SMENR1_TIM2SMEN_POS 0U +#define STM32_RCC_APB1SMENR1_TIM2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_TIM2SMEN_POS) +#define STM32_RCC_APB1SMENR1_TIM2SMEN STM32_RCC_APB1SMENR1_TIM2SMEN_MSK +#define STM32_RCC_APB1SMENR1_TIM6SMEN_POS 4U +#define STM32_RCC_APB1SMENR1_TIM6SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_TIM6SMEN_POS) +#define STM32_RCC_APB1SMENR1_TIM6SMEN STM32_RCC_APB1SMENR1_TIM6SMEN_MSK +#define STM32_RCC_APB1SMENR1_TIM7SMEN_POS 5U +#define STM32_RCC_APB1SMENR1_TIM7SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_TIM7SMEN_POS) +#define STM32_RCC_APB1SMENR1_TIM7SMEN STM32_RCC_APB1SMENR1_TIM7SMEN_MSK +#define STM32_RCC_APB1SMENR1_LCDSMEN_POS 9U +#define STM32_RCC_APB1SMENR1_LCDSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_LCDSMEN_POS) +#define STM32_RCC_APB1SMENR1_LCDSMEN STM32_RCC_APB1SMENR1_LCDSMEN_MSK +#define STM32_RCC_APB1SMENR1_RTCAPBSMEN_POS 10U +#define STM32_RCC_APB1SMENR1_RTCAPBSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_RTCAPBSMEN_POS) +#define STM32_RCC_APB1SMENR1_RTCAPBSMEN STM32_RCC_APB1SMENR1_RTCAPBSMEN_MSK +#define STM32_RCC_APB1SMENR1_WWDGSMEN_POS 11U +#define STM32_RCC_APB1SMENR1_WWDGSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_WWDGSMEN_POS) +#define STM32_RCC_APB1SMENR1_WWDGSMEN STM32_RCC_APB1SMENR1_WWDGSMEN_MSK +#define STM32_RCC_APB1SMENR1_SPI2SMEN_POS 14U +#define STM32_RCC_APB1SMENR1_SPI2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_SPI2SMEN_POS) +#define STM32_RCC_APB1SMENR1_SPI2SMEN STM32_RCC_APB1SMENR1_SPI2SMEN_MSK +#define STM32_RCC_APB1SMENR1_SPI3SMEN_POS 15U +#define STM32_RCC_APB1SMENR1_SPI3SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_SPI3SMEN_POS) +#define STM32_RCC_APB1SMENR1_SPI3SMEN STM32_RCC_APB1SMENR1_SPI3SMEN_MSK +#define STM32_RCC_APB1SMENR1_USART2SMEN_POS 17U +#define STM32_RCC_APB1SMENR1_USART2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_USART2SMEN_POS) +#define STM32_RCC_APB1SMENR1_USART2SMEN STM32_RCC_APB1SMENR1_USART2SMEN_MSK +#define STM32_RCC_APB1SMENR1_USART3SMEN_POS 18U +#define STM32_RCC_APB1SMENR1_USART3SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_USART3SMEN_POS) +#define STM32_RCC_APB1SMENR1_USART3SMEN STM32_RCC_APB1SMENR1_USART3SMEN_MSK +#define STM32_RCC_APB1SMENR1_I2C1SMEN_POS 21U +#define STM32_RCC_APB1SMENR1_I2C1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_I2C1SMEN_POS) +#define STM32_RCC_APB1SMENR1_I2C1SMEN STM32_RCC_APB1SMENR1_I2C1SMEN_MSK +#define STM32_RCC_APB1SMENR1_I2C2SMEN_POS 22U +#define STM32_RCC_APB1SMENR1_I2C2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_I2C2SMEN_POS) +#define STM32_RCC_APB1SMENR1_I2C2SMEN STM32_RCC_APB1SMENR1_I2C2SMEN_MSK +#define STM32_RCC_APB1SMENR1_I2C3SMEN_POS 23U +#define STM32_RCC_APB1SMENR1_I2C3SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_I2C3SMEN_POS) +#define STM32_RCC_APB1SMENR1_I2C3SMEN STM32_RCC_APB1SMENR1_I2C3SMEN_MSK +#define STM32_RCC_APB1SMENR1_CRSSMEN_POS 24U +#define STM32_RCC_APB1SMENR1_CRSSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_CRSSMEN_POS) +#define STM32_RCC_APB1SMENR1_CRSSMEN STM32_RCC_APB1SMENR1_CRSSMEN_MSK +#define STM32_RCC_APB1SMENR1_CAN1SMEN_POS 25U +#define STM32_RCC_APB1SMENR1_CAN1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_CAN1SMEN_POS) +#define STM32_RCC_APB1SMENR1_CAN1SMEN STM32_RCC_APB1SMENR1_CAN1SMEN_MSK +#define STM32_RCC_APB1SMENR1_USBFSSMEN_POS 26U +#define STM32_RCC_APB1SMENR1_USBFSSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_USBFSSMEN_POS) +#define STM32_RCC_APB1SMENR1_USBFSSMEN STM32_RCC_APB1SMENR1_USBFSSMEN_MSK +#define STM32_RCC_APB1SMENR1_PWRSMEN_POS 28U +#define STM32_RCC_APB1SMENR1_PWRSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_PWRSMEN_POS) +#define STM32_RCC_APB1SMENR1_PWRSMEN STM32_RCC_APB1SMENR1_PWRSMEN_MSK +#define STM32_RCC_APB1SMENR1_DAC1SMEN_POS 29U +#define STM32_RCC_APB1SMENR1_DAC1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_DAC1SMEN_POS) +#define STM32_RCC_APB1SMENR1_DAC1SMEN STM32_RCC_APB1SMENR1_DAC1SMEN_MSK +#define STM32_RCC_APB1SMENR1_OPAMPSMEN_POS 30U +#define STM32_RCC_APB1SMENR1_OPAMPSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_OPAMPSMEN_POS) +#define STM32_RCC_APB1SMENR1_OPAMPSMEN STM32_RCC_APB1SMENR1_OPAMPSMEN_MSK +#define STM32_RCC_APB1SMENR1_LPTIM1SMEN_POS 31U +#define STM32_RCC_APB1SMENR1_LPTIM1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_LPTIM1SMEN_POS) +#define STM32_RCC_APB1SMENR1_LPTIM1SMEN STM32_RCC_APB1SMENR1_LPTIM1SMEN_MSK + +/************* BIT DEFINITION FOR STM32_RCC_APB1SMENR2 REGISTER *************/ +#define STM32_RCC_APB1SMENR2_LPUART1SMEN_POS 0U +#define STM32_RCC_APB1SMENR2_LPUART1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_LPUART1SMEN_POS) +#define STM32_RCC_APB1SMENR2_LPUART1SMEN STM32_RCC_APB1SMENR2_LPUART1SMEN_MSK +#define STM32_RCC_APB1SMENR2_SWPMI1SMEN_POS 2U +#define STM32_RCC_APB1SMENR2_SWPMI1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_SWPMI1SMEN_POS) +#define STM32_RCC_APB1SMENR2_SWPMI1SMEN STM32_RCC_APB1SMENR2_SWPMI1SMEN_MSK +#define STM32_RCC_APB1SMENR2_LPTIM2SMEN_POS 5U +#define STM32_RCC_APB1SMENR2_LPTIM2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_LPTIM2SMEN_POS) +#define STM32_RCC_APB1SMENR2_LPTIM2SMEN STM32_RCC_APB1SMENR2_LPTIM2SMEN_MSK + +/************ BIT DEFINITION FOR STM32_RCC_APB2SMENR REGISTER *************/ +#define STM32_RCC_APB2SMENR_SYSCFGSMEN_POS 0U +#define STM32_RCC_APB2SMENR_SYSCFGSMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_SYSCFGSMEN_POS) +#define STM32_RCC_APB2SMENR_SYSCFGSMEN STM32_RCC_APB2SMENR_SYSCFGSMEN_MSK +#define STM32_RCC_APB2SMENR_SDMMC1SMEN_POS 10U +#define STM32_RCC_APB2SMENR_SDMMC1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_SDMMC1SMEN_POS) +#define STM32_RCC_APB2SMENR_SDMMC1SMEN STM32_RCC_APB2SMENR_SDMMC1SMEN_MSK +#define STM32_RCC_APB2SMENR_TIM1SMEN_POS 11U +#define STM32_RCC_APB2SMENR_TIM1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_TIM1SMEN_POS) +#define STM32_RCC_APB2SMENR_TIM1SMEN STM32_RCC_APB2SMENR_TIM1SMEN_MSK +#define STM32_RCC_APB2SMENR_SPI1SMEN_POS 12U +#define STM32_RCC_APB2SMENR_SPI1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_SPI1SMEN_POS) +#define STM32_RCC_APB2SMENR_SPI1SMEN STM32_RCC_APB2SMENR_SPI1SMEN_MSK +#define STM32_RCC_APB2SMENR_USART1SMEN_POS 14U +#define STM32_RCC_APB2SMENR_USART1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_USART1SMEN_POS) +#define STM32_RCC_APB2SMENR_USART1SMEN STM32_RCC_APB2SMENR_USART1SMEN_MSK +#define STM32_RCC_APB2SMENR_TIM15SMEN_POS 16U +#define STM32_RCC_APB2SMENR_TIM15SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_TIM15SMEN_POS) +#define STM32_RCC_APB2SMENR_TIM15SMEN STM32_RCC_APB2SMENR_TIM15SMEN_MSK +#define STM32_RCC_APB2SMENR_TIM16SMEN_POS 17U +#define STM32_RCC_APB2SMENR_TIM16SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_TIM16SMEN_POS) +#define STM32_RCC_APB2SMENR_TIM16SMEN STM32_RCC_APB2SMENR_TIM16SMEN_MSK +#define STM32_RCC_APB2SMENR_SAI1SMEN_POS 21U +#define STM32_RCC_APB2SMENR_SAI1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_SAI1SMEN_POS) +#define STM32_RCC_APB2SMENR_SAI1SMEN STM32_RCC_APB2SMENR_SAI1SMEN_MSK + +/************* BIT DEFINITION FOR STM32_RCC_CCIPR REGISTER ******************/ +#define STM32_RCC_CCIPR_USART1SEL_POS 0U +#define STM32_RCC_CCIPR_USART1SEL_MSK (0x3UL << STM32_RCC_CCIPR_USART1SEL_POS) +#define STM32_RCC_CCIPR_USART1SEL STM32_RCC_CCIPR_USART1SEL_MSK +#define STM32_RCC_CCIPR_USART1SEL_0 (0x1UL << STM32_RCC_CCIPR_USART1SEL_POS) +#define STM32_RCC_CCIPR_USART1SEL_1 (0x2UL << STM32_RCC_CCIPR_USART1SEL_POS) + +#define STM32_RCC_CCIPR_USART2SEL_POS 2U +#define STM32_RCC_CCIPR_USART2SEL_MSK (0x3UL << STM32_RCC_CCIPR_USART2SEL_POS) +#define STM32_RCC_CCIPR_USART2SEL STM32_RCC_CCIPR_USART2SEL_MSK +#define STM32_RCC_CCIPR_USART2SEL_0 (0x1UL << STM32_RCC_CCIPR_USART2SEL_POS) +#define STM32_RCC_CCIPR_USART2SEL_1 (0x2UL << STM32_RCC_CCIPR_USART2SEL_POS) + +#define STM32_RCC_CCIPR_USART3SEL_POS 4U +#define STM32_RCC_CCIPR_USART3SEL_MSK (0x3UL << STM32_RCC_CCIPR_USART3SEL_POS) +#define STM32_RCC_CCIPR_USART3SEL STM32_RCC_CCIPR_USART3SEL_MSK +#define STM32_RCC_CCIPR_USART3SEL_0 (0x1UL << STM32_RCC_CCIPR_USART3SEL_POS) +#define STM32_RCC_CCIPR_USART3SEL_1 (0x2UL << STM32_RCC_CCIPR_USART3SEL_POS) + +#define STM32_RCC_CCIPR_LPUART1SEL_POS 10U +#define STM32_RCC_CCIPR_LPUART1SEL_MSK (0x3UL << STM32_RCC_CCIPR_LPUART1SEL_POS) +#define STM32_RCC_CCIPR_LPUART1SEL STM32_RCC_CCIPR_LPUART1SEL_MSK +#define STM32_RCC_CCIPR_LPUART1SEL_0 (0x1UL << STM32_RCC_CCIPR_LPUART1SEL_POS) +#define STM32_RCC_CCIPR_LPUART1SEL_1 (0x2UL << STM32_RCC_CCIPR_LPUART1SEL_POS) + +#define STM32_RCC_CCIPR_I2C1SEL_POS 12U +#define STM32_RCC_CCIPR_I2C1SEL_MSK (0x3UL << STM32_RCC_CCIPR_I2C1SEL_POS) +#define STM32_RCC_CCIPR_I2C1SEL STM32_RCC_CCIPR_I2C1SEL_MSK +#define STM32_RCC_CCIPR_I2C1SEL_0 (0x1UL << STM32_RCC_CCIPR_I2C1SEL_POS) +#define STM32_RCC_CCIPR_I2C1SEL_1 (0x2UL << STM32_RCC_CCIPR_I2C1SEL_POS) + +#define STM32_RCC_CCIPR_I2C2SEL_POS 14U +#define STM32_RCC_CCIPR_I2C2SEL_MSK (0x3UL << STM32_RCC_CCIPR_I2C2SEL_POS) +#define STM32_RCC_CCIPR_I2C2SEL STM32_RCC_CCIPR_I2C2SEL_MSK +#define STM32_RCC_CCIPR_I2C2SEL_0 (0x1UL << STM32_RCC_CCIPR_I2C2SEL_POS) +#define STM32_RCC_CCIPR_I2C2SEL_1 (0x2UL << STM32_RCC_CCIPR_I2C2SEL_POS) + +#define STM32_RCC_CCIPR_I2C3SEL_POS 16U +#define STM32_RCC_CCIPR_I2C3SEL_MSK (0x3UL << STM32_RCC_CCIPR_I2C3SEL_POS) +#define STM32_RCC_CCIPR_I2C3SEL STM32_RCC_CCIPR_I2C3SEL_MSK +#define STM32_RCC_CCIPR_I2C3SEL_0 (0x1UL << STM32_RCC_CCIPR_I2C3SEL_POS) +#define STM32_RCC_CCIPR_I2C3SEL_1 (0x2UL << STM32_RCC_CCIPR_I2C3SEL_POS) + +#define STM32_RCC_CCIPR_LPTIM1SEL_POS 18U +#define STM32_RCC_CCIPR_LPTIM1SEL_MSK (0x3UL << STM32_RCC_CCIPR_LPTIM1SEL_POS) +#define STM32_RCC_CCIPR_LPTIM1SEL STM32_RCC_CCIPR_LPTIM1SEL_MSK +#define STM32_RCC_CCIPR_LPTIM1SEL_0 (0x1UL << STM32_RCC_CCIPR_LPTIM1SEL_POS) +#define STM32_RCC_CCIPR_LPTIM1SEL_1 (0x2UL << STM32_RCC_CCIPR_LPTIM1SEL_POS) + +#define STM32_RCC_CCIPR_LPTIM2SEL_POS 20U +#define STM32_RCC_CCIPR_LPTIM2SEL_MSK (0x3UL << STM32_RCC_CCIPR_LPTIM2SEL_POS) +#define STM32_RCC_CCIPR_LPTIM2SEL STM32_RCC_CCIPR_LPTIM2SEL_MSK +#define STM32_RCC_CCIPR_LPTIM2SEL_0 (0x1UL << STM32_RCC_CCIPR_LPTIM2SEL_POS) +#define STM32_RCC_CCIPR_LPTIM2SEL_1 (0x2UL << STM32_RCC_CCIPR_LPTIM2SEL_POS) + +#define STM32_RCC_CCIPR_SAI1SEL_POS 22U +#define STM32_RCC_CCIPR_SAI1SEL_MSK (0x3UL << STM32_RCC_CCIPR_SAI1SEL_POS) +#define STM32_RCC_CCIPR_SAI1SEL STM32_RCC_CCIPR_SAI1SEL_MSK +#define STM32_RCC_CCIPR_SAI1SEL_0 (0x1UL << STM32_RCC_CCIPR_SAI1SEL_POS) +#define STM32_RCC_CCIPR_SAI1SEL_1 (0x2UL << STM32_RCC_CCIPR_SAI1SEL_POS) + +#define STM32_RCC_CCIPR_CLK48SEL_POS 26U +#define STM32_RCC_CCIPR_CLK48SEL_MSK (0x3UL << STM32_RCC_CCIPR_CLK48SEL_POS) +#define STM32_RCC_CCIPR_CLK48SEL STM32_RCC_CCIPR_CLK48SEL_MSK +#define STM32_RCC_CCIPR_CLK48SEL_0 (0x1UL << STM32_RCC_CCIPR_CLK48SEL_POS) +#define STM32_RCC_CCIPR_CLK48SEL_1 (0x2UL << STM32_RCC_CCIPR_CLK48SEL_POS) + +#define STM32_RCC_CCIPR_ADCSEL_POS 28U +#define STM32_RCC_CCIPR_ADCSEL_MSK (0x3UL << STM32_RCC_CCIPR_ADCSEL_POS) +#define STM32_RCC_CCIPR_ADCSEL STM32_RCC_CCIPR_ADCSEL_MSK +#define STM32_RCC_CCIPR_ADCSEL_0 (0x1UL << STM32_RCC_CCIPR_ADCSEL_POS) +#define STM32_RCC_CCIPR_ADCSEL_1 (0x2UL << STM32_RCC_CCIPR_ADCSEL_POS) + +#define STM32_RCC_CCIPR_SWPMI1SEL_POS 30U +#define STM32_RCC_CCIPR_SWPMI1SEL_MSK (0x1UL << STM32_RCC_CCIPR_SWPMI1SEL_POS) +#define STM32_RCC_CCIPR_SWPMI1SEL STM32_RCC_CCIPR_SWPMI1SEL_MSK + +/************** Bit definition for STM32_RCC_CCIPR2 register ****************/ +#define STM32_RCC_CCIPR2_I2C4SEL_POS 0U +#define STM32_RCC_CCIPR2_I2C4SEL_MSK (0x3UL << STM32_RCC_CCIPR2_I2C4SEL_POS) +#define STM32_RCC_CCIPR2_I2C4SEL STM32_RCC_CCIPR2_I2C4SEL_MSK +#define STM32_RCC_CCIPR2_I2C4SEL_0 (0x1UL << STM32_RCC_CCIPR2_I2C4SEL_POS) +#define STM32_RCC_CCIPR2_I2C4SEL_1 (0x2UL << STM32_RCC_CCIPR2_I2C4SEL_POS) + +/************** BIT DEFINITION FOR STM32_RCC_BDCR REGISTER ******************/ +#define STM32_RCC_BDCR_LSEBYP_POS 2U +#define STM32_RCC_BDCR_LSEBYP_MSK (0x1UL << STM32_RCC_BDCR_LSEBYP_POS) +#define STM32_RCC_BDCR_LSEBYP STM32_RCC_BDCR_LSEBYP_MSK + +#define STM32_RCC_BDCR_LSEDRV_POS 3U +#define STM32_RCC_BDCR_LSEDRV_MSK (0x3UL << STM32_RCC_BDCR_LSEDRV_POS) +#define STM32_RCC_BDCR_LSEDRV STM32_RCC_BDCR_LSEDRV_MSK +#define STM32_RCC_BDCR_LSEDRV_0 (0x1UL << STM32_RCC_BDCR_LSEDRV_POS) +#define STM32_RCC_BDCR_LSEDRV_1 (0x2UL << STM32_RCC_BDCR_LSEDRV_POS) + +#define STM32_RCC_BDCR_LSECSSON_POS 5U +#define STM32_RCC_BDCR_LSECSSON_MSK (0x1UL << STM32_RCC_BDCR_LSECSSON_POS) +#define STM32_RCC_BDCR_LSECSSON STM32_RCC_BDCR_LSECSSON_MSK +#define STM32_RCC_BDCR_LSECSSD_POS 6U +#define STM32_RCC_BDCR_LSECSSD_MSK (0x1UL << STM32_RCC_BDCR_LSECSSD_POS) +#define STM32_RCC_BDCR_LSECSSD STM32_RCC_BDCR_LSECSSD_MSK + +#define STM32_RCC_BDCR_RTCSEL_POS 8U +#define STM32_RCC_BDCR_RTCSEL_MSK (0x3UL << STM32_RCC_BDCR_RTCSEL_POS) +#define STM32_RCC_BDCR_RTCSEL STM32_RCC_BDCR_RTCSEL_MSK +#define STM32_RCC_BDCR_RTCSEL_0 (0x1UL << STM32_RCC_BDCR_RTCSEL_POS) +#define STM32_RCC_BDCR_RTCSEL_1 (0x2UL << STM32_RCC_BDCR_RTCSEL_POS) + +#define STM32_RCC_BDCR_LSCOEN_POS 24U +#define STM32_RCC_BDCR_LSCOEN_MSK (0x1UL << STM32_RCC_BDCR_LSCOEN_POS) +#define STM32_RCC_BDCR_LSCOEN STM32_RCC_BDCR_LSCOEN_MSK +#define STM32_RCC_BDCR_LSCOSEL_POS 25U +#define STM32_RCC_BDCR_LSCOSEL_MSK (0x1UL << STM32_RCC_BDCR_LSCOSEL_POS) +#define STM32_RCC_BDCR_LSCOSEL STM32_RCC_BDCR_LSCOSEL_MSK + +/************** BIT DEFINITION FOR STM32_RCC_CSR REGISTER *******************/ +#define STM32_RCC_CSR_LSION_POS 0U +#define STM32_RCC_CSR_LSION_MSK (0x1UL << STM32_RCC_CSR_LSION_POS) +#define STM32_RCC_CSR_LSION STM32_RCC_CSR_LSION_MSK +#define STM32_RCC_CSR_LSIRDY_POS 1U +#define STM32_RCC_CSR_LSIRDY_MSK (0x1UL << STM32_RCC_CSR_LSIRDY_POS) +#define STM32_RCC_CSR_LSIRDY STM32_RCC_CSR_LSIRDY_MSK + +#define STM32_RCC_CSR_MSISRANGE_POS 8U +#define STM32_RCC_CSR_MSISRANGE_MSK (0xFUL << STM32_RCC_CSR_MSISRANGE_POS) +#define STM32_RCC_CSR_MSISRANGE STM32_RCC_CSR_MSISRANGE_MSK +#define STM32_RCC_CSR_MSISRANGE_1 (0x4UL << STM32_RCC_CSR_MSISRANGE_POS) +#define STM32_RCC_CSR_MSISRANGE_2 (0x5UL << STM32_RCC_CSR_MSISRANGE_POS) +#define STM32_RCC_CSR_MSISRANGE_4 (0x6UL << STM32_RCC_CSR_MSISRANGE_POS) +#define STM32_RCC_CSR_MSISRANGE_8 (0x7UL << STM32_RCC_CSR_MSISRANGE_POS) + +#define STM32_RCC_CSR_RMVF_POS 23U +#define STM32_RCC_CSR_RMVF_MSK (0x1UL << STM32_RCC_CSR_RMVF_POS) +#define STM32_RCC_CSR_RMVF STM32_RCC_CSR_RMVF_MSK +#define STM32_RCC_CSR_FWRSTF_POS 24U +#define STM32_RCC_CSR_FWRSTF_MSK (0x1UL << STM32_RCC_CSR_FWRSTF_POS) +#define STM32_RCC_CSR_FWRSTF STM32_RCC_CSR_FWRSTF_MSK +#define STM32_RCC_CSR_OBLRSTF_POS 25U +#define STM32_RCC_CSR_OBLRSTF_MSK (0x1UL << STM32_RCC_CSR_OBLRSTF_POS) +#define STM32_RCC_CSR_OBLRSTF STM32_RCC_CSR_OBLRSTF_MSK +#define STM32_RCC_CSR_PINRSTF_POS 26U +#define STM32_RCC_CSR_PINRSTF_MSK (0x1UL << STM32_RCC_CSR_PINRSTF_POS) +#define STM32_RCC_CSR_PINRSTF STM32_RCC_CSR_PINRSTF_MSK +#define STM32_RCC_CSR_BORRSTF_POS 27U +#define STM32_RCC_CSR_BORRSTF_MSK (0x1UL << STM32_RCC_CSR_BORRSTF_POS) +#define STM32_RCC_CSR_BORRSTF STM32_RCC_CSR_BORRSTF_MSK +#define STM32_RCC_CSR_SFTRSTF_POS 28U +#define STM32_RCC_CSR_SFTRSTF_MSK (0x1UL << STM32_RCC_CSR_SFTRSTF_POS) +#define STM32_RCC_CSR_SFTRSTF STM32_RCC_CSR_SFTRSTF_MSK +#define STM32_RCC_CSR_IWDGRSTF_POS 29U +#define STM32_RCC_CSR_IWDGRSTF_MSK (0x1UL << STM32_RCC_CSR_IWDGRSTF_POS) +#define STM32_RCC_CSR_IWDGRSTF STM32_RCC_CSR_IWDGRSTF_MSK +#define STM32_RCC_CSR_WWDGRSTF_POS 30U +#define STM32_RCC_CSR_WWDGRSTF_MSK (0x1UL << STM32_RCC_CSR_WWDGRSTF_POS) +#define STM32_RCC_CSR_WWDGRSTF STM32_RCC_CSR_WWDGRSTF_MSK +#define STM32_RCC_CSR_LPWRRSTF_POS 31U +#define STM32_RCC_CSR_LPWRRSTF_MSK (0x1UL << STM32_RCC_CSR_LPWRRSTF_POS) +#define STM32_RCC_CSR_LPWRRSTF STM32_RCC_CSR_LPWRRSTF_MSK + +/************** Bit definition for STM32_RCC_CRRCR register *****************/ +#define STM32_RCC_CRRCR_HSI48ON_POS 0U +#define STM32_RCC_CRRCR_HSI48ON_MSK (0x1UL << STM32_RCC_CRRCR_HSI48ON_POS) +#define STM32_RCC_CRRCR_HSI48ON STM32_RCC_CRRCR_HSI48ON_MSK +#define STM32_RCC_CRRCR_HSI48RDY_POS 1U +#define STM32_RCC_CRRCR_HSI48RDY_MSK (0x1UL << STM32_RCC_CRRCR_HSI48RDY_POS) +#define STM32_RCC_CRRCR_HSI48RDY STM32_RCC_CRRCR_HSI48RDY_MSK + +/*!< HSI48CAL configuration */ +#define STM32_RCC_CRRCR_HSI48CAL_POS 7U +#define STM32_RCC_CRRCR_HSI48CAL_MSK (0x1FFUL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL STM32_RCC_CRRCR_HSI48CAL_MSK +#define STM32_RCC_CRRCR_HSI48CAL_0 (0x001UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_1 (0x002UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_2 (0x004UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_3 (0x008UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_4 (0x010UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_5 (0x020UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_6 (0x040UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_7 (0x080UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_8 (0x100UL << STM32_RCC_CRRCR_HSI48CAL_POS) + +#define STM32_SYSCFG_CFGR1 REG32(STM32_SYSCFG_BASE + 0x04) +#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n)) +#define STM32_SYSCFG_I2CFMP(n) BIT(n + 21) + +/* Peripheral bits for STM32_RCC_APB/AHB and DBGMCU regs */ +#define STM32_RCC_PB1_PWREN BIT(28) + +#define STM32_RCC_PB2_SYSCFGEN BIT(0) +#define STM32_RCC_PB2_USART1 BIT(14) + +#define STM32_RCC_HB1_DMA1 BIT(0) +#define STM32_RCC_HB1_DMA2 BIT(1) + +#define STM32_RCC_HB2_GPIOA BIT(0) +#define STM32_RCC_HB2_GPIOB BIT(1) +#define STM32_RCC_HB2_GPIOC BIT(2) +#define STM32_RCC_HB2_GPIOD BIT(3) +#define STM32_RCC_HB2_GPIOE BIT(4) +#define STM32_RCC_HB2_GPIOH BIT(7) +#define STM32_RCC_HB2_ADC1 BIT(13) /* Reset causes definitions */ /* Reset causes in RCC CSR register */ #define STM32_RCC_RESET_CAUSE STM32_RCC_CSR -#define RESET_CAUSE_WDG 0x60000000 -#define RESET_CAUSE_SFT 0x10000000 -#define RESET_CAUSE_POR 0x08000000 -#define RESET_CAUSE_PIN 0x04000000 -#define RESET_CAUSE_OTHER 0xfe000000 -#define RESET_CAUSE_RMVF 0x01000000 +#define RESET_CAUSE_WDG 0x60000000 +#define RESET_CAUSE_SFT 0x10000000 +#define RESET_CAUSE_POR 0x08000000 +#define RESET_CAUSE_PIN 0x04000000 +#define RESET_CAUSE_OTHER 0xff000000 +#define RESET_CAUSE_RMVF BIT(23) /* Power cause in PWR CSR register */ #define STM32_PWR_RESET_CAUSE STM32_PWR_CSR -#define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CR -#define RESET_CAUSE_SBF 0x00000002 -#define RESET_CAUSE_SBF_CLR 0x00000004 +#define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_SCR +#define RESET_CAUSE_SBF BIT(8) +#define RESET_CAUSE_SBF_CLR BIT(8) /* --- Watchdogs --- */ /* --- Real-Time Clock --- */ -#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) -#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) -#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) -#define STM32_RTC_CR_BYPSHAD BIT(5) -#define STM32_RTC_CR_ALRAE BIT(8) -#define STM32_RTC_CR_ALRAIE BIT(12) -#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) -#define STM32_RTC_ISR_ALRAWF BIT(0) -#define STM32_RTC_ISR_RSF BIT(5) -#define STM32_RTC_ISR_INITF BIT(6) -#define STM32_RTC_ISR_INIT BIT(7) -#define STM32_RTC_ISR_ALRAF BIT(8) -#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) -#define STM32_RTC_PRER_A_MASK (0x7f << 16) -#define STM32_RTC_PRER_S_MASK (0x7fff << 0) -#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) -#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) -#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) -#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) -#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) -#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) -#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) -#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) -#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) -#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) -#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) - -#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) -#define STM32_BKP_BYTES 128 +#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) +#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) +#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) +#define STM32_RTC_CR_BYPSHAD BIT(5) +#define STM32_RTC_CR_ALRAE BIT(8) +#define STM32_RTC_CR_WUTE BIT(10) +#define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_CR_WUTIE BIT(14) +#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) +#define STM32_RTC_ISR_ALRAWF BIT(0) +#define STM32_RTC_ISR_WUTWF BIT(2) +#define STM32_RTC_ISR_INITS BIT(4) +#define STM32_RTC_ISR_RSF BIT(5) +#define STM32_RTC_ISR_INITF BIT(6) +#define STM32_RTC_ISR_INIT BIT(7) +#define STM32_RTC_ISR_ALRAF BIT(8) +#define STM32_RTC_ISR_WUTF BIT(9) +#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) +#define STM32_RTC_PRER_A_MASK (0x7f << 16) +#define STM32_RTC_PRER_S_MASK (0x7fff << 0) +#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) +#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) +#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) +#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) +#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) +#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) +#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) +#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) +#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) +#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) +#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n)) + +#define STM32_RTC_CLEAR_FLAG(x) \ + (STM32_RTC_ISR = (~((x) | STM32_RTC_ISR_INIT) | \ + (STM32_RTC_ISR & STM32_RTC_ISR_INIT))) + +#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n) +#define STM32_BKP_BYTES 128 + +#define RTC_TR_PM_POS 22U +#define RTC_TR_PM_MSK (0x1UL << RTC_TR_PM_POS) +#define RTC_TR_PM RTC_TR_PM_MSK +#define RTC_TR_HT_POS 20U +#define RTC_TR_HT_MSK (0x3UL << RTC_TR_HT_POS) +#define RTC_TR_HT RTC_TR_HT_MSK +#define RTC_TR_HU_POS 16U +#define RTC_TR_HU_MSK (0xFUL << RTC_TR_HU_POS) +#define RTC_TR_HU RTC_TR_HU_MSK +#define RTC_TR_MNT_POS 12U +#define RTC_TR_MNT_MSK (0x7UL << RTC_TR_MNT_POS) +#define RTC_TR_MNT RTC_TR_MNT_MSK +#define RTC_TR_MNU_POS 8U +#define RTC_TR_MNU_MSK (0xFUL << RTC_TR_MNU_POS) +#define RTC_TR_MNU RTC_TR_MNU_MSK +#define RTC_TR_ST_POS 4U +#define RTC_TR_ST_MSK (0x7UL << RTC_TR_ST_POS) +#define RTC_TR_ST RTC_TR_ST_MSK +#define RTC_TR_SU_POS 0U +#define RTC_TR_SU_MSK (0xFUL << RTC_TR_SU_POS) +#define RTC_TR_SU RTC_TR_SU_MSK /* --- SPI --- */ @@ -555,15 +1814,15 @@ struct stm32_spi_regs { uint16_t _pad0; uint16_t cr2; uint16_t _pad1; - unsigned sr; + unsigned int sr; uint8_t dr; uint8_t _pad2; uint16_t _pad3; - unsigned crcpr; - unsigned rxcrcr; - unsigned txcrcr; - unsigned i2scfgr; /* STM32L only */ - unsigned i2spr; /* STM32L only */ + unsigned int crcpr; + unsigned int rxcrcr; + unsigned int txcrcr; + unsigned int i2scfgr; /* STM32L only */ + unsigned int i2spr; /* STM32L only */ }; /* Must be volatile, or compiler optimizes out repeated accesses */ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; @@ -573,92 +1832,152 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_SPI3_REGS ((stm32_spi_regs_t *)STM32_SPI3_BASE) #define STM32_SPI4_REGS ((stm32_spi_regs_t *)STM32_SPI4_BASE) -#define STM32_SPI_CR1_BIDIMODE BIT(15) -#define STM32_SPI_CR1_BIDIOE BIT(14) -#define STM32_SPI_CR1_CRCEN BIT(13) -#define STM32_SPI_CR1_SSM BIT(9) -#define STM32_SPI_CR1_SSI BIT(8) -#define STM32_SPI_CR1_LSBFIRST BIT(7) -#define STM32_SPI_CR1_SPE BIT(6) -#define STM32_SPI_CR1_BR_DIV64R (5 << 3) -#define STM32_SPI_CR1_BR_DIV4R BIT(3) -#define STM32_SPI_CR1_MSTR BIT(2) -#define STM32_SPI_CR1_CPOL BIT(1) -#define STM32_SPI_CR1_CPHA BIT(0) -#define STM32_SPI_CR2_FRXTH BIT(12) -#define STM32_SPI_CR2_DATASIZE(n) (((n) - 1) << 8) -#define STM32_SPI_CR2_TXEIE BIT(7) -#define STM32_SPI_CR2_RXNEIE BIT(6) -#define STM32_SPI_CR2_NSSP BIT(3) -#define STM32_SPI_CR2_SSOE BIT(2) -#define STM32_SPI_CR2_TXDMAEN BIT(1) -#define STM32_SPI_CR2_RXDMAEN BIT(0) - -#define STM32_SPI_SR_RXNE BIT(0) -#define STM32_SPI_SR_TXE BIT(1) -#define STM32_SPI_SR_CRCERR BIT(4) -#define STM32_SPI_SR_BSY BIT(7) -#define STM32_SPI_SR_FRLVL (3 << 9) -#define STM32_SPI_SR_FTLVL (3 << 11) +#define STM32_SPI_CR1_BIDIMODE BIT(15) +#define STM32_SPI_CR1_BIDIOE BIT(14) +#define STM32_SPI_CR1_CRCEN BIT(13) +#define STM32_SPI_CR1_SSM BIT(9) +#define STM32_SPI_CR1_SSI BIT(8) +#define STM32_SPI_CR1_LSBFIRST BIT(7) +#define STM32_SPI_CR1_SPE BIT(6) +#define STM32_SPI_CR1_BR_DIV64R (5 << 3) +#define STM32_SPI_CR1_BR_DIV4R BIT(3) +#define STM32_SPI_CR1_MSTR BIT(2) +#define STM32_SPI_CR1_CPOL BIT(1) +#define STM32_SPI_CR1_CPHA BIT(0) +#define STM32_SPI_CR2_FRXTH BIT(12) +#define STM32_SPI_CR2_DATASIZE(n) (((n)-1) << 8) +#define STM32_SPI_CR2_TXEIE BIT(7) +#define STM32_SPI_CR2_RXNEIE BIT(6) +#define STM32_SPI_CR2_NSSP BIT(3) +#define STM32_SPI_CR2_SSOE BIT(2) +#define STM32_SPI_CR2_TXDMAEN BIT(1) +#define STM32_SPI_CR2_RXDMAEN BIT(0) + +#define STM32_SPI_SR_RXNE BIT(0) +#define STM32_SPI_SR_TXE BIT(1) +#define STM32_SPI_SR_CRCERR BIT(4) +#define STM32_SPI_SR_BSY BIT(7) +#define STM32_SPI_SR_FRLVL (3 << 9) +#define STM32_SPI_SR_FTLVL (3 << 11) /* --- Debug --- */ -#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) -#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) +#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) +#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) /* --- Flash --- */ -#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) +#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) #define STM32_FLASH_ACR_LATENCY_SHIFT (0) -#define STM32_FLASH_ACR_LATENCY_MASK (7 << STM32_FLASH_ACR_LATENCY_SHIFT) -#define STM32_FLASH_ACR_PRFTEN BIT(8) -#define STM32_FLASH_ACR_ICEN BIT(9) -#define STM32_FLASH_ACR_DCEN BIT(10) -#define STM32_FLASH_ACR_ICRST BIT(11) -#define STM32_FLASH_ACR_DCRST BIT(12) -#define STM32_FLASH_PDKEYR REG32(STM32_FLASH_REGS_BASE + 0x04) -#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x08) -#define FLASH_KEYR_KEY1 0x45670123 -#define FLASH_KEYR_KEY2 0xCDEF89AB -#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x0c) -#define FLASH_OPTKEYR_KEY1 0x08192A3B -#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F -#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x10) -#define FLASH_SR_BUSY BIT(16) -#define FLASH_SR_ERR_MASK (0xc3fa) -#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x14) -#define FLASH_CR_PG BIT(0) -#define FLASH_CR_PER BIT(1) -#define FLASH_CR_STRT BIT(16) -#define FLASH_CR_OPTSTRT BIT(17) -#define FLASH_CR_OBL_LAUNCH BIT(27) -#define FLASH_CR_OPTLOCK BIT(30) -#define FLASH_CR_LOCK BIT(31) -#define FLASH_CR_PNB(sec) (((sec) & 0xff) << 3) -#define FLASH_CR_PNB_MASK FLASH_CR_PNB(0xff) -#define STM32_FLASH_ECCR REG32(STM32_FLASH_REGS_BASE + 0x18) -#define STM32_FLASH_OPTR REG32(STM32_FLASH_REGS_BASE + 0x20) -#define STM32_FLASH_PCROP1SR REG32(STM32_FLASH_REGS_BASE + 0x24) -#define STM32_FLASH_PCROP1ER REG32(STM32_FLASH_REGS_BASE + 0x28) -#define STM32_FLASH_WRP1AR REG32(STM32_FLASH_REGS_BASE + 0x2C) -#define STM32_FLASH_WRP1BR REG32(STM32_FLASH_REGS_BASE + 0x30) +#define STM32_FLASH_ACR_LATENCY_MASK (7 << STM32_FLASH_ACR_LATENCY_SHIFT) +#define STM32_FLASH_ACR_PRFTEN BIT(8) +#define STM32_FLASH_ACR_ICEN BIT(9) +#define STM32_FLASH_ACR_DCEN BIT(10) +#define STM32_FLASH_ACR_ICRST BIT(11) +#define STM32_FLASH_ACR_DCRST BIT(12) +#define STM32_FLASH_PDKEYR REG32(STM32_FLASH_REGS_BASE + 0x04) +#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x08) +#define FLASH_KEYR_KEY1 0x45670123 +#define FLASH_KEYR_KEY2 0xCDEF89AB +#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x0c) +#define FLASH_OPTKEYR_KEY1 0x08192A3B +#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F +#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x10) +#define FLASH_SR_BUSY BIT(16) +#define FLASH_SR_ERR_MASK (0xc3fa) +#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x14) +#define FLASH_CR_PG BIT(0) +#define FLASH_CR_PER BIT(1) +#define FLASH_CR_STRT BIT(16) +#define FLASH_CR_OPTSTRT BIT(17) +#define FLASH_CR_OBL_LAUNCH BIT(27) +#define FLASH_CR_OPTLOCK BIT(30) +#define FLASH_CR_LOCK BIT(31) +#define FLASH_CR_PNB(sec) (((sec)&0xff) << 3) +#define FLASH_CR_PNB_MASK FLASH_CR_PNB(0xff) +#define STM32_FLASH_ECCR REG32(STM32_FLASH_REGS_BASE + 0x18) +#define STM32_FLASH_OPTR REG32(STM32_FLASH_REGS_BASE + 0x20) +#define STM32_FLASH_PCROP1SR REG32(STM32_FLASH_REGS_BASE + 0x24) +#define STM32_FLASH_PCROP1ER REG32(STM32_FLASH_REGS_BASE + 0x28) +#define STM32_FLASH_WRP1AR REG32(STM32_FLASH_REGS_BASE + 0x2C) +#define STM32_FLASH_WRP1BR REG32(STM32_FLASH_REGS_BASE + 0x30) /* Minimum number of bytes that can be written to flash */ -#define STM32_FLASH_MIN_WRITE_SIZE CONFIG_FLASH_WRITE_SIZE +#define STM32_FLASH_MIN_WRITE_SIZE CONFIG_FLASH_WRITE_SIZE -#define STM32_OPTB_USER_RDP REG32(STM32_OPTB_BASE + 0x00) -#define STM32_OPTB_WRP1AR REG32(STM32_OPTB_BASE + 0x18) -#define STM32_OPTB_WRP1BR REG32(STM32_OPTB_BASE + 0x20) +#define STM32_OPTB_USER_RDP REG32(STM32_OPTB_BASE + 0x00) +#define STM32_OPTB_WRP1AR REG32(STM32_OPTB_BASE + 0x18) +#define STM32_OPTB_WRP1BR REG32(STM32_OPTB_BASE + 0x20) /* --- External Interrupts --- */ -#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) -#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) -#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) -#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) -#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) -#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) +#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00) +#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04) +#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x08) +#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x0c) +#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) +#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) +#define EXTI_RTC_ALR_EVENT BIT(18) /* --- ADC --- */ - -/* --- Comparators --- */ - +#define STM32_ADC1_ISR REG32(STM32_ADC1_BASE + 0x00) +#define STM32_ADC1_ISR_ADRDY BIT(0) +#define STM32_ADC1_IER REG32(STM32_ADC1_BASE + 0x04) +#define STM32_ADC1_IER_AWDIE BIT(7) +#define STM32_ADC1_IER_OVRIE BIT(4) +#define STM32_ADC1_IER_EOSEQIE BIT(3) +#define STM32_ADC1_IER_EOCIE BIT(2) +#define STM32_ADC1_IER_EOSMPIE BIT(1) +#define STM32_ADC1_IER_ADRDYIE BIT(0) + +#define STM32_ADC1_CR REG32(STM32_ADC1_BASE + 0x08) +#define STM32_ADC1_CR_ADEN BIT(0) +#define STM32_ADC1_CR_ADDIS BIT(1) +#define STM32_ADC1_CR_ADSTP BIT(4) +#define STM32_ADC1_CR_ADVREGEN BIT(28) +#define STM32_ADC1_CR_DEEPPWD BIT(29) +#define STM32_ADC1_CR_ADCAL BIT(31) +#define STM32_ADC1_CFGR REG32(STM32_ADC1_BASE + 0x0C) +/* Analog watchdog channel selection */ +#define STM32_ADC1_CFGR_AWDCH_MASK (0x1f << 26) +#define STM32_ADC1_CFGR_AWDEN BIT(23) +#define STM32_ADC1_CFGR_AWDSGL BIT(22) +#define STM32_ADC1_CFGR_AUTDLY BIT(14) +/* Selects single vs continuous */ +#define STM32_ADC1_CFGR_CONT BIT(13) +/* Selects ADC_DR overwrite vs preserve */ +#define STM32_ADC1_CFGR_OVRMOD BIT(12) +/* External trigger polarity selection */ +#define STM32_ADC1_CFGR_EXTEN_DIS (0 << 10) +#define STM32_ADC1_CFGR_EXTEN_RISE (1 << 10) +#define STM32_ADC1_CFGR_EXTEN_FALL (2 << 10) +#define STM32_ADC1_CFGR_EXTEN_BOTH (3 << 10) +#define STM32_ADC1_CFGR_EXTEN_MASK (3 << 10) +#define STM32_ADC1_CFGR_ALIGN BIT(5) +/* External trigger selection */ +#define STM32_ADC1_CFGR_TRG0 (0 << 6) +#define STM32_ADC1_CFGR_TRG1 (1 << 6) +#define STM32_ADC1_CFGR_TRG2 (2 << 6) +#define STM32_ADC1_CFGR_TRG3 (3 << 6) +#define STM32_ADC1_CFGR_TRG4 (4 << 6) +#define STM32_ADC1_CFGR_TRG5 (5 << 6) +#define STM32_ADC1_CFGR_TRG6 (6 << 6) +#define STM32_ADC1_CFGR_TRG7 (7 << 6) +#define STM32_ADC1_CFGR_TRG_MASK (7 << 6) +/* Selects circular vs one-shot */ +#define STM32_ADC1_CFGR_DMACFG BIT(1) +#define STM32_ADC1_CFGR_DMAEN BIT(0) +#define STM32_ADC1_CFGR2 REG32(STM32_ADC1_BASE + 0x10) +/* Sampling time selection - 1.5 ADC cycles min, 239.5 cycles max */ +#define STM32_ADC1_SMPR1 REG32(STM32_ADC1_BASE + 0x14) +#define STM32_ADC1_SMPR2 REG32(STM32_ADC1_BASE + 0x18) +/* Macro to convert enum stm32_adc_smpr to SMP bits of the ADC_SMPR register */ +#define STM32_ADC1_SMPR_SMP(s) ((s)-1) +#define STM32_ADC1_TR REG32(STM32_ADC1_BASE + 0x20) +#define STM32_ADC1_CHSELR REG32(STM32_ADC1_BASE + 0x28) +#define STM32_ADC1_DR REG32(STM32_ADC1_BASE + 0x40) +#define STM32_ADC1_JSQR REG32(STM32_ADC1_BASE + 0x4C) +#define STM32_ADC1_JDR1 REG32(STM32_ADC1_BASE + 0x80) +#define STM32_ADC1_JDR2 REG32(STM32_ADC1_BASE + 0x84) +#define STM32_ADC1_JDR3 REG32(STM32_ADC1_BASE + 0x88) +#define STM32_ADC1_JDR4 REG32(STM32_ADC1_BASE + 0x8C) +#define STM32_ADC1_CCR REG32(STM32_ADC1_BASE + 0x308) /* --- DMA --- */ @@ -692,39 +2011,29 @@ enum dma_channel { STM32_DMAC_CH12 = 11, STM32_DMAC_CH13 = 12, STM32_DMAC_CH14 = 13, + STM32_DMAC_CH15 = 14, /* Channel functions */ - STM32_DMAC_ADC = STM32_DMAC_CH1, STM32_DMAC_SPI1_RX = STM32_DMAC_CH2, STM32_DMAC_SPI1_TX = STM32_DMAC_CH3, - STM32_DMAC_DAC_CH1 = STM32_DMAC_CH2, - STM32_DMAC_DAC_CH2 = STM32_DMAC_CH3, - STM32_DMAC_I2C2_TX = STM32_DMAC_CH4, - STM32_DMAC_I2C2_RX = STM32_DMAC_CH5, - STM32_DMAC_USART1_TX = STM32_DMAC_CH4, - STM32_DMAC_USART1_RX = STM32_DMAC_CH5, - STM32_DMAC_USART2_RX = STM32_DMAC_CH6, - STM32_DMAC_USART2_TX = STM32_DMAC_CH7, - STM32_DMAC_I2C1_TX = STM32_DMAC_CH6, - STM32_DMAC_I2C1_RX = STM32_DMAC_CH7, - STM32_DMAC_PMSE_ROW = STM32_DMAC_CH6, - STM32_DMAC_PMSE_COL = STM32_DMAC_CH7, + STM32_DMAC_USART1_TX = STM32_DMAC_CH14, + STM32_DMAC_USART1_RX = STM32_DMAC_CH15, STM32_DMAC_SPI2_RX = STM32_DMAC_CH4, STM32_DMAC_SPI2_TX = STM32_DMAC_CH5, STM32_DMAC_SPI3_RX = STM32_DMAC_CH9, STM32_DMAC_SPI3_TX = STM32_DMAC_CH10, - STM32_DMAC_COUNT = 14, + STM32_DMAC_COUNT = 15, }; #define STM32_DMAC_PER_CTLR 8 /* Registers for a single channel of the DMA controller */ struct stm32_dma_chan { - uint32_t ccr; /* Control */ - uint32_t cndtr; /* Number of data to transfer */ - uint32_t cpar; /* Peripheral address */ - uint32_t cmar; /* Memory address */ - uint32_t reserved; + uint32_t ccr; /* Control */ + uint32_t cndtr; /* Number of data to transfer */ + uint32_t cpar; /* Peripheral address */ + uint32_t cmar; /* Memory address */ + uint32_t reserved; }; /* Always use stm32_dma_chan_t so volatile keyword is included! */ @@ -735,8 +2044,8 @@ typedef stm32_dma_chan_t dma_chan_t; /* Registers for the DMA controller */ struct stm32_dma_regs { - uint32_t isr; - uint32_t ifcr; + uint32_t isr; + uint32_t ifcr; stm32_dma_chan_t chan[STM32_DMAC_COUNT]; }; @@ -745,209 +2054,67 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_DMA1_REGS ((stm32_dma_regs_t *)STM32_DMA1_BASE) - -#define STM32_DMA_CCR_CHANNEL(channel) (0) +#define STM32_DMA_CCR_CHANNEL(channel) (0) #define STM32_DMA2_REGS ((stm32_dma_regs_t *)STM32_DMA2_BASE) #define STM32_DMA_REGS(channel) \ ((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_REGS : STM32_DMA2_REGS) -#define STM32_DMA_CSELR(channel) \ - REG32(((channel) < STM32_DMAC_PER_CTLR ? \ - STM32_DMA1_BASE : STM32_DMA2_BASE) + 0xA8) +#define STM32_DMA_CSELR(channel) \ + REG32(((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_BASE : \ + STM32_DMA2_BASE) + \ + 0xA8) /* Bits for DMA controller regs (isr and ifcr) */ -#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) +#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) #define STM32_DMA_ISR_MASK(channel, mask) \ ((mask) << STM32_DMA_CH_OFFSET(channel)) -#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) -#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) -#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) -#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) -#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) - -#define STM32_DMA_GIF BIT(0) -#define STM32_DMA_TCIF BIT(1) -#define STM32_DMA_HTIF BIT(2) -#define STM32_DMA_TEIF BIT(3) -#define STM32_DMA_ALL 0xf - -#define STM32_DMA_GET_ISR(channel) \ - ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_ISR(channel, val) \ - (STM32_DMA_REGS(channel)->isr = \ - ((STM32_DMA_REGS(channel)->isr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) -#define STM32_DMA_GET_IFCR(channel) \ - ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) \ - & STM32_DMA_ALL) -#define STM32_DMA_SET_IFCR(channel, val) \ - (STM32_DMA_REGS(channel)->ifcr = \ - ((STM32_DMA_REGS(channel)->ifcr & \ - ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ - (((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) - +#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) +#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) +#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) +#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) +#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) + +#define STM32_DMA_GIF BIT(0) +#define STM32_DMA_TCIF BIT(1) +#define STM32_DMA_HTIF BIT(2) +#define STM32_DMA_TEIF BIT(3) +#define STM32_DMA_ALL 0xf + +#define STM32_DMA_GET_ISR(channel) \ + ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_ISR(channel, val) \ + (STM32_DMA_REGS(channel)->isr = \ + ((STM32_DMA_REGS(channel)->isr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) +#define STM32_DMA_GET_IFCR(channel) \ + ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_IFCR(channel, val) \ + (STM32_DMA_REGS(channel)->ifcr = \ + ((STM32_DMA_REGS(channel)->ifcr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) /* Bits for DMA channel regs */ -#define STM32_DMA_CCR_EN BIT(0) -#define STM32_DMA_CCR_TCIE BIT(1) -#define STM32_DMA_CCR_HTIE BIT(2) -#define STM32_DMA_CCR_TEIE BIT(3) -#define STM32_DMA_CCR_DIR BIT(4) -#define STM32_DMA_CCR_CIRC BIT(5) -#define STM32_DMA_CCR_PINC BIT(6) -#define STM32_DMA_CCR_MINC BIT(7) -#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) -#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) -#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) -#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) -#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) -#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) -#define STM32_DMA_CCR_PL_LOW (0 << 12) -#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) -#define STM32_DMA_CCR_PL_HIGH (2 << 12) -#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) -#define STM32_DMA_CCR_MEM2MEM BIT(14) - - -/* --- CRC --- */ -#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) - -#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) -#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) -#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) -#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) - -#define STM32_CRC_CR_RESET BIT(0) -#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) -#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) -#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) -#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) -#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) -#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) -#define STM32_CRC_CR_REV_IN_WORD (3 << 5) -#define STM32_CRC_CR_REV_OUT BIT(7) - -/* --- PMSE --- */ -#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) -#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) -#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) -#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) -#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) -#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) -#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) -#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x) * 4) -#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) -#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) -#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) -#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) -#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) -#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) -#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) -#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) -#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) -#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) -#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) - -/* --- USB --- */ -#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n) * 4) - -#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) - -#define STM32_USB_CNTR_FRES BIT(0) -#define STM32_USB_CNTR_PDWN BIT(1) -#define STM32_USB_CNTR_LP_MODE BIT(2) -#define STM32_USB_CNTR_FSUSP BIT(3) -#define STM32_USB_CNTR_RESUME BIT(4) -#define STM32_USB_CNTR_L1RESUME BIT(5) -#define STM32_USB_CNTR_L1REQM BIT(7) -#define STM32_USB_CNTR_ESOFM BIT(8) -#define STM32_USB_CNTR_SOFM BIT(9) -#define STM32_USB_CNTR_RESETM BIT(10) -#define STM32_USB_CNTR_SUSPM BIT(11) -#define STM32_USB_CNTR_WKUPM BIT(12) -#define STM32_USB_CNTR_ERRM BIT(13) -#define STM32_USB_CNTR_PMAOVRM BIT(14) -#define STM32_USB_CNTR_CTRM BIT(15) - -#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) - -#define STM32_USB_ISTR_EP_ID_MASK (0x000f) -#define STM32_USB_ISTR_DIR BIT(4) -#define STM32_USB_ISTR_L1REQ BIT(7) -#define STM32_USB_ISTR_ESOF BIT(8) -#define STM32_USB_ISTR_SOF BIT(9) -#define STM32_USB_ISTR_RESET BIT(10) -#define STM32_USB_ISTR_SUSP BIT(11) -#define STM32_USB_ISTR_WKUP BIT(12) -#define STM32_USB_ISTR_ERR BIT(13) -#define STM32_USB_ISTR_PMAOVR BIT(14) -#define STM32_USB_ISTR_CTR BIT(15) - -#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) - -#define STM32_USB_FNR_RXDP_RXDM_SHIFT (14) -#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) - -#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) -#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) -#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) -#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) - -#define STM32_USB_BCDR_BCDEN BIT(0) -#define STM32_USB_BCDR_DCDEN BIT(1) -#define STM32_USB_BCDR_PDEN BIT(2) -#define STM32_USB_BCDR_SDEN BIT(3) -#define STM32_USB_BCDR_DCDET BIT(4) -#define STM32_USB_BCDR_PDET BIT(5) -#define STM32_USB_BCDR_SDET BIT(6) -#define STM32_USB_BCDR_PS2DET BIT(7) - -#define EP_MASK 0x0F0F -#define EP_TX_DTOG 0x0040 -#define EP_TX_MASK 0x0030 -#define EP_TX_VALID 0x0030 -#define EP_TX_NAK 0x0020 -#define EP_TX_STALL 0x0010 -#define EP_TX_DISAB 0x0000 -#define EP_RX_DTOG 0x4000 -#define EP_RX_MASK 0x3000 -#define EP_RX_VALID 0x3000 -#define EP_RX_NAK 0x2000 -#define EP_RX_STALL 0x1000 -#define EP_RX_DISAB 0x0000 - -#define EP_STATUS_OUT 0x0100 - -#define EP_TX_RX_MASK (EP_TX_MASK | EP_RX_MASK) -#define EP_TX_RX_VALID (EP_TX_VALID | EP_RX_VALID) - -#define STM32_TOGGLE_EP(n, mask, val, flags) \ - STM32_USB_EP(n) = (((STM32_USB_EP(n) & (EP_MASK | (mask))) \ - ^ (val)) | (flags)) - -/* --- TRNG --- */ -#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) -#define STM32_RNG_CR_RNGEN BIT(2) -#define STM32_RNG_CR_IE BIT(3) -#define STM32_RNG_CR_CED BIT(5) -#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) -#define STM32_RNG_SR_DRDY BIT(0) -#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) - -/* --- AXI interconnect --- */ - -/* STM32H7: AXI_TARGx_FN_MOD exists for masters x = 1, 2 and 7 */ -#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + \ - 0x1000 * (x)) -#define WRITE_ISS_OVERRIDE BIT(1) -#define READ_ISS_OVERRIDE BIT(0) - -/* --- MISC --- */ -#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) -#define STM32_UNIQUE_ID_LENGTH (3 * 4) +#define STM32_DMA_CCR_EN BIT(0) +#define STM32_DMA_CCR_TCIE BIT(1) +#define STM32_DMA_CCR_HTIE BIT(2) +#define STM32_DMA_CCR_TEIE BIT(3) +#define STM32_DMA_CCR_DIR BIT(4) +#define STM32_DMA_CCR_CIRC BIT(5) +#define STM32_DMA_CCR_PINC BIT(6) +#define STM32_DMA_CCR_MINC BIT(7) +#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) +#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) +#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) +#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) +#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) +#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) +#define STM32_DMA_CCR_PL_LOW (0 << 12) +#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) +#define STM32_DMA_CCR_PL_HIGH (2 << 12) +#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) +#define STM32_DMA_CCR_MEM2MEM BIT(14) #endif /* !__ASSEMBLER__ */ diff --git a/chip/stm32/registers-stm32l5.h b/chip/stm32/registers-stm32l5.h new file mode 100644 index 0000000000..f83802cf5f --- /dev/null +++ b/chip/stm32/registers-stm32l5.h @@ -0,0 +1,2782 @@ +/* Copyright 2019 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * @file + * @brief Register map for the STM32L5 family of chips + * + * This header file should not be included directly. + * Please include registers.h instead. + * + * Known Chip Variants + * - STM32L552 + */ + +#ifndef __CROS_EC_REGISTERS_H +#error "This header file should not be included directly." +#endif + +/****** STM32 specific Interrupt Numbers ********/ +#define STM32_IRQ_WWDG 0 +#define STM32_IRQ_PVD 1 +#define STM32_IRQ_RTC_ALARM 2 +#define STM32_IRQ_FLASH 6 +#define STM32_IRQ_FLASH_S 7 +#define STM32_IRQ_RCC 9 +#define STM32_IRQ_RCC_S 10 +#define STM32_IRQ_EXTI0 11 +#define STM32_IRQ_EXTI1 12 +#define STM32_IRQ_EXTI2 13 +#define STM32_IRQ_EXTI3 14 +#define STM32_IRQ_EXTI4 15 +#define STM32_IRQ_EXTI5 16 +#define STM32_IRQ_EXTI6 17 +#define STM32_IRQ_EXTI7 18 +#define STM32_IRQ_EXTI8 19 +#define STM32_IRQ_EXTI9 20 +#define STM32_IRQ_EXTI10 21 +#define STM32_IRQ_EXTI11 22 +#define STM32_IRQ_EXTI12 23 +#define STM32_IRQ_EXTI13 24 +#define STM32_IRQ_EXTI14 25 +#define STM32_IRQ_EXTI15 26 +#define STM32_IRQ_DMAMUX_OVR 27 +#define STM32_IRQ_DMAMUX_OVR_S 28 +#define STM32_IRQ_DMA_CHANNEL_1 29 +#define STM32_IRQ_DMA_CHANNEL_2 30 +#define STM32_IRQ_DMA_CHANNEL_3 31 +#define STM32_IRQ_DMA_CHANNEL_4 32 +#define STM32_IRQ_DMA_CHANNEL_5 33 +#define STM32_IRQ_DMA_CHANNEL_6 34 +#define STM32_IRQ_DMA_CHANNEL_7 35 +#define STM32_IRQ_DMA_CHANNEL_8 36 +#define STM32_IRQ_ADC1 37 +#define STM32_IRQ_TIM1_BRK 41 +#define STM32_IRQ_TIM1_UP 42 +#define STM32_IRQ_TIM1_TRG_COM 43 +#define STM32_IRQ_TIM1_CC 44 +#define STM32_IRQ_TIM2 45 +#define STM32_IRQ_TIM3 46 +#define STM32_IRQ_TIM4 47 +#define STM32_IRQ_TIM5 48 +#define STM32_IRQ_TIM6 49 +#define STM32_IRQ_TIM7 50 +#define STM32_IRQ_TIM8_BRK 51 +#define STM32_IRQ_TIM8_UP 52 +#define STM32_IRQ_TIM8_TRG_COM 53 +#define STM32_IRQ_TIM8_CC 54 +#define STM32_IRQ_I2C1_EV 55 +#define STM32_IRQ_I2C1_ER 56 +#define STM32_IRQ_I2C2_EV 57 +#define STM32_IRQ_I2C2_ER 58 +#define STM32_IRQ_SPI1 59 +#define STM32_IRQ_SPI2 60 +#define STM32_IRQ_USART1 61 +#define STM32_IRQ_USART2 62 +#define STM32_IRQ_USART3 63 +#define STM32_IRQ_USART4 64 +#define STM32_IRQ_USART5 65 +#define STM32_IRQ_LPUART1 66 +#define STM32_IRQ_LPTIM1 67 +#define STM32_IRQ_LPTIM2 68 +#define STM32_IRQ_TIM15 69 +#define STM32_IRQ_TIM16 70 +#define STM32_IRQ_TIM17 71 +#define STM32_IRQ_COMP 72 +#define STM32_IRQ_USB_FS 73 +#define STM32_IRQ_CRS 74 +#define STM32_IRQ_FMC 75 +#define STM32_IRQ_DMA2_CHANNEL1 80 +#define STM32_IRQ_DMA2_CHANNEL2 81 +#define STM32_IRQ_DMA2_CHANNEL3 82 +#define STM32_IRQ_DMA2_CHANNEL4 83 +#define STM32_IRQ_DMA2_CHANNEL5 84 +#define STM32_IRQ_DMA2_CHANNEL6 85 +#define STM32_IRQ_DMA2_CHANNEL7 86 +#define STM32_IRQ_DMA2_CHANNEL8 87 + +/* To simplify code generation, define DMA channel 9..16 */ +#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 +#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 +#define STM32_IRQ_DMA_CHANNEL_11 STM32_IRQ_DMA2_CHANNEL3 +#define STM32_IRQ_DMA_CHANNEL_12 STM32_IRQ_DMA2_CHANNEL4 +#define STM32_IRQ_DMA_CHANNEL_13 STM32_IRQ_DMA2_CHANNEL5 +#define STM32_IRQ_DMA_CHANNEL_14 STM32_IRQ_DMA2_CHANNEL6 +#define STM32_IRQ_DMA_CHANNEL_15 STM32_IRQ_DMA2_CHANNEL7 +#define STM32_IRQ_DMA_CHANNEL_16 STM32_IRQ_DMA2_CHANNEL8 + +/* aliases for easier code sharing */ +#define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV +#define STM32_IRQ_I2C2 STM32_IRQ_I2C2_EV +#define STM32_IRQ_I2C3 STM32_IRQ_I2C3_EV +#define STM32_IRQ_USB_LP STM32_IRQ_USB_FS + +#define PERIPH_BASE 0x40000000UL + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x02000000UL) +#define AHB3PERIPH_BASE (PERIPH_BASE + 0x04000000UL) + +/*!< APB1 peripherals */ +#define STM32_TIM2_BASE (APB1PERIPH_BASE + 0x0000UL) +#define STM32_TIM3_BASE (APB1PERIPH_BASE + 0x0400UL) +#define STM32_TIM4_BASE (APB1PERIPH_BASE + 0x0800UL) +#define STM32_TIM5_BASE (APB1PERIPH_BASE + 0x0C00UL) +#define STM32_TIM6_BASE (APB1PERIPH_BASE + 0x1000UL) +#define STM32_TIM7_BASE (APB1PERIPH_BASE + 0x1400UL) +#define STM32_RTC_BASE (APB1PERIPH_BASE + 0x2800UL) +#define STM32_WWDG_BASE (APB1PERIPH_BASE + 0x2C00UL) +#define STM32_IWDG_BASE (APB1PERIPH_BASE + 0x3000UL) +#define STM32_TAMP_BASE (APB1PERIPH_BASE + 0x3400UL) +#define STM32_SPI2_BASE (APB1PERIPH_BASE + 0x3800UL) +#define STM32_SPI3_BASE (APB1PERIPH_BASE + 0x3C00UL) +#define STM32_USART2_BASE (APB1PERIPH_BASE + 0x4400UL) +#define STM32_USART3_BASE (APB1PERIPH_BASE + 0x4800UL) +#define STM32_USART4_BASE (APB1PERIPH_BASE + 0x4c00UL) +#define STM32_USART5_BASE (APB1PERIPH_BASE + 0x5000UL) +#define STM32_I2C1_BASE (APB1PERIPH_BASE + 0x5400UL) +#define STM32_I2C2_BASE (APB1PERIPH_BASE + 0x5800UL) +#define STM32_I2C3_BASE (APB1PERIPH_BASE + 0x5C00UL) +#define STM32_CRS_BASE (APB1PERIPH_BASE + 0x6000UL) +#define STM32_PWR_BASE (APB1PERIPH_BASE + 0x7000UL) +#define STM32_DAC_BASE (APB1PERIPH_BASE + 0x7400UL) +#define STM32_DAC1_BASE (APB1PERIPH_BASE + 0x7400UL) +#define STM32_OPAMP_BASE (APB1PERIPH_BASE + 0x7800UL) +#define STM32_LPTIM1_BASE (APB1PERIPH_BASE + 0x7C00UL) +#define STM32_LPUART1_BASE (APB1PERIPH_BASE + 0x8000UL) +#define STM32_I2C4_BASE (APB1PERIPH_BASE + 0x8400UL) +#define STM32_LPTIM2_BASE (APB1PERIPH_BASE + 0x9400UL) +#define STM32_LPTIM3_BASE (APB1PERIPH_BASE + 0x9800UL) +#define STM32_FDCAN_RAM_BASE (APB1PERIPH_BASE + 0xA400UL) +#define STM32_CAN_RAM_BASE (APB1PERIPH_BASE + 0xAC00UL) +#define STM32_USB_FS_BASE (APB1PERIPH_BASE + 0xD400UL) +#define STM32_USB_CAN_SRAM_BASE (APB1PERIPH_BASE + 0xD800UL) +#define STM32_UCPD1_BASE (APB1PERIPH_BASE + 0xDC00UL) + +/*!< APB2 peripherals */ +#define STM32_SYSCFG_BASE (APB2PERIPH_BASE + 0x0000UL) +#define STM32_EXTI_BASE (AHB1PERIPH_BASE + 0xf400UL) +#define STM32_TIM1_BASE (APB2PERIPH_BASE + 0x2C00UL) +#define STM32_SPI1_BASE (APB2PERIPH_BASE + 0x3000UL) +#define STM32_TIM8_BASE (APB2PERIPH_BASE + 0x3400UL) +#define STM32_USART1_BASE (APB2PERIPH_BASE + 0x3800UL) +#define STM32_TIM15_BASE (APB2PERIPH_BASE + 0x4000UL) +#define STM32_TIM16_BASE (APB2PERIPH_BASE + 0x4400UL) +#define STM32_TIM17_BASE (APB2PERIPH_BASE + 0x4800UL) + +/*!< AHB1 peripherals */ +#define STM32_DMA1_BASE (AHB1PERIPH_BASE + 0x0000UL) +#define STM32_DMA2_BASE (AHB1PERIPH_BASE + 0x0400UL) +#define STM32_DMAMUX_BASE (AHB1PERIPH_BASE + 0x0800UL) +#define STM32_RCC_BASE (AHB1PERIPH_BASE + 0x1000UL) +#define STM32_FLASH_R_BASE (AHB1PERIPH_BASE + 0x2000UL) +#define STM32_CRC_BASE (AHB1PERIPH_BASE + 0x3000UL) +#define STM32_DMA1_Channel1_BASE (DMA1_BASE + 0x0008UL) +#define STM32_DMA1_Channel2_BASE (DMA1_BASE + 0x001CUL) +#define STM32_DMA1_Channel3_BASE (DMA1_BASE + 0x0030UL) +#define STM32_DMA1_Channel4_BASE (DMA1_BASE + 0x0044UL) +#define STM32_DMA1_Channel5_BASE (DMA1_BASE + 0x0058UL) +#define STM32_DMA1_Channel6_BASE (DMA1_BASE + 0x006CUL) +#define STM32_DMA1_Channel7_BASE (DMA1_BASE + 0x0080UL) +#define STM32_DMA1_CSELR_BASE (DMA1_BASE + 0x00A8UL) +#define STM32_DMA2_Channel1_BASE (DMA2_BASE + 0x0008UL) +#define STM32_DMA2_Channel2_BASE (DMA2_BASE + 0x001CUL) +#define STM32_DMA2_Channel3_BASE (DMA2_BASE + 0x0030UL) +#define STM32_DMA2_Channel4_BASE (DMA2_BASE + 0x0044UL) +#define STM32_DMA2_Channel5_BASE (DMA2_BASE + 0x0058UL) +#define STM32_DMA2_Channel6_BASE (DMA2_BASE + 0x006CUL) +#define STM32_DMA2_Channel7_BASE (DMA2_BASE + 0x0080UL) +#define STM32_DMA2_CSELR_BASE (DMA2_BASE + 0x00A8UL) + +/*!< AHB2 peripherals */ +#define STM32_GPIOA_BASE (AHB2PERIPH_BASE + 0x20000UL) +#define STM32_GPIOB_BASE (AHB2PERIPH_BASE + 0x20400UL) +#define STM32_GPIOC_BASE (AHB2PERIPH_BASE + 0x20800UL) +#define STM32_GPIOD_BASE (AHB2PERIPH_BASE + 0x20C00UL) +#define STM32_GPIOE_BASE (AHB2PERIPH_BASE + 0x21000UL) +#define STM32_GPIOF_BASE (AHB2PERIPH_BASE + 0x21400UL) +#define STM32_GPIOG_BASE (AHB2PERIPH_BASE + 0x21800UL) +#define STM32_GPIOH_BASE (AHB2PERIPH_BASE + 0x21C00UL) +#define STM32_ADC1_BASE (AHB2PERIPH_BASE + 0x28000UL) +#define STM32_RNG_BASE (AHB2PERIPH_BASE + 0xC4000UL) + +/*!< AHB3 peripherals */ +#define STM32_OCTOSPI_BASE (AHB3PERIPH_BASE + 0x21000UL) + +/* Debug MCU registers base address */ +#define STM32_PACKAGE_BASE 0x0BFA0500UL +#define STM32_UID_BASE 0x0BFA0590UL +#define STM32_FLASHSIZE_BASE 0x0BFA05E0UL + +#define STM32_FLASH_REGS_BASE STM32_FLASH_R_BASE +#define STM32_UNIQUE_ID_BASE STM32_UID_BASE + +#ifndef __ASSEMBLER__ + +/* Register definitions */ + +/* --- USART --- */ +#define STM32_USART_CR1(base) STM32_USART_REG(base, 0x00) +#define STM32_USART_CR1_UE BIT(0) +#define STM32_USART_CR1_UESM BIT(1) +#define STM32_USART_CR1_RE BIT(2) +#define STM32_USART_CR1_TE BIT(3) +#define STM32_USART_CR1_RXNEIE BIT(5) +#define STM32_USART_CR1_TCIE BIT(6) +#define STM32_USART_CR1_TXEIE BIT(7) +#define STM32_USART_CR1_PS BIT(9) +#define STM32_USART_CR1_PCE BIT(10) +#define STM32_USART_CR1_M BIT(12) +#define STM32_USART_CR1_OVER8 BIT(15) + +#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04) +#define STM32_USART_CR2_SWAP BIT(15) + +#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08) +#define STM32_USART_CR3_EIE BIT(0) +#define STM32_USART_CR3_DMAR BIT(6) +#define STM32_USART_CR3_DMAT BIT(7) +#define STM32_USART_CR3_ONEBIT BIT(11) +#define STM32_USART_CR3_OVRDIS BIT(12) +#define STM32_USART_CR3_WUS_START_BIT (2 << 20) +#define STM32_USART_CR3_WUFIE BIT(22) + +#define STM32_USART_BRR(base) STM32_USART_REG(base, 0x0C) +#define STM32_USART_GTPR(base) STM32_USART_REG(base, 0x10) +#define STM32_USART_RTOR(base) STM32_USART_REG(base, 0x14) +#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18) +#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C) +#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20) +#define STM32_USART_ICR_ORECF BIT(3) +#define STM32_USART_ICR_TCCF BIT(6) +#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24) +#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28) +#define STM32_USART_PRESC(base) STM32_USART_REG(base, 0x2C) +/* register alias */ +#define STM32_USART_SR(base) STM32_USART_ISR(base) +#define STM32_USART_SR_ORE BIT(3) +#define STM32_USART_SR_RXNE BIT(5) +#define STM32_USART_SR_TC BIT(6) +#define STM32_USART_SR_TXE BIT(7) + +/* --- GPIO --- */ +#define STM32_GPIO_MODER(b) REG32((b) + 0x00) +#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04) +#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08) +#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C) +#define STM32_GPIO_IDR(b) REG16((b) + 0x10) +#define STM32_GPIO_ODR(b) REG16((b) + 0x14) +#define STM32_GPIO_BSRR(b) REG32((b) + 0x18) +#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C) +#define STM32_GPIO_AFRL(b) REG32((b) + 0x20) +#define STM32_GPIO_AFRH(b) REG32((b) + 0x24) +#define STM32_GPIO_BRR(b) REG32((b) + 0x28) +#define STM32_GPIO_ASCR(b) REG32((b) + 0x2C) /* only for stm32l4x6 */ + +#define GPIO_ALT_F0 0x0 +#define GPIO_ALT_F1 0x1 +#define GPIO_ALT_F2 0x2 +#define GPIO_ALT_F3 0x3 +#define GPIO_ALT_F4 0x4 +#define GPIO_ALT_F5 0x5 +#define GPIO_ALT_F6 0x6 +#define GPIO_ALT_F7 0x7 +#define GPIO_ALT_F8 0x8 +#define GPIO_ALT_F9 0x9 +#define GPIO_ALT_FA 0xA +#define GPIO_ALT_FB 0xB +#define GPIO_ALT_FC 0xC +#define GPIO_ALT_FD 0xD +#define GPIO_ALT_FE 0xE +#define GPIO_ALT_FF 0xF + +/* --- I2C --- */ +#define STM32_I2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00)) +#define STM32_I2C_CR1_PE BIT(0) +#define STM32_I2C_CR1_TXIE BIT(1) +#define STM32_I2C_CR1_RXIE BIT(2) +#define STM32_I2C_CR1_ADDRIE BIT(3) +#define STM32_I2C_CR1_NACKIE BIT(4) +#define STM32_I2C_CR1_STOPIE BIT(5) +#define STM32_I2C_CR1_ERRIE BIT(7) +#define STM32_I2C_CR1_WUPEN BIT(18) +#define STM32_I2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04)) +#define STM32_I2C_CR2_RD_WRN BIT(10) +#define STM32_I2C_CR2_START BIT(13) +#define STM32_I2C_CR2_STOP BIT(14) +#define STM32_I2C_CR2_NACK BIT(15) +#define STM32_I2C_CR2_RELOAD BIT(24) +#define STM32_I2C_CR2_AUTOEND BIT(25) +#define STM32_I2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08)) +#define STM32_I2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C)) +#define STM32_I2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10)) +#define STM32_I2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14)) +#define STM32_I2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18)) +#define STM32_I2C_ISR_TXE BIT(0) +#define STM32_I2C_ISR_TXIS BIT(1) +#define STM32_I2C_ISR_RXNE BIT(2) +#define STM32_I2C_ISR_ADDR BIT(3) +#define STM32_I2C_ISR_NACK BIT(4) +#define STM32_I2C_ISR_STOP BIT(5) +#define STM32_I2C_ISR_TC BIT(6) +#define STM32_I2C_ISR_TCR BIT(7) +#define STM32_I2C_ISR_BERR BIT(8) +#define STM32_I2C_ISR_ARLO BIT(9) +#define STM32_I2C_ISR_OVR BIT(10) +#define STM32_I2C_ISR_PECERR BIT(11) +#define STM32_I2C_ISR_TIMEOUT BIT(12) +#define STM32_I2C_ISR_ALERT BIT(13) +#define STM32_I2C_ISR_BUSY BIT(15) +#define STM32_I2C_ISR_DIR BIT(16) +#define STM32_I2C_ISR_ADDCODE(isr) (((isr) >> 16) & 0xfe) +#define STM32_I2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C)) +#define STM32_I2C_ICR_ADDRCF BIT(3) +#define STM32_I2C_ICR_NACKCF BIT(4) +#define STM32_I2C_ICR_STOPCF BIT(5) +#define STM32_I2C_ICR_BERRCF BIT(8) +#define STM32_I2C_ICR_ARLOCF BIT(9) +#define STM32_I2C_ICR_OVRCF BIT(10) +#define STM32_I2C_ICR_TIMEOUTCF BIT(12) +#define STM32_I2C_ICR_ALL 0x3F38 +#define STM32_I2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20)) +#define STM32_I2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24)) +#define STM32_I2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28)) + +/* --- Power / Reset / Clocks --- */ +#define STM32_PWR_CR1 REG32(STM32_PWR_BASE + 0x00) +#define STM32_PWR_CR2 REG32(STM32_PWR_BASE + 0x04) +#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x10) +#define STM32_PWR_SCR REG32(STM32_PWR_BASE + 0x18) + +#define PWR_CR1_LPMS_POS 0U +#define PWR_CR1_LPMS_MSK (0x7UL << PWR_CR1_LPMS_POS) +#define PWR_CR1_LPMS PWR_CR1_LPMS_MSK +#define PWR_CR1_LPMS_STOP0 (0x00000000UL) +#define PWR_CR1_LPMS_STOP1_POS 0U +#define PWR_CR1_LPMS_STOP1_MSK (0x1UL << PWR_CR1_LPMS_STOP1_POS) +#define PWR_CR1_LPMS_STOP1 PWR_CR1_LPMS_STOP1_MSK +#define PWR_CR1_LPMS_STOP2_POS 1U +#define PWR_CR1_LPMS_STOP2_MSK (0x1UL << PWR_CR1_LPMS_STOP2_POS) +#define PWR_CR1_LPMS_STOP2 PWR_CR1_LPMS_STOP2_MSK +#define PWR_CR1_LPMS_STANDBY_POS 0U +#define PWR_CR1_LPMS_STANDBY_MSK (0x3UL << PWR_CR1_LPMS_STANDBY_POS) +#define PWR_CR1_LPMS_STANDBY PWR_CR1_LPMS_STANDBY_MSK +#define PWR_CR1_LPMS_SHUTDOWN_POS 2U +#define PWR_CR1_LPMS_SHUTDOWN_MSK (0x1UL << PWR_CR1_LPMS_SHUTDOWN_POS) +#define PWR_CR1_LPMS_SHUTDOWN PWR_CR1_LPMS_SHUTDOWN_MSK +#define PWR_CR1_VOS_POS 9U +#define PWR_CR1_VOS_MSK (0x3UL << PWR_CR1_VOS_POS) +#define PWR_CR1_VOS PWR_CR1_VOS_MSK +#define PWR_CR1_VOS_0 (0x1UL << PWR_CR1_VOS_POS) +#define PWR_CR1_VOS_1 (0x2UL << PWR_CR1_VOS_POS) + +#define STM32_PWR_CR2_IOSV_POS 9U +#define STM32_PWR_CR2_IOSV_MASK BIT(STM32_PWR_CR2_IOSV_POS) +#define STM32_PWR_CR2_IOSV STM32_PWR_CR2_IOSV_MASK +#define STM32_PWR_CR2_USV_POS 10U +#define STM32_PWR_CR2_USV_MASK BIT(STM32_PWR_CR2_USV_POS) +#define STM32_PWR_CR2_USV STM32_PWR_CR2_USV_MASK + +/* --- Macro usage in ec code --- */ +#define STM32_RCC_AHB2ENR_GPIOMASK \ + (STM32_RCC_AHB2ENR_GPIOAEN | STM32_RCC_AHB2ENR_GPIOBEN | \ + STM32_RCC_AHB2ENR_GPIOCEN | STM32_RCC_AHB2ENR_GPIODEN | \ + STM32_RCC_AHB2ENR_GPIOEEN | STM32_RCC_AHB2ENR_GPIOFEN | \ + STM32_RCC_AHB2ENR_GPIOGEN | STM32_RCC_AHB2ENR_GPIOHEN) +#define STM32_RCC_ICSCR_MSIRANGE(n) ((n) << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_ICSCR_MSIRANGE_1MHZ STM32_RCC_ICSCR_MSIRANGE(4) +#define STM32_RCC_ICSCR_MSIRANGE_2MHZ STM32_RCC_ICSCR_MSIRANGE(5) +#define STM32_RCC_ICSCR_MSIRANGE_MASK STM32_RCC_CR_MSIRANGE_MSK +#define STM32_RCC_SYSCFGEN STM32_RCC_APB2ENR_SYSCFGEN + +#define STM32_RCC_PB2_TIM1 STM32_RCC_APB2ENR_TIM1EN +#define STM32_RCC_PB2_TIM15 STM32_RCC_APB2ENR_TIM15EN +#define STM32_RCC_PB2_TIM16 STM32_RCC_APB2ENR_TIM16EN +#ifndef CHIP_VARIANT_STM32L431X +#define STM32_RCC_PB2_TIM8 BIT(13) +#endif +#define STM32_RCC_PWREN STM32_RCC_APB1ENR1_PWREN + +#define STM32_RCC_AHB2ENR_GPIO_PORTA BIT(0) +#define STM32_RCC_AHB2ENR_GPIO_PORTB BIT(1) +#define STM32_RCC_AHB2ENR_GPIO_PORTC BIT(2) +#define STM32_RCC_AHB2ENR_GPIO_PORTD BIT(3) +#define STM32_RCC_AHB2ENR_GPIO_PORTE BIT(4) +#define STM32_RCC_AHB2ENR_GPIO_PORTH BIT(7) +#define STM32_RCC_CCIPR_USART1SEL_SHIFT (0) +#define STM32_RCC_CCIPR_USART1SEL_MASK (3 << STM32_RCC_CCIPR_USART1SEL_SHIFT) +#define STM32_RCC_CCIPR_USART2SEL_SHIFT (2) +#define STM32_RCC_CCIPR_USART2SEL_MASK (3 << STM32_RCC_CCIPR_USART2SEL_SHIFT) +#define STM32_RCC_CCIPR_USART3SEL_SHIFT (4) +#define STM32_RCC_CCIPR_USART3SEL_MASK (3 << STM32_RCC_CCIPR_USART3SEL_SHIFT) +#define STM32_RCC_CCIPR_UART4SEL_SHIFT (6) +#define STM32_RCC_CCIPR_UART4SEL_MASK (3 << STM32_RCC_CCIPR_UART4SEL_SHIFT) +#define STM32_RCC_CCIPR_UART5SEL_SHIFT (8) +#define STM32_RCC_CCIPR_UART5SEL_MASK (3 << STM32_RCC_CCIPR_UART5SEL_SHIFT) +#define STM32_RCC_CCIPR_LPUART1SEL_SHIFT (10) +#define STM32_RCC_CCIPR_LPUART1SEL_MASK (3 << STM32_RCC_CCIPR_LPUART1SEL_SHIFT) +#define STM32_RCC_CCIPR_I2C1SEL_SHIFT (12) +#define STM32_RCC_CCIPR_I2C1SEL_MASK (3 << STM32_RCC_CCIPR_I2C1SEL_SHIFT) +#define STM32_RCC_CCIPR_I2C2SEL_SHIFT (14) +#define STM32_RCC_CCIPR_I2C2SEL_MASK (3 << STM32_RCC_CCIPR_I2C2SEL_SHIFT) +#define STM32_RCC_CCIPR_I2C3SEL_SHIFT (16) +#define STM32_RCC_CCIPR_I2C3SEL_MASK (3 << STM32_RCC_CCIPR_I2C3SEL_SHIFT) +#define STM32_RCC_CCIPR_LPTIM1SEL_SHIFT (18) +#define STM32_RCC_CCIPR_LPTIM1SEL_MASK (3 << STM32_RCC_CCIPR_LPTIM1SEL_SHIFT) +#define STM32_RCC_CCIPR_LPTIM2SEL_SHIFT (20) +#define STM32_RCC_CCIPR_LPTIM2SEL_MASK (3 << STM32_RCC_CCIPR_LPTIM2SEL_SHIFT) +#define STM32_RCC_CCIPR_SAI1SEL_SHIFT (22) +#define STM32_RCC_CCIPR_SAI1SEL_MASK (3 << STM32_RCC_CCIPR_SAI1SEL_SHIFT) +#define STM32_RCC_CCIPR_SAI2SEL_SHIFT (24) +#define STM32_RCC_CCIPR_SAI2SEL_MASK (3 << STM32_RCC_CCIPR_SAI2SEL_SHIFT) +#define STM32_RCC_CCIPR_CLK48SEL_SHIFT (26) +#define STM32_RCC_CCIPR_CLK48SEL_MASK (3 << STM32_RCC_CCIPR_CLK48SEL_SHIFT) +#define STM32_RCC_CCIPR_ADCSEL_SHIFT (28) +#define STM32_RCC_CCIPR_ADCSEL_MASK (3 << STM32_RCC_CCIPR_ADCSEL_SHIFT) +#define STM32_RCC_CCIPR_SWPMI1SEL_SHIFT (30) +#define STM32_RCC_CCIPR_SWPMI1SEL_MASK BIT(STM32_RCC_CCIPR_SWPMI1SEL_SHIFT) +#define STM32_RCC_CCIPR_DFSDM1SEL_SHIFT (31) +#define STM32_RCC_CCIPR_DFSDM1SEL_MASK BIT(STM32_RCC_CCIPR_DFSDM1SEL_SHIFT) +/* Possible clock sources for each peripheral */ +#define STM32_RCC_CCIPR_UART_PCLK 0 +#define STM32_RCC_CCIPR_UART_SYSCLK 1 +#define STM32_RCC_CCIPR_UART_HSI16 2 +#define STM32_RCC_CCIPR_UART_LSE 3 + +#define STM32_RCC_CCIPR_I2C_PCLK 0 +#define STM32_RCC_CCIPR_I2C_SYSCLK 1 +#define STM32_RCC_CCIPR_I2C_HSI16 2 + +#define STM32_RCC_CCIPR_LPTIM_PCLK 0 +#define STM32_RCC_CCIPR_LPTIM_LSI 1 +#define STM32_RCC_CCIPR_LPTIM_HSI16 2 +#define STM32_RCC_CCIPR_LPTIM_LSE 3 + +#define STM32_RCC_CCIPR_SAI_PLLSAI1CLK 0 +#define STM32_RCC_CCIPR_SAI_PLLSAI2CLK 1 +#define STM32_RCC_CCIPR_SAI_PLLSAI3CLK 2 +#define STM32_RCC_CCIPR_SAI_EXTCLK 3 + +#define STM32_RCC_CCIPR_CLK48_NONE 0 +#define STM32_RCC_CCIPR_CLK48_PLL48M2CLK 1 +#define STM32_RCC_CCIPR_CLK48_PLL48M1CLK 2 +#define STM32_RCC_CCIPR_CLK48_MSI 3 + +#define STM32_RCC_CCIPR_ADC_NONE 0 +#define STM32_RCC_CCIPR_ADC_PLLADC1CLK 1 +#define STM32_RCC_CCIPR_ADC_PLLADC2CLK 2 +#define STM32_RCC_CCIPR_ADC_SYSCLK 3 + +#define STM32_RCC_CCIPR_SWPMI_PCLK 0 +#define STM32_RCC_CCIPR_SWPMI_HSI16 1 + +#define STM32_RCC_CCIPR_DFSDM_PCLK 0 +#define STM32_RCC_CCIPR_DFSDM_SYSCLK 1 + +#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) +#define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x04) +#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08) +#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x0C) +#define STM32_RCC_PLLSAI1CFGR REG32(STM32_RCC_BASE + 0x10) +#define STM32_RCC_RESERVED REG32(STM32_RCC_BASE + 0x14) +#define STM32_RCC_CIER REG32(STM32_RCC_BASE + 0x18) +#define STM32_RCC_CIFR REG32(STM32_RCC_BASE + 0x1C) +#define STM32_RCC_CICR REG32(STM32_RCC_BASE + 0x20) +#define STM32_RCC_RESERVED0 REG32(STM32_RCC_BASE + 0x24) +#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x28) +#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x2C) +#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x30) +#define STM32_RCC_RESERVED1 REG32(STM32_RCC_BASE + 0x34) +#define STM32_RCC_APB1RSTR1 REG32(STM32_RCC_BASE + 0x38) +#define STM32_RCC_APB1RSTR2 REG32(STM32_RCC_BASE + 0x3C) +#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x40) +#define STM32_RCC_RESERVED2 REG32(STM32_RCC_BASE + 0x44) +#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x48) +#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x4C) +#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x50) +#define STM32_RCC_RESERVED3 REG32(STM32_RCC_BASE + 0x54) +#define STM32_RCC_APB1ENR1 REG32(STM32_RCC_BASE + 0x58) +#define STM32_RCC_APB1ENR2 REG32(STM32_RCC_BASE + 0x5C) +#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x60) +#define STM32_RCC_RESERVED4 REG32(STM32_RCC_BASE + 0x64) +#define STM32_RCC_AHB1SMENR REG32(STM32_RCC_BASE + 0x68) +#define STM32_RCC_AHB2SMENR REG32(STM32_RCC_BASE + 0x6C) +#define STM32_RCC_AHB3SMENR REG32(STM32_RCC_BASE + 0x70) +#define STM32_RCC_RESERVED5 REG32(STM32_RCC_BASE + 0x74) +#define STM32_RCC_APB1SMENR1 REG32(STM32_RCC_BASE + 0x78) +#define STM32_RCC_APB1SMENR2 REG32(STM32_RCC_BASE + 0x7C) +#define STM32_RCC_APB2SMENR REG32(STM32_RCC_BASE + 0x80) +#define STM32_RCC_RESERVED6 REG32(STM32_RCC_BASE + 0x84) +#define STM32_RCC_CCIPR1 REG32(STM32_RCC_BASE + 0x88) +#define STM32_RCC_CCIPR STM32_RCC_CCIPR1 +#define STM32_RCC_RESERVED7 REG32(STM32_RCC_BASE + 0x8C) +#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x90) +#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x94) +#define STM32_RCC_CRRCR REG32(STM32_RCC_BASE + 0x98) +#define STM32_RCC_CCIPR2 REG32(STM32_RCC_BASE + 0x9C) +#define STM32_CRS_CR REG32(STM32_CRS_BASE + 0x00) +#define STM32_CRS_CFGR REG32(STM32_CRS_BASE + 0x04) +#define STM32_CRS_ISR REG32(STM32_CRS_BASE + 0x08) +#define STM32_CRS_ICR REG32(STM32_CRS_BASE + 0x0C) + +#define STM32_RCC_PLLSAI1_SUPPORT +#define STM32_RCC_PLLP_SUPPORT +#define STM32_RCC_HSI48_SUPPORT +#define STM32_RCC_PLLP_DIV_2_31_SUPPORT +#define STM32_RCC_PLLSAI1P_DIV_2_31_SUPPORT + +#define STM32_RCC_APB1ENR STM32_RCC_APB1ENR1 + +/******************** BIT DEFINITION FOR STM32_RCC_CR REGISTER **************/ +#define STM32_RCC_CR_MSION_POS 0U +#define STM32_RCC_CR_MSION_MSK (0x1UL << STM32_RCC_CR_MSION_POS) +#define STM32_RCC_CR_MSION STM32_RCC_CR_MSION_MSK +#define STM32_RCC_CR_MSIRDY_POS 1U +#define STM32_RCC_CR_MSIRDY_MSK (0x1UL << STM32_RCC_CR_MSIRDY_POS) +#define STM32_RCC_CR_MSIRDY STM32_RCC_CR_MSIRDY_MSK +#define STM32_RCC_CR_MSIPLLEN_POS 2U +#define STM32_RCC_CR_MSIPLLEN_MSK (0x1UL << STM32_RCC_CR_MSIPLLEN_POS) +#define STM32_RCC_CR_MSIPLLEN STM32_RCC_CR_MSIPLLEN_MSK +#define STM32_RCC_CR_MSIRGSEL_POS 3U +#define STM32_RCC_CR_MSIRGSEL_MSK (0x1UL << STM32_RCC_CR_MSIRGSEL_POS) +#define STM32_RCC_CR_MSIRGSEL STM32_RCC_CR_MSIRGSEL_MSK + +/*!< MSIRANGE CONFIGURATION : 12 FREQUENCY RANGES AVAILABLE */ +#define STM32_RCC_CR_MSIRANGE_POS 4U +#define STM32_RCC_CR_MSIRANGE_MSK (0xFUL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE STM32_RCC_CR_MSIRANGE_MSK +#define STM32_RCC_CR_MSIRANGE_0 (0x0UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_1 (0x1UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_2 (0x2UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_3 (0x3UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_4 (0x4UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_5 (0x5UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_6 (0x6UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_7 (0x7UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_8 (0x8UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_9 (0x9UL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_10 (0xAUL << STM32_RCC_CR_MSIRANGE_POS) +#define STM32_RCC_CR_MSIRANGE_11 (0xBUL << STM32_RCC_CR_MSIRANGE_POS) + +#define STM32_RCC_CR_HSION_POS 8U +#define STM32_RCC_CR_HSION_MSK (0x1UL << STM32_RCC_CR_HSION_POS) +#define STM32_RCC_CR_HSION STM32_RCC_CR_HSION_MSK +#define STM32_RCC_CR_HSIKERON_POS 9U +#define STM32_RCC_CR_HSIKERON_MSK (0x1UL << STM32_RCC_CR_HSIKERON_POS) +#define STM32_RCC_CR_HSIKERON STM32_RCC_CR_HSIKERON_MSK +#define STM32_RCC_CR_HSIRDY_POS 10U +#define STM32_RCC_CR_HSIRDY_MSK (0x1UL << STM32_RCC_CR_HSIRDY_POS) +#define STM32_RCC_CR_HSIRDY STM32_RCC_CR_HSIRDY_MSK +#define STM32_RCC_CR_HSIASFS_POS 11U +#define STM32_RCC_CR_HSIASFS_MSK (0x1UL << STM32_RCC_CR_HSIASFS_POS) +#define STM32_RCC_CR_HSIASFS STM32_RCC_CR_HSIASFS_MSK + +#define STM32_RCC_CR_HSEON_POS 16U +#define STM32_RCC_CR_HSEON_MSK (0x1UL << STM32_RCC_CR_HSEON_POS) +#define STM32_RCC_CR_HSEON STM32_RCC_CR_HSEON_MSK +#define STM32_RCC_CR_HSERDY_POS 17U +#define STM32_RCC_CR_HSERDY_MSK (0x1UL << STM32_RCC_CR_HSERDY_POS) +#define STM32_RCC_CR_HSERDY STM32_RCC_CR_HSERDY_MSK +#define STM32_RCC_CR_HSEBYP_POS 18U +#define STM32_RCC_CR_HSEBYP_MSK (0x1UL << STM32_RCC_CR_HSEBYP_POS) +#define STM32_RCC_CR_HSEBYP STM32_RCC_CR_HSEBYP_MSK +#define STM32_RCC_CR_CSSON_POS 19U +#define STM32_RCC_CR_CSSON_MSK (0x1UL << STM32_RCC_CR_CSSON_POS) +#define STM32_RCC_CR_CSSON STM32_RCC_CR_CSSON_MSK + +#define STM32_RCC_CR_PLLON_POS 24U +#define STM32_RCC_CR_PLLON_MSK (0x1UL << STM32_RCC_CR_PLLON_POS) +#define STM32_RCC_CR_PLLON STM32_RCC_CR_PLLON_MSK +#define STM32_RCC_CR_PLLRDY_POS 25U +#define STM32_RCC_CR_PLLRDY_MSK (0x1UL << STM32_RCC_CR_PLLRDY_POS) +#define STM32_RCC_CR_PLLRDY STM32_RCC_CR_PLLRDY_MSK +#define STM32_RCC_CR_PLLSAI1ON_POS 26U +#define STM32_RCC_CR_PLLSAI1ON_MSK (0x1UL << STM32_RCC_CR_PLLSAI1ON_POS) +#define STM32_RCC_CR_PLLSAI1ON STM32_RCC_CR_PLLSAI1ON_MSK +#define STM32_RCC_CR_PLLSAI1RDY_POS 27U +#define STM32_RCC_CR_PLLSAI1RDY_MSK (0x1UL << STM32_RCC_CR_PLLSAI1RDY_POS) +#define STM32_RCC_CR_PLLSAI1RDY STM32_RCC_CR_PLLSAI1RDY_MSK + +/******************** BIT DEFINITION FOR STM32_RCC_ICSCR REGISTER ***********/ +/*!< MSICAL CONFIGURATION */ +#define STM32_RCC_ICSCR_MSICAL_POS 0U +#define STM32_RCC_ICSCR_MSICAL_MSK (0xFFUL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL STM32_RCC_ICSCR_MSICAL_MSK +#define STM32_RCC_ICSCR_MSICAL_0 (0x01UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_1 (0x02UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_2 (0x04UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_3 (0x08UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_4 (0x10UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_5 (0x20UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_6 (0x40UL << STM32_RCC_ICSCR_MSICAL_POS) +#define STM32_RCC_ICSCR_MSICAL_7 (0x80UL << STM32_RCC_ICSCR_MSICAL_POS) + +/*!< MSITRIM CONFIGURATION */ +#define STM32_RCC_ICSCR_MSITRIM_POS 8U +#define STM32_RCC_ICSCR_MSITRIM_MSK (0xFFUL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM STM32_RCC_ICSCR_MSITRIM_MSK +#define STM32_RCC_ICSCR_MSITRIM_0 (0x01UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_1 (0x02UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_2 (0x04UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_3 (0x08UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_4 (0x10UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_5 (0x20UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_6 (0x40UL << STM32_RCC_ICSCR_MSITRIM_POS) +#define STM32_RCC_ICSCR_MSITRIM_7 (0x80UL << STM32_RCC_ICSCR_MSITRIM_POS) + +/*!< HSICAL CONFIGURATION */ +#define STM32_RCC_ICSCR_HSICAL_POS 16U +#define STM32_RCC_ICSCR_HSICAL_MSK (0xFFUL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL STM32_RCC_ICSCR_HSICAL_MSK +#define STM32_RCC_ICSCR_HSICAL_0 (0x01UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_1 (0x02UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_2 (0x04UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_3 (0x08UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_4 (0x10UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_5 (0x20UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_6 (0x40UL << STM32_RCC_ICSCR_HSICAL_POS) +#define STM32_RCC_ICSCR_HSICAL_7 (0x80UL << STM32_RCC_ICSCR_HSICAL_POS) + +/*!< HSITRIM CONFIGURATION */ +#define STM32_RCC_ICSCR_HSITRIM_POS 24U +#define STM32_RCC_ICSCR_HSITRIM_MSK (0x1FUL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM STM32_RCC_ICSCR_HSITRIM_MSK +#define STM32_RCC_ICSCR_HSITRIM_0 (0x01UL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM_1 (0x02UL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM_2 (0x04UL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM_3 (0x08UL << STM32_RCC_ICSCR_HSITRIM_POS) +#define STM32_RCC_ICSCR_HSITRIM_4 (0x10UL << STM32_RCC_ICSCR_HSITRIM_POS) + +/**************** BIT DEFINITION FOR STM32_RCC_CFGR REGISTER **************/ +/*!< SW CONFIGURATION */ +#define STM32_RCC_CFGR_SW_POS 0U +#define STM32_RCC_CFGR_SW_MSK (0x3UL << STM32_RCC_CFGR_SW_POS) +#define STM32_RCC_CFGR_SW STM32_RCC_CFGR_SW_MSK +#define STM32_RCC_CFGR_SW_0 (0x1UL << STM32_RCC_CFGR_SW_POS) +#define STM32_RCC_CFGR_SW_1 (0x2UL << STM32_RCC_CFGR_SW_POS) + +#define STM32_RCC_CFGR_SW_MSI (0x00000000UL) +#define STM32_RCC_CFGR_SW_HSI (0x00000001UL) +#define STM32_RCC_CFGR_SW_HSE (0x00000002UL) +#define STM32_RCC_CFGR_SW_PLL (0x00000003UL) + +/*!< SWS CONFIGURATION */ +#define STM32_RCC_CFGR_SWS_POS 2U +#define STM32_RCC_CFGR_SWS_MSK (0x3UL << STM32_RCC_CFGR_SWS_POS) +#define STM32_RCC_CFGR_SWS STM32_RCC_CFGR_SWS_MSK +#define STM32_RCC_CFGR_SWS_0 (0x1UL << STM32_RCC_CFGR_SWS_POS) +#define STM32_RCC_CFGR_SWS_1 (0x2UL << STM32_RCC_CFGR_SWS_POS) + +#define STM32_RCC_CFGR_SWS_MSI (0x00000000UL) +#define STM32_RCC_CFGR_SWS_HSI (0x00000004UL) +#define STM32_RCC_CFGR_SWS_HSE (0x00000008UL) +#define STM32_RCC_CFGR_SWS_PLL (0x0000000CUL) + +/*!< HPRE CONFIGURATION */ +#define STM32_RCC_CFGR_HPRE_POS 4U +#define STM32_RCC_CFGR_HPRE_MSK (0xFUL << STM32_RCC_CFGR_HPRE_POS) +#define STM32_RCC_CFGR_HPRE STM32_RCC_CFGR_HPRE_MSK +#define STM32_RCC_CFGR_HPRE_0 (0x1UL << STM32_RCC_CFGR_HPRE_POS) +#define STM32_RCC_CFGR_HPRE_1 (0x2UL << STM32_RCC_CFGR_HPRE_POS) +#define STM32_RCC_CFGR_HPRE_2 (0x4UL << STM32_RCC_CFGR_HPRE_POS) +#define STM32_RCC_CFGR_HPRE_3 (0x8UL << STM32_RCC_CFGR_HPRE_POS) + +#define STM32_RCC_CFGR_HPRE_DIV1 (0x00000000UL) +#define STM32_RCC_CFGR_HPRE_DIV2 (0x00000080UL) +#define STM32_RCC_CFGR_HPRE_DIV4 (0x00000090UL) +#define STM32_RCC_CFGR_HPRE_DIV8 (0x000000A0UL) +#define STM32_RCC_CFGR_HPRE_DIV16 (0x000000B0UL) +#define STM32_RCC_CFGR_HPRE_DIV64 (0x000000C0UL) +#define STM32_RCC_CFGR_HPRE_DIV128 (0x000000D0UL) +#define STM32_RCC_CFGR_HPRE_DIV256 (0x000000E0UL) +#define STM32_RCC_CFGR_HPRE_DIV512 (0x000000F0UL) + +/*!< PPRE1 CONFIGURATION */ +#define STM32_RCC_CFGR_PPRE1_POS 8U +#define STM32_RCC_CFGR_PPRE1_MSK (0x7UL << STM32_RCC_CFGR_PPRE1_POS) +#define STM32_RCC_CFGR_PPRE1 STM32_RCC_CFGR_PPRE1_MSK +#define STM32_RCC_CFGR_PPRE1_0 (0x1UL << STM32_RCC_CFGR_PPRE1_POS) +#define STM32_RCC_CFGR_PPRE1_1 (0x2UL << STM32_RCC_CFGR_PPRE1_POS) +#define STM32_RCC_CFGR_PPRE1_2 (0x4UL << STM32_RCC_CFGR_PPRE1_POS) + +#define STM32_RCC_CFGR_PPRE1_DIV1 (0x00000000UL) +#define STM32_RCC_CFGR_PPRE1_DIV2 (0x00000400UL) +#define STM32_RCC_CFGR_PPRE1_DIV4 (0x00000500UL) +#define STM32_RCC_CFGR_PPRE1_DIV8 (0x00000600UL) +#define STM32_RCC_CFGR_PPRE1_DIV16 (0x00000700UL) + +/*!< PPRE2 CONFIGURATION */ +#define STM32_RCC_CFGR_PPRE2_POS 11U +#define STM32_RCC_CFGR_PPRE2_MSK (0x7UL << STM32_RCC_CFGR_PPRE2_POS) +#define STM32_RCC_CFGR_PPRE2 STM32_RCC_CFGR_PPRE2_MSK +#define STM32_RCC_CFGR_PPRE2_0 (0x1UL << STM32_RCC_CFGR_PPRE2_POS) +#define STM32_RCC_CFGR_PPRE2_1 (0x2UL << STM32_RCC_CFGR_PPRE2_POS) +#define STM32_RCC_CFGR_PPRE2_2 (0x4UL << STM32_RCC_CFGR_PPRE2_POS) + +#define STM32_RCC_CFGR_PPRE2_DIV1 (0x00000000UL) +#define STM32_RCC_CFGR_PPRE2_DIV2 (0x00002000UL) +#define STM32_RCC_CFGR_PPRE2_DIV4 (0x00002800UL) +#define STM32_RCC_CFGR_PPRE2_DIV8 (0x00003000UL) +#define STM32_RCC_CFGR_PPRE2_DIV16 (0x00003800UL) + +#define STM32_RCC_CFGR_STOPWUCK_POS 15U +#define STM32_RCC_CFGR_STOPWUCK_MSK (0x1UL << STM32_RCC_CFGR_STOPWUCK_POS) +#define STM32_RCC_CFGR_STOPWUCK STM32_RCC_CFGR_STOPWUCK_MSK + +/*!< MCOSEL CONFIGURATION */ +#define STM32_RCC_CFGR_MCOSEL_POS 24U +#define STM32_RCC_CFGR_MCOSEL_MSK (0xFUL << STM32_RCC_CFGR_MCOSEL_POS) +#define STM32_RCC_CFGR_MCOSEL STM32_RCC_CFGR_MCOSEL_MSK +#define STM32_RCC_CFGR_MCOSEL_0 (0x1UL << STM32_RCC_CFGR_MCOSEL_POS) +#define STM32_RCC_CFGR_MCOSEL_1 (0x2UL << STM32_RCC_CFGR_MCOSEL_POS) +#define STM32_RCC_CFGR_MCOSEL_2 (0x4UL << STM32_RCC_CFGR_MCOSEL_POS) +#define STM32_RCC_CFGR_MCOSEL_3 (0x8UL << STM32_RCC_CFGR_MCOSEL_POS) + +#define STM32_RCC_CFGR_MCOPRE_POS 28U +#define STM32_RCC_CFGR_MCOPRE_MSK (0x7UL << STM32_RCC_CFGR_MCOPRE_POS) +#define STM32_RCC_CFGR_MCOPRE STM32_RCC_CFGR_MCOPRE_MSK +#define STM32_RCC_CFGR_MCOPRE_0 (0x1UL << STM32_RCC_CFGR_MCOPRE_POS) +#define STM32_RCC_CFGR_MCOPRE_1 (0x2UL << STM32_RCC_CFGR_MCOPRE_POS) +#define STM32_RCC_CFGR_MCOPRE_2 (0x4UL << STM32_RCC_CFGR_MCOPRE_POS) + +#define STM32_RCC_CFGR_MCOPRE_DIV1 (0x00000000UL) +#define STM32_RCC_CFGR_MCOPRE_DIV2 (0x10000000UL) +#define STM32_RCC_CFGR_MCOPRE_DIV4 (0x20000000UL) +#define STM32_RCC_CFGR_MCOPRE_DIV8 (0x30000000UL) +#define STM32_RCC_CFGR_MCOPRE_DIV16 (0x40000000UL) + +/* LEGACY ALIASES */ +#define STM32_RCC_CFGR_MCO_PRE STM32_RCC_CFGR_MCOPRE +#define STM32_RCC_CFGR_MCO_PRE_1 STM32_RCC_CFGR_MCOPRE_DIV1 +#define STM32_RCC_CFGR_MCO_PRE_2 STM32_RCC_CFGR_MCOPRE_DIV2 +#define STM32_RCC_CFGR_MCO_PRE_4 STM32_RCC_CFGR_MCOPRE_DIV4 +#define STM32_RCC_CFGR_MCO_PRE_8 STM32_RCC_CFGR_MCOPRE_DIV8 +#define STM32_RCC_CFGR_MCO_PRE_16 STM32_RCC_CFGR_MCOPRE_DIV16 + +/**************** BIT DEFINITION FOR STM32_RCC_PLLCFGR REGISTER ***********/ +#define STM32_RCC_PLLCFGR_PLLSRC_POS 0U +#define STM32_RCC_PLLCFGR_PLLSRC_MSK (0x3UL << STM32_RCC_PLLCFGR_PLLSRC_POS) +#define STM32_RCC_PLLCFGR_PLLSRC STM32_RCC_PLLCFGR_PLLSRC_MSK + +#define STM32_RCC_PLLCFGR_PLLSRC_MSI_POS 0U +#define STM32_RCC_PLLCFGR_PLLSRC_MSI_MSK \ + (0x1UL << STM32_RCC_PLLCFGR_PLLSRC_MSI_POS) +#define STM32_RCC_PLLCFGR_PLLSRC_MSI STM32_RCC_PLLCFGR_PLLSRC_MSI_MSK +#define STM32_RCC_PLLCFGR_PLLSRC_HSI_POS 1U +#define STM32_RCC_PLLCFGR_PLLSRC_HSI_MSK \ + (0x1UL << STM32_RCC_PLLCFGR_PLLSRC_HSI_POS) +#define STM32_RCC_PLLCFGR_PLLSRC_HSI STM32_RCC_PLLCFGR_PLLSRC_HSI_MSK +#define STM32_RCC_PLLCFGR_PLLSRC_HSE_POS 0U +#define STM32_RCC_PLLCFGR_PLLSRC_HSE_MSK \ + (0x3UL << STM32_RCC_PLLCFGR_PLLSRC_HSE_POS) +#define STM32_RCC_PLLCFGR_PLLSRC_HSE STM32_RCC_PLLCFGR_PLLSRC_HSE_MSK + +#define STM32_RCC_PLLCFGR_PLLM_POS 4U +#define STM32_RCC_PLLCFGR_PLLM_MSK (0x7UL << STM32_RCC_PLLCFGR_PLLM_POS) +#define STM32_RCC_PLLCFGR_PLLM STM32_RCC_PLLCFGR_PLLM_MSK +#define STM32_RCC_PLLCFGR_PLLM_0 (0x1UL << STM32_RCC_PLLCFGR_PLLM_POS) +#define STM32_RCC_PLLCFGR_PLLM_1 (0x2UL << STM32_RCC_PLLCFGR_PLLM_POS) +#define STM32_RCC_PLLCFGR_PLLM_2 (0x4UL << STM32_RCC_PLLCFGR_PLLM_POS) + +#define STM32_RCC_PLLCFGR_PLLN_POS 8U +#define STM32_RCC_PLLCFGR_PLLN_MSK (0x7FUL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN STM32_RCC_PLLCFGR_PLLN_MSK +#define STM32_RCC_PLLCFGR_PLLN_0 (0x01UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_1 (0x02UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_2 (0x04UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_3 (0x08UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_4 (0x10UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_5 (0x20UL << STM32_RCC_PLLCFGR_PLLN_POS) +#define STM32_RCC_PLLCFGR_PLLN_6 (0x40UL << STM32_RCC_PLLCFGR_PLLN_POS) + +#define STM32_RCC_PLLCFGR_PLLPEN_POS 16U +#define STM32_RCC_PLLCFGR_PLLPEN_MSK (0x1UL << STM32_RCC_PLLCFGR_PLLPEN_POS) +#define STM32_RCC_PLLCFGR_PLLPEN STM32_RCC_PLLCFGR_PLLPEN_MSK +#define STM32_RCC_PLLCFGR_PLLP_POS 17U +#define STM32_RCC_PLLCFGR_PLLP_MSK (0x1UL << STM32_RCC_PLLCFGR_PLLP_POS) +#define STM32_RCC_PLLCFGR_PLLP STM32_RCC_PLLCFGR_PLLP_MSK +#define STM32_RCC_PLLCFGR_PLLQEN_POS 20U +#define STM32_RCC_PLLCFGR_PLLQEN_MSK (0x1UL << STM32_RCC_PLLCFGR_PLLQEN_POS) +#define STM32_RCC_PLLCFGR_PLLQEN STM32_RCC_PLLCFGR_PLLQEN_MSK + +#define STM32_RCC_PLLCFGR_PLLQ_POS 21U +#define STM32_RCC_PLLCFGR_PLLQ_MSK (0x3UL << STM32_RCC_PLLCFGR_PLLQ_POS) +#define STM32_RCC_PLLCFGR_PLLQ STM32_RCC_PLLCFGR_PLLQ_MSK +#define STM32_RCC_PLLCFGR_PLLQ_0 (0x1UL << STM32_RCC_PLLCFGR_PLLQ_POS) +#define STM32_RCC_PLLCFGR_PLLQ_1 (0x2UL << STM32_RCC_PLLCFGR_PLLQ_POS) + +#define STM32_RCC_PLLCFGR_PLLREN_POS 24U +#define STM32_RCC_PLLCFGR_PLLREN_MSK (0x1UL << STM32_RCC_PLLCFGR_PLLREN_POS) +#define STM32_RCC_PLLCFGR_PLLREN STM32_RCC_PLLCFGR_PLLREN_MSK +#define STM32_RCC_PLLCFGR_PLLR_POS 25U +#define STM32_RCC_PLLCFGR_PLLR_MSK (0x3UL << STM32_RCC_PLLCFGR_PLLR_POS) +#define STM32_RCC_PLLCFGR_PLLR STM32_RCC_PLLCFGR_PLLR_MSK +#define STM32_RCC_PLLCFGR_PLLR_0 (0x1UL << STM32_RCC_PLLCFGR_PLLR_POS) +#define STM32_RCC_PLLCFGR_PLLR_1 (0x2UL << STM32_RCC_PLLCFGR_PLLR_POS) + +#define STM32_RCC_PLLCFGR_PLLPDIV_POS 27U +#define STM32_RCC_PLLCFGR_PLLPDIV_MSK (0x1FUL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV STM32_RCC_PLLCFGR_PLLPDIV_MSK +#define STM32_RCC_PLLCFGR_PLLPDIV_0 (0x01UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV_1 (0x02UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV_2 (0x04UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV_3 (0x08UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) +#define STM32_RCC_PLLCFGR_PLLPDIV_4 (0x10UL << STM32_RCC_PLLCFGR_PLLPDIV_POS) + +/**************** BIT DEFINITION FOR STM32_RCC_PLLSAI1CFGR REGISTER ********/ +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS 8U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_MSK \ + (0x7FUL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N STM32_RCC_PLLSAI1CFGR_PLLSAI1N_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_0 \ + (0x01UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_1 \ + (0x02UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_2 \ + (0x04UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_3 \ + (0x08UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_4 \ + (0x10UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_5 \ + (0x20UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1N_6 \ + (0x40UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1N_POS) + +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN_POS 16U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN_MSK \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN STM32_RCC_PLLSAI1CFGR_PLLSAI1PEN_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1P_POS 17U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1P_MSK \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1P_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1P STM32_RCC_PLLSAI1CFGR_PLLSAI1P_MSK + +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN_POS 20U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN_MSK \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN STM32_RCC_PLLSAI1CFGR_PLLSAI1QEN_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_POS 21U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_MSK \ + (0x3UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_0 \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_1 \ + (0x2UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1Q_POS) + +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1REN_POS 24U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1REN_MSK \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1REN_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1REN STM32_RCC_PLLSAI1CFGR_PLLSAI1REN_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R_POS 25U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R_MSK \ + (0x3UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1R_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R STM32_RCC_PLLSAI1CFGR_PLLSAI1R_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R_0 \ + (0x1UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1R_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1R_1 \ + (0x2UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1R_POS) + +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS 27U +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_MSK \ + (0x1FUL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_MSK +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_0 \ + (0x01UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_1 \ + (0x02UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_2 \ + (0x04UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_3 \ + (0x08UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) +#define STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_4 \ + (0x10UL << STM32_RCC_PLLSAI1CFGR_PLLSAI1PDIV_POS) + +/************** BIT DEFINITION FOR STM32_RCC_CIER REGISTER ******************/ +#define STM32_RCC_CIER_LSIRDYIE_POS 0U +#define STM32_RCC_CIER_LSIRDYIE_MSK (0x1UL << STM32_RCC_CIER_LSIRDYIE_POS) +#define STM32_RCC_CIER_LSIRDYIE STM32_RCC_CIER_LSIRDYIE_MSK +#define STM32_RCC_CIER_LSERDYIE_POS 1U +#define STM32_RCC_CIER_LSERDYIE_MSK (0x1UL << STM32_RCC_CIER_LSERDYIE_POS) +#define STM32_RCC_CIER_LSERDYIE STM32_RCC_CIER_LSERDYIE_MSK +#define STM32_RCC_CIER_MSIRDYIE_POS 2U +#define STM32_RCC_CIER_MSIRDYIE_MSK (0x1UL << STM32_RCC_CIER_MSIRDYIE_POS) +#define STM32_RCC_CIER_MSIRDYIE STM32_RCC_CIER_MSIRDYIE_MSK +#define STM32_RCC_CIER_HSIRDYIE_POS 3U +#define STM32_RCC_CIER_HSIRDYIE_MSK (0x1UL << STM32_RCC_CIER_HSIRDYIE_POS) +#define STM32_RCC_CIER_HSIRDYIE STM32_RCC_CIER_HSIRDYIE_MSK +#define STM32_RCC_CIER_HSERDYIE_POS 4U +#define STM32_RCC_CIER_HSERDYIE_MSK (0x1UL << STM32_RCC_CIER_HSERDYIE_POS) +#define STM32_RCC_CIER_HSERDYIE STM32_RCC_CIER_HSERDYIE_MSK +#define STM32_RCC_CIER_PLLRDYIE_POS 5U +#define STM32_RCC_CIER_PLLRDYIE_MSK (0x1UL << STM32_RCC_CIER_PLLRDYIE_POS) +#define STM32_RCC_CIER_PLLRDYIE STM32_RCC_CIER_PLLRDYIE_MSK +#define STM32_RCC_CIER_PLLSAI1RDYIE_POS 6U +#define STM32_RCC_CIER_PLLSAI1RDYIE_MSK \ + (0x1UL << STM32_RCC_CIER_PLLSAI1RDYIE_POS) +#define STM32_RCC_CIER_PLLSAI1RDYIE STM32_RCC_CIER_PLLSAI1RDYIE_MSK +#define STM32_RCC_CIER_PLLSAI2RDYIE_POS 7U +#define STM32_RCC_CIER_PLLSAI2RDYIE_MSK \ + (0x1UL << STM32_RCC_CIER_PLLSAI2RDYIE_POS) +#define STM32_RCC_CIER_PLLSAI2RDYIE STM32_RCC_CIER_PLLSAI2RDYIE_MSK +#define STM32_RCC_CIER_HSI48RDYIE_POS 10U +#define STM32_RCC_CIER_HSI48RDYIE_MSK (0x1UL << STM32_RCC_CIER_HSI48RDYIE_POS) +#define STM32_RCC_CIER_HSI48RDYIE STM32_RCC_CIER_HSI48RDYIE_MSK + +/************** BIT DEFINITION FOR STM32_RCC_CIFR REGISTER ******************/ +#define STM32_RCC_CIFR_LSIRDYF_POS 0U +#define STM32_RCC_CIFR_LSIRDYF_MSK (0x1UL << STM32_RCC_CIFR_LSIRDYF_POS) +#define STM32_RCC_CIFR_LSIRDYF STM32_RCC_CIFR_LSIRDYF_MSK +#define STM32_RCC_CIFR_LSERDYF_POS 1U +#define STM32_RCC_CIFR_LSERDYF_MSK (0x1UL << STM32_RCC_CIFR_LSERDYF_POS) +#define STM32_RCC_CIFR_LSERDYF STM32_RCC_CIFR_LSERDYF_MSK +#define STM32_RCC_CIFR_MSIRDYF_POS 2U +#define STM32_RCC_CIFR_MSIRDYF_MSK (0x1UL << STM32_RCC_CIFR_MSIRDYF_POS) +#define STM32_RCC_CIFR_MSIRDYF STM32_RCC_CIFR_MSIRDYF_MSK +#define STM32_RCC_CIFR_HSIRDYF_POS 3U +#define STM32_RCC_CIFR_HSIRDYF_MSK (0x1UL << STM32_RCC_CIFR_HSIRDYF_POS) +#define STM32_RCC_CIFR_HSIRDYF STM32_RCC_CIFR_HSIRDYF_MSK +#define STM32_RCC_CIFR_HSERDYF_POS 4U +#define STM32_RCC_CIFR_HSERDYF_MSK (0x1UL << STM32_RCC_CIFR_HSERDYF_POS) +#define STM32_RCC_CIFR_HSERDYF STM32_RCC_CIFR_HSERDYF_MSK +#define STM32_RCC_CIFR_PLLRDYF_POS 5U +#define STM32_RCC_CIFR_PLLRDYF_MSK (0x1UL << STM32_RCC_CIFR_PLLRDYF_POS) +#define STM32_RCC_CIFR_PLLRDYF STM32_RCC_CIFR_PLLRDYF_MSK +#define STM32_RCC_CIFR_PLLSAI1RDYF_POS 6U +#define STM32_RCC_CIFR_PLLSAI1RDYF_MSK (0x1UL << STM32_RCC_CIFR_PLLSAI1RDYF_POS) +#define STM32_RCC_CIFR_PLLSAI1RDYF STM32_RCC_CIFR_PLLSAI1RDYF_MSK +#define STM32_RCC_CIFR_PLLSAI2RDYF_POS 7U +#define STM32_RCC_CIFR_PLLSAI2RDYF_MSK (0x1UL << STM32_RCC_CIFR_PLLSAI2RDYF_POS) +#define STM32_RCC_CIFR_PLLSAI2RDYF STM32_RCC_CIFR_PLLSAI2RDYF_MSK +#define STM32_RCC_CIFR_CSSF_POS 8U +#define STM32_RCC_CIFR_CSSF_MSK (0x1UL << STM32_RCC_CIFR_CSSF_POS) +#define STM32_RCC_CIFR_CSSF STM32_RCC_CIFR_CSSF_MSK +#define STM32_RCC_CIFR_HSI48RDYF_POS 10U +#define STM32_RCC_CIFR_HSI48RDYF_MSK (0x1UL << STM32_RCC_CIFR_HSI48RDYF_POS) +#define STM32_RCC_CIFR_HSI48RDYF STM32_RCC_CIFR_HSI48RDYF_MSK + +/************** BIT DEFINITION FOR STM32_RCC_CICR REGISTER ******************/ +#define STM32_RCC_CICR_LSIRDYC_POS 0U +#define STM32_RCC_CICR_LSIRDYC_MSK (0x1UL << STM32_RCC_CICR_LSIRDYC_POS) +#define STM32_RCC_CICR_LSIRDYC STM32_RCC_CICR_LSIRDYC_MSK +#define STM32_RCC_CICR_LSERDYC_POS 1U +#define STM32_RCC_CICR_LSERDYC_MSK (0x1UL << STM32_RCC_CICR_LSERDYC_POS) +#define STM32_RCC_CICR_LSERDYC STM32_RCC_CICR_LSERDYC_MSK +#define STM32_RCC_CICR_MSIRDYC_POS 2U +#define STM32_RCC_CICR_MSIRDYC_MSK (0x1UL << STM32_RCC_CICR_MSIRDYC_POS) +#define STM32_RCC_CICR_MSIRDYC STM32_RCC_CICR_MSIRDYC_MSK +#define STM32_RCC_CICR_HSIRDYC_POS 3U +#define STM32_RCC_CICR_HSIRDYC_MSK (0x1UL << STM32_RCC_CICR_HSIRDYC_POS) +#define STM32_RCC_CICR_HSIRDYC STM32_RCC_CICR_HSIRDYC_MSK +#define STM32_RCC_CICR_HSERDYC_POS 4U +#define STM32_RCC_CICR_HSERDYC_MSK (0x1UL << STM32_RCC_CICR_HSERDYC_POS) +#define STM32_RCC_CICR_HSERDYC STM32_RCC_CICR_HSERDYC_MSK +#define STM32_RCC_CICR_PLLRDYC_POS 5U +#define STM32_RCC_CICR_PLLRDYC_MSK (0x1UL << STM32_RCC_CICR_PLLRDYC_POS) +#define STM32_RCC_CICR_PLLRDYC STM32_RCC_CICR_PLLRDYC_MSK +#define STM32_RCC_CICR_PLLSAI1RDYC_POS 6U +#define STM32_RCC_CICR_PLLSAI1RDYC_MSK (0x1UL << STM32_RCC_CICR_PLLSAI1RDYC_POS) +#define STM32_RCC_CICR_PLLSAI1RDYC STM32_RCC_CICR_PLLSAI1RDYC_MSK +#define STM32_RCC_CICR_PLLSAI2RDYC_POS 7U +#define STM32_RCC_CICR_PLLSAI2RDYC_MSK (0x1UL << STM32_RCC_CICR_PLLSAI2RDYC_POS) +#define STM32_RCC_CICR_PLLSAI2RDYC STM32_RCC_CICR_PLLSAI2RDYC_MSK +#define STM32_RCC_CICR_CSSC_POS 8U +#define STM32_RCC_CICR_CSSC_MSK (0x1UL << STM32_RCC_CICR_CSSC_POS) +#define STM32_RCC_CICR_CSSC STM32_RCC_CICR_CSSC_MSK +#define STM32_RCC_CICR_HSI48RDYC_POS 10U +#define STM32_RCC_CICR_HSI48RDYC_MSK (0x1UL << STM32_RCC_CICR_HSI48RDYC_POS) +#define STM32_RCC_CICR_HSI48RDYC STM32_RCC_CICR_HSI48RDYC_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB1RSTR REGISTER **************/ +#define STM32_RCC_AHB1RSTR_DMA1RST_POS 0U +#define STM32_RCC_AHB1RSTR_DMA1RST_MSK (0x1UL << STM32_RCC_AHB1RSTR_DMA1RST_POS) +#define STM32_RCC_AHB1RSTR_DMA1RST STM32_RCC_AHB1RSTR_DMA1RST_MSK +#define STM32_RCC_AHB1RSTR_DMA2RST_POS 1U +#define STM32_RCC_AHB1RSTR_DMA2RST_MSK (0x1UL << STM32_RCC_AHB1RSTR_DMA2RST_POS) +#define STM32_RCC_AHB1RSTR_DMA2RST STM32_RCC_AHB1RSTR_DMA2RST_MSK +#define STM32_RCC_AHB1RSTR_DMAMUX1RST_POS 2U +#define STM32_RCC_AHB1RSTR_DMAMUX1RST_MSK \ + (0x1UL << STM32_RCC_AHB1RSTR_DMAMUX1RST_POS) +#define STM32_RCC_AHB1RSTR_DMAMUX1RST STM32_RCC_AHB1RSTR_DMAMUX1RST_MSK +#define STM32_RCC_AHB1RSTR_FLASHRST_POS 8U +#define STM32_RCC_AHB1RSTR_FLASHRST_MSK \ + (0x1UL << STM32_RCC_AHB1RSTR_FLASHRST_POS) +#define STM32_RCC_AHB1RSTR_FLASHRST STM32_RCC_AHB1RSTR_FLASHRST_MSK +#define STM32_RCC_AHB1RSTR_CRCRST_POS 12U +#define STM32_RCC_AHB1RSTR_CRCRST_MSK (0x1UL << STM32_RCC_AHB1RSTR_CRCRST_POS) +#define STM32_RCC_AHB1RSTR_CRCRST STM32_RCC_AHB1RSTR_CRCRST_MSK +#define STM32_RCC_AHB1RSTR_TSCRST_POS 16U +#define STM32_RCC_AHB1RSTR_TSCRST_MSK (0x1UL << STM32_RCC_AHB1RSTR_TSCRST_POS) +#define STM32_RCC_AHB1RSTR_TSCRST STM32_RCC_AHB1RSTR_TSCRST_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB2RSTR REGISTER **************/ +#define STM32_RCC_AHB2RSTR_GPIOARST_POS 0U +#define STM32_RCC_AHB2RSTR_GPIOARST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOARST_POS) +#define STM32_RCC_AHB2RSTR_GPIOARST STM32_RCC_AHB2RSTR_GPIOARST_MSK +#define STM32_RCC_AHB2RSTR_GPIOBRST_POS 1U +#define STM32_RCC_AHB2RSTR_GPIOBRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOBRST_POS) +#define STM32_RCC_AHB2RSTR_GPIOBRST STM32_RCC_AHB2RSTR_GPIOBRST_MSK +#define STM32_RCC_AHB2RSTR_GPIOCRST_POS 2U +#define STM32_RCC_AHB2RSTR_GPIOCRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOCRST_POS) +#define STM32_RCC_AHB2RSTR_GPIOCRST STM32_RCC_AHB2RSTR_GPIOCRST_MSK +#define STM32_RCC_AHB2RSTR_GPIODRST_POS 3U +#define STM32_RCC_AHB2RSTR_GPIODRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIODRST_POS) +#define STM32_RCC_AHB2RSTR_GPIODRST STM32_RCC_AHB2RSTR_GPIODRST_MSK +#define STM32_RCC_AHB2RSTR_GPIOERST_POS 4U +#define STM32_RCC_AHB2RSTR_GPIOERST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOERST_POS) +#define STM32_RCC_AHB2RSTR_GPIOERST STM32_RCC_AHB2RSTR_GPIOERST_MSK +#define STM32_RCC_AHB2RSTR_GPIOFRST_POS 5U +#define STM32_RCC_AHB2RSTR_GPIOFRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOFRST_POS) +#define STM32_RCC_AHB2RSTR_GPIOFRST STM32_RCC_AHB2RSTR_GPIOFRST_MSK +#define STM32_RCC_AHB2RSTR_GPIOGRST_POS 6U +#define STM32_RCC_AHB2RSTR_GPIOGRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOGRST_POS) +#define STM32_RCC_AHB2RSTR_GPIOGRST STM32_RCC_AHB2RSTR_GPIOGRST_MSK +#define STM32_RCC_AHB2RSTR_GPIOHRST_POS 7U +#define STM32_RCC_AHB2RSTR_GPIOHRST_MSK \ + (0x1UL << STM32_RCC_AHB2RSTR_GPIOHRST_POS) +#define STM32_RCC_AHB2RSTR_GPIOHRST STM32_RCC_AHB2RSTR_GPIOHRST_MSK +#define STM32_RCC_AHB2RSTR_ADCRST_POS 13U +#define STM32_RCC_AHB2RSTR_ADCRST_MSK (0x1UL << STM32_RCC_AHB2RSTR_ADCRST_POS) +#define STM32_RCC_AHB2RSTR_ADCRST STM32_RCC_AHB2RSTR_ADCRST_MSK +#define STM32_RCC_AHB2RSTR_AESRST_POS 16U +#define STM32_RCC_AHB2RSTR_AESRST_MSK (0x1UL << STM32_RCC_AHB2RSTR_AESRST_POS) +#define STM32_RCC_AHB2RSTR_AESRST STM32_RCC_AHB2RSTR_AESRST_MSK +#define STM32_RCC_AHB2RSTR_HASHRST_POS 17U +#define STM32_RCC_AHB2RSTR_HASHRST_MSK (0x1UL << STM32_RCC_AHB2RSTR_HASHRST_POS) +#define STM32_RCC_AHB2RSTR_HASHRST STM32_RCC_AHB2RSTR_HASHRST_MSK +#define STM32_RCC_AHB2RSTR_RNGRST_POS 18U +#define STM32_RCC_AHB2RSTR_RNGRST_MSK (0x1UL << STM32_RCC_AHB2RSTR_RNGRST_POS) +#define STM32_RCC_AHB2RSTR_RNGRST STM32_RCC_AHB2RSTR_RNGRST_MSK + +/************* BIT DEFINITION FOR STM32_RCC_AHB3RSTR REGISTER **************/ +#define STM32_RCC_AHB3RSTR_FMCRST_POS 0U +#define STM32_RCC_AHB3RSTR_FMCRST_MSK (0x1UL << STM32_RCC_AHB3RSTR_FMCRST_POS) +#define STM32_RCC_AHB3RSTR_FMCRST STM32_RCC_AHB3RSTR_FMCRST_MSK +#define STM32_RCC_AHB3RSTR_QSPIRST_POS 8U +#define STM32_RCC_AHB3RSTR_QSPIRST_MSK (0x1UL << STM32_RCC_AHB3RSTR_QSPIRST_POS) +#define STM32_RCC_AHB3RSTR_QSPIRST STM32_RCC_AHB3RSTR_QSPIRST_MSK + +/************* BIT DEFINITION FOR STM32_RCC_APB1RSTR1 REGISTER **************/ +#define STM32_RCC_APB1RSTR1_TIM2RST_POS 0U +#define STM32_RCC_APB1RSTR1_TIM2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_TIM2RST_POS) +#define STM32_RCC_APB1RSTR1_TIM2RST STM32_RCC_APB1RSTR1_TIM2RST_MSK +#define STM32_RCC_APB1RSTR1_TIM3RST_POS 1U +#define STM32_RCC_APB1RSTR1_TIM3RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_TIM3RST_POS) +#define STM32_RCC_APB1RSTR1_TIM3RST STM32_RCC_APB1RSTR1_TIM3RST_MSK +#define STM32_RCC_APB1RSTR1_TIM4RST_POS 2U +#define STM32_RCC_APB1RSTR1_TIM4RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_TIM4RST_POS) +#define STM32_RCC_APB1RSTR1_TIM4RST STM32_RCC_APB1RSTR1_TIM4RST_MSK +#define STM32_RCC_APB1RSTR1_TIM5RST_POS 3U +#define STM32_RCC_APB1RSTR1_TIM5RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_TIM5RST_POS) +#define STM32_RCC_APB1RSTR1_TIM5RST STM32_RCC_APB1RSTR1_TIM5RST_MSK +#define STM32_RCC_APB1RSTR1_TIM6RST_POS 4U +#define STM32_RCC_APB1RSTR1_TIM6RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_TIM6RST_POS) +#define STM32_RCC_APB1RSTR1_TIM6RST STM32_RCC_APB1RSTR1_TIM6RST_MSK +#define STM32_RCC_APB1RSTR1_TIM7RST_POS 5U +#define STM32_RCC_APB1RSTR1_TIM7RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_TIM7RST_POS) +#define STM32_RCC_APB1RSTR1_TIM7RST STM32_RCC_APB1RSTR1_TIM7RST_MSK +#define STM32_RCC_APB1RSTR1_SPI2RST_POS 14U +#define STM32_RCC_APB1RSTR1_SPI2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_SPI2RST_POS) +#define STM32_RCC_APB1RSTR1_SPI2RST STM32_RCC_APB1RSTR1_SPI2RST_MSK +#define STM32_RCC_APB1RSTR1_SPI3RST_POS 15U +#define STM32_RCC_APB1RSTR1_SPI3RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_SPI3RST_POS) +#define STM32_RCC_APB1RSTR1_SPI3RST STM32_RCC_APB1RSTR1_SPI3RST_MSK +#define STM32_RCC_APB1RSTR1_USART2RST_POS 17U +#define STM32_RCC_APB1RSTR1_USART2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_USART2RST_POS) +#define STM32_RCC_APB1RSTR1_USART2RST STM32_RCC_APB1RSTR1_USART2RST_MSK +#define STM32_RCC_APB1RSTR1_USART3RST_POS 18U +#define STM32_RCC_APB1RSTR1_USART3RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_USART3RST_POS) +#define STM32_RCC_APB1RSTR1_USART3RST STM32_RCC_APB1RSTR1_USART3RST_MSK +#define STM32_RCC_APB1RSTR1_USART4RST_POS 19U +#define STM32_RCC_APB1RSTR1_USART4RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_USART4RST_POS) +#define STM32_RCC_APB1RSTR1_USART4RST STM32_RCC_APB1RSTR1_USART4RST_MSK +#define STM32_RCC_APB1RSTR1_USART5RST_POS 20U +#define STM32_RCC_APB1RSTR1_USART5RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_USART5RST_POS) +#define STM32_RCC_APB1RSTR1_USART5RST STM32_RCC_APB1RSTR1_USART5RST_MSK +#define STM32_RCC_APB1RSTR1_I2C1RST_POS 21U +#define STM32_RCC_APB1RSTR1_I2C1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_I2C1RST_POS) +#define STM32_RCC_APB1RSTR1_I2C1RST STM32_RCC_APB1RSTR1_I2C1RST_MSK +#define STM32_RCC_APB1RSTR1_I2C2RST_POS 22U +#define STM32_RCC_APB1RSTR1_I2C2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_I2C2RST_POS) +#define STM32_RCC_APB1RSTR1_I2C2RST STM32_RCC_APB1RSTR1_I2C2RST_MSK +#define STM32_RCC_APB1RSTR1_I2C3RST_POS 23U +#define STM32_RCC_APB1RSTR1_I2C3RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_I2C3RST_POS) +#define STM32_RCC_APB1RSTR1_I2C3RST STM32_RCC_APB1RSTR1_I2C3RST_MSK +#define STM32_RCC_APB1RSTR1_CRSRST_POS 24U +#define STM32_RCC_APB1RSTR1_CRSRST_MSK (0x1UL << STM32_RCC_APB1RSTR1_CRSRST_POS) +#define STM32_RCC_APB1RSTR1_CRSRST STM32_RCC_APB1RSTR1_CRSRST_MSK +#define STM32_RCC_APB1RSTR1_PWRRST_POS 28U +#define STM32_RCC_APB1RSTR1_PWRRST_MSK (0x1UL << STM32_RCC_APB1RSTR1_PWRRST_POS) +#define STM32_RCC_APB1RSTR1_PWRRST STM32_RCC_APB1RSTR1_PWRRST_MSK +#define STM32_RCC_APB1RSTR1_DAC1RST_POS 29U +#define STM32_RCC_APB1RSTR1_DAC1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_DAC1RST_POS) +#define STM32_RCC_APB1RSTR1_DAC1RST STM32_RCC_APB1RSTR1_DAC1RST_MSK +#define STM32_RCC_APB1RSTR1_OPAMPRST_POS 30U +#define STM32_RCC_APB1RSTR1_OPAMPRST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_OPAMPRST_POS) +#define STM32_RCC_APB1RSTR1_OPAMPRST STM32_RCC_APB1RSTR1_OPAMPRST_MSK +#define STM32_RCC_APB1RSTR1_LPTIM1RST_POS 31U +#define STM32_RCC_APB1RSTR1_LPTIM1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR1_LPTIM1RST_POS) +#define STM32_RCC_APB1RSTR1_LPTIM1RST STM32_RCC_APB1RSTR1_LPTIM1RST_MSK + +/************* BIT DEFINITION FOR STM32_RCC_APB1RSTR2 REGISTER **************/ +#define STM32_RCC_APB1RSTR2_LPUART1RST_POS 0U +#define STM32_RCC_APB1RSTR2_LPUART1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_LPUART1RST_POS) +#define STM32_RCC_APB1RSTR2_LPUART1RST STM32_RCC_APB1RSTR2_LPUART1RST_MSK +#define STM32_RCC_APB1RSTR2_I2C4RST_POS 1U +#define STM32_RCC_APB1RSTR2_I2C4RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_I2C4RST_POS) +#define STM32_RCC_APB1RSTR2_I2C4RST STM32_RCC_APB1RSTR2_I2C4RST_MSK +#define STM32_RCC_APB1RSTR2_LPTIM2RST_POS 5U +#define STM32_RCC_APB1RSTR2_LPTIM2RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_LPTIM2RST_POS) +#define STM32_RCC_APB1RSTR2_LPTIM2RST STM32_RCC_APB1RSTR2_LPTIM2RST_MSK +#define STM32_RCC_APB1RSTR2_LPTIM3RST_POS 6U +#define STM32_RCC_APB1RSTR2_LPTIM3RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_LPTIM3RST_POS) +#define STM32_RCC_APB1RSTR2_LPTIM3RST STM32_RCC_APB1RSTR2_LPTIM3RST_MSK +#define STM32_RCC_APB1RSTR2_FDCAN1RST_POS 9U +#define STM32_RCC_APB1RSTR2_FDCAN1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_FDCAN1RST_POS) +#define STM32_RCC_APB1RSTR2_FDCAN1RST STM32_RCC_APB1RSTR2_FDCAN1RST_MSK +#define STM32_RCC_APB1RSTR2_USBFSRST_POS 21U +#define STM32_RCC_APB1RSTR2_USBFSRST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_USBFSRST_POS) +#define STM32_RCC_APB1RSTR2_USBFSRST STM32_RCC_APB1RSTR2_USBFSRST_MSK +#define STM32_RCC_APB1RSTR2_UCPD1RST_POS 23U +#define STM32_RCC_APB1RSTR2_UCPD1RST_MSK \ + (0x1UL << STM32_RCC_APB1RSTR2_UCPD1RST_POS) +#define STM32_RCC_APB1RSTR2_UCPD1RST STM32_RCC_APB1RSTR2_UCPD1RST_MSK + +/************** BIT DEFINITION FOR STM32_RCC_APB2RSTR REGISTER **************/ +#define STM32_RCC_APB2RSTR_SYSCFGRST_POS 0U +#define STM32_RCC_APB2RSTR_SYSCFGRST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_SYSCFGRST_POS) +#define STM32_RCC_APB2RSTR_SYSCFGRST STM32_RCC_APB2RSTR_SYSCFGRST_MSK +#define STM32_RCC_APB2RSTR_TIM1RST_POS 11U +#define STM32_RCC_APB2RSTR_TIM1RST_MSK (0x1UL << STM32_RCC_APB2RSTR_TIM1RST_POS) +#define STM32_RCC_APB2RSTR_TIM1RST STM32_RCC_APB2RSTR_TIM1RST_MSK +#define STM32_RCC_APB2RSTR_SPI1RST_POS 12U +#define STM32_RCC_APB2RSTR_SPI1RST_MSK (0x1UL << STM32_RCC_APB2RSTR_SPI1RST_POS) +#define STM32_RCC_APB2RSTR_SPI1RST STM32_RCC_APB2RSTR_SPI1RST_MSK +#define STM32_RCC_APB2RSTR_TIM8RST_POS 13U +#define STM32_RCC_APB2RSTR_TIM8RST_MSK (0x1UL << STM32_RCC_APB2RSTR_TIM8RST_POS) +#define STM32_RCC_APB2RSTR_TIM8RST STM32_RCC_APB2RSTR_TIM8RST_MSK +#define STM32_RCC_APB2RSTR_USART1RST_POS 14U +#define STM32_RCC_APB2RSTR_USART1RST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_USART1RST_POS) +#define STM32_RCC_APB2RSTR_USART1RST STM32_RCC_APB2RSTR_USART1RST_MSK +#define STM32_RCC_APB2RSTR_TIM15RST_POS 16U +#define STM32_RCC_APB2RSTR_TIM15RST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_TIM15RST_POS) +#define STM32_RCC_APB2RSTR_TIM15RST STM32_RCC_APB2RSTR_TIM15RST_MSK +#define STM32_RCC_APB2RSTR_TIM16RST_POS 17U +#define STM32_RCC_APB2RSTR_TIM16RST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_TIM16RST_POS) +#define STM32_RCC_APB2RSTR_TIM16RST STM32_RCC_APB2RSTR_TIM16RST_MSK +#define STM32_RCC_APB2RSTR_TIM17RST_POS 18U +#define STM32_RCC_APB2RSTR_TIM17RST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_TIM17RST_POS) +#define STM32_RCC_APB2RSTR_TIM17RST STM32_RCC_APB2RSTR_TIM17RST_MSK +#define STM32_RCC_APB2RSTR_SAI1RST_POS 21U +#define STM32_RCC_APB2RSTR_SAI1RST_MSK (0x1UL << STM32_RCC_APB2RSTR_SAI1RST_POS) +#define STM32_RCC_APB2RSTR_SAI1RST STM32_RCC_APB2RSTR_SAI1RST_MSK +#define STM32_RCC_APB2RSTR_SAI2RST_POS 22U +#define STM32_RCC_APB2RSTR_SAI2RST_MSK (0x1UL << STM32_RCC_APB2RSTR_SAI2RST_POS) +#define STM32_RCC_APB2RSTR_SAI2RST STM32_RCC_APB2RSTR_SAI2RST_MSK +#define STM32_RCC_APB2RSTR_DFSDM1RST_POS 24U +#define STM32_RCC_APB2RSTR_DFSDM1RST_MSK \ + (0x1UL << STM32_RCC_APB2RSTR_DFSDM1RST_POS) +#define STM32_RCC_APB2RSTR_DFSDM1RST STM32_RCC_APB2RSTR_DFSDM1RST_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB1ENR REGISTER ***************/ +#define STM32_RCC_AHB1ENR_DMA1EN_POS 0U +#define STM32_RCC_AHB1ENR_DMA1EN_MSK (0x1UL << STM32_RCC_AHB1ENR_DMA1EN_POS) +#define STM32_RCC_AHB1ENR_DMA1EN STM32_RCC_AHB1ENR_DMA1EN_MSK +#define STM32_RCC_AHB1ENR_DMA2EN_POS 1U +#define STM32_RCC_AHB1ENR_DMA2EN_MSK (0x1UL << STM32_RCC_AHB1ENR_DMA2EN_POS) +#define STM32_RCC_AHB1ENR_DMA2EN STM32_RCC_AHB1ENR_DMA2EN_MSK +#define STM32_RCC_AHB1ENR_DMAMUX1EN_POS 2U +#define STM32_RCC_AHB1ENR_DMAMUX1EN_MSK \ + (0x1UL << STM32_RCC_AHB1ENR_DMAMUX1EN_POS) +#define STM32_RCC_AHB1ENR_DMAMUX1EN STM32_RCC_AHB1ENR_DMAMUX1EN_MSK +#define STM32_RCC_AHB1ENR_DMAMUXEN STM32_RCC_AHB1ENR_DMAMUX1EN_MSK +#define STM32_RCC_AHB1ENR_FLASHEN_POS 8U +#define STM32_RCC_AHB1ENR_FLASHEN_MSK (0x1UL << STM32_RCC_AHB1ENR_FLASHEN_POS) +#define STM32_RCC_AHB1ENR_FLASHEN STM32_RCC_AHB1ENR_FLASHEN_MSK +#define STM32_RCC_AHB1ENR_CRCEN_POS 12U +#define STM32_RCC_AHB1ENR_CRCEN_MSK (0x1UL << STM32_RCC_AHB1ENR_CRCEN_POS) +#define STM32_RCC_AHB1ENR_CRCEN STM32_RCC_AHB1ENR_CRCEN_MSK +#define STM32_RCC_AHB1ENR_TSCEN_POS 16U +#define STM32_RCC_AHB1ENR_TSCEN_MSK (0x1UL << STM32_RCC_AHB1ENR_TSCEN_POS) +#define STM32_RCC_AHB1ENR_TSCEN STM32_RCC_AHB1ENR_TSCEN_MSK +#define STM32_RCC_AHB1ENR_GTZCEN_POS 22U +#define STM32_RCC_AHB1ENR_GTZCEN_MSK (0x1UL << STM32_RCC_AHB1ENR_GTZCEN_POS) +#define STM32_RCC_AHB1ENR_GTZCEN STM32_RCC_AHB1ENR_GTZCEN_MSK + +/*************** BIT DEFINITION FOR STM32_RCC_AHB2ENR REGISTER *********/ +#define STM32_RCC_AHB2ENR_GPIOAEN_POS 0U +#define STM32_RCC_AHB2ENR_GPIOAEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOAEN_POS) +#define STM32_RCC_AHB2ENR_GPIOAEN STM32_RCC_AHB2ENR_GPIOAEN_MSK +#define STM32_RCC_AHB2ENR_GPIOBEN_POS 1U +#define STM32_RCC_AHB2ENR_GPIOBEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOBEN_POS) +#define STM32_RCC_AHB2ENR_GPIOBEN STM32_RCC_AHB2ENR_GPIOBEN_MSK +#define STM32_RCC_AHB2ENR_GPIOCEN_POS 2U +#define STM32_RCC_AHB2ENR_GPIOCEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOCEN_POS) +#define STM32_RCC_AHB2ENR_GPIOCEN STM32_RCC_AHB2ENR_GPIOCEN_MSK +#define STM32_RCC_AHB2ENR_GPIODEN_POS 3U +#define STM32_RCC_AHB2ENR_GPIODEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIODEN_POS) +#define STM32_RCC_AHB2ENR_GPIODEN STM32_RCC_AHB2ENR_GPIODEN_MSK +#define STM32_RCC_AHB2ENR_GPIOEEN_POS 4U +#define STM32_RCC_AHB2ENR_GPIOEEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOEEN_POS) +#define STM32_RCC_AHB2ENR_GPIOEEN STM32_RCC_AHB2ENR_GPIOEEN_MSK +#define STM32_RCC_AHB2ENR_GPIOFEN_POS 5U +#define STM32_RCC_AHB2ENR_GPIOFEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOFEN_POS) +#define STM32_RCC_AHB2ENR_GPIOFEN STM32_RCC_AHB2ENR_GPIOFEN_MSK +#define STM32_RCC_AHB2ENR_GPIOGEN_POS 6U +#define STM32_RCC_AHB2ENR_GPIOGEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOGEN_POS) +#define STM32_RCC_AHB2ENR_GPIOGEN STM32_RCC_AHB2ENR_GPIOGEN_MSK +#define STM32_RCC_AHB2ENR_GPIOHEN_POS 7U +#define STM32_RCC_AHB2ENR_GPIOHEN_MSK (0x1UL << STM32_RCC_AHB2ENR_GPIOHEN_POS) +#define STM32_RCC_AHB2ENR_GPIOHEN STM32_RCC_AHB2ENR_GPIOHEN_MSK +#define STM32_RCC_AHB2ENR_ADCEN_POS 13U +#define STM32_RCC_AHB2ENR_ADCEN_MSK (0x1UL << STM32_RCC_AHB2ENR_ADCEN_POS) +#define STM32_RCC_AHB2ENR_ADCEN STM32_RCC_AHB2ENR_ADCEN_MSK +#define STM32_RCC_AHB2ENR_AESEN_POS 16U +#define STM32_RCC_AHB2ENR_AESEN_MSK (0x1UL << STM32_RCC_AHB2ENR_AESEN_POS) +#define STM32_RCC_AHB2ENR_AESEN STM32_RCC_AHB2ENR_AESEN_MSK +#define STM32_RCC_AHB2ENR_HASHEN_POS 17U +#define STM32_RCC_AHB2ENR_HASHEN_MSK (0x1UL << STM32_RCC_AHB2ENR_HASHEN_POS) +#define STM32_RCC_AHB2ENR_HASHEN STM32_RCC_AHB2ENR_HASHEN_MSK +#define STM32_RCC_AHB2ENR_RNGEN_POS 18U +#define STM32_RCC_AHB2ENR_RNGEN_MSK (0x1UL << STM32_RCC_AHB2ENR_RNGEN_POS) +#define STM32_RCC_AHB2ENR_RNGEN STM32_RCC_AHB2ENR_RNGEN_MSK +#define STM32_RCC_AHB2ENR_PKAEN_POS 19U +#define STM32_RCC_AHB2ENR_PKAEN_MSK (0x1UL << STM32_RCC_AHB2ENR_PKAEN_POS) +#define STM32_RCC_AHB2ENR_PKAEN STM32_RCC_AHB2ENR_PKAEN_MSK +#define STM32_RCC_AHB2ENR_OTFDEC1EN_POS 21U +#define STM32_RCC_AHB2ENR_OTFDEC1EN_MSK \ + (0x1UL << STM32_RCC_AHB2ENR_OTFDEC1EN_POS) +#define STM32_RCC_AHB2ENR_OTFDEC1EN STM32_RCC_AHB2ENR_OTFDEC1EN_MSK +#define STM32_RCC_AHB2ENR_SDMMC1EN_POS 22U +#define STM32_RCC_AHB2ENR_SDMMC1EN_MSK (0x1UL << STM32_RCC_AHB2ENR_SDMMC1EN_POS) +#define STM32_RCC_AHB2ENR_SDMMC1EN STM32_RCC_AHB2ENR_SDMMC1EN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB3ENR REGISTER ***************/ +#define STM32_RCC_AHB3ENR_FMCEN_POS 0U +#define STM32_RCC_AHB3ENR_FMCEN_MSK (0x1UL << STM32_RCC_AHB3ENR_FMCEN_POS) +#define STM32_RCC_AHB3ENR_FMCEN STM32_RCC_AHB3ENR_FMCEN_MSK +#define STM32_RCC_AHB3ENR_QSPIEN_POS 8U +#define STM32_RCC_AHB3ENR_QSPIEN_MSK (0x1UL << STM32_RCC_AHB3ENR_QSPIEN_POS) +#define STM32_RCC_AHB3ENR_QSPIEN STM32_RCC_AHB3ENR_QSPIEN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_APB1ENR1 REGISTER **************/ +#define STM32_RCC_APB1ENR1_TIM2EN_POS 0U +#define STM32_RCC_APB1ENR1_TIM2EN_MSK (0x1UL << STM32_RCC_APB1ENR1_TIM2EN_POS) +#define STM32_RCC_APB1ENR1_TIM2EN STM32_RCC_APB1ENR1_TIM2EN_MSK +#define STM32_RCC_APB1ENR1_TIM3EN_POS 1U +#define STM32_RCC_APB1ENR1_TIM3EN_MSK (0x1UL << STM32_RCC_APB1ENR1_TIM3EN_POS) +#define STM32_RCC_APB1ENR1_TIM3EN STM32_RCC_APB1ENR1_TIM3EN_MSK +#define STM32_RCC_APB1ENR1_TIM4EN_POS 2U +#define STM32_RCC_APB1ENR1_TIM4EN_MSK (0x1UL << STM32_RCC_APB1ENR1_TIM4EN_POS) +#define STM32_RCC_APB1ENR1_TIM4EN STM32_RCC_APB1ENR1_TIM4EN_MSK +#define STM32_RCC_APB1ENR1_TIM5EN_POS 3U +#define STM32_RCC_APB1ENR1_TIM5EN_MSK (0x1UL << STM32_RCC_APB1ENR1_TIM5EN_POS) +#define STM32_RCC_APB1ENR1_TIM5EN STM32_RCC_APB1ENR1_TIM5EN_MSK +#define STM32_RCC_APB1ENR1_TIM6EN_POS 4U +#define STM32_RCC_APB1ENR1_TIM6EN_MSK (0x1UL << STM32_RCC_APB1ENR1_TIM6EN_POS) +#define STM32_RCC_APB1ENR1_TIM6EN STM32_RCC_APB1ENR1_TIM6EN_MSK +#define STM32_RCC_APB1ENR1_TIM7EN_POS 5U +#define STM32_RCC_APB1ENR1_TIM7EN_MSK (0x1UL << STM32_RCC_APB1ENR1_TIM7EN_POS) +#define STM32_RCC_APB1ENR1_TIM7EN STM32_RCC_APB1ENR1_TIM7EN_MSK +#define STM32_RCC_APB1ENR1_RTCAPBEN_POS 10U +#define STM32_RCC_APB1ENR1_RTCAPBEN_MSK \ + (0x1UL << STM32_RCC_APB1ENR1_RTCAPBEN_POS) +#define STM32_RCC_APB1ENR1_RTCAPBEN STM32_RCC_APB1ENR1_RTCAPBEN_MSK +#define STM32_RCC_APB1ENR1_WWDGEN_POS 11U +#define STM32_RCC_APB1ENR1_WWDGEN_MSK (0x1UL << STM32_RCC_APB1ENR1_WWDGEN_POS) +#define STM32_RCC_APB1ENR1_WWDGEN STM32_RCC_APB1ENR1_WWDGEN_MSK +#define STM32_RCC_APB1ENR1_SPI2EN_POS 14U +#define STM32_RCC_APB1ENR1_SPI2EN_MSK (0x1UL << STM32_RCC_APB1ENR1_SPI2EN_POS) +#define STM32_RCC_APB1ENR1_SPI2EN STM32_RCC_APB1ENR1_SPI2EN_MSK +#define STM32_RCC_APB1ENR1_SPI3EN_POS 15U +#define STM32_RCC_APB1ENR1_SPI3EN_MSK (0x1UL << STM32_RCC_APB1ENR1_SPI3EN_POS) +#define STM32_RCC_APB1ENR1_SPI3EN STM32_RCC_APB1ENR1_SPI3EN_MSK +#define STM32_RCC_APB1ENR1_USART2EN_POS 17U +#define STM32_RCC_APB1ENR1_USART2EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR1_USART2EN_POS) +#define STM32_RCC_APB1ENR1_USART2EN STM32_RCC_APB1ENR1_USART2EN_MSK +#define STM32_RCC_APB1ENR1_USART3EN_POS 18U +#define STM32_RCC_APB1ENR1_USART3EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR1_USART3EN_POS) +#define STM32_RCC_APB1ENR1_USART3EN STM32_RCC_APB1ENR1_USART3EN_MSK +#define STM32_RCC_APB1ENR1_UART4EN_POS 19U +#define STM32_RCC_APB1ENR1_UART4EN_MSK (0x1UL << STM32_RCC_APB1ENR1_UART4EN_POS) +#define STM32_RCC_APB1ENR1_UART4EN STM32_RCC_APB1ENR1_UART4EN_MSK +#define STM32_RCC_APB1ENR1_UART5EN_POS 20U +#define STM32_RCC_APB1ENR1_UART5EN_MSK (0x1UL << STM32_RCC_APB1ENR1_UART5EN_POS) +#define STM32_RCC_APB1ENR1_UART5EN STM32_RCC_APB1ENR1_UART5EN_MSK +#define STM32_RCC_APB1ENR1_I2C1EN_POS 21U +#define STM32_RCC_APB1ENR1_I2C1EN_MSK (0x1UL << STM32_RCC_APB1ENR1_I2C1EN_POS) +#define STM32_RCC_APB1ENR1_I2C1EN STM32_RCC_APB1ENR1_I2C1EN_MSK +#define STM32_RCC_APB1ENR1_I2C2EN_POS 22U +#define STM32_RCC_APB1ENR1_I2C2EN_MSK (0x1UL << STM32_RCC_APB1ENR1_I2C2EN_POS) +#define STM32_RCC_APB1ENR1_I2C2EN STM32_RCC_APB1ENR1_I2C2EN_MSK +#define STM32_RCC_APB1ENR1_I2C3EN_POS 23U +#define STM32_RCC_APB1ENR1_I2C3EN_MSK (0x1UL << STM32_RCC_APB1ENR1_I2C3EN_POS) +#define STM32_RCC_APB1ENR1_I2C3EN STM32_RCC_APB1ENR1_I2C3EN_MSK +#define STM32_RCC_APB1ENR1_CRSEN_POS 24U +#define STM32_RCC_APB1ENR1_CRSEN_MSK (0x1UL << STM32_RCC_APB1ENR1_CRSEN_POS) +#define STM32_RCC_APB1ENR1_CRSEN STM32_RCC_APB1ENR1_CRSEN_MSK +#define STM32_RCC_APB1ENR1_PWREN_POS 28U +#define STM32_RCC_APB1ENR1_PWREN_MSK (0x1UL << STM32_RCC_APB1ENR1_PWREN_POS) +#define STM32_RCC_APB1ENR1_PWREN STM32_RCC_APB1ENR1_PWREN_MSK +#define STM32_RCC_APB1ENR1_DAC1EN_POS 29U +#define STM32_RCC_APB1ENR1_DAC1EN_MSK (0x1UL << STM32_RCC_APB1ENR1_DAC1EN_POS) +#define STM32_RCC_APB1ENR1_DAC1EN STM32_RCC_APB1ENR1_DAC1EN_MSK +#define STM32_RCC_APB1ENR1_OPAMPEN_POS 30U +#define STM32_RCC_APB1ENR1_OPAMPEN_MSK (0x1UL << STM32_RCC_APB1ENR1_OPAMPEN_POS) +#define STM32_RCC_APB1ENR1_OPAMPEN STM32_RCC_APB1ENR1_OPAMPEN_MSK +#define STM32_RCC_APB1ENR1_LPTIM1EN_POS 31U +#define STM32_RCC_APB1ENR1_LPTIM1EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR1_LPTIM1EN_POS) +#define STM32_RCC_APB1ENR1_LPTIM1EN STM32_RCC_APB1ENR1_LPTIM1EN_MSK + +/************ BIT DEFINITION FOR STM32_RCC_APB1RSTR2 REGISTER **************/ +#define STM32_RCC_APB1ENR2_LPUART1EN_POS 0U +#define STM32_RCC_APB1ENR2_LPUART1EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR2_LPUART1EN_POS) +#define STM32_RCC_APB1ENR2_LPUART1EN STM32_RCC_APB1ENR2_LPUART1EN_MSK +#define STM32_RCC_APB1ENR2_I2C4EN_POS 1U +#define STM32_RCC_APB1ENR2_I2C4EN_MSK (0x1UL << STM32_RCC_APB1ENR2_I2C4EN_POS) +#define STM32_RCC_APB1ENR2_I2C4EN STM32_RCC_APB1ENR2_I2C4EN_MSK +#define STM32_RCC_APB1ENR2_LPTIM2EN_POS 5U +#define STM32_RCC_APB1ENR2_LPTIM2EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR2_LPTIM2EN_POS) +#define STM32_RCC_APB1ENR2_LPTIM2EN STM32_RCC_APB1ENR2_LPTIM2EN_MSK +#define STM32_RCC_APB1ENR2_LPTIM3EN_POS 6U +#define STM32_RCC_APB1ENR2_LPTIM3EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR2_LPTIM3EN_POS) +#define STM32_RCC_APB1ENR2_LPTIM3EN STM32_RCC_APB1ENR2_LPTIM3EN_MSK +#define STM32_RCC_APB1ENR2_FDCAN1EN_POS 9U +#define STM32_RCC_APB1ENR2_FDCAN1EN_MSK \ + (0x1UL << STM32_RCC_APB1ENR2_FDCAN1EN_POS) +#define STM32_RCC_APB1ENR2_FDCAN1EN STM32_RCC_APB1ENR2_FDCAN1EN_MSK +#define STM32_RCC_APB1ENR2_USBFSEN_POS 21U +#define STM32_RCC_APB1ENR2_USBFSEN_MSK (0x1UL << STM32_RCC_APB1ENR2_USBFSEN_POS) +#define STM32_RCC_APB1ENR2_USBFSEN STM32_RCC_APB1ENR2_USBFSEN_MSK +#define STM32_RCC_APB1ENR2_UCPD1EN_POS 23U +#define STM32_RCC_APB1ENR2_UCPD1EN_MSK (0x1UL << STM32_RCC_APB1ENR2_UCPD1EN_POS) +#define STM32_RCC_APB1ENR2_UCPD1EN STM32_RCC_APB1ENR2_UCPD1EN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_APB2ENR REGISTER ***************/ +#define STM32_RCC_APB2ENR_SYSCFGEN_POS 0U +#define STM32_RCC_APB2ENR_SYSCFGEN_MSK (0x1UL << STM32_RCC_APB2ENR_SYSCFGEN_POS) +#define STM32_RCC_APB2ENR_SYSCFGEN STM32_RCC_APB2ENR_SYSCFGEN_MSK +#define STM32_RCC_APB2ENR_TIM1EN_POS 11U +#define STM32_RCC_APB2ENR_TIM1EN_MSK (0x1UL << STM32_RCC_APB2ENR_TIM1EN_POS) +#define STM32_RCC_APB2ENR_TIM1EN STM32_RCC_APB2ENR_TIM1EN_MSK +#define STM32_RCC_APB2ENR_SPI1EN_POS 12U +#define STM32_RCC_APB2ENR_SPI1EN_MSK (0x1UL << STM32_RCC_APB2ENR_SPI1EN_POS) +#define STM32_RCC_APB2ENR_SPI1EN STM32_RCC_APB2ENR_SPI1EN_MSK +#define STM32_RCC_APB2ENR_TIM8EN_POS 13U +#define STM32_RCC_APB2ENR_TIM8EN_MSK (0x1UL << STM32_RCC_APB2ENR_TIM8EN_POS) +#define STM32_RCC_APB2ENR_TIM8EN STM32_RCC_APB2ENR_TIM8EN_MSK +#define STM32_RCC_APB2ENR_USART1EN_POS 14U +#define STM32_RCC_APB2ENR_USART1EN_MSK (0x1UL << STM32_RCC_APB2ENR_USART1EN_POS) +#define STM32_RCC_APB2ENR_USART1EN STM32_RCC_APB2ENR_USART1EN_MSK +#define STM32_RCC_APB2ENR_TIM15EN_POS 16U +#define STM32_RCC_APB2ENR_TIM15EN_MSK (0x1UL << STM32_RCC_APB2ENR_TIM15EN_POS) +#define STM32_RCC_APB2ENR_TIM15EN STM32_RCC_APB2ENR_TIM15EN_MSK +#define STM32_RCC_APB2ENR_TIM16EN_POS 17U +#define STM32_RCC_APB2ENR_TIM16EN_MSK (0x1UL << STM32_RCC_APB2ENR_TIM16EN_POS) +#define STM32_RCC_APB2ENR_TIM16EN STM32_RCC_APB2ENR_TIM16EN_MSK +#define STM32_RCC_APB2ENR_TIM17EN_POS 18U +#define STM32_RCC_APB2ENR_TIM17EN_MSK (0x1UL << STM32_RCC_APB2ENR_TIM17EN_POS) +#define STM32_RCC_APB2ENR_TIM17EN STM32_RCC_APB2ENR_TIM17EN_MSK +#define STM32_RCC_APB2ENR_SAI1EN_POS 21U +#define STM32_RCC_APB2ENR_SAI1EN_MSK (0x1UL << STM32_RCC_APB2ENR_SAI1EN_POS) +#define STM32_RCC_APB2ENR_SAI1EN STM32_RCC_APB2ENR_SAI1EN_MSK +#define STM32_RCC_APB2ENR_SAI2EN_POS 22U +#define STM32_RCC_APB2ENR_SAI2EN_MSK (0x1UL << STM32_RCC_APB2ENR_SAI2EN_POS) +#define STM32_RCC_APB2ENR_SAI2EN STM32_RCC_APB2ENR_SAI2EN_MSK +#define STM32_RCC_APB2ENR_DFSDM1EN_POS 24U +#define STM32_RCC_APB2ENR_DFSDM1EN_MSK (0x1UL << STM32_RCC_APB2ENR_DFSDM1EN_POS) +#define STM32_RCC_APB2ENR_DFSDM1EN STM32_RCC_APB2ENR_DFSDM1EN_MSK + +/************ BIT DEFINITION FOR STM32_RCC_AHB1SMENR REGISTER ***************/ +#define STM32_RCC_AHB1SMENR_DMA1SMEN_POS 0U +#define STM32_RCC_AHB1SMENR_DMA1SMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_DMA1SMEN_POS) +#define STM32_RCC_AHB1SMENR_DMA1SMEN STM32_RCC_AHB1SMENR_DMA1SMEN_MSK +#define STM32_RCC_AHB1SMENR_DMA2SMEN_POS 1U +#define STM32_RCC_AHB1SMENR_DMA2SMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_DMA2SMEN_POS) +#define STM32_RCC_AHB1SMENR_DMA2SMEN STM32_RCC_AHB1SMENR_DMA2SMEN_MSK +#define STM32_RCC_AHB1SMENR_DMAMUX1SMEN_POS 2U +#define STM32_RCC_AHB1SMENR_DMAMUX1SMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_DMAMUX1SMEN_POS) +#define STM32_RCC_AHB1SMENR_DMAMUX1SMEN STM32_RCC_AHB1SMENR_DMAMUX1SMEN_MSK +#define STM32_RCC_AHB1SMENR_FLASHSMEN_POS 8U +#define STM32_RCC_AHB1SMENR_FLASHSMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_FLASHSMEN_POS) +#define STM32_RCC_AHB1SMENR_FLASHSMEN STM32_RCC_AHB1SMENR_FLASHSMEN_MSK +#define STM32_RCC_AHB1SMENR_SRAM1SMEN_POS 9U +#define STM32_RCC_AHB1SMENR_SRAM1SMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_SRAM1SMEN_POS) +#define STM32_RCC_AHB1SMENR_SRAM1SMEN STM32_RCC_AHB1SMENR_SRAM1SMEN_MSK +#define STM32_RCC_AHB1SMENR_CRCSMEN_POS 12U +#define STM32_RCC_AHB1SMENR_CRCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_CRCSMEN_POS) +#define STM32_RCC_AHB1SMENR_CRCSMEN STM32_RCC_AHB1SMENR_CRCSMEN_MSK +#define STM32_RCC_AHB1SMENR_TSCSMEN_POS 16U +#define STM32_RCC_AHB1SMENR_TSCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_TSCSMEN_POS) +#define STM32_RCC_AHB1SMENR_TSCSMEN STM32_RCC_AHB1SMENR_TSCSMEN_MSK +#define STM32_RCC_AHB1SMENR_GTZCSMEN_POS 22U +#define STM32_RCC_AHB1SMENR_GTZCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_GTZCSMEN_POS) +#define STM32_RCC_AHB1SMENR_GTZCSMEN STM32_RCC_AHB1SMENR_GTZCSMEN_MSK +#define STM32_RCC_AHB1SMENR_ICACHESMEN_POS 23U +#define STM32_RCC_AHB1SMENR_ICACHESMEN_MSK \ + (0x1UL << STM32_RCC_AHB1SMENR_ICACHESMEN_POS) +#define STM32_RCC_AHB1SMENR_ICACHESMEN STM32_RCC_AHB1SMENR_ICACHESMEN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB2SMENR REGISTER *************/ +#define STM32_RCC_AHB2SMENR_GPIOASMEN_POS 0U +#define STM32_RCC_AHB2SMENR_GPIOASMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOASMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOASMEN STM32_RCC_AHB2SMENR_GPIOASMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOBSMEN_POS 1U +#define STM32_RCC_AHB2SMENR_GPIOBSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOBSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOBSMEN STM32_RCC_AHB2SMENR_GPIOBSMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOCSMEN_POS 2U +#define STM32_RCC_AHB2SMENR_GPIOCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOCSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOCSMEN STM32_RCC_AHB2SMENR_GPIOCSMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIODSMEN_POS 3U +#define STM32_RCC_AHB2SMENR_GPIODSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIODSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIODSMEN STM32_RCC_AHB2SMENR_GPIODSMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOESMEN_POS 4U +#define STM32_RCC_AHB2SMENR_GPIOESMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOESMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOESMEN STM32_RCC_AHB2SMENR_GPIOESMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOFSMEN_POS 5U +#define STM32_RCC_AHB2SMENR_GPIOFSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOFSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOFSMEN STM32_RCC_AHB2SMENR_GPIOFSMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOGSMEN_POS 6U +#define STM32_RCC_AHB2SMENR_GPIOGSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOGSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOGSMEN STM32_RCC_AHB2SMENR_GPIOGSMEN_MSK +#define STM32_RCC_AHB2SMENR_GPIOHSMEN_POS 7U +#define STM32_RCC_AHB2SMENR_GPIOHSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_GPIOHSMEN_POS) +#define STM32_RCC_AHB2SMENR_GPIOHSMEN STM32_RCC_AHB2SMENR_GPIOHSMEN_MSK +#define STM32_RCC_AHB2SMENR_SRAM2SMEN_POS 9U +#define STM32_RCC_AHB2SMENR_SRAM2SMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_SRAM2SMEN_POS) +#define STM32_RCC_AHB2SMENR_SRAM2SMEN STM32_RCC_AHB2SMENR_SRAM2SMEN_MSK +#define STM32_RCC_AHB2SMENR_ADCSMEN_POS 13U +#define STM32_RCC_AHB2SMENR_ADCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_ADCSMEN_POS) +#define STM32_RCC_AHB2SMENR_ADCSMEN STM32_RCC_AHB2SMENR_ADCSMEN_MSK +#define STM32_RCC_AHB2SMENR_AESSMEN_POS 16U +#define STM32_RCC_AHB2SMENR_AESSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_AESSMEN_POS) +#define STM32_RCC_AHB2SMENR_AESSMEN STM32_RCC_AHB2SMENR_AESSMEN_MSK +#define STM32_RCC_AHB2SMENR_HASHSMEN_POS 17U +#define STM32_RCC_AHB2SMENR_HASHSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_HASHSMEN_POS) +#define STM32_RCC_AHB2SMENR_HASHSMEN STM32_RCC_AHB2SMENR_HASHSMEN_MSK +#define STM32_RCC_AHB2SMENR_RNGSMEN_POS 18U +#define STM32_RCC_AHB2SMENR_RNGSMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_RNGSMEN_POS) +#define STM32_RCC_AHB2SMENR_RNGSMEN STM32_RCC_AHB2SMENR_RNGSMEN_MSK +#define STM32_RCC_AHB2SMENR_PKASMEN_POS 19U +#define STM32_RCC_AHB2SMENR_PKASMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_PKASMEN_POS) +#define STM32_RCC_AHB2SMENR_PKASMEN STM32_RCC_AHB2SMENR_PKASMEN_MSK +#define STM32_RCC_AHB2SMENR_OTFDEC1SMEN_POS 21U +#define STM32_RCC_AHB2SMENR_OTFDEC1SMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_OTFDEC1SMEN_POS) +#define STM32_RCC_AHB2SMENR_OTFDEC1SMEN STM32_RCC_AHB2SMENR_OTFDEC1SMEN_MSK +#define STM32_RCC_AHB2SMENR_SDMMC1SMEN_POS 22U +#define STM32_RCC_AHB2SMENR_SDMMC1SMEN_MSK \ + (0x1UL << STM32_RCC_AHB2SMENR_SDMMC1SMEN_POS) +#define STM32_RCC_AHB2SMENR_SDMMC1SMEN STM32_RCC_AHB2SMENR_SDMMC1SMEN_MSK + +/************** BIT DEFINITION FOR STM32_RCC_AHB3SMENR REGISTER *************/ +#define STM32_RCC_AHB3SMENR_FMCSMEN_POS 0U +#define STM32_RCC_AHB3SMENR_FMCSMEN_MSK \ + (0x1UL << STM32_RCC_AHB3SMENR_FMCSMEN_POS) +#define STM32_RCC_AHB3SMENR_FMCSMEN STM32_RCC_AHB3SMENR_FMCSMEN_MSK +#define STM32_RCC_AHB3SMENR_QSPISMEN_POS 8U +#define STM32_RCC_AHB3SMENR_QSPISMEN_MSK \ + (0x1UL << STM32_RCC_AHB3SMENR_QSPISMEN_POS) +#define STM32_RCC_AHB3SMENR_QSPISMEN STM32_RCC_AHB3SMENR_QSPISMEN_MSK + +/************* BIT DEFINITION FOR STM32_RCC_APB1SMENR1 REGISTER *************/ +#define STM32_RCC_APB1SMENR1_TIM2SMEN_POS 0U +#define STM32_RCC_APB1SMENR1_TIM2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_TIM2SMEN_POS) +#define STM32_RCC_APB1SMENR1_TIM2SMEN STM32_RCC_APB1SMENR1_TIM2SMEN_MSK +#define STM32_RCC_APB1SMENR1_TIM3SMEN_POS 1U +#define STM32_RCC_APB1SMENR1_TIM3SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_TIM3SMEN_POS) +#define STM32_RCC_APB1SMENR1_TIM3SMEN STM32_RCC_APB1SMENR1_TIM3SMEN_MSK +#define STM32_RCC_APB1SMENR1_TIM4SMEN_POS 2U +#define STM32_RCC_APB1SMENR1_TIM4SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_TIM4SMEN_POS) +#define STM32_RCC_APB1SMENR1_TIM4SMEN STM32_RCC_APB1SMENR1_TIM4SMEN_MSK +#define STM32_RCC_APB1SMENR1_TIM5SMEN_POS 3U +#define STM32_RCC_APB1SMENR1_TIM5SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_TIM5SMEN_POS) +#define STM32_RCC_APB1SMENR1_TIM5SMEN STM32_RCC_APB1SMENR1_TIM5SMEN_MSK +#define STM32_RCC_APB1SMENR1_TIM6SMEN_POS 4U +#define STM32_RCC_APB1SMENR1_TIM6SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_TIM6SMEN_POS) +#define STM32_RCC_APB1SMENR1_TIM6SMEN STM32_RCC_APB1SMENR1_TIM6SMEN_MSK +#define STM32_RCC_APB1SMENR1_TIM7SMEN_POS 5U +#define STM32_RCC_APB1SMENR1_TIM7SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_TIM7SMEN_POS) +#define STM32_RCC_APB1SMENR1_TIM7SMEN STM32_RCC_APB1SMENR1_TIM7SMEN_MSK +#define STM32_RCC_APB1SMENR1_RTCAPBSMEN_POS 10U +#define STM32_RCC_APB1SMENR1_RTCAPBSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_RTCAPBSMEN_POS) +#define STM32_RCC_APB1SMENR1_RTCAPBSMEN STM32_RCC_APB1SMENR1_RTCAPBSMEN_MSK +#define STM32_RCC_APB1SMENR1_WWDGSMEN_POS 11U +#define STM32_RCC_APB1SMENR1_WWDGSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_WWDGSMEN_POS) +#define STM32_RCC_APB1SMENR1_WWDGSMEN STM32_RCC_APB1SMENR1_WWDGSMEN_MSK +#define STM32_RCC_APB1SMENR1_SPI2SMEN_POS 14U +#define STM32_RCC_APB1SMENR1_SPI2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_SPI2SMEN_POS) +#define STM32_RCC_APB1SMENR1_SPI2SMEN STM32_RCC_APB1SMENR1_SPI2SMEN_MSK +#define STM32_RCC_APB1SMENR1_SPI3SMEN_POS 15U +#define STM32_RCC_APB1SMENR1_SPI3SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_SPI3SMEN_POS) +#define STM32_RCC_APB1SMENR1_SPI3SMEN STM32_RCC_APB1SMENR1_SPI3SMEN_MSK +#define STM32_RCC_APB1SMENR1_USART2SMEN_POS 17U +#define STM32_RCC_APB1SMENR1_USART2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_USART2SMEN_POS) +#define STM32_RCC_APB1SMENR1_USART2SMEN STM32_RCC_APB1SMENR1_USART2SMEN_MSK +#define STM32_RCC_APB1SMENR1_USART3SMEN_POS 18U +#define STM32_RCC_APB1SMENR1_USART3SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_USART3SMEN_POS) +#define STM32_RCC_APB1SMENR1_USART3SMEN STM32_RCC_APB1SMENR1_USART3SMEN_MSK +#define STM32_RCC_APB1SMENR1_USART4SMEN_POS 19U +#define STM32_RCC_APB1SMENR1_USART4SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_USART4SMEN_POS) +#define STM32_RCC_APB1SMENR1_USART4SMEN STM32_RCC_APB1SMENR1_USART4SMEN_MSK +#define STM32_RCC_APB1SMENR1_USART5SMEN_POS 20U +#define STM32_RCC_APB1SMENR1_USART5SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_USART5SMEN_POS) +#define STM32_RCC_APB1SMENR1_USART5SMEN STM32_RCC_APB1SMENR1_USART5SMEN_MSK +#define STM32_RCC_APB1SMENR1_I2C1SMEN_POS 21U +#define STM32_RCC_APB1SMENR1_I2C1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_I2C1SMEN_POS) +#define STM32_RCC_APB1SMENR1_I2C1SMEN STM32_RCC_APB1SMENR1_I2C1SMEN_MSK +#define STM32_RCC_APB1SMENR1_I2C2SMEN_POS 22U +#define STM32_RCC_APB1SMENR1_I2C2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_I2C2SMEN_POS) +#define STM32_RCC_APB1SMENR1_I2C2SMEN STM32_RCC_APB1SMENR1_I2C2SMEN_MSK +#define STM32_RCC_APB1SMENR1_I2C3SMEN_POS 23U +#define STM32_RCC_APB1SMENR1_I2C3SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_I2C3SMEN_POS) +#define STM32_RCC_APB1SMENR1_I2C3SMEN STM32_RCC_APB1SMENR1_I2C3SMEN_MSK +#define STM32_RCC_APB1SMENR1_CRSSMEN_POS 24U +#define STM32_RCC_APB1SMENR1_CRSSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_CRSSMEN_POS) +#define STM32_RCC_APB1SMENR1_CRSSMEN STM32_RCC_APB1SMENR1_CRSSMEN_MSK +#define STM32_RCC_APB1SMENR1_PWRSMEN_POS 28U +#define STM32_RCC_APB1SMENR1_PWRSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_PWRSMEN_POS) +#define STM32_RCC_APB1SMENR1_PWRSMEN STM32_RCC_APB1SMENR1_PWRSMEN_MSK +#define STM32_RCC_APB1SMENR1_DAC1SMEN_POS 29U +#define STM32_RCC_APB1SMENR1_DAC1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_DAC1SMEN_POS) +#define STM32_RCC_APB1SMENR1_DAC1SMEN STM32_RCC_APB1SMENR1_DAC1SMEN_MSK +#define STM32_RCC_APB1SMENR1_OPAMPSMEN_POS 30U +#define STM32_RCC_APB1SMENR1_OPAMPSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_OPAMPSMEN_POS) +#define STM32_RCC_APB1SMENR1_OPAMPSMEN STM32_RCC_APB1SMENR1_OPAMPSMEN_MSK +#define STM32_RCC_APB1SMENR1_LPTIM1SMEN_POS 31U +#define STM32_RCC_APB1SMENR1_LPTIM1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR1_LPTIM1SMEN_POS) +#define STM32_RCC_APB1SMENR1_LPTIM1SMEN STM32_RCC_APB1SMENR1_LPTIM1SMEN_MSK + +/************* BIT DEFINITION FOR STM32_RCC_APB1SMENR2 REGISTER *************/ +#define STM32_RCC_APB1SMENR2_LPUART1SMEN_POS 0U +#define STM32_RCC_APB1SMENR2_LPUART1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_LPUART1SMEN_POS) +#define STM32_RCC_APB1SMENR2_LPUART1SMEN STM32_RCC_APB1SMENR2_LPUART1SMEN_MSK +#define STM32_RCC_APB1SMENR2_I2C4SMEN_POS 1U +#define STM32_RCC_APB1SMENR2_I2C4SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_I2C4SMEN_POS) +#define STM32_RCC_APB1SMENR2_I2C4SMEN STM32_RCC_APB1SMENR2_I2C4SMEN_MSK +#define STM32_RCC_APB1SMENR2_LPTIM2SMEN_POS 5U +#define STM32_RCC_APB1SMENR2_LPTIM2SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_LPTIM2SMEN_POS) +#define STM32_RCC_APB1SMENR2_LPTIM2SMEN STM32_RCC_APB1SMENR2_LPTIM2SMEN_MSK +#define STM32_RCC_APB1SMENR2_LPTIM3SMEN_POS 6U +#define STM32_RCC_APB1SMENR2_LPTIM3SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_LPTIM3SMEN_POS) +#define STM32_RCC_APB1SMENR2_LPTIM3SMEN STM32_RCC_APB1SMENR2_LPTIM3SMEN_MSK +#define STM32_RCC_APB1SMENR2_FDCAN1SMEN_POS 9U +#define STM32_RCC_APB1SMENR2_FDCAN1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_FDCAN1SMEN_POS) +#define STM32_RCC_APB1SMENR2_FDCAN1SMEN STM32_RCC_APB1SMENR2_FDCAN1SMEN_MSK +#define STM32_RCC_APB1SMENR2_USBFSSMEN_POS 21U +#define STM32_RCC_APB1SMENR2_USBFSSMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_USBFSSMEN_POS) +#define STM32_RCC_APB1SMENR2_USBFSSMEN STM32_RCC_APB1SMENR2_USBFSSMEN_MSK +#define STM32_RCC_APB1SMENR2_UCPD1SMEN_POS 23U +#define STM32_RCC_APB1SMENR2_UCPD1SMEN_MSK \ + (0x1UL << STM32_RCC_APB1SMENR2_UCPD1SMEN_POS) +#define STM32_RCC_APB1SMENR2_UCPD1SMEN STM32_RCC_APB1SMENR2_UCPD1SMEN_MSK + +/************ BIT DEFINITION FOR STM32_RCC_APB2SMENR REGISTER *************/ +#define STM32_RCC_APB2SMENR_SYSCFGSMEN_POS 0U +#define STM32_RCC_APB2SMENR_SYSCFGSMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_SYSCFGSMEN_POS) +#define STM32_RCC_APB2SMENR_SYSCFGSMEN STM32_RCC_APB2SMENR_SYSCFGSMEN_MSK +#define STM32_RCC_APB2SMENR_TIM1SMEN_POS 11U +#define STM32_RCC_APB2SMENR_TIM1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_TIM1SMEN_POS) +#define STM32_RCC_APB2SMENR_TIM1SMEN STM32_RCC_APB2SMENR_TIM1SMEN_MSK +#define STM32_RCC_APB2SMENR_SPI1SMEN_POS 12U +#define STM32_RCC_APB2SMENR_SPI1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_SPI1SMEN_POS) +#define STM32_RCC_APB2SMENR_SPI1SMEN STM32_RCC_APB2SMENR_SPI1SMEN_MSK +#define STM32_RCC_APB2SMENR_TIM8SMEN_POS 13U +#define STM32_RCC_APB2SMENR_TIM8SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_TIM8SMEN_POS) +#define STM32_RCC_APB2SMENR_TIM8SMEN STM32_RCC_APB2SMENR_TIM8SMEN_MSK +#define STM32_RCC_APB2SMENR_USART1SMEN_POS 14U +#define STM32_RCC_APB2SMENR_USART1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_USART1SMEN_POS) +#define STM32_RCC_APB2SMENR_USART1SMEN STM32_RCC_APB2SMENR_USART1SMEN_MSK +#define STM32_RCC_APB2SMENR_TIM15SMEN_POS 16U +#define STM32_RCC_APB2SMENR_TIM15SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_TIM15SMEN_POS) +#define STM32_RCC_APB2SMENR_TIM15SMEN STM32_RCC_APB2SMENR_TIM15SMEN_MSK +#define STM32_RCC_APB2SMENR_TIM16SMEN_POS 17U +#define STM32_RCC_APB2SMENR_TIM16SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_TIM16SMEN_POS) +#define STM32_RCC_APB2SMENR_TIM16SMEN STM32_RCC_APB2SMENR_TIM16SMEN_MSK +#define STM32_RCC_APB2SMENR_TIM17SMEN_POS 18U +#define STM32_RCC_APB2SMENR_TIM17SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_TIM17SMEN_POS) +#define STM32_RCC_APB2SMENR_TIM17SMEN STM32_RCC_APB2SMENR_TIM17SMEN_MSK +#define STM32_RCC_APB2SMENR_SAI1SMEN_POS 21U +#define STM32_RCC_APB2SMENR_SAI1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_SAI1SMEN_POS) +#define STM32_RCC_APB2SMENR_SAI1SMEN STM32_RCC_APB2SMENR_SAI1SMEN_MSK +#define STM32_RCC_APB2SMENR_SAI2SMEN_POS 22U +#define STM32_RCC_APB2SMENR_SAI2SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_SAI2SMEN_POS) +#define STM32_RCC_APB2SMENR_SAI2SMEN STM32_RCC_APB2SMENR_SAI2SMEN_MSK +#define STM32_RCC_APB2SMENR_DFSDM1SMEN_POS 24U +#define STM32_RCC_APB2SMENR_DFSDM1SMEN_MSK \ + (0x1UL << STM32_RCC_APB2SMENR_DFSDM1SMEN_POS) +#define STM32_RCC_APB2SMENR_DFSDM1SMEN STM32_RCC_APB2SMENR_DFSDM1SMEN_MSK + +/************* BIT DEFINITION FOR STM32_RCC_CCIPR1 REGISTER *****************/ +#define STM32_RCC_CCIPR1_USART1SEL_POS 0U +#define STM32_RCC_CCIPR1_USART1SEL_MSK (0x3UL << STM32_RCC_CCIPR_USART1SEL_POS) +#define STM32_RCC_CCIPR1_USART1SEL STM32_RCC_CCIPR_USART1SEL_MSK +#define STM32_RCC_CCIPR1_USART1SEL_0 (0x1UL << STM32_RCC_CCIPR_USART1SEL_POS) +#define STM32_RCC_CCIPR1_USART1SEL_1 (0x2UL << STM32_RCC_CCIPR_USART1SEL_POS) + +#define STM32_RCC_CCIPR1_USART2SEL_POS 2U +#define STM32_RCC_CCIPR1_USART2SEL_MSK (0x3UL << STM32_RCC_CCIPR_USART2SEL_POS) +#define STM32_RCC_CCIPR1_USART2SEL STM32_RCC_CCIPR_USART2SEL_MSK +#define STM32_RCC_CCIPR1_USART2SEL_0 (0x1UL << STM32_RCC_CCIPR_USART2SEL_POS) +#define STM32_RCC_CCIPR1_USART2SEL_1 (0x2UL << STM32_RCC_CCIPR_USART2SEL_POS) + +#define STM32_RCC_CCIPR1_USART3SEL_POS 4U +#define STM32_RCC_CCIPR1_USART3SEL_MSK (0x3UL << STM32_RCC_CCIPR_USART3SEL_POS) +#define STM32_RCC_CCIPR1_USART3SEL STM32_RCC_CCIPR_USART3SEL_MSK +#define STM32_RCC_CCIPR1_USART3SEL_0 (0x1UL << STM32_RCC_CCIPR_USART3SEL_POS) +#define STM32_RCC_CCIPR1_USART3SEL_1 (0x2UL << STM32_RCC_CCIPR_USART3SEL_POS) + +#define STM32_RCC_CCIPR1_USART4SEL_POS 6U +#define STM32_RCC_CCIPR1_USART4SEL_MSK (0x3UL << STM32_RCC_CCIPR_USART4SEL_POS) +#define STM32_RCC_CCIPR1_USART4SEL STM32_RCC_CCIPR_USART4SEL_MSK +#define STM32_RCC_CCIPR1_USART4SEL_0 (0x1UL << STM32_RCC_CCIPR_USART4SEL_POS) +#define STM32_RCC_CCIPR1_USART4SEL_1 (0x2UL << STM32_RCC_CCIPR_USART4SEL_POS) + +#define STM32_RCC_CCIPR1_USART5SEL_POS 8U +#define STM32_RCC_CCIPR1_USART5SEL_MSK (0x3UL << STM32_RCC_CCIPR_USART5SEL_POS) +#define STM32_RCC_CCIPR1_USART5SEL STM32_RCC_CCIPR_USART5SEL_MSK +#define STM32_RCC_CCIPR1_USART5SEL_0 (0x1UL << STM32_RCC_CCIPR_USART5SEL_POS) +#define STM32_RCC_CCIPR1_USART5SEL_1 (0x2UL << STM32_RCC_CCIPR_USART5SEL_POS) + +#define STM32_RCC_CCIPR1_LPUART1SEL_POS 10U +#define STM32_RCC_CCIPR1_LPUART1SEL_MSK \ + (0x3UL << STM32_RCC_CCIPR_LPUART1SEL_POS) +#define STM32_RCC_CCIPR1_LPUART1SEL STM32_RCC_CCIPR_LPUART1SEL_MSK +#define STM32_RCC_CCIPR1_LPUART1SEL_0 (0x1UL << STM32_RCC_CCIPR_LPUART1SEL_POS) +#define STM32_RCC_CCIPR1_LPUART1SEL_1 (0x2UL << STM32_RCC_CCIPR_LPUART1SEL_POS) + +#define STM32_RCC_CCIPR1_I2C1SEL_POS 12U +#define STM32_RCC_CCIPR1_I2C1SEL_MSK (0x3UL << STM32_RCC_CCIPR_I2C1SEL_POS) +#define STM32_RCC_CCIPR1_I2C1SEL STM32_RCC_CCIPR_I2C1SEL_MSK +#define STM32_RCC_CCIPR1_I2C1SEL_0 (0x1UL << STM32_RCC_CCIPR_I2C1SEL_POS) +#define STM32_RCC_CCIPR1_I2C1SEL_1 (0x2UL << STM32_RCC_CCIPR_I2C1SEL_POS) + +#define STM32_RCC_CCIPR1_I2C2SEL_POS 14U +#define STM32_RCC_CCIPR1_I2C2SEL_MSK (0x3UL << STM32_RCC_CCIPR_I2C2SEL_POS) +#define STM32_RCC_CCIPR1_I2C2SEL STM32_RCC_CCIPR_I2C2SEL_MSK +#define STM32_RCC_CCIPR1_I2C2SEL_0 (0x1UL << STM32_RCC_CCIPR_I2C2SEL_POS) +#define STM32_RCC_CCIPR1_I2C2SEL_1 (0x2UL << STM32_RCC_CCIPR_I2C2SEL_POS) + +#define STM32_RCC_CCIPR1_I2C3SEL_POS 16U +#define STM32_RCC_CCIPR1_I2C3SEL_MSK (0x3UL << STM32_RCC_CCIPR_I2C3SEL_POS) +#define STM32_RCC_CCIPR1_I2C3SEL STM32_RCC_CCIPR_I2C3SEL_MSK +#define STM32_RCC_CCIPR1_I2C3SEL_0 (0x1UL << STM32_RCC_CCIPR_I2C3SEL_POS) +#define STM32_RCC_CCIPR1_I2C3SEL_1 (0x2UL << STM32_RCC_CCIPR_I2C3SEL_POS) + +#define STM32_RCC_CCIPR1_LPTIM1SEL_POS 18U +#define STM32_RCC_CCIPR1_LPTIM1SEL_MSK (0x3UL << STM32_RCC_CCIPR_LPTIM1SEL_POS) +#define STM32_RCC_CCIPR1_LPTIM1SEL STM32_RCC_CCIPR_LPTIM1SEL_MSK +#define STM32_RCC_CCIPR1_LPTIM1SEL_0 (0x1UL << STM32_RCC_CCIPR_LPTIM1SEL_POS) +#define STM32_RCC_CCIPR1_LPTIM1SEL_1 (0x2UL << STM32_RCC_CCIPR_LPTIM1SEL_POS) + +#define STM32_RCC_CCIPR1_LPTIM2SEL_POS 20U +#define STM32_RCC_CCIPR1_LPTIM2SEL_MSK (0x3UL << STM32_RCC_CCIPR_LPTIM2SEL_POS) +#define STM32_RCC_CCIPR1_LPTIM2SEL STM32_RCC_CCIPR_LPTIM2SEL_MSK +#define STM32_RCC_CCIPR1_LPTIM2SEL_0 (0x1UL << STM32_RCC_CCIPR_LPTIM2SEL_POS) +#define STM32_RCC_CCIPR1_LPTIM2SEL_1 (0x2UL << STM32_RCC_CCIPR_LPTIM2SEL_POS) + +#define STM32_RCC_CCIPR1_LPTIM3SEL_POS 22U +#define STM32_RCC_CCIPR1_LPTIM3SEL_MSK (0x3UL << STM32_RCC_CCIPR_LPTIM3SEL_POS) +#define STM32_RCC_CCIPR1_LPTIM3SEL STM32_RCC_CCIPR_LPTIM3SEL_MSK +#define STM32_RCC_CCIPR1_LPTIM3SEL_0 (0x1UL << STM32_RCC_CCIPR_LPTIM3SEL_POS) +#define STM32_RCC_CCIPR1_LPTIM3SEL_1 (0x2UL << STM32_RCC_CCIPR_LPTIM3SEL_POS) + +#define STM32_RCC_CCIPR1_FDCANSEL_POS 24U +#define STM32_RCC_CCIPR1_FDCANSEL_MSK (0x3UL << STM32_RCC_CCIPR_FDCANSEL_POS) +#define STM32_RCC_CCIPR1_FDCANSEL STM32_RCC_CCIPR_FDCANSEL_MSK +#define STM32_RCC_CCIPR1_FDCANSEL_0 (0x1UL << STM32_RCC_CCIPR_FDCANSEL_POS) +#define STM32_RCC_CCIPR1_FDCANSEL_1 (0x2UL << STM32_RCC_CCIPR_FDCANSEL_POS) + +#define STM32_RCC_CCIPR1_CLK48SEL_POS 26U +#define STM32_RCC_CCIPR1_CLK48SEL_MSK (0x3UL << STM32_RCC_CCIPR_CLK48SEL_POS) +#define STM32_RCC_CCIPR1_CLK48SEL STM32_RCC_CCIPR_CLK48SEL_MSK +#define STM32_RCC_CCIPR1_CLK48SEL_0 (0x1UL << STM32_RCC_CCIPR_CLK48SEL_POS) +#define STM32_RCC_CCIPR1_CLK48SEL_1 (0x2UL << STM32_RCC_CCIPR_CLK48SEL_POS) + +#define STM32_RCC_CCIPR_ADCSEL_POS 28U +#define STM32_RCC_CCIPR_ADCSEL_MSK (0x3UL << STM32_RCC_CCIPR_ADCSEL_POS) +#define STM32_RCC_CCIPR_ADCSEL STM32_RCC_CCIPR_ADCSEL_MSK +#define STM32_RCC_CCIPR_ADCSEL_0 (0x1UL << STM32_RCC_CCIPR_ADCSEL_POS) +#define STM32_RCC_CCIPR_ADCSEL_1 (0x2UL << STM32_RCC_CCIPR_ADCSEL_POS) + +/************** BIT DEFINITION FOR STM32_RCC_BDCR REGISTER ******************/ +#define STM32_RCC_BDCR_LSEBYP_POS 2U +#define STM32_RCC_BDCR_LSEBYP_MSK (0x1UL << STM32_RCC_BDCR_LSEBYP_POS) +#define STM32_RCC_BDCR_LSEBYP STM32_RCC_BDCR_LSEBYP_MSK + +#define STM32_RCC_BDCR_LSEDRV_POS 3U +#define STM32_RCC_BDCR_LSEDRV_MSK (0x3UL << STM32_RCC_BDCR_LSEDRV_POS) +#define STM32_RCC_BDCR_LSEDRV STM32_RCC_BDCR_LSEDRV_MSK +#define STM32_RCC_BDCR_LSEDRV_0 (0x1UL << STM32_RCC_BDCR_LSEDRV_POS) +#define STM32_RCC_BDCR_LSEDRV_1 (0x2UL << STM32_RCC_BDCR_LSEDRV_POS) + +#define STM32_RCC_BDCR_LSECSSON_POS 5U +#define STM32_RCC_BDCR_LSECSSON_MSK (0x1UL << STM32_RCC_BDCR_LSECSSON_POS) +#define STM32_RCC_BDCR_LSECSSON STM32_RCC_BDCR_LSECSSON_MSK +#define STM32_RCC_BDCR_LSECSSD_POS 6U +#define STM32_RCC_BDCR_LSECSSD_MSK (0x1UL << STM32_RCC_BDCR_LSECSSD_POS) +#define STM32_RCC_BDCR_LSECSSD STM32_RCC_BDCR_LSECSSD_MSK +#define STM32_RCC_BDCR_LSESYSEN_POS 7U +#define STM32_RCC_BDCR_LSESYSEN_MSK (0x1UL << STM32_RCC_BDCR_LSESYSEN_POS) +#define STM32_RCC_BDCR_LSESYSEN STM32_RCC_BDCR_LSESYSEN_MSK + +#define STM32_RCC_BDCR_RTCSEL_POS 8U +#define STM32_RCC_BDCR_RTCSEL_MSK (0x3UL << STM32_RCC_BDCR_RTCSEL_POS) +#define STM32_RCC_BDCR_RTCSEL STM32_RCC_BDCR_RTCSEL_MSK +#define STM32_RCC_BDCR_RTCSEL_0 (0x1UL << STM32_RCC_BDCR_RTCSEL_POS) +#define STM32_RCC_BDCR_RTCSEL_1 (0x2UL << STM32_RCC_BDCR_RTCSEL_POS) + +#define STM32_RCC_BDCR_LSESYSRDY_POS 11U +#define STM32_RCC_BDCR_LSESYSRDY_MSK (0x1UL << STM32_RCC_BDCR_LSESYSRDY_POS) +#define STM32_RCC_BDCR_LSESYSRDY STM32_RCC_BDCR_LSESYSRDY_MSK +#define STM32_RCC_BDCR_LSCOEN_POS 24U +#define STM32_RCC_BDCR_LSCOEN_MSK (0x1UL << STM32_RCC_BDCR_LSCOEN_POS) +#define STM32_RCC_BDCR_LSCOEN STM32_RCC_BDCR_LSCOEN_MSK +#define STM32_RCC_BDCR_LSCOSEL_POS 25U +#define STM32_RCC_BDCR_LSCOSEL_MSK (0x1UL << STM32_RCC_BDCR_LSCOSEL_POS) +#define STM32_RCC_BDCR_LSCOSEL STM32_RCC_BDCR_LSCOSEL_MSK + +/************** BIT DEFINITION FOR STM32_RCC_CSR REGISTER *******************/ +#define STM32_RCC_CSR_LSION_POS 0U +#define STM32_RCC_CSR_LSION_MSK (0x1UL << STM32_RCC_CSR_LSION_POS) +#define STM32_RCC_CSR_LSION STM32_RCC_CSR_LSION_MSK +#define STM32_RCC_CSR_LSIRDY_POS 1U +#define STM32_RCC_CSR_LSIRDY_MSK (0x1UL << STM32_RCC_CSR_LSIRDY_POS) +#define STM32_RCC_CSR_LSIRDY STM32_RCC_CSR_LSIRDY_MSK +#define STM32_RCC_CSR_LSIPRE_POS 4U +#define STM32_RCC_CSR_LSIPRE_MSK (0x1UL << STM32_RCC_CSR_LSIPRE_POS) +#define STM32_RCC_CSR_LSIPRE STM32_RCC_CSR_LSIPRE_MSK + +#define STM32_RCC_CSR_MSISRANGE_POS 8U +#define STM32_RCC_CSR_MSISRANGE_MSK (0xFUL << STM32_RCC_CSR_MSISRANGE_POS) +#define STM32_RCC_CSR_MSISRANGE STM32_RCC_CSR_MSISRANGE_MSK +#define STM32_RCC_CSR_MSISRANGE_1 (0x4UL << STM32_RCC_CSR_MSISRANGE_POS) +#define STM32_RCC_CSR_MSISRANGE_2 (0x5UL << STM32_RCC_CSR_MSISRANGE_POS) +#define STM32_RCC_CSR_MSISRANGE_4 (0x6UL << STM32_RCC_CSR_MSISRANGE_POS) +#define STM32_RCC_CSR_MSISRANGE_8 (0x7UL << STM32_RCC_CSR_MSISRANGE_POS) + +#define STM32_RCC_CSR_RMVF_POS 23U +#define STM32_RCC_CSR_RMVF_MSK (0x1UL << STM32_RCC_CSR_RMVF_POS) +#define STM32_RCC_CSR_RMVF STM32_RCC_CSR_RMVF_MSK +#define STM32_RCC_CSR_OBLRSTF_POS 25U +#define STM32_RCC_CSR_OBLRSTF_MSK (0x1UL << STM32_RCC_CSR_OBLRSTF_POS) +#define STM32_RCC_CSR_OBLRSTF STM32_RCC_CSR_OBLRSTF_MSK +#define STM32_RCC_CSR_PINRSTF_POS 26U +#define STM32_RCC_CSR_PINRSTF_MSK (0x1UL << STM32_RCC_CSR_PINRSTF_POS) +#define STM32_RCC_CSR_PINRSTF STM32_RCC_CSR_PINRSTF_MSK +#define STM32_RCC_CSR_BORRSTF_POS 27U +#define STM32_RCC_CSR_BORRSTF_MSK (0x1UL << STM32_RCC_CSR_BORRSTF_POS) +#define STM32_RCC_CSR_BORRSTF STM32_RCC_CSR_BORRSTF_MSK +#define STM32_RCC_CSR_SFTRSTF_POS 28U +#define STM32_RCC_CSR_SFTRSTF_MSK (0x1UL << STM32_RCC_CSR_SFTRSTF_POS) +#define STM32_RCC_CSR_SFTRSTF STM32_RCC_CSR_SFTRSTF_MSK +#define STM32_RCC_CSR_IWDGRSTF_POS 29U +#define STM32_RCC_CSR_IWDGRSTF_MSK (0x1UL << STM32_RCC_CSR_IWDGRSTF_POS) +#define STM32_RCC_CSR_IWDGRSTF STM32_RCC_CSR_IWDGRSTF_MSK +#define STM32_RCC_CSR_WWDGRSTF_POS 30U +#define STM32_RCC_CSR_WWDGRSTF_MSK (0x1UL << STM32_RCC_CSR_WWDGRSTF_POS) +#define STM32_RCC_CSR_WWDGRSTF STM32_RCC_CSR_WWDGRSTF_MSK +#define STM32_RCC_CSR_LPWRRSTF_POS 31U +#define STM32_RCC_CSR_LPWRRSTF_MSK (0x1UL << STM32_RCC_CSR_LPWRRSTF_POS) +#define STM32_RCC_CSR_LPWRRSTF STM32_RCC_CSR_LPWRRSTF_MSK + +/************** Bit definition for STM32_RCC_CRRCR register *****************/ +#define STM32_RCC_CRRCR_HSI48ON_POS 0U +#define STM32_RCC_CRRCR_HSI48ON_MSK (0x1UL << STM32_RCC_CRRCR_HSI48ON_POS) +#define STM32_RCC_CRRCR_HSI48ON STM32_RCC_CRRCR_HSI48ON_MSK +#define STM32_RCC_CRRCR_HSI48RDY_POS 1U +#define STM32_RCC_CRRCR_HSI48RDY_MSK (0x1UL << STM32_RCC_CRRCR_HSI48RDY_POS) +#define STM32_RCC_CRRCR_HSI48RDY STM32_RCC_CRRCR_HSI48RDY_MSK + +/************** Bit definition for STM32_RCC_CRRCR2 register ****************/ +/* TODO */ + +/************** Bit definition for STM32_RCC_DLYCFGR register ***************/ +/* TODO */ + +/************** Bit definition for STM32_RCC_CCIPR2 register ****************/ +#define STM32_RCC_CCIPR2_I2C4SEL_POS 0U +#define STM32_RCC_CCIPR2_I2C4SEL_MSK (0x3UL << STM32_RCC_CCIPR2_I2C4SEL_POS) +#define STM32_RCC_CCIPR2_I2C4SEL STM32_RCC_CCIPR2_I2C4SEL_MSK +#define STM32_RCC_CCIPR2_I2C4SEL_0 (0x1UL << STM32_RCC_CCIPR2_I2C4SEL_POS) +#define STM32_RCC_CCIPR2_I2C4SEL_1 (0x2UL << STM32_RCC_CCIPR2_I2C4SEL_POS) + +/************** Bit definition for STM32_CRS_CR register ********************/ +#define STM32_CRS_CR_SYNCOKIE_POS 0U +#define STM32_CRS_CR_SYNCOKIE_MSK (0x1UL << STM32_CRS_CR_SYNCOKIE_POS) +#define STM32_CRS_CR_SYNCOKIE STM32_CRS_CR_SYNCOKIE_MSK +#define STM32_CRS_CR_SYNCWARNIE_POS 1U +#define STM32_CRS_CR_SYNCWARNIE_MSK (0x1UL << STM32_CRS_CR_SYNCWARNIE_POS) +#define STM32_CRS_CR_SYNCWARNIE STM32_CRS_CR_SYNCWARNIE_MSK +#define STM32_CRS_CR_SYNCERRIE_POS 2U +#define STM32_CRS_CR_SYNCERRIE_MSK (0x1UL << STM32_CRS_CR_SYNCERRIE_POS) +#define STM32_CRS_CR_SYNCERRIE STM32_CRS_CR_SYNCERRIE_MSK +#define STM32_CRS_CR_SYNCIE_POS 3U +#define STM32_CRS_CR_SYNCIE_MSK (0x1UL << STM32_CRS_CR_SYNCIE_POS) +#define STM32_CRS_CR_SYNCIE STM32_CRS_CR_SYNCIE_MSK +#define STM32_CRS_CR_CEN_POS 5U +#define STM32_CRS_CR_CEN_MSK (0x1UL << STM32_CRS_CR_CEN_POS) +#define STM32_CRS_CR_CEN STM32_CRS_CR_CEN_MSK +#define STM32_CRS_CR_AUTOTRIMEN_POS 6U +#define STM32_CRS_CR_AUTOTRIMEN_MSK (0x1UL << STM32_CRS_CR_AUTOTRIMEN_POS) +#define STM32_CRS_CR_AUTOTRIMEN STM32_CRS_CR_AUTOTRIMEN_MSK +#define STM32_CRS_CR_SWSYNC_POS 7U +#define STM32_CRS_CR_SWSYNC_MSK (0x1UL << STM32_CRS_CR_SWSYNC_POS) +#define STM32_CRS_CR_SWSYNC STM32_CRS_CR_SWSYNC_MSK + +/*!< HSI48CAL configuration */ +#define STM32_RCC_CRRCR_HSI48CAL_POS 7U +#define STM32_RCC_CRRCR_HSI48CAL_MSK (0x1FFUL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL STM32_RCC_CRRCR_HSI48CAL_MSK +#define STM32_RCC_CRRCR_HSI48CAL_0 (0x001UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_1 (0x002UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_2 (0x004UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_3 (0x008UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_4 (0x010UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_5 (0x020UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_6 (0x040UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_7 (0x080UL << STM32_RCC_CRRCR_HSI48CAL_POS) +#define STM32_RCC_CRRCR_HSI48CAL_8 (0x100UL << STM32_RCC_CRRCR_HSI48CAL_POS) + +#define STM32_SYSCFG_CFGR1 REG32(STM32_SYSCFG_BASE + 0x04) +#define STM32_SYSCFG_I2CFMP(n) BIT(n + 21) + +/* Peripheral bits for STM32_RCC_APB/AHB and DBGMCU regs */ +#define STM32_RCC_PB1_PWREN BIT(28) + +#define STM32_RCC_PB2_SYSCFGEN BIT(0) +#define STM32_RCC_PB2_USART1 BIT(14) + +#define STM32_RCC_HB1_DMA1 BIT(0) +#define STM32_RCC_HB1_DMA2 BIT(1) + +#define STM32_RCC_HB2_GPIOA BIT(0) +#define STM32_RCC_HB2_GPIOB BIT(1) +#define STM32_RCC_HB2_GPIOC BIT(2) +#define STM32_RCC_HB2_GPIOD BIT(3) +#define STM32_RCC_HB2_GPIOE BIT(4) +#define STM32_RCC_HB2_GPIOH BIT(7) +#define STM32_RCC_HB2_ADC1 BIT(13) + +/* Reset causes definitions */ +/* Reset causes in RCC CSR register */ +#define STM32_RCC_RESET_CAUSE STM32_RCC_CSR +#define RESET_CAUSE_WDG 0x60000000 +#define RESET_CAUSE_SFT 0x10000000 +#define RESET_CAUSE_POR 0x08000000 +#define RESET_CAUSE_PIN 0x04000000 +#define RESET_CAUSE_OTHER 0xff000000 +#define RESET_CAUSE_RMVF BIT(23) +/* Power cause in PWR CSR register */ +#define STM32_PWR_RESET_CAUSE STM32_PWR_CSR +#define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_SCR +#define RESET_CAUSE_SBF BIT(8) +#define RESET_CAUSE_SBF_CLR BIT(8) + +/* --- Watchdogs --- */ + +/* --- Real-Time Clock --- */ +#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00) +#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04) +#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08) +#define STM32_RTC_CR_BYPSHAD BIT(5) +#define STM32_RTC_CR_ALRAE BIT(8) +#define STM32_RTC_CR_WUTE BIT(10) +#define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_CR_WUTIE BIT(14) +#define STM32_RTC_ISR REG32(STM32_RTC_BASE + 0x0C) +#define STM32_RTC_ISR_ALRAWF BIT(0) +#define STM32_RTC_ISR_WUTWF BIT(2) +#define STM32_RTC_ISR_INITS BIT(4) +#define STM32_RTC_ISR_RSF BIT(5) +#define STM32_RTC_ISR_INITF BIT(6) +#define STM32_RTC_ISR_INIT BIT(7) +#define STM32_RTC_ISR_ALRAF BIT(8) +#define STM32_RTC_ISR_WUTF BIT(9) +#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10) +#define STM32_RTC_PRER_A_MASK (0x7f << 16) +#define STM32_RTC_PRER_S_MASK (0x7fff << 0) +#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14) +#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18) +#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C) +#define STM32_RTC_ALRMBR REG32(STM32_RTC_BASE + 0x20) +#define STM32_RTC_WPR REG32(STM32_RTC_BASE + 0x24) +#define STM32_RTC_SSR REG32(STM32_RTC_BASE + 0x28) +#define STM32_RTC_TSTR REG32(STM32_RTC_BASE + 0x30) +#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34) +#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40) +#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44) + +#define STM32_RTC_CLEAR_FLAG(x) \ + (STM32_RTC_ISR = (~((x) | STM32_RTC_ISR_INIT) | \ + (STM32_RTC_ISR & STM32_RTC_ISR_INIT))) + +/* --- Tamper and backup registers --- */ +#define STM32_TAMP_CR1 REG32(STM32_TAMP_BASE) +#define STM32_TAMP_CR2 REG32(STM32_TAMP_BASE + 0x04) +#define STM32_TAMP_CR3 REG32(STM32_TAMP_BASE + 0x08) +#define STM32_TAMP_FLTCR REG32(STM32_TAMP_BASE + 0x0C) +#define STM32_TAMP_ATCR1 REG32(STM32_TAMP_BASE + 0x10) +#define STM32_TAMP_ATSEEDR REG32(STM32_TAMP_BASE + 0x14) +#define STM32_TAMP_ATOR REG32(STM32_TAMP_BASE + 0x18) +#define STM32_TAMP_ATOCR2 REG32(STM32_TAMP_BASE + 0x1C) +#define STM32_TAMP_ATSMCR REG32(STM32_TAMP_BASE + 0x20) +#define STM32_TAMP_PRIVCR REG32(STM32_TAMP_BASE + 0x24) +#define STM32_TAMP_IER REG32(STM32_TAMP_BASE + 0x2C) +#define STM32_TAMP_SR REG32(STM32_TAMP_BASE + 0x30) +#define STM32_TAMP_MISR REG32(STM32_TAMP_BASE + 0x34) +#define STM32_TAMP_SMISR REG32(STM32_TAMP_BASE + 0x38) +#define STM32_TAMP_SCR REG32(STM32_TAMP_BASE + 0x3C) +#define STM32_TAMP_COUNTR REG32(STM32_TAMP_BASE + 0x40) +#define STM32_TAMP_CFGR REG32(STM32_TAMP_BASE + 0x50) +#define STM32_TAMP_BACKUP(n) REG32(STM32_TAMP_BASE + 0x100 + 4 * (n)) + +#define STM32_BKP_DATA(n) STM32_TAMP_BACKUP(n) +#define STM32_BKP_BYTES 128 + +#define RTC_TR_PM_POS 22U +#define RTC_TR_PM_MSK (0x1UL << RTC_TR_PM_POS) +#define RTC_TR_PM RTC_TR_PM_MSK +#define RTC_TR_HT_POS 20U +#define RTC_TR_HT_MSK (0x3UL << RTC_TR_HT_POS) +#define RTC_TR_HT RTC_TR_HT_MSK +#define RTC_TR_HU_POS 16U +#define RTC_TR_HU_MSK (0xFUL << RTC_TR_HU_POS) +#define RTC_TR_HU RTC_TR_HU_MSK +#define RTC_TR_MNT_POS 12U +#define RTC_TR_MNT_MSK (0x7UL << RTC_TR_MNT_POS) +#define RTC_TR_MNT RTC_TR_MNT_MSK +#define RTC_TR_MNU_POS 8U +#define RTC_TR_MNU_MSK (0xFUL << RTC_TR_MNU_POS) +#define RTC_TR_MNU RTC_TR_MNU_MSK +#define RTC_TR_ST_POS 4U +#define RTC_TR_ST_MSK (0x7UL << RTC_TR_ST_POS) +#define RTC_TR_ST RTC_TR_ST_MSK +#define RTC_TR_SU_POS 0U +#define RTC_TR_SU_MSK (0xFUL << RTC_TR_SU_POS) +#define RTC_TR_SU RTC_TR_SU_MSK + +/* --- SPI --- */ + +/* The SPI controller registers */ +struct stm32_spi_regs { + uint16_t cr1; + uint16_t _pad0; + uint16_t cr2; + uint16_t _pad1; + unsigned int sr; + uint8_t dr; + uint8_t _pad2; + uint16_t _pad3; + unsigned int crcpr; + unsigned int rxcrcr; + unsigned int txcrcr; + unsigned int i2scfgr; /* STM32L only */ + unsigned int i2spr; /* STM32L only */ +}; +/* Must be volatile, or compiler optimizes out repeated accesses */ +typedef volatile struct stm32_spi_regs stm32_spi_regs_t; + +#define STM32_SPI1_REGS ((stm32_spi_regs_t *)STM32_SPI1_BASE) +#define STM32_SPI2_REGS ((stm32_spi_regs_t *)STM32_SPI2_BASE) +#define STM32_SPI3_REGS ((stm32_spi_regs_t *)STM32_SPI3_BASE) +#define STM32_SPI4_REGS ((stm32_spi_regs_t *)STM32_SPI4_BASE) + +#define STM32_SPI_CR1_BIDIMODE BIT(15) +#define STM32_SPI_CR1_BIDIOE BIT(14) +#define STM32_SPI_CR1_CRCEN BIT(13) +#define STM32_SPI_CR1_SSM BIT(9) +#define STM32_SPI_CR1_SSI BIT(8) +#define STM32_SPI_CR1_LSBFIRST BIT(7) +#define STM32_SPI_CR1_SPE BIT(6) +#define STM32_SPI_CR1_BR_DIV64R (5 << 3) +#define STM32_SPI_CR1_BR_DIV4R BIT(3) +#define STM32_SPI_CR1_MSTR BIT(2) +#define STM32_SPI_CR1_CPOL BIT(1) +#define STM32_SPI_CR1_CPHA BIT(0) +#define STM32_SPI_CR2_FRXTH BIT(12) +#define STM32_SPI_CR2_DATASIZE(n) (((n)-1) << 8) +#define STM32_SPI_CR2_TXEIE BIT(7) +#define STM32_SPI_CR2_RXNEIE BIT(6) +#define STM32_SPI_CR2_NSSP BIT(3) +#define STM32_SPI_CR2_SSOE BIT(2) +#define STM32_SPI_CR2_TXDMAEN BIT(1) +#define STM32_SPI_CR2_RXDMAEN BIT(0) + +#define STM32_SPI_SR_RXNE BIT(0) +#define STM32_SPI_SR_TXE BIT(1) +#define STM32_SPI_SR_CRCERR BIT(4) +#define STM32_SPI_SR_BSY BIT(7) +#define STM32_SPI_SR_FRLVL (3 << 9) +#define STM32_SPI_SR_FTLVL (3 << 11) +/* --- Debug --- */ +#define STM32_DBGMCU_APB1FZ REG32(STM32_DBGMCU_BASE + 0x08) +#define STM32_DBGMCU_APB2FZ REG32(STM32_DBGMCU_BASE + 0x0C) + +/* --- Flash --- */ +#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00) +#define STM32_FLASH_ACR_LATENCY_SHIFT (0) +#define STM32_FLASH_ACR_LATENCY_MASK (7 << STM32_FLASH_ACR_LATENCY_SHIFT) +#define STM32_FLASH_ACR_PRFTEN BIT(8) +#define STM32_FLASH_ACR_ICEN BIT(9) +#define STM32_FLASH_ACR_DCEN BIT(10) +#define STM32_FLASH_ACR_ICRST BIT(11) +#define STM32_FLASH_ACR_DCRST BIT(12) +#define STM32_FLASH_PDKEYR REG32(STM32_FLASH_REGS_BASE + 0x04) +#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x08) +#define FLASH_KEYR_KEY1 0x45670123 +#define FLASH_KEYR_KEY2 0xCDEF89AB +#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x10) +#define FLASH_OPTKEYR_KEY1 0x08192A3B +#define FLASH_OPTKEYR_KEY2 0x4C5D6E7F +#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x20) +#define FLASH_SR_BUSY BIT(16) +#define FLASH_SR_ERR_MASK (0xc3fa) +#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x28) +#define FLASH_CR_PG BIT(0) +#define FLASH_CR_PER BIT(1) +#define FLASH_CR_STRT BIT(16) +#define FLASH_CR_OPTSTRT BIT(17) +#define FLASH_CR_OBL_LAUNCH BIT(27) +#define FLASH_CR_OPTLOCK BIT(30) +#define FLASH_CR_LOCK BIT(31) +#define FLASH_CR_PNB(sec) (((sec)&0xff) << 3) +#define FLASH_CR_PNB_MASK FLASH_CR_PNB(0xff) +#define STM32_FLASH_ECCR REG32(STM32_FLASH_REGS_BASE + 0x30) +#define STM32_FLASH_OPTR REG32(STM32_FLASH_REGS_BASE + 0x40) +#define STM32_FLASH_WRP1AR REG32(STM32_FLASH_REGS_BASE + 0x58) +#define STM32_FLASH_WRP1BR REG32(STM32_FLASH_REGS_BASE + 0x5C) +/* Minimum number of bytes that can be written to flash */ +#define STM32_FLASH_MIN_WRITE_SIZE CONFIG_FLASH_WRITE_SIZE + +#define STM32_OPTB_WRP1AR STM32_FLASH_WRP1AR +#define STM32_OPTB_WRP1BR STM32_FLASH_WRP1BR + +/* --- External Interrupts --- */ +#define STM32_EXTI_RTSR REG32(STM32_EXTI_BASE + 0x00) +#define STM32_EXTI_FTSR REG32(STM32_EXTI_BASE + 0x04) +#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x08) +#define STM32_EXTI_RPR REG32(STM32_EXTI_BASE + 0x0C) +#define STM32_EXTI_FPR REG32(STM32_EXTI_BASE + 0x10) +#define STM32_EXTI_RTSR2 REG32(STM32_EXTI_BASE + 0x20) +#define STM32_EXTI_FTSR2 REG32(STM32_EXTI_BASE + 0x24) +#define STM32_EXTI_SWIER2 REG32(STM32_EXTI_BASE + 0x28) +#define STM32_EXTI_RPR2 REG32(STM32_EXTI_BASE + 0x2C) +#define STM32_EXTI_FPR2 REG32(STM32_EXTI_BASE + 0x30) +#define STM32_EXTI_EXTICR(n) REG32(STM32_EXTI_BASE + 0x60 + 4 * (n)) +#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x80) +#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x84) +#define STM32_EXTI_IMR2 REG32(STM32_EXTI_BASE + 0x80) +#define STM32_EXTI_EMR2 REG32(STM32_EXTI_BASE + 0x84) + +#define EXTI_RTC_ALR_EVENT BIT(18) + +/* --- ADC --- */ +#define STM32_ADC1_ISR REG32(STM32_ADC1_BASE + 0x00) +#define STM32_ADC1_ISR_ADRDY BIT(0) +#define STM32_ADC1_IER REG32(STM32_ADC1_BASE + 0x04) +#define STM32_ADC1_IER_AWDIE BIT(7) +#define STM32_ADC1_IER_OVRIE BIT(4) +#define STM32_ADC1_IER_EOSEQIE BIT(3) +#define STM32_ADC1_IER_EOCIE BIT(2) +#define STM32_ADC1_IER_EOSMPIE BIT(1) +#define STM32_ADC1_IER_ADRDYIE BIT(0) + +#define STM32_ADC1_CR REG32(STM32_ADC1_BASE + 0x08) +#define STM32_ADC1_CR_ADEN BIT(0) +#define STM32_ADC1_CR_ADDIS BIT(1) +#define STM32_ADC1_CR_ADSTP BIT(4) +#define STM32_ADC1_CR_ADVREGEN BIT(28) +#define STM32_ADC1_CR_DEEPPWD BIT(29) +#define STM32_ADC1_CR_ADCAL BIT(31) +#define STM32_ADC1_CFGR REG32(STM32_ADC1_BASE + 0x0C) +/* Analog watchdog channel selection */ +#define STM32_ADC1_CFGR_AWDCH_MASK (0x1f << 26) +#define STM32_ADC1_CFGR_AWDEN BIT(23) +#define STM32_ADC1_CFGR_AWDSGL BIT(22) +#define STM32_ADC1_CFGR_AUTDLY BIT(14) +/* Selects single vs continuous */ +#define STM32_ADC1_CFGR_CONT BIT(13) +/* Selects ADC_DR overwrite vs preserve */ +#define STM32_ADC1_CFGR_OVRMOD BIT(12) +/* External trigger polarity selection */ +#define STM32_ADC1_CFGR_EXTEN_DIS (0 << 10) +#define STM32_ADC1_CFGR_EXTEN_RISE (1 << 10) +#define STM32_ADC1_CFGR_EXTEN_FALL (2 << 10) +#define STM32_ADC1_CFGR_EXTEN_BOTH (3 << 10) +#define STM32_ADC1_CFGR_EXTEN_MASK (3 << 10) +#define STM32_ADC1_CFGR_ALIGN BIT(5) +/* External trigger selection */ +#define STM32_ADC1_CFGR_TRG0 (0 << 6) +#define STM32_ADC1_CFGR_TRG1 (1 << 6) +#define STM32_ADC1_CFGR_TRG2 (2 << 6) +#define STM32_ADC1_CFGR_TRG3 (3 << 6) +#define STM32_ADC1_CFGR_TRG4 (4 << 6) +#define STM32_ADC1_CFGR_TRG5 (5 << 6) +#define STM32_ADC1_CFGR_TRG6 (6 << 6) +#define STM32_ADC1_CFGR_TRG7 (7 << 6) +#define STM32_ADC1_CFGR_TRG_MASK (7 << 6) +/* Selects circular vs one-shot */ +#define STM32_ADC1_CFGR_DMACFG BIT(1) +#define STM32_ADC1_CFGR_DMAEN BIT(0) +#define STM32_ADC1_CFGR2 REG32(STM32_ADC1_BASE + 0x10) +/* Sampling time selection - 1.5 ADC cycles min, 239.5 cycles max */ +#define STM32_ADC1_SMPR1 REG32(STM32_ADC1_BASE + 0x14) +#define STM32_ADC1_SMPR2 REG32(STM32_ADC1_BASE + 0x18) +/* Macro to convert enum stm32_adc_smpr to SMP bits of the ADC_SMPR register */ +#define STM32_ADC1_SMPR_SMP(s) ((s)-1) +#define STM32_ADC1_TR REG32(STM32_ADC1_BASE + 0x20) +#define STM32_ADC1_CHSELR REG32(STM32_ADC1_BASE + 0x28) +#define STM32_ADC1_DR REG32(STM32_ADC1_BASE + 0x40) +#define STM32_ADC1_JSQR REG32(STM32_ADC1_BASE + 0x4C) +#define STM32_ADC1_JDR1 REG32(STM32_ADC1_BASE + 0x80) +#define STM32_ADC1_JDR2 REG32(STM32_ADC1_BASE + 0x84) +#define STM32_ADC1_JDR3 REG32(STM32_ADC1_BASE + 0x88) +#define STM32_ADC1_JDR4 REG32(STM32_ADC1_BASE + 0x8C) +#define STM32_ADC1_CCR REG32(STM32_ADC1_BASE + 0x308) + +/* --- USB --- */ +#define STM32_USB_BCDR_DPPU BIT(15) + +/* --- DMA --- */ + +/* + * Available DMA channels, numbered from 0. + * + * Note: The STM datasheet tends to number things from 1. We should ask + * the European elevator engineers to talk to MCU engineer counterparts + * about this. This means that if the datasheet refers to channel n, + * you need to use STM32_DMAC_CHn (=n-1) in the code. + * + * Also note that channels are overloaded; obviously you can only use one + * function on each channel at a time. + */ +enum dma_channel { + /* Channel numbers */ + STM32_DMAC_CH1 = 0, + STM32_DMAC_CH2 = 1, + STM32_DMAC_CH3 = 2, + STM32_DMAC_CH4 = 3, + STM32_DMAC_CH5 = 4, + STM32_DMAC_CH6 = 5, + STM32_DMAC_CH7 = 6, + /* + * Skip CH8, it should belong to DMA engine 1. + * Sharing code with STM32s that have 16 engines will be easier. + */ + STM32_DMAC_CH9 = 8, + STM32_DMAC_CH10 = 9, + STM32_DMAC_CH11 = 10, + STM32_DMAC_CH12 = 11, + STM32_DMAC_CH13 = 12, + STM32_DMAC_CH14 = 13, + STM32_DMAC_CH15 = 14, + + /* Channel functions */ + STM32_DMAC_SPI1_RX = STM32_DMAC_CH2, + STM32_DMAC_SPI1_TX = STM32_DMAC_CH3, + STM32_DMAC_USART1_TX = STM32_DMAC_CH14, + STM32_DMAC_USART1_RX = STM32_DMAC_CH15, + STM32_DMAC_SPI2_RX = STM32_DMAC_CH4, + STM32_DMAC_SPI2_TX = STM32_DMAC_CH5, + STM32_DMAC_SPI3_RX = STM32_DMAC_CH9, + STM32_DMAC_SPI3_TX = STM32_DMAC_CH10, + STM32_DMAC_COUNT = 15, +}; + +#define STM32_DMAC_PER_CTLR 8 + +/* Registers for a single channel of the DMA controller */ +struct stm32_dma_chan { + uint32_t ccr; /* Control */ + uint32_t cndtr; /* Number of data to transfer */ + uint32_t cpar; /* Peripheral address */ + uint32_t cmar; /* Memory address */ + uint32_t reserved; +}; + +/* Always use stm32_dma_chan_t so volatile keyword is included! */ +typedef volatile struct stm32_dma_chan stm32_dma_chan_t; + +/* Common code and header file must use this */ +typedef stm32_dma_chan_t dma_chan_t; + +/* Registers for the DMA controller */ +struct stm32_dma_regs { + uint32_t isr; + uint32_t ifcr; + stm32_dma_chan_t chan[STM32_DMAC_COUNT]; +}; + +/* Always use stm32_dma_regs_t so volatile keyword is included! */ +typedef volatile struct stm32_dma_regs stm32_dma_regs_t; + +#define STM32_DMA1_REGS ((stm32_dma_regs_t *)STM32_DMA1_BASE) + +#define STM32_DMA_CCR_CHANNEL(channel) (0) +#define STM32_DMA2_REGS ((stm32_dma_regs_t *)STM32_DMA2_BASE) +#define STM32_DMA_REGS(channel) \ + ((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_REGS : STM32_DMA2_REGS) +#define STM32_DMA_CSELR(channel) \ + REG32(((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_BASE : \ + STM32_DMA2_BASE) + \ + 0xA8) + +/* Bits for DMA controller regs (isr and ifcr) */ +#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR)) +#define STM32_DMA_ISR_MASK(channel, mask) \ + ((mask) << STM32_DMA_CH_OFFSET(channel)) +#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, BIT(0)) +#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, BIT(1)) +#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, BIT(2)) +#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, BIT(3)) +#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f) + +#define STM32_DMA_GIF BIT(0) +#define STM32_DMA_TCIF BIT(1) +#define STM32_DMA_HTIF BIT(2) +#define STM32_DMA_TEIF BIT(3) +#define STM32_DMA_ALL 0xf + +#define STM32_DMA_GET_ISR(channel) \ + ((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_ISR(channel, val) \ + (STM32_DMA_REGS(channel)->isr = \ + ((STM32_DMA_REGS(channel)->isr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) +#define STM32_DMA_GET_IFCR(channel) \ + ((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) & \ + STM32_DMA_ALL) +#define STM32_DMA_SET_IFCR(channel, val) \ + (STM32_DMA_REGS(channel)->ifcr = \ + ((STM32_DMA_REGS(channel)->ifcr & \ + ~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \ + (((val)&STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel)))) + +/* Bits for DMA channel regs */ +#define STM32_DMA_CCR_EN BIT(0) +#define STM32_DMA_CCR_TCIE BIT(1) +#define STM32_DMA_CCR_HTIE BIT(2) +#define STM32_DMA_CCR_TEIE BIT(3) +#define STM32_DMA_CCR_DIR BIT(4) +#define STM32_DMA_CCR_CIRC BIT(5) +#define STM32_DMA_CCR_PINC BIT(6) +#define STM32_DMA_CCR_MINC BIT(7) +#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 8) +#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 8) +#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 8) +#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 10) +#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 10) +#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 10) +#define STM32_DMA_CCR_PL_LOW (0 << 12) +#define STM32_DMA_CCR_PL_MEDIUM (1 << 12) +#define STM32_DMA_CCR_PL_HIGH (2 << 12) +#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12) +#define STM32_DMA_CCR_MEM2MEM BIT(14) + +/* The requests for the DMA1/DMA2 controllers are routed through DMAMUX. */ +/* DMAMUX registers */ +#define STM32_DMAMUX_CxCR(x) REG32(STM32_DMAMUX_BASE + 4 * (x)) +#define STM32_DMAMUX_CSR REG32(STM32_DMAMUX_BASE + 0x80) +#define STM32_DMAMUX_CFR REG32(STM32_DMAMUX_BASE + 0x84) +#define STM32_DMAMUX_RGxCR(x) REG32(STM32_DMAMUX_BASE + 0x100 + 4 * (x)) +#define STM32_DMAMUX_RGSR REG32(STM32_DMAMUX_BASE + 0x140) +#define STM32_DMAMUX_RGCFR REG32(STM32_DMAMUX_BASE + 0x144) + +enum dmamux1_request { + DMAMUX_REQ_ADC1 = 5, + DMAMUX_REQ_ADC2 = 6, + DMAMUX_REQ_DAC1 = 7, + DMAMUX_REQ_DAC2 = 8, + DMAMUX_REQ_TIM6_UP = 9, + DMAMUX_REQ_TIM7_UP = 10, + DMAMUX_REQ_SPI1_RX = 11, + DMAMUX_REQ_SPI1_TX = 12, + DMAMUX_REQ_SPI2_RX = 13, + DMAMUX_REQ_SPI2_TX = 14, + DMAMUX_REQ_SPI3_RX = 15, + DMAMUX_REQ_SPI3_TX = 16, + DMAMUX_REQ_I2C1_RX = 17, + DMAMUX_REQ_I2C1_TX = 18, + DMAMUX_REQ_I2C2_RX = 19, + DMAMUX_REQ_I2C2_TX = 20, + DMAMUX_REQ_I2C3_RX = 21, + DMAMUX_REQ_I2C3_TX = 22, + DMAMUX_REQ_I2C4_RX = 23, + DMAMUX_REQ_I2C4_TX = 24, + DMAMUX_REQ_USART1_RX = 25, + DMAMUX_REQ_USART1_TX = 26, + DMAMUX_REQ_USART2_RX = 27, + DMAMUX_REQ_USART2_TX = 28, + DMAMUX_REQ_USART3_RX = 29, + DMAMUX_REQ_USART3_TX = 30, + DMAMUX_REQ_UART4_RX = 31, + DMAMUX_REQ_UART4_TX = 32, + DMAMUX_REQ_UART5_RX = 33, + DMAMUX_REQ_UART5_TX = 34, + DMAMUX_REQ_LPUART1_RX = 35, + DMAMUX_REQ_LPUART1_TX = 36, + DMAMUX_REQ_SAI1_A = 37, + DMAMUX_REQ_SAI1_B = 38, + DMAMUX_REQ_SAI2_A = 39, + DMAMUX_REQ_SAI2_B = 40, + DMAMUX_REQ_OCTOSPI1 = 41, + DMAMUX_REQ_TIM1_CH1 = 42, + DMAMUX_REQ_TIM1_CH2 = 43, + DMAMUX_REQ_TIM1_CH3 = 44, + DMAMUX_REQ_TIM1_CH4 = 45, + DMAMUX_REQ_TIM1_UP = 46, + DMAMUX_REQ_TIM1_TRIG = 47, + DMAMUX_REQ_TIM1_COM = 48, + DMAMUX_REQ_TIM8_CH1 = 49, + DMAMUX_REQ_TIM8_CH2 = 50, + DMAMUX_REQ_TIM8_CH3 = 51, + DMAMUX_REQ_TIM8_CH4 = 52, + DMAMUX_REQ_TIM8_UP = 53, + DMAMUX_REQ_TIM8_TRIG = 54, + DMAMUX_REQ_TIM8_COM = 55, + DMAMUX_REQ_TIM2_CH1 = 56, + DMAMUX_REQ_TIM2_CH2 = 57, + DMAMUX_REQ_TIM2_CH3 = 58, + DMAMUX_REQ_TIM2_CH4 = 59, + DMAMUX_REQ_TIM2_UP = 60, + DMAMUX_REQ_TIM3_CH1 = 61, + DMAMUX_REQ_TIM3_CH2 = 62, + DMAMUX_REQ_TIM3_CH3 = 63, + DMAMUX_REQ_TIM3_CH4 = 64, + DMAMUX_REQ_TIM3_UP = 65, + DMAMUX_REQ_TIM3_TRIG = 66, + DMAMUX_REQ_TIM4_CH1 = 67, + DMAMUX_REQ_TIM4_CH2 = 68, + DMAMUX_REQ_TIM4_CH3 = 69, + DMAMUX_REQ_TIM4_CH4 = 70, + DMAMUX_REQ_TIM4_UP = 71, + DMAMUX_REQ_TIM5_CH1 = 72, + DMAMUX_REQ_TIM5_CH2 = 73, + DMAMUX_REQ_TIM5_CH3 = 74, + DMAMUX_REQ_TIM5_CH4 = 75, + DMAMUX_REQ_TIM5_UP = 76, + DMAMUX_REQ_TIM5_TRIG = 77, + DMAMUX_REQ_TIM15_CH1 = 78, + DMAMUX_REQ_TIM15_UP = 79, + DMAMUX_REQ_TIM15_TRIG = 80, + DMAMUX_REQ_TIM15_COM = 81, + DMAMUX_REQ_TIM16_CH1 = 82, + DMAMUX_REQ_TIM16_UP = 83, + DMAMUX_REQ_TIM17_CH1 = 84, + DMAMUX_REQ_TIM17_UP = 85, + DMAMUX_REQ_DFSDM1_FLT0 = 86, + DMAMUX_REQ_DFSDM1_FLT1 = 87, + DMAMUX_REQ_DFSDM1_FLT2 = 88, + DMAMUX_REQ_DFSDM1_FLT3 = 89, + DMAMUX_REQ_AES_IN = 90, + DMAMUX_REQ_AES_OUT = 91, + DMAMUX_REQ_HASH_IN = 92, + DMAMUX_REQ_USBPD_TX = 93, + DMAMUX_REQ_USBPD_RX = 94, +}; + +/* LPUART gets accessed as UART9 in STM32 uart module */ +#define STM32_USART9_BASE STM32_LPUART1_BASE +#define STM32_IRQ_USART9 STM32_IRQ_LPUART1 +#define DMAMUX_REQ_UART9_RX DMAMUX_REQ_LPUART1_RX +#define DMAMUX_REQ_UART9_TX DMAMUX_REQ_LPUART1_TX + +/* --- OCTOSPI --- */ + +#define STM32_OCTOSPI_CR REG32(STM32_OCTOSPI_BASE + 0x00) +#define STM32_OCTOSPI_DCR1 REG32(STM32_OCTOSPI_BASE + 0x08) +#define STM32_OCTOSPI_DCR2 REG32(STM32_OCTOSPI_BASE + 0x0C) +#define STM32_OCTOSPI_DCR3 REG32(STM32_OCTOSPI_BASE + 0x10) +#define STM32_OCTOSPI_DCR4 REG32(STM32_OCTOSPI_BASE + 0x14) +#define STM32_OCTOSPI_SR REG32(STM32_OCTOSPI_BASE + 0x20) +#define STM32_OCTOSPI_FCR REG32(STM32_OCTOSPI_BASE + 0x24) +#define STM32_OCTOSPI_DLR REG32(STM32_OCTOSPI_BASE + 0x40) +#define STM32_OCTOSPI_AR REG32(STM32_OCTOSPI_BASE + 0x48) +#define STM32_OCTOSPI_DR REG32(STM32_OCTOSPI_BASE + 0x50) +#define STM32_OCTOSPI_PSMKR REG32(STM32_OCTOSPI_BASE + 0x80) +#define STM32_OCTOSPI_PSMAR REG32(STM32_OCTOSPI_BASE + 0x88) +#define STM32_OCTOSPI_PIR REG32(STM32_OCTOSPI_BASE + 0x90) +#define STM32_OCTOSPI_CCR REG32(STM32_OCTOSPI_BASE + 0x100) +#define STM32_OCTOSPI_TCR REG32(STM32_OCTOSPI_BASE + 0x108) +#define STM32_OCTOSPI_IR REG32(STM32_OCTOSPI_BASE + 0x110) +#define STM32_OCTOSPI_ABR REG32(STM32_OCTOSPI_BASE + 0x120) +#define STM32_OCTOSPI_LPTR REG32(STM32_OCTOSPI_BASE + 0x130) +#define STM32_OCTOSPI_WPCCR REG32(STM32_OCTOSPI_BASE + 0x140) +#define STM32_OCTOSPI_WPTCR REG32(STM32_OCTOSPI_BASE + 0x148) +#define STM32_OCTOSPI_WPIR REG32(STM32_OCTOSPI_BASE + 0x150) +#define STM32_OCTOSPI_WPABR REG32(STM32_OCTOSPI_BASE + 0x160) +#define STM32_OCTOSPI_WCCR REG32(STM32_OCTOSPI_BASE + 0x180) +#define STM32_OCTOSPI_WTCR REG32(STM32_OCTOSPI_BASE + 0x188) +#define STM32_OCTOSPI_WIR REG32(STM32_OCTOSPI_BASE + 0x190) +#define STM32_OCTOSPI_WABR REG32(STM32_OCTOSPI_BASE + 0x1A0) +#define STM32_OCTOSPI_HLCR REG32(STM32_OCTOSPI_BASE + 0x200) + +/* Bit values for STM32_OCTOSPI_CR */ +#define STM32_OCTOSPI_CR_FMODE_POS 28U +#define STM32_OCTOSPI_CR_FMODE_MSK (0x3UL << STM32_OCTOSPI_CR_FMODE_POS) +#define STM32_OCTOSPI_CR_FMODE STM32_OCTOSPI_FMODE_MSK +#define STM32_OCTOSPI_CR_FMODE_IND_WRITE (0x0UL << STM32_OCTOSPI_CR_FMODE_POS) +#define STM32_OCTOSPI_CR_FMODE_IND_READ (0x1UL << STM32_OCTOSPI_CR_FMODE_POS) +#define STM32_OCTOSPI_CR_FMODE_AUTO_POLL (0x2UL << STM32_OCTOSPI_CR_FMODE_POS) +#define STM32_OCTOSPI_CR_FMODE_MEM_MAPPED (0x3UL << STM32_OCTOSPI_CR_FMODE_POS) + +#define STM32_OCTOSPI_CR_PMM_POS 23U +#define STM32_OCTOSPI_CR_PMM_MSK (0x1UL << STM32_OCTOSPI_CR_PMM_POS) +#define STM32_OCTOSPI_CR_PMM_AND 0 +#define STM32_OCTOSPI_CR_PMM_OR STM32_OCTOSPI_CR_PMM_MSK + +#define STM32_OCTOSPI_CR_APMS_POS 22U +#define STM32_OCTOSPI_CR_APMS_MSK (0x1UL << STM32_OCTOSPI_CR_APMS_POS) +#define STM32_OCTOSPI_CR_APMS STM32_OCTOSPI_CR_APMS_MSK + +#define STM32_OCTOSPI_CR_TOIE_POS 20U +#define STM32_OCTOSPI_CR_TOIE_MSK (0x1UL << STM32_OCTOSPI_CR_TOIE_POS) +#define STM32_OCTOSPI_CR_TOIE STM32_OCTOSPI_CR_TOIE_MSK + +#define STM32_OCTOSPI_CR_SMIE_POS 19U +#define STM32_OCTOSPI_CR_SMIE_MSK (0x1UL << STM32_OCTOSPI_CR_SMIE_POS) +#define STM32_OCTOSPI_CR_SMIE STM32_OCTOSPI_CR_SMIE_MSK + +#define STM32_OCTOSPI_CR_FTIE_POS 18U +#define STM32_OCTOSPI_CR_FTIE_MSK (0x1UL << STM32_OCTOSPI_CR_FTIE_POS) +#define STM32_OCTOSPI_CR_FTIE STM32_OCTOSPI_CR_FTIE_MSK + +#define STM32_OCTOSPI_CR_TCIE_POS 17U +#define STM32_OCTOSPI_CR_TCIE_MSK (0x1UL << STM32_OCTOSPI_CR_TCIE_POS) +#define STM32_OCTOSPI_CR_TCIE STM32_OCTOSPI_CR_TCIE_MSK + +#define STM32_OCTOSPI_CR_TEIE_POS 16U +#define STM32_OCTOSPI_CR_TEIE_MSK (0x1UL << STM32_OCTOSPI_CR_TEIE_POS) +#define STM32_OCTOSPI_CR_TEIE STM32_OCTOSPI_CR_TEIE_MSK + +#define STM32_OCTOSPI_CR_FTHRES_POS 8U +#define STM32_OCTOSPI_CR_FTHRES_MSK (0x1FUL << STM32_OCTOSPI_CR_FTHRES_POS) + +#define STM32_OCTOSPI_CR_MSEL_POS 7U +#define STM32_OCTOSPI_CR_MSEL_MSK (0x1UL << STM32_OCTOSPI_CR_MSEL_POS) +#define STM32_OCTOSPI_CR_MSEL_FLASH1 0 +#define STM32_OCTOSPI_CR_MSEL_FLASH2 STM32_OCTOSPI_CR_MSEL_MSK + +#define STM32_OCTOSPI_CR_DMM_POS 6U +#define STM32_OCTOSPI_CR_DMM_MSK (0x1UL << STM32_OCTOSPI_CR_DMM_POS) +#define STM32_OCTOSPI_CR_DMM STM32_OCTOSPI_CR_DMM_MSK + +#define STM32_OCTOSPI_CR_TCEN_POS 3U +#define STM32_OCTOSPI_CR_TCEN_MSK (0x1UL << STM32_OCTOSPI_CR_TCEN_POS) +#define STM32_OCTOSPI_CR_TCEN STM32_OCTOSPI_CR_TCEN_MSK + +#define STM32_OCTOSPI_CR_DMAEN_POS 2U +#define STM32_OCTOSPI_CR_DMAEN_MSK (0x1UL << STM32_OCTOSPI_CR_DMAEN_POS) +#define STM32_OCTOSPI_CR_DMAEN STM32_OCTOSPI_CR_DMAEN_MSK + +#define STM32_OCTOSPI_CR_ABORT_POS 1U +#define STM32_OCTOSPI_CR_ABORT_MSK (0x1UL << STM32_OCTOSPI_CR_ABORT_POS) +#define STM32_OCTOSPI_CR_ABORT STM32_OCTOSPI_CR_ABORT_MSK + +#define STM32_OCTOSPI_CR_EN_POS 0U +#define STM32_OCTOSPI_CR_EN_MSK (0x1UL << STM32_OCTOSPI_CR_EN_POS) +#define STM32_OCTOSPI_CR_EN STM32_OCTOSPI_CR_EN_MSK + +/* Bit values for STM32_OCTOSPI_DCR1 */ +#define STM32_OCTOSPI_DCR1_MTYP_POS 24U +#define STM32_OCTOSPI_DCR1_MTYP_MSK (0x7UL << STM32_OCTOSPI_DCR1_MTYP_POS) +#define STM32_OCTOSPI_DCR1_MTYP_MICROS (0x0UL << STM32_OCTOSPI_DCR1_MTYP_POS) +#define STM32_OCTOSPI_DCR1_MTYP_MACRONIX (0x1UL << STM32_OCTOSPI_DCR1_MTYP_POS) +#define STM32_OCTOSPI_DCR1_MTYP_STANDARD (0x2UL << STM32_OCTOSPI_DCR1_MTYP_POS) +#define STM32_OCTOSPI_DCR1_MTYP_MACRONIX_RAM \ + (0x3UL << STM32_OCTOSPI_DCR1_MTYP_POS) +#define STM32_OCTOSPI_DCR1_MTYP_HYPERBUS_MEM \ + (0x4UL << STM32_OCTOSPI_DCR1_MTYP_POS) +#define STM32_OCTOSPI_DCR1_MTYP_HYPERBUS_REG \ + (0x5UL << STM32_OCTOSPI_DCR1_MTYP_POS) + +#define STM32_OCTOSPI_DCR1_DEVSIZE_POS 16U +#define STM32_OCTOSPI_DCR1_DEVSIZE_MSK \ + (0x1FUL << STM32_OCTOSPI_DCR1_DEVSIZE_POS) + +#define STM32_OCTOSPI_DCR1_CSHT_POS 8U +#define STM32_OCTOSPI_DCR1_CSHT_MSK (0x1UL << STM32_OCTOSPI_DCR1_CSHT_POS) +#define STM32_OCTOSPI_DCR1_CSHT_1 (0x0UL << STM32_OCTOSPI_DCR1_CSHT_POS) +#define STM32_OCTOSPI_DCR1_CSHT_2 (0x1UL << STM32_OCTOSPI_DCR1_CSHT_POS) +#define STM32_OCTOSPI_DCR1_CSHT_3 (0x2UL << STM32_OCTOSPI_DCR1_CSHT_POS) +#define STM32_OCTOSPI_DCR1_CSHT_4 (0x3UL << STM32_OCTOSPI_DCR1_CSHT_POS) +#define STM32_OCTOSPI_DCR1_CSHT_5 (0x4UL << STM32_OCTOSPI_DCR1_CSHT_POS) +#define STM32_OCTOSPI_DCR1_CSHT_6 (0x5UL << STM32_OCTOSPI_DCR1_CSHT_POS) +#define STM32_OCTOSPI_DCR1_CSHT_7 (0x6UL << STM32_OCTOSPI_DCR1_CSHT_POS) +#define STM32_OCTOSPI_DCR1_CSHT_8 (0x7UL << STM32_OCTOSPI_DCR1_CSHT_POS) + +#define STM32_OCTOSPI_DCR1_DLYBYP_POS 3U +#define STM32_OCTOSPI_DCR1_DLYBYP_MSK (0x1UL << STM32_OCTOSPI_DCR1_DLYBYP_POS) +#define STM32_OCTOSPI_DCR1_DLYBYP STM32_OCTOSPI_DCR1_DLYBYP_MSK + +#define STM32_OCTOSPI_DCR1_FRCK_POS 1U +#define STM32_OCTOSPI_DCR1_FRCK_MSK (0x1UL << STM32_OCTOSPI_DCR1_FRCK_POS) +#define STM32_OCTOSPI_DCR1_FRCK STM32_OCTOSPI_DCR1_FRCK_MSK + +#define STM32_OCTOSPI_DCR1_CKMODE_POS 0U +#define STM32_OCTOSPI_DCR1_CKMODE_MSK (0x1UL << STM32_OCTOSPI_DCR1_CKMODE_POS) +#define STM32_OCTOSPI_DCR1_CKMODE_LOW 0 +#define STM32_OCTOSPI_DCR1_CKMODE_HIGH STM32_OCTOSPI_DCR1_CKMODE_MSK + +/* Bit values for STM32_OCTOSPI_DCR2 */ +#define STM32_OCTOSPI_DCR2_WRAPSIZE_POS 16U +#define STM32_OCTOSPI_DCR2_WRAPSIZE_MSK \ + (0x7UL << STM32_OCTOSPI_DCR2_WRAPSIZE_POS) + +#define STM32_OCTOSPI_DCR2_PRESCALER_POS 0U +#define STM32_OCTOSPI_DCR2_PRESCALER_MSK \ + (0xFFUL << STM32_OCTOSPI_DCR2_PRESCALER_POS) + +/* Bit values for STM32_OCTOSPI_DCR3 */ +#define STM32_OCTOSPI_DCR3_CSBOUND_POS 16U +#define STM32_OCTOSPI_DCR3_CSBOUND_MSK \ + (0x1FUL << STM32_OCTOSPI_DCR3_CSBOUND_POS) +#define STM32_OCTOSPI_DCR3_CSBOUND_DISABLED 0 + +/* Bit values for STM32_OCTOSPI_SR */ +#define STM32_OCTOSPI_SR_FLEVEL_POS 8U +#define STM32_OCTOSPI_SR_FLEVEL_MSK (0x3FUL << STM32_OCTOSPI_SR_FLEVEL_POS) + +#define STM32_OCTOSPI_SR_BUSY_POS 5U +#define STM32_OCTOSPI_SR_BUSY_MSK (0x1UL << STM32_OCTOSPI_SR_BUSY_POS) +#define STM32_OCTOSPI_SR_BUSY STM32_OCTOSPI_SR_BUSY_MSK + +#define STM32_OCTOSPI_SR_TOF_POS 4U +#define STM32_OCTOSPI_SR_TOF_MSK (0x1UL << STM32_OCTOSPI_SR_TOF_POS) +#define STM32_OCTOSPI_SR_TOF STM32_OCTOSPI_SR_TOF_MSK + +#define STM32_OCTOSPI_SR_SMF_POS 3U +#define STM32_OCTOSPI_SR_SMF_MSK (0x1UL << STM32_OCTOSPI_SR_SMF_POS) +#define STM32_OCTOSPI_SR_SMF STM32_OCTOSPI_SR_SMF_MSK + +#define STM32_OCTOSPI_SR_FTF_POS 2U +#define STM32_OCTOSPI_SR_FTF_MSK (0x1UL << STM32_OCTOSPI_SR_FTF_POS) +#define STM32_OCTOSPI_SR_FTF STM32_OCTOSPI_SR_FTF_MSK + +#define STM32_OCTOSPI_SR_TCF_POS 1U +#define STM32_OCTOSPI_SR_TCF_MSK (0x1UL << STM32_OCTOSPI_SR_TCF_POS) +#define STM32_OCTOSPI_SR_TCF STM32_OCTOSPI_SR_TCF_MSK + +#define STM32_OCTOSPI_SR_TEF_POS 0U +#define STM32_OCTOSPI_SR_TEF_MSK (0x1UL << STM32_OCTOSPI_SR_TEF_POS) +#define STM32_OCTOSPI_SR_TEF STM32_OCTOSPI_SR_TEF_MSK + +/* Bit values for STM32_OCTOSPI_FCR */ +#define STM32_OCTOSPI_FCR_CTOF_POS 4U +#define STM32_OCTOSPI_FCR_CTOF_MSK (0x1UL << STM32_OCTOSPI_FCR_CTOF_POS) +#define STM32_OCTOSPI_FCR_CTOF STM32_OCTOSPI_FCR_CTOF_MSK + +#define STM32_OCTOSPI_FCR_CSMF_POS 3U +#define STM32_OCTOSPI_FCR_CSMF_MSK (0x1UL << STM32_OCTOSPI_FCR_CSMF_POS) +#define STM32_OCTOSPI_FCR_CSMF STM32_OCTOSPI_FCR_CSMF_MSK + +#define STM32_OCTOSPI_FCR_CTCF_POS 1U +#define STM32_OCTOSPI_FCR_CTCF_MSK (0x1UL << STM32_OCTOSPI_FCR_CTCF_POS) +#define STM32_OCTOSPI_FCR_CTCF STM32_OCTOSPI_FCR_CTCF_MSK + +#define STM32_OCTOSPI_FCR_CTEF_POS 0U +#define STM32_OCTOSPI_FCR_CTEF_MSK (0x1UL << STM32_OCTOSPI_FCR_CTEF_POS) +#define STM32_OCTOSPI_FCR_CTEF STM32_OCTOSPI_FCR_CTEF_MSK + +/* Bit values for STM32_OCTOSPI_CCR */ +#define STM32_OCTOSPI_CCR_SIOO_POS 31U +#define STM32_OCTOSPI_CCR_SIOO_MSK (0x1UL << STM32_OCTOSPI_FCR_SIOO_POS) +#define STM32_OCTOSPI_CCR_SIOO STM32_OCTOSPI_FCR_SIOO_MSK + +#define STM32_OCTOSPI_CCR_DQSE_POS 29U +#define STM32_OCTOSPI_CCR_DQSE_MSK (0x1UL << STM32_OCTOSPI_FCR_DQSE_POS) +#define STM32_OCTOSPI_CCR_DQSE STM32_OCTOSPI_FCR_DQSE_MSK + +#define STM32_OCTOSPI_CCR_DDTR_POS 27U +#define STM32_OCTOSPI_CCR_DDTR_MSK (0x1UL << STM32_OCTOSPI_CCR_DDTR_POS) +#define STM32_OCTOSPI_CCR_DDTR STM32_OCTOSPI_CCR_DDTR_MSK + +#define STM32_OCTOSPI_CCR_DMODE_POS 24U +#define STM32_OCTOSPI_CCR_DMODE_MSK (0x1UL << STM32_OCTOSPI_CCR_DMODE_POS) +#define STM32_OCTOSPI_CCR_DMODE_NONE (0UL << STM32_OCTOSPI_CCR_DMODE_POS) +#define STM32_OCTOSPI_CCR_DMODE_1WIRE (1UL << STM32_OCTOSPI_CCR_DMODE_POS) +#define STM32_OCTOSPI_CCR_DMODE_2WIRE (2UL << STM32_OCTOSPI_CCR_DMODE_POS) +#define STM32_OCTOSPI_CCR_DMODE_4WIRE (3UL << STM32_OCTOSPI_CCR_DMODE_POS) +#define STM32_OCTOSPI_CCR_DMODE_8WIRE (4UL << STM32_OCTOSPI_CCR_DMODE_POS) + +#define STM32_OCTOSPI_CCR_ABSIZE_POS 20U +#define STM32_OCTOSPI_CCR_ABSIZE_MSK (0x1UL << STM32_OCTOSPI_CCR_ABSIZE_POS) +#define STM32_OCTOSPI_CCR_ABSIZE_1BYTE (0UL << STM32_OCTOSPI_CCR_ABSIZE_POS) +#define STM32_OCTOSPI_CCR_ABSIZE_2BYTES (1UL << STM32_OCTOSPI_CCR_ABSIZE_POS) +#define STM32_OCTOSPI_CCR_ABSIZE_3BYTES (2UL << STM32_OCTOSPI_CCR_ABSIZE_POS) +#define STM32_OCTOSPI_CCR_ABSIZE_4BYTES (3UL << STM32_OCTOSPI_CCR_ABSIZE_POS) + +#define STM32_OCTOSPI_CCR_ABDTR_POS 19U +#define STM32_OCTOSPI_CCR_ABDTR_MSK (0x1UL << STM32_OCTOSPI_CCR_ABDTR_POS) +#define STM32_OCTOSPI_CCR_ABDTR STM32_OCTOSPI_CCR_ABDTR_MSK + +#define STM32_OCTOSPI_CCR_ABMODE_POS 16U +#define STM32_OCTOSPI_CCR_ABMODE_MSK (0x1UL << STM32_OCTOSPI_CCR_ABMODE_POS) +#define STM32_OCTOSPI_CCR_ABMODE_NONE (0UL << STM32_OCTOSPI_CCR_ABMODE_POS) +#define STM32_OCTOSPI_CCR_ABMODE_1WIRE (1UL << STM32_OCTOSPI_CCR_ABMODE_POS) +#define STM32_OCTOSPI_CCR_ABMODE_2WIRE (2UL << STM32_OCTOSPI_CCR_ABMODE_POS) +#define STM32_OCTOSPI_CCR_ABMODE_4WIRE (3UL << STM32_OCTOSPI_CCR_ABMODE_POS) +#define STM32_OCTOSPI_CCR_ABMODE_8WIRE (4UL << STM32_OCTOSPI_CCR_ABMODE_POS) + +#define STM32_OCTOSPI_CCR_ADSIZE_POS 12U +#define STM32_OCTOSPI_CCR_ADSIZE_MSK (0x1UL << STM32_OCTOSPI_CCR_ADSIZE_POS) +#define STM32_OCTOSPI_CCR_ADSIZE_1BYTE (0UL << STM32_OCTOSPI_CCR_ADSIZE_POS) +#define STM32_OCTOSPI_CCR_ADSIZE_2BYTES (1UL << STM32_OCTOSPI_CCR_ADSIZE_POS) +#define STM32_OCTOSPI_CCR_ADSIZE_3BYTES (2UL << STM32_OCTOSPI_CCR_ADSIZE_POS) +#define STM32_OCTOSPI_CCR_ADSIZE_4BYTES (3UL << STM32_OCTOSPI_CCR_ADSIZE_POS) + +#define STM32_OCTOSPI_CCR_ADDTR_POS 11U +#define STM32_OCTOSPI_CCR_ADDTR_MSK (0x1UL << STM32_OCTOSPI_CCR_ADDTR_POS) +#define STM32_OCTOSPI_CCR_ADDTR STM32_OCTOSPI_CCR_ADDTR_MSK + +#define STM32_OCTOSPI_CCR_ADMODE_POS 8U +#define STM32_OCTOSPI_CCR_ADMODE_MSK (0x1UL << STM32_OCTOSPI_CCR_ADMODE_POS) +#define STM32_OCTOSPI_CCR_ADMODE_NONE (0UL << STM32_OCTOSPI_CCR_ADMODE_POS) +#define STM32_OCTOSPI_CCR_ADMODE_1WIRE (1UL << STM32_OCTOSPI_CCR_ADMODE_POS) +#define STM32_OCTOSPI_CCR_ADMODE_2WIRE (2UL << STM32_OCTOSPI_CCR_ADMODE_POS) +#define STM32_OCTOSPI_CCR_ADMODE_4WIRE (3UL << STM32_OCTOSPI_CCR_ADMODE_POS) +#define STM32_OCTOSPI_CCR_ADMODE_8WIRE (4UL << STM32_OCTOSPI_CCR_ADMODE_POS) + +#define STM32_OCTOSPI_CCR_ISIZE_POS 4U +#define STM32_OCTOSPI_CCR_ISIZE_MSK (0x1UL << STM32_OCTOSPI_CCR_ISIZE_POS) +#define STM32_OCTOSPI_CCR_ISIZE_1BYTE (0UL << STM32_OCTOSPI_CCR_ISIZE_POS) +#define STM32_OCTOSPI_CCR_ISIZE_2BYTES (1UL << STM32_OCTOSPI_CCR_ISIZE_POS) +#define STM32_OCTOSPI_CCR_ISIZE_3BYTES (2UL << STM32_OCTOSPI_CCR_ISIZE_POS) +#define STM32_OCTOSPI_CCR_ISIZE_4BYTES (3UL << STM32_OCTOSPI_CCR_ISIZE_POS) + +#define STM32_OCTOSPI_CCR_IDTR_POS 3U +#define STM32_OCTOSPI_CCR_IDTR_MSK (0x1UL << STM32_OCTOSPI_CCR_IDTR_POS) +#define STM32_OCTOSPI_CCR_IDTR STM32_OCTOSPI_CCR_IDTR_MSK + +#define STM32_OCTOSPI_CCR_IMODE_POS 0U +#define STM32_OCTOSPI_CCR_IMODE_MSK (0x1UL << STM32_OCTOSPI_CCR_IMODE_POS) +#define STM32_OCTOSPI_CCR_IMODE_NONE (0UL << STM32_OCTOSPI_CCR_IMODE_POS) +#define STM32_OCTOSPI_CCR_IMODE_1WIRE (1UL << STM32_OCTOSPI_CCR_IMODE_POS) +#define STM32_OCTOSPI_CCR_IMODE_2WIRE (2UL << STM32_OCTOSPI_CCR_IMODE_POS) +#define STM32_OCTOSPI_CCR_IMODE_4WIRE (3UL << STM32_OCTOSPI_CCR_IMODE_POS) +#define STM32_OCTOSPI_CCR_IMODE_8WIRE (4UL << STM32_OCTOSPI_CCR_IMODE_POS) + +/* Bit values for STM32_OCTOSPI_TCR */ +#define STM32_OCTOSPI_TCR_SSHIFT_POS 30U +#define STM32_OCTOSPI_TCR_SSHIFT_MSK (0x1UL << STM32_OCTOSPI_TCR_SSHIFT_POS) +#define STM32_OCTOSPI_TCR_SSHIFT STM32_OCTOSPI_TCR_SSHIFT_MSK + +#define STM32_OCTOSPI_TCR_DHQC_POS 28U +#define STM32_OCTOSPI_TCR_DHQC_MSK (0x1UL << STM32_OCTOSPI_TCR_DHQC_POS) +#define STM32_OCTOSPI_TCR_DHQC STM32_OCTOSPI_TCR_DHQC_MSK + +#define STM32_OCTOSPI_TCR_DCYC_POS 0U +#define STM32_OCTOSPI_TCR_DCYC_MSK (0x1FUL << STM32_OCTOSPI_TCR_DCYC_POS) + +#endif /* !__ASSEMBLER__ */ diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index 574921c63e..1ec4370ef1 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -46,424 +46,429 @@ #include "common.h" #include "compile_time_macros.h" - #ifndef __ASSEMBLER__ /* Register definitions */ /* --- USART --- */ -#define STM32_USART_BASE(n) CONCAT3(STM32_USART, n, _BASE) +#define STM32_USART_BASE(n) CONCAT3(STM32_USART, n, _BASE) #define STM32_USART_REG(base, offset) REG32((base) + (offset)) -#define STM32_IRQ_USART(n) CONCAT2(STM32_IRQ_USART, n) +#define STM32_IRQ_USART(n) CONCAT2(STM32_IRQ_USART, n) /* --- TIMERS --- */ -#define STM32_TIM_BASE(n) CONCAT3(STM32_TIM, n, _BASE) - -#define STM32_TIM_REG(n, offset) \ - REG16(STM32_TIM_BASE(n) + (offset)) -#define STM32_TIM_REG32(n, offset) \ - REG32(STM32_TIM_BASE(n) + (offset)) - -#define STM32_TIM_CR1(n) STM32_TIM_REG(n, 0x00) -#define STM32_TIM_CR1_CEN BIT(0) -#define STM32_TIM_CR2(n) STM32_TIM_REG(n, 0x04) -#define STM32_TIM_SMCR(n) STM32_TIM_REG(n, 0x08) -#define STM32_TIM_DIER(n) STM32_TIM_REG(n, 0x0C) -#define STM32_TIM_SR(n) STM32_TIM_REG(n, 0x10) -#define STM32_TIM_EGR(n) STM32_TIM_REG(n, 0x14) -#define STM32_TIM_EGR_UG BIT(0) -#define STM32_TIM_CCMR1(n) STM32_TIM_REG(n, 0x18) -#define STM32_TIM_CCMR1_OC1PE BIT(2) +#define STM32_TIM_BASE(n) CONCAT3(STM32_TIM, n, _BASE) + +#define STM32_TIM_REG(n, offset) REG16(STM32_TIM_BASE(n) + (offset)) +#define STM32_TIM_REG32(n, offset) REG32(STM32_TIM_BASE(n) + (offset)) + +#define STM32_TIM_CR1(n) STM32_TIM_REG(n, 0x00) +#define STM32_TIM_CR1_CEN BIT(0) +#define STM32_TIM_CR2(n) STM32_TIM_REG(n, 0x04) +#define STM32_TIM_SMCR(n) STM32_TIM_REG(n, 0x08) +#define STM32_TIM_DIER(n) STM32_TIM_REG(n, 0x0C) +#define STM32_TIM_SR(n) STM32_TIM_REG(n, 0x10) +#define STM32_TIM_EGR(n) STM32_TIM_REG(n, 0x14) +#define STM32_TIM_EGR_UG BIT(0) +#define STM32_TIM_CCMR1(n) STM32_TIM_REG(n, 0x18) +#define STM32_TIM_CCMR1_OC1PE BIT(2) /* Use in place of TIM_CCMR1_OC1M_0 through 2 from STM documentation. */ -#define STM32_TIM_CCMR1_OC1M(n) (((n) & 0x7) << 4) -#define STM32_TIM_CCMR1_OC1M_MASK STM32_TIM_CCMR1_OC1M(~0) -#define STM32_TIM_CCMR1_OC1M_FROZEN STM32_TIM_CCMR1_OC1M(0x0) -#define STM32_TIM_CCMR1_OC1M_ACTIVE_ON_MATCH STM32_TIM_CCMR1_OC1M(0x1) +#define STM32_TIM_CCMR1_OC1M(n) (((n)&0x7) << 4) +#define STM32_TIM_CCMR1_OC1M_MASK STM32_TIM_CCMR1_OC1M(~0) +#define STM32_TIM_CCMR1_OC1M_FROZEN STM32_TIM_CCMR1_OC1M(0x0) +#define STM32_TIM_CCMR1_OC1M_ACTIVE_ON_MATCH STM32_TIM_CCMR1_OC1M(0x1) #define STM32_TIM_CCMR1_OC1M_INACTIVE_ON_MATCH STM32_TIM_CCMR1_OC1M(0x2) -#define STM32_TIM_CCMR1_OC1M_TOGGLE STM32_TIM_CCMR1_OC1M(0x3) -#define STM32_TIM_CCMR1_OC1M_FORCE_INACTIVE STM32_TIM_CCMR1_OC1M(0x4) -#define STM32_TIM_CCMR1_OC1M_FORCE_ACTIVE STM32_TIM_CCMR1_OC1M(0x5) -#define STM32_TIM_CCMR1_OC1M_PWM_MODE_1 STM32_TIM_CCMR1_OC1M(0x6) -#define STM32_TIM_CCMR1_OC1M_PWM_MODE_2 STM32_TIM_CCMR1_OC1M(0x7) -#define STM32_TIM_CCMR2(n) STM32_TIM_REG(n, 0x1C) -#define STM32_TIM_CCER(n) STM32_TIM_REG(n, 0x20) -#define STM32_TIM_CCER_CC1E BIT(0) -#define STM32_TIM_CCER_CC1P BIT(1) -#define STM32_TIM_CCER_CC1NE BIT(2) -#define STM32_TIM_CCER_CC1NP BIT(3) -#define STM32_TIM_CNT(n) STM32_TIM_REG(n, 0x24) -#define STM32_TIM_PSC(n) STM32_TIM_REG(n, 0x28) -#define STM32_TIM_ARR(n) STM32_TIM_REG(n, 0x2C) -#define STM32_TIM_RCR(n) STM32_TIM_REG(n, 0x30) -#define STM32_TIM_CCR1(n) STM32_TIM_REG(n, 0x34) -#define STM32_TIM_CCR2(n) STM32_TIM_REG(n, 0x38) -#define STM32_TIM_CCR3(n) STM32_TIM_REG(n, 0x3C) -#define STM32_TIM_CCR4(n) STM32_TIM_REG(n, 0x40) -#define STM32_TIM_BDTR(n) STM32_TIM_REG(n, 0x44) -#define STM32_TIM_BDTR_MOE BIT(15) -#define STM32_TIM_DCR(n) STM32_TIM_REG(n, 0x48) -#define STM32_TIM_DMAR(n) STM32_TIM_REG(n, 0x4C) -#define STM32_TIM_OR(n) STM32_TIM_REG(n, 0x50) - -#define STM32_TIM_CCRx(n, x) STM32_TIM_REG(n, 0x34 + ((x) - 1) * 4) - -#define STM32_TIM32_CNT(n) STM32_TIM_REG32(n, 0x24) -#define STM32_TIM32_ARR(n) STM32_TIM_REG32(n, 0x2C) -#define STM32_TIM32_CCR1(n) STM32_TIM_REG32(n, 0x34) -#define STM32_TIM32_CCR2(n) STM32_TIM_REG32(n, 0x38) -#define STM32_TIM32_CCR3(n) STM32_TIM_REG32(n, 0x3C) -#define STM32_TIM32_CCR4(n) STM32_TIM_REG32(n, 0x40) +#define STM32_TIM_CCMR1_OC1M_TOGGLE STM32_TIM_CCMR1_OC1M(0x3) +#define STM32_TIM_CCMR1_OC1M_FORCE_INACTIVE STM32_TIM_CCMR1_OC1M(0x4) +#define STM32_TIM_CCMR1_OC1M_FORCE_ACTIVE STM32_TIM_CCMR1_OC1M(0x5) +#define STM32_TIM_CCMR1_OC1M_PWM_MODE_1 STM32_TIM_CCMR1_OC1M(0x6) +#define STM32_TIM_CCMR1_OC1M_PWM_MODE_2 STM32_TIM_CCMR1_OC1M(0x7) +#define STM32_TIM_CCMR2(n) STM32_TIM_REG(n, 0x1C) +#define STM32_TIM_CCER(n) STM32_TIM_REG(n, 0x20) +#define STM32_TIM_CCER_CC1E BIT(0) +#define STM32_TIM_CCER_CC1P BIT(1) +#define STM32_TIM_CCER_CC1NE BIT(2) +#define STM32_TIM_CCER_CC1NP BIT(3) +#define STM32_TIM_CNT(n) STM32_TIM_REG(n, 0x24) +#define STM32_TIM_PSC(n) STM32_TIM_REG(n, 0x28) +#define STM32_TIM_ARR(n) STM32_TIM_REG(n, 0x2C) +#define STM32_TIM_RCR(n) STM32_TIM_REG(n, 0x30) +#define STM32_TIM_CCR1(n) STM32_TIM_REG(n, 0x34) +#define STM32_TIM_CCR2(n) STM32_TIM_REG(n, 0x38) +#define STM32_TIM_CCR3(n) STM32_TIM_REG(n, 0x3C) +#define STM32_TIM_CCR4(n) STM32_TIM_REG(n, 0x40) +#define STM32_TIM_BDTR(n) STM32_TIM_REG(n, 0x44) +#define STM32_TIM_BDTR_MOE BIT(15) +#define STM32_TIM_DCR(n) STM32_TIM_REG(n, 0x48) +#define STM32_TIM_DMAR(n) STM32_TIM_REG(n, 0x4C) +#define STM32_TIM_OR(n) STM32_TIM_REG(n, 0x50) + +#define STM32_TIM_CCRx(n, x) STM32_TIM_REG(n, 0x34 + ((x)-1) * 4) + +#define STM32_TIM32_CNT(n) STM32_TIM_REG32(n, 0x24) +#define STM32_TIM32_ARR(n) STM32_TIM_REG32(n, 0x2C) +#define STM32_TIM32_CCR1(n) STM32_TIM_REG32(n, 0x34) +#define STM32_TIM32_CCR2(n) STM32_TIM_REG32(n, 0x38) +#define STM32_TIM32_CCR3(n) STM32_TIM_REG32(n, 0x3C) +#define STM32_TIM32_CCR4(n) STM32_TIM_REG32(n, 0x40) /* Timer registers as struct */ struct timer_ctlr { - unsigned cr1; - unsigned cr2; - unsigned smcr; - unsigned dier; + unsigned int cr1; + unsigned int cr2; + unsigned int smcr; + unsigned int dier; - unsigned sr; - unsigned egr; - unsigned ccmr1; - unsigned ccmr2; + unsigned int sr; + unsigned int egr; + unsigned int ccmr1; + unsigned int ccmr2; - unsigned ccer; - unsigned cnt; - unsigned psc; - unsigned arr; + unsigned int ccer; + unsigned int cnt; + unsigned int psc; + unsigned int arr; - unsigned ccr[5]; /* ccr[0] = reserved30 */ + unsigned int ccr[5]; /* ccr[0] = reserved30 */ - unsigned bdtr; - unsigned dcr; - unsigned dmar; + unsigned int bdtr; + unsigned int dcr; + unsigned int dmar; - unsigned or; + unsigned int option_register; }; /* Must be volatile, or compiler optimizes out repeated accesses */ typedef volatile struct timer_ctlr timer_ctlr_t; +#define IRQ_TIM(n) CONCAT2(STM32_IRQ_TIM, n) + /* --- Low power timers --- */ -#define STM32_LPTIM_BASE(n) CONCAT3(STM32_LPTIM, n, _BASE) - -#define STM32_LPTIM_REG(n, offset) REG32(STM32_LPTIM_BASE(n) + (offset)) - -#define STM32_LPTIM_ISR(n) STM32_LPTIM_REG(n, 0x00) -#define STM32_LPTIM_ICR(n) STM32_LPTIM_REG(n, 0x04) -#define STM32_LPTIM_IER(n) STM32_LPTIM_REG(n, 0x08) -#define STM32_LPTIM_INT_DOWN BIT(6) -#define STM32_LPTIM_INT_UP BIT(5) -#define STM32_LPTIM_INT_ARROK BIT(4) -#define STM32_LPTIM_INT_CMPOK BIT(3) -#define STM32_LPTIM_INT_EXTTRIG BIT(2) -#define STM32_LPTIM_INT_ARRM BIT(1) -#define STM32_LPTIM_INT_CMPM BIT(0) -#define STM32_LPTIM_CFGR(n) STM32_LPTIM_REG(n, 0x0C) -#define STM32_LPTIM_CR(n) STM32_LPTIM_REG(n, 0x10) -#define STM32_LPTIM_CR_RSTARE BIT(4) -#define STM32_LPTIM_CR_COUNTRST BIT(3) -#define STM32_LPTIM_CR_CNTSTRT BIT(2) -#define STM32_LPTIM_CR_SNGSTRT BIT(1) -#define STM32_LPTIM_CR_ENABLE BIT(0) -#define STM32_LPTIM_CMP(n) STM32_LPTIM_REG(n, 0x14) -#define STM32_LPTIM_ARR(n) STM32_LPTIM_REG(n, 0x18) -#define STM32_LPTIM_CNT(n) STM32_LPTIM_REG(n, 0x1C) -#define STM32_LPTIM_CFGR2(n) STM32_LPTIM_REG(n, 0x24) +#define STM32_LPTIM_BASE(n) CONCAT3(STM32_LPTIM, n, _BASE) + +#define STM32_LPTIM_REG(n, offset) REG32(STM32_LPTIM_BASE(n) + (offset)) + +#define STM32_LPTIM_ISR(n) STM32_LPTIM_REG(n, 0x00) +#define STM32_LPTIM_ICR(n) STM32_LPTIM_REG(n, 0x04) +#define STM32_LPTIM_IER(n) STM32_LPTIM_REG(n, 0x08) +#define STM32_LPTIM_INT_DOWN BIT(6) +#define STM32_LPTIM_INT_UP BIT(5) +#define STM32_LPTIM_INT_ARROK BIT(4) +#define STM32_LPTIM_INT_CMPOK BIT(3) +#define STM32_LPTIM_INT_EXTTRIG BIT(2) +#define STM32_LPTIM_INT_ARRM BIT(1) +#define STM32_LPTIM_INT_CMPM BIT(0) +#define STM32_LPTIM_CFGR(n) STM32_LPTIM_REG(n, 0x0C) +#define STM32_LPTIM_CR(n) STM32_LPTIM_REG(n, 0x10) +#define STM32_LPTIM_CR_RSTARE BIT(4) +#define STM32_LPTIM_CR_COUNTRST BIT(3) +#define STM32_LPTIM_CR_CNTSTRT BIT(2) +#define STM32_LPTIM_CR_SNGSTRT BIT(1) +#define STM32_LPTIM_CR_ENABLE BIT(0) +#define STM32_LPTIM_CMP(n) STM32_LPTIM_REG(n, 0x14) +#define STM32_LPTIM_ARR(n) STM32_LPTIM_REG(n, 0x18) +#define STM32_LPTIM_CNT(n) STM32_LPTIM_REG(n, 0x1C) +#define STM32_LPTIM_CFGR2(n) STM32_LPTIM_REG(n, 0x24) /* --- GPIO --- */ -#define GPIO_A STM32_GPIOA_BASE -#define GPIO_B STM32_GPIOB_BASE -#define GPIO_C STM32_GPIOC_BASE -#define GPIO_D STM32_GPIOD_BASE -#define GPIO_E STM32_GPIOE_BASE -#define GPIO_F STM32_GPIOF_BASE -#define GPIO_G STM32_GPIOG_BASE -#define GPIO_H STM32_GPIOH_BASE -#define GPIO_I STM32_GPIOI_BASE -#define GPIO_J STM32_GPIOJ_BASE -#define GPIO_K STM32_GPIOK_BASE +#define GPIO_A STM32_GPIOA_BASE +#define GPIO_B STM32_GPIOB_BASE +#define GPIO_C STM32_GPIOC_BASE +#define GPIO_D STM32_GPIOD_BASE +#define GPIO_E STM32_GPIOE_BASE +#define GPIO_F STM32_GPIOF_BASE +#define GPIO_G STM32_GPIOG_BASE +#define GPIO_H STM32_GPIOH_BASE +#define GPIO_I STM32_GPIOI_BASE +#define GPIO_J STM32_GPIOJ_BASE +#define GPIO_K STM32_GPIOK_BASE #define UNIMPLEMENTED_GPIO_BANK GPIO_A - /* --- I2C --- */ -#define STM32_I2C1_PORT 0 -#define STM32_I2C2_PORT 1 -#define STM32_I2C3_PORT 2 -#define STM32_FMPI2C4_PORT 3 - +#define STM32_I2C1_PORT 0 +#define STM32_I2C2_PORT 1 +#define STM32_I2C3_PORT 2 +#define STM32_FMPI2C4_PORT 3 + +#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) +#define stm32_i2c_reg(port, offset) \ + ((uint16_t *)(((port) == 3 ? STM32_I2C4_BASE : \ + (STM32_I2C1_BASE + ((port)*0x400))) + \ + (offset))) +#else #define stm32_i2c_reg(port, offset) \ - ((uint16_t *)((STM32_I2C1_BASE + ((port) * 0x400)) + (offset))) + ((uint16_t *)((STM32_I2C1_BASE + ((port)*0x400)) + (offset))) +#endif + /* --- Power / Reset / Clocks --- */ -#define STM32_PWR_CR REG32(STM32_PWR_BASE + 0x00) -#define STM32_PWR_CR_LPSDSR (1 << 0) -#define STM32_PWR_CR_FLPS (1 << 9) -#define STM32_PWR_CR_SVOS5 (1 << 14) -#define STM32_PWR_CR_SVOS4 (2 << 14) -#define STM32_PWR_CR_SVOS3 (3 << 14) -#define STM32_PWR_CR_SVOS_MASK (3 << 14) +#define STM32_PWR_CR REG32(STM32_PWR_BASE + 0x00) +#define STM32_PWR_CR_LPSDSR (1 << 0) +#define STM32_PWR_CR_FLPS (1 << 9) +#define STM32_PWR_CR_SVOS5 (1 << 14) +#define STM32_PWR_CR_SVOS4 (2 << 14) +#define STM32_PWR_CR_SVOS3 (3 << 14) +#define STM32_PWR_CR_SVOS_MASK (3 << 14) /* RTC domain control register */ -#define STM32_RCC_BDCR_BDRST BIT(16) -#define STM32_RCC_BDCR_RTCEN BIT(15) -#define STM32_RCC_BDCR_LSERDY BIT(1) -#define STM32_RCC_BDCR_LSEON BIT(0) -#define BDCR_RTCSEL_MASK ((0x3) << 8) -#define BDCR_RTCSEL(source) (((source) << 8) & BDCR_RTCSEL_MASK) -#define BDCR_SRC_LSE 0x1 -#define BDCR_SRC_LSI 0x2 -#define BDCR_SRC_HSE 0x3 +#define STM32_RCC_BDCR_BDRST BIT(16) +#define STM32_RCC_BDCR_RTCEN BIT(15) +#define STM32_RCC_BDCR_LSERDY BIT(1) +#define STM32_RCC_BDCR_LSEON BIT(0) +#define BDCR_RTCSEL_MASK ((0x3) << 8) +#define BDCR_RTCSEL(source) (((source) << 8) & BDCR_RTCSEL_MASK) +#define BDCR_SRC_LSE 0x1 +#define BDCR_SRC_LSI 0x2 +#define BDCR_SRC_HSE 0x3 /* Peripheral bits for RCC_APB/AHB and DBGMCU regs */ -#define STM32_RCC_PB1_TIM2 BIT(0) -#define STM32_RCC_PB1_TIM3 BIT(1) -#define STM32_RCC_PB1_TIM4 BIT(2) -#define STM32_RCC_PB1_TIM5 BIT(3) -#define STM32_RCC_PB1_TIM6 BIT(4) -#define STM32_RCC_PB1_TIM7 BIT(5) -#define STM32_RCC_PB1_TIM12 BIT(6) /* STM32H7 */ -#define STM32_RCC_PB1_TIM13 BIT(7) /* STM32H7 */ -#define STM32_RCC_PB1_TIM14 BIT(8) /* STM32H7 */ -#define STM32_RCC_PB1_RTC BIT(10) /* DBGMCU only */ -#define STM32_RCC_PB1_WWDG BIT(11) -#define STM32_RCC_PB1_IWDG BIT(12) /* DBGMCU only */ -#define STM32_RCC_PB1_SPI2 BIT(14) -#define STM32_RCC_PB1_SPI3 BIT(15) -#define STM32_RCC_PB1_USART2 BIT(17) -#define STM32_RCC_PB1_USART3 BIT(18) -#define STM32_RCC_PB1_USART4 BIT(19) -#define STM32_RCC_PB1_USART5 BIT(20) -#define STM32_RCC_PB1_PWREN BIT(28) -#define STM32_RCC_PB2_SPI1 BIT(12) +#define STM32_RCC_PB1_TIM2 BIT(0) +#define STM32_RCC_PB1_TIM3 BIT(1) +#define STM32_RCC_PB1_TIM4 BIT(2) +#define STM32_RCC_PB1_TIM5 BIT(3) +#define STM32_RCC_PB1_TIM6 BIT(4) +#define STM32_RCC_PB1_TIM7 BIT(5) +#define STM32_RCC_PB1_TIM12 BIT(6) /* STM32H7 */ +#define STM32_RCC_PB1_TIM13 BIT(7) /* STM32H7 */ +#define STM32_RCC_PB1_TIM14 BIT(8) /* STM32H7 */ +#define STM32_RCC_PB1_RTC BIT(10) /* DBGMCU only */ +#define STM32_RCC_PB1_WWDG BIT(11) +#define STM32_RCC_PB1_IWDG BIT(12) /* DBGMCU only */ +#define STM32_RCC_PB1_SPI2 BIT(14) +#define STM32_RCC_PB1_SPI3 BIT(15) +#define STM32_RCC_PB1_USART2 BIT(17) +#define STM32_RCC_PB1_USART3 BIT(18) +#define STM32_RCC_PB1_USART4 BIT(19) +#define STM32_RCC_PB1_USART5 BIT(20) +#define STM32_RCC_PB1_PWREN BIT(28) +#define STM32_RCC_PB2_SPI1 BIT(12) /* Reset causes definitions */ /* --- Watchdogs --- */ -#define STM32_WWDG_CR REG32(STM32_WWDG_BASE + 0x00) -#define STM32_WWDG_CFR REG32(STM32_WWDG_BASE + 0x04) -#define STM32_WWDG_SR REG32(STM32_WWDG_BASE + 0x08) - -#define STM32_WWDG_TB_8 (3 << 7) -#define STM32_WWDG_EWI BIT(9) - -#define STM32_IWDG_KR REG32(STM32_IWDG_BASE + 0x00) -#define STM32_IWDG_KR_UNLOCK 0x5555 -#define STM32_IWDG_KR_RELOAD 0xaaaa -#define STM32_IWDG_KR_START 0xcccc -#define STM32_IWDG_PR REG32(STM32_IWDG_BASE + 0x04) -#define STM32_IWDG_RLR REG32(STM32_IWDG_BASE + 0x08) -#define STM32_IWDG_RLR_MAX 0x0fff -#define STM32_IWDG_SR REG32(STM32_IWDG_BASE + 0x0C) -#define STM32_IWDG_SR_WVU BIT(2) -#define STM32_IWDG_SR_RVU BIT(1) -#define STM32_IWDG_SR_PVU BIT(0) -#define STM32_IWDG_WINR REG32(STM32_IWDG_BASE + 0x10) +#define STM32_WWDG_CR REG32(STM32_WWDG_BASE + 0x00) +#define STM32_WWDG_CFR REG32(STM32_WWDG_BASE + 0x04) +#define STM32_WWDG_SR REG32(STM32_WWDG_BASE + 0x08) + +#define STM32_WWDG_TB_8 (3 << 7) +#define STM32_WWDG_EWI BIT(9) + +#define STM32_IWDG_KR REG32(STM32_IWDG_BASE + 0x00) +#define STM32_IWDG_KR_UNLOCK 0x5555 +#define STM32_IWDG_KR_RELOAD 0xaaaa +#define STM32_IWDG_KR_START 0xcccc +#define STM32_IWDG_PR REG32(STM32_IWDG_BASE + 0x04) +#define STM32_IWDG_RLR REG32(STM32_IWDG_BASE + 0x08) +#define STM32_IWDG_RLR_MAX 0x0fff +#define STM32_IWDG_SR REG32(STM32_IWDG_BASE + 0x0C) +#define STM32_IWDG_SR_WVU BIT(2) +#define STM32_IWDG_SR_RVU BIT(1) +#define STM32_IWDG_SR_PVU BIT(0) +#define STM32_IWDG_WINR REG32(STM32_IWDG_BASE + 0x10) /* --- Real-Time Clock --- */ /* --- Debug --- */ -#define STM32_DBGMCU_IDCODE REG32(STM32_DBGMCU_BASE + 0x00) -#define STM32_DBGMCU_CR REG32(STM32_DBGMCU_BASE + 0x04) +#define STM32_DBGMCU_IDCODE REG32(STM32_DBGMCU_BASE + 0x00) +#define STM32_DBGMCU_CR REG32(STM32_DBGMCU_BASE + 0x04) /* --- Routing interface --- */ /* STM32L1xx only */ -#define STM32_RI_ICR REG32(STM32_COMP_BASE + 0x04) -#define STM32_RI_ASCR1 REG32(STM32_COMP_BASE + 0x08) -#define STM32_RI_ASCR2 REG32(STM32_COMP_BASE + 0x0C) -#define STM32_RI_HYSCR1 REG32(STM32_COMP_BASE + 0x10) -#define STM32_RI_HYSCR2 REG32(STM32_COMP_BASE + 0x14) -#define STM32_RI_HYSCR3 REG32(STM32_COMP_BASE + 0x18) -#define STM32_RI_AMSR1 REG32(STM32_COMP_BASE + 0x1C) -#define STM32_RI_CMR1 REG32(STM32_COMP_BASE + 0x20) -#define STM32_RI_CICR1 REG32(STM32_COMP_BASE + 0x24) -#define STM32_RI_AMSR2 REG32(STM32_COMP_BASE + 0x28) -#define STM32_RI_CMR2 REG32(STM32_COMP_BASE + 0x30) -#define STM32_RI_CICR2 REG32(STM32_COMP_BASE + 0x34) -#define STM32_RI_AMSR3 REG32(STM32_COMP_BASE + 0x38) -#define STM32_RI_CMR3 REG32(STM32_COMP_BASE + 0x3C) -#define STM32_RI_CICR3 REG32(STM32_COMP_BASE + 0x40) -#define STM32_RI_AMSR4 REG32(STM32_COMP_BASE + 0x44) -#define STM32_RI_CMR4 REG32(STM32_COMP_BASE + 0x48) -#define STM32_RI_CICR4 REG32(STM32_COMP_BASE + 0x4C) -#define STM32_RI_AMSR5 REG32(STM32_COMP_BASE + 0x50) -#define STM32_RI_CMR5 REG32(STM32_COMP_BASE + 0x54) -#define STM32_RI_CICR5 REG32(STM32_COMP_BASE + 0x58) +#define STM32_RI_ICR REG32(STM32_COMP_BASE + 0x04) +#define STM32_RI_ASCR1 REG32(STM32_COMP_BASE + 0x08) +#define STM32_RI_ASCR2 REG32(STM32_COMP_BASE + 0x0C) +#define STM32_RI_HYSCR1 REG32(STM32_COMP_BASE + 0x10) +#define STM32_RI_HYSCR2 REG32(STM32_COMP_BASE + 0x14) +#define STM32_RI_HYSCR3 REG32(STM32_COMP_BASE + 0x18) +#define STM32_RI_AMSR1 REG32(STM32_COMP_BASE + 0x1C) +#define STM32_RI_CMR1 REG32(STM32_COMP_BASE + 0x20) +#define STM32_RI_CICR1 REG32(STM32_COMP_BASE + 0x24) +#define STM32_RI_AMSR2 REG32(STM32_COMP_BASE + 0x28) +#define STM32_RI_CMR2 REG32(STM32_COMP_BASE + 0x30) +#define STM32_RI_CICR2 REG32(STM32_COMP_BASE + 0x34) +#define STM32_RI_AMSR3 REG32(STM32_COMP_BASE + 0x38) +#define STM32_RI_CMR3 REG32(STM32_COMP_BASE + 0x3C) +#define STM32_RI_CICR3 REG32(STM32_COMP_BASE + 0x40) +#define STM32_RI_AMSR4 REG32(STM32_COMP_BASE + 0x44) +#define STM32_RI_CMR4 REG32(STM32_COMP_BASE + 0x48) +#define STM32_RI_CICR4 REG32(STM32_COMP_BASE + 0x4C) +#define STM32_RI_AMSR5 REG32(STM32_COMP_BASE + 0x50) +#define STM32_RI_CMR5 REG32(STM32_COMP_BASE + 0x54) +#define STM32_RI_CICR5 REG32(STM32_COMP_BASE + 0x58) /* --- DAC --- */ -#define STM32_DAC_CR REG32(STM32_DAC_BASE + 0x00) -#define STM32_DAC_SWTRIGR REG32(STM32_DAC_BASE + 0x04) -#define STM32_DAC_DHR12R1 REG32(STM32_DAC_BASE + 0x08) -#define STM32_DAC_DHR12L1 REG32(STM32_DAC_BASE + 0x0C) -#define STM32_DAC_DHR8R1 REG32(STM32_DAC_BASE + 0x10) -#define STM32_DAC_DHR12R2 REG32(STM32_DAC_BASE + 0x14) -#define STM32_DAC_DHR12L2 REG32(STM32_DAC_BASE + 0x18) -#define STM32_DAC_DHR8R2 REG32(STM32_DAC_BASE + 0x1C) -#define STM32_DAC_DHR12RD REG32(STM32_DAC_BASE + 0x20) -#define STM32_DAC_DHR12LD REG32(STM32_DAC_BASE + 0x24) -#define STM32_DAC_DHR8RD REG32(STM32_DAC_BASE + 0x28) -#define STM32_DAC_DOR1 REG32(STM32_DAC_BASE + 0x2C) -#define STM32_DAC_DOR2 REG32(STM32_DAC_BASE + 0x30) -#define STM32_DAC_SR REG32(STM32_DAC_BASE + 0x34) - -#define STM32_DAC_CR_DMAEN2 BIT(28) -#define STM32_DAC_CR_TSEL2_SWTRG (7 << 19) -#define STM32_DAC_CR_TSEL2_TMR4 (5 << 19) -#define STM32_DAC_CR_TSEL2_TMR2 (4 << 19) -#define STM32_DAC_CR_TSEL2_TMR9 (3 << 19) -#define STM32_DAC_CR_TSEL2_TMR7 (2 << 19) -#define STM32_DAC_CR_TSEL2_TMR6 (0 << 19) -#define STM32_DAC_CR_TSEL2_MASK (7 << 19) -#define STM32_DAC_CR_TEN2 BIT(18) -#define STM32_DAC_CR_BOFF2 BIT(17) -#define STM32_DAC_CR_EN2 BIT(16) -#define STM32_DAC_CR_DMAEN1 BIT(12) -#define STM32_DAC_CR_TSEL1_SWTRG (7 << 3) -#define STM32_DAC_CR_TSEL1_TMR4 (5 << 3) -#define STM32_DAC_CR_TSEL1_TMR2 (4 << 3) -#define STM32_DAC_CR_TSEL1_TMR9 (3 << 3) -#define STM32_DAC_CR_TSEL1_TMR7 (2 << 3) -#define STM32_DAC_CR_TSEL1_TMR6 (0 << 3) -#define STM32_DAC_CR_TSEL1_MASK (7 << 3) -#define STM32_DAC_CR_TEN1 BIT(2) -#define STM32_DAC_CR_BOFF1 BIT(1) -#define STM32_DAC_CR_EN1 BIT(0) +#define STM32_DAC_CR REG32(STM32_DAC_BASE + 0x00) +#define STM32_DAC_SWTRIGR REG32(STM32_DAC_BASE + 0x04) +#define STM32_DAC_DHR12R1 REG32(STM32_DAC_BASE + 0x08) +#define STM32_DAC_DHR12L1 REG32(STM32_DAC_BASE + 0x0C) +#define STM32_DAC_DHR8R1 REG32(STM32_DAC_BASE + 0x10) +#define STM32_DAC_DHR12R2 REG32(STM32_DAC_BASE + 0x14) +#define STM32_DAC_DHR12L2 REG32(STM32_DAC_BASE + 0x18) +#define STM32_DAC_DHR8R2 REG32(STM32_DAC_BASE + 0x1C) +#define STM32_DAC_DHR12RD REG32(STM32_DAC_BASE + 0x20) +#define STM32_DAC_DHR12LD REG32(STM32_DAC_BASE + 0x24) +#define STM32_DAC_DHR8RD REG32(STM32_DAC_BASE + 0x28) +#define STM32_DAC_DOR1 REG32(STM32_DAC_BASE + 0x2C) +#define STM32_DAC_DOR2 REG32(STM32_DAC_BASE + 0x30) +#define STM32_DAC_SR REG32(STM32_DAC_BASE + 0x34) + +#define STM32_DAC_CR_DMAEN2 BIT(28) +#define STM32_DAC_CR_TSEL2_SWTRG (7 << 19) +#define STM32_DAC_CR_TSEL2_TMR4 (5 << 19) +#define STM32_DAC_CR_TSEL2_TMR2 (4 << 19) +#define STM32_DAC_CR_TSEL2_TMR9 (3 << 19) +#define STM32_DAC_CR_TSEL2_TMR7 (2 << 19) +#define STM32_DAC_CR_TSEL2_TMR6 (0 << 19) +#define STM32_DAC_CR_TSEL2_MASK (7 << 19) +#define STM32_DAC_CR_TEN2 BIT(18) +#define STM32_DAC_CR_BOFF2 BIT(17) +#define STM32_DAC_CR_EN2 BIT(16) +#define STM32_DAC_CR_DMAEN1 BIT(12) +#define STM32_DAC_CR_TSEL1_SWTRG (7 << 3) +#define STM32_DAC_CR_TSEL1_TMR4 (5 << 3) +#define STM32_DAC_CR_TSEL1_TMR2 (4 << 3) +#define STM32_DAC_CR_TSEL1_TMR9 (3 << 3) +#define STM32_DAC_CR_TSEL1_TMR7 (2 << 3) +#define STM32_DAC_CR_TSEL1_TMR6 (0 << 3) +#define STM32_DAC_CR_TSEL1_MASK (7 << 3) +#define STM32_DAC_CR_TEN1 BIT(2) +#define STM32_DAC_CR_BOFF1 BIT(1) +#define STM32_DAC_CR_EN1 BIT(0) /* --- CRC --- */ -#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) -#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) - -#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) -#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) -#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) -#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) - -#define STM32_CRC_CR_RESET BIT(0) -#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) -#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) -#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) -#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) -#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) -#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) -#define STM32_CRC_CR_REV_IN_WORD (3 << 5) -#define STM32_CRC_CR_REV_OUT BIT(7) +#define STM32_CRC_DR REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR32 REG32(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR16 REG16(STM32_CRC_BASE + 0x0) +#define STM32_CRC_DR8 REG8(STM32_CRC_BASE + 0x0) + +#define STM32_CRC_IDR REG32(STM32_CRC_BASE + 0x4) +#define STM32_CRC_CR REG32(STM32_CRC_BASE + 0x8) +#define STM32_CRC_INIT REG32(STM32_CRC_BASE + 0x10) +#define STM32_CRC_POL REG32(STM32_CRC_BASE + 0x14) + +#define STM32_CRC_CR_RESET BIT(0) +#define STM32_CRC_CR_POLYSIZE_32 (0 << 3) +#define STM32_CRC_CR_POLYSIZE_16 (1 << 3) +#define STM32_CRC_CR_POLYSIZE_8 (2 << 3) +#define STM32_CRC_CR_POLYSIZE_7 (3 << 3) +#define STM32_CRC_CR_REV_IN_BYTE (1 << 5) +#define STM32_CRC_CR_REV_IN_HWORD (2 << 5) +#define STM32_CRC_CR_REV_IN_WORD (3 << 5) +#define STM32_CRC_CR_REV_OUT BIT(7) /* --- PMSE --- */ -#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) -#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) -#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) -#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) -#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) -#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) -#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) -#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x) * 4) -#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) -#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) -#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) -#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) -#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) -#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) -#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) -#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) -#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) -#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) -#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) +#define STM32_PMSE_ARCR REG32(STM32_PMSE_BASE + 0x0) +#define STM32_PMSE_ACCR REG32(STM32_PMSE_BASE + 0x4) +#define STM32_PMSE_CR REG32(STM32_PMSE_BASE + 0x8) +#define STM32_PMSE_CRTDR REG32(STM32_PMSE_BASE + 0x14) +#define STM32_PMSE_IER REG32(STM32_PMSE_BASE + 0x18) +#define STM32_PMSE_SR REG32(STM32_PMSE_BASE + 0x1c) +#define STM32_PMSE_IFCR REG32(STM32_PMSE_BASE + 0x20) +#define STM32_PMSE_PxPMR(x) REG32(STM32_PMSE_BASE + 0x2c + (x)*4) +#define STM32_PMSE_PAPMR REG32(STM32_PMSE_BASE + 0x2c) +#define STM32_PMSE_PBPMR REG32(STM32_PMSE_BASE + 0x30) +#define STM32_PMSE_PCPMR REG32(STM32_PMSE_BASE + 0x34) +#define STM32_PMSE_PDPMR REG32(STM32_PMSE_BASE + 0x38) +#define STM32_PMSE_PEPMR REG32(STM32_PMSE_BASE + 0x3c) +#define STM32_PMSE_PFPMR REG32(STM32_PMSE_BASE + 0x40) +#define STM32_PMSE_PGPMR REG32(STM32_PMSE_BASE + 0x44) +#define STM32_PMSE_PHPMR REG32(STM32_PMSE_BASE + 0x48) +#define STM32_PMSE_PIPMR REG32(STM32_PMSE_BASE + 0x4c) +#define STM32_PMSE_MRCR REG32(STM32_PMSE_BASE + 0x100) +#define STM32_PMSE_MCCR REG32(STM32_PMSE_BASE + 0x104) /* --- USB --- */ -#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n) * 4) - -#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) - -#define STM32_USB_CNTR_FRES BIT(0) -#define STM32_USB_CNTR_PDWN BIT(1) -#define STM32_USB_CNTR_LP_MODE BIT(2) -#define STM32_USB_CNTR_FSUSP BIT(3) -#define STM32_USB_CNTR_RESUME BIT(4) -#define STM32_USB_CNTR_L1RESUME BIT(5) -#define STM32_USB_CNTR_L1REQM BIT(7) -#define STM32_USB_CNTR_ESOFM BIT(8) -#define STM32_USB_CNTR_SOFM BIT(9) -#define STM32_USB_CNTR_RESETM BIT(10) -#define STM32_USB_CNTR_SUSPM BIT(11) -#define STM32_USB_CNTR_WKUPM BIT(12) -#define STM32_USB_CNTR_ERRM BIT(13) -#define STM32_USB_CNTR_PMAOVRM BIT(14) -#define STM32_USB_CNTR_CTRM BIT(15) - -#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) - -#define STM32_USB_ISTR_EP_ID_MASK (0x000f) -#define STM32_USB_ISTR_DIR BIT(4) -#define STM32_USB_ISTR_L1REQ BIT(7) -#define STM32_USB_ISTR_ESOF BIT(8) -#define STM32_USB_ISTR_SOF BIT(9) -#define STM32_USB_ISTR_RESET BIT(10) -#define STM32_USB_ISTR_SUSP BIT(11) -#define STM32_USB_ISTR_WKUP BIT(12) -#define STM32_USB_ISTR_ERR BIT(13) -#define STM32_USB_ISTR_PMAOVR BIT(14) -#define STM32_USB_ISTR_CTR BIT(15) - -#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) +#define STM32_USB_EP(n) REG16(STM32_USB_FS_BASE + (n)*4) + +#define STM32_USB_CNTR REG16(STM32_USB_FS_BASE + 0x40) + +#define STM32_USB_CNTR_FRES BIT(0) +#define STM32_USB_CNTR_PDWN BIT(1) +#define STM32_USB_CNTR_LP_MODE BIT(2) +#define STM32_USB_CNTR_FSUSP BIT(3) +#define STM32_USB_CNTR_RESUME BIT(4) +#define STM32_USB_CNTR_L1RESUME BIT(5) +#define STM32_USB_CNTR_L1REQM BIT(7) +#define STM32_USB_CNTR_ESOFM BIT(8) +#define STM32_USB_CNTR_SOFM BIT(9) +#define STM32_USB_CNTR_RESETM BIT(10) +#define STM32_USB_CNTR_SUSPM BIT(11) +#define STM32_USB_CNTR_WKUPM BIT(12) +#define STM32_USB_CNTR_ERRM BIT(13) +#define STM32_USB_CNTR_PMAOVRM BIT(14) +#define STM32_USB_CNTR_CTRM BIT(15) + +#define STM32_USB_ISTR REG16(STM32_USB_FS_BASE + 0x44) + +#define STM32_USB_ISTR_EP_ID_MASK (0x000f) +#define STM32_USB_ISTR_DIR BIT(4) +#define STM32_USB_ISTR_L1REQ BIT(7) +#define STM32_USB_ISTR_ESOF BIT(8) +#define STM32_USB_ISTR_SOF BIT(9) +#define STM32_USB_ISTR_RESET BIT(10) +#define STM32_USB_ISTR_SUSP BIT(11) +#define STM32_USB_ISTR_WKUP BIT(12) +#define STM32_USB_ISTR_ERR BIT(13) +#define STM32_USB_ISTR_PMAOVR BIT(14) +#define STM32_USB_ISTR_CTR BIT(15) + +#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48) #define STM32_USB_FNR_RXDP_RXDM_SHIFT (14) -#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) - -#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) -#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) -#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) -#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) - -#define STM32_USB_BCDR_BCDEN BIT(0) -#define STM32_USB_BCDR_DCDEN BIT(1) -#define STM32_USB_BCDR_PDEN BIT(2) -#define STM32_USB_BCDR_SDEN BIT(3) -#define STM32_USB_BCDR_DCDET BIT(4) -#define STM32_USB_BCDR_PDET BIT(5) -#define STM32_USB_BCDR_SDET BIT(6) -#define STM32_USB_BCDR_PS2DET BIT(7) - -#define EP_MASK 0x0F0F -#define EP_TX_DTOG 0x0040 -#define EP_TX_MASK 0x0030 +#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT) + +#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C) +#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50) +#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) +#define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) + +#define STM32_USB_BCDR_BCDEN BIT(0) +#define STM32_USB_BCDR_DCDEN BIT(1) +#define STM32_USB_BCDR_PDEN BIT(2) +#define STM32_USB_BCDR_SDEN BIT(3) +#define STM32_USB_BCDR_DCDET BIT(4) +#define STM32_USB_BCDR_PDET BIT(5) +#define STM32_USB_BCDR_SDET BIT(6) +#define STM32_USB_BCDR_PS2DET BIT(7) + +#define EP_MASK 0x0F0F +#define EP_TX_DTOG 0x0040 +#define EP_TX_MASK 0x0030 #define EP_TX_VALID 0x0030 -#define EP_TX_NAK 0x0020 +#define EP_TX_NAK 0x0020 #define EP_TX_STALL 0x0010 #define EP_TX_DISAB 0x0000 -#define EP_RX_DTOG 0x4000 -#define EP_RX_MASK 0x3000 +#define EP_RX_DTOG 0x4000 +#define EP_RX_MASK 0x3000 #define EP_RX_VALID 0x3000 -#define EP_RX_NAK 0x2000 +#define EP_RX_NAK 0x2000 #define EP_RX_STALL 0x1000 #define EP_RX_DISAB 0x0000 #define EP_STATUS_OUT 0x0100 -#define EP_TX_RX_MASK (EP_TX_MASK | EP_RX_MASK) +#define EP_TX_RX_MASK (EP_TX_MASK | EP_RX_MASK) #define EP_TX_RX_VALID (EP_TX_VALID | EP_RX_VALID) -#define EP_TX_RX_NAK (EP_TX_NAK | EP_RX_NAK) +#define EP_TX_RX_NAK (EP_TX_NAK | EP_RX_NAK) #define STM32_TOGGLE_EP(n, mask, val, flags) \ - STM32_USB_EP(n) = (((STM32_USB_EP(n) & (EP_MASK | (mask))) \ - ^ (val)) | (flags)) + STM32_USB_EP(n) = \ + (((STM32_USB_EP(n) & (EP_MASK | (mask))) ^ (val)) | (flags)) /* --- TRNG --- */ -#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) -#define STM32_RNG_CR_RNGEN BIT(2) -#define STM32_RNG_CR_IE BIT(3) -#define STM32_RNG_CR_CED BIT(5) -#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) -#define STM32_RNG_SR_DRDY BIT(0) -#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) +#define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) +#define STM32_RNG_CR_RNGEN BIT(2) +#define STM32_RNG_CR_IE BIT(3) +#define STM32_RNG_CR_CED BIT(5) +#define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) +#define STM32_RNG_SR_DRDY BIT(0) +#define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) /* --- AXI interconnect --- */ /* STM32H7: AXI_TARGx_FN_MOD exists for masters x = 1, 2 and 7 */ -#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + \ - 0x1000 * (x)) -#define WRITE_ISS_OVERRIDE BIT(1) -#define READ_ISS_OVERRIDE BIT(0) +#define STM32_AXI_TARG_FN_MOD(x) REG32(STM32_GPV_BASE + 0x1108 + 0x1000 * (x)) +#define WRITE_ISS_OVERRIDE BIT(1) +#define READ_ISS_OVERRIDE BIT(0) /* --- MISC --- */ -#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) -#define STM32_UNIQUE_ID_LENGTH (3 * 4) +#define STM32_UNIQUE_ID_ADDRESS REG32_ADDR(STM32_UNIQUE_ID_BASE) +#define STM32_UNIQUE_ID_LENGTH (3 * 4) #endif /* !__ASSEMBLER__ */ @@ -483,6 +488,8 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #include "registers-stm32l.h" #elif defined(CHIP_FAMILY_STM32L4) #include "registers-stm32l4.h" +#elif defined(CHIP_FAMILY_STM32L5) +#include "registers-stm32l5.h" #else #error "Unsupported chip family" #endif diff --git a/chip/stm32/spi.c b/chip/stm32/spi.c index 3dbbbc4fa9..e6be946113 100644 --- a/chip/stm32/spi.c +++ b/chip/stm32/spi.c @@ -1,5 +1,5 @@ /* - * Copyright 2013 The Chromium OS Authors. All rights reserved. + * Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,6 +8,7 @@ * This uses DMA to handle transmission and reception. */ +#include "builtin/assert.h" #include "chipset.h" #include "clock.h" #include "console.h" @@ -24,8 +25,8 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_SPI, outstr) -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SPI, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SPI, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SPI, format, ##args) /* SPI FIFO registers */ #ifdef CHIP_FAMILY_STM32H7 @@ -41,7 +42,7 @@ static const struct dma_option dma_tx_option = { STM32_DMAC_SPI1_TX, (void *)&SPI_TXDR, STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT #ifdef CHIP_FAMILY_STM32F4 - | STM32_DMA_CCR_CHANNEL(STM32_SPI1_TX_REQ_CH) + | STM32_DMA_CCR_CHANNEL(STM32_SPI1_TX_REQ_CH) #endif }; @@ -49,7 +50,7 @@ static const struct dma_option dma_rx_option = { STM32_DMAC_SPI1_RX, (void *)&SPI_RXDR, STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT #ifdef CHIP_FAMILY_STM32F4 - | STM32_DMA_CCR_CHANNEL(STM32_SPI1_RX_REQ_CH) + | STM32_DMA_CCR_CHANNEL(STM32_SPI1_RX_REQ_CH) #endif }; @@ -71,8 +72,8 @@ static const struct dma_option dma_rx_option = { * the AP will have a known and identifiable value. */ #define SPI_PROTO2_OFFSET (EC_PROTO2_RESPONSE_HEADER_BYTES + 2) -#define SPI_PROTO2_OVERHEAD (SPI_PROTO2_OFFSET + \ - EC_PROTO2_RESPONSE_TRAILER_BYTES + 1) +#define SPI_PROTO2_OVERHEAD \ + (SPI_PROTO2_OFFSET + EC_PROTO2_RESPONSE_TRAILER_BYTES + 1) #endif /* defined(CONFIG_SPI_PROTOCOL_V2) */ /* * Max data size for a version 3 request/response packet. This is big enough @@ -92,10 +93,8 @@ static const struct dma_option dma_rx_option = { * 32-bit aligned. */ static const uint8_t out_preamble[4] = { - EC_SPI_PROCESSING, - EC_SPI_PROCESSING, - EC_SPI_PROCESSING, - EC_SPI_FRAME_START, /* This is the byte which matters */ + EC_SPI_PROCESSING, EC_SPI_PROCESSING, EC_SPI_PROCESSING, + EC_SPI_FRAME_START, /* This is the byte which matters */ }; /* @@ -117,7 +116,7 @@ static const uint8_t out_preamble[4] = { * message, including protocol overhead, and must be 32-bit aligned. */ static uint8_t out_msg[SPI_MAX_RESPONSE_SIZE + sizeof(out_preamble) + - EC_SPI_PAST_END_LENGTH] __aligned(4) __uncached; + EC_SPI_PAST_END_LENGTH] __aligned(4) __uncached; static uint8_t in_msg[SPI_MAX_REQUEST_SIZE] __aligned(4) __uncached; static uint8_t enabled; #ifdef CONFIG_SPI_PROTOCOL_V2 @@ -172,8 +171,7 @@ enum spi_state { * @param nss GPIO signal for NSS control line * @return 0 if bytes received, -1 if we hit a timeout or NSS went high */ -static int wait_for_bytes(dma_chan_t *rxdma, int needed, - enum gpio_signal nss) +static int wait_for_bytes(dma_chan_t *rxdma, int needed, enum gpio_signal nss) { timestamp_t deadline; @@ -230,8 +228,8 @@ static int wait_for_bytes(dma_chan_t *rxdma, int needed, * SPI_PROTO2_OFFSET bytes into out_msg * @param msg_len Number of message bytes to send */ -static void reply(dma_chan_t *txdma, - enum ec_status status, char *msg_ptr, int msg_len) +static void reply(dma_chan_t *txdma, enum ec_status status, char *msg_ptr, + int msg_len) { char *msg = out_msg; int need_copy = msg_ptr != msg + SPI_PROTO2_OFFSET; @@ -341,7 +339,7 @@ static void setup_for_transaction(void) /* Ready to receive */ state = SPI_STATE_READY_TO_RX; - tx_status(EC_SPI_OLD_READY); + tx_status(EC_SPI_RX_READY); #ifdef CHIP_FAMILY_STM32H7 spi->cr1 |= STM32_SPI_CR1_SPE; @@ -438,8 +436,10 @@ static void spi_send_response_packet(struct host_packet *pkt) /* Transmit the reply */ txdma = dma_get_channel(STM32_DMAC_SPI1_TX); - dma_prepare_tx(&dma_tx_option, sizeof(out_preamble) + pkt->response_size - + EC_SPI_PAST_END_LENGTH, out_msg); + dma_prepare_tx(&dma_tx_option, + sizeof(out_preamble) + pkt->response_size + + EC_SPI_PAST_END_LENGTH, + out_msg); dma_go(txdma); #ifdef CHIP_FAMILY_STM32H7 /* clear any previous underrun */ @@ -544,8 +544,9 @@ void spi_event(enum gpio_signal signal) memcpy(out_msg, out_preamble, sizeof(out_preamble)); spi_packet.response = out_msg + sizeof(out_preamble); /* Reserve space for the preamble and trailing past-end byte */ - spi_packet.response_max = sizeof(out_msg) - - sizeof(out_preamble) - EC_SPI_PAST_END_LENGTH; + spi_packet.response_max = sizeof(out_msg) - + sizeof(out_preamble) - + EC_SPI_PAST_END_LENGTH; spi_packet.response_size = 0; spi_packet.driver_result = EC_RES_SUCCESS; @@ -608,7 +609,7 @@ void spi_event(enum gpio_signal signal) #endif /* defined(CONFIG_SPI_PROTOCOL_V2) */ } - spi_event_error: +spi_event_error: /* Error, timeout, or protocol we can't handle. Ignore data. */ tx_status(EC_SPI_RX_BAD_DATA); state = SPI_STATE_RX_BAD; @@ -701,14 +702,13 @@ static void spi_init(void) #ifdef CHIP_FAMILY_STM32H7 spi->cfg2 = 0; spi->cfg1 = STM32_SPI_CFG1_DATASIZE(8) | STM32_SPI_CFG1_FTHLV(4) | - STM32_SPI_CFG1_CRCSIZE(8) | - STM32_SPI_CFG1_TXDMAEN | STM32_SPI_CFG1_RXDMAEN | - STM32_SPI_CFG1_UDRCFG_CONST | - STM32_SPI_CFG1_UDRDET_BEGIN_FRM; + STM32_SPI_CFG1_CRCSIZE(8) | STM32_SPI_CFG1_TXDMAEN | + STM32_SPI_CFG1_RXDMAEN | STM32_SPI_CFG1_UDRCFG_CONST | + STM32_SPI_CFG1_UDRDET_BEGIN_FRM; spi->cr1 = 0; #else /* !CHIP_FAMILY_STM32H7 */ spi->cr2 = STM32_SPI_CR2_RXDMAEN | STM32_SPI_CR2_TXDMAEN | - STM32_SPI_CR2_FRXTH | STM32_SPI_CR2_DATASIZE(8); + STM32_SPI_CR2_FRXTH | STM32_SPI_CR2_DATASIZE(8); /* Enable the SPI peripheral */ spi->cr1 |= STM32_SPI_CR1_SPE; diff --git a/chip/stm32/spi_controller-stm32h7.c b/chip/stm32/spi_controller-stm32h7.c new file mode 100644 index 0000000000..705bf4e607 --- /dev/null +++ b/chip/stm32/spi_controller-stm32h7.c @@ -0,0 +1,313 @@ +/* + * Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * SPI controller driver. + */ + +#include "common.h" +#include "dma.h" +#include "gpio.h" +#include "shared_mem.h" +#include "spi.h" +#include "stm32-dma.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +/* SPI ports are used as controller */ +static stm32_spi_regs_t *SPI_REGS[] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + STM32_SPI1_REGS, +#endif + STM32_SPI2_REGS, + STM32_SPI3_REGS, + STM32_SPI4_REGS, +}; + +/* DMA request mapping on channels */ +static uint8_t dma_req_tx[ARRAY_SIZE(SPI_REGS)] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + DMAMUX1_REQ_SPI1_TX, +#endif + DMAMUX1_REQ_SPI2_TX, + DMAMUX1_REQ_SPI3_TX, + DMAMUX1_REQ_SPI4_TX, +}; +static uint8_t dma_req_rx[ARRAY_SIZE(SPI_REGS)] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + DMAMUX1_REQ_SPI1_RX, +#endif + DMAMUX1_REQ_SPI2_RX, + DMAMUX1_REQ_SPI3_RX, + DMAMUX1_REQ_SPI4_RX, +}; + +static struct mutex spi_mutex[ARRAY_SIZE(SPI_REGS)]; + +#define SPI_TRANSACTION_TIMEOUT_USEC (800 * MSEC) + +static const struct dma_option dma_tx_option[] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + { STM32_DMAC_SPI1_TX, (void *)&STM32_SPI1_REGS->txdr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT }, +#endif + { STM32_DMAC_SPI2_TX, (void *)&STM32_SPI2_REGS->txdr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT }, + { STM32_DMAC_SPI3_TX, (void *)&STM32_SPI3_REGS->txdr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT }, + { STM32_DMAC_SPI4_TX, (void *)&STM32_SPI4_REGS->txdr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT }, +}; + +static const struct dma_option dma_rx_option[] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + { STM32_DMAC_SPI1_RX, (void *)&STM32_SPI1_REGS->rxdr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT }, +#endif + { STM32_DMAC_SPI2_RX, (void *)&STM32_SPI2_REGS->rxdr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT }, + { STM32_DMAC_SPI3_RX, (void *)&STM32_SPI3_REGS->rxdr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT }, + { STM32_DMAC_SPI4_RX, (void *)&STM32_SPI4_REGS->rxdr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT }, +}; + +static uint8_t spi_enabled[ARRAY_SIZE(SPI_REGS)]; + +/** + * Initialize SPI module, registers, and clocks + * @param spi_device device to initialize. + */ +static void spi_controller_config(const struct spi_device_t *spi_device) +{ + int port = spi_device->port; + + stm32_spi_regs_t *spi = SPI_REGS[port]; + + /* + * Set SPI controller, baud rate, and software peripheral control. + */ + spi->cr1 = STM32_SPI_CR1_SSI; + spi->cfg2 = STM32_SPI_CFG2_MSTR | STM32_SPI_CFG2_SSM | + STM32_SPI_CFG2_AFCNTR; + spi->cfg1 = STM32_SPI_CFG1_DATASIZE(8) | STM32_SPI_CFG1_FTHLV(4) | + STM32_SPI_CFG1_CRCSIZE(8) | + STM32_SPI_CR1_DIV(spi_device->div); + + dma_select_channel(dma_tx_option[port].channel, dma_req_tx[port]); + dma_select_channel(dma_rx_option[port].channel, dma_req_rx[port]); +} + +static int spi_controller_initialize(const struct spi_device_t *spi_device) +{ + spi_controller_config(spi_device); + + gpio_set_level(spi_device->gpio_cs, 1); + + /* Set flag */ + spi_enabled[spi_device->port] = 1; + + return EC_SUCCESS; +} + +/** + * Shutdown SPI module + */ +static int spi_controller_shutdown(const struct spi_device_t *spi_device) +{ + int rv = EC_SUCCESS; + int port = spi_device->port; + stm32_spi_regs_t *spi = SPI_REGS[port]; + + /* Set flag */ + spi_enabled[port] = 0; + + /* Disable DMA streams */ + dma_disable(dma_tx_option[port].channel); + dma_disable(dma_rx_option[port].channel); + + /* Disable SPI */ + spi->cr1 &= ~STM32_SPI_CR1_SPE; + + /* Disable DMA buffers */ + spi->cfg1 &= ~(STM32_SPI_CFG1_TXDMAEN | STM32_SPI_CFG1_RXDMAEN); + + return rv; +} + +int spi_enable(const struct spi_device_t *spi_device, int enable) +{ + int port = spi_device->port; + if (enable == spi_enabled[port]) + return EC_SUCCESS; + if (enable) + return spi_controller_initialize(spi_device); + else + return spi_controller_shutdown(spi_device); +} + +static int spi_dma_start(const struct spi_device_t *spi_device, + const uint8_t *txdata, uint8_t *rxdata, int len) +{ + dma_chan_t *txdma; + int port = spi_device->port; + stm32_spi_regs_t *spi = SPI_REGS[port]; + + /* + * Workaround for STM32H7 errata: without resetting the SPI controller, + * the RX DMA requests will happen too early on the 2nd transfer. + */ + STM32_RCC_APB2RSTR = STM32_RCC_PB2_SPI4; + STM32_RCC_APB2RSTR = 0; + dma_clear_isr(dma_tx_option[port].channel); + dma_clear_isr(dma_rx_option[port].channel); + /* restore proper SPI configuration registers. */ + spi_controller_config(spi_device); + + spi->cr2 = len; + spi->cfg1 |= STM32_SPI_CFG1_RXDMAEN; + /* Set up RX DMA */ + if (rxdata) + dma_start_rx(&dma_rx_option[port], len, rxdata); + + /* Set up TX DMA */ + if (txdata) { + txdma = dma_get_channel(dma_tx_option[port].channel); + dma_prepare_tx(&dma_tx_option[port], len, txdata); + dma_go(txdma); + } + + spi->cfg1 |= STM32_SPI_CFG1_TXDMAEN; + spi->cr1 |= STM32_SPI_CR1_SPE; + spi->cr1 |= STM32_SPI_CR1_CSTART; + + return EC_SUCCESS; +} + +static inline bool dma_is_enabled_(const struct dma_option *option) +{ + return dma_is_enabled(dma_get_channel(option->channel)); +} + +static int spi_dma_wait(int port) +{ + timestamp_t timeout; + stm32_spi_regs_t *spi = SPI_REGS[port]; + int rv = EC_SUCCESS; + + /* Wait for DMA transmission to complete */ + if (dma_is_enabled_(&dma_tx_option[port])) { + rv = dma_wait(dma_tx_option[port].channel); + if (rv) + return rv; + + timeout.val = get_time().val + SPI_TRANSACTION_TIMEOUT_USEC; + /* Wait for FIFO empty and BSY bit clear */ + while (!(spi->sr & (STM32_SPI_SR_TXC))) + if (get_time().val > timeout.val) + return EC_ERROR_TIMEOUT; + + /* Disable TX DMA */ + dma_disable(dma_tx_option[port].channel); + } + + /* Wait for DMA reception to complete */ + if (dma_is_enabled_(&dma_rx_option[port])) { + rv = dma_wait(dma_rx_option[port].channel); + if (rv) + return rv; + + timeout.val = get_time().val + SPI_TRANSACTION_TIMEOUT_USEC; + /* Wait for FRLVL[1:0] to indicate FIFO empty */ + while (spi->sr & (STM32_SPI_SR_FRLVL | STM32_SPI_SR_RXNE)) + if (get_time().val > timeout.val) + return EC_ERROR_TIMEOUT; + + /* Disable RX DMA */ + dma_disable(dma_rx_option[port].channel); + } + + spi->cr1 &= ~STM32_SPI_CR1_SPE; + spi->cfg1 &= ~(STM32_SPI_CFG1_TXDMAEN | STM32_SPI_CFG1_RXDMAEN); + + return rv; +} + +int spi_transaction_async(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) +{ + int rv = EC_SUCCESS; + int port = spi_device->port; + int full_readback = 0; + + char *buf = NULL; + +#ifndef CONFIG_SPI_HALFDUPLEX + if (rxlen == SPI_READBACK_ALL) { + buf = rxdata; + full_readback = 1; + } else { + rv = shared_mem_acquire(MAX(txlen, rxlen), &buf); + if (rv != EC_SUCCESS) + return rv; + } +#endif + + /* Drive SS low */ + gpio_set_level(spi_device->gpio_cs, 0); + + rv = spi_dma_start(spi_device, txdata, buf, txlen); + if (rv != EC_SUCCESS) + goto err_free; + + if (full_readback) + return EC_SUCCESS; + + if (rxlen) { + rv = spi_dma_wait(port); + if (rv != EC_SUCCESS) + goto err_free; + + rv = spi_dma_start(spi_device, buf, rxdata, rxlen); + if (rv != EC_SUCCESS) + goto err_free; + } + +err_free: + if (!full_readback) + shared_mem_release(buf); + return rv; +} + +int spi_transaction_flush(const struct spi_device_t *spi_device) +{ + int rv = spi_dma_wait(spi_device->port); + + /* Drive SS high */ + gpio_set_level(spi_device->gpio_cs, 1); + + return rv; +} + +int spi_transaction_wait(const struct spi_device_t *spi_device) +{ + return spi_dma_wait(spi_device->port); +} + +int spi_transaction(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) +{ + int rv; + int port = spi_device->port; + + mutex_lock(spi_mutex + port); + rv = spi_transaction_async(spi_device, txdata, txlen, rxdata, rxlen); + rv |= spi_transaction_flush(spi_device); + mutex_unlock(spi_mutex + port); + + return rv; +} diff --git a/chip/stm32/spi_controller.c b/chip/stm32/spi_controller.c new file mode 100644 index 0000000000..2802c35e90 --- /dev/null +++ b/chip/stm32/spi_controller.c @@ -0,0 +1,464 @@ +/* + * Copyright 2014 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * SPI controller driver. + */ + +#include "common.h" +#include "dma.h" +#include "gpio.h" +#include "hwtimer.h" +#include "shared_mem.h" +#include "spi.h" +#include "stm32-dma.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#if defined(CHIP_VARIANT_STM32F373) || defined(CHIP_FAMILY_STM32L4) || \ + defined(CHIP_FAMILY_STM32L5) || defined(CHIP_VARIANT_STM32F76X) +#define HAS_SPI3 +#else +#undef HAS_SPI3 +#endif + +/* The second (and third if available) SPI port are used as controller */ +static stm32_spi_regs_t *SPI_REGS[] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + STM32_SPI1_REGS, +#endif + STM32_SPI2_REGS, +#ifdef HAS_SPI3 + STM32_SPI3_REGS, +#endif +}; + +/* DMA request mapping on channels */ +struct dma_req_t { + uint8_t tx_req; + uint8_t rx_req; +}; +#ifdef CHIP_FAMILY_STM32L4 +static struct dma_req_t dma_req[ARRAY_SIZE(SPI_REGS)] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + /* SPI1 */ { 1, 1 }, +#endif + /* SPI2 */ { 1, 1 }, + /* SPI3 */ { 3, 3 }, +}; +#elif defined(CHIP_FAMILY_STM32L5) +static struct dma_req_t dma_req[ARRAY_SIZE(SPI_REGS)] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + /* SPI1 */ { DMAMUX_REQ_SPI1_TX, DMAMUX_REQ_SPI1_RX }, +#endif + /* SPI2 */ { DMAMUX_REQ_SPI2_TX, DMAMUX_REQ_SPI2_RX }, + /* SPI3 */ { DMAMUX_REQ_SPI3_TX, DMAMUX_REQ_SPI3_RX }, +}; +#endif + +static struct mutex spi_mutex[ARRAY_SIZE(SPI_REGS)]; + +#define SPI_TRANSACTION_TIMEOUT_USEC (800 * MSEC) + +/* Default DMA channel options */ +#ifdef CHIP_FAMILY_STM32F4 +#define F4_CHANNEL(ch) STM32_DMA_CCR_CHANNEL(ch) +#else +#define F4_CHANNEL(ch) 0 +#endif + +static const struct dma_option dma_tx_option[] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + { STM32_DMAC_SPI1_TX, (void *)&STM32_SPI1_REGS->dr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + F4_CHANNEL(STM32_SPI1_TX_REQ_CH) }, +#endif + { STM32_DMAC_SPI2_TX, (void *)&STM32_SPI2_REGS->dr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + F4_CHANNEL(STM32_SPI2_TX_REQ_CH) }, +#ifdef HAS_SPI3 + { STM32_DMAC_SPI3_TX, (void *)&STM32_SPI3_REGS->dr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + F4_CHANNEL(STM32_SPI3_TX_REQ_CH) }, +#endif +}; + +static const struct dma_option dma_rx_option[] = { +#ifdef CONFIG_STM32_SPI1_CONTROLLER + { STM32_DMAC_SPI1_RX, (void *)&STM32_SPI1_REGS->dr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + F4_CHANNEL(STM32_SPI1_RX_REQ_CH) }, +#endif + { STM32_DMAC_SPI2_RX, (void *)&STM32_SPI2_REGS->dr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + F4_CHANNEL(STM32_SPI2_RX_REQ_CH) }, +#ifdef HAS_SPI3 + { STM32_DMAC_SPI3_RX, (void *)&STM32_SPI3_REGS->dr, + STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | + F4_CHANNEL(STM32_SPI3_RX_REQ_CH) }, +#endif +}; + +static uint8_t spi_enabled[ARRAY_SIZE(SPI_REGS)]; + +static int spi_tx_done(stm32_spi_regs_t *spi) +{ + return !(spi->sr & (STM32_SPI_SR_FTLVL | STM32_SPI_SR_BSY)); +} + +static int spi_rx_done(stm32_spi_regs_t *spi) +{ + return !(spi->sr & (STM32_SPI_SR_FRLVL | STM32_SPI_SR_RXNE)); +} + +/* Read until RX FIFO is empty (i.e. RX done) */ +static int spi_clear_rx_fifo(stm32_spi_regs_t *spi) +{ + uint8_t unused __attribute__((unused)); + uint32_t start = __hw_clock_source_read(), delta; + + while (!spi_rx_done(spi)) { + unused = spi->dr; /* Read one byte from FIFO */ + delta = __hw_clock_source_read() - start; + if (delta >= SPI_TRANSACTION_TIMEOUT_USEC) + return EC_ERROR_TIMEOUT; + } + return EC_SUCCESS; +} + +/* Wait until TX FIFO is empty (i.e. TX done) */ +static int spi_clear_tx_fifo(stm32_spi_regs_t *spi) +{ + uint32_t start = __hw_clock_source_read(), delta; + + while (!spi_tx_done(spi)) { + /* wait for TX complete */ + delta = __hw_clock_source_read() - start; + if (delta >= SPI_TRANSACTION_TIMEOUT_USEC) + return EC_ERROR_TIMEOUT; + } + return EC_SUCCESS; +} + +/** + * Initialize SPI module, registers, and clocks + * + * - port: which port to initialize. + */ +static int spi_controller_initialize(const struct spi_device_t *spi_device) +{ + int port = spi_device->port; + + stm32_spi_regs_t *spi = SPI_REGS[port]; + + /* + * Set SPI controller, baud rate, and software peripheral control. + * */ + + /* + * STM32F412 + * Section 26.3.5 Chip select (NSS) pin management and Figure 276 + * https://www.st.com/resource/en/reference_manual/dm00180369.pdf#page=817 + * + * The documentation in this section is a bit confusing, so here's a + * summary based on discussion with ST: + * + * Software NSS management (SSM = 1): + * - In controller mode, the NSS output is deactivated. You need to + * use a GPIO in output mode for chip select. This is generally used + * for multi-peripheral operation, but you can also use it for + * single peripheral operation. In this case, you should make sure + * to configure a GPIO for NSS, but *not* activate the SPI alternate + * function on that same pin since that will enable hardware NSS + * management (see below). + * - In peripheral mode, the NSS input level is equal to the SSI bit + * value. + * + * Hardware NSS management (SSM = 0): + * - In peripheral mode, when NSS pin is detected low the peripheral + * (MCU) is selected. + * - In controller mode, there are two configurations, depending on + * the SSOE bit in register SPIx_CR1. + * - NSS output enable (SSM=0, SSOE=1): + * The MCU (controller) drives NSS low as soon as SPI is enabled + * (SPE=1) and releases it when SPI is disabled (SPE=0). + * + * - NSS output disable (SSM=0, SSOE=0): + * Allows multi-controller capability. The MCU (controller) + * drives NSS low. If another controller tries to takes control + * of the bus and NSS is pulled low, a mode fault is generated + * and the MCU changes to peripheral mode. + * + * - NSS output disable (SSM=0, SSOE=0): if the MCU is acting as + * controller on the bus, this config allows multi-controller + * capability. If the NSS pin is pulled low in this mode, the SPI + * enters controller mode fault state and the device is + * automatically reconfigured in peripheral mode. In peripheral + * mode, the NSS pin works as a standard "chip select" input and the + * peripheral is selected while NSS lin is at low level. + */ + spi->cr1 = STM32_SPI_CR1_MSTR | STM32_SPI_CR1_SSM | STM32_SPI_CR1_SSI | + (spi_device->div << 3); + +#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) + dma_select_channel(dma_tx_option[port].channel, dma_req[port].tx_req); + dma_select_channel(dma_rx_option[port].channel, dma_req[port].rx_req); +#endif + /* + * Configure 8-bit datasize, set FRXTH, enable DMA, + * and set data size (applies to STM32F0 only). + * + * STM32F412: + * https://www.st.com/resource/en/reference_manual/dm00180369.pdf#page=852 + * + * + * STM32F0: + * https://www.st.com/resource/en/reference_manual/dm00031936.pdf#page=803 + */ + spi->cr2 = STM32_SPI_CR2_TXDMAEN | STM32_SPI_CR2_RXDMAEN | + STM32_SPI_CR2_FRXTH | STM32_SPI_CR2_DATASIZE(8); + +#ifdef CONFIG_SPI_HALFDUPLEX + spi->cr1 |= STM32_SPI_CR1_BIDIMODE | STM32_SPI_CR1_BIDIOE; +#endif + + /* Drive Chip Select high before turning on SPI module */ + gpio_set_level(spi_device->gpio_cs, 1); + + /* Enable SPI hardware module. This will actively drive the CLK pin */ + spi->cr1 |= STM32_SPI_CR1_SPE; + + /* Set flag */ + spi_enabled[port] = 1; + + return EC_SUCCESS; +} + +/** + * Shutdown SPI module + */ +static int spi_controller_shutdown(const struct spi_device_t *spi_device) +{ + int rv = EC_SUCCESS; + int port = spi_device->port; + stm32_spi_regs_t *spi = SPI_REGS[port]; + + /* Set flag */ + spi_enabled[port] = 0; + + /* Disable DMA streams */ + dma_disable(dma_tx_option[port].channel); + dma_disable(dma_rx_option[port].channel); + + /* Disable SPI. Let the CLK pin float. */ + spi->cr1 &= ~STM32_SPI_CR1_SPE; + + spi_clear_rx_fifo(spi); + + /* Disable DMA buffers */ + spi->cr2 &= ~(STM32_SPI_CR2_TXDMAEN | STM32_SPI_CR2_RXDMAEN); + + return rv; +} + +int spi_enable(const struct spi_device_t *spi_device, int enable) +{ + if (enable == spi_enabled[spi_device->port]) + return EC_SUCCESS; + if (enable) + return spi_controller_initialize(spi_device); + else + return spi_controller_shutdown(spi_device); +} + +static int spi_dma_start(int port, const uint8_t *txdata, uint8_t *rxdata, + int len) +{ + dma_chan_t *txdma; + + /* Set up RX DMA */ + if (rxdata) + dma_start_rx(&dma_rx_option[port], len, rxdata); + + /* Set up TX DMA */ + if (txdata) { + txdma = dma_get_channel(dma_tx_option[port].channel); + dma_prepare_tx(&dma_tx_option[port], len, txdata); + dma_go(txdma); + } + + return EC_SUCCESS; +} + +static bool dma_is_enabled_(const struct dma_option *option) +{ + return dma_is_enabled(dma_get_channel(option->channel)); +} + +static int spi_dma_wait(int port) +{ + int rv = EC_SUCCESS; + + /* Wait for DMA transmission to complete */ + if (dma_is_enabled_(&dma_tx_option[port])) { + /* + * In TX mode, SPI only generates clock when we write to FIFO. + * Therefore, even though `dma_wait` polls with interval 0.1ms, + * we won't send extra bytes. + */ + rv = dma_wait(dma_tx_option[port].channel); + if (rv) + return rv; + /* Disable TX DMA */ + dma_disable(dma_tx_option[port].channel); + } + + /* Wait for DMA reception to complete */ + if (dma_is_enabled_(&dma_rx_option[port])) { + /* + * Because `dma_wait` polls with interval 0.1ms, we will read at + * least ~100 bytes (with 8MHz clock). If you don't want this + * overhead, you can use interrupt handler + * (`dma_enable_tc_interrupt_callback`) and disable SPI + * interface in callback function. + */ + rv = dma_wait(dma_rx_option[port].channel); + if (rv) + return rv; + /* Disable RX DMA */ + dma_disable(dma_rx_option[port].channel); + } + return rv; +} + +static uint8_t spi_chip_select_already_asserted[ARRAY_SIZE(SPI_REGS)]; + +int spi_transaction_async(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) +{ + int rv = EC_SUCCESS; + int port = spi_device->port; + int full_readback = 0; + + stm32_spi_regs_t *spi = SPI_REGS[port]; + char *buf = NULL; + + /* We should not ever be called when disabled, but fail early if so. */ + if (!spi_enabled[port]) + return EC_ERROR_BUSY; + +#ifndef CONFIG_SPI_HALFDUPLEX + if (rxlen == SPI_READBACK_ALL) { + buf = rxdata; + full_readback = 1; + } else { + rv = shared_mem_acquire(MAX(txlen, rxlen), &buf); + if (rv != EC_SUCCESS) + return rv; + } +#endif + + if (IS_ENABLED(CONFIG_USB_SPI)) { + spi_chip_select_already_asserted[port] = + !gpio_get_level(spi_device->gpio_cs); + } + + /* Drive SS low */ + gpio_set_level(spi_device->gpio_cs, 0); + + spi_clear_rx_fifo(spi); + + /* Initiate write part of the transaction, non-blocking. */ + if (txlen) { + rv = spi_dma_start(port, txdata, buf, txlen); + if (rv != EC_SUCCESS) + goto err_free; +#ifdef CONFIG_SPI_HALFDUPLEX + spi->cr1 |= STM32_SPI_CR1_BIDIOE; +#endif + } + + if (full_readback) + return EC_SUCCESS; + + if (rxlen) { + /* + * If "write then read" was requested, then we have to wait for + * the write to complete, before we can initiate read. + */ + if (txlen) { + rv = spi_dma_wait(port); + if (rv != EC_SUCCESS) + goto err_free; + + spi_clear_tx_fifo(spi); + } + + /* Initiate read part of the transaction, non-blocking. */ + rv = spi_dma_start(port, buf, rxdata, rxlen); + if (rv != EC_SUCCESS) + goto err_free; +#ifdef CONFIG_SPI_HALFDUPLEX + spi->cr1 &= ~STM32_SPI_CR1_BIDIOE; +#endif + } + + /* + * At this point, there is EITHER a pending non-blocking write OR a + * pending non-blocking read. In either case, spi_transaction_flush() + * will wait for completion of the DMA transfer, and also make sure + * that any last bits in the transmit shift register is flushed. + */ + +err_free: +#ifndef CONFIG_SPI_HALFDUPLEX + if (!full_readback) + shared_mem_release(buf); +#endif + return rv; +} + +int spi_transaction_flush(const struct spi_device_t *spi_device) +{ + int rv = spi_dma_wait(spi_device->port); + int port = spi_device->port; + stm32_spi_regs_t *spi = SPI_REGS[port]; + + /* + * For the case that the DMA transfer just finished was for SPI + * transfer, ensure that the last bits are fully transmitted before + * releasing CS. + */ + spi_clear_tx_fifo(spi); + + if (!IS_ENABLED(CONFIG_USB_SPI) || + !spi_chip_select_already_asserted[spi_device->port]) { + /* Drive SS high */ + gpio_set_level(spi_device->gpio_cs, 1); + } + + return rv; +} + +int spi_transaction_wait(const struct spi_device_t *spi_device) +{ + return spi_dma_wait(spi_device->port); +} + +int spi_transaction(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) +{ + int rv; + int port = spi_device->port; + + mutex_lock(spi_mutex + port); + rv = spi_transaction_async(spi_device, txdata, txlen, rxdata, rxlen); + rv |= spi_transaction_flush(spi_device); + mutex_unlock(spi_mutex + port); + + return rv; +} diff --git a/chip/stm32/spi_master-stm32h7.c b/chip/stm32/spi_master-stm32h7.c deleted file mode 100644 index 6f661b72bf..0000000000 --- a/chip/stm32/spi_master-stm32h7.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * SPI master driver. - */ - -#include "common.h" -#include "dma.h" -#include "gpio.h" -#include "shared_mem.h" -#include "spi.h" -#include "stm32-dma.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* SPI ports are used as master */ -static stm32_spi_regs_t *SPI_REGS[] = { -#ifdef CONFIG_STM32_SPI1_MASTER - STM32_SPI1_REGS, -#endif - STM32_SPI2_REGS, - STM32_SPI3_REGS, - STM32_SPI4_REGS, -}; - -/* DMA request mapping on channels */ -static uint8_t dma_req_tx[ARRAY_SIZE(SPI_REGS)] = { -#ifdef CONFIG_STM32_SPI1_MASTER - DMAMUX1_REQ_SPI1_TX, -#endif - DMAMUX1_REQ_SPI2_TX, - DMAMUX1_REQ_SPI3_TX, - DMAMUX1_REQ_SPI4_TX, -}; -static uint8_t dma_req_rx[ARRAY_SIZE(SPI_REGS)] = { -#ifdef CONFIG_STM32_SPI1_MASTER - DMAMUX1_REQ_SPI1_RX, -#endif - DMAMUX1_REQ_SPI2_RX, - DMAMUX1_REQ_SPI3_RX, - DMAMUX1_REQ_SPI4_RX, -}; - -static struct mutex spi_mutex[ARRAY_SIZE(SPI_REGS)]; - -#define SPI_TRANSACTION_TIMEOUT_USEC (800 * MSEC) - -static const struct dma_option dma_tx_option[] = { -#ifdef CONFIG_STM32_SPI1_MASTER - { - STM32_DMAC_SPI1_TX, (void *)&STM32_SPI1_REGS->txdr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - }, -#endif - { - STM32_DMAC_SPI2_TX, (void *)&STM32_SPI2_REGS->txdr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - }, - { - STM32_DMAC_SPI3_TX, (void *)&STM32_SPI3_REGS->txdr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - }, - { - STM32_DMAC_SPI4_TX, (void *)&STM32_SPI4_REGS->txdr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - }, -}; - -static const struct dma_option dma_rx_option[] = { -#ifdef CONFIG_STM32_SPI1_MASTER - { - STM32_DMAC_SPI1_RX, (void *)&STM32_SPI1_REGS->rxdr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - }, -#endif - { - STM32_DMAC_SPI2_RX, (void *)&STM32_SPI2_REGS->rxdr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - }, - { - STM32_DMAC_SPI3_RX, (void *)&STM32_SPI3_REGS->rxdr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - }, - { - STM32_DMAC_SPI4_RX, (void *)&STM32_SPI4_REGS->rxdr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - }, -}; - -static uint8_t spi_enabled[ARRAY_SIZE(SPI_REGS)]; - -/** - * Initialize SPI module, registers, and clocks - * - * - port: which port to initialize. - */ -static void spi_master_config(int port) -{ - int i, div = 0; - - stm32_spi_regs_t *spi = SPI_REGS[port]; - - /* - * Set SPI master, baud rate, and software slave control. - */ - for (i = 0; i < spi_devices_used; i++) - if ((spi_devices[i].port == port) && - (div < spi_devices[i].div)) - div = spi_devices[i].div; - - spi->cr1 = STM32_SPI_CR1_SSI; - spi->cfg2 = STM32_SPI_CFG2_MSTR | STM32_SPI_CFG2_SSM - | STM32_SPI_CFG2_AFCNTR; - spi->cfg1 = STM32_SPI_CFG1_DATASIZE(8) | STM32_SPI_CFG1_FTHLV(4) - | STM32_SPI_CFG1_CRCSIZE(8) | STM32_SPI_CR1_DIV(div); - - dma_select_channel(dma_tx_option[port].channel, dma_req_tx[port]); - dma_select_channel(dma_rx_option[port].channel, dma_req_rx[port]); -} - -static int spi_master_initialize(int port) -{ - int i; - - spi_master_config(port); - - for (i = 0; i < spi_devices_used; i++) { - if (spi_devices[i].port != port) - continue; - /* Drive SS high */ - gpio_set_level(spi_devices[i].gpio_cs, 1); - } - - /* Set flag */ - spi_enabled[port] = 1; - - return EC_SUCCESS; -} - -/** - * Shutdown SPI module - */ -static int spi_master_shutdown(int port) -{ - int rv = EC_SUCCESS; - stm32_spi_regs_t *spi = SPI_REGS[port]; - - /* Set flag */ - spi_enabled[port] = 0; - - /* Disable DMA streams */ - dma_disable(dma_tx_option[port].channel); - dma_disable(dma_rx_option[port].channel); - - /* Disable SPI */ - spi->cr1 &= ~STM32_SPI_CR1_SPE; - - /* Disable DMA buffers */ - spi->cfg1 &= ~(STM32_SPI_CFG1_TXDMAEN | STM32_SPI_CFG1_RXDMAEN); - - return rv; -} - -int spi_enable(int port, int enable) -{ - if (enable == spi_enabled[port]) - return EC_SUCCESS; - if (enable) - return spi_master_initialize(port); - else - return spi_master_shutdown(port); -} - -static int spi_dma_start(int port, const uint8_t *txdata, - uint8_t *rxdata, int len) -{ - dma_chan_t *txdma; - stm32_spi_regs_t *spi = SPI_REGS[port]; - - /* - * Workaround for STM32H7 errata: without resetting the SPI controller, - * the RX DMA requests will happen too early on the 2nd transfer. - */ - STM32_RCC_APB2RSTR = STM32_RCC_PB2_SPI4; - STM32_RCC_APB2RSTR = 0; - dma_clear_isr(dma_tx_option[port].channel); - dma_clear_isr(dma_rx_option[port].channel); - /* restore proper SPI configuration registers. */ - spi_master_config(port); - - spi->cr2 = len; - spi->cfg1 |= STM32_SPI_CFG1_RXDMAEN; - /* Set up RX DMA */ - if (rxdata) - dma_start_rx(&dma_rx_option[port], len, rxdata); - - /* Set up TX DMA */ - if (txdata) { - txdma = dma_get_channel(dma_tx_option[port].channel); - dma_prepare_tx(&dma_tx_option[port], len, txdata); - dma_go(txdma); - } - - spi->cfg1 |= STM32_SPI_CFG1_TXDMAEN; - spi->cr1 |= STM32_SPI_CR1_SPE; - spi->cr1 |= STM32_SPI_CR1_CSTART; - - return EC_SUCCESS; -} - -static inline bool dma_is_enabled_(const struct dma_option *option) -{ - return dma_is_enabled(dma_get_channel(option->channel)); -} - -static int spi_dma_wait(int port) -{ - timestamp_t timeout; - stm32_spi_regs_t *spi = SPI_REGS[port]; - int rv = EC_SUCCESS; - - /* Wait for DMA transmission to complete */ - if (dma_is_enabled_(&dma_tx_option[port])) { - rv = dma_wait(dma_tx_option[port].channel); - if (rv) - return rv; - - timeout.val = get_time().val + SPI_TRANSACTION_TIMEOUT_USEC; - /* Wait for FIFO empty and BSY bit clear */ - while (!(spi->sr & (STM32_SPI_SR_TXC))) - if (get_time().val > timeout.val) - return EC_ERROR_TIMEOUT; - - /* Disable TX DMA */ - dma_disable(dma_tx_option[port].channel); - } - - /* Wait for DMA reception to complete */ - if (dma_is_enabled_(&dma_rx_option[port])) { - rv = dma_wait(dma_rx_option[port].channel); - if (rv) - return rv; - - timeout.val = get_time().val + SPI_TRANSACTION_TIMEOUT_USEC; - /* Wait for FRLVL[1:0] to indicate FIFO empty */ - while (spi->sr & (STM32_SPI_SR_FRLVL | STM32_SPI_SR_RXNE)) - if (get_time().val > timeout.val) - return EC_ERROR_TIMEOUT; - - /* Disable RX DMA */ - dma_disable(dma_rx_option[port].channel); - } - - spi->cr1 &= ~STM32_SPI_CR1_SPE; - spi->cfg1 &= ~(STM32_SPI_CFG1_TXDMAEN | STM32_SPI_CFG1_RXDMAEN); - - return rv; -} - -int spi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - int rv = EC_SUCCESS; - int port = spi_device->port; - int full_readback = 0; - - char *buf = NULL; - -#ifndef CONFIG_SPI_HALFDUPLEX - if (rxlen == SPI_READBACK_ALL) { - buf = rxdata; - full_readback = 1; - } else { - rv = shared_mem_acquire(MAX(txlen, rxlen), &buf); - if (rv != EC_SUCCESS) - return rv; - } -#endif - - /* Drive SS low */ - gpio_set_level(spi_device->gpio_cs, 0); - - rv = spi_dma_start(port, txdata, buf, txlen); - if (rv != EC_SUCCESS) - goto err_free; - - if (full_readback) - return EC_SUCCESS; - - if (rxlen) { - rv = spi_dma_wait(port); - if (rv != EC_SUCCESS) - goto err_free; - - rv = spi_dma_start(port, buf, rxdata, rxlen); - if (rv != EC_SUCCESS) - goto err_free; - } - -err_free: - if (!full_readback) - shared_mem_release(buf); - return rv; -} - -int spi_transaction_flush(const struct spi_device_t *spi_device) -{ - int rv = spi_dma_wait(spi_device->port); - - /* Drive SS high */ - gpio_set_level(spi_device->gpio_cs, 1); - - return rv; -} - -int spi_transaction_wait(const struct spi_device_t *spi_device) -{ - return spi_dma_wait(spi_device->port); -} - -int spi_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - int rv; - int port = spi_device->port; - - mutex_lock(spi_mutex + port); - rv = spi_transaction_async(spi_device, txdata, txlen, rxdata, rxlen); - rv |= spi_transaction_flush(spi_device); - mutex_unlock(spi_mutex + port); - - return rv; -} diff --git a/chip/stm32/spi_master.c b/chip/stm32/spi_master.c deleted file mode 100644 index c2d36bb4d9..0000000000 --- a/chip/stm32/spi_master.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * SPI master driver. - */ - -#include "common.h" -#include "dma.h" -#include "gpio.h" -#include "hwtimer.h" -#include "shared_mem.h" -#include "spi.h" -#include "stm32-dma.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#if defined(CHIP_VARIANT_STM32F373) || \ - defined(CHIP_FAMILY_STM32L4) || \ - defined(CHIP_VARIANT_STM32F76X) -#define HAS_SPI3 -#else -#undef HAS_SPI3 -#endif - -/* The second (and third if available) SPI port are used as master */ -static stm32_spi_regs_t *SPI_REGS[] = { -#ifdef CONFIG_STM32_SPI1_MASTER - STM32_SPI1_REGS, -#endif - STM32_SPI2_REGS, -#ifdef HAS_SPI3 - STM32_SPI3_REGS, -#endif -}; - -#ifdef CHIP_FAMILY_STM32L4 -/* DMA request mapping on channels */ -static uint8_t dma_req[ARRAY_SIZE(SPI_REGS)] = { -#ifdef CONFIG_STM32_SPI1_MASTER - /* SPI1 */ 1, -#endif - /* SPI2 */ 1, - /* SPI3 */ 3, -}; -#endif - -static struct mutex spi_mutex[ARRAY_SIZE(SPI_REGS)]; - -#define SPI_TRANSACTION_TIMEOUT_USEC (800 * MSEC) - -/* Default DMA channel options */ -#ifdef CHIP_FAMILY_STM32F4 -#define F4_CHANNEL(ch) STM32_DMA_CCR_CHANNEL(ch) -#else -#define F4_CHANNEL(ch) 0 -#endif - -static const struct dma_option dma_tx_option[] = { -#ifdef CONFIG_STM32_SPI1_MASTER - { - STM32_DMAC_SPI1_TX, (void *)&STM32_SPI1_REGS->dr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - | F4_CHANNEL(STM32_SPI1_TX_REQ_CH) - }, -#endif - { - STM32_DMAC_SPI2_TX, (void *)&STM32_SPI2_REGS->dr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - | F4_CHANNEL(STM32_SPI2_TX_REQ_CH) - }, -#ifdef HAS_SPI3 - { - STM32_DMAC_SPI3_TX, (void *)&STM32_SPI3_REGS->dr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - | F4_CHANNEL(STM32_SPI3_TX_REQ_CH) - }, -#endif -}; - -static const struct dma_option dma_rx_option[] = { -#ifdef CONFIG_STM32_SPI1_MASTER - { - STM32_DMAC_SPI1_RX, (void *)&STM32_SPI1_REGS->dr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - | F4_CHANNEL(STM32_SPI1_RX_REQ_CH) - }, -#endif - { - STM32_DMAC_SPI2_RX, (void *)&STM32_SPI2_REGS->dr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - | F4_CHANNEL(STM32_SPI2_RX_REQ_CH) - }, -#ifdef HAS_SPI3 - { - STM32_DMAC_SPI3_RX, (void *)&STM32_SPI3_REGS->dr, - STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT - | F4_CHANNEL(STM32_SPI3_RX_REQ_CH) - }, -#endif -}; - -static uint8_t spi_enabled[ARRAY_SIZE(SPI_REGS)]; - -static int spi_tx_done(stm32_spi_regs_t *spi) -{ - return !(spi->sr & (STM32_SPI_SR_FTLVL | STM32_SPI_SR_BSY)); -} - -static int spi_rx_done(stm32_spi_regs_t *spi) -{ - return !(spi->sr & (STM32_SPI_SR_FRLVL | STM32_SPI_SR_RXNE)); -} - -/* Read until RX FIFO is empty (i.e. RX done) */ -static int spi_clear_rx_fifo(stm32_spi_regs_t *spi) -{ - uint8_t unused __attribute__((unused)); - uint32_t start = __hw_clock_source_read(), delta; - - while (!spi_rx_done(spi)) { - unused = spi->dr; /* Read one byte from FIFO */ - delta = __hw_clock_source_read() - start; - if (delta >= SPI_TRANSACTION_TIMEOUT_USEC) - return EC_ERROR_TIMEOUT; - } - return EC_SUCCESS; -} - -/* Wait until TX FIFO is empty (i.e. TX done) */ -static int spi_clear_tx_fifo(stm32_spi_regs_t *spi) -{ - uint32_t start = __hw_clock_source_read(), delta; - - while (!spi_tx_done(spi)) { - /* wait for TX complete */ - delta = __hw_clock_source_read() - start; - if (delta >= SPI_TRANSACTION_TIMEOUT_USEC) - return EC_ERROR_TIMEOUT; - } - return EC_SUCCESS; -} - -/** - * Initialize SPI module, registers, and clocks - * - * - port: which port to initialize. - */ -static int spi_master_initialize(int port) -{ - int i, div = 0; - - stm32_spi_regs_t *spi = SPI_REGS[port]; - - /* - * Set SPI master, baud rate, and software slave control. - * */ - for (i = 0; i < spi_devices_used; i++) - if ((spi_devices[i].port == port) && - (div < spi_devices[i].div)) - div = spi_devices[i].div; - - /* - * STM32F412 - * Section 26.3.5 Slave select (NSS) pin management and Figure 276 - * https://www.st.com/resource/en/reference_manual/dm00180369.pdf#page=817 - * - * The documentation in this section is a bit confusing, so here's a - * summary based on discussion with ST: - * - * Software NSS management (SSM = 1): - * - In master mode, the NSS output is deactivated. You need to use a - * GPIO in output mode for slave select. This is generally used for - * multi-slave operation, but you can also use it for single slave - * operation. In this case, you should make sure to configure a GPIO - * for NSS, but *not* activate the SPI alternate function on that - * same pin since that will enable hardware NSS management (see - * below). - * - In slave mode, the NSS input level is equal to the SSI bit value. - * - * Hardware NSS management (SSM = 0): - * - In slave mode, when NSS pin is detected low the slave (MCU) is - * selected. - * - In master mode, there are two configurations, depending on the - * SSOE bit in register SPIx_CR1. - * - NSS output enable (SSM=0, SSOE=1): - * The MCU (master) drives NSS low as soon as SPI is enabled - * (SPE=1) and releases it when SPI is disabled (SPE=0). - * - * - NSS output disable (SSM=0, SSOE=0): - * Allows multimaster capability. The MCU (master) drives NSS - * low. If another master tries to takes control of the bus and - * NSS is pulled low, a mode fault is generated and the MCU - * changes to slave mode. - * - * - NSS output disable (SSM=0, SSOE=0): if the MCU is acting as - * master on the bus, this config allows multimaster capability. If - * the NSS pin is pulled low in this mode, the SPI enters master - * mode fault state and the device is automatically reconfigured in - * slave mode. In slave mode, the NSS pin works as a standard "chip - * select" input and the slave is selected while NSS lin is at low - * level. - */ - spi->cr1 = STM32_SPI_CR1_MSTR | STM32_SPI_CR1_SSM | STM32_SPI_CR1_SSI | - (div << 3); - -#ifdef CHIP_FAMILY_STM32L4 - dma_select_channel(dma_tx_option[port].channel, dma_req[port]); - dma_select_channel(dma_rx_option[port].channel, dma_req[port]); -#endif - /* - * Configure 8-bit datasize, set FRXTH, enable DMA, - * and set data size (applies to STM32F0 only). - * - * STM32F412: - * https://www.st.com/resource/en/reference_manual/dm00180369.pdf#page=852 - * - * - * STM32F0: - * https://www.st.com/resource/en/reference_manual/dm00031936.pdf#page=803 - */ - spi->cr2 = STM32_SPI_CR2_TXDMAEN | STM32_SPI_CR2_RXDMAEN | - STM32_SPI_CR2_FRXTH | STM32_SPI_CR2_DATASIZE(8); - -#ifdef CONFIG_SPI_HALFDUPLEX - spi->cr1 |= STM32_SPI_CR1_BIDIMODE | STM32_SPI_CR1_BIDIOE; -#endif - - /* Drive Chip Select high for all ports before turning on SPI module */ - for (i = 0; i < spi_devices_used; i++) { - if (spi_devices[i].port != port) - continue; - gpio_set_level(spi_devices[i].gpio_cs, 1); - } - - /* Enable SPI hardware module. This will actively drive the CLK pin */ - spi->cr1 |= STM32_SPI_CR1_SPE; - - /* Set flag */ - spi_enabled[port] = 1; - - return EC_SUCCESS; -} - -/** - * Shutdown SPI module - */ -static int spi_master_shutdown(int port) -{ - int rv = EC_SUCCESS; - - stm32_spi_regs_t *spi = SPI_REGS[port]; - - /* Set flag */ - spi_enabled[port] = 0; - - /* Disable DMA streams */ - dma_disable(dma_tx_option[port].channel); - dma_disable(dma_rx_option[port].channel); - - /* Disable SPI. Let the CLK pin float. */ - spi->cr1 &= ~STM32_SPI_CR1_SPE; - - spi_clear_rx_fifo(spi); - - /* Disable DMA buffers */ - spi->cr2 &= ~(STM32_SPI_CR2_TXDMAEN | STM32_SPI_CR2_RXDMAEN); - - return rv; -} - -int spi_enable(int port, int enable) -{ - if (enable == spi_enabled[port]) - return EC_SUCCESS; - if (enable) - return spi_master_initialize(port); - else - return spi_master_shutdown(port); -} - -static int spi_dma_start(int port, const uint8_t *txdata, - uint8_t *rxdata, int len) -{ - dma_chan_t *txdma; - - /* Set up RX DMA */ - if (rxdata) - dma_start_rx(&dma_rx_option[port], len, rxdata); - - /* Set up TX DMA */ - if (txdata) { - txdma = dma_get_channel(dma_tx_option[port].channel); - dma_prepare_tx(&dma_tx_option[port], len, txdata); - dma_go(txdma); - } - - return EC_SUCCESS; -} - -static bool dma_is_enabled_(const struct dma_option *option) -{ - return dma_is_enabled(dma_get_channel(option->channel)); -} - -static int spi_dma_wait(int port) -{ - int rv = EC_SUCCESS; - - /* Wait for DMA transmission to complete */ - if (dma_is_enabled_(&dma_tx_option[port])) { - /* - * In TX mode, SPI only generates clock when we write to FIFO. - * Therefore, even though `dma_wait` polls with interval 0.1ms, - * we won't send extra bytes. - */ - rv = dma_wait(dma_tx_option[port].channel); - if (rv) - return rv; - /* Disable TX DMA */ - dma_disable(dma_tx_option[port].channel); - } - - /* Wait for DMA reception to complete */ - if (dma_is_enabled_(&dma_rx_option[port])) { - /* - * Because `dma_wait` polls with interval 0.1ms, we will read at - * least ~100 bytes (with 8MHz clock). If you don't want this - * overhead, you can use interrupt handler - * (`dma_enable_tc_interrupt_callback`) and disable SPI - * interface in callback function. - */ - rv = dma_wait(dma_rx_option[port].channel); - if (rv) - return rv; - /* Disable RX DMA */ - dma_disable(dma_rx_option[port].channel); - } - return rv; -} - -int spi_transaction_async(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - int rv = EC_SUCCESS; - int port = spi_device->port; - int full_readback = 0; - - stm32_spi_regs_t *spi = SPI_REGS[port]; - char *buf = NULL; - - /* We should not ever be called when disabled, but fail early if so. */ - if (!spi_enabled[port]) - return EC_ERROR_BUSY; - -#ifndef CONFIG_SPI_HALFDUPLEX - if (rxlen == SPI_READBACK_ALL) { - buf = rxdata; - full_readback = 1; - } else { - rv = shared_mem_acquire(MAX(txlen, rxlen), &buf); - if (rv != EC_SUCCESS) - return rv; - } -#endif - - /* Drive SS low */ - gpio_set_level(spi_device->gpio_cs, 0); - - spi_clear_rx_fifo(spi); - - rv = spi_dma_start(port, txdata, buf, txlen); - if (rv != EC_SUCCESS) - goto err_free; - -#ifdef CONFIG_SPI_HALFDUPLEX - spi->cr1 |= STM32_SPI_CR1_BIDIOE; -#endif - - if (full_readback) - return EC_SUCCESS; - - rv = spi_dma_wait(port); - if (rv != EC_SUCCESS) - goto err_free; - - spi_clear_tx_fifo(spi); - - if (rxlen) { - rv = spi_dma_start(port, buf, rxdata, rxlen); - if (rv != EC_SUCCESS) - goto err_free; -#ifdef CONFIG_SPI_HALFDUPLEX - spi->cr1 &= ~STM32_SPI_CR1_BIDIOE; -#endif - } - -err_free: -#ifndef CONFIG_SPI_HALFDUPLEX - if (!full_readback) - shared_mem_release(buf); -#endif - return rv; -} - -int spi_transaction_flush(const struct spi_device_t *spi_device) -{ - int rv = spi_dma_wait(spi_device->port); - - /* Drive SS high */ - gpio_set_level(spi_device->gpio_cs, 1); - - return rv; -} - -int spi_transaction_wait(const struct spi_device_t *spi_device) -{ - return spi_dma_wait(spi_device->port); -} - -int spi_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) -{ - int rv; - int port = spi_device->port; - - mutex_lock(spi_mutex + port); - rv = spi_transaction_async(spi_device, txdata, txlen, rxdata, rxlen); - rv |= spi_transaction_flush(spi_device); - mutex_unlock(spi_mutex + port); - - return rv; -} diff --git a/chip/stm32/stm32-dma.h b/chip/stm32/stm32-dma.h index 06233b9c93..3bda9ec41d 100644 --- a/chip/stm32/stm32-dma.h +++ b/chip/stm32/stm32-dma.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/stm32/system.c b/chip/stm32/system.c index aad35820c7..6d7c4b624a 100644 --- a/chip/stm32/system.c +++ b/chip/stm32/system.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,6 +9,7 @@ #include "clock.h" #include "console.h" #include "cpu.h" +#include "cros_version.h" #include "flash.h" #include "gpio_chip.h" #include "hooks.h" @@ -18,7 +19,6 @@ #include "system.h" #include "task.h" #include "util.h" -#include "version.h" #include "watchdog.h" #ifdef CONFIG_STM32_CLOCK_LSE @@ -28,10 +28,10 @@ #define BDCR_SRC BDCR_SRC_LSI #define BDCR_RDY 0 #endif -#define BDCR_ENABLE_VALUE (STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC) | \ - BDCR_RDY) -#define BDCR_ENABLE_MASK (BDCR_ENABLE_VALUE | BDCR_RTCSEL_MASK | \ - STM32_RCC_BDCR_BDRST) +#define BDCR_ENABLE_VALUE \ + (STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC) | BDCR_RDY) +#define BDCR_ENABLE_MASK \ + (BDCR_ENABLE_VALUE | BDCR_RTCSEL_MASK | STM32_RCC_BDCR_BDRST) #ifdef CONFIG_USB_PD_DUAL_ROLE BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT <= 3); @@ -87,12 +87,16 @@ static void check_reset_cause(void) { uint32_t flags = chip_read_reset_flags(); uint32_t raw_cause = STM32_RCC_RESET_CAUSE; +#ifdef STM32_PWR_RESET_CAUSE uint32_t pwr_status = STM32_PWR_RESET_CAUSE; +#endif /* Clear the hardware reset cause by setting the RMVF bit */ STM32_RCC_RESET_CAUSE |= RESET_CAUSE_RMVF; +#ifdef STM32_PWR_RESET_CAUSE /* Clear SBF in PWR_CSR */ STM32_PWR_RESET_CAUSE_CLR |= RESET_CAUSE_SBF_CLR; +#endif /* Clear saved reset flags */ chip_save_reset_flags(0); @@ -114,9 +118,11 @@ static void check_reset_cause(void) if (raw_cause & RESET_CAUSE_PIN) flags |= EC_RESET_FLAG_RESET_PIN; +#ifdef STM32_PWR_RESET_CAUSE if (pwr_status & RESET_CAUSE_SBF) /* Hibernated and subsequently awakened */ flags |= EC_RESET_FLAG_HIBERNATE; +#endif if (!flags && (raw_cause & RESET_CAUSE_OTHER)) flags |= EC_RESET_FLAG_OTHER; @@ -143,61 +149,73 @@ void chip_pre_init(void) uint32_t apb2fz_reg = 0; #if defined(CHIP_FAMILY_STM32F0) - apb1fz_reg = - STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | STM32_RCC_PB1_TIM6 | - STM32_RCC_PB1_TIM7 | STM32_RCC_PB1_WWDG | STM32_RCC_PB1_IWDG; + apb1fz_reg = STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | + STM32_RCC_PB1_TIM6 | STM32_RCC_PB1_TIM7 | + STM32_RCC_PB1_WWDG | STM32_RCC_PB1_IWDG; apb2fz_reg = STM32_RCC_PB2_TIM15 | STM32_RCC_PB2_TIM16 | - STM32_RCC_PB2_TIM17 | STM32_RCC_PB2_TIM1; + STM32_RCC_PB2_TIM17 | STM32_RCC_PB2_TIM1; /* enable clock to debug module before writing */ STM32_RCC_APB2ENR |= STM32_RCC_DBGMCUEN; #elif defined(CHIP_FAMILY_STM32F3) - apb1fz_reg = - STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | STM32_RCC_PB1_TIM4 | - STM32_RCC_PB1_TIM5 | STM32_RCC_PB1_TIM6 | STM32_RCC_PB1_TIM7 | - STM32_RCC_PB1_WWDG | STM32_RCC_PB1_IWDG; - apb2fz_reg = - STM32_RCC_PB2_TIM15 | STM32_RCC_PB2_TIM16 | STM32_RCC_PB2_TIM17; + apb1fz_reg = STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | + STM32_RCC_PB1_TIM4 | STM32_RCC_PB1_TIM5 | + STM32_RCC_PB1_TIM6 | STM32_RCC_PB1_TIM7 | + STM32_RCC_PB1_WWDG | STM32_RCC_PB1_IWDG; + apb2fz_reg = STM32_RCC_PB2_TIM15 | STM32_RCC_PB2_TIM16 | + STM32_RCC_PB2_TIM17; #elif defined(CHIP_FAMILY_STM32F4) - apb1fz_reg = - STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | STM32_RCC_PB1_TIM4 | - STM32_RCC_PB1_TIM5 | STM32_RCC_PB1_TIM6 | STM32_RCC_PB1_TIM7 | - STM32_RCC_PB1_TIM12 | STM32_RCC_PB1_TIM13 | STM32_RCC_PB1_TIM14| - STM32_RCC_PB1_RTC | STM32_RCC_PB1_WWDG | STM32_RCC_PB1_IWDG; - apb2fz_reg = - STM32_RCC_PB2_TIM1 | STM32_RCC_PB2_TIM8 | STM32_RCC_PB2_TIM9 | - STM32_RCC_PB2_TIM10 | STM32_RCC_PB2_TIM11; + apb1fz_reg = STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | + STM32_RCC_PB1_TIM4 | STM32_RCC_PB1_TIM5 | + STM32_RCC_PB1_TIM6 | STM32_RCC_PB1_TIM7 | + STM32_RCC_PB1_TIM12 | STM32_RCC_PB1_TIM13 | + STM32_RCC_PB1_TIM14 | STM32_RCC_PB1_RTC | + STM32_RCC_PB1_WWDG | STM32_RCC_PB1_IWDG; + apb2fz_reg = STM32_RCC_PB2_TIM1 | STM32_RCC_PB2_TIM8 | + STM32_RCC_PB2_TIM9 | STM32_RCC_PB2_TIM10 | + STM32_RCC_PB2_TIM11; #elif defined(CHIP_FAMILY_STM32L4) - apb1fz_reg = - STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | STM32_RCC_PB1_TIM4 | - STM32_RCC_PB1_TIM5 | STM32_RCC_PB1_TIM6 | STM32_RCC_PB1_TIM7 | - STM32_RCC_PB1_WWDG | STM32_RCC_PB1_IWDG; + +#ifdef CHIP_VARIANT_STM32L431X + apb1fz_reg = STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM7 | + STM32_RCC_PB1_TIM6 | STM32_RCC_PB1_WWDG | + STM32_RCC_PB1_IWDG; + apb2fz_reg = STM32_RCC_PB2_TIM1 | STM32_RCC_PB2_TIM15 | + STM32_RCC_PB2_TIM16; +#else + apb1fz_reg = STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | + STM32_RCC_PB1_TIM4 | STM32_RCC_PB1_TIM5 | + STM32_RCC_PB1_TIM6 | STM32_RCC_PB1_TIM7 | + STM32_RCC_PB1_WWDG | STM32_RCC_PB1_IWDG; apb2fz_reg = STM32_RCC_PB2_TIM1 | STM32_RCC_PB2_TIM8; +#endif #elif defined(CHIP_FAMILY_STM32L) - apb1fz_reg = - STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | STM32_RCC_PB1_TIM4 | - STM32_RCC_PB1_WWDG | STM32_RCC_PB1_IWDG; + apb1fz_reg = STM32_RCC_PB1_TIM2 | STM32_RCC_PB1_TIM3 | + STM32_RCC_PB1_TIM4 | STM32_RCC_PB1_WWDG | + STM32_RCC_PB1_IWDG; apb2fz_reg = STM32_RCC_PB2_TIM9 | STM32_RCC_PB2_TIM10 | - STM32_RCC_PB2_TIM11; + STM32_RCC_PB2_TIM11; #elif defined(CHIP_FAMILY_STM32G4) - apb1fz_reg = - STM32_DBGMCU_APB1FZ_TIM2 | STM32_DBGMCU_APB1FZ_TIM3 | - STM32_DBGMCU_APB1FZ_TIM4 | STM32_DBGMCU_APB1FZ_TIM5 | - STM32_DBGMCU_APB1FZ_TIM6 | STM32_DBGMCU_APB1FZ_TIM7 | - STM32_DBGMCU_APB1FZ_RTC | STM32_DBGMCU_APB1FZ_WWDG | - STM32_DBGMCU_APB1FZ_IWDG; - apb2fz_reg = - STM32_DBGMCU_APB2FZ_TIM1 | STM32_DBGMCU_APB2FZ_TIM8 | - STM32_DBGMCU_APB2FZ_TIM15 | STM32_DBGMCU_APB2FZ_TIM16 | - STM32_DBGMCU_APB2FZ_TIM17 | STM32_DBGMCU_APB2FZ_TIM20; + apb1fz_reg = STM32_DBGMCU_APB1FZ_TIM2 | STM32_DBGMCU_APB1FZ_TIM3 | + STM32_DBGMCU_APB1FZ_TIM4 | STM32_DBGMCU_APB1FZ_TIM5 | + STM32_DBGMCU_APB1FZ_TIM6 | STM32_DBGMCU_APB1FZ_TIM7 | + STM32_DBGMCU_APB1FZ_RTC | STM32_DBGMCU_APB1FZ_WWDG | + STM32_DBGMCU_APB1FZ_IWDG; + apb2fz_reg = STM32_DBGMCU_APB2FZ_TIM1 | STM32_DBGMCU_APB2FZ_TIM8 | + STM32_DBGMCU_APB2FZ_TIM15 | STM32_DBGMCU_APB2FZ_TIM16 | + STM32_DBGMCU_APB2FZ_TIM17 | STM32_DBGMCU_APB2FZ_TIM20; #elif defined(CHIP_FAMILY_STM32H7) /* TODO(b/67081508) */ #endif - +#if defined(CHIP_FAMILY_STM32L5) + (void)apb1fz_reg; + (void)apb2fz_reg; +#else if (apb1fz_reg) STM32_DBGMCU_APB1FZ |= apb1fz_reg; if (apb2fz_reg) STM32_DBGMCU_APB2FZ |= apb2fz_reg; +#endif } #ifdef CONFIG_PVD @@ -234,7 +252,7 @@ static void configure_pvd(void) STM32_PWR_CR |= STM32_PWR_PVDE; } -void pvd_interrupt(void) +static void pvd_interrupt(void) { /* Clear Pending Register */ STM32_EXTI_PR = EXTI_PVD_EVENT; @@ -247,21 +265,27 @@ DECLARE_IRQ(STM32_IRQ_PVD, pvd_interrupt, HOOK_PRIO_FIRST); void system_pre_init(void) { -#ifdef CONFIG_SOFTWARE_PANIC uint16_t reason, info; - uint8_t exception; -#endif + uint8_t exception, panic_flags; + struct panic_data *pdata; /* enable clock on Power module */ #ifndef CHIP_FAMILY_STM32H7 +#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) + STM32_RCC_APB1ENR1 |= STM32_RCC_PWREN; +#else STM32_RCC_APB1ENR |= STM32_RCC_PWREN; #endif +#endif #if defined(CHIP_FAMILY_STM32F4) /* enable backup registers */ STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_BKPSRAMEN; #elif defined(CHIP_FAMILY_STM32H7) /* enable backup registers */ STM32_RCC_AHB4ENR |= BIT(28); +#elif defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) + /* enable RTC APB clock */ + STM32_RCC_APB1ENR1 |= STM32_RCC_APB1ENR1_RTCAPBEN; #else /* enable backup registers */ STM32_RCC_APB1ENR |= BIT(27); @@ -280,6 +304,13 @@ void system_pre_init(void) /* Wait for LSI to be ready */ while (!(STM32_RCC_CSR & BIT(1))) ; + +#if defined(CHIP_FAMILY_STM32G4) + /* Make sure PWR clock is enabled */ + STM32_RCC_APB1ENR1 |= STM32_RCC_APB1ENR1_PWREN; + /* Enable access to backup domain registers */ + STM32_PWR_CR1 |= STM32_PWR_CR1_DBP; +#endif /* re-configure RTC if needed */ #ifdef CHIP_FAMILY_STM32L if ((STM32_RCC_CSR & 0x00C30000) != 0x00420000) { @@ -288,9 +319,10 @@ void system_pre_init(void) /* Enable RTC and use LSI as clock source */ STM32_RCC_CSR = (STM32_RCC_CSR & ~0x00C30000) | 0x00420000; } -#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \ - defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32F4) || \ - defined(CHIP_FAMILY_STM32H7) || defined(CHIP_FAMILY_STM32G4) +#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \ + defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) || \ + defined(CHIP_FAMILY_STM32F4) || defined(CHIP_FAMILY_STM32H7) || \ + defined(CHIP_FAMILY_STM32G4) if ((STM32_RCC_BDCR & BDCR_ENABLE_MASK) != BDCR_ENABLE_VALUE) { /* The RTC settings are bad, we need to reset it */ STM32_RCC_BDCR |= STM32_RCC_BDCR_BDRST; @@ -311,7 +343,6 @@ void system_pre_init(void) check_reset_cause(); -#ifdef CONFIG_SOFTWARE_PANIC /* Restore then clear saved panic reason */ reason = bkpdata_read(BKPDATA_INDEX_SAVED_PANIC_REASON); info = bkpdata_read(BKPDATA_INDEX_SAVED_PANIC_INFO); @@ -322,7 +353,20 @@ void system_pre_init(void) bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_INFO, 0); bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_EXCEPTION, 0); } -#endif + + /* + * Older ROs restore reason, info, and exception, but do not support + * the saved panic flags. In that case, we will let RW handle restoring + * the panic flags. If we get to this point in the code and the panic + * data does not exist, it doesn't make sense to try to only restore + * the panic flags, the information was lost. + */ + pdata = panic_get_data(); + panic_flags = bkpdata_read(BKPDATA_INDEX_SAVED_PANIC_FLAGS); + if (pdata && panic_flags) { + pdata->flags = panic_flags; + bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_FLAGS, 0); + } #ifdef CONFIG_PVD configure_pvd(); @@ -358,32 +402,47 @@ void system_reset(int flags) if (flags & SYSTEM_RESET_STAY_IN_RO) save_flags |= EC_RESET_FLAG_STAY_IN_RO; -#ifdef CONFIG_STM32_RESET_FLAGS_EXTENDED if (flags & SYSTEM_RESET_AP_WATCHDOG) save_flags |= EC_RESET_FLAG_AP_WATCHDOG; -#endif chip_save_reset_flags(save_flags); - if (flags & SYSTEM_RESET_HARD) { -#ifdef CONFIG_SOFTWARE_PANIC - uint32_t reason, info; - uint8_t exception; +#ifdef CONFIG_ARMV7M_CACHE + /* + * Disable caches (D-cache is also flushed and invalidated) + * so changes that lives in cache are saved in memory now. + * Any subsequent writes will be done immediately. + */ + cpu_disable_caches(); +#endif + if (flags & SYSTEM_RESET_HARD) { /* Panic data will be wiped by hard reset, so save it */ - panic_get_reason(&reason, &info, &exception); - /* 16 bits stored - upper 16 bits of reason / info are lost */ - bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_REASON, reason); - bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_INFO, info); - bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_EXCEPTION, exception); -#endif + uint32_t reason, info; + uint8_t exception, panic_flags; + struct panic_data *pdata = panic_get_data(); + + if (pdata) { + panic_flags = pdata->flags; + panic_get_reason(&reason, &info, &exception); + /* + * 16 bits stored - upper 16 bits of reason / info + * are lost. + */ + bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_REASON, reason); + bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_INFO, info); + bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_EXCEPTION, + exception); + bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_FLAGS, + panic_flags); + } -#ifdef CHIP_FAMILY_STM32L +#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32L4) /* * Ask the flash module to reboot, so that we reload the * option bytes. */ - flash_physical_force_reload(); + crec_flash_physical_force_reload(); /* Fall through to watchdog if that fails */ #endif @@ -396,7 +455,7 @@ void system_reset(int flags) * use this for hard reset. */ STM32_FLASH_CR |= FLASH_CR_OBL_LAUNCH; -#elif defined(CHIP_FAMILY_STM32L4) +#elif defined(CHIP_FAMILY_STM32G4) STM32_FLASH_KEYR = FLASH_KEYR_KEY1; STM32_FLASH_KEYR = FLASH_KEYR_KEY2; STM32_FLASH_OPTKEYR = FLASH_OPTKEYR_KEY1; @@ -424,6 +483,23 @@ void system_reset(int flags) * (IWDG_KR = 0x0000 AAAA) */ + /* + * RM0433 Rev 7 + * Section 45.4.4 Page 1920 + * https://www.st.com/resource/en/reference_manual/dm00314099.pdf + * If several reload, prescaler, or window values are used by + * the application, it is mandatory to wait until RVU bit is + * reset before changing the reload value, to wait until PVU bit + * is reset before changing the prescaler value, and to wait + * until WVU bit is reset before changing the window value. + * + * Here we should wait to finish previous IWDG_RLR register + * update (see watchdog_init()) before starting next update, + * otherwise new IWDG_RLR value will be lost. + */ + while (STM32_IWDG_SR & STM32_IWDG_SR_RVU) + ; + /* * Enable IWDG, which shouldn't be necessary since the IWDG * only needs to be started once, but STM32F412 hangs unless @@ -436,9 +512,11 @@ void system_reset(int flags) /* Ask the watchdog to trigger a hard reboot */ STM32_IWDG_KR = STM32_IWDG_KR_UNLOCK; STM32_IWDG_RLR = 0x1; - /* Wait for value to be reloaded. */ + /* Wait for value to be updated. */ while (STM32_IWDG_SR & STM32_IWDG_SR_RVU) ; + + /* Reload IWDG counter, it also locks registers */ STM32_IWDG_KR = STM32_IWDG_KR_RELOAD; #endif /* wait for the chip to reboot */ @@ -472,9 +550,10 @@ int system_set_scratchpad(uint32_t value) return bkpdata_write(BKPDATA_INDEX_SCRATCHPAD, (uint16_t)value); } -uint32_t system_get_scratchpad(void) +int system_get_scratchpad(uint32_t *value) { - return (uint32_t)bkpdata_read(BKPDATA_INDEX_SCRATCHPAD); + *value = (uint32_t)bkpdata_read(BKPDATA_INDEX_SCRATCHPAD); + return EC_SUCCESS; } const char *system_get_chip_vendor(void) @@ -547,16 +626,19 @@ int system_is_reboot_warm(void) #elif defined(CHIP_FAMILY_STM32L) return ((STM32_RCC_AHBENR & 0x3f) == 0x3f); #elif defined(CHIP_FAMILY_STM32L4) - return ((STM32_RCC_AHB2ENR & STM32_RCC_AHB2ENR_GPIOMASK) - == STM32_RCC_AHB2ENR_GPIOMASK); + return ((STM32_RCC_AHB2ENR & STM32_RCC_AHB2ENR_GPIOMASK) == + STM32_RCC_AHB2ENR_GPIOMASK); +#elif defined(CHIP_FAMILY_STM32L5) + return ((STM32_RCC_AHB2ENR & STM32_RCC_AHB2ENR_GPIOMASK) == + STM32_RCC_AHB2ENR_GPIOMASK); #elif defined(CHIP_FAMILY_STM32F4) - return ((STM32_RCC_AHB1ENR & STM32_RCC_AHB1ENR_GPIOMASK) - == gpio_required_clocks()); + return ((STM32_RCC_AHB1ENR & STM32_RCC_AHB1ENR_GPIOMASK) == + gpio_required_clocks()); #elif defined(CHIP_FAMILY_STM32G4) - return ((STM32_RCC_AHB2ENR & STM32_RCC_AHB2ENR_GPIOMASK) - == gpio_required_clocks()); + return ((STM32_RCC_AHB2ENR & STM32_RCC_AHB2ENR_GPIOMASK) == + gpio_required_clocks()); #elif defined(CHIP_FAMILY_STM32H7) - return ((STM32_RCC_AHB4ENR & STM32_RCC_AHB4ENR_GPIOMASK) - == STM32_RCC_AHB4ENR_GPIOMASK); + return ((STM32_RCC_AHB4ENR & STM32_RCC_AHB4ENR_GPIOMASK) == + STM32_RCC_AHB4ENR_GPIOMASK); #endif } diff --git a/chip/stm32/trng.c b/chip/stm32/trng.c index 48d5335c53..63641741d3 100644 --- a/chip/stm32/trng.c +++ b/chip/stm32/trng.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,13 +9,14 @@ #include "console.h" #include "host_command.h" #include "panic.h" +#include "printf.h" #include "registers.h" #include "system.h" #include "task.h" #include "trng.h" #include "util.h" -uint32_t rand(void) +uint32_t trng_rand(void) { int tries = 300; /* Wait for a valid random number */ @@ -28,26 +29,7 @@ uint32_t rand(void) return STM32_RNG_DR; } -test_mockable void rand_bytes(void *buffer, size_t len) -{ - while (len) { - uint32_t number = rand(); - size_t cnt = 4; - /* deal with the lack of alignment guarantee in the API */ - uintptr_t align = (uintptr_t)buffer & 3; - - if (len < 4 || align) { - cnt = MIN(4 - align, len); - memcpy(buffer, &number, cnt); - } else { - *(uint32_t *)buffer = number; - } - len -= cnt; - buffer += cnt; - } -} - -test_mockable void init_trng(void) +test_mockable void trng_init(void) { #ifdef CHIP_FAMILY_STM32L4 /* Enable the 48Mhz internal RC oscillator */ @@ -57,8 +39,8 @@ test_mockable void init_trng(void) ; /* Clock the TRNG using the HSI48 */ - STM32_RCC_CCIPR = (STM32_RCC_CCIPR & ~STM32_RCC_CCIPR_CLK48SEL_MASK) - | (0 << STM32_RCC_CCIPR_CLK48SEL_SHIFT); + STM32_RCC_CCIPR = (STM32_RCC_CCIPR & ~STM32_RCC_CCIPR_CLK48SEL_MASK) | + (0 << STM32_RCC_CCIPR_CLK48SEL_SHIFT); #elif defined(CHIP_FAMILY_STM32H7) /* Enable the 48Mhz internal RC oscillator */ STM32_RCC_CR |= STM32_RCC_CR_HSI48ON; @@ -68,8 +50,8 @@ test_mockable void init_trng(void) /* Clock the TRNG using the HSI48 */ STM32_RCC_D2CCIP2R = - (STM32_RCC_D2CCIP2R & ~STM32_RCC_D2CCIP2_RNGSEL_MASK) - | STM32_RCC_D2CCIP2_RNGSEL_HSI48; + (STM32_RCC_D2CCIP2R & ~STM32_RCC_D2CCIP2_RNGSEL_MASK) | + STM32_RCC_D2CCIP2_RNGSEL_HSI48; #elif defined(CHIP_FAMILY_STM32F4) /* * The RNG clock is the same as the SDIO/USB OTG clock, already set at @@ -84,7 +66,7 @@ test_mockable void init_trng(void) STM32_RNG_CR |= STM32_RNG_CR_RNGEN; } -test_mockable void exit_trng(void) +test_mockable void trng_exit(void) { STM32_RNG_CR &= ~STM32_RNG_CR_RNGEN; STM32_RCC_AHB2ENR &= ~STM32_RCC_AHB2ENR_RNGEN; @@ -96,50 +78,3 @@ test_mockable void exit_trng(void) /* Nothing to do */ #endif } - -#if defined(CONFIG_CMD_RAND) -/* - * We want to avoid accidentally exposing debug commands in RO since we can't - * update RO once in production. - */ -#if defined(SECTION_IS_RW) -static int command_rand(int argc, char **argv) -{ - uint8_t data[32]; - - init_trng(); - rand_bytes(data, sizeof(data)); - exit_trng(); - - ccprintf("rand %ph\n", HEX_BUF(data, sizeof(data))); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(rand, command_rand, - NULL, "Output random bytes to console."); - -static enum ec_status host_command_rand(struct host_cmd_handler_args *args) -{ - const struct ec_params_rand_num *p = args->params; - struct ec_response_rand_num *r = args->response; - uint16_t num_rand_bytes = p->num_rand_bytes; - - if (system_is_locked()) - return EC_RES_ACCESS_DENIED; - - if (num_rand_bytes > args->response_max) - return EC_RES_OVERFLOW; - - init_trng(); - rand_bytes(r->rand, num_rand_bytes); - exit_trng(); - - args->response_size = num_rand_bytes; - - return EC_SUCCESS; -} - -DECLARE_HOST_COMMAND(EC_CMD_RAND_NUM, host_command_rand, - EC_VER_MASK(EC_VER_RAND_NUM)); -#endif /* SECTION_IS_RW */ -#endif /* CONFIG_CMD_RAND */ diff --git a/chip/stm32/uart.c b/chip/stm32/uart.c index 39727d71f1..916cb2257a 100644 --- a/chip/stm32/uart.c +++ b/chip/stm32/uart.c @@ -1,24 +1,24 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* USART driver for Chrome EC */ -#include "common.h" #include "clock.h" +#include "common.h" #include "dma.h" #include "gpio.h" #include "hooks.h" #include "registers.h" +#include "stm32-dma.h" #include "system.h" #include "task.h" #include "uart.h" #include "util.h" -#include "stm32-dma.h" /* Console USART index */ -#define UARTN CONFIG_UART_CONSOLE +#define UARTN CONFIG_UART_CONSOLE #define UARTN_BASE STM32_USART_BASE(CONFIG_UART_CONSOLE) #ifdef CONFIG_UART_TX_DMA @@ -33,7 +33,7 @@ static const struct dma_option dma_tx_option = { CONFIG_UART_TX_DMA_CH, (void *)&STM32_USART_TDR(UARTN_BASE), STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT #ifdef CHIP_FAMILY_STM32F4 - | STM32_DMA_CCR_CHANNEL(CONFIG_UART_TX_REQ_CH) + | STM32_DMA_CCR_CHANNEL(CONFIG_UART_TX_REQ_CH) #endif }; @@ -51,16 +51,16 @@ static const struct dma_option dma_rx_option = { CONFIG_UART_RX_DMA_CH, (void *)&STM32_USART_RDR(UARTN_BASE), STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT | #ifdef CHIP_FAMILY_STM32F4 - STM32_DMA_CCR_CHANNEL(CONFIG_UART_RX_REQ_CH) | + STM32_DMA_CCR_CHANNEL(CONFIG_UART_RX_REQ_CH) | #endif - STM32_DMA_CCR_CIRC + STM32_DMA_CCR_CIRC }; -static int dma_rx_len; /* Size of receive DMA circular buffer */ +static int dma_rx_len; /* Size of receive DMA circular buffer */ #endif -static int init_done; /* Initialization done? */ -static int should_stop; /* Last TX control action */ +static int init_done; /* Initialization done? */ +static int should_stop; /* Last TX control action */ int uart_init_done(void) { @@ -161,7 +161,7 @@ int uart_read_char(void) } /* Interrupt handler for console USART */ -void uart_interrupt(void) +static void uart_interrupt(void) { #ifndef CONFIG_UART_TX_DMA /* @@ -176,7 +176,14 @@ void uart_interrupt(void) #if defined(CHIP_FAMILY_STM32F4) STM32_USART_SR(UARTN_BASE) &= ~STM32_USART_SR_TC; #else - STM32_USART_ICR(UARTN_BASE) |= STM32_USART_SR_TC; + /* + * ST reference code does blind write to this register, as is + * usual with the "write 1 to clear" convention, despite the + * datasheet listing the bits as "keep at reset value", (which + * we assume is due to copying from the description of + * reserved bits in read/write registers.) + */ + STM32_USART_ICR(UARTN_BASE) = STM32_USART_SR_TC; #endif if (!(STM32_USART_SR(UARTN_BASE) & ~STM32_USART_SR_TC)) return; @@ -234,18 +241,21 @@ static void uart_freq_change(void) freq = 8000000; #elif defined(CHIP_FAMILY_STM32H7) freq = 64000000; /* from 64 Mhz HSI */ +#elif defined(CHIP_FAMILY_STM32L4) + /* UART clocked from HSI 16 */ + freq = 16000000; #else /* UART clocked from the main clock */ freq = clock_get_freq(); #endif -#if (UARTN == 9) /* LPUART */ +#if (UARTN == 9) /* LPUART */ div = DIV_ROUND_NEAREST(freq, CONFIG_UART_BAUD_RATE) * 256; #else div = DIV_ROUND_NEAREST(freq, CONFIG_UART_BAUD_RATE); #endif -#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32F0) || \ +#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32F0) || \ defined(CHIP_FAMILY_STM32F3) || defined(CHIP_FAMILY_STM32L4) || \ defined(CHIP_FAMILY_STM32F4) || defined(CHIP_FAMILY_STM32G4) if (div / 16 > 0) { @@ -267,7 +277,6 @@ static void uart_freq_change(void) /* STM32F only supports x16 oversampling */ STM32_USART_BRR(UARTN_BASE) = div; #endif - } DECLARE_HOOK(HOOK_FREQ_CHANGE, uart_freq_change, HOOK_PRIO_DEFAULT); @@ -276,7 +285,7 @@ void uart_init(void) /* Select clock source */ #if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) #if (UARTN == 1) - STM32_RCC_CFGR3 |= 0x0003; /* USART1 clock source from HSI(8MHz) */ + STM32_RCC_CFGR3 |= 0x0003; /* USART1 clock source from HSI(8MHz) */ #elif (UARTN == 2) STM32_RCC_CFGR3 |= 0x030000; /* USART2 clock source from HSI(8MHz) */ #endif /* UARTN */ @@ -289,17 +298,29 @@ void uart_init(void) #elif defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32G4) /* USART1 clock source from SYSCLK */ STM32_RCC_CCIPR &= ~STM32_RCC_CCIPR_USART1SEL_MASK; +#ifdef CHIP_FAMILY_STM32L4 + /* For STM32L4, use HSI for UART, to wake up from low power mode */ STM32_RCC_CCIPR |= - (STM32_RCC_CCIPR_UART_SYSCLK << STM32_RCC_CCIPR_USART1SEL_SHIFT); + (STM32_RCC_CCIPR_UART_HSI16 << STM32_RCC_CCIPR_USART1SEL_SHIFT); +#else + STM32_RCC_CCIPR |= (STM32_RCC_CCIPR_UART_SYSCLK + << STM32_RCC_CCIPR_USART1SEL_SHIFT); +#endif /* LPUART1 clock source from SYSCLK */ STM32_RCC_CCIPR &= ~STM32_RCC_CCIPR_LPUART1SEL_MASK; - STM32_RCC_CCIPR |= - (STM32_RCC_CCIPR_UART_SYSCLK << STM32_RCC_CCIPR_LPUART1SEL_SHIFT); + STM32_RCC_CCIPR |= (STM32_RCC_CCIPR_UART_SYSCLK + << STM32_RCC_CCIPR_LPUART1SEL_SHIFT); #endif /* CHIP_FAMILY_STM32F0 || CHIP_FAMILY_STM32F3 */ /* Enable USART clock */ #if (UARTN == 1) STM32_RCC_APB2ENR |= STM32_RCC_PB2_USART1; +#ifdef CHIP_FAMILY_STM32L4 +#if defined(CONFIG_UART_RX_DMA) || defined(CONFIG_UART_TX_DMA) + STM32_RCC_AHB1ENR |= STM32_RCC_HB1_DMA1; + STM32_RCC_AHB1ENR |= STM32_RCC_HB1_DMA2; +#endif +#endif #elif (UARTN == 6) STM32_RCC_APB2ENR |= STM32_RCC_PB2_USART6; #elif (UARTN == 9) @@ -317,8 +338,8 @@ void uart_init(void) /* Configure GPIOs */ gpio_config_module(MODULE_UART, 1); -#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) \ -|| defined(CHIP_FAMILY_STM32H7) +#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \ + defined(CHIP_FAMILY_STM32H7) || defined(CHIP_FAMILY_STM32L4) /* * Wake up on start bit detection. WUS can only be written when UE=0, * so clear UE first. @@ -330,15 +351,19 @@ void uart_init(void) * and we don't want to clear an extra flag in the interrupt */ STM32_USART_CR3(UARTN_BASE) |= STM32_USART_CR3_WUS_START_BIT | - STM32_USART_CR3_OVRDIS; + STM32_USART_CR3_OVRDIS; #endif /* * UART enabled, 8 Data bits, oversampling x16, no parity, * TX and RX enabled. */ - STM32_USART_CR1(UARTN_BASE) = - STM32_USART_CR1_UE | STM32_USART_CR1_TE | STM32_USART_CR1_RE; +#ifdef CHIP_FAMILY_STM32L4 + STM32_USART_CR1(UARTN_BASE) = STM32_USART_CR1_TE | STM32_USART_CR1_RE; +#else + STM32_USART_CR1(UARTN_BASE) = STM32_USART_CR1_UE | STM32_USART_CR1_TE | + STM32_USART_CR1_RE; +#endif /* 1 stop bit, no fancy stuff */ STM32_USART_CR2(UARTN_BASE) = 0x0000; @@ -375,6 +400,10 @@ void uart_init(void) /* Enable interrupts */ task_enable_irq(STM32_IRQ_USART(UARTN)); +#ifdef CHIP_FAMILY_STM32L4 + STM32_USART_CR1(UARTN_BASE) |= STM32_USART_CR1_UE; +#endif + init_done = 1; } diff --git a/chip/stm32/ucpd-stm32gx.c b/chip/stm32/ucpd-stm32gx.c index 1355d9f042..424792c5d0 100644 --- a/chip/stm32/ucpd-stm32gx.c +++ b/chip/stm32/ucpd-stm32gx.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,46 +7,348 @@ #include "clock.h" #include "common.h" +#include "console.h" +#include "driver/tcpm/tcpm.h" #include "gpio.h" #include "hooks.h" +#include "hwtimer.h" #include "registers.h" #include "task.h" +#include "timer.h" #include "ucpd-stm32gx.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +#define USB_VID_STM32 0x0483 /* - * UCPD is fed directly from HSI which is @ 16MHz. The ucpd_clk goes to - * a prescaler who's output feeds the 'half-bit' divider which is used - * to generate clock for delay counters and BMC Rx/Tx blocks. The rx is - * designed to work in freq ranges of 6 <--> 18 MHz, however recommended - * range is 9 <--> 18 MHz. - * - * ------- @ 16 MHz --------- @ ~600 kHz ------------- - * HSI ---->| /psc |-------->| /hbit |--------------->| trans_cnt | - * ------- --------- | ------------- - * | ------------- - * |---------->| ifrgap_cnt| - * ------------- - * Requirements: - * 1. hbit_clk ~= 600 kHz: 16 MHz / 600 kHz = 26.67 - * 2. tTransitionWindow - 12 to 20 uSec - * 3. tInterframGap - uSec - * - * hbit_clk = HSI_clk / 26 = 615,385 kHz = 1.625 uSec period - * tTransitionWindow = 1.625 uS * 8 = 13 uS - * tInterFrameGap = 1.625 uS * 17 = 27.625 uS + * USB PD message buffer length. Absent extended messages, the longest PD + * message will be 7 objects (4 bytes each) plus a 2 byte header. TCPMv2 + * suports extended messages via chunking so the data buffer length is + * set assumign that extended messages are chunked. */ -#define UCPD_PSC_DIV 1 -#define UCPD_HBIT_DIV 26 -#define UCPD_TRANSWIN_HBIT_CNT 8 -#define UCPD_IFRGAP_HBIT_CNT 17 +#define UCPD_BUF_LEN 30 + +#define UCPD_IMR_RX_INT_MASK \ + (STM32_UCPD_IMR_RXNEIE | STM32_UCPD_IMR_RXORDDETIE | \ + STM32_UCPD_IMR_RXHRSTDETIE | STM32_UCPD_IMR_RXOVRIE | \ + STM32_UCPD_IMR_RXMSGENDIE) + +#define UCPD_IMR_TX_INT_MASK \ + (STM32_UCPD_IMR_TXISIE | STM32_UCPD_IMR_TXMSGDISCIE | \ + STM32_UCPD_IMR_TXMSGSENTIE | STM32_UCPD_IMR_TXMSGABTIE | \ + STM32_UCPD_IMR_TXUNDIE) + +#define UCPD_ICR_TX_INT_MASK \ + (STM32_UCPD_ICR_TXMSGDISCCF | STM32_UCPD_ICR_TXMSGSENTCF | \ + STM32_UCPD_ICR_TXMSGABTCF | STM32_UCPD_ICR_TXUNDCF) #define UCPD_ANASUB_TO_RP(r) ((r - 1) & 0x3) #define UCPD_RP_TO_ANASUB(r) ((r + 1) & 0x3) +struct msg_header_info { + enum pd_power_role pr; + enum pd_data_role dr; +}; +static struct msg_header_info msg_header; + +/* States for managing tx messages in ucpd task */ +enum ucpd_state { + STATE_IDLE, + STATE_ACTIVE_TCPM, + STATE_ACTIVE_CRC, + STATE_HARD_RESET, + STATE_WAIT_CRC_ACK, +}; + +/* Events for pd_interrupt_handler_task */ +#define UCPD_EVT_GOOD_CRC_REQ BIT(0) +#define UCPD_EVT_TCPM_MSG_REQ BIT(1) +#define UCPD_EVT_HR_REQ BIT(2) +#define UCPD_EVT_TX_MSG_FAIL BIT(3) +#define UCPD_EVT_TX_MSG_DISC BIT(4) +#define UCPD_EVT_TX_MSG_SUCCESS BIT(5) +#define UCPD_EVT_HR_DONE BIT(6) +#define UCPD_EVT_HR_FAIL BIT(7) +#define UCPD_EVT_RX_GOOD_CRC BIT(8) +#define UCPD_EVT_RX_MSG BIT(9) + +#define UCPD_T_RECEIVE_US (1 * MSEC) + +#define UCPD_N_RETRY_COUNT_REV20 3 +#define UCPD_N_RETRY_COUNT_REV30 2 + +/* + * Tx messages are iniated either by TCPM/PRL layer or from ucpd when a GoodCRC + * ack message needs to be sent. + */ +enum ucpd_tx_msg { + TX_MSG_NONE = -1, + TX_MSG_TCPM = 0, + TX_MSG_GOOD_CRC = 1, + TX_MSG_TOTAL = 2, +}; + +#define MSG_TCPM_MASK BIT(TX_MSG_TCPM) +#define MSG_GOOD_CRC_MASK BIT(TX_MSG_GOOD_CRC) + +union buffer { + uint16_t header; + uint8_t msg[UCPD_BUF_LEN]; +}; + +struct ucpd_tx_desc { + enum tcpci_msg_type type; + int msg_len; + int msg_index; + union buffer data; +}; + +/* Track VCONN on/off state */ +static int ucpd_vconn_enable; + +/* Tx message variables */ +struct ucpd_tx_desc ucpd_tx_buffers[TX_MSG_TOTAL]; +struct ucpd_tx_desc *ucpd_tx_active_buffer; +static int ucpd_tx_request; +static int ucpd_timeout_us; +static enum ucpd_state ucpd_tx_state; +static int msg_id_match; +static int tx_retry_count; +static int tx_retry_max; + +static int ucpd_txorderset[] = { + TX_ORDERSET_SOP, + TX_ORDERSET_SOP_PRIME, + TX_ORDERSET_SOP_PRIME_PRIME, + TX_ORDERSET_SOP_PRIME_DEBUG, + TX_ORDERSET_SOP_PRIME_PRIME_DEBUG, + TX_ORDERSET_HARD_RESET, + TX_ORDERSET_CABLE_RESET, +}; + +/* PD Rx variables */ +static int ucpd_rx_byte_count; +static uint8_t ucpd_rx_buffer[UCPD_BUF_LEN]; +static int ucpd_crc_id; +static bool ucpd_rx_sop_prime_enabled; +static int ucpd_rx_msg_active; +static bool ucpd_rx_bist_mode; + +#ifdef CONFIG_STM32G4_UCPD_DEBUG +/* Defines and macros for ucpd state logging */ +#define TX_STATE_LOG_LEN BIT(5) +#define TX_STATE_LOG_MASK (TX_STATE_LOG_LEN - 1) + +struct ucpd_tx_state { + uint32_t ts; + int tx_request; + int timeout_us; + enum ucpd_state enter_state; + enum ucpd_state exit_state; + uint32_t evt; +}; + +struct ucpd_tx_state ucpd_tx_statelog[TX_STATE_LOG_LEN]; +int ucpd_tx_state_log_idx; +int ucpd_tx_state_log_freeze; + +static char ucpd_names[][12] = { + "TX_IDLE", "ACT_TCPM", "ACT_CRC", "HARD_RST", "WAIT_CRC", +}; +/* Defines and macros used for ucpd pd message logging */ +#define MSG_LOG_LEN 64 +#define MSG_BUF_LEN 10 + +struct msg_info { + uint8_t dir; + uint8_t comp; + uint8_t crc; + uint16_t header; + uint32_t ts; + uint8_t buf[MSG_BUF_LEN]; +}; +static int msg_log_cnt; +static int msg_log_idx; +static struct msg_info msg_log[MSG_LOG_LEN]; + +#define UCPD_CC_STRING_LEN 5 + +static char ccx[4][UCPD_CC_STRING_LEN] = { + "Ra", + "Rp", + "Rd", + "Open", +}; +static char rp_string[][8] = { + "Rp_usb", + "Rp_1.5", + "Rp_3.0", + "Open", +}; +static int ucpd_sr_cc_event; +static int ucpd_cc_set_save; +static int ucpd_cc_change_log; + +static int ucpd_is_cc_pull_active(int port, enum usbpd_cc_pin cc_line); + +static void ucpd_log_add_msg(uint16_t header, int dir) +{ + uint32_t ts = __hw_clock_source_read(); + int idx = msg_log_idx; + uint8_t *buf = dir ? ucpd_rx_buffer : ucpd_tx_active_buffer->data.msg; + + /* + * Add a msg entry in the history log. The log is currently designed to + * be from reset until MSG_LOG_LEN messages have been added. + * ts -> lower 32 bits of 1 uSec running clock + * dir -> 0 = tx message, 1 = rx message + * comp -> ucpd transmit success + * crc -> GoodCrc received following tx message + */ + if (msg_log_cnt++ < MSG_LOG_LEN) { + int msg_bytes = + MIN((PD_HEADER_CNT(header) << 2) + 2, MSG_BUF_LEN); + + msg_log[idx].header = header; + msg_log[idx].ts = ts; + msg_log[idx].dir = dir; + msg_log[idx].comp = 0; + msg_log[idx].crc = 0; + msg_log_idx++; + memcpy(msg_log[idx].buf, buf, msg_bytes); + } +} + +static void ucpd_log_mark_tx_comp(void) +{ + /* + * This msg logging utility function is used to mark when a message was + * successfully transmitted when transmit interrupt occurs and the tx + * message sent status was set. Because the transmit message is added + * before it's sent by ucpd, the index has to back up one to mark the + * correct log entry. + */ + if (msg_log_cnt < MSG_LOG_LEN) { + if (msg_log_idx > 0) + msg_log[msg_log_idx - 1].comp = 1; + } +} + +static void ucpd_log_mark_crc(void) +{ + /* + * This msg logging utility function is used to mark when a GoodCRC + * message is received following a tx message. This status is displayed + * in column s2. Because this indication follows both transmit message + * and GoodCRC rx, the index must be back up 2 rows to mark the correct + * tx message entry. + */ + if (msg_log_cnt < MSG_LOG_LEN) { + if (msg_log_idx >= 2) + msg_log[msg_log_idx - 2].crc = 1; + } +} + +static void ucpd_cc_status(int port) +{ + int rc = stm32gx_ucpd_get_role_control(port); + int cc1_pull, cc2_pull; + enum tcpc_cc_voltage_status v_cc1, v_cc2; + int rv; + char *rp_name; + + cc1_pull = rc & 0x3; + cc2_pull = (rc >> 2) & 0x3; + + /* + * This function is used to display CC settings, including pull type, + * and if Rp, what the Rp value is set to. In addition, the current + * values of CC voltage detector, polarity, and PD enable status are + * displayed. + */ + rv = stm32gx_ucpd_get_cc(port, &v_cc1, &v_cc2); + rp_name = rp_string[(rc >> 4) % 0x3]; + ccprintf("\tcc1\t = %s\n\tcc2\t = %s\n\tRp\t = %s\n", ccx[cc1_pull], + ccx[cc2_pull], rp_name); + if (!rv) + ccprintf("\tcc1_v\t = %d\n\tcc2_v\t = %d\n", v_cc1, v_cc2); +} + +void ucpd_cc_detect_notify_enable(int enable) +{ + /* + * This variable is used to control when a CC detach detector is + * active. + */ + ucpd_cc_change_log = enable; +} + +static void ucpd_log_invalidate_entry(void) +{ + /* + * This is a msg log utility function which is triggered when an + * unexpected detach event is detected. + */ + if (msg_log_idx < (MSG_LOG_LEN - 1)) { + int idx = msg_log_idx; + + msg_log[idx].header = 0xabcd; + msg_log[idx].ts = __hw_clock_source_read(); + msg_log[idx].dir = 0; + msg_log[idx].comp = 0; + msg_log[idx].crc = 0; + msg_log_cnt++; + msg_log_idx++; + } +} + +/* + * This function will mark in the msg log when a detach event occurs. It will + * only be active if ucpd_cc_change_log is set which can be controlled via the + * ucpd console command. + */ +static void ucpd_cc_change_notify(void) +{ + if (ucpd_cc_change_log) { + uint32_t sr = ucpd_sr_cc_event; + + ucpd_log_invalidate_entry(); + + ccprintf("vstate: cc1 = %x, cc2 = %x, Rp = %d\n", + (sr >> STM32_UCPD_SR_VSTATE_CC1_SHIFT) & 0x3, + (sr >> STM32_UCPD_SR_VSTATE_CC2_SHIFT) & 0x3, + (ucpd_cc_set_save >> STM32_UCPD_CR_ANASUBMODE_SHIFT) & + 0x3); + /* Display CC status on EC console */ + ucpd_cc_status(0); + } +} +DECLARE_DEFERRED(ucpd_cc_change_notify); +#endif /* CONFIG_STM32G4_UCPD_DEBUG */ + +static int ucpd_msg_is_good_crc(uint16_t header) +{ + /* + * Good CRC is a control message (no data objects) with GOOD_CRC message + * type in the header. + */ + return ((PD_HEADER_CNT(header) == 0) && (PD_HEADER_EXT(header) == 0) && + (PD_HEADER_TYPE(header) == PD_CTRL_GOOD_CRC)) ? + 1 : + 0; +} + +static void ucpd_hard_reset_rx_log(void) +{ + CPRINTS("ucpd: hard reset recieved"); +} +DECLARE_DEFERRED(ucpd_hard_reset_rx_log); + static void ucpd_port_enable(int port, int enable) { if (enable) @@ -57,40 +359,80 @@ static void ucpd_port_enable(int port, int enable) static int ucpd_is_cc_pull_active(int port, enum usbpd_cc_pin cc_line) { - int cc_enable = STM32_UCPD_CR(port) & STM32_UCPD_CR_CCENABLE_MASK >> - STM32_UCPD_CR_CCENABLE_SHIFT; + int cc_enable = (STM32_UCPD_CR(port) & STM32_UCPD_CR_CCENABLE_MASK) >> + STM32_UCPD_CR_CCENABLE_SHIFT; return ((cc_enable >> cc_line) & 0x1); } -void stm32gx_ucpd1_irq(void) +static void ucpd_tx_data_byte(int port) { - /* STM32_IRQ_UCPD indicates this is from UCPD1, so port = 0 */ - int port = 0; - uint32_t sr = STM32_UCPD_SR(port); + int index = ucpd_tx_active_buffer->msg_index++; - if (sr & (STM32_UCPD_SR_TYPECEVT1 | STM32_UCPD_SR_TYPECEVT2)) { - task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0); + STM32_UCPD_TXDR(port) = ucpd_tx_active_buffer->data.msg[index]; +} + +static void ucpd_rx_data_byte(int port) +{ + if (ucpd_rx_byte_count < UCPD_BUF_LEN) + ucpd_rx_buffer[ucpd_rx_byte_count++] = STM32_UCPD_RXDR(port); +} + +static void ucpd_tx_interrupts_enable(int port, int enable) +{ + if (enable) { + STM32_UCPD_ICR(port) = UCPD_ICR_TX_INT_MASK; + STM32_UCPD_IMR(port) |= UCPD_IMR_TX_INT_MASK; + } else { + STM32_UCPD_IMR(port) &= ~UCPD_IMR_TX_INT_MASK; } - /* Clear interrupts now that PD events have been set */ - STM32_UCPD_ICR(port) = sr; } -DECLARE_IRQ(STM32_IRQ_UCPD1, stm32gx_ucpd1_irq, 1); + +static void ucpd_rx_enque_error(void) +{ + CPRINTS("ucpd: TCPM Enque Error!!"); +} +DECLARE_DEFERRED(ucpd_rx_enque_error); + +static void stm32gx_ucpd_state_init(int port) +{ + /* Init variables used to manage tx process */ + ucpd_tx_request = 0; + tx_retry_count = 0; + ucpd_tx_state = STATE_IDLE; + ucpd_timeout_us = -1; + + /* Init variables used to manage rx */ + ucpd_rx_sop_prime_enabled = 0; + ucpd_rx_msg_active = 0; + ucpd_rx_bist_mode = 0; + + /* Vconn tracking variable */ + ucpd_vconn_enable = 0; +} int stm32gx_ucpd_init(int port) { uint32_t cfgr1_reg; + uint32_t moder_reg; + + /* Disable UCPD interrupts */ + task_disable_irq(STM32_IRQ_UCPD1); /* - * After exiting reset, stm32gx will have dead battery mode enabled by - * default which connects Rd to CC1/CC2. This should be disabled when EC - * is powered up. - */ + * After exiting reset, stm32gx will have dead battery mode enabled by + * default which connects Rd to CC1/CC2. This should be disabled when EC + * is powered up. + */ STM32_PWR_CR3 |= STM32_PWR_CR3_UCPD1_DBDIS; /* Ensure that clock to UCPD is enabled */ STM32_RCC_APB1ENR2 |= STM32_RCC_APB1ENR2_UPCD1EN; + /* Make sure CC1/CC2 pins PB4/PB6 are set for analog mode */ + moder_reg = STM32_GPIO_MODER(GPIO_B); + moder_reg |= 0x3300; + STM32_GPIO_MODER(GPIO_B) = moder_reg; /* * CFGR1 must be written when UCPD peripheral is disabled. Note that * disabling ucpd causes the peripheral to quit any ongoing activity and @@ -99,19 +441,31 @@ int stm32gx_ucpd_init(int port) ucpd_port_enable(port, 0); cfgr1_reg = STM32_UCPD_CFGR1_PSC_CLK_VAL(UCPD_PSC_DIV - 1) | - STM32_UCPD_CFGR1_TRANSWIN_VAL(UCPD_TRANSWIN_CNT - 1) | - STM32_UCPD_CFGR1_IFRGAP_VAL(UCPD_IFRGAP_CNT - 1) | - STM32_UCPD_CFGR1_HBITCLKD_VAL(UCPD_HBIT_DIV - 1); + STM32_UCPD_CFGR1_TRANSWIN_VAL(UCPD_TRANSWIN_CNT - 1) | + STM32_UCPD_CFGR1_IFRGAP_VAL(UCPD_IFRGAP_CNT - 1) | + STM32_UCPD_CFGR1_HBITCLKD_VAL(UCPD_HBIT_DIV - 1); STM32_UCPD_CFGR1(port) = cfgr1_reg; + /* + * Set RXORDSETEN field to control which types of ordered sets the PD + * receiver must receive. + * SOP, SOP', Hard Reset Det, Cable Reset Det enabled + */ + STM32_UCPD_CFGR1(port) |= STM32_UCPD_CFGR1_RXORDSETEN_VAL(0x1B); + /* Enable ucpd */ ucpd_port_enable(port, 1); /* Configure CC change interrupts */ STM32_UCPD_IMR(port) = STM32_UCPD_IMR_TYPECEVT1IE | - STM32_UCPD_IMR_TYPECEVT2IE; + STM32_UCPD_IMR_TYPECEVT2IE; STM32_UCPD_ICR(port) = STM32_UCPD_ICR_TYPECEVT1CF | - STM32_UCPD_ICR_TYPECEVT2CF; + STM32_UCPD_ICR_TYPECEVT2CF; + + /* SOP'/SOP'' must be enabled via TCPCI call */ + ucpd_rx_sop_prime_enabled = false; + + stm32gx_ucpd_state_init(port); /* Enable UCPD interrupts */ task_enable_irq(STM32_IRQ_UCPD1); @@ -127,7 +481,7 @@ int stm32gx_ucpd_release(int port) } int stm32gx_ucpd_get_cc(int port, enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) + enum tcpc_cc_voltage_status *cc2) { int vstate_cc1; int vstate_cc2; @@ -141,7 +495,7 @@ int stm32gx_ucpd_get_cc(int port, enum tcpc_cc_voltage_status *cc1, * * vstate_cc maps directly to cc_state from tcpci spec when ANAMODE = 1, * but needs to be modified slightly for case ANAMODE = 0. - * + * * If presenting Rp (source), then need to to a circular shift of * vstate_ccx value: * vstate_cc | cc_state @@ -156,9 +510,9 @@ int stm32gx_ucpd_get_cc(int port, enum tcpc_cc_voltage_status *cc1, /* Get Rp or Rd active */ anamode = !!(STM32_UCPD_CR(port) & STM32_UCPD_CR_ANAMODE); vstate_cc1 = (sr & STM32_UCPD_SR_VSTATE_CC1_MASK) >> - STM32_UCPD_SR_VSTATE_CC1_SHIFT; + STM32_UCPD_SR_VSTATE_CC1_SHIFT; vstate_cc2 = (sr & STM32_UCPD_SR_VSTATE_CC2_MASK) >> - STM32_UCPD_SR_VSTATE_CC2_SHIFT; + STM32_UCPD_SR_VSTATE_CC2_SHIFT; /* Do circular shift if port == source */ if (anamode) { @@ -185,8 +539,9 @@ int stm32gx_ucpd_get_role_control(int port) int cc1; int cc2; int anamode = !!(STM32_UCPD_CR(port) & STM32_UCPD_CR_ANAMODE); - int anasubmode = (STM32_UCPD_CR(port) & STM32_UCPD_CR_ANASUBMODE_MASK) - >> STM32_UCPD_CR_ANASUBMODE_SHIFT; + int anasubmode = + (STM32_UCPD_CR(port) & STM32_UCPD_CR_ANASUBMODE_MASK) >> + STM32_UCPD_CR_ANASUBMODE_SHIFT; /* * Role control register is defined as: @@ -216,9 +571,9 @@ int stm32gx_ucpd_get_role_control(int port) * Rp = (ANASUBMODE - 1) & 0x3 */ cc1 = ucpd_is_cc_pull_active(port, USBPD_CC_PIN_1) ? anamode + 1 : - TYPEC_CC_OPEN; + TYPEC_CC_OPEN; cc2 = ucpd_is_cc_pull_active(port, USBPD_CC_PIN_2) ? anamode + 1 : - TYPEC_CC_OPEN; + TYPEC_CC_OPEN; role_control = cc1 | (cc2 << 2); /* Circular shift anasubmode to convert to Rp range */ role_control |= (UCPD_ANASUB_TO_RP(anasubmode) << 4); @@ -226,6 +581,37 @@ int stm32gx_ucpd_get_role_control(int port) return role_control; } +static uint32_t ucpd_get_cc_enable_mask(int port) +{ + uint32_t mask = STM32_UCPD_CR_CCENABLE_MASK; + + if (ucpd_vconn_enable) { + uint32_t cr = STM32_UCPD_CR(port); + int pol = !!(cr & STM32_UCPD_CR_PHYCCSEL); + + mask &= ~(1 << (STM32_UCPD_CR_CCENABLE_SHIFT + !pol)); + } + + return mask; +} + +int stm32gx_ucpd_vconn_disc_rp(int port, int enable) +{ + int cr; + + /* Update VCONN on/off status. Do this before getting cc enable mask */ + ucpd_vconn_enable = enable; + + cr = STM32_UCPD_CR(port); + cr &= ~STM32_UCPD_CR_CCENABLE_MASK; + cr |= ucpd_get_cc_enable_mask(port); + + /* Apply cc pull resistor change */ + STM32_UCPD_CR(port) = cr; + + return EC_SUCCESS; +} + int stm32gx_ucpd_set_cc(int port, int cc_pull, int rp) { uint32_t cr = STM32_UCPD_CR(port); @@ -238,21 +624,25 @@ int stm32gx_ucpd_set_cc(int port, int cc_pull, int rp) cr &= ~STM32_UCPD_CR_ANASUBMODE_MASK; cr |= STM32_UCPD_CR_ANASUBMODE_VAL(UCPD_RP_TO_ANASUB(rp)); - /* Disconnect both pull from both CC lines by default */ + /* Disconnect both pull from both CC lines for R_open case */ cr &= ~STM32_UCPD_CR_CCENABLE_MASK; /* Set ANAMODE if cc_pull is Rd */ if (cc_pull == TYPEC_CC_RD) { cr |= STM32_UCPD_CR_ANAMODE | STM32_UCPD_CR_CCENABLE_MASK; - /* Clear ANAMODE if cc_pull is Rp */ + /* Clear ANAMODE if cc_pull is Rp */ } else if (cc_pull == TYPEC_CC_RP) { cr &= ~(STM32_UCPD_CR_ANAMODE); - cr |= STM32_UCPD_CR_CCENABLE_MASK; + cr |= ucpd_get_cc_enable_mask(port); } +#ifdef CONFIG_STM32G4_UCPD_DEBUG + if (ucpd_cc_change_log) { + CPRINTS("ucpd: set_cc: pull = %d, rp = %d", cc_pull, rp); + } +#endif /* Update pull values */ STM32_UCPD_CR(port) = cr; - /* TODO(b/): Should this return error if cc_pull == Ra */ return EC_SUCCESS; } @@ -272,6 +662,909 @@ int stm32gx_ucpd_set_polarity(int port, enum tcpc_cc_polarity polarity) else if (polarity == POLARITY_CC2) STM32_UCPD_CR(port) |= STM32_UCPD_CR_PHYCCSEL; +#ifdef CONFIG_STM32G4_UCPD_DEBUG + ucpd_cc_set_save = STM32_UCPD_CR(port); +#endif + + return EC_SUCCESS; +} + +int stm32gx_ucpd_set_rx_enable(int port, int enable) +{ + /* + * USB PD receiver enable is controlled by the bit PHYRXEN in + * UCPD_CR. Enable Rx interrupts when RX PD decoder is active. + */ + if (enable) { + STM32_UCPD_ICR(port) = UCPD_IMR_RX_INT_MASK; + STM32_UCPD_IMR(port) |= UCPD_IMR_RX_INT_MASK; + STM32_UCPD_CR(port) |= STM32_UCPD_CR_PHYRXEN; + } else { + STM32_UCPD_CR(port) &= ~STM32_UCPD_CR_PHYRXEN; + STM32_UCPD_IMR(port) &= ~UCPD_IMR_RX_INT_MASK; + } + return EC_SUCCESS; } +int stm32gx_ucpd_set_msg_header(int port, int power_role, int data_role) +{ + msg_header.pr = power_role; + msg_header.dr = data_role; + + return EC_SUCCESS; +} + +int stm32gx_ucpd_sop_prime_enable(int port, bool enable) +{ + /* Update static varialbe used to filter SOP//SOP'' messages */ + ucpd_rx_sop_prime_enabled = enable; + + return EC_SUCCESS; +} + +int stm32gx_ucpd_get_chip_info(int port, int live, + struct ec_response_pd_chip_info_v1 *chip_info) +{ + chip_info->vendor_id = USB_VID_STM32; + chip_info->product_id = 0; + chip_info->device_id = STM32_DBGMCU_IDCODE & 0xfff; + chip_info->fw_version_number = 0xEC; + + return EC_SUCCESS; +} + +static int stm32gx_ucpd_start_transmit(int port, enum ucpd_tx_msg msg_type) +{ + enum tcpci_msg_type type; + + /* Select the correct tx desciptor */ + ucpd_tx_active_buffer = &ucpd_tx_buffers[msg_type]; + type = ucpd_tx_active_buffer->type; + + if (type == TCPCI_MSG_TX_HARD_RESET) { + /* + * From RM0440 45.4.4: + * In order to facilitate generation of a Hard Reset, a special + * code of TXMODE field is used. No other fields need to be + * written. On writing the correct code, the hardware forces + * Hard Reset Tx under the correct (optimal) timings with + * respect to an on-going Tx message, which (if still in + * progress) is cleanly terminated by truncating the current + * sequence and directly appending an EOP K-code sequence. No + * specific interrupt is generated relating to this truncation + * event. + * + * Because Hard Reset can interrupt ongoing Tx operations, it is + * started differently than all other tx messages. Only need to + * enable hard reset interrupts, and then set a bit in the CR + * register to initiate. + */ + /* Enable interrupt for Hard Reset sent/discarded */ + STM32_UCPD_ICR(port) = STM32_UCPD_ICR_HRSTDISCCF | + STM32_UCPD_ICR_HRSTSENTCF; + STM32_UCPD_IMR(port) |= STM32_UCPD_IMR_HRSTDISCIE | + STM32_UCPD_IMR_HRSTSENTIE; + /* Initiate Hard Reset */ + STM32_UCPD_CR(port) |= STM32_UCPD_CR_TXHRST; + } else if (type != TCPCI_MSG_INVALID) { + int msg_len = 0; + int mode; + + /* + * These types are normal transmission, TXMODE = 0. To transmit + * regular message, control or data, requires the following: + * 1. Set TXMODE: + * Normal -> 0 + * Cable Reset -> 1 + * Bist -> 2 + * 2. Set TX_ORDSETR based on message type + * 3. Set TX_PAYSZR which must account for 2 bytes of header + * 4. Configure DMA (optional if DMA is desired) + * 5. Enable transmit interrupts + * 6. Start TX by setting TXSEND in CR + * + */ + + /* + * Set tx length parameter (in bytes). Note the count field in + * the header is number of 32 bit objects. Also, the length + * field must account for the 2 header bytes. + */ + if (type == TCPCI_MSG_TX_BIST_MODE_2) { + mode = STM32_UCPD_CR_TXMODE_BIST; + } else if (type == TCPCI_MSG_CABLE_RESET) { + mode = STM32_UCPD_CR_TXMODE_CBL_RST; + } else { + mode = STM32_UCPD_CR_TXMODE_DEF; + msg_len = ucpd_tx_active_buffer->msg_len; + } + + STM32_UCPD_TX_PAYSZR(port) = msg_len; + + /* Set tx mode */ + STM32_UCPD_CR(port) &= ~STM32_UCPD_CR_TXMODE_MASK; + STM32_UCPD_CR(port) |= STM32_UCPD_CR_TXMODE_VAL(mode); + + /* Index into ordset enum for start of packet */ + if (type <= TCPCI_MSG_CABLE_RESET) + STM32_UCPD_TX_ORDSETR(port) = ucpd_txorderset[type]; + + /* Reset msg byte index */ + ucpd_tx_active_buffer->msg_index = 0; + + /* Enable interrupts */ + ucpd_tx_interrupts_enable(port, 1); + + /* Trigger ucpd peripheral to start pd message transmit */ + STM32_UCPD_CR(port) |= STM32_UCPD_CR_TXSEND; + +#ifdef CONFIG_STM32G4_UCPD_DEBUG + ucpd_log_add_msg(ucpd_tx_active_buffer->data.header, 0); +#endif + } + + return EC_SUCCESS; +} + +static void ucpd_set_tx_state(enum ucpd_state state) +{ + ucpd_tx_state = state; +} + +#ifdef CONFIG_STM32G4_UCPD_DEBUG +static void ucpd_task_log(int timeout, enum ucpd_state enter, + enum ucpd_state exit, int req, uint32_t evt) +{ + static int same_count = 0; + int idx = ucpd_tx_state_log_idx; + + if (ucpd_tx_state_log_freeze) + return; + + ucpd_tx_statelog[idx].ts = get_time().le.lo; + ucpd_tx_statelog[idx].tx_request = req; + ucpd_tx_statelog[idx].timeout_us = timeout; + ucpd_tx_statelog[idx].enter_state = enter; + ucpd_tx_statelog[idx].exit_state = exit; + ucpd_tx_statelog[idx].evt = evt; + + ucpd_tx_state_log_idx = (idx + 1) & TX_STATE_LOG_MASK; + + if (enter == exit) { + same_count++; + } else { + same_count = 0; + } + + /* + * Should not have same enter/exit states. If this happens, then freeze + * state log to help in debugging. + */ + if (same_count > 5) + ucpd_tx_state_log_freeze = 1; +} + +static void ucpd_task_log_dump(void) +{ + int n; + int idx; + + ucpd_tx_state_log_freeze = 1; + + /* current index will be oldest entry in the log */ + idx = ucpd_tx_state_log_idx; + + ccprintf("\n\t UCDP Task Log\n"); + for (n = 0; n < TX_STATE_LOG_LEN; n++) { + ccprintf("[%d]:\t\%8s\t%8s\t%02x\t%08x\t%09d\t%d\n", n, + ucpd_names[ucpd_tx_statelog[idx].enter_state], + ucpd_names[ucpd_tx_statelog[idx].exit_state], + ucpd_tx_statelog[idx].tx_request, + ucpd_tx_statelog[idx].evt, ucpd_tx_statelog[idx].ts, + ucpd_tx_statelog[idx].timeout_us); + + idx = (idx + 1) & TX_STATE_LOG_MASK; + msleep(5); + } + + ucpd_tx_state_log_freeze = 0; +} +#endif + +static void ucpd_manage_tx(int port, int evt) +{ + enum ucpd_tx_msg msg_src = TX_MSG_NONE; + uint16_t hdr; +#ifdef CONFIG_STM32G4_UCPD_DEBUG + enum ucpd_state enter = ucpd_tx_state; + int req = ucpd_tx_request; +#endif + + if (evt & UCPD_EVT_HR_REQ) { + /* + * Hard reset control messages are treated as a priority. The + * control message will already be set up as it comes from the + * PRL layer like any other PD ctrl/data message. So just need + * to indicate the correct message source and set the state to + * hard reset here. + */ + ucpd_set_tx_state(STATE_HARD_RESET); + msg_src = TX_MSG_TCPM; + ucpd_tx_request &= ~(1 << msg_src); + } + + switch (ucpd_tx_state) { + case STATE_IDLE: + if (ucpd_tx_request & MSG_GOOD_CRC_MASK) { + ucpd_set_tx_state(STATE_ACTIVE_CRC); + msg_src = TX_MSG_GOOD_CRC; + } else if (ucpd_tx_request & MSG_TCPM_MASK) { + if (evt & UCPD_EVT_RX_MSG) { + /* + * USB-PD Specification rev 3.0, section 6.10 + * On receiving a received message, the protocol + * layer shall discard any pending message. + * + * Since the pending message from the PRL has + * not been sent yet, it needs to be discarded + * based on the received message event. + */ + pd_transmit_complete( + port, TCPC_TX_COMPLETE_DISCARDED); + ucpd_tx_request &= ~MSG_TCPM_MASK; + } else if (!ucpd_rx_msg_active) { + ucpd_set_tx_state(STATE_ACTIVE_TCPM); + msg_src = TX_MSG_TCPM; + /* Save msgID required for GoodCRC check */ + hdr = ucpd_tx_buffers[TX_MSG_TCPM].data.header; + msg_id_match = PD_HEADER_ID(hdr); + tx_retry_max = + PD_HEADER_REV(hdr) == PD_REV30 ? + UCPD_N_RETRY_COUNT_REV30 : + UCPD_N_RETRY_COUNT_REV20; + } + } + + /* If state is not idle, then start tx message */ + if (ucpd_tx_state != STATE_IDLE) { + ucpd_tx_request &= ~(1 << msg_src); + tx_retry_count = 0; + } + break; + + case STATE_ACTIVE_TCPM: + /* + * Check if tx msg has finsihed. For TCPM messages + * transmit is not complete until a GoodCRC message + * matching the msgID just sent is received. But, a tx + * message can fail due to collision or underrun, + * etc. If that failure occurs, dont' wait for GoodCrc + * and just go to failure path. + */ + if (evt & UCPD_EVT_TX_MSG_SUCCESS) { + ucpd_set_tx_state(STATE_WAIT_CRC_ACK); + ucpd_timeout_us = UCPD_T_RECEIVE_US; + } else if (evt & UCPD_EVT_TX_MSG_DISC || + evt & UCPD_EVT_TX_MSG_FAIL) { + if (tx_retry_count < tx_retry_max) { + if (evt & UCPD_EVT_RX_MSG) { + /* + * A message was received so there is no + * need to retry this tx message which + * had failed to send previously. + * Likely, due to the wire + * being active from the message that + * was just received. + */ + ucpd_set_tx_state(STATE_IDLE); + pd_transmit_complete( + port, + TCPC_TX_COMPLETE_DISCARDED); + ucpd_set_tx_state(STATE_IDLE); + } else { + /* + * Tx attempt failed. Remain in this + * state, but trigger new tx attempt. + */ + msg_src = TX_MSG_TCPM; + tx_retry_count++; + } + } else { + enum tcpc_transmit_complete status; + + status = (evt & UCPD_EVT_TX_MSG_FAIL) ? + TCPC_TX_COMPLETE_FAILED : + TCPC_TX_COMPLETE_DISCARDED; + ucpd_set_tx_state(STATE_IDLE); + pd_transmit_complete(port, status); + } + } + break; + + case STATE_ACTIVE_CRC: + if (evt & (UCPD_EVT_TX_MSG_SUCCESS | UCPD_EVT_TX_MSG_FAIL | + UCPD_EVT_TX_MSG_DISC)) { + ucpd_set_tx_state(STATE_IDLE); + if (evt & UCPD_EVT_TX_MSG_FAIL) + CPRINTS("ucpd: Failed to send GoodCRC!"); + else if (evt & UCPD_EVT_TX_MSG_DISC) + CPRINTS("ucpd: GoodCRC message discarded!"); + } + break; + + case STATE_WAIT_CRC_ACK: + if (evt & UCPD_EVT_RX_GOOD_CRC && ucpd_crc_id == msg_id_match) { + /* GoodCRC with matching ID was received */ + pd_transmit_complete(port, TCPC_TX_COMPLETE_SUCCESS); + ucpd_set_tx_state(STATE_IDLE); +#ifdef CONFIG_STM32G4_UCPD_DEBUG + ucpd_log_mark_crc(); +#endif + } else if ((evt & UCPD_EVT_RX_GOOD_CRC) || + (evt & TASK_EVENT_TIMER)) { + /* GoodCRC w/out match or timeout waiting */ + if (tx_retry_count < tx_retry_max) { + ucpd_set_tx_state(STATE_ACTIVE_TCPM); + msg_src = TX_MSG_TCPM; + tx_retry_count++; + } else { + ucpd_set_tx_state(STATE_IDLE); + pd_transmit_complete(port, + TCPC_TX_COMPLETE_FAILED); + } + } else if (evt & UCPD_EVT_RX_MSG) { + /* + * In the case of a collsion, it's possible the port + * partner may not send a GoodCRC and instead send the + * message that was colliding. If a message is received + * in this state, then treat it as a discard from an + * incoming message. + */ + pd_transmit_complete(port, TCPC_TX_COMPLETE_DISCARDED); + ucpd_set_tx_state(STATE_IDLE); + } + break; + + case STATE_HARD_RESET: + if (evt & UCPD_EVT_HR_DONE) { + /* HR complete, reset tx state values */ + ucpd_set_tx_state(STATE_IDLE); + ucpd_tx_request = 0; + tx_retry_count = 0; + } else if (evt & UCPD_EVT_HR_FAIL) { + ucpd_set_tx_state(STATE_IDLE); + ucpd_tx_request = 0; + tx_retry_count = 0; + } + break; + } + + /* If msg_src is valid, then start transmit */ + if (msg_src > TX_MSG_NONE) { + stm32gx_ucpd_start_transmit(port, msg_src); + } + +#ifdef CONFIG_STM32G4_UCPD_DEBUG + ucpd_task_log(ucpd_timeout_us, enter, ucpd_tx_state, req, evt); +#endif +} + +/* + * Main task entry point for UCPD task + * + * @param p The PD port number for which to handle interrupts (pointer is + * reinterpreted as an integer directly). + */ +void ucpd_task(void *p) +{ + const int port = (int)((intptr_t)p); + + /* Init variables used to manage tx process */ + stm32gx_ucpd_state_init(port); + + while (1) { + /* + * Note that ucpd_timeout_us is file scope and may be modified + * in the tx state machine when entering the STATE_WAIT_CRC_ACK + * state. Otherwise, the expectation is that the task is woken + * only upon non-timer events. + */ + int evt = task_wait_event(ucpd_timeout_us); + + /* + * USB-PD messages are intiated in TCPM stack (PRL + * layer). However, GoodCRC messages are initiated within the + * UCPD driver based on USB-PD rx messages. These 2 types of + * transmit paths are managed via task events. + * + * UCPD generated GoodCRC messages, are the priority path as + * they must be sent immediately following a successful USB-PD + * rx message. As long as a transmit operation is not underway, + * then a transmit message will be started upon request. The ISR + * routine sets the event to indicate that the transmit + * operation is complete. + * + * Hard reset requests are sent as a TCPM message, but in terms + * of the ucpd transmitter, they are treated as a 3rd tx msg + * source since they can interrupt an ongoing tx msg, and there + * is no requirement to wait for a GoodCRC reply message. + */ + + /* Assume there is no timer for next task wake */ + ucpd_timeout_us = -1; + + if (evt & UCPD_EVT_GOOD_CRC_REQ) + ucpd_tx_request |= MSG_GOOD_CRC_MASK; + + if (evt & UCPD_EVT_TCPM_MSG_REQ) + ucpd_tx_request |= MSG_TCPM_MASK; + + /* + * Manage PD tx messages. The state machine may need to be + * called more than once when the task wakes. For instance, if + * the task is woken at the completion of sending a GoodCRC, + * there may be a TCPM message request pending and just changing + * the state back to idle would not trigger start of transmit. + */ + do { + ucpd_manage_tx(port, evt); + /* Look at task events only once. */ + evt = 0; + } while (ucpd_tx_request && ucpd_tx_state == STATE_IDLE && + !ucpd_rx_msg_active); + } +} + +static void ucpd_send_good_crc(int port, uint16_t rx_header) +{ + int msg_id; + int rev_id; + uint16_t tx_header; + enum tcpci_msg_type tx_type; + enum pd_power_role pr = 0; + enum pd_data_role dr = 0; + + /* + * A GoodCRC message shall be sent by receiver to ack that the previous + * message was correctly received. The GoodCRC message shall return the + * rx message's msg_id field. The one exception is for GoodCRC messages, + * which do not generate a GoodCRC response + */ + if (ucpd_msg_is_good_crc(rx_header)) { + return; + } + + /* + * Get the rx ordered set code just detected. SOP -> SOP''_Debug are in + * the same order as enum tcpci_msg_type and so can be used + * directly. + */ + tx_type = STM32_UCPD_RX_ORDSETR(port) & STM32_UCPD_RXORDSETR_MASK; + + /* + * PD Header(SOP): + * Extended b15 -> set to 0 for control messages + * Count b14:12 -> number of 32 bit data objects = 0 for ctrl msg + * MsgID b11:9 -> running byte counter (extracted from rx msg) + * Power Role b8 -> stored in static, from set_msg_header() + * Spec Rev b7:b6 -> PD spec revision (extracted from rx msg) + * Data Role b5 -> stored in static, from set_msg_header + * Msg Type b4:b0 -> data or ctrl type = PD_CTRL_GOOD_CRC + */ + /* construct header message */ + msg_id = PD_HEADER_ID(rx_header); + rev_id = PD_HEADER_REV(rx_header); + if (tx_type == TCPCI_MSG_SOP) { + pr = msg_header.pr; + dr = msg_header.dr; + } + tx_header = PD_HEADER(PD_CTRL_GOOD_CRC, pr, dr, msg_id, 0, rev_id, 0); + + /* Good CRC is header with no other objects */ + ucpd_tx_buffers[TX_MSG_GOOD_CRC].msg_len = 2; + ucpd_tx_buffers[TX_MSG_GOOD_CRC].data.header = tx_header; + ucpd_tx_buffers[TX_MSG_GOOD_CRC].type = tx_type; + + /* Notify ucpd task that a GoodCRC message tx request is pending */ + task_set_event(TASK_ID_UCPD, UCPD_EVT_GOOD_CRC_REQ); +} + +int stm32gx_ucpd_transmit(int port, enum tcpci_msg_type type, uint16_t header, + const uint32_t *data) +{ + /* Length in bytes = (4 * object len) + 2 header byes */ + int len = (PD_HEADER_CNT(header) << 2) + 2; + + if (len > UCPD_BUF_LEN) + return EC_ERROR_OVERFLOW; + + /* Store tx msg info in TCPM msg descriptor */ + ucpd_tx_buffers[TX_MSG_TCPM].msg_len = len; + ucpd_tx_buffers[TX_MSG_TCPM].type = type; + ucpd_tx_buffers[TX_MSG_TCPM].data.header = header; + /* Copy msg objects to ucpd data buffer, after 2 header bytes */ + memcpy(ucpd_tx_buffers[TX_MSG_TCPM].data.msg + 2, (uint8_t *)data, + len - 2); + + /* + * Check for hard reset message here. A different event is used for hard + * resets as they are able to interrupt ongoing transmit, and should + * have priority over any pending message. + */ + if (type == TCPCI_MSG_TX_HARD_RESET) + task_set_event(TASK_ID_UCPD, UCPD_EVT_HR_REQ); + else + task_set_event(TASK_ID_UCPD, UCPD_EVT_TCPM_MSG_REQ); + + return EC_SUCCESS; +} + +int stm32gx_ucpd_get_message_raw(int port, uint32_t *payload, int *head) +{ + uint16_t *rx_header = (uint16_t *)ucpd_rx_buffer; + int rxpaysz; +#ifdef CONFIG_USB_PD_DECODE_SOP + int sop; +#endif + + /* First 2 bytes of data buffer are the header */ + *head = *rx_header; + +#ifdef CONFIG_USB_PD_DECODE_SOP + /* + * The message header is a 16-bit value that's stored in a 32-bit data + * type. SOP* is encoded in bits 31 to 28 of the 32-bit data type. NOTE: + * The 4 byte header is not part of the PD spec. + */ + /* Get SOP value */ + sop = STM32_UCPD_RX_ORDSETR(port) & STM32_UCPD_RXORDSETR_MASK; + /* Put SOP in bits 31:28 of 32 bit header */ + *head |= PD_HEADER_SOP(sop); +#endif + rxpaysz = STM32_UCPD_RX_PAYSZR(port) & STM32_UCPD_RX_PAYSZR_MASK; + /* This size includes 2 bytes for message header */ + rxpaysz -= 2; + /* Copy payload (src/dst are both 32 bit aligned) */ + memcpy(payload, ucpd_rx_buffer + 2, rxpaysz); + + return EC_SUCCESS; +} + +enum ec_error_list stm32gx_ucpd_set_bist_test_mode(const int port, + const bool enable) +{ + ucpd_rx_bist_mode = enable; + CPRINTS("ucpd: Bist test mode = %d", enable); + + return EC_SUCCESS; +} + +static void stm32gx_ucpd1_irq(void) +{ + /* STM32_IRQ_UCPD indicates this is from UCPD1, so port = 0 */ + int port = 0; + uint32_t sr = STM32_UCPD_SR(port); + uint32_t tx_done_mask = STM32_UCPD_SR_TXMSGSENT | + STM32_UCPD_SR_TXMSGABT | + STM32_UCPD_SR_TXMSGDISC | + STM32_UCPD_SR_HRSTSENT | STM32_UCPD_SR_HRSTDISC; + + /* Check for CC events, set event to wake PD task */ + if (sr & (STM32_UCPD_SR_TYPECEVT1 | STM32_UCPD_SR_TYPECEVT2)) { + task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC); +#ifdef CONFIG_STM32G4_UCPD_DEBUG + ucpd_sr_cc_event = sr; + hook_call_deferred(&ucpd_cc_change_notify_data, 0); +#endif + } + + /* + * Check for Tx events. tx_mask includes all status bits related to the + * end of a USB-PD tx message. If any of these bits are set, the + * transmit attempt is completed. Set an event to notify ucpd tx state + * machine that transmit operation is complete. + */ + if (sr & tx_done_mask) { + /* Check for tx message complete */ + if (sr & STM32_UCPD_SR_TXMSGSENT) { + task_set_event(TASK_ID_UCPD, UCPD_EVT_TX_MSG_SUCCESS); +#ifdef CONFIG_STM32G4_UCPD_DEBUG + ucpd_log_mark_tx_comp(); +#endif + } else if (sr & + (STM32_UCPD_SR_TXMSGABT | STM32_UCPD_SR_TXUND)) { + task_set_event(TASK_ID_UCPD, UCPD_EVT_TX_MSG_FAIL); + } else if (sr & STM32_UCPD_SR_TXMSGDISC) { + task_set_event(TASK_ID_UCPD, UCPD_EVT_TX_MSG_DISC); +#ifdef CONFIG_STM32G4_UCPD_DEBUG + ucpd_log_mark_tx_comp(); +#endif + } else if (sr & STM32_UCPD_SR_HRSTSENT) { + task_set_event(TASK_ID_UCPD, UCPD_EVT_HR_DONE); + } else if (sr & STM32_UCPD_SR_HRSTDISC) { + task_set_event(TASK_ID_UCPD, UCPD_EVT_HR_FAIL); + } + /* Disable Tx interrupts */ + ucpd_tx_interrupts_enable(port, 0); + } + + /* Check for data register empty */ + if (sr & STM32_UCPD_SR_TXIS) + ucpd_tx_data_byte(port); + + /* Check for Rx Events */ + /* Check first for start of new message */ + if (sr & STM32_UCPD_SR_RXORDDET) { + ucpd_rx_byte_count = 0; + ucpd_rx_msg_active = 1; + } + /* Check for byte received */ + if (sr & STM32_UCPD_SR_RXNE) + ucpd_rx_data_byte(port); + + /* Check for end of message */ + if (sr & STM32_UCPD_SR_RXMSGEND) { + ucpd_rx_msg_active = 0; + /* Check for errors */ + if (!(sr & STM32_UCPD_SR_RXERR)) { + uint16_t *rx_header = (uint16_t *)ucpd_rx_buffer; + enum tcpci_msg_type type; + int good_crc = 0; + + type = STM32_UCPD_RX_ORDSETR(port) & + STM32_UCPD_RXORDSETR_MASK; + + good_crc = ucpd_msg_is_good_crc(*rx_header); + +#ifdef CONFIG_STM32G4_UCPD_DEBUG + ucpd_log_add_msg(*rx_header, 1); +#endif + /* + * Don't pass GoodCRC control messages to the TCPM + * layer. In addition, need to filter for SOP'/SOP'' + * packets if those are not enabled. SOP'/SOP'' + * reception is controlled by a static variable. The + * hardware orderset detection pattern can't be changed + * without disabling the ucpd peripheral. + */ + if (!good_crc && (ucpd_rx_sop_prime_enabled || + type == TCPCI_MSG_SOP)) { + /* + * If BIST test mode is active, then still need + * to send GoodCRC reply, but there is no need + * to send the message up to the tcpm layer. + */ + if (!ucpd_rx_bist_mode) { + if (tcpm_enqueue_message(port)) + hook_call_deferred( + &ucpd_rx_enque_error_data, + 0); + } + + task_set_event(TASK_ID_UCPD, UCPD_EVT_RX_MSG); + + /* Send GoodCRC message (if required) */ + ucpd_send_good_crc(port, *rx_header); + } else if (good_crc) { + task_set_event(TASK_ID_UCPD, + UCPD_EVT_RX_GOOD_CRC); + ucpd_crc_id = PD_HEADER_ID(*rx_header); + } + } else { + /* Rx message is complete, but there were bit errors */ + CPRINTS("ucpd: rx message error"); + } + } + /* Check for fault conditions */ + if (sr & STM32_UCPD_SR_RXHRSTDET) { + /* hard reset received */ + pd_execute_hard_reset(port); + task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE); + hook_call_deferred(&ucpd_hard_reset_rx_log_data, 0); + } + + /* Clear interrupts now that PD events have been set */ + STM32_UCPD_ICR(port) = sr; +} +DECLARE_IRQ(STM32_IRQ_UCPD1, stm32gx_ucpd1_irq, 1); + +#ifdef CONFIG_STM32G4_UCPD_DEBUG +static char ctrl_names[][12] = { + "rsvd", "GoodCRC", "Goto Min", "Accept", "Reject", + "Ping", "PS_Rdy", "Get_SRC", "Get_SNK", "DR_Swap", + "PR_Swap", "VCONN_Swp", "Wait", "Soft_Rst", "RSVD", + "RSVD", "Not_Sup", "Get_SRC_Ext", "Get_Status", +}; + +static char data_names[][10] = { + "RSVD", "SRC_CAP", "REQUEST", "BIST", "SINK_CAP", "BATTERY", + "ALERT", "GET_INFO", "ENTER_USB", "RSVD", "RSVD", "RSVD", + "RSVD", "RSVD", "RSVD", "VDM", +}; + +static void ucpd_dump_msg_log(void) +{ + int i; + int type; + int len; + int dir; + uint16_t header; + char *name; + + ccprintf("ucpd: msg_total = %d\n", msg_log_cnt); + ccprintf("Idx\t Delta(us)\tDir\t Type\t\tLen\t s1 s2 PR\t DR\n"); + ccprintf("-----------------------------------------------------------" + "-----------------\n"); + + for (i = 0; i < msg_log_idx; i++) { + uint32_t delta_ts = 0; + int j; + + header = msg_log[i].header; + + if (header != 0xabcd) { + type = PD_HEADER_TYPE(header); + len = PD_HEADER_CNT(header); + name = len ? data_names[type] : ctrl_names[type]; + dir = msg_log[i].dir; + if (i) { + delta_ts = msg_log[i].ts - msg_log[i - 1].ts; + } + + ccprintf("msg[%02d]: %08d\t %s\t %8s\t %02d\t %d %d\t" + "%s\t %s", + i, delta_ts, dir ? "Rx" : "Tx", name, len, + msg_log[i].comp, msg_log[i].crc, + PD_HEADER_PROLE(header) ? "SRC" : "SNK", + PD_HEADER_DROLE(header) ? "DFP" : "UFP"); + len = MIN((len * 4) + 2, MSG_BUF_LEN); + for (j = 0; j < len; j++) + ccprintf(" %02x", msg_log[i].buf[j]); + } else { + if (i) { + delta_ts = msg_log[i].ts - msg_log[i - 1].ts; + } + ccprintf("msg[%02d]: %08d\t CC Voltage Change!", i, + delta_ts); + } + ccprintf("\n"); + msleep(5); + } +} + +static void stm32gx_ucpd_set_cc_debug(int port, int cc_mask, int pull, int rp) +{ + int cc_enable; + uint32_t cr = STM32_UCPD_CR(port); + + /* + * Only update ANASUBMODE if specified pull type is Rp. + */ + if (pull == TYPEC_CC_RP) { + cr &= ~STM32_UCPD_CR_ANASUBMODE_MASK; + cr |= STM32_UCPD_CR_ANASUBMODE_VAL(UCPD_RP_TO_ANASUB(rp)); + } + + /* + * Can't independently set pull value for CC1 from CC2. But, can + * independently connect or disconnect pull for CC1 and CC2. Enable here + * the CC lines specified by cc_mask. If desired pull is TYPEC_CC_OPEN, + * then the CC lines specified in cc_mask will be disabled. + */ + /* Get existing cc enable value */ + cc_enable = (cr & STM32_UCPD_CR_CCENABLE_MASK) >> + STM32_UCPD_CR_CCENABLE_SHIFT; + /* Apply cc_mask (enable CC line specified) */ + cc_enable |= cc_mask; + + /* Set ANAMODE if cc_pull is Rd */ + if (pull == TYPEC_CC_RD) + cr |= STM32_UCPD_CR_ANAMODE; + /* Clear ANAMODE if cc_pull is Rp */ + else if (pull == TYPEC_CC_RP) + cr &= ~(STM32_UCPD_CR_ANAMODE); + else if (pull == TYPEC_CC_OPEN) + cc_enable &= ~cc_mask; + + /* The value for this field needs to be OR'd in */ + cr &= ~STM32_UCPD_CR_CCENABLE_MASK; + cr |= STM32_UCPD_CR_CCENABLE_VAL(cc_enable); + /* Update pull values */ + STM32_UCPD_CR(port) = cr; + /* Display updated settings */ + ucpd_cc_status(port); +} + +void ucpd_info(int port) +{ + ucpd_cc_status(port); + ccprintf("\trx_en\t = %d\n\tpol\t = %d\n", + !!(STM32_UCPD_CR(port) & STM32_UCPD_CR_PHYRXEN), + !!(STM32_UCPD_CR(port) & STM32_UCPD_CR_PHYCCSEL)); + + /* Dump ucpd task state info */ + ccprintf("ucpd: tx_state = %s, tx_req = %02x, timeout_us = %d\n", + ucpd_names[ucpd_tx_state], ucpd_tx_request, ucpd_timeout_us); + + ucpd_task_log_dump(); +} + +static int command_ucpd(int argc, const char **argv) +{ + uint32_t tx_data = 0; + char *e; + int val; + int port = 0; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[1], "rst")) { + /* Force reset of ucpd peripheral */ + stm32gx_ucpd_init(port); + pd_execute_hard_reset(port); + task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE); + } else if (!strcasecmp(argv[1], "info")) { + ucpd_info(port); + } else if (!strcasecmp(argv[1], "bist")) { + /* Need to initiate via DPM to have a timer */ + /* TODO(b/182861002): uncomment when Gingerbread has + * full PD support landed. + * pd_dpm_request(port, DPM_REQUEST_BIST_TX); + */ + } else if (!strcasecmp(argv[1], "hard")) { + stm32gx_ucpd_transmit(port, TCPCI_MSG_TX_HARD_RESET, 0, + &tx_data); + } else if (!strcasecmp(argv[1], "pol")) { + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + val = strtoi(argv[2], &e, 10); + if (val > 1) + val = 0; + stm32gx_ucpd_set_polarity(port, val); + stm32gx_ucpd_set_rx_enable(port, 1); + ccprintf("ucpd: set pol = %d, PHYRXEN = 1\n", val); + } else if (!strcasecmp(argv[1], "cc")) { + int cc_mask; + int pull; + int rp = 0; /* needs to be initialized */ + + if (argc < 3) { + ucpd_cc_status(port); + return EC_SUCCESS; + } + cc_mask = strtoi(argv[2], &e, 10); + if (cc_mask < 1 || cc_mask > 3) + return EC_ERROR_PARAM2; + /* cc_mask has determines which cc setting to apply */ + if (!strcasecmp(argv[3], "rd")) { + pull = TYPEC_CC_RD; + } else if (!strcasecmp(argv[3], "rp")) { + pull = TYPEC_CC_RP; + rp = strtoi(argv[4], &e, 10); + if (rp < 0 || rp > 2) + return EC_ERROR_PARAM4; + } else if (!strcasecmp(argv[3], "open")) { + pull = TYPEC_CC_OPEN; + } else { + return EC_ERROR_PARAM3; + } + stm32gx_ucpd_set_cc_debug(port, cc_mask, pull, rp); + + } else if (!strcasecmp(argv[1], "log")) { + if (argc < 3) { + ucpd_dump_msg_log(); + } else if (!strcasecmp(argv[2], "clr")) { + msg_log_cnt = 0; + msg_log_idx = 0; + } + } else { + return EC_ERROR_PARAM1; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(ucpd, command_ucpd, + "[rst|info|bist|hard|pol <0|1>|cc xx |log", + "ucpd peripheral debug and control options"); +#endif diff --git a/chip/stm32/ucpd-stm32gx.h b/chip/stm32/ucpd-stm32gx.h index f0a73cb29e..d41503f9ef 100644 --- a/chip/stm32/ucpd-stm32gx.h +++ b/chip/stm32/ucpd-stm32gx.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,6 +9,34 @@ #include "usb_pd_tcpm.h" +/* + * UCPD is fed directly from HSI which is @ 16MHz. The ucpd_clk goes to + * a prescaler who's output feeds the 'half-bit' divider which is used + * to generate clock for delay counters and BMC Rx/Tx blocks. The rx is + * designed to work in freq ranges of 6 <--> 18 MHz, however recommended + * range is 9 <--> 18 MHz. + * + * ------- @ 16 MHz --------- @ ~600 kHz ------------- + * HSI ---->| /psc |-------->| /hbit |--------------->| trans_cnt | + * ------- --------- | ------------- + * | ------------- + * |---------->| ifrgap_cnt| + * ------------- + * Requirements: + * 1. hbit_clk ~= 600 kHz: 16 MHz / 600 kHz = 26.67 + * 2. tTransitionWindow - 12 to 20 uSec + * 3. tInterframGap - uSec + * + * hbit_clk = HSI_clk / 27 = 592.6 kHz = 1.687 uSec period + * tTransitionWindow = 1.687 uS * 8 = 13.5 uS + * tInterFrameGap = 1.687 uS * 17 = 28.68 uS + */ + +#define UCPD_PSC_DIV 1 +#define UCPD_HBIT_DIV 27 +#define UCPD_TRANSWIN_CNT 8 +#define UCPD_IFRGAP_CNT 17 + /* * K-codes and ordered set defines. These codes and sets are used to encode * which type of USB-PD message is being sent. This information can be found in @@ -18,40 +46,35 @@ #define UCPD_SYNC1 0x18u #define UCPD_SYNC2 0x11u #define UCPD_SYNC3 0x06u -#define UCPD_RST1 0x07u -#define UCPD_RST2 0x19u -#define UCPD_EOP 0x0Du +#define UCPD_RST1 0x07u +#define UCPD_RST2 0x19u +#define UCPD_EOP 0x0Du +/* This order of this enum matches tcpm_sop_type */ enum ucpd_tx_ordset { - TX_ORDERSET_SOP = (UCPD_SYNC1 | - (UCPD_SYNC1<<5u) | - (UCPD_SYNC1<<10u) | - (UCPD_SYNC2<<15u)), - TX_ORDERSET_SOP1 = (UCPD_SYNC1 | - (UCPD_SYNC1<<5u) | - (UCPD_SYNC3<<10u) | - (UCPD_SYNC3<<15u)), - TX_ORDERSET_SOP2 = (UCPD_SYNC1 | - (UCPD_SYNC3<<5u) | - (UCPD_SYNC1<<10u) | - (UCPD_SYNC3<<15u)), - TX_ORDERSET_HARD_RESET = (UCPD_RST1 | - (UCPD_RST1<<5u) | - (UCPD_RST1<<10u) | - (UCPD_RST2<<15u)), - TX_ORDERSET_CABLE_RESET = - (UCPD_RST1 | - (UCPD_SYNC1<<5u) | - (UCPD_RST1<<10u) | - (UCPD_SYNC3<<15u)), - TX_ORDERSET_SOP1_DEBUG = (UCPD_SYNC1 | - (UCPD_RST2<<5u) | - (UCPD_RST2<<10u) | - (UCPD_SYNC3<<15u)), - TX_ORDERSET_SOP2_DEBUG = (UCPD_SYNC1 | - (UCPD_RST2<<5u) | - (UCPD_SYNC3<<10u) | - (UCPD_SYNC2<<15u)), + TX_ORDERSET_SOP = (UCPD_SYNC1 | (UCPD_SYNC1 << 5u) | + (UCPD_SYNC1 << 10u) | (UCPD_SYNC2 << 15u)), + + TX_ORDERSET_SOP_PRIME = (UCPD_SYNC1 | (UCPD_SYNC1 << 5u) | + (UCPD_SYNC3 << 10u) | (UCPD_SYNC3 << 15u)), + + TX_ORDERSET_SOP_PRIME_PRIME = + (UCPD_SYNC1 | (UCPD_SYNC3 << 5u) | (UCPD_SYNC1 << 10u) | + (UCPD_SYNC3 << 15u)), + + TX_ORDERSET_SOP_PRIME_DEBUG = + (UCPD_SYNC1 | (UCPD_RST2 << 5u) | (UCPD_RST2 << 10u) | + (UCPD_SYNC3 << 15u)), + + TX_ORDERSET_SOP_PRIME_PRIME_DEBUG = + (UCPD_SYNC1 | (UCPD_RST2 << 5u) | (UCPD_SYNC3 << 10u) | + (UCPD_SYNC2 << 15u)), + + TX_ORDERSET_HARD_RESET = (UCPD_RST1 | (UCPD_RST1 << 5u) | + (UCPD_RST1 << 10u) | (UCPD_RST2 << 15u)), + + TX_ORDERSET_CABLE_RESET = (UCPD_RST1 | (UCPD_SYNC1 << 5u) | + (UCPD_RST1 << 10u) | (UCPD_SYNC3 << 15u)), }; /** @@ -108,4 +131,86 @@ int stm32gx_ucpd_set_cc(int usbc_port, int cc_pull, int rp); */ int stm32gx_ucpd_set_polarity(int usbc_port, enum tcpc_cc_polarity polarity); +/** + * STM32Gx UCPD implementation of tcpci .set_rx_enable method + * + * @param usbc_port -> USB-C Port number + * @param enable -> on/off for USB-PD messages + * @return EC_SUCCESS + */ +int stm32gx_ucpd_set_rx_enable(int port, int enable); + +/** + * STM32Gx UCPD implementation of tcpci .set_msg_header method + * + * @param usbc_port -> USB-C Port number + * @param power_role -> port's current power role + * @param data_role -> port's current data role + * @return EC_SUCCESS + */ +int stm32gx_ucpd_set_msg_header(int port, int power_role, int data_role); + +/** + * STM32Gx UCPD implementation of tcpci .transmit method + * + * @param usbc_port -> USB-C Port number + * @param type -> SOP/SOP'/SOP'' etc + * @param header -> usb pd message header + * @param *data -> pointer to message contents + * @return EC_SUCCESS + */ +int stm32gx_ucpd_transmit(int port, enum tcpci_msg_type type, uint16_t header, + const uint32_t *data); + +/** + * STM32Gx UCPD implementation of tcpci .get_message_raw method + * + * @param usbc_port -> USB-C Port number + * @param *payload -> pointer to where message should be written + * @param *head -> pointer to message header + * @return EC_SUCCESS + */ +int stm32gx_ucpd_get_message_raw(int port, uint32_t *payload, int *head); + +/** + * STM32Gx method to remove Rp when VCONN is being supplied + * + * @param usbc_port -> USB-C Port number + * @param enable -> connect/disc Rp + * @return EC_SUCCESS + */ +int stm32gx_ucpd_vconn_disc_rp(int port, int enable); + +/** + * STM32Gx UCPD implementation of tcpci .sop_prime_enable method + * + * @param usbc_port -> USB-C Port number + * @param enable -> control of SOP'/SOP'' messages + * @return EC_SUCCESS + */ +int stm32gx_ucpd_sop_prime_enable(int port, bool enable); + +int stm32gx_ucpd_get_chip_info(int port, int live, + struct ec_response_pd_chip_info_v1 *chip_info); + +/** + * This function is used to enable/disable a ucpd debug feature that is used to + * mark the ucpd message log when there is a usbc detach event. + * + * @param enable -> on/off control for debug feature + */ +void ucpd_cc_detect_notify_enable(int enable); + +/** + * This function is used to enable/disable rx bist test mode in the ucpd + * driver. This mode is controlled at the PE layer. When this mode is enabled, + * the ucpd receiver will not pass BIST data messages to the protocol layer and + * only send GoodCRC replies. + * + * @param usbc_port -> USB-C Port number + * @param enable -> on/off control for rx bist mode + */ +enum ec_error_list stm32gx_ucpd_set_bist_test_mode(const int port, + const bool enable); + #endif /* __CROS_EC_UCPD_STM32GX_H */ diff --git a/chip/stm32/usart-stm32f0.c b/chip/stm32/usart-stm32f0.c index 908542146f..debb062473 100644 --- a/chip/stm32/usart-stm32f0.c +++ b/chip/stm32/usart-stm32f0.c @@ -1,15 +1,14 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "usart-stm32f0.h" - #include "clock.h" #include "common.h" #include "compile_time_macros.h" #include "hooks.h" #include "registers.h" #include "task.h" +#include "usart-stm32f0.h" #include "util.h" /* @@ -23,7 +22,7 @@ static struct usart_config const *configs[STM32_USARTS_MAX]; struct usart_configs usart_get_configs(void) { - return (struct usart_configs) {configs, ARRAY_SIZE(configs)}; + return (struct usart_configs){ configs, ARRAY_SIZE(configs) }; } static void usart_variant_enable(struct usart_config const *config) @@ -54,8 +53,7 @@ static void usart_variant_disable(struct usart_config const *config) * Only disable the shared interrupt for USART3/4 if both USARTs are * now disabled. */ - if ((index == 0) || - (index == 1) || + if ((index == 0) || (index == 1) || (index == 2 && configs[3] == NULL) || (index == 3 && configs[2] == NULL)) task_disable_irq(config->hw->irq); @@ -64,25 +62,32 @@ static void usart_variant_disable(struct usart_config const *config) } static struct usart_hw_ops const usart_variant_hw_ops = { - .enable = usart_variant_enable, + .enable = usart_variant_enable, .disable = usart_variant_disable, }; static void freq_change(void) { - size_t i; + size_t i; for (i = 0; i < ARRAY_SIZE(configs); ++i) if (configs[i]) usart_set_baud_f0_l(configs[i], configs[i]->baud, - clock_get_freq()); + clock_get_freq()); } DECLARE_HOOK(HOOK_FREQ_CHANGE, freq_change, HOOK_PRIO_DEFAULT); void usart_clear_tc(struct usart_config const *config) { - STM32_USART_ICR(config->hw->base) |= STM32_USART_ICR_TCCF; + /* + * ST reference code does blind write to this register, as is usual + * with the "write 1 to clear" convention, despite the datasheet + * listing the bits as "keep at reset value", (which we assume is due + * to copying from the description of reserved bits in read/write + * registers.) + */ + STM32_USART_ICR(config->hw->base) = STM32_USART_ICR_TCCF; } /* @@ -91,15 +96,15 @@ void usart_clear_tc(struct usart_config const *config) */ #if defined(CONFIG_STREAM_USART1) struct usart_hw_config const usart1_hw = { - .index = 0, - .base = STM32_USART1_BASE, - .irq = STM32_IRQ_USART1, + .index = 0, + .base = STM32_USART1_BASE, + .irq = STM32_IRQ_USART1, .clock_register = &STM32_RCC_APB2ENR, - .clock_enable = STM32_RCC_PB2_USART1, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB2_USART1, + .ops = &usart_variant_hw_ops, }; -void usart1_interrupt(void) +static void usart1_interrupt(void) { usart_interrupt(configs[0]); } @@ -109,15 +114,15 @@ DECLARE_IRQ(STM32_IRQ_USART1, usart1_interrupt, 2); #if defined(CONFIG_STREAM_USART2) struct usart_hw_config const usart2_hw = { - .index = 1, - .base = STM32_USART2_BASE, - .irq = STM32_IRQ_USART2, + .index = 1, + .base = STM32_USART2_BASE, + .irq = STM32_IRQ_USART2, .clock_register = &STM32_RCC_APB1ENR, - .clock_enable = STM32_RCC_PB1_USART2, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB1_USART2, + .ops = &usart_variant_hw_ops, }; -void usart2_interrupt(void) +static void usart2_interrupt(void) { usart_interrupt(configs[1]); } @@ -127,28 +132,28 @@ DECLARE_IRQ(STM32_IRQ_USART2, usart2_interrupt, 2); #if defined(CONFIG_STREAM_USART3) struct usart_hw_config const usart3_hw = { - .index = 2, - .base = STM32_USART3_BASE, - .irq = STM32_IRQ_USART3_4, + .index = 2, + .base = STM32_USART3_BASE, + .irq = STM32_IRQ_USART3_4, .clock_register = &STM32_RCC_APB1ENR, - .clock_enable = STM32_RCC_PB1_USART3, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB1_USART3, + .ops = &usart_variant_hw_ops, }; #endif #if defined(CONFIG_STREAM_USART4) struct usart_hw_config const usart4_hw = { - .index = 3, - .base = STM32_USART4_BASE, - .irq = STM32_IRQ_USART3_4, + .index = 3, + .base = STM32_USART4_BASE, + .irq = STM32_IRQ_USART3_4, .clock_register = &STM32_RCC_APB1ENR, - .clock_enable = STM32_RCC_PB1_USART4, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB1_USART4, + .ops = &usart_variant_hw_ops, }; #endif #if defined(CONFIG_STREAM_USART3) || defined(CONFIG_STREAM_USART4) -void usart3_4_interrupt(void) +static void usart3_4_interrupt(void) { /* * This interrupt handler could be called with one of these configs diff --git a/chip/stm32/usart-stm32f0.h b/chip/stm32/usart-stm32f0.h index 1b7eee95a7..72c88fba9c 100644 --- a/chip/stm32/usart-stm32f0.h +++ b/chip/stm32/usart-stm32f0.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/stm32/usart-stm32f3.c b/chip/stm32/usart-stm32f3.c index 42a0cf310e..b46ac2ed8f 100644 --- a/chip/stm32/usart-stm32f3.c +++ b/chip/stm32/usart-stm32f3.c @@ -1,14 +1,13 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "usart-stm32f3.h" - #include "common.h" #include "compile_time_macros.h" #include "hooks.h" #include "registers.h" #include "task.h" +#include "usart-stm32f3.h" #include "util.h" /* @@ -22,7 +21,7 @@ static struct usart_config const *configs[STM32_USARTS_MAX]; struct usart_configs usart_get_configs(void) { - return (struct usart_configs) {configs, ARRAY_SIZE(configs)}; + return (struct usart_configs){ configs, ARRAY_SIZE(configs) }; } static void usart_variant_enable(struct usart_config const *config) @@ -50,13 +49,20 @@ static void usart_variant_disable(struct usart_config const *config) } static struct usart_hw_ops const usart_variant_hw_ops = { - .enable = usart_variant_enable, + .enable = usart_variant_enable, .disable = usart_variant_disable, }; void usart_clear_tc(struct usart_config const *config) { - STM32_USART_ICR(config->hw->base) |= STM32_USART_ICR_TCCF; + /* + * ST reference code does blind write to this register, as is usual + * with the "write 1 to clear" convention, despite the datasheet + * listing the bits as "keep at reset value", (which we assume is due + * to copying from the description of reserved bits in read/write + * registers.) + */ + STM32_USART_ICR(config->hw->base) = STM32_USART_ICR_TCCF; } /* @@ -65,15 +71,15 @@ void usart_clear_tc(struct usart_config const *config) */ #if defined(CONFIG_STREAM_USART1) struct usart_hw_config const usart1_hw = { - .index = 0, - .base = STM32_USART1_BASE, - .irq = STM32_IRQ_USART1, + .index = 0, + .base = STM32_USART1_BASE, + .irq = STM32_IRQ_USART1, .clock_register = &STM32_RCC_APB2ENR, - .clock_enable = STM32_RCC_PB2_USART1, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB2_USART1, + .ops = &usart_variant_hw_ops, }; -void usart1_interrupt(void) +static void usart1_interrupt(void) { usart_interrupt(configs[0]); } @@ -83,15 +89,15 @@ DECLARE_IRQ(STM32_IRQ_USART1, usart1_interrupt, 2); #if defined(CONFIG_STREAM_USART2) struct usart_hw_config const usart2_hw = { - .index = 1, - .base = STM32_USART2_BASE, - .irq = STM32_IRQ_USART2, + .index = 1, + .base = STM32_USART2_BASE, + .irq = STM32_IRQ_USART2, .clock_register = &STM32_RCC_APB1ENR, - .clock_enable = STM32_RCC_PB1_USART2, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB1_USART2, + .ops = &usart_variant_hw_ops, }; -void usart2_interrupt(void) +static void usart2_interrupt(void) { usart_interrupt(configs[1]); } @@ -101,17 +107,17 @@ DECLARE_IRQ(STM32_IRQ_USART2, usart2_interrupt, 2); #if defined(CONFIG_STREAM_USART3) struct usart_hw_config const usart3_hw = { - .index = 2, - .base = STM32_USART3_BASE, - .irq = STM32_IRQ_USART3, + .index = 2, + .base = STM32_USART3_BASE, + .irq = STM32_IRQ_USART3, .clock_register = &STM32_RCC_APB1ENR, - .clock_enable = STM32_RCC_PB1_USART3, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB1_USART3, + .ops = &usart_variant_hw_ops, }; #endif #if defined(CONFIG_STREAM_USART3) -void usart3_interrupt(void) +static void usart3_interrupt(void) { usart_interrupt(configs[2]); } diff --git a/chip/stm32/usart-stm32f3.h b/chip/stm32/usart-stm32f3.h index 09f1ba608c..e1c391183d 100644 --- a/chip/stm32/usart-stm32f3.h +++ b/chip/stm32/usart-stm32f3.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/stm32/usart-stm32f4.c b/chip/stm32/usart-stm32f4.c index a554da147a..0806cab062 100644 --- a/chip/stm32/usart-stm32f4.c +++ b/chip/stm32/usart-stm32f4.c @@ -1,16 +1,15 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "usart-stm32f4.h" - #include "clock.h" #include "common.h" #include "compile_time_macros.h" #include "hooks.h" #include "registers.h" #include "task.h" +#include "usart-stm32f4.h" #include "util.h" /* @@ -24,14 +23,13 @@ static struct usart_config const *configs[STM32_USARTS_MAX]; struct usart_configs usart_get_configs(void) { - return (struct usart_configs) {configs, ARRAY_SIZE(configs)}; + return (struct usart_configs){ configs, ARRAY_SIZE(configs) }; } static void usart_variant_enable(struct usart_config const *config) { configs[config->hw->index] = config; - /* Use single-bit sampling */ STM32_USART_CR3(config->hw->base) |= STM32_USART_CR3_ONEBIT; @@ -48,7 +46,7 @@ static void usart_variant_disable(struct usart_config const *config) } static struct usart_hw_ops const usart_variant_hw_ops = { - .enable = usart_variant_enable, + .enable = usart_variant_enable, .disable = usart_variant_disable, }; @@ -58,15 +56,15 @@ static struct usart_hw_ops const usart_variant_hw_ops = { */ #if defined(CONFIG_STREAM_USART1) struct usart_hw_config const usart1_hw = { - .index = 0, - .base = STM32_USART1_BASE, - .irq = STM32_IRQ_USART1, + .index = 0, + .base = STM32_USART1_BASE, + .irq = STM32_IRQ_USART1, .clock_register = &STM32_RCC_APB2ENR, - .clock_enable = STM32_RCC_PB2_USART1, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB2_USART1, + .ops = &usart_variant_hw_ops, }; -void usart1_interrupt(void) +static void usart1_interrupt(void) { usart_interrupt(configs[0]); } @@ -76,15 +74,15 @@ DECLARE_IRQ(STM32_IRQ_USART1, usart1_interrupt, 2); #if defined(CONFIG_STREAM_USART2) struct usart_hw_config const usart2_hw = { - .index = 1, - .base = STM32_USART2_BASE, - .irq = STM32_IRQ_USART2, + .index = 1, + .base = STM32_USART2_BASE, + .irq = STM32_IRQ_USART2, .clock_register = &STM32_RCC_APB1ENR, - .clock_enable = STM32_RCC_PB1_USART2, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB1_USART2, + .ops = &usart_variant_hw_ops, }; -void usart2_interrupt(void) +static void usart2_interrupt(void) { usart_interrupt(configs[1]); } @@ -94,17 +92,17 @@ DECLARE_IRQ(STM32_IRQ_USART2, usart2_interrupt, 2); #if defined(CONFIG_STREAM_USART3) struct usart_hw_config const usart3_hw = { - .index = 2, - .base = STM32_USART3_BASE, - .irq = STM32_IRQ_USART3, + .index = 2, + .base = STM32_USART3_BASE, + .irq = STM32_IRQ_USART3, .clock_register = &STM32_RCC_APB1ENR, - .clock_enable = STM32_RCC_PB1_USART3, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB1_USART3, + .ops = &usart_variant_hw_ops, }; #endif #if defined(CONFIG_STREAM_USART3) -void usart3_interrupt(void) +static void usart3_interrupt(void) { usart_interrupt(configs[2]); } diff --git a/chip/stm32/usart-stm32f4.h b/chip/stm32/usart-stm32f4.h index 49af2af405..5ecb4d62e1 100644 --- a/chip/stm32/usart-stm32f4.h +++ b/chip/stm32/usart-stm32f4.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/stm32/usart-stm32l.c b/chip/stm32/usart-stm32l.c index 2b7406a0a4..b6c9e21595 100644 --- a/chip/stm32/usart-stm32l.c +++ b/chip/stm32/usart-stm32l.c @@ -1,15 +1,14 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "usart-stm32l.h" - #include "clock.h" #include "common.h" #include "compile_time_macros.h" #include "hooks.h" #include "registers.h" #include "task.h" +#include "usart-stm32l.h" #include "util.h" /* @@ -23,7 +22,7 @@ static struct usart_config const *configs[STM32_USARTS_MAX]; struct usart_configs usart_get_configs(void) { - return (struct usart_configs) {configs, ARRAY_SIZE(configs)}; + return (struct usart_configs){ configs, ARRAY_SIZE(configs) }; } static void usart_variant_enable(struct usart_config const *config) @@ -52,18 +51,18 @@ static void usart_variant_disable(struct usart_config const *config) } static struct usart_hw_ops const usart_variant_hw_ops = { - .enable = usart_variant_enable, + .enable = usart_variant_enable, .disable = usart_variant_disable, }; static void freq_change(void) { - size_t i; + size_t i; for (i = 0; i < ARRAY_SIZE(configs); ++i) if (configs[i]) usart_set_baud_f0_l(configs[i], configs[i]->baud, - clock_get_freq()); + clock_get_freq()); } DECLARE_HOOK(HOOK_FREQ_CHANGE, freq_change, HOOK_PRIO_DEFAULT); @@ -79,15 +78,15 @@ void usart_clear_tc(struct usart_config const *config) */ #if defined(CONFIG_STREAM_USART1) struct usart_hw_config const usart1_hw = { - .index = 0, - .base = STM32_USART1_BASE, - .irq = STM32_IRQ_USART1, + .index = 0, + .base = STM32_USART1_BASE, + .irq = STM32_IRQ_USART1, .clock_register = &STM32_RCC_APB2ENR, - .clock_enable = STM32_RCC_PB2_USART1, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB2_USART1, + .ops = &usart_variant_hw_ops, }; -void usart1_interrupt(void) +static void usart1_interrupt(void) { usart_interrupt(configs[0]); } @@ -97,15 +96,15 @@ DECLARE_IRQ(STM32_IRQ_USART1, usart1_interrupt, 2); #if defined(CONFIG_STREAM_USART2) struct usart_hw_config const usart2_hw = { - .index = 1, - .base = STM32_USART2_BASE, - .irq = STM32_IRQ_USART2, + .index = 1, + .base = STM32_USART2_BASE, + .irq = STM32_IRQ_USART2, .clock_register = &STM32_RCC_APB1ENR, - .clock_enable = STM32_RCC_PB1_USART2, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB1_USART2, + .ops = &usart_variant_hw_ops, }; -void usart2_interrupt(void) +static void usart2_interrupt(void) { usart_interrupt(configs[1]); } @@ -115,15 +114,15 @@ DECLARE_IRQ(STM32_IRQ_USART2, usart2_interrupt, 2); #if defined(CONFIG_STREAM_USART3) struct usart_hw_config const usart3_hw = { - .index = 2, - .base = STM32_USART3_BASE, - .irq = STM32_IRQ_USART3, + .index = 2, + .base = STM32_USART3_BASE, + .irq = STM32_IRQ_USART3, .clock_register = &STM32_RCC_APB1ENR, - .clock_enable = STM32_RCC_PB1_USART3, - .ops = &usart_variant_hw_ops, + .clock_enable = STM32_RCC_PB1_USART3, + .ops = &usart_variant_hw_ops, }; -void usart3_interrupt(void) +static void usart3_interrupt(void) { usart_interrupt(configs[2]); } diff --git a/chip/stm32/usart-stm32l.h b/chip/stm32/usart-stm32l.h index eb1ae9db1d..2bb92fe1c7 100644 --- a/chip/stm32/usart-stm32l.h +++ b/chip/stm32/usart-stm32l.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/stm32/usart-stm32l5.c b/chip/stm32/usart-stm32l5.c new file mode 100644 index 0000000000..5f34c37bc4 --- /dev/null +++ b/chip/stm32/usart-stm32l5.c @@ -0,0 +1,185 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "clock.h" +#include "common.h" +#include "compile_time_macros.h" +#include "hooks.h" +#include "registers.h" +#include "task.h" +#include "usart-stm32l.h" +#include "util.h" + +/* + * This configs array stores the currently active usart_config structure for + * each USART, an entry will be NULL if no USART driver is initialized for the + * corresponding hardware instance. + */ +#define STM32_USARTS_MAX 6 + +static struct usart_config const *configs[STM32_USARTS_MAX]; + +struct usart_configs usart_get_configs(void) +{ + return (struct usart_configs){ configs, ARRAY_SIZE(configs) }; +} + +static void usart_variant_enable(struct usart_config const *config) +{ + /* Use single-bit sampling */ + STM32_USART_CR3(config->hw->base) |= STM32_USART_CR3_ONEBIT; + + /* + * Make sure we register this config before enabling the HW. + * If we did it the other way around the FREQ_CHANGE hook could be + * called before we update the configs array and we would miss the + * clock frequency change event, leaving our baud rate divisor wrong. + */ + configs[config->hw->index] = config; + + usart_set_baud_f0_l(config, config->baud, clock_get_freq()); + + task_enable_irq(config->hw->irq); +} + +static void usart_variant_disable(struct usart_config const *config) +{ + task_disable_irq(config->hw->irq); + + configs[config->hw->index] = NULL; +} + +static struct usart_hw_ops const usart_variant_hw_ops = { + .enable = usart_variant_enable, + .disable = usart_variant_disable, +}; + +static void freq_change(void) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(configs); ++i) + if (configs[i]) + usart_set_baud_f0_l(configs[i], configs[i]->baud, + clock_get_freq()); +} + +DECLARE_HOOK(HOOK_FREQ_CHANGE, freq_change, HOOK_PRIO_DEFAULT); + +void usart_clear_tc(struct usart_config const *config) +{ + STM32_USART_SR(config->hw->base) &= ~STM32_USART_SR_TC; +} + +/* + * USART interrupt bindings. These functions can not be defined as static or + * they will be removed by the linker because of the way that DECLARE_IRQ works. + */ +#if defined(CONFIG_STREAM_USART1) +struct usart_hw_config const usart1_hw = { + .index = 0, + .base = STM32_USART1_BASE, + .irq = STM32_IRQ_USART1, + .clock_register = &STM32_RCC_APB2ENR, + .clock_enable = STM32_RCC_PB2_USART1, + .ops = &usart_variant_hw_ops, +}; + +static void usart1_interrupt(void) +{ + usart_interrupt(configs[0]); +} + +DECLARE_IRQ(STM32_IRQ_USART1, usart1_interrupt, 2); +#endif + +#if defined(CONFIG_STREAM_USART2) +struct usart_hw_config const usart2_hw = { + .index = 1, + .base = STM32_USART2_BASE, + .irq = STM32_IRQ_USART2, + .clock_register = &STM32_RCC_APB1ENR, + .clock_enable = STM32_RCC_PB1_USART2, + .ops = &usart_variant_hw_ops, +}; + +static void usart2_interrupt(void) +{ + usart_interrupt(configs[1]); +} + +DECLARE_IRQ(STM32_IRQ_USART2, usart2_interrupt, 2); +#endif + +#if defined(CONFIG_STREAM_USART3) +struct usart_hw_config const usart3_hw = { + .index = 2, + .base = STM32_USART3_BASE, + .irq = STM32_IRQ_USART3, + .clock_register = &STM32_RCC_APB1ENR, + .clock_enable = STM32_RCC_PB1_USART3, + .ops = &usart_variant_hw_ops, +}; + +static void usart3_interrupt(void) +{ + usart_interrupt(configs[2]); +} + +DECLARE_IRQ(STM32_IRQ_USART3, usart3_interrupt, 2); +#endif + +#if defined(CONFIG_STREAM_USART4) +struct usart_hw_config const usart4_hw = { + .index = 3, + .base = STM32_USART4_BASE, + .irq = STM32_IRQ_USART4, + .clock_register = &STM32_RCC_APB1ENR, + .clock_enable = STM32_RCC_PB1_USART4, + .ops = &usart_variant_hw_ops, +}; + +static void usart4_interrupt(void) +{ + usart_interrupt(configs[3]); +} + +DECLARE_IRQ(STM32_IRQ_USART4, usart4_interrupt, 2); +#endif + +#if defined(CONFIG_STREAM_USART5) +struct usart_hw_config const usart5_hw = { + .index = 4, + .base = STM32_USART5_BASE, + .irq = STM32_IRQ_USART5, + .clock_register = &STM32_RCC_APB1ENR, + .clock_enable = STM32_RCC_PB1_USART5, + .ops = &usart_variant_hw_ops, +}; + +static void usart5_interrupt(void) +{ + usart_interrupt(configs[4]); +} + +DECLARE_IRQ(STM32_IRQ_USART5, usart5_interrupt, 2); +#endif + +#if defined(CONFIG_STREAM_USART9) +struct usart_hw_config const usart9_hw = { + .index = 5, + .base = STM32_USART9_BASE, + .irq = STM32_IRQ_USART9, + .clock_register = &STM32_RCC_APB1ENR2, + .clock_enable = STM32_RCC_APB1ENR2_LPUART1EN, + .ops = &usart_variant_hw_ops, +}; + +static void usart9_interrupt(void) +{ + usart_interrupt(configs[5]); +} + +DECLARE_IRQ(STM32_IRQ_USART9, usart9_interrupt, 2); +#endif diff --git a/chip/stm32/usart-stm32l5.h b/chip/stm32/usart-stm32l5.h new file mode 100644 index 0000000000..ccc0985bda --- /dev/null +++ b/chip/stm32/usart-stm32l5.h @@ -0,0 +1,21 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef __CROS_EC_USART_STM32L5_H +#define __CROS_EC_USART_STM32L5_H + +#include "usart.h" + +/* + * The STM32L5 series can have as many as five UARTS. These are the HW configs + * for those UARTS. They can be used to initialize STM32 generic UART configs. + */ +extern struct usart_hw_config const usart1_hw; +extern struct usart_hw_config const usart2_hw; +extern struct usart_hw_config const usart3_hw; +extern struct usart_hw_config const usart4_hw; +extern struct usart_hw_config const usart5_hw; +extern struct usart_hw_config const usart9_hw; /* LPUART1 */ + +#endif /* __CROS_EC_USART_STM32L5_H */ diff --git a/chip/stm32/usart.c b/chip/stm32/usart.c index 7f8c55aaa6..be9d0a4571 100644 --- a/chip/stm32/usart.c +++ b/chip/stm32/usart.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -45,7 +45,7 @@ void usart_init(struct usart_config const *config) cr2 = 0x0000; cr3 = 0x0000; #if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \ - defined(CHIP_FAMILY_STM32L4) + defined(CHIP_FAMILY_STM32L4) if (config->flags & USART_CONFIG_FLAG_RX_INV) cr2 |= BIT(16); if (config->flags & USART_CONFIG_FLAG_TX_INV) @@ -87,11 +87,16 @@ void usart_shutdown(struct usart_config const *config) } void usart_set_baud_f0_l(struct usart_config const *config, int baud, - int frequency_hz) + int frequency_hz) { - int div = DIV_ROUND_NEAREST(frequency_hz, baud); + int div = DIV_ROUND_NEAREST(frequency_hz, baud); intptr_t base = config->hw->base; +#ifdef STM32_USART9_BASE + if (config->hw->base == STM32_USART9_BASE) /* LPUART */ + div *= 256; +#endif + if (div / 16 > 0) { /* * CPU clock is high enough to support x16 oversampling. @@ -110,10 +115,15 @@ void usart_set_baud_f0_l(struct usart_config const *config, int baud, } void usart_set_baud_f(struct usart_config const *config, int baud, - int frequency_hz) + int frequency_hz) { int div = DIV_ROUND_NEAREST(frequency_hz, baud); +#ifdef STM32_USART9_BASE + if (config->hw->base == STM32_USART9_BASE) /* LPUART */ + div *= 256; +#endif + /* STM32F only supports x16 oversampling */ STM32_USART_BRR(config->hw->base) = div; } diff --git a/chip/stm32/usart.h b/chip/stm32/usart.h index 491bd66a04..9067fd4b6a 100644 --- a/chip/stm32/usart.h +++ b/chip/stm32/usart.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -97,12 +97,12 @@ extern struct usart_tx const usart_tx_interrupt; * structure are provided by each variants driver, one per physical USART. */ struct usart_hw_config { - int index; + int index; intptr_t base; - int irq; + int irq; uint32_t volatile *clock_register; - uint32_t clock_enable; + uint32_t clock_enable; struct usart_hw_ops const *ops; }; @@ -160,7 +160,7 @@ struct usart_config { * BUILD_ASSERT(RX_QUEUE.unit_bytes == 1); * BUILD_ASSERT(TX_QUEUE.unit_bytes == 1); */ -#define USART_CONFIG(HW, RX, TX, BAUD, FLAGS, RX_QUEUE, TX_QUEUE) \ +#define USART_CONFIG(HW, RX, TX, BAUD, FLAGS, RX_QUEUE, TX_QUEUE) \ ((struct usart_config const) { \ .hw = &HW, \ .rx = &RX, \ @@ -208,9 +208,9 @@ void usart_tx_start(struct usart_config const *config); * change. The baud rate divisor input frequency is passed in Hertz. */ void usart_set_baud_f0_l(struct usart_config const *config, int baud, - int frequency_hz); + int frequency_hz); void usart_set_baud_f(struct usart_config const *config, int baud, - int frequency_hz); + int frequency_hz); /* * Allow specification of parity for this usart. @@ -249,7 +249,7 @@ struct usart_configs { * * configs[i]->hw->index == i; */ - struct usart_config const * const *configs; + struct usart_config const *const *configs; /* * The total possible number of configs that this family supports. diff --git a/chip/stm32/usart_host_command.c b/chip/stm32/usart_host_command.c index f4d6a65fc4..817343df98 100644 --- a/chip/stm32/usart_host_command.c +++ b/chip/stm32/usart_host_command.c @@ -1,10 +1,10 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "common.h" #include "clock.h" +#include "common.h" #include "dma.h" #include "gpio.h" #include "hooks.h" @@ -13,14 +13,14 @@ #include "registers.h" #include "system.h" #include "task.h" -#include "usart_rx_dma.h" -#include "usart_host_command.h" #include "usart-stm32f4.h" +#include "usart_host_command.h" +#include "usart_rx_dma.h" #include "util.h" /* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_HOSTCMD, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_HOSTCMD, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ##args) /* * Timeout to wait for complete request packet @@ -51,7 +51,7 @@ /* * Max data size for a version 3 request/response packet. This is big enough - * to handle a request/response header, flash write offset/size and 512 bytes + * to handle a request/response header, flash write offset/size and 512 bytes * of request payload or 224 bytes of response payload. */ #define USART_MAX_REQUEST_SIZE 0x220 @@ -271,12 +271,12 @@ static struct usart_rx_dma const usart_host_command_rx_dma = { * Configure USART structure with hardware, interrupt handlers, baudrate. */ static struct usart_config const tl_usart = { - .hw = &CONFIG_UART_HOST_COMMAND_HW, - .rx = &usart_host_command_rx_dma.usart_rx, - .tx = &usart_host_command_tx_interrupt, - .state = &((struct usart_state){}), - .baud = CONFIG_UART_HOST_COMMAND_BAUD_RATE, - .flags = 0, + .hw = &CONFIG_UART_HOST_COMMAND_HW, + .rx = &usart_host_command_rx_dma.usart_rx, + .tx = &usart_host_command_tx_interrupt, + .state = &((struct usart_state){}), + .baud = CONFIG_UART_HOST_COMMAND_BAUD_RATE, + .flags = 0, }; /* @@ -327,7 +327,7 @@ static void usart_host_command_process_request(void) { /* Handle usart_in_buffer as ec_host_request */ struct ec_host_request *ec_request = - (struct ec_host_request *)usart_in_buffer; + (struct ec_host_request *)usart_in_buffer; /* Prepare host_packet for host command task */ static struct host_packet uart_packet; @@ -362,16 +362,13 @@ static void usart_host_command_process_request(void) * Cancel deferred call to timeout handler as request * received was good. */ - hook_call_deferred( - &usart_host_command_request_timeout_data, - -1); + hook_call_deferred(&usart_host_command_request_timeout_data, -1); uart_packet.send_response = usart_host_command_process_response; uart_packet.request = usart_in_buffer; uart_packet.request_temp = NULL; uart_packet.request_max = sizeof(usart_in_buffer); - uart_packet.request_size = - host_request_expected_size(ec_request); + uart_packet.request_size = host_request_expected_size(ec_request); uart_packet.response = usart_out_buffer; uart_packet.response_max = sizeof(usart_out_buffer); uart_packet.response_size = 0; @@ -427,14 +424,10 @@ static void usart_host_command_process_response(struct host_packet *pkt) static void usart_host_command_reset(void) { /* Cancel deferred call to process_request. */ - hook_call_deferred( - &usart_host_command_process_request_data, - -1); + hook_call_deferred(&usart_host_command_process_request_data, -1); /* Cancel deferred call to timeout handler. */ - hook_call_deferred( - &usart_host_command_request_timeout_data, - -1); + hook_call_deferred(&usart_host_command_request_timeout_data, -1); /* * Disable interrupts before entering critical region @@ -491,7 +484,7 @@ size_t usart_host_command_rx_append_data(struct usart_config const *config, { /* Define ec_host_request pointer to process in bytes later*/ struct ec_host_request *ec_request = - (struct ec_host_request *) usart_in_buffer; + (struct ec_host_request *)usart_in_buffer; /* Once the header is received, store the datalen */ static int usart_in_datalen; @@ -504,8 +497,7 @@ size_t usart_host_command_rx_append_data(struct usart_config const *config, current_state == USART_HOST_CMD_RECEIVING || (usart_in_head + count) < USART_MAX_REQUEST_SIZE) { /* Copy all the bytes from DMA FIFO */ - memcpy(usart_in_buffer + usart_in_head, - src, count); + memcpy(usart_in_buffer + usart_in_head, src, count); } /* @@ -519,7 +511,7 @@ size_t usart_host_command_rx_append_data(struct usart_config const *config, if (current_state == USART_HOST_CMD_READY_TO_RX) { /* Kick deferred call to request timeout handler */ hook_call_deferred(&usart_host_command_request_timeout_data, - USART_REQ_RX_TIMEOUT); + USART_REQ_RX_TIMEOUT); /* Move current state to receiving */ current_state = USART_HOST_CMD_RECEIVING; @@ -551,8 +543,7 @@ size_t usart_host_command_rx_append_data(struct usart_config const *config, } else if (usart_in_head > usart_in_datalen) { /* Cancel deferred call to process_request */ hook_call_deferred( - &usart_host_command_process_request_data, - -1); + &usart_host_command_process_request_data, -1); /* Move state to overrun*/ current_state = USART_HOST_CMD_RX_OVERRUN; @@ -579,13 +570,12 @@ size_t usart_host_command_tx_remove_data(struct usart_config const *config, { size_t bytes_remaining = 0; - if (current_state == USART_HOST_CMD_SENDING && - usart_out_datalen != 0) { + if (current_state == USART_HOST_CMD_SENDING && usart_out_datalen != 0) { /* Calculate byte_remaining in out_buffer */ bytes_remaining = usart_out_datalen - usart_out_head; /* Get char on the head */ - *((uint8_t *) dest) = usart_out_buffer[usart_out_head++]; + *((uint8_t *)dest) = usart_out_buffer[usart_out_head++]; /* If no bytes remaining, reset layer to accept next * request. diff --git a/chip/stm32/usart_host_command.h b/chip/stm32/usart_host_command.h index ee41d8a59b..ddbd5c5c99 100644 --- a/chip/stm32/usart_host_command.h +++ b/chip/stm32/usart_host_command.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,12 +6,13 @@ #ifndef __CROS_EC_USART_HOST_COMMAND_H #define __CROS_EC_USART_HOST_COMMAND_H -#include /* For va_list */ #include "common.h" #include "gpio.h" #include "host_command.h" #include "usart.h" +#include /* For va_list */ + /* * Add data to host command layer buffer. */ diff --git a/chip/stm32/usart_info_command.c b/chip/stm32/usart_info_command.c index 16d5e5747e..ca73b51210 100644 --- a/chip/stm32/usart_info_command.c +++ b/chip/stm32/usart_info_command.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -9,7 +9,7 @@ #include "console.h" #include "usart.h" -static int command_usart_info(int argc, char **argv) +static int command_usart_info(int argc, const char **argv) { struct usart_configs configs = usart_get_configs(); size_t i; @@ -24,10 +24,10 @@ static int command_usart_info(int argc, char **argv) " dropped %d bytes\n" " overran %d times\n", config->hw->index + 1, - deprecated_atomic_read_clear( - &(config->state->rx_dropped)), - deprecated_atomic_read_clear( - &(config->state->rx_overrun))); + (int)atomic_clear( + (atomic_t *)&(config->state->rx_dropped)), + (int)atomic_clear( + (atomic_t *)&(config->state->rx_overrun))); if (config->rx->info) config->rx->info(config); @@ -39,7 +39,5 @@ static int command_usart_info(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(usart_info, - command_usart_info, - NULL, +DECLARE_CONSOLE_COMMAND(usart_info, command_usart_info, NULL, "Display USART info"); diff --git a/chip/stm32/usart_rx_dma.c b/chip/stm32/usart_rx_dma.c index 1867c0a310..8997617ff3 100644 --- a/chip/stm32/usart_rx_dma.c +++ b/chip/stm32/usart_rx_dma.c @@ -1,20 +1,19 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "usart_rx_dma.h" - #include "atomic.h" #include "common.h" #include "console.h" #include "registers.h" #include "system.h" #include "usart_host_command.h" +#include "usart_rx_dma.h" #include "util.h" typedef size_t (*add_data_t)(struct usart_config const *config, - const uint8_t *src, size_t count); + const uint8_t *src, size_t count); void usart_rx_dma_init(struct usart_config const *config) { @@ -25,10 +24,9 @@ void usart_rx_dma_init(struct usart_config const *config) struct dma_option options = { .channel = dma_config->channel, - .periph = (void *)&STM32_USART_RDR(base), - .flags = (STM32_DMA_CCR_MSIZE_8_BIT | - STM32_DMA_CCR_PSIZE_8_BIT | - STM32_DMA_CCR_CIRC), + .periph = (void *)&STM32_USART_RDR(base), + .flags = (STM32_DMA_CCR_MSIZE_8_BIT | + STM32_DMA_CCR_PSIZE_8_BIT | STM32_DMA_CCR_CIRC), }; if (IS_ENABLED(CHIP_FAMILY_STM32F4)) @@ -38,31 +36,29 @@ void usart_rx_dma_init(struct usart_config const *config) STM32_USART_CR1(base) |= STM32_USART_CR1_RE; STM32_USART_CR3(base) |= STM32_USART_CR3_DMAR; - dma_config->state->index = 0; + dma_config->state->index = 0; dma_config->state->max_bytes = 0; dma_start_rx(&options, dma_config->fifo_size, dma_config->fifo_buffer); } -static void usart_rx_dma_interrupt_common( - struct usart_config const *config, - add_data_t add_data) +static void usart_rx_dma_interrupt_common(struct usart_config const *config, + add_data_t add_data) { struct usart_rx_dma const *dma_config = DOWNCAST(config->rx, struct usart_rx_dma const, usart_rx); - dma_chan_t *channel = dma_get_channel(dma_config->channel); - size_t new_index = dma_bytes_done(channel, dma_config->fifo_size); - size_t old_index = dma_config->state->index; - size_t new_bytes = 0; - size_t added = 0; + dma_chan_t *channel = dma_get_channel(dma_config->channel); + size_t new_index = dma_bytes_done(channel, dma_config->fifo_size); + size_t old_index = dma_config->state->index; + size_t new_bytes = 0; + size_t added = 0; if (new_index > old_index) { new_bytes = new_index - old_index; - added = add_data(config, - dma_config->fifo_buffer + old_index, - new_bytes); + added = add_data(config, dma_config->fifo_buffer + old_index, + new_bytes); } else if (new_index < old_index) { /* * Handle the case where the received bytes are not contiguous @@ -71,17 +67,14 @@ static void usart_rx_dma_interrupt_common( */ new_bytes = dma_config->fifo_size - (old_index - new_index); - added = add_data(config, - dma_config->fifo_buffer + old_index, - dma_config->fifo_size - old_index) + - add_data(config, - dma_config->fifo_buffer, - new_index); + added = add_data(config, dma_config->fifo_buffer + old_index, + dma_config->fifo_size - old_index) + + add_data(config, dma_config->fifo_buffer, new_index); } else { /* (new_index == old_index): nothing to add to the queue. */ } - deprecated_atomic_add(&config->state->rx_dropped, new_bytes - added); + atomic_add((atomic_t *)&(config->state->rx_dropped), new_bytes - added); if (dma_config->state->max_bytes < new_bytes) dma_config->state->max_bytes = new_bytes; @@ -89,8 +82,8 @@ static void usart_rx_dma_interrupt_common( dma_config->state->index = new_index; } -static size_t queue_add(struct usart_config const *config, - const uint8_t *src, size_t count) +static size_t queue_add(struct usart_config const *config, const uint8_t *src, + size_t count) { return queue_add_units(config->producer.queue, (void *)src, count); } @@ -100,7 +93,6 @@ void usart_rx_dma_interrupt(struct usart_config const *config) usart_rx_dma_interrupt_common(config, &queue_add); } - #if defined(CONFIG_USART_HOST_COMMAND) void usart_host_command_rx_dma_interrupt(struct usart_config const *config) { @@ -115,5 +107,5 @@ void usart_rx_dma_info(struct usart_config const *config) DOWNCAST(config->rx, struct usart_rx_dma const, usart_rx); ccprintf(" DMA RX max_bytes %d\n", - deprecated_atomic_read_clear(&dma_config->state->max_bytes)); + (int)atomic_clear((atomic_t *)&dma_config->state->max_bytes)); } diff --git a/chip/stm32/usart_rx_dma.h b/chip/stm32/usart_rx_dma.h index 064ab8046c..191ccc8c7f 100644 --- a/chip/stm32/usart_rx_dma.h +++ b/chip/stm32/usart_rx_dma.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -7,8 +7,8 @@ #ifndef __CROS_EC_USART_RX_DMA_H #define __CROS_EC_USART_RX_DMA_H -#include "producer.h" #include "dma.h" +#include "producer.h" #include "queue.h" #include "usart.h" @@ -44,7 +44,7 @@ * reasonable stress test the "DMA RX max_bytes" value will be a reasonable * size for the FIFO (perhaps +10% for safety). */ -#define USART_RX_DMA(CHANNEL, FIFO_SIZE) \ +#define USART_RX_DMA(CHANNEL, FIFO_SIZE) \ ((struct usart_rx_dma const) { \ .usart_rx = { \ .producer_ops = { \ @@ -88,7 +88,7 @@ struct usart_rx_dma { struct usart_rx_dma_state volatile *state; uint8_t *fifo_buffer; - size_t fifo_size; + size_t fifo_size; enum dma_channel channel; }; diff --git a/chip/stm32/usart_rx_interrupt-stm32f0.c b/chip/stm32/usart_rx_interrupt-stm32f0.c deleted file mode 120000 index a756455f9b..0000000000 --- a/chip/stm32/usart_rx_interrupt-stm32f0.c +++ /dev/null @@ -1 +0,0 @@ -usart_rx_interrupt.c \ No newline at end of file diff --git a/chip/stm32/usart_rx_interrupt-stm32f0.c b/chip/stm32/usart_rx_interrupt-stm32f0.c new file mode 100644 index 0000000000..a142bcd436 --- /dev/null +++ b/chip/stm32/usart_rx_interrupt-stm32f0.c @@ -0,0 +1,48 @@ +/* Copyright 2014 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Interrupt based USART RX driver for STM32F0 and STM32F3 */ + +#include "atomic.h" +#include "common.h" +#include "queue.h" +#include "registers.h" +#include "usart.h" + +static void usart_rx_init(struct usart_config const *config) +{ + intptr_t base = config->hw->base; + + STM32_USART_CR1(base) |= STM32_USART_CR1_RXNEIE; + STM32_USART_CR1(base) |= STM32_USART_CR1_RE; + STM32_USART_CR3(base) |= STM32_USART_CR3_OVRDIS; +} + +static void usart_rx_interrupt_handler(struct usart_config const *config) +{ + intptr_t base = config->hw->base; + int32_t status = STM32_USART_SR(base); + + if (status & STM32_USART_SR_RXNE) { + uint8_t byte = STM32_USART_RDR(base); + + if (!queue_add_unit(config->producer.queue, &byte)) + atomic_add((atomic_t *)&(config->state->rx_dropped), 1); + } +} + +struct usart_rx const usart_rx_interrupt = { + .producer_ops = { + /* + * Nothing to do here, we either had enough space in the queue + * when a character came in or we dropped it already. + */ + .read = NULL, + }, + + .init = usart_rx_init, + .interrupt = usart_rx_interrupt_handler, + .info = NULL, +}; diff --git a/chip/stm32/usart_rx_interrupt-stm32f3.c b/chip/stm32/usart_rx_interrupt-stm32f3.c deleted file mode 120000 index a756455f9b..0000000000 --- a/chip/stm32/usart_rx_interrupt-stm32f3.c +++ /dev/null @@ -1 +0,0 @@ -usart_rx_interrupt.c \ No newline at end of file diff --git a/chip/stm32/usart_rx_interrupt-stm32f3.c b/chip/stm32/usart_rx_interrupt-stm32f3.c new file mode 100644 index 0000000000..a142bcd436 --- /dev/null +++ b/chip/stm32/usart_rx_interrupt-stm32f3.c @@ -0,0 +1,48 @@ +/* Copyright 2014 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Interrupt based USART RX driver for STM32F0 and STM32F3 */ + +#include "atomic.h" +#include "common.h" +#include "queue.h" +#include "registers.h" +#include "usart.h" + +static void usart_rx_init(struct usart_config const *config) +{ + intptr_t base = config->hw->base; + + STM32_USART_CR1(base) |= STM32_USART_CR1_RXNEIE; + STM32_USART_CR1(base) |= STM32_USART_CR1_RE; + STM32_USART_CR3(base) |= STM32_USART_CR3_OVRDIS; +} + +static void usart_rx_interrupt_handler(struct usart_config const *config) +{ + intptr_t base = config->hw->base; + int32_t status = STM32_USART_SR(base); + + if (status & STM32_USART_SR_RXNE) { + uint8_t byte = STM32_USART_RDR(base); + + if (!queue_add_unit(config->producer.queue, &byte)) + atomic_add((atomic_t *)&(config->state->rx_dropped), 1); + } +} + +struct usart_rx const usart_rx_interrupt = { + .producer_ops = { + /* + * Nothing to do here, we either had enough space in the queue + * when a character came in or we dropped it already. + */ + .read = NULL, + }, + + .init = usart_rx_init, + .interrupt = usart_rx_interrupt_handler, + .info = NULL, +}; diff --git a/chip/stm32/usart_rx_interrupt-stm32f4.c b/chip/stm32/usart_rx_interrupt-stm32f4.c index 44e711327d..80ba37e88f 100644 --- a/chip/stm32/usart_rx_interrupt-stm32f4.c +++ b/chip/stm32/usart_rx_interrupt-stm32f4.c @@ -1,16 +1,15 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Interrupt based USART RX driver for STM32F0 and STM32F4 */ -#include "usart.h" - #include "atomic.h" #include "common.h" #include "queue.h" #include "registers.h" +#include "usart.h" static void usart_rx_init(struct usart_config const *config) { @@ -26,14 +25,14 @@ static void usart_rx_init(struct usart_config const *config) static void usart_rx_interrupt_handler(struct usart_config const *config) { - intptr_t base = config->hw->base; - int32_t status = STM32_USART_SR(base); + intptr_t base = config->hw->base; + int32_t status = STM32_USART_SR(base); if (status & STM32_USART_SR_RXNE) { uint8_t byte = STM32_USART_RDR(base); if (!queue_add_unit(config->producer.queue, &byte)) - deprecated_atomic_add(&config->state->rx_dropped, 1); + atomic_add((atomic_t *)&(config->state->rx_dropped), 1); } } diff --git a/chip/stm32/usart_rx_interrupt-stm32l.c b/chip/stm32/usart_rx_interrupt-stm32l.c index c0cd03d8c9..2c74d7dbd1 100644 --- a/chip/stm32/usart_rx_interrupt-stm32l.c +++ b/chip/stm32/usart_rx_interrupt-stm32l.c @@ -1,16 +1,15 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Interrupt based USART RX driver for STM32L */ -#include "usart.h" - #include "atomic.h" #include "common.h" #include "queue.h" #include "registers.h" +#include "usart.h" static void usart_rx_init(struct usart_config const *config) { @@ -22,15 +21,32 @@ static void usart_rx_init(struct usart_config const *config) static void usart_rx_interrupt_handler(struct usart_config const *config) { - intptr_t base = config->hw->base; - int32_t status = STM32_USART_SR(base); + intptr_t base = config->hw->base; + int32_t status = STM32_USART_SR(base); /* * We have to check and clear the overrun error flag on STM32L because * we can't disable it. */ if (status & STM32_USART_SR_ORE) { +#ifdef STM32_USART_ICR_ORECF + /* + * Newer series (STM32L4xx and STM32L5xx) have an explicit + * "interrupt clear" register. + * + * ST reference code does blind write to this register, as is + * usual with the "write 1 to clear" convention, despite the + * datasheet listing the bits as "keep at reset value", (which + * we assume is due to copying from the description of + * reserved bits in read/write registers.) + */ + STM32_USART_ICR(config->hw->base) = STM32_USART_ICR_ORECF; +#else /* + * On the older series STM32L1xx, the overrun bit is cleared + * by a read of the status register, followed by a read of the + * data register. + * * In the unlikely event that the overrun error bit was set but * the RXNE bit was not (possibly because a read was done from * RDR without first reading the status register) we do a read @@ -38,15 +54,16 @@ static void usart_rx_interrupt_handler(struct usart_config const *config) */ if (!(status & STM32_USART_SR_RXNE)) (void)STM32_USART_RDR(config->hw->base); +#endif - deprecated_atomic_add(&config->state->rx_overrun, 1); + atomic_add((atomic_t *)&(config->state->rx_overrun), 1); } if (status & STM32_USART_SR_RXNE) { uint8_t byte = STM32_USART_RDR(base); if (!queue_add_unit(config->producer.queue, &byte)) - deprecated_atomic_add(&config->state->rx_dropped, 1); + atomic_add((atomic_t *)&(config->state->rx_dropped), 1); } } diff --git a/chip/stm32/usart_rx_interrupt-stm32l5.c b/chip/stm32/usart_rx_interrupt-stm32l5.c new file mode 100644 index 0000000000..45c2ecca9f --- /dev/null +++ b/chip/stm32/usart_rx_interrupt-stm32l5.c @@ -0,0 +1,6 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "usart_rx_interrupt-stm32l.c" diff --git a/chip/stm32/usart_rx_interrupt.c b/chip/stm32/usart_rx_interrupt.c index 3cbf1f49f4..a142bcd436 100644 --- a/chip/stm32/usart_rx_interrupt.c +++ b/chip/stm32/usart_rx_interrupt.c @@ -1,16 +1,15 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Interrupt based USART RX driver for STM32F0 and STM32F3 */ -#include "usart.h" - #include "atomic.h" #include "common.h" #include "queue.h" #include "registers.h" +#include "usart.h" static void usart_rx_init(struct usart_config const *config) { @@ -23,14 +22,14 @@ static void usart_rx_init(struct usart_config const *config) static void usart_rx_interrupt_handler(struct usart_config const *config) { - intptr_t base = config->hw->base; - int32_t status = STM32_USART_SR(base); + intptr_t base = config->hw->base; + int32_t status = STM32_USART_SR(base); if (status & STM32_USART_SR_RXNE) { uint8_t byte = STM32_USART_RDR(base); if (!queue_add_unit(config->producer.queue, &byte)) - deprecated_atomic_add(&config->state->rx_dropped, 1); + atomic_add((atomic_t *)&(config->state->rx_dropped), 1); } } diff --git a/chip/stm32/usart_tx_dma.c b/chip/stm32/usart_tx_dma.c index 0c8e2c73d6..d6469aa9e6 100644 --- a/chip/stm32/usart_tx_dma.c +++ b/chip/stm32/usart_tx_dma.c @@ -1,14 +1,13 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "usart_tx_dma.h" - -#include "usart.h" #include "common.h" #include "registers.h" #include "system.h" #include "task.h" +#include "usart.h" +#include "usart_tx_dma.h" #include "util.h" void usart_tx_dma_written(struct consumer const *consumer, size_t count) @@ -36,13 +35,13 @@ static void usart_tx_dma_start(struct usart_config const *config, struct usart_tx_dma const *dma_config) { struct usart_tx_dma_state volatile *state = dma_config->state; - intptr_t base = config->hw->base; + intptr_t base = config->hw->base; struct dma_option options = { .channel = dma_config->channel, - .periph = (void *)&STM32_USART_TDR(base), - .flags = (STM32_DMA_CCR_MSIZE_8_BIT | - STM32_DMA_CCR_PSIZE_8_BIT), + .periph = (void *)&STM32_USART_TDR(base), + .flags = + (STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT), }; /* diff --git a/chip/stm32/usart_tx_dma.h b/chip/stm32/usart_tx_dma.h index c17164e04a..f1028e3a9e 100644 --- a/chip/stm32/usart_tx_dma.h +++ b/chip/stm32/usart_tx_dma.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -29,7 +29,7 @@ * required because the queue isn't notified that it has been read from until * after the DMA transfer completes. */ -#define USART_TX_DMA(CHANNEL, MAX_BYTES) \ +#define USART_TX_DMA(CHANNEL, MAX_BYTES) \ ((struct usart_tx_dma const) { \ .usart_tx = { \ .consumer_ops = { \ diff --git a/chip/stm32/usart_tx_interrupt.c b/chip/stm32/usart_tx_interrupt.c index 6a6aaf65f7..7c99840e26 100644 --- a/chip/stm32/usart_tx_interrupt.c +++ b/chip/stm32/usart_tx_interrupt.c @@ -1,16 +1,15 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Interrupt based USART TX driver for STM32 */ -#include "usart.h" - #include "common.h" #include "registers.h" #include "system.h" #include "task.h" +#include "usart.h" #include "usart_host_command.h" #include "util.h" @@ -37,12 +36,11 @@ static void usart_written(struct consumer const *consumer, size_t count) STM32_USART_CR1(config->hw->base) |= STM32_USART_CR1_TXEIE; } -static void usart_tx_interrupt_handler_common( - struct usart_config const *config, - remove_data_t remove_data) +static void usart_tx_interrupt_handler_common(struct usart_config const *config, + remove_data_t remove_data) { intptr_t base = config->hw->base; - uint8_t byte; + uint8_t byte; if (!(STM32_USART_SR(base) & STM32_USART_SR_TXE)) return; @@ -73,7 +71,7 @@ static void usart_tx_interrupt_handler_common( static size_t queue_remove(struct usart_config const *config, uint8_t *dest) { - return queue_remove_unit(config->producer.queue, (void *) dest); + return queue_remove_unit(config->consumer.queue, (void *)dest); } static void usart_tx_interrupt_handler(struct usart_config const *config) @@ -107,11 +105,11 @@ struct usart_tx const usart_tx_interrupt = { #if defined(CONFIG_USART_HOST_COMMAND) -static void usart_host_command_tx_interrupt_handler( - struct usart_config const *config) +static void +usart_host_command_tx_interrupt_handler(struct usart_config const *config) { usart_tx_interrupt_handler_common(config, - &usart_host_command_tx_remove_data); + &usart_host_command_tx_remove_data); } struct usart_tx const usart_host_command_tx_interrupt = { diff --git a/chip/stm32/usb-stm32f0.c b/chip/stm32/usb-stm32f0.c index 08c0a17455..227842f549 100644 --- a/chip/stm32/usb-stm32f0.c +++ b/chip/stm32/usb-stm32f0.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/chip/stm32/usb-stm32f3.c b/chip/stm32/usb-stm32f3.c index 2376d00b41..bef15db566 100644 --- a/chip/stm32/usb-stm32f3.c +++ b/chip/stm32/usb-stm32f3.c @@ -1,13 +1,12 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * STM32F3 Family specific USB functionality */ -#include "usb-stm32f3.h" - #include "system.h" +#include "usb-stm32f3.h" #include "usb_api.h" void usb_connect(void) diff --git a/chip/stm32/usb-stm32f3.h b/chip/stm32/usb-stm32f3.h index 196c43a53a..62921fe491 100644 --- a/chip/stm32/usb-stm32f3.h +++ b/chip/stm32/usb-stm32f3.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/chip/stm32/usb-stm32g4.c b/chip/stm32/usb-stm32g4.c new file mode 100644 index 0000000000..acd758584b --- /dev/null +++ b/chip/stm32/usb-stm32g4.c @@ -0,0 +1,27 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * STM32G4 Family specific USB functionality + */ + +#include "registers.h" +#include "system.h" +#include "usb_api.h" + +void usb_connect(void) +{ + /* USB is in use */ + disable_sleep(SLEEP_MASK_USB_DEVICE); + + STM32_USB_BCDR |= STM32_USB_BCDR_DPPU; +} + +void usb_disconnect(void) +{ + /* disable pull-up on DP to disconnect */ + STM32_USB_BCDR &= ~STM32_USB_BCDR_DPPU; + + /* USB is off, so sleep whenever */ + enable_sleep(SLEEP_MASK_USB_DEVICE); +} diff --git a/chip/stm32/usb-stm32l.c b/chip/stm32/usb-stm32l.c index bb9838531b..3780dfed10 100644 --- a/chip/stm32/usb-stm32l.c +++ b/chip/stm32/usb-stm32l.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/chip/stm32/usb-stm32l5.c b/chip/stm32/usb-stm32l5.c new file mode 100644 index 0000000000..a286ab488e --- /dev/null +++ b/chip/stm32/usb-stm32l5.c @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "registers.h" +#include "system.h" +#include "usb_api.h" + +void usb_connect(void) +{ + /* USB is in use */ + disable_sleep(SLEEP_MASK_USB_DEVICE); + + STM32_USB_BCDR |= STM32_USB_BCDR_DPPU; +} + +void usb_disconnect(void) +{ + /* disable pull-up on DP to disconnect */ + STM32_USB_BCDR &= ~STM32_USB_BCDR_DPPU; + + /* USB is off, so sleep whenever */ + enable_sleep(SLEEP_MASK_USB_DEVICE); +} diff --git a/chip/stm32/usb-stream.c b/chip/stm32/usb-stream.c index 7429832f10..f9cd2687bf 100644 --- a/chip/stm32/usb-stream.c +++ b/chip/stm32/usb-stream.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,10 +11,10 @@ #include "registers.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usart.h" -#include "usb_hw.h" #include "usb-stream.h" +#include "usb_hw.h" +#include "util.h" static size_t rx_read(struct usb_stream_config const *config) { @@ -28,19 +28,16 @@ static size_t rx_read(struct usb_stream_config const *config) if (count > queue_space(config->producer.queue)) return 0; - return queue_add_memcpy(config->producer.queue, - (void *) address, - count, + return queue_add_memcpy(config->producer.queue, (void *)address, count, memcpy_from_usbram); } static size_t tx_write(struct usb_stream_config const *config) { uintptr_t address = btable_ep[config->endpoint].tx_addr; - size_t count = queue_remove_memcpy(config->consumer.queue, - (void *) address, - config->tx_size, - memcpy_to_usbram); + size_t count = queue_remove_memcpy(config->consumer.queue, + (void *)address, config->tx_size, + memcpy_to_usbram); btable_ep[config->endpoint].tx_count = count; @@ -127,36 +124,33 @@ void usb_stream_event(struct usb_stream_config const *config, i = config->endpoint; - btable_ep[i].tx_addr = usb_sram_addr(config->tx_ram); + btable_ep[i].tx_addr = usb_sram_addr(config->tx_ram); btable_ep[i].tx_count = 0; - btable_ep[i].rx_addr = usb_sram_addr(config->rx_ram); + btable_ep[i].rx_addr = usb_sram_addr(config->rx_ram); btable_ep[i].rx_count = usb_ep_rx_size(config->rx_size); config->state->rx_waiting = 0; - STM32_USB_EP(i) = ((i << 0) | /* Endpoint Addr*/ - (2 << 4) | /* TX NAK */ - (0 << 9) | /* Bulk EP */ + STM32_USB_EP(i) = ((i << 0) | /* Endpoint Addr*/ + (2 << 4) | /* TX NAK */ + (0 << 9) | /* Bulk EP */ (rx_disabled(config) ? EP_RX_NAK : EP_RX_VALID)); } int usb_usart_interface(struct usb_stream_config const *config, - struct usart_config const *usart, - int interface, + struct usart_config const *usart, int interface, usb_uint *rx_buf, usb_uint *tx_buf) { struct usb_setup_packet req; usb_read_setup_packet(rx_buf, &req); - if (req.bmRequestType != (USB_DIR_OUT | - USB_TYPE_VENDOR | - USB_RECIP_INTERFACE)) + if (req.bmRequestType != + (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE)) return -1; - if (req.wIndex != interface || - req.wLength != 0) + if (req.wIndex != interface || req.wLength != 0) return -1; switch (req.bRequest) { diff --git a/chip/stm32/usb-stream.h b/chip/stm32/usb-stream.h index 915d8905cd..b22ee56620 100644 --- a/chip/stm32/usb-stream.h +++ b/chip/stm32/usb-stream.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -118,32 +118,25 @@ extern struct producer_ops const usb_stream_producer_ops; * BUILD_ASSERT(RX_QUEUE.unit_bytes == 1); * BUILD_ASSERT(TX_QUEUE.unit_bytes == 1); */ -#define USB_STREAM_CONFIG_FULL(NAME, \ - INTERFACE, \ - INTERFACE_CLASS, \ - INTERFACE_SUBCLASS, \ - INTERFACE_PROTOCOL, \ - INTERFACE_NAME, \ - ENDPOINT, \ - RX_SIZE, \ - TX_SIZE, \ - RX_QUEUE, \ - TX_QUEUE) \ - \ - BUILD_ASSERT(RX_SIZE <= USB_MAX_PACKET_SIZE); \ - BUILD_ASSERT(TX_SIZE <= USB_MAX_PACKET_SIZE); \ - BUILD_ASSERT(RX_SIZE > 0); \ - BUILD_ASSERT(TX_SIZE > 0); \ - BUILD_ASSERT((RX_SIZE < 64 && (RX_SIZE & 0x01) == 0) || \ - (RX_SIZE < 1024 && (RX_SIZE & 0x1f) == 0)); \ - BUILD_ASSERT((TX_SIZE < 64 && (TX_SIZE & 0x01) == 0) || \ - (TX_SIZE < 1024 && (TX_SIZE & 0x1f) == 0)); \ - \ - static usb_uint CONCAT2(NAME, _ep_rx_buffer)[RX_SIZE / 2] __usb_ram; \ - static usb_uint CONCAT2(NAME, _ep_tx_buffer)[TX_SIZE / 2] __usb_ram; \ - static struct usb_stream_state CONCAT2(NAME, _state); \ - static void CONCAT2(NAME, _deferred_)(void); \ - DECLARE_DEFERRED(CONCAT2(NAME, _deferred_)); \ +#define USB_STREAM_CONFIG_FULL(NAME, INTERFACE, INTERFACE_CLASS, \ + INTERFACE_SUBCLASS, INTERFACE_PROTOCOL, \ + INTERFACE_NAME, ENDPOINT, RX_SIZE, TX_SIZE, \ + RX_QUEUE, TX_QUEUE) \ + \ + BUILD_ASSERT(RX_SIZE <= USB_MAX_PACKET_SIZE); \ + BUILD_ASSERT(TX_SIZE <= USB_MAX_PACKET_SIZE); \ + BUILD_ASSERT(RX_SIZE > 0); \ + BUILD_ASSERT(TX_SIZE > 0); \ + BUILD_ASSERT((RX_SIZE < 64 && (RX_SIZE & 0x01) == 0) || \ + (RX_SIZE < 1024 && (RX_SIZE & 0x1f) == 0)); \ + BUILD_ASSERT((TX_SIZE < 64 && (TX_SIZE & 0x01) == 0) || \ + (TX_SIZE < 1024 && (TX_SIZE & 0x1f) == 0)); \ + \ + static usb_uint CONCAT2(NAME, _ep_rx_buffer)[RX_SIZE / 2] __usb_ram; \ + static usb_uint CONCAT2(NAME, _ep_tx_buffer)[TX_SIZE / 2] __usb_ram; \ + static struct usb_stream_state CONCAT2(NAME, _state); \ + static void CONCAT2(NAME, _deferred_)(void); \ + DECLARE_DEFERRED(CONCAT2(NAME, _deferred_)); \ struct usb_stream_config const NAME = { \ .state = &CONCAT2(NAME, _state), \ .endpoint = ENDPOINT, \ @@ -160,107 +153,80 @@ extern struct producer_ops const usb_stream_producer_ops; .queue = &RX_QUEUE, \ .ops = &usb_stream_producer_ops, \ }, \ - }; \ - const struct usb_interface_descriptor \ - USB_IFACE_DESC(INTERFACE) = { \ - .bLength = USB_DT_INTERFACE_SIZE, \ - .bDescriptorType = USB_DT_INTERFACE, \ - .bInterfaceNumber = INTERFACE, \ - .bAlternateSetting = 0, \ - .bNumEndpoints = 2, \ - .bInterfaceClass = INTERFACE_CLASS, \ - .bInterfaceSubClass = INTERFACE_SUBCLASS, \ - .bInterfaceProtocol = INTERFACE_PROTOCOL, \ - .iInterface = INTERFACE_NAME, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 0) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = 0x80 | ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk IN */, \ - .wMaxPacketSize = TX_SIZE, \ - .bInterval = 10, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 1) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk OUT */, \ - .wMaxPacketSize = RX_SIZE, \ - .bInterval = 0, \ - }; \ - static void CONCAT2(NAME, _ep_tx)(void) \ - { \ - usb_stream_tx(&NAME); \ - } \ - static void CONCAT2(NAME, _ep_rx)(void) \ - { \ - usb_stream_rx(&NAME); \ - } \ - static void CONCAT2(NAME, _ep_event)(enum usb_ep_event evt) \ - { \ - usb_stream_event(&NAME, evt); \ - } \ - USB_DECLARE_EP(ENDPOINT, \ - CONCAT2(NAME, _ep_tx), \ - CONCAT2(NAME, _ep_rx), \ - CONCAT2(NAME, _ep_event)); \ - static void CONCAT2(NAME, _deferred_)(void) \ - { usb_stream_deferred(&NAME); } + }; \ + const struct usb_interface_descriptor USB_IFACE_DESC(INTERFACE) = { \ + .bLength = USB_DT_INTERFACE_SIZE, \ + .bDescriptorType = USB_DT_INTERFACE, \ + .bInterfaceNumber = INTERFACE, \ + .bAlternateSetting = 0, \ + .bNumEndpoints = 2, \ + .bInterfaceClass = INTERFACE_CLASS, \ + .bInterfaceSubClass = INTERFACE_SUBCLASS, \ + .bInterfaceProtocol = INTERFACE_PROTOCOL, \ + .iInterface = INTERFACE_NAME, \ + }; \ + const struct usb_endpoint_descriptor USB_EP_DESC(INTERFACE, 0) = { \ + .bLength = USB_DT_ENDPOINT_SIZE, \ + .bDescriptorType = USB_DT_ENDPOINT, \ + .bEndpointAddress = 0x80 | ENDPOINT, \ + .bmAttributes = 0x02 /* Bulk IN */, \ + .wMaxPacketSize = TX_SIZE, \ + .bInterval = 10, \ + }; \ + const struct usb_endpoint_descriptor USB_EP_DESC(INTERFACE, 1) = { \ + .bLength = USB_DT_ENDPOINT_SIZE, \ + .bDescriptorType = USB_DT_ENDPOINT, \ + .bEndpointAddress = ENDPOINT, \ + .bmAttributes = 0x02 /* Bulk OUT */, \ + .wMaxPacketSize = RX_SIZE, \ + .bInterval = 0, \ + }; \ + static void CONCAT2(NAME, _ep_tx)(void) \ + { \ + usb_stream_tx(&NAME); \ + } \ + static void CONCAT2(NAME, _ep_rx)(void) \ + { \ + usb_stream_rx(&NAME); \ + } \ + static void CONCAT2(NAME, _ep_event)(enum usb_ep_event evt) \ + { \ + usb_stream_event(&NAME, evt); \ + } \ + USB_DECLARE_EP(ENDPOINT, CONCAT2(NAME, _ep_tx), CONCAT2(NAME, _ep_rx), \ + CONCAT2(NAME, _ep_event)); \ + static void CONCAT2(NAME, _deferred_)(void) \ + { \ + usb_stream_deferred(&NAME); \ + } /* This is a short version for declaring Google serial endpoints */ -#define USB_STREAM_CONFIG(NAME, \ - INTERFACE, \ - INTERFACE_NAME, \ - ENDPOINT, \ - RX_SIZE, \ - TX_SIZE, \ - RX_QUEUE, \ - TX_QUEUE) \ - USB_STREAM_CONFIG_FULL(NAME, \ - INTERFACE, \ - USB_CLASS_VENDOR_SPEC, \ - USB_SUBCLASS_GOOGLE_SERIAL, \ - USB_PROTOCOL_GOOGLE_SERIAL, \ - INTERFACE_NAME, \ - ENDPOINT, \ - RX_SIZE, \ - TX_SIZE, \ - RX_QUEUE, \ - TX_QUEUE) +#define USB_STREAM_CONFIG(NAME, INTERFACE, INTERFACE_NAME, ENDPOINT, RX_SIZE, \ + TX_SIZE, RX_QUEUE, TX_QUEUE) \ + USB_STREAM_CONFIG_FULL(NAME, INTERFACE, USB_CLASS_VENDOR_SPEC, \ + USB_SUBCLASS_GOOGLE_SERIAL, \ + USB_PROTOCOL_GOOGLE_SERIAL, INTERFACE_NAME, \ + ENDPOINT, RX_SIZE, TX_SIZE, RX_QUEUE, TX_QUEUE) /* Declare a utility interface for setting parity/baud. */ -#define USB_USART_IFACE(NAME, INTERFACE, USART_CFG) \ - static int CONCAT2(NAME, _interface_)(usb_uint *rx_buf, \ - usb_uint *tx_buf) \ - { return usb_usart_interface(&NAME, &USART_CFG, INTERFACE, \ - rx_buf, tx_buf); } \ - USB_DECLARE_IFACE(INTERFACE, \ - CONCAT2(NAME, _interface_)) +#define USB_USART_IFACE(NAME, INTERFACE, USART_CFG) \ + static int CONCAT2(NAME, _interface_)(usb_uint * rx_buf, \ + usb_uint * tx_buf) \ + { \ + return usb_usart_interface(&NAME, &USART_CFG, INTERFACE, \ + rx_buf, tx_buf); \ + } \ + USB_DECLARE_IFACE(INTERFACE, CONCAT2(NAME, _interface_)) /* This is a medium version for declaring Google serial endpoints */ -#define USB_STREAM_CONFIG_USART_IFACE(NAME, \ - INTERFACE, \ - INTERFACE_NAME, \ - ENDPOINT, \ - RX_SIZE, \ - TX_SIZE, \ - RX_QUEUE, \ - TX_QUEUE, \ - USART_CFG) \ - USB_STREAM_CONFIG_FULL(NAME, \ - INTERFACE, \ - USB_CLASS_VENDOR_SPEC, \ - USB_SUBCLASS_GOOGLE_SERIAL, \ - USB_PROTOCOL_GOOGLE_SERIAL, \ - INTERFACE_NAME, \ - ENDPOINT, \ - RX_SIZE, \ - TX_SIZE, \ - RX_QUEUE, \ - TX_QUEUE); \ +#define USB_STREAM_CONFIG_USART_IFACE(NAME, INTERFACE, INTERFACE_NAME, \ + ENDPOINT, RX_SIZE, TX_SIZE, RX_QUEUE, \ + TX_QUEUE, USART_CFG) \ + USB_STREAM_CONFIG_FULL(NAME, INTERFACE, USB_CLASS_VENDOR_SPEC, \ + USB_SUBCLASS_GOOGLE_SERIAL, \ + USB_PROTOCOL_GOOGLE_SERIAL, INTERFACE_NAME, \ + ENDPOINT, RX_SIZE, TX_SIZE, RX_QUEUE, \ + TX_QUEUE); \ USB_USART_IFACE(NAME, INTERFACE, USART_CFG) /* @@ -285,8 +251,8 @@ enum usb_usart { #define USB_USART_BAUD_MULTIPLIER 100 int usb_usart_interface(struct usb_stream_config const *config, - struct usart_config const *usart, - int interface, usb_uint *rx_buf, usb_uint *tx_buf); + struct usart_config const *usart, int interface, + usb_uint *rx_buf, usb_uint *tx_buf); /* * These functions are used by the trampoline functions defined above to diff --git a/chip/stm32/usb.c b/chip/stm32/usb.c index 1711480d53..06cf12cb5a 100644 --- a/chip/stm32/usb.c +++ b/chip/stm32/usb.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,13 +15,13 @@ #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_api.h" #include "usb_descriptor.h" #include "usb_hw.h" +#include "util.h" /* Console output macro */ -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) #ifdef CONFIG_USB_BOS /* v2.10 (vs 2.00) BOS Descriptor provided */ @@ -55,7 +55,7 @@ static const struct usb_device_descriptor dev_desc = { .bDeviceSubClass = 0x00, .bDeviceProtocol = 0x00, .bMaxPacketSize0 = USB_MAX_PACKET_SIZE, - .idVendor = USB_VID_GOOGLE, + .idVendor = CONFIG_USB_VID, .idProduct = CONFIG_USB_PID, .bcdDevice = CONFIG_USB_BCD_DEV, .iManufacturer = USB_STR_VENDOR, @@ -73,11 +73,11 @@ const struct usb_config_descriptor USB_CONF_DESC(conf) = { .bConfigurationValue = 1, .iConfiguration = USB_STR_VERSION, .bmAttributes = 0x80 /* Reserved bit */ -#ifdef CONFIG_USB_SELF_POWERED /* bus or self powered */ - | 0x40 +#ifdef CONFIG_USB_SELF_POWERED /* bus or self powered */ + | 0x40 #endif #ifdef CONFIG_USB_REMOTE_WAKEUP - | 0x20 + | 0x20 #endif , .bMaxPower = (CONFIG_USB_MAXPOWER_MA / 2), @@ -85,17 +85,47 @@ const struct usb_config_descriptor USB_CONF_DESC(conf) = { const uint8_t usb_string_desc[] = { 4, /* Descriptor size */ - USB_DT_STRING, - 0x09, 0x04 /* LangID = 0x0409: U.S. English */ + USB_DT_STRING, 0x09, 0x04 /* LangID = 0x0409: U.S. English */ }; +#ifdef CONFIG_USB_MS_EXTENDED_COMPAT_ID_DESCRIPTOR +/* + * String descriptor for Windows Compatible ID OS Descriptor. This string + * descriptor is used by Windows OS to know to request a Windows Compatible ID + * OS Descriptor so that Windows will load the proper WINUSB driver. + */ +const void *const usb_ms_os_string_descriptor = { USB_MS_STRING_DESC( + "MSFT100") }; + +/* + * Extended Compat ID OS Feature descriptor. This descriptor is used by Windows + * OS to know which type of driver is required so the USB-EP device gets + * registered properly. This type of descriptor may contain more than one + * function interface, but this instantiation only uses one function interface + * to communicate the WINUSB compatible ID. + */ +const struct usb_ms_ext_compat_id_desc winusb_desc = { + .dwLength = sizeof(struct usb_ms_ext_compat_id_desc), + .bcdVersion = 0x100, /* Windows Compat ID Desc v1.0 */ + .wIndex = USB_MS_EXT_COMPATIBLE_ID_INDEX, + .bCount = USB_MS_COMPAT_ID_FUNCTION, + .function = { + [0] = { + .bFirstInterfaceNumber = 0, + .reserved_1 = 1, + .compatible_id = {USB_MS_COMPAT_ID}, /* WINUSB */ + }, + }, +}; +#endif + /* Endpoint table in USB controller RAM */ struct stm32_endpoint btable_ep[USB_EP_COUNT] __aligned(8) __usb_btable; /* Control endpoint (EP0) buffers */ static usb_uint ep0_buf_tx[USB_MAX_PACKET_SIZE / 2] __usb_ram; static usb_uint ep0_buf_rx[USB_MAX_PACKET_SIZE / 2] __usb_ram; -#define EP0_BUF_TX_SRAM_ADDR ((void *) usb_sram_addr(ep0_buf_tx)) +#define EP0_BUF_TX_SRAM_ADDR ((void *)usb_sram_addr(ep0_buf_tx)) static int set_addr; /* remaining size of descriptor data to transfer */ @@ -112,10 +142,10 @@ static int remote_wakeup_enabled; void usb_read_setup_packet(usb_uint *buffer, struct usb_setup_packet *packet) { packet->bmRequestType = buffer[0] & 0xff; - packet->bRequest = buffer[0] >> 8; - packet->wValue = buffer[1]; - packet->wIndex = buffer[2]; - packet->wLength = buffer[3]; + packet->bRequest = buffer[0] >> 8; + packet->wValue = buffer[1]; + packet->wIndex = buffer[2]; + packet->wLength = buffer[3]; } struct usb_descriptor_patch { @@ -125,8 +155,8 @@ struct usb_descriptor_patch { static struct usb_descriptor_patch desc_patches[USB_DESC_PATCH_COUNT]; -void set_descriptor_patch(enum usb_desc_patch_type type, - const void *address, uint16_t data) +void set_descriptor_patch(enum usb_desc_patch_type type, const void *address, + uint16_t data) { desc_patches[type].address = address; desc_patches[type].data = data; @@ -146,7 +176,8 @@ void *memcpy_to_usbram_ep0_patch(const void *src, size_t n) continue; memcpy_to_usbram((void *)(usb_sram_addr(ep0_buf_tx) + offset), - &desc_patches[i].data, sizeof(desc_patches[i].data)); + &desc_patches[i].data, + sizeof(desc_patches[i].data)); } return ret; @@ -200,17 +231,30 @@ static void ep0_rx(void) } /* vendor specific request */ if ((req & USB_TYPE_MASK) == USB_TYPE_VENDOR) { -#ifdef CONFIG_WEBUSB_URL +#if defined(CONFIG_WEBUSB_URL) || \ + defined(CONFIG_USB_MS_EXTENDED_COMPAT_ID_DESCRIPTOR) uint8_t b_req = req >> 8; /* bRequest in the transfer */ - uint16_t idx = ep0_buf_rx[2]; /* wIndex in the transfer */ + uint16_t w_index = ep0_buf_rx[2]; /* wIndex in the transfer */ - if (b_req == 0x01 && idx == WEBUSB_REQ_GET_URL) { +#ifdef CONFIG_WEBUSB_URL + if (b_req == 0x01 && w_index == WEBUSB_REQ_GET_URL) { int len = *(uint8_t *)webusb_url; ep0_send_descriptor(webusb_url, len, 0); return; } -#endif +#endif /* CONFIG_WEBUSB_URL */ + +#ifdef CONFIG_USB_MS_EXTENDED_COMPAT_ID_DESCRIPTOR + if (b_req == USB_MS_STRING_DESC_VENDOR_CODE && + w_index == USB_MS_EXT_COMPATIBLE_ID_INDEX) { + ep0_send_descriptor((uint8_t *)&winusb_desc, + winusb_desc.dwLength, 0); + return; + } +#endif /* CONFIG_USB_MS_EXTENDED_COMPAT_ID_DESCRIPTOR */ + +#endif /* CONFIG_WEBUSB_URL || CONFIG_USB_MS_EXTENDED_COMPAT_ID_DESCRIPTOR */ goto unknown_req; } @@ -237,6 +281,19 @@ static void ep0_rx(void) break; #endif case USB_DT_STRING: /* Setup : Get string descriptor */ + +#ifdef CONFIG_USB_MS_EXTENDED_COMPAT_ID_DESCRIPTOR + /* + * String descriptor request at index == 0xEE is used by + * Windows OS to know how to retrieve an Extended Compat + * ID OS Feature descriptor. + */ + if (idx == USB_GET_MS_DESCRIPTOR) { + desc = (uint8_t *)usb_ms_os_string_descriptor; + len = desc[0]; + break; + } +#endif if (idx >= USB_STR_COUNT) /* The string does not exist : STALL */ goto unknown_req; @@ -254,8 +311,9 @@ static void ep0_rx(void) default: /* unhandled descriptor */ goto unknown_req; } - ep0_send_descriptor(desc, len, type == USB_DT_CONFIGURATION ? - USB_DESC_SIZE : 0); + ep0_send_descriptor( + desc, len, + type == USB_DT_CONFIGURATION ? USB_DESC_SIZE : 0); } else if (req == (USB_DIR_IN | (USB_REQ_GET_STATUS << 8))) { uint16_t data = 0; /* Get status */ @@ -269,14 +327,14 @@ static void ep0_rx(void) memcpy_to_usbram(EP0_BUF_TX_SRAM_ADDR, (void *)&data, 2); btable_ep[0].tx_count = 2; STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, - EP_STATUS_OUT /*null OUT transaction */); + EP_STATUS_OUT /*null OUT transaction */); } else if ((req & 0xff) == USB_DIR_OUT) { switch (req >> 8) { case USB_REQ_SET_FEATURE: case USB_REQ_CLEAR_FEATURE: #ifdef CONFIG_USB_REMOTE_WAKEUP if (ep0_buf_rx[1] == - USB_REQ_FEATURE_DEVICE_REMOTE_WAKEUP) { + USB_REQ_FEATURE_DEVICE_REMOTE_WAKEUP) { remote_wakeup_enabled = ((req >> 8) == USB_REQ_SET_FEATURE); btable_ep[0].tx_count = 0; @@ -351,13 +409,12 @@ static void ep0_event(enum usb_ep_event evt) if (evt != USB_EVENT_RESET) return; - STM32_USB_EP(0) = BIT(9) /* control EP */ | - (2 << 4) /* TX NAK */ | + STM32_USB_EP(0) = BIT(9) /* control EP */ | (2 << 4) /* TX NAK */ | (3 << 12) /* RX VALID */; btable_ep[0].tx_addr = usb_sram_addr(ep0_buf_tx); btable_ep[0].rx_addr = usb_sram_addr(ep0_buf_rx); - btable_ep[0].rx_count = 0x8000 | ((USB_MAX_PACKET_SIZE/32-1) << 10); + btable_ep[0].rx_count = 0x8000 | ((USB_MAX_PACKET_SIZE / 32 - 1) << 10); btable_ep[0].tx_count = 0; } USB_DECLARE_EP(0, ep0_tx, ep0_rx, ep0_event); @@ -401,7 +458,9 @@ static void usb_suspend(void) STM32_USB_CNTR |= STM32_USB_CNTR_LP_MODE; interrupt_enable(); +#if !defined(CHIP_FAMILY_STM32F0) clock_enable_module(MODULE_USB, 0); +#endif /* USB is not in use anymore, we can (hopefully) sleep now. */ enable_sleep(SLEEP_MASK_USB_DEVICE); @@ -417,8 +476,8 @@ static volatile int sof_received; static void usb_resume_deferred(void) { - uint32_t state = (STM32_USB_FNR & STM32_USB_FNR_RXDP_RXDM_MASK) - >> STM32_USB_FNR_RXDP_RXDM_SHIFT; + uint32_t state = (STM32_USB_FNR & STM32_USB_FNR_RXDP_RXDM_MASK) >> + STM32_USB_FNR_RXDP_RXDM_SHIFT; CPRINTF("RSMd %d %04x %d\n", state, STM32_USB_CNTR, sof_received); if (sof_received == 0 && (state == 2 || state == 3)) @@ -432,7 +491,9 @@ static void usb_resume(void) { uint32_t state; +#if !defined(CHIP_FAMILY_STM32F0) clock_enable_module(MODULE_USB, 1); +#endif /* Clear FSUSP bit to exit suspend mode */ STM32_USB_CNTR &= ~STM32_USB_CNTR_FSUSP; @@ -440,8 +501,8 @@ static void usb_resume(void) /* USB is in use again */ disable_sleep(SLEEP_MASK_USB_DEVICE); - state = (STM32_USB_FNR & STM32_USB_FNR_RXDP_RXDM_MASK) - >> STM32_USB_FNR_RXDP_RXDM_SHIFT; + state = (STM32_USB_FNR & STM32_USB_FNR_RXDP_RXDM_MASK) >> + STM32_USB_FNR_RXDP_RXDM_SHIFT; CPRINTF("RSM %d %04x\n", state, STM32_USB_CNTR); @@ -478,8 +539,7 @@ static volatile int usb_wake_done = 1; */ static volatile int esof_count; -__attribute__((weak)) -void board_usb_wake(void) +__attribute__((weak)) void board_usb_wake(void) { /* Side-band USB wake, do nothing by default. */ } @@ -498,8 +558,13 @@ static void usb_wake_deferred(void) * interface. */ CPRINTF("USB stuck\n"); +#if defined(STM32_RCC_APB1RSTR2_USBFSRST) + STM32_RCC_APB1RSTR2 |= STM32_RCC_APB1RSTR2_USBFSRST; + STM32_RCC_APB1RSTR2 &= STM32_RCC_APB1RSTR2_USBFSRST; +#else STM32_RCC_APB1RSTR |= STM32_RCC_PB1_USB; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_USB; +#endif usb_init(); } } @@ -517,7 +582,7 @@ void usb_wake(void) } /* Only allow one caller at a time. */ - if (!deprecated_atomic_read_clear(&usb_wake_done)) + if (!atomic_clear((atomic_t *)&usb_wake_done)) return; CPRINTF("WAKE\n"); @@ -537,8 +602,8 @@ void usb_wake(void) /* STM32_USB_CNTR can also be updated from interrupt context. */ interrupt_disable(); - STM32_USB_CNTR |= STM32_USB_CNTR_RESUME | - STM32_USB_CNTR_ESOFM | STM32_USB_CNTR_SOFM; + STM32_USB_CNTR |= STM32_USB_CNTR_RESUME | STM32_USB_CNTR_ESOFM | + STM32_USB_CNTR_SOFM; interrupt_enable(); /* Try side-band wake as well. */ @@ -593,8 +658,8 @@ static void usb_interrupt_handle_wake(uint16_t status) STM32_USB_CNTR &= ~STM32_USB_CNTR_RESUME; /* Then count down until state is resumed. */ - state = (STM32_USB_FNR & STM32_USB_FNR_RXDP_RXDM_MASK) - >> STM32_USB_FNR_RXDP_RXDM_SHIFT; + state = (STM32_USB_FNR & STM32_USB_FNR_RXDP_RXDM_MASK) >> + STM32_USB_FNR_RXDP_RXDM_SHIFT; /* * state 2, or receiving an SOF, means resume @@ -609,13 +674,13 @@ static void usb_interrupt_handle_wake(uint16_t status) STM32_USB_CNTR &= ~STM32_USB_CNTR_ESOFM; usb_wake_done = 1; if (!good) { - CPRINTF("wake error: cnt=%d state=%d\n", - esof_count, state); + CPRINTF("wake error: cnt=%d state=%d\n", esof_count, + state); usb_suspend(); return; } - CPRINTF("RSMOK%d %d\n", -esof_count, state); + CPRINTF("RSMOK%d %d\n", -esof_count, state); for (ep = 1; ep < USB_EP_COUNT; ep++) usb_ep_event[ep](USB_EVENT_DEVICE_RESUME); @@ -623,7 +688,7 @@ static void usb_interrupt_handle_wake(uint16_t status) } #endif /* CONFIG_USB_SUSPEND && CONFIG_USB_REMOTE_WAKEUP */ -void usb_interrupt(void) +static void usb_interrupt(void) { uint16_t status = STM32_USB_ISTR; @@ -642,7 +707,7 @@ void usb_interrupt(void) #ifdef CONFIG_USB_REMOTE_WAKEUP if (status & (STM32_USB_ISTR_ESOF | STM32_USB_ISTR_SOF) && - !usb_wake_done) + !usb_wake_done) usb_interrupt_handle_wake(status); #endif @@ -672,10 +737,7 @@ DECLARE_IRQ(STM32_IRQ_USB_LP, usb_interrupt, 1); void usb_init(void) { - /* Enable USB device clock. */ - STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB; - - /* we need a proper 48MHz clock */ + /* Enable USB device clock, possibly increasing system clock to 48MHz */ clock_enable_module(MODULE_USB, 1); /* configure the pinmux */ @@ -701,12 +763,10 @@ void usb_init(void) /* Enable interrupt handlers */ task_enable_irq(STM32_IRQ_USB_LP); /* set interrupts mask : reset/correct transfer/errors */ - STM32_USB_CNTR = STM32_USB_CNTR_CTRM | - STM32_USB_CNTR_PMAOVRM | + STM32_USB_CNTR = STM32_USB_CNTR_CTRM | STM32_USB_CNTR_PMAOVRM | STM32_USB_CNTR_ERRM | #ifdef CONFIG_USB_SUSPEND - STM32_USB_CNTR_WKUPM | - STM32_USB_CNTR_SUSPM | + STM32_USB_CNTR_WKUPM | STM32_USB_CNTR_SUSPM | #endif STM32_USB_CNTR_RESETM; @@ -738,26 +798,23 @@ void usb_release(void) /* unset pinmux */ gpio_config_module(MODULE_USB, 0); - /* disable 48MHz clock */ + /* disable USB device clock, possibly slowing down system clock */ clock_enable_module(MODULE_USB, 0); - - /* disable USB device clock */ - STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB; } /* ensure the host disconnects and reconnects over a sysjump */ DECLARE_HOOK(HOOK_SYSJUMP, usb_release, HOOK_PRIO_DEFAULT); int usb_is_enabled(void) { - return (STM32_RCC_APB1ENR & STM32_RCC_PB1_USB) ? 1 : 0; + return clock_is_module_enabled(MODULE_USB); } void *memcpy_to_usbram(void *dest, const void *src, size_t n) { - int unaligned = (((uintptr_t) dest) & 1); - usb_uint *d = &__usb_ram_start[((uintptr_t) dest) / 2]; - uint8_t *s = (uint8_t *) src; - int i; + int unaligned = (((uintptr_t)dest) & 1); + usb_uint *d = &__usb_ram_start[((uintptr_t)dest) / 2]; + uint8_t *s = (uint8_t *)src; + int i; /* * Handle unaligned leading byte via read/modify/write. @@ -784,10 +841,10 @@ void *memcpy_to_usbram(void *dest, const void *src, size_t n) void *memcpy_from_usbram(void *dest, const void *src, size_t n) { - int unaligned = (((uintptr_t) src) & 1); - usb_uint const *s = &__usb_ram_start[((uintptr_t) src) / 2]; - uint8_t *d = (uint8_t *) dest; - int i; + int unaligned = (((uintptr_t)src) & 1); + usb_uint const *s = &__usb_ram_start[((uintptr_t)src) / 2]; + uint8_t *d = (uint8_t *)dest; + int i; if (unaligned && n) { *d = *s >> 8; @@ -868,7 +925,7 @@ static int usb_save_serial(const char *serialno) return rv; } -static int command_serialno(int argc, char **argv) +static int command_serialno(int argc, const char **argv) { struct usb_string_desc *sd = usb_serialno_desc; char buf[CONFIG_SERIALNO_LEN]; @@ -876,12 +933,10 @@ static int command_serialno(int argc, char **argv) int i; if (argc != 1) { - if ((strcasecmp(argv[1], "set") == 0) && - (argc == 3)) { + if ((strcasecmp(argv[1], "set") == 0) && (argc == 3)) { ccprintf("Saving serial number\n"); rv = usb_save_serial(argv[2]); - } else if ((strcasecmp(argv[1], "load") == 0) && - (argc == 2)) { + } else if ((strcasecmp(argv[1], "load") == 0) && (argc == 2)) { ccprintf("Loading serial number\n"); rv = usb_load_serial(); } else @@ -894,11 +949,10 @@ static int command_serialno(int argc, char **argv) return rv; } -DECLARE_CONSOLE_COMMAND(serialno, command_serialno, - "load/set [value]", - "Read and write USB serial number"); +DECLARE_CONSOLE_COMMAND(serialno, command_serialno, "load/set [value]", + "Read and write USB serial number"); -#endif /* CONFIG_USB_SERIALNO */ +#endif /* CONFIG_USB_SERIALNO */ #ifdef CONFIG_MAC_ADDR @@ -925,18 +979,16 @@ static int usb_save_mac_addr(const char *mac_addr) } } -static int command_macaddr(int argc, char **argv) +static int command_macaddr(int argc, const char **argv) { - const char* buf; + const char *buf; int rv = EC_SUCCESS; if (argc != 1) { - if ((strcasecmp(argv[1], "set") == 0) && - (argc == 3)) { + if ((strcasecmp(argv[1], "set") == 0) && (argc == 3)) { ccprintf("Saving MAC address\n"); rv = usb_save_mac_addr(argv[2]); - } else if ((strcasecmp(argv[1], "load") == 0) && - (argc == 2)) { + } else if ((strcasecmp(argv[1], "load") == 0) && (argc == 2)) { ccprintf("Loading MAC address\n"); } else { return EC_ERROR_INVAL; @@ -951,8 +1003,7 @@ static int command_macaddr(int argc, char **argv) return rv; } -DECLARE_CONSOLE_COMMAND(macaddr, command_macaddr, - "load/set [value]", - "Read and write MAC address"); +DECLARE_CONSOLE_COMMAND(macaddr, command_macaddr, "load/set [value]", + "Read and write MAC address"); -#endif /* CONFIG_MAC_ADDR */ +#endif /* CONFIG_MAC_ADDR */ diff --git a/chip/stm32/usb_console.c b/chip/stm32/usb_console.c index b5666c8fbf..062ce2f484 100644 --- a/chip/stm32/usb_console.c +++ b/chip/stm32/usb_console.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,17 +12,17 @@ #include "registers.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_api.h" #include "usb_descriptor.h" #include "usb_hw.h" +#include "util.h" /* Console output macro */ -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) #define USB_CONSOLE_TIMEOUT_US (30 * MSEC) -static struct queue const tx_q = QUEUE_NULL(CONFIG_USB_CONSOLE_TX_BUF_SIZE, - uint8_t); +static struct queue const tx_q = + QUEUE_NULL(CONFIG_USB_CONSOLE_TX_BUF_SIZE, uint8_t); static struct queue const rx_q = QUEUE_NULL(USB_MAX_PACKET_SIZE, uint8_t); static int last_tx_ok = 1; @@ -33,31 +33,31 @@ static int is_readonly; /* USB-Serial descriptors */ const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_CONSOLE) = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = USB_IFACE_CONSOLE, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = USB_IFACE_CONSOLE, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_SERIAL, .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_SERIAL, - .iInterface = USB_STR_CONSOLE_NAME, + .iInterface = USB_STR_CONSOLE_NAME, }; const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_CONSOLE, 0) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x80 | USB_EP_CONSOLE, - .bmAttributes = 0x02 /* Bulk IN */, - .wMaxPacketSize = USB_MAX_PACKET_SIZE, - .bInterval = 10 + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x80 | USB_EP_CONSOLE, + .bmAttributes = 0x02 /* Bulk IN */, + .wMaxPacketSize = USB_MAX_PACKET_SIZE, + .bInterval = 10 }; const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_CONSOLE, 1) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_EP_CONSOLE, - .bmAttributes = 0x02 /* Bulk OUT */, - .wMaxPacketSize = USB_MAX_PACKET_SIZE, - .bInterval = 0 + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_EP_CONSOLE, + .bmAttributes = 0x02 /* Bulk OUT */, + .wMaxPacketSize = USB_MAX_PACKET_SIZE, + .bInterval = 0 }; static usb_uint ep_buf_tx[USB_MAX_PACKET_SIZE / 2] __usb_ram; @@ -81,9 +81,8 @@ static void con_ep_rx(void) for (i = 0; i < (btable_ep[USB_EP_CONSOLE].rx_count & RX_COUNT_MASK); i++) { - int val = ((i & 1) ? - (ep_buf_rx[i >> 1] >> 8) : - (ep_buf_rx[i >> 1] & 0xff)); + int val = ((i & 1) ? (ep_buf_rx[i >> 1] >> 8) : + (ep_buf_rx[i >> 1] & 0xff)); QUEUE_ADD_UNITS(&rx_q, &val, 1); } @@ -100,18 +99,18 @@ static void ep_event(enum usb_ep_event evt) if (evt != USB_EVENT_RESET) return; - btable_ep[USB_EP_CONSOLE].tx_addr = usb_sram_addr(ep_buf_tx); + btable_ep[USB_EP_CONSOLE].tx_addr = usb_sram_addr(ep_buf_tx); btable_ep[USB_EP_CONSOLE].tx_count = 0; - btable_ep[USB_EP_CONSOLE].rx_addr = usb_sram_addr(ep_buf_rx); + btable_ep[USB_EP_CONSOLE].rx_addr = usb_sram_addr(ep_buf_rx); btable_ep[USB_EP_CONSOLE].rx_count = 0x8000 | ((USB_MAX_PACKET_SIZE / 32 - 1) << 10); - STM32_USB_EP(USB_EP_CONSOLE) = (USB_EP_CONSOLE | /* Endpoint Addr */ - (2 << 4) | /* TX NAK */ - (0 << 9) | /* Bulk EP */ - (is_readonly ? EP_RX_NAK - : EP_RX_VALID)); + STM32_USB_EP(USB_EP_CONSOLE) = + (USB_EP_CONSOLE | /* Endpoint Addr */ + (2 << 4) | /* TX NAK */ + (0 << 9) | /* Bulk EP */ + (is_readonly ? EP_RX_NAK : EP_RX_VALID)); is_reset = 1; } @@ -201,9 +200,9 @@ static void tx_fifo_handler(void) break; if (!(count & 1)) - buf[count/2] = val; + buf[count / 2] = val; else - buf[count/2] |= val << 8; + buf[count / 2] |= val << 8; count++; } diff --git a/chip/stm32/usb_dfu_runtime.c b/chip/stm32/usb_dfu_runtime.c new file mode 100644 index 0000000000..92e152078b --- /dev/null +++ b/chip/stm32/usb_dfu_runtime.c @@ -0,0 +1,92 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "dfu_bootmanager_shared.h" +#include "registers.h" +#include "usb_descriptor.h" +#include "usb_dfu_runtime.h" +#include "usb_hw.h" + +/* DFU Run-Time Descriptor Set. */ +const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_DFU) = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = USB_IFACE_DFU, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_APP_SPEC, + .bInterfaceSubClass = USB_DFU_RUNTIME_SUBCLASS, + .bInterfaceProtocol = USB_DFU_RUNTIME_PROTOCOL, + .iInterface = USB_STR_DFU_NAME, +}; + +/* DFU Functional Descriptor. */ +const struct usb_runtime_dfu_functional_desc + USB_CUSTOM_DESC_VAR(USB_IFACE_DFU, dfu, dfu_func_desc) = { + .bLength = USB_DFU_RUNTIME_DESC_SIZE, + .bDescriptorType = USB_DFU_RUNTIME_DESC_FUNCTIONAL, + .bmAttributes = USB_DFU_RUNTIME_DESC_ATTRS, + .wDetachTimeOut = USB_DFU_RUNTIME_DESC_DETACH_TIMEOUT, + .wTransferSize = USB_DFU_RUNTIME_DESC_TRANSFER_SIZE, + .bcdDFUVersion = USB_DFU_RUNTIME_DESC_DFU_VERSION, + }; + +static int dfu_runtime_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx) +{ + struct usb_setup_packet packet; + + usb_read_setup_packet(ep0_buf_rx, &packet); + btable_ep[0].tx_count = 0; + if ((packet.bmRequestType == + (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE)) && + (packet.bRequest == USB_REQ_SET_INTERFACE)) { + /* ACK the change alternative mode request. */ + + STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0); + return 0; + } else if ((packet.bmRequestType == + (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) && + (packet.bRequest == USB_DFU_RUNTIME_REQ_DETACH)) { + /* Host is requesting a jump from application to DFU mode. */ + + STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0); + return dfu_bootmanager_enter_dfu(); + } else if (packet.bmRequestType == + (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) { + if (packet.bRequest == USB_DFU_RUNTIME_REQ_GET_STATUS) { + /* Return the Get Status response. */ + + struct usb_runtime_dfu_get_status_resp response = { + .bStatus = USB_DFU_RUNTIME_STATUS_OK, + .bState = USB_DFU_RUNTIME_STATE_APP_IDLE, + }; + + memcpy_to_usbram((void *)usb_sram_addr(ep0_buf_tx), + &response, sizeof(response)); + btable_ep[0].tx_count = sizeof(response); + STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0); + return 0; + } + if (packet.bRequest == USB_DFU_RUNTIME_REQ_GET_STATE) { + /* Return the Get State response. */ + + struct usb_runtime_dfu_get_state_resp response = { + .bState = USB_DFU_RUNTIME_STATE_APP_IDLE, + }; + + memcpy_to_usbram((void *)usb_sram_addr(ep0_buf_tx), + &response, sizeof(response)); + btable_ep[0].tx_count = sizeof(response); + STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0); + return 0; + } + } + /* Return a stall response for any unhandled packets. */ + + STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_RX_VALID | EP_TX_STALL, 0); + return 0; +} + +USB_DECLARE_IFACE(USB_IFACE_DFU, dfu_runtime_request) diff --git a/chip/stm32/usb_dfu_runtime.h b/chip/stm32/usb_dfu_runtime.h new file mode 100644 index 0000000000..8b0bbbe219 --- /dev/null +++ b/chip/stm32/usb_dfu_runtime.h @@ -0,0 +1,72 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef __USB_DFU_H +#define __USB_DFU_H + +#include "common.h" + +/* Universal Serial Bus Device Class Specification for Device Firmware Upgrade + * Version 1.1 + * https://www.usb.org/sites/default/files/DFU_1.1.pdf + */ + +#define USB_DFU_RUNTIME_SUBCLASS 0x01 +#define USB_DFU_RUNTIME_PROTOCOL 0x01 + +#define USB_DFU_RUNTIME_DESC_ATTR_CAN_DOWNLOAD BIT(0) +#define USB_DFU_RUNTIME_DESC_ATTR_CAN_UPLOAD BIT(1) +#define USB_DFU_RUNTIME_DESC_ATTR_MANIFEST_TOLERANT BIT(2) +#define USB_DFU_RUNTIME_DESC_ATTR_WILL_DETACH BIT(3) + +#define USB_DFU_RUNTIME_DESC_ATTRS \ + (USB_DFU_RUNTIME_DESC_ATTR_CAN_DOWNLOAD | \ + USB_DFU_RUNTIME_DESC_ATTR_CAN_UPLOAD | \ + USB_DFU_RUNTIME_DESC_ATTR_WILL_DETACH) + +#define USB_DFU_RUNTIME_DESC_SIZE 9 +#define USB_DFU_RUNTIME_DESC_FUNCTIONAL 0x21 +#define USB_DFU_RUNTIME_DESC_DETACH_TIMEOUT 0xffff +#define USB_DFU_RUNTIME_DESC_TRANSFER_SIZE 64 +#define USB_DFU_RUNTIME_DESC_DFU_VERSION 0x0022 + +/* DFU states */ +#define USB_DFU_RUNTIME_STATE_APP_IDLE 0 +#define USB_DFU_RUNTIME_STATE_APP_DETACH 1 + +/* DFU status */ +#define USB_DFU_RUNTIME_STATUS_OK 0 + +/* DFU Request types */ +#define USB_DFU_RUNTIME_REQ_DETACH 0 +#define USB_DFU_RUNTIME_REQ_DNLOAD 1 +#define USB_DFU_RUNTIME_REQ_UPLOAD 2 +#define USB_DFU_RUNTIME_REQ_GET_STATUS 3 +#define USB_DFU_RUNTIME_REQ_CLR_STATUS 4 +#define USB_DFU_RUNTIME_REQ_GET_STATE 5 +#define USB_DFU_RUNTIME_REQ_ABORT 6 + +/* DFU Functional Descriptor */ +struct usb_runtime_dfu_functional_desc { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bmAttributes; + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +} __packed; + +/* DFU response packets */ +struct usb_runtime_dfu_get_status_resp { + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +} __packed; + +struct usb_runtime_dfu_get_state_resp { + uint8_t bState; +} __packed; + +#endif /* __USB_DFU_H */ diff --git a/chip/stm32/usb_dwc.c b/chip/stm32/usb_dwc.c index f4ee89f1f0..15ce4bff7f 100644 --- a/chip/stm32/usb_dwc.c +++ b/chip/stm32/usb_dwc.c @@ -1,8 +1,9 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "clock.h" #include "common.h" #include "config.h" @@ -12,27 +13,25 @@ #include "hooks.h" #include "link_defs.h" #include "registers.h" -#include "usb_hw.h" #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_descriptor.h" +#include "usb_hw.h" +#include "util.h" #include "watchdog.h" - /****************************************************************************/ /* Debug output */ /* Console output macro */ -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) /* TODO: Something unexpected happened. Figure out how to report & fix it. */ -#define report_error(val) \ - CPRINTS("Unhandled USB event at %s line %d: 0x%x", \ - __FILE__, __LINE__, val) - +#define report_error(val) \ + CPRINTS("Unhandled USB event at %s line %d: 0x%x", __FILE__, __LINE__, \ + val) /****************************************************************************/ /* Standard USB stuff */ @@ -49,7 +48,7 @@ #endif #ifndef CONFIG_USB_BCD_DEV -#define CONFIG_USB_BCD_DEV 0x0100 /* 1.00 */ +#define CONFIG_USB_BCD_DEV 0x0100 /* 1.00 */ #endif #ifndef CONFIG_USB_SERIALNO @@ -58,7 +57,6 @@ static int usb_load_serial(void); #endif - /* USB Standard Device Descriptor */ static const struct usb_device_descriptor dev_desc = { .bLength = USB_DT_DEVICE_SIZE, @@ -81,25 +79,24 @@ static const struct usb_device_descriptor dev_desc = { const struct usb_config_descriptor USB_CONF_DESC(conf) = { .bLength = USB_DT_CONFIG_SIZE, .bDescriptorType = USB_DT_CONFIGURATION, - .wTotalLength = 0x0BAD, /* number of returned bytes, set at runtime */ + .wTotalLength = 0x0BAD, /* number of returned bytes, set at runtime */ .bNumInterfaces = USB_IFACE_COUNT, - .bConfigurationValue = 1, /* Caution: hard-coded value */ + .bConfigurationValue = 1, /* Caution: hard-coded value */ .iConfiguration = USB_STR_VERSION, .bmAttributes = 0x80 /* Reserved bit */ -#ifdef CONFIG_USB_SELF_POWERED /* bus or self powered */ - | 0x40 +#ifdef CONFIG_USB_SELF_POWERED /* bus or self powered */ + | 0x40 #endif #ifdef CONFIG_USB_REMOTE_WAKEUP - | 0x20 + | 0x20 #endif , .bMaxPower = (CONFIG_USB_MAXPOWER_MA / 2), }; const uint8_t usb_string_desc[] = { - 4, /* Descriptor size */ - USB_DT_STRING, - 0x09, 0x04 /* LangID = 0x0409: U.S. English */ + 4, /* Descriptor size */ + USB_DT_STRING, 0x09, 0x04 /* LangID = 0x0409: U.S. English */ }; /****************************************************************************/ @@ -113,7 +110,7 @@ static enum { } what_am_i_doing; #ifdef DEBUG_ME -static const char * const wat[3] = { +static const char *const wat[3] = { [WAITING_FOR_SETUP_PACKET] = "wait_for_setup", [DATA_STAGE_IN] = "data_in", [NO_DATA_STAGE] = "no_data", @@ -182,7 +179,6 @@ static enum { } device_state; static uint8_t configuration_value; - /* True if the HW Rx/OUT FIFO is currently listening. */ int rx_ep_is_active(uint32_t ep_num) { @@ -326,10 +322,9 @@ void usb_epN_rx(uint32_t ep_num) /* Bytes received decrement DOEPTSIZ XFERSIZE */ if (GR_USB_DOEPINT(ep_num) & DOEPINT_XFERCOMPL) { if (ep->out_expected > 0) { - ep->out_pending = - ep->out_expected - - (GR_USB_DOEPTSIZ(ep_num) & - GC_USB_DOEPTSIZ1_XFERSIZE_MASK); + ep->out_pending = ep->out_expected - + (GR_USB_DOEPTSIZ(ep_num) & + GC_USB_DOEPTSIZ1_XFERSIZE_MASK); } else { CPRINTF("usb_ep%d_rx: unexpected RX DOEPTSIZ %08x\n", ep_num, GR_USB_DOEPTSIZ(ep_num)); @@ -350,25 +345,22 @@ void usb_epN_rx(uint32_t ep_num) void epN_reset(uint32_t ep_num) { GR_USB_DOEPCTL(ep_num) = DXEPCTL_MPS(USB_MAX_PACKET_SIZE) | - DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK; + DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK; GR_USB_DIEPCTL(ep_num) = DXEPCTL_MPS(USB_MAX_PACKET_SIZE) | - DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK | - DXEPCTL_TXFNUM(ep_num); - GR_USB_DAINTMSK |= DAINT_INEP(ep_num) | - DAINT_OUTEP(ep_num); + DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK | + DXEPCTL_TXFNUM(ep_num); + GR_USB_DAINTMSK |= DAINT_INEP(ep_num) | DAINT_OUTEP(ep_num); } - /****************************************************************************** * Internal and EP0 functions. */ - static void flush_all_fifos(void) { /* Flush all FIFOs according to Section 2.1.1.2 */ - GR_USB_GRSTCTL = GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH - | GRSTCTL_RXFFLSH; + GR_USB_GRSTCTL = GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH | + GRSTCTL_RXFFLSH; while (GR_USB_GRSTCTL & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH)) ; } @@ -390,7 +382,6 @@ int send_in_packet(uint32_t ep_num) GR_USB_DIEPTSIZ(0) |= DXEPTSIZ_XFERSIZE(len); GR_USB_DIEPDMA(0) = (uint32_t)ep->in_data; - /* We're sending this much. */ ep->in_pending -= len; ep->in_packets -= 1; @@ -400,7 +391,6 @@ int send_in_packet(uint32_t ep_num) return len; } - /* Load the EP0 IN FIFO buffer with some data (zero-length works too). Returns * len, or negative on error. */ @@ -418,7 +408,7 @@ int initialize_in_transfer(const void *source, uint32_t len) #else /* HS OTG port requires an external phy to support HS */ ASSERT(!((usb->phy_type == USB_PHY_INTERNAL) && - (usb->speed == USB_SPEED_HS))); + (usb->speed == USB_SPEED_HS))); ASSERT(usb->irq == STM32_IRQ_OTG_HS); #endif @@ -435,7 +425,7 @@ int initialize_in_transfer(const void *source, uint32_t len) /* We will send as many packets as necessary, including a final * packet of < USB_MAX_PACKET_SIZE (maybe zero length) */ - ep->in_packets = (len + USB_MAX_PACKET_SIZE)/USB_MAX_PACKET_SIZE; + ep->in_packets = (len + USB_MAX_PACKET_SIZE) / USB_MAX_PACKET_SIZE; ep->in_pending = len; send_in_packet(0); @@ -495,8 +485,8 @@ static void expect_data_phase_in(enum table_case tc) /* Send the reply (data phase in) */ if (tc == TABLE_CASE_SETUP) - GR_USB_DIEPCTL(0) |= DXEPCTL_USBACTEP | - DXEPCTL_CNAK | DXEPCTL_EPENA; + GR_USB_DIEPCTL(0) |= DXEPCTL_USBACTEP | DXEPCTL_CNAK | + DXEPCTL_EPENA; else GR_USB_DIEPCTL(0) |= DXEPCTL_EPENA; @@ -508,7 +498,6 @@ static void expect_data_phase_in(enum table_case tc) /* Get an interrupt when either IN or OUT arrives */ GR_USB_DAINTMSK |= (DAINT_OUTEP(0) | DAINT_INEP(0)); - } static void expect_data_phase_out(enum table_case tc) @@ -524,12 +513,12 @@ static void expect_status_phase_in(enum table_case tc) what_am_i_doing = NO_DATA_STAGE; /* Expect a zero-length IN for the Status phase */ - (void) initialize_in_transfer(0, 0); + (void)initialize_in_transfer(0, 0); /* Blindly following instructions here, too. */ if (tc == TABLE_CASE_SETUP) - GR_USB_DIEPCTL(0) |= DXEPCTL_USBACTEP - | DXEPCTL_CNAK | DXEPCTL_EPENA; + GR_USB_DIEPCTL(0) |= DXEPCTL_USBACTEP | DXEPCTL_CNAK | + DXEPCTL_EPENA; else GR_USB_DIEPCTL(0) |= DXEPCTL_EPENA; @@ -549,7 +538,7 @@ static int handle_setup_with_in_stage(enum table_case tc, const void *data = 0; uint32_t len = 0; int ugly_hack = 0; - static const uint16_t zero; /* == 0 */ + static const uint16_t zero; /* == 0 */ switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: { @@ -564,7 +553,7 @@ static int handle_setup_with_in_stage(enum table_case tc, case USB_DT_CONFIGURATION: data = __usb_desc; len = USB_DESC_SIZE; - ugly_hack = 1; /* see below */ + ugly_hack = 1; /* see below */ break; #ifdef CONFIG_USB_BOS case USB_DT_BOS: @@ -657,7 +646,7 @@ static int handle_setup_with_in_stage(enum table_case tc, /* Handle a Setup that comes with additional data for us. */ static int handle_setup_with_out_stage(enum table_case tc, - struct usb_setup_packet *req) + struct usb_setup_packet *req) { /* TODO: We don't support any of these. We should. */ report_error(-1); @@ -720,7 +709,7 @@ static int handle_setup_with_no_data_stage(enum table_case tc, configuration_value = req->wValue; device_state = DS_ADDRESS; break; - case 1: /* Caution: Only one config descriptor TODAY */ + case 1: /* Caution: Only one config descriptor TODAY */ /* TODO: All endpoints set to DATA0 toggle state */ configuration_value = req->wValue; device_state = DS_CONFIGURED; @@ -756,7 +745,7 @@ static void handle_setup(enum table_case tc) (struct usb_setup_packet *)ep->out_databuffer; int data_phase_in = req->bmRequestType & USB_DIR_IN; int data_phase_out = !data_phase_in && req->wLength; - int bytes = -1; /* default is to stall */ + int bytes = -1; /* default is to stall */ if (0 == (req->bmRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))) { /* Standard Device requests */ @@ -900,20 +889,20 @@ static void ep0_interrupt(uint32_t intr_on_out, uint32_t intr_on_in) * We support up to 3 control EPs, no periodic IN EPs, up to 16 TX EPs. Max * data packet size is 64 bytes. Total SPRAM available is 1024 slots. */ -#define MAX_CONTROL_EPS 3 -#define MAX_NORMAL_EPS 16 -#define FIFO_RAM_DEPTH 1024 +#define MAX_CONTROL_EPS 3 +#define MAX_NORMAL_EPS 16 +#define FIFO_RAM_DEPTH 1024 /* * Device RX FIFO size is thus: * (4 * 3 + 6) + 2 * ((64 / 4) + 1) + (2 * 16) + 1 == 85 */ -#define RXFIFO_SIZE ((4 * MAX_CONTROL_EPS + 6) + \ - 2 * ((USB_MAX_PACKET_SIZE / 4) + 1) + \ - (2 * MAX_NORMAL_EPS) + 1) +#define RXFIFO_SIZE \ + ((4 * MAX_CONTROL_EPS + 6) + 2 * ((USB_MAX_PACKET_SIZE / 4) + 1) + \ + (2 * MAX_NORMAL_EPS) + 1) /* * Device TX FIFO size is 2 * (64 / 4) == 32 for each IN EP (Page 46). */ -#define TXFIFO_SIZE (2 * (USB_MAX_PACKET_SIZE / 4)) +#define TXFIFO_SIZE (2 * (USB_MAX_PACKET_SIZE / 4)) /* * We need 4 slots per endpoint direction for endpoint status stuff (Table 2-1, * unconfigurable). @@ -925,20 +914,19 @@ static void ep0_interrupt(uint32_t intr_on_out, uint32_t intr_on_in) BUILD_ASSERT(RXFIFO_SIZE + TXFIFO_SIZE * MAX_NORMAL_EPS + EP_STATUS_SIZE < FIFO_RAM_DEPTH); - /* Now put those constants into the correct registers */ static void setup_data_fifos(void) { int i; /* Programmer's Guide, p31 */ - GR_USB_GRXFSIZ = RXFIFO_SIZE; /* RXFIFO */ + GR_USB_GRXFSIZ = RXFIFO_SIZE; /* RXFIFO */ GR_USB_GNPTXFSIZ = (TXFIFO_SIZE << 16) | RXFIFO_SIZE; /* TXFIFO 0 */ /* TXFIFO 1..15 */ for (i = 1; i < MAX_NORMAL_EPS; i++) - GR_USB_DIEPTXF(i) = ((TXFIFO_SIZE << 16) | - (RXFIFO_SIZE + i * TXFIFO_SIZE)); + GR_USB_DIEPTXF(i) = + ((TXFIFO_SIZE << 16) | (RXFIFO_SIZE + i * TXFIFO_SIZE)); /* * TODO: The Programmer's Guide is confusing about when or whether to @@ -953,10 +941,10 @@ static void setup_data_fifos(void) */ /* Flush all FIFOs according to Section 2.1.1.2 */ - GR_USB_GRSTCTL = GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH - | GRSTCTL_RXFFLSH; + GR_USB_GRSTCTL = GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH | + GRSTCTL_RXFFLSH; while (GR_USB_GRSTCTL & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH)) - ; /* TODO: timeout 100ms */ + ; /* TODO: timeout 100ms */ } static void usb_init_endpoints(void) @@ -998,8 +986,7 @@ static void usb_enumdone(void) GR_USB_DCTL |= DCTL_CGOUTNAK; } - -void usb_interrupt(void) +static void usb_interrupt(void) { uint32_t status = GR_USB_GINTSTS & GR_USB_GINTMSK; uint32_t oepint = status & GINTSTS(OEPINT); @@ -1027,10 +1014,10 @@ void usb_interrupt(void) * let it know which direction(s) had an interrupt. */ if (daint & (DAINT_OUTEP(0) | DAINT_INEP(0))) { - uint32_t intr_on_out = (oepint && - (daint & DAINT_OUTEP(0))); - uint32_t intr_on_in = (iepint && - (daint & DAINT_INEP(0))); + uint32_t intr_on_out = + (oepint && (daint & DAINT_OUTEP(0))); + uint32_t intr_on_in = + (iepint && (daint & DAINT_INEP(0))); ep0_interrupt(intr_on_out, intr_on_in); } @@ -1103,8 +1090,8 @@ void usb_reset_init_phy(void) if (usb->phy_type == USB_PHY_ULPI) { GR_USB_GCCFG &= ~GCCFG_PWRDWN; - GR_USB_GUSBCFG &= ~(GUSBCFG_TSDPS | - GUSBCFG_ULPIFSLS | GUSBCFG_PHYSEL); + GR_USB_GUSBCFG &= + ~(GUSBCFG_TSDPS | GUSBCFG_ULPIFSLS | GUSBCFG_PHYSEL); GR_USB_GUSBCFG &= ~(GUSBCFG_ULPIEVBUSD | GUSBCFG_ULPIEVBUSI); /* No suspend */ GR_USB_GUSBCFG |= GUSBCFG_ULPICSM | GUSBCFG_ULPIAR; @@ -1168,11 +1155,11 @@ void usb_init(void) * GR_USB_DCFG = (GR_USB_DCFG & ~GC_USB_DCFG_DEVSPD_MASK) * | DCFG_DEVSPD_HSULPI; */ - GR_USB_DCFG = (GR_USB_DCFG & ~GC_USB_DCFG_DEVSPD_MASK) - | DCFG_DEVSPD_FSULPI; + GR_USB_DCFG = (GR_USB_DCFG & ~GC_USB_DCFG_DEVSPD_MASK) | + DCFG_DEVSPD_FSULPI; } else { - GR_USB_DCFG = (GR_USB_DCFG & ~GC_USB_DCFG_DEVSPD_MASK) - | DCFG_DEVSPD_FS48; + GR_USB_DCFG = (GR_USB_DCFG & ~GC_USB_DCFG_DEVSPD_MASK) | + DCFG_DEVSPD_FS48; } GR_USB_DCFG |= DCFG_NZLSOHSK; @@ -1190,10 +1177,11 @@ void usb_init(void) GR_USB_GAHBCFG |= GAHBCFG_TXFELVL | GAHBCFG_PTXFELVL; /* Device only, no SRP */ - GR_USB_GUSBCFG |= GUSBCFG_FDMOD - | GUSBCFG_TOUTCAL(7) - /* FIXME: Magic number! 14 is for 15MHz! Use 9 for 30MHz */ - | GUSBCFG_USBTRDTIM(14); + GR_USB_GUSBCFG |= GUSBCFG_FDMOD | + GUSBCFG_TOUTCAL(7) + /* FIXME: Magic number! 14 is for 15MHz! Use 9 for + 30MHz */ + | GUSBCFG_USBTRDTIM(14); /* Be in disconnected state until we are ready */ usb_disconnect(); @@ -1225,15 +1213,15 @@ void usb_init(void) if (usb->dma_en) { GR_USB_DTHRCTL = DTHRCTL_TXTHRLEN_6 | DTHRCTL_RXTHRLEN_6; - GR_USB_DTHRCTL |= DTHRCTL_RXTHREN | DTHRCTL_ISOTHREN - | DTHRCTL_NONISOTHREN; + GR_USB_DTHRCTL |= DTHRCTL_RXTHREN | DTHRCTL_ISOTHREN | + DTHRCTL_NONISOTHREN; i = GR_USB_DTHRCTL; } GR_USB_GINTSTS = 0xFFFFFFFF; - GR_USB_GAHBCFG |= GAHBCFG_GLB_INTR_EN | GAHBCFG_TXFELVL - | GAHBCFG_PTXFELVL; + GR_USB_GAHBCFG |= GAHBCFG_GLB_INTR_EN | GAHBCFG_TXFELVL | + GAHBCFG_PTXFELVL; if (!(usb->dma_en)) GR_USB_GINTMSK |= GINTMSK(RXFLVL); @@ -1241,7 +1229,7 @@ void usb_init(void) /* Unmask some endpoint interrupt causes */ GR_USB_DIEPMSK = DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK; GR_USB_DOEPMSK = DOEPMSK_EPDISBLDMSK | DOEPMSK_XFERCOMPLMSK | - DOEPMSK_SETUPMSK; + DOEPMSK_SETUPMSK; /* Enable interrupt handlers */ task_enable_irq(usb->irq); @@ -1253,7 +1241,7 @@ void usb_init(void) /* Initialization events */ GINTMSK(USBRST) | GINTMSK(ENUMDONE) | /* Reset detected while suspended. Need to wake up. */ - GINTMSK(RESETDET) | /* TODO: Do we need this? */ + GINTMSK(RESETDET) | /* TODO: Do we need this? */ /* Idle, Suspend detected. Should go to sleep. */ GINTMSK(ERLYSUSP) | GINTMSK(USBSUSP); @@ -1314,7 +1302,7 @@ static void usb_info(void) } } -static int command_usb(int argc, char **argv) +static int command_usb(int argc, const char **argv) { if (argc > 1) { if (!strcasecmp("on", argv[1])) @@ -1328,8 +1316,7 @@ static int command_usb(int argc, char **argv) return EC_ERROR_PARAM1; } -DECLARE_CONSOLE_COMMAND(usb, command_usb, - "[on|off|info]", +DECLARE_CONSOLE_COMMAND(usb, command_usb, "[on|off|info]", "Get/set the USB connection state and PHY selection"); #ifdef CONFIG_USB_SERIALNO @@ -1391,7 +1378,7 @@ static int usb_save_serial(const char *serialno) return rv; } -static int command_serialno(int argc, char **argv) +static int command_serialno(int argc, const char **argv) { struct usb_string_desc *sd = usb_serialno_desc; char buf[CONFIG_SERIALNO_LEN]; @@ -1399,12 +1386,10 @@ static int command_serialno(int argc, char **argv) int i; if (argc != 1) { - if ((strcasecmp(argv[1], "set") == 0) && - (argc == 3)) { + if ((strcasecmp(argv[1], "set") == 0) && (argc == 3)) { ccprintf("Saving serial number\n"); rv = usb_save_serial(argv[2]); - } else if ((strcasecmp(argv[1], "load") == 0) && - (argc == 2)) { + } else if ((strcasecmp(argv[1], "load") == 0) && (argc == 2)) { ccprintf("Loading serial number\n"); rv = usb_load_serial(); } else @@ -1417,7 +1402,6 @@ static int command_serialno(int argc, char **argv) return rv; } -DECLARE_CONSOLE_COMMAND(serialno, command_serialno, - "load/set [value]", - "Read and write USB serial number"); -#endif /* CONFIG_USB_SERIALNO */ +DECLARE_CONSOLE_COMMAND(serialno, command_serialno, "load/set [value]", + "Read and write USB serial number"); +#endif /* CONFIG_USB_SERIALNO */ diff --git a/chip/stm32/usb_dwc_console.c b/chip/stm32/usb_dwc_console.c index 0d1340fb83..ff3c0817b6 100644 --- a/chip/stm32/usb_dwc_console.c +++ b/chip/stm32/usb_dwc_console.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,12 +12,12 @@ #include "registers.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_descriptor.h" #include "usb_hw.h" +#include "util.h" /* Console output macro */ -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) #define USB_CONSOLE_TIMEOUT_US (30 * MSEC) static int last_tx_ok = 1; @@ -28,31 +28,31 @@ static int is_readonly; /* USB-Serial descriptors */ const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_CONSOLE) = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = USB_IFACE_CONSOLE, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_SERIAL, - .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_SERIAL, - .iInterface = USB_STR_CONSOLE_NAME, + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = USB_IFACE_CONSOLE, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_SERIAL, + .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_SERIAL, + .iInterface = USB_STR_CONSOLE_NAME, }; const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_CONSOLE, 0) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x80 | USB_EP_CONSOLE, - .bmAttributes = 0x02 /* Bulk IN */, - .wMaxPacketSize = USB_MAX_PACKET_SIZE, - .bInterval = 10, + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x80 | USB_EP_CONSOLE, + .bmAttributes = 0x02 /* Bulk IN */, + .wMaxPacketSize = USB_MAX_PACKET_SIZE, + .bInterval = 10, }; const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_CONSOLE, 1) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_EP_CONSOLE, - .bmAttributes = 0x02 /* Bulk OUT */, - .wMaxPacketSize = USB_MAX_PACKET_SIZE, - .bInterval = 0 + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_EP_CONSOLE, + .bmAttributes = 0x02 /* Bulk OUT */, + .wMaxPacketSize = USB_MAX_PACKET_SIZE, + .bInterval = 0 }; static uint8_t ep_buf_tx[USB_MAX_PACKET_SIZE]; @@ -61,7 +61,6 @@ static uint8_t ep_buf_rx[USB_MAX_PACKET_SIZE]; static struct queue const tx_q = QUEUE_NULL(256, uint8_t); static struct queue const rx_q = QUEUE_NULL(USB_MAX_PACKET_SIZE, uint8_t); - struct dwc_usb_ep ep_console_ctl = { .max_packet = USB_MAX_PACKET_SIZE, .tx_fifo = USB_EP_CONSOLE, @@ -76,8 +75,6 @@ struct dwc_usb_ep ep_console_ctl = { .in_databuffer_max = sizeof(ep_buf_rx), }; - - /* Let the USB HW IN-to-host FIFO transmit some bytes */ static void usb_enable_tx(int len) { @@ -162,9 +159,8 @@ static void con_ep_rx(void) /* Bytes received decrement DOEPTSIZ XFERSIZE */ if (GR_USB_DOEPINT(USB_EP_CONSOLE) & DOEPINT_XFERCOMPL) { ep->out_pending = - ep->max_packet - - (GR_USB_DOEPTSIZ(USB_EP_CONSOLE) & - GC_USB_DOEPTSIZ1_XFERSIZE_MASK); + ep->max_packet - (GR_USB_DOEPTSIZ(USB_EP_CONSOLE) & + GC_USB_DOEPTSIZ1_XFERSIZE_MASK); } /* Wake up the Rx FIFO handler */ @@ -193,8 +189,8 @@ static void tx_fifo_handler(void) if (!tx_fifo_is_ready()) return; - count = QUEUE_REMOVE_UNITS(&tx_q, - ep->in_databuffer, USB_MAX_PACKET_SIZE); + count = QUEUE_REMOVE_UNITS(&tx_q, ep->in_databuffer, + USB_MAX_PACKET_SIZE); if (count) usb_enable_tx(count); } @@ -232,7 +228,6 @@ static void ep_event(enum usb_ep_event evt) usb_enable_rx(USB_MAX_PACKET_SIZE); } - USB_DECLARE_EP(USB_EP_CONSOLE, con_ep_tx, con_ep_rx, ep_event); static int usb_wait_console(void) @@ -274,8 +269,7 @@ static int usb_wait_console(void) } static int __tx_char(void *context, int c) { - struct queue *state = - (struct queue *) context; + struct queue *state = (struct queue *)context; if (c == '\n' && __tx_char(state, '\r')) return 1; @@ -308,7 +302,7 @@ int usb_puts(const char *outstr) if (is_readonly) return EC_SUCCESS; - ret = usb_wait_console(); + ret = usb_wait_console(); if (ret) return ret; diff --git a/chip/stm32/usb_dwc_console.h b/chip/stm32/usb_dwc_console.h index ab2206d359..f0a0732c7d 100644 --- a/chip/stm32/usb_dwc_console.h +++ b/chip/stm32/usb_dwc_console.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,4 +10,4 @@ extern struct dwc_usb_ep ep_console_ctl; -#endif /* __CHIP_STM32_USB_DWC_CONSOLE_H */ +#endif /* __CHIP_STM32_USB_DWC_CONSOLE_H */ diff --git a/chip/stm32/usb_dwc_hw.h b/chip/stm32/usb_dwc_hw.h index d1fe07cb87..ea87869257 100644 --- a/chip/stm32/usb_dwc_hw.h +++ b/chip/stm32/usb_dwc_hw.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,29 +18,27 @@ #define _EP_RX_HANDLER_TYPECHECK(num) _EP_HANDLER2(num, _rx_typecheck) #define _EP_EVENT_HANDLER_TYPECHECK(num) _EP_HANDLER2(num, _evt_typecheck) -#define USB_DECLARE_EP(num, tx_handler, rx_handler, evt_handler) \ - void _EP_TX_HANDLER(num)(void) \ - __attribute__ ((alias(STRINGIFY(tx_handler)))); \ - void _EP_RX_HANDLER(num)(void) \ - __attribute__ ((alias(STRINGIFY(rx_handler)))); \ - void _EP_EVENT_HANDLER(num)(enum usb_ep_event evt) \ - __attribute__ ((alias(STRINGIFY(evt_handler)))); \ - static __unused void \ - (*_EP_TX_HANDLER_TYPECHECK(num))(void) = tx_handler; \ - static __unused void \ - (*_EP_RX_HANDLER_TYPECHECK(num))(void) = rx_handler; \ - static __unused void \ - (*_EP_EVENT_HANDLER_TYPECHECK(num))(enum usb_ep_event evt)\ - = evt_handler +#define USB_DECLARE_EP(num, tx_handler, rx_handler, evt_handler) \ + void _EP_TX_HANDLER(num)(void) \ + __attribute__((alias(STRINGIFY(tx_handler)))); \ + void _EP_RX_HANDLER(num)(void) \ + __attribute__((alias(STRINGIFY(rx_handler)))); \ + void _EP_EVENT_HANDLER(num)(enum usb_ep_event evt) \ + __attribute__((alias(STRINGIFY(evt_handler)))); \ + static __unused void (*_EP_TX_HANDLER_TYPECHECK(num))(void) = \ + tx_handler; \ + static __unused void (*_EP_RX_HANDLER_TYPECHECK(num))(void) = \ + rx_handler; \ + static __unused void (*_EP_EVENT_HANDLER_TYPECHECK(num))( \ + enum usb_ep_event evt) = evt_handler /* Endpoint callbacks */ -extern void (*usb_ep_tx[]) (void); -extern void (*usb_ep_rx[]) (void); -extern void (*usb_ep_event[]) (enum usb_ep_event evt); +extern void (*usb_ep_tx[])(void); +extern void (*usb_ep_rx[])(void); +extern void (*usb_ep_event[])(enum usb_ep_event evt); struct usb_setup_packet; /* EP0 Interface handler callbacks */ -extern int (*usb_iface_request[]) (struct usb_setup_packet *req); - +extern int (*usb_iface_request[])(struct usb_setup_packet *req); /* True if the HW Rx/OUT FIFO is currently listening. */ int rx_ep_is_active(uint32_t ep_num); @@ -99,8 +97,8 @@ void epN_reset(uint32_t ep_num); * (and thus indicate error to the host). */ #define _IFACE_HANDLER(num) CONCAT3(iface_, num, _request) -#define USB_DECLARE_IFACE(num, handler) \ - int _IFACE_HANDLER(num)(struct usb_setup_packet *req) \ - __attribute__ ((alias(STRINGIFY(handler)))) +#define USB_DECLARE_IFACE(num, handler) \ + int _IFACE_HANDLER(num)(struct usb_setup_packet * req) \ + __attribute__((alias(STRINGIFY(handler)))) -#endif /* __CROS_EC_USB_DWC_HW_H */ +#endif /* __CROS_EC_USB_DWC_HW_H */ diff --git a/chip/stm32/usb_dwc_i2c.h b/chip/stm32/usb_dwc_i2c.h index e44002268a..6e6c72e22c 100644 --- a/chip/stm32/usb_dwc_i2c.h +++ b/chip/stm32/usb_dwc_i2c.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/stm32/usb_dwc_registers.h b/chip/stm32/usb_dwc_registers.h index faac9ca775..b5ada2ce65 100644 --- a/chip/stm32/usb_dwc_registers.h +++ b/chip/stm32/usb_dwc_registers.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -55,7479 +55,7467 @@ extern struct dwc_usb usb_ctl; * Added Alias Module Family Base Address to 0-instance Module Base Address * Simplify GBASE(mname) macro */ -#define GC_MODULE_OFFSET 0x10000 +#define GC_MODULE_OFFSET 0x10000 -#define GBASE(mname) \ - GC_ ## mname ## _BASE_ADDR -#define GOFFSET(mname, rname) \ - GC_ ## mname ## _ ## rname ## _OFFSET +#define GBASE(mname) GC_##mname##_BASE_ADDR +#define GOFFSET(mname, rname) GC_##mname##_##rname##_OFFSET -#define GREG8(mname, rname) \ - REG8(GBASE(mname) + GOFFSET(mname, rname)) -#define GREG32(mname, rname) \ - REG32(GBASE(mname) + GOFFSET(mname, rname)) +#define GREG8(mname, rname) REG8(GBASE(mname) + GOFFSET(mname, rname)) +#define GREG32(mname, rname) REG32(GBASE(mname) + GOFFSET(mname, rname)) #define GREG32_ADDR(mname, rname) \ REG32_ADDR(GBASE(mname) + GOFFSET(mname, rname)) #define GWRITE(mname, rname, value) (GREG32(mname, rname) = (value)) -#define GREAD(mname, rname) GREG32(mname, rname) +#define GREAD(mname, rname) GREG32(mname, rname) -#define GFIELD_MASK(mname, rname, fname) \ - GC_ ## mname ## _ ## rname ## _ ## fname ## _MASK +#define GFIELD_MASK(mname, rname, fname) GC_##mname##_##rname##_##fname##_MASK -#define GFIELD_LSB(mname, rname, fname) \ - GC_ ## mname ## _ ## rname ## _ ## fname ## _LSB +#define GFIELD_LSB(mname, rname, fname) GC_##mname##_##rname##_##fname##_LSB -#define GREAD_FIELD(mname, rname, fname) \ - ((GREG32(mname, rname) & GFIELD_MASK(mname, rname, fname)) \ - >> GFIELD_LSB(mname, rname, fname)) +#define GREAD_FIELD(mname, rname, fname) \ + ((GREG32(mname, rname) & GFIELD_MASK(mname, rname, fname)) >> \ + GFIELD_LSB(mname, rname, fname)) -#define GWRITE_FIELD(mname, rname, fname, fval) \ - (GREG32(mname, rname) = \ - ((GREG32(mname, rname) & (~GFIELD_MASK(mname, rname, fname))) | \ - (((fval) << GFIELD_LSB(mname, rname, fname)) & \ - GFIELD_MASK(mname, rname, fname)))) +#define GWRITE_FIELD(mname, rname, fname, fval) \ + (GREG32(mname, rname) = \ + ((GREG32(mname, rname) & \ + (~GFIELD_MASK(mname, rname, fname))) | \ + (((fval) << GFIELD_LSB(mname, rname, fname)) & \ + GFIELD_MASK(mname, rname, fname)))) - -#define GBASE_I(mname, i) (GBASE(mname) + i*GC_MODULE_OFFSET) +#define GBASE_I(mname, i) (GBASE(mname) + i * GC_MODULE_OFFSET) #define GREG32_I(mname, i, rname) \ - REG32(GBASE_I(mname, i) + GOFFSET(mname, rname)) + REG32(GBASE_I(mname, i) + GOFFSET(mname, rname)) #define GREG32_ADDR_I(mname, i, rname) \ - REG32_ADDR(GBASE_I(mname, i) + GOFFSET(mname, rname)) + REG32_ADDR(GBASE_I(mname, i) + GOFFSET(mname, rname)) #define GWRITE_I(mname, i, rname, value) (GREG32_I(mname, i, rname) = (value)) -#define GREAD_I(mname, i, rname) GREG32_I(mname, i, rname) +#define GREAD_I(mname, i, rname) GREG32_I(mname, i, rname) -#define GREAD_FIELD_I(mname, i, rname, fname) \ - ((GREG32_I(mname, i, rname) & GFIELD_MASK(mname, rname, fname)) \ - >> GFIELD_LSB(mname, rname, fname)) +#define GREAD_FIELD_I(mname, i, rname, fname) \ + ((GREG32_I(mname, i, rname) & GFIELD_MASK(mname, rname, fname)) >> \ + GFIELD_LSB(mname, rname, fname)) -#define GWRITE_FIELD_I(mname, i, rname, fname, fval) \ - (GREG32_I(mname, i, rname) = \ - ((GREG32_I(mname, i, rname) & (~GFIELD_MASK(mname, rname, fname))) | \ - (((fval) << GFIELD_LSB(mname, rname, fname)) & \ - GFIELD_MASK(mname, rname, fname)))) +#define GWRITE_FIELD_I(mname, i, rname, fname, fval) \ + (GREG32_I(mname, i, rname) = \ + ((GREG32_I(mname, i, rname) & \ + (~GFIELD_MASK(mname, rname, fname))) | \ + (((fval) << GFIELD_LSB(mname, rname, fname)) & \ + GFIELD_MASK(mname, rname, fname)))) /* Replace masked bits with val << lsb */ #define REG_WRITE_MLV(reg, mask, lsb, val) \ - (reg = ((reg & ~mask) | ((val << lsb) & mask))) - + (reg = ((reg & ~mask) | ((val << lsb) & mask))) /* USB device controller */ -#define GR_USB_REG(off) REG32(GC_USB_BASE_ADDR + (off)) -#define GR_USB_GOTGCTL GR_USB_REG(GC_USB_GOTGCTL_OFFSET) -#define GR_USB_GOTGINT GR_USB_REG(GC_USB_GOTGINT_OFFSET) -#define GR_USB_GAHBCFG GR_USB_REG(GC_USB_GAHBCFG_OFFSET) -#define GR_USB_GUSBCFG GR_USB_REG(GC_USB_GUSBCFG_OFFSET) -#define GR_USB_GRSTCTL GR_USB_REG(GC_USB_GRSTCTL_OFFSET) -#define GR_USB_GINTSTS GR_USB_REG(GC_USB_GINTSTS_OFFSET) -#define GINTSTS(bit) (1 << GC_USB_GINTSTS_ ## bit ## _LSB) -#define GR_USB_GINTMSK GR_USB_REG(GC_USB_GINTMSK_OFFSET) -#define GINTMSK(bit) (1 << GC_USB_GINTMSK_ ## bit ## MSK_LSB) -#define GR_USB_GRXSTSR GR_USB_REG(GC_USB_GRXSTSR_OFFSET) -#define GR_USB_GRXSTSP GR_USB_REG(GC_USB_GRXSTSP_OFFSET) -#define GR_USB_GRXFSIZ GR_USB_REG(GC_USB_GRXFSIZ_OFFSET) -#define GR_USB_GNPTXFSIZ GR_USB_REG(GC_USB_GNPTXFSIZ_OFFSET) +#define GR_USB_REG(off) REG32(GC_USB_BASE_ADDR + (off)) +#define GR_USB_GOTGCTL GR_USB_REG(GC_USB_GOTGCTL_OFFSET) +#define GR_USB_GOTGINT GR_USB_REG(GC_USB_GOTGINT_OFFSET) +#define GR_USB_GAHBCFG GR_USB_REG(GC_USB_GAHBCFG_OFFSET) +#define GR_USB_GUSBCFG GR_USB_REG(GC_USB_GUSBCFG_OFFSET) +#define GR_USB_GRSTCTL GR_USB_REG(GC_USB_GRSTCTL_OFFSET) +#define GR_USB_GINTSTS GR_USB_REG(GC_USB_GINTSTS_OFFSET) +#define GINTSTS(bit) (1 << GC_USB_GINTSTS_##bit##_LSB) +#define GR_USB_GINTMSK GR_USB_REG(GC_USB_GINTMSK_OFFSET) +#define GINTMSK(bit) (1 << GC_USB_GINTMSK_##bit##MSK_LSB) +#define GR_USB_GRXSTSR GR_USB_REG(GC_USB_GRXSTSR_OFFSET) +#define GR_USB_GRXSTSP GR_USB_REG(GC_USB_GRXSTSP_OFFSET) +#define GR_USB_GRXFSIZ GR_USB_REG(GC_USB_GRXFSIZ_OFFSET) +#define GR_USB_GNPTXFSIZ GR_USB_REG(GC_USB_GNPTXFSIZ_OFFSET) /*#define GR_USB_GGPIO GR_USB_REG(GC_USB_GGPIO_OFFSET)*/ -#define GR_USB_GCCFG GR_USB_REG(GC_USB_GCCFG_OFFSET) -#define GCCFG_VBDEN BIT(21) -#define GCCFG_PWRDWN BIT(16) -#define GR_USB_PCGCCTL GR_USB_REG(GC_USB_PCGCCTL_OFFSET) +#define GR_USB_GCCFG GR_USB_REG(GC_USB_GCCFG_OFFSET) +#define GCCFG_VBDEN BIT(21) +#define GCCFG_PWRDWN BIT(16) +#define GR_USB_PCGCCTL GR_USB_REG(GC_USB_PCGCCTL_OFFSET) -#define GR_USB_GSNPSID GR_USB_REG(GC_USB_GSNPSID_OFFSET) -#define GR_USB_GHWCFG1 GR_USB_REG(GC_USB_GHWCFG1_OFFSET) -#define GR_USB_GHWCFG2 GR_USB_REG(GC_USB_GHWCFG2_OFFSET) -#define GR_USB_GHWCFG3 GR_USB_REG(GC_USB_GHWCFG3_OFFSET) -#define GR_USB_GHWCFG4 GR_USB_REG(GC_USB_GHWCFG4_OFFSET) -#define GR_USB_GDFIFOCFG GR_USB_REG(GC_USB_GDFIFOCFG_OFFSET) -#define GR_USB_DIEPTXF(n) \ - GR_USB_REG(GC_USB_DIEPTXF1_OFFSET - 4 + (n)*4) -#define GR_USB_DCFG GR_USB_REG(GC_USB_DCFG_OFFSET) -#define GR_USB_DCTL GR_USB_REG(GC_USB_DCTL_OFFSET) -#define GR_USB_DSTS GR_USB_REG(GC_USB_DSTS_OFFSET) -#define GR_USB_DIEPMSK GR_USB_REG(GC_USB_DIEPMSK_OFFSET) -#define GR_USB_DOEPMSK GR_USB_REG(GC_USB_DOEPMSK_OFFSET) -#define GR_USB_DAINT GR_USB_REG(GC_USB_DAINT_OFFSET) -#define GR_USB_DAINTMSK GR_USB_REG(GC_USB_DAINTMSK_OFFSET) -#define DAINT_INEP(ep) (1 << (ep + GC_USB_DAINTMSK_INEPMSK0_LSB)) -#define DAINT_OUTEP(ep) \ - (1 << (ep + GC_USB_DAINTMSK_OUTEPMSK0_LSB)) -#define GR_USB_DTHRCTL GR_USB_REG(GC_USB_DTHRCTL_OFFSET) -#define DTHRCTL_TXTHRLEN_6 (0x40 << 2) -#define DTHRCTL_RXTHRLEN_6 (0x40 << 17) -#define DTHRCTL_RXTHREN BIT(16) -#define DTHRCTL_ISOTHREN BIT(1) -#define DTHRCTL_NONISOTHREN BIT(0) -#define GR_USB_DIEPEMPMSK GR_USB_REG(GC_USB_DIEPEMPMSK_OFFSET) +#define GR_USB_GSNPSID GR_USB_REG(GC_USB_GSNPSID_OFFSET) +#define GR_USB_GHWCFG1 GR_USB_REG(GC_USB_GHWCFG1_OFFSET) +#define GR_USB_GHWCFG2 GR_USB_REG(GC_USB_GHWCFG2_OFFSET) +#define GR_USB_GHWCFG3 GR_USB_REG(GC_USB_GHWCFG3_OFFSET) +#define GR_USB_GHWCFG4 GR_USB_REG(GC_USB_GHWCFG4_OFFSET) +#define GR_USB_GDFIFOCFG GR_USB_REG(GC_USB_GDFIFOCFG_OFFSET) +#define GR_USB_DIEPTXF(n) GR_USB_REG(GC_USB_DIEPTXF1_OFFSET - 4 + (n)*4) +#define GR_USB_DCFG GR_USB_REG(GC_USB_DCFG_OFFSET) +#define GR_USB_DCTL GR_USB_REG(GC_USB_DCTL_OFFSET) +#define GR_USB_DSTS GR_USB_REG(GC_USB_DSTS_OFFSET) +#define GR_USB_DIEPMSK GR_USB_REG(GC_USB_DIEPMSK_OFFSET) +#define GR_USB_DOEPMSK GR_USB_REG(GC_USB_DOEPMSK_OFFSET) +#define GR_USB_DAINT GR_USB_REG(GC_USB_DAINT_OFFSET) +#define GR_USB_DAINTMSK GR_USB_REG(GC_USB_DAINTMSK_OFFSET) +#define DAINT_INEP(ep) (1 << (ep + GC_USB_DAINTMSK_INEPMSK0_LSB)) +#define DAINT_OUTEP(ep) (1 << (ep + GC_USB_DAINTMSK_OUTEPMSK0_LSB)) +#define GR_USB_DTHRCTL GR_USB_REG(GC_USB_DTHRCTL_OFFSET) +#define DTHRCTL_TXTHRLEN_6 (0x40 << 2) +#define DTHRCTL_RXTHRLEN_6 (0x40 << 17) +#define DTHRCTL_RXTHREN BIT(16) +#define DTHRCTL_ISOTHREN BIT(1) +#define DTHRCTL_NONISOTHREN BIT(0) +#define GR_USB_DIEPEMPMSK GR_USB_REG(GC_USB_DIEPEMPMSK_OFFSET) -#define GR_USB_EPIREG(off, n) GR_USB_REG(0x900 + (n) * 0x20 + (off)) -#define GR_USB_EPOREG(off, n) GR_USB_REG(0xb00 + (n) * 0x20 + (off)) -#define GR_USB_DIEPCTL(n) GR_USB_EPIREG(0x00, n) -#define GR_USB_DIEPINT(n) GR_USB_EPIREG(0x08, n) -#define GR_USB_DIEPTSIZ(n) GR_USB_EPIREG(0x10, n) -#define GR_USB_DIEPDMA(n) GR_USB_EPIREG(0x14, n) -#define GR_USB_DTXFSTS(n) GR_USB_EPIREG(0x18, n) -#define GR_USB_DIEPDMAB(n) GR_USB_EPIREG(0x1c, n) -#define GR_USB_DOEPCTL(n) GR_USB_EPOREG(0x00, n) -#define GR_USB_DOEPINT(n) GR_USB_EPOREG(0x08, n) -#define GR_USB_DOEPTSIZ(n) GR_USB_EPOREG(0x10, n) -#define GR_USB_DOEPDMA(n) GR_USB_EPOREG(0x14, n) -#define GR_USB_DOEPDMAB(n) GR_USB_EPOREG(0x1c, n) +#define GR_USB_EPIREG(off, n) GR_USB_REG(0x900 + (n)*0x20 + (off)) +#define GR_USB_EPOREG(off, n) GR_USB_REG(0xb00 + (n)*0x20 + (off)) +#define GR_USB_DIEPCTL(n) GR_USB_EPIREG(0x00, n) +#define GR_USB_DIEPINT(n) GR_USB_EPIREG(0x08, n) +#define GR_USB_DIEPTSIZ(n) GR_USB_EPIREG(0x10, n) +#define GR_USB_DIEPDMA(n) GR_USB_EPIREG(0x14, n) +#define GR_USB_DTXFSTS(n) GR_USB_EPIREG(0x18, n) +#define GR_USB_DIEPDMAB(n) GR_USB_EPIREG(0x1c, n) +#define GR_USB_DOEPCTL(n) GR_USB_EPOREG(0x00, n) +#define GR_USB_DOEPINT(n) GR_USB_EPOREG(0x08, n) +#define GR_USB_DOEPTSIZ(n) GR_USB_EPOREG(0x10, n) +#define GR_USB_DOEPDMA(n) GR_USB_EPOREG(0x14, n) +#define GR_USB_DOEPDMAB(n) GR_USB_EPOREG(0x1c, n) -#define GOTGCTL_BVALOEN BIT(GC_USB_GOTGCTL_BVALIDOVEN_LSB) -#define GOTGCTL_BVALOVAL BIT(7) +#define GOTGCTL_BVALOEN BIT(GC_USB_GOTGCTL_BVALIDOVEN_LSB) +#define GOTGCTL_BVALOVAL BIT(7) /* Bit 5 */ -#define GAHBCFG_DMA_EN BIT(GC_USB_GAHBCFG_DMAEN_LSB) +#define GAHBCFG_DMA_EN BIT(GC_USB_GAHBCFG_DMAEN_LSB) /* Bit 1 */ -#define GAHBCFG_GLB_INTR_EN BIT(GC_USB_GAHBCFG_GLBLINTRMSK_LSB) +#define GAHBCFG_GLB_INTR_EN BIT(GC_USB_GAHBCFG_GLBLINTRMSK_LSB) /* HS Burst Len */ -#define GAHBCFG_HBSTLEN_INCR4 (3 << GC_USB_GAHBCFG_HBSTLEN_LSB) +#define GAHBCFG_HBSTLEN_INCR4 (3 << GC_USB_GAHBCFG_HBSTLEN_LSB) /* Bit 7 */ -#define GAHBCFG_NP_TXF_EMP_LVL (1 << GC_USB_GAHBCFG_NPTXFEMPLVL_LSB) -#define GAHBCFG_TXFELVL GAHBCFG_NP_TXF_EMP_LVL -#define GAHBCFG_PTXFELVL BIT(8) +#define GAHBCFG_NP_TXF_EMP_LVL (1 << GC_USB_GAHBCFG_NPTXFEMPLVL_LSB) +#define GAHBCFG_TXFELVL GAHBCFG_NP_TXF_EMP_LVL +#define GAHBCFG_PTXFELVL BIT(8) -#define GUSBCFG_TOUTCAL(n) (((n) << GC_USB_GUSBCFG_TOUTCAL_LSB) \ - & GC_USB_GUSBCFG_TOUTCAL_MASK) -#define GUSBCFG_USBTRDTIM(n) (((n) << GC_USB_GUSBCFG_USBTRDTIM_LSB) \ - & GC_USB_GUSBCFG_USBTRDTIM_MASK) +#define GUSBCFG_TOUTCAL(n) \ + (((n) << GC_USB_GUSBCFG_TOUTCAL_LSB) & GC_USB_GUSBCFG_TOUTCAL_MASK) +#define GUSBCFG_USBTRDTIM(n) \ + (((n) << GC_USB_GUSBCFG_USBTRDTIM_LSB) & GC_USB_GUSBCFG_USBTRDTIM_MASK) /* Force device mode */ -#define GUSBCFG_FDMOD BIT(GC_USB_GUSBCFG_FDMOD_LSB) -#define GUSBCFG_PHYSEL BIT(6) -#define GUSBCFG_SRPCAP BIT(8) -#define GUSBCFG_HNPCAP BIT(9) -#define GUSBCFG_ULPIFSLS BIT(17) -#define GUSBCFG_ULPIAR BIT(18) -#define GUSBCFG_ULPICSM BIT(19) -#define GUSBCFG_ULPIEVBUSD BIT(20) -#define GUSBCFG_ULPIEVBUSI BIT(21) -#define GUSBCFG_TSDPS BIT(22) -#define GUSBCFG_PCCI BIT(23) -#define GUSBCFG_PTCI BIT(24) -#define GUSBCFG_ULPIIPD BIT(25) -#define GUSBCFG_TSDPS BIT(22) - +#define GUSBCFG_FDMOD BIT(GC_USB_GUSBCFG_FDMOD_LSB) +#define GUSBCFG_PHYSEL BIT(6) +#define GUSBCFG_SRPCAP BIT(8) +#define GUSBCFG_HNPCAP BIT(9) +#define GUSBCFG_ULPIFSLS BIT(17) +#define GUSBCFG_ULPIAR BIT(18) +#define GUSBCFG_ULPICSM BIT(19) +#define GUSBCFG_ULPIEVBUSD BIT(20) +#define GUSBCFG_ULPIEVBUSI BIT(21) +#define GUSBCFG_TSDPS BIT(22) +#define GUSBCFG_PCCI BIT(23) +#define GUSBCFG_PTCI BIT(24) +#define GUSBCFG_ULPIIPD BIT(25) +#define GUSBCFG_TSDPS BIT(22) -#define GRSTCTL_CSFTRST BIT(GC_USB_GRSTCTL_CSFTRST_LSB) -#define GRSTCTL_AHBIDLE BIT(GC_USB_GRSTCTL_AHBIDLE_LSB) -#define GRSTCTL_TXFFLSH BIT(GC_USB_GRSTCTL_TXFFLSH_LSB) -#define GRSTCTL_RXFFLSH BIT(GC_USB_GRSTCTL_RXFFLSH_LSB) -#define GRSTCTL_TXFNUM(n) \ +#define GRSTCTL_CSFTRST BIT(GC_USB_GRSTCTL_CSFTRST_LSB) +#define GRSTCTL_AHBIDLE BIT(GC_USB_GRSTCTL_AHBIDLE_LSB) +#define GRSTCTL_TXFFLSH BIT(GC_USB_GRSTCTL_TXFFLSH_LSB) +#define GRSTCTL_RXFFLSH BIT(GC_USB_GRSTCTL_RXFFLSH_LSB) +#define GRSTCTL_TXFNUM(n) \ (((n) << GC_USB_GRSTCTL_TXFNUM_LSB) & GC_USB_GRSTCTL_TXFNUM_MASK) -#define DCFG_DEVSPD_HSULPI (0 << GC_USB_DCFG_DEVSPD_LSB) -#define DCFG_DEVSPD_FSULPI BIT(GC_USB_DCFG_DEVSPD_LSB) -#define DCFG_DEVSPD_FS48 (3 << GC_USB_DCFG_DEVSPD_LSB) -#define DCFG_DEVADDR(a) \ +#define DCFG_DEVSPD_HSULPI (0 << GC_USB_DCFG_DEVSPD_LSB) +#define DCFG_DEVSPD_FSULPI BIT(GC_USB_DCFG_DEVSPD_LSB) +#define DCFG_DEVSPD_FS48 (3 << GC_USB_DCFG_DEVSPD_LSB) +#define DCFG_DEVADDR(a) \ (((a) << GC_USB_DCFG_DEVADDR_LSB) & GC_USB_DCFG_DEVADDR_MASK) -#define DCFG_NZLSOHSK BIT(GC_USB_DCFG_NZSTSOUTHSHK_LSB) +#define DCFG_NZLSOHSK BIT(GC_USB_DCFG_NZSTSOUTHSHK_LSB) -#define DCTL_SFTDISCON BIT(GC_USB_DCTL_SFTDISCON_LSB) -#define DCTL_CGOUTNAK BIT(GC_USB_DCTL_CGOUTNAK_LSB) -#define DCTL_CGNPINNAK BIT(GC_USB_DCTL_CGNPINNAK_LSB) -#define DCTL_PWRONPRGDONE BIT(GC_USB_DCTL_PWRONPRGDONE_LSB) +#define DCTL_SFTDISCON BIT(GC_USB_DCTL_SFTDISCON_LSB) +#define DCTL_CGOUTNAK BIT(GC_USB_DCTL_CGOUTNAK_LSB) +#define DCTL_CGNPINNAK BIT(GC_USB_DCTL_CGNPINNAK_LSB) +#define DCTL_PWRONPRGDONE BIT(GC_USB_DCTL_PWRONPRGDONE_LSB) /* Device Endpoint Common IN Interrupt Mask bits */ -#define DIEPMSK_AHBERRMSK BIT(GC_USB_DIEPMSK_AHBERRMSK_LSB) -#define DIEPMSK_BNAININTRMSK BIT(GC_USB_DIEPMSK_BNAININTRMSK_LSB) -#define DIEPMSK_EPDISBLDMSK BIT(GC_USB_DIEPMSK_EPDISBLDMSK_LSB) -#define DIEPMSK_INEPNAKEFFMSK BIT(GC_USB_DIEPMSK_INEPNAKEFFMSK_LSB) -#define DIEPMSK_INTKNEPMISMSK BIT(GC_USB_DIEPMSK_INTKNEPMISMSK_LSB) -#define DIEPMSK_INTKNTXFEMPMSK BIT(GC_USB_DIEPMSK_INTKNTXFEMPMSK_LSB) -#define DIEPMSK_NAKMSK BIT(GC_USB_DIEPMSK_NAKMSK_LSB) -#define DIEPMSK_TIMEOUTMSK BIT(GC_USB_DIEPMSK_TIMEOUTMSK_LSB) -#define DIEPMSK_TXFIFOUNDRNMSK BIT(GC_USB_DIEPMSK_TXFIFOUNDRNMSK_LSB) -#define DIEPMSK_XFERCOMPLMSK BIT(GC_USB_DIEPMSK_XFERCOMPLMSK_LSB) +#define DIEPMSK_AHBERRMSK BIT(GC_USB_DIEPMSK_AHBERRMSK_LSB) +#define DIEPMSK_BNAININTRMSK BIT(GC_USB_DIEPMSK_BNAININTRMSK_LSB) +#define DIEPMSK_EPDISBLDMSK BIT(GC_USB_DIEPMSK_EPDISBLDMSK_LSB) +#define DIEPMSK_INEPNAKEFFMSK BIT(GC_USB_DIEPMSK_INEPNAKEFFMSK_LSB) +#define DIEPMSK_INTKNEPMISMSK BIT(GC_USB_DIEPMSK_INTKNEPMISMSK_LSB) +#define DIEPMSK_INTKNTXFEMPMSK BIT(GC_USB_DIEPMSK_INTKNTXFEMPMSK_LSB) +#define DIEPMSK_NAKMSK BIT(GC_USB_DIEPMSK_NAKMSK_LSB) +#define DIEPMSK_TIMEOUTMSK BIT(GC_USB_DIEPMSK_TIMEOUTMSK_LSB) +#define DIEPMSK_TXFIFOUNDRNMSK BIT(GC_USB_DIEPMSK_TXFIFOUNDRNMSK_LSB) +#define DIEPMSK_XFERCOMPLMSK BIT(GC_USB_DIEPMSK_XFERCOMPLMSK_LSB) /* Device Endpoint Common OUT Interrupt Mask bits */ -#define DOEPMSK_AHBERRMSK BIT(GC_USB_DOEPMSK_AHBERRMSK_LSB) -#define DOEPMSK_BBLEERRMSK BIT(GC_USB_DOEPMSK_BBLEERRMSK_LSB) -#define DOEPMSK_BNAOUTINTRMSK BIT(GC_USB_DOEPMSK_BNAOUTINTRMSK_LSB) -#define DOEPMSK_EPDISBLDMSK BIT(GC_USB_DOEPMSK_EPDISBLDMSK_LSB) -#define DOEPMSK_NAKMSK BIT(GC_USB_DOEPMSK_NAKMSK_LSB) -#define DOEPMSK_NYETMSK BIT(GC_USB_DOEPMSK_NYETMSK_LSB) -#define DOEPMSK_OUTPKTERRMSK BIT(GC_USB_DOEPMSK_OUTPKTERRMSK_LSB) -#define DOEPMSK_OUTTKNEPDISMSK BIT(GC_USB_DOEPMSK_OUTTKNEPDISMSK_LSB) -#define DOEPMSK_SETUPMSK BIT(GC_USB_DOEPMSK_SETUPMSK_LSB) -#define DOEPMSK_STSPHSERCVDMSK BIT(GC_USB_DOEPMSK_STSPHSERCVDMSK_LSB) -#define DOEPMSK_XFERCOMPLMSK BIT(GC_USB_DOEPMSK_XFERCOMPLMSK_LSB) +#define DOEPMSK_AHBERRMSK BIT(GC_USB_DOEPMSK_AHBERRMSK_LSB) +#define DOEPMSK_BBLEERRMSK BIT(GC_USB_DOEPMSK_BBLEERRMSK_LSB) +#define DOEPMSK_BNAOUTINTRMSK BIT(GC_USB_DOEPMSK_BNAOUTINTRMSK_LSB) +#define DOEPMSK_EPDISBLDMSK BIT(GC_USB_DOEPMSK_EPDISBLDMSK_LSB) +#define DOEPMSK_NAKMSK BIT(GC_USB_DOEPMSK_NAKMSK_LSB) +#define DOEPMSK_NYETMSK BIT(GC_USB_DOEPMSK_NYETMSK_LSB) +#define DOEPMSK_OUTPKTERRMSK BIT(GC_USB_DOEPMSK_OUTPKTERRMSK_LSB) +#define DOEPMSK_OUTTKNEPDISMSK BIT(GC_USB_DOEPMSK_OUTTKNEPDISMSK_LSB) +#define DOEPMSK_SETUPMSK BIT(GC_USB_DOEPMSK_SETUPMSK_LSB) +#define DOEPMSK_STSPHSERCVDMSK BIT(GC_USB_DOEPMSK_STSPHSERCVDMSK_LSB) +#define DOEPMSK_XFERCOMPLMSK BIT(GC_USB_DOEPMSK_XFERCOMPLMSK_LSB) /* Device Endpoint-n IN Interrupt Register bits */ -#define DIEPINT_AHBERR BIT(GC_USB_DIEPINT0_AHBERR_LSB) -#define DIEPINT_BBLEERR BIT(GC_USB_DIEPINT0_BBLEERR_LSB) -#define DIEPINT_BNAINTR BIT(GC_USB_DIEPINT0_BNAINTR_LSB) -#define DIEPINT_EPDISBLD BIT(GC_USB_DIEPINT0_EPDISBLD_LSB) -#define DIEPINT_INEPNAKEFF BIT(GC_USB_DIEPINT0_INEPNAKEFF_LSB) -#define DIEPINT_INTKNEPMIS BIT(GC_USB_DIEPINT0_INTKNEPMIS_LSB) -#define DIEPINT_INTKNTXFEMP BIT(GC_USB_DIEPINT0_INTKNTXFEMP_LSB) -#define DIEPINT_NAKINTRPT BIT(GC_USB_DIEPINT0_NAKINTRPT_LSB) -#define DIEPINT_NYETINTRPT BIT(GC_USB_DIEPINT0_NYETINTRPT_LSB) -#define DIEPINT_PKTDRPSTS BIT(GC_USB_DIEPINT0_PKTDRPSTS_LSB) -#define DIEPINT_TIMEOUT BIT(GC_USB_DIEPINT0_TIMEOUT_LSB) -#define DIEPINT_TXFEMP BIT(GC_USB_DIEPINT0_TXFEMP_LSB) -#define DIEPINT_TXFIFOUNDRN BIT(GC_USB_DIEPINT0_TXFIFOUNDRN_LSB) -#define DIEPINT_XFERCOMPL BIT(GC_USB_DIEPINT0_XFERCOMPL_LSB) +#define DIEPINT_AHBERR BIT(GC_USB_DIEPINT0_AHBERR_LSB) +#define DIEPINT_BBLEERR BIT(GC_USB_DIEPINT0_BBLEERR_LSB) +#define DIEPINT_BNAINTR BIT(GC_USB_DIEPINT0_BNAINTR_LSB) +#define DIEPINT_EPDISBLD BIT(GC_USB_DIEPINT0_EPDISBLD_LSB) +#define DIEPINT_INEPNAKEFF BIT(GC_USB_DIEPINT0_INEPNAKEFF_LSB) +#define DIEPINT_INTKNEPMIS BIT(GC_USB_DIEPINT0_INTKNEPMIS_LSB) +#define DIEPINT_INTKNTXFEMP BIT(GC_USB_DIEPINT0_INTKNTXFEMP_LSB) +#define DIEPINT_NAKINTRPT BIT(GC_USB_DIEPINT0_NAKINTRPT_LSB) +#define DIEPINT_NYETINTRPT BIT(GC_USB_DIEPINT0_NYETINTRPT_LSB) +#define DIEPINT_PKTDRPSTS BIT(GC_USB_DIEPINT0_PKTDRPSTS_LSB) +#define DIEPINT_TIMEOUT BIT(GC_USB_DIEPINT0_TIMEOUT_LSB) +#define DIEPINT_TXFEMP BIT(GC_USB_DIEPINT0_TXFEMP_LSB) +#define DIEPINT_TXFIFOUNDRN BIT(GC_USB_DIEPINT0_TXFIFOUNDRN_LSB) +#define DIEPINT_XFERCOMPL BIT(GC_USB_DIEPINT0_XFERCOMPL_LSB) /* Device Endpoint-n OUT Interrupt Register bits */ -#define DOEPINT_AHBERR BIT(GC_USB_DOEPINT0_AHBERR_LSB) -#define DOEPINT_BACK2BACKSETUP BIT(GC_USB_DOEPINT0_BACK2BACKSETUP_LSB) -#define DOEPINT_BBLEERR BIT(GC_USB_DOEPINT0_BBLEERR_LSB) -#define DOEPINT_BNAINTR BIT(GC_USB_DOEPINT0_BNAINTR_LSB) -#define DOEPINT_EPDISBLD BIT(GC_USB_DOEPINT0_EPDISBLD_LSB) -#define DOEPINT_NAKINTRPT BIT(GC_USB_DOEPINT0_NAKINTRPT_LSB) -#define DOEPINT_NYETINTRPT BIT(GC_USB_DOEPINT0_NYETINTRPT_LSB) -#define DOEPINT_OUTPKTERR BIT(GC_USB_DOEPINT0_OUTPKTERR_LSB) -#define DOEPINT_OUTTKNEPDIS BIT(GC_USB_DOEPINT0_OUTTKNEPDIS_LSB) -#define DOEPINT_PKTDRPSTS BIT(GC_USB_DOEPINT0_PKTDRPSTS_LSB) -#define DOEPINT_SETUP BIT(GC_USB_DOEPINT0_SETUP_LSB) -#define DOEPINT_STSPHSERCVD BIT(GC_USB_DOEPINT0_STSPHSERCVD_LSB) -#define DOEPINT_STUPPKTRCVD BIT(GC_USB_DOEPINT0_STUPPKTRCVD_LSB) -#define DOEPINT_XFERCOMPL BIT(GC_USB_DOEPINT0_XFERCOMPL_LSB) +#define DOEPINT_AHBERR BIT(GC_USB_DOEPINT0_AHBERR_LSB) +#define DOEPINT_BACK2BACKSETUP BIT(GC_USB_DOEPINT0_BACK2BACKSETUP_LSB) +#define DOEPINT_BBLEERR BIT(GC_USB_DOEPINT0_BBLEERR_LSB) +#define DOEPINT_BNAINTR BIT(GC_USB_DOEPINT0_BNAINTR_LSB) +#define DOEPINT_EPDISBLD BIT(GC_USB_DOEPINT0_EPDISBLD_LSB) +#define DOEPINT_NAKINTRPT BIT(GC_USB_DOEPINT0_NAKINTRPT_LSB) +#define DOEPINT_NYETINTRPT BIT(GC_USB_DOEPINT0_NYETINTRPT_LSB) +#define DOEPINT_OUTPKTERR BIT(GC_USB_DOEPINT0_OUTPKTERR_LSB) +#define DOEPINT_OUTTKNEPDIS BIT(GC_USB_DOEPINT0_OUTTKNEPDIS_LSB) +#define DOEPINT_PKTDRPSTS BIT(GC_USB_DOEPINT0_PKTDRPSTS_LSB) +#define DOEPINT_SETUP BIT(GC_USB_DOEPINT0_SETUP_LSB) +#define DOEPINT_STSPHSERCVD BIT(GC_USB_DOEPINT0_STSPHSERCVD_LSB) +#define DOEPINT_STUPPKTRCVD BIT(GC_USB_DOEPINT0_STUPPKTRCVD_LSB) +#define DOEPINT_XFERCOMPL BIT(GC_USB_DOEPINT0_XFERCOMPL_LSB) -#define DXEPCTL_EPTYPE_CTRL (0 << GC_USB_DIEPCTL0_EPTYPE_LSB) -#define DXEPCTL_EPTYPE_ISO (1 << GC_USB_DIEPCTL0_EPTYPE_LSB) -#define DXEPCTL_EPTYPE_BULK (2 << GC_USB_DIEPCTL0_EPTYPE_LSB) -#define DXEPCTL_EPTYPE_INT (3 << GC_USB_DIEPCTL0_EPTYPE_LSB) -#define DXEPCTL_EPTYPE_MASK GC_USB_DIEPCTL0_EPTYPE_MASK -#define DXEPCTL_TXFNUM(n) ((n) << GC_USB_DIEPCTL1_TXFNUM_LSB) -#define DXEPCTL_STALL BIT(GC_USB_DIEPCTL0_STALL_LSB) -#define DXEPCTL_CNAK BIT(GC_USB_DIEPCTL0_CNAK_LSB) -#define DXEPCTL_DPID BIT(GC_USB_DIEPCTL0_DPID_LSB) -#define DXEPCTL_SNAK BIT(GC_USB_DIEPCTL0_SNAK_LSB) -#define DXEPCTL_NAKSTS BIT(GC_USB_DIEPCTL0_NAKSTS_LSB) -#define DXEPCTL_EPENA BIT(GC_USB_DIEPCTL0_EPENA_LSB) -#define DXEPCTL_EPDIS BIT(GC_USB_DIEPCTL0_EPDIS_LSB) -#define DXEPCTL_USBACTEP BIT(GC_USB_DIEPCTL0_USBACTEP_LSB) -#define DXEPCTL_MPS64 (0 << GC_USB_DIEPCTL0_MPS_LSB) -#define DXEPCTL_MPS(cnt) ((cnt) << GC_USB_DIEPCTL1_MPS_LSB) +#define DXEPCTL_EPTYPE_CTRL (0 << GC_USB_DIEPCTL0_EPTYPE_LSB) +#define DXEPCTL_EPTYPE_ISO (1 << GC_USB_DIEPCTL0_EPTYPE_LSB) +#define DXEPCTL_EPTYPE_BULK (2 << GC_USB_DIEPCTL0_EPTYPE_LSB) +#define DXEPCTL_EPTYPE_INT (3 << GC_USB_DIEPCTL0_EPTYPE_LSB) +#define DXEPCTL_EPTYPE_MASK GC_USB_DIEPCTL0_EPTYPE_MASK +#define DXEPCTL_TXFNUM(n) ((n) << GC_USB_DIEPCTL1_TXFNUM_LSB) +#define DXEPCTL_STALL BIT(GC_USB_DIEPCTL0_STALL_LSB) +#define DXEPCTL_CNAK BIT(GC_USB_DIEPCTL0_CNAK_LSB) +#define DXEPCTL_DPID BIT(GC_USB_DIEPCTL0_DPID_LSB) +#define DXEPCTL_SNAK BIT(GC_USB_DIEPCTL0_SNAK_LSB) +#define DXEPCTL_NAKSTS BIT(GC_USB_DIEPCTL0_NAKSTS_LSB) +#define DXEPCTL_EPENA BIT(GC_USB_DIEPCTL0_EPENA_LSB) +#define DXEPCTL_EPDIS BIT(GC_USB_DIEPCTL0_EPDIS_LSB) +#define DXEPCTL_USBACTEP BIT(GC_USB_DIEPCTL0_USBACTEP_LSB) +#define DXEPCTL_MPS64 (0 << GC_USB_DIEPCTL0_MPS_LSB) +#define DXEPCTL_MPS(cnt) ((cnt) << GC_USB_DIEPCTL1_MPS_LSB) -#define DXEPTSIZ_SUPCNT(n) ((n) << GC_USB_DOEPTSIZ0_SUPCNT_LSB) -#define DXEPTSIZ_PKTCNT(n) ((n) << GC_USB_DIEPTSIZ0_PKTCNT_LSB) -#define DXEPTSIZ_XFERSIZE(n) ((n) << GC_USB_DIEPTSIZ0_XFERSIZE_LSB) - -#define DOEPDMA_BS_HOST_RDY (0 << 30) -#define DOEPDMA_BS_DMA_BSY (1 << 30) -#define DOEPDMA_BS_DMA_DONE (2 << 30) -#define DOEPDMA_BS_HOST_BSY (3 << 30) -#define DOEPDMA_BS_MASK (3 << 30) -#define DOEPDMA_RXSTS_MASK (3 << 28) -#define DOEPDMA_LAST BIT(27) -#define DOEPDMA_SP BIT(26) -#define DOEPDMA_IOC BIT(25) -#define DOEPDMA_SR BIT(24) -#define DOEPDMA_MTRF BIT(23) -#define DOEPDMA_NAK BIT(16) -#define DOEPDMA_RXBYTES(n) (((n) & 0xFFFF) << 0) -#define DOEPDMA_RXBYTES_MASK (0xFFFF << 0) - -#define DIEPDMA_BS_HOST_RDY (0 << 30) -#define DIEPDMA_BS_DMA_BSY (1 << 30) -#define DIEPDMA_BS_DMA_DONE (2 << 30) -#define DIEPDMA_BS_HOST_BSY (3 << 30) -#define DIEPDMA_BS_MASK (3 << 30) -#define DIEPDMA_TXSTS_MASK (3 << 28) -#define DIEPDMA_LAST BIT(27) -#define DIEPDMA_SP BIT(26) -#define DIEPDMA_IOC BIT(25) -#define DIEPDMA_TXBYTES(n) (((n) & 0xFFFF) << 0) -#define DIEPDMA_TXBYTES_MASK (0xFFFF << 0) +#define DXEPTSIZ_SUPCNT(n) ((n) << GC_USB_DOEPTSIZ0_SUPCNT_LSB) +#define DXEPTSIZ_PKTCNT(n) ((n) << GC_USB_DIEPTSIZ0_PKTCNT_LSB) +#define DXEPTSIZ_XFERSIZE(n) ((n) << GC_USB_DIEPTSIZ0_XFERSIZE_LSB) +#define DOEPDMA_BS_HOST_RDY (0 << 30) +#define DOEPDMA_BS_DMA_BSY (1 << 30) +#define DOEPDMA_BS_DMA_DONE (2 << 30) +#define DOEPDMA_BS_HOST_BSY (3 << 30) +#define DOEPDMA_BS_MASK (3 << 30) +#define DOEPDMA_RXSTS_MASK (3 << 28) +#define DOEPDMA_LAST BIT(27) +#define DOEPDMA_SP BIT(26) +#define DOEPDMA_IOC BIT(25) +#define DOEPDMA_SR BIT(24) +#define DOEPDMA_MTRF BIT(23) +#define DOEPDMA_NAK BIT(16) +#define DOEPDMA_RXBYTES(n) (((n)&0xFFFF) << 0) +#define DOEPDMA_RXBYTES_MASK (0xFFFF << 0) +#define DIEPDMA_BS_HOST_RDY (0 << 30) +#define DIEPDMA_BS_DMA_BSY (1 << 30) +#define DIEPDMA_BS_DMA_DONE (2 << 30) +#define DIEPDMA_BS_HOST_BSY (3 << 30) +#define DIEPDMA_BS_MASK (3 << 30) +#define DIEPDMA_TXSTS_MASK (3 << 28) +#define DIEPDMA_LAST BIT(27) +#define DIEPDMA_SP BIT(26) +#define DIEPDMA_IOC BIT(25) +#define DIEPDMA_TXBYTES(n) (((n)&0xFFFF) << 0) +#define DIEPDMA_TXBYTES_MASK (0xFFFF << 0) /* Register defs referenced from DWC block in CR50. This is not a native * ST block, so we'll use this modified regdefs list. */ -#define GC_USB_FS_BASE_ADDR 0x50000000 -#define GC_USB_HS_BASE_ADDR 0x40040000 +#define GC_USB_FS_BASE_ADDR 0x50000000 +#define GC_USB_HS_BASE_ADDR 0x40040000 #ifdef CONFIG_USB_DWC_FS -#define GC_USB_BASE_ADDR GC_USB_FS_BASE_ADDR +#define GC_USB_BASE_ADDR GC_USB_FS_BASE_ADDR #else -#define GC_USB_BASE_ADDR GC_USB_HS_BASE_ADDR +#define GC_USB_BASE_ADDR GC_USB_HS_BASE_ADDR #endif -#define GC_USB_GOTGCTL_OFFSET 0x0 -#define GC_USB_GOTGCTL_DEFAULT 0x0 -#define GC_USB_GOTGINT_OFFSET 0x4 -#define GC_USB_GOTGINT_DEFAULT 0x0 -#define GC_USB_GAHBCFG_OFFSET 0x8 -#define GC_USB_GAHBCFG_DEFAULT 0x0 -#define GC_USB_GUSBCFG_OFFSET 0xc -#define GC_USB_GUSBCFG_DEFAULT 0x0 -#define GC_USB_GRSTCTL_OFFSET 0x10 -#define GC_USB_GRSTCTL_DEFAULT 0x0 -#define GC_USB_GINTSTS_OFFSET 0x14 -#define GC_USB_GINTSTS_DEFAULT 0x0 -#define GC_USB_GINTMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_DEFAULT 0x0 -#define GC_USB_GRXSTSR_OFFSET 0x1c -#define GC_USB_GRXSTSR_DEFAULT 0x0 -#define GC_USB_GRXSTSP_OFFSET 0x20 -#define GC_USB_GRXSTSP_DEFAULT 0x0 -#define GC_USB_GRXFSIZ_OFFSET 0x24 -#define GC_USB_GRXFSIZ_DEFAULT 0x0 -#define GC_USB_GNPTXFSIZ_OFFSET 0x28 -#define GC_USB_GNPTXFSIZ_DEFAULT 0x0 +#define GC_USB_GOTGCTL_OFFSET 0x0 +#define GC_USB_GOTGCTL_DEFAULT 0x0 +#define GC_USB_GOTGINT_OFFSET 0x4 +#define GC_USB_GOTGINT_DEFAULT 0x0 +#define GC_USB_GAHBCFG_OFFSET 0x8 +#define GC_USB_GAHBCFG_DEFAULT 0x0 +#define GC_USB_GUSBCFG_OFFSET 0xc +#define GC_USB_GUSBCFG_DEFAULT 0x0 +#define GC_USB_GRSTCTL_OFFSET 0x10 +#define GC_USB_GRSTCTL_DEFAULT 0x0 +#define GC_USB_GINTSTS_OFFSET 0x14 +#define GC_USB_GINTSTS_DEFAULT 0x0 +#define GC_USB_GINTMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_DEFAULT 0x0 +#define GC_USB_GRXSTSR_OFFSET 0x1c +#define GC_USB_GRXSTSR_DEFAULT 0x0 +#define GC_USB_GRXSTSP_OFFSET 0x20 +#define GC_USB_GRXSTSP_DEFAULT 0x0 +#define GC_USB_GRXFSIZ_OFFSET 0x24 +#define GC_USB_GRXFSIZ_DEFAULT 0x0 +#define GC_USB_GNPTXFSIZ_OFFSET 0x28 +#define GC_USB_GNPTXFSIZ_DEFAULT 0x0 -#define GC_USB_GCCFG_OFFSET 0x38 -#define GC_USB_GCCFG_DEFAULT 0x0 -#define GC_USB_GUID_OFFSET 0x3c -#define GC_USB_GUID_DEFAULT 0x0 -#define GC_USB_GSNPSID_OFFSET 0x40 -#define GC_USB_GSNPSID_DEFAULT 0x0 -#define GC_USB_GHWCFG1_OFFSET 0x44 -#define GC_USB_GHWCFG1_DEFAULT 0x0 -#define GC_USB_GHWCFG2_OFFSET 0x48 -#define GC_USB_GHWCFG2_DEFAULT 0x0 -#define GC_USB_GHWCFG3_OFFSET 0x4c -#define GC_USB_GHWCFG3_DEFAULT 0x0 -#define GC_USB_GHWCFG4_OFFSET 0x50 -#define GC_USB_GHWCFG4_DEFAULT 0x0 -#define GC_USB_GDFIFOCFG_OFFSET 0x5c -#define GC_USB_GDFIFOCFG_DEFAULT 0x0 -#define GC_USB_DIEPTXF1_OFFSET 0x104 -#define GC_USB_DIEPTXF1_DEFAULT 0x1000 -#define GC_USB_DIEPTXF2_OFFSET 0x108 -#define GC_USB_DIEPTXF2_DEFAULT 0x0 -#define GC_USB_DIEPTXF3_OFFSET 0x10c -#define GC_USB_DIEPTXF3_DEFAULT 0x0 -#define GC_USB_DIEPTXF4_OFFSET 0x110 -#define GC_USB_DIEPTXF4_DEFAULT 0x0 -#define GC_USB_DIEPTXF5_OFFSET 0x114 -#define GC_USB_DIEPTXF5_DEFAULT 0x0 -#define GC_USB_DIEPTXF6_OFFSET 0x118 -#define GC_USB_DIEPTXF6_DEFAULT 0x0 -#define GC_USB_DIEPTXF7_OFFSET 0x11c -#define GC_USB_DIEPTXF7_DEFAULT 0x0 -#define GC_USB_DIEPTXF8_OFFSET 0x120 -#define GC_USB_DIEPTXF8_DEFAULT 0x0 -#define GC_USB_DIEPTXF9_OFFSET 0x124 -#define GC_USB_DIEPTXF9_DEFAULT 0x0 -#define GC_USB_DIEPTXF10_OFFSET 0x128 -#define GC_USB_DIEPTXF10_DEFAULT 0x0 -#define GC_USB_DIEPTXF11_OFFSET 0x12c -#define GC_USB_DIEPTXF11_DEFAULT 0x0 -#define GC_USB_DIEPTXF12_OFFSET 0x130 -#define GC_USB_DIEPTXF12_DEFAULT 0x0 -#define GC_USB_DIEPTXF13_OFFSET 0x134 -#define GC_USB_DIEPTXF13_DEFAULT 0x0 -#define GC_USB_DIEPTXF14_OFFSET 0x138 -#define GC_USB_DIEPTXF14_DEFAULT 0x0 -#define GC_USB_DIEPTXF15_OFFSET 0x13c -#define GC_USB_DIEPTXF15_DEFAULT 0x0 -#define GC_USB_DCFG_OFFSET 0x800 -#define GC_USB_DCFG_DEFAULT 0x8000000 -#define GC_USB_DCTL_OFFSET 0x804 -#define GC_USB_DCTL_DEFAULT 0x0 -#define GC_USB_DSTS_OFFSET 0x808 -#define GC_USB_DSTS_DEFAULT 0x0 -#define GC_USB_DIEPMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_DEFAULT 0x80 -#define GC_USB_DOEPMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_DEFAULT 0x0 -#define GC_USB_DAINT_OFFSET 0x818 -#define GC_USB_DAINT_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OFFSET 0x81c -#define GC_USB_DAINTMSK_DEFAULT 0x0 -#define GC_USB_DVBUSDIS_OFFSET 0x828 -#define GC_USB_DVBUSDIS_DEFAULT 0x0 -#define GC_USB_DVBUSPULSE_OFFSET 0x82c -#define GC_USB_DVBUSPULSE_DEFAULT 0x0 -#define GC_USB_DTHRCTL_OFFSET 0x830 -#define GC_USB_DTHRCTL_DEFAULT 0x0 -#define GC_USB_DIEPEMPMSK_OFFSET 0x834 -#define GC_USB_DIEPEMPMSK_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_OFFSET 0x900 -#define GC_USB_DIEPCTL0_DEFAULT 0x0 -#define GC_USB_DIEPINT0_OFFSET 0x908 -#define GC_USB_DIEPINT0_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ0_OFFSET 0x910 -#define GC_USB_DIEPTSIZ0_DEFAULT 0x0 -#define GC_USB_DIEPDMA0_OFFSET 0x914 -#define GC_USB_DIEPDMA0_DEFAULT 0x0 -#define GC_USB_DTXFSTS0_OFFSET 0x918 -#define GC_USB_DTXFSTS0_DEFAULT 0x0 -#define GC_USB_DIEPDMAB0_OFFSET 0x91c -#define GC_USB_DIEPDMAB0_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_OFFSET 0x920 -#define GC_USB_DIEPCTL1_DEFAULT 0x0 -#define GC_USB_DIEPINT1_OFFSET 0x928 -#define GC_USB_DIEPINT1_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ1_OFFSET 0x930 -#define GC_USB_DIEPTSIZ1_DEFAULT 0x0 -#define GC_USB_DIEPDMA1_OFFSET 0x934 -#define GC_USB_DIEPDMA1_DEFAULT 0x0 -#define GC_USB_DTXFSTS1_OFFSET 0x938 -#define GC_USB_DTXFSTS1_DEFAULT 0x0 -#define GC_USB_DIEPDMAB1_OFFSET 0x93c -#define GC_USB_DIEPDMAB1_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_OFFSET 0x940 -#define GC_USB_DIEPCTL2_DEFAULT 0x0 -#define GC_USB_DIEPINT2_OFFSET 0x948 -#define GC_USB_DIEPINT2_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ2_OFFSET 0x950 -#define GC_USB_DIEPTSIZ2_DEFAULT 0x0 -#define GC_USB_DIEPDMA2_OFFSET 0x954 -#define GC_USB_DIEPDMA2_DEFAULT 0x0 -#define GC_USB_DTXFSTS2_OFFSET 0x958 -#define GC_USB_DTXFSTS2_DEFAULT 0x0 -#define GC_USB_DIEPDMAB2_OFFSET 0x95c -#define GC_USB_DIEPDMAB2_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_OFFSET 0x960 -#define GC_USB_DIEPCTL3_DEFAULT 0x0 -#define GC_USB_DIEPINT3_OFFSET 0x968 -#define GC_USB_DIEPINT3_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ3_OFFSET 0x970 -#define GC_USB_DIEPTSIZ3_DEFAULT 0x0 -#define GC_USB_DIEPDMA3_OFFSET 0x974 -#define GC_USB_DIEPDMA3_DEFAULT 0x0 -#define GC_USB_DTXFSTS3_OFFSET 0x978 -#define GC_USB_DTXFSTS3_DEFAULT 0x0 -#define GC_USB_DIEPDMAB3_OFFSET 0x97c -#define GC_USB_DIEPDMAB3_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_OFFSET 0x980 -#define GC_USB_DIEPCTL4_DEFAULT 0x0 -#define GC_USB_DIEPINT4_OFFSET 0x988 -#define GC_USB_DIEPINT4_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ4_OFFSET 0x990 -#define GC_USB_DIEPTSIZ4_DEFAULT 0x0 -#define GC_USB_DIEPDMA4_OFFSET 0x994 -#define GC_USB_DIEPDMA4_DEFAULT 0x0 -#define GC_USB_DTXFSTS4_OFFSET 0x998 -#define GC_USB_DTXFSTS4_DEFAULT 0x0 -#define GC_USB_DIEPDMAB4_OFFSET 0x99c -#define GC_USB_DIEPDMAB4_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_DEFAULT 0x0 -#define GC_USB_DIEPINT5_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ5_OFFSET 0x9b0 -#define GC_USB_DIEPTSIZ5_DEFAULT 0x0 -#define GC_USB_DIEPDMA5_OFFSET 0x9b4 -#define GC_USB_DIEPDMA5_DEFAULT 0x0 -#define GC_USB_DTXFSTS5_OFFSET 0x9b8 -#define GC_USB_DTXFSTS5_DEFAULT 0x0 -#define GC_USB_DIEPDMAB5_OFFSET 0x9bc -#define GC_USB_DIEPDMAB5_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_DEFAULT 0x0 -#define GC_USB_DIEPINT6_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ6_OFFSET 0x9d0 -#define GC_USB_DIEPTSIZ6_DEFAULT 0x0 -#define GC_USB_DIEPDMA6_OFFSET 0x9d4 -#define GC_USB_DIEPDMA6_DEFAULT 0x0 -#define GC_USB_DTXFSTS6_OFFSET 0x9d8 -#define GC_USB_DTXFSTS6_DEFAULT 0x0 -#define GC_USB_DIEPDMAB6_OFFSET 0x9dc -#define GC_USB_DIEPDMAB6_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_DEFAULT 0x0 -#define GC_USB_DIEPINT7_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ7_OFFSET 0x9f0 -#define GC_USB_DIEPTSIZ7_DEFAULT 0x0 -#define GC_USB_DIEPDMA7_OFFSET 0x9f4 -#define GC_USB_DIEPDMA7_DEFAULT 0x0 -#define GC_USB_DTXFSTS7_OFFSET 0x9f8 -#define GC_USB_DTXFSTS7_DEFAULT 0x0 -#define GC_USB_DIEPDMAB7_OFFSET 0x9fc -#define GC_USB_DIEPDMAB7_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_DEFAULT 0x0 -#define GC_USB_DIEPINT8_OFFSET 0xa08 -#define GC_USB_DIEPINT8_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ8_OFFSET 0xa10 -#define GC_USB_DIEPTSIZ8_DEFAULT 0x0 -#define GC_USB_DIEPDMA8_OFFSET 0xa14 -#define GC_USB_DIEPDMA8_DEFAULT 0x0 -#define GC_USB_DTXFSTS8_OFFSET 0xa18 -#define GC_USB_DTXFSTS8_DEFAULT 0x0 -#define GC_USB_DIEPDMAB8_OFFSET 0xa1c -#define GC_USB_DIEPDMAB8_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_DEFAULT 0x0 -#define GC_USB_DIEPINT9_OFFSET 0xa28 -#define GC_USB_DIEPINT9_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ9_OFFSET 0xa30 -#define GC_USB_DIEPTSIZ9_DEFAULT 0x0 -#define GC_USB_DIEPDMA9_OFFSET 0xa34 -#define GC_USB_DIEPDMA9_DEFAULT 0x0 -#define GC_USB_DTXFSTS9_OFFSET 0xa38 -#define GC_USB_DTXFSTS9_DEFAULT 0x0 -#define GC_USB_DIEPDMAB9_OFFSET 0xa3c -#define GC_USB_DIEPDMAB9_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_DEFAULT 0x0 -#define GC_USB_DIEPINT10_OFFSET 0xa48 -#define GC_USB_DIEPINT10_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ10_OFFSET 0xa50 -#define GC_USB_DIEPTSIZ10_DEFAULT 0x0 -#define GC_USB_DIEPDMA10_OFFSET 0xa54 -#define GC_USB_DIEPDMA10_DEFAULT 0x0 -#define GC_USB_DTXFSTS10_OFFSET 0xa58 -#define GC_USB_DTXFSTS10_DEFAULT 0x0 -#define GC_USB_DIEPDMAB10_OFFSET 0xa5c -#define GC_USB_DIEPDMAB10_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_DEFAULT 0x0 -#define GC_USB_DIEPINT11_OFFSET 0xa68 -#define GC_USB_DIEPINT11_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ11_OFFSET 0xa70 -#define GC_USB_DIEPTSIZ11_DEFAULT 0x0 -#define GC_USB_DIEPDMA11_OFFSET 0xa74 -#define GC_USB_DIEPDMA11_DEFAULT 0x0 -#define GC_USB_DTXFSTS11_OFFSET 0xa78 -#define GC_USB_DTXFSTS11_DEFAULT 0x0 -#define GC_USB_DIEPDMAB11_OFFSET 0xa7c -#define GC_USB_DIEPDMAB11_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_DEFAULT 0x0 -#define GC_USB_DIEPINT12_OFFSET 0xa88 -#define GC_USB_DIEPINT12_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ12_OFFSET 0xa90 -#define GC_USB_DIEPTSIZ12_DEFAULT 0x0 -#define GC_USB_DIEPDMA12_OFFSET 0xa94 -#define GC_USB_DIEPDMA12_DEFAULT 0x0 -#define GC_USB_DTXFSTS12_OFFSET 0xa98 -#define GC_USB_DTXFSTS12_DEFAULT 0x0 -#define GC_USB_DIEPDMAB12_OFFSET 0xa9c -#define GC_USB_DIEPDMAB12_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_DEFAULT 0x0 -#define GC_USB_DIEPINT13_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ13_OFFSET 0xab0 -#define GC_USB_DIEPTSIZ13_DEFAULT 0x0 -#define GC_USB_DIEPDMA13_OFFSET 0xab4 -#define GC_USB_DIEPDMA13_DEFAULT 0x0 -#define GC_USB_DTXFSTS13_OFFSET 0xab8 -#define GC_USB_DTXFSTS13_DEFAULT 0x0 -#define GC_USB_DIEPDMAB13_OFFSET 0xabc -#define GC_USB_DIEPDMAB13_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_DEFAULT 0x0 -#define GC_USB_DIEPINT14_OFFSET 0xac8 -#define GC_USB_DIEPINT14_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ14_OFFSET 0xad0 -#define GC_USB_DIEPTSIZ14_DEFAULT 0x0 -#define GC_USB_DIEPDMA14_OFFSET 0xad4 -#define GC_USB_DIEPDMA14_DEFAULT 0x0 -#define GC_USB_DTXFSTS14_OFFSET 0xad8 -#define GC_USB_DTXFSTS14_DEFAULT 0x0 -#define GC_USB_DIEPDMAB14_OFFSET 0xadc -#define GC_USB_DIEPDMAB14_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_DEFAULT 0x0 -#define GC_USB_DIEPINT15_OFFSET 0xae8 -#define GC_USB_DIEPINT15_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ15_OFFSET 0xaf0 -#define GC_USB_DIEPTSIZ15_DEFAULT 0x0 -#define GC_USB_DIEPDMA15_OFFSET 0xaf4 -#define GC_USB_DIEPDMA15_DEFAULT 0x0 -#define GC_USB_DTXFSTS15_OFFSET 0xaf8 -#define GC_USB_DTXFSTS15_DEFAULT 0x0 -#define GC_USB_DIEPDMAB15_OFFSET 0xafc -#define GC_USB_DIEPDMAB15_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_DEFAULT 0x0 -#define GC_USB_DOEPINT0_OFFSET 0xb08 -#define GC_USB_DOEPINT0_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ0_OFFSET 0xb10 -#define GC_USB_DOEPTSIZ0_DEFAULT 0x0 -#define GC_USB_DOEPDMA0_OFFSET 0xb14 -#define GC_USB_DOEPDMA0_DEFAULT 0x0 -#define GC_USB_DOEPDMAB0_OFFSET 0xb1c -#define GC_USB_DOEPDMAB0_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_DEFAULT 0x0 -#define GC_USB_DOEPINT1_OFFSET 0xb28 -#define GC_USB_DOEPINT1_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ1_OFFSET 0xb30 -#define GC_USB_DOEPTSIZ1_DEFAULT 0x0 -#define GC_USB_DOEPDMA1_OFFSET 0xb34 -#define GC_USB_DOEPDMA1_DEFAULT 0x0 -#define GC_USB_DOEPDMAB1_OFFSET 0xb3c -#define GC_USB_DOEPDMAB1_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_DEFAULT 0x0 -#define GC_USB_DOEPINT2_OFFSET 0xb48 -#define GC_USB_DOEPINT2_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ2_OFFSET 0xb50 -#define GC_USB_DOEPTSIZ2_DEFAULT 0x0 -#define GC_USB_DOEPDMA2_OFFSET 0xb54 -#define GC_USB_DOEPDMA2_DEFAULT 0x0 -#define GC_USB_DOEPDMAB2_OFFSET 0xb5c -#define GC_USB_DOEPDMAB2_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_DEFAULT 0x0 -#define GC_USB_DOEPINT3_OFFSET 0xb68 -#define GC_USB_DOEPINT3_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ3_OFFSET 0xb70 -#define GC_USB_DOEPTSIZ3_DEFAULT 0x0 -#define GC_USB_DOEPDMA3_OFFSET 0xb74 -#define GC_USB_DOEPDMA3_DEFAULT 0x0 -#define GC_USB_DOEPDMAB3_OFFSET 0xb7c -#define GC_USB_DOEPDMAB3_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_DEFAULT 0x0 -#define GC_USB_DOEPINT4_OFFSET 0xb88 -#define GC_USB_DOEPINT4_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ4_OFFSET 0xb90 -#define GC_USB_DOEPTSIZ4_DEFAULT 0x0 -#define GC_USB_DOEPDMA4_OFFSET 0xb94 -#define GC_USB_DOEPDMA4_DEFAULT 0x0 -#define GC_USB_DOEPDMAB4_OFFSET 0xb9c -#define GC_USB_DOEPDMAB4_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_DEFAULT 0x0 -#define GC_USB_DOEPINT5_OFFSET 0xba8 -#define GC_USB_DOEPINT5_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ5_OFFSET 0xbb0 -#define GC_USB_DOEPTSIZ5_DEFAULT 0x0 -#define GC_USB_DOEPDMA5_OFFSET 0xbb4 -#define GC_USB_DOEPDMA5_DEFAULT 0x0 -#define GC_USB_DOEPDMAB5_OFFSET 0xbbc -#define GC_USB_DOEPDMAB5_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_DEFAULT 0x0 -#define GC_USB_DOEPINT6_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ6_OFFSET 0xbd0 -#define GC_USB_DOEPTSIZ6_DEFAULT 0x0 -#define GC_USB_DOEPDMA6_OFFSET 0xbd4 -#define GC_USB_DOEPDMA6_DEFAULT 0x0 -#define GC_USB_DOEPDMAB6_OFFSET 0xbdc -#define GC_USB_DOEPDMAB6_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_DEFAULT 0x0 -#define GC_USB_DOEPINT7_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ7_OFFSET 0xbf0 -#define GC_USB_DOEPTSIZ7_DEFAULT 0x0 -#define GC_USB_DOEPDMA7_OFFSET 0xbf4 -#define GC_USB_DOEPDMA7_DEFAULT 0x0 -#define GC_USB_DOEPDMAB7_OFFSET 0xbfc -#define GC_USB_DOEPDMAB7_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_DEFAULT 0x0 -#define GC_USB_DOEPINT8_OFFSET 0xc08 -#define GC_USB_DOEPINT8_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ8_OFFSET 0xc10 -#define GC_USB_DOEPTSIZ8_DEFAULT 0x0 -#define GC_USB_DOEPDMA8_OFFSET 0xc14 -#define GC_USB_DOEPDMA8_DEFAULT 0x0 -#define GC_USB_DOEPDMAB8_OFFSET 0xc1c -#define GC_USB_DOEPDMAB8_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_DEFAULT 0x0 -#define GC_USB_DOEPINT9_OFFSET 0xc28 -#define GC_USB_DOEPINT9_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ9_OFFSET 0xc30 -#define GC_USB_DOEPTSIZ9_DEFAULT 0x0 -#define GC_USB_DOEPDMA9_OFFSET 0xc34 -#define GC_USB_DOEPDMA9_DEFAULT 0x0 -#define GC_USB_DOEPDMAB9_OFFSET 0xc3c -#define GC_USB_DOEPDMAB9_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_DEFAULT 0x0 -#define GC_USB_DOEPINT10_OFFSET 0xc48 -#define GC_USB_DOEPINT10_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ10_OFFSET 0xc50 -#define GC_USB_DOEPTSIZ10_DEFAULT 0x0 -#define GC_USB_DOEPDMA10_OFFSET 0xc54 -#define GC_USB_DOEPDMA10_DEFAULT 0x0 -#define GC_USB_DOEPDMAB10_OFFSET 0xc5c -#define GC_USB_DOEPDMAB10_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_DEFAULT 0x0 -#define GC_USB_DOEPINT11_OFFSET 0xc68 -#define GC_USB_DOEPINT11_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ11_OFFSET 0xc70 -#define GC_USB_DOEPTSIZ11_DEFAULT 0x0 -#define GC_USB_DOEPDMA11_OFFSET 0xc74 -#define GC_USB_DOEPDMA11_DEFAULT 0x0 -#define GC_USB_DOEPDMAB11_OFFSET 0xc7c -#define GC_USB_DOEPDMAB11_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_DEFAULT 0x0 -#define GC_USB_DOEPINT12_OFFSET 0xc88 -#define GC_USB_DOEPINT12_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ12_OFFSET 0xc90 -#define GC_USB_DOEPTSIZ12_DEFAULT 0x0 -#define GC_USB_DOEPDMA12_OFFSET 0xc94 -#define GC_USB_DOEPDMA12_DEFAULT 0x0 -#define GC_USB_DOEPDMAB12_OFFSET 0xc9c -#define GC_USB_DOEPDMAB12_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_DEFAULT 0x0 -#define GC_USB_DOEPINT13_OFFSET 0xca8 -#define GC_USB_DOEPINT13_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ13_OFFSET 0xcb0 -#define GC_USB_DOEPTSIZ13_DEFAULT 0x0 -#define GC_USB_DOEPDMA13_OFFSET 0xcb4 -#define GC_USB_DOEPDMA13_DEFAULT 0x0 -#define GC_USB_DOEPDMAB13_OFFSET 0xcbc -#define GC_USB_DOEPDMAB13_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_DEFAULT 0x0 -#define GC_USB_DOEPINT14_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ14_OFFSET 0xcd0 -#define GC_USB_DOEPTSIZ14_DEFAULT 0x0 -#define GC_USB_DOEPDMA14_OFFSET 0xcd4 -#define GC_USB_DOEPDMA14_DEFAULT 0x0 -#define GC_USB_DOEPDMAB14_OFFSET 0xcdc -#define GC_USB_DOEPDMAB14_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_DEFAULT 0x0 -#define GC_USB_DOEPINT15_OFFSET 0xce8 -#define GC_USB_DOEPINT15_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ15_OFFSET 0xcf0 -#define GC_USB_DOEPTSIZ15_DEFAULT 0x0 -#define GC_USB_DOEPDMA15_OFFSET 0xcf4 -#define GC_USB_DOEPDMA15_DEFAULT 0x0 -#define GC_USB_DOEPDMAB15_OFFSET 0xcfc -#define GC_USB_DOEPDMAB15_DEFAULT 0x0 -#define GC_USB_PCGCCTL_OFFSET 0xe00 -#define GC_USB_PCGCCTL_DEFAULT 0x0 -#define GC_USB_DFIFO_OFFSET 0x20000 -#define GC_USB_GOTGCTL_BVALIDOVEN_LSB 0x6 -#define GC_USB_GOTGCTL_BVALIDOVEN_MASK 0x40 -#define GC_USB_GOTGCTL_BVALIDOVEN_SIZE 0x1 -#define GC_USB_GOTGCTL_BVALIDOVEN_DEFAULT 0x0 -#define GC_USB_GOTGCTL_BVALIDOVEN_OFFSET 0x0 -#define GC_USB_GOTGCTL_BVALIDOVVAL_LSB 0x7 -#define GC_USB_GOTGCTL_BVALIDOVVAL_MASK 0x80 -#define GC_USB_GOTGCTL_BVALIDOVVAL_SIZE 0x1 -#define GC_USB_GOTGCTL_BVALIDOVVAL_DEFAULT 0x0 -#define GC_USB_GOTGCTL_BVALIDOVVAL_OFFSET 0x0 -#define GC_USB_GOTGCTL_CONIDSTS_LSB 0x10 -#define GC_USB_GOTGCTL_CONIDSTS_MASK 0x10000 -#define GC_USB_GOTGCTL_CONIDSTS_SIZE 0x1 -#define GC_USB_GOTGCTL_CONIDSTS_DEFAULT 0x0 -#define GC_USB_GOTGCTL_CONIDSTS_OFFSET 0x0 -#define GC_USB_GOTGCTL_BSESVLD_LSB 0x13 -#define GC_USB_GOTGCTL_BSESVLD_MASK 0x80000 -#define GC_USB_GOTGCTL_BSESVLD_SIZE 0x1 -#define GC_USB_GOTGCTL_BSESVLD_DEFAULT 0x0 -#define GC_USB_GOTGCTL_BSESVLD_OFFSET 0x0 -#define GC_USB_GOTGCTL_OTGVER_LSB 0x14 -#define GC_USB_GOTGCTL_OTGVER_MASK 0x100000 -#define GC_USB_GOTGCTL_OTGVER_SIZE 0x1 -#define GC_USB_GOTGCTL_OTGVER_DEFAULT 0x0 -#define GC_USB_GOTGCTL_OTGVER_OFFSET 0x0 -#define GC_USB_GOTGCTL_CURMOD_LSB 0x15 -#define GC_USB_GOTGCTL_CURMOD_MASK 0x200000 -#define GC_USB_GOTGCTL_CURMOD_SIZE 0x1 -#define GC_USB_GOTGCTL_CURMOD_DEFAULT 0x0 -#define GC_USB_GOTGCTL_CURMOD_OFFSET 0x0 -#define GC_USB_GOTGINT_SESENDDET_LSB 0x2 -#define GC_USB_GOTGINT_SESENDDET_MASK 0x4 -#define GC_USB_GOTGINT_SESENDDET_SIZE 0x1 -#define GC_USB_GOTGINT_SESENDDET_DEFAULT 0x0 -#define GC_USB_GOTGINT_SESENDDET_OFFSET 0x4 -#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_LSB 0x8 -#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_MASK 0x100 -#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_SIZE 0x1 -#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_DEFAULT 0x0 -#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_OFFSET 0x4 -#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_LSB 0x9 -#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_MASK 0x200 -#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_SIZE 0x1 -#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_DEFAULT 0x0 -#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_OFFSET 0x4 -#define GC_USB_GOTGINT_HSTNEGDET_LSB 0x11 -#define GC_USB_GOTGINT_HSTNEGDET_MASK 0x20000 -#define GC_USB_GOTGINT_HSTNEGDET_SIZE 0x1 -#define GC_USB_GOTGINT_HSTNEGDET_DEFAULT 0x0 -#define GC_USB_GOTGINT_HSTNEGDET_OFFSET 0x4 -#define GC_USB_GOTGINT_ADEVTOUTCHG_LSB 0x12 -#define GC_USB_GOTGINT_ADEVTOUTCHG_MASK 0x40000 -#define GC_USB_GOTGINT_ADEVTOUTCHG_SIZE 0x1 -#define GC_USB_GOTGINT_ADEVTOUTCHG_DEFAULT 0x0 -#define GC_USB_GOTGINT_ADEVTOUTCHG_OFFSET 0x4 -#define GC_USB_GAHBCFG_GLBLINTRMSK_LSB 0x0 -#define GC_USB_GAHBCFG_GLBLINTRMSK_MASK 0x1 -#define GC_USB_GAHBCFG_GLBLINTRMSK_SIZE 0x1 -#define GC_USB_GAHBCFG_GLBLINTRMSK_DEFAULT 0x0 -#define GC_USB_GAHBCFG_GLBLINTRMSK_OFFSET 0x8 -#define GC_USB_GAHBCFG_HBSTLEN_LSB 0x1 -#define GC_USB_GAHBCFG_HBSTLEN_MASK 0x1e -#define GC_USB_GAHBCFG_HBSTLEN_SIZE 0x4 -#define GC_USB_GAHBCFG_HBSTLEN_DEFAULT 0x0 -#define GC_USB_GAHBCFG_HBSTLEN_OFFSET 0x8 -#define GC_USB_GAHBCFG_DMAEN_LSB 0x5 -#define GC_USB_GAHBCFG_DMAEN_MASK 0x20 -#define GC_USB_GAHBCFG_DMAEN_SIZE 0x1 -#define GC_USB_GAHBCFG_DMAEN_DEFAULT 0x0 -#define GC_USB_GAHBCFG_DMAEN_OFFSET 0x8 +#define GC_USB_GCCFG_OFFSET 0x38 +#define GC_USB_GCCFG_DEFAULT 0x0 +#define GC_USB_GUID_OFFSET 0x3c +#define GC_USB_GUID_DEFAULT 0x0 +#define GC_USB_GSNPSID_OFFSET 0x40 +#define GC_USB_GSNPSID_DEFAULT 0x0 +#define GC_USB_GHWCFG1_OFFSET 0x44 +#define GC_USB_GHWCFG1_DEFAULT 0x0 +#define GC_USB_GHWCFG2_OFFSET 0x48 +#define GC_USB_GHWCFG2_DEFAULT 0x0 +#define GC_USB_GHWCFG3_OFFSET 0x4c +#define GC_USB_GHWCFG3_DEFAULT 0x0 +#define GC_USB_GHWCFG4_OFFSET 0x50 +#define GC_USB_GHWCFG4_DEFAULT 0x0 +#define GC_USB_GDFIFOCFG_OFFSET 0x5c +#define GC_USB_GDFIFOCFG_DEFAULT 0x0 +#define GC_USB_DIEPTXF1_OFFSET 0x104 +#define GC_USB_DIEPTXF1_DEFAULT 0x1000 +#define GC_USB_DIEPTXF2_OFFSET 0x108 +#define GC_USB_DIEPTXF2_DEFAULT 0x0 +#define GC_USB_DIEPTXF3_OFFSET 0x10c +#define GC_USB_DIEPTXF3_DEFAULT 0x0 +#define GC_USB_DIEPTXF4_OFFSET 0x110 +#define GC_USB_DIEPTXF4_DEFAULT 0x0 +#define GC_USB_DIEPTXF5_OFFSET 0x114 +#define GC_USB_DIEPTXF5_DEFAULT 0x0 +#define GC_USB_DIEPTXF6_OFFSET 0x118 +#define GC_USB_DIEPTXF6_DEFAULT 0x0 +#define GC_USB_DIEPTXF7_OFFSET 0x11c +#define GC_USB_DIEPTXF7_DEFAULT 0x0 +#define GC_USB_DIEPTXF8_OFFSET 0x120 +#define GC_USB_DIEPTXF8_DEFAULT 0x0 +#define GC_USB_DIEPTXF9_OFFSET 0x124 +#define GC_USB_DIEPTXF9_DEFAULT 0x0 +#define GC_USB_DIEPTXF10_OFFSET 0x128 +#define GC_USB_DIEPTXF10_DEFAULT 0x0 +#define GC_USB_DIEPTXF11_OFFSET 0x12c +#define GC_USB_DIEPTXF11_DEFAULT 0x0 +#define GC_USB_DIEPTXF12_OFFSET 0x130 +#define GC_USB_DIEPTXF12_DEFAULT 0x0 +#define GC_USB_DIEPTXF13_OFFSET 0x134 +#define GC_USB_DIEPTXF13_DEFAULT 0x0 +#define GC_USB_DIEPTXF14_OFFSET 0x138 +#define GC_USB_DIEPTXF14_DEFAULT 0x0 +#define GC_USB_DIEPTXF15_OFFSET 0x13c +#define GC_USB_DIEPTXF15_DEFAULT 0x0 +#define GC_USB_DCFG_OFFSET 0x800 +#define GC_USB_DCFG_DEFAULT 0x8000000 +#define GC_USB_DCTL_OFFSET 0x804 +#define GC_USB_DCTL_DEFAULT 0x0 +#define GC_USB_DSTS_OFFSET 0x808 +#define GC_USB_DSTS_DEFAULT 0x0 +#define GC_USB_DIEPMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_DEFAULT 0x80 +#define GC_USB_DOEPMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_DEFAULT 0x0 +#define GC_USB_DAINT_OFFSET 0x818 +#define GC_USB_DAINT_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OFFSET 0x81c +#define GC_USB_DAINTMSK_DEFAULT 0x0 +#define GC_USB_DVBUSDIS_OFFSET 0x828 +#define GC_USB_DVBUSDIS_DEFAULT 0x0 +#define GC_USB_DVBUSPULSE_OFFSET 0x82c +#define GC_USB_DVBUSPULSE_DEFAULT 0x0 +#define GC_USB_DTHRCTL_OFFSET 0x830 +#define GC_USB_DTHRCTL_DEFAULT 0x0 +#define GC_USB_DIEPEMPMSK_OFFSET 0x834 +#define GC_USB_DIEPEMPMSK_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_OFFSET 0x900 +#define GC_USB_DIEPCTL0_DEFAULT 0x0 +#define GC_USB_DIEPINT0_OFFSET 0x908 +#define GC_USB_DIEPINT0_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ0_OFFSET 0x910 +#define GC_USB_DIEPTSIZ0_DEFAULT 0x0 +#define GC_USB_DIEPDMA0_OFFSET 0x914 +#define GC_USB_DIEPDMA0_DEFAULT 0x0 +#define GC_USB_DTXFSTS0_OFFSET 0x918 +#define GC_USB_DTXFSTS0_DEFAULT 0x0 +#define GC_USB_DIEPDMAB0_OFFSET 0x91c +#define GC_USB_DIEPDMAB0_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_OFFSET 0x920 +#define GC_USB_DIEPCTL1_DEFAULT 0x0 +#define GC_USB_DIEPINT1_OFFSET 0x928 +#define GC_USB_DIEPINT1_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ1_OFFSET 0x930 +#define GC_USB_DIEPTSIZ1_DEFAULT 0x0 +#define GC_USB_DIEPDMA1_OFFSET 0x934 +#define GC_USB_DIEPDMA1_DEFAULT 0x0 +#define GC_USB_DTXFSTS1_OFFSET 0x938 +#define GC_USB_DTXFSTS1_DEFAULT 0x0 +#define GC_USB_DIEPDMAB1_OFFSET 0x93c +#define GC_USB_DIEPDMAB1_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_OFFSET 0x940 +#define GC_USB_DIEPCTL2_DEFAULT 0x0 +#define GC_USB_DIEPINT2_OFFSET 0x948 +#define GC_USB_DIEPINT2_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ2_OFFSET 0x950 +#define GC_USB_DIEPTSIZ2_DEFAULT 0x0 +#define GC_USB_DIEPDMA2_OFFSET 0x954 +#define GC_USB_DIEPDMA2_DEFAULT 0x0 +#define GC_USB_DTXFSTS2_OFFSET 0x958 +#define GC_USB_DTXFSTS2_DEFAULT 0x0 +#define GC_USB_DIEPDMAB2_OFFSET 0x95c +#define GC_USB_DIEPDMAB2_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_OFFSET 0x960 +#define GC_USB_DIEPCTL3_DEFAULT 0x0 +#define GC_USB_DIEPINT3_OFFSET 0x968 +#define GC_USB_DIEPINT3_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ3_OFFSET 0x970 +#define GC_USB_DIEPTSIZ3_DEFAULT 0x0 +#define GC_USB_DIEPDMA3_OFFSET 0x974 +#define GC_USB_DIEPDMA3_DEFAULT 0x0 +#define GC_USB_DTXFSTS3_OFFSET 0x978 +#define GC_USB_DTXFSTS3_DEFAULT 0x0 +#define GC_USB_DIEPDMAB3_OFFSET 0x97c +#define GC_USB_DIEPDMAB3_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_OFFSET 0x980 +#define GC_USB_DIEPCTL4_DEFAULT 0x0 +#define GC_USB_DIEPINT4_OFFSET 0x988 +#define GC_USB_DIEPINT4_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ4_OFFSET 0x990 +#define GC_USB_DIEPTSIZ4_DEFAULT 0x0 +#define GC_USB_DIEPDMA4_OFFSET 0x994 +#define GC_USB_DIEPDMA4_DEFAULT 0x0 +#define GC_USB_DTXFSTS4_OFFSET 0x998 +#define GC_USB_DTXFSTS4_DEFAULT 0x0 +#define GC_USB_DIEPDMAB4_OFFSET 0x99c +#define GC_USB_DIEPDMAB4_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_DEFAULT 0x0 +#define GC_USB_DIEPINT5_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ5_OFFSET 0x9b0 +#define GC_USB_DIEPTSIZ5_DEFAULT 0x0 +#define GC_USB_DIEPDMA5_OFFSET 0x9b4 +#define GC_USB_DIEPDMA5_DEFAULT 0x0 +#define GC_USB_DTXFSTS5_OFFSET 0x9b8 +#define GC_USB_DTXFSTS5_DEFAULT 0x0 +#define GC_USB_DIEPDMAB5_OFFSET 0x9bc +#define GC_USB_DIEPDMAB5_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_DEFAULT 0x0 +#define GC_USB_DIEPINT6_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ6_OFFSET 0x9d0 +#define GC_USB_DIEPTSIZ6_DEFAULT 0x0 +#define GC_USB_DIEPDMA6_OFFSET 0x9d4 +#define GC_USB_DIEPDMA6_DEFAULT 0x0 +#define GC_USB_DTXFSTS6_OFFSET 0x9d8 +#define GC_USB_DTXFSTS6_DEFAULT 0x0 +#define GC_USB_DIEPDMAB6_OFFSET 0x9dc +#define GC_USB_DIEPDMAB6_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_DEFAULT 0x0 +#define GC_USB_DIEPINT7_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ7_OFFSET 0x9f0 +#define GC_USB_DIEPTSIZ7_DEFAULT 0x0 +#define GC_USB_DIEPDMA7_OFFSET 0x9f4 +#define GC_USB_DIEPDMA7_DEFAULT 0x0 +#define GC_USB_DTXFSTS7_OFFSET 0x9f8 +#define GC_USB_DTXFSTS7_DEFAULT 0x0 +#define GC_USB_DIEPDMAB7_OFFSET 0x9fc +#define GC_USB_DIEPDMAB7_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_DEFAULT 0x0 +#define GC_USB_DIEPINT8_OFFSET 0xa08 +#define GC_USB_DIEPINT8_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ8_OFFSET 0xa10 +#define GC_USB_DIEPTSIZ8_DEFAULT 0x0 +#define GC_USB_DIEPDMA8_OFFSET 0xa14 +#define GC_USB_DIEPDMA8_DEFAULT 0x0 +#define GC_USB_DTXFSTS8_OFFSET 0xa18 +#define GC_USB_DTXFSTS8_DEFAULT 0x0 +#define GC_USB_DIEPDMAB8_OFFSET 0xa1c +#define GC_USB_DIEPDMAB8_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_DEFAULT 0x0 +#define GC_USB_DIEPINT9_OFFSET 0xa28 +#define GC_USB_DIEPINT9_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ9_OFFSET 0xa30 +#define GC_USB_DIEPTSIZ9_DEFAULT 0x0 +#define GC_USB_DIEPDMA9_OFFSET 0xa34 +#define GC_USB_DIEPDMA9_DEFAULT 0x0 +#define GC_USB_DTXFSTS9_OFFSET 0xa38 +#define GC_USB_DTXFSTS9_DEFAULT 0x0 +#define GC_USB_DIEPDMAB9_OFFSET 0xa3c +#define GC_USB_DIEPDMAB9_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_DEFAULT 0x0 +#define GC_USB_DIEPINT10_OFFSET 0xa48 +#define GC_USB_DIEPINT10_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ10_OFFSET 0xa50 +#define GC_USB_DIEPTSIZ10_DEFAULT 0x0 +#define GC_USB_DIEPDMA10_OFFSET 0xa54 +#define GC_USB_DIEPDMA10_DEFAULT 0x0 +#define GC_USB_DTXFSTS10_OFFSET 0xa58 +#define GC_USB_DTXFSTS10_DEFAULT 0x0 +#define GC_USB_DIEPDMAB10_OFFSET 0xa5c +#define GC_USB_DIEPDMAB10_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_DEFAULT 0x0 +#define GC_USB_DIEPINT11_OFFSET 0xa68 +#define GC_USB_DIEPINT11_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ11_OFFSET 0xa70 +#define GC_USB_DIEPTSIZ11_DEFAULT 0x0 +#define GC_USB_DIEPDMA11_OFFSET 0xa74 +#define GC_USB_DIEPDMA11_DEFAULT 0x0 +#define GC_USB_DTXFSTS11_OFFSET 0xa78 +#define GC_USB_DTXFSTS11_DEFAULT 0x0 +#define GC_USB_DIEPDMAB11_OFFSET 0xa7c +#define GC_USB_DIEPDMAB11_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_DEFAULT 0x0 +#define GC_USB_DIEPINT12_OFFSET 0xa88 +#define GC_USB_DIEPINT12_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ12_OFFSET 0xa90 +#define GC_USB_DIEPTSIZ12_DEFAULT 0x0 +#define GC_USB_DIEPDMA12_OFFSET 0xa94 +#define GC_USB_DIEPDMA12_DEFAULT 0x0 +#define GC_USB_DTXFSTS12_OFFSET 0xa98 +#define GC_USB_DTXFSTS12_DEFAULT 0x0 +#define GC_USB_DIEPDMAB12_OFFSET 0xa9c +#define GC_USB_DIEPDMAB12_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_DEFAULT 0x0 +#define GC_USB_DIEPINT13_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ13_OFFSET 0xab0 +#define GC_USB_DIEPTSIZ13_DEFAULT 0x0 +#define GC_USB_DIEPDMA13_OFFSET 0xab4 +#define GC_USB_DIEPDMA13_DEFAULT 0x0 +#define GC_USB_DTXFSTS13_OFFSET 0xab8 +#define GC_USB_DTXFSTS13_DEFAULT 0x0 +#define GC_USB_DIEPDMAB13_OFFSET 0xabc +#define GC_USB_DIEPDMAB13_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_DEFAULT 0x0 +#define GC_USB_DIEPINT14_OFFSET 0xac8 +#define GC_USB_DIEPINT14_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ14_OFFSET 0xad0 +#define GC_USB_DIEPTSIZ14_DEFAULT 0x0 +#define GC_USB_DIEPDMA14_OFFSET 0xad4 +#define GC_USB_DIEPDMA14_DEFAULT 0x0 +#define GC_USB_DTXFSTS14_OFFSET 0xad8 +#define GC_USB_DTXFSTS14_DEFAULT 0x0 +#define GC_USB_DIEPDMAB14_OFFSET 0xadc +#define GC_USB_DIEPDMAB14_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_DEFAULT 0x0 +#define GC_USB_DIEPINT15_OFFSET 0xae8 +#define GC_USB_DIEPINT15_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ15_OFFSET 0xaf0 +#define GC_USB_DIEPTSIZ15_DEFAULT 0x0 +#define GC_USB_DIEPDMA15_OFFSET 0xaf4 +#define GC_USB_DIEPDMA15_DEFAULT 0x0 +#define GC_USB_DTXFSTS15_OFFSET 0xaf8 +#define GC_USB_DTXFSTS15_DEFAULT 0x0 +#define GC_USB_DIEPDMAB15_OFFSET 0xafc +#define GC_USB_DIEPDMAB15_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_DEFAULT 0x0 +#define GC_USB_DOEPINT0_OFFSET 0xb08 +#define GC_USB_DOEPINT0_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ0_OFFSET 0xb10 +#define GC_USB_DOEPTSIZ0_DEFAULT 0x0 +#define GC_USB_DOEPDMA0_OFFSET 0xb14 +#define GC_USB_DOEPDMA0_DEFAULT 0x0 +#define GC_USB_DOEPDMAB0_OFFSET 0xb1c +#define GC_USB_DOEPDMAB0_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_DEFAULT 0x0 +#define GC_USB_DOEPINT1_OFFSET 0xb28 +#define GC_USB_DOEPINT1_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ1_OFFSET 0xb30 +#define GC_USB_DOEPTSIZ1_DEFAULT 0x0 +#define GC_USB_DOEPDMA1_OFFSET 0xb34 +#define GC_USB_DOEPDMA1_DEFAULT 0x0 +#define GC_USB_DOEPDMAB1_OFFSET 0xb3c +#define GC_USB_DOEPDMAB1_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_DEFAULT 0x0 +#define GC_USB_DOEPINT2_OFFSET 0xb48 +#define GC_USB_DOEPINT2_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ2_OFFSET 0xb50 +#define GC_USB_DOEPTSIZ2_DEFAULT 0x0 +#define GC_USB_DOEPDMA2_OFFSET 0xb54 +#define GC_USB_DOEPDMA2_DEFAULT 0x0 +#define GC_USB_DOEPDMAB2_OFFSET 0xb5c +#define GC_USB_DOEPDMAB2_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_DEFAULT 0x0 +#define GC_USB_DOEPINT3_OFFSET 0xb68 +#define GC_USB_DOEPINT3_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ3_OFFSET 0xb70 +#define GC_USB_DOEPTSIZ3_DEFAULT 0x0 +#define GC_USB_DOEPDMA3_OFFSET 0xb74 +#define GC_USB_DOEPDMA3_DEFAULT 0x0 +#define GC_USB_DOEPDMAB3_OFFSET 0xb7c +#define GC_USB_DOEPDMAB3_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_DEFAULT 0x0 +#define GC_USB_DOEPINT4_OFFSET 0xb88 +#define GC_USB_DOEPINT4_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ4_OFFSET 0xb90 +#define GC_USB_DOEPTSIZ4_DEFAULT 0x0 +#define GC_USB_DOEPDMA4_OFFSET 0xb94 +#define GC_USB_DOEPDMA4_DEFAULT 0x0 +#define GC_USB_DOEPDMAB4_OFFSET 0xb9c +#define GC_USB_DOEPDMAB4_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_DEFAULT 0x0 +#define GC_USB_DOEPINT5_OFFSET 0xba8 +#define GC_USB_DOEPINT5_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ5_OFFSET 0xbb0 +#define GC_USB_DOEPTSIZ5_DEFAULT 0x0 +#define GC_USB_DOEPDMA5_OFFSET 0xbb4 +#define GC_USB_DOEPDMA5_DEFAULT 0x0 +#define GC_USB_DOEPDMAB5_OFFSET 0xbbc +#define GC_USB_DOEPDMAB5_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_DEFAULT 0x0 +#define GC_USB_DOEPINT6_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ6_OFFSET 0xbd0 +#define GC_USB_DOEPTSIZ6_DEFAULT 0x0 +#define GC_USB_DOEPDMA6_OFFSET 0xbd4 +#define GC_USB_DOEPDMA6_DEFAULT 0x0 +#define GC_USB_DOEPDMAB6_OFFSET 0xbdc +#define GC_USB_DOEPDMAB6_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_DEFAULT 0x0 +#define GC_USB_DOEPINT7_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ7_OFFSET 0xbf0 +#define GC_USB_DOEPTSIZ7_DEFAULT 0x0 +#define GC_USB_DOEPDMA7_OFFSET 0xbf4 +#define GC_USB_DOEPDMA7_DEFAULT 0x0 +#define GC_USB_DOEPDMAB7_OFFSET 0xbfc +#define GC_USB_DOEPDMAB7_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_DEFAULT 0x0 +#define GC_USB_DOEPINT8_OFFSET 0xc08 +#define GC_USB_DOEPINT8_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ8_OFFSET 0xc10 +#define GC_USB_DOEPTSIZ8_DEFAULT 0x0 +#define GC_USB_DOEPDMA8_OFFSET 0xc14 +#define GC_USB_DOEPDMA8_DEFAULT 0x0 +#define GC_USB_DOEPDMAB8_OFFSET 0xc1c +#define GC_USB_DOEPDMAB8_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_DEFAULT 0x0 +#define GC_USB_DOEPINT9_OFFSET 0xc28 +#define GC_USB_DOEPINT9_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ9_OFFSET 0xc30 +#define GC_USB_DOEPTSIZ9_DEFAULT 0x0 +#define GC_USB_DOEPDMA9_OFFSET 0xc34 +#define GC_USB_DOEPDMA9_DEFAULT 0x0 +#define GC_USB_DOEPDMAB9_OFFSET 0xc3c +#define GC_USB_DOEPDMAB9_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_DEFAULT 0x0 +#define GC_USB_DOEPINT10_OFFSET 0xc48 +#define GC_USB_DOEPINT10_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ10_OFFSET 0xc50 +#define GC_USB_DOEPTSIZ10_DEFAULT 0x0 +#define GC_USB_DOEPDMA10_OFFSET 0xc54 +#define GC_USB_DOEPDMA10_DEFAULT 0x0 +#define GC_USB_DOEPDMAB10_OFFSET 0xc5c +#define GC_USB_DOEPDMAB10_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_DEFAULT 0x0 +#define GC_USB_DOEPINT11_OFFSET 0xc68 +#define GC_USB_DOEPINT11_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ11_OFFSET 0xc70 +#define GC_USB_DOEPTSIZ11_DEFAULT 0x0 +#define GC_USB_DOEPDMA11_OFFSET 0xc74 +#define GC_USB_DOEPDMA11_DEFAULT 0x0 +#define GC_USB_DOEPDMAB11_OFFSET 0xc7c +#define GC_USB_DOEPDMAB11_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_DEFAULT 0x0 +#define GC_USB_DOEPINT12_OFFSET 0xc88 +#define GC_USB_DOEPINT12_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ12_OFFSET 0xc90 +#define GC_USB_DOEPTSIZ12_DEFAULT 0x0 +#define GC_USB_DOEPDMA12_OFFSET 0xc94 +#define GC_USB_DOEPDMA12_DEFAULT 0x0 +#define GC_USB_DOEPDMAB12_OFFSET 0xc9c +#define GC_USB_DOEPDMAB12_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_DEFAULT 0x0 +#define GC_USB_DOEPINT13_OFFSET 0xca8 +#define GC_USB_DOEPINT13_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ13_OFFSET 0xcb0 +#define GC_USB_DOEPTSIZ13_DEFAULT 0x0 +#define GC_USB_DOEPDMA13_OFFSET 0xcb4 +#define GC_USB_DOEPDMA13_DEFAULT 0x0 +#define GC_USB_DOEPDMAB13_OFFSET 0xcbc +#define GC_USB_DOEPDMAB13_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_DEFAULT 0x0 +#define GC_USB_DOEPINT14_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ14_OFFSET 0xcd0 +#define GC_USB_DOEPTSIZ14_DEFAULT 0x0 +#define GC_USB_DOEPDMA14_OFFSET 0xcd4 +#define GC_USB_DOEPDMA14_DEFAULT 0x0 +#define GC_USB_DOEPDMAB14_OFFSET 0xcdc +#define GC_USB_DOEPDMAB14_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_DEFAULT 0x0 +#define GC_USB_DOEPINT15_OFFSET 0xce8 +#define GC_USB_DOEPINT15_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ15_OFFSET 0xcf0 +#define GC_USB_DOEPTSIZ15_DEFAULT 0x0 +#define GC_USB_DOEPDMA15_OFFSET 0xcf4 +#define GC_USB_DOEPDMA15_DEFAULT 0x0 +#define GC_USB_DOEPDMAB15_OFFSET 0xcfc +#define GC_USB_DOEPDMAB15_DEFAULT 0x0 +#define GC_USB_PCGCCTL_OFFSET 0xe00 +#define GC_USB_PCGCCTL_DEFAULT 0x0 +#define GC_USB_DFIFO_OFFSET 0x20000 +#define GC_USB_GOTGCTL_BVALIDOVEN_LSB 0x6 +#define GC_USB_GOTGCTL_BVALIDOVEN_MASK 0x40 +#define GC_USB_GOTGCTL_BVALIDOVEN_SIZE 0x1 +#define GC_USB_GOTGCTL_BVALIDOVEN_DEFAULT 0x0 +#define GC_USB_GOTGCTL_BVALIDOVEN_OFFSET 0x0 +#define GC_USB_GOTGCTL_BVALIDOVVAL_LSB 0x7 +#define GC_USB_GOTGCTL_BVALIDOVVAL_MASK 0x80 +#define GC_USB_GOTGCTL_BVALIDOVVAL_SIZE 0x1 +#define GC_USB_GOTGCTL_BVALIDOVVAL_DEFAULT 0x0 +#define GC_USB_GOTGCTL_BVALIDOVVAL_OFFSET 0x0 +#define GC_USB_GOTGCTL_CONIDSTS_LSB 0x10 +#define GC_USB_GOTGCTL_CONIDSTS_MASK 0x10000 +#define GC_USB_GOTGCTL_CONIDSTS_SIZE 0x1 +#define GC_USB_GOTGCTL_CONIDSTS_DEFAULT 0x0 +#define GC_USB_GOTGCTL_CONIDSTS_OFFSET 0x0 +#define GC_USB_GOTGCTL_BSESVLD_LSB 0x13 +#define GC_USB_GOTGCTL_BSESVLD_MASK 0x80000 +#define GC_USB_GOTGCTL_BSESVLD_SIZE 0x1 +#define GC_USB_GOTGCTL_BSESVLD_DEFAULT 0x0 +#define GC_USB_GOTGCTL_BSESVLD_OFFSET 0x0 +#define GC_USB_GOTGCTL_OTGVER_LSB 0x14 +#define GC_USB_GOTGCTL_OTGVER_MASK 0x100000 +#define GC_USB_GOTGCTL_OTGVER_SIZE 0x1 +#define GC_USB_GOTGCTL_OTGVER_DEFAULT 0x0 +#define GC_USB_GOTGCTL_OTGVER_OFFSET 0x0 +#define GC_USB_GOTGCTL_CURMOD_LSB 0x15 +#define GC_USB_GOTGCTL_CURMOD_MASK 0x200000 +#define GC_USB_GOTGCTL_CURMOD_SIZE 0x1 +#define GC_USB_GOTGCTL_CURMOD_DEFAULT 0x0 +#define GC_USB_GOTGCTL_CURMOD_OFFSET 0x0 +#define GC_USB_GOTGINT_SESENDDET_LSB 0x2 +#define GC_USB_GOTGINT_SESENDDET_MASK 0x4 +#define GC_USB_GOTGINT_SESENDDET_SIZE 0x1 +#define GC_USB_GOTGINT_SESENDDET_DEFAULT 0x0 +#define GC_USB_GOTGINT_SESENDDET_OFFSET 0x4 +#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_LSB 0x8 +#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_MASK 0x100 +#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_SIZE 0x1 +#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_DEFAULT 0x0 +#define GC_USB_GOTGINT_SESREQSUCSTSCHNG_OFFSET 0x4 +#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_LSB 0x9 +#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_MASK 0x200 +#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_SIZE 0x1 +#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_DEFAULT 0x0 +#define GC_USB_GOTGINT_HSTNEGSUCSTSCHNG_OFFSET 0x4 +#define GC_USB_GOTGINT_HSTNEGDET_LSB 0x11 +#define GC_USB_GOTGINT_HSTNEGDET_MASK 0x20000 +#define GC_USB_GOTGINT_HSTNEGDET_SIZE 0x1 +#define GC_USB_GOTGINT_HSTNEGDET_DEFAULT 0x0 +#define GC_USB_GOTGINT_HSTNEGDET_OFFSET 0x4 +#define GC_USB_GOTGINT_ADEVTOUTCHG_LSB 0x12 +#define GC_USB_GOTGINT_ADEVTOUTCHG_MASK 0x40000 +#define GC_USB_GOTGINT_ADEVTOUTCHG_SIZE 0x1 +#define GC_USB_GOTGINT_ADEVTOUTCHG_DEFAULT 0x0 +#define GC_USB_GOTGINT_ADEVTOUTCHG_OFFSET 0x4 +#define GC_USB_GAHBCFG_GLBLINTRMSK_LSB 0x0 +#define GC_USB_GAHBCFG_GLBLINTRMSK_MASK 0x1 +#define GC_USB_GAHBCFG_GLBLINTRMSK_SIZE 0x1 +#define GC_USB_GAHBCFG_GLBLINTRMSK_DEFAULT 0x0 +#define GC_USB_GAHBCFG_GLBLINTRMSK_OFFSET 0x8 +#define GC_USB_GAHBCFG_HBSTLEN_LSB 0x1 +#define GC_USB_GAHBCFG_HBSTLEN_MASK 0x1e +#define GC_USB_GAHBCFG_HBSTLEN_SIZE 0x4 +#define GC_USB_GAHBCFG_HBSTLEN_DEFAULT 0x0 +#define GC_USB_GAHBCFG_HBSTLEN_OFFSET 0x8 +#define GC_USB_GAHBCFG_DMAEN_LSB 0x5 +#define GC_USB_GAHBCFG_DMAEN_MASK 0x20 +#define GC_USB_GAHBCFG_DMAEN_SIZE 0x1 +#define GC_USB_GAHBCFG_DMAEN_DEFAULT 0x0 +#define GC_USB_GAHBCFG_DMAEN_OFFSET 0x8 -#define GC_USB_GAHBCFG_NPTXFEMPLVL_LSB 0x7 -#define GC_USB_GAHBCFG_NPTXFEMPLVL_MASK 0x80 -#define GC_USB_GAHBCFG_NPTXFEMPLVL_SIZE 0x1 -#define GC_USB_GAHBCFG_NPTXFEMPLVL_DEFAULT 0x0 -#define GC_USB_GAHBCFG_NPTXFEMPLVL_OFFSET 0x8 +#define GC_USB_GAHBCFG_NPTXFEMPLVL_LSB 0x7 +#define GC_USB_GAHBCFG_NPTXFEMPLVL_MASK 0x80 +#define GC_USB_GAHBCFG_NPTXFEMPLVL_SIZE 0x1 +#define GC_USB_GAHBCFG_NPTXFEMPLVL_DEFAULT 0x0 +#define GC_USB_GAHBCFG_NPTXFEMPLVL_OFFSET 0x8 -#define GC_USB_GAHBCFG_REMMEMSUPP_LSB 0x15 -#define GC_USB_GAHBCFG_REMMEMSUPP_MASK 0x200000 -#define GC_USB_GAHBCFG_REMMEMSUPP_SIZE 0x1 -#define GC_USB_GAHBCFG_REMMEMSUPP_DEFAULT 0x0 -#define GC_USB_GAHBCFG_REMMEMSUPP_OFFSET 0x8 -#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_LSB 0x16 -#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_MASK 0x400000 -#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_SIZE 0x1 -#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_DEFAULT 0x0 -#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_OFFSET 0x8 -#define GC_USB_GAHBCFG_AHBSINGLE_LSB 0x17 -#define GC_USB_GAHBCFG_AHBSINGLE_MASK 0x800000 -#define GC_USB_GAHBCFG_AHBSINGLE_SIZE 0x1 -#define GC_USB_GAHBCFG_AHBSINGLE_DEFAULT 0x0 -#define GC_USB_GAHBCFG_AHBSINGLE_OFFSET 0x8 -#define GC_USB_GAHBCFG_INVDESCENDIANESS_LSB 0x18 -#define GC_USB_GAHBCFG_INVDESCENDIANESS_MASK 0x1000000 -#define GC_USB_GAHBCFG_INVDESCENDIANESS_SIZE 0x1 -#define GC_USB_GAHBCFG_INVDESCENDIANESS_DEFAULT 0x0 -#define GC_USB_GAHBCFG_INVDESCENDIANESS_OFFSET 0x8 -#define GC_USB_GUSBCFG_TOUTCAL_LSB 0x0 -#define GC_USB_GUSBCFG_TOUTCAL_MASK 0x7 -#define GC_USB_GUSBCFG_TOUTCAL_SIZE 0x3 -#define GC_USB_GUSBCFG_TOUTCAL_DEFAULT 0x0 -#define GC_USB_GUSBCFG_TOUTCAL_OFFSET 0xc +#define GC_USB_GAHBCFG_REMMEMSUPP_LSB 0x15 +#define GC_USB_GAHBCFG_REMMEMSUPP_MASK 0x200000 +#define GC_USB_GAHBCFG_REMMEMSUPP_SIZE 0x1 +#define GC_USB_GAHBCFG_REMMEMSUPP_DEFAULT 0x0 +#define GC_USB_GAHBCFG_REMMEMSUPP_OFFSET 0x8 +#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_LSB 0x16 +#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_MASK 0x400000 +#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_SIZE 0x1 +#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_DEFAULT 0x0 +#define GC_USB_GAHBCFG_NOTIALLDMAWRIT_OFFSET 0x8 +#define GC_USB_GAHBCFG_AHBSINGLE_LSB 0x17 +#define GC_USB_GAHBCFG_AHBSINGLE_MASK 0x800000 +#define GC_USB_GAHBCFG_AHBSINGLE_SIZE 0x1 +#define GC_USB_GAHBCFG_AHBSINGLE_DEFAULT 0x0 +#define GC_USB_GAHBCFG_AHBSINGLE_OFFSET 0x8 +#define GC_USB_GAHBCFG_INVDESCENDIANESS_LSB 0x18 +#define GC_USB_GAHBCFG_INVDESCENDIANESS_MASK 0x1000000 +#define GC_USB_GAHBCFG_INVDESCENDIANESS_SIZE 0x1 +#define GC_USB_GAHBCFG_INVDESCENDIANESS_DEFAULT 0x0 +#define GC_USB_GAHBCFG_INVDESCENDIANESS_OFFSET 0x8 +#define GC_USB_GUSBCFG_TOUTCAL_LSB 0x0 +#define GC_USB_GUSBCFG_TOUTCAL_MASK 0x7 +#define GC_USB_GUSBCFG_TOUTCAL_SIZE 0x3 +#define GC_USB_GUSBCFG_TOUTCAL_DEFAULT 0x0 +#define GC_USB_GUSBCFG_TOUTCAL_OFFSET 0xc -#define GC_USB_GUSBCFG_USBTRDTIM_LSB 0xa -#define GC_USB_GUSBCFG_USBTRDTIM_MASK 0x3c00 -#define GC_USB_GUSBCFG_USBTRDTIM_SIZE 0x4 -#define GC_USB_GUSBCFG_USBTRDTIM_DEFAULT 0x0 -#define GC_USB_GUSBCFG_USBTRDTIM_OFFSET 0xc -#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_LSB 15 -#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_MASK 0x8000 -#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_SIZE 0x1 -#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_DEFAULT 0x0 -#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_OFFSET 0xc -#define GC_USB_GUSBCFG_ULPIFSLS_LSB 17 -#define GC_USB_GUSBCFG_ULPIFSLS_MASK 0x20000 -#define GC_USB_GUSBCFG_ULPIFSLS_SIZE 0x1 -#define GC_USB_GUSBCFG_ULPIFSLS_DEFAULT 0x0 -#define GC_USB_GUSBCFG_ULPIFSLS_OFFSET 0xc -#define GC_USB_GUSBCFG_ULPIAUTORES_LSB 18 -#define GC_USB_GUSBCFG_ULPIAUTORES_MASK 0x40000 -#define GC_USB_GUSBCFG_ULPIAUTORES_SIZE 0x1 -#define GC_USB_GUSBCFG_ULPIAUTORES_DEFAULT 0x0 -#define GC_USB_GUSBCFG_ULPIAUTORES_OFFSET 0xc -#define GC_USB_GUSBCFG_ULPICLKSUSM_LSB 19 -#define GC_USB_GUSBCFG_ULPICLKSUSM_MASK 0x80000 -#define GC_USB_GUSBCFG_ULPICLKSUSM_SIZE 0x1 -#define GC_USB_GUSBCFG_ULPICLKSUSM_DEFAULT 0x0 -#define GC_USB_GUSBCFG_ULPICLKSUSM_OFFSET 0xc +#define GC_USB_GUSBCFG_USBTRDTIM_LSB 0xa +#define GC_USB_GUSBCFG_USBTRDTIM_MASK 0x3c00 +#define GC_USB_GUSBCFG_USBTRDTIM_SIZE 0x4 +#define GC_USB_GUSBCFG_USBTRDTIM_DEFAULT 0x0 +#define GC_USB_GUSBCFG_USBTRDTIM_OFFSET 0xc +#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_LSB 15 +#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_MASK 0x8000 +#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_SIZE 0x1 +#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_DEFAULT 0x0 +#define GC_USB_GUSBCFG_PHYLPWRCLKSEL_OFFSET 0xc +#define GC_USB_GUSBCFG_ULPIFSLS_LSB 17 +#define GC_USB_GUSBCFG_ULPIFSLS_MASK 0x20000 +#define GC_USB_GUSBCFG_ULPIFSLS_SIZE 0x1 +#define GC_USB_GUSBCFG_ULPIFSLS_DEFAULT 0x0 +#define GC_USB_GUSBCFG_ULPIFSLS_OFFSET 0xc +#define GC_USB_GUSBCFG_ULPIAUTORES_LSB 18 +#define GC_USB_GUSBCFG_ULPIAUTORES_MASK 0x40000 +#define GC_USB_GUSBCFG_ULPIAUTORES_SIZE 0x1 +#define GC_USB_GUSBCFG_ULPIAUTORES_DEFAULT 0x0 +#define GC_USB_GUSBCFG_ULPIAUTORES_OFFSET 0xc +#define GC_USB_GUSBCFG_ULPICLKSUSM_LSB 19 +#define GC_USB_GUSBCFG_ULPICLKSUSM_MASK 0x80000 +#define GC_USB_GUSBCFG_ULPICLKSUSM_SIZE 0x1 +#define GC_USB_GUSBCFG_ULPICLKSUSM_DEFAULT 0x0 +#define GC_USB_GUSBCFG_ULPICLKSUSM_OFFSET 0xc -#define GC_USB_GUSBCFG_ULPIEVBUSD_LSB 20 -#define GC_USB_GUSBCFG_ULPIEVBUSD_MASK 0x100000 -#define GC_USB_GUSBCFG_ULPIEVBUSD_SIZE 0x1 -#define GC_USB_GUSBCFG_ULPIEVBUSD_DEFAULT 0x0 -#define GC_USB_GUSBCFG_ULPIEVBUSD_OFFSET 0xc +#define GC_USB_GUSBCFG_ULPIEVBUSD_LSB 20 +#define GC_USB_GUSBCFG_ULPIEVBUSD_MASK 0x100000 +#define GC_USB_GUSBCFG_ULPIEVBUSD_SIZE 0x1 +#define GC_USB_GUSBCFG_ULPIEVBUSD_DEFAULT 0x0 +#define GC_USB_GUSBCFG_ULPIEVBUSD_OFFSET 0xc -#define GC_USB_GUSBCFG_ULPIEVBUSI_LSB 21 -#define GC_USB_GUSBCFG_ULPIEVBUSI_MASK 0x200000 -#define GC_USB_GUSBCFG_ULPIEVBUSI_SIZE 0x1 -#define GC_USB_GUSBCFG_ULPIEVBUSI_DEFAULT 0x0 -#define GC_USB_GUSBCFG_ULPIEVBUSI_OFFSET 0xc +#define GC_USB_GUSBCFG_ULPIEVBUSI_LSB 21 +#define GC_USB_GUSBCFG_ULPIEVBUSI_MASK 0x200000 +#define GC_USB_GUSBCFG_ULPIEVBUSI_SIZE 0x1 +#define GC_USB_GUSBCFG_ULPIEVBUSI_DEFAULT 0x0 +#define GC_USB_GUSBCFG_ULPIEVBUSI_OFFSET 0xc -#define GC_USB_GUSBCFG_TERMSELDLPULSE_LSB 22 -#define GC_USB_GUSBCFG_TERMSELDLPULSE_MASK 0x400000 -#define GC_USB_GUSBCFG_TERMSELDLPULSE_SIZE 0x1 -#define GC_USB_GUSBCFG_TERMSELDLPULSE_DEFAULT 0x0 -#define GC_USB_GUSBCFG_TERMSELDLPULSE_OFFSET 0xc +#define GC_USB_GUSBCFG_TERMSELDLPULSE_LSB 22 +#define GC_USB_GUSBCFG_TERMSELDLPULSE_MASK 0x400000 +#define GC_USB_GUSBCFG_TERMSELDLPULSE_SIZE 0x1 +#define GC_USB_GUSBCFG_TERMSELDLPULSE_DEFAULT 0x0 +#define GC_USB_GUSBCFG_TERMSELDLPULSE_OFFSET 0xc -#define GC_USB_GUSBCFG_PCCI_LSB 23 -#define GC_USB_GUSBCFG_PCCI_MASK BIT(23) -#define GC_USB_GUSBCFG_PCCI_SIZE 0x1 -#define GC_USB_GUSBCFG_PCCI_DEFAULT 0x0 -#define GC_USB_GUSBCFG_PCCI_OFFSET 0xc +#define GC_USB_GUSBCFG_PCCI_LSB 23 +#define GC_USB_GUSBCFG_PCCI_MASK BIT(23) +#define GC_USB_GUSBCFG_PCCI_SIZE 0x1 +#define GC_USB_GUSBCFG_PCCI_DEFAULT 0x0 +#define GC_USB_GUSBCFG_PCCI_OFFSET 0xc -#define GC_USB_GUSBCFG_PTCI_LSB 24 -#define GC_USB_GUSBCFG_PTCI_MASK BIT(24) -#define GC_USB_GUSBCFG_PTCI_SIZE 0x1 -#define GC_USB_GUSBCFG_PTCI_DEFAULT 0x0 -#define GC_USB_GUSBCFG_PTCI_OFFSET 0xc +#define GC_USB_GUSBCFG_PTCI_LSB 24 +#define GC_USB_GUSBCFG_PTCI_MASK BIT(24) +#define GC_USB_GUSBCFG_PTCI_SIZE 0x1 +#define GC_USB_GUSBCFG_PTCI_DEFAULT 0x0 +#define GC_USB_GUSBCFG_PTCI_OFFSET 0xc -#define GC_USB_GUSBCFG_ULPIIPD_LSB 25 -#define GC_USB_GUSBCFG_ULPIIPD_MASK BIT(25) -#define GC_USB_GUSBCFG_ULPIIPD_SIZE 0x1 -#define GC_USB_GUSBCFG_ULPIIPD_DEFAULT 0x0 -#define GC_USB_GUSBCFG_ULPIIPD_OFFSET 0xc +#define GC_USB_GUSBCFG_ULPIIPD_LSB 25 +#define GC_USB_GUSBCFG_ULPIIPD_MASK BIT(25) +#define GC_USB_GUSBCFG_ULPIIPD_SIZE 0x1 +#define GC_USB_GUSBCFG_ULPIIPD_DEFAULT 0x0 +#define GC_USB_GUSBCFG_ULPIIPD_OFFSET 0xc -#define GC_USB_GUSBCFG_FHMOD_LSB 29 -#define GC_USB_GUSBCFG_FHMOD_MASK BIT(29) -#define GC_USB_GUSBCFG_FHMOD_SIZE 0x1 -#define GC_USB_GUSBCFG_FHMOD_DEFAULT 0x0 -#define GC_USB_GUSBCFG_FHMOD_OFFSET 0xc +#define GC_USB_GUSBCFG_FHMOD_LSB 29 +#define GC_USB_GUSBCFG_FHMOD_MASK BIT(29) +#define GC_USB_GUSBCFG_FHMOD_SIZE 0x1 +#define GC_USB_GUSBCFG_FHMOD_DEFAULT 0x0 +#define GC_USB_GUSBCFG_FHMOD_OFFSET 0xc -#define GC_USB_GUSBCFG_FDMOD_LSB 30 -#define GC_USB_GUSBCFG_FDMOD_MASK BIT(30) -#define GC_USB_GUSBCFG_FDMOD_SIZE 0x1 -#define GC_USB_GUSBCFG_FDMOD_DEFAULT 0x0 -#define GC_USB_GUSBCFG_FDMOD_OFFSET 0xc +#define GC_USB_GUSBCFG_FDMOD_LSB 30 +#define GC_USB_GUSBCFG_FDMOD_MASK BIT(30) +#define GC_USB_GUSBCFG_FDMOD_SIZE 0x1 +#define GC_USB_GUSBCFG_FDMOD_DEFAULT 0x0 +#define GC_USB_GUSBCFG_FDMOD_OFFSET 0xc -#define GC_USB_GRSTCTL_CSFTRST_LSB 0x0 -#define GC_USB_GRSTCTL_CSFTRST_MASK 0x1 -#define GC_USB_GRSTCTL_CSFTRST_SIZE 0x1 -#define GC_USB_GRSTCTL_CSFTRST_DEFAULT 0x0 -#define GC_USB_GRSTCTL_CSFTRST_OFFSET 0x10 -#define GC_USB_GRSTCTL_PIUFSSFTRST_LSB 0x1 -#define GC_USB_GRSTCTL_PIUFSSFTRST_MASK 0x2 -#define GC_USB_GRSTCTL_PIUFSSFTRST_SIZE 0x1 -#define GC_USB_GRSTCTL_PIUFSSFTRST_DEFAULT 0x0 -#define GC_USB_GRSTCTL_PIUFSSFTRST_OFFSET 0x10 -#define GC_USB_GRSTCTL_RXFFLSH_LSB 0x4 -#define GC_USB_GRSTCTL_RXFFLSH_MASK 0x10 -#define GC_USB_GRSTCTL_RXFFLSH_SIZE 0x1 -#define GC_USB_GRSTCTL_RXFFLSH_DEFAULT 0x0 -#define GC_USB_GRSTCTL_RXFFLSH_OFFSET 0x10 -#define GC_USB_GRSTCTL_TXFFLSH_LSB 0x5 -#define GC_USB_GRSTCTL_TXFFLSH_MASK 0x20 -#define GC_USB_GRSTCTL_TXFFLSH_SIZE 0x1 -#define GC_USB_GRSTCTL_TXFFLSH_DEFAULT 0x0 -#define GC_USB_GRSTCTL_TXFFLSH_OFFSET 0x10 -#define GC_USB_GRSTCTL_TXFNUM_LSB 0x6 -#define GC_USB_GRSTCTL_TXFNUM_MASK 0x7c0 -#define GC_USB_GRSTCTL_TXFNUM_SIZE 0x5 -#define GC_USB_GRSTCTL_TXFNUM_DEFAULT 0x0 -#define GC_USB_GRSTCTL_TXFNUM_OFFSET 0x10 -#define GC_USB_GRSTCTL_DMAREQ_LSB 0x1e -#define GC_USB_GRSTCTL_DMAREQ_MASK 0x40000000 -#define GC_USB_GRSTCTL_DMAREQ_SIZE 0x1 -#define GC_USB_GRSTCTL_DMAREQ_DEFAULT 0x0 -#define GC_USB_GRSTCTL_DMAREQ_OFFSET 0x10 -#define GC_USB_GRSTCTL_AHBIDLE_LSB 0x1f -#define GC_USB_GRSTCTL_AHBIDLE_MASK 0x80000000 -#define GC_USB_GRSTCTL_AHBIDLE_SIZE 0x1 -#define GC_USB_GRSTCTL_AHBIDLE_DEFAULT 0x0 -#define GC_USB_GRSTCTL_AHBIDLE_OFFSET 0x10 -#define GC_USB_GINTSTS_CURMOD_LSB 0x0 -#define GC_USB_GINTSTS_CURMOD_MASK 0x1 -#define GC_USB_GINTSTS_CURMOD_SIZE 0x1 -#define GC_USB_GINTSTS_CURMOD_DEFAULT 0x0 -#define GC_USB_GINTSTS_CURMOD_OFFSET 0x14 -#define GC_USB_GINTSTS_MODEMIS_LSB 0x1 -#define GC_USB_GINTSTS_MODEMIS_MASK 0x2 -#define GC_USB_GINTSTS_MODEMIS_SIZE 0x1 -#define GC_USB_GINTSTS_MODEMIS_DEFAULT 0x0 -#define GC_USB_GINTSTS_MODEMIS_OFFSET 0x14 -#define GC_USB_GINTSTS_OTGINT_LSB 0x2 -#define GC_USB_GINTSTS_OTGINT_MASK 0x4 -#define GC_USB_GINTSTS_OTGINT_SIZE 0x1 -#define GC_USB_GINTSTS_OTGINT_DEFAULT 0x0 -#define GC_USB_GINTSTS_OTGINT_OFFSET 0x14 -#define GC_USB_GINTSTS_SOF_LSB 0x3 -#define GC_USB_GINTSTS_SOF_MASK 0x8 -#define GC_USB_GINTSTS_SOF_SIZE 0x1 -#define GC_USB_GINTSTS_SOF_DEFAULT 0x0 -#define GC_USB_GINTSTS_SOF_OFFSET 0x14 -#define GC_USB_GINTSTS_RXFLVL_LSB 0x4 -#define GC_USB_GINTSTS_RXFLVL_MASK 0x10 -#define GC_USB_GINTSTS_RXFLVL_SIZE 0x1 -#define GC_USB_GINTSTS_RXFLVL_DEFAULT 0x0 -#define GC_USB_GINTSTS_RXFLVL_OFFSET 0x14 -#define GC_USB_GINTSTS_GINNAKEFF_LSB 0x6 -#define GC_USB_GINTSTS_GINNAKEFF_MASK 0x40 -#define GC_USB_GINTSTS_GINNAKEFF_SIZE 0x1 -#define GC_USB_GINTSTS_GINNAKEFF_DEFAULT 0x0 -#define GC_USB_GINTSTS_GINNAKEFF_OFFSET 0x14 -#define GC_USB_GINTSTS_GOUTNAKEFF_LSB 0x7 -#define GC_USB_GINTSTS_GOUTNAKEFF_MASK 0x80 -#define GC_USB_GINTSTS_GOUTNAKEFF_SIZE 0x1 -#define GC_USB_GINTSTS_GOUTNAKEFF_DEFAULT 0x0 -#define GC_USB_GINTSTS_GOUTNAKEFF_OFFSET 0x14 -#define GC_USB_GINTSTS_ERLYSUSP_LSB 0xa -#define GC_USB_GINTSTS_ERLYSUSP_MASK 0x400 -#define GC_USB_GINTSTS_ERLYSUSP_SIZE 0x1 -#define GC_USB_GINTSTS_ERLYSUSP_DEFAULT 0x0 -#define GC_USB_GINTSTS_ERLYSUSP_OFFSET 0x14 -#define GC_USB_GINTSTS_USBSUSP_LSB 0xb -#define GC_USB_GINTSTS_USBSUSP_MASK 0x800 -#define GC_USB_GINTSTS_USBSUSP_SIZE 0x1 -#define GC_USB_GINTSTS_USBSUSP_DEFAULT 0x0 -#define GC_USB_GINTSTS_USBSUSP_OFFSET 0x14 -#define GC_USB_GINTSTS_USBRST_LSB 0xc -#define GC_USB_GINTSTS_USBRST_MASK 0x1000 -#define GC_USB_GINTSTS_USBRST_SIZE 0x1 -#define GC_USB_GINTSTS_USBRST_DEFAULT 0x0 -#define GC_USB_GINTSTS_USBRST_OFFSET 0x14 -#define GC_USB_GINTSTS_ENUMDONE_LSB 0xd -#define GC_USB_GINTSTS_ENUMDONE_MASK 0x2000 -#define GC_USB_GINTSTS_ENUMDONE_SIZE 0x1 -#define GC_USB_GINTSTS_ENUMDONE_DEFAULT 0x0 -#define GC_USB_GINTSTS_ENUMDONE_OFFSET 0x14 -#define GC_USB_GINTSTS_ISOOUTDROP_LSB 0xe -#define GC_USB_GINTSTS_ISOOUTDROP_MASK 0x4000 -#define GC_USB_GINTSTS_ISOOUTDROP_SIZE 0x1 -#define GC_USB_GINTSTS_ISOOUTDROP_DEFAULT 0x0 -#define GC_USB_GINTSTS_ISOOUTDROP_OFFSET 0x14 -#define GC_USB_GINTSTS_EOPF_LSB 0xf -#define GC_USB_GINTSTS_EOPF_MASK 0x8000 -#define GC_USB_GINTSTS_EOPF_SIZE 0x1 -#define GC_USB_GINTSTS_EOPF_DEFAULT 0x0 -#define GC_USB_GINTSTS_EOPF_OFFSET 0x14 -#define GC_USB_GINTSTS_EPMIS_LSB 0x11 -#define GC_USB_GINTSTS_EPMIS_MASK 0x20000 -#define GC_USB_GINTSTS_EPMIS_SIZE 0x1 -#define GC_USB_GINTSTS_EPMIS_DEFAULT 0x0 -#define GC_USB_GINTSTS_EPMIS_OFFSET 0x14 -#define GC_USB_GINTSTS_IEPINT_LSB 0x12 -#define GC_USB_GINTSTS_IEPINT_MASK 0x40000 -#define GC_USB_GINTSTS_IEPINT_SIZE 0x1 -#define GC_USB_GINTSTS_IEPINT_DEFAULT 0x0 -#define GC_USB_GINTSTS_IEPINT_OFFSET 0x14 -#define GC_USB_GINTSTS_OEPINT_LSB 0x13 -#define GC_USB_GINTSTS_OEPINT_MASK 0x80000 -#define GC_USB_GINTSTS_OEPINT_SIZE 0x1 -#define GC_USB_GINTSTS_OEPINT_DEFAULT 0x0 -#define GC_USB_GINTSTS_OEPINT_OFFSET 0x14 -#define GC_USB_GINTSTS_INCOMPISOIN_LSB 0x14 -#define GC_USB_GINTSTS_INCOMPISOIN_MASK 0x100000 -#define GC_USB_GINTSTS_INCOMPISOIN_SIZE 0x1 -#define GC_USB_GINTSTS_INCOMPISOIN_DEFAULT 0x0 -#define GC_USB_GINTSTS_INCOMPISOIN_OFFSET 0x14 -#define GC_USB_GINTSTS_INCOMPLP_LSB 0x15 -#define GC_USB_GINTSTS_INCOMPLP_MASK 0x200000 -#define GC_USB_GINTSTS_INCOMPLP_SIZE 0x1 -#define GC_USB_GINTSTS_INCOMPLP_DEFAULT 0x0 -#define GC_USB_GINTSTS_INCOMPLP_OFFSET 0x14 -#define GC_USB_GINTSTS_FETSUSP_LSB 0x16 -#define GC_USB_GINTSTS_FETSUSP_MASK 0x400000 -#define GC_USB_GINTSTS_FETSUSP_SIZE 0x1 -#define GC_USB_GINTSTS_FETSUSP_DEFAULT 0x0 -#define GC_USB_GINTSTS_FETSUSP_OFFSET 0x14 -#define GC_USB_GINTSTS_RESETDET_LSB 0x17 -#define GC_USB_GINTSTS_RESETDET_MASK 0x800000 -#define GC_USB_GINTSTS_RESETDET_SIZE 0x1 -#define GC_USB_GINTSTS_RESETDET_DEFAULT 0x0 -#define GC_USB_GINTSTS_RESETDET_OFFSET 0x14 -#define GC_USB_GINTSTS_CONIDSTSCHNG_LSB 0x1c -#define GC_USB_GINTSTS_CONIDSTSCHNG_MASK 0x10000000 -#define GC_USB_GINTSTS_CONIDSTSCHNG_SIZE 0x1 -#define GC_USB_GINTSTS_CONIDSTSCHNG_DEFAULT 0x0 -#define GC_USB_GINTSTS_CONIDSTSCHNG_OFFSET 0x14 -#define GC_USB_GINTSTS_SESSREQINT_LSB 0x1e -#define GC_USB_GINTSTS_SESSREQINT_MASK 0x40000000 -#define GC_USB_GINTSTS_SESSREQINT_SIZE 0x1 -#define GC_USB_GINTSTS_SESSREQINT_DEFAULT 0x0 -#define GC_USB_GINTSTS_SESSREQINT_OFFSET 0x14 -#define GC_USB_GINTSTS_WKUPINT_LSB 0x1f -#define GC_USB_GINTSTS_WKUPINT_MASK 0x80000000 -#define GC_USB_GINTSTS_WKUPINT_SIZE 0x1 -#define GC_USB_GINTSTS_WKUPINT_DEFAULT 0x0 -#define GC_USB_GINTSTS_WKUPINT_OFFSET 0x14 -#define GC_USB_GINTMSK_MODEMISMSK_LSB 0x1 -#define GC_USB_GINTMSK_MODEMISMSK_MASK 0x2 -#define GC_USB_GINTMSK_MODEMISMSK_SIZE 0x1 -#define GC_USB_GINTMSK_MODEMISMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_MODEMISMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_OTGINTMSK_LSB 0x2 -#define GC_USB_GINTMSK_OTGINTMSK_MASK 0x4 -#define GC_USB_GINTMSK_OTGINTMSK_SIZE 0x1 -#define GC_USB_GINTMSK_OTGINTMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_OTGINTMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_SOFMSK_LSB 0x3 -#define GC_USB_GINTMSK_SOFMSK_MASK 0x8 -#define GC_USB_GINTMSK_SOFMSK_SIZE 0x1 -#define GC_USB_GINTMSK_SOFMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_SOFMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_RXFLVLMSK_LSB 0x4 -#define GC_USB_GINTMSK_RXFLVLMSK_MASK 0x10 -#define GC_USB_GINTMSK_RXFLVLMSK_SIZE 0x1 -#define GC_USB_GINTMSK_RXFLVLMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_RXFLVLMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_UNKNOWN5_LSB 0x5 -#define GC_USB_GINTMSK_UNKNOWN5_MASK 0x20 -#define GC_USB_GINTMSK_UNKNOWN5_SIZE 0x1 -#define GC_USB_GINTMSK_UNKNOWN5_DEFAULT 0x0 -#define GC_USB_GINTMSK_UNKNOWN5_OFFSET 0x18 -#define GC_USB_GINTMSK_GINNAKEFFMSK_LSB 0x6 -#define GC_USB_GINTMSK_GINNAKEFFMSK_MASK 0x40 -#define GC_USB_GINTMSK_GINNAKEFFMSK_SIZE 0x1 -#define GC_USB_GINTMSK_GINNAKEFFMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_GINNAKEFFMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_GOUTNAKEFFMSK_LSB 0x7 -#define GC_USB_GINTMSK_GOUTNAKEFFMSK_MASK 0x80 -#define GC_USB_GINTMSK_GOUTNAKEFFMSK_SIZE 0x1 -#define GC_USB_GINTMSK_GOUTNAKEFFMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_GOUTNAKEFFMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_ERLYSUSPMSK_LSB 0xa -#define GC_USB_GINTMSK_ERLYSUSPMSK_MASK 0x400 -#define GC_USB_GINTMSK_ERLYSUSPMSK_SIZE 0x1 -#define GC_USB_GINTMSK_ERLYSUSPMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_ERLYSUSPMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_USBSUSPMSK_LSB 0xb -#define GC_USB_GINTMSK_USBSUSPMSK_MASK 0x800 -#define GC_USB_GINTMSK_USBSUSPMSK_SIZE 0x1 -#define GC_USB_GINTMSK_USBSUSPMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_USBSUSPMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_USBRSTMSK_LSB 0xc -#define GC_USB_GINTMSK_USBRSTMSK_MASK 0x1000 -#define GC_USB_GINTMSK_USBRSTMSK_SIZE 0x1 -#define GC_USB_GINTMSK_USBRSTMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_USBRSTMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_ENUMDONEMSK_LSB 0xd -#define GC_USB_GINTMSK_ENUMDONEMSK_MASK 0x2000 -#define GC_USB_GINTMSK_ENUMDONEMSK_SIZE 0x1 -#define GC_USB_GINTMSK_ENUMDONEMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_ENUMDONEMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_ISOOUTDROPMSK_LSB 0xe -#define GC_USB_GINTMSK_ISOOUTDROPMSK_MASK 0x4000 -#define GC_USB_GINTMSK_ISOOUTDROPMSK_SIZE 0x1 -#define GC_USB_GINTMSK_ISOOUTDROPMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_ISOOUTDROPMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_EOPFMSK_LSB 0xf -#define GC_USB_GINTMSK_EOPFMSK_MASK 0x8000 -#define GC_USB_GINTMSK_EOPFMSK_SIZE 0x1 -#define GC_USB_GINTMSK_EOPFMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_EOPFMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_UNKNOWN16_LSB 0x10 -#define GC_USB_GINTMSK_UNKNOWN16_MASK 0x10000 -#define GC_USB_GINTMSK_UNKNOWN16_SIZE 0x1 -#define GC_USB_GINTMSK_UNKNOWN16_DEFAULT 0x0 -#define GC_USB_GINTMSK_UNKNOWN16_OFFSET 0x18 -#define GC_USB_GINTMSK_EPMISMSK_LSB 0x11 -#define GC_USB_GINTMSK_EPMISMSK_MASK 0x20000 -#define GC_USB_GINTMSK_EPMISMSK_SIZE 0x1 -#define GC_USB_GINTMSK_EPMISMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_EPMISMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_IEPINTMSK_LSB 0x12 -#define GC_USB_GINTMSK_IEPINTMSK_MASK 0x40000 -#define GC_USB_GINTMSK_IEPINTMSK_SIZE 0x1 -#define GC_USB_GINTMSK_IEPINTMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_IEPINTMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_OEPINTMSK_LSB 0x13 -#define GC_USB_GINTMSK_OEPINTMSK_MASK 0x80000 -#define GC_USB_GINTMSK_OEPINTMSK_SIZE 0x1 -#define GC_USB_GINTMSK_OEPINTMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_OEPINTMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_INCOMPISOINMSK_LSB 0x14 -#define GC_USB_GINTMSK_INCOMPISOINMSK_MASK 0x100000 -#define GC_USB_GINTMSK_INCOMPISOINMSK_SIZE 0x1 -#define GC_USB_GINTMSK_INCOMPISOINMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_INCOMPISOINMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_LSB 0x15 -#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_MASK 0x200000 -#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_SIZE 0x1 -#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_FETSUSPMSK_LSB 0x16 -#define GC_USB_GINTMSK_FETSUSPMSK_MASK 0x400000 -#define GC_USB_GINTMSK_FETSUSPMSK_SIZE 0x1 -#define GC_USB_GINTMSK_FETSUSPMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_FETSUSPMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_RESETDETMSK_LSB 0x17 -#define GC_USB_GINTMSK_RESETDETMSK_MASK 0x800000 -#define GC_USB_GINTMSK_RESETDETMSK_SIZE 0x1 -#define GC_USB_GINTMSK_RESETDETMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_RESETDETMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_LSB 0x1c -#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_MASK 0x10000000 -#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_SIZE 0x1 -#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_DISCONNINTMSK_LSB 0x1d -#define GC_USB_GINTMSK_DISCONNINTMSK_MASK 0x20000000 -#define GC_USB_GINTMSK_DISCONNINTMSK_SIZE 0x1 -#define GC_USB_GINTMSK_DISCONNINTMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_DISCONNINTMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_SESSREQINTMSK_LSB 0x1e -#define GC_USB_GINTMSK_SESSREQINTMSK_MASK 0x40000000 -#define GC_USB_GINTMSK_SESSREQINTMSK_SIZE 0x1 -#define GC_USB_GINTMSK_SESSREQINTMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_SESSREQINTMSK_OFFSET 0x18 -#define GC_USB_GINTMSK_WKUPINTMSK_LSB 0x1f -#define GC_USB_GINTMSK_WKUPINTMSK_MASK 0x80000000 -#define GC_USB_GINTMSK_WKUPINTMSK_SIZE 0x1 -#define GC_USB_GINTMSK_WKUPINTMSK_DEFAULT 0x0 -#define GC_USB_GINTMSK_WKUPINTMSK_OFFSET 0x18 -#define GC_USB_GRXSTSR_CHNUM_LSB 0x0 -#define GC_USB_GRXSTSR_CHNUM_MASK 0xf -#define GC_USB_GRXSTSR_CHNUM_SIZE 0x4 -#define GC_USB_GRXSTSR_CHNUM_DEFAULT 0x0 -#define GC_USB_GRXSTSR_CHNUM_OFFSET 0x1c -#define GC_USB_GRXSTSR_BCNT_LSB 0x4 -#define GC_USB_GRXSTSR_BCNT_MASK 0x7ff0 -#define GC_USB_GRXSTSR_BCNT_SIZE 0xb -#define GC_USB_GRXSTSR_BCNT_DEFAULT 0x0 -#define GC_USB_GRXSTSR_BCNT_OFFSET 0x1c -#define GC_USB_GRXSTSR_DPID_LSB 0xf -#define GC_USB_GRXSTSR_DPID_MASK 0x18000 -#define GC_USB_GRXSTSR_DPID_SIZE 0x2 -#define GC_USB_GRXSTSR_DPID_DEFAULT 0x0 -#define GC_USB_GRXSTSR_DPID_OFFSET 0x1c -#define GC_USB_GRXSTSR_PKTSTS_LSB 0x11 -#define GC_USB_GRXSTSR_PKTSTS_MASK 0x1e0000 -#define GC_USB_GRXSTSR_PKTSTS_SIZE 0x4 -#define GC_USB_GRXSTSR_PKTSTS_DEFAULT 0x0 -#define GC_USB_GRXSTSR_PKTSTS_OFFSET 0x1c -#define GC_USB_GRXSTSR_FN_LSB 0x15 -#define GC_USB_GRXSTSR_FN_MASK 0x1e00000 -#define GC_USB_GRXSTSR_FN_SIZE 0x4 -#define GC_USB_GRXSTSR_FN_DEFAULT 0x0 -#define GC_USB_GRXSTSR_FN_OFFSET 0x1c -#define GC_USB_GRXSTSP_CHNUM_LSB 0x0 -#define GC_USB_GRXSTSP_CHNUM_MASK 0xf -#define GC_USB_GRXSTSP_CHNUM_SIZE 0x4 -#define GC_USB_GRXSTSP_CHNUM_DEFAULT 0x0 -#define GC_USB_GRXSTSP_CHNUM_OFFSET 0x20 -#define GC_USB_GRXSTSP_BCNT_LSB 0x4 -#define GC_USB_GRXSTSP_BCNT_MASK 0x7ff0 -#define GC_USB_GRXSTSP_BCNT_SIZE 0xb -#define GC_USB_GRXSTSP_BCNT_DEFAULT 0x0 -#define GC_USB_GRXSTSP_BCNT_OFFSET 0x20 -#define GC_USB_GRXSTSP_DPID_LSB 0xf -#define GC_USB_GRXSTSP_DPID_MASK 0x18000 -#define GC_USB_GRXSTSP_DPID_SIZE 0x2 -#define GC_USB_GRXSTSP_DPID_DEFAULT 0x0 -#define GC_USB_GRXSTSP_DPID_OFFSET 0x20 -#define GC_USB_GRXSTSP_PKTSTS_LSB 0x11 -#define GC_USB_GRXSTSP_PKTSTS_MASK 0x1e0000 -#define GC_USB_GRXSTSP_PKTSTS_SIZE 0x4 -#define GC_USB_GRXSTSP_PKTSTS_DEFAULT 0x0 -#define GC_USB_GRXSTSP_PKTSTS_OFFSET 0x20 -#define GC_USB_GRXSTSP_FN_LSB 0x15 -#define GC_USB_GRXSTSP_FN_MASK 0x1e00000 -#define GC_USB_GRXSTSP_FN_SIZE 0x4 -#define GC_USB_GRXSTSP_FN_DEFAULT 0x0 -#define GC_USB_GRXSTSP_FN_OFFSET 0x20 -#define GC_USB_GRXFSIZ_RXFDEP_LSB 0x0 -#define GC_USB_GRXFSIZ_RXFDEP_MASK 0x7ff -#define GC_USB_GRXFSIZ_RXFDEP_SIZE 0xb -#define GC_USB_GRXFSIZ_RXFDEP_DEFAULT 0x0 -#define GC_USB_GRXFSIZ_RXFDEP_OFFSET 0x24 -#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_LSB 0x0 -#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_MASK 0xffff -#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_SIZE 0x10 -#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_DEFAULT 0x0 -#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_OFFSET 0x28 -#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_LSB 0x10 -#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_MASK 0xffff0000 -#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_SIZE 0x10 -#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_DEFAULT 0x0 -#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_OFFSET 0x28 +#define GC_USB_GRSTCTL_CSFTRST_LSB 0x0 +#define GC_USB_GRSTCTL_CSFTRST_MASK 0x1 +#define GC_USB_GRSTCTL_CSFTRST_SIZE 0x1 +#define GC_USB_GRSTCTL_CSFTRST_DEFAULT 0x0 +#define GC_USB_GRSTCTL_CSFTRST_OFFSET 0x10 +#define GC_USB_GRSTCTL_PIUFSSFTRST_LSB 0x1 +#define GC_USB_GRSTCTL_PIUFSSFTRST_MASK 0x2 +#define GC_USB_GRSTCTL_PIUFSSFTRST_SIZE 0x1 +#define GC_USB_GRSTCTL_PIUFSSFTRST_DEFAULT 0x0 +#define GC_USB_GRSTCTL_PIUFSSFTRST_OFFSET 0x10 +#define GC_USB_GRSTCTL_RXFFLSH_LSB 0x4 +#define GC_USB_GRSTCTL_RXFFLSH_MASK 0x10 +#define GC_USB_GRSTCTL_RXFFLSH_SIZE 0x1 +#define GC_USB_GRSTCTL_RXFFLSH_DEFAULT 0x0 +#define GC_USB_GRSTCTL_RXFFLSH_OFFSET 0x10 +#define GC_USB_GRSTCTL_TXFFLSH_LSB 0x5 +#define GC_USB_GRSTCTL_TXFFLSH_MASK 0x20 +#define GC_USB_GRSTCTL_TXFFLSH_SIZE 0x1 +#define GC_USB_GRSTCTL_TXFFLSH_DEFAULT 0x0 +#define GC_USB_GRSTCTL_TXFFLSH_OFFSET 0x10 +#define GC_USB_GRSTCTL_TXFNUM_LSB 0x6 +#define GC_USB_GRSTCTL_TXFNUM_MASK 0x7c0 +#define GC_USB_GRSTCTL_TXFNUM_SIZE 0x5 +#define GC_USB_GRSTCTL_TXFNUM_DEFAULT 0x0 +#define GC_USB_GRSTCTL_TXFNUM_OFFSET 0x10 +#define GC_USB_GRSTCTL_DMAREQ_LSB 0x1e +#define GC_USB_GRSTCTL_DMAREQ_MASK 0x40000000 +#define GC_USB_GRSTCTL_DMAREQ_SIZE 0x1 +#define GC_USB_GRSTCTL_DMAREQ_DEFAULT 0x0 +#define GC_USB_GRSTCTL_DMAREQ_OFFSET 0x10 +#define GC_USB_GRSTCTL_AHBIDLE_LSB 0x1f +#define GC_USB_GRSTCTL_AHBIDLE_MASK 0x80000000 +#define GC_USB_GRSTCTL_AHBIDLE_SIZE 0x1 +#define GC_USB_GRSTCTL_AHBIDLE_DEFAULT 0x0 +#define GC_USB_GRSTCTL_AHBIDLE_OFFSET 0x10 +#define GC_USB_GINTSTS_CURMOD_LSB 0x0 +#define GC_USB_GINTSTS_CURMOD_MASK 0x1 +#define GC_USB_GINTSTS_CURMOD_SIZE 0x1 +#define GC_USB_GINTSTS_CURMOD_DEFAULT 0x0 +#define GC_USB_GINTSTS_CURMOD_OFFSET 0x14 +#define GC_USB_GINTSTS_MODEMIS_LSB 0x1 +#define GC_USB_GINTSTS_MODEMIS_MASK 0x2 +#define GC_USB_GINTSTS_MODEMIS_SIZE 0x1 +#define GC_USB_GINTSTS_MODEMIS_DEFAULT 0x0 +#define GC_USB_GINTSTS_MODEMIS_OFFSET 0x14 +#define GC_USB_GINTSTS_OTGINT_LSB 0x2 +#define GC_USB_GINTSTS_OTGINT_MASK 0x4 +#define GC_USB_GINTSTS_OTGINT_SIZE 0x1 +#define GC_USB_GINTSTS_OTGINT_DEFAULT 0x0 +#define GC_USB_GINTSTS_OTGINT_OFFSET 0x14 +#define GC_USB_GINTSTS_SOF_LSB 0x3 +#define GC_USB_GINTSTS_SOF_MASK 0x8 +#define GC_USB_GINTSTS_SOF_SIZE 0x1 +#define GC_USB_GINTSTS_SOF_DEFAULT 0x0 +#define GC_USB_GINTSTS_SOF_OFFSET 0x14 +#define GC_USB_GINTSTS_RXFLVL_LSB 0x4 +#define GC_USB_GINTSTS_RXFLVL_MASK 0x10 +#define GC_USB_GINTSTS_RXFLVL_SIZE 0x1 +#define GC_USB_GINTSTS_RXFLVL_DEFAULT 0x0 +#define GC_USB_GINTSTS_RXFLVL_OFFSET 0x14 +#define GC_USB_GINTSTS_GINNAKEFF_LSB 0x6 +#define GC_USB_GINTSTS_GINNAKEFF_MASK 0x40 +#define GC_USB_GINTSTS_GINNAKEFF_SIZE 0x1 +#define GC_USB_GINTSTS_GINNAKEFF_DEFAULT 0x0 +#define GC_USB_GINTSTS_GINNAKEFF_OFFSET 0x14 +#define GC_USB_GINTSTS_GOUTNAKEFF_LSB 0x7 +#define GC_USB_GINTSTS_GOUTNAKEFF_MASK 0x80 +#define GC_USB_GINTSTS_GOUTNAKEFF_SIZE 0x1 +#define GC_USB_GINTSTS_GOUTNAKEFF_DEFAULT 0x0 +#define GC_USB_GINTSTS_GOUTNAKEFF_OFFSET 0x14 +#define GC_USB_GINTSTS_ERLYSUSP_LSB 0xa +#define GC_USB_GINTSTS_ERLYSUSP_MASK 0x400 +#define GC_USB_GINTSTS_ERLYSUSP_SIZE 0x1 +#define GC_USB_GINTSTS_ERLYSUSP_DEFAULT 0x0 +#define GC_USB_GINTSTS_ERLYSUSP_OFFSET 0x14 +#define GC_USB_GINTSTS_USBSUSP_LSB 0xb +#define GC_USB_GINTSTS_USBSUSP_MASK 0x800 +#define GC_USB_GINTSTS_USBSUSP_SIZE 0x1 +#define GC_USB_GINTSTS_USBSUSP_DEFAULT 0x0 +#define GC_USB_GINTSTS_USBSUSP_OFFSET 0x14 +#define GC_USB_GINTSTS_USBRST_LSB 0xc +#define GC_USB_GINTSTS_USBRST_MASK 0x1000 +#define GC_USB_GINTSTS_USBRST_SIZE 0x1 +#define GC_USB_GINTSTS_USBRST_DEFAULT 0x0 +#define GC_USB_GINTSTS_USBRST_OFFSET 0x14 +#define GC_USB_GINTSTS_ENUMDONE_LSB 0xd +#define GC_USB_GINTSTS_ENUMDONE_MASK 0x2000 +#define GC_USB_GINTSTS_ENUMDONE_SIZE 0x1 +#define GC_USB_GINTSTS_ENUMDONE_DEFAULT 0x0 +#define GC_USB_GINTSTS_ENUMDONE_OFFSET 0x14 +#define GC_USB_GINTSTS_ISOOUTDROP_LSB 0xe +#define GC_USB_GINTSTS_ISOOUTDROP_MASK 0x4000 +#define GC_USB_GINTSTS_ISOOUTDROP_SIZE 0x1 +#define GC_USB_GINTSTS_ISOOUTDROP_DEFAULT 0x0 +#define GC_USB_GINTSTS_ISOOUTDROP_OFFSET 0x14 +#define GC_USB_GINTSTS_EOPF_LSB 0xf +#define GC_USB_GINTSTS_EOPF_MASK 0x8000 +#define GC_USB_GINTSTS_EOPF_SIZE 0x1 +#define GC_USB_GINTSTS_EOPF_DEFAULT 0x0 +#define GC_USB_GINTSTS_EOPF_OFFSET 0x14 +#define GC_USB_GINTSTS_EPMIS_LSB 0x11 +#define GC_USB_GINTSTS_EPMIS_MASK 0x20000 +#define GC_USB_GINTSTS_EPMIS_SIZE 0x1 +#define GC_USB_GINTSTS_EPMIS_DEFAULT 0x0 +#define GC_USB_GINTSTS_EPMIS_OFFSET 0x14 +#define GC_USB_GINTSTS_IEPINT_LSB 0x12 +#define GC_USB_GINTSTS_IEPINT_MASK 0x40000 +#define GC_USB_GINTSTS_IEPINT_SIZE 0x1 +#define GC_USB_GINTSTS_IEPINT_DEFAULT 0x0 +#define GC_USB_GINTSTS_IEPINT_OFFSET 0x14 +#define GC_USB_GINTSTS_OEPINT_LSB 0x13 +#define GC_USB_GINTSTS_OEPINT_MASK 0x80000 +#define GC_USB_GINTSTS_OEPINT_SIZE 0x1 +#define GC_USB_GINTSTS_OEPINT_DEFAULT 0x0 +#define GC_USB_GINTSTS_OEPINT_OFFSET 0x14 +#define GC_USB_GINTSTS_INCOMPISOIN_LSB 0x14 +#define GC_USB_GINTSTS_INCOMPISOIN_MASK 0x100000 +#define GC_USB_GINTSTS_INCOMPISOIN_SIZE 0x1 +#define GC_USB_GINTSTS_INCOMPISOIN_DEFAULT 0x0 +#define GC_USB_GINTSTS_INCOMPISOIN_OFFSET 0x14 +#define GC_USB_GINTSTS_INCOMPLP_LSB 0x15 +#define GC_USB_GINTSTS_INCOMPLP_MASK 0x200000 +#define GC_USB_GINTSTS_INCOMPLP_SIZE 0x1 +#define GC_USB_GINTSTS_INCOMPLP_DEFAULT 0x0 +#define GC_USB_GINTSTS_INCOMPLP_OFFSET 0x14 +#define GC_USB_GINTSTS_FETSUSP_LSB 0x16 +#define GC_USB_GINTSTS_FETSUSP_MASK 0x400000 +#define GC_USB_GINTSTS_FETSUSP_SIZE 0x1 +#define GC_USB_GINTSTS_FETSUSP_DEFAULT 0x0 +#define GC_USB_GINTSTS_FETSUSP_OFFSET 0x14 +#define GC_USB_GINTSTS_RESETDET_LSB 0x17 +#define GC_USB_GINTSTS_RESETDET_MASK 0x800000 +#define GC_USB_GINTSTS_RESETDET_SIZE 0x1 +#define GC_USB_GINTSTS_RESETDET_DEFAULT 0x0 +#define GC_USB_GINTSTS_RESETDET_OFFSET 0x14 +#define GC_USB_GINTSTS_CONIDSTSCHNG_LSB 0x1c +#define GC_USB_GINTSTS_CONIDSTSCHNG_MASK 0x10000000 +#define GC_USB_GINTSTS_CONIDSTSCHNG_SIZE 0x1 +#define GC_USB_GINTSTS_CONIDSTSCHNG_DEFAULT 0x0 +#define GC_USB_GINTSTS_CONIDSTSCHNG_OFFSET 0x14 +#define GC_USB_GINTSTS_SESSREQINT_LSB 0x1e +#define GC_USB_GINTSTS_SESSREQINT_MASK 0x40000000 +#define GC_USB_GINTSTS_SESSREQINT_SIZE 0x1 +#define GC_USB_GINTSTS_SESSREQINT_DEFAULT 0x0 +#define GC_USB_GINTSTS_SESSREQINT_OFFSET 0x14 +#define GC_USB_GINTSTS_WKUPINT_LSB 0x1f +#define GC_USB_GINTSTS_WKUPINT_MASK 0x80000000 +#define GC_USB_GINTSTS_WKUPINT_SIZE 0x1 +#define GC_USB_GINTSTS_WKUPINT_DEFAULT 0x0 +#define GC_USB_GINTSTS_WKUPINT_OFFSET 0x14 +#define GC_USB_GINTMSK_MODEMISMSK_LSB 0x1 +#define GC_USB_GINTMSK_MODEMISMSK_MASK 0x2 +#define GC_USB_GINTMSK_MODEMISMSK_SIZE 0x1 +#define GC_USB_GINTMSK_MODEMISMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_MODEMISMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_OTGINTMSK_LSB 0x2 +#define GC_USB_GINTMSK_OTGINTMSK_MASK 0x4 +#define GC_USB_GINTMSK_OTGINTMSK_SIZE 0x1 +#define GC_USB_GINTMSK_OTGINTMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_OTGINTMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_SOFMSK_LSB 0x3 +#define GC_USB_GINTMSK_SOFMSK_MASK 0x8 +#define GC_USB_GINTMSK_SOFMSK_SIZE 0x1 +#define GC_USB_GINTMSK_SOFMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_SOFMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_RXFLVLMSK_LSB 0x4 +#define GC_USB_GINTMSK_RXFLVLMSK_MASK 0x10 +#define GC_USB_GINTMSK_RXFLVLMSK_SIZE 0x1 +#define GC_USB_GINTMSK_RXFLVLMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_RXFLVLMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_UNKNOWN5_LSB 0x5 +#define GC_USB_GINTMSK_UNKNOWN5_MASK 0x20 +#define GC_USB_GINTMSK_UNKNOWN5_SIZE 0x1 +#define GC_USB_GINTMSK_UNKNOWN5_DEFAULT 0x0 +#define GC_USB_GINTMSK_UNKNOWN5_OFFSET 0x18 +#define GC_USB_GINTMSK_GINNAKEFFMSK_LSB 0x6 +#define GC_USB_GINTMSK_GINNAKEFFMSK_MASK 0x40 +#define GC_USB_GINTMSK_GINNAKEFFMSK_SIZE 0x1 +#define GC_USB_GINTMSK_GINNAKEFFMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_GINNAKEFFMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_GOUTNAKEFFMSK_LSB 0x7 +#define GC_USB_GINTMSK_GOUTNAKEFFMSK_MASK 0x80 +#define GC_USB_GINTMSK_GOUTNAKEFFMSK_SIZE 0x1 +#define GC_USB_GINTMSK_GOUTNAKEFFMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_GOUTNAKEFFMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_ERLYSUSPMSK_LSB 0xa +#define GC_USB_GINTMSK_ERLYSUSPMSK_MASK 0x400 +#define GC_USB_GINTMSK_ERLYSUSPMSK_SIZE 0x1 +#define GC_USB_GINTMSK_ERLYSUSPMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_ERLYSUSPMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_USBSUSPMSK_LSB 0xb +#define GC_USB_GINTMSK_USBSUSPMSK_MASK 0x800 +#define GC_USB_GINTMSK_USBSUSPMSK_SIZE 0x1 +#define GC_USB_GINTMSK_USBSUSPMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_USBSUSPMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_USBRSTMSK_LSB 0xc +#define GC_USB_GINTMSK_USBRSTMSK_MASK 0x1000 +#define GC_USB_GINTMSK_USBRSTMSK_SIZE 0x1 +#define GC_USB_GINTMSK_USBRSTMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_USBRSTMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_ENUMDONEMSK_LSB 0xd +#define GC_USB_GINTMSK_ENUMDONEMSK_MASK 0x2000 +#define GC_USB_GINTMSK_ENUMDONEMSK_SIZE 0x1 +#define GC_USB_GINTMSK_ENUMDONEMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_ENUMDONEMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_ISOOUTDROPMSK_LSB 0xe +#define GC_USB_GINTMSK_ISOOUTDROPMSK_MASK 0x4000 +#define GC_USB_GINTMSK_ISOOUTDROPMSK_SIZE 0x1 +#define GC_USB_GINTMSK_ISOOUTDROPMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_ISOOUTDROPMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_EOPFMSK_LSB 0xf +#define GC_USB_GINTMSK_EOPFMSK_MASK 0x8000 +#define GC_USB_GINTMSK_EOPFMSK_SIZE 0x1 +#define GC_USB_GINTMSK_EOPFMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_EOPFMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_UNKNOWN16_LSB 0x10 +#define GC_USB_GINTMSK_UNKNOWN16_MASK 0x10000 +#define GC_USB_GINTMSK_UNKNOWN16_SIZE 0x1 +#define GC_USB_GINTMSK_UNKNOWN16_DEFAULT 0x0 +#define GC_USB_GINTMSK_UNKNOWN16_OFFSET 0x18 +#define GC_USB_GINTMSK_EPMISMSK_LSB 0x11 +#define GC_USB_GINTMSK_EPMISMSK_MASK 0x20000 +#define GC_USB_GINTMSK_EPMISMSK_SIZE 0x1 +#define GC_USB_GINTMSK_EPMISMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_EPMISMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_IEPINTMSK_LSB 0x12 +#define GC_USB_GINTMSK_IEPINTMSK_MASK 0x40000 +#define GC_USB_GINTMSK_IEPINTMSK_SIZE 0x1 +#define GC_USB_GINTMSK_IEPINTMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_IEPINTMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_OEPINTMSK_LSB 0x13 +#define GC_USB_GINTMSK_OEPINTMSK_MASK 0x80000 +#define GC_USB_GINTMSK_OEPINTMSK_SIZE 0x1 +#define GC_USB_GINTMSK_OEPINTMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_OEPINTMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_INCOMPISOINMSK_LSB 0x14 +#define GC_USB_GINTMSK_INCOMPISOINMSK_MASK 0x100000 +#define GC_USB_GINTMSK_INCOMPISOINMSK_SIZE 0x1 +#define GC_USB_GINTMSK_INCOMPISOINMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_INCOMPISOINMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_LSB 0x15 +#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_MASK 0x200000 +#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_SIZE 0x1 +#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_INCOMPLISOOUTMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_FETSUSPMSK_LSB 0x16 +#define GC_USB_GINTMSK_FETSUSPMSK_MASK 0x400000 +#define GC_USB_GINTMSK_FETSUSPMSK_SIZE 0x1 +#define GC_USB_GINTMSK_FETSUSPMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_FETSUSPMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_RESETDETMSK_LSB 0x17 +#define GC_USB_GINTMSK_RESETDETMSK_MASK 0x800000 +#define GC_USB_GINTMSK_RESETDETMSK_SIZE 0x1 +#define GC_USB_GINTMSK_RESETDETMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_RESETDETMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_LSB 0x1c +#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_MASK 0x10000000 +#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_SIZE 0x1 +#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_CONIDSTSCHNGMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_DISCONNINTMSK_LSB 0x1d +#define GC_USB_GINTMSK_DISCONNINTMSK_MASK 0x20000000 +#define GC_USB_GINTMSK_DISCONNINTMSK_SIZE 0x1 +#define GC_USB_GINTMSK_DISCONNINTMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_DISCONNINTMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_SESSREQINTMSK_LSB 0x1e +#define GC_USB_GINTMSK_SESSREQINTMSK_MASK 0x40000000 +#define GC_USB_GINTMSK_SESSREQINTMSK_SIZE 0x1 +#define GC_USB_GINTMSK_SESSREQINTMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_SESSREQINTMSK_OFFSET 0x18 +#define GC_USB_GINTMSK_WKUPINTMSK_LSB 0x1f +#define GC_USB_GINTMSK_WKUPINTMSK_MASK 0x80000000 +#define GC_USB_GINTMSK_WKUPINTMSK_SIZE 0x1 +#define GC_USB_GINTMSK_WKUPINTMSK_DEFAULT 0x0 +#define GC_USB_GINTMSK_WKUPINTMSK_OFFSET 0x18 +#define GC_USB_GRXSTSR_CHNUM_LSB 0x0 +#define GC_USB_GRXSTSR_CHNUM_MASK 0xf +#define GC_USB_GRXSTSR_CHNUM_SIZE 0x4 +#define GC_USB_GRXSTSR_CHNUM_DEFAULT 0x0 +#define GC_USB_GRXSTSR_CHNUM_OFFSET 0x1c +#define GC_USB_GRXSTSR_BCNT_LSB 0x4 +#define GC_USB_GRXSTSR_BCNT_MASK 0x7ff0 +#define GC_USB_GRXSTSR_BCNT_SIZE 0xb +#define GC_USB_GRXSTSR_BCNT_DEFAULT 0x0 +#define GC_USB_GRXSTSR_BCNT_OFFSET 0x1c +#define GC_USB_GRXSTSR_DPID_LSB 0xf +#define GC_USB_GRXSTSR_DPID_MASK 0x18000 +#define GC_USB_GRXSTSR_DPID_SIZE 0x2 +#define GC_USB_GRXSTSR_DPID_DEFAULT 0x0 +#define GC_USB_GRXSTSR_DPID_OFFSET 0x1c +#define GC_USB_GRXSTSR_PKTSTS_LSB 0x11 +#define GC_USB_GRXSTSR_PKTSTS_MASK 0x1e0000 +#define GC_USB_GRXSTSR_PKTSTS_SIZE 0x4 +#define GC_USB_GRXSTSR_PKTSTS_DEFAULT 0x0 +#define GC_USB_GRXSTSR_PKTSTS_OFFSET 0x1c +#define GC_USB_GRXSTSR_FN_LSB 0x15 +#define GC_USB_GRXSTSR_FN_MASK 0x1e00000 +#define GC_USB_GRXSTSR_FN_SIZE 0x4 +#define GC_USB_GRXSTSR_FN_DEFAULT 0x0 +#define GC_USB_GRXSTSR_FN_OFFSET 0x1c +#define GC_USB_GRXSTSP_CHNUM_LSB 0x0 +#define GC_USB_GRXSTSP_CHNUM_MASK 0xf +#define GC_USB_GRXSTSP_CHNUM_SIZE 0x4 +#define GC_USB_GRXSTSP_CHNUM_DEFAULT 0x0 +#define GC_USB_GRXSTSP_CHNUM_OFFSET 0x20 +#define GC_USB_GRXSTSP_BCNT_LSB 0x4 +#define GC_USB_GRXSTSP_BCNT_MASK 0x7ff0 +#define GC_USB_GRXSTSP_BCNT_SIZE 0xb +#define GC_USB_GRXSTSP_BCNT_DEFAULT 0x0 +#define GC_USB_GRXSTSP_BCNT_OFFSET 0x20 +#define GC_USB_GRXSTSP_DPID_LSB 0xf +#define GC_USB_GRXSTSP_DPID_MASK 0x18000 +#define GC_USB_GRXSTSP_DPID_SIZE 0x2 +#define GC_USB_GRXSTSP_DPID_DEFAULT 0x0 +#define GC_USB_GRXSTSP_DPID_OFFSET 0x20 +#define GC_USB_GRXSTSP_PKTSTS_LSB 0x11 +#define GC_USB_GRXSTSP_PKTSTS_MASK 0x1e0000 +#define GC_USB_GRXSTSP_PKTSTS_SIZE 0x4 +#define GC_USB_GRXSTSP_PKTSTS_DEFAULT 0x0 +#define GC_USB_GRXSTSP_PKTSTS_OFFSET 0x20 +#define GC_USB_GRXSTSP_FN_LSB 0x15 +#define GC_USB_GRXSTSP_FN_MASK 0x1e00000 +#define GC_USB_GRXSTSP_FN_SIZE 0x4 +#define GC_USB_GRXSTSP_FN_DEFAULT 0x0 +#define GC_USB_GRXSTSP_FN_OFFSET 0x20 +#define GC_USB_GRXFSIZ_RXFDEP_LSB 0x0 +#define GC_USB_GRXFSIZ_RXFDEP_MASK 0x7ff +#define GC_USB_GRXFSIZ_RXFDEP_SIZE 0xb +#define GC_USB_GRXFSIZ_RXFDEP_DEFAULT 0x0 +#define GC_USB_GRXFSIZ_RXFDEP_OFFSET 0x24 +#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_LSB 0x0 +#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_MASK 0xffff +#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_SIZE 0x10 +#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_DEFAULT 0x0 +#define GC_USB_GNPTXFSIZ_INEPTXF0STADDR_OFFSET 0x28 +#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_LSB 0x10 +#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_MASK 0xffff0000 +#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_SIZE 0x10 +#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_DEFAULT 0x0 +#define GC_USB_GNPTXFSIZ_INEPTXF0DEP_OFFSET 0x28 -#define GC_USB_GUID_GUID_LSB 0x0 -#define GC_USB_GUID_GUID_MASK 0xffffffff -#define GC_USB_GUID_GUID_SIZE 0x20 -#define GC_USB_GUID_GUID_DEFAULT 0x0 -#define GC_USB_GUID_GUID_OFFSET 0x3c -#define GC_USB_GSNPSID_SYNOPSYSID_LSB 0x0 -#define GC_USB_GSNPSID_SYNOPSYSID_MASK 0xffffffff -#define GC_USB_GSNPSID_SYNOPSYSID_SIZE 0x20 -#define GC_USB_GSNPSID_SYNOPSYSID_DEFAULT 0x0 -#define GC_USB_GSNPSID_SYNOPSYSID_OFFSET 0x40 -#define GC_USB_GHWCFG1_EPDIR_LSB 0x0 -#define GC_USB_GHWCFG1_EPDIR_MASK 0xffffffff -#define GC_USB_GHWCFG1_EPDIR_SIZE 0x20 -#define GC_USB_GHWCFG1_EPDIR_DEFAULT 0x0 -#define GC_USB_GHWCFG1_EPDIR_OFFSET 0x44 -#define GC_USB_GHWCFG2_OTGMODE_LSB 0x0 -#define GC_USB_GHWCFG2_OTGMODE_MASK 0x7 -#define GC_USB_GHWCFG2_OTGMODE_SIZE 0x3 -#define GC_USB_GHWCFG2_OTGMODE_DEFAULT 0x0 -#define GC_USB_GHWCFG2_OTGMODE_OFFSET 0x48 -#define GC_USB_GHWCFG2_OTGARCH_LSB 0x3 -#define GC_USB_GHWCFG2_OTGARCH_MASK 0x18 -#define GC_USB_GHWCFG2_OTGARCH_SIZE 0x2 -#define GC_USB_GHWCFG2_OTGARCH_DEFAULT 0x0 -#define GC_USB_GHWCFG2_OTGARCH_OFFSET 0x48 -#define GC_USB_GHWCFG2_SINGPNT_LSB 0x5 -#define GC_USB_GHWCFG2_SINGPNT_MASK 0x20 -#define GC_USB_GHWCFG2_SINGPNT_SIZE 0x1 -#define GC_USB_GHWCFG2_SINGPNT_DEFAULT 0x0 -#define GC_USB_GHWCFG2_SINGPNT_OFFSET 0x48 -#define GC_USB_GHWCFG2_HSPHYTYPE_LSB 0x6 -#define GC_USB_GHWCFG2_HSPHYTYPE_MASK 0xc0 -#define GC_USB_GHWCFG2_HSPHYTYPE_SIZE 0x2 -#define GC_USB_GHWCFG2_HSPHYTYPE_DEFAULT 0x0 -#define GC_USB_GHWCFG2_HSPHYTYPE_OFFSET 0x48 -#define GC_USB_GHWCFG2_FSPHYTYPE_LSB 0x8 -#define GC_USB_GHWCFG2_FSPHYTYPE_MASK 0x300 -#define GC_USB_GHWCFG2_FSPHYTYPE_SIZE 0x2 -#define GC_USB_GHWCFG2_FSPHYTYPE_DEFAULT 0x0 -#define GC_USB_GHWCFG2_FSPHYTYPE_OFFSET 0x48 -#define GC_USB_GHWCFG2_NUMDEVEPS_LSB 0xa -#define GC_USB_GHWCFG2_NUMDEVEPS_MASK 0x3c00 -#define GC_USB_GHWCFG2_NUMDEVEPS_SIZE 0x4 -#define GC_USB_GHWCFG2_NUMDEVEPS_DEFAULT 0x0 -#define GC_USB_GHWCFG2_NUMDEVEPS_OFFSET 0x48 -#define GC_USB_GHWCFG2_NUMHSTCHNL_LSB 0xe -#define GC_USB_GHWCFG2_NUMHSTCHNL_MASK 0x3c000 -#define GC_USB_GHWCFG2_NUMHSTCHNL_SIZE 0x4 -#define GC_USB_GHWCFG2_NUMHSTCHNL_DEFAULT 0x0 -#define GC_USB_GHWCFG2_NUMHSTCHNL_OFFSET 0x48 -#define GC_USB_GHWCFG2_PERIOSUPPORT_LSB 0x12 -#define GC_USB_GHWCFG2_PERIOSUPPORT_MASK 0x40000 -#define GC_USB_GHWCFG2_PERIOSUPPORT_SIZE 0x1 -#define GC_USB_GHWCFG2_PERIOSUPPORT_DEFAULT 0x0 -#define GC_USB_GHWCFG2_PERIOSUPPORT_OFFSET 0x48 -#define GC_USB_GHWCFG2_DYNFIFOSIZING_LSB 0x13 -#define GC_USB_GHWCFG2_DYNFIFOSIZING_MASK 0x80000 -#define GC_USB_GHWCFG2_DYNFIFOSIZING_SIZE 0x1 -#define GC_USB_GHWCFG2_DYNFIFOSIZING_DEFAULT 0x0 -#define GC_USB_GHWCFG2_DYNFIFOSIZING_OFFSET 0x48 -#define GC_USB_GHWCFG2_MULTIPROCINTRPT_LSB 0x14 -#define GC_USB_GHWCFG2_MULTIPROCINTRPT_MASK 0x100000 -#define GC_USB_GHWCFG2_MULTIPROCINTRPT_SIZE 0x1 -#define GC_USB_GHWCFG2_MULTIPROCINTRPT_DEFAULT 0x0 -#define GC_USB_GHWCFG2_MULTIPROCINTRPT_OFFSET 0x48 -#define GC_USB_GHWCFG2_NPTXQDEPTH_LSB 0x16 -#define GC_USB_GHWCFG2_NPTXQDEPTH_MASK 0xc00000 -#define GC_USB_GHWCFG2_NPTXQDEPTH_SIZE 0x2 -#define GC_USB_GHWCFG2_NPTXQDEPTH_DEFAULT 0x0 -#define GC_USB_GHWCFG2_NPTXQDEPTH_OFFSET 0x48 -#define GC_USB_GHWCFG2_PTXQDEPTH_LSB 0x18 -#define GC_USB_GHWCFG2_PTXQDEPTH_MASK 0x3000000 -#define GC_USB_GHWCFG2_PTXQDEPTH_SIZE 0x2 -#define GC_USB_GHWCFG2_PTXQDEPTH_DEFAULT 0x0 -#define GC_USB_GHWCFG2_PTXQDEPTH_OFFSET 0x48 -#define GC_USB_GHWCFG2_TKNQDEPTH_LSB 0x1a -#define GC_USB_GHWCFG2_TKNQDEPTH_MASK 0x7c000000 -#define GC_USB_GHWCFG2_TKNQDEPTH_SIZE 0x5 -#define GC_USB_GHWCFG2_TKNQDEPTH_DEFAULT 0x0 -#define GC_USB_GHWCFG2_TKNQDEPTH_OFFSET 0x48 -#define GC_USB_GHWCFG3_XFERSIZEWIDTH_LSB 0x0 -#define GC_USB_GHWCFG3_XFERSIZEWIDTH_MASK 0xf -#define GC_USB_GHWCFG3_XFERSIZEWIDTH_SIZE 0x4 -#define GC_USB_GHWCFG3_XFERSIZEWIDTH_DEFAULT 0x0 -#define GC_USB_GHWCFG3_XFERSIZEWIDTH_OFFSET 0x4c -#define GC_USB_GHWCFG3_PKTSIZEWIDTH_LSB 0x4 -#define GC_USB_GHWCFG3_PKTSIZEWIDTH_MASK 0x70 -#define GC_USB_GHWCFG3_PKTSIZEWIDTH_SIZE 0x3 -#define GC_USB_GHWCFG3_PKTSIZEWIDTH_DEFAULT 0x0 -#define GC_USB_GHWCFG3_PKTSIZEWIDTH_OFFSET 0x4c -#define GC_USB_GHWCFG3_OTGEN_LSB 0x7 -#define GC_USB_GHWCFG3_OTGEN_MASK 0x80 -#define GC_USB_GHWCFG3_OTGEN_SIZE 0x1 -#define GC_USB_GHWCFG3_OTGEN_DEFAULT 0x0 -#define GC_USB_GHWCFG3_OTGEN_OFFSET 0x4c -#define GC_USB_GHWCFG3_I2CINTSEL_LSB 0x8 -#define GC_USB_GHWCFG3_I2CINTSEL_MASK 0x100 -#define GC_USB_GHWCFG3_I2CINTSEL_SIZE 0x1 -#define GC_USB_GHWCFG3_I2CINTSEL_DEFAULT 0x0 -#define GC_USB_GHWCFG3_I2CINTSEL_OFFSET 0x4c -#define GC_USB_GHWCFG3_VNDCTLSUPT_LSB 0x9 -#define GC_USB_GHWCFG3_VNDCTLSUPT_MASK 0x200 -#define GC_USB_GHWCFG3_VNDCTLSUPT_SIZE 0x1 -#define GC_USB_GHWCFG3_VNDCTLSUPT_DEFAULT 0x0 -#define GC_USB_GHWCFG3_VNDCTLSUPT_OFFSET 0x4c -#define GC_USB_GHWCFG3_OPTFEATURE_LSB 0xa -#define GC_USB_GHWCFG3_OPTFEATURE_MASK 0x400 -#define GC_USB_GHWCFG3_OPTFEATURE_SIZE 0x1 -#define GC_USB_GHWCFG3_OPTFEATURE_DEFAULT 0x0 -#define GC_USB_GHWCFG3_OPTFEATURE_OFFSET 0x4c -#define GC_USB_GHWCFG3_RSTTYPE_LSB 0xb -#define GC_USB_GHWCFG3_RSTTYPE_MASK 0x800 -#define GC_USB_GHWCFG3_RSTTYPE_SIZE 0x1 -#define GC_USB_GHWCFG3_RSTTYPE_DEFAULT 0x0 -#define GC_USB_GHWCFG3_RSTTYPE_OFFSET 0x4c -#define GC_USB_GHWCFG3_ADPSUPPORT_LSB 0xc -#define GC_USB_GHWCFG3_ADPSUPPORT_MASK 0x1000 -#define GC_USB_GHWCFG3_ADPSUPPORT_SIZE 0x1 -#define GC_USB_GHWCFG3_ADPSUPPORT_DEFAULT 0x0 -#define GC_USB_GHWCFG3_ADPSUPPORT_OFFSET 0x4c -#define GC_USB_GHWCFG3_HSICMODE_LSB 0xd -#define GC_USB_GHWCFG3_HSICMODE_MASK 0x2000 -#define GC_USB_GHWCFG3_HSICMODE_SIZE 0x1 -#define GC_USB_GHWCFG3_HSICMODE_DEFAULT 0x0 -#define GC_USB_GHWCFG3_HSICMODE_OFFSET 0x4c -#define GC_USB_GHWCFG3_BCSUPPORT_LSB 0xe -#define GC_USB_GHWCFG3_BCSUPPORT_MASK 0x4000 -#define GC_USB_GHWCFG3_BCSUPPORT_SIZE 0x1 -#define GC_USB_GHWCFG3_BCSUPPORT_DEFAULT 0x0 -#define GC_USB_GHWCFG3_BCSUPPORT_OFFSET 0x4c -#define GC_USB_GHWCFG3_LPMMODE_LSB 0xf -#define GC_USB_GHWCFG3_LPMMODE_MASK 0x8000 -#define GC_USB_GHWCFG3_LPMMODE_SIZE 0x1 -#define GC_USB_GHWCFG3_LPMMODE_DEFAULT 0x0 -#define GC_USB_GHWCFG3_LPMMODE_OFFSET 0x4c -#define GC_USB_GHWCFG3_DFIFODEPTH_LSB 0x10 -#define GC_USB_GHWCFG3_DFIFODEPTH_MASK 0xffff0000 -#define GC_USB_GHWCFG3_DFIFODEPTH_SIZE 0x10 -#define GC_USB_GHWCFG3_DFIFODEPTH_DEFAULT 0x0 -#define GC_USB_GHWCFG3_DFIFODEPTH_OFFSET 0x4c -#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_LSB 0x0 -#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_MASK 0xf -#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_SIZE 0x4 -#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_DEFAULT 0x0 -#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_OFFSET 0x50 -#define GC_USB_GHWCFG4_PARTIALPWRDN_LSB 0x4 -#define GC_USB_GHWCFG4_PARTIALPWRDN_MASK 0x10 -#define GC_USB_GHWCFG4_PARTIALPWRDN_SIZE 0x1 -#define GC_USB_GHWCFG4_PARTIALPWRDN_DEFAULT 0x0 -#define GC_USB_GHWCFG4_PARTIALPWRDN_OFFSET 0x50 -#define GC_USB_GHWCFG4_AHBFREQ_LSB 0x5 -#define GC_USB_GHWCFG4_AHBFREQ_MASK 0x20 -#define GC_USB_GHWCFG4_AHBFREQ_SIZE 0x1 -#define GC_USB_GHWCFG4_AHBFREQ_DEFAULT 0x0 -#define GC_USB_GHWCFG4_AHBFREQ_OFFSET 0x50 -#define GC_USB_GHWCFG4_HIBERNATION_LSB 0x6 -#define GC_USB_GHWCFG4_HIBERNATION_MASK 0x40 -#define GC_USB_GHWCFG4_HIBERNATION_SIZE 0x1 -#define GC_USB_GHWCFG4_HIBERNATION_DEFAULT 0x0 -#define GC_USB_GHWCFG4_HIBERNATION_OFFSET 0x50 -#define GC_USB_GHWCFG4_EXTENDEDHIBERNATION_LSB 0x7 -#define GC_USB_GHWCFG4_EXTENDEDHIBERNATION_MASK 0x80 -#define GC_USB_GHWCFG4_EXTENDEDHIBERNATION_SIZE 0x1 +#define GC_USB_GUID_GUID_LSB 0x0 +#define GC_USB_GUID_GUID_MASK 0xffffffff +#define GC_USB_GUID_GUID_SIZE 0x20 +#define GC_USB_GUID_GUID_DEFAULT 0x0 +#define GC_USB_GUID_GUID_OFFSET 0x3c +#define GC_USB_GSNPSID_SYNOPSYSID_LSB 0x0 +#define GC_USB_GSNPSID_SYNOPSYSID_MASK 0xffffffff +#define GC_USB_GSNPSID_SYNOPSYSID_SIZE 0x20 +#define GC_USB_GSNPSID_SYNOPSYSID_DEFAULT 0x0 +#define GC_USB_GSNPSID_SYNOPSYSID_OFFSET 0x40 +#define GC_USB_GHWCFG1_EPDIR_LSB 0x0 +#define GC_USB_GHWCFG1_EPDIR_MASK 0xffffffff +#define GC_USB_GHWCFG1_EPDIR_SIZE 0x20 +#define GC_USB_GHWCFG1_EPDIR_DEFAULT 0x0 +#define GC_USB_GHWCFG1_EPDIR_OFFSET 0x44 +#define GC_USB_GHWCFG2_OTGMODE_LSB 0x0 +#define GC_USB_GHWCFG2_OTGMODE_MASK 0x7 +#define GC_USB_GHWCFG2_OTGMODE_SIZE 0x3 +#define GC_USB_GHWCFG2_OTGMODE_DEFAULT 0x0 +#define GC_USB_GHWCFG2_OTGMODE_OFFSET 0x48 +#define GC_USB_GHWCFG2_OTGARCH_LSB 0x3 +#define GC_USB_GHWCFG2_OTGARCH_MASK 0x18 +#define GC_USB_GHWCFG2_OTGARCH_SIZE 0x2 +#define GC_USB_GHWCFG2_OTGARCH_DEFAULT 0x0 +#define GC_USB_GHWCFG2_OTGARCH_OFFSET 0x48 +#define GC_USB_GHWCFG2_SINGPNT_LSB 0x5 +#define GC_USB_GHWCFG2_SINGPNT_MASK 0x20 +#define GC_USB_GHWCFG2_SINGPNT_SIZE 0x1 +#define GC_USB_GHWCFG2_SINGPNT_DEFAULT 0x0 +#define GC_USB_GHWCFG2_SINGPNT_OFFSET 0x48 +#define GC_USB_GHWCFG2_HSPHYTYPE_LSB 0x6 +#define GC_USB_GHWCFG2_HSPHYTYPE_MASK 0xc0 +#define GC_USB_GHWCFG2_HSPHYTYPE_SIZE 0x2 +#define GC_USB_GHWCFG2_HSPHYTYPE_DEFAULT 0x0 +#define GC_USB_GHWCFG2_HSPHYTYPE_OFFSET 0x48 +#define GC_USB_GHWCFG2_FSPHYTYPE_LSB 0x8 +#define GC_USB_GHWCFG2_FSPHYTYPE_MASK 0x300 +#define GC_USB_GHWCFG2_FSPHYTYPE_SIZE 0x2 +#define GC_USB_GHWCFG2_FSPHYTYPE_DEFAULT 0x0 +#define GC_USB_GHWCFG2_FSPHYTYPE_OFFSET 0x48 +#define GC_USB_GHWCFG2_NUMDEVEPS_LSB 0xa +#define GC_USB_GHWCFG2_NUMDEVEPS_MASK 0x3c00 +#define GC_USB_GHWCFG2_NUMDEVEPS_SIZE 0x4 +#define GC_USB_GHWCFG2_NUMDEVEPS_DEFAULT 0x0 +#define GC_USB_GHWCFG2_NUMDEVEPS_OFFSET 0x48 +#define GC_USB_GHWCFG2_NUMHSTCHNL_LSB 0xe +#define GC_USB_GHWCFG2_NUMHSTCHNL_MASK 0x3c000 +#define GC_USB_GHWCFG2_NUMHSTCHNL_SIZE 0x4 +#define GC_USB_GHWCFG2_NUMHSTCHNL_DEFAULT 0x0 +#define GC_USB_GHWCFG2_NUMHSTCHNL_OFFSET 0x48 +#define GC_USB_GHWCFG2_PERIOSUPPORT_LSB 0x12 +#define GC_USB_GHWCFG2_PERIOSUPPORT_MASK 0x40000 +#define GC_USB_GHWCFG2_PERIOSUPPORT_SIZE 0x1 +#define GC_USB_GHWCFG2_PERIOSUPPORT_DEFAULT 0x0 +#define GC_USB_GHWCFG2_PERIOSUPPORT_OFFSET 0x48 +#define GC_USB_GHWCFG2_DYNFIFOSIZING_LSB 0x13 +#define GC_USB_GHWCFG2_DYNFIFOSIZING_MASK 0x80000 +#define GC_USB_GHWCFG2_DYNFIFOSIZING_SIZE 0x1 +#define GC_USB_GHWCFG2_DYNFIFOSIZING_DEFAULT 0x0 +#define GC_USB_GHWCFG2_DYNFIFOSIZING_OFFSET 0x48 +#define GC_USB_GHWCFG2_MULTIPROCINTRPT_LSB 0x14 +#define GC_USB_GHWCFG2_MULTIPROCINTRPT_MASK 0x100000 +#define GC_USB_GHWCFG2_MULTIPROCINTRPT_SIZE 0x1 +#define GC_USB_GHWCFG2_MULTIPROCINTRPT_DEFAULT 0x0 +#define GC_USB_GHWCFG2_MULTIPROCINTRPT_OFFSET 0x48 +#define GC_USB_GHWCFG2_NPTXQDEPTH_LSB 0x16 +#define GC_USB_GHWCFG2_NPTXQDEPTH_MASK 0xc00000 +#define GC_USB_GHWCFG2_NPTXQDEPTH_SIZE 0x2 +#define GC_USB_GHWCFG2_NPTXQDEPTH_DEFAULT 0x0 +#define GC_USB_GHWCFG2_NPTXQDEPTH_OFFSET 0x48 +#define GC_USB_GHWCFG2_PTXQDEPTH_LSB 0x18 +#define GC_USB_GHWCFG2_PTXQDEPTH_MASK 0x3000000 +#define GC_USB_GHWCFG2_PTXQDEPTH_SIZE 0x2 +#define GC_USB_GHWCFG2_PTXQDEPTH_DEFAULT 0x0 +#define GC_USB_GHWCFG2_PTXQDEPTH_OFFSET 0x48 +#define GC_USB_GHWCFG2_TKNQDEPTH_LSB 0x1a +#define GC_USB_GHWCFG2_TKNQDEPTH_MASK 0x7c000000 +#define GC_USB_GHWCFG2_TKNQDEPTH_SIZE 0x5 +#define GC_USB_GHWCFG2_TKNQDEPTH_DEFAULT 0x0 +#define GC_USB_GHWCFG2_TKNQDEPTH_OFFSET 0x48 +#define GC_USB_GHWCFG3_XFERSIZEWIDTH_LSB 0x0 +#define GC_USB_GHWCFG3_XFERSIZEWIDTH_MASK 0xf +#define GC_USB_GHWCFG3_XFERSIZEWIDTH_SIZE 0x4 +#define GC_USB_GHWCFG3_XFERSIZEWIDTH_DEFAULT 0x0 +#define GC_USB_GHWCFG3_XFERSIZEWIDTH_OFFSET 0x4c +#define GC_USB_GHWCFG3_PKTSIZEWIDTH_LSB 0x4 +#define GC_USB_GHWCFG3_PKTSIZEWIDTH_MASK 0x70 +#define GC_USB_GHWCFG3_PKTSIZEWIDTH_SIZE 0x3 +#define GC_USB_GHWCFG3_PKTSIZEWIDTH_DEFAULT 0x0 +#define GC_USB_GHWCFG3_PKTSIZEWIDTH_OFFSET 0x4c +#define GC_USB_GHWCFG3_OTGEN_LSB 0x7 +#define GC_USB_GHWCFG3_OTGEN_MASK 0x80 +#define GC_USB_GHWCFG3_OTGEN_SIZE 0x1 +#define GC_USB_GHWCFG3_OTGEN_DEFAULT 0x0 +#define GC_USB_GHWCFG3_OTGEN_OFFSET 0x4c +#define GC_USB_GHWCFG3_I2CINTSEL_LSB 0x8 +#define GC_USB_GHWCFG3_I2CINTSEL_MASK 0x100 +#define GC_USB_GHWCFG3_I2CINTSEL_SIZE 0x1 +#define GC_USB_GHWCFG3_I2CINTSEL_DEFAULT 0x0 +#define GC_USB_GHWCFG3_I2CINTSEL_OFFSET 0x4c +#define GC_USB_GHWCFG3_VNDCTLSUPT_LSB 0x9 +#define GC_USB_GHWCFG3_VNDCTLSUPT_MASK 0x200 +#define GC_USB_GHWCFG3_VNDCTLSUPT_SIZE 0x1 +#define GC_USB_GHWCFG3_VNDCTLSUPT_DEFAULT 0x0 +#define GC_USB_GHWCFG3_VNDCTLSUPT_OFFSET 0x4c +#define GC_USB_GHWCFG3_OPTFEATURE_LSB 0xa +#define GC_USB_GHWCFG3_OPTFEATURE_MASK 0x400 +#define GC_USB_GHWCFG3_OPTFEATURE_SIZE 0x1 +#define GC_USB_GHWCFG3_OPTFEATURE_DEFAULT 0x0 +#define GC_USB_GHWCFG3_OPTFEATURE_OFFSET 0x4c +#define GC_USB_GHWCFG3_RSTTYPE_LSB 0xb +#define GC_USB_GHWCFG3_RSTTYPE_MASK 0x800 +#define GC_USB_GHWCFG3_RSTTYPE_SIZE 0x1 +#define GC_USB_GHWCFG3_RSTTYPE_DEFAULT 0x0 +#define GC_USB_GHWCFG3_RSTTYPE_OFFSET 0x4c +#define GC_USB_GHWCFG3_ADPSUPPORT_LSB 0xc +#define GC_USB_GHWCFG3_ADPSUPPORT_MASK 0x1000 +#define GC_USB_GHWCFG3_ADPSUPPORT_SIZE 0x1 +#define GC_USB_GHWCFG3_ADPSUPPORT_DEFAULT 0x0 +#define GC_USB_GHWCFG3_ADPSUPPORT_OFFSET 0x4c +#define GC_USB_GHWCFG3_HSICMODE_LSB 0xd +#define GC_USB_GHWCFG3_HSICMODE_MASK 0x2000 +#define GC_USB_GHWCFG3_HSICMODE_SIZE 0x1 +#define GC_USB_GHWCFG3_HSICMODE_DEFAULT 0x0 +#define GC_USB_GHWCFG3_HSICMODE_OFFSET 0x4c +#define GC_USB_GHWCFG3_BCSUPPORT_LSB 0xe +#define GC_USB_GHWCFG3_BCSUPPORT_MASK 0x4000 +#define GC_USB_GHWCFG3_BCSUPPORT_SIZE 0x1 +#define GC_USB_GHWCFG3_BCSUPPORT_DEFAULT 0x0 +#define GC_USB_GHWCFG3_BCSUPPORT_OFFSET 0x4c +#define GC_USB_GHWCFG3_LPMMODE_LSB 0xf +#define GC_USB_GHWCFG3_LPMMODE_MASK 0x8000 +#define GC_USB_GHWCFG3_LPMMODE_SIZE 0x1 +#define GC_USB_GHWCFG3_LPMMODE_DEFAULT 0x0 +#define GC_USB_GHWCFG3_LPMMODE_OFFSET 0x4c +#define GC_USB_GHWCFG3_DFIFODEPTH_LSB 0x10 +#define GC_USB_GHWCFG3_DFIFODEPTH_MASK 0xffff0000 +#define GC_USB_GHWCFG3_DFIFODEPTH_SIZE 0x10 +#define GC_USB_GHWCFG3_DFIFODEPTH_DEFAULT 0x0 +#define GC_USB_GHWCFG3_DFIFODEPTH_OFFSET 0x4c +#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_LSB 0x0 +#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_MASK 0xf +#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_SIZE 0x4 +#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_DEFAULT 0x0 +#define GC_USB_GHWCFG4_NUMDEVPERIOEPS_OFFSET 0x50 +#define GC_USB_GHWCFG4_PARTIALPWRDN_LSB 0x4 +#define GC_USB_GHWCFG4_PARTIALPWRDN_MASK 0x10 +#define GC_USB_GHWCFG4_PARTIALPWRDN_SIZE 0x1 +#define GC_USB_GHWCFG4_PARTIALPWRDN_DEFAULT 0x0 +#define GC_USB_GHWCFG4_PARTIALPWRDN_OFFSET 0x50 +#define GC_USB_GHWCFG4_AHBFREQ_LSB 0x5 +#define GC_USB_GHWCFG4_AHBFREQ_MASK 0x20 +#define GC_USB_GHWCFG4_AHBFREQ_SIZE 0x1 +#define GC_USB_GHWCFG4_AHBFREQ_DEFAULT 0x0 +#define GC_USB_GHWCFG4_AHBFREQ_OFFSET 0x50 +#define GC_USB_GHWCFG4_HIBERNATION_LSB 0x6 +#define GC_USB_GHWCFG4_HIBERNATION_MASK 0x40 +#define GC_USB_GHWCFG4_HIBERNATION_SIZE 0x1 +#define GC_USB_GHWCFG4_HIBERNATION_DEFAULT 0x0 +#define GC_USB_GHWCFG4_HIBERNATION_OFFSET 0x50 +#define GC_USB_GHWCFG4_EXTENDEDHIBERNATION_LSB 0x7 +#define GC_USB_GHWCFG4_EXTENDEDHIBERNATION_MASK 0x80 +#define GC_USB_GHWCFG4_EXTENDEDHIBERNATION_SIZE 0x1 #define GC_USB_GHWCFG4_EXTENDEDHIBERNATION_DEFAULT 0x0 #define GC_USB_GHWCFG4_EXTENDEDHIBERNATION_OFFSET 0x50 -#define GC_USB_GHWCFG4_PHYDATAWIDTH_LSB 0xe -#define GC_USB_GHWCFG4_PHYDATAWIDTH_MASK 0xc000 -#define GC_USB_GHWCFG4_PHYDATAWIDTH_SIZE 0x2 -#define GC_USB_GHWCFG4_PHYDATAWIDTH_DEFAULT 0x0 -#define GC_USB_GHWCFG4_PHYDATAWIDTH_OFFSET 0x50 -#define GC_USB_GHWCFG4_NUMCTLEPS_LSB 0x10 -#define GC_USB_GHWCFG4_NUMCTLEPS_MASK 0xf0000 -#define GC_USB_GHWCFG4_NUMCTLEPS_SIZE 0x4 -#define GC_USB_GHWCFG4_NUMCTLEPS_DEFAULT 0x0 -#define GC_USB_GHWCFG4_NUMCTLEPS_OFFSET 0x50 -#define GC_USB_GHWCFG4_IDDGFLTR_LSB 0x14 -#define GC_USB_GHWCFG4_IDDGFLTR_MASK 0x100000 -#define GC_USB_GHWCFG4_IDDGFLTR_SIZE 0x1 -#define GC_USB_GHWCFG4_IDDGFLTR_DEFAULT 0x0 -#define GC_USB_GHWCFG4_IDDGFLTR_OFFSET 0x50 -#define GC_USB_GHWCFG4_VBUSVALIDFLTR_LSB 0x15 -#define GC_USB_GHWCFG4_VBUSVALIDFLTR_MASK 0x200000 -#define GC_USB_GHWCFG4_VBUSVALIDFLTR_SIZE 0x1 -#define GC_USB_GHWCFG4_VBUSVALIDFLTR_DEFAULT 0x0 -#define GC_USB_GHWCFG4_VBUSVALIDFLTR_OFFSET 0x50 -#define GC_USB_GHWCFG4_AVALIDFLTR_LSB 0x16 -#define GC_USB_GHWCFG4_AVALIDFLTR_MASK 0x400000 -#define GC_USB_GHWCFG4_AVALIDFLTR_SIZE 0x1 -#define GC_USB_GHWCFG4_AVALIDFLTR_DEFAULT 0x0 -#define GC_USB_GHWCFG4_AVALIDFLTR_OFFSET 0x50 -#define GC_USB_GHWCFG4_BVALIDFLTR_LSB 0x17 -#define GC_USB_GHWCFG4_BVALIDFLTR_MASK 0x800000 -#define GC_USB_GHWCFG4_BVALIDFLTR_SIZE 0x1 -#define GC_USB_GHWCFG4_BVALIDFLTR_DEFAULT 0x0 -#define GC_USB_GHWCFG4_BVALIDFLTR_OFFSET 0x50 -#define GC_USB_GHWCFG4_SESSENDFLTR_LSB 0x18 -#define GC_USB_GHWCFG4_SESSENDFLTR_MASK 0x1000000 -#define GC_USB_GHWCFG4_SESSENDFLTR_SIZE 0x1 -#define GC_USB_GHWCFG4_SESSENDFLTR_DEFAULT 0x0 -#define GC_USB_GHWCFG4_SESSENDFLTR_OFFSET 0x50 -#define GC_USB_GHWCFG4_DEDFIFOMODE_LSB 0x19 -#define GC_USB_GHWCFG4_DEDFIFOMODE_MASK 0x2000000 -#define GC_USB_GHWCFG4_DEDFIFOMODE_SIZE 0x1 -#define GC_USB_GHWCFG4_DEDFIFOMODE_DEFAULT 0x0 -#define GC_USB_GHWCFG4_DEDFIFOMODE_OFFSET 0x50 -#define GC_USB_GHWCFG4_INEPS_LSB 0x1a -#define GC_USB_GHWCFG4_INEPS_MASK 0x3c000000 -#define GC_USB_GHWCFG4_INEPS_SIZE 0x4 -#define GC_USB_GHWCFG4_INEPS_DEFAULT 0x0 -#define GC_USB_GHWCFG4_INEPS_OFFSET 0x50 -#define GC_USB_GHWCFG4_DESCDMAENABLED_LSB 0x1e -#define GC_USB_GHWCFG4_DESCDMAENABLED_MASK 0x40000000 -#define GC_USB_GHWCFG4_DESCDMAENABLED_SIZE 0x1 -#define GC_USB_GHWCFG4_DESCDMAENABLED_DEFAULT 0x0 -#define GC_USB_GHWCFG4_DESCDMAENABLED_OFFSET 0x50 -#define GC_USB_GHWCFG4_DESCDMA_LSB 0x1f -#define GC_USB_GHWCFG4_DESCDMA_MASK 0x80000000 -#define GC_USB_GHWCFG4_DESCDMA_SIZE 0x1 -#define GC_USB_GHWCFG4_DESCDMA_DEFAULT 0x0 -#define GC_USB_GHWCFG4_DESCDMA_OFFSET 0x50 -#define GC_USB_GDFIFOCFG_GDFIFOCFG_LSB 0x0 -#define GC_USB_GDFIFOCFG_GDFIFOCFG_MASK 0xffff -#define GC_USB_GDFIFOCFG_GDFIFOCFG_SIZE 0x10 -#define GC_USB_GDFIFOCFG_GDFIFOCFG_DEFAULT 0x0 -#define GC_USB_GDFIFOCFG_GDFIFOCFG_OFFSET 0x5c -#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_LSB 0x10 -#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_MASK 0xffff0000 -#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_SIZE 0x10 -#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_DEFAULT 0x0 -#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_OFFSET 0x5c -#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_OFFSET 0x104 -#define GC_USB_DIEPTXF1_RESERVED11_LSB 0xc -#define GC_USB_DIEPTXF1_RESERVED11_MASK 0x1000 -#define GC_USB_DIEPTXF1_RESERVED11_SIZE 0x1 -#define GC_USB_DIEPTXF1_RESERVED11_DEFAULT 0x1 -#define GC_USB_DIEPTXF1_RESERVED11_OFFSET 0x104 -#define GC_USB_DIEPTXF1_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF1_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF1_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF1_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF1_INEPNTXFDEP_OFFSET 0x104 -#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_OFFSET 0x108 -#define GC_USB_DIEPTXF2_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF2_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF2_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF2_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF2_INEPNTXFDEP_OFFSET 0x108 -#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_OFFSET 0x10c -#define GC_USB_DIEPTXF3_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF3_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF3_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF3_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF3_INEPNTXFDEP_OFFSET 0x10c -#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_OFFSET 0x110 -#define GC_USB_DIEPTXF4_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF4_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF4_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF4_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF4_INEPNTXFDEP_OFFSET 0x110 -#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_OFFSET 0x114 -#define GC_USB_DIEPTXF5_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF5_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF5_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF5_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF5_INEPNTXFDEP_OFFSET 0x114 -#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_OFFSET 0x118 -#define GC_USB_DIEPTXF6_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF6_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF6_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF6_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF6_INEPNTXFDEP_OFFSET 0x118 -#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_OFFSET 0x11c -#define GC_USB_DIEPTXF7_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF7_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF7_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF7_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF7_INEPNTXFDEP_OFFSET 0x11c -#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_OFFSET 0x120 -#define GC_USB_DIEPTXF8_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF8_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF8_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF8_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF8_INEPNTXFDEP_OFFSET 0x120 -#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_OFFSET 0x124 -#define GC_USB_DIEPTXF9_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF9_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF9_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF9_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF9_INEPNTXFDEP_OFFSET 0x124 -#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_OFFSET 0x128 -#define GC_USB_DIEPTXF10_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF10_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF10_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF10_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF10_INEPNTXFDEP_OFFSET 0x128 -#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_OFFSET 0x12c -#define GC_USB_DIEPTXF11_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF11_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF11_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF11_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF11_INEPNTXFDEP_OFFSET 0x12c -#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_OFFSET 0x130 -#define GC_USB_DIEPTXF12_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF12_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF12_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF12_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF12_INEPNTXFDEP_OFFSET 0x130 -#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_OFFSET 0x134 -#define GC_USB_DIEPTXF13_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF13_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF13_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF13_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF13_INEPNTXFDEP_OFFSET 0x134 -#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_OFFSET 0x138 -#define GC_USB_DIEPTXF14_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF14_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF14_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF14_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF14_INEPNTXFDEP_OFFSET 0x138 -#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_LSB 0x0 -#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_MASK 0x7ff -#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_SIZE 0xb -#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_DEFAULT 0x0 -#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_OFFSET 0x13c -#define GC_USB_DIEPTXF15_INEPNTXFDEP_LSB 0x10 -#define GC_USB_DIEPTXF15_INEPNTXFDEP_MASK 0x3f0000 -#define GC_USB_DIEPTXF15_INEPNTXFDEP_SIZE 0x6 -#define GC_USB_DIEPTXF15_INEPNTXFDEP_DEFAULT 0x0 -#define GC_USB_DIEPTXF15_INEPNTXFDEP_OFFSET 0x13c -#define GC_USB_DCFG_DEVSPD_LSB 0x0 -#define GC_USB_DCFG_DEVSPD_MASK 0x3 -#define GC_USB_DCFG_DEVSPD_SIZE 0x2 -#define GC_USB_DCFG_DEVSPD_DEFAULT 0x0 -#define GC_USB_DCFG_DEVSPD_OFFSET 0x800 -#define GC_USB_DCFG_NZSTSOUTHSHK_LSB 0x2 -#define GC_USB_DCFG_NZSTSOUTHSHK_MASK 0x4 -#define GC_USB_DCFG_NZSTSOUTHSHK_SIZE 0x1 -#define GC_USB_DCFG_NZSTSOUTHSHK_DEFAULT 0x0 -#define GC_USB_DCFG_NZSTSOUTHSHK_OFFSET 0x800 -#define GC_USB_DCFG_ENA32KHZSUSP_LSB 0x3 -#define GC_USB_DCFG_ENA32KHZSUSP_MASK 0x8 -#define GC_USB_DCFG_ENA32KHZSUSP_SIZE 0x1 -#define GC_USB_DCFG_ENA32KHZSUSP_DEFAULT 0x0 -#define GC_USB_DCFG_ENA32KHZSUSP_OFFSET 0x800 -#define GC_USB_DCFG_DEVADDR_LSB 0x4 -#define GC_USB_DCFG_DEVADDR_MASK 0x7f0 -#define GC_USB_DCFG_DEVADDR_SIZE 0x7 -#define GC_USB_DCFG_DEVADDR_DEFAULT 0x0 -#define GC_USB_DCFG_DEVADDR_OFFSET 0x800 -#define GC_USB_DCFG_PERFRINT_LSB 0xb -#define GC_USB_DCFG_PERFRINT_MASK 0x1800 -#define GC_USB_DCFG_PERFRINT_SIZE 0x2 -#define GC_USB_DCFG_PERFRINT_DEFAULT 0x0 -#define GC_USB_DCFG_PERFRINT_OFFSET 0x800 -#define GC_USB_DCFG_ENDEVOUTNAK_LSB 0xd -#define GC_USB_DCFG_ENDEVOUTNAK_MASK 0x2000 -#define GC_USB_DCFG_ENDEVOUTNAK_SIZE 0x1 -#define GC_USB_DCFG_ENDEVOUTNAK_DEFAULT 0x0 -#define GC_USB_DCFG_ENDEVOUTNAK_OFFSET 0x800 -#define GC_USB_DCFG_XCVRDLY_LSB 0xe -#define GC_USB_DCFG_XCVRDLY_MASK 0x4000 -#define GC_USB_DCFG_XCVRDLY_SIZE 0x1 -#define GC_USB_DCFG_XCVRDLY_DEFAULT 0x0 -#define GC_USB_DCFG_XCVRDLY_OFFSET 0x800 -#define GC_USB_DCFG_ERRATICINTMSK_LSB 0xf -#define GC_USB_DCFG_ERRATICINTMSK_MASK 0x8000 -#define GC_USB_DCFG_ERRATICINTMSK_SIZE 0x1 -#define GC_USB_DCFG_ERRATICINTMSK_DEFAULT 0x0 -#define GC_USB_DCFG_ERRATICINTMSK_OFFSET 0x800 -#define GC_USB_DCFG_DESCDMA_LSB 0x17 -#define GC_USB_DCFG_DESCDMA_MASK 0x800000 -#define GC_USB_DCFG_DESCDMA_SIZE 0x1 -#define GC_USB_DCFG_DESCDMA_DEFAULT 0x0 -#define GC_USB_DCFG_DESCDMA_OFFSET 0x800 -#define GC_USB_DCFG_PERSCHINTVL_LSB 0x18 -#define GC_USB_DCFG_PERSCHINTVL_MASK 0x3000000 -#define GC_USB_DCFG_PERSCHINTVL_SIZE 0x2 -#define GC_USB_DCFG_PERSCHINTVL_DEFAULT 0x0 -#define GC_USB_DCFG_PERSCHINTVL_OFFSET 0x800 -#define GC_USB_DCFG_RESVALID_LSB 0x1a -#define GC_USB_DCFG_RESVALID_MASK 0xfc000000 -#define GC_USB_DCFG_RESVALID_SIZE 0x6 -#define GC_USB_DCFG_RESVALID_DEFAULT 0x2 -#define GC_USB_DCFG_RESVALID_OFFSET 0x800 -#define GC_USB_DCTL_RMTWKUPSIG_LSB 0x0 -#define GC_USB_DCTL_RMTWKUPSIG_MASK 0x1 -#define GC_USB_DCTL_RMTWKUPSIG_SIZE 0x1 -#define GC_USB_DCTL_RMTWKUPSIG_DEFAULT 0x0 -#define GC_USB_DCTL_RMTWKUPSIG_OFFSET 0x804 -#define GC_USB_DCTL_SFTDISCON_LSB 0x1 -#define GC_USB_DCTL_SFTDISCON_MASK 0x2 -#define GC_USB_DCTL_SFTDISCON_SIZE 0x1 -#define GC_USB_DCTL_SFTDISCON_DEFAULT 0x0 -#define GC_USB_DCTL_SFTDISCON_OFFSET 0x804 -#define GC_USB_DCTL_GNPINNAKSTS_LSB 0x2 -#define GC_USB_DCTL_GNPINNAKSTS_MASK 0x4 -#define GC_USB_DCTL_GNPINNAKSTS_SIZE 0x1 -#define GC_USB_DCTL_GNPINNAKSTS_DEFAULT 0x0 -#define GC_USB_DCTL_GNPINNAKSTS_OFFSET 0x804 -#define GC_USB_DCTL_GOUTNAKSTS_LSB 0x3 -#define GC_USB_DCTL_GOUTNAKSTS_MASK 0x8 -#define GC_USB_DCTL_GOUTNAKSTS_SIZE 0x1 -#define GC_USB_DCTL_GOUTNAKSTS_DEFAULT 0x0 -#define GC_USB_DCTL_GOUTNAKSTS_OFFSET 0x804 -#define GC_USB_DCTL_TSTCTL_LSB 0x4 -#define GC_USB_DCTL_TSTCTL_MASK 0x70 -#define GC_USB_DCTL_TSTCTL_SIZE 0x3 -#define GC_USB_DCTL_TSTCTL_DEFAULT 0x0 -#define GC_USB_DCTL_TSTCTL_OFFSET 0x804 -#define GC_USB_DCTL_SGNPINNAK_LSB 0x7 -#define GC_USB_DCTL_SGNPINNAK_MASK 0x80 -#define GC_USB_DCTL_SGNPINNAK_SIZE 0x1 -#define GC_USB_DCTL_SGNPINNAK_DEFAULT 0x0 -#define GC_USB_DCTL_SGNPINNAK_OFFSET 0x804 -#define GC_USB_DCTL_CGNPINNAK_LSB 0x8 -#define GC_USB_DCTL_CGNPINNAK_MASK 0x100 -#define GC_USB_DCTL_CGNPINNAK_SIZE 0x1 -#define GC_USB_DCTL_CGNPINNAK_DEFAULT 0x0 -#define GC_USB_DCTL_CGNPINNAK_OFFSET 0x804 -#define GC_USB_DCTL_SGOUTNAK_LSB 0x9 -#define GC_USB_DCTL_SGOUTNAK_MASK 0x200 -#define GC_USB_DCTL_SGOUTNAK_SIZE 0x1 -#define GC_USB_DCTL_SGOUTNAK_DEFAULT 0x0 -#define GC_USB_DCTL_SGOUTNAK_OFFSET 0x804 -#define GC_USB_DCTL_CGOUTNAK_LSB 0xa -#define GC_USB_DCTL_CGOUTNAK_MASK 0x400 -#define GC_USB_DCTL_CGOUTNAK_SIZE 0x1 -#define GC_USB_DCTL_CGOUTNAK_DEFAULT 0x0 -#define GC_USB_DCTL_CGOUTNAK_OFFSET 0x804 -#define GC_USB_DCTL_PWRONPRGDONE_LSB 0xb -#define GC_USB_DCTL_PWRONPRGDONE_MASK 0x800 -#define GC_USB_DCTL_PWRONPRGDONE_SIZE 0x1 -#define GC_USB_DCTL_PWRONPRGDONE_DEFAULT 0x0 -#define GC_USB_DCTL_PWRONPRGDONE_OFFSET 0x804 -#define GC_USB_DCTL_GMC_LSB 0xd -#define GC_USB_DCTL_GMC_MASK 0x6000 -#define GC_USB_DCTL_GMC_SIZE 0x2 -#define GC_USB_DCTL_GMC_DEFAULT 0x0 -#define GC_USB_DCTL_GMC_OFFSET 0x804 -#define GC_USB_DCTL_IGNRFRMNUM_LSB 0xf -#define GC_USB_DCTL_IGNRFRMNUM_MASK 0x8000 -#define GC_USB_DCTL_IGNRFRMNUM_SIZE 0x1 -#define GC_USB_DCTL_IGNRFRMNUM_DEFAULT 0x0 -#define GC_USB_DCTL_IGNRFRMNUM_OFFSET 0x804 -#define GC_USB_DCTL_NAKONBBLE_LSB 0x10 -#define GC_USB_DCTL_NAKONBBLE_MASK 0x10000 -#define GC_USB_DCTL_NAKONBBLE_SIZE 0x1 -#define GC_USB_DCTL_NAKONBBLE_DEFAULT 0x0 -#define GC_USB_DCTL_NAKONBBLE_OFFSET 0x804 -#define GC_USB_DCTL_ENCONTONBNA_LSB 0x11 -#define GC_USB_DCTL_ENCONTONBNA_MASK 0x20000 -#define GC_USB_DCTL_ENCONTONBNA_SIZE 0x1 -#define GC_USB_DCTL_ENCONTONBNA_DEFAULT 0x0 -#define GC_USB_DCTL_ENCONTONBNA_OFFSET 0x804 -#define GC_USB_DSTS_SUSPSTS_LSB 0x0 -#define GC_USB_DSTS_SUSPSTS_MASK 0x1 -#define GC_USB_DSTS_SUSPSTS_SIZE 0x1 -#define GC_USB_DSTS_SUSPSTS_DEFAULT 0x0 -#define GC_USB_DSTS_SUSPSTS_OFFSET 0x808 -#define GC_USB_DSTS_ENUMSPD_LSB 0x1 -#define GC_USB_DSTS_ENUMSPD_MASK 0x6 -#define GC_USB_DSTS_ENUMSPD_SIZE 0x2 -#define GC_USB_DSTS_ENUMSPD_DEFAULT 0x0 -#define GC_USB_DSTS_ENUMSPD_OFFSET 0x808 -#define GC_USB_DSTS_ERRTICERR_LSB 0x3 -#define GC_USB_DSTS_ERRTICERR_MASK 0x8 -#define GC_USB_DSTS_ERRTICERR_SIZE 0x1 -#define GC_USB_DSTS_ERRTICERR_DEFAULT 0x0 -#define GC_USB_DSTS_ERRTICERR_OFFSET 0x808 -#define GC_USB_DSTS_SOFFN_LSB 0x8 -#define GC_USB_DSTS_SOFFN_MASK 0x3fff00 -#define GC_USB_DSTS_SOFFN_SIZE 0xe -#define GC_USB_DSTS_SOFFN_DEFAULT 0x0 -#define GC_USB_DSTS_SOFFN_OFFSET 0x808 -#define GC_USB_DSTS_DEVLNSTS_LSB 0x16 -#define GC_USB_DSTS_DEVLNSTS_MASK 0xc00000 -#define GC_USB_DSTS_DEVLNSTS_SIZE 0x2 -#define GC_USB_DSTS_DEVLNSTS_DEFAULT 0x0 -#define GC_USB_DSTS_DEVLNSTS_OFFSET 0x808 -#define GC_USB_DIEPMSK_XFERCOMPLMSK_LSB 0x0 -#define GC_USB_DIEPMSK_XFERCOMPLMSK_MASK 0x1 -#define GC_USB_DIEPMSK_XFERCOMPLMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_XFERCOMPLMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_XFERCOMPLMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_EPDISBLDMSK_LSB 0x1 -#define GC_USB_DIEPMSK_EPDISBLDMSK_MASK 0x2 -#define GC_USB_DIEPMSK_EPDISBLDMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_EPDISBLDMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_EPDISBLDMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_AHBERRMSK_LSB 0x2 -#define GC_USB_DIEPMSK_AHBERRMSK_MASK 0x4 -#define GC_USB_DIEPMSK_AHBERRMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_AHBERRMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_AHBERRMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_TIMEOUTMSK_LSB 0x3 -#define GC_USB_DIEPMSK_TIMEOUTMSK_MASK 0x8 -#define GC_USB_DIEPMSK_TIMEOUTMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_TIMEOUTMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_TIMEOUTMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_LSB 0x4 -#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_MASK 0x10 -#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_INTKNEPMISMSK_LSB 0x5 -#define GC_USB_DIEPMSK_INTKNEPMISMSK_MASK 0x20 -#define GC_USB_DIEPMSK_INTKNEPMISMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_INTKNEPMISMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_INTKNEPMISMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_INEPNAKEFFMSK_LSB 0x6 -#define GC_USB_DIEPMSK_INEPNAKEFFMSK_MASK 0x40 -#define GC_USB_DIEPMSK_INEPNAKEFFMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_INEPNAKEFFMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_INEPNAKEFFMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_RESERVED7_LSB 0x7 -#define GC_USB_DIEPMSK_RESERVED7_MASK 0x80 -#define GC_USB_DIEPMSK_RESERVED7_SIZE 0x1 -#define GC_USB_DIEPMSK_RESERVED7_DEFAULT 0x1 -#define GC_USB_DIEPMSK_RESERVED7_OFFSET 0x810 -#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_LSB 0x8 -#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_MASK 0x100 -#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_BNAININTRMSK_LSB 0x9 -#define GC_USB_DIEPMSK_BNAININTRMSK_MASK 0x200 -#define GC_USB_DIEPMSK_BNAININTRMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_BNAININTRMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_BNAININTRMSK_OFFSET 0x810 -#define GC_USB_DIEPMSK_NAKMSK_LSB 0xd -#define GC_USB_DIEPMSK_NAKMSK_MASK 0x2000 -#define GC_USB_DIEPMSK_NAKMSK_SIZE 0x1 -#define GC_USB_DIEPMSK_NAKMSK_DEFAULT 0x0 -#define GC_USB_DIEPMSK_NAKMSK_OFFSET 0x810 -#define GC_USB_DOEPMSK_XFERCOMPLMSK_LSB 0x0 -#define GC_USB_DOEPMSK_XFERCOMPLMSK_MASK 0x1 -#define GC_USB_DOEPMSK_XFERCOMPLMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_XFERCOMPLMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_XFERCOMPLMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_EPDISBLDMSK_LSB 0x1 -#define GC_USB_DOEPMSK_EPDISBLDMSK_MASK 0x2 -#define GC_USB_DOEPMSK_EPDISBLDMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_EPDISBLDMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_EPDISBLDMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_AHBERRMSK_LSB 0x2 -#define GC_USB_DOEPMSK_AHBERRMSK_MASK 0x4 -#define GC_USB_DOEPMSK_AHBERRMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_AHBERRMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_AHBERRMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_SETUPMSK_LSB 0x3 -#define GC_USB_DOEPMSK_SETUPMSK_MASK 0x8 -#define GC_USB_DOEPMSK_SETUPMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_SETUPMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_SETUPMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_LSB 0x4 -#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_MASK 0x10 -#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_STSPHSERCVDMSK_LSB 0x5 -#define GC_USB_DOEPMSK_STSPHSERCVDMSK_MASK 0x20 -#define GC_USB_DOEPMSK_STSPHSERCVDMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_STSPHSERCVDMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_STSPHSERCVDMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPMSK_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPMSK_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPMSK_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPMSK_BACK2BACKSETUP_OFFSET 0x814 -#define GC_USB_DOEPMSK_OUTPKTERRMSK_LSB 0x8 -#define GC_USB_DOEPMSK_OUTPKTERRMSK_MASK 0x100 -#define GC_USB_DOEPMSK_OUTPKTERRMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_OUTPKTERRMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_OUTPKTERRMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_BNAOUTINTRMSK_LSB 0x9 -#define GC_USB_DOEPMSK_BNAOUTINTRMSK_MASK 0x200 -#define GC_USB_DOEPMSK_BNAOUTINTRMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_BNAOUTINTRMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_BNAOUTINTRMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_BBLEERRMSK_LSB 0xc -#define GC_USB_DOEPMSK_BBLEERRMSK_MASK 0x1000 -#define GC_USB_DOEPMSK_BBLEERRMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_BBLEERRMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_BBLEERRMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_NAKMSK_LSB 0xd -#define GC_USB_DOEPMSK_NAKMSK_MASK 0x2000 -#define GC_USB_DOEPMSK_NAKMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_NAKMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_NAKMSK_OFFSET 0x814 -#define GC_USB_DOEPMSK_NYETMSK_LSB 0xe -#define GC_USB_DOEPMSK_NYETMSK_MASK 0x4000 -#define GC_USB_DOEPMSK_NYETMSK_SIZE 0x1 -#define GC_USB_DOEPMSK_NYETMSK_DEFAULT 0x0 -#define GC_USB_DOEPMSK_NYETMSK_OFFSET 0x814 -#define GC_USB_DAINT_INEPINT0_LSB 0x0 -#define GC_USB_DAINT_INEPINT0_MASK 0x1 -#define GC_USB_DAINT_INEPINT0_SIZE 0x1 -#define GC_USB_DAINT_INEPINT0_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT0_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT1_LSB 0x1 -#define GC_USB_DAINT_INEPINT1_MASK 0x2 -#define GC_USB_DAINT_INEPINT1_SIZE 0x1 -#define GC_USB_DAINT_INEPINT1_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT1_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT2_LSB 0x2 -#define GC_USB_DAINT_INEPINT2_MASK 0x4 -#define GC_USB_DAINT_INEPINT2_SIZE 0x1 -#define GC_USB_DAINT_INEPINT2_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT2_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT3_LSB 0x3 -#define GC_USB_DAINT_INEPINT3_MASK 0x8 -#define GC_USB_DAINT_INEPINT3_SIZE 0x1 -#define GC_USB_DAINT_INEPINT3_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT3_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT4_LSB 0x4 -#define GC_USB_DAINT_INEPINT4_MASK 0x10 -#define GC_USB_DAINT_INEPINT4_SIZE 0x1 -#define GC_USB_DAINT_INEPINT4_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT4_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT5_LSB 0x5 -#define GC_USB_DAINT_INEPINT5_MASK 0x20 -#define GC_USB_DAINT_INEPINT5_SIZE 0x1 -#define GC_USB_DAINT_INEPINT5_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT5_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT6_LSB 0x6 -#define GC_USB_DAINT_INEPINT6_MASK 0x40 -#define GC_USB_DAINT_INEPINT6_SIZE 0x1 -#define GC_USB_DAINT_INEPINT6_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT6_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT7_LSB 0x7 -#define GC_USB_DAINT_INEPINT7_MASK 0x80 -#define GC_USB_DAINT_INEPINT7_SIZE 0x1 -#define GC_USB_DAINT_INEPINT7_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT7_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT8_LSB 0x8 -#define GC_USB_DAINT_INEPINT8_MASK 0x100 -#define GC_USB_DAINT_INEPINT8_SIZE 0x1 -#define GC_USB_DAINT_INEPINT8_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT8_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT9_LSB 0x9 -#define GC_USB_DAINT_INEPINT9_MASK 0x200 -#define GC_USB_DAINT_INEPINT9_SIZE 0x1 -#define GC_USB_DAINT_INEPINT9_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT9_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT10_LSB 0xa -#define GC_USB_DAINT_INEPINT10_MASK 0x400 -#define GC_USB_DAINT_INEPINT10_SIZE 0x1 -#define GC_USB_DAINT_INEPINT10_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT10_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT11_LSB 0xb -#define GC_USB_DAINT_INEPINT11_MASK 0x800 -#define GC_USB_DAINT_INEPINT11_SIZE 0x1 -#define GC_USB_DAINT_INEPINT11_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT11_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT12_LSB 0xc -#define GC_USB_DAINT_INEPINT12_MASK 0x1000 -#define GC_USB_DAINT_INEPINT12_SIZE 0x1 -#define GC_USB_DAINT_INEPINT12_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT12_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT13_LSB 0xd -#define GC_USB_DAINT_INEPINT13_MASK 0x2000 -#define GC_USB_DAINT_INEPINT13_SIZE 0x1 -#define GC_USB_DAINT_INEPINT13_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT13_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT14_LSB 0xe -#define GC_USB_DAINT_INEPINT14_MASK 0x4000 -#define GC_USB_DAINT_INEPINT14_SIZE 0x1 -#define GC_USB_DAINT_INEPINT14_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT14_OFFSET 0x818 -#define GC_USB_DAINT_INEPINT15_LSB 0xf -#define GC_USB_DAINT_INEPINT15_MASK 0x8000 -#define GC_USB_DAINT_INEPINT15_SIZE 0x1 -#define GC_USB_DAINT_INEPINT15_DEFAULT 0x0 -#define GC_USB_DAINT_INEPINT15_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT0_LSB 0x10 -#define GC_USB_DAINT_OUTEPINT0_MASK 0x10000 -#define GC_USB_DAINT_OUTEPINT0_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT0_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT0_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT1_LSB 0x11 -#define GC_USB_DAINT_OUTEPINT1_MASK 0x20000 -#define GC_USB_DAINT_OUTEPINT1_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT1_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT1_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT2_LSB 0x12 -#define GC_USB_DAINT_OUTEPINT2_MASK 0x40000 -#define GC_USB_DAINT_OUTEPINT2_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT2_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT2_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT3_LSB 0x13 -#define GC_USB_DAINT_OUTEPINT3_MASK 0x80000 -#define GC_USB_DAINT_OUTEPINT3_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT3_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT3_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT4_LSB 0x14 -#define GC_USB_DAINT_OUTEPINT4_MASK 0x100000 -#define GC_USB_DAINT_OUTEPINT4_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT4_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT4_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT5_LSB 0x15 -#define GC_USB_DAINT_OUTEPINT5_MASK 0x200000 -#define GC_USB_DAINT_OUTEPINT5_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT5_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT5_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT6_LSB 0x16 -#define GC_USB_DAINT_OUTEPINT6_MASK 0x400000 -#define GC_USB_DAINT_OUTEPINT6_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT6_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT6_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT7_LSB 0x17 -#define GC_USB_DAINT_OUTEPINT7_MASK 0x800000 -#define GC_USB_DAINT_OUTEPINT7_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT7_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT7_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT8_LSB 0x18 -#define GC_USB_DAINT_OUTEPINT8_MASK 0x1000000 -#define GC_USB_DAINT_OUTEPINT8_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT8_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT8_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT9_LSB 0x19 -#define GC_USB_DAINT_OUTEPINT9_MASK 0x2000000 -#define GC_USB_DAINT_OUTEPINT9_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT9_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT9_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT10_LSB 0x1a -#define GC_USB_DAINT_OUTEPINT10_MASK 0x4000000 -#define GC_USB_DAINT_OUTEPINT10_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT10_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT10_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT11_LSB 0x1b -#define GC_USB_DAINT_OUTEPINT11_MASK 0x8000000 -#define GC_USB_DAINT_OUTEPINT11_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT11_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT11_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT12_LSB 0x1c -#define GC_USB_DAINT_OUTEPINT12_MASK 0x10000000 -#define GC_USB_DAINT_OUTEPINT12_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT12_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT12_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT13_LSB 0x1d -#define GC_USB_DAINT_OUTEPINT13_MASK 0x20000000 -#define GC_USB_DAINT_OUTEPINT13_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT13_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT13_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT14_LSB 0x1e -#define GC_USB_DAINT_OUTEPINT14_MASK 0x40000000 -#define GC_USB_DAINT_OUTEPINT14_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT14_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT14_OFFSET 0x818 -#define GC_USB_DAINT_OUTEPINT15_LSB 0x1f -#define GC_USB_DAINT_OUTEPINT15_MASK 0x80000000 -#define GC_USB_DAINT_OUTEPINT15_SIZE 0x1 -#define GC_USB_DAINT_OUTEPINT15_DEFAULT 0x0 -#define GC_USB_DAINT_OUTEPINT15_OFFSET 0x818 -#define GC_USB_DAINTMSK_INEPMSK0_LSB 0x0 -#define GC_USB_DAINTMSK_INEPMSK0_MASK 0x1 -#define GC_USB_DAINTMSK_INEPMSK0_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK0_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK0_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK1_LSB 0x1 -#define GC_USB_DAINTMSK_INEPMSK1_MASK 0x2 -#define GC_USB_DAINTMSK_INEPMSK1_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK1_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK1_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK2_LSB 0x2 -#define GC_USB_DAINTMSK_INEPMSK2_MASK 0x4 -#define GC_USB_DAINTMSK_INEPMSK2_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK2_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK2_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK3_LSB 0x3 -#define GC_USB_DAINTMSK_INEPMSK3_MASK 0x8 -#define GC_USB_DAINTMSK_INEPMSK3_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK3_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK3_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK4_LSB 0x4 -#define GC_USB_DAINTMSK_INEPMSK4_MASK 0x10 -#define GC_USB_DAINTMSK_INEPMSK4_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK4_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK4_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK5_LSB 0x5 -#define GC_USB_DAINTMSK_INEPMSK5_MASK 0x20 -#define GC_USB_DAINTMSK_INEPMSK5_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK5_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK5_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK6_LSB 0x6 -#define GC_USB_DAINTMSK_INEPMSK6_MASK 0x40 -#define GC_USB_DAINTMSK_INEPMSK6_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK6_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK6_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK7_LSB 0x7 -#define GC_USB_DAINTMSK_INEPMSK7_MASK 0x80 -#define GC_USB_DAINTMSK_INEPMSK7_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK7_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK7_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK8_LSB 0x8 -#define GC_USB_DAINTMSK_INEPMSK8_MASK 0x100 -#define GC_USB_DAINTMSK_INEPMSK8_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK8_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK8_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK9_LSB 0x9 -#define GC_USB_DAINTMSK_INEPMSK9_MASK 0x200 -#define GC_USB_DAINTMSK_INEPMSK9_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK9_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK9_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK10_LSB 0xa -#define GC_USB_DAINTMSK_INEPMSK10_MASK 0x400 -#define GC_USB_DAINTMSK_INEPMSK10_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK10_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK10_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK11_LSB 0xb -#define GC_USB_DAINTMSK_INEPMSK11_MASK 0x800 -#define GC_USB_DAINTMSK_INEPMSK11_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK11_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK11_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK12_LSB 0xc -#define GC_USB_DAINTMSK_INEPMSK12_MASK 0x1000 -#define GC_USB_DAINTMSK_INEPMSK12_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK12_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK12_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK13_LSB 0xd -#define GC_USB_DAINTMSK_INEPMSK13_MASK 0x2000 -#define GC_USB_DAINTMSK_INEPMSK13_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK13_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK13_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK14_LSB 0xe -#define GC_USB_DAINTMSK_INEPMSK14_MASK 0x4000 -#define GC_USB_DAINTMSK_INEPMSK14_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK14_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK14_OFFSET 0x81c -#define GC_USB_DAINTMSK_INEPMSK15_LSB 0xf -#define GC_USB_DAINTMSK_INEPMSK15_MASK 0x8000 -#define GC_USB_DAINTMSK_INEPMSK15_SIZE 0x1 -#define GC_USB_DAINTMSK_INEPMSK15_DEFAULT 0x0 -#define GC_USB_DAINTMSK_INEPMSK15_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK0_LSB 0x10 -#define GC_USB_DAINTMSK_OUTEPMSK0_MASK 0x10000 -#define GC_USB_DAINTMSK_OUTEPMSK0_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK0_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK0_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK1_LSB 0x11 -#define GC_USB_DAINTMSK_OUTEPMSK1_MASK 0x20000 -#define GC_USB_DAINTMSK_OUTEPMSK1_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK1_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK1_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK2_LSB 0x12 -#define GC_USB_DAINTMSK_OUTEPMSK2_MASK 0x40000 -#define GC_USB_DAINTMSK_OUTEPMSK2_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK2_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK2_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK3_LSB 0x13 -#define GC_USB_DAINTMSK_OUTEPMSK3_MASK 0x80000 -#define GC_USB_DAINTMSK_OUTEPMSK3_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK3_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK3_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK4_LSB 0x14 -#define GC_USB_DAINTMSK_OUTEPMSK4_MASK 0x100000 -#define GC_USB_DAINTMSK_OUTEPMSK4_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK4_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK4_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK5_LSB 0x15 -#define GC_USB_DAINTMSK_OUTEPMSK5_MASK 0x200000 -#define GC_USB_DAINTMSK_OUTEPMSK5_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK5_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK5_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK6_LSB 0x16 -#define GC_USB_DAINTMSK_OUTEPMSK6_MASK 0x400000 -#define GC_USB_DAINTMSK_OUTEPMSK6_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK6_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK6_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK7_LSB 0x17 -#define GC_USB_DAINTMSK_OUTEPMSK7_MASK 0x800000 -#define GC_USB_DAINTMSK_OUTEPMSK7_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK7_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK7_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK8_LSB 0x18 -#define GC_USB_DAINTMSK_OUTEPMSK8_MASK 0x1000000 -#define GC_USB_DAINTMSK_OUTEPMSK8_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK8_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK8_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK9_LSB 0x19 -#define GC_USB_DAINTMSK_OUTEPMSK9_MASK 0x2000000 -#define GC_USB_DAINTMSK_OUTEPMSK9_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK9_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK9_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK10_LSB 0x1a -#define GC_USB_DAINTMSK_OUTEPMSK10_MASK 0x4000000 -#define GC_USB_DAINTMSK_OUTEPMSK10_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK10_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK10_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK11_LSB 0x1b -#define GC_USB_DAINTMSK_OUTEPMSK11_MASK 0x8000000 -#define GC_USB_DAINTMSK_OUTEPMSK11_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK11_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK11_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK12_LSB 0x1c -#define GC_USB_DAINTMSK_OUTEPMSK12_MASK 0x10000000 -#define GC_USB_DAINTMSK_OUTEPMSK12_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK12_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK12_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK13_LSB 0x1d -#define GC_USB_DAINTMSK_OUTEPMSK13_MASK 0x20000000 -#define GC_USB_DAINTMSK_OUTEPMSK13_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK13_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK13_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK14_LSB 0x1e -#define GC_USB_DAINTMSK_OUTEPMSK14_MASK 0x40000000 -#define GC_USB_DAINTMSK_OUTEPMSK14_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK14_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK14_OFFSET 0x81c -#define GC_USB_DAINTMSK_OUTEPMSK15_LSB 0x1f -#define GC_USB_DAINTMSK_OUTEPMSK15_MASK 0x80000000 -#define GC_USB_DAINTMSK_OUTEPMSK15_SIZE 0x1 -#define GC_USB_DAINTMSK_OUTEPMSK15_DEFAULT 0x0 -#define GC_USB_DAINTMSK_OUTEPMSK15_OFFSET 0x81c -#define GC_USB_DVBUSDIS_DVBUSDIS_LSB 0x0 -#define GC_USB_DVBUSDIS_DVBUSDIS_MASK 0xffff -#define GC_USB_DVBUSDIS_DVBUSDIS_SIZE 0x10 -#define GC_USB_DVBUSDIS_DVBUSDIS_DEFAULT 0x0 -#define GC_USB_DVBUSDIS_DVBUSDIS_OFFSET 0x828 -#define GC_USB_DVBUSPULSE_DVBUSPULSE_LSB 0x0 -#define GC_USB_DVBUSPULSE_DVBUSPULSE_MASK 0xfff -#define GC_USB_DVBUSPULSE_DVBUSPULSE_SIZE 0xc -#define GC_USB_DVBUSPULSE_DVBUSPULSE_DEFAULT 0x0 -#define GC_USB_DVBUSPULSE_DVBUSPULSE_OFFSET 0x82c -#define GC_USB_DTHRCTL_NONISOTHREN_LSB 0x0 -#define GC_USB_DTHRCTL_NONISOTHREN_MASK 0x1 -#define GC_USB_DTHRCTL_NONISOTHREN_SIZE 0x1 -#define GC_USB_DTHRCTL_NONISOTHREN_DEFAULT 0x0 -#define GC_USB_DTHRCTL_NONISOTHREN_OFFSET 0x830 -#define GC_USB_DTHRCTL_ISOTHREN_LSB 0x1 -#define GC_USB_DTHRCTL_ISOTHREN_MASK 0x2 -#define GC_USB_DTHRCTL_ISOTHREN_SIZE 0x1 -#define GC_USB_DTHRCTL_ISOTHREN_DEFAULT 0x0 -#define GC_USB_DTHRCTL_ISOTHREN_OFFSET 0x830 -#define GC_USB_DTHRCTL_TXTHRLEN_LSB 0x2 -#define GC_USB_DTHRCTL_TXTHRLEN_MASK 0x7fc -#define GC_USB_DTHRCTL_TXTHRLEN_SIZE 0x9 -#define GC_USB_DTHRCTL_TXTHRLEN_DEFAULT 0x0 -#define GC_USB_DTHRCTL_TXTHRLEN_OFFSET 0x830 -#define GC_USB_DTHRCTL_AHBTHRRATIO_LSB 0xb -#define GC_USB_DTHRCTL_AHBTHRRATIO_MASK 0x1800 -#define GC_USB_DTHRCTL_AHBTHRRATIO_SIZE 0x2 -#define GC_USB_DTHRCTL_AHBTHRRATIO_DEFAULT 0x0 -#define GC_USB_DTHRCTL_AHBTHRRATIO_OFFSET 0x830 -#define GC_USB_DTHRCTL_RXTHREN_LSB 0x10 -#define GC_USB_DTHRCTL_RXTHREN_MASK 0x10000 -#define GC_USB_DTHRCTL_RXTHREN_SIZE 0x1 -#define GC_USB_DTHRCTL_RXTHREN_DEFAULT 0x0 -#define GC_USB_DTHRCTL_RXTHREN_OFFSET 0x830 -#define GC_USB_DTHRCTL_RXTHRLEN_LSB 0x11 -#define GC_USB_DTHRCTL_RXTHRLEN_MASK 0x3fe0000 -#define GC_USB_DTHRCTL_RXTHRLEN_SIZE 0x9 -#define GC_USB_DTHRCTL_RXTHRLEN_DEFAULT 0x0 -#define GC_USB_DTHRCTL_RXTHRLEN_OFFSET 0x830 -#define GC_USB_DTHRCTL_ARBPRKEN_LSB 0x1b -#define GC_USB_DTHRCTL_ARBPRKEN_MASK 0x8000000 -#define GC_USB_DTHRCTL_ARBPRKEN_SIZE 0x1 -#define GC_USB_DTHRCTL_ARBPRKEN_DEFAULT 0x0 -#define GC_USB_DTHRCTL_ARBPRKEN_OFFSET 0x830 -#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_LSB 0x0 -#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_MASK 0xffff -#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_SIZE 0x10 -#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_DEFAULT 0x0 -#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_OFFSET 0x834 -#define GC_USB_DIEPCTL0_MPS_LSB 0x0 -#define GC_USB_DIEPCTL0_MPS_MASK 0x3 -#define GC_USB_DIEPCTL0_MPS_SIZE 0x2 -#define GC_USB_DIEPCTL0_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_MPS_OFFSET 0x900 -#define GC_USB_DIEPCTL0_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL0_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL0_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL0_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_USBACTEP_OFFSET 0x900 -#define GC_USB_DIEPCTL0_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL0_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL0_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL0_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_NAKSTS_OFFSET 0x900 -#define GC_USB_DIEPCTL0_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL0_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL0_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL0_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_EPTYPE_OFFSET 0x900 -#define GC_USB_DIEPCTL0_STALL_LSB 0x15 -#define GC_USB_DIEPCTL0_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL0_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL0_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_STALL_OFFSET 0x900 -#define GC_USB_DIEPCTL0_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL0_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL0_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL0_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_TXFNUM_OFFSET 0x900 -#define GC_USB_DIEPCTL0_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL0_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL0_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL0_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_CNAK_OFFSET 0x900 -#define GC_USB_DIEPCTL0_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL0_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL0_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL0_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_SNAK_OFFSET 0x900 -#define GC_USB_DIEPCTL0_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL0_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL0_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL0_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_EPDIS_OFFSET 0x900 -#define GC_USB_DIEPCTL0_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL0_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL0_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL0_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL0_EPENA_OFFSET 0x900 -#define GC_USB_DIEPINT0_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT0_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT0_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT0_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT0_XFERCOMPL_OFFSET 0x908 -#define GC_USB_DIEPINT0_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT0_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT0_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT0_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT0_EPDISBLD_OFFSET 0x908 -#define GC_USB_DIEPINT0_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT0_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT0_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT0_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT0_AHBERR_OFFSET 0x908 -#define GC_USB_DIEPINT0_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT0_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT0_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT0_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT0_TIMEOUT_OFFSET 0x908 -#define GC_USB_DIEPINT0_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT0_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT0_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT0_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT0_INTKNTXFEMP_OFFSET 0x908 -#define GC_USB_DIEPINT0_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT0_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT0_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT0_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT0_INTKNEPMIS_OFFSET 0x908 -#define GC_USB_DIEPINT0_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT0_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT0_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT0_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT0_INEPNAKEFF_OFFSET 0x908 -#define GC_USB_DIEPINT0_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT0_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT0_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT0_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT0_TXFEMP_OFFSET 0x908 -#define GC_USB_DIEPINT0_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT0_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT0_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT0_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT0_TXFIFOUNDRN_OFFSET 0x908 -#define GC_USB_DIEPINT0_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT0_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT0_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT0_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT0_BNAINTR_OFFSET 0x908 -#define GC_USB_DIEPINT0_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT0_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT0_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT0_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT0_PKTDRPSTS_OFFSET 0x908 -#define GC_USB_DIEPINT0_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT0_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT0_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT0_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT0_BBLEERR_OFFSET 0x908 -#define GC_USB_DIEPINT0_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT0_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT0_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT0_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT0_NAKINTRPT_OFFSET 0x908 -#define GC_USB_DIEPINT0_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT0_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT0_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT0_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT0_NYETINTRPT_OFFSET 0x908 -#define GC_USB_DIEPTSIZ0_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ0_XFERSIZE_MASK 0x7f -#define GC_USB_DIEPTSIZ0_XFERSIZE_SIZE 0x7 -#define GC_USB_DIEPTSIZ0_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ0_XFERSIZE_OFFSET 0x910 -#define GC_USB_DIEPTSIZ0_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ0_PKTCNT_MASK 0x180000 -#define GC_USB_DIEPTSIZ0_PKTCNT_SIZE 0x2 -#define GC_USB_DIEPTSIZ0_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ0_PKTCNT_OFFSET 0x910 -#define GC_USB_DIEPDMA0_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA0_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA0_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA0_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA0_DMAADDR_OFFSET 0x914 -#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_OFFSET 0x918 -#define GC_USB_DIEPDMAB0_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB0_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB0_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB0_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB0_DMABUFFERADDR_OFFSET 0x91c -#define GC_USB_DIEPCTL1_MPS_LSB 0x0 -#define GC_USB_DIEPCTL1_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL1_MPS_SIZE 0xb -#define GC_USB_DIEPCTL1_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_MPS_OFFSET 0x920 -#define GC_USB_DIEPCTL1_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL1_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL1_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL1_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_USBACTEP_OFFSET 0x920 -#define GC_USB_DIEPCTL1_DPID_LSB 0x10 -#define GC_USB_DIEPCTL1_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL1_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL1_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_DPID_OFFSET 0x920 -#define GC_USB_DIEPCTL1_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL1_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL1_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL1_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_NAKSTS_OFFSET 0x920 -#define GC_USB_DIEPCTL1_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL1_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL1_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL1_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_EPTYPE_OFFSET 0x920 -#define GC_USB_DIEPCTL1_STALL_LSB 0x15 -#define GC_USB_DIEPCTL1_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL1_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL1_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_STALL_OFFSET 0x920 -#define GC_USB_DIEPCTL1_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL1_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL1_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL1_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_TXFNUM_OFFSET 0x920 -#define GC_USB_DIEPCTL1_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL1_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL1_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL1_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_CNAK_OFFSET 0x920 -#define GC_USB_DIEPCTL1_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL1_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL1_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL1_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_SNAK_OFFSET 0x920 -#define GC_USB_DIEPCTL1_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL1_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL1_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL1_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_SETD0PID_OFFSET 0x920 -#define GC_USB_DIEPCTL1_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL1_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL1_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL1_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_SETD1PID_OFFSET 0x920 -#define GC_USB_DIEPCTL1_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL1_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL1_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL1_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_EPDIS_OFFSET 0x920 -#define GC_USB_DIEPCTL1_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL1_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL1_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL1_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL1_EPENA_OFFSET 0x920 -#define GC_USB_DIEPINT1_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT1_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT1_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT1_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT1_XFERCOMPL_OFFSET 0x928 -#define GC_USB_DIEPINT1_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT1_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT1_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT1_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT1_EPDISBLD_OFFSET 0x928 -#define GC_USB_DIEPINT1_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT1_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT1_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT1_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT1_AHBERR_OFFSET 0x928 -#define GC_USB_DIEPINT1_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT1_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT1_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT1_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT1_TIMEOUT_OFFSET 0x928 -#define GC_USB_DIEPINT1_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT1_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT1_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT1_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT1_INTKNTXFEMP_OFFSET 0x928 -#define GC_USB_DIEPINT1_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT1_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT1_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT1_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT1_INTKNEPMIS_OFFSET 0x928 -#define GC_USB_DIEPINT1_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT1_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT1_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT1_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT1_INEPNAKEFF_OFFSET 0x928 -#define GC_USB_DIEPINT1_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT1_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT1_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT1_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT1_TXFEMP_OFFSET 0x928 -#define GC_USB_DIEPINT1_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT1_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT1_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT1_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT1_TXFIFOUNDRN_OFFSET 0x928 -#define GC_USB_DIEPINT1_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT1_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT1_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT1_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT1_BNAINTR_OFFSET 0x928 -#define GC_USB_DIEPINT1_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT1_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT1_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT1_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT1_PKTDRPSTS_OFFSET 0x928 -#define GC_USB_DIEPINT1_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT1_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT1_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT1_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT1_BBLEERR_OFFSET 0x928 -#define GC_USB_DIEPINT1_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT1_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT1_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT1_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT1_NAKINTRPT_OFFSET 0x928 -#define GC_USB_DIEPINT1_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT1_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT1_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT1_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT1_NYETINTRPT_OFFSET 0x928 -#define GC_USB_DIEPTSIZ1_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ1_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ1_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ1_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ1_XFERSIZE_OFFSET 0x930 -#define GC_USB_DIEPTSIZ1_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ1_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ1_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ1_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ1_PKTCNT_OFFSET 0x930 -#define GC_USB_DIEPTSIZ1_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ1_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ1_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ1_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ1_MC_OFFSET 0x930 -#define GC_USB_DIEPDMA1_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA1_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA1_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA1_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA1_DMAADDR_OFFSET 0x934 -#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_OFFSET 0x938 -#define GC_USB_DIEPDMAB1_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB1_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB1_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB1_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB1_DMABUFFERADDR_OFFSET 0x93c -#define GC_USB_DIEPCTL2_MPS_LSB 0x0 -#define GC_USB_DIEPCTL2_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL2_MPS_SIZE 0xb -#define GC_USB_DIEPCTL2_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_MPS_OFFSET 0x940 -#define GC_USB_DIEPCTL2_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL2_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL2_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL2_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_USBACTEP_OFFSET 0x940 -#define GC_USB_DIEPCTL2_DPID_LSB 0x10 -#define GC_USB_DIEPCTL2_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL2_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL2_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_DPID_OFFSET 0x940 -#define GC_USB_DIEPCTL2_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL2_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL2_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL2_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_NAKSTS_OFFSET 0x940 -#define GC_USB_DIEPCTL2_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL2_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL2_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL2_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_EPTYPE_OFFSET 0x940 -#define GC_USB_DIEPCTL2_STALL_LSB 0x15 -#define GC_USB_DIEPCTL2_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL2_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL2_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_STALL_OFFSET 0x940 -#define GC_USB_DIEPCTL2_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL2_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL2_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL2_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_TXFNUM_OFFSET 0x940 -#define GC_USB_DIEPCTL2_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL2_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL2_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL2_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_CNAK_OFFSET 0x940 -#define GC_USB_DIEPCTL2_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL2_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL2_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL2_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_SNAK_OFFSET 0x940 -#define GC_USB_DIEPCTL2_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL2_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL2_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL2_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_SETD0PID_OFFSET 0x940 -#define GC_USB_DIEPCTL2_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL2_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL2_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL2_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_SETD1PID_OFFSET 0x940 -#define GC_USB_DIEPCTL2_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL2_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL2_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL2_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_EPDIS_OFFSET 0x940 -#define GC_USB_DIEPCTL2_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL2_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL2_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL2_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL2_EPENA_OFFSET 0x940 -#define GC_USB_DIEPINT2_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT2_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT2_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT2_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT2_XFERCOMPL_OFFSET 0x948 -#define GC_USB_DIEPINT2_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT2_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT2_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT2_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT2_EPDISBLD_OFFSET 0x948 -#define GC_USB_DIEPINT2_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT2_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT2_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT2_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT2_AHBERR_OFFSET 0x948 -#define GC_USB_DIEPINT2_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT2_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT2_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT2_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT2_TIMEOUT_OFFSET 0x948 -#define GC_USB_DIEPINT2_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT2_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT2_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT2_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT2_INTKNTXFEMP_OFFSET 0x948 -#define GC_USB_DIEPINT2_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT2_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT2_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT2_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT2_INTKNEPMIS_OFFSET 0x948 -#define GC_USB_DIEPINT2_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT2_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT2_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT2_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT2_INEPNAKEFF_OFFSET 0x948 -#define GC_USB_DIEPINT2_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT2_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT2_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT2_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT2_TXFEMP_OFFSET 0x948 -#define GC_USB_DIEPINT2_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT2_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT2_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT2_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT2_TXFIFOUNDRN_OFFSET 0x948 -#define GC_USB_DIEPINT2_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT2_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT2_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT2_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT2_BNAINTR_OFFSET 0x948 -#define GC_USB_DIEPINT2_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT2_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT2_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT2_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT2_PKTDRPSTS_OFFSET 0x948 -#define GC_USB_DIEPINT2_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT2_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT2_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT2_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT2_BBLEERR_OFFSET 0x948 -#define GC_USB_DIEPINT2_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT2_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT2_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT2_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT2_NAKINTRPT_OFFSET 0x948 -#define GC_USB_DIEPINT2_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT2_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT2_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT2_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT2_NYETINTRPT_OFFSET 0x948 -#define GC_USB_DIEPTSIZ2_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ2_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ2_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ2_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ2_XFERSIZE_OFFSET 0x950 -#define GC_USB_DIEPTSIZ2_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ2_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ2_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ2_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ2_PKTCNT_OFFSET 0x950 -#define GC_USB_DIEPTSIZ2_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ2_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ2_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ2_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ2_MC_OFFSET 0x950 -#define GC_USB_DIEPDMA2_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA2_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA2_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA2_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA2_DMAADDR_OFFSET 0x954 -#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_OFFSET 0x958 -#define GC_USB_DIEPDMAB2_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB2_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB2_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB2_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB2_DMABUFFERADDR_OFFSET 0x95c -#define GC_USB_DIEPCTL3_MPS_LSB 0x0 -#define GC_USB_DIEPCTL3_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL3_MPS_SIZE 0xb -#define GC_USB_DIEPCTL3_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_MPS_OFFSET 0x960 -#define GC_USB_DIEPCTL3_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL3_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL3_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL3_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_USBACTEP_OFFSET 0x960 -#define GC_USB_DIEPCTL3_DPID_LSB 0x10 -#define GC_USB_DIEPCTL3_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL3_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL3_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_DPID_OFFSET 0x960 -#define GC_USB_DIEPCTL3_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL3_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL3_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL3_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_NAKSTS_OFFSET 0x960 -#define GC_USB_DIEPCTL3_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL3_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL3_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL3_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_EPTYPE_OFFSET 0x960 -#define GC_USB_DIEPCTL3_STALL_LSB 0x15 -#define GC_USB_DIEPCTL3_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL3_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL3_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_STALL_OFFSET 0x960 -#define GC_USB_DIEPCTL3_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL3_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL3_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL3_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_TXFNUM_OFFSET 0x960 -#define GC_USB_DIEPCTL3_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL3_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL3_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL3_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_CNAK_OFFSET 0x960 -#define GC_USB_DIEPCTL3_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL3_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL3_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL3_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_SNAK_OFFSET 0x960 -#define GC_USB_DIEPCTL3_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL3_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL3_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL3_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_SETD0PID_OFFSET 0x960 -#define GC_USB_DIEPCTL3_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL3_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL3_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL3_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_SETD1PID_OFFSET 0x960 -#define GC_USB_DIEPCTL3_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL3_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL3_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL3_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_EPDIS_OFFSET 0x960 -#define GC_USB_DIEPCTL3_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL3_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL3_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL3_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL3_EPENA_OFFSET 0x960 -#define GC_USB_DIEPINT3_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT3_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT3_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT3_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT3_XFERCOMPL_OFFSET 0x968 -#define GC_USB_DIEPINT3_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT3_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT3_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT3_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT3_EPDISBLD_OFFSET 0x968 -#define GC_USB_DIEPINT3_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT3_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT3_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT3_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT3_AHBERR_OFFSET 0x968 -#define GC_USB_DIEPINT3_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT3_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT3_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT3_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT3_TIMEOUT_OFFSET 0x968 -#define GC_USB_DIEPINT3_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT3_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT3_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT3_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT3_INTKNTXFEMP_OFFSET 0x968 -#define GC_USB_DIEPINT3_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT3_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT3_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT3_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT3_INTKNEPMIS_OFFSET 0x968 -#define GC_USB_DIEPINT3_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT3_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT3_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT3_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT3_INEPNAKEFF_OFFSET 0x968 -#define GC_USB_DIEPINT3_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT3_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT3_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT3_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT3_TXFEMP_OFFSET 0x968 -#define GC_USB_DIEPINT3_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT3_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT3_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT3_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT3_TXFIFOUNDRN_OFFSET 0x968 -#define GC_USB_DIEPINT3_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT3_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT3_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT3_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT3_BNAINTR_OFFSET 0x968 -#define GC_USB_DIEPINT3_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT3_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT3_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT3_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT3_PKTDRPSTS_OFFSET 0x968 -#define GC_USB_DIEPINT3_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT3_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT3_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT3_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT3_BBLEERR_OFFSET 0x968 -#define GC_USB_DIEPINT3_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT3_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT3_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT3_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT3_NAKINTRPT_OFFSET 0x968 -#define GC_USB_DIEPINT3_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT3_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT3_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT3_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT3_NYETINTRPT_OFFSET 0x968 -#define GC_USB_DIEPTSIZ3_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ3_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ3_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ3_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ3_XFERSIZE_OFFSET 0x970 -#define GC_USB_DIEPTSIZ3_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ3_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ3_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ3_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ3_PKTCNT_OFFSET 0x970 -#define GC_USB_DIEPTSIZ3_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ3_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ3_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ3_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ3_MC_OFFSET 0x970 -#define GC_USB_DIEPDMA3_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA3_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA3_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA3_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA3_DMAADDR_OFFSET 0x974 -#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_OFFSET 0x978 -#define GC_USB_DIEPDMAB3_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB3_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB3_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB3_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB3_DMABUFFERADDR_OFFSET 0x97c -#define GC_USB_DIEPCTL4_MPS_LSB 0x0 -#define GC_USB_DIEPCTL4_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL4_MPS_SIZE 0xb -#define GC_USB_DIEPCTL4_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_MPS_OFFSET 0x980 -#define GC_USB_DIEPCTL4_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL4_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL4_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL4_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_USBACTEP_OFFSET 0x980 -#define GC_USB_DIEPCTL4_DPID_LSB 0x10 -#define GC_USB_DIEPCTL4_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL4_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL4_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_DPID_OFFSET 0x980 -#define GC_USB_DIEPCTL4_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL4_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL4_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL4_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_NAKSTS_OFFSET 0x980 -#define GC_USB_DIEPCTL4_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL4_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL4_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL4_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_EPTYPE_OFFSET 0x980 -#define GC_USB_DIEPCTL4_STALL_LSB 0x15 -#define GC_USB_DIEPCTL4_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL4_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL4_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_STALL_OFFSET 0x980 -#define GC_USB_DIEPCTL4_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL4_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL4_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL4_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_TXFNUM_OFFSET 0x980 -#define GC_USB_DIEPCTL4_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL4_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL4_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL4_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_CNAK_OFFSET 0x980 -#define GC_USB_DIEPCTL4_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL4_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL4_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL4_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_SNAK_OFFSET 0x980 -#define GC_USB_DIEPCTL4_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL4_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL4_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL4_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_SETD0PID_OFFSET 0x980 -#define GC_USB_DIEPCTL4_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL4_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL4_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL4_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_SETD1PID_OFFSET 0x980 -#define GC_USB_DIEPCTL4_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL4_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL4_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL4_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_EPDIS_OFFSET 0x980 -#define GC_USB_DIEPCTL4_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL4_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL4_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL4_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL4_EPENA_OFFSET 0x980 -#define GC_USB_DIEPINT4_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT4_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT4_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT4_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT4_XFERCOMPL_OFFSET 0x988 -#define GC_USB_DIEPINT4_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT4_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT4_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT4_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT4_EPDISBLD_OFFSET 0x988 -#define GC_USB_DIEPINT4_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT4_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT4_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT4_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT4_AHBERR_OFFSET 0x988 -#define GC_USB_DIEPINT4_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT4_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT4_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT4_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT4_TIMEOUT_OFFSET 0x988 -#define GC_USB_DIEPINT4_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT4_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT4_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT4_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT4_INTKNTXFEMP_OFFSET 0x988 -#define GC_USB_DIEPINT4_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT4_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT4_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT4_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT4_INTKNEPMIS_OFFSET 0x988 -#define GC_USB_DIEPINT4_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT4_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT4_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT4_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT4_INEPNAKEFF_OFFSET 0x988 -#define GC_USB_DIEPINT4_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT4_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT4_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT4_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT4_TXFEMP_OFFSET 0x988 -#define GC_USB_DIEPINT4_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT4_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT4_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT4_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT4_TXFIFOUNDRN_OFFSET 0x988 -#define GC_USB_DIEPINT4_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT4_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT4_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT4_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT4_BNAINTR_OFFSET 0x988 -#define GC_USB_DIEPINT4_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT4_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT4_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT4_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT4_PKTDRPSTS_OFFSET 0x988 -#define GC_USB_DIEPINT4_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT4_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT4_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT4_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT4_BBLEERR_OFFSET 0x988 -#define GC_USB_DIEPINT4_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT4_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT4_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT4_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT4_NAKINTRPT_OFFSET 0x988 -#define GC_USB_DIEPINT4_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT4_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT4_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT4_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT4_NYETINTRPT_OFFSET 0x988 -#define GC_USB_DIEPTSIZ4_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ4_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ4_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ4_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ4_XFERSIZE_OFFSET 0x990 -#define GC_USB_DIEPTSIZ4_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ4_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ4_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ4_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ4_PKTCNT_OFFSET 0x990 -#define GC_USB_DIEPTSIZ4_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ4_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ4_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ4_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ4_MC_OFFSET 0x990 -#define GC_USB_DIEPDMA4_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA4_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA4_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA4_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA4_DMAADDR_OFFSET 0x994 -#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_OFFSET 0x998 -#define GC_USB_DIEPDMAB4_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB4_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB4_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB4_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB4_DMABUFFERADDR_OFFSET 0x99c -#define GC_USB_DIEPCTL5_MPS_LSB 0x0 -#define GC_USB_DIEPCTL5_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL5_MPS_SIZE 0xb -#define GC_USB_DIEPCTL5_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_MPS_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL5_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL5_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL5_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_USBACTEP_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_DPID_LSB 0x10 -#define GC_USB_DIEPCTL5_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL5_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL5_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_DPID_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL5_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL5_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL5_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_NAKSTS_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL5_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL5_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL5_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_EPTYPE_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_STALL_LSB 0x15 -#define GC_USB_DIEPCTL5_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL5_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL5_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_STALL_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL5_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL5_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL5_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_TXFNUM_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL5_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL5_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL5_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_CNAK_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL5_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL5_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL5_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_SNAK_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL5_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL5_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL5_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_SETD0PID_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL5_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL5_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL5_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_SETD1PID_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL5_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL5_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL5_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_EPDIS_OFFSET 0x9a0 -#define GC_USB_DIEPCTL5_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL5_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL5_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL5_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL5_EPENA_OFFSET 0x9a0 -#define GC_USB_DIEPINT5_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT5_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT5_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT5_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT5_XFERCOMPL_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT5_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT5_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT5_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT5_EPDISBLD_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT5_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT5_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT5_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT5_AHBERR_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT5_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT5_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT5_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT5_TIMEOUT_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT5_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT5_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT5_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT5_INTKNTXFEMP_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT5_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT5_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT5_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT5_INTKNEPMIS_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT5_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT5_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT5_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT5_INEPNAKEFF_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT5_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT5_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT5_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT5_TXFEMP_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT5_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT5_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT5_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT5_TXFIFOUNDRN_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT5_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT5_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT5_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT5_BNAINTR_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT5_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT5_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT5_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT5_PKTDRPSTS_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT5_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT5_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT5_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT5_BBLEERR_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT5_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT5_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT5_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT5_NAKINTRPT_OFFSET 0x9a8 -#define GC_USB_DIEPINT5_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT5_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT5_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT5_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT5_NYETINTRPT_OFFSET 0x9a8 -#define GC_USB_DIEPTSIZ5_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ5_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ5_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ5_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ5_XFERSIZE_OFFSET 0x9b0 -#define GC_USB_DIEPTSIZ5_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ5_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ5_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ5_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ5_PKTCNT_OFFSET 0x9b0 -#define GC_USB_DIEPTSIZ5_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ5_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ5_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ5_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ5_MC_OFFSET 0x9b0 -#define GC_USB_DIEPDMA5_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA5_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA5_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA5_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA5_DMAADDR_OFFSET 0x9b4 -#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_OFFSET 0x9b8 -#define GC_USB_DIEPDMAB5_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB5_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB5_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB5_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB5_DMABUFFERADDR_OFFSET 0x9bc -#define GC_USB_DIEPCTL6_MPS_LSB 0x0 -#define GC_USB_DIEPCTL6_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL6_MPS_SIZE 0xb -#define GC_USB_DIEPCTL6_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_MPS_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL6_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL6_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL6_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_USBACTEP_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_DPID_LSB 0x10 -#define GC_USB_DIEPCTL6_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL6_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL6_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_DPID_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL6_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL6_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL6_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_NAKSTS_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL6_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL6_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL6_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_EPTYPE_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_STALL_LSB 0x15 -#define GC_USB_DIEPCTL6_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL6_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL6_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_STALL_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL6_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL6_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL6_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_TXFNUM_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL6_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL6_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL6_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_CNAK_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL6_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL6_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL6_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_SNAK_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL6_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL6_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL6_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_SETD0PID_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL6_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL6_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL6_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_SETD1PID_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL6_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL6_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL6_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_EPDIS_OFFSET 0x9c0 -#define GC_USB_DIEPCTL6_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL6_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL6_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL6_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL6_EPENA_OFFSET 0x9c0 -#define GC_USB_DIEPINT6_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT6_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT6_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT6_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT6_XFERCOMPL_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT6_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT6_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT6_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT6_EPDISBLD_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT6_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT6_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT6_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT6_AHBERR_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT6_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT6_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT6_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT6_TIMEOUT_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT6_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT6_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT6_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT6_INTKNTXFEMP_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT6_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT6_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT6_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT6_INTKNEPMIS_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT6_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT6_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT6_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT6_INEPNAKEFF_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT6_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT6_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT6_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT6_TXFEMP_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT6_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT6_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT6_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT6_TXFIFOUNDRN_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT6_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT6_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT6_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT6_BNAINTR_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT6_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT6_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT6_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT6_PKTDRPSTS_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT6_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT6_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT6_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT6_BBLEERR_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT6_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT6_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT6_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT6_NAKINTRPT_OFFSET 0x9c8 -#define GC_USB_DIEPINT6_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT6_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT6_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT6_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT6_NYETINTRPT_OFFSET 0x9c8 -#define GC_USB_DIEPTSIZ6_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ6_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ6_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ6_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ6_XFERSIZE_OFFSET 0x9d0 -#define GC_USB_DIEPTSIZ6_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ6_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ6_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ6_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ6_PKTCNT_OFFSET 0x9d0 -#define GC_USB_DIEPTSIZ6_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ6_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ6_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ6_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ6_MC_OFFSET 0x9d0 -#define GC_USB_DIEPDMA6_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA6_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA6_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA6_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA6_DMAADDR_OFFSET 0x9d4 -#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_OFFSET 0x9d8 -#define GC_USB_DIEPDMAB6_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB6_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB6_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB6_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB6_DMABUFFERADDR_OFFSET 0x9dc -#define GC_USB_DIEPCTL7_MPS_LSB 0x0 -#define GC_USB_DIEPCTL7_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL7_MPS_SIZE 0xb -#define GC_USB_DIEPCTL7_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_MPS_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL7_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL7_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL7_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_USBACTEP_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_DPID_LSB 0x10 -#define GC_USB_DIEPCTL7_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL7_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL7_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_DPID_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL7_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL7_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL7_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_NAKSTS_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL7_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL7_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL7_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_EPTYPE_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_STALL_LSB 0x15 -#define GC_USB_DIEPCTL7_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL7_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL7_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_STALL_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL7_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL7_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL7_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_TXFNUM_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL7_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL7_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL7_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_CNAK_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL7_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL7_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL7_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_SNAK_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL7_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL7_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL7_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_SETD0PID_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL7_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL7_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL7_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_SETD1PID_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL7_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL7_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL7_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_EPDIS_OFFSET 0x9e0 -#define GC_USB_DIEPCTL7_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL7_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL7_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL7_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL7_EPENA_OFFSET 0x9e0 -#define GC_USB_DIEPINT7_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT7_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT7_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT7_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT7_XFERCOMPL_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT7_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT7_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT7_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT7_EPDISBLD_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT7_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT7_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT7_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT7_AHBERR_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT7_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT7_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT7_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT7_TIMEOUT_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT7_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT7_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT7_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT7_INTKNTXFEMP_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT7_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT7_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT7_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT7_INTKNEPMIS_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT7_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT7_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT7_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT7_INEPNAKEFF_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT7_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT7_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT7_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT7_TXFEMP_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT7_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT7_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT7_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT7_TXFIFOUNDRN_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT7_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT7_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT7_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT7_BNAINTR_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT7_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT7_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT7_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT7_PKTDRPSTS_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT7_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT7_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT7_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT7_BBLEERR_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT7_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT7_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT7_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT7_NAKINTRPT_OFFSET 0x9e8 -#define GC_USB_DIEPINT7_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT7_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT7_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT7_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT7_NYETINTRPT_OFFSET 0x9e8 -#define GC_USB_DIEPTSIZ7_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ7_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ7_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ7_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ7_XFERSIZE_OFFSET 0x9f0 -#define GC_USB_DIEPTSIZ7_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ7_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ7_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ7_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ7_PKTCNT_OFFSET 0x9f0 -#define GC_USB_DIEPTSIZ7_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ7_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ7_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ7_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ7_MC_OFFSET 0x9f0 -#define GC_USB_DIEPDMA7_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA7_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA7_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA7_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA7_DMAADDR_OFFSET 0x9f4 -#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_OFFSET 0x9f8 -#define GC_USB_DIEPDMAB7_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB7_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB7_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB7_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB7_DMABUFFERADDR_OFFSET 0x9fc -#define GC_USB_DIEPCTL8_MPS_LSB 0x0 -#define GC_USB_DIEPCTL8_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL8_MPS_SIZE 0xb -#define GC_USB_DIEPCTL8_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_MPS_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL8_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL8_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL8_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_USBACTEP_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_DPID_LSB 0x10 -#define GC_USB_DIEPCTL8_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL8_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL8_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_DPID_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL8_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL8_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL8_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_NAKSTS_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL8_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL8_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL8_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_EPTYPE_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_STALL_LSB 0x15 -#define GC_USB_DIEPCTL8_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL8_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL8_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_STALL_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL8_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL8_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL8_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_TXFNUM_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL8_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL8_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL8_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_CNAK_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL8_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL8_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL8_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_SNAK_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL8_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL8_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL8_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_SETD0PID_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL8_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL8_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL8_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_SETD1PID_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL8_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL8_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL8_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_EPDIS_OFFSET 0xa00 -#define GC_USB_DIEPCTL8_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL8_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL8_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL8_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL8_EPENA_OFFSET 0xa00 -#define GC_USB_DIEPINT8_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT8_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT8_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT8_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT8_XFERCOMPL_OFFSET 0xa08 -#define GC_USB_DIEPINT8_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT8_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT8_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT8_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT8_EPDISBLD_OFFSET 0xa08 -#define GC_USB_DIEPINT8_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT8_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT8_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT8_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT8_AHBERR_OFFSET 0xa08 -#define GC_USB_DIEPINT8_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT8_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT8_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT8_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT8_TIMEOUT_OFFSET 0xa08 -#define GC_USB_DIEPINT8_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT8_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT8_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT8_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT8_INTKNTXFEMP_OFFSET 0xa08 -#define GC_USB_DIEPINT8_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT8_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT8_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT8_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT8_INTKNEPMIS_OFFSET 0xa08 -#define GC_USB_DIEPINT8_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT8_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT8_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT8_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT8_INEPNAKEFF_OFFSET 0xa08 -#define GC_USB_DIEPINT8_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT8_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT8_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT8_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT8_TXFEMP_OFFSET 0xa08 -#define GC_USB_DIEPINT8_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT8_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT8_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT8_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT8_TXFIFOUNDRN_OFFSET 0xa08 -#define GC_USB_DIEPINT8_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT8_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT8_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT8_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT8_BNAINTR_OFFSET 0xa08 -#define GC_USB_DIEPINT8_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT8_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT8_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT8_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT8_PKTDRPSTS_OFFSET 0xa08 -#define GC_USB_DIEPINT8_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT8_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT8_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT8_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT8_BBLEERR_OFFSET 0xa08 -#define GC_USB_DIEPINT8_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT8_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT8_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT8_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT8_NAKINTRPT_OFFSET 0xa08 -#define GC_USB_DIEPINT8_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT8_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT8_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT8_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT8_NYETINTRPT_OFFSET 0xa08 -#define GC_USB_DIEPTSIZ8_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ8_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ8_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ8_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ8_XFERSIZE_OFFSET 0xa10 -#define GC_USB_DIEPTSIZ8_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ8_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ8_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ8_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ8_PKTCNT_OFFSET 0xa10 -#define GC_USB_DIEPTSIZ8_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ8_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ8_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ8_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ8_MC_OFFSET 0xa10 -#define GC_USB_DIEPDMA8_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA8_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA8_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA8_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA8_DMAADDR_OFFSET 0xa14 -#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_OFFSET 0xa18 -#define GC_USB_DIEPDMAB8_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB8_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB8_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB8_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB8_DMABUFFERADDR_OFFSET 0xa1c -#define GC_USB_DIEPCTL9_MPS_LSB 0x0 -#define GC_USB_DIEPCTL9_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL9_MPS_SIZE 0xb -#define GC_USB_DIEPCTL9_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_MPS_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL9_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL9_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL9_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_USBACTEP_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_DPID_LSB 0x10 -#define GC_USB_DIEPCTL9_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL9_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL9_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_DPID_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL9_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL9_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL9_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_NAKSTS_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL9_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL9_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL9_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_EPTYPE_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_STALL_LSB 0x15 -#define GC_USB_DIEPCTL9_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL9_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL9_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_STALL_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL9_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL9_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL9_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_TXFNUM_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL9_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL9_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL9_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_CNAK_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL9_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL9_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL9_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_SNAK_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL9_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL9_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL9_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_SETD0PID_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL9_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL9_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL9_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_SETD1PID_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL9_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL9_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL9_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_EPDIS_OFFSET 0xa20 -#define GC_USB_DIEPCTL9_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL9_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL9_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL9_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL9_EPENA_OFFSET 0xa20 -#define GC_USB_DIEPINT9_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT9_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT9_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT9_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT9_XFERCOMPL_OFFSET 0xa28 -#define GC_USB_DIEPINT9_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT9_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT9_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT9_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT9_EPDISBLD_OFFSET 0xa28 -#define GC_USB_DIEPINT9_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT9_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT9_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT9_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT9_AHBERR_OFFSET 0xa28 -#define GC_USB_DIEPINT9_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT9_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT9_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT9_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT9_TIMEOUT_OFFSET 0xa28 -#define GC_USB_DIEPINT9_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT9_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT9_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT9_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT9_INTKNTXFEMP_OFFSET 0xa28 -#define GC_USB_DIEPINT9_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT9_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT9_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT9_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT9_INTKNEPMIS_OFFSET 0xa28 -#define GC_USB_DIEPINT9_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT9_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT9_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT9_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT9_INEPNAKEFF_OFFSET 0xa28 -#define GC_USB_DIEPINT9_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT9_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT9_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT9_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT9_TXFEMP_OFFSET 0xa28 -#define GC_USB_DIEPINT9_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT9_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT9_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT9_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT9_TXFIFOUNDRN_OFFSET 0xa28 -#define GC_USB_DIEPINT9_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT9_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT9_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT9_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT9_BNAINTR_OFFSET 0xa28 -#define GC_USB_DIEPINT9_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT9_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT9_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT9_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT9_PKTDRPSTS_OFFSET 0xa28 -#define GC_USB_DIEPINT9_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT9_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT9_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT9_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT9_BBLEERR_OFFSET 0xa28 -#define GC_USB_DIEPINT9_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT9_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT9_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT9_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT9_NAKINTRPT_OFFSET 0xa28 -#define GC_USB_DIEPINT9_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT9_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT9_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT9_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT9_NYETINTRPT_OFFSET 0xa28 -#define GC_USB_DIEPTSIZ9_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ9_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ9_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ9_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ9_XFERSIZE_OFFSET 0xa30 -#define GC_USB_DIEPTSIZ9_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ9_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ9_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ9_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ9_PKTCNT_OFFSET 0xa30 -#define GC_USB_DIEPTSIZ9_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ9_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ9_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ9_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ9_MC_OFFSET 0xa30 -#define GC_USB_DIEPDMA9_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA9_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA9_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA9_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA9_DMAADDR_OFFSET 0xa34 -#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_SIZE 0x10 -#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_OFFSET 0xa38 -#define GC_USB_DIEPDMAB9_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB9_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB9_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB9_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB9_DMABUFFERADDR_OFFSET 0xa3c -#define GC_USB_DIEPCTL10_MPS_LSB 0x0 -#define GC_USB_DIEPCTL10_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL10_MPS_SIZE 0xb -#define GC_USB_DIEPCTL10_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_MPS_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL10_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL10_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL10_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_USBACTEP_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_DPID_LSB 0x10 -#define GC_USB_DIEPCTL10_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL10_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL10_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_DPID_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL10_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL10_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL10_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_NAKSTS_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL10_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL10_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL10_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_EPTYPE_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_STALL_LSB 0x15 -#define GC_USB_DIEPCTL10_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL10_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL10_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_STALL_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL10_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL10_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL10_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_TXFNUM_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL10_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL10_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL10_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_CNAK_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL10_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL10_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL10_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_SNAK_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL10_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL10_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL10_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_SETD0PID_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL10_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL10_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL10_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_SETD1PID_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL10_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL10_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL10_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_EPDIS_OFFSET 0xa40 -#define GC_USB_DIEPCTL10_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL10_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL10_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL10_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL10_EPENA_OFFSET 0xa40 -#define GC_USB_DIEPINT10_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT10_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT10_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT10_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT10_XFERCOMPL_OFFSET 0xa48 -#define GC_USB_DIEPINT10_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT10_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT10_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT10_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT10_EPDISBLD_OFFSET 0xa48 -#define GC_USB_DIEPINT10_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT10_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT10_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT10_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT10_AHBERR_OFFSET 0xa48 -#define GC_USB_DIEPINT10_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT10_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT10_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT10_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT10_TIMEOUT_OFFSET 0xa48 -#define GC_USB_DIEPINT10_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT10_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT10_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT10_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT10_INTKNTXFEMP_OFFSET 0xa48 -#define GC_USB_DIEPINT10_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT10_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT10_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT10_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT10_INTKNEPMIS_OFFSET 0xa48 -#define GC_USB_DIEPINT10_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT10_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT10_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT10_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT10_INEPNAKEFF_OFFSET 0xa48 -#define GC_USB_DIEPINT10_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT10_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT10_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT10_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT10_TXFEMP_OFFSET 0xa48 -#define GC_USB_DIEPINT10_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT10_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT10_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT10_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT10_TXFIFOUNDRN_OFFSET 0xa48 -#define GC_USB_DIEPINT10_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT10_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT10_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT10_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT10_BNAINTR_OFFSET 0xa48 -#define GC_USB_DIEPINT10_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT10_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT10_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT10_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT10_PKTDRPSTS_OFFSET 0xa48 -#define GC_USB_DIEPINT10_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT10_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT10_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT10_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT10_BBLEERR_OFFSET 0xa48 -#define GC_USB_DIEPINT10_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT10_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT10_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT10_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT10_NAKINTRPT_OFFSET 0xa48 -#define GC_USB_DIEPINT10_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT10_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT10_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT10_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT10_NYETINTRPT_OFFSET 0xa48 -#define GC_USB_DIEPTSIZ10_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ10_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ10_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ10_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ10_XFERSIZE_OFFSET 0xa50 -#define GC_USB_DIEPTSIZ10_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ10_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ10_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ10_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ10_PKTCNT_OFFSET 0xa50 -#define GC_USB_DIEPTSIZ10_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ10_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ10_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ10_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ10_MC_OFFSET 0xa50 -#define GC_USB_DIEPDMA10_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA10_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA10_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA10_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA10_DMAADDR_OFFSET 0xa54 -#define GC_USB_DTXFSTS10_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS10_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS10_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_GHWCFG4_PHYDATAWIDTH_LSB 0xe +#define GC_USB_GHWCFG4_PHYDATAWIDTH_MASK 0xc000 +#define GC_USB_GHWCFG4_PHYDATAWIDTH_SIZE 0x2 +#define GC_USB_GHWCFG4_PHYDATAWIDTH_DEFAULT 0x0 +#define GC_USB_GHWCFG4_PHYDATAWIDTH_OFFSET 0x50 +#define GC_USB_GHWCFG4_NUMCTLEPS_LSB 0x10 +#define GC_USB_GHWCFG4_NUMCTLEPS_MASK 0xf0000 +#define GC_USB_GHWCFG4_NUMCTLEPS_SIZE 0x4 +#define GC_USB_GHWCFG4_NUMCTLEPS_DEFAULT 0x0 +#define GC_USB_GHWCFG4_NUMCTLEPS_OFFSET 0x50 +#define GC_USB_GHWCFG4_IDDGFLTR_LSB 0x14 +#define GC_USB_GHWCFG4_IDDGFLTR_MASK 0x100000 +#define GC_USB_GHWCFG4_IDDGFLTR_SIZE 0x1 +#define GC_USB_GHWCFG4_IDDGFLTR_DEFAULT 0x0 +#define GC_USB_GHWCFG4_IDDGFLTR_OFFSET 0x50 +#define GC_USB_GHWCFG4_VBUSVALIDFLTR_LSB 0x15 +#define GC_USB_GHWCFG4_VBUSVALIDFLTR_MASK 0x200000 +#define GC_USB_GHWCFG4_VBUSVALIDFLTR_SIZE 0x1 +#define GC_USB_GHWCFG4_VBUSVALIDFLTR_DEFAULT 0x0 +#define GC_USB_GHWCFG4_VBUSVALIDFLTR_OFFSET 0x50 +#define GC_USB_GHWCFG4_AVALIDFLTR_LSB 0x16 +#define GC_USB_GHWCFG4_AVALIDFLTR_MASK 0x400000 +#define GC_USB_GHWCFG4_AVALIDFLTR_SIZE 0x1 +#define GC_USB_GHWCFG4_AVALIDFLTR_DEFAULT 0x0 +#define GC_USB_GHWCFG4_AVALIDFLTR_OFFSET 0x50 +#define GC_USB_GHWCFG4_BVALIDFLTR_LSB 0x17 +#define GC_USB_GHWCFG4_BVALIDFLTR_MASK 0x800000 +#define GC_USB_GHWCFG4_BVALIDFLTR_SIZE 0x1 +#define GC_USB_GHWCFG4_BVALIDFLTR_DEFAULT 0x0 +#define GC_USB_GHWCFG4_BVALIDFLTR_OFFSET 0x50 +#define GC_USB_GHWCFG4_SESSENDFLTR_LSB 0x18 +#define GC_USB_GHWCFG4_SESSENDFLTR_MASK 0x1000000 +#define GC_USB_GHWCFG4_SESSENDFLTR_SIZE 0x1 +#define GC_USB_GHWCFG4_SESSENDFLTR_DEFAULT 0x0 +#define GC_USB_GHWCFG4_SESSENDFLTR_OFFSET 0x50 +#define GC_USB_GHWCFG4_DEDFIFOMODE_LSB 0x19 +#define GC_USB_GHWCFG4_DEDFIFOMODE_MASK 0x2000000 +#define GC_USB_GHWCFG4_DEDFIFOMODE_SIZE 0x1 +#define GC_USB_GHWCFG4_DEDFIFOMODE_DEFAULT 0x0 +#define GC_USB_GHWCFG4_DEDFIFOMODE_OFFSET 0x50 +#define GC_USB_GHWCFG4_INEPS_LSB 0x1a +#define GC_USB_GHWCFG4_INEPS_MASK 0x3c000000 +#define GC_USB_GHWCFG4_INEPS_SIZE 0x4 +#define GC_USB_GHWCFG4_INEPS_DEFAULT 0x0 +#define GC_USB_GHWCFG4_INEPS_OFFSET 0x50 +#define GC_USB_GHWCFG4_DESCDMAENABLED_LSB 0x1e +#define GC_USB_GHWCFG4_DESCDMAENABLED_MASK 0x40000000 +#define GC_USB_GHWCFG4_DESCDMAENABLED_SIZE 0x1 +#define GC_USB_GHWCFG4_DESCDMAENABLED_DEFAULT 0x0 +#define GC_USB_GHWCFG4_DESCDMAENABLED_OFFSET 0x50 +#define GC_USB_GHWCFG4_DESCDMA_LSB 0x1f +#define GC_USB_GHWCFG4_DESCDMA_MASK 0x80000000 +#define GC_USB_GHWCFG4_DESCDMA_SIZE 0x1 +#define GC_USB_GHWCFG4_DESCDMA_DEFAULT 0x0 +#define GC_USB_GHWCFG4_DESCDMA_OFFSET 0x50 +#define GC_USB_GDFIFOCFG_GDFIFOCFG_LSB 0x0 +#define GC_USB_GDFIFOCFG_GDFIFOCFG_MASK 0xffff +#define GC_USB_GDFIFOCFG_GDFIFOCFG_SIZE 0x10 +#define GC_USB_GDFIFOCFG_GDFIFOCFG_DEFAULT 0x0 +#define GC_USB_GDFIFOCFG_GDFIFOCFG_OFFSET 0x5c +#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_LSB 0x10 +#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_MASK 0xffff0000 +#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_SIZE 0x10 +#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_DEFAULT 0x0 +#define GC_USB_GDFIFOCFG_EPINFOBASEADDR_OFFSET 0x5c +#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF1_INEPNTXFSTADDR_OFFSET 0x104 +#define GC_USB_DIEPTXF1_RESERVED11_LSB 0xc +#define GC_USB_DIEPTXF1_RESERVED11_MASK 0x1000 +#define GC_USB_DIEPTXF1_RESERVED11_SIZE 0x1 +#define GC_USB_DIEPTXF1_RESERVED11_DEFAULT 0x1 +#define GC_USB_DIEPTXF1_RESERVED11_OFFSET 0x104 +#define GC_USB_DIEPTXF1_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF1_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF1_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF1_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF1_INEPNTXFDEP_OFFSET 0x104 +#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF2_INEPNTXFSTADDR_OFFSET 0x108 +#define GC_USB_DIEPTXF2_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF2_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF2_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF2_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF2_INEPNTXFDEP_OFFSET 0x108 +#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF3_INEPNTXFSTADDR_OFFSET 0x10c +#define GC_USB_DIEPTXF3_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF3_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF3_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF3_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF3_INEPNTXFDEP_OFFSET 0x10c +#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF4_INEPNTXFSTADDR_OFFSET 0x110 +#define GC_USB_DIEPTXF4_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF4_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF4_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF4_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF4_INEPNTXFDEP_OFFSET 0x110 +#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF5_INEPNTXFSTADDR_OFFSET 0x114 +#define GC_USB_DIEPTXF5_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF5_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF5_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF5_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF5_INEPNTXFDEP_OFFSET 0x114 +#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF6_INEPNTXFSTADDR_OFFSET 0x118 +#define GC_USB_DIEPTXF6_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF6_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF6_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF6_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF6_INEPNTXFDEP_OFFSET 0x118 +#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF7_INEPNTXFSTADDR_OFFSET 0x11c +#define GC_USB_DIEPTXF7_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF7_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF7_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF7_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF7_INEPNTXFDEP_OFFSET 0x11c +#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF8_INEPNTXFSTADDR_OFFSET 0x120 +#define GC_USB_DIEPTXF8_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF8_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF8_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF8_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF8_INEPNTXFDEP_OFFSET 0x120 +#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF9_INEPNTXFSTADDR_OFFSET 0x124 +#define GC_USB_DIEPTXF9_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF9_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF9_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF9_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF9_INEPNTXFDEP_OFFSET 0x124 +#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF10_INEPNTXFSTADDR_OFFSET 0x128 +#define GC_USB_DIEPTXF10_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF10_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF10_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF10_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF10_INEPNTXFDEP_OFFSET 0x128 +#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF11_INEPNTXFSTADDR_OFFSET 0x12c +#define GC_USB_DIEPTXF11_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF11_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF11_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF11_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF11_INEPNTXFDEP_OFFSET 0x12c +#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF12_INEPNTXFSTADDR_OFFSET 0x130 +#define GC_USB_DIEPTXF12_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF12_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF12_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF12_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF12_INEPNTXFDEP_OFFSET 0x130 +#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF13_INEPNTXFSTADDR_OFFSET 0x134 +#define GC_USB_DIEPTXF13_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF13_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF13_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF13_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF13_INEPNTXFDEP_OFFSET 0x134 +#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF14_INEPNTXFSTADDR_OFFSET 0x138 +#define GC_USB_DIEPTXF14_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF14_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF14_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF14_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF14_INEPNTXFDEP_OFFSET 0x138 +#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_LSB 0x0 +#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_MASK 0x7ff +#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_SIZE 0xb +#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_DEFAULT 0x0 +#define GC_USB_DIEPTXF15_INEPNTXFSTADDR_OFFSET 0x13c +#define GC_USB_DIEPTXF15_INEPNTXFDEP_LSB 0x10 +#define GC_USB_DIEPTXF15_INEPNTXFDEP_MASK 0x3f0000 +#define GC_USB_DIEPTXF15_INEPNTXFDEP_SIZE 0x6 +#define GC_USB_DIEPTXF15_INEPNTXFDEP_DEFAULT 0x0 +#define GC_USB_DIEPTXF15_INEPNTXFDEP_OFFSET 0x13c +#define GC_USB_DCFG_DEVSPD_LSB 0x0 +#define GC_USB_DCFG_DEVSPD_MASK 0x3 +#define GC_USB_DCFG_DEVSPD_SIZE 0x2 +#define GC_USB_DCFG_DEVSPD_DEFAULT 0x0 +#define GC_USB_DCFG_DEVSPD_OFFSET 0x800 +#define GC_USB_DCFG_NZSTSOUTHSHK_LSB 0x2 +#define GC_USB_DCFG_NZSTSOUTHSHK_MASK 0x4 +#define GC_USB_DCFG_NZSTSOUTHSHK_SIZE 0x1 +#define GC_USB_DCFG_NZSTSOUTHSHK_DEFAULT 0x0 +#define GC_USB_DCFG_NZSTSOUTHSHK_OFFSET 0x800 +#define GC_USB_DCFG_ENA32KHZSUSP_LSB 0x3 +#define GC_USB_DCFG_ENA32KHZSUSP_MASK 0x8 +#define GC_USB_DCFG_ENA32KHZSUSP_SIZE 0x1 +#define GC_USB_DCFG_ENA32KHZSUSP_DEFAULT 0x0 +#define GC_USB_DCFG_ENA32KHZSUSP_OFFSET 0x800 +#define GC_USB_DCFG_DEVADDR_LSB 0x4 +#define GC_USB_DCFG_DEVADDR_MASK 0x7f0 +#define GC_USB_DCFG_DEVADDR_SIZE 0x7 +#define GC_USB_DCFG_DEVADDR_DEFAULT 0x0 +#define GC_USB_DCFG_DEVADDR_OFFSET 0x800 +#define GC_USB_DCFG_PERFRINT_LSB 0xb +#define GC_USB_DCFG_PERFRINT_MASK 0x1800 +#define GC_USB_DCFG_PERFRINT_SIZE 0x2 +#define GC_USB_DCFG_PERFRINT_DEFAULT 0x0 +#define GC_USB_DCFG_PERFRINT_OFFSET 0x800 +#define GC_USB_DCFG_ENDEVOUTNAK_LSB 0xd +#define GC_USB_DCFG_ENDEVOUTNAK_MASK 0x2000 +#define GC_USB_DCFG_ENDEVOUTNAK_SIZE 0x1 +#define GC_USB_DCFG_ENDEVOUTNAK_DEFAULT 0x0 +#define GC_USB_DCFG_ENDEVOUTNAK_OFFSET 0x800 +#define GC_USB_DCFG_XCVRDLY_LSB 0xe +#define GC_USB_DCFG_XCVRDLY_MASK 0x4000 +#define GC_USB_DCFG_XCVRDLY_SIZE 0x1 +#define GC_USB_DCFG_XCVRDLY_DEFAULT 0x0 +#define GC_USB_DCFG_XCVRDLY_OFFSET 0x800 +#define GC_USB_DCFG_ERRATICINTMSK_LSB 0xf +#define GC_USB_DCFG_ERRATICINTMSK_MASK 0x8000 +#define GC_USB_DCFG_ERRATICINTMSK_SIZE 0x1 +#define GC_USB_DCFG_ERRATICINTMSK_DEFAULT 0x0 +#define GC_USB_DCFG_ERRATICINTMSK_OFFSET 0x800 +#define GC_USB_DCFG_DESCDMA_LSB 0x17 +#define GC_USB_DCFG_DESCDMA_MASK 0x800000 +#define GC_USB_DCFG_DESCDMA_SIZE 0x1 +#define GC_USB_DCFG_DESCDMA_DEFAULT 0x0 +#define GC_USB_DCFG_DESCDMA_OFFSET 0x800 +#define GC_USB_DCFG_PERSCHINTVL_LSB 0x18 +#define GC_USB_DCFG_PERSCHINTVL_MASK 0x3000000 +#define GC_USB_DCFG_PERSCHINTVL_SIZE 0x2 +#define GC_USB_DCFG_PERSCHINTVL_DEFAULT 0x0 +#define GC_USB_DCFG_PERSCHINTVL_OFFSET 0x800 +#define GC_USB_DCFG_RESVALID_LSB 0x1a +#define GC_USB_DCFG_RESVALID_MASK 0xfc000000 +#define GC_USB_DCFG_RESVALID_SIZE 0x6 +#define GC_USB_DCFG_RESVALID_DEFAULT 0x2 +#define GC_USB_DCFG_RESVALID_OFFSET 0x800 +#define GC_USB_DCTL_RMTWKUPSIG_LSB 0x0 +#define GC_USB_DCTL_RMTWKUPSIG_MASK 0x1 +#define GC_USB_DCTL_RMTWKUPSIG_SIZE 0x1 +#define GC_USB_DCTL_RMTWKUPSIG_DEFAULT 0x0 +#define GC_USB_DCTL_RMTWKUPSIG_OFFSET 0x804 +#define GC_USB_DCTL_SFTDISCON_LSB 0x1 +#define GC_USB_DCTL_SFTDISCON_MASK 0x2 +#define GC_USB_DCTL_SFTDISCON_SIZE 0x1 +#define GC_USB_DCTL_SFTDISCON_DEFAULT 0x0 +#define GC_USB_DCTL_SFTDISCON_OFFSET 0x804 +#define GC_USB_DCTL_GNPINNAKSTS_LSB 0x2 +#define GC_USB_DCTL_GNPINNAKSTS_MASK 0x4 +#define GC_USB_DCTL_GNPINNAKSTS_SIZE 0x1 +#define GC_USB_DCTL_GNPINNAKSTS_DEFAULT 0x0 +#define GC_USB_DCTL_GNPINNAKSTS_OFFSET 0x804 +#define GC_USB_DCTL_GOUTNAKSTS_LSB 0x3 +#define GC_USB_DCTL_GOUTNAKSTS_MASK 0x8 +#define GC_USB_DCTL_GOUTNAKSTS_SIZE 0x1 +#define GC_USB_DCTL_GOUTNAKSTS_DEFAULT 0x0 +#define GC_USB_DCTL_GOUTNAKSTS_OFFSET 0x804 +#define GC_USB_DCTL_TSTCTL_LSB 0x4 +#define GC_USB_DCTL_TSTCTL_MASK 0x70 +#define GC_USB_DCTL_TSTCTL_SIZE 0x3 +#define GC_USB_DCTL_TSTCTL_DEFAULT 0x0 +#define GC_USB_DCTL_TSTCTL_OFFSET 0x804 +#define GC_USB_DCTL_SGNPINNAK_LSB 0x7 +#define GC_USB_DCTL_SGNPINNAK_MASK 0x80 +#define GC_USB_DCTL_SGNPINNAK_SIZE 0x1 +#define GC_USB_DCTL_SGNPINNAK_DEFAULT 0x0 +#define GC_USB_DCTL_SGNPINNAK_OFFSET 0x804 +#define GC_USB_DCTL_CGNPINNAK_LSB 0x8 +#define GC_USB_DCTL_CGNPINNAK_MASK 0x100 +#define GC_USB_DCTL_CGNPINNAK_SIZE 0x1 +#define GC_USB_DCTL_CGNPINNAK_DEFAULT 0x0 +#define GC_USB_DCTL_CGNPINNAK_OFFSET 0x804 +#define GC_USB_DCTL_SGOUTNAK_LSB 0x9 +#define GC_USB_DCTL_SGOUTNAK_MASK 0x200 +#define GC_USB_DCTL_SGOUTNAK_SIZE 0x1 +#define GC_USB_DCTL_SGOUTNAK_DEFAULT 0x0 +#define GC_USB_DCTL_SGOUTNAK_OFFSET 0x804 +#define GC_USB_DCTL_CGOUTNAK_LSB 0xa +#define GC_USB_DCTL_CGOUTNAK_MASK 0x400 +#define GC_USB_DCTL_CGOUTNAK_SIZE 0x1 +#define GC_USB_DCTL_CGOUTNAK_DEFAULT 0x0 +#define GC_USB_DCTL_CGOUTNAK_OFFSET 0x804 +#define GC_USB_DCTL_PWRONPRGDONE_LSB 0xb +#define GC_USB_DCTL_PWRONPRGDONE_MASK 0x800 +#define GC_USB_DCTL_PWRONPRGDONE_SIZE 0x1 +#define GC_USB_DCTL_PWRONPRGDONE_DEFAULT 0x0 +#define GC_USB_DCTL_PWRONPRGDONE_OFFSET 0x804 +#define GC_USB_DCTL_GMC_LSB 0xd +#define GC_USB_DCTL_GMC_MASK 0x6000 +#define GC_USB_DCTL_GMC_SIZE 0x2 +#define GC_USB_DCTL_GMC_DEFAULT 0x0 +#define GC_USB_DCTL_GMC_OFFSET 0x804 +#define GC_USB_DCTL_IGNRFRMNUM_LSB 0xf +#define GC_USB_DCTL_IGNRFRMNUM_MASK 0x8000 +#define GC_USB_DCTL_IGNRFRMNUM_SIZE 0x1 +#define GC_USB_DCTL_IGNRFRMNUM_DEFAULT 0x0 +#define GC_USB_DCTL_IGNRFRMNUM_OFFSET 0x804 +#define GC_USB_DCTL_NAKONBBLE_LSB 0x10 +#define GC_USB_DCTL_NAKONBBLE_MASK 0x10000 +#define GC_USB_DCTL_NAKONBBLE_SIZE 0x1 +#define GC_USB_DCTL_NAKONBBLE_DEFAULT 0x0 +#define GC_USB_DCTL_NAKONBBLE_OFFSET 0x804 +#define GC_USB_DCTL_ENCONTONBNA_LSB 0x11 +#define GC_USB_DCTL_ENCONTONBNA_MASK 0x20000 +#define GC_USB_DCTL_ENCONTONBNA_SIZE 0x1 +#define GC_USB_DCTL_ENCONTONBNA_DEFAULT 0x0 +#define GC_USB_DCTL_ENCONTONBNA_OFFSET 0x804 +#define GC_USB_DSTS_SUSPSTS_LSB 0x0 +#define GC_USB_DSTS_SUSPSTS_MASK 0x1 +#define GC_USB_DSTS_SUSPSTS_SIZE 0x1 +#define GC_USB_DSTS_SUSPSTS_DEFAULT 0x0 +#define GC_USB_DSTS_SUSPSTS_OFFSET 0x808 +#define GC_USB_DSTS_ENUMSPD_LSB 0x1 +#define GC_USB_DSTS_ENUMSPD_MASK 0x6 +#define GC_USB_DSTS_ENUMSPD_SIZE 0x2 +#define GC_USB_DSTS_ENUMSPD_DEFAULT 0x0 +#define GC_USB_DSTS_ENUMSPD_OFFSET 0x808 +#define GC_USB_DSTS_ERRTICERR_LSB 0x3 +#define GC_USB_DSTS_ERRTICERR_MASK 0x8 +#define GC_USB_DSTS_ERRTICERR_SIZE 0x1 +#define GC_USB_DSTS_ERRTICERR_DEFAULT 0x0 +#define GC_USB_DSTS_ERRTICERR_OFFSET 0x808 +#define GC_USB_DSTS_SOFFN_LSB 0x8 +#define GC_USB_DSTS_SOFFN_MASK 0x3fff00 +#define GC_USB_DSTS_SOFFN_SIZE 0xe +#define GC_USB_DSTS_SOFFN_DEFAULT 0x0 +#define GC_USB_DSTS_SOFFN_OFFSET 0x808 +#define GC_USB_DSTS_DEVLNSTS_LSB 0x16 +#define GC_USB_DSTS_DEVLNSTS_MASK 0xc00000 +#define GC_USB_DSTS_DEVLNSTS_SIZE 0x2 +#define GC_USB_DSTS_DEVLNSTS_DEFAULT 0x0 +#define GC_USB_DSTS_DEVLNSTS_OFFSET 0x808 +#define GC_USB_DIEPMSK_XFERCOMPLMSK_LSB 0x0 +#define GC_USB_DIEPMSK_XFERCOMPLMSK_MASK 0x1 +#define GC_USB_DIEPMSK_XFERCOMPLMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_XFERCOMPLMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_XFERCOMPLMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_EPDISBLDMSK_LSB 0x1 +#define GC_USB_DIEPMSK_EPDISBLDMSK_MASK 0x2 +#define GC_USB_DIEPMSK_EPDISBLDMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_EPDISBLDMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_EPDISBLDMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_AHBERRMSK_LSB 0x2 +#define GC_USB_DIEPMSK_AHBERRMSK_MASK 0x4 +#define GC_USB_DIEPMSK_AHBERRMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_AHBERRMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_AHBERRMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_TIMEOUTMSK_LSB 0x3 +#define GC_USB_DIEPMSK_TIMEOUTMSK_MASK 0x8 +#define GC_USB_DIEPMSK_TIMEOUTMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_TIMEOUTMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_TIMEOUTMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_LSB 0x4 +#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_MASK 0x10 +#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_INTKNTXFEMPMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_INTKNEPMISMSK_LSB 0x5 +#define GC_USB_DIEPMSK_INTKNEPMISMSK_MASK 0x20 +#define GC_USB_DIEPMSK_INTKNEPMISMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_INTKNEPMISMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_INTKNEPMISMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_INEPNAKEFFMSK_LSB 0x6 +#define GC_USB_DIEPMSK_INEPNAKEFFMSK_MASK 0x40 +#define GC_USB_DIEPMSK_INEPNAKEFFMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_INEPNAKEFFMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_INEPNAKEFFMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_RESERVED7_LSB 0x7 +#define GC_USB_DIEPMSK_RESERVED7_MASK 0x80 +#define GC_USB_DIEPMSK_RESERVED7_SIZE 0x1 +#define GC_USB_DIEPMSK_RESERVED7_DEFAULT 0x1 +#define GC_USB_DIEPMSK_RESERVED7_OFFSET 0x810 +#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_LSB 0x8 +#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_MASK 0x100 +#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_TXFIFOUNDRNMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_BNAININTRMSK_LSB 0x9 +#define GC_USB_DIEPMSK_BNAININTRMSK_MASK 0x200 +#define GC_USB_DIEPMSK_BNAININTRMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_BNAININTRMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_BNAININTRMSK_OFFSET 0x810 +#define GC_USB_DIEPMSK_NAKMSK_LSB 0xd +#define GC_USB_DIEPMSK_NAKMSK_MASK 0x2000 +#define GC_USB_DIEPMSK_NAKMSK_SIZE 0x1 +#define GC_USB_DIEPMSK_NAKMSK_DEFAULT 0x0 +#define GC_USB_DIEPMSK_NAKMSK_OFFSET 0x810 +#define GC_USB_DOEPMSK_XFERCOMPLMSK_LSB 0x0 +#define GC_USB_DOEPMSK_XFERCOMPLMSK_MASK 0x1 +#define GC_USB_DOEPMSK_XFERCOMPLMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_XFERCOMPLMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_XFERCOMPLMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_EPDISBLDMSK_LSB 0x1 +#define GC_USB_DOEPMSK_EPDISBLDMSK_MASK 0x2 +#define GC_USB_DOEPMSK_EPDISBLDMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_EPDISBLDMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_EPDISBLDMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_AHBERRMSK_LSB 0x2 +#define GC_USB_DOEPMSK_AHBERRMSK_MASK 0x4 +#define GC_USB_DOEPMSK_AHBERRMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_AHBERRMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_AHBERRMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_SETUPMSK_LSB 0x3 +#define GC_USB_DOEPMSK_SETUPMSK_MASK 0x8 +#define GC_USB_DOEPMSK_SETUPMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_SETUPMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_SETUPMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_LSB 0x4 +#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_MASK 0x10 +#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_OUTTKNEPDISMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_STSPHSERCVDMSK_LSB 0x5 +#define GC_USB_DOEPMSK_STSPHSERCVDMSK_MASK 0x20 +#define GC_USB_DOEPMSK_STSPHSERCVDMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_STSPHSERCVDMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_STSPHSERCVDMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPMSK_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPMSK_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPMSK_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPMSK_BACK2BACKSETUP_OFFSET 0x814 +#define GC_USB_DOEPMSK_OUTPKTERRMSK_LSB 0x8 +#define GC_USB_DOEPMSK_OUTPKTERRMSK_MASK 0x100 +#define GC_USB_DOEPMSK_OUTPKTERRMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_OUTPKTERRMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_OUTPKTERRMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_BNAOUTINTRMSK_LSB 0x9 +#define GC_USB_DOEPMSK_BNAOUTINTRMSK_MASK 0x200 +#define GC_USB_DOEPMSK_BNAOUTINTRMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_BNAOUTINTRMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_BNAOUTINTRMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_BBLEERRMSK_LSB 0xc +#define GC_USB_DOEPMSK_BBLEERRMSK_MASK 0x1000 +#define GC_USB_DOEPMSK_BBLEERRMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_BBLEERRMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_BBLEERRMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_NAKMSK_LSB 0xd +#define GC_USB_DOEPMSK_NAKMSK_MASK 0x2000 +#define GC_USB_DOEPMSK_NAKMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_NAKMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_NAKMSK_OFFSET 0x814 +#define GC_USB_DOEPMSK_NYETMSK_LSB 0xe +#define GC_USB_DOEPMSK_NYETMSK_MASK 0x4000 +#define GC_USB_DOEPMSK_NYETMSK_SIZE 0x1 +#define GC_USB_DOEPMSK_NYETMSK_DEFAULT 0x0 +#define GC_USB_DOEPMSK_NYETMSK_OFFSET 0x814 +#define GC_USB_DAINT_INEPINT0_LSB 0x0 +#define GC_USB_DAINT_INEPINT0_MASK 0x1 +#define GC_USB_DAINT_INEPINT0_SIZE 0x1 +#define GC_USB_DAINT_INEPINT0_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT0_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT1_LSB 0x1 +#define GC_USB_DAINT_INEPINT1_MASK 0x2 +#define GC_USB_DAINT_INEPINT1_SIZE 0x1 +#define GC_USB_DAINT_INEPINT1_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT1_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT2_LSB 0x2 +#define GC_USB_DAINT_INEPINT2_MASK 0x4 +#define GC_USB_DAINT_INEPINT2_SIZE 0x1 +#define GC_USB_DAINT_INEPINT2_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT2_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT3_LSB 0x3 +#define GC_USB_DAINT_INEPINT3_MASK 0x8 +#define GC_USB_DAINT_INEPINT3_SIZE 0x1 +#define GC_USB_DAINT_INEPINT3_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT3_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT4_LSB 0x4 +#define GC_USB_DAINT_INEPINT4_MASK 0x10 +#define GC_USB_DAINT_INEPINT4_SIZE 0x1 +#define GC_USB_DAINT_INEPINT4_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT4_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT5_LSB 0x5 +#define GC_USB_DAINT_INEPINT5_MASK 0x20 +#define GC_USB_DAINT_INEPINT5_SIZE 0x1 +#define GC_USB_DAINT_INEPINT5_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT5_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT6_LSB 0x6 +#define GC_USB_DAINT_INEPINT6_MASK 0x40 +#define GC_USB_DAINT_INEPINT6_SIZE 0x1 +#define GC_USB_DAINT_INEPINT6_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT6_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT7_LSB 0x7 +#define GC_USB_DAINT_INEPINT7_MASK 0x80 +#define GC_USB_DAINT_INEPINT7_SIZE 0x1 +#define GC_USB_DAINT_INEPINT7_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT7_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT8_LSB 0x8 +#define GC_USB_DAINT_INEPINT8_MASK 0x100 +#define GC_USB_DAINT_INEPINT8_SIZE 0x1 +#define GC_USB_DAINT_INEPINT8_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT8_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT9_LSB 0x9 +#define GC_USB_DAINT_INEPINT9_MASK 0x200 +#define GC_USB_DAINT_INEPINT9_SIZE 0x1 +#define GC_USB_DAINT_INEPINT9_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT9_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT10_LSB 0xa +#define GC_USB_DAINT_INEPINT10_MASK 0x400 +#define GC_USB_DAINT_INEPINT10_SIZE 0x1 +#define GC_USB_DAINT_INEPINT10_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT10_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT11_LSB 0xb +#define GC_USB_DAINT_INEPINT11_MASK 0x800 +#define GC_USB_DAINT_INEPINT11_SIZE 0x1 +#define GC_USB_DAINT_INEPINT11_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT11_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT12_LSB 0xc +#define GC_USB_DAINT_INEPINT12_MASK 0x1000 +#define GC_USB_DAINT_INEPINT12_SIZE 0x1 +#define GC_USB_DAINT_INEPINT12_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT12_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT13_LSB 0xd +#define GC_USB_DAINT_INEPINT13_MASK 0x2000 +#define GC_USB_DAINT_INEPINT13_SIZE 0x1 +#define GC_USB_DAINT_INEPINT13_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT13_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT14_LSB 0xe +#define GC_USB_DAINT_INEPINT14_MASK 0x4000 +#define GC_USB_DAINT_INEPINT14_SIZE 0x1 +#define GC_USB_DAINT_INEPINT14_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT14_OFFSET 0x818 +#define GC_USB_DAINT_INEPINT15_LSB 0xf +#define GC_USB_DAINT_INEPINT15_MASK 0x8000 +#define GC_USB_DAINT_INEPINT15_SIZE 0x1 +#define GC_USB_DAINT_INEPINT15_DEFAULT 0x0 +#define GC_USB_DAINT_INEPINT15_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT0_LSB 0x10 +#define GC_USB_DAINT_OUTEPINT0_MASK 0x10000 +#define GC_USB_DAINT_OUTEPINT0_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT0_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT0_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT1_LSB 0x11 +#define GC_USB_DAINT_OUTEPINT1_MASK 0x20000 +#define GC_USB_DAINT_OUTEPINT1_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT1_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT1_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT2_LSB 0x12 +#define GC_USB_DAINT_OUTEPINT2_MASK 0x40000 +#define GC_USB_DAINT_OUTEPINT2_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT2_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT2_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT3_LSB 0x13 +#define GC_USB_DAINT_OUTEPINT3_MASK 0x80000 +#define GC_USB_DAINT_OUTEPINT3_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT3_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT3_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT4_LSB 0x14 +#define GC_USB_DAINT_OUTEPINT4_MASK 0x100000 +#define GC_USB_DAINT_OUTEPINT4_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT4_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT4_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT5_LSB 0x15 +#define GC_USB_DAINT_OUTEPINT5_MASK 0x200000 +#define GC_USB_DAINT_OUTEPINT5_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT5_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT5_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT6_LSB 0x16 +#define GC_USB_DAINT_OUTEPINT6_MASK 0x400000 +#define GC_USB_DAINT_OUTEPINT6_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT6_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT6_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT7_LSB 0x17 +#define GC_USB_DAINT_OUTEPINT7_MASK 0x800000 +#define GC_USB_DAINT_OUTEPINT7_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT7_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT7_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT8_LSB 0x18 +#define GC_USB_DAINT_OUTEPINT8_MASK 0x1000000 +#define GC_USB_DAINT_OUTEPINT8_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT8_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT8_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT9_LSB 0x19 +#define GC_USB_DAINT_OUTEPINT9_MASK 0x2000000 +#define GC_USB_DAINT_OUTEPINT9_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT9_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT9_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT10_LSB 0x1a +#define GC_USB_DAINT_OUTEPINT10_MASK 0x4000000 +#define GC_USB_DAINT_OUTEPINT10_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT10_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT10_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT11_LSB 0x1b +#define GC_USB_DAINT_OUTEPINT11_MASK 0x8000000 +#define GC_USB_DAINT_OUTEPINT11_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT11_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT11_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT12_LSB 0x1c +#define GC_USB_DAINT_OUTEPINT12_MASK 0x10000000 +#define GC_USB_DAINT_OUTEPINT12_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT12_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT12_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT13_LSB 0x1d +#define GC_USB_DAINT_OUTEPINT13_MASK 0x20000000 +#define GC_USB_DAINT_OUTEPINT13_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT13_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT13_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT14_LSB 0x1e +#define GC_USB_DAINT_OUTEPINT14_MASK 0x40000000 +#define GC_USB_DAINT_OUTEPINT14_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT14_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT14_OFFSET 0x818 +#define GC_USB_DAINT_OUTEPINT15_LSB 0x1f +#define GC_USB_DAINT_OUTEPINT15_MASK 0x80000000 +#define GC_USB_DAINT_OUTEPINT15_SIZE 0x1 +#define GC_USB_DAINT_OUTEPINT15_DEFAULT 0x0 +#define GC_USB_DAINT_OUTEPINT15_OFFSET 0x818 +#define GC_USB_DAINTMSK_INEPMSK0_LSB 0x0 +#define GC_USB_DAINTMSK_INEPMSK0_MASK 0x1 +#define GC_USB_DAINTMSK_INEPMSK0_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK0_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK0_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK1_LSB 0x1 +#define GC_USB_DAINTMSK_INEPMSK1_MASK 0x2 +#define GC_USB_DAINTMSK_INEPMSK1_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK1_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK1_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK2_LSB 0x2 +#define GC_USB_DAINTMSK_INEPMSK2_MASK 0x4 +#define GC_USB_DAINTMSK_INEPMSK2_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK2_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK2_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK3_LSB 0x3 +#define GC_USB_DAINTMSK_INEPMSK3_MASK 0x8 +#define GC_USB_DAINTMSK_INEPMSK3_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK3_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK3_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK4_LSB 0x4 +#define GC_USB_DAINTMSK_INEPMSK4_MASK 0x10 +#define GC_USB_DAINTMSK_INEPMSK4_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK4_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK4_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK5_LSB 0x5 +#define GC_USB_DAINTMSK_INEPMSK5_MASK 0x20 +#define GC_USB_DAINTMSK_INEPMSK5_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK5_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK5_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK6_LSB 0x6 +#define GC_USB_DAINTMSK_INEPMSK6_MASK 0x40 +#define GC_USB_DAINTMSK_INEPMSK6_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK6_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK6_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK7_LSB 0x7 +#define GC_USB_DAINTMSK_INEPMSK7_MASK 0x80 +#define GC_USB_DAINTMSK_INEPMSK7_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK7_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK7_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK8_LSB 0x8 +#define GC_USB_DAINTMSK_INEPMSK8_MASK 0x100 +#define GC_USB_DAINTMSK_INEPMSK8_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK8_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK8_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK9_LSB 0x9 +#define GC_USB_DAINTMSK_INEPMSK9_MASK 0x200 +#define GC_USB_DAINTMSK_INEPMSK9_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK9_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK9_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK10_LSB 0xa +#define GC_USB_DAINTMSK_INEPMSK10_MASK 0x400 +#define GC_USB_DAINTMSK_INEPMSK10_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK10_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK10_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK11_LSB 0xb +#define GC_USB_DAINTMSK_INEPMSK11_MASK 0x800 +#define GC_USB_DAINTMSK_INEPMSK11_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK11_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK11_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK12_LSB 0xc +#define GC_USB_DAINTMSK_INEPMSK12_MASK 0x1000 +#define GC_USB_DAINTMSK_INEPMSK12_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK12_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK12_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK13_LSB 0xd +#define GC_USB_DAINTMSK_INEPMSK13_MASK 0x2000 +#define GC_USB_DAINTMSK_INEPMSK13_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK13_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK13_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK14_LSB 0xe +#define GC_USB_DAINTMSK_INEPMSK14_MASK 0x4000 +#define GC_USB_DAINTMSK_INEPMSK14_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK14_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK14_OFFSET 0x81c +#define GC_USB_DAINTMSK_INEPMSK15_LSB 0xf +#define GC_USB_DAINTMSK_INEPMSK15_MASK 0x8000 +#define GC_USB_DAINTMSK_INEPMSK15_SIZE 0x1 +#define GC_USB_DAINTMSK_INEPMSK15_DEFAULT 0x0 +#define GC_USB_DAINTMSK_INEPMSK15_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK0_LSB 0x10 +#define GC_USB_DAINTMSK_OUTEPMSK0_MASK 0x10000 +#define GC_USB_DAINTMSK_OUTEPMSK0_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK0_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK0_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK1_LSB 0x11 +#define GC_USB_DAINTMSK_OUTEPMSK1_MASK 0x20000 +#define GC_USB_DAINTMSK_OUTEPMSK1_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK1_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK1_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK2_LSB 0x12 +#define GC_USB_DAINTMSK_OUTEPMSK2_MASK 0x40000 +#define GC_USB_DAINTMSK_OUTEPMSK2_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK2_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK2_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK3_LSB 0x13 +#define GC_USB_DAINTMSK_OUTEPMSK3_MASK 0x80000 +#define GC_USB_DAINTMSK_OUTEPMSK3_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK3_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK3_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK4_LSB 0x14 +#define GC_USB_DAINTMSK_OUTEPMSK4_MASK 0x100000 +#define GC_USB_DAINTMSK_OUTEPMSK4_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK4_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK4_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK5_LSB 0x15 +#define GC_USB_DAINTMSK_OUTEPMSK5_MASK 0x200000 +#define GC_USB_DAINTMSK_OUTEPMSK5_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK5_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK5_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK6_LSB 0x16 +#define GC_USB_DAINTMSK_OUTEPMSK6_MASK 0x400000 +#define GC_USB_DAINTMSK_OUTEPMSK6_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK6_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK6_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK7_LSB 0x17 +#define GC_USB_DAINTMSK_OUTEPMSK7_MASK 0x800000 +#define GC_USB_DAINTMSK_OUTEPMSK7_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK7_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK7_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK8_LSB 0x18 +#define GC_USB_DAINTMSK_OUTEPMSK8_MASK 0x1000000 +#define GC_USB_DAINTMSK_OUTEPMSK8_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK8_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK8_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK9_LSB 0x19 +#define GC_USB_DAINTMSK_OUTEPMSK9_MASK 0x2000000 +#define GC_USB_DAINTMSK_OUTEPMSK9_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK9_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK9_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK10_LSB 0x1a +#define GC_USB_DAINTMSK_OUTEPMSK10_MASK 0x4000000 +#define GC_USB_DAINTMSK_OUTEPMSK10_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK10_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK10_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK11_LSB 0x1b +#define GC_USB_DAINTMSK_OUTEPMSK11_MASK 0x8000000 +#define GC_USB_DAINTMSK_OUTEPMSK11_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK11_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK11_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK12_LSB 0x1c +#define GC_USB_DAINTMSK_OUTEPMSK12_MASK 0x10000000 +#define GC_USB_DAINTMSK_OUTEPMSK12_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK12_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK12_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK13_LSB 0x1d +#define GC_USB_DAINTMSK_OUTEPMSK13_MASK 0x20000000 +#define GC_USB_DAINTMSK_OUTEPMSK13_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK13_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK13_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK14_LSB 0x1e +#define GC_USB_DAINTMSK_OUTEPMSK14_MASK 0x40000000 +#define GC_USB_DAINTMSK_OUTEPMSK14_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK14_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK14_OFFSET 0x81c +#define GC_USB_DAINTMSK_OUTEPMSK15_LSB 0x1f +#define GC_USB_DAINTMSK_OUTEPMSK15_MASK 0x80000000 +#define GC_USB_DAINTMSK_OUTEPMSK15_SIZE 0x1 +#define GC_USB_DAINTMSK_OUTEPMSK15_DEFAULT 0x0 +#define GC_USB_DAINTMSK_OUTEPMSK15_OFFSET 0x81c +#define GC_USB_DVBUSDIS_DVBUSDIS_LSB 0x0 +#define GC_USB_DVBUSDIS_DVBUSDIS_MASK 0xffff +#define GC_USB_DVBUSDIS_DVBUSDIS_SIZE 0x10 +#define GC_USB_DVBUSDIS_DVBUSDIS_DEFAULT 0x0 +#define GC_USB_DVBUSDIS_DVBUSDIS_OFFSET 0x828 +#define GC_USB_DVBUSPULSE_DVBUSPULSE_LSB 0x0 +#define GC_USB_DVBUSPULSE_DVBUSPULSE_MASK 0xfff +#define GC_USB_DVBUSPULSE_DVBUSPULSE_SIZE 0xc +#define GC_USB_DVBUSPULSE_DVBUSPULSE_DEFAULT 0x0 +#define GC_USB_DVBUSPULSE_DVBUSPULSE_OFFSET 0x82c +#define GC_USB_DTHRCTL_NONISOTHREN_LSB 0x0 +#define GC_USB_DTHRCTL_NONISOTHREN_MASK 0x1 +#define GC_USB_DTHRCTL_NONISOTHREN_SIZE 0x1 +#define GC_USB_DTHRCTL_NONISOTHREN_DEFAULT 0x0 +#define GC_USB_DTHRCTL_NONISOTHREN_OFFSET 0x830 +#define GC_USB_DTHRCTL_ISOTHREN_LSB 0x1 +#define GC_USB_DTHRCTL_ISOTHREN_MASK 0x2 +#define GC_USB_DTHRCTL_ISOTHREN_SIZE 0x1 +#define GC_USB_DTHRCTL_ISOTHREN_DEFAULT 0x0 +#define GC_USB_DTHRCTL_ISOTHREN_OFFSET 0x830 +#define GC_USB_DTHRCTL_TXTHRLEN_LSB 0x2 +#define GC_USB_DTHRCTL_TXTHRLEN_MASK 0x7fc +#define GC_USB_DTHRCTL_TXTHRLEN_SIZE 0x9 +#define GC_USB_DTHRCTL_TXTHRLEN_DEFAULT 0x0 +#define GC_USB_DTHRCTL_TXTHRLEN_OFFSET 0x830 +#define GC_USB_DTHRCTL_AHBTHRRATIO_LSB 0xb +#define GC_USB_DTHRCTL_AHBTHRRATIO_MASK 0x1800 +#define GC_USB_DTHRCTL_AHBTHRRATIO_SIZE 0x2 +#define GC_USB_DTHRCTL_AHBTHRRATIO_DEFAULT 0x0 +#define GC_USB_DTHRCTL_AHBTHRRATIO_OFFSET 0x830 +#define GC_USB_DTHRCTL_RXTHREN_LSB 0x10 +#define GC_USB_DTHRCTL_RXTHREN_MASK 0x10000 +#define GC_USB_DTHRCTL_RXTHREN_SIZE 0x1 +#define GC_USB_DTHRCTL_RXTHREN_DEFAULT 0x0 +#define GC_USB_DTHRCTL_RXTHREN_OFFSET 0x830 +#define GC_USB_DTHRCTL_RXTHRLEN_LSB 0x11 +#define GC_USB_DTHRCTL_RXTHRLEN_MASK 0x3fe0000 +#define GC_USB_DTHRCTL_RXTHRLEN_SIZE 0x9 +#define GC_USB_DTHRCTL_RXTHRLEN_DEFAULT 0x0 +#define GC_USB_DTHRCTL_RXTHRLEN_OFFSET 0x830 +#define GC_USB_DTHRCTL_ARBPRKEN_LSB 0x1b +#define GC_USB_DTHRCTL_ARBPRKEN_MASK 0x8000000 +#define GC_USB_DTHRCTL_ARBPRKEN_SIZE 0x1 +#define GC_USB_DTHRCTL_ARBPRKEN_DEFAULT 0x0 +#define GC_USB_DTHRCTL_ARBPRKEN_OFFSET 0x830 +#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_LSB 0x0 +#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_MASK 0xffff +#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_SIZE 0x10 +#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_DEFAULT 0x0 +#define GC_USB_DIEPEMPMSK_INEPTXFEMPMSK_OFFSET 0x834 +#define GC_USB_DIEPCTL0_MPS_LSB 0x0 +#define GC_USB_DIEPCTL0_MPS_MASK 0x3 +#define GC_USB_DIEPCTL0_MPS_SIZE 0x2 +#define GC_USB_DIEPCTL0_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_MPS_OFFSET 0x900 +#define GC_USB_DIEPCTL0_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL0_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL0_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL0_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_USBACTEP_OFFSET 0x900 +#define GC_USB_DIEPCTL0_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL0_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL0_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL0_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_NAKSTS_OFFSET 0x900 +#define GC_USB_DIEPCTL0_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL0_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL0_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL0_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_EPTYPE_OFFSET 0x900 +#define GC_USB_DIEPCTL0_STALL_LSB 0x15 +#define GC_USB_DIEPCTL0_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL0_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL0_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_STALL_OFFSET 0x900 +#define GC_USB_DIEPCTL0_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL0_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL0_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL0_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_TXFNUM_OFFSET 0x900 +#define GC_USB_DIEPCTL0_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL0_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL0_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL0_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_CNAK_OFFSET 0x900 +#define GC_USB_DIEPCTL0_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL0_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL0_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL0_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_SNAK_OFFSET 0x900 +#define GC_USB_DIEPCTL0_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL0_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL0_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL0_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_EPDIS_OFFSET 0x900 +#define GC_USB_DIEPCTL0_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL0_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL0_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL0_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL0_EPENA_OFFSET 0x900 +#define GC_USB_DIEPINT0_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT0_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT0_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT0_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT0_XFERCOMPL_OFFSET 0x908 +#define GC_USB_DIEPINT0_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT0_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT0_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT0_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT0_EPDISBLD_OFFSET 0x908 +#define GC_USB_DIEPINT0_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT0_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT0_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT0_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT0_AHBERR_OFFSET 0x908 +#define GC_USB_DIEPINT0_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT0_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT0_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT0_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT0_TIMEOUT_OFFSET 0x908 +#define GC_USB_DIEPINT0_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT0_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT0_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT0_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT0_INTKNTXFEMP_OFFSET 0x908 +#define GC_USB_DIEPINT0_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT0_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT0_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT0_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT0_INTKNEPMIS_OFFSET 0x908 +#define GC_USB_DIEPINT0_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT0_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT0_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT0_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT0_INEPNAKEFF_OFFSET 0x908 +#define GC_USB_DIEPINT0_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT0_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT0_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT0_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT0_TXFEMP_OFFSET 0x908 +#define GC_USB_DIEPINT0_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT0_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT0_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT0_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT0_TXFIFOUNDRN_OFFSET 0x908 +#define GC_USB_DIEPINT0_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT0_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT0_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT0_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT0_BNAINTR_OFFSET 0x908 +#define GC_USB_DIEPINT0_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT0_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT0_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT0_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT0_PKTDRPSTS_OFFSET 0x908 +#define GC_USB_DIEPINT0_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT0_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT0_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT0_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT0_BBLEERR_OFFSET 0x908 +#define GC_USB_DIEPINT0_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT0_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT0_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT0_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT0_NAKINTRPT_OFFSET 0x908 +#define GC_USB_DIEPINT0_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT0_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT0_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT0_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT0_NYETINTRPT_OFFSET 0x908 +#define GC_USB_DIEPTSIZ0_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ0_XFERSIZE_MASK 0x7f +#define GC_USB_DIEPTSIZ0_XFERSIZE_SIZE 0x7 +#define GC_USB_DIEPTSIZ0_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ0_XFERSIZE_OFFSET 0x910 +#define GC_USB_DIEPTSIZ0_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ0_PKTCNT_MASK 0x180000 +#define GC_USB_DIEPTSIZ0_PKTCNT_SIZE 0x2 +#define GC_USB_DIEPTSIZ0_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ0_PKTCNT_OFFSET 0x910 +#define GC_USB_DIEPDMA0_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA0_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA0_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA0_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA0_DMAADDR_OFFSET 0x914 +#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS0_INEPTXFSPCAVAIL_OFFSET 0x918 +#define GC_USB_DIEPDMAB0_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB0_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB0_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB0_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB0_DMABUFFERADDR_OFFSET 0x91c +#define GC_USB_DIEPCTL1_MPS_LSB 0x0 +#define GC_USB_DIEPCTL1_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL1_MPS_SIZE 0xb +#define GC_USB_DIEPCTL1_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_MPS_OFFSET 0x920 +#define GC_USB_DIEPCTL1_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL1_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL1_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL1_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_USBACTEP_OFFSET 0x920 +#define GC_USB_DIEPCTL1_DPID_LSB 0x10 +#define GC_USB_DIEPCTL1_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL1_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL1_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_DPID_OFFSET 0x920 +#define GC_USB_DIEPCTL1_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL1_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL1_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL1_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_NAKSTS_OFFSET 0x920 +#define GC_USB_DIEPCTL1_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL1_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL1_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL1_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_EPTYPE_OFFSET 0x920 +#define GC_USB_DIEPCTL1_STALL_LSB 0x15 +#define GC_USB_DIEPCTL1_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL1_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL1_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_STALL_OFFSET 0x920 +#define GC_USB_DIEPCTL1_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL1_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL1_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL1_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_TXFNUM_OFFSET 0x920 +#define GC_USB_DIEPCTL1_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL1_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL1_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL1_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_CNAK_OFFSET 0x920 +#define GC_USB_DIEPCTL1_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL1_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL1_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL1_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_SNAK_OFFSET 0x920 +#define GC_USB_DIEPCTL1_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL1_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL1_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL1_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_SETD0PID_OFFSET 0x920 +#define GC_USB_DIEPCTL1_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL1_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL1_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL1_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_SETD1PID_OFFSET 0x920 +#define GC_USB_DIEPCTL1_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL1_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL1_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL1_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_EPDIS_OFFSET 0x920 +#define GC_USB_DIEPCTL1_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL1_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL1_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL1_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL1_EPENA_OFFSET 0x920 +#define GC_USB_DIEPINT1_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT1_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT1_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT1_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT1_XFERCOMPL_OFFSET 0x928 +#define GC_USB_DIEPINT1_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT1_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT1_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT1_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT1_EPDISBLD_OFFSET 0x928 +#define GC_USB_DIEPINT1_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT1_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT1_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT1_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT1_AHBERR_OFFSET 0x928 +#define GC_USB_DIEPINT1_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT1_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT1_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT1_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT1_TIMEOUT_OFFSET 0x928 +#define GC_USB_DIEPINT1_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT1_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT1_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT1_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT1_INTKNTXFEMP_OFFSET 0x928 +#define GC_USB_DIEPINT1_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT1_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT1_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT1_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT1_INTKNEPMIS_OFFSET 0x928 +#define GC_USB_DIEPINT1_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT1_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT1_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT1_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT1_INEPNAKEFF_OFFSET 0x928 +#define GC_USB_DIEPINT1_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT1_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT1_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT1_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT1_TXFEMP_OFFSET 0x928 +#define GC_USB_DIEPINT1_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT1_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT1_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT1_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT1_TXFIFOUNDRN_OFFSET 0x928 +#define GC_USB_DIEPINT1_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT1_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT1_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT1_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT1_BNAINTR_OFFSET 0x928 +#define GC_USB_DIEPINT1_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT1_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT1_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT1_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT1_PKTDRPSTS_OFFSET 0x928 +#define GC_USB_DIEPINT1_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT1_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT1_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT1_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT1_BBLEERR_OFFSET 0x928 +#define GC_USB_DIEPINT1_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT1_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT1_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT1_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT1_NAKINTRPT_OFFSET 0x928 +#define GC_USB_DIEPINT1_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT1_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT1_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT1_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT1_NYETINTRPT_OFFSET 0x928 +#define GC_USB_DIEPTSIZ1_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ1_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ1_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ1_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ1_XFERSIZE_OFFSET 0x930 +#define GC_USB_DIEPTSIZ1_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ1_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ1_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ1_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ1_PKTCNT_OFFSET 0x930 +#define GC_USB_DIEPTSIZ1_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ1_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ1_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ1_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ1_MC_OFFSET 0x930 +#define GC_USB_DIEPDMA1_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA1_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA1_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA1_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA1_DMAADDR_OFFSET 0x934 +#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS1_INEPTXFSPCAVAIL_OFFSET 0x938 +#define GC_USB_DIEPDMAB1_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB1_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB1_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB1_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB1_DMABUFFERADDR_OFFSET 0x93c +#define GC_USB_DIEPCTL2_MPS_LSB 0x0 +#define GC_USB_DIEPCTL2_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL2_MPS_SIZE 0xb +#define GC_USB_DIEPCTL2_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_MPS_OFFSET 0x940 +#define GC_USB_DIEPCTL2_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL2_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL2_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL2_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_USBACTEP_OFFSET 0x940 +#define GC_USB_DIEPCTL2_DPID_LSB 0x10 +#define GC_USB_DIEPCTL2_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL2_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL2_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_DPID_OFFSET 0x940 +#define GC_USB_DIEPCTL2_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL2_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL2_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL2_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_NAKSTS_OFFSET 0x940 +#define GC_USB_DIEPCTL2_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL2_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL2_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL2_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_EPTYPE_OFFSET 0x940 +#define GC_USB_DIEPCTL2_STALL_LSB 0x15 +#define GC_USB_DIEPCTL2_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL2_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL2_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_STALL_OFFSET 0x940 +#define GC_USB_DIEPCTL2_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL2_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL2_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL2_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_TXFNUM_OFFSET 0x940 +#define GC_USB_DIEPCTL2_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL2_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL2_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL2_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_CNAK_OFFSET 0x940 +#define GC_USB_DIEPCTL2_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL2_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL2_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL2_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_SNAK_OFFSET 0x940 +#define GC_USB_DIEPCTL2_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL2_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL2_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL2_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_SETD0PID_OFFSET 0x940 +#define GC_USB_DIEPCTL2_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL2_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL2_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL2_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_SETD1PID_OFFSET 0x940 +#define GC_USB_DIEPCTL2_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL2_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL2_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL2_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_EPDIS_OFFSET 0x940 +#define GC_USB_DIEPCTL2_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL2_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL2_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL2_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL2_EPENA_OFFSET 0x940 +#define GC_USB_DIEPINT2_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT2_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT2_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT2_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT2_XFERCOMPL_OFFSET 0x948 +#define GC_USB_DIEPINT2_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT2_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT2_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT2_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT2_EPDISBLD_OFFSET 0x948 +#define GC_USB_DIEPINT2_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT2_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT2_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT2_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT2_AHBERR_OFFSET 0x948 +#define GC_USB_DIEPINT2_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT2_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT2_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT2_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT2_TIMEOUT_OFFSET 0x948 +#define GC_USB_DIEPINT2_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT2_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT2_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT2_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT2_INTKNTXFEMP_OFFSET 0x948 +#define GC_USB_DIEPINT2_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT2_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT2_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT2_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT2_INTKNEPMIS_OFFSET 0x948 +#define GC_USB_DIEPINT2_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT2_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT2_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT2_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT2_INEPNAKEFF_OFFSET 0x948 +#define GC_USB_DIEPINT2_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT2_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT2_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT2_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT2_TXFEMP_OFFSET 0x948 +#define GC_USB_DIEPINT2_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT2_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT2_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT2_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT2_TXFIFOUNDRN_OFFSET 0x948 +#define GC_USB_DIEPINT2_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT2_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT2_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT2_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT2_BNAINTR_OFFSET 0x948 +#define GC_USB_DIEPINT2_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT2_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT2_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT2_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT2_PKTDRPSTS_OFFSET 0x948 +#define GC_USB_DIEPINT2_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT2_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT2_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT2_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT2_BBLEERR_OFFSET 0x948 +#define GC_USB_DIEPINT2_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT2_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT2_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT2_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT2_NAKINTRPT_OFFSET 0x948 +#define GC_USB_DIEPINT2_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT2_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT2_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT2_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT2_NYETINTRPT_OFFSET 0x948 +#define GC_USB_DIEPTSIZ2_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ2_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ2_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ2_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ2_XFERSIZE_OFFSET 0x950 +#define GC_USB_DIEPTSIZ2_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ2_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ2_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ2_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ2_PKTCNT_OFFSET 0x950 +#define GC_USB_DIEPTSIZ2_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ2_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ2_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ2_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ2_MC_OFFSET 0x950 +#define GC_USB_DIEPDMA2_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA2_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA2_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA2_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA2_DMAADDR_OFFSET 0x954 +#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS2_INEPTXFSPCAVAIL_OFFSET 0x958 +#define GC_USB_DIEPDMAB2_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB2_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB2_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB2_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB2_DMABUFFERADDR_OFFSET 0x95c +#define GC_USB_DIEPCTL3_MPS_LSB 0x0 +#define GC_USB_DIEPCTL3_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL3_MPS_SIZE 0xb +#define GC_USB_DIEPCTL3_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_MPS_OFFSET 0x960 +#define GC_USB_DIEPCTL3_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL3_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL3_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL3_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_USBACTEP_OFFSET 0x960 +#define GC_USB_DIEPCTL3_DPID_LSB 0x10 +#define GC_USB_DIEPCTL3_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL3_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL3_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_DPID_OFFSET 0x960 +#define GC_USB_DIEPCTL3_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL3_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL3_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL3_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_NAKSTS_OFFSET 0x960 +#define GC_USB_DIEPCTL3_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL3_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL3_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL3_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_EPTYPE_OFFSET 0x960 +#define GC_USB_DIEPCTL3_STALL_LSB 0x15 +#define GC_USB_DIEPCTL3_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL3_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL3_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_STALL_OFFSET 0x960 +#define GC_USB_DIEPCTL3_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL3_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL3_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL3_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_TXFNUM_OFFSET 0x960 +#define GC_USB_DIEPCTL3_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL3_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL3_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL3_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_CNAK_OFFSET 0x960 +#define GC_USB_DIEPCTL3_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL3_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL3_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL3_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_SNAK_OFFSET 0x960 +#define GC_USB_DIEPCTL3_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL3_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL3_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL3_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_SETD0PID_OFFSET 0x960 +#define GC_USB_DIEPCTL3_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL3_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL3_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL3_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_SETD1PID_OFFSET 0x960 +#define GC_USB_DIEPCTL3_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL3_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL3_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL3_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_EPDIS_OFFSET 0x960 +#define GC_USB_DIEPCTL3_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL3_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL3_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL3_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL3_EPENA_OFFSET 0x960 +#define GC_USB_DIEPINT3_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT3_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT3_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT3_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT3_XFERCOMPL_OFFSET 0x968 +#define GC_USB_DIEPINT3_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT3_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT3_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT3_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT3_EPDISBLD_OFFSET 0x968 +#define GC_USB_DIEPINT3_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT3_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT3_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT3_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT3_AHBERR_OFFSET 0x968 +#define GC_USB_DIEPINT3_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT3_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT3_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT3_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT3_TIMEOUT_OFFSET 0x968 +#define GC_USB_DIEPINT3_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT3_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT3_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT3_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT3_INTKNTXFEMP_OFFSET 0x968 +#define GC_USB_DIEPINT3_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT3_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT3_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT3_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT3_INTKNEPMIS_OFFSET 0x968 +#define GC_USB_DIEPINT3_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT3_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT3_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT3_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT3_INEPNAKEFF_OFFSET 0x968 +#define GC_USB_DIEPINT3_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT3_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT3_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT3_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT3_TXFEMP_OFFSET 0x968 +#define GC_USB_DIEPINT3_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT3_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT3_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT3_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT3_TXFIFOUNDRN_OFFSET 0x968 +#define GC_USB_DIEPINT3_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT3_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT3_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT3_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT3_BNAINTR_OFFSET 0x968 +#define GC_USB_DIEPINT3_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT3_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT3_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT3_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT3_PKTDRPSTS_OFFSET 0x968 +#define GC_USB_DIEPINT3_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT3_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT3_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT3_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT3_BBLEERR_OFFSET 0x968 +#define GC_USB_DIEPINT3_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT3_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT3_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT3_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT3_NAKINTRPT_OFFSET 0x968 +#define GC_USB_DIEPINT3_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT3_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT3_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT3_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT3_NYETINTRPT_OFFSET 0x968 +#define GC_USB_DIEPTSIZ3_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ3_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ3_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ3_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ3_XFERSIZE_OFFSET 0x970 +#define GC_USB_DIEPTSIZ3_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ3_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ3_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ3_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ3_PKTCNT_OFFSET 0x970 +#define GC_USB_DIEPTSIZ3_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ3_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ3_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ3_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ3_MC_OFFSET 0x970 +#define GC_USB_DIEPDMA3_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA3_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA3_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA3_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA3_DMAADDR_OFFSET 0x974 +#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS3_INEPTXFSPCAVAIL_OFFSET 0x978 +#define GC_USB_DIEPDMAB3_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB3_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB3_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB3_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB3_DMABUFFERADDR_OFFSET 0x97c +#define GC_USB_DIEPCTL4_MPS_LSB 0x0 +#define GC_USB_DIEPCTL4_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL4_MPS_SIZE 0xb +#define GC_USB_DIEPCTL4_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_MPS_OFFSET 0x980 +#define GC_USB_DIEPCTL4_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL4_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL4_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL4_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_USBACTEP_OFFSET 0x980 +#define GC_USB_DIEPCTL4_DPID_LSB 0x10 +#define GC_USB_DIEPCTL4_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL4_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL4_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_DPID_OFFSET 0x980 +#define GC_USB_DIEPCTL4_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL4_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL4_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL4_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_NAKSTS_OFFSET 0x980 +#define GC_USB_DIEPCTL4_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL4_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL4_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL4_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_EPTYPE_OFFSET 0x980 +#define GC_USB_DIEPCTL4_STALL_LSB 0x15 +#define GC_USB_DIEPCTL4_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL4_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL4_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_STALL_OFFSET 0x980 +#define GC_USB_DIEPCTL4_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL4_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL4_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL4_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_TXFNUM_OFFSET 0x980 +#define GC_USB_DIEPCTL4_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL4_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL4_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL4_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_CNAK_OFFSET 0x980 +#define GC_USB_DIEPCTL4_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL4_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL4_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL4_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_SNAK_OFFSET 0x980 +#define GC_USB_DIEPCTL4_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL4_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL4_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL4_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_SETD0PID_OFFSET 0x980 +#define GC_USB_DIEPCTL4_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL4_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL4_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL4_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_SETD1PID_OFFSET 0x980 +#define GC_USB_DIEPCTL4_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL4_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL4_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL4_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_EPDIS_OFFSET 0x980 +#define GC_USB_DIEPCTL4_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL4_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL4_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL4_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL4_EPENA_OFFSET 0x980 +#define GC_USB_DIEPINT4_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT4_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT4_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT4_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT4_XFERCOMPL_OFFSET 0x988 +#define GC_USB_DIEPINT4_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT4_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT4_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT4_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT4_EPDISBLD_OFFSET 0x988 +#define GC_USB_DIEPINT4_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT4_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT4_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT4_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT4_AHBERR_OFFSET 0x988 +#define GC_USB_DIEPINT4_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT4_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT4_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT4_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT4_TIMEOUT_OFFSET 0x988 +#define GC_USB_DIEPINT4_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT4_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT4_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT4_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT4_INTKNTXFEMP_OFFSET 0x988 +#define GC_USB_DIEPINT4_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT4_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT4_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT4_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT4_INTKNEPMIS_OFFSET 0x988 +#define GC_USB_DIEPINT4_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT4_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT4_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT4_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT4_INEPNAKEFF_OFFSET 0x988 +#define GC_USB_DIEPINT4_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT4_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT4_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT4_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT4_TXFEMP_OFFSET 0x988 +#define GC_USB_DIEPINT4_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT4_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT4_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT4_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT4_TXFIFOUNDRN_OFFSET 0x988 +#define GC_USB_DIEPINT4_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT4_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT4_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT4_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT4_BNAINTR_OFFSET 0x988 +#define GC_USB_DIEPINT4_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT4_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT4_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT4_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT4_PKTDRPSTS_OFFSET 0x988 +#define GC_USB_DIEPINT4_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT4_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT4_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT4_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT4_BBLEERR_OFFSET 0x988 +#define GC_USB_DIEPINT4_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT4_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT4_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT4_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT4_NAKINTRPT_OFFSET 0x988 +#define GC_USB_DIEPINT4_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT4_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT4_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT4_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT4_NYETINTRPT_OFFSET 0x988 +#define GC_USB_DIEPTSIZ4_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ4_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ4_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ4_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ4_XFERSIZE_OFFSET 0x990 +#define GC_USB_DIEPTSIZ4_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ4_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ4_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ4_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ4_PKTCNT_OFFSET 0x990 +#define GC_USB_DIEPTSIZ4_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ4_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ4_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ4_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ4_MC_OFFSET 0x990 +#define GC_USB_DIEPDMA4_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA4_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA4_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA4_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA4_DMAADDR_OFFSET 0x994 +#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS4_INEPTXFSPCAVAIL_OFFSET 0x998 +#define GC_USB_DIEPDMAB4_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB4_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB4_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB4_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB4_DMABUFFERADDR_OFFSET 0x99c +#define GC_USB_DIEPCTL5_MPS_LSB 0x0 +#define GC_USB_DIEPCTL5_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL5_MPS_SIZE 0xb +#define GC_USB_DIEPCTL5_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_MPS_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL5_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL5_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL5_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_USBACTEP_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_DPID_LSB 0x10 +#define GC_USB_DIEPCTL5_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL5_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL5_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_DPID_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL5_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL5_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL5_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_NAKSTS_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL5_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL5_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL5_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_EPTYPE_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_STALL_LSB 0x15 +#define GC_USB_DIEPCTL5_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL5_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL5_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_STALL_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL5_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL5_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL5_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_TXFNUM_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL5_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL5_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL5_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_CNAK_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL5_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL5_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL5_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_SNAK_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL5_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL5_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL5_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_SETD0PID_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL5_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL5_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL5_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_SETD1PID_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL5_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL5_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL5_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_EPDIS_OFFSET 0x9a0 +#define GC_USB_DIEPCTL5_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL5_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL5_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL5_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL5_EPENA_OFFSET 0x9a0 +#define GC_USB_DIEPINT5_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT5_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT5_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT5_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT5_XFERCOMPL_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT5_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT5_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT5_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT5_EPDISBLD_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT5_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT5_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT5_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT5_AHBERR_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT5_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT5_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT5_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT5_TIMEOUT_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT5_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT5_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT5_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT5_INTKNTXFEMP_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT5_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT5_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT5_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT5_INTKNEPMIS_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT5_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT5_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT5_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT5_INEPNAKEFF_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT5_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT5_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT5_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT5_TXFEMP_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT5_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT5_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT5_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT5_TXFIFOUNDRN_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT5_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT5_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT5_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT5_BNAINTR_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT5_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT5_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT5_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT5_PKTDRPSTS_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT5_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT5_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT5_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT5_BBLEERR_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT5_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT5_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT5_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT5_NAKINTRPT_OFFSET 0x9a8 +#define GC_USB_DIEPINT5_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT5_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT5_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT5_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT5_NYETINTRPT_OFFSET 0x9a8 +#define GC_USB_DIEPTSIZ5_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ5_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ5_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ5_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ5_XFERSIZE_OFFSET 0x9b0 +#define GC_USB_DIEPTSIZ5_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ5_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ5_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ5_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ5_PKTCNT_OFFSET 0x9b0 +#define GC_USB_DIEPTSIZ5_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ5_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ5_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ5_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ5_MC_OFFSET 0x9b0 +#define GC_USB_DIEPDMA5_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA5_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA5_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA5_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA5_DMAADDR_OFFSET 0x9b4 +#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS5_INEPTXFSPCAVAIL_OFFSET 0x9b8 +#define GC_USB_DIEPDMAB5_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB5_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB5_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB5_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB5_DMABUFFERADDR_OFFSET 0x9bc +#define GC_USB_DIEPCTL6_MPS_LSB 0x0 +#define GC_USB_DIEPCTL6_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL6_MPS_SIZE 0xb +#define GC_USB_DIEPCTL6_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_MPS_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL6_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL6_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL6_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_USBACTEP_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_DPID_LSB 0x10 +#define GC_USB_DIEPCTL6_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL6_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL6_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_DPID_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL6_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL6_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL6_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_NAKSTS_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL6_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL6_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL6_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_EPTYPE_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_STALL_LSB 0x15 +#define GC_USB_DIEPCTL6_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL6_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL6_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_STALL_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL6_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL6_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL6_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_TXFNUM_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL6_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL6_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL6_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_CNAK_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL6_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL6_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL6_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_SNAK_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL6_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL6_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL6_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_SETD0PID_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL6_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL6_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL6_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_SETD1PID_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL6_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL6_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL6_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_EPDIS_OFFSET 0x9c0 +#define GC_USB_DIEPCTL6_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL6_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL6_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL6_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL6_EPENA_OFFSET 0x9c0 +#define GC_USB_DIEPINT6_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT6_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT6_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT6_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT6_XFERCOMPL_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT6_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT6_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT6_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT6_EPDISBLD_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT6_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT6_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT6_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT6_AHBERR_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT6_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT6_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT6_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT6_TIMEOUT_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT6_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT6_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT6_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT6_INTKNTXFEMP_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT6_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT6_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT6_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT6_INTKNEPMIS_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT6_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT6_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT6_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT6_INEPNAKEFF_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT6_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT6_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT6_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT6_TXFEMP_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT6_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT6_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT6_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT6_TXFIFOUNDRN_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT6_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT6_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT6_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT6_BNAINTR_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT6_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT6_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT6_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT6_PKTDRPSTS_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT6_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT6_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT6_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT6_BBLEERR_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT6_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT6_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT6_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT6_NAKINTRPT_OFFSET 0x9c8 +#define GC_USB_DIEPINT6_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT6_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT6_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT6_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT6_NYETINTRPT_OFFSET 0x9c8 +#define GC_USB_DIEPTSIZ6_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ6_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ6_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ6_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ6_XFERSIZE_OFFSET 0x9d0 +#define GC_USB_DIEPTSIZ6_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ6_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ6_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ6_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ6_PKTCNT_OFFSET 0x9d0 +#define GC_USB_DIEPTSIZ6_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ6_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ6_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ6_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ6_MC_OFFSET 0x9d0 +#define GC_USB_DIEPDMA6_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA6_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA6_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA6_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA6_DMAADDR_OFFSET 0x9d4 +#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS6_INEPTXFSPCAVAIL_OFFSET 0x9d8 +#define GC_USB_DIEPDMAB6_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB6_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB6_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB6_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB6_DMABUFFERADDR_OFFSET 0x9dc +#define GC_USB_DIEPCTL7_MPS_LSB 0x0 +#define GC_USB_DIEPCTL7_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL7_MPS_SIZE 0xb +#define GC_USB_DIEPCTL7_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_MPS_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL7_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL7_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL7_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_USBACTEP_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_DPID_LSB 0x10 +#define GC_USB_DIEPCTL7_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL7_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL7_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_DPID_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL7_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL7_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL7_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_NAKSTS_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL7_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL7_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL7_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_EPTYPE_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_STALL_LSB 0x15 +#define GC_USB_DIEPCTL7_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL7_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL7_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_STALL_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL7_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL7_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL7_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_TXFNUM_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL7_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL7_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL7_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_CNAK_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL7_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL7_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL7_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_SNAK_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL7_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL7_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL7_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_SETD0PID_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL7_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL7_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL7_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_SETD1PID_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL7_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL7_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL7_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_EPDIS_OFFSET 0x9e0 +#define GC_USB_DIEPCTL7_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL7_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL7_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL7_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL7_EPENA_OFFSET 0x9e0 +#define GC_USB_DIEPINT7_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT7_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT7_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT7_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT7_XFERCOMPL_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT7_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT7_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT7_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT7_EPDISBLD_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT7_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT7_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT7_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT7_AHBERR_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT7_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT7_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT7_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT7_TIMEOUT_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT7_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT7_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT7_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT7_INTKNTXFEMP_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT7_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT7_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT7_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT7_INTKNEPMIS_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT7_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT7_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT7_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT7_INEPNAKEFF_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT7_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT7_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT7_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT7_TXFEMP_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT7_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT7_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT7_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT7_TXFIFOUNDRN_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT7_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT7_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT7_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT7_BNAINTR_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT7_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT7_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT7_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT7_PKTDRPSTS_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT7_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT7_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT7_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT7_BBLEERR_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT7_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT7_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT7_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT7_NAKINTRPT_OFFSET 0x9e8 +#define GC_USB_DIEPINT7_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT7_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT7_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT7_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT7_NYETINTRPT_OFFSET 0x9e8 +#define GC_USB_DIEPTSIZ7_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ7_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ7_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ7_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ7_XFERSIZE_OFFSET 0x9f0 +#define GC_USB_DIEPTSIZ7_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ7_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ7_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ7_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ7_PKTCNT_OFFSET 0x9f0 +#define GC_USB_DIEPTSIZ7_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ7_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ7_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ7_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ7_MC_OFFSET 0x9f0 +#define GC_USB_DIEPDMA7_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA7_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA7_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA7_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA7_DMAADDR_OFFSET 0x9f4 +#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS7_INEPTXFSPCAVAIL_OFFSET 0x9f8 +#define GC_USB_DIEPDMAB7_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB7_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB7_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB7_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB7_DMABUFFERADDR_OFFSET 0x9fc +#define GC_USB_DIEPCTL8_MPS_LSB 0x0 +#define GC_USB_DIEPCTL8_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL8_MPS_SIZE 0xb +#define GC_USB_DIEPCTL8_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_MPS_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL8_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL8_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL8_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_USBACTEP_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_DPID_LSB 0x10 +#define GC_USB_DIEPCTL8_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL8_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL8_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_DPID_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL8_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL8_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL8_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_NAKSTS_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL8_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL8_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL8_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_EPTYPE_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_STALL_LSB 0x15 +#define GC_USB_DIEPCTL8_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL8_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL8_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_STALL_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL8_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL8_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL8_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_TXFNUM_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL8_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL8_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL8_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_CNAK_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL8_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL8_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL8_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_SNAK_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL8_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL8_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL8_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_SETD0PID_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL8_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL8_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL8_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_SETD1PID_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL8_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL8_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL8_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_EPDIS_OFFSET 0xa00 +#define GC_USB_DIEPCTL8_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL8_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL8_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL8_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL8_EPENA_OFFSET 0xa00 +#define GC_USB_DIEPINT8_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT8_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT8_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT8_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT8_XFERCOMPL_OFFSET 0xa08 +#define GC_USB_DIEPINT8_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT8_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT8_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT8_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT8_EPDISBLD_OFFSET 0xa08 +#define GC_USB_DIEPINT8_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT8_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT8_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT8_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT8_AHBERR_OFFSET 0xa08 +#define GC_USB_DIEPINT8_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT8_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT8_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT8_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT8_TIMEOUT_OFFSET 0xa08 +#define GC_USB_DIEPINT8_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT8_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT8_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT8_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT8_INTKNTXFEMP_OFFSET 0xa08 +#define GC_USB_DIEPINT8_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT8_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT8_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT8_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT8_INTKNEPMIS_OFFSET 0xa08 +#define GC_USB_DIEPINT8_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT8_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT8_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT8_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT8_INEPNAKEFF_OFFSET 0xa08 +#define GC_USB_DIEPINT8_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT8_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT8_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT8_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT8_TXFEMP_OFFSET 0xa08 +#define GC_USB_DIEPINT8_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT8_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT8_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT8_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT8_TXFIFOUNDRN_OFFSET 0xa08 +#define GC_USB_DIEPINT8_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT8_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT8_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT8_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT8_BNAINTR_OFFSET 0xa08 +#define GC_USB_DIEPINT8_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT8_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT8_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT8_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT8_PKTDRPSTS_OFFSET 0xa08 +#define GC_USB_DIEPINT8_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT8_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT8_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT8_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT8_BBLEERR_OFFSET 0xa08 +#define GC_USB_DIEPINT8_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT8_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT8_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT8_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT8_NAKINTRPT_OFFSET 0xa08 +#define GC_USB_DIEPINT8_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT8_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT8_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT8_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT8_NYETINTRPT_OFFSET 0xa08 +#define GC_USB_DIEPTSIZ8_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ8_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ8_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ8_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ8_XFERSIZE_OFFSET 0xa10 +#define GC_USB_DIEPTSIZ8_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ8_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ8_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ8_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ8_PKTCNT_OFFSET 0xa10 +#define GC_USB_DIEPTSIZ8_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ8_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ8_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ8_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ8_MC_OFFSET 0xa10 +#define GC_USB_DIEPDMA8_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA8_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA8_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA8_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA8_DMAADDR_OFFSET 0xa14 +#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS8_INEPTXFSPCAVAIL_OFFSET 0xa18 +#define GC_USB_DIEPDMAB8_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB8_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB8_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB8_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB8_DMABUFFERADDR_OFFSET 0xa1c +#define GC_USB_DIEPCTL9_MPS_LSB 0x0 +#define GC_USB_DIEPCTL9_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL9_MPS_SIZE 0xb +#define GC_USB_DIEPCTL9_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_MPS_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL9_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL9_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL9_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_USBACTEP_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_DPID_LSB 0x10 +#define GC_USB_DIEPCTL9_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL9_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL9_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_DPID_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL9_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL9_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL9_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_NAKSTS_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL9_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL9_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL9_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_EPTYPE_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_STALL_LSB 0x15 +#define GC_USB_DIEPCTL9_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL9_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL9_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_STALL_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL9_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL9_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL9_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_TXFNUM_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL9_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL9_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL9_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_CNAK_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL9_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL9_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL9_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_SNAK_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL9_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL9_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL9_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_SETD0PID_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL9_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL9_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL9_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_SETD1PID_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL9_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL9_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL9_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_EPDIS_OFFSET 0xa20 +#define GC_USB_DIEPCTL9_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL9_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL9_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL9_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL9_EPENA_OFFSET 0xa20 +#define GC_USB_DIEPINT9_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT9_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT9_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT9_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT9_XFERCOMPL_OFFSET 0xa28 +#define GC_USB_DIEPINT9_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT9_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT9_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT9_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT9_EPDISBLD_OFFSET 0xa28 +#define GC_USB_DIEPINT9_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT9_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT9_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT9_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT9_AHBERR_OFFSET 0xa28 +#define GC_USB_DIEPINT9_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT9_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT9_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT9_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT9_TIMEOUT_OFFSET 0xa28 +#define GC_USB_DIEPINT9_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT9_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT9_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT9_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT9_INTKNTXFEMP_OFFSET 0xa28 +#define GC_USB_DIEPINT9_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT9_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT9_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT9_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT9_INTKNEPMIS_OFFSET 0xa28 +#define GC_USB_DIEPINT9_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT9_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT9_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT9_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT9_INEPNAKEFF_OFFSET 0xa28 +#define GC_USB_DIEPINT9_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT9_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT9_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT9_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT9_TXFEMP_OFFSET 0xa28 +#define GC_USB_DIEPINT9_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT9_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT9_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT9_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT9_TXFIFOUNDRN_OFFSET 0xa28 +#define GC_USB_DIEPINT9_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT9_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT9_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT9_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT9_BNAINTR_OFFSET 0xa28 +#define GC_USB_DIEPINT9_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT9_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT9_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT9_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT9_PKTDRPSTS_OFFSET 0xa28 +#define GC_USB_DIEPINT9_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT9_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT9_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT9_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT9_BBLEERR_OFFSET 0xa28 +#define GC_USB_DIEPINT9_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT9_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT9_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT9_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT9_NAKINTRPT_OFFSET 0xa28 +#define GC_USB_DIEPINT9_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT9_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT9_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT9_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT9_NYETINTRPT_OFFSET 0xa28 +#define GC_USB_DIEPTSIZ9_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ9_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ9_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ9_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ9_XFERSIZE_OFFSET 0xa30 +#define GC_USB_DIEPTSIZ9_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ9_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ9_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ9_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ9_PKTCNT_OFFSET 0xa30 +#define GC_USB_DIEPTSIZ9_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ9_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ9_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ9_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ9_MC_OFFSET 0xa30 +#define GC_USB_DIEPDMA9_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA9_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA9_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA9_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA9_DMAADDR_OFFSET 0xa34 +#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_DEFAULT 0x0 +#define GC_USB_DTXFSTS9_INEPTXFSPCAVAIL_OFFSET 0xa38 +#define GC_USB_DIEPDMAB9_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB9_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB9_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB9_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB9_DMABUFFERADDR_OFFSET 0xa3c +#define GC_USB_DIEPCTL10_MPS_LSB 0x0 +#define GC_USB_DIEPCTL10_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL10_MPS_SIZE 0xb +#define GC_USB_DIEPCTL10_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_MPS_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL10_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL10_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL10_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_USBACTEP_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_DPID_LSB 0x10 +#define GC_USB_DIEPCTL10_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL10_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL10_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_DPID_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL10_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL10_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL10_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_NAKSTS_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL10_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL10_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL10_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_EPTYPE_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_STALL_LSB 0x15 +#define GC_USB_DIEPCTL10_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL10_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL10_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_STALL_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL10_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL10_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL10_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_TXFNUM_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL10_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL10_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL10_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_CNAK_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL10_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL10_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL10_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_SNAK_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL10_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL10_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL10_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_SETD0PID_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL10_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL10_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL10_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_SETD1PID_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL10_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL10_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL10_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_EPDIS_OFFSET 0xa40 +#define GC_USB_DIEPCTL10_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL10_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL10_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL10_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL10_EPENA_OFFSET 0xa40 +#define GC_USB_DIEPINT10_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT10_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT10_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT10_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT10_XFERCOMPL_OFFSET 0xa48 +#define GC_USB_DIEPINT10_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT10_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT10_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT10_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT10_EPDISBLD_OFFSET 0xa48 +#define GC_USB_DIEPINT10_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT10_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT10_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT10_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT10_AHBERR_OFFSET 0xa48 +#define GC_USB_DIEPINT10_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT10_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT10_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT10_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT10_TIMEOUT_OFFSET 0xa48 +#define GC_USB_DIEPINT10_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT10_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT10_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT10_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT10_INTKNTXFEMP_OFFSET 0xa48 +#define GC_USB_DIEPINT10_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT10_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT10_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT10_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT10_INTKNEPMIS_OFFSET 0xa48 +#define GC_USB_DIEPINT10_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT10_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT10_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT10_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT10_INEPNAKEFF_OFFSET 0xa48 +#define GC_USB_DIEPINT10_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT10_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT10_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT10_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT10_TXFEMP_OFFSET 0xa48 +#define GC_USB_DIEPINT10_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT10_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT10_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT10_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT10_TXFIFOUNDRN_OFFSET 0xa48 +#define GC_USB_DIEPINT10_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT10_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT10_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT10_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT10_BNAINTR_OFFSET 0xa48 +#define GC_USB_DIEPINT10_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT10_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT10_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT10_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT10_PKTDRPSTS_OFFSET 0xa48 +#define GC_USB_DIEPINT10_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT10_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT10_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT10_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT10_BBLEERR_OFFSET 0xa48 +#define GC_USB_DIEPINT10_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT10_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT10_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT10_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT10_NAKINTRPT_OFFSET 0xa48 +#define GC_USB_DIEPINT10_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT10_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT10_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT10_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT10_NYETINTRPT_OFFSET 0xa48 +#define GC_USB_DIEPTSIZ10_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ10_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ10_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ10_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ10_XFERSIZE_OFFSET 0xa50 +#define GC_USB_DIEPTSIZ10_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ10_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ10_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ10_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ10_PKTCNT_OFFSET 0xa50 +#define GC_USB_DIEPTSIZ10_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ10_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ10_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ10_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ10_MC_OFFSET 0xa50 +#define GC_USB_DIEPDMA10_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA10_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA10_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA10_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA10_DMAADDR_OFFSET 0xa54 +#define GC_USB_DTXFSTS10_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS10_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS10_INEPTXFSPCAVAIL_SIZE 0x10 #define GC_USB_DTXFSTS10_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS10_INEPTXFSPCAVAIL_OFFSET 0xa58 -#define GC_USB_DIEPDMAB10_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB10_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB10_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB10_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB10_DMABUFFERADDR_OFFSET 0xa5c -#define GC_USB_DIEPCTL11_MPS_LSB 0x0 -#define GC_USB_DIEPCTL11_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL11_MPS_SIZE 0xb -#define GC_USB_DIEPCTL11_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_MPS_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL11_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL11_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL11_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_USBACTEP_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_DPID_LSB 0x10 -#define GC_USB_DIEPCTL11_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL11_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL11_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_DPID_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL11_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL11_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL11_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_NAKSTS_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL11_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL11_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL11_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_EPTYPE_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_STALL_LSB 0x15 -#define GC_USB_DIEPCTL11_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL11_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL11_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_STALL_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL11_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL11_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL11_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_TXFNUM_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL11_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL11_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL11_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_CNAK_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL11_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL11_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL11_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_SNAK_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL11_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL11_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL11_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_SETD0PID_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL11_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL11_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL11_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_SETD1PID_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL11_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL11_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL11_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_EPDIS_OFFSET 0xa60 -#define GC_USB_DIEPCTL11_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL11_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL11_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL11_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL11_EPENA_OFFSET 0xa60 -#define GC_USB_DIEPINT11_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT11_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT11_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT11_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT11_XFERCOMPL_OFFSET 0xa68 -#define GC_USB_DIEPINT11_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT11_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT11_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT11_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT11_EPDISBLD_OFFSET 0xa68 -#define GC_USB_DIEPINT11_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT11_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT11_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT11_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT11_AHBERR_OFFSET 0xa68 -#define GC_USB_DIEPINT11_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT11_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT11_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT11_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT11_TIMEOUT_OFFSET 0xa68 -#define GC_USB_DIEPINT11_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT11_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT11_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT11_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT11_INTKNTXFEMP_OFFSET 0xa68 -#define GC_USB_DIEPINT11_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT11_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT11_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT11_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT11_INTKNEPMIS_OFFSET 0xa68 -#define GC_USB_DIEPINT11_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT11_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT11_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT11_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT11_INEPNAKEFF_OFFSET 0xa68 -#define GC_USB_DIEPINT11_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT11_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT11_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT11_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT11_TXFEMP_OFFSET 0xa68 -#define GC_USB_DIEPINT11_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT11_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT11_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT11_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT11_TXFIFOUNDRN_OFFSET 0xa68 -#define GC_USB_DIEPINT11_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT11_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT11_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT11_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT11_BNAINTR_OFFSET 0xa68 -#define GC_USB_DIEPINT11_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT11_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT11_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT11_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT11_PKTDRPSTS_OFFSET 0xa68 -#define GC_USB_DIEPINT11_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT11_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT11_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT11_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT11_BBLEERR_OFFSET 0xa68 -#define GC_USB_DIEPINT11_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT11_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT11_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT11_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT11_NAKINTRPT_OFFSET 0xa68 -#define GC_USB_DIEPINT11_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT11_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT11_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT11_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT11_NYETINTRPT_OFFSET 0xa68 -#define GC_USB_DIEPTSIZ11_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ11_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ11_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ11_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ11_XFERSIZE_OFFSET 0xa70 -#define GC_USB_DIEPTSIZ11_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ11_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ11_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ11_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ11_PKTCNT_OFFSET 0xa70 -#define GC_USB_DIEPTSIZ11_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ11_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ11_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ11_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ11_MC_OFFSET 0xa70 -#define GC_USB_DIEPDMA11_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA11_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA11_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA11_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA11_DMAADDR_OFFSET 0xa74 -#define GC_USB_DTXFSTS11_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS11_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS11_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS10_INEPTXFSPCAVAIL_OFFSET 0xa58 +#define GC_USB_DIEPDMAB10_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB10_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB10_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB10_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB10_DMABUFFERADDR_OFFSET 0xa5c +#define GC_USB_DIEPCTL11_MPS_LSB 0x0 +#define GC_USB_DIEPCTL11_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL11_MPS_SIZE 0xb +#define GC_USB_DIEPCTL11_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_MPS_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL11_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL11_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL11_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_USBACTEP_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_DPID_LSB 0x10 +#define GC_USB_DIEPCTL11_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL11_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL11_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_DPID_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL11_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL11_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL11_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_NAKSTS_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL11_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL11_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL11_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_EPTYPE_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_STALL_LSB 0x15 +#define GC_USB_DIEPCTL11_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL11_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL11_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_STALL_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL11_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL11_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL11_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_TXFNUM_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL11_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL11_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL11_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_CNAK_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL11_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL11_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL11_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_SNAK_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL11_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL11_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL11_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_SETD0PID_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL11_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL11_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL11_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_SETD1PID_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL11_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL11_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL11_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_EPDIS_OFFSET 0xa60 +#define GC_USB_DIEPCTL11_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL11_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL11_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL11_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL11_EPENA_OFFSET 0xa60 +#define GC_USB_DIEPINT11_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT11_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT11_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT11_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT11_XFERCOMPL_OFFSET 0xa68 +#define GC_USB_DIEPINT11_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT11_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT11_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT11_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT11_EPDISBLD_OFFSET 0xa68 +#define GC_USB_DIEPINT11_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT11_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT11_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT11_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT11_AHBERR_OFFSET 0xa68 +#define GC_USB_DIEPINT11_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT11_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT11_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT11_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT11_TIMEOUT_OFFSET 0xa68 +#define GC_USB_DIEPINT11_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT11_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT11_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT11_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT11_INTKNTXFEMP_OFFSET 0xa68 +#define GC_USB_DIEPINT11_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT11_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT11_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT11_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT11_INTKNEPMIS_OFFSET 0xa68 +#define GC_USB_DIEPINT11_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT11_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT11_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT11_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT11_INEPNAKEFF_OFFSET 0xa68 +#define GC_USB_DIEPINT11_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT11_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT11_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT11_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT11_TXFEMP_OFFSET 0xa68 +#define GC_USB_DIEPINT11_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT11_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT11_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT11_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT11_TXFIFOUNDRN_OFFSET 0xa68 +#define GC_USB_DIEPINT11_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT11_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT11_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT11_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT11_BNAINTR_OFFSET 0xa68 +#define GC_USB_DIEPINT11_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT11_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT11_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT11_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT11_PKTDRPSTS_OFFSET 0xa68 +#define GC_USB_DIEPINT11_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT11_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT11_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT11_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT11_BBLEERR_OFFSET 0xa68 +#define GC_USB_DIEPINT11_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT11_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT11_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT11_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT11_NAKINTRPT_OFFSET 0xa68 +#define GC_USB_DIEPINT11_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT11_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT11_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT11_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT11_NYETINTRPT_OFFSET 0xa68 +#define GC_USB_DIEPTSIZ11_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ11_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ11_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ11_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ11_XFERSIZE_OFFSET 0xa70 +#define GC_USB_DIEPTSIZ11_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ11_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ11_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ11_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ11_PKTCNT_OFFSET 0xa70 +#define GC_USB_DIEPTSIZ11_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ11_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ11_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ11_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ11_MC_OFFSET 0xa70 +#define GC_USB_DIEPDMA11_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA11_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA11_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA11_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA11_DMAADDR_OFFSET 0xa74 +#define GC_USB_DTXFSTS11_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS11_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS11_INEPTXFSPCAVAIL_SIZE 0x10 #define GC_USB_DTXFSTS11_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS11_INEPTXFSPCAVAIL_OFFSET 0xa78 -#define GC_USB_DIEPDMAB11_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB11_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB11_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB11_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB11_DMABUFFERADDR_OFFSET 0xa7c -#define GC_USB_DIEPCTL12_MPS_LSB 0x0 -#define GC_USB_DIEPCTL12_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL12_MPS_SIZE 0xb -#define GC_USB_DIEPCTL12_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_MPS_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL12_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL12_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL12_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_USBACTEP_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_DPID_LSB 0x10 -#define GC_USB_DIEPCTL12_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL12_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL12_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_DPID_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL12_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL12_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL12_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_NAKSTS_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL12_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL12_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL12_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_EPTYPE_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_STALL_LSB 0x15 -#define GC_USB_DIEPCTL12_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL12_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL12_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_STALL_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL12_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL12_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL12_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_TXFNUM_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL12_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL12_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL12_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_CNAK_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL12_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL12_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL12_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_SNAK_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL12_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL12_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL12_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_SETD0PID_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL12_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL12_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL12_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_SETD1PID_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL12_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL12_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL12_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_EPDIS_OFFSET 0xa80 -#define GC_USB_DIEPCTL12_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL12_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL12_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL12_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL12_EPENA_OFFSET 0xa80 -#define GC_USB_DIEPINT12_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT12_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT12_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT12_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT12_XFERCOMPL_OFFSET 0xa88 -#define GC_USB_DIEPINT12_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT12_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT12_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT12_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT12_EPDISBLD_OFFSET 0xa88 -#define GC_USB_DIEPINT12_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT12_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT12_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT12_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT12_AHBERR_OFFSET 0xa88 -#define GC_USB_DIEPINT12_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT12_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT12_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT12_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT12_TIMEOUT_OFFSET 0xa88 -#define GC_USB_DIEPINT12_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT12_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT12_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT12_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT12_INTKNTXFEMP_OFFSET 0xa88 -#define GC_USB_DIEPINT12_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT12_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT12_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT12_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT12_INTKNEPMIS_OFFSET 0xa88 -#define GC_USB_DIEPINT12_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT12_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT12_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT12_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT12_INEPNAKEFF_OFFSET 0xa88 -#define GC_USB_DIEPINT12_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT12_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT12_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT12_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT12_TXFEMP_OFFSET 0xa88 -#define GC_USB_DIEPINT12_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT12_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT12_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT12_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT12_TXFIFOUNDRN_OFFSET 0xa88 -#define GC_USB_DIEPINT12_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT12_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT12_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT12_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT12_BNAINTR_OFFSET 0xa88 -#define GC_USB_DIEPINT12_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT12_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT12_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT12_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT12_PKTDRPSTS_OFFSET 0xa88 -#define GC_USB_DIEPINT12_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT12_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT12_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT12_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT12_BBLEERR_OFFSET 0xa88 -#define GC_USB_DIEPINT12_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT12_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT12_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT12_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT12_NAKINTRPT_OFFSET 0xa88 -#define GC_USB_DIEPINT12_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT12_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT12_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT12_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT12_NYETINTRPT_OFFSET 0xa88 -#define GC_USB_DIEPTSIZ12_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ12_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ12_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ12_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ12_XFERSIZE_OFFSET 0xa90 -#define GC_USB_DIEPTSIZ12_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ12_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ12_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ12_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ12_PKTCNT_OFFSET 0xa90 -#define GC_USB_DIEPTSIZ12_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ12_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ12_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ12_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ12_MC_OFFSET 0xa90 -#define GC_USB_DIEPDMA12_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA12_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA12_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA12_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA12_DMAADDR_OFFSET 0xa94 -#define GC_USB_DTXFSTS12_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS12_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS12_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS11_INEPTXFSPCAVAIL_OFFSET 0xa78 +#define GC_USB_DIEPDMAB11_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB11_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB11_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB11_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB11_DMABUFFERADDR_OFFSET 0xa7c +#define GC_USB_DIEPCTL12_MPS_LSB 0x0 +#define GC_USB_DIEPCTL12_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL12_MPS_SIZE 0xb +#define GC_USB_DIEPCTL12_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_MPS_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL12_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL12_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL12_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_USBACTEP_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_DPID_LSB 0x10 +#define GC_USB_DIEPCTL12_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL12_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL12_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_DPID_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL12_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL12_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL12_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_NAKSTS_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL12_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL12_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL12_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_EPTYPE_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_STALL_LSB 0x15 +#define GC_USB_DIEPCTL12_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL12_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL12_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_STALL_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL12_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL12_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL12_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_TXFNUM_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL12_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL12_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL12_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_CNAK_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL12_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL12_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL12_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_SNAK_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL12_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL12_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL12_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_SETD0PID_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL12_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL12_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL12_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_SETD1PID_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL12_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL12_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL12_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_EPDIS_OFFSET 0xa80 +#define GC_USB_DIEPCTL12_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL12_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL12_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL12_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL12_EPENA_OFFSET 0xa80 +#define GC_USB_DIEPINT12_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT12_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT12_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT12_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT12_XFERCOMPL_OFFSET 0xa88 +#define GC_USB_DIEPINT12_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT12_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT12_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT12_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT12_EPDISBLD_OFFSET 0xa88 +#define GC_USB_DIEPINT12_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT12_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT12_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT12_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT12_AHBERR_OFFSET 0xa88 +#define GC_USB_DIEPINT12_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT12_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT12_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT12_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT12_TIMEOUT_OFFSET 0xa88 +#define GC_USB_DIEPINT12_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT12_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT12_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT12_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT12_INTKNTXFEMP_OFFSET 0xa88 +#define GC_USB_DIEPINT12_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT12_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT12_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT12_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT12_INTKNEPMIS_OFFSET 0xa88 +#define GC_USB_DIEPINT12_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT12_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT12_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT12_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT12_INEPNAKEFF_OFFSET 0xa88 +#define GC_USB_DIEPINT12_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT12_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT12_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT12_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT12_TXFEMP_OFFSET 0xa88 +#define GC_USB_DIEPINT12_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT12_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT12_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT12_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT12_TXFIFOUNDRN_OFFSET 0xa88 +#define GC_USB_DIEPINT12_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT12_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT12_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT12_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT12_BNAINTR_OFFSET 0xa88 +#define GC_USB_DIEPINT12_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT12_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT12_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT12_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT12_PKTDRPSTS_OFFSET 0xa88 +#define GC_USB_DIEPINT12_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT12_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT12_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT12_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT12_BBLEERR_OFFSET 0xa88 +#define GC_USB_DIEPINT12_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT12_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT12_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT12_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT12_NAKINTRPT_OFFSET 0xa88 +#define GC_USB_DIEPINT12_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT12_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT12_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT12_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT12_NYETINTRPT_OFFSET 0xa88 +#define GC_USB_DIEPTSIZ12_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ12_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ12_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ12_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ12_XFERSIZE_OFFSET 0xa90 +#define GC_USB_DIEPTSIZ12_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ12_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ12_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ12_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ12_PKTCNT_OFFSET 0xa90 +#define GC_USB_DIEPTSIZ12_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ12_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ12_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ12_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ12_MC_OFFSET 0xa90 +#define GC_USB_DIEPDMA12_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA12_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA12_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA12_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA12_DMAADDR_OFFSET 0xa94 +#define GC_USB_DTXFSTS12_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS12_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS12_INEPTXFSPCAVAIL_SIZE 0x10 #define GC_USB_DTXFSTS12_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS12_INEPTXFSPCAVAIL_OFFSET 0xa98 -#define GC_USB_DIEPDMAB12_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB12_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB12_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB12_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB12_DMABUFFERADDR_OFFSET 0xa9c -#define GC_USB_DIEPCTL13_MPS_LSB 0x0 -#define GC_USB_DIEPCTL13_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL13_MPS_SIZE 0xb -#define GC_USB_DIEPCTL13_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_MPS_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL13_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL13_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL13_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_USBACTEP_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_DPID_LSB 0x10 -#define GC_USB_DIEPCTL13_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL13_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL13_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_DPID_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL13_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL13_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL13_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_NAKSTS_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL13_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL13_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL13_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_EPTYPE_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_STALL_LSB 0x15 -#define GC_USB_DIEPCTL13_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL13_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL13_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_STALL_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL13_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL13_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL13_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_TXFNUM_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL13_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL13_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL13_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_CNAK_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL13_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL13_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL13_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_SNAK_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL13_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL13_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL13_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_SETD0PID_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL13_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL13_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL13_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_SETD1PID_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL13_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL13_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL13_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_EPDIS_OFFSET 0xaa0 -#define GC_USB_DIEPCTL13_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL13_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL13_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL13_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL13_EPENA_OFFSET 0xaa0 -#define GC_USB_DIEPINT13_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT13_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT13_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT13_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT13_XFERCOMPL_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT13_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT13_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT13_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT13_EPDISBLD_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT13_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT13_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT13_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT13_AHBERR_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT13_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT13_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT13_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT13_TIMEOUT_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT13_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT13_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT13_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT13_INTKNTXFEMP_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT13_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT13_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT13_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT13_INTKNEPMIS_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT13_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT13_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT13_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT13_INEPNAKEFF_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT13_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT13_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT13_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT13_TXFEMP_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT13_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT13_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT13_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT13_TXFIFOUNDRN_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT13_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT13_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT13_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT13_BNAINTR_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT13_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT13_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT13_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT13_PKTDRPSTS_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT13_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT13_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT13_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT13_BBLEERR_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT13_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT13_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT13_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT13_NAKINTRPT_OFFSET 0xaa8 -#define GC_USB_DIEPINT13_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT13_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT13_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT13_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT13_NYETINTRPT_OFFSET 0xaa8 -#define GC_USB_DIEPTSIZ13_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ13_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ13_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ13_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ13_XFERSIZE_OFFSET 0xab0 -#define GC_USB_DIEPTSIZ13_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ13_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ13_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ13_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ13_PKTCNT_OFFSET 0xab0 -#define GC_USB_DIEPTSIZ13_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ13_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ13_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ13_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ13_MC_OFFSET 0xab0 -#define GC_USB_DIEPDMA13_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA13_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA13_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA13_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA13_DMAADDR_OFFSET 0xab4 -#define GC_USB_DTXFSTS13_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS13_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS13_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS12_INEPTXFSPCAVAIL_OFFSET 0xa98 +#define GC_USB_DIEPDMAB12_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB12_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB12_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB12_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB12_DMABUFFERADDR_OFFSET 0xa9c +#define GC_USB_DIEPCTL13_MPS_LSB 0x0 +#define GC_USB_DIEPCTL13_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL13_MPS_SIZE 0xb +#define GC_USB_DIEPCTL13_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_MPS_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL13_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL13_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL13_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_USBACTEP_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_DPID_LSB 0x10 +#define GC_USB_DIEPCTL13_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL13_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL13_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_DPID_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL13_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL13_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL13_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_NAKSTS_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL13_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL13_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL13_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_EPTYPE_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_STALL_LSB 0x15 +#define GC_USB_DIEPCTL13_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL13_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL13_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_STALL_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL13_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL13_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL13_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_TXFNUM_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL13_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL13_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL13_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_CNAK_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL13_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL13_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL13_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_SNAK_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL13_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL13_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL13_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_SETD0PID_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL13_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL13_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL13_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_SETD1PID_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL13_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL13_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL13_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_EPDIS_OFFSET 0xaa0 +#define GC_USB_DIEPCTL13_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL13_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL13_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL13_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL13_EPENA_OFFSET 0xaa0 +#define GC_USB_DIEPINT13_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT13_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT13_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT13_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT13_XFERCOMPL_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT13_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT13_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT13_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT13_EPDISBLD_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT13_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT13_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT13_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT13_AHBERR_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT13_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT13_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT13_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT13_TIMEOUT_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT13_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT13_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT13_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT13_INTKNTXFEMP_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT13_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT13_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT13_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT13_INTKNEPMIS_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT13_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT13_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT13_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT13_INEPNAKEFF_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT13_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT13_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT13_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT13_TXFEMP_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT13_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT13_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT13_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT13_TXFIFOUNDRN_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT13_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT13_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT13_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT13_BNAINTR_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT13_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT13_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT13_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT13_PKTDRPSTS_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT13_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT13_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT13_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT13_BBLEERR_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT13_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT13_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT13_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT13_NAKINTRPT_OFFSET 0xaa8 +#define GC_USB_DIEPINT13_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT13_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT13_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT13_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT13_NYETINTRPT_OFFSET 0xaa8 +#define GC_USB_DIEPTSIZ13_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ13_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ13_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ13_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ13_XFERSIZE_OFFSET 0xab0 +#define GC_USB_DIEPTSIZ13_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ13_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ13_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ13_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ13_PKTCNT_OFFSET 0xab0 +#define GC_USB_DIEPTSIZ13_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ13_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ13_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ13_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ13_MC_OFFSET 0xab0 +#define GC_USB_DIEPDMA13_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA13_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA13_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA13_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA13_DMAADDR_OFFSET 0xab4 +#define GC_USB_DTXFSTS13_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS13_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS13_INEPTXFSPCAVAIL_SIZE 0x10 #define GC_USB_DTXFSTS13_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS13_INEPTXFSPCAVAIL_OFFSET 0xab8 -#define GC_USB_DIEPDMAB13_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB13_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB13_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB13_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB13_DMABUFFERADDR_OFFSET 0xabc -#define GC_USB_DIEPCTL14_MPS_LSB 0x0 -#define GC_USB_DIEPCTL14_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL14_MPS_SIZE 0xb -#define GC_USB_DIEPCTL14_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_MPS_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL14_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL14_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL14_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_USBACTEP_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_DPID_LSB 0x10 -#define GC_USB_DIEPCTL14_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL14_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL14_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_DPID_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL14_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL14_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL14_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_NAKSTS_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL14_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL14_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL14_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_EPTYPE_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_STALL_LSB 0x15 -#define GC_USB_DIEPCTL14_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL14_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL14_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_STALL_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL14_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL14_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL14_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_TXFNUM_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL14_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL14_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL14_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_CNAK_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL14_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL14_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL14_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_SNAK_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL14_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL14_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL14_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_SETD0PID_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL14_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL14_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL14_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_SETD1PID_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL14_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL14_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL14_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_EPDIS_OFFSET 0xac0 -#define GC_USB_DIEPCTL14_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL14_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL14_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL14_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL14_EPENA_OFFSET 0xac0 -#define GC_USB_DIEPINT14_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT14_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT14_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT14_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT14_XFERCOMPL_OFFSET 0xac8 -#define GC_USB_DIEPINT14_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT14_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT14_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT14_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT14_EPDISBLD_OFFSET 0xac8 -#define GC_USB_DIEPINT14_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT14_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT14_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT14_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT14_AHBERR_OFFSET 0xac8 -#define GC_USB_DIEPINT14_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT14_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT14_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT14_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT14_TIMEOUT_OFFSET 0xac8 -#define GC_USB_DIEPINT14_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT14_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT14_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT14_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT14_INTKNTXFEMP_OFFSET 0xac8 -#define GC_USB_DIEPINT14_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT14_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT14_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT14_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT14_INTKNEPMIS_OFFSET 0xac8 -#define GC_USB_DIEPINT14_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT14_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT14_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT14_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT14_INEPNAKEFF_OFFSET 0xac8 -#define GC_USB_DIEPINT14_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT14_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT14_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT14_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT14_TXFEMP_OFFSET 0xac8 -#define GC_USB_DIEPINT14_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT14_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT14_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT14_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT14_TXFIFOUNDRN_OFFSET 0xac8 -#define GC_USB_DIEPINT14_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT14_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT14_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT14_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT14_BNAINTR_OFFSET 0xac8 -#define GC_USB_DIEPINT14_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT14_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT14_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT14_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT14_PKTDRPSTS_OFFSET 0xac8 -#define GC_USB_DIEPINT14_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT14_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT14_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT14_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT14_BBLEERR_OFFSET 0xac8 -#define GC_USB_DIEPINT14_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT14_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT14_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT14_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT14_NAKINTRPT_OFFSET 0xac8 -#define GC_USB_DIEPINT14_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT14_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT14_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT14_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT14_NYETINTRPT_OFFSET 0xac8 -#define GC_USB_DIEPTSIZ14_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ14_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ14_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ14_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ14_XFERSIZE_OFFSET 0xad0 -#define GC_USB_DIEPTSIZ14_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ14_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ14_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ14_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ14_PKTCNT_OFFSET 0xad0 -#define GC_USB_DIEPTSIZ14_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ14_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ14_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ14_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ14_MC_OFFSET 0xad0 -#define GC_USB_DIEPDMA14_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA14_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA14_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA14_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA14_DMAADDR_OFFSET 0xad4 -#define GC_USB_DTXFSTS14_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS14_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS14_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS13_INEPTXFSPCAVAIL_OFFSET 0xab8 +#define GC_USB_DIEPDMAB13_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB13_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB13_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB13_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB13_DMABUFFERADDR_OFFSET 0xabc +#define GC_USB_DIEPCTL14_MPS_LSB 0x0 +#define GC_USB_DIEPCTL14_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL14_MPS_SIZE 0xb +#define GC_USB_DIEPCTL14_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_MPS_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL14_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL14_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL14_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_USBACTEP_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_DPID_LSB 0x10 +#define GC_USB_DIEPCTL14_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL14_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL14_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_DPID_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL14_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL14_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL14_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_NAKSTS_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL14_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL14_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL14_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_EPTYPE_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_STALL_LSB 0x15 +#define GC_USB_DIEPCTL14_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL14_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL14_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_STALL_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL14_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL14_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL14_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_TXFNUM_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL14_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL14_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL14_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_CNAK_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL14_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL14_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL14_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_SNAK_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL14_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL14_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL14_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_SETD0PID_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL14_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL14_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL14_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_SETD1PID_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL14_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL14_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL14_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_EPDIS_OFFSET 0xac0 +#define GC_USB_DIEPCTL14_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL14_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL14_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL14_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL14_EPENA_OFFSET 0xac0 +#define GC_USB_DIEPINT14_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT14_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT14_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT14_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT14_XFERCOMPL_OFFSET 0xac8 +#define GC_USB_DIEPINT14_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT14_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT14_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT14_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT14_EPDISBLD_OFFSET 0xac8 +#define GC_USB_DIEPINT14_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT14_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT14_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT14_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT14_AHBERR_OFFSET 0xac8 +#define GC_USB_DIEPINT14_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT14_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT14_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT14_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT14_TIMEOUT_OFFSET 0xac8 +#define GC_USB_DIEPINT14_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT14_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT14_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT14_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT14_INTKNTXFEMP_OFFSET 0xac8 +#define GC_USB_DIEPINT14_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT14_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT14_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT14_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT14_INTKNEPMIS_OFFSET 0xac8 +#define GC_USB_DIEPINT14_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT14_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT14_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT14_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT14_INEPNAKEFF_OFFSET 0xac8 +#define GC_USB_DIEPINT14_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT14_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT14_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT14_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT14_TXFEMP_OFFSET 0xac8 +#define GC_USB_DIEPINT14_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT14_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT14_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT14_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT14_TXFIFOUNDRN_OFFSET 0xac8 +#define GC_USB_DIEPINT14_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT14_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT14_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT14_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT14_BNAINTR_OFFSET 0xac8 +#define GC_USB_DIEPINT14_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT14_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT14_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT14_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT14_PKTDRPSTS_OFFSET 0xac8 +#define GC_USB_DIEPINT14_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT14_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT14_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT14_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT14_BBLEERR_OFFSET 0xac8 +#define GC_USB_DIEPINT14_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT14_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT14_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT14_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT14_NAKINTRPT_OFFSET 0xac8 +#define GC_USB_DIEPINT14_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT14_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT14_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT14_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT14_NYETINTRPT_OFFSET 0xac8 +#define GC_USB_DIEPTSIZ14_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ14_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ14_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ14_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ14_XFERSIZE_OFFSET 0xad0 +#define GC_USB_DIEPTSIZ14_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ14_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ14_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ14_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ14_PKTCNT_OFFSET 0xad0 +#define GC_USB_DIEPTSIZ14_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ14_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ14_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ14_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ14_MC_OFFSET 0xad0 +#define GC_USB_DIEPDMA14_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA14_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA14_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA14_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA14_DMAADDR_OFFSET 0xad4 +#define GC_USB_DTXFSTS14_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS14_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS14_INEPTXFSPCAVAIL_SIZE 0x10 #define GC_USB_DTXFSTS14_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS14_INEPTXFSPCAVAIL_OFFSET 0xad8 -#define GC_USB_DIEPDMAB14_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB14_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB14_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB14_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB14_DMABUFFERADDR_OFFSET 0xadc -#define GC_USB_DIEPCTL15_MPS_LSB 0x0 -#define GC_USB_DIEPCTL15_MPS_MASK 0x7ff -#define GC_USB_DIEPCTL15_MPS_SIZE 0xb -#define GC_USB_DIEPCTL15_MPS_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_MPS_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_USBACTEP_LSB 0xf -#define GC_USB_DIEPCTL15_USBACTEP_MASK 0x8000 -#define GC_USB_DIEPCTL15_USBACTEP_SIZE 0x1 -#define GC_USB_DIEPCTL15_USBACTEP_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_USBACTEP_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_DPID_LSB 0x10 -#define GC_USB_DIEPCTL15_DPID_MASK 0x10000 -#define GC_USB_DIEPCTL15_DPID_SIZE 0x1 -#define GC_USB_DIEPCTL15_DPID_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_DPID_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_NAKSTS_LSB 0x11 -#define GC_USB_DIEPCTL15_NAKSTS_MASK 0x20000 -#define GC_USB_DIEPCTL15_NAKSTS_SIZE 0x1 -#define GC_USB_DIEPCTL15_NAKSTS_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_NAKSTS_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_EPTYPE_LSB 0x12 -#define GC_USB_DIEPCTL15_EPTYPE_MASK 0xc0000 -#define GC_USB_DIEPCTL15_EPTYPE_SIZE 0x2 -#define GC_USB_DIEPCTL15_EPTYPE_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_EPTYPE_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_STALL_LSB 0x15 -#define GC_USB_DIEPCTL15_STALL_MASK 0x200000 -#define GC_USB_DIEPCTL15_STALL_SIZE 0x1 -#define GC_USB_DIEPCTL15_STALL_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_STALL_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_TXFNUM_LSB 0x16 -#define GC_USB_DIEPCTL15_TXFNUM_MASK 0x3c00000 -#define GC_USB_DIEPCTL15_TXFNUM_SIZE 0x4 -#define GC_USB_DIEPCTL15_TXFNUM_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_TXFNUM_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_CNAK_LSB 0x1a -#define GC_USB_DIEPCTL15_CNAK_MASK 0x4000000 -#define GC_USB_DIEPCTL15_CNAK_SIZE 0x1 -#define GC_USB_DIEPCTL15_CNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_CNAK_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_SNAK_LSB 0x1b -#define GC_USB_DIEPCTL15_SNAK_MASK 0x8000000 -#define GC_USB_DIEPCTL15_SNAK_SIZE 0x1 -#define GC_USB_DIEPCTL15_SNAK_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_SNAK_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_SETD0PID_LSB 0x1c -#define GC_USB_DIEPCTL15_SETD0PID_MASK 0x10000000 -#define GC_USB_DIEPCTL15_SETD0PID_SIZE 0x1 -#define GC_USB_DIEPCTL15_SETD0PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_SETD0PID_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_SETD1PID_LSB 0x1d -#define GC_USB_DIEPCTL15_SETD1PID_MASK 0x20000000 -#define GC_USB_DIEPCTL15_SETD1PID_SIZE 0x1 -#define GC_USB_DIEPCTL15_SETD1PID_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_SETD1PID_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_EPDIS_LSB 0x1e -#define GC_USB_DIEPCTL15_EPDIS_MASK 0x40000000 -#define GC_USB_DIEPCTL15_EPDIS_SIZE 0x1 -#define GC_USB_DIEPCTL15_EPDIS_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_EPDIS_OFFSET 0xae0 -#define GC_USB_DIEPCTL15_EPENA_LSB 0x1f -#define GC_USB_DIEPCTL15_EPENA_MASK 0x80000000 -#define GC_USB_DIEPCTL15_EPENA_SIZE 0x1 -#define GC_USB_DIEPCTL15_EPENA_DEFAULT 0x0 -#define GC_USB_DIEPCTL15_EPENA_OFFSET 0xae0 -#define GC_USB_DIEPINT15_XFERCOMPL_LSB 0x0 -#define GC_USB_DIEPINT15_XFERCOMPL_MASK 0x1 -#define GC_USB_DIEPINT15_XFERCOMPL_SIZE 0x1 -#define GC_USB_DIEPINT15_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DIEPINT15_XFERCOMPL_OFFSET 0xae8 -#define GC_USB_DIEPINT15_EPDISBLD_LSB 0x1 -#define GC_USB_DIEPINT15_EPDISBLD_MASK 0x2 -#define GC_USB_DIEPINT15_EPDISBLD_SIZE 0x1 -#define GC_USB_DIEPINT15_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DIEPINT15_EPDISBLD_OFFSET 0xae8 -#define GC_USB_DIEPINT15_AHBERR_LSB 0x2 -#define GC_USB_DIEPINT15_AHBERR_MASK 0x4 -#define GC_USB_DIEPINT15_AHBERR_SIZE 0x1 -#define GC_USB_DIEPINT15_AHBERR_DEFAULT 0x0 -#define GC_USB_DIEPINT15_AHBERR_OFFSET 0xae8 -#define GC_USB_DIEPINT15_TIMEOUT_LSB 0x3 -#define GC_USB_DIEPINT15_TIMEOUT_MASK 0x8 -#define GC_USB_DIEPINT15_TIMEOUT_SIZE 0x1 -#define GC_USB_DIEPINT15_TIMEOUT_DEFAULT 0x0 -#define GC_USB_DIEPINT15_TIMEOUT_OFFSET 0xae8 -#define GC_USB_DIEPINT15_INTKNTXFEMP_LSB 0x4 -#define GC_USB_DIEPINT15_INTKNTXFEMP_MASK 0x10 -#define GC_USB_DIEPINT15_INTKNTXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT15_INTKNTXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT15_INTKNTXFEMP_OFFSET 0xae8 -#define GC_USB_DIEPINT15_INTKNEPMIS_LSB 0x5 -#define GC_USB_DIEPINT15_INTKNEPMIS_MASK 0x20 -#define GC_USB_DIEPINT15_INTKNEPMIS_SIZE 0x1 -#define GC_USB_DIEPINT15_INTKNEPMIS_DEFAULT 0x0 -#define GC_USB_DIEPINT15_INTKNEPMIS_OFFSET 0xae8 -#define GC_USB_DIEPINT15_INEPNAKEFF_LSB 0x6 -#define GC_USB_DIEPINT15_INEPNAKEFF_MASK 0x40 -#define GC_USB_DIEPINT15_INEPNAKEFF_SIZE 0x1 -#define GC_USB_DIEPINT15_INEPNAKEFF_DEFAULT 0x0 -#define GC_USB_DIEPINT15_INEPNAKEFF_OFFSET 0xae8 -#define GC_USB_DIEPINT15_TXFEMP_LSB 0x7 -#define GC_USB_DIEPINT15_TXFEMP_MASK 0x80 -#define GC_USB_DIEPINT15_TXFEMP_SIZE 0x1 -#define GC_USB_DIEPINT15_TXFEMP_DEFAULT 0x0 -#define GC_USB_DIEPINT15_TXFEMP_OFFSET 0xae8 -#define GC_USB_DIEPINT15_TXFIFOUNDRN_LSB 0x8 -#define GC_USB_DIEPINT15_TXFIFOUNDRN_MASK 0x100 -#define GC_USB_DIEPINT15_TXFIFOUNDRN_SIZE 0x1 -#define GC_USB_DIEPINT15_TXFIFOUNDRN_DEFAULT 0x0 -#define GC_USB_DIEPINT15_TXFIFOUNDRN_OFFSET 0xae8 -#define GC_USB_DIEPINT15_BNAINTR_LSB 0x9 -#define GC_USB_DIEPINT15_BNAINTR_MASK 0x200 -#define GC_USB_DIEPINT15_BNAINTR_SIZE 0x1 -#define GC_USB_DIEPINT15_BNAINTR_DEFAULT 0x0 -#define GC_USB_DIEPINT15_BNAINTR_OFFSET 0xae8 -#define GC_USB_DIEPINT15_PKTDRPSTS_LSB 0xb -#define GC_USB_DIEPINT15_PKTDRPSTS_MASK 0x800 -#define GC_USB_DIEPINT15_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DIEPINT15_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DIEPINT15_PKTDRPSTS_OFFSET 0xae8 -#define GC_USB_DIEPINT15_BBLEERR_LSB 0xc -#define GC_USB_DIEPINT15_BBLEERR_MASK 0x1000 -#define GC_USB_DIEPINT15_BBLEERR_SIZE 0x1 -#define GC_USB_DIEPINT15_BBLEERR_DEFAULT 0x0 -#define GC_USB_DIEPINT15_BBLEERR_OFFSET 0xae8 -#define GC_USB_DIEPINT15_NAKINTRPT_LSB 0xd -#define GC_USB_DIEPINT15_NAKINTRPT_MASK 0x2000 -#define GC_USB_DIEPINT15_NAKINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT15_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT15_NAKINTRPT_OFFSET 0xae8 -#define GC_USB_DIEPINT15_NYETINTRPT_LSB 0xe -#define GC_USB_DIEPINT15_NYETINTRPT_MASK 0x4000 -#define GC_USB_DIEPINT15_NYETINTRPT_SIZE 0x1 -#define GC_USB_DIEPINT15_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DIEPINT15_NYETINTRPT_OFFSET 0xae8 -#define GC_USB_DIEPTSIZ15_XFERSIZE_LSB 0x0 -#define GC_USB_DIEPTSIZ15_XFERSIZE_MASK 0x7ffff -#define GC_USB_DIEPTSIZ15_XFERSIZE_SIZE 0x13 -#define GC_USB_DIEPTSIZ15_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ15_XFERSIZE_OFFSET 0xaf0 -#define GC_USB_DIEPTSIZ15_PKTCNT_LSB 0x13 -#define GC_USB_DIEPTSIZ15_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DIEPTSIZ15_PKTCNT_SIZE 0xa -#define GC_USB_DIEPTSIZ15_PKTCNT_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ15_PKTCNT_OFFSET 0xaf0 -#define GC_USB_DIEPTSIZ15_MC_LSB 0x1d -#define GC_USB_DIEPTSIZ15_MC_MASK 0x60000000 -#define GC_USB_DIEPTSIZ15_MC_SIZE 0x2 -#define GC_USB_DIEPTSIZ15_MC_DEFAULT 0x0 -#define GC_USB_DIEPTSIZ15_MC_OFFSET 0xaf0 -#define GC_USB_DIEPDMA15_DMAADDR_LSB 0x0 -#define GC_USB_DIEPDMA15_DMAADDR_MASK 0xffffffff -#define GC_USB_DIEPDMA15_DMAADDR_SIZE 0x20 -#define GC_USB_DIEPDMA15_DMAADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMA15_DMAADDR_OFFSET 0xaf4 -#define GC_USB_DTXFSTS15_INEPTXFSPCAVAIL_LSB 0x0 -#define GC_USB_DTXFSTS15_INEPTXFSPCAVAIL_MASK 0xffff -#define GC_USB_DTXFSTS15_INEPTXFSPCAVAIL_SIZE 0x10 +#define GC_USB_DTXFSTS14_INEPTXFSPCAVAIL_OFFSET 0xad8 +#define GC_USB_DIEPDMAB14_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB14_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB14_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB14_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB14_DMABUFFERADDR_OFFSET 0xadc +#define GC_USB_DIEPCTL15_MPS_LSB 0x0 +#define GC_USB_DIEPCTL15_MPS_MASK 0x7ff +#define GC_USB_DIEPCTL15_MPS_SIZE 0xb +#define GC_USB_DIEPCTL15_MPS_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_MPS_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_USBACTEP_LSB 0xf +#define GC_USB_DIEPCTL15_USBACTEP_MASK 0x8000 +#define GC_USB_DIEPCTL15_USBACTEP_SIZE 0x1 +#define GC_USB_DIEPCTL15_USBACTEP_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_USBACTEP_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_DPID_LSB 0x10 +#define GC_USB_DIEPCTL15_DPID_MASK 0x10000 +#define GC_USB_DIEPCTL15_DPID_SIZE 0x1 +#define GC_USB_DIEPCTL15_DPID_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_DPID_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_NAKSTS_LSB 0x11 +#define GC_USB_DIEPCTL15_NAKSTS_MASK 0x20000 +#define GC_USB_DIEPCTL15_NAKSTS_SIZE 0x1 +#define GC_USB_DIEPCTL15_NAKSTS_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_NAKSTS_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_EPTYPE_LSB 0x12 +#define GC_USB_DIEPCTL15_EPTYPE_MASK 0xc0000 +#define GC_USB_DIEPCTL15_EPTYPE_SIZE 0x2 +#define GC_USB_DIEPCTL15_EPTYPE_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_EPTYPE_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_STALL_LSB 0x15 +#define GC_USB_DIEPCTL15_STALL_MASK 0x200000 +#define GC_USB_DIEPCTL15_STALL_SIZE 0x1 +#define GC_USB_DIEPCTL15_STALL_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_STALL_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_TXFNUM_LSB 0x16 +#define GC_USB_DIEPCTL15_TXFNUM_MASK 0x3c00000 +#define GC_USB_DIEPCTL15_TXFNUM_SIZE 0x4 +#define GC_USB_DIEPCTL15_TXFNUM_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_TXFNUM_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_CNAK_LSB 0x1a +#define GC_USB_DIEPCTL15_CNAK_MASK 0x4000000 +#define GC_USB_DIEPCTL15_CNAK_SIZE 0x1 +#define GC_USB_DIEPCTL15_CNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_CNAK_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_SNAK_LSB 0x1b +#define GC_USB_DIEPCTL15_SNAK_MASK 0x8000000 +#define GC_USB_DIEPCTL15_SNAK_SIZE 0x1 +#define GC_USB_DIEPCTL15_SNAK_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_SNAK_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_SETD0PID_LSB 0x1c +#define GC_USB_DIEPCTL15_SETD0PID_MASK 0x10000000 +#define GC_USB_DIEPCTL15_SETD0PID_SIZE 0x1 +#define GC_USB_DIEPCTL15_SETD0PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_SETD0PID_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_SETD1PID_LSB 0x1d +#define GC_USB_DIEPCTL15_SETD1PID_MASK 0x20000000 +#define GC_USB_DIEPCTL15_SETD1PID_SIZE 0x1 +#define GC_USB_DIEPCTL15_SETD1PID_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_SETD1PID_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_EPDIS_LSB 0x1e +#define GC_USB_DIEPCTL15_EPDIS_MASK 0x40000000 +#define GC_USB_DIEPCTL15_EPDIS_SIZE 0x1 +#define GC_USB_DIEPCTL15_EPDIS_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_EPDIS_OFFSET 0xae0 +#define GC_USB_DIEPCTL15_EPENA_LSB 0x1f +#define GC_USB_DIEPCTL15_EPENA_MASK 0x80000000 +#define GC_USB_DIEPCTL15_EPENA_SIZE 0x1 +#define GC_USB_DIEPCTL15_EPENA_DEFAULT 0x0 +#define GC_USB_DIEPCTL15_EPENA_OFFSET 0xae0 +#define GC_USB_DIEPINT15_XFERCOMPL_LSB 0x0 +#define GC_USB_DIEPINT15_XFERCOMPL_MASK 0x1 +#define GC_USB_DIEPINT15_XFERCOMPL_SIZE 0x1 +#define GC_USB_DIEPINT15_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DIEPINT15_XFERCOMPL_OFFSET 0xae8 +#define GC_USB_DIEPINT15_EPDISBLD_LSB 0x1 +#define GC_USB_DIEPINT15_EPDISBLD_MASK 0x2 +#define GC_USB_DIEPINT15_EPDISBLD_SIZE 0x1 +#define GC_USB_DIEPINT15_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DIEPINT15_EPDISBLD_OFFSET 0xae8 +#define GC_USB_DIEPINT15_AHBERR_LSB 0x2 +#define GC_USB_DIEPINT15_AHBERR_MASK 0x4 +#define GC_USB_DIEPINT15_AHBERR_SIZE 0x1 +#define GC_USB_DIEPINT15_AHBERR_DEFAULT 0x0 +#define GC_USB_DIEPINT15_AHBERR_OFFSET 0xae8 +#define GC_USB_DIEPINT15_TIMEOUT_LSB 0x3 +#define GC_USB_DIEPINT15_TIMEOUT_MASK 0x8 +#define GC_USB_DIEPINT15_TIMEOUT_SIZE 0x1 +#define GC_USB_DIEPINT15_TIMEOUT_DEFAULT 0x0 +#define GC_USB_DIEPINT15_TIMEOUT_OFFSET 0xae8 +#define GC_USB_DIEPINT15_INTKNTXFEMP_LSB 0x4 +#define GC_USB_DIEPINT15_INTKNTXFEMP_MASK 0x10 +#define GC_USB_DIEPINT15_INTKNTXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT15_INTKNTXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT15_INTKNTXFEMP_OFFSET 0xae8 +#define GC_USB_DIEPINT15_INTKNEPMIS_LSB 0x5 +#define GC_USB_DIEPINT15_INTKNEPMIS_MASK 0x20 +#define GC_USB_DIEPINT15_INTKNEPMIS_SIZE 0x1 +#define GC_USB_DIEPINT15_INTKNEPMIS_DEFAULT 0x0 +#define GC_USB_DIEPINT15_INTKNEPMIS_OFFSET 0xae8 +#define GC_USB_DIEPINT15_INEPNAKEFF_LSB 0x6 +#define GC_USB_DIEPINT15_INEPNAKEFF_MASK 0x40 +#define GC_USB_DIEPINT15_INEPNAKEFF_SIZE 0x1 +#define GC_USB_DIEPINT15_INEPNAKEFF_DEFAULT 0x0 +#define GC_USB_DIEPINT15_INEPNAKEFF_OFFSET 0xae8 +#define GC_USB_DIEPINT15_TXFEMP_LSB 0x7 +#define GC_USB_DIEPINT15_TXFEMP_MASK 0x80 +#define GC_USB_DIEPINT15_TXFEMP_SIZE 0x1 +#define GC_USB_DIEPINT15_TXFEMP_DEFAULT 0x0 +#define GC_USB_DIEPINT15_TXFEMP_OFFSET 0xae8 +#define GC_USB_DIEPINT15_TXFIFOUNDRN_LSB 0x8 +#define GC_USB_DIEPINT15_TXFIFOUNDRN_MASK 0x100 +#define GC_USB_DIEPINT15_TXFIFOUNDRN_SIZE 0x1 +#define GC_USB_DIEPINT15_TXFIFOUNDRN_DEFAULT 0x0 +#define GC_USB_DIEPINT15_TXFIFOUNDRN_OFFSET 0xae8 +#define GC_USB_DIEPINT15_BNAINTR_LSB 0x9 +#define GC_USB_DIEPINT15_BNAINTR_MASK 0x200 +#define GC_USB_DIEPINT15_BNAINTR_SIZE 0x1 +#define GC_USB_DIEPINT15_BNAINTR_DEFAULT 0x0 +#define GC_USB_DIEPINT15_BNAINTR_OFFSET 0xae8 +#define GC_USB_DIEPINT15_PKTDRPSTS_LSB 0xb +#define GC_USB_DIEPINT15_PKTDRPSTS_MASK 0x800 +#define GC_USB_DIEPINT15_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DIEPINT15_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DIEPINT15_PKTDRPSTS_OFFSET 0xae8 +#define GC_USB_DIEPINT15_BBLEERR_LSB 0xc +#define GC_USB_DIEPINT15_BBLEERR_MASK 0x1000 +#define GC_USB_DIEPINT15_BBLEERR_SIZE 0x1 +#define GC_USB_DIEPINT15_BBLEERR_DEFAULT 0x0 +#define GC_USB_DIEPINT15_BBLEERR_OFFSET 0xae8 +#define GC_USB_DIEPINT15_NAKINTRPT_LSB 0xd +#define GC_USB_DIEPINT15_NAKINTRPT_MASK 0x2000 +#define GC_USB_DIEPINT15_NAKINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT15_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT15_NAKINTRPT_OFFSET 0xae8 +#define GC_USB_DIEPINT15_NYETINTRPT_LSB 0xe +#define GC_USB_DIEPINT15_NYETINTRPT_MASK 0x4000 +#define GC_USB_DIEPINT15_NYETINTRPT_SIZE 0x1 +#define GC_USB_DIEPINT15_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DIEPINT15_NYETINTRPT_OFFSET 0xae8 +#define GC_USB_DIEPTSIZ15_XFERSIZE_LSB 0x0 +#define GC_USB_DIEPTSIZ15_XFERSIZE_MASK 0x7ffff +#define GC_USB_DIEPTSIZ15_XFERSIZE_SIZE 0x13 +#define GC_USB_DIEPTSIZ15_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ15_XFERSIZE_OFFSET 0xaf0 +#define GC_USB_DIEPTSIZ15_PKTCNT_LSB 0x13 +#define GC_USB_DIEPTSIZ15_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DIEPTSIZ15_PKTCNT_SIZE 0xa +#define GC_USB_DIEPTSIZ15_PKTCNT_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ15_PKTCNT_OFFSET 0xaf0 +#define GC_USB_DIEPTSIZ15_MC_LSB 0x1d +#define GC_USB_DIEPTSIZ15_MC_MASK 0x60000000 +#define GC_USB_DIEPTSIZ15_MC_SIZE 0x2 +#define GC_USB_DIEPTSIZ15_MC_DEFAULT 0x0 +#define GC_USB_DIEPTSIZ15_MC_OFFSET 0xaf0 +#define GC_USB_DIEPDMA15_DMAADDR_LSB 0x0 +#define GC_USB_DIEPDMA15_DMAADDR_MASK 0xffffffff +#define GC_USB_DIEPDMA15_DMAADDR_SIZE 0x20 +#define GC_USB_DIEPDMA15_DMAADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMA15_DMAADDR_OFFSET 0xaf4 +#define GC_USB_DTXFSTS15_INEPTXFSPCAVAIL_LSB 0x0 +#define GC_USB_DTXFSTS15_INEPTXFSPCAVAIL_MASK 0xffff +#define GC_USB_DTXFSTS15_INEPTXFSPCAVAIL_SIZE 0x10 #define GC_USB_DTXFSTS15_INEPTXFSPCAVAIL_DEFAULT 0x0 -#define GC_USB_DTXFSTS15_INEPTXFSPCAVAIL_OFFSET 0xaf8 -#define GC_USB_DIEPDMAB15_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DIEPDMAB15_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DIEPDMAB15_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DIEPDMAB15_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DIEPDMAB15_DMABUFFERADDR_OFFSET 0xafc -#define GC_USB_DOEPCTL0_MPS_LSB 0x0 -#define GC_USB_DOEPCTL0_MPS_MASK 0x3 -#define GC_USB_DOEPCTL0_MPS_SIZE 0x2 -#define GC_USB_DOEPCTL0_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_MPS_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL0_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL0_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL0_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_USBACTEP_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL0_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL0_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL0_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_NAKSTS_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL0_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL0_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL0_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_EPTYPE_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_SNP_LSB 0x14 -#define GC_USB_DOEPCTL0_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL0_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL0_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_SNP_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_STALL_LSB 0x15 -#define GC_USB_DOEPCTL0_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL0_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL0_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_STALL_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL0_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL0_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL0_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_CNAK_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL0_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL0_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL0_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_SNAK_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL0_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL0_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL0_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_EPDIS_OFFSET 0xb00 -#define GC_USB_DOEPCTL0_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL0_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL0_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL0_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL0_EPENA_OFFSET 0xb00 -#define GC_USB_DOEPINT0_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT0_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT0_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT0_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT0_XFERCOMPL_OFFSET 0xb08 -#define GC_USB_DOEPINT0_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT0_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT0_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT0_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT0_EPDISBLD_OFFSET 0xb08 -#define GC_USB_DOEPINT0_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT0_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT0_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT0_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT0_AHBERR_OFFSET 0xb08 -#define GC_USB_DOEPINT0_SETUP_LSB 0x3 -#define GC_USB_DOEPINT0_SETUP_MASK 0x8 -#define GC_USB_DOEPINT0_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT0_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT0_SETUP_OFFSET 0xb08 -#define GC_USB_DOEPINT0_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT0_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT0_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT0_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT0_OUTTKNEPDIS_OFFSET 0xb08 -#define GC_USB_DOEPINT0_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT0_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT0_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT0_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT0_STSPHSERCVD_OFFSET 0xb08 -#define GC_USB_DOEPINT0_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT0_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT0_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT0_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT0_BACK2BACKSETUP_OFFSET 0xb08 -#define GC_USB_DOEPINT0_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT0_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT0_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT0_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT0_OUTPKTERR_OFFSET 0xb08 -#define GC_USB_DOEPINT0_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT0_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT0_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT0_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT0_BNAINTR_OFFSET 0xb08 -#define GC_USB_DOEPINT0_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT0_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT0_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT0_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT0_PKTDRPSTS_OFFSET 0xb08 -#define GC_USB_DOEPINT0_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT0_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT0_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT0_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT0_BBLEERR_OFFSET 0xb08 -#define GC_USB_DOEPINT0_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT0_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT0_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT0_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT0_NAKINTRPT_OFFSET 0xb08 -#define GC_USB_DOEPINT0_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT0_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT0_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT0_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT0_NYETINTRPT_OFFSET 0xb08 -#define GC_USB_DOEPINT0_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT0_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT0_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT0_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT0_STUPPKTRCVD_OFFSET 0xb08 -#define GC_USB_DOEPTSIZ0_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ0_XFERSIZE_MASK 0x7f -#define GC_USB_DOEPTSIZ0_XFERSIZE_SIZE 0x7 -#define GC_USB_DOEPTSIZ0_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ0_XFERSIZE_OFFSET 0xb10 -#define GC_USB_DOEPTSIZ0_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ0_PKTCNT_MASK 0x80000 -#define GC_USB_DOEPTSIZ0_PKTCNT_SIZE 0x1 -#define GC_USB_DOEPTSIZ0_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ0_PKTCNT_OFFSET 0xb10 -#define GC_USB_DOEPTSIZ0_SUPCNT_LSB 0x1d -#define GC_USB_DOEPTSIZ0_SUPCNT_MASK 0x60000000 -#define GC_USB_DOEPTSIZ0_SUPCNT_SIZE 0x2 -#define GC_USB_DOEPTSIZ0_SUPCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ0_SUPCNT_OFFSET 0xb10 -#define GC_USB_DOEPDMA0_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA0_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA0_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA0_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA0_DMAADDR_OFFSET 0xb14 -#define GC_USB_DOEPDMAB0_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB0_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB0_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB0_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB0_DMABUFFERADDR_OFFSET 0xb1c -#define GC_USB_DOEPCTL1_MPS_LSB 0x0 -#define GC_USB_DOEPCTL1_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL1_MPS_SIZE 0xb -#define GC_USB_DOEPCTL1_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_MPS_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL1_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL1_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL1_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_USBACTEP_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_DPID_LSB 0x10 -#define GC_USB_DOEPCTL1_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL1_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL1_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_DPID_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL1_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL1_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL1_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_NAKSTS_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL1_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL1_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL1_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_EPTYPE_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_SNP_LSB 0x14 -#define GC_USB_DOEPCTL1_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL1_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL1_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_SNP_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_STALL_LSB 0x15 -#define GC_USB_DOEPCTL1_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL1_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL1_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_STALL_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL1_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL1_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL1_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_CNAK_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL1_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL1_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL1_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_SNAK_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL1_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL1_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL1_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_SETD0PID_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL1_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL1_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL1_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_SETD1PID_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL1_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL1_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL1_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_EPDIS_OFFSET 0xb20 -#define GC_USB_DOEPCTL1_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL1_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL1_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL1_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL1_EPENA_OFFSET 0xb20 -#define GC_USB_DOEPINT1_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT1_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT1_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT1_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT1_XFERCOMPL_OFFSET 0xb28 -#define GC_USB_DOEPINT1_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT1_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT1_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT1_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT1_EPDISBLD_OFFSET 0xb28 -#define GC_USB_DOEPINT1_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT1_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT1_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT1_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT1_AHBERR_OFFSET 0xb28 -#define GC_USB_DOEPINT1_SETUP_LSB 0x3 -#define GC_USB_DOEPINT1_SETUP_MASK 0x8 -#define GC_USB_DOEPINT1_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT1_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT1_SETUP_OFFSET 0xb28 -#define GC_USB_DOEPINT1_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT1_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT1_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT1_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT1_OUTTKNEPDIS_OFFSET 0xb28 -#define GC_USB_DOEPINT1_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT1_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT1_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT1_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT1_STSPHSERCVD_OFFSET 0xb28 -#define GC_USB_DOEPINT1_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT1_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT1_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT1_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT1_BACK2BACKSETUP_OFFSET 0xb28 -#define GC_USB_DOEPINT1_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT1_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT1_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT1_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT1_OUTPKTERR_OFFSET 0xb28 -#define GC_USB_DOEPINT1_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT1_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT1_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT1_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT1_BNAINTR_OFFSET 0xb28 -#define GC_USB_DOEPINT1_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT1_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT1_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT1_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT1_PKTDRPSTS_OFFSET 0xb28 -#define GC_USB_DOEPINT1_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT1_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT1_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT1_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT1_BBLEERR_OFFSET 0xb28 -#define GC_USB_DOEPINT1_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT1_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT1_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT1_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT1_NAKINTRPT_OFFSET 0xb28 -#define GC_USB_DOEPINT1_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT1_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT1_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT1_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT1_NYETINTRPT_OFFSET 0xb28 -#define GC_USB_DOEPINT1_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT1_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT1_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT1_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT1_STUPPKTRCVD_OFFSET 0xb28 -#define GC_USB_DOEPTSIZ1_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ1_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ1_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ1_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ1_XFERSIZE_OFFSET 0xb30 -#define GC_USB_DOEPTSIZ1_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ1_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ1_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ1_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ1_PKTCNT_OFFSET 0xb30 -#define GC_USB_DOEPTSIZ1_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ1_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ1_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ1_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ1_RXDPID_OFFSET 0xb30 -#define GC_USB_DOEPDMA1_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA1_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA1_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA1_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA1_DMAADDR_OFFSET 0xb34 -#define GC_USB_DOEPDMAB1_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB1_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB1_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB1_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB1_DMABUFFERADDR_OFFSET 0xb3c -#define GC_USB_DOEPCTL2_MPS_LSB 0x0 -#define GC_USB_DOEPCTL2_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL2_MPS_SIZE 0xb -#define GC_USB_DOEPCTL2_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_MPS_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL2_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL2_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL2_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_USBACTEP_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_DPID_LSB 0x10 -#define GC_USB_DOEPCTL2_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL2_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL2_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_DPID_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL2_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL2_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL2_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_NAKSTS_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL2_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL2_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL2_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_EPTYPE_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_SNP_LSB 0x14 -#define GC_USB_DOEPCTL2_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL2_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL2_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_SNP_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_STALL_LSB 0x15 -#define GC_USB_DOEPCTL2_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL2_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL2_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_STALL_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL2_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL2_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL2_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_CNAK_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL2_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL2_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL2_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_SNAK_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL2_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL2_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL2_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_SETD0PID_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL2_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL2_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL2_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_SETD1PID_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL2_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL2_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL2_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_EPDIS_OFFSET 0xb40 -#define GC_USB_DOEPCTL2_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL2_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL2_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL2_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL2_EPENA_OFFSET 0xb40 -#define GC_USB_DOEPINT2_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT2_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT2_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT2_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT2_XFERCOMPL_OFFSET 0xb48 -#define GC_USB_DOEPINT2_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT2_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT2_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT2_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT2_EPDISBLD_OFFSET 0xb48 -#define GC_USB_DOEPINT2_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT2_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT2_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT2_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT2_AHBERR_OFFSET 0xb48 -#define GC_USB_DOEPINT2_SETUP_LSB 0x3 -#define GC_USB_DOEPINT2_SETUP_MASK 0x8 -#define GC_USB_DOEPINT2_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT2_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT2_SETUP_OFFSET 0xb48 -#define GC_USB_DOEPINT2_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT2_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT2_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT2_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT2_OUTTKNEPDIS_OFFSET 0xb48 -#define GC_USB_DOEPINT2_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT2_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT2_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT2_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT2_STSPHSERCVD_OFFSET 0xb48 -#define GC_USB_DOEPINT2_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT2_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT2_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT2_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT2_BACK2BACKSETUP_OFFSET 0xb48 -#define GC_USB_DOEPINT2_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT2_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT2_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT2_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT2_OUTPKTERR_OFFSET 0xb48 -#define GC_USB_DOEPINT2_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT2_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT2_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT2_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT2_BNAINTR_OFFSET 0xb48 -#define GC_USB_DOEPINT2_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT2_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT2_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT2_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT2_PKTDRPSTS_OFFSET 0xb48 -#define GC_USB_DOEPINT2_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT2_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT2_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT2_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT2_BBLEERR_OFFSET 0xb48 -#define GC_USB_DOEPINT2_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT2_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT2_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT2_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT2_NAKINTRPT_OFFSET 0xb48 -#define GC_USB_DOEPINT2_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT2_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT2_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT2_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT2_NYETINTRPT_OFFSET 0xb48 -#define GC_USB_DOEPINT2_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT2_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT2_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT2_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT2_STUPPKTRCVD_OFFSET 0xb48 -#define GC_USB_DOEPTSIZ2_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ2_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ2_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ2_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ2_XFERSIZE_OFFSET 0xb50 -#define GC_USB_DOEPTSIZ2_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ2_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ2_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ2_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ2_PKTCNT_OFFSET 0xb50 -#define GC_USB_DOEPTSIZ2_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ2_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ2_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ2_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ2_RXDPID_OFFSET 0xb50 -#define GC_USB_DOEPDMA2_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA2_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA2_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA2_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA2_DMAADDR_OFFSET 0xb54 -#define GC_USB_DOEPDMAB2_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB2_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB2_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB2_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB2_DMABUFFERADDR_OFFSET 0xb5c -#define GC_USB_DOEPCTL3_MPS_LSB 0x0 -#define GC_USB_DOEPCTL3_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL3_MPS_SIZE 0xb -#define GC_USB_DOEPCTL3_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_MPS_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL3_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL3_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL3_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_USBACTEP_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_DPID_LSB 0x10 -#define GC_USB_DOEPCTL3_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL3_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL3_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_DPID_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL3_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL3_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL3_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_NAKSTS_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL3_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL3_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL3_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_EPTYPE_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_SNP_LSB 0x14 -#define GC_USB_DOEPCTL3_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL3_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL3_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_SNP_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_STALL_LSB 0x15 -#define GC_USB_DOEPCTL3_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL3_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL3_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_STALL_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL3_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL3_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL3_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_CNAK_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL3_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL3_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL3_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_SNAK_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL3_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL3_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL3_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_SETD0PID_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL3_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL3_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL3_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_SETD1PID_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL3_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL3_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL3_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_EPDIS_OFFSET 0xb60 -#define GC_USB_DOEPCTL3_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL3_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL3_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL3_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL3_EPENA_OFFSET 0xb60 -#define GC_USB_DOEPINT3_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT3_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT3_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT3_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT3_XFERCOMPL_OFFSET 0xb68 -#define GC_USB_DOEPINT3_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT3_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT3_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT3_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT3_EPDISBLD_OFFSET 0xb68 -#define GC_USB_DOEPINT3_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT3_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT3_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT3_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT3_AHBERR_OFFSET 0xb68 -#define GC_USB_DOEPINT3_SETUP_LSB 0x3 -#define GC_USB_DOEPINT3_SETUP_MASK 0x8 -#define GC_USB_DOEPINT3_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT3_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT3_SETUP_OFFSET 0xb68 -#define GC_USB_DOEPINT3_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT3_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT3_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT3_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT3_OUTTKNEPDIS_OFFSET 0xb68 -#define GC_USB_DOEPINT3_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT3_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT3_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT3_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT3_STSPHSERCVD_OFFSET 0xb68 -#define GC_USB_DOEPINT3_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT3_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT3_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT3_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT3_BACK2BACKSETUP_OFFSET 0xb68 -#define GC_USB_DOEPINT3_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT3_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT3_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT3_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT3_OUTPKTERR_OFFSET 0xb68 -#define GC_USB_DOEPINT3_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT3_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT3_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT3_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT3_BNAINTR_OFFSET 0xb68 -#define GC_USB_DOEPINT3_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT3_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT3_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT3_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT3_PKTDRPSTS_OFFSET 0xb68 -#define GC_USB_DOEPINT3_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT3_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT3_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT3_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT3_BBLEERR_OFFSET 0xb68 -#define GC_USB_DOEPINT3_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT3_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT3_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT3_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT3_NAKINTRPT_OFFSET 0xb68 -#define GC_USB_DOEPINT3_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT3_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT3_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT3_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT3_NYETINTRPT_OFFSET 0xb68 -#define GC_USB_DOEPINT3_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT3_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT3_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT3_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT3_STUPPKTRCVD_OFFSET 0xb68 -#define GC_USB_DOEPTSIZ3_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ3_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ3_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ3_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ3_XFERSIZE_OFFSET 0xb70 -#define GC_USB_DOEPTSIZ3_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ3_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ3_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ3_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ3_PKTCNT_OFFSET 0xb70 -#define GC_USB_DOEPTSIZ3_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ3_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ3_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ3_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ3_RXDPID_OFFSET 0xb70 -#define GC_USB_DOEPDMA3_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA3_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA3_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA3_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA3_DMAADDR_OFFSET 0xb74 -#define GC_USB_DOEPDMAB3_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB3_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB3_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB3_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB3_DMABUFFERADDR_OFFSET 0xb7c -#define GC_USB_DOEPCTL4_MPS_LSB 0x0 -#define GC_USB_DOEPCTL4_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL4_MPS_SIZE 0xb -#define GC_USB_DOEPCTL4_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_MPS_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL4_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL4_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL4_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_USBACTEP_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_DPID_LSB 0x10 -#define GC_USB_DOEPCTL4_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL4_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL4_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_DPID_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL4_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL4_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL4_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_NAKSTS_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL4_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL4_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL4_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_EPTYPE_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_SNP_LSB 0x14 -#define GC_USB_DOEPCTL4_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL4_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL4_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_SNP_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_STALL_LSB 0x15 -#define GC_USB_DOEPCTL4_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL4_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL4_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_STALL_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL4_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL4_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL4_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_CNAK_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL4_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL4_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL4_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_SNAK_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL4_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL4_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL4_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_SETD0PID_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL4_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL4_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL4_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_SETD1PID_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL4_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL4_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL4_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_EPDIS_OFFSET 0xb80 -#define GC_USB_DOEPCTL4_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL4_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL4_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL4_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL4_EPENA_OFFSET 0xb80 -#define GC_USB_DOEPINT4_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT4_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT4_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT4_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT4_XFERCOMPL_OFFSET 0xb88 -#define GC_USB_DOEPINT4_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT4_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT4_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT4_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT4_EPDISBLD_OFFSET 0xb88 -#define GC_USB_DOEPINT4_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT4_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT4_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT4_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT4_AHBERR_OFFSET 0xb88 -#define GC_USB_DOEPINT4_SETUP_LSB 0x3 -#define GC_USB_DOEPINT4_SETUP_MASK 0x8 -#define GC_USB_DOEPINT4_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT4_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT4_SETUP_OFFSET 0xb88 -#define GC_USB_DOEPINT4_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT4_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT4_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT4_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT4_OUTTKNEPDIS_OFFSET 0xb88 -#define GC_USB_DOEPINT4_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT4_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT4_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT4_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT4_STSPHSERCVD_OFFSET 0xb88 -#define GC_USB_DOEPINT4_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT4_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT4_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT4_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT4_BACK2BACKSETUP_OFFSET 0xb88 -#define GC_USB_DOEPINT4_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT4_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT4_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT4_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT4_OUTPKTERR_OFFSET 0xb88 -#define GC_USB_DOEPINT4_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT4_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT4_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT4_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT4_BNAINTR_OFFSET 0xb88 -#define GC_USB_DOEPINT4_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT4_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT4_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT4_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT4_PKTDRPSTS_OFFSET 0xb88 -#define GC_USB_DOEPINT4_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT4_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT4_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT4_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT4_BBLEERR_OFFSET 0xb88 -#define GC_USB_DOEPINT4_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT4_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT4_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT4_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT4_NAKINTRPT_OFFSET 0xb88 -#define GC_USB_DOEPINT4_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT4_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT4_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT4_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT4_NYETINTRPT_OFFSET 0xb88 -#define GC_USB_DOEPINT4_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT4_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT4_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT4_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT4_STUPPKTRCVD_OFFSET 0xb88 -#define GC_USB_DOEPTSIZ4_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ4_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ4_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ4_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ4_XFERSIZE_OFFSET 0xb90 -#define GC_USB_DOEPTSIZ4_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ4_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ4_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ4_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ4_PKTCNT_OFFSET 0xb90 -#define GC_USB_DOEPTSIZ4_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ4_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ4_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ4_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ4_RXDPID_OFFSET 0xb90 -#define GC_USB_DOEPDMA4_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA4_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA4_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA4_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA4_DMAADDR_OFFSET 0xb94 -#define GC_USB_DOEPDMAB4_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB4_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB4_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB4_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB4_DMABUFFERADDR_OFFSET 0xb9c -#define GC_USB_DOEPCTL5_MPS_LSB 0x0 -#define GC_USB_DOEPCTL5_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL5_MPS_SIZE 0xb -#define GC_USB_DOEPCTL5_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_MPS_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL5_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL5_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL5_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_USBACTEP_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_DPID_LSB 0x10 -#define GC_USB_DOEPCTL5_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL5_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL5_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_DPID_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL5_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL5_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL5_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_NAKSTS_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL5_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL5_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL5_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_EPTYPE_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_SNP_LSB 0x14 -#define GC_USB_DOEPCTL5_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL5_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL5_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_SNP_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_STALL_LSB 0x15 -#define GC_USB_DOEPCTL5_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL5_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL5_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_STALL_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL5_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL5_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL5_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_CNAK_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL5_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL5_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL5_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_SNAK_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL5_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL5_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL5_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_SETD0PID_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL5_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL5_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL5_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_SETD1PID_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL5_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL5_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL5_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_EPDIS_OFFSET 0xba0 -#define GC_USB_DOEPCTL5_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL5_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL5_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL5_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL5_EPENA_OFFSET 0xba0 -#define GC_USB_DOEPINT5_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT5_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT5_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT5_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT5_XFERCOMPL_OFFSET 0xba8 -#define GC_USB_DOEPINT5_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT5_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT5_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT5_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT5_EPDISBLD_OFFSET 0xba8 -#define GC_USB_DOEPINT5_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT5_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT5_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT5_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT5_AHBERR_OFFSET 0xba8 -#define GC_USB_DOEPINT5_SETUP_LSB 0x3 -#define GC_USB_DOEPINT5_SETUP_MASK 0x8 -#define GC_USB_DOEPINT5_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT5_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT5_SETUP_OFFSET 0xba8 -#define GC_USB_DOEPINT5_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT5_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT5_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT5_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT5_OUTTKNEPDIS_OFFSET 0xba8 -#define GC_USB_DOEPINT5_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT5_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT5_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT5_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT5_STSPHSERCVD_OFFSET 0xba8 -#define GC_USB_DOEPINT5_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT5_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT5_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT5_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT5_BACK2BACKSETUP_OFFSET 0xba8 -#define GC_USB_DOEPINT5_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT5_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT5_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT5_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT5_OUTPKTERR_OFFSET 0xba8 -#define GC_USB_DOEPINT5_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT5_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT5_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT5_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT5_BNAINTR_OFFSET 0xba8 -#define GC_USB_DOEPINT5_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT5_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT5_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT5_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT5_PKTDRPSTS_OFFSET 0xba8 -#define GC_USB_DOEPINT5_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT5_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT5_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT5_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT5_BBLEERR_OFFSET 0xba8 -#define GC_USB_DOEPINT5_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT5_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT5_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT5_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT5_NAKINTRPT_OFFSET 0xba8 -#define GC_USB_DOEPINT5_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT5_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT5_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT5_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT5_NYETINTRPT_OFFSET 0xba8 -#define GC_USB_DOEPINT5_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT5_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT5_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT5_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT5_STUPPKTRCVD_OFFSET 0xba8 -#define GC_USB_DOEPTSIZ5_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ5_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ5_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ5_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ5_XFERSIZE_OFFSET 0xbb0 -#define GC_USB_DOEPTSIZ5_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ5_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ5_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ5_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ5_PKTCNT_OFFSET 0xbb0 -#define GC_USB_DOEPTSIZ5_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ5_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ5_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ5_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ5_RXDPID_OFFSET 0xbb0 -#define GC_USB_DOEPDMA5_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA5_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA5_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA5_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA5_DMAADDR_OFFSET 0xbb4 -#define GC_USB_DOEPDMAB5_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB5_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB5_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB5_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB5_DMABUFFERADDR_OFFSET 0xbbc -#define GC_USB_DOEPCTL6_MPS_LSB 0x0 -#define GC_USB_DOEPCTL6_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL6_MPS_SIZE 0xb -#define GC_USB_DOEPCTL6_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_MPS_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL6_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL6_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL6_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_USBACTEP_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_DPID_LSB 0x10 -#define GC_USB_DOEPCTL6_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL6_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL6_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_DPID_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL6_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL6_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL6_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_NAKSTS_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL6_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL6_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL6_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_EPTYPE_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_SNP_LSB 0x14 -#define GC_USB_DOEPCTL6_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL6_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL6_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_SNP_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_STALL_LSB 0x15 -#define GC_USB_DOEPCTL6_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL6_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL6_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_STALL_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL6_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL6_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL6_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_CNAK_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL6_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL6_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL6_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_SNAK_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL6_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL6_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL6_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_SETD0PID_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL6_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL6_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL6_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_SETD1PID_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL6_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL6_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL6_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_EPDIS_OFFSET 0xbc0 -#define GC_USB_DOEPCTL6_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL6_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL6_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL6_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL6_EPENA_OFFSET 0xbc0 -#define GC_USB_DOEPINT6_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT6_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT6_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT6_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT6_XFERCOMPL_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT6_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT6_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT6_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT6_EPDISBLD_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT6_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT6_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT6_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT6_AHBERR_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_SETUP_LSB 0x3 -#define GC_USB_DOEPINT6_SETUP_MASK 0x8 -#define GC_USB_DOEPINT6_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT6_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT6_SETUP_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT6_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT6_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT6_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT6_OUTTKNEPDIS_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT6_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT6_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT6_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT6_STSPHSERCVD_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT6_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT6_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT6_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT6_BACK2BACKSETUP_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT6_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT6_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT6_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT6_OUTPKTERR_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT6_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT6_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT6_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT6_BNAINTR_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT6_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT6_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT6_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT6_PKTDRPSTS_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT6_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT6_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT6_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT6_BBLEERR_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT6_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT6_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT6_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT6_NAKINTRPT_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT6_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT6_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT6_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT6_NYETINTRPT_OFFSET 0xbc8 -#define GC_USB_DOEPINT6_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT6_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT6_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT6_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT6_STUPPKTRCVD_OFFSET 0xbc8 -#define GC_USB_DOEPTSIZ6_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ6_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ6_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ6_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ6_XFERSIZE_OFFSET 0xbd0 -#define GC_USB_DOEPTSIZ6_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ6_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ6_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ6_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ6_PKTCNT_OFFSET 0xbd0 -#define GC_USB_DOEPTSIZ6_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ6_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ6_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ6_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ6_RXDPID_OFFSET 0xbd0 -#define GC_USB_DOEPDMA6_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA6_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA6_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA6_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA6_DMAADDR_OFFSET 0xbd4 -#define GC_USB_DOEPDMAB6_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB6_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB6_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB6_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB6_DMABUFFERADDR_OFFSET 0xbdc -#define GC_USB_DOEPCTL7_MPS_LSB 0x0 -#define GC_USB_DOEPCTL7_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL7_MPS_SIZE 0xb -#define GC_USB_DOEPCTL7_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_MPS_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL7_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL7_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL7_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_USBACTEP_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_DPID_LSB 0x10 -#define GC_USB_DOEPCTL7_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL7_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL7_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_DPID_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL7_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL7_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL7_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_NAKSTS_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL7_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL7_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL7_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_EPTYPE_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_SNP_LSB 0x14 -#define GC_USB_DOEPCTL7_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL7_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL7_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_SNP_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_STALL_LSB 0x15 -#define GC_USB_DOEPCTL7_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL7_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL7_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_STALL_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL7_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL7_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL7_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_CNAK_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL7_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL7_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL7_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_SNAK_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL7_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL7_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL7_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_SETD0PID_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL7_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL7_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL7_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_SETD1PID_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL7_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL7_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL7_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_EPDIS_OFFSET 0xbe0 -#define GC_USB_DOEPCTL7_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL7_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL7_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL7_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL7_EPENA_OFFSET 0xbe0 -#define GC_USB_DOEPINT7_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT7_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT7_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT7_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT7_XFERCOMPL_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT7_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT7_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT7_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT7_EPDISBLD_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT7_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT7_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT7_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT7_AHBERR_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_SETUP_LSB 0x3 -#define GC_USB_DOEPINT7_SETUP_MASK 0x8 -#define GC_USB_DOEPINT7_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT7_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT7_SETUP_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT7_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT7_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT7_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT7_OUTTKNEPDIS_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT7_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT7_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT7_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT7_STSPHSERCVD_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT7_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT7_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT7_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT7_BACK2BACKSETUP_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT7_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT7_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT7_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT7_OUTPKTERR_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT7_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT7_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT7_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT7_BNAINTR_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT7_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT7_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT7_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT7_PKTDRPSTS_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT7_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT7_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT7_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT7_BBLEERR_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT7_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT7_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT7_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT7_NAKINTRPT_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT7_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT7_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT7_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT7_NYETINTRPT_OFFSET 0xbe8 -#define GC_USB_DOEPINT7_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT7_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT7_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT7_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT7_STUPPKTRCVD_OFFSET 0xbe8 -#define GC_USB_DOEPTSIZ7_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ7_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ7_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ7_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ7_XFERSIZE_OFFSET 0xbf0 -#define GC_USB_DOEPTSIZ7_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ7_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ7_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ7_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ7_PKTCNT_OFFSET 0xbf0 -#define GC_USB_DOEPTSIZ7_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ7_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ7_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ7_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ7_RXDPID_OFFSET 0xbf0 -#define GC_USB_DOEPDMA7_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA7_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA7_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA7_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA7_DMAADDR_OFFSET 0xbf4 -#define GC_USB_DOEPDMAB7_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB7_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB7_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB7_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB7_DMABUFFERADDR_OFFSET 0xbfc -#define GC_USB_DOEPCTL8_MPS_LSB 0x0 -#define GC_USB_DOEPCTL8_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL8_MPS_SIZE 0xb -#define GC_USB_DOEPCTL8_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_MPS_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL8_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL8_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL8_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_USBACTEP_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_DPID_LSB 0x10 -#define GC_USB_DOEPCTL8_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL8_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL8_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_DPID_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL8_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL8_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL8_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_NAKSTS_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL8_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL8_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL8_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_EPTYPE_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_SNP_LSB 0x14 -#define GC_USB_DOEPCTL8_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL8_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL8_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_SNP_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_STALL_LSB 0x15 -#define GC_USB_DOEPCTL8_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL8_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL8_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_STALL_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL8_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL8_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL8_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_CNAK_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL8_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL8_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL8_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_SNAK_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL8_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL8_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL8_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_SETD0PID_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL8_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL8_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL8_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_SETD1PID_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL8_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL8_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL8_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_EPDIS_OFFSET 0xc00 -#define GC_USB_DOEPCTL8_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL8_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL8_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL8_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL8_EPENA_OFFSET 0xc00 -#define GC_USB_DOEPINT8_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT8_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT8_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT8_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT8_XFERCOMPL_OFFSET 0xc08 -#define GC_USB_DOEPINT8_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT8_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT8_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT8_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT8_EPDISBLD_OFFSET 0xc08 -#define GC_USB_DOEPINT8_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT8_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT8_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT8_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT8_AHBERR_OFFSET 0xc08 -#define GC_USB_DOEPINT8_SETUP_LSB 0x3 -#define GC_USB_DOEPINT8_SETUP_MASK 0x8 -#define GC_USB_DOEPINT8_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT8_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT8_SETUP_OFFSET 0xc08 -#define GC_USB_DOEPINT8_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT8_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT8_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT8_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT8_OUTTKNEPDIS_OFFSET 0xc08 -#define GC_USB_DOEPINT8_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT8_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT8_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT8_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT8_STSPHSERCVD_OFFSET 0xc08 -#define GC_USB_DOEPINT8_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT8_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT8_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT8_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT8_BACK2BACKSETUP_OFFSET 0xc08 -#define GC_USB_DOEPINT8_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT8_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT8_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT8_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT8_OUTPKTERR_OFFSET 0xc08 -#define GC_USB_DOEPINT8_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT8_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT8_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT8_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT8_BNAINTR_OFFSET 0xc08 -#define GC_USB_DOEPINT8_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT8_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT8_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT8_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT8_PKTDRPSTS_OFFSET 0xc08 -#define GC_USB_DOEPINT8_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT8_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT8_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT8_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT8_BBLEERR_OFFSET 0xc08 -#define GC_USB_DOEPINT8_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT8_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT8_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT8_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT8_NAKINTRPT_OFFSET 0xc08 -#define GC_USB_DOEPINT8_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT8_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT8_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT8_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT8_NYETINTRPT_OFFSET 0xc08 -#define GC_USB_DOEPINT8_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT8_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT8_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT8_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT8_STUPPKTRCVD_OFFSET 0xc08 -#define GC_USB_DOEPTSIZ8_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ8_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ8_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ8_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ8_XFERSIZE_OFFSET 0xc10 -#define GC_USB_DOEPTSIZ8_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ8_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ8_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ8_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ8_PKTCNT_OFFSET 0xc10 -#define GC_USB_DOEPTSIZ8_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ8_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ8_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ8_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ8_RXDPID_OFFSET 0xc10 -#define GC_USB_DOEPDMA8_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA8_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA8_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA8_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA8_DMAADDR_OFFSET 0xc14 -#define GC_USB_DOEPDMAB8_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB8_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB8_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB8_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB8_DMABUFFERADDR_OFFSET 0xc1c -#define GC_USB_DOEPCTL9_MPS_LSB 0x0 -#define GC_USB_DOEPCTL9_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL9_MPS_SIZE 0xb -#define GC_USB_DOEPCTL9_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_MPS_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL9_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL9_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL9_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_USBACTEP_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_DPID_LSB 0x10 -#define GC_USB_DOEPCTL9_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL9_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL9_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_DPID_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL9_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL9_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL9_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_NAKSTS_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL9_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL9_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL9_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_EPTYPE_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_SNP_LSB 0x14 -#define GC_USB_DOEPCTL9_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL9_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL9_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_SNP_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_STALL_LSB 0x15 -#define GC_USB_DOEPCTL9_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL9_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL9_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_STALL_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL9_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL9_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL9_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_CNAK_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL9_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL9_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL9_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_SNAK_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL9_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL9_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL9_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_SETD0PID_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL9_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL9_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL9_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_SETD1PID_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL9_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL9_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL9_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_EPDIS_OFFSET 0xc20 -#define GC_USB_DOEPCTL9_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL9_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL9_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL9_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL9_EPENA_OFFSET 0xc20 -#define GC_USB_DOEPINT9_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT9_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT9_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT9_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT9_XFERCOMPL_OFFSET 0xc28 -#define GC_USB_DOEPINT9_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT9_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT9_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT9_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT9_EPDISBLD_OFFSET 0xc28 -#define GC_USB_DOEPINT9_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT9_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT9_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT9_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT9_AHBERR_OFFSET 0xc28 -#define GC_USB_DOEPINT9_SETUP_LSB 0x3 -#define GC_USB_DOEPINT9_SETUP_MASK 0x8 -#define GC_USB_DOEPINT9_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT9_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT9_SETUP_OFFSET 0xc28 -#define GC_USB_DOEPINT9_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT9_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT9_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT9_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT9_OUTTKNEPDIS_OFFSET 0xc28 -#define GC_USB_DOEPINT9_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT9_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT9_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT9_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT9_STSPHSERCVD_OFFSET 0xc28 -#define GC_USB_DOEPINT9_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT9_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT9_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT9_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT9_BACK2BACKSETUP_OFFSET 0xc28 -#define GC_USB_DOEPINT9_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT9_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT9_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT9_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT9_OUTPKTERR_OFFSET 0xc28 -#define GC_USB_DOEPINT9_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT9_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT9_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT9_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT9_BNAINTR_OFFSET 0xc28 -#define GC_USB_DOEPINT9_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT9_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT9_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT9_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT9_PKTDRPSTS_OFFSET 0xc28 -#define GC_USB_DOEPINT9_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT9_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT9_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT9_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT9_BBLEERR_OFFSET 0xc28 -#define GC_USB_DOEPINT9_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT9_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT9_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT9_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT9_NAKINTRPT_OFFSET 0xc28 -#define GC_USB_DOEPINT9_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT9_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT9_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT9_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT9_NYETINTRPT_OFFSET 0xc28 -#define GC_USB_DOEPINT9_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT9_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT9_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT9_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT9_STUPPKTRCVD_OFFSET 0xc28 -#define GC_USB_DOEPTSIZ9_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ9_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ9_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ9_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ9_XFERSIZE_OFFSET 0xc30 -#define GC_USB_DOEPTSIZ9_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ9_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ9_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ9_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ9_PKTCNT_OFFSET 0xc30 -#define GC_USB_DOEPTSIZ9_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ9_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ9_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ9_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ9_RXDPID_OFFSET 0xc30 -#define GC_USB_DOEPDMA9_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA9_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA9_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA9_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA9_DMAADDR_OFFSET 0xc34 -#define GC_USB_DOEPDMAB9_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB9_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB9_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB9_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB9_DMABUFFERADDR_OFFSET 0xc3c -#define GC_USB_DOEPCTL10_MPS_LSB 0x0 -#define GC_USB_DOEPCTL10_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL10_MPS_SIZE 0xb -#define GC_USB_DOEPCTL10_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_MPS_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL10_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL10_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL10_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_USBACTEP_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_DPID_LSB 0x10 -#define GC_USB_DOEPCTL10_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL10_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL10_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_DPID_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL10_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL10_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL10_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_NAKSTS_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL10_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL10_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL10_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_EPTYPE_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_SNP_LSB 0x14 -#define GC_USB_DOEPCTL10_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL10_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL10_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_SNP_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_STALL_LSB 0x15 -#define GC_USB_DOEPCTL10_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL10_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL10_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_STALL_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL10_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL10_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL10_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_CNAK_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL10_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL10_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL10_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_SNAK_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL10_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL10_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL10_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_SETD0PID_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL10_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL10_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL10_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_SETD1PID_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL10_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL10_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL10_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_EPDIS_OFFSET 0xc40 -#define GC_USB_DOEPCTL10_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL10_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL10_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL10_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL10_EPENA_OFFSET 0xc40 -#define GC_USB_DOEPINT10_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT10_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT10_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT10_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT10_XFERCOMPL_OFFSET 0xc48 -#define GC_USB_DOEPINT10_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT10_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT10_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT10_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT10_EPDISBLD_OFFSET 0xc48 -#define GC_USB_DOEPINT10_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT10_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT10_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT10_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT10_AHBERR_OFFSET 0xc48 -#define GC_USB_DOEPINT10_SETUP_LSB 0x3 -#define GC_USB_DOEPINT10_SETUP_MASK 0x8 -#define GC_USB_DOEPINT10_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT10_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT10_SETUP_OFFSET 0xc48 -#define GC_USB_DOEPINT10_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT10_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT10_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT10_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT10_OUTTKNEPDIS_OFFSET 0xc48 -#define GC_USB_DOEPINT10_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT10_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT10_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT10_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT10_STSPHSERCVD_OFFSET 0xc48 -#define GC_USB_DOEPINT10_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT10_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT10_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT10_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT10_BACK2BACKSETUP_OFFSET 0xc48 -#define GC_USB_DOEPINT10_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT10_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT10_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT10_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT10_OUTPKTERR_OFFSET 0xc48 -#define GC_USB_DOEPINT10_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT10_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT10_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT10_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT10_BNAINTR_OFFSET 0xc48 -#define GC_USB_DOEPINT10_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT10_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT10_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT10_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT10_PKTDRPSTS_OFFSET 0xc48 -#define GC_USB_DOEPINT10_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT10_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT10_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT10_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT10_BBLEERR_OFFSET 0xc48 -#define GC_USB_DOEPINT10_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT10_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT10_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT10_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT10_NAKINTRPT_OFFSET 0xc48 -#define GC_USB_DOEPINT10_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT10_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT10_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT10_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT10_NYETINTRPT_OFFSET 0xc48 -#define GC_USB_DOEPINT10_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT10_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT10_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT10_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT10_STUPPKTRCVD_OFFSET 0xc48 -#define GC_USB_DOEPTSIZ10_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ10_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ10_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ10_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ10_XFERSIZE_OFFSET 0xc50 -#define GC_USB_DOEPTSIZ10_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ10_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ10_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ10_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ10_PKTCNT_OFFSET 0xc50 -#define GC_USB_DOEPTSIZ10_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ10_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ10_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ10_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ10_RXDPID_OFFSET 0xc50 -#define GC_USB_DOEPDMA10_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA10_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA10_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA10_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA10_DMAADDR_OFFSET 0xc54 -#define GC_USB_DOEPDMAB10_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB10_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB10_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB10_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB10_DMABUFFERADDR_OFFSET 0xc5c -#define GC_USB_DOEPCTL11_MPS_LSB 0x0 -#define GC_USB_DOEPCTL11_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL11_MPS_SIZE 0xb -#define GC_USB_DOEPCTL11_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_MPS_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL11_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL11_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL11_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_USBACTEP_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_DPID_LSB 0x10 -#define GC_USB_DOEPCTL11_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL11_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL11_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_DPID_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL11_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL11_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL11_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_NAKSTS_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL11_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL11_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL11_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_EPTYPE_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_SNP_LSB 0x14 -#define GC_USB_DOEPCTL11_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL11_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL11_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_SNP_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_STALL_LSB 0x15 -#define GC_USB_DOEPCTL11_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL11_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL11_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_STALL_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL11_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL11_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL11_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_CNAK_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL11_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL11_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL11_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_SNAK_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL11_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL11_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL11_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_SETD0PID_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL11_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL11_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL11_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_SETD1PID_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL11_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL11_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL11_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_EPDIS_OFFSET 0xc60 -#define GC_USB_DOEPCTL11_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL11_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL11_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL11_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL11_EPENA_OFFSET 0xc60 -#define GC_USB_DOEPINT11_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT11_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT11_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT11_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT11_XFERCOMPL_OFFSET 0xc68 -#define GC_USB_DOEPINT11_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT11_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT11_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT11_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT11_EPDISBLD_OFFSET 0xc68 -#define GC_USB_DOEPINT11_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT11_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT11_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT11_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT11_AHBERR_OFFSET 0xc68 -#define GC_USB_DOEPINT11_SETUP_LSB 0x3 -#define GC_USB_DOEPINT11_SETUP_MASK 0x8 -#define GC_USB_DOEPINT11_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT11_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT11_SETUP_OFFSET 0xc68 -#define GC_USB_DOEPINT11_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT11_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT11_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT11_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT11_OUTTKNEPDIS_OFFSET 0xc68 -#define GC_USB_DOEPINT11_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT11_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT11_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT11_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT11_STSPHSERCVD_OFFSET 0xc68 -#define GC_USB_DOEPINT11_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT11_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT11_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT11_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT11_BACK2BACKSETUP_OFFSET 0xc68 -#define GC_USB_DOEPINT11_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT11_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT11_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT11_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT11_OUTPKTERR_OFFSET 0xc68 -#define GC_USB_DOEPINT11_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT11_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT11_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT11_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT11_BNAINTR_OFFSET 0xc68 -#define GC_USB_DOEPINT11_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT11_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT11_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT11_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT11_PKTDRPSTS_OFFSET 0xc68 -#define GC_USB_DOEPINT11_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT11_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT11_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT11_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT11_BBLEERR_OFFSET 0xc68 -#define GC_USB_DOEPINT11_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT11_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT11_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT11_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT11_NAKINTRPT_OFFSET 0xc68 -#define GC_USB_DOEPINT11_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT11_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT11_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT11_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT11_NYETINTRPT_OFFSET 0xc68 -#define GC_USB_DOEPINT11_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT11_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT11_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT11_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT11_STUPPKTRCVD_OFFSET 0xc68 -#define GC_USB_DOEPTSIZ11_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ11_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ11_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ11_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ11_XFERSIZE_OFFSET 0xc70 -#define GC_USB_DOEPTSIZ11_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ11_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ11_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ11_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ11_PKTCNT_OFFSET 0xc70 -#define GC_USB_DOEPTSIZ11_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ11_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ11_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ11_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ11_RXDPID_OFFSET 0xc70 -#define GC_USB_DOEPDMA11_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA11_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA11_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA11_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA11_DMAADDR_OFFSET 0xc74 -#define GC_USB_DOEPDMAB11_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB11_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB11_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB11_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB11_DMABUFFERADDR_OFFSET 0xc7c -#define GC_USB_DOEPCTL12_MPS_LSB 0x0 -#define GC_USB_DOEPCTL12_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL12_MPS_SIZE 0xb -#define GC_USB_DOEPCTL12_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_MPS_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL12_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL12_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL12_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_USBACTEP_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_DPID_LSB 0x10 -#define GC_USB_DOEPCTL12_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL12_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL12_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_DPID_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL12_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL12_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL12_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_NAKSTS_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL12_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL12_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL12_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_EPTYPE_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_SNP_LSB 0x14 -#define GC_USB_DOEPCTL12_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL12_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL12_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_SNP_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_STALL_LSB 0x15 -#define GC_USB_DOEPCTL12_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL12_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL12_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_STALL_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL12_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL12_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL12_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_CNAK_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL12_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL12_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL12_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_SNAK_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL12_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL12_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL12_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_SETD0PID_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL12_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL12_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL12_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_SETD1PID_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL12_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL12_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL12_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_EPDIS_OFFSET 0xc80 -#define GC_USB_DOEPCTL12_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL12_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL12_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL12_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL12_EPENA_OFFSET 0xc80 -#define GC_USB_DOEPINT12_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT12_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT12_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT12_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT12_XFERCOMPL_OFFSET 0xc88 -#define GC_USB_DOEPINT12_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT12_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT12_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT12_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT12_EPDISBLD_OFFSET 0xc88 -#define GC_USB_DOEPINT12_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT12_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT12_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT12_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT12_AHBERR_OFFSET 0xc88 -#define GC_USB_DOEPINT12_SETUP_LSB 0x3 -#define GC_USB_DOEPINT12_SETUP_MASK 0x8 -#define GC_USB_DOEPINT12_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT12_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT12_SETUP_OFFSET 0xc88 -#define GC_USB_DOEPINT12_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT12_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT12_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT12_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT12_OUTTKNEPDIS_OFFSET 0xc88 -#define GC_USB_DOEPINT12_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT12_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT12_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT12_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT12_STSPHSERCVD_OFFSET 0xc88 -#define GC_USB_DOEPINT12_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT12_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT12_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT12_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT12_BACK2BACKSETUP_OFFSET 0xc88 -#define GC_USB_DOEPINT12_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT12_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT12_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT12_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT12_OUTPKTERR_OFFSET 0xc88 -#define GC_USB_DOEPINT12_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT12_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT12_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT12_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT12_BNAINTR_OFFSET 0xc88 -#define GC_USB_DOEPINT12_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT12_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT12_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT12_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT12_PKTDRPSTS_OFFSET 0xc88 -#define GC_USB_DOEPINT12_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT12_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT12_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT12_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT12_BBLEERR_OFFSET 0xc88 -#define GC_USB_DOEPINT12_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT12_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT12_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT12_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT12_NAKINTRPT_OFFSET 0xc88 -#define GC_USB_DOEPINT12_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT12_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT12_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT12_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT12_NYETINTRPT_OFFSET 0xc88 -#define GC_USB_DOEPINT12_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT12_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT12_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT12_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT12_STUPPKTRCVD_OFFSET 0xc88 -#define GC_USB_DOEPTSIZ12_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ12_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ12_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ12_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ12_XFERSIZE_OFFSET 0xc90 -#define GC_USB_DOEPTSIZ12_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ12_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ12_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ12_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ12_PKTCNT_OFFSET 0xc90 -#define GC_USB_DOEPTSIZ12_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ12_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ12_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ12_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ12_RXDPID_OFFSET 0xc90 -#define GC_USB_DOEPDMA12_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA12_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA12_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA12_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA12_DMAADDR_OFFSET 0xc94 -#define GC_USB_DOEPDMAB12_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB12_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB12_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB12_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB12_DMABUFFERADDR_OFFSET 0xc9c -#define GC_USB_DOEPCTL13_MPS_LSB 0x0 -#define GC_USB_DOEPCTL13_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL13_MPS_SIZE 0xb -#define GC_USB_DOEPCTL13_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_MPS_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL13_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL13_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL13_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_USBACTEP_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_DPID_LSB 0x10 -#define GC_USB_DOEPCTL13_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL13_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL13_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_DPID_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL13_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL13_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL13_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_NAKSTS_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL13_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL13_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL13_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_EPTYPE_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_SNP_LSB 0x14 -#define GC_USB_DOEPCTL13_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL13_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL13_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_SNP_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_STALL_LSB 0x15 -#define GC_USB_DOEPCTL13_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL13_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL13_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_STALL_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL13_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL13_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL13_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_CNAK_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL13_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL13_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL13_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_SNAK_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL13_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL13_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL13_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_SETD0PID_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL13_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL13_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL13_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_SETD1PID_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL13_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL13_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL13_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_EPDIS_OFFSET 0xca0 -#define GC_USB_DOEPCTL13_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL13_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL13_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL13_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL13_EPENA_OFFSET 0xca0 -#define GC_USB_DOEPINT13_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT13_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT13_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT13_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT13_XFERCOMPL_OFFSET 0xca8 -#define GC_USB_DOEPINT13_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT13_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT13_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT13_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT13_EPDISBLD_OFFSET 0xca8 -#define GC_USB_DOEPINT13_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT13_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT13_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT13_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT13_AHBERR_OFFSET 0xca8 -#define GC_USB_DOEPINT13_SETUP_LSB 0x3 -#define GC_USB_DOEPINT13_SETUP_MASK 0x8 -#define GC_USB_DOEPINT13_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT13_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT13_SETUP_OFFSET 0xca8 -#define GC_USB_DOEPINT13_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT13_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT13_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT13_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT13_OUTTKNEPDIS_OFFSET 0xca8 -#define GC_USB_DOEPINT13_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT13_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT13_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT13_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT13_STSPHSERCVD_OFFSET 0xca8 -#define GC_USB_DOEPINT13_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT13_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT13_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT13_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT13_BACK2BACKSETUP_OFFSET 0xca8 -#define GC_USB_DOEPINT13_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT13_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT13_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT13_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT13_OUTPKTERR_OFFSET 0xca8 -#define GC_USB_DOEPINT13_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT13_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT13_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT13_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT13_BNAINTR_OFFSET 0xca8 -#define GC_USB_DOEPINT13_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT13_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT13_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT13_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT13_PKTDRPSTS_OFFSET 0xca8 -#define GC_USB_DOEPINT13_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT13_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT13_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT13_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT13_BBLEERR_OFFSET 0xca8 -#define GC_USB_DOEPINT13_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT13_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT13_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT13_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT13_NAKINTRPT_OFFSET 0xca8 -#define GC_USB_DOEPINT13_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT13_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT13_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT13_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT13_NYETINTRPT_OFFSET 0xca8 -#define GC_USB_DOEPINT13_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT13_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT13_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT13_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT13_STUPPKTRCVD_OFFSET 0xca8 -#define GC_USB_DOEPTSIZ13_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ13_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ13_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ13_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ13_XFERSIZE_OFFSET 0xcb0 -#define GC_USB_DOEPTSIZ13_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ13_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ13_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ13_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ13_PKTCNT_OFFSET 0xcb0 -#define GC_USB_DOEPTSIZ13_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ13_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ13_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ13_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ13_RXDPID_OFFSET 0xcb0 -#define GC_USB_DOEPDMA13_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA13_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA13_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA13_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA13_DMAADDR_OFFSET 0xcb4 -#define GC_USB_DOEPDMAB13_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB13_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB13_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB13_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB13_DMABUFFERADDR_OFFSET 0xcbc -#define GC_USB_DOEPCTL14_MPS_LSB 0x0 -#define GC_USB_DOEPCTL14_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL14_MPS_SIZE 0xb -#define GC_USB_DOEPCTL14_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_MPS_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL14_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL14_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL14_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_USBACTEP_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_DPID_LSB 0x10 -#define GC_USB_DOEPCTL14_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL14_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL14_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_DPID_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL14_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL14_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL14_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_NAKSTS_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL14_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL14_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL14_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_EPTYPE_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_SNP_LSB 0x14 -#define GC_USB_DOEPCTL14_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL14_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL14_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_SNP_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_STALL_LSB 0x15 -#define GC_USB_DOEPCTL14_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL14_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL14_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_STALL_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL14_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL14_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL14_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_CNAK_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL14_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL14_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL14_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_SNAK_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL14_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL14_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL14_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_SETD0PID_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL14_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL14_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL14_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_SETD1PID_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL14_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL14_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL14_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_EPDIS_OFFSET 0xcc0 -#define GC_USB_DOEPCTL14_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL14_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL14_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL14_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL14_EPENA_OFFSET 0xcc0 -#define GC_USB_DOEPINT14_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT14_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT14_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT14_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT14_XFERCOMPL_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT14_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT14_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT14_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT14_EPDISBLD_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT14_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT14_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT14_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT14_AHBERR_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_SETUP_LSB 0x3 -#define GC_USB_DOEPINT14_SETUP_MASK 0x8 -#define GC_USB_DOEPINT14_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT14_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT14_SETUP_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT14_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT14_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT14_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT14_OUTTKNEPDIS_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT14_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT14_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT14_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT14_STSPHSERCVD_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT14_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT14_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT14_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT14_BACK2BACKSETUP_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT14_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT14_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT14_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT14_OUTPKTERR_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT14_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT14_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT14_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT14_BNAINTR_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT14_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT14_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT14_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT14_PKTDRPSTS_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT14_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT14_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT14_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT14_BBLEERR_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT14_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT14_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT14_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT14_NAKINTRPT_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT14_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT14_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT14_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT14_NYETINTRPT_OFFSET 0xcc8 -#define GC_USB_DOEPINT14_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT14_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT14_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT14_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT14_STUPPKTRCVD_OFFSET 0xcc8 -#define GC_USB_DOEPTSIZ14_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ14_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ14_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ14_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ14_XFERSIZE_OFFSET 0xcd0 -#define GC_USB_DOEPTSIZ14_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ14_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ14_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ14_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ14_PKTCNT_OFFSET 0xcd0 -#define GC_USB_DOEPTSIZ14_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ14_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ14_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ14_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ14_RXDPID_OFFSET 0xcd0 -#define GC_USB_DOEPDMA14_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA14_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA14_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA14_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA14_DMAADDR_OFFSET 0xcd4 -#define GC_USB_DOEPDMAB14_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB14_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB14_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB14_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB14_DMABUFFERADDR_OFFSET 0xcdc -#define GC_USB_DOEPCTL15_MPS_LSB 0x0 -#define GC_USB_DOEPCTL15_MPS_MASK 0x7ff -#define GC_USB_DOEPCTL15_MPS_SIZE 0xb -#define GC_USB_DOEPCTL15_MPS_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_MPS_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_USBACTEP_LSB 0xf -#define GC_USB_DOEPCTL15_USBACTEP_MASK 0x8000 -#define GC_USB_DOEPCTL15_USBACTEP_SIZE 0x1 -#define GC_USB_DOEPCTL15_USBACTEP_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_USBACTEP_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_DPID_LSB 0x10 -#define GC_USB_DOEPCTL15_DPID_MASK 0x10000 -#define GC_USB_DOEPCTL15_DPID_SIZE 0x1 -#define GC_USB_DOEPCTL15_DPID_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_DPID_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_NAKSTS_LSB 0x11 -#define GC_USB_DOEPCTL15_NAKSTS_MASK 0x20000 -#define GC_USB_DOEPCTL15_NAKSTS_SIZE 0x1 -#define GC_USB_DOEPCTL15_NAKSTS_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_NAKSTS_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_EPTYPE_LSB 0x12 -#define GC_USB_DOEPCTL15_EPTYPE_MASK 0xc0000 -#define GC_USB_DOEPCTL15_EPTYPE_SIZE 0x2 -#define GC_USB_DOEPCTL15_EPTYPE_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_EPTYPE_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_SNP_LSB 0x14 -#define GC_USB_DOEPCTL15_SNP_MASK 0x100000 -#define GC_USB_DOEPCTL15_SNP_SIZE 0x1 -#define GC_USB_DOEPCTL15_SNP_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_SNP_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_STALL_LSB 0x15 -#define GC_USB_DOEPCTL15_STALL_MASK 0x200000 -#define GC_USB_DOEPCTL15_STALL_SIZE 0x1 -#define GC_USB_DOEPCTL15_STALL_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_STALL_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_CNAK_LSB 0x1a -#define GC_USB_DOEPCTL15_CNAK_MASK 0x4000000 -#define GC_USB_DOEPCTL15_CNAK_SIZE 0x1 -#define GC_USB_DOEPCTL15_CNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_CNAK_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_SNAK_LSB 0x1b -#define GC_USB_DOEPCTL15_SNAK_MASK 0x8000000 -#define GC_USB_DOEPCTL15_SNAK_SIZE 0x1 -#define GC_USB_DOEPCTL15_SNAK_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_SNAK_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_SETD0PID_LSB 0x1c -#define GC_USB_DOEPCTL15_SETD0PID_MASK 0x10000000 -#define GC_USB_DOEPCTL15_SETD0PID_SIZE 0x1 -#define GC_USB_DOEPCTL15_SETD0PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_SETD0PID_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_SETD1PID_LSB 0x1d -#define GC_USB_DOEPCTL15_SETD1PID_MASK 0x20000000 -#define GC_USB_DOEPCTL15_SETD1PID_SIZE 0x1 -#define GC_USB_DOEPCTL15_SETD1PID_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_SETD1PID_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_EPDIS_LSB 0x1e -#define GC_USB_DOEPCTL15_EPDIS_MASK 0x40000000 -#define GC_USB_DOEPCTL15_EPDIS_SIZE 0x1 -#define GC_USB_DOEPCTL15_EPDIS_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_EPDIS_OFFSET 0xce0 -#define GC_USB_DOEPCTL15_EPENA_LSB 0x1f -#define GC_USB_DOEPCTL15_EPENA_MASK 0x80000000 -#define GC_USB_DOEPCTL15_EPENA_SIZE 0x1 -#define GC_USB_DOEPCTL15_EPENA_DEFAULT 0x0 -#define GC_USB_DOEPCTL15_EPENA_OFFSET 0xce0 -#define GC_USB_DOEPINT15_XFERCOMPL_LSB 0x0 -#define GC_USB_DOEPINT15_XFERCOMPL_MASK 0x1 -#define GC_USB_DOEPINT15_XFERCOMPL_SIZE 0x1 -#define GC_USB_DOEPINT15_XFERCOMPL_DEFAULT 0x0 -#define GC_USB_DOEPINT15_XFERCOMPL_OFFSET 0xce8 -#define GC_USB_DOEPINT15_EPDISBLD_LSB 0x1 -#define GC_USB_DOEPINT15_EPDISBLD_MASK 0x2 -#define GC_USB_DOEPINT15_EPDISBLD_SIZE 0x1 -#define GC_USB_DOEPINT15_EPDISBLD_DEFAULT 0x0 -#define GC_USB_DOEPINT15_EPDISBLD_OFFSET 0xce8 -#define GC_USB_DOEPINT15_AHBERR_LSB 0x2 -#define GC_USB_DOEPINT15_AHBERR_MASK 0x4 -#define GC_USB_DOEPINT15_AHBERR_SIZE 0x1 -#define GC_USB_DOEPINT15_AHBERR_DEFAULT 0x0 -#define GC_USB_DOEPINT15_AHBERR_OFFSET 0xce8 -#define GC_USB_DOEPINT15_SETUP_LSB 0x3 -#define GC_USB_DOEPINT15_SETUP_MASK 0x8 -#define GC_USB_DOEPINT15_SETUP_SIZE 0x1 -#define GC_USB_DOEPINT15_SETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT15_SETUP_OFFSET 0xce8 -#define GC_USB_DOEPINT15_OUTTKNEPDIS_LSB 0x4 -#define GC_USB_DOEPINT15_OUTTKNEPDIS_MASK 0x10 -#define GC_USB_DOEPINT15_OUTTKNEPDIS_SIZE 0x1 -#define GC_USB_DOEPINT15_OUTTKNEPDIS_DEFAULT 0x0 -#define GC_USB_DOEPINT15_OUTTKNEPDIS_OFFSET 0xce8 -#define GC_USB_DOEPINT15_STSPHSERCVD_LSB 0x5 -#define GC_USB_DOEPINT15_STSPHSERCVD_MASK 0x20 -#define GC_USB_DOEPINT15_STSPHSERCVD_SIZE 0x1 -#define GC_USB_DOEPINT15_STSPHSERCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT15_STSPHSERCVD_OFFSET 0xce8 -#define GC_USB_DOEPINT15_BACK2BACKSETUP_LSB 0x6 -#define GC_USB_DOEPINT15_BACK2BACKSETUP_MASK 0x40 -#define GC_USB_DOEPINT15_BACK2BACKSETUP_SIZE 0x1 -#define GC_USB_DOEPINT15_BACK2BACKSETUP_DEFAULT 0x0 -#define GC_USB_DOEPINT15_BACK2BACKSETUP_OFFSET 0xce8 -#define GC_USB_DOEPINT15_OUTPKTERR_LSB 0x8 -#define GC_USB_DOEPINT15_OUTPKTERR_MASK 0x100 -#define GC_USB_DOEPINT15_OUTPKTERR_SIZE 0x1 -#define GC_USB_DOEPINT15_OUTPKTERR_DEFAULT 0x0 -#define GC_USB_DOEPINT15_OUTPKTERR_OFFSET 0xce8 -#define GC_USB_DOEPINT15_BNAINTR_LSB 0x9 -#define GC_USB_DOEPINT15_BNAINTR_MASK 0x200 -#define GC_USB_DOEPINT15_BNAINTR_SIZE 0x1 -#define GC_USB_DOEPINT15_BNAINTR_DEFAULT 0x0 -#define GC_USB_DOEPINT15_BNAINTR_OFFSET 0xce8 -#define GC_USB_DOEPINT15_PKTDRPSTS_LSB 0xb -#define GC_USB_DOEPINT15_PKTDRPSTS_MASK 0x800 -#define GC_USB_DOEPINT15_PKTDRPSTS_SIZE 0x1 -#define GC_USB_DOEPINT15_PKTDRPSTS_DEFAULT 0x0 -#define GC_USB_DOEPINT15_PKTDRPSTS_OFFSET 0xce8 -#define GC_USB_DOEPINT15_BBLEERR_LSB 0xc -#define GC_USB_DOEPINT15_BBLEERR_MASK 0x1000 -#define GC_USB_DOEPINT15_BBLEERR_SIZE 0x1 -#define GC_USB_DOEPINT15_BBLEERR_DEFAULT 0x0 -#define GC_USB_DOEPINT15_BBLEERR_OFFSET 0xce8 -#define GC_USB_DOEPINT15_NAKINTRPT_LSB 0xd -#define GC_USB_DOEPINT15_NAKINTRPT_MASK 0x2000 -#define GC_USB_DOEPINT15_NAKINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT15_NAKINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT15_NAKINTRPT_OFFSET 0xce8 -#define GC_USB_DOEPINT15_NYETINTRPT_LSB 0xe -#define GC_USB_DOEPINT15_NYETINTRPT_MASK 0x4000 -#define GC_USB_DOEPINT15_NYETINTRPT_SIZE 0x1 -#define GC_USB_DOEPINT15_NYETINTRPT_DEFAULT 0x0 -#define GC_USB_DOEPINT15_NYETINTRPT_OFFSET 0xce8 -#define GC_USB_DOEPINT15_STUPPKTRCVD_LSB 0xf -#define GC_USB_DOEPINT15_STUPPKTRCVD_MASK 0x8000 -#define GC_USB_DOEPINT15_STUPPKTRCVD_SIZE 0x1 -#define GC_USB_DOEPINT15_STUPPKTRCVD_DEFAULT 0x0 -#define GC_USB_DOEPINT15_STUPPKTRCVD_OFFSET 0xce8 -#define GC_USB_DOEPTSIZ15_XFERSIZE_LSB 0x0 -#define GC_USB_DOEPTSIZ15_XFERSIZE_MASK 0x7ffff -#define GC_USB_DOEPTSIZ15_XFERSIZE_SIZE 0x13 -#define GC_USB_DOEPTSIZ15_XFERSIZE_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ15_XFERSIZE_OFFSET 0xcf0 -#define GC_USB_DOEPTSIZ15_PKTCNT_LSB 0x13 -#define GC_USB_DOEPTSIZ15_PKTCNT_MASK 0x1ff80000 -#define GC_USB_DOEPTSIZ15_PKTCNT_SIZE 0xa -#define GC_USB_DOEPTSIZ15_PKTCNT_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ15_PKTCNT_OFFSET 0xcf0 -#define GC_USB_DOEPTSIZ15_RXDPID_LSB 0x1d -#define GC_USB_DOEPTSIZ15_RXDPID_MASK 0x60000000 -#define GC_USB_DOEPTSIZ15_RXDPID_SIZE 0x2 -#define GC_USB_DOEPTSIZ15_RXDPID_DEFAULT 0x0 -#define GC_USB_DOEPTSIZ15_RXDPID_OFFSET 0xcf0 -#define GC_USB_DOEPDMA15_DMAADDR_LSB 0x0 -#define GC_USB_DOEPDMA15_DMAADDR_MASK 0xffffffff -#define GC_USB_DOEPDMA15_DMAADDR_SIZE 0x20 -#define GC_USB_DOEPDMA15_DMAADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMA15_DMAADDR_OFFSET 0xcf4 -#define GC_USB_DOEPDMAB15_DMABUFFERADDR_LSB 0x0 -#define GC_USB_DOEPDMAB15_DMABUFFERADDR_MASK 0xffffffff -#define GC_USB_DOEPDMAB15_DMABUFFERADDR_SIZE 0x20 -#define GC_USB_DOEPDMAB15_DMABUFFERADDR_DEFAULT 0x0 -#define GC_USB_DOEPDMAB15_DMABUFFERADDR_OFFSET 0xcfc -#define GC_USB_PCGCCTL_STOPPCLK_LSB 0x0 -#define GC_USB_PCGCCTL_STOPPCLK_MASK 0x1 -#define GC_USB_PCGCCTL_STOPPCLK_SIZE 0x1 -#define GC_USB_PCGCCTL_STOPPCLK_DEFAULT 0x0 -#define GC_USB_PCGCCTL_STOPPCLK_OFFSET 0xe00 -#define GC_USB_PCGCCTL_GATEHCLK_LSB 0x1 -#define GC_USB_PCGCCTL_GATEHCLK_MASK 0x2 -#define GC_USB_PCGCCTL_GATEHCLK_SIZE 0x1 -#define GC_USB_PCGCCTL_GATEHCLK_DEFAULT 0x0 -#define GC_USB_PCGCCTL_GATEHCLK_OFFSET 0xe00 -#define GC_USB_PCGCCTL_PWRCLMP_LSB 0x2 -#define GC_USB_PCGCCTL_PWRCLMP_MASK 0x4 -#define GC_USB_PCGCCTL_PWRCLMP_SIZE 0x1 -#define GC_USB_PCGCCTL_PWRCLMP_DEFAULT 0x0 -#define GC_USB_PCGCCTL_PWRCLMP_OFFSET 0xe00 -#define GC_USB_PCGCCTL_RSTPDWNMODULE_LSB 0x3 -#define GC_USB_PCGCCTL_RSTPDWNMODULE_MASK 0x8 -#define GC_USB_PCGCCTL_RSTPDWNMODULE_SIZE 0x1 -#define GC_USB_PCGCCTL_RSTPDWNMODULE_DEFAULT 0x0 -#define GC_USB_PCGCCTL_RSTPDWNMODULE_OFFSET 0xe00 -#define GC_USB_PCGCCTL_PHYSLEEP_LSB 0x6 -#define GC_USB_PCGCCTL_PHYSLEEP_MASK 0x40 -#define GC_USB_PCGCCTL_PHYSLEEP_SIZE 0x1 -#define GC_USB_PCGCCTL_PHYSLEEP_DEFAULT 0x0 -#define GC_USB_PCGCCTL_PHYSLEEP_OFFSET 0xe00 -#define GC_USB_PCGCCTL_L1SUSPENDED_LSB 0x7 -#define GC_USB_PCGCCTL_L1SUSPENDED_MASK 0x80 -#define GC_USB_PCGCCTL_L1SUSPENDED_SIZE 0x1 -#define GC_USB_PCGCCTL_L1SUSPENDED_DEFAULT 0x0 -#define GC_USB_PCGCCTL_L1SUSPENDED_OFFSET 0xe00 -#define GC_USB_DFIFO_SIZE 0x1000 - +#define GC_USB_DTXFSTS15_INEPTXFSPCAVAIL_OFFSET 0xaf8 +#define GC_USB_DIEPDMAB15_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DIEPDMAB15_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DIEPDMAB15_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DIEPDMAB15_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DIEPDMAB15_DMABUFFERADDR_OFFSET 0xafc +#define GC_USB_DOEPCTL0_MPS_LSB 0x0 +#define GC_USB_DOEPCTL0_MPS_MASK 0x3 +#define GC_USB_DOEPCTL0_MPS_SIZE 0x2 +#define GC_USB_DOEPCTL0_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_MPS_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL0_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL0_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL0_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_USBACTEP_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL0_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL0_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL0_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_NAKSTS_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL0_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL0_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL0_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_EPTYPE_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_SNP_LSB 0x14 +#define GC_USB_DOEPCTL0_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL0_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL0_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_SNP_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_STALL_LSB 0x15 +#define GC_USB_DOEPCTL0_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL0_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL0_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_STALL_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL0_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL0_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL0_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_CNAK_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL0_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL0_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL0_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_SNAK_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL0_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL0_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL0_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_EPDIS_OFFSET 0xb00 +#define GC_USB_DOEPCTL0_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL0_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL0_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL0_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL0_EPENA_OFFSET 0xb00 +#define GC_USB_DOEPINT0_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT0_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT0_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT0_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT0_XFERCOMPL_OFFSET 0xb08 +#define GC_USB_DOEPINT0_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT0_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT0_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT0_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT0_EPDISBLD_OFFSET 0xb08 +#define GC_USB_DOEPINT0_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT0_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT0_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT0_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT0_AHBERR_OFFSET 0xb08 +#define GC_USB_DOEPINT0_SETUP_LSB 0x3 +#define GC_USB_DOEPINT0_SETUP_MASK 0x8 +#define GC_USB_DOEPINT0_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT0_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT0_SETUP_OFFSET 0xb08 +#define GC_USB_DOEPINT0_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT0_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT0_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT0_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT0_OUTTKNEPDIS_OFFSET 0xb08 +#define GC_USB_DOEPINT0_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT0_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT0_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT0_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT0_STSPHSERCVD_OFFSET 0xb08 +#define GC_USB_DOEPINT0_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT0_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT0_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT0_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT0_BACK2BACKSETUP_OFFSET 0xb08 +#define GC_USB_DOEPINT0_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT0_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT0_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT0_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT0_OUTPKTERR_OFFSET 0xb08 +#define GC_USB_DOEPINT0_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT0_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT0_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT0_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT0_BNAINTR_OFFSET 0xb08 +#define GC_USB_DOEPINT0_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT0_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT0_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT0_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT0_PKTDRPSTS_OFFSET 0xb08 +#define GC_USB_DOEPINT0_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT0_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT0_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT0_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT0_BBLEERR_OFFSET 0xb08 +#define GC_USB_DOEPINT0_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT0_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT0_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT0_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT0_NAKINTRPT_OFFSET 0xb08 +#define GC_USB_DOEPINT0_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT0_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT0_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT0_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT0_NYETINTRPT_OFFSET 0xb08 +#define GC_USB_DOEPINT0_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT0_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT0_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT0_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT0_STUPPKTRCVD_OFFSET 0xb08 +#define GC_USB_DOEPTSIZ0_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ0_XFERSIZE_MASK 0x7f +#define GC_USB_DOEPTSIZ0_XFERSIZE_SIZE 0x7 +#define GC_USB_DOEPTSIZ0_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ0_XFERSIZE_OFFSET 0xb10 +#define GC_USB_DOEPTSIZ0_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ0_PKTCNT_MASK 0x80000 +#define GC_USB_DOEPTSIZ0_PKTCNT_SIZE 0x1 +#define GC_USB_DOEPTSIZ0_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ0_PKTCNT_OFFSET 0xb10 +#define GC_USB_DOEPTSIZ0_SUPCNT_LSB 0x1d +#define GC_USB_DOEPTSIZ0_SUPCNT_MASK 0x60000000 +#define GC_USB_DOEPTSIZ0_SUPCNT_SIZE 0x2 +#define GC_USB_DOEPTSIZ0_SUPCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ0_SUPCNT_OFFSET 0xb10 +#define GC_USB_DOEPDMA0_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA0_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA0_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA0_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA0_DMAADDR_OFFSET 0xb14 +#define GC_USB_DOEPDMAB0_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB0_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB0_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB0_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB0_DMABUFFERADDR_OFFSET 0xb1c +#define GC_USB_DOEPCTL1_MPS_LSB 0x0 +#define GC_USB_DOEPCTL1_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL1_MPS_SIZE 0xb +#define GC_USB_DOEPCTL1_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_MPS_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL1_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL1_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL1_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_USBACTEP_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_DPID_LSB 0x10 +#define GC_USB_DOEPCTL1_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL1_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL1_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_DPID_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL1_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL1_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL1_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_NAKSTS_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL1_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL1_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL1_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_EPTYPE_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_SNP_LSB 0x14 +#define GC_USB_DOEPCTL1_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL1_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL1_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_SNP_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_STALL_LSB 0x15 +#define GC_USB_DOEPCTL1_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL1_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL1_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_STALL_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL1_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL1_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL1_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_CNAK_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL1_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL1_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL1_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_SNAK_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL1_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL1_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL1_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_SETD0PID_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL1_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL1_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL1_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_SETD1PID_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL1_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL1_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL1_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_EPDIS_OFFSET 0xb20 +#define GC_USB_DOEPCTL1_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL1_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL1_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL1_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL1_EPENA_OFFSET 0xb20 +#define GC_USB_DOEPINT1_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT1_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT1_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT1_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT1_XFERCOMPL_OFFSET 0xb28 +#define GC_USB_DOEPINT1_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT1_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT1_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT1_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT1_EPDISBLD_OFFSET 0xb28 +#define GC_USB_DOEPINT1_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT1_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT1_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT1_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT1_AHBERR_OFFSET 0xb28 +#define GC_USB_DOEPINT1_SETUP_LSB 0x3 +#define GC_USB_DOEPINT1_SETUP_MASK 0x8 +#define GC_USB_DOEPINT1_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT1_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT1_SETUP_OFFSET 0xb28 +#define GC_USB_DOEPINT1_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT1_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT1_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT1_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT1_OUTTKNEPDIS_OFFSET 0xb28 +#define GC_USB_DOEPINT1_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT1_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT1_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT1_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT1_STSPHSERCVD_OFFSET 0xb28 +#define GC_USB_DOEPINT1_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT1_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT1_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT1_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT1_BACK2BACKSETUP_OFFSET 0xb28 +#define GC_USB_DOEPINT1_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT1_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT1_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT1_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT1_OUTPKTERR_OFFSET 0xb28 +#define GC_USB_DOEPINT1_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT1_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT1_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT1_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT1_BNAINTR_OFFSET 0xb28 +#define GC_USB_DOEPINT1_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT1_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT1_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT1_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT1_PKTDRPSTS_OFFSET 0xb28 +#define GC_USB_DOEPINT1_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT1_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT1_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT1_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT1_BBLEERR_OFFSET 0xb28 +#define GC_USB_DOEPINT1_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT1_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT1_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT1_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT1_NAKINTRPT_OFFSET 0xb28 +#define GC_USB_DOEPINT1_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT1_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT1_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT1_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT1_NYETINTRPT_OFFSET 0xb28 +#define GC_USB_DOEPINT1_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT1_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT1_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT1_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT1_STUPPKTRCVD_OFFSET 0xb28 +#define GC_USB_DOEPTSIZ1_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ1_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ1_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ1_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ1_XFERSIZE_OFFSET 0xb30 +#define GC_USB_DOEPTSIZ1_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ1_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ1_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ1_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ1_PKTCNT_OFFSET 0xb30 +#define GC_USB_DOEPTSIZ1_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ1_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ1_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ1_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ1_RXDPID_OFFSET 0xb30 +#define GC_USB_DOEPDMA1_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA1_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA1_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA1_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA1_DMAADDR_OFFSET 0xb34 +#define GC_USB_DOEPDMAB1_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB1_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB1_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB1_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB1_DMABUFFERADDR_OFFSET 0xb3c +#define GC_USB_DOEPCTL2_MPS_LSB 0x0 +#define GC_USB_DOEPCTL2_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL2_MPS_SIZE 0xb +#define GC_USB_DOEPCTL2_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_MPS_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL2_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL2_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL2_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_USBACTEP_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_DPID_LSB 0x10 +#define GC_USB_DOEPCTL2_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL2_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL2_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_DPID_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL2_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL2_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL2_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_NAKSTS_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL2_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL2_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL2_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_EPTYPE_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_SNP_LSB 0x14 +#define GC_USB_DOEPCTL2_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL2_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL2_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_SNP_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_STALL_LSB 0x15 +#define GC_USB_DOEPCTL2_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL2_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL2_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_STALL_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL2_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL2_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL2_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_CNAK_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL2_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL2_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL2_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_SNAK_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL2_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL2_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL2_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_SETD0PID_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL2_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL2_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL2_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_SETD1PID_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL2_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL2_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL2_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_EPDIS_OFFSET 0xb40 +#define GC_USB_DOEPCTL2_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL2_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL2_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL2_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL2_EPENA_OFFSET 0xb40 +#define GC_USB_DOEPINT2_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT2_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT2_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT2_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT2_XFERCOMPL_OFFSET 0xb48 +#define GC_USB_DOEPINT2_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT2_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT2_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT2_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT2_EPDISBLD_OFFSET 0xb48 +#define GC_USB_DOEPINT2_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT2_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT2_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT2_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT2_AHBERR_OFFSET 0xb48 +#define GC_USB_DOEPINT2_SETUP_LSB 0x3 +#define GC_USB_DOEPINT2_SETUP_MASK 0x8 +#define GC_USB_DOEPINT2_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT2_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT2_SETUP_OFFSET 0xb48 +#define GC_USB_DOEPINT2_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT2_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT2_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT2_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT2_OUTTKNEPDIS_OFFSET 0xb48 +#define GC_USB_DOEPINT2_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT2_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT2_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT2_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT2_STSPHSERCVD_OFFSET 0xb48 +#define GC_USB_DOEPINT2_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT2_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT2_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT2_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT2_BACK2BACKSETUP_OFFSET 0xb48 +#define GC_USB_DOEPINT2_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT2_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT2_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT2_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT2_OUTPKTERR_OFFSET 0xb48 +#define GC_USB_DOEPINT2_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT2_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT2_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT2_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT2_BNAINTR_OFFSET 0xb48 +#define GC_USB_DOEPINT2_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT2_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT2_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT2_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT2_PKTDRPSTS_OFFSET 0xb48 +#define GC_USB_DOEPINT2_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT2_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT2_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT2_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT2_BBLEERR_OFFSET 0xb48 +#define GC_USB_DOEPINT2_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT2_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT2_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT2_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT2_NAKINTRPT_OFFSET 0xb48 +#define GC_USB_DOEPINT2_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT2_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT2_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT2_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT2_NYETINTRPT_OFFSET 0xb48 +#define GC_USB_DOEPINT2_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT2_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT2_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT2_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT2_STUPPKTRCVD_OFFSET 0xb48 +#define GC_USB_DOEPTSIZ2_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ2_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ2_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ2_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ2_XFERSIZE_OFFSET 0xb50 +#define GC_USB_DOEPTSIZ2_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ2_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ2_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ2_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ2_PKTCNT_OFFSET 0xb50 +#define GC_USB_DOEPTSIZ2_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ2_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ2_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ2_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ2_RXDPID_OFFSET 0xb50 +#define GC_USB_DOEPDMA2_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA2_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA2_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA2_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA2_DMAADDR_OFFSET 0xb54 +#define GC_USB_DOEPDMAB2_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB2_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB2_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB2_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB2_DMABUFFERADDR_OFFSET 0xb5c +#define GC_USB_DOEPCTL3_MPS_LSB 0x0 +#define GC_USB_DOEPCTL3_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL3_MPS_SIZE 0xb +#define GC_USB_DOEPCTL3_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_MPS_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL3_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL3_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL3_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_USBACTEP_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_DPID_LSB 0x10 +#define GC_USB_DOEPCTL3_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL3_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL3_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_DPID_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL3_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL3_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL3_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_NAKSTS_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL3_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL3_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL3_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_EPTYPE_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_SNP_LSB 0x14 +#define GC_USB_DOEPCTL3_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL3_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL3_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_SNP_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_STALL_LSB 0x15 +#define GC_USB_DOEPCTL3_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL3_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL3_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_STALL_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL3_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL3_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL3_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_CNAK_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL3_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL3_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL3_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_SNAK_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL3_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL3_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL3_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_SETD0PID_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL3_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL3_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL3_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_SETD1PID_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL3_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL3_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL3_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_EPDIS_OFFSET 0xb60 +#define GC_USB_DOEPCTL3_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL3_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL3_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL3_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL3_EPENA_OFFSET 0xb60 +#define GC_USB_DOEPINT3_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT3_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT3_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT3_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT3_XFERCOMPL_OFFSET 0xb68 +#define GC_USB_DOEPINT3_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT3_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT3_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT3_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT3_EPDISBLD_OFFSET 0xb68 +#define GC_USB_DOEPINT3_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT3_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT3_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT3_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT3_AHBERR_OFFSET 0xb68 +#define GC_USB_DOEPINT3_SETUP_LSB 0x3 +#define GC_USB_DOEPINT3_SETUP_MASK 0x8 +#define GC_USB_DOEPINT3_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT3_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT3_SETUP_OFFSET 0xb68 +#define GC_USB_DOEPINT3_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT3_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT3_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT3_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT3_OUTTKNEPDIS_OFFSET 0xb68 +#define GC_USB_DOEPINT3_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT3_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT3_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT3_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT3_STSPHSERCVD_OFFSET 0xb68 +#define GC_USB_DOEPINT3_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT3_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT3_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT3_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT3_BACK2BACKSETUP_OFFSET 0xb68 +#define GC_USB_DOEPINT3_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT3_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT3_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT3_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT3_OUTPKTERR_OFFSET 0xb68 +#define GC_USB_DOEPINT3_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT3_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT3_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT3_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT3_BNAINTR_OFFSET 0xb68 +#define GC_USB_DOEPINT3_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT3_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT3_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT3_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT3_PKTDRPSTS_OFFSET 0xb68 +#define GC_USB_DOEPINT3_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT3_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT3_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT3_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT3_BBLEERR_OFFSET 0xb68 +#define GC_USB_DOEPINT3_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT3_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT3_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT3_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT3_NAKINTRPT_OFFSET 0xb68 +#define GC_USB_DOEPINT3_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT3_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT3_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT3_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT3_NYETINTRPT_OFFSET 0xb68 +#define GC_USB_DOEPINT3_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT3_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT3_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT3_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT3_STUPPKTRCVD_OFFSET 0xb68 +#define GC_USB_DOEPTSIZ3_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ3_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ3_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ3_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ3_XFERSIZE_OFFSET 0xb70 +#define GC_USB_DOEPTSIZ3_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ3_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ3_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ3_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ3_PKTCNT_OFFSET 0xb70 +#define GC_USB_DOEPTSIZ3_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ3_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ3_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ3_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ3_RXDPID_OFFSET 0xb70 +#define GC_USB_DOEPDMA3_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA3_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA3_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA3_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA3_DMAADDR_OFFSET 0xb74 +#define GC_USB_DOEPDMAB3_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB3_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB3_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB3_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB3_DMABUFFERADDR_OFFSET 0xb7c +#define GC_USB_DOEPCTL4_MPS_LSB 0x0 +#define GC_USB_DOEPCTL4_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL4_MPS_SIZE 0xb +#define GC_USB_DOEPCTL4_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_MPS_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL4_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL4_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL4_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_USBACTEP_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_DPID_LSB 0x10 +#define GC_USB_DOEPCTL4_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL4_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL4_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_DPID_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL4_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL4_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL4_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_NAKSTS_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL4_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL4_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL4_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_EPTYPE_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_SNP_LSB 0x14 +#define GC_USB_DOEPCTL4_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL4_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL4_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_SNP_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_STALL_LSB 0x15 +#define GC_USB_DOEPCTL4_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL4_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL4_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_STALL_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL4_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL4_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL4_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_CNAK_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL4_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL4_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL4_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_SNAK_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL4_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL4_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL4_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_SETD0PID_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL4_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL4_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL4_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_SETD1PID_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL4_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL4_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL4_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_EPDIS_OFFSET 0xb80 +#define GC_USB_DOEPCTL4_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL4_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL4_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL4_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL4_EPENA_OFFSET 0xb80 +#define GC_USB_DOEPINT4_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT4_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT4_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT4_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT4_XFERCOMPL_OFFSET 0xb88 +#define GC_USB_DOEPINT4_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT4_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT4_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT4_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT4_EPDISBLD_OFFSET 0xb88 +#define GC_USB_DOEPINT4_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT4_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT4_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT4_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT4_AHBERR_OFFSET 0xb88 +#define GC_USB_DOEPINT4_SETUP_LSB 0x3 +#define GC_USB_DOEPINT4_SETUP_MASK 0x8 +#define GC_USB_DOEPINT4_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT4_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT4_SETUP_OFFSET 0xb88 +#define GC_USB_DOEPINT4_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT4_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT4_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT4_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT4_OUTTKNEPDIS_OFFSET 0xb88 +#define GC_USB_DOEPINT4_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT4_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT4_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT4_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT4_STSPHSERCVD_OFFSET 0xb88 +#define GC_USB_DOEPINT4_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT4_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT4_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT4_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT4_BACK2BACKSETUP_OFFSET 0xb88 +#define GC_USB_DOEPINT4_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT4_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT4_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT4_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT4_OUTPKTERR_OFFSET 0xb88 +#define GC_USB_DOEPINT4_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT4_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT4_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT4_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT4_BNAINTR_OFFSET 0xb88 +#define GC_USB_DOEPINT4_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT4_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT4_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT4_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT4_PKTDRPSTS_OFFSET 0xb88 +#define GC_USB_DOEPINT4_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT4_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT4_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT4_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT4_BBLEERR_OFFSET 0xb88 +#define GC_USB_DOEPINT4_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT4_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT4_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT4_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT4_NAKINTRPT_OFFSET 0xb88 +#define GC_USB_DOEPINT4_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT4_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT4_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT4_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT4_NYETINTRPT_OFFSET 0xb88 +#define GC_USB_DOEPINT4_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT4_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT4_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT4_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT4_STUPPKTRCVD_OFFSET 0xb88 +#define GC_USB_DOEPTSIZ4_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ4_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ4_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ4_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ4_XFERSIZE_OFFSET 0xb90 +#define GC_USB_DOEPTSIZ4_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ4_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ4_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ4_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ4_PKTCNT_OFFSET 0xb90 +#define GC_USB_DOEPTSIZ4_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ4_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ4_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ4_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ4_RXDPID_OFFSET 0xb90 +#define GC_USB_DOEPDMA4_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA4_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA4_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA4_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA4_DMAADDR_OFFSET 0xb94 +#define GC_USB_DOEPDMAB4_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB4_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB4_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB4_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB4_DMABUFFERADDR_OFFSET 0xb9c +#define GC_USB_DOEPCTL5_MPS_LSB 0x0 +#define GC_USB_DOEPCTL5_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL5_MPS_SIZE 0xb +#define GC_USB_DOEPCTL5_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_MPS_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL5_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL5_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL5_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_USBACTEP_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_DPID_LSB 0x10 +#define GC_USB_DOEPCTL5_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL5_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL5_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_DPID_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL5_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL5_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL5_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_NAKSTS_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL5_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL5_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL5_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_EPTYPE_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_SNP_LSB 0x14 +#define GC_USB_DOEPCTL5_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL5_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL5_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_SNP_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_STALL_LSB 0x15 +#define GC_USB_DOEPCTL5_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL5_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL5_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_STALL_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL5_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL5_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL5_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_CNAK_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL5_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL5_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL5_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_SNAK_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL5_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL5_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL5_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_SETD0PID_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL5_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL5_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL5_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_SETD1PID_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL5_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL5_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL5_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_EPDIS_OFFSET 0xba0 +#define GC_USB_DOEPCTL5_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL5_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL5_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL5_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL5_EPENA_OFFSET 0xba0 +#define GC_USB_DOEPINT5_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT5_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT5_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT5_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT5_XFERCOMPL_OFFSET 0xba8 +#define GC_USB_DOEPINT5_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT5_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT5_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT5_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT5_EPDISBLD_OFFSET 0xba8 +#define GC_USB_DOEPINT5_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT5_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT5_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT5_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT5_AHBERR_OFFSET 0xba8 +#define GC_USB_DOEPINT5_SETUP_LSB 0x3 +#define GC_USB_DOEPINT5_SETUP_MASK 0x8 +#define GC_USB_DOEPINT5_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT5_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT5_SETUP_OFFSET 0xba8 +#define GC_USB_DOEPINT5_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT5_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT5_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT5_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT5_OUTTKNEPDIS_OFFSET 0xba8 +#define GC_USB_DOEPINT5_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT5_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT5_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT5_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT5_STSPHSERCVD_OFFSET 0xba8 +#define GC_USB_DOEPINT5_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT5_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT5_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT5_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT5_BACK2BACKSETUP_OFFSET 0xba8 +#define GC_USB_DOEPINT5_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT5_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT5_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT5_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT5_OUTPKTERR_OFFSET 0xba8 +#define GC_USB_DOEPINT5_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT5_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT5_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT5_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT5_BNAINTR_OFFSET 0xba8 +#define GC_USB_DOEPINT5_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT5_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT5_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT5_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT5_PKTDRPSTS_OFFSET 0xba8 +#define GC_USB_DOEPINT5_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT5_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT5_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT5_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT5_BBLEERR_OFFSET 0xba8 +#define GC_USB_DOEPINT5_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT5_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT5_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT5_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT5_NAKINTRPT_OFFSET 0xba8 +#define GC_USB_DOEPINT5_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT5_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT5_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT5_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT5_NYETINTRPT_OFFSET 0xba8 +#define GC_USB_DOEPINT5_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT5_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT5_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT5_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT5_STUPPKTRCVD_OFFSET 0xba8 +#define GC_USB_DOEPTSIZ5_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ5_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ5_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ5_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ5_XFERSIZE_OFFSET 0xbb0 +#define GC_USB_DOEPTSIZ5_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ5_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ5_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ5_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ5_PKTCNT_OFFSET 0xbb0 +#define GC_USB_DOEPTSIZ5_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ5_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ5_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ5_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ5_RXDPID_OFFSET 0xbb0 +#define GC_USB_DOEPDMA5_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA5_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA5_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA5_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA5_DMAADDR_OFFSET 0xbb4 +#define GC_USB_DOEPDMAB5_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB5_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB5_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB5_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB5_DMABUFFERADDR_OFFSET 0xbbc +#define GC_USB_DOEPCTL6_MPS_LSB 0x0 +#define GC_USB_DOEPCTL6_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL6_MPS_SIZE 0xb +#define GC_USB_DOEPCTL6_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_MPS_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL6_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL6_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL6_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_USBACTEP_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_DPID_LSB 0x10 +#define GC_USB_DOEPCTL6_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL6_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL6_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_DPID_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL6_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL6_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL6_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_NAKSTS_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL6_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL6_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL6_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_EPTYPE_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_SNP_LSB 0x14 +#define GC_USB_DOEPCTL6_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL6_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL6_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_SNP_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_STALL_LSB 0x15 +#define GC_USB_DOEPCTL6_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL6_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL6_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_STALL_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL6_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL6_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL6_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_CNAK_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL6_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL6_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL6_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_SNAK_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL6_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL6_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL6_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_SETD0PID_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL6_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL6_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL6_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_SETD1PID_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL6_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL6_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL6_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_EPDIS_OFFSET 0xbc0 +#define GC_USB_DOEPCTL6_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL6_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL6_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL6_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL6_EPENA_OFFSET 0xbc0 +#define GC_USB_DOEPINT6_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT6_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT6_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT6_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT6_XFERCOMPL_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT6_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT6_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT6_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT6_EPDISBLD_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT6_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT6_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT6_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT6_AHBERR_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_SETUP_LSB 0x3 +#define GC_USB_DOEPINT6_SETUP_MASK 0x8 +#define GC_USB_DOEPINT6_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT6_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT6_SETUP_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT6_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT6_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT6_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT6_OUTTKNEPDIS_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT6_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT6_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT6_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT6_STSPHSERCVD_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT6_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT6_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT6_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT6_BACK2BACKSETUP_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT6_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT6_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT6_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT6_OUTPKTERR_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT6_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT6_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT6_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT6_BNAINTR_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT6_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT6_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT6_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT6_PKTDRPSTS_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT6_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT6_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT6_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT6_BBLEERR_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT6_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT6_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT6_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT6_NAKINTRPT_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT6_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT6_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT6_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT6_NYETINTRPT_OFFSET 0xbc8 +#define GC_USB_DOEPINT6_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT6_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT6_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT6_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT6_STUPPKTRCVD_OFFSET 0xbc8 +#define GC_USB_DOEPTSIZ6_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ6_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ6_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ6_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ6_XFERSIZE_OFFSET 0xbd0 +#define GC_USB_DOEPTSIZ6_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ6_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ6_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ6_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ6_PKTCNT_OFFSET 0xbd0 +#define GC_USB_DOEPTSIZ6_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ6_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ6_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ6_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ6_RXDPID_OFFSET 0xbd0 +#define GC_USB_DOEPDMA6_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA6_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA6_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA6_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA6_DMAADDR_OFFSET 0xbd4 +#define GC_USB_DOEPDMAB6_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB6_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB6_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB6_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB6_DMABUFFERADDR_OFFSET 0xbdc +#define GC_USB_DOEPCTL7_MPS_LSB 0x0 +#define GC_USB_DOEPCTL7_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL7_MPS_SIZE 0xb +#define GC_USB_DOEPCTL7_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_MPS_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL7_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL7_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL7_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_USBACTEP_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_DPID_LSB 0x10 +#define GC_USB_DOEPCTL7_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL7_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL7_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_DPID_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL7_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL7_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL7_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_NAKSTS_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL7_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL7_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL7_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_EPTYPE_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_SNP_LSB 0x14 +#define GC_USB_DOEPCTL7_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL7_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL7_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_SNP_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_STALL_LSB 0x15 +#define GC_USB_DOEPCTL7_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL7_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL7_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_STALL_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL7_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL7_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL7_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_CNAK_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL7_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL7_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL7_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_SNAK_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL7_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL7_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL7_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_SETD0PID_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL7_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL7_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL7_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_SETD1PID_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL7_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL7_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL7_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_EPDIS_OFFSET 0xbe0 +#define GC_USB_DOEPCTL7_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL7_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL7_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL7_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL7_EPENA_OFFSET 0xbe0 +#define GC_USB_DOEPINT7_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT7_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT7_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT7_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT7_XFERCOMPL_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT7_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT7_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT7_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT7_EPDISBLD_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT7_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT7_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT7_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT7_AHBERR_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_SETUP_LSB 0x3 +#define GC_USB_DOEPINT7_SETUP_MASK 0x8 +#define GC_USB_DOEPINT7_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT7_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT7_SETUP_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT7_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT7_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT7_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT7_OUTTKNEPDIS_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT7_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT7_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT7_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT7_STSPHSERCVD_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT7_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT7_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT7_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT7_BACK2BACKSETUP_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT7_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT7_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT7_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT7_OUTPKTERR_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT7_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT7_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT7_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT7_BNAINTR_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT7_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT7_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT7_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT7_PKTDRPSTS_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT7_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT7_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT7_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT7_BBLEERR_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT7_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT7_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT7_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT7_NAKINTRPT_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT7_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT7_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT7_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT7_NYETINTRPT_OFFSET 0xbe8 +#define GC_USB_DOEPINT7_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT7_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT7_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT7_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT7_STUPPKTRCVD_OFFSET 0xbe8 +#define GC_USB_DOEPTSIZ7_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ7_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ7_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ7_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ7_XFERSIZE_OFFSET 0xbf0 +#define GC_USB_DOEPTSIZ7_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ7_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ7_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ7_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ7_PKTCNT_OFFSET 0xbf0 +#define GC_USB_DOEPTSIZ7_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ7_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ7_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ7_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ7_RXDPID_OFFSET 0xbf0 +#define GC_USB_DOEPDMA7_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA7_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA7_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA7_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA7_DMAADDR_OFFSET 0xbf4 +#define GC_USB_DOEPDMAB7_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB7_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB7_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB7_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB7_DMABUFFERADDR_OFFSET 0xbfc +#define GC_USB_DOEPCTL8_MPS_LSB 0x0 +#define GC_USB_DOEPCTL8_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL8_MPS_SIZE 0xb +#define GC_USB_DOEPCTL8_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_MPS_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL8_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL8_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL8_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_USBACTEP_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_DPID_LSB 0x10 +#define GC_USB_DOEPCTL8_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL8_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL8_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_DPID_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL8_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL8_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL8_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_NAKSTS_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL8_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL8_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL8_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_EPTYPE_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_SNP_LSB 0x14 +#define GC_USB_DOEPCTL8_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL8_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL8_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_SNP_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_STALL_LSB 0x15 +#define GC_USB_DOEPCTL8_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL8_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL8_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_STALL_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL8_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL8_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL8_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_CNAK_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL8_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL8_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL8_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_SNAK_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL8_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL8_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL8_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_SETD0PID_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL8_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL8_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL8_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_SETD1PID_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL8_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL8_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL8_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_EPDIS_OFFSET 0xc00 +#define GC_USB_DOEPCTL8_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL8_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL8_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL8_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL8_EPENA_OFFSET 0xc00 +#define GC_USB_DOEPINT8_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT8_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT8_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT8_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT8_XFERCOMPL_OFFSET 0xc08 +#define GC_USB_DOEPINT8_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT8_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT8_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT8_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT8_EPDISBLD_OFFSET 0xc08 +#define GC_USB_DOEPINT8_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT8_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT8_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT8_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT8_AHBERR_OFFSET 0xc08 +#define GC_USB_DOEPINT8_SETUP_LSB 0x3 +#define GC_USB_DOEPINT8_SETUP_MASK 0x8 +#define GC_USB_DOEPINT8_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT8_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT8_SETUP_OFFSET 0xc08 +#define GC_USB_DOEPINT8_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT8_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT8_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT8_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT8_OUTTKNEPDIS_OFFSET 0xc08 +#define GC_USB_DOEPINT8_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT8_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT8_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT8_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT8_STSPHSERCVD_OFFSET 0xc08 +#define GC_USB_DOEPINT8_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT8_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT8_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT8_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT8_BACK2BACKSETUP_OFFSET 0xc08 +#define GC_USB_DOEPINT8_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT8_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT8_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT8_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT8_OUTPKTERR_OFFSET 0xc08 +#define GC_USB_DOEPINT8_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT8_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT8_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT8_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT8_BNAINTR_OFFSET 0xc08 +#define GC_USB_DOEPINT8_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT8_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT8_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT8_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT8_PKTDRPSTS_OFFSET 0xc08 +#define GC_USB_DOEPINT8_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT8_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT8_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT8_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT8_BBLEERR_OFFSET 0xc08 +#define GC_USB_DOEPINT8_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT8_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT8_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT8_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT8_NAKINTRPT_OFFSET 0xc08 +#define GC_USB_DOEPINT8_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT8_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT8_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT8_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT8_NYETINTRPT_OFFSET 0xc08 +#define GC_USB_DOEPINT8_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT8_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT8_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT8_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT8_STUPPKTRCVD_OFFSET 0xc08 +#define GC_USB_DOEPTSIZ8_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ8_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ8_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ8_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ8_XFERSIZE_OFFSET 0xc10 +#define GC_USB_DOEPTSIZ8_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ8_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ8_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ8_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ8_PKTCNT_OFFSET 0xc10 +#define GC_USB_DOEPTSIZ8_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ8_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ8_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ8_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ8_RXDPID_OFFSET 0xc10 +#define GC_USB_DOEPDMA8_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA8_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA8_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA8_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA8_DMAADDR_OFFSET 0xc14 +#define GC_USB_DOEPDMAB8_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB8_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB8_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB8_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB8_DMABUFFERADDR_OFFSET 0xc1c +#define GC_USB_DOEPCTL9_MPS_LSB 0x0 +#define GC_USB_DOEPCTL9_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL9_MPS_SIZE 0xb +#define GC_USB_DOEPCTL9_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_MPS_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL9_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL9_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL9_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_USBACTEP_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_DPID_LSB 0x10 +#define GC_USB_DOEPCTL9_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL9_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL9_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_DPID_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL9_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL9_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL9_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_NAKSTS_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL9_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL9_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL9_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_EPTYPE_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_SNP_LSB 0x14 +#define GC_USB_DOEPCTL9_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL9_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL9_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_SNP_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_STALL_LSB 0x15 +#define GC_USB_DOEPCTL9_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL9_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL9_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_STALL_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL9_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL9_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL9_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_CNAK_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL9_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL9_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL9_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_SNAK_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL9_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL9_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL9_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_SETD0PID_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL9_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL9_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL9_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_SETD1PID_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL9_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL9_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL9_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_EPDIS_OFFSET 0xc20 +#define GC_USB_DOEPCTL9_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL9_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL9_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL9_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL9_EPENA_OFFSET 0xc20 +#define GC_USB_DOEPINT9_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT9_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT9_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT9_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT9_XFERCOMPL_OFFSET 0xc28 +#define GC_USB_DOEPINT9_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT9_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT9_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT9_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT9_EPDISBLD_OFFSET 0xc28 +#define GC_USB_DOEPINT9_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT9_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT9_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT9_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT9_AHBERR_OFFSET 0xc28 +#define GC_USB_DOEPINT9_SETUP_LSB 0x3 +#define GC_USB_DOEPINT9_SETUP_MASK 0x8 +#define GC_USB_DOEPINT9_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT9_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT9_SETUP_OFFSET 0xc28 +#define GC_USB_DOEPINT9_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT9_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT9_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT9_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT9_OUTTKNEPDIS_OFFSET 0xc28 +#define GC_USB_DOEPINT9_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT9_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT9_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT9_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT9_STSPHSERCVD_OFFSET 0xc28 +#define GC_USB_DOEPINT9_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT9_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT9_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT9_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT9_BACK2BACKSETUP_OFFSET 0xc28 +#define GC_USB_DOEPINT9_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT9_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT9_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT9_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT9_OUTPKTERR_OFFSET 0xc28 +#define GC_USB_DOEPINT9_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT9_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT9_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT9_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT9_BNAINTR_OFFSET 0xc28 +#define GC_USB_DOEPINT9_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT9_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT9_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT9_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT9_PKTDRPSTS_OFFSET 0xc28 +#define GC_USB_DOEPINT9_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT9_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT9_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT9_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT9_BBLEERR_OFFSET 0xc28 +#define GC_USB_DOEPINT9_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT9_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT9_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT9_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT9_NAKINTRPT_OFFSET 0xc28 +#define GC_USB_DOEPINT9_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT9_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT9_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT9_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT9_NYETINTRPT_OFFSET 0xc28 +#define GC_USB_DOEPINT9_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT9_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT9_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT9_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT9_STUPPKTRCVD_OFFSET 0xc28 +#define GC_USB_DOEPTSIZ9_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ9_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ9_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ9_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ9_XFERSIZE_OFFSET 0xc30 +#define GC_USB_DOEPTSIZ9_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ9_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ9_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ9_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ9_PKTCNT_OFFSET 0xc30 +#define GC_USB_DOEPTSIZ9_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ9_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ9_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ9_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ9_RXDPID_OFFSET 0xc30 +#define GC_USB_DOEPDMA9_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA9_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA9_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA9_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA9_DMAADDR_OFFSET 0xc34 +#define GC_USB_DOEPDMAB9_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB9_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB9_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB9_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB9_DMABUFFERADDR_OFFSET 0xc3c +#define GC_USB_DOEPCTL10_MPS_LSB 0x0 +#define GC_USB_DOEPCTL10_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL10_MPS_SIZE 0xb +#define GC_USB_DOEPCTL10_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_MPS_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL10_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL10_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL10_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_USBACTEP_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_DPID_LSB 0x10 +#define GC_USB_DOEPCTL10_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL10_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL10_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_DPID_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL10_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL10_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL10_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_NAKSTS_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL10_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL10_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL10_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_EPTYPE_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_SNP_LSB 0x14 +#define GC_USB_DOEPCTL10_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL10_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL10_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_SNP_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_STALL_LSB 0x15 +#define GC_USB_DOEPCTL10_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL10_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL10_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_STALL_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL10_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL10_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL10_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_CNAK_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL10_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL10_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL10_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_SNAK_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL10_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL10_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL10_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_SETD0PID_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL10_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL10_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL10_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_SETD1PID_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL10_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL10_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL10_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_EPDIS_OFFSET 0xc40 +#define GC_USB_DOEPCTL10_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL10_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL10_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL10_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL10_EPENA_OFFSET 0xc40 +#define GC_USB_DOEPINT10_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT10_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT10_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT10_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT10_XFERCOMPL_OFFSET 0xc48 +#define GC_USB_DOEPINT10_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT10_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT10_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT10_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT10_EPDISBLD_OFFSET 0xc48 +#define GC_USB_DOEPINT10_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT10_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT10_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT10_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT10_AHBERR_OFFSET 0xc48 +#define GC_USB_DOEPINT10_SETUP_LSB 0x3 +#define GC_USB_DOEPINT10_SETUP_MASK 0x8 +#define GC_USB_DOEPINT10_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT10_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT10_SETUP_OFFSET 0xc48 +#define GC_USB_DOEPINT10_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT10_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT10_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT10_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT10_OUTTKNEPDIS_OFFSET 0xc48 +#define GC_USB_DOEPINT10_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT10_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT10_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT10_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT10_STSPHSERCVD_OFFSET 0xc48 +#define GC_USB_DOEPINT10_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT10_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT10_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT10_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT10_BACK2BACKSETUP_OFFSET 0xc48 +#define GC_USB_DOEPINT10_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT10_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT10_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT10_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT10_OUTPKTERR_OFFSET 0xc48 +#define GC_USB_DOEPINT10_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT10_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT10_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT10_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT10_BNAINTR_OFFSET 0xc48 +#define GC_USB_DOEPINT10_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT10_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT10_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT10_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT10_PKTDRPSTS_OFFSET 0xc48 +#define GC_USB_DOEPINT10_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT10_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT10_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT10_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT10_BBLEERR_OFFSET 0xc48 +#define GC_USB_DOEPINT10_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT10_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT10_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT10_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT10_NAKINTRPT_OFFSET 0xc48 +#define GC_USB_DOEPINT10_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT10_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT10_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT10_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT10_NYETINTRPT_OFFSET 0xc48 +#define GC_USB_DOEPINT10_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT10_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT10_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT10_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT10_STUPPKTRCVD_OFFSET 0xc48 +#define GC_USB_DOEPTSIZ10_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ10_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ10_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ10_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ10_XFERSIZE_OFFSET 0xc50 +#define GC_USB_DOEPTSIZ10_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ10_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ10_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ10_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ10_PKTCNT_OFFSET 0xc50 +#define GC_USB_DOEPTSIZ10_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ10_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ10_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ10_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ10_RXDPID_OFFSET 0xc50 +#define GC_USB_DOEPDMA10_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA10_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA10_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA10_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA10_DMAADDR_OFFSET 0xc54 +#define GC_USB_DOEPDMAB10_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB10_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB10_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB10_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB10_DMABUFFERADDR_OFFSET 0xc5c +#define GC_USB_DOEPCTL11_MPS_LSB 0x0 +#define GC_USB_DOEPCTL11_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL11_MPS_SIZE 0xb +#define GC_USB_DOEPCTL11_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_MPS_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL11_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL11_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL11_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_USBACTEP_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_DPID_LSB 0x10 +#define GC_USB_DOEPCTL11_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL11_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL11_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_DPID_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL11_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL11_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL11_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_NAKSTS_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL11_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL11_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL11_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_EPTYPE_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_SNP_LSB 0x14 +#define GC_USB_DOEPCTL11_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL11_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL11_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_SNP_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_STALL_LSB 0x15 +#define GC_USB_DOEPCTL11_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL11_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL11_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_STALL_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL11_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL11_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL11_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_CNAK_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL11_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL11_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL11_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_SNAK_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL11_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL11_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL11_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_SETD0PID_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL11_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL11_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL11_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_SETD1PID_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL11_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL11_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL11_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_EPDIS_OFFSET 0xc60 +#define GC_USB_DOEPCTL11_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL11_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL11_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL11_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL11_EPENA_OFFSET 0xc60 +#define GC_USB_DOEPINT11_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT11_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT11_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT11_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT11_XFERCOMPL_OFFSET 0xc68 +#define GC_USB_DOEPINT11_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT11_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT11_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT11_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT11_EPDISBLD_OFFSET 0xc68 +#define GC_USB_DOEPINT11_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT11_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT11_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT11_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT11_AHBERR_OFFSET 0xc68 +#define GC_USB_DOEPINT11_SETUP_LSB 0x3 +#define GC_USB_DOEPINT11_SETUP_MASK 0x8 +#define GC_USB_DOEPINT11_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT11_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT11_SETUP_OFFSET 0xc68 +#define GC_USB_DOEPINT11_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT11_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT11_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT11_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT11_OUTTKNEPDIS_OFFSET 0xc68 +#define GC_USB_DOEPINT11_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT11_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT11_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT11_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT11_STSPHSERCVD_OFFSET 0xc68 +#define GC_USB_DOEPINT11_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT11_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT11_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT11_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT11_BACK2BACKSETUP_OFFSET 0xc68 +#define GC_USB_DOEPINT11_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT11_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT11_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT11_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT11_OUTPKTERR_OFFSET 0xc68 +#define GC_USB_DOEPINT11_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT11_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT11_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT11_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT11_BNAINTR_OFFSET 0xc68 +#define GC_USB_DOEPINT11_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT11_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT11_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT11_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT11_PKTDRPSTS_OFFSET 0xc68 +#define GC_USB_DOEPINT11_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT11_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT11_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT11_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT11_BBLEERR_OFFSET 0xc68 +#define GC_USB_DOEPINT11_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT11_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT11_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT11_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT11_NAKINTRPT_OFFSET 0xc68 +#define GC_USB_DOEPINT11_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT11_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT11_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT11_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT11_NYETINTRPT_OFFSET 0xc68 +#define GC_USB_DOEPINT11_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT11_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT11_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT11_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT11_STUPPKTRCVD_OFFSET 0xc68 +#define GC_USB_DOEPTSIZ11_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ11_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ11_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ11_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ11_XFERSIZE_OFFSET 0xc70 +#define GC_USB_DOEPTSIZ11_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ11_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ11_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ11_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ11_PKTCNT_OFFSET 0xc70 +#define GC_USB_DOEPTSIZ11_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ11_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ11_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ11_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ11_RXDPID_OFFSET 0xc70 +#define GC_USB_DOEPDMA11_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA11_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA11_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA11_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA11_DMAADDR_OFFSET 0xc74 +#define GC_USB_DOEPDMAB11_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB11_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB11_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB11_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB11_DMABUFFERADDR_OFFSET 0xc7c +#define GC_USB_DOEPCTL12_MPS_LSB 0x0 +#define GC_USB_DOEPCTL12_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL12_MPS_SIZE 0xb +#define GC_USB_DOEPCTL12_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_MPS_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL12_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL12_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL12_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_USBACTEP_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_DPID_LSB 0x10 +#define GC_USB_DOEPCTL12_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL12_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL12_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_DPID_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL12_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL12_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL12_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_NAKSTS_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL12_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL12_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL12_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_EPTYPE_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_SNP_LSB 0x14 +#define GC_USB_DOEPCTL12_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL12_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL12_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_SNP_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_STALL_LSB 0x15 +#define GC_USB_DOEPCTL12_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL12_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL12_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_STALL_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL12_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL12_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL12_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_CNAK_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL12_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL12_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL12_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_SNAK_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL12_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL12_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL12_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_SETD0PID_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL12_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL12_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL12_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_SETD1PID_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL12_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL12_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL12_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_EPDIS_OFFSET 0xc80 +#define GC_USB_DOEPCTL12_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL12_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL12_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL12_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL12_EPENA_OFFSET 0xc80 +#define GC_USB_DOEPINT12_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT12_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT12_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT12_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT12_XFERCOMPL_OFFSET 0xc88 +#define GC_USB_DOEPINT12_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT12_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT12_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT12_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT12_EPDISBLD_OFFSET 0xc88 +#define GC_USB_DOEPINT12_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT12_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT12_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT12_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT12_AHBERR_OFFSET 0xc88 +#define GC_USB_DOEPINT12_SETUP_LSB 0x3 +#define GC_USB_DOEPINT12_SETUP_MASK 0x8 +#define GC_USB_DOEPINT12_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT12_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT12_SETUP_OFFSET 0xc88 +#define GC_USB_DOEPINT12_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT12_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT12_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT12_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT12_OUTTKNEPDIS_OFFSET 0xc88 +#define GC_USB_DOEPINT12_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT12_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT12_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT12_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT12_STSPHSERCVD_OFFSET 0xc88 +#define GC_USB_DOEPINT12_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT12_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT12_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT12_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT12_BACK2BACKSETUP_OFFSET 0xc88 +#define GC_USB_DOEPINT12_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT12_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT12_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT12_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT12_OUTPKTERR_OFFSET 0xc88 +#define GC_USB_DOEPINT12_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT12_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT12_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT12_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT12_BNAINTR_OFFSET 0xc88 +#define GC_USB_DOEPINT12_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT12_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT12_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT12_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT12_PKTDRPSTS_OFFSET 0xc88 +#define GC_USB_DOEPINT12_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT12_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT12_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT12_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT12_BBLEERR_OFFSET 0xc88 +#define GC_USB_DOEPINT12_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT12_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT12_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT12_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT12_NAKINTRPT_OFFSET 0xc88 +#define GC_USB_DOEPINT12_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT12_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT12_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT12_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT12_NYETINTRPT_OFFSET 0xc88 +#define GC_USB_DOEPINT12_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT12_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT12_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT12_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT12_STUPPKTRCVD_OFFSET 0xc88 +#define GC_USB_DOEPTSIZ12_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ12_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ12_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ12_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ12_XFERSIZE_OFFSET 0xc90 +#define GC_USB_DOEPTSIZ12_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ12_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ12_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ12_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ12_PKTCNT_OFFSET 0xc90 +#define GC_USB_DOEPTSIZ12_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ12_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ12_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ12_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ12_RXDPID_OFFSET 0xc90 +#define GC_USB_DOEPDMA12_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA12_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA12_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA12_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA12_DMAADDR_OFFSET 0xc94 +#define GC_USB_DOEPDMAB12_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB12_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB12_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB12_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB12_DMABUFFERADDR_OFFSET 0xc9c +#define GC_USB_DOEPCTL13_MPS_LSB 0x0 +#define GC_USB_DOEPCTL13_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL13_MPS_SIZE 0xb +#define GC_USB_DOEPCTL13_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_MPS_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL13_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL13_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL13_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_USBACTEP_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_DPID_LSB 0x10 +#define GC_USB_DOEPCTL13_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL13_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL13_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_DPID_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL13_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL13_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL13_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_NAKSTS_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL13_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL13_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL13_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_EPTYPE_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_SNP_LSB 0x14 +#define GC_USB_DOEPCTL13_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL13_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL13_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_SNP_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_STALL_LSB 0x15 +#define GC_USB_DOEPCTL13_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL13_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL13_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_STALL_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL13_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL13_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL13_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_CNAK_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL13_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL13_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL13_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_SNAK_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL13_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL13_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL13_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_SETD0PID_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL13_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL13_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL13_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_SETD1PID_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL13_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL13_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL13_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_EPDIS_OFFSET 0xca0 +#define GC_USB_DOEPCTL13_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL13_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL13_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL13_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL13_EPENA_OFFSET 0xca0 +#define GC_USB_DOEPINT13_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT13_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT13_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT13_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT13_XFERCOMPL_OFFSET 0xca8 +#define GC_USB_DOEPINT13_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT13_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT13_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT13_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT13_EPDISBLD_OFFSET 0xca8 +#define GC_USB_DOEPINT13_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT13_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT13_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT13_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT13_AHBERR_OFFSET 0xca8 +#define GC_USB_DOEPINT13_SETUP_LSB 0x3 +#define GC_USB_DOEPINT13_SETUP_MASK 0x8 +#define GC_USB_DOEPINT13_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT13_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT13_SETUP_OFFSET 0xca8 +#define GC_USB_DOEPINT13_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT13_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT13_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT13_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT13_OUTTKNEPDIS_OFFSET 0xca8 +#define GC_USB_DOEPINT13_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT13_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT13_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT13_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT13_STSPHSERCVD_OFFSET 0xca8 +#define GC_USB_DOEPINT13_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT13_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT13_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT13_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT13_BACK2BACKSETUP_OFFSET 0xca8 +#define GC_USB_DOEPINT13_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT13_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT13_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT13_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT13_OUTPKTERR_OFFSET 0xca8 +#define GC_USB_DOEPINT13_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT13_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT13_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT13_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT13_BNAINTR_OFFSET 0xca8 +#define GC_USB_DOEPINT13_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT13_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT13_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT13_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT13_PKTDRPSTS_OFFSET 0xca8 +#define GC_USB_DOEPINT13_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT13_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT13_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT13_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT13_BBLEERR_OFFSET 0xca8 +#define GC_USB_DOEPINT13_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT13_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT13_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT13_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT13_NAKINTRPT_OFFSET 0xca8 +#define GC_USB_DOEPINT13_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT13_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT13_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT13_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT13_NYETINTRPT_OFFSET 0xca8 +#define GC_USB_DOEPINT13_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT13_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT13_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT13_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT13_STUPPKTRCVD_OFFSET 0xca8 +#define GC_USB_DOEPTSIZ13_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ13_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ13_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ13_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ13_XFERSIZE_OFFSET 0xcb0 +#define GC_USB_DOEPTSIZ13_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ13_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ13_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ13_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ13_PKTCNT_OFFSET 0xcb0 +#define GC_USB_DOEPTSIZ13_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ13_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ13_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ13_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ13_RXDPID_OFFSET 0xcb0 +#define GC_USB_DOEPDMA13_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA13_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA13_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA13_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA13_DMAADDR_OFFSET 0xcb4 +#define GC_USB_DOEPDMAB13_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB13_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB13_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB13_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB13_DMABUFFERADDR_OFFSET 0xcbc +#define GC_USB_DOEPCTL14_MPS_LSB 0x0 +#define GC_USB_DOEPCTL14_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL14_MPS_SIZE 0xb +#define GC_USB_DOEPCTL14_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_MPS_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL14_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL14_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL14_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_USBACTEP_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_DPID_LSB 0x10 +#define GC_USB_DOEPCTL14_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL14_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL14_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_DPID_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL14_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL14_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL14_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_NAKSTS_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL14_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL14_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL14_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_EPTYPE_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_SNP_LSB 0x14 +#define GC_USB_DOEPCTL14_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL14_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL14_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_SNP_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_STALL_LSB 0x15 +#define GC_USB_DOEPCTL14_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL14_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL14_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_STALL_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL14_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL14_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL14_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_CNAK_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL14_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL14_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL14_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_SNAK_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL14_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL14_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL14_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_SETD0PID_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL14_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL14_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL14_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_SETD1PID_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL14_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL14_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL14_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_EPDIS_OFFSET 0xcc0 +#define GC_USB_DOEPCTL14_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL14_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL14_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL14_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL14_EPENA_OFFSET 0xcc0 +#define GC_USB_DOEPINT14_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT14_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT14_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT14_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT14_XFERCOMPL_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT14_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT14_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT14_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT14_EPDISBLD_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT14_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT14_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT14_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT14_AHBERR_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_SETUP_LSB 0x3 +#define GC_USB_DOEPINT14_SETUP_MASK 0x8 +#define GC_USB_DOEPINT14_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT14_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT14_SETUP_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT14_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT14_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT14_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT14_OUTTKNEPDIS_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT14_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT14_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT14_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT14_STSPHSERCVD_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT14_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT14_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT14_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT14_BACK2BACKSETUP_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT14_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT14_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT14_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT14_OUTPKTERR_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT14_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT14_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT14_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT14_BNAINTR_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT14_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT14_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT14_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT14_PKTDRPSTS_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT14_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT14_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT14_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT14_BBLEERR_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT14_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT14_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT14_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT14_NAKINTRPT_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT14_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT14_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT14_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT14_NYETINTRPT_OFFSET 0xcc8 +#define GC_USB_DOEPINT14_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT14_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT14_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT14_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT14_STUPPKTRCVD_OFFSET 0xcc8 +#define GC_USB_DOEPTSIZ14_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ14_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ14_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ14_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ14_XFERSIZE_OFFSET 0xcd0 +#define GC_USB_DOEPTSIZ14_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ14_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ14_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ14_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ14_PKTCNT_OFFSET 0xcd0 +#define GC_USB_DOEPTSIZ14_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ14_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ14_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ14_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ14_RXDPID_OFFSET 0xcd0 +#define GC_USB_DOEPDMA14_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA14_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA14_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA14_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA14_DMAADDR_OFFSET 0xcd4 +#define GC_USB_DOEPDMAB14_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB14_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB14_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB14_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB14_DMABUFFERADDR_OFFSET 0xcdc +#define GC_USB_DOEPCTL15_MPS_LSB 0x0 +#define GC_USB_DOEPCTL15_MPS_MASK 0x7ff +#define GC_USB_DOEPCTL15_MPS_SIZE 0xb +#define GC_USB_DOEPCTL15_MPS_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_MPS_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_USBACTEP_LSB 0xf +#define GC_USB_DOEPCTL15_USBACTEP_MASK 0x8000 +#define GC_USB_DOEPCTL15_USBACTEP_SIZE 0x1 +#define GC_USB_DOEPCTL15_USBACTEP_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_USBACTEP_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_DPID_LSB 0x10 +#define GC_USB_DOEPCTL15_DPID_MASK 0x10000 +#define GC_USB_DOEPCTL15_DPID_SIZE 0x1 +#define GC_USB_DOEPCTL15_DPID_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_DPID_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_NAKSTS_LSB 0x11 +#define GC_USB_DOEPCTL15_NAKSTS_MASK 0x20000 +#define GC_USB_DOEPCTL15_NAKSTS_SIZE 0x1 +#define GC_USB_DOEPCTL15_NAKSTS_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_NAKSTS_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_EPTYPE_LSB 0x12 +#define GC_USB_DOEPCTL15_EPTYPE_MASK 0xc0000 +#define GC_USB_DOEPCTL15_EPTYPE_SIZE 0x2 +#define GC_USB_DOEPCTL15_EPTYPE_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_EPTYPE_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_SNP_LSB 0x14 +#define GC_USB_DOEPCTL15_SNP_MASK 0x100000 +#define GC_USB_DOEPCTL15_SNP_SIZE 0x1 +#define GC_USB_DOEPCTL15_SNP_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_SNP_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_STALL_LSB 0x15 +#define GC_USB_DOEPCTL15_STALL_MASK 0x200000 +#define GC_USB_DOEPCTL15_STALL_SIZE 0x1 +#define GC_USB_DOEPCTL15_STALL_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_STALL_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_CNAK_LSB 0x1a +#define GC_USB_DOEPCTL15_CNAK_MASK 0x4000000 +#define GC_USB_DOEPCTL15_CNAK_SIZE 0x1 +#define GC_USB_DOEPCTL15_CNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_CNAK_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_SNAK_LSB 0x1b +#define GC_USB_DOEPCTL15_SNAK_MASK 0x8000000 +#define GC_USB_DOEPCTL15_SNAK_SIZE 0x1 +#define GC_USB_DOEPCTL15_SNAK_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_SNAK_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_SETD0PID_LSB 0x1c +#define GC_USB_DOEPCTL15_SETD0PID_MASK 0x10000000 +#define GC_USB_DOEPCTL15_SETD0PID_SIZE 0x1 +#define GC_USB_DOEPCTL15_SETD0PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_SETD0PID_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_SETD1PID_LSB 0x1d +#define GC_USB_DOEPCTL15_SETD1PID_MASK 0x20000000 +#define GC_USB_DOEPCTL15_SETD1PID_SIZE 0x1 +#define GC_USB_DOEPCTL15_SETD1PID_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_SETD1PID_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_EPDIS_LSB 0x1e +#define GC_USB_DOEPCTL15_EPDIS_MASK 0x40000000 +#define GC_USB_DOEPCTL15_EPDIS_SIZE 0x1 +#define GC_USB_DOEPCTL15_EPDIS_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_EPDIS_OFFSET 0xce0 +#define GC_USB_DOEPCTL15_EPENA_LSB 0x1f +#define GC_USB_DOEPCTL15_EPENA_MASK 0x80000000 +#define GC_USB_DOEPCTL15_EPENA_SIZE 0x1 +#define GC_USB_DOEPCTL15_EPENA_DEFAULT 0x0 +#define GC_USB_DOEPCTL15_EPENA_OFFSET 0xce0 +#define GC_USB_DOEPINT15_XFERCOMPL_LSB 0x0 +#define GC_USB_DOEPINT15_XFERCOMPL_MASK 0x1 +#define GC_USB_DOEPINT15_XFERCOMPL_SIZE 0x1 +#define GC_USB_DOEPINT15_XFERCOMPL_DEFAULT 0x0 +#define GC_USB_DOEPINT15_XFERCOMPL_OFFSET 0xce8 +#define GC_USB_DOEPINT15_EPDISBLD_LSB 0x1 +#define GC_USB_DOEPINT15_EPDISBLD_MASK 0x2 +#define GC_USB_DOEPINT15_EPDISBLD_SIZE 0x1 +#define GC_USB_DOEPINT15_EPDISBLD_DEFAULT 0x0 +#define GC_USB_DOEPINT15_EPDISBLD_OFFSET 0xce8 +#define GC_USB_DOEPINT15_AHBERR_LSB 0x2 +#define GC_USB_DOEPINT15_AHBERR_MASK 0x4 +#define GC_USB_DOEPINT15_AHBERR_SIZE 0x1 +#define GC_USB_DOEPINT15_AHBERR_DEFAULT 0x0 +#define GC_USB_DOEPINT15_AHBERR_OFFSET 0xce8 +#define GC_USB_DOEPINT15_SETUP_LSB 0x3 +#define GC_USB_DOEPINT15_SETUP_MASK 0x8 +#define GC_USB_DOEPINT15_SETUP_SIZE 0x1 +#define GC_USB_DOEPINT15_SETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT15_SETUP_OFFSET 0xce8 +#define GC_USB_DOEPINT15_OUTTKNEPDIS_LSB 0x4 +#define GC_USB_DOEPINT15_OUTTKNEPDIS_MASK 0x10 +#define GC_USB_DOEPINT15_OUTTKNEPDIS_SIZE 0x1 +#define GC_USB_DOEPINT15_OUTTKNEPDIS_DEFAULT 0x0 +#define GC_USB_DOEPINT15_OUTTKNEPDIS_OFFSET 0xce8 +#define GC_USB_DOEPINT15_STSPHSERCVD_LSB 0x5 +#define GC_USB_DOEPINT15_STSPHSERCVD_MASK 0x20 +#define GC_USB_DOEPINT15_STSPHSERCVD_SIZE 0x1 +#define GC_USB_DOEPINT15_STSPHSERCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT15_STSPHSERCVD_OFFSET 0xce8 +#define GC_USB_DOEPINT15_BACK2BACKSETUP_LSB 0x6 +#define GC_USB_DOEPINT15_BACK2BACKSETUP_MASK 0x40 +#define GC_USB_DOEPINT15_BACK2BACKSETUP_SIZE 0x1 +#define GC_USB_DOEPINT15_BACK2BACKSETUP_DEFAULT 0x0 +#define GC_USB_DOEPINT15_BACK2BACKSETUP_OFFSET 0xce8 +#define GC_USB_DOEPINT15_OUTPKTERR_LSB 0x8 +#define GC_USB_DOEPINT15_OUTPKTERR_MASK 0x100 +#define GC_USB_DOEPINT15_OUTPKTERR_SIZE 0x1 +#define GC_USB_DOEPINT15_OUTPKTERR_DEFAULT 0x0 +#define GC_USB_DOEPINT15_OUTPKTERR_OFFSET 0xce8 +#define GC_USB_DOEPINT15_BNAINTR_LSB 0x9 +#define GC_USB_DOEPINT15_BNAINTR_MASK 0x200 +#define GC_USB_DOEPINT15_BNAINTR_SIZE 0x1 +#define GC_USB_DOEPINT15_BNAINTR_DEFAULT 0x0 +#define GC_USB_DOEPINT15_BNAINTR_OFFSET 0xce8 +#define GC_USB_DOEPINT15_PKTDRPSTS_LSB 0xb +#define GC_USB_DOEPINT15_PKTDRPSTS_MASK 0x800 +#define GC_USB_DOEPINT15_PKTDRPSTS_SIZE 0x1 +#define GC_USB_DOEPINT15_PKTDRPSTS_DEFAULT 0x0 +#define GC_USB_DOEPINT15_PKTDRPSTS_OFFSET 0xce8 +#define GC_USB_DOEPINT15_BBLEERR_LSB 0xc +#define GC_USB_DOEPINT15_BBLEERR_MASK 0x1000 +#define GC_USB_DOEPINT15_BBLEERR_SIZE 0x1 +#define GC_USB_DOEPINT15_BBLEERR_DEFAULT 0x0 +#define GC_USB_DOEPINT15_BBLEERR_OFFSET 0xce8 +#define GC_USB_DOEPINT15_NAKINTRPT_LSB 0xd +#define GC_USB_DOEPINT15_NAKINTRPT_MASK 0x2000 +#define GC_USB_DOEPINT15_NAKINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT15_NAKINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT15_NAKINTRPT_OFFSET 0xce8 +#define GC_USB_DOEPINT15_NYETINTRPT_LSB 0xe +#define GC_USB_DOEPINT15_NYETINTRPT_MASK 0x4000 +#define GC_USB_DOEPINT15_NYETINTRPT_SIZE 0x1 +#define GC_USB_DOEPINT15_NYETINTRPT_DEFAULT 0x0 +#define GC_USB_DOEPINT15_NYETINTRPT_OFFSET 0xce8 +#define GC_USB_DOEPINT15_STUPPKTRCVD_LSB 0xf +#define GC_USB_DOEPINT15_STUPPKTRCVD_MASK 0x8000 +#define GC_USB_DOEPINT15_STUPPKTRCVD_SIZE 0x1 +#define GC_USB_DOEPINT15_STUPPKTRCVD_DEFAULT 0x0 +#define GC_USB_DOEPINT15_STUPPKTRCVD_OFFSET 0xce8 +#define GC_USB_DOEPTSIZ15_XFERSIZE_LSB 0x0 +#define GC_USB_DOEPTSIZ15_XFERSIZE_MASK 0x7ffff +#define GC_USB_DOEPTSIZ15_XFERSIZE_SIZE 0x13 +#define GC_USB_DOEPTSIZ15_XFERSIZE_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ15_XFERSIZE_OFFSET 0xcf0 +#define GC_USB_DOEPTSIZ15_PKTCNT_LSB 0x13 +#define GC_USB_DOEPTSIZ15_PKTCNT_MASK 0x1ff80000 +#define GC_USB_DOEPTSIZ15_PKTCNT_SIZE 0xa +#define GC_USB_DOEPTSIZ15_PKTCNT_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ15_PKTCNT_OFFSET 0xcf0 +#define GC_USB_DOEPTSIZ15_RXDPID_LSB 0x1d +#define GC_USB_DOEPTSIZ15_RXDPID_MASK 0x60000000 +#define GC_USB_DOEPTSIZ15_RXDPID_SIZE 0x2 +#define GC_USB_DOEPTSIZ15_RXDPID_DEFAULT 0x0 +#define GC_USB_DOEPTSIZ15_RXDPID_OFFSET 0xcf0 +#define GC_USB_DOEPDMA15_DMAADDR_LSB 0x0 +#define GC_USB_DOEPDMA15_DMAADDR_MASK 0xffffffff +#define GC_USB_DOEPDMA15_DMAADDR_SIZE 0x20 +#define GC_USB_DOEPDMA15_DMAADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMA15_DMAADDR_OFFSET 0xcf4 +#define GC_USB_DOEPDMAB15_DMABUFFERADDR_LSB 0x0 +#define GC_USB_DOEPDMAB15_DMABUFFERADDR_MASK 0xffffffff +#define GC_USB_DOEPDMAB15_DMABUFFERADDR_SIZE 0x20 +#define GC_USB_DOEPDMAB15_DMABUFFERADDR_DEFAULT 0x0 +#define GC_USB_DOEPDMAB15_DMABUFFERADDR_OFFSET 0xcfc +#define GC_USB_PCGCCTL_STOPPCLK_LSB 0x0 +#define GC_USB_PCGCCTL_STOPPCLK_MASK 0x1 +#define GC_USB_PCGCCTL_STOPPCLK_SIZE 0x1 +#define GC_USB_PCGCCTL_STOPPCLK_DEFAULT 0x0 +#define GC_USB_PCGCCTL_STOPPCLK_OFFSET 0xe00 +#define GC_USB_PCGCCTL_GATEHCLK_LSB 0x1 +#define GC_USB_PCGCCTL_GATEHCLK_MASK 0x2 +#define GC_USB_PCGCCTL_GATEHCLK_SIZE 0x1 +#define GC_USB_PCGCCTL_GATEHCLK_DEFAULT 0x0 +#define GC_USB_PCGCCTL_GATEHCLK_OFFSET 0xe00 +#define GC_USB_PCGCCTL_PWRCLMP_LSB 0x2 +#define GC_USB_PCGCCTL_PWRCLMP_MASK 0x4 +#define GC_USB_PCGCCTL_PWRCLMP_SIZE 0x1 +#define GC_USB_PCGCCTL_PWRCLMP_DEFAULT 0x0 +#define GC_USB_PCGCCTL_PWRCLMP_OFFSET 0xe00 +#define GC_USB_PCGCCTL_RSTPDWNMODULE_LSB 0x3 +#define GC_USB_PCGCCTL_RSTPDWNMODULE_MASK 0x8 +#define GC_USB_PCGCCTL_RSTPDWNMODULE_SIZE 0x1 +#define GC_USB_PCGCCTL_RSTPDWNMODULE_DEFAULT 0x0 +#define GC_USB_PCGCCTL_RSTPDWNMODULE_OFFSET 0xe00 +#define GC_USB_PCGCCTL_PHYSLEEP_LSB 0x6 +#define GC_USB_PCGCCTL_PHYSLEEP_MASK 0x40 +#define GC_USB_PCGCCTL_PHYSLEEP_SIZE 0x1 +#define GC_USB_PCGCCTL_PHYSLEEP_DEFAULT 0x0 +#define GC_USB_PCGCCTL_PHYSLEEP_OFFSET 0xe00 +#define GC_USB_PCGCCTL_L1SUSPENDED_LSB 0x7 +#define GC_USB_PCGCCTL_L1SUSPENDED_MASK 0x80 +#define GC_USB_PCGCCTL_L1SUSPENDED_SIZE 0x1 +#define GC_USB_PCGCCTL_L1SUSPENDED_DEFAULT 0x0 +#define GC_USB_PCGCCTL_L1SUSPENDED_OFFSET 0xe00 +#define GC_USB_DFIFO_SIZE 0x1000 #endif /* __CHIP_STM32_USB_DWC_REGISTERS_H */ diff --git a/chip/stm32/usb_dwc_stream.c b/chip/stm32/usb_dwc_stream.c index 2f20d88dda..78e0a4b484 100644 --- a/chip/stm32/usb_dwc_stream.c +++ b/chip/stm32/usb_dwc_stream.c @@ -1,15 +1,14 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "console.h" #include "registers.h" #include "timer.h" #include "usb_dwc_stream.h" #include "util.h" - -#include "console.h" -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) /* * This function tries to shove new bytes from the USB host into the queue for @@ -24,9 +23,8 @@ int rx_stream_handler(struct usb_stream_config const *config) /* If we have some, try to shove them into the queue */ if (rx_count) { - size_t added = QUEUE_ADD_UNITS( - config->producer.queue, config->rx_ram, - rx_count); + size_t added = QUEUE_ADD_UNITS(config->producer.queue, + config->rx_ram, rx_count); if (added != rx_count) { CPRINTF("rx_stream_handler: failed ep%d " "queue %d bytes, accepted %d\n", @@ -60,7 +58,7 @@ int tx_stream_handler(struct usb_stream_config const *config) /* Reset stream */ void usb_stream_event(struct usb_stream_config const *config, - enum usb_ep_event evt) + enum usb_ep_event evt) { if (evt != USB_EVENT_RESET) return; diff --git a/chip/stm32/usb_dwc_stream.h b/chip/stm32/usb_dwc_stream.h index e46e7a929c..bd512f5e9a 100644 --- a/chip/stm32/usb_dwc_stream.h +++ b/chip/stm32/usb_dwc_stream.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,9 +10,9 @@ #include "compile_time_macros.h" #include "consumer.h" #include "hooks.h" -#include "registers.h" #include "producer.h" #include "queue.h" +#include "registers.h" #include "usb_descriptor.h" #include "usb_hw.h" @@ -54,7 +54,6 @@ struct usb_stream_config { extern struct consumer_ops const usb_stream_consumer_ops; extern struct producer_ops const usb_stream_producer_ops; - /* * Convenience macro for defining USB streams and their associated state and * buffers. @@ -92,26 +91,19 @@ extern struct producer_ops const usb_stream_producer_ops; * BUILD_ASSERT(RX_QUEUE.unit_bytes == 1); * BUILD_ASSERT(TX_QUEUE.unit_bytes == 1); */ -#define USB_STREAM_CONFIG_FULL(NAME, \ - INTERFACE, \ - INTERFACE_CLASS, \ - INTERFACE_SUBCLASS, \ - INTERFACE_PROTOCOL, \ - INTERFACE_NAME, \ - ENDPOINT, \ - RX_SIZE, \ - TX_SIZE, \ - RX_QUEUE, \ - TX_QUEUE) \ - \ - static uint8_t CONCAT2(NAME, _buf_rx_)[RX_SIZE]; \ - static uint8_t CONCAT2(NAME, _buf_tx_)[TX_SIZE]; \ - static int CONCAT2(NAME, _is_reset_); \ - static int CONCAT2(NAME, _overflow_); \ - static void CONCAT2(NAME, _deferred_tx_)(void); \ - DECLARE_DEFERRED(CONCAT2(NAME, _deferred_tx_)); \ - static void CONCAT2(NAME, _deferred_rx_)(void); \ - DECLARE_DEFERRED(CONCAT2(NAME, _deferred_rx_)); \ +#define USB_STREAM_CONFIG_FULL(NAME, INTERFACE, INTERFACE_CLASS, \ + INTERFACE_SUBCLASS, INTERFACE_PROTOCOL, \ + INTERFACE_NAME, ENDPOINT, RX_SIZE, TX_SIZE, \ + RX_QUEUE, TX_QUEUE) \ + \ + static uint8_t CONCAT2(NAME, _buf_rx_)[RX_SIZE]; \ + static uint8_t CONCAT2(NAME, _buf_tx_)[TX_SIZE]; \ + static int CONCAT2(NAME, _is_reset_); \ + static int CONCAT2(NAME, _overflow_); \ + static void CONCAT2(NAME, _deferred_tx_)(void); \ + DECLARE_DEFERRED(CONCAT2(NAME, _deferred_tx_)); \ + static void CONCAT2(NAME, _deferred_rx_)(void); \ + DECLARE_DEFERRED(CONCAT2(NAME, _deferred_rx_)); \ struct usb_stream_config const NAME = { \ .endpoint = ENDPOINT, \ .is_reset = &CONCAT2(NAME, _is_reset_), \ @@ -130,94 +122,80 @@ extern struct producer_ops const usb_stream_producer_ops; .queue = &RX_QUEUE, \ .ops = &usb_stream_producer_ops, \ }, \ - }; \ - const struct usb_interface_descriptor \ - USB_IFACE_DESC(INTERFACE) = { \ - .bLength = USB_DT_INTERFACE_SIZE, \ - .bDescriptorType = USB_DT_INTERFACE, \ - .bInterfaceNumber = INTERFACE, \ - .bAlternateSetting = 0, \ - .bNumEndpoints = 2, \ - .bInterfaceClass = INTERFACE_CLASS, \ - .bInterfaceSubClass = INTERFACE_SUBCLASS, \ - .bInterfaceProtocol = INTERFACE_PROTOCOL, \ - .iInterface = INTERFACE_NAME, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 0) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = 0x80 | ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk IN */, \ - .wMaxPacketSize = TX_SIZE, \ - .bInterval = 10, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 1) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk OUT */, \ - .wMaxPacketSize = RX_SIZE, \ - .bInterval = 0, \ - }; \ - static void CONCAT2(NAME, _deferred_tx_)(void) \ - { tx_stream_handler(&NAME); } \ - static void CONCAT2(NAME, _deferred_rx_)(void) \ - { rx_stream_handler(&NAME); } \ - static void CONCAT2(NAME, _ep_tx)(void) \ - { \ - usb_epN_tx(ENDPOINT); \ - } \ - static void CONCAT2(NAME, _ep_rx)(void) \ - { \ - usb_epN_rx(ENDPOINT); \ - } \ - static void CONCAT2(NAME, _ep_event)(enum usb_ep_event evt) \ - { \ - usb_stream_event(&NAME, evt); \ - } \ - struct dwc_usb_ep CONCAT2(NAME, _ep_ctl) = { \ - .max_packet = USB_MAX_PACKET_SIZE, \ - .tx_fifo = ENDPOINT, \ - .out_pending = 0, \ - .out_expected = 0, \ - .out_data = 0, \ - .out_databuffer = CONCAT2(NAME, _buf_rx_), \ - .out_databuffer_max = RX_SIZE, \ - .rx_deferred = &CONCAT2(NAME, _deferred_rx__data), \ - .in_packets = 0, \ - .in_pending = 0, \ - .in_data = 0, \ - .in_databuffer = CONCAT2(NAME, _buf_tx_), \ - .in_databuffer_max = TX_SIZE, \ - .tx_deferred = &CONCAT2(NAME, _deferred_tx__data), \ - }; \ - USB_DECLARE_EP(ENDPOINT, \ - CONCAT2(NAME, _ep_tx), \ - CONCAT2(NAME, _ep_rx), \ + }; \ + const struct usb_interface_descriptor USB_IFACE_DESC(INTERFACE) = { \ + .bLength = USB_DT_INTERFACE_SIZE, \ + .bDescriptorType = USB_DT_INTERFACE, \ + .bInterfaceNumber = INTERFACE, \ + .bAlternateSetting = 0, \ + .bNumEndpoints = 2, \ + .bInterfaceClass = INTERFACE_CLASS, \ + .bInterfaceSubClass = INTERFACE_SUBCLASS, \ + .bInterfaceProtocol = INTERFACE_PROTOCOL, \ + .iInterface = INTERFACE_NAME, \ + }; \ + const struct usb_endpoint_descriptor USB_EP_DESC(INTERFACE, 0) = { \ + .bLength = USB_DT_ENDPOINT_SIZE, \ + .bDescriptorType = USB_DT_ENDPOINT, \ + .bEndpointAddress = 0x80 | ENDPOINT, \ + .bmAttributes = 0x02 /* Bulk IN */, \ + .wMaxPacketSize = TX_SIZE, \ + .bInterval = 10, \ + }; \ + const struct usb_endpoint_descriptor USB_EP_DESC(INTERFACE, 1) = { \ + .bLength = USB_DT_ENDPOINT_SIZE, \ + .bDescriptorType = USB_DT_ENDPOINT, \ + .bEndpointAddress = ENDPOINT, \ + .bmAttributes = 0x02 /* Bulk OUT */, \ + .wMaxPacketSize = RX_SIZE, \ + .bInterval = 0, \ + }; \ + static void CONCAT2(NAME, _deferred_tx_)(void) \ + { \ + tx_stream_handler(&NAME); \ + } \ + static void CONCAT2(NAME, _deferred_rx_)(void) \ + { \ + rx_stream_handler(&NAME); \ + } \ + static void CONCAT2(NAME, _ep_tx)(void) \ + { \ + usb_epN_tx(ENDPOINT); \ + } \ + static void CONCAT2(NAME, _ep_rx)(void) \ + { \ + usb_epN_rx(ENDPOINT); \ + } \ + static void CONCAT2(NAME, _ep_event)(enum usb_ep_event evt) \ + { \ + usb_stream_event(&NAME, evt); \ + } \ + struct dwc_usb_ep CONCAT2(NAME, _ep_ctl) = { \ + .max_packet = USB_MAX_PACKET_SIZE, \ + .tx_fifo = ENDPOINT, \ + .out_pending = 0, \ + .out_expected = 0, \ + .out_data = 0, \ + .out_databuffer = CONCAT2(NAME, _buf_rx_), \ + .out_databuffer_max = RX_SIZE, \ + .rx_deferred = &CONCAT2(NAME, _deferred_rx__data), \ + .in_packets = 0, \ + .in_pending = 0, \ + .in_data = 0, \ + .in_databuffer = CONCAT2(NAME, _buf_tx_), \ + .in_databuffer_max = TX_SIZE, \ + .tx_deferred = &CONCAT2(NAME, _deferred_tx__data), \ + }; \ + USB_DECLARE_EP(ENDPOINT, CONCAT2(NAME, _ep_tx), CONCAT2(NAME, _ep_rx), \ CONCAT2(NAME, _ep_event)); /* This is a short version for declaring Google serial endpoints */ -#define USB_STREAM_CONFIG(NAME, \ - INTERFACE, \ - INTERFACE_NAME, \ - ENDPOINT, \ - RX_SIZE, \ - TX_SIZE, \ - RX_QUEUE, \ - TX_QUEUE) \ - USB_STREAM_CONFIG_FULL(NAME, \ - INTERFACE, \ - USB_CLASS_VENDOR_SPEC, \ - USB_SUBCLASS_GOOGLE_SERIAL, \ - USB_PROTOCOL_GOOGLE_SERIAL, \ - INTERFACE_NAME, \ - ENDPOINT, \ - RX_SIZE, \ - TX_SIZE, \ - RX_QUEUE, \ - TX_QUEUE) +#define USB_STREAM_CONFIG(NAME, INTERFACE, INTERFACE_NAME, ENDPOINT, RX_SIZE, \ + TX_SIZE, RX_QUEUE, TX_QUEUE) \ + USB_STREAM_CONFIG_FULL(NAME, INTERFACE, USB_CLASS_VENDOR_SPEC, \ + USB_SUBCLASS_GOOGLE_SERIAL, \ + USB_PROTOCOL_GOOGLE_SERIAL, INTERFACE_NAME, \ + ENDPOINT, RX_SIZE, TX_SIZE, RX_QUEUE, TX_QUEUE) /* * Handle USB and Queue request in a deferred callback. @@ -232,6 +210,6 @@ int tx_stream_handler(struct usb_stream_config const *config); void usb_stream_tx(struct usb_stream_config const *config); void usb_stream_rx(struct usb_stream_config const *config); void usb_stream_event(struct usb_stream_config const *config, - enum usb_ep_event evt); + enum usb_ep_event evt); #endif /* __CROS_EC_USB_STREAM_H */ diff --git a/chip/stm32/usb_dwc_update.h b/chip/stm32/usb_dwc_update.h index 6d79f3aca9..1d5027a01f 100644 --- a/chip/stm32/usb_dwc_update.h +++ b/chip/stm32/usb_dwc_update.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/chip/stm32/usb_endpoints.c b/chip/stm32/usb_endpoints.c index 85952a1387..57ebc86eb2 100644 --- a/chip/stm32/usb_endpoints.c +++ b/chip/stm32/usb_endpoints.c @@ -1,18 +1,20 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * USB endpoints/interfaces callbacks declaration */ -#include -#include -#include "config.h" #include "common.h" +#include "compiler.h" +#include "config.h" #include "usb_hw.h" +#include +#include + typedef void (*xfer_func)(void); -typedef void (*evt_func) (enum usb_ep_event evt); +typedef void (*evt_func)(enum usb_ep_event evt); #if defined(CHIP_FAMILY_STM32F4) #define iface_arguments struct usb_setup_packet *req @@ -44,18 +46,18 @@ int iface_undefined(iface_arguments) #define table(type, name, x) x -#define endpoint_tx(number) \ +#define endpoint_tx(number) \ extern void __attribute__((used, weak, alias("ep_undefined"))) \ - ep_ ## number ## _tx(void); -#define endpoint_rx(number) \ + ep_##number##_tx(void); +#define endpoint_rx(number) \ extern void __attribute__((used, weak, alias("ep_undefined"))) \ - ep_ ## number ## _rx(void); -#define endpoint_evt(number) \ + ep_##number##_rx(void); +#define endpoint_evt(number) \ extern void __attribute__((used, weak, alias("ep_evt_undefined"))) \ - ep_ ## number ## _evt(enum usb_ep_event evt); -#define interface(number) \ + ep_##number##_evt(enum usb_ep_event evt); +#define interface(number) \ extern int __attribute__((used, weak, alias("iface_undefined"))) \ - iface_ ## number ## _request(iface_arguments); + iface_##number##_request(iface_arguments); #define null @@ -69,21 +71,30 @@ int iface_undefined(iface_arguments) #undef interface #undef null +/* Disable warning that "initializer overrides prior initialization of this + * subobject", since we are explicitly doing this to handle the unused + * endpoints. + */ +DISABLE_CLANG_WARNING("-Winitializer-overrides") + /* align function pointers on a 32-bit boundary */ -#define table(type, name, x) type name[] __attribute__((aligned(4), section(".rodata.usb_ep." #name ",\"a\" @"))) = { x }; -#define null (void*)0 +#define table(type, name, x) \ + type name[] __attribute__((aligned(4), section(".rodata.usb_ep." #name \ + ",\"a\" @"))) = { x }; +#define null (void *)0 #define ep_(num, suf) CONCAT3(ep_, num, suf) #define ep(num, suf) ep_(num, suf) #define endpoint_tx(number) \ - [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_ ## number ## _tx, + [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_##number##_tx, #define endpoint_rx(number) \ - [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_ ## number ## _rx, + [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_##number##_rx, #define endpoint_evt(number) \ - [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_ ## number ## _evt, -#define interface(number) \ - [number < USB_IFACE_COUNT ? number : USB_IFACE_COUNT - 1] = iface_ ## number ## _request, + [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_##number##_evt, +#define interface(number) \ + [number < USB_IFACE_COUNT ? number : USB_IFACE_COUNT - 1] = \ + iface_##number##_request, #endif /* PASS 2 */ /* @@ -93,73 +104,40 @@ int iface_undefined(iface_arguments) * It all sorts out nicely */ table(xfer_func, usb_ep_tx, - endpoint_tx(15) - endpoint_tx(14) - endpoint_tx(13) - endpoint_tx(12) - endpoint_tx(11) - endpoint_tx(10) - endpoint_tx(9) - endpoint_tx(8) - endpoint_tx(7) - endpoint_tx(6) - endpoint_tx(5) - endpoint_tx(4) - endpoint_tx(3) - endpoint_tx(2) - endpoint_tx(1) - endpoint_tx(0) -) - -table(xfer_func, usb_ep_rx, - endpoint_rx(15) - endpoint_rx(14) - endpoint_rx(13) - endpoint_rx(12) - endpoint_rx(11) - endpoint_rx(10) - endpoint_rx(9) - endpoint_rx(8) - endpoint_rx(7) - endpoint_rx(6) - endpoint_rx(5) - endpoint_rx(4) - endpoint_rx(3) - endpoint_rx(2) - endpoint_rx(1) - endpoint_rx(0) -) - -table(evt_func, usb_ep_event, - endpoint_evt(15) - endpoint_evt(14) - endpoint_evt(13) - endpoint_evt(12) - endpoint_evt(11) - endpoint_evt(10) - endpoint_evt(9) - endpoint_evt(8) - endpoint_evt(7) - endpoint_evt(6) - endpoint_evt(5) - endpoint_evt(4) - endpoint_evt(3) - endpoint_evt(2) - endpoint_evt(1) - endpoint_evt(0) -) + endpoint_tx(15) endpoint_tx(14) endpoint_tx(13) endpoint_tx(12) + endpoint_tx(11) endpoint_tx(10) endpoint_tx(9) endpoint_tx(8) + endpoint_tx(7) endpoint_tx(6) endpoint_tx(5) + endpoint_tx(4) endpoint_tx(3) endpoint_tx(2) + endpoint_tx(1) endpoint_tx(0)) + + table(xfer_func, usb_ep_rx, + endpoint_rx(15) endpoint_rx(14) endpoint_rx(13) endpoint_rx(12) + endpoint_rx(11) endpoint_rx(10) endpoint_rx(9) + endpoint_rx(8) endpoint_rx(7) endpoint_rx(6) + endpoint_rx(5) endpoint_rx(4) + endpoint_rx(3) endpoint_rx(2) + endpoint_rx(1) + endpoint_rx(0)) + + table(evt_func, usb_ep_event, + endpoint_evt(15) endpoint_evt(14) endpoint_evt( + 13) endpoint_evt(12) endpoint_evt(11) + endpoint_evt(10) endpoint_evt(9) endpoint_evt( + 8) endpoint_evt(7) endpoint_evt(6) + endpoint_evt(5) endpoint_evt(4) + endpoint_evt(3) endpoint_evt(2) + endpoint_evt(1) + endpoint_evt(0)) #if USB_IFACE_COUNT > 0 -table(iface_func, usb_iface_request, - interface(7) - interface(6) - interface(5) - interface(4) - interface(3) - interface(2) - interface(1) - interface(0) -) + table(iface_func, usb_iface_request, + interface(7) interface(6) interface(5) + interface(4) interface(3) interface(2) + interface(1) interface(0)) +#endif + +#if PASS == 2 + ENABLE_CLANG_WARNING("-Winitializer-overrides") #endif #if PASS == 1 diff --git a/chip/stm32/usb_gpio.c b/chip/stm32/usb_gpio.c index 64d46875b5..a0655fd045 100644 --- a/chip/stm32/usb_gpio.c +++ b/chip/stm32/usb_gpio.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,8 +11,8 @@ void usb_gpio_tx(struct usb_gpio_config const *config) { - size_t i; - uint32_t mask = 1; + size_t i; + uint32_t mask = 1; uint32_t value = 0; for (i = 0; i < config->num_gpios; ++i, mask <<= 1) @@ -31,12 +31,12 @@ void usb_gpio_tx(struct usb_gpio_config const *config) void usb_gpio_rx(struct usb_gpio_config const *config) { - size_t i; - uint32_t mask = 1; - uint32_t set_mask = ((uint32_t)(config->rx_ram[0]) | - (uint32_t)(config->rx_ram[1]) << 16); - uint32_t clear_mask = ((uint32_t)(config->rx_ram[2]) | - (uint32_t)(config->rx_ram[3]) << 16); + size_t i; + uint32_t mask = 1; + uint32_t set_mask = ((uint32_t)(config->rx_ram[0]) | + (uint32_t)(config->rx_ram[1]) << 16); + uint32_t clear_mask = ((uint32_t)(config->rx_ram[2]) | + (uint32_t)(config->rx_ram[3]) << 16); uint32_t ignore_mask = set_mask & clear_mask; config->state->set_mask = set_mask; @@ -69,10 +69,10 @@ void usb_gpio_event(struct usb_gpio_config const *config, enum usb_ep_event evt) i = config->endpoint; - btable_ep[i].tx_addr = usb_sram_addr(config->tx_ram); + btable_ep[i].tx_addr = usb_sram_addr(config->tx_ram); btable_ep[i].tx_count = USB_GPIO_TX_PACKET_SIZE; - btable_ep[i].rx_addr = usb_sram_addr(config->rx_ram); + btable_ep[i].rx_addr = usb_sram_addr(config->rx_ram); btable_ep[i].rx_count = ((USB_GPIO_RX_PACKET_SIZE / 2) << 10); /* @@ -82,8 +82,8 @@ void usb_gpio_event(struct usb_gpio_config const *config, enum usb_ep_event evt) config->tx_ram[0] = 0; config->tx_ram[1] = 0; - STM32_USB_EP(i) = ((i << 0) | /* Endpoint Addr*/ - (3 << 4) | /* TX Valid */ - (0 << 9) | /* Bulk EP */ + STM32_USB_EP(i) = ((i << 0) | /* Endpoint Addr*/ + (3 << 4) | /* TX Valid */ + (0 << 9) | /* Bulk EP */ (3 << 12)); /* RX Valid */ } diff --git a/chip/stm32/usb_gpio.h b/chip/stm32/usb_gpio.h index b27c7f9485..a54801048b 100644 --- a/chip/stm32/usb_gpio.h +++ b/chip/stm32/usb_gpio.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -55,69 +55,62 @@ struct usb_gpio_config { * ENDPOINT is the index of the USB bulk endpoint used for receiving and * transmitting bytes. */ -#define USB_GPIO_CONFIG(NAME, \ - GPIO_LIST, \ - INTERFACE, \ - ENDPOINT) \ - BUILD_ASSERT(ARRAY_SIZE(GPIO_LIST) <= 32); \ - static usb_uint CONCAT2(NAME, _ep_rx_buffer)[USB_GPIO_RX_PACKET_SIZE / 2] __usb_ram; \ - static usb_uint CONCAT2(NAME, _ep_tx_buffer)[USB_GPIO_TX_PACKET_SIZE / 2] __usb_ram; \ - struct usb_gpio_config const NAME = { \ - .state = &((struct usb_gpio_state){}), \ - .endpoint = ENDPOINT, \ - .rx_ram = CONCAT2(NAME, _ep_rx_buffer), \ - .tx_ram = CONCAT2(NAME, _ep_tx_buffer), \ - .gpios = GPIO_LIST, \ - .num_gpios = ARRAY_SIZE(GPIO_LIST), \ - }; \ - const struct usb_interface_descriptor \ - USB_IFACE_DESC(INTERFACE) = { \ - .bLength = USB_DT_INTERFACE_SIZE, \ - .bDescriptorType = USB_DT_INTERFACE, \ - .bInterfaceNumber = INTERFACE, \ - .bAlternateSetting = 0, \ - .bNumEndpoints = 2, \ - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ - .bInterfaceSubClass = 0, \ - .bInterfaceProtocol = 0, \ - .iInterface = 0, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 0) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = 0x80 | ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk IN */, \ - .wMaxPacketSize = USB_GPIO_TX_PACKET_SIZE, \ - .bInterval = 10, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 1) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk OUT */, \ - .wMaxPacketSize = USB_GPIO_RX_PACKET_SIZE, \ - .bInterval = 0, \ - }; \ - static void CONCAT2(NAME, _ep_tx)(void) \ - { \ - usb_gpio_tx(&NAME); \ - } \ - static void CONCAT2(NAME, _ep_rx)(void) \ - { \ - usb_gpio_rx(&NAME); \ - } \ - static void CONCAT2(NAME, _ep_event)(enum usb_ep_event evt) \ - { \ - usb_gpio_event(&NAME, evt); \ - } \ - USB_DECLARE_EP(ENDPOINT, \ - CONCAT2(NAME, _ep_tx), \ - CONCAT2(NAME, _ep_rx), \ +#define USB_GPIO_CONFIG(NAME, GPIO_LIST, INTERFACE, ENDPOINT) \ + BUILD_ASSERT(ARRAY_SIZE(GPIO_LIST) <= 32); \ + static usb_uint CONCAT2( \ + NAME, _ep_rx_buffer)[USB_GPIO_RX_PACKET_SIZE / 2] __usb_ram; \ + static usb_uint CONCAT2( \ + NAME, _ep_tx_buffer)[USB_GPIO_TX_PACKET_SIZE / 2] __usb_ram; \ + struct usb_gpio_config const NAME = { \ + .state = &((struct usb_gpio_state){}), \ + .endpoint = ENDPOINT, \ + .rx_ram = CONCAT2(NAME, _ep_rx_buffer), \ + .tx_ram = CONCAT2(NAME, _ep_tx_buffer), \ + .gpios = GPIO_LIST, \ + .num_gpios = ARRAY_SIZE(GPIO_LIST), \ + }; \ + const struct usb_interface_descriptor USB_IFACE_DESC(INTERFACE) = { \ + .bLength = USB_DT_INTERFACE_SIZE, \ + .bDescriptorType = USB_DT_INTERFACE, \ + .bInterfaceNumber = INTERFACE, \ + .bAlternateSetting = 0, \ + .bNumEndpoints = 2, \ + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ + .bInterfaceSubClass = 0, \ + .bInterfaceProtocol = 0, \ + .iInterface = 0, \ + }; \ + const struct usb_endpoint_descriptor USB_EP_DESC(INTERFACE, 0) = { \ + .bLength = USB_DT_ENDPOINT_SIZE, \ + .bDescriptorType = USB_DT_ENDPOINT, \ + .bEndpointAddress = 0x80 | ENDPOINT, \ + .bmAttributes = 0x02 /* Bulk IN */, \ + .wMaxPacketSize = USB_GPIO_TX_PACKET_SIZE, \ + .bInterval = 10, \ + }; \ + const struct usb_endpoint_descriptor USB_EP_DESC(INTERFACE, 1) = { \ + .bLength = USB_DT_ENDPOINT_SIZE, \ + .bDescriptorType = USB_DT_ENDPOINT, \ + .bEndpointAddress = ENDPOINT, \ + .bmAttributes = 0x02 /* Bulk OUT */, \ + .wMaxPacketSize = USB_GPIO_RX_PACKET_SIZE, \ + .bInterval = 0, \ + }; \ + static void CONCAT2(NAME, _ep_tx)(void) \ + { \ + usb_gpio_tx(&NAME); \ + } \ + static void CONCAT2(NAME, _ep_rx)(void) \ + { \ + usb_gpio_rx(&NAME); \ + } \ + static void CONCAT2(NAME, _ep_event)(enum usb_ep_event evt) \ + { \ + usb_gpio_event(&NAME, evt); \ + } \ + USB_DECLARE_EP(ENDPOINT, CONCAT2(NAME, _ep_tx), CONCAT2(NAME, _ep_rx), \ CONCAT2(NAME, _ep_event)) - /* * These functions are used by the trampoline functions defined above to * connect USB endpoint events with the generic USB GPIO driver. diff --git a/chip/stm32/usb_hid.c b/chip/stm32/usb_hid.c index b8336fa0a0..321248c702 100644 --- a/chip/stm32/usb_hid.c +++ b/chip/stm32/usb_hid.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,14 +13,14 @@ #include "registers.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_descriptor.h" -#include "usb_hw.h" #include "usb_hid.h" #include "usb_hid_hw.h" +#include "usb_hw.h" +#include "util.h" /* Console output macro */ -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) void hid_tx(int ep) { @@ -41,17 +41,15 @@ void hid_reset(int ep, usb_uint *hid_ep_tx_buf, int tx_len, for (i = 0; i < DIV_ROUND_UP(tx_len, 2); i++) hid_ep_tx_buf[i] = 0; - ep_reg = (ep << 0) /* Endpoint Address */ | - EP_TX_VALID | - (3 << 9) /* interrupt EP */ | - EP_RX_DISAB; + ep_reg = (ep << 0) /* Endpoint Address */ | EP_TX_VALID | + (3 << 9) /* interrupt EP */ | EP_RX_DISAB; /* Enable RX for output reports */ if (hid_ep_rx_buf && rx_len > 0) { btable_ep[ep].rx_addr = usb_sram_addr(hid_ep_rx_buf); btable_ep[ep].rx_count = ((rx_len + 1) / 2) << 10; - ep_reg |= EP_RX_VALID; /* RX Valid */ + ep_reg |= EP_RX_VALID; /* RX Valid */ } STM32_USB_EP(ep) = ep_reg; @@ -73,14 +71,13 @@ static const uint8_t *report_ptr; * * @return 0 if entire report is sent, 1 if there are remaining data. */ -static int send_report(usb_uint *ep0_buf_tx, - const uint8_t *report, +static int send_report(usb_uint *ep0_buf_tx, const uint8_t *report, int report_size) { int packet_size = MIN(report_size, USB_MAX_PACKET_SIZE); - memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx), - report, packet_size); + memcpy_to_usbram((void *)usb_sram_addr(ep0_buf_tx), report, + packet_size); btable_ep[0].tx_count = packet_size; /* report_left != 0 if report doesn't fit in 1 packet. */ report_left = report_size - packet_size; @@ -108,8 +105,8 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, if (report_left == 0) return -1; report_size = MIN(USB_MAX_PACKET_SIZE, report_left); - memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx), - report_ptr, report_size); + memcpy_to_usbram((void *)usb_sram_addr(ep0_buf_tx), report_ptr, + report_size); btable_ep[0].tx_count = report_size; report_left -= report_size; report_ptr += report_size; @@ -117,7 +114,7 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, report_left ? 0 : EP_STATUS_OUT); return report_left ? 1 : 0; } else if (ep0_buf_rx[0] == (USB_DIR_IN | USB_RECIP_INTERFACE | - (USB_REQ_GET_DESCRIPTOR << 8))) { + (USB_REQ_GET_DESCRIPTOR << 8))) { if (ep0_buf_rx[1] == (USB_HID_DT_REPORT << 8)) { /* Setup : HID specific : Get Report descriptor */ return send_report(ep0_buf_tx, report_desc, @@ -130,10 +127,9 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, EP_STATUS_OUT); return 0; } - } else if (ep0_buf_rx[0] == (USB_DIR_IN | - USB_RECIP_INTERFACE | - USB_TYPE_CLASS | - (USB_HID_REQ_GET_REPORT << 8))) { + } else if (ep0_buf_rx[0] == + (USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS | + (USB_HID_REQ_GET_REPORT << 8))) { const uint8_t report_type = (ep0_buf_rx[1] >> 8) & 0xFF; const uint8_t report_id = ep0_buf_rx[1] & 0xFF; int retval; @@ -142,9 +138,7 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, if (!config->get_report) /* not supported */ return -1; - retval = config->get_report(report_id, - report_type, - &report_ptr, + retval = config->get_report(report_id, report_type, &report_ptr, &report_left); if (retval) return retval; diff --git a/chip/stm32/usb_hid_hw.h b/chip/stm32/usb_hid_hw.h index a36a66567e..5e28a801c1 100644 --- a/chip/stm32/usb_hid_hw.h +++ b/chip/stm32/usb_hid_hw.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,6 +8,8 @@ #ifndef __CROS_EC_USB_HID_HW_H #define __CROS_EC_USB_HID_HW_H +#include "chip/stm32/usb_hw.h" + #include struct usb_hid_config_t { @@ -25,10 +27,8 @@ struct usb_hid_config_t { * @param buffer_size: handler should set it to the size of returned * buffer. */ - int (*get_report)(uint8_t report_id, - uint8_t report_type, - const uint8_t **buffer_ptr, - int *buffer_size); + int (*get_report)(uint8_t report_id, uint8_t report_type, + const uint8_t **buffer_ptr, int *buffer_size); }; /* internal callbacks for HID class drivers */ diff --git a/chip/stm32/usb_hid_keyboard.c b/chip/stm32/usb_hid_keyboard.c index c206f9a9c5..7b40f31309 100644 --- a/chip/stm32/usb_hid_keyboard.c +++ b/chip/stm32/usb_hid_keyboard.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -20,15 +20,15 @@ #include "tablet_mode.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_api.h" #include "usb_descriptor.h" -#include "usb_hw.h" #include "usb_hid.h" #include "usb_hid_hw.h" +#include "usb_hw.h" +#include "util.h" /* Console output macro */ -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) static const int keyboard_debug; @@ -51,7 +51,7 @@ enum hid_protocol { static enum hid_protocol protocol = HID_REPORT_PROTOCOL; #if defined(CONFIG_KEYBOARD_ASSISTANT_KEY) || \ - defined(CONFIG_KEYBOARD_TABLET_MODE_SWITCH) + defined(CONFIG_KEYBOARD_TABLET_MODE_SWITCH) #define HID_KEYBOARD_EXTRA_FIELD #endif @@ -69,6 +69,9 @@ struct usb_hid_keyboard_report { /* Assistant/tablet mode switch bitmask */ uint8_t extra; #endif +#ifdef CONFIG_USB_HID_KEYBOARD_VIVALDI + uint32_t top_row; /* bitmap of top row action keys */ +#endif } __packed; struct usb_hid_keyboard_output_report { @@ -105,6 +108,12 @@ struct usb_hid_keyboard_output_report { #define HID_KEYBOARD_MODIFIER_LOW 0xe0 #define HID_KEYBOARD_MODIFIER_HIGH 0xe7 +/* Supported function key range */ +#define HID_F1 0x3a +#define HID_F12 0x45 +#define HID_F13 0x68 +#define HID_F15 0x6a + /* Special keys/switches */ #define HID_KEYBOARD_EXTRA_LOW 0xf0 #define HID_KEYBOARD_ASSISTANT_KEY 0xf0 @@ -117,19 +126,20 @@ struct usb_hid_keyboard_output_report { * Assistant key is mapped as 0xf0, but this key code is never actually send. */ const uint8_t keycodes[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { - {0x00, 0x00, 0xe0, 0xe3, 0xe4, HID_KEYBOARD_ASSISTANT_KEY, 0x00, 0x00}, - {0xe3, 0x29, 0x2b, 0x35, 0x04, 0x1d, 0x1e, 0x14}, - {0x3a, 0x3d, 0x3c, 0x3b, 0x07, 0x06, 0x20, 0x08}, - {0x05, 0x0a, 0x17, 0x22, 0x09, 0x19, 0x21, 0x15}, - {0x43, 0x40, 0x3f, 0x3e, 0x16, 0x1b, 0x1f, 0x1a}, - {0x87, 0x00, 0x30, 0x00, 0x0e, 0x36, 0x25, 0x0c}, - {0x11, 0x0b, 0x1c, 0x23, 0x0d, 0x10, 0x24, 0x18}, - {0x00, 0x00, 0x64, 0x00, 0x00, 0xe1, 0x00, 0xe5}, - {0x2e, 0x34, 0x2F, 0x2d, 0x33, 0x38, 0x27, 0x13}, - {0x00, 0x42, 0x41, 0x68, 0x0f, 0x37, 0x26, 0x12}, - {0xe6, 0x00, 0x89, 0x00, 0x31, 0x00, 0xe2, 0x00}, - {0x00, 0x2a, 0x00, 0x31, 0x28, 0x2c, 0x51, 0x52}, - {0x00, 0x8a, 0x00, 0x8b, 0x00, 0x00, 0x4f, 0x50}, + { 0x00, 0x00, 0xe0, 0xe3, 0xe4, HID_KEYBOARD_ASSISTANT_KEY, 0x00, + 0x00 }, + { 0xe3, 0x29, 0x2b, 0x35, 0x04, 0x1d, 0x1e, 0x14 }, + { 0x3a, 0x3d, 0x3c, 0x3b, 0x07, 0x06, 0x20, 0x08 }, + { 0x05, 0x0a, 0x17, 0x22, 0x09, 0x19, 0x21, 0x15 }, + { 0x43, 0x40, 0x3f, 0x3e, 0x16, 0x1b, 0x1f, 0x1a }, + { 0x87, 0x00, 0x30, 0x00, 0x0e, 0x36, 0x25, 0x0c }, + { 0x11, 0x0b, 0x1c, 0x23, 0x0d, 0x10, 0x24, 0x18 }, + { 0x00, 0x00, 0x64, 0x00, 0x00, 0xe1, 0x00, 0xe5 }, + { 0x2e, 0x34, 0x2F, 0x2d, 0x33, 0x38, 0x27, 0x13 }, + { 0x00, 0x42, 0x41, 0x68, 0x0f, 0x37, 0x26, 0x12 }, + { 0xe6, 0x00, 0x89, 0x00, 0x31, 0x00, 0xe2, 0x00 }, + { 0x00, 0x2a, 0x00, 0x31, 0x28, 0x2c, 0x51, 0x52 }, + { 0x00, 0x8a, 0x00, 0x8b, 0x00, 0x00, 0x4f, 0x50 }, }; /* HID descriptors */ @@ -168,34 +178,84 @@ const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_HID_KEYBOARD, 02) = { }; #endif -#define KEYBOARD_BASE_DESC \ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ - 0x09, 0x06, /* Usage (Keyboard) */ \ - 0xA1, 0x01, /* Collection (Application) */ \ - \ - /* Modifiers */ \ - 0x05, 0x07, /* Usage Page (Key Codes) */ \ - 0x19, HID_KEYBOARD_MODIFIER_LOW, /* Usage Minimum */ \ - 0x29, HID_KEYBOARD_MODIFIER_HIGH, /* Usage Maximum */ \ - 0x15, 0x00, /* Logical Minimum (0) */ \ - 0x25, 0x01, /* Logical Maximum (1) */ \ - 0x75, 0x01, /* Report Size (1) */ \ - 0x95, 0x08, /* Report Count (8) */ \ - 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier byte */ \ - \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x75, 0x08, /* Report Size (8) */ \ - 0x81, 0x01, /* Input (Constant), ;Reserved byte */ \ - \ - /* Normal keys */ \ - 0x95, 0x06, /* Report Count (6) */ \ - 0x75, 0x08, /* Report Size (8) */ \ - 0x15, 0x00, /* Logical Minimum (0) */ \ - 0x25, 0xa4, /* Logical Maximum (164) */ \ - 0x05, 0x07, /* Usage Page (Key Codes) */ \ - 0x19, 0x00, /* Usage Minimum (0) */ \ - 0x29, 0xa4, /* Usage Maximum (164) */ \ - 0x81, 0x00, /* Input (Data, Array), ;Key arrays (6 bytes) */ +#define KEYBOARD_BASE_DESC \ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ + 0x09, 0x06, /* Usage (Keyboard) */ \ + 0xA1, 0x01, /* Collection (Application) */ \ + \ + /* Modifiers */ \ + 0x05, 0x07, /* Usage Page (Key Codes) */ \ + 0x19, HID_KEYBOARD_MODIFIER_LOW, /* Usage Minimum */ \ + 0x29, HID_KEYBOARD_MODIFIER_HIGH, /* Usage Maximum */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x01, /* Logical Maximum (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x95, 0x08, /* Report Count (8) */ \ + 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier \ + byte */ \ + \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x75, 0x08, /* Report Size (8) */ \ + 0x81, 0x01, /* Input (Constant), ;Reserved byte */ \ + \ + /* Normal keys */ \ + 0x95, 0x06, /* Report Count (6) */ \ + 0x75, 0x08, /* Report Size (8) */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0xa4, /* Logical Maximum (164) */ \ + 0x05, 0x07, /* Usage Page (Key Codes) */ \ + 0x19, 0x00, /* Usage Minimum (0) */ \ + 0x29, 0xa4, /* Usage Maximum (164) */ \ + 0x81, 0x00, /* Input (Data, Array), ;Key arrays (6 bytes) */ + +#define KEYBOARD_TOP_ROW_DESC \ + /* Modifiers */ \ + 0x05, 0x0C, /* Consumer Page */ \ + 0x0A, 0x24, 0x02, /* AC Back (0x224) */ \ + 0x0A, 0x25, 0x02, /* AC Forward (0x225) */ \ + 0x0A, 0x27, 0x02, /* AC Refresh (0x227) */ \ + 0x0A, 0x32, 0x02, /* AC View Toggle (0x232) */ \ + 0x0A, 0x9F, 0x02, /* AC Desktop Show All windows (0x29F) */ \ + 0x09, 0x70, /* Display Brightness Decrement (0x70) */ \ + 0x09, 0x6F, /* Display Brightness Increment (0x6F) */ \ + 0x09, 0xE2, /* Mute (0xE2) */ \ + 0x09, 0xEA, /* Volume Decrement (0xEA) */ \ + 0x09, 0xE9, /* Volume Increment (0xE9) */ \ + 0x0B, 0x46, 0x00, 0x07, 0x00, /* PrintScreen (Page 0x7, Usage \ + 0x46) */ \ + 0x0A, 0xD0, 0x02, /* Privacy Screen Toggle (0x2D0) */ \ + 0x09, 0x7A, /* Keyboard Brightness Decrement (0x7A) */ \ + 0x09, 0x79, /* Keyboard Brightness Increment (0x79)*/ \ + 0x09, 0xCD, /* Play / Pause (0xCD) */ \ + 0x09, 0xB5, /* Scan Next Track (0xB5) */ \ + 0x09, 0xB6, /* Scan Previous Track (0xB6) */ \ + 0x09, 0x7C, /* Keyboard Backlight OOC (0x7C) */ \ + 0x0B, 0x2F, 0x00, 0x0B, 0x00, /* Phone Mute (Page 0xB, Usage \ + 0x2F) */ \ + 0x09, 0x32, /* Sleep (0x32) */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x01, /* Logical Maximum (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x95, 0x14, /* Report Count (20) */ \ + 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier \ + byte */ \ + \ + /* 12-bit padding */ \ + 0x95, 0x0C, /* Report Count (12) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x81, 0x01, /* Input (Constant), ;1-bit padding */ + +#define KEYBOARD_TOP_ROW_FEATURE_DESC \ + 0x06, 0xd1, 0xff, /* Usage Page (Google) */ \ + 0x09, 0x01, /* Usage (Top Row List) */ \ + 0xa1, 0x02, /* Collection (Logical) */ \ + 0x05, 0x0a, /* Usage Page (Ordinal) */ \ + 0x19, 0x01, /* Usage Minimum (1) */ \ + 0x29, CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS, /* Usage Maximum */ \ + 0x95, CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS, /* Report Count */ \ + 0x75, 0x20, /* Report Size (32) */ \ + 0xb1, 0x03, /* Feature (Cnst,Var,Abs) */ \ + 0xc0, /* End Collection */ /* * Vendor-defined Usage Page 0xffd1: @@ -204,60 +264,62 @@ const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_HID_KEYBOARD, 02) = { */ #ifdef HID_KEYBOARD_EXTRA_FIELD #ifdef CONFIG_KEYBOARD_ASSISTANT_KEY -#define KEYBOARD_ASSISTANT_KEY_DESC \ - 0x19, 0x18, /* Usage Minimum */ \ - 0x29, 0x18, /* Usage Maximum */ \ - 0x15, 0x00, /* Logical Minimum (0) */ \ - 0x25, 0x01, /* Logical Maximum (1) */ \ - 0x75, 0x01, /* Report Size (1) */ \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier byte */ +#define KEYBOARD_ASSISTANT_KEY_DESC \ + 0x19, 0x18, /* Usage Minimum */ \ + 0x29, 0x18, /* Usage Maximum */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x01, /* Logical Maximum (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier \ + byte */ #else /* No assistant key: just pad 1 bit. */ -#define KEYBOARD_ASSISTANT_KEY_DESC \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x75, 0x01, /* Report Size (1) */ \ - 0x81, 0x01, /* Input (Constant), ;1-bit padding */ +#define KEYBOARD_ASSISTANT_KEY_DESC \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x81, 0x01, /* Input (Constant), ;1-bit padding */ #endif /* !CONFIG_KEYBOARD_ASSISTANT_KEY */ #ifdef CONFIG_KEYBOARD_TABLET_MODE_SWITCH -#define KEYBOARD_TABLET_MODE_SWITCH_DESC \ - 0x19, 0x19, /* Usage Minimum */ \ - 0x29, 0x19, /* Usage Maximum */ \ - 0x15, 0x00, /* Logical Minimum (0) */ \ - 0x25, 0x01, /* Logical Maximum (1) */ \ - 0x75, 0x01, /* Report Size (1) */ \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier byte */ +#define KEYBOARD_TABLET_MODE_SWITCH_DESC \ + 0x19, 0x19, /* Usage Minimum */ \ + 0x29, 0x19, /* Usage Maximum */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x01, /* Logical Maximum (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier \ + byte */ #else /* No tablet mode swtch: just pad 1 bit. */ -#define KEYBOARD_TABLET_MODE_SWITCH_DESC \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x75, 0x01, /* Report Size (1) */ \ - 0x81, 0x01, /* Input (Constant), ;1-bit padding */ +#define KEYBOARD_TABLET_MODE_SWITCH_DESC \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x81, 0x01, /* Input (Constant), ;1-bit padding */ #endif /* CONFIG_KEYBOARD_TABLET_MODE_SWITCH */ -#define KEYBOARD_VENDOR_DESC \ - 0x06, 0xd1, 0xff, /* Usage Page (Vendor-defined 0xffd1) */ \ - \ - KEYBOARD_ASSISTANT_KEY_DESC \ - KEYBOARD_TABLET_MODE_SWITCH_DESC \ - \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x75, 0x06, /* Report Size (6) */ \ - 0x81, 0x01, /* Input (Constant), ;6-bit padding */ +#define KEYBOARD_VENDOR_DESC \ + 0x06, 0xd1, 0xff, /* Usage Page (Vendor-defined 0xffd1) */ \ + \ + KEYBOARD_ASSISTANT_KEY_DESC KEYBOARD_TABLET_MODE_SWITCH_DESC \ + \ + 0x95, \ + 0x01, /* Report Count (1) */ \ + 0x75, 0x06, /* Report Size (6) */ \ + 0x81, 0x01, /* Input (Constant), ;6-bit padding */ #endif /* HID_KEYBOARD_EXTRA_FIELD */ -#define KEYBOARD_BACKLIGHT_DESC \ - 0xA1, 0x02, /* Collection (Logical) */ \ - 0x05, 0x14, /* Usage Page (Alphanumeric Display) */ \ - 0x09, 0x46, /* Usage (Display Brightness) */ \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x75, 0x08, /* Report Size (8) */ \ - 0x15, 0x00, /* Logical Minimum (0) */ \ - 0x25, 0x64, /* Logical Maximum (100) */ \ - 0x91, 0x02, /* Output (Data, Variable, Absolute) */ \ - 0xC0, /* End Collection */ +#define KEYBOARD_BACKLIGHT_DESC \ + 0xA1, 0x02, /* Collection (Logical) */ \ + 0x05, 0x14, /* Usage Page (Alphanumeric Display) */ \ + 0x09, 0x46, /* Usage (Display Brightness) */ \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x75, 0x08, /* Report Size (8) */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x64, /* Logical Maximum (100) */ \ + 0x91, 0x02, /* Output (Data, Variable, Absolute) */ \ + 0xC0, /* End Collection */ /* * To allow dynamic detection of keyboard backlights, we define two descriptors. @@ -270,13 +332,15 @@ static const uint8_t report_desc[] = { KEYBOARD_BASE_DESC #ifdef KEYBOARD_VENDOR_DESC - KEYBOARD_VENDOR_DESC + KEYBOARD_VENDOR_DESC #endif - 0xC0 /* End Collection */ +#ifdef CONFIG_USB_HID_KEYBOARD_VIVALDI + KEYBOARD_TOP_ROW_DESC KEYBOARD_TOP_ROW_FEATURE_DESC +#endif + 0xC0 /* End Collection */ }; - #ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT /* HID : Report Descriptor with keyboard backlight */ @@ -285,34 +349,34 @@ static const uint8_t report_desc_with_backlight[] = { KEYBOARD_BASE_DESC #ifdef KEYBOARD_VENDOR_DESC - KEYBOARD_VENDOR_DESC + KEYBOARD_VENDOR_DESC #endif - KEYBOARD_BACKLIGHT_DESC +#ifdef CONFIG_USB_HID_KEYBOARD_VIVALDI + KEYBOARD_TOP_ROW_DESC KEYBOARD_TOP_ROW_FEATURE_DESC +#endif + KEYBOARD_BACKLIGHT_DESC - 0xC0 /* End Collection */ + 0xC0 /* End Collection */ }; #endif /* HID: HID Descriptor */ -const struct usb_hid_descriptor USB_CUSTOM_DESC_VAR(USB_IFACE_HID_KEYBOARD, - hid, hid_desc_kb) = { +const struct usb_hid_descriptor USB_CUSTOM_DESC_VAR(USB_IFACE_HID_KEYBOARD, hid, + hid_desc_kb) = { .bLength = 9, .bDescriptorType = USB_HID_DT_HID, .bcdHID = 0x0100, .bCountryCode = 0x00, /* Hardware target country */ .bNumDescriptors = 1, - .desc = {{ - .bDescriptorType = USB_HID_DT_REPORT, - .wDescriptorLength = sizeof(report_desc) - }} + .desc = { { .bDescriptorType = USB_HID_DT_REPORT, + .wDescriptorLength = sizeof(report_desc) } } }; #define EP_TX_BUF_SIZE DIV_ROUND_UP(HID_KEYBOARD_REPORT_SIZE, 2) static usb_uint hid_ep_tx_buf[EP_TX_BUF_SIZE] __usb_ram; -static volatile int hid_current_buf; static volatile int hid_ep_data_ready; @@ -335,16 +399,16 @@ static void write_keyboard_report(void) return; } - if (deprecated_atomic_read_clear(&hid_ep_data_ready)) { + if (atomic_clear((atomic_t *)&hid_ep_data_ready)) { /* * Endpoint is not busy, and interrupt handler did not just * send the buffer: enable TX. */ - memcpy_to_usbram((void *) usb_sram_addr(hid_ep_tx_buf), - &report, sizeof(report)); - STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, - EP_TX_VALID, 0); + memcpy_to_usbram((void *)usb_sram_addr(hid_ep_tx_buf), &report, + sizeof(report)); + STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, EP_TX_VALID, + 0); } /* @@ -360,7 +424,7 @@ static void write_keyboard_report(void) static void hid_keyboard_rx(void) { struct usb_hid_keyboard_output_report report; - memcpy_from_usbram(&report, (void *) usb_sram_addr(hid_ep_rx_buf), + memcpy_from_usbram(&report, (void *)usb_sram_addr(hid_ep_rx_buf), HID_KEYBOARD_OUTPUT_REPORT_SIZE); CPRINTF("Keyboard backlight set to %d%%\n", report.brightness); @@ -377,10 +441,10 @@ static void hid_keyboard_tx(void) { hid_tx(USB_EP_HID_KEYBOARD); if (hid_ep_data_ready) { - memcpy_to_usbram((void *) usb_sram_addr(hid_ep_tx_buf), - &report, sizeof(report)); - STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, - EP_TX_VALID, 0); + memcpy_to_usbram((void *)usb_sram_addr(hid_ep_tx_buf), &report, + sizeof(report)); + STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, EP_TX_VALID, + 0); hid_ep_data_ready = 0; } @@ -393,16 +457,14 @@ static void hid_keyboard_event(enum usb_ep_event evt) if (evt == USB_EVENT_RESET) { protocol = HID_REPORT_PROTOCOL; - hid_reset(USB_EP_HID_KEYBOARD, - hid_ep_tx_buf, + hid_reset(USB_EP_HID_KEYBOARD, hid_ep_tx_buf, HID_KEYBOARD_REPORT_SIZE, #ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT - hid_ep_rx_buf, - HID_KEYBOARD_OUTPUT_REPORT_SIZE + hid_ep_rx_buf, HID_KEYBOARD_OUTPUT_REPORT_SIZE #else NULL, 0 #endif - ); + ); /* * Reload endpoint on reset, to make sure we report accurate @@ -425,10 +487,80 @@ USB_DECLARE_EP(USB_EP_HID_KEYBOARD, hid_keyboard_tx, #endif hid_keyboard_event); +struct action_key_config { + uint32_t mask; /* bit position of usb_hid_keyboard_report.top_row */ + uint32_t usage; /*usage ID */ +}; + +static const struct action_key_config action_key[] = { + [TK_BACK] = { .mask = BIT(0), .usage = 0x000C0224 }, + [TK_FORWARD] = { .mask = BIT(1), .usage = 0x000C0225 }, + [TK_REFRESH] = { .mask = BIT(2), .usage = 0x000C0227 }, + [TK_FULLSCREEN] = { .mask = BIT(3), .usage = 0x000C0232 }, + [TK_OVERVIEW] = { .mask = BIT(4), .usage = 0x000C029F }, + [TK_BRIGHTNESS_DOWN] = { .mask = BIT(5), .usage = 0x000C0070 }, + [TK_BRIGHTNESS_UP] = { .mask = BIT(6), .usage = 0x000C006F }, + [TK_VOL_MUTE] = { .mask = BIT(7), .usage = 0x000C00E2 }, + [TK_VOL_DOWN] = { .mask = BIT(8), .usage = 0x000C00EA }, + [TK_VOL_UP] = { .mask = BIT(9), .usage = 0x000C00E9 }, + [TK_SNAPSHOT] = { .mask = BIT(10), .usage = 0x00070046 }, + [TK_PRIVACY_SCRN_TOGGLE] = { .mask = BIT(11), .usage = 0x000C02D0 }, + [TK_KBD_BKLIGHT_DOWN] = { .mask = BIT(12), .usage = 0x000C007A }, + [TK_KBD_BKLIGHT_UP] = { .mask = BIT(13), .usage = 0x000C0079 }, + [TK_PLAY_PAUSE] = { .mask = BIT(14), .usage = 0x000C00CD }, + [TK_NEXT_TRACK] = { .mask = BIT(15), .usage = 0x000C00B5 }, + [TK_PREV_TRACK] = { .mask = BIT(16), .usage = 0x000C00B6 }, + [TK_KBD_BKLIGHT_TOGGLE] = { .mask = BIT(17), .usage = 0x000C007C }, + [TK_MICMUTE] = { .mask = BIT(18), .usage = 0x000B002F }, +}; + +/* TK_* is 1-indexed, so the next bit is at ARRAY_SIZE(action_key) - 1 */ +static const int SLEEP_KEY_MASK = BIT(ARRAY_SIZE(action_key) - 1); + +#ifdef CONFIG_USB_HID_KEYBOARD_VIVALDI +static uint32_t feature_report[CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS]; + +static void hid_keyboard_feature_init(void) +{ + const struct ec_response_keybd_config *config = + board_vivaldi_keybd_config(); + + for (int i = 0; i < CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS; i++) { + int key = config->action_keys[i]; + + if (IN_RANGE(key, 0, ARRAY_SIZE(action_key) - 1)) + feature_report[i] = action_key[key].usage; + } +} +DECLARE_HOOK(HOOK_INIT, hid_keyboard_feature_init, HOOK_PRIO_DEFAULT - 1); +#endif + +static int hid_keyboard_get_report(uint8_t report_id, uint8_t report_type, + const uint8_t **buffer_ptr, int *buffer_size) +{ + if (report_type == REPORT_TYPE_INPUT) { + *buffer_ptr = (uint8_t *)&report; + *buffer_size = sizeof(report); + return 0; + } + +#ifdef CONFIG_USB_HID_KEYBOARD_VIVALDI + if (report_type == REPORT_TYPE_FEATURE) { + *buffer_ptr = (uint8_t *)feature_report; + *buffer_size = + (sizeof(uint32_t) * CONFIG_USB_HID_KB_NUM_TOP_ROW_KEYS); + return 0; + } +#endif + + return -1; +} + static struct usb_hid_config_t hid_config_kb = { .report_desc = report_desc, .report_size = sizeof(report_desc), .hid_desc = &hid_desc_kb, + .get_report = &hid_keyboard_get_report, }; static int hid_keyboard_iface_request(usb_uint *ep0_buf_rx, @@ -440,8 +572,9 @@ static int hid_keyboard_iface_request(usb_uint *ep0_buf_rx, if (ret >= 0) return ret; - if (ep0_buf_rx[0] == (USB_DIR_OUT | USB_TYPE_CLASS | - USB_RECIP_INTERFACE | (USB_HID_REQ_SET_PROTOCOL << 8))) { + if (ep0_buf_rx[0] == + (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE | + (USB_HID_REQ_SET_PROTOCOL << 8))) { uint16_t value = ep0_buf_rx[1]; if (value >= HID_PROTOCOL_COUNT) @@ -452,19 +585,21 @@ static int hid_keyboard_iface_request(usb_uint *ep0_buf_rx, /* Reload endpoint with appropriate tx_count. */ btable_ep[USB_EP_HID_KEYBOARD].tx_count = (protocol == HID_BOOT_PROTOCOL) ? - HID_KEYBOARD_BOOT_SIZE : HID_KEYBOARD_REPORT_SIZE; - STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, - EP_TX_VALID, 0); + HID_KEYBOARD_BOOT_SIZE : + HID_KEYBOARD_REPORT_SIZE; + STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, EP_TX_VALID, + 0); btable_ep[0].tx_count = 0; STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0); return 0; - } else if (ep0_buf_rx[0] == (USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE | (USB_HID_REQ_GET_PROTOCOL << 8))) { + } else if (ep0_buf_rx[0] == + (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE | + (USB_HID_REQ_GET_PROTOCOL << 8))) { uint8_t value = protocol; - memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx), - &value, sizeof(value)); + memcpy_to_usbram((void *)usb_sram_addr(ep0_buf_tx), &value, + sizeof(value)); btable_ep[0].tx_count = 1; STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0); return 0; @@ -483,12 +618,44 @@ void keyboard_clear_buffer(void) memset(&report, 0, sizeof(report)); #ifdef CONFIG_KEYBOARD_TABLET_MODE_SWITCH if (tablet_get_mode()) - report.extra |= 0x01 << (HID_KEYBOARD_TABLET_MODE_SWITCH - + report.extra |= 0x01 << (HID_KEYBOARD_TABLET_MODE_SWITCH - HID_KEYBOARD_EXTRA_LOW); #endif write_keyboard_report(); } +/* + * Convert a function key to the bit mask of corresponding action key. + * + * Return 0 if no need to map (not a function key or vivaldi not enabled) + */ +static uint32_t maybe_convert_function_key(int keycode) +{ + const struct ec_response_keybd_config *config = + board_vivaldi_keybd_config(); + /* zero-based function key index (e.g. F1 -> 0) */ + int index; + + if (!IS_ENABLED(CONFIG_USB_HID_KEYBOARD_VIVALDI) || !config) + return 0; + + if (IN_RANGE(keycode, HID_F1, HID_F12)) + index = keycode - HID_F1; + else if (IN_RANGE(keycode, HID_F13, HID_F15)) + index = keycode - HID_F13 + 12; + else + return 0; /* not a function key */ + + /* convert F13 to Sleep */ + if (index == 12 && (config->capabilities & KEYBD_CAP_SCRNLOCK_KEY)) + return SLEEP_KEY_MASK; + + if (index >= config->num_top_row_keys || + config->action_keys[index] == TK_ABSENT) + return 0; /* not mapped */ + return action_key[config->action_keys[index]].mask; +} + static void keyboard_process_queue(void) { int i; @@ -502,8 +669,8 @@ static void keyboard_process_queue(void) if (keyboard_debug) CPRINTF("Q%d (s%d ep%d hw%d)\n", queue_count(&key_queue), usb_is_suspended(), hid_ep_data_ready, - (STM32_USB_EP(USB_EP_HID_KEYBOARD) & EP_TX_MASK) - == EP_TX_VALID); + (STM32_USB_EP(USB_EP_HID_KEYBOARD) & EP_TX_MASK) == + EP_TX_VALID); mutex_lock(&key_queue_mutex); if (queue_count(&key_queue) == 0) { @@ -541,6 +708,8 @@ static void keyboard_process_queue(void) * dropping keys that are too old. */ while (queue_count(&key_queue) > 0) { + uint32_t action_key_mask; + queue_peek_units(&key_queue, &ev, 0, 1); if (keyboard_debug) CPRINTF(" =%02x/%d %d %d\n", ev.keycode, ev.keycode, @@ -552,8 +721,17 @@ static void keyboard_process_queue(void) queue_advance_head(&key_queue, 1); - if (ev.keycode >= HID_KEYBOARD_EXTRA_LOW && - ev.keycode <= HID_KEYBOARD_EXTRA_HIGH) { + action_key_mask = maybe_convert_function_key(ev.keycode); + if (action_key_mask) { +#ifdef CONFIG_USB_HID_KEYBOARD_VIVALDI + if (ev.pressed) + report.top_row |= action_key_mask; + else + report.top_row &= ~action_key_mask; + valid = 1; +#endif + } else if (ev.keycode >= HID_KEYBOARD_EXTRA_LOW && + ev.keycode <= HID_KEYBOARD_EXTRA_HIGH) { #ifdef HID_KEYBOARD_EXTRA_FIELD mask = 0x01 << (ev.keycode - HID_KEYBOARD_EXTRA_LOW); if (ev.pressed) @@ -563,7 +741,7 @@ static void keyboard_process_queue(void) valid = 1; #endif } else if (ev.keycode >= HID_KEYBOARD_MODIFIER_LOW && - ev.keycode <= HID_KEYBOARD_MODIFIER_HIGH) { + ev.keycode <= HID_KEYBOARD_MODIFIER_HIGH) { mask = 0x01 << (ev.keycode - HID_KEYBOARD_MODIFIER_LOW); if (ev.pressed) report.modifiers |= mask; @@ -630,7 +808,7 @@ static void tablet_mode_change(void) } DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, tablet_mode_change, HOOK_PRIO_DEFAULT); /* Run after tablet_mode_init. */ -DECLARE_HOOK(HOOK_INIT, tablet_mode_change, HOOK_PRIO_DEFAULT+1); +DECLARE_HOOK(HOOK_INIT, tablet_mode_change, HOOK_PRIO_DEFAULT + 1); #endif void keyboard_state_changed(int row, int col, int is_pressed) @@ -646,7 +824,8 @@ void keyboard_state_changed(int row, int col, int is_pressed) } void clear_typematic_key(void) -{ } +{ +} #ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT void usb_hid_keyboard_init(void) @@ -656,8 +835,8 @@ void usb_hid_keyboard_init(void) hid_config_kb.report_size = sizeof(report_desc_with_backlight); set_descriptor_patch(USB_DESC_KEYBOARD_BACKLIGHT, - &hid_desc_kb.desc[0].wDescriptorLength, - sizeof(report_desc_with_backlight)); + &hid_desc_kb.desc[0].wDescriptorLength, + sizeof(report_desc_with_backlight)); } } /* This needs to happen before usb_init (HOOK_PRIO_DEFAULT) */ diff --git a/chip/stm32/usb_hid_touchpad.c b/chip/stm32/usb_hid_touchpad.c index 0ead660432..8eb5ee95dc 100644 --- a/chip/stm32/usb_hid_touchpad.c +++ b/chip/stm32/usb_hid_touchpad.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,25 +15,25 @@ #include "registers.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_api.h" #include "usb_descriptor.h" -#include "usb_hw.h" #include "usb_hid.h" #include "usb_hid_hw.h" #include "usb_hid_touchpad.h" +#include "usb_hw.h" +#include "util.h" /* Console output macro */ -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) static const int touchpad_debug; -static struct queue const report_queue = QUEUE_NULL(8, - struct usb_hid_touchpad_report); +static struct queue const report_queue = + QUEUE_NULL(8, struct usb_hid_touchpad_report); static struct mutex report_queue_mutex; -#define HID_TOUCHPAD_REPORT_SIZE sizeof(struct usb_hid_touchpad_report) +#define HID_TOUCHPAD_REPORT_SIZE sizeof(struct usb_hid_touchpad_report) /* * Touchpad EP interval: Make sure this value is smaller than the typical @@ -65,58 +65,63 @@ const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_HID_TOUCHPAD, 81) = { .bInterval = HID_TOUCHPAD_EP_INTERVAL_MS /* polling interval */ }; -#define FINGER_USAGE \ - 0x05, 0x0D, /* Usage Page (Digitizer) */ \ - 0x09, 0x22, /* Usage (Finger) */ \ - 0xA1, 0x02, /* Collection (Logical) */ \ - 0x09, 0x47, /* Usage (Confidence) */ \ - 0x09, 0x42, /* Usage (Tip Switch) */ \ - 0x09, 0x32, /* Usage (In Range) */ \ - 0x15, 0x00, /* Logical Minimum (0) */ \ - 0x25, 0x01, /* Logical Maximum (1) */ \ - 0x75, 0x01, /* Report Size (1) */ \ - 0x95, 0x03, /* Report Count (3) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x09, 0x51, /* Usage (0x51) Contact identifier */ \ - 0x75, 0x04, /* Report Size (4) */ \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x25, 0x0F, /* Logical Maximum (15) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x05, 0x0D, /* Usage Page (Digitizer) */ \ - /* Logical Maximum of Pressure */ \ - 0x26, (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE & 0xFF), \ - (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE >> 8), \ - 0x75, 0x09, /* Report Size (9) */ \ - 0x09, 0x30, /* Usage (Tip pressure) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x26, 0xFF, 0x0F, /* Logical Maximum (4095) */ \ - 0x75, 0x0C, /* Report Size (12) */ \ - 0x09, 0x48, /* Usage (WIDTH) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x09, 0x49, /* Usage (HEIGHT) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ \ - 0x75, 0x0C, /* Report Size (12) */ \ - 0x55, 0x0E, /* Unit Exponent (-2) */ \ - 0x65, 0x11, /* Unit (System: SI Linear, Length: cm) */ \ - 0x09, 0x30, /* Usage (X) */ \ - 0x35, 0x00, /* Physical Minimum (0) */ \ - 0x26, (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X & 0xff), \ - (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X >> 8), \ - /* Logical Maximum */ \ - 0x46, (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X & 0xff), \ - (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X >> 8), \ - /* Physical Maximum (tenth of mm) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x26, (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y & 0xff), \ - (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y >> 8), \ - /* Logical Maximum */ \ - 0x46, (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y & 0xff), \ - (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y >> 8), \ - /* Physical Maximum (tenth of mm) */ \ - 0x09, 0x31, /* Usage (Y) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0xC0 /* End Collection */ +#define FINGER_USAGE \ + 0x05, 0x0D, /* Usage Page (Digitizer) */ \ + 0x09, 0x22, /* Usage (Finger) */ \ + 0xA1, 0x02, /* Collection (Logical) */ \ + 0x09, 0x47, /* Usage (Confidence) */ \ + 0x09, 0x42, /* Usage (Tip Switch) */ \ + 0x09, 0x32, /* Usage (In Range) */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x01, /* Logical Maximum (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x95, 0x03, /* Report Count (3) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x51, /* Usage (0x51) Contact identifier */ \ + 0x75, 0x04, /* Report Size (4) */ \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x25, 0x0F, /* Logical Maximum (15) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x05, 0x0D, /* Usage Page (Digitizer) */ /* Logical \ + Maximum of \ + Pressure */ \ + 0x26, (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE & 0xFF), \ + (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_PRESSURE >> 8), 0x75, \ + 0x09, /* Report Size (9) */ \ + 0x09, 0x30, /* Usage (Tip pressure) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x26, 0xFF, 0x0F, /* Logical Maximum (4095) */ \ + 0x75, 0x0C, /* Report Size (12) */ \ + 0x09, 0x48, /* Usage (WIDTH) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x49, /* Usage (HEIGHT) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ \ + 0x75, 0x0C, /* Report Size (12) */ \ + 0x55, 0x0E, /* Unit Exponent (-2) */ \ + 0x65, 0x11, /* Unit (System: SI Linear, Length: cm) */ \ + 0x09, 0x30, /* Usage (X) */ \ + 0x35, 0x00, /* Physical Minimum (0) */ \ + 0x26, (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X & 0xff), \ + (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X >> 8), /* Logical \ + Maximum */ \ + 0x46, (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X & 0xff), \ + (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X >> 8), /* Physical \ + Maximum \ + (tenth of \ + mm) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x26, (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y & 0xff), \ + (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y >> 8), /* Logical \ + Maximum */ \ + 0x46, (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y & 0xff), \ + (CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y >> 8), /* Physical \ + Maximum \ + (tenth of \ + mm) */ \ + 0x09, 0x31, /* Usage (Y) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0xC0 /* End Collection */ /* * HID: Report Descriptor @@ -125,10 +130,10 @@ const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_HID_TOUCHPAD, 81) = { */ static const uint8_t report_desc[] = { /* Touchpad Collection */ - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x09, 0x05, /* Usage (Touch Pad) */ - 0xA1, 0x01, /* Collection (Application) */ - 0x85, REPORT_ID_TOUCHPAD, /* Report ID (1, Touch) */ + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x09, 0x05, /* Usage (Touch Pad) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x85, REPORT_ID_TOUCHPAD, /* Report ID (1, Touch) */ /* Finger 0 */ FINGER_USAGE, /* Finger 1 */ @@ -140,52 +145,52 @@ static const uint8_t report_desc[] = { /* Finger 4 */ FINGER_USAGE, /* Contact count */ - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x09, 0x54, /* Usage (Contact count) */ - 0x25, MAX_FINGERS, /* Logical Maximum (MAX_FINGERS) */ - 0x75, 0x07, /* Report Size (7) */ - 0x95, 0x01, /* Report Count (1) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x09, 0x54, /* Usage (Contact count) */ + 0x25, MAX_FINGERS, /* Logical Maximum (MAX_FINGERS) */ + 0x75, 0x07, /* Report Size (7) */ + 0x95, 0x01, /* Report Count (1) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ /* Button */ - 0x05, 0x01, /* Usage Page(Generic Desktop Ctrls) */ - 0x05, 0x09, /* Usage (Button) */ - 0x19, 0x01, /* Usage Minimum (0x01) */ - 0x29, 0x01, /* Usage Maximum (0x01) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x75, 0x01, /* Report Size (1) */ - 0x95, 0x01, /* Report Count (1) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ + 0x05, 0x01, /* Usage Page(Generic Desktop Ctrls) */ + 0x05, 0x09, /* Usage (Button) */ + 0x19, 0x01, /* Usage Minimum (0x01) */ + 0x29, 0x01, /* Usage Maximum (0x01) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, 0x01, /* Report Count (1) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ /* Timestamp */ - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x55, 0x0C, /* Unit Exponent (-4) */ - 0x66, 0x01, 0x10, /* Unit (Seconds) */ - 0x47, 0xFF, 0xFF, 0x00, 0x00, /* Physical Maximum (65535) */ - 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535) */ - 0x75, 0x10, /* Report Size (16) */ - 0x95, 0x01, /* Report Count (1) */ - 0x09, 0x56, /* Usage (0x56, Relative Scan Time) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ - - 0x85, REPORT_ID_DEVICE_CAPS, /* Report ID (Device Capabilities) */ - 0x09, 0x55, /* Usage (Contact Count Maximum) */ - 0x09, 0x59, /* Usage (Pad Type) */ - 0x25, 0x0F, /* Logical Maximum (15) */ - 0x75, 0x08, /* Report Size (8) */ - 0x95, 0x02, /* Report Count (2) */ - 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x55, 0x0C, /* Unit Exponent (-4) */ + 0x66, 0x01, 0x10, /* Unit (Seconds) */ + 0x47, 0xFF, 0xFF, 0x00, 0x00, /* Physical Maximum (65535) */ + 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535) */ + 0x75, 0x10, /* Report Size (16) */ + 0x95, 0x01, /* Report Count (1) */ + 0x09, 0x56, /* Usage (0x56, Relative Scan Time) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ + + 0x85, REPORT_ID_DEVICE_CAPS, /* Report ID (Device Capabilities) */ + 0x09, 0x55, /* Usage (Contact Count Maximum) */ + 0x09, 0x59, /* Usage (Pad Type) */ + 0x25, 0x0F, /* Logical Maximum (15) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x02, /* Report Count (2) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ /* Page 0xFF, usage 0xC5 is device certificate. */ - 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */ - 0x85, REPORT_ID_DEVICE_CERT, /* Report ID (Device Certification) */ - 0x09, 0xC5, /* Usage (Vendor Usage 0xC5) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ - 0x75, 0x08, /* Report Size (8) */ - 0x96, 0x00, 0x01, /* Report Count (256) */ - 0xB1, 0x02, /* Feature (Data,Var,Abs) */ - - 0xC0, /* End Collection */ + 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */ + 0x85, REPORT_ID_DEVICE_CERT, /* Report ID (Device Certification) */ + 0x09, 0xC5, /* Usage (Vendor Usage 0xC5) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ + 0x75, 0x08, /* Report Size (8) */ + 0x96, 0x00, 0x01, /* Report Count (256) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + + 0xC0, /* End Collection */ }; /* A 256-byte default blob for the 'device certification status' feature report. @@ -195,59 +200,281 @@ static const uint8_t report_desc[] = { static const uint8_t device_cert_response[] = { REPORT_ID_DEVICE_CERT, - 0xFC, 0x28, 0xFE, 0x84, 0x40, 0xCB, 0x9A, 0x87, - 0x0D, 0xBE, 0x57, 0x3C, 0xB6, 0x70, 0x09, 0x88, - 0x07, 0x97, 0x2D, 0x2B, 0xE3, 0x38, 0x34, 0xB6, - 0x6C, 0xED, 0xB0, 0xF7, 0xE5, 0x9C, 0xF6, 0xC2, - 0x2E, 0x84, 0x1B, 0xE8, 0xB4, 0x51, 0x78, 0x43, - 0x1F, 0x28, 0x4B, 0x7C, 0x2D, 0x53, 0xAF, 0xFC, - 0x47, 0x70, 0x1B, 0x59, 0x6F, 0x74, 0x43, 0xC4, - 0xF3, 0x47, 0x18, 0x53, 0x1A, 0xA2, 0xA1, 0x71, - 0xC7, 0x95, 0x0E, 0x31, 0x55, 0x21, 0xD3, 0xB5, - 0x1E, 0xE9, 0x0C, 0xBA, 0xEC, 0xB8, 0x89, 0x19, - 0x3E, 0xB3, 0xAF, 0x75, 0x81, 0x9D, 0x53, 0xB9, - 0x41, 0x57, 0xF4, 0x6D, 0x39, 0x25, 0x29, 0x7C, - 0x87, 0xD9, 0xB4, 0x98, 0x45, 0x7D, 0xA7, 0x26, - 0x9C, 0x65, 0x3B, 0x85, 0x68, 0x89, 0xD7, 0x3B, - 0xBD, 0xFF, 0x14, 0x67, 0xF2, 0x2B, 0xF0, 0x2A, - 0x41, 0x54, 0xF0, 0xFD, 0x2C, 0x66, 0x7C, 0xF8, - 0xC0, 0x8F, 0x33, 0x13, 0x03, 0xF1, 0xD3, 0xC1, - 0x0B, 0x89, 0xD9, 0x1B, 0x62, 0xCD, 0x51, 0xB7, - 0x80, 0xB8, 0xAF, 0x3A, 0x10, 0xC1, 0x8A, 0x5B, - 0xE8, 0x8A, 0x56, 0xF0, 0x8C, 0xAA, 0xFA, 0x35, - 0xE9, 0x42, 0xC4, 0xD8, 0x55, 0xC3, 0x38, 0xCC, - 0x2B, 0x53, 0x5C, 0x69, 0x52, 0xD5, 0xC8, 0x73, - 0x02, 0x38, 0x7C, 0x73, 0xB6, 0x41, 0xE7, 0xFF, - 0x05, 0xD8, 0x2B, 0x79, 0x9A, 0xE2, 0x34, 0x60, - 0x8F, 0xA3, 0x32, 0x1F, 0x09, 0x78, 0x62, 0xBC, - 0x80, 0xE3, 0x0F, 0xBD, 0x65, 0x20, 0x08, 0x13, - 0xC1, 0xE2, 0xEE, 0x53, 0x2D, 0x86, 0x7E, 0xA7, - 0x5A, 0xC5, 0xD3, 0x7D, 0x98, 0xBE, 0x31, 0x48, - 0x1F, 0xFB, 0xDA, 0xAF, 0xA2, 0xA8, 0x6A, 0x89, - 0xD6, 0xBF, 0xF2, 0xD3, 0x32, 0x2A, 0x9A, 0xE4, - 0xCF, 0x17, 0xB7, 0xB8, 0xF4, 0xE1, 0x33, 0x08, - 0x24, 0x8B, 0xC4, 0x43, 0xA5, 0xE5, 0x24, 0xC2, + 0xFC, + 0x28, + 0xFE, + 0x84, + 0x40, + 0xCB, + 0x9A, + 0x87, + 0x0D, + 0xBE, + 0x57, + 0x3C, + 0xB6, + 0x70, + 0x09, + 0x88, + 0x07, + 0x97, + 0x2D, + 0x2B, + 0xE3, + 0x38, + 0x34, + 0xB6, + 0x6C, + 0xED, + 0xB0, + 0xF7, + 0xE5, + 0x9C, + 0xF6, + 0xC2, + 0x2E, + 0x84, + 0x1B, + 0xE8, + 0xB4, + 0x51, + 0x78, + 0x43, + 0x1F, + 0x28, + 0x4B, + 0x7C, + 0x2D, + 0x53, + 0xAF, + 0xFC, + 0x47, + 0x70, + 0x1B, + 0x59, + 0x6F, + 0x74, + 0x43, + 0xC4, + 0xF3, + 0x47, + 0x18, + 0x53, + 0x1A, + 0xA2, + 0xA1, + 0x71, + 0xC7, + 0x95, + 0x0E, + 0x31, + 0x55, + 0x21, + 0xD3, + 0xB5, + 0x1E, + 0xE9, + 0x0C, + 0xBA, + 0xEC, + 0xB8, + 0x89, + 0x19, + 0x3E, + 0xB3, + 0xAF, + 0x75, + 0x81, + 0x9D, + 0x53, + 0xB9, + 0x41, + 0x57, + 0xF4, + 0x6D, + 0x39, + 0x25, + 0x29, + 0x7C, + 0x87, + 0xD9, + 0xB4, + 0x98, + 0x45, + 0x7D, + 0xA7, + 0x26, + 0x9C, + 0x65, + 0x3B, + 0x85, + 0x68, + 0x89, + 0xD7, + 0x3B, + 0xBD, + 0xFF, + 0x14, + 0x67, + 0xF2, + 0x2B, + 0xF0, + 0x2A, + 0x41, + 0x54, + 0xF0, + 0xFD, + 0x2C, + 0x66, + 0x7C, + 0xF8, + 0xC0, + 0x8F, + 0x33, + 0x13, + 0x03, + 0xF1, + 0xD3, + 0xC1, + 0x0B, + 0x89, + 0xD9, + 0x1B, + 0x62, + 0xCD, + 0x51, + 0xB7, + 0x80, + 0xB8, + 0xAF, + 0x3A, + 0x10, + 0xC1, + 0x8A, + 0x5B, + 0xE8, + 0x8A, + 0x56, + 0xF0, + 0x8C, + 0xAA, + 0xFA, + 0x35, + 0xE9, + 0x42, + 0xC4, + 0xD8, + 0x55, + 0xC3, + 0x38, + 0xCC, + 0x2B, + 0x53, + 0x5C, + 0x69, + 0x52, + 0xD5, + 0xC8, + 0x73, + 0x02, + 0x38, + 0x7C, + 0x73, + 0xB6, + 0x41, + 0xE7, + 0xFF, + 0x05, + 0xD8, + 0x2B, + 0x79, + 0x9A, + 0xE2, + 0x34, + 0x60, + 0x8F, + 0xA3, + 0x32, + 0x1F, + 0x09, + 0x78, + 0x62, + 0xBC, + 0x80, + 0xE3, + 0x0F, + 0xBD, + 0x65, + 0x20, + 0x08, + 0x13, + 0xC1, + 0xE2, + 0xEE, + 0x53, + 0x2D, + 0x86, + 0x7E, + 0xA7, + 0x5A, + 0xC5, + 0xD3, + 0x7D, + 0x98, + 0xBE, + 0x31, + 0x48, + 0x1F, + 0xFB, + 0xDA, + 0xAF, + 0xA2, + 0xA8, + 0x6A, + 0x89, + 0xD6, + 0xBF, + 0xF2, + 0xD3, + 0x32, + 0x2A, + 0x9A, + 0xE4, + 0xCF, + 0x17, + 0xB7, + 0xB8, + 0xF4, + 0xE1, + 0x33, + 0x08, + 0x24, + 0x8B, + 0xC4, + 0x43, + 0xA5, + 0xE5, + 0x24, + 0xC2, }; /* Device capabilities feature report. */ static const uint8_t device_caps_response[] = { REPORT_ID_DEVICE_CAPS, - MAX_FINGERS, /* Contact Count Maximum */ - 0x00, /* Pad Type: Depressible click-pad */ + MAX_FINGERS, /* Contact Count Maximum */ + 0x00, /* Pad Type: Depressible click-pad */ }; -const struct usb_hid_descriptor USB_CUSTOM_DESC_VAR(USB_IFACE_HID_TOUCHPAD, - hid, hid_desc_tp) = { +const struct usb_hid_descriptor USB_CUSTOM_DESC_VAR(USB_IFACE_HID_TOUCHPAD, hid, + hid_desc_tp) = { .bLength = 9, .bDescriptorType = USB_HID_DT_HID, .bcdHID = 0x0100, .bCountryCode = 0x00, /* Hardware target country */ .bNumDescriptors = 1, - .desc = {{ - .bDescriptorType = USB_HID_DT_REPORT, - .wDescriptorLength = sizeof(report_desc) - }} + .desc = { { .bDescriptorType = USB_HID_DT_REPORT, + .wDescriptorLength = sizeof(report_desc) } } }; static usb_uint hid_ep_buf[DIV_ROUND_UP(HID_TOUCHPAD_REPORT_SIZE, 2)] __usb_ram; @@ -258,8 +485,8 @@ static usb_uint hid_ep_buf[DIV_ROUND_UP(HID_TOUCHPAD_REPORT_SIZE, 2)] __usb_ram; */ static void write_touchpad_report(struct usb_hid_touchpad_report *report) { - memcpy_to_usbram((void *) usb_sram_addr(hid_ep_buf), - report, sizeof(*report)); + memcpy_to_usbram((void *)usb_sram_addr(hid_ep_buf), report, + sizeof(*report)); /* enable TX */ STM32_TOGGLE_EP(USB_EP_HID_TOUCHPAD, EP_TX_MASK, EP_TX_VALID, 0); @@ -289,8 +516,7 @@ static void hid_touchpad_process_queue(void) now = __hw_clock_source_read() / USB_HID_TOUCHPAD_TIMESTAMP_UNIT; if (usb_is_suspended() || - (STM32_USB_EP(USB_EP_HID_TOUCHPAD) & EP_TX_MASK) - == EP_TX_VALID) { + (STM32_USB_EP(USB_EP_HID_TOUCHPAD) & EP_TX_MASK) == EP_TX_VALID) { usb_wake(); /* Let's trim old events from the queue, if any. */ @@ -307,8 +533,8 @@ static void hid_touchpad_process_queue(void) queue_peek_units(&report_queue, &report, 0, 1); - delta = (int)((uint16_t)(now - report.timestamp)) - * USB_HID_TOUCHPAD_TIMESTAMP_UNIT; + delta = (int)((uint16_t)(now - report.timestamp)) * + USB_HID_TOUCHPAD_TIMESTAMP_UNIT; if (touchpad_debug) CPRINTS("evt t=%d d=%d", report.timestamp, delta); @@ -345,8 +571,8 @@ void set_touchpad_report(struct usb_hid_touchpad_report *report) /* USB/EP ready and nothing in queue, just write the report. */ if (!usb_is_suspended() && - (STM32_USB_EP(USB_EP_HID_TOUCHPAD) & EP_TX_MASK) != EP_TX_VALID - && queue_count(&report_queue) == 0) { + (STM32_USB_EP(USB_EP_HID_TOUCHPAD) & EP_TX_MASK) != EP_TX_VALID && + queue_count(&report_queue) == 0) { write_touchpad_report(report); mutex_unlock(&report_queue_mutex); return; @@ -385,7 +611,7 @@ static void hid_touchpad_event(enum usb_ep_event evt) hid_reset(USB_EP_HID_TOUCHPAD, hid_ep_buf, HID_TOUCHPAD_REPORT_SIZE, NULL, 0); else if (evt == USB_EVENT_DEVICE_RESUME && - queue_count(&report_queue) > 0) + queue_count(&report_queue) > 0) hook_call_deferred(&hid_touchpad_process_queue_data, 0); } @@ -393,8 +619,7 @@ USB_DECLARE_EP(USB_EP_HID_TOUCHPAD, hid_touchpad_tx, hid_touchpad_tx, hid_touchpad_event); static int get_report(uint8_t report_id, uint8_t report_type, - const uint8_t **buffer_ptr, - int *buffer_size) + const uint8_t **buffer_ptr, int *buffer_size) { switch (report_id) { case REPORT_ID_DEVICE_CAPS: diff --git a/chip/stm32/usb_hw.h b/chip/stm32/usb_hw.h index 0c75322a7d..511cd9c75a 100644 --- a/chip/stm32/usb_hw.h +++ b/chip/stm32/usb_hw.h @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,12 +19,11 @@ enum usb_ep_event { #include "usb_dwc_hw.h" #else - /* * The STM32 has dedicated USB RAM visible on the APB1 bus (so all reads & * writes are 16-bits wide). The endpoint tables and the data buffers live in * this RAM. -*/ + */ /* Primitive to access the words in USB RAM */ typedef CONFIG_USB_RAM_ACCESS_TYPE usb_uint; @@ -87,8 +86,8 @@ enum usb_desc_patch_type { * The patches need to be setup before _before_ usb_init is executed (or, at * least, before the first call to memcpy_to_usbram_ep0_patch). */ -void set_descriptor_patch(enum usb_desc_patch_type type, - const void *address, uint16_t data); +void set_descriptor_patch(enum usb_desc_patch_type type, const void *address, + uint16_t data); /* Copy to USB ram, applying patches to src as required. */ void *memcpy_to_usbram_ep0_patch(const void *src, size_t n); @@ -106,37 +105,42 @@ void *memcpy_to_usbram_ep0_patch(const void *src, size_t n); #define _EP_RX_HANDLER_TYPECHECK(num) _EP_HANDLER2(num, _rx_typecheck) #define _EP_EVENT_HANDLER_TYPECHECK(num) _EP_HANDLER2(num, _evt_typecheck) -#define USB_DECLARE_EP(num, tx_handler, rx_handler, evt_handler) \ - void _EP_TX_HANDLER(num)(void) \ - __attribute__ ((alias(STRINGIFY(tx_handler)))); \ - void _EP_RX_HANDLER(num)(void) \ - __attribute__ ((alias(STRINGIFY(rx_handler)))); \ - void _EP_EVENT_HANDLER(num)(enum usb_ep_event evt) \ - __attribute__ ((alias(STRINGIFY(evt_handler)))); \ - static __unused void \ - (*_EP_TX_HANDLER_TYPECHECK(num))(void) = tx_handler; \ - static __unused void \ - (*_EP_RX_HANDLER_TYPECHECK(num))(void) = rx_handler; \ - static __unused void \ - (*_EP_EVENT_HANDLER_TYPECHECK(num))(enum usb_ep_event evt)\ - = evt_handler +#define USB_DECLARE_EP(num, tx_handler, rx_handler, evt_handler) \ + void _EP_TX_HANDLER(num)(void) \ + __attribute__((alias(STRINGIFY(tx_handler)))); \ + void _EP_RX_HANDLER(num)(void) \ + __attribute__((alias(STRINGIFY(rx_handler)))); \ + void _EP_EVENT_HANDLER(num)(enum usb_ep_event evt) \ + __attribute__((alias(STRINGIFY(evt_handler)))); \ + static __unused void (*_EP_TX_HANDLER_TYPECHECK(num))(void) = \ + tx_handler; \ + static __unused void (*_EP_RX_HANDLER_TYPECHECK(num))(void) = \ + rx_handler; \ + static __unused void (*_EP_EVENT_HANDLER_TYPECHECK(num))( \ + enum usb_ep_event evt) = evt_handler /* arrays with all endpoint callbacks */ -extern void (*usb_ep_tx[]) (void); -extern void (*usb_ep_rx[]) (void); -extern void (*usb_ep_event[]) (enum usb_ep_event evt); +extern void (*usb_ep_tx[])(void); +extern void (*usb_ep_rx[])(void); +extern void (*usb_ep_event[])(enum usb_ep_event evt); /* array with interface-specific control request callbacks */ -extern int (*usb_iface_request[]) (usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx); +extern int (*usb_iface_request[])(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx); /* * Interface handler returns -1 on error, 0 if it wrote the last chunk of data, * or 1 if more data needs to be transferred on the next control request. */ #define _IFACE_HANDLER(num) CONCAT3(iface_, num, _request) -#define USB_DECLARE_IFACE(num, handler) \ - int _IFACE_HANDLER(num)(usb_uint *ep0_buf_rx, \ - usb_uint *epo_buf_tx) \ - __attribute__ ((alias(STRINGIFY(handler)))); +#define USB_DECLARE_IFACE(num, handler) \ + int _IFACE_HANDLER(num)(usb_uint * ep0_buf_rx, usb_uint * epo_buf_tx) \ + __attribute__((alias(STRINGIFY(handler)))); #endif -#endif /* __CROS_EC_USB_HW_H */ + +/* + * In and out buffer sizes for host command over USB. + */ +#define USBHC_MAX_REQUEST_SIZE 0x200 +#define USBHC_MAX_RESPONSE_SIZE 0x100 + +#endif /* __CROS_EC_USB_HW_H */ diff --git a/chip/stm32/usb_isochronous.c b/chip/stm32/usb_isochronous.c index 792507aa75..d2225991c0 100644 --- a/chip/stm32/usb_isochronous.c +++ b/chip/stm32/usb_isochronous.c @@ -1,22 +1,21 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "stddef.h" #include "common.h" #include "config.h" #include "link_defs.h" #include "registers.h" -#include "util.h" +#include "stddef.h" #include "usb_api.h" #include "usb_hw.h" #include "usb_isochronous.h" - +#include "util.h" /* Console output macro */ -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) /* * Currently, we only support TX direction for USB isochronous transfer. @@ -65,8 +64,7 @@ static usb_uint *get_app_addr(struct usb_isochronous_config const *config, * Sets number of bytes written to application buffer. */ static void set_app_count(struct usb_isochronous_config const *config, - int dtog_value, - usb_uint count) + int dtog_value, usb_uint count) { if (dtog_value) btable_ep[config->endpoint].tx_count = count; @@ -74,13 +72,9 @@ static void set_app_count(struct usb_isochronous_config const *config, btable_ep[config->endpoint].rx_count = count; } -int usb_isochronous_write_buffer( - struct usb_isochronous_config const *config, - const uint8_t *src, - size_t n, - size_t dst_offset, - int *buffer_id, - int commit) +int usb_isochronous_write_buffer(struct usb_isochronous_config const *config, + const uint8_t *src, size_t n, + size_t dst_offset, int *buffer_id, int commit) { int dtog_value = get_tx_dtog(config); usb_uint *buffer = get_app_addr(config, dtog_value); @@ -142,15 +136,13 @@ void usb_isochronous_tx(struct usb_isochronous_config const *config) } int usb_isochronous_iface_handler(struct usb_isochronous_config const *config, - usb_uint *ep0_buf_rx, - usb_uint *ep0_buf_tx) + usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx) { int ret = -1; - if (ep0_buf_rx[0] == (USB_DIR_OUT | - USB_TYPE_STANDARD | - USB_RECIP_INTERFACE | - USB_REQ_SET_INTERFACE << 8)) { + if (ep0_buf_rx[0] == + (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE | + USB_REQ_SET_INTERFACE << 8)) { ret = config->set_interface(ep0_buf_rx[1], ep0_buf_rx[2]); if (ret == 0) { diff --git a/chip/stm32/usb_isochronous.h b/chip/stm32/usb_isochronous.h index efa4d94ab4..a96b6db876 100644 --- a/chip/stm32/usb_isochronous.h +++ b/chip/stm32/usb_isochronous.h @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -75,13 +75,9 @@ struct usb_isochronous_config; * * @return -EC_ERROR_CODE on failure, or number of bytes written on success. */ -int usb_isochronous_write_buffer( - struct usb_isochronous_config const *config, - const uint8_t *src, - size_t n, - size_t dst_offset, - int *buffer_id, - int commit); +int usb_isochronous_write_buffer(struct usb_isochronous_config const *config, + const uint8_t *src, size_t n, + size_t dst_offset, int *buffer_id, int commit); struct usb_isochronous_config { int endpoint; @@ -110,21 +106,15 @@ struct usb_isochronous_config { }; /* Define an USB isochronous interface */ -#define USB_ISOCHRONOUS_CONFIG_FULL(NAME, \ - INTERFACE, \ - INTERFACE_CLASS, \ - INTERFACE_SUBCLASS, \ - INTERFACE_PROTOCOL, \ - INTERFACE_NAME, \ - ENDPOINT, \ - TX_SIZE, \ - TX_CALLBACK, \ - SET_INTERFACE, \ - NUM_EXTRA_ENDPOINTS) \ - BUILD_ASSERT(TX_SIZE > 0); \ - BUILD_ASSERT((TX_SIZE < 64 && (TX_SIZE & 0x01) == 0) || \ - (TX_SIZE < 1024 && (TX_SIZE & 0x1f) == 0)); \ - /* Declare buffer */ \ +#define USB_ISOCHRONOUS_CONFIG_FULL(NAME, INTERFACE, INTERFACE_CLASS, \ + INTERFACE_SUBCLASS, INTERFACE_PROTOCOL, \ + INTERFACE_NAME, ENDPOINT, TX_SIZE, \ + TX_CALLBACK, SET_INTERFACE, \ + NUM_EXTRA_ENDPOINTS) \ + BUILD_ASSERT(TX_SIZE > 0); \ + BUILD_ASSERT((TX_SIZE < 64 && (TX_SIZE & 0x01) == 0) || \ + (TX_SIZE < 1024 && (TX_SIZE & 0x1f) == 0)); \ + /* Declare buffer */ \ static usb_uint CONCAT2(NAME, _ep_tx_buffer_0)[TX_SIZE / 2] __usb_ram; \ static usb_uint CONCAT2(NAME, _ep_tx_buffer_1)[TX_SIZE / 2] __usb_ram; \ struct usb_isochronous_config const NAME = { \ @@ -136,62 +126,57 @@ struct usb_isochronous_config { CONCAT2(NAME, _ep_tx_buffer_0), \ CONCAT2(NAME, _ep_tx_buffer_1), \ }, \ - }; \ - const struct usb_interface_descriptor \ - USB_IFACE_DESC(INTERFACE) = { \ - .bLength = USB_DT_INTERFACE_SIZE, \ - .bDescriptorType = USB_DT_INTERFACE, \ - .bInterfaceNumber = INTERFACE, \ - .bAlternateSetting = 0, \ - .bNumEndpoints = 0, \ - .bInterfaceClass = INTERFACE_CLASS, \ - .bInterfaceSubClass = INTERFACE_SUBCLASS, \ - .bInterfaceProtocol = INTERFACE_PROTOCOL, \ - .iInterface = INTERFACE_NAME, \ - }; \ - const struct usb_interface_descriptor \ - USB_CONF_DESC(CONCAT3(iface, INTERFACE, _1iface)) = { \ - .bLength = USB_DT_INTERFACE_SIZE, \ - .bDescriptorType = USB_DT_INTERFACE, \ - .bInterfaceNumber = INTERFACE, \ - .bAlternateSetting = 1, \ - .bNumEndpoints = 1 + NUM_EXTRA_ENDPOINTS, \ - .bInterfaceClass = INTERFACE_CLASS, \ - .bInterfaceSubClass = INTERFACE_SUBCLASS, \ - .bInterfaceProtocol = INTERFACE_PROTOCOL, \ - .iInterface = INTERFACE_NAME, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 0) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = 0x80 | ENDPOINT, \ - .bmAttributes = 0x01 /* Isochronous IN */, \ - .wMaxPacketSize = TX_SIZE, \ - .bInterval = 1, \ - }; \ - static void CONCAT2(NAME, _ep_tx)(void) \ - { \ - usb_isochronous_tx(&NAME); \ - } \ - static void CONCAT2(NAME, _ep_event)(enum usb_ep_event evt) \ - { \ - usb_isochronous_event(&NAME, evt); \ - } \ - static int CONCAT2(NAME, _handler)(usb_uint *rx, usb_uint *tx) \ - { \ - return usb_isochronous_iface_handler(&NAME, rx, tx); \ - } \ - USB_DECLARE_IFACE(INTERFACE, CONCAT2(NAME, _handler)); \ - USB_DECLARE_EP(ENDPOINT, \ - CONCAT2(NAME, _ep_tx), \ - CONCAT2(NAME, _ep_tx), \ - CONCAT2(NAME, _ep_event)); \ + }; \ + const struct usb_interface_descriptor USB_IFACE_DESC(INTERFACE) = { \ + .bLength = USB_DT_INTERFACE_SIZE, \ + .bDescriptorType = USB_DT_INTERFACE, \ + .bInterfaceNumber = INTERFACE, \ + .bAlternateSetting = 0, \ + .bNumEndpoints = 0, \ + .bInterfaceClass = INTERFACE_CLASS, \ + .bInterfaceSubClass = INTERFACE_SUBCLASS, \ + .bInterfaceProtocol = INTERFACE_PROTOCOL, \ + .iInterface = INTERFACE_NAME, \ + }; \ + const struct usb_interface_descriptor USB_CONF_DESC( \ + CONCAT3(iface, INTERFACE, _1iface)) = { \ + .bLength = USB_DT_INTERFACE_SIZE, \ + .bDescriptorType = USB_DT_INTERFACE, \ + .bInterfaceNumber = INTERFACE, \ + .bAlternateSetting = 1, \ + .bNumEndpoints = 1 + NUM_EXTRA_ENDPOINTS, \ + .bInterfaceClass = INTERFACE_CLASS, \ + .bInterfaceSubClass = INTERFACE_SUBCLASS, \ + .bInterfaceProtocol = INTERFACE_PROTOCOL, \ + .iInterface = INTERFACE_NAME, \ + }; \ + const struct usb_endpoint_descriptor USB_EP_DESC(INTERFACE, 0) = { \ + .bLength = USB_DT_ENDPOINT_SIZE, \ + .bDescriptorType = USB_DT_ENDPOINT, \ + .bEndpointAddress = 0x80 | ENDPOINT, \ + .bmAttributes = 0x01 /* Isochronous IN */, \ + .wMaxPacketSize = TX_SIZE, \ + .bInterval = 1, \ + }; \ + static void CONCAT2(NAME, _ep_tx)(void) \ + { \ + usb_isochronous_tx(&NAME); \ + } \ + static void CONCAT2(NAME, _ep_event)(enum usb_ep_event evt) \ + { \ + usb_isochronous_event(&NAME, evt); \ + } \ + static int CONCAT2(NAME, _handler)(usb_uint * rx, usb_uint * tx) \ + { \ + return usb_isochronous_iface_handler(&NAME, rx, tx); \ + } \ + USB_DECLARE_IFACE(INTERFACE, CONCAT2(NAME, _handler)); \ + USB_DECLARE_EP(ENDPOINT, CONCAT2(NAME, _ep_tx), CONCAT2(NAME, _ep_tx), \ + CONCAT2(NAME, _ep_event)); void usb_isochronous_tx(struct usb_isochronous_config const *config); void usb_isochronous_event(struct usb_isochronous_config const *config, enum usb_ep_event event); int usb_isochronous_iface_handler(struct usb_isochronous_config const *config, - usb_uint *ep0_buf_rx, - usb_uint *ep0_buf_tx); + usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx); #endif /* __CROS_EC_USB_ISOCHRONOUS_H */ diff --git a/chip/stm32/usb_pd_phy.c b/chip/stm32/usb_pd_phy.c index b53c5cfeeb..2d090293f9 100644 --- a/chip/stm32/usb_pd_phy.c +++ b/chip/stm32/usb_pd_phy.c @@ -1,28 +1,29 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "adc.h" +#include "builtin/assert.h" #include "clock.h" #include "common.h" #include "console.h" #include "crc.h" #include "dma.h" #include "gpio.h" -#include "hwtimer.h" #include "hooks.h" +#include "hwtimer.h" #include "registers.h" #include "system.h" #include "task.h" #include "timer.h" -#include "util.h" #include "usb_pd.h" #include "usb_pd_config.h" +#include "util.h" #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else #define CPRINTF(format, args...) #define CPRINTS(format, args...) @@ -38,7 +39,7 @@ */ #define PD_BIT_LEN 429 -#define PD_MAX_RAW_SIZE (PD_BIT_LEN*2) +#define PD_MAX_RAW_SIZE (PD_BIT_LEN * 2) /* maximum number of consecutive similar bits with Biphase Mark Coding */ #define MAX_BITS 2 @@ -46,12 +47,12 @@ /* alternating bit sequence used for packet preamble : 00 10 11 01 00 .. */ #define PD_PREAMBLE 0xB4B4B4B4 /* starts with 0, ends with 1 */ -#define TX_CLOCK_DIV ((clock_get_freq() / (2*PD_DATARATE))) +#define TX_CLOCK_DIV ((clock_get_freq() / (2 * PD_DATARATE))) /* threshold for 1 300-khz period */ #define PERIOD 4 -#define NB_PERIOD(from, to) ((((to) - (from) + (PERIOD/2)) & 0xFF) / PERIOD) -#define PERIOD_THRESHOLD ((PERIOD + 2*PERIOD) / 2) +#define NB_PERIOD(from, to) ((((to) - (from) + (PERIOD / 2)) & 0xFF) / PERIOD) +#define PERIOD_THRESHOLD ((PERIOD + 2 * PERIOD) / 2) static struct pd_physical { /* samples for the PD messages */ @@ -73,8 +74,8 @@ static struct pd_physical { } pd_phy[CONFIG_USB_PD_PORT_MAX_COUNT]; /* keep track of RX edge timing in order to trigger receive */ -static timestamp_t - rx_edge_ts[CONFIG_USB_PD_PORT_MAX_COUNT][PD_RX_TRANSITION_COUNT]; +static timestamp_t rx_edge_ts[CONFIG_USB_PD_PORT_MAX_COUNT] + [PD_RX_TRANSITION_COUNT]; static int rx_edge_ts_idx[CONFIG_USB_PD_PORT_MAX_COUNT]; /* keep track of transmit polarity for DMA interrupt */ @@ -95,8 +96,8 @@ static int wait_bits(int port, int nb) avail = dma_bytes_done(rx, PD_MAX_RAW_SIZE); if (avail < nb) { /* no received yet ... */ - while ((dma_bytes_done(rx, PD_MAX_RAW_SIZE) < nb) - && !(pd_phy[port].tim_rx->sr & 4)) + while ((dma_bytes_done(rx, PD_MAX_RAW_SIZE) < nb) && + !(pd_phy[port].tim_rx->sr & 4)) ; /* optimized for latency, not CPU usage ... */ if (dma_bytes_done(rx, PD_MAX_RAW_SIZE) < nb) { CPRINTS("PD TMOUT RX %d/%d", @@ -117,8 +118,8 @@ int pd_dequeue_bits(int port, int off, int len, uint32_t *val) w = wait_bits(port, off + 2); if (w < 0) goto stream_err; - cnt = samples[off] - samples[off-1]; - if (!cnt || (cnt > 3*PERIOD)) + cnt = samples[off] - samples[off - 1]; + if (!cnt || (cnt > 3 * PERIOD)) goto stream_err; off++; if (cnt <= PERIOD_THRESHOLD) { @@ -127,20 +128,22 @@ int pd_dequeue_bits(int port, int off, int len, uint32_t *val) if (w < 0) goto stream_err; */ - cnt = samples[off] - samples[off-1]; - if (cnt > PERIOD_THRESHOLD) + cnt = samples[off] - samples[off - 1]; + if (cnt > PERIOD_THRESHOLD) goto stream_err; off++; } /* enqueue the bit of the last period */ - pd_phy[port].d_last = (pd_phy[port].d_last >> 1) - | (cnt <= PERIOD_THRESHOLD ? 0x80000000 : 0); + pd_phy[port].d_last = + (pd_phy[port].d_last >> 1) | + (cnt <= PERIOD_THRESHOLD ? 0x80000000 : 0); pd_phy[port].d_lastlen++; } if (off < PD_MAX_RAW_SIZE) { - *val = (pd_phy[port].d_last << (pd_phy[port].d_lastlen - len)) - >> (32 - len); + *val = (pd_phy[port].d_last + << (pd_phy[port].d_lastlen - len)) >> + (32 - len); pd_phy[port].d_lastlen -= len; return off; } else { @@ -168,7 +171,7 @@ int pd_find_preamble(int port) /* wait if the bit is not received yet ... */ if (PD_MAX_RAW_SIZE - rx->cndtr < bit + 1) { while ((PD_MAX_RAW_SIZE - rx->cndtr < bit + 1) && - !(pd_phy[port].tim_rx->sr & 4)) + !(pd_phy[port].tim_rx->sr & 4)) ; if (pd_phy[port].tim_rx->sr & 4) { CPRINTS("PD TMOUT RX %d/%d", @@ -176,7 +179,7 @@ int pd_find_preamble(int port) return -1; } } - cnt = vals[bit] - vals[bit-1]; + cnt = vals[bit] - vals[bit - 1]; all = (all >> 1) | (cnt <= PERIOD_THRESHOLD ? BIT(31) : 0); if (all == 0x36db6db6) return bit - 1; /* should be SYNC-1 */ @@ -198,7 +201,7 @@ int pd_write_preamble(int port) msg[2] = PD_PREAMBLE; msg[3] = PD_PREAMBLE; pd_phy[port].b_toggle = 0x3FF; /* preamble ends with 1 */ - return 2*64; + return 2 * 64; } int pd_write_sym(int port, int bit_off, uint32_t val10) @@ -214,10 +217,10 @@ int pd_write_sym(int port, int bit_off, uint32_t val10) msg[word_idx] |= val << bit_idx; } else { msg[word_idx] |= val << bit_idx; - msg[word_idx+1] = val >> (32 - bit_idx); + msg[word_idx + 1] = val >> (32 - bit_idx); /* side effect: clear the new word when starting it */ } - return bit_off + 5*2; + return bit_off + 5 * 2; } int pd_write_last_edge(int port, int bit_off) @@ -239,7 +242,7 @@ int pd_write_last_edge(int port, int bit_off) } } /* ensure that the trailer is 0 */ - msg[word_idx+1] = 0; + msg[word_idx + 1] = 0; return bit_off + 3; } @@ -252,15 +255,15 @@ void pd_dump_packet(int port, const char *msg) CPRINTF("ERR %s:\n000:- ", msg); /* Packet debug output */ - for (bit = 1; bit < PD_MAX_RAW_SIZE; bit++) { - int cnt = NB_PERIOD(vals[bit-1], vals[bit]); + for (bit = 1; bit < PD_MAX_RAW_SIZE; bit++) { + int cnt = NB_PERIOD(vals[bit - 1], vals[bit]); if ((bit & 31) == 0) CPRINTF("\n%03d:", bit); CPRINTF("%1d ", cnt); } CPRINTF("><\n"); cflush(); - for (bit = 0; bit < PD_MAX_RAW_SIZE; bit++) { + for (bit = 0; bit < PD_MAX_RAW_SIZE; bit++) { if ((bit & 31) == 0) CPRINTF("\n%03d:", bit); CPRINTF("%02x ", vals[bit]); @@ -280,9 +283,9 @@ void pd_tx_spi_init(int port) spi->cr2 = STM32_SPI_CR2_TXDMAEN | STM32_SPI_CR2_DATASIZE(8); /* Enable the slave SPI: LSB first, force NSS, TX only, CPHA */ - spi->cr1 = STM32_SPI_CR1_SPE | STM32_SPI_CR1_LSBFIRST - | STM32_SPI_CR1_SSM | STM32_SPI_CR1_BIDIMODE - | STM32_SPI_CR1_BIDIOE | STM32_SPI_CR1_CPHA; + spi->cr1 = STM32_SPI_CR1_SPE | STM32_SPI_CR1_LSBFIRST | + STM32_SPI_CR1_SSM | STM32_SPI_CR1_BIDIMODE | + STM32_SPI_CR1_BIDIOE | STM32_SPI_CR1_CPHA; } static void tx_dma_done(void *data) @@ -303,7 +306,7 @@ static void tx_dma_done(void *data) pd_tx_disable(port, polarity); #if defined(CONFIG_COMMON_RUNTIME) && defined(CONFIG_DMA_DEFAULT_HANDLERS) - task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_DMA_TC, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_DMA_TC); #endif } @@ -330,9 +333,8 @@ int pd_start_tx(int port, int polarity, int bit_len) pd_phy[port].tim_tx->cnt = TX_CLOCK_DIV - 1; /* update DMA configuration */ - dma_prepare_tx(&(pd_phy[port].dma_tx_option), - DIV_ROUND_UP(bit_len, 8), - pd_phy[port].raw_samples); + dma_prepare_tx(&(pd_phy[port].dma_tx_option), DIV_ROUND_UP(bit_len, 8), + pd_phy[port].raw_samples); /* Flush data in write buffer so that DMA can get the latest data */ asm volatile("dmb;"); @@ -343,8 +345,7 @@ int pd_start_tx(int port, int polarity, int bit_len) if (!(pd_phy[port].dma_tx_option.flags & STM32_DMA_CCR_CIRC)) { /* Only enable interrupt if not in circular mode */ dma_enable_tc_interrupt_callback(DMAC_SPI_TX(port), - &tx_dma_done, - (void *)port); + &tx_dma_done, (void *)port); } #endif dma_go(tx); @@ -401,9 +402,10 @@ void pd_rx_start(int port) { /* start sampling the edges on the CC line using the RX timer */ dma_start_rx(&(pd_phy[port].dma_tim_option), PD_MAX_RAW_SIZE, - pd_phy[port].raw_samples); + pd_phy[port].raw_samples); /* enable TIM2 DMA requests */ - pd_phy[port].tim_rx->egr = 0x0001; /* reset counter / reload PSC */; + pd_phy[port].tim_rx->egr = 0x0001; /* reset counter / reload PSC */ + ; pd_phy[port].tim_rx->sr = 0; /* clear overflows */ pd_phy[port].tim_rx->cr1 |= 1; } @@ -441,8 +443,8 @@ void pd_rx_disable_monitoring(int port) uint64_t get_time_since_last_edge(int port) { int prev_idx = (rx_edge_ts_idx[port] == 0) ? - PD_RX_TRANSITION_COUNT - 1 : - rx_edge_ts_idx[port] - 1; + PD_RX_TRANSITION_COUNT - 1 : + rx_edge_ts_idx[port] - 1; return get_time().val - rx_edge_ts[port][prev_idx].val; } @@ -467,11 +469,12 @@ void pd_rx_handler(void) if (pending & EXTI_COMP_MASK(i)) { rx_edge_ts[i][rx_edge_ts_idx[i]].val = get_time().val; next_idx = (rx_edge_ts_idx[i] == - PD_RX_TRANSITION_COUNT - 1) ? - 0 : rx_edge_ts_idx[i] + 1; + PD_RX_TRANSITION_COUNT - 1) ? + 0 : + rx_edge_ts_idx[i] + 1; -#if defined(CONFIG_LOW_POWER_IDLE) && \ -defined(CONFIG_USB_PD_LOW_POWER_IDLE_WHEN_CONNECTED) +#if defined(CONFIG_LOW_POWER_IDLE) && \ + defined(CONFIG_USB_PD_LOW_POWER_IDLE_WHEN_CONNECTED) /* * Do not deep sleep while waiting for more edges. For * most boards, sleep is already disabled due to being @@ -487,8 +490,8 @@ defined(CONFIG_USB_PD_LOW_POWER_IDLE_WHEN_CONNECTED) * time, then trigger RX start. */ if ((rx_edge_ts[i][rx_edge_ts_idx[i]].val - - rx_edge_ts[i][next_idx].val) - < PD_RX_TRANSITION_WINDOW) { + rx_edge_ts[i][next_idx].val) < + PD_RX_TRANSITION_WINDOW) { /* start sampling */ pd_rx_start(i); /* @@ -507,7 +510,11 @@ defined(CONFIG_USB_PD_LOW_POWER_IDLE_WHEN_CONNECTED) } } #ifdef CONFIG_USB_PD_RX_COMP_IRQ -DECLARE_IRQ(STM32_IRQ_COMP, pd_rx_handler, 1); +static void _pd_rx_handler(void) +{ + pd_rx_handler(); +} +DECLARE_IRQ(STM32_IRQ_COMP, _pd_rx_handler, 1); #endif /* --- release hardware --- */ @@ -531,7 +538,7 @@ void pd_hw_init_rx(int port) phy->dma_tim_option.channel = DMAC_TIM_RX(port); phy->dma_tim_option.periph = (void *)(TIM_RX_CCR_REG(port)); phy->dma_tim_option.flags = STM32_DMA_CCR_MSIZE_8_BIT | - STM32_DMA_CCR_PSIZE_16_BIT; + STM32_DMA_CCR_PSIZE_16_BIT; /* --- set counter for RX timing : 2.4Mhz rate, free-running --- */ __hw_timer_enable_clock(TIM_CLOCK_PD_RX(port), 1); @@ -557,7 +564,8 @@ void pd_hw_init_rx(int port) phy->tim_rx->ccer = 0xB << ((TIM_RX_CCR_IDX(port) - 1) * 4); /* configure DMA request on CCRx update */ - phy->tim_rx->dier |= 1 << (8 + TIM_RX_CCR_IDX(port)); /* CCxDE */; + phy->tim_rx->dier |= 1 << (8 + TIM_RX_CCR_IDX(port)); /* CCxDE */ + ; /* set prescaler to /26 (F=1.2Mhz, T=0.8us) */ phy->tim_rx->psc = (clock_get_freq() / 2400000) - 1; /* Reload the pre-scaler and reset the counter (clear CCRx) */ @@ -586,18 +594,15 @@ void pd_hw_init_rx(int port) clock_wait_bus_cycles(BUS_APB, 1); /* currently in hi-speed mode : TODO revisit later, INM = PA0(INM6) */ STM32_COMP_CSR = STM32_COMP_CMP1MODE_LSPEED | - STM32_COMP_CMP1INSEL_INM6 | - CMP1OUTSEL | - STM32_COMP_CMP1HYST_HI | - STM32_COMP_CMP2MODE_LSPEED | - STM32_COMP_CMP2INSEL_INM6 | - CMP2OUTSEL | + STM32_COMP_CMP1INSEL_INM6 | CMP1OUTSEL | + STM32_COMP_CMP1HYST_HI | STM32_COMP_CMP2MODE_LSPEED | + STM32_COMP_CMP2INSEL_INM6 | CMP2OUTSEL | STM32_COMP_CMP2HYST_HI; #elif defined(CHIP_FAMILY_STM32L) STM32_RCC_APB1ENR |= BIT(31); /* turn on COMP */ - STM32_COMP_CSR = STM32_COMP_OUTSEL_TIM2_IC4 | STM32_COMP_INSEL_DAC_OUT1 - | STM32_COMP_SPEED_FAST; + STM32_COMP_CSR = STM32_COMP_OUTSEL_TIM2_IC4 | + STM32_COMP_INSEL_DAC_OUT1 | STM32_COMP_SPEED_FAST; /* route PB4 to COMP input2 through GR6_1 bit 4 (or PB5->GR6_2 bit 5) */ STM32_RI_ASCR2 |= BIT(4); #else @@ -634,9 +639,9 @@ void pd_hw_init(int port, enum pd_power_role role) phy->dma_tx_option.channel = DMAC_SPI_TX(port); phy->dma_tx_option.periph = (void *)&SPI_REGS(port)->dr; phy->dma_tx_option.flags = STM32_DMA_CCR_MSIZE_8_BIT | - STM32_DMA_CCR_PSIZE_8_BIT; + STM32_DMA_CCR_PSIZE_8_BIT; dma_prepare_tx(&(phy->dma_tx_option), PD_MAX_RAW_SIZE, - phy->raw_samples); + phy->raw_samples); /* configure registers used for timers */ phy->tim_tx = (void *)TIM_REG_TX(port); @@ -676,5 +681,5 @@ void pd_hw_init(int port, enum pd_power_role role) void pd_set_clock(int port, int freq) { - pd_phy[port].tim_tx->arr = clock_get_freq() / (2*freq); + pd_phy[port].tim_tx->arr = clock_get_freq() / (2 * freq); } diff --git a/chip/stm32/usb_power.c b/chip/stm32/usb_power.c index 90f0039c2c..589767f15c 100644 --- a/chip/stm32/usb_power.c +++ b/chip/stm32/usb_power.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,7 +14,7 @@ #include "usb_power.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) static int usb_power_init_inas(struct usb_power_config const *config); static int usb_power_read(struct usb_power_config const *config); @@ -42,16 +42,15 @@ void usb_power_deferred_tx(struct usb_power_config const *config) state->reports_xmit_active = state->reports_tail; /* Wait for the next command */ - usb_read_ep(config->endpoint, - config->ep->out_databuffer_max, - config->ep->out_databuffer); + usb_read_ep(config->endpoint, config->ep->out_databuffer_max, + config->ep->out_databuffer); return; } } /* Reset stream */ void usb_power_event(struct usb_power_config const *config, - enum usb_ep_event evt) + enum usb_ep_event evt) { if (evt != USB_EVENT_RESET) return; @@ -68,15 +67,15 @@ void usb_power_event(struct usb_power_config const *config, hook_call_deferred(config->ep->tx_deferred, 0); } - /* Write one or more power records to USB */ static int usb_power_write_line(struct usb_power_config const *config) { struct usb_power_state *state = config->state; - struct usb_power_report *r = (struct usb_power_report *)( - state->reports_data_area + - (USB_POWER_RECORD_SIZE(state->ina_count) - * state->reports_tail)); + struct usb_power_report *r = + (struct usb_power_report *)(state->reports_data_area + + (USB_POWER_RECORD_SIZE( + state->ina_count) * + state->reports_tail)); /* status + size + timestamps + power list */ size_t bytes = USB_POWER_RECORD_SIZE(state->ina_count); @@ -89,12 +88,12 @@ static int usb_power_write_line(struct usb_power_config const *config) recordcount = config->state->reports_head - config->state->reports_tail; else - recordcount = state->max_cached - - config->state->reports_tail; + recordcount = + state->max_cached - config->state->reports_tail; state->reports_xmit_active = state->reports_tail; - state->reports_tail = (state->reports_tail + recordcount) % - state->max_cached; + state->reports_tail = + (state->reports_tail + recordcount) % state->max_cached; usb_write_ep(config->endpoint, bytes * recordcount, r); return bytes; @@ -103,7 +102,6 @@ static int usb_power_write_line(struct usb_power_config const *config) return 0; } - static int usb_power_state_reset(struct usb_power_config const *config) { struct usb_power_state *state = config->state; @@ -117,7 +115,6 @@ static int usb_power_state_reset(struct usb_power_config const *config) return USB_POWER_SUCCESS; } - static int usb_power_state_stop(struct usb_power_config const *config) { struct usb_power_state *state = config->state; @@ -137,8 +134,6 @@ static int usb_power_state_stop(struct usb_power_config const *config) return USB_POWER_SUCCESS; } - - static int usb_power_state_start(struct usb_power_config const *config, union usb_power_command_data *cmd, int count) { @@ -182,13 +177,12 @@ static int usb_power_state_start(struct usb_power_config const *config, return USB_POWER_SUCCESS; } - static int usb_power_state_settime(struct usb_power_config const *config, - union usb_power_command_data *cmd, int count) + union usb_power_command_data *cmd, int count) { if (count != sizeof(struct usb_power_command_settime)) { - CPRINTS("[SETTIME] Error: count %d is not %d", - (int)count, sizeof(struct usb_power_command_settime)); + CPRINTS("[SETTIME] Error: count %d is not %d", (int)count, + sizeof(struct usb_power_command_settime)); return USB_POWER_ERROR_READ_SIZE; } @@ -201,9 +195,8 @@ static int usb_power_state_settime(struct usb_power_config const *config, return USB_POWER_SUCCESS; } - static int usb_power_state_addina(struct usb_power_config const *config, - union usb_power_command_data *cmd, int count) + union usb_power_command_data *cmd, int count) { struct usb_power_state *state = config->state; struct usb_power_ina_cfg *ina; @@ -217,8 +210,8 @@ static int usb_power_state_addina(struct usb_power_config const *config, } if (count != sizeof(struct usb_power_command_addina)) { - CPRINTS("[ADDINA] Error count %d is not %d", - (int)count, sizeof(struct usb_power_command_addina)); + CPRINTS("[ADDINA] Error count %d is not %d", (int)count, + sizeof(struct usb_power_command_addina)); return USB_POWER_ERROR_READ_SIZE; } @@ -286,8 +279,8 @@ static int usb_power_read(struct usb_power_config const *config) * If there is a USB packet waiting we process it and generate a * response. */ - uint8_t count = rx_ep_pending(config->endpoint); - uint8_t result = USB_POWER_SUCCESS; + uint8_t count = rx_ep_pending(config->endpoint); + uint8_t result = USB_POWER_SUCCESS; union usb_power_command_data *cmd = (union usb_power_command_data *)config->ep->out_databuffer; @@ -314,14 +307,14 @@ static int usb_power_read(struct usb_power_config const *config) result = usb_power_state_start(config, cmd, count); if (result == USB_POWER_SUCCESS) { /* Send back actual integration time. */ - ep->in_databuffer[1] = - (state->integration_us >> 0) & 0xff; - ep->in_databuffer[2] = - (state->integration_us >> 8) & 0xff; - ep->in_databuffer[3] = - (state->integration_us >> 16) & 0xff; - ep->in_databuffer[4] = - (state->integration_us >> 24) & 0xff; + ep->in_databuffer[1] = (state->integration_us >> 0) & + 0xff; + ep->in_databuffer[2] = (state->integration_us >> 8) & + 0xff; + ep->in_databuffer[3] = (state->integration_us >> 16) & + 0xff; + ep->in_databuffer[4] = (state->integration_us >> 24) & + 0xff; in_msgsize += 4; } break; @@ -363,8 +356,6 @@ static int usb_power_read(struct usb_power_config const *config) return EC_SUCCESS; } - - /****************************************************************************** * INA231 interface. * List the registers and fields here. @@ -374,20 +365,19 @@ static int usb_power_read(struct usb_power_config const *config) #define INA231_REG_CONF 0 #define INA231_REG_RSHV 1 #define INA231_REG_BUSV 2 -#define INA231_REG_PWR 3 +#define INA231_REG_PWR 3 #define INA231_REG_CURR 4 -#define INA231_REG_CAL 5 -#define INA231_REG_EN 6 - - -#define INA231_CONF_AVG(val) (((int)(val & 0x7)) << 9) -#define INA231_CONF_BUS_TIME(val) (((int)(val & 0x7)) << 6) -#define INA231_CONF_SHUNT_TIME(val) (((int)(val & 0x7)) << 3) -#define INA231_CONF_MODE(val) (((int)(val & 0x7)) << 0) -#define INA231_MODE_OFF 0x0 -#define INA231_MODE_SHUNT 0x5 -#define INA231_MODE_BUS 0x6 -#define INA231_MODE_BOTH 0x7 +#define INA231_REG_CAL 5 +#define INA231_REG_EN 6 + +#define INA231_CONF_AVG(val) (((int)(val & 0x7)) << 9) +#define INA231_CONF_BUS_TIME(val) (((int)(val & 0x7)) << 6) +#define INA231_CONF_SHUNT_TIME(val) (((int)(val & 0x7)) << 3) +#define INA231_CONF_MODE(val) (((int)(val & 0x7)) << 0) +#define INA231_MODE_OFF 0x0 +#define INA231_MODE_SHUNT 0x5 +#define INA231_MODE_BUS 0x6 +#define INA231_MODE_BOTH 0x7 int reg_type_mapping(enum usb_power_ina_type ina_type) { @@ -406,53 +396,47 @@ int reg_type_mapping(enum usb_power_ina_type ina_type) } } -uint16_t ina2xx_readagain(uint8_t port, uint16_t slave_addr_flags) +uint16_t ina2xx_readagain(uint8_t port, uint16_t addr_flags) { int res; uint16_t val; - res = i2c_xfer(port, slave_addr_flags, - NULL, 0, (uint8_t *)&val, sizeof(uint16_t)); + res = i2c_xfer(port, addr_flags, NULL, 0, (uint8_t *)&val, + sizeof(uint16_t)); if (res) { - CPRINTS("INA2XX I2C readagain failed p:%d a:%02x", - (int)port, (int)I2C_GET_ADDR(slave_addr_flags)); + CPRINTS("INA2XX I2C readagain failed p:%d a:%02x", (int)port, + (int)I2C_STRIP_FLAGS(addr_flags)); return 0x0bad; } return (val >> 8) | ((val & 0xff) << 8); } - -uint16_t ina2xx_read(uint8_t port, uint16_t slave_addr_flags, - uint8_t reg) +uint16_t ina2xx_read(uint8_t port, uint16_t addr_flags, uint8_t reg) { int res; int val; - res = i2c_read16(port, slave_addr_flags, reg, &val); + res = i2c_read16(port, addr_flags, reg, &val); if (res) { - CPRINTS("INA2XX I2C read failed p:%d a:%02x, r:%02x", - (int)port, (int)I2C_GET_ADDR(slave_addr_flags), - (int)reg); + CPRINTS("INA2XX I2C read failed p:%d a:%02x, r:%02x", (int)port, + (int)I2C_STRIP_FLAGS(addr_flags), (int)reg); return 0x0bad; } return (val >> 8) | ((val & 0xff) << 8); } -int ina2xx_write(uint8_t port, uint16_t slave_addr_flags, - uint8_t reg, uint16_t val) +int ina2xx_write(uint8_t port, uint16_t addr_flags, uint8_t reg, uint16_t val) { int res; uint16_t be_val = (val >> 8) | ((val & 0xff) << 8); - res = i2c_write16(port, slave_addr_flags, reg, be_val); + res = i2c_write16(port, addr_flags, reg, be_val); if (res) CPRINTS("INA2XX I2C write failed"); return res; } - - /****************************************************************************** * Background tasks * @@ -462,11 +446,10 @@ int ina2xx_write(uint8_t port, uint16_t slave_addr_flags, */ /* INA231 integration and averaging time presets, indexed by register value */ -#define NELEMS(x) (sizeof(x) / sizeof((x)[0])) -static const int average_settings[] = { - 1, 4, 16, 64, 128, 256, 512, 1024}; -static const int conversion_time_us[] = { - 140, 204, 332, 588, 1100, 2116, 4156, 8244}; +#define NELEMS(x) (sizeof(x) / sizeof((x)[0])) +static const int average_settings[] = { 1, 4, 16, 64, 128, 256, 512, 1024 }; +static const int conversion_time_us[] = { 140, 204, 332, 588, + 1100, 2116, 4156, 8244 }; static int usb_power_init_inas(struct usb_power_config const *config) { @@ -491,8 +474,7 @@ static int usb_power_init_inas(struct usb_power_config const *config) /* Find an averaging setting from the INA presets that fits. */ while (avg < (NELEMS(average_settings) - 1)) { if ((conversion_time_us[shunt_time] * - average_settings[avg + 1]) - > target_us) + average_settings[avg + 1]) > target_us) break; avg++; } @@ -507,15 +489,15 @@ static int usb_power_init_inas(struct usb_power_config const *config) #ifdef USB_POWER_VERBOSE { - int conf, cal; - - conf = ina2xx_read(ina->port, ina->addr_flags, - INA231_REG_CONF); - cal = ina2xx_read(ina->port, ina->addr_flags, - INA231_REG_CAL); - CPRINTS("[CAP] %d (%d,0x%02x): conf:%x, cal:%x", - i, ina->port, I2C_GET_ADDR(ina->addr_flags), - conf, cal); + int conf, cal; + + conf = ina2xx_read(ina->port, ina->addr_flags, + INA231_REG_CONF); + cal = ina2xx_read(ina->port, ina->addr_flags, + INA231_REG_CAL); + CPRINTS("[CAP] %d (%d,0x%02x): conf:%x, cal:%x", i, + ina->port, I2C_STRIP_FLAGS(ina->addr_flags), + conf, cal); } #endif /* @@ -536,54 +518,53 @@ static int usb_power_init_inas(struct usb_power_config const *config) if (ina->scale == 0) return -1; value = (5120000 * 100) / (ina->scale * ina->rs); - ret = ina2xx_write(ina->port, ina->addr_flags, - INA231_REG_CAL, value); + ret = ina2xx_write(ina->port, ina->addr_flags, INA231_REG_CAL, + value); if (ret != EC_SUCCESS) { CPRINTS("[CAP] usb_power_init_inas CAL FAIL: %d", ret); return ret; } #ifdef USB_POWER_VERBOSE { - int actual; + int actual; - actual = ina2xx_read(ina->port, ina->addr_flags, - INA231_REG_CAL); - CPRINTS("[CAP] scale: %d uA/div, %d uW/div, cal:%x act:%x", - ina->scale / 100, ina->scale*25/100, value, actual); + actual = ina2xx_read(ina->port, ina->addr_flags, + INA231_REG_CAL); + CPRINTS("[CAP] scale: %d uA/div, %d uW/div, cal:%x act:%x", + ina->scale / 100, ina->scale * 25 / 100, value, + actual); } #endif /* Conversion time, shunt + bus, set average. */ value = INA231_CONF_MODE(INA231_MODE_BOTH) | INA231_CONF_SHUNT_TIME(shunt_time) | - INA231_CONF_BUS_TIME(shunt_time) | - INA231_CONF_AVG(avg); - ret = ina2xx_write(ina->port, ina->addr_flags, - INA231_REG_CONF, value); + INA231_CONF_BUS_TIME(shunt_time) | INA231_CONF_AVG(avg); + ret = ina2xx_write(ina->port, ina->addr_flags, INA231_REG_CONF, + value); if (ret != EC_SUCCESS) { CPRINTS("[CAP] usb_power_init_inas CONF FAIL: %d", ret); return ret; } #ifdef USB_POWER_VERBOSE { - int actual; + int actual; - actual = ina2xx_read(ina->port, ina->addr_flags, - INA231_REG_CONF); - CPRINTS("[CAP] %d (%d,0x%02x): conf:%x, act:%x", - i, ina->port, I2C_GET_ADDR(ina->addr_flags), - value, actual); + actual = ina2xx_read(ina->port, ina->addr_flags, + INA231_REG_CONF); + CPRINTS("[CAP] %d (%d,0x%02x): conf:%x, act:%x", i, + ina->port, I2C_STRIP_FLAGS(ina->addr_flags), + value, actual); } #endif #ifdef USB_POWER_VERBOSE { - int busv_mv = - (ina2xx_read(ina->port, ina->addr_flags, - INA231_REG_BUSV) - * 125) / 100; - - CPRINTS("[CAP] %d (%d,0x%02x): busv:%dmv", - i, ina->port, I2C_GET_ADDR(ina->addr_flags), - busv_mv); + int busv_mv = (ina2xx_read(ina->port, ina->addr_flags, + INA231_REG_BUSV) * + 125) / + 100; + + CPRINTS("[CAP] %d (%d,0x%02x): busv:%dmv", i, ina->port, + I2C_STRIP_FLAGS(ina->addr_flags), busv_mv); } #endif /* Initialize read from power register. This register address @@ -600,7 +581,6 @@ static int usb_power_init_inas(struct usb_power_config const *config) return EC_SUCCESS; } - /* * Read each INA's power integration measurement. * @@ -614,19 +594,20 @@ static int usb_power_get_samples(struct usb_power_config const *config) { uint64_t time = get_time().val; struct usb_power_state *state = config->state; - struct usb_power_report *r = (struct usb_power_report *)( - state->reports_data_area + - (USB_POWER_RECORD_SIZE(state->ina_count) - * state->reports_head)); + struct usb_power_report *r = + (struct usb_power_report *)(state->reports_data_area + + (USB_POWER_RECORD_SIZE( + state->ina_count) * + state->reports_head)); struct usb_power_ina_cfg *inas = state->ina_cfg; int i; /* TODO(nsanders): Would we prefer to evict oldest? */ - if (((state->reports_head + 1) % USB_POWER_MAX_CACHED(state->ina_count)) - == state->reports_xmit_active) { - CPRINTS("Overflow! h:%d a:%d t:%d (%d)", - state->reports_head, state->reports_xmit_active, - state->reports_tail, + if (((state->reports_head + 1) % + USB_POWER_MAX_CACHED(state->ina_count)) == + state->reports_xmit_active) { + CPRINTS("Overflow! h:%d a:%d t:%d (%d)", state->reports_head, + state->reports_xmit_active, state->reports_tail, USB_POWER_MAX_CACHED(state->ina_count)); return USB_POWER_ERROR_OVERFLOW; } @@ -650,47 +631,48 @@ static int usb_power_get_samples(struct usb_power_config const *config) */ if (ina->shared) regval = ina2xx_read(ina->port, ina->addr_flags, - reg_type_mapping(ina->type)); + reg_type_mapping(ina->type)); else - regval = ina2xx_readagain(ina->port, - ina->addr_flags); + regval = ina2xx_readagain(ina->port, ina->addr_flags); r->power[i] = regval; #ifdef USB_POWER_VERBOSE { - int current; - int power; - int voltage; - int bvoltage; - - voltage = ina2xx_read(ina->port, ina->addr_flags, - INA231_REG_RSHV); - bvoltage = ina2xx_read(ina->port, ina->addr_flags, - INA231_REG_BUSV); - current = ina2xx_read(ina->port, ina->addr_flags, - INA231_REG_CURR); - power = ina2xx_read(ina->port, ina->addr_flags, - INA231_REG_PWR); - { - int uV = ((int)voltage * 25) / 10; - int mV = ((int)bvoltage * 125) / 100; - int uA = (uV * 1000) / ina->rs; - int CuA = (((int)current * ina->scale) / 100); - int uW = (((int)power * ina->scale*25)/100); - - CPRINTS("[CAP] %d (%d,0x%02x): %dmV / %dmO = %dmA", - i, ina->port, I2C_GET_ADDR(ina->addr_flags), - uV/1000, ina->rs, uA/1000); - CPRINTS("[CAP] %duV %dmV %duA %dCuA " - "%duW v:%04x, b:%04x, p:%04x", - uV, mV, uA, CuA, uW, voltage, bvoltage, power); - } + int current; + int power; + int voltage; + int bvoltage; + + voltage = ina2xx_read(ina->port, ina->addr_flags, + INA231_REG_RSHV); + bvoltage = ina2xx_read(ina->port, ina->addr_flags, + INA231_REG_BUSV); + current = ina2xx_read(ina->port, ina->addr_flags, + INA231_REG_CURR); + power = ina2xx_read(ina->port, ina->addr_flags, + INA231_REG_PWR); + { + int uV = ((int)voltage * 25) / 10; + int mV = ((int)bvoltage * 125) / 100; + int uA = (uV * 1000) / ina->rs; + int CuA = (((int)current * ina->scale) / 100); + int uW = (((int)power * ina->scale * 25) / 100); + + CPRINTS("[CAP] %d (%d,0x%02x): %dmV / %dmO = %dmA", + i, ina->port, + I2C_STRIP_FLAGS(ina->addr_flags), + uV / 1000, ina->rs, uA / 1000); + CPRINTS("[CAP] %duV %dmV %duA %dCuA " + "%duW v:%04x, b:%04x, p:%04x", + uV, mV, uA, CuA, uW, voltage, bvoltage, + power); + } } #endif } /* Mark this slot as used. */ state->reports_head = (state->reports_head + 1) % - USB_POWER_MAX_CACHED(state->ina_count); + USB_POWER_MAX_CACHED(state->ina_count); return EC_SUCCESS; } @@ -730,4 +712,3 @@ void usb_power_deferred_cap(struct usb_power_config const *config) if (config->state->state == USB_POWER_STATE_CAPTURING) hook_call_deferred(config->deferred_cap, timeout); } - diff --git a/chip/stm32/usb_power.h b/chip/stm32/usb_power.h index 68b7f75ca2..1445fcea0f 100644 --- a/chip/stm32/usb_power.h +++ b/chip/stm32/usb_power.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -38,7 +38,8 @@ * * addina: 0x0002 * +--------+--------------------------+-------------+--------------+-----------+--------+ - * | 0x0002 | 1B: 4b: extender 4b: bus | 1B:INA type | 1B: INA addr | 1B: extra | 4B: Rs | + * | 0x0002 | 1B: 4b: extender 4b: bus | 1B:INA type | 1B: INA addr | 1B: + *extra | 4B: Rs | * +--------+--------------------------+-------------+--------------+-----------+--------+ * * start: 0x0003 @@ -90,40 +91,40 @@ /* 8b status field. */ enum usb_power_error { - USB_POWER_SUCCESS = 0x00, - USB_POWER_ERROR_I2C = 0x01, - USB_POWER_ERROR_OVERFLOW = 0x02, - USB_POWER_ERROR_NOT_SETUP = 0x03, - USB_POWER_ERROR_NOT_CAPTURING = 0x04, - USB_POWER_ERROR_TIMEOUT = 0x05, - USB_POWER_ERROR_BUSY = 0x06, - USB_POWER_ERROR_READ_SIZE = 0x07, - USB_POWER_ERROR_FULL = 0x08, - USB_POWER_ERROR_INVAL = 0x09, - USB_POWER_ERROR_UNKNOWN = 0x80, + USB_POWER_SUCCESS = 0x00, + USB_POWER_ERROR_I2C = 0x01, + USB_POWER_ERROR_OVERFLOW = 0x02, + USB_POWER_ERROR_NOT_SETUP = 0x03, + USB_POWER_ERROR_NOT_CAPTURING = 0x04, + USB_POWER_ERROR_TIMEOUT = 0x05, + USB_POWER_ERROR_BUSY = 0x06, + USB_POWER_ERROR_READ_SIZE = 0x07, + USB_POWER_ERROR_FULL = 0x08, + USB_POWER_ERROR_INVAL = 0x09, + USB_POWER_ERROR_UNKNOWN = 0x80, }; /* 16b command field. */ enum usb_power_command { - USB_POWER_CMD_RESET = 0x0000, - USB_POWER_CMD_STOP = 0x0001, - USB_POWER_CMD_ADDINA = 0x0002, - USB_POWER_CMD_START = 0x0003, - USB_POWER_CMD_NEXT = 0x0004, - USB_POWER_CMD_SETTIME = 0x0005, + USB_POWER_CMD_RESET = 0x0000, + USB_POWER_CMD_STOP = 0x0001, + USB_POWER_CMD_ADDINA = 0x0002, + USB_POWER_CMD_START = 0x0003, + USB_POWER_CMD_NEXT = 0x0004, + USB_POWER_CMD_SETTIME = 0x0005, }; /* Addina "INA Type" field. */ enum usb_power_ina_type { - USBP_INA231_POWER = 0x01, - USBP_INA231_BUSV = 0x02, - USBP_INA231_CURRENT = 0x03, - USBP_INA231_SHUNTV = 0x04, + USBP_INA231_POWER = 0x01, + USBP_INA231_BUSV = 0x02, + USBP_INA231_CURRENT = 0x03, + USBP_INA231_SHUNTV = 0x04, }; /* Internal state machine values */ enum usb_power_states { - USB_POWER_STATE_OFF = 0, + USB_POWER_STATE_OFF = 0, USB_POWER_STATE_SETUP, USB_POWER_STATE_CAPTURING, }; @@ -154,8 +155,7 @@ struct usb_power_ina_cfg { int shared; }; - -struct __attribute__ ((__packed__)) usb_power_report { +struct __attribute__((__packed__)) usb_power_report { uint8_t status; uint8_t size; uint64_t timestamp; @@ -163,17 +163,19 @@ struct __attribute__ ((__packed__)) usb_power_report { }; /* Must be 4 byte aligned */ -#define USB_POWER_RECORD_SIZE(ina_count) \ - ((((sizeof(struct usb_power_report) \ - - (sizeof(uint16_t) * USB_POWER_MAX_READ_COUNT) \ - + (sizeof(uint16_t) * (ina_count))) + 3) / 4) * 4) - -#define USB_POWER_DATA_SIZE \ +#define USB_POWER_RECORD_SIZE(ina_count) \ + ((((sizeof(struct usb_power_report) - \ + (sizeof(uint16_t) * USB_POWER_MAX_READ_COUNT) + \ + (sizeof(uint16_t) * (ina_count))) + \ + 3) / \ + 4) * \ + 4) + +#define USB_POWER_DATA_SIZE \ (sizeof(struct usb_power_report) * (USB_POWER_MIN_CACHED + 1)) -#define USB_POWER_MAX_CACHED(ina_count) \ +#define USB_POWER_MAX_CACHED(ina_count) \ (USB_POWER_DATA_SIZE / USB_POWER_RECORD_SIZE(ina_count)) - struct usb_power_state { /* * The power data acquisition must be setup, then started, in order to @@ -212,7 +214,6 @@ struct usb_power_state { uint8_t tx_buf[USB_MAX_PACKET_SIZE * 4]; }; - /* * Compile time Per-USB gpio configuration stored in flash. Instances of this * structure are provided by the user of the USB gpio. This structure binds @@ -234,12 +235,12 @@ struct usb_power_config { const struct deferred_data *deferred_cap; }; -struct __attribute__ ((__packed__)) usb_power_command_start { +struct __attribute__((__packed__)) usb_power_command_start { uint16_t command; uint32_t integration_us; }; -struct __attribute__ ((__packed__)) usb_power_command_addina { +struct __attribute__((__packed__)) usb_power_command_addina { uint16_t command; uint8_t port; uint8_t type; @@ -248,7 +249,7 @@ struct __attribute__ ((__packed__)) usb_power_command_addina { uint32_t rs; }; -struct __attribute__ ((__packed__)) usb_power_command_settime { +struct __attribute__((__packed__)) usb_power_command_settime { uint16_t command; uint64_t time; }; @@ -260,7 +261,6 @@ union usb_power_command_data { struct usb_power_command_settime settime; }; - /* * Convenience macro for defining a USB INA Power driver. * @@ -273,92 +273,96 @@ union usb_power_command_data { * ENDPOINT is the index of the USB bulk endpoint used for receiving and * transmitting bytes. */ -#define USB_POWER_CONFIG(NAME, \ - INTERFACE, \ - ENDPOINT) \ - static void CONCAT2(NAME, _deferred_tx_)(void); \ - DECLARE_DEFERRED(CONCAT2(NAME, _deferred_tx_)); \ - static void CONCAT2(NAME, _deferred_rx_)(void); \ - DECLARE_DEFERRED(CONCAT2(NAME, _deferred_rx_)); \ - static void CONCAT2(NAME, _deferred_cap_)(void); \ - DECLARE_DEFERRED(CONCAT2(NAME, _deferred_cap_)); \ - struct usb_power_state CONCAT2(NAME, _state_) = { \ - .state = USB_POWER_STATE_OFF, \ - .ina_count = 0, \ - .integration_us = 0, \ - .reports_head = 0, \ - .reports_tail = 0, \ - .wall_offset = 0, \ - }; \ - static struct dwc_usb_ep CONCAT2(NAME, _ep_ctl) = { \ - .max_packet = USB_MAX_PACKET_SIZE, \ - .tx_fifo = ENDPOINT, \ - .out_pending = 0, \ - .out_data = 0, \ - .out_databuffer = 0, \ - .out_databuffer_max = 0, \ - .rx_deferred = &CONCAT2(NAME, _deferred_rx__data), \ - .in_packets = 0, \ - .in_pending = 0, \ - .in_data = 0, \ - .in_databuffer = 0, \ - .in_databuffer_max = 0, \ - .tx_deferred = &CONCAT2(NAME, _deferred_tx__data), \ - }; \ - struct usb_power_config const NAME = { \ - .state = &CONCAT2(NAME, _state_), \ - .ep = &CONCAT2(NAME, _ep_ctl), \ - .interface = INTERFACE, \ - .endpoint = ENDPOINT, \ - .deferred_cap = &CONCAT2(NAME, _deferred_cap__data), \ - }; \ - const struct usb_interface_descriptor \ - USB_IFACE_DESC(INTERFACE) = { \ - .bLength = USB_DT_INTERFACE_SIZE, \ - .bDescriptorType = USB_DT_INTERFACE, \ - .bInterfaceNumber = INTERFACE, \ - .bAlternateSetting = 0, \ - .bNumEndpoints = 2, \ - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ - .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_POWER, \ - .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_POWER, \ - .iInterface = 0, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 0) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = 0x80 | ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk IN */, \ - .wMaxPacketSize = USB_MAX_PACKET_SIZE, \ - .bInterval = 1, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 1) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk OUT */, \ - .wMaxPacketSize = USB_MAX_PACKET_SIZE, \ - .bInterval = 0, \ - }; \ - static void CONCAT2(NAME, _ep_tx_) (void) { usb_epN_tx(ENDPOINT); } \ - static void CONCAT2(NAME, _ep_rx_) (void) { usb_epN_rx(ENDPOINT); } \ - static void CONCAT2(NAME, _ep_event_)(enum usb_ep_event evt) \ - { \ - usb_power_event(&NAME, evt); \ - } \ - USB_DECLARE_EP(ENDPOINT, \ - CONCAT2(NAME, _ep_tx_), \ - CONCAT2(NAME, _ep_rx_), \ - CONCAT2(NAME, _ep_event_)); \ - static void CONCAT2(NAME, _deferred_tx_)(void) \ - { usb_power_deferred_tx(&NAME); } \ - static void CONCAT2(NAME, _deferred_rx_)(void) \ - { usb_power_deferred_rx(&NAME); } \ - static void CONCAT2(NAME, _deferred_cap_)(void) \ - { usb_power_deferred_cap(&NAME); } - +#define USB_POWER_CONFIG(NAME, INTERFACE, ENDPOINT) \ + static void CONCAT2(NAME, _deferred_tx_)(void); \ + DECLARE_DEFERRED(CONCAT2(NAME, _deferred_tx_)); \ + static void CONCAT2(NAME, _deferred_rx_)(void); \ + DECLARE_DEFERRED(CONCAT2(NAME, _deferred_rx_)); \ + static void CONCAT2(NAME, _deferred_cap_)(void); \ + DECLARE_DEFERRED(CONCAT2(NAME, _deferred_cap_)); \ + struct usb_power_state CONCAT2(NAME, _state_) = { \ + .state = USB_POWER_STATE_OFF, \ + .ina_count = 0, \ + .integration_us = 0, \ + .reports_head = 0, \ + .reports_tail = 0, \ + .wall_offset = 0, \ + }; \ + static struct dwc_usb_ep CONCAT2(NAME, _ep_ctl) = { \ + .max_packet = USB_MAX_PACKET_SIZE, \ + .tx_fifo = ENDPOINT, \ + .out_pending = 0, \ + .out_data = 0, \ + .out_databuffer = 0, \ + .out_databuffer_max = 0, \ + .rx_deferred = &CONCAT2(NAME, _deferred_rx__data), \ + .in_packets = 0, \ + .in_pending = 0, \ + .in_data = 0, \ + .in_databuffer = 0, \ + .in_databuffer_max = 0, \ + .tx_deferred = &CONCAT2(NAME, _deferred_tx__data), \ + }; \ + struct usb_power_config const NAME = { \ + .state = &CONCAT2(NAME, _state_), \ + .ep = &CONCAT2(NAME, _ep_ctl), \ + .interface = INTERFACE, \ + .endpoint = ENDPOINT, \ + .deferred_cap = &CONCAT2(NAME, _deferred_cap__data), \ + }; \ + const struct usb_interface_descriptor USB_IFACE_DESC(INTERFACE) = { \ + .bLength = USB_DT_INTERFACE_SIZE, \ + .bDescriptorType = USB_DT_INTERFACE, \ + .bInterfaceNumber = INTERFACE, \ + .bAlternateSetting = 0, \ + .bNumEndpoints = 2, \ + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ + .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_POWER, \ + .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_POWER, \ + .iInterface = 0, \ + }; \ + const struct usb_endpoint_descriptor USB_EP_DESC(INTERFACE, 0) = { \ + .bLength = USB_DT_ENDPOINT_SIZE, \ + .bDescriptorType = USB_DT_ENDPOINT, \ + .bEndpointAddress = 0x80 | ENDPOINT, \ + .bmAttributes = 0x02 /* Bulk IN */, \ + .wMaxPacketSize = USB_MAX_PACKET_SIZE, \ + .bInterval = 1, \ + }; \ + const struct usb_endpoint_descriptor USB_EP_DESC(INTERFACE, 1) = { \ + .bLength = USB_DT_ENDPOINT_SIZE, \ + .bDescriptorType = USB_DT_ENDPOINT, \ + .bEndpointAddress = ENDPOINT, \ + .bmAttributes = 0x02 /* Bulk OUT */, \ + .wMaxPacketSize = USB_MAX_PACKET_SIZE, \ + .bInterval = 0, \ + }; \ + static void CONCAT2(NAME, _ep_tx_)(void) \ + { \ + usb_epN_tx(ENDPOINT); \ + } \ + static void CONCAT2(NAME, _ep_rx_)(void) \ + { \ + usb_epN_rx(ENDPOINT); \ + } \ + static void CONCAT2(NAME, _ep_event_)(enum usb_ep_event evt) \ + { \ + usb_power_event(&NAME, evt); \ + } \ + USB_DECLARE_EP(ENDPOINT, CONCAT2(NAME, _ep_tx_), \ + CONCAT2(NAME, _ep_rx_), CONCAT2(NAME, _ep_event_)); \ + static void CONCAT2(NAME, _deferred_tx_)(void) \ + { \ + usb_power_deferred_tx(&NAME); \ + } \ + static void CONCAT2(NAME, _deferred_rx_)(void) \ + { \ + usb_power_deferred_rx(&NAME); \ + } \ + static void CONCAT2(NAME, _deferred_cap_)(void) \ + { \ + usb_power_deferred_cap(&NAME); \ + } /* * Handle power request in a deferred callback. @@ -374,10 +378,6 @@ void usb_power_deferred_cap(struct usb_power_config const *config); void usb_power_tx(struct usb_power_config const *config); void usb_power_rx(struct usb_power_config const *config); void usb_power_event(struct usb_power_config const *config, - enum usb_ep_event evt); - - - + enum usb_ep_event evt); #endif /* __CROS_EC_USB_DWC_POWER_H */ - diff --git a/chip/stm32/usb_spi.c b/chip/stm32/usb_spi.c index 54caae015e..7e45563e4a 100644 --- a/chip/stm32/usb_spi.c +++ b/chip/stm32/usb_spi.c @@ -1,24 +1,160 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" +#include "gpio.h" #include "link_defs.h" #include "registers.h" #include "spi.h" +#include "timer.h" #include "usb_descriptor.h" #include "usb_hw.h" #include "usb_spi.h" #include "util.h" +/* How long to wait for a flash page programming. */ +#define FLASH_BUSY_POLL_TIMEOUT_USEC (1000 * MSEC) + +const uint8_t JEDEC_READ_STATUS = 0x05; +const uint8_t JEDEC_STATUS_BUSY = 0x01; + /* Forward declare platform specific functions. */ -static bool usb_spi_received_packet(struct usb_spi_config const *config); -static bool usb_spi_transmitted_packet(struct usb_spi_config const *config); -static void usb_spi_read_packet(struct usb_spi_config const *config, - struct usb_spi_packet_ctx *packet); -static void usb_spi_write_packet(struct usb_spi_config const *config, - struct usb_spi_packet_ctx *packet); +static bool usb_spi_received_packet(void); +static bool usb_spi_transmitted_packet(void); +static void usb_spi_read_packet(struct usb_spi_packet_ctx *packet); +static void usb_spi_write_packet(struct usb_spi_packet_ctx *packet); + +struct usb_spi_transfer_ctx { + /* Address of transfer buffer. */ + uint8_t *buffer; + /* Number of bytes in the transfer. */ + size_t transfer_size; + /* Number of bytes transferred. */ + size_t transfer_index; +}; + +enum usb_spi_mode { + /* No tasks are required. */ + USB_SPI_MODE_IDLE = 0, + /* Indicates the device needs to send it's USB SPI configuration.*/ + USB_SPI_MODE_SEND_CONFIGURATION, + /* Indicates the device needs to respond to chip select. */ + USB_SPI_MODE_SEND_CHIP_SELECT_RESPONSE, + /* Indicates we device needs start the SPI transfer. */ + USB_SPI_MODE_START_SPI, + /* Indicates we should start a transfer response. */ + USB_SPI_MODE_START_RESPONSE, + /* Indicates we need to continue a transfer response. */ + USB_SPI_MODE_CONTINUE_RESPONSE, +}; + +struct usb_spi_state { + /* + * The SPI bridge must be enabled both locally and by the host to allow + * access to the SPI device. The enabled_host flag is set and cleared + * by sending USB_SPI_REQ_ENABLE and USB_SPI_REQ_DISABLE to the device + * control endpoint. The enabled_device flag is set by calling + * usb_spi_enable. + */ + uint8_t enabled_host; + uint8_t enabled_device; + + /* + * The current enabled state. This is only updated in the deferred + * callback. Whenever either of the host or device specific enable + * flags is changed the deferred callback is queued, and it will check + * their combined state against this flag. If the combined state is + * different, then one of usb_spi_board_enable or usb_spi_board_disable + * is called and this flag is updated. This ensures that the board + * specific state update routines are only called from the deferred + * callback. + */ + uint8_t enabled; + + /* + * The index of the SPI port currently receiving forwarded transactions, + * default is zero. + */ + uint8_t current_spi_device_idx; + + /* Mark the current operating mode. */ + enum usb_spi_mode mode; + + /* + * Stores the status code response for the transfer, delivered in the + * header for the first response packet. Error code is cleared during + * first RX packet and set if a failure occurs. + */ + uint16_t status_code; + + /* Stores the content from the USB packets */ + struct usb_spi_packet_ctx receive_packet; + struct usb_spi_packet_ctx transmit_packet; + + /* + * Flags describing if and how multi-lane (dual/quad), double transfer + * rate, and other advanced flash protocol features are to be used. + */ + uint32_t flash_flags; + + /* + * Context structures representing the progress receiving the SPI + * write data and transmitting the SPI read data. + */ + struct usb_spi_transfer_ctx spi_write_ctx; + struct usb_spi_transfer_ctx spi_read_ctx; +}; + +/* + * Compile time Per-USB gpio configuration stored in flash. Instances of this + * structure are provided by the user of the USB gpio. This structure binds + * together all information required to operate a USB gpio. + */ +struct usb_spi_config { + /* Interface and endpoint indices. */ + int interface; + int endpoint; + + /* Deferred function to call to handle SPI request. */ + const struct deferred_data *deferred; + + /* Pointers to USB endpoint buffers. */ + usb_uint *ep_rx_ram; + usb_uint *ep_tx_ram; +}; + +/* + * Handle SPI request in a deferred callback. + */ +void usb_spi_deferred(void); + +/* + * Storage of configuration and state of USB->SPI bridge. + */ +static uint16_t usb_spi_buffer_[(USB_SPI_BUFFER_SIZE + 1) / 2]; +static usb_uint usb_spi_ep_rx_buffer_[USB_MAX_PACKET_SIZE / 2] __usb_ram; +static usb_uint usb_spi_ep_tx_buffer_[USB_MAX_PACKET_SIZE / 2] __usb_ram; + +static struct usb_spi_state usb_spi_state = { + .enabled_host = 0, + .enabled_device = 0, + .enabled = 0, + .current_spi_device_idx = 0, + .spi_write_ctx.buffer = (uint8_t *)usb_spi_buffer_, + .spi_read_ctx.buffer = (uint8_t *)usb_spi_buffer_, +}; + +DECLARE_DEFERRED(usb_spi_deferred); + +struct usb_spi_config const usb_spi = { + .interface = USB_IFACE_SPI, + .endpoint = USB_EP_SPI, + .deferred = &usb_spi_deferred_data, + .ep_rx_ram = usb_spi_ep_rx_buffer_, + .ep_tx_ram = usb_spi_ep_tx_buffer_, +}; /* * Map EC error codes to USB_SPI error codes. @@ -30,10 +166,14 @@ static void usb_spi_write_packet(struct usb_spi_config const *config, static int16_t usb_spi_map_error(int error) { switch (error) { - case EC_SUCCESS: return USB_SPI_SUCCESS; - case EC_ERROR_TIMEOUT: return USB_SPI_TIMEOUT; - case EC_ERROR_BUSY: return USB_SPI_BUSY; - default: return USB_SPI_UNKNOWN_ERROR | (error & 0x7fff); + case EC_SUCCESS: + return USB_SPI_SUCCESS; + case EC_ERROR_TIMEOUT: + return USB_SPI_TIMEOUT; + case EC_ERROR_BUSY: + return USB_SPI_BUSY; + default: + return USB_SPI_UNKNOWN_ERROR | (error & 0x7fff); } } @@ -46,7 +186,7 @@ static int16_t usb_spi_map_error(int error) * @returns USB_SPI_RX_DATA_OVERFLOW if the source packet is too large */ static int usb_spi_read_usb_packet(struct usb_spi_transfer_ctx *dst, - const struct usb_spi_packet_ctx *src) + const struct usb_spi_packet_ctx *src) { size_t max_read_length = dst->transfer_size - dst->transfer_index; size_t bytes_in_buffer = src->packet_size - src->header_size; @@ -60,7 +200,7 @@ static int usb_spi_read_usb_packet(struct usb_spi_transfer_ctx *dst, return USB_SPI_RX_DATA_OVERFLOW; } memcpy(dst->buffer + dst->transfer_index, packet_buffer, - bytes_in_buffer); + bytes_in_buffer); dst->transfer_index += bytes_in_buffer; return USB_SPI_SUCCESS; @@ -73,7 +213,7 @@ static int usb_spi_read_usb_packet(struct usb_spi_transfer_ctx *dst, * @param src Source transmit context we are reading data from. */ static void usb_spi_fill_usb_packet(struct usb_spi_packet_ctx *dst, - struct usb_spi_transfer_ctx *src) + struct usb_spi_transfer_ctx *src) { size_t transfer_size = src->transfer_size - src->transfer_index; size_t max_buffer_size = USB_MAX_PACKET_SIZE - dst->header_size; @@ -95,17 +235,16 @@ static void usb_spi_fill_usb_packet(struct usb_spi_packet_ctx *dst, * @param write_count Number of bytes to write in the SPI transfer * @param read_count Number of bytes to read in the SPI transfer */ -static void usb_spi_setup_transfer(struct usb_spi_config const *config, - size_t write_count, size_t read_count) +static void usb_spi_setup_transfer(size_t write_count, size_t read_count) { /* Reset any status code. */ - config->state->status_code = USB_SPI_SUCCESS; + usb_spi_state.status_code = USB_SPI_SUCCESS; /* Reset the write and read counts. */ - config->state->spi_write_ctx.transfer_size = write_count; - config->state->spi_write_ctx.transfer_index = 0; - config->state->spi_read_ctx.transfer_size = read_count; - config->state->spi_read_ctx.transfer_index = 0; + usb_spi_state.spi_write_ctx.transfer_size = write_count; + usb_spi_state.spi_write_ctx.transfer_index = 0; + usb_spi_state.spi_read_ctx.transfer_size = read_count; + usb_spi_state.spi_read_ctx.transfer_index = 0; } /* @@ -113,10 +252,10 @@ static void usb_spi_setup_transfer(struct usb_spi_config const *config, * * @param config USB SPI config */ -static void usb_spi_reset_interface(struct usb_spi_config const *config) +static void usb_spi_reset_interface(void) { /* Setup a 0 byte transfer to clear the contexts. */ - usb_spi_setup_transfer(config, 0, 0); + usb_spi_setup_transfer(0, 0); } /* @@ -126,10 +265,10 @@ static void usb_spi_reset_interface(struct usb_spi_config const *config) * * @returns True if a response transfer is in progress. */ -static bool usb_spi_response_in_progress(struct usb_spi_config const *config) +static bool usb_spi_response_in_progress(void) { - if ((config->state->mode == USB_SPI_MODE_START_RESPONSE) || - (config->state->mode == USB_SPI_MODE_CONTINUE_RESPONSE)) { + if ((usb_spi_state.mode == USB_SPI_MODE_START_RESPONSE) || + (usb_spi_state.mode == USB_SPI_MODE_CONTINUE_RESPONSE)) { return true; } return false; @@ -143,16 +282,15 @@ static bool usb_spi_response_in_progress(struct usb_spi_config const *config) * @param config USB SPI config * @param status_code status code to set for the response. */ -static void setup_transfer_response(struct usb_spi_config const *config, - uint16_t status_code) +static void setup_transfer_response(uint16_t status_code) { - config->state->status_code = status_code; - config->state->spi_read_ctx.transfer_index = 0; - config->state->mode = USB_SPI_MODE_START_RESPONSE; + usb_spi_state.status_code = status_code; + usb_spi_state.spi_read_ctx.transfer_index = 0; + usb_spi_state.mode = USB_SPI_MODE_START_RESPONSE; /* If an error occurred, transmit an empty start packet. */ if (status_code != USB_SPI_SUCCESS) - config->state->spi_read_ctx.transfer_size = 0; + usb_spi_state.spi_read_ctx.transfer_size = 0; } /* @@ -161,9 +299,11 @@ static void setup_transfer_response(struct usb_spi_config const *config, * @param config USB SPI config * @param packet Packet buffer we will be transmitting. */ -static void create_spi_config_response(struct usb_spi_config const *config, - struct usb_spi_packet_ctx *packet) +static void create_spi_config_response(struct usb_spi_packet_ctx *packet) { + const struct spi_device_t *current_device = + &spi_devices[usb_spi_state.current_spi_device_idx]; + /* Construct the response packet. */ packet->rsp_config.packet_id = USB_SPI_PKT_ID_RSP_USB_SPI_CONFIG; packet->rsp_config.max_write_count = USB_SPI_MAX_WRITE_COUNT; @@ -174,8 +314,32 @@ static void create_spi_config_response(struct usb_spi_config const *config, packet->rsp_config.feature_bitmap |= USB_SPI_FEATURE_FULL_DUPLEX_SUPPORTED; #endif - packet->packet_size = - sizeof(struct usb_spi_response_configuration_v2); +#ifdef CONFIG_USB_SPI_FLASH_EXTENSIONS + packet->rsp_config.feature_bitmap |= USB_SPI_FEATURE_FLASH_EXTENSIONS; + if (current_device->usb_flags & USB_SPI_FLASH_DUAL_SUPPORT) + packet->rsp_config.feature_bitmap |= + USB_SPI_FEATURE_DUAL_MODE_SUPPORTED; + if (current_device->usb_flags & USB_SPI_FLASH_QUAD_SUPPORT) + packet->rsp_config.feature_bitmap |= + USB_SPI_FEATURE_QUAD_MODE_SUPPORTED; + if (current_device->usb_flags & USB_SPI_FLASH_OCTO_SUPPORT) + packet->rsp_config.feature_bitmap |= + USB_SPI_FEATURE_OCTO_MODE_SUPPORTED; + if (current_device->usb_flags & USB_SPI_FLASH_DTR_SUPPORT) + packet->rsp_config.feature_bitmap |= + USB_SPI_FEATURE_DTR_SUPPORTED; +#else + (void)current_device; /* Avoid warning about unused variable. */ +#endif + packet->packet_size = sizeof(struct usb_spi_response_configuration_v2); +} + +static void create_spi_chip_select_response(struct usb_spi_packet_ctx *packet) +{ + /* Construct the response packet. */ + packet->rsp_cs.packet_id = USB_SPI_PKT_ID_RSP_CHIP_SELECT; + packet->rsp_cs.status_code = 0; + packet->packet_size = sizeof(packet->rsp_cs); } /* @@ -186,239 +350,397 @@ static void create_spi_config_response(struct usb_spi_config const *config, * @param config USB SPI config * @param packet Packet buffer we will be transmitting. */ -static void usb_spi_create_spi_transfer_response( - struct usb_spi_config const *config, - struct usb_spi_packet_ctx *transmit_packet) +static void +usb_spi_create_spi_transfer_response(struct usb_spi_packet_ctx *transmit_packet) { - - if (!usb_spi_response_in_progress(config)) + if (!usb_spi_response_in_progress()) return; - if (config->state->spi_read_ctx.transfer_index == 0) { - + if (usb_spi_state.spi_read_ctx.transfer_index == 0) { /* Transmit the first packet with the status code. */ transmit_packet->header_size = offsetof(struct usb_spi_response_v2, data); transmit_packet->rsp_start.packet_id = USB_SPI_PKT_ID_RSP_TRANSFER_START; transmit_packet->rsp_start.status_code = - config->state->status_code; + usb_spi_state.status_code; usb_spi_fill_usb_packet(transmit_packet, - &config->state->spi_read_ctx); - } else if (config->state->spi_read_ctx.transfer_index < - config->state->spi_read_ctx.transfer_size) { - + &usb_spi_state.spi_read_ctx); + } else if (usb_spi_state.spi_read_ctx.transfer_index < + usb_spi_state.spi_read_ctx.transfer_size) { /* Transmit the continue packets. */ transmit_packet->header_size = offsetof(struct usb_spi_continue_v2, data); transmit_packet->rsp_continue.packet_id = USB_SPI_PKT_ID_RSP_TRANSFER_CONTINUE; transmit_packet->rsp_continue.data_index = - config->state->spi_read_ctx.transfer_index; + usb_spi_state.spi_read_ctx.transfer_index; usb_spi_fill_usb_packet(transmit_packet, - &config->state->spi_read_ctx); + &usb_spi_state.spi_read_ctx); } - if (config->state->spi_read_ctx.transfer_index < - config->state->spi_read_ctx.transfer_size) { - config->state->mode = USB_SPI_MODE_CONTINUE_RESPONSE; + if (usb_spi_state.spi_read_ctx.transfer_index < + usb_spi_state.spi_read_ctx.transfer_size) { + usb_spi_state.mode = USB_SPI_MODE_CONTINUE_RESPONSE; } else { - config->state->mode = USB_SPI_MODE_IDLE; + usb_spi_state.mode = USB_SPI_MODE_IDLE; } } +#ifdef CONFIG_USB_SPI_FLASH_EXTENSIONS +/* + * Decodes the header fields of a Flash Command Start Packet, and sets up the + * transaction depending on if it is read or write. + */ +static void setup_flash_transfer(struct usb_spi_packet_ctx *packet) +{ + const uint32_t flags = packet->cmd_flash_start.flags; + usb_spi_state.flash_flags = flags; + const uint8_t opcode_count = (flags & FLASH_FLAG_OPCODE_LEN_MSK) >> + FLASH_FLAG_OPCODE_LEN_POS; + const uint8_t addr_count = (flags & FLASH_FLAG_ADDR_LEN_MSK) >> + FLASH_FLAG_ADDR_LEN_POS; + const bool write_enable = !!(flags & FLASH_FLAG_WRITE_ENABLE); + if ((packet->cmd_flash_start.flags & FLASH_FLAG_READ_WRITE_MSK) == + FLASH_FLAG_READ_WRITE_WRITE) { + size_t write_count = packet->cmd_flash_start.count; + if (write_count > USB_SPI_MAX_WRITE_COUNT) { + usb_spi_state.status_code = USB_SPI_WRITE_COUNT_INVALID; + return; + } + usb_spi_setup_transfer(write_enable + opcode_count + + addr_count + write_count, + 0); + } else { + size_t read_count = packet->cmd_flash_start.count; + if (read_count > USB_SPI_MAX_READ_COUNT) { + usb_spi_state.status_code = USB_SPI_WRITE_COUNT_INVALID; + return; + } + usb_spi_setup_transfer(write_enable + opcode_count + addr_count, + read_count); + } + packet->header_size = offsetof(struct usb_spi_flash_command, data); + usb_spi_state.status_code = + usb_spi_read_usb_packet(&usb_spi_state.spi_write_ctx, packet); +} +#endif + /* * Process the rx packet. * * @param config USB SPI config * @param packet Received packet to process. */ -static void usb_spi_process_rx_packet(struct usb_spi_config const *config, - struct usb_spi_packet_ctx *packet) +static void usb_spi_process_rx_packet(struct usb_spi_packet_ctx *packet) { if (packet->packet_size < USB_SPI_MIN_PACKET_SIZE) { /* No valid packet exists smaller than the packet id. */ - setup_transfer_response(config, USB_SPI_RX_UNEXPECTED_PACKET); + setup_transfer_response(USB_SPI_RX_UNEXPECTED_PACKET); return; } /* Reset the mode until we've processed the packet. */ - config->state->mode = USB_SPI_MODE_IDLE; + usb_spi_state.mode = USB_SPI_MODE_IDLE; switch (packet->packet_id) { - case USB_SPI_PKT_ID_CMD_GET_USB_SPI_CONFIG: - { + case USB_SPI_PKT_ID_CMD_GET_USB_SPI_CONFIG: { /* The host requires the SPI configuration. */ - config->state->mode = USB_SPI_MODE_SEND_CONFIGURATION; + usb_spi_state.mode = USB_SPI_MODE_SEND_CONFIGURATION; break; } - case USB_SPI_PKT_ID_CMD_RESTART_RESPONSE: - { + case USB_SPI_PKT_ID_CMD_RESTART_RESPONSE: { /* * The host has requested the device restart the last response. * This is used to recover from lost USB packets without * duplicating SPI transfers. */ - setup_transfer_response(config, config->state->status_code); + setup_transfer_response(usb_spi_state.status_code); break; } - case USB_SPI_PKT_ID_CMD_TRANSFER_START: - { + case USB_SPI_PKT_ID_CMD_TRANSFER_START: { /* The host started a new USB SPI transfer */ size_t write_count = packet->cmd_start.write_count; size_t read_count = packet->cmd_start.read_count; + usb_spi_state.flash_flags = 0; - if (!config->state->enabled) { - setup_transfer_response(config, USB_SPI_DISABLED); + if (!usb_spi_state.enabled) { + setup_transfer_response(USB_SPI_DISABLED); } else if (write_count > USB_SPI_MAX_WRITE_COUNT) { - setup_transfer_response(config, - USB_SPI_WRITE_COUNT_INVALID); + setup_transfer_response(USB_SPI_WRITE_COUNT_INVALID); +#ifdef CONFIG_SPI_HALFDUPLEX } else if (read_count == USB_SPI_FULL_DUPLEX_ENABLED) { -#ifndef CONFIG_SPI_HALFDUPLEX /* Full duplex mode is not supported on this device. */ - setup_transfer_response(config, + setup_transfer_response( USB_SPI_UNSUPPORTED_FULL_DUPLEX); #endif } else if (read_count > USB_SPI_MAX_READ_COUNT && - read_count != USB_SPI_FULL_DUPLEX_ENABLED) { - setup_transfer_response(config, - USB_SPI_READ_COUNT_INVALID); + read_count != USB_SPI_FULL_DUPLEX_ENABLED) { + setup_transfer_response(USB_SPI_READ_COUNT_INVALID); + } else { + usb_spi_setup_transfer(write_count, read_count); + packet->header_size = + offsetof(struct usb_spi_command_v2, data); + usb_spi_state.status_code = usb_spi_read_usb_packet( + &usb_spi_state.spi_write_ctx, packet); + } + + /* Send responses if we encountered an error. */ + if (usb_spi_state.status_code != USB_SPI_SUCCESS) { + setup_transfer_response(usb_spi_state.status_code); + break; + } + + /* Start the SPI transfer when we've read all data. */ + if (usb_spi_state.spi_write_ctx.transfer_index == + usb_spi_state.spi_write_ctx.transfer_size) { + usb_spi_state.mode = USB_SPI_MODE_START_SPI; + } + + break; + } +#ifdef CONFIG_USB_SPI_FLASH_EXTENSIONS + case USB_SPI_PKT_ID_CMD_FLASH_TRANSFER_START: { + /* The host started a new USB serial flash SPI transfer */ + if (!usb_spi_state.enabled) { + setup_transfer_response(USB_SPI_DISABLED); } else { - usb_spi_setup_transfer(config, write_count, read_count); - packet->header_size = - offsetof(struct usb_spi_command_v2, data); - config->state->status_code = usb_spi_read_usb_packet( - &config->state->spi_write_ctx, packet); + setup_flash_transfer(packet); } /* Send responses if we encountered an error. */ - if (config->state->status_code != USB_SPI_SUCCESS) { - setup_transfer_response(config, - config->state->status_code); + if (usb_spi_state.status_code != USB_SPI_SUCCESS) { + setup_transfer_response(usb_spi_state.status_code); break; } /* Start the SPI transfer when we've read all data. */ - if (config->state->spi_write_ctx.transfer_index == - config->state->spi_write_ctx.transfer_size) { - config->state->mode = USB_SPI_MODE_START_SPI; + if (usb_spi_state.spi_write_ctx.transfer_index == + usb_spi_state.spi_write_ctx.transfer_size) { + usb_spi_state.mode = USB_SPI_MODE_START_SPI; } break; } - case USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE: - { +#endif + case USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE: { /* * The host has sent a continue packet for the SPI transfer * which contains additional data payload. */ packet->header_size = offsetof(struct usb_spi_continue_v2, data); - if (config->state->status_code == USB_SPI_SUCCESS) { - config->state->status_code = usb_spi_read_usb_packet( - &config->state->spi_write_ctx, packet); + if (usb_spi_state.status_code == USB_SPI_SUCCESS) { + usb_spi_state.status_code = usb_spi_read_usb_packet( + &usb_spi_state.spi_write_ctx, packet); } /* Send responses if we encountered an error. */ - if (config->state->status_code != USB_SPI_SUCCESS) { - setup_transfer_response(config, - config->state->status_code); + if (usb_spi_state.status_code != USB_SPI_SUCCESS) { + setup_transfer_response(usb_spi_state.status_code); break; } /* Start the SPI transfer when we've read all data. */ - if (config->state->spi_write_ctx.transfer_index == - config->state->spi_write_ctx.transfer_size) { - config->state->mode = USB_SPI_MODE_START_SPI; + if (usb_spi_state.spi_write_ctx.transfer_index == + usb_spi_state.spi_write_ctx.transfer_size) { + usb_spi_state.mode = USB_SPI_MODE_START_SPI; } break; } - default: - { + case USB_SPI_PKT_ID_CMD_CHIP_SELECT: { + /* + * The host is requesting the chip select line be + * asserted or deasserted. + */ + uint16_t flags = packet->cmd_cs.flags; + const struct spi_device_t *current_device = + &spi_devices[usb_spi_state.current_spi_device_idx]; + + if (flags & USB_SPI_CHIP_SELECT) { + /* Set chip select low (asserted). */ + gpio_set_level(current_device->gpio_cs, 0); + } else { + /* Set chip select high (adesserted). */ + gpio_set_level(current_device->gpio_cs, 1); + } + usb_spi_state.mode = USB_SPI_MODE_SEND_CHIP_SELECT_RESPONSE; + break; + } + default: { /* An unknown USB packet was delivered. */ - setup_transfer_response(config, USB_SPI_RX_UNEXPECTED_PACKET); + setup_transfer_response(USB_SPI_RX_UNEXPECTED_PACKET); break; } } } +/* + * Perform a SPI write-then-read transaction, optionally preceded by a single + * byte "write enable" (separated by deasserting chip select), and optionally + * followed by polling the "busy bit" until clear. + */ +static uint16_t do_spi_transfer(void) +{ + const struct spi_device_t *current_device = + &spi_devices[usb_spi_state.current_spi_device_idx]; + bool custom_board_driver = current_device->usb_flags & + USB_SPI_CUSTOM_SPI_DEVICE; + /* + * If CONFIG_USB_SPI_FLASH_EXTENSIONS is not enabled, then the below + * value being zero will allow the compiler to optimize away several + * large if-blocks in this function. + */ + const uint32_t flash_flags = + IS_ENABLED(CONFIG_USB_SPI_FLASH_EXTENSIONS) ? + usb_spi_state.flash_flags : + 0; + uint16_t status_code = EC_SUCCESS; + int read_count = usb_spi_state.spi_read_ctx.transfer_size; + const char *write_data_ptr = usb_spi_state.spi_write_ctx.buffer; + int write_count = usb_spi_state.spi_write_ctx.transfer_size; +#ifndef CONFIG_SPI_HALFDUPLEX + /* + * Handle the full duplex mode on supported platforms. + * The read count is equal to the write count. + */ + if (read_count == USB_SPI_FULL_DUPLEX_ENABLED) { + usb_spi_state.spi_read_ctx.transfer_size = + usb_spi_state.spi_write_ctx.transfer_size; + read_count = SPI_READBACK_ALL; + } +#endif + + if (!custom_board_driver && + (flash_flags & FLASH_FLAGS_REQUIRING_SUPPORT)) { + /* + * The standard spi_transaction() does not support + * any multi-lane modes. + */ + return USB_SPI_UNSUPPORTED_FLASH_MODE; + } + + if (status_code == EC_SUCCESS && + flash_flags & FLASH_FLAG_WRITE_ENABLE) { + /* Precede main transaction with one-byte "write enable". */ + if (custom_board_driver) { + status_code = usb_spi_board_transaction( + current_device, 0, write_data_ptr, 1, NULL, 0); + } else { + status_code = spi_transaction( + current_device, write_data_ptr, 1, NULL, 0); + } + write_data_ptr += 1; + write_count -= 1; + } + + if (status_code == EC_SUCCESS) { + if (custom_board_driver) { + status_code = usb_spi_board_transaction( + current_device, flash_flags, write_data_ptr, + write_count, usb_spi_state.spi_read_ctx.buffer, + read_count); + } else { + status_code = spi_transaction( + current_device, write_data_ptr, write_count, + usb_spi_state.spi_read_ctx.buffer, read_count); + } + } + + if (flash_flags & FLASH_FLAG_POLL) { + /* After main transaction, poll until no longer "busy". */ + static timestamp_t deadline; + deadline.val = get_time().val + FLASH_BUSY_POLL_TIMEOUT_USEC; + + while (status_code == EC_SUCCESS) { + timestamp_t now; + uint8_t status_byte; + if (custom_board_driver) { + status_code = usb_spi_board_transaction( + current_device, 0, &JEDEC_READ_STATUS, + 1, &status_byte, 1); + } else { + status_code = spi_transaction( + current_device, &JEDEC_READ_STATUS, 1, + &status_byte, 1); + } + if ((status_byte & JEDEC_STATUS_BUSY) == 0) + break; + now = get_time(); + if (timestamp_expired(deadline, &now)) { + status_code = EC_ERROR_TIMEOUT; + break; + } + } + } + return usb_spi_map_error(status_code); +} + /* Deferred function to handle state changes, process USB SPI packets, * and construct responses. * * @param config USB SPI config */ -void usb_spi_deferred(struct usb_spi_config const *config) +void usb_spi_deferred(void) { int enabled; struct usb_spi_packet_ctx *receive_packet = - &config->state->receive_packet; + &usb_spi_state.receive_packet; struct usb_spi_packet_ctx *transmit_packet = - &config->state->transmit_packet; + &usb_spi_state.transmit_packet; transmit_packet->packet_size = 0; - if (config->flags & USB_SPI_CONFIG_FLAGS_IGNORE_HOST_SIDE_ENABLE) - enabled = config->state->enabled_device; + if (IS_ENABLED(CONFIG_USB_SPI_IGNORE_HOST_SIDE_ENABLE)) + enabled = usb_spi_state.enabled_device; else - enabled = config->state->enabled_device && - config->state->enabled_host; + enabled = usb_spi_state.enabled_device && + usb_spi_state.enabled_host; /* * If our overall enabled state has changed we call the board specific * enable or disable routines and save our new state. */ - if (enabled != config->state->enabled) { - if (enabled) usb_spi_board_enable(config); - else usb_spi_board_disable(config); + if (enabled != usb_spi_state.enabled) { + if (enabled) + usb_spi_board_enable(); + else + usb_spi_board_disable(); - config->state->enabled = enabled; + usb_spi_state.enabled = enabled; } /* Read any packets from the endpoint. */ - usb_spi_read_packet(config, receive_packet); + usb_spi_read_packet(receive_packet); if (receive_packet->packet_size) { - usb_spi_process_rx_packet(config, receive_packet); + usb_spi_process_rx_packet(receive_packet); } /* Need to send the USB SPI configuration */ - if (config->state->mode == USB_SPI_MODE_SEND_CONFIGURATION) { - create_spi_config_response(config, transmit_packet); - usb_spi_write_packet(config, transmit_packet); - config->state->mode = USB_SPI_MODE_IDLE; + if (usb_spi_state.mode == USB_SPI_MODE_SEND_CONFIGURATION) { + create_spi_config_response(transmit_packet); + usb_spi_write_packet(transmit_packet); + usb_spi_state.mode = USB_SPI_MODE_IDLE; + return; + } + /* Need to send response to USB SPI chip select. */ + if (usb_spi_state.mode == USB_SPI_MODE_SEND_CHIP_SELECT_RESPONSE) { + create_spi_chip_select_response(transmit_packet); + usb_spi_write_packet(transmit_packet); + usb_spi_state.mode = USB_SPI_MODE_IDLE; return; } /* Start a new SPI transfer. */ - if (config->state->mode == USB_SPI_MODE_START_SPI) { - uint16_t status_code; - int read_count = config->state->spi_read_ctx.transfer_size; -#ifndef CONFIG_SPI_HALFDUPLEX - /* - * Handle the full duplex mode on supported platforms. - * The read count is equal to the write count. - */ - if (read_count == USB_SPI_FULL_DUPLEX_ENABLED) { - config->state->spi_read_ctx.transfer_size = - config->state->spi_write_ctx.transfer_size; - read_count = SPI_READBACK_ALL; - } -#endif - status_code = spi_transaction(SPI_FLASH_DEVICE, - config->state->spi_write_ctx.buffer, - config->state->spi_write_ctx.transfer_size, - config->state->spi_read_ctx.buffer, - read_count); - - /* Cast the EC status code to USB SPI and start the response. */ - status_code = usb_spi_map_error(status_code); - setup_transfer_response(config, status_code); + if (usb_spi_state.mode == USB_SPI_MODE_START_SPI) { + uint16_t status_code = do_spi_transfer(); + setup_transfer_response(status_code); } - if (usb_spi_response_in_progress(config) && - usb_spi_transmitted_packet(config)) { - usb_spi_create_spi_transfer_response(config, transmit_packet); - usb_spi_write_packet(config, transmit_packet); + if (usb_spi_response_in_progress() && usb_spi_transmitted_packet()) { + usb_spi_create_spi_transfer_response(transmit_packet); + usb_spi_write_packet(transmit_packet); } } @@ -428,11 +750,11 @@ void usb_spi_deferred(struct usb_spi_config const *config) * @param config USB SPI config * @param enabled usb_spi_request indicating which SPI mode is enabled. */ -void usb_spi_enable(struct usb_spi_config const *config, int enabled) +void usb_spi_enable(int enabled) { - config->state->enabled_device = enabled; + usb_spi_state.enabled_device = enabled; - hook_call_deferred(config->deferred, 0); + hook_call_deferred(usb_spi.deferred, 0); } /* @@ -442,24 +764,24 @@ void usb_spi_enable(struct usb_spi_config const *config, int enabled) * @param config USB SPI config * @param packet Destination packet used to store the endpoint data. */ -static void usb_spi_read_packet(struct usb_spi_config const *config, - struct usb_spi_packet_ctx *packet) +static void usb_spi_read_packet(struct usb_spi_packet_ctx *packet) { size_t packet_size; - if (!usb_spi_received_packet(config)) { + if (!usb_spi_received_packet()) { /* No data is present on the endpoint. */ packet->packet_size = 0; return; } /* Copy bytes from endpoint memory. */ - packet_size = btable_ep[config->endpoint].rx_count & RX_COUNT_MASK; + packet_size = btable_ep[usb_spi.endpoint].rx_count & RX_COUNT_MASK; memcpy_from_usbram(packet->bytes, - (void *)usb_sram_addr(config->ep_rx_ram), packet_size); + (void *)usb_sram_addr(usb_spi.ep_rx_ram), + packet_size); packet->packet_size = packet_size; /* Set endpoint as valid for accepting new packet. */ - STM32_TOGGLE_EP(config->endpoint, EP_RX_MASK, EP_RX_VALID, 0); + STM32_TOGGLE_EP(usb_spi.endpoint, EP_RX_MASK, EP_RX_VALID, 0); } /* @@ -469,22 +791,21 @@ static void usb_spi_read_packet(struct usb_spi_config const *config, * @param config USB SPI config * @param packet Source packet we will write to the endpoint data. */ -static void usb_spi_write_packet(struct usb_spi_config const *config, - struct usb_spi_packet_ctx *packet) +static void usb_spi_write_packet(struct usb_spi_packet_ctx *packet) { if (packet->packet_size == 0) return; /* Copy bytes to endpoint memory. */ - memcpy_to_usbram((void *)usb_sram_addr(config->ep_tx_ram), - packet->bytes, packet->packet_size); - btable_ep[config->endpoint].tx_count = packet->packet_size; + memcpy_to_usbram((void *)usb_sram_addr(usb_spi.ep_tx_ram), + packet->bytes, packet->packet_size); + btable_ep[usb_spi.endpoint].tx_count = packet->packet_size; /* Mark the packet as having no data. */ packet->packet_size = 0; /* Set endpoint as valid for transmitting new packet. */ - STM32_TOGGLE_EP(config->endpoint, EP_TX_MASK, EP_TX_VALID, 0); + STM32_TOGGLE_EP(usb_spi.endpoint, EP_TX_MASK, EP_TX_VALID, 0); } /* @@ -494,9 +815,9 @@ static void usb_spi_write_packet(struct usb_spi_config const *config, * * @returns Returns true when the RX endpoint has a packet. */ -static bool usb_spi_received_packet(struct usb_spi_config const *config) +static bool usb_spi_received_packet(void) { - return (STM32_USB_EP(config->endpoint) & EP_RX_MASK) != EP_RX_VALID; + return (STM32_USB_EP(usb_spi.endpoint) & EP_RX_MASK) != EP_RX_VALID; } /* STM32 Platform: Returns the TX endpoint status @@ -506,16 +827,16 @@ static bool usb_spi_received_packet(struct usb_spi_config const *config) * @returns Returns true when the TX endpoint transmitted * the packet written. */ -static bool usb_spi_transmitted_packet(struct usb_spi_config const *config) +static bool usb_spi_transmitted_packet(void) { - return (STM32_USB_EP(config->endpoint) & EP_TX_MASK) != EP_TX_VALID; + return (STM32_USB_EP(usb_spi.endpoint) & EP_TX_MASK) != EP_TX_VALID; } /* STM32 Platform: Handle interrupt for USB data received. * * @param config USB SPI config */ -void usb_spi_rx(struct usb_spi_config const *config) +void usb_spi_rx(void) { /* * We need to set both the TX and RX endpoints to NAK to prevent @@ -528,9 +849,9 @@ void usb_spi_rx(struct usb_spi_config const *config) * This has a side effect of disabling the endpoint interrupts until * they are set to valid or a USB reset events occurs. */ - STM32_TOGGLE_EP(config->endpoint, EP_TX_RX_MASK, EP_TX_RX_NAK, 0); + STM32_TOGGLE_EP(usb_spi.endpoint, EP_TX_RX_MASK, EP_TX_RX_NAK, 0); - hook_call_deferred(config->deferred, 0); + hook_call_deferred(usb_spi.deferred, 0); } /* @@ -538,11 +859,11 @@ void usb_spi_rx(struct usb_spi_config const *config) * * @param config USB SPI config */ -void usb_spi_tx(struct usb_spi_config const *config) +void usb_spi_tx(void) { - STM32_TOGGLE_EP(config->endpoint, EP_TX_MASK, EP_TX_NAK, 0); + STM32_TOGGLE_EP(usb_spi.endpoint, EP_TX_MASK, EP_TX_NAK, 0); - hook_call_deferred(config->deferred, 0); + hook_call_deferred(usb_spi.deferred, 0); } /* @@ -551,28 +872,28 @@ void usb_spi_tx(struct usb_spi_config const *config) * @param config USB SPI config * @param evt USB event */ -void usb_spi_event(struct usb_spi_config const *config, enum usb_ep_event evt) +void usb_spi_event(enum usb_ep_event evt) { int endpoint; if (evt != USB_EVENT_RESET) return; - endpoint = config->endpoint; + endpoint = usb_spi.endpoint; - usb_spi_reset_interface(config); + usb_spi_reset_interface(); - btable_ep[endpoint].tx_addr = usb_sram_addr(config->ep_tx_ram); + btable_ep[endpoint].tx_addr = usb_sram_addr(usb_spi.ep_tx_ram); btable_ep[endpoint].tx_count = 0; - btable_ep[endpoint].rx_addr = usb_sram_addr(config->ep_rx_ram); - btable_ep[endpoint].rx_count = - 0x8000 | ((USB_MAX_PACKET_SIZE / 32 - 1) << 10); + btable_ep[endpoint].rx_addr = usb_sram_addr(usb_spi.ep_rx_ram); + btable_ep[endpoint].rx_count = 0x8000 | + ((USB_MAX_PACKET_SIZE / 32 - 1) << 10); - STM32_USB_EP(endpoint) = ((endpoint << 0) | /* Endpoint Addr*/ - (2 << 4) | /* TX NAK */ - (0 << 9) | /* Bulk EP */ - (3 << 12)); /* RX Valid */ + STM32_USB_EP(endpoint) = ((endpoint << 0) | /* Endpoint Addr*/ + (2 << 4) | /* TX NAK */ + (0 << 9) | /* Bulk EP */ + (3 << 12)); /* RX Valid */ } /* @@ -582,46 +903,88 @@ void usb_spi_event(struct usb_spi_config const *config, enum usb_ep_event evt) * @param rx_buf Contains setup packet * @param tx_buf unused */ -int usb_spi_interface(struct usb_spi_config const *config, - usb_uint *rx_buf, - usb_uint *tx_buf) +int usb_spi_interface(usb_uint *rx_buf, usb_uint *tx_buf) { struct usb_setup_packet setup; usb_read_setup_packet(rx_buf, &setup); - if (setup.bmRequestType != (USB_DIR_OUT | - USB_TYPE_VENDOR | - USB_RECIP_INTERFACE)) + if (setup.bmRequestType != + (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE)) return 1; - if (setup.wValue != 0 || - setup.wIndex != config->interface || - setup.wLength != 0) + if (setup.wValue >= spi_devices_used || + !(spi_devices[setup.wValue].usb_flags & USB_SPI_ENABLED) || + setup.wIndex != usb_spi.interface || setup.wLength != 0) return 1; + /* Record which SPI device the host wished to manipulate. */ + usb_spi_state.current_spi_device_idx = setup.wValue; + switch (setup.bRequest) { case USB_SPI_REQ_ENABLE: - config->state->enabled_host = 1; + usb_spi_state.enabled_host = 1; break; case USB_SPI_REQ_DISABLE: - config->state->enabled_host = 0; + usb_spi_state.enabled_host = 0; break; - default: return 1; + default: + return 1; } /* * Our state has changed, call the deferred function to handle the * state change. */ - if (!(config->flags & USB_SPI_CONFIG_FLAGS_IGNORE_HOST_SIDE_ENABLE)) - hook_call_deferred(config->deferred, 0); + if (!IS_ENABLED(CONFIG_USB_SPI_IGNORE_HOST_SIDE_ENABLE)) + hook_call_deferred(usb_spi.deferred, 0); - usb_spi_reset_interface(config); + usb_spi_reset_interface(); btable_ep[0].tx_count = 0; STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, EP_STATUS_OUT); return 0; } + +__overridable int +usb_spi_board_transaction(const struct spi_device_t *spi_device, + uint32_t flash_flags, const uint8_t *txdata, + int txlen, uint8_t *rxdata, int rxlen) +{ + return EC_ERROR_UNIMPLEMENTED; +} + +/* + * Register this file with the low-level USB driver. + */ +const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_SPI) = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = USB_IFACE_SPI, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_SPI, + .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_SPI, + .iInterface = USB_STR_SPI_NAME, +}; +const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_SPI, 0) = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x80 | USB_EP_SPI, + .bmAttributes = 0x02 /* Bulk IN */, + .wMaxPacketSize = USB_MAX_PACKET_SIZE, + .bInterval = 10, +}; +const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_SPI, 1) = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_EP_SPI, + .bmAttributes = 0x02 /* Bulk OUT */, + .wMaxPacketSize = USB_MAX_PACKET_SIZE, + .bInterval = 0, +}; +USB_DECLARE_EP(USB_EP_SPI, usb_spi_tx, usb_spi_rx, usb_spi_event); +USB_DECLARE_IFACE(USB_IFACE_SPI, usb_spi_interface); diff --git a/chip/stm32/usb_spi.h b/chip/stm32/usb_spi.h index 591975234d..7ca5a57a7a 100644 --- a/chip/stm32/usb_spi.h +++ b/chip/stm32/usb_spi.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -146,6 +146,7 @@ * 0x0008: An unexpected packet arrived that the device could not * process. * 0x0009: The device does not support full duplex mode. + * 0x000A: Requested serial flash mode not supported * 0x8000: Unknown error mask * The bottom 15 bits will contain the bottom 15 bits from the EC * error code. @@ -218,7 +219,12 @@ * * feature bitmap: Bitmap of supported features. * BIT(0): Full duplex SPI mode is supported - * BIT(1:15): Reserved for future use + * BIT(1): Serial flash extensions are supported + * BIT(2): Dual mode flash supported + * BIT(3): Quad mode flash supported + * BIT(4): Octo mode flash supported + * BIT(5): Double transfer rate supported + * BIT(6:15): Reserved for future use * * Command Restart Response Packet (Host to Device): * @@ -232,6 +238,88 @@ * * packet id: 2 byte enum USB_SPI_PKT_ID_CMD_RESTART_RESPONSE * + * Command chip select Packet (Host to Device): + * + * +----------------+-------------+ + * | packet id : 2B | action : 2B | + * +----------------+-------------+ + * + * packet id: 2 byte enum USB_SPI_PKT_ID_CMD_CHIP_SELECT + * + * action: 2 byte, current options: + * 0: Deassert chip select + * 1: Assert chip select + * + * Response chip select Packet (Device to Host): + * + * +----------------+------------------+ + * | packet id : 2B | status code : 2B | + * +----------------+------------------+ + * + * packet id: 2 byte enum USB_SPI_PKT_ID_RSP_CHIP_SELECT + * + * status code: 2 byte status code + * 0x0000: Success + * others: Error + * + * Flash Command Start Packet (Host to Device): + * + * Start of the USB serial flash SPI command, contains the number of + * bytes to write or read on SPI and up to the first 58 bytes of write + * payload. Longer writes will use the continue packets with packet id + * USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE to transmit the remaining data. + * + * The reading or writing of the "main" data will be preceded by an + * short sequence of opcode, optional address, optional "alternate data", + * and optional 'dummy cycles" on the SPI bus. Flags indicate how many + * bytes of each stage to send, and whether to use advanced features such + * as dual or quad signal lanes for each stage of the transfer". + * + * The indicated number of opcode, address and alternate bytes will be + * the first in the "write payload". The "count" field will contain the + * number of data bytes to be written/read after the opcode, address and + * alternate bytes. + * + * This request is only supported if bit 1 of the "feature bitmap" + * indicates that serial flash extensions are supported. Implementations + * will further advertise whether they support dual, quad or octo modes, if + * none of these are supported, then support for "dummy cycles" is not + * guaranteed either, and callers should use one or two bytes of "extra + * address data" for dummy cycles, address length can be up to 7 bytes for + * this reason. + * + * +----------------+------------+------------+---------------+ + * | packet id : 2B | count : 2B | flags : 4B | w.p. : <= 56B | + * +----------------+------------+------------+---------------+ + * + * packet id: 2 byte enum defined by packet_id_type + * Valid values packet id = + * USB_SPI_PKT_ID_CMD_FLASH_TRANSFER_START + * + * count: 2 byte, zero based count of bytes to read or write + * + * flags: 4 byte, flags + * bits 0:1 opcode length in bytes (0-3) + * bits 2:4 address length in bytes (0-7) + * bits 5:6 mode (0: 1-1-1, 1: 1-1-N, 2: 1-N-N, 3: N-N-N) + * bits 7:8 width (0: N=1, 1: N=2, 2: N=4, 3: N=8) + * bit 9 double transfer rate (in phases marked as N) + * bits 10:14 number of dummy cycles (0-31) + * bits 15:27 reserved, must be zero + * bit 28 write to be preceded by "write enable" + * bit 29 write to be followed by polling of JEDEC "busy bit" + * bit 30 reserved, must be zero + * bit 31 read (0) / write (1) + * + * write payload: Up to 56 bytes of data to write to SPI, the total length + * of all TX packets must match: write enable length (zero or + * one, depending on bit 27) + opcode length + address length + * + count, (the last one only if bit 31 indicates a write + * operation). Due to data alignment constraints, this must + * be an even number of bytes unless this is the final + * packet. + * + * * USB Error Codes: * * send_command return codes have the following format: @@ -244,47 +332,95 @@ * http://libusb.sourceforge.net/api-1.0/group__misc.html */ -#define USB_SPI_FULL_DUPLEX_ENABLED (UINT16_MAX) +#define USB_SPI_FULL_DUPLEX_ENABLED (UINT16_MAX) -#define USB_SPI_PAYLOAD_SIZE_V2_START (58) +#define USB_SPI_PAYLOAD_SIZE_V2_START (58) -#define USB_SPI_PAYLOAD_SIZE_V2_RESPONSE (60) +#define USB_SPI_PAYLOAD_SIZE_V2_RESPONSE (60) -#define USB_SPI_PAYLOAD_SIZE_V2_CONTINUE (60) +#define USB_SPI_PAYLOAD_SIZE_V2_CONTINUE (60) -#define USB_SPI_PAYLOAD_SIZE_V2_ERROR (60) +#define USB_SPI_PAYLOAD_SIZE_V2_ERROR (60) -#define USB_SPI_MIN_PACKET_SIZE (2) +#define USB_SPI_PAYLOAD_SIZE_FLASH_START (56) + +#define USB_SPI_MIN_PACKET_SIZE (2) + +/* + * Values used in spi_device_t.usb_flags + */ + +/* Is the USB host allowed to operate on SPI device. */ +#define USB_SPI_ENABLED BIT(0) +/* Use board specific SPI driver when forwarding to this device. */ +#define USB_SPI_CUSTOM_SPI_DEVICE BIT(1) +/* This SPI device supports dual lane mode. */ +#define USB_SPI_FLASH_DUAL_SUPPORT BIT(2) +/* This SPI device supports four lane mode. */ +#define USB_SPI_FLASH_QUAD_SUPPORT BIT(3) +/* This SPI device supports eight lane mode. */ +#define USB_SPI_FLASH_OCTO_SUPPORT BIT(4) +/* This SPI device supports double transfer rate (data on both clock edges). */ +#define USB_SPI_FLASH_DTR_SUPPORT BIT(5) enum packet_id_type { /* Request USB SPI configuration data from device. */ USB_SPI_PKT_ID_CMD_GET_USB_SPI_CONFIG = 0, /* USB SPI configuration data from device. */ - USB_SPI_PKT_ID_RSP_USB_SPI_CONFIG = 1, + USB_SPI_PKT_ID_RSP_USB_SPI_CONFIG = 1, /* * Start a USB SPI transfer specifying number of bytes to write, * read and deliver first packet of data to write. */ - USB_SPI_PKT_ID_CMD_TRANSFER_START = 2, + USB_SPI_PKT_ID_CMD_TRANSFER_START = 2, /* Additional packets containing write payload. */ - USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE = 3, + USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE = 3, /* * Request the device restart the response enabling us to recover * from packet loss without another SPI transfer. */ - USB_SPI_PKT_ID_CMD_RESTART_RESPONSE = 4, + USB_SPI_PKT_ID_CMD_RESTART_RESPONSE = 4, /* * First packet of USB SPI response with the status code * and read payload if it was successful. */ - USB_SPI_PKT_ID_RSP_TRANSFER_START = 5, + USB_SPI_PKT_ID_RSP_TRANSFER_START = 5, /* Additional packets containing read payload. */ - USB_SPI_PKT_ID_RSP_TRANSFER_CONTINUE = 6, + USB_SPI_PKT_ID_RSP_TRANSFER_CONTINUE = 6, + /* + * Request assertion or deassertion of chip select + */ + USB_SPI_PKT_ID_CMD_CHIP_SELECT = 7, + /* Response to above request. */ + USB_SPI_PKT_ID_RSP_CHIP_SELECT = 8, + /* + * Start a USB serial flash SPI transfer. + */ + USB_SPI_PKT_ID_CMD_FLASH_TRANSFER_START = 9, }; enum feature_bitmap { /* Indicates the platform supports full duplex mode. */ - USB_SPI_FEATURE_FULL_DUPLEX_SUPPORTED = BIT(0) + USB_SPI_FEATURE_FULL_DUPLEX_SUPPORTED = BIT(0), + /* Indicates support for USB_SPI_PKT_ID_CMD_FLASH_TRANSFER_START. */ + USB_SPI_FEATURE_FLASH_EXTENSIONS = BIT(1), + /* + * Indicates that chip and any MUXes support bidirectional data on the + * two SPI data lines. + */ + USB_SPI_FEATURE_DUAL_MODE_SUPPORTED = BIT(2), + /* + * Indicates that chip and any MUXes support bidirectional data on the + * "hold" and "write protect" lines. + */ + USB_SPI_FEATURE_QUAD_MODE_SUPPORTED = BIT(3), + /* Indicates support for eight-line bidirectional data. */ + USB_SPI_FEATURE_OCTO_MODE_SUPPORTED = BIT(4), + /* + * Indicates support for double transfer rate, i.e. data bit shift on + * both rising and falling clock edges. + */ + USB_SPI_FEATURE_DTR_SUPPORTED = BIT(5), }; struct usb_spi_response_configuration_v2 { @@ -314,15 +450,57 @@ struct usb_spi_continue_v2 { uint8_t data[USB_SPI_PAYLOAD_SIZE_V2_CONTINUE]; } __packed; +enum chip_select_flags { + /* Indicates chip select should be asserted. */ + USB_SPI_CHIP_SELECT = BIT(0) +}; + +struct usb_spi_chip_select_command { + uint16_t packet_id; + uint16_t flags; +} __packed; + +struct usb_spi_chip_select_response { + uint16_t packet_id; + uint16_t status_code; +} __packed; + +struct usb_spi_flash_command { + uint16_t packet_id; + uint16_t count; + uint32_t flags; + uint8_t data[USB_SPI_PAYLOAD_SIZE_FLASH_START]; +} __packed; + +/* + * Mask of the flags that are handled by logic in sub_spi.c, and not passed to + * SPI drivers through usb_spi_board_transaction(). + */ +#define FLASH_FLAGS_NONBOARD 0xF0000000UL + +#define FLASH_FLAG_WRITE_ENABLE_POS 28U +#define FLASH_FLAG_WRITE_ENABLE (0x1UL << FLASH_FLAG_WRITE_ENABLE_POS) + +#define FLASH_FLAG_POLL_POS 29U +#define FLASH_FLAG_POLL (0x1UL << FLASH_FLAG_POLL_POS) + +#define FLASH_FLAG_READ_WRITE_POS 31U +#define FLASH_FLAG_READ_WRITE_MSK (0x1UL << FLASH_FLAG_READ_WRITE_POS) +#define FLASH_FLAG_READ_WRITE_READ 0 +#define FLASH_FLAG_READ_WRITE_WRITE (0x1UL << FLASH_FLAG_READ_WRITE_POS) + struct usb_spi_packet_ctx { union { uint8_t bytes[USB_MAX_PACKET_SIZE]; uint16_t packet_id; struct usb_spi_command_v2 cmd_start; + struct usb_spi_flash_command cmd_flash_start; struct usb_spi_continue_v2 cmd_continue; struct usb_spi_response_configuration_v2 rsp_config; struct usb_spi_response_v2 rsp_start; struct usb_spi_continue_v2 rsp_continue; + struct usb_spi_chip_select_command cmd_cs; + struct usb_spi_chip_select_response rsp_cs; } __packed; /* * By storing the number of bytes in the header and knowing that the @@ -336,25 +514,27 @@ struct usb_spi_packet_ctx { }; enum usb_spi_error { - USB_SPI_SUCCESS = 0x0000, - USB_SPI_TIMEOUT = 0x0001, - USB_SPI_BUSY = 0x0002, - USB_SPI_WRITE_COUNT_INVALID = 0x0003, - USB_SPI_READ_COUNT_INVALID = 0x0004, - USB_SPI_DISABLED = 0x0005, + USB_SPI_SUCCESS = 0x0000, + USB_SPI_TIMEOUT = 0x0001, + USB_SPI_BUSY = 0x0002, + USB_SPI_WRITE_COUNT_INVALID = 0x0003, + USB_SPI_READ_COUNT_INVALID = 0x0004, + USB_SPI_DISABLED = 0x0005, /* The RX continue packet's data index is invalid. */ - USB_SPI_RX_BAD_DATA_INDEX = 0x0006, + USB_SPI_RX_BAD_DATA_INDEX = 0x0006, /* The RX endpoint has received more data than write count. */ - USB_SPI_RX_DATA_OVERFLOW = 0x0007, + USB_SPI_RX_DATA_OVERFLOW = 0x0007, /* An unexpected packet arrived on the device. */ - USB_SPI_RX_UNEXPECTED_PACKET = 0x0008, + USB_SPI_RX_UNEXPECTED_PACKET = 0x0008, /* The device does not support full duplex mode. */ USB_SPI_UNSUPPORTED_FULL_DUPLEX = 0x0009, - USB_SPI_UNKNOWN_ERROR = 0x8000, + /* The device does not support dual/quad wire mode. */ + USB_SPI_UNSUPPORTED_FLASH_MODE = 0x000A, + USB_SPI_UNKNOWN_ERROR = 0x8000, }; enum usb_spi_request { - USB_SPI_REQ_ENABLE = 0x0000, + USB_SPI_REQ_ENABLE = 0x0000, USB_SPI_REQ_DISABLE = 0x0001, }; @@ -366,229 +546,92 @@ enum usb_spi_request { * If a platform has a small maximum SPI transfer size, it can be optimized * by setting these limits to the maximum transfer size. */ -#define USB_SPI_BUFFER_SIZE (USB_SPI_PAYLOAD_SIZE_V2_START + \ - (4 * USB_SPI_PAYLOAD_SIZE_V2_CONTINUE)) -#define USB_SPI_MAX_WRITE_COUNT USB_SPI_BUFFER_SIZE -#define USB_SPI_MAX_READ_COUNT USB_SPI_BUFFER_SIZE - -struct usb_spi_transfer_ctx { - /* Address of transfer buffer. */ - uint8_t *buffer; - /* Number of bytes in the transfer. */ - size_t transfer_size; - /* Number of bytes transferred. */ - size_t transfer_index; -}; - -enum usb_spi_mode { - /* No tasks are required. */ - USB_SPI_MODE_IDLE = 0, - /* Indicates the device needs to send it's USB SPI configuration.*/ - USB_SPI_MODE_SEND_CONFIGURATION, - /* Indicates we device needs start the SPI transfer. */ - USB_SPI_MODE_START_SPI, - /* Indicates we should start a transfer response. */ - USB_SPI_MODE_START_RESPONSE, - /* Indicates we need to continue a transfer response. */ - USB_SPI_MODE_CONTINUE_RESPONSE, -}; - -struct usb_spi_state { - /* - * The SPI bridge must be enabled both locally and by the host to allow - * access to the SPI device. The enabled_host flag is set and cleared - * by sending USB_SPI_REQ_ENABLE and USB_SPI_REQ_DISABLE to the device - * control endpoint. The enabled_device flag is set by calling - * usb_spi_enable. - */ - int enabled_host; - int enabled_device; - - /* - * The current enabled state. This is only updated in the deferred - * callback. Whenever either of the host or device specific enable - * flags is changed the deferred callback is queued, and it will check - * their combined state against this flag. If the combined state is - * different, then one of usb_spi_board_enable or usb_spi_board_disable - * is called and this flag is updated. This ensures that the board - * specific state update routines are only called from the deferred - * callback. - */ - int enabled; - - /* Mark the current operating mode. */ - enum usb_spi_mode mode; - - /* - * Stores the status code response for the transfer, delivered in the - * header for the first response packet. Error code is cleared during - * first RX packet and set if a failure occurs. - */ - uint16_t status_code; - - /* Stores the content from the USB packets */ - struct usb_spi_packet_ctx receive_packet; - struct usb_spi_packet_ctx transmit_packet; - - /* - * Context structures representing the progress receiving the SPI - * write data and transmitting the SPI read data. - */ - struct usb_spi_transfer_ctx spi_write_ctx; - struct usb_spi_transfer_ctx spi_read_ctx; -}; - -/* - * Compile time Per-USB gpio configuration stored in flash. Instances of this - * structure are provided by the user of the USB gpio. This structure binds - * together all information required to operate a USB gpio. - */ -struct usb_spi_config { - /* In RAM state of the USB SPI bridge. */ - struct usb_spi_state *state; - - /* Interface and endpoint indices. */ - int interface; - int endpoint; - - /* Deferred function to call to handle SPI request. */ - const struct deferred_data *deferred; - - /* Pointers to USB endpoint buffers. */ - usb_uint *ep_rx_ram; - usb_uint *ep_tx_ram; - - /* Flags. See USB_SPI_CONFIG_FLAGS_* for definitions */ - uint32_t flags; -}; +#ifdef CONFIG_USB_SPI_BUFFER_SIZE +#define USB_SPI_BUFFER_SIZE CONFIG_USB_SPI_BUFFER_SIZE +#else +#define USB_SPI_BUFFER_SIZE \ + (USB_SPI_PAYLOAD_SIZE_V2_START + (4 * USB_SPI_PAYLOAD_SIZE_V2_CONTINUE)) +#endif +#define USB_SPI_MAX_WRITE_COUNT USB_SPI_BUFFER_SIZE +#define USB_SPI_MAX_READ_COUNT USB_SPI_BUFFER_SIZE + +/* Protocol uses two-byte length fields. Larger buffer makes no sense. */ +BUILD_ASSERT(USB_SPI_BUFFER_SIZE <= 65536); /* - * Use when you want the SPI subsystem to be enabled even when the USB SPI - * endpoint is not enabled by the host. This means that when this firmware - * enables SPI, then the HW SPI module is enabled (i.e. SPE bit is set) until - * this firmware disables the SPI module; it ignores the host's enables state. - */ -#define USB_SPI_CONFIG_FLAGS_IGNORE_HOST_SIDE_ENABLE BIT(0) - -/* - * Convenience macro for defining a USB SPI bridge driver. - * - * NAME is used to construct the names of the trampoline functions and the - * usb_spi_config struct, the latter is just called NAME. - * - * INTERFACE is the index of the USB interface to associate with this - * SPI driver. - * - * ENDPOINT is the index of the USB bulk endpoint used for receiving and - * transmitting bytes. + * Set the enable state for the USB-SPI bridge. * - * FLAGS encodes different run-time control parameters. See - * USB_SPI_CONFIG_FLAGS_* for definitions. + * The bridge must be enabled from both the host and device side + * before the SPI bus is usable. This allows the bridge to be + * available for host tools to use without forcing the device to + * disconnect or disable whatever else might be using the SPI bus. */ -#define USB_SPI_CONFIG(NAME, \ - INTERFACE, \ - ENDPOINT, \ - FLAGS) \ - static uint16_t CONCAT2(NAME, _buffer_)[(USB_SPI_BUFFER_SIZE + 1) / 2];\ - static usb_uint CONCAT2(NAME, _ep_rx_buffer_)[USB_MAX_PACKET_SIZE / 2] __usb_ram; \ - static usb_uint CONCAT2(NAME, _ep_tx_buffer_)[USB_MAX_PACKET_SIZE / 2] __usb_ram; \ - static void CONCAT2(NAME, _deferred_)(void); \ - DECLARE_DEFERRED(CONCAT2(NAME, _deferred_)); \ - struct usb_spi_state CONCAT2(NAME, _state_) = { \ - .enabled_host = 0, \ - .enabled_device = 0, \ - .enabled = 0, \ - .spi_write_ctx.buffer = (uint8_t *)CONCAT2(NAME, _buffer_), \ - .spi_read_ctx.buffer = (uint8_t *)CONCAT2(NAME, _buffer_), \ - }; \ - struct usb_spi_config const NAME = { \ - .state = &CONCAT2(NAME, _state_), \ - .interface = INTERFACE, \ - .endpoint = ENDPOINT, \ - .deferred = &CONCAT2(NAME, _deferred__data), \ - .ep_rx_ram = CONCAT2(NAME, _ep_rx_buffer_), \ - .ep_tx_ram = CONCAT2(NAME, _ep_tx_buffer_), \ - .flags = FLAGS, \ - }; \ - const struct usb_interface_descriptor \ - USB_IFACE_DESC(INTERFACE) = { \ - .bLength = USB_DT_INTERFACE_SIZE, \ - .bDescriptorType = USB_DT_INTERFACE, \ - .bInterfaceNumber = INTERFACE, \ - .bAlternateSetting = 0, \ - .bNumEndpoints = 2, \ - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ - .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_SPI, \ - .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_SPI, \ - .iInterface = 0, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 0) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = 0x80 | ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk IN */, \ - .wMaxPacketSize = USB_MAX_PACKET_SIZE, \ - .bInterval = 10, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 1) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk OUT */, \ - .wMaxPacketSize = USB_MAX_PACKET_SIZE, \ - .bInterval = 0, \ - }; \ - static void CONCAT2(NAME, _ep_tx_) (void) { usb_spi_tx (&NAME); } \ - static void CONCAT2(NAME, _ep_rx_) (void) { usb_spi_rx (&NAME); } \ - static void CONCAT2(NAME, _ep_event_)(enum usb_ep_event evt) \ - { \ - usb_spi_event(&NAME, evt); \ - } \ - USB_DECLARE_EP(ENDPOINT, \ - CONCAT2(NAME, _ep_tx_), \ - CONCAT2(NAME, _ep_rx_), \ - CONCAT2(NAME, _ep_event_)); \ - static int CONCAT2(NAME, _interface_)(usb_uint *rx_buf, \ - usb_uint *tx_buf) \ - { return usb_spi_interface(&NAME, rx_buf, tx_buf); } \ - USB_DECLARE_IFACE(INTERFACE, \ - CONCAT2(NAME, _interface_)); \ - static void CONCAT2(NAME, _deferred_)(void) \ - { usb_spi_deferred(&NAME); } +void usb_spi_enable(int enabled); /* - * Handle SPI request in a deferred callback. + * These functions should be implemented by the board to provide any board + * specific operations required to enable or disable access to the SPI device. */ -void usb_spi_deferred(struct usb_spi_config const *config); +void usb_spi_board_enable(void); +void usb_spi_board_disable(void); /* - * Set the enable state for the USB-SPI bridge. - * - * The bridge must be enabled from both the host and device side - * before the SPI bus is usable. This allows the bridge to be - * available for host tools to use without forcing the device to - * disconnect or disable whatever else might be using the SPI bus. + * In order to facilitate special SPI busses not covered by standard EC + * drivers, setting the USB_SPI_CUSTOM_SPI_DEVICE_MASK bit of spi_device->port + * will cause the USB to SPI forwarding logic to invoke this method rather + * than the standard spi_transaction_async(). */ -void usb_spi_enable(struct usb_spi_config const *config, int enabled); +int usb_spi_board_transaction(const struct spi_device_t *spi_device, + uint32_t flash_flags, const uint8_t *txdata, + int txlen, uint8_t *rxdata, int rxlen); /* - * These functions are used by the trampoline functions defined above to - * connect USB endpoint events with the generic USB GPIO driver. + * Flags to use in usb_spi_board_transaction_async() for advanced serial flash + * communication, when supported. */ -void usb_spi_tx(struct usb_spi_config const *config); -void usb_spi_rx(struct usb_spi_config const *config); -void usb_spi_event(struct usb_spi_config const *config, enum usb_ep_event evt); -int usb_spi_interface(struct usb_spi_config const *config, - usb_uint *rx_buf, - usb_uint *tx_buf); + +/* Number of bytes of opcode (0-3). */ +#define FLASH_FLAG_OPCODE_LEN_POS 0 +#define FLASH_FLAG_OPCODE_LEN_MSK (0x3U << FLASH_FLAG_OPCODE_LEN_POS) + +/* Number of bytes of address plus additional data bytes (0-7). */ +#define FLASH_FLAG_ADDR_LEN_POS 2 +#define FLASH_FLAG_ADDR_LEN_MSK (0x7U << FLASH_FLAG_ADDR_LEN_POS) + +/* At what stage to switch to multi-lane mode (if any). */ +#define FLASH_FLAG_MODE_POS 5 +#define FLASH_FLAG_MODE_MSK (0x3U << FLASH_FLAG_MODE_POS) +#define FLASH_FLAG_MODE_111 (0x0U << FLASH_FLAG_MODE_POS) +#define FLASH_FLAG_MODE_11N (0x1U << FLASH_FLAG_MODE_POS) +#define FLASH_FLAG_MODE_1NN (0x2U << FLASH_FLAG_MODE_POS) +#define FLASH_FLAG_MODE_NNN (0x3U << FLASH_FLAG_MODE_POS) + +/* Data width during the later stages (value of N, above). */ +#define FLASH_FLAG_WIDTH_POS 7 +#define FLASH_FLAG_WIDTH_MSK (0x3U << FLASH_FLAG_WIDTH_POS) +#define FLASH_FLAG_WIDTH_1WIRE (0x0U << FLASH_FLAG_WIDTH_POS) +#define FLASH_FLAG_WIDTH_2WIRE (0x1U << FLASH_FLAG_WIDTH_POS) +#define FLASH_FLAG_WIDTH_4WIRE (0x2U << FLASH_FLAG_WIDTH_POS) +#define FLASH_FLAG_WIDTH_8WIRE (0x3U << FLASH_FLAG_WIDTH_POS) + +/* Transmit opcode bits at both clock edges in later stages. */ +#define FLASH_FLAG_DTR_POS 9 +#define FLASH_FLAG_DTR (0x1U << FLASH_FLAG_DTR_POS) + +/* Number of dummy clock cycles (0-31). */ +#define FLASH_FLAG_DUMMY_CYCLES_POS 10 +#define FLASH_FLAG_DUMMY_CYCLES_MSK (0x1FU << FLASH_FLAG_DUMMY_CYCLES_POS) /* - * These functions should be implemented by the board to provide any board - * specific operations required to enable or disable access to the SPI device. + * Mask of the flags that cannot be ignored. This is basically any flags + * which call for wires to switch direction, or data being clocked on both + * rising and falling edges. As long as none of these are present, then the + * remaining flags specifying the length of opcode/address can be ignored, as + * the entire data buffer can be transmitted as a sequence of bytes, without + * the controller knowing which parts are to be interpreted as + * opcode/address/data. */ -void usb_spi_board_enable(struct usb_spi_config const *config); -void usb_spi_board_disable(struct usb_spi_config const *config); +#define FLASH_FLAGS_REQUIRING_SUPPORT \ + (FLASH_FLAG_MODE_MSK | FLASH_FLAG_DTR | FLASH_FLAG_DUMMY_CYCLES_MSK) #endif /* __CROS_EC_USB_SPI_H */ diff --git a/chip/stm32/watchdog.c b/chip/stm32/watchdog.c index 067ea32aa6..1a54d6f52d 100644 --- a/chip/stm32/watchdog.c +++ b/chip/stm32/watchdog.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -21,12 +21,22 @@ * value large enough that we reload before the worst-case watchdog delay * (fastest LSI clock). */ +#ifdef CHIP_FAMILY_STM32L4 +#define LSI_CLOCK 34000 +#else #define LSI_CLOCK 56000 +#endif + +/* The timeout value is multiplied by 1000 to be converted into ms */ +#define HAL_IWDG_DEFAULT_TIMEOUT ((6UL * 256UL * 1000UL) / LSI_CLOCK) /* * Use largest prescaler divider = /256. This gives a worst-case watchdog * clock of 56000/256 = 218 Hz, and a maximum timeout period of (4095/218 Hz) = * 18.7 sec. + * + * For STM32L4, Max LSI is 34000. Watchdog clock is 34000 / 256 = 132Hz, + * Max timeout = 4095 / 132 = 31 sec. */ #define IWDG_PRESCALER 6 #define IWDG_PRESCALER_DIV (4 << IWDG_PRESCALER) @@ -44,6 +54,12 @@ DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); int watchdog_init(void) { +#ifdef CHIP_FAMILY_STM32L4 + timestamp_t tickstart, ticknow; + + /* Enable watchdog registers */ + STM32_IWDG_KR = STM32_IWDG_KR_START; +#endif /* Unlock watchdog registers */ STM32_IWDG_KR = STM32_IWDG_KR_UNLOCK; @@ -51,12 +67,50 @@ int watchdog_init(void) STM32_IWDG_PR = IWDG_PRESCALER & 7; /* Set the reload value of the watchdog counter */ - STM32_IWDG_RLR = MIN(STM32_IWDG_RLR_MAX, CONFIG_WATCHDOG_PERIOD_MS * - (LSI_CLOCK / IWDG_PRESCALER_DIV) / 1000); + STM32_IWDG_RLR = MIN(STM32_IWDG_RLR_MAX, + CONFIG_WATCHDOG_PERIOD_MS * + (LSI_CLOCK / IWDG_PRESCALER_DIV) / 1000); +#ifdef CHIP_FAMILY_STM32L4 + tickstart = get_time(); + /* Wait for SR */ + while (STM32_IWDG_SR != 0x00u) { + ticknow = get_time(); + if ((ticknow.val - tickstart.val) > + HAL_IWDG_DEFAULT_TIMEOUT * 1000) { + return EC_ERROR_TIMEOUT; + } + } + /* Reload the watchdog */ + STM32_IWDG_KR = STM32_IWDG_KR_RELOAD; +#else /* Start the watchdog (and re-lock registers) */ STM32_IWDG_KR = STM32_IWDG_KR_START; + /* + * We should really wait for IWDG_PR and IWDG_RLR value to be updated + * but updating those registers can take about 48ms (found + * empirically, it's 6 LSI cycles at 32kHz). Such a big delay is not + * desired during system init. + * + * However documentation allows us to continue code execution, but + * we should wait for RVU bit to be clear before updating IWDG_RLR + * once again (hard reboot for STM32H7 and STM32F4). + * + * RM0433 Rev 7 + * Section 45.4.4 Page 1920 + * https://www.st.com/resource/en/reference_manual/dm00314099.pdf + * If several reload, prescaler, or window values are used by the + * application, it is mandatory to wait until RVU bit is reset before + * changing the reload value, to wait until PVU bit is reset before + * changing the prescaler value, and to wait until WVU bit is reset + * before changing the window value. However, after updating the + * prescaler and/or the reload/window value it is not necessary to wait + * until RVU or PVU or WVU is reset before continuing code execution + * except in case of low-power mode entry. + */ + +#endif #ifdef CONFIG_WATCHDOG_HELP /* Use a harder timer to warn about an impending watchdog reset */ hwtimer_setup_watchdog(); diff --git a/cmake/toolchain-armv7m.cmake b/cmake/toolchain-armv7m.cmake new file mode 100644 index 0000000000..d05e6c3a1c --- /dev/null +++ b/cmake/toolchain-armv7m.cmake @@ -0,0 +1,21 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) + +set(CROSS_COMPILE armv7m-cros-eabi-) +set(CMAKE_SYSROOT /usr/armv7m-cros-eabi/) + +set(CC_NAME clang) +set(CXX_NAME clang++) + +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CROSS_COMPILE CC_NAME CXX_NAME) +include("${CMAKE_CURRENT_LIST_DIR}/toolchain-common.cmake") + +add_compile_options(-mcpu=cortex-m4) +add_compile_options(-mfloat-abi=hard) + +add_link_options(-lclang_rt.builtins-armv7m) +add_link_options(-lnosys) diff --git a/cmake/toolchain-common.cmake b/cmake/toolchain-common.cmake new file mode 100644 index 0000000000..765487267f --- /dev/null +++ b/cmake/toolchain-common.cmake @@ -0,0 +1,53 @@ +# Copyright 2023 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Input variables: +# CROSS_COMPILE: the prefix of the cross compiler. +# CC_NAME: the name of the C compiler. +# CXX_NAME: the name of the C++ compiler. + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set(CMAKE_C_COMPILER "${CROSS_COMPILE}${CC_NAME}") +set(CMAKE_CXX_COMPILER "${CROSS_COMPILE}${CXX_NAME}") +set(CMAKE_OBJCOPY "${CROSS_COMPILE}objcopy") +set(CMAKE_OBJDUMP "${CROSS_COMPILE}objdump") +set(CMAKE_READELF "${CROSS_COMPILE}readelf") + +if ("${CC_NAME}" STREQUAL "gcc") +set(CMAKE_LINKER "${CROSS_COMPILE}ld") +else() +set(CMAKE_LINKER "${CROSS_COMPILE}ld.lld") +endif() + +# This is only for host unittests build. +if ("${CC_NAME}" STREQUAL gcc AND "${CMAKE_SYSROOT}" STREQUAL "") +set(CMAKE_AR "${CROSS_COMPILE}gcc-ar") +set(CMAKE_NM "${CROSS_COMPILE}gcc-nm") +set(CMAKE_RANLIB "${CROSS_COMPILE}gcc-ranlib") +else() +set(CMAKE_AR "${CROSS_COMPILE}ar") +set(CMAKE_NM "${CROSS_COMPILE}nm") +set(CMAKE_RANLIB "${CROSS_COMPILE}ranlib") +endif() + +if ("${CC_NAME}" STREQUAL gcc) +add_compile_options(-Os) +else() +add_compile_options(-Oz) +endif() + +# Enable Link Time Optimization. +add_compile_options(-flto) +add_link_options(-flto) + +# See https://www.chromium.org/chromium-os/build/c-exception-support +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables") + +set(CMAKE_POSITION_INDEPENDENT_CODE OFF) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100644 index 0000000000..2b9baa0e69 --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +add_subdirectory(spi) diff --git a/common/Kconfig b/common/Kconfig new file mode 100644 index 0000000000..545b51ab20 --- /dev/null +++ b/common/Kconfig @@ -0,0 +1,5 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +rsource "spi/Kconfig" diff --git a/common/accel_cal.c b/common/accel_cal.c index 533a14fbc4..878f3b06fa 100644 --- a/common/accel_cal.c +++ b/common/accel_cal.c @@ -1,11 +1,11 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "accel_cal.h" #include "common.h" #include "console.h" -#include "accel_cal.h" #define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args) @@ -23,17 +23,17 @@ void accel_cal_reset(struct accel_cal *cal) static inline int compute_temp_gate(const struct accel_cal *cal, fp_t temp) { - int gate = (int) fp_div(fp_mul(temp - CONFIG_ACCEL_CAL_MIN_TEMP, - INT_TO_FP(cal->num_temp_windows)), - TEMP_RANGE); + int gate = (int)fp_div(fp_mul(temp - CONFIG_ACCEL_CAL_MIN_TEMP, + INT_TO_FP(cal->num_temp_windows)), + TEMP_RANGE); - return gate < cal->num_temp_windows - ? gate : (cal->num_temp_windows - 1); + return gate < cal->num_temp_windows ? gate : + (cal->num_temp_windows - 1); } -test_mockable bool accel_cal_accumulate( - struct accel_cal *cal, uint32_t timestamp, fp_t x, fp_t y, fp_t z, - fp_t temp) +test_mockable bool accel_cal_accumulate(struct accel_cal *cal, + uint32_t timestamp, fp_t x, fp_t y, + fp_t z, fp_t temp) { struct accel_cal_algo *algo; diff --git a/common/acpi.c b/common/acpi.c index 92117f09b1..5dd71d244e 100644 --- a/common/acpi.c +++ b/common/acpi.c @@ -1,42 +1,46 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "acpi.h" #include "battery.h" +#include "body_detection.h" #include "common.h" #include "console.h" #include "dptf.h" +#include "ec_commands.h" +#include "fan.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "keyboard_backlight.h" #include "lpc.h" -#include "ec_commands.h" -#include "tablet_mode.h" +#include "printf.h" #include "pwm.h" +#include "tablet_mode.h" #include "timer.h" #include "usb_charge.h" +#include "usb_common.h" #include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_LPC, format, ##args) +#define CPRINTS(format, args...) cprints(CC_LPC, format, ##args) /* Last received ACPI command */ -static uint8_t __bss_slow acpi_cmd; +static uint8_t acpi_cmd; /* First byte of data after ACPI command */ -static uint8_t __bss_slow acpi_addr; +static uint8_t acpi_addr; /* Number of data writes after command */ -static int __bss_slow acpi_data_count; +static int acpi_data_count; /* Test byte in ACPI memory space */ -static uint8_t __bss_slow acpi_mem_test; +static uint8_t acpi_mem_test; #ifdef CONFIG_DPTF -static int __bss_slow dptf_temp_sensor_id; /* last sensor ID written */ -static int __bss_slow dptf_temp_threshold; /* last threshold written */ +static int dptf_temp_sensor_id; /* last sensor ID written */ +static int dptf_temp_threshold; /* last threshold written */ /* * Current DPTF profile number. @@ -60,9 +64,9 @@ static int current_dptf_profile = DPTF_PROFILE_DEFAULT; #define ACPI_READ_CACHE_FLUSHED (EC_ACPI_MEM_MAPPED_BEGIN - 1) /* Calculate size of valid cache based upon end of memmap data. */ -#define ACPI_VALID_CACHE_SIZE(addr) (MIN( \ - EC_ACPI_MEM_MAPPED_SIZE + EC_ACPI_MEM_MAPPED_BEGIN - (addr), \ - ACPI_READ_CACHE_SIZE)) +#define ACPI_VALID_CACHE_SIZE(addr) \ + (MIN(EC_ACPI_MEM_MAPPED_SIZE + EC_ACPI_MEM_MAPPED_BEGIN - (addr), \ + ACPI_READ_CACHE_SIZE)) /* * In burst mode, read the requested memmap data and the data immediately @@ -131,23 +135,22 @@ static int acpi_read(uint8_t addr) uint8_t *memmap_addr = (uint8_t *)(lpc_get_memmap_range() + addr - EC_ACPI_MEM_MAPPED_BEGIN); + DISABLE_CLANG_WARNING("-Wtautological-constant-out-of-range-compare"); /* Check for out-of-range read. */ if (addr < EC_ACPI_MEM_MAPPED_BEGIN || addr >= EC_ACPI_MEM_MAPPED_BEGIN + EC_ACPI_MEM_MAPPED_SIZE) { - CPRINTS("ACPI read 0x%02x (ignored)", - acpi_addr); + CPRINTS("ACPI read 0x%02x (ignored)", acpi_addr); return 0xff; } + ENABLE_CLANG_WARNING("-Wtautological-constant-out-of-range-compare"); /* Read from cache if enabled (burst mode). */ if (acpi_read_cache.enabled) { /* Fetch to cache on miss. */ if (acpi_read_cache.start_addr == ACPI_READ_CACHE_FLUSHED || acpi_read_cache.start_addr > addr || - addr - acpi_read_cache.start_addr >= - ACPI_READ_CACHE_SIZE) { - memcpy(acpi_read_cache.data, - memmap_addr, + addr - acpi_read_cache.start_addr >= ACPI_READ_CACHE_SIZE) { + memcpy(acpi_read_cache.data, memmap_addr, ACPI_VALID_CACHE_SIZE(addr)); acpi_read_cache.start_addr = addr; } @@ -167,7 +170,7 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) { int data = 0; int retval = 0; - int result = 0xff; /* value for bogus read */ + int result = 0xff; /* value for bogus read */ /* Read command/data; this clears the FRMH status bit. */ if (is_cmd) { @@ -231,7 +234,12 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) #ifdef CONFIG_DPTF result |= (acpi_dptf_get_profile_num() & EC_ACPI_MEM_DDPN_MASK) - << EC_ACPI_MEM_DDPN_SHIFT; + << EC_ACPI_MEM_DDPN_SHIFT; +#endif + +#ifdef CONFIG_BODY_DETECTION_NOTIFY_MODE_CHANGE + if (body_detect_get_state() == BODY_DETECTION_ON_BODY) + result |= BIT(EC_ACPI_MEM_STTB_SHIFT); #endif break; @@ -250,7 +258,7 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) result = val >> (8 * off); break; - } + } case EC_ACPI_MEM_DEVICE_FEATURES4: case EC_ACPI_MEM_DEVICE_FEATURES5: case EC_ACPI_MEM_DEVICE_FEATURES6: @@ -260,7 +268,7 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) result = val >> (8 * off); break; - } + } #ifdef CONFIG_USB_PORT_POWER_DUMB case EC_ACPI_MEM_USB_PORT_POWER: { @@ -274,13 +282,18 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) */ result = 0; for (i = 0; i < port_count; ++i) { - if (gpio_get_level(usb_port_enable[i]) != 0) + if ((usb_port_enable[i] >= 0) && + (gpio_get_level(usb_port_enable[i]) != 0)) result |= 1 << i; } break; - } + } +#endif +#ifdef CONFIG_USBC_RETIMER_FW_UPDATE + case EC_ACPI_MEM_USB_RETIMER_FW_UPDATE: + result = usb_retimer_fw_update_get_result(); + break; #endif - default: result = acpi_read(acpi_addr); break; @@ -303,17 +316,19 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) break; #endif #ifdef CONFIG_KEYBOARD_BACKLIGHT - case EC_ACPI_MEM_KEYBOARD_BACKLIGHT: + case EC_ACPI_MEM_KEYBOARD_BACKLIGHT: { + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; /* * Debug output with CR not newline, because the host * does a lot of keyboard backlights and it scrolls the * debug console. */ - CPRINTF("\r[%pT ACPI kblight %d]", - PRINTF_TIMESTAMP_NOW, data); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + CPRINTF("\r[%s ACPI kblight %d]", ts_str, data); kblight_set(data); kblight_enable(data > 0); break; + } #endif #ifdef CONFIG_FANS case EC_ACPI_MEM_FAN_DUTY: @@ -327,13 +342,12 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) case EC_ACPI_MEM_TEMP_THRESHOLD: dptf_temp_threshold = data + EC_TEMP_SENSOR_OFFSET; break; - case EC_ACPI_MEM_TEMP_COMMIT: - { + case EC_ACPI_MEM_TEMP_COMMIT: { int idx = data & EC_ACPI_MEM_TEMP_COMMIT_SELECT_MASK; int enable = data & EC_ACPI_MEM_TEMP_COMMIT_ENABLE_MASK; dptf_set_temp_threshold(dptf_temp_sensor_id, - dptf_temp_threshold, - idx, enable); + dptf_temp_threshold, idx, + enable); break; } #endif @@ -365,8 +379,9 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) if (mode_field & 1) mode = USB_CHARGE_MODE_ENABLED; - if (usb_charge_set_mode(i, mode, - USB_ALLOW_SUSPEND_CHARGE)) { + if (usb_charge_set_mode( + i, mode, + USB_ALLOW_SUSPEND_CHARGE)) { CPRINTS("ERROR: could not set charge " "mode of USB port p%d to %d", i, mode); @@ -374,9 +389,15 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) mode_field >>= 1; } break; - } + } +#endif +#ifdef CONFIG_USBC_RETIMER_FW_UPDATE + case EC_ACPI_MEM_USB_RETIMER_FW_UPDATE: + usb_retimer_fw_update_process_op( + EC_ACPI_MEM_USB_RETIMER_PORT(data), + EC_ACPI_MEM_USB_RETIMER_OP(data)); + break; #endif - default: CPRINTS("ACPI write 0x%02x = 0x%02x (ignored)", acpi_addr, data); @@ -406,7 +427,8 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) * Disable from deferred function in case burst mode is enabled * for an extremely long time (ex. kernel bug / crash). */ - hook_call_deferred(&acpi_disable_burst_deferred_data, 1*SECOND); + hook_call_deferred(&acpi_disable_burst_deferred_data, + 1 * SECOND); /* ACPI 5.0-12.3.3: Burst ACK */ *resultptr = 0x90; diff --git a/common/adc.c b/common/adc.c index 5407de6cfe..4c2519c046 100644 --- a/common/adc.c +++ b/common/adc.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,7 +6,6 @@ /* ADC module for Chrome EC */ #include "adc.h" -#include "adc_chip.h" #include "common.h" #include "console.h" #include "ec_commands.h" @@ -15,21 +14,6 @@ /* 'adc' console command is not supported in continuous mode */ #ifndef CONFIG_ADC_PROFILE_FAST_CONTINUOUS -static enum adc_channel find_adc_channel_by_name(const char *name) -{ - const struct adc_t *ch = adc_channels; - int i; - - if (!name || !*name) - return ADC_CH_COUNT; - - for (i = 0; i < ADC_CH_COUNT; i++, ch++) { - if (!strcasecmp(name, ch->name)) - return i; - } - - return ADC_CH_COUNT; -} static int print_one_adc(int channel) { @@ -38,18 +22,20 @@ static int print_one_adc(int channel) v = adc_read_channel(channel); if (v == ADC_READ_ERROR) return EC_ERROR_UNKNOWN; - ccprintf(" %s = %d\n", adc_channels[channel].name, v); + ccprintf("[%d] %s = %d mV\n", channel, adc_channels[channel].name, v); return EC_SUCCESS; } -static int command_adc(int argc, char **argv) +static int command_adc(int argc, const char **argv) { int i, ret; /* If a channel is specified, read only that one */ if (argc == 2) { - i = find_adc_channel_by_name(argv[1]); - if (i == ADC_CH_COUNT) + char *end; + + i = strtoi(argv[1], &end, 0); + if (*end || i < 0 || i >= ADC_CH_COUNT) return EC_ERROR_PARAM1; return print_one_adc(i); } else { @@ -62,9 +48,7 @@ static int command_adc(int argc, char **argv) return EC_SUCCESS; } } -DECLARE_CONSOLE_COMMAND(adc, command_adc, - "[name]", - "Print ADC channel(s)"); +DECLARE_CONSOLE_COMMAND(adc, command_adc, "[id]", NULL); static enum ec_status hc_adc_read(struct host_cmd_handler_args *args) { diff --git a/common/aes-gcm.c b/common/aes-gcm.c deleted file mode 120000 index 3176d85ff8..0000000000 --- a/common/aes-gcm.c +++ /dev/null @@ -1 +0,0 @@ -../third_party/boringssl/common/aes-gcm.c \ No newline at end of file diff --git a/common/aes.c b/common/aes.c deleted file mode 120000 index ed10836943..0000000000 --- a/common/aes.c +++ /dev/null @@ -1 +0,0 @@ -../third_party/boringssl/common/aes.c \ No newline at end of file diff --git a/common/als.c b/common/als.c index 2e9c7ba96c..ea86250fef 100644 --- a/common/als.c +++ b/common/als.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,10 +18,13 @@ #include "timer.h" #include "util.h" -#define CPUTS(outstr) cputs(CC_ALS, outstr) -#define CPRINTS(format, args...) cprints(CC_ALS, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_ALS, format, ## args) +#ifdef CONFIG_ZEPHYR +#include "cros_als.h" +#endif +#define CPUTS(outstr) cputs(CC_ALS, outstr) +#define CPRINTS(format, args...) cprints(CC_ALS, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_ALS, format, ##args) #define ALS_POLL_PERIOD SECOND @@ -90,8 +93,7 @@ static void als_task_init(void) * Enable ALS task in S0 only and may need to re-enable * when sysjumped. */ - if (system_jumped_late() && - chipset_in_state(CHIPSET_STATE_ON)) + if (system_jumped_late() && chipset_in_state(CHIPSET_STATE_ON)) als_task_enable(); } @@ -103,7 +105,7 @@ DECLARE_HOOK(HOOK_INIT, als_task_init, HOOK_PRIO_ALS_INIT); /* Console commands */ #ifdef CONFIG_CMD_ALS -static int command_als(int argc, char **argv) +static int command_als(int argc, const char **argv) { int i, rv, val; @@ -121,7 +123,5 @@ static int command_als(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(als, command_als, - NULL, - "Print ALS values"); +DECLARE_CONSOLE_COMMAND(als, command_als, NULL, "Print ALS values"); #endif diff --git a/common/ap_hang_detect.c b/common/ap_hang_detect.c index 0c9e7a186d..6e3d7177a7 100644 --- a/common/ap_hang_detect.c +++ b/common/ap_hang_detect.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,12 +18,12 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) static struct ec_params_hang_detect hdparams; -static int active; /* Is hang detect timer active / counting? */ -static int timeout_will_reboot; /* Will the deferred call reboot the AP? */ +static int active; /* Is hang detect timer active / counting? */ +static int timeout_will_reboot; /* Will the deferred call reboot the AP? */ /** * Handle the hang detect timer expiring. @@ -56,7 +56,8 @@ static void hang_detect_deferred(void) timeout_will_reboot = 1; hook_call_deferred(&hang_detect_deferred_data, (hdparams.warm_reboot_timeout_msec - - hdparams.host_event_timeout_msec) * MSEC); + hdparams.host_event_timeout_msec) * + MSEC); } else { /* Not rebooting, so go back to idle */ active = 0; @@ -196,19 +197,18 @@ hang_detect_host_command(struct host_cmd_handler_args *args) */ if (hdparams.warm_reboot_timeout_msec && hdparams.warm_reboot_timeout_msec <= - hdparams.host_event_timeout_msec) + hdparams.host_event_timeout_msec) hdparams.host_event_timeout_msec = 0; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HANG_DETECT, - hang_detect_host_command, +DECLARE_HOST_COMMAND(EC_CMD_HANG_DETECT, hang_detect_host_command, EC_VER_MASK(0)); /*****************************************************************************/ /* Console command */ -static int command_hang_detect(int argc, char **argv) +static int command_hang_detect(int argc, const char **argv) { ccprintf("flags: 0x%x\n", hdparams.flags); @@ -233,6 +233,5 @@ static int command_hang_detect(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(hangdet, command_hang_detect, - NULL, +DECLARE_CONSOLE_COMMAND(hangdet, command_hang_detect, NULL, "Print hang detect state"); diff --git a/common/asm_define.h b/common/asm_define.h new file mode 100644 index 0000000000..b47bae067f --- /dev/null +++ b/common/asm_define.h @@ -0,0 +1,25 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_COMMON_ASM_DEFINE_H +#define __CROS_EC_COMMON_ASM_DEFINE_H + +#include "stddef.h" + +/* + * Use an immediate integer constraint + * (https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html) to write the + * value. This file is compiled with the "-S" flag, which stops the compiler + * after generating assembly. The resulting assembly is then grepped for the + * "__ASM_DEFINE__" strings, which is used to create a header file with the + * value. + */ +#define ASM_DEFINE(NAME, VAL) \ + __asm__ volatile(".ascii \" __ASM_DEFINE__ " NAME " %0\"" : : "i"(VAL)) + +#define ASM_DEFINE_OFFSET(NAME, TYPE, MEMBER) \ + ASM_DEFINE(NAME, offsetof(TYPE, MEMBER)) + +#endif /* __CROS_EC_COMMON_ASM_DEFINE_H */ diff --git a/common/audio_codec.c b/common/audio_codec.c index 3f7203ad15..aba1453ce3 100644 --- a/common/audio_codec.c +++ b/common/audio_codec.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,15 +9,14 @@ #include "host_command.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ##args) -static const uint32_t capabilities = - 0 +static const uint32_t capabilities = 0 #ifdef CONFIG_AUDIO_CODEC_CAP_WOV_AUDIO_SHM - | BIT(EC_CODEC_CAP_WOV_AUDIO_SHM) + | BIT(EC_CODEC_CAP_WOV_AUDIO_SHM) #endif #ifdef CONFIG_AUDIO_CODEC_CAP_WOV_LANG_SHM - | BIT(EC_CODEC_CAP_WOV_LANG_SHM) + | BIT(EC_CODEC_CAP_WOV_LANG_SHM) #endif ; @@ -122,8 +121,8 @@ int audio_codec_capable(uint8_t cap) return capabilities & BIT(cap); } -int audio_codec_register_shm(uint8_t shm_id, uint8_t cap, - uintptr_t *addr, uint32_t len, uint8_t type) +int audio_codec_register_shm(uint8_t shm_id, uint8_t cap, uintptr_t *addr, + uint32_t len, uint8_t type) { if (shm_id >= EC_CODEC_SHM_ID_LAST) return EC_ERROR_INVAL; @@ -140,8 +139,8 @@ int audio_codec_register_shm(uint8_t shm_id, uint8_t cap, return EC_SUCCESS; } -__attribute__((weak)) -int audio_codec_memmap_ap_to_ec(uintptr_t ap_addr, uintptr_t *ec_addr) +__attribute__((weak)) int audio_codec_memmap_ap_to_ec(uintptr_t ap_addr, + uintptr_t *ec_addr) { return EC_ERROR_UNIMPLEMENTED; } diff --git a/common/audio_codec_dmic.c b/common/audio_codec_dmic.c index c4f0b07a46..d85245791d 100644 --- a/common/audio_codec_dmic.c +++ b/common/audio_codec_dmic.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,7 +8,7 @@ #include "console.h" #include "host_command.h" -#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ##args) static enum ec_status dmic_get_max_gain(struct host_cmd_handler_args *args) { @@ -25,9 +25,9 @@ static enum ec_status dmic_set_gain_idx(struct host_cmd_handler_args *args) { const struct ec_param_ec_codec_dmic *p = args->params; - if (audio_codec_dmic_set_gain_idx( - p->set_gain_idx_param.channel, - p->set_gain_idx_param.gain) != EC_SUCCESS) + if (audio_codec_dmic_set_gain_idx(p->set_gain_idx_param.channel, + p->set_gain_idx_param.gain) != + EC_SUCCESS) return EC_RES_ERROR; return EC_RES_SUCCESS; @@ -38,8 +38,8 @@ static enum ec_status dmic_get_gain_idx(struct host_cmd_handler_args *args) const struct ec_param_ec_codec_dmic *p = args->params; struct ec_response_ec_codec_dmic_get_gain_idx *r = args->response; - if (audio_codec_dmic_get_gain_idx( - p->get_gain_idx_param.channel, &r->gain) != EC_SUCCESS) + if (audio_codec_dmic_get_gain_idx(p->get_gain_idx_param.channel, + &r->gain) != EC_SUCCESS) return EC_RES_ERROR; args->response_size = sizeof(*r); diff --git a/common/audio_codec_i2s_rx.c b/common/audio_codec_i2s_rx.c index aeae19bdca..ac6aa8ecce 100644 --- a/common/audio_codec_i2s_rx.c +++ b/common/audio_codec_i2s_rx.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,7 +8,7 @@ #include "console.h" #include "host_command.h" -#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ##args) static uint8_t i2s_rx_enabled; @@ -128,5 +128,5 @@ static enum ec_status i2s_rx_host_command(struct host_cmd_handler_args *args) return EC_RES_INVALID_PARAM; } -DECLARE_HOST_COMMAND(EC_CMD_EC_CODEC_I2S_RX, - i2s_rx_host_command, EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_EC_CODEC_I2S_RX, i2s_rx_host_command, + EC_VER_MASK(0)); diff --git a/common/audio_codec_wov.c b/common/audio_codec_wov.c index f84e45f342..7c7b43acae 100644 --- a/common/audio_codec_wov.c +++ b/common/audio_codec_wov.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,7 +13,7 @@ #include "task.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args) +#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ##args) /* * To shorten the variable names, or the following code is likely to greater @@ -99,7 +99,7 @@ static enum ec_status wov_set_lang_shm(struct host_cmd_handler_args *args) { const struct ec_param_ec_codec_wov *p = args->params; const struct ec_param_ec_codec_wov_set_lang_shm *pp = - &p->set_lang_shm_param; + &p->set_lang_shm_param; if (pp->total_len > LANG_BUF_LEN) return EC_RES_INVALID_PARAM; @@ -135,11 +135,11 @@ static enum ec_status wov_set_lang(struct host_cmd_handler_args *args) return EC_RES_BUSY; if (!pp->offset) - memset((uint8_t *)audio_codec_wov_lang_buf_addr, - 0, LANG_BUF_LEN); + memset((uint8_t *)audio_codec_wov_lang_buf_addr, 0, + LANG_BUF_LEN); - memcpy((uint8_t *)audio_codec_wov_lang_buf_addr + pp->offset, - pp->buf, pp->len); + memcpy((uint8_t *)audio_codec_wov_lang_buf_addr + pp->offset, pp->buf, + pp->len); if (pp->offset + pp->len == pp->total_len) { if (check_lang_buf((uint8_t *)audio_codec_wov_lang_buf_addr, @@ -176,7 +176,7 @@ static enum ec_status wov_enable(struct host_cmd_handler_args *args) if (!speech_lib_loaded) { if (!GoogleHotwordDspInit( - (void *)audio_codec_wov_lang_buf_addr)) + (void *)audio_codec_wov_lang_buf_addr)) return EC_RES_ERROR; speech_lib_loaded = 1; } else { @@ -359,7 +359,6 @@ void audio_codec_wov_task(void *arg) continue; } - /* Clear the buffer if full. */ if (is_buf_full()) { audio_buf_wp = audio_buf_rp; @@ -415,7 +414,7 @@ void audio_codec_wov_task(void *arg) * case, sample is S16_LE. Thus, n / 2. */ if (!hotword_detected && - GoogleHotwordDspProcess(p, n / 2, &r)) { + GoogleHotwordDspProcess(p, n / 2, &r)) { CPRINTS("hotword detected"); mutex_lock(&lock); diff --git a/common/backlight_lid.c b/common/backlight_lid.c index 3b857df592..f8fd8d637f 100644 --- a/common/backlight_lid.c +++ b/common/backlight_lid.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,7 +11,6 @@ #include "host_command.h" #include "lid_switch.h" - /** * Activate/Deactivate the backlight GPIO pin considering active high or low. */ @@ -32,7 +31,7 @@ static void update_backlight(void) #ifdef CONFIG_BACKLIGHT_REQ_GPIO /* Enable the backlight if lid is open AND requested by AP */ enable_backlight(lid_is_open() && - gpio_get_level(CONFIG_BACKLIGHT_REQ_GPIO)); + gpio_get_level(CONFIG_BACKLIGHT_REQ_GPIO)); #else /* * Enable backlight if lid is open; this is AND'd with the request from @@ -79,7 +78,4 @@ switch_command_enable_backlight(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_SWITCH_ENABLE_BKLIGHT, - switch_command_enable_backlight, - EC_VER_MASK(0)); - - + switch_command_enable_backlight, EC_VER_MASK(0)); diff --git a/common/base32.c b/common/base32.c index 8a33d7685c..e5c30c4d6f 100644 --- a/common/base32.c +++ b/common/base32.c @@ -1,23 +1,21 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Base-32 encoding/decoding */ -#include "common.h" #include "base32.h" +#include "common.h" #include "util.h" -static const unsigned char crc5_table1[] = { - 0x00, 0x0E, 0x1C, 0x12, 0x11, 0x1F, 0x0D, 0x03, - 0x0B, 0x05, 0x17, 0x19, 0x1A, 0x14, 0x06, 0x08 -}; +static const unsigned char crc5_table1[] = { 0x00, 0x0E, 0x1C, 0x12, 0x11, 0x1F, + 0x0D, 0x03, 0x0B, 0x05, 0x17, 0x19, + 0x1A, 0x14, 0x06, 0x08 }; -static const unsigned char crc5_table0[] = { - 0x00, 0x16, 0x05, 0x13, 0x0A, 0x1C, 0x0F, 0x19, - 0x14, 0x02, 0x11, 0x07, 0x1E, 0x08, 0x1B, 0x0D -}; +static const unsigned char crc5_table0[] = { 0x00, 0x16, 0x05, 0x13, 0x0A, 0x1C, + 0x0F, 0x19, 0x14, 0x02, 0x11, 0x07, + 0x1E, 0x08, 0x1B, 0x0D }; uint8_t crc5_sym(uint8_t sym, uint8_t previous_crc) { @@ -46,9 +44,8 @@ static int decode_sym(int sym) return -1; } -int base32_encode(char *dest, int destlen_chars, - const void *srcbits, int srclen_bits, - int add_crc_every) +int base32_encode(char *dest, int destlen_chars, const void *srcbits, + int srclen_bits, int add_crc_every) { const uint8_t *src = srcbits; int destlen_needed; @@ -59,14 +56,14 @@ int base32_encode(char *dest, int destlen_chars, *dest = 0; /* Make sure destination is big enough */ - destlen_needed = (srclen_bits + 4) / 5; /* Symbols before adding CRC */ + destlen_needed = (srclen_bits + 4) / 5; /* Symbols before adding CRC */ if (add_crc_every) { /* Must be an exact number of groups to add CRC */ if (destlen_needed % add_crc_every) return EC_ERROR_INVAL; destlen_needed += destlen_needed / add_crc_every; } - destlen_needed++; /* For terminating null */ + destlen_needed++; /* For terminating null */ if (destlen_chars < destlen_needed) return EC_ERROR_INVAL; @@ -119,12 +116,12 @@ int base32_decode(uint8_t *dest, int destlen_bits, const char *src, for (; *src; src++) { int sym, sbits, dbits, b; - if (isspace(*src) || *src == '-') + if (isspace((unsigned char)*src) || *src == '-') continue; sym = decode_sym(*src); if (sym < 0) - return -1; /* Bad input symbol */ + return -1; /* Bad input symbol */ /* Check CRC if needed */ if (crc_after_every) { @@ -155,7 +152,7 @@ int base32_decode(uint8_t *dest, int destlen_bits, const char *src, dbits = 8 - (out_bits & 7); b = MIN(dbits, sbits); if (dbits == 8) - dest[out_bits / 8] = 0; /* Starting a new byte */ + dest[out_bits / 8] = 0; /* Starting a new byte */ dest[out_bits / 8] |= (sym << (dbits - b)) >> (sbits - b); out_bits += b; sbits -= b; diff --git a/common/base_state.c b/common/base_state.c index 053b6d4b23..7bbd14eb00 100644 --- a/common/base_state.c +++ b/common/base_state.c @@ -1,14 +1,14 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "base_state.h" #include "console.h" -#include "host_command.h" #include "hooks.h" +#include "host_command.h" -#define CPRINTS(format, args...) cprints(CC_MOTION_LID, format, ## args) +#define CPRINTS(format, args...) cprints(CC_MOTION_LID, format, ##args) #ifdef CONFIG_BASE_ATTACHED_SWITCH /* 1: base attached, 0: otherwise */ @@ -33,22 +33,35 @@ void base_set_state(int state) } #endif -static int command_setbasestate(int argc, char **argv) +static int command_setbasestate(int argc, const char **argv) { if (argc != 2) return EC_ERROR_PARAM_COUNT; if (argv[1][0] == 'a') - base_force_state(1); + base_force_state(EC_SET_BASE_STATE_ATTACH); else if (argv[1][0] == 'd') - base_force_state(0); + base_force_state(EC_SET_BASE_STATE_DETACH); else if (argv[1][0] == 'r') - base_force_state(2); + base_force_state(EC_SET_BASE_STATE_RESET); else return EC_ERROR_PARAM1; return EC_SUCCESS; - } -DECLARE_CONSOLE_COMMAND(basestate, command_setbasestate, - "[attach | detach | reset]", +DECLARE_CONSOLE_COMMAND( + basestate, command_setbasestate, "[attach | detach | reset]", "Manually force base state to attached, detached or reset."); + +static enum ec_status hostcmd_setbasestate(struct host_cmd_handler_args *args) +{ + const struct ec_params_set_base_state *params = args->params; + + if (params->cmd > EC_SET_BASE_STATE_RESET) + return EC_RES_INVALID_PARAM; + + base_force_state(params->cmd); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_SET_BASE_STATE, hostcmd_setbasestate, + EC_VER_MASK(0)); diff --git a/common/battery.c b/common/battery.c index 9e03bb83a2..cd25a52b01 100644 --- a/common/battery.c +++ b/common/battery.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,36 +6,30 @@ */ #include "battery.h" +#include "battery_fuel_gauge.h" +#include "charge_manager.h" #include "charge_state.h" #include "common.h" #include "console.h" -#include "ec_ec_comm_master.h" +#include "ec_ec_comm_client.h" #include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" +#include "math_util.h" #include "timer.h" +#include "usb_pd.h" #include "util.h" #include "watchdog.h" -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) #define CUTOFFPRINTS(info) CPRINTS("%s %s", "Battery cut off", info) /* See config.h for details */ -const static int batt_full_factor = CONFIG_BATT_FULL_FACTOR; const static int batt_host_full_factor = CONFIG_BATT_HOST_FULL_FACTOR; const static int batt_host_shutdown_pct = CONFIG_BATT_HOST_SHUTDOWN_PERCENTAGE; -#ifdef CONFIG_BATTERY_V2 -/* - * Store battery information in these 2 structures. Main (lid) battery is always - * at index 0, and secondary (base) battery at index 1. - */ -struct ec_response_battery_static_info battery_static[CONFIG_BATTERY_COUNT]; -struct ec_response_battery_dynamic_info battery_dynamic[CONFIG_BATTERY_COUNT]; -#endif - #ifdef CONFIG_BATTERY_CUT_OFF #ifndef CONFIG_BATTERY_CUTOFF_DELAY_US @@ -72,7 +66,7 @@ static const char *get_error_text(int rv) static void print_item_name(const char *name) { - ccprintf(" %-11s", name); + ccprintf(" %-14s", name); } static int check_print_error(int rv) @@ -84,9 +78,14 @@ static int check_print_error(int rv) static void print_battery_status(void) { - static const char * const st[] = {"EMPTY", "FULL", "DCHG", "INIT",}; - static const char * const al[] = {"RT", "RC", "--", "TD", - "OT", "--", "TC", "OC"}; + static const char *const st[] = { + "EMPTY", + "FULL", + "DCHG", + "INIT", + }; + static const char *const al[] = { "RT", "RC", "--", "TD", + "OT", "--", "TC", "OC" }; int value, i; @@ -99,12 +98,12 @@ static void print_battery_status(void) /* bits 4-7 are status */ for (i = 0; i < 4; i++) - if (value & (1 << (i+4))) + if (value & (1 << (i + 4))) ccprintf(" %s", st[i]); /* bits 15-8 are alarms */ for (i = 0; i < 8; i++) - if (value & (1 << (i+8))) + if (value & (1 << (i + 8))) ccprintf(" %s", al[i]); ccprintf("\n"); @@ -145,10 +144,8 @@ static void print_battery_params(void) ccprintf("%08x\n", batt->flags); print_item_name("Temp:"); - ccprintf("0x%04x = %.1d K (%.1d C)\n", - batt->temperature, - batt->temperature, - batt->temperature - 2731); + ccprintf("0x%04x = %.1d K (%.1d C)\n", batt->temperature, + batt->temperature, batt->temperature - 2731); print_item_name("V:"); ccprintf("0x%04x = %d mV\n", batt->voltage, batt->voltage); @@ -174,7 +171,15 @@ static void print_battery_params(void) batt->flags & BATT_FLAG_WANT_CHARGE ? "" : "Not "); print_item_name("Charge:"); - ccprintf("%d %%\n", batt->state_of_charge); + ccprintf("%d %%\n", batt->state_of_charge); + + if (IS_ENABLED(CONFIG_CHARGER)) { + int value; + + print_item_name(" Display:"); + value = charge_get_display_charge(); + ccprintf("%d.%d %%\n", value / 10, value % 10); + } } static void print_battery_info(void) @@ -204,26 +209,23 @@ static void print_battery_info(void) print_item_name("Cap-full:"); if (check_print_error(battery_full_charge_capacity(&value))) - ccprintf("%d mAh (%d mAh with %d %% compensation)\n", - value, value*batt_full_factor/100, batt_full_factor); - -#ifdef CONFIG_CHARGER - print_item_name("Display:"); - value = charge_get_display_charge(); - ccprintf("%d.%d %%\n", value / 10, value % 10); -#endif + ccprintf("%d mAh\n", value); print_item_name(" Design:"); if (check_print_error(battery_design_capacity(&value))) ccprintf("%d mAh\n", value); + print_item_name("Charge Cycle:"); + if (check_print_error(battery_cycle_count(&value))) + ccprintf("%d\n", value); + print_item_name("Time-full:"); if (check_print_error(battery_time_to_full(&value))) { if (value == 65535) { - hour = 0; + hour = 0; minute = 0; } else { - hour = value / 60; + hour = value / 60; minute = value % 60; } ccprintf("%dh:%d\n", hour, minute); @@ -232,14 +234,29 @@ static void print_battery_info(void) print_item_name(" Empty:"); if (check_print_error(battery_time_to_empty(&value))) { if (value == 65535) { - hour = 0; + hour = 0; minute = 0; } else { - hour = value / 60; + hour = value / 60; minute = value % 60; } ccprintf("%dh:%d\n", hour, minute); } + + print_item_name("Full Factor:"); + ccprintf("0.%d\n", batt_host_full_factor); + + print_item_name("Shutdown SoC:"); + ccprintf("%d %%\n", batt_host_shutdown_pct); + +#ifdef CONFIG_BATTERY_FUEL_GAUGE + value = battery_is_charge_fet_disabled(); + /* reverse the flag if no error */ + if (value != -1) + value = !value; + print_item_name("C-FET:"); + ccprintf("%d\n", value); +#endif } void print_battery_debug(void) @@ -250,7 +267,7 @@ void print_battery_debug(void) print_battery_info(); } -static int command_battery(int argc, char **argv) +static int command_battery(int argc, const char **argv) { int repeat = 1; int loop; @@ -289,20 +306,33 @@ static int command_battery(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(battery, command_battery, - " ", +DECLARE_CONSOLE_COMMAND(battery, command_battery, " ", "Print battery info"); #ifdef CONFIG_BATTERY_CUT_OFF + +#ifdef CONFIG_CUSTOMIZED_DESIGN +void set_battery_in_cut_off(void) +{ + battery_cutoff_state = BATTERY_CUTOFF_STATE_CUT_OFF; +} +#endif + int battery_is_cut_off(void) { return (battery_cutoff_state == BATTERY_CUTOFF_STATE_CUT_OFF); } +int battery_cutoff_in_progress(void) +{ + return (battery_cutoff_state == BATTERY_CUTOFF_STATE_IN_PROGRESS); +} + static void pending_cutoff_deferred(void) { int rv; + battery_cutoff_state = BATTERY_CUTOFF_STATE_IN_PROGRESS; rv = board_cut_off_battery(); if (rv == EC_RES_SUCCESS) { @@ -338,6 +368,7 @@ static enum ec_status battery_command_cutoff(struct host_cmd_handler_args *args) } } + battery_cutoff_state = BATTERY_CUTOFF_STATE_IN_PROGRESS; rv = board_cut_off_battery(); if (rv == EC_RES_SUCCESS) { CUTOFFPRINTS("is successful."); @@ -349,7 +380,7 @@ static enum ec_status battery_command_cutoff(struct host_cmd_handler_args *args) return rv; } DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_cutoff, - EC_VER_MASK(0) | EC_VER_MASK(1)); + EC_VER_MASK(0) | EC_VER_MASK(1)); static void check_pending_cutoff(void) { @@ -362,7 +393,7 @@ static void check_pending_cutoff(void) } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, check_pending_cutoff, HOOK_PRIO_LAST); -static int command_cutoff(int argc, char **argv) +static int command_cutoff(int argc, const char **argv) { int rv; @@ -375,6 +406,7 @@ static int command_cutoff(int argc, char **argv) } } + battery_cutoff_state = BATTERY_CUTOFF_STATE_IN_PROGRESS; rv = board_cut_off_battery(); if (rv == EC_RES_SUCCESS) { ccprints("Battery cut off"); @@ -384,18 +416,49 @@ static int command_cutoff(int argc, char **argv) return EC_ERROR_UNKNOWN; } -DECLARE_CONSOLE_COMMAND(cutoff, command_cutoff, - "[at-shutdown]", - "Cut off the battery output"); +DECLARE_CONSOLE_COMMAND(cutoff, command_cutoff, "[at-shutdown]", + "Cut off the battery output"); #else int battery_is_cut_off(void) { - return 0; /* Always return NOT cut off */ + return 0; /* Always return NOT cut off */ } -#endif /* CONFIG_BATTERY_CUT_OFF */ +#endif /* CONFIG_BATTERY_CUT_OFF */ #ifdef CONFIG_BATTERY_VENDOR_PARAM -static int console_command_battery_vendor_param(int argc, char **argv) +__overridable int battery_get_vendor_param(uint32_t param, uint32_t *value) +{ + const struct battery_info *bi = battery_get_info(); + struct battery_static_info *bs = &battery_static[BATT_IDX_MAIN]; + uint8_t *data = bs->vendor_param; + int rv; + + if (param < bi->vendor_param_start) + return EC_ERROR_ACCESS_DENIED; + + /* Skip read if cache is valid. */ + if (!data[0]) { + rv = sb_read_string(bi->vendor_param_start, data, + sizeof(bs->vendor_param)); + if (rv) { + data[0] = 0; + return rv; + } + } + + if (param > bi->vendor_param_start + strlen(data)) + return EC_ERROR_INVAL; + + *value = data[param - bi->vendor_param_start]; + return EC_SUCCESS; +} + +__overridable int battery_set_vendor_param(uint32_t param, uint32_t value) +{ + return EC_ERROR_UNIMPLEMENTED; +} + +static int console_command_battery_vendor_param(int argc, const char **argv) { uint32_t param; uint32_t value; @@ -456,177 +519,201 @@ host_command_battery_vendor_param(struct host_cmd_handler_args *args) return rv; } DECLARE_HOST_COMMAND(EC_CMD_BATTERY_VENDOR_PARAM, - host_command_battery_vendor_param, - EC_VER_MASK(0)); + host_command_battery_vendor_param, EC_VER_MASK(0)); #endif /* CONFIG_BATTERY_VENDOR_PARAM */ -#ifdef CONFIG_BATTERY_V2 -#ifdef CONFIG_HOSTCMD_BATTERY_V2 -static void battery_update(enum battery_index i); -static enum ec_status -host_command_battery_get_static(struct host_cmd_handler_args *args) +void battery_compensate_params(struct batt_params *batt) { - const struct ec_params_battery_static_info *p = args->params; - struct ec_response_battery_static_info *r = args->response; + int numer, denom; + int *remain = &(batt->remaining_capacity); + int full = batt->full_capacity; - if (p->index < 0 || p->index >= CONFIG_BATTERY_COUNT) - return EC_RES_INVALID_PARAM; - battery_update(p->index); - args->response_size = sizeof(*r); - memcpy(r, &battery_static[p->index], sizeof(*r)); + if ((batt->flags & BATT_FLAG_BAD_FULL_CAPACITY) || + (batt->flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) + return; - return EC_RES_SUCCESS; + if (*remain <= 0 || full <= 0) + return; + + /* Some batteries don't update full capacity as often. */ + if (*remain > full) + *remain = full; + + /* + * EC calculates the display SoC like how Powerd used to do. Powerd + * reads the display SoC from the EC. This design allows the system to + * behave consistently on a single SoC value across all power states. + * + * Display SoC is computed as follows: + * + * actual_soc = 100 * remain / full + * + * actual_soc - shutdown_pct + * display_soc = --------------------------- x 1000 + * full_factor - shutdown_pct + * + * (100 * remain / full) - shutdown_pct + * = ------------------------------------ x 1000 + * full_factor - shutdown_pct + * + * 100 x remain - full x shutdown_pct + * = ----------------------------------- x 1000 + * full x (full_factor - shutdown_pct) + */ + numer = 1000 * ((100 * *remain) - (full * batt_host_shutdown_pct)); + denom = full * (batt_host_full_factor - batt_host_shutdown_pct); + /* Rounding (instead of truncating) */ + batt->display_charge = (numer + denom / 2) / denom; + if (batt->display_charge < 0) + batt->display_charge = 0; + if (batt->display_charge > 1000) + batt->display_charge = 1000; } -DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_STATIC, - host_command_battery_get_static, - EC_VER_MASK(0)); -static enum ec_status -host_command_battery_get_dynamic(struct host_cmd_handler_args *args) +#ifdef CONFIG_CHARGER +static enum ec_status battery_display_soc(struct host_cmd_handler_args *args) { - const struct ec_params_battery_dynamic_info *p = args->params; - struct ec_response_battery_dynamic_info *r = args->response; - - if (p->index < 0 || p->index >= CONFIG_BATTERY_COUNT) - return EC_RES_INVALID_PARAM; + struct ec_response_display_soc *r = args->response; + r->display_soc = charge_get_display_charge(); + r->full_factor = batt_host_full_factor * 10; + r->shutdown_soc = batt_host_shutdown_pct * 10; args->response_size = sizeof(*r); - memcpy(r, &battery_dynamic[p->index], sizeof(*r)); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_DYNAMIC, - host_command_battery_get_dynamic, - EC_VER_MASK(0)); -#endif /* CONFIG_HOSTCMD_BATTERY_V2 */ +DECLARE_HOST_COMMAND(EC_CMD_DISPLAY_SOC, battery_display_soc, EC_VER_MASK(0)); +#endif -#ifdef HAS_TASK_HOSTCMD -static void battery_update(enum battery_index i) +__overridable void board_battery_compensate_params(struct batt_params *batt) { - char *batt_str; - int *memmap_dcap = (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP); - int *memmap_dvlt = (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT); - int *memmap_ccnt = (int *)host_get_memmap(EC_MEMMAP_BATT_CCNT); - int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT); - int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE); - int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP); - int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC); - uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); - - /* Smart battery serial number is 16 bits */ - batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL); - memcpy(batt_str, battery_static[i].serial, EC_MEMMAP_TEXT_MAX); - - /* Design Capacity of Full */ - *memmap_dcap = battery_static[i].design_capacity; - - /* Design Voltage */ - *memmap_dvlt = battery_static[i].design_voltage; - - /* Cycle Count */ - *memmap_ccnt = battery_static[i].cycle_count; - - /* Battery Manufacturer string */ - batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR); - memcpy(batt_str, battery_static[i].manufacturer, EC_MEMMAP_TEXT_MAX); +} - /* Battery Model string */ - batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL); - memcpy(batt_str, battery_static[i].model, EC_MEMMAP_TEXT_MAX); +__attribute__((weak)) int get_battery_manufacturer_name(char *dest, int size) +{ + strzcpy(dest, "", size); + return EC_SUCCESS; +} - /* Battery Type string */ - batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE); - memcpy(batt_str, battery_static[i].type, EC_MEMMAP_TEXT_MAX); +__overridable int battery_get_avg_voltage(void) +{ + return -EC_ERROR_UNIMPLEMENTED; +} - *memmap_volt = battery_dynamic[i].actual_voltage; - *memmap_rate = battery_dynamic[i].actual_current; - *memmap_cap = battery_dynamic[i].remaining_capacity; - *memmap_lfcc = battery_dynamic[i].full_capacity; - *memmap_flags = battery_dynamic[i].flags; +__overridable int battery_get_avg_current(void) +{ + return -EC_ERROR_UNIMPLEMENTED; } -void battery_memmap_refresh(enum battery_index index) +int battery_manufacturer_name(char *dest, int size) { - if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index) - battery_update(index); + return get_battery_manufacturer_name(dest, size); } -void battery_memmap_set_index(enum battery_index index) +__overridable enum battery_disconnect_state battery_get_disconnect_state(void) { - if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index) - return; + return BATTERY_NOT_DISCONNECTED; +} - *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID; - if (index < 0 || index >= CONFIG_BATTERY_COUNT) - return; +#ifdef CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV - battery_update(index); - *host_get_memmap(EC_MEMMAP_BATT_INDEX) = index; -} +#if CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV < 5000 || \ + CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV >= PD_MAX_VOLTAGE_MV +#error "Voltage limit must be between 5000 and PD_MAX_VOLTAGE_MV" +#endif + +#if !((defined(CONFIG_USB_PD_TCPMV1) && defined(CONFIG_USB_PD_DUAL_ROLE)) || \ + (defined(CONFIG_USB_PD_TCPMV2) && defined(CONFIG_USB_PE_SM))) +#error "Voltage reducing requires TCPM with Policy Engine" +#endif -static void battery_init(void) +/* + * Returns true if input voltage should be reduced (chipset is in S5/G3) and + * battery is full, otherwise returns false + */ +static bool board_wants_reduced_input_voltage(void) { - *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID; - *host_get_memmap(EC_MEMMAP_BATT_COUNT) = CONFIG_BATTERY_COUNT; - *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 2; + struct batt_params batt; + + /* Chipset not in S5/G3, so we don't want to reduce voltage */ + if (!chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) + return false; + + battery_get_params(&batt); - battery_memmap_set_index(BATT_IDX_MAIN); + /* Battery needs charge, so we don't want to reduce voltage */ + if (batt.flags & BATT_FLAG_WANT_CHARGE) + return false; + + return true; } -DECLARE_HOOK(HOOK_INIT, battery_init, HOOK_PRIO_DEFAULT); -#endif /* HAS_TASK_HOSTCMD */ -#endif /* CONFIG_BATTERY_V2 */ -void battery_compensate_params(struct batt_params *batt) +static void reduce_input_voltage_when_full(void) { - int numer, denom; - int *remain = &(batt->remaining_capacity); - int *full = &(batt->full_capacity); + static int saved_input_voltage = -1; + int max_pd_voltage_mv = pd_get_max_voltage(); + int port; - if ((batt->flags & BATT_FLAG_BAD_FULL_CAPACITY) || - (batt->flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) - return; - - if (*remain <= 0 || *full <= 0) + port = charge_manager_get_active_charge_port(); + if (port < 0 || port >= board_get_usb_pd_port_count()) return; - /* full_factor is effectively disabled in powerd. */ - *full = *full * batt_full_factor / 100; - if (*remain > *full) - *remain = *full; + if (board_wants_reduced_input_voltage()) { + /* + * Board wants voltage to be reduced. Apply limit if current + * voltage is different. Save current voltage, it will be + * restored when board wants to stop reducing input voltage. + */ + if (max_pd_voltage_mv != + CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV) { + saved_input_voltage = max_pd_voltage_mv; + max_pd_voltage_mv = + CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV; + } + } else if (saved_input_voltage != -1) { + /* + * Board doesn't want to reduce input voltage. If current + * voltage is reduced we will restore previously saved voltage. + * If current voltage is different we will respect newer value. + */ + if (max_pd_voltage_mv == + CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV) + max_pd_voltage_mv = saved_input_voltage; - /* - * Powerd uses the following equation to calculate display percentage: - * charge = 100 * remain / full - * display = 100 * (charge - shutdown_pct) / - * (full_factor - shutdown_pct) - * = 100 * ((100 * remain / full) - shutdown_pct) / - * (full_factor - shutdown_pct) - * = 100 * ((100 * remain) - (full * shutdown_pct)) / - * (full * (full_factor - shutdown_pct)) - * - * The unit of the following batt->display_charge is 0.1%. - */ - numer = 1000 * ((100 * *remain) - (*full * batt_host_shutdown_pct)); - denom = *full * (batt_host_full_factor - batt_host_shutdown_pct); - /* Rounding (instead of truncating) */ - batt->display_charge = (numer + denom / 2) / denom; - if (batt->display_charge < 0) - batt->display_charge = 0; - if (batt->display_charge > 1000) - batt->display_charge = 1000; -} + saved_input_voltage = -1; + } -__overridable void board_battery_compensate_params(struct batt_params *batt) -{ + if (pd_get_max_voltage() != max_pd_voltage_mv) + pd_set_external_voltage_limit(port, max_pd_voltage_mv); } +DECLARE_HOOK(HOOK_AC_CHANGE, reduce_input_voltage_when_full, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, reduce_input_voltage_when_full, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, reduce_input_voltage_when_full, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, reduce_input_voltage_when_full, + HOOK_PRIO_DEFAULT); +#endif -__attribute__((weak)) int get_battery_manufacturer_name(char *dest, int size) +void battery_validate_params(struct batt_params *batt) { - strzcpy(dest, "", size); - return EC_SUCCESS; -} + /* + * TODO(crosbug.com/p/27527). Sometimes the battery thinks its + * temperature is 6280C, which seems a bit high. Let's ignore + * anything above the boiling point of tungsten until this bug + * is fixed. If the battery is really that warm, we probably + * have more urgent problems. + */ + if (batt->temperature > CELSIUS_TO_DECI_KELVIN(5660)) { + CPRINTS("ignoring ridiculous batt.temp of %dC", + DECI_KELVIN_TO_CELSIUS(batt->temperature)); + batt->flags |= BATT_FLAG_BAD_TEMPERATURE; + } -int battery_manufacturer_name(char *dest, int size) -{ - return get_battery_manufacturer_name(dest, size); + /* If the battery thinks it's above 100%, don't believe it */ + if (batt->state_of_charge > 100) { + CPRINTS("ignoring ridiculous batt.soc of %d%%", + batt->state_of_charge); + batt->flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; + } } diff --git a/common/battery_config.c b/common/battery_config.c new file mode 100644 index 0000000000..3ff05b2e82 --- /dev/null +++ b/common/battery_config.c @@ -0,0 +1,302 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Module for reading battery config + * + * Default battery config (i.e. default_battery_conf) will be updated as a value + * is read from a source storage (e.g. CBI). If a read fails, the failed field + * will be ignored and search will continue. This allows a source storage to + * store only the differences between the default and the target battery config, + * which saves us the boot time and the storage space. + * + * If data in a storage is corrupted, this may result in mix of two pieces of + * battery config. Partially updating the config (or using as much as + * discovered) is most likely better (and safer) than entirely falling back to + * the default battery config especially when only one field is missing or + * corrupted. + */ + +#include "battery_fuel_gauge.h" +#include "console.h" +#include "cros_board_info.h" +#include "hooks.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, "BCFG " format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, "BCFG " format, ##args) + +static char manuf_name[32]; +static char device_name[32]; + +test_export_static int batt_conf_read(enum cbi_data_tag tag, uint8_t *data, + uint8_t size) +{ + int rv; + + rv = cbi_get_board_info(tag, data, &size); + if (rv == EC_ERROR_UNKNOWN) + /* Tag not found. This is ok. Fall back to default. */ + return EC_ERROR_UNKNOWN; + + if (rv == EC_ERROR_INVAL) { + /* Data in CBI is larger than expected. */ + CPRINTS("batt data tag=%d is larger (%d)", tag, size); + return EC_ERROR_INVAL; + } + + /* It's ok size of the cbi data is smaller than expected, */ + return EC_SUCCESS; +} + +test_export_static int batt_conf_read_ship_mode(struct board_batt_params *info) +{ + struct ship_mode_info *ship = &info->fuel_gauge.ship_mode; + uint8_t d8; + + batt_conf_read(CBI_TAG_BATT_SHIP_MODE_REG_ADDR, &ship->reg_addr, + sizeof(ship->reg_addr)); + + batt_conf_read(CBI_TAG_BATT_SHIP_MODE_REG_DATA, + (uint8_t *)&ship->reg_data, sizeof(ship->reg_data)); + + if (batt_conf_read(CBI_TAG_BATT_SHIP_MODE_FLAGS, &d8, sizeof(d8)) == + EC_SUCCESS) + ship->wb_support = d8 & BIT(0) ? 1 : 0; + + return EC_SUCCESS; +} + +test_export_static int batt_conf_read_sleep_mode(struct board_batt_params *info) +{ + struct sleep_mode_info *sleep = &info->fuel_gauge.sleep_mode; + uint8_t d8; + + batt_conf_read(CBI_TAG_BATT_SLEEP_MODE_REG_ADDR, &sleep->reg_addr, + sizeof(sleep->reg_addr)); + + batt_conf_read(CBI_TAG_BATT_SLEEP_MODE_REG_DATA, + (uint8_t *)&sleep->reg_data, sizeof(sleep->reg_data)); + + if (batt_conf_read(CBI_TAG_BATT_SLEEP_MODE_FLAGS, &d8, sizeof(d8)) == + EC_SUCCESS) + sleep->sleep_supported = d8 & BIT(0) ? 1 : 0; + + return EC_SUCCESS; +} + +test_export_static int batt_conf_read_fet_info(struct board_batt_params *info) +{ + struct fet_info *fet = &info->fuel_gauge.fet; + uint8_t d8; + + batt_conf_read(CBI_TAG_BATT_FET_REG_ADDR, &fet->reg_addr, + sizeof(fet->reg_addr)); + batt_conf_read(CBI_TAG_BATT_FET_REG_MASK, (uint8_t *)&fet->reg_mask, + sizeof(fet->reg_mask)); + batt_conf_read(CBI_TAG_BATT_FET_DISCONNECT_VAL, + (uint8_t *)&fet->disconnect_val, + sizeof(fet->disconnect_val)); + batt_conf_read(CBI_TAG_BATT_FET_CFET_MASK, (uint8_t *)&fet->cfet_mask, + sizeof(fet->cfet_mask)); + batt_conf_read(CBI_TAG_BATT_FET_CFET_OFF_VAL, + (uint8_t *)&fet->cfet_off_val, + sizeof(fet->cfet_off_val)); + if (batt_conf_read(CBI_TAG_BATT_FET_FLAGS, &d8, sizeof(d8)) == + EC_SUCCESS) + fet->mfgacc_support = d8 & BIT(0) ? 1 : 0; + + return EC_SUCCESS; +} + +test_export_static int +batt_conf_read_fuel_gauge_info(struct board_batt_params *info) +{ + struct fuel_gauge_info *fg = &info->fuel_gauge; + uint8_t d8; + + if (batt_conf_read(CBI_TAG_FUEL_GAUGE_MANUF_NAME, (uint8_t *)manuf_name, + sizeof(manuf_name)) == EC_SUCCESS) + fg->manuf_name = manuf_name; + + if (batt_conf_read(CBI_TAG_FUEL_GAUGE_DEVICE_NAME, + (uint8_t *)device_name, + sizeof(device_name)) == EC_SUCCESS) + fg->device_name = device_name; + + if (batt_conf_read(CBI_TAG_FUEL_GAUGE_FLAGS, &d8, sizeof(d8)) == + EC_SUCCESS) + fg->override_nil = d8 & BIT(0) ? 1 : 0; + + batt_conf_read_ship_mode(info); + batt_conf_read_sleep_mode(info); + batt_conf_read_fet_info(info); + + return EC_SUCCESS; +} + +test_export_static int +batt_conf_read_battery_info(struct board_batt_params *info) +{ + const struct battery_info *batt = &info->batt_info; + + batt_conf_read(CBI_TAG_BATT_VOLTAGE_MAX, (uint8_t *)&batt->voltage_max, + sizeof(batt->voltage_max)); + batt_conf_read(CBI_TAG_BATT_VOLTAGE_NORMAL, + (uint8_t *)&batt->voltage_normal, + sizeof(batt->voltage_normal)); + batt_conf_read(CBI_TAG_BATT_VOLTAGE_MIN, (uint8_t *)&batt->voltage_min, + sizeof(batt->voltage_min)); + batt_conf_read(CBI_TAG_BATT_PRECHARGE_VOLTAGE, + (uint8_t *)&batt->precharge_voltage, + sizeof(batt->precharge_voltage)); + batt_conf_read(CBI_TAG_BATT_PRECHARGE_CURRENT, + (uint8_t *)&batt->precharge_current, + sizeof(batt->precharge_current)); + batt_conf_read(CBI_TAG_BATT_START_CHARGING_MIN_C, + (uint8_t *)&batt->start_charging_min_c, + sizeof(batt->start_charging_min_c)); + batt_conf_read(CBI_TAG_BATT_START_CHARGING_MAX_C, + (uint8_t *)&batt->start_charging_max_c, + sizeof(batt->start_charging_max_c)); + batt_conf_read(CBI_TAG_BATT_CHARGING_MIN_C, + (uint8_t *)&batt->charging_min_c, + sizeof(batt->charging_min_c)); + batt_conf_read(CBI_TAG_BATT_CHARGING_MAX_C, + (uint8_t *)&batt->charging_max_c, + sizeof(batt->charging_max_c)); + batt_conf_read(CBI_TAG_BATT_DISCHARGING_MIN_C, + (uint8_t *)&batt->discharging_min_c, + sizeof(batt->discharging_min_c)); + batt_conf_read(CBI_TAG_BATT_DISCHARGING_MAX_C, + (uint8_t *)&batt->discharging_max_c, + sizeof(batt->discharging_max_c)); + + return EC_SUCCESS; +} + +__overridable bool board_batt_conf_enabled(void) +{ + return true; +} + +test_export_static void batt_conf_main(void) +{ + CPRINTS("%s", __func__); + if (board_batt_conf_enabled()) { + CPRINTS("Reading CBI"); + batt_conf_read_fuel_gauge_info(&default_battery_conf); + batt_conf_read_battery_info(&default_battery_conf); + } else { + /* Battery config isn't in CBI. */ + CPRINTS("Detect battery"); + init_battery_type(); + } + CPRINTS("%s done", __func__); +} +DECLARE_HOOK(HOOK_INIT, batt_conf_main, HOOK_PRIO_POST_I2C); + +#ifdef CONFIG_CMD_BATTERY_CONFIG +static struct board_batt_params scratch_battery_conf; + +static void batt_conf_dump(const struct board_batt_params *info) +{ + const struct fuel_gauge_info *fg = &info->fuel_gauge; + const struct ship_mode_info *ship = &info->fuel_gauge.ship_mode; + const struct sleep_mode_info *sleep = &info->fuel_gauge.sleep_mode; + const struct fet_info *fet = &info->fuel_gauge.fet; + const struct battery_info *batt = &info->batt_info; + + ccprintf(" .fuel_gauge = {\n"); + + ccprintf("%02x:\t.manuf_name = \"%s\",\n", + CBI_TAG_FUEL_GAUGE_MANUF_NAME, fg->manuf_name); + ccprintf("%02x:\t.device_name= \"%s\",\n", + CBI_TAG_FUEL_GAUGE_DEVICE_NAME, fg->device_name); + ccprintf("%02x:\t.override_nil = %d,\n", CBI_TAG_FUEL_GAUGE_FLAGS, + fg->override_nil & BIT(0)); + + ccprintf(" \t.ship_mode = {\n"); + ccprintf("%02x:\t\t.reg_addr = 0x%02x,\n", + CBI_TAG_BATT_SHIP_MODE_REG_ADDR, ship->reg_addr); + ccprintf("%02x:\t\t.reg_data = { 0x%04x, 0x%04x },\n", + CBI_TAG_BATT_SHIP_MODE_REG_DATA, ship->reg_data[0], + ship->reg_data[1]); + ccprintf("%02x:\t\t.wb_support = %d,\n", CBI_TAG_BATT_SHIP_MODE_FLAGS, + ship->wb_support & BIT(0)); + ccprintf(" \t},\n"); + + ccprintf(" \t.sleep_mode = {\n"); + ccprintf("%02x:\t\t.reg_addr = 0x%02x,\n", + CBI_TAG_BATT_SLEEP_MODE_REG_ADDR, sleep->reg_addr); + ccprintf("%02x:\t\t.reg_data = 0x%04x,\n", + CBI_TAG_BATT_SLEEP_MODE_REG_DATA, sleep->reg_data); + ccprintf("%02x:\t\t.sleep_supported = %d,\n", + CBI_TAG_BATT_SLEEP_MODE_FLAGS, + sleep->sleep_supported & BIT(0)); + ccprintf(" \t},\n"); + + ccprintf(" \t.fet = {\n"); + ccprintf("%02x:\t\t.reg_addr = 0x%02x,\n", CBI_TAG_BATT_FET_REG_ADDR, + fet->reg_addr); + ccprintf("%02x:\t\t.reg_mask = 0x%04x,\n", CBI_TAG_BATT_FET_REG_MASK, + fet->reg_mask); + ccprintf("%02x:\t\t.disconnect_val = 0x%x,\n", + CBI_TAG_BATT_FET_DISCONNECT_VAL, fet->disconnect_val); + ccprintf("%02x:\t\t.cfet_mask = 0x%04x,\n", CBI_TAG_BATT_FET_CFET_MASK, + fet->cfet_mask); + ccprintf("%02x:\t\t.cfet_off_val = 0x%04x,\n", + CBI_TAG_BATT_FET_CFET_OFF_VAL, fet->cfet_off_val); + ccprintf("%02x:\t\t.mfgacc_support = %d,\n", CBI_TAG_BATT_FET_FLAGS, + fet->mfgacc_support & BIT(0)); + ccprintf(" \t},\n"); + + ccprintf(" },\n"); /* end of fuel_gauge */ + + ccprintf(" .batt_info = {\n"); + ccprintf("%02x:\t.voltage_max = %d,\n", CBI_TAG_BATT_VOLTAGE_MAX, + batt->voltage_max); + ccprintf("%02x:\t.voltage_normal = %d,\n", CBI_TAG_BATT_VOLTAGE_NORMAL, + batt->voltage_normal); + ccprintf("%02x:\t.voltage_min = %d,\n", CBI_TAG_BATT_VOLTAGE_MIN, + batt->voltage_min); + ccprintf("%02x:\t.precharge_voltage= %d,\n", + CBI_TAG_BATT_PRECHARGE_VOLTAGE, batt->precharge_voltage); + ccprintf("%02x:\t.precharge_current = %d,\n", + CBI_TAG_BATT_PRECHARGE_CURRENT, batt->precharge_current); + ccprintf("%02x:\t.start_charging_min_c = %d,\n", + CBI_TAG_BATT_START_CHARGING_MIN_C, batt->start_charging_min_c); + ccprintf("%02x:\t.start_charging_max_c = %d,\n", + CBI_TAG_BATT_START_CHARGING_MAX_C, batt->start_charging_max_c); + ccprintf("%02x:\t.charging_min_c = %d,\n", CBI_TAG_BATT_CHARGING_MIN_C, + batt->charging_min_c); + ccprintf("%02x:\t.charging_max_c = %d,\n", CBI_TAG_BATT_CHARGING_MAX_C, + batt->charging_max_c); + ccprintf("%02x:\t.discharging_min_c = %d,\n", + CBI_TAG_BATT_DISCHARGING_MIN_C, batt->discharging_min_c); + ccprintf("%02x:\t.discharging_max_c = %d,\n", + CBI_TAG_BATT_DISCHARGING_MAX_C, batt->discharging_max_c); + ccprintf(" },\n"); /* end of batt_info */ +} + +static int cc_batt_conf(int argc, const char *argv[]) +{ + if (argc == 1) { + batt_conf_dump(&scratch_battery_conf); + } else if (argc == 2 && strcasecmp(argv[1], "read") == 0) { + batt_conf_read_fuel_gauge_info(&scratch_battery_conf); + batt_conf_read_battery_info(&scratch_battery_conf); + } else if (argc == 2 && strcasecmp(argv[1], "reset") == 0) { + memcpy(&scratch_battery_conf, &default_battery_conf, + sizeof(scratch_battery_conf)); + } else { + return EC_ERROR_PARAM_COUNT; + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(bcfg, cc_batt_conf, "[read | reset]", + "\n" + "Dump scratch battery config\n" + "[reset] Load default config to scratch buffer\n" + "[read] Load config from CBI to scratch buffer\n"); +#endif /* CONFIG_CMD_BATTERY_CONFIG */ diff --git a/common/battery_fuel_gauge.c b/common/battery_fuel_gauge.c index 444144dfeb..d19158c62f 100644 --- a/common/battery_fuel_gauge.c +++ b/common/battery_fuel_gauge.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -7,21 +7,106 @@ #include "battery_fuel_gauge.h" #include "battery_smart.h" +#include "builtin/assert.h" #include "console.h" #include "hooks.h" #include "i2c.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) +#ifdef CONFIG_BATTERY_CONFIG_IN_CBI +static const struct board_batt_params *battery_conf = &default_battery_conf; +#endif + +/* + * Authenticate the battery connected. + * + * Compare the manufacturer name read from the fuel gauge to the + * manufacturer names defined in the board_battery_info table. If + * a device name has been specified in the board_battery_info table, + * then both the manufacturer and device name must match. + */ +test_export_static bool authenticate_battery_type(int index, + const char *manuf_name) +{ + char device_name[32]; + + const struct fuel_gauge_info *const fuel_gauge = + &board_battery_info[index].fuel_gauge; + int len = 0; + + /* check for valid index */ + if (index >= BATTERY_TYPE_COUNT) + return false; + + /* manufacturer name mismatch */ + if (strcasecmp(manuf_name, fuel_gauge->manuf_name)) + return false; + + /* device name is specified in table */ + if (fuel_gauge->device_name != NULL) { + /* Get the device name */ + if (battery_device_name(device_name, sizeof(device_name))) + return false; + + len = strlen(fuel_gauge->device_name); + + /* device name mismatch */ + if (strncasecmp(device_name, fuel_gauge->device_name, len)) + return false; + } + + CPRINTS("found batt:%s", fuel_gauge->manuf_name); + return true; +} + +#ifdef CONFIG_BATTERY_TYPE_NO_AUTO_DETECT + +/* Variable to decide the battery type */ +static int fixed_battery_type = BATTERY_TYPE_UNINITIALIZED; + +/* + * Function to get the fixed battery type. + */ +static int battery_get_fixed_battery_type(void) +{ + if (fixed_battery_type == BATTERY_TYPE_UNINITIALIZED) { + CPRINTS("Warning: Battery type is not Initialized! " + "Setting to default battery type.\n"); + fixed_battery_type = DEFAULT_BATTERY_TYPE; + } + + return fixed_battery_type; +} + +/* + * Function to set the battery type, when auto-detection cannot be used. + */ +void battery_set_fixed_battery_type(int type) +{ + if (type < BATTERY_TYPE_COUNT) + fixed_battery_type = type; +} +#endif /* CONFIG_BATTERY_TYPE_NO_AUTO_DETECT */ + +/** + * Allows us to override the battery in order to select the battery which has + * the right configuration for the test. + */ +test_export_static int battery_fuel_gauge_type_override = -1; /* Get type of the battery connected on the board */ static int get_battery_type(void) { - char manuf_name[32], device_name[32]; + char manuf_name[32]; int i; static enum battery_type battery_type = BATTERY_TYPE_COUNT; + if (IS_ENABLED(TEST_BUILD) && battery_fuel_gauge_type_override >= 0) { + return battery_fuel_gauge_type_override; + } + /* * If battery_type is not the default value, then can return here * as there is no need to query the fuel gauge. @@ -33,64 +118,75 @@ static int get_battery_type(void) if (battery_manufacturer_name(manuf_name, sizeof(manuf_name))) return battery_type; - /* - * Compare the manufacturer name read from the fuel gauge to the - * manufacturer names defined in the board_battery_info table. If - * a device name has been specified in the board_battery_info table, - * then both the manufacturer and device name must match. - */ +#if defined(CONFIG_BATTERY_TYPE_NO_AUTO_DETECT) + i = battery_get_fixed_battery_type(); + if (authenticate_battery_type(i, manuf_name)) + battery_type = i; +#else for (i = 0; i < BATTERY_TYPE_COUNT; i++) { - const struct fuel_gauge_info * const fuel_gauge = - &board_battery_info[i].fuel_gauge; - - if (strcasecmp(manuf_name, fuel_gauge->manuf_name)) - continue; + if (authenticate_battery_type(i, manuf_name)) { + battery_type = i; + break; + } + } +#endif - if (fuel_gauge->device_name != NULL) { + return battery_type; +} - if (battery_device_name(device_name, - sizeof(device_name))) - continue; +__overridable int board_get_default_battery_type(void) +{ + return DEFAULT_BATTERY_TYPE; +} - if (strcasecmp(device_name, fuel_gauge->device_name)) - continue; - } +#ifdef CONFIG_BATTERY_CONFIG_IN_CBI +void init_battery_type(void) +{ + int type = get_battery_type(); - CPRINTS("found batt:%s", fuel_gauge->manuf_name); - battery_type = i; - break; + if (type == BATTERY_TYPE_COUNT) { + CPRINTS("battery not found"); + type = board_get_default_battery_type(); } - return battery_type; + battery_conf = &board_battery_info[type]; } -/* - * Initialize the battery type for the board. - * - * The first call to battery_get_info() is when the charger task starts, so - * initialize the battery type as soon as I2C is initialized. - */ -static void init_battery_type(void) +const struct board_batt_params *get_batt_params(void) +{ + return battery_conf; +} + +#else /* !CONFIG_BATTERY_CONFIG_IN_CBI */ + +void init_battery_type(void) { if (get_battery_type() == BATTERY_TYPE_COUNT) CPRINTS("battery not found"); } -DECLARE_HOOK(HOOK_INIT, init_battery_type, HOOK_PRIO_INIT_I2C + 1); -static inline const struct board_batt_params *get_batt_params(void) +const struct board_batt_params *get_batt_params(void) { int type = get_battery_type(); return &board_battery_info[type == BATTERY_TYPE_COUNT ? - DEFAULT_BATTERY_TYPE : type]; + board_get_default_battery_type() : + type]; } +#endif /* CONFIG_BATTERY_CONFIG_IN_CBI */ const struct battery_info *battery_get_info(void) { return &get_batt_params()->batt_info; } -int cut_off_battery_block_write(const struct ship_mode_info *ship_mode) +/** + * Battery cut off command via SMBus write block. + * + * @param ship_mode Battery ship mode information + * @return non-zero if error + */ +static int cut_off_battery_block_write(const struct ship_mode_info *ship_mode) { int rv; @@ -117,7 +213,13 @@ int cut_off_battery_block_write(const struct ship_mode_info *ship_mode) return sb_write_block(ship_mode->reg_addr, cutdata, sizeof(cutdata)); } -int cut_off_battery_sb_write(const struct ship_mode_info *ship_mode) +/** + * Battery cut off command via SMBus write word. + * + * @param ship_mode Battery ship mode information + * @return non-zero if error + */ +static int cut_off_battery_sb_write(const struct ship_mode_info *ship_mode) { int rv; @@ -129,59 +231,74 @@ int cut_off_battery_sb_write(const struct ship_mode_info *ship_mode) return sb_write(ship_mode->reg_addr, ship_mode->reg_data[1]); } -int board_cut_off_battery(void) +__overridable int board_cut_off_battery(void) { + const struct board_batt_params *params = get_batt_params(); int rv; - int type = get_battery_type(); - /* If battery type is unknown can't send ship mode command */ - if (type == BATTERY_TYPE_COUNT) + /* If battery is unknown can't send ship mode command */ + if (!params) return EC_RES_ERROR; - if (board_battery_info[type].fuel_gauge.ship_mode.wb_support) - rv = cut_off_battery_block_write( - &board_battery_info[type].fuel_gauge.ship_mode); + if (params->fuel_gauge.ship_mode.wb_support) + rv = cut_off_battery_block_write(¶ms->fuel_gauge.ship_mode); else - rv = cut_off_battery_sb_write( - &board_battery_info[type].fuel_gauge.ship_mode); + rv = cut_off_battery_sb_write(¶ms->fuel_gauge.ship_mode); return rv ? EC_RES_ERROR : EC_RES_SUCCESS; } +enum ec_error_list battery_sleep_fuel_gauge(void) +{ + const struct board_batt_params *params = get_batt_params(); + const struct sleep_mode_info *sleep_command; + + /* Sleep entry command must be supplied as it will vary by gauge */ + if (!params) + return EC_ERROR_UNKNOWN; + + sleep_command = ¶ms->fuel_gauge.sleep_mode; + + if (!sleep_command->sleep_supported) + return EC_ERROR_UNIMPLEMENTED; + + return sb_write(sleep_command->reg_addr, sleep_command->reg_data); +} + static enum ec_error_list battery_get_fet_status_regval(int *regval) { + const struct board_batt_params *params = get_batt_params(); int rv; uint8_t data[6]; - int type = get_battery_type(); - /* If battery type is not known, can't check CHG/DCHG FETs */ - if (type == BATTERY_TYPE_COUNT) { - /* Still don't know, so return here */ - return EC_ERROR_BUSY; - } + ASSERT(params); /* Read the status of charge/discharge FETs */ - if (board_battery_info[type].fuel_gauge.fet.mfgacc_support == 1) { - rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, - sizeof(data)); + if (params->fuel_gauge.fet.mfgacc_support == 1) { + if (params->fuel_gauge.fet.mfgacc_smb_block == 1) + rv = sb_read_mfgacc_block(PARAM_OPERATION_STATUS, + SB_ALT_MANUFACTURER_ACCESS, + data, sizeof(data)); + else + rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, + SB_ALT_MANUFACTURER_ACCESS, data, + sizeof(data)); /* Get the lowest 16bits of the OperationStatus() data */ *regval = data[2] | data[3] << 8; } else - rv = sb_read(board_battery_info[type].fuel_gauge.fet.reg_addr, - regval); + rv = sb_read(params->fuel_gauge.fet.reg_addr, regval); return rv; } -int battery_is_charge_fet_disabled(void) +test_mockable int battery_is_charge_fet_disabled(void) { + const struct board_batt_params *params = get_batt_params(); int rv; int reg; - int type = get_battery_type(); /* If battery type is not known, can't check CHG/DCHG FETs */ - if (type == BATTERY_TYPE_COUNT) { + if (!params) { /* Still don't know, so return here */ return -1; } @@ -189,15 +306,15 @@ int battery_is_charge_fet_disabled(void) /* * If the CFET mask hasn't been defined, assume that it's not disabled. */ - if (!board_battery_info[type].fuel_gauge.fet.cfet_mask) + if (!params->fuel_gauge.fet.cfet_mask) return 0; rv = battery_get_fet_status_regval(®); if (rv) return -1; - return (reg & board_battery_info[type].fuel_gauge.fet.cfet_mask) == - board_battery_info[type].fuel_gauge.fet.cfet_off_val; + return (reg & params->fuel_gauge.fet.cfet_mask) == + params->fuel_gauge.fet.cfet_off_val; } /* @@ -214,24 +331,23 @@ int battery_is_charge_fet_disabled(void) */ enum battery_disconnect_state battery_get_disconnect_state(void) { + const struct board_batt_params *params = get_batt_params(); int reg; - int type = get_battery_type(); /* If battery type is not known, can't check CHG/DCHG FETs */ - if (type == BATTERY_TYPE_COUNT) { + if (!params) { /* Still don't know, so return here */ - return EC_ERROR_BUSY; + return BATTERY_DISCONNECT_ERROR; } if (battery_get_fet_status_regval(®)) return BATTERY_DISCONNECT_ERROR; - if ((reg & board_battery_info[type].fuel_gauge.fet.reg_mask) == - board_battery_info[type].fuel_gauge.fet.disconnect_val) { + if ((reg & params->fuel_gauge.fet.reg_mask) == + params->fuel_gauge.fet.disconnect_val) { CPRINTS("Batt disconnected: reg 0x%04x mask 0x%04x disc 0x%04x", - reg, - board_battery_info[type].fuel_gauge.fet.reg_mask, - board_battery_info[type].fuel_gauge.fet.disconnect_val); + reg, params->fuel_gauge.fet.reg_mask, + params->fuel_gauge.fet.disconnect_val); return BATTERY_DISCONNECTED; } @@ -241,14 +357,13 @@ enum battery_disconnect_state battery_get_disconnect_state(void) #ifdef CONFIG_BATTERY_MEASURE_IMBALANCE int battery_imbalance_mv(void) { - int type = get_battery_type(); + const struct board_batt_params *params = get_batt_params(); /* * If battery type is unknown, we cannot safely access non-standard * registers. */ - return (type == BATTERY_TYPE_COUNT) ? 0 : - board_battery_info[type].fuel_gauge.imbalance_mv(); + return (!params) ? 0 : params->fuel_gauge.imbalance_mv(); } int battery_default_imbalance_mv(void) diff --git a/common/battery_v1.c b/common/battery_v1.c new file mode 100644 index 0000000000..2c81d6b446 --- /dev/null +++ b/common/battery_v1.c @@ -0,0 +1,175 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery V1 APIs. + */ + +#include "battery.h" +#include "charge_state.h" +#include "common.h" +#include "console.h" +#include "extpower.h" +#include "host_command.h" +#include "math_util.h" +#include "printf.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* Returns zero if every item was updated. */ +int update_static_battery_info(void) +{ + char *batt_str; + int batt_serial; + uint8_t batt_flags = 0; + /* + * The return values have type enum ec_error_list, but EC_SUCCESS is + * zero. We'll just look for any failures so we can try them all again. + */ + int rv; + + /* Smart battery serial number is 16 bits */ + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL); + memset(batt_str, 0, EC_MEMMAP_TEXT_MAX); + rv = battery_serial_number(&batt_serial); + if (!rv) { + if (snprintf(batt_str, EC_MEMMAP_TEXT_MAX, "%04X", + batt_serial) <= 0) + rv |= EC_ERROR_UNKNOWN; + } + + /* Design Capacity of Full */ + rv |= battery_design_capacity( + (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP)); + + /* Design Voltage */ + rv |= battery_design_voltage( + (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT)); + + /* Last Full Charge Capacity (this is only mostly static) */ + rv |= battery_full_charge_capacity( + (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC)); + + /* Cycle Count */ + rv |= battery_cycle_count((int *)host_get_memmap(EC_MEMMAP_BATT_CCNT)); + + /* Battery Manufacturer string */ + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR); + memset(batt_str, 0, EC_MEMMAP_TEXT_MAX); + rv |= battery_manufacturer_name(batt_str, EC_MEMMAP_TEXT_MAX); + + /* Battery Model string */ + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL); + memset(batt_str, 0, EC_MEMMAP_TEXT_MAX); + rv |= battery_device_name(batt_str, EC_MEMMAP_TEXT_MAX); + + /* Battery Type string */ + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE); + rv |= battery_device_chemistry(batt_str, EC_MEMMAP_TEXT_MAX); + + /* Zero the dynamic entries. They'll come next. */ + *(int *)host_get_memmap(EC_MEMMAP_BATT_VOLT) = 0; + *(int *)host_get_memmap(EC_MEMMAP_BATT_RATE) = 0; + *(int *)host_get_memmap(EC_MEMMAP_BATT_CAP) = 0; + *(int *)host_get_memmap(EC_MEMMAP_BATT_LFCC) = 0; + if (extpower_is_present()) + batt_flags |= EC_BATT_FLAG_AC_PRESENT; + *host_get_memmap(EC_MEMMAP_BATT_FLAG) = batt_flags; + + if (rv) + charge_problem(PR_STATIC_UPDATE, rv); + else + /* No errors seen. Battery data is now present */ + *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 1; + + return rv; +} + +void update_dynamic_battery_info(void) +{ + /* The memmap address is constant. We should fix these calls somehow. */ + int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT); + int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE); + int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP); + int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC); + uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); + uint8_t tmp; + int send_batt_status_event = 0; + int send_batt_info_event = 0; + static int batt_present; + struct charge_state_data *curr; + + curr = charge_get_status(); + tmp = 0; + if (curr->ac) + tmp |= EC_BATT_FLAG_AC_PRESENT; + + if (curr->batt.is_present == BP_YES) { + tmp |= EC_BATT_FLAG_BATT_PRESENT; + batt_present = 1; + /* Tell the AP to read battery info if it is newly present. */ + if (!(*memmap_flags & EC_BATT_FLAG_BATT_PRESENT)) + send_batt_info_event++; + } else { + /* + * Require two consecutive updates with BP_NOT_SURE + * before reporting it gone to the host. + */ + if (batt_present) + tmp |= EC_BATT_FLAG_BATT_PRESENT; + else if (*memmap_flags & EC_BATT_FLAG_BATT_PRESENT) + send_batt_info_event++; + batt_present = 0; + } + + if (curr->batt.flags & BATT_FLAG_BAD_ANY) + tmp |= EC_BATT_FLAG_INVALID_DATA; + + if (!(curr->batt.flags & BATT_FLAG_BAD_VOLTAGE)) + *memmap_volt = curr->batt.voltage; + + if (!(curr->batt.flags & BATT_FLAG_BAD_CURRENT)) + *memmap_rate = ABS(curr->batt.current); + + if (!(curr->batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) { + /* + * If we're running off the battery, it must have some charge. + * Don't report zero charge, as that has special meaning + * to Chrome OS powerd. + */ + if (curr->batt.remaining_capacity == 0 && + !curr->batt_is_charging) + *memmap_cap = 1; + else + *memmap_cap = curr->batt.remaining_capacity; + } + + if (!(curr->batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) && + (curr->batt.full_capacity <= (*memmap_lfcc - LFCC_EVENT_THRESH) || + curr->batt.full_capacity >= (*memmap_lfcc + LFCC_EVENT_THRESH))) { + *memmap_lfcc = curr->batt.full_capacity; + /* Poke the AP if the full_capacity changes. */ + send_batt_info_event++; + } + + if (curr->batt.is_present == BP_YES && + battery_is_below_threshold(BATT_THRESHOLD_TYPE_SHUTDOWN, false)) + tmp |= EC_BATT_FLAG_LEVEL_CRITICAL; + + tmp |= curr->batt_is_charging ? EC_BATT_FLAG_CHARGING : + EC_BATT_FLAG_DISCHARGING; + + /* Tell the AP to re-read battery status if charge state changes */ + if (*memmap_flags != tmp) + send_batt_status_event++; + + /* Update flags before sending host events. */ + *memmap_flags = tmp; + + if (send_batt_info_event) + host_set_single_event(EC_HOST_EVENT_BATTERY); + if (send_batt_status_event) + host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS); +} diff --git a/common/battery_v2.c b/common/battery_v2.c new file mode 100644 index 0000000000..e0c1ed2b54 --- /dev/null +++ b/common/battery_v2.c @@ -0,0 +1,519 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery V2 APIs. + */ + +#include "battery.h" +#include "charge_state.h" +#include "common.h" +#include "console.h" +#include "extpower.h" +#include "hooks.h" +#include "host_command.h" +#include "math_util.h" +#include "printf.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) + +/* + * Store battery information in these 2 structures. Main (lid) battery is always + * at index 0, and secondary (base) battery at index 1. + */ +struct battery_static_info battery_static[CONFIG_BATTERY_COUNT]; +struct ec_response_battery_dynamic_info battery_dynamic[CONFIG_BATTERY_COUNT]; + +#ifdef HAS_TASK_HOSTCMD +static void battery_update(enum battery_index i) +{ + char *batt_str; + int *memmap_dcap = (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP); + int *memmap_dvlt = (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT); + int *memmap_ccnt = (int *)host_get_memmap(EC_MEMMAP_BATT_CCNT); + int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT); + int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE); + int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP); + int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC); + uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); + + /* Smart battery serial number is 16 bits */ + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL); + memcpy(batt_str, battery_static[i].serial_ext, EC_MEMMAP_TEXT_MAX); + batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0; + + /* Design Capacity of Full */ + *memmap_dcap = battery_static[i].design_capacity; + + /* Design Voltage */ + *memmap_dvlt = battery_static[i].design_voltage; + + /* Cycle Count */ + *memmap_ccnt = battery_static[i].cycle_count; + + /* Battery Manufacturer string */ + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR); + memcpy(batt_str, battery_static[i].manufacturer_ext, + EC_MEMMAP_TEXT_MAX); + batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0; + + /* Battery Model string */ + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL); + memcpy(batt_str, battery_static[i].model_ext, EC_MEMMAP_TEXT_MAX); + batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0; + + /* Battery Type string */ + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE); + memcpy(batt_str, battery_static[i].type_ext, EC_MEMMAP_TEXT_MAX); + batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0; + + *memmap_volt = battery_dynamic[i].actual_voltage; + /* + * Rate must be absolute, flags will indicate whether + * the battery is charging or discharging. + */ + *memmap_rate = ABS(battery_dynamic[i].actual_current); + *memmap_cap = battery_dynamic[i].remaining_capacity; + *memmap_lfcc = battery_dynamic[i].full_capacity; + *memmap_flags = battery_dynamic[i].flags; +} + +#ifdef CONFIG_HOSTCMD_BATTERY_V2 +static enum ec_status +host_command_battery_get_static(struct host_cmd_handler_args *args) +{ + const struct ec_params_battery_static_info *p = args->params; + const struct battery_static_info *bs; + + if (p->index >= CONFIG_BATTERY_COUNT) + return EC_RES_INVALID_PARAM; + bs = &battery_static[p->index]; + + battery_update(p->index); + if (args->version == 0) { + struct ec_response_battery_static_info *r = args->response; + + r->design_capacity = bs->design_capacity; + r->design_voltage = bs->design_voltage; + r->cycle_count = bs->cycle_count; + + strzcpy(r->manufacturer, bs->manufacturer_ext, + sizeof(r->manufacturer)); + strzcpy(r->model, bs->model_ext, sizeof(r->model)); + strzcpy(r->serial, bs->serial_ext, sizeof(r->serial)); + strzcpy(r->type, bs->type_ext, sizeof(r->type)); + + args->response_size = sizeof(*r); + } else if (args->version == 1) { + struct ec_response_battery_static_info_v1 *r = args->response; + + r->design_capacity = bs->design_capacity; + r->design_voltage = bs->design_voltage; + r->cycle_count = bs->cycle_count; + + strzcpy(r->manufacturer_ext, bs->manufacturer_ext, + sizeof(r->manufacturer_ext)); + strzcpy(r->model_ext, bs->model_ext, sizeof(r->model_ext)); + strzcpy(r->serial_ext, bs->serial_ext, sizeof(r->serial_ext)); + strzcpy(r->type_ext, bs->type_ext, sizeof(r->type_ext)); + + args->response_size = sizeof(*r); + } else if (args->version == 2) { + struct ec_response_battery_static_info_v2 *r = args->response; + + r->design_capacity = bs->design_capacity; + r->design_voltage = bs->design_voltage; + r->cycle_count = bs->cycle_count; + + strzcpy(r->manufacturer, bs->manufacturer_ext, + sizeof(r->manufacturer)); + strzcpy(r->device_name, bs->model_ext, sizeof(r->device_name)); + strzcpy(r->serial, bs->serial_ext, sizeof(r->serial)); + strzcpy(r->chemistry, bs->type_ext, sizeof(r->chemistry)); + + args->response_size = sizeof(*r); + } else { + return EC_RES_INVALID_VERSION; + } + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_STATIC, host_command_battery_get_static, + EC_VER_MASK(0) | EC_VER_MASK(1) | EC_VER_MASK(2)); + +static enum ec_status +host_command_battery_get_dynamic(struct host_cmd_handler_args *args) +{ + const struct ec_params_battery_dynamic_info *p = args->params; + struct ec_response_battery_dynamic_info *r = args->response; + + if (p->index >= CONFIG_BATTERY_COUNT) + return EC_RES_INVALID_PARAM; + + args->response_size = sizeof(*r); + memcpy(r, &battery_dynamic[p->index], sizeof(*r)); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_DYNAMIC, + host_command_battery_get_dynamic, EC_VER_MASK(0)); +#endif /* CONFIG_HOSTCMD_BATTERY_V2 */ + +void battery_memmap_refresh(enum battery_index index) +{ + if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index) + battery_update(index); +} + +void battery_memmap_set_index(enum battery_index index) +{ + if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index) + return; + + *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID; + if (index < 0 || index >= CONFIG_BATTERY_COUNT) + return; + + battery_update(index); + *host_get_memmap(EC_MEMMAP_BATT_INDEX) = index; +} + +static void battery_init(void) +{ + *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID; + *host_get_memmap(EC_MEMMAP_BATT_COUNT) = CONFIG_BATTERY_COUNT; + *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 2; + + battery_memmap_set_index(BATT_IDX_MAIN); +} +DECLARE_HOOK(HOOK_INIT, battery_init, HOOK_PRIO_DEFAULT); +#endif /* HAS_TASK_HOSTCMD */ + +static int is_battery_string_reliable(const char *buf) +{ + /* + * From is_string_printable rule, 0xFF is not printable. + * So, EC should think battery string is unreliable if string + * include 0xFF. + */ + while (*buf) { + if ((*buf) == '\xff') + return 0; + buf++; + } + + return 1; +} + +int update_static_battery_info(void) +{ + int batt_serial; + int val; + /* + * The return values have type enum ec_error_list, but EC_SUCCESS is + * zero. We'll just look for any failures so we can try them all again. + */ + int rv, ret; + + struct battery_static_info *const bs = &battery_static[BATT_IDX_MAIN]; + + /* Clear all static information. */ + memset(bs, 0, sizeof(*bs)); + + /* Smart battery serial number is 16 bits */ + rv = battery_serial_number(&batt_serial); + if (!rv) + if (snprintf(bs->serial_ext, sizeof(bs->serial_ext), "%04X", + batt_serial) <= 0) + rv |= EC_ERROR_UNKNOWN; + + /* Design Capacity of Full */ + ret = battery_design_capacity(&val); + if (!ret) + bs->design_capacity = val; + rv |= ret; + + /* Design Voltage */ + ret = battery_design_voltage(&val); + if (!ret) + bs->design_voltage = val; + rv |= ret; + + /* Cycle Count */ + ret = battery_cycle_count(&val); + if (!ret) + bs->cycle_count = val; + rv |= ret; + + /* Battery Manufacturer string */ + rv |= battery_manufacturer_name(bs->manufacturer_ext, + sizeof(bs->manufacturer_ext)); + + /* Battery Model string */ + rv |= battery_device_name(bs->model_ext, sizeof(bs->model_ext)); + + /* Battery Type string */ + rv |= battery_device_chemistry(bs->type_ext, sizeof(bs->type_ext)); + + /* + * b/181639264: Battery gauge follow SMBus SPEC and SMBus define + * cumulative clock low extend time for both controller (master) and + * peripheral (slave). However, I2C doesn't. + * Regarding this issue, we observe EC sometimes pull I2C CLK low + * a while after EC start running. Actually, we are not sure the + * reason until now. + * If EC pull I2C CLK low too long, and it may cause battery fw timeout + * because battery count cumulative clock extend time over 25ms. + * When it happened, battery will release both its CLK and DATA and + * reset itself. So, EC may get 0xFF when EC keep reading data from + * battery. Battery static information will be unreliable and need to + * be updated. + * This change is improvement that EC should retry if battery string is + * unreliable. + */ + if (!is_battery_string_reliable(bs->serial_ext) || + !is_battery_string_reliable(bs->manufacturer_ext) || + !is_battery_string_reliable(bs->model_ext) || + !is_battery_string_reliable(bs->type_ext)) + rv |= EC_ERROR_UNKNOWN; + + /* Zero the dynamic entries. They'll come next. */ + memset(&battery_dynamic[BATT_IDX_MAIN], 0, + sizeof(battery_dynamic[BATT_IDX_MAIN])); + +#ifdef CONFIG_CUSTOMIZED_DESIGN + if (extpower_is_present()) + battery_dynamic[BATT_IDX_MAIN].flags |= EC_BATT_FLAG_AC_PRESENT; + else + battery_dynamic[BATT_IDX_MAIN].flags &= ~EC_BATT_FLAG_AC_PRESENT; +#endif + + if (rv) + charge_problem(PR_STATIC_UPDATE, rv); + +#ifdef HAS_TASK_HOSTCMD + battery_memmap_refresh(BATT_IDX_MAIN); +#endif + + return rv; +} + +void update_dynamic_battery_info(void) +{ + static int batt_present; + uint8_t tmp; + int send_batt_status_event = 0; + int send_batt_info_event = 0; + struct charge_state_data *curr; + struct ec_response_battery_dynamic_info *const bd = + &battery_dynamic[BATT_IDX_MAIN]; + +#ifdef CONFIG_CUSTOMIZED_DESIGN + struct battery_static_info *const bs = &battery_static[BATT_IDX_MAIN]; + static int batt_os_percentage; + int rsoc_percentage; + int design_percentage; + static int brc_retry; + static int bfc_retry; +#endif + + curr = charge_get_status(); + tmp = 0; + if (curr->ac) + tmp |= EC_BATT_FLAG_AC_PRESENT; + + if (curr->batt.is_present == BP_YES) { + tmp |= EC_BATT_FLAG_BATT_PRESENT; + batt_present = 1; + /* Tell the AP to read battery info if it is newly present. */ + if (!(bd->flags & EC_BATT_FLAG_BATT_PRESENT)) + send_batt_info_event++; + } else { + /* + * Require two consecutive updates with BP_NOT_SURE + * before reporting it gone to the host. + */ + if (batt_present) + tmp |= EC_BATT_FLAG_BATT_PRESENT; + else if (bd->flags & EC_BATT_FLAG_BATT_PRESENT) + send_batt_info_event++; + batt_present = 0; + } + + if (curr->batt.flags & BATT_FLAG_BAD_ANY) + tmp |= EC_BATT_FLAG_INVALID_DATA; + + if (!(curr->batt.flags & BATT_FLAG_BAD_VOLTAGE)) + bd->actual_voltage = curr->batt.voltage; +#ifdef CONFIG_CUSTOMIZED_DESIGN + /* let the OS battery remaining time both empty and full time more smooth */ + if (!(curr->batt.flags & BATT_FLAG_BAD_CURRENT)) + bd->actual_current = battery_get_avg_current(); +#else + if (!(curr->batt.flags & BATT_FLAG_BAD_CURRENT)) + bd->actual_current = curr->batt.current; +#endif + if (!(curr->batt.flags & BATT_FLAG_BAD_DESIRED_VOLTAGE)) + bd->desired_voltage = curr->batt.desired_voltage; + + if (!(curr->batt.flags & BATT_FLAG_BAD_DESIRED_CURRENT)) + bd->desired_current = curr->batt.desired_current; + + if (!(curr->batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY) +#ifdef CONFIG_CUSTOMIZED_DESIGN + && !(curr->batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) +#endif + ) { + /* + * If we're running off the battery, it must have some charge. + * Don't report zero charge, as that has special meaning + * to Chrome OS powerd. + */ + if (curr->batt.remaining_capacity == 0 && + !curr->batt_is_charging) + bd->remaining_capacity = 1; +#ifdef CONFIG_CUSTOMIZED_DESIGN + /* Avoid to show the percentage when battery fully charge */ + else if (curr->ac && (curr->batt.status & STATUS_FULLY_CHARGED)) + bd->remaining_capacity = curr->batt.full_capacity; + else { + + /* + * TASK:866aqnw5t + * add workaround to avoid the battery abnormal response + * if new RC - old RC over than dc 2% EC will not update + * it, but if battery send 3 times maybe is battery + * correct data. + * + * example: NRC(90%) 900 - ORC(96%) 960 need lower DC(1000*2/100) 20 + * percentage jump too much would not update. + */ + if (bd->remaining_capacity == 0) + bd->remaining_capacity = curr->batt.remaining_capacity; + else { + rsoc_percentage = + curr->batt.remaining_capacity - bd->remaining_capacity; + design_percentage = (bs->design_capacity * 2) / 100; + if (ABS(rsoc_percentage) < design_percentage) { + bd->remaining_capacity = curr->batt.remaining_capacity; + } else { + brc_retry++; + if (brc_retry > 2) { + bd->remaining_capacity = + curr->batt.remaining_capacity; + brc_retry = 0; + } + } + } + } +#else + else + bd->remaining_capacity = curr->batt.remaining_capacity; +#endif + } + +#ifdef CONFIG_CUSTOMIZED_DESIGN + + /* + * TASK:866aqnw5t + * add workaround to avoid the battery abnormal response + * if new FC - old FC over than dc 2% EC will not update + * it, but if battery send 3 times maybe is battery + * correct data. + * + * example: NFC(100%) 900 - OFC(100%) 960 need lower DC(1000*2/100) 20 + * FCC jump too much would not update. + */ + if (!(curr->batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) && + ((curr->batt.full_capacity - bd->full_capacity) + < ((bs->design_capacity * 2) / 100))) { + if (curr->batt.full_capacity <= + (bd->full_capacity - LFCC_EVENT_THRESH) || + curr->batt.full_capacity >= + (bd->full_capacity + LFCC_EVENT_THRESH)) { + bd->full_capacity = curr->batt.full_capacity; + /* Poke the AP if the full_capacity changes. */ + send_batt_info_event++; + } + } else if (!(curr->batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) && + ((curr->batt.full_capacity - bd->full_capacity) + > ((bs->design_capacity * 2) / 100))) { + bfc_retry++; + if (bfc_retry > 2) { + bd->full_capacity = curr->batt.full_capacity; + send_batt_info_event++; + bfc_retry = 0; + } + } +#else + if (!(curr->batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) && + (curr->batt.full_capacity <= + (bd->full_capacity - LFCC_EVENT_THRESH) || + curr->batt.full_capacity >= + (bd->full_capacity + LFCC_EVENT_THRESH))) { + bd->full_capacity = curr->batt.full_capacity; + /* Poke the AP if the full_capacity changes. */ + send_batt_info_event++; + } +#endif + + if (curr->batt.is_present == BP_YES && + battery_is_below_threshold(BATT_THRESHOLD_TYPE_SHUTDOWN, false)) + tmp |= EC_BATT_FLAG_LEVEL_CRITICAL; + +#ifdef CONFIG_CUSTOMIZED_DESIGN + batt_os_percentage = (bd->remaining_capacity * 1000) / (curr->batt.full_capacity + 1); + /* + * sync with OS battery percentage to avoid battery show charging icon at 100% + * os battery display formula: rounding (remainig / full capacity)*100 + */ + if (curr->ac && batt_os_percentage > 994) { + tmp |= EC_BATT_FLAG_DISCHARGING; + } else { + tmp |= curr->batt_is_charging ? EC_BATT_FLAG_CHARGING : + EC_BATT_FLAG_DISCHARGING; + } + + /* + * in ACPI spec _BST(battery status) have a feature + * 3.9.6 Battery Charge Limiting follows the spec + * to return limiting status to OS and if Limiting is engaged + * and the battery has reached the steady state need to + * clear CHARGING and DISCHARGING flag. + */ + if (battery_sustainer_enabled()) { + tmp |= EC_BATT_FLAG_LIMIT_ACTIVE; + if (get_chg_ctrl_mode() == CHARGE_CONTROL_IDLE) { + tmp &= ~EC_BATT_FLAG_CHARGING; + tmp &= ~EC_BATT_FLAG_DISCHARGING; + } + } else + tmp &= ~EC_BATT_FLAG_LIMIT_ACTIVE; + +#else + tmp |= curr->batt_is_charging ? EC_BATT_FLAG_CHARGING : + EC_BATT_FLAG_DISCHARGING; +#endif + + if (battery_is_cut_off()) + tmp |= EC_BATT_FLAG_CUT_OFF; + + /* Tell the AP to re-read battery status if charge state changes */ + if (bd->flags != tmp) + send_batt_status_event++; + + bd->flags = tmp; + +#ifdef HAS_TASK_HOSTCMD + battery_memmap_refresh(BATT_IDX_MAIN); +#endif + +#ifdef CONFIG_HOSTCMD_EVENTS + if (send_batt_info_event) + host_set_single_event(EC_HOST_EVENT_BATTERY); + if (send_batt_status_event) + host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS); +#endif +} diff --git a/common/blink.c b/common/blink.c index ed16146f5a..dcd6f0bdaa 100644 --- a/common/blink.c +++ b/common/blink.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,12 +10,12 @@ #include "hooks.h" #ifndef CONFIG_BLINK_LEDS - #error The macro CONFIG_BLINK_LEDS must be specified to use BLINK. +#error The macro CONFIG_BLINK_LEDS must be specified to use BLINK. #endif static const enum gpio_signal leds[] = { CONFIG_BLINK_LEDS }; -BUILD_ASSERT(ARRAY_SIZE(leds) <= sizeof(int)*8, "Too many LEDs to drive."); +BUILD_ASSERT(ARRAY_SIZE(leds) <= sizeof(int) * 8, "Too many LEDs to drive."); BUILD_ASSERT(ARRAY_SIZE(leds) > 0, "Must have at least one LED to blink."); static void blink(void) diff --git a/common/bluetooth_le.c b/common/bluetooth_le.c index 2e68893223..d102740293 100644 --- a/common/bluetooth_le.c +++ b/common/bluetooth_le.c @@ -1,13 +1,14 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "bluetooth_le.h" -#include "util.h" +#include "builtin/assert.h" #include "console.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_LE, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_LE, format, ##args) /* * Convert from BLE Channel to frequency @@ -15,11 +16,11 @@ * Bluetooth 4.1 Vol 6 pg 36 4.1 Table 1.1 */ -#define CHAN_0_MHZ 2404 -#define CHAN_11_MHZ 2428 -#define CHAN_37_MHZ 2402 -#define CHAN_38_MHZ 2426 -#define CHAN_39_MHZ 2480 +#define CHAN_0_MHZ 2404 +#define CHAN_11_MHZ 2428 +#define CHAN_37_MHZ 2402 +#define CHAN_38_MHZ 2426 +#define CHAN_39_MHZ 2480 int chan2freq(int channel) { @@ -72,11 +73,11 @@ uint8_t get_next_data_channel(struct remapping_table *rt) /* Check if the channel is mapped */ if (rt->map[rt->last_unmapped_channel / 8] & - (1 << (rt->last_unmapped_channel % 8))) + (1 << (rt->last_unmapped_channel % 8))) return rt->last_unmapped_channel; else - return rt->remapping_index - [rt->last_unmapped_channel % rt->num_used_channels]; + return rt->remapping_index[rt->last_unmapped_channel % + rt->num_used_channels]; } /* BLE 4.1 Vol 3 Part C 11 */ @@ -85,27 +86,27 @@ uint8_t get_next_data_channel(struct remapping_table *rt) uint8_t *pack_adv(uint8_t *dest, int length, int type, const uint8_t *data) { /* Add the structure length */ - dest[0] = (uint8_t)length+1; + dest[0] = (uint8_t)length + 1; /* Add the structure type */ dest[1] = (uint8_t)type; /* Add the data */ memcpy(&dest[2], data, length); /* Return a pointer to the next structure */ - return &dest[2+length]; + return &dest[2 + length]; } uint8_t *pack_adv_int(uint8_t *dest, int length, int type, int data) { /* Add the structure length */ - dest[0] = (uint8_t)length+1; + dest[0] = (uint8_t)length + 1; /* Add the structure type */ dest[1] = (uint8_t)type; /* Add the data */ memcpy(&dest[2], &data, length); /* Return a pointer to the next structure */ - return &dest[2+length]; + return &dest[2 + length]; } uint8_t *pack_adv_addr(uint8_t *dest, uint64_t addr) @@ -139,7 +140,7 @@ static void mem_dump(uint8_t *mem, int len) for (i = 0; i < len; i++) { value = mem[i]; if (i % 8 == 0) - CPRINTF("\n%pP: %02x", &mem[i], value); + CPRINTF("\n%p: %02x", &mem[i], value); else CPRINTF(" %02x", value); } @@ -160,19 +161,19 @@ void dump_ble_packet(struct ble_pdu *ble_p) int curr_offs; if (ble_p->header_type_adv) { - CPRINTF("BLE packet @ %pP: type %d, len %d, %s %s\n", - ble_p, ble_p->header.adv.type, ble_p->header.adv.length, + CPRINTF("BLE packet @ %p: type %d, len %d, %s %s\n", ble_p, + ble_p->header.adv.type, ble_p->header.adv.length, (ble_p->header.adv.txaddr ? " TXADDR" : ""), (ble_p->header.adv.rxaddr ? " RXADDR" : "")); curr_offs = 0; if (ble_p->header.adv.type == - BLE_ADV_HEADER_PDU_TYPE_SCAN_REQ) { + BLE_ADV_HEADER_PDU_TYPE_SCAN_REQ) { dump_ble_addr(ble_p->payload, "ScanA"); curr_offs += BLUETOOTH_ADDR_OCTETS; } else if (ble_p->header.adv.type == - BLE_ADV_HEADER_PDU_TYPE_CONNECT_REQ) { + BLE_ADV_HEADER_PDU_TYPE_CONNECT_REQ) { dump_ble_addr(ble_p->payload, "InitA"); curr_offs += BLUETOOTH_ADDR_OCTETS; } @@ -187,7 +188,7 @@ void dump_ble_packet(struct ble_pdu *ble_p) mem_dump(ble_p->payload + curr_offs, ble_p->header.adv.length - curr_offs); } else { /* Data PDUs */ - CPRINTF("BLE data packet @%pP: LLID %d," + CPRINTF("BLE data packet @%p: LLID %d," " nesn %d, sn %d, md %d, length %d\n", ble_p, ble_p->header.data.llid, ble_p->header.data.nesn, ble_p->header.data.sn, ble_p->header.data.md, @@ -195,4 +196,3 @@ void dump_ble_packet(struct ble_pdu *ble_p) mem_dump(ble_p->payload, ble_p->header.data.length); } } - diff --git a/common/body_detection.c b/common/body_detection.c index f7ea95c8c4..bac4f870b3 100644 --- a/common/body_detection.c +++ b/common/body_detection.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,22 +6,30 @@ #include "accelgyro.h" #include "body_detection.h" #include "console.h" +#include "hooks.h" #include "hwtimer.h" #include "lid_switch.h" #include "math_util.h" +#include "mkbp_input_devices.h" #include "motion_sense_fifo.h" #include "timer.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_ACCEL, outstr) -#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) +#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ##args) -static struct motion_sensor_t *body_sensor = +const static struct body_detect_params default_body_detect_params = { + .var_noise_factor = CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR, + .var_threshold = CONFIG_BODY_DETECTION_VAR_THRESHOLD, + .confidence_delta = CONFIG_BODY_DETECTION_CONFIDENCE_DELTA, +}; + +test_export_static struct motion_sensor_t *body_sensor = &motion_sensors[CONFIG_BODY_DETECTION_SENSOR]; static int window_size = CONFIG_BODY_DETECTION_MAX_WINDOW_SIZE; -static uint64_t var_threshold_scaled, confidence_delta_scaled; +test_export_static uint64_t var_threshold_scaled, confidence_delta_scaled; static int stationary_timeframe; static int history_idx; @@ -29,14 +37,20 @@ static enum body_detect_states motion_state = BODY_DETECTION_OFF_BODY; static bool history_initialized; static bool body_detect_enable; +STATIC_IF(CONFIG_ACCEL_SPOOF_MODE) bool spoof_enable; -static struct body_detect_motion_data -{ +static struct body_detect_motion_data { int history[CONFIG_BODY_DETECTION_MAX_WINDOW_SIZE]; /* acceleration */ - int sum; /* sum(history) */ + int sum; /* sum(history) */ uint64_t n2_variance; /* n^2 * var(history) */ } data[2]; /* motion data for X-axis and Y-axis */ +static void print_body_detect_mode(void) +{ + CPRINTS("body detect mode %sabled", + body_detect_get_state() ? "en" : "dis"); +} + /* * This function will update new variance and new sum according to incoming * value, previous value, previous sum and previous variance. @@ -48,18 +62,18 @@ static struct body_detect_motion_data * x_0: oldest value in the window, will be replaced by x_n * x_n: new coming value * - * n^2 * var(x') = n^2 * var(x) + (sum(x') - sum(x))^2 + - * (n * x_n - sum(x'))^2 / n - (n * x_0 - sum(x'))^2 / n + * n^2 * var(x') = n^2 * var(x) + (x_n - x_0) * + * (n * (x_n + x_0) - sum(x') - sum(x)) */ static void update_motion_data(struct body_detect_motion_data *x, int x_n) { const int n = window_size; const int x_0 = x->history[history_idx]; - const int new_sum = x->sum + (x_n - x->history[history_idx]); + const int sum_diff = x_n - x_0; + const int new_sum = x->sum + sum_diff; - x->n2_variance = x->n2_variance + POW2((int64_t)new_sum - x->sum) + - (POW2((int64_t)x_n * n - new_sum) - - POW2((int64_t)x_0 * n - new_sum)) / n; + x->n2_variance += + sum_diff * ((int64_t)n * (x_n + x_0) - new_sum - x->sum); x->sum = new_sum; x->history[history_idx] = x_n; } @@ -75,8 +89,8 @@ static void update_motion_variance(void) /* return Var(X) + Var(Y) */ static uint64_t get_motion_variance(void) { - return (data[X].n2_variance + data[Y].n2_variance) - / window_size / window_size; + return (data[X].n2_variance + data[Y].n2_variance) / window_size / + window_size; } static int calculate_motion_confidence(uint64_t var) @@ -86,32 +100,41 @@ static int calculate_motion_confidence(uint64_t var) if (var > var_threshold_scaled + confidence_delta_scaled) return 100; return 100 * (var - var_threshold_scaled + confidence_delta_scaled) / - (2 * confidence_delta_scaled); + (2 * confidence_delta_scaled); } /* Change the motion state and commit the change to AP. */ -void body_detect_change_state(enum body_detect_states state) -{ -#ifdef CONFIG_GESTURE_HOST_DETECTION - struct ec_response_motion_sensor_data vector = { - .flags = MOTIONSENSE_SENSOR_FLAG_WAKEUP, - .activity = MOTIONSENSE_ACTIVITY_BODY_DETECTION, - .state = state, - .sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID, - }; - motion_sense_fifo_stage_data(&vector, NULL, 0, - __hw_clock_source_read()); - motion_sense_fifo_commit_data(); -#endif +void body_detect_change_state(enum body_detect_states state, bool spoof) +{ + if (IS_ENABLED(CONFIG_ACCEL_SPOOF_MODE) && spoof_enable && !spoof) + return; + if (IS_ENABLED(CONFIG_GESTURE_HOST_DETECTION)) { + struct ec_response_motion_sensor_data vector = { + .flags = MOTIONSENSE_SENSOR_FLAG_BYPASS_FIFO, + .activity_data = { + .activity = MOTIONSENSE_ACTIVITY_BODY_DETECTION, + .state = state, + }, + .sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID, + }; + motion_sense_fifo_stage_data(&vector, NULL, 0, + __hw_clock_source_read()); + motion_sense_fifo_commit_data(); + } /* change the motion state */ motion_state = state; if (state == BODY_DETECTION_ON_BODY) { /* reset time counting of stationary */ stationary_timeframe = 0; } + /* state changing log */ - CPRINTS("body_detect changed state to: %s body", - motion_state ? "on" : "off"); + print_body_detect_mode(); + + if (IS_ENABLED(CONFIG_BODY_DETECTION_NOTIFY_MODE_CHANGE)) + host_set_single_event(EC_HOST_EVENT_BODY_DETECT_CHANGE); + + hook_notify(HOOK_BODY_DETECT_CHANGE); } enum body_detect_states body_detect_get_state(void) @@ -131,12 +154,13 @@ static void determine_window_size(int odr) } } -/* Determine variance threshold scale by range and resolution. */ -static void determine_threshold_scale(int range, int resolution, int rms_noise) +/* Determine variance threshold scale by range. */ +static void determine_threshold_scale(int range, int rms_noise, + int var_noise_factor, int var_threshold, + int confidence_delta) { /* * range: g - * resolution: bits * data_1g: LSB/g * data_1g / 9800: LSB/(mm/s^2) * (data_1g / 9800)^2: (LSB^2)/(mm^2/s^4), which number of @@ -144,9 +168,10 @@ static void determine_threshold_scale(int range, int resolution, int rms_noise) * rms_noise: ug * var_noise: mm^2/s^4 */ - const int data_1g = BIT(resolution - 1) / range; + const int data_1g = MOTION_SCALING_FACTOR / range; const int multiplier = POW2(data_1g); const int divisor = POW2(9800); + /* * We are measuring the var(X) + var(Y), so theoretically, the * var(noise) should be 2 * rms_noise^2. However, in most case, on a @@ -154,34 +179,58 @@ static void determine_threshold_scale(int range, int resolution, int rms_noise) * rms_noise^2. We can multiply the rms_noise^2 with the * CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR / 100. */ - const int var_noise = POW2((uint64_t)rms_noise) * - CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR * POW2(98) - / 100 / POW2(10000); + const int var_noise = POW2((uint64_t)rms_noise) * var_noise_factor * + POW2(98) / 100 / POW2(10000); - var_threshold_scaled = (uint64_t) - (CONFIG_BODY_DETECTION_VAR_THRESHOLD + var_noise) * - multiplier / divisor; - confidence_delta_scaled = (uint64_t) - CONFIG_BODY_DETECTION_CONFIDENCE_DELTA * - multiplier / divisor; + var_threshold_scaled = + (uint64_t)(var_threshold + var_noise) * multiplier / divisor; + confidence_delta_scaled = + (uint64_t)confidence_delta * multiplier / divisor; } void body_detect_reset(void) { int odr = body_sensor->drv->get_data_rate(body_sensor); - int range = body_sensor->drv->get_range(body_sensor); - int resolution = body_sensor->drv->get_resolution(body_sensor); int rms_noise = body_sensor->drv->get_rms_noise(body_sensor); + int var_threshold, confidence_delta, var_noise_factor; - body_detect_change_state(BODY_DETECTION_ON_BODY); + if (motion_state == BODY_DETECTION_ON_BODY) + stationary_timeframe = 0; + else + body_detect_change_state(BODY_DETECTION_ON_BODY, false); /* * The sensor is suspended since its ODR is 0, * there is no need to reset until sensor is up again */ if (odr == 0) return; + + /* If body detection params haven't been set, use the default ones. */ + if (!body_sensor->bd_params) + body_sensor->bd_params = &default_body_detect_params; + /* + * In case only some of the parameters have been specified use + * the default values for the rest of them. + */ + if (body_sensor->bd_params->var_noise_factor != 0) + var_noise_factor = body_sensor->bd_params->var_noise_factor; + else + var_noise_factor = default_body_detect_params.var_noise_factor; + + if (body_sensor->bd_params->var_threshold != 0) + var_threshold = body_sensor->bd_params->var_threshold; + else + var_threshold = default_body_detect_params.var_threshold; + + if (body_sensor->bd_params->confidence_delta != 0) + confidence_delta = body_sensor->bd_params->confidence_delta; + else + confidence_delta = default_body_detect_params.confidence_delta; + determine_window_size(odr); - determine_threshold_scale(range, resolution, rms_noise); + determine_threshold_scale(body_sensor->current_range, rms_noise, + var_noise_factor, var_threshold, + confidence_delta); /* initialize motion data and state */ memset(data, 0, sizeof(data)); history_idx = 0; @@ -208,7 +257,7 @@ void body_detect(void) switch (motion_state) { case BODY_DETECTION_OFF_BODY: if (motion_confidence > CONFIG_BODY_DETECTION_ON_BODY_CON) - body_detect_change_state(BODY_DETECTION_ON_BODY); + body_detect_change_state(BODY_DETECTION_ON_BODY, false); break; case BODY_DETECTION_ON_BODY: stationary_timeframe += 1; @@ -218,7 +267,8 @@ void body_detect(void) /* if no motion for enough time, change state to off_body */ if (stationary_timeframe >= CONFIG_BODY_DETECTION_STATIONARY_DURATION * window_size) - body_detect_change_state(BODY_DETECTION_OFF_BODY); + body_detect_change_state(BODY_DETECTION_OFF_BODY, + false); break; } } @@ -226,10 +276,60 @@ void body_detect(void) void body_detect_set_enable(int enable) { body_detect_enable = enable; - body_detect_change_state(BODY_DETECTION_ON_BODY); + body_detect_change_state(BODY_DETECTION_ON_BODY, false); } int body_detect_get_enable(void) { return body_detect_enable; } + +#ifdef CONFIG_ACCEL_SPOOF_MODE +void body_detect_set_spoof(int enable) +{ + spoof_enable = enable; + /* After disabling spoof mode, commit current state. */ + if (!enable) + body_detect_change_state(motion_state, false); +} + +bool body_detect_get_spoof(void) +{ + return spoof_enable; +} + +static int command_setbodydetectionmode(int argc, const char **argv) +{ + if (argc == 1) { + print_body_detect_mode(); + return EC_SUCCESS; + } + + if (argc != 2) + return EC_ERROR_PARAM_COUNT; + + /* |+1| to also make sure the strings the same length. */ + if (strncmp(argv[1], "on", strlen("on") + 1) == 0) { + body_detect_change_state(BODY_DETECTION_ON_BODY, true); + spoof_enable = true; + } else if (strncmp(argv[1], "off", strlen("off") + 1) == 0) { + body_detect_change_state(BODY_DETECTION_OFF_BODY, true); + spoof_enable = true; + } else if (strncmp(argv[1], "reset", strlen("reset") + 1) == 0) { + body_detect_reset(); + /* + * Don't call body_detect_set_spoof(), since + * body_detect_change_state() was already called by + * body_detect_reset(). + */ + spoof_enable = false; + } else { + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND( + bodydetectmode, command_setbodydetectionmode, "[on | off | reset]", + "Manually force body detect mode to on (body), off (body) or reset."); +#endif /* CONFIG_ACCEL_SPOOF_MODE */ diff --git a/common/btle_hci_controller.c b/common/btle_hci_controller.c index cc5b872b19..605b67945b 100644 --- a/common/btle_hci_controller.c +++ b/common/btle_hci_controller.c @@ -1,18 +1,18 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "btle_hci_int.h" -#include "btle_hci2.h" #include "bluetooth_le_ll.h" +#include "btle_hci2.h" +#include "btle_hci_int.h" #include "console.h" #ifdef CONFIG_BLUETOOTH_HCI_DEBUG #define CPUTS(outstr) cputs(CC_BLUETOOTH_HCI, outstr) -#define CPRINTS(format, args...) cprints(CC_BLUETOOTH_HCI, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_HCI, format, ## args) +#define CPRINTS(format, args...) cprints(CC_BLUETOOTH_HCI, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_HCI, format, ##args) #else /* CONFIG_BLUETOOTH_HCI_DEBUG */ @@ -27,7 +27,7 @@ static uint64_t hci_le_event_mask; #define MAX_MESSAGE 24 -#define STATUS (return_params[0]) +#define STATUS (return_params[0]) #define RPARAMS (&(return_params[1])) void hci_cmd(uint8_t *hciCmdbuf) @@ -56,215 +56,184 @@ void hci_cmd(uint8_t *hciCmdbuf) } switch (hdr->opcode) { - case CMD_MAKE_OPCODE(HCI_OGF_Controller_and_Baseband, - HCI_CMD_Reset): + case CMD_MAKE_OPCODE(HCI_OGF_Controller_and_Baseband, HCI_CMD_Reset): STATUS = ll_reset(); - break; + break; case CMD_MAKE_OPCODE(HCI_OGF_Controller_and_Baseband, - HCI_CMD_Set_Event_Mask): + HCI_CMD_Set_Event_Mask): if (hdr->paramLen != sizeof(hci_event_mask)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = HCI_SUCCESS; memcpy(&hci_event_mask, params, sizeof(hci_event_mask)); - break; + break; case CMD_MAKE_OPCODE(HCI_OGF_Controller_and_Baseband, - HCI_CMD_Read_Transmit_Power_Level): + HCI_CMD_Read_Transmit_Power_Level): case CMD_MAKE_OPCODE(HCI_OGF_Informational, - HCI_CMD_Read_Local_Supported_Features): + HCI_CMD_Read_Local_Supported_Features): case CMD_MAKE_OPCODE(HCI_OGF_Informational, - HCI_CMD_Read_Local_Supported_Commands): + HCI_CMD_Read_Local_Supported_Commands): case CMD_MAKE_OPCODE(HCI_OGF_Informational, - HCI_CMD_Read_Local_Version_Information): - case CMD_MAKE_OPCODE(HCI_OGF_Informational, - HCI_CMD_Read_BD_ADDR): + HCI_CMD_Read_Local_Version_Information): + case CMD_MAKE_OPCODE(HCI_OGF_Informational, HCI_CMD_Read_BD_ADDR): case CMD_MAKE_OPCODE(HCI_OGF_Link_Control, - HCI_CMD_Read_Remote_Version_Information): - case CMD_MAKE_OPCODE(HCI_OGF_Status, - HCI_CMD_Read_RSSI): + HCI_CMD_Read_Remote_Version_Information): + case CMD_MAKE_OPCODE(HCI_OGF_Status, HCI_CMD_Read_RSSI): event = 0; - break; + break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Event_Mask): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Event_Mask): if (hdr->paramLen != sizeof(hci_le_event_mask)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = HCI_SUCCESS; memcpy(&hci_le_event_mask, params, sizeof(hci_le_event_mask)); - break; + break; /* LE Information */ - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Read_Buffer_Size): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Read_Buffer_Size): if (hdr->paramLen != 0) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_read_buffer_size(RPARAMS); rparam_count = sizeof(struct hciCmplLeReadBufferSize); - break; + break; case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Read_Local_Supported_Features): + HCI_CMD_LE_Read_Local_Supported_Features): if (hdr->paramLen != 0) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_read_local_supported_features(RPARAMS); rparam_count = sizeof(struct hciCmplLeReadLocalSupportedFeatures); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Read_Supported_States): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Read_Supported_States): if (hdr->paramLen != 0) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_read_supported_states(RPARAMS); rparam_count = sizeof(struct hciCmplLeReadSupportedStates); - break; + break; case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Host_Channel_Classification): + HCI_CMD_LE_Set_Host_Channel_Classification): if (hdr->paramLen != sizeof(struct hciLeSetHostChannelClassification)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_set_host_channel_classification(params); - break; + break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Random_Address): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Random_Address): if (hdr->paramLen != sizeof(struct hciLeSetRandomAddress)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_set_random_address(params); - break; + break; /* Advertising */ - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Advertise_Enable): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Advertise_Enable): STATUS = ll_set_advertising_enable(params); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Advertising_Data): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Advertising_Data): STATUS = ll_set_adv_data(params); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Adv_Params): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Adv_Params): if (hdr->paramLen != sizeof(struct hciLeSetAdvParams)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_set_advertising_params(params); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Read_Adv_Channel_TX_Power): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Read_Adv_Channel_TX_Power): STATUS = ll_read_tx_power(); rparam_count = sizeof(struct hciCmplLeReadAdvChannelTxPower); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Scan_Response_Data): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Scan_Response_Data): STATUS = ll_set_scan_response_data(params); - break; + break; /* Connections */ - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Read_Remote_Used_Features): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Read_Remote_Used_Features): if (hdr->paramLen != sizeof(struct hciLeReadRemoteUsedFeatures)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_read_remote_used_features(params); event = HCI_EVT_Command_Status; - break; - case CMD_MAKE_OPCODE(HCI_OGF_Link_Control, - HCI_CMD_Disconnect): - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Connection_Update): - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Create_Connection): - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Create_Connection_Cancel): - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Read_Channel_Map): + break; + case CMD_MAKE_OPCODE(HCI_OGF_Link_Control, HCI_CMD_Disconnect): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Connection_Update): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Create_Connection): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Create_Connection_Cancel): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Read_Channel_Map): event = 0; - break; + break; /* Encryption */ - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Encrypt): - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_LTK_Request_Reply): - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_LTK_Request_Negative_Reply): - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Rand): - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Start_Encryption): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Encrypt): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_LTK_Request_Reply): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_LTK_Request_Negative_Reply): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Rand): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Start_Encryption): event = 0; - break; + break; /* Scanning */ - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Scan_Enable): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Scan_Enable): if (hdr->paramLen != sizeof(struct hciLeSetScanEnable)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_set_scan_enable(params); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Scan_Parameters): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Scan_Parameters): if (hdr->paramLen != sizeof(struct hciLeSetScanParams)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_set_scan_params(params); - break; + break; /* Allow List */ - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Clear_Allow_List): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Clear_Allow_List): if (hdr->paramLen != 0) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_clear_allow_list(); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Read_Allow_List_Size): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Read_Allow_List_Size): if (hdr->paramLen != 0) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_read_allow_list_size(RPARAMS); rparam_count = sizeof(struct hciCmplLeReadAllowListSize); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Add_Device_To_Allow_List): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Add_Device_To_Allow_List): if (hdr->paramLen != sizeof(struct hciLeAddDeviceToAllowList)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_add_device_to_allow_list(params); - break; + break; case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Remove_Device_From_Allow_List): + HCI_CMD_LE_Remove_Device_From_Allow_List): if (hdr->paramLen != - sizeof(struct hciLeRemoveDeviceFromAllowList)) + sizeof(struct hciLeRemoveDeviceFromAllowList)) STATUS = HCI_ERR_Invalid_HCI_Command_Parameters; else STATUS = ll_remove_device_from_allow_list(params); - break; + break; /* RFPHY Testing Support */ - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Receiver_Test): + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Receiver_Test): STATUS = ll_receiver_test(params); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Transmitter_Test): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Transmitter_Test): STATUS = ll_transmitter_test(params); - break; - case CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Test_End): + break; + case CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Test_End): STATUS = ll_test_end(RPARAMS); rparam_count = sizeof(struct hciCmplLeTestEnd); - break; + break; default: STATUS = HCI_ERR_Unknown_HCI_Command; - break; + break; } hci_event(event, rparam_count, return_params); @@ -275,12 +244,11 @@ void hci_acl_to_host(uint8_t *data, uint16_t hdr, uint16_t len) int i; /* Enqueue hdr, len, len bytes of data */ - CPRINTF("Sending %d bytes of data from handle %d with PB=%x.\n", - len, hdr & ACL_HDR_MASK_CONN_ID, - hdr & ACL_HDR_MASK_PB); - for (i = 0; i < len; i++) - CPRINTF("0x%x, ", data[i]); - CPRINTF("\n"); + CPRINTF("Sending %d bytes of data from handle %d with PB=%x.\n", len, + hdr & ACL_HDR_MASK_CONN_ID, hdr & ACL_HDR_MASK_PB); + for (i = 0; i < len; i++) + CPRINTF("0x%x, ", data[i]); + CPRINTF("\n"); } void hci_acl_from_host(uint8_t *hciAclbuf) @@ -290,12 +258,11 @@ void hci_acl_from_host(uint8_t *hciAclbuf) int i; /* Send the data to the link layer */ - CPRINTF("Sending %d bytes of data to handle %d with PB=%x.\n", - hdr->len, hdr->hdr & ACL_HDR_MASK_CONN_ID, - hdr->hdr & ACL_HDR_MASK_PB); - for (i = 0; i < hdr->len; i++) - CPRINTF("0x%x, ", data[i]); - CPRINTF("\n"); + CPRINTF("Sending %d bytes of data to handle %d with PB=%x.\n", hdr->len, + hdr->hdr & ACL_HDR_MASK_CONN_ID, hdr->hdr & ACL_HDR_MASK_PB); + for (i = 0; i < hdr->len; i++) + CPRINTF("0x%x, ", data[i]); + CPRINTF("\n"); } /* @@ -335,52 +302,50 @@ void hci_event(uint8_t event_code, uint8_t len, uint8_t *params) * hcitool lcmd 0x2008 18 0x42410906 0x03454443 0x203c119 0x3030501 0x1812 * hcitool cmd 8 8 6 9 41 42 43 44 45 3 19 c1 3 2 1 5 3 3 12 18 */ -uint8_t adv0[19] = {0x07, 0x09, 'A', 'B', 'C', 'D', 'E', 'F', /* Name */ - 0x03, 0x19, 0xc1, 0x03, /* Keyboard */ - 0x02, 0x01, 0x05, /* Flags */ - 0x03, 0x03, 0x12, 0x18}; /* UUID */ +uint8_t adv0[19] = { 0x07, 0x09, 'A', 'B', 'C', 'D', 'E', 'F', /* Name */ + 0x03, 0x19, 0xc1, 0x03, /* Keyboard */ + 0x02, 0x01, 0x05, /* Flags */ + 0x03, 0x03, 0x12, 0x18 }; /* UUID */ -uint8_t adv1[18] = {0x06, 0x09, 'A', 'B', 'C', 'D', 'E', /* Name */ - 0x02, 0x01, 0x05, /* Flags */ - 0x03, 0x19, 0xc1, 0x03, /* Keyboard */ - 0x03, 0x03, 0x12, 0x18}; /* UUID */ +uint8_t adv1[18] = { 0x06, 0x09, 'A', 'B', 'C', 'D', 'E', /* Name */ + 0x02, 0x01, 0x05, /* Flags */ + 0x03, 0x19, 0xc1, 0x03, /* Keyboard */ + 0x03, 0x03, 0x12, 0x18 }; /* UUID */ -uint8_t *adverts[] = {adv0, adv1}; -uint8_t adv_lengths[] = {sizeof(adv0), sizeof(adv1)}; +uint8_t *adverts[] = { adv0, adv1 }; +uint8_t adv_lengths[] = { sizeof(adv0), sizeof(adv1) }; -uint8_t scan0[4] = {0x03, 0x08, 'A', 'B'}; /* Short Name */ +uint8_t scan0[4] = { 0x03, 0x08, 'A', 'B' }; /* Short Name */ -uint8_t scan1[] = {}; /* Empty */ +uint8_t scan1[] = {}; /* Empty */ -uint8_t *scans[] = {scan0, scan1}; -uint8_t scan_lengths[] = {sizeof(scan0), sizeof(scan1)}; +uint8_t *scans[] = { scan0, scan1 }; +uint8_t scan_lengths[] = { sizeof(scan0), sizeof(scan1) }; /* * LE_Set_Adv_Params * hcitool lcmd 0x2006 15 0x010000f0 0xb0010100 0xb4b3b2b1 0x0007c5 * hcitool cmd 8 6 f0 0 0 1 0 1 1 b0 b1 b2 b3 b4 c5 7 0 */ -uint8_t adv_param0[15] = { - 0xf0, 0x00, /* IntervalMin */ - 0x00, 0x01, /* IntervalMax */ - 0x00, /* Adv Type */ - 0x01, /* Use Random Addr */ - 0x01, /* Direct Random */ - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xc5, /* Direct Addr */ - 0x07, /* Channel Map */ - 0x00}; /* Filter Policy */ - -uint8_t adv_param1[15] = { - 0xf0, 0x00, /* IntervalMin */ - 0x00, 0x01, /* IntervalMax */ - 0x02, /* Adv Type */ - 0x01, /* Use Random Addr */ - 0x01, /* Direct Random */ - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xc5, /* Direct Addr */ - 0x07, /* Channel Map */ - 0x00}; /* Filter Policy */ - -uint8_t *adv_params[] = {adv_param0, adv_param1}; +uint8_t adv_param0[15] = { 0xf0, 0x00, /* IntervalMin */ + 0x00, 0x01, /* IntervalMax */ + 0x00, /* Adv Type */ + 0x01, /* Use Random Addr */ + 0x01, /* Direct Random */ + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xc5, /* Direct Addr */ + 0x07, /* Channel Map */ + 0x00 }; /* Filter Policy */ + +uint8_t adv_param1[15] = { 0xf0, 0x00, /* IntervalMin */ + 0x00, 0x01, /* IntervalMax */ + 0x02, /* Adv Type */ + 0x01, /* Use Random Addr */ + 0x01, /* Direct Random */ + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xc5, /* Direct Addr */ + 0x07, /* Channel Map */ + 0x00 }; /* Filter Policy */ + +uint8_t *adv_params[] = { adv_param0, adv_param1 }; /* * LE Information @@ -466,7 +431,7 @@ static uint8_t hci_buf[200]; #define MAX_BLE_HCI_PARAMS 8 static uint32_t param[MAX_BLE_HCI_PARAMS]; -static int command_ble_hci_cmd(int argc, char **argv) +static int command_ble_hci_cmd(int argc, const char **argv) { static struct hciCmdHdr header; int length, opcode, i; @@ -489,7 +454,7 @@ static int command_ble_hci_cmd(int argc, char **argv) } for (i = 3; i < argc; i++) { - param[i-3] = strtoi(argv[i], &e, 0); + param[i - 3] = strtoi(argv[i], &e, 0); if (*e) return EC_ERROR_PARAM3 + i; } @@ -498,12 +463,11 @@ static int command_ble_hci_cmd(int argc, char **argv) header.paramLen = length; memcpy(hci_buf, &header, sizeof(struct hciCmdHdr)); - memcpy(hci_buf + sizeof(struct hciCmdHdr), - param, length); + memcpy(hci_buf + sizeof(struct hciCmdHdr), param, length); hci_cmd(hci_buf); - CPRINTS("hci cmd @%pP", hci_buf); + CPRINTS("hci cmd @%p", hci_buf); return EC_SUCCESS; } @@ -511,7 +475,7 @@ DECLARE_CONSOLE_COMMAND(ble_hci_cmd, command_ble_hci_cmd, "opcode len uint32 uint32 uint32... (little endian)", "Send an hci command of length len"); -static int command_hcitool(int argc, char **argv) +static int command_hcitool(int argc, const char **argv) { static struct hciCmdHdr header; int i, ogf, ocf; @@ -521,7 +485,7 @@ static int command_hcitool(int argc, char **argv) return EC_ERROR_PARAM_COUNT; if (argv[1][0] == 'l') /* strcmp lcmd */ - return command_ble_hci_cmd(argc-1, &argv[1]); + return command_ble_hci_cmd(argc - 1, &argv[1]); ogf = strtoi(argv[2], &e, 16); if (*e) @@ -532,7 +496,7 @@ static int command_hcitool(int argc, char **argv) return EC_ERROR_PARAM3; header.opcode = CMD_MAKE_OPCODE(ogf, ocf); - header.paramLen = argc-4; + header.paramLen = argc - 4; memcpy(hci_buf, &header, sizeof(struct hciCmdHdr)); for (i = 4; i < argc; i++) { @@ -543,15 +507,16 @@ static int command_hcitool(int argc, char **argv) hci_cmd(hci_buf); - CPRINTS("hci cmd @%pP", hci_buf); + CPRINTS("hci cmd @%p", hci_buf); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(hcitool, command_hcitool, - "cmd ogf ocf b0 b1 b2 b3... or lcmd opcode len uint32.. (little endian)", - "Send an hci command of length len"); +DECLARE_CONSOLE_COMMAND( + hcitool, command_hcitool, + "cmd ogf ocf b0 b1 b2 b3... or lcmd opcode len uint32.. (little endian)", + "Send an hci command of length len"); -static int command_ble_hci_acl(int argc, char **argv) +static int command_ble_hci_acl(int argc, const char **argv) { static struct hciAclHdr header; int length, hdr, i; @@ -574,7 +539,7 @@ static int command_ble_hci_acl(int argc, char **argv) } for (i = 3; i < argc; i++) { - param[i-3] = strtoi(argv[i], &e, 0); + param[i - 3] = strtoi(argv[i], &e, 0); if (*e) return EC_ERROR_PARAM3 + i; } @@ -583,12 +548,11 @@ static int command_ble_hci_acl(int argc, char **argv) header.len = length; memcpy(hci_buf, &header, sizeof(struct hciCmdHdr)); - memcpy(hci_buf + sizeof(struct hciCmdHdr), - param, length); + memcpy(hci_buf + sizeof(struct hciCmdHdr), param, length); hci_cmd(hci_buf); - CPRINTS("hci acl @%pP", hci_buf); + CPRINTS("hci acl @%p", hci_buf); return EC_SUCCESS; } @@ -596,7 +560,7 @@ DECLARE_CONSOLE_COMMAND(ble_hci_acl, command_ble_hci_acl, "hdr len uint32 uint32 uint32... (little endian)", "Send hci acl data of length len"); -static int command_ble_hci_adv(int argc, char **argv) +static int command_ble_hci_adv(int argc, const char **argv) { static struct hciCmdHdr header; int adv, p = 0, scan_rsp = 0; @@ -625,33 +589,33 @@ static int command_ble_hci_adv(int argc, char **argv) header.paramLen = sizeof(struct hciLeSetAdvParams); memcpy(hci_buf, &header, sizeof(struct hciCmdHdr)); - memcpy(hci_buf + sizeof(struct hciCmdHdr), - adv_params[p], header.paramLen); + memcpy(hci_buf + sizeof(struct hciCmdHdr), adv_params[p], + header.paramLen); hci_cmd(hci_buf); - header.opcode = CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Advertising_Data); + header.opcode = + CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Advertising_Data); header.paramLen = adv_lengths[adv]; memcpy(hci_buf, &header, sizeof(struct hciCmdHdr)); - memcpy(hci_buf + sizeof(struct hciCmdHdr), - adverts[adv], header.paramLen); + memcpy(hci_buf + sizeof(struct hciCmdHdr), adverts[adv], + header.paramLen); hci_cmd(hci_buf); - header.opcode = CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Scan_Response_Data); + header.opcode = + CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Scan_Response_Data); header.paramLen = scan_lengths[scan_rsp]; memcpy(hci_buf, &header, sizeof(struct hciCmdHdr)); - memcpy(hci_buf + sizeof(struct hciCmdHdr), - scans[scan_rsp], header.paramLen); + memcpy(hci_buf + sizeof(struct hciCmdHdr), scans[scan_rsp], + header.paramLen); hci_cmd(hci_buf); - header.opcode = CMD_MAKE_OPCODE(HCI_OGF_LE, - HCI_CMD_LE_Set_Advertise_Enable); + header.opcode = + CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Advertise_Enable); header.paramLen = sizeof(struct hciLeSetAdvEnable); memcpy(hci_buf, &header, sizeof(struct hciCmdHdr)); diff --git a/common/btle_ll.c b/common/btle_ll.c index b2a15ce36e..eea9534fe3 100644 --- a/common/btle_ll.c +++ b/common/btle_ll.c @@ -1,23 +1,23 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "bluetooth_le_ll.h" #include "bluetooth_le.h" +#include "bluetooth_le_ll.h" #include "btle_hci_int.h" -#include "util.h" #include "console.h" #include "radio.h" #include "radio_test.h" #include "task.h" #include "timer.h" +#include "util.h" #ifdef CONFIG_BLUETOOTH_LL_DEBUG #define CPUTS(outstr) cputs(CC_BLUETOOTH_LL, outstr) -#define CPRINTS(format, args...) cprints(CC_BLUETOOTH_LL, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_LL, format, ## args) +#define CPRINTS(format, args...) cprints(CC_BLUETOOTH_LL, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_LL, format, ##args) #else /* CONFIG_BLUETOOTH_LL_DEBUG */ @@ -57,7 +57,7 @@ uint8_t is_first_data_packet; static uint64_t ll_random_address = 0xC5BADBADBAD1; /* Uninitialized */ static uint64_t ll_public_address = 0xC5BADBADBADF; /* Uninitialized */ -static uint8_t ll_channel_map[5] = {0xff, 0xff, 0xff, 0xff, 0x1f}; +static uint8_t ll_channel_map[5] = { 0xff, 0xff, 0xff, 0xff, 0x1f }; static uint8_t ll_filter_duplicates; @@ -161,8 +161,8 @@ static uint8_t ll_state_change_request(enum ll_state_t next_state) { /* Initialize the radio if it hasn't been initialized */ if (ll_state == UNINITIALIZED) { - if (ble_radio_init(BLE_ADV_ACCESS_ADDRESS, BLE_ADV_CRCINIT) - != EC_SUCCESS) + if (ble_radio_init(BLE_ADV_ACCESS_ADDRESS, BLE_ADV_CRCINIT) != + EC_SUCCESS) return HCI_ERR_Hardware_Failure; ll_state = STANDBY; } @@ -236,50 +236,50 @@ uint8_t initialize_connection(void) num_consecutive_failures = 0; /* Copy data into the appropriate portions of memory */ - memcpy((uint8_t *)&(conn_params.init_a), - payload_start, CONNECT_REQ_INITA_LEN); + memcpy((uint8_t *)&(conn_params.init_a), payload_start, + CONNECT_REQ_INITA_LEN); cur_offset += CONNECT_REQ_INITA_LEN; - memcpy((uint8_t *)&(conn_params.adv_a), - payload_start+cur_offset, CONNECT_REQ_ADVA_LEN); + memcpy((uint8_t *)&(conn_params.adv_a), payload_start + cur_offset, + CONNECT_REQ_ADVA_LEN); cur_offset += CONNECT_REQ_ADVA_LEN; - memcpy(&(conn_params.access_addr), - payload_start+cur_offset, CONNECT_REQ_ACCESS_ADDR_LEN); + memcpy(&(conn_params.access_addr), payload_start + cur_offset, + CONNECT_REQ_ACCESS_ADDR_LEN); cur_offset += CONNECT_REQ_ACCESS_ADDR_LEN; conn_params.crc_init_val = 0; - memcpy(&(conn_params.crc_init_val), - payload_start+cur_offset, CONNECT_REQ_CRC_INIT_VAL_LEN); + memcpy(&(conn_params.crc_init_val), payload_start + cur_offset, + CONNECT_REQ_CRC_INIT_VAL_LEN); cur_offset += CONNECT_REQ_CRC_INIT_VAL_LEN; - memcpy(&(conn_params.win_size), - payload_start+cur_offset, CONNECT_REQ_WIN_SIZE_LEN); + memcpy(&(conn_params.win_size), payload_start + cur_offset, + CONNECT_REQ_WIN_SIZE_LEN); cur_offset += CONNECT_REQ_WIN_SIZE_LEN; - memcpy(&(conn_params.win_offset), - payload_start+cur_offset, CONNECT_REQ_WIN_OFFSET_LEN); + memcpy(&(conn_params.win_offset), payload_start + cur_offset, + CONNECT_REQ_WIN_OFFSET_LEN); cur_offset += CONNECT_REQ_WIN_OFFSET_LEN; - memcpy(&(conn_params.interval), - payload_start+cur_offset, CONNECT_REQ_INTERVAL_LEN); + memcpy(&(conn_params.interval), payload_start + cur_offset, + CONNECT_REQ_INTERVAL_LEN); cur_offset += CONNECT_REQ_INTERVAL_LEN; - memcpy(&(conn_params.latency), - payload_start+cur_offset, CONNECT_REQ_LATENCY_LEN); + memcpy(&(conn_params.latency), payload_start + cur_offset, + CONNECT_REQ_LATENCY_LEN); cur_offset += CONNECT_REQ_LATENCY_LEN; - memcpy(&(conn_params.timeout), - payload_start+cur_offset, CONNECT_REQ_TIMEOUT_LEN); + memcpy(&(conn_params.timeout), payload_start + cur_offset, + CONNECT_REQ_TIMEOUT_LEN); cur_offset += CONNECT_REQ_TIMEOUT_LEN; conn_params.channel_map = 0; - memcpy(&(conn_params.channel_map), - payload_start+cur_offset, CONNECT_REQ_CHANNEL_MAP_LEN); + memcpy(&(conn_params.channel_map), payload_start + cur_offset, + CONNECT_REQ_CHANNEL_MAP_LEN); cur_offset += CONNECT_REQ_CHANNEL_MAP_LEN; - memcpy(&final_octet, payload_start+cur_offset, - CONNECT_REQ_HOP_INCREMENT_AND_SCA_LEN); + memcpy(&final_octet, payload_start + cur_offset, + CONNECT_REQ_HOP_INCREMENT_AND_SCA_LEN); /* last 5 bits of final_octet: */ conn_params.hop_increment = final_octet & 0x1f; @@ -288,16 +288,16 @@ uint8_t initialize_connection(void) /* Set up channel mapping table */ for (i = 0; i < 5; ++i) - remap_arr[i] = *(((uint8_t *)&(conn_params.channel_map))+i); + remap_arr[i] = *(((uint8_t *)&(conn_params.channel_map)) + i); fill_remapping_table(&remap_table, remap_arr, - conn_params.hop_increment); + conn_params.hop_increment); /* Calculate transmission window parameters */ conn_params.transmitWindowSize = conn_params.win_size * 1250; conn_params.transmitWindowOffset = conn_params.win_offset * 1250; conn_params.connInterval = conn_params.interval * 1250; /* The following two lines convert ms -> microseconds */ - conn_params.connSlaveLatency = 1000 * conn_params.latency; + conn_params.connLatency = 1000 * conn_params.latency; conn_params.connSupervisionTimeout = 10000 * conn_params.timeout; /* All these times are in microseconds! */ @@ -332,7 +332,7 @@ uint8_t ll_read_allow_list_size(uint8_t *return_params) uint8_t ll_add_device_to_allow_list(uint8_t *params) { if (ble_radio_add_device_to_allow_list(¶ms[1], params[0]) == - EC_SUCCESS) + EC_SUCCESS) return HCI_SUCCESS; else return HCI_ERR_Host_Rejected_Due_To_Limited_Resources; @@ -341,7 +341,7 @@ uint8_t ll_add_device_to_allow_list(uint8_t *params) uint8_t ll_remove_device_from_allow_list(uint8_t *params) { if (ble_radio_remove_device_from_allow_list(¶ms[1], params[0]) == - EC_SUCCESS) + EC_SUCCESS) return HCI_SUCCESS; else return HCI_ERR_Hardware_Failure; @@ -449,27 +449,28 @@ uint8_t ll_set_advertising_params(uint8_t *params) case BLE_ADV_HEADER_PDU_TYPE_ADV_NONCONN_IND: case BLE_ADV_HEADER_PDU_TYPE_ADV_SCAN_IND: if (ll_adv_params.advIntervalMin < - (100000 / LL_ADV_INTERVAL_UNIT_US)) /* 100ms */ + (100000 / LL_ADV_INTERVAL_UNIT_US)) /* 100ms */ return HCI_ERR_Invalid_HCI_Command_Parameters; /* Fall through */ case BLE_ADV_HEADER_PDU_TYPE_ADV_IND: if (ll_adv_params.advIntervalMin > ll_adv_params.advIntervalMax) return HCI_ERR_Invalid_HCI_Command_Parameters; if (ll_adv_params.advIntervalMin < - (20000 / LL_ADV_INTERVAL_UNIT_US) || /* 20ms */ + (20000 / LL_ADV_INTERVAL_UNIT_US) || /* 20ms */ ll_adv_params.advIntervalMax > - (10240000 / LL_ADV_INTERVAL_UNIT_US)) /* 10.24s */ + (10240000 / LL_ADV_INTERVAL_UNIT_US)) /* 10.24s */ return HCI_ERR_Invalid_HCI_Command_Parameters; ll_adv_interval_us = (((ll_adv_params.advIntervalMin + - ll_adv_params.advIntervalMax) / 2) * - LL_ADV_INTERVAL_UNIT_US); + ll_adv_params.advIntervalMax) / + 2) * + LL_ADV_INTERVAL_UNIT_US); /* Don't time out */ ll_adv_timeout_us = -1; - break; + break; case BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND: ll_adv_interval_us = LL_ADV_DIRECT_INTERVAL_US; ll_adv_timeout_us = LL_ADV_DIRECT_TIMEOUT_US; - break; + break; default: return HCI_ERR_Invalid_HCI_Command_Parameters; } @@ -563,25 +564,25 @@ int ble_ll_adv(int chan) case BLE_ADV_HEADER_PDU_TYPE_SCAN_REQ: /* Scan requests are only allowed for ADV_IND and SCAN_IND */ if ((ll_adv_pdu.header.adv.type != - BLE_ADV_HEADER_PDU_TYPE_ADV_IND && + BLE_ADV_HEADER_PDU_TYPE_ADV_IND && ll_adv_pdu.header.adv.type != - BLE_ADV_HEADER_PDU_TYPE_ADV_SCAN_IND) || - /* The advertising address needs to match */ + BLE_ADV_HEADER_PDU_TYPE_ADV_SCAN_IND) || + /* The advertising address needs to match */ (memcmp(&ll_rcv_packet.payload[BLUETOOTH_ADDR_OCTETS], &ll_adv_pdu.payload[0], BLUETOOTH_ADDR_OCTETS))) { /* Don't send the scan response */ radio_disable(); return rv; } - break; + break; case BLE_ADV_HEADER_PDU_TYPE_CONNECT_REQ: /* Don't send a scan response */ radio_disable(); /* Connecting is only allowed for ADV_IND and ADV_DIRECT_IND */ if (ll_adv_pdu.header.adv.type != - BLE_ADV_HEADER_PDU_TYPE_ADV_IND && + BLE_ADV_HEADER_PDU_TYPE_ADV_IND && ll_adv_pdu.header.adv.type != - BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND) + BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND) return rv; /* The advertising address needs to match */ if (memcmp(&ll_rcv_packet.payload[BLUETOOTH_ADDR_OCTETS], @@ -589,9 +590,9 @@ int ble_ll_adv(int chan) return rv; /* The InitAddr address needs to match for ADV_DIRECT_IND */ if (ll_adv_pdu.header.adv.type == - BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND && - memcmp(&ll_adv_pdu.payload[BLUETOOTH_ADDR_OCTETS], - &ll_rcv_packet.payload[0], BLUETOOTH_ADDR_OCTETS)) + BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND && + memcmp(&ll_adv_pdu.payload[BLUETOOTH_ADDR_OCTETS], + &ll_rcv_packet.payload[0], BLUETOOTH_ADDR_OCTETS)) return rv; /* Mark time that connect was received */ @@ -604,11 +605,11 @@ int ble_ll_adv(int chan) ll_state = CONNECTION; return rv; - break; + break; default: /* Unhandled response packet */ radio_disable(); return rv; - break; + break; } CPRINTF("ADV %u Response %u %u\n", tx_end, rsp_end, tx_rsp_end); @@ -632,7 +633,6 @@ int ble_ll_adv_event(void) return rv; } - void print_connection_state(void) { CPRINTF("vvvvvvvvvvvvvvvvvvvCONNECTION STATEvvvvvvvvvvvvvvvvvvv\n"); @@ -663,29 +663,29 @@ int connected_communicate(void) if (num_consecutive_failures > 0) { ble_radio_init(conn_params.access_addr, - conn_params.crc_init_val); + conn_params.crc_init_val); NRF51_RADIO_FREQUENCY = NRF51_RADIO_FREQUENCY_VAL(chan2freq(comm_channel)); NRF51_RADIO_DATAWHITEIV = comm_channel; - listen_time = last_receive_time + conn_params.connInterval - - get_time().val + conn_params.transmitWindowSize; + listen_time = last_receive_time + conn_params.connInterval - + get_time().val + conn_params.transmitWindowSize; /* * This listens for 1.25 times the expected amount * of time. This is a margin of error. This line is * only called when a connection has failed (a missed - * packet). The slave and the master could have + * packet). The peripheral and the controller could have * missed this packet due to a disagreement on when * the packet should have arrived. We listen for * slightly longer than expected in the case that * there was a timing disagreement. */ - rv = ble_rx(&ll_rcv_packet, - listen_time + (listen_time >> 2), 0); + rv = ble_rx(&ll_rcv_packet, listen_time + (listen_time >> 2), + 0); } else { if (!is_first_data_packet) { - sleep_time = receive_time + - conn_params.connInterval - get_time().val; + sleep_time = receive_time + conn_params.connInterval - + get_time().val; /* * The time slept is 31/32 (96.875%) of the calculated * required sleep time because the code to receive @@ -695,8 +695,8 @@ int connected_communicate(void) } else { last_receive_time = time_of_connect_req; sleep_time = TRANSMIT_WINDOW_OFFSET_CONSTANT + - conn_params.transmitWindowOffset + - time_of_connect_req - get_time().val; + conn_params.transmitWindowOffset + + time_of_connect_req - get_time().val; if (sleep_time >= 0) { /* * Radio is on for longer than needed for first @@ -709,7 +709,7 @@ int connected_communicate(void) } ble_radio_init(conn_params.access_addr, - conn_params.crc_init_val); + conn_params.crc_init_val); NRF51_RADIO_FREQUENCY = NRF51_RADIO_FREQUENCY_VAL(chan2freq(comm_channel)); NRF51_RADIO_DATAWHITEIV = comm_channel; @@ -722,14 +722,13 @@ int connected_communicate(void) * how early the window opens in microseconds. */ if (!is_first_data_packet) - offset = last_receive_time + conn_params.connInterval - - get_time().val; + offset = last_receive_time + conn_params.connInterval - + get_time().val; else offset = 0; rv = ble_rx(&ll_rcv_packet, - offset + conn_params.transmitWindowSize, - 0); + offset + conn_params.transmitWindowSize, 0); } /* @@ -766,9 +765,9 @@ void bluetooth_ll_task(void) case ADVERTISING: if (deadline.val == 0) { - CPRINTS("ADV @%pP", &ll_adv_pdu); + CPRINTS("ADV @%p", &ll_adv_pdu); deadline.val = get_time().val + - (uint32_t)ll_adv_timeout_us; + (uint32_t)ll_adv_timeout_us; ll_adv_events = 0; } @@ -786,7 +785,7 @@ void bluetooth_ll_task(void) ll_state = STANDBY; break; } - break; + break; case STANDBY: deadline.val = 0; CPRINTS("Standby %d events", ll_adv_events); @@ -795,20 +794,20 @@ void bluetooth_ll_task(void) task_wait_event(-1); connection_initialized = 0; errors_recovered = 0; - break; + break; case TEST_RX: if (ble_test_rx() == HCI_SUCCESS) ll_test_packets++; /* Packets come every 625us, sleep to save power */ usleep(300); - break; + break; case TEST_TX: start = get_time().le.lo; ble_test_tx(); ll_test_packets++; end = get_time().le.lo; - usleep(625 - 82 - (end-start)); /* 625us */ - break; + usleep(625 - 82 - (end - start)); /* 625us */ + break; case UNINITIALIZED: ble_radio_init(BLE_ADV_ACCESS_ADDRESS, BLE_ADV_CRCINIT); ll_adv_events = 0; @@ -816,7 +815,7 @@ void bluetooth_ll_task(void) connection_initialized = 0; packet_tb_sent = &tx_packet_1; set_empty_data_packet(&tx_packet_1); - break; + break; case CONNECTION: if (!connection_initialized) { if (initialize_connection() != HCI_SUCCESS) { @@ -835,8 +834,7 @@ void bluetooth_ll_task(void) } else { num_consecutive_failures++; if ((get_time().val - last_rx_time) > - conn_params.connSupervisionTimeout) { - + conn_params.connSupervisionTimeout) { ll_state = STANDBY; CPRINTF("EXITING CONNECTION STATE " "DUE TO TIMEOUT.\n"); @@ -847,10 +845,11 @@ void bluetooth_ll_task(void) if (ll_state == STANDBY) { CPRINTF("Exiting connection state/Entering " "Standby state after %d connections " - "events\n", ll_conn_events); + "events\n", + ll_conn_events); print_connection_state(); } - break; + break; default: CPRINTS("Unhandled State ll_state = %d", ll_state); ll_state = UNINITIALIZED; @@ -858,4 +857,3 @@ void bluetooth_ll_task(void) } } } - diff --git a/common/build.mk b/common/build.mk index ebaa3cc582..1a61295085 100644 --- a/common/build.mk +++ b/common/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # @@ -10,25 +10,29 @@ _common_dir:=$(dir $(lastword $(MAKEFILE_LIST))) common-y=util.o -common-y+=version.o printf.o queue.o queue_policies.o +common-y+=version.o printf.o queue.o queue_policies.o irq_locking.o +common-y+=gettimeofday.o common-$(CONFIG_ACCELGYRO_BMI160)+=math_util.o +common-$(CONFIG_ACCELGYRO_BMI220)+=math_util.o common-$(CONFIG_ACCELGYRO_BMI260)+=math_util.o +common-$(CONFIG_ACCELGYRO_BMI3XX)+=math_util.o common-$(CONFIG_ACCELGYRO_ICM426XX)+=math_util.o +common-$(CONFIG_ACCELGYRO_ICM42607)+=math_util.o common-$(CONFIG_ACCELGYRO_LSM6DS0)+=math_util.o common-$(CONFIG_ACCELGYRO_LSM6DSM)+=math_util.o common-$(CONFIG_ACCELGYRO_LSM6DSO)+=math_util.o common-$(CONFIG_ACCEL_FIFO)+=motion_sense_fifo.o common-$(CONFIG_ACCEL_BMA255)+=math_util.o +common-$(CONFIG_ACCEL_BMA4XX)+=math_util.o common-$(CONFIG_ACCEL_LIS2DW12)+=math_util.o common-$(CONFIG_ACCEL_LIS2DH)+=math_util.o common-$(CONFIG_ACCEL_LIS2DS)+=math_util.o common-$(CONFIG_ACCEL_KXCJ9)+=math_util.o common-$(CONFIG_ACCEL_KX022)+=math_util.o -ifneq ($(CORE),cortex-m) -common-$(CONFIG_AES)+=aes.o -endif -common-$(CONFIG_AES_GCM)+=aes-gcm.o +common-$(CONFIG_BODY_DETECTION)+=math_util.o +common-$(CONFIG_TEMP_SENSOR_TMP112)+=math_util.o +common-$(CONFIG_TEMP_SENSOR_PCT2075)+=math_util.o common-$(CONFIG_CMD_ADC)+=adc.o common-$(HAS_TASK_ALS)+=als.o common-$(CONFIG_AP_HANG_DETECT)+=ap_hang_detect.o @@ -40,25 +44,41 @@ common-$(CONFIG_BACKLIGHT_LID)+=backlight_lid.o common-$(CONFIG_BASE32)+=base32.o common-$(CONFIG_BLINK)+=blink.o common-$(CONFIG_DETACHABLE_BASE)+=base_state.o -common-$(CONFIG_BATTERY)+=battery.o +common-$(CONFIG_BATTERY)+=battery.o math_util.o +common-$(CONFIG_BATTERY_CONFIG_IN_CBI)+=battery_config.o +common-$(CONFIG_BATTERY_V1)+=battery_v1.o +common-$(CONFIG_BATTERY_V2)+=battery_v2.o common-$(CONFIG_BATTERY_FUEL_GAUGE)+=battery_fuel_gauge.o common-$(CONFIG_BLUETOOTH_LE)+=bluetooth_le.o common-$(CONFIG_BLUETOOTH_LE_STACK)+=btle_hci_controller.o btle_ll.o common-$(CONFIG_BODY_DETECTION)+=body_detection.o common-$(CONFIG_CAPSENSE)+=capsense.o common-$(CONFIG_CEC)+=cec.o -common-$(CONFIG_CROS_BOARD_INFO)+=cbi.o +common-$(CONFIG_CBI_EEPROM)+=cbi.o cbi_eeprom.o +common-$(CONFIG_USB_PD_FLAGS)+=usb_pd_flags.o +common-$(CONFIG_CBI_GPIO)+=cbi.o cbi_gpio.o +ifeq ($(HAS_MOCK_CHARGE_MANAGER),) common-$(CONFIG_CHARGE_MANAGER)+=charge_manager.o +endif common-$(CONFIG_CHARGE_RAMP_HW)+=charge_ramp.o common-$(CONFIG_CHARGE_RAMP_SW)+=charge_ramp.o charge_ramp_sw.o +common-$(CONFIG_CHARGESPLASH)+=chargesplash.o +common-$(CONFIG_CHIP_INIT_ROM_REGION)+=init_rom.o common-$(CONFIG_CMD_CHARGEN) += chargen.o -common-$(CONFIG_CHARGER)+=charger.o charge_state_v2.o +common-$(CONFIG_CHARGER)+=charger.o +ifneq ($(CONFIG_CHARGER),) +common-$(CONFIG_BATTERY)+=charge_state.o +endif +ifneq ($(CONFIG_EC_EC_COMM_BATTERY_CLIENT),) +common-$(CONFIG_BATTERY)+=charger_base.o +endif common-$(CONFIG_CHARGER_PROFILE_OVERRIDE_COMMON)+=charger_profile_override.o common-$(CONFIG_CMD_I2CWEDGE)+=i2c_wedge.o common-$(CONFIG_COMMON_GPIO)+=gpio.o gpio_commands.o -common-$(CONFIG_IO_EXPANDER)+=ioexpander.o +common-$(CONFIG_IO_EXPANDER)+=ioexpander.o ioexpander_commands.o common-$(CONFIG_COMMON_PANIC_OUTPUT)+=panic_output.o -common-$(CONFIG_COMMON_RUNTIME)+=hooks.o main.o system.o peripheral.o init_rom.o +common-$(CONFIG_COMMON_RUNTIME)+=hooks.o main.o system.o peripheral.o \ + system_boot_time.o common-$(CONFIG_COMMON_TIMER)+=timer.o common-$(CONFIG_CRC8)+= crc8.o common-$(CONFIG_CURVE25519)+=curve25519.o @@ -69,32 +89,36 @@ common-$(CONFIG_DEDICATED_RECOVERY_BUTTON)+=button.o common-$(CONFIG_DEVICE_EVENT)+=device_event.o common-$(CONFIG_DEVICE_STATE)+=device_state.o common-$(CONFIG_DPTF)+=dptf.o -common-$(CONFIG_EC_EC_COMM_MASTER)+=ec_ec_comm_master.o -common-$(CONFIG_EC_EC_COMM_SLAVE)+=ec_ec_comm_slave.o -common-$(CONFIG_HOSTCMD_ESPI)+=espi.o +common-$(CONFIG_EC_EC_COMM_CLIENT)+=ec_ec_comm_client.o +common-$(CONFIG_EC_EC_COMM_SERVER)+=ec_ec_comm_server.o +common-$(CONFIG_HOST_INTERFACE_ESPI)+=espi.o common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o common-$(CONFIG_EXTPOWER)+=extpower_common.o common-$(CONFIG_FANS)+=fan.o pwm.o -common-$(CONFIG_FLASH)+=flash.o +common-$(CONFIG_FLASH_CROS)+=flash.o common-$(CONFIG_FMAP)+=fmap.o common-$(CONFIG_GESTURE_SW_DETECTION)+=gesture.o common-$(CONFIG_HOSTCMD_EVENTS)+=host_event_commands.o common-$(CONFIG_HOSTCMD_GET_UPTIME_INFO)+=uptime.o -common-$(CONFIG_HOSTCMD_PD)+=host_command_master.o +common-$(CONFIG_HOSTCMD_PD)+=host_command_controller.o common-$(CONFIG_HOSTCMD_REGULATOR)+=regulator.o common-$(CONFIG_HOSTCMD_RTC)+=rtc.o common-$(CONFIG_I2C_DEBUG)+=i2c_trace.o common-$(CONFIG_I2C_HID_TOUCHPAD)+=i2c_hid_touchpad.o -common-$(CONFIG_I2C_MASTER)+=i2c_master.o -common-$(CONFIG_I2C_SLAVE)+=i2c_slave.o +common-$(CONFIG_I2C_CONTROLLER)+=i2c_controller.o +common-$(CONFIG_I2C_CONTROLLER)+=i2c_controller_cros_ec.o +common-$(CONFIG_I2C_PERIPHERAL)+=i2c_peripheral.o common-$(CONFIG_I2C_BITBANG)+=i2c_bitbang.o common-$(CONFIG_I2C_VIRTUAL_BATTERY)+=virtual_battery.o common-$(CONFIG_INDUCTIVE_CHARGING)+=inductive_charging.o common-$(CONFIG_KEYBOARD_PROTOCOL_8042)+=keyboard_8042.o \ keyboard_8042_sharedlib.o -common-$(CONFIG_KEYBOARD_PROTOCOL_MKBP)+=keyboard_mkbp.o +common-$(CONFIG_KEYBOARD_PROTOCOL_MKBP)+=keyboard_mkbp.o mkbp_fifo.o \ + mkbp_info.o common-$(CONFIG_KEYBOARD_TEST)+=keyboard_test.o common-$(CONFIG_KEYBOARD_VIVALDI)+=keyboard_vivaldi.o +common-$(CONFIG_MKBP_INPUT_DEVICES)+=mkbp_input_devices.o mkbp_fifo.o \ + mkbp_info.o common-$(CONFIG_LED_COMMON)+=led_common.o common-$(CONFIG_LED_POLICY_STD)+=led_policy_std.o common-$(CONFIG_LED_PWM)+=led_pwm.o @@ -108,15 +132,19 @@ common-$(CONFIG_MAG_CALIBRATE)+= mag_cal.o math_util.o vec3.o mat33.o mat44.o \ common-$(CONFIG_MKBP_EVENT)+=mkbp_event.o common-$(CONFIG_OCPC)+=ocpc.o common-$(CONFIG_ONEWIRE)+=onewire.o +common-$(CONFIG_ORIENTATION_SENSOR)+=motion_orientation.o common-$(CONFIG_PECI_COMMON)+=peci.o +common-$(CONFIG_PERIPHERAL_CHARGER)+=peripheral_charger.o common-$(CONFIG_POWER_BUTTON)+=power_button.o common-$(CONFIG_POWER_BUTTON_X86)+=power_button_x86.o common-$(CONFIG_PSTORE)+=pstore_commands.o common-$(CONFIG_PWM)+=pwm.o common-$(CONFIG_PWM_KBLIGHT)+=pwm_kblight.o common-$(CONFIG_KEYBOARD_BACKLIGHT)+=keyboard_backlight.o -common-$(CONFIG_RSA)+=rsa.o +common-$(CONFIG_RGB_KEYBOARD)+=rgb_keyboard.o +common-$(CONFIG_RNG)+=trng.o common-$(CONFIG_ROLLBACK)+=rollback.o +common-$(CONFIG_RSA)+=rsa.o common-$(CONFIG_RWSIG)+=rwsig.o vboot/common.o common-$(CONFIG_RWSIG_TYPE_RWSIG)+=vboot/vb21_lib.o common-$(CONFIG_MATH_UTIL)+=math_util.o @@ -124,12 +152,17 @@ common-$(CONFIG_ONLINE_CALIB)+=stillness_detector.o kasa.o math_util.o \ mat44.o vec3.o newton_fit.o accel_cal.o online_calibration.o \ mkbp_event.o mag_cal.o math_util.o mat33.o gyro_cal.o gyro_still_det.o common-$(CONFIG_SHA1)+= sha1.o -common-$(CONFIG_SHA256)+=sha256.o +ifeq ($(CONFIG_SHA256),y) +# use the standard software SHA256 lib if the chip cannot support SHA256 +# hardware accelerator. +ifeq ($(CONFIG_SHA256_HW_ACCELERATE),) +common-y+=sha256.o +endif +endif common-$(CONFIG_SOFTWARE_CLZ)+=clz.o common-$(CONFIG_SOFTWARE_CTZ)+=ctz.o common-$(CONFIG_CMD_SPI_XFER)+=spi_commands.o -common-$(CONFIG_SPI_FLASH)+=spi_flash.o spi_flash_reg.o -common-$(CONFIG_SPI_FLASH_REGS)+=spi_flash_reg.o +common-$(CONFIG_SPI_FLASH)+=spi_flash.o common-$(CONFIG_SPI_NOR)+=spi_nor.o common-$(CONFIG_SWITCH)+=switch.o common-$(CONFIG_SW_CRC)+=crc.o @@ -140,48 +173,76 @@ common-$(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT)+=throttle_ap.o common-$(CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE)+=throttle_ap.o common-$(CONFIG_USB_CHARGER)+=usb_charger.o common-$(CONFIG_USB_CONSOLE_STREAM)+=usb_console_stream.o +common-$(CONFIG_HOST_INTERFACE_USB)+=usb_host_command.o common-$(CONFIG_USB_I2C)+=usb_i2c.o common-$(CONFIG_USB_PORT_POWER_DUMB)+=usb_port_power_dumb.o common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o common-$(CONFIG_HAS_TASK_PD_INT)+=usbc_intr_task.o ifneq ($(CONFIG_USB_POWER_DELIVERY),) -common-$(CONFIG_USB_POWER_DELIVERY)+=usb_common.o +common-$(CONFIG_USB_POWER_DELIVERY)+=usb_common.o usb_pd_pdo.o typec_control.o ifneq ($(CONFIG_USB_PD_TCPMV1),) -common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o +common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o \ + usb_pd_pdo.o endif common-$(CONFIG_USB_PD_DUAL_ROLE)+=usb_pd_dual_role.o common-$(CONFIG_USB_PD_HOST_CMD)+=usb_pd_host_cmd.o common-$(CONFIG_USB_PD_CONSOLE_CMD)+=usb_pd_console_cmd.o endif -common-$(CONFIG_USB_PD_ALT_MODE_DFP)+=usb_pd_alt_mode_dfp.o +common-$(CONFIG_USB_PD_DISCOVERY)+=usb_pd_discovery.o +common-$(CONFIG_USB_PD_ALT_MODE_UFP)+=usb_pd_alt_mode_ufp.o +common-$(CONFIG_USB_PD_DPS)+=dps.o common-$(CONFIG_USB_PD_LOGGING)+=event_log.o pd_log.o common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o common-$(CONFIG_USB_UPDATE)+=usb_update.o update_fw.o +common-$(CONFIG_USBC_OCP)+=usbc_ocp.o common-$(CONFIG_USBC_PPC)+=usbc_ppc.o common-$(CONFIG_VBOOT_EFS)+=vboot/vboot.o common-$(CONFIG_VBOOT_EFS2)+=vboot/efs2.o -common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o +ifeq ($(CONFIG_VBOOT_HASH),y) +common-y+=vboot_hash.o +# use the standard software SHA256 lib if the chip cannot support SHA256 +# hardware accelerator. +ifeq ($(CONFIG_SHA256_HW_ACCELERATE),) +common-y+=sha256.o +endif +endif common-$(CONFIG_VOLUME_BUTTONS)+=button.o common-$(CONFIG_VSTORE)+=vstore.o common-$(CONFIG_WEBUSB_URL)+=webusb_desc.o common-$(CONFIG_WIRELESS)+=wireless.o common-$(HAS_TASK_CHIPSET)+=chipset.o -common-$(HAS_TASK_CONSOLE)+=console.o console_output.o uart_buffering.o +common-$(HAS_TASK_CONSOLE)+=console.o console_output.o +common-$(HAS_TASK_CONSOLE)+=uart_buffering.o uart_hostcmd.o uart_printf.o common-$(CONFIG_CMD_MEM)+=memory_commands.o common-$(HAS_TASK_HOSTCMD)+=host_command.o ec_features.o common-$(HAS_TASK_PDCMD)+=host_command_pd.o common-$(HAS_TASK_KEYSCAN)+=keyboard_scan.o common-$(HAS_TASK_LIGHTBAR)+=lb_common.o lightbar.o common-$(HAS_TASK_MOTIONSENSE)+=motion_sense.o +common-$(CONFIG_SYSTEM_SAFE_MODE)+=system_safe_mode.o ifneq ($(HAVE_PRIVATE_AUDIO_CODEC_WOV_LIBS),y) common-$(CONFIG_AUDIO_CODEC_WOV)+=hotword_dsp_api.o endif -ifneq ($(CONFIG_COMMON_RUNTIME),) +ifeq ($(USE_BUILTIN_STDLIB), 0) +common-y+=shared_mem_libc.o +else ifneq ($(CONFIG_COMMON_RUNTIME),) +ifeq ($(CONFIG_DFU_BOOTMANAGER_MAIN),ro) +# Ordinary RO is replaced with DFU bootloader stub, CONFIG_MALLOC should only affect RW. +ifeq ($(CONFIG_MALLOC),y) +common-rw+=shmalloc.o +else ifeq ($(CONFIG_MALLOC),rw) +common-rw+=shmalloc.o +else +common-rw+=shared_mem.o +endif +else +# CONFIG_MALLOC affects both RO and RW as usual (with shared_mem in case it is disabled.) common-$(CONFIG_MALLOC)+=shmalloc.o common-$(call not_cfg,$(CONFIG_MALLOC))+=shared_mem.o endif +endif ifeq ($(CTS_MODULE),) common-$(TEST_BUILD)+=test_util.o @@ -194,11 +255,6 @@ $(out)/RW/common/rsa.o: CFLAGS+=-O3 $(out)/RO/common/rsa.o: CFLAGS+=-O3 endif -# AES-GCM code needs C99, else we'd have to move many variables declarations -# around. -$(out)/RW/common/aes-gcm.o: CFLAGS+=-std=c99 -Wno-declaration-after-statement -$(out)/RO/common/aes-gcm.o: CFLAGS+=-std=c99 -Wno-declaration-after-statement - ifneq ($(CONFIG_BOOTBLOCK),) ifdef BOOTBLOCK @@ -220,10 +276,6 @@ $(out)/.fake-bootblock: endif # BOOTBLOCK -build-util-bin += gen_emmc_transfer_data - -# Bootblock is only packed in RO image. -$(out)/util/gen_emmc_transfer_data: BUILD_LDFLAGS += -DSECTION_IS_RO=$(EMPTY) $(out)/bootblock_data.h: $(out)/util/gen_emmc_transfer_data $(out)/.bootblock $(call quiet,emmc_bootblock,BTBLK ) @@ -280,37 +332,9 @@ $(out)/rma_key_from_blob.h: board/$(BOARD)/$(BLOB_FILE) util/bin2h.sh endif -# Build and link against libcryptoc. -ifeq ($(CONFIG_LIBCRYPTOC),y) -CRYPTOCLIB := $(realpath ../../third_party/cryptoc) -ifneq ($(BOARD),host) -CPPFLAGS += -I$(abspath ./builtin) -endif -CPPFLAGS += -I$(CRYPTOCLIB)/include -CRYPTOC_LDFLAGS := -L$(out)/cryptoc -lcryptoc - -# Force the external build each time, so it can look for changed sources. -.PHONY: $(out)/cryptoc/libcryptoc.a -$(out)/cryptoc/libcryptoc.a: - +$(call quiet,libcryptoc,MAKE ) - -# Link RO and RW against cryptoc. -$(out)/RO/ec.RO.elf $(out)/RO/ec.RO_B.elf: LDFLAGS_EXTRA += $(CRYPTOC_LDFLAGS) -$(out)/RO/ec.RO.elf $(out)/RO/ec.RO_B.elf: $(out)/cryptoc/libcryptoc.a -$(out)/RW/ec.RW.elf $(out)/RW/ec.RW_B.elf: LDFLAGS_EXTRA += $(CRYPTOC_LDFLAGS) -$(out)/RW/ec.RW.elf $(out)/RW/ec.RW_B.elf: $(out)/cryptoc/libcryptoc.a -# Host test executables (including fuzz tests). -$(out)/$(PROJECT).exe: LDFLAGS_EXTRA += $(CRYPTOC_LDFLAGS) -$(out)/$(PROJECT).exe: $(out)/cryptoc/libcryptoc.a -# On-device tests. -test-targets=$(foreach test,$(test-list-y),\ - $(out)/RW/$(test).RW.elf $(out)/RO/$(test).RO.elf) -$(test-targets): LDFLAGS_EXTRA += $(CRYPTOC_LDFLAGS) -$(test-targets): $(out)/cryptoc/libcryptoc.a -endif - include $(_common_dir)fpsensor/build.mk include $(_common_dir)usbc/build.mk +include $(_common_dir)spi/build.mk include $(_common_dir)mock/build.mk common-y+=$(foreach m,$(mock-y),mock/$(m)) diff --git a/common/button.c b/common/button.c index 6f346ec7cb..27cd8ae058 100644 --- a/common/button.c +++ b/common/button.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,10 +12,11 @@ #include "compile_time_macros.h" #include "console.h" #include "gpio.h" -#include "host_command.h" #include "hooks.h" +#include "host_command.h" #include "keyboard_protocol.h" #include "led_common.h" +#include "mkbp_input_devices.h" #include "power_button.h" #include "system.h" #include "timer.h" @@ -23,16 +24,16 @@ #include "watchdog.h" /* Console output macro */ -#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ##args) struct button_state_t { uint64_t debounce_time; int debounced_pressed; }; -static struct button_state_t __bss_slow state[BUTTON_COUNT]; +static struct button_state_t state[BUTTON_COUNT]; -static uint64_t __bss_slow next_deferred_time; +static uint64_t next_deferred_time; #if defined(CONFIG_CMD_BUTTON) || defined(CONFIG_HOSTCMD_BUTTON) #define CONFIG_SIMULATED_BUTTON @@ -42,7 +43,7 @@ static uint64_t __bss_slow next_deferred_time; /* Bitmask to keep track of simulated state of each button. * Bit numbers are aligned to enum button. */ -static int sim_button_state; +static atomic_t sim_button_state; /* * Flip state of associated button type in sim_button_state bitmask. @@ -61,7 +62,7 @@ static int sim_button_state; */ static int simulated_button_pressed(const struct button_config *button) { - return !!(sim_button_state & BIT(button->type)); + return !!((uint32_t)sim_button_state & BIT(button->type)); } #endif @@ -74,12 +75,12 @@ static int raw_button_pressed(const struct button_config *button) int simulated_value = 0; if (!(button->flags & BUTTON_FLAG_DISABLED)) { if (IS_ENABLED(CONFIG_ADC_BUTTONS) && - button_is_adc_detected(button->gpio)) { - physical_value = - adc_to_physical_value(button->gpio); + button_is_adc_detected(button->gpio)) { + physical_value = adc_to_physical_value(button->gpio); } else { - physical_value = (!!gpio_get_level(button->gpio) == - !!(button->flags & BUTTON_FLAG_ACTIVE_HIGH)); + physical_value = + (!!gpio_get_level(button->gpio) == + !!(button->flags & BUTTON_FLAG_ACTIVE_HIGH)); } #ifdef CONFIG_SIMULATED_BUTTON simulated_value = simulated_button_pressed(button); @@ -192,7 +193,7 @@ static int is_recovery_boot(void) if (system_jumped_to_this_image()) return 0; if (!(system_get_reset_flags() & - (EC_RESET_FLAG_RESET_PIN | EC_RESET_FLAG_POWER_ON))) + (EC_RESET_FLAG_RESET_PIN | EC_RESET_FLAG_POWER_ON))) return 0; if (!is_recovery_button_pressed()) return 0; @@ -201,7 +202,7 @@ static int is_recovery_boot(void) #endif /* CONFIG_BUTTON_TRIGGERED_RECOVERY */ static void button_reset(enum button button_type, - const struct button_config *button) + const struct button_config *button) { state[button_type].debounced_pressed = raw_button_pressed(button); state[button_type].debounce_time = 0; @@ -259,7 +260,6 @@ int button_disable_gpio(enum button button_type) } #endif - /* * Handle debounced button changing state. */ @@ -307,13 +307,15 @@ static void button_change_deferred(void) hook_call_deferred( &debug_mode_handle_data, 0); #endif - CPRINTS("Button '%s' was %s", - buttons[i].name, new_pressed ? - "pressed" : "released"); -#if defined(HAS_TASK_KEYPROTO) || defined(CONFIG_KEYBOARD_PROTOCOL_MKBP) - keyboard_update_button(buttons[i].type, - new_pressed); -#endif + CPRINTS("Button '%s' was %s", buttons[i].name, + new_pressed ? "pressed" : "released"); + if (IS_ENABLED(CONFIG_MKBP_INPUT_DEVICES)) { + mkbp_button_update(buttons[i].type, + new_pressed); + } else if (IS_ENABLED(HAS_TASK_KEYPROTO)) { + keyboard_update_button(buttons[i].type, + new_pressed); + } } /* Clear the debounce time to stop checking it */ @@ -323,10 +325,11 @@ static void button_change_deferred(void) * Make sure the next deferred call happens on or before * each button needs it. */ - soonest_debounce_time = (soonest_debounce_time == 0) ? - state[i].debounce_time : - MIN(soonest_debounce_time, - state[i].debounce_time); + soonest_debounce_time = + (soonest_debounce_time == 0) ? + state[i].debounce_time : + MIN(soonest_debounce_time, + state[i].debounce_time); } } @@ -385,11 +388,11 @@ static void simulate_button_release_deferred(void) /* Release the button */ for (button_idx = 0; button_idx < BUTTON_COUNT; button_idx++) { /* Check state for button pressed */ - if (sim_button_state & BIT(buttons[button_idx].type)) { + if ((uint32_t)sim_button_state & + BIT(buttons[button_idx].type)) { /* Set state of the button as released */ - deprecated_atomic_clear_bits( - &sim_button_state, - BIT(buttons[button_idx].type)); + atomic_clear_bits(&sim_button_state, + BIT(buttons[button_idx].type)); button_interrupt_simulate(button_idx); } @@ -405,8 +408,8 @@ static void simulate_button(uint32_t button_mask, int press_ms) for (button_idx = 0; button_idx < BUTTON_COUNT; button_idx++) { if (button_mask & BIT(button_idx)) { /* Set state of the button as pressed */ - deprecated_atomic_or(&sim_button_state, - BIT(buttons[button_idx].type)); + atomic_or(&sim_button_state, + BIT(buttons[button_idx].type)); button_interrupt_simulate(button_idx); } @@ -414,12 +417,12 @@ static void simulate_button(uint32_t button_mask, int press_ms) /* Defer the button release for specified duration */ hook_call_deferred(&simulate_button_release_deferred_data, - press_ms * MSEC); + press_ms * MSEC); } #endif /* #ifdef CONFIG_SIMULATED_BUTTON */ #ifdef CONFIG_CMD_BUTTON -static int console_command_button(int argc, char **argv) +static int console_command_button(int argc, const char **argv) { int press_ms = 50; char *e; @@ -461,8 +464,7 @@ static int console_command_button(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(button, console_command_button, - "vup|vdown|rec msec", +DECLARE_CONSOLE_COMMAND(button, console_command_button, "vup|vdown|rec msec", "Simulate button press"); #endif /* CONFIG_CMD_BUTTON */ @@ -490,7 +492,6 @@ DECLARE_HOST_COMMAND(EC_CMD_BUTTON, host_command_button, EC_VER_MASK(0)); #endif /* CONFIG_HOSTCMD_BUTTON */ - #ifdef CONFIG_EMULATED_SYSRQ #ifdef CONFIG_DEDICATED_RECOVERY_BUTTON @@ -531,21 +532,10 @@ static void debug_mode_handle(void) #else /* CONFIG_DEDICATED_RECOVERY_BUTTON */ -enum debug_state { - STATE_DEBUG_NONE, - STATE_DEBUG_CHECK, - STATE_STAGING, - STATE_DEBUG_MODE_ACTIVE, - STATE_SYSRQ_PATH, - STATE_WARM_RESET_PATH, - STATE_SYSRQ_EXEC, - STATE_WARM_RESET_EXEC, -}; - -#define DEBUG_BTN_POWER BIT(0) -#define DEBUG_BTN_VOL_UP BIT(1) -#define DEBUG_BTN_VOL_DN BIT(2) -#define DEBUG_TIMEOUT (10 * SECOND) +#define DEBUG_BTN_POWER BIT(0) +#define DEBUG_BTN_VOL_UP BIT(1) +#define DEBUG_BTN_VOL_DN BIT(2) +#define DEBUG_TIMEOUT (10 * SECOND) static enum debug_state curr_debug_state = STATE_DEBUG_NONE; static enum debug_state next_debug_state = STATE_DEBUG_NONE; @@ -668,6 +658,16 @@ static void debug_mode_transition(enum debug_state next_state) #endif } +__test_only void reset_button_debug_state(void) +{ + debug_mode_transition(STATE_DEBUG_NONE); +} + +__test_only enum debug_state get_button_debug_state(void) +{ + return curr_debug_state; +} + static void debug_mode_handle(void) { int mask; @@ -717,8 +717,9 @@ static void debug_mode_handle(void) * Schedule a deferred call in case timeout hasn't * occurred yet. */ - hook_call_deferred(&debug_mode_handle_data, - (debug_state_deadline.val - now.val)); + hook_call_deferred( + &debug_mode_handle_data, + (debug_state_deadline.val - now.val)); } break; @@ -848,20 +849,26 @@ struct button_config buttons[BUTTON_COUNT] = { #endif #if defined(CONFIG_DEDICATED_RECOVERY_BUTTON) +#ifndef CONFIG_DEDICATED_RECOVERY_BUTTON_FLAGS +#define CONFIG_DEDICATED_RECOVERY_BUTTON_FLAGS 0 +#endif [BUTTON_RECOVERY] = { .name = "Recovery", .type = KEYBOARD_BUTTON_RECOVERY, .gpio = GPIO_RECOVERY_L, .debounce_us = BUTTON_DEBOUNCE_US, - .flags = 0, + .flags = CONFIG_DEDICATED_RECOVERY_BUTTON_FLAGS, }, #ifdef CONFIG_DEDICATED_RECOVERY_BUTTON_2 +#ifndef CONFIG_DEDICATED_RECOVERY_BUTTON_2_FLAGS +#define CONFIG_DEDICATED_RECOVERY_BUTTON_2_FLAGS 0 +#endif [BUTTON_RECOVERY_2] = { .name = "Recovery2", .type = KEYBOARD_BUTTON_RECOVERY, .gpio = GPIO_RECOVERY_L_2, .debounce_us = BUTTON_DEBOUNCE_US, - .flags = 0, + .flags = CONFIG_DEDICATED_RECOVERY_BUTTON_2_FLAGS, } #endif /* defined(CONFIG_DEDICATED_RECOVERY_BUTTON_2) */ #endif /* defined(CONFIG_DEDICATED_RECOVERY_BUTTON) */ diff --git a/common/capsense.c b/common/capsense.c index b2413ac61f..2c2bbd6db5 100644 --- a/common/capsense.c +++ b/common/capsense.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,11 +9,12 @@ #include "hooks.h" #include "i2c.h" #include "keyboard_protocol.h" +#include "printf.h" #include "timer.h" /* Console output macro */ -#define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ##args) #define CAPSENSE_I2C_ADDR 0x08 #define CAPSENSE_MASK_BITS 8 @@ -24,8 +25,7 @@ static int capsense_read_bitmask(void) int rv; uint8_t val = 0; - rv = i2c_xfer(I2C_PORT_CAPSENSE, CAPSENSE_I2C_ADDR, - 0, 0, &val, 1); + rv = i2c_xfer(I2C_PORT_CAPSENSE, CAPSENSE_I2C_ADDR, 0, 0, &val, 1); if (rv) CPRINTS("%s failed: error %d", __func__, rv); @@ -49,11 +49,12 @@ static void capsense_change_deferred(void) static uint8_t cur_val; uint8_t new_val; int i, n, c; + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; new_val = capsense_read_bitmask(); if (new_val != cur_val) { - CPRINTF("[%pT capsense 0x%02x: ", - PRINTF_TIMESTAMP_NOW, new_val); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + CPRINTF("[%s capsense 0x%02x: ", ts_str, new_val); for (i = 0; i < CAPSENSE_MASK_BITS; i++) { /* See what changed */ n = (new_val >> i) & 0x01; diff --git a/common/cbi.c b/common/cbi.c index c6fa213807..3cbf630492 100644 --- a/common/cbi.c +++ b/common/cbi.c @@ -1,10 +1,11 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Cros Board Info */ +#include "chipset.h" #include "common.h" #include "console.h" #include "crc8.h" @@ -26,12 +27,12 @@ */ uint8_t cbi_crc8(const struct cbi_header *h) { - return crc8((uint8_t *)&h->crc + 1, - h->total_size - sizeof(h->magic) - sizeof(h->crc)); + return cros_crc8((uint8_t *)&h->crc + 1, + h->total_size - sizeof(h->magic) - sizeof(h->crc)); } -uint8_t *cbi_set_data(uint8_t *p, enum cbi_data_tag tag, - const void *buf, int size) +uint8_t *cbi_set_data(uint8_t *p, enum cbi_data_tag tag, const void *buf, + int size) { struct cbi_data *d = (struct cbi_data *)p; @@ -76,57 +77,41 @@ struct cbi_data *cbi_find_tag(const void *buf, enum cbi_data_tag tag) */ #ifndef HOST_TOOLS_BUILD -#define CPRINTS(format, args...) cprints(CC_SYSTEM, "CBI " format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, "CBI " format, ##args) -/* - * We allow EEPROMs with page size of 8 or 16. Use 8 to be the most compatible. - * This causes a little more overhead for writes, but we are not writing to the - * EEPROM outside of the factory process. - */ -#define EEPROM_PAGE_WRITE_SIZE 8 - -#define EEPROM_PAGE_WRITE_MS 5 -#define EC_ERROR_CBI_CACHE_INVALID EC_ERROR_INTERNAL_FIRST - -static int cached_read_result = EC_ERROR_CBI_CACHE_INVALID; -static uint8_t cbi[CBI_EEPROM_SIZE]; -static struct cbi_header * const head = (struct cbi_header *)cbi; +static int cache_status = CBI_CACHE_STATUS_INVALID; +static uint8_t cbi[CBI_IMAGE_SIZE]; +static struct cbi_header *const head = (struct cbi_header *)cbi; int cbi_create(void) { - struct cbi_header * const h = (struct cbi_header *)cbi; - memset(cbi, 0, sizeof(cbi)); - memcpy(h->magic, cbi_magic, sizeof(cbi_magic)); - h->total_size = sizeof(*h); - h->major_version = CBI_VERSION_MAJOR; - h->minor_version = CBI_VERSION_MINOR; - h->crc = cbi_crc8(h); - cached_read_result = EC_SUCCESS; + memcpy(head->magic, cbi_magic, sizeof(cbi_magic)); + head->total_size = sizeof(*head); + head->major_version = CBI_VERSION_MAJOR; + head->minor_version = CBI_VERSION_MINOR; + head->crc = cbi_crc8(head); + cache_status = CBI_CACHE_STATUS_SYNCED; return EC_SUCCESS; } void cbi_invalidate_cache(void) { - cached_read_result = EC_ERROR_CBI_CACHE_INVALID; + cache_status = CBI_CACHE_STATUS_INVALID; } -static int read_eeprom(uint8_t offset, uint8_t *in, int in_size) +int cbi_get_cache_status(void) { - return i2c_read_block(I2C_PORT_EEPROM, I2C_ADDR_EEPROM_FLAGS, - offset, in, in_size); + return cache_status; } -/* - * Get board information from EEPROM - */ -static int do_read_board_info(void) +static int do_cbi_read(void) { CPRINTS("Reading board info"); /* Read header */ - if (read_eeprom(0, cbi, sizeof(*head))) { + if (cbi_config.drv->load(0, cbi, sizeof(*head))) { CPRINTS("Failed to read header"); return EC_ERROR_INVAL; } @@ -143,23 +128,26 @@ static int do_read_board_info(void) return EC_ERROR_INVAL; } - /* Check the data size. It's expected to support up to 64k but our - * buffer has practical limitation. */ + /* + * Check the data size. It's expected to support up to 64k but our + * buffer has practical limitation. + */ if (head->total_size < sizeof(*head) || - sizeof(cbi) < head->total_size) { + head->total_size > CBI_IMAGE_SIZE) { CPRINTS("Bad size: %d", head->total_size); return EC_ERROR_OVERFLOW; } /* Read the data */ - if (read_eeprom(sizeof(*head), head->data, - head->total_size - sizeof(*head))) { + if (cbi_config.drv->load(sizeof(*head), head->data, + head->total_size - sizeof(*head))) { CPRINTS("Failed to read body"); return EC_ERROR_INVAL; } /* Check CRC. This supports new fields unknown to this parser. */ - if (cbi_crc8(head) != head->crc) { + if (cbi_config.storage_type != CBI_STORAGE_TYPE_GPIO && + cbi_crc8(head) != head->crc) { CPRINTS("Bad CRC"); return EC_ERROR_INVAL; } @@ -167,21 +155,28 @@ static int do_read_board_info(void) return EC_SUCCESS; } -static int read_board_info(void) +static int cbi_read(void) { - if (cached_read_result == EC_ERROR_CBI_CACHE_INVALID) { - cached_read_result = do_read_board_info(); - if (cached_read_result) - /* On error (I2C or bad contents), retry a read */ - cached_read_result = do_read_board_info(); + int i; + int rv; + + if (cbi_get_cache_status() == CBI_CACHE_STATUS_SYNCED) + return EC_SUCCESS; + + for (i = 0; i < 2; i++) { + rv = do_cbi_read(); + if (rv == EC_SUCCESS) { + cache_status = CBI_CACHE_STATUS_SYNCED; + return EC_SUCCESS; + } + /* On error (I2C or bad contents), retry a read */ } - /* Else, we already tried and know the result. Return the cached - * error code immediately to avoid wasteful reads. */ - return cached_read_result; + + return rv; } -__attribute__((weak)) -int cbi_board_override(enum cbi_data_tag tag, uint8_t *buf, uint8_t *size) +__attribute__((weak)) int cbi_board_override(enum cbi_data_tag tag, + uint8_t *buf, uint8_t *size) { return EC_SUCCESS; } @@ -190,7 +185,7 @@ int cbi_get_board_info(enum cbi_data_tag tag, uint8_t *buf, uint8_t *size) { const struct cbi_data *d; - if (read_board_info()) + if (cbi_read()) return EC_ERROR_UNKNOWN; d = cbi_find_tag(cbi, tag); @@ -221,7 +216,8 @@ static void cbi_remove_tag(void *const cbi, struct cbi_data *const d) h->total_size -= size; } -int cbi_set_board_info(enum cbi_data_tag tag, const uint8_t *buf, uint8_t size) +test_mockable int cbi_set_board_info(enum cbi_data_tag tag, const uint8_t *buf, + uint8_t size) { struct cbi_data *d; @@ -249,49 +245,17 @@ int cbi_set_board_info(enum cbi_data_tag tag, const uint8_t *buf, uint8_t size) return EC_SUCCESS; } -static int eeprom_is_write_protected(void) -{ -#ifdef CONFIG_WP_ACTIVE_HIGH - return gpio_get_level(GPIO_WP); -#else - return !gpio_get_level(GPIO_WP_L); -#endif /* CONFIG_WP_ACTIVE_HIGH */ -} - -static int write_board_info(void) +int cbi_write(void) { - const uint8_t *p = cbi; - int rest = head->total_size; - - if (eeprom_is_write_protected()) { - CPRINTS("Failed to write for WP"); + if (cbi_config.drv->is_protected()) { + CPRINTS("Failed to write due to WP"); return EC_ERROR_ACCESS_DENIED; } - while (rest > 0) { - int size = MIN(EEPROM_PAGE_WRITE_SIZE, rest); - int rv; - rv = i2c_write_block(I2C_PORT_EEPROM, I2C_ADDR_EEPROM_FLAGS, - p - cbi, p, size); - if (rv) { - CPRINTS("Failed to write for %d", rv); - return rv; - } - /* Wait for internal write cycle completion */ - msleep(EEPROM_PAGE_WRITE_MS); - p += size; - rest -= size; - } - - return EC_SUCCESS; + return cbi_config.drv->store(cbi); } -int cbi_write(void) -{ - return write_board_info(); -} - -int cbi_get_board_version(uint32_t *ver) +test_mockable int cbi_get_board_version(uint32_t *ver) { uint8_t size = sizeof(*ver); @@ -331,8 +295,7 @@ int cbi_get_ssfc(uint32_t *ssfc) { uint8_t size = sizeof(*ssfc); - return cbi_get_board_info(CBI_TAG_SSFC, (uint8_t *)ssfc, - &size); + return cbi_get_board_info(CBI_TAG_SSFC, (uint8_t *)ssfc, &size); } int cbi_get_pcb_supplier(uint32_t *pcb_supplier) @@ -340,7 +303,21 @@ int cbi_get_pcb_supplier(uint32_t *pcb_supplier) uint8_t size = sizeof(*pcb_supplier); return cbi_get_board_info(CBI_TAG_PCB_SUPPLIER, (uint8_t *)pcb_supplier, - &size); + &size); +} + +int cbi_get_rework_id(uint64_t *id) +{ + uint8_t size = sizeof(*id); + return cbi_get_board_info(CBI_TAG_REWORK_ID, (uint8_t *)id, &size); +} + +int cbi_get_factory_calibration_data(uint32_t *calibration_data) +{ + uint8_t size = sizeof(*calibration_data); + + return cbi_get_board_info(CBI_TAG_FACTORY_CALIBRATION_DATA, + (uint8_t *)calibration_data, &size); } static enum ec_status hc_cbi_get(struct host_cmd_handler_args *args) @@ -349,7 +326,7 @@ static enum ec_status hc_cbi_get(struct host_cmd_handler_args *args) uint8_t size = MIN(args->response_max, UINT8_MAX); if (p->flag & CBI_GET_RELOAD) - cached_read_result = EC_ERROR_CBI_CACHE_INVALID; + cbi_invalidate_cache(); if (cbi_get_board_info(p->tag, args->response, &size)) return EC_RES_INVALID_PARAM; @@ -357,26 +334,25 @@ static enum ec_status hc_cbi_get(struct host_cmd_handler_args *args) args->response_size = size; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_CROS_BOARD_INFO, - hc_cbi_get, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_GET_CROS_BOARD_INFO, hc_cbi_get, EC_VER_MASK(0)); -static enum ec_status hc_cbi_set(struct host_cmd_handler_args *args) +static enum ec_status +common_cbi_set(const struct __ec_align4 ec_params_set_cbi *p) { - const struct __ec_align4 ec_params_set_cbi *p = args->params; - /* * If we ultimately cannot write to the flash, then fail early unless * we are explicitly trying to write to the in-memory CBI only */ - if (eeprom_is_write_protected() && !(p->flag & CBI_SET_NO_SYNC)) { - CPRINTS("Failed to write for WP"); + if (cbi_config.drv->is_protected() && !(p->flag & CBI_SET_NO_SYNC)) { + CPRINTS("Failed to write due to WP"); return EC_RES_ACCESS_DENIED; } #ifndef CONFIG_SYSTEM_UNLOCKED - /* These fields are not allowed to be reprogrammed regardless the - * hardware WP state. They're considered as a part of the hardware. */ + /* + * These fields are not allowed to be reprogrammed regardless the + * hardware WP state. They're considered as a part of the hardware. + */ if (p->tag == CBI_TAG_BOARD_VERSION || p->tag == CBI_TAG_OEM_ID) return EC_RES_ACCESS_DENIED; #endif @@ -385,72 +361,79 @@ static enum ec_status hc_cbi_set(struct host_cmd_handler_args *args) memset(cbi, 0, sizeof(cbi)); memcpy(head->magic, cbi_magic, sizeof(cbi_magic)); head->total_size = sizeof(*head); - cached_read_result = EC_SUCCESS; } else { - if (read_board_info()) + if (cbi_read()) return EC_RES_ERROR; } - /* Given data size exceeds the packet size. */ - if (args->params_size < sizeof(*p) + p->size) - return EC_RES_INVALID_PARAM; - if (cbi_set_board_info(p->tag, p->data, p->size)) return EC_RES_INVALID_PARAM; - /* Whether we're modifying existing data or creating new one, - * we take over the format. */ + /* + * Whether we're modifying existing data or creating new one, + * we take over the format. + */ head->major_version = CBI_VERSION_MAJOR; head->minor_version = CBI_VERSION_MINOR; head->crc = cbi_crc8(head); + cache_status = CBI_CACHE_STATUS_SYNCED; /* Skip write if client asks so. */ if (p->flag & CBI_SET_NO_SYNC) return EC_RES_SUCCESS; /* We already checked write protect failure case. */ - if (write_board_info()) + if (cbi_write()) return EC_RES_ERROR; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_SET_CROS_BOARD_INFO, - hc_cbi_set, - EC_VER_MASK(0)); -#ifdef CONFIG_CMD_CBI -static void dump_flash(void) +static enum ec_status hc_cbi_set(struct host_cmd_handler_args *args) { - uint8_t buf[16]; - int i; - for (i = 0; i < CBI_EEPROM_SIZE; i += sizeof(buf)) { - if (read_eeprom(i, buf, sizeof(buf))) { - ccprintf("\nFailed to read EEPROM\n"); - return; - } - hexdump(buf, sizeof(buf)); - } + const struct __ec_align4 ec_params_set_cbi *p = args->params; + + /* Given data size exceeds the packet size. */ + if (args->params_size < sizeof(*p) + p->size) + return EC_RES_INVALID_PARAM; + + return common_cbi_set(p); } +DECLARE_HOST_COMMAND(EC_CMD_SET_CROS_BOARD_INFO, hc_cbi_set, EC_VER_MASK(0)); -static void print_tag(const char * const tag, int rv, const uint32_t *val) +#ifdef CONFIG_CMD_CBI +static void print_tag(const char *const tag, int rv, const uint32_t *val) { - ccprintf(tag); + ccprintf("%s", tag); if (rv == EC_SUCCESS && val) ccprintf(": %u (0x%x)\n", *val, *val); else ccprintf(": (Error %d)\n", rv); } +static void print_uint64_tag(const char *const tag, int rv, + const uint64_t *lval) +{ + ccprintf("%s", tag); + if (rv == EC_SUCCESS && lval) + ccprintf(": %llu (0x%llx)\n", *(unsigned long long *)lval, + *(unsigned long long *)lval); + else + ccprintf(": (Error %d)\n", rv); +} + static void dump_cbi(void) { uint32_t val; + uint64_t lval; /* Ensure we read the latest data from flash. */ - cached_read_result = EC_ERROR_CBI_CACHE_INVALID; - read_board_info(); + cbi_invalidate_cache(); + cbi_read(); - if (cached_read_result != EC_SUCCESS) { - ccprintf("Cannot Read CBI (Error %d)\n", cached_read_result); + if (cbi_get_cache_status() != CBI_CACHE_STATUS_SYNCED) { + ccprintf("Cannot Read CBI (Error %d)\n", + cbi_get_cache_status()); return; } @@ -464,15 +447,161 @@ static void dump_cbi(void) print_tag("FW_CONFIG", cbi_get_fw_config(&val), &val); print_tag("PCB_SUPPLIER", cbi_get_pcb_supplier(&val), &val); print_tag("SSFC", cbi_get_ssfc(&val), &val); + print_uint64_tag("REWORK_ID", cbi_get_rework_id(&lval), &lval); +} + +/* + * Space for the set command (does not include data space) plus maximum + * possible console input + */ +static uint8_t + buf[sizeof(struct ec_params_set_cbi) + CONFIG_CONSOLE_INPUT_LINE_SIZE]; + +static int cc_cbi(int argc, const char **argv) +{ + struct __ec_align4 ec_params_set_cbi *setter = + (struct __ec_align4 ec_params_set_cbi *)buf; + int last_arg; + char *e; + + if (argc == 1) { + dump_cbi(); + if (cbi_get_cache_status() == CBI_CACHE_STATUS_SYNCED) + hexdump(cbi, CBI_IMAGE_SIZE); + return EC_SUCCESS; + } + + if (strcasecmp(argv[1], "set") == 0) { + if (argc < 5) { + ccprintf("Set requires: \n"); + return EC_ERROR_PARAM_COUNT; + } + + setter->tag = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + if (setter->tag == CBI_TAG_DRAM_PART_NUM || + setter->tag == CBI_TAG_OEM_NAME || + setter->tag == CBI_TAG_FUEL_GAUGE_MANUF_NAME || + setter->tag == CBI_TAG_FUEL_GAUGE_DEVICE_NAME) { + setter->size = strlen(argv[3]) + 1; + memcpy(setter->data, argv[3], setter->size); + } else { + uint64_t val = strtoull(argv[3], &e, 0); + + if (*e) + return EC_ERROR_PARAM3; + + setter->size = strtoi(argv[4], &e, 0); + if (*e) + return EC_ERROR_PARAM4; + + if (setter->size < 1) { + ccprintf("Set size too small\n"); + return EC_ERROR_PARAM4; + } else if ((setter->size > 8) || + (setter->size > 4 && + setter->tag != CBI_TAG_REWORK_ID)) { + ccprintf("Set size too large\n"); + return EC_ERROR_PARAM4; + } + + memcpy(setter->data, &val, setter->size); + } + + last_arg = 5; + } else if (strcasecmp(argv[1], "remove") == 0) { + if (argc < 3) { + ccprintf("Remove requires: \n"); + return EC_ERROR_PARAM_COUNT; + } + + setter->tag = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + setter->size = 0; + last_arg = 3; + } else { + return EC_ERROR_PARAM1; + } + + setter->flag = 0; + + if (argc > last_arg) { + int i; + + for (i = last_arg; i < argc; i++) { + if (strcasecmp(argv[i], "init") == 0) { + setter->flag |= CBI_SET_INIT; + } else if (strcasecmp(argv[i], "skip_write") == 0) { + setter->flag |= CBI_SET_NO_SYNC; + } else { + ccprintf("Invalid additional option\n"); + return EC_ERROR_PARAM1 + i - 1; + } + } + } + + if (common_cbi_set(setter) == EC_RES_SUCCESS) + return EC_SUCCESS; + + return EC_ERROR_UNKNOWN; } +DECLARE_CONSOLE_COMMAND(cbi, cc_cbi, + "[set | " + "remove ] [init | skip_write]", + "Print or change Cros Board Info from flash"); +#endif /* CONFIG_CMD_CBI */ -static int cc_cbi(int argc, char **argv) +#ifndef CONFIG_AP_POWER_CONTROL +int cbi_set_fw_config(uint32_t fw_config) { + /* Check write protect status */ + if (cbi_config.drv->is_protected()) + return EC_ERROR_ACCESS_DENIED; + + /* Ensure that CBI has been configured */ + if (cbi_read()) + cbi_create(); + + /* Update the FW_CONFIG field */ + cbi_set_board_info(CBI_TAG_FW_CONFIG, (uint8_t *)&fw_config, + sizeof(int)); + + /* Update CRC calculation and write to the storage */ + head->crc = cbi_crc8(head); + if (cbi_write()) + return EC_ERROR_UNKNOWN; + dump_cbi(); - dump_flash(); + return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(cbi, cc_cbi, NULL, "Print Cros Board Info from flash"); -#endif /* CONFIG_CMD_CBI */ + +int cbi_set_ssfc(uint32_t ssfc) +{ + /* Check write protect status */ + if (cbi_config.drv->is_protected()) + return EC_ERROR_ACCESS_DENIED; + + /* Ensure that CBI has been configured */ + if (cbi_read()) + cbi_create(); + + /* Update the SSFC field */ + cbi_set_board_info(CBI_TAG_SSFC, (uint8_t *)&ssfc, sizeof(int)); + + /* Update CRC calculation and write to the storage */ + head->crc = cbi_crc8(head); + if (cbi_write()) + return EC_ERROR_UNKNOWN; + + dump_cbi(); + + return EC_SUCCESS; +} +#endif #endif /* !HOST_TOOLS_BUILD */ diff --git a/common/cbi_eeprom.c b/common/cbi_eeprom.c new file mode 100644 index 0000000000..da7d85f21b --- /dev/null +++ b/common/cbi_eeprom.c @@ -0,0 +1,82 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Support Cros Board Info EEPROM */ + +#include "console.h" +#include "cros_board_info.h" +#include "gpio.h" +#include "i2c.h" +#include "system.h" +#include "timer.h" +#include "util.h" +#include "write_protect.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, "CBI " format, ##args) + +/* + * We allow EEPROMs with page size of 8 or 16. Use 8 to be the most compatible. + * This causes a little more overhead for writes, but we are not writing to the + * EEPROM outside of the factory process. + */ +#define EEPROM_PAGE_WRITE_SIZE 8 +#define EEPROM_PAGE_WRITE_MS 5 + +static int eeprom_read(uint8_t offset, uint8_t *data, int len) +{ + return i2c_read_block(I2C_PORT_EEPROM, I2C_ADDR_EEPROM_FLAGS, offset, + data, len); +} + +static int eeprom_is_write_protected(void) +{ + if (IS_ENABLED(CONFIG_BYPASS_CBI_EEPROM_WP_CHECK)) + return 0; + + return write_protect_is_asserted(); +} + +static int eeprom_write(uint8_t *cbi) +{ + uint8_t *p = cbi; + int rest = ((struct cbi_header *)p)->total_size; + + while (rest > 0) { + int size = MIN(EEPROM_PAGE_WRITE_SIZE, rest); + int rv; + + rv = i2c_write_block(I2C_PORT_EEPROM, I2C_ADDR_EEPROM_FLAGS, + p - cbi, p, size); + if (rv) { + CPRINTS("Failed to write for %d", rv); + return rv; + } + /* Wait for internal write cycle completion */ + msleep(EEPROM_PAGE_WRITE_MS); + p += size; + rest -= size; + } + + return EC_SUCCESS; +} + +#ifdef CONFIG_EEPROM_CBI_WP +void cbi_latch_eeprom_wp(void) +{ + CPRINTS("WP latched"); + gpio_set_level(GPIO_EC_CBI_WP, 1); +} +#endif /* CONFIG_EEPROM_CBI_WP */ + +const struct cbi_storage_driver eeprom_drv = { + .store = eeprom_write, + .load = eeprom_read, + .is_protected = eeprom_is_write_protected, +}; + +const struct cbi_storage_config_t cbi_config = { + .storage_type = CBI_STORAGE_TYPE_EEPROM, + .drv = &eeprom_drv, +}; diff --git a/common/cbi_gpio.c b/common/cbi_gpio.c new file mode 100644 index 0000000000..09e1dd3a18 --- /dev/null +++ b/common/cbi_gpio.c @@ -0,0 +1,72 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Support Cros Board Info GPIO */ + +#include "console.h" +#include "cros_board_info.h" +#include "gpio.h" +#include "system.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, "CBI " format, ##args) + +static int cbi_gpio_read(uint8_t offset, uint8_t *data, int len) +{ + int board_id; + int sku_id; + int rv; + int err = 0; + + if (cbi_get_cache_status() == CBI_CACHE_STATUS_SYNCED) + return EC_SUCCESS; + + cbi_create(); + + board_id = system_get_board_version(); + if (board_id < 0) { + CPRINTS("Failed (%d) to get a valid board id", -board_id); + err++; + } else { + rv = cbi_set_board_info(CBI_TAG_BOARD_VERSION, + (uint8_t *)&board_id, sizeof(int)); + if (rv) { + CPRINTS("Failed (%d) to set BOARD_VERSION tag", rv); + err++; + } + } + + sku_id = system_get_sku_id(); + rv = cbi_set_board_info(CBI_TAG_SKU_ID, (uint8_t *)&sku_id, + sizeof(int)); + if (rv) { + CPRINTS("Failed (%d) to set SKU_ID tag", rv); + err++; + } + + if (err > 0) + return EC_ERROR_UNKNOWN; + + return EC_SUCCESS; +} + +static int cbi_gpio_is_write_protected(void) +{ + /* + * When CBI comes from strapping pins, any attempts for updating CBI + * storage should be rejected. + */ + return 1; +} + +const struct cbi_storage_driver gpio_drv = { + .load = cbi_gpio_read, + .is_protected = cbi_gpio_is_write_protected, +}; + +const struct cbi_storage_config_t cbi_config = { + .storage_type = CBI_STORAGE_TYPE_GPIO, + .drv = &gpio_drv, +}; diff --git a/common/cec.c b/common/cec.c index 1bc3273c1d..111aa60660 100644 --- a/common/cec.c +++ b/common/cec.c @@ -1,14 +1,31 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "atomic.h" #include "cec.h" +#include "chipset.h" #include "console.h" +#include "hooks.h" +#include "host_command.h" +#include "mkbp_event.h" +#include "power_button.h" +#include "printf.h" #include "task.h" +#include "util.h" -#define CPRINTF(format, args...) cprintf(CC_CEC, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CEC, format, ## args) +#ifdef CONFIG_CEC_DEBUG +#define CPRINTF(format, args...) cprintf(CC_CEC, format, ##args) +#define CPRINTS(format, args...) cprints(CC_CEC, format, ##args) +#else +#define CPRINTF(...) +#define CPRINTS(...) +#endif + +/* Only one port is supported for now */ +#define CEC_PORT 0 +BUILD_ASSERT(CEC_PORT_COUNT == 1); /* * Mutex for the read-offset of the rx queue. Needed since the @@ -16,6 +33,12 @@ */ static struct mutex rx_queue_readoffset_mutex; +/* Queue of completed incoming CEC messages */ +static struct cec_rx_queue cec_rx_queue; + +/* Events to send to AP */ +static atomic_t cec_events; + int cec_transfer_get_bit(const struct cec_msg_transfer *transfer) { if (transfer->byte >= MAX_CEC_MSG_LEN) @@ -61,6 +84,62 @@ void cec_rx_queue_flush(struct cec_rx_queue *queue) queue->write_offset = 0; } +struct cec_offline_policy cec_default_policy[] = { + { + .command = CEC_MSG_IMAGE_VIEW_ON, + .action = CEC_ACTION_POWER_BUTTON, + }, + { + .command = CEC_MSG_TEXT_VIEW_ON, + .action = CEC_ACTION_POWER_BUTTON, + }, + /* Terminator */ + { 0 }, +}; + +static enum cec_action cec_find_action(const struct cec_offline_policy *policy, + uint8_t command) +{ + if (policy == NULL) + return CEC_ACTION_NONE; + + while (policy->command != 0 && policy->action != 0) { + if (policy->command == command) + return policy->action; + policy++; + } + + return CEC_ACTION_NONE; +} + +int cec_process_offline_message(struct cec_rx_queue *queue, const uint8_t *msg, + uint8_t msg_len) +{ + uint8_t command; + char str_buf[hex_str_buf_size(msg_len)]; + int port = CEC_PORT; + + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) + /* Forward to the AP */ + return EC_ERROR_NOT_HANDLED; + + if (msg_len < 1) + return EC_ERROR_INVAL; + + snprintf_hex_buffer(str_buf, sizeof(str_buf), HEX_BUF(msg, msg_len)); + CPRINTS("MSG: %s", str_buf); + + command = msg[1]; + + if (cec_find_action(cec_config[port].offline_policy, command) == + CEC_ACTION_POWER_BUTTON) + /* Equal to PWRBTN_INITIAL_US (for x86). */ + power_button_simulate_press(200); + + /* Consumed */ + return EC_SUCCESS; +} + int cec_rx_queue_push(struct cec_rx_queue *queue, const uint8_t *msg, uint8_t msg_len) { @@ -75,7 +154,7 @@ int cec_rx_queue_push(struct cec_rx_queue *queue, const uint8_t *msg, queue->buf[offset] = 0; offset = (offset + 1) % CEC_RX_BUFFER_SIZE; - for (i = 0 ; i < msg_len; i++) { + for (i = 0; i < msg_len; i++) { if (offset == queue->read_offset) { /* Buffer full */ return EC_ERROR_OVERFLOW; @@ -101,8 +180,7 @@ int cec_rx_queue_push(struct cec_rx_queue *queue, const uint8_t *msg, return EC_SUCCESS; } -int cec_rx_queue_pop(struct cec_rx_queue *queue, uint8_t *msg, - uint8_t *msg_len) +int cec_rx_queue_pop(struct cec_rx_queue *queue, uint8_t *msg, uint8_t *msg_len) { int i; @@ -119,19 +197,197 @@ int cec_rx_queue_pop(struct cec_rx_queue *queue, uint8_t *msg, if (*msg_len == 0 || *msg_len > MAX_CEC_MSG_LEN) { mutex_unlock(&rx_queue_readoffset_mutex); *msg_len = 0; - CPRINTF("Invalid CEC msg size: %u\n", *msg_len); + cprintf(CC_CEC, "Invalid CEC msg size: %u\n", *msg_len); return -1; } queue->read_offset = (queue->read_offset + 1) % CEC_RX_BUFFER_SIZE; for (i = 0; i < *msg_len; i++) { msg[i] = queue->buf[queue->read_offset]; - queue->read_offset = (queue->read_offset + 1) % - CEC_RX_BUFFER_SIZE; - + queue->read_offset = + (queue->read_offset + 1) % CEC_RX_BUFFER_SIZE; } mutex_unlock(&rx_queue_readoffset_mutex); return 0; } + +static void send_mkbp_event(uint32_t event) +{ + atomic_or(&cec_events, event); + mkbp_send_event(EC_MKBP_EVENT_CEC_EVENT); +} + +static enum ec_status hc_cec_write(struct host_cmd_handler_args *args) +{ + const struct ec_params_cec_write *params = args->params; + int port = CEC_PORT; + + if (args->params_size == 0 || args->params_size > MAX_CEC_MSG_LEN) + return EC_RES_INVALID_PARAM; + + if (cec_config[port].drv->send(port, params->msg, args->params_size) != + EC_SUCCESS) + return EC_RES_BUSY; + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_CEC_WRITE_MSG, hc_cec_write, EC_VER_MASK(0)); + +static enum ec_status cec_set_enable(int port, uint8_t enable) +{ + if (enable != 0 && enable != 1) + return EC_RES_INVALID_PARAM; + + if (cec_config[port].drv->set_enable(port, enable) != EC_SUCCESS) + return EC_RES_ERROR; + + if (enable == 0) { + /* If disabled, clear the rx queue and events. */ + memset(&cec_rx_queue, 0, sizeof(struct cec_rx_queue)); + cec_events = 0; + } + + return EC_RES_SUCCESS; +} + +static enum ec_status cec_set_logical_addr(int port, uint8_t logical_addr) +{ + if (logical_addr >= CEC_BROADCAST_ADDR && + logical_addr != CEC_UNREGISTERED_ADDR) + return EC_RES_INVALID_PARAM; + + if (cec_config[port].drv->set_logical_addr(port, logical_addr) != + EC_SUCCESS) + return EC_RES_ERROR; + + return EC_RES_SUCCESS; +} + +static enum ec_status hc_cec_set(struct host_cmd_handler_args *args) +{ + const struct ec_params_cec_set *params = args->params; + int port = CEC_PORT; + + switch (params->cmd) { + case CEC_CMD_ENABLE: + return cec_set_enable(port, params->val); + case CEC_CMD_LOGICAL_ADDRESS: + return cec_set_logical_addr(port, params->val); + } + + return EC_RES_INVALID_PARAM; +} +DECLARE_HOST_COMMAND(EC_CMD_CEC_SET, hc_cec_set, EC_VER_MASK(0)); + +static enum ec_status hc_cec_get(struct host_cmd_handler_args *args) +{ + struct ec_response_cec_get *response = args->response; + const struct ec_params_cec_get *params = args->params; + int port = CEC_PORT; + + switch (params->cmd) { + case CEC_CMD_ENABLE: + if (cec_config[port].drv->get_enable(port, &response->val) != + EC_SUCCESS) + return EC_RES_ERROR; + break; + case CEC_CMD_LOGICAL_ADDRESS: + if (cec_config[port].drv->get_logical_addr( + port, &response->val) != EC_SUCCESS) + return EC_RES_ERROR; + break; + default: + return EC_RES_INVALID_PARAM; + } + + args->response_size = sizeof(*response); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_CEC_GET, hc_cec_get, EC_VER_MASK(0)); + +static int cec_get_next_event(uint8_t *out) +{ + uint32_t event_out = atomic_clear(&cec_events); + + memcpy(out, &event_out, sizeof(event_out)); + + return sizeof(event_out); +} +DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_CEC_EVENT, cec_get_next_event); + +static int cec_get_next_msg(uint8_t *out) +{ + int rv; + uint8_t msg_len, msg[MAX_CEC_MSG_LEN]; + + rv = cec_rx_queue_pop(&cec_rx_queue, msg, &msg_len); + if (rv != 0) + return EC_RES_UNAVAILABLE; + + memcpy(out, msg, msg_len); + + return msg_len; +} +DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_CEC_MESSAGE, cec_get_next_msg); + +static void cec_init(void) +{ + int port = CEC_PORT; + + cec_config[port].drv->init(port); + + CPRINTS("CEC initialized"); +} +DECLARE_HOOK(HOOK_INIT, cec_init, HOOK_PRIO_LAST); + +static void handle_received_message(void) +{ + int rv; + uint8_t *msg; + uint8_t msg_len; + int port = CEC_PORT; + + if (cec_config[port].drv->get_received_message(port, &msg, &msg_len) != + EC_SUCCESS) { + cprints(CC_CEC, "CEC: failed to get received message"); + return; + } + + if (cec_process_offline_message(&cec_rx_queue, msg, msg_len) == + EC_SUCCESS) { + CPRINTS("Message consumed offline"); + /* Continue to queue message and notify AP. */ + } + rv = cec_rx_queue_push(&cec_rx_queue, msg, msg_len); + if (rv == EC_ERROR_OVERFLOW) { + /* Queue full, prefer the most recent msg */ + cec_rx_queue_flush(&cec_rx_queue); + rv = cec_rx_queue_push(&cec_rx_queue, msg, msg_len); + } + if (rv == EC_SUCCESS) + mkbp_send_event(EC_MKBP_EVENT_CEC_MESSAGE); +} + +void cec_task(void *unused) +{ + uint32_t events; + + CPRINTF("CEC task starting\n"); + + while (1) { + events = task_wait_event(-1); + if (events & CEC_TASK_EVENT_RECEIVED_DATA) { + handle_received_message(); + } + if (events & CEC_TASK_EVENT_OKAY) { + send_mkbp_event(EC_MKBP_CEC_SEND_OK); + CPRINTS("SEND OKAY"); + } else if (events & CEC_TASK_EVENT_FAILED) { + send_mkbp_event(EC_MKBP_CEC_SEND_FAILED); + CPRINTS("SEND FAILED"); + } + } +} diff --git a/common/charge_manager.c b/common/charge_manager.c index bc82859e5d..c5d5543012 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,28 +6,38 @@ #include "adc.h" #include "atomic.h" #include "battery.h" +#include "builtin/assert.h" #include "charge_manager.h" #include "charge_ramp.h" -#include "charge_state_v2.h" +#include "charge_state.h" #include "charger.h" #include "console.h" +#include "dps.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "system.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" +#include "typec_control.h" +#include "usb_common.h" #include "usb_pd.h" +#include "usb_pd_dpm_sm.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#ifdef HAS_MOCK_CHARGE_MANAGER +#error Mock defined HAS_MOCK_CHARGE_MANAGER +#endif + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) #define POWER(charge_port) ((charge_port.current) * (charge_port.voltage)) /* Timeout for delayed override power swap, allow for 500ms extra */ -#define POWER_SWAP_TIMEOUT (PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON + \ - PD_T_SAFE_0V + 500 * MSEC) +#define POWER_SWAP_TIMEOUT \ + (PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON + PD_T_SAFE_0V + 500 * MSEC) /* * Default charge supplier priority @@ -61,15 +71,13 @@ __overridable const int supplier_priority[] = { [CHARGE_SUPPLIER_OTHER] = 4, [CHARGE_SUPPLIER_VBUS] = 4, #endif -#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7 - [CHARGE_SUPPLIER_WPC_BPP] = 5, - [CHARGE_SUPPLIER_WPC_EPP] = 5, - [CHARGE_SUPPLIER_WPC_GPP] = 5, -#endif }; BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT); +const char *charge_supplier_name[] = { CHARGE_SUPPLIER_NAME }; +BUILD_ASSERT(ARRAY_SIZE(charge_supplier_name) == CHARGE_SUPPLIER_COUNT); + /* Keep track of available charge for each charge port. */ static struct charge_port_info available_charge[CHARGE_SUPPLIER_COUNT] [CHARGE_PORT_COUNT]; @@ -99,12 +107,14 @@ static int charge_current = CHARGE_CURRENT_UNINITIALIZED; static int charge_current_uncapped = CHARGE_CURRENT_UNINITIALIZED; static int charge_voltage; static int charge_supplier = CHARGE_SUPPLIER_NONE; +static int charge_pd_current_uncapped = CHARGE_CURRENT_UNINITIALIZED; static int override_port = OVERRIDE_OFF; static int delayed_override_port = OVERRIDE_OFF; static timestamp_t delayed_override_deadline; -static uint8_t source_port_rp[CONFIG_USB_PD_PORT_MAX_COUNT]; +/* Source-out Rp values for TCPMv1 */ +__maybe_unused static uint8_t source_port_rp[CONFIG_USB_PD_PORT_MAX_COUNT]; #ifdef CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT /* 3A on one port and 1.5A on the rest */ @@ -139,7 +149,7 @@ enum charge_manager_change_type { CHANGE_DUALROLE, }; -static int is_pd_port(int port) +int is_pd_port(int port) { return port >= 0 && port < board_get_usb_pd_port_count(); } @@ -171,7 +181,6 @@ static int is_valid_port(int port) return 1; } -#ifndef TEST_BUILD static int is_connected(int port) { if (!is_pd_port(port)) @@ -179,7 +188,6 @@ static int is_connected(int port) return pd_is_connected(port); } -#endif /* !TEST_BUILD */ #ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING /** @@ -195,9 +203,8 @@ static int is_connected(int port) */ static int charge_manager_spoof_dualrole_capability(void) { - return (system_get_image_copy() == EC_IMAGE_RO && - system_is_locked()) || !left_safe_mode; - + return (system_get_image_copy() == EC_IMAGE_RO && system_is_locked()) || + !left_safe_mode; } #endif /* !CONFIG_CHARGE_MANAGER_DRP_CHARGING */ @@ -222,11 +229,11 @@ static void charge_manager_init(void) charge_ceil[i][j] = CHARGE_CEIL_NONE; if (!is_pd_port(i)) dualrole_capability[i] = CAP_DEDICATED; - if (is_pd_port(i)) + if (is_pd_port(i) && !IS_ENABLED(CONFIG_USB_PD_TCPMV2)) source_port_rp[i] = CONFIG_USB_PD_PULLUP; } } -DECLARE_HOOK(HOOK_INIT, charge_manager_init, HOOK_PRIO_CHARGE_MANAGER_INIT); +DECLARE_HOOK(HOOK_INIT, charge_manager_init, HOOK_PRIO_INIT_CHARGE_MANAGER); /** * Check if the charge manager is seeded. @@ -248,9 +255,9 @@ static int charge_manager_is_seeded(void) if (!is_valid_port(j)) continue; if (available_charge[i][j].current == - CHARGE_CURRENT_UNINITIALIZED || + CHARGE_CURRENT_UNINITIALIZED || available_charge[i][j].voltage == - CHARGE_VOLTAGE_UNINITIALIZED) + CHARGE_VOLTAGE_UNINITIALIZED) return 0; } } @@ -258,14 +265,18 @@ static int charge_manager_is_seeded(void) return 1; } -#ifndef TEST_BUILD +int charge_manager_get_pd_current_uncapped(void) +{ + return charge_pd_current_uncapped; +} + /** * Get the maximum charge current for a port. * * @param port Charge port. * @return Charge current (mA). */ -static int charge_manager_get_source_current(int port) +__maybe_unused static int charge_manager_get_source_current(int port) { if (!is_pd_port(port)) return 0; @@ -310,37 +321,128 @@ static enum charge_supplier find_supplier(int port, enum charge_supplier sup, return sup; } -/** - * Fills passed power_info structure with current info about the passed port. - * - * @param port Charge port. - * @param r USB PD power info to be updated. - */ -static void charge_manager_fill_power_info(int port, - struct ec_response_usb_pd_power_info *r) +static enum charge_supplier get_current_supplier(int port) { - int sup = CHARGE_SUPPLIER_NONE; + enum charge_supplier supplier = CHARGE_SUPPLIER_NONE; /* Determine supplier information to show. */ if (port == charge_port) { - sup = charge_supplier; + supplier = charge_supplier; } else { /* Consider available current */ - sup = find_supplier(port, sup, 0); - if (sup == CHARGE_SUPPLIER_NONE) + supplier = find_supplier(port, supplier, 0); + if (supplier == CHARGE_SUPPLIER_NONE) /* Ignore available current */ - sup = find_supplier(port, sup, -1); + supplier = find_supplier(port, supplier, -1); } - /* Fill in power role */ + return supplier; +} +static enum usb_power_roles +get_current_power_role(int port, enum charge_supplier supplier) +{ + enum usb_power_roles role; if (charge_port == port) - r->role = USB_PD_PORT_POWER_SINK; + role = USB_PD_PORT_POWER_SINK; else if (is_connected(port) && !is_sink(port)) - r->role = USB_PD_PORT_POWER_SOURCE; - else if (sup != CHARGE_SUPPLIER_NONE) - r->role = USB_PD_PORT_POWER_SINK_NOT_CHARGING; + role = USB_PD_PORT_POWER_SOURCE; + else if (supplier != CHARGE_SUPPLIER_NONE) + role = USB_PD_PORT_POWER_SINK_NOT_CHARGING; else - r->role = USB_PD_PORT_POWER_DISCONNECTED; + role = USB_PD_PORT_POWER_DISCONNECTED; + return role; +} + +__overridable int board_get_vbus_voltage(int port) +{ + return 0; +} + +static int get_vbus_voltage(int port, enum usb_power_roles current_role) +{ + int voltage_mv; + + /* + * If we are sourcing power or sinking but not charging, then VBUS must + * be 5V. If we are charging, then read VBUS ADC. + */ + if (current_role == USB_PD_PORT_POWER_SINK_NOT_CHARGING) { + voltage_mv = 5000; + } else { +#if defined(CONFIG_USB_PD_VBUS_MEASURE_CHARGER) + /* + * Try to get VBUS from the charger. If that fails, default to 0 + * mV. + */ + if (charger_get_vbus_voltage(port, &voltage_mv)) + voltage_mv = 0; +#elif defined(CONFIG_USB_PD_VBUS_MEASURE_TCPC) + voltage_mv = tcpc_get_vbus_voltage(port); +#elif defined(CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT) + voltage_mv = adc_read_channel(board_get_vbus_adc(port)); +#elif defined(CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT) + /* No VBUS ADC channel - voltage is unknown */ + voltage_mv = 0; +#elif defined(CONFIG_USB_PD_VBUS_MEASURE_BY_BOARD) + voltage_mv = board_get_vbus_voltage(port); +#else + /* There is a single ADC that measures joint Vbus */ + voltage_mv = adc_read_channel(ADC_VBUS); +#endif + } + return voltage_mv; +} + +int charge_manager_get_vbus_voltage(int port) +{ + return get_vbus_voltage( + port, get_current_power_role(port, get_current_supplier(port))); +} + +#ifdef CONFIG_CMD_VBUS +static int command_vbus(int argc, const char **argv) +{ + /* port = -1 to print all the ports */ + int port = -1; + int vbus, vsys; + + if (argc == 2) + port = atoi(argv[1]); + + ccprintf(" VBUS VSYS\n"); + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + if (port < 0 || i == port) { + vbus = charge_manager_get_vbus_voltage(i); + if (charger_get_vsys_voltage(i, &vsys)) + vsys = -1; + ccprintf(" P%d %6dmV ", i, vbus); + if (vsys >= 0) + ccprintf("%6dmV\n", vsys); + else + ccprintf("(unknown)\n"); + } + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(vbus, command_vbus, "[port]", + "Print VBUS & VSYS of the given port"); +#endif + +/** + * Fills passed power_info structure with current info about the passed port. + * + * @param port Charge port. + * @param r USB PD power info to be updated. + */ +static void +charge_manager_fill_power_info(int port, + struct ec_response_usb_pd_power_info *r) +{ + enum charge_supplier sup = get_current_supplier(port); + + /* Fill in power role */ + r->role = get_current_power_role(port, sup); /* Is port partner dual-role capable */ r->dualrole = (dualrole_capability[port] == CAP_DUALROLE); @@ -352,15 +454,21 @@ static void charge_manager_fill_power_info(int port, r->meas.voltage_max = 0; r->meas.voltage_now = r->role == USB_PD_PORT_POWER_SOURCE ? 5000 : 0; - r->meas.current_max = - charge_manager_get_source_current(port); + /* TCPMv2 tracks source-out current in the DPM */ + if (IS_ENABLED(CONFIG_USB_PD_TCPMV2)) + r->meas.current_max = + dpm_get_source_current(port); + else + r->meas.current_max = + charge_manager_get_source_current(port); r->max_power = 0; } else { r->type = USB_CHG_TYPE_NONE; board_fill_source_power_info(port, r); } } else { - int use_ramp_current; + uint32_t max_mv, max_ma, pdo, unused; + switch (sup) { case CHARGE_SUPPLIER_PD: r->type = USB_CHG_TYPE_PD; @@ -386,30 +494,32 @@ static void charge_manager_fill_power_info(int port, r->type = USB_CHG_TYPE_VBUS; break; #endif -#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7 - /* - * Todo:need kernel add wpc device node in power_supply - * before that use USB_CHG_TYPE_PROPRIETARY to present WPC. - */ - case CHARGE_SUPPLIER_WPC_BPP: - case CHARGE_SUPPLIER_WPC_EPP: - case CHARGE_SUPPLIER_WPC_GPP: - r->type = USB_CHG_TYPE_PROPRIETARY; - break; -#endif #if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 case CHARGE_SUPPLIER_DEDICATED: r->type = USB_CHG_TYPE_DEDICATED; break; #endif default: -#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7 - r->type = USB_CHG_TYPE_VBUS; -#else r->type = USB_CHG_TYPE_OTHER; -#endif } - r->meas.voltage_max = available_charge[sup][port].voltage; + + if (IS_ENABLED(CONFIG_USB_PD_DPS) && dps_is_enabled() && + sup == CHARGE_SUPPLIER_PD) { + /* + * Returns the maximum power the system can request when + * DPS enabled. This is to prevent the system think it's + * using a low power charger. + */ + pd_find_pdo_index(pd_get_src_cap_cnt(port), + pd_get_src_caps(port), + pd_get_max_voltage(), &pdo); + pd_extract_pdo_power(pdo, &max_ma, &max_mv, &unused); + } else { + max_mv = available_charge[sup][port].voltage; + max_ma = available_charge[sup][port].current; + } + + r->meas.voltage_max = max_mv; /* * Report unknown charger CHARGE_DETECT_DELAY after supplier @@ -423,19 +533,13 @@ static void charge_manager_fill_power_info(int port, * lose power again). */ #ifdef CONFIG_BATTERY - if (get_time().val < registration_time[port].val + - CHARGE_DETECT_DELAY) + if (get_time().val < + registration_time[port].val + CHARGE_DETECT_DELAY) r->type = USB_CHG_TYPE_UNKNOWN; #endif #if defined(HAS_TASK_CHG_RAMP) || defined(CONFIG_CHARGE_RAMP_HW) - /* Read ramped current if active charging port */ - use_ramp_current = - (charge_port == port) && chg_ramp_allowed(port, sup); -#else - use_ramp_current = 0; -#endif - if (use_ramp_current) { + if ((charge_port == port) && chg_ramp_allowed(port, sup)) { /* Current limit is output of ramp module */ r->meas.current_lim = chg_ramp_get_current_limit(); @@ -448,48 +552,21 @@ static void charge_manager_fill_power_info(int port, * If ramp is not allowed, max current is just the * available charge current. */ - r->meas.current_max = chg_ramp_is_stable() ? - r->meas.current_lim : chg_ramp_max(port, sup, - available_charge[sup][port].current); - - r->max_power = - r->meas.current_max * r->meas.voltage_max; + r->meas.current_max = + chg_ramp_is_stable() ? + r->meas.current_lim : + chg_ramp_max(port, sup, max_ma); } else { - r->meas.current_max = r->meas.current_lim = - available_charge[sup][port].current; - r->max_power = POWER(available_charge[sup][port]); + r->meas.current_max = r->meas.current_lim = max_ma; } - - /* - * If we are sourcing power, or sinking but not charging, then - * VBUS must be 5V. If we are charging, then read VBUS ADC. - */ - if (r->role == USB_PD_PORT_POWER_SINK_NOT_CHARGING) - r->meas.voltage_now = 5000; - else { -#if defined(CONFIG_USB_PD_VBUS_MEASURE_CHARGER) - int voltage; - - if (charger_get_vbus_voltage(port, &voltage)) - r->meas.voltage_now = 0; - else - r->meas.voltage_now = voltage; -#elif defined(CONFIG_USB_PD_VBUS_MEASURE_TCPC) - r->meas.voltage_now = tcpc_get_vbus_voltage(port); -#elif defined(CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT) - r->meas.voltage_now = - adc_read_channel(board_get_vbus_adc(port)); -#elif defined(CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT) - /* No VBUS ADC channel - voltage is unknown */ - r->meas.voltage_now = 0; #else - /* There is a single ADC that measures joint Vbus */ - r->meas.voltage_now = adc_read_channel(ADC_VBUS); + r->meas.current_max = r->meas.current_lim = max_ma; #endif - } + r->max_power = r->meas.current_max * r->meas.voltage_max; + + r->meas.voltage_now = get_vbus_voltage(port, r->role); } } -#endif /* TEST_BUILD */ #ifdef CONFIG_USB_PD_LOGGING /** @@ -515,8 +592,8 @@ void charge_manager_save_log(int port) (pinfo.dualrole ? CHARGE_FLAGS_DUAL_ROLE : 0); pd_log_event(PD_EVENT_MCU_CHARGE, - PD_LOG_PORT_SIZE(port, sizeof(pinfo.meas)), - flags, &pinfo.meas); + PD_LOG_PORT_SIZE(port, sizeof(pinfo.meas)), flags, + &pinfo.meas); } #endif /* CONFIG_USB_PD_LOGGING */ @@ -579,9 +656,10 @@ static void charge_manager_get_best_charge_port(int *new_port, if (override_port != OVERRIDE_DONT_CHARGE) { /* * Charge supplier selection logic: - * 1. Prefer higher priority supply. - * 2. Prefer higher power over lower in case priority is tied. - * 3. Prefer current charge port over new port in case (1) + * 1. Prefer DPS charge port. + * 2. Prefer higher priority supply. + * 3. Prefer higher power over lower in case priority is tied. + * 4. Prefer current charge port over new port in case (1) * and (2) are tied. * available_charge can be changed at any time by other tasks, * so make no assumptions about its consistency. @@ -605,8 +683,7 @@ static void charge_manager_get_best_charge_port(int *new_port, * charge on another override port. */ if (override_port != OVERRIDE_OFF && - override_port == port && - override_port != j) + override_port == port && override_port != j) continue; #ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING @@ -623,31 +700,44 @@ static void charge_manager_get_best_charge_port(int *new_port, candidate_port_power = POWER(available_charge[i][j]); - /* Select if no supplier chosen yet. */ - if (supplier == CHARGE_SUPPLIER_NONE || - /* ..or if supplier priority is higher. */ - supplier_priority[i] < - supplier_priority[supplier] || - /* ..or if this is our override port. */ - (j == override_port && - port != override_port) || - /* ..or if priority is tied and.. */ - (supplier_priority[i] == - supplier_priority[supplier] && - /* candidate port can supply more power or.. */ - (candidate_port_power > best_port_power || - /* - * candidate port is the active port and can - * supply the same amount of power. - */ - (candidate_port_power == best_port_power && - charge_port == j)))) { + /* Select DPS port if provided. */ + if (IS_ENABLED(CONFIG_USB_PD_DPS) && + override_port == OVERRIDE_OFF && + i == CHARGE_SUPPLIER_PD && + j == dps_get_charge_port()) { + supplier = i; + port = j; + break; + /* Select if no supplier chosen yet. */ + } else if (supplier == CHARGE_SUPPLIER_NONE || + /* ..or if supplier priority is + higher. */ + supplier_priority[i] < + supplier_priority[supplier] || + /* ..or if this is our override port. + */ + (j == override_port && + port != override_port) || + /* ..or if priority is tied and.. */ + (supplier_priority[i] == + supplier_priority[supplier] && + /* candidate port can supply more + power or.. */ + (candidate_port_power > + best_port_power || + /* + * candidate port is the active + * port and can supply the same + * amount of power. + */ + (candidate_port_power == + best_port_power && + charge_port == j)))) { supplier = i; port = j; best_port_power = candidate_port_power; } } - } #ifdef CONFIG_BATTERY @@ -655,8 +745,7 @@ static void charge_manager_get_best_charge_port(int *new_port, * if no battery present then retain same charge port * and charge supplier to avoid the port switching */ - if (charge_port != CHARGE_SUPPLIER_NONE && - charge_port != port && + if (charge_port != CHARGE_SUPPLIER_NONE && charge_port != port && (battery_is_present() == BP_NO || (battery_is_present() == BP_YES && battery_is_cut_off() != BATTERY_CUTOFF_STATE_NORMAL))) { @@ -699,11 +788,24 @@ static void charge_manager_refresh(void) * the port, for example, if the port has become a charge * source. */ - if ((active_charge_port_initialized && - new_port == charge_port && - new_supplier == charge_supplier) || - board_set_active_charge_port(new_port) == EC_SUCCESS) + if (active_charge_port_initialized && new_port == charge_port && + new_supplier == charge_supplier) + break; + + /* + * For OCPC systems, reset the OCPC state to prevent current + * spikes. + */ + if (IS_ENABLED(CONFIG_OCPC)) { + charge_set_active_chg_chip(new_port); + trigger_ocpc_reset(); + } + + if (board_set_active_charge_port(new_port) == EC_SUCCESS) { + if (IS_ENABLED(CONFIG_EXTPOWER)) + board_check_extpower(); break; + } /* 'Dont charge' request must be accepted. */ ASSERT(new_port != CHARGE_PORT_NONE); @@ -720,10 +822,6 @@ static void charge_manager_refresh(void) active_charge_port_initialized = 1; - /* Set the active charger chip based upon the selected charge port. */ - if (IS_ENABLED(CONFIG_OCPC)) - charge_set_active_chg_chip(new_port); - /* * Clear override if it wasn't selected as the 'best' port -- it means * that no charge is available on the port, or the port was rejected. @@ -732,8 +830,12 @@ static void charge_manager_refresh(void) override_port = OVERRIDE_OFF; if (new_supplier == CHARGE_SUPPLIER_NONE) { +#ifdef CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT + new_charge_current = CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT; +#else new_charge_current = 0; - new_charge_current_uncapped = 0; +#endif + new_charge_current_uncapped = new_charge_current; new_charge_voltage = 0; } else { new_charge_current_uncapped = @@ -751,8 +853,8 @@ static void charge_manager_refresh(void) /* Enforce port charge ceiling. */ ceil = charge_manager_get_ceil(new_port); if (left_safe_mode && ceil != CHARGE_CEIL_NONE) - new_charge_current = MIN(ceil, - new_charge_current_uncapped); + new_charge_current = + MIN(ceil, new_charge_current_uncapped); else new_charge_current = new_charge_current_uncapped; @@ -760,29 +862,45 @@ static void charge_manager_refresh(void) available_charge[new_supplier][new_port].voltage; } + /* + * Record the PD current limit to prevent from over-sinking + * the charger. + */ + if (new_supplier == CHARGE_SUPPLIER_PD) + charge_pd_current_uncapped = new_charge_current_uncapped; + else + charge_pd_current_uncapped = CHARGE_CURRENT_UNINITIALIZED; + /* Change the charge limit + charge port/supplier if modified. */ if (new_port != charge_port || new_charge_current != charge_current || new_supplier != charge_supplier) { #ifdef HAS_TASK_CHG_RAMP - chg_ramp_charge_supplier_change( - new_port, new_supplier, new_charge_current, - registration_time[new_port], - new_charge_voltage); + chg_ramp_charge_supplier_change(new_port, new_supplier, + new_charge_current, + registration_time[new_port], + new_charge_voltage); #else #ifdef CONFIG_CHARGE_RAMP_HW /* Enable or disable charge ramp */ charger_set_hw_ramp(chg_ramp_allowed(new_port, new_supplier)); #endif board_set_charge_limit(new_port, new_supplier, - new_charge_current, - new_charge_current_uncapped, - new_charge_voltage); + new_charge_current, + new_charge_current_uncapped, + new_charge_voltage); #endif /* HAS_TASK_CHG_RAMP */ power_changed = 1; CPRINTS("CL: p%d s%d i%d v%d", new_port, new_supplier, new_charge_current, new_charge_voltage); + + /* + * (b:192638664) We try to check AC OK again to avoid + * unsuccessful detection in the initial detection. + */ + if (IS_ENABLED(CONFIG_EXTPOWER)) + board_check_extpower(); } /* @@ -834,14 +952,64 @@ static void charge_manager_refresh(void) #endif /* New power requests must be set only after updating the globals. */ - if (is_pd_port(updated_new_port)) - pd_set_new_power_request(updated_new_port); + if (is_pd_port(updated_new_port)) { + /* Check if we can get requested voltage/current */ + if ((IS_ENABLED(CONFIG_USB_PD_TCPMV1) && + IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE)) || + (IS_ENABLED(CONFIG_USB_PD_TCPMV2) && + IS_ENABLED(CONFIG_USB_PE_SM))) { + uint32_t pdo; + uint32_t max_voltage; + uint32_t max_current; + uint32_t unused; + bool new_req = false; + /* + * Check if new voltage/current is different + * than requested. If yes, send new power request + */ + if (pd_get_requested_voltage(updated_new_port) != + charge_voltage || + pd_get_requested_current(updated_new_port) != + charge_current_uncapped) + new_req = true; + + if (IS_ENABLED(CONFIG_USB_PD_DPS) && dps_is_enabled()) { + /* Fall-through. DPS control sink voltage */ + } else { + /* + * Check if we can get more power from this + * port. If yes, send new power request + */ + pd_find_pdo_index( + pd_get_src_cap_cnt(updated_new_port), + pd_get_src_caps(updated_new_port), + pd_get_max_voltage(), &pdo); + pd_extract_pdo_power(pdo, &max_current, + &max_voltage, &unused); + + if (charge_voltage != max_voltage || + charge_current_uncapped != max_current) + new_req = true; + } + + if (new_req) + pd_set_new_power_request(updated_new_port); + } else { + /* + * Functions for getting requested voltage/current + * are not available. Send new power request. + */ + pd_set_new_power_request(updated_new_port); + } + } if (is_pd_port(updated_old_port)) pd_set_new_power_request(updated_old_port); - if (power_changed) + if (power_changed) { + hook_notify(HOOK_POWER_SUPPLY_CHANGE); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); + } } DECLARE_DEFERRED(charge_manager_refresh); @@ -874,8 +1042,7 @@ DECLARE_DEFERRED(charger_detect_debounced); * @param charge Charge port current / voltage. */ static void charge_manager_make_change(enum charge_manager_change_type change, - int supplier, - int port, + int supplier, int port, const struct charge_port_info *charge) { int i; @@ -891,9 +1058,8 @@ static void charge_manager_make_change(enum charge_manager_change_type change, case CHANGE_CHARGE: /* Ignore changes where charge is identical */ if (available_charge[supplier][port].current == - charge->current && - available_charge[supplier][port].voltage == - charge->voltage) + charge->current && + available_charge[supplier][port].voltage == charge->voltage) return; if (charge->current > 0 && available_charge[supplier][port].current == 0) @@ -927,12 +1093,13 @@ static void charge_manager_make_change(enum charge_manager_change_type change, } /* Remove override when a charger is plugged */ - if (clear_override && override_port != port + if (clear_override && + override_port != port #ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING /* only remove override when it's a dedicated charger */ && dualrole_capability[port] == CAP_DEDICATED #endif - ) { + ) { override_port = OVERRIDE_OFF; if (delayed_override_port != OVERRIDE_OFF) { delayed_override_port = OVERRIDE_OFF; @@ -960,7 +1127,7 @@ static void charge_manager_make_change(enum charge_manager_change_type change, /* * If we have a charge on our delayed override port within * the deadline, make it our override port. - */ + */ if (port == delayed_override_port && charge->current > 0 && is_sink(delayed_override_port) && get_time().val < delayed_override_deadline.val) { @@ -1045,11 +1212,10 @@ void typec_set_input_current_limit(int port, typec_current_t max_ma, NULL); } -void charge_manager_update_charge(int supplier, - int port, +void charge_manager_update_charge(int supplier, int port, const struct charge_port_info *charge) { - struct charge_port_info zero = {0}; + struct charge_port_info zero = { 0 }; if (!charge) charge = &zero; charge_manager_make_change(CHANGE_CHARGE, supplier, port, charge); @@ -1068,11 +1234,31 @@ void charge_manager_update_dualrole(int port, enum dualrole_capabilities cap) } #ifdef CONFIG_CHARGE_MANAGER_SAFE_MODE +__overridable int board_get_leave_safe_mode_delay_ms(void) +{ + return 500; +} + void charge_manager_leave_safe_mode(void) { if (left_safe_mode) return; + /* + * Sometimes the fuel gauge will report that it has + * sufficient state of charge and remaining capacity, + * but in actuality it doesn't. When the EC sees that + * information, it trusts it and leaves charge manager + * safe mode. Doing so will allow CHARGE_PORT_NONE to + * be selected, thereby cutting off the input FETs. + * When the battery cannot provide the charge it claims, + * the system loses power, shuts down, and the battery + * is not charged even though the charger is plugged in. + * By waiting 500ms, we can avoid the selection of + * CHARGE_PORT_NONE around init time and not cut off the + * input FETs. + */ + msleep(board_get_leave_safe_mode_delay_ms()); CPRINTS("%s()", __func__); cflush(); left_safe_mode = 1; @@ -1099,15 +1285,29 @@ void charge_manager_force_ceil(int port, int ceil) * Force our input current to ceil if we're exceeding it, without * waiting for our deferred task to run. */ - if (left_safe_mode && port == charge_port && ceil < charge_current) + if (left_safe_mode && port == charge_port && ceil < charge_current) { board_set_charge_limit(port, CHARGE_SUPPLIER_PD, ceil, charge_current_uncapped, charge_voltage); - - /* - * Now inform charge_manager so it stays in sync with the state of - * the world. - */ - charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, ceil); + /* Enforcing charge_ceil here prevents race conditions between + * the hook task and the PD task, which could occur if + * charge_ceil is changed while a deferred + * charge_manager_refresh is in process. + * charge_manager_force_ceil's premise as an API is to lower + * the ceil for the current charge port. It doesn't need to find + * a better port, supplier, or PDO. That means most of + * charge_manager_refresh doesn't need to be called. + */ + charge_current = ceil; + charge_ceil[port][CEIL_REQUESTOR_PD] = ceil; + CPRINTS("CL: p%d s%d i%d v%d (forced)", port, + CHARGE_SUPPLIER_PD, charge_current, charge_voltage); + } else { + /* + * Inform charge_manager so it stays in sync with the state + * of the world. + */ + charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, ceil); + } } int charge_manager_set_override(int port) @@ -1131,8 +1331,8 @@ int charge_manager_set_override(int port) if (override_port != port) { override_port = port; if (charge_manager_is_seeded()) - hook_call_deferred( - &charge_manager_refresh_data, 0); + hook_call_deferred(&charge_manager_refresh_data, + 0); } } /* @@ -1140,13 +1340,13 @@ int charge_manager_set_override(int port) * power swap and set the delayed override for swap completion. */ else if (!is_sink(port) && dualrole_capability[port] == CAP_DUALROLE) { - delayed_override_deadline.val = get_time().val + - POWER_SWAP_TIMEOUT; + delayed_override_deadline.val = + get_time().val + POWER_SWAP_TIMEOUT; delayed_override_port = port; hook_call_deferred(&charge_override_timeout_data, POWER_SWAP_TIMEOUT); pd_request_power_swap(port); - /* Can't charge from requested port -- return error. */ + /* Can't charge from requested port -- return error. */ } else retval = EC_ERROR_INVAL; @@ -1198,11 +1398,13 @@ int charge_manager_get_power_limit_uw(void) return current_ma * voltage_mv; } -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT +#if defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) && \ + !defined(CONFIG_USB_PD_TCPMV2) +/* Note: this functionality is a part of the TCPMv2 Device Poicy Manager */ /* Bitmap of ports used as power source */ static volatile uint32_t source_port_bitmap; -BUILD_ASSERT(sizeof(source_port_bitmap)*8 >= CONFIG_USB_PD_PORT_MAX_COUNT); +BUILD_ASSERT(sizeof(source_port_bitmap) * 8 >= CONFIG_USB_PD_PORT_MAX_COUNT); static inline int has_other_active_source(int port) { @@ -1233,7 +1435,7 @@ static int can_supply_max_current(int port) if (p == port) continue; if (source_port_rp[p] == - CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) + CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) return 0; } return 1; @@ -1248,9 +1450,9 @@ void charge_manager_source_port(int port, int enable) int p, rp; if (enable) - deprecated_atomic_or(&source_port_bitmap, 1 << port); + atomic_or((atomic_t *)&source_port_bitmap, 1 << port); else - deprecated_atomic_clear_bits(&source_port_bitmap, 1 << port); + atomic_clear_bits((atomic_t *)&source_port_bitmap, 1 << port); /* No change, exit early. */ if (prev_bitmap == source_port_bitmap) @@ -1259,8 +1461,8 @@ void charge_manager_source_port(int port, int enable) /* Set port limit according to policy */ for (p = 0; p < board_get_usb_pd_port_count(); p++) { rp = can_supply_max_current(p) ? - CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT : - CONFIG_USB_PD_PULLUP; + CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT : + CONFIG_USB_PD_PULLUP; source_port_rp[p] = rp; #ifdef CONFIG_USB_PD_LOGGING @@ -1287,9 +1489,8 @@ int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) *src_pdo = pd_src_pdo; return pd_src_pdo_cnt; } -#endif /* CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT */ +#endif /* CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT && !CONFIG_USB_PD_TCPMV2 */ -#ifndef TEST_BUILD static enum ec_status hc_pd_power_info(struct host_cmd_handler_args *args) { const struct ec_params_usb_pd_power_info *p = args->params; @@ -1313,10 +1514,8 @@ static enum ec_status hc_pd_power_info(struct host_cmd_handler_args *args) args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_POWER_INFO, - hc_pd_power_info, +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_POWER_INFO, hc_pd_power_info, EC_VER_MASK(0)); -#endif /* TEST_BUILD */ static enum ec_status hc_charge_port_count(struct host_cmd_handler_args *args) { @@ -1327,30 +1526,27 @@ static enum ec_status hc_charge_port_count(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_CHARGE_PORT_COUNT, - hc_charge_port_count, +DECLARE_HOST_COMMAND(EC_CMD_CHARGE_PORT_COUNT, hc_charge_port_count, EC_VER_MASK(0)); static enum ec_status hc_charge_port_override(struct host_cmd_handler_args *args) { const struct ec_params_charge_port_override *p = args->params; - const int16_t override_port = p->override_port; + const int16_t op = p->override_port; - if (override_port < OVERRIDE_DONT_CHARGE || - override_port >= CHARGE_PORT_COUNT) + if (op < OVERRIDE_DONT_CHARGE || op >= CHARGE_PORT_COUNT) return EC_RES_INVALID_PARAM; - return charge_manager_set_override(override_port) == EC_SUCCESS ? - EC_RES_SUCCESS : EC_RES_ERROR; + return charge_manager_set_override(op) == EC_SUCCESS ? EC_RES_SUCCESS : + EC_RES_ERROR; } -DECLARE_HOST_COMMAND(EC_CMD_PD_CHARGE_PORT_OVERRIDE, - hc_charge_port_override, +DECLARE_HOST_COMMAND(EC_CMD_PD_CHARGE_PORT_OVERRIDE, hc_charge_port_override, EC_VER_MASK(0)); #if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 -static enum ec_status hc_override_dedicated_charger_limit( - struct host_cmd_handler_args *args) +static enum ec_status +hc_override_dedicated_charger_limit(struct host_cmd_handler_args *args) { const struct ec_params_dedicated_charger_limit *p = args->params; struct charge_port_info ci = { @@ -1371,11 +1567,10 @@ static enum ec_status hc_override_dedicated_charger_limit( return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_OVERRIDE_DEDICATED_CHARGER_LIMIT, - hc_override_dedicated_charger_limit, - EC_VER_MASK(0)); + hc_override_dedicated_charger_limit, EC_VER_MASK(0)); #endif -static int command_charge_port_override(int argc, char **argv) +static int command_charge_port_override(int argc, const char **argv) { int port = OVERRIDE_OFF; int ret = EC_SUCCESS; @@ -1389,12 +1584,12 @@ static int command_charge_port_override(int argc, char **argv) ret = charge_manager_set_override(port); } - ccprintf("Override: %d\n", (argc >= 2 && ret == EC_SUCCESS) ? - port : override_port); + ccprintf("Override: %d\n", + (argc >= 2 && ret == EC_SUCCESS) ? port : override_port); return ret; } -DECLARE_CONSOLE_COMMAND(chgoverride, command_charge_port_override, - "[port | -1 | -2]", +DECLARE_CONSOLE_COMMAND( + chgoverride, command_charge_port_override, "[port | -1 | -2]", "Force charging from a given port (-1 = off, -2 = disable charging)"); #ifdef CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT @@ -1431,16 +1626,14 @@ hc_external_power_limit(struct host_cmd_handler_args *args) { const struct ec_params_external_power_limit_v1 *p = args->params; - charge_manager_set_external_power_limit(p->current_lim, - p->voltage_lim); + charge_manager_set_external_power_limit(p->current_lim, p->voltage_lim); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_EXTERNAL_POWER_LIMIT, - hc_external_power_limit, +DECLARE_HOST_COMMAND(EC_CMD_EXTERNAL_POWER_LIMIT, hc_external_power_limit, EC_VER_MASK(1)); -static int command_external_power_limit(int argc, char **argv) +static int command_external_power_limit(int argc, const char **argv) { int max_current; int max_voltage; @@ -1466,41 +1659,63 @@ static int command_external_power_limit(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(chglim, command_external_power_limit, - "[max_current (mA)] [max_voltage (mV)]", - "Set max charger current / voltage"); + "[max_current (mA)] [max_voltage (mV)]", + "Set max charger current / voltage"); #endif /* CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT */ #ifdef CONFIG_CMD_CHARGE_SUPPLIER_INFO -static int charge_supplier_info(int argc, char **argv) +static int charge_supplier_info(int argc, const char **argv) { - ccprintf("port=%d, type=%d, cur=%dmA, vtg=%dmV, lsm=%d\n", - charge_manager_get_active_charge_port(), - charge_supplier, - charge_current, - charge_voltage, - left_safe_mode); - + int p, s; + int port_printed; + + ccprintf("\n"); + ccprintf("Port --Supplier-- Prio -Available Power-\n"); + for (p = 0; p < CHARGE_PORT_COUNT; p++) { + port_printed = 0; + for (s = 0; s < CHARGE_SUPPLIER_COUNT; s++) { + if (available_charge[s][p].current == 0 && + available_charge[s][p].voltage == 0) + continue; + if (charge_manager_get_active_charge_port() == p && + charge_manager_get_supplier() == s) + ccprintf("*"); + else + ccprintf(" "); + if (!port_printed) { + ccprintf("P%d ", p); + port_printed = 1; + } else { + ccprintf(" "); + } + ccprintf("%-10s %4d %5dmA %5dmV\n", + charge_supplier_name[s], supplier_priority[s], + available_charge[s][p].current, + available_charge[s][p].voltage); + } + } + ccprintf("\n"); + ccprintf(" %s safe mode\n", left_safe_mode ? "Left" : "In"); + ccprintf(" Override port = P%d\n", charge_manager_get_override()); + ccprintf("\n"); return 0; } -DECLARE_CONSOLE_COMMAND(chgsup, charge_supplier_info, - NULL, "print chg supplier info"); +DECLARE_CONSOLE_COMMAND(chgsup, charge_supplier_info, NULL, + "print chg supplier info"); #endif -__overridable -int board_charge_port_is_sink(int port) +__overridable int board_charge_port_is_sink(int port) { return 1; } -__overridable -int board_charge_port_is_connected(int port) +__overridable int board_charge_port_is_connected(int port) { return 1; } -__overridable -void board_fill_source_power_info(int port, - struct ec_response_usb_pd_power_info *r) +__overridable void +board_fill_source_power_info(int port, struct ec_response_usb_pd_power_info *r) { r->meas.voltage_now = 0; r->meas.voltage_max = 0; @@ -1508,3 +1723,11 @@ void board_fill_source_power_info(int port, r->meas.current_lim = 0; r->max_power = 0; } + +__overridable void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ +#if defined(CONFIG_CHARGER) && defined(CONFIG_BATTERY) + charge_set_input_current_limit(charge_ma, charge_mv); +#endif +} diff --git a/common/charge_ramp.c b/common/charge_ramp.c index a408771f40..fcea02d1c7 100644 --- a/common/charge_ramp.c +++ b/common/charge_ramp.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,21 +18,37 @@ test_mockable int chg_ramp_allowed(int port, int supplier) return 0; switch (supplier) { - /* Use ramping for USB-C DTS suppliers (debug accessory eg suzy-q). */ + /* + * Use ramping for USB-C DTS suppliers (debug accessory eg suzy-q). + * The suzy-q simply passes through the VBUS. The power supplier behind + * may be a SDP/CDP which requires ramping. + */ case CHARGE_SUPPLIER_TYPEC_DTS: return 1; /* - * Use HW ramping for USB-C chargers. Don't use SW ramping since the - * slow ramp causes issues with auto power on (b/169634979). + * Don't regulate the input voltage for USB-C chargers. It is + * unnecessary as the USB-C compliant adapters should never trigger it + * active. + * + * The USB-C spec defines their load curves should not be below + * 4.75V @0A and 4V @3A. We can't define the voltage regulation value + * higher than 4V since it limits the current reaching its max 3A. If + * we define the voltage regulation value lower than 4V, their load + * curves will never be below the voltage regulation line. + * + * Check go/charge_ramp_typec for detail. */ case CHARGE_SUPPLIER_PD: case CHARGE_SUPPLIER_TYPEC: - return IS_ENABLED(CONFIG_CHARGE_RAMP_HW); - /* default: fall through */ + return 0; + /* default: fall through */ } +#ifdef CONFIG_USB_CHARGER /* Otherwise ask the BC1.2 detect module */ return usb_charger_ramp_allowed(port, supplier); +#endif + return 0; } test_mockable int chg_ramp_max(int port, int supplier, int sup_curr) @@ -40,15 +56,20 @@ test_mockable int chg_ramp_max(int port, int supplier, int sup_curr) switch (supplier) { case CHARGE_SUPPLIER_PD: case CHARGE_SUPPLIER_TYPEC: + return 0; + case CHARGE_SUPPLIER_TYPEC_DTS: /* * We should not ramp DTS beyond what they advertise, otherwise * we may brownout the systems they are connected to. */ return sup_curr; - /* default: fall through */ + /* default: fall through */ } +#ifdef CONFIG_USB_CHARGER /* Otherwise ask the BC1.2 detect module */ return usb_charger_ramp_max(port, supplier, sup_curr); +#endif + return 0; } diff --git a/common/charge_ramp_sw.c b/common/charge_ramp_sw.c index bfd6db057b..4e5bdc8149 100644 --- a/common/charge_ramp_sw.c +++ b/common/charge_ramp_sw.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,30 +16,30 @@ #include "usb_pd.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) /* Number of times to ramp current searching for limit before stable charging */ -#define RAMP_COUNT 3 +#define RAMP_COUNT 3 /* Maximum allowable time charger can be unplugged to be considered an OCP */ #define OC_RECOVER_MAX_TIME (SECOND) /* Delay for running state machine when board is not consuming full current */ -#define CURRENT_DRAW_DELAY (5*SECOND) +#define CURRENT_DRAW_DELAY (5 * SECOND) /* Current ramp increment */ -#define RAMP_CURR_INCR_MA 64 -#define RAMP_CURR_DELAY (500*MSEC) -#define RAMP_CURR_START_MA 500 +#define RAMP_CURR_INCR_MA 64 +#define RAMP_CURR_DELAY (500 * MSEC) +#define RAMP_CURR_START_MA 500 /* How much to backoff the input current limit when limit has been found */ -#define RAMP_ICL_BACKOFF (2*RAMP_CURR_INCR_MA) +#define RAMP_ICL_BACKOFF (2 * RAMP_CURR_INCR_MA) /* Interval at which VBUS voltage is monitored in stable state */ #define STABLE_VBUS_MONITOR_INTERVAL (SECOND) /* Time to delay for stablizing the charging current */ -#define STABLIZE_DELAY (5*SECOND) +#define STABLIZE_DELAY (5 * SECOND) enum chg_ramp_state { CHG_RAMP_DISCONNECTED, @@ -78,14 +78,13 @@ static int max_icl; static int min_icl; void chg_ramp_charge_supplier_change(int port, int supplier, int current, - timestamp_t registration_time, int voltage) + timestamp_t registration_time, int voltage) { /* * If the last active port was a valid port and the port * has changed, then this may have been an over-current. */ - if (active_port != CHARGE_PORT_NONE && - port != active_port) { + if (active_port != CHARGE_PORT_NONE && port != active_port) { if (oc_info_idx[active_port] == RAMP_COUNT - 1) oc_info_idx[active_port] = 0; else @@ -111,7 +110,8 @@ void chg_ramp_charge_supplier_change(int port, int supplier, int current, reg_time = registration_time; if (ramp_st != CHG_RAMP_STABILIZE) { ramp_st = (active_port == CHARGE_PORT_NONE) ? - CHG_RAMP_DISCONNECTED : CHG_RAMP_CHARGE_DETECT_DELAY; + CHG_RAMP_DISCONNECTED : + CHG_RAMP_CHARGE_DETECT_DELAY; CPRINTS("Ramp reset: st%d", ramp_st); task_wake(TASK_ID_CHG_RAMP); } @@ -153,7 +153,7 @@ void chg_ramp_task(void *u) int last_active_port = CHARGE_PORT_NONE; enum chg_ramp_state ramp_st_prev = CHG_RAMP_DISCONNECTED, - ramp_st_new = CHG_RAMP_DISCONNECTED; + ramp_st_new = CHG_RAMP_DISCONNECTED; int active_icl_new; /* Clear last OCP supplier to guarantee we ramp on first connect */ @@ -190,15 +190,15 @@ void chg_ramp_task(void *u) last_active_port = active_port; if (reg_time.val < ACTIVE_OC_INFO.ts.val + - OC_RECOVER_MAX_TIME) { + OC_RECOVER_MAX_TIME) { ACTIVE_OC_INFO.oc_detected = 1; } else { for (i = 0; i < RAMP_COUNT; ++i) - oc_info[active_port][i]. - oc_detected = 0; + oc_info[active_port][i] + .oc_detected = 0; } - detect_end_time_us = get_time().val + - CHARGE_DETECT_DELAY; + detect_end_time_us = + get_time().val + CHARGE_DETECT_DELAY; task_wait_time = CHARGE_DETECT_DELAY; break; } @@ -214,6 +214,7 @@ void chg_ramp_task(void *u) ramp_st_new = CHG_RAMP_OVERCURRENT_DETECT; /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); + __fallthrough; case CHG_RAMP_OVERCURRENT_DETECT: /* Check if we should ramp or go straight to stable */ task_wait_time = SECOND; @@ -246,8 +247,8 @@ void chg_ramp_task(void *u) if (i == RAMP_COUNT) { /* Found OC threshold! */ - active_icl_new = ACTIVE_OC_INFO.icl - - RAMP_ICL_BACKOFF; + active_icl_new = + ACTIVE_OC_INFO.icl - RAMP_ICL_BACKOFF; ramp_st_new = CHG_RAMP_STABLE; } else { /* @@ -272,8 +273,8 @@ void chg_ramp_task(void *u) if (board_is_vbus_too_low(active_port, CHG_RAMP_VBUS_RAMPING)) { CPRINTS("VBUS low"); - active_icl_new = MAX(min_icl, active_icl - - RAMP_ICL_BACKOFF); + active_icl_new = MAX( + min_icl, active_icl - RAMP_ICL_BACKOFF); ramp_st_new = CHG_RAMP_STABILIZE; task_wait_time = STABLIZE_DELAY; stablize_port = active_port; @@ -300,8 +301,8 @@ void chg_ramp_task(void *u) } ramp_st_new = active_port == CHARGE_PORT_NONE ? - CHG_RAMP_DISCONNECTED : - CHG_RAMP_CHARGE_DETECT_DELAY; + CHG_RAMP_DISCONNECTED : + CHG_RAMP_CHARGE_DETECT_DELAY; break; case CHG_RAMP_STABLE: /* Maintain input current limit */ @@ -320,7 +321,7 @@ void chg_ramp_task(void *u) CHG_RAMP_VBUS_STABLE)) { CPRINTS("VBUS low; Re-ramp"); max_icl = MAX(min_icl, - max_icl - RAMP_ICL_BACKOFF); + max_icl - RAMP_ICL_BACKOFF); active_icl_new = min_icl; ramp_st_new = CHG_RAMP_RAMP; } @@ -334,9 +335,9 @@ void chg_ramp_task(void *u) /* Skip setting limit if status is stable twice in a row */ if (ramp_st_prev != CHG_RAMP_STABLE || - ramp_st != CHG_RAMP_STABLE) { - CPRINTS("Ramp p%d st%d %dmA %dmA", - active_port, ramp_st, min_icl, active_icl); + ramp_st != CHG_RAMP_STABLE) { + CPRINTS("Ramp p%d st%d %dmA %dmA", active_port, ramp_st, + min_icl, active_icl); /* Set the input current limit */ lim = chg_ramp_get_current_limit(); board_set_charge_limit(active_port, active_sup, lim, @@ -356,13 +357,13 @@ void chg_ramp_task(void *u) } #ifdef CONFIG_CMD_CHGRAMP -static int command_chgramp(int argc, char **argv) +static int command_chgramp(int argc, const char **argv) { int i; int port; - ccprintf("Chg Ramp:\nState: %d\nMin ICL: %d\nActive ICL: %d\n", - ramp_st, min_icl, active_icl); + ccprintf("Chg Ramp:\nState: %d\nMin ICL: %d\nActive ICL: %d\n", ramp_st, + min_icl, active_icl); for (port = 0; port < board_get_usb_pd_port_count(); port++) { ccprintf("Port %d:\n", port); @@ -377,7 +378,6 @@ static int command_chgramp(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(chgramp, command_chgramp, - "", - "Dump charge ramp state info"); +DECLARE_CONSOLE_COMMAND(chgramp, command_chgramp, "", + "Dump charge ramp state info"); #endif diff --git a/common/charge_state.c b/common/charge_state.c new file mode 100644 index 0000000000..6dd7f3404d --- /dev/null +++ b/common/charge_state.c @@ -0,0 +1,2474 @@ +/* Copyright 2014 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery charging task and state machine. + */ + +#include "battery.h" +#include "battery_smart.h" +#include "builtin/assert.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "charger_base.h" +#include "charger_profile_override.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "math_util.h" +#include "power.h" +#include "printf.h" +#include "system.h" +#include "task.h" +#include "throttle_ap.h" +#include "timer.h" +#include "usb_common.h" +#include "usb_pd.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_CHARGER, outstr) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) + +/* Extra debugging prints when allocating power between lid and base. */ +#undef CHARGE_ALLOCATE_EXTRA_DEBUG + +#define CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US \ + (CONFIG_BATTERY_CRITICAL_SHUTDOWN_TIMEOUT * SECOND) +#define PRECHARGE_TIMEOUT_US (PRECHARGE_TIMEOUT * SECOND) + +#if defined(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT) || \ + defined(CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE) +#ifndef CONFIG_HOSTCMD_EVENTS +#error "Must define CONFIG_HOSTCMD_EVENTS" +#endif /* CONFIG_HOSTCMD_EVENTS */ +#endif + +#define BAT_MAX_DISCHG_CURRENT 5000 /* mA */ +#define BAT_LOW_VOLTAGE_THRESH 3200 /* mV */ + +#define BAT_OCP_TIMEOUT_US (60 * SECOND) +#define BAT_OCP_HYSTERESIS_PCT 10 +#define BAT_OCP_HYSTERESIS \ + (BAT_MAX_DISCHG_CURRENT * BAT_OCP_HYSTERESIS_PCT / 100) /* mA */ + +#define BAT_UVP_TIMEOUT_US (60 * SECOND) +#define BAT_UVP_HYSTERESIS_PCT 3 +#define BAT_UVP_HYSTERESIS \ + (BAT_LOW_VOLTAGE_THRESH * BAT_UVP_HYSTERESIS_PCT / 100) /* mV */ + +static timestamp_t uvp_throttle_start_time; + +static uint8_t battery_level_shutdown; + +/* + * State for charger_task(). Here so we can reset it on a HOOK_INIT, and + * because stack space is more limited than .bss + */ +static const struct battery_info *batt_info; +static struct charge_state_data curr; +static enum charge_state prev_state; +static int prev_ac, prev_charge, prev_disp_charge; +static enum battery_present prev_bp; +static unsigned int user_current_limit = -1U; +test_export_static timestamp_t shutdown_target_time; +static timestamp_t precharge_start_time; +static struct sustain_soc sustain_soc; +static struct current_limit { + uint32_t value; /* Charge limit to apply, in mA */ + int soc; /* Minimum battery SoC at which the limit will be applied. */ +} current_limit = { -1U, 0 }; + +/* State which is reported out from the charger or updated externally */ +struct state { + /* + * battery is full, i.e. not accepting current. + * Accessed externally via charge_get_percent() + */ + bool is_full; + /* exported by get_chg_ctrl_mode() */ + enum ec_charge_control_mode chg_ctl_mode; + /** + * Manual voltage override (-1 = no override) + * Accessed externally via chgstate_set_manual_voltage() and + * charge_get_charge_state_debug() + */ + int manual_voltage; + /* + * Manual current override (-1 = no override) + * Accessed externally via chgstate_set_manual_current() and + * charge_get_charge_state_debug() + */ + int manual_current; + /* + * Accessed externally via charging_progress_displayed() and + * show_charging_progress() (the latter for testing only) + */ + bool is_charging_progress_displayed; +} local_state; + +/* + * The timestamp when the battery charging current becomes stable. + * When a new charging status happens, charger needs several seconds to + * stabilize the battery charging current. + * stable_current should be evaluated when stable_ts expired. + * stable_ts should be reset if the charger input voltage/current changes, + * or a new battery charging voltage/request happened. + * By evaluating stable_current, we can evaluate the battery's desired charging + * power desired_mw. This allow us to have a better charging efficiency by + * negotiating the most fit PDO, i.e. the PDO provides the power just enough for + * the system and battery, or the PDO with preferred voltage. + */ +STATIC_IF(CONFIG_USB_PD_PREFER_MV) timestamp_t stable_ts; +/* battery charging current evaluated after stable_ts expired */ +STATIC_IF(CONFIG_USB_PD_PREFER_MV) int stable_current; +/* battery desired power in mW. This is used to negotiate the suitable PDO */ +STATIC_IF(CONFIG_USB_PD_PREFER_MV) int desired_mw; +STATIC_IF_NOT(CONFIG_USB_PD_PREFER_MV) struct pd_pref_config_t pd_pref_config; + +/* Is battery connected but unresponsive after precharge? */ +static int battery_seems_dead; + +static int battery_seems_disconnected; + +/* + * Was battery removed? Set when we see BP_NO, cleared after the battery is + * reattached and becomes responsive. Used to indicate an error state after + * removal and trigger re-reading the battery static info when battery is + * reattached and responsive. + */ +static int battery_was_removed; + +static int problems_exist; + +static const char *const prob_text[] = { + "static update", "set voltage", "set current", "set mode", + "set input current", "post init", "chg params", "batt params", + "custom profile", "cfg secondary chg" +}; +BUILD_ASSERT(ARRAY_SIZE(prob_text) == NUM_PROBLEM_TYPES); + +#ifdef CONFIG_CHARGE_DEBUG +static bool is_debugging; +#endif + +void set_debugging(bool val) +{ +#ifdef CONFIG_CHARGE_DEBUG + is_debugging = val; +#endif +} + +static bool debugging(void) +{ +#ifdef CONFIG_CHARGE_DEBUG + return is_debugging; +#else + return false; +#endif +} + +/* + * TODO(crosbug.com/p/27639): When do we decide a problem is real and not + * just intermittent? And what do we do about it? + */ +void charge_problem(enum problem_type p, int v) +{ + static int last_prob_val[NUM_PROBLEM_TYPES]; + static timestamp_t last_prob_time[NUM_PROBLEM_TYPES]; + timestamp_t t_now, t_diff; + + if (last_prob_val[p] != v) { + t_now = get_time(); + t_diff.val = t_now.val - last_prob_time[p].val; + CPRINTS("charge problem: %s, 0x%x -> 0x%x after %.6" PRId64 "s", + prob_text[p], last_prob_val[p], v, t_diff.val); + last_prob_val[p] = v; + last_prob_time[p] = t_now; + } + problems_exist = 1; +} + +enum ec_charge_control_mode get_chg_ctrl_mode(void) +{ + return local_state.chg_ctl_mode; +} + +void reset_prev_disp_charge(void) +{ + prev_disp_charge = -1; +} + +int battery_sustainer_set(int8_t lower, int8_t upper) +{ + if (lower == -1 || upper == -1) { + CPRINTS("Sustainer disabled"); + sustain_soc.lower = -1; + sustain_soc.upper = -1; + sustain_soc.flags = 0; + return EC_SUCCESS; + } + + if (lower <= upper && 0 <= lower && upper <= 100) { + /* Currently sustainer requires discharge_on_ac. */ + if (!IS_ENABLED(CONFIG_CHARGER_DISCHARGE_ON_AC)) + return EC_RES_UNAVAILABLE; + sustain_soc.lower = lower; + sustain_soc.upper = upper; + CPRINTS("Sustainer set: %d%% ~ %d%%", lower, upper); + return EC_SUCCESS; + } + + CPRINTS("Invalid param: %s(%d, %d)", __func__, lower, upper); + return EC_ERROR_INVAL; +} + +static void battery_sustainer_disable(void) +{ + battery_sustainer_set(-1, -1); +} + +bool battery_sustainer_enabled(void) +{ + return sustain_soc.lower != -1 && sustain_soc.upper != -1; +} + +static const char *const state_list[] = { "idle", "discharge", "charge", + "precharge" }; +BUILD_ASSERT(ARRAY_SIZE(state_list) == NUM_STATES_V2); +static const char *const batt_pres[] = { + "NO", + "YES", + "NOT_SURE", +}; + +const char *mode_text[] = EC_CHARGE_MODE_TEXT; +BUILD_ASSERT(ARRAY_SIZE(mode_text) == CHARGE_CONTROL_COUNT); + +static void dump_charge_state(void) +{ +#define DUMP(FLD, FMT) ccprintf(#FLD " = " FMT "\n", curr.FLD) +#define DUMP_CHG(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.chg.FLD) +#define DUMP_BATT(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.batt.FLD) +#define DUMP_OCPC(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.ocpc.FLD) + + enum ec_charge_control_mode cmode = get_chg_ctrl_mode(); + + ccprintf("state = %s\n", state_list[curr.state]); + DUMP(ac, "%d"); + DUMP(batt_is_charging, "%d"); + ccprintf("chg.*:\n"); + DUMP_CHG(voltage, "%dmV"); + DUMP_CHG(current, "%dmA"); + DUMP_CHG(input_current, "%dmA"); + DUMP_CHG(status, "0x%x"); + DUMP_CHG(option, "0x%x"); + DUMP_CHG(flags, "0x%x"); + cflush(); + ccprintf("batt.*:\n"); + ccprintf("\ttemperature = %dC\n", + DECI_KELVIN_TO_CELSIUS(curr.batt.temperature)); + DUMP_BATT(state_of_charge, "%d%%"); + DUMP_BATT(voltage, "%dmV"); + DUMP_BATT(current, "%dmA"); + DUMP_BATT(desired_voltage, "%dmV"); + DUMP_BATT(desired_current, "%dmA"); + DUMP_BATT(flags, "0x%x"); + DUMP_BATT(remaining_capacity, "%dmAh"); + DUMP_BATT(full_capacity, "%dmAh"); + ccprintf("\tis_present = %s\n", batt_pres[curr.batt.is_present]); + cflush(); +#ifdef CONFIG_OCPC + ccprintf("ocpc.*:\n"); + DUMP_OCPC(active_chg_chip, "%d"); + DUMP_OCPC(combined_rsys_rbatt_mo, "%dmOhm"); + if ((curr.ocpc.active_chg_chip != -1) && + !(curr.ocpc.chg_flags[curr.ocpc.active_chg_chip] & + OCPC_NO_ISYS_MEAS_CAP)) { + DUMP_OCPC(rbatt_mo, "%dmOhm"); + DUMP_OCPC(rsys_mo, "%dmOhm"); + DUMP_OCPC(isys_ma, "%dmA"); + } + DUMP_OCPC(vsys_aux_mv, "%dmV"); + DUMP_OCPC(vsys_mv, "%dmV"); + DUMP_OCPC(primary_vbus_mv, "%dmV"); + DUMP_OCPC(primary_ibus_ma, "%dmA"); + DUMP_OCPC(secondary_vbus_mv, "%dmV"); + DUMP_OCPC(secondary_ibus_ma, "%dmA"); + DUMP_OCPC(last_error, "%d"); + DUMP_OCPC(integral, "%d"); + DUMP_OCPC(last_vsys, "%dmV"); + cflush(); +#endif /* CONFIG_OCPC */ + DUMP(requested_voltage, "%dmV"); + DUMP(requested_current, "%dmA"); +#ifdef CONFIG_CHARGER_OTG + DUMP(output_current, "%dmA"); +#endif + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT)) { + ccprintf("input_voltage = %dmV\n", + charger_base_get_input_voltage(&curr)); + } + ccprintf("chg_ctl_mode = %s (%d)\n", + cmode < CHARGE_CONTROL_COUNT ? mode_text[cmode] : "UNDEF", + cmode); + ccprintf("manual_voltage = %d\n", local_state.manual_voltage); + ccprintf("manual_current = %d\n", local_state.manual_current); + ccprintf("user_current_limit = %dmA\n", user_current_limit); + ccprintf("battery_seems_dead = %d\n", battery_seems_dead); + ccprintf("battery_seems_disconnected = %d\n", + battery_seems_disconnected); + ccprintf("battery_was_removed = %d\n", battery_was_removed); + ccprintf("debug output = %s\n", debugging() ? "on" : "off"); + ccprintf("Battery sustainer = %s (%d%% ~ %d%%)\n", + battery_sustainer_enabled() ? "on" : "off", sustain_soc.lower, + sustain_soc.upper); +#undef DUMP +} + +bool charging_progress_displayed(void) +{ + bool rv = local_state.is_charging_progress_displayed; + + local_state.is_charging_progress_displayed = false; + return rv; +} + +/* Output to the console so progress is visible */ +static void show_charging_progress(bool is_full) +{ + int rv = 0, minutes, to_full, chgnum = 0; + int dsoc; + + if (IS_ENABLED(TEST_BUILD)) + local_state.is_charging_progress_displayed = true; +#ifdef CONFIG_BATTERY_SMART + /* + * Predicted remaining battery capacity based on AverageCurrent(). + * 65535 = Battery is not being discharged. + */ + if (!battery_time_to_empty(&minutes) && minutes != 65535) + to_full = 0; + /* + * Predicted time-to-full charge based on AverageCurrent(). + * 65535 = Battery is not being discharged. + */ + else if (!battery_time_to_full(&minutes) && minutes != 65535) + to_full = 1; + /* + * If both time to empty and time to full have invalid data, consider + * measured current from the coulomb counter and ac present status to + * decide whether battery is about to full or empty. + */ + else { + to_full = curr.batt_is_charging; + rv = EC_ERROR_UNKNOWN; + } +#else + if (!curr.batt_is_charging) { + rv = battery_time_to_empty(&minutes); + to_full = 0; + } else { + rv = battery_time_to_full(&minutes); + to_full = 1; + } +#endif + + dsoc = charge_get_display_charge(); + if (rv) + CPRINTS("Battery %d%% (Display %d.%d %%) / ??h:?? %s%s", + curr.batt.state_of_charge, dsoc / 10, dsoc % 10, + to_full ? "to full" : "to empty", + is_full ? ", not accepting current" : ""); + else + CPRINTS("Battery %d%% (Display %d.%d %%) / %dh:%d %s%s", + curr.batt.state_of_charge, dsoc / 10, dsoc % 10, + minutes / 60, minutes % 60, + to_full ? "to full" : "to empty", + is_full ? ", not accepting current" : ""); + + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT)) + charger_base_show_charge(); + + if (debugging()) { + ccprintf("battery:\n"); + print_battery_debug(); + ccprintf("charger:\n"); + if (IS_ENABLED(CONFIG_OCPC)) + chgnum = charge_get_active_chg_chip(); + print_charger_debug(chgnum); + ccprintf("chg:\n"); + dump_charge_state(); + } +} + +/* Calculate if battery is full based on whether it is accepting charge */ +test_mockable int calc_is_full(void) +{ + static int ret; + + /* If bad state of charge reading, return last value */ + if (curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE || + curr.batt.state_of_charge > 100) + return ret; + /* + * Battery is full when SoC is above 90% and battery desired current + * is 0. This is necessary because some batteries stop charging when + * the SoC still reports <100%, so we need to check desired current + * to know if it is actually full. + */ + ret = (curr.batt.state_of_charge >= 90 && + curr.batt.desired_current == 0); + return ret; +} + +__overridable int board_should_charger_bypass(void) +{ + return false; +} + +#ifdef CONFIG_CHARGER_BYPASS_REVERSE_TURBO +int board_want_charger_change_mode(void) +{ + static int pre_batt = BP_YES; + int curr_batt = battery_is_present(); + + if (pre_batt != curr_batt) { + pre_batt = curr_batt; + return true; + } else + return false; +} +#endif + +int charge_request(bool use_curr, bool is_full) +{ + int r1 = EC_SUCCESS, r2 = EC_SUCCESS, r3 = EC_SUCCESS, r4 = EC_SUCCESS; + static int prev_volt, prev_curr; + bool should_bypass; + int voltage = 0, current = 0; + + if (use_curr) { + voltage = curr.requested_voltage; + current = curr.requested_current; + } + if (!voltage || !current) { +#ifdef CONFIG_CHARGER_NARROW_VDC + current = 0; + /* + * With NVDC charger, keep VSYS voltage higher than battery, + * otherwise the BGATE FET body diode would conduct and + * discharge the battery. + */ + voltage = charger_closest_voltage( + curr.batt.voltage + charger_get_info()->voltage_step); + /* If the battery is full, request the max voltage. */ + if (is_full) + voltage = battery_get_info()->voltage_max; + /* And handle dead battery case */ + voltage = MAX(voltage, battery_get_info()->voltage_normal); +#else + voltage = current = 0; +#endif + } + + if (curr.ac) { + if (prev_volt != voltage || prev_curr != current) + CPRINTS("%s(%dmV, %dmA)", __func__, voltage, current); + } + + /* + * Enable bypass mode if applicable. Transition from Bypass to Bypass + + * CHRG or backward is done after this call (by set_current & set_mode) + * thus not done here. Similarly, when bypass is disabled, transitioning + * from nvdc + chrg will be done separately. + */ + should_bypass = board_should_charger_bypass(); + if ((should_bypass && !(curr.chg.status & CHARGER_BYPASS_MODE)) || + (!should_bypass && (curr.chg.status & CHARGER_BYPASS_MODE)) +#ifdef CONFIG_CHARGER_BYPASS_REVERSE_TURBO + || board_want_charger_change_mode() +#endif + ) + charger_enable_bypass_mode(0, should_bypass); + + /* + * Set current before voltage so that if we are just starting + * to charge, we allow some time (i2c delay) for charging circuit to + * start at a voltage just above battery voltage before jumping + * up. This helps avoid large current spikes when connecting + * battery. + */ + if (current >= 0) { +#ifdef CONFIG_OCPC + /* + * For OCPC systems, don't unconditionally modify the primary + * charger IC's charge current. It may be handled by the + * charger drivers directly. + */ + if (curr.ocpc.active_chg_chip == CHARGER_PRIMARY) +#endif + r2 = charger_set_current(0, current); + } + if (r2 != EC_SUCCESS) + charge_problem(PR_SET_CURRENT, r2); + + if (voltage >= 0) + r1 = charger_set_voltage(0, voltage); + if (r1 != EC_SUCCESS) + charge_problem(PR_SET_VOLTAGE, r1); + +#ifdef CONFIG_OCPC + /* + * For OCPC systems, if the secondary charger is active, we need to + * configure that charge IC as well. Note that if OCPC ever supports + * more than 2 charger ICs, we'll need to refactor things a bit. The + * following check should be comparing against CHARGER_PRIMARY and + * config_secondary_charger should probably be config_auxiliary_charger + * and take the active chgnum as a parameter. + */ + if (curr.ocpc.active_chg_chip == CHARGER_SECONDARY) { + if ((current >= 0) || (voltage >= 0)) + r3 = ocpc_config_secondary_charger( + &curr.desired_input_current, &curr.ocpc, + voltage, current); + if (r3 != EC_SUCCESS) + charge_problem(PR_CFG_SEC_CHG, r3); + } +#endif /* CONFIG_OCPC */ + + /* + * Set the charge inhibit bit when possible as it appears to save + * power in some cases (e.g. Nyan with BQ24735). + */ + if (voltage > 0 || current > 0) + r4 = charger_set_mode(0); + else + r4 = charger_set_mode(CHARGE_FLAG_INHIBIT_CHARGE); + if (r4 != EC_SUCCESS) + charge_problem(PR_SET_MODE, r4); + + /* + * Only update if the request worked, so we'll keep trying on failures. + */ + if (r1 || r2) + return r1 ? r1 : r2; + if (IS_ENABLED(CONFIG_OCPC) && r3) + return r3; + + if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV) && + (prev_volt != voltage || prev_curr != current)) + charge_reset_stable_current(); + + prev_volt = voltage; + prev_curr = current; + + return EC_SUCCESS; +} + +void chgstate_set_manual_current(int curr_ma) +{ + if (curr_ma < 0) + local_state.manual_current = -1; + else + local_state.manual_current = charger_closest_current(curr_ma); +} + +void chgstate_set_manual_voltage(int volt_mv) +{ + local_state.manual_voltage = charger_closest_voltage(volt_mv); +} + +/* Force charging off before the battery is full. */ +int set_chg_ctrl_mode(enum ec_charge_control_mode mode) +{ + bool discharge_on_ac = false; + int current, voltage; + int rv; + + current = local_state.manual_current; + voltage = local_state.manual_voltage; + + if (mode >= CHARGE_CONTROL_COUNT) + return EC_ERROR_INVAL; + + if (mode == CHARGE_CONTROL_NORMAL) { + current = -1; + voltage = -1; + } else { + /* Changing mode is only meaningful if AC is present. */ + if (!curr.ac) + return EC_ERROR_NOT_POWERED; + + if (mode == CHARGE_CONTROL_DISCHARGE) { + if (!IS_ENABLED(CONFIG_CHARGER_DISCHARGE_ON_AC)) + return EC_ERROR_UNIMPLEMENTED; + discharge_on_ac = true; + } else if (mode == CHARGE_CONTROL_IDLE) { + current = 0; + voltage = 0; + } + } + + if (IS_ENABLED(CONFIG_CHARGER_DISCHARGE_ON_AC)) { + rv = charger_discharge_on_ac(discharge_on_ac); + if (rv != EC_SUCCESS) + return rv; + } + + /* Commit all atomically */ + local_state.chg_ctl_mode = mode; + local_state.manual_current = current; + local_state.manual_voltage = voltage; + + return EC_SUCCESS; +} + +static inline int battery_too_hot(int batt_temp_c) +{ + return (!(curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) && + (batt_temp_c > batt_info->discharging_max_c)); +} + +static inline int battery_too_cold_for_discharge(int batt_temp_c) +{ + return (!(curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) && + (batt_temp_c < batt_info->discharging_min_c)); +} + +__attribute__((weak)) uint8_t board_set_battery_level_shutdown(void) +{ + return BATTERY_LEVEL_SHUTDOWN; +} + +/* True if we know the charge is too low, or we know the voltage is too low. */ +static inline int battery_too_low(void) +{ + return ((!(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && + curr.batt.state_of_charge < battery_level_shutdown) || + (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) && + curr.batt.voltage <= batt_info->voltage_min)); +} + +__attribute__((weak)) enum critical_shutdown +board_critical_shutdown_check(struct charge_state_data *curr) +{ +#ifdef CONFIG_BATTERY_CRITICAL_SHUTDOWN_CUT_OFF + return CRITICAL_SHUTDOWN_CUTOFF; +#elif defined(CONFIG_HIBERNATE) + return CRITICAL_SHUTDOWN_HIBERNATE; +#else + return CRITICAL_SHUTDOWN_IGNORE; +#endif +} + +static int is_battery_critical(void) +{ + int batt_temp_c = DECI_KELVIN_TO_CELSIUS(curr.batt.temperature); + + /* + * TODO(crosbug.com/p/27642): The thermal loop should watch the battery + * temp, so it can turn fans on. + */ + if (battery_too_hot(batt_temp_c)) { + CPRINTS("Batt too hot: %dC", batt_temp_c); + return 1; + } + + /* Note: the battery may run on AC without discharging when too cold */ + if (!curr.ac && battery_too_cold_for_discharge(batt_temp_c)) { + CPRINTS("Batt too cold: %dC", batt_temp_c); + return 1; + } + + if (battery_too_low() && !curr.batt_is_charging) { + CPRINTS("Low battery: %d%%, %dmV", curr.batt.state_of_charge, + curr.batt.voltage); + return 1; + } + + return 0; +} + +/* + * If the battery is at extremely low charge (and discharging) or extremely + * high temperature, the EC will notify the AP and start a timer. If the + * critical condition is not corrected before the timeout expires, the EC + * will shut down the AP (if the AP is not already off) and then optionally + * hibernate or cut off battery. + */ +static int shutdown_on_critical_battery(void) +{ + if (!is_battery_critical()) { + /* Reset shutdown warning time */ + shutdown_target_time.val = 0; + return 0; + } + + if (!shutdown_target_time.val) { + /* Start count down timer */ + CPRINTS("Start shutdown due to critical battery"); + shutdown_target_time.val = + get_time().val + CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US; + if (IS_ENABLED(CONFIG_HOSTCMD_EVENTS) && + !chipset_in_state(CHIPSET_STATE_ANY_OFF)) + host_set_single_event(EC_HOST_EVENT_BATTERY_SHUTDOWN); + return 1; + } + + if (!timestamp_expired(shutdown_target_time, 0)) + return 1; + + /* Timer has expired */ + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) { + switch (board_critical_shutdown_check(&curr)) { + case CRITICAL_SHUTDOWN_HIBERNATE: + if (IS_ENABLED(CONFIG_HIBERNATE)) { + /* + * If the chipset is on its way down but not + * quite there yet, give it a little time to + * get there. + */ + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) + sleep(1); + CPRINTS("Hibernate due to critical battery"); + cflush(); + system_hibernate(0, 0); + } + break; + case CRITICAL_SHUTDOWN_CUTOFF: + /* + * Give the chipset just a sec to get to off if + * it's trying. + */ + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) + sleep(1); + CPRINTS("Cutoff due to critical battery"); + cflush(); + board_cut_off_battery(); + break; + case CRITICAL_SHUTDOWN_IGNORE: + default: + break; + } + } else { + /* Timeout waiting for AP to shut down, so kill it */ + CPRINTS("charge force shutdown due to critical battery"); + chipset_force_shutdown(CHIPSET_SHUTDOWN_BATTERY_CRIT); + } + + return 1; +} + +int battery_is_below_threshold(enum batt_threshold_type type, bool transitioned) +{ + int threshold; + + /* We can't tell what the current charge is. Assume it's okay. */ + if (curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) + return 0; + + switch (type) { + case BATT_THRESHOLD_TYPE_LOW: + threshold = BATTERY_LEVEL_LOW; + break; + case BATT_THRESHOLD_TYPE_SHUTDOWN: + threshold = CONFIG_BATT_HOST_SHUTDOWN_PERCENTAGE; + break; + default: + return 0; + } + + return curr.batt.state_of_charge <= threshold && + (!transitioned || prev_charge > threshold); +} + +/* + * Send host events as the battery charge drops below certain thresholds. + * We handle forced shutdown and other actions elsewhere; this is just for the + * host events. We send these even if the AP is off, since the AP will read and + * discard any events it doesn't care about the next time it wakes up. + */ +static void notify_host_of_low_battery_charge(void) +{ + if (IS_ENABLED(CONFIG_HOSTCMD_EVENTS)) { + if (battery_is_below_threshold(BATT_THRESHOLD_TYPE_LOW, true)) + host_set_single_event(EC_HOST_EVENT_BATTERY_LOW); + + if (battery_is_below_threshold(BATT_THRESHOLD_TYPE_SHUTDOWN, + true)) + host_set_single_event(EC_HOST_EVENT_BATTERY_CRITICAL); + } +} + +static void set_charge_state(enum charge_state state) +{ + prev_state = curr.state; + curr.state = state; +} + +static void notify_host_of_low_battery_voltage(void) +{ + if (!IS_ENABLED(CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE)) + return; + + if ((curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) || + chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return; + + if (!uvp_throttle_start_time.val && + (curr.batt.voltage < BAT_LOW_VOLTAGE_THRESH)) { + throttle_ap(THROTTLE_ON, THROTTLE_SOFT, + THROTTLE_SRC_BAT_VOLTAGE); + uvp_throttle_start_time = get_time(); + } else if (uvp_throttle_start_time.val && + (curr.batt.voltage < + BAT_LOW_VOLTAGE_THRESH + BAT_UVP_HYSTERESIS)) { + /* + * Reset the timer when we are not sure if VBAT can stay + * above BAT_LOW_VOLTAGE_THRESH after we stop throttling. + */ + uvp_throttle_start_time = get_time(); + } else if (uvp_throttle_start_time.val && + (get_time().val > + uvp_throttle_start_time.val + BAT_UVP_TIMEOUT_US)) { + throttle_ap(THROTTLE_OFF, THROTTLE_SOFT, + THROTTLE_SRC_BAT_VOLTAGE); + uvp_throttle_start_time.val = 0; + } +} + +static void notify_host_of_over_current(struct batt_params *batt) +{ + static timestamp_t ocp_throttle_start_time; + + if (!IS_ENABLED(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT) || + (batt->flags & BATT_FLAG_BAD_CURRENT)) + return; + + if ((!ocp_throttle_start_time.val && + (batt->current < -BAT_MAX_DISCHG_CURRENT)) || + (ocp_throttle_start_time.val && + (batt->current < -BAT_MAX_DISCHG_CURRENT + BAT_OCP_HYSTERESIS))) { + ocp_throttle_start_time = get_time(); + throttle_ap(THROTTLE_ON, THROTTLE_SOFT, + THROTTLE_SRC_BAT_DISCHG_CURRENT); + } else if (ocp_throttle_start_time.val && + (get_time().val > + ocp_throttle_start_time.val + BAT_OCP_TIMEOUT_US)) { + /* + * Clear the timer and notify AP to stop throttling if + * we haven't seen over current for BAT_OCP_TIMEOUT_US. + */ + ocp_throttle_start_time.val = 0; + throttle_ap(THROTTLE_OFF, THROTTLE_SOFT, + THROTTLE_SRC_BAT_DISCHG_CURRENT); + } +} + +const struct batt_params *charger_current_battery_params(void) +{ + return &curr.batt; +} + +struct charge_state_data *charge_get_status(void) +{ + return &curr; +} + +/* Determine if the battery is outside of allowable temperature range */ +int battery_outside_charging_temperature(void) +{ + const struct battery_info *batt_info = battery_get_info(); + int batt_temp_c = DECI_KELVIN_TO_CELSIUS(curr.batt.temperature); + int max_c, min_c; + + if (curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) + return 0; + + if ((curr.batt.desired_voltage == 0) && + (curr.batt.desired_current == 0)) { + max_c = batt_info->start_charging_max_c; + min_c = batt_info->start_charging_min_c; + } else { + max_c = batt_info->charging_max_c; + min_c = batt_info->charging_min_c; + } + + if ((batt_temp_c >= max_c) || (batt_temp_c <= min_c)) { + return 1; + } + return 0; +} + +static enum ec_charge_control_mode +sustain_switch_mode(enum ec_charge_control_mode mode) +{ + enum ec_charge_control_mode new_mode = mode; + int soc = charge_get_display_charge() / 10; + + /* + * The sustain range is defined by 'lower' and 'upper' where the equal + * values are inclusive: + * + * |------------NORMAL------------+--IDLE--+---DISCHARGE---| + * 0% ^ ^ 100% + * lower upper + * + * The switch statement below allows the sustainer to start with any soc + * (0% ~ 100%) and any previous lower & upper limits. It sets mode to + * NORMAL to charge till the soc hits the upper limit or sets mode to + * DISCHARGE to discharge till the soc hits the upper limit. + * + * Once the soc enters in the sustain range, it'll switch to IDLE. In + * IDLE mode, the system power is supplied from the AC. Thus, the soc + * normally should stay in the sustain range unless there is high load + * on the system or the charger is too weak. + * + * Some boards have a sing capacitor problem with mode == IDLE. For such + * boards, a host can specify EC_CHARGE_CONTROL_FLAG_NO_IDLE, which + * makes the sustainer use DISCHARGE instead of IDLE. This is done by + * setting lower != upper in V2, which doesn't support the flag. + */ + switch (mode) { + case CHARGE_CONTROL_NORMAL: + /* Currently charging */ + if (sustain_soc.upper < soc) { + /* + * We come here only if the soc is already above the + * upper limit at the time the sustainer started. + */ + new_mode = CHARGE_CONTROL_DISCHARGE; + } else if (sustain_soc.upper == soc) { + /* + * We've been charging and finally reached the upper. + * Let's switch to IDLE to stay. + */ + if (sustain_soc.flags & EC_CHARGE_CONTROL_FLAG_NO_IDLE) + new_mode = CHARGE_CONTROL_DISCHARGE; + else + new_mode = CHARGE_CONTROL_IDLE; + } + break; + case CHARGE_CONTROL_IDLE: + /* Discharging naturally */ + if (soc < sustain_soc.lower) + /* + * Presumably, we stayed in the sustain range for a + * while but finally fell off the range. Let's charge to + * the upper. + */ + new_mode = CHARGE_CONTROL_NORMAL; + else if (sustain_soc.upper < soc) + /* + * This can happen only if sustainer is restarted with + * decreased upper limit. Let's discharge to the upper. + */ + new_mode = CHARGE_CONTROL_DISCHARGE; + break; + case CHARGE_CONTROL_DISCHARGE: + /* Discharging actively. */ + if (soc <= sustain_soc.upper && + !(sustain_soc.flags & EC_CHARGE_CONTROL_FLAG_NO_IDLE)) + /* + * Normal case. We've been discharging and finally + * reached the upper. Let's switch to IDLE to stay. + */ + new_mode = CHARGE_CONTROL_IDLE; + else if (soc < sustain_soc.lower) + /* + * This can happen only if sustainer is restarted with + * increase lower limit. Let's charge to the upper (then + * switch to IDLE). + */ + new_mode = CHARGE_CONTROL_NORMAL; + break; + default: + break; + } + + return new_mode; +} + +static void sustain_battery_soc(void) +{ + enum ec_charge_control_mode mode = get_chg_ctrl_mode(); + enum ec_charge_control_mode new_mode; + int rv; + + /* If either AC or battery is not present, nothing to do. */ + if (!curr.ac || curr.batt.is_present != BP_YES || + !battery_sustainer_enabled()) + return; + + new_mode = sustain_switch_mode(mode); + + if (new_mode == mode) + return; + + rv = set_chg_ctrl_mode(new_mode); + CPRINTS("%s: %s control mode to %s", __func__, + rv == EC_SUCCESS ? "Switched" : "Failed to switch", + mode_text[new_mode]); +} + +static void current_limit_battery_soc(void) +{ + if (user_current_limit != current_limit.value && + charge_get_display_charge() / 10 >= current_limit.soc) { + user_current_limit = current_limit.value; + CPRINTS("Current limit %dmA applied", user_current_limit); + } +} + +/*****************************************************************************/ +/* Hooks */ +void charger_init(void) +{ + /* Initialize current state */ + memset(&curr, 0, sizeof(curr)); + curr.batt.is_present = BP_NOT_SURE; + /* Manual voltage/current set to off */ + local_state.manual_voltage = -1; + local_state.manual_current = -1; + /* + * Other tasks read the params like state_of_charge at the beginning of + * their tasks. Make them ready first. + */ + battery_get_params(&curr.batt); + + battery_sustainer_disable(); +} +DECLARE_HOOK(HOOK_INIT, charger_init, HOOK_PRIO_DEFAULT); + +void charge_wakeup(void) +{ + task_wake(TASK_ID_CHARGER); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, charge_wakeup, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_AC_CHANGE, charge_wakeup, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_POWER_SUPPLY_CHANGE, charge_wakeup, HOOK_PRIO_DEFAULT); + +#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE +static void bat_low_voltage_throttle_reset(void) +{ + uvp_throttle_start_time.val = 0; +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, bat_low_voltage_throttle_reset, + HOOK_PRIO_DEFAULT); +#endif + +static int get_desired_input_current(enum battery_present batt_present, + const struct charger_info *const info) +{ + if (batt_present == BP_YES || system_is_locked() || base_connected()) { +#ifdef CONFIG_CHARGE_MANAGER + int ilim = charge_manager_get_charger_current(); + return ilim == CHARGE_CURRENT_UNINITIALIZED ? + CHARGE_CURRENT_UNINITIALIZED : + MAX(CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT, ilim); +#else + return CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT; +#endif + } else { +#ifdef CONFIG_USB_POWER_DELIVERY + return MIN(PD_MAX_CURRENT_MA, info->input_current_max); +#else +#ifdef CONFIG_CUSTOMIZED_DESIGN + int ilim = charge_manager_get_charger_current(); + return ilim == CHARGE_CURRENT_UNINITIALIZED ? + CHARGE_CURRENT_UNINITIALIZED : + MAX(CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT, ilim); +#else + return info->input_current_max; +#endif +#endif + } +} + +static void wakeup_battery(int *need_static) +{ + if (battery_seems_dead || battery_is_cut_off()) { + /* It's dead, do nothing */ + set_charge_state(ST_IDLE); + curr.requested_voltage = 0; + curr.requested_current = 0; + } else if (curr.state == ST_PRECHARGE && + (get_time().val > + precharge_start_time.val + PRECHARGE_TIMEOUT_US)) { + /* We've tried long enough, give up */ + CPRINTS("battery seems to be dead"); + battery_seems_dead = 1; + set_charge_state(ST_IDLE); + curr.requested_voltage = 0; + curr.requested_current = 0; + } else { + /* See if we can wake it up */ + if (curr.state != ST_PRECHARGE) { + CPRINTS("try to wake battery"); + precharge_start_time = get_time(); + *need_static = 1; + } + set_charge_state(ST_PRECHARGE); + curr.requested_voltage = batt_info->voltage_max; + curr.requested_current = batt_info->precharge_current; + } +} + +__test_only enum charge_state charge_get_state(void) +{ + return curr.state; +} + +static void deep_charge_battery(int *need_static) +{ + if ((curr.state == ST_IDLE) && + (curr.batt.flags & BATT_FLAG_DEEP_CHARGE)) { + /* Deep charge time out , do nothing */ + curr.requested_voltage = 0; + curr.requested_current = 0; + } else if (curr.state == ST_PRECHARGE && + (get_time().val > + precharge_start_time.val + + CONFIG_BATTERY_LOW_VOLTAGE_TIMEOUT)) { + /* We've tried long enough, give up */ + CPRINTS("Precharge for low voltage timed out"); + set_charge_state(ST_IDLE); + curr.requested_voltage = 0; + curr.requested_current = 0; + } else { + /* See if we can wake it up */ + if (curr.state != ST_PRECHARGE) { + CPRINTS("Start precharge for low voltage"); + precharge_start_time = get_time(); + *need_static = 1; + } + set_charge_state(ST_PRECHARGE); + curr.requested_voltage = batt_info->voltage_max; + curr.requested_current = batt_info->precharge_current; + curr.batt.flags |= BATT_FLAG_DEEP_CHARGE; + } +} + +static void revive_battery(int *need_static) +{ + if (IS_ENABLED(CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD) && + curr.requested_voltage == 0 && curr.requested_current == 0 && + curr.batt.state_of_charge == 0) { + /* + * Battery is dead, give precharge current + * TODO (crosbug.com/p/29467): remove this workaround + * for dead battery that requests no voltage/current + */ + curr.requested_voltage = batt_info->voltage_max; + curr.requested_current = batt_info->precharge_current; + } else if (IS_ENABLED(CONFIG_BATTERY_REVIVE_DISCONNECT) && + curr.requested_voltage == 0 && curr.requested_current == 0 && + battery_seems_disconnected) { + /* + * Battery is in disconnect state. Apply a + * current to kick it out of this state. + */ + CPRINTS("found battery in disconnect state"); + curr.requested_voltage = batt_info->voltage_max; + curr.requested_current = batt_info->precharge_current; + } else if (curr.state == ST_PRECHARGE || battery_seems_dead || + battery_was_removed) { + CPRINTS("battery woke up"); + /* Update the battery-specific values */ + batt_info = battery_get_info(); + *need_static = 1; + } + + battery_seems_dead = battery_was_removed = 0; +} + +/* Set up the initial state of the charger task */ +static void charger_setup(const struct charger_info *info) +{ + /* Get the battery-specific values */ + batt_info = battery_get_info(); + + prev_ac = prev_charge = prev_disp_charge = -1; + local_state.chg_ctl_mode = CHARGE_CONTROL_NORMAL; + shutdown_target_time.val = 0UL; + battery_seems_dead = 0; + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT)) { + charger_base_setup(); + charger_base_set_input_voltage(&curr, + CHARGE_VOLTAGE_UNINITIALIZED); + } +#ifdef CONFIG_OCPC + ocpc_init(&curr.ocpc); + charge_set_active_chg_chip(CHARGE_PORT_NONE); +#endif /* CONFIG_OCPC */ + + /* + * If system is not locked and we don't have a battery to live on, + * then use max input current limit so that we can pull as much power + * as needed. + */ + prev_bp = BP_NOT_INIT; + curr.desired_input_current = + get_desired_input_current(curr.batt.is_present, info); + + if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV)) { + /* init battery desired power */ + desired_mw = + curr.batt.desired_current * curr.batt.desired_voltage; + /* + * Battery charging current needs time to be stable when a + * new charge happens. Start the timer so we can evaluate the + * stable current when timeout. + */ + charge_reset_stable_current(); + } + + battery_level_shutdown = board_set_battery_level_shutdown(); +} + +/* check for and handle any state-of-charge change with the battery */ +void check_battery_change_soc(bool is_full, bool prev_full) +{ + if ((!(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && + curr.batt.state_of_charge != prev_charge) || + (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT) && + charger_base_charge_changed()) || + is_full != prev_full || (curr.state != prev_state) || + (charge_get_display_charge() != prev_disp_charge)) { + show_charging_progress(is_full); + prev_charge = curr.batt.state_of_charge; + prev_disp_charge = charge_get_display_charge(); + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT)) + charger_base_charge_update(); + hook_notify(HOOK_BATTERY_SOC_CHANGE); + } +} + +/* We've noticed a change in AC presence, let the board know */ +static void process_ac_change(const int chgnum) +{ + board_check_extpower(); + if (curr.ac) { + /* + * Some chargers are unpowered when the AC is off, so we'll + * reinitialize it when AC comes back and set the input current + * limit. Try again if it fails. + */ + int rv = charger_post_init(); + + if (rv != EC_SUCCESS) { + charge_problem(PR_POST_INIT, rv); + } else if (curr.desired_input_current != + CHARGE_CURRENT_UNINITIALIZED) { + rv = charger_set_input_current_limit( + chgnum, curr.desired_input_current); + if (rv != EC_SUCCESS) + charge_problem(PR_SET_INPUT_CURR, rv); + } + + if (rv == EC_SUCCESS) + prev_ac = curr.ac; + } else { + /* Some things are only meaningful on AC */ + set_chg_ctrl_mode(CHARGE_CONTROL_NORMAL); + battery_seems_dead = 0; + prev_ac = curr.ac; + + /* + * b/187967523, we should clear charge current, otherwise it + * will affect typeC output. This should be ok for all chargers. + */ + charger_set_current(chgnum, 0); + } +} + +/* Handle a change in the battery-present state */ +static void process_battery_present_change(const struct charger_info *info, + int chgnum) +{ + prev_bp = curr.batt.is_present; + + /* Update battery info due to change of battery */ + batt_info = battery_get_info(); + + curr.desired_input_current = get_desired_input_current(prev_bp, info); + if (curr.desired_input_current != CHARGE_CURRENT_UNINITIALIZED) + charger_set_input_current_limit(chgnum, + curr.desired_input_current); + hook_notify(HOOK_BATTERY_SOC_CHANGE); +} + +/* Decide on the charge state we are in */ +static void decide_charge_state(int *need_staticp, int *battery_criticalp) +{ + /* battery current stable now, so save the current. */ + if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV) && + get_time().val > stable_ts.val && curr.batt.current >= 0) + stable_current = curr.batt.current; + + /* + * Now decide what we want to do about it. We'll normally just pass + * along whatever the battery wants to the charger. Note that if + * battery_get_params() can't get valid values from the battery it uses + * (0, 0), which is probably safer than blindly applying power to a + * battery we can't talk to. + */ + if (curr.batt.flags & + (BATT_FLAG_BAD_DESIRED_VOLTAGE | BATT_FLAG_BAD_DESIRED_CURRENT)) { + curr.requested_voltage = 0; + curr.requested_current = 0; + } else { + curr.requested_voltage = curr.batt.desired_voltage; + curr.requested_current = curr.batt.desired_current; + } + + /* If we *know* there's no battery, wait for one to appear. */ + if (curr.batt.is_present == BP_NO) { + if (!curr.ac) + CPRINTS("running with no battery and no AC"); + set_charge_state(ST_IDLE); + curr.batt_is_charging = 0; + battery_was_removed = 1; + return; + } + + /* + * Always check the disconnect state if the battery is present. This is + * because the battery disconnect state is one of the items used to + * decide whether or not to leave safe mode. + * + * Note: For our purposes, an unresponsive battery is considered to be + * disconnected + */ + battery_seems_disconnected = battery_get_disconnect_state() != + BATTERY_NOT_DISCONNECTED; + + /* + * If we had trouble talking to the battery or the charger, we should + * probably do nothing for a bit, and if it doesn't get better then flag + * it as an error. + */ + if (curr.chg.flags & CHG_FLAG_BAD_ANY) + charge_problem(PR_CHG_FLAGS, curr.chg.flags); + if (curr.batt.flags & BATT_FLAG_BAD_ANY) + charge_problem(PR_BATT_FLAGS, curr.batt.flags); + + /* + * If AC is present, check if input current is sufficient to actually + * charge battery. + */ + curr.batt_is_charging = curr.ac && (curr.batt.current >= 0); + + /* Don't let the battery hurt itself. */ + *battery_criticalp = shutdown_on_critical_battery(); + + if (!curr.ac) { + set_charge_state(ST_DISCHARGE); + return; + } + + /* Okay, we're on AC and we should have a battery. */ + + /* Used for factory tests. */ + if (get_chg_ctrl_mode() != CHARGE_CONTROL_NORMAL) { + set_charge_state(ST_IDLE); + return; + } + + /* If the battery is not responsive, try to wake it up. */ + if (!(curr.batt.flags & BATT_FLAG_RESPONSIVE)) { + wakeup_battery(need_staticp); + return; + } + + /* + * When the battery voltage is lower than voltage_min,precharge first to + * protect the battery + */ + if (IS_ENABLED(CONFIG_BATTERY_LOW_VOLTAGE_PROTECTION)) { + if (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) && + curr.batt.voltage <= batt_info->voltage_min) { + deep_charge_battery(need_staticp); + return; + } + + /* + * Finished deep charge before timeout. Clear the flag so that + * we can do deep charge again (when it's deeply discharged + * again). + */ + if ((curr.batt.flags & BATT_FLAG_DEEP_CHARGE)) + curr.batt.flags &= ~BATT_FLAG_DEEP_CHARGE; + } + /* The battery is responding. Yay. Try to use it. */ + + revive_battery(need_staticp); + + set_charge_state(ST_CHARGE); +} + +/* Determine voltage/current to request and make it so */ +static void adjust_requested_vi(const struct charger_info *const info, + bool is_full) +{ + /* Turn charger off if it's not needed */ + if (!IS_ENABLED(CONFIG_CHARGER_MAINTAIN_VBAT) && + (curr.state == ST_IDLE || curr.state == ST_DISCHARGE)) { + curr.requested_voltage = 0; + curr.requested_current = 0; + } + + /* Apply external limits */ + if (curr.requested_current > user_current_limit) + curr.requested_current = user_current_limit; + + /* Round to valid values */ + curr.requested_voltage = + charger_closest_voltage(curr.requested_voltage); + curr.requested_current = + charger_closest_current(curr.requested_current); + + /* Charger only accepts request when AC is on. */ + if (curr.ac) { + /* + * Some batteries would wake up after cut-off if we keep + * charging it. Thus, we only charge when AC is on and battery + * is not cut off yet. + */ + if (battery_is_cut_off()) { + curr.requested_voltage = 0; + curr.requested_current = 0; + } + /* + * As a safety feature, some chargers will stop charging if we + * don't communicate with it frequently enough. In manual mode, + * we'll just tell it what it knows. + */ + else { + if (local_state.manual_voltage != -1) + curr.requested_voltage = + local_state.manual_voltage; + if (local_state.manual_current != -1) + curr.requested_current = + local_state.manual_current; + } + } else if (!IS_ENABLED(CONFIG_CHARGER_MAINTAIN_VBAT)) { + curr.requested_voltage = charger_closest_voltage( + curr.batt.voltage + info->voltage_step); + curr.requested_current = -1; + /* + * On EC-EC server, do not charge if curr.ac is 0: there might + * still be some external power available but we do not want to + * use it for charging. + */ + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_SERVER)) + curr.requested_current = 0; + } + + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT)) { + base_charge_allocate_input_current_limit(&curr, is_full, + debugging()); + } else { + charge_request(true, is_full); + } +} + +/* Handle selection of the preferred voltage */ +static void process_preferred_voltage(void) +{ + int is_pd_supply; + int port; + int bat_spec_desired_mw; + int prev_plt_and_desired_mw; + + /* sjg@: Attempt to get code coverage on this function b/281109948 */ + if (!IS_ENABLED(CONFIG_USB_PD_PREFER_MV)) + return; + + is_pd_supply = charge_manager_get_supplier() == CHARGE_SUPPLIER_PD; + port = charge_manager_get_active_charge_port(); + bat_spec_desired_mw = + curr.batt.desired_current * curr.batt.desired_voltage / 1000; + + /* save previous plt_and_desired_mw, since it will be updated below */ + prev_plt_and_desired_mw = charge_get_plt_plus_bat_desired_mw(); + + /* + * Update desired power by the following rules: + * 1. If the battery is not charging with PD, we reset the desired_mw to + * the battery spec. The actual desired_mw will be evaluated when it + * starts charging with PD again. + * 2. If the battery SoC under battery's constant voltage percent (this + * is a rough value that can be applied to most batteries), the battery + * can fully sink the power, the desired power should be the same as the + * battery spec, and we don't need to use evaluated value + * stable_current. + * 3. If the battery SoC is above battery's constant voltage percent, + * the real battery desired charging power will decrease slowly and so + * does the charging current. We can evaluate the battery desired power + * by the product of stable_current and battery voltage. + */ + if (!is_pd_supply) + desired_mw = bat_spec_desired_mw; + else if (curr.batt.state_of_charge < pd_pref_config.cv) + desired_mw = bat_spec_desired_mw; + else if (stable_current != CHARGE_CURRENT_UNINITIALIZED) + desired_mw = curr.batt.voltage * stable_current / 1000; + + /* if the plt_and_desired_mw changes, re-evaluate PDO */ + if (is_pd_supply && + prev_plt_and_desired_mw != charge_get_plt_plus_bat_desired_mw()) + pd_set_new_power_request(port); +} + +/* Calculate the sleep duration, before we run around the task loop again */ +int calculate_sleep_dur(int battery_critical, int sleep_usec) +{ + /* How long to sleep? */ + if (problems_exist) { + /* If there are errors, don't wait very long. */ + sleep_usec = CHARGE_POLL_PERIOD_SHORT; + } else if (sleep_usec <= 0) { + /* default values depend on the state */ + if (!curr.ac && + (curr.state == ST_IDLE || curr.state == ST_DISCHARGE)) { +#ifdef CONFIG_CHARGER_OTG + int output_current = curr.output_current; +#else + int output_current = 0; +#endif + /* + * If AP is off and we do not provide power, we can + * sleep a long time. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | + CHIPSET_STATE_ANY_SUSPEND) && + output_current == 0) + sleep_usec = CHARGE_POLL_PERIOD_VERY_LONG; + else +#ifndef CONFIG_CUSTOMIZED_DESIGN + /* Discharging, not too urgent */ + sleep_usec = CHARGE_POLL_PERIOD_LONG; +#else + sleep_usec = CHARGE_POLL_PERIOD_CHARGE; +#endif + } else { + /* AC present, so pay closer attention */ + sleep_usec = CHARGE_POLL_PERIOD_CHARGE; + } + } + + /* Adjust for time spent in the charge loop */ + sleep_usec -= (int)(get_time().val - curr.ts.val); + if (sleep_usec < CHARGE_MIN_SLEEP_USEC) + sleep_usec = CHARGE_MIN_SLEEP_USEC; + else if (sleep_usec > CHARGE_MAX_SLEEP_USEC) + sleep_usec = CHARGE_MAX_SLEEP_USEC; + + /* + * If battery is critical, ensure that the sleep time is not very long + * since we might want to hibernate or cut-off battery sooner. + */ + if (battery_critical && + (sleep_usec > CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US)) + sleep_usec = CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US; + + return sleep_usec; +} + +/* check external power and set curr.ac */ +static void check_extpower(int chgnum) +{ + curr.ac = extpower_is_present(); + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT)) { + if (base_check_extpower(curr.ac, prev_ac)) + curr.ac = 0; + } +} + +/* processing for new charge state, returning updated sleep_usec */ +static int process_charge_state(int *need_staticp, int sleep_usec) +{ + if (IS_ENABLED(CONFIG_CHARGER_PROFILE_OVERRIDE) && + get_chg_ctrl_mode() == CHARGE_CONTROL_NORMAL) { + sleep_usec = charger_profile_override(&curr); + if (sleep_usec < 0) + charge_problem(PR_CUSTOM, sleep_usec); + } + + if (IS_ENABLED(CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS) && + battery_outside_charging_temperature()) { + curr.requested_current = 0; + curr.requested_voltage = 0; + curr.batt.flags &= ~BATT_FLAG_WANT_CHARGE; + if (curr.state != ST_DISCHARGE) + curr.state = ST_IDLE; + } + + if (IS_ENABLED(CONFIG_CHARGE_MANAGER) && + curr.batt.state_of_charge >= + CONFIG_CHARGE_MANAGER_BAT_PCT_SAFE_MODE_EXIT && + !battery_seems_disconnected) + charge_manager_leave_safe_mode(); + + /* Keep the AP informed */ + if (*need_staticp) + *need_staticp = update_static_battery_info(); + + /* Wait on the dynamic info until the static info is good. */ + if (!*need_staticp) + update_dynamic_battery_info(); + notify_host_of_low_battery_charge(); + notify_host_of_low_battery_voltage(); + + return sleep_usec; +} + +/* Main loop */ +void charger_task(void *u) +{ + int sleep_usec; + int battery_critical; + int need_static = 1; + const struct charger_info *const info = charger_get_info(); + int chgnum = 0; + bool is_full = false; /* battery not accepting current */ + bool prev_full = false; + + /* Set up the task - note that charger_init() has already run. */ + charger_setup(info); + + while (1) { + /* Let's see what's going on... */ + curr.ts = get_time(); + sleep_usec = 0; + problems_exist = 0; + battery_critical = 0; + + check_extpower(chgnum); + if (curr.ac != prev_ac) + process_ac_change(chgnum); + + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT)) + base_update_battery_info(); + + charger_get_params(&curr.chg); + battery_get_params(&curr.batt); + +#ifdef CONFIG_CUSTOMIZED_DESIGN + battery_customize(&curr); +#endif + +#ifdef CONFIG_OCPC + if (curr.ac) + ocpc_get_adcs(&curr.ocpc); +#endif /* CONFIG_OCPC */ + + if (prev_bp != curr.batt.is_present) { + process_battery_present_change(info, chgnum); + need_static = 1; + } + + battery_validate_params(&curr.batt); + + notify_host_of_over_current(&curr.batt); + + decide_charge_state(&need_static, &battery_critical); + sleep_usec = process_charge_state(&need_static, sleep_usec); + + /* And the EC console */ + is_full = calc_is_full(); + + /* Run battery sustainer (no-op if not applicable). */ + sustain_battery_soc(); + + /* Run battery soc check for setting the current limit. */ + current_limit_battery_soc(); + + check_battery_change_soc(is_full, prev_full); + + prev_full = is_full; + + adjust_requested_vi(info, is_full); + + process_preferred_voltage(); + + /* Report our state */ + local_state.is_full = is_full; + + sleep_usec = calculate_sleep_dur(battery_critical, sleep_usec); + task_wait_event(sleep_usec); + } +} + +/*****************************************************************************/ +/* Exported functions */ + +int charge_want_shutdown(void) +{ + return (curr.state == ST_DISCHARGE) && + !(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && + (curr.batt.state_of_charge < battery_level_shutdown); +} + +#ifdef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON +test_export_static int charge_prevent_power_on_automatic_power_on = 1; +#endif + +bool charge_prevent_power_on(bool power_button_pressed) +{ + int prevent_power_on = 0; + struct batt_params params; + struct batt_params *current_batt_params = &curr.batt; + + /* If battery params seem uninitialized then retrieve them */ + if (current_batt_params->is_present == BP_NOT_SURE) { + battery_get_params(¶ms); + current_batt_params = ¶ms; + } + +#ifdef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON + + /* + * Remember that a power button was pressed, and assume subsequent + * power-ups are user-requested and non-automatic. + */ + if (power_button_pressed) + charge_prevent_power_on_automatic_power_on = 0; + /* + * Require a minimum battery level to power on and ensure that the + * battery can provide power to the system. + */ + if (current_batt_params->is_present != BP_YES || +#ifdef CONFIG_BATTERY_MEASURE_IMBALANCE + (current_batt_params->flags & BATT_FLAG_IMBALANCED_CELL && + current_batt_params->state_of_charge < + CONFIG_CHARGER_MIN_BAT_PCT_IMBALANCED_POWER_ON) || +#endif +#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT + battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED || +#endif + current_batt_params->state_of_charge < + CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) + prevent_power_on = 1; + +#if defined(CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON) && \ + defined(CONFIG_CHARGE_MANAGER) + /* However, we can power on if a sufficient charger is present. */ + if (prevent_power_on) { + if (charge_manager_get_power_limit_uw() >= + CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000) + prevent_power_on = 0; +#if defined(CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT) && \ + defined(CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC) + else if (charge_manager_get_power_limit_uw() >= + CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT * + 1000 +#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT + && battery_get_disconnect_state() == + BATTERY_NOT_DISCONNECTED +#endif + && (current_batt_params->state_of_charge >= + CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC)) + prevent_power_on = 0; +#endif + } +#endif /* CONFIG_CHARGE_MANAGER && CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON */ + + /* + * Factory override: Always allow power on if WP is disabled, + * except when auto-power-on at EC startup and the battery + * is physically present. + */ + prevent_power_on &= (system_is_locked() || + (charge_prevent_power_on_automatic_power_on +#ifdef CONFIG_BATTERY_HW_PRESENT_CUSTOM + + && battery_hw_present() == BP_YES +#endif + )); +#endif /* CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON */ + +#ifdef CONFIG_CHARGE_MANAGER + /* Always prevent power on until charge current is initialized */ + if (extpower_is_present() && (charge_manager_get_charger_current() == + CHARGE_CURRENT_UNINITIALIZED)) + prevent_power_on = 1; +#ifdef CONFIG_BATTERY_HW_PRESENT_CUSTOM + /* + * If battery is NOT physically present then prevent power on until + * a sufficient charger is present. + */ + if (extpower_is_present() && battery_hw_present() == BP_NO +#ifdef CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON + && charge_manager_get_power_limit_uw() < + CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000 +#endif /* CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON */ + ) + prevent_power_on = 1; +#endif /* CONFIG_BATTERY_HW_PRESENT_CUSTOM */ +#endif /* CONFIG_CHARGE_MANAGER */ + + /* + * Prevent power on if there is no battery nor ac power. This + * happens when the servo is powering the EC to flash it. Only + * include this logic for boards in initial bring up phase since + * this won't happen for released boards. + */ +#ifdef CONFIG_SYSTEM_UNLOCKED + if (!current_batt_params->is_present && !curr.ac) + prevent_power_on = 1; +#endif /* CONFIG_SYSTEM_UNLOCKED */ + + return prevent_power_on != 0; +} + +static int battery_near_full(void) +{ + if (charge_get_display_charge() < 1000) + return 0; + + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT) && + !charger_base_charge_near_full()) + return 0; + + return 1; +} + +enum led_pwr_state led_pwr_get_state(void) +{ + uint32_t chflags; + + switch (curr.state) { + case ST_IDLE: + chflags = charge_get_flags(); + + if (battery_seems_dead || curr.batt.is_present == BP_NO) + return LED_PWRS_ERROR; + + if (chflags & CHARGE_FLAG_FORCE_IDLE) + return LED_PWRS_FORCED_IDLE; + else + return LED_PWRS_IDLE; + case ST_DISCHARGE: +#ifdef CONFIG_PWR_STATE_DISCHARGE_FULL + if (battery_near_full()) + return LED_PWRS_DISCHARGE_FULL; + else +#endif + return LED_PWRS_DISCHARGE; + case ST_CHARGE: + /* The only difference here is what the LEDs display. */ + if (IS_ENABLED(CONFIG_CHARGE_MANAGER) && + charge_manager_get_active_charge_port() == CHARGE_PORT_NONE) + return LED_PWRS_DISCHARGE; + else if (battery_near_full()) + return LED_PWRS_CHARGE_NEAR_FULL; + else + return LED_PWRS_CHARGE; + case ST_PRECHARGE: + chflags = charge_get_flags(); + + /* we're in battery discovery mode */ + if (chflags & CHARGE_FLAG_FORCE_IDLE) + return LED_PWRS_FORCED_IDLE; + else + return LED_PWRS_IDLE; + default: + /* Anything else can be considered an error for LED purposes */ + return LED_PWRS_ERROR; + } +} + +uint32_t charge_get_flags(void) +{ + uint32_t flags = 0; + + if (get_chg_ctrl_mode() != CHARGE_CONTROL_NORMAL) + flags |= CHARGE_FLAG_FORCE_IDLE; + if (curr.ac) + flags |= CHARGE_FLAG_EXTERNAL_POWER; + if (curr.batt.flags & BATT_FLAG_RESPONSIVE) + flags |= CHARGE_FLAG_BATT_RESPONSIVE; + + return flags; +} + +int charge_get_percent(void) +{ + /* + * Since there's no way to indicate an error to the caller, we'll just + * return the last known value. Even if we've never been able to talk + * to the battery, that'll be zero, which is probably as good as + * anything. + */ + return local_state.is_full ? 100 : curr.batt.state_of_charge; +} + +test_mockable int charge_get_display_charge(void) +{ + return curr.batt.display_charge; +} + +int charge_get_battery_temp(int idx, int *temp_ptr) +{ + if (curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) + return EC_ERROR_UNKNOWN; + + /* Battery temp is 10ths of degrees K, temp wants degrees K */ + *temp_ptr = curr.batt.temperature / 10; + return EC_SUCCESS; +} + +__overridable int charge_is_consuming_full_input_current(void) +{ + int chg_pct = charge_get_percent(); + + return chg_pct > 2 && chg_pct < 95; +} + +#ifdef CONFIG_CHARGER_OTG +int charge_set_output_current_limit(int chgnum, int ma, int mv) +{ + int ret; + int enable = ma > 0; + + if (enable) { + ret = charger_set_otg_current_voltage(chgnum, ma, mv); + if (ret != EC_SUCCESS) + return ret; + } + + ret = charger_enable_otg_power(chgnum, enable); + if (ret != EC_SUCCESS) + return ret; + + /* If we start/stop providing power, wake the charger task. */ + if ((curr.output_current == 0 && enable) || + (curr.output_current > 0 && !enable)) + task_wake(TASK_ID_CHARGER); + + curr.output_current = ma; + + return EC_SUCCESS; +} +#endif + +int charge_set_input_current_limit(int ma, int mv) +{ + __maybe_unused int chgnum = 0; + +#ifdef CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT + if (CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT != 0) { + ma = (ma * (100 - CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT)) / + 100; + } +#endif +#ifdef CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT + if (CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT > 0) { + ma = MAX(ma, CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT); + } +#endif + + if (IS_ENABLED(CONFIG_OCPC)) + chgnum = charge_get_active_chg_chip(); + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT)) + charger_base_set_input_voltage(&curr, mv); + /* + * If battery is not present, we are not locked, and base is not + * connected then allow system to pull as much input current as needed. + * Yes, we might overcurrent the charger but this is no worse than + * browning out due to insufficient input current. + */ + if (curr.batt.is_present != BP_YES && !system_is_locked() && + !base_connected()) { + int prev_input = 0; + + charger_get_input_current_limit(chgnum, &prev_input); + +#ifdef CONFIG_USB_POWER_DELIVERY +#if ((PD_MAX_POWER_MW * 1000) / PD_MAX_VOLTAGE_MV != PD_MAX_CURRENT_MA) + /* + * If battery is not present, input current is set to + * PD_MAX_CURRENT_MA. If the input power set is greater than + * the maximum allowed system power, system might get damaged. + * Hence, limit the input current to meet maximum allowed + * input system power. + */ + + if (mv > 0 && + mv * curr.desired_input_current > PD_MAX_POWER_MW * 1000) + ma = (PD_MAX_POWER_MW * 1000) / mv; + /* + * If the active charger has already been initialized to at + * least this current level, nothing left to do. + */ + else if (prev_input >= ma) + return EC_SUCCESS; +#else + if (prev_input >= ma) + return EC_SUCCESS; +#endif + /* + * If the current needs lowered due to PD max power + * considerations, or needs raised for the selected + * active charger chip, fall through to set. + */ +#endif /* CONFIG_USB_POWER_DELIVERY */ + } + +#ifdef CONFIG_CHARGER_MAX_INPUT_CURRENT + /* Limit input current limit to max limit for this board */ + ma = MIN(ma, CONFIG_CHARGER_MAX_INPUT_CURRENT); +#endif + +#if !defined(CONFIG_CHARGER_BYPASS_MODE) || !defined(CONFIG_CUSTOMIZED_DESIGN) + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { + int pd_current_uncapped = + charge_manager_get_pd_current_uncapped(); + + /* + * clamp the input current to not exceeded the PD's limitation. + */ + if (pd_current_uncapped != CHARGE_CURRENT_UNINITIALIZED && + ma > pd_current_uncapped) + ma = pd_current_uncapped; + } +#endif + + curr.desired_input_current = ma; + if (IS_ENABLED(CONFIG_EC_EC_COMM_BATTERY_CLIENT)) { + /* + * Wake up charger task to allocate current between lid and + * base. + */ + charge_wakeup(); + return EC_SUCCESS; + } else { + return charger_set_input_current_limit(chgnum, ma); + } +} + +#ifdef CONFIG_OCPC +void charge_set_active_chg_chip(int idx) +{ + ASSERT(idx < (int)board_get_charger_chip_count()); + + if (idx == curr.ocpc.active_chg_chip) + return; + + CPRINTS("Act Chg: %d", idx); + curr.ocpc.active_chg_chip = idx; +} +#endif /* CONFIG_OCPC */ + +int charge_get_active_chg_chip(void) +{ +#ifdef CONFIG_OCPC + return curr.ocpc.active_chg_chip; +#else + return 0; +#endif +} + +#ifdef CONFIG_USB_PD_PREFER_MV +bool charge_is_current_stable(void) +{ + return get_time().val >= stable_ts.val; +} + +int charge_get_plt_plus_bat_desired_mw(void) +{ + /* + * Ideally, the system consuming power could be evaluated by + * "IBus * VBus - battery charging power". But in practice, + * most charger drivers don't implement IBUS ADC reading, + * so we use system PLT instead as an alterntaive approach. + */ + return pd_pref_config.plt_mw + desired_mw; +} + +int charge_get_stable_current(void) +{ + return stable_current; +} + +void charge_set_stable_current(int ma) +{ + stable_current = ma; +} + +void charge_reset_stable_current_us(uint64_t us) +{ + timestamp_t now = get_time(); + + if (stable_ts.val < now.val + us) + stable_ts.val = now.val + us; + + stable_current = CHARGE_CURRENT_UNINITIALIZED; +} + +void charge_reset_stable_current(void) +{ + /* it takes 8 to 10 seconds to stabilize battery current in practice */ + charge_reset_stable_current_us(10 * SECOND); +} +#endif + +#ifdef CONFIG_OCPC +void trigger_ocpc_reset(void) +{ + ocpc_reset(&curr.ocpc); +} +#endif + +/*****************************************************************************/ +/* Host commands */ + +static enum ec_status +charge_command_charge_control(struct host_cmd_handler_args *args) +{ + const struct ec_params_charge_control *p = args->params; + struct ec_response_charge_control *r = args->response; + int rv; + + if (p->cmd == EC_CHARGE_CONTROL_CMD_SET) { + if (p->mode == CHARGE_CONTROL_NORMAL) { + rv = battery_sustainer_set(p->sustain_soc.lower, + p->sustain_soc.upper); + if (rv == EC_RES_UNAVAILABLE) + return EC_RES_UNAVAILABLE; + if (rv) + return EC_RES_INVALID_PARAM; + if (args->version == 2) { + /* + * V2 uses lower == upper to indicate NO_IDLE. + * TODO: Remove this if-branch once all OS-side + * components are updated to v3. + */ + if (sustain_soc.lower < sustain_soc.upper) + sustain_soc.flags = + EC_CHARGE_CONTROL_FLAG_NO_IDLE; + } else { + sustain_soc.flags = p->flags; + } + } else { + battery_sustainer_disable(); + } + } else if (p->cmd == EC_CHARGE_CONTROL_CMD_GET) { + r->mode = get_chg_ctrl_mode(); + r->sustain_soc.lower = sustain_soc.lower; + r->sustain_soc.upper = sustain_soc.upper; + if (args->version > 2) + r->flags = sustain_soc.flags; + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; + } else { + return EC_RES_INVALID_PARAM; + } + + rv = set_chg_ctrl_mode(p->mode); + if (rv != EC_SUCCESS) + return EC_RES_ERROR; + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_CHARGE_CONTROL, charge_command_charge_control, + EC_VER_MASK(2) | EC_VER_MASK(3)); + +static enum ec_status +charge_command_current_limit(struct host_cmd_handler_args *args) +{ + if (args->version == 0) { + const struct ec_params_current_limit *p = args->params; + user_current_limit = p->limit; + current_limit.value = p->limit; + } else { + const struct ec_params_current_limit_v1 *p = args->params; + + /* Check if battery state of charge param is within range */ + if (p->battery_soc > 100) { + CPRINTS("Invalid battery_soc: %d", p->battery_soc); + return EC_RES_INVALID_PARAM; + } + + current_limit.value = p->limit; + current_limit.soc = p->battery_soc; + } + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_CHARGE_CURRENT_LIMIT, charge_command_current_limit, + EC_VER_MASK(0) | EC_VER_MASK(1)); + +/* + * Expose charge/battery related state + * + * @param param command to get corresponding data + * @param value the corresponding data + * @return EC_SUCCESS or error + */ +static int charge_get_charge_state_debug(int param, uint32_t *value) +{ + switch (param) { + case CS_PARAM_DEBUG_CTL_MODE: + *value = get_chg_ctrl_mode(); + break; + case CS_PARAM_DEBUG_MANUAL_CURRENT: + *value = local_state.manual_current; + break; + case CS_PARAM_DEBUG_MANUAL_VOLTAGE: + *value = local_state.manual_voltage; + break; + case CS_PARAM_DEBUG_SEEMS_DEAD: + *value = battery_seems_dead; + break; + case CS_PARAM_DEBUG_SEEMS_DISCONNECTED: + *value = battery_seems_disconnected; + break; + case CS_PARAM_DEBUG_BATT_REMOVED: + *value = battery_was_removed; + break; + default: + *value = 0; + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +static enum ec_status +charge_command_charge_state(struct host_cmd_handler_args *args) +{ + const struct ec_params_charge_state *in = args->params; + struct ec_response_charge_state *out = args->response; + uint32_t val; + int rv = EC_RES_SUCCESS; + int chgnum = 0; + + if (args->version > 0) + chgnum = in->chgnum; + + switch (in->cmd) { + case CHARGE_STATE_CMD_GET_STATE: + out->get_state.ac = curr.ac; + out->get_state.chg_voltage = curr.chg.voltage; + out->get_state.chg_current = curr.chg.current; + out->get_state.chg_input_current = curr.chg.input_current; + out->get_state.batt_state_of_charge = curr.batt.state_of_charge; + args->response_size = sizeof(out->get_state); + break; + + case CHARGE_STATE_CMD_GET_PARAM: + val = 0; + if (IS_ENABLED(CONFIG_CHARGER_PROFILE_OVERRIDE) && + in->get_param.param >= CS_PARAM_CUSTOM_PROFILE_MIN && + in->get_param.param <= CS_PARAM_CUSTOM_PROFILE_MAX) { + /* custom profile params */ + rv = charger_profile_override_get_param( + in->get_param.param, &val); + } else if (IS_ENABLED(CONFIG_CHARGE_STATE_DEBUG) && + in->get_param.param >= CS_PARAM_DEBUG_MIN && + in->get_param.param <= CS_PARAM_DEBUG_MAX) { + /* debug params */ + rv = charge_get_charge_state_debug(in->get_param.param, + &val); + } else { + /* standard params */ + switch (in->get_param.param) { + case CS_PARAM_CHG_VOLTAGE: + val = curr.chg.voltage; + break; + case CS_PARAM_CHG_CURRENT: + val = curr.chg.current; + break; + case CS_PARAM_CHG_INPUT_CURRENT: + val = curr.chg.input_current; + break; + case CS_PARAM_CHG_STATUS: + val = curr.chg.status; + break; + case CS_PARAM_CHG_OPTION: + val = curr.chg.option; + break; + case CS_PARAM_LIMIT_POWER: +#ifdef CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW + /* + * LIMIT_POWER status is based on battery level + * and external charger power. + */ + if ((curr.batt.is_present != BP_YES || + curr.batt.state_of_charge < + CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT) && + charge_manager_get_power_limit_uw() < + CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW * + 1000 && + system_is_locked()) + val = 1; + else +#endif + val = 0; + break; + default: + rv = EC_RES_INVALID_PARAM; + } + } + + /* got something */ + out->get_param.value = val; + args->response_size = sizeof(out->get_param); + break; + + case CHARGE_STATE_CMD_SET_PARAM: + if (system_is_locked()) + return EC_RES_ACCESS_DENIED; + + val = in->set_param.value; + if (IS_ENABLED(CONFIG_CHARGER_PROFILE_OVERRIDE) && + in->set_param.param >= CS_PARAM_CUSTOM_PROFILE_MIN && + in->set_param.param <= CS_PARAM_CUSTOM_PROFILE_MAX) { + /* custom profile params */ + rv = charger_profile_override_set_param( + in->set_param.param, val); + } else { + switch (in->set_param.param) { + case CS_PARAM_CHG_VOLTAGE: + chgstate_set_manual_voltage(val); + break; + case CS_PARAM_CHG_CURRENT: + chgstate_set_manual_current(val); + break; + case CS_PARAM_CHG_INPUT_CURRENT: + if (charger_set_input_current_limit(chgnum, + val)) + rv = EC_RES_ERROR; + break; + case CS_PARAM_CHG_STATUS: + case CS_PARAM_LIMIT_POWER: + /* Can't set this */ + rv = EC_RES_ACCESS_DENIED; + break; + case CS_PARAM_CHG_OPTION: + if (charger_set_option(val)) + rv = EC_RES_ERROR; + break; + default: + rv = EC_RES_INVALID_PARAM; + } + } + break; + + default: + CPRINTS("EC_CMD_CHARGE_STATE: bad cmd 0x%x", in->cmd); + rv = EC_RES_INVALID_PARAM; + } + + return rv; +} + +DECLARE_HOST_COMMAND(EC_CMD_CHARGE_STATE, charge_command_charge_state, + EC_VER_MASK(0) | EC_VER_MASK(1)); + +/*****************************************************************************/ +/* Console commands */ + +#ifdef CONFIG_CMD_PWR_AVG + +static int command_pwr_avg(int argc, const char **argv) +{ + int avg_mv; + int avg_ma; + int avg_mw; + + if (argc != 1) + return EC_ERROR_PARAM_COUNT; + + avg_mv = battery_get_avg_voltage(); + if (avg_mv < 0) + return EC_ERROR_UNKNOWN; + avg_ma = battery_get_avg_current(); + avg_mw = avg_mv * avg_ma / 1000; + + ccprintf("mv = %d\nma = %d\nmw = %d\n", avg_mv, avg_ma, avg_mw); + return EC_SUCCESS; +} + +DECLARE_CONSOLE_COMMAND(pwr_avg, command_pwr_avg, NULL, + "Get 1 min power average"); + +#endif /* CONFIG_CMD_PWR_AVG */ + +static int command_chgstate(int argc, const char **argv) +{ + int rv; + int val; + char *e; + + if (argc > 1) { + if (!strcasecmp(argv[1], "idle")) { + if (argc <= 2) + return EC_ERROR_PARAM_COUNT; + if (!parse_bool(argv[2], &val)) + return EC_ERROR_PARAM2; + rv = set_chg_ctrl_mode(val ? CHARGE_CONTROL_IDLE : + CHARGE_CONTROL_NORMAL); + if (rv) + return rv; + } else if (!strcasecmp(argv[1], "discharge")) { + if (argc <= 2) + return EC_ERROR_PARAM_COUNT; + if (!parse_bool(argv[2], &val)) + return EC_ERROR_PARAM2; + rv = set_chg_ctrl_mode(val ? CHARGE_CONTROL_DISCHARGE : + CHARGE_CONTROL_NORMAL); + if (rv) + return rv; + } else if (IS_ENABLED(CONFIG_CHARGE_DEBUG) && + !strcasecmp(argv[1], "debug")) { + int val; + + if (argc <= 2) + return EC_ERROR_PARAM_COUNT; + if (!parse_bool(argv[2], &val)) + return EC_ERROR_PARAM2; + set_debugging(val); + } else if (!strcasecmp(argv[1], "sustain")) { + int lower, upper; + + if (argc <= 3) + return EC_ERROR_PARAM_COUNT; + lower = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + upper = strtoi(argv[3], &e, 0); + if (*e) + return EC_ERROR_PARAM3; + rv = battery_sustainer_set(lower, upper); + if (rv) + return EC_ERROR_INVAL; + } else { + return EC_ERROR_PARAM1; + } + } + + dump_charge_state(); + return EC_SUCCESS; +} +#ifdef CONFIG_CHARGE_DEBUG +#define CHGSTATE_DEBUG_HELP "|debug on|off" +#else +#define CHGSTATE_DEBUG_HELP "" +#endif +DECLARE_CONSOLE_COMMAND(chgstate, command_chgstate, + "[idle|discharge" CHGSTATE_DEBUG_HELP "]" + "\n[sustain ]", + "Get/set charge state machine status"); diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c deleted file mode 100644 index 2bdac84634..0000000000 --- a/common/charge_state_v2.c +++ /dev/null @@ -1,2910 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery charging task and state machine. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "charge_manager.h" -#include "charger_profile_override.h" -#include "charge_state.h" -#include "charger.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "ec_ec_comm_master.h" -#include "ec_ec_comm_slave.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "math_util.h" -#include "printf.h" -#include "system.h" -#include "task.h" -#include "throttle_ap.h" -#include "timer.h" -#include "usb_common.h" -#include "usb_pd.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHARGER, outstr) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -/* Extra debugging prints when allocating power between lid and base. */ -#undef CHARGE_ALLOCATE_EXTRA_DEBUG - -#define CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US \ - (CONFIG_BATTERY_CRITICAL_SHUTDOWN_TIMEOUT * SECOND) -#define PRECHARGE_TIMEOUT_US (PRECHARGE_TIMEOUT * SECOND) -#define LFCC_EVENT_THRESH 5 /* Full-capacity change reqd for host event */ - -#ifdef CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT -#ifndef CONFIG_HOSTCMD_EVENTS -#error "CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT needs CONFIG_HOSTCMD_EVENTS" -#endif /* CONFIG_HOSTCMD_EVENTS */ -#define BAT_OCP_TIMEOUT_US (60 * SECOND) -/* BAT_OCP_HYSTERESIS_PCT can be optionally overridden in board.h. */ -#ifndef BAT_OCP_HYSTERESIS_PCT -#define BAT_OCP_HYSTERESIS_PCT 10 -#endif /* BAT_OCP_HYSTERESIS_PCT */ -#define BAT_OCP_HYSTERESIS \ - (BAT_MAX_DISCHG_CURRENT * BAT_OCP_HYSTERESIS_PCT / 100) /* mA */ -#endif /* CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT */ - -#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE -#ifndef CONFIG_HOSTCMD_EVENTS -#error "CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE needs CONFIG_HOSTCMD_EVENTS" -#endif /* CONFIG_HOSTCMD_EVENTS */ -#define BAT_UVP_TIMEOUT_US (60 * SECOND) -/* BAT_UVP_HYSTERESIS_PCT can be optionally overridden in board.h. */ -#ifndef BAT_UVP_HYSTERESIS_PCT -#define BAT_UVP_HYSTERESIS_PCT 3 -#endif /* BAT_UVP_HYSTERESIS_PCT */ -#define BAT_UVP_HYSTERESIS \ - (BAT_LOW_VOLTAGE_THRESH * BAT_UVP_HYSTERESIS_PCT / 100) /* mV */ -static timestamp_t uvp_throttle_start_time; -#endif /* CONFIG_THROTTLE_AP_ON_BAT_OLTAGE */ - -static int charge_request(int voltage, int current); - -static uint8_t battery_level_shutdown; - -/* - * State for charger_task(). Here so we can reset it on a HOOK_INIT, and - * because stack space is more limited than .bss - */ -static const struct battery_info *batt_info; -static struct charge_state_data curr; -static enum charge_state_v2 prev_state; -static int prev_ac, prev_charge, prev_full, prev_disp_charge; -static enum battery_present prev_bp; -static int is_full; /* battery not accepting current */ -static enum ec_charge_control_mode chg_ctl_mode; -static int manual_voltage; /* Manual voltage override (-1 = no override) */ -static int manual_current; /* Manual current override (-1 = no override) */ -static unsigned int user_current_limit = -1U; -test_export_static timestamp_t shutdown_target_time; -static timestamp_t precharge_start_time; - -/* - * The timestamp when the battery charging current becomes stable. - * When a new charging status happens, charger needs several seconds to - * stabilize the battery charging current. - * stable_current should be evaluated when stable_ts expired. - * stable_ts should be reset if the charger input voltage/current changes, - * or a new battery charging voltage/request happened. - * By evaluating stable_current, we can evaluate the battery's desired charging - * power desired_mw. This allow us to have a better charging efficiency by - * negotiating the most fit PDO, i.e. the PDO provides the power just enough for - * the system and battery, or the PDO with preferred voltage. - */ -STATIC_IF(CONFIG_USB_PD_PREFER_MV) timestamp_t stable_ts; -/* battery charging current evaluated after stable_ts expired */ -STATIC_IF(CONFIG_USB_PD_PREFER_MV) int stable_current; -/* battery desired power in mW. This is used to negotiate the suitable PDO */ -STATIC_IF(CONFIG_USB_PD_PREFER_MV) int desired_mw; -STATIC_IF_NOT(CONFIG_USB_PD_PREFER_MV) struct pd_pref_config_t pd_pref_config; - -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER -static int base_connected; -/* Base has responded to one of our commands already. */ -static int base_responsive; -static int charge_base; -static int prev_charge_base; -static int prev_current_base; -static int prev_allow_charge_base; -static int prev_current_lid; - -/* - * In debugging mode, with AC, input current to allocate to base. Negative - * value disables manual mode. - */ -static int manual_ac_current_base = -1; -/* - * In debugging mode, when discharging, current to transfer from lid to base - * (negative to transfer from base to lid). Only valid when enabled is true. - */ -static int manual_noac_enabled; -static int manual_noac_current_base; -#else -static const int base_connected; -#endif - -/* Is battery connected but unresponsive after precharge? */ -static int battery_seems_to_be_dead; - -static int battery_seems_to_be_disconnected; - -/* - * Was battery removed? Set when we see BP_NO, cleared after the battery is - * reattached and becomes responsive. Used to indicate an error state after - * removal and trigger re-reading the battery static info when battery is - * reattached and responsive. - */ -static int battery_was_removed; - -static int problems_exist; -static int debugging; - - -/* Track problems in communicating with the battery or charger */ -enum problem_type { - PR_STATIC_UPDATE, - PR_SET_VOLTAGE, - PR_SET_CURRENT, - PR_SET_MODE, - PR_SET_INPUT_CURR, - PR_POST_INIT, - PR_CHG_FLAGS, - PR_BATT_FLAGS, - PR_CUSTOM, - PR_CFG_SEC_CHG, - - NUM_PROBLEM_TYPES -}; -static const char * const prob_text[] = { - "static update", - "set voltage", - "set current", - "set mode", - "set input current", - "post init", - "chg params", - "batt params", - "custom profile", - "cfg secondary chg" -}; -BUILD_ASSERT(ARRAY_SIZE(prob_text) == NUM_PROBLEM_TYPES); - -/* - * TODO(crosbug.com/p/27639): When do we decide a problem is real and not - * just intermittent? And what do we do about it? - */ -static void problem(enum problem_type p, int v) -{ - static int __bss_slow last_prob_val[NUM_PROBLEM_TYPES]; - static timestamp_t __bss_slow last_prob_time[NUM_PROBLEM_TYPES]; - timestamp_t t_now, t_diff; - - if (last_prob_val[p] != v) { - t_now = get_time(); - t_diff.val = t_now.val - last_prob_time[p].val; - CPRINTS("charge problem: %s, 0x%x -> 0x%x after %.6" PRId64 "s", - prob_text[p], last_prob_val[p], v, t_diff.val); - last_prob_val[p] = v; - last_prob_time[p] = t_now; - } - problems_exist = 1; -} - -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER -/* - * Parameters for dual-battery policy. - * TODO(b:71881017): This should be made configurable by AP in the future. - */ -struct dual_battery_policy { - /*** Policies when AC is not connected. ***/ - /* Voltage to use when using OTG mode between lid and base (mV) */ - uint16_t otg_voltage; - /* Maximum current to apply from base to lid (mA) */ - uint16_t max_base_to_lid_current; - /* - * Margin to apply between provided OTG output current and input current - * limit, to make sure that input charger does not overcurrent output - * charger. input_current = (1-margin) * output_current. (/128) - */ - uint8_t margin_otg_current; - - /* Only do base to lid OTG when base battery above this value (%) */ - uint8_t min_charge_base_otg; - - /* - * When base/lid battery percentage is below this value, do - * battery-to-battery charging. (%) - */ - uint8_t max_charge_base_batt_to_batt; - uint8_t max_charge_lid_batt_to_batt; - - /*** Policies when AC is connected. ***/ - /* Minimum power to allocate to base (mW), includes some margin to allow - * base to charge when critically low. - */ - uint16_t min_base_system_power; - - /* Smoothing factor for lid power (/128) */ - uint8_t lid_system_power_smooth; - /* - * Smoothing factor for base/lid battery power, when the battery power - * is decreasing only: we try to estimate the maximum power that the - * battery is willing to take and always reset it when it draws more - * than the estimate. (/128) - */ - uint8_t battery_power_smooth; - - /* - * Margin to add to requested base/lid battery power, to figure out how - * much current to allocate. allocation = (1+margin) * request. (/128) - */ - uint8_t margin_base_battery_power; - uint8_t margin_lid_battery_power; - - /* Maximum current to apply from lid to base (mA) */ - uint16_t max_lid_to_base_current; -}; - -static const struct dual_battery_policy db_policy = { - .otg_voltage = 12000, /* mV */ - .max_base_to_lid_current = 1800, /* mA, about 2000mA with margin. */ - .margin_otg_current = 13, /* /128 = 10.1% */ - .min_charge_base_otg = 5, /* % */ - .max_charge_base_batt_to_batt = 4, /* % */ - .max_charge_lid_batt_to_batt = 10, /* % */ - .min_base_system_power = 1300, /* mW */ - .lid_system_power_smooth = 32, /* 32/128 = 0.25 */ - .battery_power_smooth = 1, /* 1/128 = 0.008 */ - .margin_base_battery_power = 32, /* 32/128 = 0.25 */ - .margin_lid_battery_power = 32, /* 32/128 = 0.25 */ - .max_lid_to_base_current = 2000, /* mA */ -}; - -/* Add at most "value" to power_var, subtracting from total_power budget. */ -#define CHG_ALLOCATE(power_var, total_power, value) do { \ - int val_capped = MIN(value, total_power); \ - (power_var) += val_capped; \ - (total_power) -= val_capped; \ -} while (0) - -/* Update base battery information */ -static void update_base_battery_info(void) -{ - struct ec_response_battery_dynamic_info *const bd = - &battery_dynamic[BATT_IDX_BASE]; - - base_connected = board_is_base_connected(); - - if (!base_connected) { - const int invalid_flags = EC_BATT_FLAG_INVALID_DATA; - /* Invalidate static/dynamic information */ - if (bd->flags != invalid_flags) { - bd->flags = invalid_flags; - - host_set_single_event(EC_HOST_EVENT_BATTERY); - host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS); - } - charge_base = -1; - base_responsive = 0; - prev_current_base = 0; - prev_allow_charge_base = 0; - } else if (base_responsive) { - int old_flags = bd->flags; - int flags_changed; - int old_full_capacity = bd->full_capacity; - - ec_ec_master_base_get_dynamic_info(); - flags_changed = (old_flags != bd->flags); - /* Fetch static information when flags change. */ - if (flags_changed) - ec_ec_master_base_get_static_info(); - - battery_memmap_refresh(BATT_IDX_BASE); - - /* Newly connected battery, or change in capacity. */ - if (old_flags & EC_BATT_FLAG_INVALID_DATA || - ((old_flags & EC_BATT_FLAG_BATT_PRESENT) != - (bd->flags & EC_BATT_FLAG_BATT_PRESENT)) || - old_full_capacity != bd->full_capacity) - host_set_single_event(EC_HOST_EVENT_BATTERY); - - if (flags_changed) - host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS); - - /* Update charge_base */ - if (bd->flags & (BATT_FLAG_BAD_FULL_CAPACITY | - BATT_FLAG_BAD_REMAINING_CAPACITY)) - charge_base = -1; - else if (bd->full_capacity > 0) - charge_base = 100 * bd->remaining_capacity - / bd->full_capacity; - else - charge_base = 0; - } -} - -/** - * Setup current settings for base, and record previous values, if the base - * is responsive. - * - * @param current_base Current to be drawn by base (negative to provide power) - * @param allow_charge_base Whether base battery should be charged (only makes - * sense with positive current) - */ -static int set_base_current(int current_base, int allow_charge_base) -{ - /* "OTG" voltage from base to lid. */ - const int otg_voltage = db_policy.otg_voltage; - int ret; - - ret = ec_ec_master_base_charge_control(current_base, - otg_voltage, allow_charge_base); - if (ret) { - /* Ignore errors until the base is responsive. */ - if (base_responsive) - return ret; - } else { - base_responsive = 1; - prev_current_base = current_base; - prev_allow_charge_base = allow_charge_base; - } - - return EC_RES_SUCCESS; -} - -/** - * Setup current settings for lid and base, in a safe way. - * - * @param current_base Current to be drawn by base (negative to provide power) - * @param allow_charge_base Whether base battery should be charged (only makes - * sense with positive current) - * @param current_lid Current to be drawn by lid (negative to provide power) - * @param allow_charge_lid Whether lid battery should be charged - */ -static void set_base_lid_current(int current_base, int allow_charge_base, - int current_lid, int allow_charge_lid) -{ - /* "OTG" voltage from lid to base. */ - const int otg_voltage = db_policy.otg_voltage; - - int lid_first; - int ret; - int chgnum = 0; - - /* TODO(b:71881017): This is still quite verbose during charging. */ - if (prev_current_base != current_base || - prev_allow_charge_base != allow_charge_base || - prev_current_lid != current_lid) { - CPRINTS("Base/Lid: %d%s/%d%s mA", - current_base, allow_charge_base ? "+" : "", - current_lid, allow_charge_lid ? "+" : ""); - } - - /* - * To decide whether to first control the lid or the base, we first - * control the side that _reduces_ current that would be drawn, then - * setup one that would start providing power, then increase current. - */ - if (current_lid >= 0 && current_lid < prev_current_lid) - lid_first = 1; /* Lid decreases current */ - else if (current_base >= 0 && current_base < prev_current_base) - lid_first = 0; /* Base decreases current */ - else if (current_lid < 0) - lid_first = 1; /* Lid provide power */ - else - lid_first = 0; /* All other cases: control the base first */ - - if (!lid_first && base_connected) { - ret = set_base_current(current_base, allow_charge_base); - if (ret) - return; - } - - if (current_lid >= 0) { - ret = charge_set_output_current_limit(CHARGER_SOLO, 0, 0); - if (ret) - return; - ret = charger_set_input_current(chgnum, current_lid); - if (ret) - return; - if (allow_charge_lid) - ret = charge_request(curr.requested_voltage, - curr.requested_current); - else - ret = charge_request(0, 0); - } else { - ret = charge_set_output_current_limit(CHARGER_SOLO, - -current_lid, otg_voltage); - } - - if (ret) - return; - - prev_current_lid = current_lid; - - if (lid_first && base_connected) { - ret = set_base_current(current_base, allow_charge_base); - if (ret) - return; - } - - /* - * Make sure cross-power is enabled (it might not be enabled right after - * plugging the base, or when an adapter just got connected). - */ - if (base_connected && current_base != 0) - board_enable_base_power(1); -} - -/** - * Smooth power value, covering some edge cases. - * Compute s*curr+(1-s)*prev, where s is in 1/128 unit. - */ -static int smooth_value(int prev, int curr, int s) -{ - if (curr < 0) - curr = 0; - if (prev < 0) - return curr; - - return prev + s * (curr - prev) / 128; -} - -/** - * Add margin m to value. Compute (1+m)*value, where m is in 1/128 unit. - */ -static int add_margin(int value, int m) -{ - return value + m * value / 128; -} - -static void charge_allocate_input_current_limit(void) -{ - /* - * All the power numbers are in mW. - * - * Since we work with current and voltage in mA and mV, multiplying them - * gives numbers in uW, which are dangerously close to overflowing when - * doing intermediate computations (60W * 100 overflows a 32-bit int, - * for example). We therefore divide the product by 1000 and re-multiply - * the power numbers by 1000 when converting them back to current. - */ - int total_power = 0; - - static int prev_base_battery_power = -1; - int base_battery_power = 0; - int base_battery_power_max = 0; - - static int prev_lid_system_power = -1; - int lid_system_power; - - static int prev_lid_battery_power = -1; - int lid_battery_power = 0; - int lid_battery_power_max = 0; - - int power_base = 0; - int power_lid = 0; - - int current_base = 0; - int current_lid = 0; - - int charge_lid = charge_get_percent(); - - const struct ec_response_battery_dynamic_info *const base_bd = - &battery_dynamic[BATT_IDX_BASE]; - - - if (!base_connected) { - set_base_lid_current(0, 0, curr.desired_input_current, 1); - prev_base_battery_power = -1; - return; - } - - /* Charging */ - if (curr.desired_input_current > 0 && curr.input_voltage > 0) - total_power = - curr.desired_input_current * curr.input_voltage / 1000; - - /* - * TODO(b:71723024): We should be able to replace this test by curr.ac, - * but the value is currently wrong, especially during transitions. - */ - if (total_power <= 0) { - int base_critical = charge_base >= 0 && - charge_base < db_policy.max_charge_base_batt_to_batt; - - /* Discharging */ - prev_base_battery_power = -1; - prev_lid_system_power = -1; - prev_lid_battery_power = -1; - - /* Manual control */ - if (manual_noac_enabled) { - int lid_current, base_current; - - if (manual_noac_current_base > 0) { - base_current = -manual_noac_current_base; - lid_current = - add_margin(manual_noac_current_base, - db_policy.margin_otg_current); - } else { - lid_current = manual_noac_current_base; - base_current = - add_margin(-manual_noac_current_base, - db_policy.margin_otg_current); - } - - set_base_lid_current(base_current, 0, lid_current, 0); - return; - } - - /* - * System is off, cut power to the base. We'll reset the base - * when system restarts, or when AC is plugged. - */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { - set_base_lid_current(0, 0, 0, 0); - if (base_responsive) { - /* Base still responsive, put it to sleep. */ - CPRINTF("Hibernating base\n"); - ec_ec_master_hibernate(); - base_responsive = 0; - board_enable_base_power(0); - } - return; - } - - /* - * System is suspended, let the lid and base run on their - * own power. However, if the base battery is critically low, we - * still want to provide power to the base, to make sure it - * stays alive to be able to wake the system on keyboard or - * touchpad events. - */ - if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && - !base_critical) { - set_base_lid_current(0, 0, 0, 0); - return; - } - - if (charge_base > db_policy.min_charge_base_otg) { - int lid_current = db_policy.max_base_to_lid_current; - int base_current = add_margin(lid_current, - db_policy.margin_otg_current); - /* Draw current from base to lid */ - set_base_lid_current(-base_current, 0, lid_current, - charge_lid < db_policy.max_charge_lid_batt_to_batt); - } else { - /* - * Base battery is too low, apply power to it, and allow - * it to charge if it is critically low. - * - * TODO(b:71881017): When suspended, this will make the - * battery charge oscillate between 3 and 4 percent, - * which might not be great for battery life. We need - * some hysteresis. - */ - /* - * TODO(b:71881017): Precompute (ideally, at build time) - * the base_current, so we do not need to do a division - * here. - */ - int base_current = - (db_policy.min_base_system_power * 1000) / - db_policy.otg_voltage; - int lid_current = add_margin(base_current, - db_policy.margin_otg_current); - - set_base_lid_current(base_current, base_critical, - -lid_current, 0); - } - - return; - } - - /* Manual control */ - if (manual_ac_current_base >= 0) { - int current_base = manual_ac_current_base; - int current_lid = - curr.desired_input_current - manual_ac_current_base; - - if (current_lid < 0) { - current_base = curr.desired_input_current; - current_lid = 0; - } - - set_base_lid_current(current_base, 1, current_lid, 1); - return; - } - - /* Estimate system power. */ - lid_system_power = charger_get_system_power() / 1000; - - /* Smooth system power, as it is very spiky */ - lid_system_power = smooth_value(prev_lid_system_power, - lid_system_power, db_policy.lid_system_power_smooth); - prev_lid_system_power = lid_system_power; - - /* - * TODO(b:71881017): Smoothing the battery power isn't necessarily a - * good idea: if the system takes up too much power, we may reduce the - * estimate power too quickly, leading to oscillations when the system - * power goes down. Instead, we should probably estimate the current - * based on remaining capacity. - */ - /* Estimate lid battery power. */ - if (!(curr.batt.flags & - (BATT_FLAG_BAD_VOLTAGE | BATT_FLAG_BAD_CURRENT))) - lid_battery_power = curr.batt.current * - curr.batt.voltage / 1000; - if (lid_battery_power < prev_lid_battery_power) - lid_battery_power = smooth_value(prev_lid_battery_power, - lid_battery_power, db_policy.battery_power_smooth); - if (!(curr.batt.flags & - (BATT_FLAG_BAD_DESIRED_VOLTAGE | - BATT_FLAG_BAD_DESIRED_CURRENT))) - lid_battery_power_max = curr.batt.desired_current * - curr.batt.desired_voltage / 1000; - - lid_battery_power = MIN(lid_battery_power, lid_battery_power_max); - - /* Estimate base battery power. */ - if (!(base_bd->flags & EC_BATT_FLAG_INVALID_DATA)) { - base_battery_power = base_bd->actual_current * - base_bd->actual_voltage / 1000; - base_battery_power_max = base_bd->desired_current * - base_bd->desired_voltage / 1000; - } - if (base_battery_power < prev_base_battery_power) - base_battery_power = smooth_value(prev_base_battery_power, - base_battery_power, db_policy.battery_power_smooth); - base_battery_power = MIN(base_battery_power, base_battery_power_max); - - if (debugging) { - CPRINTF("%s:\n", __func__); - CPRINTF("total power: %d\n", total_power); - CPRINTF("base battery power: %d (%d)\n", - base_battery_power, base_battery_power_max); - CPRINTF("lid system power: %d\n", lid_system_power); - CPRINTF("lid battery power: %d\n", lid_battery_power); - CPRINTF("percent base/lid: %d%% %d%%\n", - charge_base, charge_lid); - } - - prev_lid_battery_power = lid_battery_power; - prev_base_battery_power = base_battery_power; - - if (total_power > 0) { /* Charging */ - /* Allocate system power */ - CHG_ALLOCATE(power_base, total_power, - db_policy.min_base_system_power); - CHG_ALLOCATE(power_lid, total_power, lid_system_power); - - /* Allocate lid, then base battery power */ - lid_battery_power = add_margin(lid_battery_power, - db_policy.margin_lid_battery_power); - CHG_ALLOCATE(power_lid, total_power, lid_battery_power); - - base_battery_power = add_margin(base_battery_power, - db_policy.margin_base_battery_power); - CHG_ALLOCATE(power_base, total_power, base_battery_power); - - /* Give everything else to the lid. */ - CHG_ALLOCATE(power_lid, total_power, total_power); - if (debugging) - CPRINTF("power: base %d mW / lid %d mW\n", - power_base, power_lid); - - current_base = 1000 * power_base / curr.input_voltage; - current_lid = 1000 * power_lid / curr.input_voltage; - - if (current_base > db_policy.max_lid_to_base_current) { - current_lid += (current_base - - db_policy.max_lid_to_base_current); - current_base = db_policy.max_lid_to_base_current; - } - - if (debugging) - CPRINTF("current: base %d mA / lid %d mA\n", - current_base, current_lid); - - set_base_lid_current(current_base, 1, current_lid, 1); - } else { /* Discharging */ - } - - if (debugging) - CPRINTF("====\n"); -} -#endif /* CONFIG_EC_EC_COMM_BATTERY_MASTER */ - -#ifndef CONFIG_BATTERY_V2 -/* Returns zero if every item was updated. */ -static int update_static_battery_info(void) -{ - char *batt_str; - int batt_serial; - uint8_t batt_flags = 0; - /* - * The return values have type enum ec_error_list, but EC_SUCCESS is - * zero. We'll just look for any failures so we can try them all again. - */ - int rv; - - /* Smart battery serial number is 16 bits */ - batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL); - memset(batt_str, 0, EC_MEMMAP_TEXT_MAX); - rv = battery_serial_number(&batt_serial); - if (!rv) - snprintf(batt_str, EC_MEMMAP_TEXT_MAX, "%04X", batt_serial); - - /* Design Capacity of Full */ - rv |= battery_design_capacity( - (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP)); - - /* Design Voltage */ - rv |= battery_design_voltage( - (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT)); - - /* Last Full Charge Capacity (this is only mostly static) */ - rv |= battery_full_charge_capacity( - (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC)); - - /* Cycle Count */ - rv |= battery_cycle_count((int *)host_get_memmap(EC_MEMMAP_BATT_CCNT)); - - /* Battery Manufacturer string */ - batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR); - memset(batt_str, 0, EC_MEMMAP_TEXT_MAX); - rv |= battery_manufacturer_name(batt_str, EC_MEMMAP_TEXT_MAX); - - /* Battery Model string */ - batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL); - memset(batt_str, 0, EC_MEMMAP_TEXT_MAX); - rv |= battery_device_name(batt_str, EC_MEMMAP_TEXT_MAX); - - /* Battery Type string */ - batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE); - rv |= battery_device_chemistry(batt_str, EC_MEMMAP_TEXT_MAX); - - /* Zero the dynamic entries. They'll come next. */ - *(int *)host_get_memmap(EC_MEMMAP_BATT_VOLT) = 0; - *(int *)host_get_memmap(EC_MEMMAP_BATT_RATE) = 0; - *(int *)host_get_memmap(EC_MEMMAP_BATT_CAP) = 0; - *(int *)host_get_memmap(EC_MEMMAP_BATT_LFCC) = 0; - if (extpower_is_present()) - batt_flags |= EC_BATT_FLAG_AC_PRESENT; - *host_get_memmap(EC_MEMMAP_BATT_FLAG) = batt_flags; - - if (rv) - problem(PR_STATIC_UPDATE, rv); - else - /* No errors seen. Battery data is now present */ - *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 1; - - return rv; -} - -static void update_dynamic_battery_info(void) -{ - /* The memmap address is constant. We should fix these calls somehow. */ - int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT); - int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE); - int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP); - int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC); - uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); - uint8_t tmp; - int send_batt_status_event = 0; - int send_batt_info_event = 0; - static int __bss_slow batt_present; - - tmp = 0; - if (curr.ac) - tmp |= EC_BATT_FLAG_AC_PRESENT; - - if (curr.batt.is_present == BP_YES) { - tmp |= EC_BATT_FLAG_BATT_PRESENT; - batt_present = 1; - /* Tell the AP to read battery info if it is newly present. */ - if (!(*memmap_flags & EC_BATT_FLAG_BATT_PRESENT)) - send_batt_info_event++; - } else { - /* - * Require two consecutive updates with BP_NOT_SURE - * before reporting it gone to the host. - */ - if (batt_present) - tmp |= EC_BATT_FLAG_BATT_PRESENT; - else if (*memmap_flags & EC_BATT_FLAG_BATT_PRESENT) - send_batt_info_event++; - batt_present = 0; - } - - if (curr.batt.flags & EC_BATT_FLAG_INVALID_DATA) - tmp |= EC_BATT_FLAG_INVALID_DATA; - - if (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE)) - *memmap_volt = curr.batt.voltage; - - if (!(curr.batt.flags & BATT_FLAG_BAD_CURRENT)) - *memmap_rate = ABS(curr.batt.current); - - if (!(curr.batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) { - /* - * If we're running off the battery, it must have some charge. - * Don't report zero charge, as that has special meaning - * to Chrome OS powerd. - */ - if (curr.batt.remaining_capacity == 0 && !curr.batt_is_charging) - *memmap_cap = 1; - else - *memmap_cap = curr.batt.remaining_capacity; - } - - if (!(curr.batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) && - (curr.batt.full_capacity <= (*memmap_lfcc - LFCC_EVENT_THRESH) || - curr.batt.full_capacity >= (*memmap_lfcc + LFCC_EVENT_THRESH))) { - *memmap_lfcc = curr.batt.full_capacity; - /* Poke the AP if the full_capacity changes. */ - send_batt_info_event++; - } - - if (curr.batt.is_present == BP_YES && - !(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && - curr.batt.state_of_charge <= BATTERY_LEVEL_CRITICAL) - tmp |= EC_BATT_FLAG_LEVEL_CRITICAL; - - tmp |= curr.batt_is_charging ? EC_BATT_FLAG_CHARGING : - EC_BATT_FLAG_DISCHARGING; - - /* Tell the AP to re-read battery status if charge state changes */ - if (*memmap_flags != tmp) - send_batt_status_event++; - - /* Update flags before sending host events. */ - *memmap_flags = tmp; - - if (send_batt_info_event) - host_set_single_event(EC_HOST_EVENT_BATTERY); - if (send_batt_status_event) - host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS); -} -#else /* CONFIG_BATTERY_V2 */ -static int update_static_battery_info(void) -{ - int batt_serial; - int val; - /* - * The return values have type enum ec_error_list, but EC_SUCCESS is - * zero. We'll just look for any failures so we can try them all again. - */ - int rv, ret; - - struct ec_response_battery_static_info *const bs = - &battery_static[BATT_IDX_MAIN]; - - /* Clear all static information. */ - memset(bs, 0, sizeof(*bs)); - - /* Smart battery serial number is 16 bits */ - rv = battery_serial_number(&batt_serial); - if (!rv) - snprintf(bs->serial, sizeof(bs->serial), "%04X", batt_serial); - - /* Design Capacity of Full */ - ret = battery_design_capacity(&val); - if (!ret) - bs->design_capacity = val; - rv |= ret; - - /* Design Voltage */ - ret = battery_design_voltage(&val); - if (!ret) - bs->design_voltage = val; - rv |= ret; - - /* Cycle Count */ - ret = battery_cycle_count(&val); - if (!ret) - bs->cycle_count = val; - rv |= ret; - - /* Battery Manufacturer string */ - rv |= battery_manufacturer_name(bs->manufacturer, - sizeof(bs->manufacturer)); - - /* Battery Model string */ - rv |= battery_device_name(bs->model, sizeof(bs->model)); - - /* Battery Type string */ - rv |= battery_device_chemistry(bs->type, sizeof(bs->type)); - - /* Zero the dynamic entries. They'll come next. */ - memset(&battery_dynamic[BATT_IDX_MAIN], 0, - sizeof(battery_dynamic[BATT_IDX_MAIN])); - - if (rv) - problem(PR_STATIC_UPDATE, rv); - -#ifdef HAS_TASK_HOSTCMD - battery_memmap_refresh(BATT_IDX_MAIN); -#endif - - return rv; -} - -static void update_dynamic_battery_info(void) -{ - static int __bss_slow batt_present; - uint8_t tmp; - int send_batt_status_event = 0; - int send_batt_info_event = 0; - - struct ec_response_battery_dynamic_info *const bd = - &battery_dynamic[BATT_IDX_MAIN]; - - tmp = 0; - if (curr.ac) - tmp |= EC_BATT_FLAG_AC_PRESENT; - - if (curr.batt.is_present == BP_YES) { - tmp |= EC_BATT_FLAG_BATT_PRESENT; - batt_present = 1; - /* Tell the AP to read battery info if it is newly present. */ - if (!(bd->flags & EC_BATT_FLAG_BATT_PRESENT)) - send_batt_info_event++; - } else { - /* - * Require two consecutive updates with BP_NOT_SURE - * before reporting it gone to the host. - */ - if (batt_present) - tmp |= EC_BATT_FLAG_BATT_PRESENT; - else if (bd->flags & EC_BATT_FLAG_BATT_PRESENT) - send_batt_info_event++; - batt_present = 0; - } - - if (curr.batt.flags & EC_BATT_FLAG_INVALID_DATA) - tmp |= EC_BATT_FLAG_INVALID_DATA; - - if (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE)) - bd->actual_voltage = curr.batt.voltage; - - if (!(curr.batt.flags & BATT_FLAG_BAD_CURRENT)) - bd->actual_current = curr.batt.current; - - if (!(curr.batt.flags & BATT_FLAG_BAD_DESIRED_VOLTAGE)) - bd->desired_voltage = curr.batt.desired_voltage; - - if (!(curr.batt.flags & BATT_FLAG_BAD_DESIRED_CURRENT)) - bd->desired_current = curr.batt.desired_current; - - if (!(curr.batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) { - /* - * If we're running off the battery, it must have some charge. - * Don't report zero charge, as that has special meaning - * to Chrome OS powerd. - */ - if (curr.batt.remaining_capacity == 0 && !curr.batt_is_charging) - bd->remaining_capacity = 1; - else - bd->remaining_capacity = curr.batt.remaining_capacity; - } - - if (!(curr.batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) && - (curr.batt.full_capacity <= - (bd->full_capacity - LFCC_EVENT_THRESH) || - curr.batt.full_capacity >= - (bd->full_capacity + LFCC_EVENT_THRESH))) { - bd->full_capacity = curr.batt.full_capacity; - /* Poke the AP if the full_capacity changes. */ - send_batt_info_event++; - } - - if (curr.batt.is_present == BP_YES && - !(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && - curr.batt.state_of_charge <= BATTERY_LEVEL_CRITICAL) - tmp |= EC_BATT_FLAG_LEVEL_CRITICAL; - - tmp |= curr.batt_is_charging ? EC_BATT_FLAG_CHARGING : - EC_BATT_FLAG_DISCHARGING; - - /* Tell the AP to re-read battery status if charge state changes */ - if (bd->flags != tmp) - send_batt_status_event++; - - bd->flags = tmp; - -#ifdef HAS_TASK_HOSTCMD - battery_memmap_refresh(BATT_IDX_MAIN); -#endif - -#ifdef CONFIG_HOSTCMD_EVENTS - if (send_batt_info_event) - host_set_single_event(EC_HOST_EVENT_BATTERY); - if (send_batt_status_event) - host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS); -#endif -} -#endif /* CONFIG_BATTERY_V2 */ - -static const char * const state_list[] = { - "idle", "discharge", "charge", "precharge" -}; -BUILD_ASSERT(ARRAY_SIZE(state_list) == NUM_STATES_V2); -static const char * const batt_pres[] = { - "NO", "YES", "NOT_SURE", -}; - -static void dump_charge_state(void) -{ -#define DUMP(FLD, FMT) ccprintf(#FLD " = " FMT "\n", curr.FLD) -#define DUMP_CHG(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.chg. FLD) -#define DUMP_BATT(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.batt. FLD) -#define DUMP_OCPC(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.ocpc. FLD) - ccprintf("state = %s\n", state_list[curr.state]); - DUMP(ac, "%d"); - DUMP(batt_is_charging, "%d"); - ccprintf("chg.*:\n"); - DUMP_CHG(voltage, "%dmV"); - DUMP_CHG(current, "%dmA"); - DUMP_CHG(input_current, "%dmA"); - DUMP_CHG(status, "0x%x"); - DUMP_CHG(option, "0x%x"); - DUMP_CHG(flags, "0x%x"); - cflush(); - ccprintf("batt.*:\n"); - ccprintf("\ttemperature = %dC\n", - DECI_KELVIN_TO_CELSIUS(curr.batt.temperature)); - DUMP_BATT(state_of_charge, "%d%%"); - DUMP_BATT(voltage, "%dmV"); - DUMP_BATT(current, "%dmA"); - DUMP_BATT(desired_voltage, "%dmV"); - DUMP_BATT(desired_current, "%dmA"); - DUMP_BATT(flags, "0x%x"); - DUMP_BATT(remaining_capacity, "%dmAh"); - DUMP_BATT(full_capacity, "%dmAh"); - ccprintf("\tis_present = %s\n", batt_pres[curr.batt.is_present]); - cflush(); -#ifdef CONFIG_OCPC - ccprintf("ocpc.*:\n"); - DUMP_OCPC(active_chg_chip, "%d"); - DUMP_OCPC(combined_rsys_rbatt_mo, "%dmOhm"); - if ((curr.ocpc.active_chg_chip != -1) && - !(curr.ocpc.chg_flags[curr.ocpc.active_chg_chip] & - OCPC_NO_ISYS_MEAS_CAP)) { - DUMP_OCPC(rbatt_mo, "%dmOhm"); - DUMP_OCPC(rsys_mo, "%dmOhm"); - DUMP_OCPC(isys_ma, "%dmA"); - } - DUMP_OCPC(vsys_aux_mv, "%dmV"); - DUMP_OCPC(vsys_mv, "%dmV"); - DUMP_OCPC(primary_vbus_mv, "%dmV"); - DUMP_OCPC(primary_ibus_ma, "%dmA"); - DUMP_OCPC(secondary_vbus_mv, "%dmV"); - DUMP_OCPC(secondary_ibus_ma, "%dmA"); - DUMP_OCPC(last_error, "%d"); - DUMP_OCPC(integral, "%d"); - DUMP_OCPC(last_vsys, "%dmV"); - cflush(); -#endif /* CONFIG_OCPC */ - DUMP(requested_voltage, "%dmV"); - DUMP(requested_current, "%dmA"); -#ifdef CONFIG_CHARGER_OTG - DUMP(output_current, "%dmA"); -#endif -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - DUMP(input_voltage, "%dmV"); -#endif - ccprintf("chg_ctl_mode = %d\n", chg_ctl_mode); - ccprintf("manual_voltage = %d\n", manual_voltage); - ccprintf("manual_current = %d\n", manual_current); - ccprintf("user_current_limit = %dmA\n", user_current_limit); - ccprintf("battery_seems_to_be_dead = %d\n", battery_seems_to_be_dead); - ccprintf("battery_seems_to_be_disconnected = %d\n", - battery_seems_to_be_disconnected); - ccprintf("battery_was_removed = %d\n", battery_was_removed); - ccprintf("debug output = %s\n", debugging ? "on" : "off"); -#undef DUMP -} - -static void show_charging_progress(void) -{ - int rv = 0, minutes, to_full, chgnum = 0; - -#ifdef CONFIG_BATTERY_SMART - /* - * Predicted remaining battery capacity based on AverageCurrent(). - * 65535 = Battery is not being discharged. - */ - if (!battery_time_to_empty(&minutes) && minutes != 65535) - to_full = 0; - /* - * Predicted time-to-full charge based on AverageCurrent(). - * 65535 = Battery is not being discharged. - */ - else if (!battery_time_to_full(&minutes) && minutes != 65535) - to_full = 1; - /* - * If both time to empty and time to full have invalid data, consider - * measured current from the coulomb counter and ac present status to - * decide whether battery is about to full or empty. - */ - else { - to_full = curr.batt_is_charging; - rv = EC_ERROR_UNKNOWN; - } -#else - if (!curr.batt_is_charging) { - rv = battery_time_to_empty(&minutes); - to_full = 0; - } else { - rv = battery_time_to_full(&minutes); - to_full = 1; - } -#endif - - if (rv) - CPRINTS("Battery %d%% (Display %d.%d %%) / ??h:?? %s%s", - curr.batt.state_of_charge, - curr.batt.display_charge / 10, - curr.batt.display_charge % 10, - to_full ? "to full" : "to empty", - is_full ? ", not accepting current" : ""); - else - CPRINTS("Battery %d%% (Display %d.%d %%) / %dh:%d %s%s", - curr.batt.state_of_charge, - curr.batt.display_charge / 10, - curr.batt.display_charge % 10, - minutes / 60, minutes % 60, - to_full ? "to full" : "to empty", - is_full ? ", not accepting current" : ""); - -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - CPRINTS("Base battery %d%%", charge_base); -#endif - - if (debugging) { - ccprintf("battery:\n"); - print_battery_debug(); - ccprintf("charger:\n"); - if (IS_ENABLED(CONFIG_OCPC)) - chgnum = charge_get_active_chg_chip(); - print_charger_debug(chgnum); - ccprintf("chg:\n"); - dump_charge_state(); - } -} - -/* Calculate if battery is full based on whether it is accepting charge */ -static int calc_is_full(void) -{ - static int __bss_slow ret; - - /* If bad state of charge reading, return last value */ - if (curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE || - curr.batt.state_of_charge > 100) - return ret; - /* - * Battery is full when SoC is above 90% and battery desired current - * is 0. This is necessary because some batteries stop charging when - * the SoC still reports <100%, so we need to check desired current - * to know if it is actually full. - */ - ret = (curr.batt.state_of_charge >= 90 && - curr.batt.desired_current == 0); - return ret; -} - -/* - * Ask the charger for some voltage and current. If either value is 0, - * charging is disabled; otherwise it's enabled. Negative values are ignored. - */ -static int charge_request(int voltage, int current) -{ - int r1 = EC_SUCCESS, r2 = EC_SUCCESS, r3 = EC_SUCCESS, r4 = EC_SUCCESS; - static int __bss_slow prev_volt, prev_curr; - - if (!voltage || !current) { -#ifdef CONFIG_CHARGER_NARROW_VDC - current = 0; - /* - * With NVDC charger, keep VSYS voltage higher than battery, - * otherwise the BGATE FET body diode would conduct and - * discharge the battery. - */ - voltage = charger_closest_voltage( - curr.batt.voltage + charger_get_info()->voltage_step); - /* If the battery is full, request the max voltage. */ - if (is_full) - voltage = battery_get_info()->voltage_max; - /* And handle dead battery case */ - voltage = MAX(voltage, battery_get_info()->voltage_normal); -#else - voltage = current = 0; -#endif - } - - if (curr.ac) { - if (prev_volt != voltage || prev_curr != current) - CPRINTS("%s(%dmV, %dmA)", __func__, voltage, current); - } - - /* - * Set current before voltage so that if we are just starting - * to charge, we allow some time (i2c delay) for charging circuit to - * start at a voltage just above battery voltage before jumping - * up. This helps avoid large current spikes when connecting - * battery. - */ - if (current >= 0) - r2 = charger_set_current(0, current); - if (r2 != EC_SUCCESS) - problem(PR_SET_CURRENT, r2); - - if (voltage >= 0) - r1 = charger_set_voltage(0, voltage); - if (r1 != EC_SUCCESS) - problem(PR_SET_VOLTAGE, r1); - -#ifdef CONFIG_OCPC - /* - * For OCPC systems, if the secondary charger is active, we need to - * configure that charge IC as well. Note that if OCPC ever supports - * more than 2 charger ICs, we'll need to refactor things a bit. The - * following check should be comparing against CHARGER_PRIMARY and - * config_secondary_charger should probably be config_auxiliary_charger - * and take the active chgnum as a parameter. - */ - if (curr.ocpc.active_chg_chip == CHARGER_SECONDARY) { - if ((current >= 0) || (voltage >= 0)) - r3 = ocpc_config_secondary_charger(&curr.desired_input_current, - &curr.ocpc, - voltage, current); - if (r3 != EC_SUCCESS) - problem(PR_CFG_SEC_CHG, r3); - } -#endif /* CONFIG_OCPC */ - - /* - * Set the charge inhibit bit when possible as it appears to save - * power in some cases (e.g. Nyan with BQ24735). - */ - if (voltage > 0 || current > 0) - r4 = charger_set_mode(0); - else - r4 = charger_set_mode(CHARGE_FLAG_INHIBIT_CHARGE); - if (r4 != EC_SUCCESS) - problem(PR_SET_MODE, r4); - - /* - * Only update if the request worked, so we'll keep trying on failures. - */ - if (r1 || r2) - return r1 ? r1 : r2; - if (IS_ENABLED(CONFIG_OCPC) && r3) - return r3; - - if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV) && - (prev_volt != voltage || prev_curr != current)) - charge_reset_stable_current(); - - prev_volt = voltage; - prev_curr = current; - - return EC_SUCCESS; -} - -void chgstate_set_manual_current(int curr_ma) -{ - if (curr_ma < 0) - manual_current = -1; - else - manual_current = charger_closest_current(curr_ma); -} - -void chgstate_set_manual_voltage(int volt_mv) -{ - manual_voltage = charger_closest_voltage(volt_mv); -} - -/* Force charging off before the battery is full. */ -static int set_chg_ctrl_mode(enum ec_charge_control_mode mode) -{ - if (mode == CHARGE_CONTROL_NORMAL) { - chg_ctl_mode = mode; - manual_current = -1; - manual_voltage = -1; - } else { - /* - * Changing mode is only meaningful if external power is - * present. If it's not present we can't charge anyway. - */ - if (!curr.ac) - return EC_ERROR_NOT_POWERED; - - chg_ctl_mode = mode; - manual_current = 0; - manual_voltage = 0; - } - - return EC_SUCCESS; -} - -static inline int battery_too_hot(int batt_temp_c) -{ - return (!(curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) && - (batt_temp_c > batt_info->discharging_max_c)); -} - -static inline int battery_too_cold_for_discharge(int batt_temp_c) -{ - return (!(curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) && - (batt_temp_c < batt_info->discharging_min_c)); -} - -__attribute__((weak)) uint8_t board_set_battery_level_shutdown(void) -{ - return BATTERY_LEVEL_SHUTDOWN; -} - -/* True if we know the charge is too low, or we know the voltage is too low. */ -static inline int battery_too_low(void) -{ - return ((!(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && - curr.batt.state_of_charge < battery_level_shutdown) || - (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) && - curr.batt.voltage <= batt_info->voltage_min)); -} - -__attribute__((weak)) -enum critical_shutdown board_critical_shutdown_check( - struct charge_state_data *curr) -{ -#ifdef CONFIG_BATTERY_CRITICAL_SHUTDOWN_CUT_OFF - return CRITICAL_SHUTDOWN_CUTOFF; -#elif defined(CONFIG_HIBERNATE) - return CRITICAL_SHUTDOWN_HIBERNATE; -#else - return CRITICAL_SHUTDOWN_IGNORE; -#endif -} - -static int is_battery_critical(void) -{ - int batt_temp_c = DECI_KELVIN_TO_CELSIUS(curr.batt.temperature); - - /* - * TODO(crosbug.com/p/27642): The thermal loop should watch the battery - * temp, so it can turn fans on. - */ - if (battery_too_hot(batt_temp_c)) { - CPRINTS("Batt too hot: %dC", batt_temp_c); - return 1; - } - - /* Note: the battery may run on AC without discharging when too cold */ - if (!curr.ac && battery_too_cold_for_discharge(batt_temp_c)) { - CPRINTS("Batt too cold: %dC", batt_temp_c); - return 1; - } - - if (battery_too_low() && !curr.batt_is_charging) { - CPRINTS("Low battery: %d%%, %dmV", - curr.batt.state_of_charge, curr.batt.voltage); - return 1; - } - - return 0; -} - - /* - * If the battery is at extremely low charge (and discharging) or extremely - * high temperature, the EC will notify the AP and start a timer. If the - * critical condition is not corrected before the timeout expires, the EC - * will shut down the AP (if the AP is not already off) and then optionally - * hibernate or cut off battery. - */ -static int shutdown_on_critical_battery(void) -{ - if (!is_battery_critical()) { - /* Reset shutdown warning time */ - shutdown_target_time.val = 0; - return 0; - } - - if (!shutdown_target_time.val) { - /* Start count down timer */ - CPRINTS("Start shutdown due to critical battery"); - shutdown_target_time.val = get_time().val - + CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US; -#ifdef CONFIG_HOSTCMD_EVENTS - if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) - host_set_single_event(EC_HOST_EVENT_BATTERY_SHUTDOWN); -#endif - return 1; - } - - if (!timestamp_expired(shutdown_target_time, 0)) - return 1; - - /* Timer has expired */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { - switch (board_critical_shutdown_check(&curr)) { - case CRITICAL_SHUTDOWN_HIBERNATE: - CPRINTS("Hibernate due to critical battery"); - system_hibernate(0, 0); - break; - case CRITICAL_SHUTDOWN_CUTOFF: - CPRINTS("Cutoff due to critical battery"); - /* Ensure logs are flushed. */ - cflush(); - board_cut_off_battery(); - break; - case CRITICAL_SHUTDOWN_IGNORE: - default: - break; - } - } else { - /* Timeout waiting for AP to shut down, so kill it */ - CPRINTS( - "charge force shutdown due to critical battery"); - chipset_force_shutdown(CHIPSET_SHUTDOWN_BATTERY_CRIT); - } - - return 1; -} - -/* - * Send host events as the battery charge drops below certain thresholds. - * We handle forced shutdown and other actions elsewhere; this is just for the - * host events. We send these even if the AP is off, since the AP will read and - * discard any events it doesn't care about the next time it wakes up. - */ -static void notify_host_of_low_battery_charge(void) -{ - /* We can't tell what the current charge is. Assume it's okay. */ - if (curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) - return; - -#ifdef CONFIG_HOSTCMD_EVENTS - if (curr.batt.state_of_charge <= BATTERY_LEVEL_LOW && - prev_charge > BATTERY_LEVEL_LOW) - host_set_single_event(EC_HOST_EVENT_BATTERY_LOW); - - if (curr.batt.state_of_charge <= BATTERY_LEVEL_CRITICAL && - prev_charge > BATTERY_LEVEL_CRITICAL) - host_set_single_event(EC_HOST_EVENT_BATTERY_CRITICAL); -#endif -} - -static void set_charge_state(enum charge_state_v2 state) -{ - prev_state = curr.state; - curr.state = state; -} - -static void notify_host_of_low_battery_voltage(void) -{ -#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE - if ((curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) || - chipset_in_state(CHIPSET_STATE_ANY_OFF)) - return; - - if (!uvp_throttle_start_time.val && - (curr.batt.voltage < BAT_LOW_VOLTAGE_THRESH)) { - throttle_ap(THROTTLE_ON, THROTTLE_SOFT, - THROTTLE_SRC_BAT_VOLTAGE); - uvp_throttle_start_time = get_time(); - } else if (uvp_throttle_start_time.val && - (curr.batt.voltage < BAT_LOW_VOLTAGE_THRESH + - BAT_UVP_HYSTERESIS)) { - /* - * Reset the timer when we are not sure if VBAT can stay - * above BAT_LOW_VOLTAGE_THRESH after we stop throttling. - */ - uvp_throttle_start_time = get_time(); - } else if (uvp_throttle_start_time.val && - (get_time().val > uvp_throttle_start_time.val + - BAT_UVP_TIMEOUT_US)) { - throttle_ap(THROTTLE_OFF, THROTTLE_SOFT, - THROTTLE_SRC_BAT_VOLTAGE); - uvp_throttle_start_time.val = 0; - } -#endif -} - -static void notify_host_of_over_current(struct batt_params *batt) -{ -#ifdef CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT - static timestamp_t ocp_throttle_start_time; - - if (batt->flags & BATT_FLAG_BAD_CURRENT) - return; - - if ((!ocp_throttle_start_time.val && - (batt->current < -BAT_MAX_DISCHG_CURRENT)) || - (ocp_throttle_start_time.val && - (batt->current < -BAT_MAX_DISCHG_CURRENT + BAT_OCP_HYSTERESIS))) { - ocp_throttle_start_time = get_time(); - throttle_ap(THROTTLE_ON, THROTTLE_SOFT, - THROTTLE_SRC_BAT_DISCHG_CURRENT); - } else if (ocp_throttle_start_time.val && - (get_time().val > ocp_throttle_start_time.val + - BAT_OCP_TIMEOUT_US)) { - /* - * Clear the timer and notify AP to stop throttling if - * we haven't seen over current for BAT_OCP_TIMEOUT_US. - */ - ocp_throttle_start_time.val = 0; - throttle_ap(THROTTLE_OFF, THROTTLE_SOFT, - THROTTLE_SRC_BAT_DISCHG_CURRENT); - } -#endif -} - -const struct batt_params *charger_current_battery_params(void) -{ - return &curr.batt; -} - -#ifdef CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS -/* Determine if the battery is outside of allowable temperature range */ -static int battery_outside_charging_temperature(void) -{ - const struct battery_info *batt_info = battery_get_info(); - /* battery temp in 0.1 deg C */ - int batt_temp_c = DECI_KELVIN_TO_CELSIUS(curr.batt.temperature); - int max_c, min_c; - - if (curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) - return 0; - - if((curr.batt.desired_voltage == 0) && - (curr.batt.desired_current == 0)){ - max_c = batt_info->start_charging_max_c; - min_c = batt_info->start_charging_min_c; - } else { - max_c = batt_info->charging_max_c; - min_c = batt_info->charging_min_c; - } - - - if ((batt_temp_c >= max_c) || - (batt_temp_c <= min_c)) { - return 1; - } - return 0; -} -#endif - -/*****************************************************************************/ -/* Hooks */ -void charger_init(void) -{ - /* Initialize current state */ - memset(&curr, 0, sizeof(curr)); - curr.batt.is_present = BP_NOT_SURE; - /* Manual voltage/current set to off */ - manual_voltage = -1; - manual_current = -1; - /* - * Other tasks read the params like state_of_charge at the beginning of - * their tasks. Make them ready first. - */ - battery_get_params(&curr.batt); -} -DECLARE_HOOK(HOOK_INIT, charger_init, HOOK_PRIO_DEFAULT); - -/* Wake up the task when something important happens */ -static void charge_wakeup(void) -{ - task_wake(TASK_ID_CHARGER); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, charge_wakeup, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_AC_CHANGE, charge_wakeup, HOOK_PRIO_DEFAULT); - -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER -/* Reset the base on S5->S0 transition. */ -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_base_reset, HOOK_PRIO_DEFAULT); -#endif - -#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE -static void bat_low_voltage_throttle_reset(void) -{ - uvp_throttle_start_time.val = 0; -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - bat_low_voltage_throttle_reset, - HOOK_PRIO_DEFAULT); -#endif - -static int get_desired_input_current(enum battery_present batt_present, - const struct charger_info * const info) -{ - if (batt_present == BP_YES || system_is_locked() || base_connected) { -#ifdef CONFIG_CHARGE_MANAGER - int ilim = charge_manager_get_charger_current(); - return ilim == CHARGE_CURRENT_UNINITIALIZED ? - CHARGE_CURRENT_UNINITIALIZED : - MAX(CONFIG_CHARGER_INPUT_CURRENT, ilim); -#else - return CONFIG_CHARGER_INPUT_CURRENT; -#endif - } else { -#ifdef CONFIG_USB_POWER_DELIVERY - return MIN(PD_MAX_CURRENT_MA, info->input_current_max); -#else - return info->input_current_max; -#endif - } -} - -/* Main loop */ -void charger_task(void *u) -{ - int sleep_usec; - int battery_critical; - int need_static = 1; - const struct charger_info * const info = charger_get_info(); - int prev_plt_and_desired_mw; - int chgnum = 0; - - /* Get the battery-specific values */ - batt_info = battery_get_info(); - - prev_ac = prev_charge = prev_disp_charge = -1; - chg_ctl_mode = CHARGE_CONTROL_NORMAL; - shutdown_target_time.val = 0UL; - battery_seems_to_be_dead = 0; -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - base_responsive = 0; - curr.input_voltage = CHARGE_VOLTAGE_UNINITIALIZED; - battery_dynamic[BATT_IDX_BASE].flags = EC_BATT_FLAG_INVALID_DATA; - charge_base = -1; -#endif -#ifdef CONFIG_OCPC - ocpc_init(&curr.ocpc); - charge_set_active_chg_chip(CHARGE_PORT_NONE); -#endif /* CONFIG_OCPC */ - - /* - * If system is not locked and we don't have a battery to live on, - * then use max input current limit so that we can pull as much power - * as needed. - */ - prev_bp = BP_NOT_INIT; - curr.desired_input_current = get_desired_input_current( - curr.batt.is_present, info); - - if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV)) { - /* init battery desired power */ - desired_mw = - curr.batt.desired_current * curr.batt.desired_voltage; - /* - * Battery charging current needs time to be stable when a - * new charge happens. Start the timer so we can evaluate the - * stable current when timeout. - */ - charge_reset_stable_current(); - } - - battery_level_shutdown = board_set_battery_level_shutdown(); - - while (1) { - - /* Let's see what's going on... */ - curr.ts = get_time(); - sleep_usec = 0; - problems_exist = 0; - battery_critical = 0; - curr.ac = extpower_is_present(); -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - /* - * When base is powering the system, make sure curr.ac stays 0. - * TODO(b:71723024): Fix extpower_is_present() in hardware - * instead. - */ - if (base_responsive && prev_current_base < 0) - curr.ac = 0; - - /* System is off: if AC gets connected, reset the base. */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && - !prev_ac && curr.ac) - board_base_reset(); -#endif - if (curr.ac != prev_ac) { - if (curr.ac) { - /* - * Some chargers are unpowered when the AC is - * off, so we'll reinitialize it when AC - * comes back and set the input current limit. - * Try again if it fails. - */ - int rv = charger_post_init(); - if (rv != EC_SUCCESS) { - problem(PR_POST_INIT, rv); - } else { - if (curr.desired_input_current != - CHARGE_CURRENT_UNINITIALIZED) - rv = charger_set_input_current( - chgnum, - curr.desired_input_current); - if (rv != EC_SUCCESS) - problem(PR_SET_INPUT_CURR, rv); - else - prev_ac = curr.ac; - } - } else { - /* Some things are only meaningful on AC */ - chg_ctl_mode = CHARGE_CONTROL_NORMAL; - battery_seems_to_be_dead = 0; - prev_ac = curr.ac; - } - } - -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - update_base_battery_info(); -#endif - - charger_get_params(&curr.chg); - battery_get_params(&curr.batt); -#ifdef CONFIG_OCPC - if (curr.ac) - ocpc_get_adcs(&curr.ocpc); -#endif /* CONFIG_OCPC */ - - if (prev_bp != curr.batt.is_present) { - prev_bp = curr.batt.is_present; - - /* Update battery info due to change of battery */ - batt_info = battery_get_info(); - need_static = 1; - - curr.desired_input_current = - get_desired_input_current(prev_bp, info); - if (curr.desired_input_current != - CHARGE_CURRENT_UNINITIALIZED) - charger_set_input_current(chgnum, - curr.desired_input_current); - hook_notify(HOOK_BATTERY_SOC_CHANGE); - } - - /* - * TODO(crosbug.com/p/27527). Sometimes the battery thinks its - * temperature is 6280C, which seems a bit high. Let's ignore - * anything above the boiling point of tungsten until this bug - * is fixed. If the battery is really that warm, we probably - * have more urgent problems. - */ - if (curr.batt.temperature > CELSIUS_TO_DECI_KELVIN(5660)) { - CPRINTS("ignoring ridiculous batt.temp of %dC", - DECI_KELVIN_TO_CELSIUS(curr.batt.temperature)); - curr.batt.flags |= BATT_FLAG_BAD_TEMPERATURE; - } - - /* If the battery thinks it's above 100%, don't believe it */ - if (curr.batt.state_of_charge > 100) { - CPRINTS("ignoring ridiculous batt.soc of %d%%", - curr.batt.state_of_charge); - curr.batt.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - } - - notify_host_of_over_current(&curr.batt); - - /* battery current stable now, saves the current. */ - if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV) && - get_time().val > stable_ts.val && curr.batt.current >= 0) - stable_current = curr.batt.current; - - /* - * Now decide what we want to do about it. We'll normally just - * pass along whatever the battery wants to the charger. Note - * that if battery_get_params() can't get valid values from the - * battery it uses (0, 0), which is probably safer than blindly - * applying power to a battery we can't talk to. - */ - if (curr.batt.flags & (BATT_FLAG_BAD_DESIRED_VOLTAGE | - BATT_FLAG_BAD_DESIRED_CURRENT)) { - curr.requested_voltage = 0; - curr.requested_current = 0; - } else { - curr.requested_voltage = curr.batt.desired_voltage; - curr.requested_current = curr.batt.desired_current; - } - - /* If we *know* there's no battery, wait for one to appear. */ - if (curr.batt.is_present == BP_NO) { - if (!curr.ac) - CPRINTS("running with no battery and no AC"); - set_charge_state(ST_IDLE); - curr.batt_is_charging = 0; - battery_was_removed = 1; - goto wait_for_it; - } - - /* - * If we had trouble talking to the battery or the charger, we - * should probably do nothing for a bit, and if it doesn't get - * better then flag it as an error. - */ - if (curr.chg.flags & CHG_FLAG_BAD_ANY) - problem(PR_CHG_FLAGS, curr.chg.flags); - if (curr.batt.flags & BATT_FLAG_BAD_ANY) - problem(PR_BATT_FLAGS, curr.batt.flags); - - /* - * If AC is present, check if input current is sufficient to - * actually charge battery. - */ - curr.batt_is_charging = curr.ac && (curr.batt.current >= 0); - - /* Don't let the battery hurt itself. */ - battery_critical = shutdown_on_critical_battery(); - - if (!curr.ac) { - set_charge_state(ST_DISCHARGE); - goto wait_for_it; - } - - /* Okay, we're on AC and we should have a battery. */ - - /* Used for factory tests. */ - if (chg_ctl_mode != CHARGE_CONTROL_NORMAL) { - set_charge_state(ST_IDLE); - goto wait_for_it; - } - - /* If the battery is not responsive, try to wake it up. */ - if (!(curr.batt.flags & BATT_FLAG_RESPONSIVE)) { - if (battery_seems_to_be_dead || battery_is_cut_off()) { - /* It's dead, do nothing */ - set_charge_state(ST_IDLE); - curr.requested_voltage = 0; - curr.requested_current = 0; - } else if (curr.state == ST_PRECHARGE && - (get_time().val > precharge_start_time.val + - PRECHARGE_TIMEOUT_US)) { - /* We've tried long enough, give up */ - CPRINTS("battery seems to be dead"); - battery_seems_to_be_dead = 1; - set_charge_state(ST_IDLE); - curr.requested_voltage = 0; - curr.requested_current = 0; - } else { - /* See if we can wake it up */ - if (curr.state != ST_PRECHARGE) { - CPRINTS("try to wake battery"); - precharge_start_time = get_time(); - need_static = 1; - } - set_charge_state(ST_PRECHARGE); - curr.requested_voltage = - batt_info->voltage_max; - curr.requested_current = - batt_info->precharge_current; - } - goto wait_for_it; - } else { - /* The battery is responding. Yay. Try to use it. */ -#ifdef CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD - /* - * TODO (crosbug.com/p/29467): remove this workaround - * for dead battery that requests no voltage/current - */ - if (curr.requested_voltage == 0 && - curr.requested_current == 0 && -#ifdef CONFIG_BATTERY_DEAD_UNTIL_VALUE - curr.batt.state_of_charge < CONFIG_BATTERY_DEAD_UNTIL_VALUE) { -#else - curr.batt.state_of_charge == 0) { -#endif - /* Battery is dead, give precharge current */ - curr.requested_voltage = - batt_info->voltage_max; - curr.requested_current = - batt_info->precharge_current; - } else -#endif -#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT - /* - * Always check the disconnect state. This is because - * the battery disconnect state is one of the items used - * to decide whether or not to leave safe mode. - */ - battery_seems_to_be_disconnected = - battery_get_disconnect_state() == - BATTERY_DISCONNECTED; - - if (curr.requested_voltage == 0 && - curr.requested_current == 0 && - battery_seems_to_be_disconnected) { - /* - * Battery is in disconnect state. Apply a - * current to kick it out of this state. - */ - CPRINTS("found battery in disconnect state"); - curr.requested_voltage = - batt_info->voltage_max; - curr.requested_current = - batt_info->precharge_current; - } else -#endif - if (curr.state == ST_PRECHARGE || - battery_seems_to_be_dead || - battery_was_removed) { - CPRINTS("battery woke up"); - - /* Update the battery-specific values */ - batt_info = battery_get_info(); - need_static = 1; - } - - battery_seems_to_be_dead = battery_was_removed = 0; - set_charge_state(ST_CHARGE); - } - -wait_for_it: -#ifdef CONFIG_CHARGER_PROFILE_OVERRIDE - if (chg_ctl_mode == CHARGE_CONTROL_NORMAL) { - sleep_usec = charger_profile_override(&curr); - if (sleep_usec < 0) - problem(PR_CUSTOM, sleep_usec); - } -#endif - -#ifdef CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS - if (battery_outside_charging_temperature()) { - curr.requested_current = 0; - curr.requested_voltage = 0; - curr.batt.flags &= ~BATT_FLAG_WANT_CHARGE; - if (curr.state != ST_DISCHARGE) - curr.state = ST_IDLE; - } -#endif - -#ifdef CONFIG_CHARGE_MANAGER - if (curr.batt.state_of_charge >= - CONFIG_CHARGE_MANAGER_BAT_PCT_SAFE_MODE_EXIT && - !battery_seems_to_be_disconnected) { - /* - * Sometimes the fuel gauge will report that it has - * sufficient state of charge and remaining capacity, - * but in actuality it doesn't. When the EC sees that - * information, it trusts it and leaves charge manager - * safe mode. Doing so will allow CHARGE_PORT_NONE to - * be selected, thereby cutting off the input FETs. - * When the battery cannot provide the charge it claims, - * the system loses power, shuts down, and the battery - * is not charged even though the charger is plugged in. - * By waiting 500ms, we can avoid the selection of - * CHARGE_PORT_NONE around init time and not cut off the - * input FETs. - */ - msleep(500); - charge_manager_leave_safe_mode(); - } -#endif - - /* Keep the AP informed */ - if (need_static) - need_static = update_static_battery_info(); - /* Wait on the dynamic info until the static info is good. */ - if (!need_static) - update_dynamic_battery_info(); - notify_host_of_low_battery_charge(); - notify_host_of_low_battery_voltage(); - - /* And the EC console */ - is_full = calc_is_full(); - if ((!(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && - curr.batt.state_of_charge != prev_charge) || -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - (charge_base != prev_charge_base) || -#endif - (is_full != prev_full) || - (curr.state != prev_state) || - (curr.batt.display_charge != prev_disp_charge)) { - show_charging_progress(); - prev_charge = curr.batt.state_of_charge; - prev_disp_charge = curr.batt.display_charge; -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - prev_charge_base = charge_base; -#endif - hook_notify(HOOK_BATTERY_SOC_CHANGE); - } - prev_full = is_full; - -#ifndef CONFIG_CHARGER_MAINTAIN_VBAT - /* Turn charger off if it's not needed */ - if (curr.state == ST_IDLE || curr.state == ST_DISCHARGE) { - curr.requested_voltage = 0; - curr.requested_current = 0; - } -#endif - - /* Apply external limits */ - if (curr.requested_current > user_current_limit) - curr.requested_current = user_current_limit; - - /* Round to valid values */ - curr.requested_voltage = - charger_closest_voltage(curr.requested_voltage); - curr.requested_current = - charger_closest_current(curr.requested_current); - - /* Charger only accpets request when AC is on. */ - if (curr.ac) { - /* - * Some batteries would wake up after cut-off if we keep - * charging it. Thus, we only charge when AC is on and - * battery is not cut off yet. - */ - if (battery_is_cut_off()) { - curr.requested_voltage = 0; - curr.requested_current = 0; - } - /* - * As a safety feature, some chargers will stop - * charging if we don't communicate with it frequently - * enough. In manual mode, we'll just tell it what it - * knows. - */ - else { - if (manual_voltage != -1) - curr.requested_voltage = manual_voltage; - if (manual_current != -1) - curr.requested_current = manual_current; - } - } else { -#ifndef CONFIG_CHARGER_MAINTAIN_VBAT - curr.requested_voltage = charger_closest_voltage( - curr.batt.voltage + info->voltage_step); - curr.requested_current = -1; -#endif -#ifdef CONFIG_EC_EC_COMM_BATTERY_SLAVE - /* - * On EC-EC slave, do not charge if curr.ac is 0: there - * might still be some external power available but we - * do not want to use it for charging. - */ - curr.requested_current = 0; -#endif - } - -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - charge_allocate_input_current_limit(); -#else - charge_request(curr.requested_voltage, curr.requested_current); -#endif - - /* How long to sleep? */ - if (problems_exist) - /* If there are errors, don't wait very long. */ - sleep_usec = CHARGE_POLL_PERIOD_SHORT; - else if (sleep_usec <= 0) { - /* default values depend on the state */ - if (!curr.ac && - (curr.state == ST_IDLE || - curr.state == ST_DISCHARGE)) { -#ifdef CONFIG_CHARGER_OTG - int output_current = curr.output_current; -#else - int output_current = 0; -#endif - /* - * If AP is off and we do not provide power, we - * can sleep a long time. - */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF | - CHIPSET_STATE_ANY_SUSPEND) - && output_current == 0) - sleep_usec = - CHARGE_POLL_PERIOD_VERY_LONG; - else - /* Discharging, not too urgent */ - sleep_usec = CHARGE_POLL_PERIOD_LONG; - } else { - /* AC present, so pay closer attention */ - sleep_usec = CHARGE_POLL_PERIOD_CHARGE; - } - } - - if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV)) { - int is_pd_supply = charge_manager_get_supplier() == - CHARGE_SUPPLIER_PD; - int port = charge_manager_get_active_charge_port(); - int bat_spec_desired_mw = curr.batt.desired_current * - curr.batt.desired_voltage / - 1000; - - /* - * save the previous plt_and_desired_mw, since it - * will be updated below - */ - prev_plt_and_desired_mw = - charge_get_plt_plus_bat_desired_mw(); - - /* - * Update desired power by the following rules: - * 1. If the battery is not charging with PD, we reset - * the desired_mw to the battery spec. The actual - * desired_mw will be evaluated when it starts charging - * with PD again. - * 2. If the battery SoC under battery's constant - * voltage percent (this is a rough value that can be - * applied to most batteries), the battery can fully - * sink the power, the desired power should be the - * same as the battery spec, and we don't need to use - * evaluated value stable_current. - * 3. If the battery SoC is above battery's constant - * voltage percent, the real battery desired charging - * power will decrease slowly and so does the charging - * current. We can evaluate the battery desired power - * by the product of stable_current and battery voltage. - */ - if (!is_pd_supply) - desired_mw = bat_spec_desired_mw; - else if (curr.batt.state_of_charge < pd_pref_config.cv) - desired_mw = bat_spec_desired_mw; - else if (stable_current != CHARGE_CURRENT_UNINITIALIZED) - desired_mw = curr.batt.voltage * - stable_current / 1000; - - /* if the plt_and_desired_mw changes, re-evaluate PDO */ - if (is_pd_supply && - prev_plt_and_desired_mw != - charge_get_plt_plus_bat_desired_mw()) - pd_set_new_power_request(port); - } - - /* Adjust for time spent in this loop */ - sleep_usec -= (int)(get_time().val - curr.ts.val); - if (sleep_usec < CHARGE_MIN_SLEEP_USEC) - sleep_usec = CHARGE_MIN_SLEEP_USEC; - else if (sleep_usec > CHARGE_MAX_SLEEP_USEC) - sleep_usec = CHARGE_MAX_SLEEP_USEC; - - /* - * If battery is critical, ensure that the sleep time is not - * very long since we might want to hibernate or cut-off - * battery sooner. - */ - if (battery_critical && - (sleep_usec > CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US)) - sleep_usec = CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US; - - task_wait_event(sleep_usec); - } -} - - -/*****************************************************************************/ -/* Exported functions */ - -int charge_want_shutdown(void) -{ - return (curr.state == ST_DISCHARGE) && - !(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && - (curr.batt.state_of_charge < battery_level_shutdown); -} - -int charge_prevent_power_on(int power_button_pressed) -{ - int prevent_power_on = 0; - struct batt_params params; - struct batt_params *current_batt_params = &curr.batt; -#ifdef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON - static int automatic_power_on = 1; -#endif - - /* If battery params seem uninitialized then retrieve them */ - if (current_batt_params->is_present == BP_NOT_SURE) { - battery_get_params(¶ms); - current_batt_params = ¶ms; - } - -#ifdef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON - - /* - * Remember that a power button was pressed, and assume subsequent - * power-ups are user-requested and non-automatic. - */ - if (power_button_pressed) - automatic_power_on = 0; - /* - * Require a minimum battery level to power on and ensure that the - * battery can provide power to the system. - */ - if (current_batt_params->is_present != BP_YES || -#ifdef CONFIG_BATTERY_MEASURE_IMBALANCE - (current_batt_params->flags & BATT_FLAG_IMBALANCED_CELL && - current_batt_params->state_of_charge < - CONFIG_CHARGER_MIN_BAT_PCT_IMBALANCED_POWER_ON) || -#endif -#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT - battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED || -#endif - current_batt_params->state_of_charge < - CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) - prevent_power_on = 1; - -#if defined(CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON) && \ - defined(CONFIG_CHARGE_MANAGER) - /* However, we can power on if a sufficient charger is present. */ - if (prevent_power_on) { - if (charge_manager_get_power_limit_uw() >= - CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000) - prevent_power_on = 0; -#if defined(CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT) && \ - defined(CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC) - else if (charge_manager_get_power_limit_uw() >= - CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT * 1000 -#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT - && battery_get_disconnect_state() == - BATTERY_NOT_DISCONNECTED -#endif - && (current_batt_params->state_of_charge >= - CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC)) - prevent_power_on = 0; -#endif - } -#endif /* CONFIG_CHARGE_MANAGER && CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON */ - - /* - * Factory override: Always allow power on if WP is disabled, - * except when auto-power-on at EC startup and the battery - * is physically present. - */ - prevent_power_on &= (system_is_locked() || (automatic_power_on -#ifdef CONFIG_BATTERY_HW_PRESENT_CUSTOM - && battery_hw_present() == BP_YES -#endif - )); -#endif /* CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON */ - -#ifdef CONFIG_CHARGE_MANAGER - /* Always prevent power on until charge current is initialized */ - if (extpower_is_present() && - (charge_manager_get_charger_current() == - CHARGE_CURRENT_UNINITIALIZED)) - prevent_power_on = 1; -#ifdef CONFIG_BATTERY_HW_PRESENT_CUSTOM - /* - * If battery is NOT physically present then prevent power on until - * a sufficient charger is present. - */ - if (extpower_is_present() && battery_hw_present() == BP_NO -#ifdef CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON - && charge_manager_get_power_limit_uw() < - CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000 -#endif /* CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON */ - ) - prevent_power_on = 1; -#endif /* CONFIG_BATTERY_HW_PRESENT_CUSTOM */ -#endif /* CONFIG_CHARGE_MANAGER */ - - /* - * Prevent power on if there is no battery nor ac power. This - * happens when the servo is powering the EC to flash it. Only include - * this logic for boards in initial bring up phase since this won't - * happen for released boards. - */ -#ifdef CONFIG_SYSTEM_UNLOCKED - if (!current_batt_params->is_present && !curr.ac) - prevent_power_on = 1; -#endif /* CONFIG_SYSTEM_UNLOCKED */ - - return prevent_power_on; -} - -static int battery_near_full(void) -{ - if (charge_get_percent() < BATTERY_LEVEL_NEAR_FULL) - return 0; - -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - if (charge_base > -1 && charge_base < BATTERY_LEVEL_NEAR_FULL) - return 0; -#endif - - return 1; -} - -enum charge_state charge_get_state(void) -{ - switch (curr.state) { - case ST_IDLE: - if (battery_seems_to_be_dead || curr.batt.is_present == BP_NO) - return PWR_STATE_ERROR; - return PWR_STATE_IDLE; - case ST_DISCHARGE: -#ifdef CONFIG_PWR_STATE_DISCHARGE_FULL - if (battery_near_full()) - return PWR_STATE_DISCHARGE_FULL; - else -#endif - return PWR_STATE_DISCHARGE; - case ST_CHARGE: - /* The only difference here is what the LEDs display. */ - if (battery_near_full()) - return PWR_STATE_CHARGE_NEAR_FULL; - else - return PWR_STATE_CHARGE; - case ST_PRECHARGE: - /* we're in battery discovery mode */ - return PWR_STATE_IDLE; - default: - /* Anything else can be considered an error for LED purposes */ - return PWR_STATE_ERROR; - } -} - -uint32_t charge_get_flags(void) -{ - uint32_t flags = 0; - - if (chg_ctl_mode != CHARGE_CONTROL_NORMAL) - flags |= CHARGE_FLAG_FORCE_IDLE; - if (curr.ac) - flags |= CHARGE_FLAG_EXTERNAL_POWER; - if (curr.batt.flags & BATT_FLAG_RESPONSIVE) - flags |= CHARGE_FLAG_BATT_RESPONSIVE; - - return flags; -} - -int charge_get_percent(void) -{ - /* - * Since there's no way to indicate an error to the caller, we'll just - * return the last known value. Even if we've never been able to talk - * to the battery, that'll be zero, which is probably as good as - * anything. - */ - return is_full ? 100 : curr.batt.state_of_charge; -} - -int charge_get_display_charge(void) -{ - return curr.batt.display_charge; -} - -int charge_get_battery_temp(int idx, int *temp_ptr) -{ - if (curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) - return EC_ERROR_UNKNOWN; - - /* Battery temp is 10ths of degrees K, temp wants degrees K */ - *temp_ptr = curr.batt.temperature / 10; - return EC_SUCCESS; -} - -__overridable int charge_is_consuming_full_input_current(void) -{ - int chg_pct = charge_get_percent(); - - return chg_pct > 2 && chg_pct < 95; -} - -#ifdef CONFIG_CHARGER_OTG -int charge_set_output_current_limit(int chgnum, int ma, int mv) -{ - int ret; - int enable = ma > 0; - - if (enable) { - ret = charger_set_otg_current_voltage(chgnum, ma, mv); - if (ret != EC_SUCCESS) - return ret; - } - - ret = charger_enable_otg_power(chgnum, enable); - if (ret != EC_SUCCESS) - return ret; - - /* If we start/stop providing power, wake the charger task. */ - if ((curr.output_current == 0 && enable) || - (curr.output_current > 0 && !enable)) - task_wake(TASK_ID_CHARGER); - - curr.output_current = ma; - - return EC_SUCCESS; -} -#endif - -int charge_set_input_current_limit(int ma, int mv) -{ - __maybe_unused int chgnum = 0; - - if (IS_ENABLED(CONFIG_OCPC)) - chgnum = charge_get_active_chg_chip(); -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - curr.input_voltage = mv; -#endif - /* - * If battery is not present, we are not locked, and base is not - * connected then allow system to pull as much input current as needed. - * Yes, we might overcurrent the charger but this is no worse than - * browning out due to insufficient input current. - */ - if (curr.batt.is_present != BP_YES && !system_is_locked() && - !base_connected) { - - int prev_input = 0; - - charger_get_input_current(chgnum, &prev_input); - -#ifdef CONFIG_USB_POWER_DELIVERY -#if ((PD_MAX_POWER_MW * 1000) / PD_MAX_VOLTAGE_MV != PD_MAX_CURRENT_MA) - /* - * If battery is not present, input current is set to - * PD_MAX_CURRENT_MA. If the input power set is greater than - * the maximum allowed system power, system might get damaged. - * Hence, limit the input current to meet maximum allowed - * input system power. - */ - - if (mv > 0 && mv * curr.desired_input_current > - PD_MAX_POWER_MW * 1000) - ma = (PD_MAX_POWER_MW * 1000) / mv; - /* - * If the active charger has already been initialized to at - * least this current level, nothing left to do. - */ - else if (prev_input >= ma) - return EC_SUCCESS; -#else - if (prev_input >= ma) - return EC_SUCCESS; -#endif - /* - * If the current needs lowered due to PD max power - * considerations, or needs raised for the selected active - * charger chip, fall through to set. - */ -#endif /* CONFIG_USB_POWER_DELIVERY */ - } - -#ifdef CONFIG_CHARGER_MAX_INPUT_CURRENT - /* Limit input current limit to max limit for this board */ - ma = MIN(ma, CONFIG_CHARGER_MAX_INPUT_CURRENT); -#endif - curr.desired_input_current = ma; -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER - /* Wake up charger task to allocate current between lid and base. */ - charge_wakeup(); - return EC_SUCCESS; -#else - return charger_set_input_current(chgnum, ma); -#endif -} - -#ifdef CONFIG_OCPC -void charge_set_active_chg_chip(int idx) -{ - ASSERT(idx < (int)board_get_charger_chip_count()); - - if (idx == curr.ocpc.active_chg_chip) - return; - - CPRINTS("Act Chg: %d", idx); - curr.ocpc.active_chg_chip = idx; - if (idx == CHARGE_PORT_NONE) { - curr.ocpc.last_error = 0; - curr.ocpc.integral = 0; - curr.ocpc.last_vsys = OCPC_UNINIT; - } -} -#endif /* CONFIG_OCPC */ - -int charge_get_active_chg_chip(void) -{ -#ifdef CONFIG_OCPC - return curr.ocpc.active_chg_chip; -#else - return 0; -#endif -} - -#ifdef CONFIG_USB_PD_PREFER_MV -bool charge_is_current_stable(void) -{ - return get_time().val >= stable_ts.val; -} - -int charge_get_plt_plus_bat_desired_mw(void) -{ - /* - * Ideally, the system consuming power could be evaluated by - * "IBus * VBus - battery charging power". But in practice, - * most charger drivers don't implement IBUS ADC reading, - * so we use system PLT instead as an alterntaive approach. - */ - return pd_pref_config.plt_mw + desired_mw; -} - -int charge_get_stable_current(void) -{ - return stable_current; -} - -void charge_set_stable_current(int ma) -{ - stable_current = ma; -} - -void charge_reset_stable_current_us(uint64_t us) -{ - timestamp_t now = get_time(); - - if (stable_ts.val < now.val + us) - stable_ts.val = now.val + us; - - stable_current = CHARGE_CURRENT_UNINITIALIZED; -} - -void charge_reset_stable_current(void) -{ - /* it takes 8 to 10 seconds to stabilize battery current in practice */ - charge_reset_stable_current_us(10 * SECOND); -} -#endif - -/*****************************************************************************/ -/* Host commands */ - -static enum ec_status -charge_command_charge_control(struct host_cmd_handler_args *args) -{ - const struct ec_params_charge_control *p = args->params; - int rv; - - rv = set_chg_ctrl_mode(p->mode); - if (rv != EC_SUCCESS) - return EC_RES_ERROR; - -#ifdef CONFIG_CHARGER_DISCHARGE_ON_AC -#ifdef CONFIG_CHARGER_DISCHARGE_ON_AC_CUSTOM - rv = board_discharge_on_ac(p->mode == CHARGE_CONTROL_DISCHARGE); -#else - rv = charger_discharge_on_ac(p->mode == CHARGE_CONTROL_DISCHARGE); -#endif - if (rv != EC_SUCCESS) - return EC_RES_ERROR; -#endif - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_CHARGE_CONTROL, charge_command_charge_control, - EC_VER_MASK(1)); - -static void reset_current_limit(void) -{ - user_current_limit = -1U; -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, reset_current_limit, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, reset_current_limit, HOOK_PRIO_DEFAULT); - -static enum ec_status -charge_command_current_limit(struct host_cmd_handler_args *args) -{ - const struct ec_params_current_limit *p = args->params; - - user_current_limit = p->limit; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_CHARGE_CURRENT_LIMIT, charge_command_current_limit, - EC_VER_MASK(0)); - -static enum ec_status -charge_command_charge_state(struct host_cmd_handler_args *args) -{ - const struct ec_params_charge_state *in = args->params; - struct ec_response_charge_state *out = args->response; - uint32_t val; - int rv = EC_RES_SUCCESS; - int chgnum = 0; - - if (args->version > 0) - chgnum = in->chgnum; - - switch (in->cmd) { - - case CHARGE_STATE_CMD_GET_STATE: - out->get_state.ac = curr.ac; - out->get_state.chg_voltage = curr.chg.voltage; - out->get_state.chg_current = curr.chg.current; - out->get_state.chg_input_current = curr.chg.input_current; - out->get_state.batt_state_of_charge = curr.batt.state_of_charge; - args->response_size = sizeof(out->get_state); - break; - - case CHARGE_STATE_CMD_GET_PARAM: - val = 0; -#ifdef CONFIG_CHARGER_PROFILE_OVERRIDE - /* custom profile params */ - if (in->get_param.param >= CS_PARAM_CUSTOM_PROFILE_MIN && - in->get_param.param <= CS_PARAM_CUSTOM_PROFILE_MAX) { - rv = charger_profile_override_get_param( - in->get_param.param, &val); - } else -#endif -#ifdef CONFIG_CHARGE_STATE_DEBUG - /* debug params */ - if (in->get_param.param >= CS_PARAM_DEBUG_MIN && - in->get_param.param <= CS_PARAM_DEBUG_MAX) { - rv = charge_get_charge_state_debug( - in->get_param.param, &val); - } else -#endif - /* standard params */ - switch (in->get_param.param) { - case CS_PARAM_CHG_VOLTAGE: - val = curr.chg.voltage; - break; - case CS_PARAM_CHG_CURRENT: - val = curr.chg.current; - break; - case CS_PARAM_CHG_INPUT_CURRENT: - val = curr.chg.input_current; - break; - case CS_PARAM_CHG_STATUS: - val = curr.chg.status; - break; - case CS_PARAM_CHG_OPTION: - val = curr.chg.option; - break; - case CS_PARAM_LIMIT_POWER: -#ifdef CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW - /* - * LIMIT_POWER status is based on battery level - * and external charger power. - */ - if ((curr.batt.is_present != BP_YES || - curr.batt.state_of_charge < - CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT) - && charge_manager_get_power_limit_uw() < - CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW - * 1000 && system_is_locked()) - val = 1; - else -#endif - val = 0; - break; - default: - rv = EC_RES_INVALID_PARAM; - } - - /* got something */ - out->get_param.value = val; - args->response_size = sizeof(out->get_param); - break; - - case CHARGE_STATE_CMD_SET_PARAM: - if (system_is_locked()) - return EC_RES_ACCESS_DENIED; - - val = in->set_param.value; -#ifdef CONFIG_CHARGER_PROFILE_OVERRIDE - /* custom profile params */ - if (in->set_param.param >= CS_PARAM_CUSTOM_PROFILE_MIN && - in->set_param.param <= CS_PARAM_CUSTOM_PROFILE_MAX) { - rv = charger_profile_override_set_param( - in->set_param.param, val); - } else -#endif - switch (in->set_param.param) { - case CS_PARAM_CHG_VOLTAGE: - chgstate_set_manual_voltage(val); - break; - case CS_PARAM_CHG_CURRENT: - chgstate_set_manual_current(val); - break; - case CS_PARAM_CHG_INPUT_CURRENT: - if (charger_set_input_current(chgnum, val)) - rv = EC_RES_ERROR; - break; - case CS_PARAM_CHG_STATUS: - case CS_PARAM_LIMIT_POWER: - /* Can't set this */ - rv = EC_RES_ACCESS_DENIED; - break; - case CS_PARAM_CHG_OPTION: - if (charger_set_option(val)) - rv = EC_RES_ERROR; - break; - default: - rv = EC_RES_INVALID_PARAM; - - } - break; - - default: - CPRINTS("EC_CMD_CHARGE_STATE: bad cmd 0x%x", in->cmd); - rv = EC_RES_INVALID_PARAM; - } - - return rv; -} - -DECLARE_HOST_COMMAND(EC_CMD_CHARGE_STATE, charge_command_charge_state, - EC_VER_MASK(0) | EC_VER_MASK(1)); - -/*****************************************************************************/ -/* Console commands */ - -#ifdef CONFIG_CMD_PWR_AVG - -static int command_pwr_avg(int argc, char **argv) -{ - int avg_mv; - int avg_ma; - int avg_mw; - - if (argc != 1) - return EC_ERROR_PARAM_COUNT; - - avg_mv = battery_get_avg_voltage(); - if (avg_mv < 0) - return EC_ERROR_UNKNOWN; - avg_ma = battery_get_avg_current(); - avg_mw = avg_mv * avg_ma / 1000; - - ccprintf("mv = %d\nma = %d\nmw = %d\n", - avg_mv, avg_ma, avg_mw); - return EC_SUCCESS; -} - -DECLARE_CONSOLE_COMMAND(pwr_avg, command_pwr_avg, - NULL, - "Get 1 min power average"); - -#endif /* CONFIG_CMD_PWR_AVG */ - -static int command_chgstate(int argc, char **argv) -{ - int rv; - int val; - - if (argc > 1) { - if (!strcasecmp(argv[1], "idle")) { - if (argc <= 2) - return EC_ERROR_PARAM_COUNT; - if (!parse_bool(argv[2], &val)) - return EC_ERROR_PARAM2; - rv = set_chg_ctrl_mode(val ? CHARGE_CONTROL_IDLE : - CHARGE_CONTROL_NORMAL); - if (rv) - return rv; -#ifdef CONFIG_CHARGER_DISCHARGE_ON_AC - } else if (!strcasecmp(argv[1], "discharge")) { - if (argc <= 2) - return EC_ERROR_PARAM_COUNT; - if (!parse_bool(argv[2], &val)) - return EC_ERROR_PARAM2; - rv = set_chg_ctrl_mode(val ? CHARGE_CONTROL_DISCHARGE : - CHARGE_CONTROL_NORMAL); - if (rv) - return rv; -#ifdef CONFIG_CHARGER_DISCHARGE_ON_AC_CUSTOM - rv = board_discharge_on_ac(val); -#else - rv = charger_discharge_on_ac(val); -#endif /* CONFIG_CHARGER_DISCHARGE_ON_AC_CUSTOM */ - if (rv) - return rv; -#endif /* CONFIG_CHARGER_DISCHARGE_ON_AC */ - } else if (!strcasecmp(argv[1], "debug")) { - if (argc <= 2) - return EC_ERROR_PARAM_COUNT; - if (!parse_bool(argv[2], &debugging)) - return EC_ERROR_PARAM2; - } else { - return EC_ERROR_PARAM1; - } - } - - dump_charge_state(); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(chgstate, command_chgstate, - "[idle|discharge|debug on|off]", - "Get/set charge state machine status"); - -#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER -static int command_chgdualdebug(int argc, char **argv) -{ - int val; - char *e; - - if (argc > 1) { - if (argv[1][0] == 'c') { - if (argc <= 2) - return EC_ERROR_PARAM_COUNT; - - if (!strcasecmp(argv[2], "auto")) { - val = -1; - } else { - val = strtoi(argv[2], &e, 0); - if (*e || val < 0) - return EC_ERROR_PARAM2; - } - - manual_ac_current_base = val; - charge_wakeup(); - } else if (argv[1][0] == 'd') { - if (argc <= 2) - return EC_ERROR_PARAM_COUNT; - - if (!strcasecmp(argv[2], "auto")) { - manual_noac_enabled = 0; - } else { - val = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - manual_noac_current_base = val; - manual_noac_enabled = 1; - } - charge_wakeup(); - } else { - return EC_ERROR_PARAM1; - } - } else { - ccprintf("Base/Lid: %d%s/%d mA\n", - prev_current_base, prev_allow_charge_base ? "+" : "", - prev_current_lid); - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(chgdualdebug, command_chgdualdebug, - "[charge (auto|)|discharge (auto|)]", - "Manually control dual-battery charging algorithm."); -#endif - -#ifdef CONFIG_CHARGE_STATE_DEBUG -int charge_get_charge_state_debug(int param, uint32_t *value) -{ - switch (param) { - case CS_PARAM_DEBUG_CTL_MODE: - *value = chg_ctl_mode; - break; - case CS_PARAM_DEBUG_MANUAL_CURRENT: - *value = manual_current; - break; - case CS_PARAM_DEBUG_MANUAL_VOLTAGE: - *value = manual_voltage; - break; - case CS_PARAM_DEBUG_SEEMS_DEAD: - *value = battery_seems_to_be_dead; - break; - case CS_PARAM_DEBUG_SEEMS_DISCONNECTED: - *value = battery_seems_to_be_disconnected; - break; - case CS_PARAM_DEBUG_BATT_REMOVED: - *value = battery_was_removed; - break; - default: - *value = 0; - return EC_ERROR_INVAL; - } - - return EC_SUCCESS; -} -#endif diff --git a/common/chargen.c b/common/chargen.c index 24e30bb878..626e13e71f 100644 --- a/common/chargen.c +++ b/common/chargen.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,8 @@ #include "common.h" #include "config.h" #include "console.h" +#include "hooks.h" +#include "task.h" #include "timer.h" #include "uart.h" #include "usb_console.h" @@ -13,62 +15,75 @@ #include "watchdog.h" #ifndef SECTION_IS_RO + +/** + * Some unit tests do not have a watchdog enabled and the watchdog + * functions are stubbed. Define a default watchdog period in this case. + */ +#ifdef CONFIG_WATCHDOG_PERIOD_MS +#define CHARGEN_WATCHDOG_PERIOD_MS CONFIG_WATCHDOG_PERIOD_MS +#else +#define CHARGEN_WATCHDOG_PERIOD_MS 1600 +#endif + /* * Microseconds time to drain entire UART_TX console buffer at 115200 b/s, 10 * bits per character. */ -#define BUFFER_DRAIN_TIME_US (1000000UL * 10 * CONFIG_UART_TX_BUF_SIZE \ - / CONFIG_UART_BAUD_RATE) +#define BUFFER_DRAIN_TIME_US \ + (1000000UL * 10 * CONFIG_UART_TX_BUF_SIZE / CONFIG_UART_BAUD_RATE) + +struct deferred_chargen_ctx { + int wrap_value; + uint32_t seq_number; + int (*putc)(int c); + int (*tx_is_blocked)(void); +}; +static struct deferred_chargen_ctx chargen_ctx; + +static void acquire_console(void) +{ +#if !defined(CONFIG_USB_CONSOLE) && !defined(CONFIG_USB_CONSOLE_STREAM) + uart_shell_rx_bypass(true); +#endif +#if !defined(CONFIG_ZEPHYR) && !defined(BOARD_HOST) + /* The legacy fw console does not have an rx bypass feature (it is + * stubbed out). Disable the console task so that it does not + * steal character reads from chargen. + */ + if (task_start_called()) + task_disable_task(TASK_ID_CONSOLE); +#endif /* !CONFIG_ZEPHYR && !BOARD_HOST */ +} -/* - * Generate a stream of characters on the UART (and USB) console. - * - * The stream is an ever incrementing pattern of characters from the following - * set: 0..9A..Za..z. - * - * The two optional integer command line arguments work as follows: - * - * argv[1] - reset the pattern after this many characters have been printed. - * Setting this value to the width of the terminal window results - * in a very regular stream showing on the terminal, where it is - * easy to observe disruptions. - * argv[2] - limit number of printed characters to this amount. If not - * specified - keep printing indefinitely. - * - * Hitting 'x' on the keyboard stops the generator. - */ -static int command_chargen(int argc, char **argv) +static void release_console(void) { - int wrap_value = 0; - int wrap_counter = 0; - uint8_t c; - uint32_t seq_counter = 0; - uint32_t seq_number = 0; +#if !defined(CONFIG_USB_CONSOLE) && !defined(CONFIG_USB_CONSOLE_STREAM) + uart_shell_rx_bypass(false); +#endif +#if !defined(CONFIG_ZEPHYR) && !defined(BOARD_HOST) + if (task_start_called()) + task_enable_task(TASK_ID_CONSOLE); +#endif /* !CONFIG_ZEPHYR && !BOARD_HOST */ +} + +static void run_chargen(void) +{ + int wrap_value = chargen_ctx.wrap_value; + uint32_t seq_number = chargen_ctx.seq_number; + int (*putc_)(int c) = chargen_ctx.putc; + int (*tx_is_blocked_)(void) = chargen_ctx.tx_is_blocked; + timestamp_t prev_watchdog_time; + uint8_t c = '0'; + uint32_t seq_counter = 0; + int wrap_counter = 0; - int (*putc_)(int c) = uart_putc; - int (*tx_is_blocked_)(void) = uart_buffer_full; + acquire_console(); while (uart_getc() != -1 || usb_getc() != -1) ; /* Drain received characters, if any. */ - if (argc > 1) - wrap_value = atoi(argv[1]); - - if (argc > 2) - seq_number = atoi(argv[2]); - -#if defined(CONFIG_USB_CONSOLE) || defined(CONFIG_USB_CONSOLE_STREAM) - if (argc > 3) { - if (memcmp(argv[3], "usb", 3)) - return EC_ERROR_PARAM3; - - putc_ = usb_putc; - tx_is_blocked_ = usb_console_tx_blocked; - } -#endif - - c = '0'; prev_watchdog_time = get_time(); while (uart_getc() != 'x' && usb_getc() != 'x') { timestamp_t current_time; @@ -78,18 +93,21 @@ static int command_chargen(int argc, char **argv) * Let's let other tasks run for a bit while buffer is * being drained a little. */ - usleep(BUFFER_DRAIN_TIME_US/10); + usleep(BUFFER_DRAIN_TIME_US / 10); current_time = get_time(); if ((current_time.val - prev_watchdog_time.val) < - (CONFIG_WATCHDOG_PERIOD_MS * 1000 / 2)) + (CHARGEN_WATCHDOG_PERIOD_MS * 1000 / 2)) continue; watchdog_reload(); prev_watchdog_time.val = current_time.val; } + if (IS_ENABLED(CONFIG_ZEPHYR) && c == '0') + watchdog_reload(); + putc_(c++); if (seq_number && (++seq_counter == seq_number)) @@ -105,12 +123,63 @@ static int command_chargen(int argc, char **argv) c = '0'; else if (c == ('Z' + 1)) c = 'a'; - else if (c == ('9' + 1)) + else if (c == ('9' + 1)) c = 'A'; } putc_('\n'); - return EC_SUCCESS; + + release_console(); +} +DECLARE_DEFERRED(run_chargen); + +/* + * Generate a stream of characters on the UART (and USB) console. + * + * The stream is an ever incrementing pattern of characters from the following + * set: 0..9A..Za..z. + * + * The two optional integer command line arguments work as follows: + * + * argv[1] - reset the pattern after this many characters have been printed. + * Setting this value to the width of the terminal window results + * in a very regular stream showing on the terminal, where it is + * easy to observe disruptions. + * argv[2] - limit number of printed characters to this amount. If not + * specified - keep printing indefinitely. + * + * Hitting 'x' on the keyboard stops the generator. + */ +static int command_chargen(int argc, const char **argv) +{ + int wrap_value = 0; + uint32_t seq_number = 0; + + int (*putc_)(int c) = uart_putc; + int (*tx_is_blocked_)(void) = uart_buffer_full; + + if (argc > 1) + wrap_value = atoi(argv[1]); + + if (argc > 2) + seq_number = atoi(argv[2]); + +#if defined(CONFIG_USB_CONSOLE) || defined(CONFIG_USB_CONSOLE_STREAM) + if (argc > 3) { + if (memcmp(argv[3], "usb", 3)) + return EC_ERROR_PARAM3; + + putc_ = usb_putc; + tx_is_blocked_ = usb_console_tx_blocked; + } +#endif + + chargen_ctx.wrap_value = wrap_value; + chargen_ctx.seq_number = seq_number; + chargen_ctx.putc = putc_; + chargen_ctx.tx_is_blocked = tx_is_blocked_; + + return hook_call_deferred(&run_chargen_data, 0); } DECLARE_SAFE_CONSOLE_COMMAND(chargen, command_chargen, #if defined(CONFIG_USB_CONSOLE) || defined(CONFIG_USB_CONSOLE_STREAM) @@ -120,6 +189,5 @@ DECLARE_SAFE_CONSOLE_COMMAND(chargen, command_chargen, #endif "Generate a constant stream of characters on the " "UART console,\nrepeating every 'seq_length' " - "characters, up to 'num_chars' total." - ); -#endif /* !SECTION_IS_RO */ + "characters, up to 'num_chars' total."); +#endif /* !SECTION_IS_RO */ diff --git a/common/charger.c b/common/charger.c index 4037af9854..95eeb06467 100644 --- a/common/charger.c +++ b/common/charger.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,19 +6,20 @@ */ #include "battery_smart.h" -#include "charge_state_v2.h" +#include "builtin/assert.h" +#include "charge_state.h" #include "charger.h" #include "common.h" #include "console.h" #include "dptf.h" +#include "hooks.h" #include "host_command.h" #include "printf.h" #include "util.h" -#include "hooks.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_CHARGER, outstr) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) /* DPTF current limit, -1 = none */ static int dptf_limit_ma = -1; @@ -71,7 +72,7 @@ int charger_closest_voltage(int voltage) int charger_closest_current(int current) { - const struct charger_info * const info = charger_get_info(); + const struct charger_info *const info = charger_get_info(); /* Apply DPTF limit if necessary */ if (dptf_limit_ma >= 0 && current > dptf_limit_ma) @@ -96,8 +97,12 @@ void charger_get_params(struct charger_params *chg) { int chgnum = 0; - if (IS_ENABLED(CONFIG_OCPC)) + if (IS_ENABLED(CONFIG_OCPC)) { chgnum = charge_get_active_chg_chip(); + /* set to CHARGE_PORT_NONE when no charger connected */ + if (chgnum < 0) + chgnum = 0; + } memset(chg, 0, sizeof(*chg)); @@ -111,7 +116,7 @@ void charger_get_params(struct charger_params *chg) if (charger_get_voltage(chgnum, &chg->voltage)) chg->flags |= CHG_FLAG_BAD_VOLTAGE; - if (charger_get_input_current(chgnum, &chg->input_current)) + if (charger_get_input_current_limit(chgnum, &chg->input_current)) chg->flags |= CHG_FLAG_BAD_INPUT_CURRENT; if (charger_get_status(&chg->status)) @@ -146,7 +151,7 @@ void print_charger_debug(int chgnum) /* option */ print_item_name("Option:"); if (check_print_error(charger_get_option(&d))) - ccprintf("%pb (0x%04x)\n", BINARY_VALUE(d, 16), d); + ccprintf("(0x%04x)\n", d); /* manufacturer id */ print_item_name("Man id:"); @@ -158,33 +163,46 @@ void print_charger_debug(int chgnum) if (check_print_error(charger_device_id(&d))) ccprintf("0x%04x\n", d); + /* dptf current limit */ + print_item_name("I_dptf:"); + if (dptf_limit_ma >= 0) + ccprintf("%5d\n", dptf_limit_ma); + else + ccputs("disabled\n"); + + /* Limits */ + ccprintf("Limits\t\t\t ( min max step)\n"); + /* charge voltage limit */ - print_item_name("V_batt:"); + print_item_name("chg_voltage:"); if (check_print_error(charger_get_voltage(chgnum, &d))) - ccprintf("%5d (%4d - %5d, %3d)\n", d, info->voltage_min, + ccprintf("\t%5d mV (%4d - %5d, %3d)\n", d, info->voltage_min, info->voltage_max, info->voltage_step); /* charge current limit */ - print_item_name("I_batt:"); + print_item_name("chg_current:"); if (check_print_error(charger_get_current(chgnum, &d))) - ccprintf("%5d (%4d - %5d, %3d)\n", d, info->current_min, + ccprintf("\t%5d mA (%4d - %5d, %3d)\n", d, info->current_min, info->current_max, info->current_step); /* input current limit */ - print_item_name("I_in:"); - if (check_print_error(charger_get_input_current(chgnum, &d))) - ccprintf("%5d (%4d - %5d, %3d)\n", d, info->input_current_min, - info->input_current_max, info->input_current_step); + print_item_name("input_current:"); + if (check_print_error(charger_get_input_current_limit(chgnum, &d))) + ccprintf("\t%5d mA (%4d - %5d, %3d)\n", d, + info->input_current_min, info->input_current_max, + info->input_current_step); +} - /* dptf current limit */ - print_item_name("I_dptf:"); - if (dptf_limit_ma >= 0) - ccprintf("%5d\n", dptf_limit_ma); - else - ccputs("disabled\n"); +void print_charger_prochot(int chgnum) +{ + if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) + return; + + if (chg_chips[chgnum].drv->dump_prochot) + chg_chips[chgnum].drv->dump_prochot(chgnum); } -static int command_charger(int argc, char **argv) +static int command_charger(int argc, const char **argv) { int d; char *e; @@ -196,51 +214,74 @@ static int command_charger(int argc, char **argv) return EC_SUCCESS; } - idx_provided = isdigit(argv[1][0]); - if (idx_provided) + idx_provided = isdigit((unsigned char)argv[1][0]); + if (idx_provided) { chgnum = atoi(argv[1]); - else + if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) + return EC_ERROR_PARAM1; + } else { chgnum = 0; + } if ((argc == 2) && idx_provided) { print_charger_debug(chgnum); return EC_SUCCESS; } - if (strcasecmp(argv[1+idx_provided], "input") == 0) { - d = strtoi(argv[2+idx_provided], &e, 0); + if (strcasecmp(argv[1 + idx_provided], "input") == 0) { + d = strtoi(argv[2 + idx_provided], &e, 0); if (*e) - return EC_ERROR_PARAM2+idx_provided; - return charger_set_input_current(chgnum, d); - } else if (strcasecmp(argv[1+idx_provided], "current") == 0) { - d = strtoi(argv[2+idx_provided], &e, 0); + return EC_ERROR_PARAM2 + idx_provided; + return charger_set_input_current_limit(chgnum, d); + } else if (IS_ENABLED(CONFIG_BATTERY) && + strcasecmp(argv[1 + idx_provided], "current") == 0) { + d = strtoi(argv[2 + idx_provided], &e, 0); if (*e) - return EC_ERROR_PARAM2+idx_provided; + return EC_ERROR_PARAM2 + idx_provided; chgstate_set_manual_current(d); return charger_set_current(chgnum, d); - } else if (strcasecmp(argv[1+idx_provided], "voltage") == 0) { - d = strtoi(argv[2+idx_provided], &e, 0); + } else if (IS_ENABLED(CONFIG_BATTERY) && + strcasecmp(argv[1 + idx_provided], "voltage") == 0) { + d = strtoi(argv[2 + idx_provided], &e, 0); if (*e) - return EC_ERROR_PARAM2+idx_provided; + return EC_ERROR_PARAM2 + idx_provided; chgstate_set_manual_voltage(d); return charger_set_voltage(chgnum, d); - } else if (strcasecmp(argv[1+idx_provided], "dptf") == 0) { - d = strtoi(argv[2+idx_provided], &e, 0); + } else if (strcasecmp(argv[1 + idx_provided], "dptf") == 0) { + d = strtoi(argv[2 + idx_provided], &e, 0); if (*e) - return EC_ERROR_PARAM2+idx_provided; + return EC_ERROR_PARAM2 + idx_provided; dptf_limit_ma = d; return EC_SUCCESS; + } else if (strcasecmp(argv[1 + idx_provided], "dump") == 0) { + if (!IS_ENABLED(CONFIG_CMD_CHARGER_DUMP) || + !chg_chips[chgnum].drv->dump_registers) { + ccprintf("dump not supported\n"); + return EC_ERROR_PARAM1 + idx_provided; + } + ccprintf("Dump %s registers\n", + chg_chips[chgnum].drv->get_info(chgnum)->name); + chg_chips[chgnum].drv->dump_registers(chgnum); + return EC_SUCCESS; } else { - return EC_ERROR_PARAM1+idx_provided; + return EC_ERROR_PARAM1 + idx_provided; } } DECLARE_CONSOLE_COMMAND(charger, command_charger, - "[chgnum] [input | current | voltage | dptf] [newval]", - "Get or set charger param(s)"); + "[chgnum] [input | current | voltage | dptf] [newval]" +#ifdef CONFIG_CMD_CHARGER_DUMP + "\n\t[chgnum] dump" +#endif + , + "Get or set charger param(s)" +#ifdef CONFIG_CMD_CHARGER_DUMP + ". Dump registers." +#endif +); /* Driver wrapper functions */ - +#ifndef CONFIG_CHARGER_INIT_CUSTOM static void charger_chips_init(void) { int chip; @@ -250,109 +291,101 @@ static void charger_chips_init(void) chg_chips[chip].drv->init(chip); } } -DECLARE_HOOK(HOOK_INIT, charger_chips_init, HOOK_PRIO_INIT_I2C + 1); +DECLARE_HOOK(HOOK_INIT, charger_chips_init, HOOK_PRIO_POST_I2C); +#endif enum ec_error_list charger_post_init(void) { int chgnum = 0; - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->post_init) - rv = chg_chips[chgnum].drv->post_init(chgnum); + if (!chg_chips[chgnum].drv->post_init) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->post_init(chgnum); } const struct charger_info *charger_get_info(void) { int chgnum = 0; - const struct charger_info *ret = NULL; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return NULL; } - if (chg_chips[chgnum].drv->get_info) - ret = chg_chips[chgnum].drv->get_info(chgnum); + if (!chg_chips[chgnum].drv->get_info) + return NULL; - return ret; + return chg_chips[chgnum].drv->get_info(chgnum); } enum ec_error_list charger_get_status(int *status) { int chgnum = 0; - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->get_status) - rv = chg_chips[chgnum].drv->get_status(chgnum, status); + if (!chg_chips[chgnum].drv->get_status) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->get_status(chgnum, status); } enum ec_error_list charger_set_mode(int mode) { int chgnum = 0; - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->set_mode) - rv = chg_chips[chgnum].drv->set_mode(chgnum, mode); + if (!chg_chips[chgnum].drv->set_mode) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->set_mode(chgnum, mode); } enum ec_error_list charger_enable_otg_power(int chgnum, int enabled) { - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->enable_otg_power) - rv = chg_chips[chgnum].drv->enable_otg_power(chgnum, enabled); + if (!chg_chips[chgnum].drv->enable_otg_power) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->enable_otg_power(chgnum, enabled); } enum ec_error_list charger_set_otg_current_voltage(int chgnum, int output_current, int output_voltage) { - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->set_otg_current_voltage) - rv = chg_chips[chgnum].drv->set_otg_current_voltage(chgnum, - output_current, output_voltage); + if (!chg_chips[chgnum].drv->set_otg_current_voltage) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->set_otg_current_voltage( + chgnum, output_current, output_voltage); } int charger_is_sourcing_otg_power(int port) { int chgnum = 0; - int rv = 0; if (IS_ENABLED(CONFIG_OCPC)) chgnum = port; @@ -362,16 +395,31 @@ int charger_is_sourcing_otg_power(int port) return 0; } - if (chg_chips[chgnum].drv->is_sourcing_otg_power) - rv = chg_chips[chgnum].drv->is_sourcing_otg_power(chgnum, port); + if (!chg_chips[chgnum].drv->is_sourcing_otg_power) + return 0; - return rv; + return chg_chips[chgnum].drv->is_sourcing_otg_power(chgnum, port); } -enum ec_error_list charger_get_current(int chgnum, int *current) +enum ec_error_list charger_get_actual_current(int chgnum, int *current) { - int rv = EC_ERROR_UNIMPLEMENTED; + /* Note: chgnum may be -1 if no active port is selected */ + if (chgnum < 0) + return EC_ERROR_INVAL; + + if (chgnum >= board_get_charger_chip_count()) { + CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); + return EC_ERROR_INVAL; + } + + if (!chg_chips[chgnum].drv->get_actual_current) + return EC_ERROR_UNIMPLEMENTED; + + return chg_chips[chgnum].drv->get_actual_current(chgnum, current); +} +enum ec_error_list charger_get_current(int chgnum, int *current) +{ /* Note: chgnum may be -1 if no active port is selected */ if (chgnum < 0) return EC_ERROR_INVAL; @@ -381,31 +429,43 @@ enum ec_error_list charger_get_current(int chgnum, int *current) return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->get_current) - rv = chg_chips[chgnum].drv->get_current(chgnum, current); + if (!chg_chips[chgnum].drv->get_current) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->get_current(chgnum, current); } enum ec_error_list charger_set_current(int chgnum, int current) { - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->set_current) - rv = chg_chips[chgnum].drv->set_current(chgnum, current); + if (!chg_chips[chgnum].drv->set_current) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->set_current(chgnum, current); } -enum ec_error_list charger_get_voltage(int chgnum, int *voltage) +enum ec_error_list charger_get_actual_voltage(int chgnum, int *voltage) { - int rv = EC_ERROR_UNIMPLEMENTED; + if (chgnum < 0) + return EC_ERROR_INVAL; + + if (chgnum >= board_get_charger_chip_count()) { + CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); + return EC_ERROR_INVAL; + } + + if (!chg_chips[chgnum].drv->get_actual_voltage) + return EC_ERROR_UNIMPLEMENTED; + return chg_chips[chgnum].drv->get_actual_voltage(chgnum, voltage); +} + +enum ec_error_list charger_get_voltage(int chgnum, int *voltage) +{ if (chgnum < 0) return EC_ERROR_INVAL; @@ -414,25 +474,23 @@ enum ec_error_list charger_get_voltage(int chgnum, int *voltage) return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->get_voltage) - rv = chg_chips[chgnum].drv->get_voltage(chgnum, voltage); + if (!chg_chips[chgnum].drv->get_voltage) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->get_voltage(chgnum, voltage); } enum ec_error_list charger_set_voltage(int chgnum, int voltage) { - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->set_voltage) - rv = chg_chips[chgnum].drv->set_voltage(chgnum, voltage); + if (!chg_chips[chgnum].drv->set_voltage) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->set_voltage(chgnum, voltage); } enum ec_error_list charger_discharge_on_ac(int enable) @@ -440,6 +498,9 @@ enum ec_error_list charger_discharge_on_ac(int enable) int chgnum; int rv = EC_ERROR_UNIMPLEMENTED; + if (IS_ENABLED(CONFIG_CHARGER_DISCHARGE_ON_AC_CUSTOM)) + return board_discharge_on_ac(enable); + /* * When discharge on AC is selected, cycle through all chargers to * enable or disable this feature. @@ -453,10 +514,18 @@ enum ec_error_list charger_discharge_on_ac(int enable) return rv; } -enum ec_error_list charger_get_vbus_voltage(int port, int *voltage) +enum ec_error_list charger_enable_bypass_mode(int chgnum, bool enable) +{ + ASSERT(chgnum >= 0 && chgnum < board_get_charger_chip_count()); + + if (!chg_chips[chgnum].drv->enable_bypass_mode) + return EC_ERROR_UNIMPLEMENTED; + return chg_chips[chgnum].drv->enable_bypass_mode(chgnum, enable); +} + +static int charger_get_valid_chgnum(int port) { int chgnum = 0; - int rv = 0; /* Note: Assumes USBPD port == chgnum on multi-charger systems */ if (!IS_ENABLED(CONFIG_CHARGER_SINGLE_CHIP)) @@ -464,36 +533,78 @@ enum ec_error_list charger_get_vbus_voltage(int port, int *voltage) if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); - return 0; + return -1; } - if (chg_chips[chgnum].drv->get_vbus_voltage) - rv = chg_chips[chgnum].drv->get_vbus_voltage(chgnum, port, - voltage); + return chgnum; +} - return rv; +enum ec_error_list charger_get_vbus_voltage(int port, int *voltage) +{ + int chgnum = charger_get_valid_chgnum(port); + + if (chgnum < 0) + return EC_ERROR_INVAL; + + if (!chg_chips[chgnum].drv->get_vbus_voltage) + return EC_ERROR_UNIMPLEMENTED; + + return chg_chips[chgnum].drv->get_vbus_voltage(chgnum, port, voltage); } -enum ec_error_list charger_set_input_current(int chgnum, int input_current) +enum ec_error_list charger_get_vsys_voltage(int port, int *voltage) { - int rv = EC_ERROR_UNIMPLEMENTED; + int chgnum = charger_get_valid_chgnum(port); - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum < 0) + return EC_ERROR_INVAL; + + if (!chg_chips[chgnum].drv->get_vsys_voltage) + return EC_ERROR_UNIMPLEMENTED; + + return chg_chips[chgnum].drv->get_vsys_voltage(chgnum, port, voltage); +} + +enum ec_error_list charger_set_input_current_limit(int chgnum, + int input_current) +{ + /* Note: may be called with CHARGE_PORT_NONE regularly */ + if (chgnum < 0) + return EC_ERROR_INVAL; + + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->set_input_current) - rv = chg_chips[chgnum].drv->set_input_current(chgnum, + if (!chg_chips[chgnum].drv->set_input_current_limit) + return EC_ERROR_UNIMPLEMENTED; + + return chg_chips[chgnum].drv->set_input_current_limit(chgnum, input_current); +} - return rv; +enum ec_error_list charger_get_input_current_limit(int chgnum, + int *input_current) +{ + /* Note: may be called with CHARGE_PORT_NONE regularly */ + if (chgnum < 0) + return EC_ERROR_INVAL; + + if (chgnum >= board_get_charger_chip_count()) { + CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); + return EC_ERROR_INVAL; + } + + if (!chg_chips[chgnum].drv->get_input_current_limit) + return EC_ERROR_UNIMPLEMENTED; + + return chg_chips[chgnum].drv->get_input_current_limit(chgnum, + input_current); } enum ec_error_list charger_get_input_current(int chgnum, int *input_current) { - int rv = EC_ERROR_UNIMPLEMENTED; - if (chgnum < 0) return EC_ERROR_INVAL; @@ -502,89 +613,110 @@ enum ec_error_list charger_get_input_current(int chgnum, int *input_current) return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->get_input_current) - rv = chg_chips[chgnum].drv->get_input_current(chgnum, - input_current); + if (!chg_chips[chgnum].drv->get_input_current) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->get_input_current(chgnum, input_current); } enum ec_error_list charger_manufacturer_id(int *id) { int chgnum = 0; - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->manufacturer_id) - rv = chg_chips[chgnum].drv->manufacturer_id(chgnum, id); + if (!chg_chips[chgnum].drv->manufacturer_id) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->manufacturer_id(chgnum, id); } enum ec_error_list charger_device_id(int *id) { int chgnum = 0; - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->device_id) - rv = chg_chips[chgnum].drv->device_id(chgnum, id); + if (!chg_chips[chgnum].drv->device_id) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->device_id(chgnum, id); } -enum ec_error_list charger_get_option(int *option) +enum ec_error_list charger_set_frequency(int freq_khz) { int chgnum = 0; - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->get_option) - rv = chg_chips[chgnum].drv->get_option(chgnum, option); + if (!chg_chips[chgnum].drv->set_frequency) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->set_frequency(chgnum, freq_khz); } -enum ec_error_list charger_set_option(int option) +enum ec_error_list charger_get_option(int *option) { int chgnum = 0; - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->set_option) - rv = chg_chips[chgnum].drv->set_option(chgnum, option); + if (!chg_chips[chgnum].drv->get_option) + return EC_ERROR_UNIMPLEMENTED; - return rv; + return chg_chips[chgnum].drv->get_option(chgnum, option); } -enum ec_error_list charger_set_hw_ramp(int enable) +enum ec_error_list charger_set_option(int option) { int chgnum = 0; - int rv = EC_ERROR_UNIMPLEMENTED; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->set_hw_ramp) - rv = chg_chips[chgnum].drv->set_hw_ramp(chgnum, enable); + if (!chg_chips[chgnum].drv->set_option) + return EC_ERROR_UNIMPLEMENTED; + + return chg_chips[chgnum].drv->set_option(chgnum, option); +} + +enum ec_error_list charger_set_hw_ramp(int enable) +{ + int chgnum; + int rv = EC_ERROR_UNIMPLEMENTED; + + for (chgnum = 0; chgnum < board_get_charger_chip_count(); chgnum++) { + /* Check if the chg chip supports set_hw_ramp. */ + if (chg_chips[chgnum].drv->set_hw_ramp) { + if (enable) { + /* Check if this is the active chg chip. */ + if (chgnum == charge_get_active_chg_chip()) + rv = chg_chips[chgnum].drv->set_hw_ramp( + chgnum, 1); + /* This is not the active chg chip, disable + * hw_ramp. */ + else + rv = chg_chips[chgnum].drv->set_hw_ramp( + chgnum, 0); + } else + rv = chg_chips[chgnum].drv->set_hw_ramp(chgnum, + 0); + } + } return rv; } @@ -593,71 +725,110 @@ enum ec_error_list charger_set_hw_ramp(int enable) int chg_ramp_is_stable(void) { int chgnum = 0; - int rv = 0; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return 0; } - if (chg_chips[chgnum].drv->ramp_is_stable) - rv = chg_chips[chgnum].drv->ramp_is_stable(chgnum); + if (!chg_chips[chgnum].drv->ramp_is_stable) + return 0; - return rv; + return chg_chips[chgnum].drv->ramp_is_stable(chgnum); } int chg_ramp_is_detected(void) { int chgnum = 0; - int rv = 0; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return 0; } - if (chg_chips[chgnum].drv->ramp_is_detected) - rv = chg_chips[chgnum].drv->ramp_is_detected(chgnum); + if (!chg_chips[chgnum].drv->ramp_is_detected) + return 0; - return rv; + return chg_chips[chgnum].drv->ramp_is_detected(chgnum); } int chg_ramp_get_current_limit(void) { int chgnum = 0; - int rv = 0; - if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + if (chgnum >= board_get_charger_chip_count()) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return 0; } - if (chg_chips[chgnum].drv->ramp_get_current_limit) - rv = chg_chips[chgnum].drv->ramp_get_current_limit(chgnum); + if (!chg_chips[chgnum].drv->ramp_get_current_limit) + return 0; - return rv; + return chg_chips[chgnum].drv->ramp_get_current_limit(chgnum); } #endif -enum ec_error_list charger_set_vsys_compensation(int chgnum, - struct ocpc_data *ocpc, - int current_ma, - int voltage_mv) +test_mockable enum ec_error_list +charger_set_vsys_compensation(int chgnum, struct ocpc_data *ocpc, + int current_ma, int voltage_mv) { if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); return EC_ERROR_INVAL; } - if (chg_chips[chgnum].drv->set_vsys_compensation) - return chg_chips[chgnum].drv->set_vsys_compensation(chgnum, - ocpc, - current_ma, - voltage_mv); - /* * This shouldn't happen as this should only be called on chargers * that support this. */ + if (!chg_chips[chgnum].drv->set_vsys_compensation) + return EC_ERROR_UNIMPLEMENTED; + + return chg_chips[chgnum].drv->set_vsys_compensation( + chgnum, ocpc, current_ma, voltage_mv); +} + +enum ec_error_list charger_is_icl_reached(int chgnum, bool *reached) +{ + if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); + return EC_ERROR_INVAL; + } + + if (chg_chips[chgnum].drv->is_icl_reached) + return chg_chips[chgnum].drv->is_icl_reached(chgnum, reached); + + return EC_ERROR_UNIMPLEMENTED; +} + +enum ec_error_list charger_enable_linear_charge(int chgnum, bool enable) +{ + if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) { + CPRINTS("%s(%d) Invalid charger!", __func__, chgnum); + return EC_ERROR_INVAL; + } + + if (chg_chips[chgnum].drv->enable_linear_charge) + return chg_chips[chgnum].drv->enable_linear_charge(chgnum, + enable); + + return EC_ERROR_UNIMPLEMENTED; +} + +#ifdef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON +inline int charger_get_min_bat_pct_for_power_on(void) +{ + return CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON; +} +#endif + +enum ec_error_list charger_get_battery_cells(int chgnum, int *cells) +{ + if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) + return EC_ERROR_INVAL; + + if (chg_chips[chgnum].drv->get_battery_cells) + return chg_chips[chgnum].drv->get_battery_cells(chgnum, cells); + return EC_ERROR_UNIMPLEMENTED; } diff --git a/common/charger_base.c b/common/charger_base.c new file mode 100644 index 0000000000..c2f49dcf21 --- /dev/null +++ b/common/charger_base.c @@ -0,0 +1,687 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery charging task and state machine. + */ + +#include "charge_state.h" +#include "charger.h" +#include "charger_base.h" +#include "common.h" +#include "console.h" +#include "ec_ec_comm_client.h" +#include "hooks.h" +#include "string.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_CHARGER, outstr) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) + +/* Base has responded to one of our commands already. */ +static int base_responsive; +static int charge_base; +static int prev_charge_base; +static int prev_current_base; +static int prev_allow_charge_base; +static int prev_current_lid; + +/* + * In debugging mode, with AC, input current to allocate to base. Negative + * value disables manual mode. + */ +static int manual_ac_current_base = -1; +/* + * In debugging mode, when discharging, current to transfer from lid to base + * (negative to transfer from base to lid). Only valid when enabled is true. + */ +static int manual_noac_enabled; +static int manual_noac_current_base; + +/* + * Parameters for dual-battery policy. + * TODO(b:71881017): This should be made configurable by AP in the future. + */ +struct dual_battery_policy { + /*** Policies when AC is not connected. ***/ + /* Voltage to use when using OTG mode between lid and base (mV) */ + uint16_t otg_voltage; + /* Maximum current to apply from base to lid (mA) */ + uint16_t max_base_to_lid_current; + /* + * Margin to apply between provided OTG output current and input current + * limit, to make sure that input charger does not overcurrent output + * charger. input_current = (1-margin) * output_current. (/128) + */ + uint8_t margin_otg_current; + + /* Only do base to lid OTG when base battery above this value (%) */ + uint8_t min_charge_base_otg; + + /* + * When base/lid battery percentage is below this value, do + * battery-to-battery charging. (%) + */ + uint8_t max_charge_base_batt_to_batt; + uint8_t max_charge_lid_batt_to_batt; + + /*** Policies when AC is connected. ***/ + /* Minimum power to allocate to base (mW), includes some margin to allow + * base to charge when critically low. + */ + uint16_t min_base_system_power; + + /* Smoothing factor for lid power (/128) */ + uint8_t lid_system_power_smooth; + /* + * Smoothing factor for base/lid battery power, when the battery power + * is decreasing only: we try to estimate the maximum power that the + * battery is willing to take and always reset it when it draws more + * than the estimate. (/128) + */ + uint8_t battery_power_smooth; + + /* + * Margin to add to requested base/lid battery power, to figure out how + * much current to allocate. allocation = (1+margin) * request. (/128) + */ + uint8_t margin_base_battery_power; + uint8_t margin_lid_battery_power; + + /* Maximum current to apply from lid to base (mA) */ + uint16_t max_lid_to_base_current; +}; + +static const struct dual_battery_policy db_policy = { + .otg_voltage = 12000, /* mV */ + .max_base_to_lid_current = 1800, /* mA, about 2000mA with margin. */ + .margin_otg_current = 13, /* /128 = 10.1% */ + .min_charge_base_otg = 5, /* % */ + .max_charge_base_batt_to_batt = 4, /* % */ + .max_charge_lid_batt_to_batt = 10, /* % */ + .min_base_system_power = 1300, /* mW */ + .lid_system_power_smooth = 32, /* 32/128 = 0.25 */ + .battery_power_smooth = 1, /* 1/128 = 0.008 */ + .margin_base_battery_power = 32, /* 32/128 = 0.25 */ + .margin_lid_battery_power = 32, /* 32/128 = 0.25 */ + .max_lid_to_base_current = 2000, /* mA */ +}; + +/* Add at most "value" to power_var, subtracting from total_power budget. */ +#define CHG_ALLOCATE(power_var, total_power, value) \ + do { \ + int val_capped = MIN(value, total_power); \ + (power_var) += val_capped; \ + (total_power) -= val_capped; \ + } while (0) + +/* Check if a base is connected */ +bool base_connected(void) +{ + return board_is_base_connected(); +} + +/** + * Setup current settings for base, and record previous values, if the base + * is responsive. + * + * @param current_base Current to be drawn by base (negative to provide power) + * @param allow_charge_base Whether base battery should be charged (only makes + * sense with positive current) + */ +static int set_base_current(int current_base, int allow_charge_base) +{ + /* "OTG" voltage from base to lid. */ + const int otg_voltage = db_policy.otg_voltage; + int ret; + + ret = ec_ec_client_base_charge_control(current_base, otg_voltage, + allow_charge_base); + if (ret) { + /* Ignore errors until the base is responsive. */ + if (base_responsive) + return ret; + } else { + base_responsive = 1; + prev_current_base = current_base; + prev_allow_charge_base = allow_charge_base; + } + + return EC_RES_SUCCESS; +} + +/** + * Setup current settings for lid and base, in a safe way. + * + * @param current_base Current to be drawn by base (negative to provide power) + * @param allow_charge_base Whether base battery should be charged (only makes + * sense with positive current) + * @param current_lid Current to be drawn by lid (negative to provide power) + * @param allow_charge_lid Whether lid battery should be charged + * @param is_full Whether the lid battery is full + */ +static void set_base_lid_current(int current_base, int allow_charge_base, + int current_lid, int allow_charge_lid, + bool is_full) +{ + /* "OTG" voltage from lid to base. */ + const int otg_voltage = db_policy.otg_voltage; + + int lid_first; + int ret; + int chgnum = 0; + + /* TODO(b:71881017): This is still quite verbose during charging. */ + if (prev_current_base != current_base || + prev_allow_charge_base != allow_charge_base || + prev_current_lid != current_lid) { + CPRINTS("Base/Lid: %d%s/%d%s mA", current_base, + allow_charge_base ? "+" : "", current_lid, + allow_charge_lid ? "+" : ""); + } + + /* + * To decide whether to first control the lid or the base, we first + * control the side that _reduces_ current that would be drawn, then + * setup one that would start providing power, then increase current. + */ + if (current_lid >= 0 && current_lid < prev_current_lid) + lid_first = 1; /* Lid decreases current */ + else if (current_base >= 0 && current_base < prev_current_base) + lid_first = 0; /* Base decreases current */ + else if (current_lid < 0) + lid_first = 1; /* Lid provide power */ + else + lid_first = 0; /* All other cases: control the base first */ + + if (!lid_first && base_connected()) { + ret = set_base_current(current_base, allow_charge_base); + if (ret) + return; + } + + if (current_lid >= 0) { + ret = charge_set_output_current_limit(CHARGER_SOLO, 0, 0); + if (ret) + return; + ret = charger_set_input_current_limit(chgnum, current_lid); + if (ret) + return; + ret = charge_request(allow_charge_lid, is_full); + } else { + ret = charge_set_output_current_limit( + CHARGER_SOLO, -current_lid, otg_voltage); + } + + if (ret) + return; + + prev_current_lid = current_lid; + + if (lid_first && base_connected()) { + ret = set_base_current(current_base, allow_charge_base); + if (ret) + return; + } + + /* + * Make sure cross-power is enabled (it might not be enabled right after + * plugging the base, or when an adapter just got connected). + */ + if (base_connected() && current_base != 0) + board_enable_base_power(1); +} + +/** + * Smooth power value, covering some edge cases. + * Compute s*curr+(1-s)*prev, where s is in 1/128 unit. + */ +static int smooth_value(int prev, int curr, int s) +{ + if (curr < 0) + curr = 0; + if (prev < 0) + return curr; + + return prev + s * (curr - prev) / 128; +} + +/** + * Add margin m to value. Compute (1+m)*value, where m is in 1/128 unit. + */ +static int add_margin(int value, int m) +{ + return value + m * value / 128; +} + +void base_charge_allocate_input_current_limit( + const struct charge_state_data *curr, bool is_full, bool debugging) +{ + /* + * All the power numbers are in mW. + * + * Since we work with current and voltage in mA and mV, multiplying them + * gives numbers in uW, which are dangerously close to overflowing when + * doing intermediate computations (60W * 100 overflows a 32-bit int, + * for example). We therefore divide the product by 1000 and re-multiply + * the power numbers by 1000 when converting them back to current. + */ + int total_power = 0; + + static int prev_base_battery_power = -1; + int base_battery_power = 0; + int base_battery_power_max = 0; + + static int prev_lid_system_power = -1; + int lid_system_power; + + static int prev_lid_battery_power = -1; + int lid_battery_power = 0; + int lid_battery_power_max = 0; + + int power_base = 0; + int power_lid = 0; + + int current_base = 0; + int current_lid = 0; + + int charge_lid = charge_get_percent(); + + const struct ec_response_battery_dynamic_info *const base_bd = + &battery_dynamic[BATT_IDX_BASE]; + const struct batt_params *batt = &curr->batt; + + if (!base_connected()) { + set_base_lid_current(0, 0, curr->desired_input_current, 1, + is_full); + prev_base_battery_power = -1; + return; + } + + /* Charging */ + if (curr->desired_input_current > 0 && curr->input_voltage > 0) + total_power = curr->desired_input_current * + curr->input_voltage / 1000; + + /* + * TODO(b:71723024): We should be able to replace this test by curr.ac, + * but the value is currently wrong, especially during transitions. + */ + if (total_power <= 0) { + int base_critical = + charge_base >= 0 && + charge_base < db_policy.max_charge_base_batt_to_batt; + + /* Discharging */ + prev_base_battery_power = -1; + prev_lid_system_power = -1; + prev_lid_battery_power = -1; + + /* Manual control */ + if (manual_noac_enabled) { + int lid_current, base_current; + + if (manual_noac_current_base > 0) { + base_current = -manual_noac_current_base; + lid_current = add_margin( + manual_noac_current_base, + db_policy.margin_otg_current); + } else { + lid_current = manual_noac_current_base; + base_current = add_margin( + -manual_noac_current_base, + db_policy.margin_otg_current); + } + + set_base_lid_current(base_current, 0, lid_current, 0, + is_full); + return; + } + + /* + * System is off, cut power to the base. We'll reset the base + * when system restarts, or when AC is plugged. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + set_base_lid_current(0, 0, 0, 0, is_full); + if (base_responsive) { + /* Base still responsive, put it to sleep. */ + CPRINTF("Hibernating base\n"); + ec_ec_client_hibernate(); + base_responsive = 0; + board_enable_base_power(0); + } + return; + } + + /* + * System is suspended, let the lid and base run on their + * own power. However, if the base battery is critically low, we + * still want to provide power to the base, to make sure it + * stays alive to be able to wake the system on keyboard or + * touchpad events. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + !base_critical) { + set_base_lid_current(0, 0, 0, 0, is_full); + return; + } + + if (charge_base > db_policy.min_charge_base_otg) { + int lid_current = db_policy.max_base_to_lid_current; + int base_current = add_margin( + lid_current, db_policy.margin_otg_current); + /* Draw current from base to lid */ + set_base_lid_current( + -base_current, 0, lid_current, + charge_lid < + db_policy.max_charge_lid_batt_to_batt, + is_full); + } else { + /* + * Base battery is too low, apply power to it, and allow + * it to charge if it is critically low. + * + * TODO(b:71881017): When suspended, this will make the + * battery charge oscillate between 3 and 4 percent, + * which might not be great for battery life. We need + * some hysteresis. + */ + /* + * TODO(b:71881017): Precompute (ideally, at build time) + * the base_current, so we do not need to do a division + * here. + */ + int base_current = + (db_policy.min_base_system_power * 1000) / + db_policy.otg_voltage; + int lid_current = add_margin( + base_current, db_policy.margin_otg_current); + + set_base_lid_current(base_current, base_critical, + -lid_current, 0, is_full); + } + + return; + } + + /* Manual control */ + if (manual_ac_current_base >= 0) { + int current_base = manual_ac_current_base; + int current_lid = + curr->desired_input_current - manual_ac_current_base; + + if (current_lid < 0) { + current_base = curr->desired_input_current; + current_lid = 0; + } + + set_base_lid_current(current_base, 1, current_lid, 1, is_full); + return; + } + + /* Estimate system power. */ + lid_system_power = charger_get_system_power() / 1000; + + /* Smooth system power, as it is very spiky */ + lid_system_power = smooth_value(prev_lid_system_power, lid_system_power, + db_policy.lid_system_power_smooth); + prev_lid_system_power = lid_system_power; + + /* + * TODO(b:71881017): Smoothing the battery power isn't necessarily a + * good idea: if the system takes up too much power, we may reduce the + * estimate power too quickly, leading to oscillations when the system + * power goes down. Instead, we should probably estimate the current + * based on remaining capacity. + */ + /* Estimate lid battery power. */ + if (!(batt->flags & (BATT_FLAG_BAD_VOLTAGE | BATT_FLAG_BAD_CURRENT))) + lid_battery_power = batt->current * batt->voltage / 1000; + if (lid_battery_power < prev_lid_battery_power) + lid_battery_power = + smooth_value(prev_lid_battery_power, lid_battery_power, + db_policy.battery_power_smooth); + if (!(batt->flags & + (BATT_FLAG_BAD_DESIRED_VOLTAGE | BATT_FLAG_BAD_DESIRED_CURRENT))) + lid_battery_power_max = + batt->desired_current * batt->desired_voltage / 1000; + + lid_battery_power = MIN(lid_battery_power, lid_battery_power_max); + + /* Estimate base battery power. */ + if (!(base_bd->flags & EC_BATT_FLAG_INVALID_DATA)) { + base_battery_power = base_bd->actual_current * + base_bd->actual_voltage / 1000; + base_battery_power_max = base_bd->desired_current * + base_bd->desired_voltage / 1000; + } + if (base_battery_power < prev_base_battery_power) + base_battery_power = smooth_value( + prev_base_battery_power, base_battery_power, + db_policy.battery_power_smooth); + base_battery_power = MIN(base_battery_power, base_battery_power_max); + + if (debugging) { + CPRINTF("%s:\n", __func__); + CPRINTF("total power: %d\n", total_power); + CPRINTF("base battery power: %d (%d)\n", base_battery_power, + base_battery_power_max); + CPRINTF("lid system power: %d\n", lid_system_power); + CPRINTF("lid battery power: %d\n", lid_battery_power); + CPRINTF("percent base/lid: %d%% %d%%\n", charge_base, + charge_lid); + } + + prev_lid_battery_power = lid_battery_power; + prev_base_battery_power = base_battery_power; + + if (total_power > 0) { /* Charging */ + /* Allocate system power */ + CHG_ALLOCATE(power_base, total_power, + db_policy.min_base_system_power); + CHG_ALLOCATE(power_lid, total_power, lid_system_power); + + /* Allocate lid, then base battery power */ + lid_battery_power = add_margin( + lid_battery_power, db_policy.margin_lid_battery_power); + CHG_ALLOCATE(power_lid, total_power, lid_battery_power); + + base_battery_power = + add_margin(base_battery_power, + db_policy.margin_base_battery_power); + CHG_ALLOCATE(power_base, total_power, base_battery_power); + + /* Give everything else to the lid. */ + CHG_ALLOCATE(power_lid, total_power, total_power); + if (debugging) + CPRINTF("power: base %d mW / lid %d mW\n", power_base, + power_lid); + + current_base = 1000 * power_base / curr->input_voltage; + current_lid = 1000 * power_lid / curr->input_voltage; + + if (current_base > db_policy.max_lid_to_base_current) { + current_lid += (current_base - + db_policy.max_lid_to_base_current); + current_base = db_policy.max_lid_to_base_current; + } + + if (debugging) + CPRINTF("current: base %d mA / lid %d mA\n", + current_base, current_lid); + + set_base_lid_current(current_base, 1, current_lid, 1, is_full); + } else { /* Discharging */ + } + + if (debugging) + CPRINTF("====\n"); +} + +void base_update_battery_info(void) +{ + struct ec_response_battery_dynamic_info *const bd = + &battery_dynamic[BATT_IDX_BASE]; + + if (!base_connected()) { + const int invalid_flags = EC_BATT_FLAG_INVALID_DATA; + /* Invalidate static/dynamic information */ + if (bd->flags != invalid_flags) { + bd->flags = invalid_flags; + + host_set_single_event(EC_HOST_EVENT_BATTERY); + host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS); + } + charge_base = -1; + base_responsive = 0; + prev_current_base = 0; + prev_allow_charge_base = 0; + } else if (base_responsive) { + int old_flags = bd->flags; + int flags_changed; + int old_full_capacity = bd->full_capacity; + + ec_ec_client_base_get_dynamic_info(); + flags_changed = (old_flags != bd->flags); + /* Fetch static information when flags change. */ + if (flags_changed) + ec_ec_client_base_get_static_info(); + + battery_memmap_refresh(BATT_IDX_BASE); + + /* Newly connected battery, or change in capacity. */ + if (old_flags & EC_BATT_FLAG_INVALID_DATA || + ((old_flags & EC_BATT_FLAG_BATT_PRESENT) != + (bd->flags & EC_BATT_FLAG_BATT_PRESENT)) || + old_full_capacity != bd->full_capacity) + host_set_single_event(EC_HOST_EVENT_BATTERY); + + if (flags_changed) + host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS); + + /* Update charge_base */ + if (bd->flags & (BATT_FLAG_BAD_FULL_CAPACITY | + BATT_FLAG_BAD_REMAINING_CAPACITY)) + charge_base = -1; + else if (bd->full_capacity > 0) + charge_base = 100 * bd->remaining_capacity / + bd->full_capacity; + else + charge_base = 0; + } +} + +bool base_check_extpower(int ac, int prev_ac) +{ + bool zero_ac = false; + + /* + * When base is powering the system, make sure ac stays 0. + * TODO(b:71723024): Fix extpower_is_present() in hardware instead. + */ + if (base_responsive && prev_current_base < 0) { + ac = 0; + zero_ac = true; + } + + /* System is off: if AC gets connected, reset the base. */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && !prev_ac && ac) + board_base_reset(); + + return zero_ac; +} + +static int command_chgdualdebug(int argc, const char **argv) +{ + int val; + char *e; + + if (argc > 1) { + if (argv[1][0] == 'c') { + if (argc <= 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[2], "auto")) { + val = -1; + } else { + val = strtoi(argv[2], &e, 0); + if (*e || val < 0) + return EC_ERROR_PARAM2; + } + + manual_ac_current_base = val; + charge_wakeup(); + } else if (argv[1][0] == 'd') { + if (argc <= 2) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[2], "auto")) { + manual_noac_enabled = 0; + } else { + val = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + manual_noac_current_base = val; + manual_noac_enabled = 1; + } + charge_wakeup(); + } else { + return EC_ERROR_PARAM1; + } + } else { + ccprintf("Base/Lid: %d%s/%d mA\n", prev_current_base, + prev_allow_charge_base ? "+" : "", prev_current_lid); + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(chgdualdebug, command_chgdualdebug, + "[charge (auto|)|discharge (auto|)]", + "Manually control dual-battery charging algorithm."); + +void charger_base_setup(void) +{ + base_responsive = 0; + charge_base = -1; + battery_dynamic[BATT_IDX_BASE].flags = EC_BATT_FLAG_INVALID_DATA; +} + +bool charger_base_charge_changed(void) +{ + return charge_base != prev_charge_base; +} + +void charger_base_charge_update(void) +{ + prev_charge_base = charge_base; +} + +void charger_base_show_charge(void) +{ + CPRINTS("Base battery %d%%", charge_base); +} + +bool charger_base_charge_near_full(void) +{ + if (charge_base > -1 && charge_base < CONFIG_BATT_HOST_FULL_FACTOR) + return false; + + return true; +} + +int charger_base_get_input_voltage(const struct charge_state_data *curr) +{ + return curr->input_voltage; +} + +void charger_base_set_input_voltage(struct charge_state_data *curr, + int input_voltage) +{ + curr->input_voltage = input_voltage; +} + +/* Reset the base on S5->S0 transition. */ +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_base_reset, HOOK_PRIO_DEFAULT); diff --git a/common/charger_profile_override.c b/common/charger_profile_override.c index 2b691b9a5a..00aaa2b5bd 100644 --- a/common/charger_profile_override.c +++ b/common/charger_profile_override.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -20,17 +20,17 @@ static int test_vtg_mV = -1; static int fast_charging_allowed = 1; -int charger_profile_override_common(struct charge_state_data *curr, - const struct fast_charge_params *fast_chg_params, - const struct fast_charge_profile **prev_chg_prof_info, - int batt_vtg_max) +int charger_profile_override_common( + struct charge_state_data *curr, + const struct fast_charge_params *fast_chg_params, + const struct fast_charge_profile **prev_chg_prof_info, int batt_vtg_max) { int i, voltage_range; /* temp in 0.1 deg C */ int temp_c = curr->batt.temperature - 2731; int temp_ranges = fast_chg_params->total_temp_ranges; const struct fast_charge_profile *chg_profile_info = - fast_chg_params->chg_profile_info; + fast_chg_params->chg_profile_info; #ifdef CONFIG_CMD_CHARGER_PROFILE_OVERRIDE_TEST if (fast_charge_test_on && test_vtg_mV != -1) { @@ -78,9 +78,9 @@ int charger_profile_override_common(struct charge_state_data *curr, if (!(curr->batt.flags & BATT_FLAG_BAD_VOLTAGE)) { for (i = 0; i < CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES - 1; - i++) { + i++) { if (curr->batt.voltage < - fast_chg_params->voltage_mV[i]) { + fast_chg_params->voltage_mV[i]) { voltage_range = i; break; } @@ -98,13 +98,13 @@ int charger_profile_override_common(struct charge_state_data *curr, * Okay, impose our custom will: */ curr->requested_current = - (*prev_chg_prof_info)->current_mA[voltage_range]; + (*prev_chg_prof_info)->current_mA[voltage_range]; curr->requested_voltage = curr->requested_current ? batt_vtg_max : 0; #ifdef CONFIG_CMD_CHARGER_PROFILE_OVERRIDE_TEST if (fast_charge_test_on) ccprintf("Fast charge profile i=%dmA, v=%dmV\n", - curr->requested_current, curr->requested_voltage); + curr->requested_current, curr->requested_voltage); #endif return 0; @@ -134,7 +134,7 @@ enum ec_status charger_profile_override_set_param(uint32_t param, } #ifdef CONFIG_CMD_CHARGER_PROFILE_OVERRIDE -static int command_fastcharge(int argc, char **argv) +static int command_fastcharge(int argc, const char **argv) { if (argc > 1 && !parse_bool(argv[1], &fast_charging_allowed)) return EC_ERROR_PARAM1; @@ -143,8 +143,7 @@ static int command_fastcharge(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(fastcharge, command_fastcharge, - "[on|off]", +DECLARE_CONSOLE_COMMAND(fastcharge, command_fastcharge, "[on|off]", "Get or set fast charging profile"); #endif @@ -153,7 +152,7 @@ DECLARE_CONSOLE_COMMAND(fastcharge, command_fastcharge, * fast charging profile is selected. */ #ifdef CONFIG_CMD_CHARGER_PROFILE_OVERRIDE_TEST -static int command_fastcharge_test(int argc, char **argv) +static int command_fastcharge_test(int argc, const char **argv) { char *e; int test_on; diff --git a/common/chargesplash.c b/common/chargesplash.c new file mode 100644 index 0000000000..1c5187af76 --- /dev/null +++ b/common/chargesplash.c @@ -0,0 +1,261 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "extpower.h" +#include "hooks.h" +#include "host_command.h" +#include "lid_switch.h" +#include "power_button.h" +#include "timer.h" +#include "util.h" + +#include +#include + +#define CPRINTS(format, args...) \ + cprints(CC_USBCHARGE, "chargesplash: " format, ##args) + +/* + * Was this power on initiated to show a charge splash? + * + * - Set when powering on for an AC connect. + * - Unset when power button is pushed, or the chargesplash request is + * cancelled due to AC disconnection. + */ +static bool power_on_for_chargesplash; + +/* True once the display has come up */ +static bool display_initialized; + +/* + * True if the chargesplash is locked out, and we must wait until no + * requests happen during the chargesplash period until the lockout can + * be cleared. + * + * A charger can be locked out if it's too flaky, causing the charging status + * to bounce between enabled/disabled too many times within a specified + * time period. + */ +static bool locked_out; + +/* + * A circular buffer of the most recent chargesplash request + * timestamps (stored as an integer value of seconds). + */ +static int request_log[CONFIG_CHARGESPLASH_MAX_REQUESTS_PER_PERIOD]; +BUILD_ASSERT(CONFIG_CHARGESPLASH_MAX_REQUESTS_PER_PERIOD >= 1, + "There must be at least one request allowed per period"); + +/* + * Return true if the timestamp is outside of the tracking period, + * false otherwise. + */ +static bool timestamp_is_expired(int timestamp, int now) +{ + if (!timestamp) { + /* The log entry hasn't been filled yet */ + return true; + } + + return (now - timestamp) >= CONFIG_CHARGESPLASH_PERIOD; +} + +/* + * Returns true only if all timestamps have been expired, or we aren't + * locked out anyway. + */ +static bool lockout_can_be_cleared(int now) +{ + if (!locked_out) + return true; + + for (int i = 0; i < ARRAY_SIZE(request_log); i++) { + if (!timestamp_is_expired(request_log[i], now)) { + return false; + } + } + + return true; +} + +/* + * Write the current time into the request log. If the request should + * be permitted to cause a boot, return true. Otherwise, if the + * chargesplash should be inhibited, return false. + */ +static bool log_request(void) +{ + static int log_ptr; + int now = get_time().val / SECOND; + bool inhibit_boot = false; + + if (lockout_can_be_cleared(now)) { + locked_out = false; + } else { + inhibit_boot = true; + } + + if (!timestamp_is_expired(request_log[log_ptr], now)) { + locked_out = true; + inhibit_boot = true; + } + + request_log[log_ptr] = now; + log_ptr = (log_ptr + 1) % ARRAY_SIZE(request_log); + return !inhibit_boot; +} + +/* Manually reset state (via host or UART cmd) */ +static void reset_state(void) +{ + power_on_for_chargesplash = false; + display_initialized = false; + locked_out = false; + memset(request_log, 0, sizeof(request_log)); +} + +static void request_chargesplash(void) +{ + if (!log_request()) { + CPRINTS("Locked out, request inhibited"); + return; + } + + CPRINTS("Power on for charge display"); + power_on_for_chargesplash = true; + display_initialized = false; + chipset_power_on(); +} + +static void display_ready(void) +{ + /* + * TODO(b/228370390): Consider asserting PROCHOT (on + * some platforms) to slow down background boot. + */ + + CPRINTS("Display initialized"); + display_initialized = true; +} + +static void handle_ac_change(void) +{ + if (extpower_is_present() && !power_on_for_chargesplash) { + if (!lid_is_open()) { + CPRINTS("Ignore AC connect as lid is closed"); + return; + } + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + request_chargesplash(); + } + } +} +DECLARE_HOOK(HOOK_AC_CHANGE, handle_ac_change, HOOK_PRIO_LAST - 1); + +static void handle_power_button_change(void) +{ + if (power_button_is_pressed()) { + reset_state(); + } +} +DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, handle_power_button_change, + HOOK_PRIO_FIRST); + +static void handle_chipset_shutdown(void) +{ + power_on_for_chargesplash = false; + display_initialized = false; +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, handle_chipset_shutdown, HOOK_PRIO_DEFAULT); + +static int command_chargesplash(int argc, const char **argv) +{ + if (argc != 2) { + return EC_ERROR_PARAM_COUNT; + } + + if (!strcasecmp(argv[1], "state")) { + ccprintf("requested = %d\n", power_on_for_chargesplash); + ccprintf("display_initialized = %d\n", display_initialized); + ccprintf("locked_out = %d\n", locked_out); + + ccprintf("\nRequest log (raw data):\n"); + for (int i = 0; i < ARRAY_SIZE(request_log); i++) { + ccprintf(" %d\n", request_log[i]); + } + return EC_SUCCESS; + } + + if (!strcasecmp(argv[1], "request")) { + request_chargesplash(); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[1], "reset")) { + reset_state(); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[1], "lockout")) { + locked_out = true; + return EC_SUCCESS; + } + + return EC_ERROR_PARAM1; +} +DECLARE_CONSOLE_COMMAND(chargesplash, command_chargesplash, + "[state|request|reset|lockout]", + "Charge splash controls"); + +static enum ec_status chargesplash_host_cmd(struct host_cmd_handler_args *args) +{ + const struct ec_params_chargesplash *params = args->params; + struct ec_response_chargesplash *response = args->response; + + if (args->params_size < sizeof(*params)) { + return EC_RES_INVALID_PARAM; + } + + if (args->response_max < sizeof(*response)) { + return EC_RES_INVALID_RESPONSE; + } + + switch (params->cmd) { + case EC_CHARGESPLASH_GET_STATE: + /* No action to do */ + break; + case EC_CHARGESPLASH_DISPLAY_READY: + if (power_on_for_chargesplash) { + display_ready(); + } + break; + case EC_CHARGESPLASH_REQUEST: + request_chargesplash(); + break; + case EC_CHARGESPLASH_RESET: + reset_state(); + break; + case EC_CHARGESPLASH_LOCKOUT: + locked_out = true; + break; + default: + return EC_RES_INVALID_PARAM; + } + + /* All commands return the (possibly updated) state */ + response->requested = power_on_for_chargesplash; + response->display_initialized = display_initialized; + response->locked_out = locked_out; + + args->response_size = sizeof(*response); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_CHARGESPLASH, chargesplash_host_cmd, + EC_VER_MASK(0)); diff --git a/common/chipset.c b/common/chipset.c index 209334add5..5a699bfe25 100644 --- a/common/chipset.c +++ b/common/chipset.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,30 +18,27 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) /*****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_POWER_AP -static int command_apreset(int argc, char **argv) +static int command_apreset(int argc, const char **argv) { /* Force the chipset to reset */ ccprintf("Issuing AP reset...\n"); chipset_reset(CHIPSET_RESET_CONSOLE_CMD); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(apreset, command_apreset, - NULL, - "Issue AP reset"); +DECLARE_CONSOLE_COMMAND(apreset, command_apreset, NULL, "Issue AP reset"); -static int command_apshutdown(int argc, char **argv) +static int command_apshutdown(int argc, const char **argv) { chipset_force_shutdown(CHIPSET_SHUTDOWN_CONSOLE_CMD); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(apshutdown, command_apshutdown, - NULL, +DECLARE_CONSOLE_COMMAND(apshutdown, command_apshutdown, NULL, "Force AP shutdown"); #endif @@ -53,19 +50,16 @@ static enum ec_status host_command_apreset(struct host_cmd_handler_args *args) chipset_reset(CHIPSET_RESET_HOST_CMD); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_AP_RESET, - host_command_apreset, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_AP_RESET, host_command_apreset, EC_VER_MASK(0)); #endif #ifdef CONFIG_CMD_AP_RESET_LOG -static struct mutex reset_log_mutex; +K_MUTEX_DEFINE(reset_log_mutex); static int next_reset_log __preserved_logs(next_reset_log); static uint32_t ap_resets_since_ec_boot; /* keep reset_logs size a power of 2 */ -static struct ap_reset_log_entry - reset_logs[4] __preserved_logs(reset_logs); +static struct ap_reset_log_entry reset_logs[4] __preserved_logs(reset_logs); static int reset_log_checksum __preserved_logs(reset_log_checksum); /* Calculate reset log checksum */ @@ -113,11 +107,10 @@ get_ap_reset_stats(struct ap_reset_log_entry *reset_log_entries, mutex_lock(&reset_log_mutex); *resets_since_ec_boot = ap_resets_since_ec_boot; - for (i = 0; - i != ARRAY_SIZE(reset_logs) && i != num_reset_log_entries; + for (i = 0; i != ARRAY_SIZE(reset_logs) && i != num_reset_log_entries; ++i) { log_address = (next_reset_log + i) & - (ARRAY_SIZE(reset_logs) - 1); + (ARRAY_SIZE(reset_logs) - 1); reset_log_entries[i] = reset_logs[log_address]; } mutex_unlock(&reset_log_mutex); @@ -125,5 +118,37 @@ get_ap_reset_stats(struct ap_reset_log_entry *reset_log_entries, return EC_SUCCESS; } -#endif /* !CONFIG_AP_RESET_LOG */ +enum chipset_shutdown_reason chipset_get_shutdown_reason(void) +{ + enum chipset_shutdown_reason reason = CHIPSET_RESET_UNKNOWN; + + mutex_lock(&reset_log_mutex); + if (ap_resets_since_ec_boot != 0) { + int i = (next_reset_log == 0) ? ARRAY_SIZE(reset_logs) - 1 : + next_reset_log - 1; + reason = reset_logs[i].reset_cause; + } + mutex_unlock(&reset_log_mutex); + return reason; +} + +#endif /* !CONFIG_AP_RESET_LOG */ + +#ifdef TEST_BUILD +uint32_t test_chipset_get_ap_resets_since_ec_boot(void) +{ + uint32_t count; + + mutex_lock(&reset_log_mutex); + count = ap_resets_since_ec_boot; + mutex_unlock(&reset_log_mutex); + + return count; +} + +void test_chipset_corrupt_reset_log_checksum(void) +{ + reset_log_checksum = ~reset_log_checksum; +} +#endif /* TEST_BUILD */ diff --git a/common/clz.c b/common/clz.c index b0b58e76a0..178c44d345 100644 --- a/common/clz.c +++ b/common/clz.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/common/console.c b/common/console.c index 8f42dffbf5..b045af1ddf 100644 --- a/common/console.c +++ b/common/console.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,16 +19,18 @@ #define MAX_ARGS_PER_COMMAND 10 -#define PROMPT "> " - #ifdef CONFIG_EXPERIMENTAL_CONSOLE #define EC_SYN 0xEC #define EC_ACK 0xC0 -#endif /* defined(CONFIG_EXPERIMENTAL_CONSOLE) */ +#else /* defined(CONFIG_EXPERIMENTAL_CONSOLE) */ + +#define PROMPT "> " /* ASCII control character; for example, CTRL('C') = ^C */ #define CTRL(c) ((c) - '@') +#endif /* defined(CONFIG_EXPERIMENTAL_CONSOLE) */ + #ifdef CONFIG_CONSOLE_HISTORY /* History buffers */ static char history[CONFIG_CONSOLE_HISTORY][CONFIG_CONSOLE_INPUT_LINE_SIZE]; @@ -50,13 +52,14 @@ static int last_rx_was_cr; #ifndef CONFIG_EXPERIMENTAL_CONSOLE /* State of input escape code */ static enum { - ESC_OUTSIDE, /* Not in escape code */ - ESC_START, /* Got ESC */ - ESC_BAD, /* Bad escape sequence */ - ESC_BRACKET, /* Got ESC [ */ + ESC_OUTSIDE, /* Not in escape code */ + ESC_START, /* Got ESC */ + ESC_BAD, /* Bad escape sequence */ + ESC_BRACKET, /* Got ESC [ */ ESC_BRACKET_1, /* Got ESC [ 1 */ ESC_BRACKET_3, /* Got ESC [ 3 */ - ESC_O, /* Got ESC O */ + ESC_BRACKET_4, /* Got ESC [ 4 */ + ESC_O, /* Got ESC O */ } esc_state; #endif /* !defined(CONFIG_EXPERIMENTAL_CONSOLE) */ @@ -82,7 +85,7 @@ enum extended_key_code { * @return EC_SUCCESS. If more than MAX_ARGS_PER_COMMAND words are found, * discards the excess and returns EC_ERROR_OVERFLOW. */ -static int split_words(char *input, int *argc, char **argv) +static int split_words(char *input, int *argc, const char **argv) { char *c; int in_word = 0; @@ -93,7 +96,7 @@ static int split_words(char *input, int *argc, char **argv) for (c = input; in_line; c++) { if (!*c) in_line = 0; - if (isspace(*c) || !*c) { + if (isspace((unsigned char)*c) || !*c) { if (in_word) { /* Ending a word */ *c = '\0'; @@ -126,7 +129,7 @@ static int split_words(char *input, int *argc, char **argv) * * @return A pointer to the command structure, or NULL if no match found. */ -static const struct console_command *find_command(char *name) +static const struct console_command *find_command(const char *name) { const struct console_command *cmd, *match = NULL; int match_length = strlen(name); @@ -148,18 +151,10 @@ static const struct console_command *find_command(char *name) return match; } - static const char *const errmsgs[] = { - "OK", - "Unknown error", - "Unimplemented", - "Overflow", - "Timeout", - "Invalid argument", - "Busy", - "Access Denied", - "Not Powered", - "Not Calibrated", + "OK", "Unknown error", "Unimplemented", "Overflow", + "Timeout", "Invalid argument", "Busy", "Access Denied", + "Not Powered", "Not Calibrated", }; /** @@ -172,7 +167,7 @@ static const char *const errmsgs[] = { static int handle_command(char *input) { const struct console_command *cmd; - char *argv[MAX_ARGS_PER_COMMAND]; + const char *argv[MAX_ARGS_PER_COMMAND]; int argc = 0; int rv; #ifdef CONFIG_EXPERIMENTAL_CONSOLE @@ -202,10 +197,10 @@ static int handle_command(char *input) i = input[1] == '&' ? 2 : 1; /* Next, there should be 4 hex digits: XXYY + '&' */ - if (i+5 > input_len) + if (i + 5 > input_len) goto command_has_error; /* Replace the '&' with null so we can call strtoi(). */ - input[i+4] = 0; + input[i + 4] = 0; j = strtoi(input + i, &e, 16); if (*e) goto command_has_error; @@ -215,10 +210,10 @@ static int handle_command(char *input) i += 5; /* Lastly, verify the CRC8 of the command. */ - if (i+command_len > input_len) + if (i + command_len > input_len) goto command_has_error; - if (packed_crc8 != crc8(&input[i], command_len)) { -command_has_error: + if (packed_crc8 != cros_crc8(&input[i], command_len)) { + command_has_error: /* Send back the error string. */ ccprintf("&&EE\n"); return EC_ERROR_UNKNOWN; @@ -245,7 +240,7 @@ static int handle_command(char *input) rv = EC_ERROR_ACCESS_DENIED; else #endif - rv = cmd->handler(argc, argv); + rv = cmd->handler(argc, argv); if (rv == EC_SUCCESS) return rv; @@ -273,8 +268,8 @@ static void console_init(void) ccprintf("Enhanced Console is enabled (v1.0.0); type HELP for help.\n"); #else ccprintf("Console is enabled; type HELP for help.\n"); -#endif /* defined(CONFIG_EXPERIMENTAL_CONSOLE) */ ccputs(PROMPT); +#endif /* defined(CONFIG_EXPERIMENTAL_CONSOLE) */ } static int console_putc(int c) @@ -369,7 +364,7 @@ static void save_history(void) static void handle_backspace(void) { if (!input_pos) - return; /* Already at beginning of line */ + return; /* Already at beginning of line */ /* Move cursor back */ console_putc('\b'); @@ -377,8 +372,7 @@ static void handle_backspace(void) /* Print and move anything following the cursor position */ if (input_pos != input_len) { ccputs(input_buf + input_pos); - memmove(input_buf + input_pos - 1, - input_buf + input_pos, + memmove(input_buf + input_pos - 1, input_buf + input_pos, input_len - input_pos + 1); } else { input_buf[input_len - 1] = '\0'; @@ -418,6 +412,9 @@ static int handle_esc(int c) } else if (c == '3') { esc_state = ESC_BRACKET_3; return -1; + } else if (c == '4') { + esc_state = ESC_BRACKET_4; + return -1; } if (c == 'A') @@ -445,12 +442,17 @@ static int handle_esc(int c) return KEY_DEL; break; + case ESC_BRACKET_4: + if (c == '~') + return KEY_END; + break; + default: break; } /* Check if the escape code is done */ - if (isalpha(c) || c == '~') + if (isalpha((unsigned char)c) || c == '~') esc_state = ESC_OUTSIDE; else esc_state = ESC_BAD; @@ -500,15 +502,28 @@ static void console_handle_char(int c) #ifndef CONFIG_EXPERIMENTAL_CONSOLE case KEY_DEL: if (input_pos == input_len) - break; /* Already at end */ + break; /* Already at end */ move_cursor_right(); /* Drop through to backspace handling */ + __fallthrough; case '\b': case 0x7f: handle_backspace(); break; + + case CTRL('C'): + /* Terminate this line */ + ccputs("^C\n"); + + /* Start new line, discarding any existing partial input. */ + input_pos = input_len = 0; + input_buf[0] = '\0'; + + /* Reprint prompt */ + ccputs(PROMPT); + break; #endif /* !defined(CONFIG_EXPERIMENTAL_CONSOLE) */ case '\n': @@ -521,8 +536,8 @@ static void console_handle_char(int c) /* Save command in history buffer */ if (input_len) { save_history(); - history_next = (history_next + 1) % - CONFIG_CONSOLE_HISTORY; + history_next = + (history_next + 1) % CONFIG_CONSOLE_HISTORY; history_pos = history_next; } #endif @@ -610,7 +625,7 @@ static void console_handle_char(int c) default: /* Ignore non-printing characters */ - if (!isprint(c)) + if (!isprint((unsigned char)c)) break; #ifndef CONFIG_EXPERIMENTAL_CONSOLE @@ -669,7 +684,7 @@ void console_task(void *u) console_handle_char(c); } - task_wait_event(-1); /* Wait for more input */ + task_wait_event(-1); /* Wait for more input */ } } @@ -677,10 +692,10 @@ void console_task(void *u) /* Console commands */ /* Command handler - prints help. */ -static int command_help(int argc, char **argv) +static int command_help(int argc, const char **argv) { const int ncmds = __cmds_end - __cmds; - const int cols = 5; /* printing in five columns */ + const int cols = 5; /* printing in five columns */ const int rows = (ncmds + cols - 1) / cols; int i, j; @@ -692,16 +707,15 @@ static int command_help(int argc, char **argv) #ifdef CONFIG_CONSOLE_COMMAND_FLAGS ccputs("Command Flags Description\n"); for (i = 0; i < ncmds; i++) { - ccprintf(" %-14s %x %s\n", - __cmds[i].name, __cmds[i].flags, - __cmds[i].help); + ccprintf(" %-14s %x %s\n", __cmds[i].name, + __cmds[i].flags, __cmds[i].help); cflush(); } #else ccputs("Known commands:\n"); for (i = 0; i < ncmds; i++) { - ccprintf(" %-15s%s\n", - __cmds[i].name, __cmds[i].help); + ccprintf(" %-15s%s\n", __cmds[i].name, + __cmds[i].help); cflush(); } #endif @@ -748,12 +762,11 @@ static int command_help(int argc, char **argv) return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(help, command_help, - "[ list | ]", +DECLARE_SAFE_CONSOLE_COMMAND(help, command_help, "[ list | ]", "Print command help"); #ifdef CONFIG_CONSOLE_HISTORY -static int command_history(int argc, char **argv) +static int command_history(int argc, const char **argv) { int i; @@ -765,7 +778,6 @@ static int command_history(int argc, char **argv) return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(history, command_history, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(history, command_history, NULL, "Print console history"); #endif diff --git a/common/console_output.c b/common/console_output.c index 23c208c61b..72e5c4daf1 100644 --- a/common/console_output.c +++ b/common/console_output.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,7 @@ /* Console output module for Chrome EC */ #include "console.h" +#include "printf.h" #include "uart.h" #include "usb_console.h" #include "util.h" @@ -27,16 +28,52 @@ static uint32_t channel_mask_saved = CC_DEFAULT; * might also become more important if we have >32 channels - for example, if * we decide to replace enum console_channel with enum module_id. */ -static const char * const channel_names[] = { - #define CONSOLE_CHANNEL(enumeration, string) string, - #include "console_channel.inc" - #undef CONSOLE_CHANNEL +static const char *const channel_names[] = { +#define CONSOLE_CHANNEL(enumeration, string) string, +#include "console_channel.inc" +#undef CONSOLE_CHANNEL }; BUILD_ASSERT(ARRAY_SIZE(channel_names) == CC_CHANNEL_COUNT); /* ensure that we are not silently masking additional channels */ -BUILD_ASSERT(CC_CHANNEL_COUNT <= 8*sizeof(uint32_t)); +BUILD_ASSERT(CC_CHANNEL_COUNT <= 8 * sizeof(uint32_t)); + +static int console_channel_name_to_index(const char *name) +{ + int i; + + for (i = 0; i < CC_CHANNEL_COUNT; i++) { + if (!strncasecmp(name, channel_names[i], strlen(name))) + return i; + } + + /* Not found */ + return -1; +} + +void console_channel_enable(const char *name) +{ + int index = console_channel_name_to_index(name); + + if (index >= 0 && index != CC_COMMAND) + channel_mask |= CC_MASK(index); +} +void console_channel_disable(const char *name) +{ + int index = console_channel_name_to_index(name); + + if (index >= 0 && index != CC_COMMAND) + channel_mask &= ~CC_MASK(index); +} + +bool console_channel_is_disabled(enum console_channel channel) +{ + if (!(CC_MASK(channel) & channel_mask)) + return true; + return false; +} #endif /* CONFIG_CONSOLE_CHANNEL */ +#ifndef CONFIG_ZEPHYR /*****************************************************************************/ /* Channel-based console output */ @@ -44,11 +81,9 @@ int cputs(enum console_channel channel, const char *outstr) { int rv1, rv2; -#ifdef CONFIG_CONSOLE_CHANNEL /* Filter out inactive channels */ - if (!(CC_MASK(channel) & channel_mask)) + if (console_channel_is_disabled(channel)) return EC_SUCCESS; -#endif rv1 = usb_puts(outstr); rv2 = uart_puts(outstr); @@ -61,11 +96,9 @@ int cprintf(enum console_channel channel, const char *format, ...) int rv1, rv2; va_list args; -#ifdef CONFIG_CONSOLE_CHANNEL /* Filter out inactive channels */ - if (!(CC_MASK(channel) & channel_mask)) + if (console_channel_is_disabled(channel)) return EC_SUCCESS; -#endif usb_va_start(args, format); rv1 = usb_vprintf(format, args); @@ -82,14 +115,14 @@ int cprints(enum console_channel channel, const char *format, ...) { int r, rv; va_list args; + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; -#ifdef CONFIG_CONSOLE_CHANNEL /* Filter out inactive channels */ - if (!(CC_MASK(channel) & channel_mask)) + if (console_channel_is_disabled(channel)) return EC_SUCCESS; -#endif - rv = cprintf(channel, "[%pT ", PRINTF_TIMESTAMP_NOW); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + rv = cprintf(channel, "[%s ", ts_str); va_start(args, format); r = uart_vprintf(format, args); @@ -106,6 +139,7 @@ int cprints(enum console_channel channel, const char *format, ...) r = cputs(channel, "]\n"); return r ? r : rv; } +#endif /* CONFIG_ZEPHYR */ void cflush(void) { @@ -117,7 +151,7 @@ void cflush(void) #ifdef CONFIG_CONSOLE_CHANNEL /* Set active channels */ -static int command_ch(int argc, char **argv) +static int command_ch(int argc, const char **argv) { int i; char *e; @@ -133,12 +167,24 @@ static int command_ch(int argc, char **argv) } else { /* Set the mask */ - int m = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - /* No disabling the command output channel */ - channel_mask = m | CC_MASK(CC_COMMAND); + int index = console_channel_name_to_index(argv[1]); + + if (index >= 0) { + if (console_channel_is_disabled(index)) { + console_channel_enable(argv[1]); + ccprintf("chan %s enabled\n", argv[1]); + } else { + console_channel_disable(argv[1]); + ccprintf("chan %s disabled\n", argv[1]); + } + } else { + int m = strtoi(argv[1], &e, 0); + if (*e) { + return EC_ERROR_PARAM1; + } + /* No disabling the command output channel */ + channel_mask = m | CC_MASK(CC_COMMAND); + } return EC_SUCCESS; } @@ -147,8 +193,7 @@ static int command_ch(int argc, char **argv) /* Print the list of channels */ ccputs(" # Mask E Channel\n"); for (i = 0; i < CC_CHANNEL_COUNT; i++) { - ccprintf("%2d %08x %c %s\n", - i, CC_MASK(i), + ccprintf("%2d %08x %c %s\n", i, CC_MASK(i), (channel_mask & CC_MASK(i)) ? '*' : ' ', channel_names[i]); cflush(); @@ -156,6 +201,6 @@ static int command_ch(int argc, char **argv) return EC_SUCCESS; }; DECLARE_SAFE_CONSOLE_COMMAND(chan, command_ch, - "[ save | restore | ]", + "[ save | restore | | ]", "Save, restore, get or set console channel mask"); #endif /* CONFIG_CONSOLE_CHANNEL */ diff --git a/common/crc.c b/common/crc.c index 2db1ffc361..11c4936d51 100644 --- a/common/crc.c +++ b/common/crc.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -56,11 +56,11 @@ static const uint32_t crc32_tab[] = { 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; -static uint32_t crc32_hash(uint32_t crc, const void *buf, int size) +static uint32_t _crc32_hash(uint32_t crc, const void *buf, int size) { const uint8_t *p; - p = buf; + p = (const uint8_t *)buf; while (size--) { crc ^= *p++; @@ -75,19 +75,24 @@ void crc32_ctx_init(uint32_t *crc) *crc = CRC32_INITIAL; } +void crc32_ctx_hash(uint32_t *crc, const void *buf, int size) +{ + *crc = _crc32_hash(*crc, buf, size); +} + void crc32_ctx_hash32(uint32_t *crc, uint32_t val) { - *crc = crc32_hash(*crc, &val, sizeof(val)); + *crc = _crc32_hash(*crc, &val, sizeof(val)); } void crc32_ctx_hash16(uint32_t *crc, uint16_t val) { - *crc = crc32_hash(*crc, &val, sizeof(val)); + *crc = _crc32_hash(*crc, &val, sizeof(val)); } void crc32_ctx_hash8(uint32_t *crc, uint8_t val) { - *crc = crc32_hash(*crc, &val, sizeof(val)); + *crc = _crc32_hash(*crc, &val, sizeof(val)); } uint32_t crc32_ctx_result(uint32_t *crc) @@ -103,6 +108,11 @@ void crc32_init(void) crc32_ctx_init(&crc_); } +void crc32_hash(const void *buf, int size) +{ + crc32_ctx_hash(&crc_, buf, size); +} + void crc32_hash32(uint32_t val) { crc32_ctx_hash32(&crc_, val); @@ -117,3 +127,23 @@ uint32_t crc32_result(void) { return crc32_ctx_result(&crc_); } + +uint16_t cros_crc16(const uint8_t *data, int len, uint16_t previous_crc) +{ + int i, j; + uint16_t crc_poly = 0x1021; + uint16_t crc16; + + crc16 = previous_crc; + for (i = 0; i < len; i++) { + crc16 ^= (uint16_t)(data[i] << 8); + for (j = 0; j < 8; j++) { + if (crc16 & 0x8000) + crc16 = (crc16 << 1) ^ crc_poly; + else + crc16 = crc16 << 1; + } + } + + return crc16; +} diff --git a/common/crc.cc b/common/crc.cc new file mode 120000 index 0000000000..08c9c8c528 --- /dev/null +++ b/common/crc.cc @@ -0,0 +1 @@ +crc.c \ No newline at end of file diff --git a/common/crc8.c b/common/crc8.c index 83ba31c5a4..5d8df8db52 100644 --- a/common/crc8.c +++ b/common/crc8.c @@ -1,18 +1,18 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" #include "crc8.h" -inline uint8_t crc8(const uint8_t *data, int len) +inline uint8_t cros_crc8(const uint8_t *data, int len) { - return crc8_arg(data, len, 0); + return cros_crc8_arg(data, len, 0); } -uint8_t crc8_arg(const uint8_t *data, int len, uint8_t previous_crc) +uint8_t cros_crc8_arg(const uint8_t *data, int len, uint8_t previous_crc) { - unsigned crc = previous_crc << 8; + unsigned int crc = previous_crc << 8; int i, j; for (j = len; j; j--, data++) { diff --git a/common/ctz.c b/common/ctz.c index bb6f69624e..ad144225f0 100644 --- a/common/ctz.c +++ b/common/ctz.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -20,8 +20,8 @@ int __keep __ctzsi2(int x) { static const uint8_t MulDeBruijnBitPos[32] = { - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; return MulDeBruijnBitPos[((uint32_t)((x & -x) * 0x077CB531U)) >> 27]; } diff --git a/common/device_event.c b/common/device_event.c index 3b1fae79d0..b9e1bafc69 100644 --- a/common/device_event.c +++ b/common/device_event.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,10 +15,10 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_EVENTS, outstr) -#define CPRINTS(format, args...) cprints(CC_EVENTS, format, ## args) +#define CPRINTS(format, args...) cprints(CC_EVENTS, format, ##args) -static uint32_t device_current_events; -static uint32_t device_enabled_events; +static atomic_t device_current_events; +static atomic_t device_enabled_events; uint32_t device_get_current_events(void) { @@ -27,7 +27,7 @@ uint32_t device_get_current_events(void) static uint32_t device_get_and_clear_events(void) { - return deprecated_atomic_read_clear(&device_current_events); + return atomic_clear(&device_current_events); } static uint32_t device_get_enabled_events(void) @@ -40,10 +40,22 @@ void device_set_events(uint32_t mask) /* Ignore events that are not enabled */ mask &= device_enabled_events; - if ((device_current_events & mask) != mask) + if (((uint32_t)device_current_events & mask) != mask) { CPRINTS("device event set 0x%08x", mask); + } else { + /* + * We are here because there is no flag change (1->1, 0->0). + * For 0->0, we shouldn't notify the host because the flag is + * disabled. For 1->1, it's most likely redundant but we still + * need to notify the host in case the host didn't have a + * chance to read the flags. Otherwise, the flag would never be + * consumed because the host would never be notified. + */ + if (!mask) + return; + } - deprecated_atomic_or(&device_current_events, mask); + atomic_or(&device_current_events, mask); /* Signal host that a device event is pending */ host_set_single_event(EC_HOST_EVENT_DEVICE); @@ -52,10 +64,10 @@ void device_set_events(uint32_t mask) void device_clear_events(uint32_t mask) { /* Only print if something's about to change */ - if (device_current_events & mask) + if ((uint32_t)device_current_events & mask) CPRINTS("device event clear 0x%08x", mask); - deprecated_atomic_clear_bits(&device_current_events, mask); + atomic_clear_bits(&device_current_events, mask); } static void device_set_enabled_events(uint32_t mask) @@ -66,11 +78,16 @@ static void device_set_enabled_events(uint32_t mask) device_enabled_events = mask; } +void device_enable_event(enum ec_device_event event) +{ + atomic_or(&device_enabled_events, EC_DEVICE_EVENT_MASK(event)); +} + /*****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_DEVICE_EVENT -static int command_device_event(int argc, char **argv) +static int command_device_event(int argc, const char **argv) { /* Handle sub-commands */ if (argc == 3) { diff --git a/common/device_state.c b/common/device_state.c index 0ba94d6115..1739a9beb2 100644 --- a/common/device_state.c +++ b/common/device_state.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,7 +7,7 @@ #include "device_state.h" #include "hooks.h" -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /** * Return text description for a state @@ -17,8 +17,9 @@ */ static const char *state_desc(enum device_state state) { - return state == DEVICE_STATE_ON ? "on" : - state == DEVICE_STATE_OFF ? "off" : "unknown"; + return state == DEVICE_STATE_ON ? "on" : + state == DEVICE_STATE_OFF ? "off" : + "unknown"; } enum device_state device_get_state(enum device_type device) @@ -65,7 +66,7 @@ static void check_device_state(void) } DECLARE_HOOK(HOOK_SECOND, check_device_state, HOOK_PRIO_DEFAULT); -static int command_devices(int argc, char **argv) +static int command_devices(int argc, const char **argv) { const struct device_config *dc = device_states; int i; @@ -78,6 +79,5 @@ static int command_devices(int argc, char **argv) return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(devices, command_devices, - "", +DECLARE_SAFE_CONSOLE_COMMAND(devices, command_devices, "", "Get the device states"); diff --git a/common/dps.c b/common/dps.c new file mode 100644 index 0000000000..2a05077fbf --- /dev/null +++ b/common/dps.c @@ -0,0 +1,729 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Dynamic PDO Selection. + */ + +#include "atomic.h" +#include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "charger.h" +#include "common.h" +#include "console.h" +#include "dps.h" +#include "ec_commands.h" +#include "hooks.h" +#include "math_util.h" +#include "task.h" +#include "timer.h" +#include "usb_common.h" +#include "usb_pd.h" +#include "util.h" + +#include + +#define K_MORE_PWR 96 +#define K_LESS_PWR 93 +#define K_SAMPLE 1 +#define K_WINDOW 3 +#define T_REQUEST_STABLE_TIME (10 * SECOND) +#define T_NEXT_CHECK_TIME (5 * SECOND) + +#define DPS_FLAG_STOP_EVENTS \ + (DPS_FLAG_DISABLED | DPS_FLAG_NO_SRCCAP | DPS_FLAG_NO_BATTERY) +#define DPS_FLAG_ALL GENMASK(31, 0) + +#define MAX_MOVING_AVG_WINDOW 5 + +BUILD_ASSERT(K_MORE_PWR > K_LESS_PWR && 100 >= K_MORE_PWR && 100 >= K_LESS_PWR); + +/* lock for updating timeout value */ +K_MUTEX_DEFINE(dps_lock); +static timestamp_t timeout; +static bool is_enabled = true; +static int debug_level; +static bool fake_enabled; +static int fake_mv, fake_ma; +static int dynamic_mv; +static int dps_port = CHARGE_PORT_NONE; +static atomic_t flag; + +#define CPRINTF(format, args...) cprintf(CC_USBPD, "DPS " format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, "DPS " format, ##args) + +__overridable struct dps_config_t dps_config = { + .k_less_pwr = K_LESS_PWR, + .k_more_pwr = K_MORE_PWR, + .k_sample = K_SAMPLE, + .k_window = K_WINDOW, + .t_stable = T_REQUEST_STABLE_TIME, + .t_check = T_NEXT_CHECK_TIME, + .is_more_efficient = NULL, +}; + +__test_only struct dps_config_t *dps_get_config(void) +{ + return &dps_config; +} + +int dps_get_dynamic_voltage(void) +{ + return dynamic_mv; +} + +int dps_get_charge_port(void) +{ + return dps_port; +} + +bool dps_is_enabled(void) +{ + return is_enabled; +} + +test_export_static void dps_enable(bool en) +{ + bool prev_en = is_enabled; + + is_enabled = en; + + if (is_enabled && !prev_en) { + task_wake(TASK_ID_DPS); + } + + if (!is_enabled) { + /* issue a new PD request for a default voltage */ + if (dps_port != CHARGE_PORT_NONE) + pd_dpm_request(dps_port, DPM_REQUEST_NEW_POWER_LEVEL); + } +} + +static void update_timeout(int us) +{ + timestamp_t new_timeout; + + new_timeout.val = get_time().val + us; + + mutex_lock(&dps_lock); + if (new_timeout.val > timeout.val) + timeout = new_timeout; + mutex_unlock(&dps_lock); +} + +/* + * DPS reset. + */ +static void dps_reset(void) +{ + dynamic_mv = PD_MAX_VOLTAGE_MV; + dps_port = CHARGE_PORT_NONE; +} + +/* + * DPS initialization. + */ +test_export_static int dps_init(void) +{ + int rc = EC_SUCCESS; + + dps_reset(); + + if (dps_config.k_window > MAX_MOVING_AVG_WINDOW) { + CPRINTS("ERR:WIN"); + rc = EC_ERROR_INVALID_CONFIG; + } + + if (dps_config.k_less_pwr > 100 || dps_config.k_more_pwr > 100 || + dps_config.k_more_pwr <= dps_config.k_less_pwr) { + CPRINTS("ERR:COEF"); + rc = EC_ERROR_INVALID_CONFIG; + } + + return rc; +} + +static bool is_near_limit(int val, int limit) +{ + return val >= (limit * dps_config.k_more_pwr / 100); +} + +bool is_more_efficient(int curr_mv, int prev_mv, int batt_mv, int batt_mw, + int input_mw) +{ + if (dps_config.is_more_efficient) + return dps_config.is_more_efficient(curr_mv, prev_mv, batt_mv, + batt_mw, input_mw); + + return ABS(curr_mv - batt_mv) < ABS(prev_mv - batt_mv); +} + +/* + * Get the input power of the active port. + * + * input_power = vbus * input_current + * + * @param vbus: VBUS in mV + * @param input_curr: input current in mA + * + * @return input_power of the result of vbus * input_curr in mW + */ +test_mockable_static int get_desired_input_power(int *vbus, int *input_current) +{ + int active_port; + int charger_id; + enum ec_error_list rv; + + active_port = charge_manager_get_active_charge_port(); + + if (active_port == CHARGE_PORT_NONE) + return 0; + + charger_id = charge_get_active_chg_chip(); + + if (fake_enabled) { + *vbus = fake_mv; + *input_current = fake_ma; + return fake_mv * fake_ma / 1000; + } + + rv = charger_get_input_current(charger_id, input_current); + if (rv) + return 0; + + *vbus = charge_manager_get_vbus_voltage(active_port); + + return (*vbus) * (*input_current) / 1000; +} + +test_mockable_static int get_battery_target_voltage(int *target_mv) +{ + int charger_id = charge_get_active_chg_chip(); + int error = charger_get_voltage(charger_id, target_mv); + + if (!error) { + return EC_SUCCESS; + } + if (error != EC_ERROR_UNIMPLEMENTED) { + CPRINTS("Failed to get voltage for charge port %d: %d", + charger_id, error); + return error; + } + /* + * Fall back to battery design voltage if charger output voltage + * is not available. + */ + return battery_design_voltage(target_mv); +} + +/* + * Get the most efficient PDO voltage for the battery of the charging port + * + * | W\Batt | 1S(3.7V) | 2S(7.4V) | 3S(11.1V) | 4S(14.8V) | + * -------------------------------------------------------- + * | 0-15W | 5V | 9V | 12V | 15V | + * | 15-27W | 9V | 9V | 12V | 15V | + * | 27-36W | 12V | 12V | 12V | 15V | + * | 36-45W | 15V | 15V | 15V | 15V | + * | 45-60W | 20V | 20V | 20V | 20V | + * + * + * @return 0 if error occurs, else battery efficient voltage in mV + */ +test_mockable_static int get_efficient_voltage(void) +{ + int eff_mv = 0; + int batt_mv; + int batt_pwr; + int input_pwr, vbus, input_curr; + const struct batt_params *batt = charger_current_battery_params(); + + input_pwr = get_desired_input_power(&vbus, &input_curr); + + if (!input_pwr) + return 0; + + if (get_battery_target_voltage(&batt_mv)) + return 0; + + batt_pwr = batt->current * batt->voltage / 1000; + + for (int i = 0; i < board_get_usb_pd_port_count(); ++i) { + const int cnt = pd_get_src_cap_cnt(i); + const uint32_t *src_caps = pd_get_src_caps(i); + + for (int j = 0; j < cnt; ++j) { + int ma, mv, unused; + + pd_extract_pdo_power(src_caps[j], &ma, &mv, &unused); + /* + * If the eff_mv is not picked, or we have more + * efficient voltage (less voltage diff) + */ + if (eff_mv == 0 || + is_more_efficient(mv, eff_mv, batt_mv, batt_pwr, + input_pwr)) + eff_mv = mv; + } + } + + return eff_mv; +} + +struct pdo_candidate { + int port; + int mv; + int mw; +}; + +#define UPDATE_CANDIDATE(new_port, new_mv, new_mw) \ + do { \ + cand->port = new_port; \ + cand->mv = new_mv; \ + cand->mw = new_mw; \ + } while (0) + +#define CLEAR_AND_RETURN() \ + do { \ + moving_avg_count = 0; \ + return false; \ + } while (0) + +test_mockable_static int get_batt_charge_power(void) +{ + const struct batt_params *batt = charger_current_battery_params(); + + return batt->current * batt->voltage / 1000; +} + +/* + * Evaluate the system power if a new PD power request is needed. + * + * @param struct pdo_candidate: The candidate PDO. (Return value) + * @return true if a new power request, or false otherwise. + */ +test_mockable_static bool has_new_power_request(struct pdo_candidate *cand) +{ + int vbus, input_curr, input_pwr; + int input_pwr_avg = 0, input_curr_avg = 0; + int batt_pwr, batt_mv; + int max_mv = pd_get_max_voltage(); + int req_pwr, req_ma, req_mv; + int input_curr_limit; + int active_port = charge_manager_get_active_charge_port(); + int charger_id; + static int input_pwrs[MAX_MOVING_AVG_WINDOW]; + static int input_currs[MAX_MOVING_AVG_WINDOW]; + static int prev_active_port = CHARGE_PORT_NONE; + static int prev_req_mv; + static int moving_avg_count; + + /* set a default value in case it early returns. */ + UPDATE_CANDIDATE(CHARGE_PORT_NONE, INT32_MAX, 0); + + if (active_port == CHARGE_PORT_NONE) + CLEAR_AND_RETURN(); + + req_mv = pd_get_requested_voltage(active_port); + req_ma = pd_get_requested_current(active_port); + + if (!req_mv) + CLEAR_AND_RETURN(); + + if (get_battery_target_voltage(&batt_mv)) + CLEAR_AND_RETURN(); + + /* if last sample is not the same as the current one, reset counting. */ + if (prev_req_mv != req_mv || prev_active_port != active_port) + moving_avg_count = 0; + prev_active_port = active_port; + prev_req_mv = req_mv; + + req_pwr = req_mv * req_ma / 1000; + batt_pwr = get_batt_charge_power(); + input_pwr = get_desired_input_power(&vbus, &input_curr); + + if (!input_pwr) + CLEAR_AND_RETURN(); + + /* record moving average */ + input_pwrs[moving_avg_count % dps_config.k_window] = input_pwr; + input_currs[moving_avg_count % dps_config.k_window] = input_curr; + if (++moving_avg_count < dps_config.k_window) + return false; + + for (int i = 0; i < dps_config.k_window; i++) { + input_curr_avg += input_currs[i]; + input_pwr_avg += input_pwrs[i]; + } + input_curr_avg /= dps_config.k_window; + input_pwr_avg /= dps_config.k_window; + + charger_id = charge_get_active_chg_chip(); + + if (!charger_get_input_current_limit(charger_id, &input_curr_limit)) + /* set as last requested mA if we're unable to get the limit. */ + input_curr_limit = req_ma; + + /* + * input power might be insufficient, force it to negotiate a more + * powerful PDO. + */ + if (is_near_limit(input_pwr_avg, req_pwr) || + is_near_limit(input_curr_avg, MIN(req_ma, input_curr_limit))) { + atomic_or(&flag, DPS_FLAG_NEED_MORE_PWR); + if (!fake_enabled) + input_pwr_avg = req_pwr + 1; + } else { + atomic_clear_bits(&flag, DPS_FLAG_NEED_MORE_PWR); + } + + if (debug_level) + CPRINTS("C%d 0x%x last (%dmW %dmV) input (%dmW %dmV %dmA) " + "avg (%dmW, %dmA)", + active_port, (int)flag, req_pwr, req_mv, input_pwr, + vbus, input_curr, input_pwr_avg, input_curr_avg); + + for (int i = 0; i < board_get_usb_pd_port_count(); ++i) { + const uint32_t *const src_caps = pd_get_src_caps(i); + + /* If the port is not SNK, skip evaluating this port. */ + if (pd_get_power_role(i) != PD_ROLE_SINK) + continue; + + for (int j = 0; j < pd_get_src_cap_cnt(i); ++j) { + int ma, mv, unused; + int mw; + bool efficient; + + /* TODO(b:169532537): support augmented PDO. */ + if ((src_caps[j] & PDO_TYPE_MASK) != PDO_TYPE_FIXED) + continue; + + pd_extract_pdo_power(src_caps[j], &ma, &mv, &unused); + + if (mv > max_mv) + continue; + + mw = MIN(ma, PD_MAX_CURRENT_MA) * mv / 1000; + efficient = is_more_efficient(mv, cand->mv, batt_mv, + batt_pwr, input_pwr_avg); + + if (flag & DPS_FLAG_NEED_MORE_PWR) { + /* the insufficient case.*/ + if (input_pwr_avg > cand->mw && + (mw > cand->mw || + (mw == cand->mw && efficient))) { + UPDATE_CANDIDATE(i, mv, mw); + } else if (input_pwr_avg <= mw && efficient) { + UPDATE_CANDIDATE(i, mv, mw); + } + } else { + int adjust_pwr = + mw * dps_config.k_less_pwr / 100; + int adjust_cand_mw = + cand->mw * dps_config.k_less_pwr / 100; + + /* Pick if we don't have a candidate yet. */ + if (!cand->mw) { + UPDATE_CANDIDATE(i, mv, mw); + /* + * if the candidate is insufficient, and + * we get one provides more. + */ + } else if ((adjust_cand_mw < input_pwr_avg && + cand->mw < mw) || + /* + * if the candidate is sufficient, + * and we pick a more efficient one. + */ + (adjust_cand_mw >= input_pwr_avg && + adjust_pwr >= input_pwr_avg && + efficient)) { + UPDATE_CANDIDATE(i, mv, mw); + } + } + + /* + * if the candidate is the same as the current one, pick + * the one at active charge port. + */ + if (mw == cand->mw && mv == cand->mv && + i == active_port) + UPDATE_CANDIDATE(i, mv, mw); + } + } + + if (!cand->mv) + CPRINTS("ERR:CNDMV"); + + return (cand->mv != req_mv); +} + +__maybe_unused static bool has_srccap(void) +{ + for (int i = 0; i < board_get_usb_pd_port_count(); ++i) { + if (pd_is_connected(i) && + pd_get_power_role(i) == PD_ROLE_SINK && + pd_get_src_cap_cnt(i) > 0) + return true; + } + return false; +} + +void dps_update_stabilized_time(int port) +{ + update_timeout(dps_config.t_stable); +} + +void dps_task(void *u) +{ + struct pdo_candidate last_cand = { CHARGE_PORT_NONE, 0, 0 }; + int sample_count = 0; + int rv; + + rv = dps_init(); + if (rv) { + CPRINTS("ERR:INIT%d", rv); + return; + } + + update_timeout(dps_config.t_check); + + while (1) { + struct pdo_candidate curr_cand = { CHARGE_PORT_NONE, 0, 0 }; + timestamp_t now; + + now = get_time(); + if (flag & DPS_FLAG_STOP_EVENTS) { + dps_reset(); + task_wait_event(-1); + /* clear flags after wake up. */ + atomic_clear(&flag); + update_timeout(dps_config.t_check); + continue; + } else if (now.val < timeout.val) { + atomic_or(&flag, DPS_FLAG_WAITING); + task_wait_event(timeout.val - now.val); + atomic_clear_bits(&flag, DPS_FLAG_WAITING); + continue; + } + + if (!is_enabled) { + atomic_or(&flag, DPS_FLAG_DISABLED); + continue; + } + + if (!has_srccap()) { + atomic_or(&flag, DPS_FLAG_NO_SRCCAP); + continue; + } + + if (battery_is_present() != BP_YES) { + atomic_or(&flag, DPS_FLAG_NO_BATTERY); + continue; + } + + if (!has_new_power_request(&curr_cand)) { + sample_count = 0; + atomic_clear_bits(&flag, DPS_FLAG_SAMPLED); + } else { + if (last_cand.port == curr_cand.port && + last_cand.mv == curr_cand.mv && + last_cand.mw == curr_cand.mw) + sample_count++; + else + sample_count = 1; + atomic_or(&flag, DPS_FLAG_SAMPLED); + } + + if (sample_count == dps_config.k_sample) { + dynamic_mv = curr_cand.mv; + dps_port = curr_cand.port; + pd_dpm_request(dps_port, DPM_REQUEST_NEW_POWER_LEVEL); + sample_count = 0; + atomic_clear_bits(&flag, (DPS_FLAG_SAMPLED | + DPS_FLAG_NEED_MORE_PWR)); + } + + last_cand.port = curr_cand.port; + last_cand.mv = curr_cand.mv; + last_cand.mw = curr_cand.mw; + update_timeout(dps_config.t_check); + } +} + +void check_battery_present(void) +{ + const struct batt_params *batt = charger_current_battery_params(); + + if (batt->is_present == BP_YES && (flag & DPS_FLAG_NO_BATTERY)) { + atomic_clear_bits(&flag, DPS_FLAG_NO_BATTERY); + task_wake(TASK_ID_DPS); + } +} +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, check_battery_present, HOOK_PRIO_DEFAULT); + +static int command_dps(int argc, const char **argv) +{ + int port = charge_manager_get_active_charge_port(); + int input_pwr, vbus, input_curr; + int holder; + + if (argc == 1) { + uint32_t last_ma = 0, last_mv = 0; + int batt_mv; + + ccprintf("flag=0x%x k_more=%d k_less=%d k_sample=%d k_win=%d\n", + (int)flag, dps_config.k_more_pwr, + dps_config.k_less_pwr, dps_config.k_sample, + dps_config.k_window); + ccprintf("t_stable=%d t_check=%d\n", + dps_config.t_stable / SECOND, + dps_config.t_check / SECOND); + if (!is_enabled) { + ccprintf("DPS Disabled\n"); + return EC_SUCCESS; + } + + if (port == CHARGE_PORT_NONE) { + ccprintf("No charger attached\n"); + return EC_SUCCESS; + } + + get_battery_target_voltage(&batt_mv); + input_pwr = get_desired_input_power(&vbus, &input_curr); + if (!(flag & DPS_FLAG_NO_SRCCAP)) { + last_mv = pd_get_requested_voltage(port); + last_ma = pd_get_requested_current(port); + } + ccprintf("C%d DPS Enabled\n" + "Requested: %dmV/%dmA\n" + "Measured: %dmV/%dmA/%dmW\n" + "Efficient: %dmV\n" + "Batt: %dmv\n" + "PDMaxMV: %dmV\n", + port, last_mv, last_ma, vbus, input_curr, input_pwr, + get_efficient_voltage(), batt_mv, + pd_get_max_voltage()); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[1], "en")) { + dps_enable(true); + return EC_SUCCESS; + } else if (!strcasecmp(argv[1], "dis")) { + dps_enable(false); + return EC_SUCCESS; + } else if (!strcasecmp(argv[1], "fakepwr")) { + if (argc == 2) { + ccprintf("%sabled %dmV/%dmA\n", + fake_enabled ? "en" : "dis", fake_mv, fake_ma); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[2], "dis")) { + fake_enabled = false; + return EC_SUCCESS; + } + + if (argc < 4) + return EC_ERROR_PARAM_COUNT; + + holder = atoi(argv[2]); + if (holder <= 0) + return EC_ERROR_PARAM2; + fake_mv = holder; + + holder = atoi(argv[3]); + if (holder <= 0) + return EC_ERROR_PARAM3; + fake_ma = holder; + + fake_enabled = true; + return EC_SUCCESS; + } + + if (argc != 3) + return EC_ERROR_PARAM2; + + if (!strcasecmp(argv[1], "debug")) { + debug_level = atoi(argv[2]); + } else if (!strcasecmp(argv[1], "setkmore")) { + holder = atoi(argv[2]); + if (holder > 100 || holder <= 0 || + holder < dps_config.k_less_pwr) + return EC_ERROR_PARAM2; + dps_config.k_more_pwr = holder; + } else if (!strcasecmp(argv[1], "setkless")) { + holder = atoi(argv[2]); + if (holder > 100 || holder <= 0 || + holder > dps_config.k_more_pwr) + return EC_ERROR_PARAM2; + dps_config.k_less_pwr = holder; + } else if (!strcasecmp(argv[1], "setksample")) { + holder = atoi(argv[2]); + if (holder <= 0) + return EC_ERROR_PARAM2; + dps_config.k_sample = holder; + } else if (!strcasecmp(argv[1], "setkwin")) { + holder = atoi(argv[2]); + if (holder <= 0 || holder > MAX_MOVING_AVG_WINDOW) + return EC_ERROR_PARAM2; + dps_config.k_window = holder; + } else if (!strcasecmp(argv[1], "settcheck")) { + holder = atoi(argv[2]); + if (holder <= 0) + return EC_ERROR_PARAM2; + dps_config.t_check = holder * SECOND; + } else if (!strcasecmp(argv[1], "settstable")) { + holder = atoi(argv[2]); + if (holder <= 0) + return EC_ERROR_PARAM2; + dps_config.t_stable = holder * SECOND; + } else { + return EC_ERROR_PARAM1; + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(dps, command_dps, + "en|dis|debug \n" + "\t\t set(kmore|kless|ksample|kwindow) \n" + "\t\t set(tstable|tcheck) \n" + "\t\t fakepwr [dis| ]", + "Print/set Dynamic PDO Selection state."); + +static enum ec_status hc_usb_pd_dps_control(struct host_cmd_handler_args *args) +{ + const struct ec_params_usb_pd_dps_control *p = args->params; + + dps_enable(p->enable); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DPS_CONTROL, hc_usb_pd_dps_control, + EC_VER_MASK(0)); + +#ifdef TEST_BUILD +__test_only bool dps_is_fake_enabled(void) +{ + return fake_enabled; +} +__test_only int dps_get_fake_mv(void) +{ + return fake_mv; +} +__test_only int dps_get_fake_ma(void) +{ + return fake_ma; +} +__test_only int *dps_get_debug_level(void) +{ + return &debug_level; +} +__test_only int dps_get_flag(void) +{ + return flag; +} +#endif /* TEST_BUILD */ diff --git a/common/dptf.c b/common/dptf.c index f4fc6d0ff6..5c976e8ea9 100644 --- a/common/dptf.c +++ b/common/dptf.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,17 +13,23 @@ #include "temp_sensor.h" #include "util.h" +#ifdef CONFIG_ZEPHYR +#include "temp_sensor/temp_sensor.h" +#endif + /* Console output macros */ #define CPUTS(outstr) cputs(CC_DPTF, outstr) -#define CPRINTS(format, args...) cprints(CC_DPTF, format, ## args) +#define CPRINTS(format, args...) cprints(CC_DPTF, format, ##args) /*****************************************************************************/ /* DPTF temperature thresholds */ static struct { - int temp; /* degrees K, negative for disabled */ - cond_t over; /* watch for crossings */ + int temp; /* degrees K, negative for disabled */ + cond_t over; /* watch for crossings */ } dptf_threshold[TEMP_SENSOR_COUNT][DPTF_THRESHOLDS_PER_SENSOR]; +_STATIC_ASSERT(TEMP_SENSOR_COUNT > 0, + "CONFIG_PLATFORM_EC_DPTF enabled, but no temp sensors"); static void dptf_init(void) { @@ -34,20 +40,19 @@ static void dptf_init(void) dptf_threshold[id][t].temp = -1; cond_init(&dptf_threshold[id][t].over, 0); } - } DECLARE_HOOK(HOOK_INIT, dptf_init, HOOK_PRIO_DEFAULT); /* Keep track of which triggered sensor thresholds the AP has seen */ -static uint32_t dptf_seen; +static atomic_t dptf_seen; int dptf_query_next_sensor_event(void) { int id; for (id = 0; id < TEMP_SENSOR_COUNT; id++) - if (dptf_seen & BIT(id)) { /* atomic? */ - deprecated_atomic_clear_bits(&dptf_seen, BIT(id)); + if ((uint32_t)dptf_seen & BIT(id)) { + atomic_clear_bits(&dptf_seen, BIT(id)); return id; } @@ -66,9 +71,8 @@ static int dptf_check_temp_threshold(int sensor_id, int temp) } for (i = 0; i < DPTF_THRESHOLDS_PER_SENSOR; i++) { - max = dptf_threshold[sensor_id][i].temp; - if (max < 0) /* disabled? */ + if (max < 0) /* disabled? */ continue; if (temp >= max) @@ -77,15 +81,13 @@ static int dptf_check_temp_threshold(int sensor_id, int temp) cond_set_false(&dptf_threshold[sensor_id][i].over); if (cond_went_true(&dptf_threshold[sensor_id][i].over)) { - CPRINTS("DPTF over threshold [%d][%d", - sensor_id, i); - deprecated_atomic_or(&dptf_seen, BIT(sensor_id)); + CPRINTS("DPTF over threshold [%d][%d", sensor_id, i); + atomic_or(&dptf_seen, BIT(sensor_id)); tripped = 1; } if (cond_went_false(&dptf_threshold[sensor_id][i].over)) { - CPRINTS("DPTF under threshold [%d][%d", - sensor_id, i); - deprecated_atomic_or(&dptf_seen, BIT(sensor_id)); + CPRINTS("DPTF under threshold [%d][%d", sensor_id, i); + atomic_or(&dptf_seen, BIT(sensor_id)); tripped = 1; } } @@ -95,8 +97,8 @@ static int dptf_check_temp_threshold(int sensor_id, int temp) void dptf_set_temp_threshold(int sensor_id, int temp, int idx, int enable) { - CPRINTS("DPTF sensor %d, threshold %d C, index %d, %sabled", - sensor_id, K_TO_C(temp), idx, enable ? "en" : "dis"); + CPRINTS("DPTF sensor %d, threshold %d C, index %d, %sabled", sensor_id, + K_TO_C(temp), idx, enable ? "en" : "dis"); if ((sensor_id >= TEMP_SENSOR_COUNT) || (idx >= DPTF_THRESHOLDS_PER_SENSOR)) { @@ -109,7 +111,7 @@ void dptf_set_temp_threshold(int sensor_id, int temp, int idx, int enable) if (dptf_threshold[sensor_id][idx].temp == -1) cond_init(&dptf_threshold[sensor_id][idx].over, 0); dptf_threshold[sensor_id][idx].temp = temp; - deprecated_atomic_clear_bits(&dptf_seen, BIT(sensor_id)); + atomic_clear_bits(&dptf_seen, BIT(sensor_id)); } else { dptf_threshold[sensor_id][idx].temp = -1; } @@ -118,8 +120,20 @@ void dptf_set_temp_threshold(int sensor_id, int temp, int idx, int enable) /*****************************************************************************/ /* EC-specific thermal controls */ +#ifdef CONFIG_CUSTOMIZED_DESIGN +__overridable int board_temp_smi_evet(void) +{ + /* Do nothing by default. Boards can modify the temps condition */ + return true; +} +#endif + test_mockable_static void smi_sensor_failure_warning(void) { +#ifdef CONFIG_CUSTOMIZED_DESIGN + if (!board_temp_smi_evet()) + return; +#endif CPRINTS("can't read any temp sensors!"); host_set_single_event(EC_HOST_EVENT_THERMAL); } @@ -172,7 +186,7 @@ DECLARE_HOOK(HOOK_SECOND, thermal_control_dptf, HOOK_PRIO_TEMP_SENSOR_DONE); /*****************************************************************************/ /* Console commands */ -static int command_dptftemp(int argc, char **argv) +static int command_dptftemp(int argc, const char **argv) { int id, t; int temp, trig; @@ -192,9 +206,8 @@ static int command_dptftemp(int argc, char **argv) ccprintf(" %s\n", temp_sensors[id].name); } - ccprintf("AP seen mask: 0x%08x\n", dptf_seen); + ccprintf("AP seen mask: 0x%08x\n", (int)dptf_seen); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(dptftemp, command_dptftemp, - NULL, +DECLARE_CONSOLE_COMMAND(dptftemp, command_dptftemp, NULL, "Print DPTF thermal parameters (degrees Kelvin)"); diff --git a/common/ec.libsharedobjs.ld b/common/ec.libsharedobjs.ld index adf5081640..57b67daecc 100644 --- a/common/ec.libsharedobjs.ld +++ b/common/ec.libsharedobjs.ld @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/common/ec_ec_comm_client.c b/common/ec_ec_comm_client.c new file mode 100644 index 0000000000..193d121343 --- /dev/null +++ b/common/ec_ec_comm_client.c @@ -0,0 +1,377 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * EC-EC communication, functions and definitions for client. + */ + +#include "battery.h" +#include "common.h" +#include "console.h" +#include "crc8.h" +#include "ec_commands.h" +#include "ec_ec_comm_client.h" +#include "timer.h" +#include "uart.h" +#include "util.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ##args) + +/* + * TODO(b:65697962): The packed structures below do not play well if we force EC + * host commands structures to be aligned on 32-bit boundary. There are ways to + * fix that, possibly requiring copying data around, or modifying + * uart_alt_pad_write_read API to write the actual server response to a separate + * buffer. + */ +#ifdef CONFIG_HOSTCMD_ALIGNED +#error "Cannot define CONFIG_HOSTCMD_ALIGNED with EC-EC communication client." +#endif + +#define EC_EC_HOSTCMD_VERSION 4 + +/* Print extra debugging information */ +#undef EXTRA_DEBUG + +/* + * During early debugging, we would like to check that the error rate does + * grow out of control. + */ +#define DEBUG_EC_COMM_STATS +#ifdef DEBUG_EC_COMM_STATS +struct { + int total; + int errtimeout; + int errbusy; + int errunknown; + int errdatacrc; + int errcrc; + int errinval; +} comm_stats; + +#define INCR_COMM_STATS(var) (comm_stats.var++) +#else +#define INCR_COMM_STATS(var) +#endif + +/** + * Write a command on the EC-EC communication UART channel. + * + * @param command One of EC_CMD_*. + * @param data Packed structure with this layout: + * struct { + * struct { + * struct ec_host_request4 head; + * struct ec_params_* param; + * uint8_t crc8; + * } req; + * struct { + * struct ec_host_response4 head; + * struct ec_response_* info; + * uint8_t crc8; + * } resp; + * } __packed data; + * + * Where req is the request to be transmitted (head and crc8 are computed by + * this function), and resp is the response to be received (head integrity and + * crc8 are verified by this function). + * + * This format is required as the EC-EC UART is half-duplex, and all the + * transmitted data is received back, i.e. the client writes req, then reads + * req, followed by resp. + * + * When a command does not take parameters, param/crc8 must be omitted in + * tx structure. The same applies to rx structure if the response does not + * include a payload: info/crc8 must be omitted. + * + * @param req_len size of req.param (0 if no parameter is passed). + * @param resp_len size of resp.info (0 if no information is returned). + * @param timeout_us timeout in microseconds for the transaction to complete. + * + * @return + * - EC_SUCCESS on success. + * - EC_ERROR_TIMEOUT when remote end times out replying. + * - EC_ERROR_BUSY when UART is busy and cannot transmit currently. + * - EC_ERROR_CRC when the header or data CRC is invalid. + * - EC_ERROR_INVAL when the received header is invalid. + * - EC_ERROR_UNKNOWN on other error. + */ +static int write_command(uint16_t command, uint8_t *data, int req_len, + int resp_len, int timeout_us) +{ + /* Sequence number. */ + static uint8_t cur_seq; + int ret; + int hascrc, response_seq; + + struct ec_host_request4 *request_header = (void *)data; + /* Request (TX) length is header + (data + crc8), response follows. */ + int tx_length = + sizeof(*request_header) + ((req_len > 0) ? (req_len + 1) : 0); + + struct ec_host_response4 *response_header = (void *)&data[tx_length]; + /* RX length is TX length + response from server. */ + int rx_length = tx_length + sizeof(*request_header) + + ((resp_len > 0) ? (resp_len + 1) : 0); + + /* + * Make sure there is a gap between each command, so that the server + * can recover its state machine after each command. + * + * TODO(b:65697962): We can be much smarter than this, and record the + * last transaction time instead of just sleeping blindly. + */ + usleep(10 * MSEC); + +#ifdef DEBUG_EC_COMM_STATS + if ((comm_stats.total % 128) == 0) { + CPRINTF("UART %d (T%dB%d,U%dC%dD%dI%d)\n", comm_stats.total, + comm_stats.errtimeout, comm_stats.errbusy, + comm_stats.errunknown, comm_stats.errcrc, + comm_stats.errdatacrc, comm_stats.errinval); + } +#endif + + cur_seq = (cur_seq + 1) & + (EC_PACKET4_0_SEQ_NUM_MASK >> EC_PACKET4_0_SEQ_NUM_SHIFT); + + memset(request_header, 0, sizeof(*request_header)); + /* fields0: leave seq_dup and is_response as 0. */ + request_header->fields0 = + EC_EC_HOSTCMD_VERSION | /* version */ + (cur_seq << EC_PACKET4_0_SEQ_NUM_SHIFT); /* seq_num + */ + /* fields1: leave command_version as 0. */ + if (req_len > 0) + request_header->fields1 |= EC_PACKET4_1_DATA_CRC_PRESENT_MASK; + request_header->command = command; + request_header->data_len = req_len; + request_header->header_crc = cros_crc8((uint8_t *)request_header, + sizeof(*request_header) - 1); + if (req_len > 0) + data[sizeof(*request_header) + req_len] = + cros_crc8(&data[sizeof(*request_header)], req_len); + + ret = uart_alt_pad_write_read((void *)data, tx_length, (void *)data, + rx_length, timeout_us); + + INCR_COMM_STATS(total); + +#ifdef EXTRA_DEBUG + CPRINTF("EC-EC ret=%d/%d\n", ret, rx_length); +#endif + + if (ret != rx_length) { + if (ret == -EC_ERROR_TIMEOUT) { + INCR_COMM_STATS(errtimeout); + return EC_ERROR_TIMEOUT; + } + + if (ret == -EC_ERROR_BUSY) { + INCR_COMM_STATS(errbusy); + return EC_ERROR_BUSY; + } + + INCR_COMM_STATS(errunknown); + return EC_ERROR_UNKNOWN; + } + + if (response_header->header_crc != + cros_crc8((uint8_t *)response_header, + sizeof(*response_header) - 1)) { + INCR_COMM_STATS(errcrc); + return EC_ERROR_CRC; + } + + hascrc = response_header->fields1 & EC_PACKET4_1_DATA_CRC_PRESENT_MASK; + response_seq = (response_header->fields0 & EC_PACKET4_0_SEQ_NUM_MASK) >> + EC_PACKET4_0_SEQ_NUM_SHIFT; + + /* + * Validate received header. + * Note that we _require_ data crc to be present if there is data to be + * read back, else we would not know how many bytes to read exactly. + */ + if ((response_header->fields0 & EC_PACKET4_0_STRUCT_VERSION_MASK) != + EC_EC_HOSTCMD_VERSION || + !(response_header->fields0 & EC_PACKET4_0_IS_RESPONSE_MASK) || + response_seq != cur_seq || + (response_header->data_len > 0 && !hascrc) || + response_header->data_len != resp_len) { + INCR_COMM_STATS(errinval); + return EC_ERROR_INVAL; + } + + /* Check data CRC. */ + if (hascrc && + data[rx_length - 1] != + cros_crc8(&data[tx_length + sizeof(*request_header)], + resp_len)) { + INCR_COMM_STATS(errdatacrc); + return EC_ERROR_CRC; + } + + return EC_SUCCESS; +} + +/** + * handle error from write_command + * + * @param ret is return value from write_command + * @param request_result is data.resp.head.result (response result value) + * + * @return EC_RES_ERROR if ret is not EC_SUCCESS, else request_result. + */ +static int handle_error(const char *func, int ret, int request_result) +{ + if (ret != EC_SUCCESS) { + /* Do not print busy errors as they just spam the console. */ + if (ret != EC_ERROR_BUSY) + CPRINTF("%s: tx error %d\n", func, ret); + return EC_RES_ERROR; + } + + if (request_result != EC_RES_SUCCESS) + CPRINTF("%s: cmd error %d\n", func, ret); + + return request_result; +} + +#ifdef CONFIG_EC_EC_COMM_BATTERY +int ec_ec_client_base_get_dynamic_info(void) +{ + int ret; + struct { + struct { + struct ec_host_request4 head; + struct ec_params_battery_dynamic_info param; + uint8_t crc8; + } req; + struct { + struct ec_host_response4 head; + struct ec_response_battery_dynamic_info info; + uint8_t crc8; + } resp; + } __packed data; + + data.req.param.index = 0; + + ret = write_command(EC_CMD_BATTERY_GET_DYNAMIC, (void *)&data, + sizeof(data.req.param), sizeof(data.resp.info), + 15 * MSEC); + ret = handle_error(__func__, ret, data.resp.head.result); + if (ret != EC_RES_SUCCESS) + return ret; + +#ifdef EXTRA_DEBUG + CPRINTF("V: %d mV\n", data.resp.info.actual_voltage); + CPRINTF("I: %d mA\n", data.resp.info.actual_current); + CPRINTF("Remaining: %d mAh\n", data.resp.info.remaining_capacity); + CPRINTF("Cap-full: %d mAh\n", data.resp.info.full_capacity); + CPRINTF("Flags: %04x\n", data.resp.info.flags); + CPRINTF("V-desired: %d mV\n", data.resp.info.desired_voltage); + CPRINTF("I-desired: %d mA\n", data.resp.info.desired_current); +#endif + + memcpy(&battery_dynamic[BATT_IDX_BASE], &data.resp.info, + sizeof(battery_dynamic[BATT_IDX_BASE])); + return EC_RES_SUCCESS; +} + +int ec_ec_client_base_get_static_info(void) +{ + int ret; + struct { + struct { + struct ec_host_request4 head; + struct ec_params_battery_static_info param; + uint8_t crc8; + } req; + struct { + struct ec_host_response4 head; + struct ec_response_battery_static_info info; + uint8_t crc8; + } resp; + } __packed data; + const struct ec_response_battery_static_info *info = &data.resp.info; + struct battery_static_info *bs = &battery_static[BATT_IDX_BASE]; + + data.req.param.index = 0; + + ret = write_command(EC_CMD_BATTERY_GET_STATIC, (void *)&data, + sizeof(data.req.param), sizeof(data.resp.info), + 15 * MSEC); + ret = handle_error(__func__, ret, data.resp.head.result); + if (ret != EC_RES_SUCCESS) + return ret; + +#ifdef EXTRA_DEBUG + CPRINTF("Cap-design: %d mAh\n", data.resp.info.design_capacity); + CPRINTF("V-design: %d mV\n", data.resp.info.design_voltage); + CPRINTF("Manuf: %s\n", data.resp.info.manufacturer); + CPRINTF("Model: %s\n", data.resp.info.model); + CPRINTF("Serial: %s\n", data.resp.info.serial); + CPRINTF("Type: %s\n", data.resp.info.type); + CPRINTF("C-count: %d\n", data.resp.info.cycle_count); +#endif + + bs->design_capacity = info->design_capacity; + bs->design_voltage = info->design_voltage; + bs->cycle_count = info->cycle_count; + strncpy(bs->manufacturer_ext, info->manufacturer, + sizeof(bs->manufacturer_ext)); + strncpy(bs->model_ext, info->model, sizeof(bs->model_ext)); + strncpy(bs->serial_ext, info->serial, sizeof(bs->serial_ext)); + strncpy(bs->type_ext, info->type, sizeof(bs->type_ext)); + + return EC_RES_SUCCESS; +} + +int ec_ec_client_base_charge_control(int max_current, int otg_voltage, + int allow_charging) +{ + int ret; + struct { + struct { + struct ec_host_request4 head; + struct ec_params_charger_control ctrl; + uint8_t crc8; + } req; + struct { + struct ec_host_response4 head; + } resp; + } __packed data; + + data.req.ctrl.allow_charging = allow_charging; + data.req.ctrl.max_current = max_current; + data.req.ctrl.otg_voltage = otg_voltage; + + ret = write_command(EC_CMD_CHARGER_CONTROL, (void *)&data, + sizeof(data.req.ctrl), 0, 30 * MSEC); + + return handle_error(__func__, ret, data.resp.head.result); +} + +int ec_ec_client_hibernate(void) +{ + int ret; + struct { + struct { + struct ec_host_request4 head; + struct ec_params_reboot_ec param; + } req; + struct { + struct ec_host_response4 head; + } resp; + } __packed data; + + data.req.param.cmd = EC_REBOOT_HIBERNATE; + data.req.param.flags = 0; + + ret = write_command(EC_CMD_REBOOT_EC, (void *)&data, + sizeof(data.req.param), 0, 30 * MSEC); + + return handle_error(__func__, ret, data.resp.head.result); +} +#endif /* CONFIG_EC_EC_COMM_BATTERY */ diff --git a/common/ec_ec_comm_master.c b/common/ec_ec_comm_master.c deleted file mode 100644 index 966e4c0f53..0000000000 --- a/common/ec_ec_comm_master.c +++ /dev/null @@ -1,370 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * EC-EC communication, functions and definitions for master. - */ - -#include "battery.h" -#include "common.h" -#include "console.h" -#include "crc8.h" -#include "ec_commands.h" -#include "ec_ec_comm_master.h" -#include "timer.h" -#include "uart.h" -#include "util.h" - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -/* - * TODO(b:65697962): The packed structures below do not play well if we force EC - * host commands structures to be aligned on 32-bit boundary. There are ways to - * fix that, possibly requiring copying data around, or modifying - * uart_alt_pad_write_read API to write the actual slave response to a separate - * buffer. - */ -#ifdef CONFIG_HOSTCMD_ALIGNED -#error "Cannot define CONFIG_HOSTCMD_ALIGNED with EC-EC communication master." -#endif - -#define EC_EC_HOSTCMD_VERSION 4 - -/* Print extra debugging information */ -#undef EXTRA_DEBUG - -/* - * During early debugging, we would like to check that the error rate does - * grow out of control. - */ -#define DEBUG_EC_COMM_STATS -#ifdef DEBUG_EC_COMM_STATS -struct { - int total; - int errtimeout; - int errbusy; - int errunknown; - int errdatacrc; - int errcrc; - int errinval; -} comm_stats; - -#define INCR_COMM_STATS(var) (comm_stats.var++) -#else -#define INCR_COMM_STATS(var) -#endif - -/** - * Write a command on the EC-EC communication UART channel. - * - * @param command One of EC_CMD_*. - * @param data Packed structure with this layout: - * struct { - * struct { - * struct ec_host_request4 head; - * struct ec_params_* param; - * uint8_t crc8; - * } req; - * struct { - * struct ec_host_response4 head; - * struct ec_response_* info; - * uint8_t crc8; - * } resp; - * } __packed data; - * - * Where req is the request to be transmitted (head and crc8 are computed by - * this function), and resp is the response to be received (head integrity and - * crc8 are verified by this function). - * - * This format is required as the EC-EC UART is half-duplex, and all the - * transmitted data is received back, i.e. the master writes req, then reads - * req, followed by resp. - * - * When a command does not take parameters, param/crc8 must be omitted in - * tx structure. The same applies to rx structure if the response does not - * include a payload: info/crc8 must be omitted. - * - * @param req_len size of req.param (0 if no parameter is passed). - * @param resp_len size of resp.info (0 if no information is returned). - * @param timeout_us timeout in microseconds for the transaction to complete. - * - * @return - * - EC_SUCCESS on success. - * - EC_ERROR_TIMEOUT when remote end times out replying. - * - EC_ERROR_BUSY when UART is busy and cannot transmit currently. - * - EC_ERROR_CRC when the header or data CRC is invalid. - * - EC_ERROR_INVAL when the received header is invalid. - * - EC_ERROR_UNKNOWN on other error. - */ -static int write_command(uint16_t command, - uint8_t *data, int req_len, int resp_len, - int timeout_us) -{ - /* Sequence number. */ - static uint8_t cur_seq; - int ret; - int hascrc, response_seq; - - struct ec_host_request4 *request_header = (void *)data; - /* Request (TX) length is header + (data + crc8), response follows. */ - int tx_length = - sizeof(*request_header) + ((req_len > 0) ? (req_len + 1) : 0); - - struct ec_host_response4 *response_header = - (void *)&data[tx_length]; - /* RX length is TX length + response from slave. */ - int rx_length = tx_length + - sizeof(*request_header) + ((resp_len > 0) ? (resp_len + 1) : 0); - - /* - * Make sure there is a gap between each command, so that the slave - * can recover its state machine after each command. - * - * TODO(b:65697962): We can be much smarter than this, and record the - * last transaction time instead of just sleeping blindly. - */ - usleep(10*MSEC); - -#ifdef DEBUG_EC_COMM_STATS - if ((comm_stats.total % 128) == 0) { - CPRINTF("UART %d (T%dB%d,U%dC%dD%dI%d)\n", comm_stats.total, - comm_stats.errtimeout, comm_stats.errbusy, - comm_stats.errunknown, comm_stats.errcrc, - comm_stats.errdatacrc, comm_stats.errinval); - } -#endif - - cur_seq = (cur_seq + 1) & - (EC_PACKET4_0_SEQ_NUM_MASK >> EC_PACKET4_0_SEQ_NUM_SHIFT); - - memset(request_header, 0, sizeof(*request_header)); - /* fields0: leave seq_dup and is_response as 0. */ - request_header->fields0 = - EC_EC_HOSTCMD_VERSION | /* version */ - (cur_seq << EC_PACKET4_0_SEQ_NUM_SHIFT); /* seq_num */ - /* fields1: leave command_version as 0. */ - if (req_len > 0) - request_header->fields1 |= EC_PACKET4_1_DATA_CRC_PRESENT_MASK; - request_header->command = command; - request_header->data_len = req_len; - request_header->header_crc = - crc8((uint8_t *)request_header, sizeof(*request_header)-1); - if (req_len > 0) - data[sizeof(*request_header) + req_len] = - crc8(&data[sizeof(*request_header)], req_len); - - ret = uart_alt_pad_write_read((void *)data, tx_length, - (void *)data, rx_length, timeout_us); - - INCR_COMM_STATS(total); - -#ifdef EXTRA_DEBUG - CPRINTF("EC-EC ret=%d/%d\n", ret, rx_length); -#endif - - if (ret != rx_length) { - if (ret == -EC_ERROR_TIMEOUT) { - INCR_COMM_STATS(errtimeout); - return EC_ERROR_TIMEOUT; - } - - if (ret == -EC_ERROR_BUSY) { - INCR_COMM_STATS(errbusy); - return EC_ERROR_BUSY; - } - - INCR_COMM_STATS(errunknown); - return EC_ERROR_UNKNOWN; - } - - if (response_header->header_crc != - crc8((uint8_t *)response_header, - sizeof(*response_header)-1)) { - INCR_COMM_STATS(errcrc); - return EC_ERROR_CRC; - } - - hascrc = response_header->fields1 & EC_PACKET4_1_DATA_CRC_PRESENT_MASK; - response_seq = (response_header->fields0 & EC_PACKET4_0_SEQ_NUM_MASK) >> - EC_PACKET4_0_SEQ_NUM_SHIFT; - - /* - * Validate received header. - * Note that we _require_ data crc to be present if there is data to be - * read back, else we would not know how many bytes to read exactly. - */ - if ((response_header->fields0 & EC_PACKET4_0_STRUCT_VERSION_MASK) - != EC_EC_HOSTCMD_VERSION || - !(response_header->fields0 & - EC_PACKET4_0_IS_RESPONSE_MASK) || - response_seq != cur_seq || - (response_header->data_len > 0 && !hascrc) || - response_header->data_len != resp_len) { - INCR_COMM_STATS(errinval); - return EC_ERROR_INVAL; - } - - /* Check data CRC. */ - if (hascrc && data[rx_length - 1] != - crc8(&data[tx_length + sizeof(*request_header)], - resp_len)) { - INCR_COMM_STATS(errdatacrc); - return EC_ERROR_CRC; - } - - return EC_SUCCESS; -} - -/** - * handle error from write_command - * - * @param ret is return value from write_command - * @param request_result is data.resp.head.result (response result value) - * - * @return EC_RES_ERROR if ret is not EC_SUCCESS, else request_result. - */ -static int handle_error(const char *func, int ret, int request_result) -{ - if (ret != EC_SUCCESS) { - /* Do not print busy errors as they just spam the console. */ - if (ret != EC_ERROR_BUSY) - CPRINTF("%s: tx error %d\n", func, ret); - return EC_RES_ERROR; - } - - if (request_result != EC_RES_SUCCESS) - CPRINTF("%s: cmd error %d\n", func, ret); - - return request_result; -} - -#ifdef CONFIG_EC_EC_COMM_BATTERY -int ec_ec_master_base_get_dynamic_info(void) -{ - int ret; - struct { - struct { - struct ec_host_request4 head; - struct ec_params_battery_dynamic_info param; - uint8_t crc8; - } req; - struct { - struct ec_host_response4 head; - struct ec_response_battery_dynamic_info info; - uint8_t crc8; - } resp; - } __packed data; - - data.req.param.index = 0; - - ret = write_command(EC_CMD_BATTERY_GET_DYNAMIC, - (void *)&data, sizeof(data.req.param), - sizeof(data.resp.info), 15 * MSEC); - ret = handle_error(__func__, ret, data.resp.head.result); - if (ret != EC_RES_SUCCESS) - return ret; - -#ifdef EXTRA_DEBUG - CPRINTF("V: %d mV\n", data.resp.info.actual_voltage); - CPRINTF("I: %d mA\n", data.resp.info.actual_current); - CPRINTF("Remaining: %d mAh\n", data.resp.info.remaining_capacity); - CPRINTF("Cap-full: %d mAh\n", data.resp.info.full_capacity); - CPRINTF("Flags: %04x\n", data.resp.info.flags); - CPRINTF("V-desired: %d mV\n", data.resp.info.desired_voltage); - CPRINTF("I-desired: %d mA\n", data.resp.info.desired_current); -#endif - - memcpy(&battery_dynamic[BATT_IDX_BASE], &data.resp.info, - sizeof(battery_dynamic[BATT_IDX_BASE])); - return EC_RES_SUCCESS; -} - -int ec_ec_master_base_get_static_info(void) -{ - int ret; - struct { - struct { - struct ec_host_request4 head; - struct ec_params_battery_static_info param; - uint8_t crc8; - } req; - struct { - struct ec_host_response4 head; - struct ec_response_battery_static_info info; - uint8_t crc8; - } resp; - } __packed data; - - data.req.param.index = 0; - - ret = write_command(EC_CMD_BATTERY_GET_STATIC, - (void *)&data, sizeof(data.req.param), - sizeof(data.resp.info), 15 * MSEC); - ret = handle_error(__func__, ret, data.resp.head.result); - if (ret != EC_RES_SUCCESS) - return ret; - -#ifdef EXTRA_DEBUG - CPRINTF("Cap-design: %d mAh\n", data.resp.info.design_capacity); - CPRINTF("V-design: %d mV\n", data.resp.info.design_voltage); - CPRINTF("Manuf: %s\n", data.resp.info.manufacturer); - CPRINTF("Model: %s\n", data.resp.info.model); - CPRINTF("Serial: %s\n", data.resp.info.serial); - CPRINTF("Type: %s\n", data.resp.info.type); - CPRINTF("C-count: %d\n", data.resp.info.cycle_count); -#endif - - memcpy(&battery_static[BATT_IDX_BASE], &data.resp.info, - sizeof(battery_static[BATT_IDX_BASE])); - return EC_RES_SUCCESS; -} - -int ec_ec_master_base_charge_control(int max_current, - int otg_voltage, - int allow_charging) -{ - int ret; - struct { - struct { - struct ec_host_request4 head; - struct ec_params_charger_control ctrl; - uint8_t crc8; - } req; - struct { - struct ec_host_response4 head; - } resp; - } __packed data; - - data.req.ctrl.allow_charging = allow_charging; - data.req.ctrl.max_current = max_current; - data.req.ctrl.otg_voltage = otg_voltage; - - ret = write_command(EC_CMD_CHARGER_CONTROL, - (void *)&data, sizeof(data.req.ctrl), 0, 30 * MSEC); - - return handle_error(__func__, ret, data.resp.head.result); -} - -int ec_ec_master_hibernate(void) -{ - int ret; - struct { - struct { - struct ec_host_request4 head; - struct ec_params_reboot_ec param; - } req; - struct { - struct ec_host_response4 head; - } resp; - } __packed data; - - data.req.param.cmd = EC_REBOOT_HIBERNATE; - data.req.param.flags = 0; - - ret = write_command(EC_CMD_REBOOT_EC, - (void *)&data, sizeof(data.req.param), 0, 30 * MSEC); - - return handle_error(__func__, ret, data.resp.head.result); -} -#endif /* CONFIG_EC_EC_COMM_BATTERY */ diff --git a/common/ec_ec_comm_server.c b/common/ec_ec_comm_server.c new file mode 100644 index 0000000000..3c83253138 --- /dev/null +++ b/common/ec_ec_comm_server.c @@ -0,0 +1,323 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * EC-EC communication, task and functions for server. + */ + +#include "battery.h" +#include "charge_state.h" +#include "common.h" +#include "console.h" +#include "crc8.h" +#include "ec_commands.h" +#include "ec_ec_comm_server.h" +#include "extpower.h" +#include "hooks.h" +#include "hwtimer.h" +#include "queue.h" +#include "queue_policies.h" +#include "system.h" +#include "task.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) + +/* Print extra debugging information */ +#undef EXTRA_DEBUG + +/* Set if the client allows the server to charge the battery. */ +static int charging_allowed; + +/* + * Our command parameter buffer must be big enough to fit any command + * parameter, and crc byte. + */ +#define LARGEST_PARAMS_SIZE 8 + +BUILD_ASSERT(LARGEST_PARAMS_SIZE >= + sizeof(struct ec_params_battery_static_info)); +BUILD_ASSERT(LARGEST_PARAMS_SIZE >= + sizeof(struct ec_params_battery_dynamic_info)); +BUILD_ASSERT(LARGEST_PARAMS_SIZE >= sizeof(struct ec_params_charger_control)); + +#define COMMAND_BUFFER_PARAMS_SIZE (LARGEST_PARAMS_SIZE + 1) + +/* + * Maximum time needed to read a full command, commands are at most 17 bytes, so + * should not take more than 2ms to be sent at 115200 bps. + */ +#define COMMAND_TIMEOUT_US (5 * MSEC) + +void ec_ec_comm_server_written(struct consumer const *consumer, size_t count) +{ + task_wake(TASK_ID_ECCOMM); +} + +/* + * Discard all data from the input queue. + * + * Note that we always sleep for 1ms after clearing the queue, to make sure + * that we give enough time for the next byte to arrive. + */ +static void discard_queue(void) +{ + do { + queue_advance_head(&ec_ec_comm_server_input, + queue_count(&ec_ec_comm_server_input)); + usleep(1 * MSEC); + } while (queue_count(&ec_ec_comm_server_input) > 0); +} + +/* Write response to client. */ +static void write_response(uint16_t res, int seq, const void *data, int len) +{ + struct ec_host_response4 header; + uint8_t crc; + + header.fields0 = 4 | /* version */ + EC_PACKET4_0_IS_RESPONSE_MASK | /* is_response */ + (seq << EC_PACKET4_0_SEQ_NUM_SHIFT); /* seq_num */ + /* Set data_crc_present if there is data */ + header.fields1 = (len > 0) ? EC_PACKET4_1_DATA_CRC_PRESENT_MASK : 0; + header.result = res; + header.data_len = len; + header.reserved = 0; + header.header_crc = cros_crc8((uint8_t *)&header, sizeof(header) - 1); + QUEUE_ADD_UNITS(&ec_ec_comm_server_output, (uint8_t *)&header, + sizeof(header)); + + if (len > 0) { + QUEUE_ADD_UNITS(&ec_ec_comm_server_output, data, len); + crc = cros_crc8(data, len); + QUEUE_ADD_UNITS(&ec_ec_comm_server_output, &crc, sizeof(crc)); + } +} + +/* + * Read len bytes into buffer. Waiting up to COMMAND_TIMEOUT_US after start. + * + * Returns EC_SUCCESS or EC_ERROR_TIMEOUT. + */ +static int read_data(void *buffer, size_t len, uint32_t start) +{ + uint32_t delta; + + while (queue_count(&ec_ec_comm_server_input) < len) { + delta = __hw_clock_source_read() - start; + if (delta >= COMMAND_TIMEOUT_US) + return EC_ERROR_TIMEOUT; + + /* Every incoming byte wakes the task. */ + task_wait_event(COMMAND_TIMEOUT_US - delta); + } + + /* Fetch header */ + QUEUE_REMOVE_UNITS(&ec_ec_comm_server_input, buffer, len); + + return EC_SUCCESS; +} + +static void handle_cmd_reboot_ec(const struct ec_params_reboot_ec *params, + int data_len, int seq) +{ + int ret = EC_RES_SUCCESS; + + if (data_len != sizeof(*params)) { + ret = EC_RES_INVALID_COMMAND; + goto out; + } + + /* Only handle hibernate */ + if (params->cmd != EC_REBOOT_HIBERNATE) { + ret = EC_RES_INVALID_PARAM; + goto out; + } + + CPRINTS("Hibernating..."); + + system_hibernate(0, 0); + /* We should not be able to write back the response. */ + +out: + write_response(ret, seq, NULL, 0); +} + +#ifdef CONFIG_EC_EC_COMM_BATTERY +static void +handle_cmd_charger_control(const struct ec_params_charger_control *params, + int data_len, int seq) +{ + int ret = EC_RES_SUCCESS; + int prev_charging_allowed = charging_allowed; + + if (data_len != sizeof(*params)) { + ret = EC_RES_INVALID_COMMAND; + goto out; + } + + if (params->max_current >= 0) { + charge_set_output_current_limit(CHARGER_SOLO, 0, 0); + charge_set_input_current_limit( + MIN(MAX_CURRENT_MA, params->max_current), 0); + charging_allowed = params->allow_charging; + } else { + if (-params->max_current > MAX_OTG_CURRENT_MA || + params->otg_voltage > MAX_OTG_VOLTAGE_MV) { + ret = EC_RES_INVALID_PARAM; + goto out; + } + + /* Reset input current to default. */ + charge_set_input_current_limit( + CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT, 0); + /* Setup and enable "OTG". */ + charge_set_output_current_limit(CHARGER_SOLO, + -params->max_current, + params->otg_voltage); + charging_allowed = 0; + } + + if (prev_charging_allowed != charging_allowed) + hook_notify(HOOK_AC_CHANGE); + +out: + write_response(ret, seq, NULL, 0); +} + +/* + * On dual-battery server, we use the charging allowed signal from client to + * indicate whether external power is present. + * + * In most cases, this actually matches the external power status of the client + * (server battery charging when AC is connected, or discharging when server + * battery still has enough capacity), with one exception: when we do client to + * server battery charging (in this case the "external" power is the client). + */ +int extpower_is_present(void) +{ + return charging_allowed; +} +#endif + +void ec_ec_comm_server_task(void *u) +{ + struct ec_host_request4 header; + /* + * If CONFIG_HOSTCMD_ALIGNED is set, it is important that params is + * aligned on a 32-bit boundary. + */ + uint8_t __aligned(4) params[COMMAND_BUFFER_PARAMS_SIZE]; + unsigned int len, seq = 0, hascrc, cmdver; + uint32_t start; + + while (1) { + task_wait_event(-1); + + if (queue_count(&ec_ec_comm_server_input) == 0) + continue; + + /* We got some data, start timeout counter. */ + start = __hw_clock_source_read(); + + /* Wait for whole header to be available and read it. */ + if (read_data(&header, sizeof(header), start)) { + CPRINTS("%s timeout (header)", __func__); + goto discard; + } + +#ifdef EXTRA_DEBUG + CPRINTS("%s f0=%02x f1=%02x cmd=%02x, length=%d", __func__, + header.fields0, header.fields1, header.command, + header.data_len); +#endif + + /* Ignore response (we wrote that ourselves) */ + if (header.fields0 & EC_PACKET4_0_IS_RESPONSE_MASK) + goto discard; + + /* Validate version and crc. */ + if ((header.fields0 & EC_PACKET4_0_STRUCT_VERSION_MASK) != 4 || + header.header_crc != + cros_crc8((uint8_t *)&header, sizeof(header) - 1)) { + CPRINTS("%s header/crc error", __func__); + goto discard; + } + + len = header.data_len; + hascrc = header.fields1 & EC_PACKET4_1_DATA_CRC_PRESENT_MASK; + if (hascrc) + len += 1; + + /* + * Ignore commands that are too long to fit in our buffer. + */ + if (len > sizeof(params)) { + CPRINTS("%s len error (%d)", __func__, len); + /* Discard the data first, then write error back. */ + discard_queue(); + write_response(EC_RES_OVERFLOW, seq, NULL, 0); + goto discard; + } + + seq = (header.fields0 & EC_PACKET4_0_SEQ_NUM_MASK) >> + EC_PACKET4_0_SEQ_NUM_SHIFT; + + cmdver = header.fields1 & EC_PACKET4_1_COMMAND_VERSION_MASK; + + /* Wait for the rest of the data to be available and read it. */ + if (read_data(params, len, start)) { + CPRINTS("%s timeout (data)", __func__); + goto discard; + } + + /* Check data CRC */ + if (hascrc && params[len - 1] != cros_crc8(params, len - 1)) { + CPRINTS("%s data crc error", __func__); + write_response(EC_RES_INVALID_CHECKSUM, seq, NULL, 0); + goto discard; + } + + /* For now, all commands have version 0. */ + if (cmdver != 0) { + CPRINTS("%s bad command version", __func__); + write_response(EC_RES_INVALID_VERSION, seq, NULL, 0); + continue; + } + + switch (header.command) { +#ifdef CONFIG_EC_EC_COMM_BATTERY + case EC_CMD_BATTERY_GET_STATIC: + /* Note that we ignore the battery index parameter. */ + write_response(EC_RES_SUCCESS, seq, + &battery_static[BATT_IDX_MAIN], + sizeof(battery_static[BATT_IDX_MAIN])); + break; + case EC_CMD_BATTERY_GET_DYNAMIC: + /* Note that we ignore the battery index parameter. */ + write_response(EC_RES_SUCCESS, seq, + &battery_dynamic[BATT_IDX_MAIN], + sizeof(battery_dynamic[BATT_IDX_MAIN])); + break; + case EC_CMD_CHARGER_CONTROL: + handle_cmd_charger_control((void *)params, + header.data_len, seq); + break; +#endif + case EC_CMD_REBOOT_EC: + handle_cmd_reboot_ec((void *)params, header.data_len, + seq); + break; + default: + write_response(EC_RES_INVALID_COMMAND, seq, NULL, 0); + } + + continue; + discard: + /* + * Some error occurred: discard all data in the queue. + */ + discard_queue(); + } +} diff --git a/common/ec_ec_comm_slave.c b/common/ec_ec_comm_slave.c deleted file mode 100644 index ae845d58bc..0000000000 --- a/common/ec_ec_comm_slave.c +++ /dev/null @@ -1,328 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * EC-EC communication, task and functions for slave. - */ - -#include "common.h" -#include "battery.h" -#include "charge_state_v2.h" -#include "console.h" -#include "crc8.h" -#include "ec_commands.h" -#include "ec_ec_comm_slave.h" -#include "extpower.h" -#include "hwtimer.h" -#include "hooks.h" -#include "queue.h" -#include "queue_policies.h" -#include "system.h" -#include "task.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -/* Print extra debugging information */ -#undef EXTRA_DEBUG - -/* Set if the master allows the slave to charge the battery. */ -static int charging_allowed; - -/* - * Our command parameter buffer must be big enough to fit any command - * parameter, and crc byte. - */ -#define LARGEST_PARAMS_SIZE 8 - -BUILD_ASSERT(LARGEST_PARAMS_SIZE >= - sizeof(struct ec_params_battery_static_info)); -BUILD_ASSERT(LARGEST_PARAMS_SIZE >= - sizeof(struct ec_params_battery_dynamic_info)); -BUILD_ASSERT(LARGEST_PARAMS_SIZE >= - sizeof(struct ec_params_charger_control)); - -#define COMMAND_BUFFER_PARAMS_SIZE (LARGEST_PARAMS_SIZE + 1) - -/* - * Maximum time needed to read a full command, commands are at most 17 bytes, so - * should not take more than 2ms to be sent at 115200 bps. - */ -#define COMMAND_TIMEOUT_US (5 * MSEC) - - -void ec_ec_comm_slave_written(struct consumer const *consumer, size_t count) -{ - task_wake(TASK_ID_ECCOMM); -} - -/* - * Discard all data from the input queue. - * - * Note that we always sleep for 1ms after clearing the queue, to make sure - * that we give enough time for the next byte to arrive. - */ -static void discard_queue(void) -{ - do { - queue_advance_head(&ec_ec_comm_slave_input, - queue_count(&ec_ec_comm_slave_input)); - usleep(1 * MSEC); - } while (queue_count(&ec_ec_comm_slave_input) > 0); -} - -/* Write response to master. */ -static void write_response(uint16_t res, int seq, const void *data, int len) -{ - struct ec_host_response4 header; - uint8_t crc; - - header.fields0 = - 4 | /* version */ - EC_PACKET4_0_IS_RESPONSE_MASK | /* is_response */ - (seq << EC_PACKET4_0_SEQ_NUM_SHIFT); /* seq_num */ - /* Set data_crc_present if there is data */ - header.fields1 = (len > 0) ? EC_PACKET4_1_DATA_CRC_PRESENT_MASK : 0; - header.result = res; - header.data_len = len; - header.reserved = 0; - header.header_crc = - crc8((uint8_t *)&header, sizeof(header)-1); - QUEUE_ADD_UNITS(&ec_ec_comm_slave_output, - (uint8_t *)&header, sizeof(header)); - - if (len > 0) { - QUEUE_ADD_UNITS(&ec_ec_comm_slave_output, data, len); - crc = crc8(data, len); - QUEUE_ADD_UNITS(&ec_ec_comm_slave_output, &crc, sizeof(crc)); - } -} - -/* - * Read len bytes into buffer. Waiting up to COMMAND_TIMEOUT_US after start. - * - * Returns EC_SUCCESS or EC_ERROR_TIMEOUT. - */ -static int read_data(void *buffer, size_t len, uint32_t start) -{ - uint32_t delta; - - while (queue_count(&ec_ec_comm_slave_input) < len) { - delta = __hw_clock_source_read() - start; - if (delta >= COMMAND_TIMEOUT_US) - return EC_ERROR_TIMEOUT; - - /* Every incoming byte wakes the task. */ - task_wait_event(COMMAND_TIMEOUT_US - delta); - } - - /* Fetch header */ - QUEUE_REMOVE_UNITS(&ec_ec_comm_slave_input, buffer, len); - - return EC_SUCCESS; -} - -static void handle_cmd_reboot_ec( - const struct ec_params_reboot_ec *params, - int data_len, int seq) -{ - int ret = EC_RES_SUCCESS; - - if (data_len != sizeof(*params)) { - ret = EC_RES_INVALID_COMMAND; - goto out; - } - - /* Only handle hibernate */ - if (params->cmd != EC_REBOOT_HIBERNATE) { - ret = EC_RES_INVALID_PARAM; - goto out; - } - - CPRINTS("Hibernating..."); - - system_hibernate(0, 0); - /* We should not be able to write back the response. */ - -out: - write_response(ret, seq, NULL, 0); -} - -#ifdef CONFIG_EC_EC_COMM_BATTERY -static void handle_cmd_charger_control( - const struct ec_params_charger_control *params, - int data_len, int seq) -{ - int ret = EC_RES_SUCCESS; - int prev_charging_allowed = charging_allowed; - - if (data_len != sizeof(*params)) { - ret = EC_RES_INVALID_COMMAND; - goto out; - } - - if (params->max_current >= 0) { - charge_set_output_current_limit(CHARGER_SOLO, 0, 0); - charge_set_input_current_limit( - MIN(MAX_CURRENT_MA, params->max_current), 0); - charging_allowed = params->allow_charging; - } else { - if (-params->max_current > MAX_OTG_CURRENT_MA || - params->otg_voltage > MAX_OTG_VOLTAGE_MV) { - ret = EC_RES_INVALID_PARAM; - goto out; - } - - /* Reset input current to minimum. */ - charge_set_input_current_limit(CONFIG_CHARGER_INPUT_CURRENT, 0); - /* Setup and enable "OTG". */ - charge_set_output_current_limit(CHARGER_SOLO, - -params->max_current, - params->otg_voltage); - charging_allowed = 0; - } - - if (prev_charging_allowed != charging_allowed) - hook_notify(HOOK_AC_CHANGE); - -out: - write_response(ret, seq, NULL, 0); -} - -/* - * On dual-battery slave, we use the charging allowed signal from master to - * indicate whether external power is present. - * - * In most cases, this actually matches the external power status of the master - * (slave battery charging when AC is connected, or discharging when slave - * battery still has enough capacity), with one exception: when we do master to - * slave battery charging (in this case the "external" power is the master). - */ -int extpower_is_present(void) -{ - return charging_allowed; -} -#endif - -void ec_ec_comm_slave_task(void *u) -{ - struct ec_host_request4 header; - /* - * If CONFIG_HOSTCMD_ALIGNED is set, it is important that params is - * aligned on a 32-bit boundary. - */ - uint8_t __aligned(4) params[COMMAND_BUFFER_PARAMS_SIZE]; - unsigned int len, seq = 0, hascrc, cmdver; - uint32_t start; - - while (1) { - task_wait_event(-1); - - if (queue_count(&ec_ec_comm_slave_input) == 0) - continue; - - /* We got some data, start timeout counter. */ - start = __hw_clock_source_read(); - - /* Wait for whole header to be available and read it. */ - if (read_data(&header, sizeof(header), start)) { - CPRINTS("%s timeout (header)", __func__); - goto discard; - } - -#ifdef EXTRA_DEBUG - CPRINTS("%s f0=%02x f1=%02x cmd=%02x, length=%d", __func__, - header.fields0, header.fields1, - header.command, header.data_len); -#endif - - /* Ignore response (we wrote that ourselves) */ - if (header.fields0 & EC_PACKET4_0_IS_RESPONSE_MASK) - goto discard; - - /* Validate version and crc. */ - if ((header.fields0 & EC_PACKET4_0_STRUCT_VERSION_MASK) != 4 || - header.header_crc != - crc8((uint8_t *)&header, sizeof(header)-1)) { - CPRINTS("%s header/crc error", __func__); - goto discard; - } - - len = header.data_len; - hascrc = header.fields1 & EC_PACKET4_1_DATA_CRC_PRESENT_MASK; - if (hascrc) - len += 1; - - /* - * Ignore commands that are too long to fit in our buffer. - */ - if (len > sizeof(params)) { - CPRINTS("%s len error (%d)", __func__, len); - /* Discard the data first, then write error back. */ - discard_queue(); - write_response(EC_RES_OVERFLOW, seq, NULL, 0); - goto discard; - } - - seq = (header.fields0 & EC_PACKET4_0_SEQ_NUM_MASK) >> - EC_PACKET4_0_SEQ_NUM_SHIFT; - - cmdver = header.fields1 & EC_PACKET4_1_COMMAND_VERSION_MASK; - - /* Wait for the rest of the data to be available and read it. */ - if (read_data(params, len, start)) { - CPRINTS("%s timeout (data)", __func__); - goto discard; - } - - /* Check data CRC */ - if (hascrc && params[len-1] != crc8(params, len-1)) { - CPRINTS("%s data crc error", __func__); - write_response(EC_RES_INVALID_CHECKSUM, seq, NULL, 0); - goto discard; - } - - /* For now, all commands have version 0. */ - if (cmdver != 0) { - CPRINTS("%s bad command version", __func__); - write_response(EC_RES_INVALID_VERSION, seq, NULL, 0); - continue; - } - - switch (header.command) { -#ifdef CONFIG_EC_EC_COMM_BATTERY - case EC_CMD_BATTERY_GET_STATIC: - /* Note that we ignore the battery index parameter. */ - write_response(EC_RES_SUCCESS, seq, - &battery_static[BATT_IDX_MAIN], - sizeof(battery_static[BATT_IDX_MAIN])); - break; - case EC_CMD_BATTERY_GET_DYNAMIC: - /* Note that we ignore the battery index parameter. */ - write_response(EC_RES_SUCCESS, seq, - &battery_dynamic[BATT_IDX_MAIN], - sizeof(battery_dynamic[BATT_IDX_MAIN])); - break; - case EC_CMD_CHARGER_CONTROL: - handle_cmd_charger_control((void *)params, - header.data_len, seq); - break; -#endif - case EC_CMD_REBOOT_EC: - handle_cmd_reboot_ec((void *)params, - header.data_len, seq); - break; - default: - write_response(EC_RES_INVALID_COMMAND, seq, - NULL, 0); - } - - continue; -discard: - /* - * Some error occurred: discard all data in the queue. - */ - discard_queue(); - } -} diff --git a/common/ec_features.c b/common/ec_features.c index 5abe121591..9fb257d204 100644 --- a/common/ec_features.c +++ b/common/ec_features.c @@ -1,122 +1,125 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Present Chrome EC device features to the outside world */ +#include "board_config.h" #include "common.h" #include "config.h" #include "console.h" #include "ec_commands.h" -#include "board_config.h" +#include "motion_sense.h" +/* LCOV_EXCL_START */ uint32_t get_feature_flags0(void) { uint32_t result = 0 #ifdef CONFIG_FW_LIMITED_IMAGE - | EC_FEATURE_MASK_0(EC_FEATURE_LIMITED) + | EC_FEATURE_MASK_0(EC_FEATURE_LIMITED) #endif -#ifdef CONFIG_FLASH - | EC_FEATURE_MASK_0(EC_FEATURE_FLASH) +#ifdef CONFIG_FLASH_CROS + | EC_FEATURE_MASK_0(EC_FEATURE_FLASH) #endif #ifdef CONFIG_FANS - | EC_FEATURE_MASK_0(EC_FEATURE_PWM_FAN) + | EC_FEATURE_MASK_0(EC_FEATURE_PWM_FAN) #endif #ifdef CONFIG_KEYBOARD_BACKLIGHT - | EC_FEATURE_MASK_0(EC_FEATURE_PWM_KEYB) + | EC_FEATURE_MASK_0(EC_FEATURE_PWM_KEYB) #endif #ifdef HAS_TASK_LIGHTBAR - | EC_FEATURE_MASK_0(EC_FEATURE_LIGHTBAR) + | EC_FEATURE_MASK_0(EC_FEATURE_LIGHTBAR) #endif #ifdef CONFIG_LED_COMMON - | EC_FEATURE_MASK_0(EC_FEATURE_LED) + | EC_FEATURE_MASK_0(EC_FEATURE_LED) #endif #ifdef HAS_TASK_MOTIONSENSE - | EC_FEATURE_MASK_0(EC_FEATURE_MOTION_SENSE) + | EC_FEATURE_MASK_0(EC_FEATURE_MOTION_SENSE) #endif #ifdef HAS_TASK_KEYSCAN - | EC_FEATURE_MASK_0(EC_FEATURE_KEYB) + | EC_FEATURE_MASK_0(EC_FEATURE_KEYB) #endif #ifdef CONFIG_PSTORE - | EC_FEATURE_MASK_0(EC_FEATURE_PSTORE) + | EC_FEATURE_MASK_0(EC_FEATURE_PSTORE) #endif #ifdef CONFIG_HOSTCMD_X86 - | EC_FEATURE_MASK_0(EC_FEATURE_PORT80) + | EC_FEATURE_MASK_0(EC_FEATURE_PORT80) #endif #ifdef CONFIG_TEMP_SENSOR - | EC_FEATURE_MASK_0(EC_FEATURE_THERMAL) + | EC_FEATURE_MASK_0(EC_FEATURE_THERMAL) #endif #if (defined CONFIG_BACKLIGHT_LID) || (defined CONFIG_BACKLIGHT_REQ_GPIO) - | EC_FEATURE_MASK_0(EC_FEATURE_BKLIGHT_SWITCH) + | EC_FEATURE_MASK_0(EC_FEATURE_BKLIGHT_SWITCH) #endif #ifdef CONFIG_WIRELESS - | EC_FEATURE_MASK_0(EC_FEATURE_WIFI_SWITCH) + | EC_FEATURE_MASK_0(EC_FEATURE_WIFI_SWITCH) #endif #ifdef CONFIG_HOSTCMD_EVENTS - | EC_FEATURE_MASK_0(EC_FEATURE_HOST_EVENTS) + | EC_FEATURE_MASK_0(EC_FEATURE_HOST_EVENTS) #endif #ifdef CONFIG_COMMON_GPIO - | EC_FEATURE_MASK_0(EC_FEATURE_GPIO) + | EC_FEATURE_MASK_0(EC_FEATURE_GPIO) #endif -#ifdef CONFIG_I2C_MASTER - | EC_FEATURE_MASK_0(EC_FEATURE_I2C) +#ifdef CONFIG_I2C_CONTROLLER + | EC_FEATURE_MASK_0(EC_FEATURE_I2C) #endif #ifdef CONFIG_CHARGER - | EC_FEATURE_MASK_0(EC_FEATURE_CHARGER) + | EC_FEATURE_MASK_0(EC_FEATURE_CHARGER) #endif #if (defined CONFIG_BATTERY) - | EC_FEATURE_MASK_0(EC_FEATURE_BATTERY) + | EC_FEATURE_MASK_0(EC_FEATURE_BATTERY) #endif #ifdef CONFIG_BATTERY_SMART - | EC_FEATURE_MASK_0(EC_FEATURE_SMART_BATTERY) + | EC_FEATURE_MASK_0(EC_FEATURE_SMART_BATTERY) #endif #ifdef CONFIG_AP_HANG_DETECT - | EC_FEATURE_MASK_0(EC_FEATURE_HANG_DETECT) + | EC_FEATURE_MASK_0(EC_FEATURE_HANG_DETECT) #endif #if 0 | EC_FEATURE_MASK_0(EC_FEATURE_PMU) /* Obsolete */ #endif #ifdef CONFIG_HOSTCMD_PD - | EC_FEATURE_MASK_0(EC_FEATURE_SUB_MCU) + | EC_FEATURE_MASK_0(EC_FEATURE_SUB_MCU) #endif -#ifdef CONFIG_CHARGE_MANAGER - | EC_FEATURE_MASK_0(EC_FEATURE_USB_PD) +#if defined(CONFIG_CHARGE_MANAGER) && defined(CONFIG_USB_POWER_DELIVERY) + | EC_FEATURE_MASK_0(EC_FEATURE_USB_PD) #endif #ifdef CONFIG_ACCEL_FIFO - | EC_FEATURE_MASK_0(EC_FEATURE_MOTION_SENSE_FIFO) + | EC_FEATURE_MASK_0(EC_FEATURE_MOTION_SENSE_FIFO) #endif #ifdef CONFIG_VSTORE - | EC_FEATURE_MASK_0(EC_FEATURE_VSTORE) + | EC_FEATURE_MASK_0(EC_FEATURE_VSTORE) #endif #ifdef CONFIG_USB_MUX_VIRTUAL - | EC_FEATURE_MASK_0(EC_FEATURE_USBC_SS_MUX_VIRTUAL) + | EC_FEATURE_MASK_0(EC_FEATURE_USBC_SS_MUX_VIRTUAL) #endif #ifdef CONFIG_HOSTCMD_RTC - | EC_FEATURE_MASK_0(EC_FEATURE_RTC) + | EC_FEATURE_MASK_0(EC_FEATURE_RTC) #endif #ifdef CONFIG_SPI_FP_PORT - | EC_FEATURE_MASK_0(EC_FEATURE_FINGERPRINT) + | EC_FEATURE_MASK_0(EC_FEATURE_FINGERPRINT) #endif #ifdef HAS_TASK_CENTROIDING - | EC_FEATURE_MASK_0(EC_FEATURE_TOUCHPAD) + | EC_FEATURE_MASK_0(EC_FEATURE_TOUCHPAD) #endif #if defined(HAS_TASK_RWSIG) || defined(HAS_TASK_RWSIG_RO) - | EC_FEATURE_MASK_0(EC_FEATURE_RWSIG) + | EC_FEATURE_MASK_0(EC_FEATURE_RWSIG) #endif #ifdef CONFIG_DEVICE_EVENT - | EC_FEATURE_MASK_0(EC_FEATURE_DEVICE_EVENT) + | EC_FEATURE_MASK_0(EC_FEATURE_DEVICE_EVENT) #endif ; return board_override_feature_flags0(result); } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ uint32_t get_feature_flags1(void) { - uint32_t result = EC_FEATURE_MASK_1(EC_FEATURE_UNIFIED_WAKE_MASKS) -#ifdef CONFIG_HOST_EVENT64 - | EC_FEATURE_MASK_1(EC_FEATURE_HOST_EVENT64) -#endif + uint32_t result = + EC_FEATURE_MASK_1(EC_FEATURE_UNIFIED_WAKE_MASKS) | + EC_FEATURE_MASK_1(EC_FEATURE_HOST_EVENT64) #ifdef CONFIG_EXTERNAL_STORAGE | EC_FEATURE_MASK_1(EC_FEATURE_EXEC_IN_RAM) #endif @@ -127,7 +130,10 @@ uint32_t get_feature_flags1(void) | EC_FEATURE_MASK_1(EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS) #endif #if defined(CONFIG_LID_ANGLE) && defined(CONFIG_TABLET_MODE) - | EC_FEATURE_MASK_1(EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS) + | (sensor_board_is_lid_angle_available() ? + EC_FEATURE_MASK_1( + EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS) : + 0) #endif #ifdef CONFIG_VBOOT_EFS2 | EC_FEATURE_MASK_1(EC_FEATURE_EFS2) @@ -137,10 +143,35 @@ uint32_t get_feature_flags1(void) #endif #ifdef CHIP_ISH | EC_FEATURE_MASK_1(EC_FEATURE_ISH) +#endif +#ifdef CONFIG_USB_PD_TCPMV2 + | EC_FEATURE_MASK_1(EC_FEATURE_TYPEC_CMD) +#endif +#ifdef CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY + | EC_FEATURE_MASK_1(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY) +#endif +#ifdef CONFIG_USB_MUX_AP_ACK_REQUEST + | EC_FEATURE_MASK_1(EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK) +#endif +#ifdef CONFIG_POWER_S4_RESIDENCY + | EC_FEATURE_MASK_1(EC_FEATURE_S4_RESIDENCY) +#endif +#ifdef CONFIG_USB_MUX_AP_CONTROL + | EC_FEATURE_MASK_1(EC_FEATURE_TYPEC_AP_MUX_SET) +#endif +#ifdef CONFIG_USB_PD_VDM_AP_CONTROL + | EC_FEATURE_MASK_1(EC_FEATURE_TYPEC_AP_VDM_SEND) +#endif +#ifdef CONFIG_SYSTEM_SAFE_MODE + | EC_FEATURE_MASK_1(EC_FEATURE_SYSTEM_SAFE_MODE) +#endif +#ifdef CONFIG_DEBUG_ASSERT_REBOOTS + | EC_FEATURE_MASK_1(EC_FEATURE_ASSERT_REBOOTS) #endif ; return board_override_feature_flags1(result); } +/* LCOV_EXCL_STOP */ __overridable uint32_t board_override_feature_flags0(uint32_t flags0) { @@ -152,7 +183,7 @@ __overridable uint32_t board_override_feature_flags1(uint32_t flags1) return flags1; } -static int cc_feat(int argc, char **argv) +static int cc_feat(int argc, const char **argv) { ccprintf(" 0-31: 0x%08x\n", get_feature_flags0()); ccprintf("32-63: 0x%08x\n", get_feature_flags1()); diff --git a/common/espi.c b/common/espi.c index 0904f102d7..f57e13cf76 100644 --- a/common/espi.c +++ b/common/espi.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,13 +6,12 @@ /* eSPI common functionality for Chrome EC */ #include "common.h" +#include "espi.h" #include "gpio.h" #include "registers.h" -#include "espi.h" #include "timer.h" #include "util.h" - const char *espi_vw_names[] = { "VW_SLP_S3_L", "VW_SLP_S4_L", @@ -26,7 +25,7 @@ const char *espi_vw_names[] = { "VW_ERROR_FATAL", "VW_ERROR_NON_FATAL", /* Merge bit 3/0 into one signal. Need to set them simultaneously */ - "VW_SLAVE_BTLD_STATUS_DONE", + "VW_PERIPHERAL_BTLD_STATUS_DONE", "VW_SCI_L", "VW_SMI_L", "VW_RCIN_L", @@ -41,7 +40,6 @@ const char *espi_vw_names[] = { }; BUILD_ASSERT(ARRAY_SIZE(espi_vw_names) == VW_SIGNAL_COUNT); - const char *espi_vw_get_wire_name(enum espi_vw_signal signal) { if (espi_signal_is_vw(signal)) @@ -50,7 +48,6 @@ const char *espi_vw_get_wire_name(enum espi_vw_signal signal) return NULL; } - int espi_signal_is_vw(int signal) { return ((signal >= VW_SIGNAL_START) && (signal < VW_SIGNAL_END)); diff --git a/common/event_log.c b/common/event_log.c index 994967664c..f748b3d9a7 100644 --- a/common/event_log.c +++ b/common/event_log.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,9 +13,9 @@ /* Event log FIFO */ #define UNIT_SIZE sizeof(struct event_log_entry) -#define UNIT_COUNT (CONFIG_EVENT_LOG_SIZE/UNIT_SIZE) -#define UNIT_COUNT_MASK (UNIT_COUNT - 1) -static struct event_log_entry __bss_slow log_events[UNIT_COUNT]; +#define UNIT_COUNT (CONFIG_EVENT_LOG_SIZE / UNIT_SIZE) +#define UNIT_COUNT_MASK (UNIT_COUNT - 1) +static struct event_log_entry log_events[UNIT_COUNT]; BUILD_ASSERT(POWER_OF_TWO(UNIT_COUNT)); /* @@ -42,31 +42,32 @@ static size_t log_tail; static size_t log_tail_next; /* Size of one FIFO entry */ -#define ENTRY_SIZE(payload_sz) (1+DIV_ROUND_UP((payload_sz), UNIT_SIZE)) +#define ENTRY_SIZE(payload_sz) (1 + DIV_ROUND_UP((payload_sz), UNIT_SIZE)) -void log_add_event(uint8_t type, uint8_t size, uint16_t data, - void *payload, uint32_t timestamp) +void log_add_event(uint8_t type, uint8_t size, uint16_t data, void *payload, + uint32_t timestamp) { struct event_log_entry *r; size_t payload_size = EVENT_LOG_SIZE(size); size_t total_size = ENTRY_SIZE(payload_size); size_t current_tail, first; + uint32_t lock_key; /* --- critical section : reserve queue space --- */ - interrupt_disable(); + lock_key = irq_lock(); current_tail = log_tail_next; log_tail_next = current_tail + total_size; - interrupt_enable(); + irq_unlock(lock_key); /* --- end of critical section --- */ /* Out of space : discard the oldest entry */ while ((UNIT_COUNT - (current_tail - log_head)) < total_size) { struct event_log_entry *oldest; /* --- critical section : atomically free-up space --- */ - interrupt_disable(); + lock_key = irq_lock(); oldest = log_events + (log_head & UNIT_COUNT_MASK); log_head += ENTRY_SIZE(EVENT_LOG_SIZE(oldest->size)); - interrupt_enable(); + irq_unlock(lock_key); /* --- end of critical section --- */ } @@ -77,13 +78,13 @@ void log_add_event(uint8_t type, uint8_t size, uint16_t data, r->size = size; r->data = data; /* copy the payload into the FIFO */ - first = MIN(total_size - 1, (UNIT_COUNT - - (current_tail & UNIT_COUNT_MASK)) - 1); + first = MIN(total_size - 1, + (UNIT_COUNT - (current_tail & UNIT_COUNT_MASK)) - 1); if (first) memcpy(r->payload, payload, first * UNIT_SIZE); if (first < total_size - 1) memcpy(log_events, ((uint8_t *)payload) + first * UNIT_SIZE, - (total_size - first) * UNIT_SIZE); + (total_size - first) * UNIT_SIZE); /* mark the entry available in the queue if nobody is behind us */ if (current_tail == log_tail) log_tail = log_tail_next; @@ -95,6 +96,7 @@ int log_dequeue_event(struct event_log_entry *r) unsigned int total_size, first; struct event_log_entry *entry; size_t current_head; + uint32_t lock_key; retry: current_head = log_head; @@ -110,16 +112,16 @@ int log_dequeue_event(struct event_log_entry *r) first = MIN(total_size, UNIT_COUNT - (current_head & UNIT_COUNT_MASK)); memcpy(r, entry, first * UNIT_SIZE); if (first < total_size) - memcpy(r + first, log_events, (total_size-first) * UNIT_SIZE); + memcpy(r + first, log_events, (total_size - first) * UNIT_SIZE); /* --- critical section : remove the entry from the queue --- */ - interrupt_disable(); + lock_key = irq_lock(); if (log_head != current_head) { /* our entry was thrown away */ - interrupt_enable(); + irq_unlock(lock_key); goto retry; } log_head += total_size; - interrupt_enable(); + irq_unlock(lock_key); /* --- end of critical section --- */ /* fixup the timestamp : number of milliseconds in the past */ @@ -132,10 +134,10 @@ int log_dequeue_event(struct event_log_entry *r) /* * Display TPM event logs. */ -static int command_dlog(int argc, char **argv) +static int command_dlog(int argc, const char **argv) { size_t log_cur; - const uint8_t * const log_events_end = + const uint8_t *const log_events_end = (uint8_t *)&log_events[UNIT_COUNT]; if (argc > 1) { @@ -162,7 +164,7 @@ static int command_dlog(int argc, char **argv) log_cur += ENTRY_SIZE(payload_bytes); ccprintf("%10d %4d 0x%04X %4d ", r->timestamp, r->type, - r->data, payload_bytes); + r->data, payload_bytes); /* display payload if exists */ payload = r->payload; @@ -177,8 +179,6 @@ static int command_dlog(int argc, char **argv) } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(dlog, - command_dlog, - "[clear]", +DECLARE_CONSOLE_COMMAND(dlog, command_dlog, "[clear]", "Display/clear TPM event logs"); #endif diff --git a/common/extpower_common.c b/common/extpower_common.c index 453bab3a2c..9f0947a529 100644 --- a/common/extpower_common.c +++ b/common/extpower_common.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,6 +7,10 @@ #include "hooks.h" #include "host_command.h" +__overridable void board_check_extpower(void) +{ +} + void extpower_handle_update(int is_present) { uint8_t *memmap_batt_flags; diff --git a/common/extpower_gpio.c b/common/extpower_gpio.c index 4cdcb834f8..bfb9349e0e 100644 --- a/common/extpower_gpio.c +++ b/common/extpower_gpio.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,7 +14,7 @@ static int debounced_extpower_presence; -int extpower_is_present(void) +test_mockable int extpower_is_present(void) { return debounced_extpower_presence; } @@ -31,7 +31,6 @@ static void extpower_deferred(void) debounced_extpower_presence = extpower_presence; extpower_handle_update(extpower_presence); - } DECLARE_DEFERRED(extpower_deferred); @@ -39,7 +38,7 @@ void extpower_interrupt(enum gpio_signal signal) { /* Trigger deferred notification of external power change */ hook_call_deferred(&extpower_deferred_data, - CONFIG_EXTPOWER_DEBOUNCE_MS * MSEC); + CONFIG_EXTPOWER_DEBOUNCE_MS * MSEC); } static void extpower_init(void) diff --git a/common/fan.c b/common/fan.c index 398a149268..945c16952a 100644 --- a/common/fan.c +++ b/common/fan.c @@ -1,11 +1,11 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Basic Chrome OS fan control */ -#include "assert.h" +#include "builtin/assert.h" #include "chipset.h" #include "common.h" #include "console.h" @@ -56,22 +56,80 @@ void fan_set_count(int count) * Convert the percentage to a target RPM. We can't simply scale all * the way down to zero because most fans won't turn that slowly, so * we'll map [1,100] => [FAN_MIN,FAN_MAX], and [0] => "off". -*/ -int fan_percent_to_rpm(int fan, int pct) + */ +int fan_percent_to_rpm(int fan_index, int temp_ratio) { int rpm, max, min; - if (!pct) { + if (temp_ratio <= 0) { rpm = 0; } else { - min = fans[fan].rpm->rpm_min; - max = fans[fan].rpm->rpm_max; - rpm = ((pct - 1) * max + (100 - pct) * min) / 99; + min = fans[fan_index].rpm->rpm_min; + max = fans[fan_index].rpm->rpm_max; + rpm = ((temp_ratio - 1) * max + (100 - temp_ratio) * min) / 99; + } + + return rpm; +} +#endif /* CONFIG_FAN_RPM_CUSTOM */ + +int temp_ratio_to_rpm_hysteresis(const struct fan_step_1_1 *fan_table, + int num_fan_levels, int fan_index, + int temp_ratio, void (*on_change)(void)) +{ + static int previous_temp_ratio; + const int previous_rpm = fan_get_rpm_target(FAN_CH(fan_index)); + int rpm; + + if (temp_ratio <= fan_table[0].decreasing_temp_ratio_threshold) { + rpm = 0; + } else if (previous_rpm == 0 && + temp_ratio < fan_table[0].increasing_temp_ratio_threshold) { + rpm = 0; + } else { + /* + * Comparing temp_ratio and previous_temp_ratio, trichotomy: + * 1. decreasing path. (check the decreasing threshold) + * 2. increasing path. (check the increasing threshold) + * 3. invariant path. (return the current RPM) + */ + if (temp_ratio < previous_temp_ratio) { + int i = num_fan_levels - 1; + + while (i > 0 && + fan_table[i].decreasing_temp_ratio_threshold >= + temp_ratio) { + i--; + } + rpm = fan_table[i].rpm; + } else if (temp_ratio > previous_temp_ratio) { + int i = 0; + + while (i < num_fan_levels && + fan_table[i].increasing_temp_ratio_threshold <= + temp_ratio) { + i++; + } + if (i > 0) { + i--; + } + rpm = fan_table[i].rpm; + } else { + rpm = previous_rpm; + } + } + + previous_temp_ratio = temp_ratio; + + if (rpm != previous_rpm) { + cprints(CC_THERMAL, "Setting fan %d RPM to %d", fan_index, rpm); + if (on_change) { + on_change(); + } } return rpm; } -#endif /* CONFIG_FAN_RPM_CUSTOM */ /* The thermal task will only call this function with pct in [0,100]. */ test_mockable void fan_set_percent_needed(int fan, int pct) @@ -94,8 +152,7 @@ test_mockable void fan_set_percent_needed(int fan, int pct) /* If we want to turn and the fans are currently significantly below * the minimum turning speed, we should turn at least as fast as the * necessary start speed instead. */ - if (new_rpm && - actual_rpm < fans[fan].rpm->rpm_min * 9 / 10 && + if (new_rpm && actual_rpm < fans[fan].rpm->rpm_min * 9 / 10 && new_rpm < fans[fan].rpm->rpm_start) new_rpm = fans[fan].rpm->rpm_start; @@ -137,7 +194,7 @@ static void set_duty_cycle(int fan, int percent) /*****************************************************************************/ /* Console commands */ -static int cc_fanauto(int argc, char **argv) +static int cc_fanauto(int argc, const char **argv) { char *e; int fan = 0; @@ -157,8 +214,7 @@ static int cc_fanauto(int argc, char **argv) set_thermal_control_enabled(fan, 1); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(fanauto, cc_fanauto, - "{fan}", +DECLARE_CONSOLE_COMMAND(fanauto, cc_fanauto, "{fan}", "Enable thermal fan control"); /* Return 0 for off, 1 for on, -1 for unknown */ @@ -176,28 +232,27 @@ static int is_powered(int fan) return is_pgood; } -static int cc_faninfo(int argc, char **argv) +static int cc_faninfo(int argc, const char **argv) { - static const char * const human_status[] = { - "not spinning", "changing", "locked", "frustrated" - }; + static const char *const human_status[] = { "not spinning", "changing", + "locked", "frustrated" }; int tmp, is_pgood; int fan; char leader[20] = ""; for (fan = 0; fan < fan_count; fan++) { if (fan_count > 1) - snprintf(leader, sizeof(leader), "Fan %d ", fan); + if (snprintf(leader, sizeof(leader), "Fan %d ", fan) < + 0) + leader[0] = '\0'; if (fan) ccprintf("\n"); ccprintf("%sActual: %4d rpm\n", leader, fan_get_rpm_actual(FAN_CH(fan))); ccprintf("%sTarget: %4d rpm\n", leader, fan_get_rpm_target(FAN_CH(fan))); - ccprintf("%sDuty: %d%%\n", leader, - fan_get_duty(FAN_CH(fan))); + ccprintf("%sDuty: %d%%\n", leader, fan_get_duty(FAN_CH(fan))); tmp = fan_get_status(FAN_CH(fan)); - ccprintf("%sStatus: %d (%s)\n", leader, - tmp, human_status[tmp]); + ccprintf("%sStatus: %d (%s)\n", leader, tmp, human_status[tmp]); ccprintf("%sMode: %s\n", leader, fan_get_rpm_mode(FAN_CH(fan)) ? "rpm" : "duty"); ccprintf("%sAuto: %s\n", leader, @@ -212,12 +267,11 @@ static int cc_faninfo(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(faninfo, cc_faninfo, - NULL, - "Print fan info"); +DECLARE_CONSOLE_COMMAND(faninfo, cc_faninfo, NULL, "Print fan info"); -static int cc_fanset(int argc, char **argv) +static int cc_fanset(int argc, const char **argv) { + const char *rpm_str; int rpm; char *e; int fan = 0; @@ -228,22 +282,25 @@ static int cc_fanset(int argc, char **argv) } if (fan_count > 1) { - if (argc < 2) { + if (argc < 3) { ccprintf("fan number is required as the first arg\n"); return EC_ERROR_PARAM_COUNT; } + } + + if (argc == 3) { fan = strtoi(argv[1], &e, 0); if (*e || fan >= fan_count) return EC_ERROR_PARAM1; - argc--; - argv++; - } - - if (argc < 2) + rpm_str = argv[2]; + } else if (argc == 2) { + rpm_str = argv[1]; + } else { return EC_ERROR_PARAM_COUNT; + } - rpm = strtoi(argv[2], &e, 0); - if (*e == '%') { /* Wait, that's a percentage */ + rpm = strtoi(rpm_str, &e, 0); + if (*e == '%') { /* Wait, that's a percentage */ ccprintf("Fan rpm given as %d%%\n", rpm); if (rpm < 0) rpm = 0; @@ -269,12 +326,12 @@ static int cc_fanset(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(fanset, cc_fanset, - "{fan} (rpm | pct%)", +DECLARE_CONSOLE_COMMAND(fanset, cc_fanset, "[fan] (rpm | pct%)", "Set fan speed"); -static int cc_fanduty(int argc, char **argv) +static int cc_fanduty(int argc, const char **argv) { + const char *percent_str; int percent = 0; char *e; int fan = 0; @@ -285,21 +342,24 @@ static int cc_fanduty(int argc, char **argv) } if (fan_count > 1) { - if (argc < 2) { + if (argc < 3) { ccprintf("fan number is required as the first arg\n"); return EC_ERROR_PARAM_COUNT; } + } + + if (argc == 3) { fan = strtoi(argv[1], &e, 0); if (*e || fan >= fan_count) return EC_ERROR_PARAM1; - argc--; - argv++; - } - - if (argc < 2) + percent_str = argv[2]; + } else if (argc == 2) { + percent_str = argv[1]; + } else { return EC_ERROR_PARAM_COUNT; + } - percent = strtoi(argv[1], &e, 0); + percent = strtoi(percent_str, &e, 0); if (*e) return EC_ERROR_PARAM1; @@ -308,8 +368,7 @@ static int cc_fanduty(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(fanduty, cc_fanduty, - "{fan} percent", +DECLARE_CONSOLE_COMMAND(fanduty, cc_fanduty, "[fan] percent", "Set fan duty cycle"); /*****************************************************************************/ @@ -318,7 +377,7 @@ DECLARE_CONSOLE_COMMAND(fanduty, cc_fanduty, /* 0-100% if in duty mode. -1 if not */ int dptf_get_fan_duty_target(void) { - int fan = 0; /* TODO(crosbug.com/p/23803) */ + int fan = 0; /* TODO(crosbug.com/p/23803) */ if (fan_count == 0) return -1; @@ -362,8 +421,7 @@ hc_pwm_get_fan_target_rpm(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_FAN_TARGET_RPM, - hc_pwm_get_fan_target_rpm, +DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_FAN_TARGET_RPM, hc_pwm_get_fan_target_rpm, EC_VER_MASK(0)); static enum ec_status @@ -391,7 +449,7 @@ hc_pwm_set_fan_target_rpm(struct host_cmd_handler_args *args) return EC_RES_ERROR; /* enable the fan if rpm is non-zero */ - set_enabled(fan, (p_v1->rpm > 0) ? 1 :0); + set_enabled(fan, (p_v1->rpm > 0) ? 1 : 0); set_thermal_control_enabled(fan, 0); fan_set_rpm_mode(FAN_CH(fan), 1); @@ -399,8 +457,7 @@ hc_pwm_set_fan_target_rpm(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_TARGET_RPM, - hc_pwm_set_fan_target_rpm, +DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_TARGET_RPM, hc_pwm_set_fan_target_rpm, EC_VER_MASK(0) | EC_VER_MASK(1)); static enum ec_status hc_pwm_set_fan_duty(struct host_cmd_handler_args *args) @@ -424,8 +481,7 @@ static enum ec_status hc_pwm_set_fan_duty(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_DUTY, - hc_pwm_set_fan_duty, +DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_DUTY, hc_pwm_set_fan_duty, EC_VER_MASK(0) | EC_VER_MASK(1)); static enum ec_status @@ -449,10 +505,8 @@ hc_thermal_auto_fan_ctrl(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_THERMAL_AUTO_FAN_CTRL, - hc_thermal_auto_fan_ctrl, - EC_VER_MASK(0)|EC_VER_MASK(1)); - +DECLARE_HOST_COMMAND(EC_CMD_THERMAL_AUTO_FAN_CTRL, hc_thermal_auto_fan_ctrl, + EC_VER_MASK(0) | EC_VER_MASK(1)); /*****************************************************************************/ /* Hooks */ @@ -463,18 +517,18 @@ DECLARE_HOST_COMMAND(EC_CMD_THERMAL_AUTO_FAN_CTRL, */ BUILD_ASSERT(CONFIG_FANS <= EC_FAN_SPEED_ENTRIES); -#define PWMFAN_SYSJUMP_TAG 0x5046 /* "PF" */ +#define PWMFAN_SYSJUMP_TAG 0x5046 /* "PF" */ #define PWM_HOOK_VERSION 1 /* Saved PWM state across sysjumps */ struct pwm_fan_state { /* TODO(crosbug.com/p/23530): Still treating all fans as one. */ uint16_t rpm; - uint8_t flag; /* FAN_STATE_FLAG_* */ + uint8_t flag; /* FAN_STATE_FLAG_* */ }; /* For struct pwm_fan_state.flag */ -#define FAN_STATE_FLAG_ENABLED BIT(0) -#define FAN_STATE_FLAG_THERMAL BIT(1) +#define FAN_STATE_FLAG_ENABLED BIT(0) +#define FAN_STATE_FLAG_THERMAL BIT(1) static void pwm_fan_init(void) { @@ -492,8 +546,8 @@ static void pwm_fan_init(void) fan_channel_setup(FAN_CH(fan), fans[fan].conf->flags); /* Restore previous state. */ - prev = (const struct pwm_fan_state *) - system_get_jump_tag(PWMFAN_SYSJUMP_TAG, &version, &size); + prev = (const struct pwm_fan_state *)system_get_jump_tag( + PWMFAN_SYSJUMP_TAG, &version, &size); if (prev && version == PWM_HOOK_VERSION && size == sizeof(*prev)) { memcpy(&state, prev, sizeof(state)); } else { @@ -505,7 +559,7 @@ static void pwm_fan_init(void) state.flag & FAN_STATE_FLAG_ENABLED); fan_set_rpm_target(FAN_CH(fan), state.rpm); set_thermal_control_enabled( - fan, state.flag & FAN_STATE_FLAG_THERMAL); + fan, state.flag & FAN_STATE_FLAG_THERMAL); } /* Initialize memory-mapped data */ @@ -545,7 +599,7 @@ DECLARE_HOOK(HOOK_SECOND, pwm_fan_second, HOOK_PRIO_DEFAULT); static void pwm_fan_preserve_state(void) { - struct pwm_fan_state state = {0}; + struct pwm_fan_state state = { 0 }; int fan = 0; if (fan_count == 0) @@ -558,8 +612,8 @@ static void pwm_fan_preserve_state(void) state.flag |= FAN_STATE_FLAG_THERMAL; state.rpm = fan_get_rpm_target(FAN_CH(fan)); - system_add_jump_tag(PWMFAN_SYSJUMP_TAG, PWM_HOOK_VERSION, - sizeof(state), &state); + system_add_jump_tag(PWMFAN_SYSJUMP_TAG, PWM_HOOK_VERSION, sizeof(state), + &state); } DECLARE_HOOK(HOOK_SYSJUMP, pwm_fan_preserve_state, HOOK_PRIO_DEFAULT); @@ -570,9 +624,11 @@ static void pwm_fan_control(int enable) /* TODO(crosbug.com/p/23530): Still treating all fans as one. */ for (fan = 0; fan < fan_count; fan++) { set_thermal_control_enabled(fan, enable); - fan_set_rpm_target(FAN_CH(fan), enable ? - fan_percent_to_rpm(FAN_CH(fan), CONFIG_FAN_INIT_SPEED) : - 0); + fan_set_rpm_target( + FAN_CH(fan), + enable ? fan_percent_to_rpm(FAN_CH(fan), + CONFIG_FAN_INIT_SPEED) : + 0); set_enabled(fan, enable); } } diff --git a/common/firmware_image.S b/common/firmware_image.S index b7d0c0d19a..cc9034b89d 100644 --- a/common/firmware_image.S +++ b/common/firmware_image.S @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -21,6 +21,9 @@ #define FW_IMAGE_SIGN(sect,suffix) \ STRINGIFY(FW_FILE(FINAL_OUTDIR,PROJECT,sect,suffix,.sig)) +.global _start +_start: + /* Read Only firmware */ #ifdef CONFIG_FW_INCLUDE_RO .section .image.RO, "ax" @@ -58,6 +61,11 @@ .incbin FW_IMAGE_SIGN(RW,) #endif +#ifdef CONFIG_IPI +.section .ipi_buffer, "aw" +.space (CONFIG_IPC_SHARED_OBJ_BUF_SIZE + 8) * 2, 0 +#endif + #ifdef CONFIG_DRAM_BASE /* Read Write firmware in DRAM */ .section .image.RW.dram, "ax" diff --git a/common/firmware_image.lds.S b/common/firmware_image.lds.S index 7522cf792a..e62818eebb 100644 --- a/common/firmware_image.lds.S +++ b/common/firmware_image.lds.S @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,6 +22,17 @@ CONFIG_RW_B_STORAGE_OFF) #elif (CONFIG_RO_MEM_OFF == CONFIG_RW_MEM_OFF) + +#ifdef CONFIG_PROGRAM_MEMORY_BASE_LOAD + +#define IMAGE_RO_AT (CONFIG_PROGRAM_MEMORY_BASE_LOAD + CONFIG_RO_MEM_OFF) +#define IMAGE_RW_AT (CONFIG_PROGRAM_MEMORY_BASE_LOAD + \ + CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) +#define IMAGE_RW_B_AT (CONFIG_PROGRAM_MEMORY_BASE_LOAD + \ + CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE + CONFIG_RW_SIZE) + +#else + #define IMAGE_RO_AT (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RO_MEM_OFF) /* This is applicable to ECs in which RO and RW execution is mapped to the same location but we still have to generate an ec.bin with RO @@ -31,26 +42,49 @@ and RW images at different Flash offset */ #define IMAGE_RW_B_AT (CONFIG_PROGRAM_MEMORY_BASE + \ CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE + CONFIG_RW_SIZE) +#endif /* CONFIG_PROGRAM_MEMORY_BASE_LOAD */ + #else #define IMAGE_RO_AT (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RO_MEM_OFF) #define IMAGE_RW_AT (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF) #define IMAGE_RW_B_AT (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_B_MEM_OFF) #endif +#ifdef CONFIG_PROGRAM_MEMORY_BASE_LOAD +#define IMAGE_PADDING_AT (CONFIG_PROGRAM_MEMORY_BASE_LOAD + \ + CONFIG_FLASH_SIZE_BYTES - 1) +#else +#define IMAGE_PADDING_AT (CONFIG_PROGRAM_MEMORY_BASE + \ + CONFIG_FLASH_SIZE_BYTES - 1) +#endif + OUTPUT_FORMAT(BFD_FORMAT, BFD_FORMAT, BFD_FORMAT) OUTPUT_ARCH(BFD_ARCH) MEMORY { FLASH (rx) : ORIGIN = CONFIG_PROGRAM_MEMORY_BASE, - LENGTH = CONFIG_FLASH_SIZE + LENGTH = CONFIG_FLASH_SIZE_BYTES +#ifdef CONFIG_IPI + IPI_BUFFER (rw) : ORIGIN = CONFIG_PROGRAM_MEMORY_BASE + CONFIG_IPC_SHARED_OBJ_ADDR, + LENGTH = (CONFIG_IPC_SHARED_OBJ_BUF_SIZE + 8) * 2 +#endif #ifdef CONFIG_DRAM_BASE - DRAM (rx) : ORIGIN = CONFIG_DRAM_BASE_LOAD, LENGTH = CONFIG_DRAM_SIZE + DRAM (rx) : ORIGIN = CONFIG_DRAM_BASE, LENGTH = CONFIG_DRAM_SIZE #endif } SECTIONS { + /* + * Create empty text section. Without an explicit text section + * clang/lld will create one and put it at an address it selects. Even + * though the section it creates is empty, if the LMA is beyond the end + * of the flash, ec.bin will be too large since the empty space is + * filled with 0xFF. + */ + .text (NOLOAD) : {} + .image.RO : AT(IMAGE_RO_AT) { *(.image.RO) } > FLASH =0xff @@ -92,9 +126,21 @@ SECTIONS } > FLASH =0xff #endif #endif - .padding : AT(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_SIZE - 1) { +#ifdef CONFIG_IMAGE_PADDING + .padding : AT(IMAGE_PADDING_AT) { BYTE(0xff); } > FLASH =0xff +#endif + +#ifdef CONFIG_IPI + /* The section holds address of IPI buffer but no symbols. */ + .ipi_buffer(NOLOAD) : +#ifdef CONFIG_PROGRAM_MEMORY_BASE_LOAD + AT(CONFIG_PROGRAM_MEMORY_BASE_LOAD + CONFIG_IPC_SHARED_OBJ_ADDR) +#endif + { + } > IPI_BUFFER +#endif #ifdef CONFIG_DRAM_BASE .image.RW.dram : AT(CONFIG_DRAM_BASE_LOAD) { diff --git a/common/flash.c b/common/flash.c index 235121f51e..5c570d3eef 100644 --- a/common/flash.c +++ b/common/flash.c @@ -1,12 +1,17 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Flash memory module for Chrome EC - common functions */ +#include "builtin/assert.h" +#ifdef CONFIG_ZEPHYR +#include "cbi_flash.h" +#endif /* CONFIG_ZEPHYR */ #include "common.h" #include "console.h" +#include "cros_board_info.h" #include "flash.h" #include "gpio.h" #include "hooks.h" @@ -17,6 +22,7 @@ #include "system.h" #include "util.h" #include "vboot_hash.h" +#include "write_protect.h" /* * Contents of erased flash, as a 32-bit value. Most platforms erase flash @@ -40,35 +46,37 @@ /* Persistent protection state - emulates a SPI status register for flashrom */ /* NOTE: It's not expected that RO and RW will support * differing PSTATE versions. */ -#define PERSIST_STATE_VERSION 3 /* Expected persist_state.version */ +#define PERSIST_STATE_VERSION 3 /* Expected persist_state.version */ /* Flags for persist_state.flags */ /* Protect persist state and RO firmware at boot */ #define PERSIST_FLAG_PROTECT_RO 0x02 -#define PSTATE_VALID_FLAGS BIT(0) -#define PSTATE_VALID_SERIALNO BIT(1) -#define PSTATE_VALID_MAC_ADDR BIT(2) +#define PSTATE_VALID_FLAGS BIT(0) +#define PSTATE_VALID_SERIALNO BIT(1) +#define PSTATE_VALID_MAC_ADDR BIT(2) +/* + * Error correction code operates on blocks equal to CONFIG_FLASH_WRITE_SIZE + * bytes so the persist_state must be a multiple of that length. To ensure this + * occurs, the aligned attribute has been set. Alignment has a side effect + * in that pointer arithmetic can't break alignment so it adds padding to the + * size of the structure to ensure that it is also a multiple of the alignment. + */ struct persist_state { - uint8_t version; /* Version of this struct */ - uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */ - uint8_t valid_fields; /* Flags for valid data. */ - uint8_t reserved; /* Reserved; set 0 */ + uint8_t version; /* Version of this struct */ + uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */ + uint8_t valid_fields; /* Flags for valid data. */ + uint8_t reserved; /* Reserved; set 0 */ #ifdef CONFIG_SERIALNO_LEN uint8_t serialno[CONFIG_SERIALNO_LEN]; /* Serial number. */ #endif /* CONFIG_SERIALNO_LEN */ #ifdef CONFIG_MAC_ADDR_LEN uint8_t mac_addr[CONFIG_MAC_ADDR_LEN]; #endif /* CONFIG_MAC_ADDR_LEN */ -#if !defined(CONFIG_SERIALNO_LEN) && !defined(CONFIG_MAC_ADDR_LEN) - uint8_t padding[4 % CONFIG_FLASH_WRITE_SIZE]; -#endif -}; +} __aligned(CONFIG_FLASH_WRITE_SIZE); /* written with flash_physical_write, need to respect alignment constraints */ -#ifndef CHIP_FAMILY_STM32L /* STM32L1xx is somewhat lying to us */ BUILD_ASSERT(sizeof(struct persist_state) % CONFIG_FLASH_WRITE_SIZE == 0); -#endif BUILD_ASSERT(sizeof(struct persist_state) <= CONFIG_FW_PSTATE_SIZE); @@ -87,11 +95,11 @@ BUILD_ASSERT(sizeof(struct persist_state) <= CONFIG_FW_PSTATE_SIZE); * lock the flash at boot. */ #if (CONFIG_FLASH_ERASED_VALUE32 == -1U) -#define PSTATE_MAGIC_UNLOCKED 0x4f4e5057 /* "WPNO" */ -#define PSTATE_MAGIC_LOCKED 0x00000000 /* "" */ +#define PSTATE_MAGIC_UNLOCKED 0x4f4e5057 /* "WPNO" */ +#define PSTATE_MAGIC_LOCKED 0x00000000 /* "" */ #elif (CONFIG_FLASH_ERASED_VALUE32 == 0) -#define PSTATE_MAGIC_UNLOCKED 0x4f4e5057 /* "WPNO" */ -#define PSTATE_MAGIC_LOCKED 0x5f5f5057 /* "WP__" */ +#define PSTATE_MAGIC_UNLOCKED 0x4f4e5057 /* "WPNO" */ +#define PSTATE_MAGIC_LOCKED 0x5f5f5057 /* "WP__" */ #else /* What kind of wacky flash doesn't erase all bits to 1 or 0? */ #error "PSTATE needs magic values for this flash architecture." @@ -120,6 +128,9 @@ const uint32_t pstate_data __attribute__((section(".rodata.pstate"))) = #endif /* !CONFIG_FLASH_PSTATE_BANK */ #endif /* CONFIG_FLASH_PSTATE */ +/* Shim layer provides implementation of these functions based on Zephyr API */ +#if !defined(CONFIG_ZEPHYR) || \ + !defined(CONFIG_PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT) #ifdef CONFIG_FLASH_MULTIPLE_REGION const struct ec_flash_bank *flash_bank_info(int bank) { @@ -133,7 +144,7 @@ const struct ec_flash_bank *flash_bank_info(int bank) return NULL; } -int flash_bank_size(int bank) +int crec_flash_bank_size(int bank) { int rv; const struct ec_flash_bank *info = flash_bank_info(bank); @@ -146,7 +157,7 @@ int flash_bank_size(int bank) return rv; } -int flash_bank_erase_size(int bank) +int crec_flash_bank_erase_size(int bank) { int rv; const struct ec_flash_bank *info = flash_bank_info(bank); @@ -159,7 +170,7 @@ int flash_bank_erase_size(int bank) return rv; } -int flash_bank_index(int offset) +int crec_flash_bank_index(int offset) { int bank_offset = 0, i; @@ -167,8 +178,8 @@ int flash_bank_index(int offset) return bank_offset; for (i = 0; i < ARRAY_SIZE(flash_bank_array); i++) { - int all_sector_size = flash_bank_array[i].count << - flash_bank_array[i].size_exp; + int all_sector_size = flash_bank_array[i].count + << flash_bank_array[i].size_exp; if (offset >= all_sector_size) { offset -= all_sector_size; bank_offset += flash_bank_array[i].count; @@ -183,17 +194,17 @@ int flash_bank_index(int offset) return bank_offset; } -int flash_bank_count(int offset, int size) +int crec_flash_bank_count(int offset, int size) { - int begin = flash_bank_index(offset); - int end = flash_bank_index(offset + size); + int begin = crec_flash_bank_index(offset); + int end = crec_flash_bank_index(offset + size); if (begin == -1 || end == -1) return -1; return end - begin; } -int flash_bank_start_offset(int bank) +int crec_flash_bank_start_offset(int bank) { int i; int offset; @@ -204,7 +215,7 @@ int flash_bank_start_offset(int bank) offset = 0; for (i = 0; i < bank; i++) { - bank_size = flash_bank_size(i); + bank_size = crec_flash_bank_size(i); if (bank_size < 0) return -1; offset += bank_size; @@ -213,21 +224,73 @@ int flash_bank_start_offset(int bank) return offset; } -#endif /* CONFIG_FLASH_MULTIPLE_REGION */ +int crec_flash_response_fill_banks(struct ec_response_flash_info_2 *r, + int num_banks) +{ + const struct ec_flash_bank *banks = flash_bank_array; + int banks_to_copy = MIN(ARRAY_SIZE(flash_bank_array), num_banks); + + r->num_banks_desc = banks_to_copy; + r->num_banks_total = ARRAY_SIZE(flash_bank_array); + if (banks_to_copy > 0) + memcpy(r->banks, banks, + banks_to_copy * sizeof(struct ec_flash_bank)); + + return EC_RES_SUCCESS; +} +#else /* CONFIG_FLASH_MULTIPLE_REGION */ +#if CONFIG_FLASH_BANK_SIZE < CONFIG_FLASH_ERASE_SIZE +#error "Flash: Bank size expected bigger or equal to erase size." +#endif +int crec_flash_response_fill_banks(struct ec_response_flash_info_2 *r, + int num_banks) +{ + if (num_banks >= 1) { + r->banks[0].count = crec_flash_total_banks(); + r->banks[0].size_exp = __fls(CONFIG_FLASH_BANK_SIZE); + r->banks[0].write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE); + r->banks[0].erase_size_exp = __fls(CONFIG_FLASH_ERASE_SIZE); + r->banks[0].protect_size_exp = __fls(CONFIG_FLASH_BANK_SIZE); + + r->num_banks_desc = 1; + } else { + /* num_banks == 0, don't fill the banks array */ + r->num_banks_desc = 0; + } + + r->num_banks_total = 1; + + return EC_RES_SUCCESS; +} +#endif /* CONFIG_FLASH_MULTIPLE_REGION */ + +int crec_flash_total_banks(void) +{ + return PHYSICAL_BANKS; +} +#endif /* !defined(CONFIG_ZEPHYR) || \ + * !defined(CONFIG_PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT) \ + */ static int flash_range_ok(int offset, int size_req, int align) { - if (offset < 0 || size_req < 0 || - offset > CONFIG_FLASH_SIZE || - size_req > CONFIG_FLASH_SIZE || - offset + size_req > CONFIG_FLASH_SIZE || + if (offset < 0 || size_req < 0 || offset > CONFIG_FLASH_SIZE_BYTES || + size_req > CONFIG_FLASH_SIZE_BYTES || + offset + size_req > CONFIG_FLASH_SIZE_BYTES || (offset | size_req) & (align - 1)) - return 0; /* Invalid range */ + return 0; /* Invalid range */ return 1; } #ifdef CONFIG_MAPPED_STORAGE + +/** + * A test public variable allowing us to override the base address of + * flash_physical_dataptr(). + */ +test_export_static const char *flash_physical_dataptr_override; + /** * Get the physical memory address of a flash offset * @@ -241,17 +304,20 @@ static int flash_range_ok(int offset, int size_req, int align) */ static const char *flash_physical_dataptr(int offset) { + if (IS_ENABLED(TEST_BUILD) && flash_physical_dataptr_override != NULL) { + return flash_physical_dataptr_override + offset; + } return (char *)((uintptr_t)CONFIG_MAPPED_STORAGE_BASE + offset); } -int flash_dataptr(int offset, int size_req, int align, const char **ptrp) +int crec_flash_dataptr(int offset, int size_req, int align, const char **ptrp) { if (!flash_range_ok(offset, size_req, align)) - return -1; /* Invalid range */ + return -1; /* Invalid range */ if (ptrp) *ptrp = flash_physical_dataptr(offset); - return CONFIG_FLASH_SIZE - offset; + return CONFIG_FLASH_SIZE_BYTES - offset; } #endif @@ -264,8 +330,8 @@ int flash_dataptr(int offset, int size_req, int align, const char **ptrp) static uint32_t flash_read_pstate(void) { const struct persist_state *pstate = - (const struct persist_state *) - flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); + (const struct persist_state *)flash_physical_dataptr( + CONFIG_FW_PSTATE_OFF); if ((pstate->version == PERSIST_STATE_VERSION) && (pstate->valid_fields & PSTATE_VALID_FLAGS) && @@ -293,8 +359,8 @@ static int flash_write_pstate_data(struct persist_state *newpstate) int rv; /* Erase pstate */ - rv = flash_physical_erase(CONFIG_FW_PSTATE_OFF, - CONFIG_FW_PSTATE_SIZE); + rv = crec_flash_physical_erase(CONFIG_FW_PSTATE_OFF, + CONFIG_FW_PSTATE_SIZE); if (rv) return rv; @@ -305,12 +371,11 @@ static int flash_write_pstate_data(struct persist_state *newpstate) */ /* Write the updated pstate */ - return flash_physical_write(CONFIG_FW_PSTATE_OFF, sizeof(*newpstate), - (const char *)newpstate); + return crec_flash_physical_write(CONFIG_FW_PSTATE_OFF, + sizeof(*newpstate), + (const char *)newpstate); } - - /** * Validate and Init persistent state datastructure. * @@ -337,8 +402,8 @@ static int flash_write_pstate(uint32_t flags) { struct persist_state newpstate; const struct persist_state *pstate = - (const struct persist_state *) - flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); + (const struct persist_state *)flash_physical_dataptr( + CONFIG_FW_PSTATE_OFF); /* Only check the flags we write to pstate */ flags &= EC_FLASH_PROTECT_RO_AT_BOOT; @@ -364,11 +429,11 @@ static int flash_write_pstate(uint32_t flags) /** * Read and return persistent serial number. */ -const char *flash_read_pstate_serial(void) +const char *crec_flash_read_pstate_serial(void) { const struct persist_state *pstate = - (const struct persist_state *) - flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); + (const struct persist_state *)flash_physical_dataptr( + CONFIG_FW_PSTATE_OFF); if ((pstate->version == PERSIST_STATE_VERSION) && (pstate->valid_fields & PSTATE_VALID_SERIALNO)) { @@ -384,13 +449,13 @@ const char *flash_read_pstate_serial(void) * @param serialno New ascii serial number to set in pstate. * @return EC_SUCCESS, or nonzero if error. */ -int flash_write_pstate_serial(const char *serialno) +int crec_flash_write_pstate_serial(const char *serialno) { int length; struct persist_state newpstate; const struct persist_state *pstate = - (const struct persist_state *) - flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); + (const struct persist_state *)flash_physical_dataptr( + CONFIG_FW_PSTATE_OFF); /* Check that this is OK */ if (!serialno) @@ -424,11 +489,11 @@ int flash_write_pstate_serial(const char *serialno) /** * Read and return persistent MAC address. */ -const char *flash_read_pstate_mac_addr(void) +const char *crec_flash_read_pstate_mac_addr(void) { const struct persist_state *pstate = - (const struct persist_state *) - flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); + (const struct persist_state *)flash_physical_dataptr( + CONFIG_FW_PSTATE_OFF); if ((pstate->version == PERSIST_STATE_VERSION) && (pstate->valid_fields & PSTATE_VALID_MAC_ADDR)) { @@ -444,13 +509,13 @@ const char *flash_read_pstate_mac_addr(void) * @param mac_addr New ascii MAC address to set in pstate. * @return EC_SUCCESS, or nonzero if error. */ -int flash_write_pstate_mac_addr(const char *mac_addr) +int crec_flash_write_pstate_mac_addr(const char *mac_addr) { int length; struct persist_state newpstate; const struct persist_state *pstate = - (const struct persist_state *) - flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); + (const struct persist_state *)flash_physical_dataptr( + CONFIG_FW_PSTATE_OFF); /* Check that this is OK, data is valid and fits in the region. */ if (!mac_addr) { @@ -554,33 +619,32 @@ static int flash_write_pstate(uint32_t flags) * Write a new pstate. We can overwrite the existing value, because * we're only moving bits from the erased state to the unerased state. */ - return flash_physical_write(get_pstate_addr() - - CONFIG_PROGRAM_MEMORY_BASE, - sizeof(new_pstate), - (const char *)&new_pstate); + return crec_flash_physical_write( + get_pstate_addr() - CONFIG_PROGRAM_MEMORY_BASE, + sizeof(new_pstate), (const char *)&new_pstate); } #endif /* !CONFIG_FLASH_PSTATE_BANK */ #endif /* CONFIG_FLASH_PSTATE */ -int flash_is_erased(uint32_t offset, int size) +int crec_flash_is_erased(uint32_t offset, int size) { const uint32_t *ptr; #ifdef CONFIG_MAPPED_STORAGE /* Use pointer directly to flash */ - if (flash_dataptr(offset, size, sizeof(uint32_t), - (const char **)&ptr) < 0) + if (crec_flash_dataptr(offset, size, sizeof(uint32_t), + (const char **)&ptr) < 0) return 0; - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); for (size /= sizeof(uint32_t); size > 0; size--, ptr++) if (*ptr != CONFIG_FLASH_ERASED_VALUE32) { - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); return 0; - } + } - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); #else /* Read flash a chunk at a time */ uint32_t buf[8]; @@ -589,7 +653,7 @@ int flash_is_erased(uint32_t offset, int size) while (size) { bsize = MIN(size, sizeof(buf)); - if (flash_read(offset, bsize, (char *)buf)) + if (crec_flash_read(offset, bsize, (char *)buf)) return 0; size -= bsize; @@ -599,28 +663,74 @@ int flash_is_erased(uint32_t offset, int size) for (bsize /= sizeof(uint32_t); bsize > 0; bsize--, ptr++) if (*ptr != CONFIG_FLASH_ERASED_VALUE32) return 0; - } #endif return 1; } -int flash_read(int offset, int size, char *data) +#if defined(CONFIG_ZEPHYR) && defined(CONFIG_PLATFORM_EC_CBI_FLASH) +/** + * Check if the passed section overlaps with CBI section on EC flash. + * + * @param offset Flash offset. + * @param size Length of section in bytes. + * @return true if there is overlap, or false if there is no overlap. + */ +static bool check_cbi_section_overlap(int offset, int size) +{ + int cbi_start = CBI_FLASH_OFFSET; + int cbi_end = CBI_FLASH_OFFSET + CBI_IMAGE_SIZE; + int sec_start = offset; + int sec_end = offset + size; + + return !((sec_end <= cbi_start) || (sec_start >= cbi_end)); +} + +/** + * Hide the information related to CBI(EC flash) if data contains any. + * + * @param offset Flash offset. + * @param size Length of section in bytes. + * @param data Flash data. Must be 32-bit aligned. + */ +static void protect_cbi_overlapped_section(int offset, int size, char *data) +{ + if (check_cbi_section_overlap(offset, size)) { + int cbi_end = CBI_FLASH_OFFSET + CBI_IMAGE_SIZE; + int sec_end = offset + size; + int cbi_fill_start = MAX(CBI_FLASH_OFFSET, offset); + int cbi_fill_size = MIN(cbi_end, sec_end) - cbi_fill_start; + + memset(data + (cbi_fill_start - offset), 0xff, cbi_fill_size); + } +} +#endif + +test_mockable int crec_flash_unprotected_read(int offset, int size, char *data) { #ifdef CONFIG_MAPPED_STORAGE const char *src; - if (flash_dataptr(offset, size, 1, &src) < 0) + if (crec_flash_dataptr(offset, size, 1, &src) < 0) return EC_ERROR_INVAL; - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); memcpy(data, src, size); - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); return EC_SUCCESS; #else - return flash_physical_read(offset, size, data); + return crec_flash_physical_read(offset, size, data); +#endif +} + +int crec_flash_read(int offset, int size, char *data) +{ + RETURN_ERROR(crec_flash_unprotected_read(offset, size, data)); +#if defined(CONFIG_ZEPHYR) && defined(CONFIG_PLATFORM_EC_CBI_FLASH) + protect_cbi_overlapped_section(offset, size, data); #endif + return EC_SUCCESS; } static void flash_abort_or_invalidate_hash(int offset, int size) @@ -652,38 +762,71 @@ static void flash_abort_or_invalidate_hash(int offset, int size) * jump to RW after the timeout. */ if ((offset >= CONFIG_RW_MEM_OFF && - offset < (CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE)) || + offset < (CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE)) || ((offset + size) > CONFIG_RW_MEM_OFF && - (offset + size) <= (CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE)) || + (offset + size) <= (CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE)) || (offset < CONFIG_RW_MEM_OFF && - (offset + size) > (CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE))) + (offset + size) > (CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE))) rwsig_abort(); #endif } -int flash_write(int offset, int size, const char *data) +int crec_flash_write(int offset, int size, const char *data) { if (!flash_range_ok(offset, size, CONFIG_FLASH_WRITE_SIZE)) - return EC_ERROR_INVAL; /* Invalid range */ + return EC_ERROR_INVAL; /* Invalid range */ flash_abort_or_invalidate_hash(offset, size); - return flash_physical_write(offset, size, data); +#if defined(CONFIG_ZEPHYR) && defined(CONFIG_PLATFORM_EC_CBI_FLASH) + if (check_cbi_section_overlap(offset, size)) { + int cbi_end = CBI_FLASH_OFFSET + CBI_IMAGE_SIZE; + int sec_end = offset + size; + + if (offset < CBI_FLASH_OFFSET) { + RETURN_ERROR(crec_flash_physical_write( + offset, CBI_FLASH_OFFSET - offset, data)); + } + if (sec_end > cbi_end) { + RETURN_ERROR(crec_flash_physical_write( + cbi_end, sec_end - cbi_end, + data + cbi_end - offset)); + } + return EC_SUCCESS; + } +#endif + return crec_flash_physical_write(offset, size, data); } -int flash_erase(int offset, int size) +int crec_flash_erase(int offset, int size) { #ifndef CONFIG_FLASH_MULTIPLE_REGION if (!flash_range_ok(offset, size, CONFIG_FLASH_ERASE_SIZE)) - return EC_ERROR_INVAL; /* Invalid range */ + return EC_ERROR_INVAL; /* Invalid range */ #endif flash_abort_or_invalidate_hash(offset, size); - return flash_physical_erase(offset, size); +#if defined(CONFIG_ZEPHYR) && defined(CONFIG_PLATFORM_EC_CBI_FLASH) + if (check_cbi_section_overlap(offset, size)) { + int cbi_end = CBI_FLASH_OFFSET + CBI_IMAGE_SIZE; + int sec_end = offset + size; + + if (offset < CBI_FLASH_OFFSET) { + RETURN_ERROR(crec_flash_physical_erase( + offset, CBI_FLASH_OFFSET - offset)); + } + if (sec_end > cbi_end) { + RETURN_ERROR(crec_flash_physical_erase( + cbi_end, sec_end - cbi_end)); + } + return EC_SUCCESS; + } +#endif + return crec_flash_physical_erase(offset, size); } -int flash_protect_at_boot(uint32_t new_flags) +int crec_flash_protect_at_boot(uint32_t new_flags) { #ifdef CONFIG_FLASH_PSTATE uint32_t new_pstate_flags = new_flags & EC_FLASH_PROTECT_RO_AT_BOOT; @@ -695,7 +838,7 @@ int flash_protect_at_boot(uint32_t new_flags) #ifdef CONFIG_FLASH_PSTATE_BANK /* Fail if write protect block is already locked */ - if (flash_physical_get_protect(PSTATE_BANK)) + if (crec_flash_physical_get_protect(PSTATE_BANK)) return EC_ERROR_ACCESS_DENIED; #endif @@ -717,21 +860,21 @@ int flash_protect_at_boot(uint32_t new_flags) * This assumes PSTATE immediately follows RO, which it does on * all STM32 platforms (which are the only ones with this config). */ - flash_physical_protect_at_boot(new_flags); + crec_flash_physical_protect_at_boot(new_flags); #endif return EC_SUCCESS; #else - return flash_physical_protect_at_boot(new_flags); + return crec_flash_physical_protect_at_boot(new_flags); #endif } -uint32_t flash_get_protect(void) +uint32_t crec_flash_get_protect(void) { uint32_t flags = 0; int i; /* Region protection status */ - int not_protected[FLASH_REGION_COUNT] = {0}; + int not_protected[FLASH_REGION_COUNT] = { 0 }; #ifdef CONFIG_ROLLBACK /* Flags that must be set to set ALL_NOW flag. */ const uint32_t all_flags = EC_FLASH_PROTECT_RO_NOW | @@ -743,15 +886,8 @@ uint32_t flash_get_protect(void) #endif /* Read write protect GPIO */ -#ifdef CONFIG_WP_ALWAYS - flags |= EC_FLASH_PROTECT_GPIO_ASSERTED; -#elif defined(CONFIG_WP_ACTIVE_HIGH) - if (gpio_get_level(GPIO_WP)) + if (write_protect_is_asserted()) flags |= EC_FLASH_PROTECT_GPIO_ASSERTED; -#else - if (!gpio_get_level(GPIO_WP_L)) - flags |= EC_FLASH_PROTECT_GPIO_ASSERTED; -#endif #ifdef CONFIG_FLASH_PSTATE /* Read persistent state of RO-at-boot flag */ @@ -759,13 +895,13 @@ uint32_t flash_get_protect(void) #endif /* Scan flash protection */ - for (i = 0; i < PHYSICAL_BANKS; i++) { + for (i = 0; i < crec_flash_total_banks(); i++) { int is_ro = (i >= WP_BANK_OFFSET && - i < WP_BANK_OFFSET + WP_BANK_COUNT); + i < WP_BANK_OFFSET + WP_BANK_COUNT); enum flash_region region = is_ro ? FLASH_REGION_RO : - FLASH_REGION_RW; + FLASH_REGION_RW; int bank_flag = is_ro ? EC_FLASH_PROTECT_RO_NOW : - EC_FLASH_PROTECT_RW_NOW; + EC_FLASH_PROTECT_RW_NOW; #ifdef CONFIG_ROLLBACK if (i >= ROLLBACK_BANK_OFFSET && @@ -775,7 +911,7 @@ uint32_t flash_get_protect(void) } #endif - if (flash_physical_get_protect(i)) { + if (crec_flash_physical_get_protect(i)) { /* At least one bank in the region is protected */ flags |= bank_flag; if (not_protected[region]) @@ -808,7 +944,7 @@ uint32_t flash_get_protect(void) #endif /* Add in flags from physical layer */ - return flags | flash_physical_get_protect_flags(); + return flags | crec_flash_physical_get_protect_flags(); } /* @@ -822,14 +958,15 @@ uint32_t flash_get_protect(void) * 4. Commit RO_NOW. * 5. Commit ALL_NOW. */ -int flash_set_protect(uint32_t mask, uint32_t flags) +int crec_flash_set_protect(uint32_t mask, uint32_t flags) { int retval = EC_SUCCESS; int rv; - int old_flags_at_boot = flash_get_protect() & + int old_flags_at_boot = + crec_flash_get_protect() & (EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RW_AT_BOOT | - EC_FLASH_PROTECT_ROLLBACK_AT_BOOT | - EC_FLASH_PROTECT_ALL_AT_BOOT); + EC_FLASH_PROTECT_ROLLBACK_AT_BOOT | + EC_FLASH_PROTECT_ALL_AT_BOOT); int new_flags_at_boot = old_flags_at_boot; /* Sanitize input flags */ @@ -899,7 +1036,7 @@ int flash_set_protect(uint32_t mask, uint32_t flags) /* 1.f - Commit *_AT_BOOT "clears" (and RO "set" 1.b). */ if (new_flags_at_boot != old_flags_at_boot) { - rv = flash_protect_at_boot(new_flags_at_boot); + rv = crec_flash_protect_at_boot(new_flags_at_boot); if (rv) retval = rv; old_flags_at_boot = new_flags_at_boot; @@ -910,8 +1047,8 @@ int flash_set_protect(uint32_t mask, uint32_t flags) * All subsequent flags only work if write protect is enabled (that is, * hardware WP flag) *and* RO is protected at boot (software WP flag). */ - if ((~flash_get_protect()) & (EC_FLASH_PROTECT_GPIO_ASSERTED | - EC_FLASH_PROTECT_RO_AT_BOOT)) + if ((~crec_flash_get_protect()) & + (EC_FLASH_PROTECT_GPIO_ASSERTED | EC_FLASH_PROTECT_RO_AT_BOOT)) return retval; /* @@ -934,21 +1071,29 @@ int flash_set_protect(uint32_t mask, uint32_t flags) /* 3.d - Commit *_AT_BOOT "sets". */ if (new_flags_at_boot != old_flags_at_boot) { - rv = flash_protect_at_boot(new_flags_at_boot); + rv = crec_flash_protect_at_boot(new_flags_at_boot); if (rv) retval = rv; } /* 4 - Commit RO_NOW. */ if (flags & EC_FLASH_PROTECT_RO_NOW) { - rv = flash_physical_protect_now(0); + rv = crec_flash_physical_protect_now(0); if (rv) retval = rv; + + /* + * Latch the CBI EEPROM WP immediately if HW WP is asserted and + * we're now protecting the RO region with SW WP. + */ + if (IS_ENABLED(CONFIG_EEPROM_CBI_WP) && + (EC_FLASH_PROTECT_GPIO_ASSERTED & crec_flash_get_protect())) + cbi_latch_eeprom_wp(); } /* 5 - Commit ALL_NOW. */ if (flags & EC_FLASH_PROTECT_ALL_NOW) { - rv = flash_physical_protect_now(1); + rv = crec_flash_physical_protect_now(1); if (rv) retval = rv; } @@ -962,8 +1107,7 @@ static struct ec_params_flash_erase_v1 erase_info; static void flash_erase_deferred(void) { - erase_rc = EC_RES_BUSY; - if (flash_erase(erase_info.params.offset, erase_info.params.size)) + if (crec_flash_erase(erase_info.params.offset, erase_info.params.size)) erase_rc = EC_RES_ERROR; else erase_rc = EC_RES_SUCCESS; @@ -971,22 +1115,16 @@ static void flash_erase_deferred(void) DECLARE_DEFERRED(flash_erase_deferred); #endif -/*****************************************************************************/ -/* Console commands */ - -#ifdef CONFIG_CMD_FLASHINFO -static int command_flash_info(int argc, char **argv) +#if !defined(CONFIG_ZEPHYR) || \ + !defined(CONFIG_PLATFORM_EC_USE_ZEPHYR_FLASH_PAGE_LAYOUT) +void crec_flash_print_region_info(void) { - int i, flags; - - ccprintf("Usable: %4d KB\n", CONFIG_FLASH_SIZE / 1024); - ccprintf("Write: %4d B (ideal %d B)\n", CONFIG_FLASH_WRITE_SIZE, - CONFIG_FLASH_WRITE_IDEAL_SIZE); #ifdef CONFIG_FLASH_MULTIPLE_REGION + int i; + ccprintf("Regions:\n"); for (i = 0; i < ARRAY_SIZE(flash_bank_array); i++) { - ccprintf(" %d region%s:\n", - flash_bank_array[i].count, + ccprintf(" %d region%s:\n", flash_bank_array[i].count, (flash_bank_array[i].count == 1 ? "" : "s")); ccprintf(" Erase: %4d B (to %d-bits)\n", 1 << flash_bank_array[i].erase_size_exp, @@ -999,60 +1137,77 @@ static int command_flash_info(int argc, char **argv) CONFIG_FLASH_ERASED_VALUE32 ? 1 : 0); ccprintf("Protect: %4d B\n", CONFIG_FLASH_BANK_SIZE); #endif - flags = flash_get_protect(); - ccprintf("Flags: "); - if (flags & EC_FLASH_PROTECT_GPIO_ASSERTED) - ccputs(" wp_gpio_asserted"); - if (flags & EC_FLASH_PROTECT_RO_AT_BOOT) - ccputs(" ro_at_boot"); - if (flags & EC_FLASH_PROTECT_ALL_AT_BOOT) - ccputs(" all_at_boot"); - if (flags & EC_FLASH_PROTECT_RO_NOW) - ccputs(" ro_now"); - if (flags & EC_FLASH_PROTECT_ALL_NOW) - ccputs(" all_now"); +} +#endif + +/*****************************************************************************/ +/* Console commands */ + +#ifdef CONFIG_CMD_FLASHINFO +#define BIT_TO_ON_OFF(value, mask) \ + ((((value) & (mask)) == (mask)) ? "ON" : "OFF") +static int command_flash_info(int argc, const char **argv) +{ + int i, flags; + + ccprintf("Usable: %4d KB\n", CONFIG_FLASH_SIZE_BYTES / 1024); + ccprintf("Write: %4d B (ideal %d B)\n", CONFIG_FLASH_WRITE_SIZE, + CONFIG_FLASH_WRITE_IDEAL_SIZE); + crec_flash_print_region_info(); + flags = crec_flash_get_protect(); + ccprintf("Flags:\n"); + ccprintf(" wp_gpio_asserted: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_GPIO_ASSERTED)); + ccprintf(" ro_at_boot: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_RO_AT_BOOT)); + ccprintf(" all_at_boot: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_ALL_AT_BOOT)); + ccprintf(" ro_now: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_RO_NOW)); + ccprintf(" all_now: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_ALL_NOW)); #ifdef CONFIG_FLASH_PROTECT_RW - if (flags & EC_FLASH_PROTECT_RW_AT_BOOT) - ccputs(" rw_at_boot"); - if (flags & EC_FLASH_PROTECT_RW_NOW) - ccputs(" rw_now"); + ccprintf(" rw_at_boot: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_RW_AT_BOOT)); + ccprintf(" rw_now: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_RW_NOW)); #endif - if (flags & EC_FLASH_PROTECT_ERROR_STUCK) - ccputs(" STUCK"); - if (flags & EC_FLASH_PROTECT_ERROR_INCONSISTENT) - ccputs(" INCONSISTENT"); + ccprintf(" STUCK: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_ERROR_STUCK)); + ccprintf(" INCONSISTENT: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_ERROR_INCONSISTENT)); + ccprintf(" UNKNOWN_ERROR: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_ERROR_UNKNOWN)); #ifdef CONFIG_ROLLBACK - if (flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) - ccputs(" rollback_at_boot"); - if (flags & EC_FLASH_PROTECT_ROLLBACK_NOW) - ccputs(" rollback_now"); + ccprintf(" rollback_at_boot: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_ROLLBACK_AT_BOOT)); + ccprintf(" rollback_now: %s\n", + BIT_TO_ON_OFF(flags, EC_FLASH_PROTECT_ROLLBACK_NOW)); #endif - ccputs("\n"); ccputs("Protected now:"); - for (i = 0; i < PHYSICAL_BANKS; i++) { + for (i = 0; i < crec_flash_total_banks(); i++) { if (!(i & 31)) ccputs("\n "); else if (!(i & 7)) ccputs(" "); - ccputs(flash_physical_get_protect(i) ? "Y" : "."); + ccputs(crec_flash_physical_get_protect(i) ? "Y" : "."); } ccputs("\n"); return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(flashinfo, command_flash_info, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(flashinfo, command_flash_info, NULL, "Print flash info"); #endif /* CONFIG_CMD_FLASHINFO */ #ifdef CONFIG_CMD_FLASH -static int command_flash_erase(int argc, char **argv) +static int command_flash_erase(int argc, const char **argv) { int offset = -1; int size = -1; int rv; - if (flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) + if (crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) return EC_ERROR_ACCESS_DENIED; rv = parse_offset_size(argc, argv, 1, &offset, &size); @@ -1060,13 +1215,12 @@ static int command_flash_erase(int argc, char **argv) return rv; ccprintf("Erasing %d bytes at 0x%x...\n", size, offset); - return flash_erase(offset, size); + return crec_flash_erase(offset, size); } -DECLARE_CONSOLE_COMMAND(flasherase, command_flash_erase, - "offset size", +DECLARE_CONSOLE_COMMAND(flasherase, command_flash_erase, "offset size", "Erase flash"); -static int command_flash_write(int argc, char **argv) +static int command_flash_write(int argc, const char **argv) { int offset = -1; int size = -1; @@ -1074,7 +1228,7 @@ static int command_flash_write(int argc, char **argv) char *data; int i; - if (flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) + if (crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) return EC_ERROR_ACCESS_DENIED; rv = parse_offset_size(argc, argv, 1, &offset, &size); @@ -1096,23 +1250,22 @@ static int command_flash_write(int argc, char **argv) data[i] = i; ccprintf("Writing %d bytes to 0x%x...\n", size, offset); - rv = flash_write(offset, size, data); + rv = crec_flash_write(offset, size, data); /* Free the buffer */ shared_mem_release(data); return rv; } -DECLARE_CONSOLE_COMMAND(flashwrite, command_flash_write, - "offset size", +DECLARE_CONSOLE_COMMAND(flashwrite, command_flash_write, "offset size", "Write pattern to flash"); -static int command_flash_read(int argc, char **argv) +static int command_flash_read(int argc, const char **argv) { int offset = -1; int size = 256; int rv; - char *data; + uint8_t *data; int i; rv = parse_offset_size(argc, argv, 1, &offset, &size); @@ -1123,14 +1276,14 @@ static int command_flash_read(int argc, char **argv) size = shared_mem_size(); /* Acquire the shared memory buffer */ - rv = shared_mem_acquire(size, &data); + rv = shared_mem_acquire(size, (char **)&data); if (rv) { ccputs("Can't get shared mem\n"); return rv; } /* Read the data */ - if (flash_read(offset, size, data)) { + if (crec_flash_read(offset, size, data)) { shared_mem_release(data); return EC_ERROR_INVAL; } @@ -1151,12 +1304,12 @@ static int command_flash_read(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(flashread, command_flash_read, - "offset [size]", +DECLARE_CONSOLE_COMMAND(flashread, command_flash_read, "offset [size]", "Read flash"); #endif -static int command_flash_wp(int argc, char **argv) +#ifdef CONFIG_CMD_FLASH_WP +static int command_flash_wp(int argc, const char **argv) { int val; @@ -1164,34 +1317,36 @@ static int command_flash_wp(int argc, char **argv) return EC_ERROR_PARAM_COUNT; if (!strcasecmp(argv[1], "now")) - return flash_set_protect(EC_FLASH_PROTECT_ALL_NOW, -1); + return crec_flash_set_protect(EC_FLASH_PROTECT_ALL_NOW, -1); if (!strcasecmp(argv[1], "all")) - return flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, -1); + return crec_flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, -1); if (!strcasecmp(argv[1], "noall")) - return flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, 0); + return crec_flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, 0); #ifdef CONFIG_FLASH_PROTECT_RW if (!strcasecmp(argv[1], "rw")) - return flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, -1); + return crec_flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, -1); if (!strcasecmp(argv[1], "norw")) - return flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, 0); + return crec_flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, 0); #endif #ifdef CONFIG_ROLLBACK if (!strcasecmp(argv[1], "rb")) - return flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT, -1); + return crec_flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT, + -1); if (!strcasecmp(argv[1], "norb")) - return flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT, 0); + return crec_flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT, + 0); #endif /* Do this last, since anything starting with 'n' means "no" */ if (parse_bool(argv[1], &val)) - return flash_set_protect(EC_FLASH_PROTECT_RO_AT_BOOT, - val ? -1 : 0); + return crec_flash_set_protect(EC_FLASH_PROTECT_RO_AT_BOOT, + val ? -1 : 0); return EC_ERROR_PARAM1; } @@ -1203,7 +1358,9 @@ DECLARE_CONSOLE_COMMAND(flashwp, command_flash_wp, #ifdef CONFIG_ROLLBACK " | rb | norb" #endif - , "Modify flash write protect"); + , + "Modify flash write protect"); +#endif /* CONFIG_CMD_FLASH_WP */ /*****************************************************************************/ /* Host commands */ @@ -1218,40 +1375,24 @@ DECLARE_CONSOLE_COMMAND(flashwp, command_flash_wp, * region belonging to the EC. TODO(crbug.com/529365): Handle fmap_base * correctly in flashrom, dump_fmap, etc. and remove EC_FLASH_REGION_START. */ -#define EC_FLASH_REGION_START MIN(CONFIG_EC_PROTECTED_STORAGE_OFF, \ - CONFIG_EC_WRITABLE_STORAGE_OFF) +#define EC_FLASH_REGION_START \ + MIN(CONFIG_EC_PROTECTED_STORAGE_OFF, CONFIG_EC_WRITABLE_STORAGE_OFF) static enum ec_status flash_command_get_info(struct host_cmd_handler_args *args) { const struct ec_params_flash_info_2 *p_2 = args->params; struct ec_response_flash_info_2 *r_2 = args->response; -#ifdef CONFIG_FLASH_MULTIPLE_REGION - int banks_size = ARRAY_SIZE(flash_bank_array); - const struct ec_flash_bank *banks = flash_bank_array; -#else +#ifndef CONFIG_FLASH_MULTIPLE_REGION struct ec_response_flash_info_1 *r_1 = args->response; -#if CONFIG_FLASH_BANK_SIZE < CONFIG_FLASH_ERASE_SIZE -#error "Flash: Bank size expected bigger or equal to erase size." -#endif - struct ec_flash_bank single_bank = { - .count = CONFIG_FLASH_SIZE / CONFIG_FLASH_BANK_SIZE, - .size_exp = __fls(CONFIG_FLASH_BANK_SIZE), - .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE), - .erase_size_exp = __fls(CONFIG_FLASH_ERASE_SIZE), - .protect_size_exp = __fls(CONFIG_FLASH_BANK_SIZE), - }; - int banks_size = 1; - const struct ec_flash_bank *banks = &single_bank; #endif - int banks_len; - int ideal_size; + int res; /* * Compute the ideal amount of data for the host to send us, * based on the maximum response size and the ideal write size. */ - ideal_size = (args->response_max - - sizeof(struct ec_params_flash_write)) & + int ideal_size = + (args->response_max - sizeof(struct ec_params_flash_write)) & ~(CONFIG_FLASH_WRITE_IDEAL_SIZE - 1); /* * If we can't get at least one ideal block, then just want @@ -1259,13 +1400,13 @@ static enum ec_status flash_command_get_info(struct host_cmd_handler_args *args) */ if (!ideal_size) ideal_size = (args->response_max - - sizeof(struct ec_params_flash_write)) & - ~(CONFIG_FLASH_WRITE_SIZE - 1); - + sizeof(struct ec_params_flash_write)) & + ~(CONFIG_FLASH_WRITE_SIZE - 1); if (args->version >= 2) { args->response_size = sizeof(struct ec_response_flash_info_2); - r_2->flash_size = CONFIG_FLASH_SIZE - EC_FLASH_REGION_START; + r_2->flash_size = + CONFIG_FLASH_SIZE_BYTES - EC_FLASH_REGION_START; #if (CONFIG_FLASH_ERASED_VALUE32 == 0) r_2->flags = EC_FLASH_INFO_ERASE_TO_0; #else @@ -1275,17 +1416,22 @@ static enum ec_status flash_command_get_info(struct host_cmd_handler_args *args) r_2->flags |= EC_FLASH_INFO_SELECT_REQUIRED; #endif r_2->write_ideal_size = ideal_size; - r_2->num_banks_total = banks_size; - r_2->num_banks_desc = MIN(banks_size, p_2->num_banks_desc); - banks_len = r_2->num_banks_desc * sizeof(struct ec_flash_bank); - memcpy(r_2->banks, banks, banks_len); - args->response_size += banks_len; + /* + * Fill r_2->num_banks_desc, r_2->num_banks_total and + * r_2->banks. + */ + res = crec_flash_response_fill_banks(r_2, p_2->num_banks_desc); + if (res != EC_RES_SUCCESS) + return res; + + args->response_size += + r_2->num_banks_desc * sizeof(struct ec_flash_bank); return EC_RES_SUCCESS; } #ifdef CONFIG_FLASH_MULTIPLE_REGION return EC_RES_INVALID_PARAM; #else - r_1->flash_size = CONFIG_FLASH_SIZE - EC_FLASH_REGION_START; + r_1->flash_size = CONFIG_FLASH_SIZE_BYTES - EC_FLASH_REGION_START; r_1->flags = 0; r_1->write_block_size = CONFIG_FLASH_WRITE_SIZE; r_1->erase_block_size = CONFIG_FLASH_ERASE_SIZE; @@ -1305,16 +1451,14 @@ static enum ec_status flash_command_get_info(struct host_cmd_handler_args *args) #endif } return EC_RES_SUCCESS; -#endif /* CONFIG_FLASH_MULTIPLE_REGION */ +#endif /* CONFIG_FLASH_MULTIPLE_REGION */ } #ifdef CONFIG_FLASH_MULTIPLE_REGION #define FLASH_INFO_VER EC_VER_MASK(2) #else #define FLASH_INFO_VER (EC_VER_MASK(0) | EC_VER_MASK(1) | EC_VER_MASK(2)) #endif -DECLARE_HOST_COMMAND(EC_CMD_FLASH_INFO, - flash_command_get_info, FLASH_INFO_VER); - +DECLARE_HOST_COMMAND(EC_CMD_FLASH_INFO, flash_command_get_info, FLASH_INFO_VER); static enum ec_status flash_command_read(struct host_cmd_handler_args *args) { @@ -1324,16 +1468,14 @@ static enum ec_status flash_command_read(struct host_cmd_handler_args *args) if (p->size > args->response_max) return EC_RES_OVERFLOW; - if (flash_read(offset, p->size, args->response)) + if (crec_flash_read(offset, p->size, args->response)) return EC_RES_ERROR; args->response_size = p->size; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_FLASH_READ, - flash_command_read, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_FLASH_READ, flash_command_read, EC_VER_MASK(0)); /** * Flash write command @@ -1346,7 +1488,7 @@ static enum ec_status flash_command_write(struct host_cmd_handler_args *args) const struct ec_params_flash_write *p = args->params; uint32_t offset = p->offset + EC_FLASH_REGION_START; - if (flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) + if (crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) return EC_RES_ACCESS_DENIED; if (p->size + sizeof(*p) > args->params_size) @@ -1357,23 +1499,22 @@ static enum ec_status flash_command_write(struct host_cmd_handler_args *args) return EC_RES_ACCESS_DENIED; #endif - if (flash_write(offset, p->size, (const uint8_t *)(p + 1))) + if (crec_flash_write(offset, p->size, (const uint8_t *)(p + 1))) return EC_RES_ERROR; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_FLASH_WRITE, - flash_command_write, +DECLARE_HOST_COMMAND(EC_CMD_FLASH_WRITE, flash_command_write, EC_VER_MASK(0) | EC_VER_MASK(EC_VER_FLASH_WRITE)); #ifndef CONFIG_FLASH_MULTIPLE_REGION /* * Make sure our image sizes are a multiple of flash block erase size so that * the host can erase the entire image. + * Note that host (flashrom/depthcharge) does not erase/program the + * EC_FLASH_REGION_RO region, it only queries this region. */ -BUILD_ASSERT(CONFIG_RO_SIZE % CONFIG_FLASH_ERASE_SIZE == 0); -BUILD_ASSERT(CONFIG_RW_SIZE % CONFIG_FLASH_ERASE_SIZE == 0); -BUILD_ASSERT(EC_FLASH_REGION_RO_SIZE % CONFIG_FLASH_ERASE_SIZE == 0); +BUILD_ASSERT(CONFIG_WP_STORAGE_SIZE % CONFIG_FLASH_ERASE_SIZE == 0); BUILD_ASSERT(CONFIG_EC_WRITABLE_STORAGE_SIZE % CONFIG_FLASH_ERASE_SIZE == 0); #endif @@ -1393,7 +1534,7 @@ static enum ec_status flash_command_erase(struct host_cmd_handler_args *args) #endif offset = p->offset + EC_FLASH_REGION_START; - if (flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) + if (crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) return EC_RES_ACCESS_DENIED; #ifdef CONFIG_INTERNAL_STORAGE @@ -1407,7 +1548,7 @@ static enum ec_status flash_command_erase(struct host_cmd_handler_args *args) args->result = EC_RES_IN_PROGRESS; host_send_response(args); #endif - if (flash_erase(offset, p->size)) + if (crec_flash_erase(offset, p->size)) return EC_RES_ERROR; break; @@ -1418,6 +1559,7 @@ static enum ec_status flash_command_erase(struct host_cmd_handler_args *args) memcpy(&erase_info, p_1, sizeof(*p_1)); hook_call_deferred(&flash_erase_deferred_data, 100 * MSEC); + erase_rc = EC_RES_BUSY; } else { /* * Not our job to return the result of @@ -1439,16 +1581,115 @@ static enum ec_status flash_command_erase(struct host_cmd_handler_args *args) return rc; } - DECLARE_HOST_COMMAND(EC_CMD_FLASH_ERASE, flash_command_erase, - EC_VER_MASK(0) + EC_VER_MASK(0) #ifdef CONFIG_FLASH_DEFERRED_ERASE - | EC_VER_MASK(1) + | EC_VER_MASK(1) +#endif +); + +#ifdef CONFIG_FLASH_PROTECT_DEFERRED +struct flash_protect_async { + uint32_t mask; + uint32_t flags; + + volatile enum ec_status rc; +} __ec_align4; + +static struct flash_protect_async flash_protect_async_data = { + .rc = EC_RES_SUCCESS +}; + +static void crec_flash_set_protect_deferred(void) +{ + if (crec_flash_set_protect(flash_protect_async_data.mask, + flash_protect_async_data.flags)) + flash_protect_async_data.rc = EC_RES_ERROR; + else + flash_protect_async_data.rc = EC_RES_SUCCESS; +} +DECLARE_DEFERRED(crec_flash_set_protect_deferred); + +static enum ec_status +flash_command_protect_v2(struct host_cmd_handler_args *args) +{ + const struct ec_params_flash_protect_v2 *p = args->params; + struct ec_response_flash_protect *r = args->response; + int rc = EC_RES_SUCCESS; + + flash_protect_async_data.mask = p->mask; + flash_protect_async_data.flags = p->flags; + + /* + * Handle requesting new flags. Note that we ignore the return code + * from flash_set_protect(), since errors will be visible to the caller + * via the flags in the response. (If we returned error, the caller + * wouldn't get the response.) + */ + + switch (p->action) { + case FLASH_PROTECT_ASYNC: + if (p->mask) { + rc = flash_protect_async_data.rc; + if (rc != EC_RES_SUCCESS) { + rc = EC_RES_BUSY; + break; + } + hook_call_deferred( + &crec_flash_set_protect_deferred_data, + 100 * MSEC); + /* Not our job to return the result of + * the previous command. + */ + flash_protect_async_data.rc = EC_RES_BUSY; + } + return EC_RES_SUCCESS; + + case FLASH_PROTECT_GET_RESULT: + /* + * Retrieve the current flags. The caller can use this + * to determine which of the requested flags could be + * set. This is cleaner than simply returning error, + * because it provides information to the caller about + * the actual result. + */ + rc = flash_protect_async_data.rc; + if (rc == EC_RES_BUSY || rc == EC_RES_ERROR) + break; + + r->flags = crec_flash_get_protect(); + + /* Indicate which flags are valid on this platform */ + r->valid_flags = EC_FLASH_PROTECT_GPIO_ASSERTED | + EC_FLASH_PROTECT_ERROR_STUCK | + EC_FLASH_PROTECT_ERROR_INCONSISTENT | + EC_FLASH_PROTECT_ERROR_UNKNOWN | + crec_flash_physical_get_valid_flags(); + r->writable_flags = + crec_flash_physical_get_writable_flags(r->flags); + + args->response_size = sizeof(*r); + + /* Ready for another command */ + flash_protect_async_data.rc = EC_RES_SUCCESS; + break; + + default: + rc = EC_RES_INVALID_PARAM; + } + + return rc; +} #endif - ); static enum ec_status flash_command_protect(struct host_cmd_handler_args *args) { +#if defined(CONFIG_FLASH_PROTECT_DEFERRED) + if (args->version == 2) { + return flash_command_protect_v2(args); + } +#endif + const struct ec_params_flash_protect *p = args->params; struct ec_response_flash_protect *r = args->response; @@ -1459,7 +1700,7 @@ static enum ec_status flash_command_protect(struct host_cmd_handler_args *args) * wouldn't get the response.) */ if (p->mask) - flash_set_protect(p->mask, p->flags); + crec_flash_set_protect(p->mask, p->flags); /* * Retrieve the current flags. The caller can use this to determine @@ -1467,29 +1708,27 @@ static enum ec_status flash_command_protect(struct host_cmd_handler_args *args) * simply returning error, because it provides information to the * caller about the actual result. */ - r->flags = flash_get_protect(); + r->flags = crec_flash_get_protect(); /* Indicate which flags are valid on this platform */ - r->valid_flags = - EC_FLASH_PROTECT_GPIO_ASSERTED | - EC_FLASH_PROTECT_ERROR_STUCK | - EC_FLASH_PROTECT_ERROR_INCONSISTENT | - flash_physical_get_valid_flags(); - r->writable_flags = flash_physical_get_writable_flags(r->flags); + r->valid_flags = EC_FLASH_PROTECT_GPIO_ASSERTED | + EC_FLASH_PROTECT_ERROR_STUCK | + EC_FLASH_PROTECT_ERROR_INCONSISTENT | + EC_FLASH_PROTECT_ERROR_UNKNOWN | + crec_flash_physical_get_valid_flags(); + r->writable_flags = crec_flash_physical_get_writable_flags(r->flags); args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -/* - * TODO(crbug.com/239197) : Adding both versions to the version mask is a - * temporary workaround for a problem in the cros_ec driver. Drop - * EC_VER_MASK(0) once cros_ec driver can send the correct version. - */ -DECLARE_HOST_COMMAND(EC_CMD_FLASH_PROTECT, - flash_command_protect, - EC_VER_MASK(0) | EC_VER_MASK(1)); +DECLARE_HOST_COMMAND(EC_CMD_FLASH_PROTECT, flash_command_protect, + EC_VER_MASK(1) +#ifdef CONFIG_FLASH_PROTECT_DEFERRED + | EC_VER_MASK(2) +#endif +); static enum ec_status flash_command_region_info(struct host_cmd_handler_args *args) @@ -1500,23 +1739,21 @@ flash_command_region_info(struct host_cmd_handler_args *args) switch (p->region) { case EC_FLASH_REGION_RO: r->offset = CONFIG_EC_PROTECTED_STORAGE_OFF + - CONFIG_RO_STORAGE_OFF - - EC_FLASH_REGION_START; + CONFIG_RO_STORAGE_OFF - EC_FLASH_REGION_START; r->size = EC_FLASH_REGION_RO_SIZE; break; case EC_FLASH_REGION_ACTIVE: r->offset = flash_get_rw_offset(system_get_active_copy()) - - EC_FLASH_REGION_START; + EC_FLASH_REGION_START; r->size = CONFIG_EC_WRITABLE_STORAGE_SIZE; break; case EC_FLASH_REGION_WP_RO: - r->offset = CONFIG_WP_STORAGE_OFF - - EC_FLASH_REGION_START; + r->offset = CONFIG_WP_STORAGE_OFF - EC_FLASH_REGION_START; r->size = CONFIG_WP_STORAGE_SIZE; break; case EC_FLASH_REGION_UPDATE: r->offset = flash_get_rw_offset(system_get_update_copy()) - - EC_FLASH_REGION_START; + EC_FLASH_REGION_START; r->size = CONFIG_EC_WRITABLE_STORAGE_SIZE; break; default: @@ -1526,21 +1763,17 @@ flash_command_region_info(struct host_cmd_handler_args *args) args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_FLASH_REGION_INFO, - flash_command_region_info, +DECLARE_HOST_COMMAND(EC_CMD_FLASH_REGION_INFO, flash_command_region_info, EC_VER_MASK(EC_VER_FLASH_REGION_INFO)); - #ifdef CONFIG_FLASH_SELECT_REQUIRED static enum ec_status flash_command_select(struct host_cmd_handler_args *args) { const struct ec_params_flash_select *p = args->params; - return board_flash_select(p->select); + return crec_board_flash_select(p->select); } -DECLARE_HOST_COMMAND(EC_CMD_FLASH_SELECT, - flash_command_select, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_FLASH_SELECT, flash_command_select, EC_VER_MASK(0)); #endif /* CONFIG_FLASH_SELECT_REQUIRED */ diff --git a/common/fmap.c b/common/fmap.c index 001f83a184..0fa77c47cd 100644 --- a/common/fmap.c +++ b/common/fmap.c @@ -1,19 +1,20 @@ /* - * Copyright 2012 The Chromium OS Authors. All rights reserved. + * Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include - #include "common.h" +#include "cros_version.h" #include "rwsig.h" #include "util.h" -#include "version.h" + +#include /* * FMAP structs. - * See https://chromium.googlesource.com/chromiumos/third_party/flashmap/+/master/lib/fmap.h + * See + * https://chromium.googlesource.com/chromiumos/third_party/flashmap/+/HEAD/lib/fmap.h */ #define FMAP_NAMELEN 32 #define FMAP_SIGNATURE "__FMAP__" @@ -25,8 +26,8 @@ * For address containing CONFIG_PROGRAM_MEMORY_BASE (symbols in *.RO.lds.S and * variable), this computes the offset to the start of the image on flash. */ -#define RELATIVE_RO(addr) ((addr) - CONFIG_PROGRAM_MEMORY_BASE - \ - CONFIG_RO_MEM_OFF) +#define RELATIVE_RO(addr) \ + ((addr)-CONFIG_PROGRAM_MEMORY_BASE - CONFIG_RO_MEM_OFF) /* * All internal EC code assumes that offsets are provided relative to @@ -45,23 +46,23 @@ #endif struct fmap_header { - char fmap_signature[FMAP_SIGNATURE_SIZE]; - uint8_t fmap_ver_major; - uint8_t fmap_ver_minor; - uint64_t fmap_base; - uint32_t fmap_size; - char fmap_name[FMAP_NAMELEN]; - uint16_t fmap_nareas; + char fmap_signature[FMAP_SIGNATURE_SIZE]; + uint8_t fmap_ver_major; + uint8_t fmap_ver_minor; + uint64_t fmap_base; + uint32_t fmap_size; + char fmap_name[FMAP_NAMELEN]; + uint16_t fmap_nareas; } __packed; -#define FMAP_AREA_STATIC BIT(0) /* can be checksummed */ -#define FMAP_AREA_COMPRESSED BIT(1) /* may be compressed */ -#define FMAP_AREA_RO BIT(2) /* writes may fail */ +#define FMAP_AREA_STATIC BIT(0) /* can be checksummed */ +#define FMAP_AREA_COMPRESSED BIT(1) /* may be compressed */ +#define FMAP_AREA_RO BIT(2) /* writes may fail */ struct fmap_area_header { uint32_t area_offset; uint32_t area_size; - char area_name[FMAP_NAMELEN]; + char area_name[FMAP_NAMELEN]; uint16_t area_flags; } __packed; @@ -77,19 +78,18 @@ struct fmap_area_header { #define NUM_EC_FMAP_AREAS_ROLLBACK 0 #endif #ifdef CONFIG_RW_B -# ifdef CONFIG_RWSIG_TYPE_RWSIG -# define NUM_EC_FMAP_AREAS_RW_B 2 -# else -# define NUM_EC_FMAP_AREAS_RW_B 1 -# endif +#ifdef CONFIG_RWSIG_TYPE_RWSIG +#define NUM_EC_FMAP_AREAS_RW_B 2 +#else +#define NUM_EC_FMAP_AREAS_RW_B 1 +#endif #else -#define NUM_EC_FMAP_AREAS_RW_B 0 +#define NUM_EC_FMAP_AREAS_RW_B 0 #endif -#define NUM_EC_FMAP_AREAS (7 + \ - NUM_EC_FMAP_AREAS_RWSIG + \ - NUM_EC_FMAP_AREAS_ROLLBACK + \ - NUM_EC_FMAP_AREAS_RW_B) +#define NUM_EC_FMAP_AREAS \ + (7 + NUM_EC_FMAP_AREAS_RWSIG + NUM_EC_FMAP_AREAS_ROLLBACK + \ + NUM_EC_FMAP_AREAS_RW_B) const struct _ec_fmap { struct fmap_header header; @@ -97,18 +97,18 @@ const struct _ec_fmap { } ec_fmap __keep __attribute__((section(".google"))) = { /* Header */ { - .fmap_signature = {'_', '_', 'F', 'M', 'A', 'P', '_', '_'}, + .fmap_signature = { '_', '_', 'F', 'M', 'A', 'P', '_', '_' }, .fmap_ver_major = FMAP_VER_MAJOR, .fmap_ver_minor = FMAP_VER_MINOR, .fmap_base = CONFIG_PROGRAM_MEMORY_BASE, - .fmap_size = CONFIG_FLASH_SIZE, + .fmap_size = CONFIG_FLASH_SIZE_BYTES, /* Used to distinguish the EC FMAP from other FMAPs */ .fmap_name = "EC_FMAP", .fmap_nareas = NUM_EC_FMAP_AREAS, }, { - /* RO Firmware */ + /* RO Firmware */ { /* * Range of RO firmware to be updated. EC_RO @@ -120,7 +120,7 @@ const struct _ec_fmap { */ .area_name = "EC_RO", .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF - - FMAP_REGION_START, + FMAP_REGION_START, .area_size = CONFIG_RO_SIZE + CONFIG_RO_STORAGE_OFF, .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, @@ -128,7 +128,8 @@ const struct _ec_fmap { /* (Optional) RO firmware code. */ .area_name = "FR_MAIN", .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF - - FMAP_REGION_START + CONFIG_RO_STORAGE_OFF, + FMAP_REGION_START + + CONFIG_RO_STORAGE_OFF, .area_size = CONFIG_RO_SIZE, .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, @@ -138,10 +139,11 @@ const struct _ec_fmap { * ASCII, and padded with \0. */ .area_name = "RO_FRID", - .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF - + .area_offset = + CONFIG_EC_PROTECTED_STORAGE_OFF - FMAP_REGION_START + CONFIG_RO_STORAGE_OFF + RELATIVE_RO((uint32_t)__image_data_offset) + - offsetof(struct image_data, version), + offsetof(struct image_data, version), .area_size = sizeof(current_image_data.version), .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, @@ -150,8 +152,9 @@ const struct _ec_fmap { { .area_name = "FMAP", .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF - - FMAP_REGION_START + CONFIG_RO_STORAGE_OFF + - RELATIVE_RO((uint32_t)&ec_fmap), + FMAP_REGION_START + + CONFIG_RO_STORAGE_OFF + + RELATIVE_RO((uint32_t)&ec_fmap), .area_size = sizeof(ec_fmap), .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, @@ -162,8 +165,7 @@ const struct _ec_fmap { * EC_RO and aligned to hardware specification. */ .area_name = "WP_RO", - .area_offset = CONFIG_WP_STORAGE_OFF - - FMAP_REGION_START, + .area_offset = CONFIG_WP_STORAGE_OFF - FMAP_REGION_START, .area_size = CONFIG_WP_STORAGE_SIZE, .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, @@ -172,8 +174,9 @@ const struct _ec_fmap { /* RO public key address, for RW verification */ .area_name = "KEY_RO", .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF - - FMAP_REGION_START + CONFIG_RO_PUBKEY_ADDR - - CONFIG_PROGRAM_MEMORY_BASE, + FMAP_REGION_START + + CONFIG_RO_PUBKEY_ADDR - + CONFIG_PROGRAM_MEMORY_BASE, .area_size = CONFIG_RO_PUBKEY_SIZE, .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, @@ -181,10 +184,11 @@ const struct _ec_fmap { /* RW Firmware */ { - /* The range of RW firmware to be auto-updated. */ + /* The range of RW firmware to be auto-updated. */ .area_name = "EC_RW", .area_offset = CONFIG_EC_WRITABLE_STORAGE_OFF - - FMAP_REGION_START + CONFIG_RW_STORAGE_OFF, + FMAP_REGION_START + + CONFIG_RW_STORAGE_OFF, .area_size = CONFIG_RW_SIZE, .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, @@ -197,10 +201,11 @@ const struct _ec_fmap { * accommodate image asymmetry. */ .area_name = "RW_FWID", - .area_offset = CONFIG_EC_WRITABLE_STORAGE_OFF - + .area_offset = + CONFIG_EC_WRITABLE_STORAGE_OFF - FMAP_REGION_START + CONFIG_RW_STORAGE_OFF + RELATIVE_RO((uint32_t)__image_data_offset) + - offsetof(struct image_data, version), + offsetof(struct image_data, version), .area_size = sizeof(current_image_data.version), .area_flags = FMAP_AREA_STATIC, }, @@ -213,22 +218,22 @@ const struct _ec_fmap { * accommodate image asymmetry. */ .area_name = "RW_RBVER", - .area_offset = CONFIG_EC_WRITABLE_STORAGE_OFF - + .area_offset = + CONFIG_EC_WRITABLE_STORAGE_OFF - FMAP_REGION_START + CONFIG_RW_STORAGE_OFF + RELATIVE_RO((uint32_t)__image_data_offset) + offsetof(struct image_data, rollback_version), - .area_size = sizeof( - current_image_data.rollback_version), + .area_size = sizeof(current_image_data.rollback_version), .area_flags = FMAP_AREA_STATIC, }, #endif #ifdef CONFIG_RWSIG_TYPE_RWSIG { - /* RW image signature */ + /* RW image signature */ .area_name = "SIG_RW", .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF - - FMAP_REGION_START + CONFIG_RW_SIG_ADDR - - CONFIG_PROGRAM_MEMORY_BASE, + FMAP_REGION_START + CONFIG_RW_SIG_ADDR - + CONFIG_PROGRAM_MEMORY_BASE, .area_size = CONFIG_RW_SIG_SIZE, .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, @@ -236,21 +241,22 @@ const struct _ec_fmap { #ifdef CONFIG_RW_B /* RW Firmware */ { - /* The range of RW firmware to be auto-updated. */ + /* The range of RW firmware to be auto-updated. */ .area_name = "EC_RW_B", .area_offset = CONFIG_EC_WRITABLE_STORAGE_OFF - - FMAP_REGION_START + CONFIG_RW_STORAGE_OFF + - CONFIG_RW_SIZE, + FMAP_REGION_START + + CONFIG_RW_STORAGE_OFF + CONFIG_RW_SIZE, .area_size = CONFIG_RW_SIZE, .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, #ifdef CONFIG_RWSIG_TYPE_RWSIG { - /* RW_B image signature */ + /* RW_B image signature */ .area_name = "SIG_RW_B", .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF - - FMAP_REGION_START + CONFIG_RW_B_SIG_ADDR - - CONFIG_PROGRAM_MEMORY_BASE, + FMAP_REGION_START + + CONFIG_RW_B_SIG_ADDR - + CONFIG_PROGRAM_MEMORY_BASE, .area_size = CONFIG_RW_SIG_SIZE, .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, diff --git a/common/fpsensor/OWNERS b/common/fpsensor/OWNERS index 41820f5b0c..bccfa32fde 100644 --- a/common/fpsensor/OWNERS +++ b/common/fpsensor/OWNERS @@ -3,5 +3,4 @@ # Don't inherit owners from elsewhere in the manifest set noparent -tomhughes@chromium.org -adlr@chromium.org +include chromiumos/platform2:/biod/OWNERS diff --git a/common/fpsensor/build.mk b/common/fpsensor/build.mk index d7e0e72b63..129deb484d 100644 --- a/common/fpsensor/build.mk +++ b/common/fpsensor/build.mk @@ -1,13 +1,64 @@ -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # Build for fingerprint sensor +# Only build if CONFIG_FINGERPRINT_MCU or TEST_BUILD is "y". +ifneq (,$(filter y,$(CONFIG_FINGERPRINT_MCU) $(TEST_BUILD))) + # Note that this variable includes the trailing "/" _fpsensor_dir:=$(dir $(lastword $(MAKEFILE_LIST))) -all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)fpsensor_state.o -all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)fpsensor_crypto.o -all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)fpsensor.o -all-obj-$(HAS_TASK_CONSOLE)+=$(_fpsensor_dir)fpsensor_detect_strings.o +# Additional CFLAGS for only fpsensor objects +fpsensor_CFLAGS=-Wvla + +_fpsensor_state_obj:=$(_fpsensor_dir)fpsensor_state.o +_fpsensor_crypto_obj:=$(_fpsensor_dir)fpsensor_crypto.o +_fpsensor_obj:=$(_fpsensor_dir)fpsensor.o +_fpsensor_detect_strings_obj:=$(_fpsensor_dir)fpsensor_detect_strings.o +_fpsensor_debug_obj:=$(_fpsensor_dir)fpsensor_debug.o +_fpsensor_auth_commands_obj:=$(_fpsensor_dir)fpsensor_auth_commands.o +_fpsensor_auth_crypto_stateful_obj:=$(_fpsensor_dir)fpsensor_auth_crypto_stateful.o +_fpsensor_auth_crypto_stateless_obj:=$(_fpsensor_dir)fpsensor_auth_crypto_stateless.o +_fpsensor_state_without_driver_info_obj:=$(_fpsensor_dir)fpsensor_state_without_driver_info.o + +$(out)/RW/$(_fpsensor_state_obj): CFLAGS+=$(fpsensor_CFLAGS) +$(out)/RW/$(_fpsensor_crypto_obj): CFLAGS+=$(fpsensor_CFLAGS) +$(out)/RW/$(_fpsensor_obj): CFLAGS+=$(fpsensor_CFLAGS) +$(out)/RW/$(_fpsensor_detect_strings_obj): CFLAGS+=$(fpsensor_CFLAGS) +$(out)/RW/$(_fpsensor_debug_obj): CFLAGS+=$(fpsensor_CFLAGS) +$(out)/RW/$(_fpsensor_auth_commands_obj): CFLAGS+=$(fpsensor_CFLAGS) +$(out)/RW/$(_fpsensor_auth_crypto_stateful_obj): CFLAGS+=$(fpsensor_CFLAGS) +$(out)/RW/$(_fpsensor_auth_crypto_stateless_obj): CFLAGS+=$(fpsensor_CFLAGS) +$(out)/RW/$(_fpsensor_state_without_driver_info_obj): CFLAGS+=$(fpsensor_CFLAGS) + +all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_state_obj) +all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_obj) +all-obj-$(HAS_TASK_CONSOLE)+=$(_fpsensor_detect_strings_obj) +all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_debug_obj) +all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_auth_commands_obj) + +# If HAS_TASK_FPSENSOR is not empty. +ifneq (,$(HAS_TASK_FPSENSOR)) +all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_auth_crypto_stateless_obj) +endif # HAS_TASK_FPSENSOR. +# Or we are building fpsensor related projects. +ifeq (fpsensor,$(findstring fpsensor,$(PROJECT))) +all-obj-y+=$(_fpsensor_auth_crypto_stateless_obj) +endif # fpsensor projects. + +# If HAS_TASK_FPSENSOR is not empty. +ifneq (,$(HAS_TASK_FPSENSOR)) +all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_crypto_obj) +all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_state_without_driver_info_obj) +all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_auth_crypto_stateful_obj) +endif # HAS_TASK_FPSENSOR. +# Or we are building stateful fpsensor related projects. +ifeq (fpsensor,$(findstring fpsensor,$(PROJECT))$(findstring stateless,$(PROJECT))) +all-obj-y+=$(_fpsensor_crypto_obj) +all-obj-y+=$(_fpsensor_state_without_driver_info_obj) +all-obj-y+=$(_fpsensor_auth_crypto_stateful_obj) +endif # stateful fpsensor projects. + +endif # CONFIG_FINGERPRINT_MCU or TEST_BUILD diff --git a/common/fpsensor/fpsensor.c b/common/fpsensor/fpsensor.c deleted file mode 100644 index 5611fd828d..0000000000 --- a/common/fpsensor/fpsensor.c +++ /dev/null @@ -1,853 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "atomic.h" -#include "clock.h" -#include "common.h" -#include "console.h" -#include "cryptoc/util.h" -#include "ec_commands.h" -#include "fpsensor.h" -#include "fpsensor_crypto.h" -#include "fpsensor_detect.h" -#include "fpsensor_private.h" -#include "fpsensor_state.h" -#include "gpio.h" -#include "host_command.h" -#include "link_defs.h" -#include "mkbp_event.h" -#include "overflow.h" -#include "spi.h" -#include "system.h" -#include "task.h" -#include "trng.h" -#include "util.h" -#include "watchdog.h" - -#if !defined(CONFIG_RNG) -#error "fpsensor requires RNG" -#endif - -/* Ready to encrypt a template. */ -static timestamp_t encryption_deadline; - -/* raw image offset inside the acquired frame */ -#ifndef FP_SENSOR_IMAGE_OFFSET -#define FP_SENSOR_IMAGE_OFFSET 0 -#endif - -#define FP_MODE_ANY_CAPTURE (FP_MODE_CAPTURE | FP_MODE_ENROLL_IMAGE | \ - FP_MODE_MATCH) -#define FP_MODE_ANY_DETECT_FINGER (FP_MODE_FINGER_DOWN | FP_MODE_FINGER_UP | \ - FP_MODE_ANY_CAPTURE) -#define FP_MODE_ANY_WAIT_IRQ (FP_MODE_FINGER_DOWN | FP_MODE_ANY_CAPTURE) - -/* Delay between 2 s of the sensor to detect finger removal */ -#define FINGER_POLLING_DELAY (100*MSEC) - -/* Timing statistics. */ -static uint32_t capture_time_us; -static uint32_t matching_time_us; -static uint32_t overall_time_us; -static timestamp_t overall_t0; -static uint8_t timestamps_invalid; - -BUILD_ASSERT(sizeof(struct ec_fp_template_encryption_metadata) % 4 == 0); - -/* Interrupt line from the fingerprint sensor */ -void fps_event(enum gpio_signal signal) -{ - task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_SENSOR_IRQ, 0); -} - -static void send_mkbp_event(uint32_t event) -{ - deprecated_atomic_or(&fp_events, event); - mkbp_send_event(EC_MKBP_EVENT_FINGERPRINT); -} - -static inline int is_raw_capture(uint32_t mode) -{ - int capture_type = FP_CAPTURE_TYPE(mode); - - return (capture_type == FP_CAPTURE_VENDOR_FORMAT - || capture_type == FP_CAPTURE_QUALITY_TEST); -} - -#ifdef HAVE_FP_PRIVATE_DRIVER -static inline int is_test_capture(uint32_t mode) -{ - int capture_type = FP_CAPTURE_TYPE(mode); - - return (mode & FP_MODE_CAPTURE) - && (capture_type == FP_CAPTURE_PATTERN0 - || capture_type == FP_CAPTURE_PATTERN1 - || capture_type == FP_CAPTURE_RESET_TEST); -} - -/* - * contains the bit FP_MODE_ENROLL_SESSION if a finger enrollment is on-going. - * It is used to detect the ENROLL_SESSION transition when sensor_mode is - * updated by the host. - */ -static uint32_t enroll_session; - -static uint32_t fp_process_enroll(void) -{ - int percent = 0; - int res; - - if (template_newly_enrolled != FP_NO_SUCH_TEMPLATE) - CPRINTS("Warning: previously enrolled template has not been " - "read yet."); - - /* begin/continue enrollment */ - CPRINTS("[%d]Enrolling ...", templ_valid); - res = fp_finger_enroll(fp_buffer, &percent); - CPRINTS("[%d]Enroll =>%d (%d%%)", templ_valid, res, percent); - if (res < 0) - return EC_MKBP_FP_ENROLL - | EC_MKBP_FP_ERRCODE(EC_MKBP_FP_ERR_ENROLL_INTERNAL); - templ_dirty |= BIT(templ_valid); - if (percent == 100) { - res = fp_enrollment_finish(fp_template[templ_valid]); - if (res) { - res = EC_MKBP_FP_ERR_ENROLL_INTERNAL; - } else { - template_newly_enrolled = templ_valid; - fp_enable_positive_match_secret(templ_valid, - &positive_match_secret_state); - templ_valid++; - } - sensor_mode &= ~FP_MODE_ENROLL_SESSION; - enroll_session &= ~FP_MODE_ENROLL_SESSION; - } - return EC_MKBP_FP_ENROLL | EC_MKBP_FP_ERRCODE(res) - | (percent << EC_MKBP_FP_ENROLL_PROGRESS_OFFSET); -} - -static uint32_t fp_process_match(void) -{ - timestamp_t t0 = get_time(); - int res = -1; - uint32_t updated = 0; - int32_t fgr = FP_NO_SUCH_TEMPLATE; - - /* match finger against current templates */ - fp_disable_positive_match_secret(&positive_match_secret_state); - CPRINTS("Matching/%d ...", templ_valid); - if (templ_valid) { - res = fp_finger_match(fp_template[0], templ_valid, fp_buffer, - &fgr, &updated); - CPRINTS("Match =>%d (finger %d)", res, fgr); - if (res < 0 || fgr < 0 || fgr >= FP_MAX_FINGER_COUNT) { - res = EC_MKBP_FP_ERR_MATCH_NO_INTERNAL; - timestamps_invalid |= FPSTATS_MATCHING_INV; - } else { - fp_enable_positive_match_secret(fgr, - &positive_match_secret_state); - } - if (res == EC_MKBP_FP_ERR_MATCH_YES_UPDATED) - templ_dirty |= updated; - } else { - CPRINTS("No enrolled templates"); - res = EC_MKBP_FP_ERR_MATCH_NO_TEMPLATES; - timestamps_invalid |= FPSTATS_MATCHING_INV; - } - matching_time_us = time_since32(t0); - return EC_MKBP_FP_MATCH | EC_MKBP_FP_ERRCODE(res) - | ((fgr << EC_MKBP_FP_MATCH_IDX_OFFSET) & EC_MKBP_FP_MATCH_IDX_MASK); -} - -static void fp_process_finger(void) -{ - timestamp_t t0 = get_time(); - int res = fp_sensor_acquire_image_with_mode(fp_buffer, - FP_CAPTURE_TYPE(sensor_mode)); - capture_time_us = time_since32(t0); - if (!res) { - uint32_t evt = EC_MKBP_FP_IMAGE_READY; - - /* Clean up SPI before clocking up to avoid hang on the dsb - * in dma_go. Ignore the return value to let the WDT reboot - * the MCU (and avoid getting trapped in the loop). - * b/112781659 */ - res = spi_transaction_flush(&spi_devices[0]); - if (res) - CPRINTS("Failed to flush SPI: 0x%x", res); - /* we need CPU power to do the computations */ - clock_enable_module(MODULE_FAST_CPU, 1); - - if (sensor_mode & FP_MODE_ENROLL_IMAGE) - evt = fp_process_enroll(); - else if (sensor_mode & FP_MODE_MATCH) - evt = fp_process_match(); - - sensor_mode &= ~FP_MODE_ANY_CAPTURE; - overall_time_us = time_since32(overall_t0); - send_mkbp_event(evt); - - /* go back to lower power mode */ - clock_enable_module(MODULE_FAST_CPU, 0); - } else { - timestamps_invalid |= FPSTATS_CAPTURE_INV; - } -} -#endif /* HAVE_FP_PRIVATE_DRIVER */ - -void fp_task(void) -{ - int timeout_us = -1; - - CPRINTS("FP_SENSOR_SEL: %s", - fp_sensor_type_to_str(get_fp_sensor_type())); - -#ifdef HAVE_FP_PRIVATE_DRIVER - /* Reset and initialize the sensor IC */ - fp_sensor_init(); - - while (1) { - uint32_t evt; - enum finger_state st = FINGER_NONE; - - /* Wait for a sensor IRQ or a new mode configuration */ - evt = task_wait_event(timeout_us); - - if (evt & TASK_EVENT_UPDATE_CONFIG) { - uint32_t mode = sensor_mode; - - gpio_disable_interrupt(GPIO_FPS_INT); - if ((mode ^ enroll_session) & FP_MODE_ENROLL_SESSION) { - if (mode & FP_MODE_ENROLL_SESSION) { - if (fp_enrollment_begin()) - sensor_mode &= - ~FP_MODE_ENROLL_SESSION; - } else { - fp_enrollment_finish(NULL); - } - enroll_session = - sensor_mode & FP_MODE_ENROLL_SESSION; - } - if (is_test_capture(mode)) { - fp_sensor_acquire_image_with_mode(fp_buffer, - FP_CAPTURE_TYPE(mode)); - sensor_mode &= ~FP_MODE_CAPTURE; - send_mkbp_event(EC_MKBP_FP_IMAGE_READY); - continue; - } else if (sensor_mode & FP_MODE_ANY_DETECT_FINGER) { - /* wait for a finger on the sensor */ - fp_sensor_configure_detect(); - } - if (sensor_mode & FP_MODE_DEEPSLEEP) - /* Shutdown the sensor */ - fp_sensor_low_power(); - if (sensor_mode & FP_MODE_FINGER_UP) - /* Poll the sensor to detect finger removal */ - timeout_us = FINGER_POLLING_DELAY; - else - timeout_us = -1; - if (mode & FP_MODE_ANY_WAIT_IRQ) { - gpio_enable_interrupt(GPIO_FPS_INT); - } else if (mode & FP_MODE_RESET_SENSOR) { - fp_reset_and_clear_context(); - sensor_mode &= ~FP_MODE_RESET_SENSOR; - } else if (mode & FP_MODE_SENSOR_MAINTENANCE) { - fp_maintenance(); - sensor_mode &= ~FP_MODE_SENSOR_MAINTENANCE; - } else { - fp_sensor_low_power(); - } - } else if (evt & (TASK_EVENT_SENSOR_IRQ | TASK_EVENT_TIMER)) { - overall_t0 = get_time(); - timestamps_invalid = 0; - gpio_disable_interrupt(GPIO_FPS_INT); - if (sensor_mode & FP_MODE_ANY_DETECT_FINGER) { - st = fp_sensor_finger_status(); - if (st == FINGER_PRESENT && - sensor_mode & FP_MODE_FINGER_DOWN) { - CPRINTS("Finger!"); - sensor_mode &= ~FP_MODE_FINGER_DOWN; - send_mkbp_event(EC_MKBP_FP_FINGER_DOWN); - } - if (st == FINGER_NONE && - sensor_mode & FP_MODE_FINGER_UP) { - sensor_mode &= ~FP_MODE_FINGER_UP; - timeout_us = -1; - send_mkbp_event(EC_MKBP_FP_FINGER_UP); - } - } - - if (st == FINGER_PRESENT && - sensor_mode & FP_MODE_ANY_CAPTURE) - fp_process_finger(); - - if (sensor_mode & FP_MODE_ANY_WAIT_IRQ) { - fp_sensor_configure_detect(); - gpio_enable_interrupt(GPIO_FPS_INT); - } else { - fp_sensor_low_power(); - } - } - } -#else /* !HAVE_FP_PRIVATE_DRIVER */ - while (1) { - uint32_t evt = task_wait_event(timeout_us); - - send_mkbp_event(evt); - } -#endif /* !HAVE_FP_PRIVATE_DRIVER */ -} - -static enum ec_status fp_command_passthru(struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_passthru *params = args->params; - void *out = args->response; - int rc; - int ret = EC_RES_SUCCESS; - - if (system_is_locked()) - return EC_RES_ACCESS_DENIED; - - if (params->len > args->params_size + - offsetof(struct ec_params_fp_passthru, data) || - params->len > args->response_max) - return EC_RES_INVALID_PARAM; - - rc = spi_transaction_async(&spi_devices[0], params->data, - params->len, out, SPI_READBACK_ALL); - if (params->flags & EC_FP_FLAG_NOT_COMPLETE) - rc |= spi_transaction_wait(&spi_devices[0]); - else - rc |= spi_transaction_flush(&spi_devices[0]); - - if (rc == EC_ERROR_TIMEOUT) - ret = EC_RES_TIMEOUT; - else if (rc) - ret = EC_RES_ERROR; - - args->response_size = params->len; - return ret; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_PASSTHRU, fp_command_passthru, EC_VER_MASK(0)); - -static enum ec_status fp_command_info(struct host_cmd_handler_args *args) -{ - struct ec_response_fp_info *r = args->response; - -#ifdef HAVE_FP_PRIVATE_DRIVER - if (fp_sensor_get_info(r) < 0) -#endif - return EC_RES_UNAVAILABLE; - - r->template_size = FP_ALGORITHM_ENCRYPTED_TEMPLATE_SIZE; - r->template_max = FP_MAX_FINGER_COUNT; - r->template_valid = templ_valid; - r->template_dirty = templ_dirty; - r->template_version = FP_TEMPLATE_FORMAT_VERSION; - - /* V1 is identical to V0 with more information appended */ - args->response_size = args->version ? sizeof(*r) : - sizeof(struct ec_response_fp_info_v0); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_INFO, fp_command_info, - EC_VER_MASK(0) | EC_VER_MASK(1)); - -BUILD_ASSERT(FP_CONTEXT_NONCE_BYTES == 12); - -int validate_fp_buffer_offset(const uint32_t buffer_size, const uint32_t offset, - const uint32_t size) -{ - uint32_t bytes_requested; - - if (check_add_overflow(size, offset, &bytes_requested)) - return EC_ERROR_OVERFLOW; - - if (bytes_requested > buffer_size) - return EC_ERROR_INVAL; - - return EC_SUCCESS; -} - -static enum ec_status fp_command_frame(struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_frame *params = args->params; - void *out = args->response; - uint32_t idx = FP_FRAME_GET_BUFFER_INDEX(params->offset); - uint32_t offset = params->offset & FP_FRAME_OFFSET_MASK; - uint32_t size = params->size; - uint32_t fgr; - uint8_t key[SBP_ENC_KEY_LEN]; - struct ec_fp_template_encryption_metadata *enc_info; - int ret; - - if (size > args->response_max) - return EC_RES_INVALID_PARAM; - - if (idx == FP_FRAME_INDEX_RAW_IMAGE) { - /* The host requested a frame. */ - if (system_is_locked()) - return EC_RES_ACCESS_DENIED; - if (!is_raw_capture(sensor_mode)) - offset += FP_SENSOR_IMAGE_OFFSET; - - ret = validate_fp_buffer_offset(sizeof(fp_buffer), offset, - size); - if (ret != EC_SUCCESS) - return EC_RES_INVALID_PARAM; - - memcpy(out, fp_buffer + offset, size); - args->response_size = size; - return EC_RES_SUCCESS; - } - - /* The host requested a template. */ - - /* Templates are numbered from 1 in this host request. */ - fgr = idx - FP_FRAME_INDEX_TEMPLATE; - - if (fgr >= FP_MAX_FINGER_COUNT) - return EC_RES_INVALID_PARAM; - if (fgr >= templ_valid) - return EC_RES_UNAVAILABLE; - ret = validate_fp_buffer_offset(sizeof(fp_enc_buffer), offset, size); - if (ret != EC_SUCCESS) - return EC_RES_INVALID_PARAM; - - if (!offset) { - /* Host has requested the first chunk, do the encryption. */ - timestamp_t now = get_time(); - /* Encrypted template is after the metadata. */ - uint8_t *encrypted_template = fp_enc_buffer + sizeof(*enc_info); - /* Positive match salt is after the template. */ - uint8_t *positive_match_salt = - encrypted_template + sizeof(fp_template[0]); - size_t encrypted_blob_size = sizeof(fp_template[0]) + - sizeof(fp_positive_match_salt[0]); - - /* b/114160734: Not more than 1 encrypted message per second. */ - if (!timestamp_expired(encryption_deadline, &now)) - return EC_RES_BUSY; - encryption_deadline.val = now.val + (1 * SECOND); - - memset(fp_enc_buffer, 0, sizeof(fp_enc_buffer)); - /* - * The beginning of the buffer contains nonce, encryption_salt - * and tag. - */ - enc_info = (void *)fp_enc_buffer; - enc_info->struct_version = FP_TEMPLATE_FORMAT_VERSION; - init_trng(); - rand_bytes(enc_info->nonce, FP_CONTEXT_NONCE_BYTES); - rand_bytes(enc_info->encryption_salt, - FP_CONTEXT_ENCRYPTION_SALT_BYTES); - exit_trng(); - - if (fgr == template_newly_enrolled) { - /* - * Newly enrolled templates need new positive match - * salt, new positive match secret and new validation - * value. - */ - template_newly_enrolled = FP_NO_SUCH_TEMPLATE; - init_trng(); - rand_bytes(fp_positive_match_salt[fgr], - FP_POSITIVE_MATCH_SALT_BYTES); - exit_trng(); - } - - ret = derive_encryption_key(key, enc_info->encryption_salt); - if (ret != EC_SUCCESS) { - CPRINTS("fgr%d: Failed to derive key", fgr); - return EC_RES_UNAVAILABLE; - } - - /* - * Copy the payload to |fp_enc_buffer| where it will be - * encrypted in-place. - */ - memcpy(encrypted_template, fp_template[fgr], - sizeof(fp_template[0])); - memcpy(positive_match_salt, fp_positive_match_salt[fgr], - sizeof(fp_positive_match_salt[0])); - - /* Encrypt the secret blob in-place. */ - ret = aes_gcm_encrypt(key, SBP_ENC_KEY_LEN, encrypted_template, - encrypted_template, - encrypted_blob_size, - enc_info->nonce, FP_CONTEXT_NONCE_BYTES, - enc_info->tag, FP_CONTEXT_TAG_BYTES); - always_memset(key, 0, sizeof(key)); - if (ret != EC_SUCCESS) { - CPRINTS("fgr%d: Failed to encrypt template", fgr); - return EC_RES_UNAVAILABLE; - } - templ_dirty &= ~BIT(fgr); - } - memcpy(out, fp_enc_buffer + offset, size); - args->response_size = size; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_FRAME, fp_command_frame, EC_VER_MASK(0)); - -static enum ec_status fp_command_stats(struct host_cmd_handler_args *args) -{ - struct ec_response_fp_stats *r = args->response; - - r->capture_time_us = capture_time_us; - r->matching_time_us = matching_time_us; - r->overall_time_us = overall_time_us; - r->overall_t0.lo = overall_t0.le.lo; - r->overall_t0.hi = overall_t0.le.hi; - r->timestamps_invalid = timestamps_invalid; - /* - * Note that this is set to FP_NO_SUCH_TEMPLATE when positive match - * secret is read/disabled, and we are not using this field in biod. - */ - r->template_matched = positive_match_secret_state.template_matched; - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_STATS, fp_command_stats, EC_VER_MASK(0)); - -static bool template_needs_validation_value( - struct ec_fp_template_encryption_metadata *enc_info) -{ - return enc_info->struct_version == 3 - && FP_TEMPLATE_FORMAT_VERSION == 4; -} - -static int validate_template_format( - struct ec_fp_template_encryption_metadata *enc_info) -{ - if (template_needs_validation_value(enc_info)) - /* The host requested migration to v4. */ - return EC_RES_SUCCESS; - - if (enc_info->struct_version != FP_TEMPLATE_FORMAT_VERSION) { - CPRINTS("Invalid template format %d", enc_info->struct_version); - return EC_RES_INVALID_PARAM; - } - return EC_RES_SUCCESS; -} - -static enum ec_status fp_command_template(struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_template *params = args->params; - uint32_t size = params->size & ~FP_TEMPLATE_COMMIT; - int xfer_complete = params->size & FP_TEMPLATE_COMMIT; - uint32_t offset = params->offset; - uint32_t idx = templ_valid; - uint8_t key[SBP_ENC_KEY_LEN]; - struct ec_fp_template_encryption_metadata *enc_info; - int ret; - - /* Can we store one more template ? */ - if (idx >= FP_MAX_FINGER_COUNT) - return EC_RES_OVERFLOW; - - if (args->params_size != - size + offsetof(struct ec_params_fp_template, data)) - return EC_RES_INVALID_PARAM; - ret = validate_fp_buffer_offset(sizeof(fp_enc_buffer), offset, size); - if (ret != EC_SUCCESS) - return EC_RES_INVALID_PARAM; - - memcpy(&fp_enc_buffer[offset], params->data, size); - - if (xfer_complete) { - /* Encrypted template is after the metadata. */ - uint8_t *encrypted_template = fp_enc_buffer + sizeof(*enc_info); - /* Positive match salt is after the template. */ - uint8_t *positive_match_salt = - encrypted_template + sizeof(fp_template[0]); - size_t encrypted_blob_size; - - /* - * The complete encrypted template has been received, start - * decryption. - */ - fp_clear_finger_context(idx); - /* - * The beginning of the buffer contains nonce, encryption_salt - * and tag. - */ - enc_info = (void *)fp_enc_buffer; - ret = validate_template_format(enc_info); - if (ret != EC_RES_SUCCESS) { - CPRINTS("fgr%d: Template format not supported", idx); - return EC_RES_INVALID_PARAM; - } - - if (enc_info->struct_version <= 3) { - encrypted_blob_size = sizeof(fp_template[0]); - } else { - encrypted_blob_size = - sizeof(fp_template[0]) + - sizeof(fp_positive_match_salt[0]); - } - - ret = derive_encryption_key(key, enc_info->encryption_salt); - if (ret != EC_SUCCESS) { - CPRINTS("fgr%d: Failed to derive key", idx); - return EC_RES_UNAVAILABLE; - } - - /* Decrypt the secret blob in-place. */ - ret = aes_gcm_decrypt(key, SBP_ENC_KEY_LEN, encrypted_template, - encrypted_template, - encrypted_blob_size, - enc_info->nonce, FP_CONTEXT_NONCE_BYTES, - enc_info->tag, FP_CONTEXT_TAG_BYTES); - always_memset(key, 0, sizeof(key)); - if (ret != EC_SUCCESS) { - CPRINTS("fgr%d: Failed to decipher template", idx); - /* Don't leave bad data in the template buffer */ - fp_clear_finger_context(idx); - return EC_RES_UNAVAILABLE; - } - memcpy(fp_template[idx], encrypted_template, - sizeof(fp_template[0])); - if (template_needs_validation_value(enc_info)) { - CPRINTS("fgr%d: Generating positive match salt.", idx); - init_trng(); - rand_bytes(positive_match_salt, - FP_POSITIVE_MATCH_SALT_BYTES); - exit_trng(); - } - if (bytes_are_trivial(positive_match_salt, - sizeof(fp_positive_match_salt[0]))) { - CPRINTS("fgr%d: Trivial positive match salt.", idx); - always_memset(fp_template[idx], 0, - sizeof(fp_template[0])); - return EC_RES_INVALID_PARAM; - } - memcpy(fp_positive_match_salt[idx], positive_match_salt, - sizeof(fp_positive_match_salt[0])); - - templ_valid++; - } - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_TEMPLATE, fp_command_template, EC_VER_MASK(0)); - -#ifdef CONFIG_CMD_FPSENSOR_DEBUG -/* --- Debug console commands --- */ - -/* - * Send the current Fingerprint buffer to the host - * it is formatted as an 8-bpp PGM ASCII file. - * - * In addition, it prepends a short Z-Modem download signature, - * which triggers automatically your preferred viewer if you configure it - * properly in "File transfer protocols" in the Minicom options menu. - * (as triggered by Ctrl-A O) - * +--------------------------------------------------------------------------+ - * | Name Program Name U/D FullScr IO-Red. Multi | - * | A zmodem /usr/bin/sz -vv -b Y U N Y Y | - * [...] - * | L pgm /usr/bin/display_pgm N D N Y N | - * | M Zmodem download string activates... L | - * - * My /usr/bin/display_pgm looks like this: - * #!/bin/sh - * TMPF=$(mktemp) - * ascii-xfr -rdv ${TMPF} - * display ${TMPF} - * - * Alternative (if you're using screen as your terminal): - * - * From *outside* the chroot: - * - * Install ascii-xfr: sudo apt-get install minicom - * Install imagemagick: sudo apt-get install imagemagick - * - * Add the following to your ${HOME}/.screenrc: - * - * zmodem catch - * zmodem recvcmd '!!! bash -c "ascii-xfr -rdv /tmp/finger.pgm && display /tmp/finger.pgm"' - * - * From *outside the chroot*, use screen to connect to UART console: - * - * sudo screen -c ${HOME}/.screenrc /dev/pts/NN 115200 - * - */ -static void upload_pgm_image(uint8_t *frame) -{ - int x, y; - uint8_t *ptr = frame; - - /* fake Z-modem ZRQINIT signature */ - CPRINTF("#IGNORE for ZModem\r**\030B00"); - msleep(2000); /* let the download program start */ - /* Print 8-bpp PGM ASCII header */ - CPRINTF("P2\n%d %d\n255\n", FP_SENSOR_RES_X, FP_SENSOR_RES_Y); - - for (y = 0; y < FP_SENSOR_RES_Y; y++) { - watchdog_reload(); - for (x = 0; x < FP_SENSOR_RES_X; x++, ptr++) - CPRINTF("%d ", *ptr); - CPRINTF("\n"); - cflush(); - } - - CPRINTF("\x04"); /* End Of Transmission */ -} - -static enum ec_error_list fp_console_action(uint32_t mode) -{ - int tries = 200; - uint32_t mode_output = 0; - int rc = 0; - - if (!(sensor_mode & FP_MODE_RESET_SENSOR)) - CPRINTS("Waiting for finger ..."); - - rc = fp_set_sensor_mode(mode, &mode_output); - - if (rc != EC_RES_SUCCESS) { - /* - * EC host command errors do not directly map to console command - * errors. - */ - return EC_ERROR_UNKNOWN; - } - - while (tries--) { - if (!(sensor_mode & FP_MODE_ANY_CAPTURE)) { - CPRINTS("done (events:%x)", fp_events); - return 0; - } - usleep(100 * MSEC); - } - return EC_ERROR_TIMEOUT; -} - -int command_fpcapture(int argc, char **argv) -{ - int capture_type = FP_CAPTURE_SIMPLE_IMAGE; - uint32_t mode; - enum ec_error_list rc; - - /* - * TODO(b/142944002): Remove this redundant check for system_is_locked - * once we have unit-tests/integration-tests in place. - */ - if (system_is_locked()) - return EC_ERROR_ACCESS_DENIED; - - if (argc >= 2) { - char *e; - - capture_type = strtoi(argv[1], &e, 0); - if (*e || capture_type < 0) - return EC_ERROR_PARAM1; - } - mode = FP_MODE_CAPTURE | ((capture_type << FP_MODE_CAPTURE_TYPE_SHIFT) - & FP_MODE_CAPTURE_TYPE_MASK); - - rc = fp_console_action(mode); - if (rc == EC_SUCCESS) - upload_pgm_image(fp_buffer + FP_SENSOR_IMAGE_OFFSET); - - return rc; -} -DECLARE_CONSOLE_COMMAND_FLAGS(fpcapture, command_fpcapture, NULL, - "Capture fingerprint in PGM format", - CMD_FLAG_RESTRICTED); - -int command_fpenroll(int argc, char **argv) -{ - enum ec_error_list rc; - int percent = 0; - uint32_t event; - static const char * const enroll_str[] = {"OK", "Low Quality", - "Immobile", "Low Coverage"}; - - /* - * TODO(b/142944002): Remove this redundant check for system_is_locked - * once we have unit-tests/integration-tests in place. - */ - if (system_is_locked()) - return EC_ERROR_ACCESS_DENIED; - - do { - int tries = 1000; - - rc = fp_console_action(FP_MODE_ENROLL_SESSION | - FP_MODE_ENROLL_IMAGE); - if (rc != EC_SUCCESS) - break; - event = deprecated_atomic_read_clear(&fp_events); - percent = EC_MKBP_FP_ENROLL_PROGRESS(event); - CPRINTS("Enroll capture: %s (%d%%)", - enroll_str[EC_MKBP_FP_ERRCODE(event) & 3], percent); - /* wait for finger release between captures */ - sensor_mode = FP_MODE_ENROLL_SESSION | FP_MODE_FINGER_UP; - task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_UPDATE_CONFIG, 0); - while (tries-- && sensor_mode & FP_MODE_FINGER_UP) - usleep(20 * MSEC); - } while (percent < 100); - sensor_mode = 0; /* reset FP_MODE_ENROLL_SESSION */ - task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_UPDATE_CONFIG, 0); - - return rc; -} -DECLARE_CONSOLE_COMMAND_FLAGS(fpenroll, command_fpenroll, NULL, - "Enroll a new fingerprint", - CMD_FLAG_RESTRICTED); - - -int command_fpmatch(int argc, char **argv) -{ - enum ec_error_list rc = fp_console_action(FP_MODE_MATCH); - uint32_t event = deprecated_atomic_read_clear(&fp_events); - - if (rc == EC_SUCCESS && event & EC_MKBP_FP_MATCH) { - uint32_t errcode = EC_MKBP_FP_ERRCODE(event); - - CPRINTS("Match: %s (%d)", - errcode & EC_MKBP_FP_ERR_MATCH_YES ? "YES" : "NO", - errcode); - } - - return rc; -} -DECLARE_CONSOLE_COMMAND(fpmatch, command_fpmatch, NULL, - "Run match algorithm against finger"); - -int command_fpclear(int argc, char **argv) -{ - /* - * We intentionally run this on the fp_task so that we use the - * same code path as host commands. - */ - enum ec_error_list rc = fp_console_action(FP_MODE_RESET_SENSOR); - - if (rc < 0) - CPRINTS("Failed to clear fingerprint context: %d", rc); - - deprecated_atomic_read_clear(&fp_events); - - return rc; -} -DECLARE_CONSOLE_COMMAND(fpclear, command_fpclear, NULL, - "Clear fingerprint sensor context"); - -int command_fpmaintenance(int argc, char **argv) -{ -#ifdef HAVE_FP_PRIVATE_DRIVER - return fp_maintenance(); -#else - return EC_SUCCESS; -#endif /* #ifdef HAVE_FP_PRIVATE_DRIVER */ -} -DECLARE_CONSOLE_COMMAND(fpmaintenance, command_fpmaintenance, NULL, - "Run fingerprint sensor maintenance"); - -#endif /* CONFIG_CMD_FPSENSOR_DEBUG */ diff --git a/common/fpsensor/fpsensor.cc b/common/fpsensor/fpsensor.cc new file mode 100644 index 0000000000..27758492b6 --- /dev/null +++ b/common/fpsensor/fpsensor.cc @@ -0,0 +1,674 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "compile_time_macros.h" + +/* Boringssl headers need to be included before extern "C" section. */ +#include "openssl/mem.h" + +extern "C" { +#include "atomic.h" +#include "clock.h" +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "host_command.h" +#include "link_defs.h" +#include "mkbp_event.h" +#include "overflow.h" +#include "spi.h" +#include "system.h" +#include "task.h" +#include "trng.h" +#include "util.h" +#include "watchdog.h" +} + +#include "fpsensor.h" +#include "fpsensor_crypto.h" +#include "fpsensor_detect.h" +#include "fpsensor_state.h" +#include "fpsensor_utils.h" +#include "scoped_fast_cpu.h" + +#if !defined(CONFIG_RNG) +#error "fpsensor requires RNG" +#endif + +#if defined(SECTION_IS_RO) +#error "fpsensor code should not be in RO image." +#endif + +/* Ready to encrypt a template. */ +static timestamp_t encryption_deadline; + +/* Delay between 2 s of the sensor to detect finger removal */ +#define FINGER_POLLING_DELAY (100 * MSEC) + +/* Timing statistics. */ +static uint32_t capture_time_us; +static uint32_t matching_time_us; +static uint32_t overall_time_us; +static timestamp_t overall_t0; +static uint8_t timestamps_invalid; + +BUILD_ASSERT(sizeof(struct ec_fp_template_encryption_metadata) % 4 == 0); + +/* Interrupt line from the fingerprint sensor */ +void fps_event(enum gpio_signal signal) +{ + task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_SENSOR_IRQ); +} + +static void send_mkbp_event(uint32_t event) +{ + atomic_or(&fp_events, event); + mkbp_send_event(EC_MKBP_EVENT_FINGERPRINT); +} + +static inline int is_raw_capture(uint32_t mode) +{ + int capture_type = FP_CAPTURE_TYPE(mode); + + return (capture_type == FP_CAPTURE_VENDOR_FORMAT || + capture_type == FP_CAPTURE_QUALITY_TEST); +} + +__maybe_unused bool fp_match_success(int match_result) +{ + return match_result == EC_MKBP_FP_ERR_MATCH_YES || + match_result == EC_MKBP_FP_ERR_MATCH_YES_UPDATED || + match_result == EC_MKBP_FP_ERR_MATCH_YES_UPDATE_FAILED; +} + +#ifdef HAVE_FP_PRIVATE_DRIVER +static inline int is_test_capture(uint32_t mode) +{ + int capture_type = FP_CAPTURE_TYPE(mode); + + return (mode & FP_MODE_CAPTURE) && + (capture_type == FP_CAPTURE_PATTERN0 || + capture_type == FP_CAPTURE_PATTERN1 || + capture_type == FP_CAPTURE_RESET_TEST); +} + +/* + * contains the bit FP_MODE_ENROLL_SESSION if a finger enrollment is on-going. + * It is used to detect the ENROLL_SESSION transition when sensor_mode is + * updated by the host. + */ +static uint32_t enroll_session; + +static uint32_t fp_process_enroll(void) +{ + int percent = 0; + int res; + + if (template_newly_enrolled != FP_NO_SUCH_TEMPLATE) + CPRINTS("Warning: previously enrolled template has not been " + "read yet."); + + /* begin/continue enrollment */ + CPRINTS("[%d]Enrolling ...", templ_valid); + res = fp_finger_enroll(fp_buffer, &percent); + CPRINTS("[%d]Enroll =>%d (%d%%)", templ_valid, res, percent); + if (res < 0) + return EC_MKBP_FP_ENROLL | + EC_MKBP_FP_ERRCODE(EC_MKBP_FP_ERR_ENROLL_INTERNAL); + templ_dirty |= BIT(templ_valid); + if (percent == 100) { + res = fp_enrollment_finish(fp_template[templ_valid]); + if (res) { + res = EC_MKBP_FP_ERR_ENROLL_INTERNAL; + } else { + template_newly_enrolled = templ_valid; + fp_enable_positive_match_secret( + templ_valid, &positive_match_secret_state); + templ_valid++; + } + sensor_mode &= ~FP_MODE_ENROLL_SESSION; + enroll_session &= ~FP_MODE_ENROLL_SESSION; + } + return EC_MKBP_FP_ENROLL | EC_MKBP_FP_ERRCODE(res) | + (percent << EC_MKBP_FP_ENROLL_PROGRESS_OFFSET); +} + +static uint32_t fp_process_match(void) +{ + timestamp_t t0 = get_time(); + int res = -1; + uint32_t updated = 0; + int32_t fgr = FP_NO_SUCH_TEMPLATE; + + /* match finger against current templates */ + fp_disable_positive_match_secret(&positive_match_secret_state); + CPRINTS("Matching/%d ...", templ_valid); + if (templ_valid) { + res = fp_finger_match(fp_template[0], templ_valid, fp_buffer, + &fgr, &updated); + CPRINTS("Match =>%d (finger %d)", res, fgr); + + if (fp_match_success(res)) { + /* + * Match succeded! Let's check if template number + * is valid. If it is not valid, overwrite result + * with EC_MKBP_FP_ERR_MATCH_NO_INTERNAL. + */ + if (fgr >= 0 && fgr < FP_MAX_FINGER_COUNT) { + fp_enable_positive_match_secret( + fgr, &positive_match_secret_state); + } else { + res = EC_MKBP_FP_ERR_MATCH_NO_INTERNAL; + } + } else if (res < 0) { + /* + * Negative result means that there is a problem with + * code responsible for matching. Overwrite it with + * MATCH_NO_INTERNAL to let upper layers know what + * happened. + */ + res = EC_MKBP_FP_ERR_MATCH_NO_INTERNAL; + } + + if (res == EC_MKBP_FP_ERR_MATCH_YES_UPDATED) + templ_dirty |= updated; + } else { + CPRINTS("No enrolled templates"); + res = EC_MKBP_FP_ERR_MATCH_NO_TEMPLATES; + } + + if (!fp_match_success(res)) + timestamps_invalid |= FPSTATS_MATCHING_INV; + + matching_time_us = time_since32(t0); + return EC_MKBP_FP_MATCH | EC_MKBP_FP_ERRCODE(res) | + ((fgr << EC_MKBP_FP_MATCH_IDX_OFFSET) & + EC_MKBP_FP_MATCH_IDX_MASK); +} + +static void fp_process_finger(void) +{ + timestamp_t t0 = get_time(); + int res; + + CPRINTS("Capturing ..."); + res = fp_sensor_acquire_image_with_mode(fp_buffer, + FP_CAPTURE_TYPE(sensor_mode)); + capture_time_us = time_since32(t0); + if (!res) { + uint32_t evt = EC_MKBP_FP_IMAGE_READY; + + /* Clean up SPI before clocking up to avoid hang on the dsb + * in dma_go. Ignore the return value to let the WDT reboot + * the MCU (and avoid getting trapped in the loop). + * b/112781659 */ + res = spi_transaction_flush(&spi_devices[0]); + if (res) + CPRINTS("Failed to flush SPI: 0x%x", res); + + /* we need CPU power to do the computations */ + ScopedFastCpu fast_cpu; + + if (sensor_mode & FP_MODE_ENROLL_IMAGE) + evt = fp_process_enroll(); + else if (sensor_mode & FP_MODE_MATCH) + evt = fp_process_match(); + + sensor_mode &= ~FP_MODE_ANY_CAPTURE; + overall_time_us = time_since32(overall_t0); + send_mkbp_event(evt); + } else { + timestamps_invalid |= FPSTATS_CAPTURE_INV; + } +} +#endif /* HAVE_FP_PRIVATE_DRIVER */ + +extern "C" void fp_task(void) +{ + int timeout_us = -1; + + CPRINTS("FP_SENSOR_SEL: %s", + fp_sensor_type_to_str(fpsensor_detect_get_type())); + +#ifdef HAVE_FP_PRIVATE_DRIVER + /* Reset and initialize the sensor IC */ + fp_sensor_init(); + + while (1) { + uint32_t evt; + enum finger_state st = FINGER_NONE; + + /* Wait for a sensor IRQ or a new mode configuration */ + evt = task_wait_event(timeout_us); + + if (evt & TASK_EVENT_UPDATE_CONFIG) { + uint32_t mode = sensor_mode; + + gpio_disable_interrupt(GPIO_FPS_INT); + if ((mode ^ enroll_session) & FP_MODE_ENROLL_SESSION) { + if (mode & FP_MODE_ENROLL_SESSION) { + if (fp_enrollment_begin()) + sensor_mode &= + ~FP_MODE_ENROLL_SESSION; + } else { + fp_enrollment_finish(NULL); + } + enroll_session = sensor_mode & + FP_MODE_ENROLL_SESSION; + } + if (is_test_capture(mode)) { + fp_sensor_acquire_image_with_mode( + fp_buffer, FP_CAPTURE_TYPE(mode)); + sensor_mode &= ~FP_MODE_CAPTURE; + send_mkbp_event(EC_MKBP_FP_IMAGE_READY); + continue; + } else if (sensor_mode & FP_MODE_ANY_DETECT_FINGER) { + /* wait for a finger on the sensor */ + fp_sensor_configure_detect(); + } + if (sensor_mode & FP_MODE_DEEPSLEEP) + /* Shutdown the sensor */ + fp_sensor_low_power(); + if (sensor_mode & FP_MODE_FINGER_UP) + /* Poll the sensor to detect finger removal */ + timeout_us = FINGER_POLLING_DELAY; + else + timeout_us = -1; + if (mode & FP_MODE_ANY_WAIT_IRQ) { + gpio_enable_interrupt(GPIO_FPS_INT); + } else if (mode & FP_MODE_RESET_SENSOR) { + fp_reset_and_clear_context(); + sensor_mode &= ~FP_MODE_RESET_SENSOR; + } else if (mode & FP_MODE_SENSOR_MAINTENANCE) { + fp_maintenance(); + sensor_mode &= ~FP_MODE_SENSOR_MAINTENANCE; + } else { + fp_sensor_low_power(); + } + } else if (evt & (TASK_EVENT_SENSOR_IRQ | TASK_EVENT_TIMER)) { + overall_t0 = get_time(); + timestamps_invalid = 0; + gpio_disable_interrupt(GPIO_FPS_INT); + if (sensor_mode & FP_MODE_ANY_DETECT_FINGER) { + st = fp_sensor_finger_status(); + if (st == FINGER_PRESENT && + sensor_mode & FP_MODE_FINGER_DOWN) { + CPRINTS("Finger!"); + sensor_mode &= ~FP_MODE_FINGER_DOWN; + send_mkbp_event(EC_MKBP_FP_FINGER_DOWN); + } + if (st == FINGER_NONE && + sensor_mode & FP_MODE_FINGER_UP) { + sensor_mode &= ~FP_MODE_FINGER_UP; + timeout_us = -1; + send_mkbp_event(EC_MKBP_FP_FINGER_UP); + } + } + + if (st == FINGER_PRESENT && + sensor_mode & FP_MODE_ANY_CAPTURE) + fp_process_finger(); + + if (sensor_mode & FP_MODE_ANY_WAIT_IRQ) { + fp_sensor_configure_detect(); + gpio_enable_interrupt(GPIO_FPS_INT); + } else { + fp_sensor_low_power(); + } + } + } +#else /* !HAVE_FP_PRIVATE_DRIVER */ + while (1) { + uint32_t evt = task_wait_event(timeout_us); + + send_mkbp_event(evt); + } +#endif /* !HAVE_FP_PRIVATE_DRIVER */ +} + +static enum ec_status fp_command_passthru(struct host_cmd_handler_args *args) +{ + const auto *params = + static_cast(args->params); + auto *out = static_cast(args->response); + int rc; + enum ec_status ret = EC_RES_SUCCESS; + + if (system_is_locked()) + return EC_RES_ACCESS_DENIED; + + if (params->len > + args->params_size + + offsetof(struct ec_params_fp_passthru, data) || + params->len > args->response_max) + return EC_RES_INVALID_PARAM; + + rc = spi_transaction_async(&spi_devices[0], params->data, params->len, + out, SPI_READBACK_ALL); + if (params->flags & EC_FP_FLAG_NOT_COMPLETE) + rc |= spi_transaction_wait(&spi_devices[0]); + else + rc |= spi_transaction_flush(&spi_devices[0]); + + if (rc == EC_ERROR_TIMEOUT) + ret = EC_RES_TIMEOUT; + else if (rc) + ret = EC_RES_ERROR; + + args->response_size = params->len; + return ret; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_PASSTHRU, fp_command_passthru, EC_VER_MASK(0)); + +static enum ec_status fp_command_info(struct host_cmd_handler_args *args) +{ + auto *r = static_cast(args->response); + +#ifdef HAVE_FP_PRIVATE_DRIVER + if (fp_sensor_get_info(r) < 0) +#endif + return EC_RES_UNAVAILABLE; + + r->template_size = FP_ALGORITHM_ENCRYPTED_TEMPLATE_SIZE; + r->template_max = FP_MAX_FINGER_COUNT; + r->template_valid = templ_valid; + r->template_dirty = templ_dirty; + r->template_version = FP_TEMPLATE_FORMAT_VERSION; + + /* V1 is identical to V0 with more information appended */ + args->response_size = args->version ? + sizeof(*r) : + sizeof(struct ec_response_fp_info_v0); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_INFO, fp_command_info, + EC_VER_MASK(0) | EC_VER_MASK(1)); + +BUILD_ASSERT(FP_CONTEXT_NONCE_BYTES == 12); + +enum ec_error_list validate_fp_buffer_offset(const uint32_t buffer_size, + const uint32_t offset, + const uint32_t size) +{ + uint32_t bytes_requested; + + if (check_add_overflow(size, offset, &bytes_requested)) + return EC_ERROR_OVERFLOW; + + if (bytes_requested > buffer_size) + return EC_ERROR_INVAL; + + return EC_SUCCESS; +} + +static enum ec_status fp_command_frame(struct host_cmd_handler_args *args) +{ + const auto *params = + static_cast(args->params); + void *out = args->response; + uint16_t idx = FP_FRAME_GET_BUFFER_INDEX(params->offset); + uint32_t offset = params->offset & FP_FRAME_OFFSET_MASK; + uint32_t size = params->size; + uint16_t fgr; + uint8_t key[SBP_ENC_KEY_LEN]; + struct ec_fp_template_encryption_metadata *enc_info; + enum ec_error_list ret; + + if (size > args->response_max) + return EC_RES_INVALID_PARAM; + + if (idx == FP_FRAME_INDEX_RAW_IMAGE) { + /* The host requested a frame. */ + if (system_is_locked()) + return EC_RES_ACCESS_DENIED; + if (!is_raw_capture(sensor_mode)) + offset += FP_SENSOR_IMAGE_OFFSET; + + ret = validate_fp_buffer_offset(sizeof(fp_buffer), offset, + size); + if (ret != EC_SUCCESS) + return EC_RES_INVALID_PARAM; + + memcpy(out, fp_buffer + offset, size); + args->response_size = size; + return EC_RES_SUCCESS; + } + + /* The host requested a template. */ + + /* Templates are numbered from 1 in this host request. */ + fgr = idx - FP_FRAME_INDEX_TEMPLATE; + + if (fgr >= FP_MAX_FINGER_COUNT) + return EC_RES_INVALID_PARAM; + if (fgr >= templ_valid) + return EC_RES_UNAVAILABLE; + ret = validate_fp_buffer_offset(sizeof(fp_enc_buffer), offset, size); + if (ret != EC_SUCCESS) + return EC_RES_INVALID_PARAM; + + if (!offset) { + ScopedFastCpu fast_cpu; + + /* Host has requested the first chunk, do the encryption. */ + timestamp_t now = get_time(); + /* Encrypted template is after the metadata. */ + uint8_t *encrypted_template = fp_enc_buffer + sizeof(*enc_info); + /* Positive match salt is after the template. */ + uint8_t *positive_match_salt = + encrypted_template + sizeof(fp_template[0]); + size_t encrypted_blob_size = sizeof(fp_template[0]) + + sizeof(fp_positive_match_salt[0]); + + /* b/114160734: Not more than 1 encrypted message per second. */ + if (!timestamp_expired(encryption_deadline, &now)) + return EC_RES_BUSY; + encryption_deadline.val = now.val + (1 * SECOND); + + memset(fp_enc_buffer, 0, sizeof(fp_enc_buffer)); + /* + * The beginning of the buffer contains nonce, encryption_salt + * and tag. + */ + enc_info = reinterpret_cast< + struct ec_fp_template_encryption_metadata *>( + fp_enc_buffer); + enc_info->struct_version = FP_TEMPLATE_FORMAT_VERSION; + trng_init(); + trng_rand_bytes(enc_info->nonce, FP_CONTEXT_NONCE_BYTES); + trng_rand_bytes(enc_info->encryption_salt, + FP_CONTEXT_ENCRYPTION_SALT_BYTES); + trng_exit(); + + if (fgr == template_newly_enrolled) { + /* + * Newly enrolled templates need new positive match + * salt, new positive match secret and new validation + * value. + */ + template_newly_enrolled = FP_NO_SUCH_TEMPLATE; + trng_init(); + trng_rand_bytes(fp_positive_match_salt[fgr], + FP_POSITIVE_MATCH_SALT_BYTES); + trng_exit(); + } + + ret = derive_encryption_key(key, enc_info->encryption_salt); + if (ret != EC_SUCCESS) { + CPRINTS("fgr%d: Failed to derive key", fgr); + return EC_RES_UNAVAILABLE; + } + + /* + * Copy the payload to |fp_enc_buffer| where it will be + * encrypted in-place. + */ + memcpy(encrypted_template, fp_template[fgr], + sizeof(fp_template[0])); + memcpy(positive_match_salt, fp_positive_match_salt[fgr], + sizeof(fp_positive_match_salt[0])); + + /* Encrypt the secret blob in-place. */ + ret = aes_gcm_encrypt(key, SBP_ENC_KEY_LEN, encrypted_template, + encrypted_template, encrypted_blob_size, + enc_info->nonce, FP_CONTEXT_NONCE_BYTES, + enc_info->tag, FP_CONTEXT_TAG_BYTES); + OPENSSL_cleanse(key, sizeof(key)); + if (ret != EC_SUCCESS) { + CPRINTS("fgr%d: Failed to encrypt template", fgr); + return EC_RES_UNAVAILABLE; + } + templ_dirty &= ~BIT(fgr); + } + memcpy(out, fp_enc_buffer + offset, size); + args->response_size = size; + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_FRAME, fp_command_frame, EC_VER_MASK(0)); + +static enum ec_status fp_command_stats(struct host_cmd_handler_args *args) +{ + auto *r = static_cast(args->response); + + r->capture_time_us = capture_time_us; + r->matching_time_us = matching_time_us; + r->overall_time_us = overall_time_us; + r->overall_t0.lo = overall_t0.le.lo; + r->overall_t0.hi = overall_t0.le.hi; + r->timestamps_invalid = timestamps_invalid; + /* + * Note that this is set to FP_NO_SUCH_TEMPLATE when positive match + * secret is read/disabled, and we are not using this field in biod. + */ + r->template_matched = positive_match_secret_state.template_matched; + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_STATS, fp_command_stats, EC_VER_MASK(0)); + +static bool template_needs_validation_value( + struct ec_fp_template_encryption_metadata *enc_info) +{ + return enc_info->struct_version == 3 && FP_TEMPLATE_FORMAT_VERSION == 4; +} + +static enum ec_status +validate_template_format(struct ec_fp_template_encryption_metadata *enc_info) +{ + if (template_needs_validation_value(enc_info)) + /* The host requested migration to v4. */ + return EC_RES_SUCCESS; + + if (enc_info->struct_version != FP_TEMPLATE_FORMAT_VERSION) { + CPRINTS("Invalid template format %d", enc_info->struct_version); + return EC_RES_INVALID_PARAM; + } + return EC_RES_SUCCESS; +} + +static enum ec_status fp_command_template(struct host_cmd_handler_args *args) +{ + const auto *params = + static_cast(args->params); + uint32_t size = params->size & ~FP_TEMPLATE_COMMIT; + bool xfer_complete = params->size & FP_TEMPLATE_COMMIT; + uint32_t offset = params->offset; + uint16_t idx = templ_valid; + uint8_t key[SBP_ENC_KEY_LEN]; + struct ec_fp_template_encryption_metadata *enc_info; + + /* Can we store one more template ? */ + if (idx >= FP_MAX_FINGER_COUNT) + return EC_RES_OVERFLOW; + + if (args->params_size != + size + offsetof(struct ec_params_fp_template, data)) + return EC_RES_INVALID_PARAM; + enum ec_error_list ret = + validate_fp_buffer_offset(sizeof(fp_enc_buffer), offset, size); + if (ret != EC_SUCCESS) + return EC_RES_INVALID_PARAM; + + memcpy(&fp_enc_buffer[offset], params->data, size); + + if (xfer_complete) { + ScopedFastCpu fast_cpu; + + /* Encrypted template is after the metadata. */ + uint8_t *encrypted_template = fp_enc_buffer + sizeof(*enc_info); + /* Positive match salt is after the template. */ + uint8_t *positive_match_salt = + encrypted_template + sizeof(fp_template[0]); + size_t encrypted_blob_size; + + /* + * The complete encrypted template has been received, start + * decryption. + */ + fp_clear_finger_context(idx); + /* + * The beginning of the buffer contains nonce, encryption_salt + * and tag. + */ + enc_info = (struct ec_fp_template_encryption_metadata *) + fp_enc_buffer; + enum ec_status res = validate_template_format(enc_info); + if (res != EC_RES_SUCCESS) { + CPRINTS("fgr%d: Template format not supported", idx); + return EC_RES_INVALID_PARAM; + } + + if (enc_info->struct_version <= 3) { + encrypted_blob_size = sizeof(fp_template[0]); + } else { + encrypted_blob_size = sizeof(fp_template[0]) + + sizeof(fp_positive_match_salt[0]); + } + + ret = derive_encryption_key(key, enc_info->encryption_salt); + if (ret != EC_SUCCESS) { + CPRINTS("fgr%d: Failed to derive key", idx); + return EC_RES_UNAVAILABLE; + } + + /* Decrypt the secret blob in-place. */ + ret = aes_gcm_decrypt(key, SBP_ENC_KEY_LEN, encrypted_template, + encrypted_template, encrypted_blob_size, + enc_info->nonce, FP_CONTEXT_NONCE_BYTES, + enc_info->tag, FP_CONTEXT_TAG_BYTES); + OPENSSL_cleanse(key, sizeof(key)); + if (ret != EC_SUCCESS) { + CPRINTS("fgr%d: Failed to decipher template", idx); + /* Don't leave bad data in the template buffer */ + fp_clear_finger_context(idx); + return EC_RES_UNAVAILABLE; + } + memcpy(fp_template[idx], encrypted_template, + sizeof(fp_template[0])); + if (template_needs_validation_value(enc_info)) { + CPRINTS("fgr%d: Generating positive match salt.", idx); + trng_init(); + trng_rand_bytes(positive_match_salt, + FP_POSITIVE_MATCH_SALT_BYTES); + trng_exit(); + } + if (bytes_are_trivial(positive_match_salt, + sizeof(fp_positive_match_salt[0]))) { + CPRINTS("fgr%d: Trivial positive match salt.", idx); + OPENSSL_cleanse(fp_template[idx], + sizeof(fp_template[0])); + return EC_RES_INVALID_PARAM; + } + memcpy(fp_positive_match_salt[idx], positive_match_salt, + sizeof(fp_positive_match_salt[0])); + + templ_valid++; + } + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_TEMPLATE, fp_command_template, EC_VER_MASK(0)); diff --git a/common/fpsensor/fpsensor_auth_commands.cc b/common/fpsensor/fpsensor_auth_commands.cc new file mode 100644 index 0000000000..4edc0f4083 --- /dev/null +++ b/common/fpsensor/fpsensor_auth_commands.cc @@ -0,0 +1,114 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "crypto/elliptic_curve_key.h" +#include "ec_commands.h" +#include "fpsensor.h" +#include "fpsensor_auth_commands.h" +#include "fpsensor_auth_crypto.h" +#include "fpsensor_crypto.h" +#include "fpsensor_state.h" +#include "fpsensor_utils.h" +#include "openssl/mem.h" +#include "scoped_fast_cpu.h" + +#include +#include +#include + +enum ec_error_list check_context_cleared() +{ + for (uint32_t partial : user_id) + if (partial != 0) + return EC_ERROR_ACCESS_DENIED; + if (templ_valid != 0) + return EC_ERROR_ACCESS_DENIED; + if (templ_dirty != 0) + return EC_ERROR_ACCESS_DENIED; + if (positive_match_secret_state.template_matched != FP_NO_SUCH_TEMPLATE) + return EC_ERROR_ACCESS_DENIED; + return EC_SUCCESS; +} + +static enum ec_status +fp_command_establish_pairing_key_keygen(struct host_cmd_handler_args *args) +{ + auto *r = static_cast( + args->response); + + ScopedFastCpu fast_cpu; + + bssl::UniquePtr ecdh_key = generate_elliptic_curve_key(); + if (ecdh_key == nullptr) { + return EC_RES_UNAVAILABLE; + } + + std::optional encrypted_private_key = + create_encrypted_private_key(*ecdh_key, + FP_AES_KEY_ENC_METADATA_VERSION); + if (!encrypted_private_key.has_value()) { + CPRINTS("pairing_keygen: Failed to fill response encrypted private key"); + return EC_RES_UNAVAILABLE; + } + + r->encrypted_private_key = std::move(encrypted_private_key).value(); + + std::optional pubkey = + create_pubkey_from_ec_key(*ecdh_key); + if (!pubkey.has_value()) { + return EC_RES_UNAVAILABLE; + } + + r->pubkey = std::move(pubkey).value(); + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_ESTABLISH_PAIRING_KEY_KEYGEN, + fp_command_establish_pairing_key_keygen, EC_VER_MASK(0)); + +static enum ec_status +fp_command_establish_pairing_key_wrap(struct host_cmd_handler_args *args) +{ + const auto *params = + static_cast( + args->params); + auto *r = static_cast( + args->response); + + ScopedFastCpu fast_cpu; + + bssl::UniquePtr private_key = + decrypt_private_key(params->encrypted_private_key); + if (private_key == nullptr) { + return EC_RES_UNAVAILABLE; + } + + bssl::UniquePtr public_key = + create_ec_key_from_pubkey(params->peers_pubkey); + if (public_key == nullptr) { + return EC_RES_UNAVAILABLE; + } + + enum ec_error_list ret = generate_ecdh_shared_secret( + *private_key, *public_key, r->encrypted_pairing_key.data, + sizeof(r->encrypted_pairing_key.data)); + if (ret != EC_SUCCESS) { + return EC_RES_UNAVAILABLE; + } + + ret = encrypt_data_in_place(FP_AES_KEY_ENC_METADATA_VERSION, + r->encrypted_pairing_key.info, + r->encrypted_pairing_key.data, + sizeof(r->encrypted_pairing_key.data)); + if (ret != EC_SUCCESS) { + return EC_RES_UNAVAILABLE; + } + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_ESTABLISH_PAIRING_KEY_WRAP, + fp_command_establish_pairing_key_wrap, EC_VER_MASK(0)); diff --git a/common/fpsensor/fpsensor_auth_crypto_stateful.cc b/common/fpsensor/fpsensor_auth_crypto_stateful.cc new file mode 100644 index 0000000000..eea26226e7 --- /dev/null +++ b/common/fpsensor/fpsensor_auth_crypto_stateful.cc @@ -0,0 +1,130 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* TODO(b/286119221): refactor FPMCU code so that functions in this file don't + * rely on global state. */ + +#include "compile_time_macros.h" + +/* Boringssl headers need to be included before extern "C" section. */ +#include "crypto/cleanse_wrapper.h" +#include "crypto/elliptic_curve_key.h" +#include "openssl/bn.h" +#include "openssl/ec.h" +#include "openssl/mem.h" +#include "openssl/obj_mac.h" +#include "openssl/rand.h" + +extern "C" { +#include "ec_commands.h" +#include "sha256.h" +} + +#include "fpsensor_auth_crypto.h" +#include "fpsensor_crypto.h" +#include "fpsensor_state_without_driver_info.h" +#include "fpsensor_utils.h" + +#include + +enum ec_error_list +encrypt_data_in_place(uint16_t version, + struct fp_auth_command_encryption_metadata &info, + uint8_t *data, size_t data_size) +{ + if (version != 1) { + return EC_ERROR_INVAL; + } + + info.struct_version = version; + RAND_bytes(info.nonce, sizeof(info.nonce)); + RAND_bytes(info.encryption_salt, sizeof(info.encryption_salt)); + + CleanseWrapper > enc_key; + enum ec_error_list ret = + derive_encryption_key(enc_key.data(), info.encryption_salt); + if (ret != EC_SUCCESS) { + return ret; + } + + /* Encrypt the secret blob in-place. */ + ret = aes_gcm_encrypt(enc_key.data(), enc_key.size(), data, data, + data_size, info.nonce, sizeof(info.nonce), + info.tag, sizeof(info.tag)); + if (ret != EC_SUCCESS) { + return ret; + } + + return EC_SUCCESS; +} + +std::optional +create_encrypted_private_key(const EC_KEY &key, uint16_t version) +{ + fp_encrypted_private_key enc_key; + + if (EC_KEY_priv2oct(&key, enc_key.data, sizeof(enc_key.data)) != + sizeof(enc_key.data)) { + return std::nullopt; + } + + if (encrypt_data_in_place(version, enc_key.info, enc_key.data, + sizeof(enc_key.data)) != EC_SUCCESS) { + return std::nullopt; + } + + return enc_key; +} + +enum ec_error_list +decrypt_data(const struct fp_auth_command_encryption_metadata &info, + const uint8_t *enc_data, size_t enc_data_size, uint8_t *data, + size_t data_size) +{ + if (info.struct_version != 1) { + return EC_ERROR_INVAL; + } + + CleanseWrapper > enc_key; + enum ec_error_list ret = + derive_encryption_key(enc_key.data(), info.encryption_salt); + if (ret != EC_SUCCESS) { + CPRINTS("Failed to derive key"); + return ret; + } + + if (enc_data_size != data_size) { + CPRINTS("Data size mismatch"); + return EC_ERROR_OVERFLOW; + } + + ret = aes_gcm_decrypt(enc_key.data(), enc_key.size(), data, enc_data, + data_size, info.nonce, sizeof(info.nonce), + info.tag, sizeof(info.tag)); + if (ret != EC_SUCCESS) { + CPRINTS("Failed to decipher data"); + return ret; + } + + return EC_SUCCESS; +} + +bssl::UniquePtr decrypt_private_key( + const struct fp_encrypted_private_key &encrypted_private_key) +{ + CleanseWrapper > + privkey; + + enum ec_error_list ret = decrypt_data( + encrypted_private_key.info, encrypted_private_key.data, + sizeof(encrypted_private_key.data), privkey.data(), + privkey.size()); + if (ret != EC_SUCCESS) { + CPRINTS("Failed to decrypt private key"); + return nullptr; + } + + return create_ec_key_from_privkey(privkey.data(), privkey.size()); +} diff --git a/common/fpsensor/fpsensor_auth_crypto_stateless.cc b/common/fpsensor/fpsensor_auth_crypto_stateless.cc new file mode 100644 index 0000000000..b4e33bd12e --- /dev/null +++ b/common/fpsensor/fpsensor_auth_crypto_stateless.cc @@ -0,0 +1,224 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" + +#include + +/* Boringssl headers need to be included before extern "C" section. */ +#include "crypto/cleanse_wrapper.h" +#include "crypto/elliptic_curve_key.h" +#include "openssl/aes.h" +#include "openssl/bn.h" +#include "openssl/ec.h" +#include "openssl/ecdh.h" +#include "openssl/mem.h" +#include "openssl/obj_mac.h" +#include "openssl/rand.h" + +extern "C" { +#include "ec_commands.h" +#include "sha256.h" +} + +#include "fpsensor_auth_crypto.h" + +std::optional +create_pubkey_from_ec_key(const EC_KEY &key) +{ + fp_elliptic_curve_public_key pubkey; + static_assert(sizeof(pubkey) == sizeof(pubkey.x) + sizeof(pubkey.y)); + + /* POINT_CONVERSION_UNCOMPRESSED indicates that the point is encoded as + * z||x||y, where z is the octet 0x04. */ + uint8_t *data = nullptr; + if (EC_KEY_key2buf(&key, POINT_CONVERSION_UNCOMPRESSED, &data, + nullptr) != + sizeof(pubkey.x) + sizeof(pubkey.y) + 1) { + return std::nullopt; + } + + bssl::UniquePtr pubkey_data(data); + uint8_t *pubkey_ptr = reinterpret_cast(&pubkey); + std::copy(pubkey_data.get() + 1, + pubkey_data.get() + 1 + sizeof(pubkey.x) + sizeof(pubkey.y), + pubkey_ptr); + + return pubkey; +} + +bssl::UniquePtr +create_ec_key_from_pubkey(const fp_elliptic_curve_public_key &pubkey) +{ + bssl::UniquePtr x_bn( + BN_bin2bn(pubkey.x, sizeof(pubkey.x), nullptr)); + if (x_bn == nullptr) { + return nullptr; + } + + bssl::UniquePtr y_bn( + BN_bin2bn(pubkey.y, sizeof(pubkey.y), nullptr)); + if (y_bn == nullptr) { + return nullptr; + } + + static_assert(sizeof(pubkey.x) == 32); + static_assert(sizeof(pubkey.y) == 32); + bssl::UniquePtr key( + EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + if (key == nullptr) { + return nullptr; + } + + if (EC_KEY_set_public_key_affine_coordinates(key.get(), x_bn.get(), + y_bn.get()) != 1) { + return nullptr; + } + + return key; +} + +bssl::UniquePtr create_ec_key_from_privkey(const uint8_t *privkey, + size_t privkey_size) +{ + bssl::UniquePtr key( + EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + if (key == nullptr) { + return nullptr; + } + + if (EC_KEY_oct2priv(key.get(), privkey, privkey_size) != 1) { + return nullptr; + } + + return key; +} + +enum ec_error_list generate_ecdh_shared_secret(const EC_KEY &private_key, + const EC_KEY &public_key, + uint8_t *shared_secret, + uint8_t shared_secret_size) +{ + const EC_POINT *public_point = EC_KEY_get0_public_key(&public_key); + if (public_point == nullptr) { + return EC_ERROR_INVAL; + } + + if (ECDH_compute_key_fips(shared_secret, shared_secret_size, + public_point, &private_key) != 1) { + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +enum ec_error_list +generate_gsc_session_key(const uint8_t *auth_nonce, size_t auth_nonce_size, + const uint8_t *gsc_nonce, size_t gsc_nonce_size, + const uint8_t *pairing_key, size_t pairing_key_size, + uint8_t *gsc_session_key, size_t gsc_session_key_size) +{ + if (auth_nonce_size != 32 || gsc_nonce_size != 32 || + pairing_key_size != 32 || + gsc_session_key_size != SHA256_DIGEST_SIZE) { + return EC_ERROR_INVAL; + } + CleanseWrapper ctx; + SHA256_init(&ctx); + SHA256_update(&ctx, auth_nonce, auth_nonce_size); + SHA256_update(&ctx, gsc_nonce, gsc_nonce_size); + SHA256_update(&ctx, pairing_key, pairing_key_size); + uint8_t *result = SHA256_final(&ctx); + + std::copy(result, result + SHA256_DIGEST_SIZE, gsc_session_key); + + return EC_SUCCESS; +} + +enum ec_error_list decrypt_data_with_gsc_session_key_in_place( + const uint8_t *gsc_session_key, size_t gsc_session_key_size, + const uint8_t *iv, size_t iv_size, uint8_t *data, size_t data_size) +{ + if (gsc_session_key_size != 32 || iv_size != AES_BLOCK_SIZE) { + return EC_ERROR_INVAL; + } + + CleanseWrapper aes_key; + int res = AES_set_encrypt_key(gsc_session_key, 256, &aes_key); + if (res) { + return EC_ERROR_INVAL; + } + + std::array aes_iv; + std::copy(iv, iv + iv_size, aes_iv.begin()); + + /* The AES CTR uses the same function for encryption & decryption. */ + unsigned int block_num = 0; + std::array ecount_buf; + AES_ctr128_encrypt(data, data, data_size, &aes_key, aes_iv.data(), + ecount_buf.data(), &block_num); + + return EC_SUCCESS; +} + +enum ec_error_list encrypt_data_with_ecdh_key_in_place( + const struct fp_elliptic_curve_public_key &in_pubkey, uint8_t *data, + size_t data_size, uint8_t *iv, size_t iv_size, + struct fp_elliptic_curve_public_key &out_pubkey) +{ + if (iv_size != AES_BLOCK_SIZE) { + return EC_ERROR_INVAL; + } + + bssl::UniquePtr private_key = generate_elliptic_curve_key(); + if (private_key == nullptr) { + return EC_ERROR_MEMORY_ALLOCATION; + } + + std::optional out_key = + create_pubkey_from_ec_key(*private_key); + if (!out_key.has_value()) { + return EC_ERROR_INVAL; + } + + out_pubkey = out_key.value(); + + bssl::UniquePtr public_key = + create_ec_key_from_pubkey(in_pubkey); + if (public_key == nullptr) { + return EC_ERROR_MEMORY_ALLOCATION; + } + + CleanseWrapper > enc_key; + + enum ec_error_list ret = generate_ecdh_shared_secret( + *private_key, *public_key, enc_key.data(), enc_key.size()); + if (ret != EC_SUCCESS) { + return ret; + } + + CleanseWrapper aes_key; + int res = AES_set_encrypt_key(enc_key.data(), 256, &aes_key); + if (res) { + return EC_ERROR_INVAL; + } + + RAND_bytes(iv, iv_size); + + /* The IV will be changed after the AES_ctr128_encrypt, we need a copy + * for that. */ + std::array aes_iv; + + std::copy(iv, iv + iv_size, aes_iv.begin()); + + unsigned int block_num = 0; + std::array ecount_buf; + + /* The AES CTR uses the same function for encryption & decryption. */ + AES_ctr128_encrypt(data, data, data_size, &aes_key, aes_iv.data(), + ecount_buf.data(), &block_num); + + return EC_SUCCESS; +} diff --git a/common/fpsensor/fpsensor_crypto.c b/common/fpsensor/fpsensor_crypto.c deleted file mode 100644 index 73d7aca681..0000000000 --- a/common/fpsensor/fpsensor_crypto.c +++ /dev/null @@ -1,286 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include - -#include "aes.h" -#include "aes-gcm.h" -#include "cryptoc/util.h" -#include "fpsensor_crypto.h" -#include "fpsensor_private.h" -#include "fpsensor_state.h" -#include "rollback.h" - -#if !defined(CONFIG_AES) || !defined(CONFIG_AES_GCM) || \ - !defined(CONFIG_ROLLBACK_SECRET_SIZE) -#error "fpsensor requires AES, AES_GCM and ROLLBACK_SECRET_SIZE" -#endif - -static int get_ikm(uint8_t *ikm) -{ - int ret; - - if (!fp_tpm_seed_is_set()) { - CPRINTS("Seed hasn't been set."); - return EC_ERROR_ACCESS_DENIED; - } - - /* - * The first CONFIG_ROLLBACK_SECRET_SIZE bytes of IKM are read from the - * anti-rollback blocks. - */ - ret = rollback_get_secret(ikm); - if (ret != EC_SUCCESS) { - CPRINTS("Failed to read rollback secret: %d", ret); - return EC_ERROR_HW_INTERNAL; - } - /* - * IKM is the concatenation of the rollback secret and the seed from - * the TPM. - */ - memcpy(ikm + CONFIG_ROLLBACK_SECRET_SIZE, tpm_seed, sizeof(tpm_seed)); - - return EC_SUCCESS; -} - -static void hkdf_extract(uint8_t *prk, const uint8_t *salt, size_t salt_size, - const uint8_t *ikm, size_t ikm_size) -{ - /* - * Derive a key with the "extract" step of HKDF - * https://tools.ietf.org/html/rfc5869#section-2.2 - */ - hmac_SHA256(prk, salt, salt_size, ikm, ikm_size); -} - -static int hkdf_expand_one_step(uint8_t *out_key, size_t out_key_size, - uint8_t *prk, size_t prk_size, - uint8_t *info, size_t info_size) -{ - uint8_t key_buf[SHA256_DIGEST_SIZE]; - uint8_t message_buf[SHA256_DIGEST_SIZE + 1]; - - if (out_key_size > SHA256_DIGEST_SIZE) { - CPRINTS("Deriving key material longer than SHA256_DIGEST_SIZE " - "requires more steps of HKDF expand."); - return EC_ERROR_INVAL; - } - - if (info_size > SHA256_DIGEST_SIZE) { - CPRINTS("Info size too big for HKDF."); - return EC_ERROR_INVAL; - } - - memcpy(message_buf, info, info_size); - /* 1 step, set the counter byte to 1. */ - message_buf[info_size] = 0x01; - hmac_SHA256(key_buf, prk, prk_size, message_buf, info_size + 1); - - memcpy(out_key, key_buf, out_key_size); - always_memset(key_buf, 0, sizeof(key_buf)); - - return EC_SUCCESS; -} - -int hkdf_expand(uint8_t *out_key, size_t L, const uint8_t *prk, - size_t prk_size, const uint8_t *info, size_t info_size) -{ - /* - * "Expand" step of HKDF. - * https://tools.ietf.org/html/rfc5869#section-2.3 - */ -#define HASH_LEN SHA256_DIGEST_SIZE - uint8_t count = 1; - const uint8_t *T = out_key; - size_t T_len = 0; - uint8_t T_buffer[HASH_LEN]; - /* Number of blocks. */ - const uint32_t N = DIV_ROUND_UP(L, HASH_LEN); - uint8_t info_buffer[HASH_LEN + HKDF_MAX_INFO_SIZE + sizeof(count)]; - bool arguments_valid = false; - - if (out_key == NULL || L == 0) - CPRINTS("HKDF expand: output buffer not valid."); - else if (prk == NULL) - CPRINTS("HKDF expand: prk is NULL."); - else if (info == NULL && info_size > 0) - CPRINTS("HKDF expand: info is NULL but info size is not zero."); - else if (info_size > HKDF_MAX_INFO_SIZE) - CPRINTF("HKDF expand: info size larger than %d bytes.\n", - HKDF_MAX_INFO_SIZE); - else if (N > HKDF_SHA256_MAX_BLOCK_COUNT) - CPRINTS("HKDF expand: output key size too large."); - else - arguments_valid = true; - - if (!arguments_valid) - return EC_ERROR_INVAL; - - while (L > 0) { - const size_t block_size = L < HASH_LEN ? L : HASH_LEN; - - memcpy(info_buffer, T, T_len); - memcpy(info_buffer + T_len, info, info_size); - info_buffer[T_len + info_size] = count; - hmac_SHA256(T_buffer, prk, prk_size, info_buffer, - T_len + info_size + sizeof(count)); - memcpy(out_key, T_buffer, block_size); - - T += T_len; - T_len = HASH_LEN; - count++; - out_key += block_size; - L -= block_size; - } - always_memset(T_buffer, 0, sizeof(T_buffer)); - always_memset(info_buffer, 0, sizeof(info_buffer)); - return EC_SUCCESS; -#undef HASH_LEN -} - -int derive_positive_match_secret(uint8_t *output, - const uint8_t *input_positive_match_salt) -{ - int ret; - uint8_t ikm[CONFIG_ROLLBACK_SECRET_SIZE + sizeof(tpm_seed)]; - uint8_t prk[SHA256_DIGEST_SIZE]; - static const char info_prefix[] = "positive_match_secret for user "; - uint8_t info[sizeof(info_prefix) - 1 + sizeof(user_id)]; - - if (bytes_are_trivial(input_positive_match_salt, - FP_POSITIVE_MATCH_SALT_BYTES)) { - CPRINTS("Failed to derive positive match secret: " - "salt bytes are trivial."); - return EC_ERROR_INVAL; - } - - ret = get_ikm(ikm); - if (ret != EC_SUCCESS) { - CPRINTS("Failed to get IKM: %d", ret); - return ret; - } - - /* "Extract" step of HKDF. */ - hkdf_extract(prk, input_positive_match_salt, - FP_POSITIVE_MATCH_SALT_BYTES, ikm, sizeof(ikm)); - always_memset(ikm, 0, sizeof(ikm)); - - memcpy(info, info_prefix, strlen(info_prefix)); - memcpy(info + strlen(info_prefix), user_id, sizeof(user_id)); - - /* "Expand" step of HKDF. */ - ret = hkdf_expand(output, FP_POSITIVE_MATCH_SECRET_BYTES, prk, - sizeof(prk), info, sizeof(info)); - always_memset(prk, 0, sizeof(prk)); - - /* Check that secret is not full of 0x00 or 0xff. */ - if (bytes_are_trivial(output, FP_POSITIVE_MATCH_SECRET_BYTES)) { - CPRINTS("Failed to derive positive match secret: " - "derived secret bytes are trivial."); - ret = EC_ERROR_HW_INTERNAL; - } - return ret; -} - -int derive_encryption_key(uint8_t *out_key, const uint8_t *salt) -{ - int ret; - uint8_t ikm[CONFIG_ROLLBACK_SECRET_SIZE + sizeof(tpm_seed)]; - uint8_t prk[SHA256_DIGEST_SIZE]; - - BUILD_ASSERT(SBP_ENC_KEY_LEN <= SHA256_DIGEST_SIZE); - BUILD_ASSERT(SBP_ENC_KEY_LEN <= CONFIG_ROLLBACK_SECRET_SIZE); - BUILD_ASSERT(sizeof(user_id) == SHA256_DIGEST_SIZE); - - ret = get_ikm(ikm); - if (ret != EC_SUCCESS) { - CPRINTS("Failed to get IKM: %d", ret); - return ret; - } - - /* "Extract step of HKDF. */ - hkdf_extract(prk, salt, FP_CONTEXT_ENCRYPTION_SALT_BYTES, ikm, - sizeof(ikm)); - always_memset(ikm, 0, sizeof(ikm)); - - /* - * Only 1 "expand" step of HKDF since the size of the "info" context - * (user_id in our case) is exactly SHA256_DIGEST_SIZE. - * https://tools.ietf.org/html/rfc5869#section-2.3 - */ - ret = hkdf_expand_one_step(out_key, SBP_ENC_KEY_LEN, prk, sizeof(prk), - (uint8_t *)user_id, sizeof(user_id)); - always_memset(prk, 0, sizeof(prk)); - - return ret; -} - -int aes_gcm_encrypt(const uint8_t *key, int key_size, - const uint8_t *plaintext, - uint8_t *ciphertext, int text_size, - const uint8_t *nonce, int nonce_size, - uint8_t *tag, int tag_size) -{ - int res; - AES_KEY aes_key; - GCM128_CONTEXT ctx; - - if (nonce_size != FP_CONTEXT_NONCE_BYTES) { - CPRINTS("Invalid nonce size %d bytes", nonce_size); - return EC_ERROR_INVAL; - } - - res = AES_set_encrypt_key(key, 8 * key_size, &aes_key); - if (res) { - CPRINTS("Failed to set encryption key: %d", res); - return EC_ERROR_UNKNOWN; - } - CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0); - CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_size); - /* CRYPTO functions return 1 on success, 0 on error. */ - res = CRYPTO_gcm128_encrypt(&ctx, &aes_key, plaintext, ciphertext, - text_size); - if (!res) { - CPRINTS("Failed to encrypt: %d", res); - return EC_ERROR_UNKNOWN; - } - CRYPTO_gcm128_tag(&ctx, tag, tag_size); - return EC_SUCCESS; -} - -int aes_gcm_decrypt(const uint8_t *key, int key_size, uint8_t *plaintext, - const uint8_t *ciphertext, int text_size, - const uint8_t *nonce, int nonce_size, - const uint8_t *tag, int tag_size) -{ - int res; - AES_KEY aes_key; - GCM128_CONTEXT ctx; - - if (nonce_size != FP_CONTEXT_NONCE_BYTES) { - CPRINTS("Invalid nonce size %d bytes", nonce_size); - return EC_ERROR_INVAL; - } - - res = AES_set_encrypt_key(key, 8 * key_size, &aes_key); - if (res) { - CPRINTS("Failed to set decryption key: %d", res); - return EC_ERROR_UNKNOWN; - } - CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0); - CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_size); - /* CRYPTO functions return 1 on success, 0 on error. */ - res = CRYPTO_gcm128_decrypt(&ctx, &aes_key, ciphertext, plaintext, - text_size); - if (!res) { - CPRINTS("Failed to decrypt: %d", res); - return EC_ERROR_UNKNOWN; - } - res = CRYPTO_gcm128_finish(&ctx, tag, tag_size); - if (!res) { - CPRINTS("Found incorrect tag: %d", res); - return EC_ERROR_UNKNOWN; - } - return EC_SUCCESS; -} diff --git a/common/fpsensor/fpsensor_crypto.cc b/common/fpsensor/fpsensor_crypto.cc new file mode 100644 index 0000000000..01ea91f73f --- /dev/null +++ b/common/fpsensor/fpsensor_crypto.cc @@ -0,0 +1,315 @@ +/* Copyright 2019 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "aes_gcm_helpers.h" +#include "fpsensor_crypto.h" +#include "fpsensor_state_without_driver_info.h" +#include "fpsensor_utils.h" +#include "openssl/aes.h" +#include "openssl/mem.h" + +/* These must be included after the "openssl/aes.h" */ +#include "crypto/fipsmodule/aes/internal.h" +#include "crypto/fipsmodule/modes/internal.h" + +extern "C" { +#include "rollback.h" +#include "sha256.h" +#include "util.h" + +test_mockable void compute_hmac_sha256(uint8_t *output, const uint8_t *key, + const int key_len, + const uint8_t *message, + const int message_len); +} + +#include + +#if !defined(CONFIG_BORINGSSL_CRYPTO) || !defined(CONFIG_ROLLBACK_SECRET_SIZE) +#error "fpsensor requires CONFIG_BORINGSSL_CRYPTO and ROLLBACK_SECRET_SIZE" +#endif + +test_export_static enum ec_error_list get_ikm(uint8_t *ikm) +{ + enum ec_error_list ret; + + if (!fp_tpm_seed_is_set()) { + CPRINTS("Seed hasn't been set."); + return EC_ERROR_ACCESS_DENIED; + } + + /* + * The first CONFIG_ROLLBACK_SECRET_SIZE bytes of IKM are read from the + * anti-rollback blocks. + */ + ret = rollback_get_secret(ikm); + if (ret != EC_SUCCESS) { + CPRINTS("Failed to read rollback secret: %d", ret); + return EC_ERROR_HW_INTERNAL; + } + /* + * IKM is the concatenation of the rollback secret and the seed from + * the TPM. + */ + memcpy(ikm + CONFIG_ROLLBACK_SECRET_SIZE, tpm_seed, sizeof(tpm_seed)); + + return EC_SUCCESS; +} + +test_mockable void compute_hmac_sha256(uint8_t *output, const uint8_t *key, + const int key_len, + const uint8_t *message, + const int message_len) +{ + hmac_SHA256(output, key, key_len, message, message_len); +} + +static void hkdf_extract(uint8_t *prk, const uint8_t *salt, size_t salt_size, + const uint8_t *ikm, size_t ikm_size) +{ + /* + * Derive a key with the "extract" step of HKDF + * https://tools.ietf.org/html/rfc5869#section-2.2 + */ + compute_hmac_sha256(prk, salt, salt_size, ikm, ikm_size); +} + +static enum ec_error_list hkdf_expand_one_step(uint8_t *out_key, + size_t out_key_size, + uint8_t *prk, size_t prk_size, + uint8_t *info, size_t info_size) +{ + uint8_t key_buf[SHA256_DIGEST_SIZE]; + uint8_t message_buf[SHA256_DIGEST_SIZE + 1]; + + if (out_key_size > SHA256_DIGEST_SIZE) { + CPRINTS("Deriving key material longer than SHA256_DIGEST_SIZE " + "requires more steps of HKDF expand."); + return EC_ERROR_INVAL; + } + + if (info_size > SHA256_DIGEST_SIZE) { + CPRINTS("Info size too big for HKDF."); + return EC_ERROR_INVAL; + } + + memcpy(message_buf, info, info_size); + /* 1 step, set the counter byte to 1. */ + message_buf[info_size] = 0x01; + compute_hmac_sha256(key_buf, prk, prk_size, message_buf, info_size + 1); + + memcpy(out_key, key_buf, out_key_size); + OPENSSL_cleanse(key_buf, sizeof(key_buf)); + + return EC_SUCCESS; +} + +enum ec_error_list hkdf_expand(uint8_t *out_key, size_t L, const uint8_t *prk, + size_t prk_size, const uint8_t *info, + size_t info_size) +{ + /* + * "Expand" step of HKDF. + * https://tools.ietf.org/html/rfc5869#section-2.3 + */ +#define HASH_LEN SHA256_DIGEST_SIZE + uint8_t count = 1; + const uint8_t *T = out_key; + size_t T_len = 0; + uint8_t T_buffer[HASH_LEN]; + /* Number of blocks. */ + const uint32_t N = DIV_ROUND_UP(L, HASH_LEN); + uint8_t info_buffer[HASH_LEN + HKDF_MAX_INFO_SIZE + sizeof(count)]; + bool arguments_valid = false; + + if (out_key == NULL || L == 0) + CPRINTS("HKDF expand: output buffer not valid."); + else if (prk == NULL) + CPRINTS("HKDF expand: prk is NULL."); + else if (info == NULL && info_size > 0) + CPRINTS("HKDF expand: info is NULL but info size is not zero."); + else if (info_size > HKDF_MAX_INFO_SIZE) + CPRINTF("HKDF expand: info size larger than %d bytes.\n", + HKDF_MAX_INFO_SIZE); + else if (N > HKDF_SHA256_MAX_BLOCK_COUNT) + CPRINTS("HKDF expand: output key size too large."); + else + arguments_valid = true; + + if (!arguments_valid) + return EC_ERROR_INVAL; + + while (L > 0) { + const size_t block_size = L < HASH_LEN ? L : HASH_LEN; + + memcpy(info_buffer, T, T_len); + memcpy(info_buffer + T_len, info, info_size); + info_buffer[T_len + info_size] = count; + compute_hmac_sha256(T_buffer, prk, prk_size, info_buffer, + T_len + info_size + sizeof(count)); + memcpy(out_key, T_buffer, block_size); + + T += T_len; + T_len = HASH_LEN; + count++; + out_key += block_size; + L -= block_size; + } + OPENSSL_cleanse(T_buffer, sizeof(T_buffer)); + OPENSSL_cleanse(info_buffer, sizeof(info_buffer)); + return EC_SUCCESS; +#undef HASH_LEN +} + +enum ec_error_list +derive_positive_match_secret(uint8_t *output, + const uint8_t *input_positive_match_salt) +{ + enum ec_error_list ret; + uint8_t ikm[CONFIG_ROLLBACK_SECRET_SIZE + sizeof(tpm_seed)]; + uint8_t prk[SHA256_DIGEST_SIZE]; + static const char info_prefix[] = "positive_match_secret for user "; + uint8_t info[sizeof(info_prefix) - 1 + sizeof(user_id)]; + + if (bytes_are_trivial(input_positive_match_salt, + FP_POSITIVE_MATCH_SALT_BYTES)) { + CPRINTS("Failed to derive positive match secret: " + "salt bytes are trivial."); + return EC_ERROR_INVAL; + } + + ret = get_ikm(ikm); + if (ret != EC_SUCCESS) { + CPRINTS("Failed to get IKM: %d", ret); + return ret; + } + + /* "Extract" step of HKDF. */ + hkdf_extract(prk, input_positive_match_salt, + FP_POSITIVE_MATCH_SALT_BYTES, ikm, sizeof(ikm)); + OPENSSL_cleanse(ikm, sizeof(ikm)); + + memcpy(info, info_prefix, strlen(info_prefix)); + memcpy(info + strlen(info_prefix), user_id, sizeof(user_id)); + + /* "Expand" step of HKDF. */ + ret = hkdf_expand(output, FP_POSITIVE_MATCH_SECRET_BYTES, prk, + sizeof(prk), info, sizeof(info)); + OPENSSL_cleanse(prk, sizeof(prk)); + + /* Check that secret is not full of 0x00 or 0xff. */ + if (bytes_are_trivial(output, FP_POSITIVE_MATCH_SECRET_BYTES)) { + CPRINTS("Failed to derive positive match secret: " + "derived secret bytes are trivial."); + ret = EC_ERROR_HW_INTERNAL; + } + return ret; +} + +enum ec_error_list derive_encryption_key(uint8_t *out_key, const uint8_t *salt) +{ + enum ec_error_list ret; + uint8_t ikm[CONFIG_ROLLBACK_SECRET_SIZE + sizeof(tpm_seed)]; + uint8_t prk[SHA256_DIGEST_SIZE]; + + BUILD_ASSERT(SBP_ENC_KEY_LEN <= SHA256_DIGEST_SIZE); + BUILD_ASSERT(SBP_ENC_KEY_LEN <= CONFIG_ROLLBACK_SECRET_SIZE); + BUILD_ASSERT(sizeof(user_id) == SHA256_DIGEST_SIZE); + + ret = get_ikm(ikm); + if (ret != EC_SUCCESS) { + CPRINTS("Failed to get IKM: %d", ret); + return ret; + } + + /* TODO (b/276344630): Replace with boringssl version. */ + /* "Extract step of HKDF. */ + hkdf_extract(prk, salt, FP_CONTEXT_ENCRYPTION_SALT_BYTES, ikm, + sizeof(ikm)); + OPENSSL_cleanse(ikm, sizeof(ikm)); + + /* + * Only 1 "expand" step of HKDF since the size of the "info" context + * (user_id in our case) is exactly SHA256_DIGEST_SIZE. + * https://tools.ietf.org/html/rfc5869#section-2.3 + */ + ret = hkdf_expand_one_step(out_key, SBP_ENC_KEY_LEN, prk, sizeof(prk), + (uint8_t *)user_id, sizeof(user_id)); + OPENSSL_cleanse(prk, sizeof(prk)); + + return ret; +} + +enum ec_error_list aes_gcm_encrypt(const uint8_t *key, int key_size, + const uint8_t *plaintext, + uint8_t *ciphertext, int text_size, + const uint8_t *nonce, int nonce_size, + uint8_t *tag, int tag_size) +{ + int res; + AES_KEY aes_key; + GCM128_CONTEXT ctx; + + if (nonce_size != FP_CONTEXT_NONCE_BYTES) { + CPRINTS("Invalid nonce size %d bytes", nonce_size); + return EC_ERROR_INVAL; + } + + /* TODO(b/279950931): Use public boringssl API. */ + res = AES_set_encrypt_key(key, 8 * key_size, &aes_key); + if (res) { + CPRINTS("Failed to set encryption key: %d", res); + return EC_ERROR_UNKNOWN; + } + CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0); + CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_size); + /* CRYPTO functions return 1 on success, 0 on error. */ + res = CRYPTO_gcm128_encrypt(&ctx, &aes_key, plaintext, ciphertext, + text_size); + if (!res) { + CPRINTS("Failed to encrypt: %d", res); + return EC_ERROR_UNKNOWN; + } + CRYPTO_gcm128_tag(&ctx, tag, tag_size); + return EC_SUCCESS; +} + +enum ec_error_list aes_gcm_decrypt(const uint8_t *key, int key_size, + uint8_t *plaintext, + const uint8_t *ciphertext, int text_size, + const uint8_t *nonce, int nonce_size, + const uint8_t *tag, int tag_size) +{ + int res; + AES_KEY aes_key; + GCM128_CONTEXT ctx; + + if (nonce_size != FP_CONTEXT_NONCE_BYTES) { + CPRINTS("Invalid nonce size %d bytes", nonce_size); + return EC_ERROR_INVAL; + } + + /* TODO(b/279950931): Use public boringssl API. */ + res = AES_set_encrypt_key(key, 8 * key_size, &aes_key); + if (res) { + CPRINTS("Failed to set decryption key: %d", res); + return EC_ERROR_UNKNOWN; + } + CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0); + CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_size); + /* CRYPTO functions return 1 on success, 0 on error. */ + res = CRYPTO_gcm128_decrypt(&ctx, &aes_key, ciphertext, plaintext, + text_size); + if (!res) { + CPRINTS("Failed to decrypt: %d", res); + return EC_ERROR_UNKNOWN; + } + res = CRYPTO_gcm128_finish(&ctx, tag, tag_size); + if (!res) { + CPRINTS("Found incorrect tag: %d", res); + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} diff --git a/common/fpsensor/fpsensor_debug.cc b/common/fpsensor/fpsensor_debug.cc new file mode 100644 index 0000000000..cdb79b944c --- /dev/null +++ b/common/fpsensor/fpsensor_debug.cc @@ -0,0 +1,303 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "compile_time_macros.h" + +extern "C" { +#include "atomic.h" +#include "clock.h" +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "host_command.h" +#include "link_defs.h" +#include "mkbp_event.h" +#include "overflow.h" +#include "spi.h" +#include "system.h" +#include "task.h" +#include "trng.h" +#include "util.h" +#include "watchdog.h" +} + +#include "fpsensor.h" +#include "fpsensor_crypto.h" +#include "fpsensor_detect.h" +#include "fpsensor_state.h" +#include "fpsensor_utils.h" + +#ifdef CONFIG_CMD_FPSENSOR_DEBUG +/* --- Debug console commands --- */ + +/* + * Send the current Fingerprint buffer to the host + * it is formatted as an 8-bpp PGM ASCII file. + * + * In addition, it prepends a short Z-Modem download signature, + * which triggers automatically your preferred viewer if you configure it + * properly in "File transfer protocols" in the Minicom options menu. + * (as triggered by Ctrl-A O) + * +--------------------------------------------------------------------------+ + * | Name Program Name U/D FullScr IO-Red. Multi | + * | A zmodem /usr/bin/sz -vv -b Y U N Y Y | + * [...] + * | L pgm /usr/bin/display_pgm N D N Y N | + * | M Zmodem download string activates... L | + * + * My /usr/bin/display_pgm looks like this: + * #!/bin/sh + * TMPF=$(mktemp) + * ascii-xfr -rdv ${TMPF} + * display ${TMPF} + * + * Alternative (if you're using screen as your terminal): + * + * From *outside* the chroot: + * + * Install ascii-xfr: sudo apt-get install minicom + * Install imagemagick: sudo apt-get install imagemagick + * + * Add the following to your ${HOME}/.screenrc: + * + * zmodem catch + * zmodem recvcmd '!!! bash -c "ascii-xfr -rdv /tmp/finger.pgm && display + * /tmp/finger.pgm"' + * + * From *outside the chroot*, use screen to connect to UART console: + * + * sudo screen -c ${HOME}/.screenrc /dev/pts/NN 115200 + * + */ +static void upload_pgm_image(uint8_t *frame) +{ + int x, y; + uint8_t *ptr = frame; + + /* fake Z-modem ZRQINIT signature */ + CPRINTF("#IGNORE for ZModem\r**\030B00"); + msleep(2000); /* let the download program start */ + /* Print 8-bpp PGM ASCII header */ + CPRINTF("P2\n%d %d\n255\n", FP_SENSOR_RES_X, FP_SENSOR_RES_Y); + + for (y = 0; y < FP_SENSOR_RES_Y; y++) { + watchdog_reload(); + for (x = 0; x < FP_SENSOR_RES_X; x++, ptr++) + CPRINTF("%d ", *ptr); + CPRINTF("\n"); + cflush(); + } + + CPRINTF("\x04"); /* End Of Transmission */ +} + +static enum ec_error_list fp_console_action(uint32_t mode) +{ + int tries = 200; + uint32_t mode_output = 0; + int rc = 0; + + if (!(sensor_mode & FP_MODE_RESET_SENSOR)) + CPRINTS("Waiting for finger ..."); + + rc = fp_set_sensor_mode(mode, &mode_output); + + if (rc != EC_RES_SUCCESS) { + /* + * EC host command errors do not directly map to console command + * errors. + */ + return EC_ERROR_UNKNOWN; + } + + while (tries--) { + if (!(sensor_mode & FP_MODE_ANY_CAPTURE)) { + CPRINTS("done (events:%x)", (int)fp_events); + return EC_SUCCESS; + } + usleep(100 * MSEC); + } + return EC_ERROR_TIMEOUT; +} + +static int command_fpcapture(int argc, const char **argv) +{ + int capture_type = FP_CAPTURE_SIMPLE_IMAGE; + uint32_t mode; + enum ec_error_list rc; + + /* + * TODO(b/142944002): Remove this redundant check for system_is_locked + * once we have unit-tests/integration-tests in place. + */ + if (system_is_locked()) + return EC_ERROR_ACCESS_DENIED; + + if (argc >= 2) { + char *e; + + capture_type = strtoi(argv[1], &e, 0); + if (*e || capture_type < 0) + return EC_ERROR_PARAM1; + } + mode = FP_MODE_CAPTURE | ((capture_type << FP_MODE_CAPTURE_TYPE_SHIFT) & + FP_MODE_CAPTURE_TYPE_MASK); + + rc = fp_console_action(mode); + if (rc == EC_SUCCESS) + upload_pgm_image(fp_buffer + FP_SENSOR_IMAGE_OFFSET); + + return rc; +} +DECLARE_CONSOLE_COMMAND_FLAGS(fpcapture, command_fpcapture, NULL, + "Capture fingerprint in PGM format", + CMD_FLAG_RESTRICTED); + +/* Transfer a chunk of the image from the host to the FPMCU + * + * Command format: + * fpupload + * + * To limit the size of the commands, only a chunk of the image is sent for + * each command invocation. + */ +static int command_fpupload(int argc, const char **argv) +{ + const char *pixels_str; + uint8_t *dest; + int offset; + + if (argc != 3) + return EC_ERROR_PARAM1; + if (system_is_locked()) + return EC_ERROR_ACCESS_DENIED; + offset = atoi(argv[1]); + if (offset < 0) + return EC_ERROR_PARAM1; + dest = fp_buffer + FP_SENSOR_IMAGE_OFFSET + offset; + + pixels_str = argv[2]; + while (*pixels_str) { + if (dest >= fp_buffer + FP_SENSOR_IMAGE_SIZE) + return EC_ERROR_PARAM1; + char hex_str[] = { pixels_str[0], pixels_str[1], '\0' }; + *dest = static_cast(strtol(hex_str, NULL, 16)); + pixels_str += 2; + ++dest; + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(fpupload, command_fpupload, NULL, + "Copy fp image onto fpmcu fpsensor buffer"); + +/* Transfer an image from the FPMCU to the host + * + * Command format: + * fpdownload + * + * This is useful to verify the data was transferred correctly. Note that it + * requires the terminal to be configured as explained in the comment above + * upload_pgm_image(). + */ +static int command_fpdownload(int argc, const char **argv) +{ + if (system_is_locked()) + return EC_ERROR_ACCESS_DENIED; + + upload_pgm_image(fp_buffer + FP_SENSOR_IMAGE_OFFSET); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(fpdownload, command_fpdownload, NULL, + "Copy fp image from fpmcu fpsensor buffer"); + +static int command_fpenroll(int argc, const char **argv) +{ + enum ec_error_list rc; + int percent = 0; + uint32_t event; + static const char *const enroll_str[] = { "OK", "Low Quality", + "Immobile", "Low Coverage" }; + + /* + * TODO(b/142944002): Remove this redundant check for system_is_locked + * once we have unit-tests/integration-tests in place. + */ + if (system_is_locked()) + return EC_ERROR_ACCESS_DENIED; + + do { + int tries = 1000; + + rc = fp_console_action(FP_MODE_ENROLL_SESSION | + FP_MODE_ENROLL_IMAGE); + if (rc != EC_SUCCESS) + break; + event = atomic_clear(&fp_events); + percent = EC_MKBP_FP_ENROLL_PROGRESS(event); + CPRINTS("Enroll capture: %s (%d%%)", + enroll_str[EC_MKBP_FP_ERRCODE(event) & 3], percent); + /* wait for finger release between captures */ + sensor_mode = FP_MODE_ENROLL_SESSION | FP_MODE_FINGER_UP; + task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_UPDATE_CONFIG); + while (tries-- && sensor_mode & FP_MODE_FINGER_UP) + usleep(20 * MSEC); + } while (percent < 100); + sensor_mode = 0; /* reset FP_MODE_ENROLL_SESSION */ + task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_UPDATE_CONFIG); + + return rc; +} +DECLARE_CONSOLE_COMMAND_FLAGS(fpenroll, command_fpenroll, NULL, + "Enroll a new fingerprint", CMD_FLAG_RESTRICTED); + +static int command_fpmatch(int argc, const char **argv) +{ + enum ec_error_list rc = fp_console_action(FP_MODE_MATCH); + uint32_t event = atomic_clear(&fp_events); + + if (rc == EC_SUCCESS && event & EC_MKBP_FP_MATCH) { + uint32_t match_errcode = EC_MKBP_FP_ERRCODE(event); + + CPRINTS("Match: %s (%d)", + fp_match_success(match_errcode) ? "YES" : "NO", + match_errcode); + } + + return rc; +} +DECLARE_CONSOLE_COMMAND(fpmatch, command_fpmatch, NULL, + "Run match algorithm against finger"); + +static int command_fpclear(int argc, const char **argv) +{ + /* + * We intentionally run this on the fp_task so that we use the + * same code path as host commands. + */ + enum ec_error_list rc = fp_console_action(FP_MODE_RESET_SENSOR); + + if (rc != EC_SUCCESS) + CPRINTS("Failed to clear fingerprint context: %d", rc); + + atomic_clear(&fp_events); + + return rc; +} +DECLARE_CONSOLE_COMMAND(fpclear, command_fpclear, NULL, + "Clear fingerprint sensor context"); + +static int command_fpmaintenance(int argc, const char **argv) +{ +#ifdef HAVE_FP_PRIVATE_DRIVER + return fp_maintenance(); +#else + return EC_SUCCESS; +#endif /* #ifdef HAVE_FP_PRIVATE_DRIVER */ +} +DECLARE_CONSOLE_COMMAND(fpmaintenance, command_fpmaintenance, NULL, + "Run fingerprint sensor maintenance"); + +#endif /* CONFIG_CMD_FPSENSOR_DEBUG */ diff --git a/common/fpsensor/fpsensor_detect_strings.c b/common/fpsensor/fpsensor_detect_strings.c deleted file mode 100644 index b9bcf9bb3b..0000000000 --- a/common/fpsensor/fpsensor_detect_strings.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "fpsensor_detect.h" - -const char *fp_transport_type_to_str(enum fp_transport_type type) -{ - switch (type) { - case FP_TRANSPORT_TYPE_UNKNOWN: - default: - return "UNKNOWN"; - case FP_TRANSPORT_TYPE_SPI: - return "SPI"; - case FP_TRANSPORT_TYPE_UART: - return "UART"; - } -} - -const char *fp_sensor_type_to_str(enum fp_sensor_type type) -{ - switch (type) { - case FP_SENSOR_TYPE_UNKNOWN: - default: - return "UNKNOWN"; - case FP_SENSOR_TYPE_FPC: - return "FPC"; - case FP_SENSOR_TYPE_ELAN: - return "ELAN"; - } -} - diff --git a/common/fpsensor/fpsensor_detect_strings.cc b/common/fpsensor/fpsensor_detect_strings.cc new file mode 100644 index 0000000000..af08219ced --- /dev/null +++ b/common/fpsensor/fpsensor_detect_strings.cc @@ -0,0 +1,44 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "fpsensor_detect.h" + +const char *fp_transport_type_to_str(enum fp_transport_type type) +{ + switch (type) { + case FP_TRANSPORT_TYPE_UNKNOWN: + default: + return "UNKNOWN"; + case FP_TRANSPORT_TYPE_SPI: + return "SPI"; + case FP_TRANSPORT_TYPE_UART: + return "UART"; + } +} + +const char *fp_sensor_type_to_str(enum fp_sensor_type type) +{ + switch (type) { + case FP_SENSOR_TYPE_UNKNOWN: + default: + return "UNKNOWN"; + case FP_SENSOR_TYPE_FPC: + return "FPC"; + case FP_SENSOR_TYPE_ELAN: + return "ELAN"; + } +} + +const char *fp_sensor_spi_select_to_str(enum fp_sensor_spi_select type) +{ + switch (type) { + case FP_SENSOR_SPI_SELECT_UNKNOWN: + default: + return "UNKNOWN"; + case FP_SENSOR_SPI_SELECT_DEVELOPMENT: + return "DEVELOPMENT"; + case FP_SENSOR_SPI_SELECT_PRODUCTION: + return "PRODUCTION"; + } +} diff --git a/common/fpsensor/fpsensor_private.h b/common/fpsensor/fpsensor_private.h deleted file mode 100644 index a42049dece..0000000000 --- a/common/fpsensor/fpsensor_private.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Internal header file for common/fpsensor directory */ - -#ifndef __CROS_EC_FPSENSOR_PRIVATE_H -#define __CROS_EC_FPSENSOR_PRIVATE_H - -#include - -#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args) -#define CPRINTS(format, args...) cprints(CC_FP, format, ## args) - -int validate_fp_buffer_offset(uint32_t buffer_size, uint32_t offset, - uint32_t size); - -#endif /* __CROS_EC_FPSENSOR_PRIVATE_H */ diff --git a/common/fpsensor/fpsensor_state.c b/common/fpsensor/fpsensor_state.c deleted file mode 100644 index 82fa4f23a1..0000000000 --- a/common/fpsensor/fpsensor_state.c +++ /dev/null @@ -1,313 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "cryptoc/util.h" -#include "ec_commands.h" -#include "fpsensor.h" -#include "fpsensor_crypto.h" -#include "fpsensor_private.h" -#include "fpsensor_state.h" -#include "host_command.h" -#include "system.h" -#include "task.h" -#include "util.h" - -/* Last acquired frame (aligned as it is used by arbitrary binary libraries) */ -uint8_t fp_buffer[FP_SENSOR_IMAGE_SIZE] FP_FRAME_SECTION __aligned(4); -/* Fingers templates for the current user */ -uint8_t fp_template[FP_MAX_FINGER_COUNT][FP_ALGORITHM_TEMPLATE_SIZE] - FP_TEMPLATE_SECTION; -/* Encryption/decryption buffer */ -/* TODO: On-the-fly encryption/decryption without a dedicated buffer */ -/* - * Store the encryption metadata at the beginning of the buffer containing the - * ciphered data. - */ -uint8_t fp_enc_buffer[FP_ALGORITHM_ENCRYPTED_TEMPLATE_SIZE] - FP_TEMPLATE_SECTION; -/* Salt used in derivation of positive match secret. */ -uint8_t fp_positive_match_salt - [FP_MAX_FINGER_COUNT][FP_POSITIVE_MATCH_SALT_BYTES]; - -struct positive_match_secret_state positive_match_secret_state = { - .template_matched = FP_NO_SUCH_TEMPLATE, - .readable = false, - .deadline.val = 0, -}; - -/* Index of the last enrolled but not retrieved template. */ -int8_t template_newly_enrolled = FP_NO_SUCH_TEMPLATE; -/* Number of used templates */ -uint32_t templ_valid; -/* Bitmap of the templates with local modifications */ -uint32_t templ_dirty; -/* Current user ID */ -uint32_t user_id[FP_CONTEXT_USERID_WORDS]; -/* Part of the IKM used to derive encryption keys received from the TPM. */ -uint8_t tpm_seed[FP_CONTEXT_TPM_BYTES]; -/* Status of the FP encryption engine. */ -static uint32_t fp_encryption_status; - -uint32_t fp_events; - -uint32_t sensor_mode; - -void fp_task_simulate(void) -{ - int timeout_us = -1; - - while (1) - task_wait_event(timeout_us); -} - -void fp_clear_finger_context(int idx) -{ - always_memset(fp_template[idx], 0, sizeof(fp_template[0])); - always_memset(fp_positive_match_salt[idx], 0, - sizeof(fp_positive_match_salt[0])); -} - -/** - * @warning |fp_buffer| contains data used by the matching algorithm that must - * be released by calling fp_sensor_deinit() first. Call - * fp_reset_and_clear_context instead of calling this directly. - */ -static void _fp_clear_context(void) -{ - int idx; - - templ_valid = 0; - templ_dirty = 0; - always_memset(fp_buffer, 0, sizeof(fp_buffer)); - always_memset(fp_enc_buffer, 0, sizeof(fp_enc_buffer)); - always_memset(user_id, 0, sizeof(user_id)); - fp_disable_positive_match_secret(&positive_match_secret_state); - for (idx = 0; idx < FP_MAX_FINGER_COUNT; idx++) - fp_clear_finger_context(idx); -} - -void fp_reset_and_clear_context(void) -{ - if (fp_sensor_deinit() != EC_SUCCESS) - CPRINTS("Failed to deinit sensor"); - _fp_clear_context(); - if (fp_sensor_init() != EC_SUCCESS) - CPRINTS("Failed to init sensor"); -} - -int fp_get_next_event(uint8_t *out) -{ - uint32_t event_out = deprecated_atomic_read_clear(&fp_events); - - memcpy(out, &event_out, sizeof(event_out)); - - return sizeof(event_out); -} -DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_FINGERPRINT, fp_get_next_event); - -static enum ec_status fp_command_tpm_seed(struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_seed *params = args->params; - - if (params->struct_version != FP_TEMPLATE_FORMAT_VERSION) { - CPRINTS("Invalid seed format %d", params->struct_version); - return EC_RES_INVALID_PARAM; - } - - if (fp_encryption_status & FP_ENC_STATUS_SEED_SET) { - CPRINTS("Seed has already been set."); - return EC_RES_ACCESS_DENIED; - } - memcpy(tpm_seed, params->seed, sizeof(tpm_seed)); - fp_encryption_status |= FP_ENC_STATUS_SEED_SET; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_SEED, fp_command_tpm_seed, EC_VER_MASK(0)); - -int fp_tpm_seed_is_set(void) -{ - return fp_encryption_status & FP_ENC_STATUS_SEED_SET; -} - -static enum ec_status -fp_command_encryption_status(struct host_cmd_handler_args *args) -{ - struct ec_response_fp_encryption_status *r = args->response; - - r->valid_flags = FP_ENC_STATUS_SEED_SET; - r->status = fp_encryption_status; - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_ENC_STATUS, fp_command_encryption_status, - EC_VER_MASK(0)); - -static int validate_fp_mode(const uint32_t mode) -{ - uint32_t capture_type = FP_CAPTURE_TYPE(mode); - uint32_t algo_mode = mode & ~FP_MODE_CAPTURE_TYPE_MASK; - uint32_t cur_mode = sensor_mode; - - if (capture_type >= FP_CAPTURE_TYPE_MAX) - return EC_ERROR_INVAL; - - if (algo_mode & ~FP_VALID_MODES) - return EC_ERROR_INVAL; - - if ((mode & FP_MODE_ENROLL_SESSION) && - templ_valid >= FP_MAX_FINGER_COUNT) { - CPRINTS("Maximum number of fingers already enrolled: %d", - FP_MAX_FINGER_COUNT); - return EC_ERROR_INVAL; - } - - /* Don't allow sensor reset if any other mode is - * set (including FP_MODE_RESET_SENSOR itself). - */ - if (mode & FP_MODE_RESET_SENSOR) { - if (cur_mode & FP_VALID_MODES) - return EC_ERROR_INVAL; - } - - return EC_SUCCESS; -} - -int fp_set_sensor_mode(uint32_t mode, uint32_t *mode_output) -{ - int ret; - - if (mode_output == NULL) - return EC_RES_INVALID_PARAM; - - ret = validate_fp_mode(mode); - if (ret != EC_SUCCESS) { - CPRINTS("Invalid FP mode 0x%x", mode); - return EC_RES_INVALID_PARAM; - } - - if (!(mode & FP_MODE_DONT_CHANGE)) { - sensor_mode = mode; - task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_UPDATE_CONFIG, 0); - } - - *mode_output = sensor_mode; - return EC_RES_SUCCESS; -} - -static enum ec_status fp_command_mode(struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_mode *p = args->params; - struct ec_response_fp_mode *r = args->response; - - int ret = fp_set_sensor_mode(p->mode, &r->mode); - - if (ret == EC_RES_SUCCESS) - args->response_size = sizeof(*r); - - return ret; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_MODE, fp_command_mode, EC_VER_MASK(0)); - -static enum ec_status fp_command_context(struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_context_v1 *p = args->params; - uint32_t mode_output; - - switch (p->action) { - case FP_CONTEXT_ASYNC: - if (sensor_mode & FP_MODE_RESET_SENSOR) - return EC_RES_BUSY; - - /** - * Trigger a call to fp_reset_and_clear_context() by - * requesting a reset. Since that function triggers a call to - * fp_sensor_open(), this must be asynchronous because - * fp_sensor_open() can take ~175 ms. See http://b/137288498. - */ - return fp_set_sensor_mode(FP_MODE_RESET_SENSOR, &mode_output); - - case FP_CONTEXT_GET_RESULT: - if (sensor_mode & FP_MODE_RESET_SENSOR) - return EC_RES_BUSY; - - memcpy(user_id, p->userid, sizeof(user_id)); - return EC_RES_SUCCESS; - } - - return EC_RES_INVALID_PARAM; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_CONTEXT, fp_command_context, EC_VER_MASK(1)); - -int fp_enable_positive_match_secret(uint32_t fgr, - struct positive_match_secret_state *state) -{ - timestamp_t now; - - if (state->readable) { - CPRINTS("Error: positive match secret already readable."); - fp_disable_positive_match_secret(state); - return EC_ERROR_UNKNOWN; - } - - now = get_time(); - state->template_matched = fgr; - state->readable = true; - state->deadline.val = now.val + (5 * SECOND); - return EC_SUCCESS; -} - -void fp_disable_positive_match_secret( - struct positive_match_secret_state *state) -{ - state->template_matched = FP_NO_SUCH_TEMPLATE; - state->readable = false; - state->deadline.val = 0; -} - -static enum ec_status fp_command_read_match_secret( - struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_read_match_secret *params = args->params; - struct ec_response_fp_read_match_secret *response = args->response; - int8_t fgr = params->fgr; - timestamp_t now = get_time(); - struct positive_match_secret_state state_copy - = positive_match_secret_state; - - fp_disable_positive_match_secret(&positive_match_secret_state); - - if (fgr < 0 || fgr >= FP_MAX_FINGER_COUNT) { - CPRINTS("Invalid finger number %d", fgr); - return EC_RES_INVALID_PARAM; - } - if (timestamp_expired(state_copy.deadline, &now)) { - CPRINTS("Reading positive match secret disallowed: " - "deadline has passed."); - return EC_RES_TIMEOUT; - } - if (fgr != state_copy.template_matched || !state_copy.readable) { - CPRINTS("Positive match secret for finger %d is not meant to " - "be read now.", fgr); - return EC_RES_ACCESS_DENIED; - } - - if (derive_positive_match_secret(response->positive_match_secret, - fp_positive_match_salt[fgr]) - != EC_SUCCESS) { - CPRINTS("Failed to derive positive match secret for finger %d", - fgr); - /* Keep the template and encryption salt. */ - return EC_RES_ERROR; - } - CPRINTS("Derived positive match secret for finger %d", fgr); - args->response_size = sizeof(*response); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_READ_MATCH_SECRET, fp_command_read_match_secret, - EC_VER_MASK(0)); diff --git a/common/fpsensor/fpsensor_state.cc b/common/fpsensor/fpsensor_state.cc new file mode 100644 index 0000000000..453d982eab --- /dev/null +++ b/common/fpsensor/fpsensor_state.cc @@ -0,0 +1,312 @@ +/* Copyright 2019 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "compile_time_macros.h" + +/* Boringssl headers need to be included before extern "C" section. */ +#include "openssl/mem.h" + +extern "C" { +#include "atomic.h" +#include "common.h" +#include "ec_commands.h" +#include "host_command.h" +#include "system.h" +#include "task.h" +#include "util.h" +} + +#include "fpsensor.h" +#include "fpsensor_crypto.h" +#include "fpsensor_state.h" +#include "fpsensor_utils.h" + +/* Last acquired frame (aligned as it is used by arbitrary binary libraries) */ +uint8_t fp_buffer[FP_SENSOR_IMAGE_SIZE] FP_FRAME_SECTION __aligned(4); +/* Fingers templates for the current user */ +uint8_t fp_template[FP_MAX_FINGER_COUNT] + [FP_ALGORITHM_TEMPLATE_SIZE] FP_TEMPLATE_SECTION; +/* Encryption/decryption buffer */ +/* TODO: On-the-fly encryption/decryption without a dedicated buffer */ +/* + * Store the encryption metadata at the beginning of the buffer containing the + * ciphered data. + */ +uint8_t fp_enc_buffer[FP_ALGORITHM_ENCRYPTED_TEMPLATE_SIZE] FP_TEMPLATE_SECTION; +/* Salt used in derivation of positive match secret. */ +uint8_t fp_positive_match_salt[FP_MAX_FINGER_COUNT] + [FP_POSITIVE_MATCH_SALT_BYTES]; + +void fp_task_simulate(void) +{ + int timeout_us = -1; + + while (1) + task_wait_event(timeout_us); +} + +void fp_clear_finger_context(uint16_t idx) +{ + OPENSSL_cleanse(fp_template[idx], sizeof(fp_template[0])); + OPENSSL_cleanse(fp_positive_match_salt[idx], + sizeof(fp_positive_match_salt[0])); +} + +/** + * @warning |fp_buffer| contains data used by the matching algorithm that must + * be released by calling fp_sensor_deinit() first. Call + * fp_reset_and_clear_context instead of calling this directly. + */ +static void _fp_clear_context(void) +{ + templ_valid = 0; + templ_dirty = 0; + OPENSSL_cleanse(fp_buffer, sizeof(fp_buffer)); + OPENSSL_cleanse(fp_enc_buffer, sizeof(fp_enc_buffer)); + OPENSSL_cleanse(user_id, sizeof(user_id)); + fp_disable_positive_match_secret(&positive_match_secret_state); + for (uint16_t idx = 0; idx < FP_MAX_FINGER_COUNT; idx++) + fp_clear_finger_context(idx); +} + +void fp_reset_and_clear_context(void) +{ + if (fp_sensor_deinit() != EC_SUCCESS) + CPRINTS("Failed to deinit sensor"); + _fp_clear_context(); + if (fp_sensor_init() != EC_SUCCESS) + CPRINTS("Failed to init sensor"); +} + +int fp_get_next_event(uint8_t *out) +{ + uint32_t event_out = atomic_clear(&fp_events); + + memcpy(out, &event_out, sizeof(event_out)); + + return sizeof(event_out); +} +DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_FINGERPRINT, fp_get_next_event); + +static enum ec_status fp_command_tpm_seed(struct host_cmd_handler_args *args) +{ + const auto *params = + static_cast(args->params); + + if (params->struct_version != FP_TEMPLATE_FORMAT_VERSION) { + CPRINTS("Invalid seed format %d", params->struct_version); + return EC_RES_INVALID_PARAM; + } + + if (fp_encryption_status & FP_ENC_STATUS_SEED_SET) { + CPRINTS("Seed has already been set."); + return EC_RES_ACCESS_DENIED; + } + memcpy(tpm_seed, params->seed, sizeof(tpm_seed)); + fp_encryption_status |= FP_ENC_STATUS_SEED_SET; + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_SEED, fp_command_tpm_seed, EC_VER_MASK(0)); + +static enum ec_status +fp_command_encryption_status(struct host_cmd_handler_args *args) +{ + auto *r = + static_cast(args->response); + + r->valid_flags = FP_ENC_STATUS_SEED_SET; + r->status = fp_encryption_status; + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_ENC_STATUS, fp_command_encryption_status, + EC_VER_MASK(0)); + +static int validate_fp_mode(const uint32_t mode) +{ + uint32_t capture_type = FP_CAPTURE_TYPE(mode); + uint32_t algo_mode = mode & ~FP_MODE_CAPTURE_TYPE_MASK; + uint32_t cur_mode = sensor_mode; + + if (capture_type >= FP_CAPTURE_TYPE_MAX) + return EC_ERROR_INVAL; + + if (algo_mode & ~FP_VALID_MODES) + return EC_ERROR_INVAL; + + if ((mode & FP_MODE_ENROLL_SESSION) && + templ_valid >= FP_MAX_FINGER_COUNT) { + CPRINTS("Maximum number of fingers already enrolled: %d", + FP_MAX_FINGER_COUNT); + return EC_ERROR_INVAL; + } + + /* Don't allow sensor reset if any other mode is + * set (including FP_MODE_RESET_SENSOR itself). + */ + if (mode & FP_MODE_RESET_SENSOR) { + if (cur_mode & FP_VALID_MODES) + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +enum ec_status fp_set_sensor_mode(uint32_t mode, uint32_t *mode_output) +{ + int ret; + + if (mode_output == NULL) + return EC_RES_INVALID_PARAM; + + ret = validate_fp_mode(mode); + if (ret != EC_SUCCESS) { + CPRINTS("Invalid FP mode 0x%x", mode); + return EC_RES_INVALID_PARAM; + } + + if (!(mode & FP_MODE_DONT_CHANGE)) { + sensor_mode = mode; + task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_UPDATE_CONFIG); + } + + *mode_output = sensor_mode; + return EC_RES_SUCCESS; +} + +static enum ec_status fp_command_mode(struct host_cmd_handler_args *args) +{ + const auto *p = static_cast(args->params); + auto *r = static_cast(args->response); + + enum ec_status ret = fp_set_sensor_mode(p->mode, &r->mode); + + if (ret == EC_RES_SUCCESS) + args->response_size = sizeof(*r); + + return ret; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_MODE, fp_command_mode, EC_VER_MASK(0)); + +static enum ec_status fp_command_context(struct host_cmd_handler_args *args) +{ + const auto *p = + static_cast(args->params); + uint32_t mode_output; + + switch (p->action) { + case FP_CONTEXT_ASYNC: + if (sensor_mode & FP_MODE_RESET_SENSOR) + return EC_RES_BUSY; + + /** + * Trigger a call to fp_reset_and_clear_context() by + * requesting a reset. Since that function triggers a call to + * fp_sensor_open(), this must be asynchronous because + * fp_sensor_open() can take ~175 ms. See http://b/137288498. + */ + return fp_set_sensor_mode(FP_MODE_RESET_SENSOR, &mode_output); + + case FP_CONTEXT_GET_RESULT: + if (sensor_mode & FP_MODE_RESET_SENSOR) + return EC_RES_BUSY; + + memcpy(user_id, p->userid, sizeof(user_id)); + return EC_RES_SUCCESS; + } + + return EC_RES_INVALID_PARAM; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_CONTEXT, fp_command_context, EC_VER_MASK(1)); + +int fp_enable_positive_match_secret(uint16_t fgr, + struct positive_match_secret_state *state) +{ + timestamp_t now; + + if (state->readable) { + CPRINTS("Error: positive match secret already readable."); + fp_disable_positive_match_secret(state); + return EC_ERROR_UNKNOWN; + } + + now = get_time(); + state->template_matched = fgr; + state->readable = true; + state->deadline.val = now.val + (5 * SECOND); + return EC_SUCCESS; +} + +void fp_disable_positive_match_secret(struct positive_match_secret_state *state) +{ + state->template_matched = FP_NO_SUCH_TEMPLATE; + state->readable = false; + state->deadline.val = 0; +} + +enum ec_status fp_read_match_secret( + int8_t fgr, + uint8_t positive_match_secret[FP_POSITIVE_MATCH_SECRET_BYTES]) +{ + timestamp_t now = get_time(); + struct positive_match_secret_state state_copy = + positive_match_secret_state; + + fp_disable_positive_match_secret(&positive_match_secret_state); + + if (fgr < 0 || fgr >= FP_MAX_FINGER_COUNT) { + CPRINTS("Invalid finger number %d", fgr); + return EC_RES_INVALID_PARAM; + } + if (timestamp_expired(state_copy.deadline, &now)) { + CPRINTS("Reading positive match secret disallowed: " + "deadline has passed."); + return EC_RES_TIMEOUT; + } + if (fgr != state_copy.template_matched || !state_copy.readable) { + CPRINTS("Positive match secret for finger %d is not meant to " + "be read now.", + fgr); + return EC_RES_ACCESS_DENIED; + } + + if (derive_positive_match_secret(positive_match_secret, + fp_positive_match_salt[fgr]) != + EC_SUCCESS) { + CPRINTS("Failed to derive positive match secret for finger %d", + fgr); + /* Keep the template and encryption salt. */ + return EC_RES_ERROR; + } + CPRINTS("Derived positive match secret for finger %d", fgr); + + return EC_RES_SUCCESS; +} + +static enum ec_status +fp_command_read_match_secret(struct host_cmd_handler_args *args) +{ + const auto *params = + static_cast( + args->params); + auto *response = + static_cast(args->response); + int8_t fgr = params->fgr; + + ec_status ret = + fp_read_match_secret(fgr, response->positive_match_secret); + + if (ret != EC_RES_SUCCESS) { + return ret; + } + + args->response_size = sizeof(*response); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_READ_MATCH_SECRET, fp_command_read_match_secret, + EC_VER_MASK(0)); diff --git a/common/fpsensor/fpsensor_state_without_driver_info.cc b/common/fpsensor/fpsensor_state_without_driver_info.cc new file mode 100644 index 0000000000..80bee55452 --- /dev/null +++ b/common/fpsensor/fpsensor_state_without_driver_info.cc @@ -0,0 +1,40 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "fpsensor_state_without_driver_info.h" + +/* TODO(b/286119221): Refactor fingerprint sensor state. */ + +extern "C" { + +struct positive_match_secret_state + positive_match_secret_state = { .template_matched = FP_NO_SUCH_TEMPLATE, + .readable = false, + .deadline = { + .val = 0, + } }; + +/* Index of the last enrolled but not retrieved template. */ +uint16_t template_newly_enrolled = FP_NO_SUCH_TEMPLATE; +/* Number of used templates */ +uint16_t templ_valid; +/* Bitmap of the templates with local modifications */ +uint32_t templ_dirty; +/* Current user ID */ +uint32_t user_id[FP_CONTEXT_USERID_WORDS]; +/* Part of the IKM used to derive encryption keys received from the TPM. */ +uint8_t tpm_seed[FP_CONTEXT_TPM_BYTES]; +/* Status of the FP encryption engine & context. */ +uint32_t fp_encryption_status; + +atomic_t fp_events; + +uint32_t sensor_mode; + +int fp_tpm_seed_is_set(void) +{ + return fp_encryption_status & FP_ENC_STATUS_SEED_SET; +} +} diff --git a/common/gesture.c b/common/gesture.c index 86039e33bb..48e6af3571 100644 --- a/common/gesture.c +++ b/common/gesture.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,8 +8,8 @@ #include "accelgyro.h" #include "common.h" #include "console.h" -#include "hooks.h" #include "gesture.h" +#include "hooks.h" #include "lid_switch.h" #include "lightbar.h" #include "motion_sense.h" @@ -19,9 +19,8 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_GESTURE, outstr) -#define CPRINTS(format, args...) cprints(CC_GESTURE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_GESTURE, format, ## args) - +#define CPRINTS(format, args...) cprints(CC_GESTURE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_GESTURE, format, ##args) /* * Double tap detection parameters @@ -34,16 +33,16 @@ * which to check for relatively calm periods. In between the two impulses * there is a minimum and maximum interstice time allowed. */ -#define OUTER_WINDOW \ +#define OUTER_WINDOW \ (CONFIG_GESTURE_TAP_OUTER_WINDOW_T / \ CONFIG_GESTURE_SAMPLING_INTERVAL_MS) -#define INNER_WINDOW \ +#define INNER_WINDOW \ (CONFIG_GESTURE_TAP_INNER_WINDOW_T / \ CONFIG_GESTURE_SAMPLING_INTERVAL_MS) -#define MIN_INTERSTICE \ +#define MIN_INTERSTICE \ (CONFIG_GESTURE_TAP_MIN_INTERSTICE_T / \ CONFIG_GESTURE_SAMPLING_INTERVAL_MS) -#define MAX_INTERSTICE \ +#define MAX_INTERSTICE \ (CONFIG_GESTURE_TAP_MAX_INTERSTICE_T / \ CONFIG_GESTURE_SAMPLING_INTERVAL_MS) #define MAX_WINDOW OUTER_WINDOW @@ -67,10 +66,10 @@ enum tap_states { /* Tap sensor to use */ static struct motion_sensor_t *sensor = -&motion_sensors[CONFIG_GESTURE_SENSOR_DOUBLE_TAP]; + &motion_sensors[CONFIG_GESTURE_TAP_SENSOR]; /* Tap state information */ -static int history_z[MAX_WINDOW]; /* Changes in Z */ +static int history_z[MAX_WINDOW]; /* Changes in Z */ static int history_xy[MAX_WINDOW]; /* Changes in X and Y */ static int state, history_idx; static int history_initialized, history_init_index; @@ -166,7 +165,7 @@ static int gesture_tap_for_battery(void) (OUTER_WINDOW - INNER_WINDOW); delta_z_inner = sum_z_inner * 1000 / INNER_WINDOW; delta_xy_outer = (sum_xy_outer - sum_xy_inner) * 1000 / - (OUTER_WINDOW - INNER_WINDOW); + (OUTER_WINDOW - INNER_WINDOW); delta_xy_inner = sum_xy_inner * 1000 / INNER_WINDOW; state_cnt++; @@ -253,13 +252,11 @@ static int gesture_tap_for_battery(void) } /* On state transitions, print debug info */ - if (tap_debug && - (state != state_p || - (state_cnt % 10000 == 9999))) { + if (tap_debug && (state != state_p || (state_cnt % 10000 == 9999))) { /* make sure we don't divide by 0 */ if (delta_z_outer == 0 || delta_xy_inner == 0) - CPRINTS("tap st %d->%d, error div by 0", - state_p, state); + CPRINTS("tap st %d->%d, error div by 0", state_p, + state); else CPRINTS("tap st %d->%d, st_cnt %-3d " "Z_in:Z_out %-3d, Z_in:XY_in %-3d " @@ -267,10 +264,8 @@ static int gesture_tap_for_battery(void) "dZ_out %-8.3d", state_p, state, state_cnt, delta_z_inner / delta_z_outer, - delta_z_inner / delta_xy_inner, - delta_z_inner, - delta_z_inner_max, - delta_z_outer); + delta_z_inner / delta_xy_inner, delta_z_inner, + delta_z_inner_max, delta_z_outer); } return ret; @@ -281,8 +276,7 @@ static void gesture_chipset_resume(void) /* disable tap detection */ tap_detection = 0; } -DECLARE_HOOK(HOOK_CHIPSET_RESUME, gesture_chipset_resume, - GESTURE_HOOK_PRIO); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, gesture_chipset_resume, GESTURE_HOOK_PRIO); static void gesture_chipset_suspend(void) { @@ -295,8 +289,7 @@ static void gesture_chipset_suspend(void) state = TAP_IDLE; tap_detection = 1; } -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, gesture_chipset_suspend, - GESTURE_HOOK_PRIO); +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, gesture_chipset_suspend, GESTURE_HOOK_PRIO); void gesture_calc(uint32_t *event) { @@ -306,17 +299,17 @@ void gesture_calc(uint32_t *event) if (gesture_tap_for_battery()) *event |= TASK_EVENT_MOTION_ACTIVITY_INTERRUPT( - MOTIONSENSE_ACTIVITY_DOUBLE_TAP); + MOTIONSENSE_ACTIVITY_DOUBLE_TAP); } /*****************************************************************************/ /* Console commands */ -static int command_tap_info(int argc, char **argv) +static int command_tap_info(int argc, const char **argv) { int val; - ccprintf("tap: %s\n", (tap_detection && !lid_is_open()) ? - "on" : "off"); + ccprintf("tap: %s\n", + (tap_detection && !lid_is_open()) ? "on" : "off"); if (argc > 1) { if (!parse_bool(argv[1], &val)) @@ -329,7 +322,5 @@ static int command_tap_info(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(tapinfo, command_tap_info, - "debug on/off", +DECLARE_CONSOLE_COMMAND(tapinfo, command_tap_info, "debug on/off", "Print tap information"); - diff --git a/common/gettimeofday.c b/common/gettimeofday.c new file mode 100644 index 0000000000..fce5c7e04e --- /dev/null +++ b/common/gettimeofday.c @@ -0,0 +1,23 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gettimeofday.h" +#include "timer.h" + +#include + +enum ec_error_list ec_gettimeofday(struct timeval *restrict tv, + void *restrict tz) +{ + uint64_t now; + + if (tv == NULL) + return EC_ERROR_INVAL; + + now = get_time().val; + tv->tv_sec = now / SECOND; + tv->tv_usec = now % SECOND; + return EC_SUCCESS; +} diff --git a/common/gpio.c b/common/gpio.c index f89be2700d..b69878eca3 100644 --- a/common/gpio.c +++ b/common/gpio.c @@ -1,10 +1,11 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* GPIO common functionality for Chrome EC */ +#include "builtin/assert.h" #include "common.h" #include "gpio.h" #include "ioexpander.h" @@ -34,11 +35,11 @@ struct gpio_alt_func { * Construct the gpio_alt_funcs array. This array is used by gpio_config_module * to enable and disable GPIO alternate functions on a module by module basis. */ -#define ALTERNATE(pinmask, function, module, flagz) \ - {GPIO_##pinmask, .func = (function), .module_id = (module), \ - .flags = (flagz)}, +#define ALTERNATE(pinmask, function, module, flagz) \ + { GPIO_##pinmask, .func = (function), .module_id = (module), \ + .flags = (flagz) }, -static const struct gpio_alt_func gpio_alt_funcs[] = { +static __const_data const struct gpio_alt_func gpio_alt_funcs[] = { #include "gpio.wrap" }; @@ -74,9 +75,9 @@ static int gpio_config_pins(enum module_id id, uint32_t port, uint32_t pin_mask, gpio_set_flags_by_mask( af->port, (af->mask & pin_mask), enable ? af->flags : GPIO_INPUT); - gpio_set_alternate_function(af->port, - (af->mask & pin_mask), - enable ? af->func : GPIO_ALT_FUNC_NONE); + gpio_set_alternate_function( + af->port, (af->mask & pin_mask), + enable ? af->func : GPIO_ALT_FUNC_NONE); rv = EC_SUCCESS; /* We're done here if we were just setting one port. */ if (port != GPIO_CONFIG_ALL_PORTS) @@ -109,14 +110,15 @@ void gpio_set_flags(enum gpio_signal signal, int flags) gpio_set_flags_by_mask(g->port, g->mask, flags); } -#ifdef CONFIG_GPIO_GET_EXTENDED int gpio_get_flags(enum gpio_signal signal) { const struct gpio_info *g = gpio_list + signal; - return gpio_get_flags_by_mask(g->port, g->mask); + if (IS_ENABLED(CONFIG_GPIO_GET_EXTENDED)) + return gpio_get_flags_by_mask(g->port, g->mask); + else + return gpio_get_default_flags(signal); } -#endif int gpio_get_default_flags(enum gpio_signal signal) { @@ -127,8 +129,8 @@ void gpio_reset(enum gpio_signal signal) { const struct gpio_info *g = gpio_list + signal; - gpio_set_flags_by_mask(g->port, g->mask, g->flags); gpio_set_alternate_function(g->port, g->mask, GPIO_ALT_FUNC_NONE); + gpio_set_flags_by_mask(g->port, g->mask, g->flags); } const char *gpio_get_name(enum gpio_signal signal) @@ -222,8 +224,8 @@ int gpio_or_ioex_get_level(int signal, int *value) int signal_is_gpio(int signal) { - return ((signal >= GPIO_SIGNAL_START) - && (signal < GPIO_SIGNAL_START + GPIO_COUNT)); + return ((signal >= GPIO_SIGNAL_START) && + (signal < GPIO_SIGNAL_START + GPIO_COUNT)); } __attribute__((weak)) void gpio_set_wakepin(enum gpio_signal signal, diff --git a/common/gpio_commands.c b/common/gpio_commands.c index 967d051f6c..4a7be22741 100644 --- a/common/gpio_commands.c +++ b/common/gpio_commands.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -67,7 +67,7 @@ static enum ec_error_list set(const char *name, int value) if (!gpio_is_implemented(signal)) return EC_ERROR_INVAL; - if (!(gpio_get_default_flags(signal) & GPIO_OUTPUT)) + if (!(gpio_get_flags(signal) & GPIO_OUTPUT)) return EC_ERROR_INVAL; gpio_set_level(signal, value); @@ -78,45 +78,45 @@ static enum ec_error_list set(const char *name, int value) /* Console commands */ struct gpio_flag_description { - const int bitfield; - const char* name; + const int bitfield; + const char *name; }; -const struct gpio_flag_description gpio_descriptions[] = { - {GPIO_INPUT, "I"}, - {GPIO_OUTPUT, "O"}, - {GPIO_LOW, "L"}, - {GPIO_HIGH, "H"}, - {GPIO_ANALOG, "A"}, - {GPIO_OPEN_DRAIN, "ODR"}, - {GPIO_PULL_UP, "PU"}, - {GPIO_PULL_DOWN, "PD"}, - {GPIO_ALTERNATE, "ALT"}, - {GPIO_SEL_1P8V, "1P8"}, - {GPIO_LOCKED, "LCK"} +__maybe_unused static const struct gpio_flag_description gpio_descriptions[] = { + { GPIO_INPUT, "I" }, { GPIO_OUTPUT, "O" }, + { GPIO_LOW, "L" }, { GPIO_HIGH, "H" }, + { GPIO_OPEN_DRAIN, "ODR" }, { GPIO_PULL_UP, "PU" }, + { GPIO_PULL_DOWN, "PD" }, +#ifdef GPIO_SEL_1P8V + { GPIO_SEL_1P8V, "1P8" }, +#endif +#ifndef CONFIG_ZEPHYR + { GPIO_ANALOG, "A" }, { GPIO_ALTERNATE, "ALT" }, + { GPIO_LOCKED, "LCK" } +#endif }; static void print_gpio_info(int gpio) { - int changed, v, flags, i; + int changed, v, i; if (!gpio_is_implemented(gpio)) - return; /* Skip unsupported signals */ + return; /* Skip unsupported signals */ v = gpio_get_level(gpio); -#ifdef CONFIG_CMD_GPIO_EXTENDED - flags = gpio_get_flags(gpio); -#else - flags = 0; -#endif changed = last_val_changed(gpio, v); - /* Split the printf call into multiple calls to reduce the stack usage. */ + /* Split the printf call into multiple calls to reduce the stack usage. + */ ccprintf(" %d%c ", v, (changed ? '*' : ' ')); - for (i = 0; i < ARRAY_SIZE(gpio_descriptions); i++) { - if (flags & gpio_descriptions[i].bitfield) - ccprintf("%s ", gpio_descriptions[i].name); + if (IS_ENABLED(CONFIG_CMD_GPIO_EXTENDED)) { + int flags = gpio_get_flags(gpio); + + for (i = 0; i < ARRAY_SIZE(gpio_descriptions); i++) { + if (flags & gpio_descriptions[i].bitfield) + ccprintf("%s ", gpio_descriptions[i].name); + } } ccprintf("%s\n", gpio_get_name(gpio)); @@ -125,7 +125,7 @@ static void print_gpio_info(int gpio) cflush(); } -static int command_gpio_get(int argc, char **argv) +static int command_gpio_get(int argc, const char **argv) { int i; @@ -142,24 +142,22 @@ static int command_gpio_get(int argc, char **argv) /* Otherwise print them all */ for (i = 0; i < GPIO_COUNT; i++) { if (!gpio_is_implemented(i)) - continue; /* Skip unsupported signals */ + continue; /* Skip unsupported signals */ print_gpio_info(i); } return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(gpioget, command_gpio_get, - "[name]", +DECLARE_SAFE_CONSOLE_COMMAND(gpioget, command_gpio_get, "[name]", "Read GPIO value(s)"); -static int command_gpio_set(int argc, char **argv) +static int command_gpio_set(int argc, const char **argv) { #ifdef CONFIG_CMD_GPIO_EXTENDED int gpio; int flags = 0; int af = -1; - char *e; if (argc < 3) return EC_ERROR_PARAM_COUNT; @@ -174,16 +172,20 @@ static int command_gpio_set(int argc, char **argv) flags = GPIO_OUT_HIGH; else if (strcasecmp(argv[2], "0") == 0) flags = GPIO_OUT_LOW; +#ifndef CONFIG_ZEPHYR else if (strcasecmp(argv[2], "A") == 0) flags = GPIO_ANALOG; else if (strcasecmp(argv[2], "ALT") == 0) { + char *e; if (argc >= 4) { af = strtoi(argv[3], &e, 0); if (*e || af < 0 || af > 5) return EC_ERROR_PARAM2; } flags = GPIO_ALTERNATE; - } else + } +#endif + else return EC_ERROR_PARAM2; /* Update alt function if requested. */ @@ -216,9 +218,7 @@ DECLARE_CONSOLE_COMMAND_FLAGS(gpioset, command_gpio_set, #else "name <0 | 1>", #endif - "Set a GPIO", - CMD_FLAG_RESTRICTED -); + "Set a GPIO", CMD_FLAG_RESTRICTED); /*****************************************************************************/ /* Host commands */ @@ -261,7 +261,7 @@ static enum ec_status gpio_command_get(struct host_cmd_handler_args *args) i = p_v1->get_info.index; len = strlen(gpio_get_name(i)); - memcpy(r_v1->get_info.name, gpio_get_name(i), len+1); + memcpy(r_v1->get_info.name, gpio_get_name(i), len + 1); r_v1->get_info.val = gpio_get_level(i); r_v1->get_info.flags = gpio_get_default_flags(i); args->response_size = sizeof(r_v1->get_info); @@ -271,7 +271,6 @@ static enum ec_status gpio_command_get(struct host_cmd_handler_args *args) } return EC_RES_SUCCESS; - } DECLARE_HOST_COMMAND(EC_CMD_GPIO_GET, gpio_command_get, EC_VER_MASK(0) | EC_VER_MASK(1)); diff --git a/common/gyro_cal.c b/common/gyro_cal.c index 572e401b18..e2cb8d55db 100644 --- a/common/gyro_cal.c +++ b/common/gyro_cal.c @@ -1,10 +1,11 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "gyro_cal.h" #include "string.h" + #include /* diff --git a/common/gyro_still_det.c b/common/gyro_still_det.c index 4574e22e5f..303b73b15f 100644 --- a/common/gyro_still_det.c +++ b/common/gyro_still_det.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/common/hooks.c b/common/hooks.c index 4c2a4e48c6..88a6b93b93 100644 --- a/common/hooks.c +++ b/common/hooks.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,7 +14,7 @@ #ifdef CONFIG_HOOK_DEBUG #define CPUTS(outstr) cputs(CC_HOOK, outstr) -#define CPRINTS(format, args...) cprints(CC_HOOK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_HOOK, format, ##args) #else #define CPUTS(outstr) #define CPRINTS(format, args...) @@ -32,40 +32,44 @@ struct hook_ptrs { * order as enum hook_type. */ static const struct hook_ptrs hook_list[] = { - {__hooks_init, __hooks_init_end}, - {__hooks_pre_freq_change, __hooks_pre_freq_change_end}, - {__hooks_freq_change, __hooks_freq_change_end}, - {__hooks_sysjump, __hooks_sysjump_end}, - {__hooks_chipset_pre_init, __hooks_chipset_pre_init_end}, - {__hooks_chipset_startup, __hooks_chipset_startup_end}, - {__hooks_chipset_resume, __hooks_chipset_resume_end}, - {__hooks_chipset_suspend, __hooks_chipset_suspend_end}, + { __hooks_init, __hooks_init_end }, + { __hooks_pre_freq_change, __hooks_pre_freq_change_end }, + { __hooks_freq_change, __hooks_freq_change_end }, + { __hooks_sysjump, __hooks_sysjump_end }, + { __hooks_chipset_pre_init, __hooks_chipset_pre_init_end }, + { __hooks_chipset_startup, __hooks_chipset_startup_end }, + { __hooks_chipset_resume, __hooks_chipset_resume_end }, + { __hooks_chipset_suspend, __hooks_chipset_suspend_end }, #ifdef CONFIG_CHIPSET_RESUME_INIT_HOOK - {__hooks_chipset_resume_init, __hooks_chipset_resume_init_end}, - {__hooks_chipset_suspend_complete, - __hooks_chipset_suspend_complete_end}, + { __hooks_chipset_resume_init, __hooks_chipset_resume_init_end }, + { __hooks_chipset_suspend_complete, + __hooks_chipset_suspend_complete_end }, #endif - {__hooks_chipset_shutdown, __hooks_chipset_shutdown_end}, - {__hooks_chipset_shutdown_complete, - __hooks_chipset_shutdown_complete_end}, - {__hooks_chipset_reset, __hooks_chipset_reset_end}, - {__hooks_ac_change, __hooks_ac_change_end}, - {__hooks_lid_change, __hooks_lid_change_end}, - {__hooks_tablet_mode_change, __hooks_tablet_mode_change_end}, - {__hooks_base_attached_change, __hooks_base_attached_change_end}, - {__hooks_pwrbtn_change, __hooks_pwrbtn_change_end}, - {__hooks_battery_soc_change, __hooks_battery_soc_change_end}, + { __hooks_chipset_shutdown, __hooks_chipset_shutdown_end }, + { __hooks_chipset_shutdown_complete, + __hooks_chipset_shutdown_complete_end }, + { __hooks_chipset_hard_off, __hooks_chipset_hard_off_end }, + { __hooks_chipset_reset, __hooks_chipset_reset_end }, + { __hooks_ac_change, __hooks_ac_change_end }, + { __hooks_lid_change, __hooks_lid_change_end }, + { __hooks_tablet_mode_change, __hooks_tablet_mode_change_end }, +#ifdef CONFIG_BODY_DETECTION + { __hooks_body_detect_change, __hooks_body_detect_change_end }, +#endif + { __hooks_base_attached_change, __hooks_base_attached_change_end }, + { __hooks_pwrbtn_change, __hooks_pwrbtn_change_end }, + { __hooks_battery_soc_change, __hooks_battery_soc_change_end }, #ifdef CONFIG_USB_SUSPEND - {__hooks_usb_change, __hooks_usb_change_end}, + { __hooks_usb_change, __hooks_usb_change_end }, #endif - {__hooks_tick, __hooks_tick_end}, - {__hooks_second, __hooks_second_end}, - {__hooks_usb_pd_disconnect, __hooks_usb_pd_disconnect_end}, - {__hooks_usb_pd_connect, __hooks_usb_pd_connect_end}, + { __hooks_tick, __hooks_tick_end }, + { __hooks_second, __hooks_second_end }, + { __hooks_usb_pd_disconnect, __hooks_usb_pd_disconnect_end }, + { __hooks_usb_pd_connect, __hooks_usb_pd_connect_end }, + { __hooks_power_supply_change, __hooks_power_supply_change_end }, }; /* Times for deferrable functions */ -static int defer_new_call; static int hook_task_started; #ifdef CONFIG_HOOK_DEBUG @@ -149,7 +153,7 @@ int hook_call_deferred(const struct deferred_data *data, int us) int i = data - __deferred_funcs; if (data < __deferred_funcs || data >= __deferred_funcs_end) - return EC_ERROR_INVAL; /* Routine not registered */ + return EC_ERROR_INVAL; /* Routine not registered */ if (us == -1) { /* Cancel */ @@ -157,12 +161,6 @@ int hook_call_deferred(const struct deferred_data *data, int us) } else { /* Set alarm */ __deferred_until[i] = get_time().val + us; - /* - * Flag that hook_call_deferred() has been called. If the hook - * task is already active, this will allow it to go through the - * loop one more time before sleeping. - */ - defer_new_call = 1; /* Wake task so it can re-sleep for the proper time */ if (hook_task_started) @@ -191,20 +189,24 @@ void hook_task(void *u) int next = 0; int i; + interrupt_disable(); /* Handle deferred routines */ for (i = 0; i < DEFERRED_FUNCS_COUNT; i++) { if (__deferred_until[i] && __deferred_until[i] < t) { - CPRINTS("hook call deferred 0x%pP", - __deferred_funcs[i].routine); /* * Call deferred function. Clear timer first, * so it can request itself be called later. */ __deferred_until[i] = 0; + interrupt_enable(); + CPRINTS("hook call deferred 0x%p", + __deferred_funcs[i].routine); __deferred_funcs[i].routine(); + interrupt_disable(); } } + interrupt_enable(); if (t - last_tick >= HOOK_TICK_INTERVAL) { #ifdef CONFIG_HOOK_DEBUG record_hook_delay(t, last_tick, HOOK_TICK_INTERVAL, @@ -230,9 +232,7 @@ void hook_task(void *u) if (last_tick + HOOK_TICK_INTERVAL > t) next = last_tick + HOOK_TICK_INTERVAL - t; - /* Wake earlier if needed by a deferred routine */ - defer_new_call = 0; - + interrupt_disable(); for (i = 0; i < DEFERRED_FUNCS_COUNT && next > 0; i++) { if (!__deferred_until[i]) continue; @@ -243,12 +243,13 @@ void hook_task(void *u) next = __deferred_until[i] - t; } + interrupt_enable(); + /* - * If nothing is immediately pending, and hook_call_deferred() - * hasn't been called since we started calculating next, sleep - * until the next event. + * If nothing is immediately pending, sleep until the next + * event. */ - if (next > 0 && !defer_new_call) + if (next > 0) task_wait_event(next); } } @@ -267,7 +268,7 @@ static void print_hook_delay(uint32_t interval, uint32_t delay, uint32_t avg) ccprintf(" Average: %7d us (%d%%)\n\n", avg, percent_avg); } -static int command_stats(int argc, char **argv) +static int command_stats(int argc, const char **argv) { int i; @@ -286,7 +287,5 @@ static int command_stats(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(hookstats, command_stats, - NULL, - "Print stats of hooks"); +DECLARE_CONSOLE_COMMAND(hookstats, command_stats, NULL, "Print stats of hooks"); #endif diff --git a/common/host_command.c b/common/host_command.c index c7fd1baa15..37715b793f 100644 --- a/common/host_command.c +++ b/common/host_command.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,22 +6,26 @@ /* Host command module for Chrome EC */ #include "ap_hang_detect.h" +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "ec_commands.h" #include "host_command.h" #include "link_defs.h" #include "lpc.h" +#include "power.h" +#include "printf.h" #include "shared_mem.h" #include "system.h" +#include "system_safe_mode.h" #include "task.h" #include "timer.h" #include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_HOSTCMD, outstr) -#define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_HOSTCMD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_HOSTCMD, format, ##args) #define TASK_EVENT_CMD_PENDING TASK_EVENT_CUSTOM_BIT(0) @@ -42,18 +46,19 @@ static uint8_t host_memmap[EC_MEMMAP_SIZE] __aligned(4); #endif static enum { - HCDEBUG_OFF, /* No host command debug output */ - HCDEBUG_NORMAL, /* Normal output mode; skips repeated commands */ - HCDEBUG_EVERY, /* Print every command */ - HCDEBUG_PARAMS, /* ... and print params for request/response */ + HCDEBUG_OFF, /* No host command debug output */ + HCDEBUG_NORMAL, /* Normal output mode; skips repeated commands */ + HCDEBUG_EVERY, /* Print every command */ + HCDEBUG_PARAMS, /* ... and print params for request/response */ /* Number of host command debug modes */ HCDEBUG_MODES } hcdebug = CONFIG_HOSTCMD_DEBUG_MODE; #ifdef CONFIG_CMD_HCDEBUG -static const char * const hcdebug_mode_names[HCDEBUG_MODES] = { - "off", "normal", "every", "params"}; +static const char *const hcdebug_mode_names[HCDEBUG_MODES] = { "off", "normal", + "every", + "params" }; #endif #ifdef CONFIG_HOST_COMMAND_STATUS @@ -179,7 +184,7 @@ void host_command_received(struct host_cmd_handler_args *args) pending_args = args; /* Wake up the task to handle the command */ - task_set_event(TASK_ID_HOSTCMD, TASK_EVENT_CMD_PENDING, 0); + task_set_event(TASK_ID_HOSTCMD, TASK_EVENT_CMD_PENDING); return; } @@ -343,8 +348,8 @@ void host_packet_receive(struct host_packet *pkt) args0.version = r->command_version; args0.params_size = r->data_len; args0.response = (struct ec_host_response *)(pkt->response) + 1; - args0.response_max = pkt->response_max - - sizeof(struct ec_host_response); + args0.response_max = + pkt->response_max - sizeof(struct ec_host_response); args0.response_size = 0; args0.result = EC_RES_SUCCESS; @@ -370,38 +375,44 @@ void host_packet_receive(struct host_packet *pkt) */ static const struct host_command *find_host_command(int command) { -#ifdef CONFIG_HOSTCMD_SECTION_SORTED - const struct host_command *l, *r, *m; - uint32_t num; - -/* Use binary search to locate host command handler */ - l = __hcmds; - r = __hcmds_end - 1; - - while (1) { - if (l > r) + if (IS_ENABLED(CONFIG_SYSTEM_SAFE_MODE) && system_is_in_safe_mode()) { + if (!command_is_allowed_in_safe_mode(command)) return NULL; - - num = r - l; - m = l + (num / 2); - - if (m->command < command) - l = m + 1; - else if (m->command > command) - r = m - 1; - else - return m; } -#else - const struct host_command *cmd; + if (IS_ENABLED(CONFIG_ZEPHYR)) { + return zephyr_find_host_command(command); + } else if (IS_ENABLED(CONFIG_HOSTCMD_SECTION_SORTED)) { + const struct host_command *l, *r, *m; + uint32_t num; + + /* Use binary search to locate host command handler */ + l = __hcmds; + r = __hcmds_end - 1; + + while (1) { + if (l > r) + return NULL; + + num = r - l; + m = l + (num / 2); + + if (m->command < command) + l = m + 1; + else if (m->command > command) + r = m - 1; + else + return m; + } + } else { + const struct host_command *cmd; - for (cmd = __hcmds; cmd < __hcmds_end; cmd++) { - if (command == cmd->command) - return cmd; - } + for (cmd = __hcmds; cmd < __hcmds_end; cmd++) { + if (command == cmd->command) + return cmd; + } - return NULL; -#endif + return NULL; + } } static void host_command_init(void) @@ -438,7 +449,7 @@ void host_command_task(void *u) /* Process it */ if ((evt & TASK_EVENT_CMD_PENDING) && pending_args) { pending_args->result = - host_command_process(pending_args); + host_command_process(pending_args); host_send_response(pending_args); } @@ -471,8 +482,7 @@ host_command_proto_version(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PROTO_VERSION, - host_command_proto_version, +DECLARE_HOST_COMMAND(EC_CMD_PROTO_VERSION, host_command_proto_version, EC_VER_MASK(0)); static enum ec_status host_command_hello(struct host_cmd_handler_args *args) @@ -486,32 +496,7 @@ static enum ec_status host_command_hello(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HELLO, - host_command_hello, - EC_VER_MASK(0)); - -static enum ec_status host_command_read_test(struct host_cmd_handler_args *args) -{ - const struct ec_params_read_test *p = args->params; - struct ec_response_read_test *r = args->response; - - int offset = p->offset; - int size = p->size / sizeof(uint32_t); - int i; - - if (size > ARRAY_SIZE(r->data) || p->size > args->response_size) - return EC_RES_ERROR; - - for (i = 0; i < size; i++) - r->data[i] = offset + i; - - args->response_size = size * sizeof(uint32_t); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_READ_TEST, - host_command_read_test, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_HELLO, host_command_hello, EC_VER_MASK(0)); #ifndef CONFIG_HOSTCMD_X86 /* @@ -541,8 +526,7 @@ host_command_read_memmap(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_READ_MEMMAP, - host_command_read_memmap, +DECLARE_HOST_COMMAND(EC_CMD_READ_MEMMAP, host_command_read_memmap, EC_VER_MASK(0)); #endif @@ -553,9 +537,9 @@ host_command_get_cmd_versions(struct host_cmd_handler_args *args) const struct ec_params_get_cmd_versions_v1 *p_v1 = args->params; struct ec_response_get_cmd_versions *r = args->response; - const struct host_command *cmd = - (args->version == 1) ? find_host_command(p_v1->cmd) : - find_host_command(p->cmd); + const struct host_command *cmd = (args->version == 1) ? + find_host_command(p_v1->cmd) : + find_host_command(p->cmd); if (!cmd) return EC_RES_INVALID_PARAM; @@ -566,8 +550,7 @@ host_command_get_cmd_versions(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_CMD_VERSIONS, - host_command_get_cmd_versions, +DECLARE_HOST_COMMAND(EC_CMD_GET_CMD_VERSIONS, host_command_get_cmd_versions, EC_VER_MASK(0) | EC_VER_MASK(1)); static int host_command_is_suppressed(uint16_t cmd) @@ -592,11 +575,13 @@ static void dump_host_command_suppressed(int force) { #ifdef CONFIG_SUPPRESSED_HOST_COMMANDS int i; + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; if (!force && !timestamp_expired(suppressed_cmd_deadline, NULL)) return; - CPRINTF("[%pT HC Suppressed:", PRINTF_TIMESTAMP_NOW); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + CPRINTF("[%s HC Suppressed:", ts_str); for (i = 0; i < ARRAY_SIZE(hc_suppressed_cmd); i++) { CPRINTF(" 0x%x=%d", hc_suppressed_cmd[i], hc_suppressed_cnt[i]); hc_suppressed_cnt[i] = 0; @@ -612,10 +597,9 @@ static void dump_host_command_suppressed_(void) { dump_host_command_suppressed(1); } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - dump_host_command_suppressed_, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_SYSJUMP, - dump_host_command_suppressed_, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, dump_host_command_suppressed_, + HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_SYSJUMP, dump_host_command_suppressed_, HOOK_PRIO_DEFAULT); #else } #endif /* CONFIG_SUPPRESSED_HOST_COMMANDS */ @@ -657,12 +641,15 @@ static void host_command_debug_request(struct host_cmd_handler_args *args) hc_prev_cmd = args->command; } - if (hcdebug >= HCDEBUG_PARAMS && args->params_size) - CPRINTS("HC 0x%02x.%d:%ph", args->command, - args->version, - HEX_BUF(args->params, args->params_size)); - else - CPRINTS("HC 0x%02x", args->command); + if (hcdebug >= HCDEBUG_PARAMS && args->params_size) { + char str_buf[hex_str_buf_size(args->params_size)]; + + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(args->params, args->params_size)); + CPRINTS("HC 0x%04x.%d:%s", args->command, args->version, + str_buf); + } else + CPRINTS("HC 0x%04x", args->command); } uint16_t host_command_process(struct host_cmd_handler_args *args) @@ -691,9 +678,9 @@ uint16_t host_command_process(struct host_cmd_handler_args *args) if (args->command >= EC_CMD_PASSTHRU_OFFSET(1) && args->command <= EC_CMD_PASSTHRU_MAX(1)) { rv = pd_host_command(args->command - EC_CMD_PASSTHRU_OFFSET(1), - args->version, - args->params, args->params_size, - args->response, args->response_max); + args->version, args->params, + args->params_size, args->response, + args->response_max); if (rv >= 0) { /* Success; store actual response size */ args->response_size = rv; @@ -715,11 +702,16 @@ uint16_t host_command_process(struct host_cmd_handler_args *args) } if (rv != EC_RES_SUCCESS) - CPRINTS("HC 0x%02x err %d", args->command, rv); + CPRINTS("HC 0x%04x err %d", args->command, rv); + + if (hcdebug >= HCDEBUG_PARAMS && args->response_size) { + char str_buf[hex_str_buf_size(args->response_size)]; - if (hcdebug >= HCDEBUG_PARAMS && args->response_size) - CPRINTS("HC resp:%ph", - HEX_BUF(args->response, args->response_size)); + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(args->response, + args->response_size)); + CPRINTS("HC resp:%s", str_buf); + } return rv; } @@ -737,8 +729,7 @@ host_command_get_comms_status(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_COMMS_STATUS, - host_command_get_comms_status, +DECLARE_HOST_COMMAND(EC_CMD_GET_COMMS_STATUS, host_command_get_comms_status, EC_VER_MASK(0)); /* Resend the last saved response */ @@ -754,8 +745,7 @@ host_command_resend_response(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RESEND_RESPONSE, - host_command_resend_response, +DECLARE_HOST_COMMAND(EC_CMD_RESEND_RESPONSE, host_command_resend_response, EC_VER_MASK(0)); #endif /* CONFIG_HOST_COMMAND_STATUS */ @@ -773,8 +763,7 @@ host_command_test_protocol(struct host_cmd_handler_args *args) return p->ec_result; } -DECLARE_HOST_COMMAND(EC_CMD_TEST_PROTOCOL, - host_command_test_protocol, +DECLARE_HOST_COMMAND(EC_CMD_TEST_PROTOCOL, host_command_test_protocol, EC_VER_MASK(0)); /* Returns supported features. */ @@ -789,16 +778,14 @@ host_command_get_features(struct host_cmd_handler_args *args) r->flags[1] = get_feature_flags1(); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_FEATURES, - host_command_get_features, +DECLARE_HOST_COMMAND(EC_CMD_GET_FEATURES, host_command_get_features, EC_VER_MASK(0)); - /*****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_HOSTCMD -static int parse_byte(char *b, uint8_t *out) +static int parse_byte(const char *b, uint8_t *out) { int i; *out = 0; @@ -817,7 +804,7 @@ static int parse_byte(char *b, uint8_t *out) return EC_SUCCESS; } -static int parse_params(char *s, uint8_t *params) +static int parse_params(const char *s, uint8_t *params) { int len = 0; @@ -831,7 +818,7 @@ static int parse_params(char *s, uint8_t *params) return len; } -static int command_host_command(int argc, char **argv) +static int command_host_command(int argc, const char **argv) { struct host_cmd_handler_args args; char *cmd_params; @@ -886,23 +873,27 @@ static int command_host_command(int argc, char **argv) if (res != EC_RES_SUCCESS) ccprintf("Command returned %d\n", res); - else if (args.response_size) - ccprintf("Response: %ph\n", - HEX_BUF(cmd_params, args.response_size)); - else + else if (args.response_size) { + char str_buf[hex_str_buf_size(args.response_size)]; + + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(cmd_params, args.response_size)); + ccprintf("Response: %s\n", str_buf); + } else ccprintf("Command succeeded; no response.\n"); shared_mem_release(cmd_params); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(hostcmd, command_host_command, - "cmd ver param", +DECLARE_CONSOLE_COMMAND(hostcmd, command_host_command, "cmd ver param", "Fake host command"); #endif /* CONFIG_CMD_HOSTCMD */ #ifdef CONFIG_CMD_HCDEBUG -static int command_hcdebug(int argc, char **argv) +static int command_hcdebug(int argc, const char **argv) { + if (argc >= 3) + return EC_ERROR_PARAM_COUNT; if (argc > 1) { int i; @@ -926,3 +917,24 @@ DECLARE_CONSOLE_COMMAND(hcdebug, command_hcdebug, "hcdebug [off | normal | every | params]", "Set host command debug output mode"); #endif /* CONFIG_CMD_HCDEBUG */ + +#if defined(CONFIG_AP_PWRSEQ_S0IX_COUNTER) || \ + defined(CONFIG_POWERSEQ_S0IX_COUNTER) +static enum ec_status +host_command_get_s0ix_cnt(struct host_cmd_handler_args *args) +{ + const struct ec_params_s0ix_cnt *p = args->params; + struct ec_response_s0ix_cnt *r = args->response; + + if (p->flags & EC_S0IX_COUNTER_RESET) { + atomic_clear(&s0ix_counter); + } + + r->s0ix_counter = atomic_get(&s0ix_counter); + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_GET_S0IX_COUNTER, host_command_get_s0ix_cnt, + EC_VER_MASK(0)); +#endif diff --git a/common/host_command_controller.c b/common/host_command_controller.c new file mode 100644 index 0000000000..83d4ce0c86 --- /dev/null +++ b/common/host_command_controller.c @@ -0,0 +1,222 @@ +/* Copyright 2014 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Host command controller module for Chrome EC */ + +#include "common.h" +#include "console.h" +#include "host_command.h" +#include "i2c.h" +#include "task.h" +#include "timer.h" +#include "usb_pd.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_HOSTCMD, outstr) +#define CPRINTS(format, args...) cprints(CC_HOSTCMD, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ##args) + +/* Number of attempts for each PD host command */ +#define PD_HOST_COMMAND_ATTEMPTS 3 + +static struct mutex pd_mutex; + +/** + * Non-task-safe internal version of pd_host_command(). + * + * Do not call this version directly! Use pd_host_command(). + */ +static int pd_host_command_internal(int command, int version, + const void *outdata, int outsize, + void *indata, int insize) +{ + int ret, i; + int resp_len; + struct ec_host_request rq; + struct ec_host_response rs; + static uint8_t req_buf[EC_LPC_HOST_PACKET_SIZE]; + static uint8_t resp_buf[EC_LPC_HOST_PACKET_SIZE]; + uint8_t sum = 0; + const uint8_t *c; + uint8_t *d; + + /* Fail if output size is too big */ + if (outsize + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) + return -EC_RES_REQUEST_TRUNCATED; + + /* Fill in request packet */ + rq.struct_version = EC_HOST_REQUEST_VERSION; + rq.checksum = 0; + rq.command = command; + rq.command_version = version; + rq.reserved = 0; + rq.data_len = outsize; + + /* Copy data and start checksum */ + for (i = 0, c = (const uint8_t *)outdata; i < outsize; i++, c++) { + req_buf[sizeof(rq) + 1 + i] = *c; + sum += *c; + } + + /* Finish checksum */ + for (i = 0, c = (const uint8_t *)&rq; i < sizeof(rq); i++, c++) + sum += *c; + + /* Write checksum field so the entire packet sums to 0 */ + rq.checksum = (uint8_t)(-sum); + + /* Copy header */ + for (i = 0, c = (const uint8_t *)&rq; i < sizeof(rq); i++, c++) + req_buf[1 + i] = *c; + + /* Set command to use protocol v3 */ + req_buf[0] = EC_COMMAND_PROTOCOL_3; + + /* + * Transmit all data and receive 2 bytes for return value and response + * length. + */ + i2c_lock(I2C_PORT_PD_MCU, 1); + i2c_set_timeout(I2C_PORT_PD_MCU, PD_HOST_COMMAND_TIMEOUT_US); + ret = i2c_xfer_unlocked(I2C_PORT_PD_MCU, CONFIG_USB_PD_I2C_ADDR_FLAGS, + &req_buf[0], outsize + sizeof(rq) + 1, + &resp_buf[0], 2, I2C_XFER_START); + i2c_set_timeout(I2C_PORT_PD_MCU, 0); + if (ret) { + i2c_lock(I2C_PORT_PD_MCU, 0); + CPRINTS("i2c transaction 1 failed: %d", ret); + return -EC_RES_BUS_ERROR; + } + + resp_len = resp_buf[1]; + + if (resp_len > (insize + sizeof(rs))) { + /* Do a read to generate stop condition */ + i2c_xfer_unlocked(I2C_PORT_PD_MCU, CONFIG_USB_PD_I2C_ADDR_FLAGS, + 0, 0, &resp_buf[2], 1, I2C_XFER_STOP); + i2c_lock(I2C_PORT_PD_MCU, 0); + CPRINTS("response size is too large %d > %d", resp_len, + insize + sizeof(rs)); + return -EC_RES_RESPONSE_TOO_BIG; + } + + /* Receive remaining data */ + ret = i2c_xfer_unlocked(I2C_PORT_PD_MCU, CONFIG_USB_PD_I2C_ADDR_FLAGS, + 0, 0, &resp_buf[2], resp_len, I2C_XFER_STOP); + i2c_lock(I2C_PORT_PD_MCU, 0); + if (ret) { + CPRINTS("i2c transaction 2 failed: %d", ret); + return -EC_RES_BUS_ERROR; + } + + /* Check for host command error code */ + ret = resp_buf[0]; + if (ret) { + CPRINTS("command 0x%04x returned error %d", command, ret); + return -ret; + } + + /* Read back response header and start checksum */ + sum = 0; + for (i = 0, d = (uint8_t *)&rs; i < sizeof(rs); i++, d++) { + *d = resp_buf[i + 2]; + sum += *d; + } + + if (rs.struct_version != EC_HOST_RESPONSE_VERSION) { + CPRINTS("PD response version mismatch"); + return -EC_RES_INVALID_RESPONSE; + } + + if (rs.reserved) { + CPRINTS("PD response reserved != 0"); + return -EC_RES_INVALID_RESPONSE; + } + + if (rs.data_len > insize) { + CPRINTS("PD returned too much data"); + return -EC_RES_RESPONSE_TOO_BIG; + } + + /* Read back data and update checksum */ + resp_len -= sizeof(rs); + for (i = 0, d = (uint8_t *)indata; i < resp_len; i++, d++) { + *d = resp_buf[sizeof(rs) + i + 2]; + sum += *d; + } + + if ((uint8_t)sum) { + CPRINTS("command 0x%04x bad checksum returned: %d", command, + sum); + return -EC_RES_INVALID_CHECKSUM; + } + + /* Return output buffer size */ + return resp_len; +} + +int pd_host_command(int command, int version, const void *outdata, int outsize, + void *indata, int insize) +{ + int rv; + int tries = 0; + + /* Try multiple times to send host command. */ + for (tries = 0; tries < PD_HOST_COMMAND_ATTEMPTS; tries++) { + /* Acquire mutex */ + mutex_lock(&pd_mutex); + /* Call internal version of host command */ + rv = pd_host_command_internal(command, version, outdata, + outsize, indata, insize); + /* Release mutex */ + mutex_unlock(&pd_mutex); + + /* If host command error due to i2c bus error, try again. */ + if (rv != -EC_RES_BUS_ERROR) + break; + task_wait_event(50 * MSEC); + } + + return rv; +} + +static int command_pd_mcu(int argc, const char **argv) +{ + char *e; + static char outbuf[128]; + static char inbuf[128]; + int command, version; + int i, ret, tmp; + + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + + command = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM1; + + version = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + for (i = 3; i < argc; i++) { + tmp = strtoi(argv[i], &e, 0); + if (*e) + return EC_ERROR_PARAM3; + outbuf[i - 3] = tmp; + } + + ret = pd_host_command(command, version, &outbuf, argc - 3, &inbuf, + sizeof(inbuf)); + + ccprintf("Host command 0x%02x, returned %d\n", command, ret); + for (i = 0; i < ret; i++) + ccprintf("0x%02x\n", inbuf[i]); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(pdcmd, command_pd_mcu, "cmd ver [params]", + "Send PD host command"); diff --git a/common/host_command_master.c b/common/host_command_master.c deleted file mode 100644 index d51c8cdc15..0000000000 --- a/common/host_command_master.c +++ /dev/null @@ -1,230 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Host command master module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "host_command.h" -#include "i2c.h" -#include "task.h" -#include "timer.h" -#include "usb_pd.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_HOSTCMD, outstr) -#define CPRINTS(format, args...) cprints(CC_HOSTCMD, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ## args) - -/* Number of attempts for each PD host command */ -#define PD_HOST_COMMAND_ATTEMPTS 3 - -static struct mutex pd_mutex; - -/** - * Non-task-safe internal version of pd_host_command(). - * - * Do not call this version directly! Use pd_host_command(). - */ -static int pd_host_command_internal(int command, int version, - const void *outdata, int outsize, - void *indata, int insize) -{ - int ret, i; - int resp_len; - struct ec_host_request rq; - struct ec_host_response rs; - static uint8_t req_buf[EC_LPC_HOST_PACKET_SIZE]; - static uint8_t resp_buf[EC_LPC_HOST_PACKET_SIZE]; - uint8_t sum = 0; - const uint8_t *c; - uint8_t *d; - - /* Fail if output size is too big */ - if (outsize + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) - return -EC_RES_REQUEST_TRUNCATED; - - /* Fill in request packet */ - rq.struct_version = EC_HOST_REQUEST_VERSION; - rq.checksum = 0; - rq.command = command; - rq.command_version = version; - rq.reserved = 0; - rq.data_len = outsize; - - /* Copy data and start checksum */ - for (i = 0, c = (const uint8_t *)outdata; i < outsize; i++, c++) { - req_buf[sizeof(rq) + 1 + i] = *c; - sum += *c; - } - - /* Finish checksum */ - for (i = 0, c = (const uint8_t *)&rq; i < sizeof(rq); i++, c++) - sum += *c; - - /* Write checksum field so the entire packet sums to 0 */ - rq.checksum = (uint8_t)(-sum); - - /* Copy header */ - for (i = 0, c = (const uint8_t *)&rq; i < sizeof(rq); i++, c++) - req_buf[1 + i] = *c; - - /* Set command to use protocol v3 */ - req_buf[0] = EC_COMMAND_PROTOCOL_3; - - /* - * Transmit all data and receive 2 bytes for return value and response - * length. - */ - i2c_lock(I2C_PORT_PD_MCU, 1); - i2c_set_timeout(I2C_PORT_PD_MCU, PD_HOST_COMMAND_TIMEOUT_US); - ret = i2c_xfer_unlocked(I2C_PORT_PD_MCU, - CONFIG_USB_PD_I2C_SLAVE_ADDR_FLAGS, - &req_buf[0], outsize + sizeof(rq) + 1, - &resp_buf[0], 2, I2C_XFER_START); - i2c_set_timeout(I2C_PORT_PD_MCU, 0); - if (ret) { - i2c_lock(I2C_PORT_PD_MCU, 0); - CPRINTS("i2c transaction 1 failed: %d", ret); - return -EC_RES_BUS_ERROR; - } - - resp_len = resp_buf[1]; - - if (resp_len > (insize + sizeof(rs))) { - /* Do a read to generate stop condition */ - i2c_xfer_unlocked(I2C_PORT_PD_MCU, - CONFIG_USB_PD_I2C_SLAVE_ADDR_FLAGS, - 0, 0, &resp_buf[2], 1, I2C_XFER_STOP); - i2c_lock(I2C_PORT_PD_MCU, 0); - CPRINTS("response size is too large %d > %d", - resp_len, insize + sizeof(rs)); - return -EC_RES_RESPONSE_TOO_BIG; - } - - /* Receive remaining data */ - ret = i2c_xfer_unlocked(I2C_PORT_PD_MCU, - CONFIG_USB_PD_I2C_SLAVE_ADDR_FLAGS, - 0, 0, - &resp_buf[2], resp_len, I2C_XFER_STOP); - i2c_lock(I2C_PORT_PD_MCU, 0); - if (ret) { - CPRINTS("i2c transaction 2 failed: %d", ret); - return -EC_RES_BUS_ERROR; - } - - /* Check for host command error code */ - ret = resp_buf[0]; - if (ret) { - CPRINTS("command 0x%02x returned error %d", command, ret); - return -ret; - } - - /* Read back response header and start checksum */ - sum = 0; - for (i = 0, d = (uint8_t *)&rs; i < sizeof(rs); i++, d++) { - *d = resp_buf[i + 2]; - sum += *d; - } - - if (rs.struct_version != EC_HOST_RESPONSE_VERSION) { - CPRINTS("PD response version mismatch"); - return -EC_RES_INVALID_RESPONSE; - } - - if (rs.reserved) { - CPRINTS("PD response reserved != 0"); - return -EC_RES_INVALID_RESPONSE; - } - - if (rs.data_len > insize) { - CPRINTS("PD returned too much data"); - return -EC_RES_RESPONSE_TOO_BIG; - } - - /* Read back data and update checksum */ - resp_len -= sizeof(rs); - for (i = 0, d = (uint8_t *)indata; i < resp_len; i++, d++) { - *d = resp_buf[sizeof(rs) + i + 2]; - sum += *d; - } - - - if ((uint8_t)sum) { - CPRINTS("command 0x%02x bad checksum returned: %d", - command, sum); - return -EC_RES_INVALID_CHECKSUM; - } - - /* Return output buffer size */ - return resp_len; -} - -int pd_host_command(int command, int version, - const void *outdata, int outsize, - void *indata, int insize) -{ - int rv; - int tries = 0; - - /* Try multiple times to send host command. */ - for (tries = 0; tries < PD_HOST_COMMAND_ATTEMPTS; tries++) { - /* Acquire mutex */ - mutex_lock(&pd_mutex); - /* Call internal version of host command */ - rv = pd_host_command_internal(command, version, outdata, - outsize, indata, insize); - /* Release mutex */ - mutex_unlock(&pd_mutex); - - /* If host command error due to i2c bus error, try again. */ - if (rv != -EC_RES_BUS_ERROR) - break; - task_wait_event(50*MSEC); - } - - return rv; -} - -static int command_pd_mcu(int argc, char **argv) -{ - char *e; - static char __bss_slow outbuf[128]; - static char __bss_slow inbuf[128]; - int command, version; - int i, ret, tmp; - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - command = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - version = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - for (i = 3; i < argc; i++) { - tmp = strtoi(argv[i], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - outbuf[i-3] = tmp; - } - - ret = pd_host_command(command, version, &outbuf, argc - 3, &inbuf, - sizeof(inbuf)); - - ccprintf("Host command 0x%02x, returned %d\n", command, ret); - for (i = 0; i < ret; i++) - ccprintf("0x%02x\n", inbuf[i]); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(pdcmd, command_pd_mcu, - "cmd ver [params]", - "Send PD host command"); - diff --git a/common/host_command_memory_dump.c b/common/host_command_memory_dump.c new file mode 100644 index 0000000000..f8d06c5762 --- /dev/null +++ b/common/host_command_memory_dump.c @@ -0,0 +1,135 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "console.h" +#include "ec_commands.h" +#include "host_command.h" +#include "host_command_memory_dump.h" +#include "string.h" +#include "task.h" + +#define MAX_DUMP_ENTRIES 64 + +#ifndef CONFIG_ZEPHYR +/* TODO(b/271883902): Add memory dump command support for CrOS EC */ +#error "Memory Dump commands are only supported on Zephyr EC." +#endif + +struct memory_dump_entry { + uint32_t address; + uint32_t size; +}; + +static struct memory_dump_entry entries[MAX_DUMP_ENTRIES]; +static uint16_t memory_dump_entry_count; +K_MUTEX_DEFINE(memory_dump_mutex); + +int register_memory_dump(uint32_t address, uint32_t size) +{ + mutex_lock(&memory_dump_mutex); + + if (memory_dump_entry_count >= MAX_DUMP_ENTRIES) { + mutex_unlock(&memory_dump_mutex); + ccprintf("ERROR: Memory dump count exceeds max\n"); + return EC_ERROR_OVERFLOW; + } + + entries[memory_dump_entry_count].address = address; + entries[memory_dump_entry_count].size = size; + + memory_dump_entry_count += 1; + + mutex_unlock(&memory_dump_mutex); + + return EC_SUCCESS; +} + +int clear_memory_dump(void) +{ + mutex_lock(&memory_dump_mutex); + memset(entries, 0, sizeof(entries)); + memory_dump_entry_count = 0; + mutex_unlock(&memory_dump_mutex); + + return EC_SUCCESS; +} + +static enum ec_status +get_memory_dump_metadata(struct host_cmd_handler_args *args) +{ + struct ec_response_memory_dump_get_metadata *r = args->response; + + mutex_lock(&memory_dump_mutex); + + r->memory_dump_entry_count = memory_dump_entry_count; + r->memory_dump_total_size = 0; + for (int i = 0; i < memory_dump_entry_count; i++) { + r->memory_dump_total_size += entries[i].size; + } + + mutex_unlock(&memory_dump_mutex); + + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_MEMORY_DUMP_GET_METADATA, get_memory_dump_metadata, + EC_VER_MASK(0)); + +static enum ec_status +memory_dump_get_entry_info(struct host_cmd_handler_args *args) +{ + const struct ec_params_memory_dump_get_entry_info *p = args->params; + struct ec_response_memory_dump_get_entry_info *r = args->response; + + mutex_lock(&memory_dump_mutex); + + if (p->memory_dump_entry_index >= memory_dump_entry_count) { + return EC_RES_INVALID_PARAM; + } + + r->address = entries[p->memory_dump_entry_index].address; + r->size = entries[p->memory_dump_entry_index].size; + + mutex_unlock(&memory_dump_mutex); + + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_MEMORY_DUMP_GET_ENTRY_INFO, + memory_dump_get_entry_info, EC_VER_MASK(0)); + +static enum ec_status read_memory_dump(struct host_cmd_handler_args *args) +{ + const struct ec_params_memory_dump_read_memory *p = args->params; + void *r = args->response; + struct memory_dump_entry entry; + + mutex_lock(&memory_dump_mutex); + + if (p->memory_dump_entry_index >= memory_dump_entry_count) { + return EC_RES_INVALID_PARAM; + } + + entry = entries[p->memory_dump_entry_index]; + + if (p->address < entry.address || + p->address + p->size > entry.address + entry.size) { + return EC_RES_INVALID_PARAM; + } + + /* Must leave room for ec_host_response header */ + args->response_size = MIN( + p->size, args->response_max - sizeof(struct ec_host_response)); + + memcpy(r, (void *)p->address, args->response_size); + + mutex_unlock(&memory_dump_mutex); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_MEMORY_DUMP_READ_MEMORY, read_memory_dump, + EC_VER_MASK(0)); diff --git a/common/host_command_pd.c b/common/host_command_pd.c index 869cad4493..062113fb0e 100644 --- a/common/host_command_pd.c +++ b/common/host_command_pd.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,16 +14,16 @@ #include "panic.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_PD_HOST_CMD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_PD_HOST_CMD, format, ##args) -#define TASK_EVENT_EXCHANGE_PD_STATUS TASK_EVENT_CUSTOM_BIT(0) -#define TASK_EVENT_HIBERNATING TASK_EVENT_CUSTOM_BIT(1) +#define TASK_EVENT_EXCHANGE_PD_STATUS TASK_EVENT_CUSTOM_BIT(0) +#define TASK_EVENT_HIBERNATING TASK_EVENT_CUSTOM_BIT(1) /* Define local option for if we are a TCPM with an off chip TCPC */ #if defined(CONFIG_USB_POWER_DELIVERY) && !defined(CONFIG_USB_PD_TCPM_STUB) @@ -32,7 +32,7 @@ #ifdef CONFIG_HOSTCMD_PD_CHG_CTRL /* By default allow 5V charging only for the dead battery case */ -static enum pd_charge_state charge_state = PD_CHARGE_5V; +static enum pd_charge_state pd_chg_state = PD_CHARGE_5V; #define CHARGE_PORT_UNINITIALIZED -2 static int charge_port = CHARGE_PORT_UNINITIALIZED; @@ -48,20 +48,20 @@ void host_command_pd_send_status(enum pd_charge_state new_chg_state) #ifdef CONFIG_HOSTCMD_PD_CHG_CTRL /* Update PD MCU charge state if necessary */ if (new_chg_state != PD_CHARGE_NO_CHANGE) - charge_state = new_chg_state; + pd_chg_state = new_chg_state; #endif /* Wake PD HC task to send status */ - task_set_event(TASK_ID_PDCMD, TASK_EVENT_EXCHANGE_PD_STATUS, 0); + task_set_event(TASK_ID_PDCMD, TASK_EVENT_EXCHANGE_PD_STATUS); } void host_command_pd_request_hibernate(void) { - task_set_event(TASK_ID_PDCMD, TASK_EVENT_HIBERNATING, 0); + task_set_event(TASK_ID_PDCMD, TASK_EVENT_HIBERNATING); } #ifdef CONFIG_HOSTCMD_PD static int pd_send_host_command(struct ec_params_pd_status *ec_status, - struct ec_response_pd_status *pd_status) + struct ec_response_pd_status *pd_status) { return pd_host_command(EC_CMD_PD_EXCHANGE_STATUS, EC_VER_PD_EXCHANGE_STATUS, ec_status, @@ -74,7 +74,7 @@ static void pd_exchange_update_ec_status(struct ec_params_pd_status *ec_status, { /* Send PD charge state and battery state of charge */ #ifdef CONFIG_HOSTCMD_PD_CHG_CTRL - ec_status->charge_state = charge_state; + ec_status->charge_state = pd_chg_state; #endif if (charge_get_flags() & CHARGE_FLAG_BATT_RESPONSIVE) ec_status->batt_soc = charge_get_percent(); @@ -126,10 +126,7 @@ static void pd_check_chg_status(struct ec_response_pd_status *pd_status) #endif /* Set input current limit */ - rv = charge_set_input_current_limit(MAX(pd_status->curr_lim_ma, - CONFIG_CHARGER_INPUT_CURRENT), 0); - if (rv < 0) - CPRINTS("Failed to set input curr limit from PD MCU"); + board_set_charge_limit(pd_status->curr_lim_ma, 0); } #endif /* CONFIG_HOSTCMD_PD_CHG_CTRL */ #endif /* CONFIG_HOSTCMD_PD */ @@ -201,7 +198,7 @@ static void pd_exchange_status(uint32_t ec_state) if (!first_exchange) /* Delay to prevent task starvation */ - usleep(5*MSEC); + usleep(5 * MSEC); first_exchange = 0; } while (pd_get_alert()); #endif /* USB_TCPM_WITH_OFF_CHIP_TCPC */ @@ -226,4 +223,3 @@ void pd_command_task(void *u) pd_exchange_status(ec_state); } } - diff --git a/common/host_event_commands.c b/common/host_event_commands.c index 9ab7f19d04..a89c89382d 100644 --- a/common/host_event_commands.c +++ b/common/host_event_commands.c @@ -1,10 +1,11 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Host event commands for Chrome EC */ +#include "chipset.h" #include "common.h" #include "console.h" #include "hooks.h" @@ -18,13 +19,13 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_EVENTS, outstr) -#define CPRINTS(format, args...) cprints(CC_EVENTS, format, ## args) +#define CPRINTS(format, args...) cprints(CC_EVENTS, format, ##args) /* * This is used to avoid 64-bit shifts which might require a new library * function. */ -#define HOST_EVENT_32BIT_MASK(x) (1UL << ((x) - 1)) +#define HOST_EVENT_32BIT_MASK(x) (1UL << ((x)-1)) static void host_event_set_bit(host_event_t *ev, uint8_t bit) { uint32_t *ptr = (uint32_t *)ev; @@ -38,17 +39,19 @@ static void host_event_set_bit(host_event_t *ev, uint8_t bit) if (bit == 0) return; -#ifdef CONFIG_HOST_EVENT64 + /* + * The overall host event implementation assumes it's running on and + * communicating with little-endian architectures. + */ if (bit > 32) *(ptr + 1) = HOST_EVENT_32BIT_MASK(bit - 32); else -#endif *ptr = HOST_EVENT_32BIT_MASK(bit); } #ifdef CONFIG_HOSTCMD_X86 -#define LPC_SYSJUMP_TAG 0x4c50 /* "LP" */ +#define LPC_SYSJUMP_TAG 0x4c50 /* "LP" */ #define LPC_SYSJUMP_OLD_VERSION 1 #define LPC_SYSJUMP_VERSION 2 @@ -71,14 +74,14 @@ static void host_event_set_bit(host_event_t *ev, uint8_t bit) * - EC_HOST_EVENT_MKBP * */ -#define LPC_HOST_EVENT_ALWAYS_REPORT_DEFAULT_MASK \ - (EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_HANG_REBOOT) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_PANIC) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_FASTBOOT) | \ - EC_HOST_EVENT_MASK(EC_HOST_EVENT_MKBP) | \ +#define LPC_HOST_EVENT_ALWAYS_REPORT_DEFAULT_MASK \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_HANG_REBOOT) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_PANIC) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_FASTBOOT) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MKBP) | \ EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT)) static host_event_t lpc_host_events; @@ -113,7 +116,7 @@ static host_event_t lpc_get_all_host_event_masks(void) return or_mask; } -static void lpc_set_host_event_state(host_event_t events) +test_export_static void lpc_set_host_event_state(host_event_t events) { if (events == lpc_host_events) return; @@ -135,21 +138,25 @@ host_event_t lpc_get_host_events(void) int lpc_get_next_host_event(void) { host_event_t ev; - int evt_idx = __builtin_ffs(lpc_host_events); + int evt_idx = __builtin_ffs(lpc_host_events); -#ifdef CONFIG_HOST_EVENT64 if (evt_idx == 0) { int evt_idx_high = __builtin_ffs(lpc_host_events >> 32); if (evt_idx_high) evt_idx = 32 + evt_idx_high; } -#endif if (evt_idx) { host_event_set_bit(&ev, evt_idx); host_clear_events(ev); } +#ifdef CONFIG_CUSTOMIZED_DESIGN + else { + /* Workaround, call function to clear SCI event when index = 0") */ + lpc_update_host_event_status(); + } +#endif return evt_idx; } @@ -174,7 +181,7 @@ static int lpc_post_sysjump_restore_mask(void) int size, version; prev_mask = (const host_event_t *)system_get_jump_tag(LPC_SYSJUMP_TAG, - &version, &size); + &version, &size); if (!prev_mask || size != sizeof(lpc_host_event_mask) || (version != LPC_SYSJUMP_VERSION && version != LPC_SYSJUMP_OLD_VERSION)) @@ -264,28 +271,23 @@ static struct lazy_wake_masks { static void host_events_atomic_or(host_event_t *e, host_event_t m) { - uint32_t *ptr = (uint32_t *)e; + atomic_t *ptr = (atomic_t *)e; - deprecated_atomic_or(ptr, (uint32_t)m); -#ifdef CONFIG_HOST_EVENT64 - deprecated_atomic_or(ptr + 1, (uint32_t)(m >> 32)); -#endif + atomic_or(ptr, (uint32_t)m); + atomic_or(ptr + 1, (uint32_t)(m >> 32)); } static void host_events_atomic_clear(host_event_t *e, host_event_t m) { - uint32_t *ptr = (uint32_t *)e; + atomic_t *ptr = (atomic_t *)e; - deprecated_atomic_clear_bits(ptr, (uint32_t)m); -#ifdef CONFIG_HOST_EVENT64 - deprecated_atomic_clear_bits(ptr + 1, (uint32_t)(m >> 32)); -#endif + atomic_clear_bits(ptr, (uint32_t)m); + atomic_clear_bits(ptr + 1, (uint32_t)(m >> 32)); } #if !defined(CONFIG_HOSTCMD_X86) && defined(CONFIG_MKBP_EVENT) static void host_events_send_mkbp_event(host_event_t e) { -#ifdef CONFIG_HOST_EVENT64 /* * If event bits in the upper 32-bit are set, indicate 64-bit host * event. @@ -293,7 +295,6 @@ static void host_events_send_mkbp_event(host_event_t e) if (!(uint32_t)e) mkbp_send_event(EC_MKBP_EVENT_HOST_EVENT64); else -#endif mkbp_send_event(EC_MKBP_EVENT_HOST_EVENT); } #endif @@ -306,11 +307,7 @@ host_event_t host_get_events(void) void host_set_events(host_event_t mask) { /* ignore host events the rest of board doesn't care about */ -#ifdef CONFIG_HOST_EVENT64 - mask &= CONFIG_HOST_EVENT64_REPORT_MASK; -#else mask &= CONFIG_HOST_EVENT_REPORT_MASK; -#endif #ifdef CONFIG_HOSTCMD_X86 /* @@ -330,6 +327,10 @@ void host_set_events(host_event_t mask) HOST_EVENT_CPRINTS("event set", mask); + if (!IS_ENABLED(CONFIG_ZTEST) && + (mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY))) + system_enter_manual_recovery(); + host_events_atomic_or(&events, mask); host_events_atomic_or(&events_copy_b, mask); @@ -342,8 +343,8 @@ void host_set_events(host_event_t mask) #error "Config error: MKBP must not be on top of host event" #endif host_events_send_mkbp_event(events); -#endif /* CONFIG_MKBP_EVENT */ -#endif /* !CONFIG_HOSTCMD_X86 */ +#endif /* CONFIG_MKBP_EVENT */ +#endif /* !CONFIG_HOSTCMD_X86 */ } void host_set_single_event(enum host_event_code event) @@ -365,16 +366,17 @@ int host_is_event_set(enum host_event_code event) void host_clear_events(host_event_t mask) { /* ignore host events the rest of board doesn't care about */ -#ifdef CONFIG_HOST_EVENT64 - mask &= CONFIG_HOST_EVENT64_REPORT_MASK; -#else mask &= CONFIG_HOST_EVENT_REPORT_MASK; -#endif +#ifdef CONFIG_CUSTOMIZED_DESIGN + /* return early if nothing changed */ + if (!(lpc_host_events & mask)) + return; +#else /* return early if nothing changed */ if (!(events & mask)) return; - +#endif HOST_EVENT_CPRINTS("event clear", mask); host_events_atomic_clear(&events, mask); @@ -386,7 +388,7 @@ void host_clear_events(host_event_t mask) #ifdef CONFIG_MKBP_EVENT host_events_send_mkbp_event(events); #endif -#endif /* !CONFIG_HOSTCMD_X86 */ +#endif /* !CONFIG_HOSTCMD_X86 */ } #ifndef CONFIG_HOSTCMD_X86 @@ -400,7 +402,6 @@ static int host_get_next_event(uint8_t *out) } DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_HOST_EVENT, host_get_next_event); -#ifdef CONFIG_HOST_EVENT64 static int host_get_next_event64(uint8_t *out) { host_event_t event_out = events; @@ -412,7 +413,6 @@ static int host_get_next_event64(uint8_t *out) } DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_HOST_EVENT64, host_get_next_event64); #endif -#endif /** * Clear one or more host event bits from copy B. @@ -454,12 +454,12 @@ DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, clear_events_copy_b, HOOK_PRIO_DEFAULT); /*****************************************************************************/ /* Console commands */ -static int command_host_event(int argc, char **argv) +static int command_host_event(int argc, const char **argv) { /* Handle sub-commands */ if (argc == 3) { char *e; - host_event_t i = strtoul(argv[2], &e, 0); + host_event_t i = strtoull(argv[2], &e, 0); if (*e) return EC_ERROR_PARAM2; @@ -489,19 +489,21 @@ static int command_host_event(int argc, char **argv) HOST_EVENT_CCPRINTF("Events-B: ", events_copy_b); #ifdef CONFIG_HOSTCMD_X86 HOST_EVENT_CCPRINTF("SMI mask: ", - lpc_get_host_event_mask(LPC_HOST_EVENT_SMI)); + lpc_get_host_event_mask(LPC_HOST_EVENT_SMI)); HOST_EVENT_CCPRINTF("SCI mask: ", - lpc_get_host_event_mask(LPC_HOST_EVENT_SCI)); + lpc_get_host_event_mask(LPC_HOST_EVENT_SCI)); HOST_EVENT_CCPRINTF("Wake mask: ", - lpc_get_host_event_mask(LPC_HOST_EVENT_WAKE)); - HOST_EVENT_CCPRINTF("Always report mask: ", - lpc_get_host_event_mask(LPC_HOST_EVENT_ALWAYS_REPORT)); + lpc_get_host_event_mask(LPC_HOST_EVENT_WAKE)); + HOST_EVENT_CCPRINTF( + "Always report mask: ", + lpc_get_host_event_mask(LPC_HOST_EVENT_ALWAYS_REPORT)); #endif return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(hostevent, command_host_event, - "[set | clear | clearb | smi | sci | wake | always_report] [mask]", - "Print / set host event state"); +DECLARE_CONSOLE_COMMAND( + hostevent, command_host_event, + "[set | clear | clearb | smi | sci | wake | always_report] [mask]", + "Print / set host event state"); /*****************************************************************************/ /* Host commands */ @@ -518,8 +520,7 @@ host_event_get_smi_mask(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_GET_SMI_MASK, - host_event_get_smi_mask, +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_GET_SMI_MASK, host_event_get_smi_mask, EC_VER_MASK(0)); static enum ec_status @@ -532,8 +533,7 @@ host_event_get_sci_mask(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_GET_SCI_MASK, - host_event_get_sci_mask, +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_GET_SCI_MASK, host_event_get_sci_mask, EC_VER_MASK(0)); static enum ec_status @@ -546,8 +546,7 @@ host_event_get_wake_mask(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_GET_WAKE_MASK, - host_event_get_wake_mask, +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_GET_WAKE_MASK, host_event_get_wake_mask, EC_VER_MASK(0)); static enum ec_status @@ -558,8 +557,7 @@ host_event_set_smi_mask(struct host_cmd_handler_args *args) lpc_set_host_event_mask(LPC_HOST_EVENT_SMI, p->mask); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_SET_SMI_MASK, - host_event_set_smi_mask, +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_SET_SMI_MASK, host_event_set_smi_mask, EC_VER_MASK(0)); static enum ec_status @@ -570,8 +568,7 @@ host_event_set_sci_mask(struct host_cmd_handler_args *args) lpc_set_host_event_mask(LPC_HOST_EVENT_SCI, p->mask); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_SET_SCI_MASK, - host_event_set_sci_mask, +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_SET_SCI_MASK, host_event_set_sci_mask, EC_VER_MASK(0)); static enum ec_status @@ -583,8 +580,7 @@ host_event_set_wake_mask(struct host_cmd_handler_args *args) active_wm_set_by_host = !!p->mask; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_SET_WAKE_MASK, - host_event_set_wake_mask, +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_SET_WAKE_MASK, host_event_set_wake_mask, EC_VER_MASK(0)); uint8_t lpc_is_active_wm_set_by_host(void) @@ -592,7 +588,7 @@ uint8_t lpc_is_active_wm_set_by_host(void) return active_wm_set_by_host; } -#endif /* CONFIG_HOSTCMD_X86 */ +#endif /* CONFIG_HOSTCMD_X86 */ static enum ec_status host_event_get_b(struct host_cmd_handler_args *args) { @@ -603,9 +599,7 @@ static enum ec_status host_event_get_b(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_GET_B, - host_event_get_b, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_GET_B, host_event_get_b, EC_VER_MASK(0)); static enum ec_status host_event_clear(struct host_cmd_handler_args *args) { @@ -614,9 +608,7 @@ static enum ec_status host_event_clear(struct host_cmd_handler_args *args) host_clear_events(p->mask); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_CLEAR, - host_event_clear, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_CLEAR, host_event_clear, EC_VER_MASK(0)); static enum ec_status host_event_clear_b(struct host_cmd_handler_args *args) { @@ -625,8 +617,7 @@ static enum ec_status host_event_clear_b(struct host_cmd_handler_args *args) host_clear_events_b(p->mask); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_CLEAR_B, - host_event_clear_b, +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_CLEAR_B, host_event_clear_b, EC_VER_MASK(0)); static enum ec_status host_event_action_get(struct host_cmd_handler_args *args) @@ -653,8 +644,8 @@ static enum ec_status host_event_action_get(struct host_cmd_handler_args *args) r->value = lpc_get_host_event_mask(LPC_HOST_EVENT_SMI); break; case EC_HOST_EVENT_ALWAYS_REPORT_MASK: - r->value = lpc_get_host_event_mask - (LPC_HOST_EVENT_ALWAYS_REPORT); + r->value = + lpc_get_host_event_mask(LPC_HOST_EVENT_ALWAYS_REPORT); break; case EC_HOST_EVENT_ACTIVE_WAKE_MASK: r->value = lpc_get_host_event_mask(LPC_HOST_EVENT_WAKE); @@ -699,7 +690,7 @@ static enum ec_status host_event_action_set(struct host_cmd_handler_args *args) break; case EC_HOST_EVENT_ALWAYS_REPORT_MASK: lpc_set_host_event_mask(LPC_HOST_EVENT_ALWAYS_REPORT, - mask_value); + mask_value); break; case EC_HOST_EVENT_ACTIVE_WAKE_MASK: active_wm_set_by_host = !!mask_value; @@ -778,12 +769,11 @@ host_command_host_event(struct host_cmd_handler_args *args) } } -DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT, - host_command_host_event, +DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT, host_command_host_event, EC_VER_MASK(0)); -#define LAZY_WAKE_MASK_SYSJUMP_TAG 0x4C4D /* LM - Lazy Mask*/ -#define LAZY_WAKE_MASK_HOOK_VERSION 1 +#define LAZY_WAKE_MASK_SYSJUMP_TAG 0x4C4D /* LM - Lazy Mask*/ +#define LAZY_WAKE_MASK_HOOK_VERSION 1 #ifdef CONFIG_HOSTCMD_X86 int get_lazy_wake_mask(enum power_state state, host_event_t *mask) @@ -813,8 +803,7 @@ int get_lazy_wake_mask(enum power_state state, host_event_t *mask) static void preserve_lazy_wm(void) { system_add_jump_tag(LAZY_WAKE_MASK_SYSJUMP_TAG, - LAZY_WAKE_MASK_HOOK_VERSION, - sizeof(lazy_wm), + LAZY_WAKE_MASK_HOOK_VERSION, sizeof(lazy_wm), &lazy_wm); } DECLARE_HOOK(HOOK_SYSJUMP, preserve_lazy_wm, HOOK_PRIO_DEFAULT); @@ -824,14 +813,13 @@ static void restore_lazy_wm(void) const struct lazy_wake_masks *wm_state; int version, size; - wm_state = (const struct lazy_wake_masks *) - system_get_jump_tag(LAZY_WAKE_MASK_SYSJUMP_TAG, - &version, &size); + wm_state = (const struct lazy_wake_masks *)system_get_jump_tag( + LAZY_WAKE_MASK_SYSJUMP_TAG, &version, &size); if (wm_state && (version == LAZY_WAKE_MASK_HOOK_VERSION) && (size == sizeof(lazy_wm))) { lazy_wm = *wm_state; } } -DECLARE_HOOK(HOOK_INIT, restore_lazy_wm, HOOK_PRIO_INIT_CHIPSET + 1); +DECLARE_HOOK(HOOK_INIT, restore_lazy_wm, HOOK_PRIO_POST_CHIPSET); #endif diff --git a/common/hotword_dsp_api.c b/common/hotword_dsp_api.c index dc53cd0055..24291df8c0 100644 --- a/common/hotword_dsp_api.c +++ b/common/hotword_dsp_api.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Chromium OS Authors. All rights reserved. + * Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/common/i2c_bitbang.c b/common/i2c_bitbang.c index 238cc182ff..01d4f5f31e 100644 --- a/common/i2c_bitbang.c +++ b/common/i2c_bitbang.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,7 +10,8 @@ #include "timer.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPUTS(str) cputs(CC_I2C, str) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) static int started; @@ -21,8 +22,8 @@ static void i2c_delay(void) } /* Number of attempts to unwedge each pin. */ -#define UNWEDGE_SCL_ATTEMPTS 10 -#define UNWEDGE_SDA_ATTEMPTS 3 +#define UNWEDGE_SCL_ATTEMPTS 10 +#define UNWEDGE_SDA_ATTEMPTS 3 static void i2c_bitbang_unwedge(const struct i2c_port_t *i2c_port) { @@ -31,17 +32,16 @@ static void i2c_bitbang_unwedge(const struct i2c_port_t *i2c_port) gpio_set_level(i2c_port->scl, 1); /* * If clock is low, wait for a while in case of clock stretched - * by a slave. + * by a peripheral. */ if (!gpio_get_level(i2c_port->scl)) { for (i = 0;; i++) { if (i >= UNWEDGE_SCL_ATTEMPTS) { /* - * If we get here, a slave is holding the clock - * low and there is nothing we can do. + * If we get here, a peripheral is holding the + * clock low and there is nothing we can do. */ - CPRINTS("I2C%d unwedge failed, " - "SCL is held low", i2c_port->port); + CPUTS("I2C unwedge failed, SCL is held low\n"); return; } i2c_delay(); @@ -53,7 +53,7 @@ static void i2c_bitbang_unwedge(const struct i2c_port_t *i2c_port) if (gpio_get_level(i2c_port->sda)) return; - CPRINTS("I2C%d unwedge called with SDA held low", i2c_port->port); + CPUTS("I2C unwedge called with SDA held low\n"); /* Keep trying to unwedge the SDA line until we run out of attempts. */ for (i = 0; i < UNWEDGE_SDA_ATTEMPTS; i++) { @@ -62,9 +62,9 @@ static void i2c_bitbang_unwedge(const struct i2c_port_t *i2c_port) i2c_delay(); /* - * Clock through the problem by clocking out 9 bits. If slave - * releases the SDA line, then we can stop clocking bits and - * send a STOP. + * Clock through the problem by clocking out 9 bits. If + * peripheral releases the SDA line, then we can stop clocking + * bits and send a STOP. */ for (j = 0; j < 9; j++) { if (gpio_get_level(i2c_port->sda)) @@ -84,14 +84,14 @@ static void i2c_bitbang_unwedge(const struct i2c_port_t *i2c_port) /* Check if the bus is unwedged. */ if (gpio_get_level(i2c_port->sda) && - gpio_get_level(i2c_port->scl)) + gpio_get_level(i2c_port->scl)) break; } if (!gpio_get_level(i2c_port->sda)) - CPRINTS("I2C%d unwedge failed, SDA still low", i2c_port->port); + CPUTS("I2C unwedge failed, SDA still low\n"); if (!gpio_get_level(i2c_port->scl)) - CPRINTS("I2C%d unwedge failed, SCL still low", i2c_port->port); + CPUTS("I2C unwedge failed, SCL still low\n"); } static void i2c_stop_cond(const struct i2c_port_t *i2c_port) @@ -110,9 +110,9 @@ static void i2c_stop_cond(const struct i2c_port_t *i2c_port) * SMBus 3.0, 4.2.5 * * the recommendation is that if SMBDAT is still low tTIMEOUT,MAX after - * SMBCLK has gone high at the end of a transaction the master should - * hold SMBCLK low for at least tTIMEOUT,MAX in an attempt to reset the - * SMBus interface of all of the devices on the bus. + * SMBCLK has gone high at the end of a transaction the controller + * should hold SMBCLK low for at least tTIMEOUT,MAX in an attempt to + * reset the SMBus interface of all of the devices on the bus. */ for (i = 0; i < 7000; i++) { if (gpio_get_level(i2c_port->scl)) @@ -145,12 +145,12 @@ static int clock_stretching(const struct i2c_port_t *i2c_port) * Devices participating in a transfer can abort the transfer in * progress and release the bus when any single clock low interval * exceeds the value of tTIMEOUT,MIN(=25ms). - * After the master in a transaction detects this condition, it must + * After the controller in a transaction detects this condition, it must * generate a stop condition within or after the current data byte in * the transfer process. */ i2c_stop_cond(i2c_port); - CPRINTS("clock low timeout"); + CPUTS("clock low timeout\n"); return EC_ERROR_TIMEOUT; } @@ -170,7 +170,7 @@ static int i2c_start_cond(const struct i2c_port_t *i2c_port) i2c_delay(); if (gpio_get_level(i2c_port->sda) == 0) { - CPRINTS("%s: arbitration lost", __func__); + CPUTS("start_cond: arbitration lost\n"); started = 0; return EC_ERROR_UNKNOWN; } @@ -204,7 +204,7 @@ static int i2c_write_bit(const struct i2c_port_t *i2c_port, int bit) i2c_delay(); if (bit && gpio_get_level(i2c_port->sda) == 0) { - CPRINTS("%s: arbitration lost", __func__); + CPUTS("write_bit: arbitration lost\n"); started = 0; return EC_ERROR_UNKNOWN; } @@ -249,10 +249,11 @@ static int i2c_write_byte(const struct i2c_port_t *i2c_port, uint8_t byte) if (nack) { /* - * The slave device detects an invalid command or invalid data. - * In this case the slave device must NACK the received byte. - * The master upon detection of this condition must generate a - * STOP condition and retry the transaction + * The peripheral device detects an invalid command or invalid + * data. In this case the peripheral device must NACK the + * received byte. The controller upon detection of this + * condition must generate a STOP condition and retry the + * transaction */ i2c_stop_cond(i2c_port); /* return EC_ERROR_BUSY to indicate i2c_xfer() to retry */ @@ -262,7 +263,7 @@ static int i2c_write_byte(const struct i2c_port_t *i2c_port, uint8_t byte) } static int i2c_read_byte(const struct i2c_port_t *i2c_port, uint8_t *byte, - int nack) + int nack) { int i; @@ -280,15 +281,14 @@ static int i2c_read_byte(const struct i2c_port_t *i2c_port, uint8_t *byte, } static int i2c_bitbang_xfer(const struct i2c_port_t *i2c_port, - const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) + const uint16_t addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size, int flags) { - uint16_t addr_8bit = slave_addr_flags << 1, err = EC_SUCCESS; + uint16_t addr_8bit = addr_flags << 1, err = EC_SUCCESS; int i = 0; if (i2c_port->kbps != 100) - CPRINTS("warning: bitbang driver only supports 100kbps"); + CPUTS("warning: bitbang driver only supports 100kbps\n"); if (out_size) { if (flags & I2C_XFER_START) { @@ -319,7 +319,8 @@ static int i2c_bitbang_xfer(const struct i2c_port_t *i2c_port, for (i = 0; i < in_size; i++) { err = i2c_read_byte(i2c_port, &in[i], - (flags & I2C_XFER_STOP) && (i == in_size - 1)); + (flags & I2C_XFER_STOP) && + (i == in_size - 1)); if (err) goto exit; } @@ -336,9 +337,23 @@ static int i2c_bitbang_xfer(const struct i2c_port_t *i2c_port, return err; } -const struct i2c_drv bitbang_drv = { - .xfer = &i2c_bitbang_xfer -}; +void enable_i2c_raw_mode(bool enable) +{ + int i; + + for (i = 0; i < i2c_bitbang_ports_used; i++) { + if (i2c_raw_mode(i2c_bitbang_ports[i].port, enable)) + CPRINTS("I2C p%d: Failed to %s raw mode", + i2c_bitbang_ports[i].port, + enable ? "enable" : "disable"); + } +} + +__overridable void board_pre_task_i2c_peripheral_init(void) +{ +} + +const struct i2c_drv bitbang_drv = { .xfer = &i2c_bitbang_xfer }; #ifdef TEST_BUILD int bitbang_start_cond(const struct i2c_port_t *i2c_port) diff --git a/common/i2c_controller.c b/common/i2c_controller.c new file mode 100644 index 0000000000..568e8832d0 --- /dev/null +++ b/common/i2c_controller.c @@ -0,0 +1,1530 @@ +/* Copyright 2013 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* I2C cross-platform code for Chrome EC */ + +#include "battery.h" +#include "builtin/assert.h" +#include "charge_state.h" +#include "clock.h" +#include "console.h" +#include "crc8.h" +#include "gpio.h" +#include "host_command.h" +#include "i2c.h" +#include "i2c_bitbang.h" +#include "i2c_private.h" +#include "printf.h" +#include "system.h" +#include "task.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "util.h" +#include "virtual_battery.h" +#include "watchdog.h" + +#ifdef CONFIG_ZEPHYR +#include "i2c/i2c.h" + +#include +#endif /* CONFIG_ZEPHYR */ + +#define CPUTS(outstr) cputs(CC_I2C, outstr) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) + +/* Only chips with multi-port controllers will define I2C_CONTROLLER_COUNT */ +#ifndef I2C_CONTROLLER_COUNT +#define I2C_CONTROLLER_COUNT I2C_PORT_COUNT +#endif + +#ifndef CONFIG_I2C_BITBANG +#define I2C_BITBANG_PORT_COUNT 0 +#endif + +static mutex_t port_mutex[I2C_CONTROLLER_COUNT + I2C_BITBANG_PORT_COUNT]; + +/* A bitmap of the controllers which are currently servicing a request. */ +static volatile uint32_t i2c_port_active_list; +BUILD_ASSERT(ARRAY_SIZE(port_mutex) < 32); +static uint8_t port_protected[I2C_PORT_COUNT + I2C_BITBANG_PORT_COUNT]; + +#ifdef CONFIG_ZEPHYR +static int init_port_mutex(void) +{ + for (int i = 0; i < ARRAY_SIZE(port_mutex); ++i) + k_mutex_init(port_mutex + i); + + return 0; +} +SYS_INIT(init_port_mutex, POST_KERNEL, 50); +#endif /* CONFIG_ZEPHYR */ + +/** + * Non-deterministically test the lock status of the port. If another task + * has locked the port and the caller is accessing it illegally, then this test + * will incorrectly return true. However, callers which failed to statically + * lock the port will fail quickly. + */ +STATIC_IF_NOT(CONFIG_ZTEST) +int i2c_port_is_locked(int port) +{ +#ifdef CONFIG_I2C_MULTI_PORT_CONTROLLER + /* Test the controller, not the port */ + port = i2c_port_to_controller(port); +#endif + /* can't lock a non-existing port */ + if (port < 0) + return 0; + + return (i2c_port_active_list >> port) & 1; +} + +const struct i2c_port_t *get_i2c_port(const int port) +{ + int i; + + /* + * If the EC's I2C driver implementation is task event based and the + * I2C is accessed before the task is initialized, it causes the system + * panic hence these I2C will fall back to bitbang mode if enabled at + * board level and will again switch back to event based I2C upon task + * initialization. + */ + if (task_start_called()) { + /* Find the matching port in i2c_ports[] table. */ + for (i = 0; i < i2c_ports_used; i++) { + if (i2c_ports[i].port == port) + return &i2c_ports[i]; + } + } + + if (IS_ENABLED(CONFIG_I2C_BITBANG)) { + /* Find the matching port in i2c_bitbang_ports[] table. */ + for (i = 0; i < i2c_bitbang_ports_used; i++) { + if (i2c_bitbang_ports[i].port == port) + return &i2c_bitbang_ports[i]; + } + } + + return NULL; +} + +__maybe_unused static int chip_i2c_xfer_with_notify(const int port, + const uint16_t addr_flags, + const uint8_t *out, + int out_size, uint8_t *in, + int in_size, int flags) +{ + int ret; + uint16_t no_pec_af = addr_flags; + const struct i2c_port_t *i2c_port = get_i2c_port(port); + + if (i2c_port == NULL) + return EC_ERROR_INVAL; + + if (IS_ENABLED(CONFIG_I2C_XFER_BOARD_CALLBACK)) + i2c_start_xfer_notify(port, addr_flags); + + if (IS_ENABLED(CONFIG_SMBUS_PEC)) + /* + * Since we've done PEC processing here, + * remove the flag so it won't confuse chip driver. + */ + no_pec_af &= ~I2C_FLAG_PEC; + + if (i2c_port->drv) + ret = i2c_port->drv->xfer(i2c_port, no_pec_af, out, out_size, + in, in_size, flags); + else + ret = chip_i2c_xfer(port, no_pec_af, out, out_size, in, in_size, + flags); + + if (IS_ENABLED(CONFIG_I2C_XFER_BOARD_CALLBACK)) + i2c_end_xfer_notify(port, addr_flags); + + if (IS_ENABLED(CONFIG_I2C_DEBUG)) { + i2c_trace_notify(port, addr_flags, out, out_size, in, in_size, + ret); + } + + return ret; +} + +#ifdef CONFIG_I2C_XFER_LARGE_TRANSFER +/* + * Internal function that splits transfer into multiple chip_i2c_xfer() calls + * if in_size or out_size exceeds CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE. + */ +static int i2c_xfer_no_retry(const int port, const uint16_t addr_flags, + const uint8_t *out, int out_size, uint8_t *in, + int in_size, int flags) +{ + int offset; + + for (offset = 0; offset < out_size;) { + int chunk_size = MIN(out_size - offset, + CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE); + int out_flags = 0; + + if (offset == 0) + out_flags |= flags & I2C_XFER_START; + if (in_size == 0 && offset + chunk_size == out_size) + out_flags |= flags & I2C_XFER_STOP; + + RETURN_ERROR(chip_i2c_xfer_with_notify(port, addr_flags, + out + offset, chunk_size, + NULL, 0, out_flags)); + offset += chunk_size; + } + for (offset = 0; offset < in_size;) { + int chunk_size = MIN(in_size - offset, + CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE); + int in_flags = 0; + + if (offset == 0) + in_flags |= flags & I2C_XFER_START; + if (offset + chunk_size == in_size) + in_flags |= flags & I2C_XFER_STOP; + + RETURN_ERROR(chip_i2c_xfer_with_notify(port, addr_flags, NULL, + 0, in + offset, + chunk_size, in_flags)); + offset += chunk_size; + } + return EC_SUCCESS; +} +#endif /* CONFIG_I2C_XFER_LARGE_TRANSFER */ + +int i2c_xfer_unlocked(const int port, const uint16_t addr_flags, + const uint8_t *out, int out_size, uint8_t *in, + int in_size, int flags) +{ + int i; + int ret = EC_SUCCESS; + uint16_t no_pec_af = addr_flags & ~I2C_FLAG_PEC; + + if (!i2c_port_is_locked(port)) { + CPUTS("Access I2C without lock!"); + return EC_ERROR_INVAL; + } + + for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { +#ifdef CONFIG_ZEPHYR + struct i2c_msg msg[2]; + int num_msgs = 0; + + /* Be careful to respect the flags passed in */ + if (out_size) { + unsigned int wflags = I2C_MSG_WRITE; + + msg[num_msgs].buf = (uint8_t *)out; + msg[num_msgs].len = out_size; + + /* If this is the last write, add a stop */ + if (!in_size && (flags & I2C_XFER_STOP)) + wflags |= I2C_MSG_STOP; + msg[num_msgs].flags = wflags; + num_msgs++; + } + if (in_size) { + unsigned int rflags = I2C_MSG_READ; + + msg[num_msgs].buf = (uint8_t *)in; + msg[num_msgs].len = in_size; + rflags = I2C_MSG_READ; + + /* If a stop is requested, add it */ + if (flags & I2C_XFER_STOP) + rflags |= I2C_MSG_STOP; + + /* + * If this read follows a write (above) then we need a + * restart + */ + if (num_msgs) + rflags |= I2C_MSG_RESTART; + msg[num_msgs].flags = rflags; + num_msgs++; + } + + /* Big endian flag is used in wrappers for this call */ + if (no_pec_af & ~(I2C_ADDR_MASK | I2C_FLAG_BIG_ENDIAN | + I2C_FLAG_ADDR16_LITTLE_ENDIAN)) + ccprintf("Ignoring flags from i2c addr_flags: %04x", + no_pec_af); + + ret = i2c_transfer(i2c_get_device_for_port(port), msg, num_msgs, + I2C_STRIP_FLAGS(no_pec_af)); + + if (IS_ENABLED(CONFIG_I2C_DEBUG)) { + i2c_trace_notify(port, addr_flags, out, out_size, in, + in_size, ret); + } + + switch (ret) { + case 0: + return EC_SUCCESS; + case -EIO: + ret = EC_ERROR_INVAL; + continue; + default: + return EC_ERROR_UNKNOWN; + } +#elif defined(CONFIG_I2C_XFER_LARGE_TRANSFER) + ret = i2c_xfer_no_retry(port, no_pec_af, out, out_size, in, + in_size, flags); +#else + ret = chip_i2c_xfer_with_notify(port, no_pec_af, out, out_size, + in, in_size, flags); +#endif /* CONFIG_I2C_XFER_LARGE_TRANSFER */ + if (ret != EC_ERROR_BUSY) + break; + } + return ret; +} + +int i2c_xfer(const int port, const uint16_t addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size) +{ + int rv; + + i2c_lock(port, 1); + rv = i2c_xfer_unlocked(port, addr_flags, out, out_size, in, in_size, + I2C_XFER_SINGLE); + i2c_lock(port, 0); + + return rv; +} + +void i2c_lock(int port, int lock) +{ +#ifdef CONFIG_I2C_MULTI_PORT_CONTROLLER + /* Lock the controller, not the port */ + port = i2c_port_to_controller(port); +#endif + if (port < 0 || port >= ARRAY_SIZE(port_mutex)) + return; + + if (lock) { + uint32_t irq_lock_key; + + mutex_lock(port_mutex + port); + + /* Disable interrupt during changing counter for preemption. */ + irq_lock_key = irq_lock(); + + i2c_port_active_list |= BIT(port); + /* EC cannot enter sleep if there's any i2c port active. */ + disable_sleep(SLEEP_MASK_I2C_CONTROLLER); + + irq_unlock(irq_lock_key); + } else { + uint32_t irq_lock_key = irq_lock(); + + i2c_port_active_list &= ~BIT(port); + /* Once there is no i2c port active, enable sleep bit of i2c. */ + if (!i2c_port_active_list) + enable_sleep(SLEEP_MASK_I2C_CONTROLLER); + + irq_unlock(irq_lock_key); + + mutex_unlock(port_mutex + port); + } +} + +void i2c_prepare_sysjump(void) +{ + int i; + + /* Lock all i2c controllers */ + for (i = 0; i < ARRAY_SIZE(port_mutex); ++i) + mutex_lock(port_mutex + i); +} + +/* i2c_readN with optional error checking */ +static int platform_ec_i2c_read(const int port, const uint16_t addr_flags, + uint8_t reg, uint8_t *in, int in_size) +{ + if (!IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags)) + return EC_ERROR_UNIMPLEMENTED; + + if (IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags)) { + int i, rv; + /* addr_8bit = 7 bit addr_flags + 1 bit r/w */ + uint8_t addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; + uint8_t out[3] = { addr_8bit, reg, addr_8bit | 1 }; + uint8_t pec_local = 0, pec_remote; + + i2c_lock(port, 1); + for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { + rv = i2c_xfer_unlocked(port, addr_flags, ®, 1, in, + in_size, I2C_XFER_START); + if (rv) + continue; + + rv = i2c_xfer_unlocked(port, addr_flags, NULL, 0, + &pec_remote, 1, I2C_XFER_STOP); + if (rv) + continue; + + pec_local = cros_crc8(out, ARRAY_SIZE(out)); + pec_local = cros_crc8_arg(in, in_size, pec_local); + if (pec_local == pec_remote) + break; + + rv = EC_ERROR_CRC; + } + i2c_lock(port, 0); + + return rv; + } + + return i2c_xfer(port, addr_flags, ®, 1, in, in_size); +} + +/* i2c_writeN with optional error checking */ +static int platform_ec_i2c_write(const int port, const uint16_t addr_flags, + const uint8_t *out, int out_size) +{ + if (!IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags)) + return EC_ERROR_UNIMPLEMENTED; + + if (IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags)) { + int i, rv; + uint8_t addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; + uint8_t pec; + + pec = cros_crc8(&addr_8bit, 1); + pec = cros_crc8_arg(out, out_size, pec); + + i2c_lock(port, 1); + for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { + rv = i2c_xfer_unlocked(port, addr_flags, out, out_size, + NULL, 0, I2C_XFER_START); + if (rv) + continue; + + rv = i2c_xfer_unlocked(port, addr_flags, &pec, 1, NULL, + 0, I2C_XFER_STOP); + if (!rv) + break; + } + i2c_lock(port, 0); + + return rv; + } + + return i2c_xfer(port, addr_flags, out, out_size, NULL, 0); +} + +int i2c_read32(const int port, const uint16_t addr_flags, int offset, int *data) +{ + int rv; + uint8_t reg, buf[sizeof(uint32_t)]; + + reg = offset & 0xff; + /* I2C read 32-bit word: transmit 8-bit offset, and read 32bits */ + rv = platform_ec_i2c_read(port, addr_flags, reg, buf, sizeof(uint32_t)); + + if (rv) + return rv; + + if (I2C_IS_BIG_ENDIAN(addr_flags)) + *data = ((int)buf[0] << 24) | ((int)buf[1] << 16) | + ((int)buf[2] << 8) | buf[3]; + else + *data = ((int)buf[3] << 24) | ((int)buf[2] << 16) | + ((int)buf[1] << 8) | buf[0]; + + return EC_SUCCESS; +} + +int i2c_write32(const int port, const uint16_t addr_flags, int offset, int data) +{ + uint8_t buf[1 + sizeof(uint32_t)]; + + buf[0] = offset & 0xff; + + if (I2C_IS_BIG_ENDIAN(addr_flags)) { + buf[1] = (data >> 24) & 0xff; + buf[2] = (data >> 16) & 0xff; + buf[3] = (data >> 8) & 0xff; + buf[4] = data & 0xff; + } else { + buf[1] = data & 0xff; + buf[2] = (data >> 8) & 0xff; + buf[3] = (data >> 16) & 0xff; + buf[4] = (data >> 24) & 0xff; + } + + return platform_ec_i2c_write(port, addr_flags, buf, + sizeof(uint32_t) + 1); +} + +int i2c_read16(const int port, const uint16_t addr_flags, int offset, int *data) +{ + int rv; + uint8_t reg, buf[sizeof(uint16_t)]; + + reg = offset & 0xff; + /* I2C read 16-bit word: transmit 8-bit offset, and read 16bits */ + rv = platform_ec_i2c_read(port, addr_flags, reg, buf, sizeof(uint16_t)); + + if (rv) + return rv; + + if (I2C_IS_BIG_ENDIAN(addr_flags)) + *data = ((int)buf[0] << 8) | buf[1]; + else + *data = ((int)buf[1] << 8) | buf[0]; + + return EC_SUCCESS; +} + +int i2c_write16(const int port, const uint16_t addr_flags, int offset, int data) +{ + uint8_t buf[1 + sizeof(uint16_t)]; + + buf[0] = offset & 0xff; + + if (I2C_IS_BIG_ENDIAN(addr_flags)) { + buf[1] = (data >> 8) & 0xff; + buf[2] = data & 0xff; + } else { + buf[1] = data & 0xff; + buf[2] = (data >> 8) & 0xff; + } + + return platform_ec_i2c_write(port, addr_flags, buf, + 1 + sizeof(uint16_t)); +} + +int i2c_read8(const int port, const uint16_t addr_flags, int offset, int *data) +{ + int rv; + uint8_t reg = offset; + uint8_t buf; + + reg = offset; + + rv = platform_ec_i2c_read(port, addr_flags, reg, &buf, sizeof(uint8_t)); + if (!rv) + *data = buf; + + return rv; +} + +int i2c_write8(const int port, const uint16_t addr_flags, int offset, int data) +{ + uint8_t buf[2]; + + buf[0] = offset; + buf[1] = data; + + return platform_ec_i2c_write(port, addr_flags, buf, sizeof(buf)); +} + +int i2c_update8(const int port, const uint16_t addr_flags, const int offset, + const uint8_t mask, const enum mask_update_action action) +{ + int rv; + int read_val; + int write_val; + + rv = i2c_read8(port, addr_flags, offset, &read_val); + if (rv) + return rv; + + write_val = (action == MASK_SET) ? (read_val | mask) : + (read_val & ~mask); + + if (IS_ENABLED(CONFIG_I2C_UPDATE_IF_CHANGED) && write_val == read_val) + return EC_SUCCESS; + + return i2c_write8(port, addr_flags, offset, write_val); +} + +int i2c_update16(const int port, const uint16_t addr_flags, const int offset, + const uint16_t mask, const enum mask_update_action action) +{ + int rv; + int read_val; + int write_val; + + rv = i2c_read16(port, addr_flags, offset, &read_val); + if (rv) + return rv; + + write_val = (action == MASK_SET) ? (read_val | mask) : + (read_val & ~mask); + + if (IS_ENABLED(CONFIG_I2C_UPDATE_IF_CHANGED) && write_val == read_val) + return EC_SUCCESS; + + return i2c_write16(port, addr_flags, offset, write_val); +} + +int i2c_field_update8(const int port, const uint16_t addr_flags, + const int offset, const uint8_t field_mask, + const uint8_t set_value) +{ + int rv; + int read_val; + int write_val; + + rv = i2c_read8(port, addr_flags, offset, &read_val); + if (rv) + return rv; + + write_val = (read_val & (~field_mask)) | set_value; + + if (IS_ENABLED(CONFIG_I2C_UPDATE_IF_CHANGED) && write_val == read_val) + return EC_SUCCESS; + + return i2c_write8(port, addr_flags, offset, write_val); +} + +int i2c_field_update16(const int port, const uint16_t addr_flags, + const int offset, const uint16_t field_mask, + const uint16_t set_value) +{ + int rv; + int read_val; + int write_val; + + rv = i2c_read16(port, addr_flags, offset, &read_val); + if (rv) + return rv; + + write_val = (read_val & (~field_mask)) | set_value; + + if (IS_ENABLED(CONFIG_I2C_UPDATE_IF_CHANGED) && write_val == read_val) + return EC_SUCCESS; + + return i2c_write16(port, addr_flags, offset, write_val); +} + +int i2c_read_offset16(const int port, const uint16_t addr_flags, + uint16_t offset, int *data, int len) +{ + int rv; + uint8_t buf[sizeof(uint16_t)], addr[sizeof(uint16_t)]; + + if (len < 0 || len > 2) + return EC_ERROR_INVAL; + + if (I2C_IS_ADDR16_LITTLE_ENDIAN(addr_flags)) { + addr[0] = offset & 0xff; + addr[1] = (offset >> 8) & 0xff; + } else { + addr[0] = (offset >> 8) & 0xff; + addr[1] = offset & 0xff; + } + + /* I2C read 16-bit word: transmit 16-bit offset, and read buffer */ + rv = i2c_xfer(port, addr_flags, addr, 2, buf, len); + + if (rv) + return rv; + + if (len == 1) { + *data = buf[0]; + } else { + if (I2C_IS_BIG_ENDIAN(addr_flags)) + *data = ((int)buf[0] << 8) | buf[1]; + else + *data = ((int)buf[1] << 8) | buf[0]; + } + + return EC_SUCCESS; +} + +int i2c_write_offset16(const int port, const uint16_t addr_flags, + uint16_t offset, int data, int len) +{ + uint8_t buf[2 + sizeof(uint16_t)]; + + if (len < 0 || len > 2) + return EC_ERROR_INVAL; + + if (I2C_IS_ADDR16_LITTLE_ENDIAN(addr_flags)) { + buf[0] = offset & 0xff; + buf[1] = (offset >> 8) & 0xff; + } else { + buf[0] = (offset >> 8) & 0xff; + buf[1] = offset & 0xff; + } + + if (len == 1) { + buf[2] = data & 0xff; + } else { + if (I2C_IS_BIG_ENDIAN(addr_flags)) { + buf[2] = (data >> 8) & 0xff; + buf[3] = data & 0xff; + } else { + buf[2] = data & 0xff; + buf[3] = (data >> 8) & 0xff; + } + } + + return i2c_xfer(port, addr_flags, buf, 2 + len, NULL, 0); +} + +int i2c_read_offset16_block(const int port, const uint16_t addr_flags, + uint16_t offset, uint8_t *data, int len) +{ + uint8_t addr[sizeof(uint16_t)]; + + if (I2C_IS_ADDR16_LITTLE_ENDIAN(addr_flags)) { + addr[0] = offset & 0xff; + addr[1] = (offset >> 8) & 0xff; + } else { + addr[0] = (offset >> 8) & 0xff; + addr[1] = offset & 0xff; + } + + return i2c_xfer(port, addr_flags, addr, 2, data, len); +} + +int i2c_write_offset16_block(const int port, const uint16_t addr_flags, + uint16_t offset, const uint8_t *data, int len) +{ + int rv; + uint8_t addr[sizeof(uint16_t)]; + + if (I2C_IS_ADDR16_LITTLE_ENDIAN(addr_flags)) { + addr[0] = offset & 0xff; + addr[1] = (offset >> 8) & 0xff; + } else { + addr[0] = (offset >> 8) & 0xff; + addr[1] = offset & 0xff; + } + + /* + * Split into two transactions to avoid the stack space consumption of + * appending the destination address with the data array. + */ + i2c_lock(port, 1); + rv = i2c_xfer_unlocked(port, addr_flags, addr, 2, NULL, 0, + I2C_XFER_START); + if (!rv) + rv = i2c_xfer_unlocked(port, addr_flags, data, len, NULL, 0, + I2C_XFER_STOP); + i2c_lock(port, 0); + + return rv; +} + +int i2c_read_sized_block(const int port, const uint16_t addr_flags, int offset, + uint8_t *data, int max_len, int *read_len) +{ + int i, rv; + uint8_t reg, block_length; + + if (max_len == 0) + return EC_ERROR_INVAL; + + if (!IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags)) + return EC_ERROR_UNIMPLEMENTED; + + reg = offset; + i2c_lock(port, 1); + + for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { + int data_length = 0; + + /* + * Send device reg space offset, and read back block length. + * Keep this session open without a stop. + */ + rv = i2c_xfer_unlocked(port, addr_flags, ®, 1, &block_length, + 1, I2C_XFER_START); + if (rv) + continue; + + if (block_length > max_len) + data_length = max_len; + else + data_length = block_length; + + if (IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags)) { + uint8_t addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; + uint8_t out[3] = { addr_8bit, reg, addr_8bit | 1 }; + uint8_t pec, pec_remote; + + rv = i2c_xfer_unlocked(port, addr_flags, 0, 0, data, + data_length, 0); + if (rv) + continue; + + pec = cros_crc8(out, sizeof(out)); + pec = cros_crc8_arg(&block_length, 1, pec); + pec = cros_crc8_arg(data, data_length, pec); + + /* read all remaining bytes */ + block_length -= data_length; + while (block_length) { + uint8_t byte; + + rv = i2c_xfer_unlocked(port, addr_flags, NULL, + 0, &byte, 1, 0); + if (rv) + break; + pec = cros_crc8_arg(&byte, 1, pec); + --block_length; + } + if (rv) + continue; + + rv = i2c_xfer_unlocked(port, addr_flags, NULL, 0, + &pec_remote, 1, I2C_XFER_STOP); + if (rv) + continue; + + if (pec != pec_remote) + rv = EC_ERROR_CRC; + } else { + rv = i2c_xfer_unlocked(port, addr_flags, 0, 0, data, + data_length, I2C_XFER_STOP); + if (rv) + continue; + } + + /* execution reaches here implies rv=0, so we can exit now */ + *read_len = data_length; + break; + } + + i2c_lock(port, 0); + return rv; +} + +int i2c_read_string(const int port, const uint16_t addr_flags, int offset, + uint8_t *data, int len) +{ + int read_len = 0; + int rv = 0; + + if (len == 0) + return EC_ERROR_INVAL; + + rv = i2c_read_sized_block(port, addr_flags, offset, data, len - 1, + &read_len); + data[read_len] = 0; + return rv; +} + +int i2c_read_block(const int port, const uint16_t addr_flags, int offset, + uint8_t *data, int len) +{ + int rv; + uint8_t reg_address = offset; + + rv = i2c_xfer(port, addr_flags, ®_address, 1, data, len); + return rv; +} + +int i2c_write_block(const int port, const uint16_t addr_flags, int offset, + const uint8_t *data, int len) +{ + int i, rv; + uint8_t reg_address = offset, pec = 0; + + if (!IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags)) + return EC_ERROR_UNIMPLEMENTED; + + if (IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags)) { + uint8_t addr_8bit = I2C_STRIP_FLAGS(addr_flags) << 1; + + pec = cros_crc8(&addr_8bit, sizeof(uint8_t)); + pec = cros_crc8_arg(®_address, sizeof(uint8_t), pec); + pec = cros_crc8_arg(data, len, pec); + } + + /* + * Split into two transactions to avoid the stack space consumption of + * appending the destination address with the data array. + */ + i2c_lock(port, 1); + for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { + rv = i2c_xfer_unlocked(port, addr_flags, ®_address, 1, NULL, + 0, I2C_XFER_START); + if (rv) + continue; + + if (IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(addr_flags)) { + rv = i2c_xfer_unlocked(port, addr_flags, data, len, + NULL, 0, 0); + if (rv) + continue; + + rv = i2c_xfer_unlocked(port, addr_flags, &pec, + sizeof(uint8_t), NULL, 0, + I2C_XFER_STOP); + if (rv) + continue; + } else { + rv = i2c_xfer_unlocked(port, addr_flags, data, len, + NULL, 0, I2C_XFER_STOP); + if (rv) + continue; + } + + /* execution reaches here implies rv=0, so we can exit now */ + break; + } + i2c_lock(port, 0); + + return rv; +} + +int i2c_freq_to_khz(enum i2c_freq freq) +{ + switch (freq) { + case I2C_FREQ_100KHZ: + return 100; + case I2C_FREQ_400KHZ: + return 400; + case I2C_FREQ_1000KHZ: + return 1000; + default: + return 0; + } +} + +enum i2c_freq i2c_khz_to_freq(int speed_khz) +{ + switch (speed_khz) { + case 100: + return I2C_FREQ_100KHZ; + case 400: + return I2C_FREQ_400KHZ; + case 1000: + return I2C_FREQ_1000KHZ; + default: + return I2C_FREQ_COUNT; + } +} + +int i2c_set_freq(int port, enum i2c_freq freq) +{ + int ret; + const struct i2c_port_t *cfg; + + cfg = get_i2c_port(port); + if (cfg == NULL) + return EC_ERROR_INVAL; + + if (!(cfg->flags & I2C_PORT_FLAG_DYNAMIC_SPEED)) + return EC_ERROR_UNIMPLEMENTED; + + i2c_lock(port, 1); + ret = chip_i2c_set_freq(port, freq); + i2c_lock(port, 0); + return ret; +} + +enum i2c_freq i2c_get_freq(int port) +{ + return chip_i2c_get_freq(port); +} + +/*****************************************************************************/ +/* Host commands */ + +#ifdef CONFIG_I2C_DEBUG_PASSTHRU +#define PTHRUPRINTS(format, args...) CPRINTS("I2C_PTHRU " format, ##args) +#define PTHRUPRINTF(format, args...) CPRINTF(format, ##args) +#else +#define PTHRUPRINTS(format, args...) +#define PTHRUPRINTF(format, args...) +#endif + +/** + * Perform the voluminous checking required for this message + * + * @param args Arguments + * @return 0 if OK, EC_RES_INVALID_PARAM on error + */ +static int check_i2c_params(const struct host_cmd_handler_args *args) +{ + const struct ec_params_i2c_passthru *params = args->params; + const struct ec_params_i2c_passthru_msg *msg; + int read_len = 0, write_len = 0; + unsigned int size; + int msgnum; + +#ifdef CONFIG_I2C_PASSTHRU_RESTRICTED + uint8_t cmd_id = 0xff; + const uint8_t *out; +#endif + + if (args->params_size < sizeof(*params)) { + PTHRUPRINTS("no params, params_size=%d, need at least %d", + args->params_size, sizeof(*params)); + return EC_RES_INVALID_PARAM; + } + size = sizeof(*params) + params->num_msgs * sizeof(*msg); + if (args->params_size < size) { + PTHRUPRINTS("params_size=%d, need at least %d", + args->params_size, size); + return EC_RES_INVALID_PARAM; + } + +#ifdef CONFIG_I2C_PASSTHRU_RESTRICTED + out = (uint8_t *)args->params + size; +#endif + + /* Loop and process messages */; + for (msgnum = 0, msg = params->msg; msgnum < params->num_msgs; + msgnum++, msg++) { + unsigned int addr_flags = msg->addr_flags; + + PTHRUPRINTS("port=%d, %s, addr=0x%x(7-bit), len=%d", + params->port, + addr_flags & EC_I2C_FLAG_READ ? "read" : "write", + addr_flags & EC_I2C_ADDR_MASK, msg->len); + + if (addr_flags & EC_I2C_FLAG_READ) { + read_len += msg->len; + } else { +#ifdef CONFIG_I2C_PASSTHRU_RESTRICTED + cmd_id = out[write_len]; +#endif + write_len += msg->len; + } +#ifdef CONFIG_I2C_PASSTHRU_RESTRICTED + if (system_is_locked()) { + const struct i2c_cmd_desc_t cmd_desc = { + .port = params->port, + .addr_flags = addr_flags, + .cmd = cmd_id, + }; + if (!board_allow_i2c_passthru(&cmd_desc)) + return EC_RES_ACCESS_DENIED; + } +#endif + } + + /* Check there is room for the data */ + if (args->response_max < + sizeof(struct ec_response_i2c_passthru) + read_len) { + PTHRUPRINTS("overflow1"); + return EC_RES_INVALID_PARAM; + } + + /* Must have bytes to write */ + if (args->params_size < size + write_len) { + PTHRUPRINTS("overflow2"); + return EC_RES_INVALID_PARAM; + } + + return EC_RES_SUCCESS; +} + +#ifdef CONFIG_I2C_VIRTUAL_BATTERY +static inline int is_i2c_port_virtual_battery(int port) +{ +#ifdef CONFIG_ZEPHYR + /* For Zephyr compare the actual device, which will be used in + * i2c_transfer function. + */ + return (i2c_get_device_for_port(port) == + i2c_get_device_for_port(I2C_PORT_VIRTUAL_BATTERY)); +#else + return (port == I2C_PORT_VIRTUAL_BATTERY); +#endif +} +#endif /* CONFIG_I2C_VIRTUAL_BATTERY */ + +static enum ec_status i2c_command_passthru(struct host_cmd_handler_args *args) +{ +#ifdef CONFIG_ZEPHYR + /* For Zephyr, convert the received remote port number to a port number + * used in EC. + */ + ((struct ec_params_i2c_passthru *)(args->params))->port = + i2c_get_port_from_remote_port( + ((struct ec_params_i2c_passthru *)(args->params))->port); +#endif + const struct ec_params_i2c_passthru *params = args->params; + const struct ec_params_i2c_passthru_msg *msg; + struct ec_response_i2c_passthru *resp = args->response; + const struct i2c_port_t *i2c_port; + const uint8_t *out; + int in_len; + int ret, i; + int port_is_locked = 0; + +#ifdef CONFIG_BATTERY_CUT_OFF + /* + * Some batteries would wake up after cut-off if we talk to it. + */ + if (battery_is_cut_off()) + return EC_RES_ACCESS_DENIED; +#endif + + i2c_port = get_i2c_port(params->port); + if (!i2c_port) + return EC_RES_INVALID_PARAM; + + ret = check_i2c_params(args); + if (ret) + return ret; + + if (port_protected[params->port]) { + if (!i2c_port->passthru_allowed) + return EC_RES_ACCESS_DENIED; + + for (i = 0; i < params->num_msgs; i++) { + if (!i2c_port->passthru_allowed( + i2c_port, params->msg[i].addr_flags)) + return EC_RES_ACCESS_DENIED; + } + } + + /* Loop and process messages */ + resp->i2c_status = 0; + out = (uint8_t *)args->params + sizeof(*params) + + params->num_msgs * sizeof(*msg); + in_len = 0; + + for (resp->num_msgs = 0, msg = params->msg; + resp->num_msgs < params->num_msgs; resp->num_msgs++, msg++) { + int xferflags = I2C_XFER_START; + int read_len = 0, write_len = 0; + int rv = 1; + + /* Have to remove the EC flags from the address flags */ + uint16_t addr_flags = msg->addr_flags & EC_I2C_ADDR_MASK; + + if (msg->addr_flags & EC_I2C_FLAG_READ) + read_len = msg->len; + else + write_len = msg->len; + + /* Set stop bit for last message */ + if (resp->num_msgs == params->num_msgs - 1) + xferflags |= I2C_XFER_STOP; + +#ifdef CONFIG_I2C_VIRTUAL_BATTERY + if (is_i2c_port_virtual_battery(params->port) && + addr_flags == VIRTUAL_BATTERY_ADDR_FLAGS) { + if (virtual_battery_handler(resp, in_len, &rv, + xferflags, read_len, + write_len, out)) + break; + } +#endif + /* Transfer next message */ + PTHRUPRINTS("xfer port=%x addr=0x%x rlen=%d flags=0x%x", + params->port, addr_flags, read_len, xferflags); + if (write_len) { + PTHRUPRINTF(" out:"); + for (i = 0; i < write_len; i++) + PTHRUPRINTF(" 0x%02x", out[i]); + PTHRUPRINTF("\n"); + } + if (rv) { + if (!port_is_locked) + i2c_lock(params->port, (port_is_locked = 1)); + rv = i2c_xfer_unlocked(params->port, addr_flags, out, + write_len, &resp->data[in_len], + read_len, xferflags); + } + + if (rv) { + /* Driver will have sent a stop bit here */ + if (rv == EC_ERROR_TIMEOUT) + resp->i2c_status = EC_I2C_STATUS_TIMEOUT; + else + resp->i2c_status = EC_I2C_STATUS_NAK; + break; + } + + in_len += read_len; + out += write_len; + } + args->response_size = sizeof(*resp) + in_len; + + /* Unlock port */ + if (port_is_locked) + i2c_lock(params->port, 0); + + /* + * Return success even if transfer failed so response is sent. Host + * will check message status to determine the transfer result. + */ + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_I2C_PASSTHRU, i2c_command_passthru, EC_VER_MASK(0)); + +__test_only void i2c_passthru_protect_reset(void) +{ + memset(port_protected, 0, sizeof(port_protected)); +} + +static void i2c_passthru_protect_port(uint32_t port) +{ + if (port < ARRAY_SIZE(port_protected)) + port_protected[port] = 1; + else + PTHRUPRINTS("Invalid I2C port %d to be protected\n", port); +} + +static void i2c_passthru_protect_tcpc_ports(void) +{ +#ifdef CONFIG_USB_PD_PORT_MAX_COUNT + int i; + + /* + * If WP is not enabled i.e. system is not locked leave the tunnels open + * so that factory line can do updates without a new RO BIOS. + */ + if (!system_is_locked()) { + CPRINTS("System unlocked, TCPC I2C tunnels may be unprotected"); + return; + } + + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + /* TCPC tunnel not configured. No need to protect anything */ + if (!I2C_STRIP_FLAGS(tcpc_config[i].i2c_info.addr_flags)) + continue; + i2c_passthru_protect_port(tcpc_config[i].i2c_info.port); + } +#endif +} + +static enum ec_status +i2c_command_passthru_protect(struct host_cmd_handler_args *args) +{ +#ifdef CONFIG_ZEPHYR + /* For Zephyr, convert the received remote port number to a port number + * used in EC. + */ + ((struct ec_params_i2c_passthru_protect *)(args->params)) + ->port = i2c_get_port_from_remote_port( + ((struct ec_params_i2c_passthru_protect *)(args->params))->port); +#endif + const struct ec_params_i2c_passthru_protect *params = args->params; + struct ec_response_i2c_passthru_protect *resp = args->response; + + if (args->params_size < sizeof(*params)) { + PTHRUPRINTS("protect no params, params_size=%d, ", + args->params_size); + return EC_RES_INVALID_PARAM; + } + + /* + * When calling the subcmd to protect all tcpcs, the i2c port isn't + * expected to be set in the args. So, putting a check here to avoid + * the get_i2c_port return error. + */ + if (params->subcmd == EC_CMD_I2C_PASSTHRU_PROTECT_ENABLE_TCPCS) { + if (IS_ENABLED(CONFIG_USB_POWER_DELIVERY) && + !IS_ENABLED(CONFIG_USB_PD_TCPM_STUB)) + i2c_passthru_protect_tcpc_ports(); + return EC_RES_SUCCESS; + } + + if (!get_i2c_port(params->port)) { + PTHRUPRINTS("protect invalid port %d", params->port); + return EC_RES_INVALID_PARAM; + } + + if (params->subcmd == EC_CMD_I2C_PASSTHRU_PROTECT_STATUS) { + if (args->response_max < sizeof(*resp)) { + PTHRUPRINTS("protect no response, " + "response_max=%d, need at least %d", + args->response_max, sizeof(*resp)); + return EC_RES_INVALID_PARAM; + } + + resp->status = port_protected[params->port]; + args->response_size = sizeof(*resp); + } else if (params->subcmd == EC_CMD_I2C_PASSTHRU_PROTECT_ENABLE) { + i2c_passthru_protect_port(params->port); + } else { + return EC_RES_INVALID_COMMAND; + } + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_I2C_PASSTHRU_PROTECT, i2c_command_passthru_protect, + EC_VER_MASK(0)); + +#ifdef CONFIG_HOSTCMD_I2C_CONTROL + +static enum ec_status i2c_command_control(struct host_cmd_handler_args *args) +{ +#ifdef CONFIG_ZEPHYR + /* For Zephyr, convert the received remote port number to a port number + * used in EC. + */ + ((struct ec_params_i2c_control *)(args->params))->port = + i2c_get_port_from_remote_port( + ((struct ec_params_i2c_control *)(args->params))->port); +#endif + const struct ec_params_i2c_control *params = args->params; + struct ec_response_i2c_control *resp = args->response; + enum i2c_freq old_i2c_freq; + enum i2c_freq new_i2c_freq; + const struct i2c_port_t *cfg; + uint16_t old_i2c_speed_khz; + uint16_t new_i2c_speed_khz; + enum ec_error_list rv; + int khz; + + cfg = get_i2c_port(params->port); + if (!cfg) + return EC_RES_INVALID_PARAM; + + switch (params->cmd) { + case EC_I2C_CONTROL_GET_SPEED: + old_i2c_freq = i2c_get_freq(cfg->port); + khz = i2c_freq_to_khz(old_i2c_freq); + old_i2c_speed_khz = (khz != 0) ? khz : + EC_I2C_CONTROL_SPEED_UNKNOWN; + break; + + case EC_I2C_CONTROL_SET_SPEED: + new_i2c_speed_khz = params->cmd_params.speed_khz; + new_i2c_freq = i2c_khz_to_freq(new_i2c_speed_khz); + if (new_i2c_freq == I2C_FREQ_COUNT) + return EC_RES_INVALID_PARAM; + + old_i2c_freq = i2c_get_freq(cfg->port); + old_i2c_speed_khz = i2c_freq_to_khz(old_i2c_freq); + + rv = i2c_set_freq(cfg->port, new_i2c_freq); + if (rv != EC_SUCCESS) + return EC_RES_ERROR; + + CPRINTS("I2C%d speed changed from %d kHz to %d kHz", + params->port, old_i2c_speed_khz, new_i2c_speed_khz); + break; + + default: + return EC_RES_INVALID_COMMAND; + } + + resp->cmd_response.speed_khz = old_i2c_speed_khz; + args->response_size = sizeof(*resp); + + return EC_RES_SUCCESS; +} + +DECLARE_HOST_COMMAND(EC_CMD_I2C_CONTROL, i2c_command_control, EC_VER_MASK(0)); + +#endif /* CONFIG_HOSTCMD_I2C_CONTROL */ + +/*****************************************************************************/ +/* Console commands */ + +#ifdef CONFIG_CMD_I2C_PROTECT +static int command_i2cprotect(int argc, const char **argv) +{ + if (argc == 1) { + int i, port; + + for (i = 0; i < i2c_ports_used; i++) { + port = i2c_ports[i].port; + ccprintf("Port %d: %s\n", port, + port_protected[port] ? "Protected" : + "Unprotected"); + } + } else if (argc == 2) { + int port; + char *e; + + port = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + if (!get_i2c_port(port)) { + ccprintf("i2c passthru protect invalid port %d\n", + port); + return EC_RES_INVALID_PARAM; + } + + port_protected[port] = 1; + } else { + return EC_ERROR_PARAM_COUNT; + } + + return EC_RES_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(i2cprotect, command_i2cprotect, "[port]", + "Protect I2C bus"); +#endif + +#ifdef CONFIG_CMD_I2C_STRESS_TEST +static void i2c_test_status(struct i2c_test_results *i2c_test, int test_dev) +{ + ccprintf("test_dev=%2d, ", test_dev); + ccprintf("r=%5d, rs=%5d, rf=%5d, ", + i2c_test->read_success + i2c_test->read_fail, + i2c_test->read_success, i2c_test->read_fail); + + ccprintf("w=%5d, ws=%5d, wf=%5d\n", + i2c_test->write_success + i2c_test->write_fail, + i2c_test->write_success, i2c_test->write_fail); + + i2c_test->read_success = 0; + i2c_test->read_fail = 0; + i2c_test->write_success = 0, i2c_test->write_fail = 0; +} + +#define I2C_STRESS_TEST_DATA_VERIFY_RETRY_COUNT 3 +static int command_i2ctest(int argc, const char **argv) +{ + char *e; + int i, j, rv; + uint32_t rand; + int data, data_verify; + int count = 10000; + int udelay = 100; + int test_dev = i2c_test_dev_used; + struct i2c_stress_test_dev *i2c_s_test = NULL; + struct i2c_test_reg_info *reg_s_info; + struct i2c_test_results *test_s_results; + + if (argc > 1) { + count = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + } + + if (argc > 2) { + udelay = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM3; + } + + if (argc > 3) { + test_dev = strtoi(argv[3], &e, 0); + if (*e || test_dev < 1 || test_dev > i2c_test_dev_used) + return EC_ERROR_PARAM4; + test_dev--; + } + + for (i = 0; i < count; i++) { + int port; + uint16_t addr_flags; + + if (!(i % 1000)) + ccprintf("running test %d\n", i); + + if (argc < 4) { + rand = get_time().val; + test_dev = rand % i2c_test_dev_used; + } + + port = i2c_stress_tests[test_dev].port; + addr_flags = i2c_stress_tests[test_dev].addr_flags; + i2c_s_test = i2c_stress_tests[test_dev].i2c_test; + reg_s_info = &i2c_s_test->reg_info; + test_s_results = &i2c_s_test->test_results; + + rand = get_time().val; + if (rand & 0x1) { + /* read */ + rv = i2c_s_test->i2c_read ? + i2c_s_test->i2c_read(port, addr_flags, + reg_s_info->read_reg, + &data) : + i2c_s_test->i2c_read_dev( + reg_s_info->read_reg, &data); + if (rv || data != reg_s_info->read_val) + test_s_results->read_fail++; + else + test_s_results->read_success++; + } else { + /* + * Reads are more than writes in the system. + * Read and then write same value to ensure we are + * not changing any settings. + */ + + /* Read the write register */ + rv = i2c_s_test->i2c_read ? + i2c_s_test->i2c_read(port, addr_flags, + reg_s_info->read_reg, + &data) : + i2c_s_test->i2c_read_dev( + reg_s_info->read_reg, &data); + if (rv) { + /* Skip writing invalid data */ + test_s_results->read_fail++; + continue; + } else + test_s_results->read_success++; + + j = I2C_STRESS_TEST_DATA_VERIFY_RETRY_COUNT; + do { + /* Write same value back */ + rv = i2c_s_test->i2c_write ? + i2c_s_test->i2c_write( + port, addr_flags, + reg_s_info->write_reg, + data) : + i2c_s_test->i2c_write_dev( + reg_s_info->write_reg, + data); + i++; + if (rv) { + /* Skip reading as write failed */ + test_s_results->write_fail++; + break; + } + test_s_results->write_success++; + + /* Read back to verify the data */ + rv = i2c_s_test->i2c_read ? + i2c_s_test->i2c_read( + port, addr_flags, + reg_s_info->read_reg, + &data_verify) : + i2c_s_test->i2c_read_dev( + reg_s_info->read_reg, + &data_verify); + i++; + if (rv) { + /* Read failed try next time */ + test_s_results->read_fail++; + break; + } else if (!rv && data != data_verify) { + /* Either data writes/read is wrong */ + j--; + } else { + j = 0; + test_s_results->read_success++; + } + } while (j); + } + + usleep(udelay); + } + + ccprintf("\n**********final result **********\n"); + + cflush(); + if (argc > 3) { + i2c_test_status(&i2c_s_test->test_results, test_dev + 1); + } else { + for (i = 0; i < i2c_test_dev_used; i++) { + i2c_s_test = i2c_stress_tests[i].i2c_test; + i2c_test_status(&i2c_s_test->test_results, i + 1); + msleep(100); + } + } + cflush(); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(i2ctest, command_i2ctest, "i2ctest count|udelay|dev", + "I2C stress test"); +#endif /* CONFIG_CMD_I2C_STRESS_TEST */ diff --git a/common/i2c_controller_cros_ec.c b/common/i2c_controller_cros_ec.c new file mode 100644 index 0000000000..d68f67c60e --- /dev/null +++ b/common/i2c_controller_cros_ec.c @@ -0,0 +1,548 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "builtin/assert.h" +#include "console.h" +#include "gpio.h" +#include "i2c.h" +#include "i2c_bitbang.h" +#include "i2c_private.h" +#include "printf.h" +#include "system.h" +#include "util.h" +#include "watchdog.h" + +/* This source file contains I2C controller code that is used only in legacy + * (CrOS EC) builds. + */ + +#ifdef CONFIG_ZEPHYR +#error "Don't use this source in Zephyr builds" +#endif + +/* Delay for bitbanging i2c corresponds roughly to 100kHz. */ +#define I2C_BITBANG_DELAY_US 5 + +/* Number of attempts to unwedge each pin. */ +#define UNWEDGE_SCL_ATTEMPTS 10 +#define UNWEDGE_SDA_ATTEMPTS 3 + +#define CPUTS(outstr) cputs(CC_I2C, outstr) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) + +int get_sda_from_i2c_port(int port, enum gpio_signal *sda) +{ + const struct i2c_port_t *i2c_port = get_i2c_port(port); + + /* Crash if the port given is not in the i2c_ports[] table. */ + ASSERT(i2c_port); + + /* Check if the SCL and SDA pins have been defined for this port. */ + if (i2c_port->scl == 0 && i2c_port->sda == 0) + return EC_ERROR_INVAL; + + *sda = i2c_port->sda; + return EC_SUCCESS; +} + +int get_scl_from_i2c_port(int port, enum gpio_signal *scl) +{ + const struct i2c_port_t *i2c_port = get_i2c_port(port); + + /* Crash if the port given is not in the i2c_ports[] table. */ + ASSERT(i2c_port); + + /* Check if the SCL and SDA pins have been defined for this port. */ + if (i2c_port->scl == 0 && i2c_port->sda == 0) + return EC_ERROR_INVAL; + + *scl = i2c_port->scl; + return EC_SUCCESS; +} + +void i2c_raw_set_scl(int port, int level) +{ + enum gpio_signal g; + + if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS) + gpio_set_level(g, level); +} + +void i2c_raw_set_sda(int port, int level) +{ + enum gpio_signal g; + + if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS) + gpio_set_level(g, level); +} + +int i2c_raw_mode(int port, int enable) +{ + enum gpio_signal sda, scl; + int ret_sda, ret_scl; + + /* Get the SDA and SCL pins for this port. If none, then return. */ + if (get_sda_from_i2c_port(port, &sda) != EC_SUCCESS) + return EC_ERROR_INVAL; + if (get_scl_from_i2c_port(port, &scl) != EC_SUCCESS) + return EC_ERROR_INVAL; + + if (enable) { + int raw_gpio_mode_flags = GPIO_ODR_HIGH; + + /* If the CLK line is 1.8V, then ensure we set 1.8V mode */ + if ((gpio_list + scl)->flags & GPIO_SEL_1P8V) + raw_gpio_mode_flags |= GPIO_SEL_1P8V; + + /* + * To enable raw mode, take out of alternate function mode and + * set the flags to open drain output. + */ + ret_sda = gpio_config_pin(MODULE_I2C, sda, 0); + ret_scl = gpio_config_pin(MODULE_I2C, scl, 0); + + gpio_set_flags(scl, raw_gpio_mode_flags); + gpio_set_flags(sda, raw_gpio_mode_flags); + } else { + /* + * Configure the I2C pins to exit raw mode and return + * to normal mode. + */ + ret_sda = gpio_config_pin(MODULE_I2C, sda, 1); + ret_scl = gpio_config_pin(MODULE_I2C, scl, 1); + } + + return ret_sda == EC_SUCCESS ? ret_scl : ret_sda; +} + +/* + * Unwedge the i2c bus for the given port. + * + * Some devices on our i2c busses keep power even if we get a reset. That + * means that they could be part way through a transaction and could be + * driving the bus in a way that makes it hard for us to talk on the bus. + * ...or they might listen to the next transaction and interpret it in a + * weird way. + * + * Note that devices could be in one of several states: + * - If a device got interrupted in a write transaction it will be watching + * for additional data to finish its write. It will probably be looking to + * ack the data (drive the data line low) after it gets everything. + * - If a device got interrupted while responding to a register read, it will + * be watching for clocks and will drive data out when it sees clocks. At + * the moment it might be trying to send out a 1 (so both clock and data + * may be high) or it might be trying to send out a 0 (so it's driving data + * low). + * + * We attempt to unwedge the bus by doing: + * - If SCL is being held low, then a peripheral is clock extending. The only + * thing we can do is try to wait until the peripheral stops clock extending. + * - Otherwise, we will toggle the clock until the peripheral releases the SDA + * line. Once the SDA line is released, try to send a STOP bit. Rinse and + * repeat until either the bus is normal, or we run out of attempts. + * + * Note this should work for most devices, but depending on the peripheral's + * i2c state machine, it may not be possible to unwedge the bus. + */ +int i2c_unwedge(int port) +{ + int i, j; + int ret = EC_SUCCESS; + +#ifdef CONFIG_I2C_BUS_MAY_BE_UNPOWERED + /* + * Don't try to unwedge the port if we know it's unpowered; it's futile. + */ + if (!board_is_i2c_port_powered(port)) { + CPRINTS("Skipping i2c unwedge, bus not powered."); + return EC_ERROR_NOT_POWERED; + } +#endif /* CONFIG_I2C_BUS_MAY_BE_UNPOWERED */ + + /* Try to put port in to raw bit bang mode. */ + if (i2c_raw_mode(port, 1) != EC_SUCCESS) + return EC_ERROR_UNKNOWN; + + /* + * If clock is low, wait for a while in case of clock stretched + * by a peripheral. + */ + if (!i2c_raw_get_scl(port)) { + for (i = 0;; i++) { + if (i >= UNWEDGE_SCL_ATTEMPTS) { + /* + * If we get here, a peripheral is holding the + * clock low and there is nothing we can do. + */ + CPRINTS("I2C%d unwedge failed, " + "SCL is held low", + port); + ret = EC_ERROR_UNKNOWN; + goto unwedge_done; + } + udelay(I2C_BITBANG_DELAY_US); + if (i2c_raw_get_scl(port)) + break; + } + } + + if (i2c_raw_get_sda(port)) + goto unwedge_done; + + CPRINTS("I2C%d unwedge called with SDA held low", port); + + /* Keep trying to unwedge the SDA line until we run out of attempts. */ + for (i = 0; i < UNWEDGE_SDA_ATTEMPTS; i++) { + /* Drive the clock high. */ + i2c_raw_set_scl(port, 1); + udelay(I2C_BITBANG_DELAY_US); + + /* + * Clock through the problem by clocking out 9 bits. If + * peripheral releases the SDA line, then we can stop clocking + * bits and send a STOP. + */ + for (j = 0; j < 9; j++) { + if (i2c_raw_get_sda(port)) + break; + + i2c_raw_set_scl(port, 0); + udelay(I2C_BITBANG_DELAY_US); + i2c_raw_set_scl(port, 1); + udelay(I2C_BITBANG_DELAY_US); + } + + /* Take control of SDA line and issue a STOP command. */ + i2c_raw_set_sda(port, 0); + udelay(I2C_BITBANG_DELAY_US); + i2c_raw_set_sda(port, 1); + udelay(I2C_BITBANG_DELAY_US); + + /* Check if the bus is unwedged. */ + if (i2c_raw_get_sda(port) && i2c_raw_get_scl(port)) + break; + } + + if (!i2c_raw_get_sda(port)) { + CPRINTS("I2C%d unwedge failed, SDA still low", port); + ret = EC_ERROR_UNKNOWN; + } + if (!i2c_raw_get_scl(port)) { + CPRINTS("I2C%d unwedge failed, SCL still low", port); + ret = EC_ERROR_UNKNOWN; + } + +unwedge_done: + /* Take port out of raw bit bang mode. */ + i2c_raw_mode(port, 0); + + return ret; +} + +#ifdef CONFIG_CMD_I2C_SCAN +static void scan_bus(int port, const char *desc) +{ + int level; + uint8_t tmp; + uint16_t addr_flags; + + ccprintf("Scanning %d %s", port, desc); + + i2c_lock(port, 1); + + /* Don't scan a busy port, since reads will just fail / time out */ + level = i2c_get_line_levels(port); + if (level != I2C_LINE_IDLE) { + ccprintf(": port busy (SDA=%d, SCL=%d)", + (level & I2C_LINE_SDA_HIGH) ? 1 : 0, + (level & I2C_LINE_SCL_HIGH) ? 1 : 0); + goto scan_bus_exit; + } + /* + * Only scan in the valid client device address range, otherwise some + * client devices stretch the clock in weird ways that prevent the + * discovery of other devices. + */ + for (addr_flags = I2C_FIRST_VALID_ADDR; + addr_flags <= I2C_LAST_VALID_ADDR; ++addr_flags) { + watchdog_reload(); /* Otherwise a full scan trips watchdog */ + ccputs("."); + + /* Do a single read */ + if (!i2c_xfer_unlocked(port, addr_flags, NULL, 0, &tmp, 1, + I2C_XFER_SINGLE)) + ccprintf("\n 0x%02x", addr_flags); + } + +scan_bus_exit: + i2c_lock(port, 0); + ccputs("\n"); +} + +static int command_scan(int argc, const char **argv) +{ + int port; + char *e; + const struct i2c_port_t *i2c_port; + + if (argc == 1) { + for (port = 0; port < i2c_ports_used; port++) + scan_bus(i2c_ports[port].port, i2c_ports[port].name); + + if (IS_ENABLED(CONFIG_I2C_BITBANG)) + for (port = 0; port < i2c_bitbang_ports_used; port++) + scan_bus(i2c_bitbang_ports[port].port, + i2c_bitbang_ports[port].name); + + return EC_SUCCESS; + } + + port = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + i2c_port = get_i2c_port(port); + if (!i2c_port) + return EC_ERROR_PARAM2; + + scan_bus(port, i2c_port->name); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(i2cscan, command_scan, "i2cscan [port]", + "Scan I2C ports for devices"); +#endif + +#ifdef CONFIG_CMD_I2C_XFER +static int command_i2cxfer(int argc, const char **argv) +{ + int port; + uint16_t addr_flags; + uint16_t offset = 0; + uint8_t offset_size = 0; + int v = 0; + uint8_t data[32]; + char *e; + int rv = 0; + + if (argc < 5) + return EC_ERROR_PARAM_COUNT; + + port = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + addr_flags = strtoi(argv[3], &e, 0); + if (*e) + return EC_ERROR_PARAM3; + + offset = strtoi(argv[4], &e, 0); + if (*e) + return EC_ERROR_PARAM4; + + offset_size = (strlen(argv[4]) == 6) ? 2 : 1; + + if (argc >= 6) { + v = strtoi(argv[5], &e, 0); + if (*e) + return EC_ERROR_PARAM5; + } + + if (strcasecmp(argv[1], "r") == 0) { + /* 8-bit read */ + if (offset_size == 2) + rv = i2c_read_offset16(port, addr_flags, offset, &v, 1); + else + rv = i2c_read8(port, addr_flags, offset, &v); + if (!rv) + ccprintf("0x%02x [%d]\n", v, v); + + } else if (strcasecmp(argv[1], "r16") == 0) { + /* 16-bit read */ + if (offset_size == 2) + rv = i2c_read_offset16(port, addr_flags, offset, &v, 2); + else + rv = i2c_read16(port, addr_flags, offset, &v); + if (!rv) + ccprintf("0x%04x [%d]\n", v, v); + + } else if (strcasecmp(argv[1], "rlen") == 0) { + /* Arbitrary length read; param5 = len */ + if (argc < 6 || v < 0 || v > sizeof(data)) + return EC_ERROR_PARAM5; + + rv = i2c_xfer(port, addr_flags, (uint8_t *)&offset, 1, data, v); + + if (!rv) { + char str_buf[hex_str_buf_size(v)]; + + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(data, v)); + ccprintf("Data: %s\n", str_buf); + } + + } else if (strcasecmp(argv[1], "w") == 0) { + /* 8-bit write */ + if (argc < 6) + return EC_ERROR_PARAM5; + if (offset_size == 2) + rv = i2c_write_offset16(port, addr_flags, offset, v, 1); + else + rv = i2c_write8(port, addr_flags, offset, v); + + } else if (strcasecmp(argv[1], "w16") == 0) { + /* 16-bit write */ + if (argc < 6) + return EC_ERROR_PARAM5; + if (offset_size == 2) + rv = i2c_write_offset16(port, addr_flags, offset, v, 2); + else + rv = i2c_write16(port, addr_flags, offset, v); +#ifdef CONFIG_CMD_I2C_XFER_RAW + } else if (strcasecmp(argv[1], "raw") == 0) { + /* [write_bytes..] */ + int i; + int write_count = 0, read_count = 0; + int xferflags = I2C_XFER_START; + + read_count = offset; + if (read_count < 0 || read_count > sizeof(data)) + return EC_ERROR_PARAM5; + + if (argc >= 6) { + /* Parse bytes to write */ + argc -= 5; + argv += 5; + write_count = argc; + if (write_count > sizeof(data)) { + ccprintf("Too many bytes to write\n"); + return EC_ERROR_PARAM_COUNT; + } + + for (i = 0; i < write_count; i++) { + data[i] = strtoi(argv[i], &e, 0); + if (*e) { + ccprintf("Bad write byte %d\n", i); + return EC_ERROR_INVAL; + } + } + } + + if (write_count) { + if (read_count == 0) + xferflags |= I2C_XFER_STOP; + ccprintf("Writing %d bytes\n", write_count); + i2c_lock(port, 1); + rv = i2c_xfer_unlocked(port, addr_flags, data, + write_count, NULL, 0, xferflags); + if (rv || read_count == 0) { + i2c_lock(port, 0); + return rv; + } + } + if (read_count) { + ccprintf("Reading %d bytes\n", read_count); + if (write_count == 0) + i2c_lock(port, 1); + rv = i2c_xfer_unlocked(port, addr_flags, NULL, 0, data, + read_count, + I2C_XFER_START | I2C_XFER_STOP); + i2c_lock(port, 0); + if (!rv) { + char str_buf[hex_str_buf_size(read_count)]; + + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(data, read_count)); + ccprintf("Data: %s\n", str_buf); + } + } +#endif /* CONFIG_CMD_I2C_XFER_RAW */ + } else { + return EC_ERROR_PARAM1; + } + + return rv; +} +DECLARE_CONSOLE_COMMAND(i2cxfer, command_i2cxfer, + "r/r16/rlen/w/w16 port addr offset [value | len]" +#ifdef CONFIG_CMD_I2C_XFER_RAW + "\nraw port addr read_count [bytes_to_write..]" +#endif /* CONFIG_CMD_I2C_XFER_RAW */ + , + "Read write I2C"); +#endif + +#ifdef CONFIG_CMD_I2C_SPEED + +static const char *const i2c_freq_str[] = { + [I2C_FREQ_1000KHZ] = "1000 kHz", + [I2C_FREQ_400KHZ] = "400 kHz", + [I2C_FREQ_100KHZ] = "100 kHz", + [I2C_FREQ_COUNT] = "unknown", +}; + +BUILD_ASSERT(ARRAY_SIZE(i2c_freq_str) == I2C_FREQ_COUNT + 1); + +static int command_i2c_speed(int argc, const char **argv) +{ + int port; + char *e; + enum i2c_freq freq; + enum i2c_freq new_freq = I2C_FREQ_COUNT; + + if (argc < 2 || argc > 3) + return EC_ERROR_PARAM_COUNT; + + port = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM1; + + if (port < 0 || port >= I2C_PORT_COUNT) + return EC_ERROR_INVAL; + + freq = i2c_get_freq(port); + if (freq < 0 || freq > I2C_FREQ_COUNT) + return EC_ERROR_UNKNOWN; + + if (argc == 3) { + int khz; + int rv; + + khz = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + switch (khz) { + case 100: + new_freq = I2C_FREQ_100KHZ; + break; + case 400: + new_freq = I2C_FREQ_400KHZ; + break; + case 1000: + new_freq = I2C_FREQ_1000KHZ; + break; + default: + return EC_ERROR_PARAM2; + } + rv = i2c_set_freq(port, new_freq); + if (rv != EC_SUCCESS) + return rv; + } + + if (new_freq != I2C_FREQ_COUNT) + ccprintf("Port %d speed changed from %s to %s\n", port, + i2c_freq_str[freq], i2c_freq_str[new_freq]); + else + ccprintf("Port %d speed is %s\n", port, i2c_freq_str[freq]); + + return EC_SUCCESS; +} + +DECLARE_CONSOLE_COMMAND(i2cspeed, command_i2c_speed, "port [speed in kHz]", + "Get or set I2C port speed"); + +#endif /* CONFIG_CMD_I2C_SPEED */ diff --git a/common/i2c_hid_touchpad.c b/common/i2c_hid_touchpad.c index 29122f83d6..2664dabe3e 100644 --- a/common/i2c_hid_touchpad.c +++ b/common/i2c_hid_touchpad.c @@ -1,32 +1,31 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "i2c_hid_touchpad.h" - #include "console.h" #include "hwtimer.h" +#include "i2c_hid_touchpad.h" #include "util.h" /* 2 bytes for length + 1 byte for report ID */ -#define I2C_HID_HEADER_SIZE 3 +#define I2C_HID_HEADER_SIZE 3 /* Report ID */ -#define REPORT_ID_TOUCH 0x01 -#define REPORT_ID_MOUSE 0x02 -#define REPORT_ID_DEVICE_CAPS 0x0A -#define REPORT_ID_DEVICE_CERT 0x0B -#define REPORT_ID_INPUT_MODE 0x0C -#define REPORT_ID_REPORTING 0x0D +#define REPORT_ID_TOUCH 0x01 +#define REPORT_ID_MOUSE 0x02 +#define REPORT_ID_DEVICE_CAPS 0x0A +#define REPORT_ID_DEVICE_CERT 0x0B +#define REPORT_ID_INPUT_MODE 0x0C +#define REPORT_ID_REPORTING 0x0D -#define INPUT_MODE_MOUSE 0x00 -#define INPUT_MODE_TOUCH 0x03 +#define INPUT_MODE_MOUSE 0x00 +#define INPUT_MODE_TOUCH 0x03 /* VID/PID/FW version */ -#if !defined(I2C_HID_TOUCHPAD_VENDOR_ID) || \ - !defined(I2C_HID_TOUCHPAD_PRODUCT_ID) || \ - !defined(I2C_HID_TOUCHPAD_FW_VERSION) +#if !defined(I2C_HID_TOUCHPAD_VENDOR_ID) || \ + !defined(I2C_HID_TOUCHPAD_PRODUCT_ID) || \ + !defined(I2C_HID_TOUCHPAD_FW_VERSION) #error "Must define touchpad VID/PID/FW version" #endif /* @@ -34,10 +33,9 @@ * * Physical dimensions are in the unit of mms. */ -#if !defined(I2C_HID_TOUCHPAD_MAX_X) || \ - !defined(I2C_HID_TOUCHPAD_MAX_Y) || \ - !defined(I2C_HID_TOUCHPAD_MAX_PHYSICAL_X) || \ - !defined(I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y) +#if !defined(I2C_HID_TOUCHPAD_MAX_X) || !defined(I2C_HID_TOUCHPAD_MAX_Y) || \ + !defined(I2C_HID_TOUCHPAD_MAX_PHYSICAL_X) || \ + !defined(I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y) #error "Must define finger maximum X/Y and physical dimensions" #endif /* @@ -49,9 +47,9 @@ * different data ranges. It is therefore recommended for the user to check the * device's spec and set these values manually. */ -#if !defined(I2C_HID_TOUCHPAD_MAX_WIDTH) || \ - !defined(I2C_HID_TOUCHPAD_MAX_HEIGHT) || \ - !defined(I2C_HID_TOUCHPAD_MAX_PRESSURE) +#if !defined(I2C_HID_TOUCHPAD_MAX_WIDTH) || \ + !defined(I2C_HID_TOUCHPAD_MAX_HEIGHT) || \ + !defined(I2C_HID_TOUCHPAD_MAX_PRESSURE) #error "Must define finger maximum width/height/pressure" #endif /* @@ -67,42 +65,37 @@ * This is a bit similar to the mouse CPI and is used by mouse reports only. */ #if !defined(I2C_HID_TOUCHPAD_MOUSE_SCALE_X) || \ - !defined(I2C_HID_TOUCHPAD_MOUSE_SCALE_Y) + !defined(I2C_HID_TOUCHPAD_MOUSE_SCALE_Y) #error "Must define mouse horizontal/vertical scaling factors" #endif /* Helper bit-op macros */ -#define N_BITS(n) \ -( \ - (n) < (1 << 1) ? 1 : \ - (n) < (1 << 2) ? 2 : \ - (n) < (1 << 3) ? 3 : \ - (n) < (1 << 4) ? 4 : \ - (n) < (1 << 5) ? 5 : \ - (n) < (1 << 6) ? 6 : \ - (n) < (1 << 7) ? 7 : \ - (n) < (1 << 8) ? 8 : \ - (n) < (1 << 9) ? 9 : \ - (n) < (1 << 10) ? 10 : \ - (n) < (1 << 11) ? 11 : \ - (n) < (1 << 12) ? 12 : \ - (n) < (1 << 13) ? 13 : \ - (n) < (1 << 14) ? 14 : \ - (n) < (1 << 15) ? 15 : \ - 16 \ -) +#define N_BITS(n) \ + ((n) < (1 << 1) ? 1 : \ + (n) < (1 << 2) ? 2 : \ + (n) < (1 << 3) ? 3 : \ + (n) < (1 << 4) ? 4 : \ + (n) < (1 << 5) ? 5 : \ + (n) < (1 << 6) ? 6 : \ + (n) < (1 << 7) ? 7 : \ + (n) < (1 << 8) ? 8 : \ + (n) < (1 << 9) ? 9 : \ + (n) < (1 << 10) ? 10 : \ + (n) < (1 << 11) ? 11 : \ + (n) < (1 << 12) ? 12 : \ + (n) < (1 << 13) ? 13 : \ + (n) < (1 << 14) ? 14 : \ + (n) < (1 << 15) ? 15 : \ + 16) /* We would need to pad some bits at the end of each finger struct to match * the allocation unit's boundary so the array indexing may work correctly. */ -#define N_VAR_BITS \ -( \ - N_BITS(I2C_HID_TOUCHPAD_MAX_X) + \ - N_BITS(I2C_HID_TOUCHPAD_MAX_Y) + \ - N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH) + \ - N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT) + \ - N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE) + \ - N_BITS(I2C_HID_TOUCHPAD_MAX_ORIENTATION) \ -) +#define N_VAR_BITS \ + (N_BITS(I2C_HID_TOUCHPAD_MAX_X) + N_BITS(I2C_HID_TOUCHPAD_MAX_Y) + \ + N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH) + \ + N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT) + \ + N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE) + \ + N_BITS(I2C_HID_TOUCHPAD_MAX_ORIENTATION)) #define N_PADDING_BITS ((DIV_ROUND_UP(N_VAR_BITS, 8) * 8) - N_VAR_BITS) #define N_BITS_ORIENTATION \ (N_BITS(I2C_HID_TOUCHPAD_MAX_ORIENTATION) + N_PADDING_BITS) @@ -121,45 +114,45 @@ struct finger { * identify unintended contacts or palms but is up to the OS * explanation. */ - uint8_t confidence:1; + uint8_t confidence : 1; /* * Whether a finger is touching the surface (leaving/left finger gets * 0). */ - uint8_t tip:1; + uint8_t tip : 1; /* * Whether a finger is within the sensor range. For example, hovering * fingers would have tip=0 and inrange=1. */ - uint8_t inrange:1; + uint8_t inrange : 1; /* * Contact id. This is like slot numbers in Linux MT-B. */ - uint8_t id:5; - uint16_t x:N_BITS(I2C_HID_TOUCHPAD_MAX_X); - uint16_t y:N_BITS(I2C_HID_TOUCHPAD_MAX_Y); - uint16_t width:N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH); - uint16_t height:N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT); - uint16_t pressure:N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE); - uint16_t orientation:N_BITS_ORIENTATION; + uint8_t id : 5; + uint16_t x : N_BITS(I2C_HID_TOUCHPAD_MAX_X); + uint16_t y : N_BITS(I2C_HID_TOUCHPAD_MAX_Y); + uint16_t width : N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH); + uint16_t height : N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT); + uint16_t pressure : N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE); + uint16_t orientation : N_BITS_ORIENTATION; } __packed; struct touch_report { - uint8_t button:1; - uint8_t count:7; + uint8_t button : 1; + uint8_t count : 7; uint16_t timestamp; struct finger finger[I2C_HID_TOUCHPAD_MAX_FINGERS]; } __packed; struct mouse_report { - uint8_t button1:1; + uint8_t button1 : 1; /* Windows expects at least two button usages in a mouse report. Many * touchpads on the Chromebook are a single clickable surface, so * button2 isn't used. That said, we may later report a button2 event if * necessary. */ - uint8_t button2:1; - uint8_t unused:6; + uint8_t button2 : 1; + uint8_t unused : 6; int8_t x; int8_t y; } __packed; @@ -173,231 +166,215 @@ struct mouse_report { */ static const uint8_t report_desc[] = { /* Mouse Collection */ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x02, /* Usage (Mouse) */ - 0xA1, 0x01, /* Collection (Application) */ - 0x85, REPORT_ID_MOUSE, /* Report ID (Mouse) */ - 0x09, 0x01, /* Usage (Pointer) */ - 0xA1, 0x00, /* Collection (Physical) */ - 0x05, 0x09, /* Usage Page (Button) */ - 0x19, 0x01, /* Usage Minimum (Button 1) */ - 0x29, 0x02, /* Usage Maximum (Button 2) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x75, 0x01, /* Report Size (1) */ - 0x95, 0x02, /* Report Count (2) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ - 0x95, 0x06, /* Report Count (6) */ - 0x81, 0x03, /* Input (Cnst,Var,Abs) */ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x30, /* Usage (X) */ - 0x09, 0x31, /* Usage (Y) */ - 0x15, 0x81, /* Logical Minimum (-127) */ - 0x25, 0x7F, /* Logical Maximum (127) */ - 0x75, 0x08, /* Report Size (8) */ - 0x95, 0x02, /* Report Count (2) */ - 0x81, 0x06, /* Input (Data,Var,Rel) */ - 0xC0, /* End Collection */ - 0xC0, /* End Collection */ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ + 0x09, 0x02, /* Usage (Mouse) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x85, REPORT_ID_MOUSE, /* Report ID (Mouse) */ + 0x09, 0x01, /* Usage (Pointer) */ + 0xA1, 0x00, /* Collection (Physical) */ + 0x05, 0x09, /* Usage Page (Button) */ + 0x19, 0x01, /* Usage Minimum (Button 1) */ + 0x29, 0x02, /* Usage Maximum (Button 2) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, 0x02, /* Report Count (2) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ + 0x95, 0x06, /* Report Count (6) */ + 0x81, 0x03, /* Input (Cnst,Var,Abs) */ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ + 0x09, 0x30, /* Usage (X) */ + 0x09, 0x31, /* Usage (Y) */ + 0x15, 0x81, /* Logical Minimum (-127) */ + 0x25, 0x7F, /* Logical Maximum (127) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x02, /* Report Count (2) */ + 0x81, 0x06, /* Input (Data,Var,Rel) */ + 0xC0, /* End Collection */ + 0xC0, /* End Collection */ /* Touchpad Collection */ - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x09, 0x05, /* Usage (Touch Pad) */ - 0xA1, 0x01, /* Collection (Application) */ - 0x85, REPORT_ID_TOUCH, /* Report ID (Touch) */ + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x09, 0x05, /* Usage (Touch Pad) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x85, REPORT_ID_TOUCH, /* Report ID (Touch) */ /* Button */ - 0x05, 0x09, /* Usage Page (Button) */ - 0x19, 0x01, /* Usage Minimum (0x01) */ - 0x29, 0x01, /* Usage Maximum (0x01) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x75, 0x01, /* Report Size (1) */ - 0x95, 0x01, /* Report Count (1) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ + 0x05, 0x09, /* Usage Page (Button) */ + 0x19, 0x01, /* Usage Minimum (0x01) */ + 0x29, 0x01, /* Usage Maximum (0x01) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, 0x01, /* Report Count (1) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ /* Contact count */ - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x09, 0x54, /* Usage (Contact count) */ - 0x25, I2C_HID_TOUCHPAD_MAX_FINGERS, /* Logical Max. (MAX_FINGERS) */ - 0x75, 0x07, /* Report Size (7) */ - 0x95, 0x01, /* Report Count (1) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x09, 0x54, /* Usage (Contact count) */ + 0x25, I2C_HID_TOUCHPAD_MAX_FINGERS, /* Logical Max. (MAX_FINGERS) */ + 0x75, 0x07, /* Report Size (7) */ + 0x95, 0x01, /* Report Count (1) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ /* Scan time */ - 0x55, 0x0C, /* Unit Exponent (-4) */ - 0x66, 0x01, 0x10, /* Unit (Seconds) */ - 0x47, 0xFF, 0xFF, 0x00, 0x00, /* Physical Maximum (65535) */ - 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535) */ - 0x75, 0x10, /* Report Size (16) */ - 0x95, 0x01, /* Report Count (1) */ - 0x05, 0x0D, /* Usage Page (Digitizers) */ - 0x09, 0x56, /* Usage (Scan Time) */ - 0x81, 0x02, /* Input (Data,Var,Abs) */ - -#define FINGER(FINGER_NUMBER) \ - /* Finger FINGER_NUMBER */ \ - 0x05, 0x0D, /* Usage Page (Digitizer) */ \ - 0x09, 0x22, /* Usage (Finger) */ \ - 0xA1, 0x02, /* Collection (Logical) */ \ - 0x09, 0x47, /* Usage (Confidence) */ \ - 0x09, 0x42, /* Usage (Tip Switch) */ \ - 0x09, 0x32, /* Usage (In Range) */ \ - 0x15, 0x00, /* Logical Minimum (0) */ \ - 0x25, 0x01, /* Logical Maximum (1) */ \ - 0x75, 0x01, /* Report Size (1) */ \ - 0x95, 0x03, /* Report Count (3) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x09, 0x51, /* Usage (Contact identifier) */ \ - 0x25, 0x1F, /* Logical Maximum (31) */ \ - 0x75, 0x05, /* Report Size (5) */ \ - 0x95, 0x01, /* Report Count (1) */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ - 0x09, 0x30, /* Usage (X) */ \ - 0x55, 0x0E, /* Unit Exponent (-2) */ \ - 0x65, 0x11, /* Unit (SI Linear, Length: cm) */ \ - 0x35, 0x00, /* Physical Minimum (0) */ \ - 0x46, I2C_HID_TOUCHPAD_MAX_PHYSICAL_X&0xff, \ - I2C_HID_TOUCHPAD_MAX_PHYSICAL_X>>8, \ - /* Physical Maximum */ \ - 0x26, I2C_HID_TOUCHPAD_MAX_X&0xff, I2C_HID_TOUCHPAD_MAX_X>>8, \ - /* Logical Maximum */ \ - 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_X), \ - /* Report Size */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x09, 0x31, /* Usage (Y) */ \ - 0x46, I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y&0xff, \ - I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y>>8, \ - /* Physical Maximum */ \ - 0x26, I2C_HID_TOUCHPAD_MAX_Y&0xff, I2C_HID_TOUCHPAD_MAX_Y>>8, \ - /* Logical Maximum */ \ - 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_Y), \ - /* Report Size */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x05, 0x0D, /* Usage Page (Digitizer) */ \ - 0x09, 0x48, /* Usage (Width) */ \ - 0x26, I2C_HID_TOUCHPAD_MAX_WIDTH&0xff, I2C_HID_TOUCHPAD_MAX_WIDTH>>8, \ - /* Logical Maximum */ \ - 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH), \ - /* Report Size */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x09, 0x49, /* Usage (Height) */ \ - 0x26, I2C_HID_TOUCHPAD_MAX_HEIGHT&0xff, I2C_HID_TOUCHPAD_MAX_HEIGHT>>8,\ - /* Logical Maximum */ \ - 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT), \ - /* Report Size */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x09, 0x30, /* Usage (Tip pressure) */ \ - 0x26, I2C_HID_TOUCHPAD_MAX_PRESSURE&0xff, \ - I2C_HID_TOUCHPAD_MAX_PRESSURE>>8, \ - /* Logical Maximum */ \ - 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE), \ - /* Report Size */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0x09, 0x3f, /* Usage (Azimuth Orientation) */ \ - 0x16, 0x00, 0x00, /* Logical Minimum (0) */ \ - 0x26, I2C_HID_TOUCHPAD_MAX_ORIENTATION&0xff, \ - I2C_HID_TOUCHPAD_MAX_ORIENTATION>>8, \ - /* Logical Maximum */ \ - 0x75, N_BITS_ORIENTATION, /* Report Size */ \ - 0x81, 0x02, /* Input (Data,Var,Abs) */ \ - 0xC0, /* End Collection */ - - FINGER(1) - FINGER(2) - FINGER(3) - FINGER(4) - FINGER(5) + 0x55, 0x0C, /* Unit Exponent (-4) */ + 0x66, 0x01, 0x10, /* Unit (Seconds) */ + 0x47, 0xFF, 0xFF, 0x00, 0x00, /* Physical Maximum (65535) */ + 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535) */ + 0x75, 0x10, /* Report Size (16) */ + 0x95, 0x01, /* Report Count (1) */ + 0x05, 0x0D, /* Usage Page (Digitizers) */ + 0x09, 0x56, /* Usage (Scan Time) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ + +#define FINGER(FINGER_NUMBER) \ + /* Finger FINGER_NUMBER */ \ + 0x05, 0x0D, /* Usage Page (Digitizer) */ \ + 0x09, 0x22, /* Usage (Finger) */ \ + 0xA1, 0x02, /* Collection (Logical) */ \ + 0x09, 0x47, /* Usage (Confidence) */ \ + 0x09, 0x42, /* Usage (Tip Switch) */ \ + 0x09, 0x32, /* Usage (In Range) */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x01, /* Logical Maximum (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x95, 0x03, /* Report Count (3) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x51, /* Usage (Contact identifier) */ \ + 0x25, 0x1F, /* Logical Maximum (31) */ \ + 0x75, 0x05, /* Report Size (5) */ \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ + 0x09, 0x30, /* Usage (X) */ \ + 0x55, 0x0E, /* Unit Exponent (-2) */ \ + 0x65, 0x11, /* Unit (SI Linear, Length: cm) */ \ + 0x35, 0x00, /* Physical Minimum (0) */ \ + 0x46, I2C_HID_TOUCHPAD_MAX_PHYSICAL_X & 0xff, \ + I2C_HID_TOUCHPAD_MAX_PHYSICAL_X >> 8, /* Physical Maximum \ + */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_X & 0xff, \ + I2C_HID_TOUCHPAD_MAX_X >> 8, /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_X), /* Report Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x31, /* Usage (Y) */ \ + 0x46, I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y & 0xff, \ + I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y >> 8, /* Physical Maximum \ + */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_Y & 0xff, \ + I2C_HID_TOUCHPAD_MAX_Y >> 8, /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_Y), /* Report Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x05, 0x0D, /* Usage Page (Digitizer) */ \ + 0x09, 0x48, /* Usage (Width) */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_WIDTH & 0xff, \ + I2C_HID_TOUCHPAD_MAX_WIDTH >> 8, /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH), /* Report Size \ + */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x49, /* Usage (Height) */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_HEIGHT & 0xff, \ + I2C_HID_TOUCHPAD_MAX_HEIGHT >> 8, /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT), /* Report Size \ + */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x30, /* Usage (Tip pressure) */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_PRESSURE & 0xff, \ + I2C_HID_TOUCHPAD_MAX_PRESSURE >> 8, /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE), /* Report \ + Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x3f, /* Usage (Azimuth Orientation) */ \ + 0x16, 0x00, 0x00, /* Logical Minimum (0) */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_ORIENTATION & 0xff, \ + I2C_HID_TOUCHPAD_MAX_ORIENTATION >> 8, /* Logical Maximum \ + */ \ + 0x75, N_BITS_ORIENTATION, /* Report Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0xC0, /* End Collection */ + + FINGER(1) FINGER(2) FINGER(3) FINGER(4) FINGER(5) #undef FINGER - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x85, REPORT_ID_DEVICE_CAPS, /* Report ID (Device Capabilities) */ - 0x09, 0x55, /* Usage (Contact Count Maximum) */ - 0x09, 0x59, /* Usage (Pad Type) */ - 0x75, 0x08, /* Report Size (8) */ - 0x95, 0x02, /* Report Count (2) */ - 0x25, 0x0F, /* Logical Maximum (15) */ - 0xB1, 0x02, /* Feature (Data,Var,Abs) */ - 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */ - 0x85, REPORT_ID_DEVICE_CERT, /* Report ID (Device Certification) */ - 0x09, 0xC5, /* Usage (Vendor Usage 0xC5) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ - 0x75, 0x08, /* Report Size (8) */ - 0x96, 0x00, 0x01, /* Report Count (256) */ - 0xB1, 0x02, /* Feature (Data,Var,Abs) */ - 0xC0, /* End Collection */ + 0x05, + 0x0D, /* Usage Page (Digitizer) */ + 0x85, REPORT_ID_DEVICE_CAPS, /* Report ID (Device Capabilities) */ + 0x09, 0x55, /* Usage (Contact Count Maximum) */ + 0x09, 0x59, /* Usage (Pad Type) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x02, /* Report Count (2) */ + 0x25, 0x0F, /* Logical Maximum (15) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */ + 0x85, REPORT_ID_DEVICE_CERT, /* Report ID (Device Certification) */ + 0x09, 0xC5, /* Usage (Vendor Usage 0xC5) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ + 0x75, 0x08, /* Report Size (8) */ + 0x96, 0x00, 0x01, /* Report Count (256) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + 0xC0, /* End Collection */ /* Configuration Collection */ - 0x05, 0x0D, /* Usage Page (Digitizer) */ - 0x09, 0x0E, /* Usage (Configuration) */ - 0xA1, 0x01, /* Collection (Application) */ - 0x85, REPORT_ID_INPUT_MODE, /* Report ID (Input Mode) */ - 0x09, 0x22, /* Usage (Finger) */ - 0xA1, 0x02, /* Collection (Logical) */ - 0x09, 0x52, /* Usage (Input Mode) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x0F, /* Logical Maximum (15) */ - 0x75, 0x08, /* Report Size (8) */ - 0x95, 0x01, /* Report Count (1) */ - 0xB1, 0x02, /* Feature (Data,Var,Abs) */ - 0xC0, /* End Collection */ - 0x09, 0x22, /* Usage (Finger) */ - 0xA1, 0x00, /* Collection (Physical) */ - 0x85, REPORT_ID_REPORTING, /* Report ID (Selective Reporting)*/ - 0x09, 0x57, /* Usage (Surface Switch) */ - 0x09, 0x58, /* Usage (Button Switch) */ - 0x75, 0x04, /* Report Size (4) */ - 0x95, 0x02, /* Report Count (2) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0xB1, 0x02, /* Feature (Data,Var,Abs) */ - 0xC0, /* End Collection */ - 0xC0, /* End Collection */ + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x09, 0x0E, /* Usage (Configuration) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x85, REPORT_ID_INPUT_MODE, /* Report ID (Input Mode) */ + 0x09, 0x22, /* Usage (Finger) */ + 0xA1, 0x02, /* Collection (Logical) */ + 0x09, 0x52, /* Usage (Input Mode) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x0F, /* Logical Maximum (15) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x01, /* Report Count (1) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + 0xC0, /* End Collection */ + 0x09, 0x22, /* Usage (Finger) */ + 0xA1, 0x00, /* Collection (Physical) */ + 0x85, REPORT_ID_REPORTING, /* Report ID (Selective Reporting)*/ + 0x09, 0x57, /* Usage (Surface Switch) */ + 0x09, 0x58, /* Usage (Button Switch) */ + 0x75, 0x04, /* Report Size (4) */ + 0x95, 0x02, /* Report Count (2) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + 0xC0, /* End Collection */ + 0xC0, /* End Collection */ }; static const uint8_t device_caps[] = { - I2C_HID_TOUCHPAD_MAX_FINGERS, /* Contact Count Maximum */ - 0x00, /* Pad Type: Depressible click-pad */ + I2C_HID_TOUCHPAD_MAX_FINGERS, /* Contact Count Maximum */ + 0x00, /* Pad Type: Depressible click-pad */ }; /* A 256-byte default blob for the 'device certification status' feature report * expected by Windows. */ static const uint8_t device_cert[] = { - 0xFC, 0x28, 0xFE, 0x84, 0x40, 0xCB, 0x9A, 0x87, - 0x0D, 0xBE, 0x57, 0x3C, 0xB6, 0x70, 0x09, 0x88, - 0x07, 0x97, 0x2D, 0x2B, 0xE3, 0x38, 0x34, 0xB6, - 0x6C, 0xED, 0xB0, 0xF7, 0xE5, 0x9C, 0xF6, 0xC2, - 0x2E, 0x84, 0x1B, 0xE8, 0xB4, 0x51, 0x78, 0x43, - 0x1F, 0x28, 0x4B, 0x7C, 0x2D, 0x53, 0xAF, 0xFC, - 0x47, 0x70, 0x1B, 0x59, 0x6F, 0x74, 0x43, 0xC4, - 0xF3, 0x47, 0x18, 0x53, 0x1A, 0xA2, 0xA1, 0x71, - 0xC7, 0x95, 0x0E, 0x31, 0x55, 0x21, 0xD3, 0xB5, - 0x1E, 0xE9, 0x0C, 0xBA, 0xEC, 0xB8, 0x89, 0x19, - 0x3E, 0xB3, 0xAF, 0x75, 0x81, 0x9D, 0x53, 0xB9, - 0x41, 0x57, 0xF4, 0x6D, 0x39, 0x25, 0x29, 0x7C, - 0x87, 0xD9, 0xB4, 0x98, 0x45, 0x7D, 0xA7, 0x26, - 0x9C, 0x65, 0x3B, 0x85, 0x68, 0x89, 0xD7, 0x3B, - 0xBD, 0xFF, 0x14, 0x67, 0xF2, 0x2B, 0xF0, 0x2A, - 0x41, 0x54, 0xF0, 0xFD, 0x2C, 0x66, 0x7C, 0xF8, - 0xC0, 0x8F, 0x33, 0x13, 0x03, 0xF1, 0xD3, 0xC1, - 0x0B, 0x89, 0xD9, 0x1B, 0x62, 0xCD, 0x51, 0xB7, - 0x80, 0xB8, 0xAF, 0x3A, 0x10, 0xC1, 0x8A, 0x5B, - 0xE8, 0x8A, 0x56, 0xF0, 0x8C, 0xAA, 0xFA, 0x35, - 0xE9, 0x42, 0xC4, 0xD8, 0x55, 0xC3, 0x38, 0xCC, - 0x2B, 0x53, 0x5C, 0x69, 0x52, 0xD5, 0xC8, 0x73, - 0x02, 0x38, 0x7C, 0x73, 0xB6, 0x41, 0xE7, 0xFF, - 0x05, 0xD8, 0x2B, 0x79, 0x9A, 0xE2, 0x34, 0x60, - 0x8F, 0xA3, 0x32, 0x1F, 0x09, 0x78, 0x62, 0xBC, - 0x80, 0xE3, 0x0F, 0xBD, 0x65, 0x20, 0x08, 0x13, - 0xC1, 0xE2, 0xEE, 0x53, 0x2D, 0x86, 0x7E, 0xA7, - 0x5A, 0xC5, 0xD3, 0x7D, 0x98, 0xBE, 0x31, 0x48, - 0x1F, 0xFB, 0xDA, 0xAF, 0xA2, 0xA8, 0x6A, 0x89, - 0xD6, 0xBF, 0xF2, 0xD3, 0x32, 0x2A, 0x9A, 0xE4, - 0xCF, 0x17, 0xB7, 0xB8, 0xF4, 0xE1, 0x33, 0x08, - 0x24, 0x8B, 0xC4, 0x43, 0xA5, 0xE5, 0x24, 0xC2, + 0xFC, 0x28, 0xFE, 0x84, 0x40, 0xCB, 0x9A, 0x87, 0x0D, 0xBE, 0x57, 0x3C, + 0xB6, 0x70, 0x09, 0x88, 0x07, 0x97, 0x2D, 0x2B, 0xE3, 0x38, 0x34, 0xB6, + 0x6C, 0xED, 0xB0, 0xF7, 0xE5, 0x9C, 0xF6, 0xC2, 0x2E, 0x84, 0x1B, 0xE8, + 0xB4, 0x51, 0x78, 0x43, 0x1F, 0x28, 0x4B, 0x7C, 0x2D, 0x53, 0xAF, 0xFC, + 0x47, 0x70, 0x1B, 0x59, 0x6F, 0x74, 0x43, 0xC4, 0xF3, 0x47, 0x18, 0x53, + 0x1A, 0xA2, 0xA1, 0x71, 0xC7, 0x95, 0x0E, 0x31, 0x55, 0x21, 0xD3, 0xB5, + 0x1E, 0xE9, 0x0C, 0xBA, 0xEC, 0xB8, 0x89, 0x19, 0x3E, 0xB3, 0xAF, 0x75, + 0x81, 0x9D, 0x53, 0xB9, 0x41, 0x57, 0xF4, 0x6D, 0x39, 0x25, 0x29, 0x7C, + 0x87, 0xD9, 0xB4, 0x98, 0x45, 0x7D, 0xA7, 0x26, 0x9C, 0x65, 0x3B, 0x85, + 0x68, 0x89, 0xD7, 0x3B, 0xBD, 0xFF, 0x14, 0x67, 0xF2, 0x2B, 0xF0, 0x2A, + 0x41, 0x54, 0xF0, 0xFD, 0x2C, 0x66, 0x7C, 0xF8, 0xC0, 0x8F, 0x33, 0x13, + 0x03, 0xF1, 0xD3, 0xC1, 0x0B, 0x89, 0xD9, 0x1B, 0x62, 0xCD, 0x51, 0xB7, + 0x80, 0xB8, 0xAF, 0x3A, 0x10, 0xC1, 0x8A, 0x5B, 0xE8, 0x8A, 0x56, 0xF0, + 0x8C, 0xAA, 0xFA, 0x35, 0xE9, 0x42, 0xC4, 0xD8, 0x55, 0xC3, 0x38, 0xCC, + 0x2B, 0x53, 0x5C, 0x69, 0x52, 0xD5, 0xC8, 0x73, 0x02, 0x38, 0x7C, 0x73, + 0xB6, 0x41, 0xE7, 0xFF, 0x05, 0xD8, 0x2B, 0x79, 0x9A, 0xE2, 0x34, 0x60, + 0x8F, 0xA3, 0x32, 0x1F, 0x09, 0x78, 0x62, 0xBC, 0x80, 0xE3, 0x0F, 0xBD, + 0x65, 0x20, 0x08, 0x13, 0xC1, 0xE2, 0xEE, 0x53, 0x2D, 0x86, 0x7E, 0xA7, + 0x5A, 0xC5, 0xD3, 0x7D, 0x98, 0xBE, 0x31, 0x48, 0x1F, 0xFB, 0xDA, 0xAF, + 0xA2, 0xA8, 0x6A, 0x89, 0xD6, 0xBF, 0xF2, 0xD3, 0x32, 0x2A, 0x9A, 0xE4, + 0xCF, 0x17, 0xB7, 0xB8, 0xF4, 0xE1, 0x33, 0x08, 0x24, 0x8B, 0xC4, 0x43, + 0xA5, 0xE5, 0x24, 0xC2, }; #define MAX_SIZEOF(a, b) (sizeof(a) > sizeof(b) ? sizeof(a) : sizeof(b)) @@ -431,7 +408,7 @@ static bool pending_probe; static bool pending_reset; /* Reports (double buffered) */ -#define MAX_REPORT_CNT 2 +#define MAX_REPORT_CNT 2 static struct touch_report touch_reports[MAX_REPORT_CNT]; static struct mouse_report mouse_reports[MAX_REPORT_CNT]; @@ -448,8 +425,8 @@ static uint8_t input_mode; * |reporting.button_switch|, respectively. */ struct selective_reporting { - uint8_t surface_switch:4; - uint8_t button_switch:4; + uint8_t surface_switch : 4; + uint8_t button_switch : 4; } __packed; static struct selective_reporting reporting; @@ -568,7 +545,7 @@ int i2c_hid_touchpad_process(unsigned int len, uint8_t *buffer, break; case I2C_HID_COMMAND_REGISTER: *cmd = i2c_hid_touchpad_command_process(len, buffer, - send_response, data); + send_response, data); break; default: /* Unknown register has been received. */ @@ -697,9 +674,9 @@ void i2c_hid_compile_report(struct touchpad_event *event) touch->finger[i].pressure = event->finger[i].pressure; if (event->finger[i].is_palm) touch->finger[i].pressure = - I2C_HID_TOUCHPAD_MAX_PRESSURE; + I2C_HID_TOUCHPAD_MAX_PRESSURE; touch->finger[i].orientation = - event->finger[i].orientation; + event->finger[i].orientation; contact_num++; } else if (touch_old->finger[i].tip) { /* diff --git a/common/i2c_master.c b/common/i2c_master.c deleted file mode 100644 index f078e690f7..0000000000 --- a/common/i2c_master.c +++ /dev/null @@ -1,1665 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* I2C cross-platform code for Chrome EC */ - -#include "battery.h" -#include "clock.h" -#include "charge_state.h" -#include "console.h" -#include "crc8.h" -#include "host_command.h" -#include "gpio.h" -#include "i2c.h" -#include "i2c_bitbang.h" -#include "i2c_private.h" -#include "system.h" -#include "task.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "util.h" -#include "watchdog.h" -#include "virtual_battery.h" - -/* Delay for bitbanging i2c corresponds roughly to 100kHz. */ -#define I2C_BITBANG_DELAY_US 5 - -/* Number of attempts to unwedge each pin. */ -#define UNWEDGE_SCL_ATTEMPTS 10 -#define UNWEDGE_SDA_ATTEMPTS 3 - -#define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) - -/* Only chips with multi-port controllers will define I2C_CONTROLLER_COUNT */ -#ifndef I2C_CONTROLLER_COUNT -#define I2C_CONTROLLER_COUNT I2C_PORT_COUNT -#endif - -#ifndef CONFIG_I2C_BITBANG -#define I2C_BITBANG_PORT_COUNT 0 -#endif - -static struct mutex port_mutex[I2C_CONTROLLER_COUNT + I2C_BITBANG_PORT_COUNT]; -/* A bitmap of the controllers which are currently servicing a request. */ -static uint32_t i2c_port_active_list; -BUILD_ASSERT(ARRAY_SIZE(port_mutex) < 32); -static uint8_t port_protected[I2C_PORT_COUNT + I2C_BITBANG_PORT_COUNT]; - -/** - * Non-deterministically test the lock status of the port. If another task - * has locked the port and the caller is accessing it illegally, then this test - * will incorrectly return true. However, callers which failed to statically - * lock the port will fail quickly. - */ -static int i2c_port_is_locked(int port) -{ -#ifdef CONFIG_I2C_MULTI_PORT_CONTROLLER - /* Test the controller, not the port */ - port = i2c_port_to_controller(port); -#endif - /* can't lock a non-existing port */ - if (port < 0) - return 0; - - return (i2c_port_active_list >> port) & 1; -} - - -const struct i2c_port_t *get_i2c_port(const int port) -{ - int i; - - /* Find the matching port in i2c_ports[] table. */ - for (i = 0; i < i2c_ports_used; i++) { - if (i2c_ports[i].port == port) - return &i2c_ports[i]; - } - - if (IS_ENABLED(CONFIG_I2C_BITBANG)) { - for (i = 0; i < i2c_bitbang_ports_used; i++) { - if (i2c_bitbang_ports[i].port == port) - return &i2c_bitbang_ports[i]; - } - } - - return NULL; -} - -static int chip_i2c_xfer_with_notify(const int port, - const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) -{ - int ret; - uint16_t addr_flags = slave_addr_flags; - const struct i2c_port_t *i2c_port = get_i2c_port(port); - - if (IS_ENABLED(CONFIG_I2C_XFER_BOARD_CALLBACK)) - i2c_start_xfer_notify(port, slave_addr_flags); - - if (IS_ENABLED(CONFIG_SMBUS_PEC)) - /* - * Since we've done PEC processing here, - * remove the flag so it won't confuse chip driver. - */ - addr_flags &= ~I2C_FLAG_PEC; - if (i2c_port->drv) - ret = i2c_port->drv->xfer(i2c_port, addr_flags, - out, out_size, in, in_size, flags); - else - ret = chip_i2c_xfer(port, addr_flags, - out, out_size, in, in_size, flags); - - if (IS_ENABLED(CONFIG_I2C_XFER_BOARD_CALLBACK)) - i2c_end_xfer_notify(port, slave_addr_flags); - - if (IS_ENABLED(CONFIG_I2C_DEBUG)) { - i2c_trace_notify(port, slave_addr_flags, out, out_size, - in, in_size); - } - - return ret; -} - -#ifdef CONFIG_I2C_XFER_LARGE_READ -/* - * Internal function that splits reading into multiple chip_i2c_xfer() calls - * if in_size exceeds CONFIG_I2C_CHIP_MAX_READ_SIZE. - */ -static int i2c_xfer_no_retry(const int port, - const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) -{ - int ret; - int out_flags = flags & I2C_XFER_START; - int in_chunk_size = MIN(in_size, CONFIG_I2C_CHIP_MAX_READ_SIZE); - - in_size -= in_chunk_size; - out_flags |= !in_size ? (flags & I2C_XFER_STOP) : 0; - ret = chip_i2c_xfer_with_notify(port, slave_addr_flags, - out, out_size, in, - in_chunk_size, out_flags); - in += in_chunk_size; - while (in_size && ret == EC_SUCCESS) { - in_chunk_size = MIN(in_size, CONFIG_I2C_CHIP_MAX_READ_SIZE); - in_size -= in_chunk_size; - ret = chip_i2c_xfer_with_notify(port, slave_addr_flags, - NULL, 0, in, - in_chunk_size, !in_size ? (flags & I2C_XFER_STOP) : 0); - in += in_chunk_size; - } - return ret; -} -#endif /* CONFIG_I2C_XFER_LARGE_READ */ - -int i2c_xfer_unlocked(const int port, - const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) -{ - int i; - int ret = EC_SUCCESS; - - uint16_t addr_flags = slave_addr_flags & ~I2C_FLAG_PEC; - - if (!i2c_port_is_locked(port)) { - CPUTS("Access I2C without lock!"); - return EC_ERROR_INVAL; - } - - for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { -#ifdef CONFIG_I2C_XFER_LARGE_READ - ret = i2c_xfer_no_retry(port, addr_flags, - out, out_size, in, - in_size, flags); -#else - ret = chip_i2c_xfer_with_notify(port, addr_flags, - out, out_size, - in, in_size, flags); -#endif /* CONFIG_I2C_XFER_LARGE_READ */ - if (ret != EC_ERROR_BUSY) - break; - } - return ret; -} - -int i2c_xfer(const int port, - const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size) -{ - int rv; - - i2c_lock(port, 1); - rv = i2c_xfer_unlocked(port, slave_addr_flags, - out, out_size, in, in_size, - I2C_XFER_SINGLE); - i2c_lock(port, 0); - - return rv; -} - -void i2c_lock(int port, int lock) -{ -#ifdef CONFIG_I2C_MULTI_PORT_CONTROLLER - /* Lock the controller, not the port */ - port = i2c_port_to_controller(port); -#endif - if (port < 0) - return; - - if (lock) { - mutex_lock(port_mutex + port); - - /* Disable interrupt during changing counter for preemption. */ - interrupt_disable(); - - i2c_port_active_list |= 1 << port; - /* Ec cannot enter sleep if there's any i2c port active. */ - disable_sleep(SLEEP_MASK_I2C_MASTER); - - interrupt_enable(); - } else { - interrupt_disable(); - - i2c_port_active_list &= ~BIT(port); - /* Once there is no i2c port active, enable sleep bit of i2c. */ - if (!i2c_port_active_list) - enable_sleep(SLEEP_MASK_I2C_MASTER); - - interrupt_enable(); - - mutex_unlock(port_mutex + port); - } -} - -void i2c_prepare_sysjump(void) -{ - int i; - - /* Lock all i2c controllers */ - for (i = 0; i < ARRAY_SIZE(port_mutex); ++i) - mutex_lock(port_mutex + i); -} - -/* i2c_readN with optional error checking */ -static int i2c_read(const int port, const uint16_t slave_addr_flags, - uint8_t reg, uint8_t *in, int in_size) -{ - if (!IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(slave_addr_flags)) - return EC_ERROR_UNIMPLEMENTED; - - if (IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(slave_addr_flags)) { - int i, rv; - /* addr_8bit = 7 bit addr_flags + 1 bit r/w */ - uint8_t addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; - uint8_t out[3] = {addr_8bit, reg, addr_8bit | 1}; - uint8_t pec_local = 0, pec_remote; - - i2c_lock(port, 1); - for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { - rv = i2c_xfer_unlocked(port, slave_addr_flags, ®, 1, - in, in_size, I2C_XFER_START); - if (rv) - continue; - - rv = i2c_xfer_unlocked(port, slave_addr_flags, NULL, 0, - &pec_remote, 1, I2C_XFER_STOP); - if (rv) - continue; - - pec_local = crc8(out, ARRAY_SIZE(out)); - pec_local = crc8_arg(in, in_size, pec_local); - if (pec_local == pec_remote) - break; - - rv = EC_ERROR_CRC; - } - i2c_lock(port, 0); - - return rv; - } - - return i2c_xfer(port, slave_addr_flags, ®, 1, in, in_size); -} - -/* i2c_writeN with optional error checking */ -static int i2c_write(const int port, const uint16_t slave_addr_flags, - const uint8_t *out, int out_size) -{ - if (!IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(slave_addr_flags)) - return EC_ERROR_UNIMPLEMENTED; - - if (IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(slave_addr_flags)) { - int i, rv; - uint8_t addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; - uint8_t pec; - - pec = crc8(&addr_8bit, 1); - pec = crc8_arg(out, out_size, pec); - - i2c_lock(port, 1); - for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { - rv = i2c_xfer_unlocked(port, slave_addr_flags, - out, out_size, NULL, 0, - I2C_XFER_START); - if (rv) - continue; - - rv = i2c_xfer_unlocked(port, slave_addr_flags, - &pec, 1, NULL, 0, - I2C_XFER_STOP); - if (!rv) - break; - } - i2c_lock(port, 0); - - return rv; - } - - return i2c_xfer(port, slave_addr_flags, out, out_size, NULL, 0); -} - -int i2c_read32(const int port, - const uint16_t slave_addr_flags, - int offset, int *data) -{ - int rv; - uint8_t reg, buf[sizeof(uint32_t)]; - - reg = offset & 0xff; - /* I2C read 32-bit word: transmit 8-bit offset, and read 32bits */ - rv = i2c_read(port, slave_addr_flags, reg, buf, sizeof(uint32_t)); - - if (rv) - return rv; - - if (I2C_IS_BIG_ENDIAN(slave_addr_flags)) - *data = ((int)buf[0] << 24) | ((int)buf[1] << 16) | - ((int)buf[0] << 8) | buf[1]; - else - *data = ((int)buf[3] << 24) | ((int)buf[2] << 16) | - ((int)buf[1] << 8) | buf[0]; - - return EC_SUCCESS; -} - -int i2c_write32(const int port, - const uint16_t slave_addr_flags, - int offset, int data) -{ - uint8_t buf[1 + sizeof(uint32_t)]; - - buf[0] = offset & 0xff; - - if (I2C_IS_BIG_ENDIAN(slave_addr_flags)) { - buf[1] = (data >> 24) & 0xff; - buf[2] = (data >> 16) & 0xff; - buf[3] = (data >> 8) & 0xff; - buf[4] = data & 0xff; - } else { - buf[1] = data & 0xff; - buf[2] = (data >> 8) & 0xff; - buf[3] = (data >> 16) & 0xff; - buf[4] = (data >> 24) & 0xff; - } - - return i2c_write(port, slave_addr_flags, buf, sizeof(uint32_t) + 1); -} - -int i2c_read16(const int port, - const uint16_t slave_addr_flags, - int offset, int *data) -{ - int rv; - uint8_t reg, buf[sizeof(uint16_t)]; - - reg = offset & 0xff; - /* I2C read 16-bit word: transmit 8-bit offset, and read 16bits */ - rv = i2c_read(port, slave_addr_flags, reg, buf, sizeof(uint16_t)); - - if (rv) - return rv; - - if (I2C_IS_BIG_ENDIAN(slave_addr_flags)) - *data = ((int)buf[0] << 8) | buf[1]; - else - *data = ((int)buf[1] << 8) | buf[0]; - - return EC_SUCCESS; -} - -int i2c_write16(const int port, - const uint16_t slave_addr_flags, - int offset, int data) -{ - uint8_t buf[1 + sizeof(uint16_t)]; - - buf[0] = offset & 0xff; - - if (I2C_IS_BIG_ENDIAN(slave_addr_flags)) { - buf[1] = (data >> 8) & 0xff; - buf[2] = data & 0xff; - } else { - buf[1] = data & 0xff; - buf[2] = (data >> 8) & 0xff; - } - - return i2c_write(port, slave_addr_flags, buf, 1 + sizeof(uint16_t)); -} - -int i2c_read8(const int port, - const uint16_t slave_addr_flags, - int offset, int *data) -{ - int rv; - uint8_t reg = offset; - uint8_t buf; - - reg = offset; - - rv = i2c_read(port, slave_addr_flags, reg, &buf, sizeof(uint8_t)); - if (!rv) - *data = buf; - - return rv; -} - -int i2c_write8(const int port, - const uint16_t slave_addr_flags, - int offset, int data) -{ - uint8_t buf[2]; - - buf[0] = offset; - buf[1] = data; - - return i2c_write(port, slave_addr_flags, buf, sizeof(buf)); -} - -int i2c_update8(const int port, - const uint16_t slave_addr_flags, - const int offset, - const uint8_t mask, - const enum mask_update_action action) -{ - int rv; - int read_val; - int write_val; - - rv = i2c_read8(port, slave_addr_flags, offset, &read_val); - if (rv) - return rv; - - write_val = (action == MASK_SET) ? (read_val | mask) - : (read_val & ~mask); - - if (IS_ENABLED(CONFIG_I2C_UPDATE_IF_CHANGED) && write_val == read_val) - return EC_SUCCESS; - - return i2c_write8(port, slave_addr_flags, offset, write_val); -} - -int i2c_update16(const int port, - const uint16_t slave_addr_flags, - const int offset, - const uint16_t mask, - const enum mask_update_action action) -{ - int rv; - int read_val; - int write_val; - - rv = i2c_read16(port, slave_addr_flags, offset, &read_val); - if (rv) - return rv; - - write_val = (action == MASK_SET) ? (read_val | mask) - : (read_val & ~mask); - - if (IS_ENABLED(CONFIG_I2C_UPDATE_IF_CHANGED) && write_val == read_val) - return EC_SUCCESS; - - return i2c_write16(port, slave_addr_flags, offset, write_val); -} - -int i2c_field_update8(const int port, - const uint16_t slave_addr_flags, - const int offset, - const uint8_t field_mask, - const uint8_t set_value) -{ - int rv; - int read_val; - int write_val; - - rv = i2c_read8(port, slave_addr_flags, offset, &read_val); - if (rv) - return rv; - - write_val = (read_val & (~field_mask)) | set_value; - - if (IS_ENABLED(CONFIG_I2C_UPDATE_IF_CHANGED) && write_val == read_val) - return EC_SUCCESS; - - return i2c_write8(port, slave_addr_flags, offset, write_val); -} - -int i2c_field_update16(const int port, - const uint16_t slave_addr_flags, - const int offset, - const uint16_t field_mask, - const uint16_t set_value) -{ - int rv; - int read_val; - int write_val; - - rv = i2c_read16(port, slave_addr_flags, offset, &read_val); - if (rv) - return rv; - - write_val = (read_val & (~field_mask)) | set_value; - - if (IS_ENABLED(CONFIG_I2C_UPDATE_IF_CHANGED) && write_val == read_val) - return EC_SUCCESS; - - return i2c_write16(port, slave_addr_flags, offset, write_val); -} - -int i2c_read_offset16(const int port, - const uint16_t slave_addr_flags, - uint16_t offset, int *data, int len) -{ - int rv; - uint8_t buf[sizeof(uint16_t)], addr[sizeof(uint16_t)]; - - if (len < 0 || len > 2) - return EC_ERROR_INVAL; - - addr[0] = (offset >> 8) & 0xff; - addr[1] = offset & 0xff; - - /* I2C read 16-bit word: transmit 16-bit offset, and read buffer */ - rv = i2c_xfer(port, slave_addr_flags, addr, 2, buf, len); - - if (rv) - return rv; - - if (len == 1) { - *data = buf[0]; - } else { - if (I2C_IS_BIG_ENDIAN(slave_addr_flags)) - *data = ((int)buf[0] << 8) | buf[1]; - else - *data = ((int)buf[1] << 8) | buf[0]; - } - - return EC_SUCCESS; -} - -int i2c_write_offset16(const int port, - const uint16_t slave_addr_flags, - uint16_t offset, int data, int len) -{ - uint8_t buf[2 + sizeof(uint16_t)]; - - if (len < 0 || len > 2) - return EC_ERROR_INVAL; - - buf[0] = (offset >> 8) & 0xff; - buf[1] = offset & 0xff; - - if (len == 1) { - buf[2] = data & 0xff; - } else { - if (I2C_IS_BIG_ENDIAN(slave_addr_flags)) { - buf[2] = (data >> 8) & 0xff; - buf[3] = data & 0xff; - } else { - buf[2] = data & 0xff; - buf[3] = (data >> 8) & 0xff; - } - } - - return i2c_xfer(port, slave_addr_flags, buf, 2 + len, NULL, 0); -} - -int i2c_read_offset16_block(const int port, - const uint16_t slave_addr_flags, - uint16_t offset, uint8_t *data, int len) -{ - uint8_t addr[sizeof(uint16_t)]; - - addr[0] = (offset >> 8) & 0xff; - addr[1] = offset & 0xff; - - return i2c_xfer(port, slave_addr_flags, addr, 2, data, len); -} - -int i2c_write_offset16_block(const int port, - const uint16_t slave_addr_flags, - uint16_t offset, const uint8_t *data, int len) -{ - int rv; - uint8_t addr[sizeof(uint16_t)]; - - addr[0] = (offset >> 8) & 0xff; - addr[1] = offset & 0xff; - - /* - * Split into two transactions to avoid the stack space consumption of - * appending the destination address with the data array. - */ - i2c_lock(port, 1); - rv = i2c_xfer_unlocked(port, slave_addr_flags, addr, 2, NULL, 0, - I2C_XFER_START); - if (!rv) - rv = i2c_xfer_unlocked(port, slave_addr_flags, - data, len, NULL, 0, I2C_XFER_STOP); - i2c_lock(port, 0); - - return rv; -} - -int i2c_read_string(const int port, - const uint16_t slave_addr_flags, - int offset, uint8_t *data, int len) -{ - int i, rv; - uint8_t reg, block_length; - - if (!IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(slave_addr_flags)) - return EC_ERROR_UNIMPLEMENTED; - - reg = offset; - i2c_lock(port, 1); - - for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { - int data_length; - - /* - * Send device reg space offset, and read back block length. - * Keep this session open without a stop. - */ - rv = i2c_xfer_unlocked(port, slave_addr_flags, - ®, 1, &block_length, 1, - I2C_XFER_START); - if (rv) - continue; - - if (len && block_length > (len - 1)) - data_length = len - 1; - else - data_length = block_length; - - if (IS_ENABLED(CONFIG_SMBUS_PEC) && - I2C_USE_PEC(slave_addr_flags)) { - uint8_t addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; - uint8_t out[3] = {addr_8bit, reg, addr_8bit | 1}; - uint8_t pec, pec_remote; - - rv = i2c_xfer_unlocked(port, slave_addr_flags, - 0, 0, data, data_length, 0); - data[data_length] = 0; - if (rv) - continue; - - pec = crc8(out, sizeof(out)); - pec = crc8_arg(&block_length, 1, pec); - pec = crc8_arg(data, data_length, pec); - - /* read all remaining bytes */ - block_length -= data_length; - while (block_length) { - uint8_t byte; - - rv = i2c_xfer_unlocked(port, slave_addr_flags, - NULL, 0, &byte, 1, 0); - if (rv) - break; - pec = crc8_arg(&byte, 1, pec); - --block_length; - } - if (rv) - continue; - - rv = i2c_xfer_unlocked(port, slave_addr_flags, NULL, 0, - &pec_remote, 1, I2C_XFER_STOP); - if (rv) - continue; - - if (pec != pec_remote) - rv = EC_ERROR_CRC; - } else { - rv = i2c_xfer_unlocked(port, slave_addr_flags, - 0, 0, data, data_length, - I2C_XFER_STOP); - data[data_length] = 0; - if (rv) - continue; - } - - /* execution reaches here implies rv=0, so we can exit now */ - break; - } - - i2c_lock(port, 0); - return rv; -} - -int i2c_read_block(const int port, - const uint16_t slave_addr_flags, - int offset, uint8_t *data, int len) -{ - int rv; - uint8_t reg_address = offset; - - rv = i2c_xfer(port, slave_addr_flags, ®_address, 1, data, len); - return rv; -} - -int i2c_write_block(const int port, - const uint16_t slave_addr_flags, - int offset, const uint8_t *data, int len) -{ - int i, rv; - uint8_t reg_address = offset, pec = 0; - - if (!IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(slave_addr_flags)) - return EC_ERROR_UNIMPLEMENTED; - - if (IS_ENABLED(CONFIG_SMBUS_PEC) && I2C_USE_PEC(slave_addr_flags)) { - uint8_t addr_8bit = I2C_GET_ADDR(slave_addr_flags) << 1; - - pec = crc8(&addr_8bit, sizeof(uint8_t)); - pec = crc8_arg(data, len, pec); - } - - /* - * Split into two transactions to avoid the stack space consumption of - * appending the destination address with the data array. - */ - i2c_lock(port, 1); - for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { - rv = i2c_xfer_unlocked(port, slave_addr_flags, - ®_address, 1, NULL, 0, - I2C_XFER_START); - if (rv) - continue; - - if (I2C_USE_PEC(slave_addr_flags)) { - rv = i2c_xfer_unlocked(port, slave_addr_flags, - data, len, NULL, 0, 0); - if (rv) - continue; - - rv = i2c_xfer_unlocked(port, slave_addr_flags, - &pec, sizeof(uint8_t), NULL, 0, - I2C_XFER_STOP); - if (rv) - continue; - } else { - rv = i2c_xfer_unlocked(port, slave_addr_flags, - data, len, NULL, 0, - I2C_XFER_STOP); - if (rv) - continue; - } - - /* execution reaches here implies rv=0, so we can exit now */ - break; - } - i2c_lock(port, 0); - - return rv; -} - -int get_sda_from_i2c_port(int port, enum gpio_signal *sda) -{ - const struct i2c_port_t *i2c_port = get_i2c_port(port); - - /* Crash if the port given is not in the i2c_ports[] table. */ - ASSERT(i2c_port); - - /* Check if the SCL and SDA pins have been defined for this port. */ - if (i2c_port->scl == 0 && i2c_port->sda == 0) - return EC_ERROR_INVAL; - - *sda = i2c_port->sda; - return EC_SUCCESS; -} - -int get_scl_from_i2c_port(int port, enum gpio_signal *scl) -{ - const struct i2c_port_t *i2c_port = get_i2c_port(port); - - /* Crash if the port given is not in the i2c_ports[] table. */ - ASSERT(i2c_port); - - /* Check if the SCL and SDA pins have been defined for this port. */ - if (i2c_port->scl == 0 && i2c_port->sda == 0) - return EC_ERROR_INVAL; - - *scl = i2c_port->scl; - return EC_SUCCESS; -} - -void i2c_raw_set_scl(int port, int level) -{ - enum gpio_signal g; - - if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS) - gpio_set_level(g, level); -} - -void i2c_raw_set_sda(int port, int level) -{ - enum gpio_signal g; - - if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS) - gpio_set_level(g, level); -} - -int i2c_raw_mode(int port, int enable) -{ - enum gpio_signal sda, scl; - int ret_sda, ret_scl; - - /* Get the SDA and SCL pins for this port. If none, then return. */ - if (get_sda_from_i2c_port(port, &sda) != EC_SUCCESS) - return EC_ERROR_INVAL; - if (get_scl_from_i2c_port(port, &scl) != EC_SUCCESS) - return EC_ERROR_INVAL; - - if (enable) { - int raw_gpio_mode_flags = GPIO_ODR_HIGH; - - /* If the CLK line is 1.8V, then ensure we set 1.8V mode */ - if ((gpio_list + scl)->flags & GPIO_SEL_1P8V) - raw_gpio_mode_flags |= GPIO_SEL_1P8V; - - /* - * To enable raw mode, take out of alternate function mode and - * set the flags to open drain output. - */ - ret_sda = gpio_config_pin(MODULE_I2C, sda, 0); - ret_scl = gpio_config_pin(MODULE_I2C, scl, 0); - - gpio_set_flags(scl, raw_gpio_mode_flags); - gpio_set_flags(sda, raw_gpio_mode_flags); - } else { - /* - * Configure the I2C pins to exit raw mode and return - * to normal mode. - */ - ret_sda = gpio_config_pin(MODULE_I2C, sda, 1); - ret_scl = gpio_config_pin(MODULE_I2C, scl, 1); - } - - return ret_sda == EC_SUCCESS ? ret_scl : ret_sda; -} - - -/* - * Unwedge the i2c bus for the given port. - * - * Some devices on our i2c busses keep power even if we get a reset. That - * means that they could be part way through a transaction and could be - * driving the bus in a way that makes it hard for us to talk on the bus. - * ...or they might listen to the next transaction and interpret it in a - * weird way. - * - * Note that devices could be in one of several states: - * - If a device got interrupted in a write transaction it will be watching - * for additional data to finish its write. It will probably be looking to - * ack the data (drive the data line low) after it gets everything. - * - If a device got interrupted while responding to a register read, it will - * be watching for clocks and will drive data out when it sees clocks. At - * the moment it might be trying to send out a 1 (so both clock and data - * may be high) or it might be trying to send out a 0 (so it's driving data - * low). - * - * We attempt to unwedge the bus by doing: - * - If SCL is being held low, then a slave is clock extending. The only - * thing we can do is try to wait until the slave stops clock extending. - * - Otherwise, we will toggle the clock until the slave releases the SDA line. - * Once the SDA line is released, try to send a STOP bit. Rinse and repeat - * until either the bus is normal, or we run out of attempts. - * - * Note this should work for most devices, but depending on the slaves i2c - * state machine, it may not be possible to unwedge the bus. - */ -int i2c_unwedge(int port) -{ - int i, j; - int ret = EC_SUCCESS; - -#ifdef CONFIG_I2C_BUS_MAY_BE_UNPOWERED - /* - * Don't try to unwedge the port if we know it's unpowered; it's futile. - */ - if (!board_is_i2c_port_powered(port)) { - CPRINTS("Skipping i2c unwedge, bus not powered."); - return EC_ERROR_NOT_POWERED; - } -#endif /* CONFIG_I2C_BUS_MAY_BE_UNPOWERED */ - - /* Try to put port in to raw bit bang mode. */ - if (i2c_raw_mode(port, 1) != EC_SUCCESS) - return EC_ERROR_UNKNOWN; - - /* - * If clock is low, wait for a while in case of clock stretched - * by a slave. - */ - if (!i2c_raw_get_scl(port)) { - for (i = 0;; i++) { - if (i >= UNWEDGE_SCL_ATTEMPTS) { - /* - * If we get here, a slave is holding the clock - * low and there is nothing we can do. - */ - CPRINTS("I2C%d unwedge failed, " - "SCL is held low", port); - ret = EC_ERROR_UNKNOWN; - goto unwedge_done; - } - udelay(I2C_BITBANG_DELAY_US); - if (i2c_raw_get_scl(port)) - break; - } - } - - if (i2c_raw_get_sda(port)) - goto unwedge_done; - - CPRINTS("I2C%d unwedge called with SDA held low", port); - - /* Keep trying to unwedge the SDA line until we run out of attempts. */ - for (i = 0; i < UNWEDGE_SDA_ATTEMPTS; i++) { - /* Drive the clock high. */ - i2c_raw_set_scl(port, 1); - udelay(I2C_BITBANG_DELAY_US); - - /* - * Clock through the problem by clocking out 9 bits. If slave - * releases the SDA line, then we can stop clocking bits and - * send a STOP. - */ - for (j = 0; j < 9; j++) { - if (i2c_raw_get_sda(port)) - break; - - i2c_raw_set_scl(port, 0); - udelay(I2C_BITBANG_DELAY_US); - i2c_raw_set_scl(port, 1); - udelay(I2C_BITBANG_DELAY_US); - } - - /* Take control of SDA line and issue a STOP command. */ - i2c_raw_set_sda(port, 0); - udelay(I2C_BITBANG_DELAY_US); - i2c_raw_set_sda(port, 1); - udelay(I2C_BITBANG_DELAY_US); - - /* Check if the bus is unwedged. */ - if (i2c_raw_get_sda(port) && i2c_raw_get_scl(port)) - break; - } - - if (!i2c_raw_get_sda(port)) { - CPRINTS("I2C%d unwedge failed, SDA still low", port); - ret = EC_ERROR_UNKNOWN; - } - if (!i2c_raw_get_scl(port)) { - CPRINTS("I2C%d unwedge failed, SCL still low", port); - ret = EC_ERROR_UNKNOWN; - } - -unwedge_done: - /* Take port out of raw bit bang mode. */ - i2c_raw_mode(port, 0); - - return ret; -} - -int i2c_set_freq(int port, enum i2c_freq freq) -{ - int ret; - - if (!(get_i2c_port(port)->flags & I2C_PORT_FLAG_DYNAMIC_SPEED)) - return EC_ERROR_INVAL; - - i2c_lock(port, 1); - ret = chip_i2c_set_freq(port, freq); - i2c_lock(port, 0); - return ret; -} - -enum i2c_freq i2c_get_freq(int port) -{ - return chip_i2c_get_freq(port); -} - -/*****************************************************************************/ -/* Host commands */ - -#ifdef CONFIG_I2C_DEBUG_PASSTHRU -#define PTHRUPRINTS(format, args...) CPRINTS("I2C_PTHRU " format, ## args) -#define PTHRUPRINTF(format, args...) CPRINTF(format, ## args) -#else -#define PTHRUPRINTS(format, args...) -#define PTHRUPRINTF(format, args...) -#endif - -/** - * Perform the voluminous checking required for this message - * - * @param args Arguments - * @return 0 if OK, EC_RES_INVALID_PARAM on error - */ -static int check_i2c_params(const struct host_cmd_handler_args *args) -{ - const struct ec_params_i2c_passthru *params = args->params; - const struct ec_params_i2c_passthru_msg *msg; - int read_len = 0, write_len = 0; - unsigned int size; - int msgnum; - - if (args->params_size < sizeof(*params)) { - PTHRUPRINTS("no params, params_size=%d, need at least %d", - args->params_size, sizeof(*params)); - return EC_RES_INVALID_PARAM; - } - size = sizeof(*params) + params->num_msgs * sizeof(*msg); - if (args->params_size < size) { - PTHRUPRINTS("params_size=%d, need at least %d", - args->params_size, size); - return EC_RES_INVALID_PARAM; - } - - /* Loop and process messages */; - for (msgnum = 0, msg = params->msg; msgnum < params->num_msgs; - msgnum++, msg++) { - unsigned int addr_flags = msg->addr_flags; - - PTHRUPRINTS("port=%d, %s, addr=0x%x(7-bit), len=%d", - params->port, - addr_flags & EC_I2C_FLAG_READ ? "read" : "write", - addr_flags & EC_I2C_ADDR_MASK, - msg->len); - - if (addr_flags & EC_I2C_FLAG_READ) - read_len += msg->len; - else - write_len += msg->len; - } - - /* Check there is room for the data */ - if (args->response_max < - sizeof(struct ec_response_i2c_passthru) + read_len) { - PTHRUPRINTS("overflow1"); - return EC_RES_INVALID_PARAM; - } - - /* Must have bytes to write */ - if (args->params_size < size + write_len) { - PTHRUPRINTS("overflow2"); - return EC_RES_INVALID_PARAM; - } - - return EC_RES_SUCCESS; -} - -static enum ec_status i2c_command_passthru(struct host_cmd_handler_args *args) -{ - const struct ec_params_i2c_passthru *params = args->params; - const struct ec_params_i2c_passthru_msg *msg; - struct ec_response_i2c_passthru *resp = args->response; - const struct i2c_port_t *i2c_port; - const uint8_t *out; - int in_len; - int ret, i; - int port_is_locked = 0; - -#ifdef CONFIG_BATTERY_CUT_OFF - /* - * Some batteries would wake up after cut-off if we talk to it. - */ - if (battery_is_cut_off()) - return EC_RES_ACCESS_DENIED; -#endif - - i2c_port = get_i2c_port(params->port); - if (!i2c_port) - return EC_RES_INVALID_PARAM; - - ret = check_i2c_params(args); - if (ret) - return ret; - - if (port_protected[params->port] && i2c_port->passthru_allowed) { - for (i = 0; i < params->num_msgs; i++) { - if (!i2c_port->passthru_allowed(i2c_port, - params->msg[i].addr_flags)) - return EC_RES_ACCESS_DENIED; - } - } - - /* Loop and process messages */ - resp->i2c_status = 0; - out = args->params + sizeof(*params) + params->num_msgs * sizeof(*msg); - in_len = 0; - - for (resp->num_msgs = 0, msg = params->msg; - resp->num_msgs < params->num_msgs; - resp->num_msgs++, msg++) { - int xferflags = I2C_XFER_START; - int read_len = 0, write_len = 0; - int rv = 1; - - /* Have to remove the EC flags from the address flags */ - uint16_t addr_flags = msg->addr_flags & EC_I2C_ADDR_MASK; - - - if (msg->addr_flags & EC_I2C_FLAG_READ) - read_len = msg->len; - else - write_len = msg->len; - - /* Set stop bit for last message */ - if (resp->num_msgs == params->num_msgs - 1) - xferflags |= I2C_XFER_STOP; - -#if defined(VIRTUAL_BATTERY_ADDR_FLAGS) && defined(I2C_PORT_VIRTUAL_BATTERY) - if (params->port == I2C_PORT_VIRTUAL_BATTERY && - addr_flags == VIRTUAL_BATTERY_ADDR_FLAGS) { - if (virtual_battery_handler(resp, in_len, &rv, - xferflags, read_len, - write_len, out)) - break; - } -#endif - /* Transfer next message */ - PTHRUPRINTS("xfer port=%x addr=0x%x rlen=%d flags=0x%x", - params->port, addr_flags, - read_len, xferflags); - if (write_len) { - PTHRUPRINTF(" out:"); - for (i = 0; i < write_len; i++) - PTHRUPRINTF(" 0x%02x", out[i]); - PTHRUPRINTF("\n"); - } - if (rv) { -#ifdef CONFIG_I2C_PASSTHRU_RESTRICTED - if (system_is_locked() && - !board_allow_i2c_passthru(params->port)) { - if (port_is_locked) - i2c_lock(params->port, 0); - return EC_RES_ACCESS_DENIED; - } -#endif - if (!port_is_locked) - i2c_lock(params->port, (port_is_locked = 1)); - rv = i2c_xfer_unlocked(params->port, - addr_flags, - out, write_len, - &resp->data[in_len], read_len, - xferflags); - } - - if (rv) { - /* Driver will have sent a stop bit here */ - if (rv == EC_ERROR_TIMEOUT) - resp->i2c_status = EC_I2C_STATUS_TIMEOUT; - else - resp->i2c_status = EC_I2C_STATUS_NAK; - break; - } - - in_len += read_len; - out += write_len; - } - args->response_size = sizeof(*resp) + in_len; - - /* Unlock port */ - if (port_is_locked) - i2c_lock(params->port, 0); - - /* - * Return success even if transfer failed so response is sent. Host - * will check message status to determine the transfer result. - */ - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_I2C_PASSTHRU, i2c_command_passthru, EC_VER_MASK(0)); - -static void i2c_passthru_protect_port(uint32_t port) -{ - if (port < ARRAY_SIZE(port_protected)) - port_protected[port] = 1; - else - PTHRUPRINTS("Invalid I2C port %d to be protected\n", port); -} - -static void i2c_passthru_protect_tcpc_ports(void) -{ -#ifdef CONFIG_USB_PD_PORT_MAX_COUNT - int i; - - /* - * If WP is not enabled i.e. system is not locked leave the tunnels open - * so that factory line can do updates without a new RO BIOS. - */ - if (!system_is_locked()) { - CPRINTS("System unlocked, TCPC I2C tunnels may be unprotected"); - return; - } - - for (i = 0; i < board_get_usb_pd_port_count(); i++) { - /* TCPC tunnel not configured. No need to protect anything */ - if (!I2C_GET_ADDR(tcpc_config[i].i2c_info.addr_flags)) - continue; - i2c_passthru_protect_port(tcpc_config[i].i2c_info.port); - } -#endif -} - -static enum ec_status -i2c_command_passthru_protect(struct host_cmd_handler_args *args) -{ - const struct ec_params_i2c_passthru_protect *params = args->params; - struct ec_response_i2c_passthru_protect *resp = args->response; - - if (args->params_size < sizeof(*params)) { - PTHRUPRINTS("protect no params, params_size=%d, ", - args->params_size); - return EC_RES_INVALID_PARAM; - } - - /* - * When calling the subcmd to protect all tcpcs, the i2c port isn't - * expected to be set in the args. So, putting a check here to avoid - * the get_i2c_port return error. - */ - if (params->subcmd == EC_CMD_I2C_PASSTHRU_PROTECT_ENABLE_TCPCS) { - if (IS_ENABLED(CONFIG_USB_POWER_DELIVERY) && - !IS_ENABLED(CONFIG_USB_PD_TCPM_STUB)) - i2c_passthru_protect_tcpc_ports(); - return EC_RES_SUCCESS; - } - - if (!get_i2c_port(params->port)) { - PTHRUPRINTS("protect invalid port %d", params->port); - return EC_RES_INVALID_PARAM; - } - - if (params->subcmd == EC_CMD_I2C_PASSTHRU_PROTECT_STATUS) { - if (args->response_max < sizeof(*resp)) { - PTHRUPRINTS("protect no response, " - "response_max=%d, need at least %d", - args->response_max, sizeof(*resp)); - return EC_RES_INVALID_PARAM; - } - - resp->status = port_protected[params->port]; - args->response_size = sizeof(*resp); - } else if (params->subcmd == EC_CMD_I2C_PASSTHRU_PROTECT_ENABLE) { - i2c_passthru_protect_port(params->port); - } else { - return EC_RES_INVALID_COMMAND; - } - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_I2C_PASSTHRU_PROTECT, i2c_command_passthru_protect, - EC_VER_MASK(0)); - -/*****************************************************************************/ -/* Console commands */ - -#ifdef CONFIG_CMD_I2C_PROTECT -static int command_i2cprotect(int argc, char **argv) -{ - if (argc == 1) { - int i, port; - - for (i = 0; i < i2c_ports_used; i++) { - port = i2c_ports[i].port; - ccprintf("Port %d: %s\n", port, - port_protected[port] ? "Protected" : "Unprotected"); - } - } else if (argc == 2) { - int port; - char *e; - - port = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - if (!get_i2c_port(port)) { - ccprintf("i2c passthru protect invalid port %d\n", - port); - return EC_RES_INVALID_PARAM; - } - - port_protected[port] = 1; - } else { - return EC_ERROR_PARAM_COUNT; - } - - return EC_RES_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(i2cprotect, command_i2cprotect, - "[port]", - "Protect I2C bus"); -#endif - -#ifdef CONFIG_CMD_I2C_SCAN -static void scan_bus(int port, const char *desc) -{ - int level; - uint8_t tmp; - uint16_t addr_flags; - - ccprintf("Scanning %d %s", port, desc); - - i2c_lock(port, 1); - - /* Don't scan a busy port, since reads will just fail / time out */ - level = i2c_get_line_levels(port); - if (level != I2C_LINE_IDLE) { - ccprintf(": port busy (SDA=%d, SCL=%d)", - (level & I2C_LINE_SDA_HIGH) ? 1 : 0, - (level & I2C_LINE_SCL_HIGH) ? 1 : 0); - goto scan_bus_exit; - } - /* - * Only scan in the valid client device address range, otherwise some - * client devices stretch the clock in weird ways that prevent the - * discovery of other devices. - */ - for (addr_flags = I2C_FIRST_VALID_ADDR; - addr_flags <= I2C_LAST_VALID_ADDR; ++addr_flags) { - watchdog_reload(); /* Otherwise a full scan trips watchdog */ - ccputs("."); - - /* Do a single read */ - if (!i2c_xfer_unlocked(port, addr_flags, - NULL, 0, &tmp, 1, I2C_XFER_SINGLE)) - ccprintf("\n 0x%02x", addr_flags); - } - -scan_bus_exit: - i2c_lock(port, 0); - ccputs("\n"); -} - -static int command_scan(int argc, char **argv) -{ - int port; - char *e; - const struct i2c_port_t *i2c_port; - - if (argc == 1) { - for (port = 0; port < i2c_ports_used; port++) - scan_bus(i2c_ports[port].port, i2c_ports[port].name); - - if (IS_ENABLED(CONFIG_I2C_BITBANG)) - for (port = 0; port < i2c_bitbang_ports_used; port++) - scan_bus(i2c_bitbang_ports[port].port, - i2c_bitbang_ports[port].name); - - return EC_SUCCESS; - } - - - port = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - i2c_port = get_i2c_port(port); - if (!i2c_port) - return EC_ERROR_PARAM2; - - scan_bus(port, i2c_port->name); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(i2cscan, command_scan, - "i2cscan [port]", - "Scan I2C ports for devices"); -#endif - -#ifdef CONFIG_CMD_I2C_XFER -static int command_i2cxfer(int argc, char **argv) -{ - int port; - uint16_t addr_flags; - uint16_t offset = 0; - uint8_t offset_size = 0; - int v = 0; - uint8_t data[32]; - char *e; - int rv = 0; - - if (argc < 5) - return EC_ERROR_PARAM_COUNT; - - port = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - addr_flags = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - offset = strtoi(argv[4], &e, 0); - if (*e) - return EC_ERROR_PARAM4; - - offset_size = (strlen(argv[4]) == 6) ? 2 : 1; - - if (argc >= 6) { - v = strtoi(argv[5], &e, 0); - if (*e) - return EC_ERROR_PARAM5; - } - - if (strcasecmp(argv[1], "r") == 0) { - /* 8-bit read */ - if (offset_size == 2) - rv = i2c_read_offset16(port, addr_flags, - offset, &v, 1); - else - rv = i2c_read8(port, addr_flags, - offset, &v); - if (!rv) - ccprintf("0x%02x [%d]\n", v, v); - - } else if (strcasecmp(argv[1], "r16") == 0) { - /* 16-bit read */ - if (offset_size == 2) - rv = i2c_read_offset16(port, addr_flags, - offset, &v, 2); - else - rv = i2c_read16(port, addr_flags, - offset, &v); - if (!rv) - ccprintf("0x%04x [%d]\n", v, v); - - } else if (strcasecmp(argv[1], "rlen") == 0) { - /* Arbitrary length read; param5 = len */ - if (argc < 6 || v < 0 || v > sizeof(data)) - return EC_ERROR_PARAM5; - - rv = i2c_xfer(port, addr_flags, - (uint8_t *)&offset, 1, data, v); - - if (!rv) - ccprintf("Data: %ph\n", HEX_BUF(data, v)); - - } else if (strcasecmp(argv[1], "w") == 0) { - /* 8-bit write */ - if (argc < 6) - return EC_ERROR_PARAM5; - if (offset_size == 2) - rv = i2c_write_offset16(port, addr_flags, - offset, v, 1); - else - rv = i2c_write8(port, addr_flags, - offset, v); - - } else if (strcasecmp(argv[1], "w16") == 0) { - /* 16-bit write */ - if (argc < 6) - return EC_ERROR_PARAM5; - if (offset_size == 2) - rv = i2c_write_offset16(port, addr_flags, - offset, v, 2); - else - rv = i2c_write16(port, addr_flags, - offset, v); - - } else { - return EC_ERROR_PARAM1; - } - - return rv; -} -DECLARE_CONSOLE_COMMAND(i2cxfer, command_i2cxfer, - "r/r16/rlen/w/w16 port addr offset [value | len]", - "Read write I2C"); -#endif - -#ifdef CONFIG_CMD_I2C_STRESS_TEST -static void i2c_test_status(struct i2c_test_results *i2c_test, int test_dev) -{ - ccprintf("test_dev=%2d, ", test_dev); - ccprintf("r=%5d, rs=%5d, rf=%5d, ", - i2c_test->read_success + i2c_test->read_fail, - i2c_test->read_success, - i2c_test->read_fail); - - ccprintf("w=%5d, ws=%5d, wf=%5d\n", - i2c_test->write_success + i2c_test->write_fail, - i2c_test->write_success, - i2c_test->write_fail); - - i2c_test->read_success = 0; - i2c_test->read_fail = 0; - i2c_test->write_success = 0, - i2c_test->write_fail = 0; -} - -#define I2C_STRESS_TEST_DATA_VERIFY_RETRY_COUNT 3 -static int command_i2ctest(int argc, char **argv) -{ - char *e; - int i, j, rv; - uint32_t rand; - int data, data_verify; - int count = 10000; - int udelay = 100; - int test_dev = i2c_test_dev_used; - struct i2c_stress_test_dev *i2c_s_test = NULL; - struct i2c_test_reg_info *reg_s_info; - struct i2c_test_results *test_s_results; - - if (argc > 1) { - count = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - } - - if (argc > 2) { - udelay = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - } - - if (argc > 3) { - test_dev = strtoi(argv[3], &e, 0); - if (*e || test_dev < 1 || test_dev > i2c_test_dev_used) - return EC_ERROR_PARAM4; - test_dev--; - } - - for (i = 0; i < count; i++) { - int port; - uint16_t addr_flags; - - if (!(i % 1000)) - ccprintf("running test %d\n", i); - - if (argc < 4) { - rand = get_time().val; - test_dev = rand % i2c_test_dev_used; - } - - port = i2c_stress_tests[test_dev].port; - addr_flags = i2c_stress_tests[test_dev].addr_flags; - i2c_s_test = i2c_stress_tests[test_dev].i2c_test; - reg_s_info = &i2c_s_test->reg_info; - test_s_results = &i2c_s_test->test_results; - - rand = get_time().val; - if (rand & 0x1) { - /* read */ - rv = i2c_s_test->i2c_read ? - i2c_s_test->i2c_read(port, addr_flags, - reg_s_info->read_reg, &data) : - i2c_s_test->i2c_read_dev( - reg_s_info->read_reg, &data); - if (rv || data != reg_s_info->read_val) - test_s_results->read_fail++; - else - test_s_results->read_success++; - } else { - /* - * Reads are more than writes in the system. - * Read and then write same value to ensure we are - * not changing any settings. - */ - - /* Read the write register */ - rv = i2c_s_test->i2c_read ? - i2c_s_test->i2c_read(port, addr_flags, - reg_s_info->read_reg, &data) : - i2c_s_test->i2c_read_dev( - reg_s_info->read_reg, &data); - if (rv) { - /* Skip writing invalid data */ - test_s_results->read_fail++; - continue; - } else - test_s_results->read_success++; - - j = I2C_STRESS_TEST_DATA_VERIFY_RETRY_COUNT; - do { - /* Write same value back */ - rv = i2c_s_test->i2c_write ? - i2c_s_test->i2c_write(port, - addr_flags, - reg_s_info->write_reg, data) : - i2c_s_test->i2c_write_dev( - reg_s_info->write_reg, data); - i++; - if (rv) { - /* Skip reading as write failed */ - test_s_results->write_fail++; - break; - } - test_s_results->write_success++; - - /* Read back to verify the data */ - rv = i2c_s_test->i2c_read ? - i2c_s_test->i2c_read(port, - addr_flags, - reg_s_info->read_reg, &data_verify) : - i2c_s_test->i2c_read_dev( - reg_s_info->read_reg, &data_verify); - i++; - if (rv) { - /* Read failed try next time */ - test_s_results->read_fail++; - break; - } else if (!rv && data != data_verify) { - /* Either data writes/read is wrong */ - j--; - } else { - j = 0; - test_s_results->read_success++; - } - } while (j); - } - - usleep(udelay); - } - - ccprintf("\n**********final result **********\n"); - - cflush(); - if (argc > 3) { - i2c_test_status(&i2c_s_test->test_results, test_dev + 1); - } else { - for (i = 0; i < i2c_test_dev_used; i++) { - i2c_s_test = i2c_stress_tests[i].i2c_test; - i2c_test_status(&i2c_s_test->test_results, i + 1); - msleep(100); - } - } - cflush(); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(i2ctest, command_i2ctest, - "i2ctest count|udelay|dev", - "I2C stress test"); -#endif /* CONFIG_CMD_I2C_STRESS_TEST */ diff --git a/common/i2c_peripheral.c b/common/i2c_peripheral.c new file mode 100644 index 0000000000..26e46175b4 --- /dev/null +++ b/common/i2c_peripheral.c @@ -0,0 +1,33 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* I2C peripheral cross-platform code for Chrome EC */ + +#include "host_command.h" +#include "i2c.h" +#include "util.h" + +/** + * Command handler to get host command protocol information + * + * @param args: host command handler arguments + * @return EC_SUCCESS + */ +static enum ec_status i2c_get_protocol_info(struct host_cmd_handler_args *args) +{ + struct ec_response_get_protocol_info *r = args->response; + + memset(r, 0, sizeof(*r)); + r->protocol_versions = BIT(3); + r->max_request_packet_size = I2C_MAX_HOST_PACKET_SIZE; + r->max_response_packet_size = I2C_MAX_HOST_PACKET_SIZE; + r->flags = 0; + + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, i2c_get_protocol_info, + EC_VER_MASK(0)); diff --git a/common/i2c_slave.c b/common/i2c_slave.c deleted file mode 100644 index 7e710b2ef4..0000000000 --- a/common/i2c_slave.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* I2C slave cross-platform code for Chrome EC */ - -#include "host_command.h" -#include "i2c.h" -#include "util.h" - -enum ec_status i2c_get_protocol_info(struct host_cmd_handler_args *args) -{ - struct ec_response_get_protocol_info *r = args->response; - - memset(r, 0, sizeof(*r)); - r->protocol_versions = BIT(3); - r->max_request_packet_size = I2C_MAX_HOST_PACKET_SIZE; - r->max_response_packet_size = I2C_MAX_HOST_PACKET_SIZE; - r->flags = 0; - - args->response_size = sizeof(*r); - - return EC_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, - i2c_get_protocol_info, - EC_VER_MASK(0)); diff --git a/common/i2c_trace.c b/common/i2c_trace.c index 340de901f9..8532766ea8 100644 --- a/common/i2c_trace.c +++ b/common/i2c_trace.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,35 +6,34 @@ #include "common.h" #include "console.h" #include "i2c.h" -#include "stddef.h" #include "stdbool.h" +#include "stddef.h" #include "util.h" #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) struct i2c_trace_range { bool enabled; int port; - int slave_addr_lo; /* Inclusive */ - int slave_addr_hi; /* Inclusive */ + int addr_lo; /* Inclusive */ + int addr_hi; /* Inclusive */ }; static struct i2c_trace_range trace_entries[8]; -void i2c_trace_notify(int port, uint16_t slave_addr_flags, - const uint8_t *out_data, size_t out_size, - const uint8_t *in_data, size_t in_size) +void i2c_trace_notify(int port, uint16_t addr_flags, const uint8_t *out_data, + size_t out_size, const uint8_t *in_data, size_t in_size, + int ret) { size_t i; - uint16_t addr = I2C_GET_ADDR(slave_addr_flags); + uint16_t addr = I2C_STRIP_FLAGS(addr_flags); for (i = 0; i < ARRAY_SIZE(trace_entries); i++) - if (trace_entries[i].enabled - && trace_entries[i].port == port - && trace_entries[i].slave_addr_lo <= addr - && trace_entries[i].slave_addr_hi >= addr) + if (trace_entries[i].enabled && trace_entries[i].port == port && + trace_entries[i].addr_lo <= addr && + trace_entries[i].addr_hi >= addr) goto trace_enabled; return; @@ -45,7 +44,9 @@ void i2c_trace_notify(int port, uint16_t slave_addr_flags, for (i = 0; i < out_size; i++) CPRINTF("0x%02X ", out_data[i]); } - if (in_size) { + if (ret != EC_SUCCESS) { + CPRINTF(" error: %d", ret); + } else if (in_size) { CPRINTF(" rd "); for (i = 0; i < in_size; i++) CPRINTF("0x%02X ", in_data[i]); @@ -64,15 +65,16 @@ static int command_i2ctrace_list(void) for (i = 0; i < ARRAY_SIZE(trace_entries); i++) { if (trace_entries[i].enabled) { i2c_port = get_i2c_port(trace_entries[i].port); - ccprintf("%-2zd %d %-8s 0x%X", - i, - trace_entries[i].port, - i2c_port->name, - trace_entries[i].slave_addr_lo); - if (trace_entries[i].slave_addr_hi - != trace_entries[i].slave_addr_lo) - ccprintf(" to 0x%X", - trace_entries[i].slave_addr_hi); + ccprintf("%-2zd %d %-8s 0x%X", i, trace_entries[i].port, +#ifndef CONFIG_ZEPHYR + i2c_port ? i2c_port->name : "invalid", +#else + "", +#endif /* CONFIG_ZEPHYR */ + trace_entries[i].addr_lo); + if (trace_entries[i].addr_hi != + trace_entries[i].addr_lo) + ccprintf(" to 0x%X", trace_entries[i].addr_hi); ccprintf("\n"); } } @@ -89,8 +91,7 @@ static int command_i2ctrace_disable(size_t id) return EC_SUCCESS; } -static int command_i2ctrace_enable(int port, int slave_addr_lo, - int slave_addr_hi) +static int command_i2ctrace_enable(int port, int addr_lo, int addr_hi) { struct i2c_trace_range *t; struct i2c_trace_range *new_entry = NULL; @@ -98,48 +99,41 @@ static int command_i2ctrace_enable(int port, int slave_addr_lo, if (!get_i2c_port(port)) return EC_ERROR_PARAM2; - if (slave_addr_lo > slave_addr_hi) + if (addr_lo > addr_hi) return EC_ERROR_PARAM3; /* * Scan thru existing entries to see if there is one we can * extend instead of making a new entry */ - for (t = trace_entries; - t < trace_entries + ARRAY_SIZE(trace_entries); + for (t = trace_entries; t < trace_entries + ARRAY_SIZE(trace_entries); t++) { if (t->enabled && t->port == port) { /* Subset of existing range, do nothing */ - if (t->slave_addr_lo <= slave_addr_lo && - t->slave_addr_hi >= slave_addr_hi) + if (t->addr_lo <= addr_lo && t->addr_hi >= addr_hi) return EC_SUCCESS; /* Extends exising range on both directions, replace */ - if (t->slave_addr_lo >= slave_addr_lo && - t->slave_addr_hi <= slave_addr_hi) { + if (t->addr_lo >= addr_lo && t->addr_hi <= addr_hi) { t->enabled = 0; - return command_i2ctrace_enable( - port, slave_addr_lo, slave_addr_hi); + return command_i2ctrace_enable(port, addr_lo, + addr_hi); } /* Extends existing range below */ - if (t->slave_addr_lo - 1 <= slave_addr_hi && - t->slave_addr_hi >= slave_addr_hi) { + if (t->addr_lo - 1 <= addr_hi && + t->addr_hi >= addr_hi) { t->enabled = 0; - return command_i2ctrace_enable( - port, - slave_addr_lo, - t->slave_addr_hi); + return command_i2ctrace_enable(port, addr_lo, + t->addr_hi); } /* Extends existing range above */ - if (t->slave_addr_lo <= slave_addr_lo && - t->slave_addr_hi + 1 >= slave_addr_lo) { + if (t->addr_lo <= addr_lo && + t->addr_hi + 1 >= addr_lo) { t->enabled = 0; - return command_i2ctrace_enable( - port, - t->slave_addr_lo, - slave_addr_hi); + return command_i2ctrace_enable(port, t->addr_lo, + addr_hi); } } else if (!t->enabled && !new_entry) { new_entry = t; @@ -150,8 +144,8 @@ static int command_i2ctrace_enable(int port, int slave_addr_lo, if (new_entry) { new_entry->enabled = 1; new_entry->port = port; - new_entry->slave_addr_lo = slave_addr_lo; - new_entry->slave_addr_hi = slave_addr_hi; + new_entry->addr_lo = addr_lo; + new_entry->addr_hi = addr_hi; return EC_SUCCESS; } @@ -159,8 +153,7 @@ static int command_i2ctrace_enable(int port, int slave_addr_lo, return EC_ERROR_MEMORY_ALLOCATION; } - -static int command_i2ctrace(int argc, char **argv) +static int command_i2ctrace(int argc, const char **argv) { int id_or_port; int address_low; @@ -198,14 +191,13 @@ static int command_i2ctrace(int argc, char **argv) return EC_ERROR_PARAM_COUNT; } - return command_i2ctrace_enable( - id_or_port, address_low, address_high); + return command_i2ctrace_enable(id_or_port, address_low, + address_high); } return EC_ERROR_PARAM1; } -DECLARE_CONSOLE_COMMAND(i2ctrace, - command_i2ctrace, +DECLARE_CONSOLE_COMMAND(i2ctrace, command_i2ctrace, "[list | disable | enable
| " "enable ]", "Trace I2C transactions"); diff --git a/common/i2c_wedge.c b/common/i2c_wedge.c index ef87234cce..23e3f6ceae 100644 --- a/common/i2c_wedge.c +++ b/common/i2c_wedge.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,7 +10,7 @@ * pit: * * #define CONFIG_CMD_I2CWEDGE - * #define I2C_PORT_HOST I2C_PORT_MASTER + * #define I2C_PORT_HOST I2C_PORT_CONTROLLER * */ @@ -117,7 +117,7 @@ static int i2c_bang_in_bit(void) { int bit; - /* Let the slave drive data */ + /* Let the peripheral drive data */ i2c_raw_set_sda(I2C_PORT_HOST, 1); i2c_bang_delay(); @@ -134,10 +134,10 @@ static int i2c_bang_in_bit(void) return bit; } -/* Write a byte to I2C bus. Return 0 if ack by the slave. */ +/* Write a byte to I2C bus. Return 0 if ack by the peripheral. */ static int i2c_bang_out_byte(int send_start, int send_stop, unsigned char byte) { - unsigned bit; + unsigned int bit; int nack; int tmp = byte; @@ -178,19 +178,19 @@ static void i2c_bang_init(void) i2c_raw_mode(I2C_PORT_HOST, 1); } -static void i2c_bang_xfer(int slave_addr, int reg) +static void i2c_bang_xfer(int addr, int reg) { int byte; i2c_bang_init(); - /* State a write command to 'slave_addr' */ - i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, slave_addr); + /* State a write command to 'addr' */ + i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr); /* Write 'reg' */ i2c_bang_out_byte(0 /*start*/, 0 /*stop*/, reg); /* Start a read command */ - i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, slave_addr | 1); + i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr | 1); /* Read two bytes */ byte = i2c_bang_in_byte(0, 0); /* ack and no stop */ @@ -199,15 +199,14 @@ static void i2c_bang_xfer(int slave_addr, int reg) ccprintf(" read byte: %d\n", byte); } -static void i2c_bang_wedge_write(int slave_addr, int byte, int bit_count, - int reboot) +static void i2c_bang_wedge_write(int addr, int byte, int bit_count, int reboot) { int i; i2c_bang_init(); - /* State a write command to 'slave_addr' */ - i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, slave_addr); + /* State a write command to 'addr' */ + i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr); /* Send a few bits and stop */ for (i = 0; i < bit_count; ++i) { i2c_bang_out_bit((byte & 0x80) != 0); @@ -219,20 +218,19 @@ static void i2c_bang_wedge_write(int slave_addr, int byte, int bit_count, system_reset(0); } -static void i2c_bang_wedge_read(int slave_addr, int reg, int bit_count, - int reboot) +static void i2c_bang_wedge_read(int addr, int reg, int bit_count, int reboot) { int i; i2c_bang_init(); - /* State a write command to 'slave_addr' */ - i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, slave_addr); + /* State a write command to 'addr' */ + i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr); /* Write 'reg' */ i2c_bang_out_byte(0 /*start*/, 0 /*stop*/, reg); /* Start a read command */ - i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, slave_addr | 1); + i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr | 1); /* Read bit_count bits and stop */ for (i = 0; i < bit_count; ++i) @@ -244,36 +242,36 @@ static void i2c_bang_wedge_read(int slave_addr, int reg, int bit_count, system_reset(0); } -#define WEDGE_WRITE 1 -#define WEDGE_READ 2 -#define WEDGE_REBOOT 4 +#define WEDGE_WRITE 1 +#define WEDGE_READ 2 +#define WEDGE_REBOOT 4 -static int command_i2c_wedge(int argc, char **argv) +static int command_i2c_wedge(int argc, const char **argv) { - int slave_addr, reg, wedge_flag = 0, wedge_bit_count = -1; + int addr, reg, wedge_flag = 0, wedge_bit_count = -1; char *e; enum gpio_signal tmp; /* Verify that the I2C_PORT_HOST has SDA and SCL pins defined. */ if (get_sda_from_i2c_port(I2C_PORT_HOST, &tmp) != EC_SUCCESS || - get_scl_from_i2c_port(I2C_PORT_HOST, &tmp) != EC_SUCCESS) { + get_scl_from_i2c_port(I2C_PORT_HOST, &tmp) != EC_SUCCESS) { ccprintf("Cannot wedge bus because no SCL and SDA pins are" - "defined for this port. Check i2c_ports[].\n"); + "defined for this port. Check i2c_ports[].\n"); return EC_SUCCESS; } if (argc < 3) { - ccputs("Usage: i2cwedge slave_addr out_byte " - "[wedge_flag [wedge_bit_count]]\n"); + ccputs("Usage: i2cwedge addr out_byte " + "[wedge_flag [wedge_bit_count]]\n"); ccputs(" wedge_flag - (1: wedge out; 2: wedge in;" - " 5: wedge out+reboot; 6: wedge in+reboot)]\n"); + " 5: wedge out+reboot; 6: wedge in+reboot)]\n"); ccputs(" wedge_bit_count - 0 to 8\n"); return EC_ERROR_UNKNOWN; } - slave_addr = strtoi(argv[1], &e, 0); + addr = strtoi(argv[1], &e, 0); if (*e) { - ccprintf("Invalid slave_addr %s\n", argv[1]); + ccprintf("Invalid addr %s\n", argv[1]); return EC_ERROR_INVAL; } reg = strtoi(argv[2], &e, 0); @@ -301,15 +299,15 @@ static int command_i2c_wedge(int argc, char **argv) if (wedge_flag & WEDGE_WRITE) { if (wedge_bit_count < 0) wedge_bit_count = 8; - i2c_bang_wedge_write(slave_addr, reg, wedge_bit_count, - (wedge_flag & WEDGE_REBOOT)); + i2c_bang_wedge_write(addr, reg, wedge_bit_count, + (wedge_flag & WEDGE_REBOOT)); } else if (wedge_flag & WEDGE_READ) { if (wedge_bit_count < 0) wedge_bit_count = 2; - i2c_bang_wedge_read(slave_addr, reg, wedge_bit_count, - (wedge_flag & WEDGE_REBOOT)); + i2c_bang_wedge_read(addr, reg, wedge_bit_count, + (wedge_flag & WEDGE_REBOOT)); } else { - i2c_bang_xfer(slave_addr, reg); + i2c_bang_xfer(addr, reg); } /* Put it back into normal mode */ @@ -325,17 +323,15 @@ static int command_i2c_wedge(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(i2cwedge, command_i2c_wedge, - "i2cwedge slave_addr out_byte " - "[wedge_flag [wedge_bit_count]]", + "i2cwedge addr out_byte " + "[wedge_flag [wedge_bit_count]]", "Wedge host I2C bus"); -static int command_i2c_unwedge(int argc, char **argv) +static int command_i2c_unwedge(int argc, const char **argv) { i2c_unwedge(I2C_PORT_HOST); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(i2cunwedge, command_i2c_unwedge, - "", - "Unwedge host I2C bus"); - +DECLARE_CONSOLE_COMMAND(i2cunwedge, command_i2c_unwedge, "", + "Unwedge host I2C bus"); diff --git a/common/inductive_charging.c b/common/inductive_charging.c index 793f535afe..9700e37dcc 100644 --- a/common/inductive_charging.c +++ b/common/inductive_charging.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/common/init_rom.c b/common/init_rom.c index fd796f7fe9..ad9e80f423 100644 --- a/common/init_rom.c +++ b/common/init_rom.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,8 +7,8 @@ #include "builtin/assert.h" #include "common.h" -#include "init_rom.h" #include "flash.h" +#include "init_rom.h" #include "stdbool.h" #include "stddef.h" @@ -43,11 +43,11 @@ const void *init_rom_map(const void *addr, int size) /* * Convert flash offset to memory mapped address */ - if (flash_dataptr((int)offset, size, 1, &src) < 0) + if (crec_flash_dataptr((int)offset, size, 1, &src) < 0) return NULL; /* Once the flash offset is validated, lock the flash for the caller */ - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); return src; } @@ -59,11 +59,10 @@ const void *init_rom_map(const void *addr, int size) void init_rom_unmap(const void *addr, int size) { if (IS_ENABLED(CONFIG_CHIP_INIT_ROM_REGION)) - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); } int init_rom_copy(int offset, int size, char *data) { - return flash_read(offset, size, data); + return crec_flash_read(offset, size, data); } - diff --git a/common/ioexpander.c b/common/ioexpander.c index c5c06ee8e1..0a08f37c46 100644 --- a/common/ioexpander.c +++ b/common/ioexpander.c @@ -1,38 +1,19 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* IO Expander Controller Common Code */ -#include "console.h" +#include "builtin/assert.h" #include "gpio.h" #include "hooks.h" #include "ioexpander.h" #include "system.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_GPIO, format, ## args) -#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args) - -static uint8_t last_val[(IOEX_COUNT + 7) / 8]; - -static int last_val_changed(enum ioex_signal signal, int v) -{ - const int i = signal - IOEX_SIGNAL_START; - - ASSERT(signal_is_ioex(signal)); - - if (v && !(last_val[i / 8] & (BIT(i % 8)))) { - last_val[i / 8] |= BIT(i % 8); - return 1; - } else if (!v && last_val[i / 8] & (BIT(i % 8))) { - last_val[i / 8] &= ~(BIT(i % 8)); - return 1; - } else { - return 0; - } -} +#define CPRINTF(format, args...) cprintf(CC_GPIO, format, ##args) +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) int signal_is_ioex(int signal) { @@ -47,7 +28,7 @@ static const struct ioex_info *ioex_get_signal_info(enum ioex_signal signal) g = ioex_list + signal - IOEX_SIGNAL_START; - if (ioex_config[g->ioex].flags & IOEX_FLAGS_DISABLED) { + if (!(ioex_config[g->ioex].flags & IOEX_FLAGS_INITIALIZED)) { CPRINTS("ioex %s disabled", g->name); return NULL; } @@ -79,6 +60,7 @@ static int ioex_is_valid_interrupt_signal(enum ioex_signal signal) return EC_SUCCESS; } + int ioex_enable_interrupt(enum ioex_signal signal) { int rv; @@ -87,7 +69,7 @@ int ioex_enable_interrupt(enum ioex_signal signal) rv = ioex_is_valid_interrupt_signal(signal); if (rv != EC_SUCCESS) - return rv; + return rv; drv = ioex_config[g->ioex].drv; return drv->enable_interrupt(g->ioex, g->port, g->mask, 1); @@ -101,12 +83,24 @@ int ioex_disable_interrupt(enum ioex_signal signal) rv = ioex_is_valid_interrupt_signal(signal); if (rv != EC_SUCCESS) - return rv; + return rv; drv = ioex_config[g->ioex].drv; return drv->enable_interrupt(g->ioex, g->port, g->mask, 0); } +int ioex_get_ioex_flags(enum ioex_signal signal, int *val) +{ + const struct ioex_info *g = ioex_get_signal_info(signal); + + if (g == NULL) + return EC_ERROR_BUSY; + + *val = ioex_config[g->ioex].flags; + + return EC_SUCCESS; +} + int ioex_get_flags(enum ioex_signal signal, int *flags) { const struct ioex_info *g = ioex_get_signal_info(signal); @@ -114,8 +108,8 @@ int ioex_get_flags(enum ioex_signal signal, int *flags) if (g == NULL) return EC_ERROR_BUSY; - return ioex_config[g->ioex].drv->get_flags_by_mask(g->ioex, - g->port, g->mask, flags); + return ioex_config[g->ioex].drv->get_flags_by_mask(g->ioex, g->port, + g->mask, flags); } int ioex_set_flags(enum ioex_signal signal, int flags) @@ -125,8 +119,8 @@ int ioex_set_flags(enum ioex_signal signal, int flags) if (g == NULL) return EC_ERROR_BUSY; - return ioex_config[g->ioex].drv->set_flags_by_mask(g->ioex, - g->port, g->mask, flags); + return ioex_config[g->ioex].drv->set_flags_by_mask(g->ioex, g->port, + g->mask, flags); } int ioex_get_level(enum ioex_signal signal, int *val) @@ -136,8 +130,8 @@ int ioex_get_level(enum ioex_signal signal, int *val) if (g == NULL) return EC_ERROR_BUSY; - return ioex_config[g->ioex].drv->get_level(g->ioex, g->port, - g->mask, val); + return ioex_config[g->ioex].drv->get_level(g->ioex, g->port, g->mask, + val); } int ioex_set_level(enum ioex_signal signal, int value) @@ -147,8 +141,72 @@ int ioex_set_level(enum ioex_signal signal, int value) if (g == NULL) return EC_ERROR_BUSY; - return ioex_config[g->ioex].drv->set_level(g->ioex, g->port, - g->mask, value); + return ioex_config[g->ioex].drv->set_level(g->ioex, g->port, g->mask, + value); +} + +#ifdef CONFIG_IO_EXPANDER_SUPPORT_GET_PORT +int ioex_get_port(int ioex, int port, int *val) +{ + if (ioex_config[ioex].drv->get_port == NULL) + return EC_ERROR_UNIMPLEMENTED; + + return ioex_config[ioex].drv->get_port(ioex, port, val); +} +#endif + +int ioex_save_gpio_state(int ioex, int *state, int state_len) +{ + int rv; + const struct ioex_info *g = ioex_list; + const struct ioexpander_drv *drv = ioex_config[ioex].drv; + int state_offset = 0; + + for (int i = 0; i < IOEX_COUNT; i++, g++) { + if (g->ioex != ioex) + continue; + + if (state_offset >= state_len) { + CPRINTS("%s state buffer is too small", __func__); + return EC_ERROR_UNKNOWN; + } + + rv = drv->get_flags_by_mask(g->ioex, g->port, g->mask, + &state[state_offset++]); + if (rv) { + CPRINTS("%s failed to get flags rv=%d", __func__, rv); + return rv; + } + } + + return EC_SUCCESS; +} + +int ioex_restore_gpio_state(int ioex, const int *state, int state_len) +{ + int rv; + const struct ioex_info *g = ioex_list; + const struct ioexpander_drv *drv = ioex_config[ioex].drv; + int state_offset = 0; + + for (int i = 0; i < IOEX_COUNT; i++, g++) { + if (g->ioex != ioex) + continue; + + if (state_offset >= state_len) { + CPRINTS("%s state buffer is too small", __func__); + return EC_ERROR_UNKNOWN; + } + + rv = drv->set_flags_by_mask(g->ioex, g->port, g->mask, + state[state_offset++]); + if (rv) { + CPRINTS("%s failed to set flags rv=%d", __func__, rv); + return rv; + } + } + + return EC_SUCCESS; } int ioex_init(int ioex) @@ -158,9 +216,6 @@ int ioex_init(int ioex) int rv; int i; - if (ioex_config[ioex].flags & IOEX_FLAGS_DISABLED) - return EC_ERROR_BUSY; - if (drv->init != NULL) { rv = drv->init(ioex); if (rv != EC_SUCCESS) @@ -179,11 +234,14 @@ int ioex_init(int ioex) if (system_jumped_late()) flags &= ~(GPIO_LOW | GPIO_HIGH); - drv->set_flags_by_mask(g->ioex, g->port, - g->mask, flags); + drv->set_flags_by_mask(g->ioex, g->port, g->mask, + flags); } } + ioex_config[ioex].flags &= ~IOEX_FLAGS_DEFAULT_INIT_DISABLED; + ioex_config[ioex].flags |= IOEX_FLAGS_INITIALIZED; + return EC_SUCCESS; } @@ -191,8 +249,17 @@ static void ioex_init_default(void) { int i; - for (i = 0; i < CONFIG_IO_EXPANDER_PORT_COUNT; i++) + for (i = 0; i < CONFIG_IO_EXPANDER_PORT_COUNT; i++) { + /* + * If the IO Expander has been initialized or if the default + * initialization is disabled, skip initializing. + */ + if (ioex_config[i].flags & + (IOEX_FLAGS_INITIALIZED | IOEX_FLAGS_DEFAULT_INIT_DISABLED)) + continue; + ioex_init(i); + } } DECLARE_HOOK(HOOK_INIT, ioex_init_default, HOOK_PRIO_INIT_I2C + 1); @@ -202,126 +269,3 @@ const char *ioex_get_name(enum ioex_signal signal) return g->name; } - -static void print_ioex_info(enum ioex_signal signal) -{ - int changed, v, val; - int flags = 0; - const struct ioex_info *g = ioex_list + signal - IOEX_SIGNAL_START; - - if (ioex_config[g->ioex].flags & IOEX_FLAGS_DISABLED) { - ccprintf(" DISABLED %s\n", ioex_get_name(signal)); - return; - } - - - v = ioex_get_level(signal, &val); - if (v) { - ccprintf("Fail to get %s level\n", ioex_get_name(signal)); - return; - } - v = ioex_get_flags(signal, &flags); - if (v) { - ccprintf("Fail to get %s flags\n", ioex_get_name(signal)); - return; - } - - changed = last_val_changed(signal, val); - - ccprintf(" %d%c %s%s%s%s%s%s\n", val, - (changed ? '*' : ' '), - (flags & GPIO_INPUT ? "I " : ""), - (flags & GPIO_OUTPUT ? "O " : ""), - (flags & GPIO_LOW ? "L " : ""), - (flags & GPIO_HIGH ? "H " : ""), - (flags & GPIO_OPEN_DRAIN ? "ODR " : ""), - ioex_get_name(signal)); - - /* Flush console to avoid truncating output */ - cflush(); -} - -static int ioex_get_default_flags(enum ioex_signal signal) -{ - const struct ioex_info *g = ioex_get_signal_info(signal); - - if (g == NULL) - return 0; - - return g->flags; -} - -/* IO expander commands */ -static enum ioex_signal find_ioex_by_name(const char *name) -{ - int i; - - if (!name) - return -1; - - for (i = IOEX_SIGNAL_START; i < IOEX_SIGNAL_END; i++) { - if (!strcasecmp(name, ioex_get_name(i))) - return i; - } - - return -1; -} - -static enum ec_error_list ioex_set(const char *name, int value) -{ - enum ioex_signal signal = find_ioex_by_name(name); - - if (signal == -1) - return EC_ERROR_INVAL; - - if (!(ioex_get_default_flags(signal) & GPIO_OUTPUT)) - return EC_ERROR_INVAL; - - return ioex_set_level(signal, value); -} - -static int command_ioex_set(int argc, char **argv) -{ - char *e; - int v; - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - v = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - if (ioex_set(argv[1], v) != EC_SUCCESS) - return EC_ERROR_PARAM1; - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(ioexset, command_ioex_set, - "name <0 | 1>", - "Set level of a IO expander IO"); - -static int command_ioex_get(int argc, char **argv) -{ - int i; - - /* If a signal is specified, print only that one */ - if (argc == 2) { - i = find_ioex_by_name(argv[1]); - if (i == -1) - return EC_ERROR_PARAM1; - print_ioex_info(i); - - return EC_SUCCESS; - } - - /* Otherwise print them all */ - for (i = IOEX_SIGNAL_START; i < IOEX_SIGNAL_END; i++) - print_ioex_info(i); - - return EC_SUCCESS; -} -DECLARE_SAFE_CONSOLE_COMMAND(ioexget, command_ioex_get, - "[name]", - "Read level of IO expander pin(s)"); - diff --git a/common/ioexpander_commands.c b/common/ioexpander_commands.c new file mode 100644 index 0000000000..38ab82565a --- /dev/null +++ b/common/ioexpander_commands.c @@ -0,0 +1,144 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "builtin/assert.h" +#include "console.h" +#include "gpio.h" +#include "ioexpander.h" +#include "util.h" + +static uint8_t last_val[(IOEX_COUNT + 7) / 8]; + +static int last_val_changed(enum ioex_signal signal, int v) +{ + const int i = signal - IOEX_SIGNAL_START; + + ASSERT(signal_is_ioex(signal)); + + if (v && !(last_val[i / 8] & (BIT(i % 8)))) { + last_val[i / 8] |= BIT(i % 8); + return 1; + } else if (!v && last_val[i / 8] & (BIT(i % 8))) { + last_val[i / 8] &= ~(BIT(i % 8)); + return 1; + } else { + return 0; + } +} + +static enum ioex_signal find_ioex_by_name(const char *name) +{ + enum ioex_signal signal; + + if (!name) + return IOEX_SIGNAL_END; + + for (signal = IOEX_SIGNAL_START; signal < IOEX_SIGNAL_END; signal++) { + if (!strcasecmp(name, ioex_get_name(signal))) + return signal; + } + + return IOEX_SIGNAL_END; +} + +static void print_ioex_info(enum ioex_signal signal) +{ + int changed, v, val; + int flags = 0; + + if (ioex_get_ioex_flags(signal, &flags)) { + ccprintf(" ERROR getting flags\n"); + return; + } + + if (!(flags & IOEX_FLAGS_INITIALIZED)) { + ccprintf(" DISABLED %s\n", ioex_get_name(signal)); + return; + } + + v = ioex_get_level(signal, &val); + if (v) { + ccprintf("Fail to get %s level\n", ioex_get_name(signal)); + return; + } + v = ioex_get_flags(signal, &flags); + if (v) { + ccprintf("Fail to get %s flags\n", ioex_get_name(signal)); + return; + } + + changed = last_val_changed(signal, val); + + ccprintf(" %d%c %s%s%s%s%s%s\n", val, (changed ? '*' : ' '), + (flags & GPIO_INPUT ? "I " : ""), + (flags & GPIO_OUTPUT ? "O " : ""), + (flags & GPIO_LOW ? "L " : ""), + (flags & GPIO_HIGH ? "H " : ""), + (flags & GPIO_OPEN_DRAIN ? "ODR " : ""), + ioex_get_name(signal)); + + /* Flush console to avoid truncating output */ + cflush(); +} + +static enum ec_error_list ioex_set(const char *name, int value) +{ + enum ioex_signal signal = find_ioex_by_name(name); + int flags; + + if (!signal_is_ioex(signal)) + return EC_ERROR_INVAL; + + if (ioex_get_flags(signal, &flags)) + return EC_ERROR_INVAL; + + if (!(flags & GPIO_OUTPUT)) + return EC_ERROR_INVAL; + + return ioex_set_level(signal, value); +} + +static int command_ioex_set(int argc, const char **argv) +{ + char *e; + int v; + + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + + v = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + if (ioex_set(argv[1], v) != EC_SUCCESS) + return EC_ERROR_PARAM1; + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(ioexset, command_ioex_set, "name <0 | 1>", + "Set level of a IO expander pin"); + +static int command_ioex_get(int argc, const char **argv) +{ + enum ioex_signal signal; + + /* If a signal is specified, print only that one */ + if (argc == 2) { + signal = find_ioex_by_name(argv[1]); + if (!signal_is_ioex(signal)) + return EC_ERROR_PARAM1; + print_ioex_info(signal); + + return EC_SUCCESS; + } + + /* Otherwise print them all */ + for (signal = IOEX_SIGNAL_START; signal < IOEX_SIGNAL_END; signal++) + print_ioex_info(signal); + + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(ioexget, command_ioex_get, "[name]", + "Read level of IO expander pin(s)"); diff --git a/common/irq_locking.c b/common/irq_locking.c new file mode 100644 index 0000000000..1146145c5e --- /dev/null +++ b/common/irq_locking.c @@ -0,0 +1,32 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * This file is used for platform/ec implementations of irq_lock and irq_unlock + * which are defined by Zephyr. + */ + +#include "task.h" +#include "util.h" + +static uint32_t lock_count; + +uint32_t irq_lock(void) +{ + interrupt_disable(); + return lock_count++; +} + +void irq_unlock(uint32_t key) +{ + lock_count = key; + + /* + * Since we're allowing nesting locks, we only actually want to release + * the lock if the lock count reached 0. + */ + if (lock_count == 0) + interrupt_enable(); +} diff --git a/common/kasa.c b/common/kasa.c index 79c75ad55b..0ab716c729 100644 --- a/common/kasa.c +++ b/common/kasa.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,7 @@ #include "common.h" #include "kasa.h" #include "mat44.h" + #include void kasa_reset(struct kasa_fit *kasa) diff --git a/common/keyboard_8042.c b/common/keyboard_8042.c index 4e3a5b4b98..26b424dd0f 100644 --- a/common/keyboard_8042.c +++ b/common/keyboard_8042.c @@ -1,12 +1,14 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * 8042 keyboard protocol */ -#include "chipset.h" +#include "atkbd_protocol.h" +#include "builtin/assert.h" #include "button.h" +#include "chipset.h" #include "common.h" #include "console.h" #include "device_event.h" @@ -28,28 +30,39 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_KEYBOARD, outstr) -#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ##args) #ifdef CONFIG_KEYBOARD_DEBUG #define CPUTS5(outstr) cputs(CC_KEYBOARD, outstr) -#define CPRINTS5(format, args...) cprints(CC_KEYBOARD, format, ## args) +#define CPRINTS5(format, args...) cprints(CC_KEYBOARD, format, ##args) #else #define CPUTS5(outstr) #define CPRINTS5(format, args...) #endif +/* + * This command needs malloc to work. Could we use this instead? + * + * #define CMD_KEYBOARD_LOG IS_ENABLED(CONFIG_MALLOC) + */ +#ifdef CONFIG_MALLOC +#define CMD_KEYBOARD_LOG 1 +#else +#define CMD_KEYBOARD_LOG 0 +#endif + static enum { - STATE_NORMAL = 0, - STATE_SCANCODE, - STATE_SETLEDS, - STATE_EX_SETLEDS_1, /* Expect 2-byte parameter */ - STATE_EX_SETLEDS_2, - STATE_WRITE_CMD_BYTE, - STATE_WRITE_OUTPUT_PORT, - STATE_ECHO_MOUSE, - STATE_SETREP, - STATE_SEND_TO_MOUSE, -} data_port_state = STATE_NORMAL; + STATE_ATKBD_CMD = 0, + STATE_ATKBD_SCANCODE, + STATE_ATKBD_SETLEDS, + STATE_ATKBD_EX_SETLEDS_1, /* Expect 2-byte parameter */ + STATE_ATKBD_EX_SETLEDS_2, + STATE_8042_WRITE_CMD_BYTE, + STATE_8042_WRITE_OUTPUT_PORT, + STATE_8042_ECHO_MOUSE, + STATE_ATKBD_SETREP, + STATE_8042_SEND_TO_MOUSE, +} data_port_state = STATE_ATKBD_CMD; enum scancode_set_list { SCANCODE_GET_SET = 0, @@ -64,16 +77,30 @@ enum scancode_set_list { /* Number of bytes host can get behind before we start generating extra IRQs */ #define KB_TO_HOST_RETRIES 3 +/* + * Timeout for SETLEDS command. Kernel is supposed to send the second byte + * within this period. When timeout occurs, the second byte is received as + * 'Unsupported AT keyboard command 0x00' (or 0x04). You can evaluate your + * timeout is too long or too short by calculating the duration between 'KB + * SETLEDS' and 'Unsupported AT...'. + */ +#define SETLEDS_TIMEOUT (30 * MSEC) + /* * Mutex to control write access to the to-host buffer head. Don't need to * mutex the tail because reads are only done in one place. */ -static struct mutex to_host_mutex; +K_MUTEX_DEFINE(to_host_mutex); + +#if defined(CONFIG_PLATFORM_EC_CUSTOMIZED_DESIGN) +K_MUTEX_DEFINE(from_host_mutex); +#endif /* Queue command/data to the host */ enum { CHAN_KBD = 0, CHAN_AUX, + CHAN_CMD, }; struct data_byte { uint8_t chan; @@ -81,6 +108,7 @@ struct data_byte { }; static struct queue const to_host = QUEUE_NULL(16, struct data_byte); +static struct queue const to_host_cmd = QUEUE_NULL(16, struct data_byte); /* Queue command/data from the host */ enum { @@ -112,9 +140,12 @@ static int i8042_keyboard_irq_enabled; static int i8042_aux_irq_enabled; /* i8042 global settings */ -static int keyboard_enabled; /* default the keyboard is disabled. */ -static int aux_chan_enabled; /* default the mouse is disabled. */ -static int keystroke_enabled; /* output keystrokes */ +#ifdef CONFIG_BOARD_AZALEA +static bool to_host_queue_paused; +#endif +static int keyboard_enabled; /* default the keyboard is disabled. */ +static int aux_chan_enabled; /* default the mouse is disabled. */ +static int keystroke_enabled; /* output keystrokes */ static uint8_t resend_command[MAX_SCAN_CODE_LEN]; static uint8_t resend_command_len; static uint8_t controller_ram_address; @@ -142,15 +173,16 @@ static enum scancode_set_list scancode_set = SCANCODE_SET_2; * the inter-char delay = (2 ** B) * (D + 8) / 240 (sec) * Default: 500ms delay, 10.9 chars/sec. */ -#define DEFAULT_TYPEMATIC_VALUE (BIT(5) | BIT(3) | (3 << 0)) +#define DEFAULT_TYPEMATIC_VALUE (BIT(5) | (3 << 0)) static uint8_t typematic_value_from_host; static int typematic_first_delay; static int typematic_inter_delay; -static int typematic_len; /* length of typematic_scan_code */ +static int typematic_len; /* length of typematic_scan_code */ static uint8_t typematic_scan_code[MAX_SCAN_CODE_LEN]; static timestamp_t typematic_deadline; +static timestamp_t setleds_deadline; -#define KB_SYSJUMP_TAG 0x4b42 /* "KB" */ +#define KB_SYSJUMP_TAG 0x4b42 /* "KB" */ #define KB_HOOK_VERSION 2 /* the previous keyboard state before reboot_ec. */ struct kb_state { @@ -163,24 +195,22 @@ struct kb_state { /* Keyboard event log */ /* Log the traffic between EC and host -- for debug only */ -#define MAX_KBLOG 512 /* Max events in keyboard log */ +#define MAX_KBLOG 512 /* Max events in keyboard log */ struct kblog_t { /* * Type: * - * s = byte enqueued to send to host * a = aux byte enqueued to send to host - * t = to-host queue tail pointer before type='s' bytes enqueued - * - * d = data byte from host * c = command byte from host - * - * k = to-host queue head pointer before byte dequeued - * K = byte actually sent to host via LPC - * A = byte actually sent to host via LPC as AUX - * + * d = data byte from host + * r = typematic + * s = byte enqueued to send to host + * t = to-host queue tail pointer before type='s' bytes enqueued + * u = byte enqueued to send to host with priority * x = to_host queue was cleared + * A = byte actually sent to host via LPC as AUX + * K = byte actually sent to host via LPC * * The to-host head and tail pointers are logged pre-wrapping to the * queue size. This means that they continually increment as units @@ -191,8 +221,8 @@ struct kblog_t { uint8_t byte; }; -static struct kblog_t *kblog_buf; /* Log buffer; NULL if not logging */ -static int kblog_len; /* Current log length */ +static struct kblog_t *kblog_buf; /* Log buffer; NULL if not logging */ +static int kblog_len; /* Current log length */ /** * Add event to keyboard log. @@ -215,9 +245,17 @@ void keyboard_host_write(int data, int is_cmd) h.type = is_cmd ? HOST_COMMAND : HOST_DATA; h.byte = data; queue_add_unit(&from_host, &h); +#if defined(CONFIG_THIRD_PARTY_CUSTOMIZED_DESIGN) + lpc_kbc_ibf_clear(); +#endif task_wake(TASK_ID_KEYPROTO); } +int keyboard_host_write_avaliable(void) +{ + return queue_space(&from_host); +} + /** * Enable keyboard IRQ generation. * @@ -252,11 +290,11 @@ static void aux_enable_irq(int enable) * host cannot read the previous byte away in time. * * @param len Number of bytes to send to the host - * @param to_host Data to send + * @param bytes Data to send * @param chan Channel to send data on */ -static void i8042_send_to_host(int len, const uint8_t *bytes, - uint8_t chan) +static void i8042_send_to_host(int len, const uint8_t *bytes, uint8_t chan, + int is_typematic) { int i; struct data_byte data; @@ -264,15 +302,34 @@ static void i8042_send_to_host(int len, const uint8_t *bytes, /* Enqueue output data if there's space */ mutex_lock(&to_host_mutex); - for (i = 0; i < len; i++) - kblog_put(chan == CHAN_AUX ? 'a' : 's', bytes[i]); + if (is_typematic && !typematic_len) { + for (i = 0; i < len; i++) + kblog_put('r', bytes[i]); + } else { + struct queue const *queue = &to_host; + + if (chan == CHAN_CMD) + queue = &to_host_cmd; - if (queue_space(&to_host) >= len) { - kblog_put('t', to_host.state->tail); for (i = 0; i < len; i++) { - data.chan = chan; - data.byte = bytes[i]; - queue_add_unit(&to_host, &data); + char type; + + if (chan == CHAN_AUX) + type = 'a'; + else if (chan == CHAN_CMD) + type = 'u'; + else + type = 's'; + kblog_put(type, bytes[i]); + } + + if (queue_space(queue) >= len) { + kblog_put('t', queue->state->tail); + for (i = 0; i < len; i++) { + data.chan = chan; + data.byte = bytes[i]; + queue_add_unit(queue, &data); + } } } mutex_unlock(&to_host_mutex); @@ -353,8 +410,8 @@ static enum ec_error_list matrix_callback(int8_t row, int8_t col, #ifdef CONFIG_KEYBOARD_SCANCODE_CALLBACK { - enum ec_error_list r = keyboard_scancode_callback( - &make_code, pressed); + enum ec_error_list r = + keyboard_scancode_callback(&make_code, pressed); if (r != EC_SUCCESS) return r; } @@ -381,14 +438,14 @@ static enum ec_error_list matrix_callback(int8_t row, int8_t col, static void set_typematic_delays(uint8_t data) { typematic_value_from_host = data; - typematic_first_delay = MSEC * - (((typematic_value_from_host & 0x60) >> 5) + 1) * 250; - typematic_inter_delay = SECOND * - (1 << ((typematic_value_from_host & 0x18) >> 3)) * + typematic_first_delay = + MSEC * (((typematic_value_from_host & 0x60) >> 5) + 1) * 250; + typematic_inter_delay = + SECOND * (1 << ((typematic_value_from_host & 0x18) >> 3)) * ((typematic_value_from_host & 0x7) + 8) / 240; } -static void reset_rate_and_delay(void) +test_export_static void reset_rate_and_delay(void) { set_typematic_delays(DEFAULT_TYPEMATIC_VALUE); } @@ -399,6 +456,7 @@ void keyboard_clear_buffer(void) mutex_lock(&to_host_mutex); kblog_put('x', queue_count(&to_host)); queue_init(&to_host); + queue_init(&to_host_cmd); mutex_unlock(&to_host_mutex); lpc_keyboard_clear_buffer(); } @@ -408,7 +466,7 @@ static void keyboard_wakeup(void) host_set_single_event(EC_HOST_EVENT_KEY_PRESSED); } -static void set_typematic_key(const uint8_t *scan_code, int32_t len) +test_export_static void set_typematic_key(const uint8_t *scan_code, int32_t len) { typematic_deadline.val = get_time().val + typematic_first_delay; memcpy(typematic_scan_code, scan_code, len); @@ -427,11 +485,12 @@ void keyboard_state_changed(int row, int col, int is_pressed) enum ec_error_list ret; #ifdef CONFIG_KEYBOARD_DEBUG - char mylabel = get_keycap_label(row, col); + uint8_t mylabel = get_keycap_label(row, col); if (mylabel & KEYCAP_LONG_LABEL_BIT) CPRINTS("KB (%d,%d)=%d %s", row, col, is_pressed, - get_keycap_long_label(mylabel & KEYCAP_LONG_LABEL_INDEX_BITMASK)); + get_keycap_long_label(mylabel & + KEYCAP_LONG_LABEL_INDEX_BITMASK)); else CPRINTS("KB (%d,%d)=%d %c", row, col, is_pressed, mylabel); #endif @@ -441,7 +500,7 @@ void keyboard_state_changed(int row, int col, int is_pressed) if (ret == EC_SUCCESS) { ASSERT(len > 0); if (keystroke_enabled) - i8042_send_to_host(len, scan_code, CHAN_KBD); + i8042_send_to_host(len, scan_code, CHAN_KBD, 0); } if (is_pressed) { @@ -452,7 +511,17 @@ void keyboard_state_changed(int row, int col, int is_pressed) clear_typematic_key(); } } +#ifdef CONFIG_BOARD_AZALEA +void i8042_pause_to_host_queue(bool pause) +{ + CPRINTS5("8042 %s to_host queue", pause ? "pause" : "resume"); + + to_host_queue_paused = pause; + if (!to_host_queue_paused) + task_wake(TASK_ID_KEYPROTO); +} +#endif static void keystroke_enable(int enable) { if (!keystroke_enabled && enable) @@ -505,8 +574,8 @@ static void update_ctl_ram(uint8_t addr, uint8_t data) orig = controller_ram[addr]; controller_ram[addr] = data; - CPRINTS5("KB set CTR_RAM(0x%02x)=0x%02x (old:0x%02x)", - addr, data, orig); + CPRINTS5("KB set CTR_RAM(0x%02x)=0x%02x (old:0x%02x)", addr, data, + orig); if (addr == 0x00) { /* Keyboard enable/disable */ @@ -544,19 +613,19 @@ static int handle_mouse_data(uint8_t data, uint8_t *output, int *count) int out_len = 0; switch (data_port_state) { - case STATE_ECHO_MOUSE: - CPRINTS5("STATE_ECHO_MOUSE: 0x%02x", data); + case STATE_8042_ECHO_MOUSE: + CPRINTS5("STATE_8042_ECHO_MOUSE: 0x%02x", data); output[out_len++] = data; - data_port_state = STATE_NORMAL; + data_port_state = STATE_ATKBD_CMD; break; - case STATE_SEND_TO_MOUSE: - CPRINTS5("STATE_SEND_TO_MOUSE: 0x%02x", data); + case STATE_8042_SEND_TO_MOUSE: + CPRINTS5("STATE_8042_SEND_TO_MOUSE: 0x%02x", data); send_aux_data_to_device(data); - data_port_state = STATE_NORMAL; + data_port_state = STATE_ATKBD_CMD; break; - default: /* STATE_NORMAL */ + default: /* STATE_ATKBD_CMD */ return 0; } @@ -579,120 +648,125 @@ static int handle_keyboard_data(uint8_t data, uint8_t *output) int i; switch (data_port_state) { - case STATE_SCANCODE: - CPRINTS5("KB eaten by STATE_SCANCODE: 0x%02x", data); + case STATE_ATKBD_SCANCODE: + CPRINTS5("KB eaten by STATE_ATKBD_SCANCODE: 0x%02x", data); if (data == SCANCODE_GET_SET) { - output[out_len++] = I8042_RET_ACK; + output[out_len++] = ATKBD_RET_ACK; output[out_len++] = scancode_set; } else { scancode_set = data; CPRINTS("KB scancode set to %d", scancode_set); - output[out_len++] = I8042_RET_ACK; + output[out_len++] = ATKBD_RET_ACK; } - data_port_state = STATE_NORMAL; + data_port_state = STATE_ATKBD_CMD; break; - case STATE_SETLEDS: - CPRINTS5("KB eaten by STATE_SETLEDS"); - output[out_len++] = I8042_RET_ACK; - data_port_state = STATE_NORMAL; + case STATE_ATKBD_SETLEDS: + CPRINTS5("KB eaten by STATE_ATKBD_SETLEDS"); +#ifdef CONFIG_CUSTOMIZED_DESIGN + board_caps_led_control(data); +#endif /* CONFIG_CUSTOMIZED_DESIGN */ + output[out_len++] = ATKBD_RET_ACK; + data_port_state = STATE_ATKBD_CMD; break; - case STATE_EX_SETLEDS_1: - CPRINTS5("KB eaten by STATE_EX_SETLEDS_1"); - output[out_len++] = I8042_RET_ACK; - data_port_state = STATE_EX_SETLEDS_2; + case STATE_ATKBD_EX_SETLEDS_1: + CPRINTS5("KB eaten by STATE_ATKBD_EX_SETLEDS_1"); + output[out_len++] = ATKBD_RET_ACK; + data_port_state = STATE_ATKBD_EX_SETLEDS_2; break; - case STATE_EX_SETLEDS_2: - CPRINTS5("KB eaten by STATE_EX_SETLEDS_2"); - output[out_len++] = I8042_RET_ACK; - data_port_state = STATE_NORMAL; + case STATE_ATKBD_EX_SETLEDS_2: + CPRINTS5("KB eaten by STATE_ATKBD_EX_SETLEDS_2"); + output[out_len++] = ATKBD_RET_ACK; + data_port_state = STATE_ATKBD_CMD; break; - case STATE_WRITE_CMD_BYTE: - CPRINTS5("KB eaten by STATE_WRITE_CMD_BYTE: 0x%02x", - data); + case STATE_8042_WRITE_CMD_BYTE: + CPRINTS5("KB eaten by STATE_8042_WRITE_CMD_BYTE: 0x%02x", data); update_ctl_ram(controller_ram_address, data); - data_port_state = STATE_NORMAL; + data_port_state = STATE_ATKBD_CMD; break; - case STATE_WRITE_OUTPUT_PORT: - CPRINTS5("KB eaten by STATE_WRITE_OUTPUT_PORT: 0x%02x", + case STATE_8042_WRITE_OUTPUT_PORT: + CPRINTS5("KB eaten by STATE_8042_WRITE_OUTPUT_PORT: 0x%02x", data); A20_status = (data & BIT(1)) ? 1 : 0; - data_port_state = STATE_NORMAL; + data_port_state = STATE_ATKBD_CMD; break; - case STATE_SETREP: - CPRINTS5("KB eaten by STATE_SETREP: 0x%02x", data); + case STATE_ATKBD_SETREP: + CPRINTS5("KB eaten by STATE_ATKBD_SETREP: 0x%02x", data); set_typematic_delays(data); - output[out_len++] = I8042_RET_ACK; - data_port_state = STATE_NORMAL; + output[out_len++] = ATKBD_RET_ACK; + data_port_state = STATE_ATKBD_CMD; break; - default: /* STATE_NORMAL */ + default: /* STATE_ATKBD_CMD */ switch (data) { - case I8042_CMD_GSCANSET: /* also I8042_CMD_SSCANSET */ - output[out_len++] = I8042_RET_ACK; - data_port_state = STATE_SCANCODE; + case ATKBD_CMD_GSCANSET: /* also ATKBD_CMD_SSCANSET */ + output[out_len++] = ATKBD_RET_ACK; + data_port_state = STATE_ATKBD_SCANCODE; break; - case I8042_CMD_SETLEDS: + case ATKBD_CMD_SETLEDS: /* Chrome OS doesn't have keyboard LEDs, so ignore */ - output[out_len++] = I8042_RET_ACK; - data_port_state = STATE_SETLEDS; + output[out_len++] = ATKBD_RET_ACK; + data_port_state = STATE_ATKBD_SETLEDS; + setleds_deadline.val = get_time().val + SETLEDS_TIMEOUT; + CPRINTS5("KB SETLEDS"); break; - case I8042_CMD_EX_SETLEDS: - output[out_len++] = I8042_RET_ACK; - data_port_state = STATE_EX_SETLEDS_1; + case ATKBD_CMD_EX_SETLEDS: + output[out_len++] = ATKBD_RET_ACK; + data_port_state = STATE_ATKBD_EX_SETLEDS_1; break; - case I8042_CMD_DIAG_ECHO: - output[out_len++] = I8042_RET_ACK; - output[out_len++] = I8042_CMD_DIAG_ECHO; + case ATKBD_CMD_DIAG_ECHO: + output[out_len++] = ATKBD_RET_ACK; + output[out_len++] = ATKBD_RET_ECHO; break; - case I8042_CMD_GETID: /* fall-thru */ - case I8042_CMD_OK_GETID: - output[out_len++] = I8042_RET_ACK; - output[out_len++] = 0xab; /* Regular keyboards */ + case ATKBD_CMD_GETID: /* fall-thru */ + case ATKBD_CMD_OK_GETID: + output[out_len++] = ATKBD_RET_ACK; + output[out_len++] = 0xab; /* Regular keyboards */ output[out_len++] = 0x83; break; - case I8042_CMD_SETREP: - output[out_len++] = I8042_RET_ACK; - data_port_state = STATE_SETREP; + case ATKBD_CMD_SETREP: + output[out_len++] = ATKBD_RET_ACK; + data_port_state = STATE_ATKBD_SETREP; break; - case I8042_CMD_ENABLE: - output[out_len++] = I8042_RET_ACK; + case ATKBD_CMD_ENABLE: + output[out_len++] = ATKBD_RET_ACK; keystroke_enable(1); keyboard_clear_buffer(); break; - case I8042_CMD_RESET_DIS: - output[out_len++] = I8042_RET_ACK; + case ATKBD_CMD_RESET_DIS: + output[out_len++] = ATKBD_RET_ACK; keystroke_enable(0); reset_rate_and_delay(); keyboard_clear_buffer(); break; - case I8042_CMD_RESET_DEF: - output[out_len++] = I8042_RET_ACK; + case ATKBD_CMD_RESET_DEF: + output[out_len++] = ATKBD_RET_ACK; reset_rate_and_delay(); keyboard_clear_buffer(); break; - case I8042_CMD_RESET: + case ATKBD_CMD_RESET: reset_rate_and_delay(); keyboard_clear_buffer(); - output[out_len++] = I8042_RET_ACK; + output[out_len++] = ATKBD_RET_ACK; + output[out_len++] = ATKBD_RET_TEST_SUCCESS; break; - case I8042_CMD_RESEND: + case ATKBD_CMD_RESEND: save_for_resend = 0; for (i = 0; i < resend_command_len; ++i) output[out_len++] = resend_command[i]; @@ -703,12 +777,12 @@ static int handle_keyboard_data(uint8_t data, uint8_t *output) /* U-boot hack. Just ignore; don't reply. */ break; - case I8042_CMD_SETALL_MB: /* fall-thru */ - case I8042_CMD_SETALL_MBR: - case I8042_CMD_EX_ENABLE: + case ATKBD_CMD_SETALL_MB: /* fall-thru */ + case ATKBD_CMD_SETALL_MBR: + case ATKBD_CMD_EX_ENABLE: default: - output[out_len++] = I8042_RET_NAK; - CPRINTS("KB Unsupported i8042 data 0x%02x", + output[out_len++] = ATKBD_RET_RESEND; + CPRINTS("KB Unsupported AT keyboard command 0x%02x", data); break; } @@ -752,14 +826,14 @@ static int handle_keyboard_command(uint8_t command, uint8_t *output) break; case I8042_WRITE_CMD_BYTE: - data_port_state = STATE_WRITE_CMD_BYTE; + data_port_state = STATE_8042_WRITE_CMD_BYTE; controller_ram_address = command - 0x60; break; case I8042_DIS_KB: update_ctl_ram(0, read_ctl_ram(0) | I8042_KBD_DIS); reset_rate_and_delay(); - typematic_len = 0; /* stop typematic */ + typematic_len = 0; /* stop typematic */ keyboard_clear_buffer(); break; @@ -773,16 +847,16 @@ static int handle_keyboard_command(uint8_t command, uint8_t *output) output[out_len++] = (lpc_keyboard_input_pending() ? BIT(5) : 0) | (lpc_keyboard_has_char() ? BIT(4) : 0) | - (A20_status ? BIT(1) : 0) | - 1; /* Main processor in normal mode */ + (A20_status ? BIT(1) : 0) | 1; /* Main processor in + normal mode */ break; case I8042_WRITE_OUTPUT_PORT: - data_port_state = STATE_WRITE_OUTPUT_PORT; + data_port_state = STATE_8042_WRITE_OUTPUT_PORT; break; case I8042_RESET_SELF_TEST: - output[out_len++] = 0x55; /* Self test success */ + output[out_len++] = 0x55; /* Self test success */ break; case I8042_TEST_KB_PORT: @@ -798,15 +872,15 @@ static int handle_keyboard_command(uint8_t command, uint8_t *output) break; case I8042_TEST_MOUSE: - output[out_len++] = 0; /* No error detected */ + output[out_len++] = 0; /* No error detected */ break; case I8042_ECHO_MOUSE: - data_port_state = STATE_ECHO_MOUSE; + data_port_state = STATE_8042_ECHO_MOUSE; break; case I8042_SEND_TO_MOUSE: - data_port_state = STATE_SEND_TO_MOUSE; + data_port_state = STATE_8042_SEND_TO_MOUSE; break; case I8042_SYSTEM_RESET: @@ -819,7 +893,7 @@ static int handle_keyboard_command(uint8_t command, uint8_t *output) output[out_len++] = read_ctl_ram(command - 0x20); } else if (command >= I8042_WRITE_CTL_RAM && command <= I8042_WRITE_CTL_RAM_END) { - data_port_state = STATE_WRITE_CMD_BYTE; + data_port_state = STATE_8042_WRITE_CMD_BYTE; controller_ram_address = command - 0x60; } else if (command == I8042_DISABLE_A20) { A20_status = 0; @@ -837,7 +911,7 @@ static int handle_keyboard_command(uint8_t command, uint8_t *output) reset_rate_and_delay(); keyboard_clear_buffer(); output[out_len++] = I8042_RET_NAK; - data_port_state = STATE_NORMAL; + data_port_state = STATE_ATKBD_CMD; } break; } @@ -845,30 +919,67 @@ static int handle_keyboard_command(uint8_t command, uint8_t *output) return out_len; } +#if defined(CONFIG_PLATFORM_EC_CUSTOMIZED_DESIGN) static void i8042_handle_from_host(void) { struct host_byte h; int ret_len; uint8_t output[MAX_SCAN_CODE_LEN]; - uint8_t chan = CHAN_KBD; + uint8_t chan; + + k_mutex_lock(&from_host_mutex, K_FOREVER); + while (queue_count(&from_host) > 0) { + queue_peek_units(&from_host, &h, 0, 1); + if (h.type == HOST_COMMAND) { + ret_len = handle_keyboard_command(h.byte, output); + chan = CHAN_KBD; + } else { + CPRINTS5("KB recv data: 0x%02x", h.byte); + kblog_put('d', h.byte); + + if (IS_ENABLED(CONFIG_8042_AUX) && + handle_mouse_data(h.byte, output, &ret_len)) { + chan = CHAN_AUX; + } else { + ret_len = handle_keyboard_data(h.byte, output); + chan = CHAN_CMD; + } + } + /* clear queue buffer */ + queue_advance_head(&from_host, 1); + i8042_send_to_host(ret_len, output, chan, 0); + } + k_mutex_unlock(&from_host_mutex); +} +#else +static void i8042_handle_from_host(void) +{ + struct host_byte h; + int ret_len; + uint8_t output[MAX_SCAN_CODE_LEN]; + uint8_t chan; while (queue_remove_unit(&from_host, &h)) { if (h.type == HOST_COMMAND) { ret_len = handle_keyboard_command(h.byte, output); + chan = CHAN_KBD; } else { CPRINTS5("KB recv data: 0x%02x", h.byte); kblog_put('d', h.byte); if (IS_ENABLED(CONFIG_8042_AUX) && - handle_mouse_data(h.byte, output, &ret_len)) + handle_mouse_data(h.byte, output, &ret_len)) { chan = CHAN_AUX; - else + } else { ret_len = handle_keyboard_data(h.byte, output); + chan = CHAN_CMD; + } } - i8042_send_to_host(ret_len, output, chan); + i8042_send_to_host(ret_len, output, chan, 0); } } +#endif void keyboard_protocol_task(void *u) { @@ -894,23 +1005,32 @@ void keyboard_protocol_task(void *u) if (keystroke_enabled) i8042_send_to_host(typematic_len, typematic_scan_code, - CHAN_KBD); - typematic_deadline.val = t.val + - typematic_inter_delay; + CHAN_KBD, 1); + typematic_deadline.val = + t.val + typematic_inter_delay; wait = typematic_inter_delay; } else { /* Wait for remaining interval */ wait = typematic_deadline.val - t.val; } - +#ifdef CONFIG_BOARD_AZALEA + if (to_host_queue_paused) { + CPRINTS5("i8042 to_host queue is paused"); + break; + } +#endif /* Handle command/data write from host */ i8042_handle_from_host(); /* Check if we have data to send to host */ - if (queue_is_empty(&to_host)) + if (queue_is_empty(&to_host) && + queue_is_empty(&to_host_cmd)) break; - /* Handle data waiting for host */ + /* + * Check if the output buffer is full. We can't proceed + * until the host read the data. + */ if (lpc_keyboard_has_char()) { /* If interrupts disabled, nothing we can do */ if (!i8042_keyboard_irq_enabled && @@ -928,26 +1048,71 @@ void keyboard_protocol_task(void *u) * data? Send it another interrupt in case it * somehow missed the first one. */ - CPRINTS("KB extra IRQ"); + CPRINTS("KB host not responding"); lpc_keyboard_resume_irq(); retries = 0; break; } + /* + * We know DBBOUT is empty but we need act quickly as + * the host might be sending a byte to DBBIN. + * + * So be cautious if you're adding any code below up to + * lpc_keyboard_put_char since that'll increase the race + * condition. For example, you don't want to add CPRINTS + * or kblog_put. + * + * We should claim OBF=1 atomically to prevent the host + * from writing to DBBIN (i.e. set-ibf-if-not-obf). It's + * not possible for NPCX because NPCX's HIKMST-IBF is + * read-only. + */ + /* Get a char from buffer. */ - kblog_put('k', to_host.state->head); - queue_remove_unit(&to_host, &entry); + if (queue_count(&to_host_cmd)) { + queue_remove_unit(&to_host_cmd, &entry); + } else if (data_port_state == STATE_ATKBD_SETLEDS) { + /* + * to_host_cmd == empty and to_host != empty. + * We're in SETLEDS thus expecting the 2nd byte. + * Until timer expires, don't process scancode. + */ + if (!timestamp_expired(setleds_deadline, &t)) { + /* + * Let's wait for the 2nd byte but we + * don't want to wait too long because + * we already have scancode to send. + */ + if (wait == -1 || + wait > setleds_deadline.val - t.val) + wait = setleds_deadline.val - + t.val; + break; + } + /* + * Didn't receive 2nd byte. Go back to CMD. We + * don't need to cancel the timer because going + * back to CMD state implicitly disables timer. + */ + CPRINTS("KB SETLEDS timeout"); + data_port_state = STATE_ATKBD_CMD; + queue_remove_unit(&to_host, &entry); + } else { + /* to_host isn't empty && not in SETLEDS */ + queue_remove_unit(&to_host, &entry); + } /* Write to host. */ if (entry.chan == CHAN_AUX && IS_ENABLED(CONFIG_8042_AUX)) { - kblog_put('A', entry.byte); lpc_aux_put_char(entry.byte, i8042_aux_irq_enabled); + kblog_put('A', entry.byte); } else { - kblog_put('K', entry.byte); lpc_keyboard_put_char( entry.byte, i8042_keyboard_irq_enabled); + kblog_put('K', entry.byte); } retries = 0; } @@ -959,13 +1124,13 @@ static void send_aux_data_to_host_deferred(void) uint8_t data; if (IS_ENABLED(CONFIG_DEVICE_EVENT) && - chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) device_set_single_event(EC_DEVICE_EVENT_TRACKPAD); while (!queue_is_empty(&aux_to_host_queue)) { queue_remove_unit(&aux_to_host_queue, &data); if (aux_chan_enabled && IS_ENABLED(CONFIG_8042_AUX)) - i8042_send_to_host(1, &data, CHAN_AUX); + i8042_send_to_host(1, &data, CHAN_AUX, 0); else CPRINTS("AUX Callback ignored"); } @@ -1021,15 +1186,51 @@ test_mockable void keyboard_update_button(enum keyboard_button_type button, } if (keystroke_enabled) { - i8042_send_to_host(len, scan_code, CHAN_KBD); + CPRINTS5("KB UPDATE BTN"); + + i8042_send_to_host(len, scan_code, CHAN_KBD, 0); task_wake(TASK_ID_KEYPROTO); } } +#ifdef CONFIG_CUSTOMIZED_DESIGN +void simulate_keyboard(uint16_t scancode, int is_pressed) +{ + uint8_t scan_code[MAX_SCAN_CODE_LEN]; + uint32_t len; + enum scancode_set_list code_set; + + /* + * Only send the scan code if main chipset is fully awake and + * keystrokes are enabled. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) || + !keystroke_enabled || + chipset_in_state(CHIPSET_STATE_SUSPEND)) + return; + + code_set = acting_code_set(scancode_set); + if (!is_supported_code_set(code_set)) + return; + + scancode_bytes(scancode, is_pressed, code_set, scan_code, + &len); + ASSERT(len > 0); + + if (is_pressed) + set_typematic_key(scan_code, len); + else + clear_typematic_key(); + if (keystroke_enabled) { + i8042_send_to_host(len, scan_code, CHAN_KBD, 0); + task_wake(TASK_ID_KEYPROTO); + } +} +#endif /* CONFIG_CUSTOMIZED_DESIGN */ /*****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_KEYBOARD -static int command_typematic(int argc, char **argv) +static int command_typematic(int argc, const char **argv) { int i; @@ -1050,18 +1251,14 @@ static int command_typematic(int argc, char **argv) ccputs("}\n"); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(typematic, command_typematic, - "[first] [inter]", - "Get/set typematic delays"); - -static int command_codeset(int argc, char **argv) +static int command_codeset(int argc, const char **argv) { if (argc == 2) { int set = strtoi(argv[1], NULL, 0); switch (set) { - case SCANCODE_SET_1: /* fall-thru */ - case SCANCODE_SET_2: /* fall-thru */ + case SCANCODE_SET_1: /* fall-thru */ + case SCANCODE_SET_2: /* fall-thru */ scancode_set = set; break; default: @@ -1073,12 +1270,8 @@ static int command_codeset(int argc, char **argv) ccprintf("I8042_XLATE: %d\n", controller_ram[0] & I8042_XLATE ? 1 : 0); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(codeset, command_codeset, - "[set]", - "Get/set keyboard codeset"); - -static int command_controller_ram(int argc, char **argv) +static int command_controller_ram(int argc, const char **argv) { int index; @@ -1095,11 +1288,8 @@ static int command_controller_ram(int argc, char **argv) ccprintf("%d = 0x%02x\n", index, controller_ram[index]); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(ctrlram, command_controller_ram, - "index [value]", - "Get/set keyboard controller RAM"); -static int command_keyboard_log(int argc, char **argv) +static int command_keyboard_log(int argc, const char **argv) { int i; @@ -1107,8 +1297,8 @@ static int command_keyboard_log(int argc, char **argv) if (argc == 1) { ccprintf("KBC log (len=%d):\n", kblog_len); for (i = 0; kblog_buf && i < kblog_len; ++i) { - ccprintf("%c.%02x ", - kblog_buf[i].type, kblog_buf[i].byte); + ccprintf("%c.%02x ", kblog_buf[i].type, + kblog_buf[i].byte); if ((i & 15) == 15) { ccputs("\n"); cflush(); @@ -1124,9 +1314,9 @@ static int command_keyboard_log(int argc, char **argv) if (i) { if (!kblog_buf) { - int rv = SHARED_MEM_ACQUIRE_CHECK( - sizeof(*kblog_buf) * MAX_KBLOG, - (char **)&kblog_buf); + int rv = SHARED_MEM_ACQUIRE_CHECK(sizeof(*kblog_buf) * + MAX_KBLOG, + (char **)&kblog_buf); if (rv != EC_SUCCESS) kblog_buf = NULL; kblog_len = 0; @@ -1141,12 +1331,8 @@ static int command_keyboard_log(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(kblog, command_keyboard_log, - "[on | off]", - "Print or toggle keyboard event log"); - -static int command_keyboard(int argc, char **argv) +static int command_keyboard(int argc, const char **argv) { int ena; @@ -1160,12 +1346,8 @@ static int command_keyboard(int argc, char **argv) ccprintf("Enabled: %d\n", keyboard_enabled); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(kbd, command_keyboard, - "[on | off]", - "Print or toggle keyboard info"); - -static int command_8042_internal(int argc, char **argv) +static int command_8042_internal(int argc, const char **argv) { int i; @@ -1175,7 +1357,9 @@ static int command_8042_internal(int argc, char **argv) ccprintf("keyboard_enabled=%d\n", keyboard_enabled); ccprintf("keystroke_enabled=%d\n", keystroke_enabled); ccprintf("aux_chan_enabled=%d\n", aux_chan_enabled); - +#ifdef CONFIG_BOARD_AZALEA + ccprintf("to_host_queue_paused=%d\n", to_host_queue_paused); +#endif ccprintf("resend_command[]={"); for (i = 0; i < resend_command_len; i++) ccprintf("0x%02x, ", resend_command[i]); @@ -1208,8 +1392,21 @@ static int command_8042_internal(int argc, char **argv) return EC_SUCCESS; } +/* Zephyr only provides these as subcommands*/ +#ifndef CONFIG_ZEPHYR +DECLARE_CONSOLE_COMMAND(typematic, command_typematic, "[first] [inter]", + "Get/set typematic delays"); +DECLARE_CONSOLE_COMMAND(codeset, command_codeset, "[set]", + "Get/set keyboard codeset"); +DECLARE_CONSOLE_COMMAND(ctrlram, command_controller_ram, "index [value]", + "Get/set keyboard controller RAM"); +DECLARE_CONSOLE_COMMAND(kblog, command_keyboard_log, "[on | off]", + "Print or toggle keyboard event log"); +DECLARE_CONSOLE_COMMAND(kbd, command_keyboard, "[on | off]", + "Print or toggle keyboard info"); +#endif -static int command_8042(int argc, char **argv) +static int command_8042(int argc, const char **argv) { if (argc >= 2) { if (!strcasecmp(argv[1], "internal")) @@ -1220,25 +1417,27 @@ static int command_8042(int argc, char **argv) return command_codeset(argc - 1, argv + 1); else if (!strcasecmp(argv[1], "ctrlram")) return command_controller_ram(argc - 1, argv + 1); - else if (!strcasecmp(argv[1], "kblog")) + else if (CMD_KEYBOARD_LOG && !strcasecmp(argv[1], "kblog")) return command_keyboard_log(argc - 1, argv + 1); else if (!strcasecmp(argv[1], "kbd")) return command_keyboard(argc - 1, argv + 1); else return EC_ERROR_PARAM1; } else { - char *ctlram_argv[] = {"ctrlram", "0"}; + const char *ctlram_argv[] = { "ctrlram", "0" }; ccprintf("\n- Typematic:\n"); command_typematic(argc, argv); ccprintf("\n- Codeset:\n"); command_codeset(argc, argv); ccprintf("\n- Control RAM:\n"); - command_controller_ram( - sizeof(ctlram_argv) / sizeof(ctlram_argv[0]), - ctlram_argv); - ccprintf("\n- Keyboard log:\n"); - command_keyboard_log(argc, argv); + command_controller_ram(sizeof(ctlram_argv) / + sizeof(ctlram_argv[0]), + ctlram_argv); + if (CMD_KEYBOARD_LOG) { + ccprintf("\n- Keyboard log:\n"); + command_keyboard_log(argc, argv); + } ccprintf("\n- Keyboard:\n"); command_keyboard(argc, argv); ccprintf("\n- Internal:\n"); @@ -1254,7 +1453,6 @@ DECLARE_CONSOLE_COMMAND(8042, command_8042, "Print 8042 state in one place"); #endif - /*****************************************************************************/ /* Hooks */ @@ -1276,8 +1474,8 @@ static void keyboard_preserve_state(void) state.ctlram = controller_ram[0]; state.keystroke_enabled = keystroke_enabled; - system_add_jump_tag(KB_SYSJUMP_TAG, KB_HOOK_VERSION, - sizeof(state), &state); + system_add_jump_tag(KB_SYSJUMP_TAG, KB_HOOK_VERSION, sizeof(state), + &state); } DECLARE_HOOK(HOOK_SYSJUMP, keyboard_preserve_state, HOOK_PRIO_DEFAULT); @@ -1300,6 +1498,8 @@ static void keyboard_restore_state(void) } DECLARE_HOOK(HOOK_INIT, keyboard_restore_state, HOOK_PRIO_DEFAULT); +#ifndef CONFIG_PLATFORM_EC_CUSTOMIZED_DESIGN +#if defined(CONFIG_POWER_BUTTON) && !defined(CONFIG_MKBP_INPUT_DEVICES) /** * Handle power button changing state. */ @@ -1310,3 +1510,35 @@ static void keyboard_power_button(void) } DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, keyboard_power_button, HOOK_PRIO_DEFAULT); + +#endif /* CONFIG_POWER_BUTTON && !CONFIG_MKBP_INPUT_DEVICES */ +#endif /* CONFIG_PLATFORM_EC_CUSTOMIZED_DESIGN */ + +#ifdef TEST_BUILD +void test_keyboard_8042_set_resend_command(const uint8_t *data, int length) +{ + length = MIN(length, sizeof(resend_command)); + + memcpy(resend_command, data, length); + resend_command_len = length; +} + +void test_keyboard_8042_reset(void) +{ + /* Initialize controller ram */ + memset(controller_ram, 0, sizeof(controller_ram)); + controller_ram[0] = I8042_XLATE | I8042_AUX_DIS | I8042_KBD_DIS; + + /* Typematic state reset */ + reset_rate_and_delay(); + clear_typematic_key(); + + /* Use default scancode set # 2 */ + scancode_set = SCANCODE_SET_2; + + /* Keyboard not enabled (matches I8042_KBD_DIS bit being set) */ + keyboard_enabled = false; + + A20_status = 0; +} +#endif /* TEST_BUILD */ diff --git a/common/keyboard_8042_sharedlib.c b/common/keyboard_8042_sharedlib.c index 1d024d3f47..b8902cdf04 100644 --- a/common/keyboard_8042_sharedlib.c +++ b/common/keyboard_8042_sharedlib.c @@ -1,10 +1,11 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Objects which can be shared between RO and RW for 8042 keyboard protocol. */ +#include "builtin/assert.h" #include "button.h" #include "keyboard_8042_sharedlib.h" #include "keyboard_config.h" @@ -12,31 +13,39 @@ #include "libsharedobjs.h" #include "util.h" +#include + #ifndef CONFIG_KEYBOARD_CUSTOMIZATION /* The standard Chrome OS keyboard matrix table in scan code set 2. */ static uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { - {0x0000, 0x0000, 0x0014, 0xe01f, 0xe014, 0xe007, 0x0000, 0x0000}, - {0xe01f, 0x0076, 0x000d, 0x000e, 0x001c, 0x001a, 0x0016, 0x0015}, - {0x0005, 0x000c, 0x0004, 0x0006, 0x0023, 0x0021, 0x0026, 0x0024}, - {0x0032, 0x0034, 0x002c, 0x002e, 0x002b, 0x002a, 0x0025, 0x002d}, - {0x0009, 0x0083, 0x000b, 0x0003, 0x001b, 0x0022, 0x001e, 0x001d}, - {0x0051, 0x0000, 0x005b, 0x0000, 0x0042, 0x0041, 0x003e, 0x0043}, - {0x0031, 0x0033, 0x0035, 0x0036, 0x003b, 0x003a, 0x003d, 0x003c}, - {0x0000, 0x0000, 0x0061, 0x0000, 0x0000, 0x0012, 0x0000, 0x0059}, - {0x0055, 0x0052, 0x0054, 0x004e, 0x004c, 0x004a, 0x0045, 0x004d}, - {0x0000, 0x0001, 0x000a, 0x002f, 0x004b, 0x0049, 0x0046, 0x0044}, - {0xe011, 0x0000, 0x006a, 0x0000, 0x005d, 0x0000, 0x0011, 0x0000}, + { 0x0000, 0x0000, 0x0014, 0xe01f, 0xe014, 0xe007, 0x0000, 0x0000 }, + { 0xe01f, 0x0076, 0x000d, 0x000e, 0x001c, 0x001a, 0x0016, 0x0015 }, + { 0x0005, 0x000c, 0x0004, 0x0006, 0x0023, 0x0021, 0x0026, 0x0024 }, + { 0x0032, 0x0034, 0x002c, 0x002e, 0x002b, 0x002a, 0x0025, 0x002d }, + { 0x0009, 0x0083, 0x000b, 0x0003, 0x001b, 0x0022, 0x001e, 0x001d }, + { 0x0051, 0x0000, 0x005b, 0x0000, 0x0042, 0x0041, 0x003e, 0x0043 }, + { 0x0031, 0x0033, 0x0035, 0x0036, 0x003b, 0x003a, 0x003d, 0x003c }, + { 0x0000, 0x0000, 0x0061, 0x0000, 0x0000, 0x0012, 0x0000, 0x0059 }, + { 0x0055, 0x0052, 0x0054, 0x004e, 0x004c, 0x004a, 0x0045, 0x004d }, + { 0x0000, 0x0001, 0x000a, 0x002f, 0x004b, 0x0049, 0x0046, 0x0044 }, + { 0xe011, 0x0000, 0x006a, 0x0000, 0x005d, 0x0000, 0x0011, 0x0000 }, #ifndef CONFIG_KEYBOARD_KEYPAD - {0x0000, 0x0066, 0x0000, 0x005d, 0x005a, 0x0029, 0xe072, 0xe075}, - {0x0000, 0x0064, 0x0000, 0x0067, 0x0000, 0x0000, 0xe074, 0xe06b}, + { 0x0000, 0x0066, 0x0000, 0x005d, 0x005a, 0x0029, 0xe072, 0xe075 }, + { 0x0000, 0x0064, 0x0000, 0x0067, 0x0000, 0x0000, 0xe074, 0xe06b }, #else - {0x0000, 0x0066, 0xe071, 0x005d, 0x005a, 0x0029, 0xe072, 0xe075}, - {0xe06c, 0x0064, 0xe07d, 0x0067, 0xe069, 0xe07a, 0xe074, 0xe06b}, - {0xe04a, 0x007c, 0x007b, 0x0074, 0x0071, 0x0073, 0x006b, 0x0070}, - {0x006c, 0x0075, 0x007d, 0x0079, 0x007a, 0x0072, 0x0069, 0xe05a}, + { 0x0000, 0x0066, 0xe071, 0x005d, 0x005a, 0x0029, 0xe072, 0xe075 }, + { 0xe06c, 0x0064, 0xe07d, 0x0067, 0xe069, 0xe07a, 0xe074, 0xe06b }, + { 0xe04a, 0x007c, 0x007b, 0x0074, 0x0071, 0x0073, 0x006b, 0x0070 }, + { 0x006c, 0x0075, 0x007d, 0x0079, 0x007a, 0x0072, 0x0069, 0xe05a }, #endif }; +void register_scancode_set2(uint16_t *scancode_set, size_t size) +{ + ASSERT(size == sizeof(scancode_set2)); + memcpy(scancode_set2, scancode_set, size); +} + uint16_t get_scancode_set2(uint8_t row, uint8_t col) { if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) @@ -60,37 +69,32 @@ void set_scancode_set2(uint8_t row, uint8_t col, uint16_t val) * see scancode_translate_set2_to_1 below). */ SHAREDLIB(const uint8_t scancode_translate_table[128] = { - 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, - 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, - 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, - 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, - 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, - 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, - 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, - 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, - 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, - 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, - 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, - 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, - 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, - 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, - 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, - 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, -}); - + 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 0x64, 0x44, + 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, 0x65, 0x38, 0x2a, 0x70, + 0x1d, 0x10, 0x02, 0x5a, 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, + 0x03, 0x5b, 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, + 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, 0x69, 0x31, + 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, 0x6a, 0x72, 0x32, 0x24, + 0x16, 0x08, 0x09, 0x5f, 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, + 0x0a, 0x60, 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, + 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, 0x3a, 0x36, + 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, 0x55, 0x56, 0x77, 0x78, + 0x79, 0x7a, 0x0e, 0x7b, 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, + 0x7f, 0x6f, 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, + 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, + }); #ifdef CONFIG_KEYBOARD_DEBUG -SHAREDLIB(const -static char * const keycap_long_label[KLLI_MAX & KEYCAP_LONG_LABEL_INDEX_BITMASK] = { - "UNKNOWN", "F1", "F2", "F3", - "F4", "F5", "F6", "F7", - "F8", "F9", "F10", "F11", - "F12", "F13", "F14", "F15", - "L-ALT", "R-ALT", "L-CTR", "R-CTR", - "L-SHT", "R-SHT", "ENTER", "SPACE", - "B-SPC", "TAB", "SEARC", "LEFT", - "RIGHT", "DOWN", "UP", "ESC", -}); +SHAREDLIB( + const static char *const + keycap_long_label[KLLI_MAX & KEYCAP_LONG_LABEL_INDEX_BITMASK] = { + "UNKNOWN", "F1", "F2", "F3", "F4", "F5", + "F6", "F7", "F8", "F9", "F10", "F11", + "F12", "F13", "F14", "F15", "L-ALT", "R-ALT", + "L-CTR", "R-CTR", "L-SHT", "R-SHT", "ENTER", "SPACE", + "B-SPC", "TAB", "SEARC", "LEFT", "RIGHT", "DOWN", + "UP", "ESC", + }); const char *get_keycap_long_label(uint8_t idx) { @@ -100,50 +104,42 @@ const char *get_keycap_long_label(uint8_t idx) } #ifndef CONFIG_KEYBOARD_CUSTOMIZATION -static char keycap_label[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { - {KLLI_UNKNO, KLLI_UNKNO, KLLI_L_CTR, KLLI_SEARC, - KLLI_R_CTR, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO}, - {KLLI_F11, KLLI_ESC, KLLI_TAB, '~', - 'a', 'z', '1', 'q'}, - {KLLI_F1, KLLI_F4, KLLI_F3, KLLI_F2, - 'd', 'c', '3', 'e'}, - {'b', 'g', 't', '5', - 'f', 'v', '4', 'r'}, - {KLLI_F10, KLLI_F7, KLLI_F6, KLLI_F5, - 's', 'x', '2', 'w'}, - {KLLI_UNKNO, KLLI_F12, ']', KLLI_F13, - 'k', ',', '8', 'i'}, - {'n', 'h', 'y', '6', - 'j', 'm', '7', 'u'}, - {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_L_SHT, KLLI_UNKNO, KLLI_R_SHT}, - {'=', '\'', '[', '-', - ';', '/', '0', 'p'}, - {KLLI_F14, KLLI_F9, KLLI_F8, KLLI_UNKNO, - '|', '.', '9', 'o'}, - {KLLI_R_ALT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_L_ALT, KLLI_UNKNO}, - {KLLI_F15, KLLI_B_SPC, KLLI_UNKNO, '\\', - KLLI_ENTER, KLLI_SPACE, KLLI_DOWN, KLLI_UP}, - {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_RIGHT, KLLI_LEFT}, +static uint8_t keycap_label[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + { KLLI_UNKNO, KLLI_UNKNO, KLLI_L_CTR, KLLI_SEARC, KLLI_R_CTR, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_F11, KLLI_ESC, KLLI_TAB, '~', 'a', 'z', '1', 'q' }, + { KLLI_F1, KLLI_F4, KLLI_F3, KLLI_F2, 'd', 'c', '3', 'e' }, + { 'b', 'g', 't', '5', 'f', 'v', '4', 'r' }, + { KLLI_F10, KLLI_F7, KLLI_F6, KLLI_F5, 's', 'x', '2', 'w' }, + { KLLI_UNKNO, KLLI_F12, ']', KLLI_F13, 'k', ',', '8', 'i' }, + { 'n', 'h', 'y', '6', 'j', 'm', '7', 'u' }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_L_SHT, KLLI_UNKNO, KLLI_R_SHT }, + { '=', '\'', '[', '-', ';', '/', '0', 'p' }, + { KLLI_F14, KLLI_F9, KLLI_F8, KLLI_UNKNO, '|', '.', '9', 'o' }, + { KLLI_R_ALT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_L_ALT, KLLI_UNKNO }, + { KLLI_F15, KLLI_B_SPC, KLLI_UNKNO, '\\', KLLI_ENTER, KLLI_SPACE, + KLLI_DOWN, KLLI_UP }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_RIGHT, KLLI_LEFT }, #ifdef CONFIG_KEYBOARD_KEYPAD /* TODO: Populate these */ - {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO}, - {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, - KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO}, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, + { KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, + KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO }, #endif }; -char get_keycap_label(uint8_t row, uint8_t col) +uint8_t get_keycap_label(uint8_t row, uint8_t col) { if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) return keycap_label[col][row]; return KLLI_UNKNO; } -void set_keycap_label(uint8_t row, uint8_t col, char val) +void set_keycap_label(uint8_t row, uint8_t col, uint8_t val) { if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) keycap_label[col][row] = val; @@ -166,16 +162,19 @@ uint8_t scancode_translate_set2_to_1(uint8_t code) * Must be in the same order as defined in keyboard_button_type. */ SHAREDLIB(const struct button_8042_t buttons_8042[] = { - {SCANCODE_POWER, 0}, - {SCANCODE_VOLUME_DOWN, 1}, - {SCANCODE_VOLUME_UP, 1}, - {SCANCODE_1, 1}, - {SCANCODE_2, 1}, - {SCANCODE_3, 1}, - {SCANCODE_4, 1}, - {SCANCODE_5, 1}, - {SCANCODE_6, 1}, - {SCANCODE_7, 1}, - {SCANCODE_8, 1}, -}); + { SCANCODE_POWER, 0 }, + { SCANCODE_VOLUME_DOWN, 1 }, + { SCANCODE_VOLUME_UP, 1 }, + { SCANCODE_1, 1 }, + { SCANCODE_2, 1 }, + { SCANCODE_3, 1 }, + { SCANCODE_4, 1 }, + { SCANCODE_5, 1 }, + { SCANCODE_6, 1 }, + { SCANCODE_7, 1 }, + { SCANCODE_8, 1 }, +#ifdef CONFIG_CUSTOMIZED_DESIGN + {SCANCODE_FAKE_POWER, 0}, +#endif /* CONFIG_CUSTOMIZED_DESIGN */ + }); BUILD_ASSERT(ARRAY_SIZE(buttons_8042) == KEYBOARD_BUTTON_COUNT); diff --git a/common/keyboard_backlight.c b/common/keyboard_backlight.c index 694ac77446..fde20de7ef 100644 --- a/common/keyboard_backlight.c +++ b/common/keyboard_backlight.c @@ -1,25 +1,34 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "chipset.h" #include "console.h" #include "ec_commands.h" +#include "gpio.h" #include "hooks.h" #include "host_command.h" #include "keyboard_backlight.h" #include "lid_switch.h" +#include "rgb_keyboard.h" #include "timer.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ##args) static struct kblight_conf kblight; static int current_percent; +static uint8_t current_enable; -void __attribute__((weak)) board_kblight_init(void) -{ } +__overridable void board_kblight_init(void) +{ +} + +__overridable void board_kblight_shutdown(void) +{ +} static int kblight_init(void) { @@ -54,11 +63,34 @@ int kblight_get(void) return current_percent; } -int kblight_enable(int enable) +static void kblight_enable_deferred(void) { +#ifdef CONFIG_KBLIGHT_ENABLE_PIN + gpio_set_level(GPIO_EN_KEYBOARD_BACKLIGHT, current_enable); +#endif if (!kblight.drv || !kblight.drv->enable) - return -1; - return kblight.drv->enable(enable); + return; + kblight.drv->enable(current_enable); +} +DECLARE_DEFERRED(kblight_enable_deferred); + +int kblight_enable(int enable) +{ + current_enable = enable; + /* Need to defer i2c in case it's called from an interrupt handler. */ + hook_call_deferred(&kblight_enable_deferred_data, 0); + return EC_SUCCESS; +} + +int kblight_get_enabled(void) +{ +#ifdef CONFIG_KBLIGHT_ENABLE_PIN + if (!gpio_get_level(GPIO_EN_KEYBOARD_BACKLIGHT)) + return 0; +#endif + if (kblight.drv && kblight.drv->get_enabled) + return kblight.drv->get_enabled(); + return -1; } int kblight_register(const struct kblight_drv *drv) @@ -74,15 +106,26 @@ int kblight_register(const struct kblight_drv *drv) static void keyboard_backlight_init(void) { /* Uses PWM by default. Can be customized by board_kblight_init */ -#ifdef CONFIG_PWM_KBLIGHT - kblight_register(&kblight_pwm); -#endif + if (IS_ENABLED(CONFIG_PWM_KBLIGHT)) + kblight_register(&kblight_pwm); + else if (IS_ENABLED(CONFIG_RGB_KEYBOARD)) + kblight_register(&kblight_rgbkbd); + board_kblight_init(); if (kblight_init()) CPRINTS("kblight init failed"); + /* Don't leave kblight enable state undetermined */ + kblight_enable(0); } +#ifdef HAS_TASK_CHIPSET +/* We're running on a system EC. Initialize kblight once per AP start-up. */ +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, keyboard_backlight_init, HOOK_PRIO_DEFAULT); +#else +/* We're running on a KBMCU thus powered when AP starts. Do init on reset. */ DECLARE_HOOK(HOOK_INIT, keyboard_backlight_init, HOOK_PRIO_DEFAULT); +#endif +#ifdef CONFIG_AP_POWER_CONTROL static void kblight_suspend(void) { kblight_enable(0); @@ -97,17 +140,20 @@ static void kblight_resume(void) } } DECLARE_HOOK(HOOK_CHIPSET_RESUME, kblight_resume, HOOK_PRIO_DEFAULT); +#endif /* CONFIG_AP_POWER_CONTROL */ +#ifdef CONFIG_LID_SWITCH static void kblight_lid_change(void) { kblight_enable(lid_is_open() && current_percent); } DECLARE_HOOK(HOOK_LID_CHANGE, kblight_lid_change, HOOK_PRIO_DEFAULT); +#endif /* * Console and host commands */ -static int cc_kblight(int argc, char **argv) +static int cc_kblight(int argc, const char **argv) { if (argc >= 2) { char *e; @@ -119,28 +165,29 @@ static int cc_kblight(int argc, char **argv) if (kblight_enable(i > 0)) return EC_ERROR_PARAM1; } - ccprintf("Keyboard backlight: %d%%\n", kblight_get()); + ccprintf("Keyboard backlight: %d%% enabled: %d\n", kblight_get(), + kblight_get_enabled()); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(kblight, cc_kblight, - "percent", +DECLARE_CONSOLE_COMMAND(kblight, cc_kblight, "percent", "Get/set keyboard backlight"); -enum ec_status hc_get_keyboard_backlight(struct host_cmd_handler_args *args) +static enum ec_status +hc_get_keyboard_backlight(struct host_cmd_handler_args *args) { struct ec_response_pwm_get_keyboard_backlight *r = args->response; r->percent = kblight_get(); - r->enabled = 1; /* Deprecated */ + r->enabled = kblight_get_enabled(); args->response_size = sizeof(*r); return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT, - hc_get_keyboard_backlight, - EC_VER_MASK(0)); + hc_get_keyboard_backlight, EC_VER_MASK(0)); -enum ec_status hc_set_keyboard_backlight(struct host_cmd_handler_args *args) +static enum ec_status +hc_set_keyboard_backlight(struct host_cmd_handler_args *args) { const struct ec_params_pwm_set_keyboard_backlight *p = args->params; @@ -151,5 +198,11 @@ enum ec_status hc_set_keyboard_backlight(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT, - hc_set_keyboard_backlight, - EC_VER_MASK(0)); + hc_set_keyboard_backlight, EC_VER_MASK(0)); + +#ifdef TEST_BUILD +uint8_t kblight_get_current_enable(void) +{ + return current_enable; +} +#endif /* TEST_BUILD */ diff --git a/common/keyboard_mkbp.c b/common/keyboard_mkbp.c index 9b41ef593e..fa003c31a2 100644 --- a/common/keyboard_mkbp.c +++ b/common/keyboard_mkbp.c @@ -1,19 +1,12 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * MKBP keyboard protocol */ -#include "atomic.h" -#include "base_state.h" -#include "button.h" #include "chipset.h" #include "common.h" -#include "console.h" -#include "ec_commands.h" -#include "gpio.h" -#include "hooks.h" #include "host_command.h" #include "keyboard_config.h" #include "keyboard_mkbp.h" @@ -21,29 +14,14 @@ #include "keyboard_raw.h" #include "keyboard_scan.h" #include "keyboard_test.h" -#include "lid_switch.h" #include "mkbp_event.h" -#include "power_button.h" -#include "system.h" -#include "tablet_mode.h" +#include "mkbp_fifo.h" #include "task.h" -#include "timer.h" #include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_KEYBOARD, outstr) -#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) - -/* - * Common FIFO depth. This needs to be big enough not to overflow if a - * series of keys is pressed in rapid succession and the kernel is too busy - * to read them out right away. - * - * RAM usage is (depth * #cols); A 16-entry FIFO will consume 16x13=208 bytes, - * which is non-trivial but not horrible. - */ - -#define FIFO_DEPTH 16 +#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ##args) /* Changes to col,row here need to also be reflected in kernel. * drivers/input/mkbp.c ... see KEY_BATTERY. @@ -52,35 +30,15 @@ #define BATTERY_KEY_ROW 7 #define BATTERY_KEY_ROW_MASK BIT(BATTERY_KEY_ROW) -static uint32_t fifo_start; /* first entry */ -static uint32_t fifo_end; /* last entry */ -static uint32_t fifo_entries; /* number of existing entries */ -static struct ec_response_get_next_event fifo[FIFO_DEPTH]; -/* - * Mutex for critical sections of mkbp_fifo_add(), which is called - * from various tasks. - */ -static struct mutex fifo_add_mutex; -/* - * Mutex for critical sections of fifo_remove(), which is called from the - * hostcmd task and from keyboard_clear_buffer(). - */ -static struct mutex fifo_remove_mutex; - -/* Button and switch state. */ -static uint32_t mkbp_button_state; -static uint32_t mkbp_switch_state; #ifndef HAS_TASK_KEYSCAN -/* Keys simulated-pressed */ -static uint8_t __bss_slow simulated_key[KEYBOARD_COLS_MAX]; -uint8_t keyboard_cols = KEYBOARD_COLS_MAX; +#error "Task KEYSCAN has to be enabled for MKBP keyboard" #endif /* !defined(HAS_TASK_KEYSCAN) */ /* Config for mkbp protocol; does not include fields from scan config */ struct ec_mkbp_protocol_config { - uint32_t valid_mask; /* valid fields */ - uint8_t flags; /* some flags (enum mkbp_config_flags) */ - uint8_t valid_flags; /* which flags are valid */ + uint32_t valid_mask; /* valid fields */ + uint8_t flags; /* some flags (enum mkbp_config_flags) */ + uint8_t valid_flags; /* which flags are valid */ /* maximum depth to allow for fifo (0 = no keyscan output) */ uint8_t fifo_max_depth; @@ -88,540 +46,45 @@ struct ec_mkbp_protocol_config { static struct ec_mkbp_protocol_config config = { .valid_mask = EC_MKBP_VALID_SCAN_PERIOD | EC_MKBP_VALID_POLL_TIMEOUT | - EC_MKBP_VALID_MIN_POST_SCAN_DELAY | - EC_MKBP_VALID_OUTPUT_SETTLE | EC_MKBP_VALID_DEBOUNCE_DOWN | - EC_MKBP_VALID_DEBOUNCE_UP | EC_MKBP_VALID_FIFO_MAX_DEPTH, + EC_MKBP_VALID_MIN_POST_SCAN_DELAY | + EC_MKBP_VALID_OUTPUT_SETTLE | + EC_MKBP_VALID_DEBOUNCE_DOWN | EC_MKBP_VALID_DEBOUNCE_UP | + EC_MKBP_VALID_FIFO_MAX_DEPTH, .valid_flags = EC_MKBP_FLAGS_ENABLE, .flags = EC_MKBP_FLAGS_ENABLE, .fifo_max_depth = FIFO_DEPTH, }; -static int get_data_size(enum ec_mkbp_event e) -{ - switch (e) { - case EC_MKBP_EVENT_KEY_MATRIX: - return keyboard_cols; - -#ifdef CONFIG_HOST_EVENT64 - case EC_MKBP_EVENT_HOST_EVENT64: - return sizeof(uint64_t); -#endif - - case EC_MKBP_EVENT_HOST_EVENT: - case EC_MKBP_EVENT_BUTTON: - case EC_MKBP_EVENT_SWITCH: - case EC_MKBP_EVENT_SYSRQ: - return sizeof(uint32_t); - default: - /* For unknown types, say it's 0. */ - return 0; - } -} - -/** - * Pop MKBP event data from FIFO - * - * @return EC_SUCCESS if entry popped, EC_ERROR_UNKNOWN if FIFO is empty - */ -static int fifo_remove(uint8_t *buffp) -{ - int size; - - mutex_lock(&fifo_remove_mutex); - if (!fifo_entries) { - /* no entry remaining in FIFO : return last known state */ - int last = (fifo_start + FIFO_DEPTH - 1) % FIFO_DEPTH; - - size = get_data_size(fifo[last].event_type); - - memcpy(buffp, &fifo[last].data, size); - mutex_unlock(&fifo_remove_mutex); - - /* - * Bail out without changing any FIFO indices and let the - * caller know something strange happened. The buffer will - * will contain the last known state of the keyboard. - */ - return EC_ERROR_UNKNOWN; - } - - /* Return just the event data. */ - if (buffp) { - size = get_data_size(fifo[fifo_start].event_type); - /* skip over event_type. */ - memcpy(buffp, &fifo[fifo_start].data, size); - } - - fifo_start = (fifo_start + 1) % FIFO_DEPTH; - deprecated_atomic_sub(&fifo_entries, 1); - mutex_unlock(&fifo_remove_mutex); - - return EC_SUCCESS; -} - /*****************************************************************************/ /* Interface */ void keyboard_clear_buffer(void) { - int i, new_fifo_entries = 0; - - CPRINTS("clear keyboard MKBP fifo"); - - /* - * Order of these locks is important to prevent deadlock since - * mkbp_fifo_add() may call fifo_remove(). - */ - mutex_lock(&fifo_add_mutex); - mutex_lock(&fifo_remove_mutex); - - /* Reset the end position */ - fifo_end = fifo_start; - - for (i = 0; i < fifo_entries; i++) { - int cur = (fifo_start + i) % FIFO_DEPTH; - - /* Drop keyboard events */ - if (fifo[cur].event_type == EC_MKBP_EVENT_KEY_MATRIX) - continue; - - /* And move other events to the front */ - memmove(&fifo[fifo_end], &fifo[cur], sizeof(fifo[cur])); - fifo_end = (fifo_end + 1) % FIFO_DEPTH; - ++new_fifo_entries; - } - fifo_entries = new_fifo_entries; - - mutex_unlock(&fifo_remove_mutex); - mutex_unlock(&fifo_add_mutex); -} - -void mkbp_clear_fifo(void) -{ - int i; - - CPRINTS("clear MKBP fifo"); - - /* - * Order of these locks is important to prevent deadlock since - * mkbp_fifo_add() may call fifo_remove(). - */ - mutex_lock(&fifo_add_mutex); - mutex_lock(&fifo_remove_mutex); - - fifo_start = 0; - fifo_end = 0; - /* This assignment is safe since both mutexes are held. */ - fifo_entries = 0; - for (i = 0; i < FIFO_DEPTH; i++) - memset(&fifo[i], 0, sizeof(struct ec_response_get_next_event)); - - mutex_unlock(&fifo_remove_mutex); - mutex_unlock(&fifo_add_mutex); -} - -test_mockable int keyboard_fifo_add(const uint8_t *buffp) -{ - return mkbp_fifo_add((uint8_t)EC_MKBP_EVENT_KEY_MATRIX, buffp); + mkbp_fifo_clear_keyboard(); } -test_mockable int mkbp_fifo_add(uint8_t event_type, const uint8_t *buffp) +test_mockable int mkbp_keyboard_add(const uint8_t *buffp) { - uint8_t size; - /* - * If the data is a keyboard matrix and the keyboard protocol is not - * enabled, don't save the state to the FIFO or trigger an interrupt. + * If the keyboard protocol is not enabled, don't save the state to + * the FIFO or trigger an interrupt. */ - if (!(config.flags & EC_MKBP_FLAGS_ENABLE) && - (event_type == EC_MKBP_EVENT_KEY_MATRIX)) + if (!(config.flags & EC_MKBP_FLAGS_ENABLE)) return EC_SUCCESS; - mutex_lock(&fifo_add_mutex); - if (fifo_entries >= config.fifo_max_depth) { - mutex_unlock(&fifo_add_mutex); - CPRINTS("MKBP common FIFO depth %d reached", - config.fifo_max_depth); - - return EC_ERROR_OVERFLOW; - } - - size = get_data_size(event_type); - fifo[fifo_end].event_type = event_type; - memcpy(&fifo[fifo_end].data, buffp, size); - fifo_end = (fifo_end + 1) % FIFO_DEPTH; - deprecated_atomic_add(&fifo_entries, 1); - - /* - * If our event didn't generate an interrupt then the host is still - * asleep. In this case, we don't want to queue our event, except if - * another event just woke the host (and wake is already in progress). - */ - if (!mkbp_send_event(event_type) && fifo_entries == 1) - fifo_remove(NULL); - - mutex_unlock(&fifo_add_mutex); - return EC_SUCCESS; -} - -void mkbp_update_switches(uint32_t sw, int state) -{ - - mkbp_switch_state &= ~BIT(sw); - mkbp_switch_state |= (!!state << sw); - - mkbp_fifo_add(EC_MKBP_EVENT_SWITCH, - (const uint8_t *)&mkbp_switch_state); -} - -#ifdef CONFIG_LID_SWITCH -/** - * Handle lid changing state. - */ -static void mkbp_lid_change(void) -{ - mkbp_update_switches(EC_MKBP_LID_OPEN, lid_is_open()); -} -DECLARE_HOOK(HOOK_LID_CHANGE, mkbp_lid_change, HOOK_PRIO_LAST); -DECLARE_HOOK(HOOK_INIT, mkbp_lid_change, HOOK_PRIO_INIT_LID+1); -#endif - -#ifdef CONFIG_TABLET_MODE_SWITCH -static void mkbp_tablet_mode_change(void) -{ - mkbp_update_switches(EC_MKBP_TABLET_MODE, tablet_get_mode()); -} -DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, mkbp_tablet_mode_change, HOOK_PRIO_LAST); -DECLARE_HOOK(HOOK_INIT, mkbp_tablet_mode_change, HOOK_PRIO_INIT_LID+1); -#endif - -#ifdef CONFIG_BASE_ATTACHED_SWITCH -static void mkbp_base_attached_change(void) -{ - mkbp_update_switches(EC_MKBP_BASE_ATTACHED, base_get_state()); -} -DECLARE_HOOK(HOOK_BASE_ATTACHED_CHANGE, mkbp_base_attached_change, - HOOK_PRIO_LAST); -DECLARE_HOOK(HOOK_INIT, mkbp_base_attached_change, HOOK_PRIO_INIT_LID+1); -#endif - -void keyboard_update_button(enum keyboard_button_type button, int is_pressed) -{ - switch (button) { - case KEYBOARD_BUTTON_POWER: - mkbp_button_state &= ~BIT(EC_MKBP_POWER_BUTTON); - mkbp_button_state |= (is_pressed << EC_MKBP_POWER_BUTTON); - break; - - case KEYBOARD_BUTTON_VOLUME_UP: - mkbp_button_state &= ~BIT(EC_MKBP_VOL_UP); - mkbp_button_state |= (is_pressed << EC_MKBP_VOL_UP); - break; - - case KEYBOARD_BUTTON_VOLUME_DOWN: - mkbp_button_state &= ~BIT(EC_MKBP_VOL_DOWN); - mkbp_button_state |= (is_pressed << EC_MKBP_VOL_DOWN); - break; - - case KEYBOARD_BUTTON_RECOVERY: - mkbp_button_state &= ~BIT(EC_MKBP_RECOVERY); - mkbp_button_state |= (is_pressed << EC_MKBP_RECOVERY); - break; - - default: - /* ignored. */ - return; - } - - CPRINTS("buttons: %x", mkbp_button_state); - - /* Add the new state to the FIFO. */ - mkbp_fifo_add(EC_MKBP_EVENT_BUTTON, - (const uint8_t *)&mkbp_button_state); -} - -#ifdef CONFIG_EMULATED_SYSRQ -void host_send_sysrq(uint8_t key) -{ - uint32_t value = key; - - mkbp_fifo_add(EC_MKBP_EVENT_SYSRQ, (const uint8_t *)&value); -} -#endif - -#ifdef CONFIG_POWER_BUTTON -/** - * Handle power button changing state. - */ -static void keyboard_power_button(void) -{ - keyboard_update_button(KEYBOARD_BUTTON_POWER, - power_button_is_pressed()); -} -DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, keyboard_power_button, - HOOK_PRIO_DEFAULT); -#endif /* defined(CONFIG_POWER_BUTTON) */ - -static int get_next_event(uint8_t *out, enum ec_mkbp_event evt) -{ - uint8_t t = fifo[fifo_start].event_type; - uint8_t size; - - if (!fifo_entries) - return -1; - - /* - * We need to peek at the next event to check that we were called with - * the correct event. - */ - if (t != (uint8_t)evt) { - /* - * We were called with the wrong event. The next element in the - * FIFO's event type doesn't match with what we were called - * with. Return an error that we're busy. The caller will need - * to call us with the correct event first. - */ - return -EC_ERROR_BUSY; - } - - fifo_remove(out); - - /* Keep sending events if FIFO is not empty */ - if (fifo_entries) - mkbp_send_event(fifo[fifo_start].event_type); - - /* Return the correct size of the data. */ - size = get_data_size(t); - if (size) - return size; - else - return -EC_ERROR_UNKNOWN; + return mkbp_fifo_add((uint8_t)EC_MKBP_EVENT_KEY_MATRIX, buffp); } static int keyboard_get_next_event(uint8_t *out) { - return get_next_event(out, EC_MKBP_EVENT_KEY_MATRIX); + return mkbp_fifo_get_next_event(out, EC_MKBP_EVENT_KEY_MATRIX); } DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_KEY_MATRIX, keyboard_get_next_event); -static int button_get_next_event(uint8_t *out) -{ - return get_next_event(out, EC_MKBP_EVENT_BUTTON); -} -DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_BUTTON, button_get_next_event); - -static int switch_get_next_event(uint8_t *out) -{ - return get_next_event(out, EC_MKBP_EVENT_SWITCH); -} -DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_SWITCH, switch_get_next_event); - -#ifdef CONFIG_EMULATED_SYSRQ -static int sysrq_get_next_event(uint8_t *out) -{ - return get_next_event(out, EC_MKBP_EVENT_SYSRQ); -} -DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_SYSRQ, sysrq_get_next_event); -#endif - -void keyboard_send_battery_key(void) -{ - uint8_t state[KEYBOARD_COLS_MAX]; - - /* Copy debounced state and add battery pseudo-key */ - memcpy(state, keyboard_scan_get_state(), sizeof(state)); - state[BATTERY_KEY_COL] ^= BATTERY_KEY_ROW_MASK; - - /* Add to FIFO only if AP is on or else it will wake from suspend */ - if (chipset_in_state(CHIPSET_STATE_ON)) - keyboard_fifo_add(state); -} - void clear_typematic_key(void) -{ } - -/*****************************************************************************/ -/* Host commands */ -static uint32_t get_supported_buttons(void) { - uint32_t val = 0; - -#ifdef CONFIG_VOLUME_BUTTONS - val |= BIT(EC_MKBP_VOL_UP) | BIT(EC_MKBP_VOL_DOWN); -#endif /* defined(CONFIG_VOLUME_BUTTONS) */ - -#ifdef CONFIG_DEDICATED_RECOVERY_BUTTON - val |= BIT(EC_MKBP_RECOVERY); -#endif /* defined(CONFIG_DEDICATED_RECOVERY_BUTTON) */ - -#ifdef CONFIG_POWER_BUTTON - val |= BIT(EC_MKBP_POWER_BUTTON); -#endif /* defined(CONFIG_POWER_BUTTON) */ - - return val; } -static uint32_t get_supported_switches(void) -{ - uint32_t val = 0; - -#ifdef CONFIG_LID_SWITCH - val |= BIT(EC_MKBP_LID_OPEN); -#endif -#ifdef CONFIG_TABLET_MODE_SWITCH - val |= BIT(EC_MKBP_TABLET_MODE); -#endif -#ifdef CONFIG_BASE_ATTACHED_SWITCH - val |= BIT(EC_MKBP_BASE_ATTACHED); -#endif - return val; -} - -static enum ec_status mkbp_get_info(struct host_cmd_handler_args *args) -{ - const struct ec_params_mkbp_info *p = args->params; - - if (args->params_size == 0 || p->info_type == EC_MKBP_INFO_KBD) { - struct ec_response_mkbp_info *r = args->response; - - /* Version 0 just returns info about the keyboard. */ - r->rows = KEYBOARD_ROWS; - r->cols = keyboard_cols; - /* This used to be "switches" which was previously 0. */ - r->reserved = 0; - - args->response_size = sizeof(struct ec_response_mkbp_info); - } else { - union ec_response_get_next_data *r = args->response; - - /* Version 1 (other than EC_MKBP_INFO_KBD) */ - switch (p->info_type) { - case EC_MKBP_INFO_SUPPORTED: - switch (p->event_type) { - case EC_MKBP_EVENT_BUTTON: - r->buttons = get_supported_buttons(); - args->response_size = sizeof(r->buttons); - break; - - case EC_MKBP_EVENT_SWITCH: - r->switches = get_supported_switches(); - args->response_size = sizeof(r->switches); - break; - - default: - /* Don't care for now for other types. */ - return EC_RES_INVALID_PARAM; - } - break; - - case EC_MKBP_INFO_CURRENT: - switch (p->event_type) { -#ifdef HAS_TASK_KEYSCAN - case EC_MKBP_EVENT_KEY_MATRIX: - memcpy(r->key_matrix, keyboard_scan_get_state(), - sizeof(r->key_matrix)); - args->response_size = sizeof(r->key_matrix); - break; -#endif - case EC_MKBP_EVENT_HOST_EVENT: - r->host_event = (uint32_t)host_get_events(); - args->response_size = sizeof(r->host_event); - break; - -#ifdef CONFIG_HOST_EVENT64 - case EC_MKBP_EVENT_HOST_EVENT64: - r->host_event64 = host_get_events(); - args->response_size = sizeof(r->host_event64); - break; -#endif - - case EC_MKBP_EVENT_BUTTON: - r->buttons = mkbp_button_state; - args->response_size = sizeof(r->buttons); - break; - - case EC_MKBP_EVENT_SWITCH: - r->switches = mkbp_switch_state; - args->response_size = sizeof(r->switches); - break; - - default: - /* Doesn't make sense for other event types. */ - return EC_RES_INVALID_PARAM; - } - break; - - default: - /* Unsupported query. */ - return EC_RES_ERROR; - } - } - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_MKBP_INFO, mkbp_get_info, - EC_VER_MASK(0) | EC_VER_MASK(1)); - -#ifndef HAS_TASK_KEYSCAN -/* For boards without a keyscan task, try and simulate keyboard presses. */ -static void simulate_key(int row, int col, int pressed) -{ - if ((simulated_key[col] & BIT(row)) == ((pressed ? 1 : 0) << row)) - return; /* No change */ - - simulated_key[col] &= ~BIT(row); - if (pressed) - simulated_key[col] |= BIT(row); - - keyboard_fifo_add(simulated_key); -} - -static int command_mkbp_keyboard_press(int argc, char **argv) -{ - if (argc == 1) { - int i, j; - - ccputs("Simulated keys:\n"); - for (i = 0; i < keyboard_cols; ++i) { - if (simulated_key[i] == 0) - continue; - for (j = 0; j < KEYBOARD_ROWS; ++j) - if (simulated_key[i] & BIT(j)) - ccprintf("\t%d %d\n", i, j); - } - - } else if (argc == 3 || argc == 4) { - int r, c, p; - char *e; - - c = strtoi(argv[1], &e, 0); - if (*e || c < 0 || c >= keyboard_cols) - return EC_ERROR_PARAM1; - - r = strtoi(argv[2], &e, 0); - if (*e || r < 0 || r >= KEYBOARD_ROWS) - return EC_ERROR_PARAM2; - - if (argc == 3) { - /* Simulate a press and release */ - simulate_key(r, c, 1); - simulate_key(r, c, 0); - } else { - p = strtoi(argv[3], &e, 0); - if (*e || p < 0 || p > 1) - return EC_ERROR_PARAM3; - - simulate_key(r, c, p); - } - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(kbpress, command_mkbp_keyboard_press, - "[col row [0 | 1]]", - "Simulate keypress"); -#endif /* !defined(HAS_TASK_KEYSCAN) */ - -#ifdef HAS_TASK_KEYSCAN static void set_keyscan_config(const struct ec_mkbp_config *src, struct ec_mkbp_protocol_config *dst, uint32_t valid_mask, uint8_t new_flags) @@ -658,11 +121,11 @@ static void set_keyscan_config(const struct ec_mkbp_config *src, * fall out of the task_wait_event() in keyboard_scan_task(). */ if ((new_flags & EC_MKBP_FLAGS_ENABLE) && - !(dst->flags & EC_MKBP_FLAGS_ENABLE)) + !(dst->flags & EC_MKBP_FLAGS_ENABLE)) task_wake(TASK_ID_KEYSCAN); } -static void get_keyscan_config(struct ec_mkbp_config *dst) +test_export_static void get_keyscan_config(struct ec_mkbp_config *dst) { const struct keyboard_scan_config *ksc = keyboard_scan_get_config(); @@ -690,15 +153,14 @@ static void get_keyscan_config(struct ec_mkbp_config *dst) * over to dst->flags */ static void keyscan_copy_config(const struct ec_mkbp_config *src, - struct ec_mkbp_protocol_config *dst, - uint32_t valid_mask, uint8_t valid_flags) + struct ec_mkbp_protocol_config *dst, + uint32_t valid_mask, uint8_t valid_flags) { uint8_t new_flags; if (valid_mask & EC_MKBP_VALID_FIFO_MAX_DEPTH) { /* Validity check for fifo depth */ - dst->fifo_max_depth = MIN(src->fifo_max_depth, - FIFO_DEPTH); + dst->fifo_max_depth = MIN(src->fifo_max_depth, FIFO_DEPTH); } new_flags = dst->flags & ~valid_flags; @@ -717,10 +179,11 @@ host_command_mkbp_set_config(struct host_cmd_handler_args *args) config.valid_mask & req->config.valid_mask, config.valid_flags & req->config.valid_flags); + mkbp_fifo_depth_update(config.fifo_max_depth); + return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_MKBP_SET_CONFIG, - host_command_mkbp_set_config, +DECLARE_HOST_COMMAND(EC_CMD_MKBP_SET_CONFIG, host_command_mkbp_set_config, EC_VER_MASK(0)); static enum ec_status @@ -743,7 +206,5 @@ host_command_mkbp_get_config(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_MKBP_GET_CONFIG, - host_command_mkbp_get_config, +DECLARE_HOST_COMMAND(EC_CMD_MKBP_GET_CONFIG, host_command_mkbp_get_config, EC_VER_MASK(0)); -#endif /* HAS_TASK_KEYSCAN */ diff --git a/common/keyboard_scan.c b/common/keyboard_scan.c index 0e95eb6c34..1568f5ae10 100644 --- a/common/keyboard_scan.c +++ b/common/keyboard_scan.c @@ -1,10 +1,12 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Keyboard scanner module for Chrome EC */ +#include "adc.h" +#include "atomic_bit.h" #include "chipset.h" #include "clock.h" #include "common.h" @@ -18,6 +20,7 @@ #include "keyboard_scan.h" #include "keyboard_test.h" #include "lid_switch.h" +#include "printf.h" #include "switch.h" #include "system.h" #include "tablet_mode.h" @@ -26,23 +29,27 @@ #include "usb_api.h" #include "util.h" +#ifdef CONFIG_KEYBOARD_MULTIPLE +#include "keyboard_customization.h" +#endif + /* Console output macros */ #define CPUTS(outstr) cputs(CC_KEYSCAN, outstr) -#define CPRINTF(format, args...) cprintf(CC_KEYSCAN, format, ## args) -#define CPRINTS(format, args...) cprints(CC_KEYSCAN, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_KEYSCAN, format, ##args) +#define CPRINTS(format, args...) cprints(CC_KEYSCAN, format, ##args) #ifdef CONFIG_KEYBOARD_DEBUG #define CPUTS5(outstr) cputs(CC_KEYSCAN, outstr) -#define CPRINTS5(format, args...) cprints(CC_KEYBOARD, format, ## args) +#define CPRINTS5(format, args...) cprints(CC_KEYBOARD, format, ##args) #else #define CPUTS5(outstr) #define CPRINTS5(format, args...) #endif -#define SCAN_TIME_COUNT 32 /* Number of last scan times to track */ +#define SCAN_TIME_COUNT 32 /* Number of last scan times to track */ /* If we're waiting for a scan to happen, we'll give it this long */ -#define SCAN_TASK_TIMEOUT_US (100 * MSEC) +#define SCAN_TASK_TIMEOUT_US (100 * MSEC) #ifndef CONFIG_KEYBOARD_POST_SCAN_CLOCKS /* @@ -53,9 +60,7 @@ #define CONFIG_KEYBOARD_POST_SCAN_CLOCKS 16000 #endif -#ifndef CONFIG_KEYBOARD_BOARD_CONFIG -/* Use default keyboard scan config, because board didn't supply one */ -struct keyboard_scan_config keyscan_config = { +__overridable struct keyboard_scan_config keyscan_config = { #ifdef CONFIG_KEYBOARD_COL2_INVERTED /* * CONFIG_KEYBOARD_COL2_INVERTED is defined for passing the column 2 @@ -78,54 +83,52 @@ struct keyboard_scan_config keyscan_config = { 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */ }, }; -#endif - -/* Boot key list. Must be in same order as enum boot_key. */ -struct boot_key_entry { - uint8_t mask_index; - uint8_t mask_value; -}; #ifdef CONFIG_KEYBOARD_BOOT_KEYS +#ifndef CONFIG_KEYBOARD_MULTIPLE static const struct boot_key_entry boot_key_list[] = { - {KEYBOARD_COL_ESC, KEYBOARD_MASK_ESC}, /* Esc */ - {KEYBOARD_COL_DOWN, KEYBOARD_MASK_DOWN}, /* Down-arrow */ - {KEYBOARD_COL_LEFT_SHIFT, KEYBOARD_MASK_LEFT_SHIFT}, /* Left-Shift */ + { KEYBOARD_COL_ESC, KEYBOARD_ROW_ESC }, /* Esc */ + { KEYBOARD_COL_DOWN, KEYBOARD_ROW_DOWN }, /* Down-arrow */ + { KEYBOARD_COL_LEFT_SHIFT, KEYBOARD_ROW_LEFT_SHIFT }, /* Left-Shift */ +}; +#else +struct boot_key_entry boot_key_list[] = { + { KEYBOARD_COL_ESC, KEYBOARD_ROW_ESC }, /* Esc */ + { KEYBOARD_COL_DOWN, KEYBOARD_ROW_DOWN }, /* Down-arrow */ + { KEYBOARD_COL_LEFT_SHIFT, KEYBOARD_ROW_LEFT_SHIFT }, /* Left-Shift */ }; +#endif static uint32_t boot_key_value = BOOT_KEY_NONE; #endif uint8_t keyboard_cols = KEYBOARD_COLS_MAX; /* Debounced key matrix */ -static uint8_t __bss_slow debounced_state[KEYBOARD_COLS_MAX]; +static uint8_t debounced_state[KEYBOARD_COLS_MAX]; /* Mask of keys being debounced */ -static uint8_t __bss_slow debouncing[KEYBOARD_COLS_MAX]; +static uint8_t debouncing[KEYBOARD_COLS_MAX]; /* Keys simulated-pressed */ -static uint8_t __bss_slow simulated_key[KEYBOARD_COLS_MAX]; -#ifdef CONFIG_KEYBOARD_LANGUAGE_ID -static uint8_t __bss_slow keyboard_id[KEYBOARD_IDS]; -#endif +static uint8_t simulated_key[KEYBOARD_COLS_MAX]; /* Times of last scans */ -static uint32_t __bss_slow scan_time[SCAN_TIME_COUNT]; +static uint32_t scan_time[SCAN_TIME_COUNT]; /* Current scan_time[] index */ -static int __bss_slow scan_time_index; +static int scan_time_index; /* Index into scan_time[] when each key started debouncing */ -static uint8_t __bss_slow scan_edge_index[KEYBOARD_COLS_MAX][KEYBOARD_ROWS]; +static uint8_t scan_edge_index[KEYBOARD_COLS_MAX][KEYBOARD_ROWS]; /* Minimum delay between keyboard scans based on current clock frequency */ -static uint32_t __bss_slow post_scan_clock_us; +static uint32_t post_scan_clock_us; /* * Print all keyboard scan state changes? Off by default because it generates * a lot of debug output, which makes the saved EC console data less useful. */ -static int __bss_slow print_state_changes; +static int print_state_changes; /* Must init to 0 for scanning at boot */ -static volatile uint32_t __bss_slow disable_scanning_mask; +static volatile uint32_t disable_scanning_mask; /* Constantly incrementing counter of the number of times we polled */ static volatile int kbd_polls; @@ -133,7 +136,7 @@ static volatile int kbd_polls; /* If true, we'll force a keyboard poll */ static volatile int force_poll; -static int keyboard_scan_is_enabled(void) +test_export_static int keyboard_scan_is_enabled(void) { /* NOTE: this is just an instantaneous glimpse of the variable. */ return !disable_scanning_mask; @@ -141,17 +144,21 @@ static int keyboard_scan_is_enabled(void) void keyboard_scan_enable(int enable, enum kb_scan_disable_masks mask) { + atomic_val_t old; /* Access atomically */ if (enable) { - deprecated_atomic_clear_bits((uint32_t *)&disable_scanning_mask, - mask); + old = atomic_clear_bits((atomic_t *)&disable_scanning_mask, + mask); } else { - deprecated_atomic_or((uint32_t *)&disable_scanning_mask, mask); + old = atomic_or((atomic_t *)&disable_scanning_mask, mask); clear_typematic_key(); } - /* Let the task figure things out */ - task_wake(TASK_ID_KEYSCAN); + /* Using atomic_get() causes build errors on some archs */ + if (old != disable_scanning_mask) { + /* If the mask has changed, let the task figure things out */ + task_wake(TASK_ID_KEYSCAN); + } } /** @@ -163,8 +170,10 @@ void keyboard_scan_enable(int enable, enum kb_scan_disable_masks mask) static void print_state(const uint8_t *state, const char *msg) { int c; + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; - CPRINTF("[%pT KB %s:", PRINTF_TIMESTAMP_NOW, msg); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + CPRINTF("[%s KB %s:", ts_str, msg); for (c = 0; c < keyboard_cols; c++) { if (state[c]) CPRINTF(" %02x", state[c]); @@ -198,6 +207,51 @@ static void ensure_keyboard_scanned(int old_polls) usleep(keyscan_config.scan_period_us); } +#ifdef CONFIG_KEYBOARD_SCAN_ADC +/** + * Read KSI ADC rows + * + * Read each adc channel and look for voltage crossing threshold level + */ +static int keyboard_read_adc_rows(void) +{ + uint8_t kb_row = 0; + + /* Read each adc channel to build row byte */ + for (int i = 0; i < KEYBOARD_ROWS; i++) { + if (adc_read_channel(ADC_KSI_00 + i) > + keyscan_config.ksi_threshold_mv) + kb_row |= (1 << i); + } + + return kb_row; +} + +/** + * Read refresh key + * + * Refresh key is detached from rest of the matrix in ADC based + * keyboard, so needs to be read through GPIO + * + * @param state Destination for new state (must be KEYBOARD_COLS_MAX + * long). + */ +static void keyboard_read_refresh_key(uint8_t *state) +{ +#ifndef CONFIG_KEYBOARD_MULTIPLE + if (!gpio_get_level(GPIO_RFR_KEY_L)) + state[KEYBOARD_COL_REFRESH] |= BIT(KEYBOARD_ROW_REFRESH); + else + state[KEYBOARD_COL_REFRESH] &= ~BIT(KEYBOARD_ROW_REFRESH); +#else + if (!gpio_get_level(GPIO_RFR_KEY_L)) + state[key_typ.col_refresh] |= BIT(key_typ.row_refresh); + else + state[key_typ.col_refresh] &= ~BIT(key_typ.row_refresh); +#endif +} +#endif + /** * Simulate a keypress. * @@ -210,7 +264,7 @@ static void simulate_key(int row, int col, int pressed) int old_polls; if ((simulated_key[col] & BIT(row)) == ((pressed ? 1 : 0) << row)) - return; /* No change */ + return; /* No change */ simulated_key[col] ^= BIT(row); @@ -230,8 +284,8 @@ static void simulate_key(int row, int col, int pressed) * That means it needs to have run and for enough time. */ ensure_keyboard_scanned(old_polls); - usleep(pressed ? - keyscan_config.debounce_down_us : keyscan_config.debounce_up_us); + usleep(pressed ? keyscan_config.debounce_down_us : + keyscan_config.debounce_up_us); ensure_keyboard_scanned(kbd_polls); } @@ -243,10 +297,11 @@ static void simulate_key(int row, int col, int pressed) * * @param state Destination for new state (must be KEYBOARD_COLS_MAX * long). + * @param at_boot True if we are reading the boot key state. * * @return 1 if at least one key is pressed, else zero. */ -static int read_matrix(uint8_t *state) +static int read_matrix(uint8_t *state, bool at_boot) { int c; int pressed = 0; @@ -270,14 +325,52 @@ static int read_matrix(uint8_t *state) udelay(keyscan_config.output_settle_us); /* Read the row state */ +#ifdef CONFIG_KEYBOARD_SCAN_ADC + state[c] = keyboard_read_adc_rows(); +#else state[c] = keyboard_raw_read_rows(); +#endif /* Use simulated keyscan sequence instead if testing active */ if (IS_ENABLED(CONFIG_KEYBOARD_TEST)) state[c] = keyscan_seq_get_scan(c, state[c]); } - /* 2. Detect transitional ghost */ +#ifdef KEYBOARD_MASK_PWRBTN + /* + * 2. Boot key workaround. + * + * Check if KSI2 or KSI3 is asserted for all columns due to power + * button hold, and ignore it if so. + */ + if (at_boot) { + for (c = 0; c < keyboard_cols; c++) { + if (!(state[c] & KEYBOARD_MASK_PWRBTN)) + break; + } + + if (c == keyboard_cols) { + for (c = 0; c < keyboard_cols; c++) + state[c] &= ~KEYBOARD_MASK_PWRBTN; +#ifndef CONFIG_KEYBOARD_MULTIPLE + state[KEYBOARD_COL_REFRESH] |= KEYBOARD_MASK_PWRBTN; +#else + state[key_typ.col_refresh] |= KEYBOARD_MASK_PWRBTN; +#endif + } + } +#endif + +#ifdef CONFIG_KEYBOARD_SCAN_ADC + /* Account for the refresh key */ + keyboard_read_refresh_key(state); + + /* + * KB with ADC support doesn't have transitional ghost, + * this check isn't required + */ +#else + /* 3. Detect transitional ghost */ for (c = 0; c < keyboard_cols; c++) { int c2; @@ -300,8 +393,9 @@ static int read_matrix(uint8_t *state) } } } +#endif - /* 3. Fix result */ + /* 4. Fix result */ for (c = 0; c < keyboard_cols; c++) { /* Add in simulated keypresses */ state[c] |= simulated_key[c]; @@ -315,7 +409,6 @@ static int read_matrix(uint8_t *state) /* Mask off keys that don't exist on the actual keyboard */ state[c] &= keyscan_config.actual_key_mask[c]; - } keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE); @@ -323,38 +416,6 @@ static int read_matrix(uint8_t *state) return pressed ? 1 : 0; } -#ifdef CONFIG_KEYBOARD_LANGUAGE_ID -/** - * Read the raw keyboard IDs state. - * - * Used in pre-init, so must not make task-switching-dependent calls; udelay() - * is ok because it's a spin-loop. - * - * @param id Destination for keyboard id (must be KEYBOARD_IDS long). - * - */ -static void read_matrix_id(uint8_t *id) -{ - int c; - - for (c = 0; c < KEYBOARD_IDS; c++) { - /* Select the ID pin, then wait a bit for it to settle. - * Caveat: If a keyboard maker puts ID pins right after scan - * columns, we can't support variable column size with a single - * image. */ - keyboard_raw_drive_column(KEYBOARD_COLS_MAX + c); - udelay(keyscan_config.output_settle_us); - - /* Read the row state */ - id[c] = keyboard_raw_read_rows(); - - CPRINTS("Keyboard ID%u: 0x%02x", c, id[c]); - } - - keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE); -} -#endif - #ifdef CONFIG_KEYBOARD_RUNTIME_KEYS static uint8_t key_vol_up_row = KEYBOARD_DEFAULT_ROW_VOL_UP; @@ -380,47 +441,6 @@ static int check_runtime_keys(const uint8_t *state) int num_press = 0; int c; -#ifdef BOARD_SAMUS - int16_t chg_override; - - /* - * TODO(crosbug.com/p/34850): remove these hot-keys for samus, should - * be done at higher level than this. - */ - /* - * On samus, ctrl + search + 0|1|2 sets the active charge port - * by sending the charge override host command. Should only be sent - * when chipset is in S0. Note that 'search' and '1' keys are on - * the same column. - */ - if ((state[KEYBOARD_COL_LEFT_CTRL] == KEYBOARD_MASK_LEFT_CTRL || - state[KEYBOARD_COL_RIGHT_CTRL] == KEYBOARD_MASK_RIGHT_CTRL) && - ((state[KEYBOARD_COL_SEARCH] & KEYBOARD_MASK_SEARCH) == - KEYBOARD_MASK_SEARCH) && - chipset_in_state(CHIPSET_STATE_ON)) { - if (state[KEYBOARD_COL_KEY_0] == KEYBOARD_MASK_KEY_0) { - /* Charge from neither port */ - chg_override = -2; - pd_host_command(EC_CMD_PD_CHARGE_PORT_OVERRIDE, 0, - &chg_override, 2, NULL, 0); - return 0; - } else if (state[KEYBOARD_COL_KEY_1] == - (KEYBOARD_MASK_KEY_1 | KEYBOARD_MASK_SEARCH)) { - /* Charge from port 0 (left side) */ - chg_override = 0; - pd_host_command(EC_CMD_PD_CHARGE_PORT_OVERRIDE, 0, - &chg_override, 2, NULL, 0); - return 0; - } else if (state[KEYBOARD_COL_KEY_2] == KEYBOARD_MASK_KEY_2) { - /* Charge from port 1 (right side) */ - chg_override = 1; - pd_host_command(EC_CMD_PD_CHARGE_PORT_OVERRIDE, 0, - &chg_override, 2, NULL, 0); - return 0; - } - } -#endif - /* * All runtime key combos are (right or left ) alt + volume up + (some * key NOT on the same col as alt or volume up ) @@ -428,9 +448,15 @@ static int check_runtime_keys(const uint8_t *state) if (state[key_vol_up_col] != KEYBOARD_ROW_TO_MASK(key_vol_up_row)) return 0; +#ifndef CONFIG_KEYBOARD_MULTIPLE if (state[KEYBOARD_COL_RIGHT_ALT] != KEYBOARD_MASK_RIGHT_ALT && state[KEYBOARD_COL_LEFT_ALT] != KEYBOARD_MASK_LEFT_ALT) return 0; +#else + if (state[key_typ.col_right_alt] != KEYBOARD_MASK_RIGHT_ALT && + state[key_typ.col_left_alt] != KEYBOARD_MASK_LEFT_ALT) + return 0; +#endif /* * Count number of columns with keys pressed. We know two columns are @@ -445,6 +471,7 @@ static int check_runtime_keys(const uint8_t *state) if (num_press != 3) return 0; +#ifndef CONFIG_KEYBOARD_MULTIPLE /* Check individual keys */ if (state[KEYBOARD_COL_KEY_R] == KEYBOARD_MASK_KEY_R) { /* R = reboot */ @@ -455,9 +482,24 @@ static int check_runtime_keys(const uint8_t *state) } else if (state[KEYBOARD_COL_KEY_H] == KEYBOARD_MASK_KEY_H) { /* H = hibernate */ CPRINTS("KB hibernate"); - system_hibernate(0, 0); + system_enter_hibernate(0, 0); return 1; } +#else + /* Check individual keys */ + if (state[key_typ.col_key_r] == KEYBOARD_MASK_KEY_R) { + /* R = reboot */ + CPRINTS("KB warm reboot"); + keyboard_clear_buffer(); + chipset_reset(CHIPSET_RESET_KB_WARM_REBOOT); + return 1; + } else if (state[key_typ.col_key_h] == KEYBOARD_MASK_KEY_H) { + /* H = hibernate */ + CPRINTS("KB hibernate"); + system_enter_hibernate(0, 0); + return 1; + } +#endif return 0; } @@ -500,6 +542,16 @@ static int has_ghosting(const uint8_t *state) return 0; } +/* Inform keyboard module if scanning is enabled */ +test_mockable_static void key_state_changed(int row, int col, uint8_t state) +{ + if (!keyboard_scan_is_enabled()) + return; + + /* No-op for protocols that require full keyboard matrix (e.g. MKBP). */ + keyboard_state_changed(row, col, !!(state & BIT(row))); +} + /** * Update keyboard state using low-level interface to read keyboard. * @@ -512,7 +564,7 @@ static int check_keys_changed(uint8_t *state) int any_pressed = 0; int c, i; int any_change = 0; - static uint8_t __bss_slow new_state[KEYBOARD_COLS_MAX]; + static uint8_t new_state[KEYBOARD_COLS_MAX]; uint32_t tnow = get_time().le.lo; /* Save the current scan time */ @@ -521,15 +573,17 @@ static int check_keys_changed(uint8_t *state) scan_time[scan_time_index] = tnow; /* Read the raw key state */ - any_pressed = read_matrix(new_state); + any_pressed = read_matrix(new_state, false); - /* Ignore if so many keys are pressed that we're ghosting. */ - if (has_ghosting(new_state)) - return any_pressed; + if (!IS_ENABLED(CONFIG_KEYBOARD_SCAN_ADC)) { + /* Ignore if so many keys are pressed that we're ghosting. */ + if (has_ghosting(new_state)) + return any_pressed; + } /* Check for changes between previous scan and this one */ for (c = 0; c < keyboard_cols; c++) { - int diff; + int diff = new_state[c] ^ state[c]; /* Clear debouncing flag, if sufficient time has elapsed. */ for (i = 0; i < KEYBOARD_ROWS && debouncing[c]; i++) { @@ -538,8 +592,22 @@ static int check_keys_changed(uint8_t *state) if (tnow - scan_time[scan_edge_index[c][i]] < (state[c] ? keyscan_config.debounce_down_us : keyscan_config.debounce_up_us)) - continue; /* Not done debouncing */ + continue; /* Not done debouncing */ debouncing[c] &= ~BIT(i); + + if (!IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE)) + continue; + if (!(diff & BIT(i))) + /* Debounced but no difference. */ + continue; + any_change = 1; + key_state_changed(i, c, new_state[c]); + /* + * This makes state[c] == new_state[c] for row i. + * Thus, when diff is calculated below, it won't + * be asserted (for row i). + */ + state[c] ^= diff & BIT(i); } /* Recognize change in state, unless debounce in effect. */ @@ -550,15 +618,10 @@ static int check_keys_changed(uint8_t *state) if (!(diff & BIT(i))) continue; scan_edge_index[c][i] = scan_time_index; - any_change = 1; - /* Inform keyboard module if scanning is enabled */ - if (keyboard_scan_is_enabled()) { - /* This is no-op for protocols that require a - * full keyboard matrix (e.g., MKBP). - */ - keyboard_state_changed( - i, c, !!(new_state[c] & BIT(i))); + if (!IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE)) { + any_change = 1; + key_state_changed(i, c, new_state[c]); } } @@ -569,26 +632,24 @@ static int check_keys_changed(uint8_t *state) * (up or down), the state bits are only updated if the * edge was not suppressed due to debouncing. */ - state[c] ^= diff; + if (!IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE)) + state[c] ^= diff; } if (any_change) { - -#ifdef CONFIG_KEYBOARD_SUPPRESS_NOISE - /* Suppress keyboard noise */ - keyboard_suppress_noise(); -#endif - if (print_state_changes) print_state(state, "state"); #ifdef CONFIG_KEYBOARD_PRINT_SCAN_TIMES /* Print delta times from now back to each previous scan */ - CPRINTF("[%pT kb deltaT", PRINTF_TIMESTAMP_NOW); + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; + + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + CPRINTF("[%s kb deltaT", ts_str); for (i = 0; i < SCAN_TIME_COUNT; i++) { - int tnew = scan_time[ - (SCAN_TIME_COUNT + scan_time_index - i) % - SCAN_TIME_COUNT]; + int tnew = scan_time[(SCAN_TIME_COUNT + + scan_time_index - i) % + SCAN_TIME_COUNT]; CPRINTF(" %d", tnow - tnew); } CPRINTF("]\n"); @@ -601,7 +662,7 @@ static int check_keys_changed(uint8_t *state) #endif #ifdef CONFIG_KEYBOARD_PROTOCOL_MKBP - keyboard_fifo_add(state); + mkbp_keyboard_add(state); #endif } @@ -610,6 +671,15 @@ static int check_keys_changed(uint8_t *state) return any_pressed; } +static uint8_t keyboard_mask_refresh; +__overridable uint8_t board_keyboard_row_refresh(void) +{ + if (IS_ENABLED(CONFIG_KEYBOARD_REFRESH_ROW3)) + return 3; + else + return 2; +} + #ifdef CONFIG_KEYBOARD_BOOT_KEYS /* * Returns mask of the boot keys that are pressed, with at most the keys used @@ -625,29 +695,18 @@ static uint32_t check_key_list(const uint8_t *state) /* Make copy of current debounced state. */ memcpy(curr_state, state, sizeof(curr_state)); -#ifdef KEYBOARD_MASK_PWRBTN - /* - * Check if KSI2 or KSI3 is asserted for all columns due to power - * button hold, and ignore it if so. - */ - for (c = 0; c < keyboard_cols; c++) - if ((keyscan_config.actual_key_mask[c] & KEYBOARD_MASK_PWRBTN) - && !(curr_state[c] & KEYBOARD_MASK_PWRBTN)) - break; - - if (c == keyboard_cols) - for (c = 0; c < keyboard_cols; c++) - curr_state[c] &= ~KEYBOARD_MASK_PWRBTN; +#ifndef CONFIG_KEYBOARD_MULTIPLE + curr_state[KEYBOARD_COL_REFRESH] &= ~keyboard_mask_refresh; +#else + curr_state[key_typ.col_refresh] &= ~keyboard_mask_refresh; #endif - curr_state[KEYBOARD_COL_REFRESH] &= ~KEYBOARD_MASK_REFRESH; - /* Update mask with all boot keys that were pressed. */ k = boot_key_list; for (c = 0; c < ARRAY_SIZE(boot_key_list); c++, k++) { - if (curr_state[k->mask_index] & k->mask_value) { + if (curr_state[k->col] & BIT(k->row)) { boot_key_mask |= BIT(c); - curr_state[k->mask_index] &= ~k->mask_value; + curr_state[k->col] &= ~BIT(k->row); } } @@ -661,6 +720,31 @@ static uint32_t check_key_list(const uint8_t *state) return boot_key_mask; } +#ifdef CONFIG_KEYBOARD_SCAN_ADC +static void read_adc_boot_keys(uint8_t *state) +{ + int k; + + for (k = 0; k < ARRAY_SIZE(boot_key_list); k++) { + int c = boot_key_list[k].col; + int r = boot_key_list[k].row; + + /* Select column, then wait a bit for it to settle */ + keyboard_raw_drive_column(c); + udelay(keyscan_config.output_settle_us); + + if (adc_read_channel(ADC_KSI_00 + r) > + keyscan_config.ksi_threshold_mv) + state[c] |= BIT(r); + } + + /* Read refresh key */ + keyboard_read_refresh_key(state); + + keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE); +} +#endif + /** * Check what boot key is down, if any. * @@ -680,10 +764,16 @@ static uint32_t check_boot_key(const uint8_t *state) if (system_jumped_late()) return BOOT_KEY_NONE; - /* If reset was not caused by reset pin, refresh must be held down */ +/* If reset was not caused by reset pin, refresh must be held down */ +#ifndef CONFIG_KEYBOARD_MULTIPLE + if (!(system_get_reset_flags() & EC_RESET_FLAG_RESET_PIN) && + !(state[KEYBOARD_COL_REFRESH] & keyboard_mask_refresh)) + return BOOT_KEY_NONE; +#else if (!(system_get_reset_flags() & EC_RESET_FLAG_RESET_PIN) && - !(state[KEYBOARD_COL_REFRESH] & KEYBOARD_MASK_REFRESH)) + !(state[key_typ.col_refresh] & keyboard_mask_refresh)) return BOOT_KEY_NONE; +#endif return check_key_list(state); } @@ -692,7 +782,7 @@ static uint32_t check_boot_key(const uint8_t *state) static void keyboard_freq_change(void) { post_scan_clock_us = (CONFIG_KEYBOARD_POST_SCAN_CLOCKS * 1000) / - (clock_get_freq() / 1000); + (clock_get_freq() / 1000); } DECLARE_HOOK(HOOK_FREQ_CHANGE, keyboard_freq_change, HOOK_PRIO_DEFAULT); @@ -718,18 +808,31 @@ const uint8_t *keyboard_scan_get_state(void) void keyboard_scan_init(void) { - /* Configure GPIO */ - keyboard_raw_init(); + if (IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE) && + keyscan_config.debounce_down_us != keyscan_config.debounce_up_us) { + /* + * Strict debouncer is prone to keypress reordering if debounce + * durations for down and up are not equal. crbug.com/547131 + */ + CPRINTS("KB WARN: Debounce durations not equal"); + } + + /* Configure refresh key matrix */ + keyboard_mask_refresh = + KEYBOARD_ROW_TO_MASK(board_keyboard_row_refresh()); + + if (!IS_ENABLED(CONFIG_KEYBOARD_SCAN_ADC)) + /* Configure GPIO */ + keyboard_raw_init(); /* Tri-state the columns */ keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE); /* Initialize raw state */ - read_matrix(debounced_state); - -#ifdef CONFIG_KEYBOARD_LANGUAGE_ID - /* Check keyboard ID state */ - read_matrix_id(keyboard_id); +#ifndef CONFIG_KEYBOARD_SCAN_ADC + read_matrix(debounced_state, true); +#else + read_adc_boot_keys(debounced_state); #endif #ifdef CONFIG_KEYBOARD_BOOT_KEYS @@ -771,6 +874,7 @@ void keyboard_scan_task(void *u) uint32_t local_disable_scanning = 0; print_state(debounced_state, "init state"); + poll_deadline.val = 0; keyboard_raw_task_start(); @@ -792,7 +896,8 @@ void keyboard_scan_task(void *u) if (local_disable_scanning != new_disable_scanning) CPRINTS("KB disable_scanning_mask changed: " - "0x%08x", new_disable_scanning); + "0x%08x", + new_disable_scanning); if (!new_disable_scanning) { /* Enabled now */ @@ -820,9 +925,16 @@ void keyboard_scan_task(void *u) * user pressing a key and enable_interrupt() * starting to pay attention to edges. */ +#ifndef CONFIG_KEYBOARD_SCAN_ADC if (!local_disable_scanning && (keyboard_raw_read_rows() || force_poll)) break; +#else + if (!local_disable_scanning && + (keyboard_read_adc_rows() || force_poll || + !gpio_get_level(GPIO_RFR_KEY_L))) + break; +#endif else task_wait_event(-1); } @@ -841,15 +953,16 @@ void keyboard_scan_task(void *u) /* Check for keys down */ if (check_keys_changed(debounced_state)) { - poll_deadline.val = start.val - + keyscan_config.poll_timeout_us; + poll_deadline.val = + start.val + + keyscan_config.poll_timeout_us; } else if (timestamp_expired(poll_deadline, &start)) { break; } /* Delay between scans */ wait_time = keyscan_config.scan_period_us - - (get_time().val - start.val); + (get_time().val - start.val); if (wait_time < keyscan_config.min_post_scan_delay_us) wait_time = @@ -873,7 +986,7 @@ static void keyboard_lid_change(void) keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_CLOSED); } DECLARE_HOOK(HOOK_LID_CHANGE, keyboard_lid_change, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_INIT, keyboard_lid_change, HOOK_PRIO_INIT_LID + 1); +DECLARE_HOOK(HOOK_INIT, keyboard_lid_change, HOOK_PRIO_POST_LID); #endif @@ -911,8 +1024,7 @@ mkbp_command_simulate_key(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_MKBP_SIMULATE_KEY, - mkbp_command_simulate_key, +DECLARE_HOST_COMMAND(EC_CMD_MKBP_SIMULATE_KEY, mkbp_command_simulate_key, EC_VER_MASK(0)); #ifdef CONFIG_KEYBOARD_FACTORY_TEST @@ -928,19 +1040,23 @@ int keyboard_factory_test_scan(void) keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_CLOSED); flags = gpio_get_default_flags(GPIO_KBD_KSO2); + if (IS_ENABLED(CONFIG_ZEPHYR)) + /* set all KSI/KSO pins to GPIO_ALT_FUNC_NONE */ + keybaord_raw_config_alt(0); + /* Set all of KSO/KSI pins to internal pull-up and input */ for (i = 0; i < keyboard_factory_scan_pins_used; i++) { - if (keyboard_factory_scan_pins[i][0] < 0) continue; port = keyboard_factory_scan_pins[i][0]; id = keyboard_factory_scan_pins[i][1]; - gpio_set_alternate_function(port, 1 << id, - GPIO_ALT_FUNC_NONE); + if (!IS_ENABLED(CONFIG_ZEPHYR)) + gpio_set_alternate_function(port, 1 << id, + GPIO_ALT_FUNC_NONE); gpio_set_flags_by_mask(port, 1 << id, - GPIO_INPUT | GPIO_PULL_UP); + GPIO_INPUT | GPIO_PULL_UP); } /* @@ -948,7 +1064,6 @@ int keyboard_factory_test_scan(void) * going to low level, it indicate the two pins are shorted. */ for (i = 0; i < keyboard_factory_scan_pins_used; i++) { - if (keyboard_factory_scan_pins[i][0] < 0) continue; @@ -957,23 +1072,25 @@ int keyboard_factory_test_scan(void) gpio_set_flags_by_mask(port, 1 << id, GPIO_OUT_LOW); - for (j = 0; j < i; j++) { - - if (keyboard_factory_scan_pins[j][0] < 0) + for (j = 0; j < keyboard_factory_scan_pins_used; j++) { + if (keyboard_factory_scan_pins[j][0] < 0 || i == j) continue; if (keyboard_raw_is_input_low( - keyboard_factory_scan_pins[j][0], - keyboard_factory_scan_pins[j][1])) { + keyboard_factory_scan_pins[j][0], + keyboard_factory_scan_pins[j][1])) { shorted = i << 8 | j; goto done; } } gpio_set_flags_by_mask(port, 1 << id, - GPIO_INPUT | GPIO_PULL_UP); + GPIO_INPUT | GPIO_PULL_UP); } done: - gpio_config_module(MODULE_KEYBOARD_SCAN, 1); + if (IS_ENABLED(CONFIG_ZEPHYR)) + keybaord_raw_config_alt(1); + else + gpio_config_module(MODULE_KEYBOARD_SCAN, 1); gpio_set_flags(GPIO_KBD_KSO2, flags); keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_CLOSED); @@ -998,35 +1115,14 @@ static enum ec_status keyboard_factory_test(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_KEYBOARD_FACTORY_TEST, - keyboard_factory_test, +DECLARE_HOST_COMMAND(EC_CMD_KEYBOARD_FACTORY_TEST, keyboard_factory_test, EC_VER_MASK(0)); #endif -#ifdef CONFIG_KEYBOARD_LANGUAGE_ID -int keyboard_get_keyboard_id(void) -{ - int c; - uint32_t id = 0; - - BUILD_ASSERT(sizeof(id) >= KEYBOARD_IDS); - - for (c = 0; c < KEYBOARD_IDS; c++) { - /* Check ID ghosting if more than one bit in any KSIs was set */ - if (keyboard_id[c] & (keyboard_id[c] - 1)) - /* ID ghosting is found */ - return KEYBOARD_ID_UNREADABLE; - else - id |= keyboard_id[c] << (c * 8); - } - return id; -} -#endif - /*****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_KEYBOARD -static int command_ksstate(int argc, char **argv) +static int command_ksstate(int argc, const char **argv) { if (argc > 1) { if (!strcasecmp(argv[1], "force")) { @@ -1040,17 +1136,15 @@ static int command_ksstate(int argc, char **argv) print_state(debounced_state, "debounced "); print_state(debouncing, "debouncing"); - ccprintf("Keyboard scan disable mask: 0x%08x\n", - disable_scanning_mask); + ccprintf("Keyboard scan disable mask: 0x%08x\n", disable_scanning_mask); ccprintf("Keyboard scan state printing %s\n", print_state_changes ? "on" : "off"); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(ksstate, command_ksstate, - "ksstate [on | off | force]", +DECLARE_CONSOLE_COMMAND(ksstate, command_ksstate, "ksstate [on | off | force]", "Show or toggle printing keyboard scan state"); -static int command_keyboard_press(int argc, char **argv) +static int command_keyboard_press(int argc, const char **argv) { if (argc == 1) { int i, j; @@ -1091,7 +1185,29 @@ static int command_keyboard_press(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(kbpress, command_keyboard_press, - "[col row [0 | 1]]", +DECLARE_CONSOLE_COMMAND(kbpress, command_keyboard_press, "[col row [0 | 1]]", "Simulate keypress"); #endif + +#ifdef TEST_BUILD +__test_only int keyboard_scan_get_print_state_changes(void) +{ + return print_state_changes; +} + +__test_only void keyboard_scan_set_print_state_changes(int val) +{ + print_state_changes = val; +} + +__test_only void test_keyboard_scan_debounce_reset(void) +{ + memset(&debouncing, 0, sizeof(debouncing)); + memset(&debounced_state, 0, sizeof(debounced_state)); + memset(&scan_time, 0, sizeof(scan_time)); + memset(&scan_edge_index, 0, sizeof(scan_edge_index)); + + scan_time_index = 0; + post_scan_clock_us = 0; +} +#endif /* TEST_BUILD */ diff --git a/common/keyboard_test.c b/common/keyboard_test.c index e7b1dfe501..eb6fc11bdd 100644 --- a/common/keyboard_test.c +++ b/common/keyboard_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2013 The Chromium OS Authors. All rights reserved. + * Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,8 +13,8 @@ #include enum { - KEYSCAN_MAX_LENGTH = 20, - KEYSCAN_SEQ_START_DELAY_US = 10000, + KEYSCAN_MAX_LENGTH = 20, + KEYSCAN_SEQ_START_DELAY_US = 10000, }; static uint8_t keyscan_seq_count; @@ -151,8 +151,8 @@ static int keyscan_seq_collect(struct ec_params_keyscan_seq_ctrl *req, resp->collect.num_items = end - start; for (i = start, ksi = keyscan_items; i < end; i++, ksi++) - resp->collect.item[i].flags = ksi->done ? - EC_KEYSCAN_SEQ_FLAG_DONE : 0; + resp->collect.item[i].flags = + ksi->done ? EC_KEYSCAN_SEQ_FLAG_DONE : 0; return sizeof(*resp) + resp->collect.num_items; } @@ -186,7 +186,8 @@ static enum ec_status keyscan_seq_ctrl(struct host_cmd_handler_args *args) keyscan_seq_start(); break; case EC_KEYSCAN_SEQ_COLLECT: - args->response_size = keyscan_seq_collect(&req, + args->response_size = keyscan_seq_collect( + &req, (struct ec_result_keyscan_seq_ctrl *)args->response); break; default: @@ -196,6 +197,4 @@ static enum ec_status keyscan_seq_ctrl(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_KEYSCAN_SEQ_CTRL, - keyscan_seq_ctrl, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_KEYSCAN_SEQ_CTRL, keyscan_seq_ctrl, EC_VER_MASK(0)); diff --git a/common/keyboard_vivaldi.c b/common/keyboard_vivaldi.c index 6a614ef87b..44bbff2c11 100644 --- a/common/keyboard_vivaldi.c +++ b/common/keyboard_vivaldi.c @@ -1,44 +1,47 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Vivali Keyboard code for Chrome EC */ +#include "builtin/assert.h" +#include "ec_commands.h" +#include "gpio.h" #include "keyboard_8042_sharedlib.h" #include "keyboard_scan.h" -#include "ec_commands.h" + +#include #include #include -#include /* Console output macros */ #define CPUTS(outstr) cputs(CC_KEYBOARD, outstr) -#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ##args) /* * Row Column info for Top row keys T1 - T15. This has been sourced from * go/vivaldi-matrix (internal link for vivaldi scan matrix spec). */ -static const struct key { +__overridable const struct key { uint8_t row; uint8_t col; } vivaldi_keys[] = { - {.row = 0, .col = 2}, /* T1 */ - {.row = 3, .col = 2}, /* T2 */ - {.row = 2, .col = 2}, /* T3 */ - {.row = 1, .col = 2}, /* T4 */ - {.row = 3, .col = 4}, /* T5 */ - {.row = 2, .col = 4}, /* T6 */ - {.row = 1, .col = 4}, /* T7 */ - {.row = 2, .col = 9}, /* T8 */ - {.row = 1, .col = 9}, /* T9 */ - {.row = 0, .col = 4}, /* T10 */ - {.row = 0, .col = 1}, /* T11 */ - {.row = 1, .col = 5}, /* T12 */ - {.row = 3, .col = 5}, /* T13 */ - {.row = 0, .col = 9}, /* T14 */ - {.row = 0, .col = 11}, /* T15 */ + { .row = 0, .col = 2 }, /* T1 */ + { .row = 3, .col = 2 }, /* T2 */ + { .row = 2, .col = 2 }, /* T3 */ + { .row = 1, .col = 2 }, /* T4 */ + { .row = 3, .col = 4 }, /* T5 */ + { .row = 2, .col = 4 }, /* T6 */ + { .row = 1, .col = 4 }, /* T7 */ + { .row = 2, .col = 9 }, /* T8 */ + { .row = 1, .col = 9 }, /* T9 */ + { .row = 0, .col = 4 }, /* T10 */ + { .row = 0, .col = 1 }, /* T11 */ + { .row = 1, .col = 5 }, /* T12 */ + { .row = 3, .col = 5 }, /* T13 */ + { .row = 0, .col = 9 }, /* T14 */ + { .row = 0, .col = 11 }, /* T15 */ }; BUILD_ASSERT(ARRAY_SIZE(vivaldi_keys) == MAX_TOP_ROW_KEYS); @@ -61,12 +64,15 @@ static const uint16_t action_scancodes[] = { [TK_KBD_BKLIGHT_DOWN] = SCANCODE_KBD_BKLIGHT_DOWN, [TK_KBD_BKLIGHT_UP] = SCANCODE_KBD_BKLIGHT_UP, [TK_PRIVACY_SCRN_TOGGLE] = SCANCODE_PRIVACY_SCRN_TOGGLE, + [TK_MICMUTE] = SCANCODE_MICMUTE, + [TK_KBD_BKLIGHT_TOGGLE] = SCANCODE_KBD_BKLIGHT_TOGGLE, + [TK_MENU] = SCANCODE_MENU, }; static const struct ec_response_keybd_config *vivaldi_keybd; -static enum -ec_status get_vivaldi_keybd_config(struct host_cmd_handler_args *args) +static enum ec_status +get_vivaldi_keybd_config(struct host_cmd_handler_args *args) { struct ec_response_keybd_config *resp = args->response; @@ -86,8 +92,8 @@ DECLARE_HOST_COMMAND(EC_CMD_GET_KEYBD_CONFIG, get_vivaldi_keybd_config, * Boards selecting CONFIG_KEYBOARD_CUSTOMIZATION are likely to not * want vivaldi code messing with their customized keyboards. */ -__overridable -const struct ec_response_keybd_config *board_vivaldi_keybd_config(void) +__overridable const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) { return NULL; } @@ -113,8 +119,8 @@ static const struct ec_response_keybd_config default_keybd = { .capabilities = KEYBD_CAP_SCRNLOCK_KEY, }; -__overridable -const struct ec_response_keybd_config *board_vivaldi_keybd_config(void) +__overridable const struct ec_response_keybd_config * +board_vivaldi_keybd_config(void) { return &default_keybd; } @@ -145,7 +151,6 @@ static void vivaldi_init(void) } for (i = 0; i < ARRAY_SIZE(vivaldi_keys); i++) { - uint8_t row, col, *mask; enum action_key key; @@ -153,8 +158,8 @@ static void vivaldi_init(void) col = vivaldi_keys[i].col; if (col >= KEYBOARD_COLS_MAX || row >= KEYBOARD_ROWS) { - CPRINTS("VIVALDI: Bad (row,col) for T-%u: (%u,%u)", - i, row, col); + CPRINTS("VIVALDI: Bad (row,col) for T-%u: (%u,%u)", i, + row, col); ASSERT(false); } @@ -167,18 +172,16 @@ static void vivaldi_init(void) key = vivaldi_keybd->action_keys[i]; if (i < vivaldi_keybd->num_top_row_keys && key != TK_ABSENT) { - /* Enable the mask */ *mask |= BIT(row); /* Populate the scancode */ set_scancode_set2(row, col, action_scancodes[key]); - CPRINTS("VIVALDI key-%u (r-%u, c-%u) = scancode-%X", - i, row, col, action_scancodes[key]); + CPRINTS("VIVALDI key-%u (r-%u, c-%u) = scancode-%X", i, + row, col, action_scancodes[key]); if (key == TK_VOL_UP) set_vol_up_key(row, col); - } } } diff --git a/common/lb_common.c b/common/lb_common.c index 08783997fa..eca21bfb03 100644 --- a/common/lb_common.c +++ b/common/lb_common.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -97,12 +97,13 @@ #include "ec_commands.h" #include "i2c.h" #include "lb_common.h" +#include "printf.h" #include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_LIGHTBAR, outstr) -#define CPRINTF(format, args...) cprintf(CC_LIGHTBAR, format, ## args) -#define CPRINTS(format, args...) cprints(CC_LIGHTBAR, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_LIGHTBAR, format, ##args) +#define CPRINTS(format, args...) cprints(CC_LIGHTBAR, format, ##args) /******************************************************************************/ /* How to talk to the controller */ @@ -120,9 +121,8 @@ static inline void controller_write(int ctrl_num, uint8_t reg, uint8_t val) buf[0] = reg; buf[1] = val; ctrl_num = ctrl_num % ARRAY_SIZE(i2c_addr_flags); - i2c_xfer_unlocked(I2C_PORT_LIGHTBAR, i2c_addr_flags[ctrl_num], - buf, 2, 0, 0, - I2C_XFER_SINGLE); + i2c_xfer_unlocked(I2C_PORT_LIGHTBAR, i2c_addr_flags[ctrl_num], buf, 2, + 0, 0, I2C_XFER_SINGLE); } static inline uint8_t controller_read(int ctrl_num, uint8_t reg) @@ -132,7 +132,7 @@ static inline uint8_t controller_read(int ctrl_num, uint8_t reg) ctrl_num = ctrl_num % ARRAY_SIZE(i2c_addr_flags); rv = i2c_xfer_unlocked(I2C_PORT_LIGHTBAR, i2c_addr_flags[ctrl_num], - ®, 1, buf, 1, I2C_XFER_SINGLE); + ®, 1, buf, 1, I2C_XFER_SINGLE); return rv ? 0 : buf[0]; } @@ -149,24 +149,15 @@ static inline uint8_t controller_read(int ctrl_num, uint8_t reg) * I've lowered the other colors until they all appear approximately equal * brightness when full on. That's still pretty bright and a lot of current * drain on the battery, so we'll probably rarely go that high. */ -#define MAX_RED 0x5c +#define MAX_RED 0x5c #define MAX_GREEN 0x30 -#define MAX_BLUE 0x67 -#endif -#if defined(BOARD_SAMUS) -/* Samus uses completely different LEDs, so the numbers are different. The - * Samus LEDs can handle much higher currents, but these constants were - * calibrated to provide uniform intensity at the level used by Link. - * See crosbug.com/p/33017 before making any changes. */ -#define MAX_RED 0x34 -#define MAX_GREEN 0x2c -#define MAX_BLUE 0x40 +#define MAX_BLUE 0x67 #endif #ifdef BOARD_HOST /* For testing only */ -#define MAX_RED 0xff +#define MAX_RED 0xff #define MAX_GREEN 0xff -#define MAX_BLUE 0xff +#define MAX_BLUE 0xff #endif /* How we'd like to see the driver chips initialized. The controllers have some @@ -178,20 +169,20 @@ struct initdata_s { }; static const struct initdata_s init_vals[] = { - {0x04, 0x00}, /* no backlight function */ - {0x05, 0x3f}, /* xRGBRGB per chip */ - {0x0f, 0x01}, /* square law looks better */ - {0x10, 0x3f}, /* enable independent LEDs */ - {0x11, 0x00}, /* no auto cycling */ - {0x12, 0x00}, /* no auto cycling */ - {0x13, 0x00}, /* instant fade in/out */ - {0x14, 0x00}, /* not using LED 7 */ - {0x15, 0x00}, /* current for LED 6 (blue) */ - {0x16, 0x00}, /* current for LED 5 (red) */ - {0x17, 0x00}, /* current for LED 4 (green) */ - {0x18, 0x00}, /* current for LED 3 (blue) */ - {0x19, 0x00}, /* current for LED 2 (red) */ - {0x1a, 0x00}, /* current for LED 1 (green) */ + { 0x04, 0x00 }, /* no backlight function */ + { 0x05, 0x3f }, /* xRGBRGB per chip */ + { 0x0f, 0x01 }, /* square law looks better */ + { 0x10, 0x3f }, /* enable independent LEDs */ + { 0x11, 0x00 }, /* no auto cycling */ + { 0x12, 0x00 }, /* no auto cycling */ + { 0x13, 0x00 }, /* instant fade in/out */ + { 0x14, 0x00 }, /* not using LED 7 */ + { 0x15, 0x00 }, /* current for LED 6 (blue) */ + { 0x16, 0x00 }, /* current for LED 5 (red) */ + { 0x17, 0x00 }, /* current for LED 4 (green) */ + { 0x18, 0x00 }, /* current for LED 3 (blue) */ + { 0x19, 0x00 }, /* current for LED 2 (red) */ + { 0x1a, 0x00 }, /* current for LED 1 (green) */ }; /* Controller register lookup tables. */ @@ -199,9 +190,6 @@ static const uint8_t led_to_ctrl[] = { 1, 1, 0, 0 }; #ifdef BOARD_BDS static const uint8_t led_to_isc[] = { 0x18, 0x15, 0x18, 0x15 }; #endif -#ifdef BOARD_SAMUS -static const uint8_t led_to_isc[] = { 0x15, 0x18, 0x15, 0x18 }; -#endif #ifdef BOARD_HOST /* For testing only */ static const uint8_t led_to_isc[] = { 0x15, 0x18, 0x15, 0x18 }; @@ -210,7 +198,7 @@ static const uint8_t led_to_isc[] = { 0x15, 0x18, 0x15, 0x18 }; /* Scale 0-255 into max value */ static inline uint8_t scale_abs(int val, int max) { - return (val * max)/255; + return (val * max) / 255; } /* This is the overall brightness control. */ @@ -223,7 +211,7 @@ static uint8_t current[NUM_LEDS][3]; /* Scale 0-255 by brightness */ static inline uint8_t scale(int val, int max) { - return scale_abs((val * brightness)/255, max); + return scale_abs((val * brightness) / 255, max); } /* Helper function to set one LED color and remember it for later */ @@ -237,8 +225,8 @@ static void setrgb(int led, int red, int green, int blue) bank = led_to_isc[led]; i2c_lock(I2C_PORT_LIGHTBAR, 1); controller_write(ctrl, bank, scale(blue, MAX_BLUE)); - controller_write(ctrl, bank+1, scale(red, MAX_RED)); - controller_write(ctrl, bank+2, scale(green, MAX_GREEN)); + controller_write(ctrl, bank + 1, scale(red, MAX_RED)); + controller_write(ctrl, bank + 2, scale(green, MAX_GREEN)); i2c_lock(I2C_PORT_LIGHTBAR, 0); } @@ -287,8 +275,10 @@ uint8_t lb_get_brightness(void) void lb_init(int use_lock) { int i; + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; - CPRINTF("[%pT LB_init_vals ", PRINTF_TIMESTAMP_NOW); + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + CPRINTF("[%s LB_init_vals ", ts_str); for (i = 0; i < ARRAY_SIZE(init_vals); i++) { CPRINTF("%c", '0' + i % 10); if (use_lock) @@ -322,12 +312,10 @@ void lb_on(void) i2c_lock(I2C_PORT_LIGHTBAR, 0); } -static const uint8_t dump_reglist[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a -}; +static const uint8_t dump_reglist[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1a }; /* Helper for host command to dump controller registers */ void lb_hc_cmd_dump(struct ec_response_lightbar *out) @@ -335,8 +323,7 @@ void lb_hc_cmd_dump(struct ec_response_lightbar *out) int i; uint8_t reg; - BUILD_ASSERT(ARRAY_SIZE(dump_reglist) == - ARRAY_SIZE(out->dump.vals)); + BUILD_ASSERT(ARRAY_SIZE(dump_reglist) == ARRAY_SIZE(out->dump.vals)); for (i = 0; i < ARRAY_SIZE(dump_reglist); i++) { reg = dump_reglist[i]; diff --git a/common/led_common.c b/common/led_common.c index 85879b148f..cabaf22e10 100644 --- a/common/led_common.c +++ b/common/led_common.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -16,7 +16,7 @@ static uint32_t led_auto_control_flags = ~0x00; -static int led_is_supported(enum ec_led_id led_id) +__overridable int led_is_supported(enum ec_led_id led_id) { int i; static int supported_leds = -1; @@ -47,6 +47,21 @@ int led_auto_control_is_enabled(enum ec_led_id led_id) return (led_auto_control_flags & LED_AUTO_CONTROL_FLAG(led_id)) != 0; } +/* Empty functions cannot be verified in testing to not have had any + * side-effects, remove from coverage. + * LCOV_EXCL_START + */ +__attribute__((weak)) void board_led_auto_control(void) +{ + /* + * The projects have only power led won't change the led + * state immediately as the auto command is called for + * they only check the led state while the power state + * is changed. + */ +} +/* LCOV_EXCL_STOP */ + static enum ec_status led_command_control(struct host_cmd_handler_args *args) { const struct ec_params_led_control *p = args->params; @@ -69,6 +84,8 @@ static enum ec_status led_command_control(struct host_cmd_handler_args *args) if (p->flags & EC_LED_FLAGS_AUTO) { led_auto_control(p->led_id, 1); + if (!IS_ENABLED(CONFIG_LED_ONOFF_STATES)) + board_led_auto_control(); } else { if (led_set_brightness(p->led_id, p->brightness) != EC_SUCCESS) return EC_RES_INVALID_PARAM; @@ -79,11 +96,13 @@ static enum ec_status led_command_control(struct host_cmd_handler_args *args) } DECLARE_HOST_COMMAND(EC_CMD_LED_CONTROL, led_command_control, EC_VER_MASK(1)); -__attribute__((weak)) -void led_control(enum ec_led_id led_id, enum ec_led_state state) +#ifndef CONFIG_ZEPHYR +__attribute__((weak)) void led_control(enum ec_led_id led_id, + enum ec_led_state state) { /* * Default weak implementation that does not affect the state of * LED. Boards can provide their own implementation. */ } +#endif diff --git a/common/led_onoff_states.c b/common/led_onoff_states.c index c82cc2d17c..aa35a127b1 100644 --- a/common/led_onoff_states.c +++ b/common/led_onoff_states.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -14,30 +14,56 @@ #include "hooks.h" #include "led_common.h" #include "led_onoff_states.h" +#include "system.h" +#include "util.h" -#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args) +#define CPRINTS(format, args...) cprints(CC_GPIO, format, ##args) + +/* + * In order to support the battery LED being optional (ex. for Chromeboxes), + * set up default battery table, setter, and variables. + */ +__overridable struct led_descriptor led_bat_state_table[LED_NUM_STATES] + [LED_NUM_PHASES]; +__overridable const int led_charge_lvl_1; +__overridable const int led_charge_lvl_2; +__overridable void led_set_color_battery(enum ec_led_colors color) +{ +} + +#ifndef CONFIG_CHARGER +/* Include for the sake of compilation */ +int charge_get_percent(void); +#endif + +static int led_get_charge_percent(void) +{ + return DIV_ROUND_NEAREST(charge_get_display_charge(), 10); +} static enum led_states led_get_state(void) { - int charge_lvl; + int charge_lvl; enum led_states new_state = LED_NUM_STATES; - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + if (!IS_ENABLED(CONFIG_CHARGER)) + return new_state; + + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: /* Get percent charge */ - charge_lvl = charge_get_percent(); + charge_lvl = led_get_charge_percent(); /* Determine which charge state to use */ if (charge_lvl < led_charge_lvl_1) new_state = STATE_CHARGING_LVL_1; else if (charge_lvl < led_charge_lvl_2) new_state = STATE_CHARGING_LVL_2; + else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + new_state = STATE_CHARGING_FULL_S5; else - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) - new_state = STATE_CHARGING_FULL_S5; - else - new_state = STATE_CHARGING_FULL_CHARGE; + new_state = STATE_CHARGING_FULL_CHARGE; break; - case PWR_STATE_DISCHARGE_FULL: + case LED_PWRS_DISCHARGE_FULL: if (extpower_is_present()) { if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) new_state = STATE_CHARGING_FULL_S5; @@ -45,12 +71,12 @@ static enum led_states led_get_state(void) new_state = STATE_CHARGING_FULL_CHARGE; break; } - /* Intentional fall-through */ - case PWR_STATE_DISCHARGE /* and PWR_STATE_DISCHARGE_FULL */: + __fallthrough; + case LED_PWRS_DISCHARGE /* and LED_PWRS_DISCHARGE_FULL */: if (chipset_in_state(CHIPSET_STATE_ON)) { #ifdef CONFIG_LED_ONOFF_STATES_BAT_LOW - if (charge_get_percent() < - CONFIG_LED_ONOFF_STATES_BAT_LOW) + if (led_get_charge_percent() < + CONFIG_LED_ONOFF_STATES_BAT_LOW) new_state = STATE_DISCHARGE_S0_BAT_LOW; else #endif @@ -60,21 +86,24 @@ static enum led_states led_get_state(void) else new_state = STATE_DISCHARGE_S5; break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: new_state = STATE_BATTERY_ERROR; break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) new_state = STATE_CHARGING_FULL_S5; else new_state = STATE_CHARGING_FULL_CHARGE; break; - case PWR_STATE_IDLE: /* External power connected in IDLE */ - if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE) - new_state = STATE_FACTORY_TEST; + case LED_PWRS_IDLE: /* External power connected in IDLE */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + new_state = STATE_DISCHARGE_S5; else new_state = STATE_DISCHARGE_S0; break; + case LED_PWRS_FORCED_IDLE: + new_state = STATE_FACTORY_TEST; + break; default: /* Other states don't alter LED behavior */ break; @@ -83,6 +112,11 @@ static enum led_states led_get_state(void) return new_state; } +__overridable enum led_states board_led_get_state(enum led_states desired_state) +{ + return desired_state; +} + static void led_update_battery(void) { static uint8_t ticks, period; @@ -90,6 +124,8 @@ static void led_update_battery(void) int phase; enum led_states desired_state = led_get_state(); + desired_state = board_led_get_state(desired_state); + /* * We always need to check the current state since the value could * have been manually overwritten. If we're in a new valid state, @@ -111,14 +147,14 @@ static void led_update_battery(void) ticks = 0; period = led_bat_state_table[led_state][LED_PHASE_0].time + - led_bat_state_table[led_state][LED_PHASE_1].time; - + led_bat_state_table[led_state][LED_PHASE_1].time; } /* If this state is undefined, turn the LED off */ if (period == 0) { CPRINTS("Undefined LED behavior for battery state %d," - "turning off LED", led_state); + "turning off LED", + led_state); led_set_color_battery(LED_OFF); return; } @@ -127,15 +163,24 @@ static void led_update_battery(void) * Determine which phase of the state table to use. The phase is * determined if it falls within first phase time duration. */ - phase = ticks < led_bat_state_table[led_state][LED_PHASE_0].time ? - 0 : 1; + phase = ticks < led_bat_state_table[led_state][LED_PHASE_0].time ? 0 : + 1; ticks = (ticks + 1) % period; /* Set the color for the given state and phase */ led_set_color_battery(led_bat_state_table[led_state][phase].color); } -#ifdef CONFIG_LED_POWER_LED +/* + * In order to support the power LED being optional, set up default power LED + * table and setter + */ +__overridable const struct led_descriptor + led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES]; +__overridable void led_set_color_power(enum ec_led_colors color) +{ +} + static enum pwr_led_states pwr_led_get_state(void) { if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { @@ -144,7 +189,10 @@ static enum pwr_led_states pwr_led_get_state(void) else return PWR_LED_STATE_SUSPEND_NO_AC; } else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { - return PWR_LED_STATE_OFF; + if (system_can_boot_ap()) + return PWR_LED_STATE_OFF; + else + return PWR_LED_STATE_OFF_LOW_POWER; } else if (chipset_in_state(CHIPSET_STATE_ON)) { return PWR_LED_STATE_ON; } @@ -164,20 +212,28 @@ static void led_update_power(void) * Otherwise, continue to use old state */ if (desired_state != led_state && desired_state < PWR_LED_NUM_STATES) { + /* + * Allow optional OFF_LOW_POWER state to fall back to + * OFF not defined, as indicated by no specified phase 0 time. + */ + if (desired_state == PWR_LED_STATE_OFF_LOW_POWER && + led_pwr_state_table[desired_state][LED_PHASE_0].time == 0) + desired_state = PWR_LED_STATE_OFF; + /* State is changing */ led_state = desired_state; /* Reset ticks and period when state changes */ ticks = 0; period = led_pwr_state_table[led_state][LED_PHASE_0].time + - led_pwr_state_table[led_state][LED_PHASE_1].time; - + led_pwr_state_table[led_state][LED_PHASE_1].time; } /* If this state is undefined, turn the LED off */ if (period == 0) { CPRINTS("Undefined LED behavior for power state %d," - "turning off LED", led_state); + "turning off LED", + led_state); led_set_color_power(LED_OFF); return; } @@ -186,15 +242,13 @@ static void led_update_power(void) * Determine which phase of the state table to use. The phase is * determined if it falls within first phase time duration. */ - phase = ticks < led_pwr_state_table[led_state][LED_PHASE_0].time ? - 0 : 1; + phase = ticks < led_pwr_state_table[led_state][LED_PHASE_0].time ? 0 : + 1; ticks = (ticks + 1) % period; /* Set the color for the given state and phase */ led_set_color_power(led_pwr_state_table[led_state][phase].color); - } -#endif static void led_init(void) { @@ -203,11 +257,8 @@ static void led_init(void) led_set_color_battery(LED_OFF); /* If power LED is enabled, set it to "off" to start with */ -#ifdef CONFIG_LED_POWER_LED if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) led_set_color_power(LED_OFF); -#endif /* CONFIG_LED_POWER_LED */ - } DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_DEFAULT); @@ -220,9 +271,7 @@ static void led_update(void) */ if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) led_update_battery(); -#ifdef CONFIG_LED_POWER_LED if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) led_update_power(); -#endif } DECLARE_HOOK(HOOK_TICK, led_update, HOOK_PRIO_DEFAULT); diff --git a/common/led_policy_std.c b/common/led_policy_std.c index e9fe4568a2..776935f663 100644 --- a/common/led_policy_std.c +++ b/common/led_policy_std.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,14 +6,14 @@ * This assumes a red/green battery led and a single power led. */ -#include "gpio.h" -#include "hooks.h" #include "battery.h" #include "charge_state.h" #include "chipset.h" +#include "gpio.h" +#include "hooks.h" #include "led_common.h" -#include "util.h" #include "lid_switch.h" +#include "util.h" #ifdef CONFIG_LED_BAT_ACTIVE_LOW #define BAT_LED_ON 0 @@ -31,8 +31,8 @@ #define POWER_LED_OFF 0 #endif -const enum ec_led_id supported_led_ids[] = { - EC_LED_ID_BATTERY_LED, EC_LED_ID_POWER_LED}; +const enum ec_led_id supported_led_ids[] = { EC_LED_ID_BATTERY_LED, + EC_LED_ID_POWER_LED }; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); @@ -42,7 +42,7 @@ enum led_color { LED_AMBER, LED_GREEN, LED_WHITE, - LED_COLOR_COUNT /* Number of colors, not a color itself */ + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; static int bat_led_set_color(enum led_color color) @@ -108,15 +108,18 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) case EC_LED_ID_BATTERY_LED: gpio_set_level(GPIO_BAT_LED_RED, (brightness[EC_LED_COLOR_RED] != 0) ? - BAT_LED_ON : BAT_LED_OFF); + BAT_LED_ON : + BAT_LED_OFF); gpio_set_level(GPIO_BAT_LED_GREEN, (brightness[EC_LED_COLOR_GREEN] != 0) ? - BAT_LED_ON : BAT_LED_OFF); + BAT_LED_ON : + BAT_LED_OFF); break; case EC_LED_ID_POWER_LED: gpio_set_level(GPIO_POWER_LED, (brightness[EC_LED_COLOR_WHITE] != 0) ? - POWER_LED_ON : POWER_LED_OFF); + POWER_LED_ON : + POWER_LED_OFF); break; default: return EC_ERROR_UNKNOWN; @@ -124,7 +127,7 @@ int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) return EC_SUCCESS; } -#ifdef HAS_TASK_CHIPSET +#ifdef CONFIG_AP_POWER_CONTROL static void std_led_shutdown(void) { pwr_led_set_color(LED_OFF); @@ -149,7 +152,6 @@ static void std_led_set_power(void) static void std_led_set_battery(void) { static int battery_second; - uint32_t chflags = charge_get_flags(); battery_second++; @@ -157,32 +159,32 @@ static void std_led_set_battery(void) * Same as the chromeos spec * Green/Amber for CHARGE_FLAG_FORCE_IDLE */ - switch (charge_get_state()) { - case PWR_STATE_CHARGE: + switch (led_pwr_get_state()) { + case LED_PWRS_CHARGE: bat_led_set_color(LED_AMBER); break; - case PWR_STATE_DISCHARGE: + case LED_PWRS_DISCHARGE: if (charge_get_percent() < 3) - bat_led_set_color((battery_second & 1) - ? LED_OFF : LED_AMBER); + bat_led_set_color((battery_second & 1) ? LED_OFF : + LED_AMBER); else if (charge_get_percent() < 10) - bat_led_set_color((battery_second & 3) - ? LED_OFF : LED_AMBER); + bat_led_set_color((battery_second & 3) ? LED_OFF : + LED_AMBER); else bat_led_set_color(LED_OFF); break; - case PWR_STATE_ERROR: + case LED_PWRS_ERROR: bat_led_set_color((battery_second & 1) ? LED_OFF : LED_RED); break; - case PWR_STATE_CHARGE_NEAR_FULL: + case LED_PWRS_CHARGE_NEAR_FULL: bat_led_set_color(LED_GREEN); break; - case PWR_STATE_IDLE: /* External power connected in IDLE. */ - if (chflags & CHARGE_FLAG_FORCE_IDLE) - bat_led_set_color( - (battery_second & 0x2) ? LED_GREEN : LED_AMBER); - else - bat_led_set_color(LED_GREEN); + case LED_PWRS_IDLE: /* External power connected in IDLE. */ + bat_led_set_color(LED_GREEN); + break; + case LED_PWRS_FORCED_IDLE: + bat_led_set_color((battery_second & 0x2) ? LED_GREEN : + LED_AMBER); break; default: /* Other states don't alter LED behavior */ @@ -199,4 +201,3 @@ static void led_second(void) std_led_set_battery(); } DECLARE_HOOK(HOOK_SECOND, led_second, HOOK_PRIO_DEFAULT); - diff --git a/common/led_pwm.c b/common/led_pwm.c index cc946ba522..c8c6e72e9f 100644 --- a/common/led_pwm.c +++ b/common/led_pwm.c @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -31,7 +31,9 @@ #define PULSE_TICK (250 * MSEC) +#ifndef CONFIG_LED_PWM_TASK_DISABLED static uint8_t led_is_pulsing; +#endif /* CONFIG_LED_PWM_TASK_DISABLED */ static int get_led_id_color(enum pwm_led_id id, int color) { @@ -54,7 +56,7 @@ static int get_led_id_color(enum pwm_led_id id, int color) void set_pwm_led_color(enum pwm_led_id id, int color) { - struct pwm_led duty = { 0 }; + struct pwm_led_color_map duty = { 0 }; const struct pwm_led *led = &pwm_leds[id]; if ((id >= CONFIG_LED_PWM_COUNT) || (id < 0) || @@ -67,11 +69,11 @@ void set_pwm_led_color(enum pwm_led_id id, int color) duty.ch2 = led_color_map[color].ch2; } - if (led->ch0 != (enum pwm_channel)PWM_LED_NO_CHANNEL) + if (led->ch0 != PWM_LED_NO_CHANNEL) led->set_duty(led->ch0, duty.ch0); - if (led->ch1 != (enum pwm_channel)PWM_LED_NO_CHANNEL) + if (led->ch1 != PWM_LED_NO_CHANNEL) led->set_duty(led->ch1, duty.ch1); - if (led->ch2 != (enum pwm_channel)PWM_LED_NO_CHANNEL) + if (led->ch2 != PWM_LED_NO_CHANNEL) led->set_duty(led->ch2, duty.ch2); } @@ -93,17 +95,19 @@ static void set_led_color(int color) static void set_pwm_led_enable(enum pwm_led_id id, int enable) { +#ifndef CONFIG_ZEPHYR const struct pwm_led *led = &pwm_leds[id]; if ((id >= CONFIG_LED_PWM_COUNT) || (id < 0)) return; - if (led->ch0 != (enum pwm_channel)PWM_LED_NO_CHANNEL) + if (led->ch0 != PWM_LED_NO_CHANNEL) led->enable(led->ch0, enable); - if (led->ch1 != (enum pwm_channel)PWM_LED_NO_CHANNEL) + if (led->ch1 != PWM_LED_NO_CHANNEL) led->enable(led->ch1, enable); - if (led->ch2 != (enum pwm_channel)PWM_LED_NO_CHANNEL) + if (led->ch2 != PWM_LED_NO_CHANNEL) led->enable(led->ch2, enable); +#endif } static void init_leds_off(void) @@ -118,8 +122,9 @@ static void init_leds_off(void) set_pwm_led_enable(PWM_LED1, 1); #endif /* CONFIG_LED_PWM_COUNT >= 2 */ } -DECLARE_HOOK(HOOK_INIT, init_leds_off, HOOK_PRIO_INIT_PWM + 1); +DECLARE_HOOK(HOOK_INIT, init_leds_off, HOOK_PRIO_POST_PWM); +#ifndef CONFIG_LED_PWM_TASK_DISABLED static uint8_t pulse_period; static uint8_t pulse_ontime; static enum ec_led_colors pulse_color; @@ -160,9 +165,10 @@ static void pulse_leds(enum ec_led_colors color, int ontime, int period) pulse_leds_deferred(); } +#ifdef CONFIG_BATTERY static int show_charge_state(void) { - enum charge_state chg_st = charge_get_state(); + enum led_pwr_state chg_st = led_pwr_get_state(); /* * The colors listed below are the default, but can be overridden. @@ -171,17 +177,18 @@ static int show_charge_state(void) * Solid Green == Charging (near full) * Fast Flash Red == Charging error or battery not present */ - if (chg_st == PWR_STATE_CHARGE) { + if (chg_st == LED_PWRS_CHARGE) { led_is_pulsing = 0; set_led_color(CONFIG_LED_PWM_CHARGE_COLOR); - } else if (chg_st == PWR_STATE_CHARGE_NEAR_FULL || - chg_st == PWR_STATE_DISCHARGE_FULL) { + } else if (chg_st == LED_PWRS_CHARGE_NEAR_FULL || + chg_st == LED_PWRS_DISCHARGE_FULL) { led_is_pulsing = 0; set_led_color(CONFIG_LED_PWM_NEAR_FULL_COLOR); } else if ((battery_is_present() != BP_YES) || - (chg_st == PWR_STATE_ERROR)) { - /* 500 ms period, 50% duty cycle. */ - pulse_leds(CONFIG_LED_PWM_CHARGE_ERROR_COLOR, 1, 2); + (chg_st == LED_PWRS_ERROR)) { + /* Ontime and period in PULSE_TICK units. */ + pulse_leds(CONFIG_LED_PWM_CHARGE_ERROR_COLOR, + LED_CHARGER_ERROR_ON_TIME, LED_CHARGER_ERROR_PERIOD); } else { /* Discharging or not charging. */ #ifdef CONFIG_LED_PWM_CHARGE_STATE_ONLY @@ -196,8 +203,10 @@ static int show_charge_state(void) } return 1; } +#endif /* CONFIG_BATTERY */ #ifndef CONFIG_LED_PWM_CHARGE_STATE_ONLY +#ifdef CONFIG_BATTERY static int show_battery_state(void) { int batt_percentage = charge_get_percent(); @@ -220,6 +229,7 @@ static int show_battery_state(void) } return 1; } +#endif /* CONFIG_BATTERY */ static int show_chipset_state(void) { @@ -241,13 +251,17 @@ static int show_chipset_state(void) static void update_leds(void) { +#ifdef CONFIG_BATTERY /* Reflecting the charge state is the highest priority. */ if (show_charge_state()) return; +#endif /* CONFIG_BATTERY */ #ifndef CONFIG_LED_PWM_CHARGE_STATE_ONLY +#ifdef CONFIG_BATTERY if (show_battery_state()) return; +#endif /* CONFIG_BATTERY */ if (show_chipset_state()) return; @@ -257,8 +271,10 @@ static void update_leds(void) } DECLARE_HOOK(HOOK_TICK, update_leds, HOOK_PRIO_DEFAULT); +#endif /* CONFIG_LED_PWM_TASK_DISABLED */ + #ifdef CONFIG_CMD_LEDTEST -int command_ledtest(int argc, char **argv) +static int command_ledtest(int argc, const char **argv) { int enable; int pwm_led_id; @@ -273,9 +289,8 @@ int command_ledtest(int argc, char **argv) led_id = supported_led_ids[pwm_led_id]; if (argc == 2) { - ccprintf("PWM LED %d: led_id=%d, auto_control=%d\n", - pwm_led_id, led_id, - led_auto_control_is_enabled(led_id) != 0); + ccprintf("PWM LED %d: led_id=%d, auto_control=%d\n", pwm_led_id, + led_id, led_auto_control_is_enabled(led_id) != 0); return EC_SUCCESS; } if (!parse_bool(argv[2], &enable)) diff --git a/common/lid_angle.c b/common/lid_angle.c index 295f5486ac..86b6884058 100644 --- a/common/lid_angle.c +++ b/common/lid_angle.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,7 +19,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_LIDANGLE, outstr) -#define CPRINTS(format, args...) cprints(CC_LIDANGLE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LIDANGLE, format, ##args) /* * Define the number of previous lid angle measurements to keep for determining @@ -50,7 +50,7 @@ static int wake_large_angle = 180; static const int wake_small_angle = 13; /* Define hysteresis value to add stability to the flags. */ -#define LID_ANGLE_HYSTERESIS_DEG 2 +#define LID_ANGLE_HYSTERESIS_DEG 2 /* Define max and min values for wake_large_angle. */ #define LID_ANGLE_MIN_LARGE_ANGLE 0 @@ -74,8 +74,8 @@ static int lid_in_range_to_enable_peripherals(int ang) else if (wake_large_angle == LID_ANGLE_MAX_LARGE_ANGLE) return 1; - return (ang >= (wake_small_angle + LID_ANGLE_HYSTERESIS_DEG)) && - (ang <= (wake_large_angle - LID_ANGLE_HYSTERESIS_DEG)); + return (ang >= (wake_small_angle + LID_ANGLE_HYSTERESIS_DEG)) && + (ang <= (wake_large_angle - LID_ANGLE_HYSTERESIS_DEG)); } /** @@ -96,11 +96,10 @@ static int lid_in_range_to_ignore_peripherals(int ang) else if (wake_large_angle == LID_ANGLE_MAX_LARGE_ANGLE) return 0; - return (ang <= (wake_small_angle - LID_ANGLE_HYSTERESIS_DEG)) || - (ang >= (wake_large_angle + LID_ANGLE_HYSTERESIS_DEG)); + return (ang <= (wake_small_angle - LID_ANGLE_HYSTERESIS_DEG)) || + (ang >= (wake_large_angle + LID_ANGLE_HYSTERESIS_DEG)); } - int lid_angle_get_wake_angle(void) { return wake_large_angle; @@ -125,7 +124,7 @@ void lid_angle_update(int lid_ang) /* Record most recent lid angle in circular buffer. */ lidangle_buffer[index] = lid_ang; - index = (index == LID_ANGLE_BUFFER_SIZE-1) ? 0 : index+1; + index = (index == LID_ANGLE_BUFFER_SIZE - 1) ? 0 : index + 1; /* * Manage whether or not peripherals are enabled based on lid angle @@ -178,9 +177,25 @@ static void suspend_peripherals(void) DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, suspend_peripherals, HOOK_PRIO_DEFAULT); #endif /* CONFIG_TABLET_MODE */ -/* Board level callback was not linked in test build, implement it here. */ #ifdef TEST_BUILD -void lid_angle_peripheral_enable(int enable) +__overridable void lid_angle_peripheral_enable(int enable) +{ +} +#else +__overridable void lid_angle_peripheral_enable(int enable) { + int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON); + + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + } else { + /* + * Ensure that the chipset is off before disabling the keyboard. + * When the chipset is on, the EC keeps the keyboard enabled and + * the AP decides whether to ignore input devices or not. + */ + if (!chipset_in_s0) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + } } -#endif +#endif /* TEST_BUILD */ diff --git a/common/lid_switch.c b/common/lid_switch.c index 2528e00092..f0231b1ee7 100644 --- a/common/lid_switch.c +++ b/common/lid_switch.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,17 +16,15 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_SWITCH, outstr) -#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ## args) - -#define LID_DEBOUNCE_US (30 * MSEC) /* Debounce time for lid switch */ +#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ##args) /* if no X-macro is defined for LID switch GPIO, use GPIO_LID_OPEN as default */ #ifndef CONFIG_LID_SWITCH_GPIO_LIST #define CONFIG_LID_SWITCH_GPIO_LIST LID_GPIO(GPIO_LID_OPEN) #endif -static int debounced_lid_open; /* Debounced lid state */ -static int forced_lid_open; /* Forced lid open */ +static int debounced_lid_open; /* Debounced lid state */ +static int forced_lid_open; /* Forced lid open */ /** * Get raw lid switch state. @@ -89,7 +87,7 @@ static void lid_init(void) if (raw_lid_open()) debounced_lid_open = 1; - /* Enable interrupts, now that we've initialized */ + /* Enable interrupts, now that we've initialized */ #define LID_GPIO(gpio) gpio_enable_interrupt(gpio); CONFIG_LID_SWITCH_GPIO_LIST #undef LID_GPIO @@ -120,33 +118,42 @@ void lid_interrupt(enum gpio_signal signal) hook_call_deferred(&lid_change_deferred_data, LID_DEBOUNCE_US); } -static int command_lidopen(int argc, char **argv) +void enable_lid_detect(bool enable) +{ + CPRINTS("lid detect %sabled", enable ? "en" : "dis"); + if (enable) { +#define LID_GPIO(gpio) gpio_enable_interrupt(gpio); + CONFIG_LID_SWITCH_GPIO_LIST +#undef LID_GPIO + } else { +#define LID_GPIO(gpio) gpio_disable_interrupt(gpio); + CONFIG_LID_SWITCH_GPIO_LIST +#undef LID_GPIO + lid_switch_open(); + } +} + +static int command_lidopen(int argc, const char **argv) { lid_switch_open(); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(lidopen, command_lidopen, - NULL, - "Simulate lid open"); +DECLARE_CONSOLE_COMMAND(lidopen, command_lidopen, NULL, "Simulate lid open"); -static int command_lidclose(int argc, char **argv) +static int command_lidclose(int argc, const char **argv) { lid_switch_close(); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(lidclose, command_lidclose, - NULL, - "Simulate lid close"); +DECLARE_CONSOLE_COMMAND(lidclose, command_lidclose, NULL, "Simulate lid close"); -static int command_lidstate(int argc, char **argv) +static int command_lidstate(int argc, const char **argv) { ccprintf("lid state: %s\n", debounced_lid_open ? "open" : "closed"); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(lidstate, command_lidstate, - NULL, - "Get state of lid"); +DECLARE_CONSOLE_COMMAND(lidstate, command_lidstate, NULL, "Get state of lid"); /** * Host command to enable/disable lid opened. @@ -154,14 +161,15 @@ DECLARE_CONSOLE_COMMAND(lidstate, command_lidstate, static enum ec_status hc_force_lid_open(struct host_cmd_handler_args *args) { const struct ec_params_force_lid_open *p = args->params; + int old_state = forced_lid_open; /* Override lid open if necessary */ forced_lid_open = p->enabled ? 1 : 0; /* Make this take effect immediately; no debounce time */ - hook_call_deferred(&lid_change_deferred_data, 0); + if (forced_lid_open != old_state) + hook_call_deferred(&lid_change_deferred_data, 0); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_FORCE_LID_OPEN, hc_force_lid_open, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_FORCE_LID_OPEN, hc_force_lid_open, EC_VER_MASK(0)); diff --git a/common/lightbar.c b/common/lightbar.c index 03b6fe5ca1..fbc16c80d9 100644 --- a/common/lightbar.c +++ b/common/lightbar.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Chromium OS Authors. All rights reserved. + * Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -17,8 +17,8 @@ #include "hooks.h" #include "host_command.h" #include "lb_common.h" -#include "lightbar.h" #include "lid_switch.h" +#include "lightbar.h" #include "motion_sense.h" #include "pwm.h" #include "system.h" @@ -33,11 +33,11 @@ * optional features in the current version should be marked with flags. */ #define LIGHTBAR_IMPLEMENTATION_VERSION 1 -#define LIGHTBAR_IMPLEMENTATION_FLAGS 0 +#define LIGHTBAR_IMPLEMENTATION_FLAGS 0 /* Console output macros */ #define CPUTS(outstr) cputs(CC_LIGHTBAR, outstr) -#define CPRINTS(format, args...) cprints(CC_LIGHTBAR, format, ## args) +#define CPRINTS(format, args...) cprints(CC_LIGHTBAR, format, ##args) #define FP_SCALE 10000 @@ -61,10 +61,10 @@ static struct p_state { int battery_is_power_on_prevented; /* Pattern variables for state S0. */ - uint16_t w0; /* primary phase */ - uint8_t ramp; /* ramp-in for S3->S0 */ + uint16_t w0; /* primary phase */ + uint8_t ramp; /* ramp-in for S3->S0 */ - uint8_t _pad0; /* next item is __packed */ + uint8_t _pad0; /* next item is __packed */ /* Tweakable parameters. */ union { @@ -162,7 +162,7 @@ static const struct lightbar_params_v1 default_params = { }, }; -#define LB_SYSJUMP_TAG 0x4c42 /* "LB" */ +#define LB_SYSJUMP_TAG 0x4c42 /* "LB" */ static void lightbar_preserve_state(void) { system_add_jump_tag(LB_SYSJUMP_TAG, 0, sizeof(st), &st); @@ -177,10 +177,8 @@ static void lightbar_restore_state(void) old_state = system_get_jump_tag(LB_SYSJUMP_TAG, 0, &size); if (old_state && size == sizeof(st)) { memcpy(&st, old_state, size); - CPRINTS("LB state restored: %d %d - %d %d/%d", - st.cur_seq, st.prev_seq, - st.battery_is_charging, - st.battery_percent, + CPRINTS("LB state restored: %d %d - %d %d/%d", st.cur_seq, + st.prev_seq, st.battery_is_charging, st.battery_percent, st.battery_level); } else { st.cur_seq = st.prev_seq = LIGHTBAR_S5; @@ -234,7 +232,7 @@ test_export_static int lux_level_to_google_color(const int lux) } /* See if we need to decrease brightness */ - for (i = google_color_id; i < lb_brightness_levels_count ; i++) + for (i = google_color_id; i < lb_brightness_levels_count; i++) if (lux >= lb_brightness_levels[i].lux_down) break; if (i > google_color_id) { @@ -242,7 +240,7 @@ test_export_static int lux_level_to_google_color(const int lux) return 1; } /* See if we need to increase brightness */ - for (i = google_color_id; i > 0; i--) + for (i = google_color_id; i > 0; i--) if (lux < lb_brightness_levels[i - 1].lux_up) break; if (i < google_color_id) { @@ -267,7 +265,7 @@ static int get_battery_level(void) #ifdef HAS_TASK_CHARGER st.battery_percent = pct = charge_get_percent(); - st.battery_is_charging = (PWR_STATE_DISCHARGE != charge_get_state()); + st.battery_is_charging = (LED_PWRS_DISCHARGE != led_pwr_get_state()); st.battery_is_power_on_prevented = charge_prevent_power_on(0); #endif @@ -276,8 +274,8 @@ static int get_battery_level(void) /* Use some hysteresis to avoid flickering */ if (bl < st.battery_level || - (bl > st.battery_level - && pct >= (st.p.battery_threshold[st.battery_level] + 1))) { + (bl > st.battery_level && + pct >= (st.p.battery_threshold[st.battery_level] + 1))) { st.battery_level = bl; change = 1; } @@ -294,7 +292,7 @@ static int get_battery_level(void) */ if (pwm_get_enabled(PWM_CH_KBLIGHT)) { pct = pwm_get_duty(PWM_CH_KBLIGHT); - pct = (255 * pct) / 100; /* 00 - FF */ + pct = (255 * pct) / 100; /* 00 - FF */ if (pct > st.p.bright_bl_on_max[st.battery_is_charging]) pct = st.p.bright_bl_on_max[st.battery_is_charging]; else if (pct < st.p.bright_bl_on_min[st.battery_is_charging]) @@ -350,8 +348,7 @@ void demo_is_charging(int ischarge) return; st.battery_is_charging = ischarge; - CPRINTS("LB demo: battery_is_charging=%d", - st.battery_is_charging); + CPRINTS("LB demo: battery_is_charging=%d", st.battery_is_charging); } /* Bright/Dim keys */ @@ -409,7 +406,7 @@ static inline int cycle_010(uint8_t i) index = i & 0x3; return _ramp_table[bucket] + - ((_ramp_table[bucket + 1] - _ramp_table[bucket]) * index >> 2); + ((_ramp_table[bucket + 1] - _ramp_table[bucket]) * index >> 2); } /******************************************************************************/ @@ -421,12 +418,12 @@ static uint32_t pending_msg; #define PENDING_MSG TASK_EVENT_CUSTOM_BIT(0) /* Interruptible delay. */ -#define WAIT_OR_RET(A) \ - do { \ - uint32_t msg = task_wait_event(A); \ - uint32_t p_msg = pending_msg; \ - if (msg & PENDING_MSG && p_msg != st.cur_seq) \ - return p_msg; \ +#define WAIT_OR_RET(A) \ + do { \ + uint32_t msg = task_wait_event(A); \ + uint32_t p_msg = pending_msg; \ + if (msg & PENDING_MSG && p_msg != st.cur_seq) \ + return p_msg; \ } while (0) /******************************************************************************/ @@ -501,7 +498,7 @@ static uint32_t sequence_S3S0(void) } /* Initial conditions */ - st.w0 = -256; /* start cycle_npn() quietly */ + st.w0 = -256; /* start cycle_npn() quietly */ st.ramp = 0; /* Ready for S0 */ @@ -583,7 +580,7 @@ static uint32_t sequence_S0(void) return 0; } -#else /* just simple google colors */ +#else /* just simple google colors */ static uint32_t sequence_S0(void) { @@ -711,7 +708,6 @@ static uint32_t sequence_S3(void) return 0; } - /* CPU is powering up. We generally boot fast enough that we don't have time * to do anything interesting in the S3 state, but go straight on to S0. */ static uint32_t sequence_S5S3(void) @@ -817,12 +813,10 @@ static uint32_t sequence_STOP(void) do { msg = task_wait_event(-1); CPRINTS("LB %s() got pending_msg %d", __func__, pending_msg); - } while (msg != PENDING_MSG || ( - pending_msg != LIGHTBAR_RUN && - pending_msg != LIGHTBAR_S0S3 && - pending_msg != LIGHTBAR_S3 && - pending_msg != LIGHTBAR_S3S5 && - pending_msg != LIGHTBAR_S5)); + } while (msg != PENDING_MSG || + (pending_msg != LIGHTBAR_RUN && pending_msg != LIGHTBAR_S0S3 && + pending_msg != LIGHTBAR_S3 && pending_msg != LIGHTBAR_S3S5 && + pending_msg != LIGHTBAR_S5)); return 0; } @@ -856,73 +850,47 @@ static const struct { unsigned int delay; } konami[] = { - {1, 0xff, 0xff, 0x00, 0}, - {2, 0xff, 0xff, 0x00, 100000}, - {1, 0x00, 0x00, 0x00, 0}, - {2, 0x00, 0x00, 0x00, 100000}, - - {1, 0xff, 0xff, 0x00, 0}, - {2, 0xff, 0xff, 0x00, 100000}, - {1, 0x00, 0x00, 0x00, 0}, - {2, 0x00, 0x00, 0x00, 100000}, - - {0, 0x00, 0x00, 0xff, 0}, - {3, 0x00, 0x00, 0xff, 100000}, - {0, 0x00, 0x00, 0x00, 0}, - {3, 0x00, 0x00, 0x00, 100000}, - - {0, 0x00, 0x00, 0xff, 0}, - {3, 0x00, 0x00, 0xff, 100000}, - {0, 0x00, 0x00, 0x00, 0}, - {3, 0x00, 0x00, 0x00, 100000}, - - {0, 0xff, 0x00, 0x00, 0}, - {1, 0xff, 0x00, 0x00, 100000}, - {0, 0x00, 0x00, 0x00, 0}, - {1, 0x00, 0x00, 0x00, 100000}, - - {2, 0x00, 0xff, 0x00, 0}, - {3, 0x00, 0xff, 0x00, 100000}, - {2, 0x00, 0x00, 0x00, 0}, - {3, 0x00, 0x00, 0x00, 100000}, - - {0, 0xff, 0x00, 0x00, 0}, - {1, 0xff, 0x00, 0x00, 100000}, - {0, 0x00, 0x00, 0x00, 0}, - {1, 0x00, 0x00, 0x00, 100000}, - - {2, 0x00, 0xff, 0x00, 0}, - {3, 0x00, 0xff, 0x00, 100000}, - {2, 0x00, 0x00, 0x00, 0}, - {3, 0x00, 0x00, 0x00, 100000}, - - {0, 0x00, 0xff, 0xff, 0}, - {2, 0x00, 0xff, 0xff, 100000}, - {0, 0x00, 0x00, 0x00, 0}, - {2, 0x00, 0x00, 0x00, 150000}, - - {1, 0xff, 0x00, 0xff, 0}, - {3, 0xff, 0x00, 0xff, 100000}, - {1, 0x00, 0x00, 0x00, 0}, - {3, 0x00, 0x00, 0x00, 250000}, - - {4, 0xff, 0xff, 0xff, 100000}, - {4, 0x00, 0x00, 0x00, 100000}, - - {4, 0xff, 0xff, 0xff, 100000}, - {4, 0x00, 0x00, 0x00, 100000}, - - {4, 0xff, 0xff, 0xff, 100000}, - {4, 0x00, 0x00, 0x00, 100000}, - - {4, 0xff, 0xff, 0xff, 100000}, - {4, 0x00, 0x00, 0x00, 100000}, - - {4, 0xff, 0xff, 0xff, 100000}, - {4, 0x00, 0x00, 0x00, 100000}, - - {4, 0xff, 0xff, 0xff, 100000}, - {4, 0x00, 0x00, 0x00, 100000}, + { 1, 0xff, 0xff, 0x00, 0 }, { 2, 0xff, 0xff, 0x00, 100000 }, + { 1, 0x00, 0x00, 0x00, 0 }, { 2, 0x00, 0x00, 0x00, 100000 }, + + { 1, 0xff, 0xff, 0x00, 0 }, { 2, 0xff, 0xff, 0x00, 100000 }, + { 1, 0x00, 0x00, 0x00, 0 }, { 2, 0x00, 0x00, 0x00, 100000 }, + + { 0, 0x00, 0x00, 0xff, 0 }, { 3, 0x00, 0x00, 0xff, 100000 }, + { 0, 0x00, 0x00, 0x00, 0 }, { 3, 0x00, 0x00, 0x00, 100000 }, + + { 0, 0x00, 0x00, 0xff, 0 }, { 3, 0x00, 0x00, 0xff, 100000 }, + { 0, 0x00, 0x00, 0x00, 0 }, { 3, 0x00, 0x00, 0x00, 100000 }, + + { 0, 0xff, 0x00, 0x00, 0 }, { 1, 0xff, 0x00, 0x00, 100000 }, + { 0, 0x00, 0x00, 0x00, 0 }, { 1, 0x00, 0x00, 0x00, 100000 }, + + { 2, 0x00, 0xff, 0x00, 0 }, { 3, 0x00, 0xff, 0x00, 100000 }, + { 2, 0x00, 0x00, 0x00, 0 }, { 3, 0x00, 0x00, 0x00, 100000 }, + + { 0, 0xff, 0x00, 0x00, 0 }, { 1, 0xff, 0x00, 0x00, 100000 }, + { 0, 0x00, 0x00, 0x00, 0 }, { 1, 0x00, 0x00, 0x00, 100000 }, + + { 2, 0x00, 0xff, 0x00, 0 }, { 3, 0x00, 0xff, 0x00, 100000 }, + { 2, 0x00, 0x00, 0x00, 0 }, { 3, 0x00, 0x00, 0x00, 100000 }, + + { 0, 0x00, 0xff, 0xff, 0 }, { 2, 0x00, 0xff, 0xff, 100000 }, + { 0, 0x00, 0x00, 0x00, 0 }, { 2, 0x00, 0x00, 0x00, 150000 }, + + { 1, 0xff, 0x00, 0xff, 0 }, { 3, 0xff, 0x00, 0xff, 100000 }, + { 1, 0x00, 0x00, 0x00, 0 }, { 3, 0x00, 0x00, 0x00, 250000 }, + + { 4, 0xff, 0xff, 0xff, 100000 }, { 4, 0x00, 0x00, 0x00, 100000 }, + + { 4, 0xff, 0xff, 0xff, 100000 }, { 4, 0x00, 0x00, 0x00, 100000 }, + + { 4, 0xff, 0xff, 0xff, 100000 }, { 4, 0x00, 0x00, 0x00, 100000 }, + + { 4, 0xff, 0xff, 0xff, 100000 }, { 4, 0x00, 0x00, 0x00, 100000 }, + + { 4, 0xff, 0xff, 0xff, 100000 }, { 4, 0x00, 0x00, 0x00, 100000 }, + + { 4, 0xff, 0xff, 0xff, 100000 }, { 4, 0x00, 0x00, 0x00, 100000 }, }; static uint32_t sequence_KONAMI_inner(void) @@ -930,8 +898,8 @@ static uint32_t sequence_KONAMI_inner(void) int i; for (i = 0; i < ARRAY_SIZE(konami); i++) { - lb_set_rgb(konami[i].led, - konami[i].r, konami[i].g, konami[i].b); + lb_set_rgb(konami[i].led, konami[i].r, konami[i].g, + konami[i].b); if (konami[i].delay) WAIT_OR_RET(konami[i].delay); } @@ -961,7 +929,7 @@ static int range(int val, int min, int ofs) { if (val <= min) return 0; - if (val >= min+ofs) + if (val >= min + ofs) return FP_SCALE; return (val - min) * FP_SCALE / ofs; } @@ -977,7 +945,7 @@ static uint32_t sequence_TAP_inner(int dir) uint32_t elapsed_time = 0; int i, l, ci, max_led; int f_osc, f_mult; - int gi, gr, gate[NUM_LEDS] = {0, 0, 0, 0}; + int gi, gr, gate[NUM_LEDS] = { 0, 0, 0, 0 }; uint8_t w = 0; #ifdef CONFIG_LIGHTBAR_TAP_DIM_LAST_SEGMENT int f_min, f_delta, f_power; @@ -1010,7 +978,6 @@ static uint32_t sequence_TAP_inner(int dir) gate[gi - 1] = FP_SCALE; for (i = 0; i < NUM_LEDS; i++) { - #ifdef CONFIG_LIGHTBAR_TAP_DIM_LAST_SEGMENT if (max_led > i) { f_mult = FP_SCALE; @@ -1019,7 +986,8 @@ static uint32_t sequence_TAP_inner(int dir) } else { switch (base_color) { case RED: - f_power = range(st.battery_percent, 0, + f_power = range( + st.battery_percent, 0, st.p.battery_threshold[0] - 1); break; case YELLOW: @@ -1174,9 +1142,9 @@ static inline uint32_t decode_32(uint32_t *dest) CPRINTS("pc 0x%02x near or out of bounds", pc); return EC_RES_INVALID_PARAM; } - *dest = cur_prog.data[pc++] << 24; + *dest = cur_prog.data[pc++] << 24; *dest |= cur_prog.data[pc++] << 16; - *dest |= cur_prog.data[pc++] << 8; + *dest |= cur_prog.data[pc++] << 8; *dest |= cur_prog.data[pc++]; return EC_SUCCESS; } @@ -1307,7 +1275,6 @@ static uint32_t lightbyte_SET_BRIGHTNESS(void) */ static uint32_t lightbyte_SET_COLOR_SINGLE(void) { - uint8_t packed_loc, led, control, color, value; int i; if (decode_8(&packed_loc) != EC_SUCCESS) @@ -1369,8 +1336,8 @@ static uint32_t lightbyte_GET_COLORS(void) int i; for (i = 0; i < NUM_LEDS; i++) lb_get_rgb(i, &led_desc[i][LB_CONT_COLOR0][LB_COL_RED], - &led_desc[i][LB_CONT_COLOR0][LB_COL_GREEN], - &led_desc[i][LB_CONT_COLOR0][LB_COL_BLUE]); + &led_desc[i][LB_CONT_COLOR0][LB_COL_GREEN], + &led_desc[i][LB_CONT_COLOR0][LB_COL_BLUE]); return EC_SUCCESS; } @@ -1481,15 +1448,21 @@ static uint32_t lightbyte_CYCLE(void) for (w = 0;; w++) { for (i = 0; i < NUM_LEDS; i++) { - r = get_interp_value(i, LB_COL_RED, - cycle_010((w & 0xff) + - led_desc[i][LB_CONT_PHASE][LB_COL_RED])); - g = get_interp_value(i, LB_COL_GREEN, + r = get_interp_value( + i, LB_COL_RED, + cycle_010( + (w & 0xff) + + led_desc[i][LB_CONT_PHASE][LB_COL_RED])); + g = get_interp_value( + i, LB_COL_GREEN, cycle_010((w & 0xff) + - led_desc[i][LB_CONT_PHASE][LB_COL_GREEN])); - b = get_interp_value(i, LB_COL_BLUE, + led_desc[i][LB_CONT_PHASE] + [LB_COL_GREEN])); + b = get_interp_value( + i, LB_COL_BLUE, cycle_010((w & 0xff) + - led_desc[i][LB_CONT_PHASE][LB_COL_BLUE])); + led_desc[i][LB_CONT_PHASE] + [LB_COL_BLUE])); lb_set_rgb(i, r, g, b); } WAIT_OR_RET(lb_ramp_delay); @@ -1509,24 +1482,17 @@ static uint32_t lightbyte_HALT(void) #define OP(NAME, BYTES, MNEMONIC) NAME, #include "lightbar_opcode_list.h" -enum lightbyte_opcode { - LIGHTBAR_OPCODE_TABLE - MAX_OPCODE -}; +enum lightbyte_opcode { LIGHTBAR_OPCODE_TABLE MAX_OPCODE }; #undef OP -#define OP(NAME, BYTES, MNEMONIC) lightbyte_ ## NAME, +#define OP(NAME, BYTES, MNEMONIC) lightbyte_##NAME, #include "lightbar_opcode_list.h" -static uint32_t (*lightbyte_dispatch[])(void) = { - LIGHTBAR_OPCODE_TABLE -}; +static uint32_t (*lightbyte_dispatch[])(void) = { LIGHTBAR_OPCODE_TABLE }; #undef OP #define OP(NAME, BYTES, MNEMONIC) MNEMONIC, #include "lightbar_opcode_list.h" -static const char * const lightbyte_names[] = { - LIGHTBAR_OPCODE_TABLE -}; +static const char *const lightbyte_names[] = { LIGHTBAR_OPCODE_TABLE }; #undef OP static uint32_t sequence_PROGRAM(void) @@ -1563,7 +1529,7 @@ static uint32_t sequence_PROGRAM(void) return EC_RES_INVALID_PARAM; } else { CPRINTS("LB PROGRAM pc: 0x%02x, opcode 0x%02x -> %s", - old_pc, next_inst, lightbyte_names[next_inst]); + old_pc, next_inst, lightbyte_names[next_inst]); rc = lightbyte_dispatch[next_inst](); if (rc) { lb_set_brightness(saved_brightness); @@ -1588,15 +1554,16 @@ static inline int is_normal_sequence(enum lightbar_sequence seq) /* Link each sequence with a command to invoke it. */ struct lightbar_cmd_t { - const char * const string; + const char *const string; uint32_t (*sequence)(void); }; -#define LBMSG(state) { #state, sequence_##state } +#define LBMSG(state) \ + { \ + #state, sequence_##state \ + } #include "lightbar_msg_list.h" -static struct lightbar_cmd_t lightbar_cmds[] = { - LIGHTBAR_MSG_LIST -}; +static struct lightbar_cmd_t lightbar_cmds[] = { LIGHTBAR_MSG_LIST }; #undef LBMSG void lightbar_task(void) @@ -1608,9 +1575,9 @@ void lightbar_task(void) lightbar_restore_state(); while (1) { - CPRINTS("LB running cur_seq %d %s. prev_seq %d %s", - st.cur_seq, lightbar_cmds[st.cur_seq].string, - st.prev_seq, lightbar_cmds[st.prev_seq].string); + CPRINTS("LB running cur_seq %d %s. prev_seq %d %s", st.cur_seq, + lightbar_cmds[st.cur_seq].string, st.prev_seq, + lightbar_cmds[st.prev_seq].string); next_seq = lightbar_cmds[st.cur_seq].sequence(); if (next_seq) { CPRINTS("LB cur_seq %d %s returned pending msg %d %s", @@ -1622,8 +1589,8 @@ void lightbar_task(void) st.cur_seq = next_seq; } } else { - CPRINTS("LB cur_seq %d %s returned value 0", - st.cur_seq, lightbar_cmds[st.cur_seq].string); + CPRINTS("LB cur_seq %d %s returned value 0", st.cur_seq, + lightbar_cmds[st.cur_seq].string); switch (st.cur_seq) { case LIGHTBAR_S5S3: st.cur_seq = LIGHTBAR_S3; @@ -1644,6 +1611,7 @@ void lightbar_task(void) case LIGHTBAR_TAP: case LIGHTBAR_PROGRAM: st.cur_seq = st.prev_seq; + break; default: break; } @@ -1658,7 +1626,7 @@ void lightbar_sequence_f(enum lightbar_sequence num, const char *f) CPRINTS("LB %s() requests %d %s", f, num, lightbar_cmds[num].string); pending_msg = num; - task_set_event(TASK_ID_LIGHTBAR, PENDING_MSG, 0); + task_set_event(TASK_ID_LIGHTBAR, PENDING_MSG); } else CPRINTS("LB %s() requests %d - ignored", f, num); } @@ -1733,16 +1701,12 @@ static enum ec_status lpc_cmd_lightbar(struct host_cmd_handler_args *args) lb_hc_cmd_reg(in); break; case LIGHTBAR_CMD_SET_RGB: - lb_set_rgb(in->set_rgb.led, - in->set_rgb.red, - in->set_rgb.green, + lb_set_rgb(in->set_rgb.led, in->set_rgb.red, in->set_rgb.green, in->set_rgb.blue); break; case LIGHTBAR_CMD_GET_RGB: - rv = lb_get_rgb(in->get_rgb.led, - &out->get_rgb.red, - &out->get_rgb.green, - &out->get_rgb.blue); + rv = lb_get_rgb(in->get_rgb.led, &out->get_rgb.red, + &out->get_rgb.green, &out->get_rgb.blue); if (rv == EC_RES_SUCCESS) args->response_size = sizeof(out->get_rgb); return rv; @@ -1777,8 +1741,7 @@ static enum ec_status lpc_cmd_lightbar(struct host_cmd_handler_args *args) break; case LIGHTBAR_CMD_SET_PROGRAM: CPRINTS("LB_set_program"); - memcpy(&next_prog, - &in->set_program, + memcpy(&next_prog, &in->set_program, sizeof(struct lightbar_program)); break; case LIGHTBAR_CMD_VERSION: @@ -1801,28 +1764,24 @@ static enum ec_status lpc_cmd_lightbar(struct host_cmd_handler_args *args) break; case LIGHTBAR_CMD_GET_PARAMS_V2_TIMING: CPRINTS("LB_get_params_v2_timing"); - memcpy(&out->get_params_v2_timing, - &st.p_v2.timing, + memcpy(&out->get_params_v2_timing, &st.p_v2.timing, sizeof(st.p_v2.timing)); args->response_size = sizeof(out->get_params_v2_timing); break; case LIGHTBAR_CMD_SET_PARAMS_V2_TIMING: CPRINTS("LB_set_params_v2_timing"); - memcpy(&st.p_v2.timing, - &in->set_v2par_timing, + memcpy(&st.p_v2.timing, &in->set_v2par_timing, sizeof(struct lightbar_params_v2_timing)); break; case LIGHTBAR_CMD_GET_PARAMS_V2_TAP: CPRINTS("LB_get_params_v2_tap"); - memcpy(&out->get_params_v2_tap, - &st.p_v2.tap, + memcpy(&out->get_params_v2_tap, &st.p_v2.tap, sizeof(struct lightbar_params_v2_tap)); args->response_size = sizeof(out->get_params_v2_tap); break; case LIGHTBAR_CMD_SET_PARAMS_V2_TAP: CPRINTS("LB_set_params_v2_tap"); - memcpy(&st.p_v2.tap, - &in->set_v2par_tap, + memcpy(&st.p_v2.tap, &in->set_v2par_tap, sizeof(struct lightbar_params_v2_tap)); break; case LIGHTBAR_CMD_GET_PARAMS_V2_OSCILLATION: @@ -1833,47 +1792,40 @@ static enum ec_status lpc_cmd_lightbar(struct host_cmd_handler_args *args) break; case LIGHTBAR_CMD_SET_PARAMS_V2_OSCILLATION: CPRINTS("LB_set_params_v2_oscillation"); - memcpy(&st.p_v2.osc, - &in->set_v2par_osc, + memcpy(&st.p_v2.osc, &in->set_v2par_osc, sizeof(struct lightbar_params_v2_oscillation)); break; case LIGHTBAR_CMD_GET_PARAMS_V2_BRIGHTNESS: CPRINTS("LB_get_params_v2_brightness"); - memcpy(&out->get_params_v2_bright, - &st.p_v2.bright, + memcpy(&out->get_params_v2_bright, &st.p_v2.bright, sizeof(struct lightbar_params_v2_brightness)); args->response_size = sizeof(out->get_params_v2_bright); break; case LIGHTBAR_CMD_SET_PARAMS_V2_BRIGHTNESS: CPRINTS("LB_set_params_v2_brightness"); - memcpy(&st.p_v2.bright, - &in->set_v2par_bright, + memcpy(&st.p_v2.bright, &in->set_v2par_bright, sizeof(struct lightbar_params_v2_brightness)); break; case LIGHTBAR_CMD_GET_PARAMS_V2_THRESHOLDS: CPRINTS("LB_get_params_v2_thlds"); - memcpy(&out->get_params_v2_thlds, - &st.p_v2.thlds, + memcpy(&out->get_params_v2_thlds, &st.p_v2.thlds, sizeof(struct lightbar_params_v2_thresholds)); args->response_size = sizeof(out->get_params_v2_thlds); break; case LIGHTBAR_CMD_SET_PARAMS_V2_THRESHOLDS: CPRINTS("LB_set_params_v2_thlds"); - memcpy(&st.p_v2.thlds, - &in->set_v2par_thlds, + memcpy(&st.p_v2.thlds, &in->set_v2par_thlds, sizeof(struct lightbar_params_v2_thresholds)); break; case LIGHTBAR_CMD_GET_PARAMS_V2_COLORS: CPRINTS("LB_get_params_v2_colors"); - memcpy(&out->get_params_v2_colors, - &st.p_v2.colors, + memcpy(&out->get_params_v2_colors, &st.p_v2.colors, sizeof(struct lightbar_params_v2_colors)); args->response_size = sizeof(out->get_params_v2_colors); break; case LIGHTBAR_CMD_SET_PARAMS_V2_COLORS: CPRINTS("LB_set_params_v2_colors"); - memcpy(&st.p_v2.colors, - &in->set_v2par_colors, + memcpy(&st.p_v2.colors, &in->set_v2par_colors, sizeof(struct lightbar_params_v2_colors)); break; default: @@ -1884,9 +1836,7 @@ static enum ec_status lpc_cmd_lightbar(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_LIGHTBAR_CMD, - lpc_cmd_lightbar, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_LIGHTBAR_CMD, lpc_cmd_lightbar, EC_VER_MASK(0)); /****************************************************************************/ /* EC console commands */ @@ -1902,10 +1852,12 @@ static int help(const char *cmd) ccprintf(" %s init - load default vals\n", cmd); ccprintf(" %s brightness [NUM] - set intensity (0-ff)\n", cmd); ccprintf(" %s seq [NUM|SEQUENCE] - run given pattern" - " (no arg for list)\n", cmd); + " (no arg for list)\n", + cmd); ccprintf(" %s CTRL REG VAL - set LED controller regs\n", cmd); ccprintf(" %s LED RED GREEN BLUE - set color manually" - " (LED=%d for all)\n", cmd, NUM_LEDS); + " (LED=%d for all)\n", + cmd, NUM_LEDS); ccprintf(" %s LED - get current LED color\n", cmd); ccprintf(" %s demo [0|1] - turn demo mode on & off\n", cmd); #ifdef LIGHTBAR_SIMULATION @@ -1936,19 +1888,18 @@ static void show_msg_names(void) lightbar_cmds[st.cur_seq].string); } -static int command_lightbar(int argc, char **argv) +static int command_lightbar(int argc, const char **argv) { int i; uint8_t num, led, r = 0, g = 0, b = 0; struct ec_response_lightbar out; char *e; - if (argc == 1) { /* no args = dump 'em all */ + if (argc == 1) { /* no args = dump 'em all */ lb_hc_cmd_dump(&out); for (i = 0; i < ARRAY_SIZE(out.dump.vals); i++) ccprintf(" %02x %02x %02x\n", - out.dump.vals[i].reg, - out.dump.vals[i].ic0, + out.dump.vals[i].reg, out.dump.vals[i].ic0, out.dump.vals[i].ic1); return EC_SUCCESS; @@ -1987,8 +1938,7 @@ static int command_lightbar(int argc, char **argv) if (!strcasecmp(argv[1], "demo")) { if (argc > 2) { - if (!strcasecmp(argv[2], "on") || - argv[2][0] == '1') + if (!strcasecmp(argv[2], "on") || argv[2][0] == '1') demo_mode = 1; else if (!strcasecmp(argv[2], "off") || argv[2][0] == '0') @@ -2010,7 +1960,7 @@ static int command_lightbar(int argc, char **argv) num = find_msg_by_name(argv[2]); if (num >= LIGHTBAR_NUM_SEQUENCES) return EC_ERROR_PARAM2; - if (argc > 3) /* for testing TAP direction */ + if (argc > 3) /* for testing TAP direction */ force_dir = strtoi(argv[3], 0, 0); lightbar_sequence(num); return EC_SUCCESS; @@ -2056,13 +2006,11 @@ static int command_lightbar(int argc, char **argv) return EC_SUCCESS; } - #ifdef CONFIG_CONSOLE_CMDHELP help(argv[0]); #endif return EC_ERROR_INVAL; } -DECLARE_CONSOLE_COMMAND(lightbar, command_lightbar, - "[help | COMMAND [ARGS]]", +DECLARE_CONSOLE_COMMAND(lightbar, command_lightbar, "[help | COMMAND [ARGS]]", "Get/set lightbar state"); diff --git a/common/mag_cal.c b/common/mag_cal.c index 13beb93af2..2ad89c48df 100644 --- a/common/mag_cal.c +++ b/common/mag_cal.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,23 +8,22 @@ #include "mag_cal.h" #include "mat33.h" #include "mat44.h" - #include "math.h" #include "math_util.h" #include "util.h" /* Data from sensor is in 16th of uT, 0.0625 uT/LSB */ -#define MAG_CAL_RAW_UT 16 +#define MAG_CAL_RAW_UT 16 -#define MAX_EIGEN_RATIO FLOAT_TO_FP(25.0f) -#define MAX_EIGEN_MAG FLOAT_TO_FP(80.0f * MAG_CAL_RAW_UT) -#define MIN_EIGEN_MAG FLOAT_TO_FP(10.0f * MAG_CAL_RAW_UT) +#define MAX_EIGEN_RATIO FLOAT_TO_FP(25.0f) +#define MAX_EIGEN_MAG FLOAT_TO_FP(80.0f * MAG_CAL_RAW_UT) +#define MIN_EIGEN_MAG FLOAT_TO_FP(10.0f * MAG_CAL_RAW_UT) -#define MAX_FIT_MAG MAX_EIGEN_MAG -#define MIN_FIT_MAG MIN_EIGEN_MAG +#define MAX_FIT_MAG MAX_EIGEN_MAG +#define MIN_FIT_MAG MIN_EIGEN_MAG -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) -#define PRINTF_FLOAT(x) ((int)((x) * 100.0f)) +#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ##args) +#define PRINTF_FLOAT(x) ((int)((x)*100.0f)) /** * Compute the covariance element: (avg(ab) - avg(a)*avg(b)) @@ -51,34 +50,25 @@ static int moc_eigen_test(struct mag_cal_t *moc) mat33_fp_t eigenvecs; fp_t evmax, evmin, evmag; fp_t inv = fp_div_dbz(FLOAT_TO_FP(1.0f), - INT_TO_FP((int) moc->kasa_fit.nsamples)); + INT_TO_FP((int)moc->kasa_fit.nsamples)); int eigen_pass; /* covariance matrix */ - S[0][0] = covariance_element(moc->kasa_fit.acc_xx, - moc->kasa_fit.acc_x, - moc->kasa_fit.acc_x, - inv); + S[0][0] = covariance_element(moc->kasa_fit.acc_xx, moc->kasa_fit.acc_x, + moc->kasa_fit.acc_x, inv); S[0][1] = S[1][0] = covariance_element(moc->kasa_fit.acc_xy, moc->kasa_fit.acc_x, - moc->kasa_fit.acc_y, - inv); + moc->kasa_fit.acc_y, inv); S[0][2] = S[2][0] = covariance_element(moc->kasa_fit.acc_xz, moc->kasa_fit.acc_x, - moc->kasa_fit.acc_z, - inv); - S[1][1] = covariance_element(moc->kasa_fit.acc_yy, - moc->kasa_fit.acc_y, - moc->kasa_fit.acc_y, - inv); + moc->kasa_fit.acc_z, inv); + S[1][1] = covariance_element(moc->kasa_fit.acc_yy, moc->kasa_fit.acc_y, + moc->kasa_fit.acc_y, inv); S[1][2] = S[2][1] = covariance_element(moc->kasa_fit.acc_yz, moc->kasa_fit.acc_y, - moc->kasa_fit.acc_z, - inv); - S[2][2] = covariance_element(moc->kasa_fit.acc_zz, - moc->kasa_fit.acc_z, - moc->kasa_fit.acc_z, - inv); + moc->kasa_fit.acc_z, inv); + S[2][2] = covariance_element(moc->kasa_fit.acc_zz, moc->kasa_fit.acc_z, + moc->kasa_fit.acc_z, inv); mat33_fp_get_eigenbasis(S, eigenvals, eigenvecs); @@ -90,9 +80,8 @@ static int moc_eigen_test(struct mag_cal_t *moc) evmag = fp_sqrtf(eigenvals[X] + eigenvals[Y] + eigenvals[Z]); - eigen_pass = (fp_mul(evmin, MAX_EIGEN_RATIO) > evmax) - && (evmag > MIN_EIGEN_MAG) - && (evmag < MAX_EIGEN_MAG); + eigen_pass = (fp_mul(evmin, MAX_EIGEN_RATIO) > evmax) && + (evmag > MIN_EIGEN_MAG) && (evmag < MAX_EIGEN_MAG); #if 0 CPRINTF("mag eigenvalues: (%.02d %.02d %.02d), ", diff --git a/common/main.c b/common/main.c index e749c3e21f..fde91a2ed3 100644 --- a/common/main.c +++ b/common/main.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -6,24 +6,30 @@ */ #include "board_config.h" +#ifdef CONFIG_KEYBOARD_SCAN_ADC +#include "adc.h" +#endif #include "button.h" #include "chipset.h" #include "clock.h" #include "common.h" #include "console.h" #include "cpu.h" +#include "cros_board_info.h" #include "dma.h" #include "eeprom.h" #include "flash.h" #include "gpio.h" #include "hooks.h" #include "i2c.h" +#include "i2c_bitbang.h" #include "keyboard_scan.h" #include "link_defs.h" #include "lpc.h" #ifdef CONFIG_MPU #include "mpu.h" #endif +#include "panic.h" #include "rwsig.h" #include "system.h" #include "task.h" @@ -35,8 +41,8 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) test_mockable __keep int main(void) { @@ -109,7 +115,7 @@ test_mockable __keep int main(void) * Initialize flash and apply write protect if necessary. Requires * the reset flags calculated by system initialization. */ - flash_pre_init(); + crec_flash_pre_init(); #endif /* Set the CPU clocks / PLLs. System is now running at full speed. */ @@ -124,10 +130,14 @@ test_mockable __keep int main(void) */ timer_init(); + /* Compensate the elapsed time for the RTC. */ + if (IS_ENABLED(CONFIG_HIBERNATE_PSL_COMPENSATE_RTC)) + system_compensate_rtc(); + /* Main initialization stage. Modules may enable interrupts here. */ cpu_init(); -#ifdef CONFIG_DMA +#ifdef CONFIG_DMA_CROS /* Initialize DMA. Must be before UART. */ dma_init(); #endif @@ -139,20 +149,7 @@ test_mockable __keep int main(void) if (mpu_pre_init_rv != EC_SUCCESS) panic("MPU init failed"); - /* be less verbose if we boot for USB resume to meet spec timings */ - if (!(system_get_reset_flags() & EC_RESET_FLAG_USB_RESUME)) { - CPUTS("\n"); - if (system_jumped_to_this_image()) - CPRINTS("UART initialized after sysjump"); - else - CPUTS("\n--- UART initialized after reboot ---\n"); - CPRINTF("[Image: %s, %s]\n", - system_get_image_copy_string(), - system_get_build_info()); - CPUTS("[Reset cause: "); - system_print_reset_flags(); - CPUTS("]\n"); - } + system_print_banner(); #ifdef CONFIG_BRINGUP ccprintf("\n\nWARNING: BRINGUP BUILD\n\n\n"); @@ -179,32 +176,62 @@ test_mockable __keep int main(void) #endif /* - * Keyboard scan init/Button init can set recovery events to - * indicate to host entry into recovery mode. Before this is - * done, lpc always report mask needs to be initialized - * correctly. + * If the EC has exclusive control over the CBI EEPROM WP signal, have + * the EC set the WP if appropriate. Note that once the WP is set, the + * EC must be reset via EC_RST_ODL in order for the WP to become unset. */ + if (IS_ENABLED(CONFIG_EEPROM_CBI_WP) && system_is_locked()) + cbi_latch_eeprom_wp(); + + /* + * Keyboard scan init/Button init can set recovery events to + * indicate to host entry into recovery mode. Before this is + * done, LPC_HOST_EVENT_ALWAYS_REPORT mask needs to be + * initialized correctly. + */ #ifdef CONFIG_HOSTCMD_X86 lpc_init_mask(); #endif - if (IS_ENABLED(CONFIG_I2C_MASTER)) { + if (IS_ENABLED(CONFIG_I2C_CONTROLLER)) { /* * Some devices (like the I2C keyboards, CBI) need I2C access * pretty early, so let's initialize the controller now. */ i2c_init(); + + if (IS_ENABLED(CONFIG_I2C_BITBANG)) { + /* + * Enable I2C raw mode for the ports which need + * pre-task i2c transactions. + */ + enable_i2c_raw_mode(true); + + /* Board level pre-task I2C peripheral initialization */ + board_pre_task_i2c_peripheral_init(); + } } + #ifdef HAS_TASK_KEYSCAN - keyboard_scan_init(); + +#ifdef CONFIG_KEYBOARD_SCAN_ADC + /* + * Initialize adc here as we need to use it during keyboard_scan_init + * to scan boot keys + */ + adc_init(); #endif + + keyboard_scan_init(); +#endif /* HAS_TASK_KEYSCAN */ + #if defined(CONFIG_DEDICATED_RECOVERY_BUTTON) || defined(CONFIG_VOLUME_BUTTONS) button_init(); #endif /* defined(CONFIG_DEDICATED_RECOVERY_BUTTON | CONFIG_VOLUME_BUTTONS) */ /* Make sure recovery boot won't be paused. */ - if (IS_ENABLED(CONFIG_POWER_BUTTON_INIT_IDLE) - && system_is_manual_recovery() - && (system_get_reset_flags() & EC_RESET_FLAG_AP_IDLE)) { + if (IS_ENABLED(CONFIG_POWER_BUTTON_INIT_IDLE) && + system_is_manual_recovery() && + (system_get_reset_flags() & EC_RESET_FLAG_AP_IDLE)) { CPRINTS("Clear AP_IDLE for recovery mode"); system_clear_reset_flags(EC_RESET_FLAG_AP_IDLE); } @@ -244,7 +271,15 @@ test_mockable __keep int main(void) rwsig_jump_now(); } } -#endif /* !CONFIG_VBOOT_EFS && CONFIG_RWSIG && !HAS_TASK_RWSIG */ +#endif /* !CONFIG_VBOOT_EFS && CONFIG_RWSIG && !HAS_TASK_RWSIG */ + + /* + * Disable I2C raw mode for the ports which needed pre-task i2c + * transactions as the task is about to start and the I2C can resume + * to event based transactions. + */ + if (IS_ENABLED(CONFIG_I2C_BITBANG) && IS_ENABLED(CONFIG_I2C_CONTROLLER)) + enable_i2c_raw_mode(false); /* * Print the init time. Not completely accurate because it can't take diff --git a/common/mat33.c b/common/mat33.c index 87e335db26..844fd0b8cc 100644 --- a/common/mat33.c +++ b/common/mat33.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -59,8 +59,7 @@ void mat33_fp_swap_rows(mat33_fp_t A, const size_t i, const size_t j) * The i-th eigenvalue corresponds to the eigenvector in the i-th _row_ of * "eigenvecs". */ -void mat33_fp_get_eigenbasis(mat33_fp_t S, fpv3_t e_vals, - mat33_fp_t e_vecs) +void mat33_fp_get_eigenbasis(mat33_fp_t S, fpv3_t e_vals, mat33_fp_t e_vecs) { const size_t N = 3; sizev3_t ind; @@ -176,8 +175,8 @@ size_t mat33_fp_maxind(mat33_fp_t A, size_t k) return m; } -void mat33_fp_rotate(mat33_fp_t A, fp_t c, fp_t s, - size_t k, size_t l, size_t i, size_t j) +void mat33_fp_rotate(mat33_fp_t A, fp_t c, fp_t s, size_t k, size_t l, size_t i, + size_t j) { fp_t tmp = fp_mul(c, A[k][l]) - fp_mul(s, A[i][j]); A[i][j] = fp_mul(s, A[k][l]) + fp_mul(c, A[i][j]); diff --git a/common/mat44.c b/common/mat44.c index a4232bf8d4..d48ca4f596 100644 --- a/common/mat44.c +++ b/common/mat44.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/common/math_util.c b/common/math_util.c index dc52729c65..4f5eb8b877 100644 --- a/common/math_util.c +++ b/common/math_util.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,18 +11,18 @@ #include "util.h" /* For cosine lookup table, define the increment and the size of the table. */ -#define COSINE_LUT_INCR_DEG 5 -#define COSINE_LUT_SIZE ((180 / COSINE_LUT_INCR_DEG) + 1) +#define COSINE_LUT_INCR_DEG 5 +#define COSINE_LUT_SIZE ((180 / COSINE_LUT_INCR_DEG) + 1) /* Lookup table for the value of cosine from 0 degrees to 180 degrees. */ static const fp_t cos_lut[] = { - FLOAT_TO_FP( 1.00000), FLOAT_TO_FP( 0.99619), FLOAT_TO_FP( 0.98481), - FLOAT_TO_FP( 0.96593), FLOAT_TO_FP( 0.93969), FLOAT_TO_FP( 0.90631), - FLOAT_TO_FP( 0.86603), FLOAT_TO_FP( 0.81915), FLOAT_TO_FP( 0.76604), - FLOAT_TO_FP( 0.70711), FLOAT_TO_FP( 0.64279), FLOAT_TO_FP( 0.57358), - FLOAT_TO_FP( 0.50000), FLOAT_TO_FP( 0.42262), FLOAT_TO_FP( 0.34202), - FLOAT_TO_FP( 0.25882), FLOAT_TO_FP( 0.17365), FLOAT_TO_FP( 0.08716), - FLOAT_TO_FP( 0.00000), FLOAT_TO_FP(-0.08716), FLOAT_TO_FP(-0.17365), + FLOAT_TO_FP(1.00000), FLOAT_TO_FP(0.99619), FLOAT_TO_FP(0.98481), + FLOAT_TO_FP(0.96593), FLOAT_TO_FP(0.93969), FLOAT_TO_FP(0.90631), + FLOAT_TO_FP(0.86603), FLOAT_TO_FP(0.81915), FLOAT_TO_FP(0.76604), + FLOAT_TO_FP(0.70711), FLOAT_TO_FP(0.64279), FLOAT_TO_FP(0.57358), + FLOAT_TO_FP(0.50000), FLOAT_TO_FP(0.42262), FLOAT_TO_FP(0.34202), + FLOAT_TO_FP(0.25882), FLOAT_TO_FP(0.17365), FLOAT_TO_FP(0.08716), + FLOAT_TO_FP(0.00000), FLOAT_TO_FP(-0.08716), FLOAT_TO_FP(-0.17365), FLOAT_TO_FP(-0.25882), FLOAT_TO_FP(-0.34202), FLOAT_TO_FP(-0.42262), FLOAT_TO_FP(-0.50000), FLOAT_TO_FP(-0.57358), FLOAT_TO_FP(-0.64279), FLOAT_TO_FP(-0.70711), FLOAT_TO_FP(-0.76604), FLOAT_TO_FP(-0.81915), @@ -32,7 +32,6 @@ static const fp_t cos_lut[] = { }; BUILD_ASSERT(ARRAY_SIZE(cos_lut) == COSINE_LUT_SIZE); - fp_t arc_cos(fp_t x) { int i; @@ -48,8 +47,8 @@ fp_t arc_cos(fp_t x) * interpolate for precision. */ /* TODO(crosbug.com/p/25600): Optimize with binary search. */ - for (i = 0; i < COSINE_LUT_SIZE-1; i++) { - if (x >= cos_lut[i+1]) { + for (i = 0; i < COSINE_LUT_SIZE - 1; i++) { + if (x >= cos_lut[i + 1]) { const fp_t interp = fp_div(cos_lut[i] - x, cos_lut[i] - cos_lut[i + 1]); @@ -60,12 +59,9 @@ fp_t arc_cos(fp_t x) /* * Shouldn't be possible to get here because inputs are clipped to - * [-1, 1] and the cos_lut[] table goes over the same range. If we - * are here, throw an assert. + * [-1, 1] and the cos_lut[] table goes over the same range. */ - ASSERT(0); - - return 0; + __builtin_unreachable(); /* LCOV_EXCL_LINE */ } /** @@ -79,7 +75,7 @@ fp_t arc_cos(fp_t x) * except when the floating point representation of the square root rounds up * to an integer. */ -static inline int int_sqrtf(fp_inter_t x) +inline int int_sqrtf(fp_inter_t x) { return sqrtf(x); } @@ -90,26 +86,29 @@ fp_t fp_sqrtf(fp_t x) return sqrtf(x); } #else -static int int_sqrtf(fp_inter_t x) +int int_sqrtf(fp_inter_t x) { int rmax = INT32_MAX; int rmin = 0; - /* Short cut if x is 32-bit value */ - if (x < rmax) - rmax = 0x7fff; + /* + * Short cut if x is 32-bit value + * sqrt(INT32_MAX) ~= 46340.95 + */ + if (x < INT32_MAX) + rmax = 46341; /* * Just binary-search. There are better algorithms, but we call this * infrequently enough it doesn't matter. */ if (x <= 0) - return 0; /* Yeah, for imaginary numbers too */ - else if (x > (fp_inter_t)rmax * rmax) + return 0; /* Yeah, for imaginary numbers too */ + else if (x >= (fp_inter_t)rmax * rmax) return rmax; while (1) { - int r = (rmax + rmin) / 2; + int r = rmin + (rmax - rmin) / 2; fp_inter_t r2 = (fp_inter_t)r * r; if (r2 > x) { @@ -138,9 +137,8 @@ fp_t fp_sqrtf(fp_t x) int vector_magnitude(const intv3_t v) { - fp_inter_t sum = (fp_inter_t)v[0] * v[0] + - (fp_inter_t)v[1] * v[1] + - (fp_inter_t)v[2] * v[2]; + fp_inter_t sum = (fp_inter_t)v[0] * v[0] + (fp_inter_t)v[1] * v[1] + + (fp_inter_t)v[2] * v[2]; return int_sqrtf(sum); } @@ -155,8 +153,7 @@ void cross_product(const intv3_t v1, const intv3_t v2, intv3_t v) fp_inter_t dot_product(const intv3_t v1, const intv3_t v2) { - return (fp_inter_t)v1[X] * v2[X] + - (fp_inter_t)v1[Y] * v2[Y] + + return (fp_inter_t)v1[X] * v2[X] + (fp_inter_t)v1[Y] * v2[Y] + (fp_inter_t)v1[Z] * v2[Z]; } @@ -215,17 +212,13 @@ void rotate(const intv3_t v, const mat33_fp_t R, intv3_t res) return; } - /* Rotate */ - t[0] = (fp_inter_t)v[0] * R[0][0] + - (fp_inter_t)v[1] * R[1][0] + - (fp_inter_t)v[2] * R[2][0]; - t[1] = (fp_inter_t)v[0] * R[0][1] + - (fp_inter_t)v[1] * R[1][1] + - (fp_inter_t)v[2] * R[2][1]; - t[2] = (fp_inter_t)v[0] * R[0][2] + - (fp_inter_t)v[1] * R[1][2] + - (fp_inter_t)v[2] * R[2][2]; + t[0] = (fp_inter_t)v[0] * R[0][0] + (fp_inter_t)v[1] * R[1][0] + + (fp_inter_t)v[2] * R[2][0]; + t[1] = (fp_inter_t)v[0] * R[0][1] + (fp_inter_t)v[1] * R[1][1] + + (fp_inter_t)v[2] * R[2][1]; + t[2] = (fp_inter_t)v[0] * R[0][2] + (fp_inter_t)v[1] * R[1][2] + + (fp_inter_t)v[2] * R[2][2]; /* Scale by fixed point shift when writing back to result */ res[0] = FP_TO_INT(t[0]); @@ -244,38 +237,39 @@ void rotate_inv(const intv3_t v, const mat33_fp_t R, intv3_t res) return; } - deter = fp_mul(R[0][0], (fp_mul(R[1][1], R[2][2]) - - fp_mul(R[2][1], R[1][2]))) - - fp_mul(R[0][1], (fp_mul(R[1][0], R[2][2]) - - fp_mul(R[1][2], R[2][0]))) + - fp_mul(R[0][2], (fp_mul(R[1][0], R[2][1]) - - fp_mul(R[1][1], R[2][0]))); + deter = fp_mul(R[0][0], + (fp_mul(R[1][1], R[2][2]) - fp_mul(R[2][1], R[1][2]))) - + fp_mul(R[0][1], + (fp_mul(R[1][0], R[2][2]) - fp_mul(R[1][2], R[2][0]))) + + fp_mul(R[0][2], + (fp_mul(R[1][0], R[2][1]) - fp_mul(R[1][1], R[2][0]))); /* * invert the matrix: from * http://stackoverflow.com/questions/983999/ * simple-3x3-matrix-inverse-code-c */ - t[0] = (fp_inter_t)v[0] * (fp_mul(R[1][1], R[2][2]) - - fp_mul(R[2][1], R[1][2])) - - (fp_inter_t)v[1] * (fp_mul(R[1][0], R[2][2]) - - fp_mul(R[1][2], R[2][0])) + - (fp_inter_t)v[2] * (fp_mul(R[1][0], R[2][1]) - - fp_mul(R[2][0], R[1][1])); - - t[1] = (fp_inter_t)v[0] * (fp_mul(R[0][1], R[2][2]) - - fp_mul(R[0][2], R[2][1])) * -1 + - (fp_inter_t)v[1] * (fp_mul(R[0][0], R[2][2]) - - fp_mul(R[0][2], R[2][0])) - - (fp_inter_t)v[2] * (fp_mul(R[0][0], R[2][1]) - - fp_mul(R[2][0], R[0][1])); - - t[2] = (fp_inter_t)v[0] * (fp_mul(R[0][1], R[1][2]) - - fp_mul(R[0][2], R[1][1])) - - (fp_inter_t)v[1] * (fp_mul(R[0][0], R[1][2]) - - fp_mul(R[1][0], R[0][2])) + - (fp_inter_t)v[2] * (fp_mul(R[0][0], R[1][1]) - - fp_mul(R[1][0], R[0][1])); + t[0] = (fp_inter_t)v[0] * + (fp_mul(R[1][1], R[2][2]) - fp_mul(R[2][1], R[1][2])) - + (fp_inter_t)v[1] * + (fp_mul(R[1][0], R[2][2]) - fp_mul(R[1][2], R[2][0])) + + (fp_inter_t)v[2] * + (fp_mul(R[1][0], R[2][1]) - fp_mul(R[2][0], R[1][1])); + + t[1] = (fp_inter_t)v[0] * + (fp_mul(R[0][1], R[2][2]) - fp_mul(R[0][2], R[2][1])) * + -1 + + (fp_inter_t)v[1] * + (fp_mul(R[0][0], R[2][2]) - fp_mul(R[0][2], R[2][0])) - + (fp_inter_t)v[2] * + (fp_mul(R[0][0], R[2][1]) - fp_mul(R[2][0], R[0][1])); + + t[2] = (fp_inter_t)v[0] * + (fp_mul(R[0][1], R[1][2]) - fp_mul(R[0][2], R[1][1])) - + (fp_inter_t)v[1] * + (fp_mul(R[0][0], R[1][2]) - fp_mul(R[1][0], R[0][2])) + + (fp_inter_t)v[2] * + (fp_mul(R[0][0], R[1][1]) - fp_mul(R[1][0], R[0][1])); /* Scale by fixed point shift when writing back to result */ res[0] = FP_TO_INT(fp_div(t[0], deter)); @@ -287,6 +281,43 @@ void rotate_inv(const intv3_t v, const mat33_fp_t R, intv3_t res) int round_divide(int64_t dividend, int divisor) { return (dividend > 0) ^ (divisor > 0) ? - (dividend - divisor / 2) / divisor : - (dividend + divisor / 2) / divisor; + (dividend - divisor / 2) / divisor : + (dividend + divisor / 2) / divisor; +} + +#if ULONG_MAX == 0xFFFFFFFFUL +/* + * 32 bit processor + * + * Some 32 bit processors do not include a 64 bit shift + * operation. So fall back to 32 bit operations on a + * union. + */ +uint64_t bitmask_uint64(int offset) +{ + union mask64_t { + struct { +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + uint32_t lo; + uint32_t hi; +#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + uint32_t hi; + uint32_t lo; +#endif + }; + uint64_t val; + } mask = { 0 }; + + /* + * If the shift is out of range the result should + * remain 0, otherwise perform the shift + */ + if (offset >= 0 && offset < 64) { + if (offset < 32) + mask.lo = BIT(offset); + else + mask.hi = BIT(offset - 32); + } + return mask.val; } +#endif diff --git a/common/memory_commands.c b/common/memory_commands.c index 98c64d918b..163460a2d1 100644 --- a/common/memory_commands.c +++ b/common/memory_commands.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,7 +10,6 @@ #include "util.h" #include "watchdog.h" - enum format { FMT_WORD, FMT_HALF, @@ -56,7 +55,7 @@ static void show_val(uint32_t address, uint32_t index, enum format fmt) cflush(); } -static int command_mem_dump(int argc, char **argv) +static int command_mem_dump(int argc, const char **argv) { uint32_t address, i, num = 1; char *e; @@ -106,20 +105,19 @@ static int command_mem_dump(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND_FLAGS - (md, command_mem_dump, - "[.b|.h|.s] addr [count]", - "dump memory values, optionally specifying the format", - CMD_FLAG_RESTRICTED); +DECLARE_CONSOLE_COMMAND_FLAGS( + md, command_mem_dump, "[.b|.h|.s] addr [count]", + "dump memory values, optionally specifying the format", + CMD_FLAG_RESTRICTED); #endif /* CONFIG_CMD_MD */ #ifdef CONFIG_CMD_RW -static int command_read_word(int argc, char **argv) +static int command_read_word(int argc, const char **argv) { volatile uint32_t *address; uint32_t value; - unsigned access_size = 4; - unsigned argc_offs = 0; + unsigned int access_size = 4; + unsigned int argc_offs = 0; char *e; if (argc < 2) @@ -149,16 +147,16 @@ static int command_read_word(int argc, char **argv) if ((argc - argc_offs) < 3) { switch (access_size) { case 1: - ccprintf("read 0x%pP = 0x%02x\n", - address, *((uint8_t *)address)); + ccprintf("read 0x%p = 0x%02x\n", address, + *((uint8_t *)address)); break; case 2: - ccprintf("read 0x%pP = 0x%04x\n", - address, *((uint16_t *)address)); + ccprintf("read 0x%p = 0x%04x\n", address, + *((uint16_t *)address)); break; default: - ccprintf("read 0x%pP = 0x%08x\n", address, *address); + ccprintf("read 0x%p = 0x%08x\n", address, *address); break; } return EC_SUCCESS; @@ -171,17 +169,17 @@ static int command_read_word(int argc, char **argv) switch (access_size) { case 1: - ccprintf("write 0x%pP = 0x%02x\n", address, (uint8_t)value); - cflush(); /* Flush before writing in case this crashes */ + ccprintf("write 0x%p = 0x%02x\n", address, (uint8_t)value); + cflush(); /* Flush before writing in case this crashes */ *((uint8_t *)address) = (uint8_t)value; break; case 2: - ccprintf("write 0x%pP = 0x%04x\n", address, (uint16_t)value); + ccprintf("write 0x%p = 0x%04x\n", address, (uint16_t)value); cflush(); *((uint16_t *)address) = (uint16_t)value; break; default: - ccprintf("write 0x%pP = 0x%02x\n", address, value); + ccprintf("write 0x%p = 0x%02x\n", address, value); cflush(); *address = value; break; @@ -190,9 +188,8 @@ static int command_read_word(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND_FLAGS - (rw, command_read_word, - "[.b|.h] addr [value]", - "Read or write a word in memory optionally specifying the size", - CMD_FLAG_RESTRICTED); -#endif /* CONFIG_CMD_RW */ +DECLARE_CONSOLE_COMMAND_FLAGS( + rw, command_read_word, "[.b|.h] addr [value]", + "Read or write a word in memory optionally specifying the size", + CMD_FLAG_RESTRICTED); +#endif /* CONFIG_CMD_RW */ diff --git a/common/mkbp_event.c b/common/mkbp_event.c index f640a9340c..ee706e549a 100644 --- a/common/mkbp_event.c +++ b/common/mkbp_event.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,15 +11,15 @@ #include "host_command.h" #include "host_command_heci.h" #include "hwtimer.h" -#include "timer.h" #include "link_defs.h" #include "mkbp_event.h" #include "power.h" +#include "timer.h" #include "util.h" #define CPUTS(outstr) cputs(CC_COMMAND, outstr) -#define CPRINTS(format, args...) cprints(CC_COMMAND, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_COMMAND, format, ## args) +#define CPRINTS(format, args...) cprints(CC_COMMAND, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_COMMAND, format, ##args) /* * Tracks the current state of the MKBP interrupt send from the EC to the AP. @@ -48,7 +48,7 @@ enum interrupt_state { }; struct mkbp_state { - struct mutex lock; + mutex_t lock; uint32_t events; enum interrupt_state interrupt; /* @@ -68,6 +68,9 @@ struct mkbp_state { static struct mkbp_state state; uint32_t mkbp_last_event_time; +static const int ap_comm_failure_threshold = 2; +static int ap_comm_failure_count; + #ifdef CONFIG_MKBP_EVENT_WAKEUP_MASK static uint32_t mkbp_event_wake_mask = CONFIG_MKBP_EVENT_WAKEUP_MASK; #endif /* CONFIG_MKBP_EVENT_WAKEUP_MASK */ @@ -76,10 +79,21 @@ static uint32_t mkbp_event_wake_mask = CONFIG_MKBP_EVENT_WAKEUP_MASK; static uint32_t mkbp_host_event_wake_mask = CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK; #endif /* CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK */ +#ifdef CONFIG_ZEPHYR +static int init_mkbp_mutex(void) +{ + k_mutex_init(&state.lock); + + return 0; +} +SYS_INIT(init_mkbp_mutex, POST_KERNEL, 50); +#endif /* CONFIG_ZEPHYR */ + #if defined(CONFIG_MKBP_USE_GPIO) || \ defined(CONFIG_MKBP_USE_GPIO_AND_HOST_EVENT) static int mkbp_set_host_active_via_gpio(int active, uint32_t *timestamp) { + uint32_t lock_key; /* * If we want to take a timestamp, then disable interrupts temporarily * to ensure that the timestamp is as close as possible to the setting @@ -87,14 +101,17 @@ static int mkbp_set_host_active_via_gpio(int active, uint32_t *timestamp) * taking the timestamp and setting the gpio) */ if (timestamp) { - interrupt_disable(); + lock_key = irq_lock(); *timestamp = __hw_clock_source_read(); } - gpio_set_level(GPIO_EC_INT_L, !active); + if (IS_ENABLED(CONFIG_MKBP_USE_GPIO_ACTIVE_HIGH)) + gpio_set_level(GPIO_EC_INT_L, active); + else + gpio_set_level(GPIO_EC_INT_L, !active); if (timestamp) - interrupt_enable(); + irq_unlock(lock_key); #ifdef CONFIG_MKBP_USE_GPIO_AND_HOST_EVENT /* @@ -152,7 +169,7 @@ static int mkbp_set_host_active(int active, uint32_t *timestamp) return mkbp_set_host_active_via_custom(active, timestamp); #elif defined(CONFIG_MKBP_USE_HOST_EVENT) return mkbp_set_host_active_via_event(active, timestamp); -#elif defined(CONFIG_MKBP_USE_GPIO) ||\ +#elif defined(CONFIG_MKBP_USE_GPIO) || \ defined(CONFIG_MKBP_USE_GPIO_AND_HOST_EVENT) return mkbp_set_host_active_via_gpio(active, timestamp); #elif defined(CONFIG_MKBP_USE_HECI) @@ -172,10 +189,9 @@ static inline int host_is_sleeping(void) #ifdef CONFIG_POWER_TRACK_HOST_SLEEP_STATE enum host_sleep_event sleep_state = power_get_host_sleep_state(); - is_sleeping |= - (sleep_state == HOST_SLEEP_EVENT_S0IX_SUSPEND || - sleep_state == HOST_SLEEP_EVENT_S3_SUSPEND || - sleep_state == HOST_SLEEP_EVENT_S3_WAKEABLE_SUSPEND); + is_sleeping |= (sleep_state == HOST_SLEEP_EVENT_S0IX_SUSPEND || + sleep_state == HOST_SLEEP_EVENT_S3_SUSPEND || + sleep_state == HOST_SLEEP_EVENT_S3_WAKEABLE_SUSPEND); #endif return is_sleeping; } @@ -184,12 +200,12 @@ static inline int host_is_sleeping(void) /* * This is the deferred function that ensures that we attempt to set the MKBP * interrupt again if there was a failure in the system (EC or AP) and the AP - * never called get_next_event. + * never called mkbp_fifo_get_next_event. */ static void force_mkbp_if_events(void); DECLARE_DEFERRED(force_mkbp_if_events); -static void activate_mkbp_with_events(uint32_t events_to_add) +test_export_static void activate_mkbp_with_events(uint32_t events_to_add) { int interrupt_id = -1; int skip_interrupt = 0; @@ -203,16 +219,16 @@ static void activate_mkbp_with_events(uint32_t events_to_add) */ if (events_to_add == BIT(EC_MKBP_EVENT_HOST_EVENT) || events_to_add == BIT(EC_MKBP_EVENT_HOST_EVENT64)) - skip_interrupt = host_is_sleeping() && - !(host_get_events() & - mkbp_host_event_wake_mask); + skip_interrupt = + host_is_sleeping() && + !(host_get_events() & mkbp_host_event_wake_mask); #endif /* CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK */ #ifdef CONFIG_MKBP_EVENT_WAKEUP_MASK /* Check to see if this MKBP event should wake the system. */ if (!skip_interrupt) skip_interrupt = host_is_sleeping() && - !(events_to_add & mkbp_event_wake_mask); + !(events_to_add & mkbp_event_wake_mask); #endif /* CONFIG_MKBP_EVENT_WAKEUP_MASK */ mutex_lock(&state.lock); @@ -244,8 +260,8 @@ static void activate_mkbp_with_events(uint32_t events_to_add) if (state.interrupt == INTERRUPT_INACTIVE_TO_ACTIVE && interrupt_id == state.interrupt_id) { schedule_deferred = 1; - state.interrupt = rv == EC_SUCCESS ? INTERRUPT_ACTIVE - : INTERRUPT_INACTIVE; + state.interrupt = rv == EC_SUCCESS ? INTERRUPT_ACTIVE : + INTERRUPT_INACTIVE; } mutex_unlock(&state.lock); @@ -259,25 +275,80 @@ static void activate_mkbp_with_events(uint32_t events_to_add) /* * This is the deferred function that ensures that we attempt to set the MKBP * interrupt again if there was a failure in the system (EC or AP) and the AP - * never called get_next_event. + * never called mkbp_fifo_get_next_event. */ static void force_mkbp_if_events(void) { int toggled = 0; + int send_mkbp_interrupt = 0; mutex_lock(&state.lock); - if (state.interrupt == INTERRUPT_ACTIVE) { + if (state.interrupt == INTERRUPT_INACTIVE) { + /* + * When this function is called with state of interrupt set + * to INACTIVE, it means that EC failed to send MKBP interrupt + * to AP. In this case we are going to send interrupt once + * again (without limits). + */ + send_mkbp_interrupt = 1; + } else if (state.interrupt == INTERRUPT_ACTIVE) { + /* + * When this function is called with state of interrupt set + * to ACTIVE, it means that AP failed to respond. + * + * It is safe to mark interrupt state as INACTIVE, because + * force_mkbp_with_events() function can be only scheduled by + * activate_mkbp_with_event() which will set interrupt state + * to ACTIVE (and allow to increment failed_attempts counter). + * After 3 attempts, we are setting interrupt state to INACTIVE + * but we are not going to call activate_mkbp_with_events(). + * This was meant to unblock MKBP interrupt mechanism for new + * events. + */ + state.interrupt = INTERRUPT_INACTIVE; + /* + * Failed attempts counter is cleared only when AP pulls all + * of events or we exceed number of attempts, so marking + * interrupt as INACTIVE doesn't affect failed_attempts counter. + * If we need to send interrupt once again + * activate_mkbp_with_events() will set interrupt state to + * ACTIVE before this function will be called. + */ + ++ap_comm_failure_count; if (++state.failed_attempts < 3) { - state.interrupt = INTERRUPT_INACTIVE; + send_mkbp_interrupt = 1; toggled = 1; + } else { + /* + * If we exceed maximum number of failed attempts we + * will stop trying to send MKBP interrupt for current + * event (send_mkbp_interrupt == 0), but leaving + * possibility to send MKBP interrupts for future + * events (state of interrupt makred as inactive). + * Future events should have a chance to be sent + * 3 times, so we should clear failed attempts + * counter now + */ + state.failed_attempts = 0; } } mutex_unlock(&state.lock); - if (toggled) - CPRINTS("MKBP not cleared within threshold, toggling."); + if (toggled) { + /** + * Don't spam the EC logs when the AP is hung. Instead, log the + * first few failures, and then indicate the AP is likely hung. + */ + if (ap_comm_failure_count < ap_comm_failure_threshold) { + CPRINTS("MKBP not cleared within threshold, toggling."); + } else if (ap_comm_failure_count == ap_comm_failure_threshold) { + CPRINTS("MKBP: The AP is failing to respond despite " + "being powered on."); + } + } - activate_mkbp_with_events(0); + if (send_mkbp_interrupt) + activate_mkbp_with_events(0); } test_mockable int mkbp_send_event(uint8_t event_type) @@ -302,8 +373,14 @@ static int set_inactive_if_no_events(void) mutex_unlock(&state.lock); /* Cancel our safety net since the events were cleared. */ - if (interrupt_cleared) + if (interrupt_cleared) { hook_call_deferred(&force_mkbp_if_events_data, -1); + /** + * This AP communication was successful. + * Reset the count to log the next AP communication failure. + */ + ap_comm_failure_count = 0; + } return interrupt_cleared; } @@ -319,11 +396,29 @@ static int take_event_if_set(uint8_t event_type) return taken; } +static const struct mkbp_event_source *find_mkbp_event_source(uint8_t type) +{ +#ifdef CONFIG_ZEPHYR + return zephyr_find_mkbp_event_source(type); +#else + const struct mkbp_event_source *src; + + for (src = __mkbp_evt_srcs; src < __mkbp_evt_srcs_end; ++src) + if (src->event_type == type) + break; + + if (src == __mkbp_evt_srcs_end) + return NULL; + + return src; +#endif +} + static enum ec_status mkbp_get_next_event(struct host_cmd_handler_args *args) { static int last; int i, evt; - uint8_t *resp = args->response; + struct ec_response_get_next_event *r = args->response; const struct mkbp_event_source *src; int data_size = -EC_ERROR_BUSY; @@ -349,14 +444,11 @@ static enum ec_status mkbp_get_next_event(struct host_cmd_handler_args *args) evt = (i + last) % EC_MKBP_EVENT_COUNT; last = evt + 1; - for (src = __mkbp_evt_srcs; src < __mkbp_evt_srcs_end; ++src) - if (src->event_type == evt) - break; - - if (src == __mkbp_evt_srcs_end) + src = find_mkbp_event_source(evt); + if (src == NULL) return EC_RES_ERROR; - resp[0] = evt; /* Event type */ + r->event_type = evt; /* * get_data() can return -EC_ERROR_BUSY which indicates that the @@ -366,7 +458,7 @@ static enum ec_status mkbp_get_next_event(struct host_cmd_handler_args *args) * event instead. Therefore, we have to service that button * event first. */ - data_size = src->get_data(resp + 1); + data_size = src->get_data((uint8_t *)&r->data); if (data_size == -EC_ERROR_BUSY) { mutex_lock(&state.lock); state.events |= BIT(evt); @@ -376,7 +468,7 @@ static enum ec_status mkbp_get_next_event(struct host_cmd_handler_args *args) /* If there are no more events and we support the "more" flag, set it */ if (!set_inactive_if_no_events() && args->version >= 2) - resp[0] |= EC_MKBP_HAS_MORE_EVENTS; + r->event_type |= EC_MKBP_HAS_MORE_EVENTS; if (data_size < 0) return EC_RES_ERROR; @@ -384,8 +476,7 @@ static enum ec_status mkbp_get_next_event(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_NEXT_EVENT, - mkbp_get_next_event, +DECLARE_HOST_COMMAND(EC_CMD_GET_NEXT_EVENT, mkbp_get_next_event, EC_VER_MASK(0) | EC_VER_MASK(1) | EC_VER_MASK(2)); #ifdef CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK @@ -401,12 +492,11 @@ mkbp_get_host_event_wake_mask(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_HOST_EVENT_GET_WAKE_MASK, - mkbp_get_host_event_wake_mask, - EC_VER_MASK(0)); + mkbp_get_host_event_wake_mask, EC_VER_MASK(0)); #endif /* CONFIG_MKBP_USE_HOST_EVENT */ #endif /* CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK */ -#if defined(CONFIG_MKBP_EVENT_WAKEUP_MASK) || \ +#if defined(CONFIG_MKBP_EVENT_WAKEUP_MASK) || \ defined(CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK) static enum ec_status hc_mkbp_wake_mask(struct host_cmd_handler_args *args) { @@ -445,8 +535,7 @@ static enum ec_status hc_mkbp_wake_mask(struct host_cmd_handler_args *args) case EC_MKBP_HOST_EVENT_WAKE_MASK: CPRINTF("MKBP hostevent mask updated to: 0x%08x " "(was 0x%08x)\n", - p->new_wake_mask, - mkbp_host_event_wake_mask); + p->new_wake_mask, mkbp_host_event_wake_mask); mkbp_host_event_wake_mask = p->new_wake_mask; break; #endif /* CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK */ @@ -471,15 +560,13 @@ static enum ec_status hc_mkbp_wake_mask(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_MKBP_WAKE_MASK, - hc_mkbp_wake_mask, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_MKBP_WAKE_MASK, hc_mkbp_wake_mask, EC_VER_MASK(0)); -static int command_mkbp_wake_mask(int argc, char **argv) +static int command_mkbp_wake_mask(int argc, const char **argv) { if (argc == 3) { char *e; - uint32_t new_mask = strtoul(argv[2], &e, 0); + uint32_t new_mask = strtoull(argv[2], &e, 0); if (*e) return EC_ERROR_PARAM2; @@ -510,3 +597,22 @@ DECLARE_CONSOLE_COMMAND(mkbpwakemask, command_mkbp_wake_mask, "[event | hostevent] [new_mask]", "Show or set MKBP event/hostevent wake mask"); #endif /* CONFIG_MKBP_(HOST)?EVENT_WAKEUP_MASK */ + +#ifdef TEST_BUILD +void mkbp_event_clear_all(void) +{ + mutex_lock(&state.lock); + state.events = 0; + mutex_unlock(&state.lock); + + /* Reset the interrupt line */ + mkbp_set_host_active(0, NULL); +#ifdef CONFIG_MKBP_EVENT_WAKEUP_MASK + mkbp_event_wake_mask = CONFIG_MKBP_EVENT_WAKEUP_MASK; +#endif /* CONFIG_MKBP_EVENT_WAKEUP_MASK */ + +#ifdef CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK + mkbp_host_event_wake_mask = CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK; +#endif /* CONFIG_MKBP_HOST_EVENT_WAKEUP_MASK */ +} +#endif diff --git a/common/mkbp_fifo.c b/common/mkbp_fifo.c new file mode 100644 index 0000000000..8aaf1a5940 --- /dev/null +++ b/common/mkbp_fifo.c @@ -0,0 +1,239 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Matrix KeyBoard Protocol FIFO buffer implementation + */ + +#include "atomic.h" +#include "common.h" +#include "keyboard_config.h" +#include "mkbp_event.h" +#include "mkbp_fifo.h" +#include "system.h" +#include "task.h" +#include "util.h" + +/* Console output macros */ +#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ##args) + +/* + * Common FIFO depth. This needs to be big enough not to overflow if a + * series of keys is pressed in rapid succession and the kernel is too busy + * to read them out right away. + * + * RAM usage is (depth * #cols); A 16-entry FIFO will consume 16x16=256 bytes, + * which is non-trivial but not horrible. + */ + +static uint32_t fifo_start; /* first entry */ +static uint32_t fifo_end; /* last entry */ +static atomic_t fifo_entries; /* number of existing entries */ +static uint8_t fifo_max_depth = FIFO_DEPTH; +static struct ec_response_get_next_event_v1 fifo[FIFO_DEPTH]; + +BUILD_ASSERT(sizeof(fifo[0].data) >= KEYBOARD_COLS_MAX); + +/* + * Mutex for critical sections of mkbp_fifo_add(), which is called + * from various tasks. + */ +K_MUTEX_DEFINE(fifo_add_mutex); +/* + * Mutex for critical sections of fifo_remove(), which is called from the + * hostcmd task and from keyboard_clear_buffer(). + */ +K_MUTEX_DEFINE(fifo_remove_mutex); + +static int get_data_size(enum ec_mkbp_event e) +{ + switch (e) { + case EC_MKBP_EVENT_KEY_MATRIX: + return KEYBOARD_COLS_MAX; + + case EC_MKBP_EVENT_HOST_EVENT64: + return sizeof(uint64_t); + + case EC_MKBP_EVENT_HOST_EVENT: + case EC_MKBP_EVENT_BUTTON: + case EC_MKBP_EVENT_SWITCH: + case EC_MKBP_EVENT_SYSRQ: + return sizeof(uint32_t); + default: + /* For unknown types, say it's 0. */ + return 0; + } +} + +/** + * Pop MKBP event data from FIFO + * + * @return EC_SUCCESS if entry popped, EC_ERROR_UNKNOWN if FIFO is empty + */ +static int fifo_remove(uint8_t *buffp) +{ + int size; + + mutex_lock(&fifo_remove_mutex); + if (!fifo_entries) { + /* no entry remaining in FIFO : return last known state */ + int last = (fifo_start + FIFO_DEPTH - 1) % FIFO_DEPTH; + + size = get_data_size(fifo[last].event_type); + + memcpy(buffp, &fifo[last].data, size); + mutex_unlock(&fifo_remove_mutex); + + /* + * Bail out without changing any FIFO indices and let the + * caller know something strange happened. The buffer will + * will contain the last known state of the keyboard. + */ + return EC_ERROR_UNKNOWN; + } + + /* Return just the event data. */ + if (buffp) { + size = get_data_size(fifo[fifo_start].event_type); + /* skip over event_type. */ + memcpy(buffp, &fifo[fifo_start].data, size); + } + + fifo_start = (fifo_start + 1) % FIFO_DEPTH; + atomic_sub(&fifo_entries, 1); + mutex_unlock(&fifo_remove_mutex); + + return EC_SUCCESS; +} + +/*****************************************************************************/ +/* Interface */ + +void mkbp_fifo_depth_update(uint8_t new_max_depth) +{ + fifo_max_depth = new_max_depth; +} + +void mkbp_fifo_clear_keyboard(void) +{ + int i, new_fifo_entries = 0; + + CPRINTS("clear keyboard MKBP fifo"); + + /* + * Order of these locks is important to prevent deadlock since + * mkbp_fifo_add() may call fifo_remove(). + */ + mutex_lock(&fifo_add_mutex); + mutex_lock(&fifo_remove_mutex); + + /* Reset the end position */ + fifo_end = fifo_start; + + for (i = 0; i < fifo_entries; i++) { + int cur = (fifo_start + i) % FIFO_DEPTH; + + /* Drop keyboard events */ + if (fifo[cur].event_type == EC_MKBP_EVENT_KEY_MATRIX) + continue; + + /* And move other events to the front */ + memmove(&fifo[fifo_end], &fifo[cur], sizeof(fifo[cur])); + fifo_end = (fifo_end + 1) % FIFO_DEPTH; + ++new_fifo_entries; + } + fifo_entries = new_fifo_entries; + + mutex_unlock(&fifo_remove_mutex); + mutex_unlock(&fifo_add_mutex); +} + +void mkbp_clear_fifo(void) +{ + int i; + + CPRINTS("clear MKBP fifo"); + + /* + * Order of these locks is important to prevent deadlock since + * mkbp_fifo_add() may call fifo_remove(). + */ + mutex_lock(&fifo_add_mutex); + mutex_lock(&fifo_remove_mutex); + + fifo_start = 0; + fifo_end = 0; + /* This assignment is safe since both mutexes are held. */ + fifo_entries = 0; + for (i = 0; i < FIFO_DEPTH; i++) + memset(&fifo[i], 0, sizeof(struct ec_response_get_next_event)); + + mutex_unlock(&fifo_remove_mutex); + mutex_unlock(&fifo_add_mutex); +} + +test_mockable int mkbp_fifo_add(uint8_t event_type, const uint8_t *buffp) +{ + uint8_t size; + + mutex_lock(&fifo_add_mutex); + if (fifo_entries >= fifo_max_depth) { + mutex_unlock(&fifo_add_mutex); + CPRINTS("MKBP common FIFO depth %d reached", fifo_max_depth); + + return EC_ERROR_OVERFLOW; + } + + size = get_data_size(event_type); + fifo[fifo_end].event_type = event_type; + memcpy(&fifo[fifo_end].data, buffp, size); + fifo_end = (fifo_end + 1) % FIFO_DEPTH; + atomic_add(&fifo_entries, 1); + + /* + * If our event didn't generate an interrupt then the host is still + * asleep. In this case, we don't want to queue our event, except if + * another event just woke the host (and wake is already in progress). + */ + if (!mkbp_send_event(event_type) && fifo_entries == 1) + fifo_remove(NULL); + + mutex_unlock(&fifo_add_mutex); + return EC_SUCCESS; +} + +int mkbp_fifo_get_next_event(uint8_t *out, enum ec_mkbp_event evt) +{ + uint8_t t = fifo[fifo_start].event_type; + uint8_t size; + + if (!fifo_entries) + return -1; + + /* + * We need to peek at the next event to check that we were called with + * the correct event. + */ + if (t != (uint8_t)evt) { + /* + * We were called with the wrong event. The next element in the + * FIFO's event type doesn't match with what we were called + * with. Return an error that we're busy. The caller will need + * to call us with the correct event first. + */ + return -EC_ERROR_BUSY; + } + + fifo_remove(out); + + /* Keep sending events if FIFO is not empty */ + if (fifo_entries) + mkbp_send_event(fifo[fifo_start].event_type); + + /* Return the correct size of the data. */ + size = get_data_size(t); + if (size) + return size; + else + return -EC_ERROR_UNKNOWN; +} diff --git a/common/mkbp_info.c b/common/mkbp_info.c new file mode 100644 index 0000000000..c8cc6e7f58 --- /dev/null +++ b/common/mkbp_info.c @@ -0,0 +1,155 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* MKBP info host command */ + +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "host_command.h" +#include "keyboard_config.h" +#include "keyboard_mkbp.h" +#include "keyboard_scan.h" +#include "mkbp_info.h" +#include "mkbp_input_devices.h" +#include "util.h" + +__overridable int mkbp_support_volume_buttons(void) +{ +#ifdef CONFIG_VOLUME_BUTTONS + return 1; +#else + return 0; +#endif +} + +test_export_static uint32_t get_supported_buttons(void) +{ + uint32_t val = 0; + + if (mkbp_support_volume_buttons()) { + val |= BIT(EC_MKBP_VOL_UP) | BIT(EC_MKBP_VOL_DOWN); + } + +#ifdef CONFIG_DEDICATED_RECOVERY_BUTTON + val |= BIT(EC_MKBP_RECOVERY); +#endif /* defined(CONFIG_DEDICATED_RECOVERY_BUTTON) */ + +#ifdef CONFIG_POWER_BUTTON + val |= BIT(EC_MKBP_POWER_BUTTON); +#endif /* defined(CONFIG_POWER_BUTTON) */ + + return val; +} + +test_export_static uint32_t get_supported_switches(void) +{ + uint32_t val = 0; + +#ifdef CONFIG_LID_SWITCH + val |= BIT(EC_MKBP_LID_OPEN); +#endif +#ifdef CONFIG_TABLET_MODE_SWITCH + val |= BIT(EC_MKBP_TABLET_MODE); +#endif +#ifdef CONFIG_BASE_ATTACHED_SWITCH + val |= BIT(EC_MKBP_BASE_ATTACHED); +#endif +#ifdef CONFIG_FRONT_PROXIMITY_SWITCH + val |= BIT(EC_MKBP_FRONT_PROXIMITY); +#endif + return val; +} + +static enum ec_status mkbp_get_info(struct host_cmd_handler_args *args) +{ + const struct ec_params_mkbp_info *p = args->params; + + if (args->params_size == 0 || p->info_type == EC_MKBP_INFO_KBD) { + struct ec_response_mkbp_info *r = args->response; + +#ifdef CONFIG_KEYBOARD_PROTOCOL_MKBP + /* Version 0 just returns info about the keyboard. */ + r->rows = KEYBOARD_ROWS; + r->cols = KEYBOARD_COLS_MAX; +#else + r->rows = 0; + r->cols = 0; +#endif /* CONFIG_KEYBOARD_PROTOCOL_MKBP */ + + /* This used to be "switches" which was previously 0. */ + r->reserved = 0; + + args->response_size = sizeof(struct ec_response_mkbp_info); + } else { + union ec_response_get_next_data *r = args->response; + + /* Version 1 (other than EC_MKBP_INFO_KBD) */ + switch (p->info_type) { + case EC_MKBP_INFO_SUPPORTED: + switch (p->event_type) { + case EC_MKBP_EVENT_BUTTON: + r->buttons = get_supported_buttons(); + args->response_size = sizeof(r->buttons); + break; + + case EC_MKBP_EVENT_SWITCH: + r->switches = get_supported_switches(); + args->response_size = sizeof(r->switches); + break; + + default: + /* Don't care for now for other types. */ + return EC_RES_INVALID_PARAM; + } + break; + + case EC_MKBP_INFO_CURRENT: + switch (p->event_type) { +#ifdef HAS_TASK_KEYSCAN + case EC_MKBP_EVENT_KEY_MATRIX: + memcpy(r->key_matrix, keyboard_scan_get_state(), + sizeof(r->key_matrix)); + args->response_size = sizeof(r->key_matrix); + break; +#endif + case EC_MKBP_EVENT_HOST_EVENT: + r->host_event = (uint32_t)host_get_events(); + args->response_size = sizeof(r->host_event); + break; + + case EC_MKBP_EVENT_HOST_EVENT64: + r->host_event64 = host_get_events(); + args->response_size = sizeof(r->host_event64); + break; + +#ifdef CONFIG_MKBP_INPUT_DEVICES + case EC_MKBP_EVENT_BUTTON: + r->buttons = mkbp_get_button_state(); + args->response_size = sizeof(r->buttons); + break; + + case EC_MKBP_EVENT_SWITCH: + r->switches = mkbp_get_switch_state(); + args->response_size = sizeof(r->switches); + break; +#endif /* CONFIG_MKBP_INPUT_DEVICES */ + + default: + /* Doesn't make sense for other event types. */ + return EC_RES_INVALID_PARAM; + } + break; + + default: + /* Unsupported query. */ + return EC_RES_ERROR; + } + } + return EC_RES_SUCCESS; +} + +DECLARE_HOST_COMMAND(EC_CMD_MKBP_INFO, mkbp_get_info, + EC_VER_MASK(0) | EC_VER_MASK(1)); diff --git a/common/mkbp_input_devices.c b/common/mkbp_input_devices.c new file mode 100644 index 0000000000..f2fad5da21 --- /dev/null +++ b/common/mkbp_input_devices.c @@ -0,0 +1,243 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Input devices using Matrix Keyboard Protocol [MKBP] events for Chrome EC */ + +#include "base_state.h" +#include "body_detection.h" +#include "button.h" +#include "console.h" +#include "hooks.h" +#include "host_command.h" +#include "keyboard_mkbp.h" +#include "keyboard_scan.h" +#include "lid_switch.h" +#include "mkbp_event.h" +#include "mkbp_fifo.h" +#include "mkbp_input_devices.h" +#include "power_button.h" +#include "tablet_mode.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ##args) + +/* Buttons state. */ +static uint32_t mkbp_button_state; + +static bool mkbp_init_done; + +uint32_t mkbp_get_switch_state(void) +{ + uint32_t mkbp_switch_state = 0; + + /* + * These all read already debounced states and cause no side effects + * or latency. + */ + if (IS_ENABLED(CONFIG_LID_SWITCH)) + mkbp_switch_state |= lid_is_open() << EC_MKBP_LID_OPEN; + if (IS_ENABLED(CONFIG_TABLET_MODE_SWITCH)) + mkbp_switch_state |= tablet_get_mode() << EC_MKBP_TABLET_MODE; + if (IS_ENABLED(CONFIG_BASE_ATTACHED_SWITCH)) + mkbp_switch_state |= base_get_state() << EC_MKBP_BASE_ATTACHED; + if (IS_ENABLED(CONFIG_BODY_DETECTION_NOTIFY_MKBP)) + mkbp_switch_state |= body_detect_get_state() + << EC_MKBP_FRONT_PROXIMITY; + return mkbp_switch_state; +}; + +uint32_t mkbp_get_button_state(void) +{ + return mkbp_button_state; +}; + +void mkbp_button_update(enum keyboard_button_type button, int is_pressed) +{ + switch (button) { + case KEYBOARD_BUTTON_POWER: + mkbp_button_state &= ~BIT(EC_MKBP_POWER_BUTTON); + mkbp_button_state |= (is_pressed << EC_MKBP_POWER_BUTTON); + break; + + case KEYBOARD_BUTTON_VOLUME_UP: + mkbp_button_state &= ~BIT(EC_MKBP_VOL_UP); + mkbp_button_state |= (is_pressed << EC_MKBP_VOL_UP); + break; + + case KEYBOARD_BUTTON_VOLUME_DOWN: + mkbp_button_state &= ~BIT(EC_MKBP_VOL_DOWN); + mkbp_button_state |= (is_pressed << EC_MKBP_VOL_DOWN); + break; + + case KEYBOARD_BUTTON_RECOVERY: + mkbp_button_state &= ~BIT(EC_MKBP_RECOVERY); + mkbp_button_state |= (is_pressed << EC_MKBP_RECOVERY); + break; + + default: + /* ignored. */ + return; + } + + CPRINTS("mkbp buttons: %x", mkbp_button_state); + + mkbp_fifo_add(EC_MKBP_EVENT_BUTTON, + (const uint8_t *)&mkbp_button_state); +}; + +void mkbp_update_switches(void) +{ + /* + * Only inform AP mkbp changes when all switches initialized, in case + * of the middle states causing the weird behaviour in the AP side, + * especially when sysjumped while AP up. + */ + if (mkbp_init_done) { + uint32_t mkbp_switch_state = mkbp_get_switch_state(); + + CPRINTS("mkbp switches: %x", mkbp_switch_state); + mkbp_fifo_add(EC_MKBP_EVENT_SWITCH, + (const uint8_t *)&mkbp_switch_state); + } +} + +/*****************************************************************************/ +/* Hooks */ + +#ifdef CONFIG_POWER_BUTTON +/** + * Handle power button changing state. + */ +static void keyboard_power_button(void) +{ + mkbp_button_update(KEYBOARD_BUTTON_POWER, power_button_is_pressed()); +} +DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, keyboard_power_button, + HOOK_PRIO_DEFAULT); +#endif /* defined(CONFIG_POWER_BUTTON) */ + +#ifdef CONFIG_LID_SWITCH +/** + * Handle lid changing state. + */ +DECLARE_HOOK(HOOK_LID_CHANGE, mkbp_update_switches, HOOK_PRIO_LAST); +#endif + +#ifdef CONFIG_TABLET_MODE_SWITCH +DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, mkbp_update_switches, HOOK_PRIO_LAST); +#endif + +#ifdef CONFIG_BASE_ATTACHED_SWITCH +DECLARE_HOOK(HOOK_BASE_ATTACHED_CHANGE, mkbp_update_switches, HOOK_PRIO_LAST); +#endif + +#ifdef CONFIG_BODY_DETECTION_NOTIFY_MKBP +DECLARE_HOOK(HOOK_BODY_DETECT_CHANGE, mkbp_update_switches, HOOK_PRIO_LAST); +#endif + +static void mkbp_report_switch_on_init(void) +{ + /* All switches initialized, report switch state to AP */ + mkbp_init_done = true; + mkbp_update_switches(); +} +DECLARE_HOOK(HOOK_INIT, mkbp_report_switch_on_init, HOOK_PRIO_LAST); + +#ifdef CONFIG_EMULATED_SYSRQ +void host_send_sysrq(uint8_t key) +{ + uint32_t value = key; + + mkbp_fifo_add(EC_MKBP_EVENT_SYSRQ, (const uint8_t *)&value); +} +#endif + +/*****************************************************************************/ +/* Events */ + +static int mkbp_button_get_next_event(uint8_t *out) +{ + return mkbp_fifo_get_next_event(out, EC_MKBP_EVENT_BUTTON); +} +DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_BUTTON, mkbp_button_get_next_event); + +static int switch_get_next_event(uint8_t *out) +{ + return mkbp_fifo_get_next_event(out, EC_MKBP_EVENT_SWITCH); +} +DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_SWITCH, switch_get_next_event); + +#ifdef CONFIG_EMULATED_SYSRQ +static int sysrq_get_next_event(uint8_t *out) +{ + return mkbp_fifo_get_next_event(out, EC_MKBP_EVENT_SYSRQ); +} +DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_SYSRQ, sysrq_get_next_event); +#endif + +/************************ Keyboard press simulation ************************/ +#ifndef HAS_TASK_KEYSCAN +/* Keys simulated-pressed */ +static uint8_t simulated_key[KEYBOARD_COLS_MAX]; +uint8_t keyboard_cols = KEYBOARD_COLS_MAX; + +/* For boards without a keyscan task, try and simulate keyboard presses. */ +static void simulate_key(int row, int col, int pressed) +{ + if ((simulated_key[col] & BIT(row)) == ((pressed ? 1 : 0) << row)) + return; /* No change */ + + simulated_key[col] &= ~BIT(row); + if (pressed) + simulated_key[col] |= BIT(row); + + mkbp_fifo_add((uint8_t)EC_MKBP_EVENT_KEY_MATRIX, simulated_key); +} + +static int command_mkbp_keyboard_press(int argc, const char **argv) +{ + if (argc == 1) { + int i, j; + + ccputs("Simulated keys:\n"); + for (i = 0; i < keyboard_cols; ++i) { + if (simulated_key[i] == 0) + continue; + for (j = 0; j < KEYBOARD_ROWS; ++j) + if (simulated_key[i] & BIT(j)) + ccprintf("\t%d %d\n", i, j); + } + + } else if (argc == 3 || argc == 4) { + int r, c, p; + char *e; + + c = strtoi(argv[1], &e, 0); + if (*e || c < 0 || c >= keyboard_cols) + return EC_ERROR_PARAM1; + + r = strtoi(argv[2], &e, 0); + if (*e || r < 0 || r >= KEYBOARD_ROWS) + return EC_ERROR_PARAM2; + + if (argc == 3) { + /* Simulate a press and release */ + simulate_key(r, c, 1); + simulate_key(r, c, 0); + } else { + p = strtoi(argv[3], &e, 0); + if (*e || p < 0 || p > 1) + return EC_ERROR_PARAM3; + + simulate_key(r, c, p); + } + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(kbpress, command_mkbp_keyboard_press, + "[col row [0 | 1]]", "Simulate keypress"); + +#endif /* !defined(HAS_TASK_KEYSCAN) */ diff --git a/common/mock/README.md b/common/mock/README.md index bb85217bde..ab91f9f927 100644 --- a/common/mock/README.md +++ b/common/mock/README.md @@ -1,25 +1,24 @@ # Common Mocks + This directory holds mock implementations for use in fuzzers and tests. -Each mock is given some friendly build name, like ROLLBACK or FP_SENSOR. -This name is defined in [common/mock/build.mk](build.mk) and referenced -from unit tests and fuzzers' `.mocklist` file. +Each mock is given some friendly build name, like ROLLBACK or FP_SENSOR. This +name is defined in [common/mock/build.mk](build.mk) and referenced from unit +tests and fuzzers' `.mocklist` file. ## Creating a new mock -* Add the mock source to [common/mock](/common/mock) and the - optional header file to [include/mock](/include/mock). - Header files are only necessary if you want to expose additional - [mock control](#mock-controls) functions/variables. - See the [Design Patterns](#design-patterns) section - for more detail on design patterns. -* Add a new entry in [common/mock/build.mk](build.mk) - that is conditioned on your mock's name. +* Add the mock source to [common/mock](/common/mock) and the optional header + file to [include/mock](/include/mock). Header files are only necessary if + you want to expose additional [mock control](#mock-controls) + functions/variables. See the [Design Patterns](#design-patterns) section for + more detail on design patterns. +* Add a new entry in [common/mock/build.mk](build.mk) that is conditioned on + your mock's name. -If a unit test or fuzzer requests this mock, the build system will -set the variable `HAS_MOCK_` to `y` at build time. -This variable is used to conditionally include the mock source -in [common/mock/build.mk](build.mk). +If a unit test or fuzzer requests this mock, the build system will set the +variable `HAS_MOCK_` to `y` at build time. This variable is used to +conditionally include the mock source in [common/mock/build.mk](build.mk). Example line from [common/mock/build.mk](build.mk): @@ -29,28 +28,29 @@ mock-$(HAS_MOCK_ROLLBACK) += mock/rollback_mock.o ``` ## Using a mock -Unit tests and fuzzers can request a particular mock by adding an entry to -their `.mocklist` file. The mocklist file is similar to a `.tasklist` -file, where it is named according to the test/fuzz's name followed by -`.mocklist`, like `fpsensor.mocklist`. -The mocklist file is optional, so you may need to create one. + +Unit tests and fuzzers can request a particular mock by adding an entry to their +`.mocklist` file. The mocklist file is similar to a `.tasklist` file, where it +is named according to the test/fuzz's name followed by `.mocklist`, like +`fpsensor.mocklist`. The mocklist file is optional, so you may need to create +one. Example `.mocklist`: ```c -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #define CONFIG_TEST_MOCK_LIST \ - MOCK(ROLLBACK) \ - MOCK(FP_SENSOR) + MOCK(ROLLBACK) \ + MOCK(FPSENSOR) ``` -If you need additional [mock control](#mock-controls) functionality, -you may need to include the mock's header file, which is prepended -with `mock/` in the include line. +If you need additional [mock control](#mock-controls) functionality, you may +need to include the mock's header file, which is prepended with `mock/` in the +include line. For example, to control the return values of the rollback mock: @@ -58,30 +58,31 @@ For example, to control the return values of the rollback mock: #include "mock/rollback_mock.h" void yourfunction() { - mock_ctrl_rollback.get_secret_fail = true; + mock_ctrl_rollback.get_secret_fail = true; } ``` ## Mock Controls + Mocks can change their behavior by exposing "mock controls". -We do this, most commonly, by exposing an additional global struct -per mock that acts as the settings for the mock implementation. -The mock user can then modify fields of the struct to change the mock's behavior. -For example, the `fp_sensor_init_return` field may control what value -the mocked `fp_sensor_init` function returns. +We do this, most commonly, by exposing an additional global struct per mock that +acts as the settings for the mock implementation. The mock user can then modify +fields of the struct to change the mock's behavior. For example, the +`fp_sensor_init_return` field may control what value the mocked `fp_sensor_init` +function returns. The declaration for these controls are specified in the mock's header file, which resides in [include/mock](/include/mock). ## Design Patterns -* When creating mock controls, consider placing all your mock parameters in - one externally facing struct, like in - [fp_sensor_mock.h](/include/mock/fp_sensor_mock.h). - The primary reason for this is to allow the mock to be easily used - by a fuzzer (write random bytes into the struct with memcpy). -* When following the above pattern, please provide a macro for resetting - default values for this struct, like in - [fp_sensor_mock.h](/include/mock/fp_sensor_mock.h). - This allows unit tests to quickly reset the mock state/parameters - before each unrelated unit test. + +* When creating mock controls, consider placing all your mock parameters in + one externally facing struct, like in + [fpsensor_mock.h](/include/mock/fpsensor_mock.h). The primary reason for + this is to allow the mock to be easily used by a fuzzer (write random bytes + into the struct with memcpy). +* When following the above pattern, please provide a macro for resetting + default values for this struct, like in + [fpsensor_mock.h](/include/mock/fpsensor_mock.h). This allows unit tests + to quickly reset the mock state/parameters before each unrelated unit test. diff --git a/common/mock/adc_mock.c b/common/mock/adc_mock.c new file mode 100644 index 0000000000..35cf4aadb5 --- /dev/null +++ b/common/mock/adc_mock.c @@ -0,0 +1,11 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "adc.h" + +int adc_read_channel(enum adc_channel ch) +{ + return 0; +} diff --git a/common/mock/battery_mock.c b/common/mock/battery_mock.c new file mode 100644 index 0000000000..7bf15fb60a --- /dev/null +++ b/common/mock/battery_mock.c @@ -0,0 +1,223 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "string.h" + +/***************************************************************************** + * Battery functions needed to enable CONFIG_BATTERY + */ +static int battery_soc_value = 100; +int board_get_battery_soc(void) +{ + return battery_soc_value; +} +void set_battery_soc(int new_value) +{ + battery_soc_value = new_value; +} + +static int battery_status_value; +int battery_status(int *status) +{ + *status = battery_status_value; + return EC_SUCCESS; +} +void set_battery_status(int new_value) +{ + battery_status_value = new_value; +} + +static int battery_serial_number_value; +int battery_serial_number(int *serial) +{ + *serial = battery_serial_number_value; + return EC_SUCCESS; +} +void set_battery_serial_number(int new_value) +{ + battery_serial_number_value = new_value; +} + +static int battery_cycle_count_value; +int battery_cycle_count(int *count) +{ + *count = battery_cycle_count_value; + return EC_SUCCESS; +} +void set_battery_cycle_count(int new_value) +{ + battery_cycle_count_value = new_value; +} + +static int battery_design_voltage_value = 5000; +int battery_design_voltage(int *voltage) +{ + *voltage = battery_design_voltage_value; + return EC_SUCCESS; +} +void set_battery_design_voltage(int new_value) +{ + battery_design_voltage_value = new_value; +} + +static int battery_mode_value; +int battery_get_mode(int *mode) +{ + *mode = battery_mode_value; + return EC_SUCCESS; +} +void set_battery_mode(int new_value) +{ + battery_mode_value = new_value; +} + +static int battery_soc_abs_value = 100; +int battery_state_of_charge_abs(int *percent) +{ + *percent = battery_soc_abs_value; + return EC_SUCCESS; +} +void set_battery_soc_abs(int new_value) +{ + battery_soc_abs_value = new_value; +} + +static int battery_remaining_capacity_value = 100; +int battery_remaining_capacity(int *capacity) +{ + *capacity = battery_remaining_capacity_value; + return EC_SUCCESS; +} +void set_battery_remaining_capacity(int new_value) +{ + battery_remaining_capacity_value = new_value; +} + +static int battery_full_charge_capacity_value = 100; +int battery_full_charge_capacity(int *capacity) +{ + *capacity = battery_full_charge_capacity_value; + return EC_SUCCESS; +} +void set_battery_full_charge_capacity(int new_value) +{ + battery_full_charge_capacity_value = new_value; +} + +static int battery_design_capacity_value = 100; +int battery_design_capacity(int *capacity) +{ + *capacity = battery_design_capacity_value; + return EC_SUCCESS; +} +void set_battery_design_capacity(int new_value) +{ + battery_design_capacity_value = new_value; +} + +static int battery_time_to_empty_value = 60; +int battery_time_to_empty(int *minutes) +{ + *minutes = battery_time_to_empty_value; + return EC_SUCCESS; +} +void set_battery_time_to_empty(int new_value) +{ + battery_time_to_empty_value = new_value; +} + +static int battery_run_time_to_empty_value = 60; +int battery_run_time_to_empty(int *minutes) +{ + *minutes = battery_run_time_to_empty_value; + return EC_SUCCESS; +} +void set_battery_run_time_to_empty(int new_value) +{ + battery_run_time_to_empty_value = new_value; +} + +static int battery_time_to_full_value; +int battery_time_to_full(int *minutes) +{ + *minutes = battery_time_to_full_value; + return EC_SUCCESS; +} +void set_battery_time_to_full(int new_value) +{ + battery_time_to_full_value = new_value; +} + +#define MAX_DEVICE_NAME_LENGTH 40 +static char battery_device_name_value[MAX_DEVICE_NAME_LENGTH + 1] = "?"; +int battery_device_name(char *dest, int size) +{ + int i; + + for (i = 0; i < size && i < MAX_DEVICE_NAME_LENGTH; ++i) + dest[i] = battery_device_name_value[i]; + for (; i < size; ++i) + dest[i] = '\0'; + return EC_SUCCESS; +} +void set_battery_device_name(char *new_value) +{ + int i; + int size = strlen(new_value); + + for (i = 0; i < size && i < MAX_DEVICE_NAME_LENGTH; ++i) + battery_device_name_value[i] = new_value[i]; + for (; i < MAX_DEVICE_NAME_LENGTH + 1; ++i) + battery_device_name_value[i] = '\0'; +} + +#define MAX_DEVICE_CHEMISTRY_LENGTH 40 +static char battery_device_chemistry_value[MAX_DEVICE_CHEMISTRY_LENGTH + 1] = + "?"; +int battery_device_chemistry(char *dest, int size) +{ + int i; + + for (i = 0; i < size && i < MAX_DEVICE_CHEMISTRY_LENGTH; ++i) + dest[i] = battery_device_chemistry_value[i]; + for (; i < size; ++i) + dest[i] = '\0'; + return EC_SUCCESS; +} +void set_battery_device_chemistry(char *new_value) +{ + int i; + int size = strlen(new_value); + + for (i = 0; i < size && i < MAX_DEVICE_CHEMISTRY_LENGTH; ++i) + battery_device_chemistry_value[i] = new_value[i]; + for (; i < MAX_DEVICE_CHEMISTRY_LENGTH + 1; ++i) + battery_device_chemistry_value[i] = '\0'; +} + +static int battery_current_value = 3000; +static int battery_desired_current_value = 3000; +static int battery_desired_voltage_value = 5000; +static int battery_is_present_value = BP_YES; +static int battery_temperature_value = 20; +static int battery_voltage_value = 5000; +void battery_get_params(struct batt_params *batt) +{ + struct batt_params batt_new = { 0 }; + + batt_new.temperature = battery_temperature_value; + batt_new.state_of_charge = battery_soc_value; + batt_new.voltage = battery_voltage_value; + batt_new.current = battery_current_value; + batt_new.desired_voltage = battery_desired_voltage_value; + batt_new.desired_current = battery_desired_current_value; + batt_new.remaining_capacity = battery_remaining_capacity_value; + batt_new.full_capacity = battery_full_charge_capacity_value; + batt_new.status = battery_status_value; + batt_new.is_present = battery_is_present_value; + + memcpy(batt, &batt_new, sizeof(*batt)); +} diff --git a/common/mock/build.mk b/common/mock/build.mk index 5f2d548825..1293f23f4d 100644 --- a/common/mock/build.mk +++ b/common/mock/build.mk @@ -1,22 +1,28 @@ -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # See common/mock/README.md for more information. -mock-$(HAS_MOCK_FP_SENSOR) += fp_sensor_mock.o +mock-$(HAS_MOCK_ADC) += adc_mock.o +mock-$(HAS_MOCK_BATTERY) += battery_mock.o +mock-$(HAS_MOCK_CHARGE_MANAGER) += charge_manager_mock.o +mock-$(HAS_MOCK_CLOCK) += clock_mock.o +mock-$(HAS_MOCK_FPSENSOR) += fpsensor_mock.o +mock-$(HAS_MOCK_FPSENSOR_CRYPTO) += fpsensor_crypto_mock.o mock-$(HAS_MOCK_FPSENSOR_DETECT) += fpsensor_detect_mock.o mock-$(HAS_MOCK_FPSENSOR_STATE) += fpsensor_state_mock.o mock-$(HAS_MOCK_MKBP_EVENTS) += mkbp_events_mock.o mock-$(HAS_MOCK_ROLLBACK) += rollback_mock.o +mock-$(HAS_MOCK_ROLLBACK_LATEST) += rollback_latest_mock.o mock-$(HAS_MOCK_TCPC) += tcpc_mock.o mock-$(HAS_MOCK_TCPM) += tcpm_mock.o mock-$(HAS_MOCK_TCPCI_I2C) += tcpci_i2c_mock.o mock-$(HAS_MOCK_TIMER) += timer_mock.o mock-$(HAS_MOCK_USB_MUX) += usb_mux_mock.o -mock-$(HAS_MOCK_USB_PD) += usb_pd_mock.o mock-$(HAS_MOCK_USB_PE_SM) += usb_pe_sm_mock.o mock-$(HAS_MOCK_USB_TC_SM) += usb_tc_sm_mock.o mock-$(HAS_MOCK_USB_PD_DPM) += usb_pd_dpm_mock.o mock-$(HAS_MOCK_DP_ALT_MODE) += dp_alt_mode_mock.o mock-$(HAS_MOCK_USB_PRL) += usb_prl_mock.o +mock-$(HAS_MOCK_USB_PE_DRP_SM) += usb_pe_drp_sm_mock.o diff --git a/common/mock/charge_manager_mock.c b/common/mock/charge_manager_mock.c new file mode 100644 index 0000000000..745b37efa7 --- /dev/null +++ b/common/mock/charge_manager_mock.c @@ -0,0 +1,64 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * @file + * @brief Mock charge_manager + */ + +#include "charge_manager.h" +#include "common.h" +#include "mock/charge_manager_mock.h" + +#include + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + +void charge_manager_update_dualrole(int port, enum dualrole_capabilities cap) +{ +} + +void charge_manager_set_ceil(int port, enum ceil_requestor requestor, int ceil) +{ +} + +int charge_manager_get_selected_charge_port(void) +{ + return 0; +} + +int charge_manager_get_active_charge_port(void) +{ + return 0; +} + +int charge_manager_get_charger_voltage(void) +{ + return 0; +} + +void charge_manager_force_ceil(int port, int ceil) +{ +} + +enum charge_supplier charge_manager_get_supplier(void) +{ + return CHARGE_SUPPLIER_NONE; +} + +int charge_manager_get_vbus_voltage(int port) +{ + return mock_ctrl_charge_manager.vbus_voltage_mv; +} + +void mock_charge_manager_set_vbus_voltage(int voltage_mv) +{ + mock_ctrl_charge_manager.vbus_voltage_mv = voltage_mv; +} + +struct mock_ctrl_charge_manager mock_ctrl_charge_manager = + MOCK_CTRL_DEFAULT_CHARGE_MANAGER; diff --git a/common/mock/clock_mock.c b/common/mock/clock_mock.c new file mode 100644 index 0000000000..876e691b57 --- /dev/null +++ b/common/mock/clock_mock.c @@ -0,0 +1,24 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "mock/clock_mock.h" + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + +static int fast_cpu_state; + +void clock_enable_module(enum module_id module, int enable) +{ + if (module == MODULE_FAST_CPU) { + fast_cpu_state = enable; + } +} + +int get_mock_fast_cpu_status(void) +{ + return fast_cpu_state; +} diff --git a/common/mock/dp_alt_mode_mock.c b/common/mock/dp_alt_mode_mock.c index bc67d57a31..98f14949ed 100644 --- a/common/mock/dp_alt_mode_mock.c +++ b/common/mock/dp_alt_mode_mock.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,12 +9,17 @@ * section 5.2 */ -#include "usb_dp_alt_mode.h" +#include "console.h" #include "mock/dp_alt_mode_mock.h" +#include "usb_dp_alt_mode.h" + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else #define CPRINTF(format, args...) #define CPRINTS(format, args...) @@ -24,14 +29,3 @@ void mock_dp_alt_mode_reset(void) { /* Nothing to do right now, but in the future ... */ } - -void dp_init(int port) -{ - CPRINTS("C%d: DP init", port); -} - -void dp_teardown(int port) -{ - CPRINTS("C%d: DP teardown", port); -} - diff --git a/common/mock/fp_sensor_mock.c b/common/mock/fp_sensor_mock.c deleted file mode 100644 index 18e6d656be..0000000000 --- a/common/mock/fp_sensor_mock.c +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/** - * @file - * @brief Mock fpsensor private driver - */ - -#include - -#include "common.h" -#include "fpsensor.h" -#include "mock/fp_sensor_mock.h" - -struct mock_ctrl_fp_sensor mock_ctrl_fp_sensor = MOCK_CTRL_DEFAULT_FP_SENSOR; - -int fp_sensor_init(void) -{ - return mock_ctrl_fp_sensor.fp_sensor_init_return; -} - -int fp_sensor_deinit(void) -{ - return mock_ctrl_fp_sensor.fp_sensor_deinit_return; -} - -int fp_sensor_get_info(struct ec_response_fp_info *resp) -{ - resp->version = 0; - return mock_ctrl_fp_sensor.fp_sensor_get_info_return; -} - -void fp_sensor_low_power(void) -{ -} - -void fp_sensor_configure_detect(void) -{ -} - -enum finger_state fp_sensor_finger_status(void) -{ - return mock_ctrl_fp_sensor.fp_sensor_finger_status_return; -} - -int fp_sensor_acquire_image(uint8_t *image_data) -{ - return mock_ctrl_fp_sensor.fp_sensor_acquire_image_return; -} - -int fp_sensor_acquire_image_with_mode(uint8_t *image_data, int mode) -{ - return mock_ctrl_fp_sensor.fp_sensor_acquire_image_with_mode_return; -} - -int fp_finger_match(void *templ, uint32_t templ_count, - uint8_t *image, int32_t *match_index, - uint32_t *update_bitmap) -{ - return mock_ctrl_fp_sensor.fp_finger_match_return; -} - -int fp_enrollment_begin(void) -{ - return mock_ctrl_fp_sensor.fp_enrollment_begin_return; -} - -int fp_enrollment_finish(void *templ) -{ - return mock_ctrl_fp_sensor.fp_enrollment_finish_return; -} - -int fp_finger_enroll(uint8_t *image, int *completion) -{ - return mock_ctrl_fp_sensor.fp_finger_enroll_return; -} - -int fp_maintenance(void) -{ - return mock_ctrl_fp_sensor.fp_maintenance_return; -} diff --git a/common/mock/fpsensor_crypto_mock.c b/common/mock/fpsensor_crypto_mock.c new file mode 100644 index 0000000000..df88615e63 --- /dev/null +++ b/common/mock/fpsensor_crypto_mock.c @@ -0,0 +1,64 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * @file fpsensor_crypto_mock.c + * @brief Mock fpsensor_crypto library + */ +#include "assert.h" +#include "compile_time_macros.h" +#include "console.h" +#include "ec_commands.h" +#include "fpsensor_utils.h" +#include "mock/fpsensor_crypto_mock.h" +#include "sha256.h" + +#include +#include +#include + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + +struct mock_ctrl_fpsensor_crypto mock_ctrl_fpsensor_crypto = + MOCK_CTRL_DEFAULT_FPSENSOR_CRYPTO; + +#define MESSAGE_ZERO_IDX 0 +#define MESSAGE_FF_IDX 1 +typedef uint8_t key_message_pair[FP_POSITIVE_MATCH_SECRET_BYTES]; + +key_message_pair fake_fpsensor_crypto[] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } +}; + +BUILD_ASSERT(sizeof(key_message_pair) == FP_POSITIVE_MATCH_SECRET_BYTES); + +/* Mock compute_hmac_sha256 for unit or fuzz tests. */ +void compute_hmac_sha256(uint8_t *output, const uint8_t *key, const int key_len, + const uint8_t *message, const int message_len) +{ + switch (mock_ctrl_fpsensor_crypto.output_type) { + case MOCK_CTRL_FPSENSOR_CRYPTO_SHA256_TYPE_REAL: + hmac_SHA256(output, key, key_len, message, message_len); + break; + case MOCK_CTRL_FPSENSOR_CRYPTO_SHA256_TYPE_ZEROS: + memcpy(output, fake_fpsensor_crypto[MESSAGE_ZERO_IDX], + FP_POSITIVE_MATCH_SECRET_BYTES); + break; + case MOCK_CTRL_FPSENSOR_CRYPTO_SHA256_TYPE_FF: + memcpy(output, fake_fpsensor_crypto[MESSAGE_FF_IDX], + FP_POSITIVE_MATCH_SECRET_BYTES); + break; + default: + assert(0); + break; + }; +} diff --git a/common/mock/fpsensor_detect_mock.c b/common/mock/fpsensor_detect_mock.c index af1d7f5103..928c2fe6ec 100644 --- a/common/mock/fpsensor_detect_mock.c +++ b/common/mock/fpsensor_detect_mock.c @@ -1,19 +1,28 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "mock/fpsensor_detect_mock.h" +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + struct mock_ctrl_fpsensor_detect mock_ctrl_fpsensor_detect = MOCK_CTRL_DEFAULT_FPSENSOR_DETECT; -enum fp_sensor_type get_fp_sensor_type(void) +enum fp_sensor_type fpsensor_detect_get_type(void) { - return mock_ctrl_fpsensor_detect.get_fp_sensor_type_return; + return mock_ctrl_fpsensor_detect.fpsensor_detect_get_type_return; } enum fp_transport_type get_fp_transport_type(void) { return mock_ctrl_fpsensor_detect.get_fp_transport_type_return; } + +enum fp_sensor_spi_select fpsensor_detect_get_spi_select(void) +{ + return mock_ctrl_fpsensor_detect.get_fp_sensor_spi_select_return; +} diff --git a/common/mock/fpsensor_mock.c b/common/mock/fpsensor_mock.c new file mode 100644 index 0000000000..8540d30f1c --- /dev/null +++ b/common/mock/fpsensor_mock.c @@ -0,0 +1,86 @@ +/* Copyright 2019 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * @file + * @brief Mock fpsensor private driver + */ + +#include "common.h" +#include "fpsensor.h" +#include "mock/fpsensor_mock.h" + +#include + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + +struct mock_ctrl_fp_sensor mock_ctrl_fp_sensor = MOCK_CTRL_DEFAULT_FP_SENSOR; + +int fp_sensor_init(void) +{ + return mock_ctrl_fp_sensor.fp_sensor_init_return; +} + +int fp_sensor_deinit(void) +{ + return mock_ctrl_fp_sensor.fp_sensor_deinit_return; +} + +int fp_sensor_get_info(struct ec_response_fp_info *resp) +{ + resp->version = 0; + return mock_ctrl_fp_sensor.fp_sensor_get_info_return; +} + +void fp_sensor_low_power(void) +{ +} + +void fp_sensor_configure_detect(void) +{ +} + +enum finger_state fp_sensor_finger_status(void) +{ + return mock_ctrl_fp_sensor.fp_sensor_finger_status_return; +} + +int fp_sensor_acquire_image(uint8_t *image_data) +{ + return mock_ctrl_fp_sensor.fp_sensor_acquire_image_return; +} + +int fp_sensor_acquire_image_with_mode(uint8_t *image_data, int mode) +{ + return mock_ctrl_fp_sensor.fp_sensor_acquire_image_with_mode_return; +} + +int fp_finger_match(void *templ, uint32_t templ_count, uint8_t *image, + int32_t *match_index, uint32_t *update_bitmap) +{ + return mock_ctrl_fp_sensor.fp_finger_match_return; +} + +int fp_enrollment_begin(void) +{ + return mock_ctrl_fp_sensor.fp_enrollment_begin_return; +} + +int fp_enrollment_finish(void *templ) +{ + return mock_ctrl_fp_sensor.fp_enrollment_finish_return; +} + +int fp_finger_enroll(uint8_t *image, int *completion) +{ + return mock_ctrl_fp_sensor.fp_finger_enroll_return; +} + +int fp_maintenance(void) +{ + return mock_ctrl_fp_sensor.fp_maintenance_return; +} diff --git a/common/mock/fpsensor_state_mock.c b/common/mock/fpsensor_state_mock.c index 629b9a90a6..56b1fa23e7 100644 --- a/common/mock/fpsensor_state_mock.c +++ b/common/mock/fpsensor_state_mock.c @@ -1,15 +1,20 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include -#include - #include "common.h" #include "ec_commands.h" +#include "fpsensor_driver.h" #include "test_util.h" +#include +#include + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + const uint8_t default_fake_tpm_seed[] = { 0xd9, 0x71, 0xaf, 0xc4, 0xcd, 0x36, 0xe3, 0x60, 0xf8, 0x5a, 0xa0, 0xa6, 0x2c, 0xb3, 0xf5, 0xe2, 0xeb, 0xb9, 0xd8, 0x2f, 0xb5, 0x78, @@ -17,6 +22,38 @@ const uint8_t default_fake_tpm_seed[] = { }; BUILD_ASSERT(sizeof(default_fake_tpm_seed) == FP_CONTEXT_TPM_BYTES); +const uint8_t default_fake_fp_positive_match_salt + [FP_MAX_FINGER_COUNT][FP_POSITIVE_MATCH_SALT_BYTES] = { + { 0x04, 0x1f, 0x5a, 0xac, 0x5f, 0x79, 0x10, 0xaf, 0x04, 0x1d, + 0x46, 0x3a, 0x5f, 0x08, 0xee, 0xcb }, + { 0x04, 0x1f, 0x5a, 0xac, 0x5f, 0x79, 0x10, 0xaf, 0x04, 0x1d, + 0x46, 0x3a, 0x5f, 0x08, 0xee, 0xcb }, + { 0x04, 0x1f, 0x5a, 0xac, 0x5f, 0x79, 0x10, 0xaf, 0x04, 0x1d, + 0x46, 0x3a, 0x5f, 0x08, 0xee, 0xcb }, + { 0x04, 0x1f, 0x5a, 0xac, 0x5f, 0x79, 0x10, 0xaf, 0x04, 0x1d, + 0x46, 0x3a, 0x5f, 0x08, 0xee, 0xcb }, + { 0x04, 0x1f, 0x5a, 0xac, 0x5f, 0x79, 0x10, 0xaf, 0x04, 0x1d, + 0x46, 0x3a, 0x5f, 0x08, 0xee, 0xcb } + }; +BUILD_ASSERT(sizeof(default_fake_fp_positive_match_salt) == + FP_MAX_FINGER_COUNT * FP_POSITIVE_MATCH_SALT_BYTES); + +const uint8_t trivial_fp_positive_match_salt + [FP_MAX_FINGER_COUNT][FP_POSITIVE_MATCH_SALT_BYTES] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }; +BUILD_ASSERT(sizeof(trivial_fp_positive_match_salt) == + FP_MAX_FINGER_COUNT * FP_POSITIVE_MATCH_SALT_BYTES); + int fpsensor_state_mock_set_tpm_seed( const uint8_t tpm_seed[FP_CONTEXT_TPM_BYTES]) { diff --git a/common/mock/mkbp_events_mock.c b/common/mock/mkbp_events_mock.c index fdab664c39..559cb1494d 100644 --- a/common/mock/mkbp_events_mock.c +++ b/common/mock/mkbp_events_mock.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,12 +8,16 @@ * @brief Mock event handling for MKBP keyboard protocol */ -#include - #include "common.h" #include "mock/mkbp_events_mock.h" -struct mock_ctrl_mkbp_events mock_ctrl_mkbp_events = \ +#include + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + +struct mock_ctrl_mkbp_events mock_ctrl_mkbp_events = MOCK_CTRL_DEFAULT_MKBP_EVENTS; int mkbp_send_event(uint8_t event_type) diff --git a/common/mock/rollback_latest_mock.c b/common/mock/rollback_latest_mock.c new file mode 100644 index 0000000000..b3433246d7 --- /dev/null +++ b/common/mock/rollback_latest_mock.c @@ -0,0 +1,61 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * @file + * @brief Mock rollback block library + */ + +#include "common.h" +#include "compile_time_macros.h" +#include "mock/rollback_latest_mock.h" +#include "rollback_private.h" +#include "util.h" + +#include + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + +struct mock_ctrl_latest_rollback mock_ctrl_latest_rollback = + MOCK_CTRL_DEFAULT_LATEST_ROLLBACK; + +const struct rollback_data fake_latest_rollback_zeros = { + .cookie = 0, + .secret = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + + .id = 0, + .rollback_min_version = 0, +}; + +const struct rollback_data fake_latest_rollback_real = { + .cookie = 9, + .secret = { + 0xcf, 0xe3, 0x23, 0x76, 0x35, 0x04, 0xc2, 0x0f, 0x0d, 0xb6, 0x02, + 0xa9, 0x68, 0xba, 0x2a, 0x61, 0x86, 0x2a, 0x85, 0xd1, 0xca, 0x09, + 0x54, 0x8a, 0x6b, 0xe2, 0xe3, 0x38, 0xde, 0x5d, 0x59, 0x14,}, + .id = 2, + .rollback_min_version = 1, +}; + +/* Mock the rollback for unit or fuzz tests. */ +int get_latest_rollback(struct rollback_data *data) +{ + switch (mock_ctrl_latest_rollback.output_type) { + case GET_LATEST_ROLLBACK_FAIL: + return -5; + case GET_LATEST_ROLLBACK_ZEROS: + *data = fake_latest_rollback_zeros; + break; + case GET_LATEST_ROLLBACK_REAL: + *data = fake_latest_rollback_real; + break; + } + return EC_SUCCESS; +} diff --git a/common/mock/rollback_mock.c b/common/mock/rollback_mock.c index 84e9c4aa43..5b1be063c6 100644 --- a/common/mock/rollback_mock.c +++ b/common/mock/rollback_mock.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,27 +8,30 @@ * @brief Mock rollback block library */ -#include -#include - #include "common.h" #include "compile_time_macros.h" -#include "util.h" #include "mock/rollback_mock.h" +#include "util.h" + +#include +#include + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif struct mock_ctrl_rollback mock_ctrl_rollback = MOCK_CTRL_DEFAULT_ROLLBACK; static const uint8_t fake_rollback_secret[] = { - 0xcf, 0xe3, 0x23, 0x76, 0x35, 0x04, 0xc2, 0x0f, - 0x0d, 0xb6, 0x02, 0xa9, 0x68, 0xba, 0x2a, 0x61, - 0x86, 0x2a, 0x85, 0xd1, 0xca, 0x09, 0x54, 0x8a, - 0x6b, 0xe2, 0xe3, 0x38, 0xde, 0x5d, 0x59, 0x14, + 0xcf, 0xe3, 0x23, 0x76, 0x35, 0x04, 0xc2, 0x0f, 0x0d, 0xb6, 0x02, + 0xa9, 0x68, 0xba, 0x2a, 0x61, 0x86, 0x2a, 0x85, 0xd1, 0xca, 0x09, + 0x54, 0x8a, 0x6b, 0xe2, 0xe3, 0x38, 0xde, 0x5d, 0x59, 0x14, }; BUILD_ASSERT(sizeof(fake_rollback_secret) == CONFIG_ROLLBACK_SECRET_SIZE); /* Mock the rollback for unit or fuzz tests. */ -int rollback_get_secret(uint8_t *secret) +enum ec_error_list rollback_get_secret(uint8_t *secret) { if (mock_ctrl_rollback.get_secret_fail) return EC_ERROR_UNKNOWN; diff --git a/common/mock/tcpc_mock.c b/common/mock/tcpc_mock.c index 457868c96a..31dda7eba1 100644 --- a/common/mock/tcpc_mock.c +++ b/common/mock/tcpc_mock.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,6 +17,10 @@ #define cprints(format, args...) #endif +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + /* Public API for controlling/inspecting this mock */ struct mock_tcpc_ctrl mock_tcpc; @@ -121,8 +125,7 @@ static int mock_set_msg_header(int port, int power_role, int data_role) return EC_SUCCESS; ccprints("[TCPC] Setting TCPM-side header to %s %s", - from_pd_power_role(power_role), - from_pd_data_role(data_role)); + from_pd_power_role(power_role), from_pd_data_role(data_role)); return EC_SUCCESS; } @@ -137,8 +140,8 @@ static int mock_get_message_raw(int port, uint32_t *payload, int *head) return EC_SUCCESS; } -static int mock_transmit(int port, enum tcpm_transmit_type type, - uint16_t header, const uint32_t *data) +static int mock_transmit(int port, enum tcpci_msg_type type, uint16_t header, + const uint32_t *data) { return EC_SUCCESS; } @@ -183,9 +186,15 @@ __maybe_unused static int mock_set_src_ctrl(int port, int enable) __maybe_unused static int mock_enter_low_power_mode(int port) { + mock_tcpc.lpm_wake_requested = false; return EC_SUCCESS; } +__maybe_unused static void mock_wake_low_power_mode(int port) +{ + mock_tcpc.lpm_wake_requested = true; +} + int mock_set_frs_enable(int port, int enable) { return EC_SUCCESS; @@ -210,12 +219,11 @@ const struct tcpm_drv mock_tcpc_driver = { .drp_toggle = &mock_drp_toggle, #endif .get_chip_info = &mock_get_chip_info, -#ifdef CONFIG_USBC_PPC .set_snk_ctrl = &mock_set_snk_ctrl, .set_src_ctrl = &mock_set_src_ctrl, -#endif #ifdef CONFIG_USB_PD_TCPC_LOW_POWER .enter_low_power_mode = &mock_enter_low_power_mode, + .wake_low_power_mode = &mock_wake_low_power_mode, #endif #ifdef CONFIG_USB_PD_FRS_TCPC .set_frs_enable = &mock_set_frs_enable, diff --git a/common/mock/tcpci_i2c_mock.c b/common/mock/tcpci_i2c_mock.c index fa7268ddf4..a0e59ecc44 100644 --- a/common/mock/tcpci_i2c_mock.c +++ b/common/mock/tcpci_i2c_mock.c @@ -1,27 +1,36 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "mock/tcpci_i2c_mock.h" #include "task.h" -#include "tcpci.h" +#include "tcpm/tcpci.h" #include "test_util.h" #include "timer.h" +#include "usb_pd_tcpm.h" + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif #define BUFFER_SIZE 100 #define VERIFY_TIMEOUT (5 * SECOND) struct tcpci_reg { - uint8_t offset; - uint8_t size; - uint16_t value; - const char *name; + uint8_t offset; + uint8_t size; + uint16_t value; + const char *name; }; -#define TCPCI_REG(reg_name, reg_size) \ - [reg_name] = { .offset = (reg_name), .size = (reg_size), \ - .value = 0, .name = #reg_name, } +#define TCPCI_REG(reg_name, reg_size) \ + [reg_name] = { \ + .offset = (reg_name), \ + .size = (reg_size), \ + .value = 0, \ + .name = #reg_name, \ + } static struct tcpci_reg tcpci_regs[] = { TCPCI_REG(TCPC_REG_VENDOR_ID, 2), @@ -66,97 +75,150 @@ static struct tcpci_reg tcpci_regs[] = { static uint8_t tx_buffer[BUFFER_SIZE]; static int tx_pos = -1; +static int tx_msg_cnt; +static int tx_retry_cnt = -1; static uint8_t rx_buffer[BUFFER_SIZE]; static int rx_pos = -1; -static const char * const ctrl_msg_name[] = { - [0] = "RSVD-C0", - [PD_CTRL_GOOD_CRC] = "GOODCRC", - [PD_CTRL_GOTO_MIN] = "GOTOMIN", - [PD_CTRL_ACCEPT] = "ACCEPT", - [PD_CTRL_REJECT] = "REJECT", - [PD_CTRL_PING] = "PING", - [PD_CTRL_PS_RDY] = "PSRDY", - [PD_CTRL_GET_SOURCE_CAP] = "GSRCCAP", - [PD_CTRL_GET_SINK_CAP] = "GSNKCAP", - [PD_CTRL_DR_SWAP] = "DRSWAP", - [PD_CTRL_PR_SWAP] = "PRSWAP", - [PD_CTRL_VCONN_SWAP] = "VCONNSW", - [PD_CTRL_WAIT] = "WAIT", - [PD_CTRL_SOFT_RESET] = "SFT-RST", - [14] = "RSVD-C14", - [15] = "RSVD-C15", - [PD_CTRL_NOT_SUPPORTED] = "NOT-SUPPORTED", - [PD_CTRL_GET_SOURCE_CAP_EXT] = "GSRCCAP-EXT", - [PD_CTRL_GET_STATUS] = "GET-STATUS", - [PD_CTRL_FR_SWAP] = "FRSWAP", - [PD_CTRL_GET_PPS_STATUS] = "GET-PPS-STATUS", - [PD_CTRL_GET_COUNTRY_CODES] = "GET-COUNTRY-CODES", +static const char *const ctrl_msg_name[] = { + [0] = "C-RSVD_0", + [PD_CTRL_GOOD_CRC] = "C-GOODCRC", + [PD_CTRL_GOTO_MIN] = "C-GOTOMIN", + [PD_CTRL_ACCEPT] = "C-ACCEPT", + [PD_CTRL_REJECT] = "C-REJECT", + [PD_CTRL_PING] = "C-PING", + [PD_CTRL_PS_RDY] = "C-PSRDY", + [PD_CTRL_GET_SOURCE_CAP] = "C-GET_SRC_CAP", + [PD_CTRL_GET_SINK_CAP] = "C-GET_SNK_CAP", + [PD_CTRL_DR_SWAP] = "C-DR_SWAP", + [PD_CTRL_PR_SWAP] = "C-PR_SWAP", + [PD_CTRL_VCONN_SWAP] = "C-VCONN_SW", + [PD_CTRL_WAIT] = "C-WAIT", + [PD_CTRL_SOFT_RESET] = "C-SOFT-RESET", + [14] = "C-RSVD_14", + [15] = "C-RSVD_15", + [PD_CTRL_NOT_SUPPORTED] = "C-NOT_SUPPORTED", + [PD_CTRL_GET_SOURCE_CAP_EXT] = "C-GET_SRC_CAP-EXT", + [PD_CTRL_GET_STATUS] = "C-GET-STATUS", + [PD_CTRL_FR_SWAP] = "C-FR_SWAP", + [PD_CTRL_GET_PPS_STATUS] = "C-GET_PPS_STATUS", + [PD_CTRL_GET_COUNTRY_CODES] = "C-GET_COUNTRY_CODES", + [PD_CTRL_GET_SINK_CAP_EXT] = "C-GET_SINK_CAP_EXT", + [PD_CTRL_GET_SOURCE_INFO] = "C-GET_SOURCE_INFO", + [PD_CTRL_GET_REVISION] = "C-GET_REVISION", +}; + +static const char *const data_msg_name[] = { + [0] = "D-RSVD_0", + [PD_DATA_SOURCE_CAP] = "D-SRC_CAP", + [PD_DATA_REQUEST] = "D-REQUEST", + [PD_DATA_BIST] = "D-BIST", + [PD_DATA_SINK_CAP] = "D-SNK_CAP", + /* 5-14 Reserved for REV 2.0 */ + [PD_DATA_BATTERY_STATUS] = "D-BATTERY_STATUS", + [PD_DATA_ALERT] = "D-ALERT", + [PD_DATA_GET_COUNTRY_INFO] = "D-GET_COUNTRY_CODES", + /* 8-14 Reserved for REV 3.0 */ + [PD_DATA_ENTER_USB] = "D-ENTER_USB", + [PD_DATA_EPR_REQUEST] = "D-EPR_REQUEST", + [PD_DATA_EPR_MODE] = "D-EPR_MODE", + [PD_DATA_SOURCE_INFO] = "D-EPR_SOURCE_INFO", + [PD_DATA_REVISION] = "D-REVISION", + /* 13-14 Reserved for REV 3.0 */ + [PD_DATA_VENDOR_DEF] = "D-VDM", }; -static const char * const data_msg_name[] = { - [0] = "RSVD-D0", - [PD_DATA_SOURCE_CAP] = "SRCCAP", - [PD_DATA_REQUEST] = "REQUEST", - [PD_DATA_BIST] = "BIST", - [PD_DATA_SINK_CAP] = "SNKCAP", - /* 5-14 Reserved */ - [PD_DATA_VENDOR_DEF] = "VDM", +static const char *const ext_msg_name[] = { + [0] = "X-RSVD_0", + [PD_EXT_SOURCE_CAP] = "X-SRC_CAP", + [PD_EXT_STATUS] = "X-STATUS", + [PD_EXT_GET_BATTERY_CAP] = "X-GET_BATTERY_CAP", + [PD_EXT_GET_BATTERY_STATUS] = "X-GET_BATTERY_STATUS", + [PD_EXT_BATTERY_CAP] = "X-BATTERY_CAP", + [PD_EXT_GET_MANUFACTURER_INFO] = "X-GET_MFR_INFO", + [PD_EXT_MANUFACTURER_INFO] = "X-MFR_INFO", + [PD_EXT_SECURITY_REQUEST] = "X-SECURITY_REQ", + [PD_EXT_SECURITY_RESPONSE] = "X-SECURITY_RESP", + [PD_EXT_FIRMWARE_UPDATE_REQUEST] = "X-FW_UP_REQ", + [PD_EXT_FIRMWARE_UPDATE_RESPONSE] = "X-FW_UP_RESP", + [PD_EXT_PPS_STATUS] = "X-PPS_STATUS", + [PD_EXT_COUNTRY_INFO] = "X-COUNTRY_INFO", + [PD_EXT_COUNTRY_CODES] = "X-COUNTRY_CODES", + [PD_EXT_SINK_CAP] = "X-SNK_CAP", + [PD_EXT_CONTROL] = "X-CONTROL", + [PD_EXT_EPR_SOURCE_CAP] = "X-EPR_SRC_CAP", + [PD_EXT_EPR_SINK_CAP] = "X-EPR_SNK_CAP", }; -static const char * const rev_name[] = { +static const char *const rev_name[] = { [PD_REV10] = "1.0", [PD_REV20] = "2.0", [PD_REV30] = "3.0", [3] = "RSVD", }; -static const char * const drole_name[] = { +static const char *const drole_name[] = { [PD_ROLE_UFP] = "UFP", [PD_ROLE_DFP] = "DFP", }; -static const char * const prole_name[] = { +static const char *const prole_name[] = { [PD_ROLE_SINK] = "SNK", [PD_ROLE_SOURCE] = "SRC", }; static void print_header(const char *prefix, uint16_t header) { - int type = PD_HEADER_TYPE(header); + int type = PD_HEADER_TYPE(header); int drole = PD_HEADER_DROLE(header); - int rev = PD_HEADER_REV(header); + int rev = PD_HEADER_REV(header); int prole = PD_HEADER_PROLE(header); - int id = PD_HEADER_ID(header); - int cnt = PD_HEADER_CNT(header); - int ext = PD_HEADER_EXT(header); - const char *name = cnt ? data_msg_name[type] : ctrl_msg_name[type]; - - ccprints("%s header=0x%x [%s %s %s %s id=%d cnt=%d ext=%d]", - prefix, header, - name, drole_name[drole], rev_name[rev], prole_name[prole], - id, cnt, ext); + int id = PD_HEADER_ID(header); + int cnt = PD_HEADER_CNT(header); + int ext = PD_HEADER_EXT(header); + const char *name = ext ? ext_msg_name[type] : + cnt ? data_msg_name[type] : + ctrl_msg_name[type]; + + ccprints("%s header=0x%x [%s %s %s %s id=%d cnt=%d ext=%d]", prefix, + header, name, drole_name[drole], rev_name[rev], + prole_name[prole], id, cnt, ext); } -static int verify_transmit(enum tcpm_transmit_type want_tx_type, - int want_tx_retry, +static bool dead_battery(void) +{ + return false; +} + +static bool debug_accessory_indicator_supported(void) +{ + return true; +} + +static int verify_transmit(enum tcpci_msg_type want_tx_type, int want_tx_retry, enum pd_ctrl_msg_type want_ctrl_msg, - enum pd_data_msg_type want_data_msg, - int timeout) + enum pd_data_msg_type want_data_msg, int timeout) { uint64_t end_time = get_time().val + timeout; + /* + * Check that nothing was already transmitted. This ensures that all + * transmits are checked, and the test stays in sync with the code + * being tested. + */ TEST_EQ(tcpci_regs[TCPC_REG_TRANSMIT].value, 0, "%d"); + + /* Now wait for the expected message to be transmitted. */ while (get_time().val < end_time) { if (tcpci_regs[TCPC_REG_TRANSMIT].value != 0) { int tx_type = TCPC_REG_TRANSMIT_TYPE( tcpci_regs[TCPC_REG_TRANSMIT].value); int tx_retry = TCPC_REG_TRANSMIT_RETRY( tcpci_regs[TCPC_REG_TRANSMIT].value); - uint16_t header = UINT16_FROM_BYTE_ARRAY_LE( - tx_buffer, 1); - int pd_type = PD_HEADER_TYPE(header); - int pd_cnt = PD_HEADER_CNT(header); + uint16_t header = + UINT16_FROM_BYTE_ARRAY_LE(tx_buffer, 1); + int pd_type = PD_HEADER_TYPE(header); + int pd_cnt = PD_HEADER_CNT(header); TEST_EQ(tx_type, want_tx_type, "%d"); if (want_tx_retry >= 0) @@ -170,6 +232,7 @@ static int verify_transmit(enum tcpm_transmit_type want_tx_type, TEST_EQ(pd_type, want_data_msg, "0x%x"); TEST_GE(pd_cnt, 1, "%d"); } + tcpci_regs[TCPC_REG_TRANSMIT].value = 0; return EC_SUCCESS; } @@ -179,28 +242,123 @@ static int verify_transmit(enum tcpm_transmit_type want_tx_type, return EC_ERROR_UNKNOWN; } -int verify_tcpci_transmit(enum tcpm_transmit_type tx_type, +int verify_tcpci_transmit(enum tcpci_msg_type tx_type, enum pd_ctrl_msg_type ctrl_msg, enum pd_data_msg_type data_msg) { return verify_transmit(tx_type, -1, ctrl_msg, data_msg, VERIFY_TIMEOUT); } -int verify_tcpci_tx_timeout(enum tcpm_transmit_type tx_type, +int verify_tcpci_tx_timeout(enum tcpci_msg_type tx_type, enum pd_ctrl_msg_type ctrl_msg, - enum pd_data_msg_type data_msg, - int timeout) + enum pd_data_msg_type data_msg, int timeout) { return verify_transmit(tx_type, -1, ctrl_msg, data_msg, timeout); } -int verify_tcpci_tx_retry_count(enum tcpm_transmit_type tx_type, - int retry_count) +int verify_tcpci_tx_retry_count(enum tcpci_msg_type tx_type, + enum pd_ctrl_msg_type ctrl_msg, + enum pd_data_msg_type data_msg, int retry_count) { - return verify_transmit(tx_type, retry_count, 0, 0, VERIFY_TIMEOUT); + return verify_transmit(tx_type, retry_count, ctrl_msg, data_msg, + VERIFY_TIMEOUT); +} + +int verify_tcpci_tx_with_data(enum tcpci_msg_type tx_type, + enum pd_data_msg_type data_msg, uint8_t *data, + int data_bytes, int *msg_len, int timeout) +{ + int rv; + + if (timeout <= 0) + timeout = VERIFY_TIMEOUT; + + rv = verify_transmit(tx_type, -1, 0, data_msg, timeout); + if (!rv) { + TEST_NE(data, NULL, "%p"); + TEST_GE(data_bytes, tx_msg_cnt, "%d"); + memcpy(data, tx_buffer, tx_msg_cnt); + if (msg_len) + *msg_len = tx_msg_cnt; + } + return rv; } -void mock_tcpci_receive(enum pd_msg_type sop, uint16_t header, +int verify_tcpci_possible_tx(struct possible_tx possible[], int possible_cnt, + int *found_index, uint8_t *data, int data_bytes, + int *msg_len, int timeout) +{ + bool assert_on_timeout = true; + uint64_t end_time; + + *found_index = -1; + + if (timeout <= 0) { + timeout = VERIFY_TIMEOUT; + assert_on_timeout = false; + } + end_time = get_time().val + timeout; + + /* + * Check that nothing was already transmitted. This ensures that all + * transmits are checked, and the test stays in sync with the code + * being tested. + */ + TEST_EQ(tcpci_regs[TCPC_REG_TRANSMIT].value, 0, "%d"); + + /* Now wait for the expected message to be transmitted. */ + while (get_time().val < end_time) { + if (tcpci_regs[TCPC_REG_TRANSMIT].value != 0) { + int i; + int tx_type = TCPC_REG_TRANSMIT_TYPE( + tcpci_regs[TCPC_REG_TRANSMIT].value); + uint16_t header = + UINT16_FROM_BYTE_ARRAY_LE(tx_buffer, 1); + int pd_type = PD_HEADER_TYPE(header); + int pd_cnt = PD_HEADER_CNT(header); + + for (i = 0; i < possible_cnt; ++i) { + int want_tx_type = possible[i].tx_type; + int want_ctrl_msg = possible[i].ctrl_msg; + int want_data_msg = possible[i].data_msg; + + if (tx_type != want_tx_type) + continue; + + if (want_ctrl_msg != 0) { + if (pd_type != want_ctrl_msg || + pd_cnt != 0) + continue; + } + if (want_data_msg != 0) { + if (pd_type != want_data_msg || + pd_cnt == 0) + continue; + + if (data != NULL) { + TEST_GE(data_bytes, tx_msg_cnt, + "%d"); + memcpy(data, tx_buffer, + tx_msg_cnt); + } + if (msg_len != NULL) + *msg_len = tx_msg_cnt; + } + *found_index = i; + tcpci_regs[TCPC_REG_TRANSMIT].value = 0; + return EC_SUCCESS; + } + return EC_ERROR_UNKNOWN; + } + task_wait_event(5 * MSEC); + } + if (assert_on_timeout) + TEST_ASSERT(0); + + return EC_ERROR_TIMEOUT; +} + +void mock_tcpci_receive(enum tcpci_msg_type sop, uint16_t header, uint32_t *payload) { int i; @@ -217,21 +375,112 @@ void mock_tcpci_receive(enum pd_msg_type sop, uint16_t header, for (i = 4; i < rx_buffer[0]; i += 4) { rx_buffer[i] = *payload & 0xFF; - rx_buffer[i+1] = (*payload >> 8) & 0xFF; - rx_buffer[i+2] = (*payload >> 16) & 0xFF; - rx_buffer[i+3] = (*payload >> 24) & 0xFF; + rx_buffer[i + 1] = (*payload >> 8) & 0xFF; + rx_buffer[i + 2] = (*payload >> 16) & 0xFF; + rx_buffer[i + 3] = (*payload >> 24) & 0xFF; payload++; } rx_pos = 0; } -void mock_tcpci_reset(void) +/***************************************************************************** + * TCPCI register reset values + * + * These values are from USB Type-C Port Controller Interface Specification + * Revision 2.0, Version 1.2, + */ +static void tcpci_reset_register_masks(void) +{ + /* + * Using table 4-1 for default mask values + */ + tcpci_regs[TCPC_REG_ALERT_MASK].value = 0x7FFF; + tcpci_regs[TCPC_REG_POWER_STATUS_MASK].value = 0xFF; + tcpci_regs[TCPC_REG_FAULT_STATUS_MASK].value = 0xFF; + tcpci_regs[TCPC_REG_EXT_STATUS_MASK].value = 0x01; + tcpci_regs[TCPC_REG_ALERT_EXTENDED_MASK].value = 0x07; +} + +static void tcpci_reset_register_defaults(void) { int i; + /* Default all registers to 0 and then overwrite if they are not */ for (i = 0; i < ARRAY_SIZE(tcpci_regs); i++) tcpci_regs[i].value = 0; + + /* Type-C Release 1,3 */ + tcpci_regs[TCPC_REG_TC_REV].value = 0x0013; + /* PD Revision 3.0 Version 1.2 */ + tcpci_regs[TCPC_REG_PD_REV].value = 0x3012; + /* PD Interface Revision 2.0, Version 1.1 */ + tcpci_regs[TCPC_REG_PD_INT_REV].value = 0x2011; + + tcpci_reset_register_masks(); + + tcpci_regs[TCPC_REG_CONFIG_STD_OUTPUT].value = + TCPC_REG_CONFIG_STD_OUTPUT_AUDIO_CONN_N | + TCPC_REG_CONFIG_STD_OUTPUT_DBG_ACC_CONN_N; + + tcpci_regs[TCPC_REG_POWER_CTRL].value = + TCPC_REG_POWER_CTRL_VOLT_ALARM_DIS | + TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS; + + tcpci_regs[TCPC_REG_FAULT_STATUS].value = + TCPC_REG_FAULT_STATUS_ALL_REGS_RESET; + + tcpci_regs[TCPC_REG_DEV_CAP_1].value = + TCPC_REG_DEV_CAP_1_SOURCE_VBUS | TCPC_REG_DEV_CAP_1_SINK_VBUS | + TCPC_REG_DEV_CAP_1_PWRROLE_SRC_SNK_DRP | + TCPC_REG_DEV_CAP_1_SRC_RESISTOR_RP_3P0_1P5_DEF; + + /* + * Using table 4-17 to get the default Role Control and + * Message Header Info register values. + */ + switch (mock_tcpci_get_reg(TCPC_REG_DEV_CAP_1) & + TCPC_REG_DEV_CAP_1_PWRROLE_MASK) { + case TCPC_REG_DEV_CAP_1_PWRROLE_SRC_OR_SNK: + case TCPC_REG_DEV_CAP_1_PWRROLE_SNK: + case TCPC_REG_DEV_CAP_1_PWRROLE_SNK_ACC: + tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0A; + tcpci_regs[TCPC_REG_MSG_HDR_INFO].value = 0x04; + break; + + case TCPC_REG_DEV_CAP_1_PWRROLE_DRP: + if (dead_battery()) + tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0A; + else if (debug_accessory_indicator_supported()) + tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x4A; + else + tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0F; + tcpci_regs[TCPC_REG_MSG_HDR_INFO].value = 0x04; + break; + + case TCPC_REG_DEV_CAP_1_PWRROLE_SRC: + if (!dead_battery()) + tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x05; + tcpci_regs[TCPC_REG_MSG_HDR_INFO].value = 0x0D; + break; + + case TCPC_REG_DEV_CAP_1_PWRROLE_SRC_SNK_DRP_ADPT_CBL: + case TCPC_REG_DEV_CAP_1_PWRROLE_SRC_SNK_DRP: + if (dead_battery()) + tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0A; + else if (debug_accessory_indicator_supported()) + tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x4A; + else + tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0F; + tcpci_regs[TCPC_REG_MSG_HDR_INFO].value = 0x04; + break; + } +} +/*****************************************************************************/ + +void mock_tcpci_reset(void) +{ + tcpci_reset_register_defaults(); } void mock_tcpci_set_reg(int reg_offset, uint16_t value) @@ -239,7 +488,27 @@ void mock_tcpci_set_reg(int reg_offset, uint16_t value) struct tcpci_reg *reg = tcpci_regs + reg_offset; reg->value = value; - ccprints("TCPCI mock set %s = 0x%x", reg->name, reg->value); + ccprints("TCPCI mock set %s = 0x%x", reg->name, reg->value); +} + +void mock_tcpci_set_reg_bits(int reg_offset, uint16_t mask) +{ + struct tcpci_reg *reg = tcpci_regs + reg_offset; + uint16_t old_value = reg->value; + + reg->value |= mask; + ccprints("TCPCI mock set bits %s (mask=0x%x) = 0x%x -> 0x%x", reg->name, + mask, old_value, reg->value); +} + +void mock_tcpci_clr_reg_bits(int reg_offset, uint16_t mask) +{ + struct tcpci_reg *reg = tcpci_regs + reg_offset; + uint16_t old_value = reg->value; + + reg->value &= ~mask; + ccprints("TCPCI mock clr bits %s (mask=0x%x) = 0x%x -> 0x%x", reg->name, + mask, old_value, reg->value); } uint16_t mock_tcpci_get_reg(int reg_offset) @@ -247,9 +516,8 @@ uint16_t mock_tcpci_get_reg(int reg_offset) return tcpci_regs[reg_offset].value; } -int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) +int tcpci_i2c_xfer(int port, uint16_t addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size, int flags) { struct tcpci_reg *reg; @@ -257,8 +525,8 @@ int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags, ccprints("ERROR: wrong I2C port %d", port); return EC_ERROR_UNKNOWN; } - if (slave_addr_flags != MOCK_TCPCI_I2C_ADDR_FLAGS) { - ccprints("ERROR: wrong I2C address 0x%x", slave_addr_flags); + if (addr_flags != MOCK_TCPCI_I2C_ADDR_FLAGS) { + ccprints("ERROR: wrong I2C address 0x%x", addr_flags); return EC_ERROR_UNKNOWN; } @@ -268,10 +536,10 @@ int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags, return EC_ERROR_UNKNOWN; } memcpy(in, rx_buffer + rx_pos, in_size); - rx_pos += in_size; + rx_pos += in_size; if (rx_pos == rx_buffer[0] + 1) { - print_header("RX", UINT16_FROM_BYTE_ARRAY_LE( - rx_buffer, 2)); + print_header("RX", + UINT16_FROM_BYTE_ARRAY_LE(rx_buffer, 2)); rx_pos = -1; } return EC_SUCCESS; @@ -288,10 +556,12 @@ int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags, } memcpy(tx_buffer + tx_pos, out, out_size); tx_pos += out_size; + tx_msg_cnt = tx_pos; if (tx_pos > 0 && tx_pos == tx_buffer[0] + 1) { - print_header("TX", UINT16_FROM_BYTE_ARRAY_LE( - tx_buffer, 1)); + print_header("TX", + UINT16_FROM_BYTE_ARRAY_LE(tx_buffer, 1)); tx_pos = -1; + tx_retry_cnt = -1; } return EC_SUCCESS; } @@ -306,6 +576,7 @@ int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags, return EC_ERROR_UNKNOWN; } tx_pos = 0; + tx_msg_cnt = 0; if (out_size != 1) { ccprints("ERROR: TCPC_REG_TX_BUFFER out_size != 1"); return EC_ERROR_UNKNOWN; @@ -349,8 +620,7 @@ int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags, else if (reg->size == 2) value = out[1] + (out[2] << 8); ccprints("%s TCPCI write %s = 0x%x", - task_get_name(task_get_current()), - reg->name, value); + task_get_name(task_get_current()), reg->name, value); if (reg->offset == TCPC_REG_ALERT) reg->value &= ~value; else @@ -359,3 +629,369 @@ int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags, return EC_SUCCESS; } DECLARE_TEST_I2C_XFER(tcpci_i2c_xfer); + +void tcpci_register_dump(void) +{ + int reg; + int cc1, cc2; + + ccprints("********* TCPCI Register Dump ***********"); + reg = mock_tcpci_get_reg(TCPC_REG_ALERT); + ccprints("TCPC_REG_ALERT = 0x%08X", reg); + if (reg) { + if (reg & BIT(0)) + ccprints("\t0001: CC Status"); + if (reg & BIT(1)) + ccprints("\t0002: Power Status"); + if (reg & BIT(2)) + ccprints("\t0004: Received SOP* Message Status"); + if (reg & BIT(3)) + ccprints("\t0008: Received Hard Reset"); + if (reg & BIT(4)) + ccprints("\t0010: Transmit SOP* Message Failed"); + if (reg & BIT(5)) + ccprints("\t0020: Transmit SOP* Message Discarded"); + if (reg & BIT(6)) + ccprints("\t0040: Transmit SOP* Message Successful"); + if (reg & BIT(7)) + ccprints("\t0080: Vbus Voltage Alarm Hi"); + if (reg & BIT(8)) + ccprints("\t0100: Vbus Voltage Alarm Lo"); + if (reg & BIT(9)) + ccprints("\t0200: Fault"); + if (reg & BIT(10)) + ccprints("\t0400: Rx Buffer Overflow"); + if (reg & BIT(11)) + ccprints("\t0800: Vbus Sink Disconnect Detected"); + if (reg & BIT(12)) + ccprints("\t1000: Beginning SOP* Message Status"); + if (reg & BIT(13)) + ccprints("\t2000: Extended Status"); + if (reg & BIT(14)) + ccprints("\t4000: Alert Extended"); + if (reg & BIT(15)) + ccprints("\t8000: Vendor Defined Alert"); + } + + reg = mock_tcpci_get_reg(TCPC_REG_TCPC_CTRL); + ccprints("TCPC_REG_TCPC_CTRL = 0x%04X", reg); + if (reg & BIT(0)) + ccprints("\t01: Plug Orientation FLIP"); + if (reg & BIT(1)) + ccprints("\t02: BIST Test Mode"); + if (reg & (BIT(2) | BIT(3))) { + switch ((reg >> 2) & 3) { + case 2: + ccprints("\t08: Enable Clock Stretching"); + break; + case 3: + ccprints("\t0C: Enable Clock Stretching if !Alert"); + break; + } + } + if (reg & BIT(4)) + ccprints("\t10: Debug Accessory controlled by TCPM"); + if (reg & BIT(5)) + ccprints("\t20: Watchdog Timer enabled"); + if (reg & BIT(6)) + ccprints("\t40: Looking4Connection Alert enabled"); + if (reg & BIT(7)) + ccprints("\t80: SMBus PEC enabled"); + + reg = mock_tcpci_get_reg(TCPC_REG_ROLE_CTRL); + ccprints("TCPC_REG_ROLE_CTRL = 0x%04X", reg); + cc1 = (reg >> 0) & 3; + switch (cc1) { + case 0: + ccprints("\t00: CC1 == Ra"); + break; + case 1: + ccprints("\t01: CC1 == Rp"); + break; + case 2: + ccprints("\t02: CC1 == Rd"); + break; + case 3: + ccprints("\t03: CC1 == OPEN"); + break; + } + cc2 = (reg >> 2) & 3; + switch (cc2) { + case 0: + ccprints("\t00: CC2 == Ra"); + break; + case 1: + ccprints("\t04: CC2 == Rp"); + break; + case 2: + ccprints("\t08: CC2 == Rd"); + break; + case 3: + ccprints("\t0C: CC2 == OPEN"); + break; + } + switch ((reg >> 4) & 3) { + case 0: + ccprints("\t00: Rp Value == default"); + break; + case 1: + ccprints("\t10: Rp Value == 1.5A"); + break; + case 2: + ccprints("\t20: Rp Value == 3A"); + break; + } + if (reg & BIT(6)) + ccprints("\t40: DRP"); + + reg = mock_tcpci_get_reg(TCPC_REG_FAULT_CTRL); + ccprints("TCPC_REG_FAULT_CTRL = 0x%04X", reg); + if (reg & BIT(0)) + ccprints("\t01: Vconn Over Current Fault"); + if (reg & BIT(1)) + ccprints("\t02: Vbus OVP Fault"); + if (reg & BIT(2)) + ccprints("\t04: Vbus OCP Fault"); + if (reg & BIT(3)) + ccprints("\t08: Vbus Discharge Fault"); + if (reg & BIT(4)) + ccprints("\t10: Force OFF Vbus"); + + reg = mock_tcpci_get_reg(TCPC_REG_POWER_CTRL); + ccprints("TCPC_REG_POWER_CTRL = 0x%04X", reg); + if (reg & BIT(0)) + ccprints("\t01: Enable Vconn"); + if (reg & BIT(1)) + ccprints("\t02: Vconn Power Supported"); + if (reg & BIT(2)) + ccprints("\t04: Force Discharge"); + if (reg & BIT(3)) + ccprints("\t08: Enable Bleed Discharge"); + if (reg & BIT(4)) + ccprints("\t10: Auto Discharge Disconnect"); + if (reg & BIT(5)) + ccprints("\t20: Disable Voltage Alarms"); + if (reg & BIT(6)) + ccprints("\t40: VBUS_VOLTAGE monitor disabled"); + if (reg & BIT(7)) + ccprints("\t80: Fast Role Swap enabled"); + + reg = mock_tcpci_get_reg(TCPC_REG_CC_STATUS); + ccprints("TCPC_REG_CC_STATUS = 0x%04X", reg); + switch ((reg >> 0) & 3) { + case 0: + switch (cc1) { + case 1: + ccprints("\t00: CC1-Rp SRC.Open"); + break; + case 2: + ccprints("\t00: CC1-Rd SNK.Open"); + break; + } + break; + case 1: + switch (cc1) { + case 1: + ccprints("\t01: CC1-Rp SRC.Ra"); + break; + case 2: + ccprints("\t01: CC1-Rd SNK.Default"); + break; + } + break; + case 2: + switch (cc1) { + case 1: + ccprints("\t02: CC1-Rp SRC.Rd"); + break; + case 2: + ccprints("\t02: CC1-Rd SNK.Power1.5"); + break; + } + break; + case 3: + switch (cc1) { + case 2: + ccprints("\t03: CC1-Rd SNK.Power3.0"); + break; + } + break; + } + switch ((reg >> 2) & 3) { + case 0: + switch (cc2) { + case 1: + ccprints("\t00: CC2-Rp SRC.Open"); + break; + case 2: + ccprints("\t00: CC2-Rd SNK.Open"); + break; + } + break; + case 1: + switch (cc2) { + case 1: + ccprints("\t04: CC2-Rp SRC.Ra"); + break; + case 2: + ccprints("\t04: CC2-Rd SNK.Default"); + break; + } + break; + case 2: + switch (cc2) { + case 1: + ccprints("\t08: CC2-Rp SRC.Rd"); + break; + case 2: + ccprints("\t08: CC2-Rd SNK.Power1.5"); + break; + } + break; + case 3: + switch (cc2) { + case 2: + ccprints("\t0C: CC2-Rd SNK.Power3.0"); + break; + } + break; + } + if (reg & BIT(4)) + ccprints("\t10: Presenting Rd"); + else + ccprints("\t00: Presenting Rp"); + if (reg & BIT(5)) + ccprints("\t20: Looking4Connection"); + + reg = mock_tcpci_get_reg(TCPC_REG_POWER_STATUS); + ccprints("TCPC_REG_POWER_STATUS = 0x%04X", reg); + if (reg & BIT(0)) + ccprints("\t01: Sinking Vbus"); + if (reg & BIT(1)) + ccprints("\t02: Vconn Present"); + if (reg & BIT(2)) + ccprints("\t04: Vbus Present"); + if (reg & BIT(3)) + ccprints("\t08: Vbus Detect enabled"); + if (reg & BIT(4)) + ccprints("\t10: Sourcing Vbus"); + if (reg & BIT(5)) + ccprints("\t20: Sourcing non-default voltage"); + if (reg & BIT(6)) + ccprints("\t40: TCPC Initialization"); + if (reg & BIT(7)) + ccprints("\t80: Debug Accessory Connected"); + + reg = mock_tcpci_get_reg(TCPC_REG_FAULT_STATUS); + ccprints("TCPC_REG_FAULT_STATUS = 0x%04X", reg); + if (reg & BIT(0)) + ccprints("\t01: I2C Interface Error"); + if (reg & BIT(1)) + ccprints("\t02: Vconn Over Current Fault"); + if (reg & BIT(2)) + ccprints("\t04: Vbus OVP Fault"); + if (reg & BIT(3)) + ccprints("\t08: Vbus OCP Fault"); + if (reg & BIT(4)) + ccprints("\t10: Forced Discharge Failed"); + if (reg & BIT(5)) + ccprints("\t20: Auto Discharge Failed"); + if (reg & BIT(6)) + ccprints("\t40: Force OFF Vbus"); + if (reg & BIT(7)) + ccprints("\t80: TCPCI Registers Reset2Default"); + + reg = mock_tcpci_get_reg(TCPC_REG_EXT_STATUS); + ccprints("TCPC_REG_EXT_STATUS = 0x%04X", reg); + if (reg & BIT(0)) + ccprints("\t01: Vbus is at vSafe0V"); + + reg = mock_tcpci_get_reg(TCPC_REG_ALERT_EXT); + ccprints("TCPC_REG_ALERT_EXT = 0x%04X", reg); + if (reg & BIT(0)) + ccprints("\t01: SNK Fast Role Swap"); + if (reg & BIT(1)) + ccprints("\t02: SRC Fast Role Swap"); + if (reg & BIT(2)) + ccprints("\t04: Timer Expired"); + + reg = mock_tcpci_get_reg(TCPC_REG_COMMAND); + ccprints("TCPC_REG_COMMAND = 0x%04X", reg); + switch (reg) { + case 0x11: + ccprints("\t11: WakeI2C"); + break; + case 0x22: + ccprints("\t22: DisableVbusDetect"); + break; + case 0x33: + ccprints("\t33: EnableVbusDetect"); + break; + case 0x44: + ccprints("\t44: DisableSinkVbus"); + break; + case 0x55: + ccprints("\t55: SinkVbus"); + break; + case 0x66: + ccprints("\t66: DisableSourceVbus"); + break; + case 0x77: + ccprints("\t77: SourceVbusDefaultVoltage"); + break; + case 0x88: + ccprints("\t88: SourceVbusNondefaultVoltage"); + break; + case 0x99: + ccprints("\t99: Looking4Connection"); + break; + case 0xAA: + ccprints("\tAA: RxOneMore"); + break; + case 0xCC: + ccprints("\tCC: SendFRSwapSignal"); + break; + case 0xDD: + ccprints("\tDD: ResetTransmitBuffer"); + break; + case 0xEE: + ccprints("\tEE: ResetReceiveBuffer"); + break; + case 0xFF: + ccprints("\tFF: I2C Idle"); + break; + } + + reg = mock_tcpci_get_reg(TCPC_REG_MSG_HDR_INFO); + ccprints("TCPC_REG_MSG_HDR_INFO = 0x%04X", reg); + if (reg & BIT(0)) + ccprints("\t01: Power Role SRC"); + else + ccprints("\t00: Power Role SNK"); + switch ((reg >> 1) & 3) { + case 0: + ccprints("\t00: PD Revision 1.0"); + break; + case 1: + ccprints("\t02: PD Revision 2.0"); + break; + case 2: + ccprints("\t04: PD Revision 3.0"); + break; + } + if (reg & BIT(3)) + ccprints("\t08: Data Role DFP"); + else + ccprints("\t00: Data Role UFP"); + if (reg & BIT(4)) + ccprints("\t10: Message originating from Cable Plug"); + else + ccprints("\t00: Message originating from SRC/SNK/DRP"); + + reg = mock_tcpci_get_reg(TCPC_REG_RX_BUFFER); + ccprints("TCPC_REG_RX_BUFFER = 0x%04X", reg); + + reg = mock_tcpci_get_reg(TCPC_REG_TRANSMIT); + ccprints("TCPC_REG_TRANSMIT = 0x%04X", reg); + ccprints("*****************************************"); +} diff --git a/common/mock/tcpm_mock.c b/common/mock/tcpm_mock.c index 81534ad8be..a54b31839b 100644 --- a/common/mock/tcpm_mock.c +++ b/common/mock/tcpm_mock.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,6 +9,10 @@ #include "memory.h" #include "mock/tcpm_mock.h" +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + struct mock_tcpm_t mock_tcpm[CONFIG_USB_PD_PORT_MAX_COUNT]; /** @@ -27,7 +31,7 @@ int tcpm_dequeue_message(int port, uint32_t *payload, int *header) *header = mock_tcpm[port].mock_header; memcpy(payload, mock_tcpm[port].mock_rx_chk_buf, - sizeof(mock_tcpm[port].mock_rx_chk_buf)); + sizeof(mock_tcpm[port].mock_rx_chk_buf)); return EC_SUCCESS; } @@ -47,7 +51,7 @@ void mock_tcpm_reset(void) { int port; - for (port = 0 ; port < CONFIG_USB_PD_PORT_MAX_COUNT ; ++port) + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) mock_tcpm[port].mock_has_pending_message = 0; } @@ -61,7 +65,7 @@ void mock_tcpm_rx_msg(int port, uint16_t header, int cnt, const uint32_t *data) if (cnt > 0) { int idx; - for (idx = 0 ; (idx < cnt) && (idx < MOCK_CHK_BUF_SIZE) ; ++idx) + for (idx = 0; (idx < cnt) && (idx < MOCK_CHK_BUF_SIZE); ++idx) mock_tcpm[port].mock_rx_chk_buf[idx] = data[idx]; } mock_tcpm[port].mock_has_pending_message = 1; diff --git a/common/mock/timer_mock.c b/common/mock/timer_mock.c index 21408b7fe6..0504578412 100644 --- a/common/mock/timer_mock.c +++ b/common/mock/timer_mock.c @@ -1,10 +1,14 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "mock/timer_mock.h" +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + static timestamp_t now; void set_time(timestamp_t now_) diff --git a/common/mock/usb_mux_mock.c b/common/mock/usb_mux_mock.c index 2b9a5296fc..b612f47d4f 100644 --- a/common/mock/usb_mux_mock.c +++ b/common/mock/usb_mux_mock.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,14 +6,18 @@ #include "common.h" #include "console.h" -#include "usb_mux.h" -#include "mock/usb_mux_mock.h" #include "memory.h" +#include "mock/usb_mux_mock.h" +#include "usb_mux.h" #ifndef CONFIG_COMMON_RUNTIME #define cprints(format, args...) #endif +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + /* Public API for controlling/inspecting this mock */ struct mock_usb_mux_ctrl mock_usb_mux; @@ -27,8 +31,12 @@ static int mock_init(const struct usb_mux *me) return EC_SUCCESS; } -static int mock_set(const struct usb_mux *me, mux_state_t mux_state) +static int mock_set(const struct usb_mux *me, mux_state_t mux_state, + bool *ack_required) { + /* Mock does not use host command ACKs */ + *ack_required = false; + mock_usb_mux.state = mux_state; ++mock_usb_mux.num_set_calls; ccprints("[MUX] Set to 0x%02x", mux_state); diff --git a/common/mock/usb_pd_dpm_mock.c b/common/mock/usb_pd_dpm_mock.c index 344d53576d..fee51b3e15 100644 --- a/common/mock/usb_pd_dpm_mock.c +++ b/common/mock/usb_pd_dpm_mock.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,9 +8,20 @@ * Refer to USB PD 3.0 spec, version 2.0, sections 8.2 and 8.3 */ -#include "usb_pd.h" -#include "mock/usb_pd_dpm_mock.h" #include "memory.h" +#include "mock/usb_pd_dpm_mock.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + +__overridable const struct svdm_response svdm_rsp = { + .identity = NULL, + .svids = NULL, + .modes = NULL, +}; struct mock_dpm_port_t dpm[CONFIG_USB_PD_PORT_MAX_COUNT]; @@ -20,23 +31,35 @@ void mock_dpm_reset(void) memset(dpm, 0, sizeof(dpm)); } +void dfp_consume_attention(int port, uint32_t *payload) +{ +} + +void pd_prepare_sysjump(void) +{ +} + void dpm_init(int port) { dpm[port].mode_entry_done = false; dpm[port].mode_exit_request = false; } -void dpm_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, - uint32_t *vdm) +void dpm_mode_exit_complete(int port) { } -void dpm_vdm_naked(int port, enum tcpm_transmit_type type, uint16_t svid, - uint8_t vdm_cmd) +void dpm_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count, + uint32_t *vdm) { } -void dpm_set_mode_entry_done(int port) +void dpm_vdm_naked(int port, enum tcpci_msg_type type, uint16_t svid, + uint8_t vdm_cmd, uint32_t vdm_header) +{ +} + +void dpm_notify_attention(int port, size_t vdo_objects, uint32_t *buf) { } @@ -44,6 +67,53 @@ void dpm_set_mode_exit_request(int port) { } -void dpm_run(int port) +void dpm_run(int port, int evt, int en) +{ +} + +void dpm_evaluate_sink_fixed_pdo(int port, uint32_t vsafe5v_pdo) +{ +} + +void dpm_add_non_pd_sink(int port) +{ +} + +void dpm_evaluate_request_rdo(int port, uint32_t rdo) +{ +} + +void dpm_remove_sink(int port) +{ +} + +void dpm_remove_source(int port) +{ +} + +void dpm_bist_shared_mode_enter(int port) +{ +} + +void dpm_bist_shared_mode_exit(int port) +{ +} + +int dpm_get_source_pdo(const uint32_t **src_pdo, const int port) +{ + *src_pdo = pd_src_pdo; + return pd_src_pdo_cnt; +} + +int dpm_get_status_msg(int port, uint8_t *msg, uint32_t *len) +{ + return EC_SUCCESS; +} + +void dpm_handle_alert(int port, uint32_t ado) +{ +} + +void dpm_set_pe_ready(int port, bool enable) { } diff --git a/common/mock/usb_pd_mock.c b/common/mock/usb_pd_mock.c deleted file mode 100644 index 653c98c78e..0000000000 --- a/common/mock/usb_pd_mock.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Mock USB Type-C PD */ - -#include "common.h" -#include "console.h" -#include "usb_pd.h" -#include "mock/usb_pd_mock.h" -#include "memory.h" - -struct mock_pd_port_t mock_pd_port[CONFIG_USB_PD_PORT_MAX_COUNT]; - -void mock_pd_reset(void) -{ - /* Reset all values to 0. */ - memset(mock_pd_port, 0, sizeof(mock_pd_port)); -} - -enum pd_dual_role_states pd_get_dual_role(int port) -{ - return PD_DRP_TOGGLE_ON; -} - -enum pd_data_role pd_get_data_role(int port) -{ - return mock_pd_port[port].data_role; -} - -enum pd_power_role pd_get_power_role(int port) -{ - return mock_pd_port[port].power_role; -} - -enum pd_cc_states pd_get_task_cc_state(int port) -{ - return PD_CC_NONE; -} - -int pd_is_connected(int port) -{ - return 1; -} - -bool pd_is_disconnected(int port) -{ - return false; -} - -__overridable const uint32_t * const pd_get_src_caps(int port) -{ - return NULL; -} - -__overridable uint8_t pd_get_src_cap_cnt(int port) -{ - return 0; -} - -__overridable void pd_set_src_caps(int port, int cnt, uint32_t *src_caps) -{ -} - -bool pd_get_partner_usb_comm_capable(int port) -{ - return true; -} - -inline uint8_t board_get_usb_pd_port_count(void) -{ - return CONFIG_USB_PD_PORT_MAX_COUNT; -} - -void pd_set_suspend(int port, int suspend) -{ -} - -enum tcpc_cc_polarity pd_get_polarity(int port) -{ - return POLARITY_CC1; -} - -void pd_request_data_swap(int port) -{} - -void pd_request_vconn_swap_off(int port) -{} - -void pd_request_vconn_swap_on(int port) -{} - -bool pd_alt_mode_capable(int port) -{ - return false; -} diff --git a/common/mock/usb_pe_sm_mock.c b/common/mock/usb_pe_sm_mock.c index a62f9709f5..38df938c46 100644 --- a/common/mock/usb_pe_sm_mock.c +++ b/common/mock/usb_pe_sm_mock.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,18 +7,22 @@ #include "common.h" #include "console.h" -#include "usb_pe_sm.h" -#include "mock/usb_pe_sm_mock.h" #include "memory.h" +#include "mock/usb_pe_sm_mock.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usb_pe_sm.h" #ifndef CONFIG_COMMON_RUNTIME #define cprints(format, args...) #endif +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif struct mock_pe_port_t mock_pe_port[CONFIG_USB_PD_PORT_MAX_COUNT]; - /** * Resets all mock PE ports to initial values */ @@ -26,7 +30,7 @@ void mock_pe_port_reset(void) { int port; - for (port = 0 ; port < CONFIG_USB_PD_PORT_MAX_COUNT ; ++port) { + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) { mock_pe_port[port].mock_pe_error = -1; /* These mock variable only get set to 1 by various functions, * so initialize them to 0. Tests can verify they are still 0 @@ -41,7 +45,7 @@ void mock_pe_port_reset(void) } } -void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type) +void pe_report_error(int port, enum pe_error e, enum tcpci_msg_type type) { mock_pe_port[port].mock_pe_error = e; mock_pe_port[port].sop = type; @@ -77,9 +81,40 @@ void pe_got_soft_reset(int port) mock_pe_port[port].mock_got_soft_reset = 1; } +bool pe_in_frs_mode(int port) +{ + return false; +} + bool pe_in_local_ams(int port) { /* We will probably want to change this in the future */ return false; } +const uint32_t *const pd_get_src_caps(int port) +{ + return NULL; +} + +uint8_t pd_get_src_cap_cnt(int port) +{ + return 0; +} + +void pd_set_src_caps(int port, int cnt, uint32_t *src_caps) +{ +} + +void pd_request_power_swap(int port) +{ +} + +int pd_get_rev(int port, enum tcpci_msg_type type) +{ + return IS_ENABLED(CONFIG_USB_PD_REV30) ? PD_REV30 : PD_REV20; +} + +void pe_invalidate_explicit_contract(int port) +{ +} diff --git a/common/mock/usb_prl_mock.c b/common/mock/usb_prl_mock.c index b682e67f80..e69ad38712 100644 --- a/common/mock/usb_prl_mock.c +++ b/common/mock/usb_prl_mock.c @@ -1,15 +1,24 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * - * Fake Protocol Layer module. + * Mock Protocol Layer module. */ -#include #include "common.h" +#include "mock/usb_prl_mock.h" +#include "task.h" +#include "test_util.h" +#include "timer.h" #include "usb_emsg.h" +#include "usb_pd_tcpm.h" #include "usb_pe_sm.h" #include "usb_prl_sm.h" -#include "mock/usb_prl_mock.h" + +#include + +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif /* Defaults should all be 0 values. */ struct extended_msg rx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT]; @@ -17,10 +26,12 @@ struct extended_msg tx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT]; struct mock_prl_port_t { enum pd_ctrl_msg_type last_ctrl_msg; - enum pd_data_msg_type last_data_msg_type; + enum pd_data_msg_type last_data_msg; + enum tcpci_msg_type last_tx_type; bool message_sent; bool message_received; - int pe_error; + enum pe_error error; + enum tcpci_msg_type error_tx_type; }; struct mock_prl_port_t mock_prl_port[CONFIG_USB_PD_PORT_MAX_COUNT]; @@ -35,23 +46,35 @@ void mock_prl_reset(void) memset(mock_prl_port, 0, sizeof(mock_prl_port)); - for (port = 0 ; port < CONFIG_USB_PD_PORT_MAX_COUNT ; ++port) - mock_prl_port[port].pe_error = -1; + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) { + mock_prl_port[port].last_tx_type = TCPCI_MSG_INVALID; + mock_prl_port[port].error_tx_type = TCPCI_MSG_INVALID; + } } void prl_end_ams(int port) -{} +{ +} void prl_execute_hard_reset(int port) -{} +{ + mock_prl_port[port].last_ctrl_msg = 0; + mock_prl_port[port].last_data_msg = 0; + mock_prl_port[port].last_tx_type = TCPCI_MSG_TX_HARD_RESET; +} -enum pd_rev_type prl_get_rev(int port, enum tcpm_transmit_type partner) +void prl_set_data_role_check(int port, bool enable) +{ +} + +enum pd_rev_type prl_get_rev(int port, enum tcpci_msg_type partner) { return PD_REV30; } void prl_hard_reset_complete(int port) -{} +{ +} int prl_is_running(int port) { @@ -63,72 +86,101 @@ __overridable bool prl_is_busy(int port) return false; } -void prl_reset(int port) -{} - void prl_reset_soft(int port) -{} +{ +} -void prl_send_ctrl_msg(int port, enum tcpm_transmit_type type, - enum pd_ctrl_msg_type msg) +void prl_send_ctrl_msg(int port, enum tcpci_msg_type type, + enum pd_ctrl_msg_type msg) { mock_prl_port[port].last_ctrl_msg = msg; + mock_prl_port[port].last_data_msg = 0; + mock_prl_port[port].last_tx_type = type; } -void prl_send_data_msg(int port, enum tcpm_transmit_type type, - enum pd_data_msg_type msg) +void prl_send_data_msg(int port, enum tcpci_msg_type type, + enum pd_data_msg_type msg) { - mock_prl_port[port].last_data_msg_type = msg; + mock_prl_port[port].last_data_msg = msg; + mock_prl_port[port].last_ctrl_msg = 0; + mock_prl_port[port].last_tx_type = type; } -void prl_send_ext_data_msg(int port, enum tcpm_transmit_type type, - enum pd_ext_msg_type msg) -{} +void prl_send_ext_data_msg(int port, enum tcpci_msg_type type, + enum pd_ext_msg_type msg) +{ +} -void prl_set_rev(int port, enum tcpm_transmit_type partner, - enum pd_rev_type rev) -{} +void prl_set_rev(int port, enum tcpci_msg_type partner, enum pd_rev_type rev) +{ +} +int mock_prl_wait_for_tx_msg(int port, enum tcpci_msg_type tx_type, + enum pd_ctrl_msg_type ctrl_msg, + enum pd_data_msg_type data_msg, int timeout) +{ + uint64_t end_time = get_time().val + timeout; + + while (get_time().val < end_time) { + if (mock_prl_port[port].last_tx_type != TCPCI_MSG_INVALID) { + TEST_EQ(mock_prl_port[port].last_tx_type, tx_type, + "%d"); + TEST_EQ(mock_prl_port[port].last_ctrl_msg, ctrl_msg, + "%d"); + TEST_EQ(mock_prl_port[port].last_data_msg, data_msg, + "%d"); + mock_prl_clear_last_sent_msg(port); + return EC_SUCCESS; + } + task_wait_event(5 * MSEC); + } + /* A message of the expected type should have been sent by end_time. */ + TEST_ASSERT(0); + return EC_ERROR_UNKNOWN; +} -enum pd_ctrl_msg_type fake_prl_get_last_sent_ctrl_msg(int port) +enum pd_ctrl_msg_type mock_prl_get_last_sent_ctrl_msg(int port) { enum pd_ctrl_msg_type last = mock_prl_port[port].last_ctrl_msg; - fake_prl_clear_last_sent_ctrl_msg(port); + mock_prl_clear_last_sent_msg(port); return last; } -void fake_prl_clear_last_sent_ctrl_msg(int port) -{ - mock_prl_port[port].last_ctrl_msg = 0; -} - -enum pd_data_msg_type fake_prl_get_last_sent_data_msg_type(int port) +enum pd_data_msg_type mock_prl_get_last_sent_data_msg(int port) { - enum pd_data_msg_type last = mock_prl_port[port].last_data_msg_type; + enum pd_data_msg_type last = mock_prl_port[port].last_data_msg; - fake_prl_clear_last_sent_data_msg(port); + mock_prl_clear_last_sent_msg(port); return last; } -void fake_prl_clear_last_sent_data_msg(int port) +void mock_prl_clear_last_sent_msg(int port) { - mock_prl_port[port].last_data_msg_type = 0; + mock_prl_port[port].last_data_msg = 0; + mock_prl_port[port].last_ctrl_msg = 0; + mock_prl_port[port].last_tx_type = TCPCI_MSG_INVALID; } -void fake_prl_message_sent(int port) +timestamp_t prl_get_tcpc_tx_success_ts(int port) +{ + return get_time(); +} +void mock_prl_message_sent(int port) { mock_prl_port[port].message_sent = 1; } -void fake_prl_message_received(int port) +void mock_prl_message_received(int port) { mock_prl_port[port].message_received = 1; } -void fake_prl_report_error(int port, enum pe_error e) +void mock_prl_report_error(int port, enum pe_error e, + enum tcpci_msg_type tx_type) { - mock_prl_port[port].pe_error = e; + mock_prl_port[port].error = e; + mock_prl_port[port].error_tx_type = tx_type; } void prl_run(int port, int evt, int en) @@ -143,11 +195,11 @@ void prl_run(int port, int evt, int en) pe_message_received(port); mock_prl_port[port].message_received = 0; } - if (mock_prl_port[port].pe_error >= 0) { - ccprints("pe_error %d", mock_prl_port[port].pe_error); - pe_report_error(port, - mock_prl_port[port].pe_error, - TCPC_TX_SOP); - mock_prl_port[port].pe_error = -1; + if (mock_prl_port[port].error_tx_type != TCPCI_MSG_INVALID) { + ccprints("pe_error %d", mock_prl_port[port].error); + pe_report_error(port, mock_prl_port[port].error, + mock_prl_port[port].error_tx_type); + mock_prl_port[port].error = 0; + mock_prl_port[port].error_tx_type = TCPCI_MSG_INVALID; } } diff --git a/common/mock/usb_tc_sm_mock.c b/common/mock/usb_tc_sm_mock.c index dfe8eeef48..6adf6b3246 100644 --- a/common/mock/usb_tc_sm_mock.c +++ b/common/mock/usb_tc_sm_mock.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,29 +7,37 @@ #include "common.h" #include "console.h" -#include "usb_tc_sm.h" -#include "mock/usb_tc_sm_mock.h" +#include "ec_commands.h" #include "memory.h" +#include "mock/usb_tc_sm_mock.h" +#include "usb_tc_sm.h" #ifndef CONFIG_COMMON_RUNTIME #define cprints(format, args...) #endif +#ifndef TEST_BUILD +#error "Mocks should only be in the test build." +#endif + struct mock_tc_port_t mock_tc_port[CONFIG_USB_PD_PORT_MAX_COUNT]; void mock_tc_port_reset(void) { int port; - for (port = 0 ; port < CONFIG_USB_PD_PORT_MAX_COUNT ; ++port) { + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) { mock_tc_port[port].rev = PD_REV30; mock_tc_port[port].pd_enable = 0; mock_tc_port[port].msg_tx_id = 0; mock_tc_port[port].msg_rx_id = 0; - mock_tc_port[port].sop = TCPC_TX_INVALID; + mock_tc_port[port].sop = TCPCI_MSG_INVALID; mock_tc_port[port].lcl_rp = TYPEC_RP_RESERVED; mock_tc_port[port].attached_snk = 0; mock_tc_port[port].attached_src = 0; + mock_tc_port[port].vconn_src = false; + mock_tc_port[port].data_role = PD_ROLE_UFP; + mock_tc_port[port].power_role = PD_ROLE_SINK; } } @@ -48,6 +56,10 @@ void typec_select_src_collision_rp(int port, enum tcpc_rp_value rp) mock_tc_port[port].lcl_rp = rp; } +void typec_select_src_current_limit_rp(int port, enum tcpc_rp_value rp) +{ +} + int tc_is_attached_src(int port) { return mock_tc_port[port].attached_src; @@ -81,11 +93,12 @@ int tc_check_vconn_swap(int port) } void tc_ctvpd_detected(int port) -{} +{ +} int tc_is_vconn_src(int port) { - return 0; + return mock_tc_port[port].vconn_src; } void tc_hard_reset_request(int port) @@ -94,32 +107,121 @@ void tc_hard_reset_request(int port) } void tc_partner_dr_data(int port, int en) -{} +{ +} void tc_partner_dr_power(int port, int en) -{} +{ +} void tc_partner_unconstrainedpower(int port, int en) -{} +{ +} void tc_partner_usb_comm(int port, int en) -{} +{ +} void tc_pd_connection(int port, int en) -{} +{ +} void tc_pr_swap_complete(int port, bool success) -{} +{ +} void tc_src_power_off(int port) -{} +{ +} void tc_start_error_recovery(int port) -{} +{ +} void tc_snk_power_off(int port) -{} +{ +} void tc_request_power_swap(int port) { } + +enum pd_dual_role_states pd_get_dual_role(int port) +{ + return PD_DRP_TOGGLE_ON; +} + +enum pd_data_role pd_get_data_role(int port) +{ + return mock_tc_port[port].data_role; +} + +enum pd_power_role pd_get_power_role(int port) +{ + return mock_tc_port[port].power_role; +} + +enum pd_cc_states pd_get_task_cc_state(int port) +{ + return PD_CC_NONE; +} + +int pd_is_connected(int port) +{ + return 1; +} + +bool pd_is_disconnected(int port) +{ + return false; +} + +bool pd_get_partner_usb_comm_capable(int port) +{ + return true; +} + +bool pd_get_partner_dual_role_power(int port) +{ + return true; +} + +bool pd_capable(int port) +{ + return true; +} + +bool pd_waiting_on_partner_src_caps(int port) +{ + return false; +} + +void pd_set_suspend(int port, int suspend) +{ +} + +void pd_set_error_recovery(int port) +{ +} + +enum tcpc_cc_polarity pd_get_polarity(int port) +{ + return POLARITY_CC1; +} + +void pd_request_data_swap(int port) +{ +} + +void pd_request_vconn_swap_off(int port) +{ +} + +void pd_request_vconn_swap_on(int port) +{ +} + +bool pd_alt_mode_capable(int port) +{ + return false; +} diff --git a/common/motion_lid.c b/common/motion_lid.c index bdef89f3b7..878d471ed4 100644 --- a/common/motion_lid.c +++ b/common/motion_lid.c @@ -1,12 +1,12 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Motion sense module to read from various motion sensors. */ -#include "acpi.h" #include "accelgyro.h" +#include "acpi.h" #include "chipset.h" #include "common.h" #include "console.h" @@ -20,14 +20,14 @@ #include "motion_sense.h" #include "power.h" #include "tablet_mode.h" -#include "timer.h" #include "task.h" +#include "timer.h" #include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_MOTION_LID, outstr) -#define CPRINTS(format, args...) cprints(CC_MOTION_LID, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_MOTION_LID, format, ## args) +#define CPRINTS(format, args...) cprints(CC_MOTION_LID, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_MOTION_LID, format, ##args) #ifdef CONFIG_TABLET_MODE /* Previous lid_angle. */ @@ -50,7 +50,7 @@ static int lid_angle_is_reliable; static intv3_t smoothed_base, smoothed_lid; /* 8.7 m/s^2 is the the maximum acceleration parallel to the hinge */ -#define SCALED_HINGE_VERTICAL_MAXIMUM \ +#define SCALED_HINGE_VERTICAL_MAXIMUM \ ((int)((8.7f * MOTION_SCALING_FACTOR) / MOTION_ONE_G)) #define SCALED_HINGE_VERTICAL_SMOOTHING_START \ @@ -78,7 +78,7 @@ static intv3_t smoothed_base, smoothed_lid; * is less than 1<<31, so magnitude is less sqrt(2)*(1<<15), less than ~40% over * 1g. This is way above any usable noise. Assume noise is less than 10%. */ -#define MOTION_SCALING_AXIS_MAX (MOTION_SCALING_FACTOR * 110) +#define MOTION_SCALING_AXIS_MAX ((MOTION_SCALING_FACTOR * 110) / 100) #define MOTION_SCALING_FACTOR2 (MOTION_SCALING_FACTOR * MOTION_SCALING_FACTOR) @@ -88,18 +88,27 @@ static intv3_t smoothed_base, smoothed_lid; * frame before calculating lid angle). */ #ifdef CONFIG_ACCEL_STD_REF_FRAME_OLD -static const intv3_t hinge_axis = { 0, 1, 0}; +static const intv3_t hinge_axis = { 0, 1, 0 }; #define HINGE_AXIS Y #else -static const intv3_t hinge_axis = { 1, 0, 0}; +static const intv3_t hinge_axis = { 1, 0, 0 }; #define HINGE_AXIS X #endif -static const struct motion_sensor_t * const accel_base = +static const struct motion_sensor_t *const accel_base = &motion_sensors[CONFIG_LID_ANGLE_SENSOR_BASE]; -static const struct motion_sensor_t * const accel_lid = +static const struct motion_sensor_t *const accel_lid = &motion_sensors[CONFIG_LID_ANGLE_SENSOR_LID]; +STATIC_IF(CONFIG_TABLET_MODE) void motion_lid_set_tablet_mode(int reliable); +STATIC_IF(CONFIG_TABLET_MODE) +int lid_angle_set_tablet_mode_threshold(int angle, int hys); + +STATIC_IF(CONFIG_TABLET_MODE) fp_t tablet_zone_lid_angle; +STATIC_IF(CONFIG_TABLET_MODE) fp_t laptop_zone_lid_angle; +STATIC_IF(CONFIG_TABLET_MODE) int tablet_mode_lid_angle; +STATIC_IF(CONFIG_TABLET_MODE) int tablet_mode_hys_degree; + #ifdef CONFIG_TABLET_MODE __attribute__((weak)) int board_is_lid_angle_tablet_mode(void) { @@ -133,18 +142,16 @@ __attribute__((weak)) int board_is_lid_angle_tablet_mode(void) * by using MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE. */ -#define DEFAULT_TABLET_MODE_ANGLE (180) -#define DEFAULT_TABLET_MODE_HYS (20) +#define DEFAULT_TABLET_MODE_ANGLE (180) +#define DEFAULT_TABLET_MODE_HYS (20) -#define TABLET_ZONE_ANGLE(a, h) ((a) + (h)) -#define LAPTOP_ZONE_ANGLE(a, h) ((a) - (h)) +#define TABLET_ZONE_ANGLE(a, h) ((a) + (h)) +#define LAPTOP_ZONE_ANGLE(a, h) ((a) - (h)) -static fp_t tablet_zone_lid_angle = - FLOAT_TO_FP(TABLET_ZONE_ANGLE(DEFAULT_TABLET_MODE_ANGLE, - DEFAULT_TABLET_MODE_HYS)); -static fp_t laptop_zone_lid_angle = - FLOAT_TO_FP(LAPTOP_ZONE_ANGLE(DEFAULT_TABLET_MODE_ANGLE, - DEFAULT_TABLET_MODE_HYS)); +static fp_t tablet_zone_lid_angle = FLOAT_TO_FP( + TABLET_ZONE_ANGLE(DEFAULT_TABLET_MODE_ANGLE, DEFAULT_TABLET_MODE_HYS)); +static fp_t laptop_zone_lid_angle = FLOAT_TO_FP( + LAPTOP_ZONE_ANGLE(DEFAULT_TABLET_MODE_ANGLE, DEFAULT_TABLET_MODE_HYS)); static int tablet_mode_lid_angle = DEFAULT_TABLET_MODE_ANGLE; static int tablet_mode_hys_degree = DEFAULT_TABLET_MODE_HYS; @@ -167,7 +174,7 @@ static void motion_lid_set_tablet_mode(int reliable) /* Alright, we're convinced. */ tablet_mode_debounce_cnt = TABLET_MODE_DEBOUNCE_COUNT; - tablet_set_mode(new_mode); + tablet_set_mode(new_mode, TABLET_TRIGGER_LID); return; } tablet_mode_debounce_cnt--; @@ -208,7 +215,13 @@ static int lid_angle_set_tablet_mode_threshold(int angle, int hys) #if defined(CONFIG_DPTF_MULTI_PROFILE) && \ defined(CONFIG_DPTF_MOTION_LID_NO_GMR_SENSOR) +#define MOTION_LID_SET_DPTF_PROFILE +#endif + +STATIC_IF(MOTION_LID_SET_DPTF_PROFILE) +void motion_lid_set_dptf_profile(int reliable); +#ifdef MOTION_LID_SET_DPTF_PROFILE /* * If CONFIG_DPTF_MULTI_PROFILE is defined by a board, then lid motion driver * sets different profile numbers depending upon the current lid @@ -264,7 +277,7 @@ static void motion_lid_set_dptf_profile(int reliable) debounce_cnt = DPTF_MODE_DEBOUNCE_COUNT; } -#endif /* CONFIG_DPTF_MULTI_PROFILE && CONFIG_DPTF_MOTION_LID_NO_GMR_SENSOR */ +#endif /* MOTION_LID_SET_DPTF_PROFILE */ /** * Calculate the lid angle using two acceleration vectors, one recorded in @@ -292,10 +305,8 @@ static int calculate_lid_angle(const intv3_t base, const intv3_t lid, * possible. */ for (i = X; i <= Z; i++) { - scaled_base[i] = base[i] * - accel_base->drv->get_range(accel_base); - scaled_lid[i] = lid[i] * - accel_lid->drv->get_range(accel_lid); + scaled_base[i] = base[i] * accel_base->current_range; + scaled_lid[i] = lid[i] * accel_lid->current_range; if (ABS(scaled_base[i]) > MOTION_SCALING_AXIS_MAX || ABS(scaled_lid[i]) > MOTION_SCALING_AXIS_MAX) { reliable = 0; @@ -309,11 +320,11 @@ static int calculate_lid_angle(const intv3_t base, const intv3_t lid, * less than 1<<30. */ base_magnitude2 = scaled_base[X] * scaled_base[X] + - scaled_base[Y] * scaled_base[Y] + - scaled_base[Z] * scaled_base[Z]; + scaled_base[Y] * scaled_base[Y] + + scaled_base[Z] * scaled_base[Z]; lid_magnitude2 = scaled_lid[X] * scaled_lid[X] + - scaled_lid[Y] * scaled_lid[Y] + - scaled_lid[Z] * scaled_lid[Z]; + scaled_lid[Y] * scaled_lid[Y] + + scaled_lid[Z] * scaled_lid[Z]; /* * Check to see if they differ than more than NOISY_MAGNITUDE_DEVIATION. @@ -345,14 +356,16 @@ static int calculate_lid_angle(const intv3_t base, const intv3_t lid, goto end_calculate_lid_angle; } - largest_hinge_accel = MAX(ABS(scaled_base[HINGE_AXIS]), - ABS(scaled_lid[HINGE_AXIS])); + largest_hinge_accel = + MAX(ABS(scaled_base[HINGE_AXIS]), ABS(scaled_lid[HINGE_AXIS])); - smoothed_ratio = MAX(INT_TO_FP(0), MIN(INT_TO_FP(1), - fp_div(INT_TO_FP(largest_hinge_accel - - SCALED_HINGE_VERTICAL_SMOOTHING_START), - INT_TO_FP(SCALED_HINGE_VERTICAL_MAXIMUM - - SCALED_HINGE_VERTICAL_SMOOTHING_START)))); + smoothed_ratio = MAX( + INT_TO_FP(0), + MIN(INT_TO_FP(1), + fp_div(INT_TO_FP(largest_hinge_accel - + SCALED_HINGE_VERTICAL_SMOOTHING_START), + INT_TO_FP(SCALED_HINGE_VERTICAL_MAXIMUM - + SCALED_HINGE_VERTICAL_SMOOTHING_START)))); /* Check hinge is not too vertical */ if (largest_hinge_accel > SCALED_HINGE_VERTICAL_MAXIMUM) { @@ -389,15 +402,14 @@ static int calculate_lid_angle(const intv3_t base, const intv3_t lid, if (dot_product(cross, hinge_axis) > 0) lid_to_base_fp = FLOAT_TO_FP(360) - lid_to_base_fp; -#ifndef CONFIG_ACCEL_STD_REF_FRAME_OLD /* * Angle is between the keyboard and the front of screen: we need to * anlge between keyboard and back of screen: * 180 instead of 0 when lid and base are flat on surface. * 0 instead of 180 when lid is closed on keyboard. */ - lid_to_base_fp = FLOAT_TO_FP(180) - lid_to_base_fp; -#endif + if (!IS_ENABLED(CONFIG_ACCEL_STD_REF_FRAME_OLD)) + lid_to_base_fp = FLOAT_TO_FP(180) - lid_to_base_fp; /* Place lid angle between 0 and 360 degrees. */ if (lid_to_base_fp < 0) @@ -405,8 +417,7 @@ static int calculate_lid_angle(const intv3_t base, const intv3_t lid, #ifdef CONFIG_TABLET_MODE /* Ignore large angles when the lid is closed. */ - if (!lid_is_open() && - (lid_to_base_fp > SMALL_LID_ANGLE_RANGE)) { + if (!lid_is_open() && (lid_to_base_fp > SMALL_LID_ANGLE_RANGE)) { reliable = 0; goto end_calculate_lid_angle; } @@ -422,8 +433,7 @@ static int calculate_lid_angle(const intv3_t base, const intv3_t lid, * may wake us up. This is because we require at least 4 consecutive * reliable readings over a threshold to disable key scanning. */ - if (lid_is_open() && - (lid_to_base_fp <= SMALL_LID_ANGLE_RANGE)) { + if (lid_is_open() && (lid_to_base_fp <= SMALL_LID_ANGLE_RANGE)) { reliable = 0; goto end_calculate_lid_angle; } @@ -439,10 +449,8 @@ static int calculate_lid_angle(const intv3_t base, const intv3_t lid, * prove the small angle we see is correct so we take the angle * as is. */ - if ((last_lid_angle_fp >= - FLOAT_TO_FP(360) - DEBOUNCE_ANGLE_DELTA) && - (lid_to_base_fp <= DEBOUNCE_ANGLE_DELTA) && - (lid_is_open())) + if ((last_lid_angle_fp >= FLOAT_TO_FP(360) - DEBOUNCE_ANGLE_DELTA) && + (lid_to_base_fp <= DEBOUNCE_ANGLE_DELTA) && (lid_is_open())) last_lid_angle_fp = FLOAT_TO_FP(360) - lid_to_base_fp; else last_lid_angle_fp = lid_to_base_fp; @@ -457,12 +465,9 @@ static int calculate_lid_angle(const intv3_t base, const intv3_t lid, if (board_is_lid_angle_tablet_mode()) motion_lid_set_tablet_mode(reliable); -#if defined(CONFIG_DPTF_MULTI_PROFILE) && \ - defined(CONFIG_DPTF_MOTION_LID_NO_GMR_SENSOR) - motion_lid_set_dptf_profile(reliable); -#endif /* CONFIG_DPTF_MULTI_PROFILE && CONFIG_DPTF_MOTION_LID_NO_GMR_SENSOR */ - -#else /* CONFIG_TABLET_MODE */ + if (IS_ENABLED(MOTION_LID_SET_DPTF_PROFILE)) + motion_lid_set_dptf_profile(reliable); +#else /* CONFIG_TABLET_MODE */ end_calculate_lid_angle: if (reliable) *lid_angle = FP_TO_INT(lid_to_base_fp + FLOAT_TO_FP(0.5)); @@ -485,18 +490,22 @@ void motion_lid_calc(void) { /* Calculate angle of lid accel. */ lid_angle_is_reliable = calculate_lid_angle( - accel_base->xyz, accel_lid->xyz, - &lid_angle_deg); + accel_base->xyz, accel_lid->xyz, &lid_angle_deg); -#ifdef CONFIG_LID_ANGLE_UPDATE - lid_angle_update(motion_lid_get_angle()); -#endif + if (IS_ENABLED(CONFIG_LID_ANGLE_UPDATE)) + lid_angle_update(motion_lid_get_angle()); } /*****************************************************************************/ /* Host commands */ - +/** + * @brief This is a "sub"-host command accessed through EC_CMD_MOTION_SENSE_CMD, + * defined in `common/motion_sense.c` + * + * @param args Hot command args + * @return enum ec_status Exit status + */ enum ec_status host_cmd_motion_lid(struct host_cmd_handler_args *args) { const struct ec_params_motion_sense *in = args->params; @@ -504,35 +513,38 @@ enum ec_status host_cmd_motion_lid(struct host_cmd_handler_args *args) switch (in->cmd) { case MOTIONSENSE_CMD_KB_WAKE_ANGLE: -#ifdef CONFIG_LID_ANGLE_UPDATE - /* Set new keyboard wake lid angle if data arg has value. */ - if (in->kb_wake_angle.data != EC_MOTION_SENSE_NO_VALUE) - lid_angle_set_wake_angle(in->kb_wake_angle.data); - - out->kb_wake_angle.ret = lid_angle_get_wake_angle(); -#else - out->kb_wake_angle.ret = 0; -#endif + if (IS_ENABLED(CONFIG_LID_ANGLE_UPDATE)) { + /* + * Set new keyboard wake lid angle if data arg has + * value. + */ + if (in->kb_wake_angle.data != EC_MOTION_SENSE_NO_VALUE) + lid_angle_set_wake_angle( + in->kb_wake_angle.data); + + out->kb_wake_angle.ret = lid_angle_get_wake_angle(); + } else { + out->kb_wake_angle.ret = 0; + } args->response_size = sizeof(out->kb_wake_angle); break; case MOTIONSENSE_CMD_LID_ANGLE: -#ifdef CONFIG_LID_ANGLE - out->lid_angle.value = motion_lid_get_angle(); - args->response_size = sizeof(out->lid_angle); -#else - return EC_RES_INVALID_PARAM; -#endif + if (IS_ENABLED(CONFIG_LID_ANGLE)) { + out->lid_angle.value = motion_lid_get_angle(); + args->response_size = sizeof(out->lid_angle); + } else { + return EC_RES_INVALID_PARAM; + } break; case MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE: - { -#ifdef CONFIG_TABLET_MODE + if (IS_ENABLED(CONFIG_TABLET_MODE)) { int ret; ret = lid_angle_set_tablet_mode_threshold( - in->tablet_mode_threshold.lid_angle, - in->tablet_mode_threshold.hys_degree); + in->tablet_mode_threshold.lid_angle, + in->tablet_mode_threshold.hys_degree); if (ret != EC_RES_SUCCESS) return ret; @@ -544,9 +556,8 @@ enum ec_status host_cmd_motion_lid(struct host_cmd_handler_args *args) args->response_size = sizeof(out->tablet_mode_threshold); -#else + } else { return EC_RES_INVALID_PARAM; -#endif } break; default: @@ -555,4 +566,3 @@ enum ec_status host_cmd_motion_lid(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } - diff --git a/common/motion_orientation.c b/common/motion_orientation.c new file mode 100644 index 0000000000..1c52fe847e --- /dev/null +++ b/common/motion_orientation.c @@ -0,0 +1,38 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Implement an orientation sensor. */ + +#include "motion_orientation.h" + +/* + * Orientation mode vectors, must match sequential ordering of + * known orientations from enum motionsensor_orientation + */ +static const intv3_t orientation_modes[] = { + [MOTIONSENSE_ORIENTATION_LANDSCAPE] = { 0, -1, 0 }, + [MOTIONSENSE_ORIENTATION_PORTRAIT] = { 1, 0, 0 }, + [MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_PORTRAIT] = { -1, 0, 0 }, + [MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_LANDSCAPE] = { 0, 1, 0 }, +}; + +enum motionsensor_orientation +motion_orientation_remap(const struct motion_sensor_t *s, + enum motionsensor_orientation orientation) +{ + enum motionsensor_orientation rotated_orientation; + const intv3_t *orientation_v; + intv3_t rotated_orientation_v; + + if (orientation == MOTIONSENSE_ORIENTATION_UNKNOWN) + return MOTIONSENSE_ORIENTATION_UNKNOWN; + + orientation_v = &orientation_modes[orientation]; + rotate(*orientation_v, *s->rot_standard_ref, rotated_orientation_v); + rotated_orientation = + ((2 * rotated_orientation_v[1] + rotated_orientation_v[0] + 4) % + 5); + return rotated_orientation; +} diff --git a/common/motion_sense.c b/common/motion_sense.c index e739bc8f75..546034c7e2 100644 --- a/common/motion_sense.c +++ b/common/motion_sense.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #include "accelgyro.h" #include "atomic.h" #include "body_detection.h" +#include "builtin/assert.h" #include "chipset.h" #include "common.h" #include "console.h" @@ -19,72 +20,80 @@ #include "lightbar.h" #include "math_util.h" #include "mkbp_event.h" +#include "motion_lid.h" +#include "motion_orientation.h" #include "motion_sense.h" #include "motion_sense_fifo.h" -#include "motion_lid.h" #include "online_calibration.h" #include "power.h" +#include "printf.h" #include "queue.h" #include "tablet_mode.h" -#include "timer.h" #include "task.h" +#include "timer.h" #include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_MOTION_SENSE, outstr) -#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_MOTION_SENSE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_MOTION_SENSE, format, ##args) -#ifdef CONFIG_ORIENTATION_SENSOR -/* - * Orientation mode vectors, must match sequential ordering of - * known orientations from enum motionsensor_orientation - */ -const intv3_t orientation_modes[] = { - [MOTIONSENSE_ORIENTATION_LANDSCAPE] = { 0, -1, 0 }, - [MOTIONSENSE_ORIENTATION_PORTRAIT] = { 1, 0, 0 }, - [MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_PORTRAIT] = { -1, 0, 0 }, - [MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_LANDSCAPE] = { 0, 1, 0 }, -}; -#endif +/* Number of times we ran motion_sense_task; for stats printing */ +static atomic_t motion_sense_task_loops; -/* Delay between FIFO interruption. */ -static unsigned int ap_event_interval; +/* When we started the task the last time */ +static timestamp_t ts_begin_task; /* Minimum time in between running motion sense task loop. */ unsigned int motion_min_interval = CONFIG_MOTION_MIN_SENSE_WAIT_TIME * MSEC; -#ifdef CONFIG_CMD_ACCEL_INFO -static int accel_disp; -#endif +STATIC_IF(CONFIG_CMD_ACCEL_INFO) int accel_disp; #define SENSOR_ACTIVE(_sensor) (sensor_active & (_sensor)->active_mask) -/* - * Adjustment in us to ec rate when calculating interrupt interval: - * To be sure the EC will send an interrupt even if it finishes processing - * events slightly earlier than the previous period. - */ -#define MOTION_SENSOR_INT_ADJUSTMENT_US 10 - -struct mutex g_sensor_mutex; +mutex_t g_sensor_mutex; /* * Current power level (S0, S3, S5, ...) */ test_export_static enum chipset_state_mask sensor_active; -#ifdef CONFIG_ACCEL_SPOOF_MODE -static void print_spoof_mode_status(int id); -#endif /* defined(CONFIG_ACCEL_SPOOF_MODE) */ +/* + * Motion task interval. It does not have to be a global variable, + * but it allows to be tested. + */ +test_export_static int wait_us; + +STATIC_IF(CONFIG_ACCEL_SPOOF_MODE) void print_spoof_mode_status(int id); +STATIC_IF(CONFIG_GESTURE_DETECTION) +void check_and_queue_gestures(uint32_t *event); +STATIC_IF(CONFIG_MOTION_FILL_LPC_SENSE_DATA) +void update_sense_data(uint8_t *lpc_status, int *psample_id); /* Flags to control whether to send an ODR change event for a sensor */ -static uint32_t odr_event_required; +static atomic_t odr_event_required; /* Whether or not the FIFO interrupt should be enabled (set from the AP). */ __maybe_unused static int fifo_int_enabled; -static inline int motion_sensor_in_forced_mode( - const struct motion_sensor_t *sensor) +#ifdef CONFIG_ZEPHYR +static int init_sensor_mutex(void) +{ + k_mutex_init(&g_sensor_mutex); + + return 0; +} +SYS_INIT(init_sensor_mutex, POST_KERNEL, 50); +#endif /* CONFIG_ZEPHYR */ + +#ifdef CONFIG_LID_ANGLE +__attribute__((weak)) int sensor_board_is_lid_angle_available(void) +{ + return 1; +} +#endif + +static inline int +motion_sensor_in_forced_mode(const struct motion_sensor_t *sensor) { #ifdef CONFIG_ACCEL_FORCE_MODE_MASK /* Sensor not in force mode, its irq_handler is getting data. */ @@ -98,8 +107,9 @@ static inline int motion_sensor_in_forced_mode( } /* Minimal amount of time since last collection before triggering a new one */ -static inline int motion_sensor_time_to_read(const timestamp_t *ts, - const struct motion_sensor_t *sensor) +static inline int +motion_sensor_time_to_read(const timestamp_t *ts, + const struct motion_sensor_t *sensor) { if (sensor->collection_rate == 0) return 0; @@ -112,7 +122,8 @@ static inline int motion_sensor_time_to_read(const timestamp_t *ts, sensor->next_collection - motion_min_interval); } -static enum sensor_config motion_sense_get_ec_config(void) +STATIC_IF_NOT(CONFIG_ZTEST) +enum sensor_config motion_sense_get_ec_config(void) { switch (sensor_active) { case SENSOR_ACTIVE_S0: @@ -124,13 +135,15 @@ static enum sensor_config motion_sense_get_ec_config(void) default: CPRINTS("get_ec_config: Invalid active state: %x", sensor_active); - return SENSOR_CONFIG_MAX; + return SENSOR_CONFIG_EC_S5; } } /* motion_sense_set_data_rate * * Set the sensor data rate. It is altered when the AP change the data * rate or when the power state changes. + * + * NOTE: Always run in TASK_ID_MOTIONSENSE task. */ int motion_sense_set_data_rate(struct motion_sensor_t *sensor) { @@ -156,26 +169,27 @@ int motion_sense_set_data_rate(struct motion_sensor_t *sensor) roundup = !!(sensor->config[config_id].odr & ROUND_UP_FLAG); ret = sensor->drv->set_data_rate(sensor, odr, roundup); + + if (IS_ENABLED(CONFIG_CONSOLE_VERBOSE)) + CPRINTS("%s ODR: %d - roundup %d from config %d [AP %d]: %d", + sensor->name, odr, roundup, config_id, + BASE_ODR(sensor->config[SENSOR_CONFIG_AP].odr), ret); + else + CPRINTS("%c%d ODR %d rup %d cfg %d AP %d: %d", sensor->name[0], + sensor->type, odr, roundup, config_id, + BASE_ODR(sensor->config[SENSOR_CONFIG_AP].odr), ret); + if (ret) return ret; -#ifdef CONFIG_CONSOLE_VERBOSE - CPRINTS("%s ODR: %d - roundup %d from config %d [AP %d]", - sensor->name, odr, roundup, config_id, - BASE_ODR(sensor->config[SENSOR_CONFIG_AP].odr)); -#else - CPRINTS("%c%d ODR %d rup %d cfg %d AP %d", - sensor->name[0], sensor->type, odr, roundup, config_id, - BASE_ODR(sensor->config[SENSOR_CONFIG_AP].odr)); -#endif mutex_lock(&g_sensor_mutex); + odr = sensor->drv->get_data_rate(sensor); if (ap_odr_mhz) /* * In case the AP want to run the sensors faster than it can, * be sure we don't see the ratio to 0. */ - sensor->oversampling_ratio = MAX(1, - sensor->drv->get_data_rate(sensor) / ap_odr_mhz); + sensor->oversampling_ratio = MAX(1, odr / ap_odr_mhz); else sensor->oversampling_ratio = 0; @@ -183,152 +197,33 @@ int motion_sense_set_data_rate(struct motion_sensor_t *sensor) * Reset last collection: the last collection may be so much in the past * it may appear to be in the future. */ - odr = sensor->drv->get_data_rate(sensor); sensor->collection_rate = odr > 0 ? SECOND * 1000 / odr : 0; sensor->next_collection = ts.le.lo + sensor->collection_rate; sensor->oversampling = 0; + if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { + motion_sense_set_data_period(sensor - motion_sensors, + sensor->collection_rate); + } mutex_unlock(&g_sensor_mutex); -#ifdef CONFIG_BODY_DETECTION - if (sensor - motion_sensors == CONFIG_BODY_DETECTION_SENSOR) + if (IS_ENABLED(CONFIG_BODY_DETECTION) && + (sensor - motion_sensors == CONFIG_BODY_DETECTION_SENSOR)) body_detect_reset(); -#endif - return 0; -} - -static int motion_sense_set_ec_rate_from_ap( - const struct motion_sensor_t *sensor, - unsigned int new_rate_us) -{ - int odr_mhz = sensor->drv->get_data_rate(sensor); - - if (new_rate_us == 0) - return 0; - if (motion_sensor_in_forced_mode(sensor)) - /* - * AP EC sampling rate does not matter: we will collect at the - * requested sensor frequency. - */ - goto end_set_ec_rate_from_ap; - if (odr_mhz == 0) - goto end_set_ec_rate_from_ap; - - /* - * If the EC collection rate is close to the sensor data rate, - * given variation from the EC scheduler, it is possible that a sensor - * will not present any measurement for a given time slice, and then 2 - * measurement for the next. That will create a large interval between - * 2 measurements. - * To prevent that, increase the EC period by 5% to be sure to get at - * least one measurement at every collection time. - * We will apply that correction only if the ec rate is within 10% of - * the data rate. - */ - if (SECOND * 1100 / odr_mhz > new_rate_us) - new_rate_us = new_rate_us / 100 * 105; - -end_set_ec_rate_from_ap: - return MAX(new_rate_us, motion_min_interval); -} - - -/* - * motion_sense_select_ec_rate - * - * Calculate the ec_rate for a given sensor. - * - sensor: sensor to use - * - config_id: determine the requester (AP or EC). - * - interrupt: - * If interrupt is set: return the sampling rate requested by AP or EC. - * If interrupt is not set and the sensor is in forced mode, - * we return the rate needed to probe the sensor at the right ODR. - * otherwise return the sampling rate requested by AP or EC. - * - * return rate in us. - */ -static int motion_sense_select_ec_rate( - const struct motion_sensor_t *sensor, - enum sensor_config config_id, - int interrupt) -{ - if (interrupt == 0 && motion_sensor_in_forced_mode(sensor)) { - int rate_mhz = BASE_ODR(sensor->config[config_id].odr); - /* we have to run ec at the sensor frequency rate.*/ - if (rate_mhz > 0) - return SECOND * 1000 / rate_mhz; - else - return 0; - } else { - return sensor->config[config_id].ec_rate; - } -} - -/* motion_sense_ec_rate - * - * Calculate the sensor ec rate. It will be use to set the motion task polling - * rate. - * - * Return the EC rate, in us. - */ -static int motion_sense_ec_rate(struct motion_sensor_t *sensor) -{ - int ec_rate = 0, ec_rate_from_cfg; - - /* Check the AP setting first. */ - if (sensor_active != SENSOR_ACTIVE_S5) - ec_rate = motion_sense_select_ec_rate( - sensor, SENSOR_CONFIG_AP, 0); - ec_rate_from_cfg = motion_sense_select_ec_rate( - sensor, motion_sense_get_ec_config(), 0); - - if (ec_rate_from_cfg != 0) - if (ec_rate == 0 || ec_rate_from_cfg < ec_rate) - ec_rate = ec_rate_from_cfg; - return ec_rate; -} - -/* - * motion_sense_set_motion_intervals - * - * Set the wake up interval for the motion sense thread. - * It is set to the highest frequency one of the sensors need to be polled at. - * - * Note: Not static to be tested. - */ -static void motion_sense_set_motion_intervals(void) -{ - int i, sensor_ec_rate, ec_int_rate = 0; - struct motion_sensor_t *sensor; - for (i = 0; i < motion_sensor_count; ++i) { - sensor = &motion_sensors[i]; - /* - * If the sensor is sleeping, no need to check it periodically. - */ - if ((sensor->state != SENSOR_INITIALIZED) || - (sensor->drv->get_data_rate(sensor) == 0)) - continue; - - sensor_ec_rate = motion_sense_select_ec_rate( - sensor, SENSOR_CONFIG_AP, 1); - if (ec_int_rate == 0 || - (sensor_ec_rate && sensor_ec_rate < ec_int_rate)) - ec_int_rate = sensor_ec_rate; - } - - ap_event_interval = - MAX(0, ec_int_rate - MOTION_SENSOR_INT_ADJUSTMENT_US); - /* - * Wake up the motion sense task: we want to sensor task to take - * in account the new period right away. - */ - task_wake(TASK_ID_MOTIONSENSE); + return 0; } +/* Note: Always run on HOOK task, trigger by events from CHIPSET task. */ static inline int motion_sense_init(struct motion_sensor_t *sensor) { int ret, cnt = 3; BUILD_ASSERT(SENSOR_COUNT < 32); +#if defined(HAS_TASK_CONSOLE) + ASSERT((in_deferred_context()) || + (task_get_current() == TASK_ID_CONSOLE)); +#elif !defined(CONFIG_ZTEST) + ASSERT(in_deferred_context()); +#endif /* HAS_TASK_CONSOLE */ /* Initialize accelerometers. */ do { @@ -339,7 +234,6 @@ static inline int motion_sense_init(struct motion_sensor_t *sensor) sensor->state = SENSOR_INIT_ERROR; } else { sensor->state = SENSOR_INITIALIZED; - motion_sense_set_data_rate(sensor); } return ret; @@ -350,20 +244,19 @@ static inline int motion_sense_init(struct motion_sensor_t *sensor) * * Called by init routine of each sensors when successful. */ -int sensor_init_done(const struct motion_sensor_t *s) +int sensor_init_done(struct motion_sensor_t *s) { int ret; - ret = s->drv->set_range(s, BASE_RANGE(s->default_range), - !!(s->default_range & ROUND_UP_FLAG)); + ret = s->drv->set_range(s, BASE_RANGE(s->current_range), + !!(s->current_range & ROUND_UP_FLAG)); if (ret == EC_RES_SUCCESS) { -#ifdef CONFIG_CONSOLE_VERBOSE - CPRINTS("%s: MS Done Init type:0x%X range:%d", - s->name, s->type, s->drv->get_range(s)); -#else - CPRINTS("%c%d InitDone r:%d", s->name[0], s->type, - s->drv->get_range(s)); -#endif + if (IS_ENABLED(CONFIG_CONSOLE_VERBOSE)) + CPRINTS("%s: MS Done Init type:0x%X range:%d", s->name, + s->type, s->current_range); + else + CPRINTS("%c%d InitDone r:%d", s->name[0], s->type, + s->current_range); } return ret; } @@ -378,46 +271,136 @@ static void motion_sense_switch_sensor_rate(void) { int i, ret; struct motion_sensor_t *sensor; + unsigned int sensor_setup_mask = 0; + + ASSERT(in_deferred_context()); + for (i = 0; i < motion_sensor_count; ++i) { sensor = &motion_sensors[i]; if (SENSOR_ACTIVE(sensor)) { - /* Initialize or just back the odr previously set. */ + /* + * Initialize or just back the odr/range previously + * set. + */ if (sensor->state == SENSOR_INITIALIZED) { - motion_sense_set_data_rate(sensor); + sensor->drv->set_range( + sensor, sensor->current_range, 1); + sensor_setup_mask |= BIT(i); } else { ret = motion_sense_init(sensor); - if (ret != EC_SUCCESS) { + if (ret != EC_SUCCESS) CPRINTS("%s: %d: init failed: %d", sensor->name, i, ret); -#if defined(CONFIG_TABLET_MODE) && defined(CONFIG_LID_ANGLE) - /* - * No tablet mode allowed if an accel - * is not working. - */ - if (i == CONFIG_LID_ANGLE_SENSOR_BASE || - i == CONFIG_LID_ANGLE_SENSOR_LID) { - tablet_set_mode(0); - } -#endif - } + else + sensor_setup_mask |= BIT(i); + /* + * No tablet mode allowed if an accel + * is not working. + */ + if (IS_ENABLED(CONFIG_TABLET_MODE) && + IS_ENABLED(CONFIG_LID_ANGLE) && + (ret != EC_SUCCESS) && + (i == CONFIG_LID_ANGLE_SENSOR_BASE || + i == CONFIG_LID_ANGLE_SENSOR_LID)) + tablet_set_mode(0, TABLET_TRIGGER_LID); } } else { /* The sensors are being powered off */ - if (sensor->state == SENSOR_INITIALIZED) + if (sensor->state == SENSOR_INITIALIZED) { + /* + * Use mutex to be sure we are not changing the + * ODR in MOTIONSENSE, in case it is running. + */ + mutex_lock(&g_sensor_mutex); + sensor->collection_rate = 0; + mutex_unlock(&g_sensor_mutex); sensor->state = SENSOR_NOT_INITIALIZED; + } + } + } + if (sensor_setup_mask) { + atomic_or(&odr_event_required, sensor_setup_mask); + task_set_event(TASK_ID_MOTIONSENSE, + TASK_EVENT_MOTION_ODR_CHANGE); + } + + /* disable the body detection since AP is suspended */ + if (IS_ENABLED(CONFIG_BODY_DETECTION)) { + static bool was_enabled; + + switch (sensor_active) { + case SENSOR_ACTIVE_S3: + was_enabled = body_detect_get_enable(); + body_detect_set_enable(false); + break; + case SENSOR_ACTIVE_S0: + /* force to enable the body detection in S0 */ + if (IS_ENABLED( + CONFIG_BODY_DETECTION_ALWAYS_ENABLE_IN_S0)) + body_detect_set_enable(true); + else + body_detect_set_enable(was_enabled); + break; + default: + break; + } + } + /* Forget activities set by the AP */ + if (IS_ENABLED(CONFIG_GESTURE_DETECTION) && + (sensor_active == SENSOR_ACTIVE_S5)) { + uint32_t enabled = 0, disabled, mask; + + mask = CONFIG_GESTURE_DETECTION_MASK; + while (mask) { + i = get_next_bit(&mask); + sensor = &motion_sensors[i]; + if (sensor->state != SENSOR_INITIALIZED) + continue; + sensor->drv->list_activities(sensor, &enabled, + &disabled); + /* exclude double tap, it is used internally. */ + enabled &= ~BIT(MOTIONSENSE_ACTIVITY_DOUBLE_TAP); + while (enabled) { + int activity = get_next_bit(&enabled); + + sensor->drv->manage_activity(sensor, activity, + 0, NULL); + } + /* Re-enable double tap in case AP disabled it */ + if (IS_ENABLED(CONFIG_GESTURE_SENSOR_DOUBLE_TAP)) + sensor->drv->manage_activity( + sensor, MOTIONSENSE_ACTIVITY_DOUBLE_TAP, + 1, NULL); } } - motion_sense_set_motion_intervals(); } DECLARE_DEFERRED(motion_sense_switch_sensor_rate); +static void motion_sense_print_stats(const char *event) +{ + unsigned int active = 0; + unsigned int states = 0; + int i; + + for (i = 0; i < motion_sensor_count; i++) { + if (motion_sensors[i].active_mask) + active |= BIT(i); + /* States fit in 2 bits but we'll give them 4 for readbility */ + states |= motion_sensors[i].state << (4 * i); + } + + CPRINTS("Motion pre-%s; loops %u; last %u ms ago; a=0x%x, s=0x%x", + event, (unsigned int)motion_sense_task_loops, + (unsigned int)(get_time().val - ts_begin_task.val) / 1000, + active, states); +} + static void motion_sense_shutdown(void) { int i; struct motion_sensor_t *sensor; -#ifdef CONFIG_GESTURE_DETECTION_MASK - uint32_t enabled = 0, disabled, mask; -#endif + + motion_sense_print_stats("shutdown"); sensor_active = SENSOR_ACTIVE_S5; for (i = 0; i < motion_sensor_count; i++) { @@ -425,40 +408,22 @@ static void motion_sense_shutdown(void) /* Forget about changes made by the AP */ sensor->config[SENSOR_CONFIG_AP].odr = 0; sensor->config[SENSOR_CONFIG_AP].ec_rate = 0; + sensor->current_range = sensor->default_range; } - motion_sense_switch_sensor_rate(); - /* Forget activities set by the AP */ -#ifdef CONFIG_GESTURE_DETECTION_MASK - mask = CONFIG_GESTURE_DETECTION_MASK; - while (mask) { - i = get_next_bit(&mask); - sensor = &motion_sensors[i]; - if (sensor->state != SENSOR_INITIALIZED) - continue; - sensor->drv->list_activities(sensor, - &enabled, &disabled); - /* exclude double tap, it is used internally. */ - enabled &= ~BIT(MOTIONSENSE_ACTIVITY_DOUBLE_TAP); - while (enabled) { - int activity = get_next_bit(&enabled); - sensor->drv->manage_activity(sensor, activity, 0, NULL); - } - /* Re-enable double tap in case AP disabled it */ - sensor->drv->manage_activity(sensor, - MOTIONSENSE_ACTIVITY_DOUBLE_TAP, 1, NULL); - } -#endif -#ifdef CONFIG_BODY_DETECTION - /* disable the body detection since motion sensor is down */ - body_detect_set_enable(false); -#endif + /* + * Run motion_sense_switch_sensor_rate_data in the HOOK task, + * To be sure no 2 rate changes happens in parralell. + */ + hook_call_deferred(&motion_sense_switch_sensor_rate_data, 0); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, motion_sense_shutdown, MOTION_SENSE_HOOK_PRIO); static void motion_sense_suspend(void) { + motion_sense_print_stats("suspend"); + /* * If we are coming from S5, don't enter suspend: * We will go in SO almost immediately. @@ -468,10 +433,6 @@ static void motion_sense_suspend(void) sensor_active = SENSOR_ACTIVE_S3; -#ifdef CONFIG_BODY_DETECTION - /* disable the body detection since motion sensor is suspended */ - body_detect_set_enable(false); -#endif /* * During shutdown sequence sensor rails can be powered down * asynchronously to the EC hence EC cannot interlock the sensor @@ -492,12 +453,13 @@ DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, motion_sense_suspend, static void motion_sense_resume(void) { + motion_sense_print_stats("resume"); + sensor_active = SENSOR_ACTIVE_S0; hook_call_deferred(&motion_sense_switch_sensor_rate_data, CONFIG_MOTION_SENSE_RESUME_DELAY_US); } -DECLARE_HOOK(HOOK_CHIPSET_RESUME, motion_sense_resume, - MOTION_SENSE_HOOK_PRIO); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, motion_sense_resume, MOTION_SENSE_HOOK_PRIO); static void motion_sense_startup(void) { @@ -513,8 +475,7 @@ static void motion_sense_startup(void) if (chipset_in_state(SENSOR_ACTIVE_S0)) motion_sense_resume(); } -DECLARE_HOOK(HOOK_INIT, motion_sense_startup, - MOTION_SENSE_HOOK_PRIO); +DECLARE_HOOK(HOOK_INIT, motion_sense_startup, MOTION_SENSE_HOOK_PRIO); /* Write to LPC status byte to represent that accelerometers are present. */ static inline void set_present(uint8_t *lpc_status) @@ -524,13 +485,10 @@ static inline void set_present(uint8_t *lpc_status) #ifdef CONFIG_MOTION_FILL_LPC_SENSE_DATA /* Update/Write LPC data */ -static inline void update_sense_data(uint8_t *lpc_status, int *psample_id) +static void update_sense_data(uint8_t *lpc_status, int *psample_id) { int s, d, i; int16_t *lpc_data = (int16_t *)host_get_memmap(EC_MEMMAP_ACC_DATA); -#if (!defined HAS_TASK_ALS) && (defined CONFIG_ALS) - uint16_t *lpc_als = (uint16_t *)host_get_memmap(EC_MEMMAP_ALS); -#endif struct motion_sensor_t *sensor; /* * Set the busy bit before writing the sensor data. Increment @@ -549,11 +507,11 @@ static inline void update_sense_data(uint8_t *lpc_status, int *psample_id) * with uncalibrated accelerometers. The AP calculates a separate, * more accurate lid angle. */ -#ifdef CONFIG_LID_ANGLE - lpc_data[0] = motion_lid_get_angle(); -#else - lpc_data[0] = LID_ANGLE_UNRELIABLE; -#endif + if (IS_ENABLED(CONFIG_LID_ANGLE)) + lpc_data[0] = motion_lid_get_angle(); + else + lpc_data[0] = LID_ANGLE_UNRELIABLE; + /* * The first 2 entries must be accelerometers, then gyroscope. * If there is only one accel and one gyro, the entry for the second @@ -570,45 +528,40 @@ static inline void update_sense_data(uint8_t *lpc_status, int *psample_id) lpc_data[1 + i + 3 * d] = ec_motion_sensor_clamp_i16(sensor->xyz[i]); } + if (!IS_ENABLED(HAS_TASK_ALS) && IS_ENABLED(CONFIG_ALS)) { + uint16_t *lpc_als = (uint16_t *)host_get_memmap(EC_MEMMAP_ALS); -#if (!defined HAS_TASK_ALS) && (defined CONFIG_ALS) - for (i = 0; i < EC_ALS_ENTRIES && i < ALS_COUNT; i++) - lpc_als[i] = ec_motion_sensor_clamp_u16( + for (i = 0; i < EC_ALS_ENTRIES && i < ALS_COUNT; i++) + lpc_als[i] = ec_motion_sensor_clamp_u16( motion_als_sensors[i]->xyz[X]); -#endif + } /* * Increment sample id and clear busy bit to signal we finished * updating data. */ - *psample_id = (*psample_id + 1) & - EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK; + *psample_id = (*psample_id + 1) & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK; *lpc_status = EC_MEMMAP_ACC_STATUS_PRESENCE_BIT | *psample_id; } #endif static int motion_sense_read(struct motion_sensor_t *sensor) { - if (sensor->state != SENSOR_INITIALIZED) - return EC_ERROR_UNKNOWN; - - if (sensor->drv->get_data_rate(sensor) == 0) - return EC_ERROR_NOT_POWERED; + ASSERT(sensor->state == SENSOR_INITIALIZED); + ASSERT(sensor->drv->get_data_rate(sensor) != 0); -#ifdef CONFIG_ACCEL_SPOOF_MODE /* * If the sensor is in spoof mode, the readings are already present in * spoof_xyz. */ - if (sensor->flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE) + if (IS_ENABLED(CONFIG_ACCEL_SPOOF_MODE) && + (sensor->flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE)) return EC_SUCCESS; -#endif /* defined(CONFIG_ACCEL_SPOOF_MODE) */ /* Otherwise, read all raw X,Y,Z accelerations. */ return sensor->drv->read(sensor, sensor->raw_xyz); } - static inline void increment_sensor_collection(struct motion_sensor_t *sensor, const timestamp_t *ts) { @@ -638,7 +591,7 @@ static inline void increment_sensor_collection(struct motion_sensor_t *sensor, * * @param s Pointer to the sensor. */ -static void motion_sense_push_raw_xyz(struct motion_sensor_t *s) +void motion_sense_push_raw_xyz(struct motion_sensor_t *s) { if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { struct ec_response_motion_sensor_data vector; @@ -666,8 +619,7 @@ static void motion_sense_push_raw_xyz(struct motion_sensor_t *s) } } -static int motion_sense_process(struct motion_sensor_t *sensor, - uint32_t *event, +static int motion_sense_process(struct motion_sensor_t *sensor, uint32_t *event, const timestamp_t *ts) { int ret = EC_SUCCESS; @@ -675,28 +627,33 @@ static int motion_sense_process(struct motion_sensor_t *sensor, int has_data_read = 0; int sensor_num = sensor - motion_sensors; + ASSERT(task_get_current() == TASK_ID_MOTIONSENSE); + if (*event & TASK_EVENT_MOTION_ODR_CHANGE) { const int sensor_bit = 1 << sensor_num; - int odr_pending = - deprecated_atomic_read_clear(&odr_event_required); + int odr_pending = atomic_clear(&odr_event_required); is_odr_pending = odr_pending & sensor_bit; odr_pending &= ~sensor_bit; - deprecated_atomic_or(&odr_event_required, odr_pending); + atomic_or(&odr_event_required, odr_pending); } -#ifdef CONFIG_ACCEL_INTERRUPTS if ((*event & TASK_EVENT_MOTION_INTERRUPT_MASK || is_odr_pending) && (sensor->drv->irq_handler != NULL)) { ret = sensor->drv->irq_handler(sensor, event); if (ret == EC_SUCCESS) has_data_read = 1; } -#endif /* CONFIG_ACCEL_INTERRUPTS */ if (motion_sensor_in_forced_mode(sensor)) { if (motion_sensor_time_to_read(ts, sensor)) { - ret = motion_sense_read(sensor); + /* + * Since motion_sense_read can sleep, other task may be + * scheduled. In particular if suspend is called by + * HOOKS task, it may set colleciton_rate to 0 and we + * would crash in increment_sensor_collection. + */ increment_sensor_collection(sensor, ts); + ret = motion_sense_read(sensor); } else { ret = EC_ERROR_BUSY; } @@ -708,148 +665,123 @@ static int motion_sense_process(struct motion_sensor_t *sensor, } if (IS_ENABLED(CONFIG_ACCEL_FIFO) && *event & TASK_EVENT_MOTION_FLUSH_PENDING) { - int flush_pending = - deprecated_atomic_read_clear(&sensor->flush_pending); + int flush_pending = atomic_clear(&sensor->flush_pending); for (; flush_pending > 0; flush_pending--) { - motion_sense_fifo_insert_async_event( - sensor, ASYNC_EVENT_FLUSH); + motion_sense_fifo_insert_async_event(sensor, + ASYNC_EVENT_FLUSH); } } /* ODR change was requested. */ if (is_odr_pending) { motion_sense_set_data_rate(sensor); - motion_sense_set_motion_intervals(); if (IS_ENABLED(CONFIG_ACCEL_FIFO)) - motion_sense_fifo_insert_async_event( - sensor, ASYNC_EVENT_ODR); + motion_sense_fifo_insert_async_event(sensor, + ASYNC_EVENT_ODR); } if (has_data_read) { -#ifdef CONFIG_GESTURE_SW_DETECTION /* Run gesture recognition engine */ - if (sensor_num == CONFIG_GESTURE_SENSOR_DOUBLE_TAP) + if (IS_ENABLED(CONFIG_GESTURE_SW_DETECTION) && + (sensor_num == CONFIG_GESTURE_TAP_SENSOR)) gesture_calc(event); -#endif -#ifdef CONFIG_BODY_DETECTION - if (sensor_num == CONFIG_BODY_DETECTION_SENSOR) + if (IS_ENABLED(CONFIG_BODY_DETECTION) && + (sensor_num == CONFIG_BODY_DETECTION_SENSOR)) body_detect(); -#endif } return ret; } -#ifdef CONFIG_ORIENTATION_SENSOR -enum motionsensor_orientation motion_sense_remap_orientation( - const struct motion_sensor_t *s, - enum motionsensor_orientation orientation) -{ - enum motionsensor_orientation rotated_orientation; - const intv3_t *orientation_v; - intv3_t rotated_orientation_v; - - if (orientation == MOTIONSENSE_ORIENTATION_UNKNOWN) - return MOTIONSENSE_ORIENTATION_UNKNOWN; - - orientation_v = &orientation_modes[orientation]; - rotate(*orientation_v, *s->rot_standard_ref, rotated_orientation_v); - rotated_orientation = ((2 * rotated_orientation_v[1] + - rotated_orientation_v[0] + 4) % 5); - return rotated_orientation; -} -#endif - #ifdef CONFIG_GESTURE_DETECTION static void check_and_queue_gestures(uint32_t *event) { -#ifdef CONFIG_ORIENTATION_SENSOR - const struct motion_sensor_t *sensor; -#endif + if (IS_ENABLED(CONFIG_GESTURE_SENSOR_DOUBLE_TAP) && + (*event & TASK_EVENT_MOTION_ACTIVITY_INTERRUPT( + MOTIONSENSE_ACTIVITY_DOUBLE_TAP))) { + if (IS_ENABLED(CONFIG_GESTURE_HOST_DETECTION)) { + struct ec_response_motion_sensor_data vector; -#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP - if (*event & TASK_EVENT_MOTION_ACTIVITY_INTERRUPT( - MOTIONSENSE_ACTIVITY_DOUBLE_TAP)) { -#ifdef CONFIG_GESTURE_HOST_DETECTION - struct ec_response_motion_sensor_data vector; - - /* - * Send events to the FIFO - * AP is ignoring double tap event, do no wake up and no - * automatic disable. - */ -#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP_FOR_HOST - vector.flags = MOTIONSENSE_SENSOR_FLAG_WAKEUP; -#else - vector.flags = 0; -#endif - vector.activity = MOTIONSENSE_ACTIVITY_DOUBLE_TAP; - vector.state = 1; /* triggered */ - vector.sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID; - motion_sense_fifo_stage_data(&vector, NULL, 0, - __hw_clock_source_read()); - motion_sense_fifo_commit_data(); -#endif + vector.flags = MOTIONSENSE_SENSOR_FLAG_BYPASS_FIFO; + /* + * Send events to the FIFO + * AP is ignoring double tap event, do no wake up and no + * automatic disable. + */ + if (IS_ENABLED( + CONFIG_GESTURE_SENSOR_DOUBLE_TAP_FOR_HOST)) + vector.flags |= MOTIONSENSE_SENSOR_FLAG_WAKEUP; + vector.activity_data.activity = + MOTIONSENSE_ACTIVITY_DOUBLE_TAP; + vector.activity_data.state = 1 /* triggered */; + vector.sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID; + motion_sense_fifo_stage_data(&vector, NULL, 0, + __hw_clock_source_read()); + motion_sense_fifo_commit_data(); + } /* Call board specific function to process tap */ sensor_board_proc_double_tap(); } -#endif -#ifdef CONFIG_GESTURE_SIGMO - if (*event & TASK_EVENT_MOTION_ACTIVITY_INTERRUPT( - MOTIONSENSE_ACTIVITY_SIG_MOTION)) { + if (IS_ENABLED(CONFIG_GESTURE_SIGMO) && + (*event & TASK_EVENT_MOTION_ACTIVITY_INTERRUPT( + MOTIONSENSE_ACTIVITY_SIG_MOTION))) { struct motion_sensor_t *activity_sensor; -#ifdef CONFIG_GESTURE_HOST_DETECTION - struct ec_response_motion_sensor_data vector; - - /* Send events to the FIFO */ - vector.flags = MOTIONSENSE_SENSOR_FLAG_WAKEUP; - vector.activity = MOTIONSENSE_ACTIVITY_SIG_MOTION; - vector.state = 1; /* triggered */ - vector.sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID; - motion_sense_fifo_stage_data(&vector, NULL, 0, - __hw_clock_source_read()); - motion_sense_fifo_commit_data(); -#endif + if (IS_ENABLED(CONFIG_GESTURE_HOST_DETECTION)) { + struct ec_response_motion_sensor_data vector; + + /* Send events to the FIFO */ + vector.flags = MOTIONSENSE_SENSOR_FLAG_WAKEUP | + MOTIONSENSE_SENSOR_FLAG_BYPASS_FIFO; + vector.activity_data.activity = + MOTIONSENSE_ACTIVITY_SIG_MOTION; + vector.activity_data.state = 1 /* triggered */; + vector.sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID; + motion_sense_fifo_stage_data(&vector, NULL, 0, + __hw_clock_source_read()); + motion_sense_fifo_commit_data(); + } /* Disable further detection */ - activity_sensor = &motion_sensors[CONFIG_GESTURE_SIGMO]; + activity_sensor = &motion_sensors[CONFIG_GESTURE_SIGMO_SENSOR]; activity_sensor->drv->manage_activity( - activity_sensor, - MOTIONSENSE_ACTIVITY_SIG_MOTION, - 0, NULL); + activity_sensor, MOTIONSENSE_ACTIVITY_SIG_MOTION, 0, + NULL); } -#endif - -#ifdef CONFIG_ORIENTATION_SENSOR - sensor = &motion_sensors[LID_ACCEL]; - if (SENSOR_ACTIVE(sensor) && (sensor->state == SENSOR_INITIALIZED)) { - struct ec_response_motion_sensor_data vector = { - .flags = 0, - .activity = MOTIONSENSE_ACTIVITY_ORIENTATION, - .sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID, - }; - - mutex_lock(sensor->mutex); - if (ORIENTATION_CHANGED(sensor) && (GET_ORIENTATION(sensor) != - MOTIONSENSE_ORIENTATION_UNKNOWN)) { - SET_ORIENTATION_UPDATED(sensor); - vector.state = GET_ORIENTATION(sensor); - motion_sense_fifo_add_data(&vector, NULL, 0, - __hw_clock_source_read()); -#ifdef CONFIG_DEBUG_ORIENTATION - { - static const char * const mode_strs[] = { - "Landscape", - "Portrait", - "Inv_Portrait", - "Inv_Landscape", + if (IS_ENABLED(CONFIG_ORIENTATION_SENSOR)) { + const struct motion_sensor_t *sensor = + &motion_sensors[LID_ACCEL]; + + if (SENSOR_ACTIVE(sensor) && + (sensor->state == SENSOR_INITIALIZED)) { + struct ec_response_motion_sensor_data vector = { + .flags = 0, + .activity_data.activity = + MOTIONSENSE_ACTIVITY_ORIENTATION, + .sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID, + }; + + mutex_lock(sensor->mutex); + if (motion_orientation_changed(sensor) && + (*motion_orientation_ptr(sensor) != + MOTIONSENSE_ORIENTATION_UNKNOWN)) { + motion_orientation_update(sensor); + vector.activity_data.state = + *motion_orientation_ptr(sensor); + motion_sense_fifo_stage_data( + &vector, NULL, 0, + __hw_clock_source_read()); + motion_sense_fifo_commit_data(); + if (IS_ENABLED(CONFIG_DEBUG_ORIENTATION)) { + static const char *const mode[] = { + "Landscape", "Portrait", + "Inv_Portrait", "Inv_Landscape", "Unknown" - }; - CPRINTS(mode_strs[GET_ORIENTATION(sensor)]); + }; + CPRINTS("%s", + mode[vector.activity_data.state]); + } } -#endif + mutex_unlock(sensor->mutex); } - mutex_unlock(sensor->mutex); } -#endif } #endif @@ -862,34 +794,27 @@ static void check_and_queue_gestures(uint32_t *event) */ void motion_sense_task(void *u) { - int i, ret, wait_us; - timestamp_t ts_begin_task, ts_end_task; + int i, ret, sample_id = 0; + timestamp_t ts_end_task; int32_t time_diff; uint32_t event = 0; uint16_t ready_status = 0; struct motion_sensor_t *sensor; -#ifdef CONFIG_LID_ANGLE - const uint16_t lid_angle_sensors = (BIT(CONFIG_LID_ANGLE_SENSOR_BASE)| - BIT(CONFIG_LID_ANGLE_SENSOR_LID)); -#endif - timestamp_t ts_last_int; -#ifdef CONFIG_MOTION_FILL_LPC_SENSE_DATA - int sample_id = 0; uint8_t *lpc_status; - lpc_status = host_get_memmap(EC_MEMMAP_ACC_STATUS); - set_present(lpc_status); -#endif + if (IS_ENABLED(CONFIG_MOTION_FILL_LPC_SENSE_DATA)) { + lpc_status = host_get_memmap(EC_MEMMAP_ACC_STATUS); + set_present(lpc_status); + } if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { motion_sense_fifo_init(); - ts_last_int = get_time(); } while (1) { ts_begin_task = get_time(); + atomic_add(&motion_sense_task_loops, 1); for (i = 0; i < motion_sensor_count; ++i) { - sensor = &motion_sensors[i]; /* if the sensor is active in the current power state */ @@ -899,46 +824,46 @@ void motion_sense_task(void *u) } ret = motion_sense_process(sensor, &event, - &ts_begin_task); + &ts_begin_task); if (ret != EC_SUCCESS) continue; ready_status |= BIT(i); } } -#ifdef CONFIG_GESTURE_DETECTION - check_and_queue_gestures(&event); -#endif -#ifdef CONFIG_LID_ANGLE - /* - * Check to see that the sensors required for lid angle - * calculation are ready. - */ - ready_status &= lid_angle_sensors; - if (ready_status == lid_angle_sensors) { - motion_lid_calc(); - ready_status = 0; + if (IS_ENABLED(CONFIG_GESTURE_DETECTION)) + check_and_queue_gestures(&event); + if (IS_ENABLED(CONFIG_LID_ANGLE)) { + const uint16_t lid_angle_sensors = + BIT(CONFIG_LID_ANGLE_SENSOR_BASE) | + BIT(CONFIG_LID_ANGLE_SENSOR_LID); + + /* + * Check to see that the sensors required for lid angle + * calculation are ready. + */ + ready_status &= lid_angle_sensors; + if (ready_status == lid_angle_sensors) { + motion_lid_calc(); + ready_status = 0; + } } -#endif -#ifdef CONFIG_CMD_ACCEL_INFO - if (accel_disp) { - CPRINTF("[%pT event 0x%08x ", - PRINTF_TIMESTAMP_NOW, event); + if (IS_ENABLED(CONFIG_CMD_ACCEL_INFO) && (accel_disp)) { + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; + + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + CPRINTF("[%s event 0x%08x ", ts_str, event); for (i = 0; i < motion_sensor_count; ++i) { sensor = &motion_sensors[i]; CPRINTF("%s=%-5d, %-5d, %-5d ", sensor->name, - sensor->xyz[X], - sensor->xyz[Y], + sensor->xyz[X], sensor->xyz[Y], sensor->xyz[Z]); } -#ifdef CONFIG_LID_ANGLE - CPRINTF("a=%-4d", motion_lid_get_angle()); -#endif + if (IS_ENABLED(CONFIG_LID_ANGLE)) + CPRINTF("a=%-4d", motion_lid_get_angle()); CPRINTF("]\n"); } -#endif -#ifdef CONFIG_MOTION_FILL_LPC_SENSE_DATA - update_sense_data(lpc_status, &sample_id); -#endif + if (IS_ENABLED(CONFIG_MOTION_FILL_LPC_SENSE_DATA)) + update_sense_data(lpc_status, &sample_id); /* * Ask the host to flush the queue if @@ -947,32 +872,28 @@ void motion_sense_task(void *u) * - we haven't done it for a while. */ if (IS_ENABLED(CONFIG_ACCEL_FIFO) && - (motion_sense_fifo_wake_up_needed() || + (motion_sense_fifo_bypass_needed() || + motion_sense_fifo_interrupt_needed() || event & (TASK_EVENT_MOTION_ODR_CHANGE | TASK_EVENT_MOTION_FLUSH_PENDING) || - motion_sense_fifo_over_thres() || - (ap_event_interval > 0 && - time_after(ts_begin_task.le.lo, - ts_last_int.le.lo + ap_event_interval)))) { + motion_sense_fifo_over_thres())) { if ((event & TASK_EVENT_MOTION_FLUSH_PENDING) == 0) { motion_sense_fifo_add_timestamp( __hw_clock_source_read()); } - ts_last_int = ts_begin_task; -#ifdef CONFIG_MKBP_EVENT /* * Send an event if we know we are in S0 and the kernel * driver is listening, or the AP needs to be waken up. * In the latter case, the driver pulls the event and * will resume listening until it is suspended again. */ - if ((fifo_int_enabled && - sensor_active == SENSOR_ACTIVE_S0) || - motion_sense_fifo_wake_up_needed()) { + if ((IS_ENABLED(CONFIG_MKBP_EVENT) && + ((fifo_int_enabled && + sensor_active == SENSOR_ACTIVE_S0) || + motion_sense_fifo_wake_up_needed()))) { mkbp_send_event(EC_MKBP_EVENT_SENSOR_FIFO); - motion_sense_fifo_reset_wake_up_needed(); } -#endif /* CONFIG_MKBP_EVENT */ + motion_sense_fifo_reset_needed_flags(); } ts_end_task = get_time(); @@ -982,7 +903,7 @@ void motion_sense_task(void *u) struct motion_sensor_t *sensor = &motion_sensors[i]; if (!motion_sensor_in_forced_mode(sensor) || - sensor->collection_rate == 0) + sensor->collection_rate == 0) continue; time_diff = time_until(ts_end_task.le.lo, @@ -1000,9 +921,9 @@ void motion_sense_task(void *u) if (wait_us >= 0 && wait_us < motion_min_interval) { /* - * Guarantee some minimum delay to allow other lower - * priority tasks to run. - */ + * Guarantee some minimum delay to allow other lower + * priority tasks to run. + */ wait_us = motion_min_interval; } @@ -1014,8 +935,7 @@ void motion_sense_task(void *u) /* Host commands */ /* Function to map host sensor IDs to motion sensor. */ -static struct motion_sensor_t - *host_sensor_id_to_real_sensor(int host_id) +static struct motion_sensor_t *host_sensor_id_to_real_sensor(int host_id) { struct motion_sensor_t *sensor; @@ -1031,18 +951,13 @@ static struct motion_sensor_t return NULL; } -static struct motion_sensor_t - *host_sensor_id_to_motion_sensor(int host_id) +static struct motion_sensor_t *host_sensor_id_to_motion_sensor(int host_id) { -#ifdef CONFIG_GESTURE_HOST_DETECTION - if (host_id == MOTION_SENSE_ACTIVITY_SENSOR_ID) - /* - * Return the info for the first sensor that - * support some gestures. - */ + /* Return the info for the first sensor that support some gestures. */ + if (IS_ENABLED(CONFIG_GESTURE_HOST_DETECTION) && + (host_id == MOTION_SENSE_ACTIVITY_SENSOR_ID)) return host_sensor_id_to_real_sensor( __builtin_ctz(CONFIG_GESTURE_DETECTION_MASK)); -#endif return host_sensor_id_to_real_sensor(host_id); } @@ -1052,13 +967,20 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) struct ec_response_motion_sense *out = args->response; struct motion_sensor_t *sensor; int i, ret = EC_RES_INVALID_PARAM, reported; + const void *in_offset; + const void *in_scale; + void *out_calib_read; + void *out_scale; + void *out_offset; + int16_t out_temp; switch (in->cmd) { case MOTIONSENSE_CMD_DUMP: out->dump.module_flags = (*(host_get_memmap(EC_MEMMAP_ACC_STATUS)) & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT) ? - MOTIONSENSE_MODULE_FLAG_ACTIVE : 0; + MOTIONSENSE_MODULE_FLAG_ACTIVE : + 0; out->dump.sensor_count = ALL_MOTION_SENSORS; args->response_size = sizeof(out->dump); reported = MIN(ALL_MOTION_SENSORS, in->dump.max_sensor_count); @@ -1076,13 +998,14 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) } } mutex_unlock(&g_sensor_mutex); - args->response_size += reported * + args->response_size += + reported * sizeof(struct ec_response_motion_sensor_data); break; case MOTIONSENSE_CMD_DATA: sensor = host_sensor_id_to_real_sensor( - in->sensor_odr.sensor_num); + in->sensor_odr.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -1097,16 +1020,16 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_INFO: sensor = host_sensor_id_to_motion_sensor( - in->sensor_odr.sensor_num); + in->sensor_odr.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; -#ifdef CONFIG_GESTURE_HOST_DETECTION - if (in->sensor_odr.sensor_num == - MOTION_SENSE_ACTIVITY_SENSOR_ID) + if (IS_ENABLED(CONFIG_GESTURE_HOST_DETECTION) && + MOTION_SENSE_ACTIVITY_SENSOR_ID >= 0 && + (in->sensor_odr.sensor_num == + MOTION_SENSE_ACTIVITY_SENSOR_ID)) out->info.type = MOTIONSENSE_TYPE_ACTIVITY; else -#endif out->info.type = sensor->type; out->info.location = sensor->location; @@ -1116,7 +1039,8 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) if (args->version >= 3) { out->info_3.min_frequency = sensor->min_frequency; out->info_3.max_frequency = sensor->max_frequency; - out->info_3.fifo_max_event_count = MAX_FIFO_EVENT_COUNT; + out->info_3.fifo_max_event_count = + CONFIG_ACCEL_FIFO_SIZE; args->response_size = sizeof(out->info_3); } if (args->version >= 4) { @@ -1129,8 +1053,7 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) break; case MOTIONSENSE_CMD_EC_RATE: - sensor = host_sensor_id_to_real_sensor( - in->sensor_odr.sensor_num); + sensor = host_sensor_id_to_real_sensor(in->ec_rate.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -1139,18 +1062,20 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) * has a value. */ if (in->ec_rate.data != EC_MOTION_SENSE_NO_VALUE) { - sensor->config[SENSOR_CONFIG_AP].ec_rate = - motion_sense_set_ec_rate_from_ap( - sensor, in->ec_rate.data * MSEC); - /* Bound the new sampling rate. */ - motion_sense_set_motion_intervals(); + int new_ec_rate = in->ec_rate.data * MSEC; + + if (new_ec_rate > 0) + new_ec_rate = + MAX(new_ec_rate, motion_min_interval); + sensor->config[SENSOR_CONFIG_AP].ec_rate = new_ec_rate; /* Force a collection to purge old events. */ task_set_event(TASK_ID_MOTIONSENSE, - TASK_EVENT_MOTION_ODR_CHANGE, 0); + TASK_EVENT_MOTION_ODR_CHANGE); } - out->ec_rate.ret = motion_sense_ec_rate(sensor) / MSEC; + out->ec_rate.ret = + sensor->config[SENSOR_CONFIG_AP].ec_rate / MSEC; args->response_size = sizeof(out->ec_rate); break; @@ -1158,7 +1083,7 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_SENSOR_ODR: /* Verify sensor number is valid. */ sensor = host_sensor_id_to_real_sensor( - in->sensor_odr.sensor_num); + in->sensor_odr.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -1172,10 +1097,10 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) * The new ODR may suspend sensor, leaving samples * in the FIFO. Flush it explicitly. */ - deprecated_atomic_or(&odr_event_required, - 1 << (sensor - motion_sensors)); + atomic_or(&odr_event_required, + BIT(sensor - motion_sensors)); task_set_event(TASK_ID_MOTIONSENSE, - TASK_EVENT_MOTION_ODR_CHANGE, 0); + TASK_EVENT_MOTION_ODR_CHANGE); } out->sensor_odr.ret = sensor->drv->get_data_rate(sensor); @@ -1187,7 +1112,7 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_SENSOR_RANGE: /* Verify sensor number is valid. */ sensor = host_sensor_id_to_real_sensor( - in->sensor_range.sensor_num); + in->sensor_range.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; /* Set new range if the data arg has a value. */ @@ -1195,25 +1120,21 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) if (!sensor->drv->set_range) return EC_RES_INVALID_COMMAND; - if (sensor->drv->set_range(sensor, - in->sensor_range.data, - in->sensor_range.roundup) - != EC_SUCCESS) { + if (sensor->drv->set_range( + sensor, in->sensor_range.data, + in->sensor_range.roundup) != EC_SUCCESS) { return EC_RES_INVALID_PARAM; } } - if (!sensor->drv->get_range) - return EC_RES_INVALID_COMMAND; - - out->sensor_range.ret = sensor->drv->get_range(sensor); + out->sensor_range.ret = sensor->current_range; args->response_size = sizeof(out->sensor_range); break; case MOTIONSENSE_CMD_SENSOR_OFFSET: /* Verify sensor number is valid. */ sensor = host_sensor_id_to_real_sensor( - in->sensor_offset.sensor_num); + in->sensor_offset.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; /* Set new range if the data arg has a value. */ @@ -1221,9 +1142,9 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) if (!sensor->drv->set_offset) return EC_RES_INVALID_COMMAND; - ret = sensor->drv->set_offset(sensor, - in->sensor_offset.offset, - in->sensor_offset.temp); + in_offset = in->sensor_offset.offset; + ret = sensor->drv->set_offset(sensor, in_offset, + in->sensor_offset.temp); if (ret != EC_SUCCESS) return ret; } @@ -1231,17 +1152,19 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) if (!sensor->drv->get_offset) return EC_RES_INVALID_COMMAND; - ret = sensor->drv->get_offset(sensor, out->sensor_offset.offset, - &out->sensor_offset.temp); + out_offset = out->sensor_offset.offset; + ret = sensor->drv->get_offset(sensor, out_offset, &out_temp); if (ret != EC_SUCCESS) return ret; + + out->sensor_offset.temp = out_temp; args->response_size = sizeof(out->sensor_offset); break; case MOTIONSENSE_CMD_SENSOR_SCALE: /* Verify sensor number is valid. */ sensor = host_sensor_id_to_real_sensor( - in->sensor_scale.sensor_num); + in->sensor_scale.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; /* Set new range if the data arg has a value. */ @@ -1249,9 +1172,9 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) if (!sensor->drv->set_scale) return EC_RES_INVALID_COMMAND; - ret = sensor->drv->set_scale(sensor, - in->sensor_scale.scale, - in->sensor_scale.temp); + in_scale = in->sensor_scale.scale; + ret = sensor->drv->set_scale(sensor, in_scale, + in->sensor_scale.temp); if (ret != EC_SUCCESS) return ret; } @@ -1259,46 +1182,56 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) if (!sensor->drv->get_scale) return EC_RES_INVALID_COMMAND; - ret = sensor->drv->get_scale(sensor, out->sensor_scale.scale, - &out->sensor_scale.temp); + out_scale = out->sensor_scale.scale; + ret = sensor->drv->get_scale(sensor, out_scale, &out_temp); if (ret != EC_SUCCESS) return ret; + + out->sensor_scale.temp = out_temp; args->response_size = sizeof(out->sensor_scale); break; case MOTIONSENSE_CMD_PERFORM_CALIB: /* Verify sensor number is valid. */ sensor = host_sensor_id_to_real_sensor( - in->perform_calib.sensor_num); + in->perform_calib.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; if (!sensor->drv->perform_calib) return EC_RES_INVALID_COMMAND; - ret = sensor->drv->perform_calib( - sensor, in->perform_calib.enable); + ret = sensor->drv->perform_calib(sensor, + in->perform_calib.enable); if (ret != EC_SUCCESS) return ret; - ret = sensor->drv->get_offset(sensor, out->perform_calib.offset, - &out->perform_calib.temp); + + out_offset = out->perform_calib.offset; + ret = sensor->drv->get_offset(sensor, out_offset, &out_temp); if (ret != EC_SUCCESS) return ret; + + out->perform_calib.temp = out_temp; args->response_size = sizeof(out->perform_calib); break; case MOTIONSENSE_CMD_FIFO_FLUSH: - if (!IS_ENABLED(CONFIG_ACCEL_FIFO)) - return EC_RES_INVALID_PARAM; +/* TODO (http://b/255967867) Can't use the IS_ENABLED macro here because + * __fallthrough fails in clang as unreachable code. + */ +#ifndef CONFIG_ACCEL_FIFO + return EC_RES_INVALID_PARAM; +#else sensor = host_sensor_id_to_real_sensor( - in->sensor_odr.sensor_num); + in->sensor_odr.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; - deprecated_atomic_add(&sensor->flush_pending, 1); + atomic_add(&sensor->flush_pending, 1); task_set_event(TASK_ID_MOTIONSENSE, - TASK_EVENT_MOTION_FLUSH_PENDING, 0); - /* pass-through */ + TASK_EVENT_MOTION_FLUSH_PENDING); + __fallthrough; +#endif case MOTIONSENSE_CMD_FIFO_INFO: if (!IS_ENABLED(CONFIG_ACCEL_FIFO)) { /* @@ -1310,12 +1243,8 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) break; } motion_sense_fifo_get_info(&out->fifo_info, 1); - for (i = 0; i < motion_sensor_count; i++) { - out->fifo_info.lost[i] = motion_sensors[i].lost; - motion_sensors[i].lost = 0; - } args->response_size = sizeof(out->fifo_info) + - sizeof(uint16_t) * motion_sensor_count; + sizeof(uint16_t) * motion_sensor_count; break; case MOTIONSENSE_CMD_FIFO_READ: @@ -1323,8 +1252,7 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) return EC_RES_INVALID_PARAM; out->fifo_read.number_data = motion_sense_fifo_read( args->response_max - sizeof(out->fifo_read), - in->fifo_read.max_data_vector, - out->fifo_read.data, + in->fifo_read.max_data_vector, out->fifo_read.data, &(args->response_size)); args->response_size += sizeof(out->fifo_read); break; @@ -1335,7 +1263,7 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) case 0: case 1: fifo_int_enabled = in->fifo_int_enable.enable; - /* fallthrough */ + __fallthrough; case EC_MOTION_SENSE_NO_VALUE: out->fifo_int_enable.ret = fifo_int_enabled; args->response_size = sizeof(out->fifo_int_enable); @@ -1352,13 +1280,11 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) if (sensor == NULL) return EC_RES_INVALID_PARAM; - + out_calib_read = &out->online_calib_read; args->response_size = - online_calibration_read( - (int)(sensor - motion_sensors), - out->online_calib_read.data) - ? sizeof(struct ec_response_online_calibration_data) - : 0; + online_calibration_read(sensor, out_calib_read) ? + sizeof(struct ec_response_online_calibration_data) : + 0; break; #ifdef CONFIG_GESTURE_HOST_DETECTION case MOTIONSENSE_CMD_LIST_ACTIVITIES: { @@ -1371,22 +1297,22 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) while (mask && ret == EC_RES_SUCCESS) { i = get_next_bit(&mask); sensor = &motion_sensors[i]; - ret = sensor->drv->list_activities(sensor, - &enabled, &disabled); + ret = sensor->drv->list_activities(sensor, &enabled, + &disabled); if (ret == EC_RES_SUCCESS) { out->list_activities.enabled |= enabled; out->list_activities.disabled |= disabled; } } -#ifdef CONFIG_BODY_DETECTION - if (body_detect_get_enable()) { - out->list_activities.enabled |= - BIT(MOTIONSENSE_ACTIVITY_BODY_DETECTION); - } else { - out->list_activities.disabled |= - BIT(MOTIONSENSE_ACTIVITY_BODY_DETECTION); + if (IS_ENABLED(CONFIG_BODY_DETECTION)) { + if (body_detect_get_enable()) { + out->list_activities.enabled |= BIT( + MOTIONSENSE_ACTIVITY_BODY_DETECTION); + } else { + out->list_activities.disabled |= BIT( + MOTIONSENSE_ACTIVITY_BODY_DETECTION); + } } -#endif if (ret != EC_RES_SUCCESS) return ret; args->response_size = sizeof(out->list_activities); @@ -1400,35 +1326,32 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) while (mask && ret == EC_RES_SUCCESS) { i = get_next_bit(&mask); sensor = &motion_sensors[i]; - sensor->drv->list_activities(sensor, - &enabled, &disabled); + sensor->drv->list_activities(sensor, &enabled, + &disabled); if ((1 << in->set_activity.activity) & (enabled | disabled)) - ret = sensor->drv->manage_activity(sensor, - in->set_activity.activity, - in->set_activity.enable, - &in->set_activity); + ret = sensor->drv->manage_activity( + sensor, in->set_activity.activity, + in->set_activity.enable, + &in->set_activity); } -#ifdef CONFIG_BODY_DETECTION - if (in->set_activity.activity == - MOTIONSENSE_ACTIVITY_BODY_DETECTION) + if (IS_ENABLED(CONFIG_BODY_DETECTION) && + (in->set_activity.activity == + MOTIONSENSE_ACTIVITY_BODY_DETECTION)) body_detect_set_enable(in->set_activity.enable); -#endif if (ret != EC_RES_SUCCESS) return ret; args->response_size = 0; break; } case MOTIONSENSE_CMD_GET_ACTIVITY: { - switch (in->get_activity.activity) { -#ifdef CONFIG_BODY_DETECTION - case MOTIONSENSE_ACTIVITY_BODY_DETECTION: - out->get_activity.state = (uint8_t) - body_detect_get_state(); + if (IS_ENABLED(CONFIG_BODY_DETECTION) && + (in->get_activity.activity == + MOTIONSENSE_ACTIVITY_BODY_DETECTION)) { + out->get_activity.state = + (uint8_t)body_detect_get_state(); ret = EC_RES_SUCCESS; - break; -#endif - default: + } else { ret = EC_RES_INVALID_PARAM; } if (ret != EC_RES_SUCCESS) @@ -1440,6 +1363,56 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) #ifdef CONFIG_ACCEL_SPOOF_MODE case MOTIONSENSE_CMD_SPOOF: { + /* spoof activity if it is activity sensor */ + if (IS_ENABLED(CONFIG_GESTURE_HOST_DETECTION) && + MOTION_SENSE_ACTIVITY_SENSOR_ID >= 0 && + in->spoof.sensor_id == MOTION_SENSE_ACTIVITY_SENSOR_ID) { + switch (in->spoof.activity_num) { +#ifdef CONFIG_BODY_DETECTION + case MOTIONSENSE_ACTIVITY_BODY_DETECTION: + switch (in->spoof.spoof_enable) { + case MOTIONSENSE_SPOOF_MODE_DISABLE: + /* Disable spoofing. */ + body_detect_set_spoof(false); + break; + case MOTIONSENSE_SPOOF_MODE_CUSTOM: + /* + * Enable spoofing, but use provided + * state + */ + body_detect_set_spoof(true); + body_detect_change_state( + in->spoof.activity_state, true); + break; + case MOTIONSENSE_SPOOF_MODE_LOCK_CURRENT: + /* + * Enable spoofing, but lock to current + * state + */ + body_detect_set_spoof(true); + break; + case MOTIONSENSE_SPOOF_MODE_QUERY: + /* + * Query the spoof status of the + * activity + */ + out->spoof.ret = + body_detect_get_spoof(); + args->response_size = + sizeof(out->spoof); + break; + default: + return EC_RES_INVALID_PARAM; + } + break; +#endif + default: + return EC_RES_INVALID_PARAM; + } + break; + } + + /* spoof accel data */ sensor = host_sensor_id_to_real_sensor(in->spoof.sensor_id); if (sensor == NULL) return EC_RES_INVALID_PARAM; @@ -1474,7 +1447,7 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_SPOOF_MODE_QUERY: /* Querying the spoof status of the sensor. */ out->spoof.ret = !!(sensor->flags & - MOTIONSENSE_FLAG_IN_SPOOF_MODE); + MOTIONSENSE_FLAG_IN_SPOOF_MODE); args->response_size = sizeof(out->spoof); break; @@ -1494,10 +1467,10 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) default: /* Call other users of the motion task */ -#ifdef CONFIG_LID_ANGLE - if (ret == EC_RES_INVALID_PARAM) + if (IS_ENABLED(CONFIG_LID_ANGLE) && + (ret == EC_RES_INVALID_PARAM) && + sensor_board_is_lid_angle_available()) ret = host_cmd_motion_lid(args); -#endif return ret; } @@ -1506,12 +1479,12 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) DECLARE_HOST_COMMAND(EC_CMD_MOTION_SENSE_CMD, host_cmd_motion_sense, EC_VER_MASK(1) | EC_VER_MASK(2) | EC_VER_MASK(3) | - EC_VER_MASK(4)); + EC_VER_MASK(4)); /*****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_ACCELS -static int command_accelrange(int argc, char **argv) +static int command_accelrange(int argc, const char **argv) { char *e; int id, data, round = 1; @@ -1544,22 +1517,19 @@ static int command_accelrange(int argc, char **argv) * Write new range, if it returns invalid arg, then return * a parameter error. */ - if (sensor->drv->set_range(sensor, - data, - round) == EC_ERROR_INVAL) + if (sensor->drv->set_range(sensor, data, round) == + EC_ERROR_INVAL) return EC_ERROR_PARAM2; } else { - ccprintf("Range for sensor %d: %d\n", id, - sensor->drv->get_range(sensor)); + ccprintf("Sensor %d range: %d\n", id, sensor->current_range); } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(accelrange, command_accelrange, - "id [data [roundup]]", - "Read or write accelerometer range"); +DECLARE_CONSOLE_COMMAND(accelrange, command_accelrange, "id [data [roundup]]", + "Read or write accelerometer range"); -static int command_accelresolution(int argc, char **argv) +static int command_accelresolution(int argc, const char **argv) { char *e; int id, data, round = 1; @@ -1593,8 +1563,8 @@ static int command_accelresolution(int argc, char **argv) * return a parameter error. */ if (sensor->drv->set_resolution && - sensor->drv->set_resolution(sensor, data, round) - == EC_ERROR_INVAL) + sensor->drv->set_resolution(sensor, data, round) == + EC_ERROR_INVAL) return EC_ERROR_PARAM2; } else { ccprintf("Resolution for sensor %d: %d\n", id, @@ -1604,10 +1574,10 @@ static int command_accelresolution(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(accelres, command_accelresolution, - "id [data [roundup]]", - "Read or write accelerometer resolution"); + "id [data [roundup]]", + "Read or write accelerometer resolution"); -static int command_accel_data_rate(int argc, char **argv) +static int command_accel_data_rate(int argc, const char **argv) { char *e; int id, data, round = 1; @@ -1644,28 +1614,26 @@ static int command_accel_data_rate(int argc, char **argv) */ config_id = motion_sense_get_ec_config(); sensor->config[SENSOR_CONFIG_AP].odr = 0; - sensor->config[config_id].odr = - data | (round ? ROUND_UP_FLAG : 0); + sensor->config[config_id].odr = data | + (round ? ROUND_UP_FLAG : 0); - deprecated_atomic_or(&odr_event_required, - 1 << (sensor - motion_sensors)); + atomic_or(&odr_event_required, 1 << (sensor - motion_sensors)); task_set_event(TASK_ID_MOTIONSENSE, - TASK_EVENT_MOTION_ODR_CHANGE, 0); + TASK_EVENT_MOTION_ODR_CHANGE); } else { ccprintf("Data rate for sensor %d: %d\n", id, sensor->drv->get_data_rate(sensor)); ccprintf("EC rate for sensor %d: %d\n", id, - motion_sense_ec_rate(sensor)); - ccprintf("Current Interrupt rate: %d\n", ap_event_interval); + sensor->config[SENSOR_CONFIG_AP].ec_rate); } return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(accelrate, command_accel_data_rate, - "id [data [roundup]]", - "Read or write accelerometer ODR"); + "id [data [roundup]]", + "Read or write accelerometer ODR"); -static int command_accel_read_xyz(int argc, char **argv) +static int command_accel_read_xyz(int argc, const char **argv) { char *e; int id, n = 1, ret; @@ -1686,25 +1654,24 @@ static int command_accel_read_xyz(int argc, char **argv) sensor = &motion_sensors[id]; - while ((n == -1) || (n-- > 0)) { + while ((n-- > 0)) { ret = sensor->drv->read(sensor, v); if (ret == 0) - ccprintf("Current data %d: %-5d %-5d %-5d\n", - id, v[X], v[Y], v[Z]); + ccprintf("Current data %d: %-5d %-5d %-5d\n", id, v[X], + v[Y], v[Z]); else ccprintf("vector not ready\n"); - ccprintf("Last calib. data %d: %-5d %-5d %-5d\n", - id, sensor->xyz[X], sensor->xyz[Y], sensor->xyz[Z]); + ccprintf("Last calib. data %d: %-5d %-5d %-5d\n", id, + sensor->xyz[X], sensor->xyz[Y], sensor->xyz[Z]); task_wait_event(motion_min_interval); } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(accelread, command_accel_read_xyz, - "id [n]", - "Read sensor x/y/z"); +DECLARE_CONSOLE_COMMAND(accelread, command_accel_read_xyz, "id [n]", + "Read sensor x/y/z"); -static int command_accel_init(int argc, char **argv) +static int command_accel_init(int argc, const char **argv) { char *e; int id, ret; @@ -1725,16 +1692,14 @@ static int command_accel_init(int argc, char **argv) ccprintf("%s: state %d - %d\n", sensor->name, sensor->state, ret); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(accelinit, command_accel_init, - "id", - "Init sensor"); +DECLARE_CONSOLE_COMMAND(accelinit, command_accel_init, "id", "Init sensor"); #ifdef CONFIG_CMD_ACCEL_INFO -static int command_display_accel_info(int argc, char **argv) +static int command_display_accel_info(int argc, const char **argv) { int val, i, j; - if (argc > 3) + if (argc >= 3) return EC_ERROR_PARAM_COUNT; ccprintf("Motion sensors count = %d\n", motion_sensor_count); @@ -1747,17 +1712,17 @@ static int command_display_accel_info(int argc, char **argv) ccprintf("type: %d\n", motion_sensors[i].type); ccprintf("location: %d\n", motion_sensors[i].location); ccprintf("port: %d\n", motion_sensors[i].port); - ccprintf("addr: %d\n", I2C_GET_ADDR(motion_sensors[i] - .i2c_spi_addr_flags)); - ccprintf("range: %d\n", motion_sensors[i].default_range); + ccprintf("addr: %d\n", + I2C_STRIP_FLAGS(motion_sensors[i].i2c_spi_addr_flags)); + ccprintf("range: %d\n", motion_sensors[i].current_range); ccprintf("min_freq: %d\n", motion_sensors[i].min_frequency); ccprintf("max_freq: %d\n", motion_sensors[i].max_frequency); ccprintf("config:\n"); for (j = 0; j < SENSOR_CONFIG_MAX; j++) { ccprintf("%d - odr: %umHz, ec_rate: %uus\n", j, - motion_sensors[i].config[j].odr & - ~ROUND_UP_FLAG, - motion_sensors[i].config[j].ec_rate); + motion_sensors[i].config[j].odr & + ~ROUND_UP_FLAG, + motion_sensors[i].config[j].ec_rate); } } @@ -1771,59 +1736,26 @@ static int command_display_accel_info(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(accelinfo, command_display_accel_info, - "on/off [interval]", - "Print motion sensor info, lid angle calculations" - " and set calculation frequency."); +DECLARE_CONSOLE_COMMAND(accelinfo, command_display_accel_info, "on/off", + "Print motion sensor info, lid angle calculations."); #endif /* CONFIG_CMD_ACCEL_INFO */ -#ifdef CONFIG_CMD_ACCEL_FIFO -static int motion_sense_read_fifo(int argc, char **argv) -{ - int count, i; - struct ec_response_motion_sensor_data v; - - if (argc < 1) - return EC_ERROR_PARAM_COUNT; - - /* Limit the amount of data to avoid saturating the UART buffer */ - count = MIN(queue_count(&motion_sense_fifo), 16); - for (i = 0; i < count; i++) { - queue_peek_units(&motion_sense_fifo, &v, i, 1); - if (v.flags & (MOTIONSENSE_SENSOR_FLAG_TIMESTAMP | - MOTIONSENSE_SENSOR_FLAG_FLUSH)) { - uint64_t timestamp; - memcpy(×tamp, v.data, sizeof(v.data)); - ccprintf("Timestamp: 0x%016llx%s\n", timestamp, - (v.flags & MOTIONSENSE_SENSOR_FLAG_FLUSH ? - " - Flush" : "")); - } else { - ccprintf("%d %d: %-5d %-5d %-5d\n", i, v.sensor_num, - v.data[X], v.data[Y], v.data[Z]); - } - } - return EC_SUCCESS; -} - -DECLARE_CONSOLE_COMMAND(fiforead, motion_sense_read_fifo, - "id", - "Read Fifo sensor"); -#endif /* defined(CONFIG_CMD_ACCEL_FIFO) */ #endif /* CONFIG_CMD_ACCELS */ #ifdef CONFIG_ACCEL_SPOOF_MODE static void print_spoof_mode_status(int id) { CPRINTS("Sensor %d spoof mode is %s. <%d, %d, %d>", id, - (motion_sensors[id].flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE) - ? "enabled" : "disabled", + (motion_sensors[id].flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE) ? + "enabled" : + "disabled", motion_sensors[id].spoof_xyz[X], motion_sensors[id].spoof_xyz[Y], motion_sensors[id].spoof_xyz[Z]); } #ifdef CONFIG_CMD_ACCELSPOOF -static int command_accelspoof(int argc, char **argv) +static int command_accelspoof(int argc, const char **argv) { char *e; int id, enable, i; @@ -1858,8 +1790,8 @@ static int command_accelspoof(int argc, char **argv) */ if (argc == 6) { for (i = 0; i < 3; i++) - s->spoof_xyz[i] = strtoi(argv[3 + i], - &e, 0); + s->spoof_xyz[i] = + strtoi(argv[3 + i], &e, 0); } else if (argc == 3) { for (i = X; i <= Z; i++) s->spoof_xyz[i] = s->raw_xyz[i]; diff --git a/common/motion_sense_fifo.c b/common/motion_sense_fifo.c index 2325de4c87..1a7303bc79 100644 --- a/common/motion_sense_fifo.c +++ b/common/motion_sense_fifo.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,16 +6,24 @@ #include "accelgyro.h" #include "console.h" #include "hwtimer.h" +#include "math_util.h" #include "mkbp_event.h" #include "motion_sense_fifo.h" +#include "online_calibration.h" +#include "stdbool.h" #include "tablet_mode.h" #include "task.h" #include "util.h" -#include "math_util.h" -#include "online_calibration.h" -#include "stdbool.h" -#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args) + +/* + * Adjustment in us to ec rate when calculating interrupt interval: + * To be sure the EC will send an interrupt even if it finishes processing + * events slightly earlier than the previous period. + */ +#define MOTION_SENSOR_INT_ADJUSTMENT_US \ + (CONFIG_MOTION_MIN_SENSE_WAIT_TIME * MSEC / 10) /** * Staged metadata for the fifo queue. @@ -50,6 +58,12 @@ static struct queue fifo = QUEUE_NULL(CONFIG_ACCEL_FIFO_SIZE, struct ec_response_motion_sensor_data); /** Count of the number of entries lost due to a small queue. */ static int fifo_lost; +/* + * How many vector events are lost in the FIFO since last time + * FIFO info has been transmitted. + */ +static uint16_t fifo_sensor_lost[MAX_MOTION_SENSORS]; + /** Metadata for the fifo, used for staging and spreading data. */ static struct fifo_staged fifo_staged; @@ -59,22 +73,46 @@ static struct fifo_staged fifo_staged; */ static struct timestamp_state next_timestamp[MAX_MOTION_SENSORS]; +/** + * Expected data periods: + * copy of collection rate, updated when ODR changes. + */ +static uint32_t expected_data_periods[MAX_MOTION_SENSORS]; + +/** + * Calculated data periods: + * can be different from collection rate when spreading. + */ +static uint32_t data_periods[MAX_MOTION_SENSORS]; + /** * Bitmap telling which sensors have valid entries in the next_timestamp array. */ static uint32_t next_timestamp_initialized; +/** Need to bypass the FIFO for an important message. */ +static int bypass_needed; + /** Need to wake up the AP. */ static int wake_up_needed; +/** Need to interrupt the AP. */ +static int ap_interrupt_needed; + +/** + * Timestamp of the first event put in the fifo during the + * last motion_task invocation. + */ +uint32_t ts_last_int[MAX_MOTION_SENSORS]; + /** * Check whether or not a give sensor data entry is a timestamp or not. * * @param data The data entry to check. * @return 1 if the entry is a timestamp, 0 otherwise. */ -static inline int is_timestamp( - const struct ec_response_motion_sensor_data *data) +static inline int +is_timestamp(const struct ec_response_motion_sensor_data *data) { return data->flags & MOTIONSENSE_SENSOR_FLAG_TIMESTAMP; } @@ -99,8 +137,8 @@ static inline bool is_data(const struct ec_response_motion_sensor_data *data) */ static inline struct ec_response_motion_sensor_data *get_fifo_head(void) { - return ((struct ec_response_motion_sensor_data *) fifo.buffer) + - (fifo.state->head & fifo.buffer_units_mask); + return ((struct ec_response_motion_sensor_data *)fifo.buffer) + + (fifo.state->head & fifo.buffer_units_mask); } /** @@ -146,7 +184,7 @@ static void fifo_pop(void) /* Increment lost counter if we have valid data. */ if (!is_timestamp(head)) - motion_sensors[head->sensor_num].lost++; + fifo_sensor_lost[head->sensor_num]++; /* * We're done if the initial count was non-zero and we only advanced the @@ -225,15 +263,17 @@ static inline bool is_new_timestamp(uint8_t sensor_num) * @param data The data to stage. * @param sensor The sensor that generated the data * @param valid_data The number of readable data entries in the data. + * sensor can be NULL (for activity sensors). valid_data must be 0 then. */ -static void fifo_stage_unit( - struct ec_response_motion_sensor_data *data, - struct motion_sensor_t *sensor, - int valid_data) +static void fifo_stage_unit(struct ec_response_motion_sensor_data *data, + struct motion_sensor_t *sensor, int valid_data) { struct queue_chunk chunk; int i; + if (valid_data > 0 && !sensor) + return; + mutex_lock(&g_sensor_mutex); for (i = 0; i < valid_data; i++) @@ -263,7 +303,7 @@ static void fifo_stage_unit( if (removed) { mutex_unlock(&g_sensor_mutex); if (IS_ENABLED(CONFIG_ONLINE_CALIB) && - next_timestamp_initialized & BIT(data->sensor_num)) + !is_new_timestamp(data->sensor_num)) online_calibration_process_data( data, sensor, next_timestamp[data->sensor_num].next); @@ -276,7 +316,8 @@ static void fifo_stage_unit( if (IS_ENABLED(CONFIG_TABLET_MODE)) data->flags |= (tablet_get_mode() ? - MOTIONSENSE_SENSOR_FLAG_TABLET_MODE : 0); + MOTIONSENSE_SENSOR_FLAG_TABLET_MODE : + 0); /* * Get the next writable block in the fifo. We don't need to lock this @@ -313,8 +354,7 @@ static void fifo_stage_unit( * If the new per-sensor sample count is greater than 1, we'll need to * spread. */ - if (IS_ENABLED(CONFIG_SENSOR_TIGHT_TIMESTAMPS) && - !is_timestamp(data) && + if (IS_ENABLED(CONFIG_SENSOR_TIGHT_TIMESTAMPS) && !is_timestamp(data) && ++fifo_staged.sample_count[data->sensor_num] > 1) fifo_staged.requires_spreading = 1; @@ -348,8 +388,9 @@ static void fifo_stage_timestamp(uint32_t timestamp, uint8_t sensor_num) static inline struct ec_response_motion_sensor_data * peek_fifo_staged(size_t offset) { - return (struct ec_response_motion_sensor_data *) - queue_get_write_chunk(&fifo, offset).buffer; + return (struct ec_response_motion_sensor_data *)queue_get_write_chunk( + &fifo, offset) + .buffer; } void motion_sense_fifo_init(void) @@ -358,26 +399,41 @@ void motion_sense_fifo_init(void) online_calibration_init(); } -int motion_sense_fifo_wake_up_needed(void) +int motion_sense_fifo_interrupt_needed(void) { - int res; + return ap_interrupt_needed; +} - mutex_lock(&g_sensor_mutex); - res = wake_up_needed; - mutex_unlock(&g_sensor_mutex); - return res; +int motion_sense_fifo_bypass_needed(void) +{ + return bypass_needed; } -void motion_sense_fifo_reset_wake_up_needed(void) +int motion_sense_fifo_wake_up_needed(void) { - mutex_lock(&g_sensor_mutex); + return wake_up_needed; +} + +void motion_sense_fifo_reset_needed_flags(void) +{ + int i; + + if (ap_interrupt_needed) { + ap_interrupt_needed = 0; + /* + * The FIFO is emptied, note timestamp of the last event sent + * as we start counting the delay based on that timestamp. + */ + for (i = 0; i < MAX_MOTION_SENSORS; i++) + if (!is_new_timestamp(i)) + ts_last_int[i] = next_timestamp[i].prev; + } wake_up_needed = 0; - mutex_unlock(&g_sensor_mutex); + bypass_needed = 0; } -void motion_sense_fifo_insert_async_event( - struct motion_sensor_t *sensor, - enum motion_sense_async_event event) +void motion_sense_fifo_insert_async_event(struct motion_sensor_t *sensor, + enum motion_sense_async_event event) { struct ec_response_motion_sensor_data vector; @@ -395,25 +451,29 @@ inline void motion_sense_fifo_add_timestamp(uint32_t timestamp) motion_sense_fifo_commit_data(); } -void motion_sense_fifo_stage_data( - struct ec_response_motion_sensor_data *data, - struct motion_sensor_t *sensor, - int valid_data, - uint32_t time) +void motion_sense_fifo_stage_data(struct ec_response_motion_sensor_data *data, + struct motion_sensor_t *sensor, + int valid_data, uint32_t time) { + int id = data->sensor_num; + if (IS_ENABLED(CONFIG_SENSOR_TIGHT_TIMESTAMPS)) { /* First entry, save the time for spreading later. */ if (!fifo_staged.count) fifo_staged.read_ts = __hw_clock_source_read(); fifo_stage_timestamp(time, data->sensor_num); } + if (sensor && sensor->config[SENSOR_CONFIG_AP].ec_rate > 0 && + time_after(time, ts_last_int[id] + + sensor->config[SENSOR_CONFIG_AP].ec_rate - + MOTION_SENSOR_INT_ADJUSTMENT_US)) { + ap_interrupt_needed = 1; + } fifo_stage_unit(data, sensor, valid_data); } void motion_sense_fifo_commit_data(void) { - /* Cached data periods, static to store off stack. */ - static uint32_t data_periods[MAX_MOTION_SENSORS]; struct ec_response_motion_sensor_data *data; int i, window, sensor_num; @@ -454,15 +514,15 @@ void motion_sense_fifo_commit_data(void) if (!fifo_staged.sample_count[i]) continue; - period = motion_sensors[i].collection_rate; + period = expected_data_periods[i]; /* * Clamp the sample period to the MIN of collection_rate and the * window length / (sample count - 1). */ if (window && fifo_staged.sample_count[i] > 1) - period = MIN( - period, - window / (fifo_staged.sample_count[i] - 1)); + period = + MIN(period, + window / (fifo_staged.sample_count[i] - 1)); data_periods[i] = period; } @@ -478,6 +538,8 @@ void motion_sense_fifo_commit_data(void) */ for (i = 0; i < fifo_staged.count; i++) { data = peek_fifo_staged(i); + if (data->flags & MOTIONSENSE_SENSOR_FLAG_BYPASS_FIFO) + bypass_needed = 1; if (data->flags & MOTIONSENSE_SENSOR_FLAG_WAKEUP) wake_up_needed = 1; @@ -503,7 +565,7 @@ void motion_sense_fifo_commit_data(void) * sensor or the timestamp is after our computed next, skip * ahead. */ - if (!(next_timestamp_initialized & BIT(sensor_num)) || + if (is_new_timestamp(sensor_num) || time_after(data->timestamp, next_timestamp[sensor_num].prev)) { next_timestamp[sensor_num].next = data->timestamp; @@ -515,9 +577,9 @@ void motion_sense_fifo_commit_data(void) next_timestamp[sensor_num].prev = next_timestamp[sensor_num].next; next_timestamp[sensor_num].next += - fifo_staged.requires_spreading - ? data_periods[sensor_num] - : motion_sensors[sensor_num].collection_rate; + fifo_staged.requires_spreading ? + data_periods[sensor_num] : + expected_data_periods[sensor_num]; /* Update online calibration if enabled. */ data = peek_fifo_staged(i); @@ -537,22 +599,29 @@ void motion_sense_fifo_commit_data(void) } void motion_sense_fifo_get_info( - struct ec_response_motion_sense_fifo_info *fifo_info, - int reset) + struct ec_response_motion_sense_fifo_info *fifo_info, int reset) { + int i; + mutex_lock(&g_sensor_mutex); fifo_info->size = fifo.buffer_units; fifo_info->count = queue_count(&fifo); fifo_info->total_lost = fifo_lost; + for (i = 0; i < MAX_MOTION_SENSORS; i++) { + fifo_info->lost[i] = fifo_sensor_lost[i]; + } mutex_unlock(&g_sensor_mutex); #ifdef CONFIG_MKBP_EVENT fifo_info->timestamp = mkbp_last_event_time; #endif - if (reset) + if (reset) { fifo_lost = 0; + memset(fifo_sensor_lost, 0, sizeof(fifo_sensor_lost)); + } } +/* LCOV_EXCL_START - function cannot be tested due to limitations with mkbp */ static int motion_sense_get_next_event(uint8_t *out) { union ec_response_get_next_data *data = @@ -561,7 +630,7 @@ static int motion_sense_get_next_event(uint8_t *out) motion_sense_fifo_get_info(&data->sensor_fifo.info, 0); return sizeof(data->sensor_fifo); } - +/* LCOV_EXCL_STOP */ DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_SENSOR_FIFO, motion_sense_get_next_event); inline int motion_sense_fifo_over_thres(void) @@ -592,8 +661,64 @@ int motion_sense_fifo_read(int capacity_bytes, int max_count, void *out, void motion_sense_fifo_reset(void) { + static uint8_t fifo_info_buffer + [sizeof(struct ec_response_motion_sense_fifo_info) + + sizeof(uint16_t) * MAX_MOTION_SENSORS]; + struct ec_response_motion_sense_fifo_info *fifo_info = + (void *)fifo_info_buffer; + next_timestamp_initialized = 0; memset(&fifo_staged, 0, sizeof(fifo_staged)); motion_sense_fifo_init(); queue_init(&fifo); + motion_sense_fifo_get_info(fifo_info, /*reset=*/true); +} + +void motion_sense_set_data_period(int sensor_num, uint32_t data_period) +{ + expected_data_periods[sensor_num] = data_period; + /* + * Reset the timestamp: + * - Avoid overflow when the sensor has been disabled for a long + * time. + * - First ODR setting. + * We may not send the first sample on time, but that is acceptable + * for CTS. + */ + ts_last_int[sensor_num] = __hw_clock_source_read(); + next_timestamp_initialized &= ~BIT(sensor_num); } + +#ifdef CONFIG_CMD_ACCEL_FIFO +static int motion_sense_read_fifo(int argc, char **argv) +{ + int count, i; + struct ec_response_motion_sensor_data v; + + if (argc < 1) + return EC_ERROR_PARAM_COUNT; + + /* Limit the amount of data to avoid saturating the UART buffer */ + count = MIN(queue_count(&fifo), 16); + for (i = 0; i < count; i++) { + queue_peek_units(&fifo, &v, i, 1); + if (v.flags & (MOTIONSENSE_SENSOR_FLAG_TIMESTAMP | + MOTIONSENSE_SENSOR_FLAG_FLUSH)) { + uint64_t timestamp; + + memcpy(×tamp, v.data, sizeof(v.data)); + ccprintf("Timestamp: 0x%016llx%s\n", timestamp, + (v.flags & MOTIONSENSE_SENSOR_FLAG_FLUSH ? + " - Flush" : + "")); + } else { + ccprintf("%d %d: %-5d %-5d %-5d\n", i, v.sensor_num, + v.data[X], v.data[Y], v.data[Z]); + } + } + return EC_SUCCESS; +} + +DECLARE_CONSOLE_COMMAND(fiforead, motion_sense_read_fifo, "id", + "Read Fifo sensor"); +#endif /* defined(CONFIG_CMD_ACCEL_FIFO) */ diff --git a/common/newton_fit.c b/common/newton_fit.c index ae81a45f07..3ba01dbd90 100644 --- a/common/newton_fit.c +++ b/common/newton_fit.c @@ -1,13 +1,14 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" #include "console.h" -#include "newton_fit.h" #include "math.h" #include "math_util.h" +#include "newton_fit.h" + #include #define CPRINTS(fmt, args...) cprints(CC_MOTION_SENSE, fmt, ##args) @@ -32,7 +33,7 @@ static fp_t compute_error(struct newton_fit *fit, fpv3_t center) _it = (struct newton_fit_orientation *)it.ptr; e = FLOAT_TO_FP(1.0f) - - distance_squared(_it->orientation, center); + distance_squared(_it->orientation, center); error += fp_mul(e, e); } @@ -138,8 +139,8 @@ void newton_fit_compute(struct newton_fit *fit, fpv3_t bias, fp_t *radius) if (queue_is_empty(fit->orientations)) return; - inv_orient_count = fp_div(FLOAT_TO_FP(1.0f), - queue_count(fit->orientations)); + inv_orient_count = + fp_div(FLOAT_TO_FP(1.0f), queue_count(fit->orientations)); memcpy(new_bias, bias, sizeof(fpv3_t)); new_error = compute_error(fit, new_bias); diff --git a/common/ocpc.c b/common/ocpc.c index 75876457c4..39e13dc046 100644 --- a/common/ocpc.c +++ b/common/ocpc.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,7 +7,8 @@ #include "battery.h" #include "battery_fuel_gauge.h" -#include "charge_state_v2.h" +#include "charge_manager.h" +#include "charge_state.h" #include "charger.h" #include "common.h" #include "console.h" @@ -15,6 +16,7 @@ #include "math_util.h" #include "ocpc.h" #include "timer.h" +#include "usb_pd.h" #include "util.h" /* @@ -30,17 +32,22 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_CHARGER, outstr) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) -#define CPRINT_VIZ(format, args...) \ -do { \ - if (viz_output) \ - cprintf(CC_CHARGER, format, ## args); \ -} while (0) -#define CPRINTS_DBG(format, args...) \ -do { \ - if (debug_output) \ - cprints(CC_CHARGER, format, ## args); \ -} while (0) +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ##args) +#define CPRINT_VIZ(format, args...) \ + do { \ + if (viz_output) \ + cprintf(CC_CHARGER, format, ##args); \ + } while (0) +#define CPRINTS_DBG(format, args...) \ + do { \ + if (debug_output) \ + cprints(CC_CHARGER, format, ##args); \ + } while (0) +#define CPRINTF_DBG(format, args...) \ + do { \ + if (debug_output) \ + cprintf(CC_CHARGER, format, ##args); \ + } while (0) /* Code refactor will be needed if more than 2 charger chips are present */ BUILD_ASSERT(CHARGER_NUM == 2); @@ -51,11 +58,34 @@ static int k_d = KD; static int k_p_div = KP_DIV; static int k_i_div = KI_DIV; static int k_d_div = KD_DIV; +static int drive_limit = CONFIG_OCPC_DEF_DRIVELIMIT_MILLIVOLTS; static int debug_output; static int viz_output; +#define NUM_RESISTANCE_SAMPLES 8 +#define COMBINED_IDX 0 +#define RBATT_IDX 1 +#define RSYS_IDX 2 +static int resistance_tbl[NUM_RESISTANCE_SAMPLES][3] = { + /* Rsys+Rbatt Rbatt Rsys */ + { CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0 }, + { CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0 }, + { CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0 }, + { CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0 }, + { CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0 }, + { CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0 }, + { CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0 }, + { CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0 }, +}; +static int resistance_tbl_idx; +static int mean_resistance[3]; +static int stddev_resistance[3]; +static int ub[3]; +static int lb[3]; + enum phase { PHASE_UNKNOWN = -1, + PHASE_PRECHARGE, PHASE_CC, PHASE_CV_TRIP, PHASE_CV_COMPLETE, @@ -65,16 +95,104 @@ __overridable void board_ocpc_init(struct ocpc_data *ocpc) { } +static enum ec_error_list ocpc_precharge_enable(bool enable); + +static void calc_resistance_stats(struct ocpc_data *ocpc) +{ + int i; + int j; + int sum; + int cols = 3; + int act_chg = ocpc->active_chg_chip; + + /* Only perform separate stats on Rsys and Rbatt if necessary. */ + if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) + cols = 1; + + /* Calculate mean */ + for (i = 0; i < cols; i++) { + sum = 0; + for (j = 0; j < NUM_RESISTANCE_SAMPLES; j++) { + sum += resistance_tbl[j][i]; + CPRINTF_DBG("%d ", resistance_tbl[j][i]); + } + CPRINTF_DBG("\n"); + + mean_resistance[i] = sum / NUM_RESISTANCE_SAMPLES; + + /* Calculate standard deviation */ + sum = 0; + for (j = 0; j < NUM_RESISTANCE_SAMPLES; j++) + sum += POW2(resistance_tbl[j][i] - mean_resistance[i]); + + stddev_resistance[i] = + fp_sqrtf(INT_TO_FP(sum / NUM_RESISTANCE_SAMPLES)); + stddev_resistance[i] = FP_TO_INT(stddev_resistance[i]); + /* + * Don't let our stddev collapse to 0 to continually consider + * new values. + */ + stddev_resistance[i] = MAX(stddev_resistance[i], 1); + CPRINTS_DBG("%d: mean: %d stddev: %d", i, mean_resistance[i], + stddev_resistance[i]); + lb[i] = MAX(0, mean_resistance[i] - (3 * stddev_resistance[i])); + ub[i] = mean_resistance[i] + (3 * stddev_resistance[i]); + } +} + +static bool is_within_range(struct ocpc_data *ocpc, int combined, int rbatt, + int rsys) +{ + int act_chg = ocpc->active_chg_chip; + bool valid; + + /* Discard measurements not within a 6 std. dev. window. */ + if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) { + /* We only know the combined Rsys+Rbatt */ + valid = (combined > 0) && (combined <= ub[COMBINED_IDX]) && + (combined >= lb[COMBINED_IDX]); + } else { + valid = (rsys <= ub[RSYS_IDX]) && (rsys >= lb[RSYS_IDX]) && + (rbatt <= ub[RBATT_IDX]) && (rbatt >= lb[RBATT_IDX]) && + (rsys > 0) && (rbatt > 0); + } + + if (!valid) + CPRINTS_DBG("Discard Rc:%d Rb:%d Rs:%d", combined, rbatt, rsys); + + return valid; +} + enum ec_error_list ocpc_calc_resistances(struct ocpc_data *ocpc, struct batt_params *battery) { - int act_chg = ocpc->active_chg_chip; + int act_chg; + static bool seeded; + static int initial_samples; + int combined; + int rsys = -1; + int rbatt = -1; + +#ifdef TEST_BUILD + /* Mechanism for resetting static vars in tests */ + if (!ocpc && !battery) { + seeded = false; + initial_samples = 0; + + return EC_SUCCESS; + } +#endif + + act_chg = ocpc->active_chg_chip; /* * In order to actually calculate the resistance, we need to make sure - * we're actually charging the battery at a significant rate. + * we're actually charging the battery at a significant rate. The LSB + * of a charger IC can be as high as 96mV. Assuming a resistance of 60 + * mOhms, we would need a current of 1666mA to have a voltage delta of + * 100mV. */ - if ((battery->current <= 1000) || + if ((battery->current <= 1666) || (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP) && (ocpc->isys_ma <= 0)) || (ocpc->vsys_aux_mv < ocpc->vsys_mv)) { @@ -93,25 +211,59 @@ enum ec_error_list ocpc_calc_resistances(struct ocpc_data *ocpc, * There's no provision to measure Isys, so we cannot separate * out Rsys from Rbatt. */ - ocpc->combined_rsys_rbatt_mo = ((ocpc->vsys_aux_mv - - battery->voltage) * 1000) / - battery->current; + combined = ((ocpc->vsys_aux_mv - battery->voltage) * 1000) / + battery->current; + } else { + rsys = ((ocpc->vsys_aux_mv - ocpc->vsys_mv) * 1000) / + ocpc->isys_ma; + rbatt = ((ocpc->vsys_mv - battery->voltage) * 1000) / + battery->current; + combined = rsys + rbatt; + } + + /* Discard measurements not within a 6 std dev window. */ + if ((!seeded) || + (seeded && is_within_range(ocpc, combined, rbatt, rsys))) { + if (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) { + resistance_tbl[resistance_tbl_idx][RSYS_IDX] = + MAX(rsys, 0); + resistance_tbl[resistance_tbl_idx][RBATT_IDX] = + MAX(rbatt, CONFIG_OCPC_DEF_RBATT_MOHMS); + } + resistance_tbl[resistance_tbl_idx][COMBINED_IDX] = + MAX(combined, CONFIG_OCPC_DEF_RBATT_MOHMS); + calc_resistance_stats(ocpc); + resistance_tbl_idx = + (resistance_tbl_idx + 1) % NUM_RESISTANCE_SAMPLES; + } + + if (seeded) { + ocpc->combined_rsys_rbatt_mo = + MAX(mean_resistance[COMBINED_IDX], + CONFIG_OCPC_DEF_RBATT_MOHMS); + + if (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) { + ocpc->rsys_mo = mean_resistance[RSYS_IDX]; + ocpc->rbatt_mo = MAX(mean_resistance[RBATT_IDX], + CONFIG_OCPC_DEF_RBATT_MOHMS); + CPRINTS_DBG("Rsys: %dmOhm Rbatt: %dmOhm", ocpc->rsys_mo, + ocpc->rbatt_mo); + } + CPRINTS_DBG("Rsys+Rbatt: %dmOhm", ocpc->combined_rsys_rbatt_mo); } else { - ocpc->rsys_mo = ((ocpc->vsys_aux_mv - ocpc->vsys_mv) * 1000) / - ocpc->isys_ma; - ocpc->rbatt_mo = ((ocpc->vsys_mv - battery->voltage) * 1000) / - battery->current; - ocpc->combined_rsys_rbatt_mo = ocpc->rsys_mo + ocpc->rbatt_mo; - CPRINTS_DBG("Rsys: %dmOhm Rbatt: %dmOhm", ocpc->rsys_mo, - ocpc->rbatt_mo); + seeded = ++initial_samples >= (2 * NUM_RESISTANCE_SAMPLES) ? + true : + false; } + return EC_SUCCESS; } -int ocpc_config_secondary_charger(int *desired_input_current, +int ocpc_config_secondary_charger(int *desired_charger_input_current, struct ocpc_data *ocpc, - int voltage_mv, int current_ma) + int desired_batt_voltage_mv, + int desired_batt_current_ma) { int rv = EC_SUCCESS; struct batt_params batt; @@ -120,6 +272,7 @@ int ocpc_config_secondary_charger(int *desired_input_current, int vsys_target = 0; int drive = 0; int i_ma = 0; + static int i_ma_CC_CV; int min_vsys_target; int error = 0; int derivative = 0; @@ -131,6 +284,8 @@ int ocpc_config_secondary_charger(int *desired_input_current, int i_step; static timestamp_t delay; int i, step, loc; + bool icl_reached = false; + static timestamp_t precharge_exit; /* * There's nothing to do if we're not using this charger. Should @@ -144,8 +299,8 @@ int ocpc_config_secondary_charger(int *desired_input_current, batt_info = battery_get_info(); - if (current_ma == 0) { - vsys_target = voltage_mv; + if (desired_batt_current_ma == 0) { + vsys_target = desired_batt_voltage_mv; goto set_vsys; } @@ -176,8 +331,8 @@ int ocpc_config_secondary_charger(int *desired_input_current, if (!timestamp_expired(delay, NULL)) return EC_ERROR_BUSY; - result = charger_set_vsys_compensation(chgnum, ocpc, current_ma, - voltage_mv); + result = charger_set_vsys_compensation( + chgnum, ocpc, desired_batt_current_ma, desired_batt_voltage_mv); switch (result) { case EC_SUCCESS: /* No further action required, so we're done here. */ @@ -196,10 +351,10 @@ int ocpc_config_secondary_charger(int *desired_input_current, if (ocpc->last_vsys == OCPC_UNINIT) { ph = PHASE_UNKNOWN; + precharge_exit.val = 0; iterations = 0; } - /* * We need to induce a current flow that matches the requested current * by raising VSYS. Let's start by getting the latest data that we @@ -210,12 +365,12 @@ int ocpc_config_secondary_charger(int *desired_input_current, ocpc_get_adcs(ocpc); charger_get_params(&charger); - /* * If the system is in S5/G3, we can calculate the board and battery * resistances. */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | + CHIPSET_STATE_ANY_SUSPEND)) { /* * In the first few iterations of the loop, charging isn't * stable/correct so making the calculation then leads to some @@ -233,11 +388,58 @@ int ocpc_config_secondary_charger(int *desired_input_current, /* Set our current target accordingly. */ if (batt.desired_voltage) { - if (batt.voltage < batt.desired_voltage) { - if (ph < PHASE_CV_TRIP) + if (((batt.voltage < batt_info->voltage_min) || + ((batt.voltage < batt_info->voltage_normal) && + (desired_batt_current_ma >= 0) && + (desired_batt_current_ma <= + batt_info->precharge_current))) && + (ph != PHASE_PRECHARGE)) { + /* + * If the charger IC doesn't support the linear charge + * feature, proceed to the CC phase. + */ + result = ocpc_precharge_enable(true); + if (result == EC_ERROR_UNIMPLEMENTED) { + ph = PHASE_CC; + } else if (result == EC_SUCCESS) { + CPRINTS("OCPC: Enabling linear precharge"); + ph = PHASE_PRECHARGE; + i_ma = desired_batt_current_ma; + } + } else if (batt.voltage < batt.desired_voltage) { + if ((ph == PHASE_PRECHARGE) && + (desired_batt_current_ma > + batt_info->precharge_current)) { + /* + * Precharge phase is complete. Now set the + * target VSYS to the battery voltage to prevent + * a large current spike during the transition. + */ + /* + * If we'd like to exit precharge, let's wait a + * short delay. + */ + if (!precharge_exit.val) { + CPRINTS("OCPC: Preparing to exit " + "precharge"); + precharge_exit = get_time(); + precharge_exit.val += 3 * SECOND; + } + if (timestamp_expired(precharge_exit, NULL)) { + CPRINTS("OCPC: Precharge complete"); + charger_set_voltage(CHARGER_SECONDARY, + batt.voltage); + ocpc->last_vsys = batt.voltage; + ocpc_precharge_enable(false); + ph = PHASE_CC; + precharge_exit.val = 0; + } + } + + if ((ph != PHASE_PRECHARGE) && (ph < PHASE_CV_TRIP)) ph = PHASE_CC; - i_ma = batt.desired_current; - } else{ + i_ma = desired_batt_current_ma; + } else { /* * Once the battery voltage reaches the desired voltage, * we should note that we've reached the CV step and set @@ -245,7 +447,8 @@ int ocpc_config_secondary_charger(int *desired_input_current, */ i_ma = batt.current; ph = ph == PHASE_CC ? PHASE_CV_TRIP : PHASE_CV_COMPLETE; - + if (ph == PHASE_CV_TRIP) + i_ma_CC_CV = batt.current; } } @@ -265,8 +468,18 @@ int ocpc_config_secondary_charger(int *desired_input_current, */ if (ocpc->last_vsys != OCPC_UNINIT) { error = i_ma - batt.current; + + /* Uses charger input error if controller is proportional only. + */ + if ((k_i == 0) && (k_d == 0)) { + int charger_input_error = + (*desired_charger_input_current - + ocpc->secondary_ibus_ma); + error = MIN(error, charger_input_error); + } + /* Add some hysteresis. */ - if (ABS(error) < i_step) + if (ABS(error) < (i_step / 2)) error = 0; /* Make a note if we're significantly over target. */ @@ -275,7 +488,7 @@ int ocpc_config_secondary_charger(int *desired_input_current, derivative = error - ocpc->last_error; ocpc->last_error = error; - ocpc->integral += error; + ocpc->integral += error; if (ocpc->integral > 500) ocpc->integral = 500; } @@ -294,50 +507,80 @@ int ocpc_config_secondary_charger(int *desired_input_current, CPRINTS_DBG("min_vsys_target = %d", min_vsys_target); /* Obtain the drive from our PID controller. */ - if (ocpc->last_vsys != OCPC_UNINIT) { + if ((ocpc->last_vsys != OCPC_UNINIT) && (ph > PHASE_PRECHARGE)) { drive = (k_p * error / k_p_div) + (k_i * ocpc->integral / k_i_div) + (k_d * derivative / k_d_div); /* - * Let's limit upward transitions to 200mV. It's okay to reduce + * Let's limit upward transitions to 10mV. It's okay to reduce * VSYS rather quickly, but we'll be conservative on * increasing VSYS. */ - if (drive > 200) - drive = 200; + if (drive > drive_limit) + drive = drive_limit; CPRINTS_DBG("drive = %d", drive); } + CPRINTS_DBG("##DATA = %d %d %d %d %d %d %d", batt.desired_current, + batt.current, *desired_charger_input_current, + ocpc->secondary_ibus_ma, error, ocpc->last_vsys, drive); + + /* + * For the pre-charge phase, simply keep the VSYS target at the desired + * voltage. + */ + if (ph == PHASE_PRECHARGE) + vsys_target = batt.desired_voltage; + /* * Adjust our VSYS target by applying the calculated drive. Note that * we won't apply our drive the first time through this function such * that we can determine our initial error. */ - if (ocpc->last_vsys != OCPC_UNINIT) + if ((ocpc->last_vsys != OCPC_UNINIT) && (ph > PHASE_PRECHARGE)) vsys_target = ocpc->last_vsys + drive; /* * Once we're in the CV region, all we need to do is keep VSYS at the * desired voltage. */ - if (ph >= PHASE_CV_TRIP) - vsys_target = batt.desired_voltage + - ((batt_info->precharge_current * - ocpc->combined_rsys_rbatt_mo) / 1000); + if (ph == PHASE_CV_TRIP) { + vsys_target = + batt.desired_voltage + + ((i_ma_CC_CV * ocpc->combined_rsys_rbatt_mo) / 1000); + CPRINTS_DBG("i_ma_CC_CV = %d", i_ma_CC_CV); + } + if (ph == PHASE_CV_COMPLETE) + vsys_target = + batt.desired_voltage + ((batt_info->precharge_current * + ocpc->combined_rsys_rbatt_mo) / + 1000); /* * Ensure VSYS is no higher than the specified maximum battery voltage * plus the voltage drop across the system. */ - vsys_target = CLAMP(vsys_target, min_vsys_target, - batt_info->voltage_max + - (i_ma * ocpc->combined_rsys_rbatt_mo / 1000)); + vsys_target = + CLAMP(vsys_target, min_vsys_target, + batt_info->voltage_max + + (i_ma * ocpc->combined_rsys_rbatt_mo / 1000)); /* If we're input current limited, we cannot increase VSYS any more. */ CPRINTS_DBG("OCPC: Inst. Input Current: %dmA (Limit: %dmA)", - ocpc->secondary_ibus_ma, *desired_input_current); - if ((ocpc->secondary_ibus_ma >= (*desired_input_current * 95 / 100)) && - (vsys_target > ocpc->last_vsys) && + ocpc->secondary_ibus_ma, *desired_charger_input_current); + + if (charger_is_icl_reached(chgnum, &icl_reached) != EC_SUCCESS) { + /* + * If the charger doesn't support telling us, assume that the + * input current limit is reached if we're consuming more than + * 95% of the limit. + */ + if (ocpc->secondary_ibus_ma >= + (*desired_charger_input_current * 95 / 100)) + icl_reached = true; + } + + if (icl_reached && (vsys_target > ocpc->last_vsys) && (ocpc->last_vsys != OCPC_UNINIT)) { if (!prev_limited) CPRINTS("Input limited! Not increasing VSYS"); @@ -371,7 +614,7 @@ int ocpc_config_secondary_charger(int *desired_input_current, CPRINT_VIZ(i == loc ? "o" : "-"); } CPRINT_VIZ("] (actual)%dmA (desired)%dmA\n", batt.current, - batt.desired_current); + i_ma); } return rv; @@ -390,7 +633,7 @@ void ocpc_get_adcs(struct ocpc_data *ocpc) ocpc->primary_ibus_ma = val; val = 0; - if (!charger_get_voltage(CHARGER_PRIMARY, &val)) + if (!charger_get_actual_voltage(CHARGER_PRIMARY, &val)) ocpc->vsys_mv = val; if (board_get_charger_chip_count() <= CHARGER_SECONDARY) { @@ -410,21 +653,67 @@ void ocpc_get_adcs(struct ocpc_data *ocpc) ocpc->secondary_ibus_ma = val; val = 0; - if (!charger_get_voltage(CHARGER_SECONDARY, &val)) + if (!charger_get_actual_voltage(CHARGER_SECONDARY, &val)) ocpc->vsys_aux_mv = val; val = 0; - if (!charger_get_current(CHARGER_SECONDARY, &val)) + if (!charger_get_actual_current(CHARGER_SECONDARY, &val)) ocpc->isys_ma = val; } -__overridable void ocpc_get_pid_constants(int *kp, int *kp_div, - int *ki, int *ki_div, - int *kd, int *kd_div) +__overridable void ocpc_get_pid_constants(int *kp, int *kp_div, int *ki, + int *ki_div, int *kd, int *kd_div) +{ +} + +static enum ec_error_list ocpc_precharge_enable(bool enable) +{ + /* Enable linear charging on the primary charger IC. */ + int rv = charger_enable_linear_charge(CHARGER_PRIMARY, enable); + + if (rv) + CPRINTS("OCPC: Failed to %sble linear charge!", + enable ? "ena" : "dis"); + + return rv; +} + +void ocpc_reset(struct ocpc_data *ocpc) { + struct batt_params batt; + int voltage; + + battery_get_params(&batt); + ocpc->integral = 0; + ocpc->last_error = 0; + ocpc->last_vsys = OCPC_UNINIT; + + /* + * Initialize the VSYS target on the aux chargers to the current battery + * voltage to avoid a large spike. + */ + if (ocpc->active_chg_chip > CHARGER_PRIMARY) { + voltage = (batt.voltage > 0 && + !(batt.flags & BATT_FLAG_BAD_VOLTAGE)) ? + batt.voltage : + battery_get_info()->voltage_normal; +#ifdef CONFIG_CHARGER_NARROW_VDC + if (voltage < battery_get_info()->voltage_min) + voltage = battery_get_info()->voltage_min; +#endif + CPRINTS("OCPC: C%d Init VSYS to %dmV", ocpc->active_chg_chip, + voltage); + charger_set_voltage(ocpc->active_chg_chip, voltage); + } + /* + * See(b:191347747) When linear precharge is enabled, it may affect + * the charging behavior from the primary charger IC. Therefore as + * a part of the reset process, we need to disable linear precharge. + */ + ocpc_precharge_enable(false); } -static void ocpc_set_pid_constants(void) +test_export_static void ocpc_set_pid_constants(void) { ocpc_get_pid_constants(&k_p, &k_p_div, &k_i, &k_i_div, &k_d, &k_d_div); } @@ -443,7 +732,7 @@ void ocpc_init(struct ocpc_data *ocpc) board_ocpc_init(ocpc); } -static int command_ocpcdebug(int argc, char **argv) +static int command_ocpcdebug(int argc, const char **argv) { if (argc < 2) return EC_ERROR_PARAM_COUNT; @@ -473,7 +762,7 @@ DECLARE_SAFE_CONSOLE_COMMAND(ocpcdebug, command_ocpcdebug, "Each segment is 5% of current target. All shows" " both. Disable shows no debug output."); -static int command_ocpcpid(int argc, char **argv) +static int command_ocpcpid(int argc, const char **argv) { int *num, *denom; @@ -510,3 +799,42 @@ static int command_ocpcpid(int argc, char **argv) DECLARE_SAFE_CONSOLE_COMMAND(ocpcpid, command_ocpcpid, "[ ]", "Show/Set PID constants for OCPC PID loop"); + +static int command_ocpcdrvlmt(int argc, const char **argv) +{ + if (argc == 2) { + drive_limit = atoi(argv[1]); + } + + /* Print the current constants */ + ccprintf("Drive Limit = %d\n", drive_limit); + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(ocpcdrvlmt, command_ocpcdrvlmt, "[]", + "Show/Set drive limit for OCPC PID loop"); + +#ifdef TEST_BUILD +int test_ocpc_get_viz_output(void) +{ + return viz_output; +} +int test_ocpc_get_debug_output(void) +{ + return debug_output; +} +void test_ocpc_reset_resistance_state(void) +{ + for (int i = 0; i < NUM_RESISTANCE_SAMPLES; i++) { + resistance_tbl[i][0] = CONFIG_OCPC_DEF_RBATT_MOHMS; + resistance_tbl[i][1] = CONFIG_OCPC_DEF_RBATT_MOHMS; + resistance_tbl[i][2] = 0; + } + + resistance_tbl_idx = 0; + + memset(mean_resistance, 0, sizeof(mean_resistance)); + memset(stddev_resistance, 0, sizeof(stddev_resistance)); + memset(ub, 0, sizeof(ub)); + memset(lb, 0, sizeof(lb)); +} +#endif diff --git a/common/onewire.c b/common/onewire.c index 43080d096e..0b109bbdcd 100644 --- a/common/onewire.c +++ b/common/onewire.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,16 +16,19 @@ * Note that these timing are actually _longer_ than legacy 1-wire standard * speed because we're running the 1-wire bus at 3.3V instead of 5V. */ -#define T_RSTL 602 /* Reset low pulse; 600-960 us */ -#define T_MSP 72 /* Presence detect sample time; 70-75 us */ -#define T_RSTH (68 + 260 + 5 + 2) /* Reset high; tPDHmax + tPDLmax + tRECmin */ -#define T_SLOT 70 /* Timeslot; >67 us */ -#define T_W0L 63 /* Write 0 low; 62-120 us */ -#define T_W1L 7 /* Write 1 low; 5-15 us */ -#define T_RL 7 /* Read low; 5-15 us */ -#define T_MSR 9 /* Read sample time; <15 us. Must be at least 200 ns after - * T_RL since that's how long the signal takes to be pulled - * up on our board. */ +#define T_RSTL 602 /* Reset low pulse; 600-960 us */ +#define T_MSP 72 /* Presence detect sample time; 70-75 us */ +#define T_RSTH \ + (68 + 260 + 5 + 2) /* Reset high; tPDHmax + tPDLmax + tRECmin \ + */ +#define T_SLOT 70 /* Timeslot; >67 us */ +#define T_W0L 63 /* Write 0 low; 62-120 us */ +#define T_W1L 7 /* Write 1 low; 5-15 us */ +#define T_RL 7 /* Read low; 5-15 us */ +#define T_MSR \ + 9 /* Read sample time; <15 us. Must be at least 200 ns after \ + * T_RL since that's how long the signal takes to be pulled \ + * up on our board. */ /** * Output low on the bus for us, then switch back to open-drain input. @@ -54,7 +57,10 @@ static int readbit(void) /* Output low */ output0(T_RL); - /* Delay to let slave release the line if it wants to send a 1-bit */ + /* + * Delay to let peripheral release the line if it wants to send + * a 1-bit + */ udelay(T_MSR - T_RL); /* Read bit */ @@ -95,19 +101,18 @@ static void writebit(int bit) interrupt_enable(); udelay(T_SLOT - T_W0L); } - } int onewire_reset(void) { - /* Start transaction with master reset pulse */ + /* Start transaction with controller reset pulse */ output0(T_RSTL); /* Wait for presence detect sample time. * * (Alternately, we could poll waiting for a 1-bit indicating our pulse * has let go, then poll up to max time waiting for a 0-bit indicating - * the slave has responded.) + * the peripheral has responded.) */ udelay(T_MSP); @@ -130,7 +135,7 @@ int onewire_read(void) int i; for (i = 0; i < 8; i++) - data |= readbit() << i; /* LSB first */ + data |= readbit() << i; /* LSB first */ return data; } @@ -140,5 +145,5 @@ void onewire_write(int data) int i; for (i = 0; i < 8; i++) - writebit((data >> i) & 0x01); /* LSB first */ + writebit((data >> i) & 0x01); /* LSB first */ } diff --git a/common/online_calibration.c b/common/online_calibration.c index ca7a5a620d..a56aa0dce7 100644 --- a/common/online_calibration.c +++ b/common/online_calibration.c @@ -1,21 +1,21 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "accel_cal.h" #include "accelgyro.h" #include "atomic.h" -#include "hwtimer.h" -#include "online_calibration.h" #include "common.h" +#include "ec_commands.h" +#include "gyro_cal.h" +#include "hwtimer.h" #include "mag_cal.h" +#include "mkbp_event.h" +#include "online_calibration.h" +#include "task.h" #include "util.h" #include "vec3.h" -#include "task.h" -#include "ec_commands.h" -#include "accel_cal.h" -#include "mkbp_event.h" -#include "gyro_cal.h" #define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args) @@ -61,7 +61,7 @@ static void data_int16_to_fp(const struct motion_sensor_t *s, const int16_t *data, fpv3_t out) { int i; - fp_t range = INT_TO_FP(s->drv->get_range(s)); + fp_t range = INT_TO_FP(s->current_range); for (i = 0; i < 3; ++i) { fp_t v = INT_TO_FP((int32_t)data[i]); @@ -77,17 +77,16 @@ static void data_fp_to_int16(const struct motion_sensor_t *s, const fpv3_t data, int16_t *out) { int i; - fp_t range = INT_TO_FP(s->drv->get_range(s)); + fp_t range = INT_TO_FP(s->current_range); for (i = 0; i < 3; ++i) { int32_t iv; fp_t v = fp_div(data[i], range); - v = fp_mul(v, INT_TO_FP((data[i] >= INT_TO_FP(0)) ? 0x7fff : - 0x8000)); + v = fp_mul(v, INT_TO_FP(0x7fff)); iv = FP_TO_INT(v); /* Check for overflow */ - out[i] = CLAMP(iv, (int32_t)0xffff8000, (int32_t)0x00007fff); + out[i] = ec_motion_sensor_clamp_i16(iv); } } @@ -98,28 +97,36 @@ static void data_fp_to_int16(const struct motion_sensor_t *s, const fpv3_t data, * * @param sensor Pointer to the gyroscope sensor to check. */ -static void check_gyro_cal_new_bias(struct motion_sensor_t *sensor) +static bool check_gyro_cal_new_bias(struct motion_sensor_t *sensor, + fpv3_t bias_out) { struct online_calib_data *calib_data = (struct online_calib_data *)sensor->online_calib_data; struct gyro_cal_data *data = (struct gyro_cal_data *)calib_data->type_specific_data; - size_t sensor_num = motion_sensors - sensor; int temp_out; - fpv3_t bias_out; uint32_t timestamp_out; /* Check that we have a new bias. */ if (data == NULL || calib_data == NULL || !gyro_cal_new_bias_available(&data->gyro_cal)) - return; + return false; /* Read the calibration values. */ gyro_cal_get_bias(&data->gyro_cal, bias_out, &temp_out, ×tamp_out); + return true; +} + +static void set_gyro_cal_cache_values(struct motion_sensor_t *sensor, + fpv3_t bias) +{ + size_t sensor_num = sensor - motion_sensors; + struct online_calib_data *calib_data = + (struct online_calib_data *)sensor->online_calib_data; mutex_lock(&g_calib_cache_mutex); - /* Convert result to the right scale. */ - data_fp_to_int16(sensor, bias_out, calib_data->cache); + /* Convert result to the right scale and save to cache. */ + data_fp_to_int16(sensor, bias, calib_data->cache); /* Set valid and dirty. */ sensor_calib_cache_valid_map |= BIT(sensor_num); sensor_calib_cache_dirty_map |= BIT(sensor_num); @@ -140,6 +147,7 @@ static void update_gyro_cal(struct motion_sensor_t *sensor, fpv3_t data, uint32_t timestamp) { int i; + fpv3_t gyro_cal_data_out; /* * Find gyroscopes, while we don't currently have instance where more @@ -151,6 +159,7 @@ static void update_gyro_cal(struct motion_sensor_t *sensor, fpv3_t data, struct gyro_cal_data *gyro_cal_data = (struct gyro_cal_data *) s->online_calib_data->type_specific_data; + bool has_new_gyro_cal_bias = false; /* * If we're not looking at a gyroscope OR if the calibration @@ -168,14 +177,19 @@ static void update_gyro_cal(struct motion_sensor_t *sensor, fpv3_t data, gyro_cal_update_accel(&gyro_cal_data->gyro_cal, timestamp, data[X], data[Y], data[Z]); - check_gyro_cal_new_bias(s); + has_new_gyro_cal_bias = + check_gyro_cal_new_bias(s, gyro_cal_data_out); } else if (sensor->type == MOTIONSENSE_TYPE_MAG && gyro_cal_data->mag_sensor_id == sensor - motion_sensors) { gyro_cal_update_mag(&gyro_cal_data->gyro_cal, timestamp, data[X], data[Y], data[Z]); - check_gyro_cal_new_bias(s); + has_new_gyro_cal_bias = + check_gyro_cal_new_bias(s, gyro_cal_data_out); } + + if (has_new_gyro_cal_bias) + set_gyro_cal_cache_values(s, gyro_cal_data_out); } } @@ -187,11 +201,8 @@ void online_calibration_init(void) struct motion_sensor_t *s = motion_sensors + i; void *type_specific_data = NULL; - if (s->online_calib_data) { - s->online_calib_data->last_temperature = -1; - type_specific_data = - s->online_calib_data->type_specific_data; - } + s->online_calib_data->last_temperature = -1; + type_specific_data = s->online_calib_data->type_specific_data; if (!type_specific_data) continue; @@ -228,16 +239,18 @@ bool online_calibration_has_new_values(void) return has_dirty; } -bool online_calibration_read(int sensor_num, int16_t out[3]) +bool online_calibration_read(struct motion_sensor_t *sensor, + struct ec_response_online_calibration_data *out) { + int sensor_num = sensor - motion_sensors; bool has_valid; mutex_lock(&g_calib_cache_mutex); has_valid = (sensor_calib_cache_valid_map & BIT(sensor_num)) != 0; if (has_valid) { /* Update data in out */ - memcpy(out, motion_sensors[sensor_num].online_calib_data->cache, - sizeof(out)); + memcpy(out->data, sensor->online_calib_data->cache, + sizeof(out->data)); /* Clear dirty bit */ sensor_calib_cache_dirty_map &= ~(1 << sensor_num); } @@ -250,31 +263,48 @@ int online_calibration_process_data(struct ec_response_motion_sensor_data *data, struct motion_sensor_t *sensor, uint32_t timestamp) { - size_t sensor_num = motion_sensors - sensor; + int sensor_num = sensor - motion_sensors; int rc; int temperature; struct online_calib_data *calib_data; + fpv3_t fdata; + bool is_spoofed = IS_ENABLED(CONFIG_ONLINE_CALIB_SPOOF_MODE) && + (sensor->flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE); + bool has_new_calibration_values = false; + + /* Convert data to fp. */ + data_int16_to_fp(sensor, data->data, fdata); calib_data = sensor->online_calib_data; switch (sensor->type) { case MOTIONSENSE_TYPE_ACCEL: { struct accel_cal *cal = (struct accel_cal *)(calib_data->type_specific_data); - fpv3_t fdata; - /* Convert data to fp. */ - data_int16_to_fp(sensor, data->data, fdata); - - /* Possibly update the gyroscope calibration. */ - update_gyro_cal(sensor, fdata, timestamp); - - /* Temperature is required for accelerometer calibration. */ - rc = get_temperature(sensor, &temperature); - if (rc != EC_SUCCESS) - return rc; + if (is_spoofed) { + /* Copy the data to the calibration result. */ + cal->bias[X] = fdata[X]; + cal->bias[Y] = fdata[Y]; + cal->bias[Z] = fdata[Z]; + has_new_calibration_values = true; + } else { + /* Possibly update the gyroscope calibration. */ + update_gyro_cal(sensor, fdata, timestamp); + + /* + * Temperature is required for accelerometer + * calibration. + */ + rc = get_temperature(sensor, &temperature); + if (rc != EC_SUCCESS) + return rc; + + has_new_calibration_values = accel_cal_accumulate( + cal, timestamp, fdata[X], fdata[Y], fdata[Z], + temperature); + } - if (accel_cal_accumulate(cal, timestamp, fdata[X], fdata[Y], - fdata[Z], temperature)) { + if (has_new_calibration_values) { mutex_lock(&g_calib_cache_mutex); /* Convert result to the right scale. */ data_fp_to_int16(sensor, cal->bias, calib_data->cache); @@ -295,15 +325,21 @@ int online_calibration_process_data(struct ec_response_motion_sensor_data *data, (int)data->data[Y], (int)data->data[Z], }; - fpv3_t fdata; - /* Convert data to fp. */ - data_int16_to_fp(sensor, data->data, fdata); + if (is_spoofed) { + /* Copy the data to the calibration result. */ + cal->bias[X] = INT_TO_FP(idata[X]); + cal->bias[Y] = INT_TO_FP(idata[Y]); + cal->bias[Z] = INT_TO_FP(idata[Z]); + has_new_calibration_values = true; + } else { + /* Possibly update the gyroscope calibration. */ + update_gyro_cal(sensor, fdata, timestamp); - /* Possibly update the gyroscope calibration. */ - update_gyro_cal(sensor, fdata, timestamp); + has_new_calibration_values = mag_cal_update(cal, idata); + } - if (mag_cal_update(cal, idata)) { + if (has_new_calibration_values) { mutex_lock(&g_calib_cache_mutex); /* Copy the values */ calib_data->cache[X] = cal->bias[X]; @@ -319,21 +355,32 @@ int online_calibration_process_data(struct ec_response_motion_sensor_data *data, break; } case MOTIONSENSE_TYPE_GYRO: { - fpv3_t fdata; - - /* Temperature is required for gyro calibration. */ - rc = get_temperature(sensor, &temperature); - if (rc != EC_SUCCESS) - return rc; - - /* Convert data to fp. */ - data_int16_to_fp(sensor, data->data, fdata); + if (is_spoofed) { + /* + * Gyroscope uses fdata to store the calibration + * result, so there's no need to copy anything. + */ + has_new_calibration_values = true; + } else { + struct gyro_cal_data *gyro_cal_data = + (struct gyro_cal_data *) + calib_data->type_specific_data; + struct gyro_cal *gyro_cal = &gyro_cal_data->gyro_cal; + + /* Temperature is required for gyro calibration. */ + rc = get_temperature(sensor, &temperature); + if (rc != EC_SUCCESS) + return rc; + + /* Update gyroscope calibration. */ + gyro_cal_update_gyro(gyro_cal, timestamp, fdata[X], + fdata[Y], fdata[Z], temperature); + has_new_calibration_values = + check_gyro_cal_new_bias(sensor, fdata); + } - /* Update gyroscope calibration. */ - gyro_cal_update_gyro( - &((struct gyro_cal_data *)calib_data->type_specific_data)->gyro_cal, - timestamp, fdata[X], fdata[Y], fdata[Z], temperature); - check_gyro_cal_new_bias(sensor); + if (has_new_calibration_values) + set_gyro_cal_cache_values(sensor, fdata); break; } default: diff --git a/common/panic_output.c b/common/panic_output.c index 75c94223ce..5c2dce25d8 100644 --- a/common/panic_output.c +++ b/common/panic_output.c @@ -1,8 +1,9 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "cpu.h" @@ -19,20 +20,24 @@ #include "usb_console.h" #include "util.h" +/* + * For host tests, use a static area for panic data. + */ +#ifdef CONFIG_BOARD_NATIVE_POSIX +static struct panic_data zephyr_panic_data; +#undef PANIC_DATA_PTR +#undef CONFIG_PANIC_DATA_BASE +#define PANIC_DATA_PTR (&zephyr_panic_data) +#define CONFIG_PANIC_DATA_BASE (&zephyr_panic_data) +#endif /* Panic data goes at the end of RAM. */ -static struct panic_data * const pdata_ptr = PANIC_DATA_PTR; +static struct panic_data *const pdata_ptr = PANIC_DATA_PTR; /* Common SW Panic reasons strings */ -const char * const panic_sw_reasons[] = { -#ifdef CONFIG_SOFTWARE_PANIC - "PANIC_SW_DIV_ZERO", - "PANIC_SW_STACK_OVERFLOW", - "PANIC_SW_PD_CRASH", - "PANIC_SW_ASSERT", - "PANIC_SW_WATCHDOG", - "PANIC_SW_RNG", +const char *const panic_sw_reasons[] = { + "PANIC_SW_DIV_ZERO", "PANIC_SW_STACK_OVERFLOW", "PANIC_SW_PD_CRASH", + "PANIC_SW_ASSERT", "PANIC_SW_WATCHDOG", "PANIC_SW_RNG", "PANIC_SW_PMIC_FAULT", -#endif }; /** @@ -42,8 +47,7 @@ const char * const panic_sw_reasons[] = { */ int panic_sw_reason_is_valid(uint32_t reason) { - return (IS_ENABLED(CONFIG_SOFTWARE_PANIC) && - reason >= PANIC_SW_BASE && + return (reason >= PANIC_SW_BASE && (reason - PANIC_SW_BASE) < ARRAY_SIZE(panic_sw_reasons)); } @@ -114,31 +118,32 @@ void panic_reboot(void) system_reset(0); } -#ifdef CONFIG_DEBUG_ASSERT_REBOOTS +/* Complete the processing of a panic, after the initial message is shown */ +test_mockable_static +#if !(defined(TEST_FUZZ) || defined(CONFIG_ZTEST)) + noreturn +#endif + void + complete_panic(int linenum) +{ + software_panic(PANIC_SW_ASSERT, linenum); +} + #ifdef CONFIG_DEBUG_ASSERT_BRIEF void panic_assert_fail(const char *fname, int linenum) { panic_printf("\nASSERTION FAILURE at %s:%d\n", fname, linenum); -#ifdef CONFIG_SOFTWARE_PANIC - software_panic(PANIC_SW_ASSERT, linenum); -#else - panic_reboot(); -#endif + complete_panic(linenum); } #else void panic_assert_fail(const char *msg, const char *func, const char *fname, int linenum) { - panic_printf("\nASSERTION FAILURE '%s' in %s() at %s:%d\n", - msg, func, fname, linenum); -#ifdef CONFIG_SOFTWARE_PANIC - software_panic(PANIC_SW_ASSERT, linenum); -#else - panic_reboot(); -#endif + panic_printf("\nASSERTION FAILURE '%s' in %s() at %s:%d\n", msg, func, + fname, linenum); + complete_panic(linenum); } #endif -#endif void panic(const char *msg) { @@ -167,9 +172,13 @@ uintptr_t get_panic_data_start(void) if (pdata_ptr->magic != PANIC_DATA_MAGIC) return 0; - return ((uintptr_t)CONFIG_PANIC_DATA_BASE - + CONFIG_PANIC_DATA_SIZE - - pdata_ptr->struct_size); + if (IS_ENABLED(CONFIG_BOARD_NATIVE_POSIX)) + return (uintptr_t)pdata_ptr; + + /* LCOV_EXCL_START - Can't cover non posix lines (yet) */ + return ((uintptr_t)CONFIG_PANIC_DATA_BASE + CONFIG_PANIC_DATA_SIZE - + pdata_ptr->struct_size); + /* LCOV_EXCL_STOP */ } static uint32_t get_panic_data_size(void) @@ -186,7 +195,20 @@ static uint32_t get_panic_data_size(void) * It can also delete panic data from previous boot, so this function * should be used when we are sure that we don't need it. */ -struct panic_data *get_panic_data_write(void) +#ifdef CONFIG_BOARD_NATIVE_POSIX +struct panic_data *test_get_panic_data_pointer(void) +{ + return pdata_ptr; +} +#endif + +__overridable uint32_t get_panic_stack_pointer(const struct panic_data *pdata) +{ + /* Not Implemented */ + return 0; +} + +test_mockable struct panic_data *get_panic_data_write(void) { /* * Pointer to panic_data structure. It may not point to @@ -194,8 +216,8 @@ struct panic_data *get_panic_data_write(void) * and magic is safe because it is always placed at the * end of RAM. */ - struct panic_data * const pdata_ptr = PANIC_DATA_PTR; - const struct jump_data *jdata_ptr; + struct panic_data *const pdata_ptr = PANIC_DATA_PTR; + struct jump_data *jdata_ptr; uintptr_t data_begin; size_t move_size; int delta; @@ -231,8 +253,8 @@ struct panic_data *get_panic_data_write(void) * anything and can just return pdata_ptr (clear memory, set magic * and struct_size first). */ - if (jdata_ptr->magic != JUMP_DATA_MAGIC || - jdata_ptr->version < 1 || jdata_ptr->version > 3) { + if (jdata_ptr->magic != JUMP_DATA_MAGIC || jdata_ptr->version < 1 || + jdata_ptr->version > 3) { memset(pdata_ptr, 0, CONFIG_PANIC_DATA_SIZE); pdata_ptr->magic = PANIC_DATA_MAGIC; pdata_ptr->struct_size = CONFIG_PANIC_DATA_SIZE; @@ -240,22 +262,34 @@ struct panic_data *get_panic_data_write(void) return pdata_ptr; } + move_size = 0; if (jdata_ptr->version == 1) move_size = JUMP_DATA_SIZE_V1; else if (jdata_ptr->version == 2) move_size = JUMP_DATA_SIZE_V2 + jdata_ptr->jump_tag_total; else if (jdata_ptr->version == 3) move_size = jdata_ptr->struct_size + jdata_ptr->jump_tag_total; - else { - /* Unknown jump data version - set move size to 0 */ - move_size = 0; + + /* Check if there's enough space for jump tags after move */ + if (data_begin - move_size < JUMP_DATA_MIN_ADDRESS) { + /* Not enough room for jump tags, clear tags. + * TODO(b/251190975): This failure should be reported + * in the panic data structure for more visibility. + */ + /* LCOV_EXCL_START - JUMP_DATA_MIN_ADDRESS is 0 in test builds + * and we cannot go negative by subtracting unsigned ints. + */ + move_size -= jdata_ptr->jump_tag_total; + jdata_ptr->jump_tag_total = 0; + /* LCOV_EXCL_STOP */ } data_begin -= move_size; if (move_size != 0) { /* Move jump_tags and jump_data */ - memmove((void *)(data_begin - delta), (void *)data_begin, move_size); + memmove((void *)(data_begin - delta), (void *)data_begin, + move_size); } /* @@ -284,10 +318,18 @@ static void panic_init(void) DECLARE_HOOK(HOOK_INIT, panic_init, HOOK_PRIO_LAST); DECLARE_HOOK(HOOK_CHIPSET_RESET, panic_init, HOOK_PRIO_LAST); -#ifdef CONFIG_CMD_STACKOVERFLOW +#ifdef CONFIG_CMD_CRASH +/* + * Disable infinite recursion warning, since we're intentionally doing that + * here. + */ +DISABLE_CLANG_WARNING("-Winfinite-recursion") +#if __GNUC__ >= 12 +DISABLE_GCC_WARNING("-Winfinite-recursion") +#endif static void stack_overflow_recurse(int n) { - ccprintf("+%d", n); + panic_printf("+%d", n); /* * Force task context switch, since that's where we do stack overflow @@ -295,20 +337,22 @@ static void stack_overflow_recurse(int n) */ msleep(10); - stack_overflow_recurse(n+1); + stack_overflow_recurse(n + 1); /* * Do work after the recursion, or else the compiler uses tail-chaining * and we don't actually consume additional stack. */ - ccprintf("-%d", n); + panic_printf("-%d", n); } -#endif /* CONFIG_CMD_STACKOVERFLOW */ +ENABLE_CLANG_WARNING("-Winfinite-recursion") +#if __GNUC__ >= 12 +ENABLE_GCC_WARNING("-Winfinite-recursion") +#endif /*****************************************************************************/ /* Console commands */ -#ifdef CONFIG_CMD_CRASH -static int command_crash(int argc, char **argv) +static int command_crash(int argc, const char **argv) { if (argc < 2) return EC_ERROR_PARAM1; @@ -324,22 +368,36 @@ static int command_crash(int argc, char **argv) volatile int zero = 0; cflush(); - ccprintf("%08x", 1 / zero); -#ifdef CONFIG_CMD_STACKOVERFLOW + ccprintf("%08x", 1U / zero); } else if (!strcasecmp(argv[1], "stack")) { stack_overflow_recurse(1); -#endif } else if (!strcasecmp(argv[1], "unaligned")) { volatile intptr_t unaligned_ptr = 0xcdef; cflush(); ccprintf("%08x", *(volatile int *)unaligned_ptr); } else if (!strcasecmp(argv[1], "watchdog")) { - while (1) - ; + while (1) { +/* Yield on native posix to avoid locking up the simulated sys clock */ +#ifdef CONFIG_ARCH_POSIX + k_cpu_idle(); +#endif + } } else if (!strcasecmp(argv[1], "hang")) { - interrupt_disable(); - while (1) - ; + uint32_t lock_key = irq_lock(); + + while (1) { +/* Yield on native posix to avoid locking up the simulated sys clock */ +#ifdef CONFIG_ARCH_POSIX + k_cpu_idle(); +#endif + } + + /* Unreachable, but included for consistency */ + irq_unlock(lock_key); + } else if (!strcasecmp(argv[1], "null")) { + volatile uintptr_t null_ptr = 0x0; + cflush(); + ccprintf("%08x\n", *(volatile unsigned int *)null_ptr); } else { return EC_ERROR_PARAM1; } @@ -347,23 +405,41 @@ static int command_crash(int argc, char **argv) /* Everything crashes, so shouldn't get back here */ return EC_ERROR_UNKNOWN; } + DECLARE_CONSOLE_COMMAND(crash, command_crash, - "[assert | divzero | udivzero" -#ifdef CONFIG_CMD_STACKOVERFLOW - " | stack" -#endif - " | unaligned | watchdog | hang]", - "Crash the system (for testing)"); -#endif + "[assert | divzero | udivzero | stack" + " | unaligned | watchdog | hang | null]", + "Crash the system (for testing)"); + +#ifdef TEST_BUILD +int test_command_crash(int argc, const char **argv) +{ + return command_crash(argc, argv); +} +#endif /* TEST_BUILD*/ +#endif /* CONFIG_CMD_CRASH */ -static int command_panicinfo(int argc, char **argv) +static int command_panicinfo(int argc, const char **argv) { - struct panic_data * const pdata_ptr = panic_get_data(); + struct panic_data *const pdata_ptr = panic_get_data(); + + if (argc == 2) { + if (!strcasecmp(argv[1], "clear")) { + memset(get_panic_data_write(), 0, + CONFIG_PANIC_DATA_SIZE); + ccprintf("Panic info cleared\n"); + return EC_SUCCESS; + } else { + return EC_ERROR_PARAM1; + } + } else if (argc != 1) + return EC_ERROR_PARAM_COUNT; if (pdata_ptr) { - ccprintf("Saved panic data:%s\n", + ccprintf("Saved panic data: 0x%02X %s\n", pdata_ptr->flags, (pdata_ptr->flags & PANIC_DATA_FLAG_OLD_CONSOLE ? - "" : " (NEW)")); + "" : + "(NEW)")); panic_data_print(pdata_ptr); @@ -371,29 +447,36 @@ static int command_panicinfo(int argc, char **argv) pdata_ptr->flags |= PANIC_DATA_FLAG_OLD_CONSOLE; } else { ccprintf("No saved panic data available " - "or panic data can't be safely interpreted.\n"); + "or panic data can't be safely interpreted.\n"); } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(panicinfo, command_panicinfo, - NULL, +DECLARE_CONSOLE_COMMAND(panicinfo, command_panicinfo, "[clear]", "Print info from a previous panic"); /*****************************************************************************/ /* Host commands */ -enum ec_status host_command_panic_info(struct host_cmd_handler_args *args) +static enum ec_status +host_command_panic_info(struct host_cmd_handler_args *args) { uint32_t pdata_size = get_panic_data_size(); uintptr_t pdata_start = get_panic_data_start(); - struct panic_data * pdata; + struct panic_data *pdata = panic_get_data(); if (pdata_start && pdata_size > 0) { - ASSERT(pdata_size <= args->response_max); + if (pdata_size > args->response_max) { + panic_printf("Panic data size %d is too " + "large, truncating to %d\n", + pdata_size, args->response_max); + pdata_size = args->response_max; + if (pdata) { + pdata->flags |= PANIC_DATA_FLAG_TRUNCATED; + } + } memcpy(args->response, (void *)pdata_start, pdata_size); args->response_size = pdata_size; - pdata = panic_get_data(); if (pdata) { /* Data has now been returned */ pdata->flags |= PANIC_DATA_FLAG_OLD_HOSTCMD; @@ -402,6 +485,5 @@ enum ec_status host_command_panic_info(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_PANIC_INFO, - host_command_panic_info, +DECLARE_HOST_COMMAND(EC_CMD_GET_PANIC_INFO, host_command_panic_info, EC_VER_MASK(0)); diff --git a/common/pd_log.c b/common/pd_log.c index 3708aad72e..477f8327eb 100644 --- a/common/pd_log.c +++ b/common/pd_log.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -21,8 +21,7 @@ BUILD_ASSERT(PD_LOG_SIZE_MASK == EVENT_LOG_SIZE_MASK); BUILD_ASSERT(PD_LOG_TIMESTAMP_SHIFT == EVENT_LOG_TIMESTAMP_SHIFT); BUILD_ASSERT(PD_EVENT_NO_ENTRY == EVENT_LOG_NO_ENTRY); -void pd_log_event(uint8_t type, uint8_t size_port, - uint16_t data, void *payload) +void pd_log_event(uint8_t type, uint8_t size_port, uint16_t data, void *payload) { uint32_t timestamp = get_time().val >> PD_LOG_TIMESTAMP_SHIFT; @@ -48,8 +47,8 @@ void pd_log_recv_vdm(int port, int cnt, uint32_t *payload) return; if (r->type != PD_EVENT_NO_ENTRY) { - timestamp = (get_time().val >> PD_LOG_TIMESTAMP_SHIFT) - - r->timestamp; + timestamp = (get_time().val >> PD_LOG_TIMESTAMP_SHIFT) - + r->timestamp; log_add_event(r->type, size_port, r->data, r->payload, timestamp); /* record that we have enqueued new content */ @@ -84,8 +83,7 @@ static enum ec_status hc_pd_get_log_entry(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PD_GET_LOG_ENTRY, - hc_pd_get_log_entry, +DECLARE_HOST_COMMAND(EC_CMD_PD_GET_LOG_ENTRY, hc_pd_get_log_entry, EC_VER_MASK(0)); static enum ec_status hc_pd_write_log_entry(struct host_cmd_handler_args *args) @@ -117,8 +115,7 @@ static enum ec_status hc_pd_write_log_entry(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PD_WRITE_LOG_ENTRY, - hc_pd_write_log_entry, +DECLARE_HOST_COMMAND(EC_CMD_PD_WRITE_LOG_ENTRY, hc_pd_write_log_entry, EC_VER_MASK(0)); #else /* !HAS_TASK_HOSTCMD */ /* we are a PD accessory, send back the events as a VDM (VDO_CMD_GET_LOG) */ diff --git a/common/peci.c b/common/peci.c index e0f03c95dd..b124d6b67b 100644 --- a/common/peci.c +++ b/common/peci.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,12 +8,13 @@ #include "chipset.h" #include "console.h" #include "peci.h" +#include "printf.h" #include "util.h" static int peci_get_cpu_temp(int *cpu_temp) { int rv; - uint8_t r_buf[PECI_GET_TEMP_READ_LENGTH] = {0}; + uint8_t r_buf[PECI_GET_TEMP_READ_LENGTH] = { 0 }; struct peci_data peci = { .cmd_code = PECI_CMD_GET_TEMP, .addr = PECI_TARGET_ADDRESS, @@ -72,10 +73,10 @@ int peci_temp_sensor_get_val(int idx, int *temp_ptr) /*****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_PECI -static int peci_cmd(int argc, char **argv) +static int peci_cmd(int argc, const char **argv) { - uint8_t r_buf[PECI_READ_DATA_FIFO_SIZE] = {0}; - uint8_t w_buf[PECI_WRITE_DATA_FIFO_SIZE] = {0}; + uint8_t r_buf[PECI_READ_DATA_FIFO_SIZE] = { 0 }; + uint8_t w_buf[PECI_WRITE_DATA_FIFO_SIZE] = { 0 }; struct peci_data peci = { .w_buf = w_buf, .r_buf = r_buf, @@ -139,15 +140,20 @@ static int peci_cmd(int argc, char **argv) if (peci_transaction(&peci)) { ccprintf("PECI transaction error\n"); return EC_ERROR_UNKNOWN; + } else { + char str_buf[hex_str_buf_size(peci.r_len)]; + + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(r_buf, sizeof(str_buf))); + ccprintf("PECI read data: %s\n", str_buf); + + return EC_SUCCESS; } - ccprintf("PECI read data: %ph\n", HEX_BUF(r_buf, peci.r_len)); - return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(peci, peci_cmd, - "addr wlen rlen cmd timeout(us)", +DECLARE_CONSOLE_COMMAND(peci, peci_cmd, "addr wlen rlen cmd timeout(us)", "PECI command"); -static int command_peci_temp(int argc, char **argv) +static int command_peci_temp(int argc, const char **argv) { int t; @@ -159,7 +165,6 @@ static int command_peci_temp(int argc, char **argv) ccprintf("CPU temp: %d K, %d C\n", t, K_TO_C(t)); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp, - NULL, +DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp, NULL, "Print CPU temperature"); #endif /* CONFIG_CMD_PECI */ diff --git a/common/peripheral.c b/common/peripheral.c index 79a80b0ef9..0d54bc9bee 100644 --- a/common/peripheral.c +++ b/common/peripheral.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,7 +18,7 @@ static enum ec_status hc_locate_chip(struct host_cmd_handler_args *args) switch (params->type) { case EC_CHIP_TYPE_CBI_EEPROM: -#ifdef CONFIG_CROS_BOARD_INFO +#ifdef CONFIG_CBI_EEPROM if (params->index >= 1) return EC_RES_OVERFLOW; resp->bus_type = EC_BUS_TYPE_I2C; @@ -27,10 +27,11 @@ static enum ec_status hc_locate_chip(struct host_cmd_handler_args *args) #else /* Lookup type is supported, but not present on system. */ return EC_RES_UNAVAILABLE; -#endif /* CONFIG_CROS_BOARD_INFO */ +#endif /* CONFIG_CBI_EEPROM */ break; case EC_CHIP_TYPE_TCPC: -#if defined(CONFIG_USB_PD_PORT_MAX_COUNT) && !defined(CONFIG_USB_PD_TCPC) +#if defined(CONFIG_USB_POWER_DELIVERY) && \ + defined(CONFIG_USB_PD_PORT_MAX_COUNT) && !defined(CONFIG_USB_PD_TCPC) if (params->index >= board_get_usb_pd_port_count()) return EC_RES_OVERFLOW; resp->bus_type = tcpc_config[params->index].bus_type; @@ -40,11 +41,9 @@ static enum ec_status hc_locate_chip(struct host_cmd_handler_args *args) resp->i2c_info.addr_flags = tcpc_config[params->index].i2c_info.addr_flags; } -#ifdef CONFIG_INTEL_VIRTUAL_MUX - resp->reserved = tcpc_config[params->index].usb23; -#endif #else - return EC_RES_UNAVAILABLE; + /* Not reachable in new boards. */ + return EC_RES_UNAVAILABLE; /* LCOV_EXCL_LINE */ #endif /* CONFIG_USB_PD_PORT_MAX_COUNT */ break; default: diff --git a/common/peripheral_charger.c b/common/peripheral_charger.c new file mode 100644 index 0000000000..d07ca042dd --- /dev/null +++ b/common/peripheral_charger.c @@ -0,0 +1,1076 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "atomic.h" +#include "chipset.h" +#include "common.h" +#include "hooks.h" +#include "host_command.h" +#include "lid_switch.h" +#include "mkbp_event.h" +#include "peripheral_charger.h" +#include "queue.h" +#include "stdbool.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +/* Peripheral Charge Manager */ + +#define CPRINTS(fmt, args...) cprints(CC_PCHG, "PCHG: " fmt, ##args) + +/* Host event queue. Shared by all ports. */ +static struct queue const host_events = + QUEUE_NULL(PCHG_EVENT_QUEUE_SIZE, uint32_t); +struct mutex host_event_mtx; + +static int pchg_count; + +/* + * Events and errors to be reported to the host in each chipset state. + * + * Off: None + * Suspend: Device attach or detach (for wake-up) + * On: SoC change and all other events and new errors except FW update. + * FW update events are separately reported. + * + * TODO:Allow the host to update the masks. + */ +struct pchg_policy_t pchg_policy_on = { + .evt_mask = + BIT(PCHG_EVENT_IRQ) | BIT(PCHG_EVENT_RESET) | + BIT(PCHG_EVENT_INITIALIZED) | BIT(PCHG_EVENT_ENABLED) | + BIT(PCHG_EVENT_DISABLED) | BIT(PCHG_EVENT_DEVICE_DETECTED) | + BIT(PCHG_EVENT_DEVICE_CONNECTED) | BIT(PCHG_EVENT_DEVICE_LOST) | + BIT(PCHG_EVENT_CHARGE_STARTED) | BIT(PCHG_EVENT_CHARGE_UPDATE) | + BIT(PCHG_EVENT_CHARGE_ENDED) | BIT(PCHG_EVENT_CHARGE_STOPPED) | + BIT(PCHG_EVENT_ERROR) | BIT(PCHG_EVENT_IN_NORMAL) | + BIT(PCHG_EVENT_ENABLE) | BIT(PCHG_EVENT_DISABLE), + .err_mask = GENMASK(0, PCHG_ERROR_COUNT - 1), +}; + +struct pchg_policy_t pchg_policy_suspend = { + .evt_mask = BIT(PCHG_EVENT_DEVICE_DETECTED) | + BIT(PCHG_EVENT_DEVICE_LOST), + .err_mask = 0, +}; + +static const char *_text_mode(enum pchg_mode mode) +{ + static const char *const mode_names[] = { + [PCHG_MODE_NORMAL] = "NORMAL", + [PCHG_MODE_DOWNLOAD] = "DOWNLOAD", + [PCHG_MODE_PASSTHRU] = "PASSTHRU", + [PCHG_MODE_BIST] = "BIST", + }; + BUILD_ASSERT(ARRAY_SIZE(mode_names) == PCHG_MODE_COUNT); + + if (mode < 0 || mode >= PCHG_MODE_COUNT) + return "UNDEF"; + + return mode_names[mode]; +} + +static const char *_text_event(enum pchg_event event) +{ + /* TODO: Use "S%d" for normal build. */ + static const char *const event_names[] = { + [PCHG_EVENT_NONE] = "NONE", + [PCHG_EVENT_IRQ] = "IRQ", + [PCHG_EVENT_RESET] = "RESET", + [PCHG_EVENT_INITIALIZED] = "INITIALIZED", + [PCHG_EVENT_ENABLED] = "ENABLED", + [PCHG_EVENT_DISABLED] = "DISABLED", + [PCHG_EVENT_DEVICE_DETECTED] = "DEVICE_DETECTED", + [PCHG_EVENT_DEVICE_CONNECTED] = "DEVICE_CONNECTED", + [PCHG_EVENT_DEVICE_LOST] = "DEVICE_LOST", + [PCHG_EVENT_CHARGE_STARTED] = "CHARGE_STARTED", + [PCHG_EVENT_CHARGE_UPDATE] = "CHARGE_UPDATE", + [PCHG_EVENT_CHARGE_ENDED] = "CHARGE_ENDED", + [PCHG_EVENT_CHARGE_STOPPED] = "CHARGE_STOPPED", + [PCHG_EVENT_UPDATE_OPENED] = "UPDATE_OPENED", + [PCHG_EVENT_UPDATE_CLOSED] = "UPDATE_CLOSED", + [PCHG_EVENT_UPDATE_WRITTEN] = "UPDATE_WRITTEN", + [PCHG_EVENT_IN_NORMAL] = "IN_NORMAL", + [PCHG_EVENT_ERROR] = "ERROR", + [PCHG_EVENT_ENABLE] = "ENABLE", + [PCHG_EVENT_DISABLE] = "DISABLE", + [PCHG_EVENT_BIST_RUN] = "BIST_RUN", + [PCHG_EVENT_BIST_DONE] = "BIST_DONE", + [PCHG_EVENT_UPDATE_OPEN] = "UPDATE_OPEN", + [PCHG_EVENT_UPDATE_WRITE] = "UPDATE_WRITE", + [PCHG_EVENT_UPDATE_CLOSE] = "UPDATE_CLOSE", + [PCHG_EVENT_UPDATE_ERROR] = "UPDATE_ERROR", + }; + BUILD_ASSERT(ARRAY_SIZE(event_names) == PCHG_EVENT_COUNT); + + if (event >= sizeof(event_names)) + return "UNDEF"; + + return event_names[event]; +} + +static const char *_text_error(uint32_t error) +{ + static const char *const error_names[] = { + [PCHG_ERROR_COMMUNICATION] = "COMMUNICATION", + [PCHG_ERROR_OVER_TEMPERATURE] = "OVER_TEMPERATURE", + [PCHG_ERROR_OVER_CURRENT] = "OVER_CURRENT", + [PCHG_ERROR_FOREIGN_OBJECT] = "FOREIGN_OBJECT", + [PCHG_ERROR_RESPONSE] = "RESPONSE", + [PCHG_ERROR_FW_VERSION] = "FW_VERSION", + [PCHG_ERROR_INVALID_FW] = "INVALID_FW", + [PCHG_ERROR_WRITE_FLASH] = "WRITE_FLASH", + [PCHG_ERROR_OTHER] = "OTHER", + }; + BUILD_ASSERT(ARRAY_SIZE(error_names) == PCHG_ERROR_COUNT); + int ffs = __builtin_ffs(error) - 1; + + if (0 <= ffs && ffs < PCHG_ERROR_COUNT) + return error_names[ffs]; + + return "UNDEF"; +} + +static void pchg_queue_event(struct pchg *ctx, enum pchg_event event) +{ + mutex_lock(&ctx->mtx); + if (queue_add_unit(&ctx->events, &event) == 0) { + ctx->dropped_event_count++; + CPRINTS("WARN: Queue is full."); + } + mutex_unlock(&ctx->mtx); +} + +static void pchg_queue_host_event(struct pchg *ctx, uint32_t event) +{ + int len; + size_t i; + uint32_t last_event; + + event |= EC_MKBP_PCHG_PORT_TO_EVENT(PCHG_CTX_TO_PORT(ctx)); + + mutex_lock(&host_event_mtx); + i = queue_count(&host_events); + if (i > 0) { + queue_peek_units(&host_events, &last_event, i - 1, 1); + if (last_event != event) + /* New event */ + len = queue_add_unit(&host_events, &event); + else + /* Same event already in a queue. */ + len = -1; + } else { + len = queue_add_unit(&host_events, &event); + } + mutex_unlock(&host_event_mtx); + + if (len < 0) { + CPRINTS("INFO: Skipped back-to-back host event"); + } else if (len == 0) { + ctx->dropped_host_event_count++; + CPRINTS("WARN: Host event queue is full"); + } + + mkbp_send_event(EC_MKBP_EVENT_PCHG); +} + +static const char *_text_state(enum pchg_state state) +{ + /* TODO: Use "S%d" for normal build. */ + static const char *const state_names[] = EC_PCHG_STATE_TEXT; + + BUILD_ASSERT(ARRAY_SIZE(state_names) == PCHG_STATE_COUNT); + + if (state >= sizeof(state_names)) + return "UNDEF"; + + return state_names[state]; +} + +static void pchg_print_status(const struct pchg *ctx) +{ + int port = PCHG_CTX_TO_PORT(ctx); + enum pchg_event event = PCHG_EVENT_NONE; + + queue_peek_units(&ctx->events, &event, 0, 1); + ccprintf("P%d STATE_%s EVENT_%s SOC=%d%%\n", port, + _text_state(ctx->state), _text_event(ctx->event), + ctx->battery_percent); + ccprintf("mode=%s\n", _text_mode(ctx->mode)); + ccprintf("error=0x%x dropped=%u fw_version=0x%x\n", ctx->error, + ctx->dropped_event_count, ctx->fw_version); + ccprintf("bist_cmd=0x%02x next_event=%s\n", ctx->bist_cmd, + _text_event(event)); +} + +static void _clear_port(struct pchg *ctx) +{ + mutex_lock(&ctx->mtx); + queue_init(&ctx->events); + mutex_unlock(&ctx->mtx); + atomic_clear(&ctx->irq); + ctx->battery_percent = 0; + ctx->error = 0; + ctx->update.data_ready = 0; +} + +static void reset_bist_cmd(struct pchg *ctx) +{ + ctx->bist_cmd = (ctx->cfg->rf_charge_msec) ? + PCHG_BIST_CMD_RF_CHARGE_ON : + PCHG_BIST_CMD_NONE; +} + +__overridable void board_pchg_power_on(int port, bool on) +{ +} + +/* + * This handles two cases: asynchronous reset and synchronous reset. + * + * Asynchronous resets are those triggered by charger chips. When a charger chip + * resets for some reason (e.g. WDT), it's expected to send PCHG_EVENT_RESET. + * This hook allows PCHG to reset its internal states (i.e. pchgs[port]). A + * reset here (by init) could be redundant for an asynchronous reset but it adds + * robustness. + * + * Synchronous resets are those triggered by the AP or PCHG itself. + */ +static enum pchg_state pchg_reset(struct pchg *ctx) +{ + enum pchg_state state = PCHG_STATE_RESET; + int rv; + + _clear_port(ctx); + + if (ctx->mode == PCHG_MODE_NORMAL || ctx->mode == PCHG_MODE_BIST) { + rv = ctx->cfg->drv->init(ctx); + if (rv == EC_SUCCESS) { + state = PCHG_STATE_INITIALIZED; + pchg_queue_event(ctx, PCHG_EVENT_ENABLE); + } else if (rv != EC_SUCCESS_IN_PROGRESS) { + ctx->event = PCHG_EVENT_ERROR; + ctx->error |= PCHG_ERROR_MASK(PCHG_ERROR_COMMUNICATION); + CPRINTS("ERR: Failed to reset to normal mode"); + } + } else if (ctx->mode == PCHG_MODE_DOWNLOAD) { + state = PCHG_STATE_DOWNLOAD; + pchg_queue_event(ctx, PCHG_EVENT_UPDATE_OPEN); + } /* No-op for passthru mode */ + + return state; +} + +static enum pchg_state reset_to_normal(struct pchg *ctx) +{ + ctx->mode = PCHG_MODE_NORMAL; + reset_bist_cmd(ctx); + return pchg_reset(ctx); +} + +static void bist_timer_completion(void) +{ + /* Initializing ctx isn't needed if compiler is smart enough. */ + struct pchg *ctx = &pchgs[0]; + int i; + + for (i = 0; i < pchg_count; i++) { + ctx = &pchgs[i]; + if (ctx->state == PCHG_STATE_BIST) + break; + } + if (i == pchg_count) + return; + + pchg_queue_event(ctx, PCHG_EVENT_BIST_DONE); + task_wake(TASK_ID_PCHG); +} +DECLARE_DEFERRED(bist_timer_completion); + +static void pchg_state_reset(struct pchg *ctx) +{ + switch (ctx->event) { + case PCHG_EVENT_RESET: + ctx->state = pchg_reset(ctx); + break; + case PCHG_EVENT_IN_NORMAL: + ctx->state = PCHG_STATE_INITIALIZED; + pchg_queue_event(ctx, PCHG_EVENT_ENABLE); + break; + default: + break; + } +} + +static void pchg_state_initialized(struct pchg *ctx) +{ + int rv; + + switch (ctx->event) { + case PCHG_EVENT_RESET: + ctx->state = pchg_reset(ctx); + break; + case PCHG_EVENT_ENABLE: + if (ctx->mode == PCHG_MODE_BIST) { + ctx->state = PCHG_STATE_BIST; + pchg_queue_event(ctx, PCHG_EVENT_BIST_RUN); + break; + } + + rv = ctx->cfg->drv->enable(ctx, true); + if (rv == EC_SUCCESS) + ctx->state = PCHG_STATE_ENABLED; + else if (rv != EC_SUCCESS_IN_PROGRESS) { + ctx->event = PCHG_EVENT_ERROR; + ctx->error |= PCHG_ERROR_MASK(PCHG_ERROR_COMMUNICATION); + CPRINTS("ERR: Failed to enable"); + } + break; + case PCHG_EVENT_ENABLED: + ctx->state = PCHG_STATE_ENABLED; + break; + default: + break; + } +} + +static void pchg_state_bist(struct pchg *ctx) +{ + int rv; + + switch (ctx->event) { + case PCHG_EVENT_BIST_RUN: + if (!ctx->cfg->drv->bist) { + CPRINTS("WARN: BIST not implemented"); + ctx->state = reset_to_normal(ctx); + break; + } + rv = ctx->cfg->drv->bist(ctx, ctx->bist_cmd); + if (rv != EC_SUCCESS && rv != EC_SUCCESS_IN_PROGRESS) { + CPRINTS("ERR: Failed to run BIST 0x%02x for %d", + ctx->bist_cmd, rv); + ctx->state = reset_to_normal(ctx); + break; + } + CPRINTS("INFO: BIST 0x%02x executed", ctx->bist_cmd); + if (ctx->bist_cmd == PCHG_BIST_CMD_RF_CHARGE_ON) + /* Schedule timer for turning off RF charge. */ + hook_call_deferred(&bist_timer_completion_data, + ctx->cfg->rf_charge_msec * MSEC); + break; + case PCHG_EVENT_BIST_DONE: + ctx->mode = PCHG_MODE_NORMAL; + ctx->bist_cmd = PCHG_BIST_CMD_NONE; + ctx->state = pchg_reset(ctx); + break; + case PCHG_EVENT_DEVICE_LOST: + /* + * DEVICE_LOST isn't generated in STATE_BIST, which is basically + * STATE_INITIALIZED. If a stylus is removed during RF_CHARGE, + * BIST_DONE will still be fired on timer expiration. Then, PCHG + * will be left in NORMAL bist_cmd= NONE. Thus, the next stylus + * (possibly a different stylus) won't be RF-charged. + * + * To avoid this, BIST_DONE should check if the stylus is still + * attached or not. If not, it should set bist_cmd=RF_CHARGE. + */ + case PCHG_EVENT_RESET: + ctx->state = reset_to_normal(ctx); + break; + default: + break; + } +} + +static void pchg_state_enabled(struct pchg *ctx) +{ + int rv; + + switch (ctx->event) { + case PCHG_EVENT_RESET: + ctx->state = pchg_reset(ctx); + break; + case PCHG_EVENT_DISABLE: + rv = ctx->cfg->drv->enable(ctx, false); + if (rv == EC_SUCCESS) + ctx->state = PCHG_STATE_INITIALIZED; + else if (rv != EC_SUCCESS_IN_PROGRESS) { + ctx->event = PCHG_EVENT_ERROR; + ctx->error |= PCHG_ERROR_MASK(PCHG_ERROR_COMMUNICATION); + CPRINTS("ERR: Failed to disable"); + } + break; + case PCHG_EVENT_DISABLED: + ctx->state = PCHG_STATE_INITIALIZED; + break; + case PCHG_EVENT_DEVICE_DETECTED: + if (ctx->bist_cmd != PCHG_BIST_CMD_NONE) { + ctx->mode = PCHG_MODE_BIST; + ctx->state = pchg_reset(ctx); + } else { + ctx->state = PCHG_STATE_DETECTED; + } + break; + case PCHG_EVENT_DEVICE_CONNECTED: + /* + * Proactively query SOC in case charging info won't be sent + * because device is already charged. + */ + ctx->cfg->drv->get_soc(ctx); + ctx->state = PCHG_STATE_CONNECTED; + break; + case PCHG_EVENT_ERROR: + if (ctx->error & PCHG_ERROR_MASK(PCHG_ERROR_FOREIGN_OBJECT)) { + if (ctx->bist_cmd != PCHG_BIST_CMD_NONE) { + ctx->mode = PCHG_MODE_BIST; + pchg_queue_event(ctx, PCHG_EVENT_RESET); + } + } + break; + default: + break; + } +} + +static void pchg_state_detected(struct pchg *ctx) +{ + int rv; + + switch (ctx->event) { + case PCHG_EVENT_RESET: + ctx->state = pchg_reset(ctx); + break; + case PCHG_EVENT_DISABLE: + rv = ctx->cfg->drv->enable(ctx, false); + if (rv == EC_SUCCESS) + ctx->state = PCHG_STATE_INITIALIZED; + else if (rv != EC_SUCCESS_IN_PROGRESS) { + ctx->event = PCHG_EVENT_ERROR; + ctx->error |= PCHG_ERROR_MASK(PCHG_ERROR_COMMUNICATION); + CPRINTS("ERR: Failed to disable"); + } + break; + case PCHG_EVENT_DISABLED: + ctx->state = PCHG_STATE_INITIALIZED; + break; + case PCHG_EVENT_DEVICE_CONNECTED: + /* + * Proactively query SOC in case charging info won't be sent + * because device is already charged. + */ + ctx->cfg->drv->get_soc(ctx); + ctx->state = PCHG_STATE_CONNECTED; + break; + case PCHG_EVENT_DEVICE_LOST: + ctx->battery_percent = 0; + ctx->state = PCHG_STATE_ENABLED; + reset_bist_cmd(ctx); + break; + default: + break; + } +} + +static void pchg_state_connected(struct pchg *ctx) +{ + int rv; + + switch (ctx->event) { + case PCHG_EVENT_RESET: + ctx->state = pchg_reset(ctx); + break; + case PCHG_EVENT_DISABLE: + rv = ctx->cfg->drv->enable(ctx, false); + if (rv == EC_SUCCESS) + ctx->state = PCHG_STATE_INITIALIZED; + else if (rv != EC_SUCCESS_IN_PROGRESS) { + ctx->event = PCHG_EVENT_ERROR; + ctx->error |= PCHG_ERROR_MASK(PCHG_ERROR_COMMUNICATION); + CPRINTS("ERR: Failed to disable"); + } + break; + case PCHG_EVENT_DISABLED: + ctx->state = PCHG_STATE_INITIALIZED; + break; + case PCHG_EVENT_CHARGE_STARTED: + ctx->state = PCHG_STATE_CHARGING; + break; + case PCHG_EVENT_DEVICE_LOST: + ctx->battery_percent = 0; + ctx->state = PCHG_STATE_ENABLED; + reset_bist_cmd(ctx); + break; + default: + break; + } +} + +static void pchg_state_charging(struct pchg *ctx) +{ + int rv; + + switch (ctx->event) { + case PCHG_EVENT_RESET: + ctx->state = pchg_reset(ctx); + break; + case PCHG_EVENT_DISABLE: + rv = ctx->cfg->drv->enable(ctx, false); + if (rv == EC_SUCCESS) + ctx->state = PCHG_STATE_INITIALIZED; + else if (rv != EC_SUCCESS_IN_PROGRESS) { + ctx->event = PCHG_EVENT_ERROR; + ctx->error |= PCHG_ERROR_MASK(PCHG_ERROR_COMMUNICATION); + CPRINTS("ERR: Failed to disable"); + } + break; + case PCHG_EVENT_DISABLED: + ctx->state = PCHG_STATE_INITIALIZED; + break; + case PCHG_EVENT_CHARGE_UPDATE: + break; + case PCHG_EVENT_DEVICE_LOST: + ctx->battery_percent = 0; + ctx->state = PCHG_STATE_ENABLED; + reset_bist_cmd(ctx); + break; + case PCHG_EVENT_CHARGE_ENDED: + case PCHG_EVENT_CHARGE_STOPPED: + ctx->state = PCHG_STATE_CONNECTED; + break; + default: + break; + } +} + +static void pchg_state_download(struct pchg *ctx) +{ + int rv; + + switch (ctx->event) { + case PCHG_EVENT_RESET: + ctx->state = pchg_reset(ctx); + break; + case PCHG_EVENT_UPDATE_OPEN: + rv = ctx->cfg->drv->update_open(ctx); + if (rv == EC_SUCCESS) { + pchg_queue_event(ctx, PCHG_EVENT_UPDATE_OPENED); + } else if (rv != EC_SUCCESS_IN_PROGRESS) { + pchg_queue_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR); + CPRINTS("ERR: Failed to open"); + } + break; + case PCHG_EVENT_UPDATE_OPENED: + ctx->state = PCHG_STATE_DOWNLOADING; + pchg_queue_host_event(ctx, EC_MKBP_PCHG_UPDATE_OPENED); + break; + case PCHG_EVENT_UPDATE_ERROR: + pchg_queue_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR); + break; + default: + break; + } +} + +static void pchg_state_downloading(struct pchg *ctx) +{ + int rv; + + switch (ctx->event) { + case PCHG_EVENT_RESET: + ctx->state = pchg_reset(ctx); + break; + case PCHG_EVENT_UPDATE_WRITE: + if (ctx->update.data_ready == 0) + break; + rv = ctx->cfg->drv->update_write(ctx); + if (rv == EC_SUCCESS) { + pchg_queue_event(ctx, PCHG_EVENT_UPDATE_WRITTEN); + } else if (rv != EC_SUCCESS_IN_PROGRESS) { + pchg_queue_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR); + CPRINTS("ERR: Failed to write"); + } + break; + case PCHG_EVENT_UPDATE_WRITTEN: + ctx->update.data_ready = 0; + pchg_queue_host_event(ctx, EC_MKBP_PCHG_WRITE_COMPLETE); + break; + case PCHG_EVENT_UPDATE_CLOSE: + rv = ctx->cfg->drv->update_close(ctx); + if (rv == EC_SUCCESS) { + pchg_queue_event(ctx, PCHG_EVENT_UPDATE_CLOSED); + } else if (rv != EC_SUCCESS_IN_PROGRESS) { + pchg_queue_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR); + CPRINTS("ERR: Failed to close"); + } + break; + case PCHG_EVENT_UPDATE_CLOSED: + ctx->state = PCHG_STATE_DOWNLOAD; + if (ctx->cfg->flags & PCHG_CFG_FW_UPDATE_SYNC) { + gpio_enable_interrupt(ctx->cfg->irq_pin); + ctx->state = reset_to_normal(ctx); + } + pchg_queue_host_event(ctx, EC_MKBP_PCHG_UPDATE_CLOSED); + break; + case PCHG_EVENT_UPDATE_ERROR: + CPRINTS("ERR: Failed to update"); + pchg_queue_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR); + break; + default: + break; + } +} + +static int pchg_should_notify(struct pchg *ctx, enum pchg_chipset_state state, + uint32_t prev_error, uint8_t prev_battery) +{ + if (ctx->event == PCHG_EVENT_ERROR) { + uint32_t err = ctx->error & ctx->policy[state]->err_mask; + /* Report only 0->1. */ + return ((err ^ prev_error) & err) ? 1 : 0; + } + + if (BIT(ctx->event) & ctx->policy[state]->evt_mask) { + if (ctx->event == PCHG_EVENT_CHARGE_UPDATE) + /* Report only new SoC. */ + return ctx->battery_percent != prev_battery; + return 1; + } + + return 0; +} + +/** + * Process an event. + * + * The handler of the current state processes one event. If the event is IRQ, + * the driver is called (get_event), which translates the event to an actual + * event. Note that state handlers themselves may enqueue a new event. + * + * It returns 1 if the processed event needs to be reported to the host. This is + * notified as EC_MKBP_PCHG_DEVICE_EVENT. The host will call EC_CMD_PCHG to get + * updated status including the SoC and errors. + * + * State handlers may send a host event separately. For example, FW update + * events are reported as EC_MKBP_PCHG_UPDATE_*. + * + * @param ctx + * @return 1: Notify host of EC_MKBP_PCHG_DEVICE_EVENT. + */ +static int pchg_run(struct pchg *ctx) +{ + enum pchg_state previous_state = ctx->state; + uint8_t previous_battery = ctx->battery_percent; + uint32_t previous_error = ctx->error; + int port = PCHG_CTX_TO_PORT(ctx); + int rv; + + mutex_lock(&ctx->mtx); + if (!queue_remove_unit(&ctx->events, &ctx->event)) { + mutex_unlock(&ctx->mtx); + CPRINTS("P%d No event in queue", port); + return 0; + } + mutex_unlock(&ctx->mtx); + + CPRINTS("P%d(MODE_%s) Run in STATE_%s for EVENT_%s", port, + _text_mode(ctx->mode), _text_state(ctx->state), + _text_event(ctx->event)); + + /* + * IRQ event is further translated to an actual event unless we're + * in passthru mode, where IRQ events will be passed to the host. + */ + if (ctx->event == PCHG_EVENT_IRQ) { + if (ctx->mode != PCHG_MODE_PASSTHRU) { + rv = ctx->cfg->drv->get_event(ctx); + if (rv) { + CPRINTS("ERR: Failed to get event (%d)", rv); + return 0; + } + } + CPRINTS(" EVENT_%s", _text_event(ctx->event)); + } + + if (ctx->event == PCHG_EVENT_NONE) + return 0; + + switch (ctx->state) { + case PCHG_STATE_RESET: + pchg_state_reset(ctx); + break; + case PCHG_STATE_INITIALIZED: + pchg_state_initialized(ctx); + break; + case PCHG_STATE_BIST: + pchg_state_bist(ctx); + break; + case PCHG_STATE_ENABLED: + pchg_state_enabled(ctx); + break; + case PCHG_STATE_DETECTED: + pchg_state_detected(ctx); + break; + case PCHG_STATE_CONNECTED: + pchg_state_connected(ctx); + break; + case PCHG_STATE_CHARGING: + pchg_state_charging(ctx); + break; + case PCHG_STATE_DOWNLOAD: + pchg_state_download(ctx); + break; + case PCHG_STATE_DOWNLOADING: + pchg_state_downloading(ctx); + break; + default: + CPRINTS("ERR: Unknown state (%d)", ctx->state); + return 0; + } + + if (previous_state != ctx->state) + CPRINTS("->STATE_%s", _text_state(ctx->state)); + + if (ctx->battery_percent != previous_battery) + CPRINTS("Battery %u%%", ctx->battery_percent); + + if (ctx->event == PCHG_EVENT_ERROR) { + /* Print (only one) new error. */ + uint32_t err = (ctx->error ^ previous_error) & ctx->error; + + if (err) + CPRINTS("ERROR_%s", _text_error(err)); + } + + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + /* Chipset off */ + return 0; + else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) { + /* Chipset in suspend */ + if (IS_ENABLED(CONFIG_LID_SWITCH) && !lid_is_open()) + /* Don't wake up if the lid is closed. */ + return 0; + return pchg_should_notify(ctx, PCHG_CHIPSET_STATE_SUSPEND, + previous_error, previous_battery); + } else { + /* Chipset on */ + return pchg_should_notify(ctx, PCHG_CHIPSET_STATE_ON, + previous_error, previous_battery); + } +} + +void pchg_irq(enum gpio_signal signal) +{ + struct pchg *ctx; + int i; + + for (i = 0; i < pchg_count; i++) { + ctx = &pchgs[i]; + if (signal == ctx->cfg->irq_pin) { + ctx->irq = 1; + task_wake(TASK_ID_PCHG); + return; + } + } +} + +static void pchg_startup(void) +{ + struct pchg *ctx; + int p; + int active_pchg_count = 0; + int rv; + + CPRINTS("%s", __func__); + queue_init(&host_events); + + pchg_count = board_get_pchg_count(); + + for (p = 0; p < pchg_count; p++) { + rv = EC_SUCCESS; + ctx = &pchgs[p]; + _clear_port(ctx); + ctx->mode = PCHG_MODE_NORMAL; + reset_bist_cmd(ctx); + gpio_disable_interrupt(ctx->cfg->irq_pin); + board_pchg_power_on(p, 1); + ctx->cfg->drv->reset(ctx); + if (ctx->cfg->drv->get_chip_info) + rv = ctx->cfg->drv->get_chip_info(ctx); + if (rv == EC_SUCCESS) { + gpio_enable_interrupt(ctx->cfg->irq_pin); + active_pchg_count++; + } else { + CPRINTS("ERR: Failed to probe P%d", p); + board_pchg_power_on(p, 0); + } + } + + if (active_pchg_count) + task_wake(TASK_ID_PCHG); +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pchg_startup, HOOK_PRIO_DEFAULT); + +static void pchg_shutdown(void) +{ + struct pchg *ctx; + int p; + + CPRINTS("%s", __func__); + + for (p = 0; p < pchg_count; p++) { + ctx = &pchgs[0]; + gpio_disable_interrupt(ctx->cfg->irq_pin); + board_pchg_power_on(p, 0); + } +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pchg_shutdown, HOOK_PRIO_DEFAULT); + +void pchg_task(void *u) +{ + struct pchg *ctx; + int p; + + if (chipset_in_state(CHIPSET_STATE_ON)) + /* We are here after power-on (because of late sysjump). */ + pchg_startup(); + + while (true) { + /* Process pending events for all ports. */ + for (p = 0; p < pchg_count; p++) { + ctx = &pchgs[p]; + do { + if (atomic_clear(&ctx->irq)) + pchg_queue_event(ctx, PCHG_EVENT_IRQ); + if (pchg_run(ctx)) + pchg_queue_host_event( + ctx, EC_MKBP_PCHG_DEVICE_EVENT); + } while (queue_count(&ctx->events)); + } + + task_wait_event(-1); + } +} + +static enum ec_status hc_pchg_count(struct host_cmd_handler_args *args) +{ + struct ec_response_pchg_count *r = args->response; + + r->port_count = pchg_count; + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PCHG_COUNT, hc_pchg_count, EC_VER_MASK(0)); + +#define HCPRINTS(fmt, args...) cprints(CC_PCHG, "HC:PCHG: " fmt, ##args) + +static enum ec_status hc_pchg(struct host_cmd_handler_args *args) +{ + const struct ec_params_pchg_v3 *p = args->params; + struct ec_response_pchg_v2 *r = args->response; + int port = p->port; + struct pchg *ctx; + + /* Version 0 shouldn't exist. */ + if (args->version == 0) + return EC_RES_INVALID_VERSION; + + if (port >= pchg_count) + return EC_RES_INVALID_PARAM; + + ctx = &pchgs[port]; + mutex_lock(&ctx->mtx); + + if (ctx->state == PCHG_STATE_CONNECTED && + ctx->battery_percent >= ctx->cfg->full_percent) + r->state = PCHG_STATE_FULL; + else + r->state = ctx->state; + + r->battery_percentage = ctx->battery_percent; + r->error = ctx->error; + r->fw_version = ctx->fw_version; + r->dropped_event_count = ctx->dropped_event_count; + r->dropped_host_event_count = ctx->dropped_host_event_count; + + /* Clear error flags acked by the host. */ + if (args->version > 2) + ctx->error &= ~p->error; + + /* v2 and v3 have the same response struct. */ + args->response_size = args->version == 1 ? + sizeof(struct ec_response_pchg) : + sizeof(*r); + + mutex_unlock(&ctx->mtx); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PCHG, hc_pchg, + EC_VER_MASK(1) | EC_VER_MASK(2) | EC_VER_MASK(3)); + +int pchg_get_next_event(uint8_t *out) +{ + uint32_t event; + size_t len; + + mutex_lock(&host_event_mtx); + len = queue_remove_unit(&host_events, &event); + mutex_unlock(&host_event_mtx); + if (len == 0) + return 0; + + memcpy(out, &event, sizeof(event)); + + /* Ping host again if there are more events to send. */ + if (queue_count(&host_events)) + mkbp_send_event(EC_MKBP_EVENT_PCHG); + + return sizeof(event); +} +DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_PCHG, pchg_get_next_event); + +static enum ec_status hc_pchg_update(struct host_cmd_handler_args *args) +{ + const struct ec_params_pchg_update *p = args->params; + struct ec_response_pchg_update *r = args->response; + int port = p->port; + struct pchg *ctx; + + if (port >= pchg_count) + return EC_RES_INVALID_PARAM; + + ctx = &pchgs[port]; + + switch (p->cmd) { + case EC_PCHG_UPDATE_CMD_RESET_TO_NORMAL: + HCPRINTS("Resetting to normal mode"); + + gpio_disable_interrupt(ctx->cfg->irq_pin); + _clear_port(ctx); + ctx->mode = PCHG_MODE_NORMAL; + ctx->cfg->drv->reset(ctx); + gpio_enable_interrupt(ctx->cfg->irq_pin); + break; + + case EC_PCHG_UPDATE_CMD_OPEN: + HCPRINTS("Resetting to download mode"); + + gpio_disable_interrupt(ctx->cfg->irq_pin); + _clear_port(ctx); + ctx->mode = PCHG_MODE_DOWNLOAD; + ctx->cfg->drv->reset(ctx); + if (ctx->cfg->flags & PCHG_CFG_FW_UPDATE_SYNC) { + pchg_queue_event(ctx, PCHG_EVENT_RESET); + } else { + gpio_enable_interrupt(ctx->cfg->irq_pin); + } + ctx->update.version = p->version; + r->block_size = ctx->cfg->block_size; + args->response_size = sizeof(*r); + break; + + case EC_PCHG_UPDATE_CMD_WRITE: + if (ctx->state != PCHG_STATE_DOWNLOADING) + return EC_RES_ERROR; + if (p->size > sizeof(ctx->update.data)) + return EC_RES_OVERFLOW; + if (ctx->update.data_ready) + return EC_RES_BUSY; + + HCPRINTS("Writing %u bytes to 0x%x", p->size, p->addr); + ctx->update.addr = p->addr; + ctx->update.size = p->size; + memcpy(ctx->update.data, p->data, p->size); + pchg_queue_event(ctx, PCHG_EVENT_UPDATE_WRITE); + ctx->update.data_ready = 1; + break; + + case EC_PCHG_UPDATE_CMD_CLOSE: + if (ctx->state != PCHG_STATE_DOWNLOADING) + return EC_RES_ERROR; + if (ctx->update.data_ready) + return EC_RES_BUSY; + + HCPRINTS("Closing update session (crc=0x%x)", p->crc32); + ctx->update.crc32 = p->crc32; + pchg_queue_event(ctx, PCHG_EVENT_UPDATE_CLOSE); + break; + + case EC_PCHG_UPDATE_CMD_RESET: + HCPRINTS("Resetting"); + + gpio_disable_interrupt(ctx->cfg->irq_pin); + _clear_port(ctx); + ctx->cfg->drv->reset(ctx); + gpio_enable_interrupt(ctx->cfg->irq_pin); + break; + + case EC_PCHG_UPDATE_CMD_ENABLE_PASSTHRU: + HCPRINTS("Enabling passthru mode"); + mutex_lock(&ctx->mtx); + ctx->mode = PCHG_MODE_PASSTHRU; + mutex_unlock(&ctx->mtx); + break; + + default: + return EC_RES_INVALID_PARAM; + } + + task_wake(TASK_ID_PCHG); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PCHG_UPDATE, hc_pchg_update, EC_VER_MASK(0)); + +static int cc_pchg(int argc, const char **argv) +{ + int port; + char *end; + struct pchg *ctx; + + if (argc < 2 || 4 < argc) + return EC_ERROR_PARAM_COUNT; + + port = strtoi(argv[1], &end, 0); + if (*end || port < 0 || port >= pchg_count) + return EC_ERROR_PARAM1; + ctx = &pchgs[port]; + + if (argc == 2) { + pchg_print_status(ctx); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[2], "reset")) { + if (argc == 3) + ctx->mode = PCHG_MODE_NORMAL; + else if (!strcasecmp(argv[3], "download")) + ctx->mode = PCHG_MODE_DOWNLOAD; + else + return EC_ERROR_PARAM3; + gpio_disable_interrupt(ctx->cfg->irq_pin); + _clear_port(ctx); + ctx->cfg->drv->reset(ctx); + gpio_enable_interrupt(ctx->cfg->irq_pin); + } else if (!strcasecmp(argv[2], "enable")) { + pchg_queue_event(ctx, PCHG_EVENT_ENABLE); + } else if (!strcasecmp(argv[2], "disable")) { + pchg_queue_event(ctx, PCHG_EVENT_DISABLE); + } else { + return EC_ERROR_PARAM2; + } + + task_wake(TASK_ID_PCHG); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(pchg, cc_pchg, + "\n\t" + "\n\t reset [download]" + "\n\t enable" + "\n\t disable", + "Control peripheral chargers"); diff --git a/common/port80.c b/common/port80.c index 52264cc446..715d748ee9 100644 --- a/common/port80.c +++ b/common/port80.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,20 +7,27 @@ #include "common.h" #include "console.h" +#include "chipset.h" #include "display_7seg.h" #include "hooks.h" #include "host_command.h" #include "port80.h" +#include "printf.h" #include "task.h" #include "timer.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_PORT80, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_PORT80, format, ##args) -static uint16_t __bss_slow history[CONFIG_PORT80_HISTORY_LEN]; -static int __bss_slow writes; /* Number of port 80 writes so far */ -static int last_boot; /* Last code from previous boot */ -static int __bss_slow scroll; +#ifdef CONFIG_PORT80_4_BYTE +typedef uint32_t port80_code_t; +#else +typedef uint16_t port80_code_t; +#endif +static port80_code_t history[CONFIG_PORT80_HISTORY_LEN]; +static int writes; /* Number of port 80 writes so far */ +static uint16_t last_boot; /* Last code from previous boot */ +static int scroll; #ifdef CONFIG_BRINGUP #undef CONFIG_PORT80_PRINT_IN_INT @@ -32,8 +39,37 @@ static int print_in_int = CONFIG_PORT80_PRINT_IN_INT; static void port80_dump_buffer(void); DECLARE_DEFERRED(port80_dump_buffer); +#ifdef CONFIG_CUSTOMIZED_DESIGN +static int ddr_initialized_fail; +static int has_port_80_data; + +int port_80_last(void) +{ + return (uint16_t)history[(writes-1) % ARRAY_SIZE(history)]; +} + +int amd_ddr_initialized_check(void) +{ + return ddr_initialized_fail; +} + +void port_80_read_customized(int index); +DECLARE_DEFERRED(port_80_read_customized); + +void port_80_read_customized(int index) +{ + if (has_port_80_data) { + CPRINTF("PORT80: %04X\n", (history[(writes-1) % ARRAY_SIZE(history)] & 0xFFFF)); + has_port_80_data = 0; + } +} +#endif + void port_80_write(int data) { +#ifndef CONFIG_CUSTOMIZED_DESIGN + char ts_str[PRINTF_TIMESTAMP_BUF_SIZE]; + /* * By default print_in_int is disabled if: * 1. CONFIG_BRINGUP is not defined @@ -47,22 +83,36 @@ void port_80_write(int data) * schedule a deferred call 4 seconds after the last port80 write to * dump the current port80 buffer to EC console. This is to allow * developers to help debug BIOS progress by tracing port80 messages. - * - * P.S.: Deferred call is not scheduled for special event codes (data >= - * 0x100). This is because only 8-bit port80 messages are assumed to be - * coming from the host. */ - if (print_in_int) - CPRINTF("%c[%pT Port 80: 0x%02x]", - scroll ? '\n' : '\r', PRINTF_TIMESTAMP_NOW, data); - else if (data < 0x100) + + if (print_in_int) { + snprintf_timestamp_now(ts_str, sizeof(ts_str)); + CPRINTF("%c[%s Port 80: 0x%02x]", scroll ? '\n' : '\r', ts_str, + data); + } + + if (!IS_ENABLED(CONFIG_PORT80_QUIET)) { hook_call_deferred(&port80_dump_buffer_data, 4 * SECOND); + } +#else + if (!has_port_80_data) { + has_port_80_data = 1; + hook_call_deferred(&port_80_read_customized_data, 10 * MSEC); + } + + if (data == 0x12344321) + ddr_initialized_fail = 1; +#endif /* Save current port80 code if system is resetting */ if (data == PORT_80_EVENT_RESET && writes) { - int prev = history[(writes-1) % ARRAY_SIZE(history)]; + port80_code_t prev = + history[(writes - 1) % ARRAY_SIZE(history)]; - /* Ignore special event codes */ + /* + * last_boot only reports 8-bit codes. + * Ignore special event codes and 4-byte codes. + */ if (prev < 0x100) last_boot = prev; } @@ -123,7 +173,7 @@ static void port80_dump_buffer(void) /*****************************************************************************/ /* Console commands */ -static int command_port80(int argc, char **argv) +static int command_port80(int argc, const char **argv) { /* * 'port80 scroll' toggles whether port 80 output begins with a newline @@ -150,8 +200,7 @@ static int command_port80(int argc, char **argv) port80_dump_buffer(); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(port80, command_port80, - "[scroll | intprint | flush]", +DECLARE_CONSOLE_COMMAND(port80, command_port80, "[scroll | intprint | flush]", "Print port80 writes or toggle port80 scrolling"); enum ec_status port80_last_boot(struct host_cmd_handler_args *args) @@ -164,7 +213,7 @@ enum ec_status port80_last_boot(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -enum ec_status port80_command_read(struct host_cmd_handler_args *args) +static enum ec_status port80_command_read(struct host_cmd_handler_args *args) { const struct ec_params_port80_read *p = args->params; uint32_t offset = p->read_buffer.offset; @@ -183,24 +232,23 @@ enum ec_status port80_command_read(struct host_cmd_handler_args *args) } else if (p->subcmd == EC_PORT80_READ_BUFFER) { /* do not allow bad offset or size */ if (offset >= ARRAY_SIZE(history) || entries == 0 || - entries > args->response_max) + entries > args->response_max) return EC_RES_INVALID_PARAM; for (i = 0; i < entries; i++) { - uint16_t e = history[(i + offset) % - ARRAY_SIZE(history)]; + uint16_t e = + history[(i + offset) % ARRAY_SIZE(history)]; rsp->data.codes[i] = e; } - args->response_size = entries*sizeof(uint16_t); + args->response_size = entries * sizeof(uint16_t); return EC_RES_SUCCESS; } return EC_RES_INVALID_PARAM; } -DECLARE_HOST_COMMAND(EC_CMD_PORT80_READ, - port80_command_read, - EC_VER_MASK(0) | EC_VER_MASK(1)); +DECLARE_HOST_COMMAND(EC_CMD_PORT80_READ, port80_command_read, + EC_VER_MASK(0) | EC_VER_MASK(1)); static void port80_log_resume(void) { diff --git a/common/power_button.c b/common/power_button.c index 1ac3893492..484d25154a 100644 --- a/common/power_button.c +++ b/common/power_button.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,7 @@ /* Power button module for Chrome EC */ #include "button.h" +#include "chipset.h" #include "common.h" #include "console.h" #include "gpio.h" @@ -21,14 +22,14 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_SWITCH, outstr) -#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ##args) /* By default the power button is active low */ #ifndef CONFIG_POWER_BUTTON_FLAGS #define CONFIG_POWER_BUTTON_FLAGS 0 #endif -static int debounced_power_pressed; /* Debounced power button state */ +static int debounced_power_pressed; /* Debounced power button state */ static int simulate_power_pressed; static volatile int power_button_is_stable = 1; @@ -41,8 +42,11 @@ static const struct button_config power_button = { int power_button_signal_asserted(void) { - return !!(gpio_get_level(power_button.gpio) - == (power_button.flags & BUTTON_FLAG_ACTIVE_HIGH) ? 1 : 0); + return !!( + gpio_get_level(power_button.gpio) == + (power_button.flags & BUTTON_FLAG_ACTIVE_HIGH) ? + 1 : + 0); } /** @@ -93,8 +97,8 @@ int power_button_wait_for_release(int timeout_us) * the power button is debounced but not changed, or the power * button has not been debounced. */ - task_wait_event(MIN(power_button.debounce_us, - deadline.val - now.val)); + task_wait_event( + MIN(power_button.debounce_us, deadline.val - now.val)); } CPRINTS("%s released in time", power_button.name); @@ -132,6 +136,10 @@ DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pb_chipset_startup, HOOK_PRIO_DEFAULT); static void pb_chipset_shutdown(void) { + /* Don't set AP_IDLE if shutting down due to power failure. */ + if (chipset_get_shutdown_reason() == CHIPSET_SHUTDOWN_POWERFAIL) + return; + chip_save_reset_flags(chip_read_reset_flags() | EC_RESET_FLAG_AP_IDLE); system_set_reset_flags(EC_RESET_FLAG_AP_IDLE); CPRINTS("Saved AP_IDLE flag"); @@ -141,7 +149,7 @@ DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pb_chipset_shutdown, * Slightly higher than handle_pending_reboot because * it may clear AP_IDLE flag. */ - HOOK_PRIO_DEFAULT - 1); + HOOK_PRIO_PRE_DEFAULT); #endif /** @@ -164,8 +172,8 @@ static void power_button_change_deferred(void) debounced_power_pressed = new_pressed; power_button_is_stable = 1; - CPRINTS("%s %s", - power_button.name, new_pressed ? "pressed" : "released"); + CPRINTS("%s %s", power_button.name, + new_pressed ? "pressed" : "released"); /* Call hooks */ hook_notify(HOOK_POWER_BUTTON_CHANGE); @@ -176,6 +184,15 @@ static void power_button_change_deferred(void) } DECLARE_DEFERRED(power_button_change_deferred); +static void power_button_simulate_deferred(void) +{ + ccprintf("Simulating %s release.\n", power_button.name); + simulate_power_pressed = 0; + power_button_is_stable = 0; + power_button_change_deferred(); +} +DECLARE_DEFERRED(power_button_simulate_deferred); + void power_button_interrupt(enum gpio_signal signal) { /* @@ -192,36 +209,32 @@ void power_button_interrupt(enum gpio_signal signal) power_button.debounce_us); } +void power_button_simulate_press(unsigned int duration) +{ + ccprintf("Simulating %d ms %s press.\n", duration, power_button.name); + simulate_power_pressed = 1; + power_button_is_stable = 0; + power_button_change_deferred(); + hook_call_deferred(&power_button_simulate_deferred_data, + duration * MSEC); +} + /*****************************************************************************/ /* Console commands */ -static int command_powerbtn(int argc, char **argv) +static int command_powerbtn(int argc, const char **argv) { - int ms = 200; /* Press duration in ms */ + int ms = 200; /* Press duration in ms */ char *e; if (argc > 1) { ms = strtoi(argv[1], &e, 0); - if (*e) + if (*e || ms < 0) return EC_ERROR_PARAM1; } - ccprintf("Simulating %d ms %s press.\n", ms, power_button.name); - simulate_power_pressed = 1; - power_button_is_stable = 0; - hook_call_deferred(&power_button_change_deferred_data, 0); - - if (ms > 0) - msleep(ms); - - ccprintf("Simulating %s release.\n", power_button.name); - simulate_power_pressed = 0; - power_button_is_stable = 0; - hook_call_deferred(&power_button_change_deferred_data, 0); - + power_button_simulate_press(ms); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(powerbtn, command_powerbtn, - "[msec]", +DECLARE_CONSOLE_COMMAND(powerbtn, command_powerbtn, "[msec]", "Simulate power button press"); - diff --git a/common/power_button_x86.c b/common/power_button_x86.c index 661f9b2a3d..f0e43a80c3 100644 --- a/common/power_button_x86.c +++ b/common/power_button_x86.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -23,7 +23,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_SWITCH, outstr) -#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ##args) /* * x86 chipsets have a hardware timer on the power button input which causes @@ -54,14 +54,14 @@ * to host v v * @S0 make code break code */ -#define PWRBTN_DELAY_T0 (32 * MSEC) /* 32ms (PCH requires >16ms) */ -#define PWRBTN_DELAY_T1 (4 * SECOND - PWRBTN_DELAY_T0) /* 4 secs - t0 */ +#define PWRBTN_DELAY_T0 (32 * MSEC) /* 32ms (PCH requires >16ms) */ +#define PWRBTN_DELAY_T1 (4 * SECOND - PWRBTN_DELAY_T0) /* 4 secs - t0 */ /* * Length of time to stretch initial power button press to give chipset a * chance to wake up (~100ms) and react to the press (~16ms). Also used as * pulse length for simulated power button presses when the system is off. */ -#define PWRBTN_INITIAL_US (200 * MSEC) +#define PWRBTN_INITIAL_US (200 * MSEC) enum power_button_state { /* Button up; state machine idle */ @@ -92,18 +92,9 @@ enum power_button_state { }; static enum power_button_state pwrbtn_state = PWRBTN_STATE_IDLE; -static const char * const state_names[] = { - "idle", - "pressed", - "t0", - "t1", - "held", - "lid-open", - "released", - "eat-release", - "init-on", - "recovery", - "was-off", +static const char *const state_names[] = { + "idle", "pressed", "t0", "t1", "held", "lid-open", + "released", "eat-release", "init-on", "recovery", "was-off", }; /* @@ -139,7 +130,7 @@ static void set_pwrbtn_to_pch(int high, int init) */ #ifdef CONFIG_CHARGER if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && !high && - (charge_want_shutdown() || charge_prevent_power_on(!init))) { + (charge_want_shutdown() || charge_prevent_power_on(!init))) { CPRINTS("PB PCH pwrbtn ignored due to battery level"); high = 1; } @@ -211,7 +202,7 @@ static void power_button_released(uint64_t tnow) /** * Set initial power button state. */ -static void set_initial_pwrbtn_state(void) +test_export_static void set_initial_pwrbtn_state(void) { uint32_t reset_flags = system_get_reset_flags(); @@ -346,8 +337,8 @@ static void state_machine(uint64_t tnow) if (!IS_ENABLED(CONFIG_CHARGER) || charge_prevent_power_on(0)) { if (tnow > - (tpb_task_start + - CONFIG_POWER_BUTTON_INIT_TIMEOUT * SECOND)) { + (tpb_task_start + + CONFIG_POWER_BUTTON_INIT_TIMEOUT * SECOND)) { pwrbtn_state = PWRBTN_STATE_IDLE; break; } @@ -366,9 +357,9 @@ static void state_machine(uint64_t tnow) #ifdef CONFIG_DELAY_DSW_PWROK_TO_PWRBTN /* Check if power button is ready. If not, we'll come back. */ if (get_time().val - get_time_dsw_pwrok() < - CONFIG_DSW_PWROK_TO_PWRBTN_US) { + CONFIG_DSW_PWROK_TO_PWRBTN_US) { tnext_state = get_time_dsw_pwrok() + - CONFIG_DSW_PWROK_TO_PWRBTN_US; + CONFIG_DSW_PWROK_TO_PWRBTN_US; break; } #endif @@ -434,17 +425,18 @@ void power_button_task(void *u) tsleep = tnext_state; t = get_time().val; if (tsleep > t) { - unsigned d = tsleep == -1 ? -1 : (unsigned)(tsleep - t); + unsigned int d = + tsleep == -1 ? -1 : (unsigned int)(tsleep - t); /* - * (Yes, the conversion from uint64_t to unsigned could - * theoretically overflow if we wanted to sleep for - * more than 2^32 us, but our timeouts are small enough - * that can't happen - and even if it did, we'd just go - * back to sleep after deciding that we woke up too - * early.) + * (Yes, the conversion from uint64_t to unsigned int + * could theoretically overflow if we wanted to sleep + * for more than 2^32 us, but our timeouts are small + * enough that can't happen - and even if it did, we'd + * just go back to sleep after deciding that we woke up + * too early.) */ CPRINTS("PB task %d = %s, wait %d", pwrbtn_state, - state_names[pwrbtn_state], d); + state_names[pwrbtn_state], d); task_wait_event(d); } } @@ -459,6 +451,14 @@ static void powerbtn_x86_init(void) } DECLARE_HOOK(HOOK_INIT, powerbtn_x86_init, HOOK_PRIO_DEFAULT); +void chipset_power_on(void) +{ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && + pwrbtn_state != PWRBTN_STATE_INIT_ON) { + power_button_pch_pulse(); + } +} + #ifdef CONFIG_LID_SWITCH /** * Handle switch changes based on lid event. @@ -466,9 +466,9 @@ DECLARE_HOOK(HOOK_INIT, powerbtn_x86_init, HOOK_PRIO_DEFAULT); static void powerbtn_x86_lid_change(void) { /* If chipset is off, pulse the power button on lid open to wake it. */ - if (lid_is_open() && chipset_in_state(CHIPSET_STATE_ANY_OFF) - && pwrbtn_state != PWRBTN_STATE_INIT_ON) - power_button_pch_pulse(); + if (lid_is_open()) { + chipset_power_on(); + } } DECLARE_HOOK(HOOK_LID_CHANGE, powerbtn_x86_lid_change, HOOK_PRIO_DEFAULT); #endif @@ -520,12 +520,11 @@ static enum ec_status hc_config_powerbtn_x86(struct host_cmd_handler_args *args) power_button_pulse_enabled = !!(p->flags & EC_POWER_BUTTON_ENABLE_PULSE); - return EC_SUCCESS; + return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_CONFIG_POWER_BUTTON, hc_config_powerbtn_x86, EC_VER_MASK(0)); - /* * Currently, the only reason why we disable power button pulse is to allow * detachable menu on AP to use power button for selection purpose without @@ -546,8 +545,8 @@ DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, power_button_pulse_setting_reset, DECLARE_HOOK(HOOK_CHIPSET_RESUME, power_button_pulse_setting_reset, HOOK_PRIO_DEFAULT); -#define POWER_BUTTON_SYSJUMP_TAG 0x5042 /* PB */ -#define POWER_BUTTON_HOOK_VERSION 1 +#define POWER_BUTTON_SYSJUMP_TAG 0x5042 /* PB */ +#define POWER_BUTTON_HOOK_VERSION 1 static void power_button_pulse_setting_restore_state(void) { @@ -562,12 +561,11 @@ static void power_button_pulse_setting_restore_state(void) power_button_pulse_enabled = *state; } DECLARE_HOOK(HOOK_INIT, power_button_pulse_setting_restore_state, - HOOK_PRIO_INIT_POWER_BUTTON + 1); + HOOK_PRIO_POST_POWER_BUTTON); static void power_button_pulse_setting_preserve_state(void) { - system_add_jump_tag(POWER_BUTTON_SYSJUMP_TAG, - POWER_BUTTON_HOOK_VERSION, + system_add_jump_tag(POWER_BUTTON_SYSJUMP_TAG, POWER_BUTTON_HOOK_VERSION, sizeof(power_button_pulse_enabled), &power_button_pulse_enabled); } diff --git a/common/printf.c b/common/printf.c index f876a1da19..d2cc78f5aa 100644 --- a/common/printf.c +++ b/common/printf.c @@ -1,10 +1,11 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Printf-like functionality for Chrome EC */ +#include "builtin/assert.h" #include "console.h" #include "printf.h" #include "timer.h" @@ -12,24 +13,7 @@ static const char error_str[] = "ERROR"; -#define MAX_FORMAT 1024 /* Maximum chars in a single format field */ - -#ifndef CONFIG_DEBUG_PRINTF -static inline int divmod(uint64_t *n, int d) -{ - return uint64divmod(n, d); -} - -#else /* CONFIG_DEBUG_PRINTF */ -/* if we are optimizing for size, remove the 64-bit support */ -#define NO_UINT64_SUPPORT -static inline int divmod(uint32_t *n, int d) -{ - int r = *n % d; - *n /= d; - return r; -} -#endif +#define MAX_FORMAT 1024 /* Maximum chars in a single format field */ /** * Convert the lowest nibble of a number to hex @@ -47,27 +31,118 @@ static int hexdigit(int c) } /* Flags for vfnprintf() flags */ -#define PF_LEFT BIT(0) /* Left-justify */ -#define PF_PADZERO BIT(1) /* Pad with 0's not spaces */ -#define PF_SIGN BIT(2) /* Add sign (+) for a positive number */ +#define PF_LEFT BIT(0) /* Left-justify */ +#define PF_PADZERO BIT(1) /* Pad with 0's not spaces */ +#define PF_SIGN BIT(2) /* Add sign (+) for a positive number */ +#define PF_64BIT BIT(3) /* Number is 64-bit */ + +test_export_static char *uint64_to_str(char *buf, int buf_len, uint64_t val, + int precision, int base, bool uppercase) +{ + int i; + char *str; + + if (buf_len <= 1) + return NULL; + + if (base <= 1) + return NULL; + + /* + * Convert integer to string, starting at end of + * buffer and working backwards. + */ + str = buf + buf_len - 1; + *(str) = '\0'; + + /* + * Fixed-point precision must fit in our buffer. + * Leave space for "0." and the terminating null. + */ + if (precision > buf_len - 3) { + precision = buf_len - 3; + if (precision < 0) + return NULL; + } + + /* + * Handle digits to right of decimal for fixed point numbers. + */ + for (i = 0; i < precision; i++) + *(--str) = '0' + uint64divmod(&val, 10); + if (precision >= 0) + *(--str) = '.'; + + if (!val) + *(--str) = '0'; + + while (val) { + int digit; + + if (str <= buf) + return NULL; + + digit = uint64divmod(&val, base); + if (digit < 10) + *(--str) = '0' + digit; + else if (uppercase) + *(--str) = 'A' + digit - 10; + else + *(--str) = 'a' + digit - 10; + } + + return str; +} + +int snprintf_timestamp_now(char *str, size_t size) +{ + return snprintf_timestamp(str, size, get_time().val); +} + +int snprintf_timestamp(char *str, size_t size, uint64_t timestamp) +{ + int len; + int precision; + char *tmp_str; + char tmp_buf[PRINTF_TIMESTAMP_BUF_SIZE]; + int base = 10; -/* Deactivate the PF_64BIT flag is 64-bit support is disabled. */ -#ifdef NO_UINT64_SUPPORT -#define PF_64BIT 0 -#else -#define PF_64BIT BIT(3) /* Number is 64-bit */ -#endif + if (size == 0) + return -EC_ERROR_INVAL; + + /* Ensure string has terminating '\0' in error cases. */ + str[0] = '\0'; + + if (IS_ENABLED(CONFIG_CONSOLE_VERBOSE)) { + precision = 6; + } else { + precision = 3; + timestamp /= 1000; + } + + tmp_str = uint64_to_str(tmp_buf, sizeof(tmp_buf), timestamp, precision, + base, false); + if (!tmp_str) + return -EC_ERROR_OVERFLOW; + + len = strlen(tmp_str); + if (len + 1 > size) + return -EC_ERROR_OVERFLOW; + + memcpy(str, tmp_str, len + 1); + + return len; +} /* * Print the buffer as a string of bytes in hex. * Returns 0 on success or an error on failure. */ -static int print_hex_buffer(int (*addchar)(void *context, int c), - void *context, const char *vstr, int precision, - int pad_width, int flags) +static int print_hex_buffer(int (*addchar)(void *context, int c), void *context, + const char *vstr, int precision, int pad_width, + int flags) { - /* * Divide pad_width instead of multiplying precision to avoid overflow * error in the condition. The "/2" and "2*" can be optimized by @@ -100,6 +175,54 @@ static int print_hex_buffer(int (*addchar)(void *context, int c), return EC_SUCCESS; } +struct hex_char_context { + struct hex_buffer_params hex_buf_params; + char *str; + size_t size; +}; + +int add_hex_char(void *context, int c) +{ + struct hex_char_context *ctx = context; + + if (ctx->size == 0) + return EC_ERROR_OVERFLOW; + + *(ctx->str++) = c; + ctx->size--; + + return EC_SUCCESS; +} + +size_t hex_str_buf_size(size_t num_bytes) +{ + return 2 * num_bytes + 1; +} + +int snprintf_hex_buffer(char *str, size_t size, + const struct hex_buffer_params *params) +{ + int rv; + struct hex_char_context context = { + .hex_buf_params = *params, + .str = str, + /* + * Reserve space for terminating '\0'. + */ + .size = size - 1, + }; + + if (size == 0) + return -EC_ERROR_INVAL; + + rv = print_hex_buffer(add_hex_char, &context, params->buffer, + params->size, 0, 0); + + *context.str = '\0'; + + return (rv == EC_SUCCESS) ? (context.str - str) : -rv; +} + int vfnprintf(int (*addchar)(void *context, int c), void *context, const char *format, va_list args) { @@ -215,17 +338,15 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context, } else { int base = 10; -#ifdef NO_UINT64_SUPPORT - uint32_t v; -#else uint64_t v; -#endif - int ptrspec; + void *ptrval; /* * Handle length: - * %l - DEPRECATED (see below) + * %l - supports 64-bit longs, 32-bit longs are + * supported with a config flag, see comment + * below for more details * %ll - long long * %z - size_t */ @@ -240,18 +361,23 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context, } /* - * %l on 32-bit systems is deliberately - * deprecated. It was originally used as - * shorthand for 64-bit values. When + * The CONFIG_PRINTF_LONG_IS_32BITS flag is + * required to enable the %l flag on systems + * where it would signify a 32-bit value. + * Otherwise, %l on 32-bit systems is + * deliberately deprecated. %l was originally + * used as shorthand for 64-bit values. When * compile-time printf format checking was * enabled, it had to be cleaned up to be * sizeof(long), which is 32 bits on today's * ECs. This presents a mismatch which can be * dangerous if a new-style printf call is * cherry-picked into an old firmware branch. - * See crbug.com/984041 for more context. + * For more context, see + * https://issuetracker.google.com/issues/172210614 */ - if (!(flags & PF_64BIT)) { + if (!IS_ENABLED(CONFIG_PRINTF_LONG_IS_32BITS) && + !(flags & PF_64BIT)) { format = error_str; continue; } @@ -264,72 +390,11 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context, if (c == 'p') { c = -1; - ptrspec = *format++; ptrval = va_arg(args, void *); - /* - * Avoid null pointer dereference for %ph and - * %pb. %pT and %pP can accept null. - */ - if (ptrval == NULL - && ptrspec != 'T' && ptrspec != 'P') - continue; - /* %pT - print a timestamp. */ - if (ptrspec == 'T' && - !IS_ENABLED(NO_UINT64_SUPPORT)) { + v = (unsigned long)ptrval; + base = 16; + if (sizeof(unsigned long) == sizeof(uint64_t)) flags |= PF_64BIT; - if (ptrval == PRINTF_TIMESTAMP_NOW) - v = get_time().val; - else - v = *(uint64_t *)ptrval; - - if (IS_ENABLED( - CONFIG_CONSOLE_VERBOSE)) { - precision = 6; - } else { - precision = 3; - v /= 1000; - } - - } else if (ptrspec == 'h') { - /* %ph - Print a hex byte buffer. */ - struct hex_buffer_params *hexbuf = - ptrval; - int rc; - - rc = print_hex_buffer(addchar, - context, - hexbuf->buffer, - hexbuf->size, - 0, - 0); - - if (rc != EC_SUCCESS) - return rc; - - continue; - - } else if (ptrspec == 'P') { - /* %pP - Print a raw pointer. */ - v = (unsigned long)ptrval; - base = 16; - if (sizeof(unsigned long) == - sizeof(uint64_t)) - flags |= PF_64BIT; - - } else if (ptrspec == 'b') { - /* %pb - Print a binary integer */ - struct binary_print_params *binary = - ptrval; - - v = binary->value; - pad_width = binary->count; - flags |= PF_PADZERO; - base = 2; - - } else { - return EC_ERROR_INVAL; - } - } else if (flags & PF_64BIT) { v = va_arg(args, uint64_t); } else { @@ -337,12 +402,9 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context, } switch (c) { -#ifdef CONFIG_PRINTF_LEGACY_LI_FORMAT +#ifdef CONFIG_PRINTF_LONG_IS_32BITS case 'i': - /* force 32-bit for compatibility */ - flags &= ~PF_64BIT; - /* fall-through */ -#endif /* CONFIG_PRINTF_LEGACY_LI_FORMAT */ +#endif /* CONFIG_PRINTF_LONG_IS_32BITS */ case 'd': if (flags & PF_64BIT) { if ((int64_t)v < 0) { @@ -379,41 +441,9 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context, if (format == error_str) continue; /* Bad format specifier */ - /* - * Convert integer to string, starting at end of - * buffer and working backwards. - */ - vstr = intbuf + sizeof(intbuf) - 1; - *(vstr) = '\0'; - - /* - * Fixed-point precision must fit in our buffer. - * Leave space for "0." and the terminating null. - */ - if (precision > (int)(sizeof(intbuf) - 3)) - precision = sizeof(intbuf) - 3; - - /* - * Handle digits to right of decimal for fixed point - * numbers. - */ - for (vlen = 0; vlen < precision; vlen++) - *(--vstr) = '0' + divmod(&v, 10); - if (precision >= 0) - *(--vstr) = '.'; - - if (!v) - *(--vstr) = '0'; - - while (v) { - int digit = divmod(&v, base); - if (digit < 10) - *(--vstr) = '0' + digit; - else if (c == 'X') - *(--vstr) = 'A' + digit - 10; - else - *(--vstr) = 'a' + digit - 10; - } + vstr = uint64_to_str(intbuf, sizeof(intbuf), v, + precision, base, c == 'X'); + ASSERT(vstr); if (sign) *(--vstr) = sign; @@ -441,7 +471,6 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context, vlen = strnlen(vstr, precision); } - while (vlen < pad_width && !(flags & PF_LEFT)) { if (addchar(context, flags & PF_PADZERO ? '0' : ' ')) return EC_ERROR_OVERFLOW; @@ -460,59 +489,3 @@ int vfnprintf(int (*addchar)(void *context, int c), void *context, /* If we're still here, we consumed all output */ return EC_SUCCESS; } - -/* Context for snprintf() */ -struct snprintf_context { - char *str; - int size; -}; - -/** - * Add a character to the string context. - * - * @param context Context receiving character - * @param c Character to add - * @return 0 if character added, 1 if character dropped because no space. - */ -static int snprintf_addchar(void *context, int c) -{ - struct snprintf_context *ctx = (struct snprintf_context *)context; - - if (!ctx->size) - return 1; - - *(ctx->str++) = c; - ctx->size--; - return 0; -} - -int snprintf(char *str, int size, const char *format, ...) -{ - va_list args; - int rv; - - va_start(args, format); - rv = vsnprintf(str, size, format, args); - va_end(args); - - return rv; -} - -int vsnprintf(char *str, int size, const char *format, va_list args) -{ - struct snprintf_context ctx; - int rv; - - if (!str || !format || size <= 0) - return -EC_ERROR_INVAL; - - ctx.str = str; - ctx.size = size - 1; /* Reserve space for terminating '\0' */ - - rv = vfnprintf(snprintf_addchar, &ctx, format, args); - - /* Terminate string */ - *ctx.str = '\0'; - - return (rv == EC_SUCCESS) ? (ctx.str - str) : -rv; -} diff --git a/common/pstore_commands.c b/common/pstore_commands.c index 52270cd1cf..89c996379c 100644 --- a/common/pstore_commands.c +++ b/common/pstore_commands.c @@ -1,16 +1,18 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Persistent storage commands for Chrome EC */ +#include "builtin/assert.h" #include "common.h" #include "eeprom.h" #include "host_command.h" #include "util.h" -enum ec_status pstore_command_get_info(struct host_cmd_handler_args *args) +static enum ec_status +pstore_command_get_info(struct host_cmd_handler_args *args) { struct ec_response_pstore_info *r = args->response; @@ -22,11 +24,10 @@ enum ec_status pstore_command_get_info(struct host_cmd_handler_args *args) args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PSTORE_INFO, - pstore_command_get_info, +DECLARE_HOST_COMMAND(EC_CMD_PSTORE_INFO, pstore_command_get_info, EC_VER_MASK(0)); -enum ec_status pstore_command_read(struct host_cmd_handler_args *args) +static enum ec_status pstore_command_read(struct host_cmd_handler_args *args) { const struct ec_params_pstore_read *p = args->params; char *dest = args->response; @@ -59,11 +60,9 @@ enum ec_status pstore_command_read(struct host_cmd_handler_args *args) args->response_size = p->size; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PSTORE_READ, - pstore_command_read, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_PSTORE_READ, pstore_command_read, EC_VER_MASK(0)); -enum ec_status pstore_command_write(struct host_cmd_handler_args *args) +static enum ec_status pstore_command_write(struct host_cmd_handler_args *args) { const struct ec_params_pstore_write *p = args->params; @@ -96,6 +95,4 @@ enum ec_status pstore_command_write(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PSTORE_WRITE, - pstore_command_write, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_PSTORE_WRITE, pstore_command_write, EC_VER_MASK(0)); diff --git a/common/pwm.c b/common/pwm.c index 73b12fc20c..e630ddd58e 100644 --- a/common/pwm.c +++ b/common/pwm.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -45,13 +45,13 @@ __attribute__((weak)) void pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty) int percent; /* Convert 16 bit duty to percent on [0, 100] */ - percent = DIV_ROUND_NEAREST((uint32_t)duty * 100, 65535); + percent = PWM_RAW_TO_PERCENT(duty); pwm_set_duty(ch, percent); } __attribute__((weak)) uint16_t pwm_get_raw_duty(enum pwm_channel ch) { - return (pwm_get_duty(ch) * 65535) / 100; + return PWM_PERCENT_TO_RAW(pwm_get_duty(ch)); } static enum ec_status @@ -62,14 +62,12 @@ host_command_pwm_set_duty(struct host_cmd_handler_args *args) if (get_target_channel(&channel, p->pwm_type, p->index)) return EC_RES_INVALID_PARAM; - pwm_set_raw_duty(channel, p->duty); pwm_enable(channel, p->duty > 0); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_DUTY, - host_command_pwm_set_duty, +DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_DUTY, host_command_pwm_set_duty, EC_VER_MASK(0)); static enum ec_status @@ -84,12 +82,12 @@ host_command_pwm_get_duty(struct host_cmd_handler_args *args) return EC_RES_INVALID_PARAM; r->duty = pwm_get_raw_duty(channel); + args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_DUTY, - host_command_pwm_get_duty, +DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_DUTY, host_command_pwm_get_duty, EC_VER_MASK(0)); /** @@ -108,13 +106,13 @@ static void print_channel(enum pwm_channel ch, int max_duty) ccprintf(" %d: disabled\n", ch); } -static int cc_pwm_duty(int argc, char **argv) +static int cc_pwm_duty(int argc, const char **argv) { int value = 0; int max_duty = 100; int ch; char *e; - char *raw; + const char *raw; if (argc < 2) { ccprintf("PWM channels:\n"); @@ -149,7 +147,7 @@ static int cc_pwm_duty(int argc, char **argv) ccprintf("Setting channel %d to %d\n", ch, value); pwm_enable(ch, 1); (max_duty == 100) ? pwm_set_duty(ch, value) : - pwm_set_raw_duty(ch, value); + pwm_set_raw_duty(ch, value); } } @@ -162,7 +160,10 @@ DECLARE_CONSOLE_COMMAND(pwmduty, cc_pwm_duty, "Get/set PWM duty cycles "); #endif /* CONFIG_PWM */ -/* Initialize all PWM pins as functional */ +/* + * Initialize all PWM pins as functional. This is not required under + * Zephyr as pin configuration is automatically performed by chip driver + */ static void pwm_pin_init(void) { gpio_config_module(MODULE_PWM, 1); diff --git a/common/pwm_kblight.c b/common/pwm_kblight.c index 4967d36df5..bd7e07644d 100644 --- a/common/pwm_kblight.c +++ b/common/pwm_kblight.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,11 +19,6 @@ static int kblight_pwm_set(int percent) return EC_SUCCESS; } -static int kblight_pwm_get(void) -{ - return pwm_get_duty(kblight_pwm_ch); -} - static int kblight_pwm_init(void) { /* dnojiri: Why do we need save/restore setting over sysjump? */ @@ -38,9 +33,14 @@ static int kblight_pwm_enable(int enable) return EC_SUCCESS; } +static int kblight_pwm_get_enabled(void) +{ + return pwm_get_enabled(kblight_pwm_ch); +} + const struct kblight_drv kblight_pwm = { .init = kblight_pwm_init, .set = kblight_pwm_set, - .get = kblight_pwm_get, .enable = kblight_pwm_enable, + .get_enabled = kblight_pwm_get_enabled, }; diff --git a/common/queue.c b/common/queue.c index 7b083233ad..ebe9d8b63d 100644 --- a/common/queue.c +++ b/common/queue.c @@ -1,21 +1,23 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Queue data structure implementation. */ + +#include "builtin/assert.h" #include "console.h" #include "queue.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args) static void queue_action_null(struct queue_policy const *policy, size_t count) { } struct queue_policy const queue_policy_null = { - .add = queue_action_null, + .add = queue_action_null, .remove = queue_action_null, }; @@ -74,17 +76,17 @@ struct queue_chunk queue_get_write_chunk(struct queue const *q, size_t offset) { size_t head = q->state->head & q->buffer_units_mask; size_t tail = (q->state->tail + offset) & q->buffer_units_mask; - size_t last = (tail < head) ? head : /* Wrapped */ - q->buffer_units; /* Normal | Empty */ + size_t last = (tail < head) ? head : /* Wrapped */ + q->buffer_units; /* Normal | Empty */ /* Make sure that the offset doesn't exceed free space. */ if (queue_space(q) <= offset) - return ((struct queue_chunk) { + return ((struct queue_chunk){ .count = 0, .buffer = NULL, }); - return ((struct queue_chunk) { + return ((struct queue_chunk){ .count = last - tail, .buffer = q->buffer + (tail * q->unit_bytes), }); @@ -95,10 +97,10 @@ struct queue_chunk queue_get_read_chunk(struct queue const *q) size_t head = q->state->head & q->buffer_units_mask; size_t tail = q->state->tail & q->buffer_units_mask; size_t last = (queue_is_empty(q) ? head : /* Empty */ - ((head < tail) ? tail : /* Normal */ - q->buffer_units)); /* Wrapped | Full */ + ((head < tail) ? tail : /* Normal */ + q->buffer_units)); /* Wrapped | Full */ - return ((struct queue_chunk) { + return ((struct queue_chunk){ .count = (last - head), .buffer = q->buffer + (head * q->unit_bytes), }); @@ -134,7 +136,7 @@ size_t queue_add_unit(struct queue const *q, const void *src) return 0; if (q->unit_bytes == 1) - q->buffer[tail] = *((uint8_t *) src); + q->buffer[tail] = *((uint8_t *)src); else memcpy(q->buffer + tail * q->unit_bytes, src, q->unit_bytes); @@ -146,46 +148,33 @@ size_t queue_add_units(struct queue const *q, const void *src, size_t count) return queue_add_memcpy(q, src, count, memcpy); } -size_t queue_add_memcpy(struct queue const *q, - const void *src, - size_t count, - void *(*memcpy)(void *dest, - const void *src, - size_t n)) +size_t queue_add_memcpy(struct queue const *q, const void *src, size_t count, + void *(*memcpy)(void *dest, const void *src, size_t n)) { size_t transfer = MIN(count, queue_space(q)); - size_t tail = q->state->tail & q->buffer_units_mask; - size_t first = MIN(transfer, q->buffer_units - tail); + size_t tail = q->state->tail & q->buffer_units_mask; + size_t first = MIN(transfer, q->buffer_units - tail); - memcpy(q->buffer + tail * q->unit_bytes, - src, - first * q->unit_bytes); + memcpy(q->buffer + tail * q->unit_bytes, src, first * q->unit_bytes); if (first < transfer) memcpy(q->buffer, - ((uint8_t const *) src) + first * q->unit_bytes, + ((uint8_t const *)src) + first * q->unit_bytes, (transfer - first) * q->unit_bytes); return queue_advance_tail(q, transfer); } -static void queue_read_safe(struct queue const *q, - void *dest, - size_t head, - size_t transfer, - void *(*memcpy)(void *dest, - const void *src, - size_t n)) +static void +queue_read_safe(struct queue const *q, void *dest, size_t head, size_t transfer, + void *(*memcpy)(void *dest, const void *src, size_t n)) { size_t first = MIN(transfer, q->buffer_units - head); - memcpy(dest, - q->buffer + head * q->unit_bytes, - first * q->unit_bytes); + memcpy(dest, q->buffer + head * q->unit_bytes, first * q->unit_bytes); if (first < transfer) - memcpy(((uint8_t *) dest) + first * q->unit_bytes, - q->buffer, + memcpy(((uint8_t *)dest) + first * q->unit_bytes, q->buffer, (transfer - first) * q->unit_bytes); } @@ -197,7 +186,7 @@ size_t queue_remove_unit(struct queue const *q, void *dest) return 0; if (q->unit_bytes == 1) - *((uint8_t *) dest) = q->buffer[head]; + *((uint8_t *)dest) = q->buffer[head]; else memcpy(dest, q->buffer + head * q->unit_bytes, q->unit_bytes); @@ -209,39 +198,30 @@ size_t queue_remove_units(struct queue const *q, void *dest, size_t count) return queue_remove_memcpy(q, dest, count, memcpy); } -size_t queue_remove_memcpy(struct queue const *q, - void *dest, - size_t count, - void *(*memcpy)(void *dest, - const void *src, +size_t queue_remove_memcpy(struct queue const *q, void *dest, size_t count, + void *(*memcpy)(void *dest, const void *src, size_t n)) { size_t transfer = MIN(count, queue_count(q)); - size_t head = q->state->head & q->buffer_units_mask; + size_t head = q->state->head & q->buffer_units_mask; queue_read_safe(q, dest, head, transfer, memcpy); return queue_advance_head(q, transfer); } -size_t queue_peek_units(struct queue const *q, - void *dest, - size_t i, +size_t queue_peek_units(struct queue const *q, void *dest, size_t i, size_t count) { return queue_peek_memcpy(q, dest, i, count, memcpy); } -size_t queue_peek_memcpy(struct queue const *q, - void *dest, - size_t i, +size_t queue_peek_memcpy(struct queue const *q, void *dest, size_t i, size_t count, - void *(*memcpy)(void *dest, - const void *src, - size_t n)) + void *(*memcpy)(void *dest, const void *src, size_t n)) { size_t available = queue_count(q); - size_t transfer = MIN(count, available - i); + size_t transfer = MIN(count, available - i); if (i < available) { size_t head = (q->state->head + i) & q->buffer_units_mask; @@ -258,7 +238,7 @@ void queue_begin(struct queue const *q, struct queue_iterator *it) it->ptr = NULL; else it->ptr = q->buffer + (q->state->head & q->buffer_units_mask) * - q->unit_bytes; + q->unit_bytes; it->_state.offset = 0; it->_state.head = q->state->head; it->_state.tail = q->state->tail; diff --git a/common/queue_policies.c b/common/queue_policies.c index 090c837fae..6646d49cf4 100644 --- a/common/queue_policies.c +++ b/common/queue_policies.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -29,14 +29,14 @@ void queue_remove_direct(struct queue_policy const *policy, size_t count) struct producer const null_producer = { .queue = NULL, - .ops = &((struct producer_ops const) { - .read = NULL, + .ops = &((struct producer_ops const){ + .read = NULL, }), }; struct consumer const null_consumer = { .queue = NULL, - .ops = &((struct consumer_ops const) { + .ops = &((struct consumer_ops const){ .written = NULL, }), }; diff --git a/common/regulator.c b/common/regulator.c index c3f5d0b99d..5b8da2adc8 100644 --- a/common/regulator.c +++ b/common/regulator.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,27 +11,28 @@ #include "host_command.h" #include "regulator.h" -static enum ec_status -hc_regulator_get_info(struct host_cmd_handler_args *args) +static enum ec_status hc_regulator_get_info(struct host_cmd_handler_args *args) { const struct ec_params_regulator_get_info *p = args->params; struct ec_response_regulator_get_info *r = args->response; + void *voltages_mv = r->voltages_mv; + uint16_t num_voltages; int rv; - rv = board_regulator_get_info(p->index, r->name, &r->num_voltages, - r->voltages_mv); + rv = board_regulator_get_info(p->index, r->name, &num_voltages, + voltages_mv); if (rv) return EC_RES_ERROR; + r->num_voltages = num_voltages; args->response_size = sizeof(*r); return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_REGULATOR_GET_INFO, hc_regulator_get_info, EC_VER_MASK(0)); -static enum ec_status -hc_regulator_enable(struct host_cmd_handler_args *args) +static enum ec_status hc_regulator_enable(struct host_cmd_handler_args *args) { const struct ec_params_regulator_enable *p = args->params; int rv; @@ -69,13 +70,15 @@ hc_regulator_get_voltage(struct host_cmd_handler_args *args) { const struct ec_params_regulator_get_voltage *p = args->params; struct ec_response_regulator_get_voltage *r = args->response; + uint32_t voltage_mv; int rv; - rv = board_regulator_get_voltage(p->index, &r->voltage_mv); + rv = board_regulator_get_voltage(p->index, &voltage_mv); if (rv) return EC_RES_ERROR; + r->voltage_mv = voltage_mv; args->response_size = sizeof(*r); return EC_RES_SUCCESS; } diff --git a/common/rgb_keyboard.c b/common/rgb_keyboard.c new file mode 100644 index 0000000000..0036cdcd16 --- /dev/null +++ b/common/rgb_keyboard.c @@ -0,0 +1,687 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "atomic.h" +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "keyboard_backlight.h" +#include "registers.h" +#include "rgb_keyboard.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#include + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_RGBKBD, outstr) +#define CPRINTF(fmt, args...) cprintf(CC_RGBKBD, "RGBKBD: " fmt, ##args) +#define CPRINTS(fmt, args...) cprints(CC_RGBKBD, "RGBKBD: " fmt, ##args) + +test_export_static enum ec_rgbkbd_demo demo = +#if defined(CONFIG_RGBKBD_DEMO_FLOW) + EC_RGBKBD_DEMO_FLOW; +#elif defined(CONFIG_RGBKBD_DEMO_DOT) + EC_RGBKBD_DEMO_DOT; +#else + EC_RGBKBD_DEMO_OFF; +#endif + +const int default_demo_interval_ms = 250; +test_export_static int demo_interval_ms = -1; + +test_export_static uint8_t rgbkbd_table[EC_RGBKBD_MAX_KEY_COUNT]; + +static enum rgbkbd_state rgbkbd_state; + +const struct rgbkbd_init rgbkbd_init_default = { + .gcc = RGBKBD_MAX_GCC_LEVEL / 2, + .scale = { RGBKBD_MAX_SCALE, RGBKBD_MAX_SCALE, RGBKBD_MAX_SCALE }, + .color = { .r = 0x0, .g = 0x0, .b = 0x0 }, +}; + +const struct rgbkbd_init *rgbkbd_init_setting = &rgbkbd_init_default; + +void rgbkbd_register_init_setting(const struct rgbkbd_init *setting) +{ + rgbkbd_init_setting = setting; +} + +/* Search the grid where x belongs to. */ +static struct rgbkbd *find_grid_from_x(int x, uint8_t *col) +{ + struct rgbkbd *ctx = NULL; + uint8_t grid; + + *col = 0; + for (grid = 0; grid < rgbkbd_count; grid++) { + ctx = &rgbkbds[grid]; + if (x < *col + ctx->cfg->col_len) + break; + *col += ctx->cfg->col_len; + } + + return ctx; +} + +static int set_color_single(struct rgb_s color, int x, int y) +{ + struct rgbkbd *ctx = &rgbkbds[0]; + uint8_t grid, col, offset; + int rv; + + if (rgbkbd_hsize <= x || rgbkbd_vsize <= y) { + return EC_ERROR_OVERFLOW; + } + + ctx = find_grid_from_x(x, &col); + grid = RGBKBD_CTX_TO_GRID(ctx); + offset = ctx->cfg->row_len * (x - col) + y; + ctx->buf[offset] = color; + + rv = ctx->cfg->drv->set_color(ctx, offset, &ctx->buf[offset], 1); + + CPRINTS("%set (%d,%d) to color=(%d,%d,%d) grid=%u offset=%u (%d)", + rv ? "Failed to s" : "S", x, y, color.r, color.g, color.b, grid, + offset, rv); + + return rv; +} + +test_export_static uint8_t get_grid_size(const struct rgbkbd *ctx) +{ + return ctx->cfg->col_len * ctx->cfg->row_len; +} + +static void sync_grids(void) +{ + struct rgbkbd *ctx; + uint8_t len; + int i; + + for (i = 0; i < rgbkbd_count; i++) { + ctx = &rgbkbds[i]; + len = get_grid_size(ctx); + ctx->cfg->drv->set_color(ctx, 0, ctx->buf, len); + } +} + +test_export_static struct rgb_s rotate_color(struct rgb_s color, int step) +{ + color.r += step; + if (color.r == 0) { + color.g += step; + if (color.g == 0) { + color.b += step; + } + } + + return color; +} + +static void rgbkbd_reset_color(struct rgb_s color) +{ + struct rgbkbd *ctx; + int i, j; + + for (i = 0; i < rgbkbd_count; i++) { + ctx = &rgbkbds[i]; + for (j = 0; j < get_grid_size(ctx); j++) + ctx->buf[j] = color; + } + + sync_grids(); +} + +static void rgbkbd_demo_flow(void) +{ + struct rgbkbd *ctx = &rgbkbds[0]; + static struct rgb_s color; + uint8_t len; + int i, g; + + for (g = rgbkbd_count - 1; g >= 0; g--) { + ctx = &rgbkbds[g]; + len = get_grid_size(ctx); + for (i = len - 1; i > 0; i--) + ctx->buf[i] = ctx->buf[i - 1]; + if (g > 0) { + /* Copy the last dot of the g-1 grid to the 1st. */ + len = get_grid_size(&rgbkbds[g - 1]); + ctx->buf[0] = rgbkbds[g - 1].buf[len - 1]; + } + } + + /* Create a new color by shifting R by . */ + color = rotate_color(color, 32); + + /* Finally, insert a new color to (0, 0). */ + ctx->buf[0] = color; + + sync_grids(); + +#ifdef TEST_BUILD + task_wake(TASK_ID_TEST_RUNNER); +#endif +} + +static void rgbkbd_demo_dot(void) +{ + static struct rgb_s color = { 0x80, 0, 0 }; + const struct rgb_s off = { 0, 0, 0 }; + static uint8_t x, y; + + /* Turn off previous dot. */ + set_color_single(off, x, y); + + /* Move position. */ + y++; + if (y >= rgbkbd_vsize) { + y = 0; + x++; + if (x >= rgbkbd_hsize) { + x = 0; + color = rotate_color(color, 0x80); + } + } + + /* Turn on next dot. */ + set_color_single(color, x, y); + +#ifdef TEST_BUILD + task_wake(TASK_ID_TEST_RUNNER); +#endif +} + +static void rgbkbd_demo_run(enum ec_rgbkbd_demo id) +{ + switch (id) { + case EC_RGBKBD_DEMO_FLOW: + rgbkbd_demo_flow(); + break; + case EC_RGBKBD_DEMO_DOT: + rgbkbd_demo_dot(); + break; + case EC_RGBKBD_DEMO_OFF: + default: + break; + } +} + +test_export_static void rgbkbd_init_lookup_table(void) +{ + bool add = true; + int i, k = 0; + + if (rgbkbd_map[0] != RGBKBD_DELM || + rgbkbd_map[rgbkbd_map_size - 1] != RGBKBD_DELM) { + CPRINTS("Invalid Key-LED map"); + return; + } + + /* + * rgbkbd_map[] consists of LED IDs separated by a delimiter (0xff). + * When 'add' is true, the next byte will be the beginning of a new LED + * group, thus, its index will be added to rgbkbd_table. If the next + * byte is a back-to-back 0xff, it's an empty group and still added to + * rgbkbd_table. + */ + for (i = 0; i < rgbkbd_map_size && k < EC_RGBKBD_MAX_KEY_COUNT; i++) { + if (rgbkbd_map[i] != RGBKBD_DELM) { + if (add) + rgbkbd_table[k++] = i; + /* Don't add next LED ID or TERM. */ + add = false; + continue; + } + if (add) + rgbkbd_table[k++] = i; + add = true; + } + + /* A valid map should have exactly as many entries as MAX_KEY_ID. */ + if (k < EC_RGBKBD_MAX_KEY_COUNT) + CPRINTS("Key-LED map is too short (found %d)", k); + + /* + * Whether k is equal to or shorter than EC_RGBKBD_MAX_KEY_COUNT, the + * LED group pointed by rgbkbd_table[k-1] is guaranteed to be properly + * terminated. The rest of the table entries remain non-existent (0). + */ +} + +static int rgbkbd_set_global_brightness(uint8_t gcc) +{ + int e, grid; + int rv = EC_SUCCESS; + + for (grid = 0; grid < rgbkbd_count; grid++) { + struct rgbkbd *ctx = &rgbkbds[grid]; + + e = ctx->cfg->drv->set_gcc(ctx, gcc); + if (e) { + CPRINTS("Failed to set GCC to %u for grid=%d (%d)", gcc, + grid, e); + rv = e; + continue; + } + } + + CPRINTS("Set GCC to %u", gcc); + + /* Return EC_SUCCESS or the last error. */ + return rv; +} + +static int rgbkbd_reset_scale(struct rgb_s scale) +{ + int e, i, rv = EC_SUCCESS; + + for (i = 0; i < rgbkbd_count; i++) { + struct rgbkbd *ctx = &rgbkbds[i]; + + e = ctx->cfg->drv->set_scale(ctx, 0, scale, get_grid_size(ctx)); + if (e) { + CPRINTS("Failed to set scale to [%d,%d,%d] Grid%d (%d)", + scale.r, scale.g, scale.b, i, e); + rv = e; + } + } + + return rv; +} + +static int rgbkbd_set_scale(struct rgb_s scale, uint8_t key) +{ + struct rgbkbd *ctx; + uint8_t j, col, grid, offset; + union rgbkbd_coord_u8 led; + int rv = EC_SUCCESS; + + j = rgbkbd_table[key]; + if (j == RGBKBD_NONE) + return rv; + + do { + led.u8 = rgbkbd_map[j++]; + if (led.u8 == RGBKBD_DELM) + /* Reached end of the group. */ + break; + ctx = find_grid_from_x(led.coord.x, &col); + grid = RGBKBD_CTX_TO_GRID(ctx); + /* + * offset is the relative position in our buffer where LED + * colors are cached. RGB is grouped as one. Note this differs + * from the external buffer (LED drivers' buffer) where RGB is + * individually counted. + * + * offset can be calculated by multiplying the horizontal + * position (x) by the size of the rows, then, adding the + * vertical position (y). + */ + offset = ctx->cfg->row_len * (led.coord.x - col) + led.coord.y; + rv = ctx->cfg->drv->set_scale(ctx, offset, scale, 1); + if (rv) { + CPRINTS("Failed to set scale to [%d,%d,%d] Grid%d (%d)", + scale.r, scale.g, scale.b, grid, rv); + return rv; + } + } while (led.u8 != RGBKBD_DELM); + + return rv; +} + +static int rgbkbd_init(void) +{ + int rv = EC_SUCCESS; + int e, i; + + for (i = 0; i < rgbkbd_count; i++) { + struct rgbkbd *ctx = &rgbkbds[i]; + uint8_t gcc = rgbkbd_init_setting->gcc; + + e = ctx->cfg->drv->init(ctx); + if (e) { + CPRINTS("Failed to init GRID%d (%d)", i, e); + rv = e; + continue; + } + + e = ctx->cfg->drv->set_gcc(ctx, gcc); + if (e) { + CPRINTS("Failed to set GCC to %u for grid=%d (%d)", gcc, + i, e); + rv = e; + continue; + } + + CPRINTS("Initialized GRID%d", i); + } + + rv |= rgbkbd_reset_scale(rgbkbd_init_setting->scale); + rgbkbd_reset_color(rgbkbd_init_setting->color); + + if (rv == EC_SUCCESS) + rgbkbd_state = RGBKBD_STATE_INITIALIZED; + + return rv; +} + +/* This is used to re-init on the first enable. */ +static bool reinitialized; +static int rgbkbd_late_init(void) +{ + if (IS_ENABLED(CONFIG_IS31FL3743B_LATE_INIT)) { + if (!reinitialized) { + int rv; + + CPRINTS("Re-initializing"); + rv = rgbkbd_init(); + if (rv) + return rv; + reinitialized = true; + } + } + return EC_SUCCESS; +} + +static int rgbkbd_enable(int enable) +{ + int rv = EC_SUCCESS; + int e, i; + + if (enable) { + if (rgbkbd_state == RGBKBD_STATE_ENABLED) + return EC_SUCCESS; + rv = rgbkbd_late_init(); + if (rv) + return rv; + } else { + if (rgbkbd_state == RGBKBD_STATE_DISABLED) + return EC_SUCCESS; + } + + for (i = 0; i < rgbkbd_count; i++) { + struct rgbkbd *ctx = &rgbkbds[i]; + + e = ctx->cfg->drv->enable(ctx, enable); + if (e) { + CPRINTS("Failed to %s GRID%d (%d)", + enable ? "enable" : "disable", i, e); + rv = e; + continue; + } + + CPRINTS("%s GRID%d", enable ? "Enabled" : "Disabled", i); + } + + if (rv == EC_SUCCESS) { + rgbkbd_state = enable ? RGBKBD_STATE_ENABLED : + RGBKBD_STATE_DISABLED; + } + + /* Return EC_SUCCESS or the last error. */ + return rv; +} + +static void rgbkbd_demo_set(enum ec_rgbkbd_demo new_demo) +{ + CPRINTS("Setting demo %d with %d ms interval", demo, demo_interval_ms); + + demo = new_demo; + + /* suspend demo task */ + demo_interval_ms = -1; + rgbkbd_init(); + rgbkbd_enable(1); + + if (demo == EC_RGBKBD_DEMO_OFF) + return; + + demo_interval_ms = default_demo_interval_ms; + + /* start demo */ + task_wake(TASK_ID_RGBKBD); +} + +static int rgbkbd_kblight_set(int percent) +{ + uint8_t gcc = DIV_ROUND_NEAREST(percent * RGBKBD_MAX_GCC_LEVEL, 100); + int rv = rgbkbd_late_init(); + + if (rv) + return rv; + + return rgbkbd_set_global_brightness(gcc); +} + +static int rgbkbd_get_enabled(void) +{ + return rgbkbd_state >= RGBKBD_STATE_ENABLED; +} + +static void rgbkbd_reset(void) +{ + board_kblight_shutdown(); + board_kblight_init(); + rgbkbd_state = RGBKBD_STATE_RESET; + reinitialized = false; +} + +const struct kblight_drv kblight_rgbkbd = { + .init = rgbkbd_init, + .set = rgbkbd_kblight_set, + .enable = rgbkbd_enable, + .get_enabled = rgbkbd_get_enabled, +}; + +void rgbkbd_task(void *u) +{ + rgbkbd_init_lookup_table(); + + while (1) { + task_wait_event(demo_interval_ms * MSEC); + if (demo) + rgbkbd_demo_run(demo); + } +} + +static enum ec_status hc_rgbkbd_set_color(struct host_cmd_handler_args *args) +{ + const struct ec_params_rgbkbd_set_color *p = args->params; + int i; + + if (p->start_key + p->length > EC_RGBKBD_MAX_KEY_COUNT) + return EC_RES_INVALID_PARAM; + + if (rgbkbd_late_init()) + return EC_RES_ERROR; + + for (i = 0; i < p->length; i++) { + uint8_t j = rgbkbd_table[p->start_key + i]; + union rgbkbd_coord_u8 led; + + if (j == RGBKBD_NONE) + /* Null or uninitialized entry */ + continue; + + do { + led.u8 = rgbkbd_map[j++]; + if (led.u8 == RGBKBD_DELM) + /* Reached end of the group. */ + break; + if (set_color_single(p->color[i], led.coord.x, + led.coord.y)) + return EC_RES_ERROR; + } while (led.u8 != RGBKBD_DELM); + } + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_RGBKBD_SET_COLOR, hc_rgbkbd_set_color, + EC_VER_MASK(0)); + +static enum ec_status hc_rgbkbd(struct host_cmd_handler_args *args) +{ + const struct ec_params_rgbkbd *p = args->params; + struct ec_response_rgbkbd *r = args->response; + enum ec_status rv = EC_RES_SUCCESS; + + args->response_size = sizeof(*r); + + if (rgbkbd_late_init()) + return EC_RES_ERROR; + + switch (p->subcmd) { + case EC_RGBKBD_SUBCMD_CLEAR: + rgbkbd_reset_color(p->color); + break; + case EC_RGBKBD_SUBCMD_DEMO: + if (p->demo >= EC_RGBKBD_DEMO_COUNT) + return EC_RES_INVALID_PARAM; + rgbkbd_demo_set(p->demo); + break; + case EC_RGBKBD_SUBCMD_SET_SCALE: + if (rgbkbd_set_scale(p->set_scale.scale, p->set_scale.key)) + rv = EC_RES_ERROR; + break; + case EC_RGBKBD_SUBCMD_GET_CONFIG: + r->rgbkbd_type = rgbkbd_type; + break; + default: + rv = EC_RES_INVALID_PARAM; + break; + } + + return rv; +} +DECLARE_HOST_COMMAND(EC_CMD_RGBKBD, hc_rgbkbd, EC_VER_MASK(0)); + +static int int_to_rgb(const char *code, struct rgb_s *rgb) +{ + int val; + char *end; + + val = strtoi(code, &end, 0); + if (*end || val > EC_RGBKBD_MAX_RGB_COLOR) + return EC_ERROR_INVAL; + + rgb->r = (val >> 16) & 0xff; + rgb->g = (val >> 8) & 0xff; + rgb->b = (val >> 0) & 0xff; + + return EC_SUCCESS; +} + +test_export_static int cc_rgb(int argc, const char **argv) +{ + char *end, *comma; + struct rgb_s rgb, scale; + int gcc, x, y, val; + int i, rv = EC_SUCCESS; + + if (argc < 2 || 5 < argc) { + return EC_ERROR_PARAM_COUNT; + } + + comma = strstr(argv[1], ","); + if (comma && strlen(comma) > 1) { + /* Usage 2 */ + /* Found ',' and more string after that. Split it into two. */ + *comma = '\0'; + x = strtoi(argv[1], &end, 0); + if (*end || x >= rgbkbd_hsize) + return EC_ERROR_PARAM1; + y = strtoi(comma + 1, &end, 0); + if (*end || y >= rgbkbd_vsize) + return EC_ERROR_PARAM1; + + rv = int_to_rgb(argv[2], &rgb); + if (rv) + return EC_ERROR_PARAM2; + + rgbkbd_demo_set(EC_RGBKBD_DEMO_OFF); + + if (y < 0) { + /* Set all LEDs on column x. */ + ccprintf("Set column %d to 0x%02x%02x%02x\n", x, rgb.r, + rgb.g, rgb.b); + for (i = 0; i < rgbkbd_vsize; i++) + rv = set_color_single(rgb, x, i); + } else if (x < 0) { + /* Set all LEDs on row y. */ + ccprintf("Set row %d to 0x%02x%02x%02x\n", y, rgb.r, + rgb.g, rgb.b); + for (i = 0; i < rgbkbd_hsize; i++) + rv = set_color_single(rgb, i, y); + } else { + ccprintf("Set (%d,%d) to 0x%02x%02x%02x\n", x, y, rgb.r, + rgb.g, rgb.b); + rv = set_color_single(rgb, x, y); + } + } else if (!strcasecmp(argv[1], "all")) { + /* Usage 3 */ + rv = int_to_rgb(argv[2], &rgb); + if (rv) + return EC_ERROR_PARAM2; + + rgbkbd_demo_set(EC_RGBKBD_DEMO_OFF); + rgbkbd_reset_color(rgb); + } else if (!strcasecmp(argv[1], "demo")) { + /* Usage 4 */ + val = strtoi(argv[2], &end, 0); + if (*end || val >= EC_RGBKBD_DEMO_COUNT) + return EC_ERROR_PARAM1; + rgbkbd_demo_set(val); + } else if (!strcasecmp(argv[1], "reset")) { + /* Usage 5: Reset */ + rgbkbd_reset(); + rv = rgbkbd_init(); + if (rv) + return rv; + rv = rgbkbd_enable(0); + } else if (!strcasecmp(argv[1], "enable")) { + /* Usage 5: Enable */ + rv = rgbkbd_enable(1); + } else if (!strcasecmp(argv[1], "disable")) { + /* Usage 5: Disable */ + rv = rgbkbd_enable(0); + } else if (!strcasecmp(argv[1], "scale")) { + /* Usage 6 */ + rv = int_to_rgb(argv[2], &scale); + if (rv) + return EC_ERROR_PARAM2; + rv = rgbkbd_reset_scale(scale); + } else if (!strcasecmp(argv[1], "red")) { + rgb.r = 255; + rgb.g = 0; + rgb.b = 0; + rgbkbd_reset_color(rgb); + } else { + /* Usage 1 */ + if (argc != 2) + return EC_ERROR_PARAM_COUNT; + gcc = strtoi(argv[1], &end, 0); + if (*end || gcc < 0 || gcc > UINT8_MAX) + return EC_ERROR_PARAM1; + rv = rgbkbd_set_global_brightness(gcc); + } + + return rv; +} +#ifndef TEST_BUILD +DECLARE_CONSOLE_COMMAND(rgb, cc_rgb, + "\n" + "1. rgb \n" + "2. rgb <24-bit RGB code>\n" + "3. rgb all <24-bit RGB code>\n" + "4. rgb demo \n" + "5. rgb reset/enable/disable/red\n" + "6. rgb scale <24-bit RGB scale>\n", + "Control RGB keyboard"); +#endif diff --git a/common/rollback.c b/common/rollback.c index d4f206b2b6..2ff7b3f40b 100644 --- a/common/rollback.c +++ b/common/rollback.c @@ -1,15 +1,13 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Rollback protection logic. */ +#include "builtin/assert.h" #include "common.h" #include "console.h" -#ifdef CONFIG_LIBCRYPTOC -#include "cryptoc/util.h" -#endif #include "flash.h" #include "hooks.h" #include "host_command.h" @@ -24,8 +22,20 @@ #include "trng.h" #include "util.h" +#ifdef CONFIG_ROLLBACK_SECRET_SIZE +#ifdef CONFIG_BORINGSSL_CRYPTO +#include "openssl/mem.h" +#define secure_clear(buffer, size) OPENSSL_cleanse(buffer, size) +#elif defined(CONFIG_LIBCRYPTOC) +#include "cryptoc/util.h" +#define secure_clear(buffer, size) always_memset(buffer, 0, size) +#else +#error One of CONFIG_BORINGSSL_CRYPTO or CONFIG_LIBCRYPTOC should be defined +#endif +#endif + /* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /* Number of rollback regions */ #define ROLLBACK_REGIONS 2 @@ -34,9 +44,9 @@ static int get_rollback_offset(int region) { #ifdef CONFIG_FLASH_MULTIPLE_REGION int rv; - int rollback_start_bank = flash_bank_index(CONFIG_ROLLBACK_OFF); + int rollback_start_bank = crec_flash_bank_index(CONFIG_ROLLBACK_OFF); - rv = flash_bank_start_offset(rollback_start_bank + region); + rv = crec_flash_bank_start_offset(rollback_start_bank + region); ASSERT(rv >= 0); return rv; #else @@ -44,49 +54,35 @@ static int get_rollback_offset(int region) #endif } -#ifdef SECTION_IS_RO -static int get_rollback_erase_size_bytes(int region) -{ - int erase_size; - -#ifndef CONFIG_FLASH_MULTIPLE_REGION - erase_size = CONFIG_FLASH_ERASE_SIZE; -#else - int rollback_start_bank = flash_bank_index(CONFIG_ROLLBACK_OFF); - - erase_size = flash_bank_erase_size(rollback_start_bank + region); -#endif - ASSERT(erase_size > 0); - ASSERT(ROLLBACK_REGIONS * erase_size <= CONFIG_ROLLBACK_SIZE); - ASSERT(sizeof(struct rollback_data) <= erase_size); - return erase_size; -} -#endif - /* * When MPU is available, read rollback with interrupts disabled, to minimize * time protection is left open. */ -static void lock_rollback(void) +static void lock_rollback(uint32_t key) { #ifdef CONFIG_ROLLBACK_MPU_PROTECT mpu_lock_rollback(1); - interrupt_enable(); + irq_unlock(key); #endif } -static void unlock_rollback(void) +static uint32_t unlock_rollback(void) { #ifdef CONFIG_ROLLBACK_MPU_PROTECT - interrupt_disable(); + uint32_t key; + + key = irq_lock(); mpu_lock_rollback(0); + return key; +#else + return 0; #endif } static void clear_rollback(struct rollback_data *data) { #ifdef CONFIG_ROLLBACK_SECRET_SIZE - always_memset(data->secret, 0, sizeof(data->secret)); + secure_clear(data->secret, sizeof(data->secret)); #endif } @@ -94,13 +90,14 @@ int read_rollback(int region, struct rollback_data *data) { int offset; int ret = EC_SUCCESS; + uint32_t key; offset = get_rollback_offset(region); - unlock_rollback(); - if (flash_read(offset, sizeof(*data), (char *)data)) + key = unlock_rollback(); + if (crec_flash_read(offset, sizeof(*data), (char *)data)) ret = EC_ERROR_UNKNOWN; - lock_rollback(); + lock_rollback(key); return ret; } @@ -114,7 +111,7 @@ int read_rollback(int region, struct rollback_data *data) * Return most recent region index on success (>= 0, or 0 if no rollback * region is valid), negative value on error. */ -static int get_latest_rollback(struct rollback_data *data) +test_mockable_static int get_latest_rollback(struct rollback_data *data) { int ret = -1; int region; @@ -165,9 +162,9 @@ int32_t rollback_get_minimum_version(void) } #ifdef CONFIG_ROLLBACK_SECRET_SIZE -test_mockable int rollback_get_secret(uint8_t *secret) +test_mockable enum ec_error_list rollback_get_secret(uint8_t *secret) { - int ret = EC_ERROR_UNKNOWN; + enum ec_error_list ret = EC_ERROR_UNKNOWN; struct rollback_data data; if (get_latest_rollback(&data) < 0) @@ -186,27 +183,41 @@ test_mockable int rollback_get_secret(uint8_t *secret) #endif #ifdef CONFIG_ROLLBACK_UPDATE +static int get_rollback_erase_size_bytes(int region) +{ + int erase_size; + +#ifndef CONFIG_FLASH_MULTIPLE_REGION + erase_size = CONFIG_FLASH_ERASE_SIZE; +#else + int rollback_start_bank = crec_flash_bank_index(CONFIG_ROLLBACK_OFF); + + erase_size = crec_flash_bank_erase_size(rollback_start_bank + region); +#endif + ASSERT(erase_size > 0); + ASSERT(ROLLBACK_REGIONS * erase_size <= CONFIG_ROLLBACK_SIZE); + ASSERT(sizeof(struct rollback_data) <= erase_size); + return erase_size; +} #ifdef CONFIG_ROLLBACK_SECRET_SIZE -static int add_entropy(uint8_t *dst, const uint8_t *src, - const uint8_t *add, unsigned int add_len) +#ifdef CONFIG_SHA256 +static int add_entropy(uint8_t *dst, const uint8_t *src, const uint8_t *add, + unsigned int add_len) { int ret = 0; -#ifdef CONFIG_SHA256 -BUILD_ASSERT(SHA256_DIGEST_SIZE == CONFIG_ROLLBACK_SECRET_SIZE); + BUILD_ASSERT(SHA256_DIGEST_SIZE == CONFIG_ROLLBACK_SECRET_SIZE); struct sha256_ctx ctx; uint8_t *hash; -#ifdef CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE - uint8_t extra; - int i; -#endif SHA256_init(&ctx); SHA256_update(&ctx, src, CONFIG_ROLLBACK_SECRET_SIZE); SHA256_update(&ctx, add, add_len); #ifdef CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE /* Add some locally produced entropy */ - for (i = 0; i < CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE; i++) { + for (int i = 0; i < CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE; i++) { + uint8_t extra; + if (!board_get_entropy(&extra, 1)) goto failed; SHA256_update(&ctx, &extra, 1); @@ -220,12 +231,12 @@ BUILD_ASSERT(SHA256_DIGEST_SIZE == CONFIG_ROLLBACK_SECRET_SIZE); #ifdef CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE failed: #endif - always_memset(&ctx, 0, sizeof(ctx)); -#else -#error "Adding entropy to secret in rollback region requires SHA256." -#endif + secure_clear(&ctx, sizeof(ctx)); return ret; } +#else +#error "Adding entropy to secret in rollback region requires SHA256." +#endif /* CONFIG_SHA256 */ #endif /* CONFIG_ROLLBACK_SECRET_SIZE */ /** @@ -240,27 +251,28 @@ BUILD_ASSERT(SHA256_DIGEST_SIZE == CONFIG_ROLLBACK_SECRET_SIZE); * * @return EC_SUCCESS on success, EC_ERROR_* on error. */ -static int rollback_update(int32_t next_min_version, - const uint8_t *entropy, unsigned int length) +static int rollback_update(int32_t next_min_version, const uint8_t *entropy, + unsigned int length) { /* * When doing flash_write operation, the data needs to be in blocks * of CONFIG_FLASH_WRITE_SIZE, pad rollback_data as required. */ uint8_t block[CONFIG_FLASH_WRITE_SIZE * - DIV_ROUND_UP(sizeof(struct rollback_data), - CONFIG_FLASH_WRITE_SIZE)]; + DIV_ROUND_UP(sizeof(struct rollback_data), + CONFIG_FLASH_WRITE_SIZE)]; struct rollback_data *data = (struct rollback_data *)block; BUILD_ASSERT(sizeof(block) >= sizeof(*data)); int erase_size, offset, region, ret; + uint32_t key; - if (flash_get_protect() & EC_FLASH_PROTECT_ROLLBACK_NOW) { + if (crec_flash_get_protect() & EC_FLASH_PROTECT_ROLLBACK_NOW) { ret = EC_ERROR_ACCESS_DENIED; goto out; } /* Initialize the rest of the block. */ - memset(&block[sizeof(*data)], 0xff, sizeof(block)-sizeof(*data)); + memset(&block[sizeof(*data)], 0xff, sizeof(block) - sizeof(*data)); region = get_latest_rollback(data); @@ -324,15 +336,15 @@ static int rollback_update(int32_t next_min_version, goto out; } - unlock_rollback(); - if (flash_erase(offset, erase_size)) { + key = unlock_rollback(); + if (crec_flash_erase(offset, erase_size)) { ret = EC_ERROR_UNKNOWN; - lock_rollback(); + lock_rollback(key); goto out; } - ret = flash_write(offset, sizeof(block), block); - lock_rollback(); + ret = crec_flash_write(offset, sizeof(block), block); + lock_rollback(key); out: clear_rollback(data); @@ -349,7 +361,7 @@ int rollback_add_entropy(const uint8_t *data, unsigned int len) return rollback_update(-1, data, len); } -static int command_rollback_update(int argc, char **argv) +static int command_rollback_update(int argc, const char **argv) { int32_t min_version; char *e; @@ -364,24 +376,34 @@ static int command_rollback_update(int argc, char **argv) return rollback_update_version(min_version); } -DECLARE_CONSOLE_COMMAND(rollbackupdate, command_rollback_update, - "min_version", +DECLARE_CONSOLE_COMMAND(rollbackupdate, command_rollback_update, "min_version", "Update rollback info"); #ifdef CONFIG_ROLLBACK_SECRET_SIZE -static int command_rollback_add_entropy(int argc, char **argv) +static int command_rollback_add_entropy(int argc, const char **argv) { + uint8_t rand[CONFIG_ROLLBACK_SECRET_SIZE]; + const uint8_t *data; int len; - if (argc < 2) - return EC_ERROR_PARAM_COUNT; + if (argc < 2) { + if (!IS_ENABLED(CONFIG_RNG)) + return EC_ERROR_PARAM_COUNT; - len = strlen(argv[1]); + trng_init(); + trng_rand_bytes(rand, sizeof(rand)); + trng_exit(); + + data = rand; + len = sizeof(rand); + } else { + data = argv[1]; + len = strlen(argv[1]); + } - return rollback_add_entropy(argv[1], len); + return rollback_add_entropy(data, len); } -DECLARE_CONSOLE_COMMAND(rollbackaddent, command_rollback_add_entropy, - "data", +DECLARE_CONSOLE_COMMAND(rollbackaddent, command_rollback_add_entropy, "[data]", "Add entropy to rollback block"); #ifdef CONFIG_RNG @@ -400,9 +422,9 @@ static void add_entropy_deferred(void) if (add_entropy_action == ADD_ENTROPY_RESET_ASYNC) repeat = ROLLBACK_REGIONS; - init_trng(); + trng_init(); do { - rand_bytes(rand, sizeof(rand)); + trng_rand_bytes(rand, sizeof(rand)); if (rollback_add_entropy(rand, sizeof(rand)) != EC_SUCCESS) { add_entropy_rv = EC_RES_ERROR; goto out; @@ -411,7 +433,7 @@ static void add_entropy_deferred(void) add_entropy_rv = EC_RES_SUCCESS; out: - exit_trng(); + trng_exit(); } DECLARE_DEFERRED(add_entropy_deferred); @@ -438,14 +460,13 @@ hc_rollback_add_entropy(struct host_cmd_handler_args *args) return EC_RES_INVALID_PARAM; } -DECLARE_HOST_COMMAND(EC_CMD_ADD_ENTROPY, - hc_rollback_add_entropy, +DECLARE_HOST_COMMAND(EC_CMD_ADD_ENTROPY, hc_rollback_add_entropy, EC_VER_MASK(0)); #endif /* CONFIG_RNG */ #endif /* CONFIG_ROLLBACK_SECRET_SIZE */ #endif /* CONFIG_ROLLBACK_UPDATE */ -static int command_rollback_info(int argc, char **argv) +static int command_rollback_info(int argc, const char **argv) { int ret = EC_ERROR_UNKNOWN; int region, min_region; @@ -467,14 +488,13 @@ static int command_rollback_info(int argc, char **argv) if (ret) goto failed; - ccprintf("rollback %d: %08x %08x %08x", - region, data.id, data.rollback_min_version, - data.cookie); + ccprintf("rollback %d: %08x %08x %08x", region, data.id, + data.rollback_min_version, data.cookie); #ifdef CONFIG_ROLLBACK_SECRET_SIZE if (!system_is_locked()) { /* If system is unlocked, show some of the secret. */ ccprintf(" [%02x..%02x]", data.secret[0], - data.secret[CONFIG_ROLLBACK_SECRET_SIZE-1]); + data.secret[CONFIG_ROLLBACK_SECRET_SIZE - 1]); } #endif if (min_region == region) @@ -487,8 +507,7 @@ static int command_rollback_info(int argc, char **argv) clear_rollback(&data); return ret; } -DECLARE_SAFE_CONSOLE_COMMAND(rollbackinfo, command_rollback_info, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(rollbackinfo, command_rollback_info, NULL, "Print rollback info"); static enum ec_status @@ -515,6 +534,5 @@ host_command_rollback_info(struct host_cmd_handler_args *args) clear_rollback(&data); return ret; } -DECLARE_HOST_COMMAND(EC_CMD_ROLLBACK_INFO, - host_command_rollback_info, +DECLARE_HOST_COMMAND(EC_CMD_ROLLBACK_INFO, host_command_rollback_info, EC_VER_MASK(0)); diff --git a/common/rollback_private.h b/common/rollback_private.h index c757882f4f..1dbbd4f430 100644 --- a/common/rollback_private.h +++ b/common/rollback_private.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/common/rsa.c b/common/rsa.c index 10f0afa4b4..4df6fc136a 100644 --- a/common/rsa.c +++ b/common/rsa.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -39,16 +39,14 @@ static int ge_mod(const struct rsa_public_key *key, const uint32_t *a) if (a[i] > key->n[i]) return 1; } - return 1; /* equal */ + return 1; /* equal */ } /** * Montgomery c[] += a * b[] / R % mod */ -static void mont_mul_add(const struct rsa_public_key *key, - uint32_t *c, - const uint32_t a, - const uint32_t *b) +static void mont_mul_add(const struct rsa_public_key *key, uint32_t *c, + const uint32_t a, const uint32_t *b) { uint64_t A = mula32(a, b[0], c[0]); uint32_t d0 = (uint32_t)A * key->n0inv; @@ -73,9 +71,8 @@ static void mont_mul_add(const struct rsa_public_key *key, /** * Montgomery c[] += 0 * b[] / R % mod */ -static void mont_mul_add_0(const struct rsa_public_key *key, - uint32_t *c, - const uint32_t *b) +static void mont_mul_add_0(const struct rsa_public_key *key, uint32_t *c, + const uint32_t *b) { uint32_t d0 = c[0] * key->n0inv; uint64_t B = mula32(d0, key->n[0], c[0]); @@ -90,8 +87,7 @@ static void mont_mul_add_0(const struct rsa_public_key *key, } /* Montgomery c[] = a[] * 1 / R % key. */ -static void mont_mul_1(const struct rsa_public_key *key, - uint32_t *c, +static void mont_mul_1(const struct rsa_public_key *key, uint32_t *c, const uint32_t *a) { int i; @@ -108,10 +104,8 @@ static void mont_mul_1(const struct rsa_public_key *key, /** * Montgomery c[] = a[] * b[] / R % mod */ -static void mont_mul(const struct rsa_public_key *key, - uint32_t *c, - const uint32_t *a, - const uint32_t *b) +static void mont_mul(const struct rsa_public_key *key, uint32_t *c, + const uint32_t *a, const uint32_t *b) { uint32_t i; for (i = 0; i < RSANUMWORDS; ++i) @@ -136,21 +130,20 @@ static void mod_pow(const struct rsa_public_key *key, uint8_t *inout, uint32_t *a = workbuf32; uint32_t *a_r = a + RSANUMWORDS; uint32_t *aa_r = a_r + RSANUMWORDS; - uint32_t *aaa = aa_r; /* Re-use location. */ + uint32_t *aaa = aa_r; /* Re-use location. */ int i; /* Convert from big endian byte array to little endian word array. */ for (i = 0; i < RSANUMWORDS; ++i) { - uint32_t tmp = - (inout[((RSANUMWORDS - 1 - i) * 4) + 0] << 24) | - (inout[((RSANUMWORDS - 1 - i) * 4) + 1] << 16) | - (inout[((RSANUMWORDS - 1 - i) * 4) + 2] << 8) | - (inout[((RSANUMWORDS - 1 - i) * 4) + 3] << 0); + uint32_t tmp = (inout[((RSANUMWORDS - 1 - i) * 4) + 0] << 24) | + (inout[((RSANUMWORDS - 1 - i) * 4) + 1] << 16) | + (inout[((RSANUMWORDS - 1 - i) * 4) + 2] << 8) | + (inout[((RSANUMWORDS - 1 - i) * 4) + 3] << 0); a[i] = tmp; } /* TODO(drinkcat): This operation could be precomputed to save time. */ - mont_mul(key, a_r, a, key->rr); /* a_r = a * RR / R mod M */ + mont_mul(key, a_r, a, key->rr); /* a_r = a * RR / R mod M */ #ifdef CONFIG_RSA_EXPONENT_3 mont_mul(key, aa_r, a_r, a_r); mont_mul(key, a, aa_r, a_r); @@ -159,9 +152,10 @@ static void mod_pow(const struct rsa_public_key *key, uint8_t *inout, /* Exponent 65537 */ for (i = 0; i < 16; i += 2) { mont_mul(key, aa_r, a_r, a_r); /* aa_r = a_r * a_r / R mod M */ - mont_mul(key, a_r, aa_r, aa_r);/* a_r = aa_r * aa_r / R mod M */ + mont_mul(key, a_r, aa_r, aa_r); /* a_r = aa_r * aa_r / R mod M + */ } - mont_mul(key, aaa, a_r, a); /* aaa = a_r * a / R mod M */ + mont_mul(key, aaa, a_r, a); /* aaa = a_r * a / R mod M */ #endif /* Make sure aaa < mod; aaa is at most 1x mod too large. */ @@ -173,8 +167,8 @@ static void mod_pow(const struct rsa_public_key *key, uint8_t *inout, uint32_t tmp = aaa[i]; *inout++ = (uint8_t)(tmp >> 24); *inout++ = (uint8_t)(tmp >> 16); - *inout++ = (uint8_t)(tmp >> 8); - *inout++ = (uint8_t)(tmp >> 0); + *inout++ = (uint8_t)(tmp >> 8); + *inout++ = (uint8_t)(tmp >> 0); } } @@ -192,11 +186,9 @@ static void mod_pow(const struct rsa_public_key *key, uint8_t *inout, * * PS: octet string consisting of {Length(RSA Key) - Length(T) - 3} 0xFF */ -static const uint8_t sha256_tail[] = { - 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, - 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, - 0x05, 0x00, 0x04, 0x20 -}; +static const uint8_t sha256_tail[] = { 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; #define PKCS_PAD_SIZE (RSANUMBYTES - SHA256_DIGEST_SIZE) @@ -255,5 +247,5 @@ int rsa_verify(const struct rsa_public_key *key, const uint8_t *signature, if (memcmp(buf + PKCS_PAD_SIZE, sha, SHA256_DIGEST_SIZE) != 0) return 0; - return 1; /* All checked out OK. */ + return 1; /* All checked out OK. */ } diff --git a/common/rtc.c b/common/rtc.c index 8a2fbc7139..82bdae0aec 100644 --- a/common/rtc.c +++ b/common/rtc.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,8 +8,8 @@ #include "rtc.h" -static uint16_t days_since_year_start[12] = { -0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; +static uint16_t days_since_year_start[12] = { 0, 31, 59, 90, 120, 151, + 181, 212, 243, 273, 304, 334 }; /* Conversion between calendar date and seconds eclapsed since 1970-01-01 */ uint32_t date_to_sec(struct calendar_date time) @@ -24,8 +24,8 @@ uint32_t date_to_sec(struct calendar_date time) } sec += (days_since_year_start[time.month - 1] + - (IS_LEAP_YEAR(time.year) && time.month > 2) + - (time.day - 1)) * SECS_PER_DAY; + (IS_LEAP_YEAR(time.year) && time.month > 2) + (time.day - 1)) * + SECS_PER_DAY; /* add the accumulated time in seconds from 1970 to 2000 */ return sec + SECS_TILL_YEAR_2K; @@ -53,9 +53,15 @@ struct calendar_date sec_to_date(uint32_t sec) day_tmp += IS_LEAP_YEAR(time.year) ? 366 : 365; } for (i = 1; i < 12; i++) { - if (days_since_year_start[i] + - (IS_LEAP_YEAR(time.year) && (i >= 2)) >= day_tmp) + int month_offset = days_since_year_start[i]; + + if (IS_LEAP_YEAR(time.year) && (i >= 2)) { + month_offset++; + } + + if (month_offset >= day_tmp) { break; + } } time.month = i; diff --git a/common/rwsig.c b/common/rwsig.c index e23ca23293..e3689abc85 100644 --- a/common/rwsig.c +++ b/common/rwsig.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ */ #include "console.h" +#include "cros_version.h" #include "ec_commands.h" #include "flash.h" #include "host_command.h" @@ -22,38 +23,36 @@ #include "util.h" #include "vb21_struct.h" #include "vboot.h" -#include "version.h" /* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) #if !defined(CONFIG_MAPPED_STORAGE) #error rwsig implementation assumes mem-mapped storage. #endif /* RW firmware reset vector */ -static uint32_t * const rw_rst = +static uint32_t *const rw_rst = (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF + 4); - void rwsig_jump_now(void) { /* Protect all flash before jumping to RW. */ /* This may do nothing if WP is not enabled, RO is not protected. */ - flash_set_protect(EC_FLASH_PROTECT_ALL_NOW, -1); + crec_flash_set_protect(EC_FLASH_PROTECT_ALL_NOW, -1); /* * For chips that does not support EC_FLASH_PROTECT_ALL_NOW, use * EC_FLASH_PROTECT_ALL_AT_BOOT. */ if (system_is_locked() && - !(flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)) { - flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, -1); + !(crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)) { + crec_flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, -1); - if (!(flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) && - flash_get_protect() & EC_FLASH_PROTECT_ALL_AT_BOOT) { + if (!(crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) && + crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_AT_BOOT) { /* * If flash protection is still not enabled (some chips * may be able to enable it immediately), reboot. @@ -66,7 +65,7 @@ void rwsig_jump_now(void) /* When system is locked, only boot to RW if all flash is protected. */ if (!system_is_locked() || - flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) + crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) system_run_image_copy(EC_IMAGE_RW); } @@ -74,8 +73,8 @@ void rwsig_jump_now(void) * Check that memory between rwdata[start] and rwdata[len-1] is filled * with ones. data, start and len must be aligned on 4-byte boundary. */ -static int check_padding(const uint8_t *data, - unsigned int start, unsigned int len) +static int check_padding(const uint8_t *data, unsigned int start, + unsigned int len) { unsigned int i; const uint32_t *data32 = (const uint32_t *)data; @@ -83,7 +82,7 @@ static int check_padding(const uint8_t *data, if ((start % 4) != 0 || (len % 4) != 0) return 0; - for (i = start/4; i < len/4; i++) { + for (i = start / 4; i < len / 4; i++) { if (data32[i] != 0xffffffff) return 0; } @@ -99,8 +98,8 @@ int rwsig_check_signature(void) const uint8_t *sig; uint8_t *hash; uint32_t *rsa_workbuf = NULL; - const uint8_t *rwdata = (uint8_t *)CONFIG_PROGRAM_MEMORY_BASE - + CONFIG_RW_MEM_OFF; + const uint8_t *rwdata = (uint8_t *)CONFIG_MAPPED_STORAGE_BASE + + CONFIG_EC_WRITABLE_STORAGE_OFF; int good = 0; unsigned int rwlen; @@ -125,8 +124,8 @@ int rwsig_check_signature(void) if (rw_rollback_version < 0 || min_rollback_version < 0 || rw_rollback_version < min_rollback_version) { - CPRINTS("Rollback error (%d < %d)", - rw_rollback_version, min_rollback_version); + CPRINTS("Rollback error (%d < %d)", rw_rollback_version, + min_rollback_version); goto out; } #endif @@ -144,7 +143,7 @@ int rwsig_check_signature(void) rwlen = CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE; #elif defined(CONFIG_RWSIG_TYPE_RWSIG) vb21_key = vb21_get_packed_key(); - vb21_sig = (const struct vb21_signature *)CONFIG_RW_SIG_ADDR; + vb21_sig = (const struct vb21_signature *)CONFIG_RWSIG_READ_ADDR; if (vb21_key->c.magic != VB21_MAGIC_PACKED_KEY || vb21_key->key_size != sizeof(struct rsa_public_key)) { @@ -152,8 +151,8 @@ int rwsig_check_signature(void) goto out; } - key = (const struct rsa_public_key *) - ((const uint8_t *)vb21_key + vb21_key->key_offset); + key = (const struct rsa_public_key *)((const uint8_t *)vb21_key + + vb21_key->key_offset); /* * TODO(crbug.com/690773): We could verify other parameters such @@ -179,7 +178,7 @@ int rwsig_check_signature(void) * Check that unverified RW region is actually filled with ones. */ good = check_padding(rwdata, rwlen, - CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE); + CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE); if (!good) { CPRINTS("Invalid padding."); goto out; @@ -207,10 +206,10 @@ int rwsig_check_signature(void) */ if (rw_rollback_version != min_rollback_version #ifdef CONFIG_FLASH_PROTECT_RW - && ((!system_is_locked() || - flash_get_protect() & EC_FLASH_PROTECT_RW_NOW)) + && ((!system_is_locked() || + crec_flash_get_protect() & EC_FLASH_PROTECT_RW_NOW)) #endif - ) { + ) { /* * This will fail if the rollback block is protected (RW image * will unprotect that block later on). @@ -218,8 +217,7 @@ int rwsig_check_signature(void) int ret = rollback_update_version(rw_rollback_version); if (ret == 0) { - CPRINTS("Rollback updated to %d", - rw_rollback_version); + CPRINTS("Rollback updated to %d", rw_rollback_version); } else if (ret != EC_ERROR_ACCESS_DENIED) { CPRINTS("Rollback update error %d", ret); good = 0; @@ -254,12 +252,12 @@ enum rwsig_status rwsig_get_status(void) void rwsig_abort(void) { - task_set_event(TASK_ID_RWSIG, TASK_EVENT_ABORT, 0); + task_set_event(TASK_ID_RWSIG, TASK_EVENT_ABORT); } void rwsig_continue(void) { - task_set_event(TASK_ID_RWSIG, TASK_EVENT_CONTINUE, 0); + task_set_event(TASK_ID_RWSIG, TASK_EVENT_CONTINUE); } void rwsig_task(void *u) @@ -297,7 +295,7 @@ void rwsig_task(void *u) task_wait_event(-1); } -enum ec_status rwsig_cmd_action(struct host_cmd_handler_args *args) +static enum ec_status rwsig_cmd_action(struct host_cmd_handler_args *args) { const struct ec_params_rwsig_action *p = args->params; @@ -314,12 +312,10 @@ enum ec_status rwsig_cmd_action(struct host_cmd_handler_args *args) args->response_size = 0; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RWSIG_ACTION, - rwsig_cmd_action, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_RWSIG_ACTION, rwsig_cmd_action, EC_VER_MASK(0)); #else /* !HAS_TASK_RWSIG */ -enum ec_status rwsig_cmd_check_status(struct host_cmd_handler_args *args) +static enum ec_status rwsig_cmd_check_status(struct host_cmd_handler_args *args) { struct ec_response_rwsig_check_status *r = args->response; @@ -329,7 +325,6 @@ enum ec_status rwsig_cmd_check_status(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_RWSIG_CHECK_STATUS, - rwsig_cmd_check_status, +DECLARE_HOST_COMMAND(EC_CMD_RWSIG_CHECK_STATUS, rwsig_cmd_check_status, EC_VER_MASK(0)); #endif diff --git a/common/sha256.c b/common/sha256.c deleted file mode 120000 index 8c0778c3e6..0000000000 --- a/common/sha256.c +++ /dev/null @@ -1 +0,0 @@ -../third_party/sha2//sha256.c \ No newline at end of file diff --git a/common/sha256.c b/common/sha256.c new file mode 100644 index 0000000000..2826f6c68d --- /dev/null +++ b/common/sha256.c @@ -0,0 +1,296 @@ +/* SHA-256 and SHA-512 implementation based on code by Oliver Gay + * under a BSD-style license. See below. + */ + +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "builtin/assert.h" +#include "sha256.h" +#include "util.h" + +#define SHFR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) +#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n))) +#define CH(x, y, z) ((x & y) ^ (~x & z)) +#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) + +#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) +#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) + +#define UNPACK32(x, str) \ + { \ + *((str) + 3) = (uint8_t)((x)); \ + *((str) + 2) = (uint8_t)((x) >> 8); \ + *((str) + 1) = (uint8_t)((x) >> 16); \ + *((str) + 0) = (uint8_t)((x) >> 24); \ + } + +#define PACK32(str, x) \ + { \ + *(x) = ((uint32_t) * ((str) + 3)) | \ + ((uint32_t) * ((str) + 2) << 8) | \ + ((uint32_t) * ((str) + 1) << 16) | \ + ((uint32_t) * ((str) + 0) << 24); \ + } + +/* Macros used for loops unrolling */ + +#define SHA256_SCR(i) \ + { \ + w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + \ + w[i - 16]; \ + } + +#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \ + { \ + t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + \ + sha256_k[j] + w[j]; \ + t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \ + wv[d] += t1; \ + wv[h] = t1 + t2; \ + } + +static const uint32_t sha256_h0[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, + 0xa54ff53a, 0x510e527f, 0x9b05688c, + 0x1f83d9ab, 0x5be0cd19 }; + +static const uint32_t sha256_k[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +void SHA256_init(struct sha256_ctx *ctx) +{ + int i; + + for (i = 0; i < 8; i++) + ctx->h[i] = sha256_h0[i]; + + ctx->len = 0; + ctx->tot_len = 0; +} + +static void SHA256_transform(struct sha256_ctx *ctx, const uint8_t *message, + unsigned int block_nb) +{ + /* Note: this function requires a considerable amount of stack */ + uint32_t w[64]; + uint32_t wv[8]; + uint32_t t1, t2; + const unsigned char *sub_block; + int i, j; + + for (i = 0; i < (int)block_nb; i++) { + sub_block = message + (i << 6); + + for (j = 0; j < 16; j++) + PACK32(&sub_block[j << 2], &w[j]); + +#ifdef CONFIG_SHA256_UNROLLED + for (j = 16; j < 64; j += 8) { + SHA256_SCR(j); + SHA256_SCR(j + 1); + SHA256_SCR(j + 2); + SHA256_SCR(j + 3); + SHA256_SCR(j + 4); + SHA256_SCR(j + 5); + SHA256_SCR(j + 6); + SHA256_SCR(j + 7); + } +#else + for (j = 16; j < 64; j++) + SHA256_SCR(j); +#endif + + for (j = 0; j < 8; j++) + wv[j] = ctx->h[j]; + +#ifdef CONFIG_SHA256_UNROLLED + for (j = 0; j < 64; j += 8) { + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, j); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, j + 1); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, j + 2); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, j + 3); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, j + 4); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, j + 5); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, j + 6); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, j + 7); + } +#else + for (j = 0; j < 64; j++) { + t1 = wv[7] + SHA256_F2(wv[4]) + + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j]; + t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } +#endif + + for (j = 0; j < 8; j++) + ctx->h[j] += wv[j]; + } +} + +void SHA256_update(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len) +{ + unsigned int block_nb; + unsigned int new_len, rem_len, tmp_len; + const uint8_t *shifted_data; + + tmp_len = SHA256_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], data, rem_len); + + if (ctx->len + len < SHA256_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA256_BLOCK_SIZE; + + shifted_data = data + rem_len; + + SHA256_transform(ctx, ctx->block, 1); + SHA256_transform(ctx, shifted_data, block_nb); + + rem_len = new_len % SHA256_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_data[block_nb << 6], rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +/* + * Specialized SHA256_init + SHA256_update that takes the first data block of + * size SHA256_BLOCK_SIZE as input. + */ +static void SHA256_init_1b(struct sha256_ctx *ctx, const uint8_t *data) +{ + int i; + + for (i = 0; i < 8; i++) + ctx->h[i] = sha256_h0[i]; + + SHA256_transform(ctx, data, 1); + + ctx->len = 0; + ctx->tot_len = SHA256_BLOCK_SIZE; +} + +uint8_t *SHA256_final(struct sha256_ctx *ctx) +{ + unsigned int block_nb; + unsigned int pm_len; + unsigned int len_b; + int i; + + block_nb = (1 + + ((SHA256_BLOCK_SIZE - 9) < (ctx->len % SHA256_BLOCK_SIZE))); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 6; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + SHA256_transform(ctx, ctx->block, block_nb); + + for (i = 0; i < 8; i++) + UNPACK32(ctx->h[i], &ctx->buf[i << 2]); + + return ctx->buf; +} + +static void hmac_SHA256_step(uint8_t *output, uint8_t mask, const uint8_t *key, + const int key_len, const uint8_t *data, + const int data_len) +{ + struct sha256_ctx ctx; + uint8_t *key_pad = ctx.block; + uint8_t *tmp; + int i; + + /* key_pad = key (zero-padded) ^ mask */ + memset(key_pad, mask, SHA256_BLOCK_SIZE); + for (i = 0; i < key_len; i++) + key_pad[i] ^= key[i]; + + /* tmp = hash(key_pad || message) */ + SHA256_init_1b(&ctx, key_pad); + SHA256_update(&ctx, data, data_len); + tmp = SHA256_final(&ctx); + memcpy(output, tmp, SHA256_DIGEST_SIZE); +} + +void hmac_SHA256(uint8_t *output, const uint8_t *key, const int key_len, + const uint8_t *message, const int message_len) +{ + /* This code does not support key_len > block_size. */ + ASSERT(key_len <= SHA256_BLOCK_SIZE); + + /* + * i_key_pad = key (zero-padded) ^ 0x36 + * output = hash(i_key_pad || message) + * (Use output as temporary buffer) + */ + hmac_SHA256_step(output, 0x36, key, key_len, message, message_len); + + /* + * o_key_pad = key (zero-padded) ^ 0x5c + * output = hash(o_key_pad || output) + */ + hmac_SHA256_step(output, 0x5c, key, key_len, output, + SHA256_DIGEST_SIZE); +} diff --git a/common/shared_mem.c b/common/shared_mem.c index be420f60a6..c1b206f143 100644 --- a/common/shared_mem.c +++ b/common/shared_mem.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,8 +15,14 @@ static int buf_in_use; static int max_used; +/* 1 MB buffer for fake shared memory implementation */ +STATIC_IF(CONFIG_FAKE_SHMEM) char fake_shmem_buf[BIT(20)]; + int shared_mem_size(void) { + if (IS_ENABLED(CONFIG_FAKE_SHMEM)) + return sizeof(fake_shmem_buf); + /* * Use all the RAM we can. The shared memory buffer is the last thing * allocated from the start of RAM, so we can use everything up to the @@ -39,7 +45,10 @@ int shared_mem_acquire(int size, char **dest_ptr) */ buf_in_use = size; - *dest_ptr = __shared_mem_buf; + if (IS_ENABLED(CONFIG_FAKE_SHMEM)) + *dest_ptr = fake_shmem_buf; + else + *dest_ptr = __shared_mem_buf; if (max_used < size) max_used = size; @@ -49,18 +58,20 @@ int shared_mem_acquire(int size, char **dest_ptr) void shared_mem_release(void *ptr) { + if (ptr == NULL) + return; + buf_in_use = 0; } #ifdef CONFIG_CMD_SHMEM -static int command_shmem(int argc, char **argv) +static int command_shmem(int argc, const char **argv) { ccprintf("Size:%6d\n", shared_mem_size()); ccprintf("Used:%6d\n", buf_in_use); ccprintf("Max: %6d\n", max_used); return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(shmem, command_shmem, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(shmem, command_shmem, NULL, "Print shared memory stats"); #endif diff --git a/common/shared_mem_libc.c b/common/shared_mem_libc.c new file mode 100644 index 0000000000..9361ba48a0 --- /dev/null +++ b/common/shared_mem_libc.c @@ -0,0 +1,61 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * @brief Shared mem implementation that uses malloc/free from libc. + */ + +#include "common.h" +#include "console.h" +#include "link_defs.h" +#include "shared_mem.h" +#include "system.h" +#include "task.h" + +#include + +#include + +int shared_mem_size(void) +{ + return system_usable_ram_end() - (uintptr_t)__shared_mem_buf; +} + +int shared_mem_acquire(int size, char **dest_ptr) +{ + *dest_ptr = NULL; + + if (in_interrupt_context()) + return EC_ERROR_INVAL; + + *dest_ptr = malloc(size); + if (!*dest_ptr) + return EC_ERROR_BUSY; + + return EC_SUCCESS; +} + +void shared_mem_release(void *ptr) +{ + if (in_interrupt_context()) + return; + + free(ptr); +} + +#ifdef CONFIG_CMD_SHMEM +static int command_shmem(int argc, const char **argv) +{ + struct mallinfo info = mallinfo(); + + ccprintf("Total: %d\n", shared_mem_size()); + ccprintf("Allocated: %d\n", info.uordblks); + ccprintf("Free: %d\n", info.fordblks + info.fsmblks); + + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(shmem, command_shmem, NULL, + "Print shared memory stats"); +#endif /* CONFIG_CMD_SHMEM */ diff --git a/common/shmalloc.c b/common/shmalloc.c index b1705b52d1..de2c4f4e86 100644 --- a/common/shmalloc.c +++ b/common/shmalloc.c @@ -1,12 +1,10 @@ /* - * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Malloc/free memory module for Chrome EC */ -#include - #include "common.h" #include "hooks.h" #include "link_defs.h" @@ -15,6 +13,8 @@ #include "task.h" #include "util.h" +#include + static struct mutex shmem_lock; #ifndef TEST_SHMALLOC @@ -47,8 +47,8 @@ static void shared_mem_init(void) free_buf_chain = (struct shm_buffer *)__shared_mem_buf; free_buf_chain->next_buffer = NULL; free_buf_chain->prev_buffer = NULL; - free_buf_chain->buffer_size = system_usable_ram_end() - - (uintptr_t)__shared_mem_buf; + free_buf_chain->buffer_size = + system_usable_ram_end() - (uintptr_t)__shared_mem_buf; } DECLARE_HOOK(HOOK_INIT, shared_mem_init, HOOK_PRIO_FIRST); @@ -73,8 +73,7 @@ static void do_release(struct shm_buffer *ptr) * Saninty check: verify that the buffer is in the allocated * buffers chain. */ - for (pfb = allocced_buf_chain->next_buffer; - pfb; + for (pfb = allocced_buf_chain->next_buffer; pfb; pfb = pfb->next_buffer) if (pfb == ptr) break; @@ -117,10 +116,9 @@ static void do_release(struct shm_buffer *ptr) if (pfb == free_buf_chain) { set_map_bit(BIT(1)); /* Merge the two buffers. */ - ptr->buffer_size = free_buf_chain->buffer_size + - released_size; - ptr->next_buffer = - free_buf_chain->next_buffer; + ptr->buffer_size = + free_buf_chain->buffer_size + released_size; + ptr->next_buffer = free_buf_chain->next_buffer; } else { set_map_bit(BIT(2)); ptr->buffer_size = released_size; @@ -163,8 +161,7 @@ static void do_release(struct shm_buffer *ptr) if (top == pfb->next_buffer) { /* Yes, it is. */ pfb->buffer_size += pfb->next_buffer->buffer_size; - pfb->next_buffer = - pfb->next_buffer->next_buffer; + pfb->next_buffer = pfb->next_buffer->next_buffer; if (pfb->next_buffer) { set_map_bit(BIT(5)); pfb->next_buffer->prev_buffer = pfb; @@ -179,8 +176,8 @@ static void do_release(struct shm_buffer *ptr) if (top == pfb->next_buffer) { /* The new buffer is adjacent with the one right above it. */ set_map_bit(BIT(7)); - ptr->buffer_size = released_size + - pfb->next_buffer->buffer_size; + ptr->buffer_size = + released_size + pfb->next_buffer->buffer_size; ptr->next_buffer = pfb->next_buffer->next_buffer; } else { /* Just include the new free buffer into the chain. */ @@ -345,6 +342,9 @@ void shared_mem_release(void *ptr) if (in_interrupt_context()) return; + if (ptr == NULL) + return; + mutex_lock(&shmem_lock); do_release((struct shm_buffer *)ptr - 1); mutex_unlock(&shmem_lock); @@ -352,7 +352,7 @@ void shared_mem_release(void *ptr) #ifdef CONFIG_CMD_SHMEM -static int command_shmem(int argc, char **argv) +static int command_shmem(int argc, const char **argv) { size_t allocated_size; size_t free_size; @@ -373,8 +373,7 @@ static int command_shmem(int argc, char **argv) max_free = buf_room; } - for (buf = allocced_buf_chain; buf; - buf = buf->next_buffer) + for (buf = allocced_buf_chain; buf; buf = buf->next_buffer) allocated_size += buf->buffer_size; mutex_unlock(&shmem_lock); @@ -386,8 +385,7 @@ static int command_shmem(int argc, char **argv) ccprintf("Max allocated: %6d\n", max_allocated_size); return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(shmem, command_shmem, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(shmem, command_shmem, NULL, "Print shared memory stats"); -#endif /* CONFIG_CMD_SHMEM ^^^^^^^ defined */ +#endif /* CONFIG_CMD_SHMEM ^^^^^^^ defined */ diff --git a/common/spi/CMakeLists.txt b/common/spi/CMakeLists.txt new file mode 100644 index 0000000000..356a0ef16a --- /dev/null +++ b/common/spi/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +add_subdirectory_ifdef(CONFIG_PLATFORM_EC_SPI_FLASH_REGS flash_reg) diff --git a/common/spi/Kconfig b/common/spi/Kconfig new file mode 100644 index 0000000000..e8408a01f5 --- /dev/null +++ b/common/spi/Kconfig @@ -0,0 +1,5 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +rsource "flash_reg/Kconfig.module" diff --git a/common/spi/build.mk b/common/spi/build.mk new file mode 100644 index 0000000000..ad5c728db7 --- /dev/null +++ b/common/spi/build.mk @@ -0,0 +1,8 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) + +include $(SELF_DIR)flash_reg/build.mk diff --git a/common/spi/flash_reg/CMakeLists.txt b/common/spi/flash_reg/CMakeLists.txt new file mode 100644 index 0000000000..55708ac57e --- /dev/null +++ b/common/spi/flash_reg/CMakeLists.txt @@ -0,0 +1,75 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +cmake_minimum_required(VERSION 3.20.0) + +# Create the library +if(BOARD STREQUAL unit_testing) + find_package(Zephyr COMPONENTS unittest REQUIRED HINTS $ENV{ZEPHYR_BASE}) + add_library(spi_flash_reg) +else() + zephyr_library_named(spi_flash_reg) + target_link_libraries(spi_flash_reg PRIVATE cros_ec_interface) + # When LTO is enabled, enable only for the "app" library, which compiles + # and links all Chromium OS sources. + # TODO: Enable LTO for all sources when Zephyr supports it. + # See https://github.com/zephyrproject-rtos/zephyr/issues/2112 + if (DEFINED CONFIG_LTO) + # The Zephyr toolchain generates linker errors if both CONFIG_LTO and + # CONFIG_FPU are used. See b/184302085. + if(("${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "zephyr") AND + (DEFINED CONFIG_FPU)) + message(STATUS "Zephyr toolchain and CONFIG_FPU detected: disabling LTO") + else() + set_property( + TARGET + spi_flash_reg + PROPERTY + INTERPROCEDURAL_OPTIMIZATION True + ) + endif() + endif() +endif() + +# Add the sources +target_sources(spi_flash_reg + PRIVATE + src/spi_flash_reg.c + PUBLIC + public/spi_flash_reg.h +) + +# Include the public directory +target_include_directories(spi_flash_reg PUBLIC public) + +if(BOARD STREQUAL unit_testing) + project(flash_reg) + + # Set the sources for the test + target_sources(testbinary PRIVATE src/spi_flash_reg_test.c) + + # Link the library being tested + target_link_libraries(testbinary PRIVATE spi_flash_reg) + + # Add the private directory used to mock components of the EC + target_include_directories(testbinary PRIVATE private) + target_include_directories(spi_flash_reg PRIVATE private) + + # Zephyr's unittest also generates a test_interface which we need in the + # library (not just in the test binary) + target_link_libraries(spi_flash_reg PRIVATE test_interface) + string(TOLOWER "${CMAKE_C_COMPILER_ID}" lowercase_compiler_id) + if("${lowercase_compiler_id}" STREQUAL "clang") + target_link_options(testbinary PRIVATE -fprofile-instr-generate) + endif() + + # W25Q64 has 0x400000 bytes as the first section, setting + # CONFIG_FLASH_SIZE_BYTES to that allows us to test every branch of + # spi_flash_reg.c + add_compile_definitions(spi_flash_reg + PUBLIC + CONFIG_SPI_FLASH_W25Q64 + CONFIG_FLASH_SIZE_BYTES=4194304 + ) +endif() \ No newline at end of file diff --git a/common/spi/flash_reg/Kconfig.module b/common/spi/flash_reg/Kconfig.module new file mode 100644 index 0000000000..04a306c8d0 --- /dev/null +++ b/common/spi/flash_reg/Kconfig.module @@ -0,0 +1,12 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +config PLATFORM_EC_SPI_FLASH_REGS + bool + help + Enables flash registers for SPI flash (both internal and external). + When enabled, two new functions will become available: (1) a function + to compute the block write protection range from a set of status + registers, and (2) the inverse function to set the status registers + based on the desired protection offset/length. diff --git a/common/spi/flash_reg/build.mk b/common/spi/flash_reg/build.mk new file mode 100644 index 0000000000..5d6c9f10bf --- /dev/null +++ b/common/spi/flash_reg/build.mk @@ -0,0 +1,11 @@ +# -*- makefile -*- +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +REL_PATH := $(shell realpath --relative-to $(_common_dir) $(SELF_DIR)) + +includes+=$(REL_PATH)public +common-$(CONFIG_SPI_FLASH)+=$(REL_PATH)/src/spi_flash_reg.o +common-$(CONFIG_SPI_FLASH_REGS)+=$(REL_PATH)/src/spi_flash_reg.o diff --git a/common/spi/flash_reg/private/common.h b/common/spi/flash_reg/private/common.h new file mode 100644 index 0000000000..9737e2f889 --- /dev/null +++ b/common/spi/flash_reg/private/common.h @@ -0,0 +1,16 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef ZEPHYR_TEST_SPI_FLASH_REG_INCLUDE_COMMON_H_ +#define ZEPHYR_TEST_SPI_FLASH_REG_INCLUDE_COMMON_H_ + +#include + +enum ec_error_list { + EC_SUCCESS, + EC_ERROR_INVAL, +}; + +#endif /* ZEPHYR_TEST_SPI_FLASH_REG_INCLUDE_COMMON_H_ */ diff --git a/common/spi/flash_reg/private/util.h b/common/spi/flash_reg/private/util.h new file mode 100644 index 0000000000..119d3f10cc --- /dev/null +++ b/common/spi/flash_reg/private/util.h @@ -0,0 +1,12 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef ZEPHYR_TEST_SPI_FLASH_REG_INCLUDE_UTIL_H_ +#define ZEPHYR_TEST_SPI_FLASH_REG_INCLUDE_UTIL_H_ + +#include +#include + +#endif /* ZEPHYR_TEST_SPI_FLASH_REG_INCLUDE_UTIL_H_ */ diff --git a/common/spi/flash_reg/prj.conf b/common/spi/flash_reg/prj.conf new file mode 100644 index 0000000000..6ec8f4d2a9 --- /dev/null +++ b/common/spi/flash_reg/prj.conf @@ -0,0 +1,6 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y diff --git a/common/spi/flash_reg/public/spi_flash_reg.h b/common/spi/flash_reg/public/spi_flash_reg.h new file mode 100644 index 0000000000..0d70d6982d --- /dev/null +++ b/common/spi/flash_reg/public/spi_flash_reg.h @@ -0,0 +1,73 @@ +/* + * Copyright 2015 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * SPI flash protection register translation functions for Chrome OS EC. + */ + +#ifndef __CROS_EC_SPI_FLASH_REG_H +#define __CROS_EC_SPI_FLASH_REG_H + +#include "common.h" + +/* + * Common register bits for SPI flash. All registers / bits may not be valid + * for all parts. + */ +#define SPI_FLASH_SR2_SUS BIT(7) +#define SPI_FLASH_SR2_CMP BIT(6) +#define SPI_FLASH_SR2_LB3 BIT(5) +#define SPI_FLASH_SR2_LB2 BIT(4) +#define SPI_FLASH_SR2_LB1 BIT(3) +#define SPI_FLASH_SR2_QE BIT(1) +#define SPI_FLASH_SR2_SRP1 BIT(0) +#define SPI_FLASH_SR1_SRP0 BIT(7) +#define SPI_FLASH_SR1_SEC BIT(6) +#define SPI_FLASH_SR1_TB BIT(5) +#define SPI_FLASH_SR1_BP2 BIT(4) +#define SPI_FLASH_SR1_BP1 BIT(3) +#define SPI_FLASH_SR1_BP0 BIT(2) +#define SPI_FLASH_SR1_WEL BIT(1) +#define SPI_FLASH_SR1_BUSY BIT(0) + +/* SR2 register existence based upon chip */ +#ifdef CONFIG_SPI_FLASH_W25X40 +#undef CONFIG_SPI_FLASH_HAS_SR2 +#elif defined(CONFIG_SPI_FLASH_W25Q64) || defined(CONFIG_SPI_FLASH_GD25Q41B) +#define CONFIG_SPI_FLASH_HAS_SR2 +#endif + +/* W25Q128 16 Mbyte SPI flash for testing */ +#ifdef CONFIG_SPI_FLASH_W25Q128 +#define CONFIG_SPI_FLASH_HAS_SR2 +#endif + +/** + * Computes block write protection range from registers + * Returns start == len == 0 for no protection + * + * @param sr1 Status register 1 + * @param sr2 Status register 2 + * @param start Output pointer for protection start offset + * @param len Output pointer for protection length + * + * @return EC_SUCCESS, or non-zero if any error. + */ +int spi_flash_reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start, + unsigned int *len); + +/** + * Computes block write protection registers from range + * + * @param start Desired protection start offset + * @param len Desired protection length + * @param sr1 Output pointer for status register 1 + * @param sr2 Output pointer for status register 2 + * + * @return EC_SUCCESS, or non-zero if any error. + */ +int spi_flash_protect_to_reg(unsigned int start, unsigned int len, uint8_t *sr1, + uint8_t *sr2); + +#endif /* __CROS_EC_SPI_FLASH_REG_H */ diff --git a/common/spi_flash_reg.c b/common/spi/flash_reg/src/spi_flash_reg.c similarity index 83% rename from common/spi_flash_reg.c rename to common/spi/flash_reg/src/spi_flash_reg.c index 3cee0f3bd4..fa71ab5eb6 100644 --- a/common/spi_flash_reg.c +++ b/common/spi/flash_reg/src/spi_flash_reg.c @@ -1,5 +1,5 @@ /* - * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -21,7 +21,7 @@ struct protect_range { enum bit_state cmp; enum bit_state sec; enum bit_state tb; - enum bit_state bp[3]; /* Ordered {BP2, BP1, BP0} */ + enum bit_state bp[3]; /* Ordered {BP2, BP1, BP0} */ uint32_t protect_start; uint32_t protect_len; }; @@ -39,7 +39,7 @@ struct protect_range { */ #if defined(CONFIG_SPI_FLASH_W25X40) || defined(CONFIG_SPI_FLASH_GD25Q41B) static const struct protect_range spi_flash_protect_ranges[] = { - { IGN, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ + { IGN, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ { IGN, IGN, 1, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/2 */ { IGN, IGN, 1, { 0, 1, 0 }, 0, 0x20000 }, /* Lower 1/4 */ }; @@ -49,17 +49,17 @@ static const struct protect_range spi_flash_protect_ranges[] = { /* For GD25LQ40, BP3 and BP4 have same meaning as TB and SEC */ static const struct protect_range spi_flash_protect_ranges[] = { /* CMP = 0 */ - { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ - { 0, 0, 1, { 0, 1, 0 }, 0, 0x20000 }, /* Lower 1/4 */ - { 0, 0, 1, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/2 */ + { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ + { 0, 0, 1, { 0, 1, 0 }, 0, 0x20000 }, /* Lower 1/4 */ + { 0, 0, 1, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/2 */ /* CMP = 1 */ - { 1, 0, 0, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/2 */ - { 1, 0, IGN, { 1, IGN, IGN }, 0, 0 }, /* None (W25Q40EW only) */ + { 1, 0, 0, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/2 */ + { 1, 0, IGN, { 1, IGN, IGN }, 0, 0 }, /* None (W25Q40EW only) */ }; #elif defined(CONFIG_SPI_FLASH_W25Q64) static const struct protect_range spi_flash_protect_ranges[] = { - { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ + { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ { 0, 0, 1, { 1, 1, 0 }, 0, 0x400000 }, /* Lower 1/2 */ { 0, 0, 1, { 1, 0, 1 }, 0, 0x200000 }, /* Lower 1/4 */ }; @@ -67,7 +67,7 @@ static const struct protect_range spi_flash_protect_ranges[] = { #elif defined(CONFIG_SPI_FLASH_W25Q80) static const struct protect_range spi_flash_protect_ranges[] = { /* CMP = 0 */ - { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ + { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ { 0, 0, 1, { 0, 1, 0 }, 0, 0x20000 }, /* Lower 1/8 */ { 0, 0, 1, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/4 */ { 0, 0, 1, { 1, 0, 0 }, 0, 0x80000 }, /* Lower 1/2 */ @@ -75,7 +75,7 @@ static const struct protect_range spi_flash_protect_ranges[] = { #elif defined(CONFIG_SPI_FLASH_W25Q128) static const struct protect_range spi_flash_protect_ranges[] = { /* CMP = 0 */ - { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ + { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */ { 0, 0, 1, { 1, 0, 0 }, 0, 0x20000 }, /* Lower 1/8 */ { 0, 0, 1, { 1, 0, 1 }, 0, 0x40000 }, /* Lower 1/4 */ { 0, 0, 1, { 1, 1, 0 }, 0, 0x80000 }, /* Lower 1/2 */ @@ -107,8 +107,9 @@ int spi_flash_reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start, cmp = (sr2 & SPI_FLASH_SR2_CMP) ? 1 : 0; sec = (sr1 & SPI_FLASH_SR1_SEC) ? 1 : 0; tb = (sr1 & SPI_FLASH_SR1_TB) ? 1 : 0; - bp = (sr1 & (SPI_FLASH_SR1_BP2 | SPI_FLASH_SR1_BP1 | SPI_FLASH_SR1_BP0)) - >> 2; + bp = (sr1 & + (SPI_FLASH_SR1_BP2 | SPI_FLASH_SR1_BP1 | SPI_FLASH_SR1_BP0)) >> + 2; /* Bad pointers or invalid data */ if (!start || !len || sr1 == 0xff || sr2 == 0xff) @@ -163,7 +164,7 @@ int spi_flash_protect_to_reg(unsigned int start, unsigned int len, uint8_t *sr1, return EC_ERROR_INVAL; /* Invalid data */ - if ((start && !len) || start + len > CONFIG_FLASH_SIZE) + if ((start && !len) || start + len > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; for (i = 0; i < ARRAY_SIZE(spi_flash_protect_ranges); ++i) { @@ -174,12 +175,10 @@ int spi_flash_protect_to_reg(unsigned int start, unsigned int len, uint8_t *sr1, sec = GET_BIT(range->sec); tb = GET_BIT(range->tb); bp = GET_BIT(range->bp[0]) << 2 | - GET_BIT(range->bp[1]) << 1 | - GET_BIT(range->bp[2]); + GET_BIT(range->bp[1]) << 1 | GET_BIT(range->bp[2]); *sr1 = (sec ? SPI_FLASH_SR1_SEC : 0) | - (tb ? SPI_FLASH_SR1_TB : 0) | - (bp << 2); + (tb ? SPI_FLASH_SR1_TB : 0) | (bp << 2); *sr2 = (cmp ? SPI_FLASH_SR2_CMP : 0); return EC_SUCCESS; } diff --git a/common/spi/flash_reg/src/spi_flash_reg_test.c b/common/spi/flash_reg/src/spi_flash_reg_test.c new file mode 100644 index 0000000000..b9a45476b1 --- /dev/null +++ b/common/spi/flash_reg/src/spi_flash_reg_test.c @@ -0,0 +1,98 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "spi_flash_reg.h" + +#include + +ZTEST_SUITE(flash_reg_to_protect, NULL, NULL, NULL, NULL, NULL); + +ZTEST(flash_reg_to_protect, test_invalid_args) +{ + unsigned int start = 0; + unsigned int len = 0; + + zassert_equal(EC_ERROR_INVAL, + spi_flash_reg_to_protect(0, 0, NULL, &len)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_reg_to_protect(0, 0, &start, NULL)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_reg_to_protect(0xff, 0, &start, &len)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_reg_to_protect(0, 0xff, &start, &len)); +} + +ZTEST(flash_reg_to_protect, test_no_matching_range) +{ + unsigned int start = 0; + unsigned int len = 0; + + /* Bad SR1 */ + zassert_equal(EC_ERROR_INVAL, + spi_flash_reg_to_protect(SPI_FLASH_SR1_BP0, 0, &start, + &len)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_reg_to_protect(SPI_FLASH_SR1_BP1, 0, &start, + &len)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_reg_to_protect(SPI_FLASH_SR1_BP2, 0, &start, + &len)); + + /* BAD SR2 */ + zassert_equal(EC_ERROR_INVAL, spi_flash_reg_to_protect( + SPI_FLASH_SR1_BP0, + SPI_FLASH_SR2_CMP, &start, &len)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_reg_to_protect(SPI_FLASH_SR1_SEC | + SPI_FLASH_SR1_BP0, + 0, &start, &len)); +} + +ZTEST(flash_reg_to_protect, test_matching_range) +{ + unsigned int start = 0; + unsigned int len = 0; + + zassert_equal(EC_SUCCESS, spi_flash_reg_to_protect(0, 0, &start, &len)); + zassert_equal(0, start); + zassert_equal(0, len); +} + +ZTEST_SUITE(flash_protect_to_reg, NULL, NULL, NULL, NULL, NULL); + +ZTEST(flash_protect_to_reg, test_invalid_args) +{ + uint8_t sr1; + uint8_t sr2; + + zassert_equal(EC_ERROR_INVAL, + spi_flash_protect_to_reg(0, 0, NULL, &sr2)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_protect_to_reg(0, 0, &sr1, NULL)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_protect_to_reg(128, 0, &sr1, &sr2)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_protect_to_reg(128, CONFIG_FLASH_SIZE_BYTES, + &sr1, &sr2)); + zassert_equal(EC_ERROR_INVAL, + spi_flash_protect_to_reg(128, 128, &sr1, &sr2)); +} + +ZTEST(flash_protect_to_reg, test_matching_range) +{ + uint8_t sr1; + uint8_t sr2; + + zassert_equal(EC_SUCCESS, + spi_flash_protect_to_reg(0, 0x400000, &sr1, &sr2)); + zassert_equal(0x38, sr1, "Expected 0x38, but got 0x%02x", sr1); + zassert_equal(0x00, sr2, "Expected 0x00, but got 0x%02x", sr2); + + zassert_equal(EC_SUCCESS, + spi_flash_protect_to_reg(0, 0x200000, &sr1, &sr2)); + zassert_equal(0x34, sr1, "Expected 0x38, but got 0x%02x", sr1); + zassert_equal(0x00, sr2, "Expected 0x00, but got 0x%02x", sr2); +} diff --git a/common/spi/flash_reg/testcase.yaml b/common/spi/flash_reg/testcase.yaml new file mode 100644 index 0000000000..95a71b1aae --- /dev/null +++ b/common/spi/flash_reg/testcase.yaml @@ -0,0 +1,8 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +tests: + spi.flash_reg: + tags: spi + type: unit diff --git a/common/spi_commands.c b/common/spi_commands.c index 1a70a5be82..9810039ede 100644 --- a/common/spi_commands.c +++ b/common/spi_commands.c @@ -1,5 +1,5 @@ /* - * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,11 +8,12 @@ #include "common.h" #include "console.h" +#include "printf.h" #include "spi.h" #include "timer.h" #include "util.h" -static int command_spixfer(int argc, char **argv) +static int command_spixfer(int argc, const char **argv) { int dev_id; uint8_t offset; @@ -45,8 +46,13 @@ static int command_spixfer(int argc, char **argv) rv = spi_transaction(&spi_devices[dev_id], &cmd, 1, data, v); - if (!rv) - ccprintf("Data: %ph\n", HEX_BUF(data, v)); + if (!rv) { + char str_buf[hex_str_buf_size(v)]; + + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(data, v)); + ccprintf("Data: %s\n", str_buf); + } } else if (strcasecmp(argv[1], "w") == 0) { /* 8-bit write */ @@ -68,4 +74,3 @@ static int command_spixfer(int argc, char **argv) DECLARE_CONSOLE_COMMAND(spixfer, command_spixfer, "rlen/w id offset [value | len]", "Read write spi. id is spi_devices array index"); - diff --git a/common/spi_flash.c b/common/spi_flash.c index 3f003052bf..1540c7bb33 100644 --- a/common/spi_flash.c +++ b/common/spi_flash.c @@ -1,13 +1,16 @@ /* - * Copyright 2014 The Chromium OS Authors. All rights reserved. + * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * SPI flash driver for Chrome EC. */ +#include "builtin/assert.h" #include "common.h" #include "console.h" +#include "ec_commands.h" +#include "flash.h" #include "host_command.h" #include "shared_mem.h" #include "spi.h" @@ -16,18 +19,16 @@ #include "timer.h" #include "util.h" #include "watchdog.h" -#include "ec_commands.h" -#include "flash.h" /* * Time to sleep when chip is busy */ -#define SPI_FLASH_SLEEP_USEC 100 +#define SPI_FLASH_SLEEP_USEC 100 /* * This is the max time for 32kb flash erase */ -#define SPI_FLASH_TIMEOUT_USEC (800*MSEC) +#define SPI_FLASH_TIMEOUT_USEC (800 * MSEC) /* Internal buffer used by SPI flash driver */ static uint8_t buf[SPI_FLASH_MAX_MESSAGE_SIZE]; @@ -109,12 +110,12 @@ uint8_t spi_flash_get_status2(void) */ int spi_flash_set_status(int reg1, int reg2) { - uint8_t cmd[3] = {SPI_FLASH_WRITE_SR, reg1, reg2}; + uint8_t cmd[3] = { SPI_FLASH_WRITE_SR, reg1, reg2 }; int rv = EC_SUCCESS; /* fail if both HW pin is asserted and SRP(s) is 1 */ if (spi_flash_check_wp() != SPI_WP_NONE && - (flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) != 0) + (crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) != 0) return EC_ERROR_ACCESS_DENIED; /* Enable writing to SPI flash */ @@ -122,7 +123,7 @@ int spi_flash_set_status(int reg1, int reg2) if (rv) return rv; - /* Second status register not present */ + /* Second status register not present */ #ifndef CONFIG_SPI_FLASH_HAS_SR2 reg2 = -1; #endif @@ -153,7 +154,7 @@ int spi_flash_read(uint8_t *buf_usr, unsigned int offset, unsigned int bytes) { int i, read_size, ret, spi_addr; uint8_t cmd[4]; - if (offset + bytes > CONFIG_FLASH_SIZE) + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; cmd[0] = SPI_FLASH_READ; for (i = 0; i < bytes; i += read_size) { @@ -162,14 +163,11 @@ int spi_flash_read(uint8_t *buf_usr, unsigned int offset, unsigned int bytes) cmd[2] = (spi_addr >> 8) & 0xFF; cmd[3] = spi_addr & 0xFF; read_size = MIN((bytes - i), SPI_FLASH_MAX_READ_SIZE); - ret = spi_transaction(SPI_FLASH_DEVICE, - cmd, - 4, - buf_usr + i, - read_size); + ret = spi_transaction(SPI_FLASH_DEVICE, cmd, 4, buf_usr + i, + read_size); if (ret != EC_SUCCESS) break; - msleep(1); + msleep(CONFIG_SPI_FLASH_READ_WAIT_MS); } return ret; } @@ -227,7 +225,7 @@ int spi_flash_erase(unsigned int offset, unsigned int bytes) int rv = EC_SUCCESS; /* Invalid input */ - if (offset + bytes > CONFIG_FLASH_SIZE) + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; /* Not aligned to sector (4kb) */ @@ -275,20 +273,22 @@ int spi_flash_erase(unsigned int offset, unsigned int bytes) * @return EC_SUCCESS, or non-zero if any error. */ int spi_flash_write(unsigned int offset, unsigned int bytes, - const uint8_t *data) + const uint8_t *data) { int rv, write_size; /* Invalid input */ - if (!data || offset + bytes > CONFIG_FLASH_SIZE || + if (!data || offset + bytes > CONFIG_FLASH_SIZE_BYTES || bytes > SPI_FLASH_MAX_WRITE_SIZE) return EC_ERROR_INVAL; while (bytes > 0) { watchdog_reload(); /* Write length can not go beyond the end of the flash page */ - write_size = MIN(bytes, SPI_FLASH_MAX_WRITE_SIZE - - (offset & (SPI_FLASH_MAX_WRITE_SIZE - 1))); + write_size = + MIN(bytes, + SPI_FLASH_MAX_WRITE_SIZE - + (offset & (SPI_FLASH_MAX_WRITE_SIZE - 1))); /* Wait for previous operation to complete */ rv = spi_flash_wait(); @@ -309,8 +309,8 @@ int spi_flash_write(unsigned int offset, unsigned int bytes, buf[2] = (offset) >> 8; buf[3] = offset; - rv = spi_transaction(SPI_FLASH_DEVICE, - buf, 4 + write_size, NULL, 0); + rv = spi_transaction(SPI_FLASH_DEVICE, buf, 4 + write_size, + NULL, 0); if (rv) return rv; @@ -344,7 +344,7 @@ int spi_flash_get_jedec_id(uint8_t *dest) */ int spi_flash_get_mfr_dev_id(uint8_t *dest) { - uint8_t cmd[4] = {SPI_FLASH_MFR_DEV_ID, 0, 0, 0}; + uint8_t cmd[4] = { SPI_FLASH_MFR_DEV_ID, 0, 0, 0 }; return spi_transaction(SPI_FLASH_DEVICE, cmd, sizeof(cmd), dest, 2); } @@ -357,7 +357,7 @@ int spi_flash_get_mfr_dev_id(uint8_t *dest) */ int spi_flash_get_unique_id(uint8_t *dest) { - uint8_t cmd[5] = {SPI_FLASH_UNIQUE_ID, 0, 0, 0, 0}; + uint8_t cmd[5] = { SPI_FLASH_UNIQUE_ID, 0, 0, 0, 0 }; return spi_transaction(SPI_FLASH_DEVICE, cmd, sizeof(cmd), dest, 8); } @@ -435,7 +435,8 @@ int spi_flash_check_protect(unsigned int offset, unsigned int bytes) int rv = EC_SUCCESS; /* Invalid value */ - if (sr1 == 0xff || sr2 == 0xff || offset + bytes > CONFIG_FLASH_SIZE) + if (sr1 == 0xff || sr2 == 0xff || + offset + bytes > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; /* Compute current protect range */ @@ -466,7 +467,8 @@ int spi_flash_set_protect(unsigned int offset, unsigned int bytes) uint8_t sr2 = spi_flash_get_status2(); /* Invalid values */ - if (sr1 == 0xff || sr2 == 0xff || offset + bytes > CONFIG_FLASH_SIZE) + if (sr1 == 0xff || sr2 == 0xff || + offset + bytes > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; /* Compute desired protect range */ @@ -477,13 +479,14 @@ int spi_flash_set_protect(unsigned int offset, unsigned int bytes) return spi_flash_set_status(sr1, sr2); } -static int command_spi_flashinfo(int argc, char **argv) +static int command_spi_flashinfo(int argc, const char **argv) { uint8_t jedec[3]; uint8_t unique[8]; int rv; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + /* TODO(tomhughes): use board function to get devices. */ + spi_enable(SPI_FLASH_DEVICE, 1); /* Wait for previous operation to complete */ rv = spi_flash_wait(); @@ -493,18 +496,17 @@ static int command_spi_flashinfo(int argc, char **argv) spi_flash_get_jedec_id(jedec); spi_flash_get_unique_id(unique); - ccprintf("Manufacturer ID: %02x\nDevice ID: %02x %02x\n", - jedec[0], jedec[1], jedec[2]); + ccprintf("Manufacturer ID: %02x\nDevice ID: %02x %02x\n", jedec[0], + jedec[1], jedec[2]); ccprintf("Unique ID: %02x %02x %02x %02x %02x %02x %02x %02x\n", - unique[0], unique[1], unique[2], unique[3], - unique[4], unique[5], unique[6], unique[7]); + unique[0], unique[1], unique[2], unique[3], unique[4], + unique[5], unique[6], unique[7]); ccprintf("Capacity: %4d kB\n", SPI_FLASH_SIZE(jedec[2]) / 1024); return rv; } -DECLARE_CONSOLE_COMMAND(spi_flashinfo, command_spi_flashinfo, - NULL, - "Print SPI flash info"); +DECLARE_CONSOLE_COMMAND(spi_flashinfo, command_spi_flashinfo, NULL, + "Print SPI flash info"); #ifdef CONFIG_HOSTCMD_FLASH_SPI_INFO static enum ec_status flash_command_spi_info(struct host_cmd_handler_args *args) @@ -520,13 +522,12 @@ static enum ec_status flash_command_spi_info(struct host_cmd_handler_args *args) args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_FLASH_SPI_INFO, - flash_command_spi_info, +DECLARE_HOST_COMMAND(EC_CMD_FLASH_SPI_INFO, flash_command_spi_info, EC_VER_MASK(0)); -#endif /* CONFIG_HOSTCMD_FLASH_SPI_INFO */ +#endif /* CONFIG_HOSTCMD_FLASH_SPI_INFO */ #ifdef CONFIG_CMD_SPI_FLASH -static int command_spi_flasherase(int argc, char **argv) +static int command_spi_flasherase(int argc, const char **argv) { int offset = -1; int bytes = 4096; @@ -535,7 +536,7 @@ static int command_spi_flasherase(int argc, char **argv) if (rv) return rv; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(SPI_FLASH_DEVICE, 1); /* Chip has protection */ if (spi_flash_check_protect(offset, bytes)) @@ -545,10 +546,9 @@ static int command_spi_flasherase(int argc, char **argv) return spi_flash_erase(offset, bytes); } DECLARE_CONSOLE_COMMAND(spi_flasherase, command_spi_flasherase, - "offset [bytes]", - "Erase flash"); + "offset [bytes]", "Erase flash"); -static int command_spi_flashwrite(int argc, char **argv) +static int command_spi_flashwrite(int argc, const char **argv) { int offset = -1; int bytes = SPI_FLASH_MAX_WRITE_SIZE; @@ -560,7 +560,7 @@ static int command_spi_flashwrite(int argc, char **argv) if (rv) return rv; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(SPI_FLASH_DEVICE, 1); /* Chip has protection */ if (spi_flash_check_protect(offset, bytes)) @@ -574,7 +574,8 @@ static int command_spi_flashwrite(int argc, char **argv) while (bytes > 0) { /* First write multiples of 256, then (bytes % 256) last */ write_len = ((bytes % SPI_FLASH_MAX_WRITE_SIZE) == bytes) ? - bytes : SPI_FLASH_MAX_WRITE_SIZE; + bytes : + SPI_FLASH_MAX_WRITE_SIZE; /* Perform write */ rv = spi_flash_write(offset, write_len, buf); @@ -590,10 +591,9 @@ static int command_spi_flashwrite(int argc, char **argv) return rv; } DECLARE_CONSOLE_COMMAND(spi_flashwrite, command_spi_flashwrite, - "offset [bytes]", - "Write pattern to flash"); + "offset [bytes]", "Write pattern to flash"); -static int command_spi_flashread(int argc, char **argv) +static int command_spi_flashread(int argc, const char **argv) { int i; int offset = -1; @@ -605,10 +605,10 @@ static int command_spi_flashread(int argc, char **argv) if (rv) return rv; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(SPI_FLASH_DEVICE, 1); /* Can't read past size of memory */ - if (offset + bytes > CONFIG_FLASH_SIZE) + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) return EC_ERROR_INVAL; /* Wait for previous operation to complete */ @@ -623,8 +623,8 @@ static int command_spi_flashread(int argc, char **argv) /* First read (bytes % 256), then in multiples of 256 */ read_len = (bytes % SPI_FLASH_MAX_READ_SIZE) ? - (bytes % SPI_FLASH_MAX_READ_SIZE) : - SPI_FLASH_MAX_READ_SIZE; + (bytes % SPI_FLASH_MAX_READ_SIZE) : + SPI_FLASH_MAX_READ_SIZE; rv = spi_flash_read(buf, offset, read_len); if (rv) @@ -647,24 +647,22 @@ static int command_spi_flashread(int argc, char **argv) ASSERT(bytes == 0); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(spi_flashread, command_spi_flashread, - "offset bytes", - "Read flash"); +DECLARE_CONSOLE_COMMAND(spi_flashread, command_spi_flashread, "offset bytes", + "Read flash"); -static int command_spi_flashread_sr(int argc, char **argv) +static int command_spi_flashread_sr(int argc, const char **argv) { - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(SPI_FLASH_DEVICE, 1); ccprintf("Status Register 1: 0x%02x\n", spi_flash_get_status1()); ccprintf("Status Register 2: 0x%02x\n", spi_flash_get_status2()); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(spi_flash_rsr, command_spi_flashread_sr, - NULL, - "Read status registers"); +DECLARE_CONSOLE_COMMAND(spi_flash_rsr, command_spi_flashread_sr, NULL, + "Read status registers"); -static int command_spi_flashwrite_sr(int argc, char **argv) +static int command_spi_flashwrite_sr(int argc, const char **argv) { int val1 = 0; int val2 = 0; @@ -673,17 +671,16 @@ static int command_spi_flashwrite_sr(int argc, char **argv) if (rv) return rv; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(SPI_FLASH_DEVICE, 1); ccprintf("Writing 0x%02x to status register 1, ", val1); ccprintf("0x%02x to status register 2...\n", val2); return spi_flash_set_status(val1, val2); } DECLARE_CONSOLE_COMMAND(spi_flash_wsr, command_spi_flashwrite_sr, - "value1 value2", - "Write to status registers"); + "value1 value2", "Write to status registers"); -static int command_spi_flashprotect(int argc, char **argv) +static int command_spi_flashprotect(int argc, const char **argv) { int val1 = 0; int val2 = 0; @@ -692,12 +689,12 @@ static int command_spi_flashprotect(int argc, char **argv) if (rv) return rv; - spi_enable(CONFIG_SPI_FLASH_PORT, 1); + spi_enable(SPI_FLASH_DEVICE, 1); - ccprintf("Setting protection for 0x%06x to 0x%06x\n", val1, val1+val2); + ccprintf("Setting protection for 0x%06x to 0x%06x\n", val1, + val1 + val2); return spi_flash_set_protect(val1, val2); } -DECLARE_CONSOLE_COMMAND(spi_flash_prot, command_spi_flashprotect, - "offset len", - "Set block protection"); +DECLARE_CONSOLE_COMMAND(spi_flash_prot, command_spi_flashprotect, "offset len", + "Set block protection"); #endif diff --git a/common/spi_nor.c b/common/spi_nor.c index 4fda9f41e1..1eca5d806f 100644 --- a/common/spi_nor.c +++ b/common/spi_nor.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,18 +7,18 @@ #include "common.h" #include "console.h" -#include "spi_nor.h" +#include "sfdp.h" #include "shared_mem.h" -#include "util.h" -#include "task.h" #include "spi.h" -#include "sfdp.h" +#include "spi_nor.h" +#include "task.h" #include "timer.h" +#include "util.h" #include "watchdog.h" #ifdef CONFIG_SPI_NOR_DEBUG #define CPRINTS(dev, string, args...) \ - cprints(CC_SPI, "SPI NOR %s: " string, (dev)->name, ## args) + cprints(CC_SPI, "SPI NOR %s: " string, (dev)->name, ##args) #else #define CPRINTS(dev, string, args...) #endif @@ -60,7 +60,7 @@ static int spi_nor_read_status(const struct spi_nor_device_t *spi_nor_device, { uint8_t cmd = SPI_NOR_OPCODE_READ_STATUS; - return spi_transaction(&spi_devices[spi_nor_device->spi_master], + return spi_transaction(&spi_devices[spi_nor_device->spi_controller], &cmd, 1, status_register_value, 1); } @@ -74,8 +74,8 @@ static int spi_nor_write_enable(const struct spi_nor_device_t *spi_nor_device) int rv = EC_SUCCESS; /* Set the write enable latch. */ - rv = spi_transaction(&spi_devices[spi_nor_device->spi_master], - &cmd, 1, NULL, 0); + rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller], &cmd, + 1, NULL, 0); if (rv) return rv; @@ -84,7 +84,7 @@ static int spi_nor_write_enable(const struct spi_nor_device_t *spi_nor_device) if (rv) return rv; if ((status_register_value & SPI_NOR_STATUS_REGISTER_WEL) == 0) - return EC_ERROR_UNKNOWN; /* WEL not set but should be. */ + return EC_ERROR_UNKNOWN; /* WEL not set but should be. */ return rv; } @@ -100,8 +100,8 @@ static int spi_nor_read_ear(const struct spi_nor_device_t *spi_nor_device, { uint8_t command = SPI_NOR_OPCODE_RDEAR; - return spi_transaction(&spi_devices[spi_nor_device->spi_master], - &command, sizeof(command), value, 1); + return spi_transaction(&spi_devices[spi_nor_device->spi_controller], + &command, sizeof(command), value, 1); } int spi_nor_write_ear(const struct spi_nor_device_t *spi_nor_device, @@ -122,8 +122,8 @@ int spi_nor_write_ear(const struct spi_nor_device_t *spi_nor_device, buf[0] = SPI_NOR_OPCODE_WREAR; buf[1] = value; - rv = spi_transaction(&spi_devices[spi_nor_device->spi_master], - buf, sizeof(buf), NULL, 0); + rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller], buf, + sizeof(buf), NULL, 0); if (rv) { CPRINTS(spi_nor_device, "Failed to write EAR, rv=%d", rv); goto err_free; @@ -134,9 +134,9 @@ int spi_nor_write_ear(const struct spi_nor_device_t *spi_nor_device, goto err_free; if (ear != value) { - CPRINTS(spi_nor_device, - "Write EAR error: write=%d, read=%d", value, ear); - rv = EC_ERROR_UNKNOWN; /* WEL not set but should be. */ + CPRINTS(spi_nor_device, "Write EAR error: write=%d, read=%d", + value, ear); + rv = EC_ERROR_UNKNOWN; /* WEL not set but should be. */ goto err_free; } @@ -157,8 +157,7 @@ static int spi_nor_wait(const struct spi_nor_device_t *spi_nor_device) rv = spi_nor_read_status(spi_nor_device, &status_register_value); if (rv) return rv; - timeout.val = - get_time().val + spi_nor_device->timeout_usec; + timeout.val = get_time().val + spi_nor_device->timeout_usec; while (status_register_value & SPI_NOR_STATUS_REGISTER_WIP) { /* Reload the watchdog before sleeping. */ watchdog_reload(); @@ -181,10 +180,9 @@ static int spi_nor_wait(const struct spi_nor_device_t *spi_nor_device) /** * Read the Manufacturer bank and ID out of the JEDEC ID. */ -static int spi_nor_read_jedec_mfn_id( - const struct spi_nor_device_t *spi_nor_device, - uint8_t *out_mfn_bank, - uint8_t *out_mfn_id) +static int +spi_nor_read_jedec_mfn_id(const struct spi_nor_device_t *spi_nor_device, + uint8_t *out_mfn_bank, uint8_t *out_mfn_id) { int rv = EC_SUCCESS; uint8_t jedec_id[SPI_NOR_JEDEC_ID_BANKS]; @@ -192,8 +190,8 @@ static int spi_nor_read_jedec_mfn_id( uint8_t cmd = SPI_NOR_OPCODE_JEDEC_ID; /* Read the standardized part of the JEDEC ID. */ - rv = spi_transaction(&spi_devices[spi_nor_device->spi_master], - &cmd, 1, jedec_id, SPI_NOR_JEDEC_ID_BANKS); + rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller], &cmd, + 1, jedec_id, SPI_NOR_JEDEC_ID_BANKS); if (rv) return rv; @@ -214,11 +212,11 @@ static int spi_nor_read_jedec_mfn_id( /** * Read a doubleword out of a SFDP table (DWs are 1-based like the SFDP spec). */ -static int spi_nor_read_sfdp_dword( - const struct spi_nor_device_t *spi_nor_device, - uint32_t table_offset, - uint8_t table_double_word, - uint32_t *out_dw) { +static int +spi_nor_read_sfdp_dword(const struct spi_nor_device_t *spi_nor_device, + uint32_t table_offset, uint8_t table_double_word, + uint32_t *out_dw) +{ uint8_t sfdp_cmd[5]; /* Calculate the byte offset based on the double word. */ uint32_t sfdp_offset = table_offset + ((table_double_word - 1) * 4); @@ -228,8 +226,8 @@ static int spi_nor_read_sfdp_dword( sfdp_cmd[1] = (sfdp_offset & 0xFF0000) >> 16; sfdp_cmd[2] = (sfdp_offset & 0xFF00) >> 8; sfdp_cmd[3] = (sfdp_offset & 0xFF); - sfdp_cmd[4] = 0; /* Required extra cycle. */ - return spi_transaction(&spi_devices[spi_nor_device->spi_master], + sfdp_cmd[4] = 0; /* Required extra cycle. */ + return spi_transaction(&spi_devices[spi_nor_device->spi_controller], sfdp_cmd, 5, (uint8_t *)out_dw, 4); } @@ -248,10 +246,10 @@ static int is_basic_flash_parameter_table(uint8_t sfdp_major_rev, BASIC_FLASH_PARAMETER_TABLE_1_0_ID); } else if (sfdp_major_rev == 1 && sfdp_minor_rev >= 5) { return ((SFDP_GET_BITFIELD(SFDP_1_5_PARAMETER_HEADER_DW1_ID_LSB, - parameter_header_dw1) == + parameter_header_dw1) == BASIC_FLASH_PARAMETER_TABLE_1_5_ID_LSB) && (SFDP_GET_BITFIELD(SFDP_1_5_PARAMETER_HEADER_DW2_ID_MSB, - parameter_header_dw2) == + parameter_header_dw2) == BASIC_FLASH_PARAMETER_TABLE_1_5_ID_MSB)); } @@ -262,13 +260,10 @@ static int is_basic_flash_parameter_table(uint8_t sfdp_major_rev, * Helper function to locate the SFDP Basic SPI Flash NOR Parameter Table. */ static int locate_sfdp_basic_parameter_table( - const struct spi_nor_device_t *spi_nor_device, - uint8_t *out_sfdp_major_rev, - uint8_t *out_sfdp_minor_rev, - uint8_t *out_table_major_rev, - uint8_t *out_table_minor_rev, - uint32_t *out_table_offset, - size_t *out_table_size) + const struct spi_nor_device_t *spi_nor_device, + uint8_t *out_sfdp_major_rev, uint8_t *out_sfdp_minor_rev, + uint8_t *out_table_major_rev, uint8_t *out_table_minor_rev, + uint32_t *out_table_offset, size_t *out_table_size) { int rv = EC_SUCCESS; uint8_t number_parameter_headers; @@ -296,8 +291,8 @@ static int locate_sfdp_basic_parameter_table( SFDP_GET_BITFIELD(SFDP_HEADER_DW2_SFDP_MAJOR, dw2); *out_sfdp_minor_rev = SFDP_GET_BITFIELD(SFDP_HEADER_DW2_SFDP_MINOR, dw2); - CPRINTS(spi_nor_device, "SFDP v%d.%d discovered", - *out_sfdp_major_rev, *out_sfdp_minor_rev); + CPRINTS(spi_nor_device, "SFDP v%d.%d discovered", *out_sfdp_major_rev, + *out_sfdp_minor_rev); /* NPH is 0-based, so add 1. */ number_parameter_headers = @@ -315,17 +310,16 @@ static int locate_sfdp_basic_parameter_table( number_parameter_headers--; /* Read this parameter header's two dwords. */ - rv = spi_nor_read_sfdp_dword( - spi_nor_device, table_offset, 1, &dw1); - rv |= spi_nor_read_sfdp_dword( - spi_nor_device, table_offset, 2, &dw2); + rv = spi_nor_read_sfdp_dword(spi_nor_device, table_offset, 1, + &dw1); + rv |= spi_nor_read_sfdp_dword(spi_nor_device, table_offset, 2, + &dw2); if (rv) return rv; /* Ensure it's the basic flash parameter table. */ - if (!is_basic_flash_parameter_table(*out_sfdp_major_rev, - *out_sfdp_minor_rev, - dw1, dw2)) + if (!is_basic_flash_parameter_table( + *out_sfdp_major_rev, *out_sfdp_minor_rev, dw1, dw2)) continue; /* The parameter header major and minor versioning is still the @@ -352,8 +346,10 @@ static int locate_sfdp_basic_parameter_table( *out_table_offset = SFDP_GET_BITFIELD( SFDP_1_0_PARAMETER_HEADER_DW2_PTP, dw2); /* Convert the size from DW to Bytes. */ - *out_table_size = SFDP_GET_BITFIELD( - SFDP_1_0_PARAMETER_HEADER_DW1_PTL, dw1) * 4; + *out_table_size = + SFDP_GET_BITFIELD(SFDP_1_0_PARAMETER_HEADER_DW1_PTL, + dw1) * + 4; } if (!table_found) { @@ -376,8 +372,7 @@ static int spi_nor_device_discover_sfdp_page_size( struct spi_nor_device_t *spi_nor_device, uint8_t basic_parameter_table_major_version, uint8_t basic_parameter_table_minor_version, - uint32_t basic_parameter_table_offset, - size_t *page_size) + uint32_t basic_parameter_table_offset, size_t *page_size) { int rv = EC_SUCCESS; uint32_t dw; @@ -397,12 +392,12 @@ static int spi_nor_device_discover_sfdp_page_size( } else if (basic_parameter_table_major_version == 1 && basic_parameter_table_minor_version >= 5) { /* Use the Basic Flash Parameter v1.5 page size reporting. */ - rv = spi_nor_read_sfdp_dword(spi_nor_device, - basic_parameter_table_offset, 11, &dw); + rv = spi_nor_read_sfdp_dword( + spi_nor_device, basic_parameter_table_offset, 11, &dw); if (rv) return rv; - *page_size = - 1 << SFDP_GET_BITFIELD(BFPT_1_5_DW11_PAGE_SIZE, dw); + *page_size = 1 + << SFDP_GET_BITFIELD(BFPT_1_5_DW11_PAGE_SIZE, dw); } return EC_SUCCESS; @@ -413,11 +408,10 @@ static int spi_nor_device_discover_sfdp_page_size( * NOR Parameter Table. */ static int spi_nor_device_discover_sfdp_capacity( - struct spi_nor_device_t *spi_nor_device, - uint8_t basic_parameter_table_major_version, - uint8_t basic_parameter_table_minor_version, - uint32_t basic_parameter_table_offset, - uint32_t *capacity) + struct spi_nor_device_t *spi_nor_device, + uint8_t basic_parameter_table_major_version, + uint8_t basic_parameter_table_minor_version, + uint32_t basic_parameter_table_offset, uint32_t *capacity) { int rv = EC_SUCCESS; uint32_t dw; @@ -425,15 +419,16 @@ static int spi_nor_device_discover_sfdp_capacity( /* First attempt to discover the device's capacity. */ if (basic_parameter_table_major_version == 1) { /* Use the Basic Flash Parameter v1.0 capacity reporting. */ - rv = spi_nor_read_sfdp_dword(spi_nor_device, - basic_parameter_table_offset, 2, &dw); + rv = spi_nor_read_sfdp_dword( + spi_nor_device, basic_parameter_table_offset, 2, &dw); if (rv) return rv; if (SFDP_GET_BITFIELD(BFPT_1_0_DW2_GT_2_GIBIBITS, dw)) { /* Ensure the capacity is less than 4GiB. */ - uint64_t tmp_capacity = 1 << - (SFDP_GET_BITFIELD(BFPT_1_0_DW2_N, dw) - 3); + uint64_t tmp_capacity = + 1 + << (SFDP_GET_BITFIELD(BFPT_1_0_DW2_N, dw) - 3); if (tmp_capacity > UINT32_MAX) return EC_ERROR_OVERFLOW; *capacity = tmp_capacity; @@ -456,8 +451,7 @@ static int spi_nor_read_internal(const struct spi_nor_device_t *spi_nor_device, * is larger than the maximum read size. */ while (size > 0) { - size_t read_size = - MIN(size, CONFIG_SPI_NOR_MAX_READ_SIZE); + size_t read_size = MIN(size, CONFIG_SPI_NOR_MAX_READ_SIZE); size_t read_command_size; /* Set up the read command in the TX buffer. */ @@ -468,15 +462,16 @@ static int spi_nor_read_internal(const struct spi_nor_device_t *spi_nor_device, buf[3] = (offset & 0xFF00) >> 8; buf[4] = (offset & 0xFF); read_command_size = 5; - } else { /* in 3 byte addressing mode */ + } else { /* in 3 byte addressing mode */ buf[1] = (offset & 0xFF0000) >> 16; buf[2] = (offset & 0xFF00) >> 8; buf[3] = (offset & 0xFF); read_command_size = 4; } - rv = spi_transaction(&spi_devices[spi_nor_device->spi_master], - buf, read_command_size, data, read_size); + rv = spi_transaction( + &spi_devices[spi_nor_device->spi_controller], buf, + read_command_size, data, read_size); if (rv) return rv; @@ -512,16 +507,12 @@ int spi_nor_init(void) uint8_t table_major_rev, table_minor_rev; uint32_t table_offset; size_t table_size; - struct spi_nor_device_t *spi_nor_device = - &spi_nor_devices[i]; + struct spi_nor_device_t *spi_nor_device = &spi_nor_devices[i]; - rv |= locate_sfdp_basic_parameter_table(spi_nor_device, - &sfdp_major_rev, - &sfdp_minor_rev, - &table_major_rev, - &table_minor_rev, - &table_offset, - &table_size); + rv |= locate_sfdp_basic_parameter_table( + spi_nor_device, &sfdp_major_rev, &sfdp_minor_rev, + &table_major_rev, &table_minor_rev, &table_offset, + &table_size); /* If we failed to find a compatible SFDP Basic Flash Parameter * table, use the default capacity, page size, and addressing @@ -531,13 +522,11 @@ int spi_nor_init(void) uint32_t capacity = 0; rv |= spi_nor_device_discover_sfdp_page_size( - spi_nor_device, - table_major_rev, table_minor_rev, table_offset, - &page_size); + spi_nor_device, table_major_rev, + table_minor_rev, table_offset, &page_size); rv |= spi_nor_device_discover_sfdp_capacity( - spi_nor_device, - table_major_rev, table_minor_rev, table_offset, - &capacity); + spi_nor_device, table_major_rev, + table_minor_rev, table_offset, &capacity); if (rv == EC_SUCCESS) { mutex_lock(&driver_mutex); spi_nor_device->capacity = capacity; @@ -566,9 +555,9 @@ int spi_nor_init(void) * * WARNING: * 1) In 3 Byte addressing mode only 16MiB of Serial NOR Flash is accessible. - * 2) If there's a second SPI master communicating with this Serial NOR Flash - * part on the board, the user is responsible for ensuring addressing mode - * compatibility and cooperation. + * 2) If there's a second SPI controller communicating with this Serial + * NOR Flash part on the board, the user is responsible for ensuring + * addressing mode compatibility and cooperation. * 3) The user must ensure that multiple users do not trample on each other * by having multiple parties changing the device's addressing mode. * @@ -594,8 +583,8 @@ int spi_nor_set_4b_mode(struct spi_nor_device_t *spi_nor_device, /* Claim the driver mutex to modify the device state. */ mutex_lock(&driver_mutex); - rv = spi_transaction(&spi_devices[spi_nor_device->spi_master], - &cmd, 1, NULL, 0); + rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller], &cmd, + 1, NULL, 0); if (rv == EC_SUCCESS) { spi_nor_device->in_4b_addressing_mode = enter_4b_addressing_mode; @@ -618,7 +607,8 @@ int spi_nor_set_4b_mode(struct spi_nor_device_t *spi_nor_device, * @return ec_error_list (non-zero on error and timeout). */ int spi_nor_read_jedec_id(const struct spi_nor_device_t *spi_nor_device, - size_t size, uint8_t *data) { + size_t size, uint8_t *data) +{ int rv; uint8_t cmd = SPI_NOR_OPCODE_JEDEC_ID; @@ -627,8 +617,8 @@ int spi_nor_read_jedec_id(const struct spi_nor_device_t *spi_nor_device, /* Claim the driver mutex. */ mutex_lock(&driver_mutex); /* Read the JEDEC ID. */ - rv = spi_transaction(&spi_devices[spi_nor_device->spi_master], - &cmd, 1, data, size); + rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller], &cmd, + 1, data, size); /* Release the driver mutex. */ mutex_unlock(&driver_mutex); @@ -644,8 +634,8 @@ int spi_nor_read_jedec_id(const struct spi_nor_device_t *spi_nor_device, * @param data Destination buffer for data. * @return ec_error_list (non-zero on error and timeout). */ -int spi_nor_read(const struct spi_nor_device_t *spi_nor_device, - uint32_t offset, size_t size, uint8_t *data) +int spi_nor_read(const struct spi_nor_device_t *spi_nor_device, uint32_t offset, + size_t size, uint8_t *data) { int rv; @@ -707,8 +697,8 @@ int spi_nor_erase(const struct spi_nor_device_t *spi_nor_device, read_offset = offset; read_left = erase_size; while (read_left) { - read_size = MIN(read_left, - CONFIG_SPI_NOR_MAX_READ_SIZE); + read_size = + MIN(read_left, CONFIG_SPI_NOR_MAX_READ_SIZE); /* Since CONFIG_SPI_NOR_MAX_READ_SIZE & erase_size are * both guaranteed to be multiples of 4. */ @@ -730,8 +720,8 @@ int spi_nor_erase(const struct spi_nor_device_t *spi_nor_device, */ verify_offset = 0; while (verify_offset <= read_size - 4) { - if (*(uint32_t *)(buffer + verify_offset) - != 0xffffffff) { + if (*(uint32_t *)(buffer + verify_offset) != + 0xffffffff) { break; } verify_offset += 4; @@ -766,7 +756,7 @@ int spi_nor_erase(const struct spi_nor_device_t *spi_nor_device, buf[3] = (offset & 0xFF00) >> 8; buf[4] = (offset & 0xFF); erase_command_size = 5; - } else { /* in 3 byte addressing mode */ + } else { /* in 3 byte addressing mode */ buf[1] = (offset & 0xFF0000) >> 16; buf[2] = (offset & 0xFF00) >> 8; buf[3] = (offset & 0xFF); @@ -774,8 +764,8 @@ int spi_nor_erase(const struct spi_nor_device_t *spi_nor_device, } rv = spi_transaction( - &spi_devices[spi_nor_device->spi_master], - buf, erase_command_size, NULL, 0); + &spi_devices[spi_nor_device->spi_controller], buf, + erase_command_size, NULL, 0); if (rv) goto err_free; @@ -813,8 +803,8 @@ int spi_nor_write(const struct spi_nor_device_t *spi_nor_device, /* Ensure the device's page size fits in the driver's buffer, if not * emulate a smaller page size based on the buffer size. */ - effective_page_size = MIN(spi_nor_device->page_size, - CONFIG_SPI_NOR_MAX_WRITE_SIZE); + effective_page_size = + MIN(spi_nor_device->page_size, CONFIG_SPI_NOR_MAX_WRITE_SIZE); /* Split the write into multiple writes if the size is too large. */ while (size > 0) { @@ -842,7 +832,7 @@ int spi_nor_write(const struct spi_nor_device_t *spi_nor_device, buf[3] = (offset & 0xFF00) >> 8; buf[4] = (offset & 0xFF); prefix_size = 5; - } else { /* in 3 byte addressing mode */ + } else { /* in 3 byte addressing mode */ buf[1] = (offset & 0xFF0000) >> 16; buf[2] = (offset & 0xFF00) >> 8; buf[3] = (offset & 0xFF); @@ -851,8 +841,9 @@ int spi_nor_write(const struct spi_nor_device_t *spi_nor_device, /* Copy data to write into the buffer after the prefix. */ memmove(buf + prefix_size, data, write_size); - rv = spi_transaction(&spi_devices[spi_nor_device->spi_master], - buf, prefix_size + write_size, NULL, 0); + rv = spi_transaction( + &spi_devices[spi_nor_device->spi_controller], buf, + prefix_size + write_size, NULL, 0); if (rv) goto err_free; @@ -875,7 +866,7 @@ int spi_nor_write(const struct spi_nor_device_t *spi_nor_device, /* Serial NOR Flash console commands. */ #ifdef CONFIG_CMD_SPI_NOR -static int command_spi_nor_info(int argc, char **argv) +static int command_spi_nor_info(int argc, const char **argv) { int rv = EC_SUCCESS; @@ -904,16 +895,15 @@ static int command_spi_nor_info(int argc, char **argv) ccprintf("Serial NOR Flash Device %d:\n", spi_nor_device_index); ccprintf("\tName: %s\n", spi_nor_device->name); - ccprintf("\tSPI master index: %d\n", - spi_nor_device->spi_master); - ccprintf("\tTimeout: %d uSec\n", - spi_nor_device->timeout_usec); + ccprintf("\tSPI controller index: %d\n", + spi_nor_device->spi_controller); + ccprintf("\tTimeout: %d uSec\n", spi_nor_device->timeout_usec); ccprintf("\tCapacity: %d KiB\n", spi_nor_device->capacity >> 10), - ccprintf("\tAddressing: %s addressing mode\n", - spi_nor_device->in_4b_addressing_mode ? "4B" : "3B"); - ccprintf("\tPage Size: %d Bytes\n", - spi_nor_device->page_size); + ccprintf("\tAddressing: %s addressing mode\n", + spi_nor_device->in_4b_addressing_mode ? "4B" : + "3B"); + ccprintf("\tPage Size: %d Bytes\n", spi_nor_device->page_size); /* Get JEDEC ID info. */ rv = spi_nor_read_jedec_mfn_id(spi_nor_device, &mfn_bank, @@ -925,27 +915,26 @@ static int command_spi_nor_info(int argc, char **argv) /* Get SFDP info. */ if (locate_sfdp_basic_parameter_table( - spi_nor_device, &sfdp_major_rev, &sfdp_minor_rev, - &table_major_rev, &table_minor_rev, &table_offset, - &table_size) != EC_SUCCESS) { + spi_nor_device, &sfdp_major_rev, &sfdp_minor_rev, + &table_major_rev, &table_minor_rev, &table_offset, + &table_size) != EC_SUCCESS) { ccputs("\tNo JEDEC SFDP support detected\n"); - continue; /* Go on to the next device. */ + continue; /* Go on to the next device. */ } ccprintf("\tSFDP v%d.%d\n", sfdp_major_rev, sfdp_minor_rev); ccprintf("\tFlash Parameter Table v%d.%d (%dB @ 0x%x)\n", - table_major_rev, table_minor_rev, - table_size, table_offset); + table_major_rev, table_minor_rev, table_size, + table_offset); } return rv; } -DECLARE_CONSOLE_COMMAND(spinorinfo, command_spi_nor_info, - "[device]", +DECLARE_CONSOLE_COMMAND(spinorinfo, command_spi_nor_info, "[device]", "Report Serial NOR Flash device information"); -#endif /* CONFIG_CMD_SPI_NOR */ +#endif /* CONFIG_CMD_SPI_NOR */ #ifdef CONFIG_CMD_SPI_NOR -static int command_spi_nor_erase(int argc, char **argv) +static int command_spi_nor_erase(int argc, const char **argv) { const struct spi_nor_device_t *spi_nor_device; int spi_nor_device_index; @@ -965,17 +954,16 @@ static int command_spi_nor_erase(int argc, char **argv) if (rv) return rv; - ccprintf("Erasing %d bytes at 0x%x on %s...\n", - size, offset, spi_nor_device->name); + ccprintf("Erasing %d bytes at 0x%x on %s...\n", size, offset, + spi_nor_device->name); return spi_nor_erase(spi_nor_device, offset, size); } DECLARE_CONSOLE_COMMAND(spinorerase, command_spi_nor_erase, - "device [offset] [size]", - "Erase flash"); -#endif /* CONFIG_CMD_SPI_NOR */ + "device [offset] [size]", "Erase flash"); +#endif /* CONFIG_CMD_SPI_NOR */ #ifdef CONFIG_CMD_SPI_NOR -static int command_spi_nor_write(int argc, char **argv) +static int command_spi_nor_write(int argc, const char **argv) { const struct spi_nor_device_t *spi_nor_device; int spi_nor_device_index; @@ -1011,8 +999,8 @@ static int command_spi_nor_write(int argc, char **argv) for (i = 0; i < size; i++) data[i] = i; - ccprintf("Writing %d bytes to 0x%x on %s...\n", - size, offset, spi_nor_device->name); + ccprintf("Writing %d bytes to 0x%x on %s...\n", size, offset, + spi_nor_device->name); rv = spi_nor_write(spi_nor_device, offset, size, data); /* Free the buffer */ @@ -1021,12 +1009,11 @@ static int command_spi_nor_write(int argc, char **argv) return rv; } DECLARE_CONSOLE_COMMAND(spinorwrite, command_spi_nor_write, - "device [offset] [size]", - "Write pattern to flash"); -#endif /* CONFIG_CMD_SPI_NOR */ + "device [offset] [size]", "Write pattern to flash"); +#endif /* CONFIG_CMD_SPI_NOR */ #ifdef CONFIG_CMD_SPI_NOR -static int command_spi_nor_read(int argc, char **argv) +static int command_spi_nor_read(int argc, const char **argv) { const struct spi_nor_device_t *spi_nor_device; int spi_nor_device_index; @@ -1059,8 +1046,7 @@ static int command_spi_nor_read(int argc, char **argv) } /* Read the data */ - ccprintf("Reading %d bytes from %s...", - size, spi_nor_device->name); + ccprintf("Reading %d bytes from %s...", size, spi_nor_device->name); if (spi_nor_read(spi_nor_device, offset, size, data)) { rv = EC_ERROR_INVAL; goto err_free; @@ -1084,6 +1070,5 @@ static int command_spi_nor_read(int argc, char **argv) return rv; } DECLARE_CONSOLE_COMMAND(spinorread, command_spi_nor_read, - "device [offset] [size]", - "Read flash"); -#endif /* CONFIG_CMD_SPI_NOR */ + "device [offset] [size]", "Read flash"); +#endif /* CONFIG_CMD_SPI_NOR */ diff --git a/common/stillness_detector.c b/common/stillness_detector.c index c33472aa22..f81c51ef3a 100644 --- a/common/stillness_detector.c +++ b/common/stillness_detector.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,7 @@ #include "common.h" #include "stillness_detector.h" #include "timer.h" + #include static void still_det_reset(struct still_det *still_det) @@ -23,8 +24,8 @@ static bool stillness_batch_complete(struct still_det *still_det, uint32_t sample_time) { bool complete = false; - uint32_t batch_window = time_until(still_det->window_start_time, - sample_time); + uint32_t batch_window = + time_until(still_det->window_start_time, sample_time); /* Checking if enough data is accumulated */ if (batch_window >= still_det->min_batch_window && @@ -51,8 +52,8 @@ static inline fp_t compute_variance(fp_t acc_squared, fp_t acc, fp_t inv) return fp_mul((acc_squared - fp_mul(fp_sq(acc), inv)), inv); } -bool still_det_update(struct still_det *still_det, uint32_t sample_time, - fp_t x, fp_t y, fp_t z) +bool still_det_update(struct still_det *still_det, uint32_t sample_time, fp_t x, + fp_t y, fp_t z) { fp_t inv = FLOAT_TO_FP(0.0f), var_x, var_y, var_z; bool complete = false; @@ -88,12 +89,12 @@ bool still_det_update(struct still_det *still_det, uint32_t sample_time, return complete; } /* Calculating the VAR = sum(x^2)/n - sum(x)^2/n^2 */ - var_x = compute_variance( - still_det->acc_xx, still_det->acc_x, inv); - var_y = compute_variance( - still_det->acc_yy, still_det->acc_y, inv); - var_z = compute_variance( - still_det->acc_zz, still_det->acc_z, inv); + var_x = compute_variance(still_det->acc_xx, still_det->acc_x, + inv); + var_y = compute_variance(still_det->acc_yy, still_det->acc_y, + inv); + var_z = compute_variance(still_det->acc_zz, still_det->acc_z, + inv); /* Checking if sensor is still */ if (var_x < still_det->var_threshold && var_y < still_det->var_threshold && diff --git a/common/switch.c b/common/switch.c index ea07efbca0..f2a3266ed0 100644 --- a/common/switch.c +++ b/common/switch.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,10 +15,11 @@ #include "power_button.h" #include "switch.h" #include "util.h" +#include "write_protect.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_SWITCH, outstr) -#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ##args) static uint8_t *memmap_switches; @@ -43,17 +44,12 @@ static void switch_update(void) else *memmap_switches &= ~EC_SWITCH_POWER_BUTTON_PRESSED; -#ifdef CONFIG_LID_SWITCH - if (lid_is_open()) + if (!IS_ENABLED(CONFIG_LID_SWITCH) || lid_is_open()) *memmap_switches |= EC_SWITCH_LID_OPEN; else *memmap_switches &= ~EC_SWITCH_LID_OPEN; -#else - /* For lid-less systems, lid looks always open */ - *memmap_switches |= EC_SWITCH_LID_OPEN; -#endif - if ((flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) == 0) + if ((crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) == 0) *memmap_switches |= EC_SWITCH_WRITE_PROTECT_DISABLED; else *memmap_switches &= ~EC_SWITCH_WRITE_PROTECT_DISABLED; @@ -93,11 +89,7 @@ static void switch_init(void) * reading the write protect signal, but we enable the interrupt for it * here. Take ownership of WP back, or refactor it to its own module. */ -#ifdef CONFIG_WP_ACTIVE_HIGH - gpio_enable_interrupt(GPIO_WP); -#else - gpio_enable_interrupt(GPIO_WP_L); -#endif + write_protect_enable_interrupt(); } DECLARE_HOOK(HOOK_INIT, switch_init, HOOK_PRIO_INIT_SWITCH); @@ -107,18 +99,14 @@ void switch_interrupt(enum gpio_signal signal) } #ifdef CONFIG_CMD_MMAPINFO -static int command_mmapinfo(int argc, char **argv) +static int command_mmapinfo(int argc, const char **argv) { uint8_t *memmap_switches = host_get_memmap(EC_MEMMAP_SWITCHES); uint8_t val = *memmap_switches; int i; const char *explanation[] = { - "lid_open", - "powerbtn", - "wp_off", - "kbd_rec", - "gpio_rec", - "fake_dev", + "lid_open", "powerbtn", "wp_off", + "kbd_rec", "gpio_rec", "fake_dev", }; ccprintf("memmap switches = 0x%x\n", val); for (i = 0; i < ARRAY_SIZE(explanation); i++) @@ -127,7 +115,6 @@ static int command_mmapinfo(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(mmapinfo, command_mmapinfo, - NULL, +DECLARE_CONSOLE_COMMAND(mmapinfo, command_mmapinfo, NULL, "Print memmap switch state"); #endif diff --git a/common/system.c b/common/system.c index 206f74181c..6c2acc3bfc 100644 --- a/common/system.c +++ b/common/system.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,6 +13,7 @@ #include "cpu.h" #include "cros_board_info.h" #include "dma.h" +#include "extpower.h" #include "flash.h" #include "gpio.h" #include "hooks.h" @@ -26,31 +27,32 @@ #ifdef CONFIG_MPU #include "mpu.h" #endif +#include "cros_version.h" #include "panic.h" #include "sysjump.h" #include "system.h" +#include "system_boot_time.h" #include "task.h" #include "timer.h" #include "uart.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" -#include "version.h" #include "watchdog.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /* Round up to a multiple of 4 */ #define ROUNDUP4(x) (((x) + 3) & ~3) /* Data for an individual jump tag */ struct jump_tag { - uint16_t tag; /* Tag ID */ - uint8_t data_size; /* Size of data which follows */ - uint8_t data_version; /* Data version */ + uint16_t tag; /* Tag ID */ + uint8_t data_size; /* Size of data which follows */ + uint8_t data_version; /* Data version */ /* Followed by data_size bytes of data */ }; @@ -58,33 +60,37 @@ struct jump_tag { /* Jump data (at end of RAM, or preceding panic data) */ static struct jump_data *jdata; -static uint32_t reset_flags; +static uint32_t reset_flags; /* EC_RESET_FLAG_* */ static int jumped_to_image; -static int disable_jump; /* Disable ALL jumps if system is locked */ -static int force_locked; /* Force system locked even if WP isn't enabled */ -static enum ec_reboot_cmd reboot_at_shutdown; +static int disable_jump; /* Disable ALL jumps if system is locked */ +static int force_locked; /* Force system locked even if WP isn't enabled */ +static struct ec_params_reboot_ec reboot_at_shutdown; + +static enum sysinfo_flags system_info_flags; + +/* Ensure enough space for panic_data, jump_data and at least one jump tag */ +BUILD_ASSERT((sizeof(struct panic_data) + sizeof(struct jump_data) + + JUMP_TAG_MAX_SIZE) <= CONFIG_PRESERVED_END_OF_RAM_SIZE, + "End of ram data size is too small for panic and jump data"); STATIC_IF(CONFIG_HIBERNATE) uint32_t hibernate_seconds; STATIC_IF(CONFIG_HIBERNATE) uint32_t hibernate_microseconds; /* On-going actions preventing going into deep-sleep mode */ -uint32_t sleep_mask; +atomic_t sleep_mask; #ifdef CONFIG_LOW_POWER_IDLE_LIMITED /* Set it to prevent going into idle mode */ -uint32_t idle_disabled; +atomic_t idle_disabled; #endif -#ifdef CONFIG_HOSTCMD_AP_SET_SKUID +/* SKU ID sourced from AP */ static uint32_t ap_sku_id; -uint32_t system_get_sku_id(void) -{ - return ap_sku_id; -} +#ifdef CONFIG_HOSTCMD_AP_SET_SKUID -#define AP_SKUID_SYSJUMP_TAG 0x4153 /* AS */ -#define AP_SKUID_HOOK_VERSION 1 +#define AP_SKUID_SYSJUMP_TAG 0x4153 /* AS */ +#define AP_SKUID_HOOK_VERSION 1 /** * Preserve AP SKUID across a sysjump. @@ -109,13 +115,26 @@ static void ap_sku_id_restore_state(void) AP_SKUID_SYSJUMP_TAG, &version, &size); if (prev_ap_sku_id && version == AP_SKUID_HOOK_VERSION && - size == sizeof(prev_ap_sku_id)) { + size == sizeof(prev_ap_sku_id)) { memcpy(&ap_sku_id, prev_ap_sku_id, sizeof(ap_sku_id)); } } DECLARE_HOOK(HOOK_INIT, ap_sku_id_restore_state, HOOK_PRIO_DEFAULT); #endif +__overridable uint32_t board_get_sku_id(void) +{ + return 0; +} + +uint32_t system_get_sku_id(void) +{ + if (IS_ENABLED(CONFIG_HOSTCMD_AP_SET_SKUID)) + return ap_sku_id; + + return board_get_sku_id(); +} + /** * Return the program memory address where the image `copy` begins or should * begin. In the case of external storage, the image may or may not currently @@ -162,7 +181,7 @@ static uint32_t __attribute__((unused)) get_size(enum ec_image copy) } } -int system_is_locked(void) +test_mockable int system_is_locked(void) { static int is_locked = -1; @@ -176,13 +195,13 @@ int system_is_locked(void) is_locked = 0; return 0; -#elif defined(CONFIG_FLASH) +#elif defined(CONFIG_FLASH_CROS) /* * Unlocked if write protect pin deasserted or read-only firmware * is not protected. */ if ((EC_FLASH_PROTECT_GPIO_ASSERTED | EC_FLASH_PROTECT_RO_NOW) & - ~flash_get_protect()) { + ~crec_flash_get_protect()) { is_locked = 0; return 0; } @@ -209,26 +228,32 @@ test_mockable uintptr_t system_usable_ram_end(void) return (uintptr_t)jdata - jdata->jump_tag_total; } -void system_encode_save_flags(int reset_flags, uint32_t *save_flags) +void system_encode_save_flags(int flags, uint32_t *save_flags) { *save_flags = 0; /* Save current reset reasons if necessary */ - if (reset_flags & SYSTEM_RESET_PRESERVE_FLAGS) + if (flags & SYSTEM_RESET_PRESERVE_FLAGS) *save_flags = system_get_reset_flags() | EC_RESET_FLAG_PRESERVED; /* Add in AP off flag into saved flags. */ - if (reset_flags & SYSTEM_RESET_LEAVE_AP_OFF) + if (flags & SYSTEM_RESET_LEAVE_AP_OFF) *save_flags |= EC_RESET_FLAG_AP_OFF; /* Add in stay in RO flag into saved flags. */ - if (reset_flags & SYSTEM_RESET_STAY_IN_RO) + if (flags & SYSTEM_RESET_STAY_IN_RO) *save_flags |= EC_RESET_FLAG_STAY_IN_RO; + /* Add in watchdog flag into saved flags. */ + if (flags & SYSTEM_RESET_AP_WATCHDOG) + *save_flags |= EC_RESET_FLAG_AP_WATCHDOG; + /* Save reset flag */ - if (reset_flags & (SYSTEM_RESET_HARD | SYSTEM_RESET_WAIT_EXT)) + if (flags & (SYSTEM_RESET_HARD | SYSTEM_RESET_WAIT_EXT)) *save_flags |= EC_RESET_FLAG_HARD; + else if (flags & SYSTEM_RESET_HIBERNATE) + *save_flags |= EC_RESET_FLAG_HIBERNATE; else *save_flags |= EC_RESET_FLAG_SOFT; } @@ -252,8 +277,8 @@ static void print_reset_flags(uint32_t flags) { int count = 0; int i; - static const char * const reset_flag_descs[] = { - #include "reset_flag_desc.inc" + static const char *const reset_flag_descs[] = { +#include "reset_flag_desc.inc" }; if (!flags) { @@ -283,12 +308,46 @@ void system_print_reset_flags(void) print_reset_flags(reset_flags); } -int system_jumped_to_this_image(void) +void system_print_banner(void) +{ + /* be less verbose if we boot for USB resume to meet spec timings */ + if (!(system_get_reset_flags() & EC_RESET_FLAG_USB_RESUME)) { + CPUTS("\n"); + if (system_jumped_to_this_image()) + CPRINTS("UART initialized after sysjump"); + else + CPUTS("\n--- UART initialized after reboot ---\n"); + CPRINTF("[Image: %s, %s]\n", system_get_image_copy_string(), + system_get_build_info()); + CPUTS("[Reset cause: "); + system_print_reset_flags(); + CPUTS("]\n"); + } +} + +#ifdef CONFIG_RAM_SIZE +struct jump_data *get_jump_data(void) +{ + uintptr_t addr; + + /* + * Put the jump data before the panic data, or at the end of RAM if + * panic data is not present. + */ + addr = get_panic_data_start(); + if (!addr) + addr = CONFIG_RAM_BASE + CONFIG_RAM_SIZE; + + return (struct jump_data *)(addr - sizeof(struct jump_data)); +} +#endif + +test_mockable int system_jumped_to_this_image(void) { return jumped_to_image; } -int system_jumped_late(void) +test_mockable int system_jumped_late(void) { return !(reset_flags & EC_RESET_FLAG_EFS) && jumped_to_image; } @@ -296,15 +355,24 @@ int system_jumped_late(void) int system_add_jump_tag(uint16_t tag, int version, int size, const void *data) { struct jump_tag *t; + size_t new_entry_size; /* Only allowed during a sysjump */ if (!jdata || jdata->magic != JUMP_DATA_MAGIC) return EC_ERROR_UNKNOWN; /* Make room for the new tag */ - if (size > 255) + if (size > JUMP_TAG_MAX_SIZE) return EC_ERROR_INVAL; - jdata->jump_tag_total += ROUNDUP4(size) + sizeof(struct jump_tag); + + new_entry_size = ROUNDUP4(size) + sizeof(struct jump_tag); + + if (system_usable_ram_end() - new_entry_size < JUMP_DATA_MIN_ADDRESS) { + ccprintf("ERROR: out of space for jump tags\n"); + return EC_ERROR_INVAL; + } + + jdata->jump_tag_total += new_entry_size; t = (struct jump_tag *)system_usable_ram_end(); t->tag = tag; @@ -316,7 +384,8 @@ int system_add_jump_tag(uint16_t tag, int version, int size, const void *data) return EC_SUCCESS; } -const uint8_t *system_get_jump_tag(uint16_t tag, int *version, int *size) +test_mockable const uint8_t *system_get_jump_tag(uint16_t tag, int *version, + int *size) { const struct jump_tag *t; int used = 0; @@ -324,6 +393,10 @@ const uint8_t *system_get_jump_tag(uint16_t tag, int *version, int *size) if (!jdata) return NULL; + /* Ensure system_usable_ram_end() is within bounds */ + if (system_usable_ram_end() < JUMP_DATA_MIN_ADDRESS) + return NULL; + /* Search through tag data for a match */ while (used < jdata->jump_tag_total) { /* Check the next tag */ @@ -345,12 +418,13 @@ const uint8_t *system_get_jump_tag(uint16_t tag, int *version, int *size) return NULL; } -void system_disable_jump(void) +test_mockable void system_disable_jump(void) { disable_jump = 1; #ifdef CONFIG_MPU if (system_is_locked()) { +#ifndef CONFIG_ZEPHYR int ret; enum ec_image __attribute__((unused)) copy; @@ -360,9 +434,8 @@ void system_disable_jump(void) */ ret = mpu_protect_data_ram(); if (ret == EC_SUCCESS) { - CPRINTS("data RAM locked. Exclusion %pP-%pP", - &__iram_text_start, - &__iram_text_end); + CPRINTS("data RAM locked. Exclusion %p-%p", + &__iram_text_start, &__iram_text_end); } else { CPRINTS("Failed to lock data RAM (%d)", ret); return; @@ -386,11 +459,11 @@ void system_disable_jump(void) */ switch (system_get_image_copy()) { case EC_IMAGE_RO: - ret = mpu_lock_rw_flash(); + ret = mpu_lock_rw_flash(); copy = EC_IMAGE_RW; break; case EC_IMAGE_RW: - ret = mpu_lock_ro_flash(); + ret = mpu_lock_ro_flash(); copy = EC_IMAGE_RO; break; default: @@ -398,14 +471,14 @@ void system_disable_jump(void) ret = !EC_SUCCESS; } if (ret == EC_SUCCESS) { - CPRINTS("%s image locked", - ec_image_to_string(copy)); + CPRINTS("%s image locked", ec_image_to_string(copy)); } else { CPRINTS("Failed to lock %s image (%d)", ec_image_to_string(copy), ret); return; } #endif /* !CONFIG_EXTERNAL_STORAGE */ +#endif /* !CONFIG_ZEPHYR */ /* All regions were configured successfully, enable MPU */ mpu_enable(); @@ -421,8 +494,8 @@ test_mockable enum ec_image system_get_image_copy(void) /* Return which region is used in program memory */ return system_get_shrspi_image_copy(); #else - uintptr_t my_addr = (uintptr_t)system_get_image_copy - - CONFIG_PROGRAM_MEMORY_BASE; + uintptr_t my_addr = + (uintptr_t)system_get_image_copy - CONFIG_PROGRAM_MEMORY_BASE; if (my_addr >= CONFIG_RO_MEM_OFF && my_addr < (CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE)) @@ -485,12 +558,18 @@ const char *system_get_image_copy_string(void) const char *ec_image_to_string(enum ec_image copy) { - static const char * const image_names[] = { - "unknown", "RO", "RW", "RO_B", "RW_B" - }; + static const char *const image_names[] = { "unknown", "RO", "RW", + "RO_B", "RW_B" }; return image_names[copy < ARRAY_SIZE(image_names) ? copy : 0]; } +__overridable void board_pulse_entering_rw(void) +{ + gpio_set_level(GPIO_ENTERING_RW, 1); + usleep(MSEC); + gpio_set_level(GPIO_ENTERING_RW, 0); +} + /** * Jump to what we hope is the init address of an image. * @@ -498,7 +577,7 @@ const char *ec_image_to_string(enum ec_image copy) * * @param init_addr Init address of target image */ -static void jump_to_image(uintptr_t init_addr) +test_mockable_static void jump_to_image(uintptr_t init_addr) { void (*resetvec)(void); @@ -511,9 +590,7 @@ static void jump_to_image(uintptr_t init_addr) * drop it again so we don't leak power through the pulldown in the * Silego. */ - gpio_set_level(GPIO_ENTERING_RW, 1); - usleep(MSEC); - gpio_set_level(GPIO_ENTERING_RW, 0); + board_pulse_entering_rw(); /* * Since in EFS2, USB/PD won't be enabled in RO or if it's enabled in @@ -526,11 +603,11 @@ static void jump_to_image(uintptr_t init_addr) * check whether PD tasks have started (instead of VBOOT_EFS2, which * is static). */ - if (task_start_called() && IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) + if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP) && task_start_called()) /* Note: must be before i2c module is locked down */ pd_prepare_sysjump(); -#ifdef CONFIG_I2C_MASTER +#ifdef CONFIG_I2C_CONTROLLER /* Prepare I2C module for sysjump */ i2c_prepare_sysjump(); #endif @@ -543,22 +620,22 @@ static void jump_to_image(uintptr_t init_addr) jdata->magic = JUMP_DATA_MAGIC; jdata->version = JUMP_DATA_VERSION; jdata->reset_flags = reset_flags; - jdata->jump_tag_total = 0; /* Reset tags */ + jdata->jump_tag_total = 0; /* Reset tags */ jdata->struct_size = sizeof(struct jump_data); /* Call other hooks; these may add tags */ hook_notify(HOOK_SYSJUMP); /* Disable interrupts before jump */ - interrupt_disable(); + interrupt_disable_all(); -#ifdef CONFIG_DMA +#ifdef CONFIG_DMA_CROS /* Disable all DMA channels to avoid memory corruption */ dma_disable_all(); -#endif /* CONFIG_DMA */ +#endif /* CONFIG_DMA_CROS */ /* Jump to the reset vector */ - resetvec = (void(*)(void))init_addr; + resetvec = (void (*)(void))init_addr; resetvec(); } @@ -572,8 +649,8 @@ int system_is_in_rw(void) return is_rw_image(system_get_image_copy()); } -static int system_run_image_copy_with_flags(enum ec_image copy, - uint32_t add_reset_flags) +test_mockable_static int +system_run_image_copy_with_flags(enum ec_image copy, uint32_t add_reset_flags) { uintptr_t base; uintptr_t init_addr; @@ -613,11 +690,6 @@ static int system_run_image_copy_with_flags(enum ec_image copy, init_addr = system_get_fw_reset_vector(base); } else { uintptr_t init = base + 4; - - /* Skip any head room in the RO image */ - if (copy == EC_IMAGE_RO) - init += CONFIG_RO_HEAD_ROOM; - init_addr = *(uintptr_t *)(init); /* Make sure the reset vector is inside the destination image */ @@ -628,7 +700,12 @@ static int system_run_image_copy_with_flags(enum ec_image copy, system_set_reset_flags(add_reset_flags); - CPRINTS("Jumping to image %s", ec_image_to_string(copy)); + /* If jumping back to RO, we're no longer in the EFS context. */ + if (copy == EC_IMAGE_RO) + system_clear_reset_flags(EC_RESET_FLAG_EFS); + + CPRINTS("Jumping to image %s (0x%08x)", ec_image_to_string(copy), + system_get_reset_flags()); jump_to_image(init_addr); @@ -654,9 +731,9 @@ enum ec_image system_get_active_copy(void) enum ec_image system_get_update_copy(void) { -#ifdef CONFIG_VBOOT_EFS /* Not needed for EFS2, which is single-slot. */ - return system_get_active_copy() == EC_IMAGE_RW_A ? - EC_IMAGE_RW_B : EC_IMAGE_RW_A; +#ifdef CONFIG_VBOOT_EFS /* Not needed for EFS2, which is single-slot. */ + return system_get_active_copy() == EC_IMAGE_RW_A ? EC_IMAGE_RW_B : + EC_IMAGE_RW_A; #else return EC_IMAGE_RW_A; #endif @@ -667,6 +744,7 @@ int system_set_active_copy(enum ec_image copy) return system_set_bbram(SYSTEM_BBRAM_IDX_TRY_SLOT, copy); } +#ifdef CONFIG_EC_PROTECTED_STORAGE_OFF /* * This is defined in system.c instead of flash.c because it's called even * on the boards which don't include flash.o. (e.g. hadoken, stm32l476g-eval) @@ -682,6 +760,7 @@ uint32_t flash_get_rw_offset(enum ec_image copy) return CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_RO_STORAGE_OFF; } +#endif const struct image_data *system_get_image_data(enum ec_image copy) { @@ -701,7 +780,7 @@ const struct image_data *system_get_image_data(enum ec_image copy) * it's the same offset as in the current image. Find that offset. */ addr = ((uintptr_t)¤t_image_data - - get_program_memory_addr(active_copy)); + get_program_memory_addr(active_copy)); /* * Read the version information from the proper location @@ -711,12 +790,12 @@ const struct image_data *system_get_image_data(enum ec_image copy) #ifdef CONFIG_MAPPED_STORAGE addr += CONFIG_MAPPED_STORAGE_BASE; - flash_lock_mapped_storage(1); + crec_flash_lock_mapped_storage(1); memcpy(&data, (const void *)addr, sizeof(data)); - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(0); #else /* Read the version struct from flash into a buffer. */ - if (flash_read(addr, sizeof(data), (char *)&data)) + if (crec_flash_read(addr, sizeof(data), (char *)&data)) return NULL; #endif @@ -729,14 +808,30 @@ const struct image_data *system_get_image_data(enum ec_image copy) return NULL; } -__attribute__((weak)) /* Weird chips may need their own implementations */ -const char *system_get_version(enum ec_image copy) +__attribute__((weak)) /* Weird chips may need their own implementations */ +const char * +system_get_version(enum ec_image copy) { const struct image_data *data = system_get_image_data(copy); return data ? data->version : ""; } +const char *system_get_cros_fwid(enum ec_image copy) +{ + const struct image_data *data; + + if (IS_ENABLED(CONFIG_CROS_FWID_VERSION)) { + data = system_get_image_data(copy); + if (data && (data->cookie3 & CROS_EC_IMAGE_DATA_COOKIE3_MASK) == + CROS_EC_IMAGE_DATA_COOKIE3) + return data->cros_fwid; + else + return CROS_FWID_MISSING_STR; + } + return ""; +} + #ifdef CONFIG_ROLLBACK int32_t system_get_rollback_version(enum ec_image copy) { @@ -753,45 +848,52 @@ int system_get_image_used(enum ec_image copy) return data ? MAX((int)data->size, 0) : 0; } +/* + * Overwrite it in board directory in case that we want to read board version + * in our own way. + */ +__overridable int board_get_version(void) +{ +#ifdef CONFIG_BOARD_VERSION_GPIO + return (!!gpio_get_level(GPIO_BOARD_VERSION1) << 0) | + (!!gpio_get_level(GPIO_BOARD_VERSION2) << 1) | + (!!gpio_get_level(GPIO_BOARD_VERSION3) << 2); +#else + return 0; +#endif +} + /* * Returns positive board version if successfully retrieved. Otherwise the * value is a negative version of an EC return code. Without this optimization * multiple boards run out of flash size. */ -int system_get_board_version(void) +test_mockable int system_get_board_version(void) { -#if defined(CONFIG_BOARD_VERSION_CUSTOM) + int board_id; + + if (IS_ENABLED(CONFIG_BOARD_VERSION_CBI)) { + int error; + + error = cbi_get_board_version(&board_id); + if (error) + return -error; + + return board_id; + }; + return board_get_version(); -#elif defined(CONFIG_BOARD_VERSION_GPIO) - return - (!!gpio_get_level(GPIO_BOARD_VERSION1) << 0) | - (!!gpio_get_level(GPIO_BOARD_VERSION2) << 1) | - (!!gpio_get_level(GPIO_BOARD_VERSION3) << 2); -#elif defined(CONFIG_BOARD_VERSION_CBI) - int error; - int32_t version; - - error = cbi_get_board_version(&version); - if (error) - return -error; - else - return version; -#else - return 0; -#endif } -__attribute__((weak)) /* Weird chips may need their own implementations */ -const char *system_get_build_info(void) +__attribute__((weak)) /* Weird chips may need their own implementations */ +const char * +system_get_build_info(void) { return build_info; } void system_common_pre_init(void) { - uintptr_t addr; - -#ifdef CONFIG_SOFTWARE_PANIC /* * Log panic cause if watchdog caused reset and panic cause * was not already logged. This must happen before calculating @@ -801,22 +903,21 @@ void system_common_pre_init(void) uint32_t reason; uint32_t info; uint8_t exception; + struct panic_data *pdata; panic_get_reason(&reason, &info, &exception); - if (reason != PANIC_SW_WATCHDOG) + pdata = panic_get_data(); + /* The watchdog panic info may have already been initialized by + * the watchdog handler, so only set it here if the panic reason + * is not a watchdog or the panic info has already been read, + * i.e. an old watchdog panic. + */ + if (reason != PANIC_SW_WATCHDOG || !pdata || + pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD) panic_set_reason(PANIC_SW_WATCHDOG, 0, 0); } -#endif - - /* - * Put the jump data before the panic data, or at the end of RAM if - * panic data is not present. - */ - addr = get_panic_data_start(); - if (!addr) - addr = CONFIG_RAM_BASE + CONFIG_RAM_SIZE; - jdata = (struct jump_data *)(addr - sizeof(struct jump_data)); + jdata = get_jump_data(); /* * Check jump data if this is a jump between images. @@ -838,12 +939,24 @@ void system_common_pre_init(void) * the new fields below. */ if (jdata->version == 1) - delta = 0; /* No tags in v1, so no need for move */ + delta = 0; /* No tags in v1, so no need for move */ else if (jdata->version == 2) delta = sizeof(struct jump_data) - JUMP_DATA_SIZE_V2; else delta = sizeof(struct jump_data) - jdata->struct_size; + /* + * Check if enough space for jump data. + * Clear jump data and return if not. + */ + if (system_usable_ram_end() < JUMP_DATA_MIN_ADDRESS) { + /* TODO(b/251190975): This failure should be reported + * in the panic data structure for more visibility. + */ + memset(jdata, 0, sizeof(struct jump_data)); + return; + } + if (delta && jdata->jump_tag_total) { uint8_t *d = (uint8_t *)system_usable_ram_end(); memmove(d, d + delta, jdata->jump_tag_total); @@ -872,25 +985,44 @@ void system_common_pre_init(void) } } +void system_enter_manual_recovery(void) +{ + system_info_flags |= SYSTEM_IN_MANUAL_RECOVERY; +} + +void system_exit_manual_recovery(void) +{ + system_info_flags &= ~SYSTEM_IN_MANUAL_RECOVERY; +} + int system_is_manual_recovery(void) { - return host_is_event_set(EC_HOST_EVENT_KEYBOARD_RECOVERY); + return system_info_flags & SYSTEM_IN_MANUAL_RECOVERY; } /** * Handle a pending reboot command. */ -static int handle_pending_reboot(enum ec_reboot_cmd cmd) +static int handle_pending_reboot(struct ec_params_reboot_ec p) { - switch (cmd) { + if (IS_ENABLED(CONFIG_POWER_BUTTON_INIT_IDLE) && + (p.flags & EC_REBOOT_FLAG_CLEAR_AP_IDLE)) { + CPRINTS("Clearing AP_IDLE"); + chip_save_reset_flags(chip_read_reset_flags() & + ~EC_RESET_FLAG_AP_IDLE); + } + + switch (p.cmd) { case EC_REBOOT_CANCEL: + case EC_REBOOT_NO_OP: return EC_SUCCESS; case EC_REBOOT_JUMP_RO: - return system_run_image_copy_with_flags(EC_IMAGE_RO, - EC_RESET_FLAG_STAY_IN_RO); + return system_run_image_copy_with_flags( + EC_IMAGE_RO, EC_RESET_FLAG_STAY_IN_RO); case EC_REBOOT_JUMP_RW: return system_run_image_copy(system_get_active_copy()); case EC_REBOOT_COLD: + case EC_REBOOT_COLD_AP_OFF: /* * Reboot the PD chip(s) as well, but first suspend the ports * if this board has PD tasks running so they don't query the @@ -916,26 +1048,27 @@ static int handle_pending_reboot(enum ec_reboot_cmd cmd) board_reset_pd_mcu(); cflush(); - system_reset(SYSTEM_RESET_HARD); + if (p.cmd == EC_REBOOT_COLD_AP_OFF) + system_reset(SYSTEM_RESET_HARD | + SYSTEM_RESET_LEAVE_AP_OFF); + else + system_reset(SYSTEM_RESET_HARD); /* That shouldn't return... */ return EC_ERROR_UNKNOWN; case EC_REBOOT_DISABLE_JUMP: system_disable_jump(); return EC_SUCCESS; - case EC_REBOOT_HIBERNATE_CLEAR_AP_OFF: - if (!IS_ENABLED(CONFIG_HIBERNATE)) - return EC_ERROR_INVAL; - - if (IS_ENABLED(CONFIG_POWER_BUTTON_INIT_IDLE)) { - CPRINTS("Clearing AP_IDLE"); - chip_save_reset_flags(chip_read_reset_flags() & - ~EC_RESET_FLAG_AP_IDLE); - } - /* Intentional fall-through */ case EC_REBOOT_HIBERNATE: if (!IS_ENABLED(CONFIG_HIBERNATE)) return EC_ERROR_INVAL; + /* + * Allow some time for the system to quiesce before entering EC + * hibernate. Otherwise, some stray signals may cause an + * immediate wake up. + */ + CPRINTS("Waiting 1s before hibernating..."); + msleep(1000); CPRINTS("system hibernating"); system_hibernate(hibernate_seconds, hibernate_microseconds); /* That shouldn't return... */ @@ -945,14 +1078,54 @@ static int handle_pending_reboot(enum ec_reboot_cmd cmd) } } +test_mockable void system_enter_hibernate(uint32_t seconds, + uint32_t microseconds) +{ + if (!IS_ENABLED(CONFIG_HIBERNATE)) + return; + + /* + * On ChromeOS devices, if AC is present, don't hibernate. + * It might trigger an immediate wake up (since AC is present), + * resulting in an AP reboot. + * Hibernate when AC is present never occurs in normal circumstances, + * this is to prevent an action triggered by developers. + * See: b/192259035 + */ + if (IS_ENABLED(CONFIG_EXTPOWER) && + IS_ENABLED(CONFIG_AP_POWER_CONTROL) && extpower_is_present()) { + CPRINTS("AC on, skip hibernate"); + return; + } + + /* + * If chipset is already off, then call system_hibernate directly. Else, + * let chipset_task bring down the power rails and transition to proper + * state before system_hibernate is called. + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + system_hibernate(seconds, microseconds); + else { + reboot_at_shutdown.cmd = EC_REBOOT_HIBERNATE; + hibernate_seconds = seconds; + hibernate_microseconds = microseconds; + + chipset_force_shutdown(CHIPSET_SHUTDOWN_CONSOLE_CMD); + } +} + /*****************************************************************************/ /* Hooks */ static void system_common_shutdown(void) { - if (reboot_at_shutdown) - CPRINTF("Reboot at shutdown: %d\n", reboot_at_shutdown); + system_exit_manual_recovery(); + if (reboot_at_shutdown.cmd) + CPRINTF("Reboot at shutdown: %d\n", reboot_at_shutdown.cmd); handle_pending_reboot(reboot_at_shutdown); + + /* Reset cnt on cold boot */ + update_ap_boot_time(RESET_CNT); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN_COMPLETE, system_common_shutdown, HOOK_PRIO_DEFAULT); @@ -970,23 +1143,25 @@ static int sysinfo(struct ec_response_sysinfo *info) info->current_image = system_get_image_copy(); if (system_jumped_to_this_image()) - info->flags |= SYSTEM_JUMPED_TO_CURRENT_IMAGE; + system_info_flags |= SYSTEM_JUMPED_TO_CURRENT_IMAGE; if (system_is_locked()) { - info->flags |= SYSTEM_IS_LOCKED; + system_info_flags |= SYSTEM_IS_LOCKED; if (force_locked) - info->flags |= SYSTEM_IS_FORCE_LOCKED; + system_info_flags |= SYSTEM_IS_FORCE_LOCKED; if (!disable_jump) - info->flags |= SYSTEM_JUMP_ENABLED; + system_info_flags |= SYSTEM_JUMP_ENABLED; } - if (reboot_at_shutdown) - info->flags |= SYSTEM_REBOOT_AT_SHUTDOWN; + if (reboot_at_shutdown.cmd) + system_info_flags |= SYSTEM_REBOOT_AT_SHUTDOWN; + + info->flags = system_info_flags; return EC_SUCCESS; } -static int command_sysinfo(int argc, char **argv) +static int command_sysinfo(int argc, const char **argv) { struct ec_response_sysinfo info; int rv; @@ -1001,6 +1176,8 @@ static int command_sysinfo(int argc, char **argv) ccprintf("Copy: %s\n", ec_image_to_string(info.current_image)); ccprintf("Jumped: %s\n", (info.flags & SYSTEM_JUMPED_TO_CURRENT_IMAGE) ? "yes" : "no"); + ccprintf("Recovery: %s\n", + (info.flags & SYSTEM_IN_MANUAL_RECOVERY) ? "yes" : "no"); ccputs("Flags: "); if (info.flags & SYSTEM_IS_LOCKED) { @@ -1019,8 +1196,7 @@ static int command_sysinfo(int argc, char **argv) return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(sysinfo, command_sysinfo, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(sysinfo, command_sysinfo, NULL, "Print system info"); static enum ec_status host_command_sysinfo(struct host_cmd_handler_args *args) @@ -1040,9 +1216,10 @@ DECLARE_HOST_COMMAND(EC_CMD_SYSINFO, host_command_sysinfo, #endif #ifdef CONFIG_CMD_SCRATCHPAD -static int command_scratchpad(int argc, char **argv) +static int command_scratchpad(int argc, const char **argv) { int rv = EC_SUCCESS; + uint32_t scratchpad_value; if (argc == 2) { char *e; @@ -1050,17 +1227,26 @@ static int command_scratchpad(int argc, char **argv) if (*e) return EC_ERROR_PARAM1; rv = system_set_scratchpad(s); + + if (rv) { + ccprintf("Error setting scratchpad register (%d)\b", + rv); + return rv; + } } - ccprintf("Scratchpad: 0x%08x\n", system_get_scratchpad()); + rv = system_get_scratchpad(&scratchpad_value); + if (rv) + ccprintf("Error reading scratchpad register (%d)\n", rv); + else + ccprintf("Scratchpad: 0x%08x\n", scratchpad_value); return rv; } -DECLARE_CONSOLE_COMMAND(scratchpad, command_scratchpad, - "[val]", +DECLARE_CONSOLE_COMMAND(scratchpad, command_scratchpad, "[val]", "Get or set scratchpad value"); #endif /* CONFIG_CMD_SCRATCHPAD */ -__maybe_unused static int command_hibernate(int argc, char **argv) +__maybe_unused static int command_hibernate(int argc, const char **argv) { int seconds = 0; int microseconds = 0; @@ -1071,7 +1257,8 @@ __maybe_unused static int command_hibernate(int argc, char **argv) microseconds = strtoi(argv[2], NULL, 0); if (seconds || microseconds) { - if (IS_ENABLED(CONFIG_HIBERNATE_PSL)) { + if (IS_ENABLED(CONFIG_HIBERNATE_PSL) && + !IS_ENABLED(NPCX_LCT_SUPPORT)) { ccprintf("Hibernating with timeout not supported " "when PSL is enabled.\n"); return EC_ERROR_INVAL; @@ -1080,26 +1267,12 @@ __maybe_unused static int command_hibernate(int argc, char **argv) } else ccprintf("Hibernating until wake pin asserted.\n"); - /* - * If chipset is already off, then call system_hibernate directly. Else, - * let chipset_task bring down the power rails and transition to proper - * state before system_hibernate is called. - */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) - system_hibernate(seconds, microseconds); - else { - reboot_at_shutdown = EC_REBOOT_HIBERNATE; - hibernate_seconds = seconds; - hibernate_microseconds = microseconds; - - chipset_force_shutdown(CHIPSET_SHUTDOWN_CONSOLE_CMD); - } + system_enter_hibernate(seconds, microseconds); return EC_SUCCESS; } #ifdef CONFIG_HIBERNATE -DECLARE_CONSOLE_COMMAND(hibernate, command_hibernate, - "[sec] [usec]", +DECLARE_CONSOLE_COMMAND(hibernate, command_hibernate, "[sec] [usec]", "Hibernate the EC"); #endif /* CONFIG_HIBERNATE */ @@ -1114,106 +1287,109 @@ DECLARE_CONSOLE_COMMAND(hibernate, command_hibernate, * * cr50_v1.1.4979-0061603+ private-cr51:v0.0.66-bd9a0fe tpm2:v0.0.259-2b... * - * Each subcomponent in this case includes the ":v" substring. For these - * combined version strings this function prints each version or subcomponent - * version on a different line. */ static void print_build_string(void) { const char *full_build_string; const char *p; - char symbol; - int seen_colonv; + size_t next_token_len; + size_t line_len = 0; + const size_t max_line_len = 50; - ccprintf("Build: "); + ccprintf("Build:\t"); full_build_string = system_get_build_info(); - - /* 50 characters or less, will fit into the terminal line. */ - if (strlen(full_build_string) < 50) { - ccprintf("%s\n", full_build_string); - return; - } - - /* - * Build version string needs splitting, let's split it at the first - * space (this is where the main version ends), and then on each space - * after the ":v" substring, this is where subcomponent versions are - * separated. - */ p = full_build_string; - seen_colonv = 1; - - symbol = *p++; - while (symbol) { - if ((symbol == ' ') && seen_colonv) { - seen_colonv = 0; - /* Indent each line under 'Build: ' */ - ccprintf("\n "); - } else { - if ((symbol == ':') && (*p == 'v')) - seen_colonv = 1; - ccprintf("%c", symbol); + + while (*p) { + /* Print first token */ + if (*p == ' ') { + next_token_len = strcspn(p + 1, " \0"); + if (next_token_len + line_len > max_line_len) { + line_len = 0; + p++; + ccprintf("\n\t\t"); + continue; + } } - symbol = *p++; + ccprintf("%c", *p++); + line_len++; } ccprintf("\n"); } -static int command_version(int argc, char **argv) +static int command_version(int argc, const char **argv) { int board_version; + const char *fw_version; + const char *cros_fwid; + bool __maybe_unused is_active; - ccprintf("Chip: %s %s %s\n", system_get_chip_vendor(), + ccprintf("Chip:\t%s %s %s\n", system_get_chip_vendor(), system_get_chip_name(), system_get_chip_revision()); board_version = system_get_board_version(); if (board_version < 0) - ccprintf("Board: Error %d\n", -board_version); + ccprintf("Board:\tError %d\n", -board_version); else - ccprintf("Board: %d\n", board_version); - -#ifdef CHIP_HAS_RO_B - { - enum ec_image active; - - active = system_get_ro_image_copy(); - ccprintf("RO_A: %c %s\n", - (active == EC_IMAGE_RO ? '*' : ' '), - system_get_version(EC_IMAGE_RO)); - ccprintf("RO_B: %c %s\n", - (active == EC_IMAGE_RO_B ? '*' : ' '), - system_get_version(EC_IMAGE_RO_B)); + ccprintf("Board:\t%d\n", board_version); + + fw_version = system_get_version(EC_IMAGE_RO); + cros_fwid = system_get_cros_fwid(EC_IMAGE_RO); + if (IS_ENABLED(CHIP_HAS_RO_B)) { + is_active = system_get_ro_image_copy() == EC_IMAGE_RO; + + ccprintf("RO_A:\t%s%s\n", is_active ? "* " : "", fw_version); + if (IS_NONEMPTY_STRING(cros_fwid)) + ccprintf("\t\t%s%s\n", is_active ? "* " : "", + cros_fwid); + + is_active = system_get_ro_image_copy() == EC_IMAGE_RO_B; + fw_version = system_get_version(EC_IMAGE_RO_B); + cros_fwid = system_get_cros_fwid(EC_IMAGE_RO_B); + + ccprintf("RO_B:\t%s%s\n", is_active ? "* " : "", fw_version); + if (IS_NONEMPTY_STRING(cros_fwid)) + ccprintf("\t\t%s%s\n", is_active ? "* " : "", + cros_fwid); + } else { + ccprintf("RO:\t%s\n", fw_version); + if (IS_NONEMPTY_STRING(cros_fwid)) + ccprintf("\t\t%s\n", cros_fwid); } -#else - ccprintf("RO: %s\n", system_get_version(EC_IMAGE_RO)); -#endif -#ifdef CONFIG_RW_B - { - enum ec_image active; - - active = system_get_image_copy(); - ccprintf("RW_A: %c %s\n", - (active == EC_IMAGE_RW ? '*' : ' '), - system_get_version(EC_IMAGE_RW)); - ccprintf("RW_B: %c %s\n", - (active == EC_IMAGE_RW_B ? '*' : ' '), - system_get_version(EC_IMAGE_RW_B)); + + fw_version = system_get_version(EC_IMAGE_RW); + cros_fwid = system_get_cros_fwid(EC_IMAGE_RW); + if (IS_ENABLED(CONFIG_RW_B)) { + is_active = system_get_active_copy() == EC_IMAGE_RW; + + ccprintf("RW_A:\t%s%s\n", is_active ? "* " : "", fw_version); + if (IS_NONEMPTY_STRING(cros_fwid)) + ccprintf("\t\t%s%s\n", is_active ? "* " : "", + cros_fwid); + + fw_version = system_get_version(EC_IMAGE_RW_B); + cros_fwid = system_get_cros_fwid(EC_IMAGE_RW_B); + is_active = system_get_active_copy() == EC_IMAGE_RW_B; + + ccprintf("RW_B:\t%s%s\n", is_active ? "* " : "", fw_version); + if (IS_NONEMPTY_STRING(cros_fwid)) + ccprintf("\t\t%s%s\n", is_active ? "* " : "", + cros_fwid); + } else { + ccprintf("RW:\t%s\n", fw_version); + if (IS_NONEMPTY_STRING(cros_fwid)) + ccprintf("\t\t%s\n", cros_fwid); } -#else - ccprintf("RW: %s\n", system_get_version(EC_IMAGE_RW)); -#endif system_print_extended_version_info(); print_build_string(); return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(version, command_version, - NULL, - "Print versions"); +DECLARE_SAFE_CONSOLE_COMMAND(version, command_version, NULL, "Print versions"); #ifdef CONFIG_CMD_SYSJUMP -static int command_sysjump(int argc, char **argv) +static int command_sysjump(int argc, const char **argv) { uint32_t addr; char *e; @@ -1223,8 +1399,8 @@ static int command_sysjump(int argc, char **argv) /* Handle named images */ if (!strcasecmp(argv[1], "RO")) - return system_run_image_copy_with_flags(EC_IMAGE_RO, - EC_RESET_FLAG_STAY_IN_RO); + return system_run_image_copy_with_flags( + EC_IMAGE_RO, EC_RESET_FLAG_STAY_IN_RO); else if (!strcasecmp(argv[1], "RW") || !strcasecmp(argv[1], "A")) return system_run_image_copy(EC_IMAGE_RW); else if (!strcasecmp(argv[1], "B")) { @@ -1257,7 +1433,7 @@ DECLARE_CONSOLE_COMMAND(sysjump, command_sysjump, "Jump to a system image or address"); #endif -static int command_reboot(int argc, char **argv) +static int command_reboot(int argc, const char **argv) { int flags = SYSTEM_RESET_MANUALLY_TRIGGERED; int i; @@ -1276,7 +1452,7 @@ static int command_reboot(int argc, char **argv) } else if (!strcasecmp(argv[i], "ro")) { flags |= SYSTEM_RESET_STAY_IN_RO; } else if (!strcasecmp(argv[i], "cancel")) { - reboot_at_shutdown = EC_REBOOT_CANCEL; + reboot_at_shutdown.cmd = EC_REBOOT_CANCEL; return EC_SUCCESS; } else if (!strcasecmp(argv[i], "preserve")) { flags |= SYSTEM_RESET_PRESERVE_FLAGS; @@ -1304,13 +1480,12 @@ DECLARE_CONSOLE_COMMAND( "Reboot the EC"); #ifdef CONFIG_CMD_SYSLOCK -static int command_system_lock(int argc, char **argv) +static int command_system_lock(int argc, const char **argv) { force_locked = 1; return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(syslock, command_system_lock, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(syslock, command_system_lock, NULL, "Lock the system, even if WP is disabled"); #endif @@ -1319,7 +1494,7 @@ DECLARE_SAFE_CONSOLE_COMMAND(syslock, command_system_lock, * Modify and print the sleep mask which controls access to deep sleep * mode in the idle task. */ -static int command_sleepmask(int argc, char **argv) +static int command_sleepmask(int argc, const char **argv) { #ifdef CONFIG_CMD_SLEEPMASK_SET int v; @@ -1341,7 +1516,7 @@ static int command_sleepmask(int argc, char **argv) } } #endif - ccprintf("sleep mask: %08x\n", sleep_mask); + ccprintf("sleep mask: %08x\n", (int)sleep_mask); return EC_SUCCESS; } @@ -1351,7 +1526,7 @@ DECLARE_SAFE_CONSOLE_COMMAND(sleepmask, command_sleepmask, #endif #ifdef CONFIG_CMD_JUMPTAGS -static int command_jumptags(int argc, char **argv) +static int command_jumptags(int argc, const char **argv) { const struct jump_tag *t; int used = 0; @@ -1365,21 +1540,18 @@ static int command_jumptags(int argc, char **argv) t = (const struct jump_tag *)(system_usable_ram_end() + used); used += sizeof(struct jump_tag) + ROUNDUP4(t->data_size); - ccprintf("%08x: 0x%04x %c%c.%d %3d\n", - (uintptr_t)t, - t->tag, t->tag >> 8, (uint8_t)t->tag, - t->data_version, t->data_size); + ccprintf("%08x: 0x%04x %c%c.%d %3d\n", (uintptr_t)t, t->tag, + t->tag >> 8, (uint8_t)t->tag, t->data_version, + t->data_size); } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(jumptags, command_jumptags, - NULL, - "List jump tags"); +DECLARE_CONSOLE_COMMAND(jumptags, command_jumptags, NULL, "List jump tags"); #endif /* CONFIG_CMD_JUMPTAGS */ #ifdef CONFIG_EMULATED_SYSRQ -static int command_sysrq(int argc, char **argv) +static int command_sysrq(int argc, const char **argv) { char key = 'x'; @@ -1390,20 +1562,18 @@ static int command_sysrq(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(sysrq, command_sysrq, - "[key]", +DECLARE_CONSOLE_COMMAND(sysrq, command_sysrq, "[key]", "Simulate sysrq press (default: x)"); #endif /* CONFIG_EMULATED_SYSRQ */ #ifdef CONFIG_CMD_RESET_FLAGS -static int command_rflags(int argc, char **argv) +static int command_rflags(int argc, const char **argv) { print_reset_flags(chip_read_reset_flags()); ccprintf("\n"); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(rflags, command_rflags, - NULL, +DECLARE_CONSOLE_COMMAND(rflags, command_rflags, NULL, "Print reset flags saved in non-volatile memory"); #endif @@ -1413,13 +1583,12 @@ DECLARE_CONSOLE_COMMAND(rflags, command_rflags, static enum ec_status host_command_get_version(struct host_cmd_handler_args *args) { - struct ec_response_get_version *r = args->response; + struct ec_response_get_version_v1 *r = args->response; enum ec_image active_slot = system_get_active_copy(); strzcpy(r->version_string_ro, system_get_version(EC_IMAGE_RO), sizeof(r->version_string_ro)); - strzcpy(r->version_string_rw, - system_get_version(active_slot), + strzcpy(r->version_string_rw, system_get_version(active_slot), sizeof(r->version_string_rw)); switch (system_get_image_copy()) { @@ -1435,13 +1604,38 @@ host_command_get_version(struct host_cmd_handler_args *args) break; } - args->response_size = sizeof(*r); + /* + * Assuming args->response is zero'd in host_command_process, so no need + * to zero uninitialized fields here. + */ + if (args->version > 0 && IS_ENABLED(CONFIG_CROS_FWID_VERSION)) { + if (args->response_max < sizeof(*r)) + return EC_RES_RESPONSE_TOO_BIG; + + strzcpy(r->cros_fwid_ro, system_get_cros_fwid(EC_IMAGE_RO), + sizeof(r->cros_fwid_ro)); + strzcpy(r->cros_fwid_rw, system_get_cros_fwid(EC_IMAGE_RW), + sizeof(r->cros_fwid_rw)); + } + + /* + * By convention, ec_response_get_version_v1 is a strict superset of + * ec_response_get_version(v0). The v1 response changes the semantics + * of one field (reserved to cros_fwid_ro) and adds one additional field + * (cros_fwid_rw). So simply adjusting the response size here is safe. + */ + if (args->version == 0) + args->response_size = sizeof(struct ec_response_get_version); + else if (args->version == 1) + args->response_size = sizeof(struct ec_response_get_version_v1); + else + /* Shouldn't happen because of EC_VER_MASK */ + return EC_RES_INVALID_VERSION; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_VERSION, - host_command_get_version, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_GET_VERSION, host_command_get_version, + EC_VER_MASK(0) | EC_VER_MASK(1)); #ifdef CONFIG_HOSTCMD_SKUID static enum ec_status @@ -1454,8 +1648,7 @@ host_command_get_sku_id(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_SKU_ID, - host_command_get_sku_id, +DECLARE_HOST_COMMAND(EC_CMD_GET_SKU_ID, host_command_get_sku_id, EC_VER_MASK(0)); #endif @@ -1469,24 +1662,7 @@ host_command_set_sku_id(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_SET_SKU_ID, - host_command_set_sku_id, - EC_VER_MASK(0)); -#endif - -#ifdef CONFIG_KEYBOARD_LANGUAGE_ID -static enum ec_status -host_command_get_keyboard_id(struct host_cmd_handler_args *args) -{ - struct ec_response_keyboard_id *r = args->response; - - r->keyboard_id = keyboard_get_keyboard_id(); - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_GET_KEYBOARD_ID, - host_command_get_keyboard_id, +DECLARE_HOST_COMMAND(EC_CMD_SET_SKU_ID, host_command_set_sku_id, EC_VER_MASK(0)); #endif @@ -1498,8 +1674,7 @@ host_command_build_info(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_BUILD_INFO, - host_command_build_info, +DECLARE_HOST_COMMAND(EC_CMD_GET_BUILD_INFO, host_command_build_info, EC_VER_MASK(0)); static enum ec_status @@ -1515,12 +1690,10 @@ host_command_get_chip_info(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_CHIP_INFO, - host_command_get_chip_info, +DECLARE_HOST_COMMAND(EC_CMD_GET_CHIP_INFO, host_command_get_chip_info, EC_VER_MASK(0)); -#ifdef CONFIG_BOARD_VERSION -enum ec_status +static enum ec_status host_command_get_board_version(struct host_cmd_handler_args *args) { struct ec_response_board_version *r = args->response; @@ -1537,45 +1710,10 @@ host_command_get_board_version(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_BOARD_VERSION, - host_command_get_board_version, +DECLARE_HOST_COMMAND(EC_CMD_GET_BOARD_VERSION, host_command_get_board_version, EC_VER_MASK(0)); -#endif -#ifdef CONFIG_HOSTCMD_VBNV_CONTEXT -enum ec_status host_command_vbnvcontext(struct host_cmd_handler_args *args) -{ - const struct ec_params_vbnvcontext *p = args->params; - struct ec_response_vbnvcontext *r; - int i; - - switch (p->op) { - case EC_VBNV_CONTEXT_OP_READ: - r = args->response; - for (i = 0; i < EC_VBNV_BLOCK_SIZE; ++i) - if (system_get_bbram(SYSTEM_BBRAM_IDX_VBNVBLOCK0 + i, - r->block + i)) - return EC_RES_ERROR; - args->response_size = sizeof(*r); - break; - case EC_VBNV_CONTEXT_OP_WRITE: - for (i = 0; i < EC_VBNV_BLOCK_SIZE; ++i) - if (system_set_bbram(SYSTEM_BBRAM_IDX_VBNVBLOCK0 + i, - p->block[i])) - return EC_RES_ERROR; - break; - default: - return EC_RES_ERROR; - } - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_VBNV_CONTEXT, - host_command_vbnvcontext, - EC_VER_MASK(EC_VER_VBNV_CONTEXT)); -#endif /* CONFIG_HOSTCMD_VBNV_CONTEXT */ - -enum ec_status host_command_reboot(struct host_cmd_handler_args *args) +static enum ec_status host_command_reboot(struct host_cmd_handler_args *args) { struct ec_params_reboot_ec p; @@ -1587,7 +1725,8 @@ enum ec_status host_command_reboot(struct host_cmd_handler_args *args) if (p.cmd == EC_REBOOT_CANCEL) { /* Cancel pending reboot */ - reboot_at_shutdown = EC_REBOOT_CANCEL; + reboot_at_shutdown.cmd = EC_REBOOT_CANCEL; + reboot_at_shutdown.flags = 0; return EC_RES_SUCCESS; } @@ -1601,15 +1740,15 @@ enum ec_status host_command_reboot(struct host_cmd_handler_args *args) } if (p.flags & EC_REBOOT_FLAG_ON_AP_SHUTDOWN) { /* Store request for processing at chipset shutdown */ - reboot_at_shutdown = p.cmd; + p.flags &= ~(EC_REBOOT_FLAG_ON_AP_SHUTDOWN); + reboot_at_shutdown = p; return EC_RES_SUCCESS; } #ifdef HAS_TASK_HOSTCMD - if (p.cmd == EC_REBOOT_JUMP_RO || - p.cmd == EC_REBOOT_JUMP_RW || - p.cmd == EC_REBOOT_COLD || - p.cmd == EC_REBOOT_HIBERNATE) { + if (p.cmd == EC_REBOOT_JUMP_RO || p.cmd == EC_REBOOT_JUMP_RW || + p.cmd == EC_REBOOT_COLD || p.cmd == EC_REBOOT_HIBERNATE || + p.cmd == EC_REBOOT_COLD_AP_OFF) { /* Clean busy bits on host for commands that won't return */ args->result = EC_RES_SUCCESS; host_send_response(args); @@ -1617,7 +1756,7 @@ enum ec_status host_command_reboot(struct host_cmd_handler_args *args) #endif CPRINTS("Executing host reboot command %d", p.cmd); - switch (handle_pending_reboot(p.cmd)) { + switch (handle_pending_reboot(p)) { case EC_SUCCESS: return EC_RES_SUCCESS; case EC_ERROR_INVAL: @@ -1628,21 +1767,18 @@ enum ec_status host_command_reboot(struct host_cmd_handler_args *args) return EC_RES_ERROR; } } -DECLARE_HOST_COMMAND(EC_CMD_REBOOT_EC, - host_command_reboot, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_REBOOT_EC, host_command_reboot, EC_VER_MASK(0)); -int system_can_boot_ap(void) +test_mockable int system_can_boot_ap(void) { int soc = -1; int pow = -1; -#if defined(CONFIG_BATTERY) && \ - defined(CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) +#if defined(CONFIG_BATTERY) && defined(CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) /* Require a minimum battery level to power on. If battery isn't * present, battery_state_of_charge_abs returns false. */ if (battery_state_of_charge_abs(&soc) == EC_SUCCESS && - soc >= CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) + soc >= CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) return 1; #endif @@ -1666,7 +1802,7 @@ __overridable const char *board_read_serial(void) { if (IS_ENABLED(CONFIG_FLASH_PSTATE) && IS_ENABLED(CONFIG_FLASH_PSTATE_BANK)) - return flash_read_pstate_serial(); + return crec_flash_read_pstate_serial(); else if (IS_ENABLED(CONFIG_OTP)) return otp_read_serial(); else @@ -1677,13 +1813,13 @@ __overridable int board_write_serial(const char *serialno) { if (IS_ENABLED(CONFIG_FLASH_PSTATE) && IS_ENABLED(CONFIG_FLASH_PSTATE_BANK)) - return flash_write_pstate_serial(serialno); + return crec_flash_write_pstate_serial(serialno); else if (IS_ENABLED(CONFIG_OTP)) return otp_write_serial(serialno); else return EC_ERROR_UNIMPLEMENTED; } -#endif /* CONFIG_SERIALNO_LEN */ +#endif /* CONFIG_SERIALNO_LEN */ #ifdef CONFIG_MAC_ADDR_LEN /* By default, read MAC address from flash, can be overridden. */ @@ -1691,7 +1827,7 @@ __overridable const char *board_read_mac_addr(void) { if (IS_ENABLED(CONFIG_FLASH_PSTATE) && IS_ENABLED(CONFIG_FLASH_PSTATE_BANK)) - return flash_read_pstate_mac_addr(); + return crec_flash_read_pstate_mac_addr(); else return ""; } @@ -1701,24 +1837,25 @@ __overridable int board_write_mac_addr(const char *mac_addr) { if (IS_ENABLED(CONFIG_FLASH_PSTATE) && IS_ENABLED(CONFIG_FLASH_PSTATE_BANK)) - return flash_write_pstate_mac_addr(mac_addr); + return crec_flash_write_pstate_mac_addr(mac_addr); else return EC_ERROR_UNIMPLEMENTED; } -#endif /* CONFIG_MAC_ADDR_LEN */ - -__attribute__((weak)) -void clock_enable_module(enum module_id module, int enable) -{ - /* - * Default weak implementation - for chips that don't support this - * function. - */ -} +#endif /* CONFIG_MAC_ADDR_LEN */ __test_only void system_common_reset_state(void) { jdata = 0; reset_flags = 0; jumped_to_image = 0; + system_info_flags = 0; +} + +__test_only enum ec_reboot_cmd system_common_get_reset_reboot_at_shutdown(void) +{ + int ret = reboot_at_shutdown.cmd; + + reboot_at_shutdown.cmd = EC_REBOOT_CANCEL; + + return ret; } diff --git a/common/system_boot_time.c b/common/system_boot_time.c new file mode 100644 index 0000000000..62ce39be7e --- /dev/null +++ b/common/system_boot_time.c @@ -0,0 +1,96 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "console.h" +#include "host_command.h" +#include "system.h" +#include "util.h" + +#include + +#ifdef CONFIG_SYSTEM_BOOT_TIME_LOGGING +/* Content of ap_boot_time will be lost on sysjump */ +static struct ec_response_get_boot_time ap_boot_time; +#endif + +/* This function updates timestamp for ap boot time params */ +void update_ap_boot_time(enum boot_time_param param) +{ +#ifdef CONFIG_SYSTEM_BOOT_TIME_LOGGING + static bool ap_booted; /* tracks AP booted after #PLTRST */ + static bool pltrst_transition; /* tracks #PLTRST transtion */ + + if (param > RESET_CNT) { + ccprintf("invalid boot_time_param: %d\n", param); + return; + } + if (param < RESET_CNT) { + ap_boot_time.timestamp[param] = get_time().val; + ccprintf("Boot Time: %d, %llu\n", param, + ap_boot_time.timestamp[param]); + } + + /* warm reboot counter set to 1 only when #PLTRST transtion is complete + * and AP is already booted (ap_booted = 1). + * In initial boot or cold reboot scenario (ap_booted = 0) warm reboot + * counter will be set to 0. + */ + switch (param) { + case PLTRST_HIGH: + /* warm reboot happened */ + if (ap_booted && pltrst_transition) + ap_boot_time.cnt = 1; + else /* cold reboot happened */ + ap_boot_time.cnt = 0; + + if (pltrst_transition) { + ap_booted = true; + pltrst_transition = false; + } + break; + case PLTRST_LOW: + /* #PLTRST is in transition state */ + pltrst_transition = true; + break; + case RESET_CNT: + ap_boot_time.cnt = 0; + + if (ap_booted) + pltrst_transition = false; + + ap_booted = false; + break; + default: + break; + } +#endif +} + +#ifdef CONFIG_SYSTEM_BOOT_TIME_LOGGING +/* Returns system boot time data */ +static enum ec_status +host_command_get_boot_time(struct host_cmd_handler_args *args) +{ + struct ec_response_get_boot_time *boot_time = args->response; + + if (args->response_max < sizeof(*boot_time)) { + return EC_RES_RESPONSE_TOO_BIG; + } + + /* update current time */ + update_ap_boot_time(EC_CUR_TIME); + + /* copy data from ap_boot_time struct */ + memcpy(boot_time, &ap_boot_time, sizeof(*boot_time)); + + args->response_size = sizeof(*boot_time); + + return EC_RES_SUCCESS; +} + +DECLARE_HOST_COMMAND(EC_CMD_GET_BOOT_TIME, host_command_get_boot_time, + EC_VER_MASK(0)); +#endif diff --git a/common/system_safe_mode.c b/common/system_safe_mode.c new file mode 100644 index 0000000000..33be2622f5 --- /dev/null +++ b/common/system_safe_mode.c @@ -0,0 +1,186 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "console.h" +#include "cpu.h" +#include "ec_commands.h" +#include "hooks.h" +#include "host_command.h" +#include "panic.h" +#include "stddef.h" +#include "system.h" +#include "system_safe_mode.h" +#include "task.h" +#include "timer.h" +#include "watchdog.h" + +#define STACK_PRINT_SIZE_WORDS 32 + +#define CANNOT_ENTER_SAFE_MODE_FMT "Cannot start SSM: %s\n" + +static bool in_safe_mode; + +static const int safe_mode_allowed_hostcmds[] = { + EC_CMD_CONSOLE_READ, + EC_CMD_CONSOLE_SNAPSHOT, + EC_CMD_GET_NEXT_EVENT, + EC_CMD_GET_PANIC_INFO, + EC_CMD_GET_PROTOCOL_INFO, + EC_CMD_GET_UPTIME_INFO, + EC_CMD_GET_VERSION, + EC_CMD_MEMORY_DUMP_GET_ENTRY_INFO, + EC_CMD_MEMORY_DUMP_GET_METADATA, + EC_CMD_MEMORY_DUMP_READ_MEMORY, + EC_CMD_SYSINFO, +}; + +bool is_task_safe_mode_critical(task_id_t task_id) +{ + const task_id_t safe_mode_critical_tasks[] = { +#ifdef HAS_TASK_HOOKS + TASK_ID_HOOKS, +#endif + TASK_ID_IDLE, +#ifdef HAS_TASK_HOSTCMD + TASK_ID_HOSTCMD, +#endif +#ifdef HAS_TASK_MAIN + TASK_ID_MAIN, +#endif +#ifdef HAS_TASK_SYSWORKQ + TASK_ID_SYSWORKQ, +#endif + }; + for (int i = 0; i < ARRAY_SIZE(safe_mode_critical_tasks); i++) + if (safe_mode_critical_tasks[i] == task_id) + return true; + return false; +} + +bool is_current_task_safe_mode_critical(void) +{ + return is_task_safe_mode_critical(task_get_current()); +} + +#ifndef CONFIG_ZEPHYR + +int disable_non_safe_mode_critical_tasks(void) +{ + for (task_id_t task_id = 0; task_id < TASK_ID_COUNT; task_id++) { + /* Do not disable current task, + * that is the responsibility of the panic handler. + * If the current task is disabled while outside an interrupt + * context, execution will halt. + */ + if (!is_task_safe_mode_critical(task_id) && + task_id != task_get_current()) + task_disable_task(task_id); + } + return EC_SUCCESS; +} + +#endif /* CONFIG_ZEPHYR */ + +void handle_system_safe_mode_timeout(void) +{ + panic_printf("SSM timeout\n"); + panic_reboot(); +} +DECLARE_DEFERRED(handle_system_safe_mode_timeout); + +bool system_is_in_safe_mode(void) +{ + return !!in_safe_mode; +} + +/* + * Print contents of stack to console buffer. + */ +static void print_panic_stack(void) +{ + uint32_t sp; + const struct panic_data *pdata = panic_get_data(); + + ccprintf("\nStack Contents"); + sp = get_panic_stack_pointer(pdata); + for (int i = 0; i < STACK_PRINT_SIZE_WORDS; i++) { + if (sp == 0 || + sp + sizeof(uint32_t) > CONFIG_RAM_BASE + CONFIG_RAM_SIZE) { + ccprintf("\nSP(%x) out of range", sp); + break; + } + if (i % 4 == 0) + ccprintf("\n%08x:", sp); + ccprintf(" %08x", *(uint32_t *)sp); + sp += sizeof(uint32_t); + } + ccprintf("\n"); + /* Flush so dump isn't mixed with other output */ + cflush(); +} + +bool command_is_allowed_in_safe_mode(int command) +{ + for (int i = 0; i < ARRAY_SIZE(safe_mode_allowed_hostcmds); i++) + if (command == safe_mode_allowed_hostcmds[i]) + return true; + return false; +} + +static void system_safe_mode_start(void) +{ + ccprintf("Post Panic SSM\n"); + if (IS_ENABLED(CONFIG_SYSTEM_SAFE_MODE_PRINT_STACK)) + print_panic_stack(); + if (IS_ENABLED(CONFIG_HOSTCMD_EVENTS)) + host_set_single_event(EC_HOST_EVENT_PANIC); +} +DECLARE_DEFERRED(system_safe_mode_start); + +int start_system_safe_mode(void) +{ + if (!system_is_in_rw()) { + panic_printf(CANNOT_ENTER_SAFE_MODE_FMT, "RO image"); + return EC_ERROR_INVAL; + } + + if (system_is_in_safe_mode()) { + panic_printf(CANNOT_ENTER_SAFE_MODE_FMT, "Already in SSM"); + return EC_ERROR_INVAL; + } + + if (is_current_task_safe_mode_critical()) { + /* TODO: Restart critical tasks */ + panic_printf(CANNOT_ENTER_SAFE_MODE_FMT, + "Panic in critical task"); + return EC_ERROR_INVAL; + } + + hook_call_deferred(&handle_system_safe_mode_timeout_data, + CONFIG_SYSTEM_SAFE_MODE_TIMEOUT_MSEC * MSEC); + + /* + * Schedule a deferred function to run immediately + * after returning from fault handler. Defer operations that + * must not run in an ISR to this function. + */ + hook_call_deferred(&system_safe_mode_start_data, 0); + + disable_non_safe_mode_critical_tasks(); + + in_safe_mode = true; + + panic_printf("Starting SSM\n"); + + return EC_SUCCESS; +} + +#ifdef TEST_BUILD +void set_system_safe_mode(bool mode) +{ + in_safe_mode = mode; +} +#endif diff --git a/common/tablet_mode.c b/common/tablet_mode.c index 5486ffc668..1fdf698a1d 100644 --- a/common/tablet_mode.c +++ b/common/tablet_mode.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,18 +9,25 @@ #include "hooks.h" #include "host_command.h" #include "lid_angle.h" +#include "lid_switch.h" #include "stdbool.h" #include "tablet_mode.h" #include "timer.h" -#define CPRINTS(format, args...) cprints(CC_MOTION_LID, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_MOTION_LID, format, ## args) +#include + +#define CPRINTS(format, args...) cprints(CC_MOTION_LID, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_MOTION_LID, format, ##args) /* - * Other code modules assume that notebook mode (i.e. tablet_mode = false) at - * startup + * Other code modules assume that notebook mode (i.e. tablet_mode = 0) at + * startup. + * tablet_mode is mask, one bit for each source that can trigger a change to + * tablet mode: + * - TABLET_TRIGGER_LID: the lid angle is over the threshold. + * - TABLET_TRIGGER_BASE: the detachable keyboard is disconnected. */ -static bool tablet_mode; +static uint32_t tablet_mode; /* * Console command can force the value of tablet_mode. If tablet_mode_force is @@ -28,8 +35,17 @@ static bool tablet_mode; */ static bool tablet_mode_forced; -/* True if GMR sensor is reporting 360 degrees. */ -static bool gmr_sensor_at_360; +/* + * Console command can force the value of tablet_mode. If tablet_mode_force is + * false, use stored tablet mode value before it was (possibly) overridden. + */ +static uint32_t tablet_mode_store; + +/* True if the tablet GMR sensor is reporting 360 degrees. */ +STATIC_IF(CONFIG_GMR_TABLET_MODE) bool gmr_sensor_at_360; + +/* True if the lid GMR sensor is reporting 0 degrees. */ +STATIC_IF(CONFIG_GMR_TABLET_MODE) bool gmr_sensor_at_0; /* * True: all calls to tablet_set_mode are ignored and tablet_mode if forced to 0 @@ -37,14 +53,25 @@ static bool gmr_sensor_at_360; */ static bool disabled; +static const char *const tablet_mode_names[] = { + "clamshell", + "tablet", +}; +BUILD_ASSERT(ARRAY_SIZE(tablet_mode_names) == 2); + int tablet_get_mode(void) { - return tablet_mode; + return !!tablet_mode; +} + +static inline void print_tablet_mode(void) +{ + CPRINTS("%s mode", tablet_mode_names[tablet_get_mode()]); } static void notify_tablet_mode_change(void) { - CPRINTS("tablet mode %sabled", tablet_mode ? "en" : "dis"); + print_tablet_mode(); hook_notify(HOOK_TABLET_MODE_CHANGE); /* @@ -53,53 +80,98 @@ static void notify_tablet_mode_change(void) */ if (IS_ENABLED(CONFIG_HOSTCMD_EVENTS)) host_set_single_event(EC_HOST_EVENT_MODE_CHANGE); - } -void tablet_set_mode(int mode) +void tablet_set_mode(int mode, uint32_t trigger) { - /* If tablet_mode is forced via a console command, ignore set. */ - if (tablet_mode_forced) - return; + uint32_t new_mode = tablet_mode_forced ? tablet_mode_store : + tablet_mode; + uint32_t old_mode = 0; - if (tablet_mode == !!mode) + if (disabled) { + /* + * If tablet mode is being forced by the user, then this logging + * would be misleading since the mode wouldn't change anyway, so + * skip it. + */ + if (!tablet_mode_forced) + CPRINTS("Tablet mode set while disabled (ignoring)!"); return; + } - if (disabled) { - CPRINTS("Tablet mode set while disabled (ignoring)!"); + if (IS_ENABLED(CONFIG_GMR_TABLET_MODE) && + ((gmr_sensor_at_360 && !mode) || (gmr_sensor_at_0 && mode))) { + /* + * If tablet mode is being forced by the user, then this logging + * would be misleading since the mode wouldn't change anyway, so + * skip it. + */ + if (!tablet_mode_forced) + CPRINTS("Ignoring %s mode entry while gmr sensors " + "reports lid %s", + tablet_mode_names[mode], + (gmr_sensor_at_360 ? "flipped" : "closed")); return; } - if (gmr_sensor_at_360 && !mode) { - CPRINTS("Ignoring tablet mode exit while gmr sensor " - "reports 360-degree tablet mode."); + if (mode) + new_mode |= trigger; + else + new_mode &= ~trigger; + + if (tablet_mode_forced) { + /* + * Save the current mode based on the HW orientation, so we + * apply the correct mode if tablet mode no longer forced in the + * future. Don't notify of the tablet mode change yet, since + * that will be done as part of handling 'tabletmode reset'. + */ + tablet_mode_store = new_mode; return; } - tablet_mode = !!mode; + old_mode = tablet_mode; + tablet_mode = new_mode; + + /* Boolean comparison */ + if (!tablet_mode == !old_mode) + return; notify_tablet_mode_change(); } void tablet_disable(void) { - tablet_mode = false; + bool need_to_notify = false; + + /* Already disabled, nothing to do. */ + if (disabled) + return; + disabled = true; + /* + * We may have already transition to tablet mode: + * At board init time, while the sensors are not running yet, we may + * have read the Tablet GMR GPIO already, and transitioned to tablet + * mode, especially if the GMR is not stuffed and the GPIO is floating. + */ + if (tablet_get_mode()) + need_to_notify = true; + tablet_mode = 0; + if (need_to_notify) + notify_tablet_mode_change(); } /* This ifdef can be removed once we clean up past projects which do own init */ #ifdef CONFIG_GMR_TABLET_MODE -#ifndef GMR_TABLET_MODE_GPIO_L -#error GMR_TABLET_MODE_GPIO_L must be defined -#endif #ifdef CONFIG_DPTF_MOTION_LID_NO_GMR_SENSOR #error The board has GMR sensor #endif static void gmr_tablet_switch_interrupt_debounce(void) { - gmr_sensor_at_360 = IS_ENABLED(CONFIG_GMR_TABLET_MODE_CUSTOM) - ? board_sensor_at_360() - : !gpio_get_level(GMR_TABLET_MODE_GPIO_L); + gmr_sensor_at_360 = IS_ENABLED(CONFIG_GMR_TABLET_MODE_CUSTOM) ? + board_sensor_at_360() : + !gpio_get_level(GPIO_TABLET_MODE_L); /* * DPTF table is updated only when the board enters/exits completely @@ -108,10 +180,18 @@ static void gmr_tablet_switch_interrupt_debounce(void) * calculation and update DPTF table when lid angle > 300 degrees. */ if (IS_ENABLED(CONFIG_HOSTCMD_X86) && IS_ENABLED(CONFIG_DPTF)) { - acpi_dptf_set_profile_num(gmr_sensor_at_360 ? - DPTF_PROFILE_FLIPPED_360_MODE : - DPTF_PROFILE_CLAMSHELL); + acpi_dptf_set_profile_num( + gmr_sensor_at_360 ? DPTF_PROFILE_FLIPPED_360_MODE : + DPTF_PROFILE_CLAMSHELL); } + + /* + * When tablet mode is only decided by the GMR sensor (or + * or substitute, send the tablet_mode change request. + */ + if (!IS_ENABLED(CONFIG_LID_ANGLE)) + tablet_set_mode(gmr_sensor_at_360, TABLET_TRIGGER_LID); + /* * 1. Peripherals are disabled only when lid reaches 360 position (It's * probably already disabled by motion_sense task). We deliberately do @@ -123,18 +203,37 @@ static void gmr_tablet_switch_interrupt_debounce(void) * deliberately do not clear tablet mode when lid is leaving 360 * position(if motion lid driver is used). Instead, we let motion lid * driver to clear it when lid goes into laptop zone. + * 3. However, there is a potential race condition with + * tablet_mode_lid_event() which can be triggered before this debounce + * function is called, with |gmr_sensor_at_360| still true. + * When we notice the lid is closed when the this function is called and + * |gmr_sensor_at_360| false, send a transition to go in clamshell mode. + * It would mean the user was able to transition in less than ~10ms... */ - - if (!IS_ENABLED(CONFIG_LID_ANGLE) || gmr_sensor_at_360) - tablet_set_mode(gmr_sensor_at_360); + if (IS_ENABLED(CONFIG_LID_ANGLE)) { + if (gmr_sensor_at_360) + tablet_set_mode(1, TABLET_TRIGGER_LID); + else if (gmr_sensor_at_0) + tablet_set_mode(0, TABLET_TRIGGER_LID); + } if (IS_ENABLED(CONFIG_LID_ANGLE_UPDATE) && gmr_sensor_at_360) lid_angle_peripheral_enable(0); } DECLARE_DEFERRED(gmr_tablet_switch_interrupt_debounce); -/* Debounce time for gmr sensor tablet mode interrupt */ -#define GMR_SENSOR_DEBOUNCE_US (30 * MSEC) +/* + * Debounce time for gmr sensor tablet mode interrupt + * There could be a race between the GMR sensor for the tablet and + * the GMR sensor for the lid changes state at the same time. + * We let the lid sensor GMR debouce first. We would be able to go in tablet + * mode when LID_OPEN goes from low to high and TABLET_MODE_L goes from high + * to low. + * However, in the opposite case, the debouce lid angle interrupt will request + * the tablet_mode to be clamshell, but |gmr_sensor_at_360| will still be true, + * the request will be ignored. + */ +#define GMR_SENSOR_DEBOUNCE_US (LID_DEBOUNCE_US + 10 * MSEC) void gmr_tablet_switch_isr(enum gpio_signal signal) { @@ -142,42 +241,113 @@ void gmr_tablet_switch_isr(enum gpio_signal signal) GMR_SENSOR_DEBOUNCE_US); } +/* + * tablet gmr sensor() calls tablet_set_mode() to go in tablet mode + * when we know for sure the tablet is in tablet mode, + * + * It would call tablet_set_mode() to get out only when there are not + * accelerometer, as we want to get out at ~180 degree. + * But if for some reason the accelerometers are not working, we won't get + * out of tablet mode. Therefore, we need a similar function to go in + * clamshell mode when the lid is closed. + */ +static __maybe_unused void tablet_mode_lid_event(void) +{ + if (!lid_is_open()) { + gmr_sensor_at_0 = true; + tablet_set_mode(0, TABLET_TRIGGER_LID); + if (IS_ENABLED(CONFIG_LID_ANGLE_UPDATE)) + lid_angle_peripheral_enable(1); + } else { + gmr_sensor_at_0 = false; + } +} +#if defined(CONFIG_LID_ANGLE) && defined(CONFIG_LID_SWITCH) +DECLARE_HOOK(HOOK_LID_CHANGE, tablet_mode_lid_event, HOOK_PRIO_DEFAULT); +#endif + static void gmr_tablet_switch_init(void) { /* If this sub-system was disabled before initializing, honor that. */ if (disabled) return; - gpio_enable_interrupt(GMR_TABLET_MODE_GPIO_L); + gpio_enable_interrupt(GPIO_TABLET_MODE_L); /* * Ensure tablet mode is initialized according to the hardware state * so that the cached state reflects reality. */ gmr_tablet_switch_interrupt_debounce(); + if (IS_ENABLED(CONFIG_LID_ANGLE) && IS_ENABLED(CONFIG_LID_SWITCH)) + tablet_mode_lid_event(); } -DECLARE_HOOK(HOOK_INIT, gmr_tablet_switch_init, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, gmr_tablet_switch_init, HOOK_PRIO_POST_LID); void gmr_tablet_switch_disable(void) { - gpio_disable_interrupt(GMR_TABLET_MODE_GPIO_L); + gpio_disable_interrupt(GPIO_TABLET_MODE_L); /* Cancel any pending debounce calls */ hook_call_deferred(&gmr_tablet_switch_interrupt_debounce_data, -1); tablet_disable(); } -#endif +#endif /* CONFIG_GMR_TABLET_MODE */ + +static enum ec_status tablet_mode_command(struct host_cmd_handler_args *args) +{ + const struct ec_params_set_tablet_mode *p = args->params; + + if (tablet_mode_forced == false) + tablet_mode_store = tablet_mode; + + switch (p->tablet_mode) { + case TABLET_MODE_DEFAULT: + tablet_mode = tablet_mode_store; + tablet_mode_forced = false; + break; + case TABLET_MODE_FORCE_TABLET: + tablet_mode = TABLET_TRIGGER_LID; + tablet_mode_forced = true; + break; + case TABLET_MODE_FORCE_CLAMSHELL: + tablet_mode = 0; + tablet_mode_forced = true; + break; + default: + CPRINTS("Invalid EC_CMD_SET_TABLET_MODE parameter: %d", + p->tablet_mode); + return EC_RES_INVALID_PARAM; + } + + notify_tablet_mode_change(); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_SET_TABLET_MODE, tablet_mode_command, + EC_VER_MASK(0) | EC_VER_MASK(1)); -static int command_settabletmode(int argc, char **argv) +#ifdef CONFIG_TABLET_MODE +static int command_settabletmode(int argc, const char **argv) { + if (argc == 1) { + print_tablet_mode(); + return EC_SUCCESS; + } + if (argc != 2) return EC_ERROR_PARAM_COUNT; - if (argv[1][0] == 'o' && argv[1][1] == 'n') { - tablet_mode = true; + if (tablet_mode_forced == false) + tablet_mode_store = tablet_mode; + + /* |+1| to also make sure the strings the same length. */ + if (strncmp(argv[1], "on", strlen("on") + 1) == 0) { + tablet_mode = TABLET_TRIGGER_LID; tablet_mode_forced = true; - } else if (argv[1][0] == 'o' && argv[1][1] == 'f') { - tablet_mode = false; + } else if (strncmp(argv[1], "off", strlen("off") + 1) == 0) { + tablet_mode = 0; tablet_mode_forced = true; - } else if (argv[1][0] == 'r') { + } else if (strncmp(argv[1], "reset", strlen("reset") + 1) == 0) { + tablet_mode = tablet_mode_store; tablet_mode_forced = false; } else { return EC_ERROR_PARAM1; @@ -186,6 +356,13 @@ static int command_settabletmode(int argc, char **argv) notify_tablet_mode_change(); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(tabletmode, command_settabletmode, - "[on | off | reset]", - "Manually force tablet mode to on, off or reset."); +DECLARE_CONSOLE_COMMAND(tabletmode, command_settabletmode, "[on | off | reset]", + "Manually force tablet mode to on, off or reset."); +#endif + +__test_only void tablet_reset(void) +{ + tablet_mode = 0; + tablet_mode_forced = false; + disabled = false; +} diff --git a/common/temp_sensor.c b/common/temp_sensor.c index 0f687bb2a2..ccd9b3bc26 100644 --- a/common/temp_sensor.c +++ b/common/temp_sensor.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,6 +15,11 @@ #include "timer.h" #include "util.h" +#ifdef CONFIG_ZEPHYR +#include "temp_sensor/temp_sensor.h" +#endif + +#ifndef CONFIG_ZEPHYR int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr) { const struct temp_sensor_t *sensor; @@ -25,6 +30,7 @@ int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr) return sensor->read(sensor->idx, temp_ptr); } +#endif static void update_mapped_memory(void) { @@ -38,8 +44,7 @@ static void update_mapped_memory(void) */ if (i == EC_TEMP_SENSOR_ENTRIES) mptr = host_get_memmap(EC_MEMMAP_TEMP_SENSOR_B); - else if (i >= EC_TEMP_SENSOR_ENTRIES + - EC_TEMP_SENSOR_B_ENTRIES) + else if (i >= EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES) break; switch (temp_sensor_read(i, &t)) { @@ -94,31 +99,30 @@ static void temp_sensor_init(void) } DECLARE_HOOK(HOOK_INIT, temp_sensor_init, HOOK_PRIO_DEFAULT); -/*****************************************************************************/ -/* Console commands */ - -static int command_temps(int argc, char **argv) +int print_temps(void) { int t, i; int rv, rv1 = EC_SUCCESS; for (i = 0; i < TEMP_SENSOR_COUNT; ++i) { - ccprintf(" %-20s: ", temp_sensors[i].name); + ccprintf(" %-20s ", temp_sensors[i].name); rv = temp_sensor_read(i, &t); if (rv) rv1 = rv; switch (rv) { case EC_SUCCESS: - ccprintf("%d K = %d C", t, K_TO_C(t)); + ccprintf("%d K (= %d C)", t, K_TO_C(t)); #ifdef CONFIG_THROTTLE_AP if (thermal_params[i].temp_fan_off && thermal_params[i].temp_fan_max) - ccprintf(" %d%%", + ccprintf(" %11d%% (%d K and %d K)", thermal_fan_percent( thermal_params[i].temp_fan_off, thermal_params[i].temp_fan_max, - t)); + t), + thermal_params[i].temp_fan_off, + thermal_params[i].temp_fan_max); #endif ccprintf("\n"); break; @@ -135,14 +139,24 @@ static int command_temps(int argc, char **argv) return rv1; } -DECLARE_CONSOLE_COMMAND(temps, command_temps, - NULL, - "Print temp sensors"); + +/*****************************************************************************/ +/* Console commands */ + +#ifdef CONFIG_CMD_TEMP_SENSOR +static int command_temps(int argc, const char **argv) +{ + return print_temps(); +} +DECLARE_CONSOLE_COMMAND(temps, command_temps, NULL, + "Print temp sensors and temp ratio."); +#endif /*****************************************************************************/ /* Host commands */ -enum ec_status temp_sensor_command_get_info(struct host_cmd_handler_args *args) +static enum ec_status +temp_sensor_command_get_info(struct host_cmd_handler_args *args) { const struct ec_params_temp_sensor_get_info *p = args->params; struct ec_response_temp_sensor_get_info *r = args->response; @@ -158,6 +172,5 @@ enum ec_status temp_sensor_command_get_info(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_TEMP_SENSOR_GET_INFO, - temp_sensor_command_get_info, +DECLARE_HOST_COMMAND(EC_CMD_TEMP_SENSOR_GET_INFO, temp_sensor_command_get_info, EC_VER_MASK(0)); diff --git a/common/test_util.c b/common/test_util.c index 704fa1d018..9316b36bf1 100644 --- a/common/test_util.c +++ b/common/test_util.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -19,6 +19,8 @@ #include "test_util.h" #include "util.h" +#include + struct test_util_tag { uint8_t error_count; }; @@ -29,23 +31,42 @@ struct test_util_tag { int __test_error_count; /* Weak reference function as an entry point for unit test */ -test_mockable void run_test(int argc, char **argv) { } +test_mockable void run_test(int argc, const char **argv) +{ + /* This function should always be replaced by a real implementation of + * run_test(). + * If this assertion is failing, it means your test was not linked + * correctly. Check the signature of run_test() defined in your test + * matches the one above. + */ + ccprintf("%s:%d: ASSERTION failed: ran weakly linked fallback test\n", + __FILE__, __LINE__); + assert(0); +} /* Default mock test init */ -test_mockable void test_init(void) { } +test_mockable void test_init(void) +{ +} /* Default mock before test */ -test_mockable void before_test(void) { } +test_mockable void before_test(void) +{ +} /* Default mock after test */ -test_mockable void after_test(void) { } +test_mockable void after_test(void) +{ +} #ifdef TEST_COVERAGE -extern void __gcov_flush(void); +extern void __gcov_dump(void); +extern void __gcov_reset(void); void emulator_flush(void) { - __gcov_flush(); + __gcov_dump(); + __gcov_reset(); } #else void emulator_flush(void) @@ -102,18 +123,26 @@ int test_get_error_count(void) uint32_t test_get_state(void) { - return system_get_scratchpad(); + uint32_t state; + + system_get_scratchpad(&state); + return state; } test_mockable void test_clean_up(void) { } +void test_set_next_step(enum test_state_t step) +{ + system_set_scratchpad(TEST_STATE_MASK(step)); +} + void test_reboot_to_next_step(enum test_state_t step) { ccprintf("Rebooting to next test step...\n"); cflush(); - system_set_scratchpad(TEST_STATE_MASK(step)); + test_set_next_step(step); system_reset(SYSTEM_RESET_HARD); } @@ -144,8 +173,9 @@ void test_run_multistep(void) } #ifdef HAS_TASK_HOSTCMD -int test_send_host_command(int command, int version, const void *params, - int params_size, void *resp, int resp_size) +enum ec_status test_send_host_command(int command, int version, + const void *params, int params_size, + void *resp, int resp_size) { struct host_cmd_handler_args args; @@ -159,7 +189,7 @@ int test_send_host_command(int command, int version, const void *params, return host_command_process(&args); } -#endif /* TASK_HAS_HOSTCMD */ +#endif /* TASK_HAS_HOSTCMD */ /* Linear congruential pseudo random number generator */ uint32_t prng(uint32_t seed) @@ -180,8 +210,7 @@ static void restore_state(void) tag = (const struct test_util_tag *)system_get_jump_tag( TEST_UTIL_SYSJUMP_TAG, &version, &size); - if (tag && version == TEST_UTIL_SYSJUMP_VERSION && - size == sizeof(*tag)) + if (tag && version == TEST_UTIL_SYSJUMP_VERSION && size == sizeof(*tag)) __test_error_count = tag->error_count; else __test_error_count = 0; @@ -197,10 +226,30 @@ static void preserve_state(void) } DECLARE_HOOK(HOOK_SYSJUMP, preserve_state, HOOK_PRIO_DEFAULT); -static int command_run_test(int argc, char **argv) +static int command_run_test(int argc, const char **argv) { run_test(argc, argv); return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(runtest, command_run_test, - NULL, NULL); +DECLARE_CONSOLE_COMMAND(runtest, command_run_test, NULL, NULL); + +#ifndef CONFIG_ZEPHYR +void z_ztest_run_test_suite(const char *name, struct unit_test *suite) +{ + test_reset(); + + while (suite->test) { + suite->setup(); + RUN_TEST(suite->test); + suite->teardown(); + suite++; + } + + /* Sometimes the console task doesn't start until the test is done. */ + sleep(1); + + ccprintf("%s: ", name); + + test_print_result(); +} +#endif /* CONFIG_ZEPHYR */ diff --git a/common/thermal.c b/common/thermal.c index d1cc47e924..89c145556e 100644 --- a/common/thermal.c +++ b/common/thermal.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,15 +19,31 @@ #include "timer.h" #include "util.h" +#ifdef CONFIG_ZEPHYR +#include "temp_sensor/temp_sensor.h" +#endif + /* Console output macros */ #define CPUTS(outstr) cputs(CC_THERMAL, outstr) -#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) /*****************************************************************************/ /* EC-specific thermal controls */ +#ifdef CONFIG_CUSTOMIZED_DESIGN +__overridable int board_temp_smi_evet(void) +{ + /* Do nothing by default. Boards can modify the temps condition */ + return true; +} +#endif + test_mockable_static void smi_sensor_failure_warning(void) { +#ifdef CONFIG_CUSTOMIZED_DESIGN + if (!board_temp_smi_evet()) + return; +#endif CPRINTS("can't read any temp sensors!"); host_set_single_event(EC_HOST_EVENT_THERMAL); } @@ -48,36 +64,54 @@ BUILD_ASSERT(EC_TEMP_THRESH_COUNT == 3); /* Keep track of which thresholds have triggered */ static cond_t cond_hot[EC_TEMP_THRESH_COUNT]; +#ifdef CONFIG_PLATFORM_EC_CUSTOMIZED_DESIGN +static bool thermal_warn_active; +#endif + +/* thermal sensor read delay */ +#if defined(CONFIG_TEMP_SENSOR_POWER) && \ + defined(CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS) +static int first_read_delay = CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS; +#endif static void thermal_control(void) { - int i, j, t, rv, f; + int i, j, t, rv; int count_over[EC_TEMP_THRESH_COUNT]; int count_under[EC_TEMP_THRESH_COUNT]; int num_valid_limits[EC_TEMP_THRESH_COUNT]; int num_sensors_read; - int fmax; - int temp_fan_configured; - -#ifdef CONFIG_CUSTOM_FAN_CONTROL +#ifdef CONFIG_FANS +#ifndef CONFIG_CUSTOM_FAN_CONTROL + int f = 0; + int fmax = 0; + int temp_fan_configured = 0; +#else int temp[TEMP_SENSOR_COUNT]; #endif +#endif + + /* add delay to ensure thermal sensor is ready when EC boot */ +#if defined(CONFIG_TEMP_SENSOR_POWER) && \ + defined(CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS) + if (first_read_delay != 0) { + msleep(first_read_delay); + first_read_delay = 0; + } +#endif /* Get ready to count things */ memset(count_over, 0, sizeof(count_over)); memset(count_under, 0, sizeof(count_under)); memset(num_valid_limits, 0, sizeof(num_valid_limits)); num_sensors_read = 0; - fmax = 0; - temp_fan_configured = 0; /* go through all the sensors */ for (i = 0; i < TEMP_SENSOR_COUNT; ++i) { - /* read one */ rv = temp_sensor_read(i, &t); -#ifdef CONFIG_CUSTOM_FAN_CONTROL +#if defined(CONFIG_FANS) && defined(CONFIG_CUSTOM_FAN_CONTROL) /* Store all sensors value */ temp[i] = K_TO_C(t); #endif @@ -104,6 +138,8 @@ static void thermal_control(void) } } +#ifdef CONFIG_FANS +#ifndef CONFIG_CUSTOM_FAN_CONTROL /* figure out the max fan needed, too */ if (thermal_params[i].temp_fan_off && thermal_params[i].temp_fan_max) { @@ -115,6 +151,8 @@ static void thermal_control(void) temp_fan_configured = 1; } +#endif +#endif } if (!num_sensors_read) { @@ -156,6 +194,13 @@ static void thermal_control(void) if (cond_went_true(&cond_hot[EC_TEMP_THRESH_HALT])) { CPRINTS("thermal SHUTDOWN"); + + /* Print temperature sensor values before shutting down AP */ + if (IS_ENABLED(CONFIG_CMD_TEMP_SENSOR)) { + print_temps(); + cflush(); + } + chipset_force_shutdown(CHIPSET_SHUTDOWN_THERMAL); } else if (cond_went_false(&cond_hot[EC_TEMP_THRESH_HALT])) { /* We don't reboot automatically - the user has to push @@ -177,21 +222,27 @@ static void thermal_control(void) if (cond_went_true(&cond_hot[EC_TEMP_THRESH_WARN])) { CPRINTS("thermal WARN"); throttle_ap(THROTTLE_ON, THROTTLE_SOFT, THROTTLE_SRC_THERMAL); +#ifdef CONFIG_PLATFORM_EC_CUSTOMIZED_DESIGN + thermal_warn_active = true; +#endif } else if (cond_went_false(&cond_hot[EC_TEMP_THRESH_WARN])) { CPRINTS("thermal no longer warn"); throttle_ap(THROTTLE_OFF, THROTTLE_SOFT, THROTTLE_SRC_THERMAL); +#ifdef CONFIG_PLATFORM_EC_CUSTOMIZED_DESIGN + thermal_warn_active = false; +#endif } - if (temp_fan_configured) { #ifdef CONFIG_FANS #ifdef CONFIG_CUSTOM_FAN_CONTROL - for (i = 0; i < fan_get_count(); i++) { - if (!is_thermal_control_enabled(i)) - continue; + for (i = 0; i < fan_get_count(); i++) { + if (!is_thermal_control_enabled(i)) + continue; - board_override_fan_control(i, temp); - } + board_override_fan_control(i, temp); + } #else + if (temp_fan_configured) { /* TODO(crosbug.com/p/23797): For now, we just treat all * fans the same. It would be better if we could assign * different thermal profiles to each fan - in case one @@ -200,41 +251,44 @@ static void thermal_control(void) */ for (i = 0; i < fan_get_count(); i++) fan_set_percent_needed(i, fmax); + } #endif #endif - } } /* Wait until after the sensors have been read */ DECLARE_HOOK(HOOK_SECOND, thermal_control, HOOK_PRIO_TEMP_SENSOR_DONE); +/*****************************************************************************/ +/* Project */ +bool thermal_warn_trigger(void) +{ + return thermal_warn_active; +} + /*****************************************************************************/ /* Console commands */ -static int command_thermalget(int argc, char **argv) +static int command_thermalget(int argc, const char **argv) { int i; ccprintf("sensor warn high halt fan_off fan_max name\n"); for (i = 0; i < TEMP_SENSOR_COUNT; i++) { ccprintf(" %2d %3d %3d %3d %3d %3d %s\n", - i, - thermal_params[i].temp_host[EC_TEMP_THRESH_WARN], + i, thermal_params[i].temp_host[EC_TEMP_THRESH_WARN], thermal_params[i].temp_host[EC_TEMP_THRESH_HIGH], thermal_params[i].temp_host[EC_TEMP_THRESH_HALT], thermal_params[i].temp_fan_off, - thermal_params[i].temp_fan_max, - temp_sensors[i].name); + thermal_params[i].temp_fan_max, temp_sensors[i].name); } return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(thermalget, command_thermalget, - NULL, +DECLARE_CONSOLE_COMMAND(thermalget, command_thermalget, NULL, "Print thermal parameters (degrees Kelvin)"); - -static int command_thermalset(int argc, char **argv) +static int command_thermalset(int argc, const char **argv) { unsigned int n; int i, val; @@ -298,8 +352,7 @@ thermal_command_set_threshold(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_THERMAL_SET_THRESHOLD, - thermal_command_set_threshold, - EC_VER_MASK(1)); + thermal_command_set_threshold, EC_VER_MASK(1)); static enum ec_status thermal_command_get_threshold(struct host_cmd_handler_args *args) @@ -315,5 +368,4 @@ thermal_command_get_threshold(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_THERMAL_GET_THRESHOLD, - thermal_command_get_threshold, - EC_VER_MASK(1)); + thermal_command_get_threshold, EC_VER_MASK(1)); diff --git a/common/throttle_ap.c b/common/throttle_ap.c index 8a4314db4d..77c3f83969 100644 --- a/common/throttle_ap.c +++ b/common/throttle_ap.c @@ -1,14 +1,16 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Common chipset throttling code for Chrome EC */ +#include "builtin/assert.h" #include "chipset.h" #include "common.h" #include "console.h" #include "dptf.h" +#include "gpio.h" #include "hooks.h" #include "host_command.h" #include "task.h" @@ -18,19 +20,23 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_THERMAL, outstr) -#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args) +#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args) -#define PROCHOT_IN_DEBOUNCE_US (100 * MSEC) +/* + * When C10 deasserts, PROCHOT may also change state when the corresponding + * power rail is turned back on. Recheck PROCHOT directly from the C10 exit + * using a shorter debounce than the PROCHOT interrupt. + */ +#define C10_IN_DEBOUNCE_US (10 * MSEC) /*****************************************************************************/ /* This enforces the virtual OR of all throttling sources. */ -static struct mutex throttle_mutex; +K_MUTEX_DEFINE(throttle_mutex); static uint32_t throttle_request[NUM_THROTTLE_TYPES]; static int debounced_prochot_in; -static enum gpio_signal gpio_prochot_in = GPIO_COUNT; +static const struct prochot_cfg *prochot_cfg; -void throttle_ap(enum throttle_level level, - enum throttle_type type, +void throttle_ap(enum throttle_level level, enum throttle_type type, enum throttle_sources source) { uint32_t tmpval, bitmask; @@ -48,7 +54,7 @@ void throttle_ap(enum throttle_level level, break; } - tmpval = throttle_request[type]; /* save for printing */ + tmpval = throttle_request[type]; /* save for printing */ switch (type) { case THROTTLE_SOFT: @@ -72,9 +78,32 @@ void throttle_ap(enum throttle_level level, mutex_unlock(&throttle_mutex); /* print outside the mutex */ - CPRINTS("set AP throttling type %d to %s (0x%08x)", - type, tmpval ? "on" : "off", tmpval); + CPRINTS("set AP throttling type %d to %s (0x%08x)", type, + tmpval ? "on" : "off", tmpval); +} + +void throttle_ap_config_prochot(const struct prochot_cfg *cfg) +{ + prochot_cfg = cfg; + if (IS_ENABLED(CONFIG_THROTTLE_AP_SINGLE_PIN)) { + gpio_set_flags(prochot_cfg->gpio_prochot_in, GPIO_INPUT); + } +} + +__maybe_unused static bool prochot_is_gated_by_c10(int prochot_in) +{ +#ifdef CONFIG_CPU_PROCHOT_GATE_ON_C10 + int c10_in = gpio_get_level(prochot_cfg->gpio_c10_in); + + if (!prochot_cfg->c10_active_high) + c10_in = !c10_in; + + if (c10_in && prochot_in) { + return true; + } +#endif + return false; } static void prochot_input_deferred(void) @@ -82,12 +111,11 @@ static void prochot_input_deferred(void) int prochot_in; /* - * Shouldn't be possible, but better to protect against buffer - * overflow + * Validate board called throttle_ap_config_prochot(). */ - ASSERT(signal_is_gpio(gpio_prochot_in)); + ASSERT(prochot_cfg); - prochot_in = gpio_get_level(gpio_prochot_in); + prochot_in = gpio_get_level(prochot_cfg->gpio_prochot_in); if (IS_ENABLED(CONFIG_CPU_PROCHOT_ACTIVE_LOW)) prochot_in = !prochot_in; @@ -95,44 +123,71 @@ static void prochot_input_deferred(void) if (prochot_in == debounced_prochot_in) return; + /* + * b/173180788 Confirmed from Intel internal that SLP_S3# asserts low + * about 10us before PROCHOT# asserts low, which means that + * the CPU is already in reset and therefore the PROCHOT# + * asserting low is normal behavior and not a concern + * for PROCHOT# event. Ignore all PROCHOT changes while the AP is off + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF | CHIPSET_STATE_ANY_SUSPEND)) + return; + + /* + * b/185810479 When the AP enters C10, the PROCHOT signal may not be + * valid. Refer to the CONFIG_CPU_PROCHOT_GATE_ON_C10 documentation + * for details. + */ + if (prochot_is_gated_by_c10(prochot_in)) + return; + debounced_prochot_in = prochot_in; if (debounced_prochot_in) { CPRINTS("External PROCHOT assertion detected"); -#ifdef CONFIG_FANS +#if defined(CONFIG_FANS) && !defined(CONFIG_THROTTLE_AP_NO_FAN) dptf_set_fan_duty_target(100); #endif } else { CPRINTS("External PROCHOT condition cleared"); -#ifdef CONFIG_FANS +#if defined(CONFIG_FANS) && !defined(CONFIG_THROTTLE_AP_NO_FAN) /* Revert to automatic control of the fan */ dptf_set_fan_duty_target(-1); #endif } + + if (prochot_cfg->callback) + prochot_cfg->callback(debounced_prochot_in, + prochot_cfg->callback_data); } DECLARE_DEFERRED(prochot_input_deferred); void throttle_ap_prochot_input_interrupt(enum gpio_signal signal) { - /* - * Save the PROCHOT signal that generated the interrupt so we don't - * rely on a specific pin name. - */ - if (gpio_prochot_in == GPIO_COUNT) - gpio_prochot_in = signal; - /* * Trigger deferred notification of PROCHOT change so we can ignore * any pulses that are too short. */ hook_call_deferred(&prochot_input_deferred_data, - PROCHOT_IN_DEBOUNCE_US); + PROCHOT_IN_DEBOUNCE_US); } +#ifdef CONFIG_CPU_PROCHOT_GATE_ON_C10 +void throttle_ap_c10_input_interrupt(enum gpio_signal signal) +{ + /* + * This interrupt is configured to fire only when the AP exits C10 + * and de-asserts the C10 signal. Recheck the PROCHOT signal in case + * another PROCHOT source is active when the AP exits C10. + */ + hook_call_deferred(&prochot_input_deferred_data, C10_IN_DEBOUNCE_US); +} +#endif + /*****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_APTHROTTLE -static int command_apthrottle(int argc, char **argv) +static int command_apthrottle(int argc, const char **argv) { int i; uint32_t tmpval; @@ -148,7 +203,6 @@ static int command_apthrottle(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(apthrottle, command_apthrottle, - NULL, +DECLARE_CONSOLE_COMMAND(apthrottle, command_apthrottle, NULL, "Display the AP throttling state"); #endif diff --git a/common/timer.c b/common/timer.c index c359efb541..9d45e4faf3 100644 --- a/common/timer.c +++ b/common/timer.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,56 +6,56 @@ /* Timer module for Chrome EC operating system */ #include "atomic.h" +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "hooks.h" #include "hwtimer.h" #include "system.h" -#include "util.h" #include "task.h" #include "timer.h" +#include "util.h" #include "watchdog.h" #ifdef CONFIG_ZEPHYR -#include /* For k_usleep() */ +#include /* For k_usleep() */ #else -extern __error("k_usleep() should only be called from Zephyr code") -int32_t k_usleep(int32_t); +extern __error("k_usleep() should only be called from Zephyr code") int32_t + k_usleep(int32_t); #endif /* CONFIG_ZEPHYR */ -#define TIMER_SYSJUMP_TAG 0x4d54 /* "TM" */ +#ifdef CONFIG_COMMON_RUNTIME +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#else +#define CPRINTS(format, args...) +#define CPRINTF(format, args...) +#endif + +#define TIMER_SYSJUMP_TAG 0x4d54 /* "TM" */ /* High 32-bits of the 64-bit timestamp counter. */ -STATIC_IF_NOT(CONFIG_HWTIMER_64BIT) uint32_t clksrc_high; +STATIC_IF_NOT(CONFIG_HWTIMER_64BIT) volatile uint32_t clksrc_high; +/* Hardware timer routine IRQ number */ +static int timer_irq; + +#ifndef CONFIG_ZEPHYR /* Bitmap of currently running timers */ static uint32_t timer_running; +BUILD_ASSERT((sizeof(timer_running) * 8) > TASK_ID_COUNT); + /* Deadlines of all timers */ static timestamp_t timer_deadline[TASK_ID_COUNT]; static uint32_t next_deadline = 0xffffffff; -/* Hardware timer routine IRQ number */ -static int timer_irq; - static void expire_timer(task_id_t tskid) { /* we are done with this timer */ - deprecated_atomic_clear_bits(&timer_running, 1 << tskid); + atomic_clear_bits((atomic_t *)&timer_running, 1 << tskid); /* wake up the taks waiting for this timer */ - task_set_event(tskid, TASK_EVENT_TIMER, 0); -} - -int timestamp_expired(timestamp_t deadline, const timestamp_t *now) -{ - timestamp_t now_val; - - if (!now) { - now_val = get_time(); - now = &now_val; - } - - return ((int64_t)(now->val - deadline.val) >= 0); + task_set_event(tskid, TASK_EVENT_TIMER); } void process_timers(int overflow) @@ -74,7 +74,6 @@ void process_timers(int overflow) /* read atomically the current state of timer running */ check_timer = running_t0 = timer_running; while (check_timer) { - int tskid = __fls(check_timer); /* timer has expired ? */ if (timer_deadline[tskid].val <= now.val) @@ -87,7 +86,7 @@ void process_timers(int overflow) check_timer &= ~BIT(tskid); } - /* if there is a new timer, let's retry */ + /* if there is a new timer, let's retry */ } while (timer_running & ~running_t0); if (next.le.hi == 0xffffffff) { @@ -101,11 +100,24 @@ void process_timers(int overflow) next_deadline = next.le.lo; } while (next.val <= get_time().val); } +#endif /* !defined(CONFIG_ZEPHYR) */ + +int timestamp_expired(timestamp_t deadline, const timestamp_t *now) +{ + timestamp_t now_val; + + if (!now) { + now_val = get_time(); + now = &now_val; + } + + return ((int64_t)(now->val - deadline.val) >= 0); +} #ifndef CONFIG_HW_SPECIFIC_UDELAY -void udelay(unsigned us) +void udelay(unsigned int us) { - unsigned t0 = __hw_clock_source_read(); + unsigned int t0 = __hw_clock_source_read(); /* * udelay() may be called with interrupts disabled, so we can't rely on @@ -122,6 +134,8 @@ void udelay(unsigned us) } #endif +/* Zephyr provides its own implementation in task shim */ +#ifndef CONFIG_ZEPHYR int timer_arm(timestamp_t event, task_id_t tskid) { timestamp_t now = get_time(); @@ -132,7 +146,7 @@ int timer_arm(timestamp_t event, task_id_t tskid) return EC_ERROR_BUSY; timer_deadline[tskid] = event; - deprecated_atomic_or(&timer_running, BIT(tskid)); + atomic_or((atomic_t *)&timer_running, BIT(tskid)); /* Modify the next event if needed */ if ((event.le.hi < now.le.hi) || @@ -146,12 +160,13 @@ void timer_cancel(task_id_t tskid) { ASSERT(tskid < TASK_ID_COUNT); - deprecated_atomic_clear_bits(&timer_running, BIT(tskid)); + atomic_clear_bits((atomic_t *)&timer_running, BIT(tskid)); /* * Don't need to cancel the hardware timer interrupt, instead do * timer-related housekeeping when the next timer interrupt fires. */ } +#endif /* * For us < (2^31 - task scheduling latency)(~ 2147 sec), this function will @@ -159,11 +174,15 @@ void timer_cancel(task_id_t tskid) * probability of delay longer than 2*us (and possibly infinite delay) * increases. */ -void usleep(unsigned us) +void usleep(unsigned int us) { uint32_t evt = 0; uint32_t t0; + /* If a wait is 0, return immediately. */ + if (!us) + return; + if (IS_ENABLED(CONFIG_ZEPHYR)) { while (us) us = k_usleep(us); @@ -178,27 +197,47 @@ void usleep(unsigned us) return; } - ASSERT(us); + /* If in interrupt context or interrupts are disabled, use udelay() */ + if (!is_interrupt_enabled() || in_interrupt_context()) { + CPRINTS("Sleeping not allowed"); + udelay(us); + return; + } + do { evt |= task_wait_event(us); } while (!(evt & TASK_EVENT_TIMER) && - ((__hw_clock_source_read() - t0) < us)); + ((__hw_clock_source_read() - t0) < us)); /* Re-queue other events which happened in the meanwhile */ if (evt) - deprecated_atomic_or(task_get_event_bitmap(task_get_current()), - evt & ~TASK_EVENT_TIMER); + atomic_or(task_get_event_bitmap(task_get_current()), + evt & ~TASK_EVENT_TIMER); } +#ifdef CONFIG_ZTEST +timestamp_t *get_time_mock; +#endif /* CONFIG_ZTEST */ + timestamp_t get_time(void) { timestamp_t ts; +#ifdef CONFIG_ZTEST + if (get_time_mock != NULL) + return *get_time_mock; +#endif /* CONFIG_ZTEST */ + if (IS_ENABLED(CONFIG_HWTIMER_64BIT)) { ts.val = __hw_clock_source_read64(); } else { ts.le.hi = clksrc_high; ts.le.lo = __hw_clock_source_read(); + /* + * TODO(b/213342294) If statement below doesn't catch overflows + * when interrupts are disabled or currently processed interrupt + * has higher priority. + */ if (ts.le.hi != clksrc_high) { ts.le.hi = clksrc_high; ts.le.lo = __hw_clock_source_read(); @@ -211,7 +250,7 @@ timestamp_t get_time(void) clock_t clock(void) { /* __hw_clock_source_read() returns a microsecond resolution timer.*/ - return (clock_t) __hw_clock_source_read() / 1000; + return (clock_t)__hw_clock_source_read() / 1000; } void force_time(timestamp_t ts) @@ -219,8 +258,24 @@ void force_time(timestamp_t ts) if (IS_ENABLED(CONFIG_HWTIMER_64BIT)) { __hw_clock_source_set64(ts.val); } else { + /* Save current interrupt state */ + bool interrupt_enabled = is_interrupt_enabled(); + + /* + * Updating timer shouldn't be interrupted (eg. when counter + * overflows) because it could lead to some unintended + * consequences. Please note that this function can be called + * with disabled or enabled interrupts so we need to restore + * the original state later. + */ + interrupt_disable(); + clksrc_high = ts.le.hi; __hw_clock_source_set(ts.le.lo); + + /* Restore original interrupt state */ + if (interrupt_enabled) + interrupt_enable(); } /* some timers might be already expired : process them */ @@ -248,9 +303,7 @@ void __hw_clock_source_set(uint32_t ts) void timer_print_info(void) { timestamp_t t = get_time(); - uint64_t deadline = (uint64_t)t.le.hi << 32 | - __hw_clock_event_get(); - int tskid; + uint64_t deadline = (uint64_t)t.le.hi << 32 | __hw_clock_event_get(); ccprintf("Time: 0x%016llx us, %11.6lld s\n" "Deadline: 0x%016llx -> %11.6lld s from now\n" @@ -258,7 +311,8 @@ void timer_print_info(void) t.val, t.val, deadline, deadline - t.val); cflush(); - for (tskid = 0; tskid < TASK_ID_COUNT; tskid++) { +#ifndef CONFIG_ZEPHYR + for (int tskid = 0; tskid < TASK_ID_COUNT; tskid++) { if (timer_running & BIT(tskid)) { ccprintf(" Tsk %2d 0x%016llx -> %11.6lld\n", tskid, timer_deadline[tskid].val, @@ -266,6 +320,7 @@ void timer_print_info(void) cflush(); } } +#endif /* !defined(CONFIG_ZEPHYR) */ } void timer_init(void) @@ -273,8 +328,6 @@ void timer_init(void) const timestamp_t *ts; int size, version; - BUILD_ASSERT(TASK_ID_COUNT < sizeof(timer_running) * 8); - /* Restore time from before sysjump */ ts = (const timestamp_t *)system_get_jump_tag(TIMER_SYSJUMP_TAG, &version, &size); @@ -303,7 +356,7 @@ static void timer_sysjump(void) DECLARE_HOOK(HOOK_SYSJUMP, timer_sysjump, HOOK_PRIO_DEFAULT); #ifdef CONFIG_CMD_WAITMS -static int command_wait(int argc, char **argv) +static int command_wait(int argc, const char **argv) { char *e; int i; @@ -315,6 +368,9 @@ static int command_wait(int argc, char **argv) if (*e) return EC_ERROR_PARAM1; + if (i < 0) + return EC_ERROR_PARAM1; + /* * Reload the watchdog so that issuing multiple small waitms commands * quickly one after the other will not cause a reset. @@ -333,8 +389,7 @@ static int command_wait(int argc, char **argv) return EC_SUCCESS; } /* Typically a large delay (e.g. 3s) will cause a reset */ -DECLARE_CONSOLE_COMMAND(waitms, command_wait, - "msec", +DECLARE_CONSOLE_COMMAND(waitms, command_wait, "msec", "Busy-wait for msec (large delays will reset)"); #endif @@ -344,7 +399,7 @@ DECLARE_CONSOLE_COMMAND(waitms, command_wait, * especially when going "backward" in time, because task deadlines are * left un-adjusted. */ -static int command_force_time(int argc, char **argv) +static int command_force_time(int argc, const char **argv) { char *e; timestamp_t new; @@ -365,32 +420,29 @@ static int command_force_time(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(forcetime, command_force_time, - "hi lo", +DECLARE_CONSOLE_COMMAND(forcetime, command_force_time, "hi lo", "Force current time"); #endif #ifdef CONFIG_CMD_GETTIME -static int command_get_time(int argc, char **argv) +static int command_get_time(int argc, const char **argv) { timestamp_t ts = get_time(); ccprintf("Time: 0x%016llx = %.6lld s\n", ts.val, ts.val); return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(gettime, command_get_time, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(gettime, command_get_time, NULL, "Print current time"); #endif #ifdef CONFIG_CMD_TIMERINFO -int command_timer_info(int argc, char **argv) +static int command_timer_info(int argc, const char **argv) { timer_print_info(); return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(timerinfo, command_timer_info, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(timerinfo, command_timer_info, NULL, "Print timer info"); #endif diff --git a/common/trng.c b/common/trng.c new file mode 100644 index 0000000000..273a078d7a --- /dev/null +++ b/common/trng.c @@ -0,0 +1,82 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Common Random Number Generation (RNG) routines */ + +#include "common.h" +#include "console.h" +#include "cpu.h" +#include "host_command.h" +#include "panic.h" +#include "printf.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "trng.h" +#include "util.h" + +test_mockable void trng_rand_bytes(void *buffer, size_t len) +{ + while (len) { + uint32_t number = trng_rand(); + size_t cnt = 4; + /* deal with the lack of alignment guarantee in the API */ + uintptr_t align = (uintptr_t)buffer & 3; + + if (len < 4 || align) { + cnt = MIN(4 - align, len); + memcpy(buffer, &number, cnt); + } else { + *(uint32_t *)buffer = number; + } + len -= cnt; + buffer += cnt; + } +} + +#if defined(CONFIG_CMD_RAND) +/* + * We want to avoid accidentally exposing debug commands in RO since we can't + * update RO once in production. + */ +#if defined(SECTION_IS_RW) +static int command_rand(int argc, const char **argv) +{ + uint8_t data[32]; + char str_buf[hex_str_buf_size(sizeof(data))]; + + trng_init(); + trng_rand_bytes(data, sizeof(data)); + trng_exit(); + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(data, sizeof(data))); + ccprintf("rand %s\n", str_buf); + + return EC_RES_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(rand, command_rand, NULL, + "Output random bytes to console."); + +static enum ec_status host_command_rand(struct host_cmd_handler_args *args) +{ + const struct ec_params_rand_num *p = args->params; + struct ec_response_rand_num *r = args->response; + uint16_t num_rand_bytes = p->num_rand_bytes; + + if (system_is_locked()) + return EC_RES_ACCESS_DENIED; + if (num_rand_bytes > args->response_max) + return EC_RES_OVERFLOW; + trng_init(); + trng_rand_bytes(r->rand, num_rand_bytes); + trng_exit(); + args->response_size = num_rand_bytes; + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_RAND_NUM, host_command_rand, + EC_VER_MASK(EC_VER_RAND_NUM)); +#endif /* SECTION_IS_RW */ +#endif /* CONFIG_CMD_RAND */ diff --git a/common/typec_control.c b/common/typec_control.c new file mode 100644 index 0000000000..94070d47df --- /dev/null +++ b/common/typec_control.c @@ -0,0 +1,76 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Type-C control logic source */ + +#include "tcpm/tcpm.h" +#include "usbc_ocp.h" +#include "usbc_ppc.h" + +void typec_set_polarity(int port, enum tcpc_cc_polarity polarity) +{ + tcpm_set_polarity(port, polarity); + + if (IS_ENABLED(CONFIG_USBC_PPC_POLARITY)) + ppc_set_polarity(port, polarity); +} + +void typec_set_sbu(int port, bool enable) +{ + if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) + ppc_set_sbu(port, enable); + +#ifdef CONFIG_USB_PD_TCPM_SBU + tcpc_set_sbu(port, enable); +#endif +} + +__overridable void typec_set_source_current_limit(int port, + enum tcpc_rp_value rp) +{ + if (IS_ENABLED(CONFIG_USBC_PPC)) + ppc_set_vbus_source_current_limit(port, rp); +} + +void typec_set_vconn(int port, bool enable) +{ + if (!IS_ENABLED(CONFIG_USBC_VCONN)) + return; + + /* + * Check our OC event counter. If we've exceeded our threshold, then + * let's latch our source path off to prevent continuous cycling. When + * the PD state machine detects a disconnection on the CC lines, we will + * reset our OC event counter. + */ + if (IS_ENABLED(CONFIG_USBC_OCP) && enable && + usbc_ocp_is_port_latched_off(port)) + return; + + /* + * Disable PPC Vconn first then TCPC in case the voltage feeds back + * to TCPC and damages. + */ + if (IS_ENABLED(CONFIG_USBC_PPC_VCONN) && !enable) + ppc_set_vconn(port, false); + + /* + * Some TCPCs/PPC combinations can trigger OVP if the TCPC doesn't + * source VCONN. This happens if the TCPC will trip OVP with 5V, and the + * PPC doesn't isolate the TCPC from VCONN when sourcing. But, some PPCs + * which do isolate the TCPC can't handle 5V on its host-side CC pins, + * so the TCPC shouldn't source VCONN in those cases. + * + * In the first case, both TCPC and PPC will potentially source Vconn, + * but that should be okay since Vconn has "make before break" + * electrical requirements when swapping anyway. + * + * See b/72961003 and b/180973460 + */ + tcpm_set_vconn(port, enable); + + if (IS_ENABLED(CONFIG_USBC_PPC_VCONN) && enable) + ppc_set_vconn(port, true); +} diff --git a/common/uart_buffering.c b/common/uart_buffering.c index 1c0db3b151..f3d150dfda 100644 --- a/common/uart_buffering.c +++ b/common/uart_buffering.c @@ -1,12 +1,10 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Common code to do UART buffering and printing */ -#include - #include "common.h" #include "console.h" #include "hooks.h" @@ -19,10 +17,12 @@ #include "uart.h" #include "util.h" +#include + /* Macros to advance in the circular buffers */ #define TX_BUF_NEXT(i) (((i) + 1) & (CONFIG_UART_TX_BUF_SIZE - 1)) #define RX_BUF_NEXT(i) (((i) + 1) & (CONFIG_UART_RX_BUF_SIZE - 1)) -#define RX_BUF_PREV(i) (((i) - 1) & (CONFIG_UART_RX_BUF_SIZE - 1)) +#define RX_BUF_PREV(i) (((i)-1) & (CONFIG_UART_RX_BUF_SIZE - 1)) /* Macros to calculate difference of pointers in the circular buffers. */ #define TX_BUF_DIFF(i, j) (((i) - (j)) & (CONFIG_UART_TX_BUF_SIZE - 1)) @@ -37,12 +37,12 @@ BUILD_ASSERT((CONFIG_UART_RX_BUF_SIZE & (CONFIG_UART_RX_BUF_SIZE - 1)) == 0); * of input has been detected by the normal tick task. There will be * CONFIG_UART_RX_DMA_RECHECKS rechecks between this tick and the next tick. */ -#define RX_DMA_RECHECK_INTERVAL (HOOK_TICK_INTERVAL / \ - (CONFIG_UART_RX_DMA_RECHECKS + 1)) +#define RX_DMA_RECHECK_INTERVAL \ + (HOOK_TICK_INTERVAL / (CONFIG_UART_RX_DMA_RECHECKS + 1)) /* Transmit and receive buffers */ -static volatile char tx_buf[CONFIG_UART_TX_BUF_SIZE] - __uncached __preserved_logs(tx_buf); +static volatile char tx_buf[CONFIG_UART_TX_BUF_SIZE] __uncached + __preserved_logs(tx_buf); static volatile int tx_buf_head __preserved_logs(tx_buf_head); static volatile int tx_buf_tail __preserved_logs(tx_buf_tail); static volatile char rx_buf[CONFIG_UART_RX_BUF_SIZE] __uncached; @@ -59,34 +59,29 @@ static int uart_buffer_calc_checksum(void) return tx_buf_head ^ tx_buf_tail; } - void uart_init_buffer(void) { if (tx_checksum != uart_buffer_calc_checksum() || - !IN_RANGE(tx_buf_head, 0, CONFIG_UART_TX_BUF_SIZE) || - !IN_RANGE(tx_buf_tail, 0, CONFIG_UART_TX_BUF_SIZE)) { + !IN_RANGE(tx_buf_head, 0, CONFIG_UART_TX_BUF_SIZE - 1) || + !IN_RANGE(tx_buf_tail, 0, CONFIG_UART_TX_BUF_SIZE - 1)) { + /* + * NOTE: + * We are here because EC cold reset or RO/RW's preserve_logs + * section are different. + */ tx_buf_head = 0; tx_buf_tail = 0; tx_checksum = 0; } } -/** - * Put a single character into the transmit buffer. - * - * Does not enable the transmit interrupt; assumes that happens elsewhere. - * - * @param context Context; ignored. - * @param c Character to write. - * @return 0 if the character was transmitted, 1 if it was dropped. - */ -static int __tx_char_raw(void *context, int c) +int uart_tx_char_raw(void *context, int c) { int tx_buf_next, tx_buf_new_tail; #if defined CONFIG_POLLING_UART - (void) tx_buf_next; - (void) tx_buf_new_tail; + (void)tx_buf_next; + (void)tx_buf_new_tail; uart_write_char(c); #else @@ -118,14 +113,6 @@ static int __tx_char_raw(void *context, int c) return 0; } -static int __tx_char(void *context, int c) -{ - /* Translate '\n' to '\r\n' */ - if (c == '\n' && __tx_char_raw(NULL, '\r')) - return 1; - return __tx_char_raw(context, c); -} - #ifdef CONFIG_UART_TX_DMA /** @@ -149,7 +136,7 @@ void uart_process_output(void) /* If a previous DMA transfer completed, free up the buffer it used */ if (tx_dma_in_progress) { tx_buf_tail = (tx_buf_tail + tx_dma_in_progress) & - (CONFIG_UART_TX_BUF_SIZE - 1); + (CONFIG_UART_TX_BUF_SIZE - 1); tx_dma_in_progress = 0; if (IS_ENABLED(CONFIG_PRESERVE_LOGS)) @@ -166,8 +153,9 @@ void uart_process_output(void) * Get the largest contiguous block of output. If the transmit buffer * wraps, only use the part before the wrap. */ - tx_dma_in_progress = (head > tx_buf_tail ? head : - CONFIG_UART_TX_BUF_SIZE) - tx_buf_tail; + tx_dma_in_progress = + (head > tx_buf_tail ? head : CONFIG_UART_TX_BUF_SIZE) - + tx_buf_tail; uart_tx_dma_start((char *)(tx_buf + tx_buf_tail), tx_dma_in_progress); } @@ -193,7 +181,7 @@ void uart_process_output(void) #endif /* !CONFIG_UART_TX_DMA */ #ifdef CONFIG_UART_RX_DMA -#ifdef CONFIG_UART_INPUT_FILTER /* TODO(crosbug.com/p/36745): */ +#ifdef CONFIG_UART_INPUT_FILTER /* TODO(crosbug.com/p/36745): */ #error "Filtering the UART input with DMA enabled is NOT SUPPORTED!" #endif @@ -257,7 +245,7 @@ void uart_process_input(void) void uart_clear_input(void) { - int scratch __attribute__ ((unused)); + int scratch __attribute__((unused)); while (uart_rx_available()) scratch = uart_read_char(); rx_buf_head = rx_buf_tail = 0; @@ -265,77 +253,6 @@ void uart_clear_input(void) #endif /* !CONFIG_UART_RX_DMA */ -int uart_putc(int c) -{ - int rv = __tx_char(NULL, c); - - uart_tx_start(); - - return rv ? EC_ERROR_OVERFLOW : EC_SUCCESS; -} - -int uart_puts(const char *outstr) -{ - /* Put all characters in the output buffer */ - while (*outstr) { - if (__tx_char(NULL, *outstr++) != 0) - break; - } - - uart_tx_start(); - - /* Successful if we consumed all output */ - return *outstr ? EC_ERROR_OVERFLOW : EC_SUCCESS; -} - -int uart_put(const char *out, int len) -{ - /* Put all characters in the output buffer */ - while (len--) { - if (__tx_char(NULL, *out++) != 0) - break; - } - - uart_tx_start(); - - /* Successful if we consumed all output */ - return len ? EC_ERROR_OVERFLOW : EC_SUCCESS; -} - -int uart_put_raw(const char *out, int len) -{ - /* Put all characters in the output buffer */ - while (len--) { - if (__tx_char_raw(NULL, *out++) != 0) - break; - } - - uart_tx_start(); - - /* Successful if we consumed all output */ - return len ? EC_ERROR_OVERFLOW : EC_SUCCESS; -} - -int uart_vprintf(const char *format, va_list args) -{ - int rv = vfnprintf(__tx_char, NULL, format, args); - - uart_tx_start(); - - return rv; -} - -int uart_printf(const char *format, ...) -{ - int rv; - va_list args; - - va_start(args, format); - rv = uart_vprintf(format, args); - va_end(args); - return rv; -} - void uart_flush_output(void) { /* If UART not initialized ignore flush request. */ @@ -344,7 +261,7 @@ void uart_flush_output(void) /* Loop until buffer is empty */ while (tx_buf_head != tx_buf_tail) { - if (in_interrupt_context()) { + if (in_interrupt_context() || !is_interrupt_enabled()) { /* * Explicitly process UART output, since the UART * interrupt may not be able to preempt the interrupt @@ -402,55 +319,6 @@ static void uart_rx_dma_init(void) DECLARE_HOOK(HOOK_INIT, uart_rx_dma_init, HOOK_PRIO_DEFAULT); #endif -/*****************************************************************************/ -/* Host commands */ - -static enum ec_status -host_command_console_snapshot(struct host_cmd_handler_args *args) -{ - return uart_console_read_buffer_init(); -} -DECLARE_HOST_COMMAND(EC_CMD_CONSOLE_SNAPSHOT, - host_command_console_snapshot, - EC_VER_MASK(0)); - -static enum ec_status -host_command_console_read(struct host_cmd_handler_args *args) -{ - if (args->version == 0) { - /* - * Prior versions of this command only support reading from - * an entire snapshot, not just the output since the last - * snapshot. - */ - return uart_console_read_buffer( - CONSOLE_READ_NEXT, - (char *)args->response, - args->response_max, - &args->response_size); -#ifdef CONFIG_CONSOLE_ENABLE_READ_V1 - } else if (args->version == 1) { - const struct ec_params_console_read_v1 *p; - - /* Check the params to figure out where to start reading. */ - p = args->params; - return uart_console_read_buffer( - p->subcmd, - (char *)args->response, - args->response_max, - &args->response_size); -#endif - } - return EC_RES_INVALID_PARAM; -} -DECLARE_HOST_COMMAND(EC_CMD_CONSOLE_READ, - host_command_console_read, - EC_VER_MASK(0) -#ifdef CONFIG_CONSOLE_ENABLE_READ_V1 - | EC_VER_MASK(1) -#endif - ); - enum ec_status uart_console_read_buffer_init(void) { /* Assume the whole circular buffer is full */ @@ -479,9 +347,7 @@ enum ec_status uart_console_read_buffer_init(void) return EC_RES_SUCCESS; } -int uart_console_read_buffer(uint8_t type, - char *dest, - uint16_t dest_size, +int uart_console_read_buffer(uint8_t type, char *dest, uint16_t dest_size, uint16_t *write_count) { int *tail; @@ -503,7 +369,6 @@ int uart_console_read_buffer(uint8_t type, /* Copy data to response */ while (*tail != tx_snapshot_head && *write_count < dest_size - 1) { - /* * Copy only non-zero bytes, so that we don't copy unused * bytes if the buffer hasn't completely rolled at boot. diff --git a/common/uart_hostcmd.c b/common/uart_hostcmd.c new file mode 100644 index 0000000000..506a49221d --- /dev/null +++ b/common/uart_hostcmd.c @@ -0,0 +1,54 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "config.h" +#include "ec_commands.h" +#include "host_command.h" +#include "uart.h" + +static enum ec_status +host_command_console_snapshot(struct host_cmd_handler_args *args) +{ + return uart_console_read_buffer_init(); +} +DECLARE_HOST_COMMAND(EC_CMD_CONSOLE_SNAPSHOT, host_command_console_snapshot, + EC_VER_MASK(0)); + +static enum ec_status +host_command_console_read(struct host_cmd_handler_args *args) +{ + if (args->version == 0) { + /* + * Prior versions of this command only support reading from + * an entire snapshot, not just the output since the last + * snapshot. + */ + return uart_console_read_buffer(CONSOLE_READ_NEXT, + (char *)args->response, + args->response_max, + &args->response_size); + } else if (IS_ENABLED(CONFIG_CONSOLE_ENABLE_READ_V1) && + args->version == 1) { + const struct ec_params_console_read_v1 *p; + + /* Check the params to figure out where to start reading. */ + p = args->params; + return uart_console_read_buffer(p->subcmd, + (char *)args->response, + args->response_max, + &args->response_size); + } + return EC_RES_INVALID_PARAM; +} + +#ifdef CONFIG_CONSOLE_ENABLE_READ_V1 +#define READ_V1_MASK EC_VER_MASK(1) +#else +#define READ_V1_MASK 0 +#endif + +DECLARE_HOST_COMMAND(EC_CMD_CONSOLE_READ, host_command_console_read, + EC_VER_MASK(0) | READ_V1_MASK); diff --git a/common/uart_printf.c b/common/uart_printf.c new file mode 100644 index 0000000000..55b8a40cde --- /dev/null +++ b/common/uart_printf.c @@ -0,0 +1,96 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "printf.h" +#include "uart.h" + +#include + +static int __tx_char(void *context, int c) +{ + /* + * Translate '\n' to '\r\n'. + */ + if (c == '\n' && uart_tx_char_raw(context, '\r')) + return 1; + return uart_tx_char_raw(context, c); +} + +int uart_putc(int c) +{ + int rv = __tx_char(NULL, c); + + uart_tx_start(); + + return rv ? EC_ERROR_OVERFLOW : EC_SUCCESS; +} + +int uart_puts(const char *outstr) +{ + /* Put all characters in the output buffer */ + for (; *outstr != '\0'; ++outstr) { + if (__tx_char(NULL, *outstr) != 0) { + break; + } + } + + uart_tx_start(); + + /* Successful if we consumed all output */ + return *outstr ? EC_ERROR_OVERFLOW : EC_SUCCESS; +} + +int uart_put(const char *out, int len) +{ + int written; + + /* Put all characters in the output buffer */ + for (written = 0; written < len; written++) { + if (__tx_char(NULL, *out++) != 0) { + break; + } + } + + uart_tx_start(); + + return written; +} + +int uart_put_raw(const char *out, int len) +{ + int written; + + /* Put all characters in the output buffer */ + for (written = 0; written < len; written++) { + if (uart_tx_char_raw(NULL, *out++) != 0) { + break; + } + } + + uart_tx_start(); + + return written; +} + +int uart_vprintf(const char *format, va_list args) +{ + int rv = vfnprintf(__tx_char, NULL, format, args); + + uart_tx_start(); + + return rv; +} + +int uart_printf(const char *format, ...) +{ + int rv; + va_list args; + + va_start(args, format); + rv = uart_vprintf(format, args); + va_end(args); + return rv; +} diff --git a/common/update_fw.c b/common/update_fw.c index bdb432acd6..85b805191c 100644 --- a/common/update_fw.c +++ b/common/update_fw.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -25,13 +25,13 @@ #include "touchpad_fw_hash.h" BUILD_ASSERT(sizeof(touchpad_fw_hashes) == - (CONFIG_TOUCHPAD_FW_CHUNKS * SHA256_DIGEST_SIZE)); + (CONFIG_TOUCHPAD_FW_CHUNKS * SHA256_DIGEST_SIZE)); BUILD_ASSERT(sizeof(touchpad_fw_hashes[0]) == SHA256_DIGEST_SIZE); BUILD_ASSERT(sizeof(touchpad_fw_full_hash) == SHA256_DIGEST_SIZE); #endif -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) /* Section to be updated (i.e. not the current section). */ struct { @@ -47,9 +47,8 @@ struct { static int is_touchpad_block(uint32_t block_offset, size_t body_size) { return (block_offset >= CONFIG_TOUCHPAD_VIRTUAL_OFF) && - (block_offset + body_size) <= - (CONFIG_TOUCHPAD_VIRTUAL_OFF + - CONFIG_TOUCHPAD_VIRTUAL_SIZE); + (block_offset + body_size) <= (CONFIG_TOUCHPAD_VIRTUAL_OFF + + CONFIG_TOUCHPAD_VIRTUAL_SIZE); } #endif @@ -71,16 +70,15 @@ static uint8_t check_update_chunk(uint32_t block_offset, size_t body_size) if (update_section.base_offset != update_section.top_offset && (block_offset >= update_section.base_offset) && ((block_offset + body_size) <= update_section.top_offset)) { - base = update_section.base_offset; - size = update_section.top_offset - - update_section.base_offset; + size = update_section.top_offset - update_section.base_offset; /* * If this is the first chunk for this section, it needs to * be erased. */ if (block_offset == base) { - if (flash_physical_erase(base, size) != EC_SUCCESS) { + if (crec_flash_physical_erase(base, size) != + EC_SUCCESS) { CPRINTF("%s:%d erase failure of 0x%x..+0x%x\n", __func__, __LINE__, base, size); return UPDATE_ERASE_FAILURE; @@ -95,14 +93,11 @@ static uint8_t check_update_chunk(uint32_t block_offset, size_t body_size) return UPDATE_SUCCESS; #endif - CPRINTF("%s:%d %x, %d section base %x top %x\n", - __func__, __LINE__, - block_offset, body_size, - update_section.base_offset, + CPRINTF("%s:%d %x, %d section base %x top %x\n", __func__, __LINE__, + block_offset, body_size, update_section.base_offset, update_section.top_offset); return UPDATE_BAD_ADDR; - } int update_pdu_valid(struct update_command *cmd_body, size_t cmd_size) @@ -119,8 +114,8 @@ static void new_chunk_written(uint32_t block_offset) { } -static int contents_allowed(uint32_t block_offset, - size_t body_size, void *update_data) +static int contents_allowed(uint32_t block_offset, size_t body_size, + void *update_data) { #if defined(CONFIG_TOUCHPAD_VIRTUAL_OFF) && defined(CONFIG_TOUCHPAD_HASH_FW) if (is_touchpad_block(block_offset, body_size)) { @@ -131,9 +126,9 @@ static int contents_allowed(uint32_t block_offset, int good = 0; if (chunk >= CONFIG_TOUCHPAD_FW_CHUNKS || - (fw_offset % CONFIG_UPDATE_PDU_SIZE) != 0) { - CPRINTF("%s: TP invalid offset %08x\n", - __func__, fw_offset); + (fw_offset % CONFIG_UPDATE_PDU_SIZE) != 0) { + CPRINTF("%s: TP invalid offset %08x\n", __func__, + fw_offset); return 0; } @@ -142,10 +137,10 @@ static int contents_allowed(uint32_t block_offset, tmp = SHA256_final(&ctx); good = !memcmp(tmp, touchpad_fw_hashes[chunk], - SHA256_DIGEST_SIZE); + SHA256_DIGEST_SIZE); - CPRINTF("%s: TP %08x %02x..%02x (%s)\n", __func__, - fw_offset, tmp[0], tmp[31], good ? "GOOD" : "BAD"); + CPRINTF("%s: TP %08x %02x..%02x (%s)\n", __func__, fw_offset, + tmp[0], tmp[31], good ? "GOOD" : "BAD"); return good; } @@ -189,11 +184,11 @@ void fw_update_start(struct first_response_pdu *rpdu) } rpdu->common.maximum_pdu_size = htobe32(CONFIG_UPDATE_PDU_SIZE); - rpdu->common.flash_protection = htobe32(flash_get_protect()); + rpdu->common.flash_protection = htobe32(crec_flash_get_protect()); rpdu->common.offset = htobe32(update_section.base_offset); if (version) memcpy(rpdu->common.version, version, - sizeof(rpdu->common.version)); + sizeof(rpdu->common.version)); #ifdef CONFIG_ROLLBACK rpdu->common.min_rollback = htobe32(rollback_get_minimum_version()); @@ -215,13 +210,12 @@ void fw_update_start(struct first_response_pdu *rpdu) #endif } -void fw_update_command_handler(void *body, - size_t cmd_size, +void fw_update_command_handler(void *body, size_t cmd_size, size_t *response_size) { struct update_command *cmd_body = body; void *update_data; - uint8_t *error_code = body; /* Cache the address for code clarity. */ + uint8_t *error_code = body; /* Cache the address for code clarity. */ size_t body_size; uint32_t block_offset; @@ -284,11 +278,11 @@ void fw_update_command_handler(void *body, #ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF if (is_touchpad_block(block_offset, body_size)) { if (touchpad_update_write( - block_offset - CONFIG_TOUCHPAD_VIRTUAL_OFF, - body_size, update_data) != EC_SUCCESS) { + block_offset - CONFIG_TOUCHPAD_VIRTUAL_OFF, + body_size, update_data) != EC_SUCCESS) { *error_code = UPDATE_WRITE_FAILURE; - CPRINTF("%s:%d update write error\n", - __func__, __LINE__); + CPRINTF("%s:%d update write error\n", __func__, + __LINE__); return; } @@ -300,8 +294,8 @@ void fw_update_command_handler(void *body, #endif CPRINTF("update: 0x%x\n", block_offset + CONFIG_PROGRAM_MEMORY_BASE); - if (flash_physical_write(block_offset, body_size, update_data) - != EC_SUCCESS) { + if (crec_flash_physical_write(block_offset, body_size, update_data) != + EC_SUCCESS) { *error_code = UPDATE_WRITE_FAILURE; CPRINTF("%s:%d update write error\n", __func__, __LINE__); return; @@ -310,12 +304,12 @@ void fw_update_command_handler(void *body, new_chunk_written(block_offset); /* Verify that data was written properly. */ - if (memcmp(update_data, (void *) - (block_offset + CONFIG_PROGRAM_MEMORY_BASE), + if (memcmp(update_data, + (void *)(block_offset + CONFIG_PROGRAM_MEMORY_BASE), body_size)) { *error_code = UPDATE_VERIFY_ERROR; - CPRINTF("%s:%d update verification error\n", - __func__, __LINE__); + CPRINTF("%s:%d update verification error\n", __func__, + __LINE__); return; } diff --git a/common/uptime.c b/common/uptime.c index 2fdd8bdb19..1ce7e2a329 100644 --- a/common/uptime.c +++ b/common/uptime.c @@ -1,14 +1,14 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include - #include "chipset.h" -#include "system.h" #include "host_command.h" +#include "system.h" #include "util.h" +#include + static enum ec_status host_command_get_uptime_info(struct host_cmd_handler_args *args) { @@ -24,19 +24,20 @@ host_command_get_uptime_info(struct host_cmd_handler_args *args) struct ec_response_uptime_info *r = args->response; timestamp_t now = get_time(); uint32_t now_ms = (uint32_t)(now.val / MSEC); + void *recent_ap_reset = r->recent_ap_reset; + uint32_t ap_resets_since_ec_boot = 0; enum ec_error_list rc; r->time_since_ec_boot_ms = now_ms; r->ec_reset_flags = system_get_reset_flags(); memset(r->recent_ap_reset, 0, sizeof(r->recent_ap_reset)); - rc = get_ap_reset_stats(r->recent_ap_reset, - ARRAY_SIZE(r->recent_ap_reset), - &r->ap_resets_since_ec_boot); + rc = get_ap_reset_stats(recent_ap_reset, ARRAY_SIZE(r->recent_ap_reset), + &ap_resets_since_ec_boot); + r->ap_resets_since_ec_boot = ap_resets_since_ec_boot; args->response_size = sizeof(*r); return rc == EC_SUCCESS ? EC_RES_SUCCESS : EC_RES_ERROR; } -DECLARE_HOST_COMMAND(EC_CMD_GET_UPTIME_INFO, - host_command_get_uptime_info, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_GET_UPTIME_INFO, host_command_get_uptime_info, + EC_VER_MASK(0)); diff --git a/common/usb_charger.c b/common/usb_charger.c index a8396b47bd..1452ada079 100644 --- a/common/usb_charger.c +++ b/common/usb_charger.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,6 +12,7 @@ * is necessary to update charge_manager with detected charger attributes. */ +#include "builtin/assert.h" #include "charge_manager.h" #include "charger.h" #include "common.h" @@ -22,12 +23,33 @@ #include "task.h" #include "usb_charge.h" #include "usb_pd.h" +#include "usb_pd_flags.h" #include "usbc_ppc.h" #include "util.h" +#ifdef CONFIG_PLATFORM_EC_USB_CHARGER_SINGLE_TASK + +/* Hold the event bits for all ports, 1 byte per port. */ +static atomic_t usb_charger_port_events; + +/* Convert event bits for port so it can be stored in a 32 bit value. */ +#define PORT_EVENT_PACK(port, event) ((event & 0xff) << (8 * port)) + +/* Extract the event bits for port from a 32 bit value. */ +#define PORT_EVENT_UNPACK(port, event_packed) \ + ((event_packed >> (8 * port)) & 0xff) + +/* Ensure port event bits are valid. */ +BUILD_ASSERT(BIT(0) == TASK_EVENT_CUSTOM_BIT(0)); +BUILD_ASSERT(BIT(1) == TASK_EVENT_CUSTOM_BIT(1)); +BUILD_ASSERT(BIT(2) == TASK_EVENT_CUSTOM_BIT(2)); +BUILD_ASSERT(BIT(3) == TASK_EVENT_CUSTOM_BIT(3)); + +#endif /* CONFIG_PLATFORM_EC_USB_CHARGER_SINGLE_TASK */ + static void update_vbus_supplier(int port, int vbus_level) { - struct charge_port_info charge = {0}; + struct charge_port_info charge = { 0 }; if (vbus_level && !usb_charger_port_is_sourcing_vbus(port)) { charge.voltage = USB_CHARGER_VOLTAGE_MV; @@ -41,6 +63,8 @@ static void update_vbus_supplier(int port, int vbus_level) #define USB_5V_EN(port) board_is_sourcing_vbus(port) #elif defined(CONFIG_USBC_PPC) #define USB_5V_EN(port) ppc_is_sourcing_vbus(port) +#elif defined(CONFIG_USB_PD_PPC) +#define USB_5V_EN(port) tcpci_tcpm_get_src_ctrl(port) #elif defined(CONFIG_USB_PD_5V_CHARGER_CTRL) #define USB_5V_EN(port) charger_is_sourcing_otg_power(port) #elif defined(CONFIG_USB_PD_5V_EN_ACTIVE_LOW) @@ -70,43 +94,52 @@ void usb_charger_vbus_change(int port, int vbus_level) /* Update VBUS supplier and signal VBUS change to USB_CHG task */ update_vbus_supplier(port, vbus_level); -#ifdef HAS_TASK_USB_CHG_P0 +#if defined(HAS_TASK_USB_CHG_P0) || \ + defined(CONFIG_PLATFORM_EC_USB_CHARGER_SINGLE_TASK) /* USB Charger task(s) */ - task_set_event(USB_CHG_PORT_TO_TASK_ID(port), USB_CHG_EVENT_VBUS, 0); -#endif + usb_charger_task_set_event(port, USB_CHG_EVENT_VBUS); -#if (defined(CONFIG_USB_PD_VBUS_DETECT_CHARGER) \ - || defined(CONFIG_USB_PD_VBUS_DETECT_PPC)) - /* USB PD task */ - task_wake(PD_PORT_TO_TASK_ID(port)); + /* If we swapped to sourcing, drop any related charge suppliers */ + if (usb_charger_port_is_sourcing_vbus(port)) + usb_charger_reset_charge(port); #endif + + if ((get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_CHARGER) || + (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_PPC)) { + /* USB PD task */ + task_wake(PD_PORT_TO_TASK_ID(port)); + } } void usb_charger_reset_charge(int port) { - charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY, - port, NULL); - charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP, - port, NULL); - charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP, - port, NULL); - charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP, - port, NULL); - charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, - port, NULL); + charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY, port, NULL); + charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP, port, NULL); + charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP, port, NULL); + charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP, port, NULL); + charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, port, NULL); #if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 - charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, - port, NULL); + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, port, NULL); #endif -#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7 - charge_manager_update_charge(CHARGE_SUPPLIER_WPC_BPP, - port, NULL); - charge_manager_update_charge(CHARGE_SUPPLIER_WPC_EPP, - port, NULL); - charge_manager_update_charge(CHARGE_SUPPLIER_WPC_GPP, - port, NULL); +} + +void usb_charger_task_set_event(int port, uint8_t event) +{ +#ifdef CONFIG_PLATFORM_EC_USB_CHARGER_SINGLE_TASK + atomic_or(&usb_charger_port_events, PORT_EVENT_PACK(port, event)); + task_set_event(TASK_ID_USB_CHG, BIT(port)); +#else + task_set_event(USB_CHG_PORT_TO_TASK_ID(port), event); #endif +} +void usb_charger_task_set_event_sync(int port, uint8_t event) +{ + struct bc12_config *bc12_port; + + bc12_port = &bc12_ports[port]; + + bc12_port->drv->usb_charger_task_event(port, event); } static void usb_charger_init(void) @@ -118,12 +151,71 @@ static void usb_charger_init(void) update_vbus_supplier(i, pd_is_vbus_present(i)); } } -DECLARE_HOOK(HOOK_INIT, usb_charger_init, HOOK_PRIO_CHARGE_MANAGER_INIT + 1); +DECLARE_HOOK(HOOK_INIT, usb_charger_init, HOOK_PRIO_POST_CHARGE_MANAGER); + +#ifdef CONFIG_PLATFORM_EC_USB_CHARGER_SINGLE_TASK + +void usb_charger_task_shared(void *u) +{ + int port; + uint32_t evt; + uint32_t port_evt; + struct bc12_config *bc12_port; + + for (port = 0; port < board_get_usb_pd_port_count(); port++) { + bc12_port = &bc12_ports[port]; + + ASSERT(bc12_port->drv->usb_charger_task_init); + ASSERT(bc12_port->drv->usb_charger_task_event); + + bc12_port->drv->usb_charger_task_init(port); + } + + while (1) { + evt = task_wait_event(-1); + + for (port = 0; port < board_get_usb_pd_port_count(); port++) { + if (!(evt & BIT(port))) { + continue; + } + + port_evt = PORT_EVENT_UNPACK( + port, atomic_get(&usb_charger_port_events)); + atomic_and(&usb_charger_port_events, + ~PORT_EVENT_PACK(port, port_evt)); + + usb_charger_task_set_event_sync(port, port_evt); + } + } +} + +#else /* CONFIG_PLATFORM_EC_USB_CHARGER_SINGLE_TASK */ void usb_charger_task(void *u) { int port = TASK_ID_TO_USB_CHG_PORT(task_get_current()); + uint32_t evt; + struct bc12_config *bc12_port; + + /* + * The actual number of ports may be less than the maximum + * configured, so only run the task if the port exists. + */ + if (port >= board_get_usb_pd_port_count()) + return; + + bc12_port = &bc12_ports[port]; + + ASSERT(bc12_port->drv->usb_charger_task_init); + ASSERT(bc12_port->drv->usb_charger_task_event); - ASSERT(bc12_ports[port].drv->usb_charger_task); - bc12_ports[port].drv->usb_charger_task(port); + bc12_port->drv->usb_charger_task_init(port); + + while (1) { + evt = task_wait_event(-1); + + usb_charger_task_set_event_sync(port, evt); + } } + +#endif /* CONFIG_PLATFORM_EC_USB_CHARGER_SINGLE_TASK */ diff --git a/common/usb_common.c b/common/usb_common.c index 47b0bc9454..259b503b16 100644 --- a/common/usb_common.c +++ b/common/usb_common.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,110 +15,83 @@ #include "common.h" #include "console.h" #include "ec_commands.h" +#include "gpio.h" #include "hooks.h" -#include "stdbool.h" #include "host_command.h" +#include "mkbp_event.h" +#include "stdbool.h" #include "system.h" #include "task.h" +#include "typec_control.h" #include "usb_api.h" #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_dpm_sm.h" +#include "usb_pd_flags.h" #include "usb_pd_tcpm.h" +#include "usb_pe_sm.h" +#include "usbc_ocp.h" #include "usbc_ppc.h" #include "util.h" +/* + * TODO(b/272518464): Work around coreboot GCC preprocessor bug. + * #line marks the *next* line, so it is off by one. + */ +#line 43 + #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) #else #define CPRINTS(format, args...) #define CPRINTF(format, args...) #endif -__overridable void board_vbus_present_change(void) -{ -} - -#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) -int hex8tou32(char *str, uint32_t *val) -{ - char *ptr = str; - uint32_t tmp = 0; - - while (*ptr) { - char c = *ptr++; +/* + * If we are trying to upgrade PD firmwares (TCPC chips, retimer, etc), we + * need to ensure the battery has enough charge for this process. Set the + * threshold to 10%, and it should be enough charge to get us + * through the EC jump to RW and PD upgrade. + */ +#define MIN_BATTERY_FOR_PD_UPGRADE_PERCENT 10 /* % */ - if (c >= '0' && c <= '9') - tmp = (tmp << 4) + (c - '0'); - else if (c >= 'A' && c <= 'F') - tmp = (tmp << 4) + (c - 'A' + 10); - else if (c >= 'a' && c <= 'f') - tmp = (tmp << 4) + (c - 'a' + 10); - else - return EC_ERROR_INVAL; - } - if (ptr != str + 8) - return EC_ERROR_INVAL; - *val = tmp; - return EC_SUCCESS; -} +#ifdef CONFIG_COMMON_RUNTIME +struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES]; +#endif /* CONFIG_COMMON_RUNTIME */ -int remote_flashing(int argc, char **argv) +bool pd_firmware_upgrade_check_power_readiness(int port) { - int port, cnt, cmd; - uint32_t data[VDO_MAX_SIZE-1]; - char *e; - static int flash_offset[CONFIG_USB_PD_PORT_MAX_COUNT]; - - if (argc < 4 || argc > (VDO_MAX_SIZE + 4 - 1)) - return EC_ERROR_PARAM_COUNT; - - port = strtoi(argv[1], &e, 10); - if (*e || port >= board_get_usb_pd_port_count()) - return EC_ERROR_PARAM2; - - cnt = 0; - if (!strcasecmp(argv[3], "erase")) { - cmd = VDO_CMD_FLASH_ERASE; - flash_offset[port] = 0; - ccprintf("ERASE ..."); - } else if (!strcasecmp(argv[3], "reboot")) { - cmd = VDO_CMD_REBOOT; - ccprintf("REBOOT ..."); - } else if (!strcasecmp(argv[3], "signature")) { - cmd = VDO_CMD_ERASE_SIG; - ccprintf("ERASE SIG ..."); - } else if (!strcasecmp(argv[3], "info")) { - cmd = VDO_CMD_READ_INFO; - ccprintf("INFO..."); - } else if (!strcasecmp(argv[3], "version")) { - cmd = VDO_CMD_VERSION; - ccprintf("VERSION..."); + if (IS_ENABLED(HAS_TASK_CHARGER)) { + struct batt_params batt = { 0 }; + /* + * Cannot rely on the EC's active charger data as the + * EC may just rebooted into RW and has not necessarily + * picked the active charger yet. Charger task may not + * initialized, so check battery directly. + * Prevent the upgrade if the battery doesn't have enough + * charge to finish the upgrade. + */ + battery_get_params(&batt); + if (batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE || + batt.state_of_charge < MIN_BATTERY_FOR_PD_UPGRADE_PERCENT) { + CPRINTS("C%d: Cannot suspend for upgrade, not " + "enough battery (%d%%)!", + port, batt.state_of_charge); + return false; + } } else { - int i; - - argc -= 3; - for (i = 0; i < argc; i++) - if (hex8tou32(argv[i+3], data + i)) - return EC_ERROR_INVAL; - cmd = VDO_CMD_FLASH_WRITE; - cnt = argc; - ccprintf("WRITE %d @%04x ...", argc * 4, - flash_offset[port]); - flash_offset[port] += argc * 4; + /* VBUS is present on the port (it is either a + * source or sink) to provide power, so don't allow + * PD firmware upgrade on the port. + */ + if (pd_is_vbus_present(port)) + return false; } - pd_send_vdm(port, USB_VID_GOOGLE, cmd, data, cnt); - - /* Wait until VDM is done */ - while (pd[port].vdm_state > 0) - task_wait_event(100*MSEC); - - ccprintf("DONE %d\n", pd[port].vdm_state); - return EC_SUCCESS; + return true; } -#endif /* defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) */ int usb_get_battery_soc(void) { @@ -131,8 +104,8 @@ int usb_get_battery_soc(void) #endif } -#if defined(CONFIG_USB_PD_PREFER_MV) && defined(PD_PREFER_LOW_VOLTAGE) + \ - defined(PD_PREFER_HIGH_VOLTAGE) > 1 +#if defined(CONFIG_USB_PD_PREFER_MV) && \ + defined(PD_PREFER_LOW_VOLTAGE) + defined(PD_PREFER_HIGH_VOLTAGE) > 1 #error "PD preferred voltage strategy should be mutually exclusive." #endif @@ -150,7 +123,8 @@ int usb_get_battery_soc(void) */ typec_current_t usb_get_typec_current_limit(enum tcpc_cc_polarity polarity, - enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2) + enum tcpc_cc_voltage_status cc1, + enum tcpc_cc_voltage_status cc2) { typec_current_t charge = 0; enum tcpc_cc_voltage_status cc; @@ -186,7 +160,7 @@ typec_current_t usb_get_typec_current_limit(enum tcpc_cc_polarity polarity, } enum tcpc_cc_polarity get_snk_polarity(enum tcpc_cc_voltage_status cc1, - enum tcpc_cc_voltage_status cc2) + enum tcpc_cc_voltage_status cc2) { /* The following assumes: * @@ -201,13 +175,13 @@ enum tcpc_cc_polarity get_snk_polarity(enum tcpc_cc_voltage_status cc1, } enum tcpc_cc_polarity get_src_polarity(enum tcpc_cc_voltage_status cc1, - enum tcpc_cc_voltage_status cc2) + enum tcpc_cc_voltage_status cc2) { return (cc1 == TYPEC_CC_VOLT_RD) ? POLARITY_CC1 : POLARITY_CC2; } -enum pd_cc_states pd_get_cc_state( - enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2) +enum pd_cc_states pd_get_cc_state(enum tcpc_cc_voltage_status cc1, + enum tcpc_cc_voltage_status cc2) { /* Port partner is a SNK */ if (cc_is_snk_dbg_acc(cc1, cc2)) @@ -230,29 +204,27 @@ enum pd_cc_states pd_get_cc_state( return PD_CC_NONE; } -/** - * This function checks the current CC status of the port partner - * and returns true if the attached partner is debug accessory. - */ -bool pd_is_debug_acc(int port) +__overridable int pd_board_check_request(uint32_t rdo, int pdo_cnt) { - enum pd_cc_states cc_state = pd_get_task_cc_state(port); - - return cc_state == PD_CC_UFP_DEBUG_ACC || - cc_state == PD_CC_DFP_DEBUG_ACC; + return EC_SUCCESS; } -void pd_set_polarity(int port, enum tcpc_cc_polarity polarity) +int pd_get_source_pdo(const uint32_t **src_pdo_p, const int port) { - tcpm_set_polarity(port, polarity); - - if (IS_ENABLED(CONFIG_USBC_PPC_POLARITY)) - ppc_set_polarity(port, polarity); -} +#if defined(CONFIG_USB_PD_TCPMV2) && defined(CONFIG_USB_PE_SM) + const uint32_t *src_pdo; + const int pdo_cnt = dpm_get_source_pdo(&src_pdo, port); +#elif defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ + defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) + const uint32_t *src_pdo; + const int pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); +#else + const uint32_t *src_pdo = pd_src_pdo; + const int pdo_cnt = pd_src_pdo_cnt; +#endif -__overridable int pd_board_check_request(uint32_t rdo, int pdo_cnt) -{ - return EC_SUCCESS; + *src_pdo_p = src_pdo; + return pdo_cnt; } int pd_check_requested_voltage(uint32_t rdo, const int port) @@ -262,14 +234,10 @@ int pd_check_requested_voltage(uint32_t rdo, const int port) int idx = RDO_POS(rdo); uint32_t pdo; uint32_t pdo_ma; -#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ - defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) const uint32_t *src_pdo; - const int pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); -#else - const uint32_t *src_pdo = pd_src_pdo; - const int pdo_cnt = pd_src_pdo_cnt; -#endif + int pdo_cnt; + + pdo_cnt = pd_get_source_pdo(&src_pdo, port); /* Check for invalid index */ if (!idx || idx > pdo_cnt) @@ -290,8 +258,8 @@ int pd_check_requested_voltage(uint32_t rdo, const int port) return EC_ERROR_INVAL; /* too much max current */ CPRINTF("Requested %d mV %d mA (for %d/%d mA)\n", - ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10, - op_ma * 10, max_ma * 10); + ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10, op_ma * 10, + max_ma * 10); /* Accept the requested voltage */ return EC_SUCCESS; @@ -302,20 +270,39 @@ __overridable uint8_t board_get_usb_pd_port_count(void) return CONFIG_USB_PD_PORT_MAX_COUNT; } +__overridable bool board_is_usb_pd_port_present(int port) +{ + /* + * Use board_get_usb_pd_port_count() instead of checking + * CONFIG_USB_PD_PORT_MAX_COUNT directly here for legacy boards + * that implement board_get_usb_pd_port_count() but do not + * implement board_is_usb_pd_port_present(). + */ + + return (port >= 0) && (port < board_get_usb_pd_port_count()); +} + +__overridable bool board_is_dts_port(int port) +{ + return true; +} + +int pd_get_retry_count(int port, enum tcpci_msg_type type) +{ + /* PD 3.0 6.7.7: nRetryCount = 2; PD 2.0 6.6.9: nRetryCount = 3 */ + return pd_get_rev(port, type) == PD_REV30 ? 2 : 3; +} + enum pd_drp_next_states drp_auto_toggle_next_state( - uint64_t *drp_sink_time, - enum pd_power_role power_role, - enum pd_dual_role_states drp_state, - enum tcpc_cc_voltage_status cc1, - enum tcpc_cc_voltage_status cc2, - bool auto_toggle_supported) + uint64_t *drp_sink_time, enum pd_power_role power_role, + enum pd_dual_role_states drp_state, enum tcpc_cc_voltage_status cc1, + enum tcpc_cc_voltage_status cc2, bool auto_toggle_supported) { const bool hardware_debounced_unattached = - ((drp_state == PD_DRP_TOGGLE_ON) && - auto_toggle_supported); + ((drp_state == PD_DRP_TOGGLE_ON) && auto_toggle_supported); /* Set to appropriate port state */ - if (cc_is_open(cc1, cc2)) { + if (cc_is_open(cc1, cc2) || cc_is_pwred_cbl_without_snk(cc1, cc2)) { /* * If nothing is attached then use drp_state to determine next * state. If DRP auto toggle is still on, then remain in the @@ -346,13 +333,13 @@ enum pd_drp_next_states drp_auto_toggle_next_state( return DRP_TC_DRP_AUTO_TOGGLE; } } else if ((cc_is_rp(cc1) || cc_is_rp(cc2)) && - drp_state != PD_DRP_FORCE_SOURCE) { + drp_state != PD_DRP_FORCE_SOURCE) { /* SNK allowed unless ForceSRC */ if (hardware_debounced_unattached) return DRP_TC_ATTACHED_WAIT_SNK; return DRP_TC_UNATTACHED_SNK; } else if (cc_is_at_least_one_rd(cc1, cc2) || - cc_is_audio_acc(cc1, cc2)) { + cc_is_audio_acc(cc1, cc2)) { /* * SRC allowed unless ForceSNK or Toggle Off * @@ -368,10 +355,10 @@ enum pd_drp_next_states drp_auto_toggle_next_state( * ready for a new connection. */ if (drp_state == PD_DRP_TOGGLE_OFF || - drp_state == PD_DRP_FORCE_SINK) { - if (get_time().val > *drp_sink_time + 200*MSEC) + drp_state == PD_DRP_FORCE_SINK) { + if (get_time().val > *drp_sink_time + 200 * MSEC) *drp_sink_time = get_time().val; - if (get_time().val < *drp_sink_time + 100*MSEC) + if (get_time().val < *drp_sink_time + 100 * MSEC) return DRP_TC_UNATTACHED_SNK; else return DRP_TC_DRP_AUTO_TOGGLE; @@ -393,13 +380,18 @@ enum pd_drp_next_states drp_auto_toggle_next_state( } } +__overridable bool usb_ufp_check_usb3_enable(int port) +{ + return false; +} + mux_state_t get_mux_mode_to_set(int port) { /* * If the SoC is down, then we disconnect the MUX to save power since * no one cares about the data lines. */ - if (IS_ENABLED(CONFIG_POWER_COMMON) && + if (IS_ENABLED(CONFIG_AP_POWER_CONTROL) && chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) return USB_PD_MUX_NONE; @@ -412,18 +404,42 @@ mux_state_t get_mux_mode_to_set(int port) if (pd_is_disconnected(port)) return USB_PD_MUX_NONE; + /* + * For type-c only connections, there may be a need to enable USB3.1 + * mode when the port is in a UFP data role, independent of any other + * conditions which are checked below. The default function returns + * false, so only boards that override this check will be affected. + */ + if (usb_ufp_check_usb3_enable(port) && + pd_get_data_role(port) == PD_ROLE_UFP) + return USB_PD_MUX_USB_ENABLED; + /* If new data role isn't DFP & we only support DFP, also disconnect. */ if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) && IS_ENABLED(CONFIG_USBC_SS_MUX_DFP_ONLY) && pd_get_data_role(port) != PD_ROLE_DFP) return USB_PD_MUX_NONE; + /* If new data role isn't UFP & we only support UFP then disconnect. */ + if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) && + IS_ENABLED(CONFIG_USBC_SS_MUX_UFP_ONLY) && + pd_get_data_role(port) != PD_ROLE_UFP) + return USB_PD_MUX_NONE; + /* - * If the power role is sink and the partner device is not capable + * If the power role is sink and the PD partner device is not capable * of USB communication then disconnect. + * + * On an entry into Unattached.SNK, the partner may be PD capable but + * hasn't yet sent source capabilities. In this case, hold off enabling + * USB3 termination until the PD capability is resolved. + * + * TODO(b/188588458): TCPMv2: Delay enabling USB3 termination when USB4 + * is supported. */ if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) && pd_get_power_role(port) == PD_ROLE_SINK && + (pd_capable(port) || pd_waiting_on_partner_src_caps(port)) && !pd_get_partner_usb_comm_capable(port)) return USB_PD_MUX_NONE; @@ -436,85 +452,66 @@ void set_usb_mux_with_current_data_role(int port) if (IS_ENABLED(CONFIG_USBC_SS_MUX)) { mux_state_t mux_mode = get_mux_mode_to_set(port); enum usb_switch usb_switch_mode = - (mux_mode == USB_PD_MUX_NONE) ? - USB_SWITCH_DISCONNECT : USB_SWITCH_CONNECT; + (mux_mode == USB_PD_MUX_NONE) ? USB_SWITCH_DISCONNECT : + USB_SWITCH_CONNECT; usb_mux_set(port, mux_mode, usb_switch_mode, - pd_get_polarity(port)); + polarity_rm_dts(pd_get_polarity(port))); } } void usb_mux_set_safe_mode(int port) { if (IS_ENABLED(CONFIG_USBC_SS_MUX)) { - usb_mux_set(port, IS_ENABLED(CONFIG_USB_MUX_VIRTUAL) ? - USB_PD_MUX_SAFE_MODE : USB_PD_MUX_NONE, - USB_SWITCH_CONNECT, pd_get_polarity(port)); + usb_mux_set(port, USB_PD_MUX_SAFE_MODE, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); } /* Isolate the SBU lines. */ - if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) - ppc_set_sbu(port, 0); + typec_set_sbu(port, false); } -static void pd_send_hard_reset(int port) +void usb_mux_set_safe_mode_exit(int port) { - task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SEND_HARD_RESET, 0); -} - -#ifdef CONFIG_USBC_PPC + if (IS_ENABLED(CONFIG_USBC_SS_MUX)) + usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); -static uint32_t port_oc_reset_req; + /* Isolate the SBU lines. */ + typec_set_sbu(port, false); +} -static void re_enable_ports(void) +void pd_send_hard_reset(int port) { - uint32_t ports = deprecated_atomic_read_clear(&port_oc_reset_req); - - while (ports) { - int port = __fls(ports); - - ports &= ~BIT(port); - - /* - * Let the board know that the overcurrent is - * over since we're going to attempt re-enabling - * the port. - */ - board_overcurrent_event(port, 0); - - pd_send_hard_reset(port); - /* - * TODO(b/117854867): PD3.0 to send an alert message - * indicating OCP after explicit contract. - */ - } + task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SEND_HARD_RESET); } -DECLARE_DEFERRED(re_enable_ports); +#ifdef CONFIG_USBC_OCP void pd_handle_overcurrent(int port) { + if ((port < 0) || (port >= board_get_usb_pd_port_count())) { + CPRINTS("%s(%d) Invalid port!", __func__, port); + return; + } + CPRINTS("C%d: overcurrent!", port); if (IS_ENABLED(CONFIG_USB_PD_LOGGING)) pd_log_event(PD_EVENT_PS_FAULT, PD_LOG_PORT_SIZE(port, 0), - PS_FAULT_OCP, NULL); + PS_FAULT_OCP, NULL); /* No action to take if disconnected, just log. */ if (pd_is_disconnected(port)) return; - /* Keep track of the overcurrent events. */ - ppc_add_oc_event(port); - - /* Let the board specific code know about the OC event. */ - board_overcurrent_event(port, 1); - - /* Wait 1s before trying to re-enable the port. */ - deprecated_atomic_or(&port_oc_reset_req, BIT(port)); - hook_call_deferred(&re_enable_ports_data, SECOND); + /* + * Keep track of the overcurrent events and allow the module to perform + * the spec-dictated recovery actions. + */ + usbc_ocp_add_event(port); } -#endif /* CONFIG_USBC_PPC */ +#endif /* CONFIG_USBC_OCP */ __maybe_unused void pd_handle_cc_overvoltage(int port) { @@ -526,8 +523,7 @@ __overridable int pd_board_checks(void) return EC_SUCCESS; } -__overridable int pd_check_data_swap(int port, - enum pd_data_role data_role) +__overridable int pd_check_data_swap(int port, enum pd_data_role data_role) { /* Allow data swap if we are a UFP, otherwise don't allow. */ return (data_role == PD_ROLE_UFP) ? 1 : 0; @@ -535,6 +531,16 @@ __overridable int pd_check_data_swap(int port, __overridable int pd_check_power_swap(int port) { +#ifdef CONFIG_CHARGE_MANAGER + /* + * If the Type-C port is our active charge port and we don't have a + * battery, don't allow power role swap (to source). + */ + if (!IS_ENABLED(CONFIG_BATTERY) && + port == charge_manager_get_active_charge_port()) + return 0; +#endif + /* * Allow power swap if we are acting as a dual role device. If we are * not acting as dual role (ex. suspended), then only allow power swap @@ -548,8 +554,7 @@ __overridable int pd_check_power_swap(int port) return 0; } -__overridable void pd_execute_data_swap(int port, - enum pd_data_role data_role) +__overridable void pd_execute_data_swap(int port, enum pd_data_role data_role) { } @@ -559,6 +564,12 @@ __overridable enum pd_dual_role_states pd_get_drp_state_in_suspend(void) return PD_DRP_TOGGLE_OFF; } +__overridable enum pd_dual_role_states pd_get_drp_state_in_s0(void) +{ + /* Enable dual role when chipset on */ + return PD_DRP_TOGGLE_ON; +} + __overridable void pd_try_execute_vconn_swap(int port, int flags) { /* @@ -580,101 +591,6 @@ __overridable void pd_transition_voltage(int idx) /* Most devices are fixed 5V output. */ } -__overridable void typec_set_source_current_limit(int p, enum tcpc_rp_value rp) -{ - if (IS_ENABLED(CONFIG_USBC_PPC)) - ppc_set_vbus_source_current_limit(p, rp); -} - -/* ---------------- Power Data Objects (PDOs) ----------------- */ -#ifndef CONFIG_USB_PD_CUSTOM_PDO -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP) - -const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); -const uint32_t pd_src_pdo_max[] = { - PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max); - -const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), - PDO_BATT(4750, PD_MAX_VOLTAGE_MV, PD_OPERATING_POWER_MW), - PDO_VAR(4750, PD_MAX_VOLTAGE_MV, PD_MAX_CURRENT_MA), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); -#endif /* CONFIG_USB_PD_CUSTOM_PDO */ - -/* ----------------- Vendor Defined Messages ------------------ */ -#if defined(CONFIG_USB_PE_SM) && !defined(CONFIG_USB_VPD) && \ - !defined(CONFIG_USB_CTVPD) -__overridable int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) -{ - int cmd = PD_VDO_CMD(payload[0]); - uint16_t dev_id = 0; - int is_rw, is_latest; - - /* make sure we have some payload */ - if (cnt == 0) - return 0; - - switch (cmd) { - case VDO_CMD_VERSION: - /* guarantee last byte of payload is null character */ - *(payload + cnt - 1) = 0; - CPRINTF("version: %s\n", (char *)(payload+1)); - break; - case VDO_CMD_READ_INFO: - case VDO_CMD_SEND_INFO: - /* copy hash */ - if (cnt == 7) { - dev_id = VDO_INFO_HW_DEV_ID(payload[6]); - is_rw = VDO_INFO_IS_RW(payload[6]); - - is_latest = pd_dev_store_rw_hash( - port, dev_id, payload + 1, - is_rw ? EC_IMAGE_RW : EC_IMAGE_RO); - - /* - * Send update host event unless our RW hash is - * already known to be the latest update RW. - */ - if (!is_rw || !is_latest) - pd_send_host_event(PD_EVENT_UPDATE_DEVICE); - - CPRINTF("DevId:%d.%d SW:%d RW:%d\n", - HW_DEV_ID_MAJ(dev_id), - HW_DEV_ID_MIN(dev_id), - VDO_INFO_SW_DBG_VER(payload[6]), - is_rw); - } else if (cnt == 6) { - /* really old devices don't have last byte */ - pd_dev_store_rw_hash(port, dev_id, payload + 1, - EC_IMAGE_UNKNOWN); - } - break; - case VDO_CMD_CURRENT: - CPRINTF("Current: %dmA\n", payload[1]); - break; - case VDO_CMD_FLIP: - if (IS_ENABLED(CONFIG_USBC_SS_MUX)) - usb_mux_flip(port); - break; -#ifdef CONFIG_USB_PD_LOGGING - case VDO_CMD_GET_LOG: - pd_log_recv_vdm(port, cnt, payload); - break; -#endif /* CONFIG_USB_PD_LOGGING */ - } - - return 0; -} -#endif /* CONFIG_USB_PE_SM && !CONFIG_USB_VPD && !CONFIG_USB_CTVPD */ - __overridable bool vboot_allow_usb_pd(void) { return false; @@ -684,15 +600,15 @@ __overridable bool vboot_allow_usb_pd(void) static void pd_usb_billboard_deferred(void) { if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE) && - !IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP) && - !IS_ENABLED(CONFIG_USB_PD_SIMPLE_DFP) && - IS_ENABLED(CONFIG_USB_BOS)) { + !IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP) && + !IS_ENABLED(CONFIG_USB_PD_SIMPLE_DFP) && + IS_ENABLED(CONFIG_USB_BOS)) { /* * TODO(tbroch) * 1. Will we have multiple type-C port UFPs * 2. Will there be other modes applicable to DFPs besides DP */ - if (!pd_alt_mode(0, TCPC_TX_SOP, USB_SID_DISPLAYPORT)) + if (!pd_alt_mode(0, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT)) usb_connect(); } } @@ -719,32 +635,45 @@ static void gpio_discharge_vbus(int port, int enable) void pd_set_vbus_discharge(int port, int enable) { - static struct mutex discharge_lock[CONFIG_USB_PD_PORT_MAX_COUNT]; + static mutex_t discharge_lock[CONFIG_USB_PD_PORT_MAX_COUNT]; +#ifdef CONFIG_ZEPHYR + static bool inited[CONFIG_USB_PD_PORT_MAX_COUNT]; +#endif if (port >= board_get_usb_pd_port_count()) return; +#ifdef CONFIG_ZEPHYR + if (!inited[port]) { + (void)k_mutex_init(&discharge_lock[port]); + inited[port] = true; + } +#endif mutex_lock(&discharge_lock[port]); enable &= !board_vbus_source_enabled(port); - if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_GPIO)) + if (get_usb_pd_discharge() == USB_PD_DISCHARGE_GPIO) { gpio_discharge_vbus(port, enable); - else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_TCPC)) + } else if (get_usb_pd_discharge() == USB_PD_DISCHARGE_TCPC) { +#ifdef CONFIG_USB_PD_DISCHARGE_TCPC tcpc_discharge_vbus(port, enable); - else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_PPC)) +#endif + } else if (get_usb_pd_discharge() == USB_PD_DISCHARGE_PPC) { +#ifdef CONFIG_USB_PD_DISCHARGE_PPC ppc_discharge_vbus(port, enable); +#endif + } mutex_unlock(&discharge_lock[port]); } #endif /* CONFIG_USB_PD_DISCHARGE */ #ifdef CONFIG_USB_PD_TCPM_TCPCI -static uint32_t pd_ports_to_resume; +static atomic_t pd_ports_to_resume; static void resume_pd_port(void) { uint32_t port; - uint32_t suspended_ports = - deprecated_atomic_read_clear(&pd_ports_to_resume); + uint32_t suspended_ports = atomic_clear(&pd_ports_to_resume); while (suspended_ports) { port = __builtin_ctz(suspended_ports); @@ -756,11 +685,15 @@ DECLARE_DEFERRED(resume_pd_port); void pd_deferred_resume(int port) { - deprecated_atomic_or(&pd_ports_to_resume, 1 << port); + atomic_or(&pd_ports_to_resume, 1 << port); hook_call_deferred(&resume_pd_port_data, 5 * SECOND); } #endif /* CONFIG_USB_PD_TCPM_TCPCI */ +__overridable int pd_snk_is_vbus_provided(int port) +{ + return EC_SUCCESS; +} /* * Check the specified Vbus level @@ -770,9 +703,10 @@ void pd_deferred_resume(int port) */ __overridable bool pd_check_vbus_level(int port, enum vbus_level level) { - if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_TCPC)) + if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_TCPC) && + (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_TCPC)) { return tcpm_check_vbus_level(port, level); - else if (level == VBUS_PRESENT) + } else if (level == VBUS_PRESENT) return pd_snk_is_vbus_provided(port); else return !pd_snk_is_vbus_provided(port); @@ -795,7 +729,8 @@ int pd_set_frs_enable(int port, int enable) if (IS_ENABLED(CONFIG_USB_PD_FRS_PPC)) rv = ppc_set_frs_enable(port, enable); - if (rv == EC_SUCCESS && IS_ENABLED(CONFIG_USB_PD_FRS_TCPC)) + if ((rv == EC_SUCCESS || rv == EC_ERROR_UNIMPLEMENTED) && + tcpm_tcpc_has_frs_control(port)) rv = tcpm_set_frs_enable(port, enable); if (rv == EC_SUCCESS) rv = board_pd_set_frs_enable(port, enable); @@ -808,7 +743,7 @@ int pd_set_frs_enable(int port, int enable) * Dump TCPC registers. */ void tcpc_dump_registers(int port, const struct tcpc_reg_dump_map *reg, - int count) + int count) { int i, val; @@ -816,21 +751,20 @@ void tcpc_dump_registers(int port, const struct tcpc_reg_dump_map *reg, switch (reg->size) { case 1: tcpc_read(port, reg->addr, &val); - ccprintf(" %-30s(0x%02x) = 0x%02x\n", - reg->name, reg->addr, (uint8_t)val); + ccprintf(" %-30s(0x%02x) = 0x%02x\n", reg->name, + reg->addr, (uint8_t)val); break; case 2: tcpc_read16(port, reg->addr, &val); - ccprintf(" %-30s(0x%02x) = 0x%04x\n", - reg->name, reg->addr, (uint16_t)val); + ccprintf(" %-30s(0x%02x) = 0x%04x\n", reg->name, + reg->addr, (uint16_t)val); break; } cflush(); } - } -static int command_tcpc_dump(int argc, char **argv) +static int command_tcpc_dump(int argc, const char **argv) { int port; @@ -851,22 +785,136 @@ DECLARE_CONSOLE_COMMAND(tcpci_dump, command_tcpc_dump, "", "dump the TCPC regs"); #endif /* defined(CONFIG_CMD_TCPC_DUMP) */ -int pd_build_alert_msg(uint32_t *msg, uint32_t *len, enum pd_power_role pr) +void pd_srccaps_dump(int port) { - if (msg == NULL || len == NULL) - return EC_ERROR_INVAL; + int i; + const uint32_t *const srccaps = pd_get_src_caps(port); + + for (i = 0; i < pd_get_src_cap_cnt(port); ++i) { + uint32_t max_ma, max_mv, min_mv; + +#ifdef CONFIG_CMD_PD_SRCCAPS_REDUCED_SIZE + pd_extract_pdo_power(srccaps[i], &max_ma, &max_mv, &min_mv); + + if ((srccaps[i] & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) { + if (IS_ENABLED(CONFIG_USB_PD_REV30)) + ccprintf("%d: %dmV-%dmV/%dmA\n", i, min_mv, + max_mv, max_ma); + } else { + ccprintf("%d: %dmV/%dmA\n", i, max_mv, max_ma); + } +#else + const uint32_t pdo = srccaps[i]; + const uint32_t pdo_mask = pdo & PDO_TYPE_MASK; + const char *pdo_type = "?"; + bool range_flag = true; + + pd_extract_pdo_power(pdo, &max_ma, &max_mv, &min_mv); + + switch (pdo_mask) { + case PDO_TYPE_FIXED: + pdo_type = "Fixed"; + range_flag = false; + break; + case PDO_TYPE_BATTERY: + pdo_type = "Battery"; + break; + case PDO_TYPE_VARIABLE: + pdo_type = "Variable"; + break; + case PDO_TYPE_AUGMENTED: + pdo_type = "Augmnt"; + if (!IS_ENABLED(CONFIG_USB_PD_REV30)) { + pdo_type = "Aug3.0"; + range_flag = false; + } + break; + } + + ccprintf("Src %d: (%s) %dmV", i, pdo_type, max_mv); + if (range_flag) + ccprintf("-%dmV", min_mv); + ccprintf("/%dm%c", max_ma, + pdo_mask == PDO_TYPE_BATTERY ? 'W' : 'A'); + + if (pdo & PDO_FIXED_DUAL_ROLE) + ccprintf(" DRP"); + if (pdo & PDO_FIXED_UNCONSTRAINED) + ccprintf(" UP"); + if (pdo & PDO_FIXED_COMM_CAP) + ccprintf(" USB"); + if (pdo & PDO_FIXED_DATA_SWAP) + ccprintf(" DRD"); + /* Note from ectool.c: FRS bits are reserved in PD 2.0 spec */ + if (pdo & PDO_FIXED_FRS_CURR_MASK) + ccprintf(" FRS"); + ccprintf("\n"); +#endif + } +} + +int pd_broadcast_alert_msg(uint32_t ado) +{ +#if defined(CONFIG_USB_PD_TCPMV2) && defined(CONFIG_USB_PE_SM) && \ + !defined(CONFIG_USB_VPD) && !defined(CONFIG_USB_CTVPD) + int ret = EC_SUCCESS; + + for (int i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (pd_send_alert_msg(i, ado) != EC_SUCCESS) + ret = EC_ERROR_BUSY; + } + + return ret; +#else + return EC_ERROR_INVALID_CONFIG; +#endif +} + +int pd_send_alert_msg(int port, uint32_t ado) +{ +#if defined(CONFIG_USB_PD_TCPMV2) && defined(CONFIG_USB_PE_SM) && \ + !defined(CONFIG_USB_VPD) && !defined(CONFIG_USB_CTVPD) + struct rmdo partner_rmdo; /* - * SOURCE: currently only supports OCP - * SINK: currently only supports OVP + * The Alert Data Object (ADO) definition changed between USB PD + * Revision 3.0 and 3.1. Clear reserved bits from the USB PD 3.0 + * ADO before sending to a USB PD 3.0 partner and block the + * message if the ADO is empty. */ - if (pr == PD_ROLE_SOURCE) - *msg = ADO_OCP_EVENT; - else - *msg = ADO_OVP_EVENT; + partner_rmdo = pd_get_partner_rmdo(port); + if (partner_rmdo.major_rev == 0) { + ado &= ~(ADO_EXTENDED_ALERT_EVENT | + ADO_EXTENDED_ALERT_EVENT_TYPE); + } + + if (!ado) + return EC_ERROR_INVAL; - /* Alert data is 4 bytes */ - *len = 4; + if (pe_set_ado(port, ado) != EC_SUCCESS) + return EC_ERROR_BUSY; + pd_dpm_request(port, DPM_REQUEST_SEND_ALERT); return EC_SUCCESS; +#else + return EC_ERROR_INVALID_CONFIG; +#endif +} + +#ifdef CONFIG_MKBP_EVENT +static int dp_alt_mode_entry_get_next_event(uint8_t *data) +{ + return EC_SUCCESS; +} +DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_DP_ALT_MODE_ENTERED, + dp_alt_mode_entry_get_next_event); +#endif /* CONFIG_MKBP_EVENT */ + +__overridable void pd_notify_dp_alt_mode_entry(int port) +{ + if (IS_ENABLED(CONFIG_MKBP_EVENT)) { + (void)port; + CPRINTS("Notifying AP of DP Alt Mode Entry..."); + mkbp_send_event(EC_MKBP_EVENT_DP_ALT_MODE_ENTERED); + } } diff --git a/common/usb_console_stream.c b/common/usb_console_stream.c index 13dd7f8264..629e7ba1f8 100644 --- a/common/usb_console_stream.c +++ b/common/usb_console_stream.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -25,13 +25,12 @@ /* Console output macro */ #define USB_CONSOLE_TIMEOUT_US (30 * MSEC) -#define QUEUE_SIZE_USB_TX CONFIG_USB_CONSOLE_TX_BUF_SIZE -#define QUEUE_SIZE_USB_RX USB_MAX_PACKET_SIZE +#define QUEUE_SIZE_USB_TX CONFIG_USB_CONSOLE_TX_BUF_SIZE +#define QUEUE_SIZE_USB_RX USB_MAX_PACKET_SIZE static void usb_console_wr(struct queue_policy const *policy, size_t count); static void uart_console_rd(struct queue_policy const *policy, size_t count); - static int last_tx_ok = 1; /* @@ -52,24 +51,19 @@ static int is_readonly = 1; * usb-stream.c. */ static struct queue_policy const usb_console_policy = { - .add = usb_console_wr, + .add = usb_console_wr, .remove = uart_console_rd, }; static struct queue const tx_q = QUEUE_NULL(QUEUE_SIZE_USB_TX, uint8_t); -static struct queue const rx_q = QUEUE(QUEUE_SIZE_USB_RX, uint8_t, - usb_console_policy); +static struct queue const rx_q = + QUEUE(QUEUE_SIZE_USB_RX, uint8_t, usb_console_policy); struct usb_stream_config const usb_console; -USB_STREAM_CONFIG(usb_console, - USB_IFACE_CONSOLE, - USB_STR_CONSOLE_NAME, - USB_EP_CONSOLE, - USB_MAX_PACKET_SIZE, - USB_MAX_PACKET_SIZE, - rx_q, - tx_q) +USB_STREAM_CONFIG(usb_console, USB_IFACE_CONSOLE, USB_STR_CONSOLE_NAME, + USB_EP_CONSOLE, USB_MAX_PACKET_SIZE, USB_MAX_PACKET_SIZE, + rx_q, tx_q) static void usb_console_wr(struct queue_policy const *policy, size_t count) { @@ -185,7 +179,7 @@ int usb_puts(const char *outstr) if (!is_enabled) return EC_SUCCESS; - ret = usb_wait_console(); + ret = usb_wait_console(); if (ret) return ret; diff --git a/common/usb_host_command.c b/common/usb_host_command.c new file mode 100644 index 0000000000..0aeff40d39 --- /dev/null +++ b/common/usb_host_command.c @@ -0,0 +1,264 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "console.h" +#include "consumer.h" +#include "ec_commands.h" +#include "host_command.h" +#include "printf.h" +#include "queue_policies.h" +#include "system.h" +#include "usb-stream.h" +#include "usb_api.h" +#include "usb_hw.h" +#include "util.h" + +#define CPUTS(outstr) cputs(CC_USB, outstr) +#define CPRINTS(format, args...) cprints(CC_HOSTCMD, "USBHC: " format, ##args) + +enum usbhc_state { + /* Initial State - Ready to receive next request */ + USBHC_STATE_READY_TO_RX = 0, + /* Receiving request */ + USBHC_STATE_RECEIVING, + /* Processing request */ + USBHC_STATE_PROCESSING, + /* Sending response */ + USBHC_STATE_SENDING, + /* Received bad data */ + USBHC_STATE_RX_BAD, +} state; + +struct consumer const hostcmd_consumer; +struct producer const hostcmd_producer; +struct usb_stream_config const usbhc_stream; + +/* RX (Host->EC) queue */ +static struct queue const usb_to_hostcmd = + QUEUE_DIRECT(64, uint8_t, usbhc_stream.producer, hostcmd_consumer); +/* TX (EC->Host) queue */ +static struct queue const hostcmd_to_usb = + QUEUE_DIRECT(64, uint8_t, hostcmd_producer, usbhc_stream.consumer); + +USB_STREAM_CONFIG_FULL(usbhc_stream, USB_IFACE_HOSTCMD, USB_CLASS_VENDOR_SPEC, + USB_SUBCLASS_GOOGLE_HOSTCMD, USB_PROTOCOL_GOOGLE_HOSTCMD, + USB_STR_HOSTCMD_NAME, USB_EP_HOSTCMD, + USB_MAX_PACKET_SIZE, USB_MAX_PACKET_SIZE, usb_to_hostcmd, + hostcmd_to_usb) + +static uint8_t in_msg[USBHC_MAX_REQUEST_SIZE]; +static uint8_t out_msg[USBHC_MAX_RESPONSE_SIZE]; +static uint32_t out_size; +static struct host_packet usbhc_packet; +static struct ec_host_request *header = (struct ec_host_request *)in_msg; + +static void usbhc_read(struct producer const *producer, size_t count) +{ + static uint32_t out_index; + size_t len; + + len = MIN(producer->queue->buffer_units, out_size - out_index); + len = MIN(count, len); + + /* If we're not sending, what's going on? */ + if (state != USBHC_STATE_SENDING) + return; + + /* Put a piece of a response in the Tx queue. */ + QUEUE_ADD_UNITS(producer->queue, out_msg + out_index, len); + out_index += len; + + if (out_index < out_size) + /* More data to send. */ + return; + + if (IS_ENABLED(DEBUG)) + CPRINTS("Tx complete (%u bytes)", out_index); + out_index = 0; + state = USBHC_STATE_READY_TO_RX; +} + +struct producer const hostcmd_producer = { + .queue = &hostcmd_to_usb, + .ops = &((struct producer_ops const){ + .read = usbhc_read, + }), +}; + +/* + * Called when a command handler finished execution and prepared a response. + * It's supposed returns a response back to the host. + */ +static void usbhc_send_response_packet(struct host_packet *pkt) +{ + /* + * If we're not processing, then the AP has already terminated the + * transaction and won't be listening to a response. + */ + if (state != USBHC_STATE_PROCESSING) + return; + + if (sizeof(out_msg) < pkt->response_size) { + CPRINTS("Reponse size (%u) exceeds Tx buffer", + pkt->response_size); + return; + } + + memcpy(out_msg, pkt->response, pkt->response_size); + out_size = pkt->response_size; + state = USBHC_STATE_SENDING; + + usbhc_read(&hostcmd_producer, hostcmd_to_usb.buffer_units); +} + +/* + * Pass a complete packet to the host command protocol subsystem. + */ +static void usbhc_process_packet(uint32_t pkt_size) +{ + usbhc_packet.send_response = usbhc_send_response_packet; + usbhc_packet.request = in_msg; + usbhc_packet.request_temp = NULL; + usbhc_packet.request_max = sizeof(in_msg); + usbhc_packet.request_size = pkt_size; + + usbhc_packet.response = out_msg; + usbhc_packet.response_max = sizeof(out_msg); + usbhc_packet.response_size = 0; + usbhc_packet.driver_result = EC_RES_SUCCESS; + + host_packet_receive(&usbhc_packet); +} + +/* + * Called when usb-stream copies incoming data to the USBHC's Rx queue. + */ +static void usbhc_written(struct consumer const *consumer, size_t count) +{ + static uint32_t block_index; + static uint32_t expected_size; + static uint64_t prev_activity_timestamp; + uint64_t delta_time; + + /* How much time since the previous USB callback? */ + delta_time = get_time().val - prev_activity_timestamp; + prev_activity_timestamp += delta_time; + + /* If a session lasts more than 5 seconds, let's start over. */ + if ((delta_time > 5 * SECOND) && state != USBHC_STATE_READY_TO_RX) { + state = USBHC_STATE_READY_TO_RX; + CPRINTS("Recovering after timeout"); + } + + switch (state) { + case USBHC_STATE_READY_TO_RX: + if (IS_ENABLED(DEBUG)) + CPRINTS("Rx start. (count=%d)", count); + block_index = 0; + /* Only version 3 is supported. Using in_msg as a courtesy. */ + QUEUE_REMOVE_UNITS(consumer->queue, in_msg, count); + if (IS_ENABLED(DEBUG)) { + char str_buf[hex_str_buf_size(count)]; + + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(in_msg, count)); + CPRINTS("%s", str_buf); + } + if (in_msg[0] != EC_HOST_REQUEST_VERSION) { + CPRINTS("Unsupported version: %u", in_msg[0]); + return; + } + block_index += count; + expected_size = host_request_expected_size(header); + if (block_index < expected_size) { + state = USBHC_STATE_RECEIVING; + } else if (sizeof(in_msg) < expected_size) { + CPRINTS("Expected data size (%d) is too large", + expected_size); + state = USBHC_STATE_RX_BAD; + } else { + if (IS_ENABLED(DEBUG)) + CPRINTS("Rx complete (%d bytes)", block_index); + state = USBHC_STATE_PROCESSING; + usbhc_process_packet(block_index); + } + return; + case USBHC_STATE_RECEIVING: + /* Continue to receive the remaining data. */ + break; + case USBHC_STATE_RX_BAD: + /* + * Once we're in RX_BAD, we'll discard the incoming data for 5 + * seconds. We don't want to be READY too soon because most + * likely more anomalous data will come, hopefully the host will + * fix the situation. + */ + queue_advance_head(consumer->queue, count); + return; + case USBHC_STATE_PROCESSING: + case USBHC_STATE_SENDING: + /* + * Take no action and return though we may have resource to + * receive a new request. Host will get a buffer full error or + * timeout. + */ + return; + } + + /* Receive the remaining packet. */ + + if (IS_ENABLED(DEBUG)) + CPRINTS("Received %d bytes", count); + + if (sizeof(in_msg) < block_index + count) { + CPRINTS("Rx buffer overflow"); + state = USBHC_STATE_RX_BAD; + return; + } + QUEUE_REMOVE_UNITS(consumer->queue, in_msg + block_index, count); + block_index += count; + + if (block_index < expected_size) + return; /* More to come. */ + + if (IS_ENABLED(DEBUG)) + CPRINTS("Rx complete (%d bytes)", block_index); + + if (expected_size < block_index) { + CPRINTS("Packet is larger than expected (%d)", expected_size); + state = USBHC_STATE_RX_BAD; + return; + } + + /* Ok, the entire packet has been received and assembled. */ + state = USBHC_STATE_PROCESSING; + usbhc_process_packet(block_index); +} + +struct consumer const hostcmd_consumer = { + .queue = &usb_to_hostcmd, + .ops = &((struct consumer_ops const){ + .written = usbhc_written, + }), +}; + +static enum ec_status +host_command_protocol_info(struct host_cmd_handler_args *args) +{ + struct ec_response_get_protocol_info *r = args->response; + + memset(r, 0, sizeof(*r)); + r->protocol_versions |= BIT(3); + r->max_request_packet_size = USBHC_MAX_REQUEST_SIZE; + r->max_response_packet_size = USBHC_MAX_RESPONSE_SIZE; + r->flags = EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED; + + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, host_command_protocol_info, + EC_VER_MASK(0)); diff --git a/common/usb_i2c.c b/common/usb_i2c.c index ace2e7139c..b1cd45c76a 100644 --- a/common/usb_i2c.c +++ b/common/usb_i2c.c @@ -1,46 +1,41 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "common.h" -#include "link_defs.h" -#include "registers.h" -#include "i2c.h" -#include "usb_descriptor.h" -#include "util.h" - #include "common.h" #include "console.h" #include "consumer.h" +#include "i2c.h" +#include "link_defs.h" #include "producer.h" #include "queue.h" #include "queue_policies.h" +#include "registers.h" #include "task.h" #include "usb-stream.h" +#include "usb_descriptor.h" #include "usb_i2c.h" +#include "util.h" +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) - - -USB_I2C_CONFIG(i2c, - USB_IFACE_I2C, - USB_STR_I2C_NAME, - USB_EP_I2C) +USB_I2C_CONFIG(i2c, USB_IFACE_I2C, USB_STR_I2C_NAME, USB_EP_I2C) -static int (*cros_cmd_handler)(void *data_in, - size_t in_size, - void *data_out, +static int (*cros_cmd_handler)(void *data_in, size_t in_size, void *data_out, size_t out_size); static int16_t usb_i2c_map_error(int error) { switch (error) { - case EC_SUCCESS: return USB_I2C_SUCCESS; - case EC_ERROR_TIMEOUT: return USB_I2C_TIMEOUT; - case EC_ERROR_BUSY: return USB_I2C_BUSY; - default: return USB_I2C_UNKNOWN_ERROR | (error & 0x7fff); + case EC_SUCCESS: + return USB_I2C_SUCCESS; + case EC_ERROR_TIMEOUT: + return USB_I2C_TIMEOUT; + case EC_ERROR_BUSY: + return USB_I2C_BUSY; + default: + return USB_I2C_UNKNOWN_ERROR | (error & 0x7fff); } } @@ -52,7 +47,7 @@ static int16_t usb_i2c_map_error(int error) static uint32_t usb_i2c_read_packet(struct usb_i2c_config const *config) { return QUEUE_REMOVE_UNITS(config->consumer.queue, config->buffer, - queue_count(config->consumer.queue)); + queue_count(config->consumer.queue)); } static void usb_i2c_write_packet(struct usb_i2c_config const *config, @@ -72,9 +67,8 @@ static uint8_t usb_i2c_executable(struct usb_i2c_config const *config) * In order to support larger write payload, we need to peek * the queue to see if we need to wait for more data. */ - if (queue_peek_units(config->consumer.queue, - peek, 0, sizeof(peek)) - != sizeof(peek)) { + if (queue_peek_units(config->consumer.queue, peek, 0, + sizeof(peek)) != sizeof(peek)) { /* Not enough data to calculate expected_size. */ return 0; } @@ -92,7 +86,6 @@ static uint8_t usb_i2c_executable(struct usb_i2c_config const *config) expected_size += (((size_t)peek[0] & 0xf0) << 4) | peek[2]; } - if (queue_count(config->consumer.queue) >= expected_size) { expected_size = 0; return 1; @@ -104,20 +97,20 @@ static uint8_t usb_i2c_executable(struct usb_i2c_config const *config) static void usb_i2c_execute(struct usb_i2c_config const *config) { /* Payload is ready to execute. */ - uint32_t count = usb_i2c_read_packet(config); - int portindex = (config->buffer[0] >> 0) & 0xf; + uint32_t count = usb_i2c_read_packet(config); + int portindex = (config->buffer[0] >> 0) & 0xf; uint16_t addr_flags = (config->buffer[0] >> 8) & 0x7f; - int write_count = ((config->buffer[0] << 4) & 0xf00) | - ((config->buffer[1] >> 0) & 0xff); - int read_count = (config->buffer[1] >> 8) & 0xff; - int offset = 0; /* Offset for extended reading header. */ + int write_count = ((config->buffer[0] << 4) & 0xf00) | + ((config->buffer[1] >> 0) & 0xff); + int read_count = (config->buffer[1] >> 8) & 0xff; + int offset = 0; /* Offset for extended reading header. */ config->buffer[0] = 0; config->buffer[1] = 0; if (read_count & 0x80) { read_count = ((config->buffer[2] & 0xff) << 7) | - (read_count & 0x7f); + (read_count & 0x7f); offset = 2; } @@ -127,7 +120,7 @@ static void usb_i2c_execute(struct usb_i2c_config const *config) if (!usb_i2c_board_is_enabled()) { config->buffer[0] = USB_I2C_DISABLED; } else if (write_count > CONFIG_USB_I2C_MAX_WRITE_COUNT || - write_count != (count - 4 - offset)) { + write_count != (count - 4 - offset)) { config->buffer[0] = USB_I2C_WRITE_COUNT_INVALID; } else if (read_count > CONFIG_USB_I2C_MAX_READ_COUNT) { config->buffer[0] = USB_I2C_READ_COUNT_INVALID; @@ -156,8 +149,7 @@ static void usb_i2c_execute(struct usb_i2c_config const *config) */ ret = i2c_xfer(i2c_ports[portindex].port, addr_flags, (uint8_t *)(config->buffer + 2) + offset, - write_count, - (uint8_t *)(config->buffer + 2), + write_count, (uint8_t *)(config->buffer + 2), read_count); config->buffer[0] = usb_i2c_map_error(ret); } @@ -183,11 +175,8 @@ struct consumer_ops const usb_i2c_consumer_ops = { .written = usb_i2c_written, }; -int usb_i2c_register_cros_cmd_handler(int (*cmd_handler) - (void *data_in, - size_t in_size, - void *data_out, - size_t out_size)) +int usb_i2c_register_cros_cmd_handler(int (*cmd_handler)( + void *data_in, size_t in_size, void *data_out, size_t out_size)) { if (cros_cmd_handler) return -1; diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c deleted file mode 100644 index 75d7744597..0000000000 --- a/common/usb_pd_alt_mode_dfp.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Alternate Mode Downstream Facing Port (DFP) USB-PD module. - */ - -#include "chipset.h" -#include "console.h" -#include "task.h" -#include "task_id.h" -#include "timer.h" -#include "usb_common.h" -#include "usb_charge.h" -#include "usb_dp_alt_mode.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "usb_tbt_alt_mode.h" -#include "usbc_ppc.h" -#include "util.h" - -#ifdef CONFIG_COMMON_RUNTIME -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#else -#define CPRINTS(format, args...) -#define CPRINTF(format, args...) -#endif - -#ifndef PORT_TO_HPD -#define PORT_TO_HPD(port) ((port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD) -#endif /* PORT_TO_HPD */ - -/* Tracker for which task is waiting on sysjump prep to finish */ -static volatile task_id_t sysjump_task_waiting = TASK_ID_INVALID; - -/* - * timestamp of the next possible toggle to ensure the 2-ms spacing - * between IRQ_HPD. Since this is used in overridable functions, this - * has to be global. - */ -uint64_t svdm_hpd_deadline[CONFIG_USB_PD_PORT_MAX_COUNT]; - -int dp_flags[CONFIG_USB_PD_PORT_MAX_COUNT]; - -uint32_t dp_status[CONFIG_USB_PD_PORT_MAX_COUNT]; - -__overridable const struct svdm_response svdm_rsp = { - .identity = NULL, - .svids = NULL, - .modes = NULL, -}; - -static int pd_get_mode_idx(int port, enum tcpm_transmit_type type, - uint16_t svid) -{ - int amode_idx; - struct partner_active_modes *active = - pd_get_partner_active_modes(port, type); - - for (amode_idx = 0; amode_idx < PD_AMODE_COUNT; amode_idx++) { - if (active->amodes[amode_idx].fx && - (active->amodes[amode_idx].fx->svid == svid)) - return amode_idx; - } - return -1; -} - -static int pd_allocate_mode(int port, enum tcpm_transmit_type type, - uint16_t svid) -{ - int i, j; - struct svdm_amode_data *modep; - int mode_idx = pd_get_mode_idx(port, type, svid); - struct pd_discovery *disc = pd_get_am_discovery(port, type); - struct partner_active_modes *active = - pd_get_partner_active_modes(port, type); - assert(active); - - if (mode_idx != -1) - return mode_idx; - - /* There's no space to enter another mode */ - if (active->amode_idx == PD_AMODE_COUNT) { - CPRINTF("ERR:NO AMODE SPACE\n"); - return -1; - } - - /* Allocate ... if SVID == 0 enter default supported policy */ - for (i = 0; i < supported_modes_cnt; i++) { - for (j = 0; j < disc->svid_cnt; j++) { - struct svid_mode_data *svidp = &disc->svids[j]; - - /* - * Looking for a match between supported_modes and - * discovered SVIDs; must also match the passed-in SVID - * if that was non-zero. Otherwise, go to the next - * discovered SVID. - * TODO(b/155890173): Support AP-directed mode entry - * where the mode is unknown to the TCPM. - */ - if ((svidp->svid != supported_modes[i].svid) || - (svid && (svidp->svid != svid))) - continue; - - modep = &active->amodes[active->amode_idx]; - modep->fx = &supported_modes[i]; - modep->data = &disc->svids[j]; - active->amode_idx++; - return active->amode_idx - 1; - } - } - return -1; -} - -static int validate_mode_request(struct svdm_amode_data *modep, - uint16_t svid, int opos) -{ - if (!modep->fx) - return 0; - - if (svid != modep->fx->svid) { - CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n", - svid, modep->fx->svid); - return 0; - } - - if (opos != modep->opos) { - CPRINTF("ERR:opos r:%d != c:%d\n", - opos, modep->opos); - return 0; - } - - return 1; -} - -void pd_prepare_sysjump(void) -{ - int i; - - /* Exit modes before sysjump so we can cleanly enter again later */ - for (i = 0; i < board_get_usb_pd_port_count(); i++) { - /* - * If the port is not capable of Alternate mode no need to - * send the event. - */ - if (!pd_alt_mode_capable(i)) - continue; - - sysjump_task_waiting = task_get_current(); - task_set_event(PD_PORT_TO_TASK_ID(i), PD_EVENT_SYSJUMP, 0); - task_wait_event_mask(TASK_EVENT_SYSJUMP_READY, -1); - sysjump_task_waiting = TASK_ID_INVALID; - } -} - -/* - * This algorithm defaults to choosing higher pin config over lower ones in - * order to prefer multi-function if desired. - * - * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG - * ------------------------------------------------------------- - * A | USB G2 | ? | no | 00_0001 - * B | USB G2 | ? | yes | 00_0010 - * C | DP | CONVERTED | no | 00_0100 - * D | PD | CONVERTED | yes | 00_1000 - * E | DP | DP | no | 01_0000 - * F | PD | DP | yes | 10_0000 - * - * if UFP has NOT asserted multi-function preferred code masks away B/D/F - * leaving only A/C/E. For single-output dongles that should leave only one - * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP - * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C - * receptacle must always choose C/D in those cases. - */ -int pd_dfp_dp_get_pin_mode(int port, uint32_t status) -{ - struct svdm_amode_data *modep = - pd_get_amode_data(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); - uint32_t mode_caps; - uint32_t pin_caps; - - if (!modep) - return 0; - - mode_caps = modep->data->mode_vdo[modep->opos - 1]; - - /* TODO(crosbug.com/p/39656) revisit with DFP that can be a sink */ - pin_caps = PD_DP_PIN_CAPS(mode_caps); - - /* if don't want multi-function then ignore those pin configs */ - if (!PD_VDO_DPSTS_MF_PREF(status)) - pin_caps &= ~MODE_DP_PIN_MF_MASK; - - /* TODO(crosbug.com/p/39656) revisit if DFP drives USB Gen 2 signals */ - pin_caps &= ~MODE_DP_PIN_BR2_MASK; - - /* if C/D present they have precedence over E/F for USB-C->USB-C */ - if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D)) - pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F); - - /* get_next_bit returns undefined for zero */ - if (!pin_caps) - return 0; - - return 1 << get_next_bit(&pin_caps); -} - -struct svdm_amode_data *pd_get_amode_data(int port, - enum tcpm_transmit_type type, uint16_t svid) -{ - int idx = pd_get_mode_idx(port, type, svid); - struct partner_active_modes *active = - pd_get_partner_active_modes(port, type); - assert(active); - - return (idx == -1) ? NULL : &active->amodes[idx]; -} - -/* - * Enter default mode ( payload[0] == 0 ) or attempt to enter mode via svid & - * opos - */ -uint32_t pd_dfp_enter_mode(int port, enum tcpm_transmit_type type, - uint16_t svid, int opos) -{ - int mode_idx = pd_allocate_mode(port, type, svid); - struct svdm_amode_data *modep; - uint32_t mode_caps; - - if (mode_idx == -1) - return 0; - modep = &pd_get_partner_active_modes(port, type)->amodes[mode_idx]; - - if (!opos) { - /* choose the lowest as default */ - modep->opos = 1; - } else if (opos <= modep->data->mode_cnt) { - modep->opos = opos; - } else { - CPRINTS("C%d: Invalid opos %d for SVID %x", port, opos, svid); - return 0; - } - - mode_caps = modep->data->mode_vdo[modep->opos - 1]; - if (modep->fx->enter(port, mode_caps) == -1) - return 0; - - /* - * Strictly speaking, this should only happen when the request - * has been ACKed. - * TODO(b/159854667): Redo setting the enter mode flag to incorporate - * it into the DP state machine. - */ - pd_set_dfp_enter_mode_flag(port, true); - - /* SVDM to send to UFP for mode entry */ - return VDO(modep->fx->svid, 1, CMD_ENTER_MODE | VDO_OPOS(modep->opos)); -} - -int pd_dfp_exit_mode(int port, enum tcpm_transmit_type type, uint16_t svid, - int opos) -{ - struct svdm_amode_data *modep; - struct partner_active_modes *active = - pd_get_partner_active_modes(port, type); - int idx; - - /* - * Empty svid signals we should reset DFP VDM state by exiting all - * entered modes then clearing state. This occurs when we've - * disconnected or for hard reset. - */ - if (!svid) { - for (idx = 0; idx < PD_AMODE_COUNT; idx++) - if (active->amodes[idx].fx) - active->amodes[idx].fx->exit(port); - - pd_dfp_discovery_init(port); - return 0; - } - - /* - * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple - * mode exit. Additionally it should honor OPOS == 7 as DFP's request - * to exit all modes. We currently don't have any UFPs that support - * multiple modes on one SVID. - */ - modep = pd_get_amode_data(port, type, svid); - if (!modep || !validate_mode_request(modep, svid, opos)) - return 0; - - /* call DFPs exit function */ - modep->fx->exit(port); - - pd_set_dfp_enter_mode_flag(port, false); - - /* exit the mode */ - modep->opos = 0; - return 1; -} - -void dfp_consume_attention(int port, uint32_t *payload) -{ - uint16_t svid = PD_VDO_VID(payload[0]); - int opos = PD_VDO_OPOS(payload[0]); - struct svdm_amode_data *modep = - pd_get_amode_data(port, TCPC_TX_SOP, svid); - - if (!modep || !validate_mode_request(modep, svid, opos)) - return; - - if (modep->fx->attention) - modep->fx->attention(port, payload); -} - -void dfp_consume_identity(int port, enum tcpm_transmit_type type, int cnt, - uint32_t *payload) -{ - int ptype; - struct pd_discovery *disc; - size_t identity_size; - - if (type == TCPC_TX_SOP_PRIME && - !IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) { - CPRINTF("ERR:Unexpected cable response\n"); - return; - } - - ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]); - disc = pd_get_am_discovery(port, type); - identity_size = MIN(sizeof(union disc_ident_ack), - (cnt - 1) * sizeof(uint32_t)); - - /* Note: only store VDOs, not the VDM header */ - memcpy(disc->identity.raw_value, payload + 1, identity_size); - disc->identity_cnt = identity_size / sizeof(uint32_t); - - switch (ptype) { - case IDH_PTYPE_AMA: - /* Leave vbus ON if the following macro is false */ - if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) && - IS_ENABLED(CONFIG_USBC_VCONN_SWAP)) { - /* Adapter is requesting vconn, try to supply it */ - if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)])) - pd_try_vconn_src(port); - - /* Only disable vbus if vconn was requested */ - if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)]) && - !PD_VDO_AMA_VBUS_REQ(payload[VDO_I(AMA)])) - pd_power_supply_reset(port); - } - break; - default: - break; - } - pd_set_identity_discovery(port, type, PD_DISC_COMPLETE); -} - -void dfp_consume_svids(int port, enum tcpm_transmit_type type, int cnt, - uint32_t *payload) -{ - int i; - uint32_t *ptr = payload + 1; - int vdo = 1; - uint16_t svid0, svid1; - struct pd_discovery *disc = pd_get_am_discovery(port, type); - - for (i = disc->svid_cnt; i < disc->svid_cnt + 12; i += 2) { - if (i >= SVID_DISCOVERY_MAX) { - CPRINTF("ERR:SVIDCNT\n"); - break; - } - /* - * Verify we're still within the valid packet (count will be one - * for the VDM header + xVDOs) - */ - if (vdo >= cnt) - break; - - svid0 = PD_VDO_SVID_SVID0(*ptr); - if (!svid0) - break; - disc->svids[i].svid = svid0; - disc->svid_cnt++; - - svid1 = PD_VDO_SVID_SVID1(*ptr); - if (!svid1) - break; - disc->svids[i + 1].svid = svid1; - disc->svid_cnt++; - ptr++; - vdo++; - } - /* TODO(tbroch) need to re-issue discover svids if > 12 */ - if (i && ((i % 12) == 0)) - CPRINTF("ERR:SVID+12\n"); - - pd_set_svids_discovery(port, type, PD_DISC_COMPLETE); -} - -void dfp_consume_modes(int port, enum tcpm_transmit_type type, int cnt, - uint32_t *payload) -{ - int svid_idx; - struct svid_mode_data *mode_discovery = NULL; - struct pd_discovery *disc = pd_get_am_discovery(port, type); - uint16_t response_svid = (uint16_t) PD_VDO_VID(payload[0]); - - for (svid_idx = 0; svid_idx < disc->svid_cnt; ++svid_idx) { - uint16_t svid = disc->svids[svid_idx].svid; - - if (svid == response_svid) { - mode_discovery = &disc->svids[svid_idx]; - break; - } - } - if (!mode_discovery) { - const struct svid_mode_data *requested_mode_data = - pd_get_next_mode(port, type); - CPRINTF("C%d: Mode response for undiscovered SVID %x, but TCPM " - "requested SVID %x\n", - port, response_svid, requested_mode_data->svid); - /* - * Although SVIDs discovery seemed like it succeeded before, the - * partner is now responding with undiscovered SVIDs. Discovery - * cannot reasonably continue under these circumstances. - */ - pd_set_modes_discovery(port, type, requested_mode_data->svid, - PD_DISC_FAIL); - return; - } - - mode_discovery->mode_cnt = cnt - 1; - if (mode_discovery->mode_cnt < 1) { - CPRINTF("ERR:NOMODE\n"); - pd_set_modes_discovery(port, type, mode_discovery->svid, - PD_DISC_FAIL); - return; - } - - memcpy(mode_discovery->mode_vdo, &payload[1], - sizeof(uint32_t) * mode_discovery->mode_cnt); - disc->svid_idx++; - pd_set_modes_discovery(port, type, mode_discovery->svid, - PD_DISC_COMPLETE); -} - -int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid) -{ - struct svdm_amode_data *modep = pd_get_amode_data(port, type, svid); - - return (modep) ? modep->opos : -1; -} - -void pd_set_identity_discovery(int port, enum tcpm_transmit_type type, - enum pd_discovery_state disc) -{ - struct pd_discovery *pd = pd_get_am_discovery(port, type); - - pd->identity_discovery = disc; -} - -enum pd_discovery_state pd_get_identity_discovery(int port, - enum tcpm_transmit_type type) -{ - struct pd_discovery *disc = pd_get_am_discovery(port, type); - - return disc->identity_discovery; -} - -const union disc_ident_ack *pd_get_identity_response(int port, - enum tcpm_transmit_type type) -{ - if (type >= DISCOVERY_TYPE_COUNT) - return NULL; - - return &pd_get_am_discovery(port, type)->identity; -} - -uint16_t pd_get_identity_vid(int port) -{ - const union disc_ident_ack *resp = pd_get_identity_response(port, - TCPC_TX_SOP); - - return resp->idh.usb_vendor_id; -} - -uint16_t pd_get_identity_pid(int port) -{ - const union disc_ident_ack *resp = pd_get_identity_response(port, - TCPC_TX_SOP); - - return resp->product.product_id; -} - -uint8_t pd_get_product_type(int port) -{ - const union disc_ident_ack *resp = pd_get_identity_response(port, - TCPC_TX_SOP); - - return resp->idh.product_type; -} - -void pd_set_svids_discovery(int port, enum tcpm_transmit_type type, - enum pd_discovery_state disc) -{ - struct pd_discovery *pd = pd_get_am_discovery(port, type); - - pd->svids_discovery = disc; -} - -enum pd_discovery_state pd_get_svids_discovery(int port, - enum tcpm_transmit_type type) -{ - struct pd_discovery *disc = pd_get_am_discovery(port, type); - - return disc->svids_discovery; -} - -int pd_get_svid_count(int port, enum tcpm_transmit_type type) -{ - struct pd_discovery *disc = pd_get_am_discovery(port, type); - - return disc->svid_cnt; -} - -uint16_t pd_get_svid(int port, uint16_t svid_idx, enum tcpm_transmit_type type) -{ - struct pd_discovery *disc = pd_get_am_discovery(port, type); - - return disc->svids[svid_idx].svid; -} - -void pd_set_modes_discovery(int port, enum tcpm_transmit_type type, - uint16_t svid, enum pd_discovery_state disc) -{ - struct pd_discovery *pd = pd_get_am_discovery(port, type); - int svid_idx; - - for (svid_idx = 0; svid_idx < pd->svid_cnt; ++svid_idx) { - struct svid_mode_data *mode_data = &pd->svids[svid_idx]; - - if (mode_data->svid != svid) - continue; - - mode_data->discovery = disc; - return; - } -} - -enum pd_discovery_state pd_get_modes_discovery(int port, - enum tcpm_transmit_type type) -{ - const struct svid_mode_data *mode_data = pd_get_next_mode(port, type); - - /* - * If there are no SVIDs for which to discover modes, mode discovery is - * trivially complete. - */ - if (!mode_data) - return PD_DISC_COMPLETE; - - return mode_data->discovery; -} - -int pd_get_mode_vdo_for_svid(int port, enum tcpm_transmit_type type, - uint16_t svid, uint32_t *vdo_out) -{ - int idx; - struct pd_discovery *disc; - - if (type >= DISCOVERY_TYPE_COUNT) - return 0; - - disc = pd_get_am_discovery(port, type); - - for (idx = 0; idx < disc->svid_cnt; ++idx) { - if (pd_get_svid(port, idx, type) == svid) { - memcpy(vdo_out, disc->svids[idx].mode_vdo, - sizeof(uint32_t) * disc->svids[idx].mode_cnt); - return disc->svids[idx].mode_cnt; - } - } - return 0; -} - -struct svid_mode_data *pd_get_next_mode(int port, - enum tcpm_transmit_type type) -{ - struct pd_discovery *disc = pd_get_am_discovery(port, type); - struct svid_mode_data *failed_mode_data = NULL; - bool svid_good_discovery = false; - int svid_idx; - - /* Walk through all of the discovery mode entries */ - for (svid_idx = 0; svid_idx < disc->svid_cnt; ++svid_idx) { - struct svid_mode_data *mode_data = &disc->svids[svid_idx]; - - /* Discovery is needed, so send this one back now */ - if (mode_data->discovery == PD_DISC_NEEDED) - return mode_data; - - /* Discovery already succeeded, save that it was seen */ - if (mode_data->discovery == PD_DISC_COMPLETE) - svid_good_discovery = true; - /* Discovery already failed, save first failure */ - else if (!failed_mode_data) - failed_mode_data = mode_data; - } - - /* If no good entries were located, then return last failed */ - if (!svid_good_discovery) - return failed_mode_data; - - /* - * Mode discovery has been attempted for every discovered SVID (if - * any exist) - */ - return NULL; -} - -uint32_t *pd_get_mode_vdo(int port, uint16_t svid_idx, - enum tcpm_transmit_type type) -{ - struct pd_discovery *disc = pd_get_am_discovery(port, type); - - return disc->svids[svid_idx].mode_vdo; -} - -bool pd_is_mode_discovered_for_svid(int port, enum tcpm_transmit_type type, - uint16_t svid) -{ - const struct pd_discovery *disc = pd_get_am_discovery(port, type); - const struct svid_mode_data *mode_data; - - for (mode_data = disc->svids; mode_data < disc->svids + disc->svid_cnt; - ++mode_data) { - if (mode_data->svid == svid && - mode_data->discovery == PD_DISC_COMPLETE) - return true; - } - - return false; -} - -void notify_sysjump_ready(void) -{ - /* - * If event was set from pd_prepare_sysjump, wake the - * task waiting on us to complete. - */ - if (sysjump_task_waiting != TASK_ID_INVALID) - task_set_event(sysjump_task_waiting, - TASK_EVENT_SYSJUMP_READY, 0); -} - -static inline bool is_rev3_vdo(int port, enum tcpm_transmit_type type) -{ - return pd_get_vdo_ver(port, type) == PD_REV30; -} - -/* - * ############################################################################ - * - * Cable communication functions - * - * ############################################################################ - */ -enum idh_ptype get_usb_pd_cable_type(int port) -{ - struct pd_discovery *disc = - pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); - - return disc->identity.idh.product_type; -} - -bool is_usb2_cable_support(int port) -{ - struct pd_discovery *disc = - pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); - - return disc->identity.idh.product_type == IDH_PTYPE_PCABLE || - disc->identity.product_t2.a2_rev30.usb_20_support == - USB2_SUPPORTED; -} - -bool is_cable_speed_gen2_capable(int port) -{ - struct pd_discovery *disc = - pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); - - switch (pd_get_vdo_ver(port, TCPC_TX_SOP_PRIME)) { - case PD_REV20: - return disc->identity.product_t1.p_rev20.ss == - USB_R20_SS_U31_GEN1_GEN2; - - case PD_REV30: - return disc->identity.product_t1.p_rev30.ss == - USB_R30_SS_U32_U40_GEN2 || - disc->identity.product_t1.p_rev30.ss == - USB_R30_SS_U40_GEN3; - default: - return false; - } -} - -bool is_active_cable_element_retimer(int port) -{ - struct pd_discovery *disc = - pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); - - /* Ref: USB PD Spec 2.0 Table 6-29 Active Cable VDO - * Revision 2 Active cables do not have Active element support. - */ - return is_rev3_vdo(port, TCPC_TX_SOP_PRIME) && - disc->identity.idh.product_type == IDH_PTYPE_ACABLE && - disc->identity.product_t2.a2_rev30.active_elem == - ACTIVE_RETIMER; -} - -/* - * ############################################################################ - * - * Thunderbolt-Compatible functions - * - * ############################################################################ - */ - -uint32_t pd_get_tbt_mode_vdo(int port, enum tcpm_transmit_type type) -{ - uint32_t tbt_mode_vdo[PDO_MODES]; - - return pd_get_mode_vdo_for_svid(port, type, USB_VID_INTEL, - tbt_mode_vdo) ? tbt_mode_vdo[0] : 0; -} - -/* TODO (b/148528713): Need to enable Thunderbolt-compatible mode on TCPMv2 */ -void set_tbt_compat_mode_ready(int port) -{ - if (IS_ENABLED(CONFIG_USBC_SS_MUX) && - IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) { - /* Connect the SBU and USB lines to the connector. */ - if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) - ppc_set_sbu(port, 1); - - /* Set usb mux to Thunderbolt-compatible mode */ - usb_mux_set(port, USB_PD_MUX_TBT_COMPAT_ENABLED, - USB_SWITCH_CONNECT, pd_get_polarity(port)); - } -} - -/* - * Ref: USB Type-C Cable and Connector Specification - * Figure F-1 TBT3 Discovery Flow - */ -bool is_tbt_cable_superspeed(int port) -{ - struct pd_discovery *disc; - - if (!IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) || - !IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) - return false; - - disc = pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); - - /* Product type is Active cable, hence don't check for speed */ - if (disc->identity.idh.product_type == IDH_PTYPE_ACABLE) - return true; - - if (disc->identity.idh.product_type != IDH_PTYPE_PCABLE) - return false; - - if (IS_ENABLED(CONFIG_USB_PD_REV30) && - is_rev3_vdo(port, TCPC_TX_SOP_PRIME)) - return disc->identity.product_t1.p_rev30.ss == - USB_R30_SS_U32_U40_GEN1 || - disc->identity.product_t1.p_rev30.ss == - USB_R30_SS_U32_U40_GEN2 || - disc->identity.product_t1.p_rev30.ss == - USB_R30_SS_U40_GEN3; - - return disc->identity.product_t1.p_rev20.ss == - USB_R20_SS_U31_GEN1 || - disc->identity.product_t1.p_rev20.ss == - USB_R20_SS_U31_GEN1_GEN2; -} - -enum tbt_compat_cable_speed get_tbt_cable_speed(int port) -{ - union tbt_mode_resp_cable cable_mode_resp = { - .raw_value = pd_get_tbt_mode_vdo(port, TCPC_TX_SOP_PRIME) }; - enum tbt_compat_cable_speed max_tbt_speed = - board_get_max_tbt_speed(port); - - /* - * Ref: USB Type-C Cable and Connector Specification, - * figure F-1 TBT3 Discovery Flow. - * If cable doesn't have Intel SVID, limit Thunderbolt cable speed to - * Passive Gen 2 cable speed. - */ - if (!cable_mode_resp.raw_value) - return max_tbt_speed < TBT_SS_U32_GEN1_GEN2 ? - max_tbt_speed : TBT_SS_U32_GEN1_GEN2; - - return max_tbt_speed < cable_mode_resp.tbt_cable_speed ? - max_tbt_speed : cable_mode_resp.tbt_cable_speed; -} - -int enter_tbt_compat_mode(int port, enum tcpm_transmit_type sop, - uint32_t *payload) -{ - union tbt_dev_mode_enter_cmd enter_dev_mode = { .raw_value = 0 }; - union tbt_mode_resp_device dev_mode_resp; - union tbt_mode_resp_cable cable_mode_resp; - enum tcpm_transmit_type enter_mode_sop = - sop == TCPC_TX_SOP_PRIME_PRIME ? - TCPC_TX_SOP_PRIME : sop; - - /* Table F-12 TBT3 Cable Enter Mode Command */ - /* - * The port doesn't query Discover SOP'' to the cable so, the port - * doesn't have opos for SOP''. Hence, send Enter Mode SOP'' with same - * opos and revision as SOP'. - */ - payload[0] = pd_dfp_enter_mode(port, enter_mode_sop, USB_VID_INTEL, 0) | - VDO_CMDT(CMDT_INIT) | - VDO_SVDM_VERS(pd_get_vdo_ver(port, enter_mode_sop)); - - /* For TBT3 Cable Enter Mode Command, number of Objects is 1 */ - if ((sop == TCPC_TX_SOP_PRIME) || - (sop == TCPC_TX_SOP_PRIME_PRIME)) - return 1; - - usb_mux_set_safe_mode(port); - - dev_mode_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPC_TX_SOP); - cable_mode_resp.raw_value = - pd_get_tbt_mode_vdo(port, TCPC_TX_SOP_PRIME); - - /* Table F-13 TBT3 Device Enter Mode Command */ - enter_dev_mode.vendor_spec_b1 = dev_mode_resp.vendor_spec_b1; - enter_dev_mode.vendor_spec_b0 = dev_mode_resp.vendor_spec_b0; - enter_dev_mode.intel_spec_b0 = dev_mode_resp.intel_spec_b0; - enter_dev_mode.cable = - get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE ? - TBT_ENTER_PASSIVE_CABLE : TBT_ENTER_ACTIVE_CABLE; - - if (get_tbt_cable_speed(port) == TBT_SS_TBT_GEN3) { - enter_dev_mode.lsrx_comm = - cable_mode_resp.lsrx_comm; - enter_dev_mode.retimer_type = - cable_mode_resp.retimer_type; - enter_dev_mode.tbt_cable = - cable_mode_resp.tbt_cable; - enter_dev_mode.tbt_rounded = - cable_mode_resp.tbt_rounded; - enter_dev_mode.tbt_cable_speed = - cable_mode_resp.tbt_cable_speed; - } else { - enter_dev_mode.tbt_cable_speed = TBT_SS_U32_GEN1_GEN2; - } - enter_dev_mode.tbt_alt_mode = TBT_ALTERNATE_MODE; - - payload[1] = enter_dev_mode.raw_value; - - /* For TBT3 Device Enter Mode Command, number of Objects are 2 */ - return 2; -} - -enum tbt_compat_rounded_support get_tbt_rounded_support(int port) -{ - union tbt_mode_resp_cable cable_mode_resp = { - .raw_value = pd_get_tbt_mode_vdo(port, TCPC_TX_SOP_PRIME) }; - - /* tbt_rounded_support is zero when uninitialized */ - return cable_mode_resp.tbt_rounded; -} - -/* Return the current cable speed received from Cable Discover Mode command */ -__overridable enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) -{ - union tbt_mode_resp_cable cable_mode_resp = { - .raw_value = pd_get_tbt_mode_vdo(port, TCPC_TX_SOP_PRIME) }; - - return cable_mode_resp.tbt_cable_speed; -} -/* - * ############################################################################ - * - * USB4 functions - * - * ############################################################################ - */ - -/* - * For Cable rev 3.0: USB4 cable speed is set according to speed supported by - * the port and the response received from the cable, whichever is least. - * - * For Cable rev 2.0: If get_tbt_cable_speed() is less than - * TBT_SS_U32_GEN1_GEN2, return USB_R30_SS_U2_ONLY speed since the board - * doesn't support superspeed else the USB4 cable speed is set according to - * the cable response. - */ -enum usb_rev30_ss get_usb4_cable_speed(int port) -{ - struct pd_discovery *disc; - enum tbt_compat_cable_speed tbt_speed = get_tbt_cable_speed(port); - enum usb_rev30_ss max_usb4_speed; - - - if (tbt_speed < TBT_SS_U32_GEN1_GEN2) - return USB_R30_SS_U2_ONLY; - - /* - * Converting Thunderbolt-Compatible board speed to equivalent USB4 - * speed. - */ - max_usb4_speed = tbt_speed == TBT_SS_TBT_GEN3 ? - USB_R30_SS_U40_GEN3 : USB_R30_SS_U32_U40_GEN2; - - if (is_rev3_vdo(port, TCPC_TX_SOP_PRIME)) { - disc = pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); - - return max_usb4_speed < disc->identity.product_t1.p_rev30.ss ? - max_usb4_speed : disc->identity.product_t1.p_rev30.ss; - } - - return max_usb4_speed; -} - -uint32_t get_enter_usb_msg_payload(int port) -{ - /* - * Ref: USB Power Delivery Specification Revision 3.0, Version 2.0 - * Table 6-47 Enter_USB Data Object - */ - union enter_usb_data_obj eudo; - struct pd_discovery *disc; - - if (!IS_ENABLED(CONFIG_USB_PD_USB4)) - return 0; - - disc = pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); - eudo.mode = USB_PD_40; - eudo.usb4_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB4_DRD); - eudo.usb3_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB32_DRD); - eudo.cable_speed = get_usb4_cable_speed(port); - - if (is_rev3_vdo(port, TCPC_TX_SOP_PRIME) && - (disc->identity.idh.product_type == IDH_PTYPE_ACABLE)) { - eudo.cable_type = - (disc->identity.product_t2.a2_rev30.active_elem == - ACTIVE_RETIMER) ? CABLE_TYPE_ACTIVE_RETIMER : - CABLE_TYPE_ACTIVE_REDRIVER; - /* TODO: Add eudo.cable_type for Revisiosn 2 active cables */ - } else { - eudo.cable_type = CABLE_TYPE_PASSIVE; - } - - switch (disc->identity.product_t1.p_rev20.vbus_cur) { - case USB_VBUS_CUR_3A: - eudo.cable_current = USB4_CABLE_CURRENT_3A; - break; - case USB_VBUS_CUR_5A: - eudo.cable_current = USB4_CABLE_CURRENT_5A; - break; - default: - eudo.cable_current = USB4_CABLE_CURRENT_INVALID; - break; - } - eudo.pcie_supported = IS_ENABLED(CONFIG_USB_PD_PCIE_TUNNELING); - eudo.dp_supported = IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP); - eudo.tbt_supported = IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE); - eudo.host_present = 1; - - return eudo.raw_value; -} - -__overridable bool board_is_tbt_usb4_port(int port) -{ - return true; -} - -__overridable void svdm_safe_dp_mode(int port) -{ - /* make DP interface safe until configure */ - dp_flags[port] = 0; - dp_status[port] = 0; - - usb_mux_set_safe_mode(port); -} - -__overridable int svdm_enter_dp_mode(int port, uint32_t mode_caps) -{ - /* - * Don't enter the mode if the SoC is off. - * - * There's no need to enter the mode while the SoC is off; we'll - * actually enter the mode on the chipset resume hook. Entering DP Alt - * Mode twice will confuse some monitors and require and unplug/replug - * to get them to work again. The DP Alt Mode on USB-C spec says that - * if we don't need to maintain HPD connectivity info in a low power - * mode, then we shall exit DP Alt Mode. (This is why we don't enter - * when the SoC is off as opposed to suspend where adding a display - * could cause a wake up.) - */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) - return -1; - - /* Only enter mode if device is DFP_D capable */ - if (mode_caps & MODE_DP_SNK) { - svdm_safe_dp_mode(port); - - if (IS_ENABLED(CONFIG_MKBP_EVENT) && - chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) - /* - * Wake the system up since we're entering DP AltMode. - */ - pd_notify_dp_alt_mode_entry(); - - return 0; - } - - return -1; -} - -__overridable int svdm_dp_status(int port, uint32_t *payload) -{ - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); - - payload[0] = VDO(USB_SID_DISPLAYPORT, 1, - CMD_DP_STATUS | VDO_OPOS(opos)); - payload[1] = VDO_DP_STATUS(0, /* HPD IRQ ... not applicable */ - 0, /* HPD level ... not applicable */ - 0, /* exit DP? ... no */ - 0, /* usb mode? ... no */ - 0, /* multi-function ... no */ - (!!(dp_flags[port] & DP_FLAGS_DP_ON)), - 0, /* power low? ... no */ - (!!DP_FLAGS_DP_ON)); - return 2; -}; - -__overridable uint8_t get_dp_pin_mode(int port) -{ - return pd_dfp_dp_get_pin_mode(port, dp_status[port]); -} - -__overridable int svdm_dp_config(int port, uint32_t *payload) -{ - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); - int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); - uint8_t pin_mode = get_dp_pin_mode(port); - mux_state_t mux_mode; - - if (!pin_mode) - return 0; - - /* - * Multi-function operation is only allowed if that pin config is - * supported. - */ - mux_mode = ((pin_mode & MODE_DP_PIN_MF_MASK) && mf_pref) ? - USB_PD_MUX_DOCK : USB_PD_MUX_DP_ENABLED; - CPRINTS("pin_mode: %x, mf: %d, mux: %d", pin_mode, mf_pref, mux_mode); - - /* Connect the SBU and USB lines to the connector. */ - if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) - ppc_set_sbu(port, 1); - usb_mux_set(port, mux_mode, USB_SWITCH_CONNECT, pd_get_polarity(port)); - - payload[0] = VDO(USB_SID_DISPLAYPORT, 1, - CMD_DP_CONFIG | VDO_OPOS(opos)); - payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ - 1, /* DPv1.3 signaling */ - 2); /* UFP connected */ - return 2; -}; - -#if defined(CONFIG_USB_PD_DP_HPD_GPIO) && \ - !defined(CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM) -void svdm_set_hpd_gpio(int port, int en) -{ - gpio_set_level(PORT_TO_HPD(port), en); -} - -int svdm_get_hpd_gpio(int port) -{ - return gpio_get_level(PORT_TO_HPD(port)); -} -#endif - -__overridable void svdm_dp_post_config(int port) -{ - dp_flags[port] |= DP_FLAGS_DP_ON; - if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) - return; - -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - svdm_set_hpd_gpio(port, 1); - - /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - - usb_mux_hpd_update(port, 1, 0); - -#ifdef USB_PD_PORT_TCPC_MST - if (port == USB_PD_PORT_TCPC_MST) - baseboard_mst_enable_control(port, 1); -#endif -} - -__overridable int svdm_dp_attention(int port, uint32_t *payload) -{ - int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); - int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - int cur_lvl = svdm_get_hpd_gpio(port); -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - - dp_status[port] = payload[1]; - - if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && - (irq || lvl)) - /* - * Wake up the AP. IRQ or level high indicates a DP sink is now - * present. - */ - if (IS_ENABLED(CONFIG_MKBP_EVENT)) - pd_notify_dp_alt_mode_entry(); - - /* Its initial DP status message prior to config */ - if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { - if (lvl) - dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; - return 1; - } - -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - if (irq & !lvl) { - /* - * IRQ can only be generated when the level is high, because - * the IRQ is signaled by a short low pulse from the high level. - */ - CPRINTF("ERR:HPD:IRQ&LOW\n"); - return 0; /* nak */ - } - - if (irq & cur_lvl) { - uint64_t now = get_time().val; - /* wait for the minimum spacing between IRQ_HPD if needed */ - if (now < svdm_hpd_deadline[port]) - usleep(svdm_hpd_deadline[port] - now); - - /* generate IRQ_HPD pulse */ - svdm_set_hpd_gpio(port, 0); - usleep(HPD_DSTREAM_DEBOUNCE_IRQ); - svdm_set_hpd_gpio(port, 1); - } else { - svdm_set_hpd_gpio(port, lvl); - } - - /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - - usb_mux_hpd_update(port, lvl, irq); - -#ifdef USB_PD_PORT_TCPC_MST - if (port == USB_PD_PORT_TCPC_MST) - baseboard_mst_enable_control(port, lvl); -#endif - - /* ack */ - return 1; -} - -__overridable void svdm_exit_dp_mode(int port) -{ - svdm_safe_dp_mode(port); -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - svdm_set_hpd_gpio(port, 0); -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - usb_mux_hpd_update(port, 0, 0); -#ifdef USB_PD_PORT_TCPC_MST - if (port == USB_PD_PORT_TCPC_MST) - baseboard_mst_enable_control(port, 0); -#endif -#ifdef CONFIG_USB_PD_TCPMV2 - dp_teardown(port); -#endif -} - -__overridable int svdm_enter_gfu_mode(int port, uint32_t mode_caps) -{ - /* Always enter GFU mode */ - return 0; -} - -__overridable void svdm_exit_gfu_mode(int port) -{ -} - -__overridable int svdm_gfu_status(int port, uint32_t *payload) -{ - /* - * This is called after enter mode is successful, send unstructured - * VDM to read info. - */ - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_READ_INFO, NULL, 0); - return 0; -} - -__overridable int svdm_gfu_config(int port, uint32_t *payload) -{ - return 0; -} - -__overridable int svdm_gfu_attention(int port, uint32_t *payload) -{ - return 0; -} - -#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE -__overridable int svdm_tbt_compat_enter_mode(int port, uint32_t mode_caps) -{ - return 0; -} - -__overridable void svdm_tbt_compat_exit_mode(int port) -{ - if (IS_ENABLED(CONFIG_USB_PD_TCPMV2)) { - usb_mux_set_safe_mode(port); - tbt_teardown(port); - } -} - -__overridable int svdm_tbt_compat_status(int port, uint32_t *payload) -{ - return 0; -} - -__overridable int svdm_tbt_compat_config(int port, uint32_t *payload) -{ - return 0; -} - -__overridable int svdm_tbt_compat_attention(int port, uint32_t *payload) -{ - return 0; -} -#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */ - -const struct svdm_amode_fx supported_modes[] = { - { - .svid = USB_SID_DISPLAYPORT, - .enter = &svdm_enter_dp_mode, - .status = &svdm_dp_status, - .config = &svdm_dp_config, - .post_config = &svdm_dp_post_config, - .attention = &svdm_dp_attention, - .exit = &svdm_exit_dp_mode, - }, - - { - .svid = USB_VID_GOOGLE, - .enter = &svdm_enter_gfu_mode, - .status = &svdm_gfu_status, - .config = &svdm_gfu_config, - .attention = &svdm_gfu_attention, - .exit = &svdm_exit_gfu_mode, - }, -#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE - { - .svid = USB_VID_INTEL, - .enter = &svdm_tbt_compat_enter_mode, - .status = &svdm_tbt_compat_status, - .config = &svdm_tbt_compat_config, - .attention = &svdm_tbt_compat_attention, - .exit = &svdm_tbt_compat_exit_mode, - }, -#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */ -}; -const int supported_modes_cnt = ARRAY_SIZE(supported_modes); diff --git a/common/usb_pd_alt_mode_ufp.c b/common/usb_pd_alt_mode_ufp.c new file mode 100644 index 0000000000..5585056b58 --- /dev/null +++ b/common/usb_pd_alt_mode_ufp.c @@ -0,0 +1,22 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Alternate Mode Upstream Facing Port (UFP) USB-PD module. + */ +#include "usb_pd.h" +#include "usb_tbt_alt_mode.h" + +static uint32_t ufp_enter_mode[CONFIG_USB_PD_PORT_MAX_COUNT]; + +/* Save port partner's enter mode message */ +void pd_ufp_set_enter_mode(int port, uint32_t *payload) +{ + ufp_enter_mode[port] = payload[1]; +} + +/* Return port partner's enter mode message */ +uint32_t pd_ufp_get_enter_mode(int port) +{ + return ufp_enter_mode[port]; +} diff --git a/common/usb_pd_console_cmd.c b/common/usb_pd_console_cmd.c index c155a59077..9d03bdf9aa 100644 --- a/common/usb_pd_console_cmd.c +++ b/common/usb_pd_console_cmd.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -7,6 +7,7 @@ #include "console.h" #include "usb_pd.h" +#include "usb_pd_tcpm.h" #include "util.h" #ifdef CONFIG_USB_PD_ALT_MODE_DFP @@ -14,32 +15,30 @@ static void dump_pe(int port) { int i, j, idh_ptype; - struct svdm_amode_data *modep; - uint32_t mode_caps; const union disc_ident_ack *resp; - enum tcpm_transmit_type type; + enum tcpci_msg_type type; /* TODO(b/152417597): Output SOP' discovery results */ const struct pd_discovery *disc = - pd_get_am_discovery(port, TCPC_TX_SOP); + pd_get_am_discovery(port, TCPCI_MSG_SOP); - static const char * const idh_ptype_names[] = { - "UNDEF", "Hub", "Periph", "PCable", "ACable", "AMA", - "RSV6", "RSV7"}; - static const char * const tx_names[] = {"SOP", "SOP'", "SOP''"}; + static const char *const idh_ptype_names[] = { "UNDEF", "Hub", + "Periph", "PCable", + "ACable", "AMA", + "RSV6", "RSV7" }; + static const char *const tx_names[] = { "SOP", "SOP'", "SOP''" }; - for (type = TCPC_TX_SOP; type < DISCOVERY_TYPE_COUNT; type++) { + for (type = TCPCI_MSG_SOP; type < DISCOVERY_TYPE_COUNT; type++) { resp = pd_get_identity_response(port, type); if (pd_get_identity_discovery(port, type) != PD_DISC_COMPLETE) { ccprintf("No %s identity discovered yet.\n", - tx_names[type]); + tx_names[type]); continue; } idh_ptype = resp->idh.product_type; ccprintf("IDENT %s:\n", tx_names[type]); ccprintf("\t[ID Header] %08x :: %s, VID:%04x\n", - resp->raw_value[0], - idh_ptype_names[idh_ptype], + resp->raw_value[0], idh_ptype_names[idh_ptype], resp->idh.usb_vendor_id); ccprintf("\t[Cert Stat] %08x\n", resp->cert.xid); @@ -51,30 +50,22 @@ static void dump_pe(int port) ccprintf("\n"); } - if (pd_get_svid_count(port, TCPC_TX_SOP) < 1) { + if (pd_get_svid_count(port, TCPCI_MSG_SOP) < 1) { ccprintf("No SVIDS discovered yet.\n"); return; } /* TODO(b/152418267): Display discovered SVIDs and modes for SOP' */ - for (i = 0; i < pd_get_svid_count(port, TCPC_TX_SOP); i++) { + for (i = 0; i < pd_get_svid_count(port, TCPCI_MSG_SOP); i++) { ccprintf("SVID[%d]: %04x MODES:", i, disc->svids[i].svid); for (j = 0; j < disc->svids[j].mode_cnt; j++) ccprintf(" [%d] %08x", j + 1, - disc->svids[i].mode_vdo[j]); + disc->svids[i].mode_vdo[j]); ccprintf("\n"); - - modep = pd_get_amode_data(port, TCPC_TX_SOP, - disc->svids[i].svid); - if (modep) { - mode_caps = modep->data->mode_vdo[modep->opos - 1]; - ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos, - modep->fx->svid, mode_caps); - } } } -static int command_pe(int argc, char **argv) +static int command_pe(int argc, const char **argv) { int port; char *e; @@ -91,29 +82,28 @@ static int command_pe(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(pe, command_pe, - " dump", - "USB PE"); +DECLARE_CONSOLE_COMMAND(pe, command_pe, " dump", "USB PE"); #endif /* CONFIG_CMD_USB_PD_PE */ #ifdef CONFIG_CMD_USB_PD_CABLE -static const char * const cable_type[] = { +static const char *const cable_type[] = { [IDH_PTYPE_PCABLE] = "Passive", [IDH_PTYPE_ACABLE] = "Active", }; -static const char * const cable_curr[] = { +static const char *const cable_curr[] = { [USB_VBUS_CUR_3A] = "3A", [USB_VBUS_CUR_5A] = "5A", }; -static int command_cable(int argc, char **argv) +static int command_cable(int argc, const char **argv) { int port; char *e; - struct pd_discovery *disc; + const struct pd_discovery *disc; enum idh_ptype ptype; int cable_rev; + union tbt_mode_resp_cable cable_mode_resp; if (argc < 2) return EC_ERROR_PARAM_COUNT; @@ -125,15 +115,18 @@ static int command_cable(int argc, char **argv) ptype = get_usb_pd_cable_type(port); ccprintf("Cable Type: "); - if (ptype != IDH_PTYPE_PCABLE && - ptype != IDH_PTYPE_ACABLE) { + if (ptype != IDH_PTYPE_PCABLE && ptype != IDH_PTYPE_ACABLE) { ccprintf("Not Emark Cable\n"); return EC_SUCCESS; } ccprintf("%s\n", cable_type[ptype]); - cable_rev = pd_get_vdo_ver(port, TCPC_TX_SOP_PRIME); - disc = pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); + cable_rev = pd_get_rev(port, TCPCI_MSG_SOP_PRIME); + disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + cable_mode_resp.raw_value = + IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) ? + pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME) : + 0; /* Cable revision */ ccprintf("Cable Rev: %d.0\n", cable_rev + 1); @@ -143,13 +136,15 @@ static int command_cable(int argc, char **argv) * connector type (Bit 19:18) and current handling capability bit 6:5 */ ccprintf("Connector Type: %d\n", - disc->identity.product_t1.p_rev20.connector); + disc->identity.product_t1.p_rev20.connector); if (disc->identity.product_t1.p_rev20.vbus_cur) { ccprintf("Cable Current: %s\n", - disc->identity.product_t1.p_rev20.vbus_cur > - ARRAY_SIZE(cable_curr) ? "Invalid" : - cable_curr[disc->identity.product_t1.p_rev20.vbus_cur]); + disc->identity.product_t1.p_rev20.vbus_cur > + ARRAY_SIZE(cable_curr) ? + "Invalid" : + cable_curr[disc->identity.product_t1.p_rev20 + .vbus_cur]); } else ccprintf("Cable Current: Invalid\n"); @@ -159,7 +154,7 @@ static int command_cable(int argc, char **argv) */ if (ptype == IDH_PTYPE_PCABLE) ccprintf("USB Superspeed Signaling support: %d\n", - disc->identity.product_t1.p_rev20.ss); + disc->identity.product_t1.p_rev20.ss); /* * For Rev 3.0 active cables and Rev 2.0 active and passive cables, @@ -167,7 +162,8 @@ static int command_cable(int argc, char **argv) */ if (ptype == IDH_PTYPE_ACABLE) ccprintf("SOP'' Controller: %s present\n", - disc->identity.product_t1.a_rev20.sop_p_p ? "" : "Not"); + disc->identity.product_t1.a_rev20.sop_p_p ? "" : + "Not"); if (cable_rev == PD_REV30) { /* @@ -175,22 +171,46 @@ static int command_cable(int argc, char **argv) * same bits 10:9. */ ccprintf("Max vbus voltage: %d\n", - 20 + 10 * disc->identity.product_t1.p_rev30.vbus_max); + 20 + 10 * disc->identity.product_t1.p_rev30.vbus_max); /* For Rev 3.0 Active cables */ if (ptype == IDH_PTYPE_ACABLE) { ccprintf("SS signaling: USB_SS_GEN%u\n", - disc->identity.product_t2.a2_rev30.usb_gen ? - 2 : 1); + disc->identity.product_t2.a2_rev30.usb_gen ? + 2 : + 1); ccprintf("Number of SS lanes supported: %u\n", - disc->identity.product_t2.a2_rev30.usb_lanes); + disc->identity.product_t2.a2_rev30.usb_lanes); } } + + if (!cable_mode_resp.raw_value) + return EC_SUCCESS; + + ccprintf("Rounded support: %s\n", + cable_mode_resp.tbt_rounded == + TBT_GEN3_GEN4_ROUNDED_NON_ROUNDED ? + "Yes" : + "No"); + + ccprintf("Optical cable: %s\n", + cable_mode_resp.tbt_cable == TBT_CABLE_OPTICAL ? "Yes" : "No"); + + ccprintf("Retimer support: %s\n", + cable_mode_resp.retimer_type == USB_RETIMER ? "Yes" : "No"); + + ccprintf("Link training: %s-directional\n", + cable_mode_resp.lsrx_comm == BIDIR_LSRX_COMM ? "Bi" : "Uni"); + + ccprintf("Thunderbolt cable type: %s\n", + cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE ? + "Active" : + "Passive"); + return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(pdcable, command_cable, - "", +DECLARE_CONSOLE_COMMAND(pdcable, command_cable, "", "Cable Characteristics"); #endif /* CONFIG_CMD_USB_PD_CABLE */ diff --git a/common/usb_pd_discovery.c b/common/usb_pd_discovery.c new file mode 100644 index 0000000000..589be657b5 --- /dev/null +++ b/common/usb_pd_discovery.c @@ -0,0 +1,452 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Alternate Mode Discovery storage, access, and helpers + */ + +#include "builtin/assert.h" +#include "chipset.h" +#include "console.h" +#include "gpio.h" +#include "task.h" +#include "task_id.h" +#include "timer.h" +#include "typec_control.h" +#include "usb_charge.h" +#include "usb_common.h" +#include "usb_dp_alt_mode.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "usb_tbt_alt_mode.h" +#include "usbc_ppc.h" +#include "util.h" + +#ifdef CONFIG_COMMON_RUNTIME +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#else +#define CPRINTS(format, args...) +#define CPRINTF(format, args...) +#endif + +/* + * Check if the SVID has been recorded previously. Some peripherals provide + * duplicated SVID. + */ +static bool is_svid_duplicated(const struct pd_discovery *disc, uint16_t svid) +{ + int i; + + for (i = 0; i < disc->svid_cnt; ++i) + if (disc->svids[i].svid == svid) { + CPRINTF("ERR:SVIDDUP\n"); + return true; + } + + return false; +} + +void dfp_consume_identity(int port, enum tcpci_msg_type type, int cnt, + uint32_t *payload) +{ + int ptype; + struct pd_discovery *disc; + size_t identity_size; + + if (type == TCPCI_MSG_SOP_PRIME && + !IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) { + CPRINTF("ERR:Unexpected cable response\n"); + return; + } + + ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]); + disc = pd_get_am_discovery_and_notify_access(port, type); + identity_size = + MIN(sizeof(union disc_ident_ack), (cnt - 1) * sizeof(uint32_t)); + + /* Note: only store VDOs, not the VDM header */ + memcpy(disc->identity.raw_value, payload + 1, identity_size); + disc->identity_cnt = identity_size / sizeof(uint32_t); + + switch (ptype) { + case IDH_PTYPE_AMA: + /* Leave vbus ON if the following macro is false */ + if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) && + IS_ENABLED(CONFIG_USBC_VCONN_SWAP)) { + /* Adapter is requesting vconn, try to supply it */ + if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)])) + pd_try_vconn_src(port); + + /* Only disable vbus if vconn was requested */ + if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)]) && + !PD_VDO_AMA_VBUS_REQ(payload[VDO_I(AMA)])) + pd_power_supply_reset(port); + } + break; + default: + break; + } + pd_set_identity_discovery(port, type, PD_DISC_COMPLETE); +} + +void dfp_consume_svids(int port, enum tcpci_msg_type type, int cnt, + uint32_t *payload) +{ + int i; + uint32_t *ptr = payload + 1; + int vdo = 1; + uint16_t svid0, svid1; + struct pd_discovery *disc = + pd_get_am_discovery_and_notify_access(port, type); + + for (i = disc->svid_cnt; i < disc->svid_cnt + 12; i += 2) { + if (i >= SVID_DISCOVERY_MAX) { + CPRINTF("ERR:SVIDCNT\n"); + break; + } + /* + * Verify we're still within the valid packet (count will be one + * for the VDM header + xVDOs) + */ + if (vdo >= cnt) + break; + + svid0 = PD_VDO_SVID_SVID0(*ptr); + if (!svid0) + break; + + if (!is_svid_duplicated(disc, svid0)) + disc->svids[disc->svid_cnt++].svid = svid0; + + svid1 = PD_VDO_SVID_SVID1(*ptr); + if (!svid1) + break; + + if (!is_svid_duplicated(disc, svid1)) + disc->svids[disc->svid_cnt++].svid = svid1; + + ptr++; + vdo++; + } + /* TODO(tbroch) need to re-issue discover svids if > 12 */ + if (i && ((i % 12) == 0)) + CPRINTF("ERR:SVID+12\n"); + + pd_set_svids_discovery(port, type, PD_DISC_COMPLETE); +} + +void dfp_consume_modes(int port, enum tcpci_msg_type type, int cnt, + uint32_t *payload) +{ + int svid_idx; + struct svid_mode_data *mode_discovery = NULL; + struct pd_discovery *disc = + pd_get_am_discovery_and_notify_access(port, type); + uint16_t response_svid = (uint16_t)PD_VDO_VID(payload[0]); + const struct svid_mode_data *requested_mode_data = + pd_get_next_mode(port, type); + + for (svid_idx = 0; svid_idx < disc->svid_cnt; ++svid_idx) { + uint16_t svid = disc->svids[svid_idx].svid; + + if (svid == response_svid) { + mode_discovery = &disc->svids[svid_idx]; + break; + } + } + if (!mode_discovery || (requested_mode_data->svid != response_svid)) { + CPRINTF("C%d: Unexpected mode repsonse for SVID %x, but TCPM " + "requested SVID %x\n", + port, response_svid, requested_mode_data->svid); + /* + * Although SVIDs discovery seemed like it succeeded before, the + * partner is now responding with undiscovered SVIDs. Discovery + * cannot reasonably continue under these circumstances. + */ + pd_set_modes_discovery(port, type, requested_mode_data->svid, + PD_DISC_FAIL); + return; + } + + mode_discovery->mode_cnt = cnt - 1; + if (mode_discovery->mode_cnt < 1) { + CPRINTF("ERR:NOMODE\n"); + pd_set_modes_discovery(port, type, mode_discovery->svid, + PD_DISC_FAIL); + return; + } + + memcpy(mode_discovery->mode_vdo, &payload[1], + sizeof(uint32_t) * mode_discovery->mode_cnt); + disc->svid_idx++; + pd_set_modes_discovery(port, type, mode_discovery->svid, + PD_DISC_COMPLETE); +} + +void pd_disable_discovery(int port) +{ + /* Mark identity and SVIDs for the port partner and cable as failed. + * With no discovered SVIDs, there are no modes to mark as failed. + */ + pd_set_identity_discovery(port, TCPCI_MSG_SOP, PD_DISC_FAIL); + pd_set_svids_discovery(port, TCPCI_MSG_SOP, PD_DISC_FAIL); + pd_set_identity_discovery(port, TCPCI_MSG_SOP_PRIME, PD_DISC_FAIL); + pd_set_svids_discovery(port, TCPCI_MSG_SOP_PRIME, PD_DISC_FAIL); +} + +void pd_set_identity_discovery(int port, enum tcpci_msg_type type, + enum pd_discovery_state disc) +{ + struct pd_discovery *pd = + pd_get_am_discovery_and_notify_access(port, type); + + pd->identity_discovery = disc; +} + +enum pd_discovery_state pd_get_identity_discovery(int port, + enum tcpci_msg_type type) +{ + const struct pd_discovery *disc = pd_get_am_discovery(port, type); + + return disc->identity_discovery; +} + +const union disc_ident_ack *pd_get_identity_response(int port, + enum tcpci_msg_type type) +{ + if (type >= DISCOVERY_TYPE_COUNT) + return NULL; + + return &pd_get_am_discovery(port, type)->identity; +} + +uint16_t pd_get_identity_vid(int port) +{ + const union disc_ident_ack *resp = + pd_get_identity_response(port, TCPCI_MSG_SOP); + + return resp->idh.usb_vendor_id; +} + +uint16_t pd_get_identity_pid(int port) +{ + const union disc_ident_ack *resp = + pd_get_identity_response(port, TCPCI_MSG_SOP); + + return resp->product.product_id; +} + +uint8_t pd_get_product_type(int port) +{ + const union disc_ident_ack *resp = + pd_get_identity_response(port, TCPCI_MSG_SOP); + + return resp->idh.product_type; +} + +void pd_set_svids_discovery(int port, enum tcpci_msg_type type, + enum pd_discovery_state disc) +{ + struct pd_discovery *pd = + pd_get_am_discovery_and_notify_access(port, type); + + pd->svids_discovery = disc; +} + +enum pd_discovery_state pd_get_svids_discovery(int port, + enum tcpci_msg_type type) +{ + const struct pd_discovery *disc = pd_get_am_discovery(port, type); + + return disc->svids_discovery; +} + +int pd_get_svid_count(int port, enum tcpci_msg_type type) +{ + const struct pd_discovery *disc = pd_get_am_discovery(port, type); + + return disc->svid_cnt; +} + +uint16_t pd_get_svid(int port, uint16_t svid_idx, enum tcpci_msg_type type) +{ + const struct pd_discovery *disc = pd_get_am_discovery(port, type); + + return disc->svids[svid_idx].svid; +} + +void pd_set_modes_discovery(int port, enum tcpci_msg_type type, uint16_t svid, + enum pd_discovery_state disc) +{ + struct pd_discovery *pd = + pd_get_am_discovery_and_notify_access(port, type); + int svid_idx; + + for (svid_idx = 0; svid_idx < pd->svid_cnt; ++svid_idx) { + struct svid_mode_data *mode_data = &pd->svids[svid_idx]; + + if (mode_data->svid != svid) + continue; + + mode_data->discovery = disc; + return; + } +} + +enum pd_discovery_state pd_get_modes_discovery(int port, + enum tcpci_msg_type type) +{ + const struct svid_mode_data *mode_data = pd_get_next_mode(port, type); + + /* + * If there are no SVIDs for which to discover modes, mode discovery is + * trivially complete. + */ + if (!mode_data) + return PD_DISC_COMPLETE; + + return mode_data->discovery; +} + +int pd_get_mode_vdo_for_svid(int port, enum tcpci_msg_type type, uint16_t svid, + uint32_t *vdo_out) +{ + int idx; + const struct pd_discovery *disc; + + if (type >= DISCOVERY_TYPE_COUNT) + return 0; + + disc = pd_get_am_discovery(port, type); + + for (idx = 0; idx < disc->svid_cnt; ++idx) { + if (pd_get_svid(port, idx, type) == svid) { + memcpy(vdo_out, disc->svids[idx].mode_vdo, + sizeof(uint32_t) * disc->svids[idx].mode_cnt); + return disc->svids[idx].mode_cnt; + } + } + return 0; +} + +const struct svid_mode_data *pd_get_next_mode(int port, + enum tcpci_msg_type type) +{ + const struct pd_discovery *disc = pd_get_am_discovery(port, type); + const struct svid_mode_data *failed_mode_data = NULL; + bool svid_good_discovery = false; + int svid_idx; + + /* Walk through all of the discovery mode entries */ + for (svid_idx = 0; svid_idx < disc->svid_cnt; ++svid_idx) { + const struct svid_mode_data *mode_data = &disc->svids[svid_idx]; + + /* Discovery is needed, so send this one back now */ + if (mode_data->discovery == PD_DISC_NEEDED) + return mode_data; + + /* Discovery already succeeded, save that it was seen */ + if (mode_data->discovery == PD_DISC_COMPLETE) + svid_good_discovery = true; + /* Discovery already failed, save first failure */ + else if (!failed_mode_data) + failed_mode_data = mode_data; + } + + /* If no good entries were located, then return last failed */ + if (!svid_good_discovery) + return failed_mode_data; + + /* + * Mode discovery has been attempted for every discovered SVID (if + * any exist) + */ + return NULL; +} + +bool pd_is_mode_discovered_for_svid(int port, enum tcpci_msg_type type, + uint16_t svid) +{ + const struct pd_discovery *disc = pd_get_am_discovery(port, type); + const struct svid_mode_data *mode_data; + + for (mode_data = disc->svids; mode_data < disc->svids + disc->svid_cnt; + ++mode_data) { + if (mode_data->svid == svid && + mode_data->discovery == PD_DISC_COMPLETE) + return true; + } + + return false; +} + +static inline bool is_pd_rev3(int port, enum tcpci_msg_type type) +{ + return pd_get_rev(port, type) == PD_REV30; +} + +/* + * ############################################################################ + * + * (Charge Through) Vconn Powered Device functions + * + * ############################################################################ + */ +bool is_vpd_ct_supported(int port) +{ + const struct pd_discovery *disc = + pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + union vpd_vdo vpd = disc->identity.product_t1.vpd; + + return vpd.ct_support; +} + +/* + * ############################################################################ + * + * Cable communication functions + * + * ############################################################################ + */ +enum idh_ptype get_usb_pd_cable_type(int port) +{ + const struct pd_discovery *disc = + pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + + return disc->identity.idh.product_type; +} + +bool is_cable_speed_gen2_capable(int port) +{ + const struct pd_discovery *disc = + pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + + switch (pd_get_rev(port, TCPCI_MSG_SOP_PRIME)) { + case PD_REV20: + return disc->identity.product_t1.p_rev20.ss == + USB_R20_SS_U31_GEN1_GEN2; + + case PD_REV30: + return disc->identity.product_t1.p_rev30.ss == + USB_R30_SS_U32_U40_GEN2 || + disc->identity.product_t1.p_rev30.ss == + USB_R30_SS_U40_GEN3; + default: + return false; + } +} + +bool is_active_cable_element_retimer(int port) +{ + const struct pd_discovery *disc = + pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + + /* Ref: USB PD Spec 2.0 Table 6-29 Active Cable VDO + * Revision 2 Active cables do not have Active element support. + */ + return is_pd_rev3(port, TCPCI_MSG_SOP_PRIME) && + disc->identity.idh.product_type == IDH_PTYPE_ACABLE && + disc->identity.product_t2.a2_rev30.active_elem == ACTIVE_RETIMER; +} diff --git a/common/usb_pd_dual_role.c b/common/usb_pd_dual_role.c index aad8d56768..a15b764cd2 100644 --- a/common/usb_pd_dual_role.c +++ b/common/usb_pd_dual_role.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -7,11 +7,17 @@ #include "charge_manager.h" #include "charge_state.h" +#include "dps.h" #include "system.h" #include "usb_common.h" #include "usb_pd.h" #include "util.h" +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* The macro is used to prevent a DBZ exception while decoding PDOs. */ +#define PROCESS_ZERO_DIVISOR(x) ((x) == 0 ? 1 : (x)) + #if defined(PD_MAX_VOLTAGE_MV) && defined(PD_OPERATING_POWER_MW) /* * As a sink, this is the max voltage (in millivolts) we can request @@ -19,6 +25,7 @@ */ static unsigned int max_request_mv = PD_MAX_VOLTAGE_MV; +/* TODO(b:169532537): deprecate CONFIG_USB_PD_PREFER_MV */ STATIC_IF_NOT(CONFIG_USB_PD_PREFER_MV) struct pd_pref_config_t __maybe_unused pd_pref_config; @@ -32,13 +39,35 @@ unsigned int pd_get_max_voltage(void) return max_request_mv; } +/** + * Return true if port is capable of communication over USB data lines. + * + * @param port USB-C port number + */ +static bool pd_get_usb_comm_capable(int port) +{ + uint32_t fixed_pdo; + + /* the fixed PDO is always the first entry */ + if (pd_get_power_role(port) == PD_ROLE_SINK) { + fixed_pdo = pd_snk_pdo[0]; + } else { + const uint32_t *pdo; + + pd_get_source_pdo(&pdo, port); + fixed_pdo = pdo[0]; + } + + return !!(fixed_pdo & PDO_FIXED_COMM_CAP); +} + /* * Zinger implements a board specific usb policy that does not define * PD_MAX_VOLTAGE_MV and PD_OPERATING_POWER_MW. And in turn, does not * use the following functions. */ -int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t * const src_caps, - int max_mv, uint32_t *selected_pdo) +int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t *const src_caps, + int max_mv, uint32_t *selected_pdo) { int i, uw, mv; int ret = 0; @@ -59,14 +88,23 @@ int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t * const src_caps, /* Get max power that is under our max voltage input */ for (i = 0; i < src_cap_cnt; i++) { + if (IS_ENABLED(CONFIG_USB_PD_ONLY_FIXED_PDOS) && + (src_caps[i] & PDO_TYPE_MASK) != PDO_TYPE_FIXED) + continue; /* its an unsupported Augmented PDO (PD3.0) */ if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) continue; - mv = ((src_caps[i] >> 10) & 0x3FF) * 50; + mv = PDO_FIXED_GET_VOLT(src_caps[i]); /* Skip invalid voltage */ if (!mv) continue; + /* + * It's illegal to have EPR PDO in 1...7. + * TODO: This is supposed to be a hard reset (8.3.3.3.8) + */ + if (i < 7 && mv > PD_MAX_SPR_VOLTAGE) + continue; /* Skip any voltage not supported by this board */ if (!pd_is_valid_input_voltage(mv)) continue; @@ -74,7 +112,7 @@ int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t * const src_caps, if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { uw = 250000 * (src_caps[i] & 0x3FF); } else { - int ma = (src_caps[i] & 0x3FF) * 10; + int ma = PDO_FIXED_GET_CURR(src_caps[i]); ma = MIN(ma, PD_MAX_CURRENT_MA); uw = ma * mv; @@ -125,10 +163,10 @@ int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t * const src_caps, mv < cur_mv) prefer_cur = 1; } - /* - * pick the largest power if we don't see one staisfy - * desired power - */ + /* + * pick the largest power if we don't see one + * staisfy desired power + */ } else if (cur_uw == 0 || uw > cur_uw) { prefer_cur = 1; } @@ -152,30 +190,48 @@ int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t * const src_caps, return ret; } -void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv) +void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *max_mv, + uint32_t *min_mv) { - int max_ma, uw; - - *mv = ((pdo >> 10) & 0x3FF) * 50; + int max_ma, mw; + + if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_FIXED) { + *max_mv = PDO_FIXED_VOLTAGE(pdo); + *min_mv = *max_mv; + } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) { + *max_mv = PDO_AUG_MAX_VOLTAGE(pdo); + *min_mv = PDO_AUG_MIN_VOLTAGE(pdo); + } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_VARIABLE) { + *max_mv = PDO_VAR_MAX_VOLTAGE(pdo); + *min_mv = PDO_VAR_MIN_VOLTAGE(pdo); + } else { + *max_mv = PDO_BATT_MAX_VOLTAGE(pdo); + *min_mv = PDO_BATT_MIN_VOLTAGE(pdo); + } - if (*mv == 0) { + if (*max_mv == 0) { *ma = 0; + *min_mv = 0; return; } - if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { - uw = 250000 * (pdo & 0x3FF); - max_ma = 1000 * MIN(1000 * uw, PD_MAX_POWER_MW) / *mv; + if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_FIXED) { + max_ma = PDO_FIXED_CURRENT(pdo); + } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) { + max_ma = PDO_AUG_MAX_CURRENT(pdo); + } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_VARIABLE) { + max_ma = PDO_VAR_MAX_CURRENT(pdo); } else { - max_ma = 10 * (pdo & 0x3FF); - max_ma = MIN(max_ma, PD_MAX_POWER_MW * 1000 / *mv); + mw = PDO_BATT_MAX_POWER(pdo); + max_ma = 1000 * mw / PROCESS_ZERO_DIVISOR(*min_mv); } - + max_ma = MIN(max_ma, + PD_MAX_POWER_MW * 1000 / PROCESS_ZERO_DIVISOR(*min_mv)); *ma = MIN(max_ma, PD_MAX_CURRENT_MA); } void pd_build_request(int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma, - uint32_t *mv, int port) + uint32_t *mv, int port) { uint32_t pdo; int pdo_index, flags = 0; @@ -186,10 +242,11 @@ void pd_build_request(int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma, int vpd_vbus_dcr; int vpd_gnd_dcr; uint32_t src_cap_cnt = pd_get_src_cap_cnt(port); - const uint32_t * const src_caps = pd_get_src_caps(port); + const uint32_t *const src_caps = pd_get_src_caps(port); int charging_allowed; int max_request_allowed; uint32_t max_request_mv = pd_get_max_voltage(); + uint32_t unused; /* * If this port is the current charge port, or if there isn't an active @@ -213,6 +270,9 @@ void pd_build_request(int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma, else max_request_allowed = 1; + if (IS_ENABLED(CONFIG_USB_PD_DPS) && dps_is_enabled()) + max_request_mv = MIN(max_request_mv, dps_get_dynamic_voltage()); + /* * If currently charging on a different port, or we are not allowed to * request the max voltage, then select vSafe5V @@ -220,14 +280,14 @@ void pd_build_request(int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma, if (charging_allowed && max_request_allowed) { /* find pdo index for max voltage we can request */ pdo_index = pd_find_pdo_index(src_cap_cnt, src_caps, - max_request_mv, &pdo); + max_request_mv, &pdo); } else { /* src cap 0 should be vSafe5V */ pdo_index = 0; pdo = src_caps[0]; } - pd_extract_pdo_power(pdo, ma, mv); + pd_extract_pdo_power(pdo, ma, mv, &unused); /* * Adjust VBUS current if CTVPD device was detected. @@ -263,29 +323,33 @@ void pd_build_request(int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma, if (uw < (1000 * PD_OPERATING_POWER_MW)) flags |= RDO_CAP_MISMATCH; + /* b:271612382S has more details. */ + if (IS_ENABLED(CONFIG_USB_PD_EPR)) + flags |= RDO_EPR_MODE_CAPABLE; + #ifdef CONFIG_USB_PD_GIVE_BACK - /* Tell source we are give back capable. */ - flags |= RDO_GIVE_BACK; + /* Tell source we are give back capable. */ + flags |= RDO_GIVE_BACK; - /* - * BATTERY PDO: Inform the source that the sink will reduce - * power to this minimum level on receipt of a GotoMin Request. - */ - max_or_min_mw = PD_MIN_POWER_MW; + /* + * BATTERY PDO: Inform the source that the sink will reduce + * power to this minimum level on receipt of a GotoMin Request. + */ + max_or_min_mw = PD_MIN_POWER_MW; - /* - * FIXED or VARIABLE PDO: Inform the source that the sink will - * reduce current to this minimum level on receipt of a GotoMin - * Request. - */ - max_or_min_ma = PD_MIN_CURRENT_MA; + /* + * FIXED or VARIABLE PDO: Inform the source that the sink will + * reduce current to this minimum level on receipt of a GotoMin + * Request. + */ + max_or_min_ma = PD_MIN_CURRENT_MA; #else - /* - * Can't give back, so set maximum current and power to - * operating level. - */ - max_or_min_ma = *ma; - max_or_min_mw = uw / 1000; + /* + * Can't give back, so set maximum current and power to + * operating level. + */ + max_or_min_ma = *ma; + max_or_min_mw = uw / 1000; #endif if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { @@ -301,12 +365,12 @@ void pd_build_request(int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma, * 6.4.2.4 USB Communications Capable * 6.4.2.5 No USB Suspend * - * If the port partner is capable of USB communication set the - * USB Communications Capable flag. + * If the port is capable of USB communication, set the USB + * Communications Capable flag. * If the port partner is sink device do not suspend USB as the * power can be used for charging. */ - if (pd_get_partner_usb_comm_capable(port)) { + if (pd_get_usb_comm_capable(port)) { *rdo |= RDO_COMM_CAP; if (pd_get_power_role(port) == PD_ROLE_SINK) *rdo |= RDO_NO_SUSPEND; @@ -318,31 +382,48 @@ void pd_process_source_cap(int port, int cnt, uint32_t *src_caps) pd_set_src_caps(port, cnt, src_caps); if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { - uint32_t ma, mv, pdo; + uint32_t ma, mv, pdo, unused; + uint32_t max_mv = pd_get_max_voltage(); + + if (IS_ENABLED(CONFIG_USB_PD_DPS) && dps_is_enabled()) + max_mv = MIN(max_mv, dps_get_dynamic_voltage()); /* Get max power info that we could request */ pd_find_pdo_index(pd_get_src_cap_cnt(port), - pd_get_src_caps(port), - PD_MAX_VOLTAGE_MV, &pdo); - pd_extract_pdo_power(pdo, &ma, &mv); + pd_get_src_caps(port), max_mv, &pdo); + pd_extract_pdo_power(pdo, &ma, &mv, &unused); - /* Set max. limit, but apply 500mA ceiling */ - charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, PD_MIN_MA); + /* Set max. limit, but 2.5 W ceiling will be applied later. */ pd_set_input_current_limit(port, ma, mv); } } #endif /* defined(PD_MAX_VOLTAGE_MV) && defined(PD_OPERATING_POWER_MW) */ -int pd_charge_from_device(uint16_t vid, uint16_t pid) +bool pd_is_battery_capable(void) { - /* TODO: rewrite into table if we get more of these */ + bool capable; + + /* Battery is present and at some minimum percentage. */ + capable = (usb_get_battery_soc() >= CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC); + +#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT /* - * Allow the Apple charge-through accessory since it doesn't set - * unconstrained bit, but we still need to charge from it when - * we are a sink. + * Not capable if the battery is in the disconnect state. The discharge + * FET may not be enabled and so attempting being a SRC may cut off + * our only power source at the time. */ - return (vid == USB_VID_APPLE && - (pid == USB_PID1_APPLE || pid == USB_PID2_APPLE)); + capable &= (battery_get_disconnect_state() == BATTERY_NOT_DISCONNECTED); +#elif defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ + defined(CONFIG_BATTERY_PRESENT_GPIO) + /* + * When battery is cutoff in ship mode it may not be reliable to + * check if battery is present with its state of charge. + * Also check if battery is initialized and ready to provide power. + */ + capable &= (battery_is_present() == BP_YES); +#endif /* CONFIG_BATTERY_PRESENT_[CUSTOM|GPIO] */ + + return capable; } #ifdef CONFIG_USB_PD_TRY_SRC @@ -356,37 +437,18 @@ bool pd_is_try_source_capable(void) try_src |= (pd_get_dual_role(i) == PD_DRP_TOGGLE_ON); /* - * Enable try source when dual-role toggling AND battery is present - * and at some minimum percentage. - */ - new_try_src = (try_src && - usb_get_battery_soc() >= CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC); - -#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT - /* - * Don't attempt Try.Src if the battery is in the disconnect state. The - * discharge FET may not be enabled and so attempting Try.Src may cut - * off our only power source at the time. + * Enable try source when dual-role toggling AND battery is capable + * of powering the whole system. */ - new_try_src &= (battery_get_disconnect_state() == - BATTERY_NOT_DISCONNECTED); -#elif defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ - defined(CONFIG_BATTERY_PRESENT_GPIO) - /* - * When battery is cutoff in ship mode it may not be reliable to - * check if battery is present with its state of charge. - * Also check if battery is initialized and ready to provide power. - */ - new_try_src &= (battery_is_present() == BP_YES); -#endif /* CONFIG_BATTERY_PRESENT_[CUSTOM|GPIO] */ + new_try_src = (try_src && pd_is_battery_capable()); #if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0 /* * If a dedicated supplier is present, power is not a concern and - * therefore always allow Try.Src. + * therefore allow Try.Src if we're toggling. */ - new_try_src |= (charge_manager_get_supplier() == - CHARGE_SUPPLIER_DEDICATED); + new_try_src = try_src && (charge_manager_get_supplier() == + CHARGE_SUPPLIER_DEDICATED); #endif /* CONFIG_DEDICATED_CHARGE_PORT_COUNT */ return new_try_src; diff --git a/common/usb_pd_flags.c b/common/usb_pd_flags.c new file mode 100644 index 0000000000..fdd7a6f2af --- /dev/null +++ b/common/usb_pd_flags.c @@ -0,0 +1,66 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Contains USB PD accessors definition + */ + +#include "common.h" +#include "usb_pd_flags.h" + +static union usb_pd_runtime_flags usb_pd_flags; +BUILD_ASSERT(sizeof(usb_pd_flags) == sizeof(uint32_t)); + +enum usb_pd_vbus_detect get_usb_pd_vbus_detect(void) +{ + if (IS_ENABLED(CONFIG_USB_PD_RUNTIME_FLAGS)) + return (enum usb_pd_vbus_detect)usb_pd_flags.vbus_detect; + else if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_TCPC)) + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_TCPC; + else if (IS_ENABLED(CONFIG_USD_PD_VBUS_DETECT_GPIO)) + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_GPIO; + else if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_PPC)) + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_PPC; + else if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_CHARGER)) + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_CHARGER; + else if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_NONE)) + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_NONE; + else + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_UNKNOWN; +} + +enum usb_pd_discharge get_usb_pd_discharge(void) +{ + if (IS_ENABLED(CONFIG_USB_PD_RUNTIME_FLAGS)) + return (enum usb_pd_discharge)usb_pd_flags.discharge; + else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_TCPC)) + return (enum usb_pd_discharge)USB_PD_DISCHARGE_TCPC; + else if (IS_ENABLED(CONFIG_USD_PD_DISCHARGE_GPIO)) + return (enum usb_pd_discharge)USB_PD_DISCHARGE_GPIO; + else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_PPC)) + return (enum usb_pd_discharge)USB_PD_DISCHARGE_PPC; + else + return (enum usb_pd_discharge)USB_PD_DISCHARGE_NONE; +} + +enum usb_pd_charger_otg get_usb_pd_charger_otg(void) +{ + return usb_pd_flags.charger_otg; +} + +void set_usb_pd_vbus_detect(enum usb_pd_vbus_detect vbus_detect) +{ + usb_pd_flags.vbus_detect = vbus_detect; +} + +void set_usb_pd_discharge(enum usb_pd_discharge discharge) +{ + usb_pd_flags.discharge = discharge; +} + +void set_usb_pd_charger_otg(enum usb_pd_charger_otg charger_otg) +{ + usb_pd_flags.charger_otg = charger_otg; +} diff --git a/common/usb_pd_host_cmd.c b/common/usb_pd_host_cmd.c index 8bdc50a0e3..d051a8f2e7 100644 --- a/common/usb_pd_host_cmd.c +++ b/common/usb_pd_host_cmd.c @@ -1,36 +1,27 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Host commands for USB-PD module. */ -#include - #include "atomic.h" #include "battery.h" #include "charge_manager.h" #include "console.h" #include "ec_commands.h" #include "host_command.h" -#include "tcpm.h" +#include "mkbp_event.h" +#include "tcpm/tcpm.h" +#include "usb_common.h" #include "usb_mux.h" -#include "usb_pd_tcpm.h" #include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include #ifdef CONFIG_COMMON_RUNTIME -/* - * If we are trying to upgrade the TCPC port that is supplying power, then we - * need to ensure that the battery has enough charge for the upgrade. 100mAh - * is about 5% of most batteries, and it should be enough charge to get us - * through the EC jump to RW and PD upgrade. - */ -#define MIN_BATTERY_FOR_TCPC_UPGRADE_MAH 100 /* mAH */ - -struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES]; - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else /* CONFIG_COMMON_RUNTIME */ #define CPRINTF(format, args...) #define CPRINTS(format, args...) @@ -47,9 +38,7 @@ static enum ec_status hc_pd_ports(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_PORTS, - hc_pd_ports, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_PORTS, hc_pd_ports, EC_VER_MASK(0)); #ifdef CONFIG_HOSTCMD_RWHASHPD static enum ec_status @@ -80,8 +69,7 @@ hc_remote_rw_hash_entry(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_RW_HASH_ENTRY, - hc_remote_rw_hash_entry, +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_RW_HASH_ENTRY, hc_remote_rw_hash_entry, EC_VER_MASK(0)); #endif /* CONFIG_HOSTCMD_RWHASHPD */ @@ -102,145 +90,55 @@ static enum ec_status hc_remote_pd_chip_info(struct host_cmd_handler_args *args) * same layout for v0 data. (v1 just appends data) */ args->response_size = - args->version ? sizeof(struct ec_response_pd_chip_info_v1) - : sizeof(struct ec_response_pd_chip_info); + args->version ? sizeof(struct ec_response_pd_chip_info_v1) : + sizeof(struct ec_response_pd_chip_info); memcpy(args->response, &info, args->response_size); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_PD_CHIP_INFO, - hc_remote_pd_chip_info, +DECLARE_HOST_COMMAND(EC_CMD_PD_CHIP_INFO, hc_remote_pd_chip_info, EC_VER_MASK(0) | EC_VER_MASK(1)); #endif /* CONFIG_EC_CMD_PD_CHIP_INFO && !CONFIG_USB_PD_TCPC */ #ifdef CONFIG_USB_PD_ALT_MODE_DFP -static enum ec_status hc_remote_pd_set_amode(struct host_cmd_handler_args *args) -{ - const struct ec_params_usb_pd_set_mode_request *p = args->params; - - if ((p->port >= board_get_usb_pd_port_count()) || - (!p->svid) || (!p->opos)) - return EC_RES_INVALID_PARAM; - - switch (p->cmd) { - case PD_EXIT_MODE: - if (pd_dfp_exit_mode(p->port, TCPC_TX_SOP, p->svid, p->opos)) - pd_send_vdm(p->port, p->svid, - CMD_EXIT_MODE | VDO_OPOS(p->opos), NULL, 0); - else { - CPRINTF("Failed exit mode\n"); - return EC_RES_ERROR; - } - break; - case PD_ENTER_MODE: - if (pd_dfp_enter_mode(p->port, TCPC_TX_SOP, p->svid, p->opos)) - pd_send_vdm(p->port, p->svid, CMD_ENTER_MODE | - VDO_OPOS(p->opos), NULL, 0); - break; - default: - return EC_RES_INVALID_PARAM; - } - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_SET_AMODE, - hc_remote_pd_set_amode, - EC_VER_MASK(0)); - static enum ec_status hc_remote_pd_discovery(struct host_cmd_handler_args *args) { - const uint8_t *port = args->params; + const struct ec_params_usb_pd_info_request *p = args->params; struct ec_params_usb_pd_discovery_entry *r = args->response; - if (*port >= board_get_usb_pd_port_count()) + if (p->port >= board_get_usb_pd_port_count()) return EC_RES_INVALID_PARAM; - r->vid = pd_get_identity_vid(*port); - r->ptype = pd_get_product_type(*port); + r->vid = pd_get_identity_vid(p->port); + r->ptype = pd_get_product_type(p->port); /* pid only included if vid is assigned */ if (r->vid) - r->pid = pd_get_identity_pid(*port); - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DISCOVERY, - hc_remote_pd_discovery, - EC_VER_MASK(0)); - -static enum ec_status hc_remote_pd_get_amode(struct host_cmd_handler_args *args) -{ - struct svdm_amode_data *modep; - const struct ec_params_usb_pd_get_mode_request *p = args->params; - struct ec_params_usb_pd_get_mode_response *r = args->response; - - if (p->port >= board_get_usb_pd_port_count()) - return EC_RES_INVALID_PARAM; - - /* no more to send */ - /* TODO(b/148528713): Use TCPMv2's separate storage for SOP'. */ - if (p->svid_idx >= pd_get_svid_count(p->port, TCPC_TX_SOP)) { - r->svid = 0; - args->response_size = sizeof(r->svid); - return EC_RES_SUCCESS; - } - - r->svid = pd_get_svid(p->port, p->svid_idx, TCPC_TX_SOP); - r->opos = 0; - memcpy(r->vdo, pd_get_mode_vdo(p->port, p->svid_idx, TCPC_TX_SOP), - sizeof(uint32_t) * PDO_MODES); - modep = pd_get_amode_data(p->port, TCPC_TX_SOP, r->svid); - - if (modep) - r->opos = pd_alt_mode(p->port, TCPC_TX_SOP, r->svid); + r->pid = pd_get_identity_pid(p->port); args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_GET_AMODE, - hc_remote_pd_get_amode, +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DISCOVERY, hc_remote_pd_discovery, EC_VER_MASK(0)); #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ #ifdef CONFIG_COMMON_RUNTIME -static enum ec_status hc_remote_pd_dev_info(struct host_cmd_handler_args *args) -{ - const uint8_t *port = args->params; - struct ec_params_usb_pd_rw_hash_entry *r = args->response; - uint16_t dev_id; - uint32_t current_image; - - if (*port >= board_get_usb_pd_port_count()) - return EC_RES_INVALID_PARAM; - - pd_dev_get_rw_hash(*port, &dev_id, r->dev_rw_hash, ¤t_image); - - r->dev_id = dev_id; - r->current_image = current_image; - - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DEV_INFO, - hc_remote_pd_dev_info, - EC_VER_MASK(0)); - static const enum pd_dual_role_states dual_role_map[USB_PD_CTRL_ROLE_COUNT] = { - [USB_PD_CTRL_ROLE_TOGGLE_ON] = PD_DRP_TOGGLE_ON, - [USB_PD_CTRL_ROLE_TOGGLE_OFF] = PD_DRP_TOGGLE_OFF, - [USB_PD_CTRL_ROLE_FORCE_SINK] = PD_DRP_FORCE_SINK, + [USB_PD_CTRL_ROLE_TOGGLE_ON] = PD_DRP_TOGGLE_ON, + [USB_PD_CTRL_ROLE_TOGGLE_OFF] = PD_DRP_TOGGLE_OFF, + [USB_PD_CTRL_ROLE_FORCE_SINK] = PD_DRP_FORCE_SINK, [USB_PD_CTRL_ROLE_FORCE_SOURCE] = PD_DRP_FORCE_SOURCE, - [USB_PD_CTRL_ROLE_FREEZE] = PD_DRP_FREEZE, + [USB_PD_CTRL_ROLE_FREEZE] = PD_DRP_FREEZE, }; static const mux_state_t typec_mux_map[USB_PD_CTRL_MUX_COUNT] = { [USB_PD_CTRL_MUX_NONE] = USB_PD_MUX_NONE, - [USB_PD_CTRL_MUX_USB] = USB_PD_MUX_USB_ENABLED, + [USB_PD_CTRL_MUX_USB] = USB_PD_MUX_USB_ENABLED, [USB_PD_CTRL_MUX_AUTO] = USB_PD_MUX_DP_ENABLED, - [USB_PD_CTRL_MUX_DP] = USB_PD_MUX_DP_ENABLED, + [USB_PD_CTRL_MUX_DP] = USB_PD_MUX_DP_ENABLED, [USB_PD_CTRL_MUX_DOCK] = USB_PD_MUX_DOCK, }; @@ -250,49 +148,66 @@ static const mux_state_t typec_mux_map[USB_PD_CTRL_MUX_COUNT] = { * Bit 1: Optical/Non-optical cable * Bit 2: Legacy Thunderbolt adapter * Bit 3: Active Link Uni-Direction/Bi-Direction + * Bit 4: Retimer/Rediriver cable */ static uint8_t get_pd_control_flags(int port) { union tbt_mode_resp_cable cable_resp; union tbt_mode_resp_device device_resp; + uint8_t control_flags = 0; - if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) + if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP) || + !IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) return 0; - cable_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPC_TX_SOP_PRIME); - device_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPC_TX_SOP); + cable_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); + device_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP); /* * Ref: USB Type-C Cable and Connector Specification * Table F-11 TBT3 Cable Discover Mode VDO Responses * For Passive cables, Active Cable Plug link training is set to 0 */ - return (cable_resp.lsrx_comm == UNIDIR_LSRX_COMM ? - USB_PD_CTRL_ACTIVE_LINK_UNIDIR : 0) | - (device_resp.tbt_adapter == TBT_ADAPTER_TBT2_LEGACY ? - USB_PD_CTRL_TBT_LEGACY_ADAPTER : 0) | - (cable_resp.tbt_cable == TBT_CABLE_OPTICAL ? - USB_PD_CTRL_OPTICAL_CABLE : 0) | - (cable_resp.retimer_type == USB_RETIMER ? - USB_PD_CTRL_ACTIVE_CABLE : 0); + control_flags |= (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE || + cable_resp.tbt_active_passive == TBT_CABLE_ACTIVE) ? + USB_PD_CTRL_ACTIVE_CABLE : + 0; + control_flags |= cable_resp.tbt_cable == TBT_CABLE_OPTICAL ? + USB_PD_CTRL_OPTICAL_CABLE : + 0; + control_flags |= device_resp.tbt_adapter == TBT_ADAPTER_TBT2_LEGACY ? + USB_PD_CTRL_TBT_LEGACY_ADAPTER : + 0; + control_flags |= cable_resp.lsrx_comm == UNIDIR_LSRX_COMM ? + USB_PD_CTRL_ACTIVE_LINK_UNIDIR : + 0; + control_flags |= cable_resp.retimer_type == USB_RETIMER ? + USB_PD_CTRL_RETIMER_CABLE : + 0; + + return control_flags; } static uint8_t pd_get_role_flags(int port) { return (pd_get_power_role(port) == PD_ROLE_SOURCE ? - PD_CTRL_RESP_ROLE_POWER : 0) | - (pd_get_data_role(port) == PD_ROLE_DFP ? - PD_CTRL_RESP_ROLE_DATA : 0) | - (pd_get_vconn_state(port) ? - PD_CTRL_RESP_ROLE_VCONN : 0) | - (pd_get_partner_dual_role_power(port) ? - PD_CTRL_RESP_ROLE_DR_POWER : 0) | - (pd_get_partner_data_swap_capable(port) ? - PD_CTRL_RESP_ROLE_DR_DATA : 0) | - (pd_get_partner_usb_comm_capable(port) ? - PD_CTRL_RESP_ROLE_USB_COMM : 0) | - (pd_get_partner_unconstr_power(port) ? - PD_CTRL_RESP_ROLE_UNCONSTRAINED : 0); + PD_CTRL_RESP_ROLE_POWER : + 0) | + (pd_get_data_role(port) == PD_ROLE_DFP ? PD_CTRL_RESP_ROLE_DATA : + 0) | + (pd_get_vconn_state(port) ? PD_CTRL_RESP_ROLE_VCONN : 0) | + (pd_get_partner_dual_role_power(port) ? + PD_CTRL_RESP_ROLE_DR_POWER : + 0) | + (pd_get_partner_data_swap_capable(port) ? + PD_CTRL_RESP_ROLE_DR_DATA : + 0) | + (pd_get_partner_usb_comm_capable(port) ? + PD_CTRL_RESP_ROLE_USB_COMM : + 0) | + (pd_get_partner_unconstr_power(port) ? + PD_CTRL_RESP_ROLE_UNCONSTRAINED : + 0); } static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args) @@ -302,7 +217,6 @@ static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args) struct ec_response_usb_pd_control_v1 *r_v1 = args->response; struct ec_response_usb_pd_control *r = args->response; const char *task_state_name; - mux_state_t mux_state; if (p->port >= board_get_usb_pd_port_count()) return EC_RES_INVALID_PARAM; @@ -319,12 +233,12 @@ static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args) } if (IS_ENABLED(CONFIG_USBC_SS_MUX) && - p->mux != USB_PD_CTRL_MUX_NO_CHANGE) + p->mux != USB_PD_CTRL_MUX_NO_CHANGE) usb_mux_set(p->port, typec_mux_map[p->mux], typec_mux_map[p->mux] == USB_PD_MUX_NONE ? - USB_SWITCH_DISCONNECT : - USB_SWITCH_CONNECT, - pd_get_polarity(p->port)); + USB_SWITCH_DISCONNECT : + USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(p->port))); if (p->swap == USB_PD_CTRL_SWAP_DATA) { pd_request_data_swap(p->port); @@ -332,7 +246,7 @@ static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args) if (p->swap == USB_PD_CTRL_SWAP_POWER) pd_request_power_swap(p->port); else if (IS_ENABLED(CONFIG_USBC_VCONN_SWAP) && - p->swap == USB_PD_CTRL_SWAP_VCONN) + p->swap == USB_PD_CTRL_SWAP_VCONN) pd_request_vconn_swap(p->port); } @@ -346,17 +260,19 @@ static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args) break; case 1: case 2: - r_v2->enabled = - (pd_comm_is_enabled(p->port) ? - PD_CTRL_RESP_ENABLED_COMMS : 0) | - (pd_is_connected(p->port) ? - PD_CTRL_RESP_ENABLED_CONNECTED : 0) | - (pd_capable(p->port) ? - PD_CTRL_RESP_ENABLED_PD_CAPABLE : 0); + r_v2->enabled = (pd_comm_is_enabled(p->port) ? + PD_CTRL_RESP_ENABLED_COMMS : + 0) | + (pd_is_connected(p->port) ? + PD_CTRL_RESP_ENABLED_CONNECTED : + 0) | + (pd_capable(p->port) ? + PD_CTRL_RESP_ENABLED_PD_CAPABLE : + 0); r_v2->role = pd_get_role_flags(p->port); r_v2->polarity = pd_get_polarity(p->port); - r_v2->cc_state = pd_get_task_cc_state(p->port); + r_v2->cc_state = pd_get_task_cc_state(p->port); task_state_name = pd_get_task_state_name(p->port); if (task_state_name) strzcpy(r_v2->state, task_state_name, @@ -365,18 +281,12 @@ static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args) r_v2->state[0] = '\0'; r_v2->control_flags = get_pd_control_flags(p->port); - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { - r_v2->dp_mode = get_dp_pin_mode(p->port); - mux_state = usb_mux_get(p->port); - if (mux_state & USB_PD_MUX_USB4_ENABLED) { - r_v2->cable_speed = - get_usb4_cable_speed(p->port); - } else if (mux_state & USB_PD_MUX_TBT_COMPAT_ENABLED) { - r_v2->cable_speed = - get_tbt_cable_speed(p->port); - r_v2->cable_gen = - get_tbt_rounded_support(p->port); - } + + r_v2->dp_mode = get_dp_pin_mode(p->port); + + if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) { + r_v2->cable_speed = get_tbt_cable_speed(p->port); + r_v2->cable_gen = get_tbt_rounded_support(p->port); } if (args->version == 1) @@ -390,99 +300,10 @@ static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args) } return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_CONTROL, - hc_usb_pd_control, +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_CONTROL, hc_usb_pd_control, EC_VER_MASK(0) | EC_VER_MASK(1) | EC_VER_MASK(2)); #endif /* CONFIG_COMMON_RUNTIME */ -#if defined(CONFIG_HOSTCMD_FLASHPD) && defined(CONFIG_USB_PD_TCPMV2) -static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args) -{ - const struct ec_params_usb_pd_fw_update *p = args->params; - int port = p->port; - int rv = EC_RES_SUCCESS; - const uint32_t *data = &(p->size) + 1; - int i, size; - - if (port >= board_get_usb_pd_port_count()) - return EC_RES_INVALID_PARAM; - - if (p->size + sizeof(*p) > args->params_size) - return EC_RES_INVALID_PARAM; - -#if defined(CONFIG_CHARGE_MANAGER) && defined(CONFIG_BATTERY) && \ - (defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ - defined(CONFIG_BATTERY_PRESENT_GPIO)) - /* - * Do not allow PD firmware update if no battery and this port - * is sinking power, because we will lose power. - */ - if (battery_is_present() != BP_YES && - charge_manager_get_active_charge_port() == port) - return EC_RES_UNAVAILABLE; -#endif - - switch (p->cmd) { - case USB_PD_FW_REBOOT: - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0); - /* - * Return immediately to free pending i2c bus. Host needs to - * manage this delay. - */ - return EC_RES_SUCCESS; - - case USB_PD_FW_FLASH_ERASE: - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0); - /* - * Return immediately. Host needs to manage delays here which - * can be as long as 1.2 seconds on 64KB RW flash. - */ - return EC_RES_SUCCESS; - - case USB_PD_FW_ERASE_SIG: - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0); - break; - - case USB_PD_FW_FLASH_WRITE: - /* Data size must be a multiple of 4 */ - if (!p->size || p->size % 4) - return EC_RES_INVALID_PARAM; - - size = p->size / 4; - for (i = 0; i < size; i += VDO_MAX_SIZE - 1) { - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE, - data + i, MIN(size - i, VDO_MAX_SIZE - 1)); - } - return EC_RES_SUCCESS; - - default: - return EC_RES_INVALID_PARAM; - } - - return rv; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE, - hc_remote_flash, - EC_VER_MASK(0)); -#endif /* CONFIG_HOSTCMD_FLASHPD && CONFIG_USB_PD_TCPMV2 */ - -#ifdef CONFIG_HOSTCMD_EVENTS -void pd_notify_dp_alt_mode_entry(void) -{ - /* - * Note: EC_HOST_EVENT_PD_MCU may be a more appropriate host event to - * send, but we do not send that here because there are other cases - * where we send EC_HOST_EVENT_PD_MCU such as charger insertion or - * removal. Currently, those do not wake the system up, but - * EC_HOST_EVENT_MODE_CHANGE does. If we made the system wake up on - * EC_HOST_EVENT_PD_MCU, we would be turning the internal display on on - * every charger insertion/removal, which is not desired. - */ - CPRINTS("Notifying AP of DP Alt Mode Entry..."); - host_set_single_event(EC_HOST_EVENT_MODE_CHANGE); -} -#endif /* CONFIG_HOSTCMD_EVENTS */ - __overridable enum ec_pd_port_location board_get_pd_port_location(int port) { (void)port; @@ -509,8 +330,7 @@ static enum ec_status hc_get_pd_port_caps(struct host_cmd_handler_args *args) else r->pd_try_power_role_cap = EC_PD_TRY_POWER_ROLE_NONE; - if (IS_ENABLED(CONFIG_USB_VPD) || - IS_ENABLED(CONFIG_USB_CTVPD)) + if (IS_ENABLED(CONFIG_USB_VPD) || IS_ENABLED(CONFIG_USB_CTVPD)) r->pd_data_role_cap = EC_PD_DATA_ROLE_UFP; else r->pd_data_role_cap = EC_PD_DATA_ROLE_DUAL; @@ -522,14 +342,22 @@ static enum ec_status hc_get_pd_port_caps(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_GET_PD_PORT_CAPS, - hc_get_pd_port_caps, +DECLARE_HOST_COMMAND(EC_CMD_GET_PD_PORT_CAPS, hc_get_pd_port_caps, EC_VER_MASK(0)); #ifdef CONFIG_HOSTCMD_PD_CONTROL +static int pd_control_disabled[CONFIG_USB_PD_PORT_MAX_COUNT]; + +/* Only allow port re-enable in unit tests */ +#ifdef TEST_BUILD +void pd_control_port_enable(int port) +{ + pd_control_disabled[port] = 0; +} +#endif /* TEST_BUILD */ + static enum ec_status pd_control(struct host_cmd_handler_args *args) { - static int pd_control_disabled[CONFIG_USB_PD_PORT_MAX_COUNT]; const struct ec_params_pd_control *cmd = args->params; int enable = 0; @@ -546,49 +374,13 @@ static enum ec_status pd_control(struct host_cmd_handler_args *args) return EC_RES_ACCESS_DENIED; if (cmd->subcmd == PD_SUSPEND) { - /* - * The AP is requesting to suspend PD traffic on the EC so it - * can perform a firmware upgrade. If Vbus is present on the - * connector (it is either a source or sink), then we will - * prevent the upgrade if there is not enough battery to finish - * the upgrade. We cannot rely on the EC's active charger data - * as the EC just rebooted into RW and has not necessarily - * picked the active charger yet. - */ -#ifdef HAS_TASK_CHARGER - if (pd_is_vbus_present(cmd->chip)) { - struct batt_params batt = { 0 }; - /* - * The charger task has not re-initialized, so we need - * to ask the battery directly. - */ - battery_get_params(&batt); - if (batt.remaining_capacity < - MIN_BATTERY_FOR_TCPC_UPGRADE_MAH || - batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY) { - CPRINTS("C%d: Cannot suspend for upgrade, not " - "enough battery (%dmAh)!", - cmd->chip, batt.remaining_capacity); - return EC_RES_BUSY; - } - } -#else - if (pd_is_vbus_present(cmd->chip)) { - CPRINTS("C%d: Cannot suspend for upgrade, Vbus " - "present!", - cmd->chip); + if (!pd_firmware_upgrade_check_power_readiness(cmd->chip)) return EC_RES_BUSY; - } -#endif enable = 0; } else if (cmd->subcmd == PD_RESUME) { enable = 1; } else if (cmd->subcmd == PD_RESET) { -#ifdef HAS_TASK_PDCMD board_reset_pd_mcu(); -#else - return EC_RES_INVALID_COMMAND; -#endif } else if (cmd->subcmd == PD_CHIP_ON && board_set_tcpc_power_mode) { board_set_tcpc_power_mode(cmd->chip, 1); return EC_RES_SUCCESS; @@ -604,13 +396,24 @@ static enum ec_status pd_control(struct host_cmd_handler_args *args) DECLARE_HOST_COMMAND(EC_CMD_PD_CONTROL, pd_control, EC_VER_MASK(0)); #endif /* CONFIG_HOSTCMD_PD_CONTROL */ -#if !defined(CONFIG_USB_PD_TCPM_STUB) && !defined(TEST_BUILD) +#if !defined(CONFIG_USB_PD_TCPM_STUB) /* * PD host event status for host command * Note: this variable must be aligned on 4-byte boundary because we pass the - * address to deprecated_atomic_ functions which use assembly to access them. + * address to atomic_ functions which use assembly to access them. */ -static uint32_t pd_host_event_status __aligned(4); +static atomic_t pd_host_event_status __aligned(4); + +void pd_send_host_event(int mask) +{ + /* mask must be set */ + if (!mask) + return; + + atomic_or(&pd_host_event_status, mask); + /* interrupt the AP */ + host_set_single_event(EC_HOST_EVENT_PD_MCU); +} static enum ec_status hc_pd_host_event_status(struct host_cmd_handler_args *args) @@ -618,25 +421,13 @@ hc_pd_host_event_status(struct host_cmd_handler_args *args) struct ec_response_host_event_status *r = args->response; /* Read and clear the host event status to return to AP */ - r->status = deprecated_atomic_read_clear(&pd_host_event_status); + r->status = atomic_clear(&pd_host_event_status); args->response_size = sizeof(*r); return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_PD_HOST_EVENT_STATUS, hc_pd_host_event_status, EC_VER_MASK(0)); - -/* Send host event up to AP */ -void pd_send_host_event(int mask) -{ - /* mask must be set */ - if (!mask) - return; - - deprecated_atomic_or(&pd_host_event_status, mask); - /* interrupt the AP */ - host_set_single_event(EC_HOST_EVENT_PD_MCU); -} -#endif /* ! CONFIG_USB_PD_TCPM_STUB && ! TEST_BUILD */ +#endif /* ! CONFIG_USB_PD_TCPM_STUB */ #endif /* HAS_TASK_HOSTCMD */ diff --git a/common/usb_pd_pdo.c b/common/usb_pd_pdo.c new file mode 100644 index 0000000000..66f5f3feac --- /dev/null +++ b/common/usb_pd_pdo.c @@ -0,0 +1,33 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "usb_pd.h" +#include "usb_pd_pdo.h" +#include "util.h" + +#ifndef CONFIG_USB_PD_CUSTOM_PDO + +#define PDO_FIXED_FLAGS \ + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_COMM_CAP) + +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +const uint32_t pd_src_pdo_max[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max); + +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, + GENERIC_MIN((PD_OPERATING_POWER_MW / 5), PD_MAX_CURRENT_MA), + PDO_FIXED_FLAGS), + PDO_BATT(4750, PD_MAX_VOLTAGE_MV, PD_OPERATING_POWER_MW), + PDO_VAR(4750, PD_MAX_VOLTAGE_MV, PD_MAX_CURRENT_MA), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); + +#endif /* CONFIG_USB_PD_CUSTOM_PDO */ diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c index 5ad4188e54..feb30db440 100644 --- a/common/usb_pd_policy.c +++ b/common/usb_pd_policy.c @@ -1,12 +1,15 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "atomic.h" +#include "builtin/assert.h" #include "charge_manager.h" +#include "chipset.h" #include "common.h" #include "console.h" +#include "cros_version.h" #include "ec_commands.h" #include "flash.h" #include "gpio.h" @@ -18,19 +21,20 @@ #include "sha256.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" #include "timer.h" -#include "util.h" +#include "typec_control.h" #include "usb_api.h" #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_tcpm.h" #include "usbc_ppc.h" -#include "version.h" +#include "util.h" #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) #else #define CPRINTS(format, args...) #define CPRINTF(format, args...) @@ -44,10 +48,42 @@ #error This file must only be used with TCPMv1 #endif +#ifdef CONFIG_USB_PD_ALT_MODE_DFP +#ifndef PORT_TO_HPD +#define PORT_TO_HPD(port) ((port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD) +#endif /* PORT_TO_HPD */ + +/* Tracker for which task is waiting on sysjump prep to finish */ +static volatile task_id_t sysjump_task_waiting = TASK_ID_INVALID; + +/* + * timestamp of the next possible toggle to ensure the 2-ms spacing + * between IRQ_HPD. Since this is used in overridable functions, this + * has to be global. + */ +uint64_t svdm_hpd_deadline[CONFIG_USB_PD_PORT_MAX_COUNT]; + +int dp_flags[CONFIG_USB_PD_PORT_MAX_COUNT]; + +uint32_t dp_status[CONFIG_USB_PD_PORT_MAX_COUNT]; + +/* Console command multi-function preference set for a PD port. */ + +__maybe_unused bool dp_port_mf_allow[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [0 ... CONFIG_USB_PD_PORT_MAX_COUNT - 1] = true +}; + +__overridable const struct svdm_response svdm_rsp = { + .identity = NULL, + .svids = NULL, + .modes = NULL, +}; +#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ + static int rw_flash_changed = 1; -__overridable void pd_check_pr_role(int port, - enum pd_power_role pr_role, int flags) +__overridable void pd_check_pr_role(int port, enum pd_power_role pr_role, + int flags) { /* * If partner is dual-role power and dualrole toggling is on, consider @@ -63,34 +99,24 @@ __overridable void pd_check_pr_role(int port, int partner_unconstrained = flags & PD_FLAGS_PARTNER_UNCONSTR; if ((!partner_unconstrained && pr_role == PD_ROLE_SINK) || - (partner_unconstrained && pr_role == PD_ROLE_SOURCE)) + (partner_unconstrained && pr_role == PD_ROLE_SOURCE)) pd_request_power_swap(port); } } -__overridable void pd_check_dr_role(int port, - enum pd_data_role dr_role, int flags) +__overridable void pd_check_dr_role(int port, enum pd_data_role dr_role, + int flags) { /* If UFP, try to switch to DFP */ if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP) pd_request_data_swap(port); } -#ifdef CONFIG_MKBP_EVENT -static int dp_alt_mode_entry_get_next_event(uint8_t *data) -{ - return EC_SUCCESS; -} -DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_DP_ALT_MODE_ENTERED, - dp_alt_mode_entry_get_next_event); -#endif /* CONFIG_MKBP_EVENT */ - -#ifdef CONFIG_USB_PD_DUAL_ROLE /* Last received source cap */ static uint32_t pd_src_caps[CONFIG_USB_PD_PORT_MAX_COUNT][PDO_MAX_OBJECTS]; static uint8_t pd_src_cap_cnt[CONFIG_USB_PD_PORT_MAX_COUNT]; -const uint32_t * const pd_get_src_caps(int port) +const uint32_t *const pd_get_src_caps(int port) { return pd_src_caps[port]; } @@ -109,261 +135,24 @@ uint8_t pd_get_src_cap_cnt(int port) { return pd_src_cap_cnt[port]; } -#endif /* CONFIG_USB_PD_DUAL_ROLE */ - -static struct pd_cable cable[CONFIG_USB_PD_PORT_MAX_COUNT]; - -enum pd_rev_type get_usb_pd_cable_revision(int port) -{ - return cable[port].rev; -} - -bool consume_sop_prime_repeat_msg(int port, uint8_t msg_id) -{ - - if (cable[port].last_sop_p_msg_id != msg_id) { - cable[port].last_sop_p_msg_id = msg_id; - return false; - } - CPRINTF("C%d SOP Prime repeat msg_id %d\n", port, msg_id); - return true; -} - -bool consume_sop_prime_prime_repeat_msg(int port, uint8_t msg_id) -{ - - if (cable[port].last_sop_p_p_msg_id != msg_id) { - cable[port].last_sop_p_p_msg_id = msg_id; - return false; - } - CPRINTF("C%d SOP Prime Prime repeat msg_id %d\n", port, msg_id); - return true; -} - -__maybe_unused static uint8_t is_sop_prime_ready(int port) -{ - /* - * Ref: USB PD 3.0 sec 2.5.4: When an Explicit Contract is in place the - * VCONN Source (either the DFP or the UFP) can communicate with the - * Cable Plug(s) using SOP’/SOP’’ Packets - * - * Ref: USB PD 2.0 sec 2.4.4: When an Explicit Contract is in place the - * DFP (either the Source or the Sink) can communicate with the - * Cable Plug(s) using SOP’/SOP” Packets. - * Sec 3.6.11 : Before communicating with a Cable Plug a Port Should - * ensure that it is the Vconn Source - */ - return (pd_get_vconn_state(port) && (IS_ENABLED(CONFIG_USB_PD_REV30) - || (pd_get_data_role(port) == PD_ROLE_DFP))); -} - -void reset_pd_cable(int port) -{ - memset(&cable[port], 0, sizeof(cable[port])); - cable[port].last_sop_p_msg_id = INVALID_MSG_ID_COUNTER; - cable[port].last_sop_p_p_msg_id = INVALID_MSG_ID_COUNTER; -} - -bool should_enter_usb4_mode(int port) -{ - return IS_ENABLED(CONFIG_USB_PD_USB4) && - cable[port].flags & CABLE_FLAGS_ENTER_USB_MODE; -} - -void enable_enter_usb4_mode(int port) -{ - if (IS_ENABLED(CONFIG_USB_PD_USB4)) - cable[port].flags |= CABLE_FLAGS_ENTER_USB_MODE; -} - -void disable_enter_usb4_mode(int port) -{ - if (IS_ENABLED(CONFIG_USB_PD_USB4)) - cable[port].flags &= ~CABLE_FLAGS_ENTER_USB_MODE; -} #ifdef CONFIG_USB_PD_ALT_MODE #ifdef CONFIG_USB_PD_ALT_MODE_DFP -static struct pd_discovery - discovery[CONFIG_USB_PD_PORT_MAX_COUNT][DISCOVERY_TYPE_COUNT]; -static struct partner_active_modes - partner_amodes[CONFIG_USB_PD_PORT_MAX_COUNT][AMODE_TYPE_COUNT]; - -static bool is_vdo_present(int cnt, int index) -{ - return cnt > index; -} - -static bool is_modal(int port, int cnt, const uint32_t *payload) -{ - return is_vdo_present(cnt, VDO_INDEX_IDH) && - PD_IDH_IS_MODAL(payload[VDO_INDEX_IDH]); -} - -static bool is_tbt_compat_mode(int port, int cnt, const uint32_t *payload) -{ - /* - * Ref: USB Type-C cable and connector specification - * F.2.5 TBT3 Device Discover Mode Responses - */ - return is_vdo_present(cnt, VDO_INDEX_IDH) && - PD_VDO_RESP_MODE_INTEL_TBT(payload[VDO_INDEX_IDH]); -} - -static bool cable_supports_tbt_speed(int port) -{ - enum tbt_compat_cable_speed tbt_cable_speed = - get_tbt_cable_speed(port); - - return (tbt_cable_speed == TBT_SS_TBT_GEN3 || - tbt_cable_speed == TBT_SS_U32_GEN1_GEN2); -} - -static bool is_tbt_compat_enabled(int port) -{ - return (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && - (cable[port].flags & CABLE_FLAGS_TBT_COMPAT_ENABLE)); -} - -static void enable_tbt_compat_mode(int port) -{ - if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) - cable[port].flags |= CABLE_FLAGS_TBT_COMPAT_ENABLE; -} - -static inline void disable_tbt_compat_mode(int port) -{ - if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) - cable[port].flags &= ~CABLE_FLAGS_TBT_COMPAT_ENABLE; -} - -static inline void limit_tbt_cable_speed(int port) -{ - /* Cable flags are cleared when cable reset is called */ - cable[port].flags |= CABLE_FLAGS_TBT_COMPAT_LIMIT_SPEED; -} - -static inline bool is_limit_tbt_cable_speed(int port) -{ - return !!(cable[port].flags & CABLE_FLAGS_TBT_COMPAT_LIMIT_SPEED); -} - -static bool is_intel_svid(int port, enum tcpm_transmit_type type) -{ - int i; - - for (i = 0; i < discovery[port][type].svid_cnt; i++) { - if (pd_get_svid(port, i, type) == USB_VID_INTEL) - return true; - } - - return false; -} - -static inline bool is_usb4_mode_enabled(int port) -{ - return (IS_ENABLED(CONFIG_USB_PD_USB4) && - (cable[port].flags & CABLE_FLAGS_USB4_CAPABLE)); -} - -static inline void enable_usb4_mode(int port) -{ - if (IS_ENABLED(CONFIG_USB_PD_USB4)) - cable[port].flags |= CABLE_FLAGS_USB4_CAPABLE; -} - -static inline void disable_usb4_mode(int port) -{ - if (IS_ENABLED(CONFIG_USB_PD_USB4)) - cable[port].flags &= ~CABLE_FLAGS_USB4_CAPABLE; -} - -/* - * Ref: USB Type-C Cable and Connector Specification - * Figure 5-1 USB4 Discovery and Entry Flow Model. - * - * Note: USB Type-C Cable and Connector Specification - * doesn't include details for Revision 2 cables. - * - * Passive Cable - * | - * ----------------------------------- - * | | - * Revision 2 Revision 3 - * USB Signalling USB Signalling - * | | - * ------------------ ------------------------- - * | | | | | | | - * USB2.0 USB3.1 USB3.1 USB3.2 USB4 USB3.2 USB2 - * | Gen1 Gen1 Gen2 Gen2 Gen3 Gen1 | - * | | | | | | Exit - * -------- ------------ -------- USB4 - * | | | Discovery. - * Exit Is DFP Gen3 Capable? Enter USB4 - * USB4 | with respective - * Discovery. --- No ---|--- Yes --- cable speed. - * | | - * Enter USB4 with Is Cable TBT3 - * respective cable | - * speed. --- No ---|--- Yes --- - * | | - * Enter USB4 with Enter USB4 with - * TBT Gen2 passive TBT Gen3 passive - * cable. cable. - * - */ -static bool is_cable_ready_to_enter_usb4(int port, int cnt) -{ - /* TODO: USB4 enter mode for Active cables */ - struct pd_discovery *disc = &discovery[port][TCPC_TX_SOP_PRIME]; - if (IS_ENABLED(CONFIG_USB_PD_USB4) && - (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) && - is_vdo_present(cnt, VDO_INDEX_PTYPE_CABLE1)) { - switch (cable[port].rev) { - case PD_REV30: - switch (disc->identity.product_t1.p_rev30.ss) { - case USB_R30_SS_U40_GEN3: - case USB_R30_SS_U32_U40_GEN1: - return true; - case USB_R30_SS_U32_U40_GEN2: - /* Check if DFP is Gen 3 capable */ - if (IS_ENABLED(CONFIG_USB_PD_TBT_GEN3_CAPABLE)) - return false; - return true; - default: - disable_usb4_mode(port); - return false; - } - case PD_REV20: - switch (disc->identity.product_t1.p_rev20.ss) { - case USB_R20_SS_U31_GEN1_GEN2: - /* Check if DFP is Gen 3 capable */ - if (IS_ENABLED(CONFIG_USB_PD_TBT_GEN3_CAPABLE)) - return false; - return true; - default: - disable_usb4_mode(port); - return false; - } - default: - disable_usb4_mode(port); - } - } - return false; -} +static struct pd_discovery discovery[CONFIG_USB_PD_PORT_MAX_COUNT] + [DISCOVERY_TYPE_COUNT]; +static struct partner_active_modes partner_amodes[CONFIG_USB_PD_PORT_MAX_COUNT] + [AMODE_TYPE_COUNT]; void pd_dfp_discovery_init(int port) { memset(&discovery[port], 0, sizeof(struct pd_discovery)); - memset(&partner_amodes[port], 0, sizeof(partner_amodes[0])); } -static int dfp_discover_ident(uint32_t *payload) +void pd_dfp_mode_init(int port) { - payload[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_IDENT); - return 1; + memset(&partner_amodes[port], 0, sizeof(partner_amodes[0])); } static int dfp_discover_svids(uint32_t *payload) @@ -372,13 +161,20 @@ static int dfp_discover_svids(uint32_t *payload) return 1; } -struct pd_discovery *pd_get_am_discovery(int port, enum tcpm_transmit_type type) +struct pd_discovery * +pd_get_am_discovery_and_notify_access(int port, enum tcpci_msg_type type) +{ + return (struct pd_discovery *)pd_get_am_discovery(port, type); +} + +const struct pd_discovery *pd_get_am_discovery(int port, + enum tcpci_msg_type type) { return &discovery[port][type]; } -struct partner_active_modes *pd_get_partner_active_modes(int port, - enum tcpm_transmit_type type) +struct partner_active_modes * +pd_get_partner_active_modes(int port, enum tcpci_msg_type type) { assert(type < AMODE_TYPE_COUNT); return &partner_amodes[port][type]; @@ -398,7 +194,8 @@ void pd_set_dfp_enter_mode_flag(int port, bool set) */ static int dfp_discover_modes(int port, uint32_t *payload) { - struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP); + const struct pd_discovery *disc = + pd_get_am_discovery(port, TCPCI_MSG_SOP); uint16_t svid = disc->svids[disc->svid_idx].svid; if (disc->svid_idx >= disc->svid_cnt) @@ -409,231 +206,34 @@ static int dfp_discover_modes(int port, uint32_t *payload) return 1; } -static bool is_usb4_vdo(int port, int cnt, uint32_t *payload) -{ - enum idh_ptype ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]); - - if (IS_PD_IDH_UFP_PTYPE(ptype)) { - /* - * Ref: USB Type-C Cable and Connector Specification - * Figure 5-1 USB4 Discovery and Entry Flow Model - * Device USB4 VDO detection. - */ - return IS_ENABLED(CONFIG_USB_PD_USB4) && - is_vdo_present(cnt, VDO_INDEX_PTYPE_UFP1_VDO) && - PD_PRODUCT_IS_USB4(payload[VDO_INDEX_PTYPE_UFP1_VDO]); - } - return false; -} - -static int process_am_discover_ident_sop(int port, int cnt, - uint32_t head, uint32_t *payload, - enum tcpm_transmit_type *rtype) +static int process_am_discover_ident_sop(int port, int cnt, uint32_t head, + uint32_t *payload, + enum tcpci_msg_type *rtype) { pd_dfp_discovery_init(port); - dfp_consume_identity(port, TCPC_TX_SOP, cnt, payload); - - if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP) && is_sop_prime_ready(port) && - board_is_tbt_usb4_port(port)) { - - /* Enable USB4 mode if USB4 VDO present and port partner - * supports USB Rev 3.0. - */ - if (is_usb4_vdo(port, cnt, payload) && - PD_HEADER_REV(head) == PD_REV30) - enable_usb4_mode(port); - - /* - * Enable Thunderbolt-compatible mode if the modal operation is - * supported. - */ - if (is_modal(port, cnt, payload)) - enable_tbt_compat_mode(port); - - if (is_modal(port, cnt, payload) || - is_usb4_vdo(port, cnt, payload)) { - *rtype = TCPC_TX_SOP_PRIME; - return dfp_discover_ident(payload); - } - } - - return dfp_discover_svids(payload); -} - -static int process_am_discover_ident_sop_prime(int port, int cnt, - uint32_t head, uint32_t *payload) -{ - dfp_consume_identity(port, TCPC_TX_SOP_PRIME, cnt, payload); - cable[port].rev = PD_HEADER_REV(head); - - /* - * Enter USB4 mode if the cable supports USB4 operation and has USB4 - * VDO. - */ - if (is_usb4_mode_enabled(port) && - is_cable_ready_to_enter_usb4(port, cnt)) { - enable_enter_usb4_mode(port); - usb_mux_set_safe_mode(port); - /* - * To change the mode of operation from USB4 the port needs to - * be reconfigured. - * Ref: USB Type-C Cable and Connectot Spec section 5.4.4. - */ - disable_tbt_compat_mode(port); - return 0; - } - - /* - * Disable Thunderbolt-compatible mode if the cable does not support - * superspeed. - */ - if (is_tbt_compat_enabled(port) && !is_tbt_cable_superspeed(port)) - disable_tbt_compat_mode(port); + pd_dfp_mode_init(port); + dfp_consume_identity(port, TCPCI_MSG_SOP, cnt, payload); return dfp_discover_svids(payload); } static int process_am_discover_svids(int port, int cnt, uint32_t *payload, - enum tcpm_transmit_type sop, - enum tcpm_transmit_type *rtype) + enum tcpci_msg_type sop, + enum tcpci_msg_type *rtype) { /* * The pd_discovery structure stores SOP and SOP' discovery results * separately, but TCPMv1 depends on one-dimensional storage of SVIDs - * and modes. Therefore, always use TCPC_TX_SOP in TCPMv1. + * and modes. Therefore, always use TCPCI_MSG_SOP in TCPMv1. */ dfp_consume_svids(port, sop, cnt, payload); - /* - * Ref: USB Type-C Cable and Connector Specification, - * figure F-1: TBT3 Discovery Flow - * - * For USB4 mode if device or cable doesn't have Intel SVID, - * disable Thunderbolt-Compatible mode directly enter USB4 mode - * with USB3.2 Gen1/Gen2 speed. - * - * For Thunderbolt-compatible, check if 0x8087 is received for - * Discover SVID SOP. If not, disable Thunderbolt-compatible mode - * - * If 0x8087 is not received for Discover SVID SOP' limit to TBT - * passive Gen 2 cable. - */ - if (is_tbt_compat_enabled(port)) { - bool intel_svid = is_intel_svid(port, sop); - if (!intel_svid) { - if (is_usb4_mode_enabled(port)) { - disable_tbt_compat_mode(port); - cable[port].cable_mode_resp.tbt_cable_speed = - TBT_SS_U32_GEN1_GEN2; - enable_enter_usb4_mode(port); - usb_mux_set_safe_mode(port); - return 0; - } - - if (sop == TCPC_TX_SOP_PRIME) - limit_tbt_cable_speed(port); - else - disable_tbt_compat_mode(port); - } else if (sop == TCPC_TX_SOP) { - *rtype = TCPC_TX_SOP_PRIME; - return dfp_discover_svids(payload); - } - } - return dfp_discover_modes(port, payload); } - -static int process_tbt_compat_discover_modes(int port, - enum tcpm_transmit_type sop, uint32_t *payload, - enum tcpm_transmit_type *rtype) -{ - int rsize; - - /* Initialize transmit type to SOP */ - *rtype = TCPC_TX_SOP; - - /* - * For active cables, Enter mode: SOP', SOP'', SOP - * Ref: USB Type-C Cable and Connector Specification, figure F-1: TBT3 - * Discovery Flow and Section F.2.7 TBT3 Cable Enter Mode Command. - */ - if (sop == TCPC_TX_SOP_PRIME) { - /* Store Discover Mode SOP' response */ - cable[port].cable_mode_resp.raw_value = payload[1]; - - if (is_usb4_mode_enabled(port)) { - /* - * If Cable is not Thunderbolt Gen 3 - * capable or Thunderbolt Gen1_Gen2 - * capable, disable USB4 mode and - * continue flow for - * Thunderbolt-compatible mode - */ - if (cable_supports_tbt_speed(port)) { - enable_enter_usb4_mode(port); - usb_mux_set_safe_mode(port); - return 0; - } - disable_usb4_mode(port); - } - - /* - * Send TBT3 Cable Enter Mode (SOP') for active cables, - * otherwise send TBT3 Device Enter Mode (SOP). - */ - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) - *rtype = TCPC_TX_SOP_PRIME; - - rsize = enter_tbt_compat_mode(port, *rtype, payload); - } else { - /* Store Discover Mode SOP response */ - cable[port].dev_mode_resp.raw_value = payload[1]; - - if (is_limit_tbt_cable_speed(port)) { - /* - * Passive cable has Nacked for Discover SVID. - * No need to do Discover modes of cable. - * Enter into device Thunderbolt-compatible mode. - */ - rsize = enter_tbt_compat_mode(port, *rtype, payload); - } else { - /* Discover modes for SOP' */ - discovery[port][TCPC_TX_SOP].svid_idx--; - rsize = dfp_discover_modes(port, payload); - *rtype = TCPC_TX_SOP_PRIME; - } - } - - return rsize; -} - -static int obj_cnt_enter_tbt_compat_mode(int port, - enum tcpm_transmit_type sop, uint32_t *payload, - enum tcpm_transmit_type *rtype) -{ - struct pd_discovery *disc = &discovery[port][TCPC_TX_SOP_PRIME]; - - /* Enter mode SOP' for active cables */ - if (sop == TCPC_TX_SOP_PRIME) { - /* Check if the cable has a SOP'' controller */ - if (disc->identity.product_t1.a_rev20.sop_p_p) - *rtype = TCPC_TX_SOP_PRIME_PRIME; - return enter_tbt_compat_mode(port, *rtype, payload); - } - - /* Enter Mode SOP'' for active cables with SOP'' controller */ - if (sop == TCPC_TX_SOP_PRIME_PRIME) - return enter_tbt_compat_mode(port, *rtype, payload); - - /* Update Mux state to Thunderbolt-compatible mode. */ - set_tbt_compat_mode_ready(port); - /* No response once device (and cable) acks */ - return 0; -} #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, - uint32_t head, enum tcpm_transmit_type *rtype) + uint32_t head, enum tcpci_msg_type *rtype) { int cmd = PD_VDO_CMD(payload[0]); int cmd_type = PD_VDO_CMDT(payload[0]); @@ -642,11 +242,11 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, int rsize = 1; /* VDM header at a minimum */ #ifdef CONFIG_USB_PD_ALT_MODE_DFP - enum tcpm_transmit_type sop = PD_HEADER_GET_SOP(head); + enum tcpci_msg_type sop = PD_HEADER_GET_SOP(head); #endif /* Transmit SOP messages by default */ - *rtype = TCPC_TX_SOP; + *rtype = TCPCI_MSG_SOP; payload[0] &= ~VDO_CMDT_MASK; *rpayload = payload; @@ -702,32 +302,21 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, payload[0] |= VDO_CMDT(CMDT_RSP_BUSY); rsize = 1; } - payload[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)); + payload[0] |= + VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)); } else if (cmd_type == CMDT_RSP_ACK) { #ifdef CONFIG_USB_PD_ALT_MODE_DFP struct svdm_amode_data *modep; - modep = pd_get_amode_data(port, TCPC_TX_SOP, - PD_VDO_VID(payload[0])); + modep = pd_get_amode_data(port, TCPCI_MSG_SOP, + PD_VDO_VID(payload[0])); #endif switch (cmd) { #ifdef CONFIG_USB_PD_ALT_MODE_DFP case CMD_DISCOVER_IDENT: - /* Received a SOP' Discover Ident msg */ - if (sop == TCPC_TX_SOP_PRIME) { - rsize = process_am_discover_ident_sop_prime( - port, cnt, head, payload); /* Received a SOP Discover Ident Message */ - } else { - rsize = process_am_discover_ident_sop(port, - cnt, head, payload, rtype); - } -#ifdef CONFIG_CHARGE_MANAGER - if (pd_charge_from_device(pd_get_identity_vid(port), - pd_get_identity_pid(port))) - charge_manager_update_dualrole(port, - CAP_DEDICATED); -#endif + rsize = process_am_discover_ident_sop(port, cnt, head, + payload, rtype); break; case CMD_DISCOVER_SVID: rsize = process_am_discover_svids(port, cnt, payload, @@ -735,42 +324,23 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, break; case CMD_DISCOVER_MODES: dfp_consume_modes(port, sop, cnt, payload); - if (is_tbt_compat_enabled(port) && - is_tbt_compat_mode(port, cnt, payload)) { - rsize = process_tbt_compat_discover_modes( - port, sop, payload, rtype); - break; - } rsize = dfp_discover_modes(port, payload); /* enter the default mode for DFP */ if (!rsize) { - /* - * Disabling Thunderbolt-Compatible mode if - * discover mode response doesn't include Intel - * SVID. - */ - disable_tbt_compat_mode(port); - payload[0] = pd_dfp_enter_mode(port, - TCPC_TX_SOP, 0, 0); + payload[0] = pd_dfp_enter_mode( + port, TCPCI_MSG_SOP, 0, 0); if (payload[0]) rsize = 1; } break; case CMD_ENTER_MODE: - if (is_tbt_compat_enabled(port)) { - rsize = obj_cnt_enter_tbt_compat_mode(port, - sop, payload, rtype); - /* - * Continue with PD flow if Thunderbolt-compatible mode - * is disabled. - */ - } else if (!modep) { + if (!modep) { rsize = 0; } else { if (!modep->opos) - pd_dfp_enter_mode(port, TCPC_TX_SOP, 0, - 0); + pd_dfp_enter_mode(port, TCPCI_MSG_SOP, + 0, 0); if (modep->opos) { rsize = modep->fx->status(port, @@ -780,13 +350,31 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, } break; case CMD_DP_STATUS: - /* DP status response & UFP's DP attention have same - payload */ + /* + * Note: DP status response & UFP's DP attention have + * the same payload + */ dfp_consume_attention(port, payload); - if (modep && modep->opos) + + if (modep && modep->opos) { + /* + * Place the USB Type-C pins that are to be + * re-configured to DisplayPort Configuration + * into the Safe state. For USB_PD_MUX_DOCK, + * the superspeed signals can remain connected. + * For USB_PD_MUX_DP_ENABLED, disconnect the + * superspeed signals here, before the pins are + * re-configured to DisplayPort (in + * svdm_dp_post_config, when we receive the + * config ack). + */ + if (svdm_dp_get_mux_mode(port) == + USB_PD_MUX_DP_ENABLED) + usb_mux_set_safe_mode(port); rsize = modep->fx->config(port, payload); - else + } else { rsize = 0; + } break; case CMD_DP_CONFIG: if (modep && modep->opos && modep->fx->post_config) @@ -809,7 +397,8 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, } payload[0] |= VDO_CMDT(CMDT_INIT); - payload[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)); + payload[0] |= + VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)); #ifdef CONFIG_USB_PD_ALT_MODE_DFP } else if (cmd_type == CMDT_RSP_BUSY) { switch (cmd) { @@ -831,15 +420,7 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, rsize = 0; } } else if (cmd_type == CMDT_RSP_NAK) { - /* Passive cable Nacked for Discover SVID */ - if (cmd == CMD_DISCOVER_SVID && is_tbt_compat_enabled(port) && - sop == TCPC_TX_SOP_PRIME && - get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) { - limit_tbt_cable_speed(port); - rsize = dfp_discover_modes(port, payload); - } else { - rsize = 0; - } + rsize = 0; #endif /* CONFIG_USB_PD_ALT_MODE_DFP */ } else { CPRINTF("ERR:CMDT:%d\n", cmd); @@ -852,15 +433,16 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, #else int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, - uint32_t head, enum tcpm_transmit_type *rtype) + uint32_t head, enum tcpci_msg_type *rtype) { return 0; } #endif /* CONFIG_USB_PD_ALT_MODE */ -#define FW_RW_END (CONFIG_EC_WRITABLE_STORAGE_OFF + \ - CONFIG_RW_STORAGE_OFF + CONFIG_RW_SIZE) +#define FW_RW_END \ + (CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF + \ + CONFIG_RW_SIZE) uint8_t *flash_hash_rw(void) { @@ -870,8 +452,9 @@ uint8_t *flash_hash_rw(void) if (rw_flash_changed) { rw_flash_changed = 0; SHA256_init(&ctx); - SHA256_update(&ctx, (void *)CONFIG_PROGRAM_MEMORY_BASE + - CONFIG_RW_MEM_OFF, + SHA256_update(&ctx, + (void *)CONFIG_PROGRAM_MEMORY_BASE + + CONFIG_RW_MEM_OFF, CONFIG_RW_SIZE - RSANUMBYTES); return SHA256_final(&ctx); } else { @@ -922,21 +505,22 @@ int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload) if (system_get_image_copy() != EC_IMAGE_RO) break; pd_log_event(PD_EVENT_ACC_RW_ERASE, 0, 0, NULL); - flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF; - flash_physical_erase(CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF, CONFIG_RW_SIZE); + flash_offset = + CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF; + crec_flash_physical_erase(CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_STORAGE_OFF, + CONFIG_RW_SIZE); rw_flash_changed = 1; break; case VDO_CMD_FLASH_WRITE: /* do not kill the code under our feet */ if ((system_get_image_copy() != EC_IMAGE_RO) || - (flash_offset < CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF)) + (flash_offset < + CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF)) break; - flash_physical_write(flash_offset, 4*(cnt - 1), - (const char *)(payload+1)); - flash_offset += 4*(cnt - 1); + crec_flash_physical_write(flash_offset, 4 * (cnt - 1), + (const char *)(payload + 1)); + flash_offset += 4 * (cnt - 1); rw_flash_changed = 1; break; case VDO_CMD_ERASE_SIG: @@ -947,8 +531,8 @@ int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload) /* zeroes the area containing the RSA signature */ for (offset = FW_RW_END - RSANUMBYTES; offset < FW_RW_END; offset += 4) - flash_physical_write(offset, 4, - (const char *)&zero); + crec_flash_physical_write(offset, 4, + (const char *)&zero); } break; default: @@ -957,3 +541,736 @@ int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload) } return rsize; } + +#ifdef CONFIG_USB_PD_ALT_MODE_DFP +static enum ec_status hc_remote_pd_set_amode(struct host_cmd_handler_args *args) +{ + const struct ec_params_usb_pd_set_mode_request *p = args->params; + + if ((p->port >= board_get_usb_pd_port_count()) || (!p->svid) || + (!p->opos)) + return EC_RES_INVALID_PARAM; + + switch (p->cmd) { + case PD_EXIT_MODE: + if (pd_dfp_exit_mode(p->port, TCPCI_MSG_SOP, p->svid, p->opos)) + pd_send_vdm(p->port, p->svid, + CMD_EXIT_MODE | VDO_OPOS(p->opos), NULL, 0); + else { + CPRINTF("Failed exit mode\n"); + return EC_RES_ERROR; + } + break; + case PD_ENTER_MODE: + if (pd_dfp_enter_mode(p->port, TCPCI_MSG_SOP, p->svid, p->opos)) + pd_send_vdm(p->port, p->svid, + CMD_ENTER_MODE | VDO_OPOS(p->opos), NULL, + 0); + break; + default: + return EC_RES_INVALID_PARAM; + } + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_SET_AMODE, hc_remote_pd_set_amode, + EC_VER_MASK(0)); + +const uint32_t *pd_get_mode_vdo(int port, uint16_t svid_idx, + enum tcpci_msg_type type) +{ + const struct pd_discovery *disc = pd_get_am_discovery(port, type); + + return disc->svids[svid_idx].mode_vdo; +} + +static enum ec_status hc_remote_pd_get_amode(struct host_cmd_handler_args *args) +{ + struct svdm_amode_data *modep; + const struct ec_params_usb_pd_get_mode_request *p = args->params; + struct ec_params_usb_pd_get_mode_response *r = args->response; + + if (p->port >= board_get_usb_pd_port_count()) + return EC_RES_INVALID_PARAM; + + /* no more to send */ + /* TODO(b/148528713): Use TCPMv2's separate storage for SOP'. */ + if (p->svid_idx >= pd_get_svid_count(p->port, TCPCI_MSG_SOP)) { + r->svid = 0; + args->response_size = sizeof(r->svid); + return EC_RES_SUCCESS; + } + + r->svid = pd_get_svid(p->port, p->svid_idx, TCPCI_MSG_SOP); + r->opos = 0; + memcpy(r->vdo, pd_get_mode_vdo(p->port, p->svid_idx, TCPCI_MSG_SOP), + sizeof(uint32_t) * VDO_MAX_OBJECTS); + modep = pd_get_amode_data(p->port, TCPCI_MSG_SOP, r->svid); + + if (modep) + r->opos = pd_alt_mode(p->port, TCPCI_MSG_SOP, r->svid); + + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_GET_AMODE, hc_remote_pd_get_amode, + EC_VER_MASK(0)); + +static int pd_get_mode_idx(int port, enum tcpci_msg_type type, uint16_t svid) +{ + int amode_idx; + struct partner_active_modes *active = + pd_get_partner_active_modes(port, type); + + for (amode_idx = 0; amode_idx < PD_AMODE_COUNT; amode_idx++) { + if (active->amodes[amode_idx].fx && + (active->amodes[amode_idx].fx->svid == svid)) + return amode_idx; + } + return -1; +} + +static int pd_allocate_mode(int port, enum tcpci_msg_type type, uint16_t svid) +{ + int i, j; + struct svdm_amode_data *modep; + int mode_idx = pd_get_mode_idx(port, type, svid); + const struct pd_discovery *disc = pd_get_am_discovery(port, type); + struct partner_active_modes *active = + pd_get_partner_active_modes(port, type); + assert(active); + + if (mode_idx != -1) + return mode_idx; + + /* There's no space to enter another mode */ + if (active->amode_idx == PD_AMODE_COUNT) { + CPRINTF("ERR:NO AMODE SPACE\n"); + return -1; + } + + /* Allocate ... if SVID == 0 enter default supported policy */ + for (i = 0; i < supported_modes_cnt; i++) { + for (j = 0; j < disc->svid_cnt; j++) { + const struct svid_mode_data *svidp = &disc->svids[j]; + + /* + * Looking for a match between supported_modes and + * discovered SVIDs; must also match the passed-in SVID + * if that was non-zero. Otherwise, go to the next + * discovered SVID. + * TODO(b/155890173): Support AP-directed mode entry + * where the mode is unknown to the TCPM. + */ + if ((svidp->svid != supported_modes[i].svid) || + (svid && (svidp->svid != svid))) + continue; + + modep = &active->amodes[active->amode_idx]; + modep->fx = &supported_modes[i]; + modep->data = &disc->svids[j]; + active->amode_idx++; + return active->amode_idx - 1; + } + } + return -1; +} + +static int validate_mode_request(struct svdm_amode_data *modep, uint16_t svid, + int opos) +{ + if (!modep->fx) + return 0; + + if (svid != modep->fx->svid) { + CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n", svid, + modep->fx->svid); + return 0; + } + + if (opos != modep->opos) { + CPRINTF("ERR:opos r:%d != c:%d\n", opos, modep->opos); + return 0; + } + + return 1; +} + +void pd_prepare_sysjump(void) +{ + int i; + + /* Exit modes before sysjump so we can cleanly enter again later */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + /* + * If the port is not capable of Alternate mode no need to + * send the event. + */ + if (!pd_alt_mode_capable(i)) + continue; + + sysjump_task_waiting = task_get_current(); + task_set_event(PD_PORT_TO_TASK_ID(i), PD_EVENT_SYSJUMP); + task_wait_event_mask(TASK_EVENT_SYSJUMP_READY, -1); + sysjump_task_waiting = TASK_ID_INVALID; + } +} + +#ifdef CONFIG_USB_PD_DP_MODE +/* + * This algorithm defaults to choosing higher pin config over lower ones in + * order to prefer multi-function if desired. + * + * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG + * ------------------------------------------------------------- + * A | USB G2 | ? | no | 00_0001 + * B | USB G2 | ? | yes | 00_0010 + * C | DP | CONVERTED | no | 00_0100 + * D | PD | CONVERTED | yes | 00_1000 + * E | DP | DP | no | 01_0000 + * F | PD | DP | yes | 10_0000 + * + * if UFP has NOT asserted multi-function preferred code masks away B/D/F + * leaving only A/C/E. For single-output dongles that should leave only one + * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP + * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C + * receptacle must always choose C/D in those cases. + */ +int pd_dfp_dp_get_pin_mode(int port, uint32_t status) +{ + struct svdm_amode_data *modep = + pd_get_amode_data(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); + uint32_t mode_caps; + uint32_t pin_caps; + int mf_pref; + + /* + * Default dp_port_mf_allow is true, we allow mf operation + * if UFP_D supports it. + */ + + if (IS_ENABLED(CONFIG_CMD_MFALLOW)) + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]) && + dp_port_mf_allow[port]; + else + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); + + if (!modep) + return 0; + + mode_caps = modep->data->mode_vdo[modep->opos - 1]; + + /* TODO(crosbug.com/p/39656) revisit with DFP that can be a sink */ + pin_caps = PD_DP_PIN_CAPS(mode_caps); + + /* if don't want multi-function then ignore those pin configs */ + if (!mf_pref) + pin_caps &= ~MODE_DP_PIN_MF_MASK; + + /* TODO(crosbug.com/p/39656) revisit if DFP drives USB Gen 2 signals */ + pin_caps &= ~MODE_DP_PIN_BR2_MASK; + + /* if C/D present they have precedence over E/F for USB-C->USB-C */ + if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D)) + pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F); + + /* get_next_bit returns undefined for zero */ + if (!pin_caps) + return 0; + + return 1 << get_next_bit(&pin_caps); +} +#endif /* CONFIG_USB_PD_DP_MODE */ + +struct svdm_amode_data *pd_get_amode_data(int port, enum tcpci_msg_type type, + uint16_t svid) +{ + int idx = pd_get_mode_idx(port, type, svid); + struct partner_active_modes *active = + pd_get_partner_active_modes(port, type); + assert(active); + + return (idx == -1) ? NULL : &active->amodes[idx]; +} + +/* + * Enter default mode ( payload[0] == 0 ) or attempt to enter mode via svid & + * opos + */ +uint32_t pd_dfp_enter_mode(int port, enum tcpci_msg_type type, uint16_t svid, + int opos) +{ + int mode_idx = pd_allocate_mode(port, type, svid); + struct svdm_amode_data *modep; + uint32_t mode_caps; + + if (mode_idx == -1) + return 0; + modep = &pd_get_partner_active_modes(port, type)->amodes[mode_idx]; + + if (!opos) { + /* choose the lowest as default */ + modep->opos = 1; + } else if (opos <= modep->data->mode_cnt) { + modep->opos = opos; + } else { + CPRINTS("C%d: Invalid opos %d for SVID %x", port, opos, svid); + return 0; + } + + mode_caps = modep->data->mode_vdo[modep->opos - 1]; + if (modep->fx->enter(port, mode_caps) == -1) + return 0; + + /* + * Strictly speaking, this should only happen when the request + * has been ACKed. + * For TCPMV1, still set modal flag pre-emptively. For TCPMv2, the modal + * flag is set when the ENTER command is ACK'd for each alt mode that is + * supported. + */ + if (IS_ENABLED(CONFIG_USB_PD_TCPMV1)) + pd_set_dfp_enter_mode_flag(port, true); + + /* SVDM to send to UFP for mode entry */ + return VDO(modep->fx->svid, 1, CMD_ENTER_MODE | VDO_OPOS(modep->opos)); +} + +int pd_dfp_exit_mode(int port, enum tcpci_msg_type type, uint16_t svid, + int opos) +{ + struct svdm_amode_data *modep; + struct partner_active_modes *active = + pd_get_partner_active_modes(port, type); + int idx; + + /* + * Empty svid signals we should reset DFP VDM state by exiting all + * entered modes then clearing state. This occurs when we've + * disconnected or for hard reset. + */ + if (!svid) { + for (idx = 0; idx < PD_AMODE_COUNT; idx++) + if (active->amodes[idx].fx) + active->amodes[idx].fx->exit(port); + + pd_dfp_mode_init(port); + return 0; + } + + /* + * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple + * mode exit. Additionally it should honor OPOS == 7 as DFP's request + * to exit all modes. We currently don't have any UFPs that support + * multiple modes on one SVID. + */ + modep = pd_get_amode_data(port, type, svid); + if (!modep || !validate_mode_request(modep, svid, opos)) + return 0; + + /* call DFPs exit function */ + modep->fx->exit(port); + + pd_set_dfp_enter_mode_flag(port, false); + + /* exit the mode */ + modep->opos = 0; + return 1; +} + +void dfp_consume_attention(int port, uint32_t *payload) +{ + uint16_t svid = PD_VDO_VID(payload[0]); + int opos = PD_VDO_OPOS(payload[0]); + struct svdm_amode_data *modep = + pd_get_amode_data(port, TCPCI_MSG_SOP, svid); + + if (!modep || !validate_mode_request(modep, svid, opos)) + return; + + if (modep->fx->attention) + modep->fx->attention(port, payload); +} + +int pd_alt_mode(int port, enum tcpci_msg_type type, uint16_t svid) +{ + struct svdm_amode_data *modep = pd_get_amode_data(port, type, svid); + + return (modep) ? modep->opos : -1; +} + +void notify_sysjump_ready(void) +{ + /* + * If event was set from pd_prepare_sysjump, wake the + * task waiting on us to complete. + */ + if (sysjump_task_waiting != TASK_ID_INVALID) + task_set_event(sysjump_task_waiting, TASK_EVENT_SYSJUMP_READY); +} + +#ifdef CONFIG_USB_PD_DP_MODE +__overridable void svdm_safe_dp_mode(int port) +{ + /* make DP interface safe until configure */ + dp_flags[port] = 0; + dp_status[port] = 0; + + usb_mux_set_safe_mode(port); +} + +__overridable int svdm_enter_dp_mode(int port, uint32_t mode_caps) +{ + /* + * Don't enter the mode if the SoC is off. + * + * There's no need to enter the mode while the SoC is off; we'll + * actually enter the mode on the chipset resume hook. Entering DP Alt + * Mode twice will confuse some monitors and require and unplug/replug + * to get them to work again. The DP Alt Mode on USB-C spec says that + * if we don't need to maintain HPD connectivity info in a low power + * mode, then we shall exit DP Alt Mode. (This is why we don't enter + * when the SoC is off as opposed to suspend where adding a display + * could cause a wake up.) When in S5->S3 transition state, we + * should treat it as a SoC off state. + */ +#ifdef CONFIG_AP_POWER_CONTROL + if (!chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON)) + return -1; +#endif + + /* + * TCPMv2: Enable logging of CCD line state CCD_MODE_ODL. + * DisplayPort Alternate mode requires that the SBU lines are + * used for AUX communication. However, in Chromebooks SBU + * signals are repurposed as USB2 signals for CCD. This + * functionality is accomplished by override fets whose state is + * controlled by CCD_MODE_ODL. + * + * This condition helps in debugging unexpected AUX timeout + * issues by indicating the state of the CCD override fets. + */ +#ifdef GPIO_CCD_MODE_ODL + if (!gpio_get_level(GPIO_CCD_MODE_ODL)) + CPRINTS("WARNING: Tried to EnterMode DP with [CCD on AUX/SBU]"); +#endif + + /* Only enter mode if device is DFP_D capable */ + if (mode_caps & MODE_DP_SNK) { + svdm_safe_dp_mode(port); + + if (IS_ENABLED(CONFIG_MKBP_EVENT) && + chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + /* + * Wake the system up since we're entering DP AltMode. + */ + pd_notify_dp_alt_mode_entry(port); + + return 0; + } + + return -1; +} + +__overridable int svdm_dp_status(int port, uint32_t *payload) +{ + int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); + + payload[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_STATUS | VDO_OPOS(opos)); + payload[1] = VDO_DP_STATUS(0, /* HPD IRQ ... not applicable */ + 0, /* HPD level ... not applicable */ + 0, /* exit DP? ... no */ + 0, /* usb mode? ... no */ + 0, /* multi-function ... no */ + (!!(dp_flags[port] & DP_FLAGS_DP_ON)), + 0, /* power low? ... no */ + (!!DP_FLAGS_DP_ON)); + return 2; +}; + +__overridable uint8_t get_dp_pin_mode(int port) +{ + return pd_dfp_dp_get_pin_mode(port, dp_status[port]); +} + +mux_state_t svdm_dp_get_mux_mode(int port) +{ + int pin_mode = get_dp_pin_mode(port); + /* Default dp_port_mf_allow is true */ + int mf_pref; + + if (IS_ENABLED(CONFIG_CMD_MFALLOW)) + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]) && + dp_port_mf_allow[port]; + else + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); + + /* + * Multi-function operation is only allowed if that pin config is + * supported. + */ + if ((pin_mode & MODE_DP_PIN_MF_MASK) && mf_pref) + return USB_PD_MUX_DOCK; + else + return USB_PD_MUX_DP_ENABLED; +} + +/* Note: Assumes that pins have already been set in safe state if necessary */ +__overridable int svdm_dp_config(int port, uint32_t *payload) +{ + int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); + uint8_t pin_mode = get_dp_pin_mode(port); + mux_state_t mux_mode = svdm_dp_get_mux_mode(port); + /* Default dp_port_mf_allow is true */ + int mf_pref; + + if (IS_ENABLED(CONFIG_CMD_MFALLOW)) + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]) && + dp_port_mf_allow[port]; + else + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); + + if (!pin_mode) + return 0; + + CPRINTS("pin_mode: %x, mf: %d, mux: %d", pin_mode, mf_pref, mux_mode); + + payload[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); + payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ + 1, /* DPv1.3 signaling */ + 2); /* UFP connected */ + return 2; +}; + +#if defined(CONFIG_USB_PD_DP_HPD_GPIO) && \ + !defined(CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM) +void svdm_set_hpd_gpio(int port, int en) +{ + gpio_set_level(PORT_TO_HPD(port), en); +} + +int svdm_get_hpd_gpio(int port) +{ + return gpio_get_level(PORT_TO_HPD(port)); +} +#endif + +__overridable void svdm_dp_post_config(int port) +{ + mux_state_t mux_mode = svdm_dp_get_mux_mode(port); + /* Connect the SBU and USB lines to the connector. */ + typec_set_sbu(port, true); + + usb_mux_set(port, mux_mode, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); + + dp_flags[port] |= DP_FLAGS_DP_ON; + if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) + return; + +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + svdm_set_hpd_gpio(port, 1); + + /* set the minimum time delay (2ms) for the next HPD IRQ */ + svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + + usb_mux_hpd_update(port, + USB_PD_MUX_HPD_LVL | USB_PD_MUX_HPD_IRQ_DEASSERTED); + +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, 1); +#endif +} + +__overridable int svdm_dp_attention(int port, uint32_t *payload) +{ + int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); + int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + int cur_lvl = svdm_get_hpd_gpio(port); +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + mux_state_t mux_state; + + dp_status[port] = payload[1]; + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && (irq || lvl)) + /* + * Wake up the AP. IRQ or level high indicates a DP sink is now + * present. + */ + if (IS_ENABLED(CONFIG_MKBP_EVENT)) + pd_notify_dp_alt_mode_entry(port); + + /* Its initial DP status message prior to config */ + if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { + if (lvl) + dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; + return 1; + } + +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + if (irq && !lvl) { + /* + * IRQ can only be generated when the level is high, because + * the IRQ is signaled by a short low pulse from the high level. + */ + CPRINTF("ERR:HPD:IRQ&LOW\n"); + return 0; /* nak */ + } + + if (irq && cur_lvl) { + uint64_t now = get_time().val; + /* wait for the minimum spacing between IRQ_HPD if needed */ + if (now < svdm_hpd_deadline[port]) + usleep(svdm_hpd_deadline[port] - now); + + /* generate IRQ_HPD pulse */ + svdm_set_hpd_gpio(port, 0); + usleep(HPD_DSTREAM_DEBOUNCE_IRQ); + svdm_set_hpd_gpio(port, 1); + } else { + svdm_set_hpd_gpio(port, lvl); + } + + /* set the minimum time delay (2ms) for the next HPD IRQ */ + svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + + mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | + (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); + usb_mux_hpd_update(port, mux_state); + +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, lvl); +#endif + + /* ack */ + return 1; +} + +__overridable void svdm_exit_dp_mode(int port) +{ + dp_flags[port] = 0; + dp_status[port] = 0; +#ifdef CONFIG_USB_PD_DP_HPD_GPIO + svdm_set_hpd_gpio(port, 0); +#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, 0); +#endif +} +#endif /* CONFIG_USB_PD_DP_MODE */ + +__overridable int svdm_enter_gfu_mode(int port, uint32_t mode_caps) +{ + /* Always enter GFU mode */ + return 0; +} + +__overridable void svdm_exit_gfu_mode(int port) +{ +} + +__overridable int svdm_gfu_status(int port, uint32_t *payload) +{ + /* + * This is called after enter mode is successful, send unstructured + * VDM to read info. + */ + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_READ_INFO, NULL, 0); + return 0; +} + +__overridable int svdm_gfu_config(int port, uint32_t *payload) +{ + return 0; +} + +__overridable int svdm_gfu_attention(int port, uint32_t *payload) +{ + return 0; +} + +const struct svdm_amode_fx supported_modes[] = { +#ifdef CONFIG_USB_PD_DP_MODE + { + .svid = USB_SID_DISPLAYPORT, + .enter = &svdm_enter_dp_mode, + .status = &svdm_dp_status, + .config = &svdm_dp_config, + .post_config = &svdm_dp_post_config, + .attention = &svdm_dp_attention, + .exit = &svdm_exit_dp_mode, + }, +#endif /* CONFIG_USB_PD_DP_MODE */ + { + .svid = USB_VID_GOOGLE, + .enter = &svdm_enter_gfu_mode, + .status = &svdm_gfu_status, + .config = &svdm_gfu_config, + .attention = &svdm_gfu_attention, + .exit = &svdm_exit_gfu_mode, + }, +}; +const int supported_modes_cnt = ARRAY_SIZE(supported_modes); + +#if defined(CONFIG_CMD_MFALLOW) +static int command_mfallow(int argc, const char **argv) +{ + char *e; + int port; + + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + + port = strtoi(argv[1], &e, 10); + if (*e || port >= board_get_usb_pd_port_count()) + return EC_ERROR_PARAM1; + + if (!strcasecmp(argv[2], "true")) + dp_port_mf_allow[port] = true; + else if (!strcasecmp(argv[2], "false")) + dp_port_mf_allow[port] = false; + else + return EC_ERROR_PARAM2; + + ccprintf("Port: %d multi function allowed is %s ", port, argv[2]); + return EC_SUCCESS; +} + +DECLARE_CONSOLE_COMMAND(mfallow, command_mfallow, "port [true | false]", + "Controls Multifunction choice during DP Altmode."); +#endif /* CONFIG_CMD_MFALLOW */ + +#ifdef CONFIG_COMMON_RUNTIME +static enum ec_status hc_remote_pd_dev_info(struct host_cmd_handler_args *args) +{ + const struct ec_params_usb_pd_info_request *p = args->params; + struct ec_params_usb_pd_rw_hash_entry *r = args->response; + uint16_t dev_id; + uint32_t current_image; + + if (p->port >= board_get_usb_pd_port_count()) + return EC_RES_INVALID_PARAM; + + pd_dev_get_rw_hash(p->port, &dev_id, r->dev_rw_hash, ¤t_image); + + r->dev_id = dev_id; + r->current_image = current_image; + + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DEV_INFO, hc_remote_pd_dev_info, + EC_VER_MASK(0)); +#endif /* CONFIG_COMMON_RUNTIME */ + +#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 1fe963f1fc..9179e53be3 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,11 +7,13 @@ #include "battery.h" #include "battery_smart.h" #include "board.h" +#include "builtin/assert.h" #include "charge_manager.h" #include "charge_state.h" #include "chipset.h" #include "common.h" #include "console.h" +#include "cros_version.h" #include "ec_commands.h" #include "gpio.h" #include "hooks.h" @@ -20,42 +22,36 @@ #include "registers.h" #include "system.h" #include "task.h" -#include "tcpci.h" -#include "tcpm.h" +#include "tcpm/tcpci.h" +#include "tcpm/tcpm.h" #include "timer.h" -#include "util.h" +#include "typec_control.h" #include "usb_charge.h" #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" -#include "usb_pd_tcpm.h" +#include "usb_pd_flags.h" #include "usb_pd_tcpc.h" +#include "usb_pd_tcpm.h" +#include "usbc_ocp.h" #include "usbc_ppc.h" -#include "version.h" +#include "util.h" #include "vboot.h" /* Flags to clear on a disconnect */ -#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \ - PD_FLAGS_PARTNER_DR_DATA | \ - PD_FLAGS_CHECK_IDENTITY | \ - PD_FLAGS_SNK_CAP_RECVD | \ - PD_FLAGS_TCPC_DRP_TOGGLE | \ - PD_FLAGS_EXPLICIT_CONTRACT | \ - PD_FLAGS_PREVIOUS_PD_CONN | \ - PD_FLAGS_CHECK_PR_ROLE | \ - PD_FLAGS_CHECK_DR_ROLE | \ - PD_FLAGS_PARTNER_UNCONSTR | \ - PD_FLAGS_VCONN_ON | \ - PD_FLAGS_TRY_SRC | \ - PD_FLAGS_PARTNER_USB_COMM | \ - PD_FLAGS_UPDATE_SRC_CAPS | \ - PD_FLAGS_TS_DTS_PARTNER | \ - PD_FLAGS_SNK_WAITING_BATT | \ - PD_FLAGS_CHECK_VCONN_STATE) +#define PD_FLAGS_RESET_ON_DISCONNECT_MASK \ + (PD_FLAGS_PARTNER_DR_POWER | PD_FLAGS_PARTNER_DR_DATA | \ + PD_FLAGS_CHECK_IDENTITY | PD_FLAGS_SNK_CAP_RECVD | \ + PD_FLAGS_TCPC_DRP_TOGGLE | PD_FLAGS_EXPLICIT_CONTRACT | \ + PD_FLAGS_PREVIOUS_PD_CONN | PD_FLAGS_CHECK_PR_ROLE | \ + PD_FLAGS_CHECK_DR_ROLE | PD_FLAGS_PARTNER_UNCONSTR | \ + PD_FLAGS_VCONN_ON | PD_FLAGS_TRY_SRC | PD_FLAGS_PARTNER_USB_COMM | \ + PD_FLAGS_UPDATE_SRC_CAPS | PD_FLAGS_TS_DTS_PARTNER | \ + PD_FLAGS_SNK_WAITING_BATT | PD_FLAGS_CHECK_VCONN_STATE) #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) static int tcpc_prints(const char *string, int port) { @@ -102,11 +98,11 @@ static const int debug_level; #define DUAL_ROLE_IF_ELSE(port, sink_clause, src_clause) (src_clause) #endif -#define READY_RETURN_STATE(port) DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_READY, \ - PD_STATE_SRC_READY) +#define READY_RETURN_STATE(port) \ + DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_READY, PD_STATE_SRC_READY) /* Type C supply voltage (mV) */ -#define TYPE_C_VOLTAGE 5000 /* mV */ +#define TYPE_C_VOLTAGE 5000 /* mV */ /* PD counter definitions */ #define PD_MESSAGE_ID_COUNT 7 @@ -150,8 +146,9 @@ enum vdm_states { #ifdef CONFIG_USB_PD_DUAL_ROLE /* Port dual-role state */ enum pd_dual_role_states drp_state[CONFIG_USB_PD_PORT_MAX_COUNT] = { - [0 ... (CONFIG_USB_PD_PORT_MAX_COUNT - 1)] = - CONFIG_USB_PD_INITIAL_DRP_STATE}; + [0 ...(CONFIG_USB_PD_PORT_MAX_COUNT - 1)] = + CONFIG_USB_PD_INITIAL_DRP_STATE +}; /* Enable variable for Try.SRC states */ static bool pd_try_src_enable; @@ -180,8 +177,7 @@ static bool pd_try_src_enable; * Rev 1 (VDO 1.0) - return VDM_VER10 * Rev 2 (VDO 2.0) - return VDM_VER20 */ -static const uint8_t vdo_ver[] = { - VDM_VER10, VDM_VER10, VDM_VER20}; +static const uint8_t vdo_ver[] = { VDM_VER10, VDM_VER10, VDM_VER20 }; #define VDO_VER(v) vdo_ver[v] #else #define VDO_VER(v) VDM_VER10 @@ -241,9 +237,9 @@ static struct pd_protocol { /* Time to debounce exit low power mode */ uint64_t low_power_exit_time; /* Tasks to notify after TCPC has been reset */ - int tasks_waiting_on_reset; + atomic_t tasks_waiting_on_reset; /* Tasks preventing TCPC from entering low power mode */ - int tasks_preventing_lpm; + atomic_t tasks_preventing_lpm; #endif #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE @@ -267,14 +263,14 @@ static struct pd_protocol { /* next Vendor Defined Message to send */ uint32_t vdo_data[VDO_MAX_SIZE]; /* type of transmit message (SOP/SOP'/SOP'') */ - enum tcpm_transmit_type xmit_type; + enum tcpci_msg_type xmit_type; uint8_t vdo_count; /* VDO to retry if UFP responder replied busy. */ uint32_t vdo_retry; /* Attached ChromeOS device id, RW hash, and current RO / RW image */ uint16_t dev_id; - uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4]; + uint32_t dev_rw_hash[PD_RW_HASH_SIZE / 4]; enum ec_image current_image; #ifdef CONFIG_USB_PD_REV30 /* protocol revision */ @@ -295,24 +291,46 @@ static struct pd_protocol { } pd[CONFIG_USB_PD_PORT_MAX_COUNT]; #ifdef CONFIG_USB_PD_TCPMV1_DEBUG -static const char * const pd_state_names[] = { - "DISABLED", "SUSPENDED", - "SNK_DISCONNECTED", "SNK_DISCONNECTED_DEBOUNCE", +static const char *const pd_state_names[] = { + "DISABLED", + "SUSPENDED", + "SNK_DISCONNECTED", + "SNK_DISCONNECTED_DEBOUNCE", "SNK_HARD_RESET_RECOVER", - "SNK_DISCOVERY", "SNK_REQUESTED", "SNK_TRANSITION", "SNK_READY", - "SNK_SWAP_INIT", "SNK_SWAP_SNK_DISABLE", - "SNK_SWAP_SRC_DISABLE", "SNK_SWAP_STANDBY", "SNK_SWAP_COMPLETE", - "SRC_DISCONNECTED", "SRC_DISCONNECTED_DEBOUNCE", - "SRC_HARD_RESET_RECOVER", "SRC_STARTUP", - "SRC_DISCOVERY", "SRC_NEGOCIATE", "SRC_ACCEPTED", "SRC_POWERED", - "SRC_TRANSITION", "SRC_READY", "SRC_GET_SNK_CAP", "DR_SWAP", - "SRC_SWAP_INIT", "SRC_SWAP_SNK_DISABLE", "SRC_SWAP_SRC_DISABLE", + "SNK_DISCOVERY", + "SNK_REQUESTED", + "SNK_TRANSITION", + "SNK_READY", + "SNK_SWAP_INIT", + "SNK_SWAP_SNK_DISABLE", + "SNK_SWAP_SRC_DISABLE", + "SNK_SWAP_STANDBY", + "SNK_SWAP_COMPLETE", + "SRC_DISCONNECTED", + "SRC_DISCONNECTED_DEBOUNCE", + "SRC_HARD_RESET_RECOVER", + "SRC_STARTUP", + "SRC_DISCOVERY", + "SRC_NEGOCIATE", + "SRC_ACCEPTED", + "SRC_POWERED", + "SRC_TRANSITION", + "SRC_READY", + "SRC_GET_SNK_CAP", + "DR_SWAP", + "SRC_SWAP_INIT", + "SRC_SWAP_SNK_DISABLE", + "SRC_SWAP_SRC_DISABLE", "SRC_SWAP_STANDBY", - "VCONN_SWAP_SEND", "VCONN_SWAP_INIT", "VCONN_SWAP_READY", - "SOFT_RESET", "HARD_RESET_SEND", "HARD_RESET_EXECUTE", "BIST_RX", + "VCONN_SWAP_SEND", + "VCONN_SWAP_INIT", + "VCONN_SWAP_READY", + "SOFT_RESET", + "HARD_RESET_SEND", + "HARD_RESET_EXECUTE", + "BIST_RX", "BIST_TX", "DRP_AUTO_TOGGLE", - "ENTER_USB", }; BUILD_ASSERT(ARRAY_SIZE(pd_state_names) == PD_STATE_COUNT); #endif @@ -333,38 +351,31 @@ bool pd_alt_mode_capable(int port) * the port is not suspended. */ return pd_comm_is_enabled(port) && - !(pd[port].task_state == PD_STATE_SUSPENDED); + !(pd[port].task_state == PD_STATE_SUSPENDED); } -static inline void set_state_timeout(int port, - uint64_t timeout, +static inline void set_state_timeout(int port, uint64_t timeout, enum pd_states timeout_state) { pd[port].timeout = timeout; pd[port].timeout_state = timeout_state; } -int pd_get_rev(int port, enum tcpm_transmit_type type) +int pd_get_rev(int port, enum tcpci_msg_type type) { #ifdef CONFIG_USB_PD_REV30 /* TCPMv1 Only stores PD revision for SOP and SOP' types */ ASSERT(type < NUM_SOP_STAR_TYPES - 1); - if (type == TCPC_TX_SOP_PRIME) - return get_usb_pd_cable_revision(port); - return pd[port].rev; #else return PD_REV20; #endif } -int pd_get_vdo_ver(int port, enum tcpm_transmit_type type) +int pd_get_vdo_ver(int port, enum tcpci_msg_type type) { #ifdef CONFIG_USB_PD_REV30 - if (type == TCPC_TX_SOP_PRIME) - return vdo_ver[get_usb_pd_cable_revision(port)]; - return vdo_ver[pd[port].rev]; #else return VDM_VER10; @@ -382,22 +393,16 @@ int pd_is_connected(int port) return 0; #endif - return DUAL_ROLE_IF_ELSE(port, + return DUAL_ROLE_IF_ELSE( + port, /* sink */ pd[port].task_state != PD_STATE_SNK_DISCONNECTED && - pd[port].task_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE, + pd[port].task_state != + PD_STATE_SNK_DISCONNECTED_DEBOUNCE, /* source */ pd[port].task_state != PD_STATE_SRC_DISCONNECTED && - pd[port].task_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE); -} - -/* - * Return true if partner port is a DTS or TS capable of entering debug - * mode (eg. is presenting Rp/Rp or Rd/Rd). - */ -int pd_ts_dts_plugged(int port) -{ - return pd[port].flags & PD_FLAGS_TS_DTS_PARTNER; + pd[port].task_state != + PD_STATE_SRC_DISCONNECTED_DEBOUNCE); } /* Return true if partner port is known to be PD capable. */ @@ -406,6 +411,15 @@ bool pd_capable(int port) return !!(pd[port].flags & PD_FLAGS_PREVIOUS_PD_CONN); } +/* + * For TCPMv1, this routine always returns false so that the USB3 signals + * are connected without delay when the initial connection is UFP. + */ +bool pd_waiting_on_partner_src_caps(int port) +{ + return false; +} + /* * Return true if partner port is capable of communication over USB data * lines. @@ -422,7 +436,6 @@ void pd_vbus_low(int port) } #endif - #ifdef CONFIG_USBC_VCONN static void set_vconn(int port, int enable) { @@ -434,11 +447,17 @@ static void set_vconn(int port, int enable) ppc_set_vconn(port, 0); /* - * We always need to tell the TCPC to enable Vconn first, otherwise some - * TCPCs get confused when a PPC sets secondary CC line to 5V and TCPC - * immediately disconnect. If there is a PPC, both devices will - * potentially source Vconn, but that should be okay since Vconn has - * "make before break" electrical requirements when swapping anyway. + * Some TCPCs/PPC combinations can trigger OVP if the TCPC doesn't + * source VCONN. This happens if the TCPC will trip OVP with 5V, and the + * PPC doesn't isolate the TCPC from VCONN when sourcing. But, some PPCs + * which do isolate the TCPC can't handle 5V on its host-side CC pins, + * so the TCPC shouldn't source VCONN in those cases. + * + * In the first case, both TCPC and PPC will potentially source Vconn, + * but that should be okay since Vconn has "make before break" + * electrical requirements when swapping anyway. + * + * See b/72961003 and b/180973460 */ tcpm_set_vconn(port, enable); @@ -476,12 +495,12 @@ static void handle_device_access(int port) pd[port].low_power_time = get_time().val + PD_LPM_DEBOUNCE_US; if (pd[port].flags & PD_FLAGS_LPM_ENGAGED) { tcpc_prints("Exit Low Power Mode", port); - pd[port].flags &= ~(PD_FLAGS_LPM_ENGAGED | - PD_FLAGS_LPM_REQUESTED); + pd[port].flags &= + ~(PD_FLAGS_LPM_ENGAGED | PD_FLAGS_LPM_REQUESTED); pd[port].flags |= PD_FLAGS_LPM_EXIT; - pd[port].low_power_exit_time = get_time().val - + PD_LPM_EXIT_DEBOUNCE_US; + pd[port].low_power_exit_time = + get_time().val + PD_LPM_EXIT_DEBOUNCE_US; /* * Wake to ensure we make another pass through the main task * loop after clearing the flags. @@ -531,11 +550,10 @@ static int reset_device_and_notify(int port) * waking the TCPC, but it has also set PD_EVENT_TCPC_RESET again, which * would result in a second, unnecessary init. */ - deprecated_atomic_clear_bits(task_get_event_bitmap(task_get_current()), - PD_EVENT_TCPC_RESET); + atomic_clear_bits(task_get_event_bitmap(task_get_current()), + PD_EVENT_TCPC_RESET); - waiting_tasks = - deprecated_atomic_read_clear(&pd[port].tasks_waiting_on_reset); + waiting_tasks = atomic_clear(&pd[port].tasks_waiting_on_reset); /* * Now that we are done waking up the device, handle device access @@ -550,7 +568,7 @@ static int reset_device_and_notify(int port) while (waiting_tasks) { task = __fls(waiting_tasks); waiting_tasks &= ~BIT(task); - task_set_event(task, TASK_EVENT_PD_AWAKE, 0); + task_set_event(task, TASK_EVENT_PD_AWAKE); } return rv; @@ -563,8 +581,8 @@ static void pd_wait_for_wakeup(int port) reset_device_and_notify(port); } else { /* Otherwise, we need to wait for the TCPC reset to complete */ - deprecated_atomic_or(&pd[port].tasks_waiting_on_reset, - 1 << task_get_current()); + atomic_or(&pd[port].tasks_waiting_on_reset, + 1 << task_get_current()); /* * NOTE: We could be sending the PD task the reset event while * it is already processing the reset event. If that occurs, @@ -573,8 +591,7 @@ static void pd_wait_for_wakeup(int port) * happen much, but it if starts occurring, we can add a guard * to prevent/reduce it. */ - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_TCPC_RESET, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TCPC_RESET); task_wait_event_mask(TASK_EVENT_PD_AWAKE, -1); } } @@ -599,7 +616,7 @@ void pd_device_accessed(int port) handle_device_access(port); } else { task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_DEVICE_ACCESSED, 0); + PD_EVENT_DEVICE_ACCESSED); } } @@ -608,11 +625,10 @@ void pd_prevent_low_power_mode(int port, int prevent) const int current_task_mask = (1 << task_get_current()); if (prevent) - deprecated_atomic_or(&pd[port].tasks_preventing_lpm, - current_task_mask); + atomic_or(&pd[port].tasks_preventing_lpm, current_task_mask); else - deprecated_atomic_clear_bits(&pd[port].tasks_preventing_lpm, - current_task_mask); + atomic_clear_bits(&pd[port].tasks_preventing_lpm, + current_task_mask); } /* This is only called from the PD tasks that owns the port. */ @@ -669,28 +685,18 @@ static bool consume_sop_repeat_message(int port, uint8_t msg_id) * @param port USB PD TCPC port number * @param msg_header Message Header containing the RX message ID * @return True if the received message is a duplicate one, False otherwise. - * - * From USB PD version 1.3 section 6.7.1, the port which communicates - * using SOP* Packets Shall maintain copies of the last MessageID for - * each type of SOP* it uses. */ static bool consume_repeat_message(int port, uint32_t msg_header) { uint8_t msg_id = PD_HEADER_ID(msg_header); - enum tcpm_transmit_type sop = PD_HEADER_GET_SOP(msg_header); /* If repeat message ignore, except softreset control request. */ if (PD_HEADER_TYPE(msg_header) == PD_CTRL_SOFT_RESET && PD_HEADER_CNT(msg_header) == 0) { return false; - } else if (sop == TCPC_TX_SOP_PRIME) { - return consume_sop_prime_repeat_msg(port, msg_id); - } else if (sop == TCPC_TX_SOP_PRIME_PRIME) { - return consume_sop_prime_prime_repeat_msg(port, msg_id); } else { return consume_sop_repeat_message(port, msg_id); } - } /** @@ -718,14 +724,18 @@ static inline void set_state(int port, enum pd_states next_state) #if defined(CONFIG_USBC_PPC) && defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) /* If we're entering DRP_AUTO_TOGGLE, there is no sink connected. */ if (next_state == PD_STATE_DRP_AUTO_TOGGLE) { - ppc_sink_is_connected(port, 0); - /* - * Clear the overcurrent event counter - * since we've detected a disconnect. - */ - ppc_clear_oc_event_counter(port); + ppc_dev_is_connected(port, PPC_DEV_DISCONNECTED); /* Disable Auto Discharge Disconnect */ tcpm_enable_auto_discharge_disconnect(port, 0); + + if (IS_ENABLED(CONFIG_USBC_OCP)) { + usbc_ocp_snk_is_connected(port, false); + /* + * Clear the overcurrent event counter + * since we've detected a disconnect. + */ + usbc_ocp_clear_event_counter(port); + } } #endif /* CONFIG_USBC_PPC && CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE */ @@ -754,17 +764,22 @@ static inline void set_state(int port, enum pd_states next_state) tcpm_get_cc(port, &cc1, &cc2); /* * Neither a debug accessory nor UFP attached. - * Tell the PPC module that there is no sink connected. + * Tell the PPC module that there is no device connected. */ if (!cc_is_at_least_one_rd(cc1, cc2)) { - ppc_sink_is_connected(port, 0); - /* - * Clear the overcurrent event counter - * since we've detected a disconnect. - */ - ppc_clear_oc_event_counter(port); + ppc_dev_is_connected(port, PPC_DEV_DISCONNECTED); + + if (IS_ENABLED(CONFIG_USBC_OCP)) { + usbc_ocp_snk_is_connected(port, false); + /* + * Clear the overcurrent event counter + * since we've detected a disconnect. + */ + usbc_ocp_clear_event_counter(port); + } } #endif /* CONFIG_USBC_PPC */ + /* Clear the holdoff timer since the port is disconnected. */ pd[port].ready_state_holdoff_timer = 0; @@ -776,15 +791,13 @@ static inline void set_state(int port, enum pd_states next_state) if (last_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE && last_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE) { pd[port].flags &= ~PD_FLAGS_RESET_ON_DISCONNECT_MASK; - reset_pd_cable(port); } /* Clear the input current limit */ pd_set_input_current_limit(port, 0, 0); #ifdef CONFIG_CHARGE_MANAGER typec_set_input_current_limit(port, 0, 0); - charge_manager_set_ceil(port, - CEIL_REQUESTOR_PD, + charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, CHARGE_CEIL_NONE); #endif #ifdef CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER @@ -793,8 +806,7 @@ static inline void set_state(int port, enum pd_states next_state) * detach events are used to notify BC1.2 that it can be powered * down. */ - task_set_event(USB_CHG_PORT_TO_TASK_ID(port), - USB_CHG_EVENT_CC_OPEN, 0); + usb_charger_task_set_event(port, USB_CHG_EVENT_CC_OPEN); #endif /* CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER */ #ifdef CONFIG_USBC_VCONN set_vconn(port, 0); @@ -822,7 +834,8 @@ static inline void set_state(int port, enum pd_states next_state) charge_manager_update_dualrole(port, CAP_UNKNOWN); #endif #ifdef CONFIG_USB_PD_ALT_MODE_DFP - pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); + if (pd_dfp_exit_mode(port, TCPCI_MSG_SOP, 0, 0)) + usb_mux_set_safe_mode(port); #endif /* * Indicate that the port is disconnected by setting role to @@ -853,7 +866,7 @@ static inline void set_state(int port, enum pd_states next_state) /* Upon entering SRC_READY, it is safe for the sink to transmit */ if (next_state == PD_STATE_SRC_READY) { if (pd[port].rev == PD_REV30 && - pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT) + pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT) sink_can_xmit(port, SINK_TX_OK); } #endif @@ -873,7 +886,7 @@ static inline void set_state(int port, enum pd_states next_state) #ifdef CONFIG_USB_PD_TCPMV1_DEBUG if (debug_level > 0) CPRINTF("C%d st%d %s\n", port, next_state, - pd_state_names[next_state]); + pd_state_names[next_state]); else #endif CPRINTF("C%d st%d\n", port, next_state); @@ -891,11 +904,11 @@ void pd_transmit_complete(int port, int status) inc_id(port); pd[port].tx_status = status; - task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX); } -static int pd_transmit(int port, enum tcpm_transmit_type type, - uint16_t header, const uint32_t *data, enum ams_seq ams) +static int pd_transmit(int port, enum tcpci_msg_type type, uint16_t header, + const uint32_t *data, enum ams_seq ams) { int evt; int res; @@ -907,9 +920,9 @@ static int pd_transmit(int port, enum tcpm_transmit_type type, if (!pd_comm_is_enabled(port)) return -1; - /* Don't try to transmit anything until we have processed - * all RX messages. - */ + /* Don't try to transmit anything until we have processed + * all RX messages. + */ if (tcpm_has_pending_message(port)) return -1; @@ -936,7 +949,7 @@ static int pd_transmit(int port, enum tcpm_transmit_type type, * Note: a Sink can still send Hard Reset signaling at any time. */ if ((pd[port].rev == PD_REV30) && ams == AMS_START && - (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)) { + (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)) { if (pd[port].power_role == PD_ROLE_SOURCE) { /* * Inform Sink that it can't transmit. If a sink @@ -947,12 +960,12 @@ static int pd_transmit(int port, enum tcpm_transmit_type type, */ sink_can_xmit(port, SINK_TX_NG); sink_ng = 1; - } else if (type != TCPC_TX_HARD_RESET) { + } else if (type != TCPCI_MSG_TX_HARD_RESET) { enum tcpc_cc_voltage_status cc1, cc2; tcpm_get_cc(port, &cc1, &cc2); if (cc1 == TYPEC_CC_VOLT_RP_1_5 || - cc2 == TYPEC_CC_VOLT_RP_1_5) { + cc2 == TYPEC_CC_VOLT_RP_1_5) { /* Sink can't transmit now. */ /* Return failure, pd_task can retry later */ return -1; @@ -989,17 +1002,17 @@ static int send_control(int port, int type) { int bit_len; uint16_t header = PD_HEADER(type, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 0, - pd_get_rev(port, TCPC_TX_SOP), 0); + pd[port].data_role, pd[port].msg_id, 0, + pd_get_rev(port, TCPCI_MSG_SOP), 0); /* * For PD 3.0, collision avoidance logic needs to know if this message * will begin a new Atomic Message Sequence (AMS) */ - enum ams_seq ams = ((1 << type) & PD_CTRL_AMS_START_MASK) - ? AMS_START : AMS_RESPONSE; + enum ams_seq ams = ((1 << type) & PD_CTRL_AMS_START_MASK) ? + AMS_START : + AMS_RESPONSE; - - bit_len = pd_transmit(port, TCPC_TX_SOP, header, NULL, ams); + bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, NULL, ams); if (debug_level >= 2) CPRINTF("C%d CTRL[%d]>%d\n", port, type, bit_len); @@ -1015,7 +1028,7 @@ static int send_source_cap(int port, enum ams_seq ams) { int bit_len; #if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ - defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) + defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) const uint32_t *src_pdo; const int src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); #else @@ -1027,14 +1040,15 @@ static int send_source_cap(int port, enum ams_seq ams) if (src_pdo_cnt == 0) /* No source capabilities defined, sink only */ header = PD_HEADER(PD_CTRL_REJECT, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 0, - pd_get_rev(port, TCPC_TX_SOP), 0); + pd[port].data_role, pd[port].msg_id, 0, + pd_get_rev(port, TCPCI_MSG_SOP), 0); else header = PD_HEADER(PD_DATA_SOURCE_CAP, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, src_pdo_cnt, - pd_get_rev(port, TCPC_TX_SOP), 0); + pd[port].data_role, pd[port].msg_id, + src_pdo_cnt, pd_get_rev(port, TCPCI_MSG_SOP), + 0); - bit_len = pd_transmit(port, TCPC_TX_SOP, header, src_pdo, ams); + bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, src_pdo, ams); if (debug_level >= 2) CPRINTF("C%d srcCAP>%d\n", port, bit_len); @@ -1045,21 +1059,19 @@ static int send_source_cap(int port, enum ams_seq ams) static int send_battery_cap(int port, uint32_t *payload) { int bit_len; - uint16_t msg[6] = {0, 0, 0, 0, 0, 0}; - uint16_t header = PD_HEADER(PD_EXT_BATTERY_CAP, - pd[port].power_role, - pd[port].data_role, - pd[port].msg_id, + uint16_t msg[6] = { 0, 0, 0, 0, 0, 0 }; + uint16_t header = PD_HEADER(PD_EXT_BATTERY_CAP, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, 3, /* Number of Data Objects */ - pd[port].rev, - 1 /* This is an exteded message */ - ); + pd[port].rev, 1 /* This is an exteded + message */ + ); /* Set extended header */ msg[0] = PD_EXT_HEADER(0, /* Chunk Number */ 0, /* Request Chunk */ - 9 /* Data Size in bytes */ - ); + 9 /* Data Size in bytes */ + ); /* Set VID */ msg[1] = USB_VID_GOOGLE; @@ -1106,7 +1118,7 @@ static int send_battery_cap(int port, uint32_t *payload) * 10th of a Wh = Wh * 10 */ msg[3] = DIV_ROUND_NEAREST((c * v), - 100000); + 100000); } if (battery_full_charge_capacity(&c) == 0) { @@ -1115,31 +1127,29 @@ static int send_battery_cap(int port, uint32_t *payload) * 10th of a Wh = Wh * 10 */ msg[4] = DIV_ROUND_NEAREST((c * v), - 100000); + 100000); } } } } - bit_len = pd_transmit(port, TCPC_TX_SOP, header, (uint32_t *)msg, + bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, (uint32_t *)msg, AMS_RESPONSE); if (debug_level >= 2) CPRINTF("C%d batCap>%d\n", port, bit_len); return bit_len; } -static int send_battery_status(int port, uint32_t *payload) +static int send_battery_status(int port, uint32_t *payload) { int bit_len; uint32_t msg = 0; - uint16_t header = PD_HEADER(PD_DATA_BATTERY_STATUS, - pd[port].power_role, - pd[port].data_role, - pd[port].msg_id, + uint16_t header = PD_HEADER(PD_DATA_BATTERY_STATUS, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, 1, /* Number of Data Objects */ - pd[port].rev, - 0 /* This is NOT an extended message */ - ); + pd[port].rev, 0 /* This is NOT an extended + message */ + ); if (battery_is_present()) { /* @@ -1154,15 +1164,15 @@ static int send_battery_status(int port, uint32_t *payload) uint32_t c; if (battery_design_voltage(&v) != 0 || - battery_remaining_capacity(&c) != 0) { + battery_remaining_capacity(&c) != 0) { msg |= BSDO_CAP(BSDO_CAP_UNKNOWN); } else { /* * Wh = (c * v) / 1000000 * 10th of a Wh = Wh * 10 */ - msg |= BSDO_CAP(DIV_ROUND_NEAREST((c * v), - 100000)); + msg |= BSDO_CAP( + DIV_ROUND_NEAREST((c * v), 100000)); } /* Battery is present */ @@ -1189,7 +1199,7 @@ static int send_battery_status(int port, uint32_t *payload) msg = BSDO_CAP(BSDO_CAP_UNKNOWN); } - bit_len = pd_transmit(port, TCPC_TX_SOP, header, &msg, AMS_RESPONSE); + bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, &msg, AMS_RESPONSE); if (debug_level >= 2) CPRINTF("C%d batStat>%d\n", port, bit_len); @@ -1202,10 +1212,11 @@ static void send_sink_cap(int port) { int bit_len; uint16_t header = PD_HEADER(PD_DATA_SINK_CAP, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, pd_snk_pdo_cnt, - pd_get_rev(port, TCPC_TX_SOP), 0); + pd[port].data_role, pd[port].msg_id, + pd_snk_pdo_cnt, + pd_get_rev(port, TCPCI_MSG_SOP), 0); - bit_len = pd_transmit(port, TCPC_TX_SOP, header, pd_snk_pdo, + bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, pd_snk_pdo, AMS_RESPONSE); if (debug_level >= 2) CPRINTF("C%d snkCAP>%d\n", port, bit_len); @@ -1215,11 +1226,11 @@ static int send_request(int port, uint32_t rdo) { int bit_len; uint16_t header = PD_HEADER(PD_DATA_REQUEST, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 1, - pd_get_rev(port, TCPC_TX_SOP), 0); + pd[port].data_role, pd[port].msg_id, 1, + pd_get_rev(port, TCPCI_MSG_SOP), 0); /* Note: ams will need to be AMS_START if used for PPS keep alive */ - bit_len = pd_transmit(port, TCPC_TX_SOP, header, &rdo, AMS_RESPONSE); + bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, &rdo, AMS_RESPONSE); if (debug_level >= 2) CPRINTF("C%d REQ>%d\n", port, bit_len); @@ -1235,10 +1246,10 @@ static int send_bist_cmd(int port) uint32_t bdo = BDO(BDO_MODE_CARRIER2, 0); int bit_len; uint16_t header = PD_HEADER(PD_DATA_BIST, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, 1, - pd_get_rev(port, TCPC_TX_SOP), 0); + pd[port].data_role, pd[port].msg_id, 1, + pd_get_rev(port, TCPCI_MSG_SOP), 0); - bit_len = pd_transmit(port, TCPC_TX_SOP, header, &bdo, AMS_START); + bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, &bdo, AMS_START); CPRINTF("C%d BIST>%d\n", port, bit_len); return bit_len; @@ -1246,32 +1257,97 @@ static int send_bist_cmd(int port) #endif static void queue_vdm(int port, uint32_t *header, const uint32_t *data, - int data_cnt, enum tcpm_transmit_type type) + int data_cnt, enum tcpci_msg_type type) { pd[port].vdo_count = data_cnt + 1; pd[port].vdo_data[0] = header[0]; pd[port].xmit_type = type; - memcpy(&pd[port].vdo_data[1], data, - sizeof(uint32_t) * data_cnt); + memcpy(&pd[port].vdo_data[1], data, sizeof(uint32_t) * data_cnt); /* Set ready, pd task will actually send */ pd[port].vdm_state = VDM_STATE_READY; } +/* ----------------- Vendor Defined Messages ------------------ */ +__overridable int pd_custom_vdm(int port, int cnt, uint32_t *payload, + uint32_t **rpayload) +{ + int cmd = PD_VDO_CMD(payload[0]); + uint16_t dev_id = 0; + int is_rw, is_latest; + + /* make sure we have some payload */ + if (cnt == 0) + return 0; + + /* Only handle custom requests for SVID Google */ + if (PD_VDO_VID(*payload) != USB_VID_GOOGLE) + return 0; + + switch (cmd) { + case VDO_CMD_VERSION: + /* guarantee last byte of payload is null character */ + *(payload + cnt - 1) = 0; + CPRINTF("version: %s\n", (char *)(payload + 1)); + break; + case VDO_CMD_READ_INFO: + case VDO_CMD_SEND_INFO: + /* copy hash */ + if (cnt == 7) { + dev_id = VDO_INFO_HW_DEV_ID(payload[6]); + is_rw = VDO_INFO_IS_RW(payload[6]); + + is_latest = pd_dev_store_rw_hash( + port, dev_id, payload + 1, + is_rw ? EC_IMAGE_RW : EC_IMAGE_RO); + + /* + * Send update host event unless our RW hash is + * already known to be the latest update RW. + */ + if (!is_rw || !is_latest) + pd_send_host_event(PD_EVENT_UPDATE_DEVICE); + + CPRINTF("DevId:%d.%d SW:%d RW:%d\n", + HW_DEV_ID_MAJ(dev_id), HW_DEV_ID_MIN(dev_id), + VDO_INFO_SW_DBG_VER(payload[6]), is_rw); + } else if (cnt == 6) { + /* really old devices don't have last byte */ + pd_dev_store_rw_hash(port, dev_id, payload + 1, + EC_IMAGE_UNKNOWN); + } + break; + case VDO_CMD_CURRENT: + CPRINTF("Current: %dmA\n", payload[1]); + break; + case VDO_CMD_FLIP: + if (IS_ENABLED(CONFIG_USBC_SS_MUX)) + usb_mux_flip(port); + break; +#ifdef CONFIG_USB_PD_LOGGING + case VDO_CMD_GET_LOG: + pd_log_recv_vdm(port, cnt, payload); + break; +#endif /* CONFIG_USB_PD_LOGGING */ + } + + return 0; +} + static void handle_vdm_request(int port, int cnt, uint32_t *payload, - uint32_t head) + uint32_t head) { int rlen = 0; uint32_t *rdata; - enum tcpm_transmit_type rtype = TCPC_TX_SOP; + enum tcpci_msg_type rtype = TCPCI_MSG_SOP; if (pd[port].vdm_state == VDM_STATE_BUSY) { /* If UFP responded busy retry after timeout */ if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) { - pd[port].vdm_timeout.val = get_time().val + - PD_T_VDM_BUSY; + pd[port].vdm_timeout.val = + get_time().val + PD_T_VDM_BUSY; pd[port].vdm_state = VDM_STATE_WAIT_RSP_BUSY; pd[port].vdo_retry = (payload[0] & ~VDO_CMDT_MASK) | - CMDT_INIT; + CMDT_INIT; return; } else { pd[port].vdm_state = VDM_STATE_DONE; @@ -1295,8 +1371,8 @@ static void handle_vdm_request(int port, int cnt, uint32_t *payload, } if (debug_level >= 2) - CPRINTF("C%d Unhandled VDM VID %04x CMD %04x\n", - port, PD_VDO_VID(payload[0]), payload[0] & 0xFFFF); + CPRINTF("C%d Unhandled VDM VID %04x CMD %04x\n", port, + PD_VDO_VID(payload[0]), payload[0] & 0xFFFF); } bool pd_is_disconnected(int port) @@ -1325,11 +1401,9 @@ static void pd_set_data_role(int port, enum pd_data_role role) * task and indicate the current data role. */ if (role == PD_ROLE_UFP) - task_set_event(USB_CHG_PORT_TO_TASK_ID(port), - USB_CHG_EVENT_DR_UFP, 0); + usb_charger_task_set_event(port, USB_CHG_EVENT_DR_UFP); else if (role == PD_ROLE_DFP) - task_set_event(USB_CHG_PORT_TO_TASK_ID(port), - USB_CHG_EVENT_DR_DFP, 0); + usb_charger_task_set_event(port, USB_CHG_EVENT_DR_DFP); #endif /* CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER */ } @@ -1357,7 +1431,8 @@ void pd_execute_hard_reset(int port) invalidate_last_message_id(port); tcpm_set_rx_enable(port, 0); #ifdef CONFIG_USB_PD_ALT_MODE_DFP - pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); + if (pd_dfp_exit_mode(port, TCPCI_MSG_SOP, 0, 0)) + usb_mux_set_safe_mode(port); #endif #ifdef CONFIG_USB_PD_REV30 @@ -1387,8 +1462,7 @@ void pd_execute_hard_reset(int port) /* Clear the input current limit */ pd_set_input_current_limit(port, 0, 0); #ifdef CONFIG_CHARGE_MANAGER - charge_manager_set_ceil(port, - CEIL_REQUESTOR_PD, + charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, CHARGE_CEIL_NONE); #endif /* CONFIG_CHARGE_MANAGER */ @@ -1428,7 +1502,7 @@ static void execute_soft_reset(int port) { invalidate_last_message_id(port); set_state(port, DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCOVERY, - PD_STATE_SRC_DISCOVERY)); + PD_STATE_SRC_DISCOVERY)); CPRINTF("C%d Soft Rst\n", port); } @@ -1470,8 +1544,8 @@ static int pd_send_request_msg(int port, int always_send_request) #endif } - CPRINTF("C%d Req [%d] %dmV %dmA", port, RDO_POS(rdo), - supply_voltage, curr_limit); + CPRINTF("C%d Req [%d] %dmV %dmA", port, RDO_POS(rdo), supply_voltage, + curr_limit); if (rdo & RDO_CAP_MISMATCH) CPRINTF(" Mismatch"); CPRINTF("\n"); @@ -1487,63 +1561,62 @@ static int pd_send_request_msg(int port, int always_send_request) } #endif -static void pd_update_pdo_flags(int port, uint32_t pdo) +static void pd_update_pdo_flags(int port, int pdo_cnt, uint32_t *pdos) { -#ifdef CONFIG_CHARGE_MANAGER -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - int charge_allowlisted = - (pd[port].power_role == PD_ROLE_SINK && - pd_charge_from_device(pd_get_identity_vid(port), - pd_get_identity_pid(port))); -#else - const int charge_allowlisted = 0; -#endif -#endif - /* can only parse PDO flags if type is fixed */ - if ((pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED) + if ((pdos[0] & PDO_TYPE_MASK) != PDO_TYPE_FIXED) return; #ifdef CONFIG_USB_PD_DUAL_ROLE - if (pdo & PDO_FIXED_DUAL_ROLE) + if (pdos[0] & PDO_FIXED_DUAL_ROLE) pd[port].flags |= PD_FLAGS_PARTNER_DR_POWER; else pd[port].flags &= ~PD_FLAGS_PARTNER_DR_POWER; - if (pdo & PDO_FIXED_UNCONSTRAINED) + if (pdos[0] & PDO_FIXED_UNCONSTRAINED) pd[port].flags |= PD_FLAGS_PARTNER_UNCONSTR; else pd[port].flags &= ~PD_FLAGS_PARTNER_UNCONSTR; - if (pdo & PDO_FIXED_COMM_CAP) + if (pdos[0] & PDO_FIXED_COMM_CAP) pd[port].flags |= PD_FLAGS_PARTNER_USB_COMM; else pd[port].flags &= ~PD_FLAGS_PARTNER_USB_COMM; #endif - if (pdo & PDO_FIXED_DATA_SWAP) + if (pdos[0] & PDO_FIXED_DATA_SWAP) pd[port].flags |= PD_FLAGS_PARTNER_DR_DATA; else pd[port].flags &= ~PD_FLAGS_PARTNER_DR_DATA; -#ifdef CONFIG_CHARGE_MANAGER /* * Treat device as a dedicated charger (meaning we should charge - * from it) if it does not support power swap, or has unconstrained - * power, or if we are a sink and the device identity matches a - * charging allow-list. + * from it) if: + * - it does not support power swap, or + * - it is unconstrained power, or + * - it presents at least 27 W of available power */ - if (!(pd[port].flags & PD_FLAGS_PARTNER_DR_POWER) || - (pd[port].flags & PD_FLAGS_PARTNER_UNCONSTR) || - charge_allowlisted) - charge_manager_update_dualrole(port, CAP_DEDICATED); - else - charge_manager_update_dualrole(port, CAP_DUALROLE); -#endif + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { + uint32_t max_ma, max_mv, max_pdo, max_mw, unused; + + /* + * Get max power that the partner offers (not necessarily what + * this board will request) + */ + pd_find_pdo_index(pdo_cnt, pdos, PD_REV3_MAX_VOLTAGE, &max_pdo); + pd_extract_pdo_power(max_pdo, &max_ma, &max_mv, &unused); + max_mw = max_ma * max_mv / 1000; + + if (!(pdos[0] & PDO_FIXED_DUAL_ROLE) || + (pdos[0] & PDO_FIXED_UNCONSTRAINED) || + max_mw >= PD_DRP_CHARGE_POWER_MIN) + charge_manager_update_dualrole(port, CAP_DEDICATED); + else + charge_manager_update_dualrole(port, CAP_DUALROLE); + } } -static void handle_data_request(int port, uint32_t head, - uint32_t *payload) +static void handle_data_request(int port, uint32_t head, uint32_t *payload) { int type = PD_HEADER_TYPE(head); int cnt = PD_HEADER_CNT(head); @@ -1551,14 +1624,12 @@ static void handle_data_request(int port, uint32_t head, switch (type) { #ifdef CONFIG_USB_PD_DUAL_ROLE case PD_DATA_SOURCE_CAP: - if ((pd[port].task_state == PD_STATE_SNK_DISCOVERY) - || (pd[port].task_state == PD_STATE_SNK_TRANSITION) - || (pd[port].task_state == PD_STATE_SNK_REQUESTED) -#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE - || (pd[port].task_state == - PD_STATE_SNK_HARD_RESET_RECOVER) -#endif - || (pd[port].task_state == PD_STATE_SNK_READY)) { + if ((pd[port].task_state == PD_STATE_SNK_DISCOVERY) || + (pd[port].task_state == PD_STATE_SNK_TRANSITION) || + (pd[port].task_state == PD_STATE_SNK_REQUESTED) || + ((get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_NONE) && + (pd[port].task_state == PD_STATE_SNK_HARD_RESET_RECOVER)) || + (pd[port].task_state == PD_STATE_SNK_READY)) { #ifdef CONFIG_USB_PD_REV30 /* * Only adjust sink rev if source rev is higher. @@ -1570,7 +1641,7 @@ static void handle_data_request(int port, uint32_t head, pd[port].flags |= PD_FLAGS_PREVIOUS_PD_CONN; /* src cap 0 should be fixed PDO */ - pd_update_pdo_flags(port, payload[0]); + pd_update_pdo_flags(port, cnt, payload); pd_process_source_cap(port, cnt, payload); @@ -1615,37 +1686,33 @@ static void handle_data_request(int port, uint32_t head, break; case PD_DATA_BIST: /* If not in READY state, then don't start BIST */ - if (DUAL_ROLE_IF_ELSE(port, - pd[port].task_state == PD_STATE_SNK_READY, - pd[port].task_state == PD_STATE_SRC_READY)) { + if (DUAL_ROLE_IF_ELSE( + port, pd[port].task_state == PD_STATE_SNK_READY, + pd[port].task_state == PD_STATE_SRC_READY)) { /* currently only support sending bist carrier mode 2 */ if ((payload[0] >> 28) == 5) { /* bist data object mode is 2 */ - pd_transmit(port, TCPC_TX_BIST_MODE_2, 0, + pd_transmit(port, TCPCI_MSG_TX_BIST_MODE_2, 0, NULL, AMS_RESPONSE); /* Set to appropriate port disconnected state */ - set_state(port, DUAL_ROLE_IF_ELSE(port, - PD_STATE_SNK_DISCONNECTED, - PD_STATE_SRC_DISCONNECTED)); + set_state(port, + DUAL_ROLE_IF_ELSE( + port, + PD_STATE_SNK_DISCONNECTED, + PD_STATE_SRC_DISCONNECTED)); } } break; case PD_DATA_SINK_CAP: pd[port].flags |= PD_FLAGS_SNK_CAP_RECVD; /* snk cap 0 should be fixed PDO */ - pd_update_pdo_flags(port, payload[0]); + pd_update_pdo_flags(port, cnt, payload); if (pd[port].task_state == PD_STATE_SRC_GET_SINK_CAP) set_state(port, PD_STATE_SRC_READY); break; #ifdef CONFIG_USB_PD_REV30 case PD_DATA_BATTERY_STATUS: break; - /* TODO : Add case PD_DATA_RESET for exiting USB4 */ - - /* - * TODO : Add case PD_DATA_ENTER_USB to accept or reject - * Enter_USB request from port partner. - */ #endif case PD_DATA_VENDOR_DEF: handle_vdm_request(port, cnt, payload, head); @@ -1690,9 +1757,8 @@ void pd_try_vconn_src(int port) void pd_request_data_swap(int port) { - if (DUAL_ROLE_IF_ELSE(port, - pd[port].task_state == PD_STATE_SNK_READY, - pd[port].task_state == PD_STATE_SRC_READY)) + if (DUAL_ROLE_IF_ELSE(port, pd[port].task_state == PD_STATE_SNK_READY, + pd[port].task_state == PD_STATE_SRC_READY)) set_state(port, PD_STATE_DR_SWAP); task_wake(PD_PORT_TO_TASK_ID(port)); } @@ -1711,8 +1777,7 @@ static void pd_dr_swap(int port) pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; } -static void handle_ctrl_request(int port, uint32_t head, - uint32_t *payload) +static void handle_ctrl_request(int port, uint32_t head, uint32_t *payload) { int type = PD_HEADER_TYPE(head); int res; @@ -1753,7 +1818,7 @@ static void handle_ctrl_request(int port, uint32_t head, * later time. */ pd_snk_give_back(port, &pd[port].curr_limit, - &pd[port].supply_voltage); + &pd[port].supply_voltage); set_state(port, PD_STATE_SNK_TRANSITION); } #endif @@ -1798,37 +1863,21 @@ static void handle_ctrl_request(int port, uint32_t head, */ if (pd[port].task_state == PD_STATE_SNK_TRANSITION) pd[port].ready_state_holdoff_timer = - get_time().val + SNK_READY_HOLD_OFF_US - + (get_time().le.lo & 0xf) * 12 * MSEC; + get_time().val + SNK_READY_HOLD_OFF_US + + (get_time().le.lo & 0xf) * 12 * MSEC; set_state(port, PD_STATE_SNK_READY); pd_set_input_current_limit(port, pd[port].curr_limit, pd[port].supply_voltage); #ifdef CONFIG_CHARGE_MANAGER /* Set ceiling based on what's negotiated */ - charge_manager_set_ceil(port, - CEIL_REQUESTOR_PD, + charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, pd[port].curr_limit); #endif } break; #endif case PD_CTRL_REJECT: - if (pd[port].task_state == PD_STATE_ENTER_USB) { - if (!IS_ENABLED(CONFIG_USBC_SS_MUX)) - break; - - /* - * Since Enter USB sets the mux state to SAFE mode, - * resetting the mux state back to USB mode on - * recieveing a NACK. - */ - usb_mux_set(port, USB_PD_MUX_USB_ENABLED, - USB_SWITCH_CONNECT, pd[port].polarity); - - set_state(port, READY_RETURN_STATE(port)); - break; - } case PD_CTRL_WAIT: if (pd[port].task_state == PD_STATE_DR_SWAP) { if (type == PD_CTRL_WAIT) /* try again ... */ @@ -1883,28 +1932,15 @@ static void handle_ctrl_request(int port, uint32_t head, const int in_contract = pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT; - set_state(port, - in_contract ? PD_STATE_SNK_READY - : PD_STATE_SNK_DISCOVERY); + set_state(port, in_contract ? + PD_STATE_SNK_READY : + PD_STATE_SNK_DISCOVERY); } } #endif break; case PD_CTRL_ACCEPT: - if (pd[port].task_state == PD_STATE_ENTER_USB) { - if (!IS_ENABLED(CONFIG_USBC_SS_MUX)) - break; - - /* Connect the SBU and USB lines to the connector */ - if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) - ppc_set_sbu(port, 1); - - /* Set usb mux to USB4 mode */ - usb_mux_set(port, USB_PD_MUX_USB4_ENABLED, - USB_SWITCH_CONNECT, pd[port].polarity); - - set_state(port, READY_RETURN_STATE(port)); - } else if (pd[port].task_state == PD_STATE_SOFT_RESET) { + if (pd[port].task_state == PD_STATE_SOFT_RESET) { /* * For the case that we sent soft reset in SNK_DISCOVERY * on startup due to VBUS never low, clear the flag. @@ -1924,23 +1960,20 @@ static void handle_ctrl_request(int port, uint32_t head, } else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) { /* explicit contract goes away for power swap */ pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; - pd_update_saved_port_flags(port, - PD_BBRMFLG_EXPLICIT_CONTRACT, - 0); + pd_update_saved_port_flags( + port, PD_BBRMFLG_EXPLICIT_CONTRACT, 0); set_state(port, PD_STATE_SRC_SWAP_SNK_DISABLE); } else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) { /* explicit contract goes away for power swap */ pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT; - pd_update_saved_port_flags(port, - PD_BBRMFLG_EXPLICIT_CONTRACT, - 0); + pd_update_saved_port_flags( + port, PD_BBRMFLG_EXPLICIT_CONTRACT, 0); set_state(port, PD_STATE_SNK_SWAP_SNK_DISABLE); } else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) { /* explicit contract is now in place */ pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT; - pd_update_saved_port_flags(port, - PD_BBRMFLG_EXPLICIT_CONTRACT, - 1); + pd_update_saved_port_flags( + port, PD_BBRMFLG_EXPLICIT_CONTRACT, 1); set_state(port, PD_STATE_SNK_TRANSITION); #endif } @@ -1961,9 +1994,9 @@ static void handle_ctrl_request(int port, uint32_t head, */ pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; set_state(port, - DUAL_ROLE_IF_ELSE(port, - PD_STATE_SNK_SWAP_SNK_DISABLE, - PD_STATE_SRC_SWAP_SNK_DISABLE)); + DUAL_ROLE_IF_ELSE( + port, PD_STATE_SNK_SWAP_SNK_DISABLE, + PD_STATE_SRC_SWAP_SNK_DISABLE)); } else { send_control(port, PD_CTRL_REJECT); } @@ -1983,7 +2016,6 @@ static void handle_ctrl_request(int port, uint32_t head, pd_dr_swap(port); } else { send_control(port, PD_CTRL_REJECT); - } break; case PD_CTRL_VCONN_SWAP: @@ -2030,8 +2062,7 @@ static void handle_ext_request(int port, uint16_t head, uint32_t *payload) } #endif -static void handle_request(int port, uint32_t head, - uint32_t *payload) +static void handle_request(int port, uint32_t head, uint32_t *payload) { int cnt = PD_HEADER_CNT(head); int data_role = PD_HEADER_DROLE(head); @@ -2076,8 +2107,7 @@ static void handle_request(int port, uint32_t head, TYPEC_CC_RP)); } set_state(port, - DUAL_ROLE_IF_ELSE(port, - PD_STATE_SNK_DISCONNECTED, + DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCONNECTED, PD_STATE_SRC_DISCONNECTED)); return; } @@ -2104,12 +2134,15 @@ void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, } /* set VDM header with VID & CMD */ - pd[port].vdo_data[0] = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ? - 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd); + pd[port].vdo_data[0] = VDO(vid, + ((vid & USB_SID_PD) == USB_SID_PD) ? + 1 : + (PD_VDO_CMD(cmd) <= CMD_ATTENTION), + cmd); #ifdef CONFIG_USB_PD_REV30 pd[port].vdo_data[0] |= VDO_SVDM_VERS(vdo_ver[pd[port].rev]); #endif - queue_vdm(port, pd[port].vdo_data, data, count, TCPC_TX_SOP); + queue_vdm(port, pd[port].vdo_data, data, count, TCPCI_MSG_SOP); task_wake(PD_PORT_TO_TASK_ID(port)); } @@ -2135,7 +2168,7 @@ static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr) /* its not a structured VDM command */ if (!PD_VDO_SVDM(vdm_hdr)) - return 500*MSEC; + return 500 * MSEC; switch (PD_VDO_CMDT(vdm_hdr)) { case CMDT_INIT: @@ -2154,48 +2187,10 @@ static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr) return timeout; } -static void exit_tbt_mode_sop_prime(int port) -{ - /* Exit Thunderbolt-Compatible mode SOP' */ - uint16_t header; - int opos; - - if (!IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) - return; - - opos = pd_alt_mode(port, TCPC_TX_SOP, USB_VID_INTEL); - if (opos <= 0) - return; - - CPRINTS("C%d Cable exiting TBT Compat mode", port); - /* - * Note: TCPMv2 contemplates separate discovery structures for each SOP - * type. TCPMv1 only uses one discovery structure, so all accesses - * specify TCPC_TX_SOP. - */ - if (!pd_dfp_exit_mode(port, TCPC_TX_SOP, USB_VID_INTEL, opos)) - return; - - header = PD_HEADER(PD_DATA_VENDOR_DEF, pd[port].power_role, - pd[port].data_role, pd[port].msg_id, - (int)pd[port].vdo_count, - pd_get_rev(port, TCPC_TX_SOP), 0); - - pd[port].vdo_data[0] = VDO(USB_VID_INTEL, 1, - CMD_EXIT_MODE | VDO_OPOS(opos)); - - pd_transmit(port, TCPC_TX_SOP_PRIME, header, pd[port].vdo_data, - AMS_START); - - usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT, - pd_get_polarity(port)); -} - static void pd_vdm_send_state_machine(int port) { int res; uint16_t header; - enum tcpm_transmit_type msg_type = pd[port].xmit_type; switch (pd[port].vdm_state) { case VDM_STATE_READY: @@ -2212,82 +2207,20 @@ static void pd_vdm_send_state_machine(int port) if (pdo_busy(port)) break; - /* - * To communicate with the cable plug, an explicit contract - * should be established, VCONN should be enabled and data role - * that can communicate with the cable plug should be in place. - * For USB3.0, UFP/DFP can communicate whereas in case of - * USB2.0 only DFP can talk to the cable plug. - * - * For communication between USB2.0 UFP and cable plug, - * data role swap takes place during source and sink - * negotiation and in case of failure, a soft reset is issued. - */ - if ((msg_type == TCPC_TX_SOP_PRIME) || - (msg_type == TCPC_TX_SOP_PRIME_PRIME)) { - /* Prepare SOP'/SOP'' header and send VDM */ - header = PD_HEADER( - PD_DATA_VENDOR_DEF, - PD_PLUG_FROM_DFP_UFP, - 0, - pd[port].msg_id, - (int)pd[port].vdo_count, - pd_get_rev(port, TCPC_TX_SOP), - 0); - res = pd_transmit(port, msg_type, header, - pd[port].vdo_data, AMS_START); - /* - * In the case of SOP', if there is no response from - * the cable, it's a non-emark cable and therefore the - * pd flow should continue irrespective of cable - * response, sending discover_identity so the pd flow - * remains intact. - * - * In the case of SOP'', if there is no response from - * the cable, exit Thunderbolt-Compatible mode - * discovery, reset the mux state since, the mux will - * be set to a safe state before entering - * Thunderbolt-Compatible mode and enter the default - * mode. - */ - if (res < 0) { - header = PD_HEADER(PD_DATA_VENDOR_DEF, - pd[port].power_role, - pd[port].data_role, - pd[port].msg_id, - (int)pd[port].vdo_count, - pd_get_rev - (port, TCPC_TX_SOP), - 0); - - if ((msg_type == TCPC_TX_SOP_PRIME_PRIME) && - IS_ENABLED(CONFIG_USBC_SS_MUX)) { - exit_tbt_mode_sop_prime(port); - } else if (msg_type == TCPC_TX_SOP_PRIME) { - pd[port].vdo_data[0] = VDO(USB_SID_PD, - 1, CMD_DISCOVER_SVID); - } - res = pd_transmit(port, TCPC_TX_SOP, header, - pd[port].vdo_data, AMS_START); - reset_pd_cable(port); - } - } else { - /* Prepare SOP header and send VDM */ - header = PD_HEADER(PD_DATA_VENDOR_DEF, - pd[port].power_role, - pd[port].data_role, - pd[port].msg_id, - (int)pd[port].vdo_count, - pd_get_rev(port, TCPC_TX_SOP), 0); - res = pd_transmit(port, TCPC_TX_SOP, header, - pd[port].vdo_data, AMS_START); - } + /* Prepare SOP header and send VDM */ + header = PD_HEADER(PD_DATA_VENDOR_DEF, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, + (int)pd[port].vdo_count, + pd_get_rev(port, TCPCI_MSG_SOP), 0); + res = pd_transmit(port, TCPCI_MSG_SOP, header, + pd[port].vdo_data, AMS_START); if (res < 0) { pd[port].vdm_state = VDM_STATE_ERR_SEND; } else { pd[port].vdm_state = VDM_STATE_BUSY; - pd[port].vdm_timeout.val = get_time().val + + pd[port].vdm_timeout.val = + get_time().val + vdm_get_ready_timeout(pd[port].vdo_data[0]); } break; @@ -2349,15 +2282,14 @@ int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash, /* Search table for matching device / hash */ for (i = 0; i < RW_HASH_ENTRIES; i++) if (dev_id == rw_hash_table[i].dev_id) - return !memcmp(rw_hash, - rw_hash_table[i].dev_rw_hash, + return !memcmp(rw_hash, rw_hash_table[i].dev_rw_hash, PD_RW_HASH_SIZE); #endif return 0; } void pd_dev_get_rw_hash(int port, uint16_t *dev_id, uint8_t *rw_hash, - uint32_t *current_image) + uint32_t *current_image) { *dev_id = pd[port].dev_id; *current_image = pd[port].current_image; @@ -2373,14 +2305,15 @@ __maybe_unused static void exit_supported_alt_mode(int port) return; for (i = 0; i < supported_modes_cnt; i++) { - int opos = pd_alt_mode(port, TCPC_TX_SOP, - supported_modes[i].svid); + int opos = pd_alt_mode(port, TCPCI_MSG_SOP, + supported_modes[i].svid); if (opos > 0 && - pd_dfp_exit_mode( - port, TCPC_TX_SOP, supported_modes[i].svid, opos)) { + pd_dfp_exit_mode(port, TCPCI_MSG_SOP, + supported_modes[i].svid, opos)) { CPRINTS("C%d Exiting ALT mode with SVID = 0x%x", port, supported_modes[i].svid); + usb_mux_set_safe_mode(port); pd_send_vdm(port, supported_modes[i].svid, CMD_EXIT_MODE | VDO_OPOS(opos), NULL, 0); /* Wait for an ACK from port-partner */ @@ -2389,10 +2322,9 @@ __maybe_unused static void exit_supported_alt_mode(int port) } } -#ifdef CONFIG_POWER_COMMON +#ifdef CONFIG_AP_POWER_CONTROL static void handle_new_power_state(int port) { - if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) { /* * The SoC will negotiate the alternate mode again when @@ -2409,7 +2341,7 @@ static void handle_new_power_state(int port) /* Ensure mux is set properly after chipset transition */ set_usb_mux_with_current_data_role(port); } -#endif /* CONFIG_POWER_COMMON */ +#endif /* CONFIG_AP_POWER_CONTROL */ #ifdef CONFIG_USB_PD_DUAL_ROLE enum pd_dual_role_states pd_get_dual_role(int port) @@ -2456,8 +2388,8 @@ static void pd_update_snk_reset(void) if (pd[i].task_state == PD_STATE_SNK_DISCOVERY) { CPRINTS("C%d: Starting soft reset timer", i); - set_state_timeout(i, - get_time().val + PD_T_SINK_WAIT_CAP, + set_state_timeout( + i, get_time().val + PD_T_SINK_WAIT_CAP, PD_STATE_SOFT_RESET); } } @@ -2495,8 +2427,19 @@ void pd_set_dual_role(int port, enum pd_dual_role_states state) pd_set_dual_role_no_wakeup(port, state); /* Wake task up to process change */ - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_UPDATE_DUAL_ROLE, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_UPDATE_DUAL_ROLE); +} + +static int pd_is_power_swapping(int port) +{ + /* return true if in the act of swapping power roles */ + return pd[port].task_state == PD_STATE_SNK_SWAP_SNK_DISABLE || + pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE || + pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY || + pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE || + pd[port].task_state == PD_STATE_SRC_SWAP_SNK_DISABLE || + pd[port].task_state == PD_STATE_SRC_SWAP_SRC_DISABLE || + pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY; } /* This must only be called from the PD task */ @@ -2504,14 +2447,13 @@ static void pd_update_dual_role_config(int port) { /* * Change to sink if port is currently a source AND (new DRP - * state is force sink OR new DRP state is either toggle off - * or debug accessory toggle only and we are in the source - * disconnected state). + * state is force sink OR new DRP state is toggle off and we are in the + * source disconnected state). */ if (pd[port].power_role == PD_ROLE_SOURCE && - ((drp_state[port] == PD_DRP_FORCE_SINK && !pd_ts_dts_plugged(port)) - || (drp_state[port] == PD_DRP_TOGGLE_OFF - && pd[port].task_state == PD_STATE_SRC_DISCONNECTED))) { + (drp_state[port] == PD_DRP_FORCE_SINK || + (drp_state[port] == PD_DRP_TOGGLE_OFF && + pd[port].task_state == PD_STATE_SRC_DISCONNECTED))) { pd_set_power_role(port, PD_ROLE_SINK); set_state(port, PD_STATE_SNK_DISCONNECTED); tcpm_set_cc(port, TYPEC_CC_RD); @@ -2521,28 +2463,20 @@ static void pd_update_dual_role_config(int port) /* * Change to source if port is currently a sink and the - * new DRP state is force source. + * new DRP state is force source. If we are performing + * power swap we won't change anything because + * changing state will disrupt power swap process + * and we are power swapping to desired power role. */ if (pd[port].power_role == PD_ROLE_SINK && - drp_state[port] == PD_DRP_FORCE_SOURCE) { + drp_state[port] == PD_DRP_FORCE_SOURCE && + !pd_is_power_swapping(port)) { pd_set_power_role(port, PD_ROLE_SOURCE); set_state(port, PD_STATE_SRC_DISCONNECTED); tcpm_set_cc(port, TYPEC_CC_RP); } } -static int pd_is_power_swapping(int port) -{ - /* return true if in the act of swapping power roles */ - return pd[port].task_state == PD_STATE_SNK_SWAP_SNK_DISABLE || - pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE || - pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY || - pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE || - pd[port].task_state == PD_STATE_SRC_SWAP_SNK_DISABLE || - pd[port].task_state == PD_STATE_SRC_SWAP_SRC_DISABLE || - pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY; -} - /* * Provide Rp to ensure the partner port is in a known state (eg. not * PD negotiated, not sourcing 20V). @@ -2613,6 +2547,18 @@ uint8_t pd_get_task_state(int port) return pd[port].task_state; } +#ifdef CONFIG_USB_PD_DUAL_ROLE +uint32_t pd_get_requested_voltage(int port) +{ + return pd[port].supply_voltage; +} + +uint32_t pd_get_requested_current(int port) +{ + return pd[port].curr_limit; +} +#endif + const char *pd_get_task_state_name(int port) { #ifdef CONFIG_USB_PD_TCPMV1_DEBUG @@ -2664,8 +2610,7 @@ void pd_comm_enable(int port, int enable) * any port in PD_SNK_DISCOVERY. */ if (enable && pd[port].task_state == PD_STATE_SNK_DISCOVERY) - set_state_timeout(port, - get_time().val + PD_T_SINK_WAIT_CAP, + set_state_timeout(port, get_time().val + PD_T_SINK_WAIT_CAP, PD_STATE_HARD_RESET_SEND); #endif } @@ -2723,7 +2668,7 @@ static void pd_init_tasks(void) if (initialized) return; -#if defined(HAS_TASK_CHIPSET) && defined(CONFIG_USB_PD_DUAL_ROLE) +#if defined(CONFIG_AP_POWER_CONTROL) && defined(CONFIG_USB_PD_DUAL_ROLE) /* Set dual-role state based on chipset power state */ if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) for (i = 0; i < board_get_usb_pd_port_count(); i++) @@ -2763,56 +2708,12 @@ static int pd_restart_tcpc(int port) } #endif -static void pd_send_enter_usb(int port, int *timeout) -{ - uint32_t usb4_payload; - uint16_t header; - int res; - - /* - * TODO: Enable Enter USB for cables (SOP'). - * This is needed for active cables - */ - if (!IS_ENABLED(CONFIG_USBC_SS_MUX) || - !IS_ENABLED(CONFIG_USB_PD_USB4) || - !IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) - return; - - usb4_payload = get_enter_usb_msg_payload(port); - - header = PD_HEADER(PD_DATA_ENTER_USB, - pd[port].power_role, - pd[port].data_role, - pd[port].msg_id, - 1, - PD_REV30, - 0); - - res = pd_transmit(port, TCPC_TX_SOP, header, &usb4_payload, AMS_START); - if (res < 0) { - *timeout = 10*MSEC; - /* - * If failed to get goodCRC, send soft reset, otherwise ignore - * failure. - */ - set_state(port, res == -1 ? - PD_STATE_SOFT_RESET : - READY_RETURN_STATE(port)); - return; - } - - /* Disable Enter USB4 mode prevent re-entry */ - disable_enter_usb4_mode(port); - - set_state(port, PD_STATE_ENTER_USB); -} - void pd_task(void *u) { uint32_t head; int port = TASK_ID_TO_PD_PORT(task_get_current()); uint32_t payload[7]; - int timeout = 10*MSEC; + int timeout = 10 * MSEC; enum tcpc_cc_voltage_status cc1, cc2; int res, incoming_packet = 0; int hard_reset_count = 0; @@ -2890,8 +2791,7 @@ void pd_task(void *u) if (!res) { struct ec_response_pd_chip_info_v1 info; - if (tcpm_get_chip_info(port, 0, &info) == - EC_SUCCESS) { + if (tcpm_get_chip_info(port, 0, &info) == EC_SUCCESS) { CPRINTS("TCPC p%d VID:0x%x PID:0x%x DID:0x%x " "FWV:0x%" PRIx64, port, info.vendor_id, info.product_id, @@ -2911,8 +2811,8 @@ void pd_task(void *u) * present. This flag is used to maintain a PD connection after a * reset by sending a soft reset. */ - pd[port].flags |= - pd_is_vbus_present(port) ? PD_FLAGS_VBUS_NEVER_LOW : 0; + pd[port].flags |= pd_is_vbus_present(port) ? PD_FLAGS_VBUS_NEVER_LOW : + 0; #endif /* Disable TCPC RX until connection is established */ @@ -2936,14 +2836,17 @@ void pd_task(void *u) if ((saved_flgs & PD_BBRMFLG_POWER_ROLE) == PD_ROLE_SINK) { pd_set_power_role(port, (saved_flgs & PD_BBRMFLG_POWER_ROLE) ? - PD_ROLE_SOURCE : PD_ROLE_SINK); + PD_ROLE_SOURCE : + PD_ROLE_SINK); pd_set_data_role(port, (saved_flgs & PD_BBRMFLG_DATA_ROLE) ? - PD_ROLE_DFP : PD_ROLE_UFP); + PD_ROLE_DFP : + PD_ROLE_UFP); #ifdef CONFIG_USBC_VCONN pd_set_vconn_role(port, (saved_flgs & PD_BBRMFLG_VCONN_ROLE) ? - PD_ROLE_VCONN_ON : PD_ROLE_VCONN_OFF); + PD_ROLE_VCONN_ON : + PD_ROLE_VCONN_OFF); #endif /* CONFIG_USBC_VCONN */ /* @@ -2965,9 +2868,8 @@ void pd_task(void *u) * earlier, so clear the contract flag and re-start as * default role */ - pd_update_saved_port_flags(port, - PD_BBRMFLG_EXPLICIT_CONTRACT, 0); - + pd_update_saved_port_flags( + port, PD_BBRMFLG_EXPLICIT_CONTRACT, 0); } /* * Set the TCPC reset event such that we can set our CC @@ -2975,7 +2877,7 @@ void pd_task(void *u) * can hear back from our port partner if maintaining our old * connection. */ - task_set_event(task_get_current(), PD_EVENT_TCPC_RESET, 0); + task_set_event(task_get_current(), PD_EVENT_TCPC_RESET); } #endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */ /* Set the power role if we haven't already. */ @@ -2994,7 +2896,8 @@ void pd_task(void *u) if (!(saved_flgs & PD_BBRMFLG_EXPLICIT_CONTRACT)) #endif /* CONFIG_USB_PD_DUAL_ROLE */ tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ? - TYPEC_CC_RP : TYPEC_CC_RD); + TYPEC_CC_RP : + TYPEC_CC_RD); #ifdef CONFIG_USBC_PPC /* @@ -3009,6 +2912,7 @@ void pd_task(void *u) #ifdef CONFIG_USB_PD_ALT_MODE_DFP /* Initialize PD Policy engine */ pd_dfp_discovery_init(port); + pd_dfp_mode_init(port); #endif #ifdef CONFIG_CHARGE_MANAGER @@ -3038,7 +2942,7 @@ void pd_task(void *u) /* cut the power */ pd_execute_hard_reset(port); /* notify the other side of the issue */ - pd_transmit(port, TCPC_TX_HARD_RESET, 0, NULL, + pd_transmit(port, TCPCI_MSG_TX_HARD_RESET, 0, NULL, AMS_START); } @@ -3051,7 +2955,7 @@ void pd_task(void *u) if (evt & PD_EVENT_DEVICE_ACCESSED) handle_device_access(port); #endif -#ifdef CONFIG_POWER_COMMON +#ifdef CONFIG_AP_POWER_CONTROL if (evt & PD_EVENT_POWER_STATE_CHANGE) handle_new_power_state(port); #endif @@ -3093,7 +2997,8 @@ void pd_task(void *u) * role. */ tcpm_set_cc(port, pd[port].power_role ? - TYPEC_CC_RP : TYPEC_CC_RD); + TYPEC_CC_RP : + TYPEC_CC_RD); /* Determine the polarity. */ tcpm_get_cc(port, &cc1, &cc2); @@ -3103,7 +3008,7 @@ void pd_task(void *u) } else if (cc_is_snk_dbg_acc(cc1, cc2)) { pd[port].polarity = board_get_src_dts_polarity( - port); + port); } else { pd[port].polarity = get_src_polarity(cc1, cc2); @@ -3112,9 +3017,11 @@ void pd_task(void *u) #endif /* CONFIG_USB_PD_DUAL_ROLE */ { /* Ensure CC termination is default */ - tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == - PD_ROLE_SOURCE ? TYPEC_CC_RP : - TYPEC_CC_RD); + tcpm_set_cc(port, + PD_ROLE_DEFAULT(port) == + PD_ROLE_SOURCE ? + TYPEC_CC_RP : + TYPEC_CC_RD); } /* @@ -3124,15 +3031,19 @@ void pd_task(void *u) * Otherwise, go to the default disconnected state * and force renegotiation. */ - if (pd[port].vdm_state == VDM_STATE_DONE && ( + if (pd[port].vdm_state == VDM_STATE_DONE && + ( #ifdef CONFIG_USB_PD_DUAL_ROLE - (PD_ROLE_DEFAULT(port) == PD_ROLE_SINK && - pd[port].task_state == PD_STATE_SNK_READY) || - (pd[port].task_state == PD_STATE_SOFT_RESET) || -#endif - (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE && - pd[port].task_state == PD_STATE_SRC_READY))) { - pd_set_polarity(port, pd[port].polarity); + (PD_ROLE_DEFAULT(port) == PD_ROLE_SINK && + pd[port].task_state == + PD_STATE_SNK_READY) || + (pd[port].task_state == + PD_STATE_SOFT_RESET) || +#endif + (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE && + pd[port].task_state == + PD_STATE_SRC_READY))) { + typec_set_polarity(port, pd[port].polarity); tcpm_set_msg_header(port, pd[port].power_role, pd[port].data_role); tcpm_set_rx_enable(port, 1); @@ -3165,15 +3076,14 @@ void pd_task(void *u) if (incoming_packet) { /* Dequeue and consume duplicate message ID. */ if (tcpm_dequeue_message(port, payload, &head) == - EC_SUCCESS - && !consume_repeat_message(port, head) - ) + EC_SUCCESS && + !consume_repeat_message(port, head)) handle_request(port, head, payload); /* Check if there are any more messages */ if (tcpm_has_pending_message(port)) task_set_event(PD_PORT_TO_TASK_ID(port), - TASK_EVENT_WAKE, 0); + TASK_EVENT_WAKE); } if (pd[port].req_suspend_state) @@ -3181,14 +3091,14 @@ void pd_task(void *u) /* if nothing to do, verify the state of the world in 500ms */ this_state = pd[port].task_state; - timeout = 500*MSEC; + timeout = 500 * MSEC; switch (this_state) { case PD_STATE_DISABLED: /* Nothing to do */ break; case PD_STATE_SRC_DISCONNECTED: - timeout = 10*MSEC; - + timeout = 10 * MSEC; + pd_set_src_caps(port, 0, NULL); #ifdef CONFIG_USB_PD_TCPC_LOW_POWER /* * If SW decided we should be in a low power state and @@ -3209,10 +3119,9 @@ void pd_task(void *u) */ if (auto_toggle_supported && !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) && - !is_try_src(port) && - cc_is_open(cc1, cc2)) { + !is_try_src(port) && cc_is_open(cc1, cc2)) { set_state(port, PD_STATE_DRP_AUTO_TOGGLE); - timeout = 2*MSEC; + timeout = 2 * MSEC; break; } #endif @@ -3242,7 +3151,7 @@ void pd_task(void *u) #endif pd[port].cc_state = PD_CC_NONE; set_state(port, - PD_STATE_SRC_DISCONNECTED_DEBOUNCE); + PD_STATE_SRC_DISCONNECTED_DEBOUNCE); break; } #if defined(CONFIG_USB_PD_DUAL_ROLE) @@ -3298,7 +3207,7 @@ void pd_task(void *u) #endif break; case PD_STATE_SRC_DISCONNECTED_DEBOUNCE: - timeout = 20*MSEC; + timeout = 20 * MSEC; tcpm_get_cc(port, &cc1, &cc2); if (cc_is_snk_dbg_acc(cc1, cc2)) { @@ -3313,7 +3222,7 @@ void pd_task(void *u) } else { /* No UFP */ set_state(port, PD_STATE_SRC_DISCONNECTED); - timeout = 5*MSEC; + timeout = 5 * MSEC; break; } @@ -3321,8 +3230,8 @@ void pd_task(void *u) if (new_cc_state != pd[port].cc_state) { pd[port].cc_debounce = get_time().val + - (is_try_src(port) ? PD_T_DEBOUNCE - : PD_T_CC_DEBOUNCE); + (is_try_src(port) ? PD_T_DEBOUNCE : + PD_T_CC_DEBOUNCE); pd[port].cc_state = new_cc_state; break; } @@ -3340,7 +3249,7 @@ void pd_task(void *u) * If the port is latched off, just continue to * monitor for a detach. */ - if (ppc_is_port_latched_off(port)) + if (usbc_ocp_is_port_latched_off(port)) break; #endif /* CONFIG_USBC_PPC */ @@ -3349,8 +3258,10 @@ void pd_task(void *u) new_cc_state == PD_CC_UFP_DEBUG_ACC) { #ifdef CONFIG_USBC_PPC /* Inform PPC that a sink is connected. */ - ppc_sink_is_connected(port, 1); + ppc_dev_is_connected(port, PPC_DEV_SNK); #endif /* CONFIG_USBC_PPC */ + if (IS_ENABLED(CONFIG_USBC_OCP)) + usbc_ocp_snk_is_connected(port, true); if (new_cc_state == PD_CC_UFP_DEBUG_ACC) { pd[port].polarity = board_get_src_dts_polarity( @@ -3359,7 +3270,7 @@ void pd_task(void *u) pd[port].polarity = get_src_polarity(cc1, cc2); } - pd_set_polarity(port, pd[port].polarity); + typec_set_polarity(port, pd[port].polarity); /* initial data role for source is DFP */ pd_set_data_role(port, PD_ROLE_DFP); @@ -3420,7 +3331,7 @@ void pd_task(void *u) pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE | PD_FLAGS_CHECK_DR_ROLE; hard_reset_count = 0; - timeout = 5*MSEC; + timeout = 5 * MSEC; set_state(port, PD_STATE_SRC_STARTUP); } @@ -3432,7 +3343,7 @@ void pd_task(void *u) case PD_STATE_SRC_HARD_RESET_RECOVER: /* Do not continue until hard reset recovery time */ if (get_time().val < pd[port].src_recover) { - timeout = 50*MSEC; + timeout = 50 * MSEC; break; } @@ -3446,12 +3357,12 @@ void pd_task(void *u) #endif /* Enable VBUS */ - timeout = 10*MSEC; + timeout = 10 * MSEC; if (pd_set_power_supply_ready(port)) { set_state(port, PD_STATE_SRC_DISCONNECTED); break; } -#ifdef CONFIG_USB_PD_TCPM_TCPCI +#if defined(CONFIG_USB_PD_TCPM_TCPCI) || defined(CONFIG_USB_PD_TCPM_STUB) /* * After transmitting hard reset, TCPM writes * to RECEIVE_DETECT register to enable @@ -3459,13 +3370,13 @@ void pd_task(void *u) */ if (pd_comm_is_enabled(port)) tcpm_set_rx_enable(port, 1); -#endif /* CONFIG_USB_PD_TCPM_TCPCI */ +#endif /* CONFIG_USB_PD_TCPM_TCPCI || CONFIG_USB_PD_TCPM_STUB */ + pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE | + PD_FLAGS_CHECK_DR_ROLE; set_state(port, PD_STATE_SRC_STARTUP); break; case PD_STATE_SRC_STARTUP: - /* Reset cable attributes and flags */ - reset_pd_cable(port); /* Wait for power source to enable */ if (pd[port].last_state != pd[port].task_state) { pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; @@ -3483,13 +3394,14 @@ void pd_task(void *u) * on during debounce. */ get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY - - (pd[port].last_state == - PD_STATE_SRC_DISCONNECTED_DEBOUNCE - ? PD_T_CC_DEBOUNCE : 0), + PD_POWER_SUPPLY_TURN_ON_DELAY - + (pd[port].last_state == + PD_STATE_SRC_DISCONNECTED_DEBOUNCE ? + PD_T_CC_DEBOUNCE : + 0), #else get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY, + PD_POWER_SUPPLY_TURN_ON_DELAY, #endif PD_STATE_SRC_DISCOVERY); } @@ -3504,25 +3416,25 @@ void pd_task(void *u) * partner, then start NoResponseTimer. */ if (pd_capable(port)) - set_state_timeout(port, + set_state_timeout( + port, get_time().val + - PD_T_NO_RESPONSE, + PD_T_NO_RESPONSE, hard_reset_count < - PD_HARD_RESET_COUNT ? - PD_STATE_HARD_RESET_SEND : - PD_STATE_SRC_DISCONNECTED); + PD_HARD_RESET_COUNT ? + PD_STATE_HARD_RESET_SEND : + PD_STATE_SRC_DISCONNECTED); } /* Send source cap some minimum number of times */ - if (caps_count < PD_CAPS_COUNT && - next_src_cap <= now.val) { + if (caps_count < PD_CAPS_COUNT && + next_src_cap <= now.val) { /* Query capabilities of the other side */ res = send_source_cap(port, AMS_START); /* packet was acked => PD capable device) */ if (res >= 0) { - set_state(port, - PD_STATE_SRC_NEGOCIATE); - timeout = 10*MSEC; + set_state(port, PD_STATE_SRC_NEGOCIATE); + timeout = 10 * MSEC; hard_reset_count = 0; caps_count = 0; /* Port partner is PD capable */ @@ -3530,8 +3442,8 @@ void pd_task(void *u) PD_FLAGS_PREVIOUS_PD_CONN; } else { /* failed, retry later */ timeout = PD_T_SEND_SOURCE_CAP; - next_src_cap = now.val + - PD_T_SEND_SOURCE_CAP; + next_src_cap = + now.val + PD_T_SEND_SOURCE_CAP; caps_count++; } } else if (caps_count < PD_CAPS_COUNT) { @@ -3543,17 +3455,16 @@ void pd_task(void *u) if (pd[port].last_state != pd[port].task_state) set_state_timeout(port, get_time().val + - PD_T_SENDER_RESPONSE, + PD_T_SENDER_RESPONSE, PD_STATE_HARD_RESET_SEND); break; case PD_STATE_SRC_ACCEPTED: /* Accept sent, wait for enabling the new voltage */ if (pd[port].last_state != pd[port].task_state) - set_state_timeout( - port, - get_time().val + - PD_T_SINK_TRANSITION, - PD_STATE_SRC_POWERED); + set_state_timeout(port, + get_time().val + + PD_T_SINK_TRANSITION, + PD_STATE_SRC_POWERED); break; case PD_STATE_SRC_POWERED: /* Switch to the new requested voltage */ @@ -3563,7 +3474,7 @@ void pd_task(void *u) set_state_timeout( port, get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY, + PD_POWER_SUPPLY_TURN_ON_DELAY, PD_STATE_SRC_TRANSITION); } break; @@ -3571,7 +3482,7 @@ void pd_task(void *u) /* the voltage output is good, notify the source */ res = send_control(port, PD_CTRL_PS_RDY); if (res >= 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* * Give the sink some time to send any messages @@ -3584,8 +3495,8 @@ void pd_task(void *u) * SRC_READY state. */ pd[port].ready_state_holdoff_timer = - get_time().val + SRC_READY_HOLD_OFF_US - + (get_time().le.lo & 0xf) * 12 * MSEC; + get_time().val + SRC_READY_HOLD_OFF_US + + (get_time().le.lo & 0xf) * 12 * MSEC; /* it's time to ping regularly the sink */ set_state(port, PD_STATE_SRC_READY); @@ -3621,8 +3532,7 @@ void pd_task(void *u) if (pd[port].flags & PD_FLAGS_UPDATE_SRC_CAPS) { res = send_source_cap(port, AMS_START); if (res >= 0) { - set_state(port, - PD_STATE_SRC_NEGOCIATE); + set_state(port, PD_STATE_SRC_NEGOCIATE); pd[port].flags &= ~PD_FLAGS_UPDATE_SRC_CAPS; } @@ -3632,12 +3542,16 @@ void pd_task(void *u) /* Send get sink cap if haven't received it yet */ if (!(pd[port].flags & PD_FLAGS_SNK_CAP_RECVD)) { if (++snk_cap_count <= PD_SNK_CAP_RETRIES) { - /* Get sink cap to know if dual-role device */ - send_control(port, PD_CTRL_GET_SINK_CAP); - set_state(port, PD_STATE_SRC_GET_SINK_CAP); + /* Get sink cap to know if dual-role + * device */ + send_control(port, + PD_CTRL_GET_SINK_CAP); + set_state(port, + PD_STATE_SRC_GET_SINK_CAP); break; } else if (debug_level >= 2 && - snk_cap_count == PD_SNK_CAP_RETRIES+1) { + snk_cap_count == + PD_SNK_CAP_RETRIES + 1) { CPRINTF("C%d ERR SNK_CAP\n", port); } } @@ -3649,7 +3563,6 @@ void pd_task(void *u) pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE; } - /* Check data role policy, which may trigger a swap */ if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) { pd_check_dr_role(port, pd[port].data_role, @@ -3668,8 +3581,7 @@ void pd_task(void *u) * initiate or receive a request an exchange * of VCONN Source. */ - pd_try_execute_vconn_swap(port, - pd[port].flags); + pd_try_execute_vconn_swap(port, pd[port].flags); pd[port].flags &= ~PD_FLAGS_CHECK_VCONN_STATE; break; } @@ -3685,15 +3597,6 @@ void pd_task(void *u) break; } - /* - * Enter_USB if port partner and cable are - * USB4 compatible. - */ - if (should_enter_usb4_mode(port)) { - pd_send_enter_usb(port, &timeout); - break; - } - if (!(pd[port].flags & PD_FLAGS_PING_ENABLED)) break; @@ -3710,28 +3613,30 @@ void pd_task(void *u) if (pd[port].last_state != pd[port].task_state) set_state_timeout(port, get_time().val + - PD_T_SENDER_RESPONSE, + PD_T_SENDER_RESPONSE, PD_STATE_SRC_READY); break; case PD_STATE_DR_SWAP: if (pd[port].last_state != pd[port].task_state) { res = send_control(port, PD_CTRL_DR_SWAP); if (res < 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* * If failed to get goodCRC, send * soft reset, otherwise ignore * failure. */ - set_state(port, res == -1 ? - PD_STATE_SOFT_RESET : - READY_RETURN_STATE(port)); + set_state(port, + res == -1 ? + PD_STATE_SOFT_RESET : + READY_RETURN_STATE( + port)); break; } /* Wait for accept or reject */ set_state_timeout(port, get_time().val + - PD_T_SENDER_RESPONSE, + PD_T_SENDER_RESPONSE, READY_RETURN_STATE(port)); } break; @@ -3740,31 +3645,32 @@ void pd_task(void *u) if (pd[port].last_state != pd[port].task_state) { res = send_control(port, PD_CTRL_PR_SWAP); if (res < 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* * If failed to get goodCRC, send * soft reset, otherwise ignore * failure. */ - set_state(port, res == -1 ? - PD_STATE_SOFT_RESET : - PD_STATE_SRC_READY); + set_state(port, + res == -1 ? + PD_STATE_SOFT_RESET : + PD_STATE_SRC_READY); break; } /* Wait for accept or reject */ set_state_timeout(port, get_time().val + - PD_T_SENDER_RESPONSE, + PD_T_SENDER_RESPONSE, PD_STATE_SRC_READY); } break; case PD_STATE_SRC_SWAP_SNK_DISABLE: /* Give time for sink to stop drawing current */ if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, - get_time().val + - PD_T_SINK_TRANSITION, - PD_STATE_SRC_SWAP_SRC_DISABLE); + set_state_timeout( + port, + get_time().val + PD_T_SINK_TRANSITION, + PD_STATE_SRC_SWAP_SRC_DISABLE); break; case PD_STATE_SRC_SWAP_SRC_DISABLE: if (pd[port].last_state != pd[port].task_state) { @@ -3787,10 +3693,11 @@ void pd_task(void *u) /* Inform TCPC of power role update. */ pd_update_roles(port); - set_state_timeout(port, - get_time().val + - PD_POWER_SUPPLY_TURN_OFF_DELAY, - PD_STATE_SRC_SWAP_STANDBY); + set_state_timeout( + port, + get_time().val + + PD_POWER_SUPPLY_TURN_OFF_DELAY, + PD_STATE_SRC_SWAP_STANDBY); } break; case PD_STATE_SRC_SWAP_STANDBY: @@ -3799,7 +3706,7 @@ void pd_task(void *u) /* Send PS_RDY */ res = send_control(port, PD_CTRL_PS_RDY); if (res < 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; set_state(port, PD_STATE_SRC_DISCONNECTED); break; @@ -3807,7 +3714,7 @@ void pd_task(void *u) /* Wait for PS_RDY from new source */ set_state_timeout(port, get_time().val + - PD_T_PS_SOURCE_ON, + PD_T_PS_SOURCE_ON, PD_STATE_SNK_DISCONNECTED); } break; @@ -3858,8 +3765,8 @@ void pd_task(void *u) /* Set the CC termination and state back to default */ tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ? - TYPEC_CC_RP : - TYPEC_CC_RD); + TYPEC_CC_RP : + TYPEC_CC_RD); set_state(port, PD_DEFAULT_STATE(port)); tcpc_prints("resumed!", port); #endif @@ -3867,12 +3774,13 @@ void pd_task(void *u) } case PD_STATE_SNK_DISCONNECTED: #ifdef CONFIG_USB_PD_LOW_POWER - timeout = (drp_state[port] != - PD_DRP_TOGGLE_ON ? SECOND : 10*MSEC); + timeout = (drp_state[port] != PD_DRP_TOGGLE_ON ? + SECOND : + 10 * MSEC); #else - timeout = 10*MSEC; + timeout = 10 * MSEC; #endif - + pd_set_src_caps(port, 0, NULL); #ifdef CONFIG_USB_PD_TCPC_LOW_POWER /* * If SW decided we should be in a low power state and @@ -3894,11 +3802,10 @@ void pd_task(void *u) */ if (auto_toggle_supported && !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) && - !is_try_src(port) && - cc_is_open(cc1, cc2) && - (drp_state[port] == PD_DRP_TOGGLE_ON)) { + !is_try_src(port) && cc_is_open(cc1, cc2) && + (drp_state[port] == PD_DRP_TOGGLE_ON)) { set_state(port, PD_STATE_DRP_AUTO_TOGGLE); - timeout = 2*MSEC; + timeout = 2 * MSEC; break; } #endif @@ -3908,11 +3815,11 @@ void pd_task(void *u) pd[port].cc_state = PD_CC_NONE; hard_reset_count = 0; new_cc_state = PD_CC_NONE; - pd[port].cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; + pd[port].cc_debounce = + get_time().val + PD_T_CC_DEBOUNCE; set_state(port, - PD_STATE_SNK_DISCONNECTED_DEBOUNCE); - timeout = 10*MSEC; + PD_STATE_SNK_DISCONNECTED_DEBOUNCE); + timeout = 10 * MSEC; break; } @@ -3946,7 +3853,7 @@ void pd_task(void *u) #endif /* Swap states quickly */ - timeout = 2*MSEC; + timeout = 2 * MSEC; break; } @@ -3957,7 +3864,7 @@ void pd_task(void *u) * CC status. */ pd[port].flags |= PD_FLAGS_LPM_REQUESTED; -#endif/* CONFIG_USB_PD_TCPC_LOW_POWER */ +#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */ break; case PD_STATE_SNK_DISCONNECTED_DEBOUNCE: @@ -3971,16 +3878,16 @@ void pd_task(void *u) } else { /* No connection any more */ set_state(port, PD_STATE_SNK_DISCONNECTED); - timeout = 5*MSEC; + timeout = 5 * MSEC; break; } - timeout = 20*MSEC; + timeout = 20 * MSEC; /* Debounce the cc state */ if (new_cc_state != pd[port].cc_state) { - pd[port].cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; + pd[port].cc_debounce = + get_time().val + PD_T_CC_DEBOUNCE; pd[port].cc_state = new_cc_state; break; } @@ -3995,14 +3902,14 @@ void pd_task(void *u) * If TRY_SRC is enabled, but not active, * then force attempt to connect as source. */ - pd[port].try_src_marker = get_time().val - + PD_T_DRP_TRY; - pd[port].try_timeout = get_time().val - + PD_T_TRY_TIMEOUT; + pd[port].try_src_marker = + get_time().val + PD_T_DRP_TRY; + pd[port].try_timeout = + get_time().val + PD_T_TRY_TIMEOUT; /* Swap roles to source */ pd_set_power_role(port, PD_ROLE_SOURCE); tcpm_set_cc(port, TYPEC_CC_RP); - timeout = 2*MSEC; + timeout = 2 * MSEC; set_state(port, PD_STATE_SRC_DISCONNECTED); /* Set flag after the state change */ pd[port].flags |= PD_FLAGS_TRY_SRC; @@ -4013,7 +3920,7 @@ void pd_task(void *u) if (IS_ENABLED(CONFIG_COMMON_RUNTIME)) hook_notify(HOOK_USB_PD_CONNECT); pd[port].polarity = get_snk_polarity(cc1, cc2); - pd_set_polarity(port, pd[port].polarity); + typec_set_polarity(port, pd[port].polarity); /* reset message ID on connection */ pd[port].msg_id = 0; /* initial data role for sink is UFP */ @@ -4023,9 +3930,17 @@ void pd_task(void *u) #if defined(CONFIG_CHARGE_MANAGER) typec_curr = usb_get_typec_current_limit( pd[port].polarity, cc1, cc2); - typec_set_input_current_limit( - port, typec_curr, TYPE_C_VOLTAGE); + typec_set_input_current_limit(port, typec_curr, + TYPE_C_VOLTAGE); #endif + +#ifdef CONFIG_USBC_PPC + /* Inform PPC that a source is connected. */ + ppc_dev_is_connected(port, PPC_DEV_SRC); +#endif /* CONFIG_USBC_PPC */ + if (IS_ENABLED(CONFIG_USBC_OCP)) + usbc_ocp_snk_is_connected(port, false); + /* If PD comm is enabled, enable TCPC RX */ if (pd_comm_is_enabled(port)) tcpm_set_rx_enable(port, 1); @@ -4036,14 +3951,11 @@ void pd_task(void *u) pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE | PD_FLAGS_CHECK_DR_ROLE | PD_FLAGS_CHECK_IDENTITY; - /* Reset cable attributes and flags */ - reset_pd_cable(port); - if (new_cc_state == PD_CC_DFP_DEBUG_ACC) pd[port].flags |= PD_FLAGS_TS_DTS_PARTNER; set_state(port, PD_STATE_SNK_DISCOVERY); - timeout = 10*MSEC; + timeout = 10 * MSEC; hook_call_deferred( &pd_usb_billboard_deferred_data, PD_T_AME); @@ -4052,58 +3964,66 @@ void pd_task(void *u) case PD_STATE_SNK_HARD_RESET_RECOVER: if (pd[port].last_state != pd[port].task_state) pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; -#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE - /* - * Can't measure vbus state so this is the maximum - * recovery time for the source. - */ - if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, get_time().val + - PD_T_SAFE_0V + - PD_T_SRC_RECOVER_MAX + - PD_T_SRC_TURN_ON, - PD_STATE_SNK_DISCONNECTED); -#else - /* Wait for VBUS to go low and then high*/ - if (pd[port].last_state != pd[port].task_state) { - snk_hard_reset_vbus_off = 0; - set_state_timeout(port, - get_time().val + - PD_T_SAFE_0V, - hard_reset_count < - PD_HARD_RESET_COUNT ? - PD_STATE_HARD_RESET_SEND : - PD_STATE_SNK_DISCOVERY); - } - if (!pd_is_vbus_present(port) && - !snk_hard_reset_vbus_off) { - /* VBUS has gone low, reset timeout */ - snk_hard_reset_vbus_off = 1; - set_state_timeout(port, - get_time().val + - PD_T_SRC_RECOVER_MAX + - PD_T_SRC_TURN_ON, - PD_STATE_SNK_DISCONNECTED); - } - if (pd_is_vbus_present(port) && - snk_hard_reset_vbus_off) { - /* VBUS went high again */ - set_state(port, PD_STATE_SNK_DISCOVERY); - timeout = 10*MSEC; - } + if (get_usb_pd_vbus_detect() == + USB_PD_VBUS_DETECT_NONE) { + /* + * Can't measure vbus state so this is the + * maximum recovery time for the source. + */ + if (pd[port].last_state != pd[port].task_state) + set_state_timeout( + port, + get_time().val + PD_T_SAFE_0V + + PD_T_SRC_RECOVER_MAX + + PD_T_SRC_TURN_ON, + PD_STATE_SNK_DISCONNECTED); + } else { +#ifndef CONFIG_USB_PD_VBUS_DETECT_NONE + /* Wait for VBUS to go low and then high*/ + if (pd[port].last_state != + pd[port].task_state) { + snk_hard_reset_vbus_off = 0; + set_state_timeout( + port, + get_time().val + PD_T_SAFE_0V, + hard_reset_count < + PD_HARD_RESET_COUNT ? + PD_STATE_HARD_RESET_SEND : + PD_STATE_SNK_DISCOVERY); + } - /* - * Don't need to set timeout because VBUS changing - * will trigger an interrupt and wake us up. - */ + if (!pd_is_vbus_present(port) && + !snk_hard_reset_vbus_off) { + /* VBUS has gone low, reset timeout */ + snk_hard_reset_vbus_off = 1; + set_state_timeout( + port, + get_time().val + + PD_T_SRC_RECOVER_MAX + + PD_T_SRC_TURN_ON, + PD_STATE_SNK_DISCONNECTED); + } + if (pd_is_vbus_present(port) && + snk_hard_reset_vbus_off) { + /* VBUS went high again */ + set_state(port, PD_STATE_SNK_DISCOVERY); + timeout = 10 * MSEC; + } + + /* + * Don't need to set timeout because VBUS + * changing will trigger an interrupt and + * wake us up. + */ #endif + } break; case PD_STATE_SNK_DISCOVERY: /* Wait for source cap expired only if we are enabled */ - if ((pd[port].last_state != pd[port].task_state) - && pd_comm_is_enabled(port)) { -#ifdef CONFIG_USB_PD_TCPM_TCPCI + if ((pd[port].last_state != pd[port].task_state) && + pd_comm_is_enabled(port)) { +#if defined(CONFIG_USB_PD_TCPM_TCPCI) || defined(CONFIG_USB_PD_TCPM_STUB) /* * If we come from hard reset recover state, * then we can process the source capabilities @@ -4113,7 +4033,7 @@ void pd_task(void *u) if (pd[port].last_state == PD_STATE_SNK_HARD_RESET_RECOVER) tcpm_set_rx_enable(port, 1); -#endif /* CONFIG_USB_PD_TCPM_TCPCI */ +#endif /* CONFIG_USB_PD_TCPM_TCPCI || CONFIG_USB_PD_TCPM_STUB */ #ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC /* * If the battery has not met a configured safe @@ -4125,57 +4045,64 @@ void pd_task(void *u) */ int batt_soc = usb_get_battery_soc(); - if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC || - battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED) + if (batt_soc < + CONFIG_USB_PD_RESET_MIN_BATT_SOC || + battery_get_disconnect_state() != + BATTERY_NOT_DISCONNECTED) pd[port].flags |= - PD_FLAGS_SNK_WAITING_BATT; + PD_FLAGS_SNK_WAITING_BATT; else pd[port].flags &= - ~PD_FLAGS_SNK_WAITING_BATT; + ~PD_FLAGS_SNK_WAITING_BATT; #endif if (pd[port].flags & - PD_FLAGS_SNK_WAITING_BATT) { + PD_FLAGS_SNK_WAITING_BATT) { #ifdef CONFIG_CHARGE_MANAGER /* * Configure this port as dedicated for * now, so it won't be de-selected by * the charge manager leaving safe mode. */ - charge_manager_update_dualrole(port, - CAP_DEDICATED); + charge_manager_update_dualrole( + port, CAP_DEDICATED); #endif CPRINTS("C%d: Battery low. " - "Hold reset timer", port); - /* - * If VBUS has never been low, and we timeout - * waiting for source cap, try a soft reset - * first, in case we were already in a stable - * contract before this boot. - */ + "Hold reset timer", + port); + /* + * If VBUS has never been low, and we + * timeout waiting for source cap, try a + * soft reset first, in case we were + * already in a stable contract before + * this boot. + */ } else if (pd[port].flags & - PD_FLAGS_VBUS_NEVER_LOW) { - set_state_timeout(port, - get_time().val + - PD_T_SINK_WAIT_CAP, - PD_STATE_SOFT_RESET); - /* - * If we haven't passed hard reset counter, - * start SinkWaitCapTimer, otherwise start - * NoResponseTimer. - */ + PD_FLAGS_VBUS_NEVER_LOW) { + set_state_timeout( + port, + get_time().val + + PD_T_SINK_WAIT_CAP, + PD_STATE_SOFT_RESET); + /* + * If we haven't passed hard reset + * counter, start SinkWaitCapTimer, + * otherwise start NoResponseTimer. + */ } else if (hard_reset_count < - PD_HARD_RESET_COUNT) { - set_state_timeout(port, - get_time().val + - PD_T_SINK_WAIT_CAP, - PD_STATE_HARD_RESET_SEND); + PD_HARD_RESET_COUNT) { + set_state_timeout( + port, + get_time().val + + PD_T_SINK_WAIT_CAP, + PD_STATE_HARD_RESET_SEND); } else if (pd_capable(port)) { /* ErrorRecovery */ - set_state_timeout(port, - get_time().val + - PD_T_NO_RESPONSE, - PD_STATE_SNK_DISCONNECTED); + set_state_timeout( + port, + get_time().val + + PD_T_NO_RESPONSE, + PD_STATE_SNK_DISCONNECTED); } #if defined(CONFIG_CHARGE_MANAGER) /* @@ -4195,17 +4122,17 @@ void pd_task(void *u) /* Check if CC pull-up has changed */ tcpm_get_cc(port, &cc1, &cc2); - if (typec_curr != usb_get_typec_current_limit( - pd[port].polarity, cc1, cc2)) { + if (typec_curr != + usb_get_typec_current_limit(pd[port].polarity, cc1, + cc2)) { /* debounce signal by requiring two reads */ if (typec_curr_change) { /* set new input current limit */ - typec_curr = - usb_get_typec_current_limit( - pd[port].polarity, - cc1, cc2); + typec_curr = usb_get_typec_current_limit( + pd[port].polarity, cc1, cc2); typec_set_input_current_limit( - port, typec_curr, TYPE_C_VOLTAGE); + port, typec_curr, + TYPE_C_VOLTAGE); } else { /* delay for debounce */ timeout = PD_T_DEBOUNCE; @@ -4223,7 +4150,7 @@ void pd_task(void *u) hard_reset_count = 0; set_state_timeout(port, get_time().val + - PD_T_SENDER_RESPONSE, + PD_T_SENDER_RESPONSE, PD_STATE_HARD_RESET_SEND); } break; @@ -4232,11 +4159,11 @@ void pd_task(void *u) if (pd[port].last_state != pd[port].task_state) set_state_timeout(port, get_time().val + - PD_T_PS_TRANSITION, + PD_T_PS_TRANSITION, PD_STATE_HARD_RESET_SEND); break; case PD_STATE_SNK_READY: - timeout = 20*MSEC; + timeout = 20 * MSEC; /* * Don't send any traffic yet until our holdoff timer @@ -4291,52 +4218,43 @@ void pd_task(void *u) * initiate or receive a request an exchange * of VCONN Source. */ - pd_try_execute_vconn_swap(port, - pd[port].flags); + pd_try_execute_vconn_swap(port, pd[port].flags); pd[port].flags &= ~PD_FLAGS_CHECK_VCONN_STATE; break; } /* If DFP, send discovery SVDMs */ if (pd[port].data_role == PD_ROLE_DFP && - (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { + (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) { pd_send_vdm(port, USB_SID_PD, CMD_DISCOVER_IDENT, NULL, 0); pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY; break; } - /* - * Enter_USB if port partner and cable are - * USB4 compatible. - */ - if (should_enter_usb4_mode(port)) { - pd_send_enter_usb(port, &timeout); - break; - } - /* Sent all messages, don't need to wake very often */ - timeout = 200*MSEC; + timeout = 200 * MSEC; break; case PD_STATE_SNK_SWAP_INIT: if (pd[port].last_state != pd[port].task_state) { res = send_control(port, PD_CTRL_PR_SWAP); if (res < 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* * If failed to get goodCRC, send * soft reset, otherwise ignore * failure. */ - set_state(port, res == -1 ? - PD_STATE_SOFT_RESET : - PD_STATE_SNK_READY); + set_state(port, + res == -1 ? + PD_STATE_SOFT_RESET : + PD_STATE_SNK_READY); break; } /* Wait for accept or reject */ set_state_timeout(port, get_time().val + - PD_T_SENDER_RESPONSE, + PD_T_SENDER_RESPONSE, PD_STATE_SNK_READY); } break; @@ -4345,19 +4263,18 @@ void pd_task(void *u) pd_set_input_current_limit(port, 0, 0); #ifdef CONFIG_CHARGE_MANAGER typec_set_input_current_limit(port, 0, 0); - charge_manager_set_ceil(port, - CEIL_REQUESTOR_PD, + charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, CHARGE_CEIL_NONE); #endif set_state(port, PD_STATE_SNK_SWAP_SRC_DISABLE); - timeout = 10*MSEC; + timeout = 10 * MSEC; break; case PD_STATE_SNK_SWAP_SRC_DISABLE: /* Wait for PS_RDY */ if (pd[port].last_state != pd[port].task_state) set_state_timeout(port, get_time().val + - PD_T_PS_SOURCE_OFF, + PD_T_PS_SOURCE_OFF, PD_STATE_HARD_RESET_SEND); break; case PD_STATE_SNK_SWAP_STANDBY: @@ -4367,7 +4284,7 @@ void pd_task(void *u) if (pd_set_power_supply_ready(port)) { /* Restore Rd */ tcpm_set_cc(port, TYPEC_CC_RD); - timeout = 10*MSEC; + timeout = 10 * MSEC; set_state(port, PD_STATE_SNK_DISCONNECTED); break; @@ -4376,7 +4293,7 @@ void pd_task(void *u) set_state_timeout( port, get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY, + PD_POWER_SUPPLY_TURN_ON_DELAY, PD_STATE_SNK_SWAP_COMPLETE); } break; @@ -4393,34 +4310,36 @@ void pd_task(void *u) } /* Don't send GET_SINK_CAP on swap */ - snk_cap_count = PD_SNK_CAP_RETRIES+1; + snk_cap_count = PD_SNK_CAP_RETRIES + 1; caps_count = 0; pd[port].msg_id = 0; pd_set_power_role(port, PD_ROLE_SOURCE); pd_update_roles(port); set_state(port, PD_STATE_SRC_DISCOVERY); - timeout = 10*MSEC; + timeout = 10 * MSEC; break; #ifdef CONFIG_USBC_VCONN_SWAP case PD_STATE_VCONN_SWAP_SEND: if (pd[port].last_state != pd[port].task_state) { res = send_control(port, PD_CTRL_VCONN_SWAP); if (res < 0) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* * If failed to get goodCRC, send * soft reset, otherwise ignore * failure. */ - set_state(port, res == -1 ? - PD_STATE_SOFT_RESET : - READY_RETURN_STATE(port)); + set_state(port, + res == -1 ? + PD_STATE_SOFT_RESET : + READY_RETURN_STATE( + port)); break; } /* Wait for accept or reject */ set_state_timeout(port, get_time().val + - PD_T_SENDER_RESPONSE, + PD_T_SENDER_RESPONSE, READY_RETURN_STATE(port)); } break; @@ -4429,13 +4348,17 @@ void pd_task(void *u) if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) { /* Turn VCONN on and wait for it */ set_vconn(port, 1); - set_state_timeout(port, - get_time().val + PD_VCONN_SWAP_DELAY, - PD_STATE_VCONN_SWAP_READY); + set_state_timeout( + port, + get_time().val + + CONFIG_USBC_VCONN_SWAP_DELAY_US, + PD_STATE_VCONN_SWAP_READY); } else { - set_state_timeout(port, - get_time().val + PD_T_VCONN_SOURCE_ON, - READY_RETURN_STATE(port)); + set_state_timeout( + port, + get_time().val + + PD_T_VCONN_SOURCE_ON, + READY_RETURN_STATE(port)); } } break; @@ -4448,7 +4371,7 @@ void pd_task(void *u) res = send_control(port, PD_CTRL_PS_RDY); if (res == -1) { - timeout = 10*MSEC; + timeout = 10 * MSEC; /* * If failed to get goodCRC, * send soft reset @@ -4464,9 +4387,11 @@ void pd_task(void *u) set_vconn(port, 0); pd_set_vconn_role(port, PD_ROLE_VCONN_OFF); - set_state_timeout(port, - get_time().val + PD_VCONN_SWAP_DELAY, - READY_RETURN_STATE(port)); + set_state_timeout( + port, + get_time().val + + CONFIG_USBC_VCONN_SWAP_DELAY_US, + READY_RETURN_STATE(port)); } } break; @@ -4483,14 +4408,14 @@ void pd_task(void *u) if (res < 0) { set_state(port, PD_STATE_HARD_RESET_SEND); - timeout = 5*MSEC; + timeout = 5 * MSEC; break; } - set_state_timeout( - port, - get_time().val + PD_T_SENDER_RESPONSE, - PD_STATE_HARD_RESET_SEND); + set_state_timeout(port, + get_time().val + + PD_T_SENDER_RESPONSE, + PD_STATE_HARD_RESET_SEND); } break; case PD_STATE_HARD_RESET_SEND: @@ -4521,8 +4446,8 @@ void pd_task(void *u) if (hard_reset_sent) break; - if (pd_transmit(port, TCPC_TX_HARD_RESET, 0, NULL, - AMS_START) < 0) { + if (pd_transmit(port, TCPCI_MSG_TX_HARD_RESET, 0, NULL, + AMS_START) < 0) { /* * likely a non-idle channel * TCPCI r2.0 v1.0 4.4.15: @@ -4559,7 +4484,8 @@ void pd_task(void *u) */ if (pd[port].power_role == PD_ROLE_SOURCE) { set_state_timeout(port, - get_time().val + PD_T_PS_HARD_RESET, + get_time().val + + PD_T_PS_HARD_RESET, PD_STATE_HARD_RESET_EXECUTE); } else { set_state(port, PD_STATE_HARD_RESET_EXECUTE); @@ -4578,32 +4504,31 @@ void pd_task(void *u) /* reset our own state machine */ pd_execute_hard_reset(port); - timeout = 10*MSEC; + timeout = 10 * MSEC; break; #ifdef CONFIG_COMMON_RUNTIME case PD_STATE_BIST_RX: send_bist_cmd(port); /* Delay at least enough for partner to finish BIST */ - timeout = PD_T_BIST_RECEIVE + 20*MSEC; + timeout = PD_T_BIST_RECEIVE + 20 * MSEC; /* Set to appropriate port disconnected state */ - set_state(port, DUAL_ROLE_IF_ELSE(port, - PD_STATE_SNK_DISCONNECTED, + set_state(port, DUAL_ROLE_IF_ELSE( + port, PD_STATE_SNK_DISCONNECTED, PD_STATE_SRC_DISCONNECTED)); break; case PD_STATE_BIST_TX: - pd_transmit(port, TCPC_TX_BIST_MODE_2, 0, NULL, + pd_transmit(port, TCPCI_MSG_TX_BIST_MODE_2, 0, NULL, AMS_START); /* Delay at least enough to finish sending BIST */ - timeout = PD_T_BIST_TRANSMIT + 20*MSEC; + timeout = PD_T_BIST_TRANSMIT + 20 * MSEC; /* Set to appropriate port disconnected state */ - set_state(port, DUAL_ROLE_IF_ELSE(port, - PD_STATE_SNK_DISCONNECTED, + set_state(port, DUAL_ROLE_IF_ELSE( + port, PD_STATE_SNK_DISCONNECTED, PD_STATE_SRC_DISCONNECTED)); break; #endif #ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE - case PD_STATE_DRP_AUTO_TOGGLE: - { + case PD_STATE_DRP_AUTO_TOGGLE: { enum pd_drp_next_states next_state; assert(auto_toggle_supported); @@ -4646,10 +4571,8 @@ void pd_task(void *u) tcpm_get_cc(port, &cc1, &cc2); next_state = drp_auto_toggle_next_state( - &pd[port].drp_sink_time, - pd[port].power_role, - drp_state[port], - cc1, cc2, false); + &pd[port].drp_sink_time, pd[port].power_role, + drp_state[port], cc1, cc2, false); #ifdef CONFIG_USB_PD_TCPC_LOW_POWER /* @@ -4663,7 +4586,7 @@ void pd_task(void *u) #endif if (next_state == DRP_TC_DEFAULT) { if (PD_DEFAULT_STATE(port) == - PD_STATE_SNK_DISCONNECTED) + PD_STATE_SNK_DISCONNECTED) next_state = DRP_TC_UNATTACHED_SNK; else next_state = DRP_TC_UNATTACHED_SRC; @@ -4682,7 +4605,7 @@ void pd_task(void *u) tcpm_set_cc(port, TYPEC_CC_RD); pd_set_power_role(port, PD_ROLE_SINK); - timeout = 2*MSEC; + timeout = 2 * MSEC; set_state(port, PD_STATE_SNK_DISCONNECTED); } else if (next_state == DRP_TC_UNATTACHED_SRC) { /* @@ -4697,7 +4620,7 @@ void pd_task(void *u) tcpm_set_cc(port, TYPEC_CC_RP); pd_set_power_role(port, PD_ROLE_SOURCE); - timeout = 2*MSEC; + timeout = 2 * MSEC; set_state(port, PD_STATE_SRC_DISCONNECTED); } else { /* @@ -4712,13 +4635,6 @@ void pd_task(void *u) break; } #endif - case PD_STATE_ENTER_USB: - if (pd[port].last_state != pd[port].task_state) { - set_state_timeout(port, - get_time().val + PD_T_SENDER_RESPONSE, - READY_RETURN_STATE(port)); - } - break; default: break; } @@ -4734,7 +4650,8 @@ void pd_task(void *u) if (now.val >= pd[port].timeout) { set_state(port, pd[port].timeout_state); /* On a state timeout, run next state soon */ - timeout = timeout < 10*MSEC ? timeout : 10*MSEC; + timeout = timeout < 10 * MSEC ? timeout : + 10 * MSEC; } else if (pd[port].timeout - now.val < timeout) { timeout = pd[port].timeout - now.val; } @@ -4776,12 +4693,12 @@ void pd_task(void *u) if (pd[port].power_role == PD_ROLE_SOURCE) { /* Source: detect disconnect by monitoring CC */ tcpm_get_cc(port, &cc1, &cc2); - if (pd[port].polarity) + if (polarity_rm_dts(pd[port].polarity)) cc1 = cc2; if (cc1 == TYPEC_CC_VOLT_OPEN) { set_state(port, PD_STATE_SRC_DISCONNECTED); /* Debouncing */ - timeout = 10*MSEC; + timeout = 10 * MSEC; #ifdef CONFIG_USB_PD_DUAL_ROLE /* * If Try.SRC is configured, then ATTACHED_SRC @@ -4793,8 +4710,8 @@ void pd_task(void *u) pd_set_power_role(port, PD_ROLE_SINK); tcpm_set_cc(port, TYPEC_CC_RD); /* Set timer for TryWait.SNK state */ - pd[port].try_src_marker = get_time().val - + PD_T_DEBOUNCE; + pd[port].try_src_marker = + get_time().val + PD_T_DEBOUNCE; /* Advance to TryWait.SNK state */ set_state(port, PD_STATE_SNK_DISCONNECTED); @@ -4819,7 +4736,7 @@ void pd_task(void *u) /* Sink: detect disconnect by monitoring VBUS */ set_state(port, PD_STATE_SNK_DISCONNECTED); /* set timeout small to reconnect fast */ - timeout = 5*MSEC; + timeout = 5 * MSEC; } #endif /* CONFIG_USB_PD_DUAL_ROLE */ } @@ -4860,12 +4777,9 @@ static void pd_chipset_startup(void) for (i = 0; i < board_get_usb_pd_port_count(); i++) { pd_set_dual_role_no_wakeup(i, PD_DRP_TOGGLE_OFF); pd[i].flags |= PD_FLAGS_CHECK_IDENTITY; - /* Reset cable attributes and flags */ - reset_pd_cable(i); task_set_event(PD_PORT_TO_TASK_ID(i), PD_EVENT_POWER_STATE_CHANGE | - PD_EVENT_UPDATE_DUAL_ROLE, - 0); + PD_EVENT_UPDATE_DUAL_ROLE); } CPRINTS("PD:S5->S3"); } @@ -4879,8 +4793,7 @@ static void pd_chipset_shutdown(void) pd_set_dual_role_no_wakeup(i, PD_DRP_FORCE_SINK); task_set_event(PD_PORT_TO_TASK_ID(i), PD_EVENT_POWER_STATE_CHANGE | - PD_EVENT_UPDATE_DUAL_ROLE, - 0); + PD_EVENT_UPDATE_DUAL_ROLE); } CPRINTS("PD:S3->S5"); } @@ -4947,24 +4860,29 @@ int pd_is_port_enabled(int port) } } +void pd_set_error_recovery(int port) +{ + /* No-op for linking. Can be implemented later if necessary */ +} + #if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) void pd_send_hpd(int port, enum hpd_event hpd) { uint32_t data[1]; - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); if (!opos) return; - data[0] = VDO_DP_STATUS((hpd == hpd_irq), /* IRQ_HPD */ - (hpd != hpd_low), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - 0, /* MF pref */ - 1, /* enabled */ - 0, /* power low */ + data[0] = VDO_DP_STATUS((hpd == hpd_irq), /* IRQ_HPD */ + (hpd != hpd_low), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ + 1, /* enabled */ + 0, /* power low */ 0x2); - pd_send_vdm(port, USB_SID_DISPLAYPORT, - VDO_OPOS(opos) | CMD_ATTENTION, data, 1); + pd_send_vdm(port, USB_SID_DISPLAYPORT, VDO_OPOS(opos) | CMD_ATTENTION, + data, 1); /* Wait until VDM is done. */ while (pd[0].vdm_state > 0) task_wait_event(USB_PD_RX_TMOUT_US * @@ -4979,15 +4897,15 @@ int pd_fetch_acc_log_entry(int port) /* Cannot send a VDM now, the host should retry */ if (pd[port].vdm_state > 0) return pd[port].vdm_state == VDM_STATE_BUSY ? - EC_RES_BUSY : EC_RES_UNAVAILABLE; + EC_RES_BUSY : + EC_RES_UNAVAILABLE; pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_GET_LOG, NULL, 0); - timeout.val = get_time().val + 75*MSEC; + timeout.val = get_time().val + 75 * MSEC; /* Wait until VDM is done */ - while ((pd[port].vdm_state > 0) && - (get_time().val < timeout.val)) - task_wait_event(10*MSEC); + while ((pd[port].vdm_state > 0) && (get_time().val < timeout.val)) + task_wait_event(10 * MSEC); if (pd[port].vdm_state > 0) return EC_RES_TIMEOUT; @@ -5038,7 +4956,99 @@ void pd_update_contract(int port) #endif /* CONFIG_USB_PD_DUAL_ROLE */ -static int command_pd(int argc, char **argv) +#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) +int hex8tou32(char *str, uint32_t *val) +{ + char *ptr = str; + uint32_t tmp = 0; + + while (*ptr) { + char c = *ptr++; + + if (c >= '0' && c <= '9') + tmp = (tmp << 4) + (c - '0'); + else if (c >= 'A' && c <= 'F') + tmp = (tmp << 4) + (c - 'A' + 10); + else if (c >= 'a' && c <= 'f') + tmp = (tmp << 4) + (c - 'a' + 10); + else + return EC_ERROR_INVAL; + } + if (ptr != str + 8) + return EC_ERROR_INVAL; + *val = tmp; + return EC_SUCCESS; +} + +/* + * Flash a USB PD device using the ChromeOS Vendor Defined Command. + * + * @param argc number arguments in argv. Must be greater than 3. + * @param argv [1] is the usb port + * [2] unused + * [3] is the command {"erase", "rebooot", "signature", + * "info", "version", "write"} + * [4] if command was "write", then this will be the + * start of the data that will be written. + * @return EC_SUCCESS on success, else EC_ERROR_PARAM_COUNT or EC_ERROR_PARAM2 + * on failure. + */ +static int remote_flashing(int argc, char **argv) +{ + int port, cnt, cmd; + uint32_t data[VDO_MAX_SIZE - 1]; + char *e; + static int flash_offset[CONFIG_USB_PD_PORT_MAX_COUNT]; + + if (argc < 4 || argc > (VDO_MAX_SIZE + 4 - 1)) + return EC_ERROR_PARAM_COUNT; + + port = strtoi(argv[1], &e, 10); + if (*e || port >= board_get_usb_pd_port_count()) + return EC_ERROR_PARAM2; + + cnt = 0; + if (!strcasecmp(argv[3], "erase")) { + cmd = VDO_CMD_FLASH_ERASE; + flash_offset[port] = 0; + ccprintf("ERASE ..."); + } else if (!strcasecmp(argv[3], "reboot")) { + cmd = VDO_CMD_REBOOT; + ccprintf("REBOOT ..."); + } else if (!strcasecmp(argv[3], "signature")) { + cmd = VDO_CMD_ERASE_SIG; + ccprintf("ERASE SIG ..."); + } else if (!strcasecmp(argv[3], "info")) { + cmd = VDO_CMD_READ_INFO; + ccprintf("INFO..."); + } else if (!strcasecmp(argv[3], "version")) { + cmd = VDO_CMD_VERSION; + ccprintf("VERSION..."); + } else { + int i; + + argc -= 3; + for (i = 0; i < argc; i++) + if (hex8tou32(argv[i + 3], data + i)) + return EC_ERROR_INVAL; + cmd = VDO_CMD_FLASH_WRITE; + cnt = argc; + ccprintf("WRITE %d @%04x ...", argc * 4, flash_offset[port]); + flash_offset[port] += argc * 4; + } + + pd_send_vdm(port, USB_VID_GOOGLE, cmd, data, cnt); + + /* Wait until VDM is done */ + while (pd[port].vdm_state > 0) + task_wait_event(100 * MSEC); + + ccprintf("DONE %d\n", pd[port].vdm_state); + return EC_SUCCESS; +} +#endif /* defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) */ + +static int command_pd(int argc, const char **argv) { int port; char *e; @@ -5061,7 +5071,6 @@ static int command_pd(int argc, char **argv) return EC_SUCCESS; } - #ifdef CONFIG_CMD_PD #ifdef CONFIG_CMD_PD_DEV_DUMP_INFO else if (!strncasecmp(argv[1], "rwhashtable", 3)) { @@ -5163,6 +5172,8 @@ static int command_pd(int argc, char **argv) #endif else return EC_ERROR_PARAM3; + } else if (!strncasecmp(argv[2], "srccaps", 7)) { + pd_srccaps_dump(port); } else if (!strncasecmp(argv[2], "ping", 4)) { int enable; @@ -5174,8 +5185,8 @@ static int command_pd(int argc, char **argv) } ccprintf("Pings %s\n", - (pd[port].flags & PD_FLAGS_PING_ENABLED) ? - "on" : "off"); + (pd[port].flags & PD_FLAGS_PING_ENABLED) ? "on" : + "off"); } else if (!strncasecmp(argv[2], "vdm", 3)) { if (argc < 4) return EC_ERROR_PARAM_COUNT; @@ -5190,11 +5201,11 @@ static int command_pd(int argc, char **argv) pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_PING_ENABLE, &enable, 1); } else if (!strncasecmp(argv[3], "curr", 4)) { - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_CURRENT, - NULL, 0); + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_CURRENT, NULL, + 0); } else if (!strncasecmp(argv[3], "vers", 4)) { - pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_VERSION, - NULL, 0); + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_VERSION, NULL, + 0); } else { return EC_ERROR_PARAM_COUNT; } @@ -5233,8 +5244,7 @@ static int command_pd(int argc, char **argv) else if (!strcasecmp(argv[3], "sink")) pd_set_dual_role(port, PD_DRP_FORCE_SINK); else if (!strcasecmp(argv[3], "source")) - pd_set_dual_role(port, - PD_DRP_FORCE_SOURCE); + pd_set_dual_role(port, PD_DRP_FORCE_SOURCE); else return EC_ERROR_PARAM4; } @@ -5242,17 +5252,17 @@ static int command_pd(int argc, char **argv) #endif } else #endif - if (!strncasecmp(argv[2], "state", 5)) { + if (!strncasecmp(argv[2], "state", 5)) { ccprintf("Port C%d CC%d, %s - Role: %s-%s%s " "State: %d(%s), Flags: 0x%04x\n", - port, pd[port].polarity + 1, - pd_comm_is_enabled(port) ? "Ena" : "Dis", - pd[port].power_role == PD_ROLE_SOURCE ? "SRC" : "SNK", - pd[port].data_role == PD_ROLE_DFP ? "DFP" : "UFP", - (pd[port].flags & PD_FLAGS_VCONN_ON) ? "-VC" : "", - pd[port].task_state, - debug_level > 0 ? pd_get_task_state_name(port) : "", - pd[port].flags); + port, pd[port].polarity + 1, + pd_comm_is_enabled(port) ? "Ena" : "Dis", + pd[port].power_role == PD_ROLE_SOURCE ? "SRC" : "SNK", + pd[port].data_role == PD_ROLE_DFP ? "DFP" : "UFP", + (pd[port].flags & PD_FLAGS_VCONN_ON) ? "-VC" : "", + pd[port].task_state, + debug_level > 0 ? pd_get_task_state_name(port) : "", + pd[port].flags); } else { return EC_ERROR_PARAM1; } @@ -5280,7 +5290,7 @@ DECLARE_CONSOLE_COMMAND(pd, command_pd, "\n\t flash [erase|reboot|signature|info|version]" #endif /* CONFIG_CMD_PD_FLASH */ #endif /* CONFIG_USB_PD_DUAL_ROLE */ - , + "\n\t srccaps", "USB PD"); #ifdef HAS_TASK_HOSTCMD @@ -5300,9 +5310,8 @@ static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args) if (p->size + sizeof(*p) > args->params_size) return EC_RES_INVALID_PARAM; -#if defined(CONFIG_BATTERY) && \ - (defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ - defined(CONFIG_BATTERY_PRESENT_GPIO)) +#if defined(CONFIG_BATTERY) && (defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ + defined(CONFIG_BATTERY_PRESENT_GPIO)) /* * Do not allow PD firmware update if no battery and this port * is sinking power, because we will lose power. @@ -5340,7 +5349,7 @@ static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args) case USB_PD_FW_ERASE_SIG: pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0); - timeout.val = get_time().val + 500*MSEC; + timeout.val = get_time().val + 500 * MSEC; break; case USB_PD_FW_FLASH_WRITE: @@ -5352,12 +5361,12 @@ static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args) for (i = 0; i < size; i += VDO_MAX_SIZE - 1) { pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE, data + i, MIN(size - i, VDO_MAX_SIZE - 1)); - timeout.val = get_time().val + 500*MSEC; + timeout.val = get_time().val + 500 * MSEC; /* Wait until VDM is done */ while ((pd[port].vdm_state > 0) && (get_time().val < timeout.val)) - task_wait_event(10*MSEC); + task_wait_event(10 * MSEC); if (pd[port].vdm_state > 0) return EC_RES_TIMEOUT; @@ -5371,7 +5380,7 @@ static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args) /* Wait until VDM is done or timeout */ while ((pd[port].vdm_state > 0) && (get_time().val < timeout.val)) - task_wait_event(50*MSEC); + task_wait_event(50 * MSEC); if ((pd[port].vdm_state > 0) || (pd[port].vdm_state == VDM_STATE_ERR_TMOUT)) @@ -5381,12 +5390,8 @@ static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args) return rv; } -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE, - hc_remote_flash, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE, hc_remote_flash, EC_VER_MASK(0)); #endif /* CONFIG_HOSTCMD_FLASHPD */ #endif /* HAS_TASK_HOSTCMD */ - - #endif /* CONFIG_COMMON_RUNTIME */ diff --git a/common/usb_pd_tcpc.c b/common/usb_pd_tcpc.c index 2878e53574..a9a4d1d5a5 100644 --- a/common/usb_pd_tcpc.c +++ b/common/usb_pd_tcpc.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,17 +15,17 @@ #include "registers.h" #include "system.h" #include "task.h" -#include "tcpci.h" -#include "tcpm.h" +#include "tcpm/tcpci.h" +#include "tcpm/tcpm.h" #include "timer.h" -#include "util.h" #include "usb_pd.h" #include "usb_pd_config.h" #include "usb_pd_tcpm.h" +#include "util.h" #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) /* * Debug log level - higher number == more log @@ -45,93 +45,93 @@ static const int debug_level; #endif /* Encode 5 bits using Biphase Mark Coding */ -#define BMC(x) ((x & 1 ? 0x001 : 0x3FF) \ - ^ (x & 2 ? 0x004 : 0x3FC) \ - ^ (x & 4 ? 0x010 : 0x3F0) \ - ^ (x & 8 ? 0x040 : 0x3C0) \ - ^ (x & 16 ? 0x100 : 0x300)) +#define BMC(x) \ + ((x & 1 ? 0x001 : 0x3FF) ^ (x & 2 ? 0x004 : 0x3FC) ^ \ + (x & 4 ? 0x010 : 0x3F0) ^ (x & 8 ? 0x040 : 0x3C0) ^ \ + (x & 16 ? 0x100 : 0x300)) /* 4b/5b + Bimark Phase encoding */ static const uint16_t bmc4b5b[] = { -/* 0 = 0000 */ BMC(0x1E) /* 11110 */, -/* 1 = 0001 */ BMC(0x09) /* 01001 */, -/* 2 = 0010 */ BMC(0x14) /* 10100 */, -/* 3 = 0011 */ BMC(0x15) /* 10101 */, -/* 4 = 0100 */ BMC(0x0A) /* 01010 */, -/* 5 = 0101 */ BMC(0x0B) /* 01011 */, -/* 6 = 0110 */ BMC(0x0E) /* 01110 */, -/* 7 = 0111 */ BMC(0x0F) /* 01111 */, -/* 8 = 1000 */ BMC(0x12) /* 10010 */, -/* 9 = 1001 */ BMC(0x13) /* 10011 */, -/* A = 1010 */ BMC(0x16) /* 10110 */, -/* B = 1011 */ BMC(0x17) /* 10111 */, -/* C = 1100 */ BMC(0x1A) /* 11010 */, -/* D = 1101 */ BMC(0x1B) /* 11011 */, -/* E = 1110 */ BMC(0x1C) /* 11100 */, -/* F = 1111 */ BMC(0x1D) /* 11101 */, -/* Sync-1 K-code 11000 Startsynch #1 */ -/* Sync-2 K-code 10001 Startsynch #2 */ -/* RST-1 K-code 00111 Hard Reset #1 */ -/* RST-2 K-code 11001 Hard Reset #2 */ -/* EOP K-code 01101 EOP End Of Packet */ -/* Reserved Error 00000 */ -/* Reserved Error 00001 */ -/* Reserved Error 00010 */ -/* Reserved Error 00011 */ -/* Reserved Error 00100 */ -/* Reserved Error 00101 */ -/* Reserved Error 00110 */ -/* Reserved Error 01000 */ -/* Reserved Error 01100 */ -/* Reserved Error 10000 */ -/* Reserved Error 11111 */ + /* 0 = 0000 */ BMC(0x1E) /* 11110 */, + /* 1 = 0001 */ BMC(0x09) /* 01001 */, + /* 2 = 0010 */ BMC(0x14) /* 10100 */, + /* 3 = 0011 */ BMC(0x15) /* 10101 */, + /* 4 = 0100 */ BMC(0x0A) /* 01010 */, + /* 5 = 0101 */ BMC(0x0B) /* 01011 */, + /* 6 = 0110 */ BMC(0x0E) /* 01110 */, + /* 7 = 0111 */ BMC(0x0F) /* 01111 */, + /* 8 = 1000 */ BMC(0x12) /* 10010 */, + /* 9 = 1001 */ BMC(0x13) /* 10011 */, + /* A = 1010 */ BMC(0x16) /* 10110 */, + /* B = 1011 */ BMC(0x17) /* 10111 */, + /* C = 1100 */ BMC(0x1A) /* 11010 */, + /* D = 1101 */ BMC(0x1B) /* 11011 */, + /* E = 1110 */ BMC(0x1C) /* 11100 */, + /* F = 1111 */ BMC(0x1D) /* 11101 */, + /* Sync-1 K-code 11000 Startsynch #1 */ + /* Sync-2 K-code 10001 Startsynch #2 */ + /* RST-1 K-code 00111 Hard Reset #1 */ + /* RST-2 K-code 11001 Hard Reset #2 */ + /* EOP K-code 01101 EOP End Of Packet */ + /* Reserved Error 00000 */ + /* Reserved Error 00001 */ + /* Reserved Error 00010 */ + /* Reserved Error 00011 */ + /* Reserved Error 00100 */ + /* Reserved Error 00101 */ + /* Reserved Error 00110 */ + /* Reserved Error 01000 */ + /* Reserved Error 01100 */ + /* Reserved Error 10000 */ + /* Reserved Error 11111 */ }; static const uint8_t dec4b5b[] = { -/* Error */ 0x10 /* 00000 */, -/* Error */ 0x10 /* 00001 */, -/* Error */ 0x10 /* 00010 */, -/* Error */ 0x10 /* 00011 */, -/* Error */ 0x10 /* 00100 */, -/* Error */ 0x10 /* 00101 */, -/* Error */ 0x10 /* 00110 */, -/* RST-1 */ 0x13 /* 00111 K-code: Hard Reset #1 */, -/* Error */ 0x10 /* 01000 */, -/* 1 = 0001 */ 0x01 /* 01001 */, -/* 4 = 0100 */ 0x04 /* 01010 */, -/* 5 = 0101 */ 0x05 /* 01011 */, -/* Error */ 0x10 /* 01100 */, -/* EOP */ 0x15 /* 01101 K-code: EOP End Of Packet */, -/* 6 = 0110 */ 0x06 /* 01110 */, -/* 7 = 0111 */ 0x07 /* 01111 */, -/* Error */ 0x10 /* 10000 */, -/* Sync-2 */ 0x12 /* 10001 K-code: Startsynch #2 */, -/* 8 = 1000 */ 0x08 /* 10010 */, -/* 9 = 1001 */ 0x09 /* 10011 */, -/* 2 = 0010 */ 0x02 /* 10100 */, -/* 3 = 0011 */ 0x03 /* 10101 */, -/* A = 1010 */ 0x0A /* 10110 */, -/* B = 1011 */ 0x0B /* 10111 */, -/* Sync-1 */ 0x11 /* 11000 K-code: Startsynch #1 */, -/* RST-2 */ 0x14 /* 11001 K-code: Hard Reset #2 */, -/* C = 1100 */ 0x0C /* 11010 */, -/* D = 1101 */ 0x0D /* 11011 */, -/* E = 1110 */ 0x0E /* 11100 */, -/* F = 1111 */ 0x0F /* 11101 */, -/* 0 = 0000 */ 0x00 /* 11110 */, -/* Error */ 0x10 /* 11111 */, + /* Error */ 0x10 /* 00000 */, + /* Error */ 0x10 /* 00001 */, + /* Error */ 0x10 /* 00010 */, + /* Error */ 0x10 /* 00011 */, + /* Error */ 0x10 /* 00100 */, + /* Error */ 0x10 /* 00101 */, + /* Error */ 0x10 /* 00110 */, + /* RST-1 */ 0x13 /* 00111 K-code: Hard Reset #1 */, + /* Error */ 0x10 /* 01000 */, + /* 1 = 0001 */ 0x01 /* 01001 */, + /* 4 = 0100 */ 0x04 /* 01010 */, + /* 5 = 0101 */ 0x05 /* 01011 */, + /* Error */ 0x10 /* 01100 */, + /* EOP */ 0x15 /* 01101 K-code: EOP End Of Packet */, + /* 6 = 0110 */ 0x06 /* 01110 */, + /* 7 = 0111 */ 0x07 /* 01111 */, + /* Error */ 0x10 /* 10000 */, + /* Sync-2 */ 0x12 /* 10001 K-code: Startsynch #2 */, + /* 8 = 1000 */ 0x08 /* 10010 */, + /* 9 = 1001 */ 0x09 /* 10011 */, + /* 2 = 0010 */ 0x02 /* 10100 */, + /* 3 = 0011 */ 0x03 /* 10101 */, + /* A = 1010 */ 0x0A /* 10110 */, + /* B = 1011 */ 0x0B /* 10111 */, + /* Sync-1 */ 0x11 /* 11000 K-code: Startsynch #1 */, + /* RST-2 */ 0x14 /* 11001 K-code: Hard Reset #2 */, + /* C = 1100 */ 0x0C /* 11010 */, + /* D = 1101 */ 0x0D /* 11011 */, + /* E = 1110 */ 0x0E /* 11100 */, + /* F = 1111 */ 0x0F /* 11101 */, + /* 0 = 0000 */ 0x00 /* 11110 */, + /* Error */ 0x10 /* 11111 */, }; /* Start of Packet sequence : three Sync-1 K-codes, then one Sync-2 K-code */ -#define PD_SOP (PD_SYNC1 | (PD_SYNC1<<5) | (PD_SYNC1<<10) | (PD_SYNC2<<15)) -#define PD_SOP_PRIME (PD_SYNC1 | (PD_SYNC1<<5) | \ - (PD_SYNC3<<10) | (PD_SYNC3<<15)) -#define PD_SOP_PRIME_PRIME (PD_SYNC1 | (PD_SYNC3<<5) | \ - (PD_SYNC1<<10) | (PD_SYNC3<<15)) +#define PD_SOP \ + (PD_SYNC1 | (PD_SYNC1 << 5) | (PD_SYNC1 << 10) | (PD_SYNC2 << 15)) +#define PD_SOP_PRIME \ + (PD_SYNC1 | (PD_SYNC1 << 5) | (PD_SYNC3 << 10) | (PD_SYNC3 << 15)) +#define PD_SOP_PRIME_PRIME \ + (PD_SYNC1 | (PD_SYNC3 << 5) | (PD_SYNC1 << 10) | (PD_SYNC3 << 15)) /* Hard Reset sequence : three RST-1 K-codes, then one RST-2 K-code */ -#define PD_HARD_RESET (PD_RST1 | (PD_RST1 << 5) |\ - (PD_RST1 << 10) | (PD_RST2 << 15)) +#define PD_HARD_RESET \ + (PD_RST1 | (PD_RST1 << 5) | (PD_RST1 << 10) | (PD_RST2 << 15)) /* * Polarity based on 'DFP Perspective' (see table USB Type-C Cable and Connector @@ -159,11 +159,11 @@ static const uint8_t dec4b5b[] = { #endif #ifndef CC_RA -#define CC_RA(port, cc, sel) (cc < PD_SRC_RD_THRESHOLD) +#define CC_RA(port, cc, sel) (cc < PD_SRC_RD_THRESHOLD) #endif #define CC_RD(cc) ((cc >= PD_SRC_RD_THRESHOLD) && (cc < PD_SRC_VNC)) #ifndef CC_NC -#define CC_NC(port, cc, sel) (cc >= PD_SRC_VNC) +#define CC_NC(port, cc, sel) (cc >= PD_SRC_VNC) #endif /* @@ -180,16 +180,16 @@ static const uint8_t dec4b5b[] = { #define PD_SNK_VA PD_SNK_VA_MV #endif -#define CC_RP(cc) (cc >= PD_SNK_VA) +#define CC_RP(cc) (cc >= PD_SNK_VA) /* * Type C power source charge current limits are identified by their cc * voltage (set by selecting the proper Rd resistor). Any voltage below * TYPE_C_SRC_500_THRESHOLD will not be identified as a type C charger. */ -#define TYPE_C_SRC_500_THRESHOLD PD_SRC_RD_THRESHOLD -#define TYPE_C_SRC_1500_THRESHOLD 660 /* mV */ -#define TYPE_C_SRC_3000_THRESHOLD 1230 /* mV */ +#define TYPE_C_SRC_500_THRESHOLD PD_SRC_RD_THRESHOLD +#define TYPE_C_SRC_1500_THRESHOLD 660 /* mV */ +#define TYPE_C_SRC_3000_THRESHOLD 1230 /* mV */ /* Convert TCPC Alert register to index into pd.alert[] */ #define ALERT_REG_TO_INDEX(reg) (reg - TCPC_REG_ALERT) @@ -254,12 +254,12 @@ static struct pd_port_controller { #endif /* Last received */ - int rx_head[RX_BUFFER_SIZE+1]; - uint32_t rx_payload[RX_BUFFER_SIZE+1][7]; + int rx_head[RX_BUFFER_SIZE + 1]; + uint32_t rx_payload[RX_BUFFER_SIZE + 1][7]; int rx_buf_head, rx_buf_tail; /* Next transmit */ - enum tcpm_transmit_type tx_type; + enum tcpci_msg_type tx_type; uint16_t tx_head; uint32_t tx_payload[7]; const uint32_t *tx_data; @@ -309,7 +309,7 @@ int encode_word(int port, int off, uint32_t val32) /* prepare a 4b/5b-encoded PD message to send */ int prepare_message(int port, uint16_t header, uint8_t cnt, - const uint32_t *data) + const uint32_t *data) { int off, i; /* 64-bit preamble */ @@ -387,8 +387,8 @@ static int send_validate_message(int port, uint16_t header, uint8_t expected_msg_id = PD_HEADER_ID(header); uint8_t cnt = PD_HEADER_CNT(header); int retries = PD_HEADER_TYPE(header) == PD_DATA_SOURCE_CAP ? - 0 : - CONFIG_PD_RETRY_COUNT; + 0 : + CONFIG_PD_RETRY_COUNT; /* retry 3 times if we are not getting a valid answer */ for (r = 0; r <= retries; r++) { @@ -464,7 +464,7 @@ static int send_validate_message(int port, uint16_t header, static void send_goodcrc(int port, int id) { uint16_t header = PD_HEADER(PD_CTRL_GOOD_CRC, pd[port].power_role, - pd[port].data_role, id, 0, 0, 0); + pd[port].data_role, id, 0, 0, 0); int bit_len = prepare_message(port, header, 0, NULL); if (pd_start_tx(port, pd[port].polarity, bit_len) < 0) @@ -536,7 +536,7 @@ static void bist_mode_2_tx(int port) * build context buffer with 5 bytes, where the data is * alternating 1's and 0's. */ - bit = pd_write_sym(port, 0, BMC(0x15)); + bit = pd_write_sym(port, 0, BMC(0x15)); bit = pd_write_sym(port, bit, BMC(0x0a)); bit = pd_write_sym(port, bit, BMC(0x15)); bit = pd_write_sym(port, bit, BMC(0x0a)); @@ -566,10 +566,9 @@ static inline int decode_short(int port, int off, uint16_t *val16) dec4b5b[(w >> 15) & 0x1f], dec4b5b[(w >> 10) & 0x1f], dec4b5b[(w >> 5) & 0x1f], dec4b5b[(w >> 0) & 0x1f]); #endif - *val16 = dec4b5b[w & 0x1f] | - (dec4b5b[(w >> 5) & 0x1f] << 4) | - (dec4b5b[(w >> 10) & 0x1f] << 8) | - (dec4b5b[(w >> 15) & 0x1f] << 12); + *val16 = dec4b5b[w & 0x1f] | (dec4b5b[(w >> 5) & 0x1f] << 4) | + (dec4b5b[(w >> 10) & 0x1f] << 8) | + (dec4b5b[(w >> 15) & 0x1f] << 12); return end; } @@ -674,7 +673,7 @@ int pd_analyze_rx(int port, uint32_t *payload) #else /* CONFIG_USB_VPD || CONFIG_USB_CTVPD */ #ifdef CONFIG_USB_PD_DECODE_SOP if (val == PD_SOP || val == PD_SOP_PRIME || - val == PD_SOP_PRIME_PRIME) + val == PD_SOP_PRIME_PRIME) break; #else if (val == PD_SOP) { @@ -721,11 +720,11 @@ int pd_analyze_rx(int port, uint32_t *payload) #ifdef CONFIG_USB_PD_DECODE_SOP /* Encode message address */ if (val == PD_SOP) { - phs.head |= PD_HEADER_SOP(PD_MSG_SOP); + phs.head |= PD_HEADER_SOP(TCPCI_MSG_SOP); } else if (val == PD_SOP_PRIME) { - phs.head |= PD_HEADER_SOP(PD_MSG_SOP_PRIME); + phs.head |= PD_HEADER_SOP(TCPCI_MSG_SOP_PRIME); } else if (val == PD_SOP_PRIME_PRIME) { - phs.head |= PD_HEADER_SOP(PD_MSG_SOP_PRIME_PRIME); + phs.head |= PD_HEADER_SOP(TCPCI_MSG_SOP_PRIME_PRIME); } else { msg = "SOP*"; goto packet_err; @@ -734,7 +733,7 @@ int pd_analyze_rx(int port, uint32_t *payload) /* read payload data */ for (p = 0; p < cnt && bit > 0; p++) { - bit = decode_word(port, bit, payload+p); + bit = decode_word(port, bit, payload + p); crc32_hash32(payload[p]); } ccrc = crc32_result(); @@ -801,7 +800,7 @@ static int cc_voltage_to_status(int port, int cc_volt, int cc_sel) return TYPEC_CC_VOLT_RA; else return TYPEC_CC_VOLT_RD; - /* If we have a pull-down, then we are sink, check for Rp. */ + /* If we have a pull-down, then we are sink, check for Rp. */ } #ifdef CONFIG_USB_PD_DUAL_ROLE else if (pd[port].cc_pull == TYPEC_CC_RD) { @@ -843,9 +842,8 @@ int tcpc_run(int port, int evt) /* incoming packet ? */ if (pd_rx_started(port) && pd[port].rx_enabled) { /* Get message and place at RX buffer head */ - res = pd[port].rx_head[pd[port].rx_buf_head] = - pd_analyze_rx(port, - pd[port].rx_payload[pd[port].rx_buf_head]); + res = pd[port].rx_head[pd[port].rx_buf_head] = pd_analyze_rx( + port, pd[port].rx_payload[pd[port].rx_buf_head]); pd_rx_complete(port); /* @@ -868,19 +866,18 @@ int tcpc_run(int port, int evt) if ((evt & PD_EVENT_TX) && pd[port].rx_enabled) { switch (pd[port].tx_type) { #if defined(CONFIG_USB_VPD) || defined(CONFIG_USB_CTVPD) - case TCPC_TX_SOP_PRIME: + case TCPCI_MSG_SOP_PRIME: #else - case TCPC_TX_SOP: + case TCPCI_MSG_SOP: #endif - res = send_validate_message(port, - pd[port].tx_head, - pd[port].tx_data); + res = send_validate_message(port, pd[port].tx_head, + pd[port].tx_data); break; - case TCPC_TX_BIST_MODE_2: + case TCPCI_MSG_TX_BIST_MODE_2: bist_mode_2_tx(port); res = 0; break; - case TCPC_TX_HARD_RESET: + case TCPCI_MSG_TX_HARD_RESET: res = send_hard_reset(port); break; default: @@ -929,11 +926,11 @@ int tcpc_run(int port, int evt) */ return (get_time().val >= pd[port].low_power_ts.val && pd[port].cc_pull == TYPEC_CC_RD && - cc_is_open(pd[port].cc_status[0], pd[port].cc_status[1])) - ? 200 * MSEC - : 10 * MSEC; + cc_is_open(pd[port].cc_status[0], pd[port].cc_status[1])) ? + 200 * MSEC : + 10 * MSEC; #else - return 10*MSEC; + return 10 * MSEC; #endif } @@ -941,7 +938,7 @@ int tcpc_run(int port, int evt) void pd_task(void *u) { int port = TASK_ID_TO_PD_PORT(task_get_current()); - int timeout = 10*MSEC; + int timeout = 10 * MSEC; int evt; /* initialize phy task */ @@ -962,7 +959,7 @@ void pd_task(void *u) void pd_rx_event(int port) { - task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE); } int tcpc_alert_status(int port, int *alert) @@ -1024,8 +1021,8 @@ int tcpc_set_cc(int port, int pull) * because we only want to go into low power mode when we are not * dual-role toggling. */ - pd[port].low_power_ts.val = get_time().val + - 2*(PD_T_DRP_SRC + PD_T_DRP_SNK); + pd[port].low_power_ts.val = + get_time().val + 2 * (PD_T_DRP_SRC + PD_T_DRP_SNK); #endif /* @@ -1041,13 +1038,13 @@ int tcpc_set_cc(int port, int pull) #ifdef CONFIG_USB_POWER_DELIVERY tcpc_run(port, PD_EVENT_CC); #else - task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC); #endif return EC_SUCCESS; } int tcpc_get_cc(int port, enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) + enum tcpc_cc_voltage_status *cc2) { *cc2 = pd[port].cc_status[1]; *cc1 = pd[port].cc_status[0]; @@ -1128,7 +1125,7 @@ int tcpc_set_rx_enable(int port, int enable) return EC_SUCCESS; } -int tcpc_transmit(int port, enum tcpm_transmit_type type, uint16_t header, +int tcpc_transmit(int port, enum tcpci_msg_type type, uint16_t header, const uint32_t *data) { /* Store data to transmit and wake task to send it */ @@ -1139,7 +1136,7 @@ int tcpc_transmit(int port, enum tcpm_transmit_type type, uint16_t header, #ifdef CONFIG_USB_POWER_DELIVERY tcpc_run(port, PD_EVENT_TX); #else - task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX); #endif return EC_SUCCESS; } @@ -1184,8 +1181,9 @@ void tcpc_init(int port) /* Initialize physical layer */ pd_hw_init(port, PD_ROLE_DEFAULT(port)); - pd[port].cc_pull = PD_ROLE_DEFAULT(port) == - PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD; + pd[port].cc_pull = PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ? + TYPEC_CC_RP : + TYPEC_CC_RD; #ifdef TCPC_LOW_POWER /* Don't use low power immediately after boot */ pd[port].low_power_ts.val = get_time().val + SECOND; @@ -1196,16 +1194,15 @@ void tcpc_init(int port) /* make initial readings of CC voltages */ for (i = 0; i < 2; i++) { - pd[port].cc_status[i] = cc_voltage_to_status(port, - pd_adc_read(port, i), - i); + pd[port].cc_status[i] = + cc_voltage_to_status(port, pd_adc_read(port, i), i); } #ifdef CONFIG_USB_PD_TCPC_TRACK_VBUS #if CONFIG_USB_PD_PORT_MAX_COUNT >= 2 - tcpc_set_power_status(port, !gpio_get_level(port ? - GPIO_USB_C1_VBUS_WAKE_L : - GPIO_USB_C0_VBUS_WAKE_L)); + tcpc_set_power_status(port, + !gpio_get_level(port ? GPIO_USB_C1_VBUS_WAKE_L : + GPIO_USB_C0_VBUS_WAKE_L)); #else tcpc_set_power_status(port, !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L)); #endif /* CONFIG_USB_PD_PORT_MAX_COUNT >= 2 */ @@ -1223,7 +1220,7 @@ void tcpc_init(int port) void pd_vbus_evt_p0(enum gpio_signal signal) { tcpc_set_power_status(TASK_ID_TO_PD_PORT(TASK_ID_PD_C0), - !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L)); + !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L)); task_wake(TASK_ID_PD_C0); } @@ -1234,7 +1231,7 @@ void pd_vbus_evt_p1(enum gpio_signal signal) return; tcpc_set_power_status(TASK_ID_TO_PD_PORT(TASK_ID_PD_C1), - !gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L)); + !gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L)); task_wake(TASK_ID_PD_C1); } #endif /* PD_PORT_COUNT >= 2 */ @@ -1277,8 +1274,8 @@ static void tcpc_i2c_write(int port, int reg, int len, uint8_t *payload) tcpc_alert_mask_set(port, alert); break; case TCPC_REG_RX_DETECT: - tcpc_set_rx_enable(port, payload[1] & - TCPC_REG_RX_DETECT_SOP_HRST_MASK); + tcpc_set_rx_enable( + port, payload[1] & TCPC_REG_RX_DETECT_SOP_HRST_MASK); break; case TCPC_REG_POWER_STATUS_MASK: tcpc_set_power_status_mask(port, payload[1]); @@ -1308,12 +1305,11 @@ static int tcpc_i2c_read(int port, int reg, uint8_t *payload) case TCPC_REG_CC_STATUS: tcpc_get_cc(port, &cc1, &cc2); payload[0] = TCPC_REG_CC_STATUS_SET( - pd[port].cc_pull == TYPEC_CC_RD, - pd[port].cc_status[0], pd[port].cc_status[1]); + pd[port].cc_pull == TYPEC_CC_RD, pd[port].cc_status[0], + pd[port].cc_status[1]); return 1; case TCPC_REG_ROLE_CTRL: - payload[0] = TCPC_REG_ROLE_CTRL_SET(0, 0, - pd[port].cc_pull, + payload[0] = TCPC_REG_ROLE_CTRL_SET(0, 0, pd[port].cc_pull, pd[port].cc_pull); return 1; case TCPC_REG_TCPC_CTRL: @@ -1325,7 +1321,8 @@ static int tcpc_i2c_read(int port, int reg, uint8_t *payload) return 1; case TCPC_REG_RX_DETECT: payload[0] = pd[port].rx_enabled ? - TCPC_REG_RX_DETECT_SOP_HRST_MASK : 0; + TCPC_REG_RX_DETECT_SOP_HRST_MASK : + 0; return 1; case TCPC_REG_ALERT: tcpc_alert_status(port, &alert); @@ -1337,13 +1334,14 @@ static int tcpc_i2c_read(int port, int reg, uint8_t *payload) payload[1] = (pd[port].alert_mask >> 8) & 0xff; return 2; case TCPC_REG_RX_BYTE_CNT: - payload[0] = 3 + 4 * - PD_HEADER_CNT(pd[port].rx_head[pd[port].rx_buf_tail]); + payload[0] = + 3 + 4 * PD_HEADER_CNT( + pd[port].rx_head[pd[port].rx_buf_tail]); return 1; case TCPC_REG_RX_HDR: payload[0] = pd[port].rx_head[pd[port].rx_buf_tail] & 0xff; - payload[1] = - (pd[port].rx_head[pd[port].rx_buf_tail] >> 8) & 0xff; + payload[1] = (pd[port].rx_head[pd[port].rx_buf_tail] >> 8) & + 0xff; return 2; case TCPC_REG_RX_DATA: memcpy(payload, pd[port].rx_payload[pd[port].rx_buf_tail], @@ -1408,7 +1406,7 @@ void tcpc_i2c_process(int read, int port, int len, uint8_t *payload, #endif #ifdef CONFIG_COMMON_RUNTIME -static int command_tcpc(int argc, char **argv) +static int command_tcpc(int argc, const char **argv) { int port; char *e; @@ -1452,12 +1450,12 @@ static int command_tcpc(int argc, char **argv) } else if (!strncasecmp(argv[2], "state", 5)) { ccprintf("Port C%d, %s - CC:%d, CC0:%d, CC1:%d\n" "Alert: 0x%02x Mask: 0x%04x\n" - "Power Status: 0x%02x Mask: 0x%02x\n", port, - pd[port].rx_enabled ? "Ena" : "Dis", - pd[port].cc_pull, - pd[port].cc_status[0], pd[port].cc_status[1], - pd[port].alert, pd[port].alert_mask, - pd[port].power_status, pd[port].power_status_mask); + "Power Status: 0x%02x Mask: 0x%02x\n", + port, pd[port].rx_enabled ? "Ena" : "Dis", + pd[port].cc_pull, pd[port].cc_status[0], + pd[port].cc_status[1], pd[port].alert, + pd[port].alert_mask, pd[port].power_status, + pd[port].power_status_mask); } return EC_SUCCESS; diff --git a/common/usb_port_power_dumb.c b/common/usb_port_power_dumb.c index be60f6727f..cfdc016662 100644 --- a/common/usb_port_power_dumb.c +++ b/common/usb_port_power_dumb.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,17 +16,22 @@ #include "util.h" #define CPUTS(outstr) cputs(CC_USBCHARGE, outstr) -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) static uint8_t charge_mode[USB_PORT_COUNT]; static void usb_port_set_enabled(int port_id, int en) { - gpio_set_level(usb_port_enable[port_id], en); - charge_mode[port_id] = en; + /* + * Only enable valid ports. + */ + if (usb_port_enable[port_id] >= 0) { + gpio_or_ioex_set_level(usb_port_enable[port_id], en); + charge_mode[port_id] = en; + } } -static void usb_port_all_ports_on(void) +__maybe_unused static void usb_port_all_ports_on(void) { int i; for (i = 0; i < USB_PORT_COUNT; i++) @@ -70,20 +75,19 @@ usb_port_command_set_mode(struct host_cmd_handler_args *args) { const struct ec_params_usb_charge_set_mode *p = args->params; - if (usb_charge_set_mode(p->usb_port_id, p->mode, - p->inhibit_charge) != EC_SUCCESS) + if (usb_charge_set_mode(p->usb_port_id, p->mode, p->inhibit_charge) != + EC_SUCCESS) return EC_RES_ERROR; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_USB_CHARGE_SET_MODE, - usb_port_command_set_mode, +DECLARE_HOST_COMMAND(EC_CMD_USB_CHARGE_SET_MODE, usb_port_command_set_mode, EC_VER_MASK(0)); /*****************************************************************************/ /* Console commands */ -static int command_set_mode(int argc, char **argv) +static int command_set_mode(int argc, const char **argv) { int port_id = -1; int mode = -1; @@ -100,21 +104,19 @@ static int command_set_mode(int argc, char **argv) return EC_ERROR_PARAM2; usb_port_set_enabled(port_id, mode); - /* fallthrough */ + __fallthrough; case 1: for (i = 0; i < USB_PORT_COUNT; i++) - ccprintf("Port %d: %s\n", - i, charge_mode[i] ? "on" : "off"); + ccprintf("Port %d: %s\n", i, + charge_mode[i] ? "on" : "off"); return EC_SUCCESS; } return EC_ERROR_PARAM_COUNT; } -DECLARE_CONSOLE_COMMAND(usbchargemode, command_set_mode, - "[ ]", +DECLARE_CONSOLE_COMMAND(usbchargemode, command_set_mode, "[ ]", "Set USB charge mode"); - /*****************************************************************************/ /* Hooks */ @@ -130,10 +132,10 @@ static void usb_port_init(void) const uint8_t *prev; int version, size, i; - prev = (const uint8_t *)system_get_jump_tag(USB_SYSJUMP_TAG, - &version, &size); + prev = (const uint8_t *)system_get_jump_tag(USB_SYSJUMP_TAG, &version, + &size); if (!prev || version != USB_HOOK_VERSION || - size != sizeof(charge_mode)) { + size != sizeof(charge_mode)) { usb_port_all_ports_off(); return; } @@ -143,6 +145,7 @@ static void usb_port_init(void) } DECLARE_HOOK(HOOK_INIT, usb_port_init, HOOK_PRIO_DEFAULT); +#ifndef CONFIG_USB_PORT_POWER_DUMB_CUSTOM_HOOK static void usb_port_startup(void) { /* Turn on USB ports on as we go into S0 from S5. */ @@ -156,3 +159,4 @@ static void usb_port_shutdown(void) usb_port_all_ports_off(); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, usb_port_shutdown, HOOK_PRIO_DEFAULT); +#endif /* CONFIG_USB_PORT_POWER_DUMB_CUSTOM_HOOK */ diff --git a/common/usb_port_power_smart.c b/common/usb_port_power_smart.c index 170180cbab..42fbc7dd64 100644 --- a/common/usb_port_power_smart.c +++ b/common/usb_port_power_smart.c @@ -1,10 +1,11 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* USB charging control module for Chrome EC */ +#include "builtin/assert.h" #include "chipset.h" #include "common.h" #include "console.h" @@ -16,15 +17,15 @@ #include "util.h" #define CPUTS(outstr) cputs(CC_USBCHARGE, outstr) -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) #ifndef CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE #define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_SDP2 #endif struct charge_mode_t { - uint8_t mode:7; - uint8_t inhibit_charging_in_suspend:1; + uint8_t mode : 7; + uint8_t inhibit_charging_in_suspend : 1; } __pack; static struct charge_mode_t charge_mode[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT]; @@ -34,7 +35,9 @@ static struct charge_mode_t charge_mode[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT]; * If we only support CDP and SDP, the control signals are hard-wired so * there's nothing to do. The only to do is set ILIM_SEL. */ -static void usb_charge_set_control_mode(int port_id, int mode) {} +static void usb_charge_set_control_mode(int port_id, int mode) +{ +} #else /* !defined(CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY) */ static void usb_charge_set_control_mode(int port_id, int mode) { @@ -62,14 +65,19 @@ static void usb_charge_set_control_mode(int port_id, int mode) static void usb_charge_set_enabled(int port_id, int en) { ASSERT(port_id < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT); - gpio_or_ioex_set_level(usb_port_enable[port_id], en); + /* + * Only enable valid ports. + */ + if (usb_port_enable[port_id] >= 0) { + gpio_or_ioex_set_level(usb_port_enable[port_id], en); + } } static void usb_charge_set_ilim(int port_id, int sel) { int ilim_sel; -#if defined(CONFIG_USB_PORT_POWER_SMART_SIMPLE) || \ +#if defined(CONFIG_USB_PORT_POWER_SMART_SIMPLE) || \ defined(CONFIG_USB_PORT_POWER_SMART_INVERTED) /* ILIM_SEL is inverted. */ sel = !sel; @@ -137,7 +145,7 @@ int usb_charge_set_mode(int port_id, enum usb_charge_mode mode, /*****************************************************************************/ /* Console commands */ -static int command_set_mode(int argc, char **argv) +static int command_set_mode(int argc, const char **argv) { int port_id = -1; int mode = -1, inhibit_charge = 0; @@ -147,7 +155,7 @@ static int command_set_mode(int argc, char **argv) if (argc == 1) { for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++) ccprintf("Port %d: %d,%d\n", i, charge_mode[i].mode, - charge_mode[i].inhibit_charging_in_suspend); + charge_mode[i].inhibit_charging_in_suspend); return EC_SUCCESS; } @@ -183,14 +191,13 @@ usb_charge_command_set_mode(struct host_cmd_handler_args *args) { const struct ec_params_usb_charge_set_mode *p = args->params; - if (usb_charge_set_mode(p->usb_port_id, p->mode, - p->inhibit_charge) != EC_SUCCESS) + if (usb_charge_set_mode(p->usb_port_id, p->mode, p->inhibit_charge) != + EC_SUCCESS) return EC_RES_ERROR; return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_USB_CHARGE_SET_MODE, - usb_charge_command_set_mode, +DECLARE_HOST_COMMAND(EC_CMD_USB_CHARGE_SET_MODE, usb_charge_command_set_mode, EC_VER_MASK(0)); /*****************************************************************************/ @@ -208,18 +215,18 @@ static void usb_charge_init(void) const struct charge_mode_t *prev; int version, size, i; - prev = (const struct charge_mode_t *)system_get_jump_tag(USB_SYSJUMP_TAG, - &version, &size); + prev = (const struct charge_mode_t *)system_get_jump_tag( + USB_SYSJUMP_TAG, &version, &size); if (!prev || version != USB_HOOK_VERSION || - size != sizeof(charge_mode)) { + size != sizeof(charge_mode)) { usb_charge_all_ports_ctrl(USB_CHARGE_MODE_DISABLED); return; } for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++) usb_charge_set_mode(i, prev[i].mode, - prev[i].inhibit_charging_in_suspend); + prev[i].inhibit_charging_in_suspend); } DECLARE_HOOK(HOOK_INIT, usb_charge_init, HOOK_PRIO_DEFAULT); @@ -229,9 +236,8 @@ static void usb_charge_resume(void) /* Turn on USB ports on as we go into S0 from S3 or S5. */ for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++) - usb_charge_set_mode(i, - CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE, - charge_mode[i].inhibit_charging_in_suspend); + usb_charge_set_mode(i, CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE, + charge_mode[i].inhibit_charging_in_suspend); } DECLARE_HOOK(HOOK_CHIPSET_RESUME, usb_charge_resume, HOOK_PRIO_DEFAULT); diff --git a/common/usb_update.c b/common/usb_update.c index cc443163ba..2e9a681fed 100644 --- a/common/usb_update.c +++ b/common/usb_update.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,8 +9,8 @@ #include "consumer.h" #include "curve25519.h" #include "flash.h" -#include "queue_policies.h" #include "host_command.h" +#include "queue_policies.h" #include "rollback.h" #include "rwsig.h" #include "sha256.h" @@ -20,8 +20,8 @@ #include "usb-stream.h" #include "util.h" -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) /* * This file is an adaptation layer between the USB interface and the firmware @@ -47,37 +47,27 @@ struct consumer const update_consumer; struct usb_stream_config const usb_update; -static struct queue const update_to_usb = QUEUE_DIRECT(64, uint8_t, - null_producer, - usb_update.consumer); -static struct queue const usb_to_update = QUEUE_DIRECT(64, uint8_t, - usb_update.producer, - update_consumer); - -USB_STREAM_CONFIG_FULL(usb_update, - USB_IFACE_UPDATE, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_GOOGLE_UPDATE, - USB_PROTOCOL_GOOGLE_UPDATE, - USB_STR_UPDATE_NAME, - USB_EP_UPDATE, - USB_MAX_PACKET_SIZE, - USB_MAX_PACKET_SIZE, - usb_to_update, - update_to_usb) +static struct queue const update_to_usb = + QUEUE_DIRECT(64, uint8_t, null_producer, usb_update.consumer); +static struct queue const usb_to_update = + QUEUE_DIRECT(64, uint8_t, usb_update.producer, update_consumer); +USB_STREAM_CONFIG_FULL(usb_update, USB_IFACE_UPDATE, USB_CLASS_VENDOR_SPEC, + USB_SUBCLASS_GOOGLE_UPDATE, USB_PROTOCOL_GOOGLE_UPDATE, + USB_STR_UPDATE_NAME, USB_EP_UPDATE, USB_MAX_PACKET_SIZE, + USB_MAX_PACKET_SIZE, usb_to_update, update_to_usb) /* The receiver can be in one of the states below. */ enum rx_state { - rx_idle, /* Nothing happened yet. */ - rx_inside_block, /* Assembling a block to pass to the programmer. */ - rx_outside_block, /* Waiting for the next block to start or for the - reset command. */ + rx_idle, /* Nothing happened yet. */ + rx_inside_block, /* Assembling a block to pass to the programmer. */ + rx_outside_block, /* Waiting for the next block to start or for the + reset command. */ }; enum rx_state rx_state_ = rx_idle; -static uint8_t block_buffer[sizeof(struct update_command) + - CONFIG_UPDATE_PDU_SIZE]; +static uint8_t + block_buffer[sizeof(struct update_command) + CONFIG_UPDATE_PDU_SIZE]; static uint32_t block_size; static uint32_t block_index; @@ -117,8 +107,8 @@ static int pair_challenge(struct pair_challenge *challenge) * tmp2 = device_private * = HMAC_SHA256(device_secret, "device-identity") */ - hmac_SHA256(tmp2, tmp, CONFIG_ROLLBACK_SECRET_SIZE, - KEY_CONTEXT, sizeof(KEY_CONTEXT) - 1); + hmac_SHA256(tmp2, tmp, CONFIG_ROLLBACK_SECRET_SIZE, KEY_CONTEXT, + sizeof(KEY_CONTEXT) - 1); /* tmp = device_public = x25519(device_private, x25519_base_point) */ X25519_public_from_private(tmp, tmp2); @@ -128,10 +118,11 @@ static int pair_challenge(struct pair_challenge *challenge) X25519(tmp, tmp2, challenge->host_public); /* tmp2 = authenticator = HMAC_SHA256(shared_secret, nonce) */ - hmac_SHA256(tmp2, tmp, sizeof(tmp), - challenge->nonce, sizeof(challenge->nonce)); + hmac_SHA256(tmp2, tmp, sizeof(tmp), challenge->nonce, + sizeof(challenge->nonce)); QUEUE_ADD_UNITS(&update_to_usb, tmp2, - member_size(struct pair_challenge_response, authenticator)); + member_size(struct pair_challenge_response, + authenticator)); return 1; } #endif @@ -198,7 +189,8 @@ static int try_vendor_command(struct consumer const *consumer, size_t count) /* Looks like this is a vendor command, let's verify it. */ if (update_pdu_valid(&cmd_buffer->cmd, - count - offsetof(struct update_frame_header, cmd))) { + count - offsetof(struct update_frame_header, + cmd))) { enum update_extra_command subcommand; uint8_t response; size_t response_size = sizeof(response); @@ -262,12 +254,13 @@ static int try_vendor_command(struct consumer const *consumer, size_t count) break; #endif case UPDATE_EXTRA_CMD_UNLOCK_RW: - flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, 0); + crec_flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, 0); response = EC_RES_SUCCESS; break; #ifdef CONFIG_ROLLBACK case UPDATE_EXTRA_CMD_UNLOCK_ROLLBACK: - flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT, 0); + crec_flash_set_protect( + EC_FLASH_PROTECT_ROLLBACK_AT_BOOT, 0); response = EC_RES_SUCCESS; break; #ifdef CONFIG_ROLLBACK_SECRET_SIZE @@ -294,8 +287,8 @@ static int try_vendor_command(struct consumer const *consumer, size_t count) } /* pair_challenge takes care of answering */ - return pair_challenge((struct pair_challenge *) - (buffer + header_size)); + return pair_challenge(( + struct pair_challenge *)(buffer + header_size)); } #endif #endif /* CONFIG_ROLLBACK_SECRET_SIZE */ @@ -321,11 +314,10 @@ static int try_vendor_command(struct consumer const *consumer, size_t count) #ifdef CONFIG_TOUCHPAD_HASH_FW memcpy(tp.allowed_fw_hash, touchpad_fw_full_hash, - sizeof(tp.allowed_fw_hash)); + sizeof(tp.allowed_fw_hash)); #endif #endif /* CONFIG_TOUCHPAD_VIRTUAL_OFF */ - QUEUE_ADD_UNITS(&update_to_usb, - &tp, response_size); + QUEUE_ADD_UNITS(&update_to_usb, &tp, response_size); return 1; } case UPDATE_EXTRA_CMD_TOUCHPAD_DEBUG: { @@ -337,7 +329,8 @@ static int try_vendor_command(struct consumer const *consumer, size_t count) * with the payload data, and put the response in data. */ response = touchpad_debug(buffer + header_size, - data_count, &data, &write_count); + data_count, &data, + &write_count); /* * On error, or if there is no data to write back, just @@ -373,11 +366,10 @@ static int try_vendor_command(struct consumer const *consumer, size_t count) } response = uart_console_read_buffer( - data[0], - (char *)output, - MIN(sizeof(output), - queue_space(&update_to_usb)), - &write_count); + data[0], (char *)output, + MIN(sizeof(output), + queue_space(&update_to_usb)), + &write_count); if (response != EC_RES_SUCCESS || write_count == 0) break; @@ -405,7 +397,7 @@ static uint64_t prev_activity_timestamp; * A flag indicating that at least one valid PDU containing flash update block * has been received in the current transfer session. */ -static uint8_t data_was_transferred; +static uint8_t data_was_transferred; /* Reply with an error to remote side, reset state. */ static void send_error_reset(uint8_t resp_value) @@ -458,10 +450,10 @@ static void update_out_handler(struct consumer const *consumer, size_t count) * digest = 0, and base = 0. */ if (!fetch_transfer_start(consumer, count, &u.upfr) || - be32toh(u.upfr.block_size) != - sizeof(struct update_frame_header) || - u.upfr.cmd.block_digest != 0 || - u.upfr.cmd.block_base != 0) { + be32toh(u.upfr.block_size) != + sizeof(struct update_frame_header) || + u.upfr.cmd.block_digest != 0 || + u.upfr.cmd.block_base != 0) { /* * Something is wrong, this payload is not a valid * update start PDU. Let'w indicate this by returning @@ -473,14 +465,14 @@ static void update_out_handler(struct consumer const *consumer, size_t count) } CPRINTS("FW update: starting..."); - fw_update_command_handler(&u.upfr.cmd, count - - offsetof(struct update_frame_header, - cmd), - &resp_size); + fw_update_command_handler( + &u.upfr.cmd, + count - offsetof(struct update_frame_header, cmd), + &resp_size); if (!u.startup_resp.return_value) { - rx_state_ = rx_outside_block; /* We're in business. */ - data_was_transferred = 0; /* No data received yet. */ + rx_state_ = rx_outside_block; /* We're in business. */ + data_was_transferred = 0; /* No data received yet. */ } /* Let the host know what updater had to say. */ @@ -508,8 +500,7 @@ static void update_out_handler(struct consumer const *consumer, size_t count) } resp_value = 0; - QUEUE_ADD_UNITS(&update_to_usb, - &resp_value, 1); + QUEUE_ADD_UNITS(&update_to_usb, &resp_value, 1); rx_state_ = rx_idle; return; } @@ -527,7 +518,7 @@ static void update_out_handler(struct consumer const *consumer, size_t count) /* Let's allocate a large enough buffer. */ block_size = be32toh(upfr.block_size) - - offsetof(struct update_frame_header, cmd); + offsetof(struct update_frame_header, cmd); /* * Only update start PDU is allowed to have a size 0 payload. @@ -544,7 +535,7 @@ static void update_out_handler(struct consumer const *consumer, size_t count) * to the updater. */ block_index = sizeof(upfr) - - offsetof(struct update_frame_header, cmd); + offsetof(struct update_frame_header, cmd); memcpy(block_buffer, &upfr.cmd, block_index); block_size -= block_index; rx_state_ = rx_inside_block; @@ -566,7 +557,7 @@ static void update_out_handler(struct consumer const *consumer, size_t count) send_error_reset(UPDATE_GEN_ERROR); return; } - return; /* More to come. */ + return; /* More to come. */ } /* @@ -587,7 +578,7 @@ static void update_out_handler(struct consumer const *consumer, size_t count) struct consumer const update_consumer = { .queue = &usb_to_update, - .ops = &((struct consumer_ops const) { + .ops = &((struct consumer_ops const){ .written = update_out_handler, }), }; diff --git a/common/usbc/ap_vdm_control.c b/common/usbc/ap_vdm_control.c new file mode 100644 index 0000000000..7941b852e8 --- /dev/null +++ b/common/usbc/ap_vdm_control.c @@ -0,0 +1,301 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * AP VDM control support + * Note: this is mutually exclusive with EC VDM control + */ + +#include "builtin/assert.h" +#include "chipset.h" +#include "compile_time_macros.h" +#include "console.h" +#include "ec_commands.h" +#include "hooks.h" +#include "queue.h" +#include "system.h" +#include "task.h" +#include "tcpm/tcpm.h" +#include "temp_sensor.h" +#include "usb_pd.h" +#include "usb_pd_dp_hpd_gpio.h" +#include "usb_pd_dpm_sm.h" + +#include +#include + +#ifdef CONFIG_COMMON_RUNTIME +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) +#else +#define CPRINTF(format, args...) +#define CPRINTS(format, args...) +#endif + +/* + * VDM:Attention queue for boards using AP-driven VDMs + * + * Depth must be a power of 2, which is normally enforced by the queue init + * code, but must be manually enforced here. + */ +#define DPM_ATTENTION_QUEUE_DEPTH 8 +BUILD_ASSERT(POWER_OF_TWO(DPM_ATTENTION_QUEUE_DEPTH)); + +/* + * timestamp of the next possible toggle to ensure the 2-ms spacing + * between IRQ_HPD. Note, other boards use the DP module to store this + * variable so it's globally accessible for board code. + * + * Note: This is also defined in the EC-driven DP module, and it's assumed + * that these modules are mutually exclusive and will not be compiled + * for the same board. + */ +uint64_t svdm_hpd_deadline[CONFIG_USB_PD_PORT_MAX_COUNT]; + +struct attention_queue_entry { + int objects; + uint32_t attention[PD_ATTENTION_MAX_VDO]; +}; + +static struct { + uint32_t vdm_reply[VDO_MAX_SIZE]; + uint8_t vdm_reply_cnt; + enum tcpci_msg_type vdm_reply_type; + struct queue attention_queue; + struct queue_state queue_state; + struct attention_queue_entry queue_buffer[DPM_ATTENTION_QUEUE_DEPTH]; + mutex_t queue_lock; + /* Have we seen the DP:Configure ACK? */ + bool dp_configured; + /* Did we get a HPD high signal before DP:Configure completed? */ + bool hpd_pending; +} ap_storage[CONFIG_USB_PD_PORT_MAX_COUNT]; + +#ifdef CONFIG_ZEPHYR +static int init_ap_vdm_mutexes(void) +{ + int port; + + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) { + k_mutex_init(&ap_storage[port].queue_lock); + } + + return 0; +} +SYS_INIT(init_ap_vdm_mutexes, POST_KERNEL, 50); +#endif /* CONFIG_ZEPHYR */ + +static void init_attention_queue_structs(void) +{ + int i; + + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + ap_storage[i].attention_queue.state = + &ap_storage[i].queue_state; + ap_storage[i].attention_queue.policy = &queue_policy_null; + ap_storage[i].attention_queue.buffer_units = + DPM_ATTENTION_QUEUE_DEPTH; + ap_storage[i].attention_queue.buffer_units_mask = + DPM_ATTENTION_QUEUE_DEPTH - 1; + ap_storage[i].attention_queue.unit_bytes = + sizeof(struct attention_queue_entry); + ap_storage[i].attention_queue.buffer = + (uint8_t *)&ap_storage[i].queue_buffer[0]; + } +} +DECLARE_HOOK(HOOK_INIT, init_attention_queue_structs, HOOK_PRIO_FIRST); + +/* Process HPD signals from the DP:Status or Attention contents */ +static void attention_hpd_process(int port, uint32_t vdo) +{ + bool hpd_level = PD_VDO_DPSTS_HPD_LVL(vdo); + bool hpd_irq = PD_VDO_DPSTS_HPD_IRQ(vdo); + + if (!ap_storage[port].dp_configured && hpd_level) + ap_storage[port].hpd_pending = true; + else + dp_hpd_gpio_set(port, hpd_level, hpd_irq); + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && + (hpd_irq || hpd_level)) + /* + * Wake up the AP. IRQ or level high indicates a DP + * sink is now present. + */ + if (IS_ENABLED(CONFIG_MKBP_EVENT)) + pd_notify_dp_alt_mode_entry(port); +} + +void ap_vdm_attention_enqueue(int port, int length, uint32_t *buf) +{ + struct attention_queue_entry new_entry; + + /* + * Process HPD from the message if we're configured + * Note: the IRQ toggles are time critical and should be done before + * sending the VDM to the queue + */ + if (PD_VDO_VID(buf[0]) == USB_SID_DISPLAYPORT && length > 1) + attention_hpd_process(port, buf[1]); + + new_entry.objects = length; + memcpy(new_entry.attention, buf, length * sizeof(uint32_t)); + + mutex_lock(&ap_storage[port].queue_lock); + + /* If the queue is already full, discard the last entry */ + if (queue_is_full(&ap_storage[port].attention_queue)) + queue_advance_head(&ap_storage[port].attention_queue, 1); + + /* Note: this should not happen, but log anyway */ + if (queue_add_unit(&ap_storage[port].attention_queue, &new_entry) == 0) + CPRINTS("Error: Dropping port %d Attention", port); + else + pd_notify_event(port, PD_STATUS_EVENT_VDM_ATTENTION); + + mutex_unlock(&ap_storage[port].queue_lock); +} + +static uint8_t ap_vdm_attention_pop(int port, uint32_t *buf, + uint8_t *items_left) +{ + int length = 0; + struct attention_queue_entry popped_entry; + + mutex_lock(&ap_storage[port].queue_lock); + + if (!queue_is_empty(&ap_storage[port].attention_queue)) { + queue_remove_unit(&ap_storage[port].attention_queue, + &popped_entry); + + length = popped_entry.objects; + memcpy(buf, popped_entry.attention, length * sizeof(buf[0])); + } + *items_left = queue_count(&ap_storage[port].attention_queue); + + mutex_unlock(&ap_storage[port].queue_lock); + + return length; +} + +void ap_vdm_init(int port) +{ + /* Clear any stored AP messages */ + ap_storage[port].vdm_reply_cnt = 0; + queue_init(&ap_storage[port].attention_queue); + ap_storage[port].dp_configured = false; + ap_storage[port].hpd_pending = false; + dp_hpd_gpio_set(port, false, false); +} + +void ap_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count, + uint32_t *vdm) +{ + assert(vdo_count >= 1); + assert(vdo_count <= VDO_MAX_SIZE); + + /* Store and notify the AP */ + ap_storage[port].vdm_reply_cnt = vdo_count; + memcpy(ap_storage[port].vdm_reply, vdm, vdo_count * sizeof(uint32_t)); + ap_storage[port].vdm_reply_type = type; + pd_notify_event(port, PD_STATUS_EVENT_VDM_REQ_REPLY); + + /* Clear the flag now that reply fields are updated */ + dpm_clear_vdm_request(port); + + if ((PD_VDO_VID(vdm[0]) == USB_SID_DISPLAYPORT) && + PD_VDO_SVDM(vdm[0]) && (PD_VDO_CMD(vdm[0]) == CMD_DP_CONFIG)) { + /* + * If this was a DP:Configure ACK, register it so we can start + * sending HPD signals + */ + ap_storage[port].dp_configured = true; + if (ap_storage[port].hpd_pending) + dp_hpd_gpio_set(port, true, false); + } else if ((PD_VDO_VID(vdm[0]) == USB_SID_DISPLAYPORT) && + PD_VDO_SVDM(vdm[0]) && + (PD_VDO_CMD(vdm[0]) == CMD_DP_STATUS) && vdo_count > 1) { + /* + * If this was a DP:Status ACK, register if the HPD signal was + * set in it. According to 3.9.2.2 USB PD-to-HPD Timing in + * VESA DisplayPort Alt Mode on USB Type-C Standard Version + * 2.0: + * "A USB PD-to-HPD converter shall drive a low level on its + * HPD driver whenever DisplayPort Configuration on the USB-C + * interface is not enabled" + * + * So we may not transmit this HPD high until DP:Configure ACK + */ + attention_hpd_process(port, vdm[1]); + } +} + +void ap_vdm_naked(int port, enum tcpci_msg_type type, uint16_t svid, + uint8_t vdm_cmd, uint32_t vdm_header) +{ + /* Store and notify the AP */ + ap_storage[port].vdm_reply_type = type; + + if (vdm_header != 0) { + ap_storage[port].vdm_reply_cnt = 1; + ap_storage[port].vdm_reply[0] = vdm_header; + pd_notify_event(port, PD_STATUS_EVENT_VDM_REQ_REPLY); + } else { + ap_storage[port].vdm_reply_cnt = 0; + pd_notify_event(port, PD_STATUS_EVENT_VDM_REQ_FAILED); + } + + /* Clear the flag now that reply fields are updated */ + dpm_clear_vdm_request(port); +} + +static enum ec_status ap_vdm_copy_reply(int port, uint8_t *type, uint8_t *size, + uint32_t *buf) +{ + if (dpm_check_vdm_request(port)) + return EC_RES_BUSY; + + if (ap_storage[port].vdm_reply_cnt == 0) + return EC_RES_UNAVAILABLE; + + *type = ap_storage[port].vdm_reply_type; + *size = ap_storage[port].vdm_reply_cnt; + memcpy(buf, ap_storage[port].vdm_reply, *size * sizeof(uint32_t)); + + return EC_RES_SUCCESS; +} + +/* Feature-specific host commands */ +static enum ec_status hc_typec_vdm_response(struct host_cmd_handler_args *args) +{ + const struct ec_params_typec_vdm_response *p = args->params; + struct ec_response_typec_vdm_response *r = args->response; + uint32_t data[VDO_MAX_SIZE]; + + if (p->port >= board_get_usb_pd_port_count()) + return EC_RES_INVALID_PARAM; + + if (args->response_max < sizeof(*r)) + return EC_RES_RESPONSE_TOO_BIG; + + args->response_size = sizeof(*r); + + r->vdm_response_err = ap_vdm_copy_reply(p->port, &r->partner_type, + &r->vdm_data_objects, data); + + if (r->vdm_data_objects > 0) + memcpy(r->vdm_response, data, + r->vdm_data_objects * sizeof(uint32_t)); + + r->vdm_attention_objects = + ap_vdm_attention_pop(p->port, data, &r->vdm_attention_left); + if (r->vdm_attention_objects > 0) + memcpy(r->vdm_attention, data, + r->vdm_attention_objects * sizeof(uint32_t)); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_TYPEC_VDM_RESPONSE, hc_typec_vdm_response, + EC_VER_MASK(0)); diff --git a/common/usbc/build.mk b/common/usbc/build.mk index c39d1a57e6..159ce05e0b 100644 --- a/common/usbc/build.mk +++ b/common/usbc/build.mk @@ -1,4 +1,4 @@ -# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -8,8 +8,9 @@ _usbc_dir:=$(dir $(lastword $(MAKEFILE_LIST))) ifneq ($(CONFIG_USB_PD_TCPMV2),) -all-obj-y+=$(_usbc_dir)usb_sm.o -all-obj-y+=$(_usbc_dir)usbc_task.o +all-obj-$(CONFIG_USB_PD_TCPMV2)+=$(_usbc_dir)usb_pd_timer.o +all-obj-$(CONFIG_USB_PD_TCPMV2)+=$(_usbc_dir)usb_sm.o +all-obj-$(CONFIG_USB_PD_TCPMV2)+=$(_usbc_dir)usbc_task.o # Type-C state machines ifneq ($(CONFIG_USB_TYPEC_SM),) @@ -20,24 +21,34 @@ endif # CONFIG_USB_TYPEC_SM # Protocol state machine ifneq ($(CONFIG_USB_PRL_SM),) -all-obj-y+=$(_usbc_dir)usb_prl_sm.o +all-obj-$(CONFIG_USB_PD_TCPMV2)+=$(_usbc_dir)usb_prl_sm.o endif # CONFIG_USB_PRL_SM # Policy Engine state machines ifneq ($(CONFIG_USB_PE_SM),) all-obj-$(CONFIG_USB_VPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o all-obj-$(CONFIG_USB_CTVPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o +all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)usbc_pd_policy.o all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)usb_pe_drp_sm.o all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)usb_pd_dpm.o -all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)dp_alt_mode.o +all-obj-$(CONFIG_USB_PD_VDM_AP_CONTROL)+=$(_usbc_dir)ap_vdm_control.o +all-obj-$(CONFIG_USB_PD_DP_MODE)+=$(_usbc_dir)dp_alt_mode.o +all-obj-$(CONFIG_USB_PD_DP_HPD_GPIO)+=$(_usbc_dir)dp_hpd_gpio.o all-obj-$(CONFIG_USB_PD_TBT_COMPAT_MODE)+=$(_usbc_dir)tbt_alt_mode.o all-obj-$(CONFIG_USB_PD_USB4)+=$(_usbc_dir)usb_mode.o all-obj-$(CONFIG_CMD_PD)+=$(_usbc_dir)usb_pd_console.o all-obj-$(CONFIG_USB_PD_HOST_CMD)+=$(_usbc_dir)usb_pd_host.o endif # CONFIG_USB_PE_SM +# Retimer firmware update +all-obj-$(CONFIG_USBC_RETIMER_FW_UPDATE)+=$(_usbc_dir)usb_retimer_fw_update.o + +# ALT-DP mode for UFP ports +all-obj-$(CONFIG_USB_PD_ALT_MODE_UFP_DP)+=$(_usbc_dir)usb_pd_dp_ufp.o endif # CONFIG_USB_PD_TCPMV2 # For testing +all-obj-$(CONFIG_TEST_USB_PD_TIMER)+=$(_usbc_dir)usb_pd_timer.o +all-obj-$(CONFIG_TEST_USB_PE_SM)+=$(_usbc_dir)usbc_pd_policy.o all-obj-$(CONFIG_TEST_USB_PE_SM)+=$(_usbc_dir)usb_pe_drp_sm.o all-obj-$(CONFIG_TEST_SM)+=$(_usbc_dir)usb_sm.o diff --git a/common/usbc/dp_alt_mode.c b/common/usbc/dp_alt_mode.c index cc5305c0c3..dbccd9b0fd 100644 --- a/common/usbc/dp_alt_mode.c +++ b/common/usbc/dp_alt_mode.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,30 +9,67 @@ * section 5.2 */ -#include -#include -#include "assert.h" -#include "usb_pd.h" +#include "atomic.h" +#include "builtin/assert.h" +#include "chipset.h" +#include "console.h" +#include "gpio.h" +#include "timer.h" +#include "typec_control.h" +#include "usb_common.h" #include "usb_dp_alt_mode.h" -#include "usb_pd_dpm.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_dp_hpd_gpio.h" #include "usb_pd_tcpm.h" +#include +#include + #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else #define CPRINTF(format, args...) #define CPRINTS(format, args...) #endif +/* + * Note: the following DP-related variables must be kept as-is since + * some boards are using them in their board-specific code. + * TODO(b/267545470): Fold board DP code into the DP module + */ + +/* + * timestamp of the next possible toggle to ensure the 2-ms spacing + * between IRQ_HPD. Since this is used in overridable functions, this + * has to be global. + * + * Note: This variable is also defined in the AP VDM control module and it + * is assumed that the two will never be compiled together, as the modules are + * mutually exclusive. + */ +uint64_t svdm_hpd_deadline[CONFIG_USB_PD_PORT_MAX_COUNT]; + +int dp_flags[CONFIG_USB_PD_PORT_MAX_COUNT]; + +uint32_t dp_status[CONFIG_USB_PD_PORT_MAX_COUNT]; + +/* Console command multi-function preference set for a PD port. */ +__maybe_unused bool dp_port_mf_allow[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [0 ... CONFIG_USB_PD_PORT_MAX_COUNT - 1] = true +}; + /* The state of the DP negotiation */ enum dp_states { DP_START = 0, DP_ENTER_ACKED, DP_ENTER_NAKED, DP_STATUS_ACKED, + DP_PREPARE_CONFIG, DP_ACTIVE, DP_ENTER_RETRY, + DP_PREPARE_EXIT, DP_INACTIVE, DP_STATE_COUNT }; @@ -43,39 +80,55 @@ static enum dp_states dp_state[CONFIG_USB_PD_PORT_MAX_COUNT]; * Default of 0 indicates no command expected. */ static const uint8_t state_vdm_cmd[DP_STATE_COUNT] = { - [DP_START] = CMD_ENTER_MODE, - [DP_ENTER_ACKED] = CMD_DP_STATUS, - [DP_STATUS_ACKED] = CMD_DP_CONFIG, - [DP_ACTIVE] = CMD_EXIT_MODE, - [DP_ENTER_NAKED] = CMD_EXIT_MODE, + [DP_START] = CMD_ENTER_MODE, [DP_ENTER_ACKED] = CMD_DP_STATUS, + [DP_PREPARE_CONFIG] = CMD_DP_CONFIG, [DP_PREPARE_EXIT] = CMD_EXIT_MODE, [DP_ENTER_RETRY] = CMD_ENTER_MODE, }; +/* + * Track if we're retrying due to an Enter Mode NAK + */ +#define DP_FLAG_RETRY BIT(0) + +static atomic_t dpm_dp_flags[CONFIG_USB_PD_PORT_MAX_COUNT]; + +#define DP_SET_FLAG(port, flag) atomic_or(&dpm_dp_flags[port], (flag)) +#define DP_CLR_FLAG(port, flag) atomic_clear_bits(&dpm_dp_flags[port], (flag)) +#define DP_CHK_FLAG(port, flag) (dpm_dp_flags[port] & (flag)) + +/* Note: There is only one DP mode currently specified */ +static const int dp_opos = 1; + bool dp_is_active(int port) { - return dp_state[port] == DP_ACTIVE; + return dp_state[port] == DP_ACTIVE || dp_state[port] == DP_PREPARE_EXIT; +} + +bool dp_is_idle(int port) +{ + return dp_state[port] == DP_INACTIVE || dp_state[port] == DP_START; } void dp_init(int port) { dp_state[port] = DP_START; + dpm_dp_flags[port] = 0; } -void dp_teardown(int port) +bool dp_entry_is_done(int port) { - CPRINTS("C%d: DP teardown", port); - dp_state[port] = DP_INACTIVE; + return dp_state[port] == DP_ACTIVE || dp_state[port] == DP_INACTIVE; } static void dp_entry_failed(int port) { CPRINTS("C%d: DP alt mode protocol failed!", port); dp_state[port] = DP_INACTIVE; - dpm_set_mode_entry_done(port); + dpm_dp_flags[port] = 0; } -static bool dp_response_valid(int port, enum tcpm_transmit_type type, - char *cmdt, int vdm_cmd) +static bool dp_response_valid(int port, enum tcpci_msg_type type, char *cmdt, + int vdm_cmd) { enum dp_states st = dp_state[port]; @@ -83,11 +136,12 @@ static bool dp_response_valid(int port, enum tcpm_transmit_type type, * Check for an unexpected response. * If DP is inactive, ignore the command. */ - if (type != TCPC_TX_SOP || + if (type != TCPCI_MSG_SOP || (st != DP_INACTIVE && state_vdm_cmd[st] != vdm_cmd)) { CPRINTS("C%d: Received unexpected DP VDM %s (cmd %d) from" - " %s in state %d", port, cmdt, vdm_cmd, - type == TCPC_TX_SOP ? "port partner" : "cable plug", + " %s in state %d", + port, cmdt, vdm_cmd, + type == TCPCI_MSG_SOP ? "port partner" : "cable plug", st); dp_entry_failed(port); return false; @@ -95,11 +149,26 @@ static bool dp_response_valid(int port, enum tcpm_transmit_type type, return true; } -void dp_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, - uint32_t *vdm) +static void dp_exit_to_usb_mode(int port) +{ + svdm_exit_dp_mode(port); + pd_set_dfp_enter_mode_flag(port, false); + + set_usb_mux_with_current_data_role(port); + + CPRINTS("C%d: Exited DP mode", port); + /* + * If the EC exits an alt mode autonomously, don't try to enter it + * again. If the AP commands the EC to exit DP mode, it might command + * the EC to enter again later, so leave the state machine ready for + * that possibility. + */ + dp_state[port] = DP_INACTIVE; +} + +void dp_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count, + uint32_t *vdm) { - const struct svdm_amode_data *modep = - pd_get_amode_data(port, type, USB_SID_DISPLAYPORT); const uint8_t vdm_cmd = PD_VDO_CMD(vdm[0]); if (!dp_response_valid(port, type, "ACK", vdm_cmd)) @@ -111,33 +180,30 @@ void dp_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, case DP_START: case DP_ENTER_RETRY: dp_state[port] = DP_ENTER_ACKED; + /* Inform PE layer that alt mode is now active */ + pd_set_dfp_enter_mode_flag(port, true); break; case DP_ENTER_ACKED: /* DP status response & UFP's DP attention have same payload. */ dfp_consume_attention(port, vdm); dp_state[port] = DP_STATUS_ACKED; break; - case DP_STATUS_ACKED: - if (modep && modep->opos && modep->fx->post_config) - modep->fx->post_config(port); - dpm_set_mode_entry_done(port); + case DP_PREPARE_CONFIG: + svdm_dp_post_config(port); dp_state[port] = DP_ACTIVE; CPRINTS("C%d: Entered DP mode", port); break; - case DP_ACTIVE: - /* - * Request to exit mode successful, so put it in - * inactive state. - */ - CPRINTS("C%d: Exited DP mode", port); - dp_state[port] = DP_INACTIVE; - break; - case DP_ENTER_NAKED: + case DP_PREPARE_EXIT: /* - * The request to exit the mode was successful, - * so try to enter the mode again. + * Request to exit mode successful, so put the module in an + * inactive state or give entry another shot. */ - dp_state[port] = DP_ENTER_RETRY; + if (DP_CHK_FLAG(port, DP_FLAG_RETRY)) { + dp_state[port] = DP_ENTER_RETRY; + DP_CLR_FLAG(port, DP_FLAG_RETRY); + } else { + dp_exit_to_usb_mode(port); + } break; case DP_INACTIVE: /* @@ -148,14 +214,14 @@ void dp_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, break; default: /* Invalid or unexpected negotiation state */ - CPRINTF("%s called with invalid state %d\n", - __func__, dp_state[port]); + CPRINTF("%s called with invalid state %d\n", __func__, + dp_state[port]); dp_entry_failed(port); break; } } -void dp_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd) +void dp_vdm_naked(int port, enum tcpci_msg_type type, uint8_t vdm_cmd) { if (!dp_response_valid(port, type, "NAK", vdm_cmd)) return; @@ -179,60 +245,86 @@ void dp_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd) */ dp_entry_failed(port); break; + case DP_PREPARE_EXIT: + /* Treat an Exit Mode NAK the same as an Exit Mode ACK. */ + dp_exit_to_usb_mode(port); + break; default: - CPRINTS("C%d: NAK for cmd %d in state %d", port, - vdm_cmd, dp_state[port]); + CPRINTS("C%d: NAK for cmd %d in state %d", port, vdm_cmd, + dp_state[port]); dp_entry_failed(port); break; } } -int dp_setup_next_vdm(int port, int vdo_count, uint32_t *vdm) +enum dpm_msg_setup_status dp_setup_next_vdm(int port, int *vdo_count, + uint32_t *vdm) { - const struct svdm_amode_data *modep = pd_get_amode_data(port, - TCPC_TX_SOP, USB_SID_DISPLAYPORT); + uint32_t mode_vdos[VDO_MAX_OBJECTS]; int vdo_count_ret; - if (vdo_count < VDO_MAX_SIZE) - return -1; + if (*vdo_count < VDO_MAX_SIZE) + return MSG_SETUP_ERROR; switch (dp_state[port]) { case DP_START: case DP_ENTER_RETRY: /* Enter the first supported mode for DisplayPort. */ - vdm[0] = pd_dfp_enter_mode(port, TCPC_TX_SOP, - USB_SID_DISPLAYPORT, 0); - if (vdm[0] == 0) - return -1; + if (pd_get_mode_vdo_for_svid(port, TCPCI_MSG_SOP, + USB_SID_DISPLAYPORT, + mode_vdos) == 0) + return MSG_SETUP_ERROR; + if (svdm_enter_dp_mode(port, mode_vdos[dp_opos - 1]) < 0) + return MSG_SETUP_ERROR; + vdm[0] = VDO(USB_SID_DISPLAYPORT, 1, + CMD_ENTER_MODE | VDO_OPOS(dp_opos)); /* CMDT_INIT is 0, so this is a no-op */ vdm[0] |= VDO_CMDT(CMDT_INIT); - vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)); + vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)); vdo_count_ret = 1; if (dp_state[port] == DP_START) CPRINTS("C%d: Attempting to enter DP mode", port); break; case DP_ENTER_ACKED: - if (!(modep && modep->opos)) - return -1; - - vdo_count_ret = modep->fx->status(port, vdm); + vdo_count_ret = svdm_dp_status(port, vdm); if (vdo_count_ret == 0) - return -1; - vdm[0] |= PD_VDO_OPOS(modep->opos); + return MSG_SETUP_ERROR; + vdm[0] |= PD_VDO_OPOS(dp_opos); vdm[0] |= VDO_CMDT(CMDT_INIT); - vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)); + vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)); break; case DP_STATUS_ACKED: - if (!(modep && modep->opos)) - return -1; + if (!get_dp_pin_mode(port)) + return MSG_SETUP_ERROR; + + dp_state[port] = DP_PREPARE_CONFIG; - vdo_count_ret = modep->fx->config(port, vdm); + /* + * Place the USB Type-C pins that are to be re-configured to + * DisplayPort Configuration into the Safe state. For + * USB_PD_MUX_DOCK, the superspeed signals can remain + * connected. For USB_PD_MUX_DP_ENABLED, disconnect the + * superspeed signals here, before the pins are re-configured + * to DisplayPort (in svdm_dp_post_config, when we receive + * the config ack). + */ + if (svdm_dp_get_mux_mode(port) == USB_PD_MUX_DP_ENABLED) { + usb_mux_set_safe_mode(port); + return MSG_SETUP_MUX_WAIT; + } + /* Fall through if no mux set is needed */ + __fallthrough; + case DP_PREPARE_CONFIG: + vdo_count_ret = svdm_dp_config(port, vdm); if (vdo_count_ret == 0) - return -1; + return MSG_SETUP_ERROR; vdm[0] |= VDO_CMDT(CMDT_INIT); - vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)); + vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)); break; case DP_ENTER_NAKED: + DP_SET_FLAG(port, DP_FLAG_RETRY); + /* Fall through to send exit mode */ + __fallthrough; case DP_ACTIVE: /* * Called to exit DP alt mode, either when the mode @@ -240,31 +332,339 @@ int dp_setup_next_vdm(int port, int vdo_count, uint32_t *vdm) * when an initial request to enter the mode is NAK'ed. * This can happen if the EC is restarted (e.g to go * into recovery mode) while DP alt mode is active. - * It would be good to invoke modep->fx->exit but - * this doesn't set up the VDM, it clears state. - * TODO(b/159856063): Clean up the API to the fx functions. */ - if (!(modep && modep->opos)) - return -1; - - vdm[0] = VDO(USB_SID_DISPLAYPORT, - 1, /* structured */ + usb_mux_set_safe_mode_exit(port); + dp_state[port] = DP_PREPARE_EXIT; + return MSG_SETUP_MUX_WAIT; + case DP_PREPARE_EXIT: + /* DPM should call setup only after safe state is set */ + vdm[0] = VDO(USB_SID_DISPLAYPORT, 1, /* structured */ CMD_EXIT_MODE); - vdm[0] |= VDO_OPOS(modep->opos); + vdm[0] |= VDO_OPOS(dp_opos); vdm[0] |= VDO_CMDT(CMDT_INIT); - vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)); + vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)); vdo_count_ret = 1; break; case DP_INACTIVE: /* * DP mode is inactive. */ - return -1; + return MSG_SETUP_ERROR; default: - CPRINTF("%s called with invalid state %d\n", - __func__, dp_state[port]); + CPRINTF("%s called with invalid state %d\n", __func__, + dp_state[port]); + return MSG_SETUP_ERROR; + } + + if (vdo_count_ret) { + *vdo_count = vdo_count_ret; + return MSG_SETUP_SUCCESS; + } + + return MSG_SETUP_UNSUPPORTED; +} + +int svdm_dp_status(int port, uint32_t *payload) +{ + payload[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_STATUS | VDO_OPOS(dp_opos)); + payload[1] = VDO_DP_STATUS(0, /* HPD IRQ ... not applicable */ + 0, /* HPD level ... not applicable */ + 0, /* exit DP? ... no */ + 0, /* usb mode? ... no */ + 0, /* multi-function ... no */ + (!!(dp_flags[port] & DP_FLAGS_DP_ON)), + 0, /* power low? ... no */ + (!!DP_FLAGS_DP_ON)); + return 2; +}; + +/* + * This algorithm defaults to choosing higher pin config over lower ones in + * order to prefer multi-function if desired. + * + * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG + * ------------------------------------------------------------- + * A | USB G2 | ? | no | 00_0001 + * B | USB G2 | ? | yes | 00_0010 + * C | DP | CONVERTED | no | 00_0100 + * D | PD | CONVERTED | yes | 00_1000 + * E | DP | DP | no | 01_0000 + * F | PD | DP | yes | 10_0000 + * + * if UFP has NOT asserted multi-function preferred code masks away B/D/F + * leaving only A/C/E. For single-output dongles that should leave only one + * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP + * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C + * receptacle must always choose C/D in those cases. + */ +int pd_dfp_dp_get_pin_mode(int port, uint32_t status) +{ + uint32_t mode_vdos[VDO_MAX_OBJECTS]; + uint32_t mode_caps; + uint32_t pin_caps; + int mf_pref; + + /* + * Default dp_port_mf_allow is true, we allow mf operation + * if UFP_D supports it. + */ + + if (IS_ENABLED(CONFIG_CMD_MFALLOW)) + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]) && + dp_port_mf_allow[port]; + else + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); + + if (pd_get_mode_vdo_for_svid(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT, + mode_vdos) == 0) + return 0; + + mode_caps = mode_vdos[dp_opos - 1]; + + /* TODO(crosbug.com/p/39656) revisit with DFP that can be a sink */ + pin_caps = PD_DP_PIN_CAPS(mode_caps); + + /* if don't want multi-function then ignore those pin configs */ + if (!mf_pref) + pin_caps &= ~MODE_DP_PIN_MF_MASK; + + /* TODO(crosbug.com/p/39656) revisit if DFP drives USB Gen 2 signals */ + pin_caps &= ~MODE_DP_PIN_BR2_MASK; + + /* if C/D present they have precedence over E/F for USB-C->USB-C */ + if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D)) + pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F); + + /* get_next_bit returns undefined for zero */ + if (!pin_caps) + return 0; + + return 1 << get_next_bit(&pin_caps); +} + +mux_state_t svdm_dp_get_mux_mode(int port) +{ + int pin_mode = get_dp_pin_mode(port); + /* Default dp_port_mf_allow is true */ + int mf_pref; + + if (IS_ENABLED(CONFIG_CMD_MFALLOW)) + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]) && + dp_port_mf_allow[port]; + else + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); + + /* + * Multi-function operation is only allowed if that pin config is + * supported. + */ + if ((pin_mode & MODE_DP_PIN_MF_MASK) && mf_pref) + return USB_PD_MUX_DOCK; + else + return USB_PD_MUX_DP_ENABLED; +} + +/* + * Note: the following DP-related overridables must be kept as-is since + * some boards are using them in their board-specific code. + * TODO(b/267545470): Fold board DP code into the DP module + */ +__overridable void svdm_safe_dp_mode(int port) +{ + /* make DP interface safe until configure */ + dp_flags[port] = 0; + dp_status[port] = 0; + + usb_mux_set_safe_mode(port); +} + +__overridable int svdm_enter_dp_mode(int port, uint32_t mode_caps) +{ + /* + * Don't enter the mode if the SoC is off. + * + * There's no need to enter the mode while the SoC is off; we'll + * actually enter the mode on the chipset resume hook. Entering DP Alt + * Mode twice will confuse some monitors and require and unplug/replug + * to get them to work again. The DP Alt Mode on USB-C spec says that + * if we don't need to maintain HPD connectivity info in a low power + * mode, then we shall exit DP Alt Mode. (This is why we don't enter + * when the SoC is off as opposed to suspend where adding a display + * could cause a wake up.) When in S5->S3 transition state, we + * should treat it as a SoC off state. + */ +#ifdef CONFIG_AP_POWER_CONTROL + if (!chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON)) return -1; +#endif + + /* + * TCPMv2: Enable logging of CCD line state CCD_MODE_ODL. + * DisplayPort Alternate mode requires that the SBU lines are + * used for AUX communication. However, in Chromebooks SBU + * signals are repurposed as USB2 signals for CCD. This + * functionality is accomplished by override fets whose state is + * controlled by CCD_MODE_ODL. + * + * This condition helps in debugging unexpected AUX timeout + * issues by indicating the state of the CCD override fets. + */ +#ifdef GPIO_CCD_MODE_ODL + if (!gpio_get_level(GPIO_CCD_MODE_ODL)) + CPRINTS("WARNING: Tried to EnterMode DP with [CCD on AUX/SBU]"); +#endif + + /* Only enter mode if device is DFP_D capable */ + if (mode_caps & MODE_DP_SNK) { + svdm_safe_dp_mode(port); + + if (IS_ENABLED(CONFIG_MKBP_EVENT) && + chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) + /* + * Wake the system up since we're entering DP AltMode. + */ + pd_notify_dp_alt_mode_entry(port); + + return 0; } - return vdo_count_ret; + + return -1; +} + +__overridable uint8_t get_dp_pin_mode(int port) +{ + return pd_dfp_dp_get_pin_mode(port, dp_status[port]); } + +/* Note: Assumes that pins have already been set in safe state if necessary */ +__overridable int svdm_dp_config(int port, uint32_t *payload) +{ + uint8_t pin_mode = get_dp_pin_mode(port); + mux_state_t mux_mode = svdm_dp_get_mux_mode(port); + /* Default dp_port_mf_allow is true */ + int mf_pref; + + if (IS_ENABLED(CONFIG_CMD_MFALLOW)) + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]) && + dp_port_mf_allow[port]; + else + mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); + + if (!pin_mode) + return 0; + + CPRINTS("pin_mode: %x, mf: %d, mux: %d", pin_mode, mf_pref, mux_mode); + + payload[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(dp_opos)); + payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ + 1, /* DPv1.3 signaling */ + 2); /* UFP connected */ + return 2; +}; + +__overridable void svdm_dp_post_config(int port) +{ + mux_state_t mux_mode = svdm_dp_get_mux_mode(port); + /* Connect the SBU and USB lines to the connector. */ + typec_set_sbu(port, true); + + usb_mux_set(port, mux_mode, USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); + + dp_flags[port] |= DP_FLAGS_DP_ON; + if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) + return; + + dp_hpd_gpio_set(port, true, false); + + usb_mux_hpd_update(port, + USB_PD_MUX_HPD_LVL | USB_PD_MUX_HPD_IRQ_DEASSERTED); + +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, 1); +#endif +} + +__overridable int svdm_dp_attention(int port, uint32_t *payload) +{ + int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); + int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); + mux_state_t mux_state; + + dp_status[port] = payload[1]; + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && (irq || lvl)) + /* + * Wake up the AP. IRQ or level high indicates a DP sink is now + * present. + */ + if (IS_ENABLED(CONFIG_MKBP_EVENT)) + pd_notify_dp_alt_mode_entry(port); + + /* Its initial DP status message prior to config */ + if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { + if (lvl) + dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; + return 1; + } + + if (dp_hpd_gpio_set(port, lvl, irq) != EC_SUCCESS) + return 0; + + mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | + (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); + usb_mux_hpd_update(port, mux_state); + +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, lvl); +#endif + + /* ack */ + return 1; +} + +__overridable void svdm_exit_dp_mode(int port) +{ + dp_flags[port] = 0; + dp_status[port] = 0; + dp_hpd_gpio_set(port, false, false); + usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | + USB_PD_MUX_HPD_IRQ_DEASSERTED); +#ifdef USB_PD_PORT_TCPC_MST + if (port == USB_PD_PORT_TCPC_MST) + baseboard_mst_enable_control(port, 0); +#endif +} + +#ifdef CONFIG_CMD_MFALLOW +static int command_mfallow(int argc, const char **argv) +{ + char *e; + int port; + + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + + port = strtoi(argv[1], &e, 10); + if (*e || port >= board_get_usb_pd_port_count()) + return EC_ERROR_PARAM1; + + if (!strcasecmp(argv[2], "true")) + dp_port_mf_allow[port] = true; + else if (!strcasecmp(argv[2], "false")) + dp_port_mf_allow[port] = false; + else + return EC_ERROR_PARAM2; + + ccprintf("Port: %d multi function allowed is %s ", port, argv[2]); + return EC_SUCCESS; +} + +DECLARE_CONSOLE_COMMAND(mfallow, command_mfallow, "port [true | false]", + "Controls Multifunction choice during DP Altmode."); +#endif diff --git a/common/usbc/dp_hpd_gpio.c b/common/usbc/dp_hpd_gpio.c new file mode 100644 index 0000000000..3a3e75da00 --- /dev/null +++ b/common/usbc/dp_hpd_gpio.c @@ -0,0 +1,83 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Support for setting the Hot Plug Detect indication to the AP + */ + +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "timer.h" +#include "usb_pd.h" + +#include +#include + +#ifdef CONFIG_COMMON_RUNTIME +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) +#else +#define CPRINTF(format, args...) +#define CPRINTS(format, args...) +#endif + +/* TODO(b/270409742): Remove this macro system for determining the GPIO */ +#ifndef PORT_TO_HPD +#define PORT_TO_HPD(port) ((port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD) +#endif /* PORT_TO_HPD */ + +/* + * Note: the following DP-related variables and functions must be kept + * as-is since some boards are using them in their board-specific code. + * TODO(b/267545470): Fold board DP code into the DP module + */ + +#if defined(CONFIG_USB_PD_DP_HPD_GPIO) && \ + !defined(CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM) +void svdm_set_hpd_gpio(int port, int en) +{ + gpio_set_level(PORT_TO_HPD(port), en); +} + +int svdm_get_hpd_gpio(int port) +{ + return gpio_get_level(PORT_TO_HPD(port)); +} +#endif + +enum ec_error_list dp_hpd_gpio_set(int port, bool level, bool irq) +{ + int cur_level = svdm_get_hpd_gpio(port); + + if (irq && !level) { + /* + * IRQ can only be generated when the level is high, because + * the IRQ is signaled by a short low pulse from the high level. + */ + CPRINTF("ERR:HPD:IRQ&LOW\n"); + return EC_ERROR_INVAL; + } + + if (irq && cur_level) { + uint64_t now = get_time().val; + /* wait for the minimum spacing between IRQ_HPD if needed */ + if (now < svdm_hpd_deadline[port]) + usleep(svdm_hpd_deadline[port] - now); + + /* generate IRQ_HPD pulse */ + svdm_set_hpd_gpio(port, 0); + usleep(HPD_DSTREAM_DEBOUNCE_IRQ); + svdm_set_hpd_gpio(port, 1); + } else { + svdm_set_hpd_gpio(port, level); + } + + /* set the minimum time delay (2ms) for the next HPD IRQ */ + svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; + + return EC_SUCCESS; +} diff --git a/common/usbc/svdm_rsp_dfp_only.c b/common/usbc/svdm_rsp_dfp_only.c new file mode 100644 index 0000000000..ee2b11a379 --- /dev/null +++ b/common/usbc/svdm_rsp_dfp_only.c @@ -0,0 +1,50 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * SVDM identity support for DFP-only devices. + * + * This file is only supported for Zephyr builds, enabled by + * CONFIG_SVDM_RSP_DFP_ONLY. No equivalent config exists for EC-OS. + */ + +#include "usb_pd.h" + +static int svdm_identity(int port, uint32_t *payload) +{ + if (pd_get_rev(port, TCPCI_MSG_SOP) < PD_REV30) { + /* + * PD 2 requires that DFPs nack received SVDM requests when no + * modes are supported. PD 3 allows a response. + */ + return 0; + } + + payload[VDO_I(CSTAT)] = VDO_CSTAT(CONFIG_USB_PD_XID); + payload[VDO_I(PRODUCT)] = + VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); + + payload[VDO_I(IDH)] = VDO_IDH_REV30(1, /* USB host */ + 0, /* Not a USB device */ + IDH_PTYPE_UNDEF, /* Not a UFP */ + 0, /* No alt modes (not a UFP) */ + IDH_PTYPE_DFP_HOST, /* PDUSB host */ + USB_TYPEC_RECEPTACLE, + CONFIG_USB_VID); + /* Single VDO for DFP product type */ + payload[VDO_I(PRODUCT) + 1] = VDO_DFP(VDO_DFP_HOST_CAPABILITY_USB32, + USB_TYPEC_RECEPTACLE, port); + return VDO_I(PRODUCT) + 2; +} + +__override const struct svdm_response svdm_rsp = { + .identity = svdm_identity, + /* + * Discover Identity support is required for devices with more than one + * DFP, but other SVDM commands are optional. We don't support operating + * as Responder in any mode, so leave them unimplemented. See 6.13.5, + * Applicability of Structured VDM Commands. + */ +}; diff --git a/common/usbc/tbt_alt_mode.c b/common/usbc/tbt_alt_mode.c index 4b79f26efb..5c02eb30fb 100644 --- a/common/usbc/tbt_alt_mode.c +++ b/common/usbc/tbt_alt_mode.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,18 +8,22 @@ * Refer to USB Type-C Cable and Connector Specification Release 2.0 Section F */ -#include -#include +#include "atomic.h" #include "compile_time_macros.h" #include "console.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" +#include "typec_control.h" +#include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" -#include "usb_pd_dpm.h" #include "usb_pd_tbt.h" +#include "usb_pd_tcpm.h" #include "usb_pe_sm.h" #include "usb_tbt_alt_mode.h" +#include +#include + /* * Enter/Exit TBT mode with active cable * @@ -55,8 +59,8 @@ */ #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else #define CPRINTF(format, args...) #define CPRINTS(format, args...) @@ -68,7 +72,18 @@ * with a partner. It may be fixed in b/159495742, in which case this * logic is unneeded. */ -static bool retry_done; +#define TBT_FLAG_RETRY_DONE BIT(0) +#define TBT_FLAG_EXIT_DONE BIT(1) +#define TBT_FLAG_CABLE_ENTRY_DONE BIT(2) + +static uint8_t tbt_flags[CONFIG_USB_PD_PORT_MAX_COUNT]; + +#define TBT_SET_FLAG(port, flag) (tbt_flags[port] |= (flag)) +#define TBT_CLR_FLAG(port, flag) (tbt_flags[port] &= (~flag)) +#define TBT_CHK_FLAG(port, flag) (tbt_flags[port] & (flag)) + +/* Note: there is currently only one defined TBT mode */ +static const int tbt_opos = 1; static int tbt_prints(const char *string, int port) { @@ -80,6 +95,8 @@ enum tbt_states { TBT_START = 0, TBT_ENTER_SOP, TBT_ACTIVE, + /* Set to force Exit mode from non-Active states */ + TBT_PREPARE_EXIT_MODE, TBT_EXIT_SOP, TBT_INACTIVE, /* Active cable only */ @@ -93,7 +110,6 @@ static enum tbt_states tbt_state[CONFIG_USB_PD_PORT_MAX_COUNT]; static const uint8_t state_vdm_cmd[TBT_STATE_COUNT] = { [TBT_ENTER_SOP] = CMD_ENTER_MODE, - [TBT_ACTIVE] = CMD_EXIT_MODE, [TBT_EXIT_SOP] = CMD_EXIT_MODE, /* Active cable only */ [TBT_ENTER_SOP_PRIME] = CMD_ENTER_MODE, @@ -105,33 +121,117 @@ static const uint8_t state_vdm_cmd[TBT_STATE_COUNT] = { void tbt_init(int port) { tbt_state[port] = TBT_START; - retry_done = false; + TBT_CLR_FLAG(port, TBT_FLAG_RETRY_DONE); + TBT_SET_FLAG(port, TBT_FLAG_EXIT_DONE); + TBT_CLR_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE); } bool tbt_is_active(int port) { - return tbt_state[port] == TBT_ACTIVE; + return tbt_state[port] != TBT_INACTIVE && tbt_state[port] != TBT_START; +} + +bool tbt_entry_is_done(int port) +{ + return tbt_state[port] == TBT_ACTIVE || tbt_state[port] == TBT_INACTIVE; } -void tbt_teardown(int port) +bool tbt_cable_entry_is_done(int port) { - tbt_prints("teardown", port); - tbt_state[port] = TBT_INACTIVE; - retry_done = false; + return TBT_CHK_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE); } -static void tbt_entry_failed(int port) +static void tbt_exit_done(int port) { + /* + * If the EC exits an alt mode autonomously, don't try to enter it + * again. If the AP commands the EC to exit DP mode, it might command + * the EC to enter again later, so leave the state machine ready for + * that possibility. + */ + tbt_state[port] = IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) ? + TBT_START : + TBT_INACTIVE; + TBT_CLR_FLAG(port, TBT_FLAG_RETRY_DONE); + TBT_CLR_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE); + + if (!TBT_CHK_FLAG(port, TBT_FLAG_EXIT_DONE)) { + TBT_SET_FLAG(port, TBT_FLAG_EXIT_DONE); + tbt_prints("Exited alternate mode", port); + return; + } + tbt_prints("alt mode protocol failed!", port); - tbt_state[port] = TBT_INACTIVE; - retry_done = false; - dpm_set_mode_entry_done(port); } -static bool tbt_response_valid(int port, enum tcpm_transmit_type type, - char *cmdt, int vdm_cmd) +static bool tbt_is_lrd_active_cable(int port) +{ + union tbt_mode_resp_cable cable_mode_resp; + + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); + if (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE && + cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE) + return true; + + return false; +} + +/* Check if this port requires SOP' mode entry and exit */ +static bool tbt_sop_prime_needed(int port) +{ + /* + * We require SOP' entry if cable is + * active cable, or + * an LRD cable (passive in DiscoverIdentity, active in TBT mode) + */ + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE || + tbt_is_lrd_active_cable(port)) + return true; + return false; +} + +/* Check if this port requires SOP'' mode entry and exit */ +static bool tbt_sop_prime_prime_needed(int port) +{ + const struct pd_discovery *disc; + + disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE && + disc->identity.product_t1.a_rev20.sop_p_p) + return true; + return false; +} + +void tbt_exit_mode_request(int port) +{ + TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE); + TBT_CLR_FLAG(port, TBT_FLAG_EXIT_DONE); + /* + * If the port has entered USB4 mode with Thunderbolt mode for the + * cable, on request to exit, only exit Thunderbolt mode for the + * cable. + * TODO (b/156749387): Remove once data reset feature is in place. + */ + if (tbt_state[port] == TBT_ENTER_SOP) { + /* + * For Linear re-driver cables, the port enters USB4 mode + * with Thunderbolt mode for SOP prime. Hence, on request to + * exit, only exit Thunderbolt mode SOP prime + */ + tbt_state[port] = tbt_sop_prime_prime_needed(port) ? + TBT_EXIT_SOP_PRIME_PRIME : + TBT_EXIT_SOP_PRIME; + } +} + +static bool tbt_response_valid(int port, enum tcpci_msg_type type, char *cmdt, + int vdm_cmd) { enum tbt_states st = tbt_state[port]; + union tbt_mode_resp_cable cable_mode_resp = { + .raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME) + }; /* * Check for an unexpected response. @@ -141,8 +241,9 @@ static bool tbt_response_valid(int port, enum tcpm_transmit_type type, */ if ((st != TBT_INACTIVE && state_vdm_cmd[st] != vdm_cmd) || (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE && - type != TCPC_TX_SOP)) { - tbt_entry_failed(port); + cable_mode_resp.tbt_active_passive == TBT_CABLE_PASSIVE && + type != TCPCI_MSG_SOP)) { + tbt_exit_done(port); return false; } return true; @@ -152,83 +253,101 @@ static bool tbt_response_valid(int port, enum tcpm_transmit_type type, static void tbt_retry_enter_mode(int port) { tbt_state[port] = TBT_START; - retry_done = true; + TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE); } -/* Send Exit Mode to SOP''(if supported), or SOP' */ -static void tbt_active_cable_exit_mode(int port) +bool tbt_cable_entry_required_for_usb4(int port) { - struct pd_discovery *disc; + const struct pd_discovery *disc_sop_prime; - disc = pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); + if (tbt_cable_entry_is_done(port)) + return false; - if (disc->identity.product_t1.a_rev20.sop_p_p) - tbt_state[port] = TBT_EXIT_SOP_PRIME_PRIME; - else - tbt_state[port] = TBT_EXIT_SOP_PRIME; + /* + * For some cables, the TCPM may need to enter TBT mode with the + * cable to support USB4 mode with the partner. Request to enter + * Thunderbolt mode for the cable prior to entering USB4 for + * the port partner if + * 1. The cable advertises itself as passive in its Identity VDO + * but active in its TBT mode VDO, or + * 2. The cable advertises itself as active, but its PD support + * is not new enough to support Enter_USB. + */ + if (tbt_is_lrd_active_cable(port)) + return true; + + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) { + disc_sop_prime = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + if (pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME) < VDM_VER20 || + disc_sop_prime->identity.product_t1.a_rev30.vdo_ver < + VDO_VERSION_1_3) + return true; + } + return false; } -void intel_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, - uint32_t *vdm) +void intel_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count, + uint32_t *vdm) { - struct pd_discovery *disc; const uint8_t vdm_cmd = PD_VDO_CMD(vdm[0]); if (!tbt_response_valid(port, type, "ACK", vdm_cmd)) return; - disc = pd_get_am_discovery(port, TCPC_TX_SOP_PRIME); - switch (tbt_state[port]) { case TBT_ENTER_SOP_PRIME: - if (disc->identity.product_t1.a_rev20.sop_p_p) + tbt_prints("enter mode SOP'", port); + /* For LRD cables, Enter mode SOP' -> Enter mode SOP */ + if (tbt_sop_prime_prime_needed(port)) { tbt_state[port] = TBT_ENTER_SOP_PRIME_PRIME; - else + } else { + TBT_SET_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE); tbt_state[port] = TBT_ENTER_SOP; + } break; case TBT_ENTER_SOP_PRIME_PRIME: + tbt_prints("enter mode SOP''", port); + TBT_SET_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE); tbt_state[port] = TBT_ENTER_SOP; break; case TBT_ENTER_SOP: set_tbt_compat_mode_ready(port); - dpm_set_mode_entry_done(port); tbt_state[port] = TBT_ACTIVE; - retry_done = true; tbt_prints("enter mode SOP", port); - break; - case TBT_ACTIVE: - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) - tbt_active_cable_exit_mode(port); - else { - /* - * Exit Mode process is complete; go to inactive state. - */ - tbt_prints("exit mode SOP", port); - tbt_state[port] = TBT_INACTIVE; - retry_done = false; - } + TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE); + /* Indicate to PE layer that alt mode is active */ + pd_set_dfp_enter_mode_flag(port, true); break; case TBT_EXIT_SOP: - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) - tbt_active_cable_exit_mode(port); - else { - if (retry_done) + tbt_prints("exit mode SOP", port); + pd_set_dfp_enter_mode_flag(port, false); + + if (tbt_sop_prime_prime_needed(port)) { + tbt_state[port] = TBT_EXIT_SOP_PRIME_PRIME; + } else if (tbt_sop_prime_needed(port)) { + tbt_state[port] = TBT_EXIT_SOP_PRIME; + } else { + set_usb_mux_with_current_data_role(port); + if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE)) /* retried enter mode, still failed, give up */ - tbt_entry_failed(port); + tbt_exit_done(port); else tbt_retry_enter_mode(port); } break; case TBT_EXIT_SOP_PRIME_PRIME: + tbt_prints("exit mode SOP''", port); tbt_state[port] = TBT_EXIT_SOP_PRIME; break; case TBT_EXIT_SOP_PRIME: - if (retry_done) { + tbt_prints("exit mode SOP'", port); + if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE)) { /* * Exit mode process is complete; go to inactive state. */ - tbt_prints("exit mode SOP'", port); - tbt_entry_failed(port); + tbt_exit_done(port); + /* Clear Thunderbolt related signals */ + set_usb_mux_with_current_data_role(port); } else { tbt_retry_enter_mode(port); } @@ -242,14 +361,14 @@ void intel_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, break; default: /* Invalid or unexpected negotiation state */ - CPRINTF("%s called with invalid state %d\n", - __func__, tbt_state[port]); - tbt_entry_failed(port); + CPRINTF("%s called with invalid state %d\n", __func__, + tbt_state[port]); + tbt_exit_done(port); break; } } -void intel_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd) +void intel_vdm_naked(int port, enum tcpci_msg_type type, uint8_t vdm_cmd) { if (!tbt_response_valid(port, type, "NAK", vdm_cmd)) return; @@ -264,26 +383,21 @@ void intel_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd) * so request to exit the mode first before retrying the enter * command. This can happen if the EC is restarted */ - tbt_state[port] = TBT_EXIT_SOP; - break; - case TBT_ACTIVE: - /* Exit SOP got NAK'ed */ - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) - tbt_active_cable_exit_mode(port); - else { - tbt_prints("exit mode SOP failed", port); - tbt_state[port] = TBT_INACTIVE; - retry_done = false; - } + tbt_state[port] = TBT_PREPARE_EXIT_MODE; break; case TBT_EXIT_SOP: /* Exit SOP got NAK'ed */ - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) - tbt_active_cable_exit_mode(port); - else { - if (retry_done) + tbt_prints("exit mode SOP failed", port); + + if (tbt_sop_prime_prime_needed(port)) { + tbt_state[port] = TBT_EXIT_SOP_PRIME_PRIME; + } else if (tbt_sop_prime_needed(port)) { + tbt_state[port] = TBT_EXIT_SOP_PRIME; + } else { + set_usb_mux_with_current_data_role(port); + if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE)) /* Retried enter mode, still failed, give up */ - tbt_entry_failed(port); + tbt_exit_done(port); else tbt_retry_enter_mode(port); } @@ -293,20 +407,21 @@ void intel_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd) tbt_state[port] = TBT_EXIT_SOP_PRIME; break; case TBT_EXIT_SOP_PRIME: - if (retry_done) { + set_usb_mux_with_current_data_role(port); + if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE)) { /* * Exit mode process is complete; go to inactive state. */ tbt_prints("exit mode SOP' failed", port); - tbt_entry_failed(port); + tbt_exit_done(port); } else { tbt_retry_enter_mode(port); } break; default: - CPRINTS("C%d: NAK for cmd %d in state %d", port, - vdm_cmd, tbt_state[port]); - tbt_entry_failed(port); + CPRINTS("C%d: NAK for cmd %d in state %d", port, vdm_cmd, + tbt_state[port]); + tbt_exit_done(port); break; } } @@ -314,117 +429,306 @@ void intel_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd) static bool tbt_mode_is_supported(int port, int vdo_count) { const struct pd_discovery *disc = - pd_get_am_discovery(port, TCPC_TX_SOP); + pd_get_am_discovery(port, TCPCI_MSG_SOP); + + if (!disc->identity.idh.modal_support) + return false; + + if (get_tbt_cable_speed(port) < TBT_SS_U31_GEN1) + return false; + + /* + * TBT4 PD Discovery Flow Application Notes Revision 0.9: + * Figure 2: for active cable, SOP' should support + * SVID USB_VID_INTEL to enter Thunderbolt alt mode + */ + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE && + !pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP_PRIME, + USB_VID_INTEL)) + return false; - return disc->identity.idh.modal_support && - is_tbt_cable_superspeed(port) && - get_tbt_cable_speed(port) >= TBT_SS_U31_GEN1; + return true; } -int tbt_setup_next_vdm(int port, int vdo_count, uint32_t *vdm, - enum tcpm_transmit_type *tx_type) +enum dpm_msg_setup_status tbt_setup_next_vdm(int port, int *vdo_count, + uint32_t *vdm, + enum tcpci_msg_type *tx_type) { - struct svdm_amode_data *modep; int vdo_count_ret = 0; - *tx_type = TCPC_TX_SOP; + *tx_type = TCPCI_MSG_SOP; - if (vdo_count < VDO_MAX_SIZE) - return -1; + if (*vdo_count < VDO_MAX_SIZE) + return MSG_SETUP_ERROR; switch (tbt_state[port]) { case TBT_START: - if (!tbt_mode_is_supported(port, vdo_count)) - return 0; + if (!tbt_mode_is_supported(port, *vdo_count)) + return MSG_SETUP_UNSUPPORTED; - if (!retry_done) + if (!TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE)) tbt_prints("attempt to enter mode", port); else tbt_prints("retry to enter mode", port); - /* Active cable send Enter Mode SOP' first */ - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) { - vdo_count_ret = - enter_tbt_compat_mode( - port, TCPC_TX_SOP_PRIME, vdm); - *tx_type = TCPC_TX_SOP_PRIME; + + /* + * Enter safe mode before sending Enter mode SOP/SOP'/SOP'' + * Ref: Tiger Lake Platform PD Controller Interface + * Requirements for Integrated USB C, section A.1.2 TBT as DFP. + */ + usb_mux_set_safe_mode(port); + + /* Active cable and LRD cables send Enter Mode SOP' first */ + if (tbt_sop_prime_needed(port)) { tbt_state[port] = TBT_ENTER_SOP_PRIME; } else { /* Passive cable send Enter Mode SOP */ - vdo_count_ret = - enter_tbt_compat_mode(port, TCPC_TX_SOP, vdm); tbt_state[port] = TBT_ENTER_SOP; } - break; + + return MSG_SETUP_MUX_WAIT; case TBT_ENTER_SOP_PRIME: vdo_count_ret = - enter_tbt_compat_mode(port, TCPC_TX_SOP_PRIME, vdm); - *tx_type = TCPC_TX_SOP_PRIME; + enter_tbt_compat_mode(port, TCPCI_MSG_SOP_PRIME, vdm); + *tx_type = TCPCI_MSG_SOP_PRIME; break; case TBT_ENTER_SOP_PRIME_PRIME: - vdo_count_ret = - enter_tbt_compat_mode( - port, TCPC_TX_SOP_PRIME_PRIME, vdm); - *tx_type = TCPC_TX_SOP_PRIME_PRIME; + vdo_count_ret = enter_tbt_compat_mode( + port, TCPCI_MSG_SOP_PRIME_PRIME, vdm); + *tx_type = TCPCI_MSG_SOP_PRIME_PRIME; break; case TBT_ENTER_SOP: - vdo_count_ret = - enter_tbt_compat_mode(port, TCPC_TX_SOP, vdm); + vdo_count_ret = enter_tbt_compat_mode(port, TCPCI_MSG_SOP, vdm); break; - case TBT_EXIT_SOP: case TBT_ACTIVE: + /* + * Since we had successfully entered mode, consider ourselves + * done with any retires. + */ + TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE); + __fallthrough; + case TBT_PREPARE_EXIT_MODE: /* * Called to exit Thunderbolt alt mode, either when the mode is * active and the system is shutting down, or when an initial * request to enter the mode is NAK'ed. This can happen if EC * is restarted while Thunderbolt mode is active. */ - modep = pd_get_amode_data(port, - TCPC_TX_SOP, USB_VID_INTEL); - if (!(modep && modep->opos)) - return -1; + usb_mux_set_safe_mode_exit(port); + tbt_state[port] = TBT_EXIT_SOP; + return MSG_SETUP_MUX_WAIT; + case TBT_EXIT_SOP: + /* DPM will only call this after safe state set is done */ vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) | - VDO_OPOS(modep->opos) | - VDO_CMDT(CMDT_INIT) | - VDO_SVDM_VERS( - pd_get_vdo_ver(port, TCPC_TX_SOP)); + VDO_OPOS(tbt_opos) | VDO_CMDT(CMDT_INIT) | + VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)); vdo_count_ret = 1; break; case TBT_EXIT_SOP_PRIME_PRIME: - modep = pd_get_amode_data(port, - TCPC_TX_SOP_PRIME, USB_VID_INTEL); - if (!(modep && modep->opos)) - return -1; - vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) | - VDO_OPOS(modep->opos) | - VDO_CMDT(CMDT_INIT) | - VDO_SVDM_VERS(pd_get_vdo_ver(port, - TCPC_TX_SOP_PRIME_PRIME)); + VDO_OPOS(tbt_opos) | VDO_CMDT(CMDT_INIT) | + VDO_SVDM_VERS(pd_get_vdo_ver( + port, TCPCI_MSG_SOP_PRIME_PRIME)); vdo_count_ret = 1; - *tx_type = TCPC_TX_SOP_PRIME_PRIME; + *tx_type = TCPCI_MSG_SOP_PRIME_PRIME; break; case TBT_EXIT_SOP_PRIME: - modep = pd_get_amode_data(port, - TCPC_TX_SOP_PRIME, USB_VID_INTEL); - if (!(modep && modep->opos)) - return -1; - vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) | - VDO_OPOS(modep->opos) | - VDO_CMDT(CMDT_INIT) | - VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP_PRIME)); + VDO_OPOS(tbt_opos) | VDO_CMDT(CMDT_INIT) | + VDO_SVDM_VERS( + pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME)); vdo_count_ret = 1; - *tx_type = TCPC_TX_SOP_PRIME; + *tx_type = TCPCI_MSG_SOP_PRIME; break; case TBT_INACTIVE: /* Thunderbolt mode is inactive */ - return 0; + return MSG_SETUP_UNSUPPORTED; default: - CPRINTF("%s called with invalid state %d\n", - __func__, tbt_state[port]); - return -1; + CPRINTF("%s called with invalid state %d\n", __func__, + tbt_state[port]); + return MSG_SETUP_ERROR; } - return vdo_count_ret; + if (vdo_count_ret) { + *vdo_count = vdo_count_ret; + return MSG_SETUP_SUCCESS; + } + + return MSG_SETUP_UNSUPPORTED; +} + +uint32_t pd_get_tbt_mode_vdo(int port, enum tcpci_msg_type type) +{ + uint32_t tbt_mode_vdo[VDO_MAX_OBJECTS]; + + return pd_get_mode_vdo_for_svid(port, type, USB_VID_INTEL, + tbt_mode_vdo) ? + tbt_mode_vdo[0] : + 0; +} + +void set_tbt_compat_mode_ready(int port) +{ + if (IS_ENABLED(CONFIG_USBC_SS_MUX) && + IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) { + /* Connect the SBU and USB lines to the connector. */ + typec_set_sbu(port, true); + + /* Set usb mux to Thunderbolt-compatible mode */ + usb_mux_set(port, USB_PD_MUX_TBT_COMPAT_ENABLED, + USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); + } +} + +/* + * Ref: USB Type-C Cable and Connector Specification + * Figure F-1 TBT3 Discovery Flow + */ +static bool is_tbt_cable_superspeed(int port) +{ + const struct pd_discovery *disc; + + if (!IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) || + !IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) + return false; + + disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + + /* Product type is Active cable, hence don't check for speed */ + if (disc->identity.idh.product_type == IDH_PTYPE_ACABLE) + return true; + + if (disc->identity.idh.product_type != IDH_PTYPE_PCABLE) + return false; + + if (IS_ENABLED(CONFIG_USB_PD_REV30) && + pd_get_rev(port, TCPCI_MSG_SOP_PRIME) == PD_REV30) + return disc->identity.product_t1.p_rev30.ss == + USB_R30_SS_U32_U40_GEN1 || + disc->identity.product_t1.p_rev30.ss == + USB_R30_SS_U32_U40_GEN2 || + disc->identity.product_t1.p_rev30.ss == + USB_R30_SS_U40_GEN3; + + return disc->identity.product_t1.p_rev20.ss == USB_R20_SS_U31_GEN1 || + disc->identity.product_t1.p_rev20.ss == USB_R20_SS_U31_GEN1_GEN2; +} + +static enum tbt_compat_cable_speed usb_rev30_to_tbt_speed(enum usb_rev30_ss ss) +{ + switch (ss) { + case USB_R30_SS_U32_U40_GEN1: + return TBT_SS_U31_GEN1; + case USB_R30_SS_U32_U40_GEN2: + return TBT_SS_U32_GEN1_GEN2; + case USB_R30_SS_U40_GEN3: + return TBT_SS_TBT_GEN3; + default: + return TBT_SS_U32_GEN1_GEN2; + } +} + +enum tbt_compat_cable_speed get_tbt_cable_speed(int port) +{ + union tbt_mode_resp_cable cable_mode_resp; + enum tbt_compat_cable_speed max_tbt_speed; + enum tbt_compat_cable_speed cable_tbt_speed; + + if (!is_tbt_cable_superspeed(port)) + return TBT_SS_RES_0; + + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); + max_tbt_speed = board_get_max_tbt_speed(port); + + /* + * Ref: TBT4 PD Discovery Flow Application Notes Revision 0.9, Figure 2 + * For passive cable, if cable doesn't support USB_VID_INTEL, enter + * Thunderbolt alternate mode with speed from USB Highest Speed field of + * the Passive Cable VDO + * For active cable, if the cable doesn't support USB_VID_INTEL, do not + * enter Thunderbolt alternate mode. + */ + if (!cable_mode_resp.raw_value) { + const struct pd_discovery *disc; + + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) + return TBT_SS_RES_0; + + disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + cable_tbt_speed = usb_rev30_to_tbt_speed( + disc->identity.product_t1.p_rev30.ss); + } else { + cable_tbt_speed = cable_mode_resp.tbt_cable_speed; + } + + return max_tbt_speed < cable_tbt_speed ? max_tbt_speed : + cable_tbt_speed; +} + +/* Note: Assumes that pins have already been set in safe state */ +int enter_tbt_compat_mode(int port, enum tcpci_msg_type sop, uint32_t *payload) +{ + union tbt_dev_mode_enter_cmd enter_dev_mode = { .raw_value = 0 }; + union tbt_mode_resp_device dev_mode_resp; + union tbt_mode_resp_cable cable_mode_resp; + enum tcpci_msg_type enter_mode_sop = + sop == TCPCI_MSG_SOP_PRIME_PRIME ? TCPCI_MSG_SOP_PRIME : sop; + + /* Table F-12 TBT3 Cable Enter Mode Command */ + /* + * The port doesn't query Discover SOP'' to the cable so, the port + * doesn't have opos for SOP''. Hence, send Enter Mode SOP'' with same + * opos and revision as SOP'. + */ + payload[0] = + VDO(USB_VID_INTEL, 1, CMD_ENTER_MODE | VDO_OPOS(tbt_opos)) | + VDO_CMDT(CMDT_INIT) | + VDO_SVDM_VERS(pd_get_vdo_ver(port, enter_mode_sop)); + + /* For TBT3 Cable Enter Mode Command, number of Objects is 1 */ + if ((sop == TCPCI_MSG_SOP_PRIME) || (sop == TCPCI_MSG_SOP_PRIME_PRIME)) + return 1; + + dev_mode_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP); + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); + + /* Table F-13 TBT3 Device Enter Mode Command */ + enter_dev_mode.vendor_spec_b1 = dev_mode_resp.vendor_spec_b1; + enter_dev_mode.vendor_spec_b0 = dev_mode_resp.vendor_spec_b0; + enter_dev_mode.intel_spec_b0 = dev_mode_resp.intel_spec_b0; + + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE || + cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE) + enter_dev_mode.cable = TBT_ENTER_ACTIVE_CABLE; + + enter_dev_mode.lsrx_comm = cable_mode_resp.lsrx_comm; + enter_dev_mode.retimer_type = cable_mode_resp.retimer_type; + enter_dev_mode.tbt_cable = cable_mode_resp.tbt_cable; + enter_dev_mode.tbt_rounded = cable_mode_resp.tbt_rounded; + enter_dev_mode.tbt_cable_speed = get_tbt_cable_speed(port); + enter_dev_mode.tbt_alt_mode = TBT_ALTERNATE_MODE; + + payload[1] = enter_dev_mode.raw_value; + + /* For TBT3 Device Enter Mode Command, number of Objects are 2 */ + return 2; +} + +enum tbt_compat_rounded_support get_tbt_rounded_support(int port) +{ + union tbt_mode_resp_cable cable_mode_resp = { + .raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME) + }; + + /* tbt_rounded_support is zero when uninitialized */ + return cable_mode_resp.tbt_rounded; +} + +__overridable enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + return TBT_SS_TBT_GEN3; } diff --git a/common/usbc/usb_mode.c b/common/usbc/usb_mode.c index fcbb58cd6f..b41a05a520 100644 --- a/common/usbc/usb_mode.c +++ b/common/usbc/usb_mode.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,23 +9,27 @@ * USB Power Delivery Specification Revision 3.0, Version 2.0 Section 6.4.8 */ -#include -#include #include "compile_time_macros.h" #include "console.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" +#include "typec_control.h" #include "usb_common.h" #include "usb_mode.h" #include "usb_mux.h" #include "usb_pd.h" -#include "usb_pd_dpm.h" -#include "usb_pd_tbt.h" +#include "usb_pd_dpm_sm.h" +#include "usb_pd_tcpm.h" #include "usb_pe_sm.h" +#include "usb_prl_sm.h" +#include "usb_tbt_alt_mode.h" #include "usbc_ppc.h" +#include +#include + #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else #define CPRINTF(format, args...) #define CPRINTS(format, args...) @@ -37,11 +41,73 @@ enum usb4_mode_status { }; enum usb4_states { + USB4_START, USB4_ENTER_SOP, + USB4_ENTER_SOP_PRIME, + USB4_ENTER_SOP_PRIME_PRIME, USB4_ACTIVE, USB4_INACTIVE, USB4_STATE_COUNT, }; + +/* + * USB4 PD flow: + * + * Cable type + * | + * |-------- Passive ---|---- Active -----| + * | | + * USB Highest Speed Structured VDM version + * | (cable revision)-- <2.0---->| + * --------|--------|------| | | + * | | | | >=2.0 | + * >=Gen3 Gen2 Gen1 USB2.0 | | + * | | | | VDO version--- <1.3 ---> Modal op? -- N --| + * Enter USB | | | (B21:23 of | | + * SOP with | | | Discover ID SOP'- y | + * Gen3 cable | | Skip Active cable VDO1) | | + * speed | | USB4 | TBT SVID? -- N --| + * | | mode >=1.3 | | + * Is modal op? | entry | y | + * | | Cable USB4 - N | | + * y | support? | Gen4 cable? - N - Skip + * | | | Skip USB4 | USB4 + * Is TBT SVID? -N- Enter | mode entry | mode + * | USB4 SOP | | entry + * y with Gen2 y | + * | cable speed | | + * | | | + * Is Discover mode | | + * SOP' B25? - N - Enter Enter USB4 mode | + * | USB4 SOP (SOP, SOP', SOP'') | + * | with speed | + * y from TBT mode | + * | SOP' VDO | + * | |<-- NAK -- Enter mode TBT SOP'<---| + * |---->Enter TBT SOP'-------NAK------>| | | | + * | | | | ACK | + * | ACK | | | | + * | | | |<-- NAK -- Enter mode TBT SOP'' | + * | Enter USB4 SOP | | | | + * | with speed from Exit TBT mode SOP ACK | + * | TBT mode SOP' VDO | | | | + * | ACK/NAK Enter USB4 SOP | + * | | | with speed from | + * | Exit TBT mode SOP'' TBT mode SOP' VDO | + * | | | | + * | ACK/NAK | + * | | | | + * | Exit TBT mode SOP' | + * | | | | + * | ACK/NAK | + * | | | | + * |---- N ----Retry done? -------------| |--------Retry done? ---- N -------| + * | | + * y y + * | | + * Skip USB4 mode entry Skip USB4 mode entry + */ + static enum usb4_states usb4_state[CONFIG_USB_PD_PORT_MAX_COUNT]; static void usb4_debug_prints(int port, enum usb4_mode_status usb4_status) @@ -50,9 +116,24 @@ static void usb4_debug_prints(int port, enum usb4_mode_status usb4_status) usb4_status); } +bool enter_usb_entry_is_done(int port) +{ + return usb4_state[port] == USB4_ACTIVE || + usb4_state[port] == USB4_INACTIVE; +} + +void usb4_exit_mode_request(int port) +{ + usb4_state[port] = USB4_START; + usb_mux_set_safe_mode_exit(port); + /* If TBT mode is active, leave safe state for mode exit VDMs */ + if (!tbt_is_active(port)) + set_usb_mux_with_current_data_role(port); +} + void enter_usb_init(int port) { - usb4_state[port] = USB4_ENTER_SOP; + usb4_state[port] = USB4_START; } void enter_usb_failed(int port) @@ -62,61 +143,119 @@ void enter_usb_failed(int port) * to USB mode on receiving a NAK. */ usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT, - pd_get_polarity(port)); + polarity_rm_dts(pd_get_polarity(port))); usb4_debug_prints(port, USB4_MODE_FAILURE); usb4_state[port] = USB4_INACTIVE; } -static bool enter_usb_response_valid(int port, enum tcpm_transmit_type type) +static bool enter_usb_response_valid(int port, enum tcpci_msg_type type) { /* * Check for an unexpected response. */ if (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE && - type != TCPC_TX_SOP) { + type != TCPCI_MSG_SOP) { enter_usb_failed(port); return false; } return true; } -bool enter_usb_is_capable(int port) +bool enter_usb_port_partner_is_capable(int port) { const struct pd_discovery *disc = - pd_get_am_discovery(port, TCPC_TX_SOP); - /* - * TODO: b/156749387 Add support for entering the USB4 mode with an - * active cable. - */ - if (!IS_ENABLED(CONFIG_USB_PD_USB4) || - !PD_PRODUCT_IS_USB4(disc->identity.product_t1.raw_value) || - get_usb4_cable_speed(port) < USB_R30_SS_U32_U40_GEN1 || - usb4_state[port] == USB4_INACTIVE || - get_usb_pd_cable_type(port) != IDH_PTYPE_PCABLE) + pd_get_am_discovery(port, TCPCI_MSG_SOP); + + if (usb4_state[port] == USB4_INACTIVE) return false; + if (prl_get_rev(port, TCPCI_MSG_SOP) < PD_REV30) + return false; + + if (!PD_PRODUCT_IS_USB4(disc->identity.product_t1.raw_value)) + return false; + + return true; +} + +bool enter_usb_cable_is_capable(int port) +{ + if (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) { + if (get_usb4_cable_speed(port) < USB_R30_SS_U32_U40_GEN1) + return false; + } else if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) { + const struct pd_discovery *disc_sop_prime = + pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + + if (pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME) >= VDM_VER20 && + disc_sop_prime->identity.product_t1.a_rev30.vdo_ver >= + VDO_VERSION_1_3) { + union active_cable_vdo2_rev30 a2_rev30 = + disc_sop_prime->identity.product_t2.a2_rev30; + /* + * For VDM version >= 2.0 and VD0 version is >= 1.3, + * do not enter USB4 mode if the cable isn't USB4 + * capable. + */ + if (a2_rev30.usb_40_support == USB4_NOT_SUPPORTED) + return false; + /* + * For VDM version < 2.0 or VDO version < 1.3, do not + * enter USB4 mode if the cable - doesn't support modal + * operation or doesn't support Intel SVID or doesn't + * have rounded support. + */ + } else { + const struct pd_discovery *disc = + pd_get_am_discovery(port, TCPCI_MSG_SOP); + union tbt_mode_resp_cable cable_mode_resp = { + .raw_value = pd_get_tbt_mode_vdo( + port, TCPCI_MSG_SOP_PRIME) + }; + + if (!disc->identity.idh.modal_support || + !pd_is_mode_discovered_for_svid( + port, TCPCI_MSG_SOP_PRIME, USB_VID_INTEL) || + cable_mode_resp.tbt_rounded != + TBT_GEN3_GEN4_ROUNDED_NON_ROUNDED) + return false; + } + } else { + /* Not Emark cable */ + return false; + } + return true; } -void enter_usb_accepted(int port, enum tcpm_transmit_type type) +void enter_usb_accepted(int port, enum tcpci_msg_type type) { + const struct pd_discovery *disc; + if (!enter_usb_response_valid(port, type)) return; switch (usb4_state[port]) { + case USB4_ENTER_SOP_PRIME: + disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + if (disc->identity.product_t1.a_rev20.sop_p_p) + usb4_state[port] = USB4_ENTER_SOP_PRIME_PRIME; + else + usb4_state[port] = USB4_ENTER_SOP; + break; + case USB4_ENTER_SOP_PRIME_PRIME: + usb4_state[port] = USB4_ENTER_SOP; + break; case USB4_ENTER_SOP: /* Connect the SBU and USB lines to the connector */ - if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) - ppc_set_sbu(port, 1); - - dpm_set_mode_entry_done(port); + typec_set_sbu(port, true); usb4_state[port] = USB4_ACTIVE; /* Set usb mux to USB4 mode */ usb_mux_set(port, USB_PD_MUX_USB4_ENABLED, USB_SWITCH_CONNECT, - pd_get_polarity(port)); + polarity_rm_dts(pd_get_polarity(port))); usb4_debug_prints(port, USB4_MODE_SUCCESS); break; @@ -127,7 +266,7 @@ void enter_usb_accepted(int port, enum tcpm_transmit_type type) } } -void enter_usb_rejected(int port, enum tcpm_transmit_type type) +void enter_usb_rejected(int port, enum tcpci_msg_type type) { if (!enter_usb_response_valid(port, type) || usb4_state[port] == USB4_ACTIVE) @@ -136,24 +275,147 @@ void enter_usb_rejected(int port, enum tcpm_transmit_type type) enter_usb_failed(port); } -uint32_t enter_usb_setup_next_msg(int port) +uint32_t enter_usb_setup_next_msg(int port, enum tcpci_msg_type *type) { + const struct pd_discovery *disc_sop_prime; + switch (usb4_state[port]) { - case USB4_ENTER_SOP: + case USB4_START: + disc_sop_prime = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); /* - * Set the USB mux to safe state to avoid damaging the mux pins - * since, they are being re-purposed for USB4. - * - * TODO: b/141363146 Remove once data reset feature is in place + * Ref: Tiger Lake Platform PD Controller Interface Requirements + * for Integrated USBC, section A.2.2: USB4 as DFP. + * Enter safe mode before sending Enter USB SOP/SOP'/SOP'' */ usb_mux_set_safe_mode(port); - usb4_state[port] = USB4_ENTER_SOP; - return get_enter_usb_msg_payload(port); + if (pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME) < VDM_VER20 || + disc_sop_prime->identity.product_t1.a_rev30.vdo_ver < + VDO_VERSION_1_3 || + get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) { + usb4_state[port] = USB4_ENTER_SOP; + } else { + usb4_state[port] = USB4_ENTER_SOP_PRIME; + *type = TCPCI_MSG_SOP_PRIME; + } + break; + case USB4_ENTER_SOP_PRIME: + *type = TCPCI_MSG_SOP_PRIME; + break; + case USB4_ENTER_SOP_PRIME_PRIME: + *type = TCPCI_MSG_SOP_PRIME_PRIME; + break; + case USB4_ENTER_SOP: + *type = TCPCI_MSG_SOP; + break; case USB4_ACTIVE: return -1; default: + return 0; + } + return get_enter_usb_msg_payload(port); +} + +/* + * For Cable rev 3.0: USB4 cable speed is set according to speed supported by + * the port and the response received from the cable, whichever is least. + * + * For Cable rev 2.0: If get_tbt_cable_speed() is less than + * TBT_SS_U31_GEN1, return USB_R30_SS_U2_ONLY speed since the board + * doesn't support superspeed else the USB4 cable speed is set according to + * the cable response. + */ +enum usb_rev30_ss get_usb4_cable_speed(int port) +{ + enum tbt_compat_cable_speed tbt_speed = get_tbt_cable_speed(port); + enum usb_rev30_ss max_usb4_speed; + + if (tbt_speed < TBT_SS_U31_GEN1) + return USB_R30_SS_U2_ONLY; + + /* + * Converting Thunderbolt-Compatible board speed to equivalent USB4 + * speed. + */ + max_usb4_speed = tbt_speed == TBT_SS_TBT_GEN3 ? USB_R30_SS_U40_GEN3 : + USB_R30_SS_U32_U40_GEN2; + + if ((get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) && + pd_get_rev(port, TCPCI_MSG_SOP_PRIME) == PD_REV30) { + const struct pd_discovery *disc = + pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + union active_cable_vdo1_rev30 a_rev30 = + disc->identity.product_t1.a_rev30; + + if (a_rev30.vdo_ver >= VDO_VERSION_1_3) { + return max_usb4_speed < a_rev30.ss ? max_usb4_speed : + a_rev30.ss; + } + } + + return max_usb4_speed; +} + +uint32_t get_enter_usb_msg_payload(int port) +{ + /* + * Ref: USB Power Delivery Specification Revision 3.0, Version 2.0 + * Table 6-47 Enter_USB Data Object + */ + union enter_usb_data_obj eudo; + const struct pd_discovery *disc; + union tbt_mode_resp_cable cable_mode_resp; + + if (!IS_ENABLED(CONFIG_USB_PD_USB4)) + return 0; + + disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + eudo.mode = USB_PD_40; + eudo.usb4_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB4_DRD); + eudo.usb3_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB32_DRD); + eudo.cable_speed = get_usb4_cable_speed(port); + + if (disc->identity.idh.product_type == IDH_PTYPE_ACABLE) { + if (pd_get_rev(port, TCPCI_MSG_SOP_PRIME) == PD_REV30) { + enum retimer_active_element active_element = + disc->identity.product_t2.a2_rev30.active_elem; + eudo.cable_type = active_element == ACTIVE_RETIMER ? + CABLE_TYPE_ACTIVE_RETIMER : + CABLE_TYPE_ACTIVE_REDRIVER; + } else { + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); + + eudo.cable_type = cable_mode_resp.retimer_type == + USB_RETIMER ? + CABLE_TYPE_ACTIVE_RETIMER : + CABLE_TYPE_ACTIVE_REDRIVER; + } + } else { + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); + + eudo.cable_type = cable_mode_resp.tbt_active_passive == + TBT_CABLE_ACTIVE ? + CABLE_TYPE_ACTIVE_REDRIVER : + CABLE_TYPE_PASSIVE; + } + + switch (disc->identity.product_t1.p_rev20.vbus_cur) { + case USB_VBUS_CUR_3A: + eudo.cable_current = USB4_CABLE_CURRENT_3A; + break; + case USB_VBUS_CUR_5A: + eudo.cable_current = USB4_CABLE_CURRENT_5A; + break; + default: + eudo.cable_current = USB4_CABLE_CURRENT_INVALID; break; } - return 0; + eudo.pcie_supported = IS_ENABLED(CONFIG_USB_PD_PCIE_TUNNELING); + eudo.dp_supported = IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP); + eudo.tbt_supported = IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE); + eudo.host_present = 1; + + return eudo.raw_value; } diff --git a/common/usbc/usb_pd_console.c b/common/usbc/usb_pd_console.c index e183f0852b..ae6527b601 100644 --- a/common/usbc/usb_pd_console.c +++ b/common/usbc/usb_pd_console.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,16 +6,23 @@ #include "common.h" #include "console.h" #include "usb_common.h" +#include "usb_pd.h" +#include "usb_pd_dpm_sm.h" +#include "usb_pd_timer.h" #include "usb_pe_sm.h" #include "usb_prl_sm.h" #include "usb_tc_sm.h" -#include "usb_pd.h" #include "util.h" -test_export_static int command_pd(int argc, char **argv) +#ifndef TEST_USB_PD_CONSOLE +static +#endif + int + command_pd(int argc, const char **argv) { int port; char *e; + int rv = EC_SUCCESS; if (argc < 2) return EC_ERROR_PARAM_COUNT; @@ -32,6 +39,7 @@ test_export_static int command_pd(int argc, char **argv) else if (level > DEBUG_LEVEL_MAX) level = DEBUG_LEVEL_MAX; + dpm_set_debug_level(level); prl_set_debug_level(level); pe_set_debug_level(level); tc_set_debug_level(level); @@ -39,7 +47,7 @@ test_export_static int command_pd(int argc, char **argv) return EC_SUCCESS; } } else if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC) && - !strcasecmp(argv[1], "trysrc")) { + !strcasecmp(argv[1], "trysrc")) { enum try_src_override_t ov = tc_get_try_src_override(); if (argc >= 3) { @@ -58,6 +66,14 @@ test_export_static int command_pd(int argc, char **argv) } else if (!strcasecmp(argv[1], "version")) { ccprintf("%d\n", PD_STACK_VERSION); return EC_SUCCESS; + } else if (!strcasecmp(argv[1], "bistsharemode")) { + if (!strcasecmp(argv[2], "disable")) + rv = pd_set_bist_share_mode(0); + else if (!strcasecmp(argv[2], "enable")) + rv = pd_set_bist_share_mode(1); + else + rv = EC_ERROR_PARAM2; + return rv; } /* command: pd [args] */ @@ -107,12 +123,13 @@ test_export_static int command_pd(int argc, char **argv) else if (!strcasecmp(argv[3], "data")) pd_dpm_request(port, DPM_REQUEST_DR_SWAP); else if (IS_ENABLED(CONFIG_USBC_VCONN_SWAP) && - !strcasecmp(argv[3], "vconn")) + !strcasecmp(argv[3], "vconn")) pd_dpm_request(port, DPM_REQUEST_VCONN_SWAP); else return EC_ERROR_PARAM3; } else if (!strcasecmp(argv[2], "dualrole")) { if (argc < 4) { + cflush(); ccprintf("dual-role toggling: "); switch (pd_get_dual_role(port)) { case PD_DRP_TOGGLE_ON: @@ -131,65 +148,125 @@ test_export_static int command_pd(int argc, char **argv) ccprintf("force source\n"); break; } + cflush(); } else { if (!strcasecmp(argv[3], "on")) pd_set_dual_role(port, - PD_DRP_TOGGLE_ON); + PD_DRP_TOGGLE_ON); else if (!strcasecmp(argv[3], "off")) pd_set_dual_role(port, - PD_DRP_TOGGLE_OFF); + PD_DRP_TOGGLE_OFF); else if (!strcasecmp(argv[3], "freeze")) pd_set_dual_role(port, PD_DRP_FREEZE); else if (!strcasecmp(argv[3], "sink")) pd_set_dual_role(port, - PD_DRP_FORCE_SINK); + PD_DRP_FORCE_SINK); else if (!strcasecmp(argv[3], "source")) pd_set_dual_role(port, - PD_DRP_FORCE_SOURCE); + PD_DRP_FORCE_SOURCE); else return EC_ERROR_PARAM4; } return EC_SUCCESS; + } else if (!strcasecmp(argv[2], "suspend")) { + pd_comm_enable(port, 0); + pd_set_suspend(port, 1); + } else if (!strcasecmp(argv[2], "resume")) { + pd_comm_enable(port, 1); + pd_set_suspend(port, 0); } } if (!strcasecmp(argv[2], "state")) { - ccprintf("Port C%d CC%d, %s - Role: %s-%s", - port, pd_get_polarity(port) + 1, - pd_comm_is_enabled(port) ? "Enable" : "Disable", - pd_get_power_role(port) == - PD_ROLE_SOURCE ? "SRC" : "SNK", - pd_get_data_role(port) == PD_ROLE_DFP ? "DFP" : "UFP"); + cflush(); + ccprintf("Port C%d CC%d, %s - Role: %s-%s", port, + pd_get_polarity(port) + 1, + pd_comm_is_enabled(port) ? "Enable" : "Disable", + pd_get_power_role(port) == PD_ROLE_SOURCE ? "SRC" : + "SNK", + pd_get_data_role(port) == PD_ROLE_DFP ? "DFP" : "UFP"); if (IS_ENABLED(CONFIG_USBC_VCONN)) ccprintf("%s ", tc_is_vconn_src(port) ? "-VC" : ""); ccprintf("TC State: %s, Flags: 0x%04x", - tc_get_current_state(port), - tc_get_flags(port)); + tc_get_current_state(port), tc_get_flags(port)); - if (IS_ENABLED(CONFIG_USB_PE_SM)) - ccprintf(" PE State: %s, Flags: 0x%04x\n", - pe_get_current_state(port), - pe_get_flags(port)); - else - ccprintf("\n"); + if (IS_ENABLED(CONFIG_USB_PE_SM)) { + ccprintf(" PE State: %s, Flags: 0x%04x", + pe_get_current_state(port), + pe_get_flags(port)); + if (pe_is_explicit_contract(port)) { + if (pe_snk_in_epr_mode(port)) + ccprintf(" EPR"); + else + ccprintf(" SPR"); + } + } + ccprintf("\n"); + + cflush(); + } else if (!strcasecmp(argv[2], "srccaps")) { + pd_srccaps_dump(port); + } else if (!strcasecmp(argv[2], "cc")) { + ccprintf("Port C%d CC%d\n", port, pd_get_task_cc_state(port)); +#ifdef CONFIG_USB_PD_EPR + } else if (!strcasecmp(argv[2], "epr")) { + enum pd_dpm_request req; + + if (argc < 4) { + return EC_ERROR_PARAM_COUNT; + } + if (pd_get_power_role(port) != PD_ROLE_SINK) { + ccprintf("EPR is currently supported only for sink\n"); + /* Suppress (long) help message */ + return EC_SUCCESS; + } + if (!strcasecmp(argv[3], "enter")) { + req = DPM_REQUEST_EPR_MODE_ENTRY; + } else if (!strcasecmp(argv[3], "exit")) { + req = DPM_REQUEST_EPR_MODE_EXIT; + /* Prevent snk_ready from repeatedly entering EPR. */ + pe_snk_epr_explicit_exit(port); + } else { + return EC_ERROR_PARAM3; + } + pd_dpm_request(port, req); + ccprintf("EPR %s requested\n", argv[3]); + return EC_SUCCESS; +#endif + } + + if (IS_ENABLED(CONFIG_CMD_PD_TIMER) && !strcasecmp(argv[2], "timer")) { + pd_timer_dump(port); } return EC_SUCCESS; } +#ifndef TEST_USB_PD_CONSOLE DECLARE_CONSOLE_COMMAND(pd, command_pd, - "version" - "\ndump [0|1|2|3]" + "version" + "\ndump [0|1|2|3]" #ifdef CONFIG_USB_PD_TRY_SRC - "\ntrysrc [0|1|2]" + "\ntrysrc [0|1|2]" #endif - "\n\t state" + "\nbistsharemode [disable|enable]" + "\n\t state" + "\n\t srccaps" + "\n\t cc" +#ifdef CONFIG_CMD_PD_TIMER + "\n\t timer" +#endif /* CONFIG_CMD_PD_TIMER */ #ifdef CONFIG_USB_PD_DUAL_ROLE - "|tx|charger|dev" - "\n\t disable|enable|soft|hard" - "\n\t dualrole [on|off|freeze|sink|source]" - "\n\t swap [power|data|vconn]" + "|tx|charger|dev" + "\n\t disable|enable|soft|hard" + "\n\t suspend|resume" + "\n\t dualrole [on|off|freeze|sink|source]" + "\n\t swap [power|data|vconn]" +#ifdef CONFIG_USB_PD_EPR + "\n\t epr [enter|exit]" +#endif #endif /* CONFIG_USB_PD_DUAL_ROLE */ - , - "USB PD"); + , + "USB PD"); +#endif diff --git a/common/usbc/usb_pd_dp_ufp.c b/common/usbc/usb_pd_dp_ufp.c new file mode 100644 index 0000000000..1d375c5e2b --- /dev/null +++ b/common/usbc/usb_pd_dp_ufp.c @@ -0,0 +1,446 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Functions required for UFP_D operation + */ + +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "system.h" +#include "task.h" +#include "usb_pd.h" +#include "usb_pd_dp_ufp.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +enum hpd_state { + LOW_WAIT, + HIGH_CHECK, + HIGH_WAIT, + LOW_CHECK, + IRQ_CHECK, +}; + +#define EDGE_QUEUE_DEPTH BIT(3) +#define EDGE_QUEUE_MASK (EDGE_QUEUE_DEPTH - 1) +#define HPD_QUEUE_DEPTH BIT(2) +#define HPD_QUEUE_MASK (HPD_QUEUE_DEPTH - 1) +#define HPD_T_IRQ_MIN_PULSE 250 +#define HPD_T_IRQ_MAX_PULSE (2 * MSEC) +#define HPD_T_MIN_DP_ATTEN (10 * MSEC) + +struct hpd_mark { + int level; + uint64_t ts; +}; + +struct hpd_edge { + int overflow; + uint32_t head; + uint32_t tail; + struct hpd_mark buffer[EDGE_QUEUE_DEPTH]; +}; + +struct hpd_info { + enum hpd_state state; + int count; + int send_enable; + uint64_t timer; + uint64_t last_send_ts; + enum hpd_event queue[HPD_QUEUE_DEPTH]; + struct hpd_edge edges; +}; + +static struct hpd_info hpd; +static struct mutex hpd_mutex; + +static int alt_dp_mode_opos[CONFIG_USB_PD_PORT_MAX_COUNT]; + +void pd_ufp_set_dp_opos(int port, int opos) +{ + alt_dp_mode_opos[port] = opos; +} + +int pd_ufp_get_dp_opos(int port) +{ + return alt_dp_mode_opos[port]; +} + +void pd_ufp_enable_hpd_send(int port) +{ + /* + * This control is used ensure that a DP_ATTENTION message is not sent + * to the DFP-D before a DP_CONFIG messaage has been received. This + * control is not strictly required by the spec, but some port partners + * will get confused if DP_ATTENTION is sent prior to DP_CONFIG. + */ + hpd.send_enable = 1; +} + +static void hpd_to_dp_attention(void) +{ + int port = hpd_config.port; + int evt_index = hpd.count - 1; + uint32_t vdm[2]; + uint32_t svdm_header; + enum hpd_event evt; + int opos = pd_ufp_get_dp_opos(port); + + if (!opos) + return; + + /* Get the next hpd event from the queue */ + evt = hpd.queue[evt_index]; + /* Save timestamp of when most recent DP attention message was sent */ + hpd.last_send_ts = get_time().val; + + /* + * Construct DP Attention message. This consists of the VDM header and + * the DP_STATUS VDO. + */ + svdm_header = VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)) | + VDO_OPOS(opos) | CMD_ATTENTION; + vdm[0] = VDO(USB_SID_DISPLAYPORT, 1, svdm_header); + + vdm[1] = VDO_DP_STATUS((evt == hpd_irq), /* IRQ_HPD */ + (evt != hpd_low), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + dock_get_mf_preference(), /* MF pref */ + 1, /* enabled */ + 0, /* power low */ + 0x2); + + /* Send request to DPM to send an attention VDM */ + pd_request_vdm(port, vdm, ARRAY_SIZE(vdm), TCPCI_MSG_SOP); + + /* If there are still events, need to shift the buffer */ + if (--hpd.count) { + int i; + + for (i = 0; i < hpd.count; i++) + hpd.queue[i] = hpd.queue[i + 1]; + } +} + +static void hpd_queue_event(enum hpd_event evt) +{ + /* + * HPD events are put into a queue. However, this queue is not a typical + * FIFO queue. Instead there are special rules based on which type of + * event is being added. + * HPD_LOW -> always resets the queue and must be in slot 0 + * HPD_HIGH -> must follow a HPD_LOW, so can only be in slot 0 or + * slot 1. + * HPD_IRQ -> There shall never be more than 2 HPD_IRQ events + * stored in the queue and HPD_IRQ must follow HPD_HIGH + * + * Worst case for queueing HPD events is 4 events in the queue: + * 0 - HPD_LOW + * 1 - HPD_HIGH + * 2 - HPD_IRQ + * 3 - HPD_IRQ + * + * The above rules mean that HPD_LOW and HPD_HIGH events can always be + * added to the queue since high must follow low and a low event resets + * the queue. HPD_IRQ events are checked to make sure that they don't + * overflow the queue and to ensure that no more than 2 hpd_irq events + * are kept in the queue. + */ + if (evt == hpd_irq) { + if ((hpd.count >= HPD_QUEUE_DEPTH) || + ((hpd.count >= 2) && + (hpd.queue[hpd.count - 2] == hpd_irq))) { + CPRINTS("hpd: discard hpd: count - %d", hpd.count); + return; + } + } + + if (evt == hpd_low) { + hpd.count = 0; + } + + /* Add event to the queue */ + hpd.queue[hpd.count++] = evt; +} + +static void hpd_to_pd_converter(int level, uint64_t ts) +{ + /* + * HPD edges are marked in the irq routine. The converter state machine + * runs in the hooks task and so there will be some delay between when + * the edge was captured and when that edge is processed here in the + * state machine. This means that the delitch timer (250 uSec) may have + * already expired or is about to expire. + * + * If transitioning to timing dependent state, need to ensure the state + * machine is executed again. All timers are relative to the ts value + * passed into this routine. The timestamps passed into this routine + * are either the values latched in the irq routine, or the current + * time latched by the calling function. From the perspective of the + * state machine, ts represents the current time. + * + * Note that all hpd queue events are contingent on detecting edges + * on the incoming hpd gpio signal. The hpd->dp attention converter is + * enabled/disabled as part of the svdm dp enter/exit response handler + * functions. When the converter is disabled, gpio interrupts for the + * hpd gpio signal are disabled so it will never execute, unless the + * converter is enabled, and the converter is only enabled when the + * UFP-D is actively in ALT-DP mode. + */ + switch (hpd.state) { + case LOW_WAIT: + /* + * In this state only expected event is a level change from low + * to high. + */ + if (level) { + hpd.state = HIGH_CHECK; + hpd.timer = ts + HPD_T_IRQ_MIN_PULSE; + } + break; + case HIGH_CHECK: + /* + * In this state if level is high and deglitch timer is + * exceeded, then state advances to HIGH_WAIT, otherwise return + * to LOW_WAIT state. + */ + if (!level || (ts <= hpd.timer)) { + hpd.state = LOW_WAIT; + } else { + hpd.state = HIGH_WAIT; + hpd_queue_event(hpd_high); + } + break; + case HIGH_WAIT: + /* + * In this state, only expected event is a level change from + * high to low. If current level is low, then advance to + * LOW_CHECK for deglitch checking. + */ + if (!level) { + hpd.state = LOW_CHECK; + hpd.timer = ts + HPD_T_IRQ_MIN_PULSE; + } + break; + case LOW_CHECK: + /* + * This state is used to deglitch high->low level + * change. However, due to processing latency, it's possible to + * detect hpd_irq event if level is high and low pulse width was + * valid. + */ + if (!level) { + /* Still low, now wait for IRQ or LOW determination */ + hpd.timer = ts + + (HPD_T_IRQ_MAX_PULSE - HPD_T_IRQ_MIN_PULSE); + hpd.state = IRQ_CHECK; + + } else { + uint64_t irq_ts = hpd.timer + HPD_T_IRQ_MAX_PULSE - + HPD_T_IRQ_MIN_PULSE; + /* + * If hpd is high now, this must have been an edge + * event, but still need to determine if the pulse width + * is longer than hpd_irq min pulse width. State will + * advance to HIGH_WAIT, but if pulse width is < 2 msec, + * must send hpd_irq event. + */ + if ((ts >= hpd.timer) && (ts <= irq_ts)) { + /* hpd irq detected */ + hpd_queue_event(hpd_irq); + } + hpd.state = HIGH_WAIT; + } + break; + case IRQ_CHECK: + /* + * In this state deglitch time has already passed. If current + * level is low and hpd_irq timer has expired, then go to + * LOW_WAIT as hpd_low event has been detected. If level is high + * and low pulse is < hpd_irq, hpd_irq event has been detected. + */ + if (level) { + hpd.state = HIGH_WAIT; + if (ts <= hpd.timer) { + hpd_queue_event(hpd_irq); + } + } else if (ts > hpd.timer) { + hpd.state = LOW_WAIT; + hpd_queue_event(hpd_low); + } + break; + } +} + +static void manage_hpd(void); +DECLARE_DEFERRED(manage_hpd); + +static void manage_hpd(void) +{ + int level; + uint64_t ts = get_time().val; + uint32_t num_hpd_events = (hpd.edges.head - hpd.edges.tail) & + EDGE_QUEUE_MASK; + + /* + * HPD edges are detected via GPIO interrupts. The ISR routine adds edge + * info to a queue and scheudles this routine. If this routine is called + * without a new edge detected, then it is being called due to a timer + * event. + */ + + /* First check to see overflow condition has occurred */ + if (hpd.edges.overflow) { + /* Disable hpd interrupts */ + usb_pd_hpd_converter_enable(0); + /* Re-enable hpd converter */ + usb_pd_hpd_converter_enable(1); + } + + if (num_hpd_events) { + while (num_hpd_events-- > 0) { + int idx = hpd.edges.tail; + + level = hpd.edges.buffer[idx].level; + ts = hpd.edges.buffer[idx].ts; + + hpd_to_pd_converter(level, ts); + hpd.edges.tail = (hpd.edges.tail + 1) & EDGE_QUEUE_MASK; + } + } else { + /* no new edge event, so get current time and level */ + level = gpio_get_level(hpd_config.signal); + ts = get_time().val; + hpd_to_pd_converter(level, ts); + } + + /* + * If min time spacing requirement is exceeded and a hpd_event is + * queued, then send DP_ATTENTION message. + */ + if (hpd.count > 0) { + /* + * If at least one hpd event is pending in the queue, send + * a DP_ATTENTION message if a DP_CONFIG message has been + * received and have passed the minimum spacing interval. + */ + if (hpd.send_enable && ((get_time().val - hpd.last_send_ts) > + HPD_T_MIN_DP_ATTEN)) { + /* Generate DP_ATTENTION event pending in queue */ + hpd_to_dp_attention(); + } else { + uint32_t callback_us; + + /* + * Need to wait until until min spacing requirement of + * DP attention messages. Set callback time to the min + * value required. This callback time could be changed + * based on hpd interrupts. + * + * This wait is also used to prevent a DP_ATTENTION + * message from being sent before at least one DP_CONFIG + * message has been received. If DP_ATTENTION messages + * need to be delayed for this reason, then just wait + * the minimum time spacing. + */ + callback_us = HPD_T_MIN_DP_ATTEN - + (get_time().val - hpd.last_send_ts); + if (callback_us <= 0 || + callback_us > HPD_T_MIN_DP_ATTEN) + callback_us = HPD_T_MIN_DP_ATTEN; + hook_call_deferred(&manage_hpd_data, callback_us); + } + } + + /* + * Because of the delay between gpio edge irq, and when those edge + * events are processed here, all timers must be done relative to the + * timing marker stored in the hpd edge queue. If the state machine + * required a new timer, then hpd.timer will be advanced relative to the + * ts that was passed into the state machine. + * + * If the deglitch timer is active, then it can likely already have been + * expired when the edge gets processed. So if the timer is active the + * deferred callback must be requested. + *. + */ + if (hpd.timer > ts) { + uint64_t callback_us = 0; + uint64_t now = get_time().val; + + /* If timer is in the future, adjust the callback timer */ + if (now < hpd.timer) + callback_us = (hpd.timer - now) & 0xffffffff; + + hook_call_deferred(&manage_hpd_data, callback_us); + } +} + +void usb_pd_hpd_converter_enable(int enable) +{ + /* + * The hpd converter should be enabled as part of the UFP-D enter mode + * response function. Likewise, the converter should be disabled by the + * exit mode function. In addition, the coverter may get disabled so + * that it can be reset in the case that the input gpio edges queue + * overflows. A muxtex must be used here since this function may be + * called from the PD task (enter/exit response mode functions) or from + * the hpd event handler state machine (hook task). + */ + mutex_lock(&hpd_mutex); + + if (enable) { + gpio_disable_interrupt(hpd_config.signal); + /* Reset HPD event queue */ + hpd.state = LOW_WAIT; + hpd.count = 0; + hpd.timer = 0; + hpd.last_send_ts = 0; + hpd.send_enable = 0; + + /* Reset hpd signal edges queue */ + hpd.edges.head = 0; + hpd.edges.tail = 0; + hpd.edges.overflow = 0; + + /* If signal is high, need to ensure state machine executes */ + if (gpio_get_level(hpd_config.signal)) + hook_call_deferred(&manage_hpd_data, 0); + + /* Enable hpd edge detection */ + gpio_enable_interrupt(hpd_config.signal); + } else { + gpio_disable_interrupt(hpd_config.signal); + hook_call_deferred(&manage_hpd_data, -1); + } + + mutex_unlock(&hpd_mutex); +} + +void usb_pd_hpd_edge_event(int signal) +{ + int next_head = (hpd.edges.head + 1) & EDGE_QUEUE_MASK; + struct hpd_mark mark; + + /* Get current timestamp and level */ + mark.ts = get_time().val; + mark.level = gpio_get_level(hpd_config.signal); + + /* Add this edge to the buffer if there is space */ + if (next_head != hpd.edges.tail) { + hpd.edges.buffer[hpd.edges.head].ts = mark.ts; + hpd.edges.buffer[hpd.edges.head].level = mark.level; + hpd.edges.head = next_head; + } else { + /* Edge queue is overflowing, need to reset the converter */ + hpd.edges.overflow = 1; + } + /* Schedule HPD state machine to run ASAP */ + hook_call_deferred(&manage_hpd_data, 0); +} diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c index e9c7782512..022d81109b 100644 --- a/common/usbc/usb_pd_dpm.c +++ b/common/usbc/usb_pd_dpm.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,103 +8,1176 @@ * Refer to USB PD 3.0 spec, version 2.0, sections 8.2 and 8.3 */ +#include "builtin/assert.h" #include "charge_state.h" +#include "chipset.h" #include "compile_time_macros.h" #include "console.h" +#include "ec_commands.h" +#include "hooks.h" +#include "power.h" +#include "power_button.h" +#include "queue.h" +#include "system.h" +#include "task.h" +#include "tcpm/tcpm.h" +#include "temp_sensor.h" #include "usb_dp_alt_mode.h" #include "usb_mode.h" +#include "usb_mux.h" #include "usb_pd.h" -#include "usb_pd_dpm.h" +#include "usb_pd_ap_vdm_control.h" +#include "usb_pd_dpm_sm.h" +#include "usb_pd_pdo.h" +#include "usb_pd_tcpm.h" +#include "usb_pd_timer.h" +#include "usb_pe_sm.h" #include "usb_tbt_alt_mode.h" -#include "tcpm.h" +#include "usb_tc_sm.h" + +/* + * TODO(b/272518464): Work around coreboot GCC preprocessor bug. + * #line marks the *next* line, so it is off by one. + */ +#line 43 + +#ifdef CONFIG_ZEPHYR +#include "temp_sensor/temp_sensor.h" +#endif + +#ifdef CONFIG_USB_PD_DEBUG_LEVEL +static const enum debug_level dpm_debug_level = CONFIG_USB_PD_DEBUG_LEVEL; +#elif defined(CONFIG_USB_PD_INITIAL_DEBUG_LEVEL) +static enum debug_level dpm_debug_level = CONFIG_USB_PD_INITIAL_DEBUG_LEVEL; +#else +static enum debug_level dpm_debug_level = DEBUG_LEVEL_1; +#endif #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else #define CPRINTF(format, args...) #define CPRINTS(format, args...) #endif static struct { - bool mode_entry_done; - bool mode_exit_request; + /* state machine context */ + struct sm_ctx ctx; + atomic_t flags; + uint32_t vdm_req[VDO_MAX_SIZE]; + int vdm_req_cnt; + enum tcpci_msg_type req_type; + mutex_t vdm_req_mutex; + enum dpm_pd_button_state pd_button_state; } dpm[CONFIG_USB_PD_PORT_MAX_COUNT]; +__overridable const struct svdm_response svdm_rsp = { + .identity = NULL, + .svids = NULL, + .modes = NULL, +}; + +/* Tracker for which task is waiting on sysjump prep to finish */ +static volatile task_id_t sysjump_task_waiting = TASK_ID_INVALID; + +#define DPM_SET_FLAG(port, flag) atomic_or(&dpm[(port)].flags, (flag)) +#define DPM_CLR_FLAG(port, flag) atomic_clear_bits(&dpm[(port)].flags, (flag)) +#define DPM_CHK_FLAG(port, flag) (dpm[(port)].flags & (flag)) + +/* Flags for internal DPM state */ +#define DPM_FLAG_MODE_ENTRY_DONE BIT(0) +#define DPM_FLAG_EXIT_REQUEST BIT(1) +#define DPM_FLAG_ENTER_DP BIT(2) +#define DPM_FLAG_ENTER_TBT BIT(3) +#define DPM_FLAG_ENTER_USB4 BIT(4) +#define DPM_FLAG_ENTER_ANY \ + (DPM_FLAG_ENTER_DP | DPM_FLAG_ENTER_TBT | DPM_FLAG_ENTER_USB4) +#define DPM_FLAG_SEND_VDM_REQ BIT(5) +#define DPM_FLAG_DATA_RESET_DONE BIT(6) +#define DPM_FLAG_PD_BUTTON_PRESSED BIT(7) +#define DPM_FLAG_PD_BUTTON_RELEASED BIT(8) +#define DPM_FLAG_PE_READY BIT(9) + +/* List of all Device Policy Manager level states */ +enum usb_dpm_state { + /* Normal States */ + DPM_WAITING, + DPM_DFP_READY, + DPM_UFP_READY, + DPM_DATA_RESET, +}; + +/* Forward declare the full list of states. This is indexed by usb_pd_state */ +static const struct usb_state dpm_states[]; + +/* List of human readable state names for console debugging */ +__maybe_unused static __const_data const char *const dpm_state_names[] = { + /* Normal States */ + [DPM_WAITING] = "DPM Waiting", + [DPM_DFP_READY] = "DPM DFP Ready", + [DPM_UFP_READY] = "DPM UFP Ready", + [DPM_DATA_RESET] = "DPM Data Reset", +}; + +static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT]; + +void dpm_set_debug_level(enum debug_level debug_level) +{ +#ifndef CONFIG_USB_PD_DEBUG_LEVEL + dpm_debug_level = debug_level; +#endif +} + +/* Set the DPM state machine to a new state. */ +static void set_state_dpm(const int port, const enum usb_dpm_state new_state) +{ + set_state(port, &dpm[port].ctx, &dpm_states[new_state]); +} + +/* Get the current TypeC state. */ +__maybe_unused test_export_static enum usb_dpm_state +get_state_dpm(const int port) +{ + return dpm[port].ctx.current - &dpm_states[0]; +} + +static void print_current_state(const int port) +{ + CPRINTS("C%d: %s", port, dpm_state_names[get_state_dpm(port)]); +} + +#ifdef CONFIG_ZEPHYR +static int init_dpm_mutexes(void) +{ + int port; + + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) { + k_mutex_init(&dpm[port].vdm_req_mutex); + } + + return 0; +} +SYS_INIT(init_dpm_mutexes, POST_KERNEL, 50); +#endif /* CONFIG_ZEPHYR */ + +void pd_prepare_sysjump(void) +{ +#ifndef CONFIG_ZEPHYR + int i; + + /* Exit modes before sysjump so we can cleanly enter again later */ + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + /* + * If the port is not capable of alternate mode, then there's no + * need to send the event. + */ + if (!pd_alt_mode_capable(i)) + continue; + + sysjump_task_waiting = task_get_current(); + task_set_event(PD_PORT_TO_TASK_ID(i), PD_EVENT_SYSJUMP); + task_wait_event_mask(TASK_EVENT_SYSJUMP_READY, -1); + sysjump_task_waiting = TASK_ID_INVALID; + } +#endif /* CONFIG_ZEPHYR */ +} + +void notify_sysjump_ready(void) +{ + /* + * If event was set from pd_prepare_sysjump, wake the + * task waiting on us to complete. + */ + if (sysjump_task_waiting != TASK_ID_INVALID) + task_set_event(sysjump_task_waiting, TASK_EVENT_SYSJUMP_READY); +} + +/* + * TODO(b/270409939): Refactor this function + */ +int pd_dfp_exit_mode(int port, enum tcpci_msg_type type, uint16_t svid, + int opos) +{ + /* + * Empty svid signals we should reset DFP VDM state by exiting all + * entered modes then clearing state. This occurs when we've + * disconnected or for hard reset. + */ + if (!svid) { + if (IS_ENABLED(CONFIG_USB_PD_DP_MODE) && dp_is_active(port)) + svdm_exit_dp_mode(port); + pd_dfp_mode_init(port); + } + + /* + * Return 0 indicating no message is needed. All modules should be + * handling their SVID-specific cases themselves. + */ + return 0; +} + +/* + * Note: this interface is used in board code, but should be obsoleted + * TODO(b/267545470): Fold board DP code into the DP module + */ +int pd_alt_mode(int port, enum tcpci_msg_type type, uint16_t svid) +{ + if (svid == USB_SID_DISPLAYPORT && !dp_is_idle(port)) + return 1; + else if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && + svid == USB_VID_INTEL && tbt_is_active(port)) + return 1; + + return -1; +} + +void dfp_consume_attention(int port, uint32_t *payload) +{ + uint16_t svid = PD_VDO_VID(payload[0]); + + if (IS_ENABLED(CONFIG_USB_PD_DP_MODE) && svid == USB_SID_DISPLAYPORT) { + /* + * Attention is only valid after EnterMode, so drop if this is + * out of sequence + */ + if (!dp_is_idle(port)) + svdm_dp_attention(port, payload); + } +} + +__overridable bool board_is_tbt_usb4_port(int port) +{ + return true; +} + +enum ec_status pd_request_vdm(int port, const uint32_t *data, int vdo_count, + enum tcpci_msg_type tx_type) +{ + mutex_lock(&dpm[port].vdm_req_mutex); + + /* Only one VDM REQ message may be pending */ + if (DPM_CHK_FLAG(port, DPM_FLAG_SEND_VDM_REQ)) { + mutex_unlock(&dpm[port].vdm_req_mutex); + return EC_RES_BUSY; + } + + /* VDM header is required and we cannot exceed standard message size*/ + if (!vdo_count || vdo_count > VDO_MAX_SIZE) { + mutex_unlock(&dpm[port].vdm_req_mutex); + return EC_RES_INVALID_PARAM; + } + + /* SVDM Attention message must be 1 or 2 VDOs in length */ + if (PD_VDO_SVDM(data[0]) && (PD_VDO_CMD(data[0]) == CMD_ATTENTION) && + vdo_count > PD_ATTENTION_MAX_VDO) { + mutex_unlock(&dpm[port].vdm_req_mutex); + return EC_RES_INVALID_PARAM; + } + + /* Save contents of VDM REQ message */ + memcpy(dpm[port].vdm_req, data, vdo_count * sizeof(uint32_t)); + dpm[port].vdm_req_cnt = vdo_count; + dpm[port].req_type = tx_type; + + /* + * Indicate to DPM that a REQ message needs to be sent. This flag + * will be cleared when the REQ message is sent to the policy + * engine (VDM:Attention), or when the reply is received (all others). + */ + DPM_SET_FLAG(port, DPM_FLAG_SEND_VDM_REQ); + + mutex_unlock(&dpm[port].vdm_req_mutex); + + return EC_RES_SUCCESS; +} + +void dpm_clear_vdm_request(int port) +{ + DPM_CLR_FLAG(port, DPM_FLAG_SEND_VDM_REQ); +} + +bool dpm_check_vdm_request(int port) +{ + return DPM_CHK_FLAG(port, DPM_FLAG_SEND_VDM_REQ); +} + +enum ec_status pd_request_enter_mode(int port, enum typec_mode mode) +{ + if (port >= board_get_usb_pd_port_count()) + return EC_RES_INVALID_PARAM; + + /* Only one enter request may be active at a time. */ + if (DPM_CHK_FLAG(port, DPM_FLAG_ENTER_DP | DPM_FLAG_ENTER_TBT | + DPM_FLAG_ENTER_USB4)) + return EC_RES_BUSY; + + if (IS_ENABLED(CONFIG_USB_PD_DP_MODE) && mode == TYPEC_MODE_DP) { + if (dp_is_idle(port)) + dp_init(port); + DPM_SET_FLAG(port, DPM_FLAG_ENTER_DP); + } else if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && + mode == TYPEC_MODE_TBT) { + /* TODO(b/235984702#comment21): Refactor alt mode modules + * to better support mode reentry. */ + if (dp_is_idle(port)) + dp_init(port); + DPM_SET_FLAG(port, DPM_FLAG_ENTER_TBT); + } else if (IS_ENABLED(CONFIG_USB_PD_USB4) && mode == TYPEC_MODE_USB4) { + DPM_SET_FLAG(port, DPM_FLAG_ENTER_USB4); + } else { + return EC_RES_INVALID_PARAM; + } + + DPM_CLR_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE); + DPM_CLR_FLAG(port, DPM_FLAG_EXIT_REQUEST); + DPM_CLR_FLAG(port, DPM_FLAG_DATA_RESET_DONE); + + return EC_RES_SUCCESS; +} + void dpm_init(int port) { - dpm[port].mode_entry_done = false; - dpm[port].mode_exit_request = false; + dpm[port].flags = 0; + dpm[port].pd_button_state = DPM_PD_BUTTON_IDLE; + ap_vdm_init(port); + + /* Ensure that DPM state machine gets reset */ + set_state_dpm(port, DPM_WAITING); +} + +void dpm_mode_exit_complete(int port) +{ + DPM_CLR_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE | DPM_FLAG_EXIT_REQUEST | + DPM_FLAG_SEND_VDM_REQ); } -void dpm_set_mode_entry_done(int port) +static void dpm_set_mode_entry_done(int port) { - dpm[port].mode_entry_done = true; + DPM_SET_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE); + DPM_CLR_FLAG(port, DPM_FLAG_ENTER_DP | DPM_FLAG_ENTER_TBT | + DPM_FLAG_ENTER_USB4); } void dpm_set_mode_exit_request(int port) { - dpm[port].mode_exit_request = true; + DPM_SET_FLAG(port, DPM_FLAG_EXIT_REQUEST); + DPM_CLR_FLAG(port, DPM_FLAG_DATA_RESET_DONE); +} + +void dpm_data_reset_complete(int port) +{ + DPM_SET_FLAG(port, DPM_FLAG_DATA_RESET_DONE); + DPM_CLR_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE); } -static inline void dpm_clear_mode_exit_request(int port) +void dpm_set_pe_ready(int port, bool enable) { - dpm[port].mode_exit_request = false; + /* + * DPM should remain DPM_WAITING state until the PE is in its ready + * state and is able to accept requests from the DPM layer. + */ + if (enable) + DPM_SET_FLAG(port, DPM_FLAG_PE_READY); + else + DPM_CLR_FLAG(port, DPM_FLAG_PE_READY); +} + +static void dpm_clear_mode_exit_request(int port) +{ + DPM_CLR_FLAG(port, DPM_FLAG_EXIT_REQUEST); +} + +/* + * Returns true if the current policy requests that the EC try to enter this + * mode on this port. If the EC is in charge of policy, the answer is always + * yes. + */ +static bool dpm_mode_entry_requested(int port, enum typec_mode mode) +{ + /* If the AP isn't controlling policy, the EC is. */ + if (!IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY)) + return true; + + switch (mode) { + case TYPEC_MODE_DP: + return !!DPM_CHK_FLAG(port, DPM_FLAG_ENTER_DP); + case TYPEC_MODE_TBT: + return !!DPM_CHK_FLAG(port, DPM_FLAG_ENTER_TBT); + case TYPEC_MODE_USB4: + return !!DPM_CHK_FLAG(port, DPM_FLAG_ENTER_USB4); + default: + return false; + } } -void dpm_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, - uint32_t *vdm) +void dpm_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count, + uint32_t *vdm) { - const uint16_t svid = PD_VDO_VID(vdm[0]); + __maybe_unused const uint16_t svid = PD_VDO_VID(vdm[0]); assert(vdo_count >= 1); + assert(vdo_count <= VDO_MAX_SIZE); + + if (IS_ENABLED(CONFIG_USB_PD_VDM_AP_CONTROL)) { + ap_vdm_acked(port, type, vdo_count, vdm); + return; + } switch (svid) { case USB_SID_DISPLAYPORT: dp_vdm_acked(port, type, vdo_count, vdm); break; case USB_VID_INTEL: - if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) { - intel_vdm_acked(port, type, vdo_count, vdm); - break; - } +/* TODO (http://b/255967867) Can't use the IS_ENABLED macro here because + * __fallthrough fails in clang as unreachable code. + */ +#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE + intel_vdm_acked(port, type, vdo_count, vdm); + break; +#else + __fallthrough; +#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */ default: CPRINTS("C%d: Received unexpected VDM ACK for SVID %d", port, - svid); + svid); } } -void dpm_vdm_naked(int port, enum tcpm_transmit_type type, uint16_t svid, - uint8_t vdm_cmd) +void dpm_vdm_naked(int port, enum tcpci_msg_type type, uint16_t svid, + uint8_t vdm_cmd, uint32_t vdm_header) { + if (IS_ENABLED(CONFIG_USB_PD_VDM_AP_CONTROL)) { + ap_vdm_naked(port, type, svid, vdm_cmd, vdm_header); + return; + } + switch (svid) { case USB_SID_DISPLAYPORT: dp_vdm_naked(port, type, vdm_cmd); break; case USB_VID_INTEL: - if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) { - intel_vdm_naked(port, type, vdm_cmd); - break; - } +/* TODO (http://b/255967867) Can't use the IS_ENABLED macro here because + * __fallthrough fails in clang as unreachable code. + */ +#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE + intel_vdm_naked(port, type, vdm_cmd); + break; +#else + __fallthrough; +#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */ default: CPRINTS("C%d: Received unexpected VDM NAK for SVID %d", port, - svid); + svid); + } +} + +static void dpm_send_req_vdm(int port) +{ + /* Set up VDM REQ msg that was passed in previously */ + if (pd_setup_vdm_request(port, dpm[port].req_type, dpm[port].vdm_req, + dpm[port].vdm_req_cnt) == true) + /* Trigger PE to start a VDM command run */ + pd_dpm_request(port, DPM_REQUEST_VDM); + + /* + * Clear flag after message is sent to PE layer if it was Attention, + * which generates no reply. + * + * Otherwise, clear flag after message is ACK'd or NAK'd. The flag + * will serve as a guard to indicate that the VDM reply buffer is not + * yet ready to read. + * + */ + if (PD_VDO_SVDM(dpm[port].vdm_req[0]) && + (PD_VDO_CMD(dpm[port].vdm_req[0]) == CMD_ATTENTION)) + DPM_CLR_FLAG(port, DPM_FLAG_SEND_VDM_REQ); +} + +void dpm_notify_attention(int port, size_t vdo_objects, uint32_t *buf) +{ + /* + * Note: legacy code just assumes 1 VDO, but the spec allows 0 + * This should be fine because baked-in EC logic will only be + * handling DP:Attention messages, which are defined to have 1 + * VDO + */ + dfp_consume_attention(port, buf); + ap_vdm_attention_enqueue(port, vdo_objects, buf); +} + +void dpm_handle_alert(int port, uint32_t ado) +{ + if (ado & ADO_EXTENDED_ALERT_EVENT) { + /* Extended Alert */ + if (pd_get_data_role(port) == PD_ROLE_DFP && + (ADO_EXTENDED_ALERT_EVENT_TYPE & ado) == + ADO_POWER_BUTTON_PRESS) { + DPM_SET_FLAG(port, DPM_FLAG_PD_BUTTON_PRESSED); + } else if (pd_get_data_role(port) == PD_ROLE_DFP && + (ADO_EXTENDED_ALERT_EVENT_TYPE & ado) == + ADO_POWER_BUTTON_RELEASE) { + DPM_SET_FLAG(port, DPM_FLAG_PD_BUTTON_RELEASED); + } + } +} + +static void dpm_run_pd_button_sm(int port) +{ +#ifdef CONFIG_AP_POWER_CONTROL + if (!IS_ENABLED(CONFIG_POWER_BUTTON_X86) && + !IS_ENABLED(CONFIG_CHIPSET_SC7180) && + !IS_ENABLED(CONFIG_CHIPSET_SC7280)) { + /* Insufficient chipset API support for USB PD power button. */ + DPM_CLR_FLAG(port, DPM_FLAG_PD_BUTTON_PRESSED); + DPM_CLR_FLAG(port, DPM_FLAG_PD_BUTTON_RELEASED); + return; + } + + /* + * Check for invalid flag combination. Alerts can only send a press or + * release event at once and only one flag should be set. If press and + * release flags are both set, we cannot know the order they were + * received. Clear the flags, disable the timer and return to an idle + * state. + */ + if (DPM_CHK_FLAG(port, DPM_FLAG_PD_BUTTON_PRESSED) && + DPM_CHK_FLAG(port, DPM_FLAG_PD_BUTTON_RELEASED)) { + DPM_CLR_FLAG(port, DPM_FLAG_PD_BUTTON_PRESSED | + DPM_FLAG_PD_BUTTON_RELEASED); + pd_timer_disable(port, DPM_TIMER_PD_BUTTON_SHORT_PRESS); + pd_timer_disable(port, DPM_TIMER_PD_BUTTON_LONG_PRESS); + dpm[port].pd_button_state = DPM_PD_BUTTON_IDLE; + return; + } + + switch (dpm[port].pd_button_state) { + case DPM_PD_BUTTON_IDLE: + if (DPM_CHK_FLAG(port, DPM_FLAG_PD_BUTTON_PRESSED)) { + pd_timer_enable(port, DPM_TIMER_PD_BUTTON_SHORT_PRESS, + CONFIG_USB_PD_SHORT_PRESS_MAX_MS * + MSEC); + pd_timer_enable(port, DPM_TIMER_PD_BUTTON_LONG_PRESS, + CONFIG_USB_PD_LONG_PRESS_MAX_MS * MSEC); + dpm[port].pd_button_state = DPM_PD_BUTTON_PRESSED; + } + break; + case DPM_PD_BUTTON_PRESSED: + if (DPM_CHK_FLAG(port, DPM_FLAG_PD_BUTTON_PRESSED)) { + pd_timer_enable(port, DPM_TIMER_PD_BUTTON_SHORT_PRESS, + CONFIG_USB_PD_SHORT_PRESS_MAX_MS * + MSEC); + pd_timer_enable(port, DPM_TIMER_PD_BUTTON_LONG_PRESS, + CONFIG_USB_PD_LONG_PRESS_MAX_MS * MSEC); + } else if (pd_timer_is_expired( + port, DPM_TIMER_PD_BUTTON_LONG_PRESS)) { + pd_timer_disable(port, DPM_TIMER_PD_BUTTON_SHORT_PRESS); + pd_timer_disable(port, DPM_TIMER_PD_BUTTON_LONG_PRESS); + dpm[port].pd_button_state = DPM_PD_BUTTON_IDLE; + } else if (DPM_CHK_FLAG(port, DPM_FLAG_PD_BUTTON_RELEASED)) { + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + /* + * Wake chipset on any button press when the + * system is off. + */ + chipset_power_on(); + } else if (chipset_in_state( + CHIPSET_STATE_ANY_SUSPEND) || + chipset_in_state(CHIPSET_STATE_ON)) { + if (pd_timer_is_expired( + port, + DPM_TIMER_PD_BUTTON_SHORT_PRESS)) { + /* + * Shutdown chipset on long USB PD power + * button press. + */ + chipset_force_shutdown( + CHIPSET_SHUTDOWN_BUTTON); + } else { + /* + * Simulate a short power button press + * on short USB PD power button press. + * This will wake the system from + * suspend, or bring up the power UI + * when the system is on. + */ + power_button_simulate_press( + USB_PD_SHORT_BUTTON_PRESS_MS); + } + } + pd_timer_disable(port, DPM_TIMER_PD_BUTTON_SHORT_PRESS); + pd_timer_disable(port, DPM_TIMER_PD_BUTTON_LONG_PRESS); + dpm[port].pd_button_state = DPM_PD_BUTTON_IDLE; + } + break; + } +#endif /* CONFIG_AP_POWER_CONTROL */ + + /* After checking flags, clear them. */ + DPM_CLR_FLAG(port, DPM_FLAG_PD_BUTTON_PRESSED); + DPM_CLR_FLAG(port, DPM_FLAG_PD_BUTTON_RELEASED); +} + +/* + * Source-out policy variables and APIs + * + * Priority for the available 3.0 A ports is given in the following order: + * - sink partners which report requiring > 1.5 A in their Sink_Capabilities + */ + +/* + * Bitmasks of port numbers in each following category + * + * Note: request bitmasks should be accessed atomically as other ports may alter + * them + */ +static uint32_t max_current_claimed; +K_MUTEX_DEFINE(max_current_claimed_lock); + +/* Ports with PD sink needing > 1.5 A */ +static atomic_t sink_max_pdo_requested; +/* Ports with FRS source needing > 1.5 A */ +static atomic_t source_frs_max_requested; +/* Ports with non-PD sinks, so current requirements are unknown */ +static atomic_t non_pd_sink_max_requested; + +/* BIST shared test mode */ +static bool bist_shared_mode_enabled; + +#define LOWEST_PORT(p) __builtin_ctz(p) /* Undefined behavior if p == 0 */ + +static int count_port_bits(uint32_t bitmask) +{ + int i, total = 0; + + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (bitmask & BIT(i)) + total++; } + + return total; } /* - * The call to this function requests that the PE send one VDM, whichever is - * next in the mode entry sequence. This only happens if preconditions for mode - * entry are met. + * Centralized, mutex-controlled updates to the claimed 3.0 A ports */ -static void dpm_attempt_mode_entry(int port) +static void balance_source_ports(void); +DECLARE_DEFERRED(balance_source_ports); + +static void balance_source_ports(void) +{ + uint32_t removed_ports, new_ports; + static bool deferred_waiting; + + if (in_deferred_context()) + deferred_waiting = false; + + /* + * Ignore balance attempts while we're waiting for a downgraded port to + * finish the downgrade. + */ + if (deferred_waiting) + return; + + /* + * Turn off all shared power logic while BIST shared test mode is active + * on the system. + */ + if (bist_shared_mode_enabled) + return; + + mutex_lock(&max_current_claimed_lock); + + /* Remove any ports which no longer require 3.0 A */ + removed_ports = max_current_claimed & + ~(sink_max_pdo_requested | source_frs_max_requested | + non_pd_sink_max_requested); + max_current_claimed &= ~removed_ports; + + /* Allocate 3.0 A to new PD sink ports that need it */ + new_ports = sink_max_pdo_requested & ~max_current_claimed; + while (new_ports) { + int new_max_port = LOWEST_PORT(new_ports); + + if (count_port_bits(max_current_claimed) < + CONFIG_USB_PD_3A_PORTS) { + max_current_claimed |= BIT(new_max_port); + typec_select_src_current_limit_rp(new_max_port, + TYPEC_RP_3A0); + } else if (non_pd_sink_max_requested & max_current_claimed) { + /* Always downgrade non-PD ports first */ + int rem_non_pd = LOWEST_PORT(non_pd_sink_max_requested & + max_current_claimed); + typec_select_src_current_limit_rp( + rem_non_pd, + typec_get_default_current_limit_rp(rem_non_pd)); + max_current_claimed &= ~BIT(rem_non_pd); + + /* Wait tSinkAdj before using current */ + deferred_waiting = true; + hook_call_deferred(&balance_source_ports_data, + PD_T_SINK_ADJ); + goto unlock; + } else if (source_frs_max_requested & max_current_claimed) { + /* Downgrade lowest FRS port from 3.0 A slot */ + int rem_frs = LOWEST_PORT(source_frs_max_requested & + max_current_claimed); + pd_dpm_request(rem_frs, DPM_REQUEST_FRS_DET_DISABLE); + max_current_claimed &= ~BIT(rem_frs); + + /* Give 20 ms for the PD task to process DPM flag */ + deferred_waiting = true; + hook_call_deferred(&balance_source_ports_data, + 20 * MSEC); + goto unlock; + } else { + /* No lower priority ports to downgrade */ + goto unlock; + } + new_ports &= ~BIT(new_max_port); + } + + /* Allocate 3.0 A to any new FRS ports that need it */ + new_ports = source_frs_max_requested & ~max_current_claimed; + while (new_ports) { + int new_frs_port = LOWEST_PORT(new_ports); + + if (count_port_bits(max_current_claimed) < + CONFIG_USB_PD_3A_PORTS) { + max_current_claimed |= BIT(new_frs_port); + pd_dpm_request(new_frs_port, + DPM_REQUEST_FRS_DET_ENABLE); + } else if (non_pd_sink_max_requested & max_current_claimed) { + int rem_non_pd = LOWEST_PORT(non_pd_sink_max_requested & + max_current_claimed); + typec_select_src_current_limit_rp( + rem_non_pd, + typec_get_default_current_limit_rp(rem_non_pd)); + max_current_claimed &= ~BIT(rem_non_pd); + + /* Wait tSinkAdj before using current */ + deferred_waiting = true; + hook_call_deferred(&balance_source_ports_data, + PD_T_SINK_ADJ); + goto unlock; + } else { + /* No lower priority ports to downgrade */ + goto unlock; + } + new_ports &= ~BIT(new_frs_port); + } + + /* Allocate 3.0 A to any non-PD ports which could need it */ + new_ports = non_pd_sink_max_requested & ~max_current_claimed; + while (new_ports) { + int new_max_port = LOWEST_PORT(new_ports); + + if (count_port_bits(max_current_claimed) < + CONFIG_USB_PD_3A_PORTS) { + max_current_claimed |= BIT(new_max_port); + typec_select_src_current_limit_rp(new_max_port, + TYPEC_RP_3A0); + } else { + /* No lower priority ports to downgrade */ + goto unlock; + } + new_ports &= ~BIT(new_max_port); + } +unlock: + mutex_unlock(&max_current_claimed_lock); +} + +/* Process port's first Sink_Capabilities PDO for port current consideration */ +void dpm_evaluate_sink_fixed_pdo(int port, uint32_t vsafe5v_pdo) +{ + /* Verify partner supplied valid vSafe5V fixed object first */ + if ((vsafe5v_pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED) + return; + + if (PDO_FIXED_VOLTAGE(vsafe5v_pdo) != 5000) + return; + + if (pd_get_power_role(port) == PD_ROLE_SOURCE) { + if (CONFIG_USB_PD_3A_PORTS == 0) + return; + + /* Valid PDO to process, so evaluate whether >1.5A is needed */ + if (PDO_FIXED_CURRENT(vsafe5v_pdo) <= 1500) + return; + + atomic_or(&sink_max_pdo_requested, BIT(port)); + } else { + int frs_current = vsafe5v_pdo & PDO_FIXED_FRS_CURR_MASK; + + if (!IS_ENABLED(CONFIG_USB_PD_FRS)) + return; + + /* FRS is only supported in PD 3.0 and higher */ + if (pd_get_rev(port, TCPCI_MSG_SOP) == PD_REV20) + return; + + if ((vsafe5v_pdo & PDO_FIXED_DUAL_ROLE) && frs_current) { + /* Always enable FRS when 3.0 A is not needed */ + if (frs_current == PDO_FIXED_FRS_CURR_DFLT_USB_POWER || + frs_current == PDO_FIXED_FRS_CURR_1A5_AT_5V) { + pd_dpm_request(port, + DPM_REQUEST_FRS_DET_ENABLE); + return; + } + + if (CONFIG_USB_PD_3A_PORTS == 0) + return; + + atomic_or(&source_frs_max_requested, BIT(port)); + } else { + return; + } + } + + balance_source_ports(); +} + +void dpm_add_non_pd_sink(int port) +{ + if (CONFIG_USB_PD_3A_PORTS == 0) + return; + + atomic_or(&non_pd_sink_max_requested, BIT(port)); + + balance_source_ports(); +} + +void dpm_evaluate_request_rdo(int port, uint32_t rdo) +{ + int idx; + int op_ma; + + if (CONFIG_USB_PD_3A_PORTS == 0) + return; + + idx = RDO_POS(rdo); + /* Check for invalid index */ + if (!idx) + return; + + op_ma = (rdo >> 10) & 0x3FF; + if ((BIT(port) & sink_max_pdo_requested) && (op_ma <= 150)) { + /* + * sink_max_pdo_requested will be set when we get 5V/3A sink + * capability from port partner. If port partner only request + * 5V/1.5A, we need to provide 5V/1.5A. + */ + atomic_clear_bits(&sink_max_pdo_requested, BIT(port)); + + balance_source_ports(); + } +} + +void dpm_remove_sink(int port) +{ + if (CONFIG_USB_PD_3A_PORTS == 0) + return; + + if (!(BIT(port) & (uint32_t)sink_max_pdo_requested) && + !(BIT(port) & (uint32_t)non_pd_sink_max_requested)) + return; + + atomic_clear_bits(&sink_max_pdo_requested, BIT(port)); + atomic_clear_bits(&non_pd_sink_max_requested, BIT(port)); + + /* Restore selected default Rp on the port */ + typec_select_src_current_limit_rp( + port, typec_get_default_current_limit_rp(port)); + + balance_source_ports(); +} + +void dpm_remove_source(int port) +{ + if (CONFIG_USB_PD_3A_PORTS == 0) + return; + + if (!IS_ENABLED(CONFIG_USB_PD_FRS)) + return; + + if (!(BIT(port) & (uint32_t)source_frs_max_requested)) + return; + + atomic_clear_bits(&source_frs_max_requested, BIT(port)); + + balance_source_ports(); +} + +void dpm_bist_shared_mode_enter(int port) +{ + /* + * From 6.4.3.3.1 BIST Shared Test Mode Entry: + * + * "When any Master Port in a shared capacity group receives a BIST + * Message with a BIST Shared Test Mode Entry BIST Data Object, while + * in the PE_SRC_Ready State, the UUT Shall enter a compliance test + * mode where the maximum source capability is always offered on every + * port, regardless of the availability of shared power i.e. all shared + * power management is disabled. + * . . . + * On entering this mode, the UUT Shall send a new Source_Capabilities + * Message from each Port in the shared capacity group within + * tBISTSharedTestMode. The Tester will not exceed the shared capacity + * during this mode." + */ + + /* Shared mode is unnecessary without at least one 3.0 A port */ + if (CONFIG_USB_PD_3A_PORTS == 0) + return; + + /* Enter mode only if this port had been in PE_SRC_Ready */ + if (pd_get_power_role(port) != PD_ROLE_SOURCE) + return; + + bist_shared_mode_enabled = true; + + /* Trigger new source caps on all source ports */ + for (int i = 0; i < board_get_usb_pd_port_count(); i++) { + if (pd_get_power_role(i) == PD_ROLE_SOURCE) + typec_select_src_current_limit_rp(i, TYPEC_RP_3A0); + } +} + +void dpm_bist_shared_mode_exit(int port) +{ + /* + * From 6.4.3.3.2 BIST Shared Test Mode Exit: + * + * "Upon receipt of a BIST Message, with a BIST Shared Test Mode Exit + * BIST Data Object, the UUT Shall return a GoodCRC Message and Shall + * exit the BIST Shared Capacity Test Mode. + * . . . + * On exiting the mode, the UUT May send a new Source_Capabilities + * Message to each port in the shared capacity group or the UUT May + * perform ErrorRecovery on each port." + */ + + /* Shared mode is unnecessary without at least one 3.0 A port */ + if (CONFIG_USB_PD_3A_PORTS == 0) + return; + + /* Do nothing if Exit was received with no Entry */ + if (!bist_shared_mode_enabled) + return; + + bist_shared_mode_enabled = false; + + /* Declare error recovery bankruptcy */ + for (int i = 0; i < board_get_usb_pd_port_count(); i++) { + pd_set_error_recovery(i); + } +} + +/* + * Note: all ports receive the 1.5 A source offering until they are found to + * match a criteria on the 3.0 A priority list (ex. through sink capability + * probing), at which point they will be offered a new 3.0 A source capability. + * + * All ports must be offered our full capability while in BIST shared test mode. + */ +__overridable int dpm_get_source_pdo(const uint32_t **src_pdo, const int port) +{ + /* Max PDO may not exist on boards which don't offer 3 A */ +#if CONFIG_USB_PD_3A_PORTS > 0 + if (max_current_claimed & BIT(port) || bist_shared_mode_enabled) { + *src_pdo = pd_src_pdo_max; + return pd_src_pdo_max_cnt; + } +#endif + + *src_pdo = pd_src_pdo; + return pd_src_pdo_cnt; +} + +int dpm_get_source_current(const int port) +{ + if (pd_get_power_role(port) == PD_ROLE_SINK) + return 0; + + if (max_current_claimed & BIT(port) || bist_shared_mode_enabled) + return 3000; + else if (typec_get_default_current_limit_rp(port) == TYPEC_RP_1A5) + return 1500; + else + return 500; +} + +__overridable enum pd_sdb_power_indicator +board_get_pd_sdb_power_indicator(enum pd_sdb_power_state power_state) +{ + /* + * LED on for S0 and blinking for S0ix/S3. + * LED off for all other power states (S4, S5, G3, NOT_SUPPORTED) + */ + switch (power_state) { + case PD_SDB_POWER_STATE_S0: + return PD_SDB_POWER_INDICATOR_ON; + case PD_SDB_POWER_STATE_MODERN_STANDBY: + case PD_SDB_POWER_STATE_S3: + return PD_SDB_POWER_INDICATOR_BLINKING; + default: + return PD_SDB_POWER_INDICATOR_OFF; + } +} + +static uint8_t get_status_internal_temp(void) +{ + /* + * Internal Temp + */ +#ifdef CONFIG_TEMP_SENSOR + int temp_k, temp_c; + + if (temp_sensor_read(CONFIG_USB_PD_TEMP_SENSOR, &temp_k) != EC_SUCCESS) + return 0; + + /* Check temp is in expected range (<255°C) */ + temp_c = K_TO_C(temp_k); + if (temp_c > 255) + return 0; + else if (temp_c < 2) + temp_c = 1; + + return (uint8_t)temp_c; +#else + return 0; +#endif +} + +static enum pd_sdb_temperature_status get_status_temp_status(void) +{ + /* + * Temperature Status + * + * OTP events are currently unsupported by the EC, the temperature + * status will be reported as "not supported" on temp sensor read + * failures and "Normal" otherwise. + */ +#ifdef CONFIG_TEMP_SENSOR + int temp_k; + + if (temp_sensor_read(CONFIG_USB_PD_TEMP_SENSOR, &temp_k) != EC_SUCCESS) + return PD_SDB_TEMPERATURE_STATUS_NOT_SUPPORTED; + + return PD_SDB_TEMPERATURE_STATUS_NORMAL; +#else + return PD_SDB_TEMPERATURE_STATUS_NOT_SUPPORTED; +#endif +} + +static uint8_t get_status_power_state_change(void) +{ + enum pd_sdb_power_state ret = PD_SDB_POWER_STATE_NOT_SUPPORTED; + +#ifdef CONFIG_AP_POWER_CONTROL + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_HARD_OFF)) { + ret = PD_SDB_POWER_STATE_G3; + } else if (chipset_in_or_transitioning_to_state( + CHIPSET_STATE_SOFT_OFF)) { + /* + * SOFT_OFF includes S4; chipset_state API doesn't support S4 + * specifically, so fold S4 to S5 + */ + ret = PD_SDB_POWER_STATE_S5; + } else if (chipset_in_or_transitioning_to_state( + CHIPSET_STATE_SUSPEND)) { + ret = PD_SDB_POWER_STATE_S3; + } else if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON)) { + ret = PD_SDB_POWER_STATE_S0; + } else if (chipset_in_or_transitioning_to_state( + CHIPSET_STATE_STANDBY)) { + ret = PD_SDB_POWER_STATE_MODERN_STANDBY; + } +#endif /* CONFIG_AP_POWER_CONTROL */ + + return ret | board_get_pd_sdb_power_indicator(ret); +} + +int dpm_get_status_msg(int port, uint8_t *msg, uint32_t *len) +{ + struct pd_sdb sdb; + struct rmdo partner_rmdo; + + /* TODO(b/227236917): Fill in fields of Status message */ + + /* Internal Temp */ + sdb.internal_temp = get_status_internal_temp(); + + /* Present Input */ + sdb.present_input = 0x0; + + /* Present Battery Input */ + sdb.present_battery_input = 0x0; + + /* Event Flags */ + sdb.event_flags = 0x0; + + /* Temperature Status */ + sdb.temperature_status = get_status_temp_status(); + + /* Power Status */ + sdb.power_status = 0x0; + + partner_rmdo = pd_get_partner_rmdo(port); + if ((partner_rmdo.major_rev == 3 && partner_rmdo.minor_rev >= 1) || + partner_rmdo.major_rev > 3) { + /* USB PD Rev 3.1: 6.5.2 Status Message */ + sdb.power_state_change = get_status_power_state_change(); + *len = 7; + } else { + /* USB PD Rev 3.0: 6.5.2 Status Message */ + sdb.power_state_change = 0; + *len = 6; + } + + memcpy(msg, &sdb, *len); + return EC_SUCCESS; +} + +enum ec_status pd_set_bist_share_mode(uint8_t enable) +{ + /* + * This command is not allowed if system is locked. + */ + if (CONFIG_USB_PD_3A_PORTS == 0 || system_is_locked()) + return EC_RES_ACCESS_DENIED; + + if (enable) + bist_shared_mode_enabled = true; + else + bist_shared_mode_enabled = false; + + return EC_RES_SUCCESS; +} + +uint8_t pd_get_bist_share_mode(void) +{ + return bist_shared_mode_enabled; +} + +/* + * Requests that the PE send one VDM, whichever is next in the mode entry + * sequence. This only happens if preconditions for mode entry are met. If + * CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY is enabled, this function waits for the + * AP to direct mode entry. + * + * Returns true when the DPM state is changed in this function. + */ +static bool dpm_dfp_enter_mode_msg(int port) { int vdo_count = 0; uint32_t vdm[VDO_MAX_SIZE]; - enum tcpm_transmit_type tx_type = TCPC_TX_SOP; + enum tcpci_msg_type tx_type = TCPCI_MSG_SOP; + bool enter_mode_requested = + IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) ? false : true; + enum dpm_msg_setup_status status = MSG_SETUP_UNSUPPORTED; - if (pd_get_data_role(port) != PD_ROLE_DFP) - return; +#ifdef CONFIG_AP_POWER_CONTROL /* * Do not try to enter mode while CPU is off. * CPU transitions (e.g b/158634281) can occur during the discovery @@ -112,48 +1185,107 @@ static void dpm_attempt_mode_entry(int port) * of the modes can get out of sync, causing the attempt to * enter the mode to fail prematurely. */ - if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) - return; + if (!chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON)) + return false; +#endif /* * If discovery has not occurred for modes, do not attempt to switch * to alt mode. */ - if (pd_get_svids_discovery(port, TCPC_TX_SOP) != PD_DISC_COMPLETE || - pd_get_modes_discovery(port, TCPC_TX_SOP) != PD_DISC_COMPLETE) - return; + if (pd_get_svids_discovery(port, TCPCI_MSG_SOP) != PD_DISC_COMPLETE || + pd_get_modes_discovery(port, TCPCI_MSG_SOP) != PD_DISC_COMPLETE) + return false; - /* Check if the device and cable support USB4. */ - if (IS_ENABLED(CONFIG_USB_PD_USB4) && enter_usb_is_capable(port)) { - pd_dpm_request(port, DPM_REQUEST_ENTER_USB); - return; + if (dp_entry_is_done(port) || + (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && + tbt_entry_is_done(port)) || + (IS_ENABLED(CONFIG_USB_PD_USB4) && enter_usb_entry_is_done(port))) { + dpm_set_mode_entry_done(port); + return false; + } + + /* + * If AP mode entry is enabled, and a Data Reset has not been done, then + * first request Data Reset prior to attempting to enter any modes. + */ + if (IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) && + IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) && + DPM_CHK_FLAG(port, DPM_FLAG_ENTER_ANY) && + !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) { + set_state_dpm(port, DPM_DATA_RESET); + return true; + } + + /* Check if port, port partner and cable support USB4. */ + if (IS_ENABLED(CONFIG_USB_PD_USB4) && board_is_tbt_usb4_port(port) && + enter_usb_port_partner_is_capable(port) && + enter_usb_cable_is_capable(port) && + dpm_mode_entry_requested(port, TYPEC_MODE_USB4)) { + /* + * For certain cables, enter Thunderbolt alt mode with the + * cable and USB4 mode with the port partner. + */ + if (tbt_cable_entry_required_for_usb4(port)) { + vdo_count = ARRAY_SIZE(vdm); + status = tbt_setup_next_vdm(port, &vdo_count, vdm, + &tx_type); + } else { + pd_dpm_request(port, DPM_REQUEST_ENTER_USB); + return false; + } } /* If not, check if they support Thunderbolt alt mode. */ if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && - pd_is_mode_discovered_for_svid(port, TCPC_TX_SOP, USB_VID_INTEL)) - vdo_count = tbt_setup_next_vdm(port, - ARRAY_SIZE(vdm), vdm, &tx_type); + board_is_tbt_usb4_port(port) && + pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP, + USB_VID_INTEL) && + dpm_mode_entry_requested(port, TYPEC_MODE_TBT)) { + enter_mode_requested = true; + vdo_count = ARRAY_SIZE(vdm); + status = tbt_setup_next_vdm(port, &vdo_count, vdm, &tx_type); + } /* If not, check if they support DisplayPort alt mode. */ - if (vdo_count == 0 && !dpm[port].mode_entry_done && - pd_is_mode_discovered_for_svid(port, TCPC_TX_SOP, - USB_SID_DISPLAYPORT)) - vdo_count = dp_setup_next_vdm(port, ARRAY_SIZE(vdm), vdm); + if (status == MSG_SETUP_UNSUPPORTED && + !DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE) && + pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP, + USB_SID_DISPLAYPORT) && + dpm_mode_entry_requested(port, TYPEC_MODE_DP)) { + enter_mode_requested = true; + vdo_count = ARRAY_SIZE(vdm); + status = dp_setup_next_vdm(port, &vdo_count, vdm); + } + + /* Not ready to send a VDM, check again next cycle */ + if (status == MSG_SETUP_MUX_WAIT) + return false; /* - * If the PE didn't discover any supported alternate mode, just mark - * setup done and get out of here. + * If the PE didn't discover any supported (requested) alternate mode, + * just mark setup done and get out of here. */ - if (vdo_count == 0 && !dpm[port].mode_entry_done) { - CPRINTS("C%d: No supported alt mode discovered", port); + if (status != MSG_SETUP_SUCCESS && + !DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE)) { + if (enter_mode_requested) { + /* + * TODO(b/168030639): Notify the AP that mode entry + * failed. + */ + CPRINTS("C%d: No supported alt mode discovered", port); + } + /* + * If the AP did not request mode entry, it may do so in the + * future, but the DPM is done trying for now. + */ dpm_set_mode_entry_done(port); - return; + return false; } - if (vdo_count < 0) { + if (status != MSG_SETUP_SUCCESS) { dpm_set_mode_entry_done(port); CPRINTS("C%d: Couldn't construct alt mode VDM", port); - return; + return false; } /* @@ -162,59 +1294,246 @@ static void dpm_attempt_mode_entry(int port) */ if (!pd_setup_vdm_request(port, tx_type, vdm, vdo_count)) { dpm_set_mode_entry_done(port); - return; + return false; } + /* Wait for PE to handle VDM request */ pd_dpm_request(port, DPM_REQUEST_VDM); + set_state_dpm(port, DPM_WAITING); + + return true; } -static void dpm_attempt_mode_exit(int port) +/* + * Checks to see if either USB4 or ALT-DP/TBT modes need to be exited. If the + * DPM is requesting the PE to send an exit message, then this function will + * return true to indicate that the DPM state has been changed. + */ +static bool dpm_dfp_exit_mode_msg(int port) { - int opos; - uint16_t svid; - uint32_t vdm; + uint32_t vdm[VDO_MAX_SIZE]; + int vdo_count = ARRAY_SIZE(vdm); + enum dpm_msg_setup_status status = MSG_SETUP_ERROR; + enum tcpci_msg_type tx_type = TCPCI_MSG_SOP; - /* TODO(b/156749387): Support Data Reset for exiting USB4. */ - if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && - tbt_is_active(port)) - svid = USB_VID_INTEL; - else if (dp_is_active(port)) - svid = USB_SID_DISPLAYPORT; - else { + /* First, try Data Reset. If Data Reset completes, all the alt mode + * state checked below will reset to its inactive state. If Data Reset + * is not supported, exit active modes individually. + */ + if (IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) && + !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) { + set_state_dpm(port, DPM_DATA_RESET); + return true; + } + + /* TODO(b/209625351): Data Reset is the only real way to exit from USB4 + * mode. If that failed, the TCPM shouldn't try anything else. + */ + if (IS_ENABLED(CONFIG_USB_PD_USB4) && enter_usb_entry_is_done(port)) { + CPRINTS("C%d: USB4 teardown", port); + usb4_exit_mode_request(port); + } + + if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && tbt_is_active(port)) { + /* + * When the port is in USB4 mode and receives an exit request, + * it leaves USB4 SOP in active state. + */ + CPRINTS("C%d: TBT teardown", port); + tbt_exit_mode_request(port); + status = tbt_setup_next_vdm(port, &vdo_count, vdm, &tx_type); + } else if (dp_is_active(port)) { + CPRINTS("C%d: DP teardown", port); + status = dp_setup_next_vdm(port, &vdo_count, vdm); + } else { /* Clear exit mode request */ dpm_clear_mode_exit_request(port); + return false; + } + + /* This covers error, wait mux, and unsupported cases */ + if (status != MSG_SETUP_SUCCESS) + return false; + + if (!pd_setup_vdm_request(port, tx_type, vdm, vdo_count)) { + dpm_clear_mode_exit_request(port); + return false; + } + + pd_dpm_request(port, DPM_REQUEST_VDM); + set_state_dpm(port, DPM_WAITING); + + return true; +} + +void dpm_run(int port, int evt, int en) +{ + switch (local_state[port]) { + case SM_PAUSED: + if (!en) + break; + __fallthrough; + case SM_INIT: + dpm_init(port); + local_state[port] = SM_RUN; + __fallthrough; + case SM_RUN: + if (!en) { + local_state[port] = SM_PAUSED; + /* + * While we are paused, exit all states and wait until + * initialized again. + */ + set_state(port, &dpm[port].ctx, NULL); + break; + } + + /* Run state machine */ + run_state(port, &dpm[port].ctx); + + break; + } +} + +/* + * DPM_WAITING + */ +static void dpm_waiting_entry(const int port) +{ + DPM_CLR_FLAG(port, DPM_FLAG_PE_READY); + if (dpm_debug_level >= DEBUG_LEVEL_2) { + print_current_state(port); + } +} + +static void dpm_waiting_run(const int port) +{ + enum pd_data_role dr = pd_get_data_role(port); + + if (DPM_CHK_FLAG(port, DPM_FLAG_PE_READY)) { + if (dr == PD_ROLE_UFP) { + set_state_dpm(port, DPM_UFP_READY); + } else if (dr == PD_ROLE_DFP) { + set_state_dpm(port, DPM_DFP_READY); + } + } +} + +/* + * DPM_DFP_READY + */ +static void dpm_dfp_ready_entry(const int port) +{ + if (dpm_debug_level >= DEBUG_LEVEL_2) { + print_current_state(port); + } +} + +static void dpm_dfp_ready_run(const int port) +{ + if (!DPM_CHK_FLAG(port, DPM_FLAG_PE_READY)) { + set_state_dpm(port, DPM_WAITING); return; } + /* Run power button state machine */ + dpm_run_pd_button_sm(port); + /* - * TODO(b/148528713): Support cable plug Exit Mode (probably outsource - * VDM construction to alt mode modules). + * If muxes are still settling, then wait on our next VDM. We must + * ensure we correctly sequence actions such as USB safe state with TBT + * or DP mode exit. */ - opos = pd_alt_mode(port, TCPC_TX_SOP, svid); - if (opos > 0 && pd_dfp_exit_mode(port, TCPC_TX_SOP, svid, opos)) { - /* - * TODO b/159717794: Delay deleting the data until after the - * EXIT_MODE message is has ACKed. Unfortunately the callers - * of this function expect the mode to be cleaned up before - * return. - */ - vdm = VDO(svid, 1, /* Structured */ - VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)) | - VDO_OPOS(opos) | VDO_CMDT(CMDT_INIT) | CMD_EXIT_MODE); + if (IS_ENABLED(CONFIG_USBC_SS_MUX) && !usb_mux_set_completed(port)) + return; - if (!pd_setup_vdm_request(port, TCPC_TX_SOP, &vdm, 1)) { - dpm_clear_mode_exit_request(port); + /* Run DFP related DPM requests */ + if (DPM_CHK_FLAG(port, DPM_FLAG_EXIT_REQUEST)) { + if (dpm_dfp_exit_mode_msg(port)) return; - } + } else if (!DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE)) { + if (dpm_dfp_enter_mode_msg(port)) + return; + } - pd_dpm_request(port, DPM_REQUEST_VDM); + /* Run any VDM REQ messages */ + if (DPM_CHK_FLAG(port, DPM_FLAG_SEND_VDM_REQ)) { + dpm_send_req_vdm(port); + set_state_dpm(port, DPM_WAITING); + return; + } +} + +/* + * DPM_UFP_READY + */ +static void dpm_ufp_ready_entry(const int port) +{ + if (dpm_debug_level >= DEBUG_LEVEL_2) { + print_current_state(port); + } +} + +static void dpm_ufp_ready_run(const int port) +{ + if (!DPM_CHK_FLAG(port, DPM_FLAG_PE_READY)) { + set_state_dpm(port, DPM_WAITING); + return; + } + + if (DPM_CHK_FLAG(port, DPM_FLAG_ENTER_ANY)) { + DPM_CLR_FLAG(port, DPM_FLAG_ENTER_DP | DPM_FLAG_ENTER_TBT | + DPM_FLAG_ENTER_USB4); + /* + * TODO(b/168030639): Notify the AP that the + * enter mode request failed. + */ + return; + } + + /* Run any VDM REQ messages */ + if (DPM_CHK_FLAG(port, DPM_FLAG_SEND_VDM_REQ)) { + dpm_send_req_vdm(port); + set_state_dpm(port, DPM_WAITING); + return; } } -void dpm_run(int port) +/* + * DPM_DATA_RESET + */ +static void dpm_data_reset_entry(const int port) { - if (dpm[port].mode_exit_request) - dpm_attempt_mode_exit(port); - else if (!dpm[port].mode_entry_done) - dpm_attempt_mode_entry(port); + print_current_state(port); + + pd_dpm_request(port, DPM_REQUEST_DATA_RESET); } + +static void dpm_data_reset_run(const int port) +{ + /* Wait for Data Reset to Complete */ + if (!DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) + return; + + set_state_dpm(port, DPM_DFP_READY); +} + +static __const_data const struct usb_state dpm_states[] = { + /* Normal States */ + [DPM_WAITING] = { + .entry = dpm_waiting_entry, + .run = dpm_waiting_run, + }, + [DPM_DFP_READY] = { + .entry = dpm_dfp_ready_entry, + .run = dpm_dfp_ready_run, + }, + [DPM_UFP_READY] = { + .entry = dpm_ufp_ready_entry, + .run = dpm_ufp_ready_run, + }, + [DPM_DATA_RESET] = { + .entry = dpm_data_reset_entry, + .run = dpm_data_reset_run, + }, +}; diff --git a/common/usbc/usb_pd_host.c b/common/usbc/usb_pd_host.c index 61c1c69966..81cdc4fc49 100644 --- a/common/usbc/usb_pd_host.c +++ b/common/usbc/usb_pd_host.c @@ -1,21 +1,23 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Host commands for TCPMv2 USB PD module */ -#include - #include "console.h" #include "ec_commands.h" #include "host_command.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_dpm_sm.h" +#include "usb_pd_tcpm.h" #include "util.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) /* Retrieve all discovery results for the given port and transmit type */ static enum ec_status hc_typec_discovery(struct host_cmd_handler_args *args) @@ -23,7 +25,7 @@ static enum ec_status hc_typec_discovery(struct host_cmd_handler_args *args) const struct ec_params_typec_discovery *p = args->params; struct ec_response_typec_discovery *r = args->response; const struct pd_discovery *disc; - enum tcpm_transmit_type type; + enum tcpci_msg_type type; /* Confirm the number of HC VDOs matches our stored VDOs */ BUILD_ASSERT(sizeof(r->discovery_vdo) == sizeof(union disc_ident_ack)); @@ -34,8 +36,8 @@ static enum ec_status hc_typec_discovery(struct host_cmd_handler_args *args) if (p->partner_type > TYPEC_PARTNER_SOP_PRIME) return EC_RES_INVALID_PARAM; - type = p->partner_type == TYPEC_PARTNER_SOP ? - TCPC_TX_SOP : TCPC_TX_SOP_PRIME; + type = p->partner_type == TYPEC_PARTNER_SOP ? TCPCI_MSG_SOP : + TCPCI_MSG_SOP_PRIME; /* * Clear out access mask so we can track if tasks have touched data @@ -43,7 +45,7 @@ static enum ec_status hc_typec_discovery(struct host_cmd_handler_args *args) */ pd_discovery_access_clear(p->port, type); - disc = pd_get_am_discovery(p->port, type); + disc = pd_get_am_discovery_and_notify_access(p->port, type); /* Initialize return size to that of discovery with no SVIDs */ args->response_size = sizeof(*r); @@ -60,8 +62,9 @@ static enum ec_status hc_typec_discovery(struct host_cmd_handler_args *args) if (pd_get_modes_discovery(p->port, type) == PD_DISC_COMPLETE) { int svid_i; - int max_resp_svids = (args->response_max - args->response_size)/ - sizeof(struct svid_mode_info); + int max_resp_svids = + (args->response_max - args->response_size) / + sizeof(struct svid_mode_info); if (disc->svid_cnt > max_resp_svids) { CPRINTS("Warn: SVIDS exceeded HC response"); @@ -73,7 +76,7 @@ static enum ec_status hc_typec_discovery(struct host_cmd_handler_args *args) for (svid_i = 0; svid_i < r->svid_count; svid_i++) { r->svids[svid_i].svid = disc->svids[svid_i].svid; r->svids[svid_i].mode_count = - disc->svids[svid_i].mode_cnt; + disc->svids[svid_i].mode_cnt; memcpy(r->svids[svid_i].mode_vdo, disc->svids[svid_i].mode_vdo, sizeof(r->svids[svid_i].mode_vdo)); @@ -88,18 +91,29 @@ static enum ec_status hc_typec_discovery(struct host_cmd_handler_args *args) * of the copy. If the data was accessed, return BUSY so the AP will * try retrieving again and get the updated data. */ - if (!pd_discovery_access_validate(p->port, type)) + if (!pd_discovery_access_validate(p->port, type)) { + CPRINTS("[C%d] %s returns EC_RES_BUSY!!", p->port, __func__); return EC_RES_BUSY; + } return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_TYPEC_DISCOVERY, - hc_typec_discovery, +DECLARE_HOST_COMMAND(EC_CMD_TYPEC_DISCOVERY, hc_typec_discovery, EC_VER_MASK(0)); +/* Default to feature unavailable, with boards supporting it overriding */ +__overridable enum ec_status +board_set_tbt_ufp_reply(int port, enum typec_tbt_ufp_reply reply) +{ + return EC_RES_UNAVAILABLE; +} + static enum ec_status hc_typec_control(struct host_cmd_handler_args *args) { const struct ec_params_typec_control *p = args->params; + mux_state_t mode; + uint32_t data[VDO_MAX_SIZE]; + enum tcpci_msg_type tx_type; if (p->port >= board_get_usb_pd_port_count()) return EC_RES_INVALID_PARAM; @@ -111,49 +125,163 @@ static enum ec_status hc_typec_control(struct host_cmd_handler_args *args) case TYPEC_CONTROL_COMMAND_CLEAR_EVENTS: pd_clear_events(p->port, p->clear_events_mask); break; + case TYPEC_CONTROL_COMMAND_ENTER_MODE: + return pd_request_enter_mode(p->port, p->mode_to_enter); + case TYPEC_CONTROL_COMMAND_TBT_UFP_REPLY: + return board_set_tbt_ufp_reply(p->port, p->tbt_ufp_reply); + case TYPEC_CONTROL_COMMAND_USB_MUX_SET: + /* The EC will fill in polarity, so filter flip out */ + mode = p->mux_params.mux_flags & ~USB_PD_MUX_POLARITY_INVERTED; + + if (!IS_ENABLED(CONFIG_USB_MUX_AP_CONTROL)) + return EC_RES_INVALID_PARAM; + + usb_mux_set_single(p->port, p->mux_params.mux_index, mode, + USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(p->port))); + return EC_RES_SUCCESS; + case TYPEC_CONTROL_COMMAND_BIST_SHARE_MODE: + return pd_set_bist_share_mode(p->bist_share_mode); + case TYPEC_CONTROL_COMMAND_SEND_VDM_REQ: + if (!IS_ENABLED(CONFIG_USB_PD_VDM_AP_CONTROL)) + return EC_RES_INVALID_PARAM; + + if (p->vdm_req_params.vdm_data_objects <= 0 || + p->vdm_req_params.vdm_data_objects > VDO_MAX_SIZE) + return EC_RES_INVALID_PARAM; + + memcpy(data, p->vdm_req_params.vdm_data, + sizeof(uint32_t) * p->vdm_req_params.vdm_data_objects); + + switch (p->vdm_req_params.partner_type) { + case TYPEC_PARTNER_SOP: + tx_type = TCPCI_MSG_SOP; + break; + case TYPEC_PARTNER_SOP_PRIME: + tx_type = TCPCI_MSG_SOP_PRIME; + break; + case TYPEC_PARTNER_SOP_PRIME_PRIME: + tx_type = TCPCI_MSG_SOP_PRIME_PRIME; + break; + default: + return EC_RES_INVALID_PARAM; + } + + return pd_request_vdm(p->port, data, + p->vdm_req_params.vdm_data_objects, + tx_type); default: return EC_RES_INVALID_PARAM; } - return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_TYPEC_CONTROL, hc_typec_control, EC_VER_MASK(0)); +/* + * Validate ec_response_typec_status_v0's binary compatibility with + * ec_response_typec_status, which is being deprecated. + */ +BUILD_ASSERT(offsetof(struct ec_response_typec_status_v0, + typec_status.sop_prime_revision) == + offsetof(struct ec_response_typec_status, sop_prime_revision)); +BUILD_ASSERT(offsetof(struct ec_response_typec_status_v0, source_cap_pdos) == + offsetof(struct ec_response_typec_status, source_cap_pdos)); +BUILD_ASSERT(sizeof(struct ec_response_typec_status_v0) == + sizeof(struct ec_response_typec_status)); + +/* + * Validate ec_response_typec_status_v0's binary compatibility with + * ec_response_typec_status_v1 with respect to typec_status. + */ +BUILD_ASSERT(offsetof(struct ec_response_typec_status_v0, + typec_status.pd_enabled) == + offsetof(struct ec_response_typec_status_v1, + typec_status.pd_enabled)); +BUILD_ASSERT(offsetof(struct ec_response_typec_status_v0, + typec_status.sop_prime_revision) == + offsetof(struct ec_response_typec_status_v1, + typec_status.sop_prime_revision)); + static enum ec_status hc_typec_status(struct host_cmd_handler_args *args) { const struct ec_params_typec_status *p = args->params; - struct ec_response_typec_status *r = args->response; + struct ec_response_typec_status_v1 *r1 = args->response; + struct ec_response_typec_status_v0 *r0 = args->response; + struct cros_ec_typec_status *cs = &r1->typec_status; const char *tc_state_name; if (p->port >= board_get_usb_pd_port_count()) return EC_RES_INVALID_PARAM; - if (args->response_max < sizeof(*r)) - return EC_RES_RESPONSE_TOO_BIG; + args->response_size = args->version == 0 ? sizeof(*r0) : sizeof(*r1); - args->response_size = sizeof(*r); + if (args->response_max < args->response_size) + return EC_RES_RESPONSE_TOO_BIG; - r->pd_enabled = pd_comm_is_enabled(p->port); - r->dev_connected = pd_is_connected(p->port); - r->sop_connected = pd_capable(p->port); + cs->pd_enabled = pd_comm_is_enabled(p->port); + cs->dev_connected = pd_is_connected(p->port); + cs->sop_connected = pd_capable(p->port); - r->power_role = pd_get_power_role(p->port); - r->data_role = pd_get_data_role(p->port); - r->vconn_role = pd_get_vconn_state(p->port) ? PD_ROLE_VCONN_SRC : - PD_ROLE_VCONN_OFF; - r->polarity = pd_get_polarity(p->port); - r->cc_state = pd_get_task_cc_state(p->port); - r->dp_pin = get_dp_pin_mode(p->port); - r->mux_state = usb_mux_get(p->port); + cs->power_role = pd_get_power_role(p->port); + cs->data_role = pd_get_data_role(p->port); + cs->vconn_role = pd_get_vconn_state(p->port) ? PD_ROLE_VCONN_SRC : + PD_ROLE_VCONN_OFF; + cs->polarity = pd_get_polarity(p->port); + cs->cc_state = pd_get_task_cc_state(p->port); + cs->dp_pin = get_dp_pin_mode(p->port); + cs->mux_state = usb_mux_get(p->port); tc_state_name = pd_get_task_state_name(p->port); - strzcpy(r->tc_state, tc_state_name, sizeof(r->tc_state)); - - r->events = pd_get_events(p->port); + strzcpy(cs->tc_state, tc_state_name, sizeof(cs->tc_state)); + + cs->events = pd_get_events(p->port); + + if (pd_get_partner_rmdo(p->port).major_rev != 0) { + cs->sop_revision = + PD_STATUS_RMDO_REV_SET_MAJOR( + pd_get_partner_rmdo(p->port).major_rev) | + PD_STATUS_RMDO_REV_SET_MINOR( + pd_get_partner_rmdo(p->port).minor_rev) | + PD_STATUS_RMDO_VER_SET_MAJOR( + pd_get_partner_rmdo(p->port).major_ver) | + PD_STATUS_RMDO_VER_SET_MINOR( + pd_get_partner_rmdo(p->port).minor_ver); + } else if (cs->sop_connected) { + cs->sop_revision = PD_STATUS_REV_SET_MAJOR( + pd_get_rev(p->port, TCPCI_MSG_SOP)); + } else { + cs->sop_revision = 0; + } - /* TODO(b/167700356): Add revisions and source cap PDOs */ + cs->sop_prime_revision = + pd_get_identity_discovery(p->port, TCPCI_MSG_SOP_PRIME) == + PD_DISC_COMPLETE ? + PD_STATUS_REV_SET_MAJOR( + pd_get_rev(p->port, TCPCI_MSG_SOP_PRIME)) : + 0; + + if (args->version == 0) { + cs->source_cap_count = MIN(pd_get_src_cap_cnt(p->port), + ARRAY_SIZE(r0->source_cap_pdos)); + memcpy(r0->source_cap_pdos, pd_get_src_caps(p->port), + cs->source_cap_count * sizeof(uint32_t)); + cs->sink_cap_count = MIN(pd_get_snk_cap_cnt(p->port), + ARRAY_SIZE(r0->sink_cap_pdos)); + memcpy(r0->sink_cap_pdos, pd_get_snk_caps(p->port), + cs->sink_cap_count * sizeof(uint32_t)); + } else { + cs->source_cap_count = MIN(pd_get_src_cap_cnt(p->port), + ARRAY_SIZE(r1->source_cap_pdos)); + memcpy(r1->source_cap_pdos, pd_get_src_caps(p->port), + cs->source_cap_count * sizeof(uint32_t)); + cs->sink_cap_count = MIN(pd_get_snk_cap_cnt(p->port), + ARRAY_SIZE(r1->sink_cap_pdos)); + memcpy(r1->sink_cap_pdos, pd_get_snk_caps(p->port), + cs->sink_cap_count * sizeof(uint32_t)); + } return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_TYPEC_STATUS, hc_typec_status, EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_TYPEC_STATUS, hc_typec_status, + EC_VER_MASK(0) | EC_VER_MASK(1)); diff --git a/common/usbc/usb_pd_timer.c b/common/usbc/usb_pd_timer.c new file mode 100644 index 0000000000..a6ec07125d --- /dev/null +++ b/common/usbc/usb_pd_timer.c @@ -0,0 +1,282 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "assert.h" +#include "atomic.h" +#include "atomic_bit.h" +#include "common.h" +#include "console.h" +#include "limits.h" +#include "math_util.h" +#include "system.h" +#include "usb_pd_timer.h" +#include "usb_tc_sm.h" + +#define MAX_PD_PORTS CONFIG_USB_PD_PORT_MAX_COUNT +#define MAX_PD_TIMERS PD_TIMER_COUNT +#define PD_TIMERS_ALL_MASK (UINT64_MAX >> (64 - PD_TIMER_COUNT)) + +#define MAX_EXPIRE (0x7FFFFFFF) +#define NO_TIMEOUT (-1) +#define EXPIRE_NOW (0) + +#define PD_SET_ACTIVE(p, bit) \ + atomic_set_bit(timer_active, (p)*PD_TIMER_COUNT + (bit)) + +#define PD_CLR_ACTIVE(p, bit) \ + atomic_clear_bit(timer_active, (p)*PD_TIMER_COUNT + (bit)) + +#define PD_CHK_ACTIVE(p, bit) \ + atomic_test_bit(timer_active, (p)*PD_TIMER_COUNT + (bit)) + +#define PD_SET_DISABLED(p, bit) \ + atomic_set_bit(timer_disabled, (p)*PD_TIMER_COUNT + (bit)) + +#define PD_CLR_DISABLED(p, bit) \ + atomic_clear_bit(timer_disabled, (p)*PD_TIMER_COUNT + (bit)) + +#define PD_CHK_DISABLED(p, bit) \ + atomic_test_bit(timer_disabled, (p)*PD_TIMER_COUNT + (bit)) + +test_mockable_static ATOMIC_DEFINE(timer_active, PD_TIMER_COUNT *MAX_PD_PORTS); +test_mockable_static ATOMIC_DEFINE(timer_disabled, + PD_TIMER_COUNT *MAX_PD_PORTS); +static uint64_t timer_expires[MAX_PD_PORTS][PD_TIMER_COUNT]; + +/* + * CONFIG_CMD_PD_TIMER debug variables + */ +static int count[MAX_PD_PORTS]; +static int max_count[MAX_PD_PORTS]; + +__maybe_unused static __const_data const char *const pd_timer_names[] = { + [DPM_TIMER_PD_BUTTON_LONG_PRESS] = "DPM-PD_BUTTON_LONG_PRESS", + [DPM_TIMER_PD_BUTTON_SHORT_PRESS] = "DPM-PD_BUTTON_SHORT_PRESS", + [PE_TIMER_BIST_CONT_MODE] = "PE-BIST_CONT_MODE", + [PE_TIMER_CHUNKING_NOT_SUPPORTED] = "PE-CHUNKING_NOT_SUPPORTED", + [PE_TIMER_DISCOVER_IDENTITY] = "PE-DISCOVER_IDENTITY", + [PE_TIMER_NO_RESPONSE] = "PE-NO_RESPONSE", + [PE_TIMER_PR_SWAP_WAIT] = "PE-PR_SWAP_WAIT", + [PE_TIMER_PS_HARD_RESET] = "PE-PS_HARD_RESET", + [PE_TIMER_PS_SOURCE] = "PE-PS_SOURCE", + [PE_TIMER_PS_TRANSITION] = "PE-PS_TRANSITION", + [PE_TIMER_SENDER_RESPONSE] = "PE-SENDER_RESPONSE", + [PE_TIMER_SINK_REQUEST] = "PE-SINK_REQUEST", + [PE_TIMER_SOURCE_CAP] = "PE-SOURCE_CAP", + [PE_TIMER_SRC_TRANSITION] = "PE-SRC_TRANSITION", + [PE_TIMER_SWAP_SOURCE_START] = "PE-SWAP_SOURCE_START", + [PE_TIMER_TIMEOUT] = "PE-TIMEOUT", + [PE_TIMER_VCONN_ON] = "PE-VCONN_ON", + [PE_TIMER_VDM_RESPONSE] = "PE-VDM_RESPONSE", + [PE_TIMER_WAIT_AND_ADD_JITTER] = "PE-WAIT_AND_ADD_JITTER", + [PE_TIMER_VCONN_DISCHARGE] = "PE-VCONN_DISCHARGE", + [PE_TIMER_VCONN_REAPPLIED] = "PE-VCONN_REAPPLIED", + [PE_TIMER_DATA_RESET_FAIL] = "PE-DATA_RESET_FAIL", + + [PR_TIMER_CHUNK_SENDER_REQUEST] = "PR-CHUNK_SENDER_REQUEST", + [PR_TIMER_CHUNK_SENDER_RESPONSE] = "PR-CHUNK_SENDER_RESPONSE", + [PR_TIMER_HARD_RESET_COMPLETE] = "PR-HARD_RESET_COMPLETE", + [PR_TIMER_SINK_TX] = "PR-SINK_TX", + [PR_TIMER_TCPC_TX_TIMEOUT] = "PR-TCPC_TX_TIMEOUT", + [TC_TIMER_CC_DEBOUNCE] = "TC-CC_DEBOUNCE", + [TC_TIMER_LOW_POWER_EXIT_TIME] = "TC-LOW_POWER_EXIT_TIME", + [TC_TIMER_LOW_POWER_TIME] = "TC-LOW_POWER_TIME", + [TC_TIMER_NEXT_ROLE_SWAP] = "TC-NEXT_ROLE_SWAP", + [TC_TIMER_PD_DEBOUNCE] = "TC-PD_DEBOUNCE", + [TC_TIMER_TIMEOUT] = "TC-TIMEOUT", + [TC_TIMER_TRY_WAIT_DEBOUNCE] = "TC-TRY_WAIT_DEBOUNCE", + [TC_TIMER_VBUS_DEBOUNCE] = "TC-VBUS_DEBOUNCE", +}; + +/***************************************************************************** + * PD_TIMER private functions + * + * The view of timers to the outside world is enabled and disabled. Internally + * timers that are enabled are in the active and inactive states. An active + * timer has a valid timeout value that gets checked for expiration and can + * adjust the task wakeup time. An inactive timer is assumed to have expired + * already and will always return that it is still expired. This timer state + * will not adjust the task scheduling timeout value. + */ + +static void pd_timer_inactive(int port, enum pd_task_timer timer) +{ + if (PD_CHK_ACTIVE(port, timer)) { + PD_CLR_ACTIVE(port, timer); + + if (IS_ENABLED(CONFIG_CMD_PD_TIMER)) + count[port]--; + } + PD_CLR_DISABLED(port, timer); +} + +static bool pd_timer_is_active(int port, enum pd_task_timer timer) +{ + return PD_CHK_ACTIVE(port, timer); +} + +static bool pd_timer_is_inactive(int port, enum pd_task_timer timer) +{ + return !PD_CHK_ACTIVE(port, timer) && !PD_CHK_DISABLED(port, timer); +} + +/***************************************************************************** + * PD_TIMER public functions + */ +void pd_timer_init(int port) +{ + if (IS_ENABLED(CONFIG_CMD_PD_TIMER)) + count[port] = 0; + + /* + * Set timers to init state for "port". + */ + for (int bit = 0; bit < PD_TIMER_COUNT; bit++) { + PD_CLR_ACTIVE(port, bit); + PD_SET_DISABLED(port, bit); + } +} + +void pd_timer_enable(int port, enum pd_task_timer timer, uint32_t expires_us) +{ + if (!PD_CHK_ACTIVE(port, timer)) { + PD_SET_ACTIVE(port, timer); + + if (IS_ENABLED(CONFIG_CMD_PD_TIMER)) { + count[port]++; + if (count[port] > max_count[port]) + max_count[port] = count[port]; + } + } + PD_CLR_DISABLED(port, timer); + timer_expires[port][timer] = get_time().val + expires_us; +} + +void pd_timer_disable(int port, enum pd_task_timer timer) +{ + if (PD_CHK_ACTIVE(port, timer)) { + PD_CLR_ACTIVE(port, timer); + + if (IS_ENABLED(CONFIG_CMD_PD_TIMER)) + count[port]--; + } + PD_SET_DISABLED(port, timer); +} + +void pd_timer_disable_range(int port, enum pd_timer_range range) +{ + int start, end; + enum pd_task_timer timer; + + switch (range) { + case DPM_TIMER_RANGE: + start = DPM_TIMER_START; + end = DPM_TIMER_END; + break; + case PE_TIMER_RANGE: + start = PE_TIMER_START; + end = PE_TIMER_END; + break; + case PR_TIMER_RANGE: + start = PR_TIMER_START; + end = PR_TIMER_END; + break; + case TC_TIMER_RANGE: + start = TC_TIMER_START; + end = TC_TIMER_END; + break; + default: + return; + } + + for (timer = start; timer <= end; ++timer) + pd_timer_disable(port, timer); +} + +bool pd_timer_is_disabled(int port, enum pd_task_timer timer) +{ + return PD_CHK_DISABLED(port, timer); +} + +bool pd_timer_is_expired(int port, enum pd_task_timer timer) +{ + if (pd_timer_is_active(port, timer)) { + if (get_time().val >= timer_expires[port][timer]) { + pd_timer_inactive(port, timer); + return true; + } + return false; + } + return pd_timer_is_inactive(port, timer); +} + +void pd_timer_manage_expired(int port) +{ + int timer; + + for (timer = 0; timer < PD_TIMER_COUNT; ++timer) + if (pd_timer_is_active(port, timer) && + pd_timer_is_expired(port, timer)) + pd_timer_inactive(port, timer); +} + +int pd_timer_next_expiration(int port) +{ + int timer; + int ret_value = MAX_EXPIRE; + uint64_t now = get_time().val; + + for (timer = 0; timer < PD_TIMER_COUNT; ++timer) { + /* Only use active timers for the next expired value */ + if (pd_timer_is_active(port, timer)) { + int delta; + uint64_t t_value = timer_expires[port][timer]; + + if (t_value <= now) { + ret_value = EXPIRE_NOW; + break; + } + + delta = t_value - now; + if (ret_value > delta) + ret_value = delta; + } + } + + if (ret_value == MAX_EXPIRE) + ret_value = NO_TIMEOUT; + + return ret_value; +} + +#ifdef CONFIG_CMD_PD_TIMER +test_mockable_static void pd_timer_dump(int port) +{ + int timer; + uint64_t now = get_time().val; + + ccprints("Timers(%d): cur=%d max=%d", port, count[port], + max_count[port]); + + for (timer = 0; timer < PD_TIMER_COUNT; ++timer) { + if (pd_timer_is_disabled(port, timer)) { + continue; + } else if (pd_timer_is_active(port, timer)) { + uint32_t delta = 0; + + if (now < timer_expires[port][timer]) + delta = timer_expires[port][timer] - now; + + ccprints("[%2d] Active: %s (%d%s)", timer, + pd_timer_names[timer], (uint32_t)delta, + tc_event_loop_is_paused(port) ? "-PAUSED" : + ""); + } else { + ccprints("[%2d] Inactive: %s", timer, + pd_timer_names[timer]); + } + } +} +#endif /* CONFIG_CMD_PD_TIMER */ diff --git a/common/usbc/usb_pe_ctvpd_sm.c b/common/usbc/usb_pe_ctvpd_sm.c index ee5c10aca1..223c40c71d 100644 --- a/common/usbc/usb_pe_ctvpd_sm.c +++ b/common/usbc/usb_pe_ctvpd_sm.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,14 +6,14 @@ #include "common.h" #include "console.h" #include "task.h" -#include "util.h" +#include "usb_emsg.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "usb_pe_sm.h" #include "usb_prl_sm.h" -#include "usb_tc_sm.h" -#include "usb_emsg.h" #include "usb_sm.h" +#include "usb_tc_sm.h" +#include "util.h" /* USB Policy Engine Charge-Through VCONN Powered Device module */ @@ -53,6 +53,12 @@ static void pe_init(int port) set_state_pe(port, PE_REQUEST); } +bool pe_in_frs_mode(int port) +{ + /* Will never be in FRS mode */ + return false; +} + bool pe_in_local_ams(int port) { /* We never start a local AMS */ @@ -67,11 +73,11 @@ void pe_run(int port, int evt, int en) case SM_PAUSED: if (!en) break; - /* fall through */ + __fallthrough; case SM_INIT: pe_init(port); local_state[port] = SM_RUN; - /* fall through */ + __fallthrough; case SM_RUN: if (en) run_state(port, &pe[port].ctx); @@ -104,7 +110,7 @@ void pe_got_hard_reset(int port) /* No implementation needed by this policy engine */ } -void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type) +void pe_report_error(int port, enum pe_error e, enum tcpci_msg_type type) { /* No implementation needed by this policy engine */ } @@ -160,53 +166,48 @@ static void pe_request_run(const int port) /* Prepare to send ACK */ /* VDM Header */ - payload[0] = VDO( - USB_VID_GOOGLE, - 1, /* Structured VDM */ - VDO_SVDM_VERS(1) | - VDO_CMDT(CMDT_RSP_ACK) | - CMD_DISCOVER_IDENT); + payload[0] = VDO(USB_VID_GOOGLE, 1, /* Structured VDM */ + VDO_SVDM_VERS(1) | VDO_CMDT(CMDT_RSP_ACK) | + CMD_DISCOVER_IDENT); /* ID Header VDO */ - payload[1] = VDO_IDH( - 0, /* Not a USB Host */ - 1, /* Capable of being enumerated as USB Device */ - IDH_PTYPE_VPD, - 0, /* Modal Operation Not Supported */ - USB_VID_GOOGLE); + payload[1] = VDO_IDH(0, /* Not a USB Host */ + 1, /* Capable of being enumerated as USB + Device */ + IDH_PTYPE_VPD, 0, /* Modal Operation Not + Supported */ + USB_VID_GOOGLE); /* Cert State VDO */ payload[2] = 0; /* Product VDO */ - payload[3] = VDO_PRODUCT( - CONFIG_USB_PID, - USB_BCD_DEVICE); + payload[3] = VDO_PRODUCT(CONFIG_USB_PID, USB_BCD_DEVICE); /* VPD VDO */ payload[4] = VDO_VPD( - VPD_HW_VERSION, - VPD_FW_VERSION, - VPD_MAX_VBUS_20V, - VPD_VBUS_IMP(VPD_VBUS_IMPEDANCE), - VPD_GND_IMP(VPD_GND_IMPEDANCE), -#ifdef CONFIG_USB_CTVPD - VPD_CTS_SUPPORTED -#else - VPD_CTS_NOT_SUPPORTED -#endif - ); + VPD_HW_VERSION, VPD_FW_VERSION, VPD_MAX_VBUS_20V, + IS_ENABLED(CONFIG_USB_CTVPD) ? VPD_CT_CURRENT : 0, + IS_ENABLED(CONFIG_USB_CTVPD) ? + VPD_VBUS_IMP(VPD_VBUS_IMPEDANCE) : + 0, + IS_ENABLED(CONFIG_USB_CTVPD) ? + VPD_GND_IMP(VPD_GND_IMPEDANCE) : + 0, + IS_ENABLED(CONFIG_USB_CTVPD) ? VPD_CTS_SUPPORTED : + VPD_CTS_NOT_SUPPORTED); /* 20 bytes, 5 data objects */ tx_emsg[port].len = 20; /* Set to highest revision supported by both ports. */ - prl_set_rev(port, TCPC_TX_SOP_PRIME, - (PD_HEADER_REV(header) > PD_REV30) ? - PD_REV30 : PD_HEADER_REV(header)); + prl_set_rev(port, TCPCI_MSG_SOP_PRIME, + (PD_HEADER_REV(header) > PD_REV30) ? + PD_REV30 : + PD_HEADER_REV(header)); /* Send the ACK */ - prl_send_data_msg(port, TCPC_TX_SOP_PRIME, - PD_DATA_VENDOR_DEF); + prl_send_data_msg(port, TCPCI_MSG_SOP_PRIME, + PD_DATA_VENDOR_DEF); } } diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index 19fb59d0a2..dba06dfbfb 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,29 +6,40 @@ #include "atomic.h" #include "battery.h" #include "battery_smart.h" +#include "builtin/assert.h" #include "charge_manager.h" #include "charge_state.h" #include "common.h" #include "console.h" +#include "dps.h" +#include "driver/tcpm/tcpm.h" +#include "ec_commands.h" #include "hooks.h" #include "host_command.h" +#include "power_button.h" #include "stdbool.h" +#include "system.h" #include "task.h" -#include "tcpm.h" -#include "util.h" +#include "tcpm/tcpm.h" +#include "usb_charge.h" #include "usb_common.h" #include "usb_dp_alt_mode.h" +#include "usb_emsg.h" #include "usb_mode.h" -#include "usb_pd_dpm.h" +#include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_dpm_sm.h" +#include "usb_pd_policy.h" #include "usb_pd_tcpm.h" +#include "usb_pd_timer.h" +#include "usb_pe_private.h" #include "usb_pe_sm.h" -#include "usb_tbt_alt_mode.h" #include "usb_prl_sm.h" -#include "usb_tc_sm.h" -#include "usb_emsg.h" #include "usb_sm.h" +#include "usb_tbt_alt_mode.h" +#include "usb_tc_sm.h" #include "usbc_ppc.h" +#include "util.h" /* * USB Policy Engine Sink / Source module @@ -38,123 +49,64 @@ */ #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else #define CPRINTF(format, args...) #define CPRINTS(format, args...) #endif -#define CPRINTF_LX(x, format, args...) \ - do { \ - if (pe_debug_level >= x) \ - CPRINTF(format, ## args); \ +#define CPRINTF_LX(x, format, args...) \ + do { \ + if (pe_debug_level >= x) \ + CPRINTF(format, ##args); \ } while (0) -#define CPRINTF_L1(format, args...) CPRINTF_LX(1, format, ## args) -#define CPRINTF_L2(format, args...) CPRINTF_LX(2, format, ## args) -#define CPRINTF_L3(format, args...) CPRINTF_LX(3, format, ## args) - -#define CPRINTS_LX(x, format, args...) \ - do { \ - if (pe_debug_level >= x) \ - CPRINTS(format, ## args); \ +#define CPRINTF_L1(format, args...) CPRINTF_LX(1, format, ##args) +#define CPRINTF_L2(format, args...) CPRINTF_LX(2, format, ##args) +#define CPRINTF_L3(format, args...) CPRINTF_LX(3, format, ##args) + +#define CPRINTS_LX(x, format, args...) \ + do { \ + if (pe_debug_level >= x) \ + CPRINTS(format, ##args); \ } while (0) -#define CPRINTS_L1(format, args...) CPRINTS_LX(1, format, ## args) -#define CPRINTS_L2(format, args...) CPRINTS_LX(2, format, ## args) -#define CPRINTS_L3(format, args...) CPRINTS_LX(3, format, ## args) +#define CPRINTS_L1(format, args...) CPRINTS_LX(1, format, ##args) +#define CPRINTS_L2(format, args...) CPRINTS_LX(2, format, ##args) +#define CPRINTS_L3(format, args...) CPRINTS_LX(3, format, ##args) + +#define PE_SET_FN(port, _fn) \ + atomic_or(ATOMIC_ELEM(pe[port].flags_a, (_fn)), ATOMIC_MASK(_fn)) +#define PE_CLR_FN(port, _fn) \ + atomic_clear_bits(ATOMIC_ELEM(pe[port].flags_a, (_fn)), \ + ATOMIC_MASK(_fn)) +#define PE_CHK_FN(port, _fn) \ + (pe[port].flags_a[ATOMIC_ELEM(0, (_fn))] & ATOMIC_MASK(_fn)) + +#define PE_SET_FLAG(port, name) PE_SET_FN(port, (name##_FN)) +#define PE_CLR_FLAG(port, name) PE_CLR_FN(port, (name##_FN)) +#define PE_CHK_FLAG(port, name) PE_CHK_FN(port, (name##_FN)) - -#define PE_SET_FLAG(port, flag) deprecated_atomic_or(&pe[port].flags, (flag)) -#define PE_CLR_FLAG(port, flag) \ - deprecated_atomic_clear_bits(&pe[port].flags, (flag)) -#define PE_CHK_FLAG(port, flag) (pe[port].flags & (flag)) +/* + * TODO(b/229655319): support more than 32 bits + */ +#define PE_SET_MASK(port, mask) atomic_or(&pe[port].flags_a[0], (mask)) +#define PE_CLR_MASK(port, mask) atomic_clear_bits(&pe[port].flags_a[0], (mask)) /* * These macros SET, CLEAR, and CHECK, a DPM (Device Policy Manager) * Request. The Requests are listed in usb_pe_sm.h. */ -#define PE_SET_DPM_REQUEST(port, req) \ - deprecated_atomic_or(&pe[port].dpm_request, (req)) +#define PE_SET_DPM_REQUEST(port, req) atomic_or(&pe[port].dpm_request, (req)) #define PE_CLR_DPM_REQUEST(port, req) \ - deprecated_atomic_clear_bits(&pe[port].dpm_request, (req)) + atomic_clear_bits(&pe[port].dpm_request, (req)) #define PE_CHK_DPM_REQUEST(port, req) (pe[port].dpm_request & (req)) -/* - * Policy Engine Layer Flags - * These are reproduced in test/usb_pe.h. If they change here, they must change - * there. - */ - -/* At least one successful PD communication packet received from port partner */ -#define PE_FLAGS_PD_CONNECTION BIT(0) -/* Accept message received from port partner */ -#define PE_FLAGS_ACCEPT BIT(1) -/* Power Supply Ready message received from port partner */ -#define PE_FLAGS_PS_READY BIT(2) -/* Protocol Error was determined based on error recovery current state */ -#define PE_FLAGS_PROTOCOL_ERROR BIT(3) -/* Set if we are in Modal Operation */ -#define PE_FLAGS_MODAL_OPERATION BIT(4) -/* A message we requested to be sent has been transmitted */ -#define PE_FLAGS_TX_COMPLETE BIT(5) -/* A message sent by a port partner has been received */ -#define PE_FLAGS_MSG_RECEIVED BIT(6) -/* A hard reset has been requested but has not been sent, not currently used */ -#define PE_FLAGS_HARD_RESET_PENDING BIT(7) -/* Port partner sent a Wait message. Wait before we resend our message */ -#define PE_FLAGS_WAIT BIT(8) -/* An explicit contract is in place with our port partner */ -#define PE_FLAGS_EXPLICIT_CONTRACT BIT(9) -/* Waiting for Sink Capabailities timed out. Used for retry error handling */ -#define PE_FLAGS_SNK_WAIT_CAP_TIMEOUT BIT(10) -/* Power Supply voltage/current transition timed out */ -#define PE_FLAGS_PS_TRANSITION_TIMEOUT BIT(11) -/* Flag to note current Atomic Message Sequence is interruptible */ -#define PE_FLAGS_INTERRUPTIBLE_AMS BIT(12) -/* Flag to note Power Supply reset has completed */ -#define PE_FLAGS_PS_RESET_COMPLETE BIT(13) -/* VCONN swap operation has completed */ -#define PE_FLAGS_VCONN_SWAP_COMPLETE BIT(14) -/* Flag to note no more setup VDMs (discovery, etc.) should be sent */ -#define PE_FLAGS_VDM_SETUP_DONE BIT(15) -/* Flag to note PR Swap just completed for Startup entry */ -#define PE_FLAGS_PR_SWAP_COMPLETE BIT(16) -/* Flag to note Port Discovery port partner replied with BUSY */ -#define PE_FLAGS_VDM_REQUEST_BUSY BIT(17) -/* Flag to note Port Discovery port partner replied with NAK */ -#define PE_FLAGS_VDM_REQUEST_NAKED BIT(18) -/* Flag to note FRS/PRS context in shared state machine path */ -#define PE_FLAGS_FAST_ROLE_SWAP_PATH BIT(19) -/* Flag to note if FRS listening is enabled */ -#define PE_FLAGS_FAST_ROLE_SWAP_ENABLED BIT(20) -/* Flag to note TCPC passed on FRS signal from port partner */ -#define PE_FLAGS_FAST_ROLE_SWAP_SIGNALED BIT(21) -/* TODO: POLICY decision: Triggers a DR SWAP attempt from UFP to DFP */ -#define PE_FLAGS_DR_SWAP_TO_DFP BIT(22) -/* - * TODO: POLICY decision - * Flag to trigger a message resend after receiving a WAIT from port partner - */ -#define PE_FLAGS_WAITING_PR_SWAP BIT(23) -/* FLAG to track if port partner is dualrole capable */ -#define PE_FLAGS_PORT_PARTNER_IS_DUALROLE BIT(24) -/* FLAG is set when an AMS is initiated locally. ie. AP requested a PR_SWAP */ -#define PE_FLAGS_LOCALLY_INITIATED_AMS BIT(25) -/* Flag to note the first message sent in PE_SRC_READY and PE_SNK_READY */ -#define PE_FLAGS_FIRST_MSG BIT(26) -/* Flag to continue a VDM request if it was interrupted */ -#define PE_FLAGS_VDM_REQUEST_CONTINUE BIT(27) -/* TODO: POLICY decision: Triggers a Vconn SWAP attempt to on */ -#define PE_FLAGS_VCONN_SWAP_TO_ON BIT(28) -/* FLAG to track that VDM request to port partner timed out */ -#define PE_FLAGS_VDM_REQUEST_TIMEOUT BIT(29) -/* FLAG to note message was discarded due to incoming message */ -#define PE_FLAGS_MSG_DISCARDED BIT(30) - /* Message flags which should not persist on returning to ready state */ -#define PE_FLAGS_READY_CLR (PE_FLAGS_LOCALLY_INITIATED_AMS \ - | PE_FLAGS_MSG_DISCARDED \ - | PE_FLAGS_VDM_REQUEST_TIMEOUT) +#define PE_MASK_READY_CLR \ + (BIT(PE_FLAGS_LOCALLY_INITIATED_AMS_FN) | \ + BIT(PE_FLAGS_MSG_DISCARDED_FN) | \ + BIT(PE_FLAGS_VDM_REQUEST_TIMEOUT_FN) | \ + BIT(PE_FLAGS_INTERRUPTIBLE_AMS_FN)) /* * Combination to check whether a reply to a message was received. Our message @@ -165,9 +117,9 @@ * on the same run cycle. With chunking, received message will take an * additional cycle to be flagged. */ -#define PE_CHK_REPLY(port) (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED) && \ - !PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) - +#define PE_CHK_REPLY(port) \ + (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED) && \ + !PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) /* 6.7.3 Hard Reset Counter */ #define N_HARD_RESET_COUNT 2 @@ -184,13 +136,25 @@ #define N_DISCOVER_IDENTITY_COUNT 6 /* - * tDiscoverIdentity is only defined while an explicit contract is in place. - * To support captive cable devices that power the SOP' responder from VBUS - * instead of VCONN stretch out the SOP' Discover Identity messages when - * no contract is present. 200 ms provides about 1 second for the cable - * to power up (200 * 5 retries). + * It is permitted to send SOP' Discover Identity messages before a PD contract + * is in place. However, this is only beneficial if the cable powers up quickly + * solely from VCONN. Limit the number of retries without a contract to + * ensure we attempt some cable discovery after a contract is in place. + */ +#define N_DISCOVER_IDENTITY_PRECONTRACT_LIMIT 2 + +/* + * Once this limit of SOP' Discover Identity messages has been set, downgrade + * to PD 2.0 in case the cable is non-compliant about GoodCRC-ing higher + * revisions. This limit should be higher than the precontract limit. + */ +#define N_DISCOVER_IDENTITY_PD3_0_LIMIT 4 + +/* + * tDiscoverIdentity is only defined while an explicit contract is in place, so + * extend the interval between retries pre-contract. */ -#define PE_T_DISCOVER_IDENTITY_NO_CONTRACT (200*MSEC) +#define PE_T_DISCOVER_IDENTITY_NO_CONTRACT (200 * MSEC) /* * Only VCONN source can communicate with the cable plug. Hence, try VCONN swap @@ -221,12 +185,13 @@ /* * The time that we allow the port partner to send any messages after an - * explicit contract is established. 400ms was chosen somewhat arbitrarily as + * explicit contract is established. 200ms was chosen somewhat arbitrarily as * it should be long enough for sources to decide to send a message if they were * going to, but not so long that a "low power charger connected" notification - * would be shown in the chrome OS UI. + * would be shown in the chrome OS UI. Setting t0o large a delay can cause + * problems if the PD discovery time exceeds 1s (tAMETimeout) */ -#define SRC_SNK_READY_HOLD_OFF_US (400 * MSEC) +#define SRC_SNK_READY_HOLD_OFF_US (200 * MSEC) /* * Function pointer to a Structured Vendor Defined Message (SVDM) response @@ -237,77 +202,98 @@ typedef int (*svdm_rsp_func)(int port, uint32_t *payload); /* List of all Policy Engine level states */ enum usb_pe_state { /* Super States */ - PE_PRS_FRS_SHARED, - PE_VDM_SEND_REQUEST, + PE_PRS_FRS_SHARED, /* pe-st0 */ + PE_VDM_SEND_REQUEST, /* pe-st1 */ /* Normal States */ - PE_SRC_STARTUP, - PE_SRC_DISCOVERY, - PE_SRC_SEND_CAPABILITIES, - PE_SRC_NEGOTIATE_CAPABILITY, - PE_SRC_TRANSITION_SUPPLY, - PE_SRC_READY, - PE_SRC_DISABLED, - PE_SRC_CAPABILITY_RESPONSE, - PE_SRC_HARD_RESET, - PE_SRC_HARD_RESET_RECEIVED, - PE_SRC_TRANSITION_TO_DEFAULT, - PE_SNK_STARTUP, - PE_SNK_DISCOVERY, - PE_SNK_WAIT_FOR_CAPABILITIES, - PE_SNK_EVALUATE_CAPABILITY, - PE_SNK_SELECT_CAPABILITY, - PE_SNK_READY, - PE_SNK_HARD_RESET, - PE_SNK_TRANSITION_TO_DEFAULT, - PE_SNK_GIVE_SINK_CAP, - PE_SNK_GET_SOURCE_CAP, - PE_SNK_TRANSITION_SINK, - PE_SEND_SOFT_RESET, - PE_SOFT_RESET, - PE_SEND_NOT_SUPPORTED, - PE_SRC_PING, - PE_DRS_EVALUATE_SWAP, - PE_DRS_CHANGE, - PE_DRS_SEND_SWAP, - PE_PRS_SRC_SNK_EVALUATE_SWAP, - PE_PRS_SRC_SNK_TRANSITION_TO_OFF, - PE_PRS_SRC_SNK_ASSERT_RD, - PE_PRS_SRC_SNK_WAIT_SOURCE_ON, - PE_PRS_SRC_SNK_SEND_SWAP, - PE_PRS_SNK_SRC_EVALUATE_SWAP, - PE_PRS_SNK_SRC_TRANSITION_TO_OFF, - PE_PRS_SNK_SRC_ASSERT_RP, - PE_PRS_SNK_SRC_SOURCE_ON, - PE_PRS_SNK_SRC_SEND_SWAP, - PE_VCS_EVALUATE_SWAP, - PE_VCS_SEND_SWAP, - PE_VCS_WAIT_FOR_VCONN_SWAP, - PE_VCS_TURN_ON_VCONN_SWAP, - PE_VCS_TURN_OFF_VCONN_SWAP, - PE_VCS_SEND_PS_RDY_SWAP, - PE_VDM_IDENTITY_REQUEST_CBL, - PE_INIT_PORT_VDM_IDENTITY_REQUEST, - PE_INIT_VDM_SVIDS_REQUEST, - PE_INIT_VDM_MODES_REQUEST, - PE_VDM_REQUEST_DPM, - PE_VDM_RESPONSE, - PE_HANDLE_CUSTOM_VDM_REQUEST, - PE_WAIT_FOR_ERROR_RECOVERY, - PE_BIST_TX, - PE_BIST_RX, - PE_DEU_SEND_ENTER_USB, - PE_DR_SNK_GET_SINK_CAP, - PE_DR_SNK_GIVE_SOURCE_CAP, - PE_DR_SRC_GET_SOURCE_CAP, + PE_SRC_STARTUP, /* pe-st2 */ + PE_SRC_DISCOVERY, /* pe-st3 */ + PE_SRC_SEND_CAPABILITIES, /* pe-st4 */ + PE_SRC_NEGOTIATE_CAPABILITY, /* pe-st5 */ + PE_SRC_TRANSITION_SUPPLY, /* pe-st6 */ + PE_SRC_READY, /* pe-st7 */ + PE_SRC_DISABLED, /* pe-st8 */ + PE_SRC_CAPABILITY_RESPONSE, /* pe-st9 */ + PE_SRC_HARD_RESET, /* pe-st10 */ + PE_SRC_HARD_RESET_RECEIVED, /* pe-st11 */ + PE_SRC_TRANSITION_TO_DEFAULT, /* pe-st12 */ + PE_SNK_STARTUP, /* pe-st13 */ + PE_SNK_DISCOVERY, /* pe-st14 */ + PE_SNK_WAIT_FOR_CAPABILITIES, /* pe-st15 */ + PE_SNK_EVALUATE_CAPABILITY, /* pe-st16 */ + PE_SNK_SELECT_CAPABILITY, /* pe-st17 */ + PE_SNK_READY, /* pe-st18 */ + PE_SNK_HARD_RESET, /* pe-st19 */ + PE_SNK_TRANSITION_TO_DEFAULT, /* pe-st20 */ + PE_SNK_GIVE_SINK_CAP, /* pe-st21 */ + PE_SNK_GET_SOURCE_CAP, /* pe-st22 */ + PE_SNK_TRANSITION_SINK, /* pe-st23 */ + PE_SEND_SOFT_RESET, /* pe-st24 */ + PE_SOFT_RESET, /* pe-st25 */ + PE_SEND_NOT_SUPPORTED, /* pe-st26 */ + PE_SRC_PING, /* pe-st27 */ + PE_DRS_EVALUATE_SWAP, /* pe-st28 */ + PE_DRS_CHANGE, /* pe-st29 */ + PE_DRS_SEND_SWAP, /* pe-st30 */ + PE_PRS_SRC_SNK_EVALUATE_SWAP, /* pe-st31 */ + PE_PRS_SRC_SNK_TRANSITION_TO_OFF, /* pe-st32 */ + PE_PRS_SRC_SNK_ASSERT_RD, /* pe-st33 */ + PE_PRS_SRC_SNK_WAIT_SOURCE_ON, /* pe-st34 */ + PE_PRS_SRC_SNK_SEND_SWAP, /* pe-st35 */ + PE_PRS_SNK_SRC_EVALUATE_SWAP, /* pe-st36 */ + PE_PRS_SNK_SRC_TRANSITION_TO_OFF, /* pe-st37 */ + PE_PRS_SNK_SRC_ASSERT_RP, /* pe-st38 */ + PE_PRS_SNK_SRC_SOURCE_ON, /* pe-st39 */ + PE_PRS_SNK_SRC_SEND_SWAP, /* pe-st40 */ + PE_VCS_EVALUATE_SWAP, /* pe-st41 */ + PE_VCS_SEND_SWAP, /* pe-st42 */ + PE_VCS_WAIT_FOR_VCONN_SWAP, /* pe-st43 */ + PE_VCS_TURN_ON_VCONN_SWAP, /* pe-st44 */ + PE_VCS_TURN_OFF_VCONN_SWAP, /* pe-st45 */ + PE_VCS_SEND_PS_RDY_SWAP, /* pe-st46 */ + PE_VCS_CBL_SEND_SOFT_RESET, /* pe-st47 */ + PE_VDM_IDENTITY_REQUEST_CBL, /* pe-st48 */ + PE_INIT_PORT_VDM_IDENTITY_REQUEST, /* pe-st49 */ + PE_INIT_VDM_SVIDS_REQUEST, /* pe-st50 */ + PE_INIT_VDM_MODES_REQUEST, /* pe-st51 */ + PE_VDM_REQUEST_DPM, /* pe-st52 */ + PE_VDM_RESPONSE, /* pe-st53 */ + PE_WAIT_FOR_ERROR_RECOVERY, /* pe-st54 */ + PE_BIST_TX, /* pe-st55 */ + PE_DEU_SEND_ENTER_USB, /* pe-st56 */ + PE_DR_GET_SINK_CAP, /* pe-st57 */ + PE_DR_SNK_GIVE_SOURCE_CAP, /* pe-st58 */ + PE_DR_SRC_GET_SOURCE_CAP, /* pe-st59 */ /* PD3.0 only states below here*/ - PE_FRS_SNK_SRC_START_AMS, - PE_GIVE_BATTERY_CAP, - PE_GIVE_BATTERY_STATUS, - PE_SEND_ALERT, - PE_SRC_CHUNK_RECEIVED, - PE_SNK_CHUNK_RECEIVED, + /* UFP Data Reset States */ + PE_UDR_SEND_DATA_RESET, /* pe-st60 */ + PE_UDR_DATA_RESET_RECEIVED, /* pe-st61 */ + PE_UDR_TURN_OFF_VCONN, /* pe-st62 */ + PE_UDR_SEND_PS_RDY, /* pe-st63 */ + PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE, /* pe-st64 */ + /* DFP Data Reset States */ + PE_DDR_SEND_DATA_RESET, /* pe-st65 */ + PE_DDR_DATA_RESET_RECEIVED, /* pe-st66 */ + PE_DDR_WAIT_FOR_VCONN_OFF, /* pe-st67 */ + PE_DDR_PERFORM_DATA_RESET, /* pe-st68 */ + PE_FRS_SNK_SRC_START_AMS, /* pe-st69 */ + PE_GIVE_BATTERY_CAP, /* pe-st70 */ + PE_GIVE_BATTERY_STATUS, /* pe-st71 */ + PE_GIVE_STATUS, /* pe-st72 */ + PE_SEND_ALERT, /* pe-st73 */ + PE_ALERT_RECEIVED, /* pe-st74 */ + PE_SRC_CHUNK_RECEIVED, /* pe-st75 */ + PE_SNK_CHUNK_RECEIVED, /* pe-st76 */ + PE_VCS_FORCE_VCONN, /* pe-st77 */ + PE_GET_REVISION, /* pe-st78 */ + + /* EPR states */ + PE_SNK_SEND_EPR_MODE_ENTRY, + PE_SNK_EPR_MODE_ENTRY_WAIT_FOR_RESPONSE, + PE_SNK_EPR_KEEP_ALIVE, + PE_SNK_SEND_EPR_MODE_EXIT, + PE_SNK_EPR_MODE_EXIT_RECEIVED, }; /* @@ -342,21 +328,18 @@ static const struct usb_state pe_states[]; * If we can't print or the CONFIG_USB_PD_DEBUG_LEVEL is defined to be 0 * then the DEBUG LABELS will be removed from the build. */ -#if defined(CONFIG_COMMON_RUNTIME) && \ - (!defined(CONFIG_USB_PD_DEBUG_LEVEL) || \ - (CONFIG_USB_PD_DEBUG_LEVEL > 0)) +#if defined(CONFIG_COMMON_RUNTIME) && (!defined(CONFIG_USB_PD_DEBUG_LEVEL) || \ + (CONFIG_USB_PD_DEBUG_LEVEL > 0)) #define USB_PD_DEBUG_LABELS #endif -#ifdef USB_PD_DEBUG_LABELS /* List of human readable state names for console debugging */ -static const char * const pe_state_names[] = { - /* Super States */ +__maybe_unused static __const_data const char *const pe_state_names[] = { +/* Super States */ #ifdef CONFIG_USB_PD_REV30 [PE_PRS_FRS_SHARED] = "SS:PE_PRS_FRS_SHARED", #endif [PE_VDM_SEND_REQUEST] = "SS:PE_VDM_Send_Request", - [PE_VDM_RESPONSE] = "SS:PE_VDM_Response", /* Normal States */ [PE_SRC_STARTUP] = "PE_SRC_Startup", @@ -405,44 +388,61 @@ static const char * const pe_state_names[] = { [PE_VCS_TURN_ON_VCONN_SWAP] = "PE_VCS_Turn_On_Vconn_Swap", [PE_VCS_TURN_OFF_VCONN_SWAP] = "PE_VCS_Turn_Off_Vconn_Swap", [PE_VCS_SEND_PS_RDY_SWAP] = "PE_VCS_Send_Ps_Rdy_Swap", + [PE_VCS_CBL_SEND_SOFT_RESET] = "PE_VCS_CBL_Send_Soft_Reset", #endif [PE_VDM_IDENTITY_REQUEST_CBL] = "PE_VDM_Identity_Request_Cbl", [PE_INIT_PORT_VDM_IDENTITY_REQUEST] = - "PE_INIT_PORT_VDM_Identity_Request", + "PE_INIT_PORT_VDM_Identity_Request", [PE_INIT_VDM_SVIDS_REQUEST] = "PE_INIT_VDM_SVIDs_Request", [PE_INIT_VDM_MODES_REQUEST] = "PE_INIT_VDM_Modes_Request", [PE_VDM_REQUEST_DPM] = "PE_VDM_Request_DPM", - [PE_HANDLE_CUSTOM_VDM_REQUEST] = "PE_Handle_Custom_Vdm_Request", + [PE_VDM_RESPONSE] = "PE_VDM_Response", [PE_WAIT_FOR_ERROR_RECOVERY] = "PE_Wait_For_Error_Recovery", [PE_BIST_TX] = "PE_Bist_TX", - [PE_BIST_RX] = "PE_Bist_RX", - [PE_DEU_SEND_ENTER_USB] = "PE_DEU_Send_Enter_USB", -#ifdef CONFIG_USB_PD_FRS - [PE_DR_SNK_GET_SINK_CAP] = "PE_DR_SNK_Get_Sink_Cap", -#endif + [PE_DEU_SEND_ENTER_USB] = "PE_DEU_Send_Enter_USB", + [PE_DR_GET_SINK_CAP] = "PE_DR_Get_Sink_Cap", [PE_DR_SNK_GIVE_SOURCE_CAP] = "PE_DR_SNK_Give_Source_Cap", [PE_DR_SRC_GET_SOURCE_CAP] = "PE_DR_SRC_Get_Source_Cap", - /* PD3.0 only states below here*/ +/* PD3.0 only states below here*/ #ifdef CONFIG_USB_PD_REV30 [PE_FRS_SNK_SRC_START_AMS] = "PE_FRS_SNK_SRC_Start_Ams", + [PE_GET_REVISION] = "PE_Get_Revision", #ifdef CONFIG_USB_PD_EXTENDED_MESSAGES [PE_GIVE_BATTERY_CAP] = "PE_Give_Battery_Cap", [PE_GIVE_BATTERY_STATUS] = "PE_Give_Battery_Status", + [PE_GIVE_STATUS] = "PE_Give_Status", [PE_SEND_ALERT] = "PE_Send_Alert", + [PE_ALERT_RECEIVED] = "PE_Alert_Received", #else [PE_SRC_CHUNK_RECEIVED] = "PE_SRC_Chunk_Received", [PE_SNK_CHUNK_RECEIVED] = "PE_SNK_Chunk_Received", #endif +#ifdef CONFIG_USBC_VCONN + [PE_VCS_FORCE_VCONN] = "PE_VCS_Force_Vconn", +#endif +#ifdef CONFIG_USB_PD_DATA_RESET_MSG + [PE_UDR_SEND_DATA_RESET] = "PE_UDR_Send_Data_Reset", + [PE_UDR_DATA_RESET_RECEIVED] = "PE_UDR_Data_Reset_Received", + [PE_UDR_TURN_OFF_VCONN] = "PE_UDR_Turn_Off_VCONN", + [PE_UDR_SEND_PS_RDY] = "PE_UDR_Send_Ps_Rdy", + [PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE] = + "PE_UDR_Wait_For_Data_Reset_Complete", + [PE_DDR_SEND_DATA_RESET] = "PE_DDR_Send_Data_Reset", + [PE_DDR_DATA_RESET_RECEIVED] = "PE_DDR_Data_Reset_Received", + [PE_DDR_WAIT_FOR_VCONN_OFF] = "PE_DDR_Wait_For_VCONN_Off", + [PE_DDR_PERFORM_DATA_RESET] = "PE_DDR_Perform_Data_Reset", +#endif /* CONFIG_USB_PD_DATA_RESET_MSG */ +#ifdef CONFIG_USB_PD_EPR + [PE_SNK_SEND_EPR_MODE_ENTRY] = "PE_SNK_Send_EPR_Mode_Entry", + [PE_SNK_EPR_MODE_ENTRY_WAIT_FOR_RESPONSE] = + "PE_SNK_EPR_Mode_Entry_Wait_For_Response", + [PE_SNK_EPR_KEEP_ALIVE] = "PE_SNK_EPR_Keep_Alive", + [PE_SNK_SEND_EPR_MODE_EXIT] = "PE_SNK_Send_EPR_Mode_Exit", + [PE_SNK_EPR_MODE_EXIT_RECEIVED] = "PE_SNK_EPR_Mode_Exit_Received", +#endif #endif /* CONFIG_USB_PD_REV30 */ }; -#else -/* - * Here and below, ensure that invalid states don't link properly. This lets us - * use guard code with IS_ENABLED instead of ifdefs and still save flash space. - */ -STATIC_IF(USB_PD_DEBUG_LABELS) const char **pe_state_names; -#endif #ifndef CONFIG_USBC_VCONN GEN_NOT_SUPPORTED(PE_VCS_EVALUATE_SWAP); @@ -468,19 +468,24 @@ GEN_NOT_SUPPORTED(PE_SRC_CHUNK_RECEIVED); #define PE_SRC_CHUNK_RECEIVED PE_SRC_CHUNK_RECEIVED_NOT_SUPPORTED GEN_NOT_SUPPORTED(PE_SNK_CHUNK_RECEIVED); #define PE_SNK_CHUNK_RECEIVED PE_SNK_CHUNK_RECEIVED_NOT_SUPPORTED -void pe_set_frs_enable(int port, int enable); +GEN_NOT_SUPPORTED(PE_GET_REVISION); +#define PE_GET_REVISION PE_GET_REVISION_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_ALERT_RECEIVED); +#define PE_ALERT_RECEIVED PE_ALERT_RECEIVED_NOT_SUPPORTED #endif /* CONFIG_USB_PD_REV30 */ -#ifndef CONFIG_USB_PD_FRS -GEN_NOT_SUPPORTED(PE_DR_SNK_GET_SINK_CAP); -#define PE_DR_SNK_GET_SINK_CAP PE_DR_SNK_GET_SINK_CAP_NOT_SUPPORTED -#endif /* CONFIG_USB_PD_FRS */ +#if !defined(CONFIG_USBC_VCONN) || !defined(CONFIG_USB_PD_REV30) +GEN_NOT_SUPPORTED(PE_VCS_FORCE_VCONN); +#define PE_VCS_FORCE_VCONN PE_VCS_FORCE_VCONN_NOT_SUPPORTED +#endif #ifndef CONFIG_USB_PD_EXTENDED_MESSAGES GEN_NOT_SUPPORTED(PE_GIVE_BATTERY_CAP); #define PE_GIVE_BATTERY_CAP PE_GIVE_BATTERY_CAP_NOT_SUPPORTED GEN_NOT_SUPPORTED(PE_GIVE_BATTERY_STATUS); #define PE_GIVE_BATTERY_STATUS PE_GIVE_BATTERY_STATUS_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_GIVE_STATUS); +#define PE_GIVE_STATUS PE_GIVE_STATUS_NOT_SUPPORTED GEN_NOT_SUPPORTED(PE_SEND_ALERT); #define PE_SEND_ALERT PE_SEND_ALERT_NOT_SUPPORTED #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ @@ -492,15 +497,27 @@ GEN_NOT_SUPPORTED(PE_SNK_CHUNK_RECEIVED); #define PE_SNK_CHUNK_RECEIVED PE_SNK_CHUNK_RECEIVED_NOT_SUPPORTED #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ -/* - * This enum is used to implement a state machine consisting of at most - * 3 states, inside a Policy Engine State. - */ -enum sub_state { - PE_SUB0, - PE_SUB1, - PE_SUB2 -}; +#ifndef CONFIG_USB_PD_DATA_RESET_MSG +GEN_NOT_SUPPORTED(PE_UDR_SEND_DATA_RESET); +#define PE_UDR_SEND_DATA_RESET PE_UDR_SEND_DATA_RESET_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_UDR_DATA_RESET_RECEIVED); +#define PE_UDR_DATA_RESET_RECEIVED PE_UDR_DATA_RESET_RECEIVED_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_UDR_TURN_OFF_VCONN); +#define PE_UDR_TURN_OFF_VCONN PE_UDR_TURN_OFF_VCONN_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_UDR_SEND_PS_RDY); +#define PE_UDR_SEND_PS_RDY PE_UDR_SEND_PS_RDY_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE); +#define PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE \ + PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_DDR_SEND_DATA_RESET); +#define PE_DDR_SEND_DATA_RESET PE_DDR_SEND_DATA_RESET_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_DDR_DATA_RESET_RECEIVED); +#define PE_DDR_DATA_RESET_RECEIVED PE_DDR_DATA_RESET_RECEIVED_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_DDR_WAIT_FOR_VCONN_OFF); +#define PE_DDR_WAIT_FOR_VCONN_OFF PE_DDR_WAIT_FOR_VCONN_OFF_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_DDR_PERFORM_DATA_RESET); +#define PE_DDR_PERFORM_DATA_RESET PE_DDR_PERFORM_DATA_RESET_NOT_SUPPORTED +#endif /* CONFIG_USB_PD_DATA_RESET_MSG */ static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT]; @@ -533,19 +550,22 @@ static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT]; * what ever is needed to handle the Discard. */ enum pe_msg_check { - PE_MSG_SEND_PENDING = BIT(0), - PE_MSG_SENT = BIT(1), - PE_MSG_DISCARDED = BIT(2), + PE_MSG_SEND_PENDING = BIT(0), + PE_MSG_SENT = BIT(1), + PE_MSG_DISCARDED = BIT(2), - PE_MSG_SEND_COMPLETED = BIT(3) | PE_MSG_SENT, - PE_MSG_DPM_DISCARDED = BIT(4) | PE_MSG_DISCARDED, + PE_MSG_SEND_COMPLETED = BIT(3) | PE_MSG_SENT, + PE_MSG_DPM_DISCARDED = BIT(4) | PE_MSG_DISCARDED, }; static void pe_sender_response_msg_entry(const int port); static enum pe_msg_check pe_sender_response_msg_run(const int port); +static void pe_sender_response_msg_exit(const int port); /* Debug log level - higher number == more log */ #ifdef CONFIG_USB_PD_DEBUG_LEVEL static const enum debug_level pe_debug_level = CONFIG_USB_PD_DEBUG_LEVEL; +#elif defined(CONFIG_USB_PD_INITIAL_DEBUG_LEVEL) +static enum debug_level pe_debug_level = CONFIG_USB_PD_INITIAL_DEBUG_LEVEL; #else static enum debug_level pe_debug_level = DEBUG_LEVEL_1; #endif @@ -561,12 +581,10 @@ static struct policy_engine { /* current port data role (DFP or UFP) */ enum pd_data_role data_role; /* state machine flags */ - uint32_t flags; + ATOMIC_DEFINE(flags_a, PE_FLAGS_COUNT); /* Device Policy Manager Request */ - uint32_t dpm_request; + atomic_t dpm_request; uint32_t dpm_curr_request; - /* state timeout timer */ - uint64_t timeout; /* last requested voltage PDO index */ int requested_idx; @@ -574,150 +592,32 @@ static struct policy_engine { * Port events - PD_STATUS_EVENT_* values * Set from PD task but may be cleared by host command */ - uint32_t events; + atomic_t events; /* port address where soft resets are sent */ - enum tcpm_transmit_type soft_reset_sop; + enum tcpci_msg_type soft_reset_sop; /* Current limit / voltage based on the last request message */ uint32_t curr_limit; uint32_t supply_voltage; - /* state specific state machine variable */ - enum sub_state sub; - /* PD_VDO_INVALID is used when there is an invalid VDO */ int32_t ama_vdo; int32_t vpd_vdo; /* Alternate mode discovery results */ struct pd_discovery discovery[DISCOVERY_TYPE_COUNT]; - /* Active alternate modes */ - struct partner_active_modes partner_amodes[AMODE_TYPE_COUNT]; /* Partner type to send */ - enum tcpm_transmit_type tx_type; + enum tcpci_msg_type tx_type; /* VDM - used to send information to shared VDM Request state */ uint32_t vdm_cnt; uint32_t vdm_data[VDO_HDR_SIZE + VDO_MAX_SIZE]; uint8_t vdm_ack_min_data_objects; - /* Timers */ - - /* - * The NoResponseTimer is used by the Policy Engine in a Source - * to determine that its Port Partner is not responding after a - * Hard Reset. - */ - uint64_t no_response_timer; - - /* - * Prior to a successful negotiation, a Source Shall use the - * SourceCapabilityTimer to periodically send out a - * Source_Capabilities Message. - */ - uint64_t source_cap_timer; - - /* - * This timer is started when a request for a new Capability has been - * accepted and will timeout after PD_T_PS_TRANSITION if a PS_RDY - * Message has not been received. - */ - uint64_t ps_transition_timer; - - /* - * This timer is used to ensure that a Message requesting a response - * (e.g. Get_Source_Cap Message) is responded to within a bounded time - * of PD_T_SENDER_RESPONSE. - */ - uint64_t sender_response_timer; - - /* - * This timer is used during an Explicit Contract when discovering - * whether a Port Partner is PD Capable using SOP'. - */ - uint64_t discover_identity_timer; - - /* - * This timer is used in a Source to ensure that the Sink has had - * sufficient time to process Hard Reset Signaling before turning - * off its power supply to VBUS. - */ - uint64_t ps_hard_reset_timer; - - /* - * This timer is used to ensure that the time before the next Sink - * Request Message, after a Wait Message has been received from the - * Source in response to a Sink Request Message. - */ - uint64_t sink_request_timer; - - /* - * This timer tracks the time after receiving a Wait message in response - * to a PR_Swap message. - */ - uint64_t pr_swap_wait_timer; - - /* - * This timer combines the PSSourceOffTimer and PSSourceOnTimer timers. - * For PSSourceOffTimer, when this DRP device is currently acting as a - * Sink, this timer times out on a PS_RDY Message during a Power Role - * Swap sequence. - * - * For PSSourceOnTimer, when this DRP device is currently acting as a - * Source that has just stopped sourcing power and is waiting to start - * sinking power to timeout on a PS_RDY Message during a Power Role - * Swap. - */ - uint64_t ps_source_timer; - - /* - * In BIST_TX mode, this timer is used by a UUT to ensure that a - * Continuous BIST Mode (i.e. BIST Carrier Mode) is exited in a timely - * fashion. - * - * In BIST_RX mode, this timer is used to give the port partner time - * to respond. - */ - uint64_t bist_cont_mode_timer; - /* - * This timer is used by the new Source, after a Power Role Swap or - * Fast Role Swap, to ensure that it does not send Source_Capabilities - * Message before the new Sink is ready to receive the - * Source_Capabilities Message. - */ - uint64_t swap_source_start_timer; - - /* - * This timer is used by the Initiator’s Policy Engine to ensure that - * a Structured VDM Command request needing a response (e.g. Discover - * Identity Command request) is responded to within a bounded time of - * tVDMSenderResponse. - */ - uint64_t vdm_response_timer; - - /* - * This timer is used during a VCONN Swap. - */ - uint64_t vconn_on_timer; - - /* - * For PD2.0, this timer is used to wait 400ms and add some - * jitter of up to 100ms before sending a message. - * NOTE: This timer is not part of the TypeC/PD spec. - */ - uint64_t wait_and_add_jitter_timer; - - /* - * PD 3.0, version 2.0, section 6.6.18.1: The ChunkingNotSupportedTimer - * is used by a Source or Sink which does not support multi-chunk - * Chunking but has received a Message Chunk. The - * ChunkingNotSupportedTimer Shall be started when the last bit of the - * EOP of a Message Chunk of a multi-chunk Message is received. The - * Policy Engine Shall Not send its Not_Supported Message before the - * ChunkingNotSupportedTimer expires. - */ - uint64_t chunking_not_supported_timer; + /* ADO - Used to store information about alert messages */ + uint32_t ado; + mutex_t ado_lock; /* Counters */ @@ -764,17 +664,20 @@ static struct policy_engine { /* Last received source cap */ uint32_t src_caps[PDO_MAX_OBJECTS]; - int src_cap_cnt; + int src_cap_cnt; /* -1 on error retrieving source caps */ - /* Attached ChromeOS device id, RW hash, and current RO / RW image */ - uint16_t dev_id; - uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4]; - enum ec_image current_image; + /* Last received sink cap */ + uint32_t snk_caps[PDO_MAX_OBJECTS]; + int snk_cap_cnt; + + /* Last received Revision Message Data Object (RMDO) from the partner */ + struct rmdo partner_rmdo; } pe[CONFIG_USB_PD_PORT_MAX_COUNT]; test_export_static enum usb_pe_state get_state_pe(const int port); test_export_static void set_state_pe(const int port, const enum usb_pe_state new_state); +static void pe_set_dpm_curr_request(const int port, const int request); /* * The spec. revision is used to index into this array. * PD 1.0 (VDO 1.0) - return VDM_VER10 @@ -787,12 +690,12 @@ static const uint8_t vdo_ver[] = { [PD_REV30] = VDM_VER20, }; -int pd_get_rev(int port, enum tcpm_transmit_type type) +int pd_get_rev(int port, enum tcpci_msg_type type) { return prl_get_rev(port, type); } -int pd_get_vdo_ver(int port, enum tcpm_transmit_type type) +int pd_get_vdo_ver(int port, enum tcpci_msg_type type) { enum pd_rev_type rev = prl_get_rev(port, type); @@ -810,7 +713,15 @@ static void pe_set_ready_state(int port) set_state_pe(port, PE_SNK_READY); } -static inline void send_data_msg(int port, enum tcpm_transmit_type type, +static void pe_set_hard_reset(int port) +{ + if (pe[port].power_role == PD_ROLE_SOURCE) + set_state_pe(port, PE_SRC_HARD_RESET); + else + set_state_pe(port, PE_SNK_HARD_RESET); +} + +static inline void send_data_msg(int port, enum tcpci_msg_type type, enum pd_data_msg_type msg) { /* Clear any previous TX status before sending a new message */ @@ -818,15 +729,15 @@ static inline void send_data_msg(int port, enum tcpm_transmit_type type, prl_send_data_msg(port, type, msg); } -static __maybe_unused inline void send_ext_data_msg( - int port, enum tcpm_transmit_type type, enum pd_ext_msg_type msg) +static __maybe_unused inline void +send_ext_data_msg(int port, enum tcpci_msg_type type, enum pd_ext_msg_type msg) { /* Clear any previous TX status before sending a new message */ PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); prl_send_ext_data_msg(port, type, msg); } -static inline void send_ctrl_msg(int port, enum tcpm_transmit_type type, +static inline void send_ctrl_msg(int port, enum tcpci_msg_type type, enum pd_ctrl_msg_type msg) { /* Clear any previous TX status before sending a new message */ @@ -834,6 +745,35 @@ static inline void send_ctrl_msg(int port, enum tcpm_transmit_type type, prl_send_ctrl_msg(port, type, msg); } +/* Set both the SOP' and SOP'' revisions to the given value */ +static void set_cable_rev(int port, enum pd_rev_type rev) +{ + prl_set_rev(port, TCPCI_MSG_SOP_PRIME, rev); + prl_set_rev(port, TCPCI_MSG_SOP_PRIME_PRIME, rev); +} + +/* Initialize the cable revision based only on the partner SOP revision */ +static void init_cable_rev(int port) +{ + /* + * If port partner runs PD 2.0, cable communication must + * also be PD 2.0 + */ + if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV20) { + /* + * If the cable supports PD 3.0, but the port partner supports + * PD 2.0, redo the cable discover with PD 2.0 + */ + if (prl_get_rev(port, TCPCI_MSG_SOP_PRIME) == PD_REV30 && + pd_get_identity_discovery(port, TCPCI_MSG_SOP_PRIME) == + PD_DISC_COMPLETE) { + pd_set_identity_discovery(port, TCPCI_MSG_SOP_PRIME, + PD_DISC_NEEDED); + } + set_cable_rev(port, PD_REV20); + } +} + /* Compile-time insurance to ensure this code does not call into prl directly */ #define prl_send_data_msg DO_NOT_USE #define prl_send_ext_data_msg DO_NOT_USE @@ -841,13 +781,12 @@ static inline void send_ctrl_msg(int port, enum tcpm_transmit_type type, static void pe_init(int port) { - pe[port].flags = 0; + memset(&pe[port].flags_a, 0, sizeof(pe[port].flags_a)); pe[port].dpm_request = 0; pe[port].dpm_curr_request = 0; - pe[port].source_cap_timer = TIMER_DISABLED; - pe[port].no_response_timer = TIMER_DISABLED; + pd_timer_disable_range(port, PE_TIMER_RANGE); pe[port].data_role = pd_get_data_role(port); - pe[port].tx_type = TCPC_TX_INVALID; + pe[port].tx_type = TCPCI_MSG_INVALID; pe[port].events = 0; tc_pd_connection(port, 0); @@ -863,6 +802,11 @@ int pe_is_running(int port) return local_state[port] == SM_RUN; } +bool pe_in_frs_mode(int port) +{ + return PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH); +} + bool pe_in_local_ams(int port) { return !!PE_CHK_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); @@ -881,11 +825,11 @@ void pe_run(int port, int evt, int en) case SM_PAUSED: if (!en) break; - /* fall through */ + __fallthrough; case SM_INIT: pe_init(port); local_state[port] = SM_RUN; - /* fall through */ + __fallthrough; case SM_RUN: if (!en) { local_state[port] = SM_PAUSED; @@ -897,6 +841,37 @@ void pe_run(int port, int evt, int en) break; } + /* + * 8.3.3.3.8 PE_SNK_Hard_Reset State + * The Policy Engine Shall transition to the PE_SNK_Hard_Reset + * state from any state when: + * - Hard Reset request from Device Policy Manager + * + * USB PD specification clearly states that we should go to + * PE_SNK_Hard_Reset from ANY state (including states in which + * port is source) when DPM requests that. This can lead to + * execute Hard Reset path for sink when actually our power + * role is source. In our implementation we will choose Hard + * Reset path depending on current power role. + */ + if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_HARD_RESET_SEND)) { + /* + * If a hard reset condition came up during FRS, we must + * go into ErrorRecovery. Performing a hard reset could + * leave us assuming our own FRS Vbus is coming from the + * partner and leave the port stuck as Attached.SNK + */ + if (pe_in_frs_mode(port)) { + PE_CLR_DPM_REQUEST(port, + DPM_REQUEST_HARD_RESET_SEND); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + } else { + pe_set_dpm_curr_request( + port, DPM_REQUEST_HARD_RESET_SEND); + pe_set_hard_reset(port); + } + } + /* * Check for Fast Role Swap signal * This is not a typical pattern for adding state changes. @@ -905,7 +880,7 @@ void pe_run(int port, int evt, int en) * make sure to handle it immediately. */ if (IS_ENABLED(CONFIG_USB_PD_REV30) && - PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED)) { + PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED)) { PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED); set_state_pe(port, PE_FRS_SNK_SRC_START_AMS); } @@ -927,6 +902,7 @@ void pe_message_received(int port) assert(port == TASK_ID_TO_PD_PORT(task_get_current())); PE_SET_FLAG(port, PE_FLAGS_MSG_RECEIVED); + task_wake(PD_PORT_TO_TASK_ID(port)); } void pe_hard_reset_sent(int port) @@ -942,6 +918,15 @@ void pe_got_hard_reset(int port) /* This should only be called from the PD task */ assert(port == TASK_ID_TO_PD_PORT(task_get_current())); + /* + * If we're in the middle of an FRS, any error should cause us to follow + * the ErrorRecovery path + */ + if (pe_in_frs_mode(port)) { + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + return; + } + /* * Transition from any state to the PE_SRC_Hard_Reset_Received or * PE_SNK_Transition_to_default state when: @@ -949,6 +934,9 @@ void pe_got_hard_reset(int port) */ pe[port].power_role = pd_get_power_role(port); + /* Exit BIST Test mode, in case the TCPC entered it. */ + tcpc_set_bist_test_mode(port, false); + if (pe[port].power_role == PD_ROLE_SOURCE) set_state_pe(port, PE_SRC_HARD_RESET_RECEIVED); else @@ -962,12 +950,20 @@ void pe_got_hard_reset(int port) * Called by the handler that detects the FRS signal in order to * switch PE states to complete the FRS that the hardware has * started. + * + * If the PE is not running, generate an error recovery to turn off + * Vbus and get the port back into a known state. */ void pd_got_frs_signal(int port) { - PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED); - task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE, 0); + if (pe_is_running(port)) + PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED); + else + pd_set_error_recovery(port); + + task_wake(PD_PORT_TO_TASK_ID(port)); } +#endif /* CONFIG_USB_PD_REV30 */ /* * PE_Set_FRS_Enable @@ -982,26 +978,33 @@ void pd_got_frs_signal(int port) */ static void pe_set_frs_enable(int port, int enable) { + int current = PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_ENABLED); + /* This should only be called from the PD task */ - assert(port == TASK_ID_TO_PD_PORT(task_get_current())); + if (!IS_ENABLED(TEST_BUILD)) + assert(port == TASK_ID_TO_PD_PORT(task_get_current())); + + if (!IS_ENABLED(CONFIG_USB_PD_FRS) || !IS_ENABLED(CONFIG_USB_PD_REV30)) + return; - if (IS_ENABLED(CONFIG_USB_PD_FRS)) { - int current = PE_CHK_FLAG(port, - PE_FLAGS_FAST_ROLE_SWAP_ENABLED); + /* Request an FRS change, only if the state has changed */ + if (!!current == !!enable) + return; - /* Request an FRS change, only if the state has changed */ - if (!!current != !!enable) { - pd_set_frs_enable(port, enable); - if (enable) - PE_SET_FLAG(port, - PE_FLAGS_FAST_ROLE_SWAP_ENABLED); - else - PE_CLR_FLAG(port, - PE_FLAGS_FAST_ROLE_SWAP_ENABLED); - } + pd_set_frs_enable(port, enable); + if (enable) { + int curr_limit = *pd_get_snk_caps(port) & + PDO_FIXED_FRS_CURR_MASK; + + typec_select_src_current_limit_rp( + port, curr_limit == PDO_FIXED_FRS_CURR_3A0_AT_5V ? + TYPEC_RP_3A0 : + TYPEC_RP_1A5); + PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_ENABLED); + } else { + PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_ENABLED); } } -#endif /* CONFIG_USB_PD_REV30 */ void pe_set_explicit_contract(int port) { @@ -1014,22 +1017,18 @@ void pe_set_explicit_contract(int port) void pe_invalidate_explicit_contract(int port) { - if (IS_ENABLED(CONFIG_USB_PD_REV30)) - pe_set_frs_enable(port, 0); + pe_set_frs_enable(port, 0); PE_CLR_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT); - /* Set Rp for current limit */ - if (IS_ENABLED(CONFIG_USB_PD_REV30)) + /* Set Rp for current limit if still attached */ + if (IS_ENABLED(CONFIG_USB_PD_REV30) && pd_is_connected(port)) typec_update_cc(port); } -void pe_notify_event(int port, uint32_t event_mask) +void pd_notify_event(int port, uint32_t event_mask) { - /* Events may only be set from the PD task */ - assert(port == TASK_ID_TO_PD_PORT(task_get_current())); - - deprecated_atomic_or(&pe[port].events, event_mask); + atomic_or(&pe[port].events, event_mask); /* Notify the host that new events are available to read */ pd_send_host_event(PD_EVENT_TYPEC); @@ -1037,7 +1036,7 @@ void pe_notify_event(int port, uint32_t event_mask) void pd_clear_events(int port, uint32_t clear_mask) { - deprecated_atomic_clear_bits(&pe[port].events, clear_mask); + atomic_clear_bits(&pe[port].events, clear_mask); } uint32_t pd_get_events(int port) @@ -1045,6 +1044,45 @@ uint32_t pd_get_events(int port) return pe[port].events; } +void pe_set_snk_caps(int port, int cnt, uint32_t *snk_caps) +{ + pe[port].snk_cap_cnt = cnt; + + memcpy(pe[port].snk_caps, snk_caps, sizeof(uint32_t) * cnt); +} + +const uint32_t *const pd_get_snk_caps(int port) +{ + return pe[port].snk_caps; +} + +uint8_t pd_get_snk_cap_cnt(int port) +{ + return pe[port].snk_cap_cnt; +} + +uint32_t pd_get_requested_voltage(int port) +{ + return pe[port].supply_voltage; +} + +uint32_t pd_get_requested_current(int port) +{ + return pe[port].curr_limit; +} + +#ifdef CONFIG_USB_PD_EPR +/** + * Return true if we're in an SPR contract. Note that before exiting EPR mode, + * port partners are required first to drop to SPR. Thus, we can be still in + * EPR mode (with a SPR contract). + */ +static int pe_in_spr_contract(int port) +{ + return pd_get_requested_voltage(port) <= PD_MAX_SPR_VOLTAGE; +} +#endif /* CONFIG_USB_PD_EPR */ + /* * Determine if this port may communicate with the cable plug. * @@ -1063,14 +1101,14 @@ static bool pe_can_send_sop_prime(int port) { if (IS_ENABLED(CONFIG_USBC_VCONN)) { if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT)) { - if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20) + if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV20) return tc_is_vconn_src(port) && - pe[port].data_role == PD_ROLE_DFP; + pe[port].data_role == PD_ROLE_DFP; else return tc_is_vconn_src(port); } else { return tc_is_vconn_src(port) && - pe[port].power_role == PD_ROLE_SOURCE; + pe[port].power_role == PD_ROLE_SOURCE; } } else { return false; @@ -1093,7 +1131,7 @@ static bool pe_can_send_sop_prime(int port) static bool pe_can_send_sop_vdm(int port, int vdm_cmd) { if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT)) { - if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20) { + if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV20) { if (pe[port].data_role == PD_ROLE_UFP && vdm_cmd != CMD_ATTENTION) { return false; @@ -1111,7 +1149,47 @@ static bool pe_can_send_sop_vdm(int port, int vdm_cmd) return false; } -static void pe_send_soft_reset(const int port, enum tcpm_transmit_type type) +static const uint32_t pd_get_fixed_pdo(int port) +{ + return pe[port].src_caps[0]; +} + +bool pe_snk_in_epr_mode(int port) +{ + return PE_CHK_FLAG(port, PE_FLAGS_IN_EPR); +} + +void pe_snk_epr_explicit_exit(int port) +{ + PE_SET_FLAG(port, PE_FLAGS_EPR_EXPLICIT_EXIT); +} + +bool pe_snk_can_enter_epr_mode(int port) +{ + /* + * 6.4.10.1 of USB PD R3.1 V1.6 + * + * 1. A Sink Shall Not be Connected to the Source through a CT-VPD. + * 2. The Source and Sink Shall be in an SPR Explicit Contract. + * 3. The EPR Mode capable bit Shall have been set in the 5V fixed PDO + * in the last Source_Capabilities Message the Sink received. + * 4. The EPR Mode capable bit Shall have been set in the RDO in the + * last Request Message the Source received. + */ + if (is_vpd_ct_supported(port)) { + return false; + } + + if (!pe_is_explicit_contract(port)) + return false; + + if (!(pd_get_fixed_pdo(port) & PDO_FIXED_EPR_MODE_CAPABLE)) + return false; + + return true; +} + +static void pe_send_soft_reset(const int port, enum tcpci_msg_type type) { pe[port].soft_reset_sop = type; set_state_pe(port, PE_SEND_SOFT_RESET); @@ -1129,20 +1207,54 @@ void pe_report_discard(int port) /* TODO(b/157228506): Ensure all states are checking discard */ } -void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type) +/* + * Utility function to check for an outgoing message discard during states which + * send a message as a part of an AMS and wait for the transmit to complete. + * Note these states should not be power transitioning. + * + * In these states, discard due to an incoming message is a protocol error. + */ +static bool pe_check_outgoing_discard(int port) +{ + /* + * On outgoing discard, soft reset with SOP* of incoming message + * + * See Table 6-65 Response to an incoming Message (except VDM) in PD 3.0 + * Version 2.0 Specification. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED) && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + enum tcpci_msg_type sop = + PD_HEADER_GET_SOP(rx_emsg[port].header); + + PE_CLR_FLAG(port, PE_FLAGS_MSG_DISCARDED); + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + pe_send_soft_reset(port, sop); + return true; + } + + return false; +} + +void pe_report_error(int port, enum pe_error e, enum tcpci_msg_type type) { /* This should only be called from the PD task */ assert(port == TASK_ID_TO_PD_PORT(task_get_current())); + /* + * If there is a timeout error while waiting for a chunk of a chunked + * message, there is no requirement to trigger a soft reset. + */ + if (e == ERR_RCH_CHUNK_WAIT_TIMEOUT) + return; + /* * Generate Hard Reset if Protocol Error occurred * while in PE_Send_Soft_Reset state. */ if (get_state_pe(port) == PE_SEND_SOFT_RESET) { - if (pe[port].power_role == PD_ROLE_SINK) - set_state_pe(port, PE_SNK_HARD_RESET); - else - set_state_pe(port, PE_SRC_HARD_RESET); + pe_set_hard_reset(port); return; } @@ -1155,15 +1267,28 @@ void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type) * TODO(b/150774779): TCPMv2: Improve pe_error documentation */ if ((get_state_pe(port) == PE_SRC_SEND_CAPABILITIES || - get_state_pe(port) == PE_SRC_TRANSITION_SUPPLY || - get_state_pe(port) == PE_PRS_SRC_SNK_WAIT_SOURCE_ON || - get_state_pe(port) == PE_SRC_DISABLED || - get_state_pe(port) == PE_SRC_DISCOVERY || - get_state_pe(port) == PE_VDM_IDENTITY_REQUEST_CBL) || - (IS_ENABLED(CONFIG_USBC_VCONN) && - get_state_pe(port) == PE_VCS_SEND_PS_RDY_SWAP) - ) { + get_state_pe(port) == PE_SRC_TRANSITION_SUPPLY || + get_state_pe(port) == PE_PRS_SNK_SRC_EVALUATE_SWAP || + get_state_pe(port) == PE_PRS_SNK_SRC_SOURCE_ON || + get_state_pe(port) == PE_PRS_SRC_SNK_WAIT_SOURCE_ON || + get_state_pe(port) == PE_SRC_DISABLED || + get_state_pe(port) == PE_SRC_DISCOVERY || + get_state_pe(port) == PE_VCS_CBL_SEND_SOFT_RESET || + get_state_pe(port) == PE_VDM_IDENTITY_REQUEST_CBL) || + (IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) && + (get_state_pe(port) == PE_UDR_SEND_DATA_RESET || + get_state_pe(port) == PE_UDR_DATA_RESET_RECEIVED || + get_state_pe(port) == PE_UDR_TURN_OFF_VCONN || + get_state_pe(port) == PE_UDR_SEND_PS_RDY || + get_state_pe(port) == PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE || + get_state_pe(port) == PE_DDR_SEND_DATA_RESET || + get_state_pe(port) == PE_DDR_DATA_RESET_RECEIVED || + get_state_pe(port) == PE_DDR_WAIT_FOR_VCONN_OFF || + get_state_pe(port) == PE_DDR_PERFORM_DATA_RESET)) || + (pe_in_frs_mode(port) && + get_state_pe(port) == PE_PRS_SNK_SRC_SEND_SWAP)) { PE_SET_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + task_wake(PD_PORT_TO_TASK_ID(port)); return; } @@ -1171,14 +1296,23 @@ void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type) * See section 8.3.3.4.1.1 PE_SRC_Send_Soft_Reset State: * * The PE_Send_Soft_Reset state shall be entered from - * any state when a Protocol Error is detected by - * Protocol Layer during a Non-Interruptible AMS or when - * Message has not been sent after retries. When an explicit - * contract is not in effect. Otherwise go to PE_Snk/Src_Ready - */ - if (!PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT) && - (!PE_CHK_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS) - || (e == ERR_TCH_XMIT))) { + * any state when + * * A Protocol Error is detected by Protocol Layer during a + * Non-Interruptible AMS or + * * A message has not been sent after retries or + * * When not in an explicit contract and + * * Protocol Errors occurred on SOP during an Interruptible AMS or + * * Protocol Errors occurred on SOP during any AMS where the first + * Message in the sequence has not yet been sent i.e. an unexpected + * Message is received instead of the expected GoodCRC Message + * response. + */ + /* All error types besides transmit errors are Protocol Errors. */ + if ((e != ERR_TCH_XMIT && + !PE_CHK_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS)) || + e == ERR_TCH_XMIT || + (!PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT) && + type == TCPCI_MSG_SOP)) { pe_send_soft_reset(port, type); } /* @@ -1198,8 +1332,70 @@ void pe_got_soft_reset(int port) /* * The PE_SRC_Soft_Reset state Shall be entered from any state when a * Soft_Reset Message is received from the Protocol Layer. + * + * However, if we're in the middle of an FRS sequence, we need to go to + * ErrorRecovery instead. + */ + set_state_pe(port, pe_in_frs_mode(port) ? PE_WAIT_FOR_ERROR_RECOVERY : + PE_SOFT_RESET); +} + +__overridable bool pd_can_charge_from_device(int port, const int pdo_cnt, + const uint32_t *pdos) +{ + /* + * Don't attempt to charge from a device we have no SrcCaps from. Or, if + * drp_state is FORCE_SOURCE then don't attempt a PRS. + */ + if (pdo_cnt == 0 || pd_get_dual_role(port) == PD_DRP_FORCE_SOURCE) + return false; + + /* + * Treat device as a dedicated charger (meaning we should charge + * from it) if: + * - it does not support power swap, or + * - it is unconstrained power, or + * - it presents at least 27 W of available power */ - set_state_pe(port, PE_SOFT_RESET); + + /* Unconstrained Power or NOT Dual Role Power we can charge from */ + if (pdos[0] & PDO_FIXED_UNCONSTRAINED || + (pdos[0] & PDO_FIXED_DUAL_ROLE) == 0) + return true; + + /* [virtual] allow_list */ + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { + uint32_t max_ma, max_mv, max_pdo, max_mw, unused; + + /* + * Get max power that the partner offers (not necessarily what + * this board will request) + */ + pd_find_pdo_index(pdo_cnt, pdos, pd_get_max_voltage(), + &max_pdo); + pd_extract_pdo_power(max_pdo, &max_ma, &max_mv, &unused); + max_mw = max_ma * max_mv / 1000; + + if (max_mw >= PD_DRP_CHARGE_POWER_MIN) + return true; + } + return false; +} + +void pd_resume_check_pr_swap_needed(int port) +{ + /* + * Explicit contract, current power role of SNK, the device + * indicates it should not power us, and device isn't selected + * as the charging port (ex. through the GUI) then trigger a PR_Swap + */ + if (pe_is_explicit_contract(port) && + pd_get_power_role(port) == PD_ROLE_SINK && + !pd_can_charge_from_device(port, pd_get_src_cap_cnt(port), + pd_get_src_caps(port)) && + (!IS_ENABLED(CONFIG_CHARGE_MANAGER) || + charge_manager_get_active_charge_port() != port)) + pd_dpm_request(port, DPM_REQUEST_PR_SWAP); } void pd_dpm_request(int port, enum pd_dpm_request req) @@ -1229,29 +1425,49 @@ void pe_message_sent(int port) assert(port == TASK_ID_TO_PD_PORT(task_get_current())); PE_SET_FLAG(port, PE_FLAGS_TX_COMPLETE); + task_wake(PD_PORT_TO_TASK_ID(port)); } void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, - int count) + int count) { /* Copy VDM Header */ - pe[port].vdm_data[0] = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ? - 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), - VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)) - | cmd); + pe[port].vdm_data[0] = + VDO(vid, + ((vid & USB_SID_PD) == USB_SID_PD) ? + 1 : + (PD_VDO_CMD(cmd) <= CMD_ATTENTION), + VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)) | cmd); - /* Copy Data after VDM Header */ - memcpy((pe[port].vdm_data + 1), data, count); + /* + * Copy VDOs after the VDM Header. Note that the count refers to VDO + * count. + */ + memcpy((pe[port].vdm_data + 1), data, count * sizeof(uint32_t)); pe[port].vdm_cnt = count + 1; + /* + * The PE transmit routine assumes that tx_type was set already. Note, + * that this function is likely called from outside the PD task. + * (b/180465870) + */ + pe[port].tx_type = TCPCI_MSG_SOP; + pd_dpm_request(port, DPM_REQUEST_VDM); + task_wake(PD_PORT_TO_TASK_ID(port)); } -static void pe_handle_detach(void) +#ifdef TEST_BUILD +/* + * Allow unit tests to access this function to clear internal state data between + * runs + */ +void pe_clear_port_data(int port) +#else +static void pe_clear_port_data(int port) +#endif /* TEST_BUILD */ { - const int port = TASK_ID_TO_PD_PORT(task_get_current()); - /* * PD 3.0 Section 8.3.3.3.8 * Note: The HardResetCounter is reset on a power cycle or Detach. @@ -1260,14 +1476,110 @@ static void pe_handle_detach(void) /* Reset port events */ pd_clear_events(port, GENMASK(31, 0)); -} -DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, pe_handle_detach, HOOK_PRIO_DEFAULT); -/* - * Private functions + /* But then set disconnected event */ + pd_notify_event(port, PD_STATUS_EVENT_DISCONNECTED); + + /* Tell Policy Engine to invalidate the explicit contract */ + pe_invalidate_explicit_contract(port); + + /* + * Saved Source and Sink Capabilities are no longer valid on disconnect + */ + pd_set_src_caps(port, 0, NULL); + pe_set_snk_caps(port, 0, NULL); + + /* + * Saved Revision responses are no longer valid on disconnect + */ + pe[port].partner_rmdo.reserved = 0; + pe[port].partner_rmdo.minor_ver = 0; + pe[port].partner_rmdo.major_ver = 0; + pe[port].partner_rmdo.minor_rev = 0; + pe[port].partner_rmdo.major_rev = 0; + + /* Clear any stored discovery data, but leave modes for alt mode exit */ + pd_dfp_discovery_init(port); + + /* Clear any pending alerts */ + pe_clear_ado(port); + + dpm_remove_sink(port); + dpm_remove_source(port); + dpm_init(port); + + /* Exit BIST Test mode, in case the TCPC entered it. */ + tcpc_set_bist_test_mode(port, false); +} + +int pe_set_ado(int port, uint32_t data) +{ + /* return busy error if unable to set ado */ + int ret = EC_ERROR_BUSY; + + mutex_lock(&pe[port].ado_lock); + if (pe[port].ado == 0x0) { + pe[port].ado = data; + ret = EC_SUCCESS; + } + + mutex_unlock(&pe[port].ado_lock); + return ret; +} + +void pe_clear_ado(int port) +{ + mutex_lock(&pe[port].ado_lock); + pe[port].ado = 0x0; + mutex_unlock(&pe[port].ado_lock); +} + +struct rmdo pd_get_partner_rmdo(int port) +{ + return pe[port].partner_rmdo; +} + +static void pe_handle_detach(void) +{ + const int port = TASK_ID_TO_PD_PORT(task_get_current()); + + pe_clear_port_data(port); +} +DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, pe_handle_detach, HOOK_PRIO_DEFAULT); + +#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC +static void pe_update_waiting_batt_flag(void) +{ + int i; + int batt_soc = usb_get_battery_soc(); + + if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC || + battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED) + return; + + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + if (PE_CHK_FLAG(i, PE_FLAGS_SNK_WAITING_BATT)) { + /* + * Battery has gained sufficient charge to kick off PD + * negotiation and withstand a hard reset. Clear the + * flag and perform Hard Reset. + */ + PE_CLR_FLAG(i, PE_FLAGS_SNK_WAITING_BATT); + CPRINTS("C%d: Battery has enough charge (%d%%) " + "to withstand a hard reset", + i, batt_soc); + pd_dpm_request(i, DPM_REQUEST_HARD_RESET_SEND); + } + } +} +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pe_update_waiting_batt_flag, + HOOK_PRIO_DEFAULT); +#endif + +/* + * Private functions */ -static void pe_set_dpm_curr_request(const int port, - const int request) +static void pe_set_dpm_curr_request(const int port, const int request) { PE_CLR_DPM_REQUEST(port, request); pe[port].dpm_curr_request = request; @@ -1286,57 +1598,56 @@ test_export_static enum usb_pe_state get_state_pe(const int port) return pe[port].ctx.current - &pe_states[0]; } +/* + * Handle common DPM requests to both source and sink. + * + * Note: it is assumed the calling state set PE_FLAGS_LOCALLY_INITIATED_AMS + * + * Returns true if state was set and calling run state should now return. + */ static bool common_src_snk_dpm_requests(int port) { - if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES) && - PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SEND_ALERT)) { - pe_set_dpm_curr_request(port, DPM_REQUEST_SEND_ALERT); - set_state_pe(port, PE_SEND_ALERT); - return true; - } else if (IS_ENABLED(CONFIG_USBC_VCONN) && - PE_CHK_DPM_REQUEST(port, DPM_REQUEST_VCONN_SWAP)) { + if (IS_ENABLED(CONFIG_USBC_VCONN) && + PE_CHK_DPM_REQUEST(port, DPM_REQUEST_VCONN_SWAP)) { pe_set_dpm_curr_request(port, DPM_REQUEST_VCONN_SWAP); set_state_pe(port, PE_VCS_SEND_SWAP); return true; - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_BIST_RX)) { - pe_set_dpm_curr_request(port, DPM_REQUEST_BIST_RX); - set_state_pe(port, PE_BIST_RX); - return true; - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_BIST_TX)) { + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_BIST_TX)) { pe_set_dpm_curr_request(port, DPM_REQUEST_BIST_TX); set_state_pe(port, PE_BIST_TX); return true; - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_SNK_STARTUP)) { + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SNK_STARTUP)) { pe_set_dpm_curr_request(port, DPM_REQUEST_SNK_STARTUP); set_state_pe(port, PE_SNK_STARTUP); return true; - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_SRC_STARTUP)) { + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SRC_STARTUP)) { pe_set_dpm_curr_request(port, DPM_REQUEST_SRC_STARTUP); set_state_pe(port, PE_SRC_STARTUP); return true; - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_SOFT_RESET_SEND)) { + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SOFT_RESET_SEND)) { pe_set_dpm_curr_request(port, DPM_REQUEST_SOFT_RESET_SEND); /* Currently only support sending soft reset to SOP */ - pe_send_soft_reset(port, TCPC_TX_SOP); + pe_send_soft_reset(port, TCPCI_MSG_SOP); return true; - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_PORT_DISCOVERY)) { + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_PORT_DISCOVERY)) { pe_set_dpm_curr_request(port, DPM_REQUEST_PORT_DISCOVERY); if (!PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION)) { /* * Clear counters and reset timer to trigger a - * port discovery. + * port discovery, and also clear any pending VDM send + * requests. */ pd_dfp_discovery_init(port); + /* + * TODO(b/189353401): Do not reinitialize modes when no + * longer required. + */ + pd_dfp_mode_init(port); pe[port].dr_swap_attempt_counter = 0; pe[port].discover_identity_counter = 0; - pe[port].discover_identity_timer = get_time().val + - PD_T_DISCOVER_IDENTITY; + pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY, + PD_T_DISCOVER_IDENTITY); + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_VDM); } return true; } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_VDM)) { @@ -1352,11 +1663,242 @@ static bool common_src_snk_dpm_requests(int port) pe_set_dpm_curr_request(port, DPM_REQUEST_EXIT_MODES); dpm_set_mode_exit_request(port); return true; + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_GET_SNK_CAPS)) { + pe_set_dpm_curr_request(port, DPM_REQUEST_GET_SNK_CAPS); + set_state_pe(port, PE_DR_GET_SINK_CAP); + return true; + } else if (PE_CHK_DPM_REQUEST(port, + DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND)) { + pe_set_dpm_curr_request(port, + DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND); + pe[port].tx_type = TCPCI_MSG_SOP_PRIME; + set_state_pe(port, PE_VCS_CBL_SEND_SOFT_RESET); + return true; + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_DR_SWAP)) { + pe_set_dpm_curr_request(port, DPM_REQUEST_DR_SWAP); + /* 6.3.9 DR_Swap Message in Revision 3.1, Version 1.3 + * If there are any Active Modes between the Port Partners when + * a DR_Swap Message is a received, then a Hard Reset Shall be + * performed + */ + if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION)) + pe_set_hard_reset(port); + else + set_state_pe(port, PE_DRS_SEND_SWAP); + return true; + } else if (IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) && + PE_CHK_DPM_REQUEST(port, DPM_REQUEST_DATA_RESET)) { + if (prl_get_rev(port, TCPCI_MSG_SOP) < PD_REV30) { + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_DATA_RESET); + dpm_data_reset_complete(port); + return false; + } + + pe_set_dpm_curr_request(port, DPM_REQUEST_DATA_RESET); + if (pe[port].data_role == PD_ROLE_DFP) + set_state_pe(port, PE_DDR_SEND_DATA_RESET); + else + set_state_pe(port, PE_UDR_SEND_DATA_RESET); + return true; + } else if (IS_ENABLED(CONFIG_USB_PD_REV30) && + PE_CHK_DPM_REQUEST(port, DPM_REQUEST_GET_REVISION)) { + if (prl_get_rev(port, TCPCI_MSG_SOP) < PD_REV30) { + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_GET_REVISION); + return false; + } + pe_set_dpm_curr_request(port, DPM_REQUEST_GET_REVISION); + set_state_pe(port, PE_GET_REVISION); + return true; + } else if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES) && + PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SEND_ALERT)) { + if (prl_get_rev(port, TCPCI_MSG_SOP) < PD_REV30) { + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_SEND_ALERT); + return false; + } + pe_set_dpm_curr_request(port, DPM_REQUEST_SEND_ALERT); + set_state_pe(port, PE_SEND_ALERT); + return true; + } + + return false; +} + +/* + * Handle source-specific DPM requests + * + * Returns true if state was set and calling run state should now return. + */ +static bool source_dpm_requests(int port) +{ + /* + * Ignore sink-specific request: + * DPM_REQUEST_NEW_POWER_LEVEL + * DPM_REQUEST_SOURCE_CAP + * DPM_REQUEST_FRS_DET_ENABLE + * DPM_REQURST_FRS_DET_DISABLE + */ + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_NEW_POWER_LEVEL | + DPM_REQUEST_SOURCE_CAP | + DPM_REQUEST_FRS_DET_ENABLE | + DPM_REQUEST_FRS_DET_DISABLE); + + if (pe[port].dpm_request) { + uint32_t dpm_request = pe[port].dpm_request; + + PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); + + if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP)) { + pe_set_dpm_curr_request(port, DPM_REQUEST_PR_SWAP); + set_state_pe(port, PE_PRS_SRC_SNK_SEND_SWAP); + return true; + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_GOTO_MIN)) { + pe_set_dpm_curr_request(port, DPM_REQUEST_GOTO_MIN); + set_state_pe(port, PE_SRC_TRANSITION_SUPPLY); + return true; + } else if (PE_CHK_DPM_REQUEST(port, + DPM_REQUEST_SRC_CAP_CHANGE)) { + pe_set_dpm_curr_request(port, + DPM_REQUEST_SRC_CAP_CHANGE); + set_state_pe(port, PE_SRC_SEND_CAPABILITIES); + return true; + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_GET_SRC_CAPS)) { + pe_set_dpm_curr_request(port, DPM_REQUEST_GET_SRC_CAPS); + set_state_pe(port, PE_DR_SRC_GET_SOURCE_CAP); + return true; + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SEND_PING)) { + pe_set_dpm_curr_request(port, DPM_REQUEST_SEND_PING); + set_state_pe(port, PE_SRC_PING); + return true; + } else if (common_src_snk_dpm_requests(port)) { + return true; + } + + CPRINTF("Unhandled DPM Request %x received\n", dpm_request); + PE_CLR_DPM_REQUEST(port, dpm_request); + PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); + } + return false; +} + +/* + * Handle sink-specific DPM requests + * + * Returns true if state was set and calling run state should now return. + */ +static bool sink_dpm_requests(int port) +{ + /* + * Ignore source specific requests: + * DPM_REQUEST_GOTO_MIN + * DPM_REQUEST_SRC_CAP_CHANGE, + * DPM_REQUEST_SEND_PING + */ + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_GOTO_MIN | + DPM_REQUEST_SRC_CAP_CHANGE | + DPM_REQUEST_SEND_PING); + + if (pe[port].dpm_request) { + uint32_t dpm_request = pe[port].dpm_request; + + PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); + + if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP)) { + pe_set_dpm_curr_request(port, DPM_REQUEST_PR_SWAP); + set_state_pe(port, PE_PRS_SNK_SRC_SEND_SWAP); + return true; + } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SOURCE_CAP)) { + pe_set_dpm_curr_request(port, DPM_REQUEST_SOURCE_CAP); + set_state_pe(port, PE_SNK_GET_SOURCE_CAP); + return true; + } else if (PE_CHK_DPM_REQUEST(port, + DPM_REQUEST_NEW_POWER_LEVEL)) { + pe_set_dpm_curr_request(port, + DPM_REQUEST_NEW_POWER_LEVEL); + set_state_pe(port, PE_SNK_SELECT_CAPABILITY); + return true; + } else if (PE_CHK_DPM_REQUEST(port, + DPM_REQUEST_FRS_DET_ENABLE)) { + pe_set_frs_enable(port, 1); + + /* Requires no state change, fall through to false */ + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_FRS_DET_ENABLE); + } else if (PE_CHK_DPM_REQUEST(port, + DPM_REQUEST_FRS_DET_DISABLE)) { + pe_set_frs_enable(port, 0); + /* Restore a default port current limit */ + typec_select_src_current_limit_rp(port, + CONFIG_USB_PD_PULLUP); + + /* Requires no state change, fall through to false */ + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_FRS_DET_DISABLE); + } else if (common_src_snk_dpm_requests(port)) { + return true; +#ifdef CONFIG_USB_PD_EPR + } else if (PE_CHK_DPM_REQUEST(port, + DPM_REQUEST_EPR_MODE_ENTRY)) { + if (pe_snk_in_epr_mode(port)) { + PE_CLR_DPM_REQUEST(port, + DPM_REQUEST_EPR_MODE_ENTRY); + CPRINTS("C%d: Already in EPR mode", port); + return false; + } + + if (!pe_snk_can_enter_epr_mode(port)) { + PE_CLR_DPM_REQUEST(port, + DPM_REQUEST_EPR_MODE_ENTRY); + CPRINTS("C%d: Not allowed to enter EPR", port); + return false; + } + + pe_set_dpm_curr_request(port, + DPM_REQUEST_EPR_MODE_ENTRY); + pd_set_max_voltage(PD_MAX_VOLTAGE_MV); + set_state_pe(port, PE_SNK_SEND_EPR_MODE_ENTRY); + return true; + } else if (PE_CHK_DPM_REQUEST(port, + DPM_REQUEST_EPR_MODE_EXIT)) { + if (!pe_snk_in_epr_mode(port)) { + PE_CLR_DPM_REQUEST(port, + DPM_REQUEST_EPR_MODE_EXIT); + CPRINTS("C%d: Not in EPR mode", port); + return false; + } + + /* + * If we're already in an SPR contract, send an exit + * message. Figure 8-217. + */ + if (pe_in_spr_contract(port)) { + pe_set_dpm_curr_request( + port, DPM_REQUEST_EPR_MODE_EXIT); + set_state_pe(port, PE_SNK_SEND_EPR_MODE_EXIT); + return true; + } + + /* + * Can't exit yet because we're still in EPR contract. + * Send an SPR RDO to negotiate an SPR contract. + * Keep DPM_REQUEST_EPR_MODE_EXIT so that we can retry. + */ + CPRINTS("C%d: Request SPR before EPR exit", port); + pd_set_max_voltage(PD_MAX_SPR_VOLTAGE); + pe_set_dpm_curr_request(port, + DPM_REQUEST_NEW_POWER_LEVEL); + set_state_pe(port, PE_SNK_SELECT_CAPABILITY); + return true; +#endif /* CONFIG_USB_PD_EPR */ + } else { + CPRINTF("Unhandled DPM Request %x received\n", + dpm_request); + PE_CLR_DPM_REQUEST(port, dpm_request); + } + + PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); } return false; } -/* Get the previous TypeC state. */ +/* Get the previous PE state. */ static enum usb_pe_state get_last_state_pe(const int port) { return pe[port].ctx.previous - &pe_states[0]; @@ -1366,37 +1908,30 @@ static void print_current_state(const int port) { const char *mode = ""; - if (IS_ENABLED(CONFIG_USB_PD_REV30) && - PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH)) + if (IS_ENABLED(CONFIG_USB_PD_REV30) && pe_in_frs_mode(port)) mode = " FRS-MODE"; if (IS_ENABLED(USB_PD_DEBUG_LABELS)) CPRINTS_L1("C%d: %s%s", port, - pe_state_names[get_state_pe(port)], mode); + pe_state_names[get_state_pe(port)], mode); else - CPRINTS("C%d: pe-st%d", port, get_state_pe(port)); + CPRINTS_L1("C%d: pe-st%d", port, get_state_pe(port)); } static void send_source_cap(int port) { -#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ - defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) const uint32_t *src_pdo; - const int src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); -#else - const uint32_t *src_pdo = pd_src_pdo; - const int src_pdo_cnt = pd_src_pdo_cnt; -#endif + const int src_pdo_cnt = dpm_get_source_pdo(&src_pdo, port); if (src_pdo_cnt == 0) { /* No source capabilities defined, sink only */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT); } tx_emsg[port].len = src_pdo_cnt * 4; memcpy(tx_emsg[port].buf, (uint8_t *)src_pdo, tx_emsg[port].len); - send_data_msg(port, TCPC_TX_SOP, PD_DATA_SOURCE_CAP); + send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_SOURCE_CAP); } /* @@ -1404,16 +1939,31 @@ static void send_source_cap(int port) */ static void pe_send_request_msg(int port) { + uint32_t vpd_vdo = 0; uint32_t rdo; uint32_t curr_limit; uint32_t supply_voltage; + enum pd_data_msg_type msg; + + /* + * If we are charging through a VPD, the requested voltage and current + * might need adjusting. + */ + if ((get_usb_pd_cable_type(port) == IDH_PTYPE_VPD) && + is_vpd_ct_supported(port)) { + union vpd_vdo vpd = + pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME) + ->identity.product_t1.vpd; + + /* The raw vpd_vdo is passed to pd_build_request */ + vpd_vdo = vpd.raw_value; + } /* Build and send request RDO */ - pd_build_request(pe[port].vpd_vdo, &rdo, &curr_limit, - &supply_voltage, port); + pd_build_request(vpd_vdo, &rdo, &curr_limit, &supply_voltage, port); - CPRINTF("C%d: Req [%d] %dmV %dmA", port, RDO_POS(rdo), - supply_voltage, curr_limit); + CPRINTF("C%d: Req [%d] %dmV %dmA", port, RDO_POS(rdo), supply_voltage, + curr_limit); if (rdo & RDO_CAP_MISMATCH) CPRINTF(" Mismatch"); CPRINTF("\n"); @@ -1421,72 +1971,72 @@ static void pe_send_request_msg(int port) pe[port].curr_limit = curr_limit; pe[port].supply_voltage = supply_voltage; - tx_emsg[port].len = 4; + if (IS_ENABLED(CONFIG_USB_PD_EPR) && pe_snk_in_epr_mode(port)) { + const uint32_t *src_caps = pd_get_src_caps(port); + + tx_emsg[port].len = 8; + memcpy(tx_emsg[port].buf, (uint8_t *)&rdo, sizeof(rdo)); + memcpy(tx_emsg[port].buf + sizeof(rdo), + (uint8_t *)&src_caps[RDO_POS(rdo) - 1], + sizeof(src_caps[0])); + msg = PD_DATA_EPR_REQUEST; + } else { + tx_emsg[port].len = 4; + memcpy(tx_emsg[port].buf, (uint8_t *)&rdo, tx_emsg[port].len); + msg = PD_DATA_REQUEST; + } - memcpy(tx_emsg[port].buf, (uint8_t *)&rdo, tx_emsg[port].len); - send_data_msg(port, TCPC_TX_SOP, PD_DATA_REQUEST); + send_data_msg(port, TCPCI_MSG_SOP, msg); } -static void pe_update_pdo_flags(int port, uint32_t pdo) +static void pe_update_src_pdo_flags(int port, int pdo_cnt, uint32_t *pdos) { -#ifdef CONFIG_CHARGE_MANAGER -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - int charge_allowlisted = - (pd_get_power_role(port) == PD_ROLE_SINK && - pd_charge_from_device(pd_get_identity_vid(port), - pd_get_identity_pid(port))); -#else - const int charge_allowlisted = 0; -#endif -#endif - - /* can only parse PDO flags if type is fixed */ - if ((pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED) + /* + * Only parse PDO flags if type is fixed + * + * Note: From 6.4.1 Capabilities Message "The vSafe5V Fixed Supply + * Object Shall always be the first object." so hitting this condition + * would mean the partner is voilating spec. + */ + if ((pdos[0] & PDO_TYPE_MASK) != PDO_TYPE_FIXED) return; - if (pdo & PDO_FIXED_DUAL_ROLE) - tc_partner_dr_power(port, 1); - else - tc_partner_dr_power(port, 0); - - if (pdo & PDO_FIXED_UNCONSTRAINED) - tc_partner_unconstrainedpower(port, 1); - else - tc_partner_unconstrainedpower(port, 0); - - /* Do not set USB comm if we are in an alt-mode */ - if (pe[port].partner_amodes[TCPC_TX_SOP].amode_idx == 0) { - if (pdo & PDO_FIXED_COMM_CAP) - tc_partner_usb_comm(port, 1); - else - tc_partner_usb_comm(port, 0); + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { + if (pd_can_charge_from_device(port, pdo_cnt, pdos)) { + charge_manager_update_dualrole(port, CAP_DEDICATED); + } else { + charge_manager_update_dualrole(port, CAP_DUALROLE); + } } +} - if (pdo & PDO_FIXED_DATA_SWAP) - tc_partner_dr_data(port, 1); - else - tc_partner_dr_data(port, 0); +/* + * Evaluate whether our PR role is in the middle of changing, meaning we our + * current PR role is not the one we expect to have very shortly. + */ +bool pe_is_pr_swapping(int port) +{ + enum usb_pe_state cur_state = get_state_pe(port); -#ifdef CONFIG_CHARGE_MANAGER - /* - * Treat device as a dedicated charger (meaning we should charge - * from it) if it does not support power swap, or if it is unconstrained - * power, or if we are a sink and the device identity matches a - * charging allow-list. - */ - if (!(pdo & PDO_FIXED_DUAL_ROLE) || (pdo & PDO_FIXED_UNCONSTRAINED) || - charge_allowlisted) { - PE_CLR_FLAG(port, PE_FLAGS_PORT_PARTNER_IS_DUALROLE); - charge_manager_update_dualrole(port, CAP_DEDICATED); - } else { - PE_SET_FLAG(port, PE_FLAGS_PORT_PARTNER_IS_DUALROLE); - charge_manager_update_dualrole(port, CAP_DUALROLE); - } -#endif + if (cur_state == PE_PRS_SRC_SNK_EVALUATE_SWAP || + cur_state == PE_PRS_SRC_SNK_TRANSITION_TO_OFF || + cur_state == PE_PRS_SNK_SRC_EVALUATE_SWAP || + cur_state == PE_PRS_SNK_SRC_TRANSITION_TO_OFF) + return true; + + return false; } void pd_request_power_swap(int port) { + /* Ignore requests when the board does not wish to swap */ + if (!pd_check_power_swap(port)) + return; + + /* Ignore requests when our power role is transitioning */ + if (pe_is_pr_swapping(port)) + return; + /* * Always reset the SRC to SNK PR swap counter when a PR swap is * requested by policy. @@ -1495,29 +2045,17 @@ void pd_request_power_swap(int port) pd_dpm_request(port, DPM_REQUEST_PR_SWAP); } -int pd_is_port_partner_dualrole(int port) -{ - return PE_CHK_FLAG(port, PE_FLAGS_PORT_PARTNER_IS_DUALROLE); -} - -static void pe_prl_execute_hard_reset(int port) -{ - prl_execute_hard_reset(port); -} - /* The function returns true if there is a PE state change, false otherwise */ static bool port_try_vconn_swap(int port) { if (pe[port].vconn_swap_counter < N_VCONN_SWAP_COUNT) { - pe[port].vconn_swap_counter++; - PE_SET_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON); + pd_dpm_request(port, DPM_REQUEST_VCONN_SWAP); set_state_pe(port, get_last_state_pe(port)); return true; } return false; } -#ifdef CONFIG_USB_PD_ALT_MODE_DFP /* * Run discovery at our leisure from PE_SNK_Ready or PE_SRC_Ready, after * attempting to get into the desired default policy of DFP/Vconn source @@ -1525,96 +2063,105 @@ static bool port_try_vconn_swap(int port) * Return indicates whether set_state was called, in which case the calling * function should return as well. */ -static bool pe_attempt_port_discovery(int port) +__maybe_unused static bool pe_attempt_port_discovery(int port) { - /* - * DONE set once modal entry is successful, discovery completes, or - * discovery results in a NAK + if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) + assert(0); + + /* TODO(b/272827504): Gate discovery via a DPM request and remove this + * flag. */ - if (PE_CHK_FLAG(port, PE_FLAGS_VDM_SETUP_DONE)) + if (PE_CHK_FLAG(port, PE_FLAGS_DISCOVERY_DISABLED)) return false; - /* - * TODO: POLICY decision: move policy functionality out to a separate - * file. For now, try once to become DFP/Vconn source - */ - if (PE_CHK_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP)) { + /* Apply Port Discovery DR Swap Policy */ + if (port_discovery_dr_swap_policy( + port, pe[port].data_role, + PE_CHK_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP))) { + PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); PE_CLR_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP); + set_state_pe(port, PE_DRS_SEND_SWAP); + return true; + } - if (pe[port].data_role == PD_ROLE_UFP) { - PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); - set_state_pe(port, PE_DRS_SEND_SWAP); - return true; - } + /* + * An edge case of DR Swap fail (port still UFP) and partner in PD 2.0. + * PD 2.0 allows only DFP to initiate Discover Identity, but partner may + * reject a DR Swap. + */ + if (pe[port].data_role == PD_ROLE_UFP && + prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV20) { + /* Although, logically, "pd_disable_discovery" should set + * "PE_FLAGS_DISCOVERY_DISABLED," set it here to make its + * limited purpose obvious: When discovery is impossible, send + * discovery-done events exactly once. + */ + PE_SET_FLAG(port, PE_FLAGS_DISCOVERY_DISABLED); + pd_disable_discovery(port); + pd_notify_event(port, PD_STATUS_EVENT_SOP_DISC_DONE); + pd_notify_event(port, PD_STATUS_EVENT_SOP_PRIME_DISC_DONE); + return false; } + /* Apply Port Discovery VCONN Swap Policy */ if (IS_ENABLED(CONFIG_USBC_VCONN) && - PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON)) { + port_discovery_vconn_swap_policy( + port, PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON))) { + PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON); - - if (!tc_is_vconn_src(port)) { - PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); - set_state_pe(port, PE_VCS_SEND_SWAP); - return true; - } - } - - /* If mode entry was successful, disable the timer */ - if (PE_CHK_FLAG(port, PE_FLAGS_VDM_SETUP_DONE)) { - pe[port].discover_identity_timer = TIMER_DISABLED; - return false; + set_state_pe(port, PE_VCS_SEND_SWAP); + return true; } /* * Run discovery functions when the timer indicating either cable * discovery spacing or BUSY spacing runs out. */ - if (get_time().val > pe[port].discover_identity_timer) { - if (pd_get_identity_discovery(port, TCPC_TX_SOP_PRIME) == - PD_DISC_NEEDED && pe_can_send_sop_prime(port)) { - pe[port].tx_type = TCPC_TX_SOP_PRIME; + if (pd_timer_is_expired(port, PE_TIMER_DISCOVER_IDENTITY)) { + if (pd_get_identity_discovery(port, TCPCI_MSG_SOP_PRIME) == + PD_DISC_NEEDED) { + pe[port].tx_type = TCPCI_MSG_SOP_PRIME; set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL); return true; - } else if (pd_get_identity_discovery(port, TCPC_TX_SOP) == - PD_DISC_NEEDED && - pe_can_send_sop_vdm(port, CMD_DISCOVER_IDENT)) { - pe[port].tx_type = TCPC_TX_SOP; - set_state_pe(port, - PE_INIT_PORT_VDM_IDENTITY_REQUEST); + } else if (pd_get_identity_discovery(port, TCPCI_MSG_SOP) == + PD_DISC_NEEDED && + pe_can_send_sop_vdm(port, CMD_DISCOVER_IDENT)) { + pe[port].tx_type = TCPCI_MSG_SOP; + set_state_pe(port, PE_INIT_PORT_VDM_IDENTITY_REQUEST); return true; - } else if (pd_get_svids_discovery(port, TCPC_TX_SOP) == - PD_DISC_NEEDED && - pe_can_send_sop_vdm(port, CMD_DISCOVER_SVID)) { - pe[port].tx_type = TCPC_TX_SOP; + } else if (pd_get_svids_discovery(port, TCPCI_MSG_SOP) == + PD_DISC_NEEDED && + pe_can_send_sop_vdm(port, CMD_DISCOVER_SVID)) { + pe[port].tx_type = TCPCI_MSG_SOP; set_state_pe(port, PE_INIT_VDM_SVIDS_REQUEST); return true; - } else if (pd_get_modes_discovery(port, TCPC_TX_SOP) == - PD_DISC_NEEDED && - pe_can_send_sop_vdm(port, CMD_DISCOVER_MODES)) { - pe[port].tx_type = TCPC_TX_SOP; + } else if (pd_get_modes_discovery(port, TCPCI_MSG_SOP) == + PD_DISC_NEEDED && + pe_can_send_sop_vdm(port, CMD_DISCOVER_MODES)) { + pe[port].tx_type = TCPCI_MSG_SOP; set_state_pe(port, PE_INIT_VDM_MODES_REQUEST); return true; - } else if (pd_get_svids_discovery(port, TCPC_TX_SOP_PRIME) - == PD_DISC_NEEDED && - pe_can_send_sop_prime(port)) { - pe[port].tx_type = TCPC_TX_SOP_PRIME; + } else if (pd_get_svids_discovery(port, TCPCI_MSG_SOP_PRIME) == + PD_DISC_NEEDED) { + pe[port].tx_type = TCPCI_MSG_SOP_PRIME; set_state_pe(port, PE_INIT_VDM_SVIDS_REQUEST); return true; - } else if (pd_get_modes_discovery(port, TCPC_TX_SOP_PRIME) == - PD_DISC_NEEDED && - pe_can_send_sop_prime(port)) { - pe[port].tx_type = TCPC_TX_SOP_PRIME; + } else if (pd_get_modes_discovery(port, TCPCI_MSG_SOP_PRIME) == + PD_DISC_NEEDED) { + pe[port].tx_type = TCPCI_MSG_SOP_PRIME; set_state_pe(port, PE_INIT_VDM_MODES_REQUEST); return true; + } else { + pd_timer_disable(port, PE_TIMER_DISCOVER_IDENTITY); + return false; } } return false; } -#endif -bool pd_setup_vdm_request(int port, enum tcpm_transmit_type tx_type, - uint32_t *vdm, uint32_t vdo_cnt) +bool pd_setup_vdm_request(int port, enum tcpci_msg_type tx_type, uint32_t *vdm, + uint32_t vdo_cnt) { if (vdo_cnt < VDO_HDR_SIZE || vdo_cnt > VDO_MAX_SIZE) return false; @@ -1626,42 +2173,13 @@ bool pd_setup_vdm_request(int port, enum tcpm_transmit_type tx_type, return true; } -int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash, - uint32_t current_image) -{ - pe[port].dev_id = dev_id; - memcpy(pe[port].dev_rw_hash, rw_hash, PD_RW_HASH_SIZE); -#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO - pd_dev_dump_info(dev_id, rw_hash); -#endif - pe[port].current_image = current_image; - - if (IS_ENABLED(CONFIG_USB_PD_HOST_CMD)) { - int i; - - /* Search table for matching device / hash */ - for (i = 0; i < RW_HASH_ENTRIES; i++) - if (dev_id == rw_hash_table[i].dev_id) - return !memcmp(rw_hash, - rw_hash_table[i].dev_rw_hash, - PD_RW_HASH_SIZE); - } - - return 0; -} - -void pd_dev_get_rw_hash(int port, uint16_t *dev_id, uint8_t *rw_hash, - uint32_t *current_image) -{ - *dev_id = pe[port].dev_id; - *current_image = pe[port].current_image; - if (*dev_id) - memcpy(rw_hash, pe[port].dev_rw_hash, PD_RW_HASH_SIZE); -} - /* * This function must only be called from the PE_SNK_READY entry and * PE_SRC_READY entry State. + * + * TODO(b:181339670) Rethink jitter timer restart if this is the first + * message but the partner gets a message in first, may not want to + * disable and restart it. */ static void pe_update_wait_and_add_jitter_timer(int port) { @@ -1683,11 +2201,12 @@ static void pe_update_wait_and_add_jitter_timer(int port) * we start our interrogation. Add some jitter of up to * ~345ms to prevent multiple collisions. */ - if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20 && - PE_CHK_FLAG(port, PE_FLAGS_FIRST_MSG)) { - pe[port].wait_and_add_jitter_timer = get_time().val + + if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV20 && + PE_CHK_FLAG(port, PE_FLAGS_FIRST_MSG) && + pd_timer_is_disabled(port, PE_TIMER_WAIT_AND_ADD_JITTER)) { + pd_timer_enable(port, PE_TIMER_WAIT_AND_ADD_JITTER, SRC_SNK_READY_HOLD_OFF_US + - (get_time().le.lo & 0xf) * 23 * MSEC; + (get_time().le.lo & 0xf) * 23 * MSEC); } } @@ -1700,14 +2219,14 @@ static void pe_update_wait_and_add_jitter_timer(int port) */ /* * pe_sender_response_msg_entry - * Initiallization for handling sender response messages. + * Initialization for handling sender response messages. * * @param port USB-C Port number */ static void pe_sender_response_msg_entry(const int port) { /* Stop sender response timer */ - pe[port].sender_response_timer = TIMER_DISABLED; + pd_timer_disable(port, PE_TIMER_SENDER_RESPONSE); } /* @@ -1730,7 +2249,9 @@ static void pe_sender_response_msg_entry(const int port) */ static enum pe_msg_check pe_sender_response_msg_run(const int port) { - if (pe[port].sender_response_timer == TIMER_DISABLED) { + timestamp_t tx_success_ts; + uint32_t offset; + if (pd_timer_is_disabled(port, PE_TIMER_SENDER_RESPONSE)) { /* Check for Discard */ if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { int dpm_request = pe[port].dpm_curr_request; @@ -1748,9 +2269,19 @@ static enum pe_msg_check pe_sender_response_msg_run(const int port) if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); - /* Initialize and run the SenderResponseTimer */ - pe[port].sender_response_timer = get_time().val + - PD_T_SENDER_RESPONSE; + /* TCPC TX success time stamp */ + tx_success_ts = prl_get_tcpc_tx_success_ts(port); + /* Calculate the delay from TX success to PE */ + offset = time_since32(tx_success_ts); + + /* + * Initialize and run the SenderResponseTimer by + * offsetting it with TX transmit success time. + * This would remove the effect of the latency from + * propagating the TX status. + */ + pd_timer_enable(port, PE_TIMER_SENDER_RESPONSE, + PD_T_SENDER_RESPONSE - offset); return PE_MSG_SEND_COMPLETED; } return PE_MSG_SEND_PENDING; @@ -1758,6 +2289,17 @@ static enum pe_msg_check pe_sender_response_msg_run(const int port) return PE_MSG_SENT; } +/* + * pe_sender_response_msg_exit + * Exit cleanup for handling sender response messages. + * + * @param port USB-C Port number + */ +static void pe_sender_response_msg_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_SENDER_RESPONSE); +} + /** * PE_SRC_Startup */ @@ -1769,7 +2311,7 @@ static void pe_src_startup_entry(int port) pe[port].caps_counter = 0; /* Reset the protocol layer */ - prl_reset(port); + prl_reset_soft(port); /* Set initial data role */ pe[port].data_role = pd_get_data_role(port); @@ -1780,29 +2322,62 @@ static void pe_src_startup_entry(int port) /* Clear explicit contract. */ pe_invalidate_explicit_contract(port); + /* Clear any pending PD events */ + pe_clear_ado(port); + if (PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE); + /* + * Protocol layer reset clears the message IDs for all SOP + * types. Indicate that a SOP' soft reset is required before any + * other messages are sent to the cable. + * + * Note that other paths into this state are for the initial + * connection and for a hard reset. In both cases the cable + * should also automatically clear the message IDs so don't + * generate an SOP' soft reset for those cases. Sending + * unnecessary SOP' soft resets causes bad behavior with + * some devices. See b/179325862. + */ + pd_dpm_request(port, DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND); /* Start SwapSourceStartTimer */ - pe[port].swap_source_start_timer = get_time().val + - PD_T_SWAP_SOURCE_START; - } else { + pd_timer_enable(port, PE_TIMER_SWAP_SOURCE_START, + PD_T_SWAP_SOURCE_START); + + /* + * Evaluate port's sink caps for preferred current, if + * already available + */ + if (pd_get_snk_cap_cnt(port) > 0) + dpm_evaluate_sink_fixed_pdo(port, + *pd_get_snk_caps(port)); + + /* + * Remove prior FRS claims to 3.0 A now that sink current has + * been claimed, to avoid issues with lower priority ports + * potentially receiving a 3.0 A claim between calls. + */ + dpm_remove_source(port); + } else { /* * SwapSourceStartTimer delay is not needed, so trigger now. * We can't use set_state_pe here, since we need to ensure that * the protocol layer is running again (done in run function). */ - pe[port].swap_source_start_timer = get_time().val; + pd_timer_enable(port, PE_TIMER_SWAP_SOURCE_START, 0); /* * Set DiscoverIdentityTimer to trigger when we enter * src_discovery for the first time. After initial startup * set, vdm_identity_request_cbl will handle the timer updates. */ - pe[port].discover_identity_timer = get_time().val; + pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY, 0); - /* Clear port discovery flags */ + /* Clear port discovery/mode flags */ pd_dfp_discovery_init(port); + pd_dfp_mode_init(port); + dpm_init(port); pe[port].ama_vdo = PD_VDO_INVALID; pe[port].vpd_vdo = PD_VDO_INVALID; pe[port].discover_identity_counter = 0; @@ -1812,6 +2387,18 @@ static void pe_src_startup_entry(int port) /* Reset VCONN swap counter */ pe[port].vconn_swap_counter = 0; + + /* Request partner sink caps if a feature requires them */ + if (IS_ENABLED(CONFIG_USB_PD_HOST_CMD) || + CONFIG_USB_PD_3A_PORTS > 0 || IS_ENABLED(CONFIG_USB_PD_FRS)) + pd_dpm_request(port, DPM_REQUEST_GET_SNK_CAPS); + + /* + * Request partner's revision information. The PE_Get_Revision + * state will only send Get_Revision to partners with major + * revision 3.0 + */ + pd_dpm_request(port, DPM_REQUEST_GET_REVISION); } } @@ -1821,10 +2408,15 @@ static void pe_src_startup_run(int port) if (!prl_is_running(port)) return; - if (get_time().val > pe[port].swap_source_start_timer) + if (pd_timer_is_expired(port, PE_TIMER_SWAP_SOURCE_START)) set_state_pe(port, PE_SRC_SEND_CAPABILITIES); } +static void pe_src_startup_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_SWAP_SOURCE_START); +} + /** * PE_SRC_Discovery */ @@ -1844,8 +2436,8 @@ static void pe_src_discovery_entry(int port) * is in place. All other probing must happen from ready states. */ if (get_last_state_pe(port) != PE_VDM_IDENTITY_REQUEST_CBL) - pe[port].source_cap_timer = - get_time().val + PD_T_SEND_SOURCE_CAP; + pd_timer_enable(port, PE_TIMER_SOURCE_CAP, + PD_T_SEND_SOURCE_CAP); } static void pe_src_discovery_run(int port) @@ -1864,11 +2456,24 @@ static void pe_src_discovery_run(int port) * 1) DPM requests the identity of the cable plug and * 2) DiscoverIdentityCounter < nDiscoverIdentityCount */ - if (get_time().val > pe[port].source_cap_timer) { + if (pd_timer_is_expired(port, PE_TIMER_SOURCE_CAP)) { if (pe[port].caps_counter <= N_CAPS_COUNT) { set_state_pe(port, PE_SRC_SEND_CAPABILITIES); return; } else if (!PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION)) { + /* + * Cable identity may be discovered without a PD + * contract in place. If it has been discovered, notify + * the AP. + */ + if (pd_get_identity_discovery(port, + TCPCI_MSG_SOP_PRIME) == + PD_DISC_COMPLETE) { + pd_notify_event( + port, + PD_STATUS_EVENT_SOP_PRIME_DISC_DONE); + } + set_state_pe(port, PE_SRC_DISABLED); return; } @@ -1879,10 +2484,13 @@ static void pe_src_discovery_run(int port) * contract, we use it here to ensure we space any potential BUSY * requests properly. */ - if (pd_get_identity_discovery(port, TCPC_TX_SOP_PRIME) == PD_DISC_NEEDED - && get_time().val > pe[port].discover_identity_timer - && pe_can_send_sop_prime(port)) { - pe[port].tx_type = TCPC_TX_SOP_PRIME; + if (pd_get_identity_discovery(port, TCPCI_MSG_SOP_PRIME) == + PD_DISC_NEEDED && + pd_timer_is_expired(port, PE_TIMER_DISCOVER_IDENTITY) && + pe_can_send_sop_prime(port) && + (pe[port].discover_identity_counter < + N_DISCOVER_IDENTITY_PRECONTRACT_LIMIT)) { + pe[port].tx_type = TCPCI_MSG_SOP_PRIME; set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL); return; } @@ -1894,8 +2502,8 @@ static void pe_src_discovery_run(int port) * 3) And the HardResetCounter > nHardResetCount. */ if (!PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION) && - get_time().val > pe[port].no_response_timer && - pe[port].hard_reset_counter > N_HARD_RESET_COUNT) { + pd_timer_is_expired(port, PE_TIMER_NO_RESPONSE) && + pe[port].hard_reset_counter > N_HARD_RESET_COUNT) { set_state_pe(port, PE_SRC_DISABLED); return; } @@ -1934,7 +2542,7 @@ static void pe_src_send_capabilities_run(int port) set_state_pe(port, PE_SRC_READY); return; } else if (msg_check == PE_MSG_DISCARDED) { - pe_send_soft_reset(port, TCPC_TX_SOP); + pe_send_soft_reset(port, TCPCI_MSG_SOP); return; } @@ -1950,7 +2558,7 @@ static void pe_src_send_capabilities_run(int port) * 3) Initialize and run the SenderResponseTimer. */ /* Stop the NoResponseTimer */ - pe[port].no_response_timer = TIMER_DISABLED; + pd_timer_disable(port, PE_TIMER_NO_RESPONSE); /* Reset the HardResetCounter to zero */ pe[port].hard_reset_counter = 0; @@ -1971,22 +2579,16 @@ static void pe_src_send_capabilities_run(int port) * Request Message Received? */ if (PD_HEADER_CNT(rx_emsg[port].header) > 0 && - PD_HEADER_TYPE(rx_emsg[port].header) == - PD_DATA_REQUEST) { - + PD_HEADER_TYPE(rx_emsg[port].header) == PD_DATA_REQUEST) { /* * Set to highest revision supported by both * ports. */ - prl_set_rev(port, TCPC_TX_SOP, - MIN(PD_REVISION, PD_HEADER_REV(rx_emsg[port].header))); + prl_set_rev(port, TCPCI_MSG_SOP, + MIN(PD_REVISION, + PD_HEADER_REV(rx_emsg[port].header))); - /* - * If port partner runs PD 2.0, cable communication must - * also be PD 2.0 - */ - if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20) - prl_set_rev(port, TCPC_TX_SOP_PRIME, PD_REV20); + init_cable_rev(port); /* We are PD connected */ PE_SET_FLAG(port, PE_FLAGS_PD_CONNECTION); @@ -2029,7 +2631,7 @@ static void pe_src_send_capabilities_run(int port) if (!PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION)) set_state_pe(port, PE_SRC_DISCOVERY); else - pe_send_soft_reset(port, TCPC_TX_SOP); + pe_send_soft_reset(port, TCPCI_MSG_SOP); return; } @@ -2044,9 +2646,9 @@ static void pe_src_send_capabilities_run(int port) * 2) The NoResponseTimer times out * 3) And the HardResetCounter > nHardResetCount. */ - if (get_time().val > pe[port].no_response_timer) { + if (pd_timer_is_expired(port, PE_TIMER_NO_RESPONSE)) { if (pe[port].hard_reset_counter <= N_HARD_RESET_COUNT) - set_state_pe(port, PE_SRC_HARD_RESET); + pe_set_hard_reset(port); else if (PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION)) set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); else @@ -2058,12 +2660,17 @@ static void pe_src_send_capabilities_run(int port) * Transition to the PE_SRC_Hard_Reset state when: * 1) The SenderResponseTimer times out. */ - if (get_time().val > pe[port].sender_response_timer) { - set_state_pe(port, PE_SRC_HARD_RESET); + if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) { + pe_set_hard_reset(port); return; } } +static void pe_src_send_capabilities_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + /** * PE_SRC_Negotiate_Capability */ @@ -2080,6 +2687,7 @@ static void pe_src_negotiate_capability_entry(int port) * Evaluate the Request from the Attached Sink */ + dpm_evaluate_request_rdo(port, payload); /* * Transition to the PE_SRC_Capability_Response state when: * 1) The Request cannot be met. @@ -2105,17 +2713,13 @@ static void pe_src_transition_supply_entry(int port) { print_current_state(port); - /* Transition Power Supply */ - pd_transition_voltage(pe[port].requested_idx); - /* Send a GotoMin Message or otherwise an Accept Message */ if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) { PE_CLR_FLAG(port, PE_FLAGS_ACCEPT); - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT); } else { - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_GOTO_MIN); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GOTO_MIN); } - } static void pe_src_transition_supply_run(int port) @@ -2144,45 +2748,66 @@ static void pe_src_transition_supply_run(int port) if (PE_CHK_FLAG(port, PE_FLAGS_PS_READY)) { PE_CLR_FLAG(port, PE_FLAGS_PS_READY); - /* NOTE: Second pass through this code block */ - /* Explicit Contract is now in place */ - pe_set_explicit_contract(port); /* * Set first message flag to trigger a wait and add - * jitter delay when operating in PD2.0 mode. + * jitter delay when operating in PD2.0 mode. Skip + * if we already have a contract. */ - PE_SET_FLAG(port, PE_FLAGS_FIRST_MSG); + if (!pe_is_explicit_contract(port)) { + PE_SET_FLAG(port, PE_FLAGS_FIRST_MSG); + pd_timer_disable(port, + PE_TIMER_WAIT_AND_ADD_JITTER); + } + + /* NOTE: Second pass through this code block */ + /* Explicit Contract is now in place */ + pe_set_explicit_contract(port); /* * Setup to get Device Policy Manager to request * Source Capabilities, if needed, for possible - * PR_Swap + * PR_Swap. Get the number directly to avoid re-probing + * if the partner generated an error and left -1 for the + * count. */ - if (pd_get_src_cap_cnt(port) == 0) + if (pe[port].src_cap_cnt == 0) pd_dpm_request(port, DPM_REQUEST_GET_SRC_CAPS); set_state_pe(port, PE_SRC_READY); } else { /* NOTE: First pass through this code block */ - /* Send PS_RDY message */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PS_RDY); - PE_SET_FLAG(port, PE_FLAGS_PS_READY); + /* Wait for tSrcTransition before changing supply. */ + pd_timer_enable(port, PE_TIMER_SRC_TRANSITION, + PD_T_SRC_TRANSITION); } return; } + if (pd_timer_is_expired(port, PE_TIMER_SRC_TRANSITION)) { + pd_timer_disable(port, PE_TIMER_SRC_TRANSITION); + /* Transition power supply and send PS_RDY. */ + pd_transition_voltage(pe[port].requested_idx); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PS_RDY); + PE_SET_FLAG(port, PE_FLAGS_PS_READY); + } + /* * Transition to the PE_SRC_Hard_Reset state when: * 1) A Protocol Error occurs. */ if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); - set_state_pe(port, PE_SRC_HARD_RESET); + pe_set_hard_reset(port); } } +static void pe_src_transition_supply_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_SRC_TRANSITION); +} + /* * Transitions state after receiving a Not Supported extended message. Under * appropriate conditions, transitions to a PE_{SRC,SNK}_Chunk_Received. @@ -2192,13 +2817,13 @@ static void extended_message_not_supported(int port, uint32_t *payload) uint16_t ext_header = GET_EXT_HEADER(*payload); if (IS_ENABLED(CONFIG_USB_PD_REV30) && - !IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES) && - PD_EXT_HEADER_CHUNKED(ext_header) && - PD_EXT_HEADER_DATA_SIZE(ext_header) > - PD_MAX_EXTENDED_MSG_CHUNK_LEN) { - set_state_pe(port, - pe[port].power_role == PD_ROLE_SOURCE ? - PE_SRC_CHUNK_RECEIVED : PE_SNK_CHUNK_RECEIVED); + !IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES) && + PD_EXT_HEADER_CHUNKED(ext_header) && + PD_EXT_HEADER_DATA_SIZE(ext_header) > + PD_MAX_EXTENDED_MSG_CHUNK_LEN) { + set_state_pe(port, pe[port].power_role == PD_ROLE_SOURCE ? + PE_SRC_CHUNK_RECEIVED : + PE_SNK_CHUNK_RECEIVED); return; } @@ -2213,7 +2838,11 @@ static void pe_src_ready_entry(int port) print_current_state(port); /* Ensure any message send flags are cleaned up */ - PE_CLR_FLAG(port, PE_FLAGS_READY_CLR); + PE_CLR_MASK(port, PE_MASK_READY_CLR); + + /* If configured, clear any stale hard reset events */ + if (IS_ENABLED(CONFIG_USB_PD_CLEAR_HARD_RESET_STATUS)) + pd_clear_events(port, PD_STATUS_EVENT_HARD_RESET); /* Clear DPM Current Request */ pe[port].dpm_curr_request = 0; @@ -2227,15 +2856,6 @@ static void pe_src_ready_entry(int port) static void pe_src_ready_run(int port) { - /* - * Don't delay handling a hard reset from the device policy manager. - */ - if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_HARD_RESET_SEND)) { - pe_set_dpm_curr_request(port, DPM_REQUEST_HARD_RESET_SEND); - set_state_pe(port, PE_SRC_HARD_RESET); - return; - } - /* * Handle incoming messages before discovery and DPMs other than hard * reset @@ -2258,7 +2878,7 @@ static void pe_src_ready_run(int port) case PD_EXT_GET_BATTERY_STATUS: set_state_pe(port, PE_GIVE_BATTERY_STATUS); break; -#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES && CONFIG_BATTERY*/ +#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES && CONFIG_BATTERY */ default: extended_message_not_supported(port, payload); } @@ -2273,19 +2893,25 @@ static void pe_src_ready_run(int port) case PD_DATA_SINK_CAP: break; case PD_DATA_VENDOR_DEF: - if (PD_HEADER_TYPE(rx_emsg[port].header) == - PD_DATA_VENDOR_DEF) { - if (PD_VDO_SVDM(*payload)) { - set_state_pe(port, - PE_VDM_RESPONSE); - } else - set_state_pe(port, - PE_HANDLE_CUSTOM_VDM_REQUEST); - } + if (PD_VDO_SVDM(*payload)) + set_state_pe(port, PE_VDM_RESPONSE); + /* The TCPM does not support any unstructured + * VDMs. For PD 3.x, send Not Supported. For + * PD 2.0, ignore. + */ + else if (prl_get_rev(port, TCPCI_MSG_SOP) > + PD_REV20) + set_state_pe(port, + PE_SEND_NOT_SUPPORTED); return; case PD_DATA_BIST: set_state_pe(port, PE_BIST_TX); return; +#ifdef CONFIG_USB_PD_REV30 + case PD_DATA_ALERT: + set_state_pe(port, PE_ALERT_RECEIVED); + return; +#endif /* CONFIG_USB_PD_REV30 */ default: set_state_pe(port, PE_SEND_NOT_SUPPORTED); return; @@ -2310,12 +2936,12 @@ static void pe_src_ready_run(int port) break; case PD_CTRL_PR_SWAP: set_state_pe(port, - PE_PRS_SRC_SNK_EVALUATE_SWAP); + PE_PRS_SRC_SNK_EVALUATE_SWAP); return; case PD_CTRL_DR_SWAP: if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION)) { - set_state_pe(port, PE_SRC_HARD_RESET); + pe_set_hard_reset(port); return; } @@ -2324,10 +2950,10 @@ static void pe_src_ready_run(int port) case PD_CTRL_VCONN_SWAP: if (IS_ENABLED(CONFIG_USBC_VCONN)) set_state_pe(port, - PE_VCS_EVALUATE_SWAP); + PE_VCS_EVALUATE_SWAP); else set_state_pe(port, - PE_SEND_NOT_SUPPORTED); + PE_SEND_NOT_SUPPORTED); return; /* * USB PD 3.0 6.8.1: @@ -2338,13 +2964,33 @@ static void pe_src_ready_run(int port) case PD_CTRL_REJECT: case PD_CTRL_WAIT: case PD_CTRL_PS_RDY: - pe_send_soft_reset(port, - PD_HEADER_GET_SOP(rx_emsg[port].header)); + pe_send_soft_reset( + port, PD_HEADER_GET_SOP( + rx_emsg[port].header)); return; - /* - * Receiving an unknown or unsupported message - * shall be responded to with a not supported message. - */ +#ifdef CONFIG_USB_PD_DATA_RESET_MSG + case PD_CTRL_DATA_RESET: + if (pe[port].data_role == PD_ROLE_DFP) + set_state_pe( + port, + PE_DDR_DATA_RESET_RECEIVED); + else + set_state_pe( + port, + PE_UDR_DATA_RESET_RECEIVED); + return; +#endif /* CONFIG_USB_PD_DATA_RESET_MSG */ +#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES + case PD_CTRL_GET_STATUS: + set_state_pe(port, PE_GIVE_STATUS); + return; +#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ + /* + * Receiving an unknown or unsupported message + * shall be responded to with a not supported + * message. + */ + default: set_state_pe(port, PE_SEND_NOT_SUPPORTED); return; @@ -2366,91 +3012,40 @@ static void pe_src_ready_run(int port) } if (PE_CHK_FLAG(port, PE_FLAGS_WAITING_PR_SWAP) && - get_time().val > pe[port].pr_swap_wait_timer) { + pd_timer_is_expired(port, PE_TIMER_PR_SWAP_WAIT)) { PE_CLR_FLAG(port, PE_FLAGS_WAITING_PR_SWAP); PE_SET_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP); } - if (pe[port].wait_and_add_jitter_timer == TIMER_DISABLED || - get_time().val > pe[port].wait_and_add_jitter_timer) { - + if (pd_timer_is_disabled(port, PE_TIMER_WAIT_AND_ADD_JITTER) || + pd_timer_is_expired(port, PE_TIMER_WAIT_AND_ADD_JITTER)) { PE_CLR_FLAG(port, PE_FLAGS_FIRST_MSG); - pe[port].wait_and_add_jitter_timer = TIMER_DISABLED; - - /* - * Attempt discovery if possible, and return if state was - * changed for that discovery. - */ - if (pe_attempt_port_discovery(port)) - return; + pd_timer_disable(port, PE_TIMER_WAIT_AND_ADD_JITTER); /* * Handle Device Policy Manager Requests */ + if (source_dpm_requests(port)) + return; /* - * Ignore sink specific request: - * DPM_REQUEST_NEW_POWER_LEVEL - * DPM_REQUEST_SOURCE_CAP + * Attempt discovery if possible, and return if state was + * changed for that discovery. */ - - PE_CLR_DPM_REQUEST(port, DPM_REQUEST_NEW_POWER_LEVEL | - DPM_REQUEST_SOURCE_CAP); - - if (pe[port].dpm_request) { - uint32_t dpm_request = pe[port].dpm_request; - - PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); - - if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_DR_SWAP)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_DR_SWAP); - if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION)) - set_state_pe(port, PE_SRC_HARD_RESET); - else - set_state_pe(port, PE_DRS_SEND_SWAP); - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_PR_SWAP)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_PR_SWAP); - set_state_pe(port, PE_PRS_SRC_SNK_SEND_SWAP); - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_GOTO_MIN)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_GOTO_MIN); - set_state_pe(port, PE_SRC_TRANSITION_SUPPLY); - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_SRC_CAP_CHANGE)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_SRC_CAP_CHANGE); - set_state_pe(port, PE_SRC_SEND_CAPABILITIES); - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_GET_SRC_CAPS)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_GET_SRC_CAPS); - set_state_pe(port, PE_DR_SRC_GET_SOURCE_CAP); - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_SEND_PING)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_SEND_PING); - set_state_pe(port, PE_SRC_PING); - } else if (!common_src_snk_dpm_requests(port)) { - CPRINTF("Unhandled DPM Request %x received\n", - dpm_request); - PE_CLR_DPM_REQUEST(port, dpm_request); - PE_CLR_FLAG(port, - PE_FLAGS_LOCALLY_INITIATED_AMS); - } - + if (pe_attempt_port_discovery(port)) return; - } - /* No DPM requests; attempt mode entry/exit if needed */ - dpm_run(port); + /* Inform DPM state machine that PE is set for messages */ + dpm_set_pe_ready(port, true); } } +static void pe_src_ready_exit(int port) +{ + /* Inform DPM state machine that PE is in ready state */ + dpm_set_pe_ready(port, false); +} + /** * PE_SRC_Disabled */ @@ -2458,7 +3053,8 @@ static void pe_src_disabled_entry(int port) { print_current_state(port); - if ((pe[port].vpd_vdo >= 0) && VPD_VDO_CTS(pe[port].vpd_vdo)) { + if ((get_usb_pd_cable_type(port) == IDH_PTYPE_VPD) && + is_vpd_ct_supported(port)) { /* * Inform the Device Policy Manager that a Charge-Through VCONN * Powered Device was detected. @@ -2466,6 +3062,9 @@ static void pe_src_disabled_entry(int port) tc_ctvpd_detected(port); } + if (pd_get_power_role(port) == PD_ROLE_SOURCE) + dpm_add_non_pd_sink(port); + /* * Unresponsive to USB Power Delivery messaging, but not to Hard Reset * Signaling. See pe_got_hard_reset @@ -2481,7 +3080,7 @@ static void pe_src_capability_response_entry(int port) /* NOTE: Wait messaging should be implemented. */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT); } static void pe_src_capability_response_run(int port) @@ -2539,15 +3138,13 @@ static void pe_src_hard_reset_entry(int port) pe[port].hard_reset_counter++; /* Start NoResponseTimer */ - pe[port].no_response_timer = get_time().val + PD_T_NO_RESPONSE; + pd_timer_enable(port, PE_TIMER_NO_RESPONSE, PD_T_NO_RESPONSE); /* Start PSHardResetTimer */ - pe[port].ps_hard_reset_timer = get_time().val + PD_T_PS_HARD_RESET; + pd_timer_enable(port, PE_TIMER_PS_HARD_RESET, PD_T_PS_HARD_RESET); /* Clear error flags */ - PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED | - PE_FLAGS_PROTOCOL_ERROR | - PE_FLAGS_VDM_REQUEST_BUSY); + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); } static void pe_src_hard_reset_run(int port) @@ -2556,10 +3153,15 @@ static void pe_src_hard_reset_run(int port) * Transition to the PE_SRC_Transition_to_default state when: * 1) The PSHardResetTimer times out. */ - if (get_time().val > pe[port].ps_hard_reset_timer) + if (pd_timer_is_expired(port, PE_TIMER_PS_HARD_RESET)) set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT); } +static void pe_src_hard_reset_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_PS_HARD_RESET); +} + /** * PE_SRC_Hard_Reset_Received */ @@ -2568,10 +3170,10 @@ static void pe_src_hard_reset_received_entry(int port) print_current_state(port); /* Start NoResponseTimer */ - pe[port].no_response_timer = get_time().val + PD_T_NO_RESPONSE; + pd_timer_enable(port, PE_TIMER_NO_RESPONSE, PD_T_NO_RESPONSE); /* Start PSHardResetTimer */ - pe[port].ps_hard_reset_timer = get_time().val + PD_T_PS_HARD_RESET; + pd_timer_enable(port, PE_TIMER_PS_HARD_RESET, PD_T_PS_HARD_RESET); } static void pe_src_hard_reset_received_run(int port) @@ -2580,10 +3182,15 @@ static void pe_src_hard_reset_received_run(int port) * Transition to the PE_SRC_Transition_to_default state when: * 1) The PSHardResetTimer times out. */ - if (get_time().val > pe[port].ps_hard_reset_timer) + if (pd_timer_is_expired(port, PE_TIMER_PS_HARD_RESET)) set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT); } +static void pe_src_hard_reset_received_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_PS_HARD_RESET); +} + /** * PE_SRC_Transition_To_Default */ @@ -2592,7 +3199,7 @@ static void pe_src_transition_to_default_entry(int port) print_current_state(port); /* Reset flags */ - pe[port].flags = 0; + memset(&pe[port].flags_a, 0, sizeof(pe[port].flags_a)); /* Reset DPM Request */ pe[port].dpm_request = 0; @@ -2629,7 +3236,7 @@ static void pe_snk_startup_entry(int port) print_current_state(port); /* Reset the protocol layer */ - prl_reset(port); + prl_reset_soft(port); /* Set initial data role */ pe[port].data_role = pd_get_data_role(port); @@ -2640,17 +3247,47 @@ static void pe_snk_startup_entry(int port) /* Invalidate explicit contract */ pe_invalidate_explicit_contract(port); + /* Clear any pending PD events */ + pe_clear_ado(port); + if (PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE); + /* + * Protocol layer reset clears the message IDs for all SOP + * types. Indicate that a SOP' soft reset is required before any + * other messages are sent to the cable. + * + * Note that other paths into this state are for the initial + * connection and for a hard reset. In both cases the cable + * should also automatically clear the message IDs so don't + * generate an SOP' soft reset for those cases. Sending + * unnecessary SOP' soft resets causes bad behavior with + * some devices. See b/179325862. + */ + pd_dpm_request(port, DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND); + + /* + * Some port partners may violate spec and attempt to + * communicate with the cable after power role swaps, despite + * not being Vconn source. Disable our SOP' receiving here to + * avoid GoodCRC-ing any erroneous cable probes, and re-enable + * after our contract is in place. + */ + if (tc_is_vconn_src(port)) + tcpm_sop_prime_enable(port, false); + + dpm_remove_sink(port); } else { /* * Set DiscoverIdentityTimer to trigger when we enter * snk_ready for the first time. */ - pe[port].discover_identity_timer = get_time().val; + pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY, 0); - /* Clear port discovery flags */ + /* Clear port discovery/mode flags */ pd_dfp_discovery_init(port); + pd_dfp_mode_init(port); + dpm_init(port); pe[port].discover_identity_counter = 0; /* Reset dr swap attempt counter */ @@ -2665,6 +3302,25 @@ static void pe_snk_startup_entry(int port) PE_SET_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP); PE_SET_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON); } + + /* + * Request sink caps for FRS, output power consideration, or reporting + * to the AP through host commands. + * + * On entry to the PE_SNK_Ready state if the Sink supports Fast Role + * Swap, then the Policy Engine Shall do the following: + * - Send a Get_Sink_Cap Message + */ + if (IS_ENABLED(CONFIG_USB_PD_HOST_CMD) || CONFIG_USB_PD_3A_PORTS > 0 || + IS_ENABLED(CONFIG_USB_PD_FRS)) + pd_dpm_request(port, DPM_REQUEST_GET_SNK_CAPS); + + /* + * Request partner's revision information. The PE_Get_Revision + * state will only send Get_Revision to partners with major + * revision 3.0 + */ + pd_dpm_request(port, DPM_REQUEST_GET_REVISION); } static void pe_snk_startup_run(int port) @@ -2694,7 +3350,7 @@ static void pe_snk_discovery_run(int port) * Transition to the PE_SNK_Wait_for_Capabilities state when: * 1) VBUS has been detected */ - if (pd_is_vbus_present(port)) + if (!pd_check_vbus_level(port, VBUS_REMOVED)) set_state_pe(port, PE_SNK_WAIT_FOR_CAPABILITIES); } @@ -2706,7 +3362,7 @@ static void pe_snk_wait_for_capabilities_entry(int port) print_current_state(port); /* Initialize and start the SinkWaitCapTimer */ - pe[port].timeout = get_time().val + PD_T_SINK_WAIT_CAP; + pd_timer_enable(port, PE_TIMER_TIMEOUT, PD_T_SINK_WAIT_CAP); } static void pe_snk_wait_for_capabilities_run(int port) @@ -2714,6 +3370,7 @@ static void pe_snk_wait_for_capabilities_run(int port) uint8_t type; uint8_t cnt; uint8_t ext; + uint32_t *payload; /* * Transition to the PE_SNK_Evaluate_Capability state when: @@ -2725,20 +3382,39 @@ static void pe_snk_wait_for_capabilities_run(int port) type = PD_HEADER_TYPE(rx_emsg[port].header); cnt = PD_HEADER_CNT(rx_emsg[port].header); ext = PD_HEADER_EXT(rx_emsg[port].header); + payload = (uint32_t *)rx_emsg[port].buf; if ((ext == 0) && (cnt > 0) && (type == PD_DATA_SOURCE_CAP)) { set_state_pe(port, PE_SNK_EVALUATE_CAPABILITY); return; + } else if (ext > 0) { + switch (type) { +#ifdef CONFIG_USB_PD_EPR + case PD_EXT_EPR_SOURCE_CAP: + if (!pe_snk_in_epr_mode(port)) + break; + set_state_pe(port, PE_SNK_EVALUATE_CAPABILITY); + break; +#endif /* CONFIG_USB_PD_EPR */ + default: + extended_message_not_supported(port, payload); + } + return; } } /* When the SinkWaitCapTimer times out, perform a Hard Reset. */ - if (get_time().val > pe[port].timeout) { + if (pd_timer_is_expired(port, PE_TIMER_TIMEOUT)) { PE_SET_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT); - set_state_pe(port, PE_SNK_HARD_RESET); + pe_set_hard_reset(port); } } +static void pe_snk_wait_for_capabilities_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_TIMEOUT); +} + /** * PE_SNK_Evaluate_Capability State */ @@ -2753,26 +3429,38 @@ static void pe_snk_evaluate_capability_entry(int port) pe[port].hard_reset_counter = 0; /* Set to highest revision supported by both ports. */ - prl_set_rev(port, TCPC_TX_SOP, - MIN(PD_REVISION, PD_HEADER_REV(rx_emsg[port].header))); + prl_set_rev(port, TCPCI_MSG_SOP, + MIN(PD_REVISION, PD_HEADER_REV(rx_emsg[port].header))); - /* - * If port partner runs PD 2.0, cable communication must - * also be PD 2.0 - */ - if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20) - prl_set_rev(port, TCPC_TX_SOP_PRIME, PD_REV20); + init_cable_rev(port); - pd_set_src_caps(port, num, pdo); + /* Parse source caps if they have changed */ + if (pe[port].src_cap_cnt != num || + memcmp(pdo, pe[port].src_caps, num << 2)) { + /* + * If port policy preference is to be a power role source, + * then request a power role swap. If we'd previously queued a + * PR swap but can now charge from this device, clear it. + */ + if (!pd_can_charge_from_device(port, num, pdo)) + pd_request_power_swap(port); + else + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP); + } - /* src cap 0 should be fixed PDO */ - pe_update_pdo_flags(port, pdo[0]); + pe_update_src_pdo_flags(port, num, pdo); + pd_set_src_caps(port, num, pdo); /* Evaluate the options based on supplied capabilities */ pd_process_source_cap(port, pe[port].src_cap_cnt, pe[port].src_caps); /* Device Policy Response Received */ set_state_pe(port, PE_SNK_SELECT_CAPABILITY); + +#ifdef HAS_TASK_DPS + /* Wake DPS task to evaluate the SrcCaps */ + task_wake(TASK_ID_DPS); +#endif } /** @@ -2791,11 +3479,31 @@ static void pe_snk_select_capability_entry(int port) tc_pd_connection(port, 1); } +static void pe_snk_apply_psnkstdby(int port) +{ + uint32_t mv = pd_get_requested_voltage(port); + uint32_t high; + + /* + * Apply 2.5W ceiling during transition. We need choose the larger of + * the current input voltage and the new PDO voltage because during a + * transition, both voltages can be applied to the device. If the + * current source isn't PD, we don't need to care about drawing more + * than pSnkStdby. Thus, it's not considered (in the else clause). + */ + if (charge_manager_get_supplier() == CHARGE_SUPPLIER_PD) + high = MAX(charge_manager_get_charger_voltage(), mv); + else + high = mv; + charge_manager_force_ceil( + port, high > 0 ? PD_SNK_STDBY_MW * 1000 / high : PD_MIN_MA); +} + static void pe_snk_select_capability_run(int port) { uint8_t type; uint8_t cnt; - enum tcpm_transmit_type sop; + enum tcpci_msg_type sop; enum pe_msg_check msg_check; /* @@ -2815,7 +3523,7 @@ static void pe_snk_select_capability_run(int port) * 2) SE_SNK_READY: goes back to SNK Ready */ if (get_last_state_pe(port) == PE_SNK_EVALUATE_CAPABILITY) - pe_send_soft_reset(port, TCPC_TX_SOP); + pe_send_soft_reset(port, TCPCI_MSG_SOP); else set_state_pe(port, PE_SNK_READY); return; @@ -2855,25 +3563,23 @@ static void pe_snk_select_capability_run(int port) /* explicit contract is now in place */ pe_set_explicit_contract(port); + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) + pe_snk_apply_psnkstdby(port); + set_state_pe(port, PE_SNK_TRANSITION_SINK); - /* - * Setup to get Device Policy Manager to - * request Sink Capabilities for possible FRS - */ - if (IS_ENABLED(CONFIG_USB_PD_FRS)) - pd_dpm_request(port, - DPM_REQUEST_GET_SNK_CAPS); return; } /* * Reject or Wait Message Received */ else if (type == PD_CTRL_REJECT || - type == PD_CTRL_WAIT) { + type == PD_CTRL_WAIT) { if (type == PD_CTRL_WAIT) PE_SET_FLAG(port, PE_FLAGS_WAIT); + pd_timer_disable(port, PE_TIMER_SINK_REQUEST); + /* * We had a previous explicit contract, so * transition to PE_SNK_Ready @@ -2886,7 +3592,8 @@ static void pe_snk_select_capability_run(int port) * to PE_SNK_Wait_For_Capabilities */ else - set_state_pe(port, + set_state_pe( + port, PE_SNK_WAIT_FOR_CAPABILITIES); return; } @@ -2910,8 +3617,13 @@ static void pe_snk_select_capability_run(int port) } /* SenderResponsetimer timeout */ - if (get_time().val > pe[port].sender_response_timer) - set_state_pe(port, PE_SNK_HARD_RESET); + if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) + pe_set_hard_reset(port); +} + +void pe_snk_select_capability_exit(int port) +{ + pe_sender_response_msg_exit(port); } /** @@ -2922,7 +3634,7 @@ static void pe_snk_transition_sink_entry(int port) print_current_state(port); /* Initialize and run PSTransitionTimer */ - pe[port].ps_transition_timer = get_time().val + PD_T_PS_TRANSITION; + pd_timer_enable(port, PE_TIMER_PS_TRANSITION, PD_T_PS_TRANSITION); } static void pe_snk_transition_sink_run(int port) @@ -2942,57 +3654,86 @@ static void pe_snk_transition_sink_run(int port) * PS_RDY message received */ if ((PD_HEADER_CNT(rx_emsg[port].header) == 0) && - (PD_HEADER_TYPE(rx_emsg[port].header) == - PD_CTRL_PS_RDY)) { + (PD_HEADER_TYPE(rx_emsg[port].header) == PD_CTRL_PS_RDY)) { /* * Set first message flag to trigger a wait and add * jitter delay when operating in PD2.0 mode. */ PE_SET_FLAG(port, PE_FLAGS_FIRST_MSG); + pd_timer_disable(port, PE_TIMER_WAIT_AND_ADD_JITTER); + + /* + * If we've successfully completed our new power + * contract, ensure SOP' communication is enabled before + * entering PE_SNK_READY. It may have been disabled + * during a power role swap to avoid interoperability + * issues with out-of-spec partners. + */ + if (tc_is_vconn_src(port)) + tcpm_sop_prime_enable(port, true); + + /* + * Evaluate port's sink caps for FRS current, if + * already available + */ + if (pd_get_snk_cap_cnt(port) > 0) + dpm_evaluate_sink_fixed_pdo( + port, *pd_get_snk_caps(port)); set_state_pe(port, PE_SNK_READY); - return; + } else { + /* + * Protocol Error + */ + pe_set_hard_reset(port); } - - /* - * Protocol Error - */ - set_state_pe(port, PE_SNK_HARD_RESET); + return; } /* * Timeout will lead to a Hard Reset */ - if (get_time().val > pe[port].ps_transition_timer && - pe[port].hard_reset_counter <= N_HARD_RESET_COUNT) { + if (pd_timer_is_expired(port, PE_TIMER_PS_TRANSITION) && + pe[port].hard_reset_counter <= N_HARD_RESET_COUNT) { PE_SET_FLAG(port, PE_FLAGS_PS_TRANSITION_TIMEOUT); - set_state_pe(port, PE_SNK_HARD_RESET); + pe_set_hard_reset(port); } } static void pe_snk_transition_sink_exit(int port) { /* Transition Sink's power supply to the new power level */ - pd_set_input_current_limit(port, - pe[port].curr_limit, pe[port].supply_voltage); + pd_set_input_current_limit(port, pe[port].curr_limit, + pe[port].supply_voltage); if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) /* Set ceiling based on what's negotiated */ - charge_manager_set_ceil(port, - CEIL_REQUESTOR_PD, pe[port].curr_limit); -} + charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, + pe[port].curr_limit); + + pd_timer_disable(port, PE_TIMER_PS_TRANSITION); + if (IS_ENABLED(CONFIG_USB_PD_DPS)) + if (charge_manager_get_active_charge_port() == port) + dps_update_stabilized_time(port); +} /** * PE_SNK_Ready State */ static void pe_snk_ready_entry(int port) { - print_current_state(port); + if (get_last_state_pe(port) != PE_SNK_EPR_KEEP_ALIVE) { + print_current_state(port); + } /* Ensure any message send flags are cleaned up */ - PE_CLR_FLAG(port, PE_FLAGS_READY_CLR); + PE_CLR_MASK(port, PE_MASK_READY_CLR); + + /* If configured, clear any stale hard reset events */ + if (IS_ENABLED(CONFIG_USB_PD_CLEAR_HARD_RESET_STATUS)) + pd_clear_events(port, PD_STATUS_EVENT_HARD_RESET); /* Clear DPM Current Request */ pe[port].dpm_curr_request = 0; @@ -3004,10 +3745,7 @@ static void pe_snk_ready_entry(int port) */ if (PE_CHK_FLAG(port, PE_FLAGS_WAIT)) { PE_CLR_FLAG(port, PE_FLAGS_WAIT); - pe[port].sink_request_timer = - get_time().val + PD_T_SINK_REQUEST; - } else { - pe[port].sink_request_timer = TIMER_DISABLED; + pd_timer_enable(port, PE_TIMER_SINK_REQUEST, PD_T_SINK_REQUEST); } /* @@ -3015,19 +3753,18 @@ static void pe_snk_ready_entry(int port) * have been sent since enter this state. */ pe_update_wait_and_add_jitter_timer(port); + + if (IS_ENABLED(CONFIG_USB_PD_EPR)) { + if (pe_snk_in_epr_mode(port)) + pd_timer_enable(port, PE_TIMER_SINK_EPR_KEEP_ALIVE, + PD_T_SINK_EPR_KEEP_ALIVE); + else if (!PE_CHK_FLAG(port, PE_FLAGS_EPR_EXPLICIT_EXIT)) + pd_dpm_request(port, DPM_REQUEST_EPR_MODE_ENTRY); + } } static void pe_snk_ready_run(int port) { - /* - * Don't delay handling a hard reset from the device policy manager. - */ - if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_HARD_RESET_SEND)) { - pe_set_dpm_curr_request(port, DPM_REQUEST_HARD_RESET_SEND); - set_state_pe(port, PE_SNK_HARD_RESET); - return; - } - /* * Handle incoming messages before discovery and DPMs other than hard * reset @@ -3050,6 +3787,13 @@ static void pe_snk_ready_run(int port) case PD_EXT_GET_BATTERY_STATUS: set_state_pe(port, PE_GIVE_BATTERY_STATUS); break; +#ifdef CONFIG_USB_PD_EPR + case PD_EXT_EPR_SOURCE_CAP: + if (!pe_snk_in_epr_mode(port)) + break; + set_state_pe(port, PE_SNK_EVALUATE_CAPABILITY); + break; +#endif /* CONFIG_USB_PD_EPR */ #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES && CONFIG_BATTERY */ default: extended_message_not_supported(port, payload); @@ -3060,27 +3804,43 @@ static void pe_snk_ready_run(int port) else if (cnt > 0) { switch (type) { case PD_DATA_SOURCE_CAP: - set_state_pe(port, - PE_SNK_EVALUATE_CAPABILITY); - break; + set_state_pe(port, PE_SNK_EVALUATE_CAPABILITY); + return; case PD_DATA_VENDOR_DEF: - if (PD_HEADER_TYPE(rx_emsg[port].header) == - PD_DATA_VENDOR_DEF) { - if (PD_VDO_SVDM(*payload)) - set_state_pe(port, - PE_VDM_RESPONSE); - else - set_state_pe(port, - PE_HANDLE_CUSTOM_VDM_REQUEST); - } - break; + if (PD_VDO_SVDM(*payload)) + set_state_pe(port, PE_VDM_RESPONSE); + /* The TCPM does not support any unstructured + * VDMs. For PD 3.x, send Not Supported. For + * PD 2.0, ignore. + */ + else if (prl_get_rev(port, TCPCI_MSG_SOP) > + PD_REV20) + set_state_pe(port, + PE_SEND_NOT_SUPPORTED); + return; case PD_DATA_BIST: set_state_pe(port, PE_BIST_TX); - break; + return; +#ifdef CONFIG_USB_PD_REV30 + case PD_DATA_ALERT: + set_state_pe(port, PE_ALERT_RECEIVED); + return; +#ifdef CONFIG_USB_PD_EPR + case PD_DATA_EPR_MODE: + struct eprmdo *mdo = (void *)payload; + + if (mdo->action == PD_EPRMDO_ACTION_EXIT) { + set_state_pe( + port, + PE_SNK_EPR_MODE_EXIT_RECEIVED); + } + return; +#endif /* CONFIG_USB_PD_EPR */ +#endif /* CONFIG_USB_PD_REV30 */ default: set_state_pe(port, PE_SEND_NOT_SUPPORTED); + return; } - return; } /* Control Messages */ else { @@ -3102,23 +3862,40 @@ static void pe_snk_ready_run(int port) return; case PD_CTRL_PR_SWAP: set_state_pe(port, - PE_PRS_SNK_SRC_EVALUATE_SWAP); + PE_PRS_SNK_SRC_EVALUATE_SWAP); return; case PD_CTRL_DR_SWAP: if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION)) - set_state_pe(port, PE_SNK_HARD_RESET); + pe_set_hard_reset(port); else set_state_pe(port, - PE_DRS_EVALUATE_SWAP); + PE_DRS_EVALUATE_SWAP); return; case PD_CTRL_VCONN_SWAP: if (IS_ENABLED(CONFIG_USBC_VCONN)) set_state_pe(port, - PE_VCS_EVALUATE_SWAP); + PE_VCS_EVALUATE_SWAP); else set_state_pe(port, - PE_SEND_NOT_SUPPORTED); + PE_SEND_NOT_SUPPORTED); + return; +#ifdef CONFIG_USB_PD_DATA_RESET_MSG + case PD_CTRL_DATA_RESET: + if (pe[port].data_role == PD_ROLE_DFP) + set_state_pe( + port, + PE_DDR_DATA_RESET_RECEIVED); + else + set_state_pe( + port, + PE_UDR_DATA_RESET_RECEIVED); + return; +#endif /* CONFIG_USB_PD_DATA_RESET_MSG */ +#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES + case PD_CTRL_GET_STATUS: + set_state_pe(port, PE_GIVE_STATUS); return; +#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ case PD_CTRL_NOT_SUPPORTED: /* Do nothing */ break; @@ -3131,8 +3908,9 @@ static void pe_snk_ready_run(int port) case PD_CTRL_REJECT: case PD_CTRL_WAIT: case PD_CTRL_PS_RDY: - pe_send_soft_reset(port, - PD_HEADER_GET_SOP(rx_emsg[port].header)); + pe_send_soft_reset( + port, PD_HEADER_GET_SOP( + rx_emsg[port].header)); return; /* * Receiving an unknown or unsupported message @@ -3158,84 +3936,47 @@ static void pe_snk_ready_run(int port) return; } - if (pe[port].wait_and_add_jitter_timer == TIMER_DISABLED || - get_time().val > pe[port].wait_and_add_jitter_timer) { + if (pd_timer_is_disabled(port, PE_TIMER_WAIT_AND_ADD_JITTER) || + pd_timer_is_expired(port, PE_TIMER_WAIT_AND_ADD_JITTER)) { PE_CLR_FLAG(port, PE_FLAGS_FIRST_MSG); - pe[port].wait_and_add_jitter_timer = TIMER_DISABLED; + pd_timer_disable(port, PE_TIMER_WAIT_AND_ADD_JITTER); - if (get_time().val > pe[port].sink_request_timer) { + if (pd_timer_is_expired(port, PE_TIMER_SINK_REQUEST)) { + pd_timer_disable(port, PE_TIMER_SINK_REQUEST); set_state_pe(port, PE_SNK_SELECT_CAPABILITY); return; } /* - * Attempt discovery if possible, and return if state was - * changed for that discovery. + * Handle Device Policy Manager Requests */ - if (pe_attempt_port_discovery(port)) + if (sink_dpm_requests(port)) return; /* - * Handle Device Policy Manager Requests - */ - /* - * Ignore source specific requests: - * DPM_REQUEST_GOTO_MIN - * DPM_REQUEST_SRC_CAP_CHANGE, - * DPM_REQUEST_SEND_PING + * Attempt discovery if possible, and return if state was + * changed for that discovery. */ - PE_CLR_DPM_REQUEST(port, DPM_REQUEST_GOTO_MIN | - DPM_REQUEST_SRC_CAP_CHANGE | - DPM_REQUEST_SEND_PING); - - if (pe[port].dpm_request) { - uint32_t dpm_request = pe[port].dpm_request; - - PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); + if (pe_attempt_port_discovery(port)) + return; - if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_DR_SWAP)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_DR_SWAP); - if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION)) - set_state_pe(port, PE_SNK_HARD_RESET); - else - set_state_pe(port, PE_DRS_SEND_SWAP); - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_PR_SWAP)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_PR_SWAP); - set_state_pe(port, PE_PRS_SNK_SRC_SEND_SWAP); - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_SOURCE_CAP)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_SOURCE_CAP); - set_state_pe(port, PE_SNK_GET_SOURCE_CAP); - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_NEW_POWER_LEVEL)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_NEW_POWER_LEVEL); - set_state_pe(port, PE_SNK_SELECT_CAPABILITY); - } else if (IS_ENABLED(CONFIG_USB_PD_FRS) && - PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_GET_SNK_CAPS)) { - pe_set_dpm_curr_request(port, - DPM_REQUEST_GET_SNK_CAPS); - set_state_pe(port, PE_DR_SNK_GET_SINK_CAP); - } else if (!common_src_snk_dpm_requests(port)) { - CPRINTF("Unhandled DPM Request %x received\n", - dpm_request); - PE_CLR_DPM_REQUEST(port, dpm_request); - PE_CLR_FLAG(port, - PE_FLAGS_LOCALLY_INITIATED_AMS); - } + /* Inform DPM state machine that PE is set for messages */ + dpm_set_pe_ready(port, true); + if (pd_timer_is_expired(port, PE_TIMER_SINK_EPR_KEEP_ALIVE)) { + set_state_pe(port, PE_SNK_EPR_KEEP_ALIVE); return; } + } +} - /* No DPM requests; attempt mode entry/exit if needed */ - dpm_run(port); +static void pe_snk_ready_exit(int port) +{ + /* Inform DPM state machine that PE is in ready state */ + dpm_set_pe_ready(port, false); + if (IS_ENABLED(CONFIG_USB_PD_EPR) && pe_snk_in_epr_mode(port)) { + pd_timer_disable(port, PE_TIMER_SINK_EPR_KEEP_ALIVE); } } @@ -3244,6 +3985,10 @@ static void pe_snk_ready_run(int port) */ static void pe_snk_hard_reset_entry(int port) { +#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC + int batt_soc; +#endif + print_current_state(port); /* @@ -3252,17 +3997,66 @@ static void pe_snk_hard_reset_entry(int port) * Source is non-responsive. */ if (PE_CHK_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT) && - pe[port].hard_reset_counter > N_HARD_RESET_COUNT) { + pe[port].hard_reset_counter > N_HARD_RESET_COUNT) { + set_state_pe(port, PE_SRC_DISABLED); + return; + } + + /* + * If we're about to kill our active charge port and have no battery to + * supply power, disable the PE layer instead. If we have no battery, + * but we haven't determined our active charge port yet, also avoid + * performing the HardReset. It might be that this port was our active + * charge port. + * + * Note: On systems without batteries (ex. chromeboxes), it's preferable + * to brown out rather than leave the port only semi-functional for a + * customer. For systems which should have a battery, this condition is + * not expected to be encountered by a customer. + */ + if (IS_ENABLED(CONFIG_BATTERY) && (battery_is_present() == BP_NO) && + IS_ENABLED(CONFIG_CHARGE_MANAGER) && + ((port == charge_manager_get_active_charge_port() || + (charge_manager_get_active_charge_port() == CHARGE_PORT_NONE))) && + system_get_reset_flags() & EC_RESET_FLAG_SYSJUMP) { + CPRINTS("C%d: Disabling port to avoid brown out, " + "please reboot EC to enable port again", + port); set_state_pe(port, PE_SRC_DISABLED); + return; + } + +#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC + /* + * If the battery has not met a configured safe level for hard + * resets, set state to PE_SRC_Disabled as a hard + * reset could brown out the board. + * Note this may mean that high-power chargers will stay at + * 15W until a reset is sent, depending on boot timing. + * + * PE_FLAGS_SNK_WAITING_BATT flags will be cleared and + * PE state will be switched to PE_SNK_Startup when + * battery reaches CONFIG_USB_PD_RESET_MIN_BATT_SOC. + * See pe_update_waiting_batt_flag() for more details. + */ + batt_soc = usb_get_battery_soc(); + + if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC || + battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED) { + PE_SET_FLAG(port, PE_FLAGS_SNK_WAITING_BATT); + CPRINTS("C%d: Battery low %d%%! Stay in disabled state " + "until battery level reaches %d%%", + port, batt_soc, CONFIG_USB_PD_RESET_MIN_BATT_SOC); + set_state_pe(port, PE_SRC_DISABLED); + return; } +#endif - PE_CLR_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT | - PE_FLAGS_VDM_REQUEST_NAKED | - PE_FLAGS_PROTOCOL_ERROR | - PE_FLAGS_VDM_REQUEST_BUSY); + PE_CLR_MASK(port, BIT(PE_FLAGS_SNK_WAIT_CAP_TIMEOUT_FN) | + BIT(PE_FLAGS_PROTOCOL_ERROR_FN)); /* Request the generation of Hard Reset Signaling by the PHY Layer */ - pe_prl_execute_hard_reset(port); + prl_execute_hard_reset(port); /* Increment the HardResetCounter */ pe[port].hard_reset_counter++; @@ -3276,11 +4070,11 @@ static void pe_snk_hard_reset_entry(int port) /* Transition Sink's power supply to the new power level */ pd_set_input_current_limit(port, pe[port].curr_limit, - pe[port].supply_voltage); + pe[port].supply_voltage); if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) /* Set ceiling based on what's negotiated */ charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, - pe[port].curr_limit); + pe[port].curr_limit); } } @@ -3303,6 +4097,12 @@ static void pe_snk_transition_to_default_entry(int port) { print_current_state(port); + /* Reset flags */ + memset(&pe[port].flags_a, 0, sizeof(pe[port].flags_a)); + + /* Reset DPM Request */ + pe[port].dpm_request = 0; + /* Inform the TC Layer of Hard Reset */ tc_hard_reset_request(port); } @@ -3310,8 +4110,7 @@ static void pe_snk_transition_to_default_entry(int port) static void pe_snk_transition_to_default_run(int port) { if (PE_CHK_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE)) { - /* PE_SNK_Startup clears all flags */ - + PE_CLR_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE); /* Inform the Protocol Layer that the Hard Reset is complete */ prl_hard_reset_complete(port); set_state_pe(port, PE_SNK_STARTUP); @@ -3327,7 +4126,7 @@ static void pe_snk_get_source_cap_entry(int port) /* Send a Get_Source_Cap Message */ tx_emsg[port].len = 0; - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_GET_SOURCE_CAP); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GET_SOURCE_CAP); } static void pe_snk_get_source_cap_run(int port) @@ -3346,10 +4145,19 @@ static void pe_send_soft_reset_entry(int port) { print_current_state(port); + PE_CLR_FLAG(port, PE_FLAGS_ENTERING_EPR); + PE_CLR_FLAG(port, PE_FLAGS_EPR_EXPLICIT_EXIT); + /* Reset Protocol Layer (softly) */ prl_reset_soft(port); - pe[port].sender_response_timer = TIMER_DISABLED; + pe_sender_response_msg_entry(port); + + /* + * Mark the temporary timer PE_TIMER_TIMEOUT as expired to limit + * to sending a single SoftReset message. + */ + pd_timer_enable(port, PE_TIMER_TIMEOUT, 0); } static void pe_send_soft_reset_run(int port) @@ -3357,23 +4165,42 @@ static void pe_send_soft_reset_run(int port) int type; int cnt; int ext; + enum pe_msg_check msg_check; /* Wait until protocol layer is running */ if (!prl_is_running(port)) return; - if (pe[port].sender_response_timer == TIMER_DISABLED) { + /* + * Protocol layer is running, so need to send a single SoftReset. + * Use temporary timer to act as a flag to keep this as a single + * message send. + */ + if (!pd_timer_is_disabled(port, PE_TIMER_TIMEOUT)) { + pd_timer_disable(port, PE_TIMER_TIMEOUT); + /* * TODO(b/150614211): Soft reset type should match * unexpected incoming message type */ /* Send Soft Reset message */ - send_ctrl_msg(port, - pe[port].soft_reset_sop, PD_CTRL_SOFT_RESET); + send_ctrl_msg(port, pe[port].soft_reset_sop, + PD_CTRL_SOFT_RESET); + + return; + } + + /* + * Check the state of the message sent + */ + msg_check = pe_sender_response_msg_run(port); - /* Initialize and run SenderResponseTimer */ - pe[port].sender_response_timer = - get_time().val + PD_T_SENDER_RESPONSE; + /* + * Handle discarded message + */ + if (msg_check == PE_MSG_DISCARDED) { + pe_set_ready_state(port); + return; } /* @@ -3381,7 +4208,8 @@ static void pe_send_soft_reset_run(int port) * PE_SRC_Send_Capabilities state when: * 1) An Accept Message has been received. */ - if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + if (msg_check == PE_MSG_SENT && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); type = PD_HEADER_TYPE(rx_emsg[port].header); @@ -3391,10 +4219,9 @@ static void pe_send_soft_reset_run(int port) if ((ext == 0) && (cnt == 0) && (type == PD_CTRL_ACCEPT)) { if (pe[port].power_role == PD_ROLE_SINK) set_state_pe(port, - PE_SNK_WAIT_FOR_CAPABILITIES); + PE_SNK_WAIT_FOR_CAPABILITIES); else - set_state_pe(port, - PE_SRC_SEND_CAPABILITIES); + set_state_pe(port, PE_SRC_SEND_CAPABILITIES); return; } } @@ -3403,17 +4230,18 @@ static void pe_send_soft_reset_run(int port) * Transition to PE_SNK_Hard_Reset or PE_SRC_Hard_Reset on Sender * Response Timer Timeout or Protocol Layer or Protocol Error */ - if (get_time().val > pe[port].sender_response_timer || - PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE) || + PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); - - if (pe[port].power_role == PD_ROLE_SINK) - set_state_pe(port, PE_SNK_HARD_RESET); - else - set_state_pe(port, PE_SRC_HARD_RESET); + pe_set_hard_reset(port); return; } +} +static void pe_send_soft_reset_exit(int port) +{ + pe_sender_response_msg_exit(port); + pd_timer_disable(port, PE_TIMER_TIMEOUT); } /** @@ -3423,12 +4251,10 @@ static void pe_soft_reset_entry(int port) { print_current_state(port); - pe[port].sender_response_timer = TIMER_DISABLED; - - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT); } -static void pe_soft_reset_run(int port) +static void pe_soft_reset_run(int port) { if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); @@ -3439,11 +4265,7 @@ static void pe_soft_reset_run(int port) set_state_pe(port, PE_SRC_SEND_CAPABILITIES); } else if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); - - if (pe[port].power_role == PD_ROLE_SINK) - set_state_pe(port, PE_SNK_HARD_RESET); - else - set_state_pe(port, PE_SRC_HARD_RESET); + pe_set_hard_reset(port); } } @@ -3461,10 +4283,10 @@ static void pe_send_not_supported_entry(int port) print_current_state(port); /* Request the Protocol Layer to send a Not_Supported Message. */ - if (prl_get_rev(port, TCPC_TX_SOP) > PD_REV20) - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_NOT_SUPPORTED); + if (prl_get_rev(port, TCPCI_MSG_SOP) > PD_REV20) + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_NOT_SUPPORTED); else - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT); } static void pe_send_not_supported_run(int port) @@ -3472,11 +4294,9 @@ static void pe_send_not_supported_run(int port) if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); pe_set_ready_state(port); - } } -#if defined(CONFIG_USB_PD_REV30) && !defined(CONFIG_USB_PD_EXTENDED_MESSAGES) /** * PE_SRC_Chunk_Received and PE_SNK_Chunk_Received * @@ -3491,19 +4311,31 @@ static void pe_send_not_supported_run(int port) * 6.6.18.1 ChunkingNotSupportedTimer * 8.3.3.6 Not Supported Message State Diagrams */ -static void pe_chunk_received_entry(int port) +__maybe_unused static void pe_chunk_received_entry(int port) { + if (!IS_ENABLED(CONFIG_USB_PD_REV30) || + IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) + assert(0); + print_current_state(port); - pe[port].chunking_not_supported_timer = - get_time().val + PD_T_CHUNKING_NOT_SUPPORTED; + pd_timer_enable(port, PE_TIMER_CHUNKING_NOT_SUPPORTED, + PD_T_CHUNKING_NOT_SUPPORTED); } -static void pe_chunk_received_run(int port) +__maybe_unused static void pe_chunk_received_run(int port) { - if (get_time().val > pe[port].chunking_not_supported_timer) + if (!IS_ENABLED(CONFIG_USB_PD_REV30) || + IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) + assert(0); + + if (pd_timer_is_expired(port, PE_TIMER_CHUNKING_NOT_SUPPORTED)) set_state_pe(port, PE_SEND_NOT_SUPPORTED); } -#endif + +__maybe_unused static void pe_chunk_received_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_CHUNKING_NOT_SUPPORTED); +} /** * PE_SRC_Ping @@ -3511,7 +4343,7 @@ static void pe_chunk_received_run(int port) static void pe_src_ping_entry(int port) { print_current_state(port); - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PING); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PING); } static void pe_src_ping_run(int port) @@ -3528,55 +4360,86 @@ static void pe_src_ping_run(int port) */ static void pe_give_battery_cap_entry(int port) { - uint32_t payload = *(uint32_t *)(&rx_emsg[port].buf); + uint8_t *payload = rx_emsg[port].buf; uint16_t *msg = (uint16_t *)tx_emsg[port].buf; if (!IS_ENABLED(CONFIG_BATTERY)) return; print_current_state(port); - /* msg[0] - extended header is set by Protocol Layer */ - /* Set VID */ - msg[1] = USB_VID_GOOGLE; + msg[BCDB_VID] = USB_VID_GOOGLE; /* Set PID */ - msg[2] = CONFIG_USB_PID; + msg[BCDB_PID] = CONFIG_USB_PID; - if (battery_is_present()) { + /* + * We only have one fixed battery, + * so make sure batt cap ref is 0. + * This value is the first byte after the headers. + */ + if (payload[0] != 0) { /* - * We only have one fixed battery, - * so make sure batt cap ref is 0. + * If the Battery Cap Ref field in the Get_Battery_Cap + * Message is Invalid, this VID field Shall be 0xFFFF. + * + * When the VID Is 0xFFFF the PID field Shall be set to + * 0x0000. */ - if (BATT_CAP_REF(payload) != 0) { - /* Invalid battery reference */ - msg[3] = 0; - msg[4] = 0; - msg[5] = 1; - } else { - uint32_t v; - uint32_t c; + msg[BCDB_VID] = 0xffff; + msg[BCDB_PID] = 0; + /* Invalid battery reference */ + msg[BCDB_DESIGN_CAP] = 0; + msg[BCDB_FULL_CAP] = 0; + /* Set invalid battery bit in response bit 0, byte 8 */ + msg[BCDB_BATT_TYPE] = 1; + } else if (battery_is_present()) { + /* + * The Battery Design Capacity field shall return the + * Battery’s design capacity in tenths of Wh. If the + * Battery is Hot Swappable and is not present, the + * Battery Design Capacity field shall be set to 0. If + * the Battery is unable to report its Design Capacity, + * it shall return 0xFFFF + */ + msg[BCDB_DESIGN_CAP] = 0xffff; + + /* + * The Battery Last Full Charge Capacity field shall + * return the Battery’s last full charge capacity in + * tenths of Wh. If the Battery is Hot Swappable and + * is not present, the Battery Last Full Charge Capacity + * field shall be set to 0. If the Battery is unable to + * report its Design Capacity, the Battery Last Full + * Charge Capacity field shall be set to 0xFFFF. + */ + msg[BCDB_FULL_CAP] = 0xffff; + + if (IS_ENABLED(HAS_TASK_HOSTCMD) && + *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) != 0) { + int design_volt, design_cap, full_cap; + + design_volt = + *(int *)host_get_memmap(EC_MEMMAP_BATT_DVLT); + design_cap = + *(int *)host_get_memmap(EC_MEMMAP_BATT_DCAP); + full_cap = *(int *)host_get_memmap(EC_MEMMAP_BATT_LFCC); /* - * The Battery Design Capacity field shall return the - * Battery’s design capacity in tenths of Wh. If the - * Battery is Hot Swappable and is not present, the - * Battery Design Capacity field shall be set to 0. If - * the Battery is unable to report its Design Capacity, - * it shall return 0xFFFF + * Wh = (c * v) / 1000000 + * 10th of a Wh = Wh * 10 */ - msg[3] = 0xffff; - + msg[BCDB_DESIGN_CAP] = DIV_ROUND_NEAREST( + (design_cap * design_volt), 100000); /* - * The Battery Last Full Charge Capacity field shall - * return the Battery’s last full charge capacity in - * tenths of Wh. If the Battery is Hot Swappable and - * is not present, the Battery Last Full Charge Capacity - * field shall be set to 0. If the Battery is unable to - * report its Design Capacity, the Battery Last Full - * Charge Capacity field shall be set to 0xFFFF. + * Wh = (c * v) / 1000000 + * 10th of a Wh = Wh * 10 */ - msg[4] = 0xffff; + msg[BCDB_FULL_CAP] = DIV_ROUND_NEAREST( + (design_cap * full_cap), 100000); + } else { + uint32_t v; + uint32_t c; if (battery_design_voltage(&v) == 0) { if (battery_design_capacity(&c) == 0) { @@ -3584,8 +4447,9 @@ static void pe_give_battery_cap_entry(int port) * Wh = (c * v) / 1000000 * 10th of a Wh = Wh * 10 */ - msg[3] = DIV_ROUND_NEAREST((c * v), - 100000); + msg[BCDB_DESIGN_CAP] = + DIV_ROUND_NEAREST((c * v), + 100000); } if (battery_full_charge_capacity(&c) == 0) { @@ -3593,17 +4457,24 @@ static void pe_give_battery_cap_entry(int port) * Wh = (c * v) / 1000000 * 10th of a Wh = Wh * 10 */ - msg[4] = DIV_ROUND_NEAREST((c * v), - 100000); + msg[BCDB_FULL_CAP] = DIV_ROUND_NEAREST( + (c * v), 100000); } } } + /* Valid battery selected */ + msg[BCDB_BATT_TYPE] = 0; + } else { + /* Battery not present indicated by 0's in the capacity */ + msg[BCDB_DESIGN_CAP] = 0; + msg[BCDB_FULL_CAP] = 0; + msg[BCDB_BATT_TYPE] = 0; } /* Extended Battery Cap data is 9 bytes */ tx_emsg[port].len = 9; - send_ext_data_msg(port, TCPC_TX_SOP, PD_EXT_BATTERY_CAP); + send_ext_data_msg(port, TCPCI_MSG_SOP, PD_EXT_BATTERY_CAP); } static void pe_give_battery_cap_run(int port) @@ -3619,7 +4490,7 @@ static void pe_give_battery_cap_run(int port) */ static void pe_give_battery_status_entry(int port) { - uint32_t payload = *(uint32_t *)(&rx_emsg[port].buf); + uint8_t *payload = rx_emsg[port].buf; uint32_t *msg = (uint32_t *)tx_emsg[port].buf; if (!IS_ENABLED(CONFIG_BATTERY)) @@ -3630,24 +4501,38 @@ static void pe_give_battery_status_entry(int port) /* * We only have one fixed battery, * so make sure batt cap ref is 0. + * This value is the first byte after the headers. */ - if (BATT_CAP_REF(payload) != 0) { + if (payload[0] != 0) { /* Invalid battery reference */ + *msg = BSDO_CAP(BSDO_CAP_UNKNOWN); *msg |= BSDO_INVALID; } else { uint32_t v; uint32_t c; - if (battery_design_voltage(&v) != 0 || - battery_remaining_capacity(&c) != 0) { - *msg |= BSDO_CAP(BSDO_CAP_UNKNOWN); - } else { + *msg = BSDO_CAP(BSDO_CAP_UNKNOWN); + + if (IS_ENABLED(HAS_TASK_HOSTCMD) && + *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) != 0) { + v = *(int *)host_get_memmap( + EC_MEMMAP_BATT_DVLT); + c = *(int *)host_get_memmap(EC_MEMMAP_BATT_CAP); + /* * Wh = (c * v) / 1000000 * 10th of a Wh = Wh * 10 */ - *msg |= BSDO_CAP(DIV_ROUND_NEAREST((c * v), - 100000)); + *msg = BSDO_CAP( + DIV_ROUND_NEAREST((c * v), 100000)); + } else if (battery_design_voltage(&v) == 0 && + battery_remaining_capacity(&c) == 0) { + /* + * Wh = (c * v) / 1000000 + * 10th of a Wh = Wh * 10 + */ + *msg = BSDO_CAP( + DIV_ROUND_NEAREST((c * v), 100000)); } /* Battery is present */ @@ -3672,12 +4557,14 @@ static void pe_give_battery_status_entry(int port) } } else { *msg = BSDO_CAP(BSDO_CAP_UNKNOWN); + if (payload[0] != 0) + *msg |= BSDO_INVALID; } /* Battery Status data is 4 bytes */ tx_emsg[port].len = 4; - send_data_msg(port, TCPC_TX_SOP, PD_DATA_BATTERY_STATUS); + send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_BATTERY_STATUS); } static void pe_give_battery_status_run(int port) @@ -3688,6 +4575,37 @@ static void pe_give_battery_status_run(int port) } } +/** + * PE_SRC_Give_Source_Status and + * PE_SNK_Give_Sink_Status + */ +static void pe_give_status_entry(int port) +{ + uint8_t *msg = (uint8_t *)tx_emsg[port].buf; + uint32_t *len = &tx_emsg[port].len; + + print_current_state(port); + if (dpm_get_status_msg(port, msg, len) != EC_SUCCESS) { + pe_set_ready_state(port); + return; + } + + send_ext_data_msg(port, TCPCI_MSG_SOP, PD_EXT_STATUS); +} + +static void pe_give_status_run(int port) +{ + if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + pe_set_ready_state(port); + } else if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR) || + PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + PE_CLR_FLAG(port, PE_FLAGS_MSG_DISCARDED); + pe_send_soft_reset(port, TCPCI_MSG_SOP); + } +} + /** * PE_SRC_Send_Source_Alert and * PE_SNK_Send_Sink_Alert @@ -3699,24 +4617,53 @@ static void pe_send_alert_entry(int port) print_current_state(port); - if (pd_build_alert_msg(msg, len, pe[port].power_role) != EC_SUCCESS) + if (msg == NULL || len == NULL) { pe_set_ready_state(port); + } else { + /* Get ADO from PE state, the ADO is a uint32_t */ + mutex_lock(&pe[port].ado_lock); + *msg = pe[port].ado; + *len = sizeof(pe[port].ado); + mutex_unlock(&pe[port].ado_lock); + } /* Request the Protocol Layer to send Alert Message. */ - send_data_msg(port, TCPC_TX_SOP, PD_DATA_ALERT); + send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_ALERT); } static void pe_send_alert_run(int port) { if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + pe_clear_ado(port); + pe_set_ready_state(port); + return; + } else if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { + PE_CLR_FLAG(port, PE_FLAGS_MSG_DISCARDED); + pd_dpm_request(port, DPM_REQUEST_SEND_ALERT); pe_set_ready_state(port); + return; } } + +/** + * PE_SNK_Source_Alert_Received and + * PE_SRC_Sink_Alert_Received + */ +static void pe_alert_received_entry(int port) +{ + uint32_t *ado = (uint32_t *)rx_emsg[port].buf; + + print_current_state(port); + dpm_handle_alert(port, *ado); + pe_set_ready_state(port); +} + #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ /** * PE_DRS_Evaluate_Swap + * PE_DRS_UFP_DFP_Evaluate_Swap and PE_DRS_DFP_UFP_Evaluate_Swap embedded here. */ static void pe_drs_evaluate_swap_entry(int port) { @@ -3726,16 +4673,24 @@ static void pe_drs_evaluate_swap_entry(int port) if (pd_check_data_swap(port, pe[port].data_role)) { PE_SET_FLAG(port, PE_FLAGS_ACCEPT); /* - * PE_DRS_UFP_DFP_Evaluate_Swap and - * PE_DRS_DFP_UFP_Evaluate_Swap states embedded here. + * PE_DRS_UFP_DFP_Accept_Swap and + * PE_DRS_DFP_UFP_Accept_Swap states embedded here. */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT); + /* + * The PD spec implies that the PE transitions through + * PE_DRS_*_Accept_Swap and PE_DRS_Change and updates the data + * role instantaneously, but this PE doesn't. During the + * transition, do not validate the data role of incoming + * messages, in case the port partner transitioned faster. + */ + prl_set_data_role_check(port, false); } else { /* * PE_DRS_UFP_DFP_Reject_Swap and PE_DRS_DFP_UFP_Reject_Swap * states embedded here. */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT); } } @@ -3781,6 +4736,7 @@ static void pe_drs_change_run(int port) /* Update the data role */ pe[port].data_role = pd_get_data_role(port); + prl_set_data_role_check(port, true); if (pe[port].data_role == PD_ROLE_DFP) PE_CLR_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP); @@ -3804,7 +4760,7 @@ static void pe_drs_send_swap_entry(int port) * states embedded here. */ /* Request the Protocol Layer to send a DR_Swap Message */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_DR_SWAP); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_DR_SWAP); pe_sender_response_msg_entry(port); } @@ -3841,8 +4797,8 @@ static void pe_drs_send_swap_run(int port) set_state_pe(port, PE_DRS_CHANGE); return; } else if ((type == PD_CTRL_REJECT) || - (type == PD_CTRL_WAIT) || - (type == PD_CTRL_NOT_SUPPORTED)) { + (type == PD_CTRL_WAIT) || + (type == PD_CTRL_NOT_SUPPORTED)) { pe_set_ready_state(port); return; } @@ -3855,10 +4811,15 @@ static void pe_drs_send_swap_run(int port) * 2) Message was discarded. */ if ((msg_check & PE_MSG_DISCARDED) || - get_time().val > pe[port].sender_response_timer) + pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) pe_set_ready_state(port); } +static void pe_drs_send_swap_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + /** * PE_PRS_SRC_SNK_Evaluate_Swap */ @@ -3868,12 +4829,12 @@ static void pe_prs_src_snk_evaluate_swap_entry(int port) if (!pd_check_power_swap(port)) { /* PE_PRS_SRC_SNK_Reject_PR_Swap state embedded here */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT); } else { tc_request_power_swap(port); /* PE_PRS_SRC_SNK_Accept_Swap state embedded here */ PE_SET_FLAG(port, PE_FLAGS_ACCEPT); - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT); } } @@ -3885,6 +4846,12 @@ static void pe_prs_src_snk_evaluate_swap_run(int port) if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) { PE_CLR_FLAG(port, PE_FLAGS_ACCEPT); + /* + * Clear any pending DPM power role swap request so we + * don't trigger a power role swap request back to src + * power role. + */ + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP); /* * Power Role Swap OK, transition to * PE_PRS_SRC_SNK_Transition_to_off @@ -3907,21 +4874,50 @@ static void pe_prs_src_snk_transition_to_off_entry(int port) /* Contract is invalid */ pe_invalidate_explicit_contract(port); - /* Tell TypeC to power off the source */ - tc_src_power_off(port); - - pe[port].ps_source_timer = - get_time().val + PD_POWER_SUPPLY_TURN_OFF_DELAY; + pd_timer_enable(port, PE_TIMER_SRC_TRANSITION, PD_T_SRC_TRANSITION); } static void pe_prs_src_snk_transition_to_off_run(int port) { + /* + * This is a non-interruptible AMS and power is transitioning - hard + * reset on interruption. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + tc_pr_swap_complete(port, 0); + pe_set_hard_reset(port); + return; + } + + /* Wait tSrcTransition (~ 25ms) before turning off VBUS */ + if (!pd_timer_is_expired(port, PE_TIMER_SRC_TRANSITION)) + return; + + if (!PE_CHK_FLAG(port, PE_FLAGS_SRC_SNK_SETTLE)) { + PE_SET_FLAG(port, PE_FLAGS_SRC_SNK_SETTLE); + /* Tell TypeC to power off the source */ + tc_src_power_off(port); + + pd_timer_enable(port, PE_TIMER_PS_SOURCE, + PD_POWER_SUPPLY_TURN_OFF_DELAY); + return; + } + /* Give time for supply to power off */ - if (get_time().val > pe[port].ps_source_timer && + if (pd_timer_is_expired(port, PE_TIMER_PS_SOURCE) && pd_check_vbus_level(port, VBUS_SAFE0V)) set_state_pe(port, PE_PRS_SRC_SNK_ASSERT_RD); } +static void pe_prs_src_snk_transition_to_off_exit(int port) +{ + PE_CLR_FLAG(port, PE_FLAGS_SRC_SNK_SETTLE); + pd_timer_disable(port, PE_TIMER_SRC_TRANSITION); + pd_timer_disable(port, PE_TIMER_PS_SOURCE); +} + /** * PE_PRS_SRC_SNK_Assert_Rd */ @@ -3946,44 +4942,45 @@ static void pe_prs_src_snk_assert_rd_run(int port) static void pe_prs_src_snk_wait_source_on_entry(int port) { print_current_state(port); - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PS_RDY); - pe[port].ps_source_timer = TIMER_DISABLED; + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PS_RDY); } static void pe_prs_src_snk_wait_source_on_run(int port) { - int type; - int cnt; - int ext; - - if (pe[port].ps_source_timer == TIMER_DISABLED && - PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + if (pd_timer_is_disabled(port, PE_TIMER_PS_SOURCE) && + PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); /* Update pe power role */ pe[port].power_role = pd_get_power_role(port); - pe[port].ps_source_timer = get_time().val + PD_T_PS_SOURCE_ON; + pd_timer_enable(port, PE_TIMER_PS_SOURCE, PD_T_PS_SOURCE_ON); } /* * Transition to PE_SNK_Startup when: * 1) A PS_RDY Message is received. */ - if (pe[port].ps_source_timer != TIMER_DISABLED && - PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { - PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + if (!pd_timer_is_disabled(port, PE_TIMER_PS_SOURCE) && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + int type = PD_HEADER_TYPE(rx_emsg[port].header); + int cnt = PD_HEADER_CNT(rx_emsg[port].header); + int ext = PD_HEADER_EXT(rx_emsg[port].header); - type = PD_HEADER_TYPE(rx_emsg[port].header); - cnt = PD_HEADER_CNT(rx_emsg[port].header); - ext = PD_HEADER_EXT(rx_emsg[port].header); + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); if ((ext == 0) && (cnt == 0) && (type == PD_CTRL_PS_RDY)) { - pe[port].ps_source_timer = TIMER_DISABLED; - PE_SET_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE); set_state_pe(port, PE_SNK_STARTUP); - return; + } else { + int sop = PD_HEADER_GET_SOP(rx_emsg[port].header); + /* + * USB PD 3.0 6.8.1: + * Receiving an unexpected message shall be responded + * to with a soft reset message. + */ + pe_send_soft_reset(port, sop); } + return; } /* @@ -3991,7 +4988,7 @@ static void pe_prs_src_snk_wait_source_on_run(int port) * 1) The PSSourceOnTimer times out. * 2) PS_RDY not sent after retries. */ - if (get_time().val > pe[port].ps_source_timer || + if (pd_timer_is_expired(port, PE_TIMER_PS_SOURCE) || PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); @@ -4002,8 +4999,8 @@ static void pe_prs_src_snk_wait_source_on_run(int port) static void pe_prs_src_snk_wait_source_on_exit(int port) { - tc_pr_swap_complete(port, - PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)); + pd_timer_disable(port, PE_TIMER_PS_SOURCE); + tc_pr_swap_complete(port, PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)); } /** @@ -4013,8 +5010,11 @@ static void pe_prs_src_snk_send_swap_entry(int port) { print_current_state(port); + /* Making an attempt to PR_Swap, clear we were possibly waiting */ + pd_timer_disable(port, PE_TIMER_PR_SWAP_WAIT); + /* Request the Protocol Layer to send a PR_Swap Message. */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PR_SWAP); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PR_SWAP); pe_sender_response_msg_entry(port); } @@ -4051,7 +5051,7 @@ static void pe_prs_src_snk_send_swap_run(int port) pe[port].src_snk_pr_swap_counter = 0; tc_request_power_swap(port); set_state_pe(port, - PE_PRS_SRC_SNK_TRANSITION_TO_OFF); + PE_PRS_SRC_SNK_TRANSITION_TO_OFF); } else if (type == PD_CTRL_REJECT) { pe[port].src_snk_pr_swap_counter = 0; set_state_pe(port, PE_SRC_READY); @@ -4059,10 +5059,10 @@ static void pe_prs_src_snk_send_swap_run(int port) if (pe[port].src_snk_pr_swap_counter < N_SNK_SRC_PR_SWAP_COUNT) { PE_SET_FLAG(port, - PE_FLAGS_WAITING_PR_SWAP); - pe[port].pr_swap_wait_timer = - get_time().val + - PD_T_PR_SWAP_WAIT; + PE_FLAGS_WAITING_PR_SWAP); + pd_timer_enable(port, + PE_TIMER_PR_SWAP_WAIT, + PD_T_PR_SWAP_WAIT); } pe[port].src_snk_pr_swap_counter++; set_state_pe(port, PE_SRC_READY); @@ -4077,10 +5077,15 @@ static void pe_prs_src_snk_send_swap_run(int port) * 2) Message was discarded. */ if ((msg_check & PE_MSG_DISCARDED) || - get_time().val > pe[port].sender_response_timer) + pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) set_state_pe(port, PE_SRC_READY); } +static void pe_prs_src_snk_send_swap_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + /** * PE_PRS_SNK_SRC_Evaluate_Swap */ @@ -4097,12 +5102,12 @@ static void pe_prs_snk_src_evaluate_swap_entry(int port) if (!pd_check_power_swap(port)) { /* PE_PRS_SNK_SRC_Reject_Swap state embedded here */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT); } else { tc_request_power_swap(port); /* PE_PRS_SNK_SRC_Accept_Swap state embedded here */ PE_SET_FLAG(port, PE_FLAGS_ACCEPT); - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT); } } @@ -4113,6 +5118,12 @@ static void pe_prs_snk_src_evaluate_swap_run(int port) if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) { PE_CLR_FLAG(port, PE_FLAGS_ACCEPT); + /* + * Clear any pending DPM power role swap request so we + * don't trigger a power role swap request back to sink + * power role. + */ + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP); /* * Accept message sent, transition to * PE_PRS_SNK_SRC_Transition_to_off @@ -4123,6 +5134,19 @@ static void pe_prs_snk_src_evaluate_swap_run(int port) set_state_pe(port, PE_SNK_READY); } } + + if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + /* + * Protocol Error occurs while PR swap, this may + * brown out if the port-parnter can't hold VBUS + * for tSrcTransition. Notify TC that we end the PR + * swap and start to watch VBUS. + * + * TODO(b:155181980): issue soft reset on protocol error. + */ + tc_pr_swap_complete(port, 0); + } } /** @@ -4135,11 +5159,10 @@ static void pe_prs_snk_src_transition_to_off_entry(int port) { print_current_state(port); - if (!IS_ENABLED(CONFIG_USB_PD_REV30) || - !PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH)) + if (!IS_ENABLED(CONFIG_USB_PD_REV30) || !pe_in_frs_mode(port)) tc_snk_power_off(port); - pe[port].ps_source_timer = get_time().val + PD_T_PS_SOURCE_OFF; + pd_timer_enable(port, PE_TIMER_PS_SOURCE, PD_T_PS_SOURCE_OFF); } static void pe_prs_snk_src_transition_to_off_run(int port) @@ -4152,7 +5175,7 @@ static void pe_prs_snk_src_transition_to_off_run(int port) * Transition to ErrorRecovery state when: * 1) The PSSourceOffTimer times out. */ - if (get_time().val > pe[port].ps_source_timer) + if (pd_timer_is_expired(port, PE_TIMER_PS_SOURCE)) set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); /* @@ -4177,6 +5200,11 @@ static void pe_prs_snk_src_transition_to_off_run(int port) } } +static void pe_prs_snk_src_transition_to_off_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_PS_SOURCE); +} + /** * PE_PRS_SNK_SRC_Assert_Rp * PE_FRS_SNK_SRC_Assert_Rp @@ -4198,8 +5226,7 @@ static void pe_prs_snk_src_assert_rp_run(int port) { /* Wait until TypeC is in the Attached.SRC state */ if (tc_is_attached_src(port)) { - if (!IS_ENABLED(CONFIG_USB_PD_REV30) || - !PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH)) { + if (!IS_ENABLED(CONFIG_USB_PD_REV30) || !pe_in_frs_mode(port)) { /* Contract is invalid now */ pe_invalidate_explicit_contract(port); } @@ -4221,22 +5248,22 @@ static void pe_prs_snk_src_source_on_entry(int port) * VBUS was enabled when the TypeC state machine entered * Attached.SRC state */ - pe[port].ps_source_timer = get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY; + pd_timer_enable(port, PE_TIMER_PS_SOURCE, + PD_POWER_SUPPLY_TURN_ON_DELAY); } static void pe_prs_snk_src_source_on_run(int port) { /* Wait until power supply turns on */ - if (pe[port].ps_source_timer != TIMER_DISABLED) { - if (get_time().val < pe[port].ps_source_timer) + if (!pd_timer_is_disabled(port, PE_TIMER_PS_SOURCE)) { + if (!pd_timer_is_expired(port, PE_TIMER_PS_SOURCE)) return; /* update pe power role */ pe[port].power_role = pd_get_power_role(port); - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PS_RDY); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PS_RDY); /* reset timer so PD_CTRL_PS_RDY isn't sent again */ - pe[port].ps_source_timer = TIMER_DISABLED; + pd_timer_disable(port, PE_TIMER_PS_SOURCE); } /* @@ -4259,8 +5286,8 @@ static void pe_prs_snk_src_source_on_run(int port) static void pe_prs_snk_src_source_on_exit(int port) { - tc_pr_swap_complete(port, - PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)); + pd_timer_disable(port, PE_TIMER_PS_SOURCE); + tc_pr_swap_complete(port, PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)); } /** @@ -4283,13 +5310,11 @@ static void pe_prs_snk_src_send_swap_entry(int port) * Request the Protocol Layer to send a FR_Swap Message. */ if (IS_ENABLED(CONFIG_USB_PD_REV30)) { - send_ctrl_msg(port, - TCPC_TX_SOP, - PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH) - ? PD_CTRL_FR_SWAP - : PD_CTRL_PR_SWAP); + send_ctrl_msg(port, TCPCI_MSG_SOP, + pe_in_frs_mode(port) ? PD_CTRL_FR_SWAP : + PD_CTRL_PR_SWAP); } else { - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PR_SWAP); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PR_SWAP); } pe_sender_response_msg_entry(port); } @@ -4310,10 +5335,9 @@ static void pe_prs_snk_src_send_swap_run(int port) * Handle discarded message */ if (msg_check & PE_MSG_DISCARDED) { - if (PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH)) - set_state_pe(port, PE_SNK_HARD_RESET); - else - set_state_pe(port, PE_SNK_READY); + set_state_pe(port, pe_in_frs_mode(port) ? + PE_WAIT_FOR_ERROR_RECOVERY : + PE_SNK_READY); return; } @@ -4340,13 +5364,13 @@ static void pe_prs_snk_src_send_swap_run(int port) set_state_pe(port, PE_PRS_SNK_SRC_TRANSITION_TO_OFF); } else if ((type == PD_CTRL_REJECT) || - (type == PD_CTRL_WAIT)) { + (type == PD_CTRL_WAIT)) { if (IS_ENABLED(CONFIG_USB_PD_REV30)) - set_state_pe(port, - PE_CHK_FLAG(port, - PE_FLAGS_FAST_ROLE_SWAP_PATH) - ? PE_WAIT_FOR_ERROR_RECOVERY - : PE_SNK_READY); + set_state_pe( + port, + pe_in_frs_mode(port) ? + PE_WAIT_FOR_ERROR_RECOVERY : + PE_SNK_READY); else set_state_pe(port, PE_SNK_READY); } @@ -4359,41 +5383,66 @@ static void pe_prs_snk_src_send_swap_run(int port) * FRS: Transition to ErrorRecovery state when: * 1) The SenderResponseTimer times out. */ - if (get_time().val > pe[port].sender_response_timer) { + if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) { if (IS_ENABLED(CONFIG_USB_PD_REV30)) - set_state_pe(port, - PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH) - ? PE_WAIT_FOR_ERROR_RECOVERY - : PE_SNK_READY); + set_state_pe(port, pe_in_frs_mode(port) ? + PE_WAIT_FOR_ERROR_RECOVERY : + PE_SNK_READY); else set_state_pe(port, PE_SNK_READY); + return; + } + /* + * FRS Only: Transition to ErrorRecovery state when: + * 2) The FR_Swap Message is not sent after retries (a GoodCRC Message + * has not been received). A soft reset Shall Not be initiated in + * this case. + */ + if (IS_ENABLED(CONFIG_USB_PD_REV30) && pe_in_frs_mode(port) && + PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); } } -#ifdef CONFIG_USB_PD_REV30 +static void pe_prs_snk_src_send_swap_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + /** * PE_FRS_SNK_SRC_Start_AMS */ -static void pe_frs_snk_src_start_ams_entry(int port) +__maybe_unused static void pe_frs_snk_src_start_ams_entry(int port) { - print_current_state(port); + if (!IS_ENABLED(CONFIG_USB_PD_REV30)) + assert(0); - /* Contract is invalid now */ - pe_invalidate_explicit_contract(port); + print_current_state(port); /* Inform Protocol Layer this is start of AMS */ PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); /* Shared PRS/FRS code, indicate FRS path */ PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH); + + /* + * Invalidate the contract after the FRS flags set so the + * flags can be propagated to this function. + */ + pe_invalidate_explicit_contract(port); + set_state_pe(port, PE_PRS_SNK_SRC_SEND_SWAP); } /** * PE_PRS_FRS_SHARED */ -static void pe_prs_frs_shared_entry(int port) +__maybe_unused static void pe_prs_frs_shared_entry(int port) { + if (!IS_ENABLED(CONFIG_USB_PD_REV30)) + assert(0); + /* * Shared PRS/FRS code, assume PRS path * @@ -4405,52 +5454,99 @@ static void pe_prs_frs_shared_entry(int port) PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH); } -static void pe_prs_frs_shared_exit(int port) +__maybe_unused static void pe_prs_frs_shared_exit(int port) { + if (!IS_ENABLED(CONFIG_USB_PD_REV30)) + assert(0); + /* * Shared PRS/FRS code, when not in shared path * indicate PRS path */ PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH); } -#endif /* CONFIG_USB_PD_REV30 */ /** - * BIST TX + * PE_BIST_TX */ static void pe_bist_tx_entry(int port) { uint32_t *payload = (uint32_t *)rx_emsg[port].buf; uint8_t mode = BIST_MODE(payload[0]); + int vbus_mv; + int ibus_ma; print_current_state(port); - /* - * See section 6.4.3.6 BIST Carrier Mode 2: - * With a BIST Carrier Mode 2 BIST Data Object, the UUT Shall send out - * a continuous string of alternating "1"s and “0”s. - * The UUT Shall exit the Continuous BIST Mode within tBISTContMode of - * this Continuous BIST Mode being enabled. - */ + /* Get the current nominal VBUS value */ + if (pe[port].power_role == PD_ROLE_SOURCE) { + const uint32_t *src_pdo; + uint32_t unused; + + dpm_get_source_pdo(&src_pdo, port); + pd_extract_pdo_power(src_pdo[pe[port].requested_idx - 1], + &ibus_ma, &vbus_mv, &unused); + } else { + vbus_mv = pe[port].supply_voltage; + } + + /* If VBUS is not at vSafe5V, then don't enter BIST test mode */ + if (vbus_mv != PD_V_SAFE5V_NOM) { + pe_set_ready_state(port); + return; + } + if (mode == BIST_CARRIER_MODE_2) { - send_ctrl_msg(port, TCPC_TX_BIST_MODE_2, 0); - pe[port].bist_cont_mode_timer = - get_time().val + PD_T_BIST_CONT_MODE; + /* + * PE_BIST_Carrier_Mode embedded here. + * See PD 3.0 section 6.4.3.1 BIST Carrier Mode 2: With a BIST + * Carrier Mode 2 BIST Data Object, the UUT Shall send out a + * continuous string of BMC-encoded alternating "1"s and “0”s. + * The UUT Shall exit the Continuous BIST Mode within + * tBISTContMode of this Continuous BIST Mode being enabled. + */ + send_ctrl_msg(port, TCPCI_MSG_TX_BIST_MODE_2, 0); + pd_timer_enable(port, PE_TIMER_BIST_CONT_MODE, + PD_T_BIST_CONT_MODE); + } else if (mode == BIST_TEST_DATA) { + /* + * See PD 3.0 section 6.4.3.2 BIST Test Data: + * With a BIST Test Data BIST Data Object, the UUT Shall return + * a GoodCRC Message and Shall enter a test mode in which it + * sends no further Messages except for GoodCRC Messages in + * response to received Messages.... The test Shall be ended by + * sending Hard Reset Signaling to reset the UUT. + */ + if (tcpc_set_bist_test_mode(port, true) != EC_SUCCESS) + CPRINTS("C%d: Failed to enter BIST Test Mode", port); + } else if (IS_ENABLED(CONFIG_USB_PD_REV30) && + mode == BIST_SHARED_MODE_ENTER) { + /* Notify the DPM and return to ready */ + dpm_bist_shared_mode_enter(port); + pe_set_ready_state(port); + return; + } else if (IS_ENABLED(CONFIG_USB_PD_REV30) && + mode == BIST_SHARED_MODE_EXIT) { + /* Notify the DPM and return to ready */ + dpm_bist_shared_mode_exit(port); + pe_set_ready_state(port); + return; + } else { + /* Ignore unsupported BIST messages. */ + pe_set_ready_state(port); + return; } - /* - * See section 6.4.3.9 BIST Test Data: - * With a BIST Test Data BIST Data Object, the UUT Shall return a - * GoodCRC Message and Shall enter a test mode in which it sends no - * further Messages except for GoodCRC Messages in response to received - * Messages. - */ - else if (mode == BIST_TEST_DATA) - pe[port].bist_cont_mode_timer = TIMER_DISABLED; } static void pe_bist_tx_run(int port) { - if (get_time().val > pe[port].bist_cont_mode_timer) { + if (pd_timer_is_expired(port, PE_TIMER_BIST_CONT_MODE)) { + /* + * Entry point to disable BIST in TCPC if that's not already + * handled automatically by the TCPC. Unless this method is + * implemented in a TCPM driver, this function does nothing. + */ + tcpm_reset_bist_type_2(port); if (pe[port].power_role == PD_ROLE_SOURCE) set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT); @@ -4467,34 +5563,9 @@ static void pe_bist_tx_run(int port) } } -/** - * BIST RX - */ -static void pe_bist_rx_entry(int port) -{ - /* currently only support bist carrier 2 */ - uint32_t bdo = BDO(BDO_MODE_CARRIER2, 0); - - print_current_state(port); - - tx_emsg[port].len = sizeof(bdo); - memcpy(tx_emsg[port].buf, (uint8_t *)&bdo, tx_emsg[port].len); - send_data_msg(port, TCPC_TX_SOP, PD_DATA_BIST); - - /* Delay at least enough for partner to finish BIST */ - pe[port].bist_cont_mode_timer = - get_time().val + PD_T_BIST_RECEIVE; -} - -static void pe_bist_rx_run(int port) +static void pe_bist_tx_exit(int port) { - if (get_time().val < pe[port].bist_cont_mode_timer) - return; - - if (pe[port].power_role == PD_ROLE_SOURCE) - set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT); - else - set_state_pe(port, PE_SNK_TRANSITION_TO_DEFAULT); + pd_timer_disable(port, PE_TIMER_BIST_CONT_MODE); } /** @@ -4507,7 +5578,7 @@ static void pe_snk_give_sink_cap_entry(int port) /* Send a Sink_Capabilities Message */ tx_emsg[port].len = pd_snk_pdo_cnt * 4; memcpy(tx_emsg[port].buf, (uint8_t *)pd_snk_pdo, tx_emsg[port].len); - send_data_msg(port, TCPC_TX_SOP, PD_DATA_SINK_CAP); + send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_SINK_CAP); } static void pe_snk_give_sink_cap_run(int port) @@ -4515,7 +5586,11 @@ static void pe_snk_give_sink_cap_run(int port) if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); pe_set_ready_state(port); + return; } + + if (pe_check_outgoing_discard(port)) + return; } /** @@ -4532,51 +5607,7 @@ static void pe_wait_for_error_recovery_run(int port) /* Stay here until error recovery is complete */ } -/** - * PE_Handle_Custom_Vdm_Request - */ -static void pe_handle_custom_vdm_request_entry(int port) -{ - /* Get the message */ - uint32_t *payload = (uint32_t *)rx_emsg[port].buf; - int cnt = PD_HEADER_CNT(rx_emsg[port].header); - int sop = PD_HEADER_GET_SOP(rx_emsg[port].header); - int rlen = 0; - uint32_t *rdata; - - print_current_state(port); - - /* This is an Interruptible AMS */ - PE_SET_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS); - - rlen = pd_custom_vdm(port, cnt, payload, &rdata); - if (rlen > 0) { - tx_emsg[port].len = rlen * 4; - memcpy(tx_emsg[port].buf, (uint8_t *)rdata, tx_emsg[port].len); - send_data_msg(port, sop, PD_DATA_VENDOR_DEF); - } -} - -static void pe_handle_custom_vdm_request_run(int port) -{ - /* Wait for ACCEPT, WAIT or Reject message to send. */ - if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { - PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); - - /* - * Message sent. Transition back to - * PE_SRC_Ready or PE_SINK_Ready - */ - pe_set_ready_state(port); - } -} - -static void pe_handle_custom_vdm_request_exit(int port) -{ - PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS); -} - -static enum vdm_response_result parse_vdm_response_common(int port) +static enum vdm_response_result parse_vdm_response_common(int port) { /* Retrieve the message information */ uint32_t *payload; @@ -4595,10 +5626,10 @@ static enum vdm_response_result parse_vdm_response_common(int port) cnt = PD_HEADER_CNT(rx_emsg[port].header); ext = PD_HEADER_EXT(rx_emsg[port].header); - if (sop == pe[port].tx_type && type == PD_DATA_VENDOR_DEF && cnt >= 1 - && ext == 0) { + if (sop == pe[port].tx_type && type == PD_DATA_VENDOR_DEF && cnt >= 1 && + ext == 0) { if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_ACK && - cnt >= pe[port].vdm_ack_min_data_objects) { + cnt >= pe[port].vdm_ack_min_data_objects) { /* Handle ACKs in state-specific code. */ return VDM_RESULT_ACK; } else if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_NAK) { @@ -4610,9 +5641,9 @@ static enum vdm_response_result parse_vdm_response_common(int port) * tVDMBusy */ CPRINTS("C%d: Partner BUSY, request will be retried", - port); - pe[port].discover_identity_timer = - get_time().val + PD_T_VDM_BUSY; + port); + pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY, + PD_T_VDM_BUSY); return VDM_RESULT_NO_ACTION; } else if (PD_VDO_CMDT(payload[0]) == CMDT_INIT) { @@ -4628,11 +5659,11 @@ static enum vdm_response_result parse_vdm_response_common(int port) * Partner gave us an incorrect size or command; mark discovery * as failed. */ - CPRINTS("C%d: Unexpected VDM response: 0x%04x 0x%04x", - port, rx_emsg[port].header, payload[0]); + CPRINTS("C%d: Unexpected VDM response: 0x%04x 0x%04x", port, + rx_emsg[port].header, payload[0]); return VDM_RESULT_NAK; } else if (sop == pe[port].tx_type && ext == 0 && cnt == 0 && - type == PD_CTRL_NOT_SUPPORTED) { + type == PD_CTRL_NOT_SUPPORTED) { /* * A NAK would be more expected here, but Not Supported is still * allowed with the same meaning. @@ -4652,7 +5683,7 @@ static enum vdm_response_result parse_vdm_response_common(int port) */ static void pe_vdm_send_request_entry(int port) { - if (pe[port].tx_type == TCPC_TX_INVALID) { + if (pe[port].tx_type == TCPCI_MSG_INVALID) { if (IS_ENABLED(USB_PD_DEBUG_LABELS)) CPRINTS("C%d: %s: Tx type expected to be set, " "returning", @@ -4661,31 +5692,30 @@ static void pe_vdm_send_request_entry(int port) return; } - if ((pe[port].tx_type == TCPC_TX_SOP_PRIME || - pe[port].tx_type == TCPC_TX_SOP_PRIME_PRIME) && - !tc_is_vconn_src(port)) { + if ((pe[port].tx_type == TCPCI_MSG_SOP_PRIME || + pe[port].tx_type == TCPCI_MSG_SOP_PRIME_PRIME) && + !tc_is_vconn_src(port) && + port_discovery_vconn_swap_policy( + port, BIT(PE_FLAGS_VCONN_SWAP_TO_ON_FN))) { if (port_try_vconn_swap(port)) return; } /* All VDM sequences are Interruptible */ - PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS | - PE_FLAGS_INTERRUPTIBLE_AMS); - - pe[port].vdm_response_timer = TIMER_DISABLED; + PE_SET_MASK(port, BIT(PE_FLAGS_LOCALLY_INITIATED_AMS_FN) | + BIT(PE_FLAGS_INTERRUPTIBLE_AMS_FN)); } static void pe_vdm_send_request_run(int port) { - if (pe[port].vdm_response_timer == TIMER_DISABLED && - PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE) && + pd_timer_is_disabled(port, PE_TIMER_VDM_RESPONSE)) { /* Message was sent */ PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); /* Start no response timer */ /* TODO(b/155890173): Support DPM-supplied timeout */ - pe[port].vdm_response_timer = - get_time().val + PD_T_VDM_SNDR_RSP; + pd_timer_enable(port, PE_TIMER_VDM_RESPONSE, PD_T_VDM_SNDR_RSP); } if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { @@ -4701,10 +5731,9 @@ static void pe_vdm_send_request_run(int port) * Check the VDM timer, child will be responsible for processing * messages and reacting appropriately to unexpected messages. */ - if (get_time().val > pe[port].vdm_response_timer) { + if (pd_timer_is_expired(port, PE_TIMER_VDM_RESPONSE)) { CPRINTF("VDM %s Response Timeout\n", - pe[port].tx_type == TCPC_TX_SOP ? - "Port" : "Cable"); + pe[port].tx_type == TCPCI_MSG_SOP ? "Port" : "Cable"); /* * Flag timeout so child state can mark appropriate discovery * item as failed. @@ -4724,7 +5753,9 @@ static void pe_vdm_send_request_exit(int port) PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS); /* Invalidate TX type so it must be set before next call */ - pe[port].tx_type = TCPC_TX_INVALID; + pe[port].tx_type = TCPCI_MSG_INVALID; + + pd_timer_disable(port, PE_TIMER_VDM_RESPONSE); } /** @@ -4739,15 +5770,19 @@ static void pe_vdm_identity_request_cbl_entry(int port) print_current_state(port); - if (!tc_is_vconn_src(port)) { + if (!pe_can_send_sop_prime(port)) { + /* + * The parent state already tried to enable SOP' traffic. If it + * is still disabled, there's nothing left to try. + */ pd_set_identity_discovery(port, pe[port].tx_type, PD_DISC_FAIL); set_state_pe(port, get_last_state_pe(port)); return; } msg[0] = VDO(USB_SID_PD, 1, - VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) | - CMD_DISCOVER_IDENT); + VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) | + CMD_DISCOVER_IDENT); tx_emsg[port].len = sizeof(uint32_t); send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF); @@ -4764,7 +5799,7 @@ static void pe_vdm_identity_request_cbl_entry(int port) static void pe_vdm_identity_request_cbl_run(int port) { /* Retrieve the message information */ - uint32_t *payload = (uint32_t *) rx_emsg[port].buf; + uint32_t *payload = (uint32_t *)rx_emsg[port].buf; int sop = PD_HEADER_GET_SOP(rx_emsg[port].header); uint8_t type = PD_HEADER_TYPE(rx_emsg[port].header); uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header); @@ -4797,9 +5832,8 @@ static void pe_vdm_identity_request_cbl_run(int port) * state. */ if (get_last_state_pe(port) == PE_SRC_DISCOVERY && - (sop != pe[port].tx_type || - type != PD_DATA_VENDOR_DEF || - cnt == 0 || ext != 0)) { + (sop != pe[port].tx_type || type != PD_DATA_VENDOR_DEF || + cnt == 0 || ext != 0)) { /* * Unexpected non-VDM received: Before an explicit * contract, an unexpected message shall generate a soft @@ -4820,9 +5854,9 @@ static void pe_vdm_identity_request_cbl_run(int port) * PD Spec Table 6-2: Revision Interoperability during an * Explicit Contract */ - if (prl_get_rev(port, TCPC_TX_SOP) != PD_REV20) - prl_set_rev(port, sop, - PD_HEADER_REV(rx_emsg[port].header)); + if (prl_get_rev(port, TCPCI_MSG_SOP) != PD_REV20) + set_cable_rev(port, + PD_HEADER_REV(rx_emsg[port].header)); break; case VDM_RESULT_NAK: /* PE_INIT_PORT_VDM_IDENTITY_NAKed embedded here */ @@ -4850,7 +5884,7 @@ static void pe_vdm_identity_request_cbl_exit(int port) */ if (PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT)) { PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT); - prl_set_rev(port, TCPC_TX_SOP_PRIME, PD_REV20); + set_cable_rev(port, PD_REV20); } /* @@ -4863,24 +5897,22 @@ static void pe_vdm_identity_request_cbl_exit(int port) * Not send any further SOP’/SOP’’ Messages. */ if (pe[port].discover_identity_counter >= N_DISCOVER_IDENTITY_COUNT) - pd_set_identity_discovery(port, pe[port].tx_type, - PD_DISC_FAIL); + pd_set_identity_discovery(port, pe[port].tx_type, PD_DISC_FAIL); else if (pe[port].discover_identity_counter == - (N_DISCOVER_IDENTITY_COUNT / 2)) + N_DISCOVER_IDENTITY_PD3_0_LIMIT) /* - * Downgrade to PD 2.0 if the partner hasn't replied halfway - * through discovery as well, in case the cable is + * Downgrade to PD 2.0 if the partner hasn't replied before + * all retries are exhausted in case the cable is * non-compliant about GoodCRC-ing higher revisions */ - prl_set_rev(port, TCPC_TX_SOP_PRIME, PD_REV20); + set_cable_rev(port, PD_REV20); /* * Set discover identity timer unless BUSY case already did so. */ - if (pd_get_identity_discovery(port, pe[port].tx_type) == PD_DISC_NEEDED - && pe[port].discover_identity_timer < get_time().val) { - uint64_t timer; - + if (pd_get_identity_discovery(port, pe[port].tx_type) == + PD_DISC_NEEDED && + pd_timer_is_expired(port, PE_TIMER_DISCOVER_IDENTITY)) { /* * The tDiscoverIdentity timer is used during an explicit * contract when discovering whether a cable is PD capable. @@ -4889,17 +5921,20 @@ static void pe_vdm_identity_request_cbl_exit(int port) * sent. This permits operation with captive cable devices that * power the SOP' responder from VBUS instead of VCONN. */ - if (pe_is_explicit_contract(port)) - timer = PD_T_DISCOVER_IDENTITY; - else - timer = PE_T_DISCOVER_IDENTITY_NO_CONTRACT; - - pe[port].discover_identity_timer = get_time().val + timer; + pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY, + pe_is_explicit_contract(port) ? + PD_T_DISCOVER_IDENTITY : + PE_T_DISCOVER_IDENTITY_NO_CONTRACT); } /* Do not attempt further discovery if identity discovery failed. */ - if (pd_get_identity_discovery(port, pe[port].tx_type) == PD_DISC_FAIL) + if (pd_get_identity_discovery(port, pe[port].tx_type) == PD_DISC_FAIL) { pd_set_svids_discovery(port, pe[port].tx_type, PD_DISC_FAIL); + pd_notify_event(port, + pe[port].tx_type == TCPCI_MSG_SOP ? + PD_STATUS_EVENT_SOP_DISC_DONE : + PD_STATUS_EVENT_SOP_PRIME_DISC_DONE); + } } /** @@ -4917,8 +5952,8 @@ static void pe_init_port_vdm_identity_request_entry(int port) print_current_state(port); msg[0] = VDO(USB_SID_PD, 1, - VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) | - CMD_DISCOVER_IDENT); + VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) | + CMD_DISCOVER_IDENT); tx_emsg[port].len = sizeof(uint32_t); send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF); @@ -4945,21 +5980,18 @@ static void pe_init_port_vdm_identity_request_run(int port) break; case VDM_RESULT_ACK: { /* Retrieve the message information. */ - uint32_t *payload = (uint32_t *) rx_emsg[port].buf; + uint32_t *payload = (uint32_t *)rx_emsg[port].buf; int sop = PD_HEADER_GET_SOP(rx_emsg[port].header); uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header); /* PE_INIT_PORT_VDM_Identity_ACKed embedded here */ dfp_consume_identity(port, sop, cnt, payload); + break; - } + } case VDM_RESULT_NAK: /* PE_INIT_PORT_VDM_IDENTITY_NAKed embedded here */ pd_set_identity_discovery(port, pe[port].tx_type, PD_DISC_FAIL); - /* - * Note: AP is only notified of discovery complete when - * something was found (at least one ACK) - */ break; } @@ -4984,8 +6016,13 @@ static void pe_init_port_vdm_identity_request_exit(int port) } /* Do not attempt further discovery if identity discovery failed. */ - if (pd_get_identity_discovery(port, pe[port].tx_type) == PD_DISC_FAIL) + if (pd_get_identity_discovery(port, pe[port].tx_type) == PD_DISC_FAIL) { pd_set_svids_discovery(port, pe[port].tx_type, PD_DISC_FAIL); + pd_notify_event(port, + pe[port].tx_type == TCPCI_MSG_SOP ? + PD_STATUS_EVENT_SOP_DISC_DONE : + PD_STATUS_EVENT_SOP_PRIME_DISC_DONE); + } } /** @@ -4999,16 +6036,20 @@ static void pe_init_vdm_svids_request_entry(int port) print_current_state(port); - if (pe[port].tx_type == TCPC_TX_SOP_PRIME && - !tc_is_vconn_src(port)) { + if (pe[port].tx_type == TCPCI_MSG_SOP_PRIME && + !pe_can_send_sop_prime(port)) { + /* + * The parent state already tried to enable SOP' traffic. If it + * is still disabled, there's nothing left to try. + */ pd_set_svids_discovery(port, pe[port].tx_type, PD_DISC_FAIL); set_state_pe(port, get_last_state_pe(port)); return; } msg[0] = VDO(USB_SID_PD, 1, - VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) | - CMD_DISCOVER_SVID); + VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) | + CMD_DISCOVER_SVID); tx_emsg[port].len = sizeof(uint32_t); send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF); @@ -5035,14 +6076,14 @@ static void pe_init_vdm_svids_request_run(int port) break; case VDM_RESULT_ACK: { /* Retrieve the message information. */ - uint32_t *payload = (uint32_t *) rx_emsg[port].buf; + uint32_t *payload = (uint32_t *)rx_emsg[port].buf; int sop = PD_HEADER_GET_SOP(rx_emsg[port].header); uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header); /* PE_INIT_VDM_SVIDs_ACKed embedded here */ dfp_consume_svids(port, sop, cnt, payload); break; - } + } case VDM_RESULT_NAK: /* PE_INIT_VDM_SVIDs_NAKed embedded here */ pd_set_svids_discovery(port, pe[port].tx_type, PD_DISC_FAIL); @@ -5071,9 +6112,10 @@ static void pe_init_vdm_svids_request_exit(int port) /* If SVID discovery failed, discovery is done at this point */ if (pd_get_svids_discovery(port, pe[port].tx_type) == PD_DISC_FAIL) - pe_notify_event(port, pe[port].tx_type == TCPC_TX_SOP ? - PD_STATUS_EVENT_SOP_DISC_DONE : - PD_STATUS_EVENT_SOP_PRIME_DISC_DONE); + pd_notify_event(port, + pe[port].tx_type == TCPCI_MSG_SOP ? + PD_STATUS_EVENT_SOP_DISC_DONE : + PD_STATUS_EVENT_SOP_PRIME_DISC_DONE); } /** @@ -5097,17 +6139,21 @@ static void pe_init_vdm_modes_request_entry(int port) print_current_state(port); - if (pe[port].tx_type == TCPC_TX_SOP_PRIME && - !tc_is_vconn_src(port)) { + if (pe[port].tx_type == TCPCI_MSG_SOP_PRIME && + !pe_can_send_sop_prime(port)) { + /* + * The parent state already tried to enable SOP' traffic. If it + * is still disabled, there's nothing left to try. + */ pd_set_modes_discovery(port, pe[port].tx_type, svid, - PD_DISC_FAIL); + PD_DISC_FAIL); set_state_pe(port, get_last_state_pe(port)); return; } - msg[0] = VDO((uint16_t) svid, 1, - VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) | - CMD_DISCOVER_MODES); + msg[0] = VDO((uint16_t)svid, 1, + VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) | + CMD_DISCOVER_MODES); tx_emsg[port].len = sizeof(uint32_t); send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF); @@ -5121,7 +6167,7 @@ static void pe_init_vdm_modes_request_entry(int port) static void pe_init_vdm_modes_request_run(int port) { - struct svid_mode_data *mode_data; + const struct svid_mode_data *mode_data; uint16_t requested_svid; mode_data = pd_get_next_mode(port, pe[port].tx_type); @@ -5143,29 +6189,22 @@ static void pe_init_vdm_modes_request_run(int port) break; case VDM_RESULT_ACK: { /* Retrieve the message information. */ - uint32_t *payload = (uint32_t *) rx_emsg[port].buf; + uint32_t *payload = (uint32_t *)rx_emsg[port].buf; int sop = PD_HEADER_GET_SOP(rx_emsg[port].header); uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header); - uint16_t response_svid = (uint16_t) PD_VDO_VID(payload[0]); /* * Accept ACK if the request and response SVIDs are equal; * otherwise, treat this as a NAK of the request SVID. - * - * TODO(b:169242812): support valid mode checking in - * dfp_consume_modes. */ - if (requested_svid == response_svid) { - /* PE_INIT_VDM_Modes_ACKed embedded here */ - dfp_consume_modes(port, sop, cnt, payload); - break; - } - } - /* Fall Through */ + /* PE_INIT_VDM_Modes_ACKed embedded here */ + dfp_consume_modes(port, sop, cnt, payload); + break; + } case VDM_RESULT_NAK: /* PE_INIT_VDM_Modes_NAKed embedded here */ pd_set_modes_discovery(port, pe[port].tx_type, requested_svid, - PD_DISC_FAIL); + PD_DISC_FAIL); break; } @@ -5177,10 +6216,10 @@ static void pe_init_vdm_modes_request_exit(int port) { if (pd_get_modes_discovery(port, pe[port].tx_type) != PD_DISC_NEEDED) /* Mode discovery done, notify the AP */ - pe_notify_event(port, pe[port].tx_type == TCPC_TX_SOP ? - PD_STATUS_EVENT_SOP_DISC_DONE : - PD_STATUS_EVENT_SOP_PRIME_DISC_DONE); - + pd_notify_event(port, + pe[port].tx_type == TCPCI_MSG_SOP ? + PD_STATUS_EVENT_SOP_DISC_DONE : + PD_STATUS_EVENT_SOP_PRIME_DISC_DONE); } /** @@ -5193,12 +6232,16 @@ static void pe_vdm_request_dpm_entry(int port) { print_current_state(port); - if ((pe[port].tx_type == TCPC_TX_SOP_PRIME || - pe[port].tx_type == TCPC_TX_SOP_PRIME_PRIME) && - !tc_is_vconn_src(port)) { + if ((pe[port].tx_type == TCPCI_MSG_SOP_PRIME || + pe[port].tx_type == TCPCI_MSG_SOP_PRIME_PRIME) && + !pe_can_send_sop_prime(port)) { + /* + * The parent state already tried to enable SOP' traffic. If it + * is still disabled, there's nothing left to try. + */ dpm_vdm_naked(port, pe[port].tx_type, PD_VDO_VID(pe[port].vdm_data[0]), - PD_VDO_CMD(pe[port].vdm_data[0])); + PD_VDO_CMD(pe[port].vdm_data[0]), 0); set_state_pe(port, get_last_state_pe(port)); return; } @@ -5206,20 +6249,12 @@ static void pe_vdm_request_dpm_entry(int port) /* Copy Vendor Data Objects (VDOs) into message buffer */ if (pe[port].vdm_cnt > 0) { /* Copy data after header */ - memcpy(&tx_emsg[port].buf, - (uint8_t *)pe[port].vdm_data, - pe[port].vdm_cnt * 4); + memcpy(&tx_emsg[port].buf, (uint8_t *)pe[port].vdm_data, + pe[port].vdm_cnt * 4); /* Update len with the number of VDO bytes */ tx_emsg[port].len = pe[port].vdm_cnt * 4; } - /* - * Clear the VDM nak'ed flag so that each request is - * treated separately (NAKs are handled by the - * DPM layer). Otherwise previous NAKs received will - * cause the state to exit early. - */ - PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED); send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF); /* @@ -5231,54 +6266,80 @@ static void pe_vdm_request_dpm_entry(int port) static void pe_vdm_request_dpm_run(int port) { + uint32_t vdm_hdr; + switch (parse_vdm_response_common(port)) { case VDM_RESULT_WAITING: - /* If common code didn't parse a message, continue waiting. */ + /* + * USB-PD 3.0 Rev 1.1 - 6.4.4.2.5 + * Structured VDM command consists of a command request and a + * command response (ACK, NAK, or BUSY). An exception is made + * for the Attention command which shall have no response. + * + * Since Attention commands do not have an expected reply, + * the SVDM command is complete once the Attention command + * transmit is complete. + */ + vdm_hdr = pe[port].vdm_data[0]; + if (PD_VDO_SVDM(vdm_hdr) && + (PD_VDO_CMD(vdm_hdr) == CMD_ATTENTION)) { + if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + break; + } + } + /* + * If common code didn't parse a message, and the VDM + * just sent was not an Attention message, then continue + * waiting. + */ return; case VDM_RESULT_NO_ACTION: /* * If the received message doesn't change the discovery state, * there is nothing to do but return to the previous ready - * state. + * state. This includes Attention commands which have no + * expected SVDM response. */ break; case VDM_RESULT_ACK: { /* Retrieve the message information. */ - uint32_t *payload = (uint32_t *) rx_emsg[port].buf; + uint32_t *payload = (uint32_t *)rx_emsg[port].buf; int sop = PD_HEADER_GET_SOP(rx_emsg[port].header); uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header); - uint16_t svid = PD_VDO_VID(payload[0]); - uint8_t vdm_cmd = PD_VDO_CMD(payload[0]); /* * PE initiator VDM-ACKed state for requested VDM, like * PE_INIT_VDM_FOO_ACKed, embedded here. */ dpm_vdm_acked(port, sop, cnt, payload); - - if (sop == TCPC_TX_SOP && svid == USB_SID_DISPLAYPORT && - vdm_cmd == CMD_DP_CONFIG) { - PE_SET_FLAG(port, PE_FLAGS_VDM_SETUP_DONE); - } break; - } - case VDM_RESULT_NAK: + } + case VDM_RESULT_NAK: { + uint32_t vdm_header = 0; + /* * PE initiator VDM-NAKed state for requested VDM, like * PE_INIT_VDM_FOO_NAKed, embedded here. */ - PE_SET_FLAG(port, PE_FLAGS_VDM_SETUP_DONE); /* * Because Not Supported messages or response timeouts are * treated as NAKs, there may not be a NAK message to parse. - * Extract the needed information from the sent VDM. + * Extract the needed information from the sent VDM, and send + * the NAK if present. */ + if (PD_HEADER_TYPE(rx_emsg[port].header) == + PD_DATA_VENDOR_DEF && + PD_HEADER_CNT(rx_emsg[port].header) > 0) + vdm_header = ((uint32_t *)rx_emsg[port].buf)[0]; + dpm_vdm_naked(port, pe[port].tx_type, - PD_VDO_VID(pe[port].vdm_data[0]), - PD_VDO_CMD(pe[port].vdm_data[0])); + PD_VDO_VID(pe[port].vdm_data[0]), + PD_VDO_CMD(pe[port].vdm_data[0]), vdm_header); break; } + } /* Return to calling state (PE_{SRC,SNK}_Ready) */ set_state_pe(port, get_last_state_pe(port)); @@ -5286,12 +6347,29 @@ static void pe_vdm_request_dpm_run(int port) static void pe_vdm_request_dpm_exit(int port) { + if (PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT)) { + PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT); + + /* + * Mark failure to respond as discovery failure. + * + * For PD 2.0 partners (6.10.3 Applicability of Structured VDM + * Commands Note 3): + * + * If Structured VDMs are not supported, a Structured VDM + * Command received by a DFP or UFP Shall be Ignored. + */ + dpm_vdm_naked(port, pe[port].tx_type, + PD_VDO_VID(pe[port].vdm_data[0]), + PD_VDO_CMD(pe[port].vdm_data[0]), 0); + } + /* * Force Tx type to be reset before reentering a VDM state, unless the * current VDM request will be resumed. */ if (!PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_CONTINUE)) - pe[port].tx_type = TCPC_TX_INVALID; + pe[port].tx_type = TCPCI_MSG_INVALID; } /** @@ -5299,13 +6377,10 @@ static void pe_vdm_request_dpm_exit(int port) */ static void pe_vdm_response_entry(int port) { - int response_size_bytes = 0; + int vdo_len = 0; uint32_t *rx_payload; uint32_t *tx_payload; - uint16_t vdo_vdm_svid; uint8_t vdo_cmd; - uint8_t vdo_opos = 0; - int cmd_type; svdm_rsp_func func = NULL; print_current_state(port); @@ -5316,18 +6391,48 @@ static void pe_vdm_response_entry(int port) /* Get the message */ rx_payload = (uint32_t *)rx_emsg[port].buf; - vdo_vdm_svid = PD_VDO_VID(rx_payload[0]); + /* Extract VDM command from the VDM header */ vdo_cmd = PD_VDO_CMD(rx_payload[0]); - cmd_type = PD_VDO_CMDT(rx_payload[0]); - rx_payload[0] &= ~VDO_CMDT_MASK; - - if (cmd_type != CMDT_INIT) { - CPRINTF("ERR:CMDT:%d:%d\n", cmd_type, vdo_cmd); + /* This must be a command request to proceed further */ + if (PD_VDO_CMDT(rx_payload[0]) != CMDT_INIT) { + CPRINTF("ERR:CMDT:%d:%d\n", PD_VDO_CMDT(rx_payload[0]), + vdo_cmd); pe_set_ready_state(port); return; } + tx_payload = (uint32_t *)tx_emsg[port].buf; + /* + * Designed in TCPMv1, svdm_response functions use same + * buffer to take received data and overwrite with response + * data. To work with this interface, here copy rx data to + * tx buffer and pass tx_payload to func. + * TODO(b/166455363): change the interface to pass both rx + * and tx buffer. + * + * The SVDM header is dependent on both VDM command request being + * replied to and the result of response function. The SVDM command + * message is copied into tx_payload. tx_payload[0] is the VDM header + * for the response message. The SVDM response function takes the role + * of the DPM layer and will indicate the response type (ACK/NAK/BUSY) + * by its return value (vdo_len) + * vdo_len > 0 --> ACK + * vdo_len == 0 --> NAK + * vdo_len < 0 --> BUSY + */ + memcpy(tx_payload, rx_payload, PD_HEADER_CNT(rx_emsg[port].header) * 4); + /* + * Clear fields in SVDM response message that will be set based on the + * result of the svdm response function. + */ + tx_payload[0] &= ~VDO_CMDT_MASK; + tx_payload[0] &= ~VDO_SVDM_VERS(0x3); + + /* Add SVDM structured version being used */ + tx_payload[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)); + + /* Use VDM command to select the response handler function */ switch (vdo_cmd) { case CMD_DISCOVER_IDENT: func = svdm_rsp.identity; @@ -5339,7 +6444,6 @@ static void pe_vdm_response_entry(int port) func = svdm_rsp.modes; break; case CMD_ENTER_MODE: - vdo_opos = PD_VDO_OPOS(rx_payload[0]); func = svdm_rsp.enter_mode; break; case CMD_DP_STATUS: @@ -5351,7 +6455,6 @@ static void pe_vdm_response_entry(int port) func = svdm_rsp.amode->config; break; case CMD_EXIT_MODE: - vdo_opos = PD_VDO_OPOS(rx_payload[0]); func = svdm_rsp.exit_mode; break; #ifdef CONFIG_USB_PD_ALT_MODE_DFP @@ -5360,7 +6463,8 @@ static void pe_vdm_response_entry(int port) * attention is only SVDM with no response * (just goodCRC) return zero here. */ - dfp_consume_attention(port, rx_payload); + dpm_notify_attention(port, PD_HEADER_CNT(rx_emsg[port].header), + rx_payload); pe_set_ready_state(port); return; #endif @@ -5368,77 +6472,75 @@ static void pe_vdm_response_entry(int port) CPRINTF("VDO ERR:CMD:%d\n", vdo_cmd); } - tx_payload = (uint32_t *)tx_emsg[port].buf; - - if (func) { + /* + * If the port partner is PD_REV20 and our data role is DFP, we must + * reply to any SVDM command with a NAK. If the SVDM was an Attention + * command, it does not have a response, and exits the function above. + */ + if (func && (prl_get_rev(port, TCPCI_MSG_SOP) != PD_REV20 || + pe[port].data_role == PD_ROLE_UFP)) { /* - * Designed in TCPMv1, svdm_response functions use same - * buffer to take received data and overwrite with response - * data. To work with this interface, here copy rx data to - * tx buffer and pass tx_payload to func. - * TODO(b/166455363): change the interface to pass both rx - * and tx buffer + * Execute SVDM response function selected above and set the + * correct response type in the VDM header. */ - memcpy(tx_payload, rx_payload, rx_emsg[port].len); + vdo_len = func(port, tx_payload); + if (vdo_len > 0) { + tx_payload[0] |= VDO_CMDT(CMDT_RSP_ACK); + /* + * If command response is an ACK and if the command was + * either enter/exit mode, then update the PE modal flag + * accordingly and cancel any DFP swap attempts. + */ + if (vdo_cmd == CMD_ENTER_MODE) { + PE_CLR_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP); + PE_SET_FLAG(port, PE_FLAGS_MODAL_OPERATION); + } + if (vdo_cmd == CMD_EXIT_MODE) + PE_CLR_FLAG(port, PE_FLAGS_MODAL_OPERATION); + } else if (!vdo_len) { + tx_payload[0] |= VDO_CMDT(CMDT_RSP_NAK); + vdo_len = 1; + } else { + tx_payload[0] |= VDO_CMDT(CMDT_RSP_BUSY); + vdo_len = 1; + } + } else { /* - * Return value of func is the data objects count in payload. - * return 1 means only VDM header, no VDO. + * Received at VDM command which is not supported. PD 2.0 may + * NAK or ignore the message (see TD.PD.VNDI.E1. VDM Identity + * steps), but PD 3.0 must send Not_Supported (PD 3.0 Ver 2.0 + + * ECNs 2020-12-10 Table 6-64 Response to an incoming + * VDM or TD.PD.VNDI3.E3 VDM Identity steps) */ - response_size_bytes = - func(port, tx_payload) * sizeof(*tx_payload); - if (response_size_bytes > 0) - /* ACK */ - tx_payload[0] = VDO( - vdo_vdm_svid, - 1, /* Structured VDM */ - VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)) - | VDO_CMDT(CMDT_RSP_ACK) | - VDO_OPOS(vdo_opos) | - vdo_cmd); - else if (response_size_bytes == 0) - /* NAK */ - tx_payload[0] = VDO( - vdo_vdm_svid, - 1, /* Structured VDM */ - VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)) - | VDO_CMDT(CMDT_RSP_NAK) | - VDO_OPOS(vdo_opos) | - vdo_cmd); - else - /* BUSY */ - tx_payload[0] = VDO( - vdo_vdm_svid, - 1, /* Structured VDM */ - VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)) - | VDO_CMDT(CMDT_RSP_BUSY) | - VDO_OPOS(vdo_opos) | - vdo_cmd); - - if (response_size_bytes <= 0) - response_size_bytes = 4; - } else { - /* not supported : NAK it */ - tx_payload[0] = VDO( - vdo_vdm_svid, - 1, /* Structured VDM */ - VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)) | - VDO_CMDT(CMDT_RSP_NAK) | - VDO_OPOS(vdo_opos) | - vdo_cmd); - response_size_bytes = 4; + if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV30) { + set_state_pe(port, PE_SEND_NOT_SUPPORTED); + return; + } + tx_payload[0] |= VDO_CMDT(CMDT_RSP_NAK); + vdo_len = 1; } - /* Send ACK, NAK, or BUSY */ - tx_emsg[port].len = response_size_bytes; - send_data_msg(port, TCPC_TX_SOP, PD_DATA_VENDOR_DEF); + /* Send response message. Note len is in bytes, not VDO objects */ + tx_emsg[port].len = (vdo_len * sizeof(uint32_t)); + send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_VENDOR_DEF); } static void pe_vdm_response_run(int port) { + /* + * This state waits for a VDM response message to be sent. Return to the + * ready state once the message has been sent, a protocol error was + * detected, or if the VDM response msg was discarded based on being + * interrupted by another rx message. Since VDM sequences are AMS + * interruptible, there is no need to soft reset regardless of exit + * reason. + */ if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE) || - PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { - PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE | - PE_FLAGS_PROTOCOL_ERROR); + PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR) || + PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { + PE_CLR_MASK(port, BIT(PE_FLAGS_TX_COMPLETE_FN) | + BIT(PE_FLAGS_PROTOCOL_ERROR_FN) | + BIT(PE_FLAGS_MSG_DISCARDED_FN)); pe_set_ready_state(port); } @@ -5463,28 +6565,32 @@ static void pe_enter_usb_entry(int port) return; } - usb4_payload = enter_usb_setup_next_msg(port); - /* Port is already in USB4 mode, do not send enter USB message again */ - if (usb4_payload < 0) { + if (enter_usb_entry_is_done(port)) { pe_set_ready_state(port); return; } + if ((pe[port].tx_type == TCPCI_MSG_SOP_PRIME || + pe[port].tx_type == TCPCI_MSG_SOP_PRIME_PRIME) && + !tc_is_vconn_src(port)) { + if (port_try_vconn_swap(port)) + return; + } + + pe[port].tx_type = TCPCI_MSG_SOP; + usb4_payload = enter_usb_setup_next_msg(port, &pe[port].tx_type); + if (!usb4_payload) { enter_usb_failed(port); pe_set_ready_state(port); return; } - /* - * TODO: b/156749387 In case of Enter USB SOP'/SOP'', check if the port - * is the VCONN source, if not, request for a VCONN swap. - */ tx_emsg[port].len = sizeof(usb4_payload); memcpy(tx_emsg[port].buf, &usb4_payload, tx_emsg[port].len); - send_data_msg(port, TCPC_TX_SOP, PD_DATA_ENTER_USB); + send_data_msg(port, pe[port].tx_type, PD_DATA_ENTER_USB); pe_sender_response_msg_entry(port); } @@ -5513,7 +6619,7 @@ static void pe_enter_usb_run(int port) return; } - if (get_time().val > pe[port].sender_response_timer) { + if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) { pe_set_ready_state(port); enter_usb_failed(port); return; @@ -5550,6 +6656,11 @@ static void pe_enter_usb_run(int port) } } +static void pe_enter_usb_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + #ifdef CONFIG_USBC_VCONN /* * PE_VCS_Evaluate_Swap @@ -5575,37 +6686,20 @@ static void pe_vcs_evaluate_swap_entry(int port) */ /* DPM rejects a VCONN Swap and port is not a VCONN source*/ - if (!tc_check_vconn_swap(port) && tc_is_vconn_src(port) < 1) { + if (!tc_check_vconn_swap(port) || tc_is_vconn_src(port) < 1) { /* NOTE: PE_VCS_Reject_Swap State embedded here */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_REJECT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT); } /* Port is not ready to perform a VCONN swap */ else if (tc_is_vconn_src(port) < 0) { /* NOTE: PE_VCS_Reject_Swap State embedded here */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_WAIT); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_WAIT); } /* Port is ready to perform a VCONN swap */ else { /* NOTE: PE_VCS_Accept_Swap State embedded here */ PE_SET_FLAG(port, PE_FLAGS_ACCEPT); - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT); - - /* - * The USB PD 3.0 spec indicates that the initial VCONN source - * shall cease sourcing VCONN within tVCONNSourceOff (25ms) - * after receiving the PS_RDY message. However, some partners - * begin sending SOP' messages only 1 ms after sending PS_RDY - * during VCONN swap. - * - * Preemptively disable receipt of SOP' and SOP'' messages while - * we wait for PS_RDY so we don't attempt to process messages - * directed at the cable. If the partner fails to send PS_RDY we - * perform a hard reset so no need to re-enable SOP' messages. - * - * We continue to source VCONN while we wait as required by the - * spec. - */ - tcpm_sop_prime_disable(port); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT); } } @@ -5630,7 +6724,11 @@ static void pe_vcs_evaluate_swap_run(int port) */ pe_set_ready_state(port); } + return; } + + if (pe_check_outgoing_discard(port)) + return; } /* @@ -5641,7 +6739,7 @@ static void pe_vcs_send_swap_entry(int port) print_current_state(port); /* Send a VCONN_Swap Message */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_VCONN_SWAP); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_VCONN_SWAP); pe_sender_response_msg_entry(port); } @@ -5649,7 +6747,7 @@ static void pe_vcs_send_swap_run(int port) { uint8_t type; uint8_t cnt; - enum tcpm_transmit_type sop; + enum tcpci_msg_type sop; enum pe_msg_check msg_check; /* @@ -5661,6 +6759,9 @@ static void pe_vcs_send_swap_run(int port) PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + /* Increment once message has successfully sent */ + pe[port].vconn_swap_counter++; + type = PD_HEADER_TYPE(rx_emsg[port].header); cnt = PD_HEADER_CNT(rx_emsg[port].header); sop = PD_HEADER_GET_SOP(rx_emsg[port].header); @@ -5677,18 +6778,13 @@ static void pe_vcs_send_swap_run(int port) * 2) The Port is not presently the VCONN Source. */ if (type == PD_CTRL_ACCEPT) { - pe[port].vconn_swap_counter = 0; if (tc_is_vconn_src(port)) { - /* - * Prevent receiving any SOP' and SOP'' - * messages while a swap is in progress. - */ - tcpm_sop_prime_disable(port); - set_state_pe(port, + set_state_pe( + port, PE_VCS_WAIT_FOR_VCONN_SWAP); } else { set_state_pe(port, - PE_VCS_TURN_ON_VCONN_SWAP); + PE_VCS_TURN_ON_VCONN_SWAP); } return; } @@ -5702,15 +6798,28 @@ static void pe_vcs_send_swap_run(int port) pe_set_ready_state(port); return; } + + /* + * The Policy Engine May transition to the + * PE_VCS_Force_Vconn state when: + * - A Not_Supported Message is received and + * - The Port is not presently the VCONN Source + */ + if (type == PD_CTRL_NOT_SUPPORTED) { + if (IS_ENABLED(CONFIG_USB_PD_REV30) && + !tc_is_vconn_src(port)) + set_state_pe(port, PE_VCS_FORCE_VCONN); + else + pe_set_ready_state(port); + return; + } } /* - * Unexpected Data Message Received + * Unexpected Message Received, send soft reset with SOP* of + * incoming message. */ - else { - /* Send Soft Reset */ - pe_send_soft_reset(port, sop); - return; - } + pe_send_soft_reset(port, sop); + return; } /* @@ -5720,10 +6829,15 @@ static void pe_vcs_send_swap_run(int port) * 2) Message was discarded. */ if ((msg_check & PE_MSG_DISCARDED) || - get_time().val > pe[port].sender_response_timer) + pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) pe_set_ready_state(port); } +static void pe_vcs_send_swap_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + /* * PE_VCS_Wait_for_VCONN_Swap */ @@ -5732,7 +6846,23 @@ static void pe_vcs_wait_for_vconn_swap_entry(int port) print_current_state(port); /* Start the VCONNOnTimer */ - pe[port].vconn_on_timer = get_time().val + PD_T_VCONN_SOURCE_ON; + pd_timer_enable(port, PE_TIMER_VCONN_ON, PD_T_VCONN_SOURCE_ON); + + /* + * The USB PD 3.0 spec indicates that the initial VCONN source + * shall cease sourcing VCONN within tVCONNSourceOff (25ms) + * after receiving the PS_RDY message. However, some partners + * begin sending SOP' messages only 1 ms after sending PS_RDY + * during VCONN swap. + * + * Preemptively disable receipt of SOP' and SOP'' messages while + * we wait for PS_RDY so we don't attempt to process messages + * directed at the cable. + * + * We continue to source VCONN while we wait as required by the + * spec. + */ + tcpm_sop_prime_enable(port, false); } static void pe_vcs_wait_for_vconn_swap_run(int port) @@ -5742,15 +6872,26 @@ static void pe_vcs_wait_for_vconn_swap_run(int port) * 1) A PS_RDY Message is received. */ if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { - PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); /* * PS_RDY message received + * + * Note: intentionally leave the receive flag set to indicate + * our route on exit when PS_RDY is received. */ if ((PD_HEADER_CNT(rx_emsg[port].header) == 0) && - (PD_HEADER_TYPE(rx_emsg[port].header) == - PD_CTRL_PS_RDY)) { + (PD_HEADER_EXT(rx_emsg[port].header) == 0) && + (PD_HEADER_TYPE(rx_emsg[port].header) == PD_CTRL_PS_RDY)) { set_state_pe(port, PE_VCS_TURN_OFF_VCONN_SWAP); return; + } else { + /* + * Unexpected message received - reset with the SOP* of + * the incoming message. + */ + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + pe_send_soft_reset( + port, PD_HEADER_GET_SOP(rx_emsg[port].header)); + return; } } @@ -5759,14 +6900,25 @@ static void pe_vcs_wait_for_vconn_swap_run(int port) * PE_SNK_Hard_Reset state when: * 1) The VCONNOnTimer times out. */ - if (get_time().val > pe[port].vconn_on_timer) { - if (pe[port].power_role == PD_ROLE_SOURCE) - set_state_pe(port, PE_SRC_HARD_RESET); - else - set_state_pe(port, PE_SNK_HARD_RESET); + if (pd_timer_is_expired(port, PE_TIMER_VCONN_ON)) { + pe_set_hard_reset(port); } } +static void pe_vcs_wait_for_vconn_swap_exit(int port) +{ + /* + * If we exited without getting PS_RDY, re-enable SOP' messaging since + * we are still the Vconn source. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + else + tcpm_sop_prime_enable(port, true); + + pd_timer_disable(port, PE_TIMER_VCONN_ON); +} + /* * PE_VCS_Turn_On_VCONN_Swap */ @@ -5776,26 +6928,30 @@ static void pe_vcs_turn_on_vconn_swap_entry(int port) /* Request DPM to turn on VCONN */ pd_request_vconn_swap_on(port); - pe[port].timeout = 0; } static void pe_vcs_turn_on_vconn_swap_run(int port) { - /* * Transition to the PE_VCS_Send_Ps_Rdy state when: * 1) The Port’s VCONN is on. */ - if (pe[port].timeout == 0 && - PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) { + if (pd_timer_is_disabled(port, PE_TIMER_TIMEOUT) && + PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE); - pe[port].timeout = get_time().val + PD_VCONN_SWAP_DELAY; + pd_timer_enable(port, PE_TIMER_TIMEOUT, + CONFIG_USBC_VCONN_SWAP_DELAY_US); } - if (pe[port].timeout > 0 && get_time().val > pe[port].timeout) + if (pd_timer_is_expired(port, PE_TIMER_TIMEOUT)) set_state_pe(port, PE_VCS_SEND_PS_RDY_SWAP); } +static void pe_vcs_turn_on_vconn_swap_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_TIMEOUT); +} + /* * PE_VCS_Turn_Off_VCONN_Swap */ @@ -5805,321 +6961,1251 @@ static void pe_vcs_turn_off_vconn_swap_entry(int port) /* Request DPM to turn off VCONN */ pd_request_vconn_swap_off(port); - pe[port].timeout = 0; } static void pe_vcs_turn_off_vconn_swap_run(int port) { /* Wait for VCONN to turn off */ - if (pe[port].timeout == 0 && - PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) { + if (PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE); - pe[port].timeout = get_time().val + PD_VCONN_SWAP_DELAY; + + /* + * A VCONN Swap Shall reset the DiscoverIdentityCounter + * to zero + */ + pe[port].discover_identity_counter = 0; + pe[port].dr_swap_attempt_counter = 0; + + if (PE_CHK_FLAG(port, PE_FLAGS_ENTERING_EPR)) + set_state_pe(port, + PE_SNK_EPR_MODE_ENTRY_WAIT_FOR_RESPONSE); + else + pe_set_ready_state(port); + return; + } +} + +/* + * PE_VCS_Send_PS_Rdy_Swap + */ +static void pe_vcs_send_ps_rdy_swap_entry(int port) +{ + print_current_state(port); + + /* Check for any interruptions to this non-interruptible AMS */ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + enum tcpci_msg_type sop = + PD_HEADER_GET_SOP(rx_emsg[port].header); + + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + /* Soft reset with the SOP* of the incoming message */ + pe_send_soft_reset(port, sop); + return; + } + + /* Send a PS_RDY Message */ + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PS_RDY); +} + +static void pe_vcs_send_ps_rdy_swap_run(int port) +{ + /* + * After a VCONN Swap the VCONN Source needs to reset + * the Cable Plug’s Protocol Layer in order to ensure + * MessageID synchronization. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + /* + * A VCONN Swap Shall reset the + * DiscoverIdentityCounter to zero + */ + pe[port].discover_identity_counter = 0; + pe[port].dr_swap_attempt_counter = 0; + + /* A SOP' soft reset is required after VCONN swap */ + pd_dpm_request(port, DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND); + pe_set_ready_state(port); + } + + if (pe_check_outgoing_discard(port)) + return; + + if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + /* PS_RDY didn't send, soft reset */ + pe_send_soft_reset(port, TCPCI_MSG_SOP); } +} + +/* + * PE_VCS_Force_Vconn + */ +__maybe_unused static void pe_vcs_force_vconn_entry(int port) +{ + print_current_state(port); + + /* Request DPM to turn on VCONN */ + pd_request_vconn_swap_on(port); +} + +__maybe_unused static void pe_vcs_force_vconn_run(int port) +{ + /* + * The Policy Engine Shall transition back to either the PE_SRC_Ready + * or PE_SNK_Ready state when: + * 1) The Port’s VCONN is on. + * + * Note we'll wait CONFIG_USBC_VCONN_SWAP_DELAY_US, as defined by the + * board, to ensure Vconn is on. + */ + if (pd_timer_is_disabled(port, PE_TIMER_TIMEOUT) && + PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE); + pd_timer_enable(port, PE_TIMER_TIMEOUT, + CONFIG_USBC_VCONN_SWAP_DELAY_US); + } + + if (pd_timer_is_expired(port, PE_TIMER_TIMEOUT)) { + /* + * Note: A cable soft reset shouldn't be necessary as a + * Not_Supported reply means the partner doesn't support + * sourcing Vconn and did not communicate with the cable. + */ + pe_set_ready_state(port); + return; + } +} + +__maybe_unused static void pe_vcs_force_vconn_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_TIMEOUT); +} + +/* + * PE_VCS_CBL_SEND_SOFT_RESET + * Note - Entry is only when directed by the DPM. Protocol errors are handled + * by the PE_SEND_SOFT_RESET state. + */ +static void pe_vcs_cbl_send_soft_reset_entry(int port) +{ + print_current_state(port); + + if (!pe_can_send_sop_prime(port)) { + /* + * If we're not VCONN source, return the appropriate state. + * A VCONN swap re-triggers sending SOP' soft reset + */ + if (pe_is_explicit_contract(port)) { + /* Return to PE_{SRC,SNK}_Ready state */ + pe_set_ready_state(port); + } else { + /* + * Not in Explicit Contract, so we must be a SRC, + * return to PE_Src_Send_Capabilities. + */ + set_state_pe(port, PE_SRC_SEND_CAPABILITIES); + } + return; + } + + send_ctrl_msg(port, TCPCI_MSG_SOP_PRIME, PD_CTRL_SOFT_RESET); + pe_sender_response_msg_entry(port); +} + +static void pe_vcs_cbl_send_soft_reset_run(int port) +{ + bool cable_soft_reset_complete = false; + enum pe_msg_check msg_check; + + msg_check = pe_sender_response_msg_run(port); + + /* Got ACCEPT or REJECT from Cable Plug */ + if ((msg_check & PE_MSG_SENT) && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + cable_soft_reset_complete = true; + + /* + * Note: If port partner runs PD 2.0, we must use PD 2.0 to + * communicate with the cable plug when in an explicit contract. + * + * PD Spec Table 6-2: Revision Interoperability during an + * Explicit Contract + */ + if (prl_get_rev(port, TCPCI_MSG_SOP) != PD_REV20) + set_cable_rev(port, + PD_HEADER_REV(rx_emsg[port].header)); + } + + /* No GoodCRC received, cable is not present */ + if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + /* + * TODO(b/171823328): TCPMv2: Implement cable reset + * Cable reset will only be done here if we know for certain + * a cable is present (we've received the SOP' DiscId response). + */ + cable_soft_reset_complete = true; + } + + if (cable_soft_reset_complete || + pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE) || + (msg_check & PE_MSG_DISCARDED)) { + if (pe_is_explicit_contract(port)) { + /* Return to PE_{SRC,SNK}_Ready state */ + pe_set_ready_state(port); + } else { + /* + * Not in Explicit Contract, so we must be a SRC, + * return to PE_Src_Send_Capabilities. + */ + set_state_pe(port, PE_SRC_SEND_CAPABILITIES); + } + } +} + +static void pe_vcs_cbl_send_soft_reset_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + +#endif /* CONFIG_USBC_VCONN */ + +/* + * PE_DR_SNK_Get_Sink_Cap and PE_SRC_Get_Sink_Cap State (shared) + */ +static void pe_dr_get_sink_cap_entry(int port) +{ + print_current_state(port); + + /* Send a Get Sink Cap Message */ + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GET_SINK_CAP); + pe_sender_response_msg_entry(port); +} + +static void pe_dr_get_sink_cap_run(int port) +{ + int type; + int cnt; + int ext; + enum pe_msg_check msg_check; + enum tcpci_msg_type sop; + + /* + * Check the state of the message sent + */ + msg_check = pe_sender_response_msg_run(port); + + /* + * Transition to PE_[SRC,SNK]_Ready when: + * 1) A Sink_Capabilities Message is received + * 2) Or SenderResponseTimer times out + * 3) Or a Reject Message is received. + * + * Transition to PE_SEND_SOFT_RESET state when: + * 1) An unexpected message is received + */ + if ((msg_check & PE_MSG_SENT) && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + type = PD_HEADER_TYPE(rx_emsg[port].header); + cnt = PD_HEADER_CNT(rx_emsg[port].header); + ext = PD_HEADER_EXT(rx_emsg[port].header); + sop = PD_HEADER_GET_SOP(rx_emsg[port].header); + + if (ext == 0 && sop == TCPCI_MSG_SOP) { + if ((cnt > 0) && (type == PD_DATA_SINK_CAP)) { + uint32_t *payload = + (uint32_t *)rx_emsg[port].buf; + uint8_t cap_cnt = + rx_emsg[port].len / sizeof(uint32_t); + + pe_set_snk_caps(port, cap_cnt, payload); + + dpm_evaluate_sink_fixed_pdo(port, payload[0]); + pe_set_ready_state(port); + return; + } else if (cnt == 0 && + (type == PD_CTRL_REJECT || + type == PD_CTRL_NOT_SUPPORTED)) { + pe_set_ready_state(port); + return; + } + /* Unexpected messages fall through to soft reset */ + } + + pe_send_soft_reset(port, sop); + return; + } + + /* + * Transition to PE_[SRC,SNK]_Ready state when: + * 1) SenderResponseTimer times out. + * 2) Message was discarded. + */ + if ((msg_check & PE_MSG_DISCARDED) || + pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) + pe_set_ready_state(port); +} + +static void pe_dr_get_sink_cap_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + +/* + * PE_DR_SNK_Give_Source_Cap + */ +static void pe_dr_snk_give_source_cap_entry(int port) +{ + print_current_state(port); + + /* Send source capabilities. */ + send_source_cap(port); +} + +static void pe_dr_snk_give_source_cap_run(int port) +{ + /* + * Transition back to PE_SNK_Ready when the Source_Capabilities message + * has been successfully sent. + * + * Get Source Capabilities AMS is uninterruptible, but in case the + * partner violates the spec then send a soft reset rather than get + * stuck here. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + set_state_pe(port, PE_SNK_READY); + } else if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { + pe_send_soft_reset(port, TCPCI_MSG_SOP); + } +} + +/* + * PE_DR_SRC_Get_Source_Cap + */ +static void pe_dr_src_get_source_cap_entry(int port) +{ + print_current_state(port); + + /* Send a Get_Source_Cap Message */ + tx_emsg[port].len = 0; + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GET_SOURCE_CAP); + pe_sender_response_msg_entry(port); +} + +static void pe_dr_src_get_source_cap_run(int port) +{ + int type; + int cnt; + int ext; + enum pe_msg_check msg_check; + + /* + * Check the state of the message sent + */ + msg_check = pe_sender_response_msg_run(port); + + /* + * Transition to PE_SRC_Ready when: + * 1) A Source Capabilities Message is received. + * 2) A Reject Message is received. + */ + if ((msg_check & PE_MSG_SENT) && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + type = PD_HEADER_TYPE(rx_emsg[port].header); + cnt = PD_HEADER_CNT(rx_emsg[port].header); + ext = PD_HEADER_EXT(rx_emsg[port].header); + + if (ext == 0) { + if ((cnt > 0) && (type == PD_DATA_SOURCE_CAP)) { + uint32_t *payload = + (uint32_t *)rx_emsg[port].buf; + + pd_set_src_caps(port, cnt, payload); + + /* + * If we'd prefer to charge from this partner, + * then propose a PR swap. + */ + if (pd_can_charge_from_device(port, cnt, + payload)) + pd_request_power_swap(port); + + /* + * Report dual role power capability to the + * charge manager if present + */ + if (IS_ENABLED(CONFIG_CHARGE_MANAGER) && + pd_get_partner_dual_role_power(port)) + charge_manager_update_dualrole( + port, CAP_DUALROLE); + + set_state_pe(port, PE_SRC_READY); + } else if ((cnt == 0) && + (type == PD_CTRL_REJECT || + type == PD_CTRL_NOT_SUPPORTED)) { + pd_set_src_caps(port, -1, NULL); + set_state_pe(port, PE_SRC_READY); + } else { + /* + * On protocol error, consider source cap + * retrieval a failure + */ + pd_set_src_caps(port, -1, NULL); + set_state_pe(port, PE_SEND_SOFT_RESET); + } + return; + } else { + pd_set_src_caps(port, -1, NULL); + set_state_pe(port, PE_SEND_SOFT_RESET); + return; + } + } + + /* + * Transition to PE_SRC_Ready state when: + * 1) the SenderResponseTimer times out. + * 2) Message was discarded. + */ + if ((msg_check & PE_MSG_DISCARDED) || + pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) + set_state_pe(port, PE_SRC_READY); +} + +static void pe_dr_src_get_source_cap_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + +/* + * PE_Get_Revision + */ +__maybe_unused static void pe_get_revision_entry(int port) +{ + print_current_state(port); + + /* Send a Get_Revision message */ + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GET_REVISION); + pe_sender_response_msg_entry(port); +} + +__maybe_unused static void pe_get_revision_run(int port) +{ + int type; + int cnt; + int ext; + enum pe_msg_check msg_check; + + /* Check the state of the message sent */ + msg_check = pe_sender_response_msg_run(port); + + if ((msg_check & PE_MSG_SENT) && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + type = PD_HEADER_TYPE(rx_emsg[port].header); + cnt = PD_HEADER_CNT(rx_emsg[port].header); + ext = PD_HEADER_EXT(rx_emsg[port].header); + + if (ext == 0 && cnt == 1 && type == PD_DATA_REVISION) { + /* Revision returned by partner */ + pe[port].partner_rmdo = + *((struct rmdo *)rx_emsg[port].buf); + } else if (type != PD_CTRL_NOT_SUPPORTED) { + /* + * If the partner response with a message other than + * Revision or Not_Supported, there was an interrupt. + * Setting PE_FLAGS_MSG_RECEIVED to handle unexpected + * message. + */ + PE_SET_FLAG(port, PE_FLAGS_MSG_RECEIVED); + } + + /* + * Get_Revision is an interruptible AMS. Return to ready state + * after response whether or not there was a protocol error. + */ + pe_set_ready_state(port); + return; + } + + /* + * Return to ready state if the message was discarded or timer expires + */ + if ((msg_check & PE_MSG_DISCARDED) || + pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) + pe_set_ready_state(port); +} + +__maybe_unused static void pe_get_revision_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + +#ifdef CONFIG_USB_PD_DATA_RESET_MSG +/* + * PE_UDR_Send_Data_Reset + * See PD r. 3.1, v. 1.3, Figure 8-89. + */ +static void pe_udr_send_data_reset_entry(int port) +{ + print_current_state(port); + /* Send Data Reset Message */ + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_DATA_RESET); + pe_sender_response_msg_entry(port); +} + +static void pe_udr_send_data_reset_run(int port) +{ + enum pe_msg_check msg_check = pe_sender_response_msg_run(port); + + /* Handle Discarded message, return to PE_SNK/SRC_READY */ + if (msg_check & PE_MSG_DISCARDED) { + pe_set_ready_state(port); + return; + } else if (msg_check == PE_MSG_SEND_PENDING) { + /* Wait until message is sent */ + return; + } + + /* + * Transition to the next Data Reset state after receiving Accept. + * Return to the ready state after receiving Not Supported. After + * receiving Reject or any other message type (Protocol Error), + * transition to Error Recovery. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + const uint32_t hdr = rx_emsg[port].header; + + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + if (PD_HEADER_GET_SOP(hdr) == TCPCI_MSG_SOP && + PD_HEADER_CNT(hdr) == 0 && !PD_HEADER_EXT(hdr) && + PD_HEADER_TYPE(hdr) == PD_CTRL_ACCEPT) { + set_state_pe( + port, + tc_is_vconn_src(port) ? + PE_UDR_TURN_OFF_VCONN : + PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE); + return; + } else if (PD_HEADER_GET_SOP(hdr) == TCPCI_MSG_SOP && + PD_HEADER_CNT(hdr) == 0 && !PD_HEADER_EXT(hdr) && + PD_HEADER_TYPE(hdr) == PD_CTRL_NOT_SUPPORTED) { + /* Just pretend it worked. */ + dpm_data_reset_complete(port); + pe_set_ready_state(port); + return; + } + + /* Otherwise, it's a protocol error. */ + PE_SET_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + } + + if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE) || + PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + return; + } +} + +static void pe_udr_send_data_reset_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + +/* PE_UDR_Data_Reset_Received */ +static void pe_udr_data_reset_received_entry(int port) +{ + print_current_state(port); + /* send accept message */ + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT); +} + +static void pe_udr_data_reset_received_run(int port) +{ + if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + if (tc_is_vconn_src(port)) + set_state_pe(port, PE_UDR_TURN_OFF_VCONN); + else + set_state_pe(port, PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE); + } else if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR) || + PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + PE_CLR_FLAG(port, PE_FLAGS_MSG_DISCARDED); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + } +} + +/* PE_UDR_Turn_Off_VCONN */ +static void pe_udr_turn_off_vconn_entry(int port) +{ + print_current_state(port); + /* Tell device policy manager to turn off VCONN */ + pd_request_vconn_swap_off(port); +} + +static void pe_udr_turn_off_vconn_run(int port) +{ + /* Wait until VCONN is fully discharged */ + if (pd_timer_is_disabled(port, PE_TIMER_TIMEOUT) && + PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE); + pd_timer_enable(port, PE_TIMER_TIMEOUT, + CONFIG_USBC_VCONN_SWAP_DELAY_US); + } + + if (pd_timer_is_expired(port, PE_TIMER_TIMEOUT)) + set_state_pe(port, PE_UDR_SEND_PS_RDY); +} + +/* PE_UDR_Send_Ps_Rdy */ +static void pe_udr_send_ps_rdy_entry(int port) +{ + print_current_state(port); + /* Send PS Ready message */ + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PS_RDY); +} + +static void pe_udr_send_ps_rdy_run(int port) +{ + if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + set_state_pe(port, PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE); + } else if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR) || + PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + PE_CLR_FLAG(port, PE_FLAGS_MSG_DISCARDED); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + } +} + +/* PE_UDR_Wait_For_Data_Reset_Complete */ +static void pe_udr_wait_for_data_reset_complete_entry(int port) +{ + print_current_state(port); +} + +static void pe_udr_wait_for_data_reset_complete_run(int port) +{ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + const uint32_t hdr = rx_emsg[port].header; + + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + /* Expecting Data_Reset_Complete. */ + if (PD_HEADER_GET_SOP(hdr) == TCPCI_MSG_SOP && + PD_HEADER_CNT(hdr) == 0 && !PD_HEADER_EXT(hdr) && + PD_HEADER_TYPE(hdr) == PD_CTRL_DATA_RESET_COMPLETE) { + pe_set_ready_state(port); + return; + } + + /* + * Any other message is a protocol error. The spec doesn't + * provide a timeout for the Data Reset process to be enforced + * by the UFP. The DFP should enforce DataResetFailTimer. + */ + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + } else if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + } +} + +static void pe_udr_wait_for_data_reset_complete_exit(int port) +{ + dpm_data_reset_complete(port); +} + +/* + * PE_DDR_Send_Data_Reset + * See PD rev 3.1, v. 1.2, Figure 8-88. + */ +static void pe_ddr_send_data_reset_entry(int port) +{ + print_current_state(port); + /* Send Data Reset message */ + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_DATA_RESET); + pe_sender_response_msg_entry(port); +} + +static void pe_ddr_send_data_reset_run(int port) +{ + enum pe_msg_check msg_check = pe_sender_response_msg_run(port); + + /* Handle Discarded message, return to PE_SNK/SRC_READY */ + if (msg_check & PE_MSG_DISCARDED) { + pe_set_ready_state(port); + return; + } else if (msg_check == PE_MSG_SEND_PENDING) { + /* Wait until message is sent */ + return; + } + + /* + * Transition to the next Data Reset state after receiving Accept. + * Return to the ready state after receiving Not Supported. After + * receiving Reject or any other message type (Protocol Error), + * transition to Error Recovery. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + const uint32_t hdr = rx_emsg[port].header; + + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + if (PD_HEADER_GET_SOP(hdr) == TCPCI_MSG_SOP && + PD_HEADER_CNT(hdr) == 0 && !PD_HEADER_EXT(hdr) && + PD_HEADER_TYPE(hdr) == PD_CTRL_ACCEPT) { + /* + * Start DataResetFailTimer NOTE: This timer continues + * to run in every state until it is stopped or it times + * out. + */ + pd_timer_enable(port, PE_TIMER_DATA_RESET_FAIL, + PD_T_DATA_RESET_FAIL); + set_state_pe(port, tc_is_vconn_src(port) ? + PE_DDR_PERFORM_DATA_RESET : + PE_DDR_WAIT_FOR_VCONN_OFF); + return; + } else if (PD_HEADER_GET_SOP(hdr) == TCPCI_MSG_SOP && + PD_HEADER_CNT(hdr) == 0 && !PD_HEADER_EXT(hdr) && + PD_HEADER_TYPE(hdr) == PD_CTRL_NOT_SUPPORTED) { + /* Just pretend it worked. */ + dpm_data_reset_complete(port); + pe_set_ready_state(port); + return; + } + + /* Otherwise, it's a protocol error. */ + PE_SET_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + } + + if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE) || + PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + return; + } +} + +static void pe_ddr_send_data_reset_exit(int port) +{ + pe_sender_response_msg_exit(port); +} + +/* + * PE_DDR_Data_Reset_Received + */ +static void pe_ddr_data_reset_received_entry(int port) +{ + print_current_state(port); + /* Send Data Reset message */ + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT); +} + +static void pe_ddr_data_reset_received_run(int port) +{ + if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + if (tc_is_vconn_src(port)) + set_state_pe(port, PE_DDR_PERFORM_DATA_RESET); + else + set_state_pe(port, PE_DDR_WAIT_FOR_VCONN_OFF); + } else if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + } +} + +static void pe_ddr_data_reset_received_exit(int port) +{ + /* + * Start DataResetFailTimer + * NOTE: This timer continues to run in every state until it is stopped + * or it times out. + */ + pd_timer_enable(port, PE_TIMER_DATA_RESET_FAIL, PD_T_DATA_RESET_FAIL); +} + +/* + * PE_DDR_Wait_For_VCONN_Off + */ +static void pe_ddr_wait_for_vconn_off_entry(int port) +{ + print_current_state(port); + /* Initialize and start VCONNDischargeTimer */ + pd_timer_enable(port, PE_TIMER_VCONN_DISCHARGE, PD_T_VCONN_DISCHARGE); +} + +static void pe_ddr_wait_for_vconn_off_run(int port) +{ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + const uint32_t hdr = rx_emsg[port].header; + + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + if (PD_HEADER_GET_SOP(hdr) == TCPCI_MSG_SOP && + PD_HEADER_CNT(hdr) == 0 && !PD_HEADER_EXT(hdr) && + PD_HEADER_TYPE(hdr) == PD_CTRL_PS_RDY) { + /* PS_RDY message received */ + pd_timer_enable(port, PE_TIMER_VCONN_REAPPLIED, + PD_T_VCONN_REAPPLIED); + set_state_pe(port, PE_DDR_PERFORM_DATA_RESET); + return; + } + + /* Otherwise, it's a protocol error. */ + PE_SET_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + } + + if (pd_timer_is_expired(port, PE_TIMER_VCONN_DISCHARGE) || + PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + return; + } +} + +static void pe_ddr_wait_for_vconn_off_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_VCONN_DISCHARGE); +} + +/* + * PE_DDR_Perform_Data_Reset + * See PD rev 3.1, v. 1.2, section 6.3.14. + */ +static void pe_ddr_perform_data_reset_entry(int port) +{ + print_current_state(port); + + /* + * 1) The DFP shall: + * a) Disconnect the Port’s USB 2.0 D+/D- signals. + * b) If operating in USB 3.2 remove the port’s Rx Terminations. + * c) If operating in [USB4] drive the port’s SBTX to a logic low. + */ + usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_DISCONNECT, + polarity_rm_dts(pd_get_polarity(port))); + + /* 2) Both the DFP and UFP Shall exit all Alternate Modes if any. */ + if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { + pd_dfp_exit_mode(port, TCPCI_MSG_SOP, 0, 0); + pd_dfp_exit_mode(port, TCPCI_MSG_SOP_PRIME, 0, 0); + pd_dfp_exit_mode(port, TCPCI_MSG_SOP_PRIME_PRIME, 0, 0); + } + + /* 3) Reset the cable */ + /* + * TODO(b/141363146): The PD spec is ambiguous about which state the PE + * should be in during the cable reset (step 3 in section 6.3.14). If + * the DFP is not the initial VCONN Source, the cable reset presumably + * starts in PE_DDR_Wait_for_VCONN_Off and finishes in + * PE_DDR_Perform_Data_Reset. To be consistent with the steps in 6.3.14, + * that would imply that steps 1 and 2 take place in + * PE_DDR_Send_Data_Reset. However, this would be inconsistent with the, + * "Tell the Policy Manager to Perform Data Reset," action in + * PE_DDR_Perform_Data_Reset in figure 8-88, DFP Data_Reset Message + * State Diagram, since the Data Reset process would have had to start + * before then. Resolve this ambiguity and update this implementation. + */ + if (IS_ENABLED(CONFIG_USBC_VCONN) && tc_is_vconn_src(port)) + pd_request_vconn_swap_off(port); +} + +static void pe_ddr_perform_data_reset_run(int port) +{ + /* + * PE_FLAGS_VCONN_SWAP_COMPLETE may be set in 2 cases: + * a) If the PE requested to turn VCONN off while entering this state, + * i.e. if the TCPM was VCONN Source at that time. If the TCPM did not + * start out as VCONN Source, then PE_DDR_Wait_For_VCONN_Off will have + * already started the VCONN reapplied timer. + * b) When this state requests to turn VCONN on after tVCONNReapplied + * expires. At this point, the Data Reset process is complete. + */ + if (IS_ENABLED(CONFIG_USBC_VCONN) && !tc_is_vconn_src(port) && + PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE); + /* Wait until VCONN has discharged to start tVconnReapplied. */ + pd_timer_enable(port, PE_TIMER_TIMEOUT, + CONFIG_USBC_VCONN_SWAP_DELAY_US); + } else if (IS_ENABLED(CONFIG_USBC_VCONN) && + pd_timer_is_expired(port, PE_TIMER_TIMEOUT)) { + pd_timer_disable(port, PE_TIMER_TIMEOUT); + pd_timer_enable(port, PE_TIMER_VCONN_REAPPLIED, + PD_T_VCONN_REAPPLIED); + } else if (IS_ENABLED(CONFIG_USBC_VCONN) && + pd_timer_is_expired(port, PE_TIMER_VCONN_REAPPLIED)) { + pd_request_vconn_swap_on(port); + pd_timer_disable(port, PE_TIMER_VCONN_REAPPLIED); + + /* + * 4) After tDataReset the DFP shall: + * a) Reconnect the USB 2.0 D+/D- signals. + * b) If the Port was operating in USB 3.2 or USB4 reapply + * the port’s Rx Terminations. + * TODO: Section 6.3.14 implies that tDataReset is a minimum + * time for the DFP to leave the lines disconnected during Data + * Reset, possibly starting after the cable reset. Section + * 6.6.10.2 implies that tDataReset is the maximum time for the + * DFP to send Data_Reset_Complete after receiving Accept. These + * interpretations are mutually exclusive. Resolve that + * ambiguity and update this implementation. + */ + set_usb_mux_with_current_data_role(port); + } else if (IS_ENABLED(CONFIG_USBC_VCONN) && + PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE) && + tc_is_vconn_src(port)) { + PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE); + PE_SET_FLAG(port, PE_FLAGS_DATA_RESET_COMPLETE); + } else if (PE_CHK_FLAG(port, PE_FLAGS_DATA_RESET_COMPLETE) && + !pd_timer_is_disabled(port, PE_TIMER_DATA_RESET_FAIL)) { + pd_timer_disable(port, PE_TIMER_DATA_RESET_FAIL); + /* + * Because the cable power-cycled, reset the Tx (optional) and + * cached Rx (mandatory) message IDs. + */ + prl_reset_msg_ids(port, TCPCI_MSG_SOP_PRIME); + prl_reset_msg_ids(port, TCPCI_MSG_SOP_PRIME_PRIME); + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_DATA_RESET_COMPLETE); + } else if (PE_CHK_FLAG(port, PE_FLAGS_DATA_RESET_COMPLETE)) { + /* + * There is no specified response to Data_Reset_Complete, but + * make sure the port partner receives it before returning to a + * ready state. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { + PE_CLR_FLAG(port, PE_FLAGS_MSG_DISCARDED); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + } else if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + pe_set_ready_state(port); + } + return; + } else if (pd_timer_is_expired(port, PE_TIMER_DATA_RESET_FAIL) || + PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { + PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + return; + } + + /* + * No messages are expected, so any received would be a protocol error. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY); + } +} + +static void pe_ddr_perform_data_reset_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_VCONN_REAPPLIED); + pd_timer_disable(port, PE_TIMER_DATA_RESET_FAIL); + PE_CLR_FLAG(port, PE_FLAGS_DATA_RESET_COMPLETE); + pd_dpm_request(port, DPM_REQUEST_PORT_DISCOVERY); + dpm_data_reset_complete(port); +} +#endif /* CONFIG_USB_PD_DATA_RESET_MSG */ + +#ifdef CONFIG_USB_PD_EPR +static void pe_enter_epr_mode(int port) +{ + PE_CLR_FLAG(port, PE_FLAGS_ENTERING_EPR); + PE_CLR_FLAG(port, PE_FLAGS_EPR_EXPLICIT_EXIT); + PE_SET_FLAG(port, PE_FLAGS_IN_EPR); + CPRINTS("C%d: Entered EPR", port); +} + +static void pe_exit_epr_mode(int port) +{ + PE_CLR_FLAG(port, PE_FLAGS_IN_EPR); + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_EPR_MODE_EXIT); + CPRINTS("C%d: Exited EPR", port); +} + +/* + * PE_SNK_EPR_KEEP_ALIVE + */ +static void pe_snk_epr_keep_alive_entry(int port) +{ + struct pd_ecdb *ecdb = (void *)tx_emsg[port].buf; + + if (pe_debug_level >= DEBUG_LEVEL_2) { + print_current_state(port); + } + + ecdb->type = PD_EXT_CTRL_EPR_KEEPALIVE; + ecdb->data = 0; + tx_emsg[port].len = sizeof(*ecdb); + + send_ext_data_msg(port, TCPCI_MSG_SOP, PD_EXT_CONTROL); + pe_sender_response_msg_entry(port); +} + +static void pe_snk_epr_keep_alive_run(int port) +{ + enum pe_msg_check msg_check = pe_sender_response_msg_run(port); + + if (msg_check & PE_MSG_DISCARDED) { + /* + * An EPR_KeepAlive was discarded due to an incoming message + * from the source. Both ends know the partnership is alive. We + * go back to SNK_Ready and restart the KeepAlive timer. + */ + set_state_pe(port, PE_SNK_READY); + return; + } + + if (msg_check & PE_MSG_SENT && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + int type = PD_HEADER_TYPE(rx_emsg[port].header); + int cnt = PD_HEADER_CNT(rx_emsg[port].header); + int ext = PD_HEADER_EXT(rx_emsg[port].header); + struct pd_ecdb *ecdb = (void *)rx_emsg[port].buf; - if (pe[port].timeout > 0 && get_time().val > pe[port].timeout) { - /* - * A VCONN Swap Shall reset the DiscoverIdentityCounter - * to zero - */ - pe[port].discover_identity_counter = 0; - pe[port].dr_swap_attempt_counter = 0; + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); - if (pe[port].power_role == PD_ROLE_SOURCE) - set_state_pe(port, PE_SRC_READY); - else + if (cnt == 0 || ext == 0 || type != PD_EXT_CONTROL) { + CPRINTS("C%d: Protocol Error: 0x%04x", port, + rx_emsg[port].header); + pe_send_soft_reset(port, TCPCI_MSG_SOP); + } else if (ecdb->type == PD_EXT_CTRL_EPR_KEEPALIVE_ACK) { + pe_sender_response_msg_exit(port); set_state_pe(port, PE_SNK_READY); + } + + return; } + + if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) + pe_set_hard_reset(port); } /* - * PE_VCS_Send_PS_Rdy_Swap + * PE_SNK_SEND_EPR_MODE_ENTRY */ -static void pe_vcs_send_ps_rdy_swap_entry(int port) +static void pe_snk_send_epr_mode_entry_entry(int port) { + struct eprmdo *eprmdo = (void *)tx_emsg[port].buf; + print_current_state(port); - /* Send a PS_RDY Message */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PS_RDY); - pe[port].sub = PE_SUB0; + PE_SET_FLAG(port, PE_FLAGS_ENTERING_EPR); + + /* Send EPR mode entry message */ + eprmdo->action = PD_EPRMDO_ACTION_ENTER; + eprmdo->data = 0; /* EPR Sink Operational PDP */ + eprmdo->reserved = 0; + tx_emsg[port].len = sizeof(*eprmdo); + + send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_EPR_MODE); + pe_sender_response_msg_entry(port); + + pd_timer_enable(port, PE_TIMER_SINK_EPR_ENTER, PD_T_ENTER_EPR); } -static void pe_vcs_send_ps_rdy_swap_run(int port) +static void pe_snk_send_epr_mode_entry_run(int port) { - /* TODO(b/152058087): TCPMv2: Break up pe_vcs_send_ps_rdy_swap */ - switch (pe[port].sub) { - case PE_SUB0: - /* - * After a VCONN Swap the VCONN Source needs to reset - * the Cable Plug’s Protocol Layer in order to ensure - * MessageID synchronization. - */ - if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { - PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); - - send_ctrl_msg(port, TCPC_TX_SOP_PRIME, - PD_CTRL_SOFT_RESET); - pe[port].sub = PE_SUB1; - } - break; - case PE_SUB1: - if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { - PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); - pe[port].sender_response_timer = get_time().val + - PD_T_SENDER_RESPONSE; - } + enum pe_msg_check msg_check; - /* Got ACCEPT or REJECT from Cable Plug */ - if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED) || - get_time().val > pe[port].sender_response_timer) { - PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); - /* - * A VCONN Swap Shall reset the - * DiscoverIdentityCounter to zero - */ - pe[port].discover_identity_counter = 0; - pe[port].dr_swap_attempt_counter = 0; + /* Check the state of the message sent */ + msg_check = pe_sender_response_msg_run(port); - if (pe[port].power_role == PD_ROLE_SOURCE) - set_state_pe(port, PE_SRC_READY); - else - set_state_pe(port, PE_SNK_READY); - } - break; - case PE_SUB2: - /* Do nothing */ - break; + if (msg_check & PE_MSG_DISCARDED) { + PE_CLR_FLAG(port, PE_FLAGS_ENTERING_EPR); + set_state_pe(port, PE_SNK_READY); + return; } - if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) { - PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR); + if ((msg_check & PE_MSG_SENT) && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + uint8_t type = PD_HEADER_TYPE(rx_emsg[port].header); + uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header); + uint8_t ext = PD_HEADER_EXT(rx_emsg[port].header); - if (pe[port].sub == PE_SUB0) { - /* PS_RDY didn't send, soft reset */ - pe_send_soft_reset(port, TCPC_TX_SOP); - } else { + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + if ((ext == 0) && (cnt > 0) && (type == PD_DATA_EPR_MODE)) { + struct eprmdo *eprmdo = (void *)rx_emsg[port].buf; + + if (eprmdo->action == PD_EPRMDO_ACTION_ENTER_ACK) { + /* EPR Enter Mode Acknowledge received */ + set_state_pe( + port, + PE_SNK_EPR_MODE_ENTRY_WAIT_FOR_RESPONSE); + return; + } /* - * Cable plug wasn't present, - * return to ready state + * Other actions should result in soft reset but not + * clear from the spec. So, we just let it time out. */ - pe_set_ready_state(port); } } + + /* When the SinkEPREnterTimer times out, send a soft reset. */ + if (pd_timer_is_expired(port, PE_TIMER_SINK_EPR_ENTER)) { + pe_send_soft_reset(port, TCPCI_MSG_SOP); + } else if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) { + pe_send_soft_reset(port, TCPCI_MSG_SOP); + } +} + +static void pe_snk_send_epr_mode_entry_exit(int port) +{ + pe_sender_response_msg_exit(port); } -#endif /* CONFIG_USBC_VCONN */ /* - * PE_DR_SNK_Get_Sink_Cap + * PE_SNK_EPR_MODE_ENTRY_WAIT_FOR_RESPONSE */ -static __maybe_unused void pe_dr_snk_get_sink_cap_entry(int port) +static void pe_snk_epr_mode_entry_wait_for_response_entry(int port) { print_current_state(port); - - /* Send a Get Sink Cap Message */ - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_GET_SINK_CAP); - pe_sender_response_msg_entry(port); + /* Wait for EPR Enter Mode response */ } -static __maybe_unused void pe_dr_snk_get_sink_cap_run(int port) +static void pe_snk_epr_mode_entry_wait_for_response_run(int port) { - int type; - int cnt; - int ext; - int rev; - enum pe_msg_check msg_check; - - /* - * Check the state of the message sent - */ - msg_check = pe_sender_response_msg_run(port); + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + uint8_t type = PD_HEADER_TYPE(rx_emsg[port].header); + uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header); + uint8_t ext = PD_HEADER_EXT(rx_emsg[port].header); - /* - * Determine if FRS is possible based on the returned Sink Caps - * - * Transition to PE_SNK_Ready when: - * 1) A Sink_Capabilities Message is received - * 2) Or SenderResponseTimer times out - * 3) Or a Reject Message is received. - * - * Transition to PE_SEND_SOFT_RESET state when: - * 1) An unexpected message is received - */ - if ((msg_check & PE_MSG_SENT) && - PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + if ((ext == 0) && (cnt > 0) && (type == PD_DATA_EPR_MODE)) { + struct eprmdo *eprmdo = (void *)rx_emsg[port].buf; - type = PD_HEADER_TYPE(rx_emsg[port].header); - cnt = PD_HEADER_CNT(rx_emsg[port].header); - ext = PD_HEADER_EXT(rx_emsg[port].header); - rev = PD_HEADER_REV(rx_emsg[port].header); - - if (ext == 0) { - if ((cnt > 0) && (type == PD_DATA_SINK_CAP)) { - uint32_t payload = - *(uint32_t *)rx_emsg[port].buf; - - /* - * Check message to see if we can handle - * FRS for this connection. Multiple PDOs - * may be returned, for FRS only Fixed PDOs - * shall be used, and this shall be the 1st - * PDO returned. - * - * TODO(b/14191267): Make sure we can handle - * the required current before we enable FRS. - */ - if (IS_ENABLED(CONFIG_USB_PD_REV30) && - (rev > PD_REV20) && - (payload & PDO_FIXED_DUAL_ROLE)) { - switch (payload & - PDO_FIXED_FRS_CURR_MASK) { - case PDO_FIXED_FRS_CURR_NOT_SUPPORTED: - break; - case PDO_FIXED_FRS_CURR_DFLT_USB_POWER: - case PDO_FIXED_FRS_CURR_1A5_AT_5V: - case PDO_FIXED_FRS_CURR_3A0_AT_5V: - typec_set_source_current_limit( - port, TYPEC_RP_3A0); - pe_set_frs_enable(port, 1); - break; - } - } - set_state_pe(port, PE_SNK_READY); - } else if (type == PD_CTRL_REJECT || - type == PD_CTRL_NOT_SUPPORTED) { - set_state_pe(port, PE_SNK_READY); - } else { - set_state_pe(port, PE_SEND_SOFT_RESET); + if (eprmdo->action == PD_EPRMDO_ACTION_ENTER_SUCCESS) { + pe_enter_epr_mode(port); + set_state_pe(port, + PE_SNK_WAIT_FOR_CAPABILITIES); + return; + } else if (eprmdo->action == + PD_EPRMDO_ACTION_ENTER_FAILED) { + PE_CLR_FLAG(port, PE_FLAGS_ENTERING_EPR); + /* Table 6-50 EPR Mode Data Object */ + CPRINTS("C%d: Failed to enter EPR for 0x%x", + port, eprmdo->data); } + /* Fall through to soft reset. */ + } else if ((ext == 0) && (cnt == 0) && + (type == PD_CTRL_VCONN_SWAP)) { + set_state_pe(port, PE_VCS_EVALUATE_SWAP); return; } + /* + * 6.4.10.1 Process to enter EPR Mode + * "3. If the Sink receives any Message, other than an + * EPR_ModeMessage with ENTER_SUCCESS, the Sink Shall initiate a + * Soft Reset." + */ + pe_send_soft_reset(port, TCPCI_MSG_SOP); + return; + } + + /* When the SinkEPREnterTimer times out, send a soft reset. */ + if (pd_timer_is_expired(port, PE_TIMER_SINK_EPR_ENTER)) { + PE_SET_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT); + pe_send_soft_reset(port, TCPCI_MSG_SOP); } +} +static void pe_snk_epr_mode_entry_wait_for_response_exit(int port) +{ + pd_timer_disable(port, PE_TIMER_SINK_EPR_ENTER); /* - * Transition to PE_SNK_Ready state when: - * 1) SenderResponseTimer times out. - * 2) Message was discarded. + * Figure 8-215 indicates a sink shall enter EPR Mode on exit but Figure + * 6-34 indicates we enter EPR mode only on success (and soft reset + * otherwise). Since the later makes sense, we don't enter EPR here. */ - if ((msg_check & PE_MSG_DISCARDED) || - get_time().val > pe[port].sender_response_timer) - set_state_pe(port, PE_SNK_READY); } /* - * PE_DR_SNK_Give_Source_Cap + * PE_SNK_SEND_EPR_MODE_EXIT */ -static void pe_dr_snk_give_source_cap_entry(int port) +static void pe_snk_send_epr_mode_exit_entry(int port) { + struct eprmdo *eprmdo = (void *)tx_emsg[port].buf; + print_current_state(port); - /* Send source capabilities. */ - send_source_cap(port); + /* Send EPR mode entry message */ + eprmdo->action = PD_EPRMDO_ACTION_EXIT; + eprmdo->data = 0; + eprmdo->reserved = 0; + tx_emsg[port].len = sizeof(*eprmdo); + + send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_EPR_MODE); + pe_sender_response_msg_entry(port); } -static void pe_dr_snk_give_source_cap_run(int port) +static void pe_snk_send_epr_mode_exit_run(int port) { - /* - * Transition back to PE_SNK_Ready when the Source_Capabilities message - * has been successfully sent. - * - * Get Source Capabilities AMS is uninterruptible, but in case the - * partner violates the spec then send a soft reset rather than get - * stuck here. - */ - if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { - PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + enum pe_msg_check msg_check = pe_sender_response_msg_run(port); + + if (msg_check & PE_MSG_DISCARDED) { set_state_pe(port, PE_SNK_READY); - } else if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { - pe_send_soft_reset(port, TCPC_TX_SOP); + return; + } + + if (msg_check & PE_MSG_SENT) { + pe_sender_response_msg_exit(port); + pe_exit_epr_mode(port); + set_state_pe(port, PE_SNK_WAIT_FOR_CAPABILITIES); } } /* - * PE_DR_SRC_Get_Source_Cap + * PE_SNK_EPR_MODE_EXIT_RECEIVED */ -static void pe_dr_src_get_source_cap_entry(int port) +static void pe_snk_epr_mode_exit_received_entry(int port) { print_current_state(port); - /* Send a Get_Source_Cap Message */ - tx_emsg[port].len = 0; - send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_GET_SOURCE_CAP); - pe_sender_response_msg_entry(port); -} - -static void pe_dr_src_get_source_cap_run(int port) -{ - int type; - int cnt; - int ext; - enum pe_msg_check msg_check; - - /* - * Check the state of the message sent - */ - msg_check = pe_sender_response_msg_run(port); - /* - * Transition to PE_SRC_Ready when: - * 1) A Source Capabilities Message is received. - * 2) A Reject Message is received. + * Table 8-22 Steps for Exiting EPR Mode (Source Initiated) states 'The + * Port Partners are in an Explicit Contract using an SPR PDO.' Thus, + * it's expected Source already has sent new SPR PDOs (and we switched + * to a SPR contract) before it sent EPR mode exit. Violation of this + * results in a hard reset (6.4.10.3.3 Exits due to errors). */ - if ((msg_check & PE_MSG_SENT) && - PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { - PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); - - type = PD_HEADER_TYPE(rx_emsg[port].header); - cnt = PD_HEADER_CNT(rx_emsg[port].header); - ext = PD_HEADER_EXT(rx_emsg[port].header); - - if (ext == 0) { - if ((cnt > 0) && (type == PD_DATA_SOURCE_CAP)) { - uint32_t *payload = - (uint32_t *)rx_emsg[port].buf; - - /* - * Unconstrained power by the partner should - * be enough to request a PR_Swap to use their - * power instead of our battery - */ - pd_set_src_caps(port, cnt, payload); - if (pe[port].src_caps[0] & - PDO_FIXED_UNCONSTRAINED) { - pe[port].src_snk_pr_swap_counter = 0; - PE_SET_DPM_REQUEST(port, - DPM_REQUEST_PR_SWAP); - } - - set_state_pe(port, PE_SRC_READY); - } else if (type == PD_CTRL_REJECT || - type == PD_CTRL_NOT_SUPPORTED) { - set_state_pe(port, PE_SRC_READY); - } else { - set_state_pe(port, PE_SEND_SOFT_RESET); - } - return; - } + if (!pe_in_spr_contract(port)) { + CPRINTS("C%d: Received EPR exit while in EPR contract", port); + pe_set_hard_reset(port); + return; } - /* - * Transition to PE_SRC_Ready state when: - * 1) the SenderResponseTimer times out. - * 2) Message was discarded. - */ - if ((msg_check & PE_MSG_DISCARDED) || - get_time().val > pe[port].sender_response_timer) - set_state_pe(port, PE_SRC_READY); + pe_exit_epr_mode(port); + set_state_pe(port, PE_SNK_WAIT_FOR_CAPABILITIES); } +#endif /* CONFIG_USB_PD_EPR */ -const uint32_t * const pd_get_src_caps(int port) +const uint32_t *const pd_get_src_caps(int port) { return pe[port].src_caps; } void pd_set_src_caps(int port, int cnt, uint32_t *src_caps) { + const int limit = ARRAY_SIZE(pe[port].src_caps); int i; + if (cnt > limit) { + CPRINTS("C%d: Trim PDOs (%d) exceeding limit (%d)", port, cnt, + limit); + cnt = limit; + } + pe[port].src_cap_cnt = cnt; for (i = 0; i < cnt; i++) @@ -6128,32 +8214,30 @@ void pd_set_src_caps(int port, int cnt, uint32_t *src_caps) uint8_t pd_get_src_cap_cnt(int port) { - return pe[port].src_cap_cnt; -} + if (pe[port].src_cap_cnt > 0) + return pe[port].src_cap_cnt; + return 0; +} /* Track access to the PD discovery structures during HC execution */ -uint32_t task_access[CONFIG_USB_PD_PORT_MAX_COUNT][DISCOVERY_TYPE_COUNT]; +atomic_t task_access[CONFIG_USB_PD_PORT_MAX_COUNT][DISCOVERY_TYPE_COUNT]; void pd_dfp_discovery_init(int port) { - /* - * Clear the VDM Setup Done and Modal Operation flags so we will - * have a fresh discovery - */ - PE_CLR_FLAG(port, PE_FLAGS_VDM_SETUP_DONE | - PE_FLAGS_MODAL_OPERATION); - - deprecated_atomic_or(&task_access[port][TCPC_TX_SOP], - BIT(task_get_current())); - deprecated_atomic_or(&task_access[port][TCPC_TX_SOP_PRIME], - BIT(task_get_current())); + atomic_or(&task_access[port][TCPCI_MSG_SOP], BIT(task_get_current())); + atomic_or(&task_access[port][TCPCI_MSG_SOP_PRIME], + BIT(task_get_current())); memset(pe[port].discovery, 0, sizeof(pe[port].discovery)); - memset(pe[port].partner_amodes, 0, sizeof(pe[port].partner_amodes)); +} + +void pd_dfp_mode_init(int port) +{ + PE_CLR_FLAG(port, PE_FLAGS_MODAL_OPERATION); /* Reset the DPM and DP modules to enable alternate mode entry. */ - dpm_init(port); + dpm_mode_exit_complete(port); dp_init(port); if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) @@ -6161,43 +8245,56 @@ void pd_dfp_discovery_init(int port) if (IS_ENABLED(CONFIG_USB_PD_USB4)) enter_usb_init(port); -} -#ifdef CONFIG_USB_PD_ALT_MODE_DFP + if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_UFP_DP)) + pd_ufp_set_dp_opos(port, 0); +} -void pd_discovery_access_clear(int port, enum tcpm_transmit_type type) +__maybe_unused void pd_discovery_access_clear(int port, + enum tcpci_msg_type type) { - deprecated_atomic_clear_bits(&task_access[port][type], 0xFFFFFFFF); + if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) + assert(0); + + atomic_clear_bits(&task_access[port][type], 0xFFFFFFFF); } -bool pd_discovery_access_validate(int port, enum tcpm_transmit_type type) +__maybe_unused bool pd_discovery_access_validate(int port, + enum tcpci_msg_type type) { + if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) + assert(0); + return !(task_access[port][type] & ~BIT(task_get_current())); } -struct pd_discovery *pd_get_am_discovery(int port, enum tcpm_transmit_type type) +__maybe_unused struct pd_discovery * +pd_get_am_discovery_and_notify_access(int port, enum tcpci_msg_type type) { + atomic_or(&task_access[port][type], BIT(task_get_current())); + return (struct pd_discovery *)pd_get_am_discovery(port, type); +} + +__maybe_unused const struct pd_discovery * +pd_get_am_discovery(int port, enum tcpci_msg_type type) +{ + if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) + assert(0); ASSERT(type < DISCOVERY_TYPE_COUNT); - deprecated_atomic_or(&task_access[port][type], BIT(task_get_current())); return &pe[port].discovery[type]; } -struct partner_active_modes *pd_get_partner_active_modes(int port, - enum tcpm_transmit_type type) +__maybe_unused void pd_set_dfp_enter_mode_flag(int port, bool set) { - ASSERT(type < AMODE_TYPE_COUNT); - return &pe[port].partner_amodes[type]; -} + if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) + assert(0); -void pd_set_dfp_enter_mode_flag(int port, bool set) -{ if (set) PE_SET_FLAG(port, PE_FLAGS_MODAL_OPERATION); else PE_CLR_FLAG(port, PE_FLAGS_MODAL_OPERATION); } -#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ const char *pe_get_current_state(int port) { @@ -6209,12 +8306,14 @@ const char *pe_get_current_state(int port) uint32_t pe_get_flags(int port) { - return pe[port].flags; + /* + * TODO(b/229655319): support more than 32 bits + */ + return pe[port].flags_a[0]; } - -static const struct usb_state pe_states[] = { - /* Super States */ +static __const_data const struct usb_state pe_states[] = { +/* Super States */ #ifdef CONFIG_USB_PD_REV30 [PE_PRS_FRS_SHARED] = { .entry = pe_prs_frs_shared_entry, @@ -6231,6 +8330,7 @@ static const struct usb_state pe_states[] = { [PE_SRC_STARTUP] = { .entry = pe_src_startup_entry, .run = pe_src_startup_run, + .exit = pe_src_startup_exit, }, [PE_SRC_DISCOVERY] = { .entry = pe_src_discovery_entry, @@ -6239,6 +8339,7 @@ static const struct usb_state pe_states[] = { [PE_SRC_SEND_CAPABILITIES] = { .entry = pe_src_send_capabilities_entry, .run = pe_src_send_capabilities_run, + .exit = pe_src_send_capabilities_exit, }, [PE_SRC_NEGOTIATE_CAPABILITY] = { .entry = pe_src_negotiate_capability_entry, @@ -6246,10 +8347,12 @@ static const struct usb_state pe_states[] = { [PE_SRC_TRANSITION_SUPPLY] = { .entry = pe_src_transition_supply_entry, .run = pe_src_transition_supply_run, + .exit = pe_src_transition_supply_exit, }, [PE_SRC_READY] = { .entry = pe_src_ready_entry, .run = pe_src_ready_run, + .exit = pe_src_ready_exit, }, [PE_SRC_DISABLED] = { .entry = pe_src_disabled_entry, @@ -6261,10 +8364,12 @@ static const struct usb_state pe_states[] = { [PE_SRC_HARD_RESET] = { .entry = pe_src_hard_reset_entry, .run = pe_src_hard_reset_run, + .exit = pe_src_hard_reset_exit, }, [PE_SRC_HARD_RESET_RECEIVED] = { .entry = pe_src_hard_reset_received_entry, .run = pe_src_hard_reset_received_run, + .exit = pe_src_hard_reset_received_exit, }, [PE_SRC_TRANSITION_TO_DEFAULT] = { .entry = pe_src_transition_to_default_entry, @@ -6281,6 +8386,7 @@ static const struct usb_state pe_states[] = { [PE_SNK_WAIT_FOR_CAPABILITIES] = { .entry = pe_snk_wait_for_capabilities_entry, .run = pe_snk_wait_for_capabilities_run, + .exit = pe_snk_wait_for_capabilities_exit, }, [PE_SNK_EVALUATE_CAPABILITY] = { .entry = pe_snk_evaluate_capability_entry, @@ -6288,10 +8394,12 @@ static const struct usb_state pe_states[] = { [PE_SNK_SELECT_CAPABILITY] = { .entry = pe_snk_select_capability_entry, .run = pe_snk_select_capability_run, + .exit = pe_snk_select_capability_exit, }, [PE_SNK_READY] = { .entry = pe_snk_ready_entry, .run = pe_snk_ready_run, + .exit = pe_snk_ready_exit, }, [PE_SNK_HARD_RESET] = { .entry = pe_snk_hard_reset_entry, @@ -6317,6 +8425,7 @@ static const struct usb_state pe_states[] = { [PE_SEND_SOFT_RESET] = { .entry = pe_send_soft_reset_entry, .run = pe_send_soft_reset_run, + .exit = pe_send_soft_reset_exit, }, [PE_SOFT_RESET] = { .entry = pe_soft_reset_entry, @@ -6341,6 +8450,7 @@ static const struct usb_state pe_states[] = { [PE_DRS_SEND_SWAP] = { .entry = pe_drs_send_swap_entry, .run = pe_drs_send_swap_run, + .exit = pe_drs_send_swap_exit, }, [PE_PRS_SRC_SNK_EVALUATE_SWAP] = { .entry = pe_prs_src_snk_evaluate_swap_entry, @@ -6349,6 +8459,7 @@ static const struct usb_state pe_states[] = { [PE_PRS_SRC_SNK_TRANSITION_TO_OFF] = { .entry = pe_prs_src_snk_transition_to_off_entry, .run = pe_prs_src_snk_transition_to_off_run, + .exit = pe_prs_src_snk_transition_to_off_exit, }, [PE_PRS_SRC_SNK_ASSERT_RD] = { .entry = pe_prs_src_snk_assert_rd_entry, @@ -6362,6 +8473,7 @@ static const struct usb_state pe_states[] = { [PE_PRS_SRC_SNK_SEND_SWAP] = { .entry = pe_prs_src_snk_send_swap_entry, .run = pe_prs_src_snk_send_swap_run, + .exit = pe_prs_src_snk_send_swap_exit, }, [PE_PRS_SNK_SRC_EVALUATE_SWAP] = { .entry = pe_prs_snk_src_evaluate_swap_entry, @@ -6375,6 +8487,7 @@ static const struct usb_state pe_states[] = { [PE_PRS_SNK_SRC_TRANSITION_TO_OFF] = { .entry = pe_prs_snk_src_transition_to_off_entry, .run = pe_prs_snk_src_transition_to_off_run, + .exit = pe_prs_snk_src_transition_to_off_exit, #ifdef CONFIG_USB_PD_REV30 .parent = &pe_states[PE_PRS_FRS_SHARED], #endif /* CONFIG_USB_PD_REV30 */ @@ -6400,6 +8513,7 @@ static const struct usb_state pe_states[] = { [PE_PRS_SNK_SRC_SEND_SWAP] = { .entry = pe_prs_snk_src_send_swap_entry, .run = pe_prs_snk_src_send_swap_run, + .exit = pe_prs_snk_src_send_swap_exit, #ifdef CONFIG_USB_PD_REV30 .parent = &pe_states[PE_PRS_FRS_SHARED], #endif /* CONFIG_USB_PD_REV30 */ @@ -6412,14 +8526,17 @@ static const struct usb_state pe_states[] = { [PE_VCS_SEND_SWAP] = { .entry = pe_vcs_send_swap_entry, .run = pe_vcs_send_swap_run, + .exit = pe_vcs_send_swap_exit, }, [PE_VCS_WAIT_FOR_VCONN_SWAP] = { .entry = pe_vcs_wait_for_vconn_swap_entry, .run = pe_vcs_wait_for_vconn_swap_run, + .exit = pe_vcs_wait_for_vconn_swap_exit, }, [PE_VCS_TURN_ON_VCONN_SWAP] = { .entry = pe_vcs_turn_on_vconn_swap_entry, .run = pe_vcs_turn_on_vconn_swap_run, + .exit = pe_vcs_turn_on_vconn_swap_exit, }, [PE_VCS_TURN_OFF_VCONN_SWAP] = { .entry = pe_vcs_turn_off_vconn_swap_entry, @@ -6429,6 +8546,11 @@ static const struct usb_state pe_states[] = { .entry = pe_vcs_send_ps_rdy_swap_entry, .run = pe_vcs_send_ps_rdy_swap_run, }, + [PE_VCS_CBL_SEND_SOFT_RESET] = { + .entry = pe_vcs_cbl_send_soft_reset_entry, + .run = pe_vcs_cbl_send_soft_reset_run, + .exit = pe_vcs_cbl_send_soft_reset_exit, + }, #endif /* CONFIG_USBC_VCONN */ [PE_VDM_IDENTITY_REQUEST_CBL] = { .entry = pe_vdm_identity_request_cbl_entry, @@ -6465,14 +8587,10 @@ static const struct usb_state pe_states[] = { .run = pe_vdm_response_run, .exit = pe_vdm_response_exit, }, - [PE_HANDLE_CUSTOM_VDM_REQUEST] = { - .entry = pe_handle_custom_vdm_request_entry, - .run = pe_handle_custom_vdm_request_run, - .exit = pe_handle_custom_vdm_request_exit, - }, [PE_DEU_SEND_ENTER_USB] = { .entry = pe_enter_usb_entry, .run = pe_enter_usb_run, + .exit = pe_enter_usb_exit, }, [PE_WAIT_FOR_ERROR_RECOVERY] = { .entry = pe_wait_for_error_recovery_entry, @@ -6481,17 +8599,13 @@ static const struct usb_state pe_states[] = { [PE_BIST_TX] = { .entry = pe_bist_tx_entry, .run = pe_bist_tx_run, + .exit = pe_bist_tx_exit, }, - [PE_BIST_RX] = { - .entry = pe_bist_rx_entry, - .run = pe_bist_rx_run, - }, -#ifdef CONFIG_USB_PD_FRS - [PE_DR_SNK_GET_SINK_CAP] = { - .entry = pe_dr_snk_get_sink_cap_entry, - .run = pe_dr_snk_get_sink_cap_run, + [PE_DR_GET_SINK_CAP] = { + .entry = pe_dr_get_sink_cap_entry, + .run = pe_dr_get_sink_cap_run, + .exit = pe_dr_get_sink_cap_exit, }, -#endif [PE_DR_SNK_GIVE_SOURCE_CAP] = { .entry = pe_dr_snk_give_source_cap_entry, .run = pe_dr_snk_give_source_cap_run, @@ -6499,12 +8613,18 @@ static const struct usb_state pe_states[] = { [PE_DR_SRC_GET_SOURCE_CAP] = { .entry = pe_dr_src_get_source_cap_entry, .run = pe_dr_src_get_source_cap_run, + .exit = pe_dr_src_get_source_cap_exit, }, #ifdef CONFIG_USB_PD_REV30 [PE_FRS_SNK_SRC_START_AMS] = { .entry = pe_frs_snk_src_start_ams_entry, .parent = &pe_states[PE_PRS_FRS_SHARED], }, + [PE_GET_REVISION] = { + .entry = pe_get_revision_entry, + .run = pe_get_revision_run, + .exit = pe_get_revision_exit, + }, #ifdef CONFIG_USB_PD_EXTENDED_MESSAGES [PE_GIVE_BATTERY_CAP] = { .entry = pe_give_battery_cap_entry, @@ -6514,24 +8634,108 @@ static const struct usb_state pe_states[] = { .entry = pe_give_battery_status_entry, .run = pe_give_battery_status_run, }, + [PE_GIVE_STATUS] = { + .entry = pe_give_status_entry, + .run = pe_give_status_run, + }, [PE_SEND_ALERT] = { .entry = pe_send_alert_entry, .run = pe_send_alert_run, }, + [PE_ALERT_RECEIVED] = { + .entry = pe_alert_received_entry, + }, #else [PE_SRC_CHUNK_RECEIVED] = { .entry = pe_chunk_received_entry, .run = pe_chunk_received_run, + .exit = pe_chunk_received_exit, }, [PE_SNK_CHUNK_RECEIVED] = { .entry = pe_chunk_received_entry, .run = pe_chunk_received_run, + .exit = pe_chunk_received_exit, }, #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ +#ifdef CONFIG_USBC_VCONN + [PE_VCS_FORCE_VCONN] = { + .entry = pe_vcs_force_vconn_entry, + .run = pe_vcs_force_vconn_run, + .exit = pe_vcs_force_vconn_exit, + }, +#endif /* CONFIG_USBC_VCONN */ +#ifdef CONFIG_USB_PD_DATA_RESET_MSG + [PE_UDR_SEND_DATA_RESET] = { + .entry = pe_udr_send_data_reset_entry, + .run = pe_udr_send_data_reset_run, + .exit = pe_udr_send_data_reset_exit, + }, + [PE_UDR_DATA_RESET_RECEIVED] = { + .entry = pe_udr_data_reset_received_entry, + .run = pe_udr_data_reset_received_run, + }, + [PE_UDR_TURN_OFF_VCONN] = { + .entry = pe_udr_turn_off_vconn_entry, + .run = pe_udr_turn_off_vconn_run, + }, + [PE_UDR_SEND_PS_RDY] = { + .entry = pe_udr_send_ps_rdy_entry, + .run = pe_udr_send_ps_rdy_run, + }, + [PE_UDR_WAIT_FOR_DATA_RESET_COMPLETE] = { + .entry = pe_udr_wait_for_data_reset_complete_entry, + .run = pe_udr_wait_for_data_reset_complete_run, + .exit = pe_udr_wait_for_data_reset_complete_exit, + }, + [PE_DDR_SEND_DATA_RESET] = { + .entry = pe_ddr_send_data_reset_entry, + .run = pe_ddr_send_data_reset_run, + .exit = pe_ddr_send_data_reset_exit, + }, + [PE_DDR_DATA_RESET_RECEIVED] = { + .entry = pe_ddr_data_reset_received_entry, + .run = pe_ddr_data_reset_received_run, + .exit = pe_ddr_data_reset_received_exit, + }, + [PE_DDR_WAIT_FOR_VCONN_OFF] = { + .entry = pe_ddr_wait_for_vconn_off_entry, + .run = pe_ddr_wait_for_vconn_off_run, + .exit = pe_ddr_wait_for_vconn_off_exit, + }, + [PE_DDR_PERFORM_DATA_RESET] = { + .entry = pe_ddr_perform_data_reset_entry, + .run = pe_ddr_perform_data_reset_run, + .exit = pe_ddr_perform_data_reset_exit, + }, +#endif /* CONFIG_USB_PD_DATA_RESET_MSG */ +#ifdef CONFIG_USB_PD_EPR + [PE_SNK_EPR_KEEP_ALIVE] = { + .entry = pe_snk_epr_keep_alive_entry, + .run = pe_snk_epr_keep_alive_run, + }, + [PE_SNK_SEND_EPR_MODE_ENTRY] = { + .entry = pe_snk_send_epr_mode_entry_entry, + .run = pe_snk_send_epr_mode_entry_run, + .exit = pe_snk_send_epr_mode_entry_exit, + }, + [PE_SNK_EPR_MODE_ENTRY_WAIT_FOR_RESPONSE] = { + .entry = pe_snk_epr_mode_entry_wait_for_response_entry, + .run = pe_snk_epr_mode_entry_wait_for_response_run, + .exit = pe_snk_epr_mode_entry_wait_for_response_exit, + }, + [PE_SNK_SEND_EPR_MODE_EXIT] = { + .entry = pe_snk_send_epr_mode_exit_entry, + .run = pe_snk_send_epr_mode_exit_run, + }, + [PE_SNK_EPR_MODE_EXIT_RECEIVED] = { + .entry = pe_snk_epr_mode_exit_received_entry, + }, +#endif /* CONFIG_USB_PD_EPR */ #endif /* CONFIG_USB_PD_REV30 */ }; #ifdef TEST_BUILD +/* TODO(b/173791979): Unit tests shouldn't need to access internal states */ const struct test_sm_data test_pe_sm_data[] = { { .base = pe_states, @@ -6543,24 +8747,20 @@ const struct test_sm_data test_pe_sm_data[] = { BUILD_ASSERT(ARRAY_SIZE(pe_states) == ARRAY_SIZE(pe_state_names)); const int test_pe_sm_data_size = ARRAY_SIZE(test_pe_sm_data); -void pe_set_flag(int port, int flag) -{ - PE_SET_FLAG(port, flag); -} -void pe_clr_flag(int port, int flag) +void pe_set_fn(int port, int fn) { - PE_CLR_FLAG(port, flag); + PE_SET_FN(port, fn); } -int pe_chk_flag(int port, int flag) +void pe_clr_fn(int port, int fn) { - return PE_CHK_FLAG(port, flag); + PE_CLR_FN(port, fn); } -int pe_get_all_flags(int port) +int pe_chk_fn(int port, int fn) { - return pe[port].flags; + return PE_CHK_FN(port, fn); } -void pe_set_all_flags(int port, int flags) +void pe_clr_dpm_requests(int port) { - pe[port].flags = flags; + pe[port].dpm_request = 0; } #endif diff --git a/common/usbc/usb_pe_private.h b/common/usbc/usb_pe_private.h new file mode 100644 index 0000000000..b71cfced86 --- /dev/null +++ b/common/usbc/usb_pe_private.h @@ -0,0 +1,113 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_USB_PE_PRIVATE_H +#define __CROS_EC_USB_PE_PRIVATE_H + +/** Internal header file for usb_pe. + * + * EC code should not normally include this. These are exposed so they can be + * used by unit test code. + */ + +enum { + /* At least one successful PD communication packet received from port + partner */ + PE_FLAGS_PD_CONNECTION_FN = 0, + /* Accept message received from port partner */ + PE_FLAGS_ACCEPT_FN, + /* Power Supply Ready message received from port partner */ + PE_FLAGS_PS_READY_FN, + /* Protocol Error was determined based on error recovery current state + */ + PE_FLAGS_PROTOCOL_ERROR_FN, + /* Set if we are in Modal Operation */ + PE_FLAGS_MODAL_OPERATION_FN, + /* A message we requested to be sent has been transmitted */ + PE_FLAGS_TX_COMPLETE_FN, + /* A message sent by a port partner has been received */ + PE_FLAGS_MSG_RECEIVED_FN, + /* A hard reset has been requested but has not been sent, not currently + used */ + PE_FLAGS_HARD_RESET_PENDING_FN, + /* Port partner sent a Wait message. Wait before we resend our message + */ + PE_FLAGS_WAIT_FN, + /* An explicit contract is in place with our port partner */ + PE_FLAGS_EXPLICIT_CONTRACT_FN, + /* Waiting for Sink Capabailities timed out. Used for retry error + handling */ + PE_FLAGS_SNK_WAIT_CAP_TIMEOUT_FN, + /* Power Supply voltage/current transition timed out */ + PE_FLAGS_PS_TRANSITION_TIMEOUT_FN, + /* Flag to note current Atomic Message Sequence is interruptible */ + PE_FLAGS_INTERRUPTIBLE_AMS_FN, + /* Flag to note Power Supply reset has completed */ + PE_FLAGS_PS_RESET_COMPLETE_FN, + /* VCONN swap operation has completed */ + PE_FLAGS_VCONN_SWAP_COMPLETE_FN, + /* Flag to note PR Swap just completed for Startup entry */ + PE_FLAGS_PR_SWAP_COMPLETE_FN, + /* Flag to note FRS/PRS context in shared state machine path */ + PE_FLAGS_FAST_ROLE_SWAP_PATH_FN, + /* Flag to note if FRS listening is enabled */ + PE_FLAGS_FAST_ROLE_SWAP_ENABLED_FN, + /* Flag to note TCPC passed on FRS signal from port partner */ + PE_FLAGS_FAST_ROLE_SWAP_SIGNALED_FN, + /* TODO: POLICY decision: Triggers a DR SWAP attempt from UFP to DFP */ + PE_FLAGS_DR_SWAP_TO_DFP_FN, + /* + * TODO: POLICY decision + * Flag to trigger a message resend after receiving a WAIT from port + * partner + */ + PE_FLAGS_WAITING_PR_SWAP_FN, + /* FLAG is set when an AMS is initiated locally. ie. AP requested a + PR_SWAP */ + PE_FLAGS_LOCALLY_INITIATED_AMS_FN, + /* Flag to note the first message sent in PE_SRC_READY and PE_SNK_READY + */ + PE_FLAGS_FIRST_MSG_FN, + /* Flag to continue a VDM request if it was interrupted */ + PE_FLAGS_VDM_REQUEST_CONTINUE_FN, + /* TODO: POLICY decision: Triggers a Vconn SWAP attempt to on */ + PE_FLAGS_VCONN_SWAP_TO_ON_FN, + /* FLAG to track that VDM request to port partner timed out */ + PE_FLAGS_VDM_REQUEST_TIMEOUT_FN, + /* FLAG to note message was discarded due to incoming message */ + PE_FLAGS_MSG_DISCARDED_FN, + /* FLAG to note that hard reset can't be performed due to battery low */ + PE_FLAGS_SNK_WAITING_BATT_FN, + /* FLAG to note that a data reset is complete */ + PE_FLAGS_DATA_RESET_COMPLETE_FN, + /* Waiting for SRC to SNK settle time */ + PE_FLAGS_SRC_SNK_SETTLE_FN, + /* + * Indicates the port is in the process of entering EPR mode. For a + * sink, the SM is in and after PE_SNK_EPR_Mode_Entry. For a source, + * the SM is in and after PE_SRC_EPR_Mode_Entery_ACK. + */ + PE_FLAGS_ENTERING_EPR_FN, + /* In EPR mode */ + PE_FLAGS_IN_EPR_FN, + /* + * Indicate the port exited EPR mode explicitly. If this is set, the + * port wouldn't enter EPR mode automatically. + */ + PE_FLAGS_EPR_EXPLICIT_EXIT_FN, + /* Discovery disabled due to UFP/PD 2.0 constraint. */ + PE_FLAGS_DISCOVERY_DISABLED_FN, + /* Last element */ + PE_FLAGS_COUNT +}; + +#ifdef TEST_BUILD +void pe_set_fn(int port, int fn); +void pe_clr_fn(int port, int fn); +int pe_chk_fn(int port, int fn); +void pe_clr_dpm_requests(int port); +#endif /* TEST_BUILD */ + +#endif /* __CROS_EC_USB_PE_PRIVATE_H */ diff --git a/common/usbc/usb_prl_sm.c b/common/usbc/usb_prl_sm.c index 69861fb482..6fa3011fa7 100644 --- a/common/usbc/usb_prl_sm.c +++ b/common/usbc/usb_prl_sm.c @@ -1,16 +1,18 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "battery.h" #include "battery_smart.h" -#include "board.h" +#include "builtin/assert.h" #include "charge_manager.h" #include "charge_state.h" #include "chipset.h" #include "common.h" +#include "compile_time_macros.h" #include "console.h" +#include "cros_version.h" #include "ec_commands.h" #include "gpio.h" #include "hooks.h" @@ -18,54 +20,74 @@ #include "registers.h" #include "system.h" #include "task.h" -#include "timer.h" -#include "tcpm.h" -#include "util.h" +#include "tcpm/tcpm.h" #include "usb_charge.h" +#include "usb_emsg.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_timer.h" #include "usb_pe_sm.h" #include "usb_prl_sm.h" -#include "usb_tc_sm.h" -#include "usb_emsg.h" #include "usb_sm.h" +#include "usb_tc_sm.h" +#include "util.h" #include "vpd_api.h" -#include "version.h" #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else #define CPRINTF(format, args...) #define CPRINTS(format, args...) #endif -#define RCH_SET_FLAG(port, flag) deprecated_atomic_or(&rch[port].flags, (flag)) -#define RCH_CLR_FLAG(port, flag) \ - deprecated_atomic_clear_bits(&rch[port].flags, (flag)) +/* + * Define DEBUG_PRINT_FLAG_NAMES to print flag names when set and cleared. + */ +#undef DEBUG_PRINT_FLAG_NAMES + +#ifdef DEBUG_PRINT_FLAG_NAMES +__maybe_unused static void print_flag(const char *group, int set_or_clear, + int flag); +#define SET_FLAG(group, flags, flag) \ + do { \ + print_flag(group, 1, flag); \ + atomic_or(flags, (flag)); \ + } while (0) +#define CLR_FLAG(group, flags, flag) \ + do { \ + int before = *flags; \ + atomic_clear_bits(flags, (flag)); \ + if (*flags != before) \ + print_flag(group, 0, flag); \ + } while (0) +#else +#define SET_FLAG(group, flags, flag) atomic_or(flags, (flag)) +#define CLR_FLAG(group, flags, flag) atomic_clear_bits(flags, (flag)) +#endif + +#define RCH_SET_FLAG(port, flag) SET_FLAG("RCH", &rch[port].flags, (flag)) +#define RCH_CLR_FLAG(port, flag) CLR_FLAG("RCH", &rch[port].flags, (flag)) #define RCH_CHK_FLAG(port, flag) (rch[port].flags & (flag)) -#define TCH_SET_FLAG(port, flag) deprecated_atomic_or(&tch[port].flags, (flag)) -#define TCH_CLR_FLAG(port, flag) \ - deprecated_atomic_clear_bits(&tch[port].flags, (flag)) +#define TCH_SET_FLAG(port, flag) SET_FLAG("TCH", &tch[port].flags, (flag)) +#define TCH_CLR_FLAG(port, flag) CLR_FLAG("TCH", &tch[port].flags, (flag)) #define TCH_CHK_FLAG(port, flag) (tch[port].flags & (flag)) #define PRL_TX_SET_FLAG(port, flag) \ - deprecated_atomic_or(&prl_tx[port].flags, (flag)) + SET_FLAG("PRL_TX", &prl_tx[port].flags, (flag)) #define PRL_TX_CLR_FLAG(port, flag) \ - deprecated_atomic_clear_bits(&prl_tx[port].flags, (flag)) + CLR_FLAG("PRL_TX", &prl_tx[port].flags, (flag)) #define PRL_TX_CHK_FLAG(port, flag) (prl_tx[port].flags & (flag)) #define PRL_HR_SET_FLAG(port, flag) \ - deprecated_atomic_or(&prl_hr[port].flags, (flag)) + SET_FLAG("PRL_HR", &prl_hr[port].flags, (flag)) #define PRL_HR_CLR_FLAG(port, flag) \ - deprecated_atomic_clear_bits(&prl_hr[port].flags, (flag)) + CLR_FLAG("PRL_HR", &prl_hr[port].flags, (flag)) #define PRL_HR_CHK_FLAG(port, flag) (prl_hr[port].flags & (flag)) -#define PDMSG_SET_FLAG(port, flag) \ - deprecated_atomic_or(&pdmsg[port].flags, (flag)) -#define PDMSG_CLR_FLAG(port, flag) \ - deprecated_atomic_clear_bits(&pdmsg[port].flags, (flag)) +#define PDMSG_SET_FLAG(port, flag) SET_FLAG("PDMSG", &pdmsg[port].flags, (flag)) +#define PDMSG_CLR_FLAG(port, flag) CLR_FLAG("PDMSG", &pdmsg[port].flags, (flag)) #define PDMSG_CHK_FLAG(port, flag) (pdmsg[port].flags & (flag)) /* Protocol Layer Flags */ @@ -75,30 +97,81 @@ * different meanings in each state machine. */ /* Flag to note message transmission completed */ -#define PRL_FLAGS_TX_COMPLETE BIT(0) +#define PRL_FLAGS_TX_COMPLETE BIT(0) /* Flag to note that PRL requested to set SINK_NG CC state */ -#define PRL_FLAGS_SINK_NG BIT(1) +#define PRL_FLAGS_SINK_NG BIT(1) /* Flag to note PRL waited for SINK_OK CC state before transmitting */ -#define PRL_FLAGS_WAIT_SINK_OK BIT(2) +#define PRL_FLAGS_WAIT_SINK_OK BIT(2) /* Flag to note transmission error occurred */ -#define PRL_FLAGS_TX_ERROR BIT(3) +#define PRL_FLAGS_TX_ERROR BIT(3) /* Flag to note PE triggered a hard reset */ -#define PRL_FLAGS_PE_HARD_RESET BIT(4) +#define PRL_FLAGS_PE_HARD_RESET BIT(4) /* Flag to note hard reset has completed */ -#define PRL_FLAGS_HARD_RESET_COMPLETE BIT(5) +#define PRL_FLAGS_HARD_RESET_COMPLETE BIT(5) /* Flag to note port partner sent a hard reset */ #define PRL_FLAGS_PORT_PARTNER_HARD_RESET BIT(6) /* * Flag to note a message transmission has been requested. It is only cleared * when we send the message to the TCPC layer. */ -#define PRL_FLAGS_MSG_XMIT BIT(7) +#define PRL_FLAGS_MSG_XMIT BIT(7) /* Flag to note a message was received */ -#define PRL_FLAGS_MSG_RECEIVED BIT(8) +#define PRL_FLAGS_MSG_RECEIVED BIT(8) /* Flag to note aborting current TX message, not currently set */ -#define PRL_FLAGS_ABORT BIT(9) +#define PRL_FLAGS_ABORT BIT(9) /* Flag to note current TX message uses chunking */ -#define PRL_FLAGS_CHUNKING BIT(10) +#define PRL_FLAGS_CHUNKING BIT(10) +/* Flag to disable checking data role on incoming messages. */ +#define PRL_FLAGS_IGNORE_DATA_ROLE BIT(11) + +/* For checking flag_bit_names[] */ +#define PRL_FLAGS_COUNT 12 + +struct bit_name { + int value; + const char *name; +}; + +static __const_data const struct bit_name flag_bit_names[] = { + { PRL_FLAGS_TX_COMPLETE, "PRL_FLAGS_TX_COMPLETE" }, + { PRL_FLAGS_SINK_NG, "PRL_FLAGS_SINK_NG" }, + { PRL_FLAGS_WAIT_SINK_OK, "PRL_FLAGS_WAIT_SINK_OK" }, + { PRL_FLAGS_TX_ERROR, "PRL_FLAGS_TX_ERROR" }, + { PRL_FLAGS_PE_HARD_RESET, "PRL_FLAGS_PE_HARD_RESET" }, + { PRL_FLAGS_HARD_RESET_COMPLETE, "PRL_FLAGS_HARD_RESET_COMPLETE" }, + { PRL_FLAGS_PORT_PARTNER_HARD_RESET, + "PRL_FLAGS_PORT_PARTNER_HARD_RESET" }, + { PRL_FLAGS_MSG_XMIT, "PRL_FLAGS_MSG_XMIT" }, + { PRL_FLAGS_MSG_RECEIVED, "PRL_FLAGS_MSG_RECEIVED" }, + { PRL_FLAGS_ABORT, "PRL_FLAGS_ABORT" }, + { PRL_FLAGS_CHUNKING, "PRL_FLAGS_CHUNKING" }, + { PRL_FLAGS_IGNORE_DATA_ROLE, "PRL_FLAGS_IGNORE_DATA_ROLE" }, +}; +BUILD_ASSERT(ARRAY_SIZE(flag_bit_names) == PRL_FLAGS_COUNT); + +__maybe_unused static void print_bits(const char *group, const char *desc, + int value, const struct bit_name *names, + int names_size) +{ + int i; + + CPRINTF("%s %s 0x%x : ", group, desc, value); + for (i = 0; i < names_size; i++) { + if (value & names[i].value) + CPRINTF("%s | ", names[i].name); + value &= ~names[i].value; + } + if (value != 0) + CPRINTF("0x%x", value); + CPRINTF("\n"); +} + +__maybe_unused static void print_flag(const char *group, int set_or_clear, + int flag) +{ + print_bits(group, set_or_clear ? "Set" : "Clr", flag, flag_bit_names, + ARRAY_SIZE(flag_bit_names)); +} /* PD counter definitions */ #define PD_MESSAGE_ID_COUNT 7 @@ -119,6 +192,8 @@ */ #ifdef CONFIG_USB_PD_DEBUG_LEVEL static const enum debug_level prl_debug_level = CONFIG_USB_PD_DEBUG_LEVEL; +#elif defined(CONFIG_USB_PD_INITIAL_DEBUG_LEVEL) +static enum debug_level prl_debug_level = CONFIG_USB_PD_INITIAL_DEBUG_LEVEL; #else static enum debug_level prl_debug_level = DEBUG_LEVEL_1; #endif @@ -168,7 +243,7 @@ enum usb_tch_state { TCH_REPORT_ERROR, }; -static const char * const prl_tx_state_names[] = { +static const char *const prl_tx_state_names[] = { [PRL_TX_PHY_LAYER_RESET] = "PRL_TX_PHY_LAYER_RESET", [PRL_TX_WAIT_FOR_MESSAGE_REQUEST] = "PRL_TX_WAIT_FOR_MESSAGE_REQUEST", [PRL_TX_LAYER_RESET_FOR_TRANSMIT] = "PRL_TX_LAYER_RESET_FOR_TRANSMIT", @@ -180,19 +255,18 @@ static const char * const prl_tx_state_names[] = { [PRL_TX_DISCARD_MESSAGE] = "PRL_TX_DISCARD_MESSAGE", }; -static const char * const prl_hr_state_names[] = { +static const char *const prl_hr_state_names[] = { [PRL_HR_WAIT_FOR_REQUEST] = "PRL_HR_WAIT_FOR_REQUEST", [PRL_HR_RESET_LAYER] = "PRL_HR_RESET_LAYER", - [PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE] - = "PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE", - [PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE] - = "PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE", + [PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE] = + "PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE", + [PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE] = + "PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE", }; -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES -static const char * const rch_state_names[] = { - [RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER] - = "RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER", +__maybe_unused static const char *const rch_state_names[] = { + [RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER] = + "RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER", [RCH_PASS_UP_MESSAGE] = "RCH_PASS_UP_MESSAGE", [RCH_PROCESSING_EXTENDED_MESSAGE] = "RCH_PROCESSING_EXTENDED_MESSAGE", [RCH_REQUESTING_CHUNK] = "RCH_REQUESTING_CHUNK", @@ -200,11 +274,11 @@ static const char * const rch_state_names[] = { [RCH_REPORT_ERROR] = "RCH_REPORT_ERROR", }; -static const char * const tch_state_names[] = { - [TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE] - = "TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE", - [TCH_WAIT_FOR_TRANSMISSION_COMPLETE] - = "TCH_WAIT_FOR_TRANSMISSION_COMPLETE", +__maybe_unused static const char *const tch_state_names[] = { + [TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE] = + "TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE", + [TCH_WAIT_FOR_TRANSMISSION_COMPLETE] = + "TCH_WAIT_FOR_TRANSMISSION_COMPLETE", [TCH_CONSTRUCT_CHUNKED_MESSAGE] = "TCH_CONSTRUCT_CHUNKED_MESSAGE", [TCH_SENDING_CHUNKED_MESSAGE] = "TCH_SENDING_CHUNKED_MESSAGE", [TCH_WAIT_CHUNK_REQUEST] = "TCH_WAIT_CHUNK_REQUEST", @@ -212,25 +286,22 @@ static const char * const tch_state_names[] = { [TCH_MESSAGE_SENT] = "TCH_MESSAGE_SENT", [TCH_REPORT_ERROR] = "TCH_REPORT_ERROR", }; -#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ /* Forward declare full list of states. Index by above enums. */ static const struct usb_state prl_tx_states[]; static const struct usb_state prl_hr_states[]; -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES -static const struct usb_state rch_states[]; -static const struct usb_state tch_states[]; -#endif /* CONFIG_USB_PD_REV30 */ +__maybe_unused static const struct usb_state rch_states[]; +__maybe_unused static const struct usb_state tch_states[]; /* Chunked Rx State Machine Object */ static struct rx_chunked { /* state machine context */ struct sm_ctx ctx; /* PRL_FLAGS */ - uint32_t flags; - /* protocol timer */ - uint64_t chunk_sender_response_timer; + atomic_t flags; + /* error to report when moving to rch_report_error state */ + enum pe_error error; } rch[CONFIG_USB_PD_PORT_MAX_COUNT]; /* Chunked Tx State Machine Object */ @@ -238,9 +309,7 @@ static struct tx_chunked { /* state machine context */ struct sm_ctx ctx; /* state machine flags */ - uint32_t flags; - /* protocol timer */ - uint64_t chunk_sender_request_timer; + atomic_t flags; /* error to report when moving to tch_report_error state */ enum pe_error error; } tch[CONFIG_USB_PD_PORT_MAX_COUNT]; @@ -248,7 +317,7 @@ static struct tx_chunked { /* Message Reception State Machine Object */ static struct protocol_layer_rx { /* received message type */ - enum tcpm_transmit_type sop; + enum tcpci_msg_type sop; /* message ids for all valid port partners */ int msg_id[NUM_SOP_STAR_TYPES]; } prl_rx[CONFIG_USB_PD_PORT_MAX_COUNT]; @@ -258,13 +327,9 @@ static struct protocol_layer_tx { /* state machine context */ struct sm_ctx ctx; /* state machine flags */ - uint32_t flags; - /* protocol timer */ - uint64_t sink_tx_timer; - /* timeout to limit waiting on TCPC response (not in spec) */ - uint64_t tcpc_tx_timeout; + atomic_t flags; /* last message type we transmitted */ - enum tcpm_transmit_type last_xmit_type; + enum tcpci_msg_type last_xmit_type; /* message id counters for all 6 port partners */ uint32_t msg_id_counter[NUM_SOP_STAR_TYPES]; /* transmit status */ @@ -276,17 +341,15 @@ static struct protocol_hard_reset { /* state machine context */ struct sm_ctx ctx; /* state machine flags */ - uint32_t flags; - /* protocol timer */ - uint64_t hard_reset_complete_timer; + atomic_t flags; } prl_hr[CONFIG_USB_PD_PORT_MAX_COUNT]; /* Chunking Message Object */ static struct pd_message { /* message status flags */ - uint32_t flags; + atomic_t flags; /* SOP* */ - enum tcpm_transmit_type xmit_type; + enum tcpci_msg_type xmit_type; /* type of message */ uint8_t msg_type; /* PD revision */ @@ -303,12 +366,24 @@ static struct pd_message { uint8_t ext; uint32_t chunk_number_to_send; uint32_t send_offset; -#endif /* CONFIG_USB_PD_REV30 */ +#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ } pdmsg[CONFIG_USB_PD_PORT_MAX_COUNT]; struct extended_msg rx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT]; struct extended_msg tx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT]; +enum prl_event_log_state_kind { + /* Identifies uninitialized entries */ + PRL_EVENT_LOG_STATE_NONE, + PRL_EVENT_LOG_STATE_TX, + PRL_EVENT_LOG_STATE_HR, + PRL_EVENT_LOG_STATE_RCH, + PRL_EVENT_LOG_STATE_TCH, +}; + +__maybe_unused static void +prl_event_log_append(enum prl_event_log_state_kind kind, int port); + /* Common Protocol Layer Message Transmission */ static void prl_tx_construct_message(int port); static void prl_rx_wait_for_phy_message(const int port, int evt); @@ -322,12 +397,12 @@ GEN_NOT_SUPPORTED(PRL_TX_SNK_START_AMS); GEN_NOT_SUPPORTED(RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER); #define RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER \ - RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER_NOT_SUPPORTED + RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER_NOT_SUPPORTED GEN_NOT_SUPPORTED(RCH_PASS_UP_MESSAGE); #define RCH_PASS_UP_MESSAGE RCH_PASS_UP_MESSAGE_NOT_SUPPORTED GEN_NOT_SUPPORTED(RCH_PROCESSING_EXTENDED_MESSAGE); #define RCH_PROCESSING_EXTENDED_MESSAGE \ - RCH_PROCESSING_EXTENDED_MESSAGE_NOT_SUPPORTED + RCH_PROCESSING_EXTENDED_MESSAGE_NOT_SUPPORTED GEN_NOT_SUPPORTED(RCH_REQUESTING_CHUNK); #define RCH_REQUESTING_CHUNK RCH_REQUESTING_CHUNK_NOT_SUPPORTED GEN_NOT_SUPPORTED(RCH_WAITING_CHUNK); @@ -337,13 +412,13 @@ GEN_NOT_SUPPORTED(RCH_REPORT_ERROR); GEN_NOT_SUPPORTED(TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE); #define TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE \ - TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE_NOT_SUPPORTED + TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE_NOT_SUPPORTED GEN_NOT_SUPPORTED(TCH_WAIT_FOR_TRANSMISSION_COMPLETE); #define TCH_WAIT_FOR_TRANSMISSION_COMPLETE \ - TCH_WAIT_FOR_TRANSMISSION_COMPLETE_NOT_SUPPORTED + TCH_WAIT_FOR_TRANSMISSION_COMPLETE_NOT_SUPPORTED GEN_NOT_SUPPORTED(TCH_CONSTRUCT_CHUNKED_MESSAGE); #define TCH_CONSTRUCT_CHUNKED_MESSAGE \ - TCH_CONSTRUCT_CHUNKED_MESSAGE_NOT_SUPPORTED + TCH_CONSTRUCT_CHUNKED_MESSAGE_NOT_SUPPORTED GEN_NOT_SUPPORTED(TCH_SENDING_CHUNKED_MESSAGE); #define TCH_SENDING_CHUNKED_MESSAGE TCH_SENDING_CHUNKED_MESSAGE_NOT_SUPPORTED GEN_NOT_SUPPORTED(TCH_WAIT_CHUNK_REQUEST); @@ -356,6 +431,8 @@ GEN_NOT_SUPPORTED(TCH_REPORT_ERROR); #define TCH_REPORT_ERROR TCH_REPORT_ERROR_NOT_SUPPORTED #endif /* !CONFIG_USB_PD_REV30 */ +/* To store the time stamp when TCPC sets TX Complete Success */ +static timestamp_t tcpc_tx_success_ts[CONFIG_USB_PD_PORT_MAX_COUNT]; /* Set the protocol transmit statemachine to a new state. */ static void set_state_prl_tx(const int port, @@ -373,9 +450,10 @@ test_export_static enum usb_prl_tx_state prl_tx_get_state(const int port) /* Print the protocol transmit statemachine's current state. */ static void print_current_prl_tx_state(const int port) { + prl_event_log_append(PRL_EVENT_LOG_STATE_TX, port); if (prl_debug_level >= DEBUG_LEVEL_3) CPRINTS("C%d: %s", port, - prl_tx_state_names[prl_tx_get_state(port)]); + prl_tx_state_names[prl_tx_get_state(port)]); } /* Set the hard reset statemachine to a new state. */ @@ -394,17 +472,17 @@ enum usb_prl_hr_state prl_hr_get_state(const int port) /* Print the hard reset statemachine's current state. */ static void print_current_prl_hr_state(const int port) { + prl_event_log_append(PRL_EVENT_LOG_STATE_HR, port); if (prl_debug_level >= DEBUG_LEVEL_3) CPRINTS("C%d: %s", port, - prl_hr_state_names[prl_hr_get_state(port)]); + prl_hr_state_names[prl_hr_get_state(port)]); } /* Set the chunked Rx statemachine to a new state. */ static void set_state_rch(const int port, const enum usb_rch_state new_state) { -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES - set_state(port, &rch[port].ctx, &rch_states[new_state]); -#endif /* CONFIG_USB_PD_REV30 */ + if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) + set_state(port, &rch[port].ctx, &rch_states[new_state]); } #ifdef CONFIG_USB_PD_EXTENDED_MESSAGES @@ -417,42 +495,53 @@ test_export_static enum usb_rch_state rch_get_state(const int port) /* Print the chunked Rx statemachine's current state. */ static void print_current_rch_state(const int port) { + prl_event_log_append(PRL_EVENT_LOG_STATE_RCH, port); if (prl_debug_level >= DEBUG_LEVEL_3) - CPRINTS("C%d: %s", port, - rch_state_names[rch_get_state(port)]); + CPRINTS("C%d: %s", port, rch_state_names[rch_get_state(port)]); } #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ /* Set the chunked Tx statemachine to a new state. */ static void set_state_tch(const int port, const enum usb_tch_state new_state) { -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES - set_state(port, &tch[port].ctx, &tch_states[new_state]); -#endif /* CONFIG_USB_PD_REV30 */ + if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) + set_state(port, &tch[port].ctx, &tch_states[new_state]); } /* Get the chunked Tx statemachine's current state. */ test_export_static enum usb_tch_state tch_get_state(const int port) { -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES - return tch[port].ctx.current - &tch_states[0]; -#else - return 0; -#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ + if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) + return tch[port].ctx.current - &tch_states[0]; + else + return 0; } #ifdef CONFIG_USB_PD_EXTENDED_MESSAGES /* Print the chunked Tx statemachine's current state. */ static void print_current_tch_state(const int port) { + prl_event_log_append(PRL_EVENT_LOG_STATE_TCH, port); if (prl_debug_level >= DEBUG_LEVEL_3) - CPRINTS("C%d: %s", port, - tch_state_names[tch_get_state(port)]); + CPRINTS("C%d: %s", port, tch_state_names[tch_get_state(port)]); } #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ +timestamp_t prl_get_tcpc_tx_success_ts(int port) +{ + return tcpc_tx_success_ts[port]; +} + +/* Sets the time stamp when TCPC reports TX success. */ +static void set_tcpc_tx_success_ts(int port) +{ + tcpc_tx_success_ts[port] = get_time(); +} + void pd_transmit_complete(int port, int status) { + if (status == TCPC_TX_COMPLETE_SUCCESS) + set_tcpc_tx_success_ts(port); prl_tx[port].xmit_status = status; } @@ -478,6 +567,14 @@ void prl_execute_hard_reset(int port) task_wake(PD_PORT_TO_TASK_ID(port)); } +void prl_set_data_role_check(int port, bool enable) +{ + if (enable) + RCH_CLR_FLAG(port, PRL_FLAGS_IGNORE_DATA_ROLE); + else + RCH_SET_FLAG(port, PRL_FLAGS_IGNORE_DATA_ROLE); +} + int prl_is_running(int port) { return local_state[port] == SM_RUN; @@ -495,34 +592,34 @@ static void prl_init(int port) prl_tx[port].flags = 0; if (IS_ENABLED(CONFIG_USB_PD_REV30)) typec_select_src_collision_rp(port, SINK_TX_OK); - prl_tx[port].last_xmit_type = TCPC_TX_SOP; + prl_tx[port].last_xmit_type = TCPCI_MSG_SOP; prl_tx[port].xmit_status = TCPC_TX_UNSET; -#ifdef CONFIG_USB_PD_REV30 - tch[port].flags = 0; - rch[port].flags = 0; -#endif /* CONFIG_USB_PD_REV30 */ + if (IS_ENABLED(CONFIG_USB_PD_REV30)) { + tch[port].flags = 0; + rch[port].flags = 0; + } pdmsg[port].flags = 0; prl_hr[port].flags = 0; - for (i = 0; i < NUM_SOP_STAR_TYPES; i++) { - prl_rx[port].msg_id[i] = -1; - prl_tx[port].msg_id_counter[i] = 0; - } + for (i = 0; i < NUM_SOP_STAR_TYPES; i++) + prl_reset_msg_ids(port, i); + + pd_timer_disable_range(port, PR_TIMER_RANGE); /* Clear state machines and set initial states */ prl_tx[port].ctx = cleared; set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET); -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES - rch[port].ctx = cleared; - set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER); + if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) { + rch[port].ctx = cleared; + set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER); - tch[port].ctx = cleared; - set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE); -#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ + tch[port].ctx = cleared; + set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE); + } prl_hr[port].ctx = cleared; set_state_prl_hr(port, PRL_HR_WAIT_FOR_REQUEST); @@ -532,9 +629,8 @@ bool prl_is_busy(int port) { #ifdef CONFIG_USB_PD_EXTENDED_MESSAGES return rch_get_state(port) != - RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER || - tch_get_state(port) != - TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE; + RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER || + tch_get_state(port) != TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE; #else return false; #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ @@ -553,9 +649,8 @@ void prl_hard_reset_complete(int port) task_wake(PD_PORT_TO_TASK_ID(port)); } -void prl_send_ctrl_msg(int port, - enum tcpm_transmit_type type, - enum pd_ctrl_msg_type msg) +void prl_send_ctrl_msg(int port, enum tcpci_msg_type type, + enum pd_ctrl_msg_type msg) { pdmsg[port].xmit_type = type; pdmsg[port].msg_type = msg; @@ -568,14 +663,13 @@ void prl_send_ctrl_msg(int port, TCH_SET_FLAG(port, PRL_FLAGS_MSG_XMIT); #else PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT); -#endif /* CONFIG_USB_PD_REV30 */ +#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ task_wake(PD_PORT_TO_TASK_ID(port)); } -void prl_send_data_msg(int port, - enum tcpm_transmit_type type, - enum pd_data_msg_type msg) +void prl_send_data_msg(int port, enum tcpci_msg_type type, + enum pd_data_msg_type msg) { pdmsg[port].xmit_type = type; pdmsg[port].msg_type = msg; @@ -587,15 +681,14 @@ void prl_send_data_msg(int port, #else prl_copy_msg_to_buffer(port); PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT); -#endif /* CONFIG_USB_PD_REV30 */ +#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ task_wake(PD_PORT_TO_TASK_ID(port)); } #ifdef CONFIG_USB_PD_EXTENDED_MESSAGES -void prl_send_ext_data_msg(int port, - enum tcpm_transmit_type type, - enum pd_ext_msg_type msg) +void prl_send_ext_data_msg(int port, enum tcpci_msg_type type, + enum pd_ext_msg_type msg) { pdmsg[port].xmit_type = type; pdmsg[port].msg_type = msg; @@ -606,17 +699,18 @@ void prl_send_ext_data_msg(int port, } #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ -static void prl_set_default_pd_revision(int port) { +void prl_set_default_pd_revision(int port) +{ /* * Initialize to highest revision supported. If the port or cable * partner doesn't support this revision, the Protocol Engine will * lower this value to the revision supported by the partner. */ - pdmsg[port].rev[TCPC_TX_SOP] = PD_REVISION; - pdmsg[port].rev[TCPC_TX_SOP_PRIME] = PD_REVISION; - pdmsg[port].rev[TCPC_TX_SOP_PRIME_PRIME] = PD_REVISION; - pdmsg[port].rev[TCPC_TX_SOP_DEBUG_PRIME] = PD_REVISION; - pdmsg[port].rev[TCPC_TX_SOP_DEBUG_PRIME_PRIME] = PD_REVISION; + pdmsg[port].rev[TCPCI_MSG_SOP] = PD_REVISION; + pdmsg[port].rev[TCPCI_MSG_SOP_PRIME] = PD_REVISION; + pdmsg[port].rev[TCPCI_MSG_SOP_PRIME_PRIME] = PD_REVISION; + pdmsg[port].rev[TCPCI_MSG_SOP_DEBUG_PRIME] = PD_REVISION; + pdmsg[port].rev[TCPCI_MSG_SOP_DEBUG_PRIME_PRIME] = PD_REVISION; } void prl_reset_soft(int port) @@ -628,27 +722,17 @@ void prl_reset_soft(int port) task_wake(PD_PORT_TO_TASK_ID(port)); } -void prl_reset(int port) -{ - prl_set_default_pd_revision(port); - local_state[port] = SM_INIT; - - /* Ensure we process the reset quickly */ - task_wake(PD_PORT_TO_TASK_ID(port)); -} - void prl_run(int port, int evt, int en) { switch (local_state[port]) { case SM_PAUSED: if (!en) break; - prl_set_default_pd_revision(port); - /* fall through */ + __fallthrough; case SM_INIT: prl_init(port); local_state[port] = SM_RUN; - /* fall through */ + __fallthrough; case SM_RUN: if (!en) { /* Disable RX */ @@ -662,43 +746,51 @@ void prl_run(int port, int evt, int en) break; } - /* Run Protocol Layer Message Reception */ - prl_rx_wait_for_phy_message(port, evt); + /* Run Protocol Layer Hard Reset state machine */ + run_state(port, &prl_hr[port].ctx); -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES /* - * Run RX Chunked state machine after prl_rx. This is what - * informs the PE of incoming message. Its input is prl_rx + * If the Hard Reset state machine is active, then there is no + * need to execute any other PRL state machines. When the hard + * reset is complete, all PRL state machines will have been + * reset. */ - run_state(port, &rch[port].ctx); + if (prl_hr_get_state(port) == PRL_HR_WAIT_FOR_REQUEST) { + /* Run Protocol Layer Message Reception */ + prl_rx_wait_for_phy_message(port, evt); - /* - * Run TX Chunked state machine before prl_tx in case we need - * to split an extended message and prl_tx can send it for us - */ - run_state(port, &tch[port].ctx); -#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ + if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) { + /* + * Run RX Chunked state machine after prl_rx. + * This is what informs the PE of incoming + * message. Its input is prl_rx + */ + run_state(port, &rch[port].ctx); - /* Run Protocol Layer Message Transmission state machine */ - run_state(port, &prl_tx[port].ctx); + /* + * Run TX Chunked state machine before prl_tx + * in case we need to split an extended message + * and prl_tx can send it for us + */ + run_state(port, &tch[port].ctx); + } -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES - /* - * Run TX Chunked state machine again after prl_tx so we can - * handle passing TX_COMPLETE (or failure) up to PE in a single - * iteration. - */ - run_state(port, &tch[port].ctx); -#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ + /* Run Protocol Layer Message Tx state machine */ + run_state(port, &prl_tx[port].ctx); - /* Run Protocol Layer Hard Reset state machine */ - run_state(port, &prl_hr[port].ctx); + if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) + /* + * Run TX Chunked state machine again after + * prl_tx so we can handle passing TX_COMPLETE + * (or failure) up to PE in a single iteration. + */ + run_state(port, &tch[port].ctx); + } break; } } -void prl_set_rev(int port, enum tcpm_transmit_type type, - enum pd_rev_type rev) +void prl_set_rev(int port, enum tcpci_msg_type type, enum pd_rev_type rev) { /* We only store revisions for SOP* types. */ ASSERT(type < NUM_SOP_STAR_TYPES); @@ -706,7 +798,7 @@ void prl_set_rev(int port, enum tcpm_transmit_type type, pdmsg[port].rev[type] = rev; } -enum pd_rev_type prl_get_rev(int port, enum tcpm_transmit_type type) +enum pd_rev_type prl_get_rev(int port, enum tcpci_msg_type type) { /* We only store revisions for SOP* types. */ ASSERT(type < NUM_SOP_STAR_TYPES); @@ -714,6 +806,12 @@ enum pd_rev_type prl_get_rev(int port, enum tcpm_transmit_type type) return pdmsg[port].rev[type]; } +void prl_reset_msg_ids(int port, enum tcpci_msg_type type) +{ + prl_tx[port].msg_id_counter[type] = 0; + prl_rx[port].msg_id[type] = -1; +} + static void prl_copy_msg_to_buffer(int port) { /* @@ -739,7 +837,7 @@ static void prl_copy_msg_to_buffer(int port) /* Copy message to chunked buffer */ memset((uint8_t *)pdmsg[port].tx_chk_buf, 0, CHK_BUF_SIZE_BYTES); memcpy((uint8_t *)pdmsg[port].tx_chk_buf, (uint8_t *)tx_emsg[port].buf, - tx_emsg[port].len); + tx_emsg[port].len); /* * Pad length to 4-byte boundary and * convert to number of 32-bit objects. @@ -753,8 +851,8 @@ static void prl_copy_msg_to_buffer(int port) static __maybe_unused int pdmsg_xmit_type_is_rev30(const int port) { if (IS_ENABLED(CONFIG_USB_PD_REV30)) - return ((pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES) - && (prl_get_rev(port, pdmsg[port].xmit_type) == PD_REV30)); + return ((pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES) && + (prl_get_rev(port, pdmsg[port].xmit_type) == PD_REV30)); else return 0; } @@ -763,7 +861,7 @@ static __maybe_unused int pdmsg_xmit_type_is_rev30(const int port) static bool is_sop_rev30(const int port) { return IS_ENABLED(CONFIG_USB_PD_REV30) && - prl_get_rev(port, TCPC_TX_SOP) == PD_REV30; + prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV30; } /* Common Protocol Layer Message Transmission */ @@ -771,8 +869,7 @@ static void prl_tx_phy_layer_reset_entry(const int port) { print_current_prl_tx_state(port); - if (IS_ENABLED(CONFIG_USB_CTVPD) - || IS_ENABLED(CONFIG_USB_VPD)) { + if (IS_ENABLED(CONFIG_USB_CTVPD) || IS_ENABLED(CONFIG_USB_VPD)) { vpd_rx_enable(pd_is_connected(port)); } else { /* Note: can't clear PHY messages due to TCPC architecture */ @@ -784,6 +881,8 @@ static void prl_tx_phy_layer_reset_entry(const int port) static void prl_tx_wait_for_message_request_entry(const int port) { + /* No phy layer response is pending */ + prl_tx[port].xmit_status = TCPC_TX_UNSET; print_current_prl_tx_state(port); } @@ -807,7 +906,7 @@ static void prl_tx_wait_for_message_request_run(const int port) if (IS_ENABLED(CONFIG_USB_PD_REV30) && is_sop_rev30(port) && pe_in_local_ams(port)) { if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_SINK_NG | - PRL_FLAGS_WAIT_SINK_OK)) { + PRL_FLAGS_WAIT_SINK_OK)) { /* * If we are already in an AMS then allow the * multi-message AMS to continue, even if we @@ -838,7 +937,7 @@ static void prl_tx_wait_for_message_request_run(const int port) * Soft Reset Message Message pending */ if ((pdmsg[port].msg_type == PD_CTRL_SOFT_RESET) && - (tx_emsg[port].len == 0)) { + (tx_emsg[port].len == 0)) { set_state_prl_tx(port, PRL_TX_LAYER_RESET_FOR_TRANSMIT); } /* @@ -876,8 +975,17 @@ static void prl_tx_discard_message_entry(const int port) * Discard queued message * Note: We differ from spec here, which allows us to not discard on * incoming SOP' or SOP''. However this would get the TCH out of sync. + * + * prl_tx will be set to this state following message reception in + * prl_rx. So this path will be entered following each rx message. If + * this state is entered, and there is either a message from the PE + * pending, or if a message was passed to the phy and there is either no + * response yet, or it was discarded in the phy layer, then a tx message + * discard event has been detected. */ - if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) { + if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT) || + prl_tx[port].xmit_status == TCPC_TX_WAIT || + prl_tx[port].xmit_status == TCPC_TX_COMPLETE_DISCARDED) { PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT); increment_msgid_counter(port); pe_report_discard(port); @@ -935,13 +1043,25 @@ static void prl_tx_snk_start_ams_run(const int port) */ static void prl_tx_layer_reset_for_transmit_entry(const int port) { - int i; - print_current_prl_tx_state(port); - /* Reset MessageIdCounters */ - for (i = 0; i < NUM_SOP_STAR_TYPES; i++) - prl_tx[port].msg_id_counter[i] = 0; + if (pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES) { + /* + * This state is only used during soft resets. Reset only the + * matching message type. + * + * From section 6.3.13 Soft Reset Message in the USB PD 3.0 + * v2.0 spec, Soft_Reset Message Shall be targeted at a + * specific entity depending on the type of SOP* Packet used. + * + * + * From section 6.11.2.3.2, the MessageID should be cleared + * from the PRL_Rx_Layer_Reset_for_Receive state. However, we + * don't implement a full state machine for PRL RX states so + * clear the MessageID here. + */ + prl_reset_msg_ids(port, pdmsg[port].xmit_type); + } } static void prl_tx_layer_reset_for_transmit_run(const int port) @@ -953,7 +1073,7 @@ static void prl_tx_layer_reset_for_transmit_run(const int port) static uint32_t get_sop_star_header(const int port) { - const int is_sop_packet = pdmsg[port].xmit_type == TCPC_TX_SOP; + const int is_sop_packet = pdmsg[port].xmit_type == TCPCI_MSG_SOP; int ext; #ifdef CONFIG_USB_PD_EXTENDED_MESSAGES @@ -963,33 +1083,32 @@ static uint32_t get_sop_star_header(const int port) #endif /* SOP vs SOP'/SOP" headers are different. Replace fields as needed */ - return PD_HEADER( - pdmsg[port].msg_type, - is_sop_packet ? - pd_get_power_role(port) : tc_get_cable_plug(port), - is_sop_packet ? - pd_get_data_role(port) : 0, - prl_tx[port].msg_id_counter[pdmsg[port].xmit_type], - pdmsg[port].data_objs, - pdmsg[port].rev[pdmsg[port].xmit_type], - ext); + return PD_HEADER(pdmsg[port].msg_type, + is_sop_packet ? pd_get_power_role(port) : + tc_get_cable_plug(port), + is_sop_packet ? pd_get_data_role(port) : 0, + prl_tx[port].msg_id_counter[pdmsg[port].xmit_type], + pdmsg[port].data_objs, + pdmsg[port].rev[pdmsg[port].xmit_type], ext); } static void prl_tx_construct_message(const int port) { /* The header is unused for hard reset, etc. */ const uint32_t header = pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES ? - get_sop_star_header(port) : 0; + get_sop_star_header(port) : + 0; /* Save SOP* so the correct msg_id_counter can be incremented */ prl_tx[port].last_xmit_type = pdmsg[port].xmit_type; + /* Indicate that a tx message is being passed to the phy layer */ + prl_tx[port].xmit_status = TCPC_TX_WAIT; /* - * These flags could be set if this function is called before the - * Policy Engine is informed of the previous transmission. Clear the - * flags so that this message can be sent. + * PRL_FLAGS_TX_COMPLETE could be set if this function is called before + * the Policy Engine is informed of the previous transmission. Clear the + * flag so that this message can be sent. */ - prl_tx[port].xmit_status = TCPC_TX_UNSET; PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE); /* @@ -1011,18 +1130,11 @@ static void prl_tx_wait_for_phy_response_entry(const int port) { print_current_prl_tx_state(port); - prl_tx[port].tcpc_tx_timeout = get_time().val + PD_T_TCPC_TX_TIMEOUT; + pd_timer_enable(port, PR_TIMER_TCPC_TX_TIMEOUT, PD_T_TCPC_TX_TIMEOUT); } static void prl_tx_wait_for_phy_response_run(const int port) { - /* - * TODO(b/164154200): Revert Change-Id - * If6dce35dfd78ee3a70e6216a7b6bf62d3ded5646 workaround to support - * validation for Delbin build. - */ - const bool timed_out = get_time().val > prl_tx[port].tcpc_tx_timeout; - /* Wait until TX is complete */ /* @@ -1032,8 +1144,7 @@ static void prl_tx_wait_for_phy_response_run(const int port) * requirement. */ - if ((IS_ENABLED(BOARD_DELBIN) && timed_out) || - prl_tx[port].xmit_status == TCPC_TX_COMPLETE_SUCCESS) { + if (prl_tx[port].xmit_status == TCPC_TX_COMPLETE_SUCCESS) { /* NOTE: PRL_TX_Message_Sent State embedded here. */ /* Increment messageId counter */ increment_msgid_counter(port); @@ -1050,9 +1161,8 @@ static void prl_tx_wait_for_phy_response_run(const int port) */ task_wake(PD_PORT_TO_TASK_ID(port)); set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST); - } else if ((!IS_ENABLED(BOARD_DELBIN) && timed_out) || - prl_tx[port].xmit_status == TCPC_TX_COMPLETE_FAILED || - prl_tx[port].xmit_status == TCPC_TX_COMPLETE_DISCARDED) { + } else if (pd_timer_is_expired(port, PR_TIMER_TCPC_TX_TIMEOUT) || + prl_tx[port].xmit_status == TCPC_TX_COMPLETE_FAILED) { /* * NOTE: PRL_Tx_Transmission_Error State embedded * here. @@ -1078,7 +1188,7 @@ static void prl_tx_wait_for_phy_response_run(const int port) static void prl_tx_wait_for_phy_response_exit(const int port) { - prl_tx[port].xmit_status = TCPC_TX_UNSET; + pd_timer_disable(port, PR_TIMER_TCPC_TX_TIMEOUT); } /* Source Protocol Layer Message Transmission */ @@ -1090,12 +1200,12 @@ static void prl_tx_src_pending_entry(const int port) print_current_prl_tx_state(port); /* Start SinkTxTimer */ - prl_tx[port].sink_tx_timer = get_time().val + PD_T_SINK_TX; + pd_timer_enable(port, PR_TIMER_SINK_TX, PD_T_SINK_TX); } static void prl_tx_src_pending_run(const int port) { - if (get_time().val > prl_tx[port].sink_tx_timer) { + if (pd_timer_is_expired(port, PR_TIMER_SINK_TX)) { /* * We clear the pending XMIT flag here right before we send so * we can detect if we discarded this message or not @@ -1107,7 +1217,7 @@ static void prl_tx_src_pending_run(const int port) * SinkTxTimer timeout */ if ((tx_emsg[port].len == 0) && - (pdmsg[port].msg_type == PD_CTRL_SOFT_RESET)) { + (pdmsg[port].msg_type == PD_CTRL_SOFT_RESET)) { set_state_prl_tx(port, PRL_TX_LAYER_RESET_FOR_TRANSMIT); } /* Message pending (except Soft Reset) & @@ -1122,6 +1232,11 @@ static void prl_tx_src_pending_run(const int port) } } +static void prl_tx_src_pending_exit(int port) +{ + pd_timer_disable(port, PR_TIMER_SINK_TX); +} + /* * PrlTxSnkPending */ @@ -1132,11 +1247,25 @@ static void prl_tx_snk_pending_entry(const int port) static void prl_tx_snk_pending_run(const int port) { - enum tcpc_cc_voltage_status cc1, cc2; + bool start_tx = false; + + /* + * Wait unit the SRC applies SINK_TX_OK so we can transmit. In FRS mode, + * don't wait for SINK_TX_OK since either the source (and Rp) could be + * gone or the TCPC CC_STATUS update time could be too long to meet + * tFRSwapInit. + */ + if (pe_in_frs_mode(port)) { + /* shortcut to save some i2c_xfer calls on the FRS path. */ + start_tx = true; + } else { + enum tcpc_cc_voltage_status cc1, cc2; - /* Wait unit the SRC applies SINK_TX_OK so we can transmit */ - tcpm_get_cc(port, &cc1, &cc2); - if (cc1 == TYPEC_CC_VOLT_RP_3_0 || cc2 == TYPEC_CC_VOLT_RP_3_0) { + tcpm_get_cc(port, &cc1, &cc2); + start_tx = (cc1 == TYPEC_CC_VOLT_RP_3_0 || + cc2 == TYPEC_CC_VOLT_RP_3_0); + } + if (start_tx) { /* * We clear the pending XMIT flag here right before we send so * we can detect if we discarded this message or not @@ -1148,7 +1277,7 @@ static void prl_tx_snk_pending_run(const int port) * Rp = SinkTxOk */ if ((pdmsg[port].msg_type == PD_CTRL_SOFT_RESET) && - (tx_emsg[port].len == 0)) { + (tx_emsg[port].len == 0)) { set_state_prl_tx(port, PRL_TX_LAYER_RESET_FOR_TRANSMIT); } /* @@ -1164,6 +1293,25 @@ static void prl_tx_snk_pending_run(const int port) } /* Hard Reset Operation */ +void prl_hr_send_msg_to_phy(const int port) +{ + /* Header is not used for hard reset */ + const uint32_t header = 0; + + pdmsg[port].xmit_type = TCPCI_MSG_TX_HARD_RESET; + + /* + * These flags could be set if this function is called before the + * Policy Engine is informed of the previous transmission. Clear the + * flags so that this message can be sent. + */ + prl_tx[port].xmit_status = TCPC_TX_UNSET; + PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE); + + /* Pass message to PHY Layer */ + tcpm_transmit(port, pdmsg[port].xmit_type, header, + pdmsg[port].tx_chk_buf); +} static void prl_hr_wait_for_request_entry(const int port) { @@ -1175,7 +1323,7 @@ static void prl_hr_wait_for_request_entry(const int port) static void prl_hr_wait_for_request_run(const int port) { if (PRL_HR_CHK_FLAG(port, PRL_FLAGS_PE_HARD_RESET | - PRL_FLAGS_PORT_PARTNER_HARD_RESET)) + PRL_FLAGS_PORT_PARTNER_HARD_RESET)) set_state_prl_hr(port, PRL_HR_RESET_LAYER); } @@ -1188,35 +1336,46 @@ static void prl_hr_reset_layer_entry(const int port) print_current_prl_hr_state(port); - /* reset messageIDCounters */ - for (i = 0; i < NUM_SOP_STAR_TYPES; i++) - prl_tx[port].msg_id_counter[i] = 0; - /* - * Protocol Layer message transmission transitions to - * PRL_Tx_Wait_For_Message_Request state. - */ - set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST); - -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES - tch[port].flags = 0; - rch[port].flags = 0; -#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ + if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) { + tch[port].flags = 0; + rch[port].flags = 0; + } pdmsg[port].flags = 0; - /* Reset message ids */ + /* Hard reset resets messageIDCounters for all TX types */ for (i = 0; i < NUM_SOP_STAR_TYPES; i++) { - prl_rx[port].msg_id[i] = -1; - prl_tx[port].msg_id_counter[i] = 0; + prl_reset_msg_ids(port, i); } /* Disable RX */ - if (IS_ENABLED(CONFIG_USB_CTVPD) || - IS_ENABLED(CONFIG_USB_VPD)) + if (IS_ENABLED(CONFIG_USB_CTVPD) || IS_ENABLED(CONFIG_USB_VPD)) vpd_rx_enable(0); else tcpm_set_rx_enable(port, 0); + /* + * PD r3.0 v2.0, ss6.2.1.1.5: + * After a physical or logical (USB Type-C Error Recovery) Attach, a + * Port discovers the common Specification Revision level between itself + * and its Port Partner and/or the Cable Plug(s), and uses this + * Specification Revision level until a Detach, Hard Reset or Error + * Recovery happens. + * + * This covers the Hard Reset case. + */ + prl_set_default_pd_revision(port); + + /* Inform the AP of Hard Reset */ + if (IS_ENABLED(CONFIG_USB_PD_HOST_CMD)) + pd_notify_event(port, PD_STATUS_EVENT_HARD_RESET); + + /* + * Protocol Layer message transmission transitions to + * PRL_Tx_Wait_For_Message_Request state. + */ + set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST); + return; } @@ -1227,8 +1386,11 @@ static void prl_hr_reset_layer_run(const int port) * Hard Reset was initiated by Policy Engine */ if (PRL_HR_CHK_FLAG(port, PRL_FLAGS_PE_HARD_RESET)) { - /* Request PHY to perform a Hard Reset */ - prl_send_ctrl_msg(port, TCPC_TX_HARD_RESET, 0); + /* + * Request PHY to perform a Hard Reset. Note + * PRL_HR_Request_Reset state is embedded here. + */ + prl_hr_send_msg_to_phy(port); set_state_prl_hr(port, PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE); } /* @@ -1250,8 +1412,7 @@ static void prl_hr_wait_for_phy_hard_reset_complete_entry(const int port) print_current_prl_hr_state(port); /* Start HardResetCompleteTimer */ - prl_hr[port].hard_reset_complete_timer = - get_time().val + PD_T_PS_HARD_RESET; + pd_timer_enable(port, PR_TIMER_HARD_RESET_COMPLETE, PD_T_PS_HARD_RESET); } static void prl_hr_wait_for_phy_hard_reset_complete_run(const int port) @@ -1261,7 +1422,7 @@ static void prl_hr_wait_for_phy_hard_reset_complete_run(const int port) * or timeout */ if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE) || - (get_time().val > prl_hr[port].hard_reset_complete_timer)) { + pd_timer_is_expired(port, PR_TIMER_HARD_RESET_COMPLETE)) { /* PRL_HR_PHY_Hard_Reset_Requested */ /* Inform Policy Engine Hard Reset was sent */ @@ -1272,6 +1433,11 @@ static void prl_hr_wait_for_phy_hard_reset_complete_run(const int port) } } +static void prl_hr_wait_for_phy_hard_reset_complete_exit(int port) +{ + pd_timer_disable(port, PR_TIMER_HARD_RESET_COMPLETE); +} + /* * PrlHrWaitForPeHardResetComplete */ @@ -1304,11 +1470,11 @@ static void copy_chunk_to_ext(int port) { /* Calculate number of bytes */ pdmsg[port].num_bytes_received = - (PD_HEADER_CNT(rx_emsg[port].header) * 4); + (PD_HEADER_CNT(rx_emsg[port].header) * 4); /* Copy chunk into extended message */ memcpy((uint8_t *)rx_emsg[port].buf, (uint8_t *)pdmsg[port].rx_chk_buf, - pdmsg[port].num_bytes_received); + pdmsg[port].num_bytes_received); /* Set extended message length */ rx_emsg[port].len = pdmsg[port].num_bytes_received; @@ -1340,10 +1506,10 @@ static void rch_wait_for_message_from_protocol_layer_run(const int port) * Are we communicating with a PD3.0 device and is * this an extended message? */ - if (pdmsg_xmit_type_is_rev30(port) - && PD_HEADER_EXT(rx_emsg[port].header)) { + if (pdmsg_xmit_type_is_rev30(port) && + PD_HEADER_EXT(rx_emsg[port].header)) { uint16_t exhdr = - GET_EXT_HEADER(*pdmsg[port].rx_chk_buf); + GET_EXT_HEADER(*pdmsg[port].rx_chk_buf); uint8_t chunked = PD_EXT_HEADER_CHUNKED(exhdr); /* @@ -1351,7 +1517,7 @@ static void rch_wait_for_message_from_protocol_layer_run(const int port) * (Chunking = 1 & Chunked = 1) */ if ((RCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING)) && - chunked) { + chunked) { /* * RCH_Processing_Extended_Message first chunk * entry processing embedded here @@ -1373,7 +1539,7 @@ static void rch_wait_for_message_from_protocol_layer_run(const int port) * (Chunking = 0 & Chunked = 0)) */ else if (!RCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING) && - !chunked) { + !chunked) { /* Copy chunk to extended buffer */ copy_chunk_to_ext(port); set_state_rch(port, RCH_PASS_UP_MESSAGE); @@ -1382,6 +1548,7 @@ static void rch_wait_for_message_from_protocol_layer_run(const int port) * Chunked != Chunking */ else { + rch[port].error = ERR_RCH_CHUNKED; set_state_rch(port, RCH_REPORT_ERROR); } } @@ -1398,6 +1565,7 @@ static void rch_wait_for_message_from_protocol_layer_run(const int port) * revision lower than PD3.0 */ else { + rch[port].error = ERR_RCH_CHUNKED; set_state_rch(port, RCH_REPORT_ERROR); } } @@ -1449,8 +1617,9 @@ static void rch_processing_extended_message_run(const int port) byte_num = PD_MAX_EXTENDED_MSG_CHUNK_LEN; /* Make sure extended message buffer does not overflow */ - if (pdmsg[port].num_bytes_received + - byte_num > EXTENDED_BUFFER_SIZE) { + if (pdmsg[port].num_bytes_received + byte_num > + EXTENDED_BUFFER_SIZE) { + rch[port].error = ERR_RCH_CHUNKED; set_state_rch(port, RCH_REPORT_ERROR); return; } @@ -1458,9 +1627,8 @@ static void rch_processing_extended_message_run(const int port) /* Append data */ /* Add 2 to chk_buf to skip over extended message header */ memcpy(((uint8_t *)rx_emsg[port].buf + - pdmsg[port].num_bytes_received), - (uint8_t *)pdmsg[port].rx_chk_buf + 2, - byte_num); + pdmsg[port].num_bytes_received), + (uint8_t *)pdmsg[port].rx_chk_buf + 2, byte_num); /* increment chunk number expected */ pdmsg[port].chunk_number_expected++; /* adjust num bytes received */ @@ -1469,7 +1637,7 @@ static void rch_processing_extended_message_run(const int port) /* Was that the last chunk? */ if (pdmsg[port].num_bytes_received >= data_size) { rx_emsg[port].len = pdmsg[port].num_bytes_received; - /* Pass Message to Policy Engine */ + /* Pass Message to Policy Engine */ set_state_rch(port, RCH_PASS_UP_MESSAGE); } /* @@ -1481,8 +1649,10 @@ static void rch_processing_extended_message_run(const int port) /* * Unexpected Chunk Number */ - else + else { + rch[port].error = ERR_RCH_CHUNKED; set_state_rch(port, RCH_REPORT_ERROR); + } } /* @@ -1496,16 +1666,17 @@ static void rch_requesting_chunk_entry(const int port) * Send Chunk Request to Protocol Layer * with chunk number = Chunk_Number_Expected */ - pdmsg[port].tx_chk_buf[0] = PD_EXT_HEADER( - pdmsg[port].chunk_number_expected, - 1, /* Request Chunk */ - 0 /* Data Size */ - ); + pdmsg[port].tx_chk_buf[0] = + PD_EXT_HEADER(pdmsg[port].chunk_number_expected, 1, /* Request + Chunk */ + 0 /* Data Size */ + ); pdmsg[port].data_objs = 1; pdmsg[port].ext = 1; + pdmsg[port].xmit_type = prl_rx[port].sop; PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT); - task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX); } static void rch_requesting_chunk_run(const int port) @@ -1516,18 +1687,20 @@ static void rch_requesting_chunk_run(const int port) if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE)) { PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE); set_state_rch(port, RCH_WAITING_CHUNK); - } - /* - * Transmission Error from Protocol Layer or - * Message Received From Protocol Layer - */ - else if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED) || - PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_ERROR)) { + } else if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_ERROR)) { + /* Transmission Error from Protocol Layer detetected */ + rch[port].error = ERR_RCH_CHUNKED; + set_state_rch(port, RCH_REPORT_ERROR); + } else if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) { /* - * Leave PRL_FLAGS_MSG_RECEIVED flag set. It'll be - * cleared in rch_report_error state + * It is possible to have both message received and the chunk + * request transmit complete before a full PRL SM run. But, the + * PRL_RX state machine runs prior to RCH, but before PRL_TX, so + * PRL_FLAGS_MSG_RECEIVED can be set without + * PRL_FLAGS_TX_COMPLETE set at this point (though it will be + * set as soon as PRL_TX is executed next. */ - set_state_rch(port, RCH_REPORT_ERROR); + set_state_rch(port, RCH_WAITING_CHUNK); } } @@ -1541,13 +1714,23 @@ static void rch_waiting_chunk_entry(const int port) /* * Start ChunkSenderResponseTimer */ - rch[port].chunk_sender_response_timer = - get_time().val + PD_T_CHUNK_SENDER_RESPONSE; + pd_timer_enable(port, PR_TIMER_CHUNK_SENDER_RESPONSE, + PD_T_CHUNK_SENDER_RESPONSE); } static void rch_waiting_chunk_run(const int port) { if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) { + /* + * Because of the 5 msec tick time, it is possible to have both + * msg_received and tx_complete flags set for a given PRL sm + * run. Since prl_rx runs prior to the tx state machines, clear + * the tx_complete flag as the next chunk has already been + * received. + */ + if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE)) + PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE); + /* * Leave PRL_FLAGS_MSG_RECEIVED flag set just in case an error * is detected. If an error is detected, PRL_FLAGS_MSG_RECEIVED @@ -1562,6 +1745,7 @@ static void rch_waiting_chunk_run(const int port) */ if (PD_EXT_HEADER_REQ_CHUNK(exhdr) || !PD_EXT_HEADER_CHUNKED(exhdr)) { + rch[port].error = ERR_RCH_CHUNKED; set_state_rch(port, RCH_REPORT_ERROR); } /* @@ -1569,7 +1753,7 @@ static void rch_waiting_chunk_run(const int port) */ else { /* - * No error wad detected, so clear + * No error was detected, so clear * PRL_FLAGS_MSG_RECEIVED flag. */ RCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED); @@ -1581,11 +1765,17 @@ static void rch_waiting_chunk_run(const int port) /* * ChunkSenderResponseTimer Timeout */ - else if (get_time().val > rch[port].chunk_sender_response_timer) { + else if (pd_timer_is_expired(port, PR_TIMER_CHUNK_SENDER_RESPONSE)) { + rch[port].error = ERR_RCH_CHUNK_WAIT_TIMEOUT; set_state_rch(port, RCH_REPORT_ERROR); } } +static void rch_waiting_chunk_exit(int port) +{ + pd_timer_disable(port, PR_TIMER_CHUNK_SENDER_RESPONSE); +} + /* * RchReportError */ @@ -1607,8 +1797,7 @@ static void rch_report_error_entry(const int port) /* Report error */ pe_report_error(port, ERR_RCH_MSG_REC, prl_rx[port].sop); } else { - /* Report error */ - pe_report_error(port, ERR_RCH_CHUNKED, prl_rx[port].sop); + pe_report_error(port, rch[port].error, prl_rx[port].sop); } } @@ -1632,7 +1821,7 @@ static void tch_wait_for_message_request_from_pe_entry(const int port) PDMSG_CLR_FLAG(port, PRL_FLAGS_ABORT); /* All Messages are chunked */ - tch[port].flags = PRL_FLAGS_CHUNKING; + TCH_SET_FLAG(port, PRL_FLAGS_CHUNKING); } static void tch_wait_for_message_request_from_pe_run(const int port) @@ -1652,16 +1841,15 @@ static void tch_wait_for_message_request_from_pe_run(const int port) * Discard the Message */ if (rch_get_state(port) != - RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER) { + RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER) { tch[port].error = ERR_TCH_XMIT; set_state_tch(port, TCH_REPORT_ERROR); } else { /* * Extended Message Request & Chunking */ - if (pdmsg_xmit_type_is_rev30(port) - && pdmsg[port].ext - && TCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING)) { + if (pdmsg_xmit_type_is_rev30(port) && pdmsg[port].ext && + TCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING)) { /* * NOTE: TCH_Prepare_To_Send_Chunked_Message * embedded here. @@ -1680,7 +1868,8 @@ static void tch_wait_for_message_request_from_pe_run(const int port) /* Pass Message to Protocol Layer */ PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT); - set_state_tch(port, + set_state_tch( + port, TCH_WAIT_FOR_TRANSMISSION_COMPLETE); } } @@ -1715,13 +1904,17 @@ static void tch_wait_for_transmission_complete_run(const int port) return; } /* - * Any message received and not in state TCH_Wait_Chunk_Request - * MUST be checked after transmission status due to our TCPC - * architecture, and should not be checked if prl_tx is still waiting on - * the TCPC. + * A message was received while TCH is waiting for the phy to complete + * sending a tx message. + * + * Because of our prl_sm architecture and I2C access delays for TCPCs, + * it's possible to have a message received and the prl_tx state not be + * in its default waiting state. To avoid a false protocol error, only + * jump to TCH_MESSAGE_RECEIVED if the phy layer has not indicated that + * the tx message was sent successfully. */ if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED) && - prl_tx_get_state(port) != PRL_TX_WAIT_FOR_PHY_RESPONSE) { + prl_tx[port].xmit_status != TCPC_TX_COMPLETE_SUCCESS) { TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED); set_state_tch(port, TCH_MESSAGE_RECEIVED); return; @@ -1758,8 +1951,9 @@ static void tch_construct_chunked_message_entry(const int port) num = PD_MAX_EXTENDED_MSG_CHUNK_LEN; /* Set the chunks extended header */ - *ext_hdr = PD_EXT_HEADER(pdmsg[port].chunk_number_to_send, - 0, /* Chunk Request */ + *ext_hdr = PD_EXT_HEADER(pdmsg[port].chunk_number_to_send, 0, /* Chunk + Request + */ tx_emsg[port].len); /* Copy the message chunk into chk_buf */ @@ -1837,8 +2031,8 @@ static void tch_wait_chunk_request_entry(const int port) /* Increment Chunk Number to Send */ pdmsg[port].chunk_number_to_send++; /* Start Chunk Sender Request Timer */ - tch[port].chunk_sender_request_timer = - get_time().val + PD_T_CHUNK_SENDER_REQUEST; + pd_timer_enable(port, PR_TIMER_CHUNK_SENDER_REQUEST, + PD_T_CHUNK_SENDER_REQUEST); } static void tch_wait_chunk_request_run(const int port) @@ -1857,7 +2051,8 @@ static void tch_wait_chunk_request_run(const int port) */ if (PD_EXT_HEADER_CHUNK_NUM(exthdr) == pdmsg[port].chunk_number_to_send) { - set_state_tch(port, + set_state_tch( + port, TCH_CONSTRUCT_CHUNKED_MESSAGE); } /* @@ -1880,10 +2075,13 @@ static void tch_wait_chunk_request_run(const int port) /* * ChunkSenderRequestTimer timeout */ - else if (get_time().val >= - tch[port].chunk_sender_request_timer) { + else if (pd_timer_is_expired(port, PR_TIMER_CHUNK_SENDER_REQUEST)) set_state_tch(port, TCH_MESSAGE_SENT); - } +} + +static void tch_wait_chunk_request_exit(int port) +{ + pd_timer_disable(port, PR_TIMER_CHUNK_SENDER_REQUEST); } /* @@ -1929,8 +2127,6 @@ static void tch_message_sent_entry(const int port) return; } - - set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE); } @@ -1954,7 +2150,6 @@ static void tch_report_error_entry(const int port) return; } - set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE); } #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ @@ -1994,7 +2189,7 @@ static void prl_rx_wait_for_phy_message(const int port, int evt) /* dump received packet content (only dump ping at debug level MAX) */ if ((prl_debug_level >= DEBUG_LEVEL_2 && type != PD_CTRL_PING) || - prl_debug_level >= DEBUG_LEVEL_3) { + prl_debug_level >= DEBUG_LEVEL_3) { int p; ccprintf("C%d: RECV %04x/%d ", port, header, cnt); @@ -2007,31 +2202,44 @@ static void prl_rx_wait_for_phy_message(const int port, int evt) * Ignore messages sent to the cable from our * port partner if we aren't Vconn powered device. */ - if (!IS_ENABLED(CONFIG_USB_CTVPD) && - !IS_ENABLED(CONFIG_USB_VPD) && - PD_HEADER_GET_SOP(header) != PD_MSG_SOP && + if (!IS_ENABLED(CONFIG_USB_CTVPD) && !IS_ENABLED(CONFIG_USB_VPD) && + PD_HEADER_GET_SOP(header) != TCPCI_MSG_SOP && PD_HEADER_PROLE(header) == PD_PLUG_FROM_DFP_UFP) return; + /* + * From 6.2.1.1.6 Port Data Role in USB PD Rev 3.1, Ver 1.3 + * "If a USB Type-C Port receives a Message with the Port Data Role + * field set to the same Data Role as its current Data Role, except + * for the GoodCRC Message, USB Type-C Error Recovery actions as + * defined in [USB Type-C 2.0] Shall be performed." + * + * The spec lists no required state for this check, so centralize it by + * processing this requirement in the PRL RX. Because the TCPM does not + * swap data roles instantaneously, disable this check during the + * transition. + */ + if (!RCH_CHK_FLAG(port, PRL_FLAGS_IGNORE_DATA_ROLE) && + PD_HEADER_GET_SOP(header) == TCPCI_MSG_SOP && + PD_HEADER_DROLE(header) == pd_get_data_role(port)) { + CPRINTS("C%d Error: Data role mismatch (0x%08x)", port, header); + tc_start_error_recovery(port); + return; + } + /* Handle incoming soft reset as special case */ if (cnt == 0 && type == PD_CTRL_SOFT_RESET) { - int i; - - for (i = 0; i < NUM_SOP_STAR_TYPES; i++) { - /* Clear MessageIdCounter */ - prl_tx[port].msg_id_counter[i] = 0; - /* Clear stored MessageID value */ - prl_rx[port].msg_id[i] = -1; - } + /* Clear MessageIdCounter and stored MessageID value. */ + prl_reset_msg_ids(port, prl_rx[port].sop); /* Soft Reset occurred */ set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET); if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) { set_state_rch(port, - RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER); + RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER); set_state_tch(port, - TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE); + TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE); } /* @@ -2063,7 +2271,7 @@ static void prl_rx_wait_for_phy_message(const int port, int evt) * complete at the same time as a response so only do this if a * message is pending. */ - if (prl_tx_get_state(port) != PRL_TX_WAIT_FOR_PHY_RESPONSE || + if (prl_tx[port].xmit_status != TCPC_TX_COMPLETE_SUCCESS || PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) set_state_prl_tx(port, PRL_TX_DISCARD_MESSAGE); } @@ -2091,7 +2299,7 @@ static void prl_rx_wait_for_phy_message(const int port, int evt) * tch_wait_for_message_request_from_pe has been run */ else if (tch_get_state(port) != - TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE || + TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE || TCH_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) { /* NOTE: RTR_TX_CHUNKS State embedded here. */ /* @@ -2123,7 +2331,7 @@ static void prl_rx_wait_for_phy_message(const int port, int evt) } /* All necessary Protocol Transmit States (Section 6.11.2.2) */ -static const struct usb_state prl_tx_states[] = { +static __const_data const struct usb_state prl_tx_states[] = { [PRL_TX_PHY_LAYER_RESET] = { .entry = prl_tx_phy_layer_reset_entry, }, @@ -2153,6 +2361,7 @@ static const struct usb_state prl_tx_states[] = { [PRL_TX_SRC_PENDING] = { .entry = prl_tx_src_pending_entry, .run = prl_tx_src_pending_run, + .exit = prl_tx_src_pending_exit, }, [PRL_TX_SNK_PENDING] = { .entry = prl_tx_snk_pending_entry, @@ -2164,7 +2373,7 @@ static const struct usb_state prl_tx_states[] = { }; /* All necessary Protocol Hard Reset States (Section 6.11.2.4) */ -static const struct usb_state prl_hr_states[] = { +static __const_data const struct usb_state prl_hr_states[] = { [PRL_HR_WAIT_FOR_REQUEST] = { .entry = prl_hr_wait_for_request_entry, .run = prl_hr_wait_for_request_run, @@ -2176,6 +2385,7 @@ static const struct usb_state prl_hr_states[] = { [PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE] = { .entry = prl_hr_wait_for_phy_hard_reset_complete_entry, .run = prl_hr_wait_for_phy_hard_reset_complete_run, + .exit = prl_hr_wait_for_phy_hard_reset_complete_exit, }, [PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE] = { .entry = prl_hr_wait_for_pe_hard_reset_complete_entry, @@ -2184,9 +2394,9 @@ static const struct usb_state prl_hr_states[] = { }, }; -#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES /* All necessary Chunked Rx states (Section 6.11.2.1.2) */ -static const struct usb_state rch_states[] = { +__maybe_unused static const struct usb_state rch_states[] = { +#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES [RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER] = { .entry = rch_wait_for_message_from_protocol_layer_entry, .run = rch_wait_for_message_from_protocol_layer_run, @@ -2205,15 +2415,18 @@ static const struct usb_state rch_states[] = { [RCH_WAITING_CHUNK] = { .entry = rch_waiting_chunk_entry, .run = rch_waiting_chunk_run, + .exit = rch_waiting_chunk_exit, }, [RCH_REPORT_ERROR] = { .entry = rch_report_error_entry, .run = rch_report_error_run, }, +#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ }; /* All necessary Chunked Tx states (Section 6.11.2.1.3) */ -static const struct usb_state tch_states[] = { +__maybe_unused static const struct usb_state tch_states[] = { +#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES [TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE] = { .entry = tch_wait_for_message_request_from_pe_entry, .run = tch_wait_for_message_request_from_pe_run, @@ -2233,6 +2446,7 @@ static const struct usb_state tch_states[] = { [TCH_WAIT_CHUNK_REQUEST] = { .entry = tch_wait_chunk_request_entry, .run = tch_wait_chunk_request_run, + .exit = tch_wait_chunk_request_exit, }, [TCH_MESSAGE_RECEIVED] = { .entry = tch_message_received_entry, @@ -2244,8 +2458,155 @@ static const struct usb_state tch_states[] = { [TCH_REPORT_ERROR] = { .entry = tch_report_error_entry, }, -}; #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ +}; + +#ifdef CONFIG_USB_PD_PRL_EVENT_LOG +struct prl_event_log_entry { + /* + * Truncating to 32 bits still covers a time range of about an hour and + * saves 4 bytes of RAM per entry, which is significant. + */ + uint32_t timestamp; + uint16_t flags; + uint8_t port; + enum prl_event_log_state_kind kind; + union { + enum usb_prl_tx_state tx; + enum usb_prl_hr_state hr; + enum usb_rch_state rch; + enum usb_tch_state tch; + }; +}; +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT <= UINT8_MAX); + +static struct prl_event_log_entry + prl_event_log_buffer[CONFIG_USB_PD_PRL_EVENT_LOG_CAPACITY]; +static atomic_t prl_event_log_next; + +static void prl_event_log_append(enum prl_event_log_state_kind kind, int port) +{ + struct prl_event_log_entry entry = { + .timestamp = get_time().val, + .port = port, + .kind = kind, + }; + + switch (kind) { + case PRL_EVENT_LOG_STATE_TX: + entry.flags = prl_tx[port].flags; + entry.tx = prl_tx_get_state(port); + break; + case PRL_EVENT_LOG_STATE_HR: + entry.flags = prl_hr[port].flags; + entry.hr = prl_hr_get_state(port); + break; + case PRL_EVENT_LOG_STATE_RCH: + entry.flags = rch[port].flags; + entry.rch = rch_get_state(port); + break; + case PRL_EVENT_LOG_STATE_TCH: + entry.flags = tch[port].flags; + entry.tch = tch_get_state(port); + break; + case PRL_EVENT_LOG_STATE_NONE: + /* Should never be written to the log */ + return; + } + + prl_event_log_buffer[atomic_add(&prl_event_log_next, 1) % + ARRAY_SIZE(prl_event_log_buffer)] = entry; +} + +static int command_prllog(int argc, const char **argv) +{ + if (argc == 2 && strcmp("clear", argv[1]) == 0) { + /* Clear buffer contents */ + for (int i = 0; i < ARRAY_SIZE(prl_event_log_buffer); i++) { + memset(prl_event_log_buffer, 0, + sizeof(prl_event_log_buffer)); + } + return EC_SUCCESS; + } else if (argc != 1) { + return EC_ERROR_PARAM1; + } + + /* Locate the oldest entry in the buffer, to start output there. */ + unsigned int oldest_index = INT_MAX; + + for (int i = 0; i < ARRAY_SIZE(prl_event_log_buffer); i++) { + const struct prl_event_log_entry *entry = + &prl_event_log_buffer[i]; + if (entry->kind == PRL_EVENT_LOG_STATE_NONE) { + continue; + } + + if (oldest_index == INT_MAX) { + oldest_index = i; + } else if (entry->timestamp < + prl_event_log_buffer[oldest_index].timestamp) { + oldest_index = i; + /* + * Timestamps increase monotonically, so any decrease in + * time indicates we rolled over to old entries and any + * after this will always be newer. + */ + break; + } + } + if (oldest_index == INT_MAX) { + /* No valid entries in the buffer. */ + return EC_SUCCESS; + } + + /* Dump buffer contents */ + for (unsigned int i = 0; i < ARRAY_SIZE(prl_event_log_buffer); i++) { + const struct prl_event_log_entry *entry = + &prl_event_log_buffer[(oldest_index + i) % + ARRAY_SIZE(prl_event_log_buffer)]; + + if (entry->kind == PRL_EVENT_LOG_STATE_NONE) { + /* + * oldest_index refers to the oldest non-empty entry, so + * if we find an empty one later we know the buffer is + * empty past that point. + */ + break; + } + + CPRINTF("%" PRIu32 " C%d ", entry->timestamp, entry->port); + switch (entry->kind) { + case PRL_EVENT_LOG_STATE_TX: + CPRINTF("%s ", prl_tx_state_names[entry->tx]); + print_flag("PRL_TX", 1, entry->flags); + break; + case PRL_EVENT_LOG_STATE_HR: + CPRINTF("%s ", prl_hr_state_names[entry->hr]); + print_flag("PRL_HR", 1, entry->flags); + break; + case PRL_EVENT_LOG_STATE_RCH: + CPRINTF("%s ", rch_state_names[entry->rch]); + print_flag("RCH", 1, entry->flags); + break; + case PRL_EVENT_LOG_STATE_TCH: + CPRINTF("%s ", tch_state_names[entry->tch]); + print_flag("TCH", 1, entry->flags); + break; + default: + CPRINTF("unrecognized event kind\n"); + continue; + } + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(prllog, command_prllog, "[clear]", + "Dump USB-PD PRL state log"); +#else +__maybe_unused static void +prl_event_log_append(enum prl_event_log_state_kind kind, int port) +{ +} +#endif #ifdef TEST_BUILD @@ -2285,4 +2646,3 @@ BUILD_ASSERT(ARRAY_SIZE(tch_states) == ARRAY_SIZE(tch_state_names)); #endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */ const int test_prl_sm_data_size = ARRAY_SIZE(test_prl_sm_data); #endif - diff --git a/common/usbc/usb_retimer_fw_update.c b/common/usbc/usb_retimer_fw_update.c new file mode 100644 index 0000000000..a8cabf00a2 --- /dev/null +++ b/common/usbc/usb_retimer_fw_update.c @@ -0,0 +1,401 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "builtin/assert.h" +#include "compile_time_macros.h" +#include "console.h" +#include "hooks.h" +#include "timer.h" +#include "usb_common.h" +#include "usb_mux.h" +#include "usb_tc_sm.h" + +#include +#include + +#ifdef CONFIG_COMMON_RUNTIME +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#else +#define CPRINTS(format, args...) +#define CPRINTF(format, args...) +#endif + +/* + * Update retimer firmware of no device attached (NDA) ports + * + * https://docs.kernel.org/admin-guide/thunderbolt.html# + * upgrading-on-board-retimer-nvm-when-there-is-no-cable-connected + * + * On EC side: + * Retimer firmware update is initiated by AP. + * The operations requested by AP are: + * 0 - USB_RETIMER_FW_UPDATE_QUERY_PORT + * 1 - USB_RETIMER_FW_UPDATE_SUSPEND_PD + * 2 - USB_RETIMER_FW_UPDATE_RESUME_PD + * 3 - USB_RETIMER_FW_UPDATE_GET_MUX + * 4 - USB_RETIMER_FW_UPDATE_SET_USB + * 5 - USB_RETIMER_FW_UPDATE_SET_SAFE + * 6 - USB_RETIMER_FW_UPDATE_SET_TBT + * 7 - USB_RETIMER_FW_UPDATE_DISCONNECT + * + * Operation 0 is processed immediately. + * Operations 1 to 7 are deferred and processed inside tc_run(). + * Operations 1/2/3 can be processed any time; while 4/5/6/7 have + * to be processed when PD task is suspended. + * Two TC flags are created for this situation. + * If Op 1/2/3 is received, TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN + * is set, PD task will be waken up and process it. + * If 4/5/6/7 is received, TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN is + * set, PD task should be in suspended mode and process it. + * + * On host side: + * 1. Put NDA ports into offline mode. + * This forces retimer to power on, and requests EC to suspend + * PD port, set USB mux to USB, Safe then TBT. + * 2. Scan for retimers + * 3. Update retimer NVM firmware. + * 4. Authenticate. + * 5. Wait 5 or more seconds for retimer to come back. + * 6. Put NDA ports into online mode -- the functional state. + * This requestes EC to disconnect(set USB mux to 0), resume PD port. + * + * Error recovery: + * As mentioned above, to put port online, host sends two requests to EC + * 1. Disconnect USB MUX: USB_RETIMER_FW_UPDATE_DISCONNECT + * if step 1 is successful, then + * 2. Resume PD port: USB_RETIMER_FW_UPDATE_RESUME_PD + * + * If step 1 fails, host will not send step 2. This means no + * resume request from host. PD port stays in suspended state. + * EC needs an error recovery to resume PD port by itself. + * + * Below is how error recovery works: + * PD port state is set to RETIMER_ONLINE_REQUESTED when receives + * "Disconnect USB MUX"; a deferred call is set up too. When EC resumes + * port upon host's request, port state will be set to RETIMER_ONLINE; + * or port state stays RETIMER_ONLINE_REQUESTED if host doesn't request. + * By the time the deferrred call is fired, it will check if any port is + * still in RETIMER_ONLINE_REQUESTED state. If true, EC will put the + * port online by itself. That is, retry disconnect and unconditionally + * resume the port. + */ + +#define SUSPEND 1 +#define RESUME 0 + +enum retimer_port_state { + RETIMER_ONLINE, + RETIMER_OFFLINE, + RETIMER_ONLINE_REQUESTED +}; + +/* + * Two seconds buffer is added on top of required 5 seconds; + * to cover the time to disconnect and resume. + */ +#define RETIMTER_ONLINE_DELAY (7 * SECOND) + +/* Track current port AP requested to update retimer firmware */ +static int cur_port; +static int last_op; /* Operation received from AP via ACPI_WRITE */ +/* Operation result returned to ACPI_READ */ +static int last_result; +/* Track port state: SUSPEND or RESUME */ +static enum retimer_port_state port_state[CONFIG_USB_PD_PORT_MAX_COUNT]; + +int usb_retimer_fw_update_get_result(void) +{ + int result = 0; + + switch (last_op) { + case USB_RETIMER_FW_UPDATE_SUSPEND_PD: + if (last_result == USB_RETIMER_FW_UPDATE_ERR) { + result = last_result; + break; + } + __fallthrough; + case USB_RETIMER_FW_UPDATE_RESUME_PD: + result = pd_is_port_enabled(cur_port); + break; + case USB_RETIMER_FW_UPDATE_QUERY_PORT: + result = usb_mux_retimer_fw_update_port_info(); + break; + case USB_RETIMER_FW_UPDATE_GET_MUX: + case USB_RETIMER_FW_UPDATE_SET_USB: + case USB_RETIMER_FW_UPDATE_SET_SAFE: + case USB_RETIMER_FW_UPDATE_SET_TBT: + case USB_RETIMER_FW_UPDATE_DISCONNECT: + result = last_result; + break; + default: + break; + } + + return result; +} + +static void retimer_fw_update_set_port_state(int port, + enum retimer_port_state state) +{ + port_state[port] = state; +} + +static enum retimer_port_state retimer_fw_update_get_port_state(int port) +{ + return port_state[port]; +} + +/** + * @brief Suspend or resume PD task and update the state of the port. + * + * @param port PD port + * @param suspend + * SUSPEND: suspend PD task; set state to RETIMER_OFFLINE + * RESUME: resume PD task; set state to RETIMER_ONLINE. + * + */ +static void retimer_fw_update_port_handler(int port, bool suspend) +{ + pd_set_suspend(port, suspend); + retimer_fw_update_set_port_state( + port, suspend == SUSPEND ? RETIMER_OFFLINE : RETIMER_ONLINE); +} + +static void deferred_pd_suspend(void) +{ + retimer_fw_update_port_handler(cur_port, SUSPEND); +} +DECLARE_DEFERRED(deferred_pd_suspend); + +static inline mux_state_t retimer_fw_update_usb_mux_get(int port) +{ + return usb_mux_get(port) & USB_RETIMER_FW_UPDATE_MUX_MASK; +} + +/* + * Host will wait maximum 300ms for result; otherwise it's error. + * so the polling takes 300ms too. + */ +#define POLLING_CYCLE 15 +#define POLLING_TIME_MS 20 + +static bool query_usb_mux_set_completed_timeout(int port) +{ + int i; + + for (i = 0; i < POLLING_CYCLE; i++) { + if (!usb_mux_set_completed(port)) + msleep(POLLING_TIME_MS); + else + return false; + } + + return true; +} + +static void retry_online(int port) +{ + usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_DISCONNECT, + pd_get_polarity(port)); + /* Wait maximum 300 ms for USB mux to be set */ + query_usb_mux_set_completed_timeout(port); + /* Resume the port unconditionally */ + retimer_fw_update_port_handler(port, RESUME); +} + +/* + * After NVM update, if AP skips step 5, not wait 5+ seconds for retimer + * to come back; then do step 6 immediately, requesting EC to put + * retimer online. Step 6 will fail; port is still offline afterwards. + * + * This deferred function monitors if any port has this problem and retry + * online one more time. + */ +static void retimer_check_online(void) +{ + int i; + + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + if (retimer_fw_update_get_port_state(i) == + RETIMER_ONLINE_REQUESTED) { + /* + * Now the time has passed RETIMTER_ONLINE_DELAY; + * retry online. + * The port is suspended; if the port is not + * suspended, DISCONNECT request won't go through, + * we couldn't be here. + */ + retry_online(i); + /* PD port is resumed */ + } + } +} +DECLARE_DEFERRED(retimer_check_online); + +/* Allow mux results to be filled in during HOOKS if needed */ +static void last_result_mux_get(void); +DECLARE_DEFERRED(last_result_mux_get); + +static void last_result_mux_get(void) +{ + if (query_usb_mux_set_completed_timeout(cur_port)) { + last_result = USB_RETIMER_FW_UPDATE_ERR; + return; + } + + last_result = retimer_fw_update_usb_mux_get(cur_port); +} + +void usb_retimer_fw_update_process_op_cb(int port) +{ + bool result_mux_get = false; + + if (port != cur_port) { + CPRINTS("Unexpected FW op: port %d, cur %d", port, cur_port); + return; + } + + switch (last_op) { + case USB_RETIMER_FW_UPDATE_SUSPEND_PD: + last_result = 0; + /* + * Do not perform retimer firmware update process + * if battery is not present, or battery level is low. + */ + if (!pd_firmware_upgrade_check_power_readiness(port)) { + last_result = USB_RETIMER_FW_UPDATE_ERR; + break; + } + + /* + * If the port has entered low power mode, the PD task + * is paused and will not complete processing of + * pd_set_suspend(). Move pd_set_suspend() into a deferred + * call so that it runs from the HOOKS task and can generate + * a wake event to the PD task and enter suspended mode. + */ + hook_call_deferred(&deferred_pd_suspend_data, 0); + break; + case USB_RETIMER_FW_UPDATE_RESUME_PD: + retimer_fw_update_port_handler(port, RESUME); + break; + case USB_RETIMER_FW_UPDATE_GET_MUX: + result_mux_get = true; + break; + case USB_RETIMER_FW_UPDATE_SET_USB: + usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT, + pd_get_polarity(port)); + result_mux_get = true; + break; + case USB_RETIMER_FW_UPDATE_SET_SAFE: + usb_mux_set_safe_mode(port); + result_mux_get = true; + break; + case USB_RETIMER_FW_UPDATE_SET_TBT: + usb_mux_set(port, USB_PD_MUX_TBT_COMPAT_ENABLED, + USB_SWITCH_CONNECT, pd_get_polarity(port)); + result_mux_get = true; + break; + case USB_RETIMER_FW_UPDATE_DISCONNECT: + usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_DISCONNECT, + pd_get_polarity(port)); + result_mux_get = true; + /* + * Host decides to put retimer online; now disconnects USB MUX + * and sets port state to "RETIMER_ONLINE_REQUESTED". + */ + retimer_fw_update_set_port_state(port, + RETIMER_ONLINE_REQUESTED); + hook_call_deferred(&retimer_check_online_data, + RETIMTER_ONLINE_DELAY); + break; + default: + break; + } + + /* + * Fill in our mux result if available, or set up a deferred retrieval + * if the set is still pending. + */ + if (result_mux_get) + last_result_mux_get(); +} + +void usb_retimer_fw_update_process_op(int port, int op) +{ + ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); + + /* + * The order of requests from host are: + * + * Port 0 offline + * Port 0 rescan retimers + * Port 1 offline + * Port 1 rescan retimers + * ... + * Port 0 online + * Port 1 online + * ... + */ + last_op = op; + cur_port = port; + + /* + * Host has requested to put this port back online, and haven't + * finished online process. During this period, don't accept any + * requests, except USB_RETIMER_FW_UPDATE_RESUME_PD. + */ + if (port_state[port] == RETIMER_ONLINE_REQUESTED) { + if (op != USB_RETIMER_FW_UPDATE_RESUME_PD) { + last_result = USB_RETIMER_FW_UPDATE_ERR; + return; + } + } + + switch (op) { + case USB_RETIMER_FW_UPDATE_QUERY_PORT: + break; + /* Operations can't be processed in ISR, defer to later */ + case USB_RETIMER_FW_UPDATE_GET_MUX: + last_result = USB_RETIMER_FW_UPDATE_INVALID_MUX; + tc_usb_firmware_fw_update_run(port); + break; + case USB_RETIMER_FW_UPDATE_SUSPEND_PD: + case USB_RETIMER_FW_UPDATE_RESUME_PD: + tc_usb_firmware_fw_update_run(port); + break; + case USB_RETIMER_FW_UPDATE_SET_USB: + case USB_RETIMER_FW_UPDATE_SET_SAFE: + case USB_RETIMER_FW_UPDATE_SET_TBT: + case USB_RETIMER_FW_UPDATE_DISCONNECT: + if (pd_is_port_enabled(port)) { + last_result = USB_RETIMER_FW_UPDATE_ERR; + } else { + last_result = USB_RETIMER_FW_UPDATE_INVALID_MUX; + tc_usb_firmware_fw_update_limited_run(port); + } + break; + default: + break; + } +} + +/* + * If due to any reason system shuts down during firmware update, resume + * the PD port; otherwise, PD port is suspended even system powers up again. + * In normal case, system should not allow shutdown during firmware update. + */ +static void restore_port(void) +{ + int port; + + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) { + if (retimer_fw_update_get_port_state(port)) + retimer_fw_update_port_handler(port, RESUME); + } +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, restore_port, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESET, restore_port, HOOK_PRIO_DEFAULT); diff --git a/common/usbc/usb_sm.c b/common/usbc/usb_sm.c index 04b7193c0f..96b0b81e33 100644 --- a/common/usbc/usb_sm.c +++ b/common/usbc/usb_sm.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,8 +12,8 @@ #include "util.h" #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) #else /* CONFIG_COMMON_RUNTIME */ #define CPRINTF(format, args...) #define CPRINTS(format, args...) @@ -23,8 +23,8 @@ struct internal_ctx { usb_state_ptr last_entered; uint32_t running : 1; - uint32_t enter : 1; - uint32_t exit : 1; + uint32_t enter : 1; + uint32_t exit : 1; }; BUILD_ASSERT(sizeof(struct internal_ctx) == member_size(struct sm_ctx, internal)); @@ -65,9 +65,9 @@ static usb_state_ptr shared_parent_state(usb_state_ptr a, usb_state_ptr b) * functions. */ static void call_entry_functions(const int port, - struct internal_ctx *const internal, - const usb_state_ptr stop, - const usb_state_ptr current) + struct internal_ctx *const internal, + const usb_state_ptr stop, + const usb_state_ptr current) { if (current == stop) return; @@ -92,7 +92,7 @@ static void call_entry_functions(const int port, * during an exit function. */ static void call_exit_functions(const int port, const usb_state_ptr stop, - const usb_state_ptr current) + const usb_state_ptr current) { if (current == stop) return; @@ -106,7 +106,7 @@ static void call_exit_functions(const int port, const usb_state_ptr stop, void set_state(const int port, struct sm_ctx *const ctx, const usb_state_ptr new_state) { - struct internal_ctx * const internal = (void *) ctx->internal; + struct internal_ctx *const internal = (void *)ctx->internal; usb_state_ptr last_state; usb_state_ptr shared_parent; @@ -116,8 +116,8 @@ void set_state(const int port, struct sm_ctx *const ctx, * intended state to transition into. */ if (internal->exit) { - CPRINTF("C%d: Ignoring set state to 0x%pP within 0x%pP", - port, new_state, ctx->current); + CPRINTF("C%d: Ignoring set state to 0x%p within 0x%p", port, + new_state, ctx->current); return; } @@ -176,8 +176,8 @@ void set_state(const int port, struct sm_ctx *const ctx, * functions. */ static void call_run_functions(const int port, - const struct internal_ctx *const internal, - const usb_state_ptr current) + const struct internal_ctx *const internal, + const usb_state_ptr current) { if (!current) return; @@ -194,7 +194,7 @@ static void call_run_functions(const int port, void run_state(const int port, struct sm_ctx *const ctx) { - struct internal_ctx * const internal = (void *) ctx->internal; + struct internal_ctx *const internal = (void *)ctx->internal; internal->running = true; call_run_functions(port, internal, ctx->current); diff --git a/common/usbc/usb_tc_ctvpd_sm.c b/common/usbc/usb_tc_ctvpd_sm.c index f6aab7dec3..045cca55c4 100644 --- a/common/usbc/usb_tc_ctvpd_sm.c +++ b/common/usbc/usb_tc_ctvpd_sm.c @@ -1,13 +1,15 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" +#include "typec_control.h" #include "usb_pd.h" #include "usb_tc_sm.h" #include "vpd_api.h" @@ -15,18 +17,18 @@ /* USB Type-C CTVPD module */ #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else /* CONFIG_COMMON_RUNTIME */ #define CPRINTF(format, args...) #define CPRINTS(format, args...) #endif /* Type-C Layer Flags */ -#define TC_FLAGS_VCONN_ON BIT(0) +#define TC_FLAGS_VCONN_ON BIT(0) -#define SUPPORT_TIMER_RESET_INIT 0 -#define SUPPORT_TIMER_RESET_REQUEST 1 +#define SUPPORT_TIMER_RESET_INIT 0 +#define SUPPORT_TIMER_RESET_REQUEST 1 #define SUPPORT_TIMER_RESET_COMPLETE 2 /** @@ -104,10 +106,9 @@ enum usb_tc_state { /* Forward declare the full list of states. This is indexed by usb_tc_state */ static const struct usb_state tc_states[]; - -#ifdef CONFIG_COMMON_RUNTIME /* List of human readable state names for console debugging */ -const char * const tc_state_names[] = { +__maybe_unused const char *const tc_state_names[] = { +#ifdef CONFIG_COMMON_RUNTIME [TC_DISABLED] = "Disabled", [TC_UNATTACHED_SNK] = "Unattached.SNK", [TC_ATTACH_WAIT_SNK] = "AttachWait.SNK", @@ -126,8 +127,8 @@ const char * const tc_state_names[] = { [TC_CT_DISABLED_VPD] = "CTDisabled.VPD", [TC_CT_ATTACHED_VPD] = "CTAttached.VPD", [TC_CT_ATTACH_WAIT_VPD] = "CTAttachWait.VPD", -}; #endif +}; /* Forward declare private, common functions */ static void set_state_tc(const int port, enum usb_tc_state new_state); @@ -170,6 +171,17 @@ void tc_reset_support_timer(int port) tc[port].support_timer_reset |= SUPPORT_TIMER_RESET_REQUEST; } +void tc_start_error_recovery(int port) +{ + assert(port == TASK_ID_TO_PD_PORT(task_get_current())); + + /* + * The port should transition to the ErrorRecovery state + * from any other state when directed. + */ + set_state_tc(port, TC_ERROR_RECOVERY); +} + /* * TCPC CC/Rp management * @@ -245,9 +257,9 @@ test_mockable_static void print_current_state(const int port) int pd_is_connected(int port) { return (get_state_tc(port) == TC_ATTACHED_SNK) || - (get_state_tc(port) == TC_ATTACHED_SRC) || - (get_state_tc(port) == TC_CT_ATTACHED_UNSUPPORTED) || - (get_state_tc(port) == TC_CT_ATTACHED_VPD); + (get_state_tc(port) == TC_ATTACHED_SRC) || + (get_state_tc(port) == TC_CT_ATTACHED_UNSUPPORTED) || + (get_state_tc(port) == TC_CT_ATTACHED_VPD); } bool pd_is_disconnected(int port) @@ -386,7 +398,7 @@ static void tc_unattached_snk_run(const int port) * 2) VBUS is detected */ if (vpd_is_ct_vbus_present() && - tc[port].cc_state == PD_CC_DFP_ATTACHED) { + tc[port].cc_state == PD_CC_DFP_ATTACHED) { set_state_tc(port, TC_UNATTACHED_SRC); return; } @@ -424,11 +436,11 @@ static void tc_attach_wait_snk_run(const int port) if (tc[port].host_cc_state != host_new_cc_state) { tc[port].host_cc_state = host_new_cc_state; if (host_new_cc_state == PD_CC_DFP_ATTACHED) - tc[port].host_cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; + tc[port].host_cc_debounce = + get_time().val + PD_T_CC_DEBOUNCE; else - tc[port].host_cc_debounce = get_time().val + - PD_T_PD_DEBOUNCE; + tc[port].host_cc_debounce = + get_time().val + PD_T_PD_DEBOUNCE; return; } @@ -446,7 +458,7 @@ static void tc_attach_wait_snk_run(const int port) * CC2 pins is SNK.Open for at least tPDDebounce. */ if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED && - (vpd_is_vconn_present() || vpd_is_host_vbus_present())) + (vpd_is_vconn_present() || vpd_is_host_vbus_present())) set_state_tc(port, TC_ATTACHED_SNK); else if (tc[port].host_cc_state == PD_CC_NONE) set_state_tc(port, TC_UNATTACHED_SNK); @@ -461,7 +473,7 @@ static void tc_attached_snk_entry(const int port) /* Enable PD */ tc[port].pd_enable = 1; - pd_set_polarity(port, 0); + typec_set_polarity(port, 0); /* * This state can only be entered from states AttachWait.SNK @@ -539,7 +551,7 @@ static void tc_attached_snk_run(const int port) /* Check the Support Timer */ if (get_time().val > tc[port].support_timer && - !tc[port].billboard_presented) { + !tc[port].billboard_presented) { /* * Present USB Billboard Device Class interface * indicating that Charge-Through is not supported @@ -642,7 +654,7 @@ static void tc_unattached_src_run(const int port) * if Charge-Through VBUS is removed. */ if (!vpd_is_ct_vbus_present() || - get_time().val > tc[port].next_role_swap) { + get_time().val > tc[port].next_role_swap) { set_state_tc(port, TC_UNATTACHED_SNK); return; } @@ -707,7 +719,7 @@ static void tc_attach_wait_src_run(const int port) * state is on the Host-side port’s CC pin for at least tCCDebounce. */ if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED && - !vpd_is_host_vbus_present()) { + !vpd_is_host_vbus_present()) { set_state_tc(port, TC_TRY_SNK); return; } @@ -722,7 +734,7 @@ static void tc_attached_src_entry(const int port) /* Enable PD */ tc[port].pd_enable = 1; - pd_set_polarity(port, 0); + typec_set_polarity(port, 0); /* Connect Charge-Through VBUS to Host VBUS */ vpd_vbus_pass_en(1); @@ -835,7 +847,7 @@ static void tc_try_snk_run(const int port) * for tTryCCDebounce. */ if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED && - (vpd_is_host_vbus_present() || vpd_is_vconn_present())) + (vpd_is_host_vbus_present() || vpd_is_vconn_present())) set_state_tc(port, TC_ATTACHED_SNK); else if (tc[port].host_cc_state == PD_CC_NONE) set_state_tc(port, TC_TRY_WAIT_SRC); @@ -875,7 +887,7 @@ static void tc_try_wait_src_run(const int port) if (tc[port].host_cc_state != host_new_cc_state) { tc[port].host_cc_state = host_new_cc_state; tc[port].host_cc_debounce = - get_time().val + PD_T_TRY_CC_DEBOUNCE; + get_time().val + PD_T_TRY_CC_DEBOUNCE; return; } @@ -887,7 +899,7 @@ static void tc_try_wait_src_run(const int port) * at least tTryCCDebounce. */ if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED && - !vpd_is_host_vbus_present()) { + !vpd_is_host_vbus_present()) { set_state_tc(port, TC_ATTACHED_SRC); return; } @@ -922,7 +934,7 @@ static void tc_ct_try_snk_entry(const int port) /* Enable PD */ tc[port].pd_enable = 1; - pd_set_polarity(port, 0); + typec_set_polarity(port, 0); tc[port].cc_state = PD_CC_UNSET; tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY; @@ -976,7 +988,7 @@ static void tc_ct_try_snk_run(const int port) * Charge-Through port. */ if (tc[port].cc_state == PD_CC_DFP_ATTACHED && - vpd_is_ct_vbus_present()) { + vpd_is_ct_vbus_present()) { set_state_tc(port, TC_CT_ATTACHED_VPD); return; } @@ -989,8 +1001,7 @@ static void tc_ct_try_snk_run(const int port) * for tDRPTryWait. */ if (tc[port].cc_state == PD_CC_NONE) { - set_state_tc(port, - TC_CT_ATTACHED_UNSUPPORTED); + set_state_tc(port, TC_CT_ATTACHED_UNSUPPORTED); return; } } @@ -1018,7 +1029,7 @@ static void tc_ct_attach_wait_unsupported_entry(const int port) /* Enable PD */ tc[port].pd_enable = 1; - pd_set_polarity(port, 0); + typec_set_polarity(port, 0); tc[port].cc_state = PD_CC_UNSET; } @@ -1148,7 +1159,7 @@ static void tc_ct_unattached_unsupported_entry(const int port) /* Enable PD */ tc[port].pd_enable = 1; - pd_set_polarity(port, 0); + typec_set_polarity(port, 0); tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC; } @@ -1169,8 +1180,7 @@ static void tc_ct_unattached_unsupported_run(const int port) * on both the CC1 and CC2 pins. */ if (cc_is_at_least_one_rd(cc1, cc2) || cc_is_audio_acc(cc1, cc2)) { - set_state_tc(port, - TC_CT_ATTACH_WAIT_UNSUPPORTED); + set_state_tc(port, TC_CT_ATTACH_WAIT_UNSUPPORTED); return; } @@ -1216,7 +1226,7 @@ static void tc_ct_unattached_vpd_entry(const int port) /* Enable PD */ tc[port].pd_enable = 1; - pd_set_polarity(port, 0); + typec_set_polarity(port, 0); tc[port].cc_state = PD_CC_UNSET; } @@ -1331,7 +1341,7 @@ static void tc_ct_attached_vpd_entry(const int port) * pins is connected through the cable */ vpd_ct_get_cc(&cc1, &cc2); - tc[port].ct_cc = cc_is_rp(cc2) ? CT_CC2 : CT_CC1; + tc[port].ct_cc = cc_is_rp(cc2) ? CT_CC2 : CT_CC1; /* * 1. Remove or reduce any additional capacitance on the @@ -1423,7 +1433,7 @@ static void tc_ct_attach_wait_vpd_entry(const int port) /* Enable PD */ tc[port].pd_enable = 1; - pd_set_polarity(port, 0); + typec_set_polarity(port, 0); tc[port].cc_state = PD_CC_UNSET; } @@ -1456,10 +1466,8 @@ static void tc_ct_attach_wait_vpd_run(const int port) /* Debounce the cc state */ if (new_cc_state != tc[port].cc_state) { tc[port].cc_state = new_cc_state; - tc[port].cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; - tc[port].pd_debounce = get_time().val + - PD_T_PD_DEBOUNCE; + tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE; + tc[port].pd_debounce = get_time().val + PD_T_PD_DEBOUNCE; return; } @@ -1470,7 +1478,7 @@ static void tc_ct_attach_wait_vpd_run(const int port) * port’s CC1 and CC2 pins are SNK.Open for at least * tPDDebounce. */ - if (tc[port].cc_state == PD_CC_NONE) { + if (tc[port].cc_state == PD_CC_NONE) { set_state_tc(port, TC_CT_UNATTACHED_VPD); return; } @@ -1484,8 +1492,8 @@ static void tc_ct_attach_wait_vpd_run(const int port) * least tCCDebounce and VBUS on the Charge-Through port is * detected. */ - if (tc[port].cc_state == PD_CC_DFP_ATTACHED && - vpd_is_ct_vbus_present()) { + if (tc[port].cc_state == PD_CC_DFP_ATTACHED && + vpd_is_ct_vbus_present()) { set_state_tc(port, TC_CT_ATTACHED_VPD); return; } diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c index 1756f39c4a..a43a9ffa2a 100644 --- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c +++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c @@ -1,24 +1,30 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "charge_manager.h" #include "charge_state.h" #include "common.h" #include "console.h" +#include "gpio.h" #include "hooks.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" +#include "typec_control.h" #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" -#include "usb_pd_dpm.h" +#include "usb_pd_dpm_sm.h" +#include "usb_pd_tcpm.h" +#include "usb_pd_timer.h" #include "usb_pe_sm.h" #include "usb_prl_sm.h" #include "usb_sm.h" #include "usb_tc_sm.h" +#include "usbc_ocp.h" #include "usbc_ppc.h" #include "vboot.h" @@ -27,30 +33,30 @@ * See Figure 4-16 in Release 1.4 of USB Type-C Spec. */ #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else /* CONFIG_COMMON_RUNTIME */ #define CPRINTF(format, args...) #define CPRINTS(format, args...) #endif -#define CPRINTF_LX(x, format, args...) \ - do { \ - if (tc_debug_level >= x) \ - CPRINTF(format, ## args); \ +#define CPRINTF_LX(x, format, args...) \ + do { \ + if (tc_debug_level >= x) \ + CPRINTF(format, ##args); \ } while (0) -#define CPRINTF_L1(format, args...) CPRINTF_LX(1, format, ## args) -#define CPRINTF_L2(format, args...) CPRINTF_LX(2, format, ## args) -#define CPRINTF_L3(format, args...) CPRINTF_LX(3, format, ## args) - -#define CPRINTS_LX(x, format, args...) \ - do { \ - if (tc_debug_level >= x) \ - CPRINTS(format, ## args); \ +#define CPRINTF_L1(format, args...) CPRINTF_LX(1, format, ##args) +#define CPRINTF_L2(format, args...) CPRINTF_LX(2, format, ##args) +#define CPRINTF_L3(format, args...) CPRINTF_LX(3, format, ##args) + +#define CPRINTS_LX(x, format, args...) \ + do { \ + if (tc_debug_level >= x) \ + CPRINTS(format, ##args); \ } while (0) -#define CPRINTS_L1(format, args...) CPRINTS_LX(1, format, ## args) -#define CPRINTS_L2(format, args...) CPRINTS_LX(2, format, ## args) -#define CPRINTS_L3(format, args...) CPRINTS_LX(3, format, ## args) +#define CPRINTS_L1(format, args...) CPRINTS_LX(1, format, ##args) +#define CPRINTS_L2(format, args...) CPRINTS_LX(2, format, ##args) +#define CPRINTS_L3(format, args...) CPRINTS_LX(3, format, ##args) /* * Define DEBUG_PRINT_FLAG_AND_EVENT_NAMES to print flag names when set and @@ -59,78 +65,85 @@ #undef DEBUG_PRINT_FLAG_AND_EVENT_NAMES #ifdef DEBUG_PRINT_FLAG_AND_EVENT_NAMES -void print_flag(int set_or_clear, int flag); -#define TC_SET_FLAG(port, flag) \ - do { \ - print_flag(1, flag); \ - deprecated_atomic_or(&tc[port].flags, (flag)); \ +void print_flag(int port, int set_or_clear, int flag); +#define TC_SET_FLAG(port, flag) \ + do { \ + print_flag(port, 1, flag); \ + atomic_or(&tc[port].flags, (flag)); \ } while (0) -#define TC_CLR_FLAG(port, flag) \ - do { \ - print_flag(0, flag); \ - deprecated_atomic_clear_bits(&tc[port].flags, (flag)); \ +#define TC_CLR_FLAG(port, flag) \ + do { \ + print_flag(port, 0, flag); \ + atomic_clear_bits(&tc[port].flags, (flag)); \ } while (0) #else -#define TC_SET_FLAG(port, flag) deprecated_atomic_or(&tc[port].flags, (flag)) -#define TC_CLR_FLAG(port, flag) \ - deprecated_atomic_clear_bits(&tc[port].flags, (flag)) +#define TC_SET_FLAG(port, flag) atomic_or(&tc[port].flags, (flag)) +#define TC_CLR_FLAG(port, flag) atomic_clear_bits(&tc[port].flags, (flag)) #endif #define TC_CHK_FLAG(port, flag) (tc[port].flags & (flag)) /* Type-C Layer Flags */ /* Flag to note we are sourcing VCONN */ -#define TC_FLAGS_VCONN_ON BIT(0) +#define TC_FLAGS_VCONN_ON BIT(0) /* Flag to note port partner has Rp/Rp or Rd/Rd */ -#define TC_FLAGS_TS_DTS_PARTNER BIT(1) +#define TC_FLAGS_TS_DTS_PARTNER BIT(1) /* Flag to note VBus input has never been low */ -#define TC_FLAGS_VBUS_NEVER_LOW BIT(2) +#define TC_FLAGS_VBUS_NEVER_LOW BIT(2) /* Flag to note Low Power Mode transition is currently happening */ -#define TC_FLAGS_LPM_TRANSITION BIT(3) +#define TC_FLAGS_LPM_TRANSITION BIT(3) /* Flag to note Low Power Mode is currently on */ -#define TC_FLAGS_LPM_ENGAGED BIT(4) +#define TC_FLAGS_LPM_ENGAGED BIT(4) /* Flag to note CVTPD has been detected */ -#define TC_FLAGS_CTVPD_DETECTED BIT(5) +#define TC_FLAGS_CTVPD_DETECTED BIT(5) /* Flag to note request to swap to VCONN on */ -#define TC_FLAGS_REQUEST_VC_SWAP_ON BIT(6) +#define TC_FLAGS_REQUEST_VC_SWAP_ON BIT(6) /* Flag to note request to swap to VCONN off */ -#define TC_FLAGS_REQUEST_VC_SWAP_OFF BIT(7) +#define TC_FLAGS_REQUEST_VC_SWAP_OFF BIT(7) /* Flag to note request to swap VCONN is being rejected */ -#define TC_FLAGS_REJECT_VCONN_SWAP BIT(8) +#define TC_FLAGS_REJECT_VCONN_SWAP BIT(8) /* Flag to note request to power role swap */ -#define TC_FLAGS_REQUEST_PR_SWAP BIT(9) +#define TC_FLAGS_REQUEST_PR_SWAP BIT(9) /* Flag to note request to data role swap */ -#define TC_FLAGS_REQUEST_DR_SWAP BIT(10) +#define TC_FLAGS_REQUEST_DR_SWAP BIT(10) /* Flag to note request to power off sink */ -#define TC_FLAGS_POWER_OFF_SNK BIT(11) -/* Flag to note port partner has unconstrained power */ -#define TC_FLAGS_PARTNER_UNCONSTRAINED BIT(12) -/* Flag to note port partner is Dual Role Data */ -#define TC_FLAGS_PARTNER_DR_DATA BIT(13) -/* Flag to note port partner is Dual Role Power */ -#define TC_FLAGS_PARTNER_DR_POWER BIT(14) +#define TC_FLAGS_POWER_OFF_SNK BIT(11) /* Flag to note port partner is Power Delivery capable */ -#define TC_FLAGS_PARTNER_PD_CAPABLE BIT(15) +#define TC_FLAGS_PARTNER_PD_CAPABLE BIT(12) /* Flag to note hard reset has been requested */ -#define TC_FLAGS_HARD_RESET_REQUESTED BIT(16) -/* Flag to note port partner is USB comms capable */ -#define TC_FLAGS_PARTNER_USB_COMM BIT(17) +#define TC_FLAGS_HARD_RESET_REQUESTED BIT(13) /* Flag to note we are currently performing PR Swap */ -#define TC_FLAGS_PR_SWAP_IN_PROGRESS BIT(18) -/* Flag to note we are performing Discover Identity */ -#define TC_FLAGS_DISC_IDENT_IN_PROGRESS BIT(19) +#define TC_FLAGS_PR_SWAP_IN_PROGRESS BIT(14) /* Flag to note we should check for connection */ -#define TC_FLAGS_CHECK_CONNECTION BIT(20) -/* Flag to note pd_set_suspend SUSPEND state */ -#define TC_FLAGS_SUSPEND BIT(21) +#define TC_FLAGS_CHECK_CONNECTION BIT(15) +/* Flag to note request from pd_set_suspend to enter TC_DISABLED state */ +#define TC_FLAGS_REQUEST_SUSPEND BIT(16) +/* Flag to note we are in TC_DISABLED state */ +#define TC_FLAGS_SUSPENDED BIT(17) +/* Flag to indicate the port current limit has changed */ +#define TC_FLAGS_UPDATE_CURRENT BIT(18) +/* Flag to indicate USB mux should be updated */ +#define TC_FLAGS_UPDATE_USB_MUX BIT(19) +/* Flag for retimer firmware update */ +#define TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN BIT(20) +#define TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN BIT(21) +/* Flag for asynchronous call to request Error Recovery */ +#define TC_FLAGS_REQUEST_ERROR_RECOVERY BIT(22) + +/* For checking flag_bit_names[] array */ +#define TC_FLAGS_COUNT 23 + +/* On disconnect, clear most of the flags. */ +#define CLR_FLAGS_ON_DISCONNECT(port) \ + TC_CLR_FLAG(port, ~(TC_FLAGS_LPM_ENGAGED | TC_FLAGS_REQUEST_SUSPEND | \ + TC_FLAGS_SUSPENDED)) /* - * Clear all flags except TC_FLAGS_LPM_ENGAGED and TC_FLAGS_SUSPEND. + * 10 ms is enough time for any TCPC transaction to complete + * + * This value must be below ~39.7 ms to put ANX7447 into LPM due to bug in + * silicon (see b/77544959 and b/149761477 for more details). */ -#define CLR_ALL_BUT_LPM_FLAGS(port) TC_CLR_FLAG(port, \ - ~(TC_FLAGS_LPM_ENGAGED | TC_FLAGS_SUSPEND)) - -/* 100 ms is enough time for any TCPC transaction to complete. */ -#define PD_LPM_DEBOUNCE_US (100 * MSEC) +#define PD_LPM_DEBOUNCE_US (10 * MSEC) /* * This delay is not part of the USB Type-C specification or the USB port @@ -142,20 +155,27 @@ void print_flag(int set_or_clear, int flag); * * TODO(b/162347811): TCPMv2: Wait for debounce on Vbus and CC lines */ +#ifdef CONFIG_USB_PD_TCPC_LOW_POWER #define PD_LPM_EXIT_DEBOUNCE_US CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE +#else +/* + * Define this value regardless so it is not missing at compile time. + */ +#define PD_LPM_EXIT_DEBOUNCE_US 0 +#endif /* * The TypeC state machine uses this bit to disable/enable PD * This bit corresponds to bit-0 of pd_disabled_mask */ -#define PD_DISABLED_NO_CONNECTION BIT(0) +#define PD_DISABLED_NO_CONNECTION BIT(0) /* * Console and Host commands use this bit to override the * PD_DISABLED_NO_CONNECTION bit that was set by the TypeC * state machine. * This bit corresponds to bit-1 of pd_disabled_mask */ -#define PD_DISABLED_BY_POLICY BIT(1) +#define PD_DISABLED_BY_POLICY BIT(1) /* Unreachable time in future */ #define TIMER_DISABLED 0xffffffffffffffff @@ -187,6 +207,8 @@ enum usb_tc_state { TC_LOW_POWER_MODE, TC_CT_UNATTACHED_SNK, TC_CT_ATTACHED_SNK, + + TC_STATE_COUNT, }; /* Forward declare the full list of states. This is indexed by usb_tc_state */ static const struct usb_state tc_states[]; @@ -212,6 +234,16 @@ GEN_NOT_SUPPORTED(TC_CT_ATTACHED_SNK); #define TC_CT_ATTACHED_SNK TC_CT_ATTACHED_SNK_NOT_SUPPORTED #endif /* CONFIG_USB_PE_SM */ +/* + * If CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT is not defined then + * _GPIO_CCD_MODE_ODL is not needed. Declare as extern so IS_ENABLED will work. + */ +#ifndef CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT +extern int _GPIO_CCD_MODE_ODL; +#else +#define _GPIO_CCD_MODE_ODL GPIO_CCD_MODE_ODL +#endif /* CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT */ + /* * We will use DEBUG LABELS if we will be able to print (COMMON RUNTIME) * and either CONFIG_USB_PD_DEBUG_LEVEL is not defined (no override) or @@ -220,9 +252,8 @@ GEN_NOT_SUPPORTED(TC_CT_ATTACHED_SNK); * If we can't print or the CONFIG_USB_PD_DEBUG_LEVEL is defined to be 0 * then the DEBUG LABELS will be removed from the build. */ -#if defined(CONFIG_COMMON_RUNTIME) && \ - (!defined(CONFIG_USB_PD_DEBUG_LEVEL) || \ - (CONFIG_USB_PD_DEBUG_LEVEL > 0)) +#if defined(CONFIG_COMMON_RUNTIME) && (!defined(CONFIG_USB_PD_DEBUG_LEVEL) || \ + (CONFIG_USB_PD_DEBUG_LEVEL > 0)) #define USB_PD_DEBUG_LABELS #endif @@ -238,10 +269,9 @@ GEN_NOT_SUPPORTED(TC_CT_ATTACHED_SNK); */ #define IS_ATTACHED_SNK(port) (get_state_tc(port) == TC_ATTACHED_SNK) - -#ifdef USB_PD_DEBUG_LABELS /* List of human readable state names for console debugging */ -static const char * const tc_state_names[] = { +__maybe_unused static __const_data const char *const tc_state_names[] = { +#ifdef USB_PD_DEBUG_LABELS [TC_DISABLED] = "Disabled", [TC_ERROR_RECOVERY] = "ErrorRecovery", [TC_UNATTACHED_SNK] = "Unattached.SNK", @@ -259,33 +289,31 @@ static const char * const tc_state_names[] = { [TC_LOW_POWER_MODE] = "LowPowerMode", #endif #ifdef CONFIG_USB_PE_SM - [TC_CT_UNATTACHED_SNK] = "CTUnattached.SNK", + [TC_CT_UNATTACHED_SNK] = "CTUnattached.SNK", [TC_CT_ATTACHED_SNK] = "CTAttached.SNK", #endif /* Super States */ [TC_CC_OPEN] = "SS:CC_OPEN", [TC_CC_RD] = "SS:CC_RD", [TC_CC_RP] = "SS:CC_RP", -}; -#else -/* - * Reference so IS_ENABLED section below that references the names - * will compile and the optimizer will remove it. - */ -extern const char **tc_state_names; + + [TC_STATE_COUNT] = "", #endif +}; /* Debug log level - higher number == more log */ #ifdef CONFIG_USB_PD_DEBUG_LEVEL static const enum debug_level tc_debug_level = CONFIG_USB_PD_DEBUG_LEVEL; +#elif defined(CONFIG_USB_PD_INITIAL_DEBUG_LEVEL) +static enum debug_level tc_debug_level = CONFIG_USB_PD_INITIAL_DEBUG_LEVEL; #else static enum debug_level tc_debug_level = DEBUG_LEVEL_1; #endif #ifdef DEBUG_PRINT_FLAG_AND_EVENT_NAMES struct bit_name { - int value; - const char *name; + int value; + const char *name; }; static struct bit_name flag_bit_names[] = { @@ -301,17 +329,20 @@ static struct bit_name flag_bit_names[] = { { TC_FLAGS_REQUEST_PR_SWAP, "REQUEST_PR_SWAP" }, { TC_FLAGS_REQUEST_DR_SWAP, "REQUEST_DR_SWAP" }, { TC_FLAGS_POWER_OFF_SNK, "POWER_OFF_SNK" }, - { TC_FLAGS_PARTNER_UNCONSTRAINED, "PARTNER_UNCONSTRAINED" }, - { TC_FLAGS_PARTNER_DR_DATA, "PARTNER_DR_DATA" }, - { TC_FLAGS_PARTNER_DR_POWER, "PARTNER_DR_POWER" }, { TC_FLAGS_PARTNER_PD_CAPABLE, "PARTNER_PD_CAPABLE" }, { TC_FLAGS_HARD_RESET_REQUESTED, "HARD_RESET_REQUESTED" }, - { TC_FLAGS_PARTNER_USB_COMM, "PARTNER_USB_COMM" }, { TC_FLAGS_PR_SWAP_IN_PROGRESS, "PR_SWAP_IN_PROGRESS" }, - { TC_FLAGS_DISC_IDENT_IN_PROGRESS, "DISC_IDENT_IN_PROGRESS" }, { TC_FLAGS_CHECK_CONNECTION, "CHECK_CONNECTION" }, - { TC_FLAGS_SUSPEND, "SUSPEND" }, + { TC_FLAGS_REQUEST_SUSPEND, "REQUEST_SUSPEND" }, + { TC_FLAGS_SUSPENDED, "SUSPENDED" }, + { TC_FLAGS_UPDATE_CURRENT, "UPDATE_CURRENT" }, + { TC_FLAGS_UPDATE_USB_MUX, "UPDATE_USB_MUX" }, + { TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN, "USB_RETIMER_FW_UPDATE_RUN" }, + { TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN, + "USB_RETIMER_FW_UPDATE_LTD_RUN" }, + { TC_FLAGS_REQUEST_ERROR_RECOVERY, "REQUEST_ERROR_RECOCVERY" }, }; +BUILD_ASSERT(ARRAY_SIZE(flag_bit_names) == TC_FLAGS_COUNT); static struct bit_name event_bit_names[] = { { TASK_EVENT_SYSJUMP_READY, "SYSJUMP_READY" }, @@ -319,7 +350,9 @@ static struct bit_name event_bit_names[] = { { TASK_EVENT_PD_AWAKE, "PD_AWAKE" }, { TASK_EVENT_PECI_DONE, "PECI_DONE" }, { TASK_EVENT_I2C_IDLE, "I2C_IDLE" }, +#ifdef TASK_EVENT_PS2_DONE { TASK_EVENT_PS2_DONE, "PS2_DONE" }, +#endif { TASK_EVENT_DMA_TC, "DMA_TC" }, { TASK_EVENT_ADC_DONE, "ADC_DONE" }, { TASK_EVENT_RESET_DONE, "RESET_DONE" }, @@ -336,12 +369,12 @@ static struct bit_name event_bit_names[] = { { PD_EVENT_SYSJUMP, "SYSJUMP" }, }; -static void print_bits(const char *desc, int value, +static void print_bits(int port, const char *desc, int value, struct bit_name *names, int names_size) { int i; - CPRINTF("%s 0x%x : ", desc, value); + CPRINTF("C%d: %s 0x%x : ", port, desc, value); for (i = 0; i < names_size; i++) { if (value & names[i].value) CPRINTF("%s | ", names[i].name); @@ -352,17 +385,18 @@ static void print_bits(const char *desc, int value, CPRINTF("\n"); } -void print_flag(int set_or_clear, int flag) +void print_flag(int port, int set_or_clear, int flag) { - print_bits(set_or_clear ? "Set" : "Clr", flag, flag_bit_names, + print_bits(port, set_or_clear ? "Set" : "Clr", flag, flag_bit_names, ARRAY_SIZE(flag_bit_names)); } #endif /* DEBUG_PRINT_FLAG_AND_EVENT_NAMES */ -/* Generate a compiler error if invalid states are referenced */ #ifndef CONFIG_USB_PD_TRY_SRC -#define TC_TRY_SRC TC_TRY_SRC_UNDEFINED -#define TC_TRY_WAIT_SNK TC_TRY_WAIT_SNK_UNDEFINED +extern int TC_TRY_SRC_UNDEFINED; +extern int TC_TRY_WAIT_SNK_UNDEFINED; +#define TC_TRY_SRC TC_TRY_SRC_UNDEFINED +#define TC_TRY_WAIT_SNK TC_TRY_WAIT_SNK_UNDEFINED #endif static struct type_c { @@ -377,7 +411,7 @@ static struct type_c { * else they're disabled if bits PD_DISABLED_NO_CONNECTION or * PD_DISABLED_BY_POLICY are set. */ - uint32_t pd_disabled_mask; + atomic_t pd_disabled_mask; /* * Timer for handling TOGGLE_OFF/FORCE_SINK mode when auto-toggle * enabled. See drp_auto_toggle_next_state() for details. @@ -390,41 +424,13 @@ static struct type_c { /* Port polarity */ enum tcpc_cc_polarity polarity; /* port flags, see TC_FLAGS_* */ - uint32_t flags; - /* Time a port shall wait before it can determine it is attached */ - uint64_t cc_debounce; - /* - * Time a Sink port shall wait before it can determine it is detached - * due to the potential for USB PD signaling on CC as described in - * the state definitions. - */ - uint64_t pd_debounce; - /* - * Time to ignore Vbus absence due to external IC debounce detection - * logic immediately after a power role swap. - */ - uint64_t vbus_debounce_time; -#ifdef CONFIG_USB_PD_TRY_SRC - /* - * Time a port shall wait before it can determine it is - * re-attached during the try-wait process. - */ - uint64_t try_wait_debounce; -#endif + atomic_t flags; /* The cc state */ enum pd_cc_states cc_state; - /* Role toggle timer */ - uint64_t next_role_swap; - /* Generic timer */ - uint64_t timeout; - /* Time to enter low power mode */ - uint64_t low_power_time; - /* Time to debounce exit low power mode */ - uint64_t low_power_exit_time; /* Tasks to notify after TCPC has been reset */ - int tasks_waiting_on_reset; + atomic_t tasks_waiting_on_reset; /* Tasks preventing TCPC from entering low power mode */ - int tasks_preventing_lpm; + atomic_t tasks_preventing_lpm; /* Voltage on CC pin */ enum tcpc_cc_voltage_status cc_voltage; /* Type-C current */ @@ -439,10 +445,11 @@ static struct type_c { } tc[CONFIG_USB_PD_PORT_MAX_COUNT]; /* Port dual-role state */ -static volatile __maybe_unused -enum pd_dual_role_states drp_state[CONFIG_USB_PD_PORT_MAX_COUNT] = { - [0 ... (CONFIG_USB_PD_PORT_MAX_COUNT - 1)] = - CONFIG_USB_PD_INITIAL_DRP_STATE}; +static volatile __maybe_unused enum pd_dual_role_states + drp_state[CONFIG_USB_PD_PORT_MAX_COUNT] = { + [0 ...(CONFIG_USB_PD_PORT_MAX_COUNT - 1)] = + CONFIG_USB_PD_INITIAL_DRP_STATE + }; static void set_vconn(int port, int enable); @@ -450,10 +457,9 @@ static void set_vconn(int port, int enable); static __maybe_unused int reset_device_and_notify(int port); static __maybe_unused void check_drp_connection(const int port); static void sink_power_sub_states(int port); +static void set_ccd_mode(int port, bool enable); -#ifdef CONFIG_POWER_COMMON -static void handle_new_power_state(int port); -#endif /* CONFIG_POWER_COMMON */ +__maybe_unused static void handle_new_power_state(int port); static void pd_update_dual_role_config(int port); @@ -461,19 +467,19 @@ static void pd_update_dual_role_config(int port); static void set_state_tc(const int port, const enum usb_tc_state new_state); test_export_static enum usb_tc_state get_state_tc(const int port); -#ifdef CONFIG_USB_PD_TRY_SRC /* Enable variable for Try.SRC states */ -static uint32_t pd_try_src; +static atomic_t pd_try_src; static volatile enum try_src_override_t pd_try_src_override; static void pd_update_try_source(void); -#endif static void sink_stop_drawing_current(int port); -static bool is_try_src_enabled(int port) +__maybe_unused static bool is_try_src_enabled(int port) { - return IS_ENABLED(CONFIG_USB_PD_TRY_SRC) && - ((pd_try_src_override == TRY_SRC_OVERRIDE_ON) || + if (!IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) + assert(0); + + return ((pd_try_src_override == TRY_SRC_OVERRIDE_ON) || (pd_try_src_override == TRY_SRC_NO_OVERRIDE && pd_try_src)); } @@ -500,18 +506,60 @@ void pd_execute_hard_reset(int port) /* DO NOTHING */ } -void pd_set_vbus_discharge(int port, int enable) +__overridable void pd_set_vbus_discharge(int port, int enable) { /* DO NOTHING */ } -uint16_t pd_get_identity_vid(int port) +#endif /* !CONFIG_USB_PRL_SM */ + +#ifndef CONFIG_USB_PE_SM + +/* + * These pd_ functions are implemented in the PE layer + */ +const uint32_t *const pd_get_src_caps(int port) +{ + return NULL; +} + +uint8_t pd_get_src_cap_cnt(int port) { - /* DO NOTHING */ return 0; } -#endif /* !CONFIG_USB_PRL_SM */ +const uint32_t *const pd_get_snk_caps(int port) +{ + return NULL; +} + +uint8_t pd_get_snk_cap_cnt(int port) +{ + return 0; +} + +void pd_set_src_caps(int port, int cnt, uint32_t *src_caps) +{ +} + +int pd_get_rev(int port, enum tcpci_msg_type type) +{ + return PD_REV30; +} + +#endif /* !CONFIG_USB_PR_SM */ + +#ifndef CONFIG_AP_POWER_CONTROL +__overridable enum pd_dual_role_states board_tc_get_initial_drp_mode(int port) +{ + /* + * DRP state is typically adjusted as the chipset state is changed. For + * projects which don't include an AP this function can be used for to + * specify what the starting DRP state should be. + */ + return PD_DRP_FORCE_SINK; +} +#endif void pd_update_contract(int port) { @@ -567,7 +615,7 @@ void tc_request_power_swap(int port) TC_SET_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS); /* Let tc_pr_swap_complete start the Vbus debounce */ - tc[port].vbus_debounce_time = TIMER_DISABLED; + pd_timer_disable(port, TC_TIMER_VBUS_DEBOUNCE); } /* @@ -584,6 +632,26 @@ void tc_request_power_swap(int port) } } +/* Flag to indicate PD comm is disabled on init */ +static int pd_disabled_on_init; + +static void pd_update_pd_comm(void) +{ + int i; + + /* + * Some batteries take much longer time to report its SOC. + * The init function disabled PD comm on startup. Need this + * hook to enable PD comm when the battery level is enough. + */ + if (pd_disabled_on_init && pd_is_battery_capable()) { + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + pd_comm_enable(i, 1); + pd_disabled_on_init = 0; + } +} +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_pd_comm, HOOK_PRIO_DEFAULT); + static bool pd_comm_allowed_by_policy(void) { if (system_is_in_rw()) @@ -597,10 +665,15 @@ static bool pd_comm_allowed_by_policy(void) * when sysjump to RW that makes the device brownout on the dead-battery * case. Disable PD for this special case as a workaround. */ - if (IS_ENABLED(CONFIG_SYSTEM_UNLOCKED) && - (IS_ENABLED(CONFIG_VBOOT_EFS2) || - usb_get_battery_soc() >= CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC)) - return true; + if (!system_is_locked()) { + if (IS_ENABLED(CONFIG_VBOOT_EFS2)) + return true; + + if (pd_is_battery_capable()) + return true; + + pd_disabled_on_init = 1; + } return false; } @@ -608,11 +681,10 @@ static bool pd_comm_allowed_by_policy(void) static void tc_policy_pd_enable(int port, int en) { if (en) - deprecated_atomic_clear_bits(&tc[port].pd_disabled_mask, - PD_DISABLED_BY_POLICY); + atomic_clear_bits(&tc[port].pd_disabled_mask, + PD_DISABLED_BY_POLICY); else - deprecated_atomic_or(&tc[port].pd_disabled_mask, - PD_DISABLED_BY_POLICY); + atomic_or(&tc[port].pd_disabled_mask, PD_DISABLED_BY_POLICY); CPRINTS("C%d: PD comm policy %sabled", port, en ? "en" : "dis"); } @@ -620,31 +692,62 @@ static void tc_policy_pd_enable(int port, int en) static void tc_enable_pd(int port, int en) { if (en) - deprecated_atomic_clear_bits(&tc[port].pd_disabled_mask, - PD_DISABLED_NO_CONNECTION); + atomic_clear_bits(&tc[port].pd_disabled_mask, + PD_DISABLED_NO_CONNECTION); else - deprecated_atomic_or(&tc[port].pd_disabled_mask, - PD_DISABLED_NO_CONNECTION); + atomic_or(&tc[port].pd_disabled_mask, + PD_DISABLED_NO_CONNECTION); } -static void tc_enable_try_src(int en) +__maybe_unused static void tc_enable_try_src(int en) { + if (!IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) + assert(0); + if (en) - deprecated_atomic_or(&pd_try_src, 1); + atomic_or(&pd_try_src, 1); else - deprecated_atomic_clear_bits(&pd_try_src, 1); + atomic_clear_bits(&pd_try_src, 1); +} + +/* + * Exit all modes due to a detach event or hard reset + * + * Note: this skips the ExitMode VDM steps in the PE because it is assumed the + * partner is not present to receive them, and the PE will no longer be running, + * or we've forced an abrupt mode exit through a hard reset. + */ +static void tc_set_modes_exit(int port) +{ + if (IS_ENABLED(CONFIG_USB_PE_SM) && + IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { + pd_dfp_exit_mode(port, TCPCI_MSG_SOP, 0, 0); + pd_dfp_exit_mode(port, TCPCI_MSG_SOP_PRIME, 0, 0); + pd_dfp_exit_mode(port, TCPCI_MSG_SOP_PRIME_PRIME, 0, 0); + } } static void tc_detached(int port) { TC_CLR_FLAG(port, TC_FLAGS_TS_DTS_PARTNER); hook_notify(HOOK_USB_PD_DISCONNECT); + tc_enable_pd(port, 0); tc_pd_connection(port, 0); tcpm_debug_accessory(port, 0); + set_ccd_mode(port, 0); + tc_set_modes_exit(port); + if (IS_ENABLED(CONFIG_USB_PRL_SM)) + prl_set_default_pd_revision(port); + + /* Clear any mux connection on detach */ + if (IS_ENABLED(CONFIG_USBC_SS_MUX)) + usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_DISCONNECT, + tc[port].polarity); } static inline void pd_set_dual_role_and_event(int port, - enum pd_dual_role_states state, uint32_t event) + enum pd_dual_role_states state, + uint32_t event) { drp_state[port] = state; @@ -652,7 +755,7 @@ static inline void pd_set_dual_role_and_event(int port, pd_update_try_source(); if (event != 0) - task_set_event(PD_PORT_TO_TASK_ID(port), event, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), event); } void pd_set_dual_role(int port, enum pd_dual_role_states state) @@ -660,12 +763,6 @@ void pd_set_dual_role(int port, enum pd_dual_role_states state) pd_set_dual_role_and_event(port, state, PD_EVENT_UPDATE_DUAL_ROLE); } -bool pd_get_partner_data_swap_capable(int port) -{ - /* return data swap capable status of port partner */ - return !!TC_CHK_FLAG(port, TC_FLAGS_PARTNER_DR_DATA); -} - int pd_comm_is_enabled(int port) { return tc_get_pd_enabled(port); @@ -684,15 +781,6 @@ void pd_request_data_swap(int port) } } -/* - * Return true if partner port is a DTS or TS capable of entering debug - * mode (eg. is presenting Rp/Rp or Rd/Rd). - */ -int pd_ts_dts_plugged(int port) -{ - return TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER); -} - /* Return true if partner port is known to be PD capable. */ bool pd_capable(int port) { @@ -700,12 +788,13 @@ bool pd_capable(int port) } /* - * Return true if partner port is capable of communication over USB data - * lines. + * Return true if we transition through Unattached.SNK, but we're still waiting + * to receive source caps from the partner. This indicates that the PD + * capabilities are not yet known. */ -bool pd_get_partner_usb_comm_capable(int port) +bool pd_waiting_on_partner_src_caps(int port) { - return !!TC_CHK_FLAG(port, TC_FLAGS_PARTNER_USB_COMM); + return !pd_get_src_cap_cnt(port); } enum pd_dual_role_states pd_get_dual_role(int port) @@ -713,19 +802,6 @@ enum pd_dual_role_states pd_get_dual_role(int port) return drp_state[port]; } -#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO -static inline void pd_dev_dump_info(uint16_t dev_id, uint32_t *hash) -{ - int j; - - ccprintf("DevId:%d.%d Hash:", HW_DEV_ID_MAJ(dev_id), - HW_DEV_ID_MIN(dev_id)); - for (j = 0; j < PD_RW_HASH_SIZE / 4; j++) - ccprintf(" %08x ", hash[i]); - ccprintf("\n"); -} -#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */ - const char *tc_get_current_state(int port) { if (IS_ENABLED(USB_PD_DEBUG_LABELS)) @@ -749,52 +825,41 @@ int tc_is_attached_snk(int port) return IS_ATTACHED_SNK(port); } -void tc_partner_dr_power(int port, int en) +__overridable void tc_update_pd_sleep_mask(int port) { - if (en) - TC_SET_FLAG(port, TC_FLAGS_PARTNER_DR_POWER); - else - TC_CLR_FLAG(port, TC_FLAGS_PARTNER_DR_POWER); -} - -void tc_partner_unconstrainedpower(int port, int en) -{ - if (en) - TC_SET_FLAG(port, TC_FLAGS_PARTNER_UNCONSTRAINED); - else - TC_CLR_FLAG(port, TC_FLAGS_PARTNER_UNCONSTRAINED); -} - -void tc_partner_usb_comm(int port, int en) -{ - if (en) - TC_SET_FLAG(port, TC_FLAGS_PARTNER_USB_COMM); - else - TC_CLR_FLAG(port, TC_FLAGS_PARTNER_USB_COMM); -} - -void tc_partner_dr_data(int port, int en) -{ - if (en) - TC_SET_FLAG(port, TC_FLAGS_PARTNER_DR_DATA); - else - TC_CLR_FLAG(port, TC_FLAGS_PARTNER_DR_DATA); } void tc_pd_connection(int port, int en) { if (en) { + bool new_pd_capable = false; + + if (!TC_CHK_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE)) + new_pd_capable = true; + TC_SET_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE); /* If a PD device is attached then disable deep sleep */ if (IS_ENABLED(CONFIG_LOW_POWER_IDLE) && - !IS_ENABLED(CONFIG_USB_PD_TCPC_ON_CHIP)) { + IS_ENABLED(CONFIG_USB_PD_TCPC_ON_CHIP)) + tc_update_pd_sleep_mask(port); + else if (IS_ENABLED(CONFIG_LOW_POWER_IDLE)) disable_sleep(SLEEP_MASK_USB_PD); - } + + /* + * Update the mux state, only when the PD capable flag + * transitions from 0 to 1. This ensures that PD charger + * devices, without data capability are not marked as having + * USB. + */ + if (new_pd_capable) + set_usb_mux_with_current_data_role(port); } else { TC_CLR_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE); /* If a PD device isn't attached then enable deep sleep */ if (IS_ENABLED(CONFIG_LOW_POWER_IDLE) && - !IS_ENABLED(CONFIG_USB_PD_TCPC_ON_CHIP)) { + IS_ENABLED(CONFIG_USB_PD_TCPC_ON_CHIP)) + tc_update_pd_sleep_mask(port); + else if (IS_ENABLED(CONFIG_LOW_POWER_IDLE)) { int i; /* If all ports are not connected, allow the sleep */ @@ -820,14 +885,13 @@ void pd_try_vconn_src(int port) int tc_check_vconn_swap(int port) { -#ifdef CONFIG_USBC_VCONN - if (TC_CHK_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP)) - return 0; + if (IS_ENABLED(CONFIG_USBC_VCONN)) { + if (TC_CHK_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP)) + return 0; - return pd_check_vconn_swap(port); -#else - return 0; -#endif + return pd_check_vconn_swap(port); + } else + return 0; } void tc_pr_swap_complete(int port, bool success) @@ -841,7 +905,7 @@ void tc_pr_swap_complete(int port, bool success) * Note: Swap in progress should not be cleared until the * debounce is completed. */ - tc[port].vbus_debounce_time = get_time().val + PD_T_DEBOUNCE; + pd_timer_enable(port, TC_TIMER_VBUS_DEBOUNCE, PD_T_DEBOUNCE); } else { /* PR Swap is no longer in progress */ TC_CLR_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS); @@ -908,18 +972,11 @@ void tc_hard_reset_request(int port) task_wake(PD_PORT_TO_TASK_ID(port)); } -void tc_disc_ident_in_progress(int port) -{ - TC_SET_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS); -} - -void tc_disc_ident_complete(int port) -{ - TC_CLR_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS); -} - void tc_try_src_override(enum try_src_override_t ov) { + if (!IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) + assert(0); + if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) { switch (ov) { case TRY_SRC_OVERRIDE_OFF: /* 0 */ @@ -936,6 +993,9 @@ void tc_try_src_override(enum try_src_override_t ov) enum try_src_override_t tc_get_try_src_override(void) { + if (!IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) + assert(0); + return pd_try_src_override; } @@ -949,6 +1009,15 @@ void tc_snk_power_off(int port) int tc_src_power_on(int port) { + /* + * Check our OC event counter. If we've exceeded our threshold, then + * let's latch our source path off to prevent continuous cycling. When + * the PD state machine detects a disconnection on the CC lines, we will + * reset our OC event counter. + */ + if (IS_ENABLED(CONFIG_USBC_OCP) && usbc_ocp_is_port_latched_off(port)) + return EC_ERROR_ACCESS_DENIED; + if (IS_ATTACHED_SRC(port)) return pd_set_power_supply_ready(port); @@ -965,14 +1034,37 @@ void tc_src_power_off(int port) CHARGE_CEIL_NONE); } +enum ocp_action { + OCP_CLEAR, + OCP_NO_ACTION, +}; + +/* Set what role the partner is right now, for the PPC and OCP module */ +static void tc_set_partner_role(int port, enum ppc_device_role role, + enum ocp_action ocp_command) +{ + if (IS_ENABLED(CONFIG_USBC_PPC)) + ppc_dev_is_connected(port, role); + + if (IS_ENABLED(CONFIG_USBC_OCP)) { + usbc_ocp_snk_is_connected(port, role == PPC_DEV_SNK); + /* + * Clear the overcurrent event counter + * if we're not in ErrorRecovery due to OCP + */ + if (ocp_command == OCP_CLEAR) + usbc_ocp_clear_event_counter(port); + } +} + /* * Depending on the load on the processor and the tasks running * it can take a while for the task associated with this port * to run. So build in 1ms delays, for up to 300ms, to wait for * the suspend to actually happen. */ -#define SUSPEND_SLEEP_DELAY 1 -#define SUSPEND_SLEEP_RETRIES 300 +#define SUSPEND_SLEEP_DELAY 1 +#define SUSPEND_SLEEP_RETRIES 300 void pd_set_suspend(int port, int suspend) { @@ -983,7 +1075,7 @@ void pd_set_suspend(int port, int suspend) if (suspend) { int wait = 0; - TC_SET_FLAG(port, TC_FLAGS_SUSPEND); + TC_SET_FLAG(port, TC_FLAGS_REQUEST_SUSPEND); /* * Avoid deadlock when running from task @@ -997,21 +1089,31 @@ void pd_set_suspend(int port, int suspend) /* Sleep this task if we are not suspended */ while (pd_is_port_enabled(port)) { if (++wait > SUSPEND_SLEEP_RETRIES) { - CPRINTS("C%d: NOT SUSPENDED after %dms", - port, wait * SUSPEND_SLEEP_DELAY); + CPRINTS("C%d: NOT SUSPENDED after %dms", port, + wait * SUSPEND_SLEEP_DELAY); return; } msleep(SUSPEND_SLEEP_DELAY); } } else { - TC_CLR_FLAG(port, TC_FLAGS_SUSPEND); + TC_CLR_FLAG(port, TC_FLAGS_REQUEST_SUSPEND); task_wake(PD_PORT_TO_TASK_ID(port)); } } +void pd_set_error_recovery(int port) +{ + TC_SET_FLAG(port, TC_FLAGS_REQUEST_ERROR_RECOVERY); +} + int pd_is_port_enabled(int port) { - return get_state_tc(port) != TC_DISABLED; + /* + * Checking get_state_tc(port) from another task isn't safe since it + * can return TC_DISABLED before tc_cc_open_entry and tc_disabled_entry + * are complete. So check TC_FLAGS_SUSPENDED instead. + */ + return !TC_CHK_FLAG(port, TC_FLAGS_SUSPENDED); } int pd_fetch_acc_log_entry(int port) @@ -1052,16 +1154,6 @@ bool pd_get_vconn_state(int port) return !!TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON); } -bool pd_get_partner_dual_role_power(int port) -{ - return !!TC_CHK_FLAG(port, TC_FLAGS_PARTNER_DR_POWER); -} - -bool pd_get_partner_unconstr_power(int port) -{ - return !!TC_CHK_FLAG(port, TC_FLAGS_PARTNER_UNCONSTRAINED); -} - const char *pd_get_task_state_name(int port) { return tc_get_current_state(port); @@ -1075,9 +1167,9 @@ void pd_vbus_low(int port) int pd_is_connected(int port) { return (IS_ATTACHED_SRC(port) || -#ifdef CONFIG_USB_PE_SM - (get_state_tc(port) == TC_CT_ATTACHED_SNK) || -#endif + (IS_ENABLED(CONFIG_USB_PE_SM) && + ((get_state_tc(port) == TC_CT_UNATTACHED_SNK) || + (get_state_tc(port) == TC_CT_ATTACHED_SNK))) || IS_ATTACHED_SNK(port)); } @@ -1086,18 +1178,73 @@ bool pd_is_disconnected(int port) return !pd_is_connected(port); } -static __maybe_unused void bc12_role_change_handler(int port) +/* + * PD functions which query our fixed PDO flags. Both the source and sink + * capabilities can present these values, and they should match between the two + * for compliant partners. + */ +static bool pd_check_fixed_flag(int port, uint32_t flag) +{ + uint32_t fixed_pdo; + + if (pd_get_src_cap_cnt(port) != 0) + fixed_pdo = *pd_get_src_caps(port); + else if (pd_get_snk_cap_cnt(port) != 0) + fixed_pdo = *pd_get_snk_caps(port); + else + return false; + + /* + * Error check that first PDO is fixed, as 6.4.1 Capabilities requires + * in the Power Delivery Specification. + * "The vSafe5V Fixed Supply Object Shall always be the first object" + */ + if ((fixed_pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED) + return false; + + return fixed_pdo & flag; +} + +bool pd_get_partner_data_swap_capable(int port) +{ + return pd_check_fixed_flag(port, PDO_FIXED_DATA_SWAP); +} + +bool pd_get_partner_usb_comm_capable(int port) { - int event; - int task_id = USB_CHG_PORT_TO_TASK_ID(port); + return pd_check_fixed_flag(port, PDO_FIXED_COMM_CAP); +} + +bool pd_get_partner_dual_role_power(int port) +{ + return pd_check_fixed_flag(port, PDO_FIXED_DUAL_ROLE); +} + +bool pd_get_partner_unconstr_power(int port) +{ + return pd_check_fixed_flag(port, PDO_FIXED_UNCONSTRAINED); +} + +static void bc12_role_change_handler(int port, enum pd_data_role prev_data_role, + enum pd_data_role data_role) +{ + int event = 0; + bool role_changed = (data_role != prev_data_role); + + if (!IS_ENABLED(CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER)) + return; /* Get the data role of our device */ - switch (pd_get_data_role(port)) { + switch (data_role) { case PD_ROLE_UFP: - event = USB_CHG_EVENT_DR_UFP; + /* Only trigger BC12 detection on a role change */ + if (role_changed) + event = USB_CHG_EVENT_DR_UFP; break; case PD_ROLE_DFP: - event = USB_CHG_EVENT_DR_DFP; + /* Only trigger BC12 host mode on a role change */ + if (role_changed) + event = USB_CHG_EVENT_DR_DFP; break; case PD_ROLE_DISCONNECTED: event = USB_CHG_EVENT_CC_OPEN; @@ -1105,7 +1252,9 @@ static __maybe_unused void bc12_role_change_handler(int port) default: return; } - task_set_event(task_id, event, 0); + + if (event) + usb_charger_task_set_event(port, event); } /* @@ -1118,6 +1267,17 @@ static void typec_select_pull(int port, enum tcpc_cc_pull pull) void typec_select_src_current_limit_rp(int port, enum tcpc_rp_value rp) { tc[port].select_current_limit_rp = rp; + if (IS_ATTACHED_SRC(port)) + TC_SET_FLAG(port, TC_FLAGS_UPDATE_CURRENT); +} +__overridable int typec_get_default_current_limit_rp(int port) +{ + int rp = CONFIG_USB_PD_PULLUP; + + if (pd_get_bist_share_mode()) + rp = TYPEC_RP_3A0; + + return rp; } void typec_select_src_collision_rp(int port, enum tcpc_rp_value rp) { @@ -1126,8 +1286,7 @@ void typec_select_src_collision_rp(int port, enum tcpc_rp_value rp) static enum tcpc_rp_value typec_get_active_select_rp(int port) { /* Explicit contract will use the collision Rp */ - if (IS_ENABLED(CONFIG_USB_PD_REV30) && - pe_is_explicit_contract(port)) + if (IS_ENABLED(CONFIG_USB_PD_REV30) && pe_is_explicit_contract(port)) return tc[port].select_collision_rp; return tc[port].select_current_limit_rp; } @@ -1163,8 +1322,15 @@ static bool tc_perform_src_hard_reset(int port) /* Set role to DFP */ tc_set_data_role(port, PD_ROLE_DFP); + /* + * USB PD Rev 3.0 Ver 2.0 6.8.3.2: "A Hard Reset Shall cause + * all Active Modes to be exited by both Port Partners and any + * Cable Plugs" + */ + tc_set_modes_exit(port); + tc[port].ps_reset_state = PS_STATE1; - tc[port].timeout = get_time().val + PD_T_SRC_RECOVER; + pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_T_SRC_RECOVER); return false; case PS_STATE1: /* Enable VBUS */ @@ -1177,8 +1343,8 @@ static bool tc_perform_src_hard_reset(int port) set_vconn(port, 1); tc[port].ps_reset_state = PS_STATE2; - tc[port].timeout = get_time().val + - PD_POWER_SUPPLY_TURN_ON_DELAY; + pd_timer_enable(port, TC_TIMER_TIMEOUT, + PD_POWER_SUPPLY_TURN_ON_DELAY); return false; case PS_STATE2: /* Tell Policy Engine Hard Reset is complete */ @@ -1204,39 +1370,64 @@ static bool tc_perform_snk_hard_reset(int port) { switch (tc[port].ps_reset_state) { case PS_STATE0: - /* Shutting off power, Disable AutoDischargeDisconnect */ - tcpm_enable_auto_discharge_disconnect(port, 0); - /* Hard reset sets us back to default data role */ tc_set_data_role(port, PD_ROLE_UFP); - /* Clear the input current limit */ - sink_stop_drawing_current(port); + /* + * USB PD Rev 3.0 Ver 2.0 6.8.3.2: "A Hard Reset Shall cause + * all Active Modes to be exited by both Port Partners and any + * Cable Plugs" + */ + tc_set_modes_exit(port); /* * When VCONN is supported, the Hard Reset Shall cause * the Port with the Rd resistor asserted to turn off * VCONN. */ -#ifdef CONFIG_USBC_VCONN - if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON)) + if (IS_ENABLED(CONFIG_USBC_VCONN) && + TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON)) set_vconn(port, 0); -#endif - /* Wait tSafe0V + tSrcRecover, then check for Vbus presence */ + + /* Wait up to tVSafe0V for Vbus to disappear */ tc[port].ps_reset_state = PS_STATE1; - tc[port].timeout = get_time().val + PD_T_SAFE_0V + - PD_T_SRC_RECOVER_MAX; + pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_T_SAFE_0V); return false; case PS_STATE1: - if (get_time().val < tc[port].timeout) - return false; + if (pd_check_vbus_level(port, VBUS_SAFE0V)) { + /* + * Partner dropped Vbus, reduce our current consumption + * and await its return. + */ + sink_stop_drawing_current(port); - /* Watch for Vbus to return */ - tc[port].ps_reset_state = PS_STATE2; - tc[port].timeout = get_time().val + PD_T_SRC_TURN_ON; + tcpm_enable_auto_discharge_disconnect(port, 0); + + /* Move on to waiting for the return of Vbus */ + tc[port].ps_reset_state = PS_STATE2; + pd_timer_enable(port, TC_TIMER_TIMEOUT, + PD_T_SRC_RECOVER_MAX + + PD_T_SRC_TURN_ON); + } + + if (pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) { + /* + * No Vbus drop likely indicates a non-PD port partner, + * move to the next stage anyway. + */ + tc[port].ps_reset_state = PS_STATE2; + pd_timer_enable(port, TC_TIMER_TIMEOUT, + PD_T_SRC_RECOVER_MAX + + PD_T_SRC_TURN_ON); + } return false; case PS_STATE2: - if (pd_is_vbus_present(port)) { + /* + * Look for the voltage to be above disconnect. Since we didn't + * drop our draw on non-PD partners, they may have dipped below + * vSafe5V but still be in a valid connected voltage. + */ + if (!pd_check_vbus_level(port, VBUS_REMOVED)) { /* * Inform policy engine that power supply * reset is complete @@ -1254,7 +1445,7 @@ static bool tc_perform_snk_hard_reset(int port) * now, such that we'll actually reset the correct input * current limit. */ - tc[port].cc_debounce = get_time().val; + pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, 0); sink_power_sub_states(port); /* Power is back, Enable AutoDischargeDisconnect */ @@ -1264,7 +1455,7 @@ static bool tc_perform_snk_hard_reset(int port) /* * If Vbus isn't back after wait + tSrcTurnOn, go unattached */ - if (get_time().val > tc[port].timeout) { + if (pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) { tc[port].ps_reset_state = PS_STATE0; set_state_tc(port, TC_UNATTACHED_SNK); return true; @@ -1301,7 +1492,8 @@ static void restart_tc_sm(int port, enum usb_tc_state start_state) * Update the Rp Value. We don't need to update CC lines though as that * happens in below set_state transition. */ - typec_select_src_current_limit_rp(port, CONFIG_USB_PD_PULLUP); + typec_select_src_current_limit_rp( + port, typec_get_default_current_limit_rp(port)); /* Disable if restart failed, otherwise start in default state. */ set_state_tc(port, res ? TC_DISABLED : start_state); @@ -1322,12 +1514,31 @@ static void restart_tc_sm(int port, enum usb_tc_state start_state) } if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { - /* Initialize PD and type-C supplier current limits to 0 */ + /* + * Only initialize PD supplier current limit to 0. + * Defer initializing type-C supplier current limit + * to Unattached.SNK or Attached.SNK. + */ pd_set_input_current_limit(port, 0, 0); - typec_set_input_current_limit(port, 0, 0); charge_manager_update_dualrole(port, CAP_UNKNOWN); } + /* + * PD r3.0 v2.0, ss6.2.1.1.5: + * After a physical or logical (USB Type-C Error Recovery) Attach, a + * Port discovers the common Specification Revision level between itself + * and its Port Partner and/or the Cable Plug(s), and uses this + * Specification Revision level until a Detach, Hard Reset or Error + * Recovery happens. + * + * This covers the Error Recovery case, because TC_ERROR_RECOVERY + * reinitializes the TC state machine. This also covers the implicit + * case when PD is suspended and resumed or when the state machine is + * first initialized. + */ + if (IS_ENABLED(CONFIG_USB_PRL_SM)) + prl_set_default_pd_revision(port); + #ifdef CONFIG_USB_PE_SM tc_enable_pd(port, 0); tc[port].ps_reset_state = PS_STATE0; @@ -1338,39 +1549,51 @@ void tc_state_init(int port) { enum usb_tc_state first_state; + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return; + /* For test builds, replicate static initialization */ if (IS_ENABLED(TEST_BUILD)) { - int i; - - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; ++i) { - memset(&tc[i], 0, sizeof(tc[i])); - drp_state[i] = CONFIG_USB_PD_INITIAL_DRP_STATE; - } + memset(&tc[port], 0, sizeof(tc[port])); + drp_state[port] = CONFIG_USB_PD_INITIAL_DRP_STATE; } /* If port is not available, there is nothing to initialize */ if (port >= board_get_usb_pd_port_count()) { tc_enable_pd(port, 0); - tc_pause_event_loop(port); - TC_SET_FLAG(port, TC_FLAGS_SUSPEND); + TC_SET_FLAG(port, TC_FLAGS_REQUEST_SUSPEND); return; } /* Allow system to set try src enable */ - tc_try_src_override(TRY_SRC_NO_OVERRIDE); + if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) + tc_try_src_override(TRY_SRC_NO_OVERRIDE); /* * Set initial PD communication policy. */ tc_policy_pd_enable(port, pd_comm_allowed_by_policy()); +#ifdef CONFIG_AP_POWER_CONTROL /* Set dual-role state based on chipset power state */ if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) pd_set_dual_role_and_event(port, PD_DRP_FORCE_SINK, 0); else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) - pd_set_dual_role_and_event(port, pd_get_drp_state_in_suspend(), 0); + pd_set_dual_role_and_event(port, pd_get_drp_state_in_suspend(), + 0); else /* CHIPSET_STATE_ON */ - pd_set_dual_role_and_event(port, PD_DRP_TOGGLE_ON, 0); + pd_set_dual_role_and_event(port, pd_get_drp_state_in_s0(), 0); +#else + pd_set_dual_role_and_event(port, board_tc_get_initial_drp_mode(port), + 0); +#endif + + /* + * We are going to apply CC open (start with ErrorRecovery state) + * unless there is something which forbids us to do that (one of + * conditions below is true) + */ + first_state = TC_ERROR_RECOVERY; /* * If we just lost power, don't apply CC open. Otherwise we would boot @@ -1380,12 +1603,28 @@ void tc_state_init(int port) if (system_get_reset_flags() & (EC_RESET_FLAG_BROWNOUT | EC_RESET_FLAG_POWER_ON)) { first_state = TC_UNATTACHED_SNK; + } + + /* + * If this is non-EFS2 device, battery is not present or at some minimum + * voltage and EC RO doesn't keep power-on reset flag after reset caused + * by H1, then don't apply CC open because it will cause brown out. + * + * Please note that we are checking if CONFIG_BOARD_RESET_AFTER_POWER_ON + * is defined now, but actually we need to know if it was enabled in + * EC RO! It was assumed that if CONFIG_BOARD_RESET_AFTER_POWER_ON is + * defined now it was defined in EC RO too. + */ + if (!IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON) && + !IS_ENABLED(CONFIG_VBOOT_EFS2) && IS_ENABLED(CONFIG_BATTERY) && + !pd_is_battery_capable()) { + first_state = TC_UNATTACHED_SNK; + } + if (first_state == TC_UNATTACHED_SNK) { /* Turn off any previous sourcing */ tc_src_power_off(port); set_vconn(port, 0); - } else { - first_state = TC_ERROR_RECOVERY; } #ifdef CONFIG_USB_PD_TCPC_BOARD_INIT @@ -1438,6 +1677,17 @@ void tc_set_power_role(int port, enum pd_power_role role) * Private Functions */ +/* Set GPIO_CCD_MODE_ODL gpio */ +static void set_ccd_mode(const int port, const bool enable) +{ + if (IS_ENABLED(CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT) && + port == CONFIG_CCD_USBC_PORT_NUMBER) { + if (enable) + CPRINTS("Asserting GPIO_CCD_MODE_ODL"); + gpio_set_level(_GPIO_CCD_MODE_ODL, !enable); + } +} + /* Set the TypeC state machine to a new state. */ static void set_state_tc(const int port, const enum usb_tc_state new_state) { @@ -1449,7 +1699,11 @@ static void set_state_tc(const int port, const enum usb_tc_state new_state) /* Get the current TypeC state. */ test_export_static enum usb_tc_state get_state_tc(const int port) { - return tc[port].ctx.current - &tc_states[0]; + /* Default to returning TC_STATE_COUNT if no state has been set */ + if (tc[port].ctx.current == NULL) + return TC_STATE_COUNT; + else + return tc[port].ctx.current - &tc_states[0]; } /* Get the previous TypeC state. */ @@ -1463,19 +1717,24 @@ static void print_current_state(const int port) if (IS_ENABLED(USB_PD_DEBUG_LABELS)) CPRINTS_L1("C%d: %s", port, tc_state_names[get_state_tc(port)]); else - CPRINTS("C%d: tc-st%d", port, get_state_tc(port)); + CPRINTS_L1("C%d: tc-st%d", port, get_state_tc(port)); } static void handle_device_access(int port) { - tc[port].low_power_time = get_time().val + PD_LPM_DEBOUNCE_US; + if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER) && + get_state_tc(port) == TC_LOW_POWER_MODE) { + tc_start_event_loop(port); + pd_timer_enable(port, TC_TIMER_LOW_POWER_TIME, + PD_LPM_DEBOUNCE_US); + } } void tc_event_check(int port, int evt) { #ifdef DEBUG_PRINT_FLAG_AND_EVENT_NAMES if (evt != TASK_EVENT_TIMER) - print_bits("Event", evt, event_bit_names, + print_bits(port, "Event", evt, event_bit_names, ARRAY_SIZE(event_bit_names)); #endif @@ -1491,36 +1750,38 @@ void tc_event_check(int port, int evt) if (evt & PD_EVENT_RX_HARD_RESET) pd_execute_hard_reset(port); - if (evt & PD_EVENT_SEND_HARD_RESET) - tc_hard_reset_request(port); + if (evt & PD_EVENT_SEND_HARD_RESET) { + /* Pass Hard Reset request to PE layer if available */ + if (IS_ENABLED(CONFIG_USB_PE_SM) && tc_get_pd_enabled(port)) + pd_dpm_request(port, DPM_REQUEST_HARD_RESET_SEND); + } -#ifdef CONFIG_POWER_COMMON - if (IS_ENABLED(CONFIG_POWER_COMMON)) { + if (IS_ENABLED(CONFIG_AP_POWER_CONTROL)) { if (evt & PD_EVENT_POWER_STATE_CHANGE) handle_new_power_state(port); } -#endif /* CONFIG_POWER_COMMON */ -#ifdef CONFIG_USB_PD_ALT_MODE_DFP - { + if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { int i; - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { - /* - * Notify all ports of sysjump - */ - if (evt & PD_EVENT_SYSJUMP) { - for (i = 0; i < - CONFIG_USB_PD_PORT_MAX_COUNT; i++) - dpm_set_mode_exit_request(i); - notify_sysjump_ready(); - } + /* + * Notify all ports of sysjump + */ + if (evt & PD_EVENT_SYSJUMP) { + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) + dpm_set_mode_exit_request(i); + notify_sysjump_ready(); } } -#endif - if (evt & PD_EVENT_UPDATE_DUAL_ROLE) + if (evt & PD_EVENT_UPDATE_DUAL_ROLE) { + /* If TCPC is idle, start the wake process */ + if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER) && + get_state_tc(port) == TC_LOW_POWER_MODE) + tcpm_wake_low_power_mode(port); + pd_update_dual_role_config(port); + } } /* @@ -1538,6 +1799,9 @@ void tc_event_check(int port, int evt) void tc_set_data_role(int port, enum pd_data_role role) { + enum pd_data_role prev_data_role; + + prev_data_role = tc[port].data_role; tc[port].data_role = role; if (IS_ENABLED(CONFIG_USBC_SS_MUX)) @@ -1554,8 +1818,7 @@ void tc_set_data_role(int port, enum pd_data_role role) * instead of VBUS changes, need to set an event to wake up the USB_CHG * task and indicate the current data role. */ - if (IS_ENABLED(CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER)) - bc12_role_change_handler(port); + bc12_role_change_handler(port, prev_data_role, tc[port].data_role); /* Notify TCPC of role update */ tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role); @@ -1567,18 +1830,18 @@ static void sink_stop_drawing_current(int port) if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { typec_set_input_current_limit(port, 0, 0); - charge_manager_set_ceil(port, - CEIL_REQUESTOR_PD, CHARGE_CEIL_NONE); + charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, + CHARGE_CEIL_NONE); } } -#ifdef CONFIG_USB_PD_TRY_SRC static void pd_update_try_source(void) { +#ifdef CONFIG_USB_PD_TRY_SRC tc_enable_try_src(pd_is_try_source_capable()); +#endif } DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_try_source, HOOK_PRIO_DEFAULT); -#endif /* CONFIG_USB_PD_TRY_SRC */ static void set_vconn(int port, int enable) { @@ -1587,43 +1850,24 @@ static void set_vconn(int port, int enable) else TC_CLR_FLAG(port, TC_FLAGS_VCONN_ON); - /* - * Disable PPC Vconn first then TCPC in case the voltage feeds back - * to TCPC and damages. - */ - if (IS_ENABLED(CONFIG_USBC_PPC_VCONN) && !enable) - ppc_set_vconn(port, 0); - - /* - * We always need to tell the TCPC to enable Vconn first, otherwise some - * TCPCs get confused and think the CC line is in over voltage mode and - * immediately disconnects. If there is a PPC, both devices will - * potentially source Vconn, but that should be okay since Vconn has - * "make before break" electrical requirements when swapping anyway. - */ - tcpm_set_vconn(port, enable); - - if (IS_ENABLED(CONFIG_USBC_PPC_VCONN) && enable) - ppc_set_vconn(port, 1); + typec_set_vconn(port, enable); } /* This must only be called from the PD task */ static void pd_update_dual_role_config(int port) { if (tc[port].power_role == PD_ROLE_SOURCE && - ((drp_state[port] == PD_DRP_FORCE_SINK && - !pd_ts_dts_plugged(port)) || - (drp_state[port] == PD_DRP_TOGGLE_OFF && - get_state_tc(port) == TC_UNATTACHED_SRC))) { + (drp_state[port] == PD_DRP_FORCE_SINK || + (drp_state[port] == PD_DRP_TOGGLE_OFF && + get_state_tc(port) == TC_UNATTACHED_SRC))) { /* * Change to sink if port is currently a source AND (new DRP - * state is force sink OR new DRP state is either toggle off - * or debug accessory toggle only and we are in the source - * disconnected state). + * state is force sink OR new DRP state is toggle off and we are + * in the source disconnected state). */ set_state_tc(port, TC_UNATTACHED_SNK); } else if (tc[port].power_role == PD_ROLE_SINK && - drp_state[port] == PD_DRP_FORCE_SOURCE) { + drp_state[port] == PD_DRP_FORCE_SOURCE) { /* * Change to source if port is currently a sink and the * new DRP state is force source. @@ -1632,56 +1876,54 @@ static void pd_update_dual_role_config(int port) } } -#ifdef CONFIG_POWER_COMMON -static void handle_new_power_state(int port) +__maybe_unused static void handle_new_power_state(int port) { - if (IS_ENABLED(CONFIG_POWER_COMMON) && + if (!IS_ENABLED(CONFIG_AP_POWER_CONTROL)) + assert(0); + + if (IS_ENABLED(CONFIG_AP_POWER_CONTROL) && IS_ENABLED(CONFIG_USB_PE_SM)) { if (chipset_in_or_transitioning_to_state( - CHIPSET_STATE_ANY_OFF)) { + CHIPSET_STATE_ANY_OFF)) { /* * The SoC will negotiate alternate mode again when it * boots up */ dpm_set_mode_exit_request(port); - - /* - * The following function will disconnect both USB and - * DP mux, as the chipset is transitioning to OFF. - */ - set_usb_mux_with_current_data_role(port); } } -} -#endif /* CONFIG_POWER_COMMON */ -#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) -void pd_send_hpd(int port, enum hpd_event hpd) -{ - uint32_t data[1]; - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); - - if (!opos) - return; + /* + * If the sink port was sourcing Vconn, and can no longer, request a + * hard reset on this port to restore Vconn to the source. If we do not + * have sufficient battery to withstand Vbus loss, then continue with + * the inconsistent Vconn state in order to keep the board powered. + */ + if (IS_ENABLED(CONFIG_USB_PE_SM)) { + if (tc_is_vconn_src(port) && tc_is_attached_snk(port) && + !pd_check_vconn_swap(port) && pd_is_battery_capable()) + pd_dpm_request(port, DPM_REQUEST_HARD_RESET_SEND); + } - data[0] = VDO_DP_STATUS((hpd == hpd_irq), /* IRQ_HPD */ - (hpd != hpd_low), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - 0, /* MF pref */ - 1, /* enabled */ - 0, /* power low */ - 0x2); - pd_send_vdm(port, USB_SID_DISPLAYPORT, VDO_OPOS(opos) | CMD_ATTENTION, - data, 1); + /* + * TC_FLAGS_UPDATE_USB_MUX is set on chipset startup and shutdown. + * Set the USB mux according to the new power state. If the chipset + * is transitioning to OFF, this disconnects USB and DP mux. + * + * Transitions to and from suspend states do not change the USB mux + * or the alternate mode configuration. + */ + if (TC_CHK_FLAG(port, TC_FLAGS_UPDATE_USB_MUX)) { + TC_CLR_FLAG(port, TC_FLAGS_UPDATE_USB_MUX); + set_usb_mux_with_current_data_role(port); + } } -#endif #ifdef CONFIG_USBC_VCONN_SWAP void pd_request_vconn_swap_off(int port) { if (get_state_tc(port) == TC_ATTACHED_SRC || - get_state_tc(port) == TC_ATTACHED_SNK) { + get_state_tc(port) == TC_ATTACHED_SNK) { TC_SET_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_OFF); task_wake(PD_PORT_TO_TASK_ID(port)); } @@ -1690,7 +1932,7 @@ void pd_request_vconn_swap_off(int port) void pd_request_vconn_swap_on(int port) { if (get_state_tc(port) == TC_ATTACHED_SRC || - get_state_tc(port) == TC_ATTACHED_SNK) { + get_state_tc(port) == TC_ATTACHED_SNK) { TC_SET_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON); task_wake(PD_PORT_TO_TASK_ID(port)); } @@ -1724,10 +1966,7 @@ static __maybe_unused int reset_device_and_notify(int port) TC_CLR_FLAG(port, TC_FLAGS_LPM_ENGAGED); tc_start_event_loop(port); - if (rv == EC_SUCCESS) - CPRINTS("C%d: TCPC init ready", port); - else - CPRINTS("C%d: TCPC init failed!", port); + CPRINTS("C%d: TCPC init %s", port, rv ? "failed!" : "ready"); /* * Before getting the other tasks that are waiting, clear the reset @@ -1740,17 +1979,16 @@ static __maybe_unused int reset_device_and_notify(int port) * waking the TCPC, but it has also set PD_EVENT_TCPC_RESET again, which * would result in a second, unnecessary init. */ - deprecated_atomic_clear_bits(task_get_event_bitmap(task_get_current()), - PD_EVENT_TCPC_RESET); + atomic_clear_bits(task_get_event_bitmap(task_get_current()), + PD_EVENT_TCPC_RESET); - waiting_tasks = - deprecated_atomic_read_clear(&tc[port].tasks_waiting_on_reset); + waiting_tasks = atomic_clear(&tc[port].tasks_waiting_on_reset); /* Wake up all waiting tasks. */ while (waiting_tasks) { task = __fls(waiting_tasks); waiting_tasks &= ~BIT(task); - task_set_event(task, TASK_EVENT_PD_AWAKE, 0); + task_set_event(task, TASK_EVENT_PD_AWAKE); } return rv; @@ -1767,8 +2005,8 @@ void pd_wait_exit_low_power(int port) reset_device_and_notify(port); } else { /* Otherwise, we need to wait for the TCPC reset to complete */ - deprecated_atomic_or(&tc[port].tasks_waiting_on_reset, - 1 << task_get_current()); + atomic_or(&tc[port].tasks_waiting_on_reset, + 1 << task_get_current()); /* * NOTE: We could be sending the PD task the reset event while * it is already processing the reset event. If that occurs, @@ -1777,8 +2015,7 @@ void pd_wait_exit_low_power(int port) * happen much, but it if starts occurring, we can add a guard * to prevent/reduce it. */ - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_TCPC_RESET, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TCPC_RESET); task_wait_event_mask(TASK_EVENT_PD_AWAKE, -1); } } @@ -1793,7 +2030,7 @@ void pd_device_accessed(int port) handle_device_access(port); else task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_DEVICE_ACCESSED, 0); + PD_EVENT_DEVICE_ACCESSED); } /* @@ -1804,15 +2041,11 @@ void pd_prevent_low_power_mode(int port, int prevent) { const int current_task_mask = (1 << task_get_current()); - if (!IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER)) - return; - if (prevent) - deprecated_atomic_or(&tc[port].tasks_preventing_lpm, - current_task_mask); + atomic_or(&tc[port].tasks_preventing_lpm, current_task_mask); else - deprecated_atomic_clear_bits(&tc[port].tasks_preventing_lpm, - current_task_mask); + atomic_clear_bits(&tc[port].tasks_preventing_lpm, + current_task_mask); } #endif /* CONFIG_USB_PD_TCPC_LOW_POWER */ @@ -1823,7 +2056,7 @@ static void sink_power_sub_states(int port) tcpm_get_cc(port, &cc1, &cc2); - cc = tc[port].polarity ? cc2 : cc1; + cc = polarity_rm_dts(tc[port].polarity) ? cc2 : cc1; if (cc == TYPEC_CC_VOLT_RP_DEF) new_cc_voltage = TYPEC_CC_VOLT_RP_DEF; @@ -1837,28 +2070,28 @@ static void sink_power_sub_states(int port) /* Debounce the cc state */ if (new_cc_voltage != tc[port].cc_voltage) { tc[port].cc_voltage = new_cc_voltage; - tc[port].cc_debounce = - get_time().val + PD_T_RP_VALUE_CHANGE; + pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, + PD_T_RP_VALUE_CHANGE); return; } - if (tc[port].cc_debounce == 0 || - get_time().val < tc[port].cc_debounce) - return; + if (!pd_timer_is_disabled(port, TC_TIMER_CC_DEBOUNCE)) { + if (!pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE)) + return; - tc[port].cc_debounce = 0; + pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE); - if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { - tc[port].typec_curr = usb_get_typec_current_limit( - tc[port].polarity, cc1, cc2); + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { + tc[port].typec_curr = usb_get_typec_current_limit( + tc[port].polarity, cc1, cc2); - typec_set_input_current_limit(port, - tc[port].typec_curr, TYPE_C_VOLTAGE); - charge_manager_update_dualrole(port, CAP_DEDICATED); + typec_set_input_current_limit(port, tc[port].typec_curr, + TYPE_C_VOLTAGE); + charge_manager_update_dualrole(port, CAP_DEDICATED); + } } } - /* * TYPE-C State Implementations */ @@ -1868,36 +2101,50 @@ static void sink_power_sub_states(int port) * * Super State Entry Actions: * Remove the terminations from CC - * Set's VBUS and VCONN off + * Set VBUS and VCONN off */ static void tc_disabled_entry(const int port) { print_current_state(port); + /* + * We have completed tc_cc_open_entry (our super state), so set flag + * to indicate to pd_is_port_enabled that we are now suspended. + */ + TC_SET_FLAG(port, TC_FLAGS_SUSPENDED); + tcpm_release(port); } static void tc_disabled_run(const int port) { - /* - * If pd_set_suspend SUSPEND state changes to - * no longer be suspended then we need to exit - * our current state and go UNATTACHED_SNK - */ - if (!TC_CHK_FLAG(port, TC_FLAGS_SUSPEND)) - set_state_tc(port, TC_UNATTACHED_SNK); - - task_wait_event(-1); + /* If pd_set_suspend clears the request, go to TC_UNATTACHED_SNK/SRC. */ + if (!TC_CHK_FLAG(port, TC_FLAGS_REQUEST_SUSPEND)) { + set_state_tc(port, drp_state[port] == PD_DRP_FORCE_SOURCE ? + TC_UNATTACHED_SRC : + TC_UNATTACHED_SNK); + } else { + if (IS_ENABLED(CONFIG_USBC_RETIMER_FW_UPDATE)) { + if (TC_CHK_FLAG( + port, + TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN)) { + TC_CLR_FLAG( + port, + TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN); + usb_retimer_fw_update_process_op_cb(port); + } + } + tc_pause_event_loop(port); + } } static void tc_disabled_exit(const int port) { - if (!IS_ENABLED(CONFIG_USB_PD_TCPC)) { - if (tcpm_init(port) != 0) { - CPRINTS("C%d: TCPC restart failed!", port); - return; - } - } + int rv; + + tc_start_event_loop(port); + TC_CLR_FLAG(port, TC_FLAGS_SUSPENDED); - CPRINTS("C%d: TCPC resumed!", port); + rv = tcpm_init(port); + CPRINTS("C%d: TCPC init %s", port, rv ? "failed!" : "ready"); } /** @@ -1911,12 +2158,16 @@ static void tc_error_recovery_entry(const int port) { print_current_state(port); - tc[port].timeout = get_time().val + PD_T_ERROR_RECOVERY; + pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_T_ERROR_RECOVERY); + + TC_CLR_FLAG(port, TC_FLAGS_REQUEST_ERROR_RECOVERY); } static void tc_error_recovery_run(const int port) { - if (get_time().val < tc[port].timeout) + enum usb_tc_state start_state; + + if (!pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) return; /* @@ -1925,7 +2176,9 @@ static void tc_error_recovery_run(const int port) * because we just did that. So transition to the state directly. */ if (tc[port].ctx.previous == NULL) { - set_state_tc(port, TC_UNATTACHED_SNK); + set_state_tc(port, drp_state[port] == PD_DRP_FORCE_SOURCE ? + TC_UNATTACHED_SRC : + TC_UNATTACHED_SNK); return; } @@ -1933,8 +2186,18 @@ static void tc_error_recovery_run(const int port) * If try src support is active (e.g. in S0). Then try to become the * SRC, otherwise we should try to be the sink. */ - restart_tc_sm(port, is_try_src_enabled(port) ? TC_UNATTACHED_SRC : - TC_UNATTACHED_SNK); + start_state = TC_UNATTACHED_SNK; + if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) + if (is_try_src_enabled(port) || + drp_state[port] == PD_DRP_FORCE_SOURCE) + start_state = TC_UNATTACHED_SRC; + + restart_tc_sm(port, start_state); +} + +static void tc_error_recovery_exit(const int port) +{ + pd_timer_disable(port, TC_TIMER_TIMEOUT); } /** @@ -1942,6 +2205,8 @@ static void tc_error_recovery_run(const int port) */ static void tc_unattached_snk_entry(const int port) { + enum pd_data_role prev_data_role; + if (get_last_state_tc(port) != TC_UNATTACHED_SRC) { tc_detached(port); print_current_state(port); @@ -1955,58 +2220,44 @@ static void tc_unattached_snk_entry(const int port) * * Both CC1 and CC2 pins shall be independently terminated to * ground through Rd. + * + * Restore default current limit Rp in case we swap to source + * + * Run any debug detaches needed before setting CC, as some TCPCs may + * require we set CC Open before changing power roles with a debug + * accessory. */ + tcpm_debug_detach(port); typec_select_pull(port, TYPEC_CC_RD); + typec_select_src_current_limit_rp( + port, typec_get_default_current_limit_rp(port)); typec_update_cc(port); - /* - * Tell Policy Engine to invalidate the explicit contract. - * This mainly used to clear the BB Ram Explicit Contract - * value. - */ - pe_invalidate_explicit_contract(port); - + prev_data_role = tc[port].data_role; tc[port].data_role = PD_ROLE_DISCONNECTED; - - /* - * Saved SRC_Capabilities are no longer valid on disconnect - */ - pd_set_src_caps(port, 0, NULL); - /* * When data role set events are used to enable BC1.2, then CC * detach events are used to notify BC1.2 that it can be powered * down. */ - if (IS_ENABLED(CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER)) - bc12_role_change_handler(port); + bc12_role_change_handler(port, prev_data_role, tc[port].data_role); if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) charge_manager_update_dualrole(port, CAP_UNKNOWN); - if (IS_ENABLED(CONFIG_USBC_PPC)) { - /* - * Clear the overcurrent event counter - * since we've detected a disconnect. - */ - ppc_clear_oc_event_counter(port); - } + tc_set_partner_role(port, PPC_DEV_DISCONNECTED, OCP_CLEAR); /* * Indicate that the port is disconnected so the board * can restore state from any previous data swap. */ pd_execute_data_swap(port, PD_ROLE_DISCONNECTED); - tc[port].next_role_swap = get_time().val + PD_T_DRP_SNK; + pd_timer_enable(port, TC_TIMER_NEXT_ROLE_SWAP, PD_T_DRP_SNK); - if (IS_ENABLED(CONFIG_USBC_SS_MUX)) - usb_mux_set(port, USB_PD_MUX_NONE, - USB_SWITCH_DISCONNECT, tc[port].polarity); - - if (IS_ENABLED(CONFIG_USB_PE_SM)) { - CLR_ALL_BUT_LPM_FLAGS(port); - tc_enable_pd(port, 0); - } +#ifdef CONFIG_USB_PE_SM + CLR_FLAGS_ON_DISCONNECT(port); + tc[port].ps_reset_state = PS_STATE0; +#endif } static void tc_unattached_snk_run(const int port) @@ -2030,17 +2281,6 @@ static void tc_unattached_snk_run(const int port) /* Check for connection */ tcpm_get_cc(port, &cc1, &cc2); - /* - * Attempt TCPC auto DRP toggle if it is - * not already auto toggling. - */ - if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && - drp_state[port] == PD_DRP_TOGGLE_ON && - tcpm_auto_toggle_supported(port) && cc_is_open(cc1, cc2)) { - set_state_tc(port, TC_DRP_AUTO_TOGGLE); - return; - } - /* * The port shall transition to AttachWait.SNK when a Source * connection is detected, as indicated by the SNK.Rp state @@ -2053,9 +2293,34 @@ static void tc_unattached_snk_run(const int port) if (cc_is_rp(cc1) || cc_is_rp(cc2)) { /* Connection Detected */ set_state_tc(port, TC_ATTACH_WAIT_SNK); - } else if (get_time().val > tc[port].next_role_swap && - drp_state[port] == PD_DRP_TOGGLE_ON) { - /* DRP Toggle */ + return; + } + + /* + * Debounce the CC open status. Some TCPC needs time to get the CC + * status valid. Before that, CC open is reported by default. Wait + * to make sure the CC is really open. Reuse the role toggle timer. + */ + if (!pd_timer_is_expired(port, TC_TIMER_NEXT_ROLE_SWAP)) + return; + + /* + * Initialize type-C supplier current limits to 0. The charge + * manage is now seeded if it was not. + */ + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) + typec_set_input_current_limit(port, 0, 0); + + /* + * Attempt TCPC auto DRP toggle if it is + * not already auto toggling. + */ + if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && + drp_state[port] == PD_DRP_TOGGLE_ON && + tcpm_auto_toggle_supported(port)) { + set_state_tc(port, TC_DRP_AUTO_TOGGLE); + } else if (drp_state[port] == PD_DRP_TOGGLE_ON) { + /* DRP Toggle. The timer was checked above. */ set_state_tc(port, TC_UNATTACHED_SRC); } else if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER) && (drp_state[port] == PD_DRP_FORCE_SINK || @@ -2064,6 +2329,11 @@ static void tc_unattached_snk_run(const int port) } } +static void tc_unattached_snk_exit(const int port) +{ + pd_timer_disable(port, TC_TIMER_NEXT_ROLE_SWAP); +} + /** * AttachWait.SNK * @@ -2087,7 +2357,7 @@ static void tc_attach_wait_snk_run(const int port) /* Check for connection */ tcpm_get_cc(port, &cc1, &cc2); - if (cc_is_rp(cc1) && cc_is_rp(cc2)) + if (cc_is_rp(cc1) && cc_is_rp(cc2) && board_is_dts_port(port)) new_cc_state = PD_CC_DFP_DEBUG_ACC; else if (cc_is_rp(cc1) || cc_is_rp(cc2)) new_cc_state = PD_CC_DFP_ATTACHED; @@ -2096,8 +2366,8 @@ static void tc_attach_wait_snk_run(const int port) /* Debounce the cc state */ if (new_cc_state != tc[port].cc_state) { - tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE; - tc[port].pd_debounce = get_time().val + PD_T_PD_DEBOUNCE; + pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_CC_DEBOUNCE); + pd_timer_enable(port, TC_TIMER_PD_DEBOUNCE, PD_T_PD_DEBOUNCE); tc[port].cc_state = new_cc_state; return; } @@ -2109,18 +2379,11 @@ static void tc_attach_wait_snk_run(const int port) * Unattached.SNK. */ if (new_cc_state == PD_CC_NONE && - get_time().val > tc[port].pd_debounce) { - if (IS_ENABLED(CONFIG_USB_PE_SM) && - IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { - pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); - pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0); - pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, 0, 0); - } - + pd_timer_is_expired(port, TC_TIMER_PD_DEBOUNCE)) { /* We are detached */ - if (drp_state[port] == PD_DRP_TOGGLE_OFF - || drp_state[port] == PD_DRP_FREEZE - || drp_state[port] == PD_DRP_FORCE_SINK) + if (drp_state[port] == PD_DRP_TOGGLE_OFF || + drp_state[port] == PD_DRP_FREEZE || + drp_state[port] == PD_DRP_FORCE_SINK) set_state_tc(port, TC_UNATTACHED_SNK); else set_state_tc(port, TC_UNATTACHED_SRC); @@ -2128,7 +2391,7 @@ static void tc_attach_wait_snk_run(const int port) } /* Wait for CC debounce */ - if (get_time().val < tc[port].cc_debounce) + if (!pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE)) return; /* @@ -2147,7 +2410,8 @@ static void tc_attach_wait_snk_run(const int port) */ if (pd_is_vbus_present(port)) { if (new_cc_state == PD_CC_DFP_ATTACHED) { - if (is_try_src_enabled(port)) + if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC) && + is_try_src_enabled(port)) set_state_tc(port, TC_TRY_SRC); else set_state_tc(port, TC_ATTACHED_SNK); @@ -2159,13 +2423,19 @@ static void tc_attach_wait_snk_run(const int port) } if (IS_ENABLED(CONFIG_USB_PE_SM) && - IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { + IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { hook_call_deferred(&pd_usb_billboard_deferred_data, - PD_T_AME); + PD_T_AME); } } } +static void tc_attach_wait_snk_exit(const int port) +{ + pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE); + pd_timer_disable(port, TC_TIMER_PD_DEBOUNCE); +} + /** * Attached.SNK, shared with Debug Accessory.SNK */ @@ -2185,8 +2455,11 @@ static void tc_attached_snk_entry(const int port) */ typec_select_pull(port, TYPEC_CC_RD); -#ifdef CONFIG_USB_PE_SM - if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) { + /* Inform the PPC and OCP module that a source is connected */ + tc_set_partner_role(port, PPC_DEV_SRC, OCP_NO_ACTION); + + if (IS_ENABLED(CONFIG_USB_PE_SM) && + TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) { /* Flipping power role - Disable AutoDischargeDisconnect */ tcpm_enable_auto_discharge_disconnect(port, 0); @@ -2196,7 +2469,7 @@ static void tc_attached_snk_entry(const int port) /* Change role to sink */ tc_set_power_role(port, PD_ROLE_SINK); tcpm_set_msg_header(port, tc[port].power_role, - tc[port].data_role); + tc[port].data_role); /* * Maintain VCONN supply state, whether ON or OFF, and its @@ -2204,44 +2477,90 @@ static void tc_attached_snk_entry(const int port) * AutoDischargeDisconnect until the swap is completed * and tc_pr_swap_complete is called. */ - } else -#endif - { + } else { /* Get connector orientation */ tcpm_get_cc(port, &cc1, &cc2); tc[port].polarity = get_snk_polarity(cc1, cc2); - pd_set_polarity(port, tc[port].polarity); + typec_set_polarity(port, tc[port].polarity); tc_set_data_role(port, PD_ROLE_UFP); hook_notify(HOOK_USB_PD_CONNECT); if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { - tc[port].typec_curr = - usb_get_typec_current_limit(tc[port].polarity, - cc1, cc2); - typec_set_input_current_limit(port, - tc[port].typec_curr, TYPE_C_VOLTAGE); - charge_manager_update_dualrole(port, - pd_is_port_partner_dualrole(port) ? - CAP_DUALROLE : CAP_DEDICATED); + tc[port].typec_curr = usb_get_typec_current_limit( + tc[port].polarity, cc1, cc2); + typec_set_input_current_limit(port, tc[port].typec_curr, + TYPE_C_VOLTAGE); + /* + * Start new connections as dedicated until source caps + * are received, at which point the PE will update the + * flag. + */ + charge_manager_update_dualrole(port, CAP_DEDICATED); + } + + /* Apply Rd */ + typec_update_cc(port); + + /* + * Attached.SNK - enable AutoDischargeDisconnect + * Do this after applying Rd to CC lines to avoid + * TCPC_REG_FAULT_STATUS_AUTO_DISCHARGE_FAIL (b/171567398) + */ + tcpm_enable_auto_discharge_disconnect(port, 1); + } + + pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE); + + /* Enable PD */ + if (IS_ENABLED(CONFIG_USB_PE_SM)) + tc_enable_pd(port, 1); + + if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) { + tcpm_debug_accessory(port, 1); + set_ccd_mode(port, 1); + } +} + +/* + * Check whether Vbus has been removed on this port, accounting for some Vbus + * debounce if FRS is enabled. + * + * Returns true if a new state was set and the calling run should exit. + */ +static bool tc_snk_check_vbus_removed(const int port) +{ + if (IS_ENABLED(CONFIG_USB_PD_FRS)) { + /* + * Debounce Vbus presence when FRS is enabled. Note that we may + * lose Vbus before the FRS signal comes in to let us know + * we're PR swapping, but we must still transition to unattached + * within tSinkDisconnect. + * + * We may safely re-use the Vbus debounce timer here + * since a PR swap would no longer be in progress when Vbus + * removal is checked. + */ + if (pd_check_vbus_level(port, VBUS_REMOVED)) { + if (pd_timer_is_disabled(port, + TC_TIMER_VBUS_DEBOUNCE)) { + pd_timer_enable(port, TC_TIMER_VBUS_DEBOUNCE, + PD_T_FRS_VBUS_DEBOUNCE); + } else if (pd_timer_is_expired( + port, TC_TIMER_VBUS_DEBOUNCE)) { + set_state_tc(port, TC_UNATTACHED_SNK); + return true; + } + } else { + pd_timer_disable(port, TC_TIMER_VBUS_DEBOUNCE); } - - /* Attached.SNK - enable AutoDischargeDisconnect */ - tcpm_enable_auto_discharge_disconnect(port, 1); - - /* Apply Rd */ - typec_update_cc(port); + } else if (pd_check_vbus_level(port, VBUS_REMOVED)) { + set_state_tc(port, TC_UNATTACHED_SNK); + return true; } - tc[port].cc_debounce = 0; - - /* Enable PD */ - if (IS_ENABLED(CONFIG_USB_PE_SM)) - tc_enable_pd(port, 1); - - if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) - tcpm_debug_accessory(port, 1); + return false; } static void tc_attached_snk_run(const int port) @@ -2279,9 +2598,10 @@ static void tc_attached_snk_run(const int port) * Debounce Vbus before we drop that we are doing a PR_Swap */ if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) && - tc[port].vbus_debounce_time < get_time().val) { + pd_timer_is_expired(port, TC_TIMER_VBUS_DEBOUNCE)) { /* PR Swap is no longer in progress */ TC_CLR_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS); + pd_timer_disable(port, TC_TIMER_VBUS_DEBOUNCE); /* * AutoDischargeDisconnect was turned off when we @@ -2302,17 +2622,8 @@ static void tc_attached_snk_run(const int port) /* * Detach detection */ - if (pd_check_vbus_level(port, VBUS_REMOVED)) { - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { - pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); - pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0); - pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, - 0, 0); - } - - set_state_tc(port, TC_UNATTACHED_SNK); + if (tc_snk_check_vbus_removed(port)) return; - } if (!pe_is_explicit_contract(port)) sink_power_sub_states(port); @@ -2344,16 +2655,17 @@ static void tc_attached_snk_run(const int port) /* Perform Data Role Swap */ tc_set_data_role(port, - tc[port].data_role == PD_ROLE_UFP ? - PD_ROLE_DFP : PD_ROLE_UFP); + tc[port].data_role == PD_ROLE_UFP ? + PD_ROLE_DFP : + PD_ROLE_UFP); } -#ifdef CONFIG_USBC_VCONN /* * VCONN Swap * UnorientedDebugAccessory.SRC shall not drive Vconn */ - if (!TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) { + if (IS_ENABLED(CONFIG_USBC_VCONN) && + !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) { if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON)) { TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON); @@ -2375,7 +2687,7 @@ static void tc_attached_snk_run(const int port) pe_vconn_swap_complete(port); } } -#endif + if (!TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) { /* * If the port supports Charge-Through VCONN-Powered USB @@ -2401,10 +2713,8 @@ static void tc_attached_snk_run(const int port) #else /* CONFIG_USB_PE_SM */ /* Detach detection */ - if (pd_check_vbus_level(port, VBUS_REMOVED)) { - set_state_tc(port, TC_UNATTACHED_SNK); + if (tc_snk_check_vbus_removed(port)) return; - } /* Run Sink Power Sub-State */ sink_power_sub_states(port); @@ -2428,7 +2738,7 @@ static void tc_attached_snk_exit(const int port) * happen in tc_cc_open_entry if that is the path we are * taking. */ - if (!TC_CHK_FLAG(port, TC_FLAGS_SUSPEND)) + if (!TC_CHK_FLAG(port, TC_FLAGS_REQUEST_SUSPEND)) tcpm_enable_auto_discharge_disconnect(port, 0); } @@ -2437,6 +2747,13 @@ static void tc_attached_snk_exit(const int port) /* Stop drawing power */ sink_stop_drawing_current(port); + + if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) + tcpm_debug_detach(port); + + pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE); + pd_timer_disable(port, TC_TIMER_TIMEOUT); + pd_timer_disable(port, TC_TIMER_VBUS_DEBOUNCE); } /** @@ -2444,6 +2761,8 @@ static void tc_attached_snk_exit(const int port) */ static void tc_unattached_src_entry(const int port) { + enum pd_data_role prev_data_role; + if (get_last_state_tc(port) != TC_UNATTACHED_SNK) { tc_detached(port); print_current_state(port); @@ -2457,46 +2776,40 @@ static void tc_unattached_src_entry(const int port) * * Both CC1 and CC2 pins shall be independently terminated to * ground through Rp. + * + * Restore default current limit Rp. + * + * Run any debug detaches needed before setting CC, as some TCPCs may + * require we set CC Open before changing power roles with a debug + * accessory. */ + tcpm_debug_detach(port); typec_select_pull(port, TYPEC_CC_RP); - typec_select_src_current_limit_rp(port, CONFIG_USB_PD_PULLUP); + typec_select_src_current_limit_rp( + port, typec_get_default_current_limit_rp(port)); typec_update_cc(port); + prev_data_role = tc[port].data_role; tc[port].data_role = PD_ROLE_DISCONNECTED; - /* - * Saved SRC_Capabilities are no longer valid on disconnect - */ - pd_set_src_caps(port, 0, NULL); - /* * When data role set events are used to enable BC1.2, then CC * detach events are used to notify BC1.2 that it can be powered * down. */ - if (IS_ENABLED(CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER)) - bc12_role_change_handler(port); - - if (IS_ENABLED(CONFIG_USBC_PPC)) { - /* There is no sink connected. */ - ppc_sink_is_connected(port, 0); + bc12_role_change_handler(port, prev_data_role, tc[port].data_role); - /* - * Clear the overcurrent event counter - * since we've detected a disconnect. - */ - ppc_clear_oc_event_counter(port); - } + tc_set_partner_role(port, PPC_DEV_DISCONNECTED, OCP_CLEAR); if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) charge_manager_update_dualrole(port, CAP_UNKNOWN); - if (IS_ENABLED(CONFIG_USB_PE_SM)) { - CLR_ALL_BUT_LPM_FLAGS(port); - tc_enable_pd(port, 0); - } +#ifdef CONFIG_USB_PE_SM + CLR_FLAGS_ON_DISCONNECT(port); + tc[port].ps_reset_state = PS_STATE0; +#endif - tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC; + pd_timer_enable(port, TC_TIMER_NEXT_ROLE_SWAP, PD_T_DRP_SRC); } static void tc_unattached_src_run(const int port) @@ -2512,12 +2825,12 @@ static void tc_unattached_src_run(const int port) } } - if (IS_ENABLED(CONFIG_USBC_PPC)) { + if (IS_ENABLED(CONFIG_USBC_OCP)) { /* * If the port is latched off, just continue to * monitor for a detach. */ - if (ppc_is_port_latched_off(port)) + if (usbc_ocp_is_port_latched_off(port)) return; } @@ -2534,7 +2847,7 @@ static void tc_unattached_src_run(const int port) */ if (cc_is_at_least_one_rd(cc1, cc2) || cc_is_audio_acc(cc1, cc2)) set_state_tc(port, TC_ATTACH_WAIT_SRC); - else if (get_time().val > tc[port].next_role_swap && + else if (pd_timer_is_expired(port, TC_TIMER_NEXT_ROLE_SWAP) && drp_state[port] != PD_DRP_FORCE_SOURCE && drp_state[port] != PD_DRP_FREEZE) set_state_tc(port, TC_UNATTACHED_SNK); @@ -2551,6 +2864,11 @@ static void tc_unattached_src_run(const int port) set_state_tc(port, TC_LOW_POWER_MODE); } +static void tc_unattached_src_exit(const int port) +{ + pd_timer_disable(port, TC_TIMER_NEXT_ROLE_SWAP); +} + /** * AttachWait.SRC * @@ -2574,9 +2892,12 @@ static void tc_attach_wait_src_run(const int port) /* Check for connection */ tcpm_get_cc(port, &cc1, &cc2); - /* Debug accessory */ - if (cc_is_snk_dbg_acc(cc1, cc2)) { - /* Debug accessory */ + if (cc_is_snk_dbg_acc(cc1, cc2) && board_is_dts_port(port)) { + /* + * Debug accessory. + * A debug accessory in a non-DTS port will be + * recognized by at_least_one_rd as UFP attached. + */ new_cc_state = PD_CC_UFP_DEBUG_ACC; } else if (cc_is_at_least_one_rd(cc1, cc2)) { /* UFP attached */ @@ -2586,19 +2907,22 @@ static void tc_attach_wait_src_run(const int port) new_cc_state = PD_CC_UFP_AUDIO_ACC; } else { /* No UFP */ - set_state_tc(port, TC_UNATTACHED_SNK); + if (drp_state[port] == PD_DRP_FORCE_SOURCE) + set_state_tc(port, TC_UNATTACHED_SRC); + else + set_state_tc(port, TC_UNATTACHED_SNK); return; } /* Debounce the cc state */ if (new_cc_state != tc[port].cc_state) { - tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE; + pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_CC_DEBOUNCE); tc[port].cc_state = new_cc_state; return; } /* Wait for CC debounce */ - if (get_time().val < tc[port].cc_debounce) + if (!pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE)) return; /* @@ -2624,6 +2948,11 @@ static void tc_attach_wait_src_run(const int port) } } +static void tc_attach_wait_src_exit(const int port) +{ + pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE); +} + /** * Attached.SRC, shared with UnorientedDebugAccessory.SRC */ @@ -2633,8 +2962,7 @@ static void tc_attached_src_entry(const int port) print_current_state(port); - /* Run function relies on timeout being 0 or meaningful */ - tc[port].timeout = 0; + pd_timer_disable(port, TC_TIMER_TIMEOUT); /* * Known state of attach is SRC. We need to apply this pull value @@ -2643,34 +2971,99 @@ static void tc_attached_src_entry(const int port) * * Both CC1 and CC2 pins shall be independently terminated to * pulled up through Rp. + * + * Set selected current limit in the hardware. */ typec_select_pull(port, TYPEC_CC_RP); - typec_select_src_current_limit_rp(port, CONFIG_USB_PD_PULLUP); + typec_set_source_current_limit(port, tc[port].select_current_limit_rp); + + if (IS_ENABLED(CONFIG_USB_PE_SM)) { + if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) { + /* Change role to source */ + tc_set_power_role(port, PD_ROLE_SOURCE); + tcpm_set_msg_header(port, tc[port].power_role, + tc[port].data_role); -#if defined(CONFIG_USB_PE_SM) - if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) { - /* Change role to source */ - tc_set_power_role(port, PD_ROLE_SOURCE); - tcpm_set_msg_header(port, - tc[port].power_role, tc[port].data_role); + /* Enable VBUS */ + tc_src_power_on(port); - /* Enable VBUS */ - tc_src_power_on(port); + /* Apply Rp */ + typec_update_cc(port); - /* Apply Rp */ - typec_update_cc(port); + /* + * Maintain VCONN supply state, whether ON or OFF, and + * its data role / usb mux connections. Do not + * re-enable AutoDischargeDisconnect until the swap is + * completed and tc_pr_swap_complete is called. + */ + } else { + /* + * Set up CC's, Vconn, and ADD before Vbus, as per + * Figure 4-24. DRP Initialization and Connection + * Detection in TCPCI r2 v1.2 specification. + */ + + /* Get connector orientation */ + tcpm_get_cc(port, &cc1, &cc2); + tc[port].polarity = get_src_polarity(cc1, cc2); + typec_set_polarity(port, tc[port].polarity); + + /* Attached.SRC - enable AutoDischargeDisconnect */ + tcpm_enable_auto_discharge_disconnect(port, 1); + + /* Apply Rp */ + typec_update_cc(port); + + /* + * Initial data role for sink is DFP + * This also sets the usb mux + */ + tc_set_data_role(port, PD_ROLE_DFP); + + /* + * Start sourcing Vconn before Vbus to ensure + * we are within USB Type-C Spec 1.4 tVconnON + * + * UnorientedDebugAccessory.SRC shall not drive Vconn + */ + if (IS_ENABLED(CONFIG_USBC_VCONN) && + !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) + set_vconn(port, 1); + + /* Enable VBUS */ + if (tc_src_power_on(port)) { + /* Stop sourcing Vconn if Vbus failed */ + if (IS_ENABLED(CONFIG_USBC_VCONN)) + set_vconn(port, 0); + + if (IS_ENABLED(CONFIG_USBC_SS_MUX)) + usb_mux_set(port, USB_PD_MUX_NONE, + USB_SWITCH_DISCONNECT, + tc[port].polarity); + } + tc_enable_pd(port, 0); + pd_timer_enable(port, TC_TIMER_TIMEOUT, + MAX(PD_POWER_SUPPLY_TURN_ON_DELAY, + PD_T_VCONN_STABLE)); + } + } else { /* - * Maintain VCONN supply state, whether ON or OFF, and its - * data role / usb mux connections. Do not re-enable - * AutoDischargeDisconnect until the swap is completed - * and tc_pr_swap_complete is called. + * Set up CC's, Vconn, and ADD before Vbus, as per + * Figure 4-24. DRP Initialization and Connection + * Detection in TCPCI r2 v1.2 specification. */ - } else { + /* Get connector orientation */ tcpm_get_cc(port, &cc1, &cc2); tc[port].polarity = get_src_polarity(cc1, cc2); - pd_set_polarity(port, tc[port].polarity); + typec_set_polarity(port, tc[port].polarity); + + /* Attached.SRC - enable AutoDischargeDisconnect */ + tcpm_enable_auto_discharge_disconnect(port, 1); + + /* Apply Rp */ + typec_update_cc(port); /* * Initial data role for sink is DFP @@ -2685,7 +3078,7 @@ static void tc_attached_src_entry(const int port) * UnorientedDebugAccessory.SRC shall not drive Vconn */ if (IS_ENABLED(CONFIG_USBC_VCONN) && - !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) + !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) set_vconn(port, 1); /* Enable VBUS */ @@ -2696,63 +3089,17 @@ static void tc_attached_src_entry(const int port) if (IS_ENABLED(CONFIG_USBC_SS_MUX)) usb_mux_set(port, USB_PD_MUX_NONE, - USB_SWITCH_DISCONNECT, tc[port].polarity); + USB_SWITCH_DISCONNECT, + tc[port].polarity); } - - /* Attached.SRC - enable AutoDischargeDisconnect */ - tcpm_enable_auto_discharge_disconnect(port, 1); - - /* Apply Rp */ - typec_update_cc(port); - - tc_enable_pd(port, 0); - tc[port].timeout = get_time().val + - MAX(PD_POWER_SUPPLY_TURN_ON_DELAY, PD_T_VCONN_STABLE); - } -#else - /* Get connector orientation */ - tcpm_get_cc(port, &cc1, &cc2); - tc[port].polarity = get_src_polarity(cc1, cc2); - pd_set_polarity(port, tc[port].polarity); - - /* - * Initial data role for sink is DFP - * This also sets the usb mux - */ - tc_set_data_role(port, PD_ROLE_DFP); - - /* - * Start sourcing Vconn before Vbus to ensure - * we are within USB Type-C Spec 1.4 tVconnON - * - * UnorientedDebugAccessory.SRC shall not drive Vconn - */ - if (IS_ENABLED(CONFIG_USBC_VCONN) && - !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) - set_vconn(port, 1); - - /* Enable VBUS */ - if (tc_src_power_on(port)) { - /* Stop sourcing Vconn if Vbus failed */ - if (IS_ENABLED(CONFIG_USBC_VCONN)) - set_vconn(port, 0); - - if (IS_ENABLED(CONFIG_USBC_SS_MUX)) - usb_mux_set(port, USB_PD_MUX_NONE, - USB_SWITCH_DISCONNECT, tc[port].polarity); } - /* Attached.SRC - enable AutoDischargeDisconnect */ - tcpm_enable_auto_discharge_disconnect(port, 1); - - /* Apply Rp */ - typec_update_cc(port); - -#endif /* CONFIG_USB_PE_SM */ + /* Inform PPC and OCP module that a sink is connected. */ + tc_set_partner_role(port, PPC_DEV_SNK, OCP_NO_ACTION); - /* Inform PPC that a sink is connected. */ - if (IS_ENABLED(CONFIG_USBC_PPC)) - ppc_sink_is_connected(port, 1); + /* Initialize type-C supplier to seed the charge manger */ + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) + typec_set_input_current_limit(port, 0, 0); /* * Only notify if we're not performing a power role swap. During a @@ -2762,8 +3109,21 @@ static void tc_attached_src_entry(const int port) hook_notify(HOOK_USB_PD_CONNECT); } - if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) + if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) { tcpm_debug_accessory(port, 1); + set_ccd_mode(port, 1); + } + + /* + * Some TCPCs require time to correctly return CC status after + * changing the ROLE_CONTROL register. Due to that, we have to ignore + * CC_NONE state until PD_T_SRC_DISCONNECT delay has elapsed. + * From the "Universal Serial Bus Type-C Cable and Connector + * Specification" Release 2.0 paragraph 4.5.2.2.9.2: + * The Source shall detect the SRC.Open state within tSRCDisconnect, + * but should detect it as quickly as possible + */ + pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_SRC_DISCONNECT); } static void tc_attached_src_run(const int port) @@ -2773,7 +3133,7 @@ static void tc_attached_src_run(const int port) /* Check for connection */ tcpm_get_cc(port, &cc1, &cc2); - if (tc[port].polarity) + if (polarity_rm_dts(tc[port].polarity)) cc1 = cc2; if (cc1 == TYPEC_CC_VOLT_OPEN) @@ -2792,22 +3152,21 @@ static void tc_attached_src_run(const int port) * Attached.SRC. */ if (tc[port].cc_state == PD_CC_NONE && - !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) && - !TC_CHK_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS)) { + pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE)) { + bool tryWait; + enum usb_tc_state new_tc_state = TC_UNATTACHED_SNK; - const bool tryWait = is_try_src_enabled(port) && - !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER); + if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) + tryWait = is_try_src_enabled(port) && + !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER); - if (IS_ENABLED(CONFIG_USB_PE_SM)) - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { - pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); - pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0); - pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, - 0, 0); - } + if (drp_state[port] == PD_DRP_FORCE_SOURCE) + new_tc_state = TC_UNATTACHED_SRC; + else if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) + new_tc_state = tryWait ? TC_TRY_WAIT_SNK : + TC_UNATTACHED_SNK; - set_state_tc(port, tryWait ? - TC_TRY_WAIT_SNK : TC_UNATTACHED_SNK); + set_state_tc(port, new_tc_state); return; } @@ -2816,9 +3175,9 @@ static void tc_attached_src_run(const int port) * Enable PD communications after power supply has fully * turned on */ - if (tc[port].timeout > 0 && get_time().val > tc[port].timeout) { + if (pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) { tc_enable_pd(port, 1); - tc[port].timeout = 0; + pd_timer_disable(port, TC_TIMER_TIMEOUT); } if (!tc_get_pd_enabled(port)) @@ -2829,7 +3188,8 @@ static void tc_attached_src_run(const int port) */ if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) { /* Ignoring Hard Resets while the power supply is resetting.*/ - if (get_time().val < tc[port].timeout) + if (!pd_timer_is_disabled(port, TC_TIMER_TIMEOUT) && + !pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) return; if (tc_perform_src_hard_reset(port)) @@ -2858,8 +3218,9 @@ static void tc_attached_src_run(const int port) /* Perform Data Role Swap */ tc_set_data_role(port, - tc[port].data_role == PD_ROLE_DFP ? - PD_ROLE_UFP : PD_ROLE_DFP); + tc[port].data_role == PD_ROLE_DFP ? + PD_ROLE_UFP : + PD_ROLE_DFP); } /* @@ -2867,7 +3228,7 @@ static void tc_attached_src_run(const int port) * UnorientedDebugAccessory.SRC shall not drive Vconn */ if (IS_ENABLED(CONFIG_USBC_VCONN) && - !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) { + !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) { /* * VCONN Swap Request */ @@ -2876,7 +3237,7 @@ static void tc_attached_src_run(const int port) set_vconn(port, 1); pe_vconn_swap_complete(port); } else if (TC_CHK_FLAG(port, - TC_FLAGS_REQUEST_VC_SWAP_OFF)) { + TC_FLAGS_REQUEST_VC_SWAP_OFF)) { TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_OFF); set_vconn(port, 0); pe_vconn_swap_complete(port); @@ -2902,16 +3263,23 @@ static void tc_attached_src_run(const int port) * applied. */ if (!TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER) && - TC_CHK_FLAG(port, TC_FLAGS_CTVPD_DETECTED)) { - TC_CLR_FLAG(port, TC_FLAGS_CTVPD_DETECTED); - - /* Clear TC_FLAGS_DISC_IDENT_IN_PROGRESS */ - TC_CLR_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS); - + TC_CHK_FLAG(port, TC_FLAGS_CTVPD_DETECTED)) { set_state_tc(port, TC_CT_UNATTACHED_SNK); } } #endif + + if (TC_CHK_FLAG(port, TC_FLAGS_UPDATE_CURRENT)) { + TC_CLR_FLAG(port, TC_FLAGS_UPDATE_CURRENT); + typec_set_source_current_limit( + port, tc[port].select_current_limit_rp); + pd_update_contract(port); + + /* Update Rp if no contract is present */ + if (!IS_ENABLED(CONFIG_USB_PE_SM) || + !pe_is_explicit_contract(port)) + typec_update_cc(port); + } } static void tc_attached_src_exit(const int port) @@ -2926,13 +3294,26 @@ static void tc_attached_src_exit(const int port) /* Attached.SRC exit - disable AutoDischargeDisconnect */ tcpm_enable_auto_discharge_disconnect(port, 0); - /* Disable VCONN if not power role swapping */ - if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON)) + /* + * Disable VCONN if not power role swapping and + * a CTVPD was not detected + */ + if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON) && + !TC_CHK_FLAG(port, TC_FLAGS_CTVPD_DETECTED)) set_vconn(port, 0); } + /* Clear CTVPD detected after checking for Vconn */ + TC_CLR_FLAG(port, TC_FLAGS_CTVPD_DETECTED); + /* Clear PR swap flag after checking for Vconn */ TC_CLR_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP); + + if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) + tcpm_debug_detach(port); + + pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE); + pd_timer_disable(port, TC_TIMER_TIMEOUT); } static __maybe_unused void check_drp_connection(const int port) @@ -2948,14 +3329,14 @@ static __maybe_unused void check_drp_connection(const int port) tc[port].drp_sink_time = get_time().val; /* Get the next toggle state */ - next_state = drp_auto_toggle_next_state(&tc[port].drp_sink_time, - tc[port].power_role, drp_state[port], cc1, cc2, - tcpm_auto_toggle_supported(port)); + next_state = drp_auto_toggle_next_state( + &tc[port].drp_sink_time, tc[port].power_role, drp_state[port], + cc1, cc2, tcpm_auto_toggle_supported(port)); if (next_state == DRP_TC_DEFAULT) - next_state = (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE) - ? DRP_TC_UNATTACHED_SRC - : DRP_TC_UNATTACHED_SNK; + next_state = (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE) ? + DRP_TC_UNATTACHED_SRC : + DRP_TC_UNATTACHED_SNK; switch (next_state) { case DRP_TC_UNATTACHED_SNK: @@ -2983,12 +3364,14 @@ static __maybe_unused void check_drp_connection(const int port) } } -#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE /** * DrpAutoToggle */ -static void tc_drp_auto_toggle_entry(const int port) +__maybe_unused static void tc_drp_auto_toggle_entry(const int port) { + if (!IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE)) + assert(0); + print_current_state(port); /* @@ -2996,11 +3379,15 @@ static void tc_drp_auto_toggle_entry(const int port) * for the minimum of DRP SNK or SRC so the first toggle cause by * transition into auto toggle doesn't violate spec timing. */ - tc[port].timeout = get_time().val + MAX(PD_T_DRP_SNK, PD_T_DRP_SRC); + pd_timer_enable(port, TC_TIMER_TIMEOUT, + MAX(PD_T_DRP_SNK, PD_T_DRP_SRC)); } -static void tc_drp_auto_toggle_run(const int port) +__maybe_unused static void tc_drp_auto_toggle_run(const int port) { + if (!IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE)) + assert(0); + /* * A timer is running, but if a connection comes in while waiting * then allow that to take higher priority. @@ -3008,11 +3395,11 @@ static void tc_drp_auto_toggle_run(const int port) if (TC_CHK_FLAG(port, TC_FLAGS_CHECK_CONNECTION)) check_drp_connection(port); - else if (tc[port].timeout != TIMER_DISABLED) { - if (tc[port].timeout > get_time().val) + else if (!pd_timer_is_disabled(port, TC_TIMER_TIMEOUT)) { + if (!pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) return; - tc[port].timeout = TIMER_DISABLED; + pd_timer_disable(port, TC_TIMER_TIMEOUT); tcpm_enable_drp_toggle(port); if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER)) { @@ -3020,26 +3407,33 @@ static void tc_drp_auto_toggle_run(const int port) } } } -#endif /* CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE */ -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER -static void tc_low_power_mode_entry(const int port) +__maybe_unused static void tc_drp_auto_toggle_exit(const int port) +{ + pd_timer_disable(port, TC_TIMER_TIMEOUT); +} + +__maybe_unused static void tc_low_power_mode_entry(const int port) { + if (!IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER)) + assert(0); + print_current_state(port); - tc[port].low_power_time = get_time().val + PD_LPM_DEBOUNCE_US; - tc[port].low_power_exit_time = 0; + pd_timer_enable(port, TC_TIMER_LOW_POWER_TIME, PD_LPM_DEBOUNCE_US); } -static void tc_low_power_mode_run(const int port) +__maybe_unused static void tc_low_power_mode_run(const int port) { - if (TC_CHK_FLAG(port, TC_FLAGS_CHECK_CONNECTION)) { - uint64_t now = get_time().val; + if (!IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER)) + assert(0); + if (TC_CHK_FLAG(port, TC_FLAGS_CHECK_CONNECTION)) { tc_start_event_loop(port); - if (tc[port].low_power_exit_time == 0) { - tc[port].low_power_exit_time = now - + PD_LPM_EXIT_DEBOUNCE_US; - } else if (now > tc[port].low_power_exit_time) { + if (pd_timer_is_disabled(port, TC_TIMER_LOW_POWER_EXIT_TIME)) { + pd_timer_enable(port, TC_TIMER_LOW_POWER_EXIT_TIME, + PD_LPM_EXIT_DEBOUNCE_US); + } else if (pd_timer_is_expired(port, + TC_TIMER_LOW_POWER_EXIT_TIME)) { CPRINTS("C%d: Exit Low Power Mode", port); check_drp_connection(port); } @@ -3047,9 +3441,10 @@ static void tc_low_power_mode_run(const int port) } if (tc[port].tasks_preventing_lpm) - tc[port].low_power_time = get_time().val + PD_LPM_DEBOUNCE_US; + pd_timer_enable(port, TC_TIMER_LOW_POWER_TIME, + PD_LPM_DEBOUNCE_US); - if (get_time().val > tc[port].low_power_time) { + if (pd_timer_is_expired(port, TC_TIMER_LOW_POWER_TIME)) { CPRINTS("C%d: TCPC Enter Low Power Mode", port); TC_SET_FLAG(port, TC_FLAGS_LPM_ENGAGED); TC_SET_FLAG(port, TC_FLAGS_LPM_TRANSITION); @@ -3057,11 +3452,15 @@ static void tc_low_power_mode_run(const int port) TC_CLR_FLAG(port, TC_FLAGS_LPM_TRANSITION); tc_pause_event_loop(port); - tc[port].low_power_exit_time = 0; + pd_timer_disable(port, TC_TIMER_LOW_POWER_EXIT_TIME); } } -#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */ +__maybe_unused static void tc_low_power_mode_exit(const int port) +{ + pd_timer_disable(port, TC_TIMER_LOW_POWER_TIME); + pd_timer_disable(port, TC_TIMER_LOW_POWER_EXIT_TIME); +} /** * Try.SRC @@ -3077,8 +3476,8 @@ static void tc_try_src_entry(const int port) print_current_state(port); tc[port].cc_state = PD_CC_UNSET; - tc[port].try_wait_debounce = get_time().val + PD_T_DRP_TRY; - tc[port].timeout = get_time().val + PD_T_TRY_TIMEOUT; + pd_timer_enable(port, TC_TIMER_TRY_WAIT_DEBOUNCE, PD_T_DRP_TRY); + pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_T_TRY_TIMEOUT); /* * We are a SNK but would prefer to be a SRC. Set the pull to @@ -3088,7 +3487,9 @@ static void tc_try_src_entry(const int port) * ground through Rp. */ typec_select_pull(port, TYPEC_CC_RP); - typec_select_src_current_limit_rp(port, CONFIG_USB_PD_PULLUP); + + typec_select_src_current_limit_rp( + port, typec_get_default_current_limit_rp(port)); /* Apply Rp */ typec_update_cc(port); @@ -3103,7 +3504,7 @@ static void tc_try_src_run(const int port) tcpm_get_cc(port, &cc1, &cc2); if ((cc1 == TYPEC_CC_VOLT_RD && cc2 != TYPEC_CC_VOLT_RD) || - (cc1 != TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD)) + (cc1 != TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD)) new_cc_state = PD_CC_UFP_ATTACHED; else new_cc_state = PD_CC_NONE; @@ -3111,7 +3512,7 @@ static void tc_try_src_run(const int port) /* Debounce the cc state */ if (new_cc_state != tc[port].cc_state) { tc[port].cc_state = new_cc_state; - tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE; + pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_CC_DEBOUNCE); } /* @@ -3119,8 +3520,8 @@ static void tc_try_src_run(const int port) * detected on exactly one of the CC1 or CC2 pins for at least * tTryCCDebounce. */ - if (get_time().val > tc[port].cc_debounce && - new_cc_state == PD_CC_UFP_ATTACHED) + if (new_cc_state == PD_CC_UFP_ATTACHED && + pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE)) set_state_tc(port, TC_ATTACHED_SRC); /* @@ -3129,14 +3530,21 @@ static void tc_try_src_run(const int port) * or after tTryTimeout and the SRC.Rd state has not been detected. */ if (new_cc_state == PD_CC_NONE) { - if ((get_time().val > tc[port].try_wait_debounce && + if ((pd_timer_is_expired(port, TC_TIMER_TRY_WAIT_DEBOUNCE) && pd_check_vbus_level(port, VBUS_SAFE0V)) || - get_time().val > tc[port].timeout) { + pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) { set_state_tc(port, TC_TRY_WAIT_SNK); } } } +static void tc_try_src_exit(const int port) +{ + pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE); + pd_timer_disable(port, TC_TIMER_TIMEOUT); + pd_timer_disable(port, TC_TIMER_TRY_WAIT_DEBOUNCE); +} + /** * TryWait.SNK * @@ -3151,7 +3559,7 @@ static void tc_try_wait_snk_entry(const int port) tc_enable_pd(port, 0); tc[port].cc_state = PD_CC_UNSET; - tc[port].try_wait_debounce = get_time().val + PD_T_CC_DEBOUNCE; + pd_timer_enable(port, TC_TIMER_TRY_WAIT_DEBOUNCE, PD_T_CC_DEBOUNCE); /* * We were a SNK, tried to be a SRC and it didn't work out. Try to @@ -3184,15 +3592,15 @@ static void tc_try_wait_snk_run(const int port) /* Debounce the cc state */ if (new_cc_state != tc[port].cc_state) { tc[port].cc_state = new_cc_state; - tc[port].pd_debounce = get_time().val + PD_T_PD_DEBOUNCE; + pd_timer_enable(port, TC_TIMER_PD_DEBOUNCE, PD_T_PD_DEBOUNCE); } /* * The port shall transition to Unattached.SNK when the state of both * of the CC1 and CC2 pins is SNK.Open for at least tPDDebounce. */ - if ((get_time().val > tc[port].pd_debounce) && - (new_cc_state == PD_CC_NONE)) { + if (new_cc_state == PD_CC_NONE && + pd_timer_is_expired(port, TC_TIMER_PD_DEBOUNCE)) { set_state_tc(port, TC_UNATTACHED_SNK); return; } @@ -3201,19 +3609,26 @@ static void tc_try_wait_snk_run(const int port) * The port shall transition to Attached.SNK after tCCDebounce if or * when VBUS is detected. */ - if (get_time().val > tc[port].try_wait_debounce && + if (pd_timer_is_expired(port, TC_TIMER_TRY_WAIT_DEBOUNCE) && pd_is_vbus_present(port)) set_state_tc(port, TC_ATTACHED_SNK); } +static void tc_try_wait_snk_exit(const int port) +{ + pd_timer_disable(port, TC_TIMER_PD_DEBOUNCE); + pd_timer_disable(port, TC_TIMER_TRY_WAIT_DEBOUNCE); +} #endif -#if defined(CONFIG_USB_PE_SM) /* * CTUnattached.SNK */ -static void tc_ct_unattached_snk_entry(int port) +__maybe_unused static void tc_ct_unattached_snk_entry(int port) { + if (!IS_ENABLED(CONFIG_USB_PE_SM)) + assert(0); + print_current_state(port); /* @@ -3221,7 +3636,6 @@ static void tc_ct_unattached_snk_entry(int port) * ground through Rd. */ typec_select_pull(port, TYPEC_CC_RD); - typec_select_src_current_limit_rp(port, CONFIG_USB_PD_PULLUP); typec_update_cc(port); tc[port].cc_state = PD_CC_UNSET; @@ -3236,22 +3650,26 @@ static void tc_ct_unattached_snk_entry(int port) */ tc_enable_pd(port, 0); - tc[port].timeout = get_time().val + PD_POWER_SUPPLY_TURN_ON_DELAY; + pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_POWER_SUPPLY_TURN_ON_DELAY); } -static void tc_ct_unattached_snk_run(int port) +__maybe_unused static void tc_ct_unattached_snk_run(int port) { enum tcpc_cc_voltage_status cc1; enum tcpc_cc_voltage_status cc2; enum pd_cc_states new_cc_state; - if (tc[port].timeout > 0 && get_time().val > tc[port].timeout) { - tc_enable_pd(port, 1); - tc[port].timeout = 0; - } + if (!IS_ENABLED(CONFIG_USB_PE_SM)) + assert(0); - if (tc[port].timeout > 0) - return; + if (!pd_timer_is_disabled(port, TC_TIMER_TIMEOUT)) { + if (pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) { + tc_enable_pd(port, 1); + pd_timer_disable(port, TC_TIMER_TIMEOUT); + } else { + return; + } + } /* Wait until Protocol Layer is ready */ if (!prl_is_running(port)) @@ -3279,23 +3697,16 @@ static void tc_ct_unattached_snk_run(int port) /* Debounce the cc state */ if (new_cc_state != tc[port].cc_state) { tc[port].cc_state = new_cc_state; - tc[port].cc_debounce = get_time().val + PD_T_VPDDETACH; + pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_VPDDETACH); } /* * The port shall transition to Unattached.SNK if the state of * the CC pin is SNK.Open for tVPDDetach after VBUS is vSafe0V. */ - if (get_time().val > tc[port].cc_debounce) { + else if (pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE)) { if (new_cc_state == PD_CC_NONE && pd_check_vbus_level(port, VBUS_SAFE0V)) { - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { - pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); - pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0); - pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, - 0, 0); - } - set_state_tc(port, TC_UNATTACHED_SNK); return; } @@ -3308,19 +3719,38 @@ static void tc_ct_unattached_snk_run(int port) set_state_tc(port, TC_CT_ATTACHED_SNK); } +__maybe_unused static void tc_ct_unattached_snk_exit(int port) +{ + pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE); + pd_timer_disable(port, TC_TIMER_TIMEOUT); +} + /** * CTAttached.SNK */ -static void tc_ct_attached_snk_entry(int port) +__maybe_unused static void tc_ct_attached_snk_entry(int port) { + if (!IS_ENABLED(CONFIG_USB_PE_SM)) + assert(0); + print_current_state(port); /* The port shall reject a VCONN swap request. */ TC_SET_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP); + + /* + * Type-C r 2.2: The Host shall not advertise dual-role data or + * dual-role power in its SourceCapability or SinkCapability messages - + * Host changes its advertised capabilities to UFP role/sink only role. + */ + tc_set_data_role(port, PD_ROLE_UFP); } -static void tc_ct_attached_snk_run(int port) +__maybe_unused static void tc_ct_attached_snk_run(int port) { + if (!IS_ENABLED(CONFIG_USB_PE_SM)) + assert(0); + /* * Hard Reset is sent when the PE layer is disabled due to a * CTVPD connection. @@ -3350,14 +3780,16 @@ static void tc_ct_attached_snk_run(int port) sink_power_sub_states(port); } -static void tc_ct_attached_snk_exit(int port) +__maybe_unused static void tc_ct_attached_snk_exit(int port) { + if (!IS_ENABLED(CONFIG_USB_PE_SM)) + assert(0); + /* Stop drawing power */ sink_stop_drawing_current(port); TC_CLR_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP); } -#endif /* CONFIG_USB_PE_SM */ /** * Super State CC_RD @@ -3373,7 +3805,6 @@ static void tc_cc_rd_entry(const int port) tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role); } - /** * Super State CC_RP */ @@ -3412,24 +3843,26 @@ static void tc_cc_open_entry(const int port) if (battery_is_present()) tcpm_enable_auto_discharge_disconnect(port, 0); - /* We may brown out after applying CC open, so flush console first. */ + /* + * We may brown out after applying CC open, so flush console first. + * Console flush can take a long time, so if we aren't in danger of + * browning out, don't do it so we can meet certain compliance timing + * requirements. + */ CPRINTS("C%d: Applying CC Open!", port); - cflush(); + if (!battery_is_present()) + cflush(); /* Remove terminations from CC */ typec_select_pull(port, TYPEC_CC_OPEN); typec_update_cc(port); - if (IS_ENABLED(CONFIG_USBC_PPC)) { - /* There is no sink connected. */ - ppc_sink_is_connected(port, 0); - - /* - * Clear the overcurrent event counter - * since we've detected a disconnect. - */ - ppc_clear_oc_event_counter(port); - } + /* + * While we've disconnected the partner, leave any OCP counts in place + * to persist over ErrorRecovery + */ + tc_set_partner_role(port, PPC_DEV_DISCONNECTED, OCP_NO_ACTION); + tc_detached(port); } void tc_set_debug_level(enum debug_level debug_level) @@ -3439,20 +3872,47 @@ void tc_set_debug_level(enum debug_level debug_level) #endif } +void tc_usb_firmware_fw_update_limited_run(int port) +{ + TC_SET_FLAG(port, TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN); + task_wake(PD_PORT_TO_TASK_ID(port)); +} + +void tc_usb_firmware_fw_update_run(int port) +{ + TC_SET_FLAG(port, TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN); + task_wake(PD_PORT_TO_TASK_ID(port)); +} + void tc_run(const int port) { /* - * If pd_set_suspend SUSPEND state changes to - * be suspended then we need to go directly to - * DISABLED + * If pd_set_suspend set TC_FLAGS_REQUEST_SUSPEND, go directly to + * TC_DISABLED. */ - if (TC_CHK_FLAG(port, TC_FLAGS_SUSPEND)) { + if (get_state_tc(port) != TC_DISABLED && + TC_CHK_FLAG(port, TC_FLAGS_REQUEST_SUSPEND)) { /* Invalidate a contract, if there is one */ - pe_invalidate_explicit_contract(port); + if (IS_ENABLED(CONFIG_USB_PE_SM)) + pe_invalidate_explicit_contract(port); set_state_tc(port, TC_DISABLED); } + /* If error recovery has been requested, transition now */ + if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_ERROR_RECOVERY)) { + if (IS_ENABLED(CONFIG_USB_PE_SM)) + pe_invalidate_explicit_contract(port); + set_state_tc(port, TC_ERROR_RECOVERY); + } + + if (IS_ENABLED(CONFIG_USBC_RETIMER_FW_UPDATE)) { + if (TC_CHK_FLAG(port, TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN)) { + TC_CLR_FLAG(port, TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN); + usb_retimer_fw_update_process_op_cb(port); + } + } + run_state(port, &tc[port].ctx); } @@ -3461,10 +3921,17 @@ static void pd_chipset_resume(void) int i; for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - pd_set_dual_role_and_event(i, - PD_DRP_TOGGLE_ON, - PD_EVENT_UPDATE_DUAL_ROLE - | PD_EVENT_POWER_STATE_CHANGE); + if (IS_ENABLED(CONFIG_USB_PE_SM)) + pd_resume_check_pr_swap_needed(i); + + pd_set_dual_role_and_event(i, pd_get_drp_state_in_s0(), + PD_EVENT_UPDATE_DUAL_ROLE | + PD_EVENT_POWER_STATE_CHANGE); + + if (tc[i].data_role == PD_ROLE_DFP) { + pd_send_alert_msg(i, ADO_EXTENDED_ALERT_EVENT | + ADO_POWER_STATE_CHANGE); + } } CPRINTS("PD:S3->S0"); @@ -3476,26 +3943,65 @@ static void pd_chipset_suspend(void) int i; for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - pd_set_dual_role_and_event(i, - pd_get_drp_state_in_suspend(), - PD_EVENT_UPDATE_DUAL_ROLE - | PD_EVENT_POWER_STATE_CHANGE); + pd_set_dual_role_and_event(i, pd_get_drp_state_in_suspend(), + PD_EVENT_UPDATE_DUAL_ROLE | + PD_EVENT_POWER_STATE_CHANGE); + + if (tc[i].data_role == PD_ROLE_DFP) { + pd_send_alert_msg(i, ADO_EXTENDED_ALERT_EVENT | + ADO_POWER_STATE_CHANGE); + } } CPRINTS("PD:S0->S3"); } DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pd_chipset_suspend, HOOK_PRIO_DEFAULT); +static void pd_chipset_reset(void) +{ + int i; + + if (!IS_ENABLED(CONFIG_USB_PE_SM)) + return; + + for (i = 0; i < board_get_usb_pd_port_count(); i++) { + enum tcpci_msg_type tx; + + /* Do not notify the AP of irrelevant past Hard Resets. */ + pd_clear_events(i, PD_STATUS_EVENT_HARD_RESET); + + /* + * Re-set events for SOP and SOP' discovery complete so the + * kernel knows to consume discovery information for them. + */ + for (tx = TCPCI_MSG_SOP; tx <= TCPCI_MSG_SOP_PRIME; tx++) { + if (pd_get_identity_discovery(i, tx) != + PD_DISC_NEEDED && + pd_get_svids_discovery(i, tx) != PD_DISC_NEEDED && + pd_get_modes_discovery(i, tx) != PD_DISC_NEEDED) + pd_notify_event( + i, + tx == TCPCI_MSG_SOP ? + PD_STATUS_EVENT_SOP_DISC_DONE : + PD_STATUS_EVENT_SOP_PRIME_DISC_DONE); + } + + /* Exit mode so AP can enter mode again after reset */ + if (IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY)) + dpm_set_mode_exit_request(i); + } +} +DECLARE_HOOK(HOOK_CHIPSET_RESET, pd_chipset_reset, HOOK_PRIO_DEFAULT); + static void pd_chipset_startup(void) { int i; for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - set_usb_mux_with_current_data_role(i); - pd_set_dual_role_and_event(i, - pd_get_drp_state_in_suspend(), - PD_EVENT_UPDATE_DUAL_ROLE - | PD_EVENT_POWER_STATE_CHANGE); + TC_SET_FLAG(i, TC_FLAGS_UPDATE_USB_MUX); + pd_set_dual_role_and_event(i, pd_get_drp_state_in_suspend(), + PD_EVENT_UPDATE_DUAL_ROLE | + PD_EVENT_POWER_STATE_CHANGE); /* * Request port discovery to restore any * alt modes. @@ -3504,6 +4010,11 @@ static void pd_chipset_startup(void) */ if (IS_ENABLED(CONFIG_USB_PE_SM)) pd_dpm_request(i, DPM_REQUEST_PORT_DISCOVERY); + + if (tc[i].data_role == PD_ROLE_DFP) { + pd_send_alert_msg(i, ADO_EXTENDED_ALERT_EVENT | + ADO_POWER_STATE_CHANGE); + } } CPRINTS("PD:S5->S3"); @@ -3515,16 +4026,42 @@ static void pd_chipset_shutdown(void) int i; for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - pd_set_dual_role_and_event(i, - PD_DRP_FORCE_SINK, - PD_EVENT_UPDATE_DUAL_ROLE - | PD_EVENT_POWER_STATE_CHANGE); + TC_SET_FLAG(i, TC_FLAGS_UPDATE_USB_MUX); + pd_set_dual_role_and_event(i, PD_DRP_FORCE_SINK, + PD_EVENT_UPDATE_DUAL_ROLE | + PD_EVENT_POWER_STATE_CHANGE); + + if (tc[i].data_role == PD_ROLE_DFP) { + pd_send_alert_msg(i, ADO_EXTENDED_ALERT_EVENT | + ADO_POWER_STATE_CHANGE); + } } CPRINTS("PD:S3->S5"); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pd_chipset_shutdown, HOOK_PRIO_DEFAULT); +static void pd_set_power_change(void) +{ + int i; + + for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { + task_set_event(PD_PORT_TO_TASK_ID(i), + PD_EVENT_POWER_STATE_CHANGE); + } +} +DECLARE_DEFERRED(pd_set_power_change); + +static void pd_chipset_hard_off(void) +{ + /* + * Wait 1 second to check our Vconn sourcing status, as the power rails + * which were supporting it may take some time to change after entering + * G3. + */ + hook_call_deferred(&pd_set_power_change_data, 1 * SECOND); +} +DECLARE_HOOK(HOOK_CHIPSET_HARD_OFF, pd_chipset_hard_off, HOOK_PRIO_DEFAULT); /* * Type-C State Hierarchy (Sub-States are listed inside the boxes) @@ -3545,7 +4082,7 @@ DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pd_chipset_shutdown, HOOK_PRIO_DEFAULT); * TC_ATTACHED_SNK TC_ATTACHED_SRC TC_DRP_AUTO_TOGGLE TC_LOW_POWER_MODE * */ -static const struct usb_state tc_states[] = { +static __const_data const struct usb_state tc_states[] = { /* Super States */ [TC_CC_OPEN] = { .entry = tc_cc_open_entry, @@ -3566,16 +4103,19 @@ static const struct usb_state tc_states[] = { [TC_ERROR_RECOVERY] = { .entry = tc_error_recovery_entry, .run = tc_error_recovery_run, + .exit = tc_error_recovery_exit, .parent = &tc_states[TC_CC_OPEN], }, [TC_UNATTACHED_SNK] = { .entry = tc_unattached_snk_entry, .run = tc_unattached_snk_run, + .exit = tc_unattached_snk_exit, .parent = &tc_states[TC_CC_RD], }, [TC_ATTACH_WAIT_SNK] = { .entry = tc_attach_wait_snk_entry, .run = tc_attach_wait_snk_run, + .exit = tc_attach_wait_snk_exit, .parent = &tc_states[TC_CC_RD], }, [TC_ATTACHED_SNK] = { @@ -3586,11 +4126,13 @@ static const struct usb_state tc_states[] = { [TC_UNATTACHED_SRC] = { .entry = tc_unattached_src_entry, .run = tc_unattached_src_run, + .exit = tc_unattached_src_exit, .parent = &tc_states[TC_CC_RP], }, [TC_ATTACH_WAIT_SRC] = { .entry = tc_attach_wait_src_entry, .run = tc_attach_wait_src_run, + .exit = tc_attach_wait_src_exit, .parent = &tc_states[TC_CC_RP], }, [TC_ATTACHED_SRC] = { @@ -3602,11 +4144,13 @@ static const struct usb_state tc_states[] = { [TC_TRY_SRC] = { .entry = tc_try_src_entry, .run = tc_try_src_run, + .exit = tc_try_src_exit, .parent = &tc_states[TC_CC_RP], }, [TC_TRY_WAIT_SNK] = { .entry = tc_try_wait_snk_entry, .run = tc_try_wait_snk_run, + .exit = tc_try_wait_snk_exit, .parent = &tc_states[TC_CC_RD], }, #endif /* CONFIG_USB_PD_TRY_SRC */ @@ -3614,18 +4158,21 @@ static const struct usb_state tc_states[] = { [TC_DRP_AUTO_TOGGLE] = { .entry = tc_drp_auto_toggle_entry, .run = tc_drp_auto_toggle_run, + .exit = tc_drp_auto_toggle_exit, }, #endif /* CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE */ #ifdef CONFIG_USB_PD_TCPC_LOW_POWER [TC_LOW_POWER_MODE] = { .entry = tc_low_power_mode_entry, .run = tc_low_power_mode_run, + .exit = tc_low_power_mode_exit, }, #endif /* CONFIG_USB_PD_TCPC_LOW_POWER */ #ifdef CONFIG_USB_PE_SM [TC_CT_UNATTACHED_SNK] = { .entry = tc_ct_unattached_snk_entry, .run = tc_ct_unattached_snk_run, + .exit = tc_ct_unattached_snk_exit, }, [TC_CT_ATTACHED_SNK] = { .entry = tc_ct_attached_snk_entry, @@ -3644,6 +4191,5 @@ const struct test_sm_data test_tc_sm_data[] = { .names_size = ARRAY_SIZE(tc_state_names), }, }; -BUILD_ASSERT(ARRAY_SIZE(tc_states) == ARRAY_SIZE(tc_state_names)); const int test_tc_sm_data_size = ARRAY_SIZE(test_tc_sm_data); #endif diff --git a/common/usbc/usb_tc_vpd_sm.c b/common/usbc/usb_tc_vpd_sm.c index 7d25001813..1a820c4003 100644 --- a/common/usbc/usb_tc_vpd_sm.c +++ b/common/usbc/usb_tc_vpd_sm.c @@ -1,30 +1,32 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "system.h" #include "task.h" -#include "tcpm.h" +#include "tcpm/tcpm.h" +#include "typec_control.h" #include "usb_pd.h" -#include "usb_tc_sm.h" #include "usb_sm.h" +#include "usb_tc_sm.h" #include "vpd_api.h" /* USB Type-C VCONN Powered Device module */ #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USB, format, ##args) #else /* CONFIG_COMMON_RUNTIME */ #define CPRINTF(format, args...) #define CPRINTS(format, args...) #endif /* Type-C Layer Flags */ -#define TC_FLAGS_VCONN_ON BIT(0) +#define TC_FLAGS_VCONN_ON BIT(0) /** * This is the Type-C Port object that contains information needed to @@ -59,15 +61,15 @@ enum usb_tc_state { /* Forward declare the full list of states. This is indexed by usb_tc_state */ static const struct usb_state tc_states[]; -#ifdef CONFIG_COMMON_RUNTIME /* List of human readable state names for console debugging */ -static const char * const tc_state_names[] = { +__maybe_unused static const char *const tc_state_names[] = { +#ifdef CONFIG_COMMON_RUNTIME [TC_DISABLED] = "Disabled", [TC_UNATTACHED_SNK] = "Unattached.SNK", [TC_ATTACH_WAIT_SNK] = "AttachWait.SNK", [TC_ATTACHED_SNK] = "Attached.SNK", -}; #endif +}; /* Forward declare private, common functions */ static void set_state_tc(const int port, enum usb_tc_state new_state); @@ -269,11 +271,11 @@ static void tc_attach_wait_snk_run(const int port) if (tc[port].host_cc_state != host_new_cc_state) { tc[port].host_cc_state = host_new_cc_state; if (host_new_cc_state == PD_CC_DFP_ATTACHED) - tc[port].cc_debounce = get_time().val + - PD_T_CC_DEBOUNCE; + tc[port].cc_debounce = + get_time().val + PD_T_CC_DEBOUNCE; else - tc[port].cc_debounce = get_time().val + - PD_T_PD_DEBOUNCE; + tc[port].cc_debounce = + get_time().val + PD_T_PD_DEBOUNCE; return; } @@ -292,7 +294,7 @@ static void tc_attach_wait_snk_run(const int port) * CC2 pins is SNK.Open for at least tPDDebounce. */ if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED && - (vpd_is_vconn_present() || vpd_is_host_vbus_present())) + (vpd_is_vconn_present() || vpd_is_host_vbus_present())) set_state_tc(port, TC_ATTACHED_SNK); else if (tc[port].host_cc_state == PD_CC_NONE) set_state_tc(port, TC_UNATTACHED_SNK); @@ -307,7 +309,7 @@ static void tc_attached_snk_entry(const int port) /* Enable PD */ tc[port].pd_enable = 1; - pd_set_polarity(port, 0); + typec_set_polarity(port, 0); } static void tc_attached_snk_run(const int port) diff --git a/common/usbc/usbc_pd_policy.c b/common/usbc/usbc_pd_policy.c new file mode 100644 index 0000000000..6d82ed114c --- /dev/null +++ b/common/usbc/usbc_pd_policy.c @@ -0,0 +1,48 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "console.h" +#include "ec_commands.h" +#include "usb_pe_sm.h" +#include "usb_tc_sm.h" + +/* + * TODO(b:159715784): Implement a more robust solution + * to managing PD Policies. + */ + +/* + * Default Port Discovery DR Swap Policy. + * + * 1) If dr_swap_to_dfp_flag == true and port data role is UFP, + * transition to pe_drs_send_swap + */ +__overridable bool port_discovery_dr_swap_policy(int port, enum pd_data_role dr, + bool dr_swap_flag) +{ + if (dr_swap_flag && dr == PD_ROLE_UFP) + return true; + + /* Do not perform a DR swap */ + return false; +} + +/* + * Default Port Discovery VCONN Swap Policy. + * + * 1) If vconn_swap_to_on_flag == true, and vconn is currently off, + * 2) Sourcing VCONN is possible + * then transition to pe_vcs_send_swap + */ +__overridable bool port_discovery_vconn_swap_policy(int port, + bool vconn_swap_flag) +{ + if (IS_ENABLED(CONFIG_USBC_VCONN) && vconn_swap_flag && + !tc_is_vconn_src(port) && tc_check_vconn_swap(port)) + return true; + + /* Do not perform a VCONN swap */ + return false; +} diff --git a/common/usbc/usbc_task.c b/common/usbc/usbc_task.c index 624c55a651..5d68221b3e 100644 --- a/common/usbc/usbc_task.c +++ b/common/usbc/usbc_task.c @@ -1,16 +1,17 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "battery.h" #include "battery_smart.h" -#include "board.h" +#include "builtin/assert.h" #include "charge_manager.h" #include "charge_state.h" #include "chipset.h" #include "common.h" #include "console.h" +#include "cros_version.h" #include "ec_commands.h" #include "gpio.h" #include "hooks.h" @@ -18,24 +19,35 @@ #include "registers.h" #include "system.h" #include "task.h" +#include "tcpm/tcpm.h" #include "timer.h" -#include "util.h" #include "usb_charge.h" #include "usb_mux.h" #include "usb_pd.h" -#include "usb_prl_sm.h" -#include "tcpm.h" +#include "usb_pd_dpm_sm.h" +#include "usb_pd_timer.h" #include "usb_pe_sm.h" #include "usb_prl_sm.h" #include "usb_sm.h" #include "usb_tc_sm.h" #include "usbc_ppc.h" -#include "version.h" +#include "util.h" #define USBC_EVENT_TIMEOUT (5 * MSEC) +#define USBC_MIN_EVENT_TIMEOUT (1 * MSEC) -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* + * If CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT is not defined then + * _GPIO_CCD_MODE_ODL is not needed. Declare as extern so IS_ENABLED will work. + */ +#ifndef CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT +extern int _GPIO_CCD_MODE_ODL; +#else +#define _GPIO_CCD_MODE_ODL GPIO_CCD_MODE_ODL +#endif /* CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT */ static uint8_t paused[CONFIG_USB_PD_PORT_MAX_COUNT]; @@ -44,6 +56,11 @@ void tc_pause_event_loop(int port) paused[port] = 1; } +bool tc_event_loop_is_paused(int port) +{ + return paused[port]; +} + void tc_start_event_loop(int port) { /* @@ -52,7 +69,7 @@ void tc_start_event_loop(int port) */ if (paused[port]) { paused[port] = 0; - task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE, 0); + task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE); } } @@ -71,15 +88,40 @@ static void pd_task_init(int port) */ if (IS_ENABLED(CONFIG_HAS_TASK_PD_INT)) schedule_deferred_pd_interrupt(port); + + /* + * GPIO_CCD_MODE_ODL must be initialized with GPIO_ODR_HIGH + * when CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT is enabled + */ + if (IS_ENABLED(CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT)) + ASSERT(gpio_get_default_flags(_GPIO_CCD_MODE_ODL) & + GPIO_ODR_HIGH); +} + +static int pd_task_timeout(int port) +{ + int timeout; + + if (paused[port]) + timeout = -1; + else { + timeout = pd_timer_next_expiration(port); + if (timeout < 0 || timeout > USBC_EVENT_TIMEOUT) + timeout = USBC_EVENT_TIMEOUT; + else if (timeout < USBC_MIN_EVENT_TIMEOUT) + timeout = USBC_MIN_EVENT_TIMEOUT; + } + return timeout; } static bool pd_task_loop(int port) { /* wait for next event/packet or timeout expiration */ - const uint32_t evt = - task_wait_event(paused[port] - ? -1 - : USBC_EVENT_TIMEOUT); + const uint32_t evt = task_wait_event(pd_task_timeout(port)); + + /* Manage expired PD Timers on timeouts */ + if (evt & TASK_EVENT_TIMER) + pd_timer_manage_expired(port); /* * Re-use TASK_EVENT_RESET_DONE in tests to restart the USB task @@ -99,6 +141,10 @@ static bool pd_task_loop(int port) if (IS_ENABLED(CONFIG_USB_PD_TCPC)) tcpc_run(port, evt); + /* Run Device Policy Manager */ + if (IS_ENABLED(CONFIG_USB_DPM_SM)) + dpm_run(port, evt, tc_get_pd_enabled(port)); + /* Run policy engine state machine */ if (IS_ENABLED(CONFIG_USB_PE_SM)) pe_run(port, evt, tc_get_pd_enabled(port)); @@ -124,7 +170,12 @@ void pd_task(void *u) if (port >= board_get_usb_pd_port_count()) return; +#if CONFIG_USB_PD_STARTUP_DELAY_MS > 0 + msleep(CONFIG_USB_PD_STARTUP_DELAY_MS); +#endif + while (1) { + pd_timer_init(port); pd_task_init(port); /* As long as pd_task_loop returns true, keep running the loop. diff --git a/common/usbc_intr_task.c b/common/usbc_intr_task.c index ca410363f1..68190aff4b 100644 --- a/common/usbc_intr_task.c +++ b/common/usbc_intr_task.c @@ -1,51 +1,103 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* High-priority interrupt tasks implementations */ +/* + * TODO(b/272518464): Work around coreboot GCC preprocessor bug. + * #line marks the *next* line, so it is off by one. + */ +#line 13 + +#include "builtin/assert.h" +#include "common.h" +#include "compile_time_macros.h" #include "console.h" +#include "ec_commands.h" #include "task.h" +#include "tcpm/tcpm.h" #include "timer.h" -#include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_tcpm.h" -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#include + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) /* Events for pd_interrupt_handler_task */ -#define PD_PROCESS_INTERRUPT BIT(0) +#define PD_PROCESS_INTERRUPT BIT(0) /* - * Theoretically, we may need to support up to 480 USB-PD packets per second for - * intensive operations such as FW update over PD. This value has tested well - * preventing watchdog resets with a single bad port partner plugged in. + * Theoretically, we may need to support up to 1800 USB-PD packets per second + * for intensive operations such as BIST compliance tests. This value has tested + * well preventing watchdog resets with a single bad port partner plugged in. */ -#define ALERT_STORM_MAX_COUNT 480 -#define ALERT_STORM_INTERVAL SECOND +#define ALERT_STORM_MAX_COUNT 1800 +#define ALERT_STORM_INTERVAL SECOND static uint8_t pd_int_task_id[CONFIG_USB_PD_PORT_MAX_COUNT]; void schedule_deferred_pd_interrupt(const int port) { - task_set_event(pd_int_task_id[port], PD_PROCESS_INTERRUPT, 0); + /* + * Don't set event to idle task if task id is 0. This happens when + * not all the port have pd int task, the pd_int_task_id of port + * that doesn't have pd int task is 0. + */ + if (pd_int_task_id[port] != 0) + task_set_event(pd_int_task_id[port], PD_PROCESS_INTERRUPT); +} + +static struct { + int count; + timestamp_t time; +} storm_tracker[CONFIG_USB_PD_PORT_MAX_COUNT]; + +static void service_one_port(int port) +{ + timestamp_t now; + + tcpc_alert(port); + + now = get_time(); + if (timestamp_expired(storm_tracker[port].time, &now)) { + /* Reset timer into future */ + storm_tracker[port].time.val = now.val + ALERT_STORM_INTERVAL; + + /* + * Start at 1 since we are processing an interrupt right + * now + */ + storm_tracker[port].count = 1; + } else if (++storm_tracker[port].count > ALERT_STORM_MAX_COUNT) { + CPRINTS("C%d: Interrupt storm detected." + " Disabling port temporarily", + port); + + pd_set_suspend(port, 1); + pd_deferred_resume(port); + } +} + +__overridable void board_process_pd_alert(int port) +{ } /* - * Main task entry point that handles PD interrupts for a single port + * Main task entry point that handles PD interrupts for a single port. These + * interrupts usually come from a TCPC, but may also come from PD-related chips + * sharing the TCPC interrupt line. * * @param p The PD port number for which to handle interrupts (pointer is * reinterpreted as an integer directly). */ void pd_interrupt_handler_task(void *p) { - const int port = (int) ((intptr_t) p); + const int port = (int)((intptr_t)p); const int port_mask = (PD_STATUS_TCPC_ALERT_0 << port); - struct { - int count; - timestamp_t time; - } storm_tracker[CONFIG_USB_PD_PORT_MAX_COUNT] = {}; ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); @@ -60,46 +112,108 @@ void pd_interrupt_handler_task(void *p) while (1) { const int evt = task_wait_event(-1); - if (evt & PD_PROCESS_INTERRUPT) { - /* - * While the interrupt signal is asserted; we have more - * work to do. This effectively makes the interrupt a - * level-interrupt instead of an edge-interrupt without - * having to enable/disable a real level-interrupt in - * multiple locations. - * - * Also, if the port is disabled do not process - * interrupts. Upon existing suspend, we schedule a - * PD_PROCESS_INTERRUPT to check if we missed anything. - */ - while ((tcpc_get_alert_status() & port_mask) && - pd_is_port_enabled(port)) { - timestamp_t now; - - tcpc_alert(port); - - now = get_time(); - if (timestamp_expired(storm_tracker[port].time, - &now)) { - /* Reset timer into future */ - storm_tracker[port].time.val = - now.val + ALERT_STORM_INTERVAL; - - /* - * Start at 1 since we are processing an - * interrupt right now - */ - storm_tracker[port].count = 1; - } else if (++storm_tracker[port].count > - ALERT_STORM_MAX_COUNT) { - CPRINTS("C%d: Interrupt storm detected." - " Disabling port temporarily", - port); - - pd_set_suspend(port, 1); - pd_deferred_resume(port); + if ((evt & PD_PROCESS_INTERRUPT) == 0) + continue; + /* + * While the interrupt signal is asserted; we have more + * work to do. This effectively makes the interrupt a + * level-interrupt instead of an edge-interrupt without + * having to enable/disable a real level-interrupt in + * multiple locations. + * + * Also, if the port is disabled do not process + * interrupts. Upon existing suspend, we schedule a + * PD_PROCESS_INTERRUPT to check if we missed anything. + */ + while ((tcpc_get_alert_status() & port_mask) && + pd_is_port_enabled(port)) { + service_one_port(port); + } + + board_process_pd_alert(port); + } +} + +/* + * This code assumes port alert masks are adjacent to each other. + */ +BUILD_ASSERT(PD_STATUS_TCPC_ALERT_3 == (PD_STATUS_TCPC_ALERT_0 << 3)); + +/* + * Shared TCPC interrupt handler. The function argument in ec.tasklist + * is the mask of ports to handle. For example: + * + * BIT(USBC_PORT_C2) | BIT(USBC_PORT_C0) + * + * Note that this bitmask is 0-based while PD_STATUS_TCPC_ALERT_ + * is not. + */ + +#if !defined(CONFIG_ZEPHYR) || defined(CONFIG_HAS_TASK_PD_INT_SHARED) +void pd_shared_alert_task(void *p) +{ + const int sources_mask = (int)((intptr_t)p); + int want_alerts = 0; + int port; + int port_mask; + + CPRINTS("%s: port mask 0x%02x", __func__, sources_mask); + + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) { + if ((sources_mask & BIT(port)) == 0) + continue; + if (!board_is_usb_pd_port_present(port)) + continue; + + port_mask = PD_STATUS_TCPC_ALERT_0 << port; + want_alerts |= port_mask; + pd_int_task_id[port] = task_get_current(); + } + + if (want_alerts == 0) { + /* + * None of the configured alert sources are available. + */ + return; + } + + while (1) { + const int evt = task_wait_event(-1); + int have_alerts; + + if ((evt & PD_PROCESS_INTERRUPT) == 0) + continue; + + /* + * While the interrupt signal is asserted; we have more + * work to do. This effectively makes the interrupt a + * level-interrupt instead of an edge-interrupt without + * having to enable/disable a real level-interrupt in + * multiple locations. + * + * Also, if the port is disabled do not process + * interrupts. Upon existing suspend, we schedule a + * PD_PROCESS_INTERRUPT to check if we missed anything. + */ + do { + have_alerts = tcpc_get_alert_status(); + have_alerts &= want_alerts; + + for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; + ++port) { + port_mask = PD_STATUS_TCPC_ALERT_0 << port; + if ((have_alerts & port_mask) == 0) { + /* skip quiet port */ + continue; } + if (!pd_is_port_enabled(port)) { + /* filter out disabled port */ + have_alerts &= ~port_mask; + continue; + } + service_one_port(port); } - } + } while (have_alerts != 0); } } +#endif /* !CONFIG_ZEPHYR || CONFIG_HAS_TASK_PD_INT_SHARED */ diff --git a/common/usbc_ocp.c b/common/usbc_ocp.c new file mode 100644 index 0000000000..406deb2b20 --- /dev/null +++ b/common/usbc_ocp.c @@ -0,0 +1,171 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* USB-C Overcurrent Protection Common Code */ + +#include "atomic.h" +#include "common.h" +#include "console.h" +#include "hooks.h" +#include "timer.h" +#include "usb_common.h" +#include "usb_pd.h" +#include "usbc_ocp.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) + +/* + * Number of seconds until a latched-off port is re-enabled for sourcing after + * detecting a physical disconnect. + */ +#define OCP_COOLDOWN_DELAY_US (2 * SECOND) + +/* + * A per-port table that indicates how many VBUS overcurrent events have + * occurred. This table is cleared after detecting a physical disconnect of the + * sink. + */ +static uint8_t oc_event_cnt_tbl[CONFIG_USB_PD_PORT_MAX_COUNT]; + +/* A flag for ports with sink device connected. */ +static atomic_t snk_connected_ports; + +static void clear_oc_tbl(void) +{ + int port; + + for (port = 0; port < board_get_usb_pd_port_count(); port++) + /* + * Only clear the table if the port partner is no longer + * attached after debouncing. + */ + if ((!(BIT(port) & (uint32_t)snk_connected_ports)) && + oc_event_cnt_tbl[port]) { + oc_event_cnt_tbl[port] = 0; + CPRINTS("C%d: OC events cleared", port); + } +} +DECLARE_DEFERRED(clear_oc_tbl); + +static atomic_t port_oc_reset_req; + +static void re_enable_ports(void) +{ + uint32_t ports = atomic_clear(&port_oc_reset_req); + + while (ports) { + int port = __fls(ports); + + ports &= ~BIT(port); + + /* + * Let the board know that the overcurrent is + * over since we've completed our recovery actions by now. + */ + board_overcurrent_event(port, 0); + + /* Queue up an Alert message for the partner */ + pd_send_alert_msg(port, ADO_OCP_EVENT); + } +} +DECLARE_DEFERRED(re_enable_ports); + +int usbc_ocp_add_event(int port) +{ + int delay = 0; + + if ((port < 0) || (port >= board_get_usb_pd_port_count())) { + CPRINTS("%s(%d) Invalid port!", __func__, port); + return EC_ERROR_INVAL; + } + + /* Let the board specific code know about the OC event. */ + board_overcurrent_event(port, 1); + + oc_event_cnt_tbl[port]++; + + /* The port overcurrented, so don't clear it's OC events. */ + atomic_clear_bits(&snk_connected_ports, 1 << port); + + if (oc_event_cnt_tbl[port] >= OCP_MAX_CNT) { + CPRINTS("C%d: OC event limit reached! " + "Source path disabled until physical disconnect.", + port); + pd_power_supply_reset(port); + } else if (oc_event_cnt_tbl[port] <= OCP_HR_CNT) { + /* + * Hard reset for the first few offenses, sending an alert after + * at least the time we need to hard reset and make a new + * contract. + */ + pd_send_hard_reset(port); + delay = PD_T_SRC_RECOVER + 100 * MSEC; + } else { + /* + * ErrorRecovery must be performed past the third OCP event, + * queueing up the alert for after it completes and a new + * contract is in place + */ + pd_set_error_recovery(port); + delay = PD_T_ERROR_RECOVERY + 100 * MSEC; + } + + if (delay) { + atomic_or(&port_oc_reset_req, BIT(port)); + hook_call_deferred(&re_enable_ports_data, delay); + } + + return EC_SUCCESS; +} + +int usbc_ocp_clear_event_counter(int port) +{ + if ((port < 0) || (port >= board_get_usb_pd_port_count())) { + CPRINTS("%s(%d) Invalid port!", __func__, port); + return EC_ERROR_INVAL; + } + + /* + * If we are clearing our event table in quick succession, we may be in + * an overcurrent loop where we are also detecting a disconnect on the + * CC pins. Therefore, let's not clear it just yet and the let the + * limit be reached. This way, we won't send the hard reset and + * actually detect the physical disconnect. + */ + if (oc_event_cnt_tbl[port]) { + hook_call_deferred(&clear_oc_tbl_data, OCP_COOLDOWN_DELAY_US); + } + return EC_SUCCESS; +} + +int usbc_ocp_is_port_latched_off(int port) +{ + if ((port < 0) || (port >= board_get_usb_pd_port_count())) { + CPRINTS("%s(%d) Invalid port!", __func__, port); + return 0; + } + + return oc_event_cnt_tbl[port] >= OCP_MAX_CNT; +} + +void usbc_ocp_snk_is_connected(int port, bool connected) +{ + if ((port < 0) || (port >= board_get_usb_pd_port_count())) { + CPRINTS("%s(%d) Invalid port!", __func__, port); + return; + } + + if (connected) + atomic_or(&snk_connected_ports, 1 << port); + else + atomic_clear_bits(&snk_connected_ports, 1 << port); +} + +__overridable void board_overcurrent_event(int port, int is_overcurrented) +{ + /* Do nothing by default. Boards with overcurrent GPIOs may override */ +} diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c index 7a334ae439..7063dfb93a 100644 --- a/common/usbc_ppc.c +++ b/common/usbc_ppc.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,43 +10,44 @@ #include "console.h" #include "hooks.h" #include "timer.h" +#include "usb_pd.h" #include "usbc_ppc.h" #include "util.h" -#ifndef TEST_BUILD -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#ifndef TEST_LEGACY_BUILD +/* + * We limit the CPRINTF/S invocations to all builds that are not + * legacy test builds because they dont build otherwise. + */ +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else -#define CPRINTF(args...) -#define CPRINTS(args...) +#define CPRINTF(format, args...) +#define CPRINTS(format, args...) #endif int ppc_prints(const char *string, int port) { -#ifndef TEST_BUILD - return CPRINTS("ppc p%d %s", port, string); -#else +#if defined(TEST_LEGACY_BUILD) || !defined(CONFIG_USBC_PPC_LOGGING) return 0; -#endif +#else + return CPRINTS("ppc p%d %s", port, string); +#endif /* defined(TEST_LEGACY_BUILD) || !defined(CONFIG_USBC_PPC_LOGGING) */ } int ppc_err_prints(const char *string, int port, int error) { -#ifndef TEST_BUILD - return CPRINTS("ppc p%d %s (%d)", port, string, error); -#else +#if defined(TEST_LEGACY_BUILD) || !defined(CONFIG_USBC_PPC_LOGGING) return 0; -#endif +#else + return CPRINTS("ppc p%d %s (%d)", port, string, error); +#endif /* defined(TEST_LEGACY_BUILD) || !defined(CONFIG_USBC_PPC_LOGGING) */ } -/* - * A per-port table that indicates how many VBUS overcurrent events have - * occurred. This table is cleared after detecting a physical disconnect of the - * sink. - */ -static uint8_t oc_event_cnt_tbl[CONFIG_USB_PD_PORT_MAX_COUNT]; - -static uint32_t connected_ports; +__overridable bool board_port_has_ppc(int port) +{ + return true; +} /* Simple wrappers to dispatch to the drivers. */ @@ -55,6 +56,9 @@ int ppc_init(int port) int rv = EC_ERROR_UNIMPLEMENTED; const struct ppc_config_t *ppc; + if (!board_port_has_ppc(port)) + return EC_SUCCESS; + if ((port < 0) || (port >= ppc_cnt)) { CPRINTS("%s(%d) Invalid port!", __func__, port); return EC_ERROR_INVAL; @@ -72,64 +76,7 @@ int ppc_init(int port) return rv; } -int ppc_add_oc_event(int port) -{ - if ((port < 0) || (port >= ppc_cnt)) { - CPRINTS("%s(%d) Invalid port!", __func__, port); - return EC_ERROR_INVAL; - } - - oc_event_cnt_tbl[port]++; - - /* The port overcurrented, so don't clear it's OC events. */ - deprecated_atomic_clear_bits(&connected_ports, 1 << port); - - if (oc_event_cnt_tbl[port] >= PPC_OC_CNT_THRESH) - ppc_prints("OC event limit reached! " - "Source path disabled until physical disconnect.", - port); - return EC_SUCCESS; -} - -static void clear_oc_tbl(void) -{ - int port; - - for (port = 0; port < ppc_cnt; port++) - /* - * Only clear the table if the port partner is no longer - * attached after debouncing. - */ - if ((!(BIT(port) & connected_ports)) && - oc_event_cnt_tbl[port]) { - oc_event_cnt_tbl[port] = 0; - ppc_prints("OC events cleared", port); - } -} -DECLARE_DEFERRED(clear_oc_tbl); - -int ppc_clear_oc_event_counter(int port) -{ - if ((port < 0) || (port >= ppc_cnt)) { - CPRINTS("%s(%d) Invalid port!", __func__, port); - return EC_ERROR_INVAL; - } - - /* - * If we are clearing our event table in quick succession, we may be in - * an overcurrent loop where we are also detecting a disconnect on the - * CC pins. Therefore, let's not clear it just yet and the let the - * limit be reached. This way, we won't send the hard reset and - * actually detect the physical disconnect. - */ - if (oc_event_cnt_tbl[port]) { - hook_call_deferred(&clear_oc_tbl_data, - PPC_OC_COOLDOWN_DELAY_US); - } - return EC_SUCCESS; -} - -int ppc_is_sourcing_vbus(int port) +test_mockable int ppc_is_sourcing_vbus(int port) { int rv = 0; const struct ppc_config_t *ppc; @@ -152,6 +99,9 @@ int ppc_set_polarity(int port, int polarity) int rv = EC_ERROR_UNIMPLEMENTED; const struct ppc_config_t *ppc; + if (!board_port_has_ppc(port)) + return EC_SUCCESS; + if ((port < 0) || (port >= ppc_cnt)) { CPRINTS("%s(%d) Invalid port!", __func__, port); return EC_ERROR_INVAL; @@ -170,6 +120,9 @@ int ppc_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) int rv = EC_ERROR_UNIMPLEMENTED; const struct ppc_config_t *ppc; + if (!board_port_has_ppc(port)) + return EC_SUCCESS; + if ((port < 0) || (port >= ppc_cnt)) { CPRINTS("%s(%d) Invalid port!", __func__, port); return EC_ERROR_INVAL; @@ -199,22 +152,15 @@ int ppc_discharge_vbus(int port, int enable) return rv; } -int ppc_is_port_latched_off(int port) -{ - if ((port < 0) || (port >= ppc_cnt)) { - CPRINTS("%s(%d) Invalid port!", __func__, port); - return 0; - } - - return oc_event_cnt_tbl[port] >= PPC_OC_CNT_THRESH; -} - #ifdef CONFIG_USBC_PPC_SBU int ppc_set_sbu(int port, int enable) { int rv = EC_ERROR_UNIMPLEMENTED; const struct ppc_config_t *ppc; + if (!board_port_has_ppc(port)) + return EC_SUCCESS; + if ((port < 0) || (port >= ppc_cnt)) { CPRINTS("%s(%d) Invalid port!", __func__, port); return EC_ERROR_INVAL; @@ -234,20 +180,14 @@ int ppc_set_vconn(int port, int enable) int rv = EC_ERROR_UNIMPLEMENTED; const struct ppc_config_t *ppc; + if (!board_port_has_ppc(port)) + return EC_SUCCESS; + if ((port < 0) || (port >= ppc_cnt)) { CPRINTS("%s(%d) Invalid port!", __func__, port); return EC_ERROR_INVAL; } - /* - * Check our OC event counter. If we've exceeded our threshold, then - * let's latch our source path off to prevent continuous cycling. When - * the PD state machine detects a disconnection on the CC lines, we will - * reset our OC event counter. - */ - if (enable && ppc_is_port_latched_off(port)) - return EC_ERROR_ACCESS_DENIED; - ppc = &ppc_chips[port]; if (ppc->drv->set_vconn) rv = ppc->drv->set_vconn(port, enable); @@ -256,17 +196,24 @@ int ppc_set_vconn(int port, int enable) } #endif -void ppc_sink_is_connected(int port, int is_connected) +int ppc_dev_is_connected(int port, enum ppc_device_role dev) { + int rv = EC_SUCCESS; + const struct ppc_config_t *ppc; + + if (!board_port_has_ppc(port)) + return EC_SUCCESS; + if ((port < 0) || (port >= ppc_cnt)) { CPRINTS("%s(%d) Invalid port!", __func__, port); - return; + return EC_ERROR_INVAL; } - if (is_connected) - deprecated_atomic_or(&connected_ports, 1 << port); - else - deprecated_atomic_clear_bits(&connected_ports, 1 << port); + ppc = &ppc_chips[port]; + if (ppc->drv->dev_is_connected) + rv = ppc->drv->dev_is_connected(port, dev); + + return rv; } int ppc_vbus_sink_enable(int port, int enable) @@ -313,15 +260,6 @@ int ppc_vbus_source_enable(int port, int enable) return EC_ERROR_INVAL; } - /* - * Check our OC event counter. If we've exceeded our threshold, then - * let's latch our source path off to prevent continuous cycling. When - * the PD state machine detects a disconnection on the CC lines, we will - * reset our OC event counter. - */ - if (enable && ppc_is_port_latched_off(port)) - return EC_ERROR_ACCESS_DENIED; - ppc = &ppc_chips[port]; if (ppc->drv->vbus_source_enable) rv = ppc->drv->vbus_source_enable(port, enable); @@ -343,7 +281,7 @@ int ppc_set_frs_enable(int port, int enable) ppc = &ppc_chips[port]; if (ppc->drv->set_frs_enable) - rv = ppc->drv->set_frs_enable(port,enable); + rv = ppc->drv->set_frs_enable(port, enable); return rv; } @@ -370,7 +308,7 @@ int ppc_is_vbus_present(int port) #endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ #ifdef CONFIG_CMD_PPC_DUMP -static int command_ppc_dump(int argc, char **argv) +static int command_ppc_dump(int argc, const char **argv) { int port; int rv = EC_ERROR_UNIMPLEMENTED; diff --git a/common/util.c b/common/util.c index ed5b87c2c9..7672dc1325 100644 --- a/common/util.c +++ b/common/util.c @@ -1,149 +1,19 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Utility functions for Chrome EC */ +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "util.h" -__stdlib_compat size_t strlen(const char *s) +int find_base(int base, int *c, const char **nptr) { - int len = 0; - - while (*s++) - len++; - - return len; -} - - -__stdlib_compat size_t strnlen(const char *s, size_t maxlen) -{ - size_t len = 0; - - while (len < maxlen && *s) { - s++; - len++; - } - return len; -} - - -__stdlib_compat int isspace(int c) -{ - return c == ' ' || c == '\t' || c == '\r' || c == '\n'; -} - - -__stdlib_compat int isdigit(int c) -{ - return c >= '0' && c <= '9'; -} - - -__stdlib_compat int isalpha(int c) -{ - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); -} - -__stdlib_compat int isupper(int c) -{ - return c >= 'A' && c <= 'Z'; -} - -__stdlib_compat int isprint(int c) -{ - return c >= ' ' && c <= '~'; -} - -__stdlib_compat int tolower(int c) -{ - return c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c; -} - - -__stdlib_compat int strcasecmp(const char *s1, const char *s2) -{ - int diff; - - do { - diff = tolower(*s1) - tolower(*s2); - if (diff) - return diff; - } while (*(s1++) && *(s2++)); - return 0; -} - - -__stdlib_compat int strncasecmp(const char *s1, const char *s2, size_t size) -{ - int diff; - - if (!size) - return 0; - - do { - diff = tolower(*s1) - tolower(*s2); - if (diff) - return diff; - } while (*(s1++) && *(s2++) && --size); - return 0; -} - - -__stdlib_compat char *strstr(const char *s1, const char *s2) -{ - const char *p, *q, *r; - size_t len1 = strlen(s1); - size_t len2 = strlen(s2); - - if (len1 == 0 || len2 == 0 || len1 < len2) - return NULL; - - r = s1 + len1 - len2 + 1; - for (; s1 < r; s1++) { - if (*s1 == *s2) { - p = s1 + 1; - q = s2 + 1; - for (; q < s2 + len2;) { - if (*p++ != *q++) - break; - } - if (*q == '\0') - return (char *)s1; - } - } - return NULL; -} - -__stdlib_compat int atoi(const char *nptr) -{ - int result = 0; - int neg = 0; - char c = '\0'; - - while ((c = *nptr++) && isspace(c)) - ; - - if (c == '-') { - neg = 1; - c = *nptr++; - } - - while (isdigit(c)) { - result = result * 10 + (c - '0'); - c = *nptr++; - } - - return neg ? -result : result; -} - -static int find_base(int base, int *c, const char **nptr) { - if ((base == 0 || base == 16) && *c == '0' - && (**nptr == 'x' || **nptr == 'X')) { + if ((base == 0 || base == 16) && *c == '0' && + (**nptr == 'x' || **nptr == 'X')) { *c = (*nptr)[1]; (*nptr) += 2; base = 16; @@ -153,9 +23,8 @@ static int find_base(int base, int *c, const char **nptr) { return base; } - /* Like strtol(), but for integers */ -__stdlib_compat int strtoi(const char *nptr, char **endptr, int base) +int strtoi(const char *nptr, char **endptr, int base) { int result = 0; int neg = 0; @@ -191,54 +60,20 @@ __stdlib_compat int strtoi(const char *nptr, char **endptr, int base) return neg ? -result : result; } -__stdlib_compat uint64_t strtoul(const char *nptr, char **endptr, int base) -{ - uint64_t result = 0; - int c = '\0'; - - while ((c = *nptr++) && isspace(c)) - ; - - if (c == '+') { - c = *nptr++; - } else if (c == '-') { - if (endptr) - *endptr = (char *)nptr - 1; - return result; - } - - base = find_base(base, &c, &nptr); - - while (c) { - if (c >= '0' && c < '0' + MIN(base, 10)) - result = result * base + (c - '0'); - else if (c >= 'A' && c < 'A' + base - 10) - result = result * base + (c - 'A' + 10); - else if (c >= 'a' && c < 'a' + base - 10) - result = result * base + (c - 'a' + 10); - else - break; - - c = *nptr++; - } - - if (endptr) - *endptr = (char *)nptr - 1; - return result; -} - -__stdlib_compat int parse_bool(const char *s, int *dest) +int parse_bool(const char *s, int *dest) { /* off, disable, false, no */ if (!strcasecmp(s, "off") || !strncasecmp(s, "dis", 3) || - tolower(*s) == 'f' || tolower(*s) == 'n') { + tolower((unsigned char)*s) == 'f' || + tolower((unsigned char)*s) == 'n') { *dest = 0; return 1; } /* on, enable, true, yes */ if (!strcasecmp(s, "on") || !strncasecmp(s, "ena", 3) || - tolower(*s) == 't' || tolower(*s) == 'y') { + tolower((unsigned char)*s) == 't' || + tolower((unsigned char)*s) == 'y') { *dest = 1; return 1; } @@ -247,21 +82,6 @@ __stdlib_compat int parse_bool(const char *s, int *dest) return 0; } -__stdlib_compat int memcmp(const void *s1, const void *s2, size_t len) -{ - const char *sa = s1; - const char *sb = s2; - - int diff = 0; - while (len-- > 0) { - diff = *(sa++) - *(sb++); - if (diff) - return diff; - } - - return 0; -} - /* Constant-time memory comparison */ int safe_memcmp(const void *s1, const void *s2, size_t size) { @@ -282,160 +102,6 @@ int safe_memcmp(const void *s1, const void *s2, size_t size) return result != 0; } -#if !(__has_feature(address_sanitizer) || __has_feature(memory_sanitizer)) -__stdlib_compat void *memcpy(void *dest, const void *src, size_t len) -{ - char *d = (char *)dest; - const char *s = (const char *)src; - uint32_t *dw; - const uint32_t *sw; - char *head; - char * const tail = (char *)dest + len; - /* Set 'body' to the last word boundary */ - uint32_t * const body = (uint32_t *)((uintptr_t)tail & ~3); - - if (((uintptr_t)dest & 3) != ((uintptr_t)src & 3)) { - /* Misaligned. no body, no tail. */ - head = tail; - } else { - /* Aligned */ - if ((uintptr_t)tail < (((uintptr_t)d + 3) & ~3)) - /* len is shorter than the first word boundary */ - head = tail; - else - /* Set 'head' to the first word boundary */ - head = (char *)(((uintptr_t)d + 3) & ~3); - } - - /* Copy head */ - while (d < head) - *(d++) = *(s++); - - /* Copy body */ - dw = (uint32_t *)d; - sw = (uint32_t *)s; - while (dw < body) - *(dw++) = *(sw++); - - /* Copy tail */ - d = (char *)dw; - s = (const char *)sw; - while (d < tail) - *(d++) = *(s++); - - return dest; -} -#endif /* address_sanitizer || memory_sanitizer */ - - -#if !(__has_feature(address_sanitizer) || __has_feature(memory_sanitizer)) -__stdlib_compat __visible void *memset(void *dest, int c, size_t len) -{ - char *d = (char *)dest; - uint32_t cccc; - uint32_t *dw; - char *head; - char * const tail = (char *)dest + len; - /* Set 'body' to the last word boundary */ - uint32_t * const body = (uint32_t *)((uintptr_t)tail & ~3); - - c &= 0xff; /* Clear upper bits before ORing below */ - cccc = c | (c << 8) | (c << 16) | (c << 24); - - if ((uintptr_t)tail < (((uintptr_t)d + 3) & ~3)) - /* len is shorter than the first word boundary */ - head = tail; - else - /* Set 'head' to the first word boundary */ - head = (char *)(((uintptr_t)d + 3) & ~3); - - /* Copy head */ - while (d < head) - *(d++) = c; - - /* Copy body */ - dw = (uint32_t *)d; - while (dw < body) - *(dw++) = cccc; - - /* Copy tail */ - d = (char *)dw; - while (d < tail) - *(d++) = c; - - return dest; -} -#endif /* address_sanitizer || memory_sanitizer */ - - -#if !(__has_feature(address_sanitizer) || __has_feature(memory_sanitizer)) -__stdlib_compat void *memmove(void *dest, const void *src, size_t len) -{ - if ((uintptr_t)dest <= (uintptr_t)src || - (uintptr_t)dest >= (uintptr_t)src + len) { - /* Start of destination doesn't overlap source, so just use - * memcpy(). */ - return memcpy(dest, src, len); - } else { - /* Need to copy from tail because there is overlap. */ - char *d = (char *)dest + len; - const char *s = (const char *)src + len; - uint32_t *dw; - const uint32_t *sw; - char *head; - char * const tail = (char *)dest; - /* Set 'body' to the last word boundary */ - uint32_t * const body = (uint32_t *)(((uintptr_t)tail+3) & ~3); - - if (((uintptr_t)dest & 3) != ((uintptr_t)src & 3)) { - /* Misaligned. no body, no tail. */ - head = tail; - } else { - /* Aligned */ - if ((uintptr_t)tail > ((uintptr_t)d & ~3)) - /* Shorter than the first word boundary */ - head = tail; - else - /* Set 'head' to the first word boundary */ - head = (char *)((uintptr_t)d & ~3); - } - - /* Copy head */ - while (d > head) - *(--d) = *(--s); - - /* Copy body */ - dw = (uint32_t *)d; - sw = (uint32_t *)s; - while (dw > body) - *(--dw) = *(--sw); - - /* Copy tail */ - d = (char *)dw; - s = (const char *)sw; - while (d > tail) - *(--d) = *(--s); - - return dest; - } -} -#endif /* address_sanitizer || memory_sanitizer */ - - -__stdlib_compat void *memchr(const void *buffer, int c, size_t n) -{ - char *current = (char *)buffer; - char *end = current + n; - - while (current != end) { - if (*current == c) - return current; - current++; - } - return NULL; -} - - void reverse(void *dest, size_t len) { int i; @@ -450,8 +116,7 @@ void reverse(void *dest, size_t len) } } - -__stdlib_compat char *strzcpy(char *dest, const char *src, int len) +char *strzcpy(char *dest, const char *src, int len) { char *d = dest; if (len <= 0) @@ -464,36 +129,6 @@ __stdlib_compat char *strzcpy(char *dest, const char *src, int len) return dest; } - -__stdlib_compat char *strncpy(char *dest, const char *src, size_t n) -{ - char *d = dest; - - while (n && *src) { - *d++ = *src++; - n--; - } - if (n) - *d = '\0'; - return dest; -} - - -__stdlib_compat int strncmp(const char *s1, const char *s2, size_t n) -{ - while (n--) { - if (*s1 != *s2) - return *s1 - *s2; - if (!*s1) - break; - s1++; - s2++; - - } - return 0; -} - - int uint64divmod(uint64_t *n, int d) { uint64_t q = 0, mask; @@ -566,13 +201,19 @@ bool is_aligned(uint32_t addr, uint32_t align) return (addr & (align - 1)) == 0; } +int alignment_log2(unsigned int x) +{ + ASSERT(x != 0); /* ctz(0) is undefined */ + return __builtin_ctz(x); +} + /****************************************************************************/ /* stateful conditional stuff */ enum cond_internal_bits { - COND_CURR_MASK = BIT(0), /* current value */ - COND_RISE_MASK = BIT(1), /* set if 0->1 */ - COND_FALL_MASK = BIT(2), /* set if 1->0 */ + COND_CURR_MASK = BIT(0), /* current value */ + COND_RISE_MASK = BIT(1), /* set if 0->1 */ + COND_FALL_MASK = BIT(2), /* set if 1->0 */ }; void cond_init(cond_t *c, int val) @@ -591,7 +232,6 @@ int cond_is(cond_t *c, int val) return !(*c & COND_CURR_MASK); } - void cond_set(cond_t *c, int val) { if (val && cond_is(c, 0)) @@ -604,7 +244,6 @@ void cond_set(cond_t *c, int val) *c &= ~COND_CURR_MASK; } - int cond_went(cond_t *c, int val) { int ret; @@ -630,8 +269,8 @@ int cond_went(cond_t *c, int val) * *offset<0. If argc= 0; i--) { + /* + * We keep track of the normal ternary result and whether + * we found any bit that was a Z. We also determine the + * amount of numbers that can be represented with only binary + * digits (no Z) whose value in the normal ternary system + * is lower than the one we are parsing. Counting from the left, + * we add 2^i for any '1' digit to account for the binary + * numbers whose values would be below it if all following + * digits we parsed would be '0'. As soon as we find a '2' digit + * we can total the remaining binary numbers below as 2^(i+1) + * because we know that all binary representations counting only + * this and following digits must have values below our number + * (since 1xxx is always smaller than 2xxx). + * + * Example: 1 0 2 1 (counting from the left / most significant) + * '1' at 3^3: Add 2^3 = 8 to account for binaries 0000-0111 + * '0' at 3^2: Ignore (not all binaries 1000-1100 are below us) + * '2' at 3^1: Add 2^(1+1) = 4 to account for binaries 1000-1011 + * Stop adding for lower digits (3^0), all already accounted + * now. We know that there can be no binary numbers 1020-102X. + */ + base3 = (base3 * 3) + bits[i]; + + if (!has_z) { + switch (bits[i]) { + case 0: /* Ignore '0' digits. */ + break; + case 1: /* Account for binaries 0 to 2^i - 1. */ + binary_below += 1 << i; + break; + case 2: /* Account for binaries 0 to 2^(i+1) - 1. */ + binary_below += 1 << (i + 1); + has_z = 1; + } + } + } + + if (has_z) + return base3 + (1 << nbits) - binary_below; + + /* binary_below is normal binary system value if !has_z. */ + return binary_below; +} + +int binary_from_bits(int *bits, int nbits) +{ + int value = 0; + int i; + + /* Loop through every binary digit, from MSB to LSB. */ + for (i = nbits - 1; i >= 0; i--) + value = (value << 1) | bits[i]; + + return value; +} + +int ternary_from_bits(int *bits, int nbits) +{ + int value = 0; + int i; + + /* Loop through every ternary digit, from MSB to LSB. */ + for (i = nbits - 1; i >= 0; i--) + value = (value * 3) + bits[i]; + + return value; +} diff --git a/common/vboot/common.c b/common/vboot/common.c index 39f8c193c7..a92652364b 100644 --- a/common/vboot/common.c +++ b/common/vboot/common.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,8 +10,8 @@ #include "shared_mem.h" #include "vboot.h" -#define CPRINTS(format, args...) cprints(CC_VBOOT, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_VBOOT, format, ## args) +#define CPRINTS(format, args...) cprints(CC_VBOOT, format, ##args) +#define CPRINTF(format, args...) cprintf(CC_VBOOT, format, ##args) int vboot_is_padding_valid(const uint8_t *data, uint32_t start, uint32_t end) { @@ -32,8 +32,8 @@ int vboot_is_padding_valid(const uint8_t *data, uint32_t start, uint32_t end) return EC_SUCCESS; } -int vboot_verify(const uint8_t *data, int len, - const struct rsa_public_key *key, const uint8_t *sig) +int vboot_verify(const uint8_t *data, int len, const struct rsa_public_key *key, + const uint8_t *sig) { struct sha256_ctx ctx; uint8_t *hash; diff --git a/common/vboot/efs2.c b/common/vboot/efs2.c index e608fd5841..3346a2c76b 100644 --- a/common/vboot/efs2.c +++ b/common/vboot/efs2.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -16,28 +16,33 @@ #include "console.h" #include "crc8.h" #include "flash.h" +#include "gpio.h" #include "hooks.h" #include "sha256.h" #include "system.h" #include "task.h" -#include "usb_pd.h" #include "uart.h" +#include "usb_pd.h" #include "vboot.h" #include "vboot_hash.h" -#define CPRINTS(format, args...) cprints(CC_VBOOT,"VB " format, ## args) -#define CPRINTF(format, args...) cprintf(CC_VBOOT,"VB " format, ## args) +#define CPRINTS(format, args...) cprints(CC_VBOOT, "VB " format, ##args) +#define CPRINTF(format, args...) cprintf(CC_VBOOT, "VB " format, ##args) +/* LCOV_EXCL_START - TODO(b/172210316) implement is_battery_ready(), and remove + * this lcov excl. + */ static const char *boot_mode_to_string(uint8_t mode) { static const char *boot_mode_str[] = { - [BOOT_MODE_NORMAL] = "NORMAL", - [BOOT_MODE_NO_BOOT] = "NO_BOOT", + [BOOT_MODE_NORMAL] = "NORMAL", + [BOOT_MODE_NO_BOOT] = "NO_BOOT", }; if (mode < ARRAY_SIZE(boot_mode_str)) return boot_mode_str[mode]; return "UNDEF"; } +/* LCOV_EXCL_STOP */ /* * Check whether the session has successfully ended or not. ERR_TIMEOUT is @@ -45,11 +50,11 @@ static const char *boot_mode_to_string(uint8_t mode) */ static bool is_valid_cr50_response(enum cr50_comm_err code) { - return code != CR50_COMM_ERR_TIMEOUT - && (code >> 8) == CR50_COMM_ERR_PREFIX; + return code != CR50_COMM_ERR_TIMEOUT && + (code >> 8) == CR50_COMM_ERR_PREFIX; } -static void enable_packet_mode(bool enable) +__overridable void board_enable_packet_mode(bool enable) { /* * This can be done by set_flags(INPUT|PULL_UP). We don't need it now @@ -62,14 +67,26 @@ static enum cr50_comm_err send_to_cr50(const uint8_t *data, size_t size) { timestamp_t until; int i, timeout = 0; + uint32_t lock_key; struct cr50_comm_response res = {}; /* This will wake up (if it's sleeping) and interrupt Cr50. */ - enable_packet_mode(true); + board_enable_packet_mode(true); uart_flush_output(); uart_clear_input(); + if (uart_shell_stop()) { + /* Failed to stop the shell. */ + /* LCOV_EXCL_START - At least on posix systems, uart_shell_stop + * will never fail, it will crash the binary or hang forever on + * error. + */ + board_enable_packet_mode(false); + return CR50_COMM_ERR_UNKNOWN; + /* LCOV_EXCL_STOP */ + } + /* * Send packet. No traffic control, assuming Cr50 consumes stream much * faster. TX buffer shouldn't overflow because it's cleared above and @@ -78,24 +95,29 @@ static enum cr50_comm_err send_to_cr50(const uint8_t *data, size_t size) * Disable interrupts so that the data frame will be stored in the Tx * buffer in one piece. */ - interrupt_disable(); + lock_key = irq_lock(); uart_put_raw(data, size); - interrupt_enable(); + irq_unlock(lock_key); uart_flush_output(); until.val = get_time().val + CR50_COMM_TIMEOUT; - /* Make sure console task won't steal the response (in case in the - * future we should exchange packets after tasks start). */ - task_disable_task(TASK_ID_CONSOLE); + /* + * Make sure console task won't steal the response in case we exchange + * packets after tasks start. + */ +#ifndef CONFIG_ZEPHYR + if (task_start_called()) + task_disable_task(TASK_ID_CONSOLE); +#endif /* !CONFIG_ZEPHYR */ /* Wait for response from Cr50 */ for (i = 0; i < sizeof(res); i++) { while (!timeout) { int c = uart_getc(); if (c != -1) { - res.error = res.error | c << (i*8); + res.error = res.error | c << (i * 8); break; } msleep(1); @@ -103,18 +125,22 @@ static enum cr50_comm_err send_to_cr50(const uint8_t *data, size_t size) } } - task_enable_task(TASK_ID_CONSOLE); + uart_shell_start(); +#ifndef CONFIG_ZEPHYR + if (task_start_called()) + task_enable_task(TASK_ID_CONSOLE); +#endif /* CONFIG_ZEPHYR */ /* Exit packet mode */ - enable_packet_mode(false); + board_enable_packet_mode(false); + + CPRINTS("Received 0x%04x", res.error); if (timeout) { CPRINTS("Timeout"); return CR50_COMM_ERR_TIMEOUT; } - CPRINTS("Received 0x%04x", res.error); - return res.error; } @@ -141,8 +167,8 @@ static enum cr50_comm_err cmd_to_cr50(enum cr50_comm_cmd cmd, p->type = cmd; p->size = size; memcpy(p->data, data, size); - p->crc = crc8((uint8_t *)&p->type, - sizeof(p->type) + sizeof(p->size) + size); + p->crc = cros_crc8((uint8_t *)&p->type, + sizeof(p->type) + sizeof(p->size) + size); do { rv = send_to_cr50((uint8_t *)&s, @@ -161,10 +187,10 @@ static enum cr50_comm_err verify_hash(void) int rv; /* Wake up Cr50 beforehand in case it's asleep. */ - enable_packet_mode(true); + board_enable_packet_mode(true); CPRINTS("Ping Cr50"); msleep(1); - enable_packet_mode(false); + board_enable_packet_mode(false); rv = vboot_get_rw_hash(&hash); if (rv) @@ -174,17 +200,21 @@ static enum cr50_comm_err verify_hash(void) return cmd_to_cr50(CR50_COMM_CMD_VERIFY_HASH, hash, SHA256_DIGEST_SIZE); } +/* LCOV_EXCL_START - TODO(b/172210316) implement is_battery_ready(), and remove + * this lcov excl. + */ static enum cr50_comm_err set_boot_mode(uint8_t mode) { enum cr50_comm_err rv; CPRINTS("Setting boot mode to %s(%d)", boot_mode_to_string(mode), mode); - rv = cmd_to_cr50(CR50_COMM_CMD_SET_BOOT_MODE, - &mode, sizeof(enum boot_mode)); + rv = cmd_to_cr50(CR50_COMM_CMD_SET_BOOT_MODE, &mode, + sizeof(enum boot_mode)); if (rv != CR50_COMM_SUCCESS) CPRINTS("Failed to set boot mode"); return rv; } +/* LCOV_EXCL_STOP */ static bool pd_comm_enabled; @@ -199,10 +229,19 @@ bool vboot_allow_usb_pd(void) return pd_comm_enabled; } +#ifdef TEST_BUILD +void vboot_disable_pd(void) +{ + pd_comm_enabled = false; +} +#endif + +/* LCOV_EXCL_START - This is just a stub intended to be overridden */ __overridable void show_critical_error(void) { CPRINTS("%s", __func__); } +/* LCOV_EXCL_STOP */ static void verify_and_jump(void) { @@ -227,14 +266,16 @@ static void verify_and_jump(void) } } +/* LCOV_EXCL_START - This is just a stub intended to be overridden */ __overridable void show_power_shortage(void) { CPRINTS("%s", __func__); } +/* LCOV_EXCL_STOP */ static bool is_battery_ready(void) { - /* TODO: Add battery check (https://crbug.com/1045216) */ + /* TODO(b/172210316): Add battery check */ return true; } @@ -257,8 +298,8 @@ void vboot_main(void) (system_get_reset_flags() & EC_RESET_FLAG_STAY_IN_RO)) { if (system_is_manual_recovery()) CPRINTS("In recovery mode"); - if (!IS_ENABLED(CONFIG_BATTERY) - && !IS_ENABLED(HAS_TASK_KEYSCAN)) { + if (!IS_ENABLED(CONFIG_BATTERY) && + !IS_ENABLED(HAS_TASK_KEYSCAN)) { /* * For Chromeboxes, we relax security by allowing PD in * RO. Attackers don't gain meaningful advantage on @@ -276,12 +317,16 @@ void vboot_main(void) * If battery is drained or bad, we will boot in NO_BOOT mode to * inform the user of the problem. */ + /* LCOV_EXCL_START - TODO(b/172210316) implement + * is_battery_ready(), and remove this lcov excl. + */ if (!is_battery_ready()) { CPRINTS("Battery not ready or bad"); if (set_boot_mode(BOOT_MODE_NO_BOOT) == - CR50_COMM_SUCCESS) + CR50_COMM_SUCCESS) enable_pd(); } + /* LCOV_EXCL_STOP */ /* We'll enter recovery mode immediately, later, or never. */ return; diff --git a/common/vboot/vb21_lib.c b/common/vboot/vb21_lib.c index 4e215c14e5..3a380c24eb 100644 --- a/common/vboot/vb21_lib.c +++ b/common/vboot/vb21_lib.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -47,12 +47,11 @@ int vb21_is_signature_valid(const struct vb21_signature *sig, const struct vb21_packed_key *vb21_get_packed_key(void) { - return (const struct vb21_packed_key *)(CONFIG_RO_PUBKEY_ADDR); + return (const struct vb21_packed_key *)(CONFIG_RO_PUBKEY_READ_ADDR); } static void read_rwsig_info(struct ec_response_rwsig_info *r) { - const struct vb21_packed_key *vb21_key; int rv; @@ -61,17 +60,21 @@ static void read_rwsig_info(struct ec_response_rwsig_info *r) r->sig_alg = vb21_key->sig_alg; r->hash_alg = vb21_key->hash_alg; r->key_version = vb21_key->key_version; - { BUILD_ASSERT(sizeof(r->key_id) == sizeof(vb21_key->id), - "key ID sizes must match"); } - { BUILD_ASSERT(sizeof(vb21_key->id) == sizeof(vb21_key->id.raw), - "key ID sizes must match"); } + { + BUILD_ASSERT(sizeof(r->key_id) == sizeof(vb21_key->id), + "key ID sizes must match"); + } + { + BUILD_ASSERT(sizeof(vb21_key->id) == sizeof(vb21_key->id.raw), + "key ID sizes must match"); + } memcpy(r->key_id, vb21_key->id.raw, sizeof(r->key_id)); rv = vb21_is_packed_key_valid(vb21_key); r->key_is_valid = (rv == EC_SUCCESS); } -static int command_rwsig_info(int argc, char **argv) +static int command_rwsig_info(int argc, const char **argv) { int i; struct ec_response_rwsig_info r; diff --git a/common/vboot/vboot.c b/common/vboot/vboot.c index 1cf9cf7d80..162b396ba5 100644 --- a/common/vboot/vboot.c +++ b/common/vboot/vboot.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,16 +17,16 @@ #include "host_command.h" #include "rsa.h" #include "rwsig.h" -#include "stdbool.h" #include "sha256.h" #include "shared_mem.h" +#include "stdbool.h" #include "system.h" #include "usb_pd.h" -#include "vboot.h" #include "vb21_struct.h" +#include "vboot.h" -#define CPRINTS(format, args...) cprints(CC_VBOOT,"VB " format, ## args) -#define CPRINTF(format, args...) cprintf(CC_VBOOT,"VB " format, ## args) +#define CPRINTS(format, args...) cprints(CC_VBOOT, "VB " format, ##args) +#define CPRINTF(format, args...) cprintf(CC_VBOOT, "VB " format, ##args) static int has_matrix_keyboard(void) { @@ -45,34 +45,34 @@ static int verify_slot(enum ec_image slot) CPRINTS("Verifying %s", ec_image_to_string(slot)); - vb21_key = (const struct vb21_packed_key *)( - CONFIG_MAPPED_STORAGE_BASE + - CONFIG_EC_PROTECTED_STORAGE_OFF + - CONFIG_RO_PUBKEY_STORAGE_OFF); + vb21_key = + (const struct vb21_packed_key *)(CONFIG_MAPPED_STORAGE_BASE + + CONFIG_EC_PROTECTED_STORAGE_OFF + + CONFIG_RO_PUBKEY_STORAGE_OFF); rv = vb21_is_packed_key_valid(vb21_key); if (rv) { CPRINTS("Invalid key (%d)", rv); return EC_ERROR_VBOOT_KEY; } - key = (const struct rsa_public_key *) - ((const uint8_t *)vb21_key + vb21_key->key_offset); + key = (const struct rsa_public_key *)((const uint8_t *)vb21_key + + vb21_key->key_offset); if (slot == EC_IMAGE_RW_A) { data = (const uint8_t *)(CONFIG_MAPPED_STORAGE_BASE + - CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_A_STORAGE_OFF); - vb21_sig = (const struct vb21_signature *)( - CONFIG_MAPPED_STORAGE_BASE + - CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_A_SIGN_STORAGE_OFF); + CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_A_STORAGE_OFF); + vb21_sig = (const struct vb21_signature + *)(CONFIG_MAPPED_STORAGE_BASE + + CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_A_SIGN_STORAGE_OFF); } else { data = (const uint8_t *)(CONFIG_MAPPED_STORAGE_BASE + - CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_B_STORAGE_OFF); - vb21_sig = (const struct vb21_signature *)( - CONFIG_MAPPED_STORAGE_BASE + - CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_B_SIGN_STORAGE_OFF); + CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_B_STORAGE_OFF); + vb21_sig = (const struct vb21_signature + *)(CONFIG_MAPPED_STORAGE_BASE + + CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_B_SIGN_STORAGE_OFF); } rv = vb21_is_signature_valid(vb21_sig, vb21_key); @@ -187,7 +187,7 @@ void vboot_main(void) return; } - if (!(flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED)) { + if (!(crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED)) { /* * If hardware WP is disabled, PD communication is enabled. * We can return and wait for more power. diff --git a/common/vboot_hash.c b/common/vboot_hash.c index a08c707630..944092a12d 100644 --- a/common/vboot_hash.c +++ b/common/vboot_hash.c @@ -1,19 +1,22 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Verified boot hash computing module for Chrome EC */ +#include "builtin/assert.h" #include "clock.h" #include "common.h" #include "console.h" #include "flash.h" #include "hooks.h" #include "host_command.h" +#include "printf.h" #include "sha256.h" #include "shared_mem.h" #include "stdbool.h" +#include "stdint.h" #include "system.h" #include "task.h" #include "timer.h" @@ -22,7 +25,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_VBOOT, outstr) -#define CPRINTS(format, args...) cprints(CC_VBOOT, format, ## args) +#define CPRINTS(format, args...) cprints(CC_VBOOT, format, ##args) struct vboot_hash_tag { uint8_t hash[SHA256_DIGEST_SIZE]; @@ -30,11 +33,8 @@ struct vboot_hash_tag { uint32_t size; }; -#define VBOOT_HASH_SYSJUMP_TAG 0x5648 /* "VH" */ -#define VBOOT_HASH_SYSJUMP_VERSION 1 - -#define CHUNK_SIZE 1024 /* Bytes to hash per deferred call */ -#define WORK_INTERVAL_US 100 /* Delay between deferred calls */ +#define CHUNK_SIZE 1024 /* Bytes to hash per deferred call */ +#define WORK_INTERVAL_US 100 /* Delay between deferred calls */ /* Check that CHUNK_SIZE fits in shared memory. */ SHARED_MEM_CHECK_SIZE(CHUNK_SIZE); @@ -42,13 +42,17 @@ SHARED_MEM_CHECK_SIZE(CHUNK_SIZE); static uint32_t data_offset; static uint32_t data_size; static uint32_t curr_pos; -static const uint8_t *hash; /* Hash, or NULL if not valid */ +static const uint8_t *hash; /* Hash, or NULL if not valid */ static int want_abort; static int in_progress; -#define VBOOT_HASH_DEFERRED true -#define VBOOT_HASH_BLOCKING false +#define VBOOT_HASH_DEFERRED true +#define VBOOT_HASH_BLOCKING false -static struct sha256_ctx ctx; +static +#ifdef CONFIG_SOC_IT8XXX2_SHA256_HW_ACCELERATE + __attribute__((section(".__sha256_ram_block"))) +#endif + struct sha256_ctx ctx; int vboot_hash_in_progress(void) { @@ -67,6 +71,9 @@ void vboot_hash_abort(void) want_abort = 0; data_size = 0; hash = NULL; +#ifdef CONFIG_SHA256_HW_ACCELERATE + SHA256_abort(&ctx); +#endif } } @@ -94,7 +101,7 @@ static int read_and_hash_chunk(int offset, int size) return rv; } - rv = flash_read(offset, size, buf); + rv = crec_flash_read(offset, size, buf); if (rv == EC_SUCCESS) SHA256_update(&ctx, (const uint8_t *)buf, size); else @@ -115,10 +122,12 @@ static int read_and_hash_chunk(int offset, int size) static void hash_next_chunk(size_t size) { #ifdef CONFIG_MAPPED_STORAGE - flash_lock_mapped_storage(1); - SHA256_update(&ctx, (const uint8_t *)(CONFIG_MAPPED_STORAGE_BASE + - data_offset + curr_pos), size); - flash_lock_mapped_storage(0); + crec_flash_lock_mapped_storage(1); + SHA256_update(&ctx, + (const uint8_t *)((uintptr_t)CONFIG_MAPPED_STORAGE_BASE + + data_offset + curr_pos), + size); + crec_flash_lock_mapped_storage(0); #else if (read_and_hash_chunk(data_offset + curr_pos, size) != EC_SUCCESS) return; @@ -127,6 +136,8 @@ static void hash_next_chunk(size_t size) static void vboot_hash_all_chunks(void) { + char str_buf[hex_str_buf_size(SHA256_PRINT_SIZE)]; + do { size_t size = MIN(CHUNK_SIZE, data_size - curr_pos); hash_next_chunk(size); @@ -134,7 +145,9 @@ static void vboot_hash_all_chunks(void) } while (curr_pos < data_size); hash = SHA256_final(&ctx); - CPRINTS("hash done %ph", HEX_BUF(hash, SHA256_PRINT_SIZE)); + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(hash, SHA256_PRINT_SIZE)); + CPRINTS("hash done %s", str_buf); in_progress = 0; clock_enable_module(MODULE_FAST_CPU, 0); @@ -162,9 +175,14 @@ static void vboot_hash_next_chunk(void) curr_pos += size; if (curr_pos >= data_size) { + char str_buf[hex_str_buf_size(SHA256_PRINT_SIZE)]; + /* Store the final hash */ hash = SHA256_final(&ctx); - CPRINTS("hash done %ph", HEX_BUF(hash, SHA256_PRINT_SIZE)); + + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(hash, SHA256_PRINT_SIZE)); + CPRINTS("hash done %s", str_buf); in_progress = 0; @@ -208,8 +226,9 @@ static int vboot_hash_start(uint32_t offset, uint32_t size, * Make sure request fits inside flash. That is, you can't use this * command to peek at other memory. */ - if (offset > CONFIG_FLASH_SIZE || size > CONFIG_FLASH_SIZE || - offset + size > CONFIG_FLASH_SIZE || nonce_size < 0) { + if (offset > CONFIG_FLASH_SIZE_BYTES || + size > CONFIG_FLASH_SIZE_BYTES || + offset + size > CONFIG_FLASH_SIZE_BYTES || nonce_size < 0) { return EC_ERROR_INVAL; } @@ -268,9 +287,9 @@ int vboot_hash_invalidate(int offset, int size) */ static uint32_t get_rw_size(void) { -#ifdef CONFIG_VBOOT_EFS /* Only needed for EFS, which signs and verifies - * entire RW, thus not needed for EFS2, which - * verifies only the used image size. */ +#ifdef CONFIG_VBOOT_EFS /* Only needed for EFS, which signs and verifies \ + * entire RW, thus not needed for EFS2, which \ + * verifies only the used image size. */ return CONFIG_RW_SIZE; #else return system_get_image_used(EC_IMAGE_RW); @@ -279,21 +298,6 @@ static uint32_t get_rw_size(void) static void vboot_hash_init(void) { -#ifdef CONFIG_SAVE_VBOOT_HASH - const struct vboot_hash_tag *tag; - int version, size; - - tag = (const struct vboot_hash_tag *)system_get_jump_tag( - VBOOT_HASH_SYSJUMP_TAG, &version, &size); - if (tag && version == VBOOT_HASH_SYSJUMP_VERSION && - size == sizeof(*tag)) { - /* Already computed a hash, so don't recompute */ - CPRINTS("hash precomputed"); - hash = tag->hash; - data_offset = tag->offset; - data_size = tag->size; - } else -#endif #ifdef CONFIG_HOSTCMD_EVENTS /* * Don't auto-start hash computation if we've asked the host to enter @@ -306,9 +310,18 @@ static void vboot_hash_init(void) EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY))) #endif { - /* Start computing the hash of RW firmware */ - vboot_hash_start(flash_get_rw_offset(system_get_active_copy()), - get_rw_size(), NULL, 0, VBOOT_HASH_DEFERRED); + /* + * At this point, it's likely that EFS2 vboot_main() already + * requested the RW hash calculation once. + * + * Start computing the hash of RW firmware only if we haven't + * done it before. + */ + if (!hash) { + vboot_hash_start( + flash_get_rw_offset(system_get_active_copy()), + get_rw_size(), NULL, 0, VBOOT_HASH_DEFERRED); + } } } DECLARE_HOOK(HOOK_INIT, vboot_hash_init, HOOK_PRIO_INIT_VBOOT_HASH); @@ -321,27 +334,15 @@ int vboot_get_rw_hash(const uint8_t **dst) return rv; } -#ifdef CONFIG_SAVE_VBOOT_HASH - -static int vboot_hash_preserve_state(void) +int vboot_get_ro_hash(const uint8_t **dst) { - struct vboot_hash_tag tag; - - /* If we haven't finished our hash, nothing to save */ - if (!hash) - return EC_SUCCESS; - - memcpy(tag.hash, hash, sizeof(tag.hash)); - tag.offset = data_offset; - tag.size = data_size; - system_add_jump_tag(VBOOT_HASH_SYSJUMP_TAG, - VBOOT_HASH_SYSJUMP_VERSION, - sizeof(tag), &tag); - return EC_SUCCESS; + int rv = vboot_hash_start(CONFIG_EC_PROTECTED_STORAGE_OFF + + CONFIG_RO_STORAGE_OFF, + system_get_image_used(EC_IMAGE_RO), NULL, 0, + VBOOT_HASH_BLOCKING); + *dst = hash; + return rv; } -DECLARE_HOOK(HOOK_SYSJUMP, vboot_hash_preserve_state, HOOK_PRIO_DEFAULT); - -#endif /** * Returns the offset of RO or RW image if the either region is specifically @@ -361,10 +362,10 @@ static int get_offset(int offset) /****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_HASH -static int command_hash(int argc, char **argv) +static int command_hash(int argc, const char **argv) { - uint32_t offset = CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF; + uint32_t offset = + CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF; uint32_t size = CONFIG_RW_SIZE; char *e; @@ -376,9 +377,13 @@ static int command_hash(int argc, char **argv) ccprintf("(aborting)\n"); else if (in_progress) ccprintf("(in progress)\n"); - else if (hash) - ccprintf("%ph\n", HEX_BUF(hash, SHA256_DIGEST_SIZE)); - else + else if (hash) { + char str_buf[hex_str_buf_size(SHA256_DIGEST_SIZE)]; + + snprintf_hex_buffer(str_buf, sizeof(str_buf), + HEX_BUF(hash, SHA256_DIGEST_SIZE)); + ccprintf("%s\n", str_buf); + } else ccprintf("(invalid)\n"); return EC_SUCCESS; @@ -390,15 +395,14 @@ static int command_hash(int argc, char **argv) return EC_SUCCESS; } else if (!strcasecmp(argv[1], "rw")) { return vboot_hash_start( - get_offset(EC_VBOOT_HASH_OFFSET_ACTIVE), - get_rw_size(), - NULL, 0, VBOOT_HASH_DEFERRED); + get_offset(EC_VBOOT_HASH_OFFSET_ACTIVE), + get_rw_size(), NULL, 0, VBOOT_HASH_DEFERRED); } else if (!strcasecmp(argv[1], "ro")) { return vboot_hash_start( CONFIG_EC_PROTECTED_STORAGE_OFF + - CONFIG_RO_STORAGE_OFF, - system_get_image_used(EC_IMAGE_RO), - NULL, 0, VBOOT_HASH_DEFERRED); + CONFIG_RO_STORAGE_OFF, + system_get_image_used(EC_IMAGE_RO), NULL, 0, + VBOOT_HASH_DEFERRED); } return EC_ERROR_PARAM2; } @@ -418,12 +422,11 @@ static int command_hash(int argc, char **argv) if (*e) return EC_ERROR_PARAM3; - return vboot_hash_start(offset, size, - (const uint8_t *)&nonce, + return vboot_hash_start(offset, size, (const uint8_t *)&nonce, sizeof(nonce), VBOOT_HASH_DEFERRED); } else - return vboot_hash_start(offset, size, - NULL, 0, VBOOT_HASH_DEFERRED); + return vboot_hash_start(offset, size, NULL, 0, + VBOOT_HASH_DEFERRED); } DECLARE_CONSOLE_COMMAND(hash, command_hash, "[abort | ro | rw] | [ []]", @@ -433,8 +436,7 @@ DECLARE_CONSOLE_COMMAND(hash, command_hash, /* Host commands */ /* Fill in the response with the current hash status */ -static void fill_response(struct ec_response_vboot_hash *r, - int request_offset) +static void fill_response(struct ec_response_vboot_hash *r, int request_offset) { if (in_progress) r->status = EC_VBOOT_HASH_STATUS_BUSY; @@ -473,7 +475,7 @@ static int host_start_hash(const struct ec_params_vboot_hash *p) if (offset == EC_VBOOT_HASH_OFFSET_RO) size = system_get_image_used(EC_IMAGE_RO); else if ((offset == EC_VBOOT_HASH_OFFSET_ACTIVE) || - (offset == EC_VBOOT_HASH_OFFSET_UPDATE)) + (offset == EC_VBOOT_HASH_OFFSET_UPDATE)) size = get_rw_size(); offset = get_offset(offset); rv = vboot_hash_start(offset, size, p->nonce_data, p->nonce_size, @@ -527,6 +529,5 @@ host_command_vboot_hash(struct host_cmd_handler_args *args) return EC_RES_INVALID_PARAM; } } -DECLARE_HOST_COMMAND(EC_CMD_VBOOT_HASH, - host_command_vboot_hash, +DECLARE_HOST_COMMAND(EC_CMD_VBOOT_HASH, host_command_vboot_hash, EC_VER_MASK(0)); diff --git a/common/vec3.c b/common/vec3.c index dadf7715ff..4cf26ebf4c 100644 --- a/common/vec3.c +++ b/common/vec3.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,12 +6,11 @@ #include "common.h" #include "math.h" #include "math_util.h" -#include "vec3.h" #include "util.h" +#include "vec3.h" -static fpv3_t zero_initialized_vector = { - FLOAT_TO_FP(0.0f), FLOAT_TO_FP(0.0f), FLOAT_TO_FP(0.0f) -}; +static fpv3_t zero_initialized_vector = { FLOAT_TO_FP(0.0f), FLOAT_TO_FP(0.0f), + FLOAT_TO_FP(0.0f) }; void fpv3_zero(fpv3_t v) { diff --git a/common/version.c b/common/version.c index 1888fc0aef..fe082abbe0 100644 --- a/common/version.c +++ b/common/version.c @@ -1,24 +1,24 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Embed firmware version number in the binary */ -#include #include "common.h" #include "compile_time_macros.h" +#include "cros_version.h" #include "ec_commands.h" #include "ec_version.h" #include "stddef.h" #include "system.h" -#include "version.h" + +#include BUILD_ASSERT(CONFIG_ROLLBACK_VERSION >= 0); BUILD_ASSERT(CONFIG_ROLLBACK_VERSION <= INT32_MAX); -const struct image_data __keep current_image_data - __attribute__((section(".rodata.ver"))) = { +const struct image_data __keep current_image_data FIXED_SECTION("ver") = { .cookie1 = CROS_EC_IMAGE_DATA_COOKIE1, .version = CROS_EC_VERSION32, #ifndef TEST_BUILD @@ -26,12 +26,21 @@ const struct image_data __keep current_image_data #endif .rollback_version = CONFIG_ROLLBACK_VERSION, .cookie2 = CROS_EC_IMAGE_DATA_COOKIE2, + .cros_fwid = CROS_FWID32, + .cookie3 = CROS_EC_IMAGE_DATA_COOKIE3, }; BUILD_ASSERT(sizeof(CROS_EC_VERSION32) <= 32); +BUILD_ASSERT(sizeof(CROS_FWID32) <= 32); +#ifdef CONFIG_CROS_FWID_VERSION +const char build_info[] __keep __attribute__((section(".rodata.buildinfo"))) = + VERSION " " CROS_FWID32 " " DATE " " BUILDER; +#else const char build_info[] __keep __attribute__((section(".rodata.buildinfo"))) = VERSION " " DATE " " BUILDER; +#endif +/* LCOV_EXCL_START - this function doesn't work in GitLab */ static int get_num_commits(const struct image_data *data) { int numperiods = 0; @@ -60,9 +69,10 @@ static int get_num_commits(const struct image_data *data) } return (i == sizeof(data->version) ? 0 : ret); - } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START - this function doesn't work in GitLab */ int ver_get_num_commits(enum ec_image copy) { const struct image_data *data; @@ -72,3 +82,4 @@ int ver_get_num_commits(enum ec_image copy) data = ¤t_image_data; return data ? get_num_commits(data) : 0; } +/* LCOV_EXCL_STOP */ diff --git a/common/virtual_battery.c b/common/virtual_battery.c index ef33a4c67a..743f2a8801 100644 --- a/common/virtual_battery.c +++ b/common/virtual_battery.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,7 +14,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) #define BATT_MODE_UNINITIALIZED -1 @@ -25,8 +25,8 @@ enum batt_cmd_parse_state { IDLE = 0, /* initial state */ START = 1, /* received the register address (command code) */ - WRITE_VB, /* writing data bytes to the slave */ - READ_VB, /* reading data bytes to the slave */ + WRITE_VB, /* writing data bytes to the peripheral */ + READ_VB, /* reading data bytes to the peripheral */ }; static enum batt_cmd_parse_state sb_cmd_state; @@ -34,12 +34,10 @@ static uint8_t cache_hit; static const uint8_t *batt_cmd_head; static int acc_write_len; -int virtual_battery_handler(struct ec_response_i2c_passthru *resp, - int in_len, int *err_code, int xferflags, - int read_len, int write_len, - const uint8_t *out) +int virtual_battery_handler(struct ec_response_i2c_passthru *resp, int in_len, + int *err_code, int xferflags, int read_len, + int write_len, const uint8_t *out) { - #if defined(CONFIG_BATTERY_PRESENT_GPIO) || \ defined(CONFIG_BATTERY_PRESENT_CUSTOM) /* @@ -74,7 +72,7 @@ int virtual_battery_handler(struct ec_response_i2c_passthru *resp, } else { sb_cmd_state = READ_VB; *err_code = virtual_battery_operation(batt_cmd_head, - NULL, 0, 0); + NULL, 0, 0); /* * If the reg is not handled by virtual battery, we * do not support it. @@ -105,9 +103,6 @@ int virtual_battery_handler(struct ec_response_i2c_passthru *resp, if (cache_hit) *err_code = 0; break; - default: - reset_parse_state(); - return EC_ERROR_INVAL; } acc_write_len += write_len; @@ -118,10 +113,8 @@ int virtual_battery_handler(struct ec_response_i2c_passthru *resp, /* write to virtual battery */ case START: case WRITE_VB: - virtual_battery_operation(batt_cmd_head, - NULL, - 0, - acc_write_len); + virtual_battery_operation(batt_cmd_head, NULL, 0, + acc_write_len); break; /* read from virtual battery */ case READ_VB: @@ -129,16 +122,19 @@ int virtual_battery_handler(struct ec_response_i2c_passthru *resp, read_len += in_len; memset(&resp->data[0], 0, read_len); virtual_battery_operation(batt_cmd_head, - &resp->data[0], - read_len, - 0); + &resp->data[0], + read_len, 0); } break; + /* LCOV_EXCL_START - Unreachable in IDLE state and remaining + * states covered above. + */ default: reset_parse_state(); return EC_ERROR_INVAL; - } + /* LCOV_EXCL_STOP */ + /* Reset the state in the end of messages */ reset_parse_state(); } @@ -166,18 +162,29 @@ void copy_memmap_string(uint8_t *dest, int offset, int len) memmap_str = host_get_memmap(offset); /* memmap_str might not be NULL terminated */ memmap_strlen = *(memmap_str + EC_MEMMAP_TEXT_MAX - 1) == '\0' ? - strlen(memmap_str) : EC_MEMMAP_TEXT_MAX; + strlen(memmap_str) : + EC_MEMMAP_TEXT_MAX; dest[0] = memmap_strlen; memcpy(dest + 1, memmap_str, MIN(memmap_strlen, len - 1)); } -int virtual_battery_operation(const uint8_t *batt_cmd_head, - uint8_t *dest, - int read_len, - int write_len) +static void copy_battery_info_string(uint8_t *dst, const uint8_t *src, int len) +{ + if (len == 0) + return; + + dst[0] = strlen(src); + strncpy(dst + 1, src, len - 1); +} + +int virtual_battery_operation(const uint8_t *batt_cmd_head, uint8_t *dest, + int read_len, int write_len) { int val; int year, month, day; +#ifdef CONFIG_BATTERY_SMART + char str[32]; +#endif /* * We cache battery operational mode locally for both read and write * commands. If MODE_CAPACITY bit is set, battery capacity will be @@ -192,6 +199,14 @@ int virtual_battery_operation(const uint8_t *batt_cmd_head, * are two bytes. */ int bounded_read_len = MIN(read_len, 2); + const struct battery_static_info *bs; + + if (IS_ENABLED(CONFIG_BATTERY_V2)) + /* + * TODO: To support multiple batteries, we need to translate + * i2c address to a battery index. + */ + bs = &battery_static[BATT_IDX_MAIN]; curr_batt = charger_current_battery_params(); switch (*batt_cmd_head) { @@ -213,9 +228,8 @@ int virtual_battery_operation(const uint8_t *batt_cmd_head, * typical SB defaults. */ batt_mode_cache = - MODE_INTERNAL_CHARGE_CONTROLLER | - MODE_ALARM | - MODE_CHARGER; + MODE_INTERNAL_CHARGE_CONTROLLER | + MODE_ALARM | MODE_CHARGER; memcpy(dest, &batt_mode_cache, bounded_read_len); } @@ -244,9 +258,21 @@ int virtual_battery_operation(const uint8_t *batt_cmd_head, return EC_ERROR_BUSY; memcpy(dest, &(curr_batt->current), bounded_read_len); break; + case SB_AVERAGE_CURRENT: + /* This may cause an i2c transaction */ + if (curr_batt->flags & BATT_FLAG_BAD_AVERAGE_CURRENT) + return EC_ERROR_BUSY; + val = battery_get_avg_current(); + memcpy(dest, &val, bounded_read_len); + break; + case SB_MAX_ERROR: + /* report as 3% to make kernel happy */ + val = BATTERY_LEVEL_SHUTDOWN; + memcpy(dest, &val, bounded_read_len); + break; case SB_FULL_CHARGE_CAPACITY: if (curr_batt->flags & BATT_FLAG_BAD_FULL_CAPACITY || - curr_batt->flags & BATT_FLAG_BAD_VOLTAGE) + curr_batt->flags & BATT_FLAG_BAD_VOLTAGE) return EC_ERROR_BUSY; val = curr_batt->full_capacity; if (batt_mode_cache & MODE_CAPACITY) @@ -276,7 +302,7 @@ int virtual_battery_operation(const uint8_t *batt_cmd_head, break; case SB_REMAINING_CAPACITY: if (curr_batt->flags & BATT_FLAG_BAD_REMAINING_CAPACITY || - curr_batt->flags & BATT_FLAG_BAD_VOLTAGE) + curr_batt->flags & BATT_FLAG_BAD_VOLTAGE) return EC_ERROR_BUSY; val = curr_batt->remaining_capacity; if (batt_mode_cache & MODE_CAPACITY) @@ -284,10 +310,24 @@ int virtual_battery_operation(const uint8_t *batt_cmd_head, memcpy(dest, &val, bounded_read_len); break; case SB_MANUFACTURER_NAME: - copy_memmap_string(dest, EC_MEMMAP_BATT_MFGR, read_len); + if (IS_ENABLED(CONFIG_BATTERY_V2)) + copy_battery_info_string(dest, bs->manufacturer_ext, + read_len); + else + copy_memmap_string(dest, EC_MEMMAP_BATT_MFGR, read_len); break; case SB_DEVICE_NAME: - copy_memmap_string(dest, EC_MEMMAP_BATT_MODEL, read_len); + if (IS_ENABLED(CONFIG_BATTERY_V2)) + copy_battery_info_string(dest, bs->model_ext, read_len); + else + copy_memmap_string(dest, EC_MEMMAP_BATT_MODEL, + read_len); + break; + case SB_DEVICE_CHEMISTRY: + if (IS_ENABLED(CONFIG_BATTERY_V2)) + copy_battery_info_string(dest, bs->type_ext, read_len); + else + copy_memmap_string(dest, EC_MEMMAP_BATT_TYPE, read_len); break; case SB_AVERAGE_TIME_TO_FULL: /* This may cause an i2c transaction */ @@ -301,6 +341,30 @@ int virtual_battery_operation(const uint8_t *batt_cmd_head, return EC_ERROR_INVAL; memcpy(dest, &val, bounded_read_len); break; +#ifdef CONFIG_BATTERY_SMART + /* + * Only supports sb for now, respective gauges should implement their + * function. + */ + case SB_RUN_TIME_TO_EMPTY: + /* This may cause an i2c transaction */ + if (battery_run_time_to_empty(&val)) + return EC_ERROR_INVAL; + memcpy(dest, &val, bounded_read_len); + break; +#endif + case SB_CHARGING_CURRENT: + if (curr_batt->flags & BATT_FLAG_BAD_DESIRED_CURRENT) + return EC_ERROR_BUSY; + val = curr_batt->desired_current; + memcpy(dest, &val, bounded_read_len); + break; + case SB_CHARGING_VOLTAGE: + if (curr_batt->flags & BATT_FLAG_BAD_DESIRED_VOLTAGE) + return EC_ERROR_BUSY; + val = curr_batt->desired_voltage; + memcpy(dest, &val, bounded_read_len); + break; case SB_MANUFACTURE_DATE: /* This may cause an i2c transaction */ if (!battery_manufacture_date(&year, &month, &day)) { @@ -315,13 +379,50 @@ int virtual_battery_operation(const uint8_t *batt_cmd_head, } memcpy(dest, &val, bounded_read_len); break; +#ifdef CONFIG_BATTERY_SMART + case SB_MANUFACTURER_DATA: + if (read_len > ARRAY_SIZE(str)) + return EC_ERROR_INVAL; + /* This may cause an i2c transaction */ + if (battery_manufacturer_data(str, ARRAY_SIZE(str))) + return EC_ERROR_INVAL; + memcpy(dest, &str, read_len); + break; + + case SB_MANUFACTURE_INFO: + if (sb_read_string(*batt_cmd_head, str, sizeof(str))) + return EC_ERROR_INVAL; + memcpy(dest, &str, MIN(read_len, sizeof(str))); + break; +#endif case SB_MANUFACTURER_ACCESS: - /* No manuf. access reg access allowed over VB interface */ +#ifdef CONFIG_BATTERY_SMART + if ((write_len >= 2) && (write_len <= 3)) { + val = batt_cmd_head[1] | batt_cmd_head[2] << 8; + /* This may cause an i2c transaction */ + if (!battery_manufacturer_access(val)) + return EC_SUCCESS; + } +#endif return EC_ERROR_INVAL; + case SB_SPECIFICATION_INFO: + /* v1.1 without PEC, no scale factor to voltage and current */ + val = 0x0011; + memcpy(dest, &val, bounded_read_len); + break; +#ifdef CONFIG_SMART_BATTERY_OPTIONAL_MFG_FUNC + case SB_OPTIONAL_MFG_FUNC1: + case SB_OPTIONAL_MFG_FUNC2: + case SB_OPTIONAL_MFG_FUNC3: + case SB_OPTIONAL_MFG_FUNC4: + if (sb_read(*batt_cmd_head, &val)) + return EC_ERROR_INVAL; + memcpy(dest, &val, bounded_read_len); + break; +#endif default: CPRINTS("Unhandled VB reg %x", *batt_cmd_head); return EC_ERROR_INVAL; } return EC_SUCCESS; } - diff --git a/common/vstore.c b/common/vstore.c index 9b4636397c..254a515b48 100644 --- a/common/vstore.c +++ b/common/vstore.c @@ -1,4 +1,4 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2015 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,7 +22,7 @@ #include "system.h" #include "util.h" -#define VSTORE_SYSJUMP_TAG 0x5653 /* "VS" */ +#define VSTORE_SYSJUMP_TAG 0x5653 /* "VS" */ #define VSTORE_HOOK_VERSION 1 struct vstore_slot { @@ -32,7 +32,7 @@ struct vstore_slot { static struct vstore_slot vstore_slots[CONFIG_VSTORE_SLOT_COUNT]; static const int vstore_size = - sizeof(struct vstore_slot) * CONFIG_VSTORE_SLOT_COUNT; + sizeof(struct vstore_slot) * CONFIG_VSTORE_SLOT_COUNT; BUILD_ASSERT(ARRAY_SIZE(vstore_slots) <= EC_VSTORE_SLOT_MAX); /* @@ -97,7 +97,7 @@ static enum ec_status vstore_write(struct host_cmd_handler_args *args) } DECLARE_HOST_COMMAND(EC_CMD_VSTORE_WRITE, vstore_write, EC_VER_MASK(0)); -static void vstore_clear_lock(void) +test_export_static void vstore_clear_lock(void) { int i; diff --git a/common/webusb_desc.c b/common/webusb_desc.c index 41d39006e0..e2f51b4c0f 100644 --- a/common/webusb_desc.c +++ b/common/webusb_desc.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/common/wireless.c b/common/wireless.c index d1f5cad645..dfc2d4843e 100644 --- a/common/wireless.c +++ b/common/wireless.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -34,13 +34,11 @@ static int suspend_flags = CONFIG_WIRELESS_SUSPEND; static void wireless_enable(int flags) { #ifdef WIRELESS_GPIO_WLAN - gpio_set_level(WIRELESS_GPIO_WLAN, - flags & EC_WIRELESS_SWITCH_WLAN); + gpio_set_level(WIRELESS_GPIO_WLAN, flags & EC_WIRELESS_SWITCH_WLAN); #endif #ifdef WIRELESS_GPIO_WWAN - gpio_set_level(WIRELESS_GPIO_WWAN, - flags & EC_WIRELESS_SWITCH_WWAN); + gpio_set_level(WIRELESS_GPIO_WWAN, flags & EC_WIRELESS_SWITCH_WWAN); #endif #ifdef WIRELESS_GPIO_BLUETOOTH @@ -57,7 +55,6 @@ static void wireless_enable(int flags) !(flags & EC_WIRELESS_SWITCH_WLAN_POWER)); #endif /* CONFIG_WLAN_POWER_ACTIVE_LOW */ #endif - } static int wireless_get(void) @@ -126,7 +123,7 @@ static enum ec_status wireless_enable_cmd(struct host_cmd_handler_args *args) (p->now_flags & p->now_mask)); suspend_flags = (suspend_flags & ~p->suspend_mask) | - (p->suspend_flags & p->suspend_mask); + (p->suspend_flags & p->suspend_mask); /* And return the current flags */ r->now_flags = wireless_get(); @@ -134,11 +131,10 @@ static enum ec_status wireless_enable_cmd(struct host_cmd_handler_args *args) args->response_size = sizeof(*r); return EC_RES_SUCCESS; } -DECLARE_HOST_COMMAND(EC_CMD_SWITCH_ENABLE_WIRELESS, - wireless_enable_cmd, +DECLARE_HOST_COMMAND(EC_CMD_SWITCH_ENABLE_WIRELESS, wireless_enable_cmd, EC_VER_MASK(0) | EC_VER_MASK(1)); -static int command_wireless(int argc, char **argv) +static int command_wireless(int argc, const char **argv) { char *e; int i; @@ -164,6 +160,5 @@ static int command_wireless(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(wireless, command_wireless, - "[now [suspend]]", +DECLARE_CONSOLE_COMMAND(wireless, command_wireless, "[now [suspend]]", "Get/set wireless flags"); diff --git a/core/build.mk b/core/build.mk new file mode 100644 index 0000000000..407550bf7c --- /dev/null +++ b/core/build.mk @@ -0,0 +1,20 @@ +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +CORE_RW_OUT:=$(out)/RW/core/$(CORE) +CORE_RO_OUT:=$(out)/RO/core/$(CORE) + +cmd_asm_define_to_h = grep ASM_DEFINE $< \ + | sed 's/.*__ASM_DEFINE__\s\(.*\)\s\#\(.*\)"/\#define \1 \2/g' > $@ + +$(CORE_RO_OUT)/asm_offsets.h:$(CORE_RO_OUT)/asm_offsets.s + $(call quiet,asm_define_to_h, ) +$(CORE_RW_OUT)/asm_offsets.h:$(CORE_RW_OUT)/asm_offsets.s + $(call quiet,asm_define_to_h, ) + +$(CORE_RW_OUT)/asm_offsets.s: core/$(CORE)/asm_offsets.c +$(CORE_RW_OUT)/asm_offsets.h: $(CORE_RW_OUT)/asm_offsets.s + +$(CORE_RO_OUT)/asm_offsets.s: core/$(CORE)/asm_offsets.c +$(CORE_RO_OUT)/asm_offsets.h: $(CORE_RO_OUT)/asm_offsets.s diff --git a/core/cortex-m/aes.S b/core/cortex-m/aes.S deleted file mode 120000 index 39d1286943..0000000000 --- a/core/cortex-m/aes.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/boringssl/core/cortex-m/aes.S \ No newline at end of file diff --git a/core/cortex-m/atomic.h b/core/cortex-m/atomic.h index 736d5887b4..92ecdd96e5 100644 --- a/core/cortex-m/atomic.h +++ b/core/cortex-m/atomic.h @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,69 +8,37 @@ #ifndef __CROS_EC_ATOMIC_H #define __CROS_EC_ATOMIC_H +#include "atomic_t.h" #include "common.h" -/** - * Implements atomic arithmetic operations on 32-bit integers. - * - * It used load/store exclusive. - * If you write directly the integer used as an atomic variable, - * you must either clear explicitly the exclusive monitor (using clrex) - * or do it in exception context (which clears the monitor). - */ -#define ATOMIC_OP(asm_op, a, v) do { \ - uint32_t reg0, reg1; \ - \ - __asm__ __volatile__("1: ldrex %0, [%2]\n" \ - #asm_op" %0, %0, %3\n" \ - " strex %1, %0, [%2]\n" \ - " teq %1, #0\n" \ - " bne 1b" \ - : "=&r" (reg0), "=&r" (reg1) \ - : "r" (a), "r" (v) : "cc"); \ -} while (0) - -/* - * The atomic_* functions are marked as deprecated as a part of the process of - * transaction to Zephyr compatible atomic functions. These prefixes will be - * removed in the following patches. Please see b:169151160 for more details. - */ - -static inline void deprecated_atomic_clear_bits(uint32_t volatile *addr, - uint32_t bits) +static inline atomic_val_t atomic_clear_bits(atomic_t *addr, atomic_val_t bits) { - ATOMIC_OP(bic, addr, bits); + return __atomic_fetch_and(addr, ~bits, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_or(uint32_t volatile *addr, uint32_t bits) +static inline atomic_val_t atomic_or(atomic_t *addr, atomic_val_t bits) { - ATOMIC_OP(orr, addr, bits); + return __atomic_fetch_or(addr, bits, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_add(uint32_t volatile *addr, - uint32_t value) +static inline atomic_val_t atomic_add(atomic_t *addr, atomic_val_t value) { - ATOMIC_OP(add, addr, value); + return __atomic_fetch_add(addr, value, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_sub(uint32_t volatile *addr, - uint32_t value) +static inline atomic_val_t atomic_sub(atomic_t *addr, atomic_val_t value) { - ATOMIC_OP(sub, addr, value); + return __atomic_fetch_sub(addr, value, __ATOMIC_SEQ_CST); } -static inline uint32_t deprecated_atomic_read_clear(uint32_t volatile *addr) +static inline atomic_val_t atomic_clear(atomic_t *addr) { - uint32_t ret, tmp; - - __asm__ __volatile__(" mov %3, #0\n" - "1: ldrex %0, [%2]\n" - " strex %1, %3, [%2]\n" - " teq %1, #0\n" - " bne 1b" - : "=&r" (ret), "=&r" (tmp) - : "r" (addr), "r" (0) : "cc"); + return __atomic_exchange_n(addr, 0, __ATOMIC_SEQ_CST); +} - return ret; +static inline atomic_val_t atomic_and(atomic_t *addr, atomic_val_t bits) +{ + return __atomic_fetch_and(addr, bits, __ATOMIC_SEQ_CST); } -#endif /* __CROS_EC_ATOMIC_H */ + +#endif /* __CROS_EC_ATOMIC_H */ diff --git a/core/cortex-m/build.mk b/core/cortex-m/build.mk index 2bcf32317d..9562a31ec4 100644 --- a/core/cortex-m/build.mk +++ b/core/cortex-m/build.mk @@ -1,21 +1,38 @@ # -*- makefile -*- -# Copyright 2012 The Chromium OS Authors. All rights reserved. +# Copyright 2012 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Cortex-M4 core OS files build # -# Use coreboot-sdk -$(call set-option,CROSS_COMPILE,\ - $(CROSS_COMPILE_arm),\ - /opt/coreboot-sdk/bin/arm-eabi-) - # FPU compilation flags -CFLAGS_FPU-$(CONFIG_FPU)=-mfpu=fpv4-sp-d16 -mfloat-abi=hard +CFLAGS_FPU-$(CONFIG_FPU)=-mfloat-abi=hard +ifeq ($(cc-name),gcc) +# -mfpu=auto will choose correct hardware based on settings of -mcpu and -march +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html. +# +# According to the above doc "-mfpu=auto" is the default and shouldn't be +# required, but compilation using gcc fails without the flag. +# +# clang does not support "-mfpu=auto" flag, but will choose the correct floating +# point unit based on the -mcpu flag: +# https://lists.llvm.org/pipermail/llvm-dev/2018-September/126468.html +CFLAGS_FPU-$(CONFIG_FPU)+=-mfpu=auto +endif # CPU specific compilation flags -CFLAGS_CPU+=-mthumb -Os -mno-sched-prolog +CFLAGS_CPU+=-mthumb +ifeq ($(cc-name),clang) +CFLAGS_CPU+=-Oz # Like -Os (and thus -O2), but reduces code size further. +# b/256193799: Reduce inline threshold to decrease code size. +CFLAGS_CPU+=-Wl,-mllvm -Wl,-inline-threshold=-10 +# Link compiler-rt when using clang, so clang finds the builtins it provides. +LDFLAGS_EXTRA+=-lclang_rt.builtins-armv7m +else +CFLAGS_CPU+=-Os +CFLAGS_CPU+=-mno-sched-prolog +endif CFLAGS_CPU+=-mno-unaligned-access CFLAGS_CPU+=$(CFLAGS_FPU-y) @@ -24,11 +41,14 @@ CFLAGS_CPU+=-flto LDFLAGS_EXTRA+=-flto endif -core-y=cpu.o init.o ldivmod.o llsr.o uldivmod.o vecttable.o -core-$(CONFIG_AES)+=aes.o -core-$(CONFIG_AES_GCM)+=ghash.o +core-y=cpu.o debug.o init.o vecttable.o +# When using clang, we get these as builtins from compiler-rt. +ifneq ($(cc-name),clang) +core-y+=ldivmod.o llsr.o uldivmod.o +endif core-$(CONFIG_ARMV7M_CACHE)+=cache.o core-$(CONFIG_COMMON_PANIC_OUTPUT)+=panic.o core-$(CONFIG_COMMON_RUNTIME)+=switch.o task.o +core-$(CONFIG_FPU)+=fpu.o core-$(CONFIG_WATCHDOG)+=watchdog.o core-$(CONFIG_MPU)+=mpu.o diff --git a/core/cortex-m/cache.S b/core/cortex-m/cache.S index 0a3d3bb67d..d5089a920e 100644 --- a/core/cortex-m/cache.S +++ b/core/cortex-m/cache.S @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/core/cortex-m/config_core.h b/core/cortex-m/config_core.h index 0665b28852..3b9ccb89e6 100644 --- a/core/cortex-m/config_core.h +++ b/core/cortex-m/config_core.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,6 +10,4 @@ #define BFD_ARCH arm #define BFD_FORMAT "elf32-littlearm" -#define CONFIG_SOFTWARE_PANIC - #endif /* __CROS_EC_CONFIG_CORE_H */ diff --git a/core/cortex-m/cpu.c b/core/cortex-m/cpu.c index 96ac96a016..5a882bb532 100644 --- a/core/cortex-m/cpu.c +++ b/core/cortex-m/cpu.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -9,6 +9,10 @@ #include "cpu.h" #include "hooks.h" +#define STACK_IDX_REG_LR 5 +#define STACK_IDX_REG_PC 6 +#define STACK_IDX_REG_PSR 7 + void cpu_init(void) { /* Catch divide by 0 and unaligned access */ @@ -16,7 +20,42 @@ void cpu_init(void) /* Enable reporting of memory faults, bus faults and usage faults */ CPU_NVIC_SHCSR |= CPU_NVIC_SHCSR_MEMFAULTENA | - CPU_NVIC_SHCSR_BUSFAULTENA | CPU_NVIC_SHCSR_USGFAULTENA; + CPU_NVIC_SHCSR_BUSFAULTENA | + CPU_NVIC_SHCSR_USGFAULTENA; +} + +void cpu_return_from_exception_msp(void (*func)(void)) +{ + uint32_t *msp; + + __asm__ volatile("mrs %0, msp" : "=r"(msp)); + + msp[STACK_IDX_REG_LR] = 0; /* Will never return */ + msp[STACK_IDX_REG_PC] = (uint32_t)func; /* Return to this function */ + msp[STACK_IDX_REG_PSR] = (1 << 24); /* Just set thumb mode */ + + /* Return from exception using main stack */ + __asm__ volatile("bx %0" : : "r"(0xFFFFFFF9)); + + /* should not reach here */ + __builtin_unreachable(); +} + +void cpu_return_from_exception_psp(void (*func)(void)) +{ + uint32_t *psp; + + __asm__ volatile("mrs %0, psp" : "=r"(psp)); + + psp[STACK_IDX_REG_LR] = 0; /* Will never return */ + psp[STACK_IDX_REG_PC] = (uint32_t)func; /* Return to this function */ + psp[STACK_IDX_REG_PSR] = (1 << 24); /* Just set thumb mode */ + + /* Return from exception using main stack */ + __asm__ volatile("bx %0" : : "r"(0xFFFFFFFD)); + + /* should not reach here */ + __builtin_unreachable(); } #ifdef CONFIG_ARMV7M_CACHE @@ -50,16 +89,16 @@ void cpu_enable_caches(void) } } -static void cpu_sysjump_cache(void) +void cpu_disable_caches(void) { /* * Disable the I-cache and the D-cache - * The I-cache will be invalidated after the sysjump if needed + * The I-cache will be invalidated after the reboot/sysjump if needed * (e.g after a flash update). */ cpu_clean_invalidate_dcache(); CPU_NVIC_CCR &= ~(CPU_NVIC_CCR_ICACHE | CPU_NVIC_CCR_DCACHE); asm volatile("dsb; isb"); } -DECLARE_HOOK(HOOK_SYSJUMP, cpu_sysjump_cache, HOOK_PRIO_LAST); +DECLARE_HOOK(HOOK_SYSJUMP, cpu_disable_caches, HOOK_PRIO_LAST); #endif /* CONFIG_ARMV7M_CACHE */ diff --git a/core/cortex-m/cpu.h b/core/cortex-m/cpu.h index 5f7dd02801..d3144006f6 100644 --- a/core/cortex-m/cpu.h +++ b/core/cortex-m/cpu.h @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,72 +8,115 @@ #ifndef __CROS_EC_CPU_H #define __CROS_EC_CPU_H -#include #include "compile_time_macros.h" +#include "debug.h" + +#include /* Macro to access 32-bit registers */ -#define CPUREG(addr) (*(volatile uint32_t*)(addr)) +#define CPUREG(addr) (*(volatile uint32_t *)(addr)) -#define CPU_NVIC_ST_CTRL CPUREG(0xE000E010) -#define ST_ENABLE BIT(0) -#define ST_TICKINT BIT(1) -#define ST_CLKSOURCE BIT(2) -#define ST_COUNTFLAG BIT(16) +#define CPU_NVIC_ST_CTRL CPUREG(0xE000E010) +#define ST_ENABLE BIT(0) +#define ST_TICKINT BIT(1) +#define ST_CLKSOURCE BIT(2) +#define ST_COUNTFLAG BIT(16) /* Nested Vectored Interrupt Controller */ -#define CPU_NVIC_EN(x) CPUREG(0xe000e100 + 4 * (x)) -#define CPU_NVIC_DIS(x) CPUREG(0xe000e180 + 4 * (x)) -#define CPU_NVIC_UNPEND(x) CPUREG(0xe000e280 + 4 * (x)) -#define CPU_NVIC_PRI(x) CPUREG(0xe000e400 + 4 * (x)) +#define CPU_NVIC_EN(x) CPUREG(0xe000e100 + 4 * (x)) +#define CPU_NVIC_DIS(x) CPUREG(0xe000e180 + 4 * (x)) +#define CPU_NVIC_UNPEND(x) CPUREG(0xe000e280 + 4 * (x)) +#define CPU_NVIC_PRI(x) CPUREG(0xe000e400 + 4 * (x)) /* SCB AIRCR : Application interrupt and reset control register */ -#define CPU_NVIC_APINT CPUREG(0xe000ed0c) -#define CPU_NVIC_APINT_SYSRST BIT(2) /* System reset request */ -#define CPU_NVIC_APINT_PRIOGRP (BIT(8)|BIT(9)|BIT(10)) -#define CPU_NVIC_APINT_ENDIAN BIT(15) /* Endianness */ -#define CPU_NVIC_APINT_KEY_RD (0xFA05U << 16) -#define CPU_NVIC_APINT_KEY_WR (0x05FAU << 16) +#define CPU_NVIC_APINT CPUREG(0xe000ed0c) +#define CPU_NVIC_APINT_SYSRST BIT(2) /* System reset request */ +#define CPU_NVIC_APINT_PRIOGRP (BIT(8) | BIT(9) | BIT(10)) +#define CPU_NVIC_APINT_ENDIAN BIT(15) /* Endianness */ +#define CPU_NVIC_APINT_KEY_RD (0xFA05U << 16) +#define CPU_NVIC_APINT_KEY_WR (0x05FAU << 16) /* NVIC STIR : Software Trigger Interrupt Register */ -#define CPU_NVIC_SWTRIG CPUREG(0xe000ef00) +#define CPU_NVIC_SWTRIG CPUREG(0xe000ef00) /* SCB SCR : System Control Register */ -#define CPU_SCB_SYSCTRL CPUREG(0xe000ed10) +#define CPU_SCB_SYSCTRL CPUREG(0xe000ed10) -#define CPU_NVIC_CCR CPUREG(0xe000ed14) -#define CPU_NVIC_SHCSR CPUREG(0xe000ed24) -#define CPU_NVIC_CFSR CPUREG(0xe000ed28) -#define CPU_NVIC_HFSR CPUREG(0xe000ed2c) -#define CPU_NVIC_DFSR CPUREG(0xe000ed30) -#define CPU_NVIC_MFAR CPUREG(0xe000ed34) -#define CPU_NVIC_BFAR CPUREG(0xe000ed38) +#define CPU_NVIC_CCR CPUREG(0xe000ed14) +#define CPU_NVIC_SHCSR CPUREG(0xe000ed24) +#define CPU_NVIC_CFSR CPUREG(0xe000ed28) +#define CPU_NVIC_HFSR CPUREG(0xe000ed2c) +#define CPU_NVIC_DFSR CPUREG(0xe000ed30) +#define CPU_NVIC_MFAR CPUREG(0xe000ed34) +#define CPU_NVIC_BFAR CPUREG(0xe000ed38) enum { - CPU_NVIC_CFSR_BFARVALID = BIT(15), - CPU_NVIC_CFSR_MFARVALID = BIT(7), + CPU_NVIC_CFSR_BFARVALID = BIT(15), + CPU_NVIC_CFSR_MFARVALID = BIT(7), - CPU_NVIC_CCR_ICACHE = BIT(17), - CPU_NVIC_CCR_DCACHE = BIT(16), - CPU_NVIC_CCR_DIV_0_TRAP = BIT(4), - CPU_NVIC_CCR_UNALIGN_TRAP = BIT(3), + CPU_NVIC_CCR_ICACHE = BIT(17), + CPU_NVIC_CCR_DCACHE = BIT(16), + CPU_NVIC_CCR_DIV_0_TRAP = BIT(4), + CPU_NVIC_CCR_UNALIGN_TRAP = BIT(3), - CPU_NVIC_HFSR_DEBUGEVT = 1UL << 31, - CPU_NVIC_HFSR_FORCED = BIT(30), - CPU_NVIC_HFSR_VECTTBL = BIT(1), + CPU_NVIC_HFSR_DEBUGEVT = 1UL << 31, + CPU_NVIC_HFSR_FORCED = BIT(30), + CPU_NVIC_HFSR_VECTTBL = BIT(1), - CPU_NVIC_SHCSR_MEMFAULTENA = BIT(16), - CPU_NVIC_SHCSR_BUSFAULTENA = BIT(17), - CPU_NVIC_SHCSR_USGFAULTENA = BIT(18), + CPU_NVIC_SHCSR_MEMFAULTENA = BIT(16), + CPU_NVIC_SHCSR_BUSFAULTENA = BIT(17), + CPU_NVIC_SHCSR_USGFAULTENA = BIT(18), }; /* System Control Block: cache registers */ -#define CPU_SCB_CCSIDR CPUREG(0xe000ed80) -#define CPU_SCB_CCSELR CPUREG(0xe000ed84) -#define CPU_SCB_ICIALLU CPUREG(0xe000ef50) -#define CPU_SCB_DCISW CPUREG(0xe000ef60) -#define CPU_SCB_DCCISW CPUREG(0xe000ef74) +#define CPU_SCB_CCSIDR CPUREG(0xe000ed80) +#define CPU_SCB_CCSELR CPUREG(0xe000ed84) +#define CPU_SCB_ICIALLU CPUREG(0xe000ef50) +#define CPU_SCB_DCISW CPUREG(0xe000ef60) +#define CPU_SCB_DCCISW CPUREG(0xe000ef74) + +/* Floating Point Context Address Register */ +#define CPU_FPU_FPCAR CPUREG(0xe000ef38) + +/* + * As defined by Armv7-M Reference Manual B1.5.7 "Context state stacking on + * exception entry with the FP extension" the structure of the FPU state is: + * s0, s1, ..., s14, s15, fpscr. + */ +#define FPU_IDX_REG_FPSCR 16 +#define FPU_FPSCR_IOC BIT(0) /* Invalid operation */ +#define FPU_FPSCR_DZC BIT(1) /* Division by zero */ +#define FPU_FPSCR_OFC BIT(2) /* Overflow */ +#define FPU_FPSCR_UFC BIT(3) /* Underflow */ +#define FPU_FPSCR_IXC BIT(4) /* Inexact */ +#define FPU_FPSCR_IDC BIT(7) /* Input denormal */ +#define FPU_FPSCR_EXC_FLAGS \ + (FPU_FPSCR_IOC | FPU_FPSCR_DZC | FPU_FPSCR_OFC | FPU_FPSCR_UFC | \ + FPU_FPSCR_IXC | FPU_FPSCR_IDC) + +/* Bitfield values for EXC_RETURN. */ +#define EXC_RETURN_ES_MASK BIT(0) +#define EXC_RETURN_ES_NON_SECURE 0 +#define EXC_RETURN_ES_SECURE BIT(0) +#define EXC_RETURN_SPSEL_MASK BIT(2) +#define EXC_RETURN_SPSEL_MSP 0 +#define EXC_RETURN_SPSEL_PSP BIT(2) +#define EXC_RETURN_MODE_MASK BIT(3) +#define EXC_RETURN_MODE_HANDLER 0 +#define EXC_RETURN_MODE_THREAD BIT(3) +#define EXC_RETURN_FTYPE_MASK BIT(4) +#define EXC_RETURN_FTYPE_ON 0 +#define EXC_RETURN_FTYPE_OFF BIT(4) +#define EXC_RETURN_DCRS_MASK BIT(5) +#define EXC_RETURN_DCRS_OFF 0 +#define EXC_RETURN_DCRS_ON BIT(5) +#define EXC_RETURN_S_MASK BIT(6) +#define EXC_RETURN_S_NON_SECURE 0 +#define EXC_RETURN_S_SECURE BIT(6) /* Set up the cpu to detect faults */ void cpu_init(void); /* Enable the CPU I-cache and D-cache if they are not already enabled */ void cpu_enable_caches(void); +/* Disable the CPU I-cache and D-cache */ +void cpu_disable_caches(void); /* Invalidate the D-cache */ void cpu_invalidate_dcache(void); /* Clean and Invalidate the D-cache to the Point of Coherency */ @@ -84,6 +127,11 @@ void cpu_invalidate_dcache_range(uintptr_t base, unsigned int length); /* Clean and Invalidate a single range of the D-cache */ void cpu_clean_invalidate_dcache_range(uintptr_t base, unsigned int length); +/* Return to specified function from exception handler using main stack. */ +void cpu_return_from_exception_msp(void (*func)(void)); +/* Return to specified function from exception handler using process stack. */ +void cpu_return_from_exception_psp(void (*func)(void)); + /* Set the priority of the given IRQ in the NVIC (0 is highest). */ static inline void cpu_set_interrupt_priority(uint8_t irq, uint8_t priority) { @@ -92,10 +140,16 @@ static inline void cpu_set_interrupt_priority(uint8_t irq, uint8_t priority) if (priority > 7) priority = 7; - CPU_NVIC_PRI(irq / 4) = - (CPU_NVIC_PRI(irq / 4) & - ~(7 << prio_shift)) | - (priority << prio_shift); + CPU_NVIC_PRI(irq / 4) = (CPU_NVIC_PRI(irq / 4) & ~(7 << prio_shift)) | + (priority << prio_shift); +} + +static inline void cpu_enter_suspend_mode(void) +{ + /* Preserve debug sessions by not suspending when connected */ + if (!debugger_is_connected()) { + asm("wfi"); + } } #endif /* __CROS_EC_CPU_H */ diff --git a/core/cortex-m/debug.c b/core/cortex-m/debug.c new file mode 100644 index 0000000000..214e8dd177 --- /dev/null +++ b/core/cortex-m/debug.c @@ -0,0 +1,12 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "debug.h" +#include "stdbool.h" + +bool debugger_is_connected(void) +{ + return CPU_DHCSR & DHCSR_C_DEBUGEN; +} diff --git a/core/cortex-m/debug.h b/core/cortex-m/debug.h new file mode 100644 index 0000000000..30643268cb --- /dev/null +++ b/core/cortex-m/debug.h @@ -0,0 +1,37 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_DEBUG_H +#define __CROS_EC_DEBUG_H + +#include "common.h" +#include "stdbool.h" + +/* For Cortex-M0, see "C1.6.3 Debug Halting Control and Status Register, DHCSR" + * in the ARMv6-M Architecture Reference Manual. + * + * For other Cortex-M, see + * "C1.6.2 Debug Halting Control and Status Register, DHCSR" in the ARMv7-M + * Architecture Reference Manual or + * https://developer.arm.com/documentation/ddi0337/e/core-debug/core-debug-registers/debug-halting-control-and-status-register. + */ +#define CPU_DHCSR REG32(0xE000EDF0) +#define DHCSR_C_DEBUGEN BIT(0) +#define DHCSR_C_HALT BIT(1) +#define DHCSR_C_STEP BIT(2) +#define DHCSR_C_MASKINTS BIT(3) +#ifndef CHIP_CORE_CORTEX_M0 +#define DHCSR_C_SNAPSTALL BIT(5) /* Not available on Cortex-M0 */ +#endif +#define DHCSR_S_REGRDY BIT(16) +#define DHCSR_S_HALT BIT(17) +#define DHCSR_S_SLEEP BIT(18) +#define DHCSR_S_LOCKUP BIT(19) +#define DHCSR_S_RETIRE_ST BIT(24) +#define DHCSR_S_RESET_ST BIT(25) + +bool debugger_is_connected(void); + +#endif /* __CROS_EC_DEBUG_H */ diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S index fc24d181b5..6fb3b48568 100644 --- a/core/cortex-m/ec.lds.S +++ b/core/cortex-m/ec.lds.S @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -145,12 +145,6 @@ SECTIONS } > SHARED_LIB #endif .text : { -#ifdef SECTION_IS_RO - . = . + CONFIG_RO_HEAD_ROOM; -#endif -#ifdef SECTION_IS_RW - . = . + CONFIG_RW_HEAD_ROOM; -#endif *(.text.vecttable) . = ALIGN(4); __image_data_offset = .; @@ -261,6 +255,10 @@ SECTIONS KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN_COMPLETE)) __hooks_chipset_shutdown_complete_end = .; + __hooks_chipset_hard_off = .; + KEEP(*(.rodata.HOOK_CHIPSET_HARD_OFF)) + __hooks_chipset_hard_off_end = .; + __hooks_chipset_reset = .; KEEP(*(.rodata.HOOK_CHIPSET_RESET)) __hooks_chipset_reset_end = .; @@ -277,6 +275,12 @@ SECTIONS KEEP(*(.rodata.HOOK_TABLET_MODE_CHANGE)) __hooks_tablet_mode_change_end = .; +#ifdef CONFIG_BODY_DETECTION + __hooks_body_detect_change = .; + KEEP(*(.rodata.HOOK_BODY_DETECT_CHANGE)) + __hooks_body_detect_change_end = .; +#endif + __hooks_base_attached_change = .; KEEP(*(.rodata.HOOK_BASE_ATTACHED_CHANGE)) __hooks_base_attached_change_end = .; @@ -311,6 +315,10 @@ SECTIONS KEEP(*(.rodata.HOOK_USB_PD_CONNECT)) __hooks_usb_pd_connect_end = .; + __hooks_power_supply_change = .; + KEEP(*(.rodata.HOOK_POWER_SUPPLY_CHANGE)) + __hooks_power_supply_change_end = .; + __deferred_funcs = .; KEEP(*(.rodata.deferred)) __deferred_funcs_end = .; @@ -341,22 +349,66 @@ SECTIONS __init_rom_end = .; #endif /* CONFIG_CHIP_INIT_ROM_REGION */ -#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH) +#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS) . = ALIGN(64); KEEP(*(.google)) #endif + /* + * https://developer.arm.com/documentation/dui0475/c/the-arm-c-and-c---libraries/c---initialization--construction-and-destruction + */ + . = ALIGN(4); + __init_array_start = .; + *(.init_array*) + __init_array_end = .; + + /* + * Empty C++ exception index table. The exception index + * table is described in more detail in "Exception Handling + * ABI for ARM Architecture": + * https://github.com/ARM-software/abi-aa/blob/60a8eb8c55e999d74dac5e368fc9d7e36e38dda4/ehabi32/ehabi32.rst#54the-object-producer-interface + */ + __exidx_start = 0; + __exidx_end = 0; + . = ALIGN(4); } > EC_IMAGE_VMA_MEM_REGION AT > EC_IMAGE_LMA_MEM_REGION #ifdef CONFIG_CHIP_DATA_IN_INIT_ROM __data_lma_start = ORIGIN(ROM_RESIDENT_VMA); #define INIT_ROM_LMA (ORIGIN(ROM_RESIDENT_VMA) + SIZEOF(.data)) +#else +/* + * TODO(b/202863352): Unify clang and gcc behavior. + */ +#ifdef __clang__ +#if defined(SECTION_IS_RO) && defined(NPCX_RO_HEADER) + __data_lma_start = LOADADDR(.data) - SIZEOF(.header); +#else + __data_lma_start = LOADADDR(.data); +#endif #else __data_lma_start = .; +#endif #define INIT_ROM_LMA ORIGIN(ROM_RESIDENT_VMA) #endif + /* + * This SRAM section is not used by common/ or chip/stm32/, but + * available if particular boards want to move the vector table + * into SRAM for performance or mutability. + */ + .vtable : { + /* + * Vector table must be at the base of SRAM. The vector + * table section contains a RAM copy of the vector table used on + * STM chips for relocating the vector table. + */ + . = ALIGN(8); + *(.bss.vector_table) + . = ALIGN(8); + } > IRAM + #ifdef CONFIG_PRESERVE_LOGS .preserve_logs(NOLOAD) : { . = ALIGN(8); @@ -391,7 +443,7 @@ SECTIONS *(.bss.Tpm2_common) __bss_libtpm2_end = .; - *(.bss) + *(.bss*) /* * Reserve space for deferred function firing times. @@ -403,16 +455,7 @@ SECTIONS __deferred_until = .; . += (__deferred_funcs_end - __deferred_funcs) * (8 / 4); __deferred_until_end = .; - } > IRAM - .bss.slow : { - /* Region of RAM reclaimed from the little firmware(LFW). */ - *(.bss.slow) - /* - * Not replacing the loader, so .bss.slow is part of .bss. - * It needs to be followed by __bss_end so that .bss.slow - * will be zeroed by init. - */ . = ALIGN(4); __bss_end = .; } > IRAM @@ -476,6 +519,17 @@ SECTIONS __ram_free = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE) - (__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE); + /* + * Relocations are not supported, so make sure that there is no GOT + * section. See http://issuetracker.google.com/234507656#comment15. + */ + .got (NOLOAD) : + { + KEEP(*(.got*)); + } + ASSERT(SIZEOF(.got) == 0, "GOT section found, but not supported.\ + Make sure that all code is compiled without -fPIC.") + #ifdef CONFIG_CHIP_DATA_IN_INIT_ROM /* * .data is ROM resident, last section in the EC image is the .rodata @@ -490,20 +544,39 @@ SECTIONS #endif /* - * __flash_used is used in flash free calculations by the makefile. + * __flash_used and __flash_size is used in flash free calculations by + * the makefile. Note the difference between __flash_size and + * __config_flash_size. __flash_size is the flash size for the given + * image (RW, RO, etc.), while __config_flash_size is the *total* + * flash size. * __image_size is stored in the struct image_data header and used - * in hash calcuations. + * in hash calculations. */ __flash_used = FLASH_USED_END - ORIGIN(EC_IMAGE_LMA_MEM_REGION); + __flash_size = LENGTH(EC_IMAGE_LMA_MEM_REGION); #ifndef CONFIG_CHIP_INIT_ROM_REGION +#if defined(SECTION_IS_RW) && (CONFIG_FLASH_WRITE_SIZE > 4) + .rw_image_size_alignment FLASH_USED_END : AT(FLASH_USED_END) + { + . = ALIGN (CONFIG_FLASH_WRITE_SIZE); + } > FLASH = 0xFF + + __image_size = __flash_used + SIZEOF(.rw_image_size_alignment); +#else __image_size = __flash_used; +#endif +#if defined(SECTION_IS_RW) && (CONFIG_FLASH_WRITE_SIZE > 0) + /* Alignment is needed by flash_command_write() for RW update. */ + ASSERT(__image_size % CONFIG_FLASH_WRITE_SIZE == 0, + "Error: RW image is not aligned to CONFIG_FLASH_WRITE_SIZE") +#endif #endif /* CONFIG_CHIP_INIT_ROM_REGION */ -#ifdef CONFIG_FLASH +#ifdef CONFIG_FLASH_CROS /* * These linker labels are just for analysis and not used in the code. */ - __config_flash_size = CONFIG_FLASH_SIZE; + __config_flash_size = CONFIG_FLASH_SIZE_BYTES; __config_ro_size = CONFIG_RO_SIZE; __config_ec_protected_storage_size = CONFIG_EC_PROTECTED_STORAGE_SIZE; __config_rw_size = CONFIG_RW_SIZE; @@ -699,7 +772,7 @@ SECTIONS } > DRAM #endif -#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH)) +#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS)) /DISCARD/ : { *(.google) } #endif /DISCARD/ : { *(.ARM.*) } diff --git a/core/cortex-m/fpu.c b/core/cortex-m/fpu.c new file mode 100644 index 0000000000..6e897a5266 --- /dev/null +++ b/core/cortex-m/fpu.c @@ -0,0 +1,108 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "atomic.h" +#include "console.h" +#include "cpu.h" +#include "hooks.h" +#include "task.h" + +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPUTS(format, args...) cputs(CC_SYSTEM, format, ##args) + +/* Floating point unit common code */ + +/* + * As defined by Armv7-M Reference Manual B1.5.6 "Exception Entry Behavior", + * the structure of the saved context on the stack is: + * r0, r1, r2, r3, r12, lr, pc, psr, ... + */ +#define STACK_IDX_REG_LR 5 +#define STACK_IDX_REG_PC 6 + +static atomic_t fpu_exc_present; +static uint32_t fpu_pc; +static uint32_t fpu_lr; +static uint32_t fpu_fpscr; +static int fpu_task; + +static void fpu_warn(void) +{ + if (!IS_ENABLED(CONFIG_FPU_WARNINGS) || !fpu_exc_present) + return; + + CPRINTF("\n### FPU exception at PC=0x%08x LR=0x%08x ", fpu_pc, fpu_lr); + if (fpu_task == -1) + CPUTS("(exc) ###\n"); + else + CPRINTF("(task %d) ###\n", fpu_task); + + CPRINTF("### FPSCR=0x%08x => ", fpu_fpscr); + if (fpu_fpscr & FPU_FPSCR_IOC) + CPUTS("Invalid Operation "); + + if (fpu_fpscr & FPU_FPSCR_DZC) + CPUTS("Division By Zero "); + + if (fpu_fpscr & FPU_FPSCR_OFC) + CPUTS("Overflow "); + + if (fpu_fpscr & FPU_FPSCR_UFC) + CPUTS("Underflow "); + + if (fpu_fpscr & FPU_FPSCR_IXC) + CPUTS("Inexact "); + + if (fpu_fpscr & FPU_FPSCR_IDC) + CPUTS("Input Denormal "); + + CPUTS("###\n"); + + atomic_clear(&fpu_exc_present); +} + +DECLARE_DEFERRED(fpu_warn); + +test_mockable void __keep fpu_irq(uint32_t excep_lr, uint32_t excep_sp) +{ + /* + * Get address of exception FPU exception frame. FPCAR register points + * to the beginning of allocated FPU exception frame on the stack. + */ + uint32_t *fpu_state = (uint32_t *)CPU_FPU_FPCAR; + + if (IS_ENABLED(CONFIG_FPU_WARNINGS)) { + uint32_t *stack; + + if (!fpu_exc_present) { + /* + * Examine least significant 4 bits from exception LR + * to find which stack should be used to find the + * exception frame: + * - 0xd - CPU was in Thread Mode and PSP was used + * - 0x9 - CPU was in Thread Mode and MSP was used + * - 0x1 - CPU was in Handler Mode and MSP was used + */ + if ((excep_lr & 0xf) == 0xd) + asm("mrs %0, psp" : "=r"(stack)); + else + stack = (uint32_t *)excep_sp; + + fpu_pc = stack[STACK_IDX_REG_PC]; + fpu_lr = stack[STACK_IDX_REG_LR]; + fpu_fpscr = fpu_state[FPU_IDX_REG_FPSCR]; + fpu_task = -1; + + if ((excep_lr & 0xf) != 0x1) + fpu_task = task_get_current(); + + atomic_add(&fpu_exc_present, 1); + } + hook_call_deferred(&fpu_warn_data, 0); + } + + /* Clear FPSCR on stack */ + fpu_state[FPU_IDX_REG_FPSCR] &= ~FPU_FPSCR_EXC_FLAGS; +} diff --git a/core/cortex-m/ghash.S b/core/cortex-m/ghash.S deleted file mode 120000 index e9acbf4b25..0000000000 --- a/core/cortex-m/ghash.S +++ /dev/null @@ -1 +0,0 @@ -../../third_party/boringssl/core/cortex-m/ghash.S \ No newline at end of file diff --git a/core/cortex-m/include/fpu.h b/core/cortex-m/include/fpu.h new file mode 100644 index 0000000000..74862d00ab --- /dev/null +++ b/core/cortex-m/include/fpu.h @@ -0,0 +1,27 @@ +/* Copyright 2012 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Math utility functions for ARMv7 */ + +#ifndef __CROS_EC_FPU_H +#define __CROS_EC_FPU_H + +#ifdef CONFIG_FPU +static inline float sqrtf(float v) +{ + float root; + asm volatile("fsqrts %0, %1" : "=w"(root) : "w"(v)); + return root; +} + +static inline float fabsf(float v) +{ + float root; + asm volatile("fabss %0, %1" : "=w"(root) : "w"(v)); + return root; +} +#endif /* CONFIG_FPU */ + +#endif /* __CROS_EC_FPU_H */ diff --git a/core/cortex-m/include/math.h b/core/cortex-m/include/math.h deleted file mode 100644 index 1b336eb2aa..0000000000 --- a/core/cortex-m/include/math.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Math utility functions for ARMv7 */ - -#ifndef __CROS_EC_MATH_H -#define __CROS_EC_MATH_H - -#ifdef CONFIG_FPU -static inline float sqrtf(float v) -{ - float root; - asm volatile( - "fsqrts %0, %1" - : "=w" (root) - : "w" (v) - ); - return root; -} - -static inline float fabsf(float v) -{ - float root; - asm volatile( - "fabss %0, %1" - : "=w" (root) - : "w" (v) - ); - return root; -} -#endif /* CONFIG_FPU */ - -#endif /* __CROS_EC_MATH_H */ diff --git a/core/cortex-m/include/mpu.h b/core/cortex-m/include/mpu.h index 610728b501..75f95e7000 100644 --- a/core/cortex-m/include/mpu.h +++ b/core/cortex-m/include/mpu.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,7 +14,7 @@ /* * ARMv7-M SRAM region */ -#define CORTEX_M_SRAM_BASE 0x20000000 +#define CORTEX_M_SRAM_BASE 0x20000000 /* * Region assignment. 7 as the highest, a higher index has a higher priority. @@ -26,64 +26,64 @@ * made mutually exclusive. */ enum mpu_region { - REGION_DATA_RAM = 0, /* For internal data RAM */ - REGION_DATA_RAM2 = 1, /* Second region for unaligned size */ - REGION_CODE_RAM = 2, /* For internal code RAM */ - REGION_CODE_RAM2 = 3, /* Second region for unaligned size */ - REGION_STORAGE = 4, /* For mapped internal storage */ - REGION_STORAGE2 = 5, /* Second region for unaligned size */ - REGION_DATA_RAM_TEXT = 6, /* Exempt region of data RAM */ - REGION_CHIP_RESERVED = 7, /* Reserved for use in chip/ */ + REGION_DATA_RAM = 0, /* For internal data RAM */ + REGION_DATA_RAM2 = 1, /* Second region for unaligned size */ + REGION_CODE_RAM = 2, /* For internal code RAM */ + REGION_CODE_RAM2 = 3, /* Second region for unaligned size */ + REGION_STORAGE = 4, /* For mapped internal storage */ + REGION_STORAGE2 = 5, /* Second region for unaligned size */ + REGION_DATA_RAM_TEXT = 6, /* Exempt region of data RAM */ + REGION_CHIP_RESERVED = 7, /* Reserved for use in chip/ */ /* only for chips with MPU supporting 16 regions */ - REGION_UNCACHED_RAM = 8, /* For uncached data RAM */ - REGION_UNCACHED_RAM2 = 9, /* Second region for unaligned size */ - REGION_ROLLBACK = 10, /* For rollback */ + REGION_UNCACHED_RAM = 8, /* For uncached data RAM */ + REGION_UNCACHED_RAM2 = 9, /* Second region for unaligned size */ + REGION_ROLLBACK = 10, /* For rollback */ }; -#define MPU_TYPE REG32(0xe000ed90) -#define MPU_CTRL REG32(0xe000ed94) -#define MPU_NUMBER REG32(0xe000ed98) -#define MPU_BASE REG32(0xe000ed9c) -#define MPU_SIZE REG16(0xe000eda0) -#define MPU_ATTR REG16(0xe000eda2) +#define MPU_TYPE REG32(0xe000ed90) +#define MPU_CTRL REG32(0xe000ed94) +#define MPU_NUMBER REG32(0xe000ed98) +#define MPU_BASE REG32(0xe000ed9c) +#define MPU_SIZE REG16(0xe000eda0) +#define MPU_ATTR REG16(0xe000eda2) /* * See ARM v7-M Architecture Reference Manual * Section B3.5.5 MPU Type Register, MPU_TYPE */ -#define MPU_TYPE_UNIFIED_MASK 0x00FF0001 -#define MPU_TYPE_REG_COUNT(t) (((t) >> 8) & 0xFF) +#define MPU_TYPE_UNIFIED_MASK 0x00FF0001 +#define MPU_TYPE_REG_COUNT(t) (((t) >> 8) & 0xFF) -#define MPU_CTRL_PRIVDEFEN BIT(2) -#define MPU_CTRL_HFNMIENA BIT(1) -#define MPU_CTRL_ENABLE BIT(0) +#define MPU_CTRL_PRIVDEFEN BIT(2) +#define MPU_CTRL_HFNMIENA BIT(1) +#define MPU_CTRL_ENABLE BIT(0) /* * Minimum region size is 32 bytes, 5 bits of address space */ -#define MPU_SIZE_BITS_MIN 5 +#define MPU_SIZE_BITS_MIN 5 /* * XN (execute never) bit. It's bit 12 if accessed by halfword. * 0: XN off * 1: XN on */ -#define MPU_ATTR_XN BIT(12) +#define MPU_ATTR_XN BIT(12) /* AP bit. See table 3-5 of Stellaris LM4F232H5QC datasheet for details */ -#define MPU_ATTR_NO_NO (0 << 8) /* previleged no access, unprev no access */ -#define MPU_ATTR_RW_NO (1 << 8) /* previleged ReadWrite, unprev no access */ -#define MPU_ATTR_RW_RO (2 << 8) /* previleged ReadWrite, unprev Read-only */ -#define MPU_ATTR_RW_RW (3 << 8) /* previleged ReadWrite, unprev ReadWrite */ -#define MPU_ATTR_RO_NO (5 << 8) /* previleged Read-only, unprev no access */ +#define MPU_ATTR_NO_NO (0 << 8) /* previleged no access, unprev no access */ +#define MPU_ATTR_RW_NO (1 << 8) /* previleged ReadWrite, unprev no access */ +#define MPU_ATTR_RW_RO (2 << 8) /* previleged ReadWrite, unprev Read-only */ +#define MPU_ATTR_RW_RW (3 << 8) /* previleged ReadWrite, unprev ReadWrite */ +#define MPU_ATTR_RO_NO (5 << 8) /* previleged Read-only, unprev no access */ /* Suggested value for TEX S/C/B bit. See table 3-6 of Stellaris LM4F232H5QC * datasheet and table 38 of STM32F10xxx Cortex-M3 programming manual. */ #ifndef MPU_ATTR_INTERNAL_SRAM -#define MPU_ATTR_INTERNAL_SRAM 6 /* for Internal SRAM */ +#define MPU_ATTR_INTERNAL_SRAM 6 /* for Internal SRAM */ #endif #ifndef MPU_ATTR_FLASH_MEMORY -#define MPU_ATTR_FLASH_MEMORY 2 /* for flash memory */ +#define MPU_ATTR_FLASH_MEMORY 2 /* for flash memory */ #endif /* Represent RW with at most 2 MPU regions. */ diff --git a/core/cortex-m/include/mpu_private.h b/core/cortex-m/include/mpu_private.h index e6030114c2..fc7617da66 100644 --- a/core/cortex-m/include/mpu_private.h +++ b/core/cortex-m/include/mpu_private.h @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,6 +12,9 @@ #ifndef __CROS_EC_MPU_PRIVATE_H #define __CROS_EC_MPU_PRIVATE_H +#include +#include + int mpu_num_regions(void); bool has_mpu(void); bool mpu_is_unified(void); @@ -21,5 +24,6 @@ int mpu_update_region(uint8_t region, uint32_t addr, uint8_t size_bit, int mpu_config_region(uint8_t region, uint32_t addr, uint32_t size, uint16_t attr, uint8_t enable); struct mpu_rw_regions mpu_get_rw_regions(void); +uint32_t align_down_to_bits(uint32_t addr, uint8_t addr_bits); #endif /* __CROS_EC_MPU_PRIVATE_H */ diff --git a/core/cortex-m/init.S b/core/cortex-m/init.S index bc650c4c64..a947b2e9d1 100644 --- a/core/cortex-m/init.S +++ b/core/cortex-m/init.S @@ -1,4 +1,4 @@ -/* Copyright 2011 The Chromium OS Authors. All rights reserved. +/* Copyright 2011 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -98,6 +98,14 @@ data_loop: isb /* Reset pipeline */ #endif /* CONFIG_DEBUG_DISABLE_WRITE_BUFFER */ +#if !defined(USE_BUILTIN_STDLIB) + /* + * Constructors of global objects. + * https://developer.arm.com/documentation/dui0475/c/the-arm-c-and-c---libraries/c---initialization--construction-and-destruction + */ + bl __libc_init_array +#endif + /* Jump to C code */ bl main @@ -117,19 +125,9 @@ _data_end: _data_lma_start: .long __data_lma_start -/* Mock functions to avoid linker complaints */ -.global __aeabi_unwind_cpp_pr0 -.global __aeabi_unwind_cpp_pr1 -.global __aeabi_unwind_cpp_pr2 -__aeabi_unwind_cpp_pr0: -__aeabi_unwind_cpp_pr1: -__aeabi_unwind_cpp_pr2: - bx lr - /* Reserve space for system stack */ .section .bss.system_stack stack_start: .space CONFIG_STACK_SIZE, 0 stack_end: .global stack_end - diff --git a/core/cortex-m/irq_handler.h b/core/cortex-m/irq_handler.h index ae5d95cd94..b510064652 100644 --- a/core/cortex-m/irq_handler.h +++ b/core/cortex-m/irq_handler.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,9 +9,10 @@ #define __CROS_EC_IRQ_HANDLER_H #ifdef CONFIG_TASK_PROFILING -#define bl_task_start_irq_handler "bl task_start_irq_handler\n" +#define TASK_START_IRQ_HANDLER(excep_return) \ + task_start_irq_handler(excep_return) #else -#define bl_task_start_irq_handler "" +#define TASK_START_IRQ_HANDLER(excep_return) #endif /* Helper macros to build the IRQ handler and priority struct names */ @@ -22,23 +23,19 @@ * ensure it is enabled in the interrupt controller with the right priority. */ #define DECLARE_IRQ(irq, routine, priority) DECLARE_IRQ_(irq, routine, priority) -#define DECLARE_IRQ_(irq, routine, priority) \ - void IRQ_HANDLER(irq)(void) __attribute__((naked)); \ - typedef struct { \ - int fake[irq >= CONFIG_IRQ_COUNT ? -1 : 1]; \ - } irq_num_check_##irq; \ - void __keep routine(void); \ - void IRQ_HANDLER(irq)(void) \ - { \ - asm volatile("mov r0, lr\n" \ - "push {r0, lr}\n" \ - bl_task_start_irq_handler \ - "bl "#routine"\n" \ - "pop {r0, lr}\n" \ - "b task_resched_if_needed\n" \ - ); \ - } \ - const struct irq_priority __keep IRQ_PRIORITY(irq) \ - __attribute__((section(".rodata.irqprio"))) \ - = {irq, priority} -#endif /* __CROS_EC_IRQ_HANDLER_H */ +#define DECLARE_IRQ_(irq, routine, priority) \ + void IRQ_HANDLER(irq)(void); \ + typedef struct { \ + int fake[irq >= CONFIG_IRQ_COUNT ? -1 : 1]; \ + } irq_num_check_##irq; \ + static void __keep routine(void); \ + void IRQ_HANDLER(irq)(void) \ + { \ + void *ret = __builtin_return_address(0); \ + TASK_START_IRQ_HANDLER(ret); \ + routine(); \ + task_resched_if_needed(ret); \ + } \ + const struct irq_priority __keep IRQ_PRIORITY(irq) __attribute__(( \ + weak, section(".rodata.irqprio"))) = { irq, priority } +#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/cortex-m/llsr.c b/core/cortex-m/llsr.c index 0827121e97..933382034b 100644 --- a/core/cortex-m/llsr.c +++ b/core/cortex-m/llsr.c @@ -1,20 +1,21 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Enable the use of right shift for uint64_t. */ -#include -#include #include +#include +#include + union words { uint64_t u64; uint32_t w[2]; }; -uint64_t __attribute__((used)) __aeabi_llsr(uint64_t v, uint32_t shift) +uint64_t __keep __aeabi_llsr(uint64_t v, uint32_t shift) { union words val; union words res; @@ -29,7 +30,7 @@ uint64_t __attribute__((used)) __aeabi_llsr(uint64_t v, uint32_t shift) #ifdef CONFIG_LLSR_TEST -static int command_llsr(int argc, char **argv) +static int command_llsr(int argc, const char **argv) { /* Volatile to prevent compilier optimization from interfering. */ volatile uint64_t start = 0x123456789ABCDEF0ull; @@ -38,13 +39,11 @@ static int command_llsr(int argc, char **argv) const struct { uint32_t shift_by; uint64_t result; - } cases[] = { - {0, start}, - {16, 0x123456789ABCull}, - {32, 0x12345678u}, - {48, 0x1234u}, - {64, 0u} - }; + } cases[] = { { 0, start }, + { 16, 0x123456789ABCull }, + { 32, 0x12345678u }, + { 48, 0x1234u }, + { 64, 0u } }; for (x = 0; x < ARRAY_SIZE(cases); ++x) { if ((start >> cases[x].shift_by) != cases[x].result) { @@ -58,8 +57,7 @@ static int command_llsr(int argc, char **argv) } DECLARE_CONSOLE_COMMAND( - llsrtest, command_llsr, - "", - "Run tests against the LLSR ABI. Prints SUCCESS or FAILURE."); + llsrtest, command_llsr, "", + "Run tests against the LLSR ABI. Prints SUCCESS or FAILURE."); -#endif /* CONFIG_LLSR_TEST */ +#endif /* CONFIG_LLSR_TEST */ diff --git a/core/cortex-m/mpu.c b/core/cortex-m/mpu.c index d1db27d78e..953cbb7393 100644 --- a/core/cortex-m/mpu.c +++ b/core/cortex-m/mpu.c @@ -1,13 +1,14 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* MPU module for Chrome EC */ -#include "mpu.h" +#include "builtin/assert.h" #include "console.h" #include "cpu.h" +#include "mpu.h" #include "registers.h" #include "task.h" #include "util.h" @@ -37,7 +38,6 @@ bool mpu_is_unified(void) return (mpu_get_type() & MPU_TYPE_UNIFIED_MASK) == 0; } - /** * Update a memory region. * @@ -74,7 +74,7 @@ int mpu_update_region(uint8_t region, uint32_t addr, uint8_t size_bit, asm volatile("isb; dsb;"); MPU_NUMBER = region; - MPU_SIZE &= ~1; /* Disable */ + MPU_SIZE &= ~1; /* Disable */ if (enable) { MPU_BASE = addr; /* @@ -85,8 +85,8 @@ int mpu_update_region(uint8_t region, uint32_t addr, uint8_t size_bit, * according to the doc, but they don't ..., do a single 32-bit * one. */ - REG32(&MPU_SIZE) = ((uint32_t)attr << 16) - | (srd << 8) | ((size_bit - 1) << 1) | 1; + REG32(&MPU_SIZE) = ((uint32_t)attr << 16) | (srd << 8) | + ((size_bit - 1) << 1) | 1; } asm volatile("isb; dsb;"); @@ -94,6 +94,88 @@ int mpu_update_region(uint8_t region, uint32_t addr, uint8_t size_bit, return EC_SUCCESS; } +/* + * Align address to a maximum of 31 bits + */ +uint32_t align_down_to_bits(uint32_t addr, uint8_t addr_bits) +{ + if (addr_bits < 32) + return addr & ~((1u << addr_bits) - 1); + else + return addr; +} + +/* + * Greedily configure the largest possible part of the given region from the + * base address. + * + * Returns EC_SUCCESS on success and sets *consumed to the number of bytes + * mapped from the base address. In case of error, the value of *consumed is + * unpredictable. + * + * For instance, if addr is 0x10070000 and size is 0x30000 then memory in the + * range 0x10070000-0x10080000 will be configured and *consumed will be set to + * 0x10000. + */ +static int mpu_config_region_greedy(uint8_t region, uint32_t addr, + uint32_t size, uint16_t attr, + uint8_t enable, uint32_t *consumed) +{ + /* + * Compute candidate alignment to be used for the MPU region. + * + * This is the minimum of the base address and size alignment, since + * regions must be naturally aligned to their size. + */ + uint8_t natural_alignment = MIN(addr == 0 ? 32 : alignment_log2(addr), + alignment_log2(size)); + uint8_t subregion_disable = 0; + + if (natural_alignment >= 5) { + int sr_idx; + uint32_t subregion_base, subregion_size; + /* + * For MPU regions larger than 256 bytes we can use subregions, + * (which are a minimum of 32 bytes in size) making the actual + * MPU region 8x larger. Depending on the address alignment this + * can allow us to cover a larger area (and never a smaller + * one). + */ + natural_alignment += 3; + /* Region size cannot exceed 4GB. */ + if (natural_alignment > 32) + natural_alignment = 32; + + /* + * Generate the subregion mask by walking through each, + * disabling if it is not completely contained in the requested + * range. + */ + subregion_base = align_down_to_bits(addr, natural_alignment); + subregion_size = 1 << (natural_alignment - 3); + *consumed = 0; + for (sr_idx = 0; sr_idx < 8; sr_idx++) { + if (subregion_base < addr || + (subregion_base + subregion_size) > (addr + size)) + /* lsb of subregion mask is lowest address */ + subregion_disable |= 1 << sr_idx; + else + /* not disabled means consumed */ + *consumed += subregion_size; + + subregion_base += subregion_size; + } + } else { + /* Not using subregions; all enabled */ + *consumed = 1 << natural_alignment; + } + + return mpu_update_region(region, + align_down_to_bits(addr, natural_alignment), + natural_alignment, attr, enable, + subregion_disable); +} + /** * Configure a region * @@ -103,76 +185,42 @@ int mpu_update_region(uint8_t region, uint32_t addr, uint8_t size_bit, * attr: Attribute bits. Current value will be overwritten if enable is set. * enable: Enables the region if non zero. Otherwise, disables the region. * - * Returns EC_SUCCESS on success or -EC_ERROR_INVAL if a parameter is invalid. + * Returns EC_SUCCESS on success, -EC_ERROR_OVERFLOW if it is not possible to + * fully configure the given region, or -EC_ERROR_INVAL if a parameter is + * invalid (such as the address or size having unsupported alignment). */ int mpu_config_region(uint8_t region, uint32_t addr, uint32_t size, uint16_t attr, uint8_t enable) { int rv; - int size_bit = 0; - uint8_t blocks, srd1, srd2; + uint32_t consumed; - if (!size) + /* Zero size doesn't require configuration */ + if (size == 0) return EC_SUCCESS; - /* Bit position of first '1' in size */ - size_bit = 31 - __builtin_clz(size); - /* Min. region size is 32 bytes */ - if (size_bit < 5) - return -EC_ERROR_INVAL; - - /* If size is a power of 2 then represent it with a single MPU region */ - if (POWER_OF_TWO(size)) - return mpu_update_region(region, addr, size_bit, attr, enable, - 0); - - /* Sub-regions are not supported for region <= 128 bytes */ - if (size_bit < 7) - return -EC_ERROR_INVAL; - /* Verify we can represent range with <= 2 regions */ - if (size & ~(0x3f << (size_bit - 5))) - return -EC_ERROR_INVAL; - - /* - * Round up size of first region to power of 2. - * Calculate the number of fully occupied blocks (block size = - * region size / 8) in the first region. - */ - blocks = size >> (size_bit - 2); - - /* Represent occupied blocks of two regions with srd mask. */ - srd1 = BIT(blocks) - 1; - srd2 = (1 << ((size >> (size_bit - 5)) & 0x7)) - 1; - - /* - * Second region not supported for DATA_RAM_TEXT, also verify size of - * second region is sufficient to support sub-regions. - */ - if (srd2 && (region == REGION_DATA_RAM_TEXT || size_bit < 10)) - return -EC_ERROR_INVAL; - - /* Write first region. */ - rv = mpu_update_region(region, addr, size_bit + 1, attr, enable, ~srd1); + rv = mpu_config_region_greedy(region, addr, size, attr, enable, + &consumed); if (rv != EC_SUCCESS) return rv; + ASSERT(consumed <= size); + addr += consumed; + size -= consumed; + + /* Regions other than DATA_RAM_TEXT may use two MPU regions */ + if (size > 0 && region != REGION_DATA_RAM_TEXT) { + rv = mpu_config_region_greedy(region + 1, addr, size, attr, + enable, &consumed); + if (rv != EC_SUCCESS) + return rv; + ASSERT(consumed <= size); + addr += consumed; + size -= consumed; + } - /* - * Second protection region (if necessary) begins at the first block - * we marked unoccupied in the first region. - * Size of the second region is the block size of first region. - */ - addr += (1 << (size_bit - 2)) * blocks; - - /* - * Now represent occupied blocks in the second region. It's possible - * that the first region completely represented the occupied area, if - * so then no second protection region is required. - */ - if (srd2) - rv = mpu_update_region(region + 1, addr, size_bit - 2, attr, - enable, ~srd2); - - return rv; + if (size > 0) + return EC_ERROR_OVERFLOW; + return EC_SUCCESS; } /** @@ -186,8 +234,8 @@ int mpu_config_region(uint8_t region, uint32_t addr, uint32_t size, static int mpu_unlock_region(uint8_t region, uint32_t addr, uint32_t size, uint8_t texscb) { - return mpu_config_region(region, addr, size, - MPU_ATTR_RW_RW | texscb, 1); + return mpu_config_region(region, addr, size, MPU_ATTR_RW_RW | texscb, + 1); } void mpu_enable(void) @@ -210,13 +258,9 @@ int mpu_protect_data_ram(void) int ret; /* Prevent code execution from data RAM */ - ret = mpu_config_region(REGION_DATA_RAM, - CONFIG_RAM_BASE, - CONFIG_DATA_RAM_SIZE, - MPU_ATTR_XN | - MPU_ATTR_RW_RW | - MPU_ATTR_INTERNAL_SRAM, - 1); + ret = mpu_config_region( + REGION_DATA_RAM, CONFIG_RAM_BASE, CONFIG_DATA_RAM_SIZE, + MPU_ATTR_XN | MPU_ATTR_RW_RW | MPU_ATTR_INTERNAL_SRAM, 1); if (ret != EC_SUCCESS) return ret; @@ -234,18 +278,16 @@ int mpu_protect_code_ram(void) return mpu_config_region(REGION_STORAGE, CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RO_MEM_OFF, CONFIG_CODE_RAM_SIZE, - MPU_ATTR_RO_NO | MPU_ATTR_INTERNAL_SRAM, - 1); + MPU_ATTR_RO_NO | MPU_ATTR_INTERNAL_SRAM, 1); } #else int mpu_lock_ro_flash(void) { /* Prevent execution from internal mapped RO flash */ - return mpu_config_region(REGION_STORAGE, - CONFIG_MAPPED_STORAGE_BASE + CONFIG_RO_MEM_OFF, - CONFIG_RO_SIZE, - MPU_ATTR_XN | MPU_ATTR_RW_RW | - MPU_ATTR_FLASH_MEMORY, 1); + return mpu_config_region( + REGION_STORAGE, CONFIG_MAPPED_STORAGE_BASE + CONFIG_RO_MEM_OFF, + CONFIG_RO_SIZE, + MPU_ATTR_XN | MPU_ATTR_RW_RW | MPU_ATTR_FLASH_MEMORY, 1); } /* Represent RW with at most 2 MPU regions. */ @@ -261,8 +303,7 @@ struct mpu_rw_regions mpu_get_rw_regions(void) * the region because on the Cortex-M3, Cortex-M4 and Cortex-M7, the * address used for an MPU region must be aligned to the size. */ - aligned_size_bit = - __fls(regions.addr[0] & -regions.addr[0]); + aligned_size_bit = __fls(regions.addr[0] & -regions.addr[0]); regions.size[0] = MIN(BIT(aligned_size_bit), CONFIG_RW_SIZE); regions.addr[1] = regions.addr[0] + regions.size[0]; regions.size[1] = CONFIG_RW_SIZE - regions.size[0]; @@ -349,10 +390,10 @@ int mpu_lock_rollback(int lock) #ifdef CONFIG_CHIP_UNCACHED_REGION /* Store temporarily the regions ranges to use them for the MPU configuration */ -#define REGION(_name, _flag, _start, _size) \ - static const uint32_t CONCAT2(_region_start_, _name) \ +#define REGION(_name, _flag, _start, _size) \ + static const uint32_t CONCAT2(_region_start_, _name) \ __attribute__((unused, section(".unused"))) = _start; \ - static const uint32_t CONCAT2(_region_size_, _name) \ + static const uint32_t CONCAT2(_region_size_, _name) \ __attribute__((unused, section(".unused"))) = _size; #include "memory_regions.inc" #undef REGION @@ -387,7 +428,7 @@ int mpu_pre_init(void) * to the region size. */ rv = mpu_update_region(i, CORTEX_M_SRAM_BASE, MPU_SIZE_BITS_MIN, - 0, 0, 0); + 0, 0, 0); if (rv != EC_SUCCESS) return rv; } diff --git a/core/cortex-m/panic-internal.h b/core/cortex-m/panic-internal.h index 1a58afa8a2..6fa6440006 100644 --- a/core/cortex-m/panic-internal.h +++ b/core/cortex-m/panic-internal.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,4 +8,4 @@ void exception_panic(void) __attribute__((naked)); -#endif /* __CROS_EC_PANIC_INTERNAL_H */ +#endif /* __CROS_EC_PANIC_INTERNAL_H */ diff --git a/core/cortex-m/panic.c b/core/cortex-m/panic.c index 8fabaf4b21..e8d21a6866 100644 --- a/core/cortex-m/panic.c +++ b/core/cortex-m/panic.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,26 +7,28 @@ #include "console.h" #include "cpu.h" #include "host_command.h" -#include "panic.h" #include "panic-internal.h" +#include "panic.h" #include "printf.h" #include "system.h" +#include "system_safe_mode.h" #include "task.h" #include "timer.h" #include "uart.h" #include "util.h" #include "watchdog.h" +#define BASE_EXCEPTION_FRAME_SIZE_BYTES (8 * sizeof(uint32_t)) +#define FPU_EXCEPTION_FRAME_SIZE_BYTES (18 * sizeof(uint32_t)) + /* Whether bus fault is ignored */ static int bus_fault_ignored; - /* Panic data goes at the end of RAM. */ -static struct panic_data * const pdata_ptr = PANIC_DATA_PTR; +static struct panic_data *const pdata_ptr = PANIC_DATA_PTR; /* Preceded by stack, rounded down to nearest 64-bit-aligned boundary */ -static const uint32_t pstack_addr = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE - - sizeof(struct panic_data)) & ~7; +static const uint32_t pstack_addr = ((uint32_t)pdata_ptr) & ~7; /** * Print the name and value of a register @@ -76,9 +78,56 @@ static int32_t is_frame_in_handler_stack(const uint32_t exc_return) return (exc_return & 0xf) == 1 || (exc_return & 0xf) == 9; } +/* + * Returns the size of the exception frame. + * + * See B1.5.7 "Stack alignment on exception entry" of ARM DDI 0403D for details. + * In short, the exception frame size can be either 0x20, 0x24, 0x68, or 0x6c + * depending on FPU context and padding for 8-byte alignment. + */ +static uint32_t get_exception_frame_size(const struct panic_data *pdata) +{ + uint32_t frame_size = 0; + + /* base exception frame */ + frame_size += BASE_EXCEPTION_FRAME_SIZE_BYTES; + + /* CPU uses xPSR[9] to indicate whether it padded the stack for + * alignment or not. + */ + if (pdata->cm.frame[CORTEX_PANIC_FRAME_REGISTER_PSR] & BIT(9)) + frame_size += sizeof(uint32_t); + +#ifdef CONFIG_FPU + /* CPU uses EXC_RETURN[4] to indicate whether it stored extended + * frame for FPU or not. + */ + if (!(pdata->cm.regs[CORTEX_PANIC_REGISTER_LR] & BIT(4))) + frame_size += FPU_EXCEPTION_FRAME_SIZE_BYTES; +#endif + + return frame_size; +} + +/* + * Returns the position of the process stack before the exception frame. + * It computes the size of the exception frame and adds it to psp. + * If the exception happened in the exception context, it returns psp as is. + */ +uint32_t get_panic_stack_pointer(const struct panic_data *pdata) +{ + uint32_t psp = pdata->cm.regs[CORTEX_PANIC_REGISTER_PSP]; + + if (!is_frame_in_handler_stack( + pdata->cm.regs[CORTEX_PANIC_REGISTER_LR])) + psp += get_exception_frame_size(pdata); + + return psp; +} + #ifdef CONFIG_DEBUG_EXCEPTIONS /* Names for each of the bits in the cfs register, starting at bit 0 */ -static const char * const cfsr_name[32] = { +static const char *const cfsr_name[32] = { /* MMFSR */ [0] = "Instruction access violation", [1] = "Data access violation", @@ -102,11 +151,9 @@ static const char * const cfsr_name[32] = { }; /* Names for the first 5 bits in the DFSR */ -static const char * const dfsr_name[] = { - "Halt request", - "Breakpoint", - "Data watchpoint/trace", - "Vector catch", +static const char *const dfsr_name[] = { + "Halt request", "Breakpoint", + "Data watchpoint/trace", "Vector catch", "External debug request", }; @@ -167,50 +214,6 @@ static void show_fault(uint32_t cfsr, uint32_t hfsr, uint32_t dfsr) } } -/* - * Returns the size of the exception frame. - * - * See B1.5.7 "Stack alignment on exception entry" of ARM DDI 0403D for details. - * In short, the exception frame size can be either 0x20, 0x24, 0x68, or 0x6c - * depending on FPU context and padding for 8-byte alignment. - */ -static uint32_t get_exception_frame_size(const struct panic_data *pdata) -{ - uint32_t frame_size = 0; - - /* base exception frame */ - frame_size += 8 * sizeof(uint32_t); - - /* CPU uses xPSR[9] to indicate whether it padded the stack for - * alignment or not. */ - if (pdata->cm.frame[7] & BIT(9)) - frame_size += sizeof(uint32_t); - -#ifdef CONFIG_FPU - /* CPU uses EXC_RETURN[4] to indicate whether it stored extended - * frame for FPU or not. */ - if (!(pdata->cm.regs[11] & BIT(4))) - frame_size += 18 * sizeof(uint32_t); -#endif - - return frame_size; -} - -/* - * Returns the position of the process stack before the exception frame. - * It computes the size of the exception frame and adds it to psp. - * If the exception happened in the exception context, it returns psp as is. - */ -static uint32_t get_process_stack_position(const struct panic_data *pdata) -{ - uint32_t psp = pdata->cm.regs[0]; - - if (!is_frame_in_handler_stack(pdata->cm.regs[11])) - psp += get_exception_frame_size(pdata); - - return psp; -} - /* * Show extra information that might be useful to understand a panic() * @@ -237,7 +240,7 @@ static void panic_show_process_stack(const struct panic_data *pdata) { panic_printf("\n=========== Process Stack Contents ==========="); if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) { - uint32_t psp = get_process_stack_position(pdata); + uint32_t psp = get_panic_stack_pointer(pdata); int i; for (i = 0; i < 16; i++) { if (psp + sizeof(uint32_t) > @@ -261,8 +264,8 @@ void panic_data_print(const struct panic_data *pdata) { const uint32_t *lregs = pdata->cm.regs; const uint32_t *sregs = NULL; - const int32_t in_handler = - is_frame_in_handler_stack(pdata->cm.regs[11]); + const int32_t in_handler = is_frame_in_handler_stack( + pdata->cm.regs[CORTEX_PANIC_REGISTER_LR]); int i; if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) @@ -270,23 +273,36 @@ void panic_data_print(const struct panic_data *pdata) panic_printf("\n=== %s EXCEPTION: %02x ====== xPSR: %08x ===\n", in_handler ? "HANDLER" : "PROCESS", - lregs[1] & 0xff, sregs ? sregs[7] : -1); + lregs[CORTEX_PANIC_REGISTER_IPSR] & 0xff, + sregs ? sregs[CORTEX_PANIC_FRAME_REGISTER_PSR] : -1); for (i = 0; i < 4; i++) print_reg(i, sregs, i); for (i = 4; i < 10; i++) print_reg(i, lregs, i - 1); - print_reg(10, lregs, 9); - print_reg(11, lregs, 10); - print_reg(12, sregs, 4); - print_reg(13, lregs, in_handler ? 2 : 0); - print_reg(14, sregs, 5); - print_reg(15, sregs, 6); + print_reg(10, lregs, CORTEX_PANIC_REGISTER_R10); + print_reg(11, lregs, CORTEX_PANIC_REGISTER_R11); + print_reg(12, sregs, CORTEX_PANIC_FRAME_REGISTER_R12); + print_reg(13, lregs, + in_handler ? CORTEX_PANIC_REGISTER_MSP : + CORTEX_PANIC_REGISTER_PSP); + print_reg(14, sregs, CORTEX_PANIC_FRAME_REGISTER_LR); + print_reg(15, sregs, CORTEX_PANIC_FRAME_REGISTER_PC); #ifdef CONFIG_DEBUG_EXCEPTIONS panic_show_extra(pdata); #endif } +/* This is just a placeholder function for returning from exception. + * It's not expected to actually be executed. + */ +static void exception_return_placeholder(void) +{ + panic_printf("Unexpected return from exception\n"); + panic_reboot(); + __builtin_unreachable(); +} + void __keep report_panic(void) { /* @@ -304,16 +320,29 @@ void __keep report_panic(void) pdata->reserved = 0; /* Choose the right sp (psp or msp) based on EXC_RETURN value */ - sp = is_frame_in_handler_stack(pdata->cm.regs[11]) - ? pdata->cm.regs[2] : pdata->cm.regs[0]; + sp = is_frame_in_handler_stack( + pdata->cm.regs[CORTEX_PANIC_REGISTER_LR]) ? + pdata->cm.regs[CORTEX_PANIC_REGISTER_MSP] : + pdata->cm.regs[CORTEX_PANIC_REGISTER_PSP]; /* If stack is valid, copy exception frame to pdata */ - if ((sp & 3) == 0 && - sp >= CONFIG_RAM_BASE && - sp <= CONFIG_RAM_BASE + CONFIG_RAM_SIZE - 8 * sizeof(uint32_t)) { + if ((sp & 3) == 0 && sp >= CONFIG_RAM_BASE && + sp <= CONFIG_RAM_BASE + CONFIG_RAM_SIZE - + BASE_EXCEPTION_FRAME_SIZE_BYTES) { const uint32_t *sregs = (const uint32_t *)sp; int i; - for (i = 0; i < 8; i++) + + /* Skip r0-r3 and r12 registers if necessary */ + for (i = CORTEX_PANIC_FRAME_REGISTER_R0; + i <= CORTEX_PANIC_FRAME_REGISTER_R12; i++) + if (IS_ENABLED(CONFIG_PANIC_STRIP_GPR)) + pdata->cm.frame[i] = 0; + else + pdata->cm.frame[i] = sregs[i]; + + for (i = CORTEX_PANIC_FRAME_REGISTER_LR; + i < NUM_CORTEX_PANIC_FRAME_REGISTERS; i++) pdata->cm.frame[i] = sregs[i]; + pdata->flags |= PANIC_DATA_FLAG_FRAME_VALID; } @@ -336,6 +365,36 @@ void __keep report_panic(void) * exception happened in a handler's context. */ #endif + + /* Make sure that all changes are saved into RAM */ + if (IS_ENABLED(CONFIG_ARMV7M_CACHE)) + cpu_clean_invalidate_dcache(); + + /* Start safe mode if possible */ + if (IS_ENABLED(CONFIG_SYSTEM_SAFE_MODE)) { + /* TODO: check for nested exceptions */ + if (start_system_safe_mode() == EC_SUCCESS) { + pdata->flags |= PANIC_DATA_FLAG_SAFE_MODE_STARTED; + /* If not in an interrupt context (e.g. software_panic), + * the next highest priority task will immediately + * execute when the current task is disabled on the + * following line. + */ + task_disable_task(task_get_current()); + /* Return from exception on process stack. + * We should not actually land in + * exception_return_placeholder function. Instead the + * scheduler should interrupt and schedule + * a different task since the current task has + * been disabled. + */ + cpu_return_from_exception_psp( + exception_return_placeholder); + __builtin_unreachable(); + } + pdata->flags |= PANIC_DATA_FLAG_SAFE_MODE_FAIL_PRECONDITIONS; + } + panic_reboot(); } @@ -348,35 +407,72 @@ void exception_panic(void) { /* Save registers and branch directly to panic handler */ asm volatile( - "mov r0, %[pregs]\n" "mrs r1, psp\n" "mrs r2, ipsr\n" "mov r3, sp\n" - "stmia r0, {r1-r11, lr}\n" +#ifdef CONFIG_PANIC_STRIP_GPR + /* + * Check if we are in exception. This is similar to + * in_interrupt_context(). Exception bits are 9 LSB, so + * we can perform left shift for 23 bits and check if result + * is 0 (lsls instruction is setting appropriate flags). + */ + "lsls r6, r2, #23\n" + /* + * If this is software panic (shift result == 0) then register + * r4 and r5 contain additional info about panic. + * Clear r6-r11 always and r4, r5 only if this is exception + * panic. To clear r4 and r5, 'movne' conditional instruction + * is used. It works only when flags contain information that + * result was != 0. Itt is pseudo instruction which is used + * to make sure we are using correct conditional instructions. + */ + "itt ne\n" + "movne r4, #0\n" + "movne r5, #0\n" + "mov r6, #0\n" + "mov r7, #0\n" + "mov r8, #0\n" + "mov r9, #0\n" + "mov r10, #0\n" + "mov r11, #0\n" +#endif + "stmia %[pregs], {r1-r11, lr}\n" "mov sp, %[pstack]\n" - "bl report_panic\n" : : - [pregs] "r" (pdata_ptr->cm.regs), - [pstack] "r" (pstack_addr) : - /* Constraints protecting these from being clobbered. - * Gcc should be using r0 & r12 for pregs and pstack. */ - "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", - "r10", "r11", "cc", "memory" - ); + "bl report_panic\n" + : + : [pregs] "r"(pdata_ptr->cm.regs), [pstack] "r"(pstack_addr) + : + /* Constraints protecting these from being clobbered. + * Gcc should be using r0 & r12 for pregs and pstack. */ + "r1", "r2", "r3", "r4", "r5", "r6", + /* clang warns that we're clobbering a reserved register: + * inline asm clobber list contains reserved registers: R7 + * [-Werror,-Winline-asm]. The intent of the clobber list is + * to force pregs and pstack to be in R0 and R12, which + * still holds. + */ +#ifndef __clang__ + "r7", +#endif + "r8", "r9", "r10", "r11", "cc", "memory"); } -#ifdef CONFIG_SOFTWARE_PANIC void software_panic(uint32_t reason, uint32_t info) { - __asm__("mov " STRINGIFY(SOFTWARE_PANIC_INFO_REG) ", %0\n" - "mov " STRINGIFY(SOFTWARE_PANIC_REASON_REG) ", %1\n" - "bl exception_panic\n" - : : "r"(info), "r"(reason)); + __asm__("mov " STRINGIFY( + SOFTWARE_PANIC_INFO_REG) ", %0\n" + "mov " STRINGIFY( + SOFTWARE_PANIC_REASON_REG) ", %1\n" + "bl exception_panic\n" + : + : "r"(info), "r"(reason)); __builtin_unreachable(); } void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) { - struct panic_data * const pdata = get_panic_data_write(); + struct panic_data *const pdata = get_panic_data_write(); uint32_t *lregs; lregs = pdata->cm.regs; @@ -389,26 +485,25 @@ void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) pdata->arch = PANIC_ARCH_CORTEX_M; /* Log panic cause */ - lregs[1] = exception; - lregs[3] = reason; - lregs[4] = info; + lregs[CORTEX_PANIC_REGISTER_IPSR] = exception; + lregs[CORTEX_PANIC_REGISTER_R4] = reason; + lregs[CORTEX_PANIC_REGISTER_R5] = info; } void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) { - struct panic_data * const pdata = panic_get_data(); + struct panic_data *const pdata = panic_get_data(); uint32_t *lregs; if (pdata && pdata->struct_version == 2) { lregs = pdata->cm.regs; - *exception = lregs[1]; - *reason = lregs[3]; - *info = lregs[4]; + *exception = lregs[CORTEX_PANIC_REGISTER_IPSR]; + *reason = lregs[CORTEX_PANIC_REGISTER_R4]; + *info = lregs[CORTEX_PANIC_REGISTER_R5]; } else { *exception = *reason = *info = 0; } } -#endif void bus_fault_handler(void) { @@ -418,6 +513,17 @@ void bus_fault_handler(void) void ignore_bus_fault(int ignored) { + /* + * According to + * https://developer.arm.com/documentation/ddi0403/d/System-Level-Architecture/System-Level-Programmers--Model/Overview-of-system-level-terminology-and-operation/Exceptions?lang=en, + * the Imprecise BusFault is an asynchronous fault in ARMv7-M. + * + * Before re-enabling the bus fault, we use a barrier to make sure that + * the fault has been processed. + */ + if (ignored == 0) + asm volatile("dsb; isb"); + /* * Flash code might call this before cpu_init(), * ensure that the bus faults really go through our handler. diff --git a/core/cortex-m/switch.S b/core/cortex-m/switch.S index f56c5e4c74..512b48036f 100644 --- a/core/cortex-m/switch.S +++ b/core/cortex-m/switch.S @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -98,4 +98,3 @@ __task_start: /* we should never return here */ mov r0, #1 @ set to EC_ERROR_UNKNOWN bx lr - diff --git a/core/cortex-m/task.c b/core/cortex-m/task.c index 510d18fca0..f42b4f9dc0 100644 --- a/core/cortex-m/task.c +++ b/core/cortex-m/task.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,9 +6,11 @@ /* Task scheduling / events module for Chrome EC operating system */ #include "atomic.h" +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "cpu.h" +#include "debug.h" #include "link_defs.h" #include "panic.h" #include "task.h" @@ -21,10 +23,10 @@ typedef union { * Note that sp must be the first element in the task struct * for __switchto() to work. */ - uint32_t sp; /* Saved stack pointer for context switch */ - uint32_t events; /* Bitmaps of received events */ - uint64_t runtime; /* Time spent in task */ - uint32_t *stack; /* Start of stack */ + uint32_t sp; /* Saved stack pointer for context switch */ + atomic_t events; /* Bitmaps of received events */ + uint64_t runtime; /* Time spent in task */ + uint32_t *stack; /* Start of stack */ }; } task_; @@ -40,12 +42,10 @@ CONFIG_CTS_TASK_LIST #undef TASK /* Task names for easier debugging */ -#define TASK(n, r, d, s) #n, -static const char * const task_names[] = { +#define TASK(n, r, d, s) #n, +static const char *const task_names[] = { "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST CONFIG_CTS_TASK_LIST }; #undef TASK @@ -55,12 +55,12 @@ static uint64_t task_start_time; /* Time task scheduling started */ * We only keep 32-bit values for exception start/end time, to avoid * accounting errors when we service interrupt when the timer wraps around. */ -static uint32_t exc_start_time; /* Time of task->exception transition */ -static uint32_t exc_end_time; /* Time of exception->task transition */ -static uint64_t exc_total_time; /* Total time in exceptions */ -static uint32_t svc_calls; /* Number of service calls */ -static uint32_t task_switches; /* Number of times active task changed */ -static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ +static uint32_t exc_start_time; /* Time of task->exception transition */ +static uint32_t exc_end_time; /* Time of exception->task transition */ +static uint64_t exc_total_time; /* Total time in exceptions */ +static uint32_t svc_calls; /* Number of service calls */ +static uint32_t task_switches; /* Number of times active task changed */ +static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ #endif extern void __switchto(task_ *from, task_ *to); @@ -79,7 +79,7 @@ void __idle(void) * CSAE bit is set. Please notice this symptom only * occurs at npcx5. */ -#if defined(CHIP_FAMILY_NPCX5) && defined(CONFIG_HOSTCMD_ESPI) +#if defined(CHIP_FAMILY_NPCX5) && defined(CONFIG_HOST_INTERFACE_ESPI) /* Enable Host access wakeup */ SET_BIT(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6); #endif @@ -91,21 +91,20 @@ void __idle(void) * shortly therefore, resumes execution on exiting idle mode. * Workaround: Replace the idle function with the followings */ - asm ( - "cpsid i\n" /* Disable interrupt */ - "push {r0-r5}\n" /* Save needed registers */ - "wfi\n" /* Wait for int to enter idle */ - "ldm %0, {r0-r5}\n" /* Add a delay after WFI */ - "pop {r0-r5}\n" /* Restore regs before enabling ints */ - "isb\n" /* Flush the cpu pipeline */ - "cpsie i\n" :: "r" (0x100A8000) /* Enable interrupts */ + asm("cpsid i\n" /* Disable interrupt */ + "push {r0-r5}\n" /* Save needed registers */ + "wfi\n" /* Wait for int to enter idle */ + "ldm %0, {r0-r5}\n" /* Add a delay after WFI */ + "pop {r0-r5}\n" /* Restore regs before enabling ints */ + "isb\n" /* Flush the cpu pipeline */ + "cpsie i\n" ::"r"(0x100A8000) /* Enable interrupts */ ); #else /* * Wait for the next irq event. This stops the CPU clock * (sleep / deep sleep, depending on chip config). */ - asm("wfi"); + cpu_enter_suspend_mode(); #endif } } @@ -121,20 +120,19 @@ static void task_exit_trap(void) } /* Startup parameters for all tasks. */ -#define TASK(n, r, d, s) { \ - .r0 = (uint32_t)d, \ - .pc = (uint32_t)r, \ - .stack_size = s, \ -}, +#define TASK(n, r, d, s) \ + { \ + .r0 = (uint32_t)d, \ + .pc = (uint32_t)r, \ + .stack_size = s, \ + }, static const struct { uint32_t r0; uint32_t pc; uint16_t stack_size; } tasks_init[] = { TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST CONFIG_CTS_TASK_LIST }; #undef TASK @@ -142,17 +140,16 @@ static const struct { static task_ tasks[TASK_ID_COUNT]; /* Reset constants and state for all tasks */ -#define TASK_RESET_SUPPORTED BIT(31) -#define TASK_RESET_LOCK BIT(30) -#define TASK_RESET_STATE_MASK (TASK_RESET_SUPPORTED | TASK_RESET_LOCK) -#define TASK_RESET_WAITERS_MASK ~TASK_RESET_STATE_MASK -#define TASK_RESET_UNSUPPORTED 0 -#define TASK_RESET_STATE_LOCKED (TASK_RESET_SUPPORTED | TASK_RESET_LOCK) -#define TASK_RESET_STATE_UNLOCKED TASK_RESET_SUPPORTED +#define TASK_RESET_SUPPORTED BIT(31) +#define TASK_RESET_LOCK BIT(30) +#define TASK_RESET_STATE_MASK (TASK_RESET_SUPPORTED | TASK_RESET_LOCK) +#define TASK_RESET_WAITERS_MASK ~TASK_RESET_STATE_MASK +#define TASK_RESET_UNSUPPORTED 0 +#define TASK_RESET_STATE_LOCKED (TASK_RESET_SUPPORTED | TASK_RESET_LOCK) +#define TASK_RESET_STATE_UNLOCKED TASK_RESET_SUPPORTED #ifdef CONFIG_TASK_RESET_LIST -#define ENABLE_RESET(n) \ - [TASK_ID_##n] = TASK_RESET_SUPPORTED, +#define ENABLE_RESET(n) [TASK_ID_##n] = TASK_RESET_SUPPORTED, static uint32_t task_reset_state[TASK_ID_COUNT] = { #ifdef CONFIG_TASK_RESET_LIST CONFIG_TASK_RESET_LIST @@ -162,18 +159,15 @@ static uint32_t task_reset_state[TASK_ID_COUNT] = { #endif /* CONFIG_TASK_RESET_LIST */ /* Validity checks about static task invariants */ -BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned) * 8); +BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned int) * 8); BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); BUILD_ASSERT(BIT(TASK_ID_COUNT) < TASK_RESET_LOCK); /* Stacks for all tasks */ -#define TASK(n, r, d, s) + s -uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST -] __aligned(8); +#define TASK(n, r, d, s) +s +uint8_t task_stacks[0 TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST + CONFIG_CTS_TASK_LIST] __aligned(8); #undef TASK @@ -202,15 +196,15 @@ static int need_resched_or_profiling; * can do their init within a task switching context. The hooks task will then * make a call to enable all tasks. */ -static uint32_t tasks_ready = BIT(TASK_ID_HOOKS); +static atomic_t tasks_ready = BIT(TASK_ID_HOOKS); /* * Initially allow only the HOOKS and IDLE task to run, regardless of ready * status, in order for HOOK_INIT to complete before other tasks. * task_enable_all_tasks() will open the flood gates. */ -static uint32_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); +static atomic_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); -static int start_called; /* Has task swapping started */ +static int start_called; /* Has task swapping started */ static inline task_ *__task_id_to_ptr(task_id_t id) { @@ -227,11 +221,22 @@ void interrupt_enable(void) asm("cpsie i"); } -inline int in_interrupt_context(void) +inline bool is_interrupt_enabled(void) +{ + int primask; + + /* Interrupts are enabled when PRIMASK bit is 0 */ + asm("mrs %0, primask" : "=r"(primask)); + + return !(primask & 0x1); +} + +inline bool in_interrupt_context(void) { int ret; - asm("mrs %0, ipsr \n" /* read exception number */ - "lsl %0, #23 \n":"=r"(ret)); /* exception bits are the 9 LSB */ + asm("mrs %0, ipsr \n" /* read exception number */ + "lsl %0, #23 \n" + : "=r"(ret)); /* exception bits are the 9 LSB */ return ret; } @@ -239,8 +244,8 @@ inline int in_interrupt_context(void) static inline int get_interrupt_context(void) { int ret; - asm("mrs %0, ipsr \n":"=r"(ret)); /* read exception number */ - return ret & 0x1ff; /* exception bits are the 9 LSB */ + asm("mrs %0, ipsr \n" : "=r"(ret)); /* read exception number */ + return ret & 0x1ff; /* exception bits are the 9 LSB */ } #endif @@ -253,7 +258,7 @@ task_id_t task_get_current(void) return current_task - tasks; } -uint32_t *task_get_event_bitmap(task_id_t tskid) +atomic_t *task_get_event_bitmap(task_id_t tskid) { task_ *tsk = __task_id_to_ptr(tskid); return &tsk->events; @@ -296,12 +301,11 @@ void svc_handler(int desched, task_id_t resched) current = current_task; #ifdef CONFIG_DEBUG_STACK_OVERFLOW - if (*current->stack != STACK_UNUSED_VALUE) { + if (*current->stack != STACK_UNUSED_VALUE && + task_enabled(current - tasks)) { panic_printf("\n\nStack overflow in %s task!\n", task_names[current - tasks]); -#ifdef CONFIG_SOFTWARE_PANIC software_panic(PANIC_SW_STACK_OVERFLOW, current - tasks); -#endif } #endif @@ -341,7 +345,7 @@ void svc_handler(int desched, task_id_t resched) if (next == current) return; - /* Switch to new task */ + /* Switch to new task */ #ifdef CONFIG_TASK_PROFILING task_switches++; #endif @@ -354,7 +358,7 @@ void __schedule(int desched, int resched) register int p0 asm("r0") = desched; register int p1 asm("r1") = resched; - asm("svc 0"::"r"(p0),"r"(p1)); + asm("svc 0" ::"r"(p0), "r"(p1)); } #ifdef CONFIG_TASK_PROFILING @@ -379,7 +383,9 @@ void __keep task_start_irq_handler(void *excep_return) * and we are not called from another exception (this must match the * logic for when we chain to svc_handler() below). */ - if (!need_resched_or_profiling || (((uint32_t)excep_return & 0xf) == 1)) + if (!need_resched_or_profiling || + (((uint32_t)excep_return & EXC_RETURN_MODE_MASK) == + EXC_RETURN_MODE_HANDLER)) return; exc_start_time = t; @@ -392,7 +398,9 @@ void __keep task_resched_if_needed(void *excep_return) * Continue iff a rescheduling event happened or profiling is active, * and we are not called from another exception. */ - if (!need_resched_or_profiling || (((uint32_t)excep_return & 0xf) == 1)) + if (!need_resched_or_profiling || + (((uint32_t)excep_return & EXC_RETURN_MODE_MASK) == + EXC_RETURN_MODE_HANDLER)) return; svc_handler(0, 0); @@ -405,6 +413,15 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched) uint32_t evt; int ret __attribute__((unused)); + /* + * Scheduling task when interrupts are disabled will result in Forced + * Hard Fault because: + * - Disabling interrupt using 'cpsid i' also disables SVCall handler + * (because it has configurable priority) + * - Escalation to Hard Fault (also known as 'priority escalation') + * occurs when handler for that fault is not enabled + */ + ASSERT(is_interrupt_enabled()); ASSERT(!in_interrupt_context()); if (timeout_us > 0) { @@ -413,7 +430,7 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched) ret = timer_arm(deadline, me); ASSERT(ret == EC_SUCCESS); } - while (!(evt = deprecated_atomic_read_clear(&tsk->events))) { + while (!(evt = atomic_clear(&tsk->events))) { /* Remove ourself and get the next task in the scheduler */ __schedule(1, resched); resched = TASK_ID_IDLE; @@ -421,35 +438,30 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched) if (timeout_us > 0) { timer_cancel(me); /* Ensure timer event is clear, we no longer care about it */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); + atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); } return evt; } -uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait) +void task_set_event(task_id_t tskid, uint32_t event) { task_ *receiver = __task_id_to_ptr(tskid); ASSERT(receiver); /* Set the event bit in the receiver message bitmap */ - deprecated_atomic_or(&receiver->events, event); + atomic_or(&receiver->events, event); /* Re-schedule if priorities have changed */ - if (in_interrupt_context()) { + if (in_interrupt_context() || !is_interrupt_enabled()) { /* The receiver might run again */ - deprecated_atomic_or(&tasks_ready, 1 << tskid); + atomic_or(&tasks_ready, 1 << tskid); #ifndef CONFIG_TASK_PROFILING if (start_called) need_resched_or_profiling = 1; #endif } else { - if (wait) - return __wait_evt(-1, tskid); - else - __schedule(0, tskid); + __schedule(0, tskid); } - - return 0; } uint32_t task_wait_event(int timeout_us) @@ -480,8 +492,7 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) /* Re-post any other events collected */ if (events & ~event_mask) - deprecated_atomic_or(¤t_task->events, - events & ~event_mask); + atomic_or(¤t_task->events, events & ~event_mask); return events & event_mask; } @@ -491,19 +502,26 @@ void task_enable_all_tasks(void) /* Mark all tasks as ready and able to run. */ tasks_ready = tasks_enabled = BIT(TASK_ID_COUNT) - 1; /* Reschedule the highest priority task. */ - __schedule(0, 0); + if (is_interrupt_enabled()) + __schedule(0, 0); } void task_enable_task(task_id_t tskid) { - deprecated_atomic_or(&tasks_enabled, BIT(tskid)); + atomic_or(&tasks_enabled, BIT(tskid)); +} + +bool task_enabled(task_id_t tskid) +{ + return tasks_enabled & BIT(tskid); } void task_disable_task(task_id_t tskid) { - deprecated_atomic_clear_bits(&tasks_enabled, BIT(tskid)); + atomic_clear_bits(&tasks_enabled, BIT(tskid)); - if (!in_interrupt_context() && tskid == task_get_current()) + if (!in_interrupt_context() && is_interrupt_enabled() && + tskid == task_get_current()) __schedule(0, 0); } @@ -522,6 +540,15 @@ void task_clear_pending_irq(int irq) CPU_NVIC_UNPEND(irq / 32) = 1 << (irq % 32); } +/* + * Reading interrupt clear-pending register gives us information if interrupt + * is pending. + */ +bool task_is_irq_pending(int irq) +{ + return CPU_NVIC_UNPEND(irq / 32) & (1 << (irq % 32)); +} + void task_trigger_irq(int irq) { CPU_NVIC_SWTRIG = irq; @@ -542,10 +569,10 @@ static uint32_t init_task_context(task_id_t id) tasks[id].sp = (uint32_t)sp; /* Initial context on stack (see __switchto()) */ - sp[8] = tasks_init[id].r0; /* r0 */ - sp[13] = (uint32_t)task_exit_trap; /* lr */ - sp[14] = tasks_init[id].pc; /* pc */ - sp[15] = 0x01000000; /* psr */ + sp[8] = tasks_init[id].r0; /* r0 */ + sp[13] = (uint32_t)task_exit_trap; /* lr */ + sp[14] = tasks_init[id].pc; /* pc */ + sp[15] = 0x01000000; /* psr */ /* Fill unused stack; also used to detect stack overflow. */ for (sp = tasks[id].stack; sp < (uint32_t *)tasks[id].sp; sp++) @@ -579,8 +606,7 @@ static void deferred_task_reset(void) while (deferred_reset_task_ids) { task_id_t reset_id = __fls(deferred_reset_task_ids); - deprecated_atomic_clear_bits(&deferred_reset_task_ids, - 1 << reset_id); + atomic_clear_bits(&deferred_reset_task_ids, 1 << reset_id); do_task_reset(reset_id); } } @@ -591,8 +617,7 @@ DECLARE_DEFERRED(deferred_task_reset); * and if it matches if_value, updates the state to new_value, and returns * TRUE. */ -static int update_reset_state(uint32_t *state, - uint32_t if_value, +static int update_reset_state(uint32_t *state, uint32_t if_value, uint32_t to_value) { int update; @@ -648,8 +673,7 @@ void task_enable_resets(void) uint32_t *state = &task_reset_state[id]; if (*state == TASK_RESET_UNSUPPORTED) { - cprints(CC_TASK, - "%s called from non-resettable task, id: %d", + cprints(CC_TASK, "%s called from non-resettable task, id: %d", __func__, id); return; } @@ -675,7 +699,7 @@ void task_enable_resets(void) return; /* People are waiting for us to reset; schedule a reset. */ - deprecated_atomic_or(&deferred_reset_task_ids, 1 << id); + atomic_or(&deferred_reset_task_ids, 1 << id); /* * This will always trigger a deferred call after our new ID was * written. If the hook call is currently executing, it will run @@ -692,8 +716,7 @@ void task_disable_resets(void) uint32_t *state = &task_reset_state[id]; if (*state == TASK_RESET_UNSUPPORTED) { - cprints(CC_TASK, - "%s called from non-resettable task, id %d", + cprints(CC_TASK, "%s called from non-resettable task, id %d", __func__, id); return; } @@ -748,8 +771,8 @@ int task_reset_cleanup(void) if (cleanup_req) { while (!try_release_reset_lock(state)) { /* Find the first waiter to notify. */ - task_id_t notify_id = __fls( - *state & TASK_RESET_WAITERS_MASK); + task_id_t notify_id = + __fls(*state & TASK_RESET_WAITERS_MASK); /* * Remove the task from waiters first, so that * when it wakes after being notified, it is in @@ -760,15 +783,14 @@ int task_reset_cleanup(void) * itself back to the list of tasks to notify, * and we will notify it again. */ - deprecated_atomic_clear_bits(state, 1 << notify_id); + atomic_clear_bits(state, 1 << notify_id); /* * Skip any invalid ids set by tasks that * requested a non-blocking reset. */ if (notify_id < TASK_ID_COUNT) task_set_event(notify_id, - TASK_EVENT_RESET_DONE, - 0); + TASK_EVENT_RESET_DONE); } } @@ -878,7 +900,7 @@ void mutex_lock(struct mutex *mtx) id = 1 << task_get_current(); - deprecated_atomic_or(&mtx->waiters, id); + atomic_or(&mtx->waiters, id); do { /* Try to get the lock (set 1 into the lock field) */ @@ -886,8 +908,9 @@ void mutex_lock(struct mutex *mtx) " teq %0, #0\n" " it eq\n" " strexeq %0, %2, [%1]\n" - : "=&r" (value) - : "r" (&mtx->lock), "r" (2) : "cc"); + : "=&r"(value) + : "r"(&mtx->lock), "r"(2) + : "cc"); /* * "value" is equals to 1 if the store conditional failed, * 2 if somebody else owns the mutex, 0 else. @@ -897,7 +920,7 @@ void mutex_lock(struct mutex *mtx) task_wait_event_mask(TASK_EVENT_MUTEX, 0); } while (value); - deprecated_atomic_clear_bits(&mtx->waiters, id); + atomic_clear_bits(&mtx->waiters, id); } void mutex_unlock(struct mutex *mtx) @@ -919,11 +942,11 @@ void mutex_unlock(struct mutex *mtx) waiters &= ~BIT(id); /* Somebody is waiting on the mutex */ - task_set_event(id, TASK_EVENT_MUTEX, 0); + task_set_event(id, TASK_EVENT_MUTEX); } /* Ensure no event is remaining from mutex wake-up */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); + atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); } void task_print_list(void) @@ -933,7 +956,7 @@ void task_print_list(void) ccputs("Task Ready Name Events Time (s) StkUsed\n"); for (i = 0; i < TASK_ID_COUNT; i++) { - char is_ready = (tasks_ready & (1< #endif @@ -20,20 +22,18 @@ typedef void (*func)(void); #if PASS == 1 /* Default exception handler */ void __attribute__((used, naked)) default_handler(void); -void default_handler() +void default_handler(void) { - asm( - ".thumb_func\n" - " b exception_panic" - ); + asm(".thumb_func\n" + " b exception_panic"); } #define table(x) x -#define weak_with_default __attribute__((used,weak,alias("default_handler"))) +#define weak_with_default __attribute__((used, weak, alias("default_handler"))) -#define vec(name) extern void weak_with_default name ## _handler(void); -#define irq(num) vec(irq_ ## num) +#define vec(name) extern void weak_with_default name##_handler(void); +#define irq(num) vec(irq_##num) #define item(name) extern void name(void); #define null @@ -41,13 +41,10 @@ void default_handler() extern void stack_end(void); /* not technically correct, it's just a pointer */ extern void reset(void); -#pragma GCC diagnostic push -#if __GNUC__ >= 8 -#pragma GCC diagnostic ignored "-Wattribute-alias" -#endif +DISABLE_GCC_WARNING("-Wattribute-alias") /* Call default_handler if svc_handler is not found (task.c is not built) */ void weak_with_default svc_handler(int desched, task_id_t resched); -#pragma GCC diagnostic pop +ENABLE_GCC_WARNING("-Wattribute-alias") /* * SVC handler helper @@ -59,21 +56,19 @@ void weak_with_default svc_handler(int desched, task_id_t resched); * This approach differs slightly from the one in the document, * it only loads r0 (desched) and r1 (resched) for svc_handler. */ -void __attribute__((used,naked)) svc_helper_handler(void); -void svc_helper_handler() +void __attribute__((used, naked)) svc_helper_handler(void); +void svc_helper_handler(void) { - asm( - ".thumb_func\n" - " tst lr, #4 /* see if called from supervisor mode */\n" - " mrs r2, msp /* get the correct stack pointer into r2 */\n" - " it ne\n" - " mrsne r2, psp\n" - " ldr r1, [r2, #4] /* get regs from stack frame */\n" - " ldr r0, [r2]\n" - " b %0 /* call svc_handler */\n" - : - : "i"(svc_handler) - ); + asm(".thumb_func\n" + " tst lr, #4 /* see if called from supervisor mode */\n" + " mrs r2, msp /* get the correct stack pointer into r2 */\n" + " it ne\n" + " mrsne r2, psp\n" + " ldr r1, [r2, #4] /* get regs from stack frame */\n" + " ldr r0, [r2]\n" + " b %0 /* call svc_handler */\n" + : + : "i"(svc_handler)); } #endif /* PASS 1 */ @@ -92,292 +87,73 @@ void svc_helper_handler() */ #define IRQ_UNUSED_OFFSET 8 -#define table(x) \ - const func vectors[] __attribute__((section(".text.vecttable"))) = { \ - x \ - [IRQ_UNUSED_OFFSET] = null \ - }; +/* Disable warning that "initializer overrides prior initialization of this + * subobject", since we are explicitly doing this to handle the unused IRQs. + */ +DISABLE_CLANG_WARNING("-Winitializer-overrides") + +#define table(x) \ + const func vectors[] __attribute__((section( \ + ".text.vecttable"))) = { x[IRQ_UNUSED_OFFSET] = null }; -#define vec(name) name ## _handler, -#define irq(num) [num < CONFIG_IRQ_COUNT ? num + IRQ_OFFSET : IRQ_UNUSED_OFFSET] = vec(irq_ ## num) +#define vec(name) name##_handler, +#define irq(num) \ + [num < CONFIG_IRQ_COUNT ? num + IRQ_OFFSET : IRQ_UNUSED_OFFSET] = \ + vec(irq_##num) #define item(name) name, -#define null (void*)0, +#define null (void *)0, #endif /* PASS 2 */ -table( - item(stack_end) - item(reset) - vec(nmi) - vec(hard_fault) - vec(mpu_fault) - vec(bus_fault) - vec(usage_fault) - null - null - null - null - item(svc_helper_handler) - vec(debug) - null - vec(pendsv) - vec(sys_tick) - irq(0) - irq(1) - irq(2) - irq(3) - irq(4) - irq(5) - irq(6) - irq(7) - irq(8) - irq(9) - irq(10) - irq(11) - irq(12) - irq(13) - irq(14) - irq(15) - irq(16) - irq(17) - irq(18) - irq(19) - irq(20) - irq(21) - irq(22) - irq(23) - irq(24) - irq(25) - irq(26) - irq(27) - irq(28) - irq(29) - irq(30) - irq(31) - irq(32) - irq(33) - irq(34) - irq(35) - irq(36) - irq(37) - irq(38) - irq(39) - irq(40) - irq(41) - irq(42) - irq(43) - irq(44) - irq(45) - irq(46) - irq(47) - irq(48) - irq(49) - irq(50) - irq(51) - irq(52) - irq(53) - irq(54) - irq(55) - irq(56) - irq(57) - irq(58) - irq(59) - irq(60) - irq(61) - irq(62) - irq(63) - irq(64) - irq(65) - irq(66) - irq(67) - irq(68) - irq(69) - irq(70) - irq(71) - irq(72) - irq(73) - irq(74) - irq(75) - irq(76) - irq(77) - irq(78) - irq(79) - irq(80) - irq(81) - irq(82) - irq(83) - irq(84) - irq(85) - irq(86) - irq(87) - irq(88) - irq(89) - irq(90) - irq(91) - irq(92) - irq(93) - irq(94) - irq(95) - irq(96) - irq(97) - irq(98) - irq(99) - irq(100) - irq(101) - irq(102) - irq(103) - irq(104) - irq(105) - irq(106) - irq(107) - irq(108) - irq(109) - irq(110) - irq(111) - irq(112) - irq(113) - irq(114) - irq(115) - irq(116) - irq(117) - irq(118) - irq(119) - irq(120) - irq(121) - irq(122) - irq(123) - irq(124) - irq(125) - irq(126) - irq(127) - irq(128) - irq(129) - irq(130) - irq(131) - irq(132) - irq(133) - irq(134) - irq(135) - irq(136) - irq(137) - irq(138) - irq(139) - irq(140) - irq(141) - irq(142) - irq(143) - irq(144) - irq(145) - irq(146) - irq(147) - irq(148) - irq(149) - irq(150) - irq(151) - irq(152) - irq(153) - irq(154) - irq(155) - irq(156) - irq(157) - irq(158) - irq(159) - irq(160) - irq(161) - irq(162) - irq(163) - irq(164) - irq(165) - irq(166) - irq(167) - irq(168) - irq(169) - irq(170) - irq(171) - irq(172) - irq(173) - irq(174) - irq(175) - irq(176) - irq(177) - irq(178) - irq(179) - irq(180) - irq(181) - irq(182) - irq(183) - irq(184) - irq(185) - irq(186) - irq(187) - irq(188) - irq(189) - irq(190) - irq(191) - irq(192) - irq(193) - irq(194) - irq(195) - irq(196) - irq(197) - irq(198) - irq(199) - irq(200) - irq(201) - irq(202) - irq(203) - irq(204) - irq(205) - irq(206) - irq(207) - irq(208) - irq(209) - irq(210) - irq(211) - irq(212) - irq(213) - irq(214) - irq(215) - irq(216) - irq(217) - irq(218) - irq(219) - irq(220) - irq(221) - irq(222) - irq(223) - irq(224) - irq(225) - irq(226) - irq(227) - irq(228) - irq(229) - irq(230) - irq(231) - irq(232) - irq(233) - irq(234) - irq(235) - irq(236) - irq(237) - irq(238) - irq(239) - irq(240) - irq(241) - irq(242) - irq(243) - irq(244) - irq(245) - irq(246) - irq(247) - irq(248) - irq(249) - irq(250) - irq(251) - irq(252) - irq(253) - irq(254) -) +table(item(stack_end) item(reset) vec(nmi) vec(hard_fault) vec(mpu_fault) vec( + bus_fault) vec(usage_fault) null null null null item(svc_helper_handler) vec(debug) + null vec(pendsv) vec(sys_tick) irq(0) irq(1) irq(2) irq(3) irq(4) irq( + 5) irq(6) irq(7) irq(8) irq(9) irq(10) irq(11) irq(12) irq(13) + irq(14) irq(15) irq(16) irq(17) irq(18) irq(19) irq(20) irq( + 21) irq(22) irq(23) irq(24) irq(25) irq(26) irq(27) + irq(28) irq(29) irq(30) irq(31) irq(32) irq(33) irq( + 34) irq(35) irq(36) irq(37) irq(38) irq(39) + irq(40) irq(41) irq(42) irq(43) irq(44) irq( + 45) irq(46) irq(47) irq(48) irq(49) + irq(50) irq(51) irq(52) irq(53) irq( + 54) irq(55) irq(56) irq(57) + irq(58) irq(59) irq(60) irq( + 61) irq(62) irq(63) + irq(64) irq(65) irq( + 66) irq(67) + irq(68) irq( + 69) irq(70) + irq(71) irq(72) irq(73) irq(74) irq(75) irq(76) irq(77) irq(78) irq(79) irq(80) irq(81) irq(82) irq(83) irq(84) irq(85) irq(86) irq(87) irq(88) irq(89) irq(90) irq(91) irq(92) irq(93) irq(94) irq(95) irq(96) irq(97) irq( + 98) irq(99) + irq(100) irq(101) irq(102) irq(103) irq(104) irq(105) irq(106) irq( + 107) irq(108) irq(109) irq(110) irq(111) irq(112) irq(113) irq(114) irq(115) + irq(116) irq(117) irq(118) irq(119) irq(120) irq(121) irq(122) irq( + 123) irq(124) irq(125) irq(126) irq(127) irq(128) irq(129) irq(130) irq(131) + irq(132) irq(133) irq(134) irq(135) irq(136) irq(137) irq(138) irq( + 139) irq(140) irq(141) irq(142) irq(143) irq(144) irq(145) irq(146) irq(147) + irq(148) irq(149) irq(150) irq(151) irq(152) irq(153) irq(154) irq( + 155) irq(156) irq(157) irq(158) irq(159) irq(160) irq(161) irq(162) irq(163) + irq(164) irq(165) irq(166) irq(167) irq(168) irq(169) irq(170) irq( + 171) irq(172) irq(173) irq(174) irq(175) irq(176) irq(177) irq(178) + irq(179) irq(180) irq(181) irq(182) irq(183) irq(184) irq(185) irq( + 186) irq(187) irq(188) irq(189) irq(190) irq(191) irq(192) + irq(193) irq(194) irq(195) irq(196) irq(197) irq(198) irq( + 199) irq(200) irq(201) irq(202) irq(203) irq(204) + irq(205) irq(206) irq(207) irq(208) irq(209) irq( + 210) irq(211) irq(212) irq(213) irq(214) + irq(215) irq(216) irq(217) irq(218) irq( + 219) irq(220) irq(221) irq(222) + irq(223) irq(224) irq(225) irq( + 226) irq(227) irq(228) + irq(229) irq(230) irq(231) irq( + 232) irq(233) irq(234) + irq(235) irq(236) irq( + 237) irq(238) + irq(239)) + +#if PASS == 2 + ENABLE_CLANG_WARNING("-Winitializer-overrides") +#endif #if PASS == 1 #undef PASS diff --git a/core/cortex-m/watchdog.c b/core/cortex-m/watchdog.c index 3e62b5f4c5..a94c6a9c25 100644 --- a/core/cortex-m/watchdog.c +++ b/core/cortex-m/watchdog.c @@ -1,4 +1,4 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. +/* Copyright 2012 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,11 +6,20 @@ /* Watchdog common code */ #include "common.h" +#include "cpu.h" #include "panic.h" #include "task.h" #include "timer.h" #include "watchdog.h" +/* + * As defined by Armv7-M Reference Manual B1.5.6 "Exception Entry Behavior", + * the structure of the saved context on the stack is: + * r0, r1, r2, r3, r12, lr, pc, psr, ... + */ +#define STACK_IDX_REG_LR 5 +#define STACK_IDX_REG_PC 6 + void __keep watchdog_trace(uint32_t excep_lr, uint32_t excep_sp) { uint32_t psp; @@ -25,11 +34,18 @@ void __keep watchdog_trace(uint32_t excep_lr, uint32_t excep_sp) stack = (uint32_t *)psp; } - panic_set_reason(PANIC_SW_WATCHDOG, stack[6], + panic_set_reason(PANIC_SW_WATCHDOG, stack[STACK_IDX_REG_PC], (excep_lr & 0xf) == 1 ? 0xff : task_get_current()); + /* + * This is our last breath, the last opportunity to sort out all + * matters. Flush and invalidate D-cache if cache enabled. + */ + if (IS_ENABLED(CONFIG_ARMV7M_CACHE)) + cpu_clean_invalidate_dcache(); + panic_printf("### WATCHDOG PC=%08x / LR=%08x / pSP=%08x ", - stack[6], stack[5], psp); + stack[STACK_IDX_REG_PC], stack[STACK_IDX_REG_LR], psp); if ((excep_lr & 0xf) == 1) panic_puts("(exc) ###\n"); else diff --git a/core/cortex-m0/__builtin.c b/core/cortex-m0/__builtin.c index 4bf495a011..8e2bf984ff 100644 --- a/core/cortex-m0/__builtin.c +++ b/core/cortex-m0/__builtin.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/core/cortex-m0/asm_offsets.c b/core/cortex-m0/asm_offsets.c new file mode 100644 index 0000000000..8bf44007bc --- /dev/null +++ b/core/cortex-m0/asm_offsets.c @@ -0,0 +1,16 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "asm_define.h" +#include "config.h" +#include "panic.h" + +void unused(void) +{ + ASM_DEFINE_OFFSET("ASM_PANIC_DATA_CM_REGS_OFFSET", struct panic_data, + cm.regs); + ASM_DEFINE("ASM_PANIC_DATA_PTR", PANIC_DATA_PTR); + ASM_DEFINE("ASM_PANIC_STACK_ADDR", ((uint32_t)PANIC_DATA_PTR) & ~7); +} diff --git a/core/cortex-m0/atomic.h b/core/cortex-m0/atomic.h index 78ac91a676..9fd3ab849b 100644 --- a/core/cortex-m0/atomic.h +++ b/core/cortex-m0/atomic.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,7 @@ #ifndef __CROS_EC_ATOMIC_H #define __CROS_EC_ATOMIC_H +#include "atomic_t.h" #include "common.h" /** @@ -15,59 +16,62 @@ * * There is no load/store exclusive on ARMv6-M, just disable interrupts */ -#define ATOMIC_OP(asm_op, a, v) do { \ - uint32_t reg0; \ - \ - __asm__ __volatile__(" cpsid i\n" \ - " ldr %0, [%1]\n" \ - #asm_op" %0, %0, %2\n" \ - " str %0, [%1]\n" \ - " cpsie i\n" \ - : "=&b" (reg0) \ - : "b" (a), "r" (v) : "cc"); \ -} while (0) +#define ATOMIC_OP(asm_op, a, v) \ + ({ \ + uint32_t reg0, reg1; \ + \ + __asm__ __volatile__(".syntax unified\n" \ + " cpsid i\n" \ + " ldr %0, [%2]\n" \ + " mov %1, %0\n" #asm_op \ + " %0, %0, %3\n" \ + " str %0, [%2]\n" \ + " cpsie i\n" \ + : "=&l"(reg0), "=&l"(reg1) \ + : "l"(a), "r"(v) \ + : "cc", "memory"); \ + reg1; \ + }) -/* - * The atomic_* functions are marked as deprecated as a part of the process of - * transaction to Zephyr compatible atomic functions. These prefixes will be - * removed in the following patches. Please see b:169151160 for more details. - */ - -static inline void deprecated_atomic_clear_bits(uint32_t volatile *addr, - uint32_t bits) +static inline atomic_val_t atomic_clear_bits(atomic_t *addr, atomic_val_t bits) { - ATOMIC_OP(bic, addr, bits); + return ATOMIC_OP(bics, addr, bits); } -static inline void deprecated_atomic_or(uint32_t volatile *addr, uint32_t bits) +static inline atomic_val_t atomic_or(atomic_t *addr, atomic_val_t bits) { - ATOMIC_OP(orr, addr, bits); + return ATOMIC_OP(orrs, addr, bits); } -static inline void deprecated_atomic_add(uint32_t volatile *addr, - uint32_t value) +static inline atomic_val_t atomic_add(atomic_t *addr, atomic_val_t value) { - ATOMIC_OP(add, addr, value); + return ATOMIC_OP(add, addr, value); } -static inline void deprecated_atomic_sub(uint32_t volatile *addr, - uint32_t value) +static inline atomic_val_t atomic_sub(atomic_t *addr, atomic_val_t value) { - ATOMIC_OP(sub, addr, value); + return ATOMIC_OP(subs, addr, value); } -static inline uint32_t deprecated_atomic_read_clear(uint32_t volatile *addr) +static inline atomic_val_t atomic_clear(atomic_t *addr) { - uint32_t ret; + atomic_t ret; - __asm__ __volatile__(" mov %2, #0\n" + __asm__ __volatile__(" movs %2, #0\n" " cpsid i\n" " ldr %0, [%1]\n" " str %2, [%1]\n" " cpsie i\n" - : "=&b" (ret) - : "b" (addr), "r" (0) : "cc"); + : "=&l"(ret) + : "l"(addr), "r"(0) + : "cc", "memory"); return ret; } -#endif /* __CROS_EC_ATOMIC_H */ + +static inline atomic_val_t atomic_and(atomic_t *addr, atomic_val_t bits) +{ + return ATOMIC_OP(ands, addr, bits); +} + +#endif /* __CROS_EC_ATOMIC_H */ diff --git a/core/cortex-m0/build.mk b/core/cortex-m0/build.mk index a314976bce..9fef30668d 100644 --- a/core/cortex-m0/build.mk +++ b/core/cortex-m0/build.mk @@ -1,18 +1,31 @@ # -*- makefile -*- -# Copyright 2014 The Chromium OS Authors. All rights reserved. +# Copyright 2014 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Cortex-M0 core OS files build # -# Use coreboot-sdk -$(call set-option,CROSS_COMPILE,\ - $(CROSS_COMPILE_arm),\ - /opt/coreboot-sdk/bin/arm-eabi-) +# When set to 1, exclusively use builtins from compiler-rt. +# When set to 0, use EC's builtins. +USE_LLVM_COMPILER_RT:=0 + +ifeq ($(USE_LLVM_COMPILER_RT),1) +CFLAGS_CPU+=-DUSE_LLVM_COMPILER_RT +endif # CPU specific compilation flags -CFLAGS_CPU+=-mthumb -Os -mno-sched-prolog +CFLAGS_CPU+=-mthumb +ifeq ($(cc-name),clang) +CFLAGS_CPU+=-Oz # Like -Os (and thus -O2), but reduces code size further. +# b/256193799: Reduce inline threshold to decrease code size. +CFLAGS_CPU+=-Wl,-mllvm -Wl,-inline-threshold=-10 +# Link compiler-rt when using clang, so clang finds the builtins it provides. +LDFLAGS_EXTRA+=-lclang_rt.builtins-armv6m +else +CFLAGS_CPU+=-Os +CFLAGS_CPU+=-mno-sched-prolog +endif CFLAGS_CPU+=-mno-unaligned-access ifneq ($(CONFIG_LTO),) @@ -20,8 +33,15 @@ CFLAGS_CPU+=-flto LDFLAGS_EXTRA+=-flto endif -core-y=cpu.o init.o thumb_case.o div.o lmul.o ldivmod.o mula.o uldivmod.o -core-y+=vecttable.o __builtin.o +core-y=cpu.o debug.o init.o thumb_case.o mula.o +ifeq ($(USE_LLVM_COMPILER_RT),0) +core-y+=div.o lmul.o ldivmod.o uldivmod.o +endif + +core-y+=vecttable.o +ifeq ($(USE_LLVM_COMPILER_RT),0) +core-y+=__builtin.o +endif core-$(CONFIG_COMMON_PANIC_OUTPUT)+=panic.o core-$(CONFIG_COMMON_RUNTIME)+=switch.o task.o @@ -34,3 +54,11 @@ core-$(CONFIG_CURVE25519)+=curve25519/scalarmult.o core-$(CONFIG_CURVE25519)+=curve25519/sqr.o core-$(CONFIG_WATCHDOG)+=watchdog.o + +core-$(CONFIG_COMMON_PANIC_OUTPUT)+=exception_panic.o + +$(CORE_RW_OUT)/exception_panic.o: $(CORE_RW_OUT)/asm_offsets.h +$(CORE_RW_OUT)/exception_panic.o: CFLAGS+=-I$(CORE_RW_OUT) + +$(CORE_RO_OUT)/exception_panic.o: $(CORE_RO_OUT)/asm_offsets.h +$(CORE_RO_OUT)/exception_panic.o: CFLAGS+=-I$(CORE_RO_OUT) diff --git a/core/cortex-m0/config_core.h b/core/cortex-m0/config_core.h index c31adc471c..63e6da8972 100644 --- a/core/cortex-m0/config_core.h +++ b/core/cortex-m0/config_core.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,10 +10,13 @@ #define BFD_ARCH arm #define BFD_FORMAT "elf32-littlearm" -/* Emulate the CLZ/CTZ instructions since the CPU core is lacking support */ +/* + * Emulate the CLZ/CTZ instructions since the CPU core is lacking support. + */ +#ifndef USE_LLVM_COMPILER_RT #define CONFIG_SOFTWARE_CLZ #define CONFIG_SOFTWARE_CTZ -#define CONFIG_SOFTWARE_PANIC +#endif /* USE_LLVM_COMPILER_RT */ #define CONFIG_ASSEMBLY_MULA32 diff --git a/core/cortex-m0/cpu.c b/core/cortex-m0/cpu.c index b354cc03e2..e180570863 100644 --- a/core/cortex-m0/cpu.c +++ b/core/cortex-m0/cpu.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/core/cortex-m0/cpu.h b/core/cortex-m0/cpu.h index ac184090f9..bdb7a3c6f5 100644 --- a/core/cortex-m0/cpu.h +++ b/core/cortex-m0/cpu.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,36 +8,46 @@ #ifndef __CROS_EC_CPU_H #define __CROS_EC_CPU_H -#include #include "compile_time_macros.h" +#include "debug.h" + +#include /* Macro to access 32-bit registers */ -#define CPUREG(addr) (*(volatile uint32_t*)(addr)) +#define CPUREG(addr) (*(volatile uint32_t *)(addr)) /* Nested Vectored Interrupt Controller */ -#define CPU_NVIC_EN(x) CPUREG(0xe000e100) -#define CPU_NVIC_DIS(x) CPUREG(0xe000e180) -#define CPU_NVIC_UNPEND(x) CPUREG(0xe000e280) -#define CPU_NVIC_ISPR(x) CPUREG(0xe000e200) -#define CPU_NVIC_PRI(x) CPUREG(0xe000e400 + 4 * (x)) +#define CPU_NVIC_EN(x) CPUREG(0xe000e100) +#define CPU_NVIC_DIS(x) CPUREG(0xe000e180) +#define CPU_NVIC_UNPEND(x) CPUREG(0xe000e280) +#define CPU_NVIC_ISPR(x) CPUREG(0xe000e200) +#define CPU_NVIC_PRI(x) CPUREG(0xe000e400 + 4 * (x)) /* System Control Block */ -#define CPU_SCB_ICSR CPUREG(0xe000ed04) +#define CPU_SCB_ICSR CPUREG(0xe000ed04) /* SCB AIRCR : Application interrupt and reset control register */ -#define CPU_NVIC_APINT CPUREG(0xe000ed0c) -#define CPU_NVIC_APINT_SYSRST BIT(2) /* System reset request */ -#define CPU_NVIC_APINT_ENDIAN BIT(15) /* Endianness */ -#define CPU_NVIC_APINT_KEY_RD (0U) -#define CPU_NVIC_APINT_KEY_WR (0x05FAU << 16) +#define CPU_NVIC_APINT CPUREG(0xe000ed0c) +#define CPU_NVIC_APINT_SYSRST BIT(2) /* System reset request */ +#define CPU_NVIC_APINT_ENDIAN BIT(15) /* Endianness */ +#define CPU_NVIC_APINT_KEY_RD (0U) +#define CPU_NVIC_APINT_KEY_WR (0x05FAU << 16) /* SCB SCR : System Control Register */ -#define CPU_SCB_SYSCTRL CPUREG(0xe000ed10) -#define CPU_NVIC_CCR CPUREG(0xe000ed14) -#define CPU_NVIC_SHCSR2 CPUREG(0xe000ed1c) -#define CPU_NVIC_SHCSR3 CPUREG(0xe000ed20) +#define CPU_SCB_SYSCTRL CPUREG(0xe000ed10) +#define CPU_NVIC_CCR CPUREG(0xe000ed14) +#define CPU_NVIC_SHCSR2 CPUREG(0xe000ed1c) +#define CPU_NVIC_SHCSR3 CPUREG(0xe000ed20) #define CPU_NVIC_CCR_UNALIGN_TRAP BIT(3) +/* Bitfield values for EXC_RETURN. */ +#define EXC_RETURN_SPSEL_MASK BIT(2) +#define EXC_RETURN_SPSEL_MSP 0 +#define EXC_RETURN_SPSEL_PSP BIT(2) +#define EXC_RETURN_MODE_MASK BIT(3) +#define EXC_RETURN_MODE_HANDLER 0 +#define EXC_RETURN_MODE_THREAD BIT(3) + /* Set up the cpu to detect faults */ void cpu_init(void); @@ -49,10 +59,16 @@ static inline void cpu_set_interrupt_priority(uint8_t irq, uint8_t priority) if (priority > 3) priority = 3; - CPU_NVIC_PRI(irq / 4) = - (CPU_NVIC_PRI(irq / 4) & - ~(3 << prio_shift)) | - (priority << prio_shift); + CPU_NVIC_PRI(irq / 4) = (CPU_NVIC_PRI(irq / 4) & ~(3 << prio_shift)) | + (priority << prio_shift); +} + +static inline void cpu_enter_suspend_mode(void) +{ + /* Preserve debug sessions by not suspending when connected */ + if (!debugger_is_connected()) { + asm("wfi"); + } } #endif /* __CROS_EC_CPU_H */ diff --git a/core/cortex-m0/debug.c b/core/cortex-m0/debug.c new file mode 120000 index 0000000000..3cada87897 --- /dev/null +++ b/core/cortex-m0/debug.c @@ -0,0 +1 @@ +../cortex-m/debug.c \ No newline at end of file diff --git a/core/cortex-m0/debug.h b/core/cortex-m0/debug.h new file mode 120000 index 0000000000..d79be16190 --- /dev/null +++ b/core/cortex-m0/debug.h @@ -0,0 +1 @@ +../cortex-m/debug.h \ No newline at end of file diff --git a/core/cortex-m0/ec.lds.S b/core/cortex-m0/ec.lds.S index 6839b37778..6e8206e311 100644 --- a/core/cortex-m0/ec.lds.S +++ b/core/cortex-m0/ec.lds.S @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -135,6 +135,10 @@ SECTIONS KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN_COMPLETE)) __hooks_chipset_shutdown_complete_end = .; + __hooks_chipset_hard_off = .; + KEEP(*(.rodata.HOOK_CHIPSET_HARD_OFF)) + __hooks_chipset_hard_off_end = .; + __hooks_chipset_reset = .; KEEP(*(.rodata.HOOK_CHIPSET_RESET)) __hooks_chipset_reset_end = .; @@ -151,6 +155,12 @@ SECTIONS KEEP(*(.rodata.HOOK_TABLET_MODE_CHANGE)) __hooks_tablet_mode_change_end = .; +#ifdef CONFIG_BODY_DETECTION + __hooks_body_detect_change = .; + KEEP(*(.rodata.HOOK_BODY_DETECT_CHANGE)) + __hooks_body_detect_change_end = .; +#endif + __hooks_base_attached_change = .; KEEP(*(.rodata.HOOK_BASE_ATTACHED_CHANGE)) __hooks_base_attached_change_end = .; @@ -185,6 +195,10 @@ SECTIONS KEEP(*(.rodata.HOOK_USB_PD_CONNECT)) __hooks_usb_pd_connect_end = .; + __hooks_power_supply_change = .; + KEEP(*(.rodata.HOOK_POWER_SUPPLY_CHANGE)) + __hooks_power_supply_change_end = .; + __deferred_funcs = .; KEEP(*(.rodata.deferred)) __deferred_funcs_end = .; @@ -216,7 +230,7 @@ SECTIONS *(.init.rom) __init_rom_end = .; -#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH) +#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS) . = ALIGN(64); KEEP(*(.google)) #endif @@ -259,8 +273,7 @@ SECTIONS . = ALIGN(8); *(.bss.system_stack) /* Rest of .bss takes care of its own alignment */ - *(.bss) - *(.bss.slow) + *(.bss*) /* * Reserve space for deferred function firing times. @@ -281,7 +294,7 @@ SECTIONS . = ALIGN(4); __data_start = .; *(.data.tasks) - *(.data) + *(.data*) . = ALIGN(4); *(.iram.text) . = ALIGN(4); @@ -304,18 +317,40 @@ SECTIONS (__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE); /* - * __flash_used is used in flash free calculations by the makefile. + * Relocations are not supported, so make sure that there is no GOT + * section. See http://issuetracker.google.com/234507656#comment15. + */ + .got (NOLOAD) : + { + KEEP(*(.got*)); + } + ASSERT(SIZEOF(.got) == 0, "GOT section found, but not supported.\ + Make sure that all code is compiled without -fPIC.") + + /* + * __flash_used and __flash_size is used in flash free calculations by + * the makefile. Note the difference between __flash_size and + * __config_flash_size. __flash_size is the flash size for the given + * image (RW, RO, etc.), while __config_flash_size is the *total* + * flash size. * __image_size is stored in the struct image_data header and used - * in hash calcuations. + * in hash calculations. */ __flash_used = LOADADDR(.data) + SIZEOF(.data) - ORIGIN(FLASH); + __flash_size = LENGTH(FLASH); __image_size = __flash_used; -#ifdef CONFIG_FLASH +#if defined(SECTION_IS_RW) && (CONFIG_FLASH_WRITE_SIZE > 0) + /* Alignment is needed by flash_command_write() for RW update. */ + ASSERT(__image_size % CONFIG_FLASH_WRITE_SIZE == 0, + "Error: RW image is not aligned to CONFIG_FLASH_WRITE_SIZE") +#endif + +#ifdef CONFIG_FLASH_CROS /* * These linker labels are just for analysis and not used in the code. */ - __config_flash_size = CONFIG_FLASH_SIZE; + __config_flash_size = CONFIG_FLASH_SIZE_BYTES; __config_ro_size = CONFIG_RO_SIZE; __config_ec_protected_storage_size = CONFIG_EC_PROTECTED_STORAGE_SIZE; __config_rw_size = CONFIG_RW_SIZE; @@ -349,7 +384,7 @@ SECTIONS #undef REGION #endif /* CONFIG_CHIP_MEMORY_REGIONS */ -#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH)) +#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS)) /DISCARD/ : { *(.google) } #endif /DISCARD/ : { *(.ARM.*) } diff --git a/core/cortex-m0/exception_panic.S b/core/cortex-m0/exception_panic.S new file mode 100644 index 0000000000..73585bb6d9 --- /dev/null +++ b/core/cortex-m0/exception_panic.S @@ -0,0 +1,38 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "asm_offsets.h" + +.syntax unified +.text +.thumb +.cpu cortex-m0 + +.global exception_panic +.thumb_func +.align 2 +exception_panic: + ldr r3, pstack + ldr r0, pregs + mov ip, r3 + mrs r1, psp + mrs r2, ipsr + mov r3, sp + stmia r0!, {r1-r7} + mov r1, r8 + mov r2, r9 + mov r3, r10 + mov r4, r11 + mov r5, lr + stmia r0!, {r1-r5} + mov sp, ip + bl report_panic + +pstack: + .word ASM_PANIC_STACK_ADDR + +.equ PREGS, (ASM_PANIC_DATA_CM_REGS_OFFSET + ASM_PANIC_DATA_PTR) +pregs: + .word PREGS diff --git a/core/cortex-m0/include/fpu.h b/core/cortex-m0/include/fpu.h new file mode 100644 index 0000000000..1054f388b0 --- /dev/null +++ b/core/cortex-m0/include/fpu.h @@ -0,0 +1,11 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Math utility functions for ARMv6-M */ + +#ifndef __CROS_EC_FPU_H +#define __CROS_EC_FPU_H + +#endif /* __CROS_EC_FPU_H */ diff --git a/core/cortex-m0/include/math.h b/core/cortex-m0/include/math.h deleted file mode 100644 index 4c8955e74d..0000000000 --- a/core/cortex-m0/include/math.h +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Math utility functions for ARMv6-M */ - -#ifndef __CROS_EC_MATH_H -#define __CROS_EC_MATH_H - -#endif /* __CROS_EC_MATH_H */ diff --git a/core/cortex-m0/init.S b/core/cortex-m0/init.S index 5047d18380..58316e92d6 100644 --- a/core/cortex-m0/init.S +++ b/core/cortex-m0/init.S @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -111,19 +111,9 @@ _data_end: _data_lma_start: .long __data_lma_start -/* Mock functions to avoid linker complaints */ -.global __aeabi_unwind_cpp_pr0 -.global __aeabi_unwind_cpp_pr1 -.global __aeabi_unwind_cpp_pr2 -__aeabi_unwind_cpp_pr0: -__aeabi_unwind_cpp_pr1: -__aeabi_unwind_cpp_pr2: - bx lr - /* Reserve space for system stack */ .section .bss.system_stack stack_start: .space CONFIG_STACK_SIZE, 0 stack_end: .global stack_end - diff --git a/core/cortex-m0/irq_handler.h b/core/cortex-m0/irq_handler.h index 1ad033ab2d..f2f6a220e4 100644 --- a/core/cortex-m0/irq_handler.h +++ b/core/cortex-m0/irq_handler.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -20,23 +20,26 @@ */ #define DECLARE_IRQ(irq, routine, priority) DECLARE_IRQ_(irq, routine, priority) #ifdef CONFIG_TASK_PROFILING -#define DECLARE_IRQ_(irq, routine, priority) \ - void IRQ_HANDLER(irq)(void) \ - { \ - void *ret = __builtin_return_address(0); \ - task_start_irq_handler(ret); \ - routine(); \ - task_end_irq_handler(ret); \ - } \ - const struct irq_priority __keep IRQ_PRIORITY(irq) \ - __attribute__((section(".rodata.irqprio"))) \ - = {irq, priority} +#define DECLARE_IRQ_(irq, routine, priority) \ + static void routine(void); \ + void IRQ_HANDLER(irq)(void) \ + { \ + void *ret = __builtin_return_address(0); \ + task_start_irq_handler(ret); \ + routine(); \ + task_end_irq_handler(ret); \ + } \ + const struct irq_priority __keep IRQ_PRIORITY(irq) \ + __attribute__((section(".rodata.irqprio"))) = { irq, \ + priority } #else /* CONFIG_TASK_PROFILING */ /* No Profiling : connect directly the IRQ vector */ -#define DECLARE_IRQ_(irq, routine, priority) \ - void IRQ_HANDLER(irq)(void) __attribute__((alias(STRINGIFY(routine))));\ - const struct irq_priority __keep IRQ_PRIORITY(irq) \ - __attribute__((section(".rodata.irqprio"))) \ - = {irq, priority} +#define DECLARE_IRQ_(irq, routine, priority) \ + static void __keep routine(void); \ + void IRQ_HANDLER(irq)(void) \ + __attribute__((alias(STRINGIFY(routine)))); \ + const struct irq_priority __keep IRQ_PRIORITY(irq) \ + __attribute__((section(".rodata.irqprio"))) = { irq, \ + priority } #endif /* CONFIG_TASK_PROFILING */ -#endif /* __CROS_EC_IRQ_HANDLER_H */ +#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/cortex-m0/mula.S b/core/cortex-m0/mula.S index 02e617c328..7bb54263b4 100644 --- a/core/cortex-m0/mula.S +++ b/core/cortex-m0/mula.S @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/core/cortex-m0/panic-internal.h b/core/cortex-m0/panic-internal.h index 51c12f65b2..9f831495ff 100644 --- a/core/cortex-m0/panic-internal.h +++ b/core/cortex-m0/panic-internal.h @@ -1,4 +1,4 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,4 +10,4 @@ noreturn void exception_panic(void) __attribute__((naked)); -#endif /* __CROS_EC_PANIC_INTERNAL_H */ +#endif /* __CROS_EC_PANIC_INTERNAL_H */ diff --git a/core/cortex-m0/panic.c b/core/cortex-m0/panic.c index 4fe69fddb1..533e45713d 100644 --- a/core/cortex-m0/panic.c +++ b/core/cortex-m0/panic.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,8 +7,8 @@ #include "console.h" #include "cpu.h" #include "host_command.h" -#include "panic.h" #include "panic-internal.h" +#include "panic.h" #include "printf.h" #include "system.h" #include "task.h" @@ -19,13 +19,8 @@ /* Whether bus fault is ignored */ static int bus_fault_ignored; - /* Panic data goes at the end of RAM. */ -static struct panic_data * const pdata_ptr = PANIC_DATA_PTR; - -/* Preceded by stack, rounded down to nearest 64-bit-aligned boundary */ -static const uint32_t pstack_addr = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE - - sizeof(struct panic_data)) & ~7; +static struct panic_data *const pdata_ptr = PANIC_DATA_PTR; /** * Print the name and value of a register @@ -82,8 +77,8 @@ void panic_data_print(const struct panic_data *pdata) { const uint32_t *lregs = pdata->cm.regs; const uint32_t *sregs = NULL; - const int32_t in_handler = - is_frame_in_handler_stack(pdata->cm.regs[11]); + const int32_t in_handler = is_frame_in_handler_stack( + pdata->cm.regs[CORTEX_PANIC_REGISTER_LR]); int i; if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) @@ -91,17 +86,20 @@ void panic_data_print(const struct panic_data *pdata) panic_printf("\n=== %s EXCEPTION: %02x ====== xPSR: %08x ===\n", in_handler ? "HANDLER" : "PROCESS", - lregs[1] & 0xff, sregs ? sregs[7] : -1); + lregs[CORTEX_PANIC_REGISTER_IPSR] & 0xff, + sregs ? sregs[CORTEX_PANIC_FRAME_REGISTER_PSR] : -1); for (i = 0; i < 4; i++) print_reg(i, sregs, i); for (i = 4; i < 10; i++) print_reg(i, lregs, i - 1); - print_reg(10, lregs, 9); - print_reg(11, lregs, 10); - print_reg(12, sregs, 4); - print_reg(13, lregs, in_handler ? 2 : 0); - print_reg(14, sregs, 5); - print_reg(15, sregs, 6); + print_reg(10, lregs, CORTEX_PANIC_REGISTER_R10); + print_reg(11, lregs, CORTEX_PANIC_REGISTER_R11); + print_reg(12, sregs, CORTEX_PANIC_FRAME_REGISTER_R12); + print_reg(13, lregs, + in_handler ? CORTEX_PANIC_REGISTER_MSP : + CORTEX_PANIC_REGISTER_PSP); + print_reg(14, sregs, CORTEX_PANIC_FRAME_REGISTER_LR); + print_reg(15, sregs, CORTEX_PANIC_FRAME_REGISTER_PC); } void __keep report_panic(void) @@ -121,11 +119,12 @@ void __keep report_panic(void) pdata->reserved = 0; /* Choose the right sp (psp or msp) based on EXC_RETURN value */ - sp = is_frame_in_handler_stack(pdata->cm.regs[11]) - ? pdata->cm.regs[2] : pdata->cm.regs[0]; + sp = is_frame_in_handler_stack( + pdata->cm.regs[CORTEX_PANIC_REGISTER_LR]) ? + pdata->cm.regs[CORTEX_PANIC_REGISTER_MSP] : + pdata->cm.regs[CORTEX_PANIC_REGISTER_PSP]; /* If stack is valid, copy exception frame to pdata */ - if ((sp & 3) == 0 && - sp >= CONFIG_RAM_BASE && + if ((sp & 3) == 0 && sp >= CONFIG_RAM_BASE && sp <= CONFIG_RAM_BASE + CONFIG_RAM_SIZE - 8 * sizeof(uint32_t)) { const uint32_t *sregs = (const uint32_t *)sp; int i; @@ -138,50 +137,21 @@ void __keep report_panic(void) panic_reboot(); } -/** - * Default exception handler, which reports a panic. - * - * Declare this as a naked call so we can extract raw LR and IPSR values. - */ -void exception_panic(void) -{ - /* Save registers and branch directly to panic handler */ - asm volatile( - "mov r0, %[pregs]\n" - "mrs r1, psp\n" - "mrs r2, ipsr\n" - "mov r3, sp\n" - "stmia r0!, {r1-r7}\n" - "mov r1, r8\n" - "mov r2, r9\n" - "mov r3, r10\n" - "mov r4, r11\n" - "mov r5, lr\n" - "stmia r0!, {r1-r5}\n" - "mov sp, %[pstack]\n" - "bl report_panic\n" : : - [pregs] "r" (pdata_ptr->cm.regs), - [pstack] "r" (pstack_addr) : - /* Constraints protecting these from being clobbered. - * Gcc should be using r0 & r12 for pregs and pstack. */ - "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", - "r10", "r11", "cc", "memory" - ); -} - -#ifdef CONFIG_SOFTWARE_PANIC void software_panic(uint32_t reason, uint32_t info) { - __asm__("mov " STRINGIFY(SOFTWARE_PANIC_INFO_REG) ", %0\n" - "mov " STRINGIFY(SOFTWARE_PANIC_REASON_REG) ", %1\n" - "bl exception_panic\n" - : : "r"(info), "r"(reason)); + __asm__("mov " STRINGIFY( + SOFTWARE_PANIC_INFO_REG) ", %0\n" + "mov " STRINGIFY( + SOFTWARE_PANIC_REASON_REG) ", %1\n" + "bl exception_panic\n" + : + : "r"(info), "r"(reason)); __builtin_unreachable(); } void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) { - struct panic_data * const pdata = get_panic_data_write(); + struct panic_data *const pdata = get_panic_data_write(); uint32_t *lregs; lregs = pdata->cm.regs; @@ -194,26 +164,25 @@ void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) pdata->arch = PANIC_ARCH_CORTEX_M; /* Log panic cause */ - lregs[1] = exception; - lregs[3] = reason; - lregs[4] = info; + lregs[CORTEX_PANIC_REGISTER_IPSR] = exception; + lregs[CORTEX_PANIC_REGISTER_R4] = reason; + lregs[CORTEX_PANIC_REGISTER_R5] = info; } void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) { - struct panic_data * const pdata = panic_get_data(); + struct panic_data *const pdata = panic_get_data(); uint32_t *lregs; if (pdata && pdata->struct_version == 2) { lregs = pdata->cm.regs; - *exception = lregs[1]; - *reason = lregs[3]; - *info = lregs[4]; + *exception = lregs[CORTEX_PANIC_REGISTER_IPSR]; + *reason = lregs[CORTEX_PANIC_REGISTER_R4]; + *info = lregs[CORTEX_PANIC_REGISTER_R5]; } else { *exception = *reason = *info = 0; } } -#endif void bus_fault_handler(void) { diff --git a/core/cortex-m0/switch.S b/core/cortex-m0/switch.S index a27d929816..4914788460 100644 --- a/core/cortex-m0/switch.S +++ b/core/cortex-m0/switch.S @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -104,7 +104,7 @@ svc_handler_return: .thumb_func pendsv_handler: push {r3, lr} @ save link register and keep stack aligned - ldr r0, =#CPU_SCB_ICSR @ load CPU_SCB_ICSR's address + ldr r0, =CPU_SCB_ICSR @ load CPU_SCB_ICSR's address movs r1, #1 @ prepare left shift (1 << 27) lsls r1, #27 @ shift the bit str r1, [r0] @ clear pending flag diff --git a/core/cortex-m0/task.c b/core/cortex-m0/task.c index 3e54630ab2..315b8d6d16 100644 --- a/core/cortex-m0/task.c +++ b/core/cortex-m0/task.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,7 @@ /* Task scheduling / events module for Chrome EC operating system */ #include "atomic.h" +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "cpu.h" @@ -21,10 +22,10 @@ typedef union { * Note that sp must be the first element in the task struct * for __switchto() to work. */ - uint32_t sp; /* Saved stack pointer for context switch */ - uint32_t events; /* Bitmaps of received events */ - uint64_t runtime; /* Time spent in task */ - uint32_t *stack; /* Start of stack */ + uint32_t sp; /* Saved stack pointer for context switch */ + atomic_t events; /* Bitmaps of received events */ + uint64_t runtime; /* Time spent in task */ + uint32_t *stack; /* Start of stack */ }; } task_; @@ -40,12 +41,10 @@ CONFIG_CTS_TASK_LIST #undef TASK /* Task names for easier debugging */ -#define TASK(n, r, d, s) #n, -static const char * const task_names[] = { +#define TASK(n, r, d, s) #n, +static const char *const task_names[] = { "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST CONFIG_CTS_TASK_LIST }; #undef TASK @@ -55,12 +54,12 @@ static uint64_t task_start_time; /* Time task scheduling started */ * We only keep 32-bit values for exception start/end time, to avoid * accounting errors when we service interrupt when the timer wraps around. */ -static uint32_t exc_start_time; /* Time of task->exception transition */ -static uint32_t exc_end_time; /* Time of exception->task transition */ -static uint64_t exc_total_time; /* Total time in exceptions */ -static uint32_t svc_calls; /* Number of service calls */ -static uint32_t task_switches; /* Number of times active task changed */ -static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ +static uint32_t exc_start_time; /* Time of task->exception transition */ +static uint32_t exc_end_time; /* Time of exception->task transition */ +static uint64_t exc_total_time; /* Total time in exceptions */ +static uint32_t svc_calls; /* Number of service calls */ +static uint32_t task_switches; /* Number of times active task changed */ +static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ #endif extern int __task_start(int *task_stack_ready); @@ -74,7 +73,7 @@ void __idle(void) * Wait for the next irq event. This stops the CPU clock * (sleep / deep sleep, depending on chip config). */ - asm("wfi"); + cpu_enter_suspend_mode(); } } #endif /* !CONFIG_LOW_POWER_IDLE */ @@ -89,38 +88,33 @@ static void task_exit_trap(void) } /* Startup parameters for all tasks. */ -#define TASK(n, r, d, s) { \ - .r0 = (uint32_t)d, \ - .pc = (uint32_t)r, \ - .stack_size = s, \ -}, +#define TASK(n, r, d, s) \ + { \ + .r0 = (uint32_t)d, \ + .pc = (uint32_t)r, \ + .stack_size = s, \ + }, static const struct { uint32_t r0; uint32_t pc; uint16_t stack_size; } tasks_init[] = { TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST CONFIG_CTS_TASK_LIST }; #undef TASK /* Contexts for all tasks */ static task_ tasks[TASK_ID_COUNT]; /* Validity checks about static task invariants */ -BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned) * 8); +BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned int) * 8); BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); - /* Stacks for all tasks */ -#define TASK(n, r, d, s) + s -uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST -] __aligned(8); +#define TASK(n, r, d, s) +s +uint8_t task_stacks[0 TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST + CONFIG_CTS_TASK_LIST] __aligned(8); #undef TASK @@ -136,15 +130,15 @@ task_ *current_task = (task_ *)scratchpad; * can do their init within a task switching context. The hooks task will then * make a call to enable all tasks. */ -static uint32_t tasks_ready = BIT(TASK_ID_HOOKS); +static atomic_t tasks_ready = BIT(TASK_ID_HOOKS); /* * Initially allow only the HOOKS and IDLE task to run, regardless of ready * status, in order for HOOK_INIT to complete before other tasks. * task_enable_all_tasks() will open the flood gates. */ -static uint32_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); +static atomic_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); -static int start_called; /* Has task swapping started */ +static int start_called; /* Has task swapping started */ static inline task_ *__task_id_to_ptr(task_id_t id) { @@ -161,20 +155,32 @@ void interrupt_enable(void) asm("cpsie i"); } -inline int in_interrupt_context(void) +inline bool is_interrupt_enabled(void) +{ + int primask; + + /* Interrupts are enabled when PRIMASK bit is 0 */ + asm("mrs %0, primask" : "=r"(primask)); + + return !(primask & 0x1); +} + +inline bool in_interrupt_context(void) { int ret; - asm("mrs %0, ipsr\n" /* read exception number */ - "lsl %0, #23\n" : "=r"(ret)); /* exception bits are the 9 LSB */ - return ret; + asm("mrs %0, ipsr\n" /* read exception number */ + : "=r"(ret)); + return ret & GENMASK(8, 0); /* exception bits are the 9 LSB */ } +#ifdef CONFIG_TASK_PROFILING static inline int get_interrupt_context(void) { int ret; asm("mrs %0, ipsr\n" : "=r"(ret)); /* read exception number */ - return ret & 0x1ff; /* exception bits are the 9 LSB */ + return ret & 0x1ff; /* exception bits are the 9 LSB */ } +#endif task_id_t task_get_current(void) { @@ -185,7 +191,7 @@ task_id_t task_get_current(void) return current_task - tasks; } -uint32_t *task_get_event_bitmap(task_id_t tskid) +atomic_t *task_get_event_bitmap(task_id_t tskid) { task_ *tsk = __task_id_to_ptr(tskid); return &tsk->events; @@ -199,7 +205,7 @@ int task_start_called(void) /** * Scheduling system call */ -task_ __attribute__((noinline)) *__svc_handler(int desched, task_id_t resched) +task_ __attribute__((noinline)) * __svc_handler(int desched, task_id_t resched) { task_ *current, *next; #ifdef CONFIG_TASK_PROFILING @@ -225,12 +231,11 @@ task_ __attribute__((noinline)) *__svc_handler(int desched, task_id_t resched) current = current_task; #ifdef CONFIG_DEBUG_STACK_OVERFLOW - if (*current->stack != STACK_UNUSED_VALUE) { + if (*current->stack != STACK_UNUSED_VALUE && + task_enabled(current - tasks)) { panic_printf("\n\nStack overflow in %s task!\n", task_names[current - tasks]); -#ifdef CONFIG_SOFTWARE_PANIC software_panic(PANIC_SW_STACK_OVERFLOW, current - tasks); -#endif } #endif @@ -292,7 +297,8 @@ void task_start_irq_handler(void *excep_return) * Continue iff the tasks are ready and we are not called from another * exception (as the time accouting is done in the outer irq). */ - if (!start_called || ((uint32_t)excep_return & 0xf) == 1) + if (!start_called || (((uint32_t)excep_return & EXC_RETURN_MODE_MASK) == + EXC_RETURN_MODE_HANDLER)) return; exc_start_time = t; @@ -310,7 +316,8 @@ void task_end_irq_handler(void *excep_return) * Continue iff the tasks are ready and we are not called from another * exception (as the time accouting is done in the outer irq). */ - if (!start_called || ((uint32_t)excep_return & 0xf) == 1) + if (!start_called || (((uint32_t)excep_return & EXC_RETURN_MODE_MASK) == + EXC_RETURN_MODE_HANDLER)) return; /* Track time in interrupts */ @@ -326,6 +333,12 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched) uint32_t evt; int ret __attribute__((unused)); + /* + * Scheduling task when interrupts are disabled will result in Forced + * Hard Fault because disabling interrupt using 'cpsid i' also disables + * SVCall handler (because it has configurable priority) + */ + ASSERT(is_interrupt_enabled()); ASSERT(!in_interrupt_context()); if (timeout_us > 0) { @@ -334,7 +347,7 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched) ret = timer_arm(deadline, me); ASSERT(ret == EC_SUCCESS); } - while (!(evt = deprecated_atomic_read_clear(&tsk->events))) { + while (!(evt = atomic_clear(&tsk->events))) { /* * We need to ensure that the execution priority is actually * decreased after the "cpsie i" in the atomic operation above @@ -349,23 +362,23 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched) if (timeout_us > 0) { timer_cancel(me); /* Ensure timer event is clear, we no longer care about it */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); + atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); } return evt; } -uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait) +void task_set_event(task_id_t tskid, uint32_t event) { task_ *receiver = __task_id_to_ptr(tskid); ASSERT(receiver); /* Set the event bit in the receiver message bitmap */ - deprecated_atomic_or(&receiver->events, event); + atomic_or(&receiver->events, event); /* Re-schedule if priorities have changed */ - if (in_interrupt_context()) { + if (in_interrupt_context() || !is_interrupt_enabled()) { /* The receiver might run again */ - deprecated_atomic_or(&tasks_ready, 1 << tskid); + atomic_or(&tasks_ready, 1 << tskid); if (start_called) { /* * Trigger the scheduler when there's @@ -374,22 +387,16 @@ uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait) CPU_SCB_ICSR = BIT(28); } } else { - if (wait) { - return __wait_evt(-1, tskid); - } else { - /* - * We need to ensure that the execution priority is - * actually decreased after the "cpsie i" in the atomic - * operation above else the "svc" in the __schedule - * call below will trigger a HardFault. - * Use a barrier to force it at that point. - */ - asm volatile("isb"); - __schedule(0, tskid); - } + /* + * We need to ensure that the execution priority is + * actually decreased after the "cpsie i" in the atomic + * operation above else the "svc" in the __schedule + * call below will trigger a HardFault. + * Use a barrier to force it at that point. + */ + asm volatile("isb"); + __schedule(0, tskid); } - - return 0; } uint32_t task_wait_event(int timeout_us) @@ -420,8 +427,7 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) /* Re-post any other events collected */ if (events & ~event_mask) - deprecated_atomic_or(¤t_task->events, - events & ~event_mask); + atomic_or(¤t_task->events, events & ~event_mask); return events & event_mask; } @@ -431,19 +437,26 @@ void task_enable_all_tasks(void) /* Mark all tasks as ready and able to run. */ tasks_ready = tasks_enabled = BIT(TASK_ID_COUNT) - 1; /* Reschedule the highest priority task. */ - __schedule(0, 0); + if (is_interrupt_enabled()) + __schedule(0, 0); } void task_enable_task(task_id_t tskid) { - deprecated_atomic_or(&tasks_enabled, BIT(tskid)); + atomic_or(&tasks_enabled, BIT(tskid)); +} + +bool task_enabled(task_id_t tskid) +{ + return tasks_enabled & BIT(tskid); } void task_disable_task(task_id_t tskid) { - deprecated_atomic_clear_bits(&tasks_enabled, BIT(tskid)); + atomic_clear_bits(&tasks_enabled, BIT(tskid)); - if (!in_interrupt_context() && tskid == task_get_current()) + if (!in_interrupt_context() && is_interrupt_enabled() && + tskid == task_get_current()) __schedule(0, 0); } @@ -500,7 +513,7 @@ void mutex_lock(struct mutex *mtx) uint32_t id = 1 << task_get_current(); ASSERT(id != TASK_ID_INVALID); - deprecated_atomic_or(&mtx->waiters, id); + atomic_or(&mtx->waiters, id); while (1) { /* Try to get the lock (set 2 into the lock field) */ @@ -514,7 +527,7 @@ void mutex_lock(struct mutex *mtx) mtx->lock = 2; __asm__ __volatile__("cpsie i"); - deprecated_atomic_clear_bits(&mtx->waiters, id); + atomic_clear_bits(&mtx->waiters, id); } void mutex_unlock(struct mutex *mtx) @@ -536,11 +549,11 @@ void mutex_unlock(struct mutex *mtx) waiters &= ~BIT(id); /* Somebody is waiting on the mutex */ - task_set_event(id, TASK_EVENT_MUTEX, 0); + task_set_event(id, TASK_EVENT_MUTEX); } /* Ensure no event is remaining from mutex wake-up */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); + atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); } void task_print_list(void) @@ -550,7 +563,7 @@ void task_print_list(void) ccputs("Task Ready Name Events Time (s) StkUsed\n"); for (i = 0; i < TASK_ID_COUNT; i++) { - char is_ready = (tasks_ready & (1< -#include - +#include "compiler.h" #include "config.h" #include "panic-internal.h" #include "task.h" -#endif /* __INIT */ + +#include +#include +#endif /* __INIT */ typedef void (*func)(void); @@ -30,7 +31,7 @@ void __attribute__((naked)) default_handler(void) * restricting the relative placement of default_handler and * exception_panic. */ - asm volatile("bx %0\n" : : "r" (exception_panic)); + asm volatile("bx %0\n" : : "r"(exception_panic)); } #define table(x) x @@ -38,8 +39,8 @@ void __attribute__((naked)) default_handler(void) /* Note: the alias target must be defined in this translation unit */ #define weak_with_default __attribute__((used, weak, alias("default_handler"))) -#define vec(name) extern void weak_with_default name ## _handler(void); -#define irq(num) vec(irq_ ## num) +#define vec(name) extern void weak_with_default name##_handler(void); +#define irq(num) vec(irq_##num) #define item(name) extern void name(void); #define null @@ -47,12 +48,6 @@ void __attribute__((naked)) default_handler(void) extern void stack_end(void); /* not technically correct, it's just a pointer */ extern void reset(void); -#pragma GCC diagnostic push -#if __GNUC__ >= 8 -#pragma GCC diagnostic ignored "-Wattribute-alias" -#endif -#pragma GCC diagnostic pop - #endif /* PASS 1 */ #if PASS == 2 @@ -69,65 +64,37 @@ extern void reset(void); */ #define IRQ_UNUSED_OFFSET 8 -#define table(x) func vectors[] __attribute__((section(".text.vecttable,\"a\" @"))) = { x[IRQ_UNUSED_OFFSET] = null }; +/* Disable warning that "initializer overrides prior initialization of this + * subobject", since we are explicitly doing this to handle the unused IRQs. + */ +DISABLE_CLANG_WARNING("-Winitializer-overrides") + +#define table(x) \ + const func vectors[] __attribute__(( \ + section(".text.vecttable"))) = { x[IRQ_UNUSED_OFFSET] = null } -#define vec(name) name ## _handler, -#define irq(num) [num < CONFIG_IRQ_COUNT ? num + IRQ_OFFSET : IRQ_UNUSED_OFFSET] = vec(irq_ ## num) +#define vec(name) name##_handler, +#define irq(num) \ + [num < CONFIG_IRQ_COUNT ? num + IRQ_OFFSET : IRQ_UNUSED_OFFSET] = \ + vec(irq_##num) #define item(name) name, #define null (void *)0, #endif /* PASS 2 */ -table( - item(stack_end) - item(reset) - vec(nmi) - vec(hard_fault) - vec(mpu_fault) - vec(bus_fault) - vec(usage_fault) - null - null - null - null - vec(svc) - vec(debug) - null - vec(pendsv) - vec(sys_tick) - irq(0) - irq(1) - irq(2) - irq(3) - irq(4) - irq(5) - irq(6) - irq(7) - irq(8) - irq(9) - irq(10) - irq(11) - irq(12) - irq(13) - irq(14) - irq(15) - irq(16) - irq(17) - irq(18) - irq(19) - irq(20) - irq(21) - irq(22) - irq(23) - irq(24) - irq(25) - irq(26) - irq(27) - irq(28) - irq(29) - irq(30) - irq(31) -) +table(item(stack_end) item(reset) vec(nmi) vec(hard_fault) vec(mpu_fault) vec( + bus_fault) vec(usage_fault) null null null null vec(svc) vec(debug) + null vec(pendsv) vec(sys_tick) irq(0) irq(1) irq(2) irq(3) irq(4) + irq(5) irq(6) irq(7) irq(8) irq(9) irq(10) irq(11) irq(12) + irq(13) irq(14) irq(15) irq(16) irq(17) irq(18) + irq(19) irq(20) irq(21) irq(22) irq(23) + irq(24) irq(25) irq(26) irq(27) + irq(28) irq(29) irq(30) + irq(31)); + +#if PASS == 2 +ENABLE_CLANG_WARNING("-Winitializer-overrides") +#endif #if PASS == 1 #undef PASS diff --git a/core/cortex-m0/watchdog.c b/core/cortex-m0/watchdog.c index 20fcc2ab35..0b5a038168 100644 --- a/core/cortex-m0/watchdog.c +++ b/core/cortex-m0/watchdog.c @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,6 +11,14 @@ #include "timer.h" #include "watchdog.h" +/* + * As defined by Armv7-M Reference Manual B1.5.6 "Exception Entry Behavior", + * the structure of the saved context on the stack is: + * r0, r1, r2, r3, r12, lr, pc, psr, ... + */ +#define STACK_IDX_REG_LR 5 +#define STACK_IDX_REG_PC 6 + void watchdog_trace(uint32_t excep_lr, uint32_t excep_sp) { uint32_t psp; @@ -26,13 +34,11 @@ void watchdog_trace(uint32_t excep_lr, uint32_t excep_sp) } /* Log PC. If we were in task context, log task id too. */ -#ifdef CONFIG_SOFTWARE_PANIC - panic_set_reason(PANIC_SW_WATCHDOG, stack[6], + panic_set_reason(PANIC_SW_WATCHDOG, stack[STACK_IDX_REG_PC], (excep_lr & 0xf) == 1 ? 0xff : task_get_current()); -#endif panic_printf("### WATCHDOG PC=%08x / LR=%08x / pSP=%08x ", - stack[6], stack[5], psp); + stack[STACK_IDX_REG_PC], stack[STACK_IDX_REG_LR], psp); if ((excep_lr & 0xf) == 1) panic_puts("(exc) ###\n"); else diff --git a/core/host/atomic.h b/core/host/atomic.h index 7f2e0ba16f..0d27e1bc6f 100644 --- a/core/host/atomic.h +++ b/core/host/atomic.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,39 +8,36 @@ #ifndef __CROS_EC_ATOMIC_H #define __CROS_EC_ATOMIC_H +#include "atomic_t.h" #include "common.h" -/* - * The atomic_* functions are marked as deprecated as a part of the process of - * transaction to Zephyr compatible atomic functions. These prefixes will be - * removed in the following patches. Please see b:169151160 for more details. - */ +static inline atomic_val_t atomic_clear_bits(atomic_t *addr, atomic_val_t bits) +{ + return __atomic_fetch_and(addr, ~bits, __ATOMIC_SEQ_CST); +} -static inline void deprecated_atomic_clear_bits(uint32_t volatile *addr, - uint32_t bits) +static inline atomic_val_t atomic_or(atomic_t *addr, atomic_val_t bits) { - __sync_and_and_fetch(addr, ~bits); + return __atomic_fetch_or(addr, bits, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_or(uint32_t volatile *addr, uint32_t bits) +static inline atomic_val_t atomic_add(atomic_t *addr, atomic_val_t value) { - __sync_or_and_fetch(addr, bits); + return __atomic_fetch_add(addr, value, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_add(uint32_t volatile *addr, - uint32_t value) +static inline atomic_val_t atomic_sub(atomic_t *addr, atomic_val_t value) { - __sync_add_and_fetch(addr, value); + return __atomic_fetch_sub(addr, value, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_sub(uint32_t volatile *addr, - uint32_t value) +static inline atomic_val_t atomic_clear(atomic_t *addr) { - __sync_sub_and_fetch(addr, value); + return __atomic_exchange_n(addr, 0, __ATOMIC_SEQ_CST); } -static inline uint32_t deprecated_atomic_read_clear(uint32_t volatile *addr) +static inline atomic_val_t atomic_and(atomic_t *addr, atomic_val_t bits) { - return __sync_fetch_and_and(addr, 0); + return __atomic_fetch_and(addr, bits, __ATOMIC_SEQ_CST); } -#endif /* __CROS_EC_ATOMIC_H */ +#endif /* __CROS_EC_ATOMIC_H */ diff --git a/core/host/build.mk b/core/host/build.mk index 503aa5538a..3995e7e4e4 100644 --- a/core/host/build.mk +++ b/core/host/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. +# Copyright 2013 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/core/host/cpu.h b/core/host/cpu.h index d990e06afa..f63e0b9d23 100644 --- a/core/host/cpu.h +++ b/core/host/cpu.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,6 +8,8 @@ #ifndef __CROS_EC_CPU_H #define __CROS_EC_CPU_H -static inline void cpu_init(void) { } +static inline void cpu_init(void) +{ +} #endif /* __CROS_EC_CPU_H */ diff --git a/core/host/disabled.c b/core/host/disabled.c index 759c215ebd..8f05e5e1d6 100644 --- a/core/host/disabled.c +++ b/core/host/disabled.c @@ -1,10 +1,13 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Disabled functions */ -#define DISABLED(proto) proto { } +#define DISABLED(proto) \ + proto \ + { \ + } DISABLED(void clock_init(void)); diff --git a/core/host/host_exe.lds b/core/host/host_exe.lds index fbf7b56351..05943b408a 100644 --- a/core/host/host_exe.lds +++ b/core/host/host_exe.lds @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -65,6 +65,10 @@ SECTIONS { *(.rodata.HOOK_CHIPSET_SHUTDOWN_COMPLETE) __hooks_chipset_shutdown_complete_end = .; + __hooks_chipset_hard_off = .; + KEEP(*(.rodata.HOOK_CHIPSET_HARD_OFF)) + __hooks_chipset_hard_off_end = .; + __hooks_chipset_reset = .; *(.rodata.HOOK_CHIPSET_RESET) __hooks_chipset_reset_end = .; @@ -81,6 +85,10 @@ SECTIONS { KEEP(*(.rodata.HOOK_TABLET_MODE_CHANGE)) __hooks_tablet_mode_change_end = .; + __hooks_body_detect_change = .; + KEEP(*(.rodata.HOOK_BODY_DETECT_CHANGE)) + __hooks_body_detect_change_end = .; + __hooks_base_attached_change = .; KEEP(*(.rodata.HOOK_BASE_ATTACHED_CHANGE)) __hooks_base_attached_change_end = .; @@ -109,6 +117,10 @@ SECTIONS { KEEP(*(.rodata.HOOK_USB_PD_CONNECT)) __hooks_usb_pd_connect_end = .; + __hooks_power_supply_change = .; + KEEP(*(.rodata.HOOK_POWER_SUPPLY_CHANGE)) + __hooks_power_supply_change_end = .; + __deferred_funcs = .; *(.rodata.deferred) __deferred_funcs_end = .; diff --git a/core/host/host_task.h b/core/host/host_task.h index 30cd2ff594..e79111f6f4 100644 --- a/core/host/host_task.h +++ b/core/host/host_task.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,10 +8,10 @@ #ifndef __CROS_EC_HOST_TASK_H #define __CROS_EC_HOST_TASK_H -#include - #include "task.h" +#include + /** * Returns the thread corresponding to the task. */ @@ -34,4 +34,4 @@ void task_register_interrupt(void); */ pid_t getpid(void); -#endif /* __CROS_EC_HOST_TASK_H */ +#endif /* __CROS_EC_HOST_TASK_H */ diff --git a/core/host/irq_handler.h b/core/host/irq_handler.h index 9ff5d9979c..8bbf596a57 100644 --- a/core/host/irq_handler.h +++ b/core/host/irq_handler.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,15 +15,16 @@ * Macro to connect the interrupt handler "routine" to the irq number "irq" and * ensure it is enabled in the interrupt controller with the right priority. */ -#define DECLARE_IRQ(irq, routine, priority) \ - void IRQ_HANDLER(irq)(void) \ - { \ - void *ret = __builtin_return_address(0); \ - task_start_irq_handler(ret); \ - routine(); \ - task_resched_if_needed(ret); \ - } \ - const struct irq_priority __keep IRQ_PRIORITY(irq) \ - __attribute__((section(".rodata.irqprio"))) \ - = {irq, priority} -#endif /* __CROS_EC_IRQ_HANDLER_H */ +#define DECLARE_IRQ(irq, routine, priority) \ + static void __keep routine(void); \ + void IRQ_HANDLER(irq)(void) \ + { \ + void *ret = __builtin_return_address(0); \ + task_start_irq_handler(ret); \ + routine(); \ + task_resched_if_needed(ret); \ + } \ + const struct irq_priority __keep IRQ_PRIORITY(irq) \ + __attribute__((section(".rodata.irqprio"))) = { irq, \ + priority } +#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/host/main.c b/core/host/main.c index e773713b2a..1af5fa928c 100644 --- a/core/host/main.c +++ b/core/host/main.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -19,7 +19,7 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) const char *__prog_name; @@ -40,7 +40,7 @@ static int test_main(void) register_test_end_hook(); - flash_pre_init(); + crec_flash_pre_init(); system_pre_init(); system_common_pre_init(); @@ -85,7 +85,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) * We lose the program name as LLVM fuzzer takes over main function: * make up one. */ - static const char *name = STRINGIFY(PROJECT)".exe"; + static const char *name = STRINGIFY(PROJECT) ".exe"; if (!initialized) { __prog_name = name; diff --git a/core/host/panic.c b/core/host/panic.c index 7b0829989d..0dd00ac604 100644 --- a/core/host/panic.c +++ b/core/host/panic.c @@ -1,18 +1,23 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "config.h" +#include "panic.h" +#include "stack_trace.h" + +#include +#include #include #include - -#include "stack_trace.h" +#include void panic_assert_fail(const char *msg, const char *func, const char *fname, int linenum) { - fprintf(stderr, "ASSERTION FAIL: %s:%d:%s - %s\n", - fname, linenum, func, msg); + fprintf(stderr, "ASSERTION FAIL: %s:%d:%s - %s\n", fname, linenum, func, + msg); task_dump_trace(); puts("Fail!"); /* Inform test runner */ @@ -20,3 +25,34 @@ void panic_assert_fail(const char *msg, const char *func, const char *fname, exit(1); } + +void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) +{ + struct panic_data *const pdata = panic_get_data(); + + assert(pdata); + memset(pdata, 0, CONFIG_PANIC_DATA_SIZE); + pdata->magic = PANIC_DATA_MAGIC; + pdata->struct_size = CONFIG_PANIC_DATA_SIZE; + pdata->struct_version = 2; + pdata->arch = PANIC_ARCH_X86; + + pdata->x86.vector = reason; + pdata->x86.error_code = info; + pdata->x86.eflags = exception; +} + +void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) +{ + struct panic_data *const pdata = panic_get_data(); + + assert(pdata); + assert(pdata->struct_version == 2); + + if (reason) + *reason = pdata->x86.vector; + if (info) + *info = pdata->x86.error_code; + if (exception) + *exception = pdata->x86.eflags; +} diff --git a/core/host/stack_trace.c b/core/host/stack_trace.c index adef66dd44..4f4ab380d9 100644 --- a/core/host/stack_trace.c +++ b/core/host/stack_trace.c @@ -1,16 +1,17 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include +#include "host_task.h" +#include "host_test.h" +#include "timer.h" + #include #include #include -#include "host_task.h" -#include "host_test.h" -#include "timer.h" +#include #define SIGNAL_TRACE_DUMP SIGTERM #define MAX_TRACE 30 @@ -40,13 +41,17 @@ static void __attribute__((noinline)) _task_dump_trace_impl(int offset) int i, nb; sz = backtrace(trace, MAX_TRACE); + if (sz < offset) { + fprintf(stderr, "Can't print backtrace: %ld < %d\n", sz, + offset); + return; + } messages = backtrace_symbols(trace + offset, sz - offset); for (i = 0; i < sz - offset; ++i) { fprintf(stderr, "#%-2d %s\n", i, messages[i]); - /* %p is correct (as opposed to %pP) since this is the host */ - sprintf(buf, "addr2line %p -e %s", - trace[i + offset], __get_prog_name()); + sprintf(buf, "addr2line %p -e %s", trace[i + offset], + __get_prog_name()); file = popen(buf, "r"); if (file) { nb = fread(buf, 1, sizeof(buf) - 1, file); @@ -77,8 +82,8 @@ static void __attribute__((noinline)) _task_dump_trace_dispatch(int sig) } else if (in_interrupt_context()) { fprintf(stderr, "Stack trace of ISR:\n"); } else { - fprintf(stderr, "Stack trace of task %d (%s):\n", - running, task_get_name(running)); + fprintf(stderr, "Stack trace of task %d (%s):\n", running, + task_get_name(running)); } if (need_dispatch) { diff --git a/core/host/task.c b/core/host/task.c index ae5e525303..36996784af 100644 --- a/core/host/task.c +++ b/core/host/task.c @@ -1,19 +1,10 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Task scheduling / events module for Chrome EC operating system */ -#include -#include -#include -#include -#include -#include -#include -#include - #include "atomic.h" #include "common.h" #include "console.h" @@ -23,12 +14,22 @@ #include "test_util.h" #include "timer.h" +#include +#include +#include +#include +#include + +#include +#include +#include + #define SIGNAL_INTERRUPT SIGUSR1 struct emu_task_t { pthread_t thread; pthread_cond_t resume; - uint32_t event; + atomic_t event; timestamp_t wake_time; uint8_t started; }; @@ -47,7 +48,7 @@ static int task_started; static sem_t interrupt_sem; static pthread_mutex_t interrupt_lock; static pthread_t interrupt_thread; -static int in_interrupt; +static bool in_interrupt; static int interrupt_disabled; static void (*pending_isr)(void); static int generator_sleeping; @@ -66,6 +67,7 @@ CONFIG_CTS_TASK_LIST #undef TASK /* usleep that uses OS functions, instead of emulated timer. */ +/* LCOV_EXCL_START */ void _usleep(int usec) { struct timespec req; @@ -75,6 +77,7 @@ void _usleep(int usec) nanosleep(&req, NULL); } +/* LCOV_EXCL_STOP */ /* msleep that uses OS functions, instead of emulated timer. */ void _msleep(int msec) @@ -94,22 +97,18 @@ void _run_test(void *d) run_test(0, NULL); } -#define TASK(n, r, d, s) {r, d}, +#define TASK(n, r, d, s) { r, d }, const struct task_args task_info[TASK_ID_COUNT] = { - {__idle, NULL}, - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST - {_run_test, NULL}, + { __idle, NULL }, + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST CONFIG_CTS_TASK_LIST{ _run_test, + NULL }, }; #undef TASK #define TASK(n, r, d, s) #n, -static const char * const task_names[] = { +static const char *const task_names[] = { "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST - CONFIG_CTS_TASK_LIST + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST CONFIG_CTS_TASK_LIST "<< test runner >>", }; #undef TASK @@ -119,31 +118,36 @@ void task_pre_init(void) /* Nothing */ } -int in_interrupt_context(void) +bool in_interrupt_context(void) { - return !!in_interrupt; + return in_interrupt; } -void interrupt_disable(void) +test_mockable void interrupt_disable(void) { pthread_mutex_lock(&interrupt_lock); interrupt_disabled = 1; pthread_mutex_unlock(&interrupt_lock); } -void interrupt_enable(void) +test_mockable void interrupt_enable(void) { pthread_mutex_lock(&interrupt_lock); interrupt_disabled = 0; pthread_mutex_unlock(&interrupt_lock); } +inline bool is_interrupt_enabled(void) +{ + return !interrupt_disabled; +} + static void _task_execute_isr(int sig) { - in_interrupt = 1; + in_interrupt = true; pending_isr(); sem_post(&interrupt_sem); - in_interrupt = 0; + in_interrupt = false; } void task_register_interrupt(void) @@ -161,7 +165,7 @@ void task_trigger_test_interrupt(void (*isr)(void)) return; } - /* Suspend current task and excute ISR */ + /* Suspend current task and execute ISR */ pending_isr = isr; if (task_started) { pthread_kill(tasks[running_task_id].thread, SIGNAL_INTERRUPT); @@ -172,14 +176,16 @@ void task_trigger_test_interrupt(void (*isr)(void)) /* Wait for ISR to complete */ sem_wait(&interrupt_sem); + /* LCOV_EXCL_START */ while (in_interrupt) _usleep(10); + /* LCOV_EXCL_STOP */ pending_isr = NULL; pthread_mutex_unlock(&interrupt_lock); } -void interrupt_generator_udelay(unsigned us) +void interrupt_generator_udelay(unsigned int us) { generator_sleep_deadline.val = get_time().val + us; generator_sleeping = 1; @@ -198,15 +204,12 @@ pthread_t task_get_thread(task_id_t tskid) return tasks[tskid].thread; } -uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait) +void task_set_event(task_id_t tskid, uint32_t event) { - deprecated_atomic_or(&tasks[tskid].event, event); - if (wait) - return task_wait_event(-1); - return 0; + atomic_or(&tasks[tskid].event, event); } -uint32_t *task_get_event_bitmap(task_id_t tskid) +atomic_t *task_get_event_bitmap(task_id_t tskid) { return &tasks[tskid].event; } @@ -224,7 +227,7 @@ uint32_t task_wait_event(int timeout_us) pthread_cond_wait(&tasks[tid].resume, &run_lock); /* Resume */ - ret = deprecated_atomic_read_clear(&tasks[tid].event); + ret = atomic_clear(&tasks[tid].event); pthread_mutex_unlock(&interrupt_lock); return ret; } @@ -252,8 +255,8 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) /* Re-post any other events collected */ if (events & ~event_mask) - deprecated_atomic_or(&tasks[task_get_current()].event, - events & ~event_mask); + atomic_or(&tasks[task_get_current()].event, + events & ~event_mask); return events & event_mask; } @@ -286,7 +289,7 @@ void mutex_unlock(struct mutex *mtx) for (v = 31; v >= 0; --v) if ((1ul << v) & mtx->waiters) { mtx->waiters &= ~(1ul << v); - task_set_event(v, TASK_EVENT_MUTEX, 0); + task_set_event(v, TASK_EVENT_MUTEX); break; } } @@ -313,14 +316,13 @@ void task_print_list(void) } } -int command_task_info(int argc, char **argv) +static int command_task_info(int argc, const char **argv) { task_print_list(); return EC_SUCCESS; } -DECLARE_SAFE_CONSOLE_COMMAND(taskinfo, command_task_info, - NULL, +DECLARE_SAFE_CONSOLE_COMMAND(taskinfo, command_task_info, NULL, "Print task info"); static void _wait_for_task_started(int can_sleep) @@ -513,8 +515,8 @@ int task_start(void) */ pthread_mutex_lock(&interrupt_lock); - pthread_create(&interrupt_thread, NULL, - _task_int_generator_start, NULL); + pthread_create(&interrupt_thread, NULL, _task_int_generator_start, + NULL); /* * Tell the hooks task to continue so that it can call back to enable @@ -551,7 +553,6 @@ static void task_enable_all_tasks_callback(void) pthread_mutex_unlock(&interrupt_lock); pthread_cond_wait(&scheduler_cond, &run_lock); } - } void task_enable_all_tasks(void) diff --git a/core/host/timer.c b/core/host/timer.c index c99c002533..03c1f70018 100644 --- a/core/host/timer.c +++ b/core/host/timer.c @@ -1,22 +1,23 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Timer module */ -#include -#include - +#include "builtin/assert.h" #include "task.h" #include "test_util.h" #include "timer.h" #include "util.h" +#include +#include + static timestamp_t boot_time; static int time_set; -void usleep(unsigned us) +void usleep(unsigned int us) { if (!task_start_called() || task_get_current() == TASK_ID_INVALID) { udelay(us); @@ -62,7 +63,7 @@ void force_time(timestamp_t ts) time_set = 1; } -void udelay(unsigned us) +void udelay(unsigned int us) { timestamp_t deadline; @@ -90,6 +91,13 @@ int timestamp_expired(timestamp_t deadline, const timestamp_t *now) void timer_init(void) { - if (!time_set) - boot_time = _get_time(); + if (!time_set) { + /* + * Start the timer just before the 64-bit rollover to try + * and catch 32-bit rollover/truncation bugs. + */ + timestamp_t ts = { .val = 0xFFFFFFF0 }; + + force_time(ts); + } } diff --git a/core/host/toolchain.mk b/core/host/toolchain.mk new file mode 100644 index 0000000000..9575559eb4 --- /dev/null +++ b/core/host/toolchain.mk @@ -0,0 +1,11 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +CROSS_COMPILE_HOST_DEFAULT:=x86_64-pc-linux-gnu- +CMAKE_SYSTEM_PROCESSOR ?= x86_64 +OPENSSL_NO_ASM ?= 0 + +$(call set-option,CROSS_COMPILE,\ + $(CROSS_COMPILE_host),\ + $(CROSS_COMPILE_HOST_DEFAULT)) diff --git a/core/minute-ia/atomic.h b/core/minute-ia/atomic.h index 598fc5b3ed..e722d799c8 100644 --- a/core/minute-ia/atomic.h +++ b/core/minute-ia/atomic.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,87 +8,61 @@ #ifndef __CROS_EC_ATOMIC_H #define __CROS_EC_ATOMIC_H +#include "atomic_t.h" #include "common.h" #include "util.h" -#define ATOMIC_OP(asm_op, a, v) do { \ - __asm__ __volatile__ ( \ - ASM_LOCK_PREFIX #asm_op " %1, %0\n" \ - : "+m" (*a) \ - : "ir" (v) \ - : "memory"); \ -} while (0) - static inline int bool_compare_and_swap_u32(uint32_t *var, uint32_t old_value, - uint32_t new_value) + uint32_t new_value) { uint32_t _old_value = old_value; __asm__ __volatile__(ASM_LOCK_PREFIX "cmpxchgl %2, %1" - : "=a" (old_value), "+m" (*var) - : "r" (new_value), "0" (old_value) + : "=a"(old_value), "+m"(*var) + : "r"(new_value), "0"(old_value) : "memory"); return (_old_value == old_value); } -/* - * The atomic_* functions are marked as deprecated as a part of the process of - * transaction to Zephyr compatible atomic functions. These prefixes will be - * removed in the following patches. Please see b:169151160 for more details. - */ - -static inline void deprecated_atomic_or_u8(uint8_t *addr, uint8_t bits) +static inline atomic_val_t atomic_or_u8(uint8_t *addr, uint8_t bits) { - ATOMIC_OP(or, addr, bits); + return __atomic_fetch_or(addr, bits, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_and_u8(uint8_t *addr, uint8_t bits) +static inline atomic_val_t atomic_and_u8(uint8_t *addr, uint8_t bits) { - ATOMIC_OP(and, addr, bits); + return __atomic_fetch_and(addr, bits, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_clear_bits(uint32_t volatile *addr, - uint32_t bits) +static inline atomic_val_t atomic_clear_bits(atomic_t *addr, atomic_val_t bits) { - ATOMIC_OP(andl, addr, ~bits); + return __atomic_fetch_and(addr, ~bits, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_or(uint32_t volatile *addr, uint32_t bits) +static inline atomic_val_t atomic_or(atomic_t *addr, atomic_val_t bits) { - ATOMIC_OP(orl, addr, bits); + return __atomic_fetch_or(addr, bits, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_add(uint32_t volatile *addr, - uint32_t value) +static inline atomic_val_t atomic_add(atomic_t *addr, atomic_val_t value) { - ATOMIC_OP(addl, addr, value); + return __atomic_fetch_add(addr, value, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_and(uint32_t volatile *addr, - uint32_t value) +static inline atomic_val_t atomic_and(atomic_t *addr, atomic_val_t bits) { - ATOMIC_OP(andl, addr, value); + return __atomic_fetch_and(addr, bits, __ATOMIC_SEQ_CST); } -static inline void deprecated_atomic_sub(uint32_t volatile *addr, - uint32_t value) +static inline atomic_val_t atomic_sub(atomic_t *addr, atomic_val_t value) { - ATOMIC_OP(subl, addr, value); + return __atomic_fetch_sub(addr, value, __ATOMIC_SEQ_CST); } -static inline uint32_t deprecated_atomic_read_clear(uint32_t volatile *addr) +static inline atomic_val_t atomic_clear(atomic_t *addr) { - int ret = 0; - - if (*addr == 0) - return 0; - - asm volatile(ASM_LOCK_PREFIX "xchgl %0, %1\n" - : "+r" (ret), "+m" (*addr) - : : "memory", "cc"); - - return ret; + return __atomic_exchange_n(addr, 0, __ATOMIC_SEQ_CST); } -#endif /* __CROS_EC_ATOMIC_H */ +#endif /* __CROS_EC_ATOMIC_H */ diff --git a/core/minute-ia/build.mk b/core/minute-ia/build.mk index 099b9ea736..cd92c5618f 100644 --- a/core/minute-ia/build.mk +++ b/core/minute-ia/build.mk @@ -1,24 +1,23 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Minute-IA core build # -# Select Minute-IA bare-metal toolchain -$(call set-option,CROSS_COMPILE,$(CROSS_COMPILE_i386),\ - /opt/coreboot-sdk/bin/i386-elf-) - # FPU compilation flags CFLAGS_FPU-$(CONFIG_FPU)= # CPU specific compilation flags -CFLAGS_CPU+=-O2 -fomit-frame-pointer -mno-accumulate-outgoing-args \ +CFLAGS_CPU+=-O2 -fomit-frame-pointer \ -ffunction-sections -fdata-sections \ -fno-builtin-printf -fno-builtin-sprintf \ -fno-stack-protector -gdwarf-2 -fno-common -ffreestanding \ -minline-all-stringops -fno-strict-aliasing +ifneq ($(cc-name),clang) +CFLAGS_CPU+=-mno-accumulate-outgoing-args +endif CFLAGS_CPU+=$(CFLAGS_FPU-y) diff --git a/core/minute-ia/config_core.h b/core/minute-ia/config_core.h index 47121642a4..d8a9b3adb1 100644 --- a/core/minute-ia/config_core.h +++ b/core/minute-ia/config_core.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,8 +10,6 @@ #define BFD_ARCH "i386" #define BFD_FORMAT "elf32-i386" -#define CONFIG_SOFTWARE_PANIC - /* * Since all implementations minute-ia are a single core, we do not need a * "lock;" prefix on any instructions. We use the below define in places where @@ -29,6 +27,6 @@ /* * Flag indicates the task uses FPU H/W */ -#define MIA_TASK_FLAG_USE_FPU 0x00000001 +#define MIA_TASK_FLAG_USE_FPU 0x00000001 #endif /* __CROS_EC_CONFIG_CORE_H */ diff --git a/core/minute-ia/cpu.c b/core/minute-ia/cpu.c index cef39fe1ce..0157fec90b 100644 --- a/core/minute-ia/cpu.c +++ b/core/minute-ia/cpu.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -7,7 +7,6 @@ #include - void cpu_init(void) { /* Nothing to do now */ diff --git a/core/minute-ia/cpu.h b/core/minute-ia/cpu.h index 09eb50e4ca..bf5f3c5bbd 100644 --- a/core/minute-ia/cpu.h +++ b/core/minute-ia/cpu.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,6 +8,5 @@ #ifndef __CROS_EC_CPU_H #define __CROS_EC_CPU_H - void cpu_init(void); -#endif /* __CROS_EC_CPU_H */ +#endif /* __CROS_EC_CPU_H */ diff --git a/core/minute-ia/ec.lds.S b/core/minute-ia/ec.lds.S index 2463c6d397..e396b0e097 100644 --- a/core/minute-ia/ec.lds.S +++ b/core/minute-ia/ec.lds.S @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -102,6 +102,10 @@ SECTIONS KEEP(*(.rodata.HOOK_CHIPSET_SHUTDOWN_COMPLETE)) __hooks_chipset_shutdown_complete_end = .; + __hooks_chipset_hard_off = .; + KEEP(*(.rodata.HOOK_CHIPSET_HARD_OFF)) + __hooks_chipset_hard_off_end = .; + __hooks_chipset_reset = .; KEEP(*(.rodata.HOOK_CHIPSET_RESET)) __hooks_chipset_reset_end = .; @@ -118,6 +122,12 @@ SECTIONS KEEP(*(.rodata.HOOK_TABLET_MODE_CHANGE)) __hooks_tablet_mode_change_end = .; +#ifdef CONFIG_BODY_DETECTION + __hooks_body_detect_change = .; + KEEP(*(.rodata.HOOK_BODY_DETECT_CHANGE)) + __hooks_body_detect_change_end = .; +#endif + __hooks_base_attached_change = .; KEEP(*(.rodata.HOOK_BASE_ATTACHED_CHANGE)) __hooks_base_attached_change_end = .; @@ -152,6 +162,10 @@ SECTIONS KEEP(*(.rodata.HOOK_USB_PD_CONNECT)) __hooks_usb_pd_connect_end = .; + __hooks_power_supply_change = .; + KEEP(*(.rodata.HOOK_POWER_SUPPLY_CHANGE)) + __hooks_power_supply_change_end = .; + __deferred_funcs = .; KEEP(*(.rodata.deferred)) __deferred_funcs_end = .; @@ -231,6 +245,12 @@ SECTIONS /* TODO: Adjust __image_size to proper value for core minute-ia later */ __image_size = . - CONFIG_ISH_BOOT_START; +#if defined(SECTION_IS_RW) && (CONFIG_FLASH_WRITE_SIZE > 0) + /* Alignment is needed by flash_command_write() for RW update. */ + ASSERT(__image_size % CONFIG_FLASH_WRITE_SIZE == 0, + "Error: RW image is not aligned to CONFIG_FLASH_WRITE_SIZE") +#endif + def_irq_low = ABSOLUTE(default_int_handler) & 0xFFFF; def_irq_high = ABSOLUTE(default_int_handler) >> 16; diff --git a/core/minute-ia/ia_structs.h b/core/minute-ia/ia_structs.h index 29bbb6c005..83214e2c1b 100644 --- a/core/minute-ia/ia_structs.h +++ b/core/minute-ia/ia_structs.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,7 +10,6 @@ #include "common.h" - /** * IA32/x86 architecture related data structure definitions. * including: Global Descriptor Table (GDT), Local Descriptor Table (LDT), @@ -24,16 +23,16 @@ struct gdt_entry { union { struct { - uint32_t dword_lo; /* lower dword */ - uint32_t dword_up; /* upper dword */ + uint32_t dword_lo; /* lower dword */ + uint32_t dword_up; /* upper dword */ }; struct { - uint16_t limit_lw; /* limit (0:15) */ - uint16_t base_addr_lw; /* base address (0:15) */ - uint8_t base_addr_mb; /* base address (16:23) */ - uint8_t flags; /* flags */ - uint8_t limit_ub; /* limit (16:19) */ - uint8_t base_addr_ub; /* base address (24:31) */ + uint16_t limit_lw; /* limit (0:15) */ + uint16_t base_addr_lw; /* base address (0:15) */ + uint8_t base_addr_mb; /* base address (16:23) */ + uint8_t flags; /* flags */ + uint8_t limit_ub; /* limit (16:19) */ + uint8_t base_addr_ub; /* base address (24:31) */ }; }; @@ -43,32 +42,32 @@ typedef struct gdt_entry ldt_entry; /* GDT header */ struct gdt_header { - uint16_t limit; /* GDT limit size */ - struct gdt_entry *entries; /* pointer to GDT entries */ + uint16_t limit; /* GDT limit size */ + struct gdt_entry *entries; /* pointer to GDT entries */ } __packed; /* IDT entry descriptor */ struct idt_entry { union { struct { - uint32_t dword_lo; /* lower dword */ - uint32_t dword_up; /* upper dword */ + uint32_t dword_lo; /* lower dword */ + uint32_t dword_up; /* upper dword */ }; struct { - uint16_t offset_lw; /* offset (0:15) */ - uint16_t seg_selector; /* segment selector */ - uint8_t zero; /* must be set to zero */ - uint8_t flags; /* flags */ - uint16_t offset_uw; /* offset (16:31) */ + uint16_t offset_lw; /* offset (0:15) */ + uint16_t seg_selector; /* segment selector */ + uint8_t zero; /* must be set to zero */ + uint8_t flags; /* flags */ + uint16_t offset_uw; /* offset (16:31) */ }; }; } __packed; /* IDT header */ struct idt_header { - uint16_t limit; /* IDT limit size */ - struct idt_entry *entries; /* pointer to IDT entries */ + uint16_t limit; /* IDT limit size */ + struct idt_entry *entries; /* pointer to IDT entries */ } __packed; /* TSS entry descriptor */ @@ -117,22 +116,22 @@ struct tss_entry { #endif /* code segment flag, E/R, Present = 1, DPL = 0, Acesssed = 1 */ -#define GDT_DESC_CODE_FLAGS (0x9B) +#define GDT_DESC_CODE_FLAGS (0x9B) /* data segment flag, R/W, Present = 1, DPL = 0, Acesssed = 1 */ -#define GDT_DESC_DATA_FLAGS (0x93) +#define GDT_DESC_DATA_FLAGS (0x93) /* TSS segment limit size */ -#define GDT_DESC_TSS_LIMIT (0x67) +#define GDT_DESC_TSS_LIMIT (0x67) /* TSS segment flag, Present = 1, DPL = 0, Acesssed = 1 */ -#define GDT_DESC_TSS_FLAGS (0x89) +#define GDT_DESC_TSS_FLAGS (0x89) /* LDT segment flag, Present = 1, DPL = 0 */ -#define GDT_DESC_LDT_FLAGS (0x82) +#define GDT_DESC_LDT_FLAGS (0x82) /* IDT descriptor flag, Present = 1, DPL = 0, 32-bit interrupt gate */ -#define IDT_DESC_FLAGS (0x8E) +#define IDT_DESC_FLAGS (0x8E) /** * macros helper to create a GDT entry descriptor @@ -141,21 +140,20 @@ struct tss_entry { * limit: 32bit limit size of bytes (will covert to unit of 4096-byte pages) * flags: 8bit flags */ -#define GEN_GDT_DESC_LO(base, limit, flags) \ - ((((limit) >> 12) & 0xFFFF) | (((base) & 0xFFFF) << 16)) - -#define GEN_GDT_DESC_UP(base, limit, flags) \ - ((((base) >> 16) & 0xFF) | (((flags) << 8) & 0xFF00) | \ - (((limit) >> 12) & 0xFF0000) | ((base) & 0xFF000000) | 0xc00000) +#define GEN_GDT_DESC_LO(base, limit, flags) \ + ((((limit) >> 12) & 0xFFFF) | (((base)&0xFFFF) << 16)) +#define GEN_GDT_DESC_UP(base, limit, flags) \ + ((((base) >> 16) & 0xFF) | (((flags) << 8) & 0xFF00) | \ + (((limit) >> 12) & 0xFF0000) | ((base)&0xFF000000) | 0xc00000) /** * macro helper to create a IDT entry descriptor */ -#define GEN_IDT_DESC_LO(offset, selector, flags) \ - (((uint32_t)(offset) & 0xFFFF) | (((selector) & 0xFFFF) << 16)) +#define GEN_IDT_DESC_LO(offset, selector, flags) \ + (((uint32_t)(offset)&0xFFFF) | (((selector)&0xFFFF) << 16)) -#define GEN_IDT_DESC_UP(offset, selector, flags) \ - (((uint32_t)(offset) & 0xFFFF0000) | (((flags) & 0xFF) << 8)) +#define GEN_IDT_DESC_UP(offset, selector, flags) \ + (((uint32_t)(offset)&0xFFFF0000) | (((flags)&0xFF) << 8)) #endif /* __CROS_EC_IA_STRUCTS_H */ diff --git a/core/minute-ia/include/fpu.h b/core/minute-ia/include/fpu.h new file mode 100644 index 0000000000..9c0e818099 --- /dev/null +++ b/core/minute-ia/include/fpu.h @@ -0,0 +1,180 @@ +/* Copyright 2016 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Math utility functions for minute-IA */ + +#ifndef __CROS_EC_FPU_H +#define __CROS_EC_FPU_H + +#include "config.h" + +#ifdef CONFIG_FPU + +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 + +static inline float sqrtf(float v) +{ + float root; + + /* root = fsqart (v); */ + asm volatile("fsqrt" : "=t"(root) : "0"(v)); + return root; +} + +/* Absolute value of V. */ +static inline float fabsf(float v) +{ + float root; + + /* root = fabs (v); */ + asm volatile("fabs" : "=t"(root) : "0"(v)); + return root; +} + +/** + * Natural logarithm of V. + * + * @return ln(v) + */ +static inline float logf(float v) +{ + float res; + + asm volatile("fldln2\n" + "fxch\n" + "fyl2x\n" + : "=t"(res) + : "0"(v)); + + return res; +} + +/** + * Exponential function of V. + * + * @return e**v + */ +static inline float expf(float v) +{ + float res; + + asm volatile("fldl2e\n" + "fmulp\n" + "fld %%st(0)\n" + "frndint\n" + "fsubr %%st(0),%%st(1)\n" /* bug-binutils/19054 */ + "fxch %%st(1)\n" + "f2xm1\n" + "fld1\n" + "faddp\n" + "fscale\n" + "fstp %%st(1)\n" + : "=t"(res) + : "0"(v)); + + return res; +} + +/** + * X to the Y power. + * + * @return x**y + */ +static inline float powf(float x, float y) +{ + float res; + + asm volatile("fyl2x\n" + "fld %%st(0)\n" + "frndint\n" + "fsub %%st,%%st(1)\n" + "fxch\n" + "fchs\n" + "f2xm1\n" + "fld1\n" + "faddp\n" + "fxch\n" + "fld1\n" + "fscale\n" + "fstp %%st(1)\n" + "fmulp\n" + : "=t"(res) + : "0"(x), "u"(y) + : "st(1)"); + + return res; +} + +/* Smallest integral value not less than V. */ +static inline float ceilf(float v) +{ + float res; + unsigned short control_word, control_word_tmp; + + asm volatile("fnstcw %0" : "=m"(control_word)); + /* Set Rounding Mode to 10B, round up toward +infinity */ + control_word_tmp = (control_word | 0x0800) & 0xfbff; + asm volatile("fld %3\n" + "fldcw %1\n" + "frndint\n" + "fldcw %2" + : "=t"(res) + : "m"(control_word_tmp), "m"(control_word), "m"(v)); + + return res; +} + +/* Arc tangent of Y/X. */ +static inline float atan2f(float y, float x) +{ + float res; + + asm volatile("fpatan" : "=t"(res) : "0"(x), "u"(y) : "st(1)"); + + return res; +} + +/* Arc tangent of V. */ +static inline float atanf(float v) +{ + float res; + + asm volatile("fld1\n" + "fpatan\n" + : "=t"(res) + : "0"(v)); + + return res; +} + +/* Sine of V. */ +static inline float sinf(float v) +{ + float res; + + asm volatile("fsin" : "=t"(res) : "0"(v)); + + return res; +} + +/* Cosine of V. */ +static inline float cosf(float v) +{ + float res; + + asm volatile("fcos" : "=t"(res) : "0"(v)); + + return res; +} + +/* Arc cosine of V. */ +static inline float acosf(float v) +{ + return atan2f(sqrtf(1.0 - v * v), v); +} + +#endif /* CONFIG_FPU */ +#endif /* __CROS_EC_FPU_H */ diff --git a/core/minute-ia/include/math.h b/core/minute-ia/include/math.h deleted file mode 100644 index 00f73ccaa1..0000000000 --- a/core/minute-ia/include/math.h +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Math utility functions for minute-IA */ - -#ifndef __CROS_EC_MATH_H -#define __CROS_EC_MATH_H - -#include "config.h" - -#ifdef CONFIG_FPU - -#define M_PI 3.14159265358979323846 -#define M_PI_2 1.57079632679489661923 - -static inline float sqrtf(float v) -{ - float root; - - /* root = fsqart (v); */ - asm volatile( - "fsqrt" - : "=t" (root) - : "0" (v) - ); - return root; -} - -/* Absolute value of V. */ -static inline float fabsf(float v) -{ - float root; - - /* root = fabs (v); */ - asm volatile( - "fabs" - : "=t" (root) - : "0" (v) - ); - return root; -} - -/** - * Natural logarithm of V. - * - * @return ln(v) - */ -static inline float logf(float v) -{ - float res; - - asm volatile( - "fldln2\n" - "fxch\n" - "fyl2x\n" - : "=t" (res) - : "0" (v)); - - return res; -} - -/** - * Exponential function of V. - * - * @return e**v - */ -static inline float expf(float v) -{ - float res; - - asm volatile( - "fldl2e\n" - "fmulp\n" - "fld %%st(0)\n" - "frndint\n" - "fsubr %%st(0),%%st(1)\n" /* bug-binutils/19054 */ - "fxch %%st(1)\n" - "f2xm1\n" - "fld1\n" - "faddp\n" - "fscale\n" - "fstp %%st(1)\n" - : "=t" (res) - : "0" (v)); - - return res; -} - -/** - * X to the Y power. - * - * @return x**y - */ -static inline float powf(float x, float y) -{ - float res; - - asm volatile( - "fyl2x\n" - "fld %%st(0)\n" - "frndint\n" - "fsub %%st,%%st(1)\n" - "fxch\n" - "fchs\n" - "f2xm1\n" - "fld1\n" - "faddp\n" - "fxch\n" - "fld1\n" - "fscale\n" - "fstp %%st(1)\n" - "fmulp\n" - : "=t" (res) - : "0" (x), "u" (y) - : "st(1)"); - - return res; -} - -/* Smallest integral value not less than V. */ -static inline float ceilf(float v) -{ - float res; - unsigned short control_word, control_word_tmp; - - asm volatile("fnstcw %0" : "=m" (control_word)); - /* Set Rounding Mode to 10B, round up toward +infinity */ - control_word_tmp = (control_word | 0x0800) & 0xfbff; - asm volatile( - "fld %3\n" - "fldcw %1\n" - "frndint\n" - "fldcw %2" - : "=t" (res) - : "m" (control_word_tmp), "m"(control_word), "m" (v)); - - return res; -} - -/* Arc tangent of Y/X. */ -static inline float atan2f(float y, float x) -{ - float res; - - asm volatile("fpatan" : "=t" (res) : "0" (x), "u" (y) : "st(1)"); - - return res; -} - -/* Arc tangent of V. */ -static inline float atanf(float v) -{ - float res; - - asm volatile( - "fld1\n" - "fpatan\n" - : "=t" (res) - : "0" (v)); - - return res; -} - -/* Sine of V. */ -static inline float sinf(float v) -{ - float res; - - asm volatile("fsin" : "=t" (res) : "0" (v)); - - return res; -} - -/* Cosine of V. */ -static inline float cosf(float v) -{ - float res; - - asm volatile("fcos" : "=t" (res) : "0" (v)); - - return res; -} - -/* Arc cosine of V. */ -static inline float acosf(float v) -{ - return atan2f(sqrtf(1.0 - v * v), v); -} - -#define COND_FP_NAN 0x0100 -#define COND_FP_SIGNBIT 0x0200 -#define COND_FP_NORMAL 0x0400 -#define COND_FP_ZERO 0x4000 -#define COND_FP_INFINITE (COND_FP_NAN | COND_FP_NORMAL) - -/* Check if V is NaN (not-a-number). */ -static inline int __isnanf(float v) -{ - uint16_t stat; - - asm volatile( - "fxam\n" - "fnstsw %0\n" - : "=r" (stat) - : "0" (v)); - - return (stat & (COND_FP_NAN | COND_FP_NORMAL | COND_FP_ZERO)) - == COND_FP_NAN; -} - -/** - * Check if V is infinite. - * - * @return 0 if V is finite or NaN. - * @return +1 if V is +infinite. - * @return -1 if V is -infinite. - */ -static inline int __isinff(float v) -{ - uint16_t stat; - - asm volatile( - "fxam\n" - "fnstsw %0\n" - : "=r" (stat) - : "v" (v)); - - if ((stat & (COND_FP_NAN | COND_FP_NORMAL | COND_FP_ZERO)) == - COND_FP_INFINITE) { - /* Infinite number, check sign */ - return stat & COND_FP_SIGNBIT ? -1 : 1; - } - - /* Finite or NaN */ - return 0; -} - -#endif /* CONFIG_FPU */ -#endif /* __CROS_EC_MATH_H */ diff --git a/core/minute-ia/init.S b/core/minute-ia/init.S index b8e51ccc91..4d3ac47da6 100644 --- a/core/minute-ia/init.S +++ b/core/minute-ia/init.S @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/core/minute-ia/interrupts.c b/core/minute-ia/interrupts.c index 2d55d3129e..b99bb6e49a 100644 --- a/core/minute-ia/interrupts.c +++ b/core/minute-ia/interrupts.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -20,8 +20,8 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /* The IDT - initialized in init.S */ extern struct idt_entry __idt[NUM_VECTORS]; @@ -54,7 +54,7 @@ static void set_ioapic_redtbl_raw(const uint32_t irq, const uint32_t val) * bitmap for current IRQ's mask status * ISH support max 64 IRQs, 64 bit bitmap value is ok */ -#define ISH_MAX_IOAPIC_IRQS (64) +#define ISH_MAX_IOAPIC_IRQS (64) uint64_t ioapic_irq_mask_bitmap; /** @@ -70,7 +70,7 @@ uint64_t disable_all_interrupts(void) uint64_t saved_map; int i; - saved_map = ioapic_irq_mask_bitmap; + saved_map = ioapic_irq_mask_bitmap; for (i = 0; i < ISH_MAX_IOAPIC_IRQS; i++) { if (((uint64_t)0x1 << i) & saved_map) @@ -179,27 +179,27 @@ static const irq_desc_t system_irqs[] = { * and go directly to the CPU core, so get_current_interrupt_vector * cannot be used. */ -#define DEFINE_EXN_HANDLER(vector) \ +#define DEFINE_EXN_HANDLER(vector) \ _DEFINE_EXN_HANDLER(vector, exception_panic_##vector) -#define _DEFINE_EXN_HANDLER(vector, name) \ - void __keep name(void); \ - noreturn void name(void) \ - { \ - __asm__ ("push $0\n" \ - "push $" #vector "\n" \ - "call exception_panic\n"); \ - __builtin_unreachable(); \ +#define _DEFINE_EXN_HANDLER(vector, name) \ + void __keep name(void); \ + noreturn void name(void) \ + { \ + __asm__("push $0\n" \ + "push $" #vector "\n" \ + "call exception_panic\n"); \ + __builtin_unreachable(); \ } -#define DEFINE_EXN_HANDLER_W_ERRORCODE(vector) \ +#define DEFINE_EXN_HANDLER_W_ERRORCODE(vector) \ _DEFINE_EXN_HANDLER_W_ERRORCODE(vector, exception_panic_##vector) -#define _DEFINE_EXN_HANDLER_W_ERRORCODE(vector, name) \ - void __keep name(void); \ - noreturn void name(void) \ - { \ - __asm__ ("push $" #vector "\n" \ - "call exception_panic\n"); \ - __builtin_unreachable(); \ +#define _DEFINE_EXN_HANDLER_W_ERRORCODE(vector, name) \ + void __keep name(void); \ + noreturn void name(void) \ + { \ + __asm__("push $" #vector "\n" \ + "call exception_panic\n"); \ + __builtin_unreachable(); \ } DEFINE_EXN_HANDLER(0); @@ -228,15 +228,10 @@ DEFINE_EXN_HANDLER(20); * watchdog timer expiration. However, this time, hardware does not * push errorcode, and we must account for that by pushing zero. */ -noreturn __keep -void exception_panic_wdt(uint32_t cs) +noreturn __keep void exception_panic_wdt(uint32_t cs) { - exception_panic( - CONFIG_MIA_WDT_VEC, - 0, - (uint32_t)__builtin_return_address(0), - cs, - 0); + exception_panic(CONFIG_MIA_WDT_VEC, 0, + (uint32_t)__builtin_return_address(0), cs, 0); } void set_interrupt_gate(uint8_t num, isr_handler_t func, uint8_t flags) @@ -244,7 +239,7 @@ void set_interrupt_gate(uint8_t num, isr_handler_t func, uint8_t flags) uint16_t code_segment; /* When the flat model is used the CS will never change. */ - __asm volatile ("mov %%cs, %0":"=r" (code_segment)); + __asm volatile("mov %%cs, %0" : "=r"(code_segment)); __idt[num].dword_lo = GEN_IDT_DESC_LO(func, code_segment, flags); __idt[num].dword_up = GEN_IDT_DESC_UP(func, code_segment, flags); @@ -384,26 +379,28 @@ void handle_lapic_lvt_error(void) /* LAPIC LVT error is not an IRQ and can not use DECLARE_IRQ() to call. */ void _lapic_error_handler(void); -__asm__ ( - ".section .text._lapic_error_handler\n" +__asm__(".section .text._lapic_error_handler\n" "_lapic_error_handler:\n" - "pusha\n" - ASM_LOCK_PREFIX "addl $1, __in_isr\n" - "movl %esp, %eax\n" - "movl $stack_end, %esp\n" - "push %eax\n" + "pusha\n" ASM_LOCK_PREFIX "addl $1, __in_isr\n" + "movl %esp, %eax\n" + "movl $stack_end, %esp\n" + "push %eax\n" #ifdef CONFIG_TASK_PROFILING - "push $" STRINGIFY(CONFIG_IRQ_COUNT) "\n" - "call task_start_irq_handler\n" - "addl $0x04, %esp\n" + "push $" STRINGIFY( + CONFIG_IRQ_COUNT) "\n" + "call task_start_irq_handler\n" + "addl $0x04, %esp\n" #endif - "call handle_lapic_lvt_error\n" - "pop %esp\n" - "movl $0x00, (0xFEE000B0)\n" /* Set EOI for LAPIC */ - ASM_LOCK_PREFIX "subl $1, __in_isr\n" - "popa\n" - "iret\n" - ); + "call handle_lapic_lvt_error\n" + "pop %esp\n" + "movl $0x00, (0xFEE000B0)\n" /* Set + EOI + for + LAPIC + */ + ASM_LOCK_PREFIX "subl $1, __in_isr\n" + "popa\n" + "iret\n"); /* Should only be called in interrupt context */ void unhandled_vector(void) @@ -411,7 +408,7 @@ void unhandled_vector(void) uint32_t vec = get_current_interrupt_vector(); CPRINTF("Ignoring vector 0x%0x!\n", vec); /* Put the vector number in eax so default_int_handler can use it */ - asm("" : : "a" (vec)); + asm("" : : "a"(vec)); } /** @@ -447,15 +444,15 @@ void lapic_restore(void) void init_interrupts(void) { - unsigned entry; + unsigned int entry; const struct irq_def *p; - unsigned num_system_irqs = ARRAY_SIZE(system_irqs); - unsigned max_entries = (read_ioapic_reg(IOAPIC_VERSION) >> 16) & 0xff; + unsigned int num_system_irqs = ARRAY_SIZE(system_irqs); + unsigned int max_entries = (read_ioapic_reg(IOAPIC_VERSION) >> 16) & + 0xff; /* Setup gates for IRQs declared by drivers using DECLARE_IRQ */ for (p = __irq_data; p < __irq_data_end; p++) - set_interrupt_gate(IRQ_TO_VEC(p->irq), - p->handler, + set_interrupt_gate(IRQ_TO_VEC(p->irq), p->handler, IDT_DESC_FLAGS); /* Software generated IRQ */ @@ -474,11 +471,11 @@ void init_interrupts(void) for (entry = 0; entry < num_system_irqs; entry++) set_ioapic_redtbl_raw(system_irqs[entry].irq, system_irqs[entry].vector | - IOAPIC_REDTBL_DELMOD_FIXED | - IOAPIC_REDTBL_DESTMOD_PHYS | - IOAPIC_REDTBL_MASK | - system_irqs[entry].polarity | - system_irqs[entry].trigger); + IOAPIC_REDTBL_DELMOD_FIXED | + IOAPIC_REDTBL_DESTMOD_PHYS | + IOAPIC_REDTBL_MASK | + system_irqs[entry].polarity | + system_irqs[entry].trigger); set_interrupt_gate(ISH_TS_VECTOR, __switchto, IDT_DESC_FLAGS); diff --git a/core/minute-ia/interrupts.h b/core/minute-ia/interrupts.h index 3a951a5ddb..34abd587d3 100644 --- a/core/minute-ia/interrupts.h +++ b/core/minute-ia/interrupts.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -11,21 +11,19 @@ #ifndef __ASSEMBLER__ #include -#define USHRT_MAX 0xFFFF +#define USHRT_MAX 0xFFFF typedef struct { - unsigned irq; - unsigned trigger; - unsigned polarity; - unsigned vector; + unsigned int irq; + unsigned int trigger; + unsigned int polarity; + unsigned int vector; } irq_desc_t; -#define INTR_DESC(__irq,__vector,__trig) \ - { \ - .irq = __irq, \ - .trigger = __trig, \ - .polarity = IOAPIC_REDTBL_INTPOL_HIGH, \ - .vector = __vector \ - } +#define INTR_DESC(__irq, __vector, __trig) \ + { \ + .irq = __irq, .trigger = __trig, \ + .polarity = IOAPIC_REDTBL_INTPOL_HIGH, .vector = __vector \ + } #define LEVEL_INTR(__irq, __vector) \ INTR_DESC(__irq, __vector, IOAPIC_REDTBL_TRIGGER_LEVEL) @@ -34,18 +32,18 @@ typedef struct { #endif /* ISH has a single core processor */ -#define DEST_APIC_ID 0 -#define NUM_VECTORS 256 +#define DEST_APIC_ID 0 +#define NUM_VECTORS 256 /* APIC bit definitions. */ -#define APIC_DIV_16 0x03 -#define APIC_ENABLE_BIT (1UL << 8UL) -#define APIC_SPURIOUS_INT REG32(ISH_LAPIC_BASE + 0xF0UL ) -#define APIC_LVT_ERROR REG32(ISH_LAPIC_BASE + 0x370UL) +#define APIC_DIV_16 0x03 +#define APIC_ENABLE_BIT (1UL << 8UL) +#define APIC_SPURIOUS_INT REG32(ISH_LAPIC_BASE + 0xF0UL) +#define APIC_LVT_ERROR REG32(ISH_LAPIC_BASE + 0x370UL) #ifndef __ASSEMBLER__ -typedef void (*isr_handler_t) (void); +typedef void (*isr_handler_t)(void); void init_interrupts(void); void mask_interrupt(unsigned int irq); @@ -66,4 +64,4 @@ void restore_interrupts(uint64_t irq_map); uint32_t get_current_interrupt_vector(void); #endif -#endif /* __CROS_EC_IA32_INTERRUPTS_H */ +#endif /* __CROS_EC_IA32_INTERRUPTS_H */ diff --git a/core/minute-ia/irq_handler.h b/core/minute-ia/irq_handler.h index eec0ffddb4..deb8048e12 100644 --- a/core/minute-ia/irq_handler.h +++ b/core/minute-ia/irq_handler.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,7 +12,7 @@ #include "task.h" #include "task_defs.h" -asm (".include \"core/minute-ia/irq_handler_common.S\""); +asm(".include \"core/minute-ia/irq_handler_common.S\""); /* Helper macros to build the IRQ handler and priority struct names */ #define IRQ_HANDLER(irqname) CONCAT3(_irq_, irqname, _handler) @@ -30,26 +30,24 @@ asm (".include \"core/minute-ia/irq_handler_common.S\""); * Each irq has a irq_data structure placed in .rodata.irqs section, * to be used for dynamically setting up interrupt gates */ -#define DECLARE_IRQ_(irq_, routine_, vector) \ - void __keep routine_(void); \ - void IRQ_HANDLER(irq_)(void); \ - __asm__ (".section .rodata.irqs\n"); \ - const struct irq_def __keep CONCAT4(__irq_, irq_, _, routine_) \ - __attribute__((section(".rodata.irqs"))) = { \ - .irq = irq_, \ - .routine = routine_, \ - .handler = IRQ_HANDLER(irq_) \ - }; \ - __asm__ ( \ - ".section .text._irq_" #irq_ "_handler\n" \ - "_irq_" #irq_ "_handler:\n" \ - "pusha\n" \ - ASM_LOCK_PREFIX "addl $1, __in_isr\n" \ - "irq_handler_common $0 $0 $" #irq_ "\n" \ - "movl $"#vector ", " STRINGIFY(IOAPIC_EOI_REG_ADDR) "\n" \ - "movl $0x00, " STRINGIFY(LAPIC_EOI_REG_ADDR) "\n" \ - ASM_LOCK_PREFIX "subl $1, __in_isr\n" \ - "popa\n" \ - "iret\n" \ - ) -#endif /* __CROS_EC_IRQ_HANDLER_H */ +#define DECLARE_IRQ_(irq_, routine_, vector) \ + static void __keep routine_(void); \ + void IRQ_HANDLER(irq_)(void); \ + __asm__(".section .rodata.irqs\n"); \ + const struct irq_def __keep CONCAT4(__irq_, irq_, _, routine_) \ + __attribute__((section( \ + ".rodata.irqs"))) = { .irq = irq_, \ + .routine = routine_, \ + .handler = IRQ_HANDLER(irq_) }; \ + __asm__(".section .text._irq_" #irq_ "_handler\n" \ + "_irq_" #irq_ "_handler:\n" \ + "pusha\n" ASM_LOCK_PREFIX "addl $1, __in_isr\n" \ + "irq_handler_common $0 $0 $" #irq_ "\n" \ + "movl $" #vector ", " STRINGIFY( \ + IOAPIC_EOI_REG_ADDR) "\n" \ + "movl $0x00, " STRINGIFY( \ + LAPIC_EOI_REG_ADDR) "\n" ASM_LOCK_PREFIX \ + "subl $1, __in_isr\n" \ + "popa\n" \ + "iret\n") +#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/minute-ia/irq_handler_common.S b/core/minute-ia/irq_handler_common.S index e07cf26ce1..2445f83730 100644 --- a/core/minute-ia/irq_handler_common.S +++ b/core/minute-ia/irq_handler_common.S @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/core/minute-ia/mia_panic_internal.h b/core/minute-ia/mia_panic_internal.h index 748ccbf2dd..d9d213ca85 100644 --- a/core/minute-ia/mia_panic_internal.h +++ b/core/minute-ia/mia_panic_internal.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -8,10 +8,5 @@ * convenientely in the same order as pushed by hardwared during a * processor exception. */ -noreturn -void exception_panic( - uint32_t vector, - uint32_t errorcode, - uint32_t eip, - uint32_t cs, - uint32_t eflags); +noreturn void exception_panic(uint32_t vector, uint32_t errorcode, uint32_t eip, + uint32_t cs, uint32_t eflags); diff --git a/core/minute-ia/mpu.c b/core/minute-ia/mpu.c index 389668ea6f..6cbf4c634f 100644 --- a/core/minute-ia/mpu.c +++ b/core/minute-ia/mpu.c @@ -1,12 +1,12 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* MPU module for ISH */ -#include "mpu.h" #include "console.h" +#include "mpu.h" #include "registers.h" #include "task.h" #include "util.h" diff --git a/core/minute-ia/panic.c b/core/minute-ia/panic.c index acaee72496..d02778891d 100644 --- a/core/minute-ia/panic.c +++ b/core/minute-ia/panic.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -57,13 +57,12 @@ void panic_data_print(const struct panic_data *pdata) else if (pdata->x86.vector <= 20) panic_printf("Reason: %s\n", panic_reason[pdata->x86.vector]); else if (panic_sw_reason_is_valid(pdata->x86.vector)) { - panic_printf("Software panic reason %s\n", - panic_sw_reasons[pdata->x86.vector - - PANIC_SW_BASE]); + panic_printf( + "Software panic reason %s\n", + panic_sw_reasons[pdata->x86.vector - PANIC_SW_BASE]); panic_printf("Software panic info 0x%x\n", pdata->x86.error_code); - } - else + } else panic_printf("Interrupt vector number: 0x%08X (unknown)\n", pdata->x86.vector); panic_printf("\n"); @@ -91,12 +90,8 @@ void panic_data_print(const struct panic_data *pdata) * order pushed to the stack by hardware: see "Intel 64 and IA-32 * Architectures Software Developer's Manual", Volume 3A, Figure 6-4. */ -void exception_panic( - uint32_t vector, - uint32_t error_code, - uint32_t eip, - uint32_t cs, - uint32_t eflags) +void exception_panic(uint32_t vector, uint32_t error_code, uint32_t eip, + uint32_t cs, uint32_t eflags) { /* * If a panic were to occur during the reset procedure, we want @@ -105,6 +100,7 @@ void exception_panic( * already. */ static int panic_once; + struct panic_data *pdata; register uint32_t eax asm("eax"); register uint32_t ebx asm("ebx"); @@ -112,8 +108,10 @@ void exception_panic( register uint32_t edx asm("edx"); register uint32_t esi asm("esi"); register uint32_t edi asm("edi"); + asm("" + : "=r"(eax), "=r"(ebx), "=r"(ecx), "=r"(edx), "=r"(esi), "=r"(edi)); - struct panic_data * const pdata = get_panic_data_write(); + pdata = get_panic_data_write(); /* Save registers to global panic structure */ pdata->x86.eax = eax; @@ -173,26 +171,22 @@ void exception_panic( __builtin_unreachable(); } -noreturn -void software_panic(uint32_t reason, uint32_t info) +noreturn void software_panic(uint32_t reason, uint32_t info) { uint16_t code_segment; /* Get the current code segment */ - __asm__ volatile ("movw %%cs, %0":"=m" (code_segment)); + __asm__ volatile("movw %%cs, %0" : "=m"(code_segment)); - exception_panic(reason, - info, - (uint32_t)__builtin_return_address(0), - code_segment, - 0); + exception_panic(reason, info, (uint32_t)__builtin_return_address(0), + code_segment, 0); __builtin_unreachable(); } void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) { - struct panic_data * const pdata = get_panic_data_write(); + struct panic_data *const pdata = get_panic_data_write(); /* Setup panic data structure */ memset(pdata, 0, CONFIG_PANIC_DATA_SIZE); @@ -209,7 +203,7 @@ void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) { - struct panic_data * const pdata = panic_get_data(); + struct panic_data *const pdata = panic_get_data(); if (pdata && pdata->struct_version == 2) { *reason = pdata->x86.vector; diff --git a/core/minute-ia/switch.S b/core/minute-ia/switch.S index f8d0be3874..b014bb4c29 100644 --- a/core/minute-ia/switch.S +++ b/core/minute-ia/switch.S @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -24,7 +24,6 @@ # Start the task scheduling. Start current_task (hook_task) # This function is not an ISR but imitates the sequence. .align 4 -.func __task_start __task_start: movl 0x4(%esp), %ecx movl current_task, %eax @@ -39,12 +38,10 @@ __task_start: movl $0x1, (%ecx) # first task is ready. set start_called = 1 popa iret -.endfunc # Default interrupt handler - to handle exceptions # and prints error .align 4 -.func default_int_handler default_int_handler: pusha @@ -70,10 +67,8 @@ default_int_handler: ASM_LOCK_PREFIX subl $1, __in_isr popa iret -.endfunc .align 4 -.func sw_irq_handler sw_irq_handler: pusha ASM_LOCK_PREFIX addl $1, __in_isr @@ -91,14 +86,12 @@ sw_irq_handler: ASM_LOCK_PREFIX subl $1, __in_isr popa iret -.endfunc # Switches from one task to another if ready. # __schedule triggers software interrupt ISH_TS_VECTOR, which is handled by # __switchto .align 4 -.func __switchto __switchto: pusha ASM_LOCK_PREFIX addl $1, __in_isr @@ -116,4 +109,3 @@ __switchto: ASM_LOCK_PREFIX subl $1, __in_isr popa iret -.endfunc diff --git a/core/minute-ia/task.c b/core/minute-ia/task.c index 431bd62e54..6322125247 100644 --- a/core/minute-ia/task.c +++ b/core/minute-ia/task.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,21 +13,22 @@ #define TEST_TASK_EXTRA_ARGS 0 #include "atomic.h" +#include "builtin/assert.h" #include "common.h" #include "console.h" +#include "hpet.h" +#include "interrupts.h" #include "link_defs.h" #include "panic.h" #include "task.h" +#include "task_defs.h" #include "timer.h" #include "util.h" -#include "task_defs.h" -#include "interrupts.h" -#include "hpet.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) /* Value to store in unused stack */ #define STACK_UNUSED_VALUE 0xdeadd00d @@ -43,11 +44,9 @@ CONFIG_TEST_TASK_LIST extern volatile uint32_t __in_isr; /* Task names for easier debugging */ -#define TASK(n, r, d, s, f) #n, -static const char * const task_names[] = { - "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST +#define TASK(n, r, d, s, f) #n, +static const char *const task_names[] = { + "<< idle >>", CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST }; #undef TASK @@ -57,12 +56,12 @@ static uint64_t task_start_time; /* Time task scheduling started */ * We only keep 32-bit values for exception start/end time, to avoid * accounting errors when we service interrupt when the timer wraps around. */ -static uint32_t exc_start_time; /* Time of task->exception transition */ -static uint32_t exc_end_time; /* Time of exception->task transition */ -static uint64_t exc_total_time; /* Total time in exceptions */ -static uint32_t svc_calls; /* Number of service calls */ -static uint32_t task_switches; /* Number of times active task changed */ -static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ +static uint32_t exc_start_time; /* Time of task->exception transition */ +static uint32_t exc_end_time; /* Time of exception->task transition */ +static uint64_t exc_total_time; /* Total time in exceptions */ +static atomic_t svc_calls; /* Number of service calls */ +static uint32_t task_switches; /* Number of times active task changed */ +static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ #endif void __schedule(int desched, int resched); @@ -97,43 +96,36 @@ static void task_exit_trap(void) } /* Startup parameters for all tasks. */ -#define TASK(n, r, d, s, f) { \ - .r0 = (uint32_t)d, \ - .pc = (uint32_t)r, \ - .stack_size = s, \ - .flags = f, \ -}, +#define TASK(n, r, d, s, f) \ + { \ + .r0 = (uint32_t)d, \ + .pc = (uint32_t)r, \ + .stack_size = s, \ + .flags = f, \ + }, static const struct { uint32_t r0; uint32_t pc; uint16_t stack_size; uint32_t flags; -} tasks_init[] = { - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE, 0) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -}; +} tasks_init[] = { TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE, 0) + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST }; #undef TASK /* Contexts for all tasks */ static task_ tasks[TASK_ID_COUNT]; /* Validity checks about static task invariants */ -BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned) * 8); +BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned int) * 8); BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); - /* Stacks for all tasks */ -#define TASK(n, r, d, s, f) + s -uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE, 0) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -] __aligned(8); +#define TASK(n, r, d, s, f) +s +uint8_t task_stacks[0 TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE, 0) + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST] __aligned(8); #undef TASK - task_ *current_task, *next_task; /* @@ -143,15 +135,15 @@ task_ *current_task, *next_task; * can do their init within a task switching context. The hooks task will then * make a call to enable all tasks. */ -static uint32_t tasks_ready = BIT(TASK_ID_HOOKS); +static atomic_t tasks_ready = BIT(TASK_ID_HOOKS); /* * Initially allow only the HOOKS and IDLE task to run, regardless of ready * status, in order for HOOK_INIT to complete before other tasks. * task_enable_all_tasks() will open the flood gates. */ -static uint32_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); +static atomic_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); -static int start_called; /* Has task swapping started */ +static int start_called; /* Has task swapping started */ static inline task_ *__task_id_to_ptr(task_id_t id) { @@ -160,7 +152,7 @@ static inline task_ *__task_id_to_ptr(task_id_t id) void interrupt_disable(void) { - __asm__ __volatile__ ("cli"); + __asm__ __volatile__("cli"); } void interrupt_enable(void) @@ -170,12 +162,24 @@ void interrupt_enable(void) */ ASSERT(task_start_called() != 1); - __asm__ __volatile__ ("sti"); + __asm__ __volatile__("sti"); } -inline int in_interrupt_context(void) +inline bool is_interrupt_enabled(void) { - return !!__in_isr; + uint32_t eflags = 0; + + __asm__ __volatile__("pushfl\n" + "popl %0\n" + : "=r"(eflags)); + + /* Check Interrupt Enable flag */ + return eflags & 0x200; +} + +inline bool in_interrupt_context(void) +{ + return __in_isr; } task_id_t task_get_current(void) @@ -195,7 +199,7 @@ const char *task_get_name(task_id_t tskid) return "<< unknown >>"; } -uint32_t *task_get_event_bitmap(task_id_t tskid) +atomic_t *task_get_event_bitmap(task_id_t tskid) { task_ *tsk = __task_id_to_ptr(tskid); @@ -217,13 +221,12 @@ uint32_t switch_handler(int desched, task_id_t resched) current = current_task; if (IS_ENABLED(CONFIG_DEBUG_STACK_OVERFLOW) && - *current->stack != STACK_UNUSED_VALUE) { + *current->stack != STACK_UNUSED_VALUE && + task_enabled(current - tasks)) { panic_printf("\n\nStack overflow in %s task!\n", task_get_name(current - tasks)); - if (IS_ENABLED(CONFIG_SOFTWARE_PANIC)) - software_panic(PANIC_SW_STACK_OVERFLOW, - current - tasks); + software_panic(PANIC_SW_STACK_OVERFLOW, current - tasks); } if (desched && !current->events) { @@ -239,8 +242,7 @@ uint32_t switch_handler(int desched, task_id_t resched) next = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); /* Only the first ISR on the (nested IRQ) stack calculates time */ - if (IS_ENABLED(CONFIG_TASK_PROFILING) && - __in_isr == 1) { + if (IS_ENABLED(CONFIG_TASK_PROFILING) && __in_isr == 1) { /* Track time in interrupts */ uint32_t t = get_time().le.lo; @@ -287,7 +289,7 @@ void __keep task_start_irq_handler(void *data) irq_dist[irq]++; else /* Track total number of service calls */ - deprecated_atomic_add(&svc_calls, 1); + atomic_add(&svc_calls, 1); /* Only the outer ISR should keep track of the ISR start time */ if (__in_isr == 1) { @@ -318,7 +320,7 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched) ret = timer_arm(deadline, me); ASSERT(ret == EC_SUCCESS); } - while (!(evt = deprecated_atomic_read_clear(&tsk->events))) { + while (!(evt = atomic_clear(&tsk->events))) { /* Remove ourself and get the next task in the scheduler */ __schedule(1, resched); resched = TASK_ID_IDLE; @@ -326,12 +328,12 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched) if (timeout_us > 0) { timer_cancel(me); /* Ensure timer event is clear, we no longer care about it */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); + atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); } return evt; } -uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait) +void task_set_event(task_id_t tskid, uint32_t event) { task_ *receiver = __task_id_to_ptr(tskid); @@ -345,20 +347,15 @@ uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait) ASSERT(receiver); /* Set the event bit in the receiver message bitmap */ - deprecated_atomic_or(&receiver->events, event); + atomic_or(&receiver->events, event); /* Re-schedule if priorities have changed */ if (in_interrupt_context()) { /* The receiver might run again */ - deprecated_atomic_or(&tasks_ready, 1 << tskid); + atomic_or(&tasks_ready, 1 << tskid); } else { - if (wait) - return __wait_evt(-1, tskid); - else - __schedule(0, tskid); + __schedule(0, tskid); } - - return 0; } uint32_t task_wait_event(int timeout_us) @@ -389,8 +386,7 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) /* Re-post any other events collected */ if (events & ~event_mask) - deprecated_atomic_or(¤t_task->events, - events & ~event_mask); + atomic_or(¤t_task->events, events & ~event_mask); return events & event_mask; } @@ -406,12 +402,17 @@ void task_enable_all_tasks(void) void task_enable_task(task_id_t tskid) { - deprecated_atomic_or(&tasks_enabled, BIT(tskid)); + atomic_or(&tasks_enabled, BIT(tskid)); +} + +bool task_enabled(task_id_t tskid) +{ + return tasks_enabled & BIT(tskid); } void task_disable_task(task_id_t tskid) { - deprecated_atomic_clear_bits(&tasks_enabled, BIT(tskid)); + atomic_clear_bits(&tasks_enabled, BIT(tskid)); if (!in_interrupt_context() && tskid == task_get_current()) __schedule(0, 0); @@ -455,15 +456,14 @@ void mutex_lock(struct mutex *mtx) uint32_t id = 1 << task_get_current(); ASSERT(id != TASK_ID_INVALID); - deprecated_atomic_or(&mtx->waiters, id); + atomic_or(&mtx->waiters, id); do { old_val = 0; - __asm__ __volatile__( - ASM_LOCK_PREFIX "cmpxchg %1, %2\n" - : "=a" (old_val) - : "r" (value), "m" (mtx->lock), "a" (old_val) - : "memory"); + __asm__ __volatile__(ASM_LOCK_PREFIX "cmpxchg %1, %2\n" + : "=a"(old_val) + : "r"(value), "m"(mtx->lock), "a"(old_val) + : "memory"); if (old_val != 0) { /* Contention on the mutex */ @@ -471,7 +471,7 @@ void mutex_lock(struct mutex *mtx) } } while (old_val); - deprecated_atomic_clear_bits(&mtx->waiters, id); + atomic_clear_bits(&mtx->waiters, id); } void mutex_unlock(struct mutex *mtx) @@ -480,11 +480,10 @@ void mutex_unlock(struct mutex *mtx) uint32_t old_val = 1, val = 0; task_ *tsk = current_task; - __asm__ __volatile__( - ASM_LOCK_PREFIX "cmpxchg %1, %2\n" - : "=a" (old_val) - : "r" (val), "m" (mtx->lock), "a" (old_val) - : "memory"); + __asm__ __volatile__(ASM_LOCK_PREFIX "cmpxchg %1, %2\n" + : "=a"(old_val) + : "r"(val), "m"(mtx->lock), "a"(old_val) + : "memory"); if (old_val == 1) waiters = mtx->waiters; /* else? Does unlock fail - what to do then ? */ @@ -494,11 +493,11 @@ void mutex_unlock(struct mutex *mtx) waiters &= ~BIT(id); /* Somebody is waiting on the mutex */ - task_set_event(id, TASK_EVENT_MUTEX, 0); + task_set_event(id, TASK_EVENT_MUTEX); } /* Ensure no event is remaining from mutex wake-up */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); + atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); } void task_print_list(void) @@ -513,7 +512,7 @@ void task_print_list(void) "StkUsed\n"); for (i = 0; i < TASK_ID_COUNT; i++) { - char is_ready = (tasks_ready & (1< 0) + /* Alignment is needed by flash_command_write() for RW update. */ + ASSERT(__image_size % CONFIG_FLASH_WRITE_SIZE == 0, + "Error: RW image is not aligned to CONFIG_FLASH_WRITE_SIZE") +#endif + +#ifdef CONFIG_FLASH_CROS /* * These linker labels are just for analysis and not used in the code. */ - __config_flash_size = CONFIG_FLASH_SIZE; + __config_flash_size = CONFIG_FLASH_SIZE_BYTES; __config_ro_size = CONFIG_RO_SIZE; __config_ec_protected_storage_size = CONFIG_EC_PROTECTED_STORAGE_SIZE; __config_rw_size = CONFIG_RW_SIZE; __config_ec_writable_storage_size = CONFIG_EC_WRITABLE_STORAGE_SIZE; #endif -#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_SLAVE) +#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_PERIPHERAL) .h2ram (NOLOAD) : { . += CONFIG_H2RAM_HOST_LPC_IO_BASE; *(.h2ram.pool.hostcmd) . = ALIGN(256); *(.h2ram.pool.acpiec) -#ifdef CONFIG_I2C_SLAVE +#ifdef CONFIG_I2C_PERIPHERAL . = ALIGN(256); *(.h2ram.pool.i2cslv) #endif @@ -309,7 +333,7 @@ SECTIONS "Not enough space for h2ram section.") #endif -#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH)) +#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS)) /DISCARD/ : { *(.google) } #endif diff --git a/core/nds32/include/fpu.h b/core/nds32/include/fpu.h new file mode 100644 index 0000000000..80c3395d14 --- /dev/null +++ b/core/nds32/include/fpu.h @@ -0,0 +1,14 @@ +/* Copyright 2017 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Math utility functions for N8 */ + +#ifndef __CROS_EC_FPU_H +#define __CROS_EC_FPU_H + +float sqrtf(float x); +float fabsf(float x); + +#endif /* __CROS_EC_FPU_H */ diff --git a/core/nds32/include/math.h b/core/nds32/include/math.h deleted file mode 100644 index 49d5585657..0000000000 --- a/core/nds32/include/math.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Math utility functions for N8 */ - -#ifndef __CROS_EC_MATH_H -#define __CROS_EC_MATH_H - -float sqrtf(float x); -float fabsf(float x); - -#endif /* __CROS_EC_MATH_H */ diff --git a/core/nds32/init.S b/core/nds32/init.S index b8e109c434..648e3d8183 100644 --- a/core/nds32/init.S +++ b/core/nds32/init.S @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -87,7 +87,7 @@ vector irq_15, 15 /* HW 15 */ .global eflash_sig eflash_sig: .byte 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5 -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI .byte 0xA4 /* eSPI */ #else .byte 0xA5 /* LPC */ diff --git a/core/nds32/irq_chip.h b/core/nds32/irq_chip.h index ca517558b3..a339bb516c 100644 --- a/core/nds32/irq_chip.h +++ b/core/nds32/irq_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/core/nds32/irq_handler.h b/core/nds32/irq_handler.h index b37b7927ef..b1feaa44c3 100644 --- a/core/nds32/irq_handler.h +++ b/core/nds32/irq_handler.h @@ -1,4 +1,4 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. +/* Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -15,11 +15,12 @@ * Macro to connect the interrupt handler "routine" to the irq number "irq" and * ensure it is enabled in the interrupt controller with the right priority. */ -#define DECLARE_IRQ(irq, routine, priority) \ - void IRQ_HANDLER(CPU_INT(irq))(void) \ - __attribute__ ((alias(STRINGIFY(routine)))); \ - const struct irq_priority __keep IRQ_PRIORITY(CPU_INT(irq)) \ - __attribute__((section(".rodata.irqprio"))) \ - = {CPU_INT(irq), priority} +#define DECLARE_IRQ(irq, routine, priority) \ + static void __keep routine(void); \ + void IRQ_HANDLER(CPU_INT(irq))(void) \ + __attribute__((alias(STRINGIFY(routine)))); \ + const struct irq_priority __keep IRQ_PRIORITY(CPU_INT(irq)) \ + __attribute__((section(".rodata.irqprio"))) = { CPU_INT(irq), \ + priority } -#endif /* __CROS_EC_IRQ_HANDLER_H */ +#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/nds32/math.c b/core/nds32/math.c index 496fcc0e5d..d0c8fc5c33 100644 --- a/core/nds32/math.c +++ b/core/nds32/math.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,19 +12,19 @@ union ieee_float_shape_type { }; /* Get a 32 bit int from a float. */ -#define GET_FLOAT_WORD(i, d) \ - do { \ +#define GET_FLOAT_WORD(i, d) \ + do { \ union ieee_float_shape_type gf_u; \ - gf_u.value = (d); \ - (i) = gf_u.word; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ } while (0) /* Set a float from a 32 bit int. */ -#define SET_FLOAT_WORD(d, i) \ - do { \ +#define SET_FLOAT_WORD(d, i) \ + do { \ union ieee_float_shape_type sf_u; \ - sf_u.word = (i); \ - (d) = sf_u.value; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ } while (0) float fabsf(float x) diff --git a/core/nds32/panic.c b/core/nds32/panic.c index 70e2cae3e0..b50da13e2c 100644 --- a/core/nds32/panic.c +++ b/core/nds32/panic.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,6 +10,7 @@ #include "printf.h" #include "software_panic.h" #include "system.h" +#include "system_safe_mode.h" #include "task.h" #include "timer.h" #include "util.h" @@ -17,7 +18,7 @@ /* General purpose register (r6) for saving software panic reason */ #define SOFT_PANIC_GPR_REASON 6 /* General purpose register (r7) for saving software panic information */ -#define SOFT_PANIC_GPR_INFO 7 +#define SOFT_PANIC_GPR_INFO 7 #ifdef CONFIG_DEBUG_EXCEPTIONS /** @@ -46,7 +47,7 @@ * All other exceptions not in the abovetable should have the INST field of * the ITYPE register set to 0. */ -static const char * const itype_inst[2] = { +static const char *const itype_inst[2] = { "a data memory access", "an instruction fetch access", }; @@ -54,7 +55,7 @@ static const char * const itype_inst[2] = { /** * bit[3-0] @ ITYPE, general exception type information. */ -static const char * const itype_exc_type[16] = { +static const char *const itype_exc_type[16] = { "Alignment check", "Reserved instruction", "Trap", @@ -75,11 +76,10 @@ static const char * const itype_exc_type[16] = { }; #endif /* CONFIG_DEBUG_EXCEPTIONS */ -#ifdef CONFIG_SOFTWARE_PANIC void software_panic(uint32_t reason, uint32_t info) { - asm volatile ("mov55 $r6, %0" : : "r"(reason)); - asm volatile ("mov55 $r7, %0" : : "r"(info)); + asm volatile("mov55 $r6, %0" : : "r"(reason)); + asm volatile("mov55 $r7, %0" : : "r"(info)); if (in_interrupt_context()) asm("j excep_handler"); else @@ -94,7 +94,7 @@ void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) * If it was called earlier (eg. when saving nds_n8.ipc) calling it * once again won't remove any data */ - struct panic_data * const pdata = get_panic_data_write(); + struct panic_data *const pdata = get_panic_data_write(); uint32_t warning_ipc; uint32_t *regs; @@ -121,7 +121,7 @@ void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) { - struct panic_data * const pdata = panic_get_data(); + struct panic_data *const pdata = panic_get_data(); uint32_t *regs; if (pdata && pdata->struct_version == 2) { @@ -133,20 +133,27 @@ void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) *exception = *reason = *info = 0; } } -#endif /* CONFIG_SOFTWARE_PANIC */ + +/** + * Returns the SP register + */ +uint32_t get_panic_stack_pointer(const struct panic_data *pdata) +{ + return pdata->nds_n8.regs[15]; +} static void print_panic_information(uint32_t *regs, uint32_t itype, - uint32_t ipc, uint32_t ipsw) + uint32_t ipc, uint32_t ipsw) { panic_printf("=== EXCEP: ITYPE=%x ===\n", itype); - panic_printf("R0 %08x R1 %08x R2 %08x R3 %08x\n", - regs[0], regs[1], regs[2], regs[3]); - panic_printf("R4 %08x R5 %08x R6 %08x R7 %08x\n", - regs[4], regs[5], regs[6], regs[7]); - panic_printf("R8 %08x R9 %08x R10 %08x R15 %08x\n", - regs[8], regs[9], regs[10], regs[11]); - panic_printf("FP %08x GP %08x LP %08x SP %08x\n", - regs[12], regs[13], regs[14], regs[15]); + panic_printf("R0 %08x R1 %08x R2 %08x R3 %08x\n", regs[0], regs[1], + regs[2], regs[3]); + panic_printf("R4 %08x R5 %08x R6 %08x R7 %08x\n", regs[4], regs[5], + regs[6], regs[7]); + panic_printf("R8 %08x R9 %08x R10 %08x R15 %08x\n", regs[8], regs[9], + regs[10], regs[11]); + panic_printf("FP %08x GP %08x LP %08x SP %08x\n", regs[12], + regs[13], regs[14], regs[15]); panic_printf("IPC %08x IPSW %05x\n", ipc, ipsw); if ((ipsw & PSW_INTL_MASK) == (2 << PSW_INTL_SHIFT)) { /* 2nd level exception */ @@ -159,18 +166,16 @@ static void print_panic_information(uint32_t *regs, uint32_t itype, #ifdef CONFIG_DEBUG_EXCEPTIONS panic_printf("SWID of ITYPE: %x\n", ((itype >> 16) & 0x7fff)); if (panic_sw_reason_is_valid(regs[SOFT_PANIC_GPR_REASON])) { -#ifdef CONFIG_SOFTWARE_PANIC panic_printf("Software panic reason %s\n", - panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] - - PANIC_SW_BASE)]); + panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] - + PANIC_SW_BASE)]); panic_printf("Software panic info 0x%x\n", - regs[SOFT_PANIC_GPR_INFO]); -#endif + regs[SOFT_PANIC_GPR_INFO]); } else { panic_printf("Exception type: General exception [%s]\n", - itype_exc_type[(itype & 0xf)]); + itype_exc_type[(itype & 0xf)]); panic_printf("Exception is caused by %s\n", - itype_inst[(itype & BIT(4))]); + itype_inst[(itype & BIT(4))]); } #endif } @@ -178,7 +183,7 @@ static void print_panic_information(uint32_t *regs, uint32_t itype, void report_panic(uint32_t *regs, uint32_t itype) { int i; - struct panic_data * const pdata = get_panic_data_write(); + struct panic_data *const pdata = get_panic_data_write(); pdata->magic = PANIC_DATA_MAGIC; pdata->struct_size = CONFIG_PANIC_DATA_SIZE; @@ -194,6 +199,26 @@ void report_panic(uint32_t *regs, uint32_t itype) pdata->nds_n8.ipsw = regs[17]; print_panic_information(regs, itype, regs[16], regs[17]); + + if (IS_ENABLED(CONFIG_SYSTEM_SAFE_MODE)) { + if (start_system_safe_mode() == EC_SUCCESS) { + pdata->flags |= PANIC_DATA_FLAG_SAFE_MODE_STARTED; + /* If not in an interrupt context (e.g. software_panic), + * the next highest priority task will immediately + * execute when the current task is disabled on the + * following line. + */ + task_disable_task(task_get_current()); + /* Current task has been disabled. + * Returning from the exception here should cause the + * highest priority task that wasn't disabled to run. + */ + asm("iret"); + __builtin_unreachable(); + } + pdata->flags |= PANIC_DATA_FLAG_SAFE_MODE_FAIL_PRECONDITIONS; + } + panic_reboot(); } diff --git a/core/nds32/switch.S b/core/nds32/switch.S index 8696ef5f00..e7a8584ce5 100644 --- a/core/nds32/switch.S +++ b/core/nds32/switch.S @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,7 +8,7 @@ #include "config.h" #include "cpu.h" -.text +.section .ram_code /** * Task context switching @@ -73,6 +73,7 @@ __switch_task: /* restore PC and PSW */ iret +.text /** * Start the task scheduling. * @@ -81,6 +82,11 @@ __switch_task: */ .global __task_start __task_start: + /* + * Disable global interrupt here to ensure below sequence won't be + * broken. The "iret" instruction of ISR will enable GIE again. + */ + setgie.d /* area used as thread stack for the first switch */ la $r3, scratchpad @@ -100,4 +106,3 @@ __task_start: /* we should never return here: set code to EC_ERROR_UNKNOWN */ movi55 $r0, 0x1 ret5 $lp - diff --git a/core/nds32/task.c b/core/nds32/task.c index 9c3d6357ac..bbfc5f79c7 100644 --- a/core/nds32/task.c +++ b/core/nds32/task.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,6 +6,7 @@ /* Task scheduling / events module for Chrome EC operating system */ #include "atomic.h" +#include "builtin/assert.h" #include "common.h" #include "console.h" #include "cpu.h" @@ -13,6 +14,7 @@ #include "intc.h" #include "irq_chip.h" #include "link_defs.h" +#include "panic.h" #include "registers.h" #include "task.h" #include "timer.h" @@ -24,10 +26,10 @@ typedef union { * Note that sp must be the first element in the task struct * for __switchto() to work. */ - uint32_t sp; /* Saved stack pointer for context switch */ - uint32_t events; /* Bitmaps of received events */ - uint64_t runtime; /* Time spent in task */ - uint32_t *stack; /* Start of stack */ + uint32_t sp; /* Saved stack pointer for context switch */ + atomic_t events; /* Bitmaps of received events */ + uint64_t runtime; /* Time spent in task */ + uint32_t *stack; /* Start of stack */ }; } task_; @@ -42,11 +44,9 @@ CONFIG_TEST_TASK_LIST #undef TASK /* Task names for easier debugging */ -#define TASK(n, r, d, s) #n, -static const char * const task_names[] = { - "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST +#define TASK(n, r, d, s) #n, +static const char *const task_names[] = { + "<< idle >>", CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST }; #undef TASK @@ -54,12 +54,12 @@ static const char * const task_names[] = { static int task_will_switch; static uint32_t exc_sub_time; static uint64_t task_start_time; /* Time task scheduling started */ -static uint32_t exc_start_time; /* Time of task->exception transition */ -static uint32_t exc_end_time; /* Time of exception->task transition */ -static uint64_t exc_total_time; /* Total time in exceptions */ -static uint32_t svc_calls; /* Number of service calls */ -static uint32_t task_switches; /* Number of times active task changed */ -static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ +static uint32_t exc_start_time; /* Time of task->exception transition */ +static uint32_t exc_end_time; /* Time of exception->task transition */ +static uint64_t exc_total_time; /* Total time in exceptions */ +static uint32_t svc_calls; /* Number of service calls */ +static uint32_t task_switches; /* Number of times active task changed */ +static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ #endif extern int __task_start(void); @@ -80,7 +80,7 @@ void __idle(void) /* doze mode */ IT83XX_ECPM_PLLCTRL = EC_PLL_DOZE; #endif - asm volatile ("dsb"); + asm volatile("dsb"); /* * Wait for the next irq event. This stops the CPU clock * (sleep / deep sleep, depending on chip config). @@ -100,42 +100,36 @@ static void task_exit_trap(void) } /* Startup parameters for all tasks. */ -#define TASK(n, r, d, s) { \ - .r0 = (uint32_t)d, \ - .pc = (uint32_t)r, \ - .stack_size = s, \ -}, +#define TASK(n, r, d, s) \ + { \ + .r0 = (uint32_t)d, \ + .pc = (uint32_t)r, \ + .stack_size = s, \ + }, static const struct { uint32_t r0; uint32_t pc; uint16_t stack_size; -} tasks_init[] = { - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -}; +} tasks_init[] = { TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST }; #undef TASK /* Contexts for all tasks */ static task_ tasks[TASK_ID_COUNT]; /* Validity checks about static task invariants */ -BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned) * 8); +BUILD_ASSERT(TASK_ID_COUNT <= sizeof(unsigned int) * 8); BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); - /* Stacks for all tasks */ -#define TASK(n, r, d, s) + s -uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -] __aligned(8); +#define TASK(n, r, d, s) +s +uint8_t task_stacks[0 TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST] __aligned(8); #undef TASK /* Reserve space to discard context on first context switch. */ -uint32_t scratchpad[TASK_SCRATCHPAD_SIZE] __attribute__ - ((section(".bss.task_scratchpad"))); +uint32_t scratchpad[TASK_SCRATCHPAD_SIZE] + __attribute__((section(".bss.task_scratchpad"))); task_ *current_task = (task_ *)scratchpad; @@ -159,15 +153,15 @@ int need_resched; * can do their init within a task switching context. The hooks task will then * make a call to enable all tasks. */ -static uint32_t tasks_ready = BIT(TASK_ID_HOOKS); +static atomic_t tasks_ready = BIT(TASK_ID_HOOKS); /* * Initially allow only the HOOKS and IDLE task to run, regardless of ready * status, in order for HOOK_INIT to complete before other tasks. * task_enable_all_tasks() will open the flood gates. */ -static uint32_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); +static atomic_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); -int start_called; /* Has task swapping started */ +int start_called; /* Has task swapping started */ /* interrupt number of sw interrupt */ static int sw_int_num; @@ -213,18 +207,28 @@ void __ram_code interrupt_disable(void) { /* Mask all interrupts, only keep division by zero exception */ uint32_t val = BIT(30); - asm volatile ("mtsr %0, $INT_MASK" : : "r"(val)); - asm volatile ("dsb"); + asm volatile("mtsr %0, $INT_MASK" : : "r"(val)); + asm volatile("dsb"); } void __ram_code interrupt_enable(void) { /* Enable HW2 ~ HW15 and division by zero exception interrupts */ uint32_t val = (BIT(30) | 0xFFFC); - asm volatile ("mtsr %0, $INT_MASK" : : "r"(val)); + asm volatile("mtsr %0, $INT_MASK" : : "r"(val)); } -inline int in_interrupt_context(void) +inline bool is_interrupt_enabled(void) +{ + uint32_t val = 0; + + asm volatile("mfsr %0, $INT_MASK" : "=r"(val)); + + /* Interrupts are enabled if any of HW2 ~ HW15 is enabled */ + return val & 0xFFFC; +} + +inline bool in_interrupt_context(void) { /* check INTL (Interrupt Stack Level) bits */ return get_psw() & PSW_INTL_MASK; @@ -236,10 +240,11 @@ task_id_t task_get_current(void) /* If we haven't done a context switch then our task ID isn't valid */ ASSERT(current_task != (task_ *)scratchpad); #endif - return current_task - tasks; + /* return invalid task id if task scheduling is not yet start */ + return start_called ? (current_task - tasks) : TASK_ID_INVALID; } -uint32_t *task_get_event_bitmap(task_id_t tskid) +atomic_t *task_get_event_bitmap(task_id_t tskid) { task_ *tsk = __task_id_to_ptr(tskid); return &tsk->events; @@ -256,7 +261,7 @@ int task_start_called(void) * Also includes emulation of software triggering interrupt vector */ void __ram_code __keep syscall_handler(int desched, task_id_t resched, - int swirq) + int swirq) { /* are we emulating an interrupt ? */ if (swirq) { @@ -296,7 +301,7 @@ task_ *next_sched_task(void) #ifdef CONFIG_TASK_PROFILING if (current_task != new_task) { current_task->runtime += - (exc_start_time - exc_end_time - exc_sub_time); + (exc_start_time - exc_end_time - exc_sub_time); task_will_switch = 1; } #endif @@ -304,11 +309,11 @@ task_ *next_sched_task(void) #ifdef CONFIG_DEBUG_STACK_OVERFLOW if (*current_task->stack != STACK_UNUSED_VALUE) { int i = task_get_current(); - - panic_printf("\n\nStack overflow in %s task!\n", task_names[i]); -#ifdef CONFIG_SOFTWARE_PANIC - software_panic(PANIC_SW_STACK_OVERFLOW, i); -#endif + if (task_enabled(i)) { + panic_printf("\n\nStack overflow in %s task!\n", + task_names[i]); + software_panic(PANIC_SW_STACK_OVERFLOW, i); + } } #endif @@ -337,7 +342,7 @@ volatile int ec_int; void __ram_code start_irq_handler(void) { /* save r0, r1, and r2 for syscall */ - asm volatile ("smw.adm $r0, [$sp], $r2, 0"); + asm volatile("smw.adm $r0, [$sp], $r2, 0"); /* If this is a SW interrupt */ if (get_itype() & 8) ec_int = sw_int_num; @@ -358,7 +363,7 @@ void __ram_code start_irq_handler(void) irq_dist[ec_int]++; #endif /* restore r0, r1, and r2 */ - asm volatile ("lmw.bim $r0, [$sp], $r2, 0"); + asm volatile("lmw.bim $r0, [$sp], $r2, 0"); } void end_irq_handler(void) @@ -369,7 +374,7 @@ void end_irq_handler(void) * save r0 and fp (fp for restore r0-r5, r15, fp, lp and sp * while interrupt exit. */ - asm volatile ("smw.adm $r0, [$sp], $r0, 8"); + asm volatile("smw.adm $r0, [$sp], $r0, 8"); t = get_time().le.lo; p = t - exc_start_time; @@ -384,7 +389,7 @@ void end_irq_handler(void) } /* restore r0 and fp */ - asm volatile ("lmw.bim $r0, [$sp], $r0, 8"); + asm volatile("lmw.bim $r0, [$sp], $r0, 8"); #endif } @@ -403,7 +408,7 @@ static uint32_t __ram_code __wait_evt(int timeout_us, task_id_t resched) ret = timer_arm(deadline, me); ASSERT(ret == EC_SUCCESS); } - while (!(evt = deprecated_atomic_read_clear(&tsk->events))) { + while (!(evt = atomic_clear(&tsk->events))) { /* Remove ourself and get the next task in the scheduler */ __schedule(1, resched, 0); resched = TASK_ID_IDLE; @@ -411,33 +416,28 @@ static uint32_t __ram_code __wait_evt(int timeout_us, task_id_t resched) if (timeout_us > 0) { timer_cancel(me); /* Ensure timer event is clear, we no longer care about it */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); + atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); } return evt; } -uint32_t __ram_code task_set_event(task_id_t tskid, uint32_t event, int wait) +void __ram_code task_set_event(task_id_t tskid, uint32_t event) { task_ *receiver = __task_id_to_ptr(tskid); ASSERT(receiver); /* Set the event bit in the receiver message bitmap */ - deprecated_atomic_or(&receiver->events, event); + atomic_or(&receiver->events, event); /* Re-schedule if priorities have changed */ if (in_interrupt_context()) { /* The receiver might run again */ - deprecated_atomic_or(&tasks_ready, 1 << tskid); + atomic_or(&tasks_ready, 1 << tskid); if (start_called) need_resched = 1; } else { - if (wait) - return __wait_evt(-1, tskid); - else - __schedule(0, tskid, 0); + __schedule(0, tskid, 0); } - - return 0; } uint32_t __ram_code task_wait_event(int timeout_us) @@ -468,8 +468,7 @@ uint32_t __ram_code task_wait_event_mask(uint32_t event_mask, int timeout_us) /* Re-post any other events collected */ if (events & ~event_mask) - deprecated_atomic_or(¤t_task->events, - events & ~event_mask); + atomic_or(¤t_task->events, events & ~event_mask); return events & event_mask; } @@ -478,37 +477,36 @@ uint32_t __ram_code read_clear_int_mask(void) { uint32_t int_mask, int_dis = BIT(30); - asm volatile( - "mfsr %0, $INT_MASK\n\t" - "mtsr %1, $INT_MASK\n\t" - "dsb\n\t" - : "=&r"(int_mask) - : "r"(int_dis)); + asm volatile("mfsr %0, $INT_MASK\n\t" + "mtsr %1, $INT_MASK\n\t" + "dsb\n\t" + : "=&r"(int_mask) + : "r"(int_dis)); return int_mask; } void __ram_code set_int_mask(uint32_t val) { - asm volatile ("mtsr %0, $INT_MASK" : : "r"(val)); + asm volatile("mtsr %0, $INT_MASK" : : "r"(val)); } static void set_int_priority(uint32_t val) { - asm volatile ("mtsr %0, $INT_PRI" : : "r"(val)); + asm volatile("mtsr %0, $INT_PRI" : : "r"(val)); } uint32_t get_int_ctrl(void) { uint32_t ret; - asm volatile ("mfsr %0, $INT_CTRL" : "=r"(ret)); + asm volatile("mfsr %0, $INT_CTRL" : "=r"(ret)); return ret; } void set_int_ctrl(uint32_t val) { - asm volatile ("mtsr %0, $INT_CTRL" : : "r"(val)); + asm volatile("mtsr %0, $INT_CTRL" : : "r"(val)); } void task_enable_all_tasks(void) @@ -521,12 +519,17 @@ void task_enable_all_tasks(void) void task_enable_task(task_id_t tskid) { - deprecated_atomic_or(&tasks_enabled, BIT(tskid)); + atomic_or(&tasks_enabled, BIT(tskid)); +} + +bool task_enabled(task_id_t tskid) +{ + return tasks_enabled & BIT(tskid); } void task_disable_task(task_id_t tskid) { - deprecated_atomic_clear_bits(&tasks_enabled, BIT(tskid)); + atomic_clear_bits(&tasks_enabled, BIT(tskid)); if (!in_interrupt_context() && tskid == task_get_current()) __schedule(0, 0, 0); @@ -594,7 +597,7 @@ static void ivic_init_irqs(void) for (i = 0; i < exc_calls; i++) { uint8_t irq = __irqprio[i].irq; uint8_t prio = __irqprio[i].priority; - all_priorities |= (prio & 0x3) << (irq * 2); + all_priorities |= (prio & 0x3) << (irq * 2); } set_int_priority(all_priorities); } @@ -631,20 +634,29 @@ void __ram_code mutex_unlock(struct mutex *mtx) uint32_t waiters; task_ *tsk = current_task; - waiters = mtx->waiters; - /* give back the lock */ - mtx->lock = 0; + /* + * we need to read to waiters after giving the lock back + * otherwise we might miss a waiter between the two calls. + * + * prevent compiler reordering + */ + asm volatile( + /* give back the lock */ + "movi %0, #0\n\t" + "lwi %1, [%2]\n\t" + : "=&r"(mtx->lock), "=&r"(waiters) + : "r"(&mtx->waiters)); while (waiters) { task_id_t id = __fls(waiters); waiters &= ~BIT(id); /* Somebody is waiting on the mutex */ - task_set_event(id, TASK_EVENT_MUTEX, 0); + task_set_event(id, TASK_EVENT_MUTEX); } /* Ensure no event is remaining from mutex wake-up */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); + atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); } void task_print_list(void) @@ -654,7 +666,7 @@ void task_print_list(void) ccputs("Task Ready Name Events Time (s) StkUsed\n"); for (i = 0; i < TASK_ID_COUNT; i++) { - char is_ready = (tasks_ready & (1< IRAM + __preserved_logs_size = __preserved_logs_end - __preserved_logs_start; +#ifdef CONFIG_IT83XX_HARD_RESET_BY_GPG1 + ASSERT(__preserved_logs_size <= CHIP_FLASH_PRESERVE_LOGS_SIZE, + "Not enough flash space to save EC logs.") +#endif +#endif /* CONFIG_PRESERVE_LOGS */ + .data : { . = ALIGN(4); __data_start = .; @@ -287,7 +329,6 @@ SECTIONS . = ALIGN(4); /* Rest of .bss takes care of its own alignment */ *(.bss) - *(.bss.slow) /* * Reserve space for deferred function firing times. @@ -317,23 +358,38 @@ SECTIONS (__shared_mem_buf + CONFIG_SHAREDMEM_MINIMUM_SIZE); /* - * __flash_used is used in flash free calculations by the makefile. + * __flash_used and __flash_size is used in flash free calculations by + * the makefile. Note the difference between __flash_size and + * __config_flash_size. __flash_size is the flash size for the given + * image (RW, RO, etc.), while __config_flash_size is the *total* + * flash size. * __image_size is stored in the struct image_data header and used - * in hash calcuations. + * in hash calculations. */ #if defined(CHIP_FAMILY_IT8XXX2) __flash_used = LOADADDR(.data) + SIZEOF(.data) + \ CHIP_ILM_BASE - FW_OFF(SECTION); #else __flash_used = LOADADDR(.data) + SIZEOF(.data) - FW_OFF(SECTION); +#endif +#if defined(CONFIG_FLASH_PHYSICAL) + __flash_size = LENGTH(FLASH); +#else + __flash_size = LENGTH(IROM); #endif __image_size = __flash_used; -#ifdef CONFIG_FLASH +#if defined(SECTION_IS_RW) && (CONFIG_FLASH_WRITE_SIZE > 0) + /* Alignment is needed by flash_command_write() for RW update. */ + ASSERT(__image_size % CONFIG_FLASH_WRITE_SIZE == 0, + "Error: RW image is not aligned to CONFIG_FLASH_WRITE_SIZE") +#endif + +#ifdef CONFIG_FLASH_CROS /* * These linker labels are just for analysis and not used in the code. */ - __config_flash_size = CONFIG_FLASH_SIZE; + __config_flash_size = CONFIG_FLASH_SIZE_BYTES; __config_ro_size = CONFIG_RO_SIZE; __config_ec_protected_storage_size = CONFIG_EC_PROTECTED_STORAGE_SIZE; __config_rw_size = CONFIG_RW_SIZE; @@ -341,13 +397,13 @@ SECTIONS #endif #if defined(CHIP_FAMILY_IT8XXX2) -#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_SLAVE) +#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_PERIPHERAL) .h2ram (NOLOAD) : { . += CONFIG_H2RAM_HOST_LPC_IO_BASE; *(.h2ram.pool.hostcmd) . = ALIGN(256); *(.h2ram.pool.acpiec) -#ifdef CONFIG_I2C_SLAVE +#ifdef CONFIG_I2C_PERIPHERAL . = ALIGN(256); *(.h2ram.pool.i2cslv) #endif @@ -359,7 +415,67 @@ SECTIONS #endif #endif /* CHIP_FAMILY_IT8XXX2 */ -#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH)) +#ifdef CONFIG_DRAM_BASE + /* + * Sections in DRAM region are constructed as like in non-DRAM regions: + * .dram.data LMA is for preserving initialized data across resets. + * The only difference is that they are all in the DRAM region: + * .dram.text | LOAD + * .dram.rodata | LOAD + * .dram.data LMA | LOAD + * .dram.data VMA | + * .dram.bss | NOLOAD + */ + + .dram.text : { + . = ALIGN(4); + KEEP(*(SORT(.dram.text.keep.*))) + *(SORT(.dram.text.*)) + . = ALIGN(4); + } > DRAM + + .dram.rodata : { + . = ALIGN(4); + KEEP(*(SORT(.dram.rodata.keep.*))) + *(SORT(.dram.rodata.*)) + . = ALIGN(4); + } > DRAM + + __dram_data_lma_start = ADDR(.dram.rodata) + SIZEOF(.dram.rodata); + + /* Place .dram.data LMA in between .dram.rodata and .dram.data VMA. */ + .dram.data __dram_data_lma_start + + (__dram_data_end - __dram_data_start) : { + . = ALIGN(4); + __dram_data_start = .; + *(.dram.data*) + . = ALIGN(4); + __dram_data_end = .; + + /* + * Normally, '> DRAM AT > DRAM' should be the same as '> DRAM', + * and they will be at the same address. However, if the address + * of VMA specified, LMA and VMA might have different addresses: + * '> DRAM' places VMA at the address where section declaration + * specified. + * 'AT > DRAM' places LMA at the location counter's address. + */ + } > DRAM AT > DRAM + + /* + * ld assigns correct attribute for .bss, but not for other .*.bss, + * we need an explicltly NOLOAD. + */ + .dram.bss(NOLOAD) : { + . = ALIGN(4); + __dram_bss_start = .; + *(SORT(.dram.bss*)) + . = ALIGN(4); + __dram_bss_end = .; + } > DRAM +#endif /* CONFIG_DRAM_BASE */ + +#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH_CROS)) /DISCARD/ : { *(.google) } #endif diff --git a/core/riscv-rv32i/include/fpu.h b/core/riscv-rv32i/include/fpu.h new file mode 100644 index 0000000000..da48139d1c --- /dev/null +++ b/core/riscv-rv32i/include/fpu.h @@ -0,0 +1,13 @@ +/* Copyright 2020 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Math utility functions for RISC-V */ + +#ifndef __CROS_EC_FPU_H +#define __CROS_EC_FPU_H + +float sqrtf(float x); + +#endif /* __CROS_EC_FPU_H */ diff --git a/core/riscv-rv32i/include/math.h b/core/riscv-rv32i/include/math.h deleted file mode 100644 index f17144762a..0000000000 --- a/core/riscv-rv32i/include/math.h +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Math utility functions for RISC-V */ - -#ifndef __CROS_EC_MATH_H -#define __CROS_EC_MATH_H - -float sqrtf(float x); - -#endif /* __CROS_EC_MATH_H */ diff --git a/core/riscv-rv32i/init.S b/core/riscv-rv32i/init.S index 0bc99052da..6231ad94c0 100644 --- a/core/riscv-rv32i/init.S +++ b/core/riscv-rv32i/init.S @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -29,6 +29,26 @@ __startup: __irq: j __irq_isr /* interrupts / exceptions */ +.align 2 +__ec_intc: + vector irq_0 /* INT GROUP 0 */ + vector irq_1 /* INT GROUP 1 */ + vector irq_2 /* INT GROUP 2 */ + vector irq_3 /* INT GROUP 3 */ + vector irq_4 /* INT GROUP 4 */ + vector irq_5 /* INT GROUP 5 */ + vector irq_6 /* INT GROUP 6 */ + vector irq_7 /* INT GROUP 7 */ + vector irq_8 /* INT GROUP 8 */ + vector irq_9 /* INT GROUP 9 */ + vector irq_10 /* INT GROUP 10 */ + vector irq_11 /* INT GROUP 11 */ + vector irq_12 /* INT GROUP 12 */ + vector irq_13 /* INT GROUP 13 */ + vector irq_14 /* INT GROUP 14 */ + vector irq_15 /* INT GROUP 15 */ + vector syscall /* system call (emulate INT GROUP 16) */ + #ifdef CHIP_FAMILY_IT8XXX2 /* * E-flash signature used to enable specific function after power-on reset. @@ -55,7 +75,7 @@ __irq: .global eflash_sig eflash_sig: .byte 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5 -#ifdef CONFIG_HOSTCMD_ESPI +#ifdef CONFIG_HOST_INTERFACE_ESPI .byte 0xA4 /* eSPI */ #else .byte 0xA5 /* LPC */ @@ -65,27 +85,9 @@ eflash_sig: /* flags: internal oscillator + implicit location */ #endif /* CHIP_FAMILY_IT8XXX2 */ -.align 2 -__ec_intc: - vector irq_0 /* INT GROUP 0 */ - vector irq_1 /* INT GROUP 1 */ - vector irq_2 /* INT GROUP 2 */ - vector irq_3 /* INT GROUP 3 */ - vector irq_4 /* INT GROUP 4 */ - vector irq_5 /* INT GROUP 5 */ - vector irq_6 /* INT GROUP 6 */ - vector irq_7 /* INT GROUP 7 */ - vector irq_8 /* INT GROUP 8 */ - vector irq_9 /* INT GROUP 9 */ - vector irq_10 /* INT GROUP 10 */ - vector irq_11 /* INT GROUP 11 */ - vector irq_12 /* INT GROUP 12 */ - vector irq_13 /* INT GROUP 13 */ - vector irq_14 /* INT GROUP 14 */ - vector irq_15 /* INT GROUP 15 */ - vector syscall /* system call (emulate INT GROUP 16) */ .align 2 +.section .text.vectirq __irq_isr: /* save t2 to scratch register */ csrw mscratch, t2 @@ -165,6 +167,10 @@ __irq_isr: bltu sp, t0, __sp_16byte_aligned mv sp, t0 __sp_16byte_aligned: + /* in_interrupt = 1 */ + li t0, 1 + la t1, in_interrupt + sb t0, 0(t1) /* * This ensures sp is 16-byte aligned. This only applies to when there * is an interrupt before tasks start. Otherwise stack_end is already @@ -183,9 +189,19 @@ __sp_16byte_aligned: /* This interrupt is unhandled */ j unhandled_interrupt __irq_handler: + /* save a0, a1, and a2 for syscall */ + addi sp, sp, -4*3 + sw a0, 0(sp) + sw a1, 1*4(sp) + sw a2, 2*4(sp) jal start_irq_handler - /* t0 = -1 if it cannot find the corresponding interrupt source */ - bltz t0, unhandled_interrupt + /* a0 = -1 if it cannot find the corresponding interrupt source */ + bltz a0, unhandled_interrupt + /* restore a0, a1, and a2 */ + lw a0, 0(sp) + lw a1, 1*4(sp) + lw a2, 2*4(sp) + addi sp, sp, 4*3 /* get EC interrupt group 0-15 or 16:ecall */ la t0, ec_int_group /* get corresponding isr */ @@ -202,6 +218,9 @@ __irq_handler: .global __irq_exit __irq_exit: jal end_irq_handler + /* in_interrupt = 0 */ + la t0, in_interrupt + sb zero, 0(t0) /* restore sp from scratch register */ csrr sp, mscratch #ifdef CONFIG_FPU @@ -332,10 +351,11 @@ unhandled_ec_irq: unhandled_interrupt: li tp, 0xBAD0 __unhandled_irq: - slli tp, tp, 8 - csrr t0, mcause + slli tp, tp, 16 + la t0, ec_int + lw t0, 0(t0) add tp, tp, t0 - j excep_handler /* display exception with TP 80bad[0|1] */ + j excep_handler /* display exception with TP bad[0|1] */ .global excep_handler excep_handler: diff --git a/core/riscv-rv32i/irq_chip.h b/core/riscv-rv32i/irq_chip.h index 45cabf346e..b45a754f45 100644 --- a/core/riscv-rv32i/irq_chip.h +++ b/core/riscv-rv32i/irq_chip.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * diff --git a/core/riscv-rv32i/irq_handler.h b/core/riscv-rv32i/irq_handler.h index 8d26ae6474..b980e8e0bc 100644 --- a/core/riscv-rv32i/irq_handler.h +++ b/core/riscv-rv32i/irq_handler.h @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -20,11 +20,12 @@ * Macro to connect the interrupt handler "routine" to the irq number "irq" and * ensure it is enabled in the interrupt controller with the right priority. */ -#define DECLARE_IRQ(irq, routine, priority) \ - void IRQ_HANDLER(CPU_INT(irq))(void) \ - __attribute__ ((alias(STRINGIFY(routine)))); \ - const struct irq_priority __keep IRQ_PRIORITY(CPU_INT(irq)) \ - __attribute__((section(".rodata.irqprio"))) \ - = {CPU_INT(irq), priority} +#define DECLARE_IRQ(irq, routine, priority) \ + static void __keep routine(void); \ + void IRQ_HANDLER(CPU_INT(irq))(void) \ + __attribute__((alias(STRINGIFY(routine)))); \ + const struct irq_priority __keep IRQ_PRIORITY(CPU_INT(irq)) \ + __attribute__((section(".rodata.irqprio"))) = { CPU_INT(irq), \ + priority } -#endif /* __CROS_EC_IRQ_HANDLER_H */ +#endif /* __CROS_EC_IRQ_HANDLER_H */ diff --git a/core/riscv-rv32i/math.c b/core/riscv-rv32i/math.c index 591a67eb8f..425814f185 100644 --- a/core/riscv-rv32i/math.c +++ b/core/riscv-rv32i/math.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,10 +9,7 @@ /* Single precision floating point square root. */ float sqrtf(float x) { - asm volatile ( - "fsqrt.s %0, %1" - : "=f" (x) - : "f" (x)); + asm volatile("fsqrt.s %0, %1" : "=f"(x) : "f"(x)); return x; } diff --git a/core/riscv-rv32i/panic.c b/core/riscv-rv32i/panic.c index 3d8cec1b06..0ea86840f9 100644 --- a/core/riscv-rv32i/panic.c +++ b/core/riscv-rv32i/panic.c @@ -1,8 +1,9 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "console.h" #include "cpu.h" #include "panic.h" #include "task.h" @@ -12,7 +13,7 @@ /** * bit[3-0] @ mcause, general exception type information. */ -static const char * const exc_type[16] = { +static const char *const exc_type[16] = { "Instruction address misaligned", "Instruction access fault", "Illegal instruction", @@ -33,16 +34,15 @@ static const char * const exc_type[16] = { }; #endif /* CONFIG_DEBUG_EXCEPTIONS */ -#ifdef CONFIG_SOFTWARE_PANIC /* General purpose register (s0) for saving software panic reason */ #define SOFT_PANIC_GPR_REASON 11 /* General purpose register (s1) for saving software panic information */ -#define SOFT_PANIC_GPR_INFO 10 +#define SOFT_PANIC_GPR_INFO 10 void software_panic(uint32_t reason, uint32_t info) { - asm volatile ("mv s0, %0" : : "r"(reason)); - asm volatile ("mv s1, %0" : : "r"(info)); + asm volatile("mv s0, %0" : : "r"(reason) : "s0"); + asm volatile("mv s1, %0" : : "r"(info) : "s1"); if (in_interrupt_context()) asm("j excep_handler"); else @@ -57,7 +57,7 @@ void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) * If it was called earlier (eg. when saving riscv.mepc) calling it * once again won't remove any data */ - struct panic_data * const pdata = get_panic_data_write(); + struct panic_data *const pdata = get_panic_data_write(); uint32_t warning_mepc; uint32_t *regs; @@ -84,7 +84,7 @@ void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) { - struct panic_data * const pdata = panic_get_data(); + struct panic_data *const pdata = panic_get_data(); uint32_t *regs; if (pdata && pdata->struct_version == 2) { @@ -96,38 +96,35 @@ void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) *exception = *reason = *info = 0; } } -#endif /* CONFIG_SOFTWARE_PANIC */ static void print_panic_information(uint32_t *regs, uint32_t mcause, - uint32_t mepc) + uint32_t mepc) { panic_printf("=== EXCEPTION: MCAUSE=%x ===\n", mcause); - panic_printf("S11 %08x S10 %08x S9 %08x S8 %08x\n", - regs[0], regs[1], regs[2], regs[3]); - panic_printf("S7 %08x S6 %08x S5 %08x S4 %08x\n", - regs[4], regs[5], regs[6], regs[7]); - panic_printf("S3 %08x S2 %08x S1 %08x S0 %08x\n", - regs[8], regs[9], regs[10], regs[11]); - panic_printf("T6 %08x T5 %08x T4 %08x T3 %08x\n", - regs[12], regs[13], regs[14], regs[15]); - panic_printf("T2 %08x T1 %08x T0 %08x A7 %08x\n", - regs[16], regs[17], regs[18], regs[19]); - panic_printf("A6 %08x A5 %08x A4 %08x A3 %08x\n", - regs[20], regs[21], regs[22], regs[23]); - panic_printf("A2 %08x A1 %08x A0 %08x TP %08x\n", - regs[24], regs[25], regs[26], regs[27]); - panic_printf("GP %08x RA %08x SP %08x MEPC %08x\n", - regs[28], regs[29], regs[30], mepc); + panic_printf("S11 %08x S10 %08x S9 %08x S8 %08x\n", regs[0], + regs[1], regs[2], regs[3]); + panic_printf("S7 %08x S6 %08x S5 %08x S4 %08x\n", regs[4], + regs[5], regs[6], regs[7]); + panic_printf("S3 %08x S2 %08x S1 %08x S0 %08x\n", regs[8], + regs[9], regs[10], regs[11]); + panic_printf("T6 %08x T5 %08x T4 %08x T3 %08x\n", regs[12], + regs[13], regs[14], regs[15]); + panic_printf("T2 %08x T1 %08x T0 %08x A7 %08x\n", regs[16], + regs[17], regs[18], regs[19]); + panic_printf("A6 %08x A5 %08x A4 %08x A3 %08x\n", regs[20], + regs[21], regs[22], regs[23]); + panic_printf("A2 %08x A1 %08x A0 %08x TP %08x\n", regs[24], + regs[25], regs[26], regs[27]); + panic_printf("GP %08x RA %08x SP %08x MEPC %08x\n", regs[28], + regs[29], regs[30], mepc); #ifdef CONFIG_DEBUG_EXCEPTIONS if ((regs[SOFT_PANIC_GPR_REASON] & 0xfffffff0) == PANIC_SW_BASE) { -#ifdef CONFIG_SOFTWARE_PANIC panic_printf("Software panic reason: %s\n", - panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] - - PANIC_SW_BASE)]); + panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] - + PANIC_SW_BASE)]); panic_printf("Software panic info: %d\n", - regs[SOFT_PANIC_GPR_INFO]); -#endif + regs[SOFT_PANIC_GPR_INFO]); } else { panic_printf("Exception type: %s\n", exc_type[(mcause & 0xf)]); } @@ -137,7 +134,7 @@ static void print_panic_information(uint32_t *regs, uint32_t mcause, void report_panic(uint32_t *regs) { uint32_t i, mcause, mepc; - struct panic_data * const pdata = get_panic_data_write(); + struct panic_data *const pdata = get_panic_data_write(); mepc = get_mepc(); mcause = get_mcause(); @@ -167,3 +164,51 @@ void panic_data_print(const struct panic_data *pdata) mepc = pdata->riscv.mepc; print_panic_information(regs, mcause, mepc); } + +#ifdef CONFIG_PANIC_CONSOLE_OUTPUT +static void ccprint_panic_information(uint32_t *regs, uint32_t mcause, + uint32_t mepc) +{ + ccprintf("=== EXCEPTION: MCAUSE=%x ===\n", mcause); + ccprintf("S11 %08x S10 %08x S9 %08x S8 %08x\n", regs[0], regs[1], + regs[2], regs[3]); + ccprintf("S7 %08x S6 %08x S5 %08x S4 %08x\n", regs[4], regs[5], + regs[6], regs[7]); + ccprintf("S3 %08x S2 %08x S1 %08x S0 %08x\n", regs[8], regs[9], + regs[10], regs[11]); + ccprintf("T6 %08x T5 %08x T4 %08x T3 %08x\n", regs[12], regs[13], + regs[14], regs[15]); + ccprintf("T2 %08x T1 %08x T0 %08x A7 %08x\n", regs[16], regs[17], + regs[18], regs[19]); + cflush(); + + ccprintf("A6 %08x A5 %08x A4 %08x A3 %08x\n", regs[20], regs[21], + regs[22], regs[23]); + ccprintf("A2 %08x A1 %08x A0 %08x TP %08x\n", regs[24], regs[25], + regs[26], regs[27]); + ccprintf("GP %08x RA %08x SP %08x MEPC %08x\n", regs[28], regs[29], + regs[30], mepc); + +#ifdef CONFIG_DEBUG_EXCEPTIONS + if ((regs[SOFT_PANIC_GPR_REASON] & 0xfffffff0) == PANIC_SW_BASE) { + ccprintf("Software panic reason: %s\n", + panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] - + PANIC_SW_BASE)]); + ccprintf("Software panic info: %d\n", + regs[SOFT_PANIC_GPR_INFO]); + } else { + ccprintf("Exception type: %s\n", exc_type[(mcause & 0xf)]); + } +#endif /* CONFIG_DEBUG_EXCEPTIONS */ + cflush(); +} +void panic_data_ccprint(const struct panic_data *pdata) +{ + uint32_t *regs, mcause, mepc; + + regs = (uint32_t *)pdata->riscv.regs; + mcause = pdata->riscv.mcause; + mepc = pdata->riscv.mepc; + ccprint_panic_information(regs, mcause, mepc); +} +#endif /* CONFIG_PANIC_CONSOLE_OUTPUT */ diff --git a/core/riscv-rv32i/switch.S b/core/riscv-rv32i/switch.S index d6c00b8591..f8b88f9235 100644 --- a/core/riscv-rv32i/switch.S +++ b/core/riscv-rv32i/switch.S @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -8,7 +8,9 @@ #include "config.h" #include "cpu.h" -.text +#ifdef __RAM_CODE_ILM0_SECTION_NAME +.section __RAM_CODE_ILM0_SECTION_NAME +#endif /** * Task context switching @@ -142,6 +144,7 @@ __switch_task: add sp, t3, zero j __irq_exit +.text /** * Start the task scheduling. */ diff --git a/core/riscv-rv32i/task.c b/core/riscv-rv32i/task.c index ecd8d72382..48244bc1b2 100644 --- a/core/riscv-rv32i/task.c +++ b/core/riscv-rv32i/task.c @@ -1,4 +1,4 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -6,10 +6,12 @@ /* Task scheduling / events module for Chrome EC operating system */ #include "atomic.h" +#include "builtin/assert.h" #include "console.h" #include "cpu.h" #include "irq_chip.h" #include "link_defs.h" +#include "panic.h" #include "task.h" #include "timer.h" #include "util.h" @@ -19,10 +21,10 @@ typedef struct { * Note that sp must be the first element in the task struct * for __switchto() to work. */ - uint32_t sp; /* Saved stack pointer for context switch */ - uint32_t events; /* Bitmaps of received events */ - uint64_t runtime; /* Time spent in task */ - uint32_t *stack; /* Start of stack */ + uint32_t sp; /* Saved stack pointer for context switch */ + atomic_t events; /* Bitmaps of received events */ + uint64_t runtime; /* Time spent in task */ + uint32_t *stack; /* Start of stack */ } task_; /* Value to store in unused stack */ @@ -36,11 +38,9 @@ CONFIG_TEST_TASK_LIST #undef TASK /* Task names for easier debugging */ -#define TASK(n, r, d, s) #n, -static const char * const task_names[] = { - "<< idle >>", - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST +#define TASK(n, r, d, s) #n, +static const char *const task_names[] = { + "<< idle >>", CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST }; #undef TASK @@ -48,12 +48,12 @@ static const char * const task_names[] = { static int task_will_switch; static uint32_t exc_sub_time; static uint64_t task_start_time; /* Time task scheduling started */ -static uint32_t exc_start_time; /* Time of task->exception transition */ -static uint32_t exc_end_time; /* Time of exception->task transition */ -static uint64_t exc_total_time; /* Total time in exceptions */ -static uint32_t svc_calls; /* Number of service calls */ -static uint32_t task_switches; /* Number of times active task changed */ -static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ +static uint32_t exc_start_time; /* Time of task->exception transition */ +static uint32_t exc_end_time; /* Time of exception->task transition */ +static uint64_t exc_total_time; /* Total time in exceptions */ +static uint32_t svc_calls; /* Number of service calls */ +static uint32_t task_switches; /* Number of times active task changed */ +static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */ #endif extern int __task_start(void); @@ -96,41 +96,36 @@ static void task_exit_trap(void) } /* Startup parameters for all tasks. */ -#define TASK(n, r, d, s) { \ - .a0 = (uint32_t)d, \ - .pc = (uint32_t)r, \ - .stack_size = s, \ -}, +#define TASK(n, r, d, s) \ + { \ + .a0 = (uint32_t)d, \ + .pc = (uint32_t)r, \ + .stack_size = s, \ + }, static const struct { uint32_t a0; uint32_t pc; uint16_t stack_size; -} tasks_init[] = { - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -}; +} tasks_init[] = { TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST }; #undef TASK /* Contexts for all tasks */ -static task_ tasks[TASK_ID_COUNT] __attribute__ ((section(".bss.tasks"))); +static task_ tasks[TASK_ID_COUNT] __attribute__((section(".bss.tasks"))); /* Validity checks about static task invariants */ -BUILD_ASSERT(TASK_ID_COUNT <= (sizeof(unsigned) * 8)); +BUILD_ASSERT(TASK_ID_COUNT <= (sizeof(unsigned int) * 8)); BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); /* Stacks for all tasks */ -#define TASK(n, r, d, s) + s -uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) - CONFIG_TASK_LIST - CONFIG_TEST_TASK_LIST -] __aligned(8); +#define TASK(n, r, d, s) +s +uint8_t task_stacks[0 TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) + CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST] __aligned(8); #undef TASK /* Reserve space to discard context on first context switch. */ -uint32_t scratchpad[TASK_SCRATCHPAD_SIZE] __attribute__ - ((section(".bss.task_scratchpad"))); +uint32_t scratchpad[TASK_SCRATCHPAD_SIZE] + __attribute__((section(".bss.task_scratchpad"))); task_ *current_task = (task_ *)scratchpad; @@ -154,18 +149,18 @@ int need_resched; * can do their init within a task switching context. The hooks task will then * make a call to enable all tasks. */ -static uint32_t tasks_ready = BIT(TASK_ID_HOOKS); +static atomic_t tasks_ready = BIT(TASK_ID_HOOKS); /* * Initially allow only the HOOKS and IDLE task to run, regardless of ready * status, in order for HOOK_INIT to complete before other tasks. * task_enable_all_tasks() will open the flood gates. */ -static uint32_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); +static atomic_t tasks_enabled = BIT(TASK_ID_HOOKS) | BIT(TASK_ID_IDLE); -int start_called; /* Has task swapping started */ +int start_called; /* Has task swapping started */ /* in interrupt context */ -static volatile int in_interrupt; +volatile bool in_interrupt; /* Interrupt number of EC modules */ volatile int ec_int; /* Interrupt group of EC INTC modules */ @@ -188,23 +183,33 @@ static inline task_ *__task_id_to_ptr(task_id_t id) void __ram_code interrupt_disable(void) { /* bit11: disable MEIE */ - asm volatile ("li t0, 0x800"); - asm volatile ("csrc mie, t0"); + asm volatile("li t0, 0x800"); + asm volatile("csrc mie, t0"); } void __ram_code interrupt_enable(void) { /* bit11: enable MEIE */ - asm volatile ("li t0, 0x800"); - asm volatile ("csrs mie, t0"); + asm volatile("li t0, 0x800"); + asm volatile("csrs mie, t0"); +} + +inline bool is_interrupt_enabled(void) +{ + int mie = 0; + + asm volatile("csrr %0, mie" : "=r"(mie)); + + /* Check if MEIE bit is set in MIE register */ + return mie & 0x800; } -inline int in_interrupt_context(void) +inline bool in_interrupt_context(void) { return in_interrupt; } -int in_soft_interrupt_context(void) +bool in_soft_interrupt_context(void) { /* group 16 is reserved for soft-irq */ return in_interrupt_context() && ec_int_group == 16; @@ -219,7 +224,7 @@ task_id_t __ram_code task_get_current(void) return current_task - tasks; } -uint32_t * __ram_code task_get_event_bitmap(task_id_t tskid) +atomic_t *__ram_code task_get_event_bitmap(task_id_t tskid) { task_ *tsk = __task_id_to_ptr(tskid); @@ -237,7 +242,7 @@ int task_start_called(void) * Also includes emulation of software triggering interrupt vector */ void __ram_code __keep syscall_handler(int desched, task_id_t resched, - int swirq) + int swirq) { /* are we emulating an interrupt ? */ if (swirq) { @@ -269,14 +274,14 @@ void __ram_code __keep syscall_handler(int desched, task_id_t resched, set_mepc(get_mepc() + 4); } -task_ * __ram_code next_sched_task(void) +task_ *__ram_code next_sched_task(void) { task_ *new_task = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); #ifdef CONFIG_TASK_PROFILING if (current_task != new_task) { current_task->runtime += - (exc_start_time - exc_end_time - exc_sub_time); + (exc_start_time - exc_end_time - exc_sub_time); task_will_switch = 1; } #endif @@ -284,11 +289,11 @@ task_ * __ram_code next_sched_task(void) #ifdef CONFIG_DEBUG_STACK_OVERFLOW if (*current_task->stack != STACK_UNUSED_VALUE) { int i = task_get_current(); - - panic_printf("\n\nStack overflow in %s task!\n", task_names[i]); -#ifdef CONFIG_SOFTWARE_PANIC - software_panic(PANIC_SW_STACK_OVERFLOW, i); -#endif + if (task_enabled(i)) { + panic_printf("\n\nStack overflow in %s task!\n", + task_names[i]); + software_panic(PANIC_SW_STACK_OVERFLOW, i); + } } #endif @@ -311,16 +316,14 @@ void __ram_code update_exc_start_time(void) #endif } -void __ram_code start_irq_handler(void) +/** + * The beginning of interrupt handler of c language code. + * + * @param none + * @return -1 if it cannot find the corresponding interrupt source. + */ +int __ram_code start_irq_handler(void) { - /* save a0, a1, and a2 for syscall */ - asm volatile ("addi sp, sp, -4*3"); - asm volatile ("sw a0, 0(sp)"); - asm volatile ("sw a1, 1*4(sp)"); - asm volatile ("sw a2, 2*4(sp)"); - - in_interrupt = 1; - /* If this is a SW interrupt */ if (get_mcause() == 11) { ec_int = sw_int_num; @@ -330,9 +333,8 @@ void __ram_code start_irq_handler(void) * Determine interrupt number. * -1 if it cannot find the corresponding interrupt source. */ - ec_int = chip_get_ec_int(); - if (ec_int == -1) - goto error; + if (chip_get_ec_int() == -1) + return -1; ec_int_group = chip_get_intc_group(ec_int); } @@ -350,15 +352,7 @@ void __ram_code start_irq_handler(void) irq_dist[ec_int]++; #endif -error: - /* cannot use return statement because a0 has been used */ - asm volatile ("add t0, zero, %0" :: "r"(ec_int)); - - /* restore a0, a1, and a2 */ - asm volatile ("lw a0, 0(sp)"); - asm volatile ("lw a1, 1*4(sp)"); - asm volatile ("lw a2, 2*4(sp)"); - asm volatile ("addi sp, sp, 4*3"); + return EC_SUCCESS; } void __ram_code end_irq_handler(void) @@ -378,7 +372,6 @@ void __ram_code end_irq_handler(void) task_switches++; } #endif - in_interrupt = 0; } static uint32_t __ram_code __wait_evt(int timeout_us, task_id_t resched) @@ -397,7 +390,7 @@ static uint32_t __ram_code __wait_evt(int timeout_us, task_id_t resched) ret = timer_arm(deadline, me); ASSERT(ret == EC_SUCCESS); } - while (!(evt = deprecated_atomic_read_clear(&tsk->events))) { + while (!(evt = atomic_clear(&tsk->events))) { /* Remove ourself and get the next task in the scheduler */ __schedule(1, resched, 0); resched = TASK_ID_IDLE; @@ -405,34 +398,29 @@ static uint32_t __ram_code __wait_evt(int timeout_us, task_id_t resched) if (timeout_us > 0) { timer_cancel(me); /* Ensure timer event is clear, we no longer care about it */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); + atomic_clear_bits(&tsk->events, TASK_EVENT_TIMER); } return evt; } -uint32_t __ram_code task_set_event(task_id_t tskid, uint32_t event, int wait) +void __ram_code task_set_event(task_id_t tskid, uint32_t event) { task_ *receiver = __task_id_to_ptr(tskid); ASSERT(receiver); /* Set the event bit in the receiver message bitmap */ - deprecated_atomic_or(&receiver->events, event); + atomic_or(&receiver->events, event); /* Re-schedule if priorities have changed */ if (in_interrupt_context()) { /* The receiver might run again */ - deprecated_atomic_or(&tasks_ready, 1 << tskid); + atomic_or(&tasks_ready, 1 << tskid); if (start_called) need_resched = 1; } else { - if (wait) - return __wait_evt(-1, tskid); - else - __schedule(0, tskid, 0); + __schedule(0, tskid, 0); } - - return 0; } uint32_t __ram_code task_wait_event(int timeout_us) @@ -463,8 +451,7 @@ uint32_t __ram_code task_wait_event_mask(uint32_t event_mask, int timeout_us) /* Re-post any other events collected */ if (events & ~event_mask) - deprecated_atomic_or(¤t_task->events, - events & ~event_mask); + atomic_or(¤t_task->events, events & ~event_mask); return events & event_mask; } @@ -474,14 +461,14 @@ uint32_t __ram_code read_clear_int_mask(void) uint32_t mie, meie = BIT(11); /* Read and clear MEIE bit of MIE register. */ - asm volatile ("csrrc %0, mie, %1" : "=r"(mie) : "r"(meie)); + asm volatile("csrrc %0, mie, %1" : "=r"(mie) : "r"(meie)); return mie; } void __ram_code set_int_mask(uint32_t val) { - asm volatile ("csrw mie, %0" : : "r"(val)); + asm volatile("csrw mie, %0" : : "r"(val)); } void task_enable_all_tasks(void) @@ -494,12 +481,17 @@ void task_enable_all_tasks(void) void task_enable_task(task_id_t tskid) { - deprecated_atomic_or(&tasks_enabled, BIT(tskid)); + atomic_or(&tasks_enabled, BIT(tskid)); +} + +bool task_enabled(task_id_t tskid) +{ + return tasks_enabled & BIT(tskid); } void task_disable_task(task_id_t tskid) { - deprecated_atomic_clear_bits(&tasks_enabled, BIT(tskid)); + atomic_clear_bits(&tasks_enabled, BIT(tskid)); if (!in_interrupt_context() && tskid == task_get_current()) __schedule(0, 0, 0); @@ -558,15 +550,15 @@ void __ram_code mutex_lock(struct mutex *mtx) uint32_t id = 1 << task_get_current(); ASSERT(id != TASK_ID_INVALID); - deprecated_atomic_or(&mtx->waiters, id); + atomic_or(&mtx->waiters, id); while (1) { - asm volatile ( + asm volatile( /* set lock value */ "li %0, 2\n\t" /* attempt to acquire lock */ "amoswap.w.aq %0, %0, %1\n\t" - : "=r" (locked), "+A" (mtx->lock)); + : "=&r"(locked), "+A"(mtx->lock)); /* we got it ! */ if (!locked) break; @@ -575,7 +567,7 @@ void __ram_code mutex_lock(struct mutex *mtx) task_wait_event_mask(TASK_EVENT_MUTEX, 0); } - deprecated_atomic_clear_bits(&mtx->waiters, id); + atomic_clear_bits(&mtx->waiters, id); } void __ram_code mutex_unlock(struct mutex *mtx) @@ -584,9 +576,7 @@ void __ram_code mutex_unlock(struct mutex *mtx) task_ *tsk = current_task; /* give back the lock */ - asm volatile ( - "amoswap.w.aqrl zero, zero, %0\n\t" - : "+A" (mtx->lock)); + asm volatile("amoswap.w.aqrl zero, zero, %0\n\t" : "+A"(mtx->lock)); waiters = mtx->waiters; while (waiters) { @@ -595,11 +585,11 @@ void __ram_code mutex_unlock(struct mutex *mtx) waiters &= ~BIT(id); /* Somebody is waiting on the mutex */ - task_set_event(id, TASK_EVENT_MUTEX, 0); + task_set_event(id, TASK_EVENT_MUTEX); } /* Ensure no event is remaining from mutex wake-up */ - deprecated_atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); + atomic_clear_bits(&tsk->events, TASK_EVENT_MUTEX); } void task_print_list(void) @@ -609,7 +599,7 @@ void task_print_list(void) ccputs("Task Ready Name Events Time (s) StkUsed\n"); for (i = 0; i < TASK_ID_COUNT; i++) { - char is_ready = (tasks_ready & (1< generate_elliptic_curve_key() +{ + bssl::UniquePtr key( + EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + if (key == nullptr) { + return nullptr; + } + + if (EC_KEY_generate_key(key.get()) != 1) { + return nullptr; + } + + return key; +} diff --git a/cts/build.mk b/cts/build.mk index 3f0cd750db..44db306f40 100644 --- a/cts/build.mk +++ b/cts/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -13,7 +13,7 @@ ifeq "$(CTS_MODULE)" "i2c" CFLAGS_CTS+=-DCTS_MODULE_I2C=$(EMPTY) CONFIG_I2C=y ifneq ($(BOARD),stm32l476g-eval) -CONFIG_I2C_MASTER=y +CONFIG_I2C_CONTROLLER=y endif endif diff --git a/cts/common/board.py b/cts/common/board.py index 478da1479c..d04f73fe5f 100644 --- a/cts/common/board.py +++ b/cts/common/board.py @@ -1,4 +1,4 @@ -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -6,379 +6,417 @@ from __future__ import print_function -from abc import ABCMeta -from abc import abstractmethod +from abc import ABCMeta, abstractmethod import os import shutil import subprocess as sp -import serial +import serial # pylint:disable=import-error import six -OCD_SCRIPT_DIR = '/usr/share/openocd/scripts' +OCD_SCRIPT_DIR = "/usr/share/openocd/scripts" OPENOCD_CONFIGS = { - 'stm32l476g-eval': 'board/stm32l4discovery.cfg', - 'nucleo-f072rb': 'board/st_nucleo_f0.cfg', - 'nucleo-f411re': 'board/st_nucleo_f4.cfg', + "stm32l476g-eval": "board/stm32l4discovery.cfg", + "nucleo-f072rb": "board/st_nucleo_f0.cfg", + "nucleo-f411re": "board/st_nucleo_f4.cfg", } FLASH_OFFSETS = { - 'stm32l476g-eval': '0x08000000', - 'nucleo-f072rb': '0x08000000', - 'nucleo-f411re': '0x08000000', + "stm32l476g-eval": "0x08000000", + "nucleo-f072rb": "0x08000000", + "nucleo-f411re": "0x08000000", } -REBOOT_MARKER = 'UART initialized after reboot' +REBOOT_MARKER = "UART initialized after reboot" def get_subprocess_args(): - if six.PY3: - return {'encoding': 'utf-8'} - return {} + if six.PY3: + return {"encoding": "utf-8"} + return {} class Board(six.with_metaclass(ABCMeta, object)): - """Class representing a single board connected to a host machine. - - Attributes: - board: String containing actual type of board, i.e. nucleo-f072rb - config: Directory of board config file relative to openocd's - scripts directory - hla_serial: String containing board's hla_serial number (if board - is an stm32 board) - tty_port: String that is the path to the tty port which board's - UART outputs to - tty: String of file descriptor for tty_port - """ - - def __init__(self, board, module, hla_serial=None): - """Initializes a board object with given attributes. - - Args: - board: String containing board name - module: String of the test module you are building, - i.e. gpio, timer, etc. - hla_serial: Serial number if board's adaptor is an HLA - - Raises: - RuntimeError: Board is not supported + """Class representing a single board connected to a host machine. + + Attributes: + board: String containing actual type of board, i.e. nucleo-f072rb + config: Directory of board config file relative to openocd's + scripts directory + hla_serial: String containing board's hla_serial number (if board + is an stm32 board) + tty_port: String that is the path to the tty port which board's + UART outputs to + tty: String of file descriptor for tty_port """ - if board not in OPENOCD_CONFIGS: - msg = 'OpenOcd configuration not found for ' + board - raise RuntimeError(msg) - if board not in FLASH_OFFSETS: - msg = 'Flash offset not found for ' + board - raise RuntimeError(msg) - self.board = board - self.flash_offset = FLASH_OFFSETS[self.board] - self.openocd_config = OPENOCD_CONFIGS[self.board] - self.module = module - self.hla_serial = hla_serial - self.tty_port = None - self.tty = None - - def reset_log_dir(self): - """Reset log directory.""" - if os.path.isdir(self.log_dir): - shutil.rmtree(self.log_dir) - os.makedirs(self.log_dir) - - @staticmethod - def get_stlink_serials(): - """Gets serial numbers of all st-link v2.1 board attached to host. - - Returns: - List of serials - """ - usb_args = ['sudo', 'lsusb', '-v', '-d', '0x0483:0x374b'] - st_link_info = sp.check_output(usb_args, **get_subprocess_args()) - st_serials = [] - for line in st_link_info.split('\n'): - if 'iSerial' not in line: - continue - words = line.split() - if len(words) <= 2: - continue - st_serials.append(words[2].strip()) - return st_serials - - @abstractmethod - def get_serial(self): - """Subclass should implement this.""" - pass - - def send_openocd_commands(self, commands): - """Send a command to the board via openocd. - - Args: - commands: A list of commands to send - - Returns: - True if execution is successful or False otherwise. - """ - args = ['sudo', 'openocd', '-s', OCD_SCRIPT_DIR, - '-f', self.openocd_config, '-c', 'hla_serial ' + self.hla_serial] - - for cmd in commands: - args += ['-c', cmd] - args += ['-c', 'shutdown'] - - rv = 1 - with open(self.openocd_log, 'a') as output: - rv = sp.call(args, stdout=output, stderr=sp.STDOUT) - - if rv != 0: - self.dump_openocd_log() - - return rv == 0 - - def dump_openocd_log(self): - with open(self.openocd_log) as log: - print(log.read()) - def build(self, ec_dir): - """Builds test suite module for board. - - Args: - ec_dir: String of the ec directory path - - Returns: - True if build is successful or False otherwise. - """ - cmds = ['make', - '--directory=' + ec_dir, - 'BOARD=' + self.board, - 'CTS_MODULE=' + self.module, - '-j'] - - rv = 1 - with open(self.build_log, 'a') as output: - rv = sp.call(cmds, stdout=output, stderr=sp.STDOUT) - - if rv != 0: - self.dump_build_log() - - return rv == 0 - - def dump_build_log(self): - with open(self.build_log) as log: - print(log.read()) - - def flash(self, image_path): - """Flashes board with most recent build ec.bin.""" - cmd = ['reset_config connect_assert_srst', - 'init', - 'reset init', - 'flash write_image erase %s %s' % (image_path, self.flash_offset)] - return self.send_openocd_commands(cmd) - - def to_string(self): - s = ('Type: Board\n' - 'board: ' + self.board + '\n' - 'hla_serial: ' + self.hla_serial + '\n' - 'openocd_config: ' + self.openocd_config + '\n' - 'tty_port: ' + self.tty_port + '\n' - 'tty: ' + str(self.tty) + '\n') - return s - - def reset_halt(self): - """Reset then halt board.""" - return self.send_openocd_commands(['init', 'reset halt']) - - def resume(self): - """Resume halting board.""" - return self.send_openocd_commands(['init', 'resume']) - - def setup_tty(self): - """Call this before calling read_tty for the first time. - - This is not in the initialization because caller only should call - this function after serial numbers are setup - """ - self.get_serial() - self.reset_halt() - self.identify_tty_port() - - tty = None - try: - tty = serial.Serial(self.tty_port, 115200, timeout=1) - except serial.SerialException: - raise ValueError('Failed to open ' + self.tty_port + ' of ' + self.board + - '. Please make sure the port is available and you have' + - ' permission to read it. Create dialout group and run:' + - ' sudo usermod -a -G dialout .') - self.tty = tty - - def read_tty(self, max_boot_count=1): - """Read info from a serial port described by a file descriptor. - - Args: - max_boot_count: Stop reading if boot count exceeds this number - - Returns: - result: characters read from tty - boot: boot counts - """ - buf = [] - line = [] - boot = 0 - while True: - c = self.tty.read().decode('utf-8') - if not c: - break - line.append(c) - if c == '\n': - l = ''.join(line) - buf.append(l) - if REBOOT_MARKER in l: - boot += 1 + def __init__(self, board, module, hla_serial=None): + """Initializes a board object with given attributes. + + Args: + board: String containing board name + module: String of the test module you are building, + i.e. gpio, timer, etc. + hla_serial: Serial number if board's adaptor is an HLA + + Raises: + RuntimeError: Board is not supported + """ + if board not in OPENOCD_CONFIGS: + msg = "OpenOcd configuration not found for " + board + raise RuntimeError(msg) + if board not in FLASH_OFFSETS: + msg = "Flash offset not found for " + board + raise RuntimeError(msg) + self.board = board + self.flash_offset = FLASH_OFFSETS[self.board] + self.openocd_config = OPENOCD_CONFIGS[self.board] + self.module = module + self.hla_serial = hla_serial + self.tty_port = None + self.tty = None + self.log_dir = None + self.openocd_log = os.devnull + self.build_log = os.devnull + + def reset_log_dir(self): + """Reset log directory.""" + if self.log_dir: + if os.path.isdir(self.log_dir): + shutil.rmtree(self.log_dir) + os.makedirs(self.log_dir) + + @staticmethod + def get_stlink_serials(): + """Gets serial numbers of all st-link v2.1 board attached to host. + + Returns: + List of serials + """ + usb_args = ["sudo", "lsusb", "-v", "-d", "0x0483:0x374b"] + st_link_info = sp.check_output(usb_args, **get_subprocess_args()) + st_serials = [] + for line in st_link_info.split("\n"): + if "iSerial" not in line: + continue + words = line.split() + if len(words) <= 2: + continue + st_serials.append(words[2].strip()) + return st_serials + + @abstractmethod + def get_serial(self): + """Subclass should implement this.""" + pass + + def send_openocd_commands(self, commands): + """Send a command to the board via openocd. + + Args: + commands: A list of commands to send + + Returns: + True if execution is successful or False otherwise. + """ + args = [ + "sudo", + "openocd", + "-s", + OCD_SCRIPT_DIR, + "-f", + self.openocd_config, + "-c", + "hla_serial " + self.hla_serial, + ] + + for cmd in commands: + args += ["-c", cmd] + args += ["-c", "shutdown"] + + rv = 1 + with open(self.openocd_log, "a") as output: + rv = sp.call(args, stdout=output, stderr=sp.STDOUT) + + if rv != 0: + self.dump_openocd_log() + + return rv == 0 + + def dump_openocd_log(self): + with open(self.openocd_log) as log: + print(log.read()) + + def build(self, ec_dir): + """Builds test suite module for board. + + Args: + ec_dir: String of the ec directory path + + Returns: + True if build is successful or False otherwise. + """ + cmds = [ + "make", + "--directory=" + ec_dir, + "BOARD=" + self.board, + "CTS_MODULE=" + self.module, + "-j", + ] + + rv = 1 + with open(self.build_log, "a") as output: + rv = sp.call(cmds, stdout=output, stderr=sp.STDOUT) + + if rv != 0: + self.dump_build_log() + + return rv == 0 + + def dump_build_log(self): + with open(self.build_log) as log: + print(log.read()) + + def flash(self, image_path): + """Flashes board with most recent build ec.bin.""" + cmd = [ + "reset_config connect_assert_srst", + "init", + "reset init", + "flash write_image erase %s %s" % (image_path, self.flash_offset), + ] + return self.send_openocd_commands(cmd) + + def to_string(self): + s = ( + "Type: Board\n" + "board: " + self.board + "\n" + "hla_serial: " + self.hla_serial + "\n" + "openocd_config: " + self.openocd_config + "\n" + "tty_port: " + self.tty_port + "\n" + "tty: " + str(self.tty) + "\n" + ) + return s + + def reset_halt(self): + """Reset then halt board.""" + return self.send_openocd_commands(["init", "reset halt"]) + + def resume(self): + """Resume halting board.""" + return self.send_openocd_commands(["init", "resume"]) + + def setup_tty(self): + """Call this before calling read_tty for the first time. + + This is not in the initialization because caller only should call + this function after serial numbers are setup + """ + self.get_serial() + self.reset_halt() + self.identify_tty_port() + + tty = None + try: + tty = serial.Serial(self.tty_port, 115200, timeout=1) + except serial.SerialException: + raise ValueError( + "Failed to open " + + self.tty_port + + " of " + + self.board + + ". Please make sure the port is available and you have" + + " permission to read it. Create dialout group and run:" + + " sudo usermod -a -G dialout ." + ) + self.tty = tty + + def read_tty(self, max_boot_count=1): + """Read info from a serial port described by a file descriptor. + + Args: + max_boot_count: Stop reading if boot count exceeds this number + + Returns: + result: characters read from tty + boot: boot counts + """ + buf = [] line = [] - if boot > max_boot_count: - break - - l = ''.join(line) - buf.append(l) - result = ''.join(buf) - - return result, boot - - def identify_tty_port(self): - """Saves this board's serial port.""" - dev_dir = '/dev' - id_prefix = 'ID_SERIAL_SHORT=' - com_devices = [f for f in os.listdir(dev_dir) if f.startswith('ttyACM')] - - for device in com_devices: - self.tty_port = os.path.join(dev_dir, device) - properties = sp.check_output( - ['udevadm', 'info', '-a', '-n', self.tty_port, '--query=property'], - **get_subprocess_args()) - for line in [l.strip() for l in properties.split('\n')]: - if line.startswith(id_prefix): - if self.hla_serial == line[len(id_prefix):]: - return - - # If we get here without returning, something is wrong - raise RuntimeError('The device dev path could not be found') - - def close_tty(self): - """Close tty.""" - self.tty.close() + boot = 0 + while True: + c = self.tty.read().decode("utf-8") + if not c: + break + line.append(c) + if c == "\n": + l = "".join(line) + buf.append(l) + if REBOOT_MARKER in l: + boot += 1 + line = [] + if boot > max_boot_count: + break + + l = "".join(line) + buf.append(l) + result = "".join(buf) + + return result, boot + + def identify_tty_port(self): + """Saves this board's serial port.""" + dev_dir = "/dev" + id_prefix = "ID_SERIAL_SHORT=" + com_devices = [f for f in os.listdir(dev_dir) if f.startswith("ttyACM")] + + for device in com_devices: + self.tty_port = os.path.join(dev_dir, device) + properties = sp.check_output( + [ + "udevadm", + "info", + "-a", + "-n", + self.tty_port, + "--query=property", + ], + **get_subprocess_args() + ) + for line in [l.strip() for l in properties.split("\n")]: + if line.startswith(id_prefix): + if self.hla_serial == line[len(id_prefix) :]: + return + + # If we get here without returning, something is wrong + raise RuntimeError("The device dev path could not be found") + + def close_tty(self): + """Close tty.""" + self.tty.close() class TestHarness(Board): - """Subclass of Board representing a Test Harness. + """Subclass of Board representing a Test Harness. - Attributes: - serial_path: Path to file containing serial number - """ - - def __init__(self, board, module, log_dir, serial_path): - """Initializes a board object with given attributes. - - Args: - board: board name - module: module name - log_dir: Directory where log file is stored + Attributes: serial_path: Path to file containing serial number """ - Board.__init__(self, board, module) - self.log_dir = log_dir - self.openocd_log = os.path.join(log_dir, 'openocd_th.log') - self.build_log = os.path.join(log_dir, 'build_th.log') - self.serial_path = serial_path - self.reset_log_dir() - - def get_serial(self): - """Loads serial number from saved location.""" - if self.hla_serial: - return # serial was already loaded - try: - with open(self.serial_path, mode='r') as f: - s = f.read() - self.hla_serial = s.strip() + + def __init__(self, board, module, log_dir, serial_path): + """Initializes a board object with given attributes. + + Args: + board: board name + module: module name + log_dir: Directory where log file is stored + serial_path: Path to file containing serial number + """ + Board.__init__(self, board, module) + self.log_dir = log_dir + self.openocd_log = os.path.join(log_dir, "openocd_th.log") + self.build_log = os.path.join(log_dir, "build_th.log") + self.serial_path = serial_path + self.reset_log_dir() + + def get_serial(self): + """Loads serial number from saved location.""" + if self.hla_serial: + return # serial was already loaded + try: + with open(self.serial_path, mode="r") as f: + s = f.read() + self.hla_serial = s.strip() + return + except IOError: + msg = ( + "Your TH board has not been identified.\n" + "Connect only TH and run the script --setup, then try again." + ) + raise RuntimeError(msg) + + def save_serial(self): + """Saves the TH serial number to a file.""" + serials = Board.get_stlink_serials() + if len(serials) > 1: + msg = ( + "There are more than one test board connected to the host." + "\nConnect only the test harness and remove other boards." + ) + raise RuntimeError(msg) + if len(serials) < 1: + msg = "No test boards were found.\n" "Check boards are connected." + raise RuntimeError(msg) + + s = serials[0] + serial_dir = os.path.dirname(self.serial_path) + if not os.path.exists(serial_dir): + os.makedirs(serial_dir) + with open(self.serial_path, mode="w") as f: + f.write(s) + self.hla_serial = s + + print("Your TH serial", s, "has been saved as", self.serial_path) return - except IOError: - msg = ('Your TH board has not been identified.\n' - 'Connect only TH and run the script --setup, then try again.') - raise RuntimeError(msg) - - def save_serial(self): - """Saves the TH serial number to a file.""" - serials = Board.get_stlink_serials() - if len(serials) > 1: - msg = ('There are more than one test board connected to the host.' - '\nConnect only the test harness and remove other boards.') - raise RuntimeError(msg) - if len(serials) < 1: - msg = ('No test boards were found.\n' - 'Check boards are connected.') - raise RuntimeError(msg) - - s = serials[0] - serial_dir = os.path.dirname(self.serial_path) - if not os.path.exists(serial_dir): - os.makedirs(serial_dir) - with open(self.serial_path, mode='w') as f: - f.write(s) - self.hla_serial = s - - print('Your TH serial', s, 'has been saved as', self.serial_path) - return class DeviceUnderTest(Board): - """Subclass of Board representing a DUT board. + """Subclass of Board representing a DUT board. - Attributes: - th: Reference to test harness board to which this DUT is attached - """ - - def __init__(self, board, th, module, log_dir, hla_ser=None): - """Initializes a DUT object. - - Args: - board: String containing board name + Attributes: th: Reference to test harness board to which this DUT is attached - module: module name - log_dir: Directory where log file is stored - hla_ser: Serial number if board uses an HLA adaptor """ - Board.__init__(self, board, module, hla_serial=hla_ser) - self.th = th - self.log_dir = log_dir - self.openocd_log = os.path.join(log_dir, 'openocd_dut.log') - self.build_log = os.path.join(log_dir, 'build_dut.log') - self.reset_log_dir() - - def get_serial(self): - """Get serial number. - Precondition: The DUT and TH must both be connected, and th.hla_serial - must hold the correct value (the th's serial #) + def __init__(self, board, th, module, log_dir, hla_ser=None): + """Initializes a DUT object. + + Args: + board: String containing board name + th: Reference to test harness board to which this DUT is attached + module: module name + log_dir: Directory where log file is stored + hla_ser: Serial number if board uses an HLA adaptor + """ + Board.__init__(self, board, module, hla_serial=hla_ser) + self.th = th + self.log_dir = log_dir + self.openocd_log = os.path.join(log_dir, "openocd_dut.log") + self.build_log = os.path.join(log_dir, "build_dut.log") + self.reset_log_dir() + + def get_serial(self): + """Get serial number. + + Precondition: The DUT and TH must both be connected, and th.hla_serial + must hold the correct value (the th's serial #) + + Raises: + RuntimeError: DUT isn't found or multiple DUTs are found. + """ + if self.hla_serial is not None: + # serial was already set ('' is a valid serial) + return - Raises: - RuntimeError: DUT isn't found or multiple DUTs are found. - """ - if self.hla_serial is not None: - # serial was already set ('' is a valid serial) - return - - serials = Board.get_stlink_serials() - dut = [s for s in serials if self.th.hla_serial != s] - - # If len(dut) is 0 then your dut doesn't use an st-link device, so we - # don't have to worry about its serial number - if not dut: - msg = ('Failed to find serial for DUT.\n' - 'Is ' + self.board + ' connected?') - raise RuntimeError(msg) - if len(dut) > 1: - msg = ('Found multiple DUTs.\n' - 'You can connect only one DUT at a time. This may be caused by\n' - 'an incorrect TH serial. Check if ' + self.th.serial_path + '\n' - 'contains a correct serial.') - raise RuntimeError(msg) - - # Found your other st-link device serial! - self.hla_serial = dut[0] - return + serials = Board.get_stlink_serials() + dut = [s for s in serials if self.th.hla_serial != s] + + # If len(dut) is 0 then your dut doesn't use an st-link device, so we + # don't have to worry about its serial number + if not dut: + msg = ( + "Failed to find serial for DUT.\nIs " + + self.board + + " connected?" + ) + raise RuntimeError(msg) + if len(dut) > 1: + msg = ( + "Found multiple DUTs.\n" + "You can connect only one DUT at a time. This may be caused by\n" + "an incorrect TH serial. Check if " + self.th.serial_path + "\n" + "contains a correct serial." + ) + raise RuntimeError(msg) + + # Found your other st-link device serial! + self.hla_serial = dut[0] + return diff --git a/cts/common/cts.rc b/cts/common/cts.rc index 264b982655..fe27b2c308 100644 --- a/cts/common/cts.rc +++ b/cts/common/cts.rc @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/common/cts_common.c b/cts/common/cts_common.c index 8975636655..4b56456a3c 100644 --- a/cts/common/cts_common.c +++ b/cts/common/cts_common.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,7 +11,7 @@ __attribute__((weak)) void clean_state(void) /* Each test overrides as needed */ } -void cts_main_loop(const struct cts_test* tests, const char *name) +void cts_main_loop(const struct cts_test *tests, const char *name) { enum cts_rc rc; int i; diff --git a/cts/common/cts_common.h b/cts/common/cts_common.h index 13a435e655..8fd9073c62 100644 --- a/cts/common/cts_common.h +++ b/cts/common/cts_common.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,16 +10,16 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTL(format, args...) CPRINTS("%s:%d: "format, \ - __func__, __LINE__, ## args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTL(format, args...) \ + CPRINTS("%s:%d: " format, __func__, __LINE__, ##args) -#define READ_WAIT_TIME_MS 100 -#define CTS_INTERRUPT_TRIGGER_DELAY_US (250 * MSEC) +#define READ_WAIT_TIME_MS 100 +#define CTS_INTERRUPT_TRIGGER_DELAY_US (250 * MSEC) enum cts_rc { - #include "cts.rc" +#include "cts.rc" }; struct cts_test { @@ -38,7 +38,7 @@ extern const int cts_test_count; * @test: List of tests to run * @name: Name of the test to be printed on EC console */ -void cts_main_loop(const struct cts_test* tests, const char *name); +void cts_main_loop(const struct cts_test *tests, const char *name); /** * Callback function called at the beginning of the main loop diff --git a/cts/common/cts_testlist.h b/cts/common/cts_testlist.h index 1586c1348e..ee3ea58d39 100644 --- a/cts/common/cts_testlist.h +++ b/cts/common/cts_testlist.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,7 +22,7 @@ #undef CTS_TEST #define CTS_TEST(test, th_rc, th_string, dut_rc, dut_string) \ - {test, STRINGIFY(test)}, + { test, STRINGIFY(test) }, struct cts_test tests[] = { #include "cts.testlist" }; diff --git a/cts/common/dut_common.c b/cts/common/dut_common.c index 6e62a280e2..aa68436d41 100644 --- a/cts/common/dut_common.c +++ b/cts/common/dut_common.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -25,4 +25,3 @@ enum cts_rc sync(void) return CTS_RC_SUCCESS; } - diff --git a/cts/common/th_common.c b/cts/common/th_common.c index 1d692b7843..cc9c6be75f 100644 --- a/cts/common/th_common.c +++ b/cts/common/th_common.c @@ -1,12 +1,12 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "cts_common.h" #include "gpio.h" #include "timer.h" #include "watchdog.h" -#include "cts_common.h" /* Return SUCCESS if and only if we reach end of function * Returning success here means sync was successful diff --git a/cts/cts.py b/cts/cts.py index 95a3b1c5f3..619c8858c2 100755 --- a/cts/cts.py +++ b/cts/cts.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -24,416 +24,444 @@ import os import shutil import time + import common.board as board -CTS_RC_PREFIX = 'CTS_RC_' -DEFAULT_TH = 'stm32l476g-eval' -DEFAULT_DUT = 'nucleo-f072rb' +CTS_RC_PREFIX = "CTS_RC_" +DEFAULT_TH = "stm32l476g-eval" +DEFAULT_DUT = "nucleo-f072rb" MAX_SUITE_TIME_SEC = 5 -CTS_TEST_RESULT_DIR = '/tmp/ects' +CTS_TEST_RESULT_DIR = "/tmp/ects" # Host only return codes. Make sure they match values in cts.rc -CTS_RC_DID_NOT_START = -1 # test did not run. -CTS_RC_DID_NOT_END = -2 # test did not run. -CTS_RC_DUPLICATE_RUN = -3 # test was run multiple times. -CTS_RC_INVALID_RETURN_CODE = -4 # failed to parse return code +CTS_RC_DID_NOT_START = -1 # test did not run. +CTS_RC_DID_NOT_END = -2 # test did not run. +CTS_RC_DUPLICATE_RUN = -3 # test was run multiple times. +CTS_RC_INVALID_RETURN_CODE = -4 # failed to parse return code class Cts(object): - """Class that represents a eCTS run. - - Attributes: - dut: DeviceUnderTest object representing DUT - th: TestHarness object representing a test harness - module: Name of module to build/run tests for - testlist: List of strings of test names contained in given module - return_codes: Dict of strings of return codes, with a code's integer - value being the index for the corresponding string representation - """ - - def __init__(self, ec_dir, th, dut, module): - """Initializes cts class object with given arguments. - - Args: - ec_dir: Path to ec directory - th: Name of the test harness board - dut: Name of the device under test board - module: Name of module to build/run tests for (e.g. gpio, interrupt) - """ - self.results_dir = os.path.join(CTS_TEST_RESULT_DIR, dut, module) - if os.path.isdir(self.results_dir): - shutil.rmtree(self.results_dir) - else: - os.makedirs(self.results_dir) - self.ec_dir = ec_dir - self.module = module - serial_path = os.path.join(CTS_TEST_RESULT_DIR, 'th_serial') - self.th = board.TestHarness(th, module, self.results_dir, serial_path) - self.dut = board.DeviceUnderTest(dut, self.th, module, self.results_dir) - cts_dir = os.path.join(self.ec_dir, 'cts') - testlist_path = os.path.join(cts_dir, self.module, 'cts.testlist') - return_codes_path = os.path.join(cts_dir, 'common', 'cts.rc') - self.get_return_codes(return_codes_path) - self.testlist = self.get_macro_args(testlist_path, 'CTS_TEST') - - def build(self): - """Build images for DUT and TH.""" - print('Building DUT image...') - if not self.dut.build(self.ec_dir): - raise RuntimeError('Building module %s for DUT failed' % (self.module)) - print('Building TH image...') - if not self.th.build(self.ec_dir): - raise RuntimeError('Building module %s for TH failed' % (self.module)) - - def flash_boards(self): - """Flashes TH and DUT with their most recently built ec.bin.""" - cts_module = 'cts_' + self.module - image_path = os.path.join('build', self.th.board, cts_module, 'ec.bin') - self.identify_boards() - print('Flashing TH with', image_path) - if not self.th.flash(image_path): - raise RuntimeError('Flashing TH failed') - image_path = os.path.join('build', self.dut.board, cts_module, 'ec.bin') - print('Flashing DUT with', image_path) - if not self.dut.flash(image_path): - raise RuntimeError('Flashing DUT failed') - - def setup(self): - """Setup boards.""" - self.th.save_serial() - - def identify_boards(self): - """Updates serials of TH and DUT in that order (order matters).""" - self.th.get_serial() - self.dut.get_serial() - - def get_macro_args(self, filepath, macro): - """Get list of args of a macro in a file when macro. - - Args: - filepath: String containing absolute path to the file - macro: String containing text of macro to get args of - - Returns: - List of dictionaries where each entry is: - 'name': Test name, - 'th_string': Expected string from TH, - 'dut_string': Expected string from DUT, + """Class that represents a eCTS run. + + Attributes: + dut: DeviceUnderTest object representing DUT + th: TestHarness object representing a test harness + module: Name of module to build/run tests for + testlist: List of strings of test names contained in given module + return_codes: Dict of strings of return codes, with a code's integer + value being the index for the corresponding string representation """ - tests = [] - with open(filepath, 'r') as f: - lines = f.readlines() - joined = ''.join(lines).replace('\\\n', '').splitlines() - for l in joined: - if not l.strip().startswith(macro): - continue - d = {} - l = l.strip()[len(macro):] - l = l.strip('()').split(',') - d['name'] = l[0].strip() - d['th_rc'] = self.get_return_code_value(l[1].strip().strip('"')) - d['th_string'] = l[2].strip().strip('"') - d['dut_rc'] = self.get_return_code_value(l[3].strip().strip('"')) - d['dut_string'] = l[4].strip().strip('"') - tests.append(d) - return tests - - def get_return_codes(self, filepath): - """Read return code names from the return code definition file.""" - self.return_codes = {} - val = 0 - with open(filepath, 'r') as f: - for line in f: - line = line.strip() - if not line.startswith(CTS_RC_PREFIX): - continue - line = line.split(',')[0] - if '=' in line: - tokens = line.split('=') - line = tokens[0].strip() - val = int(tokens[1].strip()) - self.return_codes[line] = val - val += 1 - - def parse_output(self, output): - """Parse console output from DUT or TH. - - Args: - output: String containing consoule output - - Returns: - List of dictionaries where each key and value are: - name = 'ects_test_x', - started = True/False, - ended = True/False, - rc = CTS_RC_*, - output = All text between 'ects_test_x start' and 'ects_test_x end' - """ - results = [] - i = 0 - for test in self.testlist: - results.append({}) - results[i]['name'] = test['name'] - results[i]['started'] = False - results[i]['rc'] = CTS_RC_DID_NOT_START - results[i]['string'] = False - results[i]['output'] = [] - i += 1 - - i = 0 - for ln in [ln.strip() for ln in output.split('\n')]: - if i + 1 > len(results): - break - tokens = ln.split() - if len(tokens) >= 2: - if tokens[0].strip() == results[i]['name']: - if tokens[1].strip() == 'start': - # start line found - if results[i]['started']: # Already started - results[i]['rc'] = CTS_RC_DUPLICATE_RUN - else: - results[i]['rc'] = CTS_RC_DID_NOT_END - results[i]['started'] = True - continue - elif results[i]['started'] and tokens[1].strip() == 'end': - # end line found - results[i]['rc'] = CTS_RC_INVALID_RETURN_CODE - if len(tokens) == 3: - try: - results[i]['rc'] = int(tokens[2].strip()) - except ValueError: - pass - # Since index is incremented when 'end' is encountered, we don't - # need to check duplicate 'end'. - i += 1 - continue - if results[i]['started']: - results[i]['output'].append(ln) - - return results - - def get_return_code_name(self, code, strip_prefix=False): - name = '' - for k, v in self.return_codes.items(): - if v == code: - if strip_prefix: - name = k[len(CTS_RC_PREFIX):] - else: - name = k - return name - - def get_return_code_value(self, name): - if name: - return self.return_codes[name] - return 0 - - def evaluate_run(self, dut_output, th_output): - """Parse outputs to derive test results. - - Args: - dut_output: String output of DUT - th_output: String output of TH - Returns: - th_results: list of test results for TH - dut_results: list of test results for DUT - """ - th_results = self.parse_output(th_output) - dut_results = self.parse_output(dut_output) - - # Search for expected string in each output - for i, v in enumerate(self.testlist): - if v['th_string'] in th_results[i]['output'] or not v['th_string']: - th_results[i]['string'] = True - if v['dut_string'] in dut_results[i]['output'] or not v['dut_string']: - dut_results[i]['string'] = True + def __init__(self, ec_dir, th, dut, module): + """Initializes cts class object with given arguments. + + Args: + ec_dir: Path to ec directory + th: Name of the test harness board + dut: Name of the device under test board + module: Name of module to build/run tests for (e.g. gpio, interrupt) + """ + self.results_dir = os.path.join(CTS_TEST_RESULT_DIR, dut, module) + if os.path.isdir(self.results_dir): + shutil.rmtree(self.results_dir) + else: + os.makedirs(self.results_dir) + self.ec_dir = ec_dir + self.module = module + serial_path = os.path.join(CTS_TEST_RESULT_DIR, "th_serial") + self.th = board.TestHarness(th, module, self.results_dir, serial_path) + self.dut = board.DeviceUnderTest(dut, self.th, module, self.results_dir) + cts_dir = os.path.join(self.ec_dir, "cts") + testlist_path = os.path.join(cts_dir, self.module, "cts.testlist") + return_codes_path = os.path.join(cts_dir, "common", "cts.rc") + self.get_return_codes(return_codes_path) + self.testlist = self.get_macro_args(testlist_path, "CTS_TEST") + + def build(self): + """Build images for DUT and TH.""" + print("Building DUT image...") + if not self.dut.build(self.ec_dir): + raise RuntimeError( + "Building module %s for DUT failed" % (self.module) + ) + print("Building TH image...") + if not self.th.build(self.ec_dir): + raise RuntimeError( + "Building module %s for TH failed" % (self.module) + ) + + def flash_boards(self): + """Flashes TH and DUT with their most recently built ec.bin.""" + cts_module = "cts_" + self.module + image_path = os.path.join("build", self.th.board, cts_module, "ec.bin") + self.identify_boards() + print("Flashing TH with", image_path) + if not self.th.flash(image_path): + raise RuntimeError("Flashing TH failed") + image_path = os.path.join("build", self.dut.board, cts_module, "ec.bin") + print("Flashing DUT with", image_path) + if not self.dut.flash(image_path): + raise RuntimeError("Flashing DUT failed") + + def setup(self): + """Setup boards.""" + self.th.save_serial() + + def identify_boards(self): + """Updates serials of TH and DUT in that order (order matters).""" + self.th.get_serial() + self.dut.get_serial() + + def get_macro_args(self, filepath, macro): + """Get list of args of a macro in a file when macro. + + Args: + filepath: String containing absolute path to the file + macro: String containing text of macro to get args of + + Returns: + List of dictionaries where each entry is: + 'name': Test name, + 'th_string': Expected string from TH, + 'dut_string': Expected string from DUT, + """ + tests = [] + with open(filepath, "r") as f: + lines = f.readlines() + joined = "".join(lines).replace("\\\n", "").splitlines() + for l in joined: + if not l.strip().startswith(macro): + continue + d = {} + l = l.strip()[len(macro) :] + l = l.strip("()").split(",") + d["name"] = l[0].strip() + d["th_rc"] = self.get_return_code_value(l[1].strip().strip('"')) + d["th_string"] = l[2].strip().strip('"') + d["dut_rc"] = self.get_return_code_value( + l[3].strip().strip('"') + ) + d["dut_string"] = l[4].strip().strip('"') + tests.append(d) + return tests + + def get_return_codes(self, filepath): + """Read return code names from the return code definition file.""" + self.return_codes = {} + val = 0 + with open(filepath, "r") as f: + for line in f: + line = line.strip() + if not line.startswith(CTS_RC_PREFIX): + continue + line = line.split(",")[0] + if "=" in line: + tokens = line.split("=") + line = tokens[0].strip() + val = int(tokens[1].strip()) + self.return_codes[line] = val + val += 1 + + def parse_output(self, output): + """Parse console output from DUT or TH. + + Args: + output: String containing consoule output + + Returns: + List of dictionaries where each key and value are: + name = 'ects_test_x', + started = True/False, + ended = True/False, + rc = CTS_RC_*, + output = All text between 'ects_test_x start' and 'ects_test_x end' + """ + results = [] + i = 0 + for test in self.testlist: + results.append({}) + results[i]["name"] = test["name"] + results[i]["started"] = False + results[i]["rc"] = CTS_RC_DID_NOT_START + results[i]["string"] = False + results[i]["output"] = [] + i += 1 - return th_results, dut_results + i = 0 + for ln in [ln.strip() for ln in output.split("\n")]: + if i + 1 > len(results): + break + tokens = ln.split() + if len(tokens) >= 2: + if tokens[0].strip() == results[i]["name"]: + if tokens[1].strip() == "start": + # start line found + if results[i]["started"]: # Already started + results[i]["rc"] = CTS_RC_DUPLICATE_RUN + else: + results[i]["rc"] = CTS_RC_DID_NOT_END + results[i]["started"] = True + continue + elif results[i]["started"] and tokens[1].strip() == "end": + # end line found + results[i]["rc"] = CTS_RC_INVALID_RETURN_CODE + if len(tokens) == 3: + try: + results[i]["rc"] = int(tokens[2].strip()) + except ValueError: + pass + # Since index is incremented when 'end' is encountered, we don't + # need to check duplicate 'end'. + i += 1 + continue + if results[i]["started"]: + results[i]["output"].append(ln) + + return results + + def get_return_code_name(self, code, strip_prefix=False): + name = "" + for k, v in self.return_codes.items(): + if v == code: + if strip_prefix: + name = k[len(CTS_RC_PREFIX) :] + else: + name = k + return name + + def get_return_code_value(self, name): + if name: + return self.return_codes[name] + return 0 + + def evaluate_run(self, dut_output, th_output): + """Parse outputs to derive test results. + + Args: + dut_output: String output of DUT + th_output: String output of TH + + Returns: + th_results: list of test results for TH + dut_results: list of test results for DUT + """ + th_results = self.parse_output(th_output) + dut_results = self.parse_output(dut_output) + + # Search for expected string in each output + for i, v in enumerate(self.testlist): + if v["th_string"] in th_results[i]["output"] or not v["th_string"]: + th_results[i]["string"] = True + if ( + v["dut_string"] in dut_results[i]["output"] + or not v["dut_string"] + ): + dut_results[i]["string"] = True + + return th_results, dut_results + + def print_result(self, th_results, dut_results): + """Print results to the screen. + + Args: + th_results: list of test results for TH + dut_results: list of test results for DUT + """ + len_test_name = max(len(s["name"]) for s in self.testlist) + len_code_name = max( + len(self.get_return_code_name(v, True)) + for v in self.return_codes.values() + ) + + head = "{:^" + str(len_test_name) + "} " + head += "{:^" + str(len_code_name) + "} " + head += "{:^" + str(len_code_name) + "}" + head += "{:^" + str(len(" TH_STR")) + "}" + head += "{:^" + str(len(" DUT_STR")) + "}" + head += "{:^" + str(len(" RESULT")) + "}\n" + fmt = "{:" + str(len_test_name) + "} " + fmt += "{:>" + str(len_code_name) + "} " + fmt += "{:>" + str(len_code_name) + "}" + fmt += "{:>" + str(len(" TH_STR")) + "}" + fmt += "{:>" + str(len(" DUT_STR")) + "}" + fmt += "{:>" + str(len(" RESULT")) + "}\n" + + self.formatted_results = head.format( + "TEST NAME", "TH_RC", "DUT_RC", " TH_STR", " DUT_STR", " RESULT" + ) + for i, d in enumerate(dut_results): + th_cn = self.get_return_code_name(th_results[i]["rc"], True) + dut_cn = self.get_return_code_name(dut_results[i]["rc"], True) + th_res = self.evaluate_result( + th_results[i], + self.testlist[i]["th_rc"], + self.testlist[i]["th_string"], + ) + dut_res = self.evaluate_result( + dut_results[i], + self.testlist[i]["dut_rc"], + self.testlist[i]["dut_string"], + ) + self.formatted_results += fmt.format( + d["name"], + th_cn, + dut_cn, + "YES" if th_results[i]["string"] else "NO", + "YES" if dut_results[i]["string"] else "NO", + "PASS" if th_res and dut_res else "FAIL", + ) + + def evaluate_result(self, result, expected_rc, expected_string): + if result["rc"] != expected_rc: + return False + if expected_string and expected_string not in result["output"]: + return False + return True + + def run(self): + """Resets boards, records test results in results dir.""" + print("Reading serials...") + self.identify_boards() + print("Opening DUT tty...") + self.dut.setup_tty() + print("Opening TH tty...") + self.th.setup_tty() + + # Boards might be still writing to tty. Wait a few seconds before flashing. + time.sleep(3) + + # clear buffers + print("Clearing DUT tty...") + self.dut.read_tty() + print("Clearing TH tty...") + self.th.read_tty() + + # Resets the boards and allows them to run tests + # Due to current (7/27/16) version of sync function, + # both boards must be rest and halted, with the th + # resuming first, in order for the test suite to run in sync + print("Halting TH...") + if not self.th.reset_halt(): + raise RuntimeError("Failed to halt TH") + print("Halting DUT...") + if not self.dut.reset_halt(): + raise RuntimeError("Failed to halt DUT") + print("Resuming TH...") + if not self.th.resume(): + raise RuntimeError("Failed to resume TH") + print("Resuming DUT...") + if not self.dut.resume(): + raise RuntimeError("Failed to resume DUT") + + time.sleep(MAX_SUITE_TIME_SEC) + + print("Reading DUT tty...") + dut_output, _ = self.dut.read_tty() + self.dut.close_tty() + print("Reading TH tty...") + th_output, _ = self.th.read_tty() + self.th.close_tty() + + print("Halting TH...") + if not self.th.reset_halt(): + raise RuntimeError("Failed to halt TH") + print("Halting DUT...") + if not self.dut.reset_halt(): + raise RuntimeError("Failed to halt DUT") + + if not dut_output or not th_output: + raise ValueError( + "Output missing from boards. If you have a process " + "reading ttyACMx, please kill that process and try " + "again." + ) + + print("Pursing results...") + th_results, dut_results = self.evaluate_run(dut_output, th_output) + + # Print out results + self.print_result(th_results, dut_results) + + # Write results + dest = os.path.join(self.results_dir, "results.log") + with open(dest, "w") as fl: + fl.write(self.formatted_results) + + # Write UART outputs + dest = os.path.join(self.results_dir, "uart_th.log") + with open(dest, "w") as fl: + fl.write(th_output) + dest = os.path.join(self.results_dir, "uart_dut.log") + with open(dest, "w") as fl: + fl.write(dut_output) + + print(self.formatted_results) + + # TODO(chromium:735652): Should set exit code for the shell - def print_result(self, th_results, dut_results): - """Print results to the screen. - Args: - th_results: list of test results for TH - dut_results: list of test results for DUT - """ - len_test_name = max(len(s['name']) for s in self.testlist) - len_code_name = max(len(self.get_return_code_name(v, True)) - for v in self.return_codes.values()) - - head = '{:^' + str(len_test_name) + '} ' - head += '{:^' + str(len_code_name) + '} ' - head += '{:^' + str(len_code_name) + '}' - head += '{:^' + str(len(' TH_STR')) + '}' - head += '{:^' + str(len(' DUT_STR')) + '}' - head += '{:^' + str(len(' RESULT')) + '}\n' - fmt = '{:' + str(len_test_name) + '} ' - fmt += '{:>' + str(len_code_name) + '} ' - fmt += '{:>' + str(len_code_name) + '}' - fmt += '{:>' + str(len(' TH_STR')) + '}' - fmt += '{:>' + str(len(' DUT_STR')) + '}' - fmt += '{:>' + str(len(' RESULT')) + '}\n' - - self.formatted_results = head.format( - 'TEST NAME', 'TH_RC', 'DUT_RC', - ' TH_STR', ' DUT_STR', ' RESULT') - for i, d in enumerate(dut_results): - th_cn = self.get_return_code_name(th_results[i]['rc'], True) - dut_cn = self.get_return_code_name(dut_results[i]['rc'], True) - th_res = self.evaluate_result(th_results[i], - self.testlist[i]['th_rc'], - self.testlist[i]['th_string']) - dut_res = self.evaluate_result(dut_results[i], - self.testlist[i]['dut_rc'], - self.testlist[i]['dut_string']) - self.formatted_results += fmt.format( - d['name'], th_cn, dut_cn, - 'YES' if th_results[i]['string'] else 'NO', - 'YES' if dut_results[i]['string'] else 'NO', - 'PASS' if th_res and dut_res else 'FAIL') - - def evaluate_result(self, result, expected_rc, expected_string): - if result['rc'] != expected_rc: - return False - if expected_string and expected_string not in result['output']: - return False - return True - - def run(self): - """Resets boards, records test results in results dir.""" - print('Reading serials...') - self.identify_boards() - print('Opening DUT tty...') - self.dut.setup_tty() - print('Opening TH tty...') - self.th.setup_tty() - - # Boards might be still writing to tty. Wait a few seconds before flashing. - time.sleep(3) - - # clear buffers - print('Clearing DUT tty...') - self.dut.read_tty() - print('Clearing TH tty...') - self.th.read_tty() - - # Resets the boards and allows them to run tests - # Due to current (7/27/16) version of sync function, - # both boards must be rest and halted, with the th - # resuming first, in order for the test suite to run in sync - print('Halting TH...') - if not self.th.reset_halt(): - raise RuntimeError('Failed to halt TH') - print('Halting DUT...') - if not self.dut.reset_halt(): - raise RuntimeError('Failed to halt DUT') - print('Resuming TH...') - if not self.th.resume(): - raise RuntimeError('Failed to resume TH') - print('Resuming DUT...') - if not self.dut.resume(): - raise RuntimeError('Failed to resume DUT') - - time.sleep(MAX_SUITE_TIME_SEC) - - print('Reading DUT tty...') - dut_output, _ = self.dut.read_tty() - self.dut.close_tty() - print('Reading TH tty...') - th_output, _ = self.th.read_tty() - self.th.close_tty() - - print('Halting TH...') - if not self.th.reset_halt(): - raise RuntimeError('Failed to halt TH') - print('Halting DUT...') - if not self.dut.reset_halt(): - raise RuntimeError('Failed to halt DUT') - - if not dut_output or not th_output: - raise ValueError('Output missing from boards. If you have a process ' - 'reading ttyACMx, please kill that process and try ' - 'again.') - - print('Pursing results...') - th_results, dut_results = self.evaluate_run(dut_output, th_output) - - # Print out results - self.print_result(th_results, dut_results) - - # Write results - dest = os.path.join(self.results_dir, 'results.log') - with open(dest, 'w') as fl: - fl.write(self.formatted_results) - - # Write UART outputs - dest = os.path.join(self.results_dir, 'uart_th.log') - with open(dest, 'w') as fl: - fl.write(th_output) - dest = os.path.join(self.results_dir, 'uart_dut.log') - with open(dest, 'w') as fl: - fl.write(dut_output) - - print(self.formatted_results) - - # TODO(chromium:735652): Should set exit code for the shell +def main(): + ec_dir = os.path.realpath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") + ) + os.chdir(ec_dir) + + dut = DEFAULT_DUT + module = "meta" + + parser = argparse.ArgumentParser(description="Used to build/flash boards") + parser.add_argument( + "-d", "--dut", help="Specify DUT you want to build/flash" + ) + parser.add_argument( + "-m", "--module", help="Specify module you want to build/flash" + ) + parser.add_argument( + "-s", + "--setup", + action="store_true", + help="Connect only the TH to save its serial", + ) + parser.add_argument( + "-b", + "--build", + action="store_true", + help="Build test suite (no flashing)", + ) + parser.add_argument( + "-f", + "--flash", + action="store_true", + help="Flash boards with most recent images", + ) + parser.add_argument( + "-r", "--run", action="store_true", help="Run tests without flashing" + ) + + args = parser.parse_args() + + if args.module: + module = args.module + + if args.dut: + dut = args.dut + + cts = Cts(ec_dir, DEFAULT_TH, dut=dut, module=module) + + if args.setup: + cts.setup() + elif args.build: + cts.build() + elif args.flash: + cts.flash_boards() + elif args.run: + cts.run() + else: + cts.build() + cts.flash_boards() + cts.run() -def main(): - ec_dir = os.path.realpath(os.path.join( - os.path.dirname(os.path.abspath(__file__)), '..')) - os.chdir(ec_dir) - - dut = DEFAULT_DUT - module = 'meta' - - parser = argparse.ArgumentParser(description='Used to build/flash boards') - parser.add_argument('-d', - '--dut', - help='Specify DUT you want to build/flash') - parser.add_argument('-m', - '--module', - help='Specify module you want to build/flash') - parser.add_argument('-s', - '--setup', - action='store_true', - help='Connect only the TH to save its serial') - parser.add_argument('-b', - '--build', - action='store_true', - help='Build test suite (no flashing)') - parser.add_argument('-f', - '--flash', - action='store_true', - help='Flash boards with most recent images') - parser.add_argument('-r', - '--run', - action='store_true', - help='Run tests without flashing') - - args = parser.parse_args() - - if args.module: - module = args.module - - if args.dut: - dut = args.dut - - cts = Cts(ec_dir, DEFAULT_TH, dut=dut, module=module) - - if args.setup: - cts.setup() - elif args.build: - cts.build() - elif args.flash: - cts.flash_boards() - elif args.run: - cts.run() - else: - cts.build() - cts.flash_boards() - cts.run() - -if __name__ == '__main__': - main() +if __name__ == "__main__": + main() diff --git a/cts/cts.tasklist b/cts/cts.tasklist index 152b0d02b2..40dfb21e10 100644 --- a/cts/cts.tasklist +++ b/cts/cts.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/gpio/cts.testlist b/cts/gpio/cts.testlist index 113d2b405f..a5b7482675 100644 --- a/cts/gpio/cts.testlist +++ b/cts/gpio/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/gpio/dut.c b/cts/gpio/dut.c index 828996db8e..ef609cf4a8 100644 --- a/cts/gpio/dut.c +++ b/cts/gpio/dut.c @@ -1,15 +1,15 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" -#include "watchdog.h" -#include "uart.h" +#include "cts_common.h" +#include "gpio.h" #include "task.h" #include "timer.h" +#include "uart.h" #include "watchdog.h" -#include "cts_common.h" enum cts_rc sync_test(void) { @@ -20,7 +20,7 @@ enum cts_rc set_high_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW); gpio_set_level(GPIO_OUTPUT_TEST, 1); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } @@ -28,7 +28,7 @@ enum cts_rc set_low_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW); gpio_set_level(GPIO_OUTPUT_TEST, 0); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } diff --git a/cts/gpio/th.c b/cts/gpio/th.c index 6c628b0ad5..54a083cef9 100644 --- a/cts/gpio/th.c +++ b/cts/gpio/th.c @@ -1,15 +1,15 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "common.h" -#include "watchdog.h" -#include "uart.h" +#include "cts_common.h" +#include "gpio.h" #include "task.h" #include "timer.h" +#include "uart.h" #include "watchdog.h" -#include "cts_common.h" enum cts_rc sync_test(void) { @@ -46,7 +46,7 @@ enum cts_rc read_high_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW); gpio_set_level(GPIO_OUTPUT_TEST, 1); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } @@ -54,14 +54,14 @@ enum cts_rc read_low_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW); gpio_set_level(GPIO_OUTPUT_TEST, 0); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } enum cts_rc od_read_high_test(void) { gpio_set_flags(GPIO_INPUT_TEST, GPIO_OUTPUT | GPIO_ODR_LOW); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } diff --git a/cts/hook/cts.testlist b/cts/hook/cts.testlist index 97b25575d4..75e1a11324 100644 --- a/cts/hook/cts.testlist +++ b/cts/hook/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/hook/dut.c b/cts/hook/dut.c index f3a52ddaf4..fc6187cade 100644 --- a/cts/hook/dut.c +++ b/cts/hook/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -88,8 +88,7 @@ static enum cts_rc test_ticks(void) msleep(1300); interval = tick_time[1].val - tick_time[0].val; - error_pct = (interval - HOOK_TICK_INTERVAL) * 100 / - HOOK_TICK_INTERVAL; + error_pct = (interval - HOOK_TICK_INTERVAL) * 100 / HOOK_TICK_INTERVAL; if (error_pct < -10 || 10 < error_pct) { CPRINTS("tick error=%d%% interval=%lld", error_pct, interval); return CTS_RC_FAILURE; @@ -142,8 +141,8 @@ static enum cts_rc test_deferred(void) /* Invalid deferred function */ deferred_call_count = 0; - if (hook_call_deferred(&invalid_deferred_func_data, 50 * MSEC) - == EC_SUCCESS) { + if (hook_call_deferred(&invalid_deferred_func_data, 50 * MSEC) == + EC_SUCCESS) { CPRINTL("non_deferred_func_data"); return CTS_RC_FAILURE; } diff --git a/cts/hook/th.c b/cts/hook/th.c deleted file mode 120000 index 41eab28462..0000000000 --- a/cts/hook/th.c +++ /dev/null @@ -1 +0,0 @@ -dut.c \ No newline at end of file diff --git a/cts/hook/th.c b/cts/hook/th.c new file mode 100644 index 0000000000..fc6187cade --- /dev/null +++ b/cts/hook/th.c @@ -0,0 +1,164 @@ +/* Copyright 2013 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Test hooks. + */ + +#include "common.h" +#include "console.h" +#include "cts_common.h" +#include "hooks.h" +#include "task.h" +#include "timer.h" +#include "util.h" +#include "watchdog.h" + +static int init_hook_count; +static int tick_hook_count; +static int tick2_hook_count; +static int tick_count_seen_by_tick2; +static timestamp_t tick_time[2]; +static int second_hook_count; +static timestamp_t second_time[2]; +static int deferred_call_count; + +static void init_hook(void) +{ + init_hook_count++; +} +DECLARE_HOOK(HOOK_INIT, init_hook, HOOK_PRIO_DEFAULT); + +static void tick_hook(void) +{ + tick_hook_count++; + tick_time[0] = tick_time[1]; + tick_time[1] = get_time(); +} +DECLARE_HOOK(HOOK_TICK, tick_hook, HOOK_PRIO_DEFAULT); + +static void tick2_hook(void) +{ + tick2_hook_count++; + tick_count_seen_by_tick2 = tick_hook_count; +} +/* tick2_hook() prio means it should be called after tick_hook() */ +DECLARE_HOOK(HOOK_TICK, tick2_hook, HOOK_PRIO_DEFAULT + 1); + +static void second_hook(void) +{ + second_hook_count++; + second_time[0] = second_time[1]; + second_time[1] = get_time(); +} +DECLARE_HOOK(HOOK_SECOND, second_hook, HOOK_PRIO_DEFAULT); + +static void deferred_func(void) +{ + deferred_call_count++; +} +DECLARE_DEFERRED(deferred_func); + +static void invalid_deferred_func(void) +{ + deferred_call_count++; +} + +static const struct deferred_data invalid_deferred_func_data = { + invalid_deferred_func +}; + +static enum cts_rc test_init_hook(void) +{ + if (init_hook_count != 1) + return CTS_RC_FAILURE; + return CTS_RC_SUCCESS; +} + +static enum cts_rc test_ticks(void) +{ + int64_t interval; + int error_pct; + + /* + * HOOK_SECOND must have been fired at least once when HOOK + * task starts. We only need to wait for just more than a second + * to allow it fires for the second time. + */ + msleep(1300); + + interval = tick_time[1].val - tick_time[0].val; + error_pct = (interval - HOOK_TICK_INTERVAL) * 100 / HOOK_TICK_INTERVAL; + if (error_pct < -10 || 10 < error_pct) { + CPRINTS("tick error=%d%% interval=%lld", error_pct, interval); + return CTS_RC_FAILURE; + } + + interval = second_time[1].val - second_time[0].val; + error_pct = (interval - SECOND) * 100 / SECOND; + if (error_pct < -10 || 10 < error_pct) { + CPRINTS("second error=%d%% interval=%lld", error_pct, interval); + return CTS_RC_FAILURE; + } + + return CTS_RC_SUCCESS; +} + +static enum cts_rc test_priority(void) +{ + usleep(HOOK_TICK_INTERVAL); + if (tick_hook_count != tick2_hook_count) + return CTS_RC_FAILURE; + if (tick_hook_count != tick_count_seen_by_tick2) + return CTS_RC_FAILURE; + return CTS_RC_SUCCESS; +} + +static enum cts_rc test_deferred(void) +{ + deferred_call_count = 0; + hook_call_deferred(&deferred_func_data, 50 * MSEC); + if (deferred_call_count != 0) { + CPRINTL("deferred_call_count=%d", deferred_call_count); + return CTS_RC_FAILURE; + } + msleep(100); + if (deferred_call_count != 1) { + CPRINTL("deferred_call_count=%d", deferred_call_count); + return CTS_RC_FAILURE; + } + + /* Test cancellation */ + deferred_call_count = 0; + hook_call_deferred(&deferred_func_data, 50 * MSEC); + msleep(25); + hook_call_deferred(&deferred_func_data, -1); + msleep(75); + if (deferred_call_count != 0) { + CPRINTL("deferred_call_count=%d", deferred_call_count); + return CTS_RC_FAILURE; + } + + /* Invalid deferred function */ + deferred_call_count = 0; + if (hook_call_deferred(&invalid_deferred_func_data, 50 * MSEC) == + EC_SUCCESS) { + CPRINTL("non_deferred_func_data"); + return CTS_RC_FAILURE; + } + msleep(100); + if (deferred_call_count != 0) { + CPRINTL("deferred_call_count=%d", deferred_call_count); + return CTS_RC_FAILURE; + } + + return CTS_RC_SUCCESS; +} + +#include "cts_testlist.h" + +void cts_task(void) +{ + cts_main_loop(tests, "Hook"); + task_wait_event(-1); +} diff --git a/cts/i2c/cts.testlist b/cts/i2c/cts.testlist index 7b6461e84d..b52e247680 100644 --- a/cts/i2c/cts.testlist +++ b/cts/i2c/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/i2c/cts_i2c.h b/cts/i2c/cts_i2c.h index 2914d92a99..ae4aab9878 100644 --- a/cts/i2c/cts_i2c.h +++ b/cts/i2c/cts_i2c.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,9 +12,9 @@ enum cts_i2c_packets { READ32_OFF, }; -#define WRITE8_DATA 0x42 -#define WRITE16_DATA 0x1234 -#define WRITE32_DATA 0xDEADBEEF -#define READ8_DATA 0x23 -#define READ16_DATA 0xACED -#define READ32_DATA 0x01ABCDEF +#define WRITE8_DATA 0x42 +#define WRITE16_DATA 0x1234 +#define WRITE32_DATA 0xDEADBEEF +#define READ8_DATA 0x23 +#define READ16_DATA 0xACED +#define READ32_DATA 0x01ABCDEF diff --git a/cts/i2c/dut.c b/cts/i2c/dut.c index c7a3f9fccf..d2d721fdd6 100644 --- a/cts/i2c/dut.c +++ b/cts/i2c/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,24 +17,24 @@ enum cts_rc write8_test(void) { - if (i2c_write8(i2c_ports[0].port, TH_ADDR_FLAGS, - WRITE8_OFF, WRITE8_DATA)) + if (i2c_write8(i2c_ports[0].port, TH_ADDR_FLAGS, WRITE8_OFF, + WRITE8_DATA)) return CTS_RC_FAILURE; return CTS_RC_SUCCESS; } enum cts_rc write16_test(void) { - if (i2c_write16(i2c_ports[0].port, TH_ADDR_FLAGS, - WRITE16_OFF, WRITE16_DATA)) + if (i2c_write16(i2c_ports[0].port, TH_ADDR_FLAGS, WRITE16_OFF, + WRITE16_DATA)) return CTS_RC_FAILURE; return CTS_RC_SUCCESS; } enum cts_rc write32_test(void) { - if (i2c_write32(i2c_ports[0].port, TH_ADDR_FLAGS, - WRITE32_OFF, WRITE32_DATA)) + if (i2c_write32(i2c_ports[0].port, TH_ADDR_FLAGS, WRITE32_OFF, + WRITE32_DATA)) return CTS_RC_FAILURE; return CTS_RC_SUCCESS; } @@ -43,8 +43,7 @@ enum cts_rc read8_test(void) { int data; - if (i2c_read8(i2c_ports[0].port, TH_ADDR_FLAGS, - READ8_OFF, &data)) + if (i2c_read8(i2c_ports[0].port, TH_ADDR_FLAGS, READ8_OFF, &data)) return CTS_RC_FAILURE; if (data != READ8_DATA) { CPRINTL("Expecting 0x%x but read 0x%x", READ8_DATA, data); @@ -58,8 +57,7 @@ enum cts_rc read16_test(void) { int data; - if (i2c_read16(i2c_ports[0].port, TH_ADDR_FLAGS, - READ16_OFF, &data)) + if (i2c_read16(i2c_ports[0].port, TH_ADDR_FLAGS, READ16_OFF, &data)) return CTS_RC_FAILURE; if (data != READ16_DATA) { CPRINTL("Expecting 0x%x but read 0x%x", READ16_DATA, data); @@ -73,8 +71,7 @@ enum cts_rc read32_test(void) { int data; - if (i2c_read32(i2c_ports[0].port, TH_ADDR_FLAGS, - READ32_OFF, &data)) + if (i2c_read32(i2c_ports[0].port, TH_ADDR_FLAGS, READ32_OFF, &data)) return CTS_RC_FAILURE; if (data != READ32_DATA) { CPRINTL("Read 0x%x expecting 0x%x", data, READ32_DATA); @@ -84,7 +81,6 @@ enum cts_rc read32_test(void) return CTS_RC_SUCCESS; } - #include "cts_testlist.h" void cts_task(void) diff --git a/cts/i2c/th.c b/cts/i2c/th.c index 78035cb1b2..b613f2d25d 100644 --- a/cts/i2c/th.c +++ b/cts/i2c/th.c @@ -1,9 +1,8 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include #include "common.h" #include "cts_common.h" #include "cts_i2c.h" @@ -14,6 +13,8 @@ #include "uart.h" #include "watchdog.h" +#include + static uint8_t inbox[I2C_MAX_HOST_PACKET_SIZE + 2]; static char data_received; diff --git a/cts/interrupt/cts.testlist b/cts/interrupt/cts.testlist index 0fdaf6fca2..e48208d900 100644 --- a/cts/interrupt/cts.testlist +++ b/cts/interrupt/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/interrupt/dut.c b/cts/interrupt/dut.c index 3c83e5701f..15bba740f0 100644 --- a/cts/interrupt/dut.c +++ b/cts/interrupt/dut.c @@ -1,9 +1,8 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include #include "common.h" #include "cts_common.h" #include "gpio.h" @@ -12,6 +11,8 @@ #include "timer.h" #include "watchdog.h" +#include + static int got_interrupt; static int wake_me_up; static int state_index; @@ -66,7 +67,7 @@ void cts_irq2(enum gpio_signal signal) void clean_state(void) { - uint32_t *event; + atomic_t *event; interrupt_enable(); got_interrupt = 0; diff --git a/cts/interrupt/th.c b/cts/interrupt/th.c index 1639a1868c..ff9a3b303b 100644 --- a/cts/interrupt/th.c +++ b/cts/interrupt/th.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/meta/cts.testlist b/cts/meta/cts.testlist index 28ac7e325f..2d41848737 100644 --- a/cts/meta/cts.testlist +++ b/cts/meta/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/meta/dut.c b/cts/meta/dut.c index c321676aec..8880c7ba13 100644 --- a/cts/meta/dut.c +++ b/cts/meta/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/meta/th.c b/cts/meta/th.c index 57b2f492bd..ec7f061793 100644 --- a/cts/meta/th.c +++ b/cts/meta/th.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/mutex/cts.tasklist b/cts/mutex/cts.tasklist index 3387e1de09..ad0c75c601 100644 --- a/cts/mutex/cts.tasklist +++ b/cts/mutex/cts.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/mutex/cts.testlist b/cts/mutex/cts.testlist index 5b1cdb1dae..5cea62c079 100644 --- a/cts/mutex/cts.testlist +++ b/cts/mutex/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/mutex/dut.c b/cts/mutex/dut.c index 4fcea73fdf..c4778de957 100644 --- a/cts/mutex/dut.c +++ b/cts/mutex/dut.c @@ -1,13 +1,13 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. - * Copyright 2011 Google Inc. + * Copyright 2011 Google LLC * * Tasks for mutexes basic tests. */ -#include "console.h" #include "common.h" +#include "console.h" #include "cts_common.h" #include "task.h" #include "test_util.h" @@ -23,7 +23,7 @@ static struct mutex mtx; int mutex_random_task(void *unused) { - char letter = 'A'+(TASK_ID_MTX3A - task_get_current()); + char letter = 'A' + (TASK_ID_MTX3A - task_get_current()); /* wait to be activated */ while (1) { @@ -82,7 +82,8 @@ static enum cts_rc lock_unlock_test(void) /* --- Serialization to test simple contention --- */ ccprintf("Simple contention :\n"); /* lock the mutex from the other task */ - task_set_event(TASK_ID_MTX2, TASK_EVENT_WAKE, 1); + task_set_event(TASK_ID_MTX2, TASK_EVENT_WAKE); + task_wait_event(0); /* block on the mutex */ ccprintf("MTX1: blocking...\n"); mutex_lock(&mtx); diff --git a/cts/mutex/th.c b/cts/mutex/th.c index 4fcea73fdf..c4778de957 100644 --- a/cts/mutex/th.c +++ b/cts/mutex/th.c @@ -1,13 +1,13 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. - * Copyright 2011 Google Inc. + * Copyright 2011 Google LLC * * Tasks for mutexes basic tests. */ -#include "console.h" #include "common.h" +#include "console.h" #include "cts_common.h" #include "task.h" #include "test_util.h" @@ -23,7 +23,7 @@ static struct mutex mtx; int mutex_random_task(void *unused) { - char letter = 'A'+(TASK_ID_MTX3A - task_get_current()); + char letter = 'A' + (TASK_ID_MTX3A - task_get_current()); /* wait to be activated */ while (1) { @@ -82,7 +82,8 @@ static enum cts_rc lock_unlock_test(void) /* --- Serialization to test simple contention --- */ ccprintf("Simple contention :\n"); /* lock the mutex from the other task */ - task_set_event(TASK_ID_MTX2, TASK_EVENT_WAKE, 1); + task_set_event(TASK_ID_MTX2, TASK_EVENT_WAKE); + task_wait_event(0); /* block on the mutex */ ccprintf("MTX1: blocking...\n"); mutex_lock(&mtx); diff --git a/cts/task/cts.tasklist b/cts/task/cts.tasklist index 6477d74c2c..1adbf211ec 100644 --- a/cts/task/cts.tasklist +++ b/cts/task/cts.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/task/cts.testlist b/cts/task/cts.testlist index c4b7bc3231..3ad8e33928 100644 --- a/cts/task/cts.testlist +++ b/cts/task/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/task/dut.c b/cts/task/dut.c index 7297b7de96..257809b4b8 100644 --- a/cts/task/dut.c +++ b/cts/task/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -34,10 +34,13 @@ void task_abc(void *data) while (1) { wake_count[id]++; - if (id == 2 && wake_count[id] == repeat_count) - task_set_event(TASK_ID_CTS, TASK_EVENT_WAKE, 1); - else - task_set_event(next, TASK_EVENT_WAKE, 1); + if (id == 2 && wake_count[id] == repeat_count) { + task_set_event(TASK_ID_CTS, TASK_EVENT_WAKE); + task_wait_event(0); + } else { + task_set_event(next, TASK_EVENT_WAKE); + task_wait_event(0); + } } } @@ -67,15 +70,15 @@ enum cts_rc test_task_switch(void) } if (wake_count[0] != repeat_count || wake_count[1] != repeat_count) { - CPRINTS("Unexpected counter values: %d %d %d", - wake_count[0], wake_count[1], wake_count[2]); + CPRINTS("Unexpected counter values: %d %d %d", wake_count[0], + wake_count[1], wake_count[2]); return CTS_RC_FAILURE; } /* TODO: Verify no tasks are ready, no events are pending. */ - if (*task_get_event_bitmap(TASK_ID_A) - || *task_get_event_bitmap(TASK_ID_B) - || *task_get_event_bitmap(TASK_ID_C)) { + if (*task_get_event_bitmap(TASK_ID_A) || + *task_get_event_bitmap(TASK_ID_B) || + *task_get_event_bitmap(TASK_ID_C)) { CPRINTS("Events are pending"); return CTS_RC_FAILURE; } @@ -99,17 +102,17 @@ enum cts_rc test_task_priority(void) return CTS_RC_FAILURE; } - if (wake_count[0] != repeat_count - 1 - || wake_count[1] != repeat_count - 1) { - CPRINTS("Unexpected counter values: %d %d %d", - wake_count[0], wake_count[1], wake_count[2]); + if (wake_count[0] != repeat_count - 1 || + wake_count[1] != repeat_count - 1) { + CPRINTS("Unexpected counter values: %d %d %d", wake_count[0], + wake_count[1], wake_count[2]); return CTS_RC_FAILURE; } /* TODO: Verify no tasks are ready, no events are pending. */ - if (*task_get_event_bitmap(TASK_ID_A) - || *task_get_event_bitmap(TASK_ID_B) - || *task_get_event_bitmap(TASK_ID_C)) { + if (*task_get_event_bitmap(TASK_ID_A) || + *task_get_event_bitmap(TASK_ID_B) || + *task_get_event_bitmap(TASK_ID_C)) { CPRINTS("Events are pending"); return CTS_RC_FAILURE; } diff --git a/cts/task/th.c b/cts/task/th.c deleted file mode 120000 index 41eab28462..0000000000 --- a/cts/task/th.c +++ /dev/null @@ -1 +0,0 @@ -dut.c \ No newline at end of file diff --git a/cts/task/th.c b/cts/task/th.c new file mode 100644 index 0000000000..257809b4b8 --- /dev/null +++ b/cts/task/th.c @@ -0,0 +1,144 @@ +/* Copyright 2013 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Tasks for scheduling test. + */ + +#include "common.h" +#include "cts_common.h" +#include "task.h" +#include "timer.h" + +static int repeat_count; +static int wake_count[3]; + +void clean_state(void) +{ + wake_count[0] = wake_count[1] = wake_count[2] = 0; +} + +void task_abc(void *data) +{ + int task_id = task_get_current(); + int id = task_id - TASK_ID_A; + task_id_t next = task_id + 1; + + if (next > TASK_ID_C) + next = TASK_ID_A; + + task_wait_event(-1); + + CPRINTS("%c Starting", 'A' + id); + cflush(); + + while (1) { + wake_count[id]++; + if (id == 2 && wake_count[id] == repeat_count) { + task_set_event(TASK_ID_CTS, TASK_EVENT_WAKE); + task_wait_event(0); + } else { + task_set_event(next, TASK_EVENT_WAKE); + task_wait_event(0); + } + } +} + +void task_tick(void *data) +{ + task_wait_event(-1); + ccprintf("\n[starting Task T]\n"); + + /* Wake up every tick */ + while (1) + /* Wait for timer interrupt message */ + usleep(3000); +} + +enum cts_rc test_task_switch(void) +{ + uint32_t event; + + repeat_count = 3000; + + task_wake(TASK_ID_A); + event = task_wait_event(5 * SECOND); + + if (event != TASK_EVENT_WAKE) { + CPRINTS("Woken up by unexpected event: 0x%08x", event); + return CTS_RC_FAILURE; + } + + if (wake_count[0] != repeat_count || wake_count[1] != repeat_count) { + CPRINTS("Unexpected counter values: %d %d %d", wake_count[0], + wake_count[1], wake_count[2]); + return CTS_RC_FAILURE; + } + + /* TODO: Verify no tasks are ready, no events are pending. */ + if (*task_get_event_bitmap(TASK_ID_A) || + *task_get_event_bitmap(TASK_ID_B) || + *task_get_event_bitmap(TASK_ID_C)) { + CPRINTS("Events are pending"); + return CTS_RC_FAILURE; + } + + return CTS_RC_SUCCESS; +} + +enum cts_rc test_task_priority(void) +{ + uint32_t event; + + repeat_count = 2; + + task_wake(TASK_ID_A); + task_wake(TASK_ID_C); + + event = task_wait_event(5 * SECOND); + + if (event != TASK_EVENT_WAKE) { + CPRINTS("Woken up by unexpected event: 0x%08x", event); + return CTS_RC_FAILURE; + } + + if (wake_count[0] != repeat_count - 1 || + wake_count[1] != repeat_count - 1) { + CPRINTS("Unexpected counter values: %d %d %d", wake_count[0], + wake_count[1], wake_count[2]); + return CTS_RC_FAILURE; + } + + /* TODO: Verify no tasks are ready, no events are pending. */ + if (*task_get_event_bitmap(TASK_ID_A) || + *task_get_event_bitmap(TASK_ID_B) || + *task_get_event_bitmap(TASK_ID_C)) { + CPRINTS("Events are pending"); + return CTS_RC_FAILURE; + } + + return CTS_RC_SUCCESS; +} + +static void recurse(int x) +{ + CPRINTS("+%d", x); + msleep(1); + recurse(x + 1); + CPRINTS("-%d", x); +} + +enum cts_rc test_stack_overflow(void) +{ + recurse(0); + return CTS_RC_FAILURE; +} + +#include "cts_testlist.h" + +void cts_task(void) +{ + task_wake(TASK_ID_TICK); + cts_main_loop(tests, "Task"); + task_wait_event(-1); +} diff --git a/cts/timer/cts.testlist b/cts/timer/cts.testlist index 9b5da0d6c9..6567757ced 100644 --- a/cts/timer/cts.testlist +++ b/cts/timer/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/timer/dut.c b/cts/timer/dut.c index 96d7c5a3cf..9f94b9a398 100644 --- a/cts/timer/dut.c +++ b/cts/timer/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/timer/th.c b/cts/timer/th.c index e82cac71ab..e301ce0e38 100644 --- a/cts/timer/th.c +++ b/cts/timer/th.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/docs/ap-ec-comm.md b/docs/ap-ec-comm.md index a65c419171..6f1292bcaf 100644 --- a/docs/ap-ec-comm.md +++ b/docs/ap-ec-comm.md @@ -9,11 +9,12 @@ by issuing *host commands*, which are identified by a command ID and version number, and then reading a response. When a host command is issued through `ectool`, two or three software components are involved: -* `ectool`, the user-space binary, -* normally the `cros-ec` Kernel driver, and -* the code on the EC itself. This can be thought of as two parts: - * a chip-specific driver for the appropriate transport, and - * the generic host command handling code (mostly in the [host command task]). +* `ectool`, the user-space binary, +* normally the `cros-ec` Kernel driver, and +* the code on the EC itself. This can be thought of as two parts: + * a chip-specific driver for the appropriate transport, and + * the generic host command handling code (mostly in the + [host command task]). We'll go into detail of each of these, as well as the traffic on the wire, in the following sections. @@ -24,6 +25,21 @@ the following sections. providing a CLI. They call one of the transport-specific `ec_command` implementations in the `util/comm-*.c` files to send and receive from the EC. +#### Stress test + +The `ectool stress` command sends a large amount of host commands continuously +to the EC. This verifies that the EC can respond to all commands received +without timeouts or communication errors. + +It will log the time elapsed for every iteration of sending 10000 host commands +with the time that it took to send them. + +Example output of stress test is: +`Update: attempt 10000 round 1 | took 205 seconds` + +Killing the process will result in displaying the total runtime and failures +that happened during it. + ### EC kernel driver In most cases, `ectool` communicates via the [`cros-ec` Kernel driver], rather @@ -39,25 +55,25 @@ to the Linux [Industrial I/O] system. Now we come to the protocol itself. All transactions take this general form: -* Host writes the request packet, consisting of: - * a transport-specific header; - * a `struct ec_host_request` containing the command ID, data length, and a - checksum; and - * zero or more bytes of parameters for the command, the format of which - depends on the command. -* Host reads the response to its request, consisting of: - * a transport-specific header; - * a `struct ec_host_response` containing the result code, data length, and a - checksum; and - * zero or more bytes of response from the command, again with a - command-specific format. +* Host writes the request packet, consisting of: + * a transport-specific header; + * a `struct ec_host_request` containing the command ID, data length, and a + checksum; and + * zero or more bytes of parameters for the command, the format of which + depends on the command. +* Host reads the response to its request, consisting of: + * a transport-specific header; + * a `struct ec_host_response` containing the result code, data length, and + a checksum; and + * zero or more bytes of response from the command, again with a + command-specific format. ### On the EC The host packet is received on the EC by some chip-specific code which checks -its transport-specific header, then passes it on to the common host command code, -starting at `host_packet_receive`. The common code validates the packet and -then sends it on to the handler function (annotated with the +its transport-specific header, then passes it on to the common host command +code, starting at `host_packet_receive`. The common code validates the packet +and then sends it on to the handler function (annotated with the `DECLARE_HOST_COMMAND` macro), which runs in the `HOSTCMD` task. The handler can set a response by modifying its arguments struct, which is sent back to the host via the chip-specific code. @@ -74,8 +90,8 @@ of the overarching protocol, and versions of individual commands. ### Protocol versions There have been three protocol versions so far, and this document describes -version 3. Version 1 was superseded by 2 before it shipped, so no devices use -it anymore. Version 2 is generally deprecated, but you might still encounter it +version 3. Version 1 was superseded by 2 before it shipped, so no devices use it +anymore. Version 2 is generally deprecated, but you might still encounter it occasionally. Which version is in use can be determined using the `EC_CMD_GET_PROTOCOL_INFO` @@ -90,6 +106,41 @@ they're being called with. Different versions of a command may have different parameter or response formats. `EC_CMD_GET_CMD_VERSIONS` returns the versions of the given command supported by the EC. These version numbers start at 0. +## Tracing + +Command tracing can be done on the EC console (`hc debug` command) and/or in +the kernel: +``` +echo 1 > /sys/kernel/debug/tracing/events/cros_ec/enable +cat /sys/kernel/debug/tracing/trace + +369.416372: cros_ec_request_start: version: 0, command: EC_CMD_USB_PD_POWER_INFO +369.420528: cros_ec_request_done: version: 0, command: EC_CMD_USB_PD_POWER_INFO, ec result: EC_RES_SUCCESS, retval: 16 +369.420529: cros_ec_request_start: version: 0, command: EC_CMD_USB_PD_DISCOVERY +369.421383: cros_ec_request_done: version: 0, command: EC_CMD_USB_PD_DISCOVERY, ec result: EC_RES_SUCCESS, retval: 5 +``` + +## API synchronization + +EC, coreboot, user space (`platform2)` and kernel needs to access the same +information contained in `ec_commands.h`. + +* Coreboot regularly update [ec_commands.h]. +* User space/depthcharge use `ec_commands.h` installed by + `chromeos-base/chromeos-ec-headers` package. +* Kernel `ec_commands.h` - named + `./include/linux/platform_data/cros_ec_commands.h` - is not a direct +copy. New commands and options are added on a need-to-know basis +alongside the kernel code that uses these commands. + +A copy of `ec_commands.h`, matching kernel standard is auto-generated at +`/build/kernel/include/linux/mfd/cros_ec_commands.h` when +`make build_cros_ec_commands` or `make buildall` is run. (It is far from +perfect, since the kernel include file has not been updated with `clang-format` as +`ec_commands.h` has been). Copy the necessary changes from that file to +`include/linux/platform_data/cros_ec_commands.h` and push the changes upstream +first following the [upstream instructions]. + ## Transport-specific details Although the command and response formats are the same across all transports, @@ -128,15 +179,14 @@ embedded controllers either aren't fast enough or don't have any support for hardware flow-control. It works like this: When the AP sends a byte to the EC, if the EC doesn't have a -response queued up in advance, a default byte is returned. The EC -preconfigures that default response byte to indicate its status (ready, busy, -waiting for more input, etc.). Once the AP has sent a complete command message, -it continues clocking bytes to the EC (which the EC ignores) and just looks at -the response byte that comes back. Once the EC has parsed the AP's command and -is ready to reply, it sends a "start of frame" byte, followed by the actual -response. The AP continues to read and ignore bytes from the EC until it sees -the start of frame byte, and then it knows that the EC's response is starting -with the next byte. +response queued up in advance, a default byte is returned. The EC preconfigures +that default response byte to indicate its status (ready, busy, waiting for more +input, etc.). Once the AP has sent a complete command message, it continues +clocking bytes to the EC (which the EC ignores) and just looks at the response +byte that comes back. Once the EC has parsed the AP's command and is ready to +reply, it sends a "start of frame" byte, followed by the actual response. The AP +continues to read and ignore bytes from the EC until it sees the start of frame +byte, and then it knows that the EC's response is starting with the next byte. Once the response packet has been read, any additional reads should return `EC_SPI_PAST_END`. @@ -146,8 +196,9 @@ Once the response packet has been read, any additional reads should return The EC should set `EC_LPC_STATUS_PROCESSING` in its command status register after receiving a host packet and before it has a response ready. - [`cros-ec` Kernel driver]: https://chromium.googlesource.com/chromiumos/third_party/kernel/+/refs/heads/chromeos-4.19/drivers/mfd/cros_ec_dev.c [Industrial I/O]: https://www.kernel.org/doc/html/v4.14/driver-api/iio/index.html -[host command task]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/common/host_command.c +[host command task]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/common/host_command.c [Transport-specific details]: #Transport_specific-details +[ec_commands.h]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/coreboot/src/ec/google/chromeec/ec_commands.h +[upstream instructions]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/kernel_development.md#Upstream-development. diff --git a/docs/case_closed_debugging.md b/docs/case_closed_debugging.md index 05373f1de9..8310970652 100644 --- a/docs/case_closed_debugging.md +++ b/docs/case_closed_debugging.md @@ -1,2 +1,2 @@ -The has been moved into a [different -branch](https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md) +The has been moved into a +[different branch](https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md) diff --git a/docs/case_closed_debugging_cr50.md b/docs/case_closed_debugging_cr50.md index 6eb622cc37..ac518c0153 100644 --- a/docs/case_closed_debugging_cr50.md +++ b/docs/case_closed_debugging_cr50.md @@ -1,2 +1,2 @@ -The has been moved into a [different -branch](https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md) +The has been moved into a +[different branch](https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md) diff --git a/docs/ccd_howtos.md b/docs/ccd_howtos.md index 624253d22c..44deecd16d 100644 --- a/docs/ccd_howtos.md +++ b/docs/ccd_howtos.md @@ -1,2 +1,2 @@ -The has been moved into a [different -branch](https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/ccd_howtos.md) +The has been moved into a +[different branch](https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/ccd_howtos.md) diff --git a/docs/chromeos-ec-firmware-test-requirements.md b/docs/chromeos-ec-firmware-test-requirements.md new file mode 100644 index 0000000000..721021275a --- /dev/null +++ b/docs/chromeos-ec-firmware-test-requirements.md @@ -0,0 +1,121 @@ +# ChromeOS EC Firmware Code Test Requirements + +[TOC] + +## Overview + +The ChromeOS EC firmware requires that all C source and header file code changes +include tests covering at least 90% of any new or changed lines of code. A +non-blocking warning comment is posted on CLs that do not exceed 95% coverage +This change is in effect as of 2023-01-19. + +The Gerrit commit-queue enforces the coverage requirement with the +`firmware-zephyr-cov-cq` builder. + +## Rationale + +Starting 2H’22, all new Chromebook projects use the Zephyr RTOS as the +foundation for the ChromeOS EC firmware. As part of the switch to Zephyr RTOS, +Google wrote unit and integration tests to verify functionality of the EC +firmware. These tests run directly on your development system using the +native_posix environment and do not require any Chromebook hardware. + +These tests improve the quality of the EC firmware, reducing the number of EC +crashes and bugs found on shipping Chromebooks. + +The ChromeOS EC firmware requires that all projects based on the Zephyr RTOS +achieve code coverage of 90% or better. + +A Gitlab project creates and publishes the code coverage reports for the +Zephyr EC projects. The latest results are available on the Gitlab [Jobs page]. +Refer to the [Gitlab CI] documentation for implementation details. + +## Resources for writing tests + +* The [Zephyr Testing] documentation in the ChromeOS EC firmware provides the + most up-to-date information for writing tests specifically for the ChromeOS EC + firmware. + +* [Zephyr Test Framework] documentation in the Zephyr Project provides general + information about the test framework used by Zephyr RTOS. + +### Testing project specific code + +* The board + +### Generating coverage reports + +* [Zephyr ztest code coverage] provides instructions for generating code coverage +reports locally on your machine. + +* [Code Coverage in CQ] provides details for viewing the coverage information + directly from Gerrit or by using Google's code search tool. + +### Bypassing the code coverage requirement + +In limited cases, you may amend your commit message to include the +`LOW_COVERAGE_REASON` tag. This tag bypasses the code coverage requirement +enforced by Gerrit. Simply add the tag followed by a description to justify +bypassing code coverage. You must include a reference to a bug (in the form +`b:1234567` or `b/1234567`) that tracks whatever issue is impeding coverage. + +``` +LOW_COVERAGE_REASON=no emulator for the ANX7483 exists b/248086547 +``` + +Permissible reasons for bypassing the code coverage requirements include: + +* Fixing a high-priority bug that blocks a release or some other milestone. + +* Fixing a bug in an existing driver that is currently untested. + +* Modifying on-chip EC peripheral drivers. See the [Known Issues](#known_issues) + section below for details. + +When bypassing code coverage, please open a bug to track the work required to +create tests. + +Reviewers may reject your low coverage reason and request that you update or add +tests for your change. + +## Exceptions to code coverage + +### Legacy EC code + +Zephyr EC projects share large portions of the legacy code found under the +[`platform/ec`] repository. The code coverage requirements apply to the shared +code, with exceptions for the following directories: + +* [`platform/ec/baseboard`] +* [`platform/ec/board`] +* [`platform/ec/chip`] + +### Known issues + +There are no tests for the chip specific code found under the +[`platform/ec/zephyr/drivers`] directory. Due to include file conflicts, it is +not currently known how to test these drivers. + +### False positives + +The coverage tool may falsely mark a line of code as executable but the line of +code is not reachable. An example could be a switch statement, but the default +label is not reachable. In these cases add a comment using exclusion markers, +`LCOV_EXCL_*`, to the file. See the [geninfo manpage] for more information. + +Do not use exclusion markers to bypass executable code or to avoid writing tests +for difficult to reach code. + + +[`platform/ec/baseboard`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/baseboard +[`platform/ec/board`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/board +[`platform/ec/chip`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/chip +[`platform/ec/zephyr/drivers`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/drivers +[Jobs page]: https://gitlab.com/zephyr-ec/ec/-/jobs/ +[Gitlab CI]: ./gitlab.md +[Zephyr Testing]: ./zephyr/ztest.md +[Zephyr Test Framework]: https://docs.zephyrproject.org/latest/develop/test/ztest.html +[Zephyr ztest code coverage]: ./code_coverage.md#Zephyr-ztest-code-coverage +[Code Coverage in CQ]: ./code_coverage.md#code-coverage-in-cq +[`platform/ec`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/ +[geninfo manpage]: https://manpages.debian.org/unstable/lcov/geninfo.1.en.html diff --git a/docs/code_coverage.md b/docs/code_coverage.md index 458d87b7c5..0683dbe401 100644 --- a/docs/code_coverage.md +++ b/docs/code_coverage.md @@ -5,10 +5,16 @@ tests in the EC codebase. [TOC] +## Test Coverage Requirements + +All changes to the EC code base require you include tests covering at least 80% +of any new or changed lines of code. Refer to the [ChromeOS EC Firmware Test +Requirements] for details. + ## Availability -Code coverage is only available for host-based unit tests, as opposed to -manual tests that run on target hardware. +Code coverage is only available for host-based unit tests, as opposed to manual +tests that run on target hardware. ## Building for code coverage @@ -23,12 +29,131 @@ data into a code coverage report using the `lcov` and `genhtml` tools. The coverage report top-level page is `build/coverage/coverage_rpt/index.html`. +To get a report for one specific board's coverage run these commands: + +``` +BOARD=eldrid +make -j$(nproc) build/coverage/initial-${BOARD}.info test-coverage +# Merge board coverage and test coverage +lcov -o build/coverage/${BOARD}_merged.info --rc lcov_branch_coverage=1 \ + -a build/coverage/initial-${BOARD}.info -a build/coverage/lcov.info +# Filter out some unhelpful paths +lcov -o build/coverage/${BOARD}_filtered.info --rc lcov_branch_coverage=1 \ + -r build/coverage/${BOARD}_merged.info ${PWD}'/third_party/**' \ + ${PWD}'/build/**' '/usr/include/**' '/usr/lib/**' '${PWD}/test/**' \ + ${PWD}'/private/fingerprint/*/mcutest/**' +# Restrict to only files used by the board +grep "SF:" "build/coverage/initial-${BOARD}.info" | sort -u | \ + sed -e 's|^SF:||' | xargs lcov --rc lcov_branch_coverage=1 \ + -o build/coverage/${BOARD}_final.info \ + -e build/coverage/${BOARD}_filtered.info +# Generate HTML +genhtml --branch-coverage -q -o build/coverage/${BOARD}_rpt \ + -t "${BOARD} coverage" -s build/coverage/${BOARD}_final.info +``` + ### Noise in the build output When building for code coverage, you may see multiple warnings of the form -`geninfo: WARNING: no data found for /mnt/host/source/src/platform/ec/core/host/cpu.h` -and -`genhtml: WARNING: function data mismatch at /mnt/host/source/src/platform/ec/common/math_util.c:134` +`geninfo: WARNING: no data found for +/mnt/host/source/src/platform/ec/core/host/cpu.h` and `genhtml: WARNING: +function data mismatch at +/mnt/host/source/src/platform/ec/common/math_util.c:134` These warnings can be ignored. (FYI, the "function data mismatch" warnings appear to be caused in part by using relative paths instead of absolute paths.) + +## Zephyr ztest code coverage + +To build the Zephyr unit tests for code coverage run: + +`./twister -v -i --coverage -p native_posix -p unit_testing` + +The coverage report top-level page is +`twister-out/coverage/index.html`. + +However you probably want to merge that with a single board's coverage report +also, so that you can include code that is not part of any test as well. + +``` +zmake build --coverage herobrine +./twister -v -i --coverage -p native_posix -p unit_testing +genhtml -q -s --branch-coverage -o build/zephyr/coverage_rpt/ \ + twister-out/coverage.info build/zephyr/herobrine/output/zephyr.info +``` + +The coverage report top-level page is +`build/zephyr/coverage_rpt/index.html`. + +For coverage report for a single test you can run: `./twister -v -i --coverage +-p native_posix -p unit_testing -s /` + +Example of running test `tasks.default` from `zephyr/test/tasks/testcase.yaml`: +`./twister -v -i --coverage -p native_posix -p unit_testing -s +tasks/tasks.default` + +## Code Coverage in CQ + +There are several ways to see the code coverage without running the tests +locally, depending on what information you want to see. Many of the links +below are only available to Googlers or TVCs with google.com accounts. + +### Code search + +To see the coverage of each directory, visit +http://cs/chromeos_public/src/platform/ec/ and turn on the "Directory Coverage" +layer. The denominator for the percentage covered is not clear, so these +numbers are really only useful if you are looking in very general terms. I.e. +zephyr is covered better than common. Don't get too fixated on the specific +percent shown. The results are also the last 7 days of builds combined, so there +may be some odd results if the code has changed greatly in the last week. + +![Directory coverage screenshot](images/dir_coverage.png) + +The coverage of files is much more useful. If you are about to write a test +and not sure what to focus on, you can look at the uncovered lines in code +search. Visit [a file](http://cs/chromeos_public/src/platform/ec/common/mkbp_event.c) +in code search and make sure the "File Coverage" layer is enabled. Lines that +are not covered by any test are in red, tested lines are in green, and uncolored +lines were not built at all in any board or test. + +![File coverage screenshot](images/file_coverage.png) + +### Presubmit + +Every gerrit cl, if you did a dry-run or full run of the CQ will have coverage +results. They are slightly difficult to get to, but are very useful. + +On the "Checks" tab, find the build "firmware-zephyr-cov-cq" and open it. + +![Gerrit screenshot](images/gerrit_coverage_links.png) + +On the LUCI page, expand the "test firmware" step and click on "response". That +will show you a very basic summary of the coverage. + +![LUCI screenshot test firmware](images/test_firmware.png) + +For a detailed report, you can download the coverage report. Expand "try to +upload artifacts", then "upload artifacts", and click on "gs upload dir". + +![LUCI screenshot artifacts](images/artifacts.png) + +From there, click on the download icon for the html.tbz2 file, and untar it +locally. Open lcov_rpt/index.html to view your results. + +![GCS screenshot](images/download_html.png) + +### Post-submit + +If you are interested in the state of the world, not a specific CL, and the +coverage info in Code Search is not sufficient, you can download the coverage +report from the post-submit CQ build. + +Visit https://ci.chromium.org/p/chromeos/builders/postsubmit/firmware-zephyr-cov-postsubmit +and click on the latest successful build. + +![LUCI post-submit screenshot](images/postsubmit.png) + +From there, it is exactly the same steps as above to get to the artifacts. + +[ChromeOS EC Firmware Test Requirements]: ./chromeos-ec-firmware-test-requirements.md diff --git a/docs/code_reviews.md b/docs/code_reviews.md index 8bda5fe31a..a8e77c3fd8 100644 --- a/docs/code_reviews.md +++ b/docs/code_reviews.md @@ -44,11 +44,11 @@ Add your name to the [list of reviewers][1]. ## Reference -* [Chrome OS firmware review guidelines][2] -* [Coreboot Gerrit Guidelines][3] -* [Google small CL guidelines][5] +* [Chrome OS firmware review guidelines][2] +* [Coreboot Gerrit Guidelines][3] +* [Google small CL guidelines][5] [1]: http://google3/chrome/crosinfra/gwsq/ec_reviewers -[2]: http://chromium.googlesource.com/chromiumos/docs/+/master/firmware_code_reviews.md +[2]: http://chromium.googlesource.com/chromiumos/docs/+/HEAD/firmware_code_reviews.md [3]: https://doc.coreboot.org/getting_started/gerrit_guidelines.html [5]: https://google.github.io/eng-practices/review/developer/small-cls.html diff --git a/docs/configuration/ap_power_sequencing.md b/docs/configuration/ap_power_sequencing.md index 2b78592e57..ba9fc89f29 100644 --- a/docs/configuration/ap_power_sequencing.md +++ b/docs/configuration/ap_power_sequencing.md @@ -3,19 +3,19 @@ This section details the configuration related to managing the system power states (G3, S5, S3, S0, S0iX, etc). This includes the following tasks: -- Selecting the AP chipset type. -- Configure output GPIOs that enable voltage rails. -- Configure input GPIOs that monitor the voltage rail status (power good - signals). -- Configure input GPIOs that monitor the AP sleep states. -- Pass through power sequencing signals from the board to the AP, often with - delays or other sequencing control. +- Selecting the AP chipset type. +- Configure output GPIOs that enable voltage rails. +- Configure input GPIOs that monitor the voltage rail status (power good + signals). +- Configure input GPIOs that monitor the AP sleep states. +- Pass through power sequencing signals from the board to the AP, often with + delays or other sequencing control. ## Config options The AP chipset options are grouped together in [config.h]. Select exactly one of the available AP chipset options (e.g. `CONFIG_CHIPSET_APOLLOLAKE`, -`CONFIG_CHIPSET_BRASWELL`, etc). If the AP chipset support is not available, +`CONFIG_CHIPSET_COMETLAKE`, etc). If the AP chipset support is not available, select `CONFIG_CHIPSET_ECDRIVEN` to enable basic support for handling S3 and S0 power states. @@ -28,8 +28,8 @@ particular, the `CONFIG_POWER_BUTTON`, and `CONFIG_POWER_COMMON` should be defined. The `CONFIG_BRINGUP` option is especially useful option during the initial power -up of a new board. This option is discussed in more detail in the [Testing and -Debugging](#Testing-and-Debugging) section. +up of a new board. This option is discussed in more detail in the +[Testing and Debugging](#Testing-and-Debugging) section. ## Feature Parameters @@ -54,15 +54,16 @@ GPIO(EN_PP5000, PIN(A, 4), GPIO_OUT_LOW) For boards with an x86 AP, the following signals can be connected between the EC and AP/PCH. Create `GPIO()` entries for any signals used on your board. -- `GPIO_PCH_PWRBTN_L` - Output from the EC that proxies the status of the EC - input `GPIO_POWER_BUTTON_L` (driven by the H1). Only used when - `CONFIG_POWER_BUTTON_X86` is defined. -- `GPIO_PCH_RSMRST_L` - Output from the EC that proxies the status of the EC - input `GPIO_RSMRST_L_PGOOD` (driven by the PMIC or voltage regulators on the - board). -- `GPIO_PCH_SYS_PWROK` - Output from the EC that indicates when the system power - is good and the AP can power up. -- `GPIO_PCH_WAKE_L` - Output from the EC, driven low when there is a wake event. +- `GPIO_PCH_PWRBTN_L` - Output from the EC that proxies the status of the EC + input `GPIO_POWER_BUTTON_L` (driven by the H1). Only used when + `CONFIG_POWER_BUTTON_X86` is defined. +- `GPIO_PCH_RSMRST_L` - Output from the EC that proxies the status of the EC + input `GPIO_RSMRST_L_PGOOD` (driven by the PMIC or voltage regulators on the + board). +- `GPIO_PCH_SYS_PWROK` - Output from the EC that indicates when the system + power is good and the AP can power up. +- `GPIO_PCH_WAKE_L` - Output from the EC, driven low when there is a wake + event. ### Power Signal Interrupts @@ -85,15 +86,15 @@ macros. ## Data structures -- `const struct power_signal_info power_signal_list[]` - This array defines the - signals from the AP and from the power subsystem on the board that control the - power state. For some Intel chipsets, including Apollo Lake and Ice Lake, this - power signal list is already defined by the corresponding chipset file under - the `./power` directory. +- `const struct power_signal_info power_signal_list[]` - This array defines + the signals from the AP and from the power subsystem on the board that + control the power state. For some Intel chipsets, including Apollo Lake and + Ice Lake, this power signal list is already defined by the corresponding + chipset file under the `./power` directory. ## Tasks -The `CHIPSET` task monitors and handles the power state changes. This task +The `CHIPSET` task monitors and handles the power state changes. This task should always be enabled with a priority higher than the `CHARGER` task, but lower than the `HOSTCMD` and `CONSOLE` tasks. @@ -178,8 +179,8 @@ RTC: 0x000067bf (26559.00 s) [9.128640 power state 7 = S3->S0, in 0x003f] ``` -This example shows successful power on of the AP as the AP transitions from the G3 -state all the way to the S0 state. +This example shows successful power on of the AP as the AP transitions from the +G3 state all the way to the S0 state. The console messages shown in brackets `[]` include a timestamp. This timestamp records when the corresponding console message was printed. @@ -192,7 +193,7 @@ signal changes shown on the console to be out of order with respect to the other EC messages. The power signal changes include a timestamp to help you correlate when the -actual power signal changed compared to other messages. From the example above, +actual power signal changed compared to other messages. From the example above, the first power signal change recorded is the `DSW_PWROK` signal transitioning from 0 to 1, and this is recorded at timestamp `6.807298`. Using the regular EC console timestamp, you can reconstruct the real power sequence to look like the @@ -246,7 +247,6 @@ RTC: 0x000067bf (26559.00 s) [9.128640 power state 7 = S3->S0, in 0x003f] ``` - *TODO ([b/147808790](http://issuetracker.google.com/147808790)) Add documentation specific to each x86 processor type.* diff --git a/docs/configuration/cbi.md b/docs/configuration/cbi.md index f285e8a8c2..f89ee78454 100644 --- a/docs/configuration/cbi.md +++ b/docs/configuration/cbi.md @@ -8,13 +8,13 @@ before enabling CBI. Add the following config options to `baseboard.h` or `board.h`. -- `CONFIG_BOARD_VERSION_CBI` -- `CONFIG_CROS_BOARD_INFO` +- `CONFIG_BOARD_VERSION_CBI` +- `CONFIG_CBI_EEPROM` ## Feature Parameters -- `I2C_ADDR_EEPROM_FLAGS <7-bit addr>` - Defines the 7-bit slave address for the - EEPROM containing CBI. +- `I2C_ADDR_EEPROM_FLAGS <7-bit addr>` - Defines the 7-bit slave address for + the EEPROM containing CBI. ## GPIOs and Alternate Pins @@ -31,8 +31,9 @@ None required by this feature. ## Testing and Debugging -Refer to the [I2C debugging information] to verify communication with the CBI EEPROM. +Refer to the [I2C debugging information] to verify communication with the CBI +EEPROM. -[CBI]: https://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/cros_board_info.md +[CBI]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/cros_board_info.md [I2C buses]: ./i2c.md -[I2C debugging information]: ./i2c.md# \ No newline at end of file +[I2C debugging information]: ./i2c.md# diff --git a/docs/configuration/config_ap_to_ec_comm.md b/docs/configuration/config_ap_to_ec_comm.md index 2fdcc5a147..0a517401be 100644 --- a/docs/configuration/config_ap_to_ec_comm.md +++ b/docs/configuration/config_ap_to_ec_comm.md @@ -1,7 +1,7 @@ # Configure AP to EC Communication This document provides details on how to configure the AP to EC communication -channel used on your board. The [AP to EC Communication] document provides +channel used on your board. The [AP to EC Communication] document provides details a system level of the operation of this feature. ## Config options @@ -9,13 +9,13 @@ details a system level of the operation of this feature. Configure the AP to EC communication channel, picking exactly one of the following options. -- `CONFIG_HOSTCMD_SPS` - [SPI slave](./ec_terms.md#spi) (SPS) interface -- `CONFIG_HOSTCMD_HECI` - HECI interface -- `CONFIG_HOSTCMD_LPC` - [LPC](./ec_terms.md#lpc) bus -- `CONFIG_HOSTCMD_ESPI` - [eSPI](./ec_terms.md#espi) bus +- `CONFIG_HOST_INTERFACE_SHI` - [SPI Host Interface](../ec_terms.md#shi) (SHI) +- `CONFIG_HOST_INTERFACE_HECI` - HECI interface +- `CONFIG_HOST_INTERFACE_LPC` - [LPC](../ec_terms.md#lpc) bus +- `CONFIG_HOST_INTERFACE_ESPI` - [eSPI](../ec_terms.md#espi) bus In [config.h], search for options that start with the same name as your selected -communication interface. Override defaults as needed. +communication interface. Override defaults as needed. ## Feature Parameters @@ -26,26 +26,26 @@ None needed in this section. The EC code requires the following signals between the AP and the EC to be defined by each board variant. -- `GPIO_ENTERING_RW` - Output from the EC, active high signal indicates when the - EC code transitions from RO to RW code. +- `GPIO_ENTERING_RW` - Output from the EC, active high signal indicates when + the EC code transitions from RO to RW code. - ```c - GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) - ``` + ```c + GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW) + ``` -- `GPIO_SYS_RESET_L` - Output from the EC, active low signal used to put the AP - into reset. +- `GPIO_SYS_RESET_L` - Output from the EC, active low signal used to put the + AP into reset. - ```c - GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) - ``` + ```c + GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) + ``` Create `ALTERNATE()` entries for all EC signals used for AP communication. This step can be skipped for any pins that default to communication channel functionality. -See the [GPIO](./gpio.md) documentation for additional details on -the GPIO macros. +See the [GPIO](./gpio.md) documentation for additional details on the GPIO +macros. ## Data structures @@ -58,15 +58,15 @@ always required. The typical priority is higher than the `CHIPSET` task, but lower than the `CONSOLE` task. ```c - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE, 0) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE, 0) \ ``` ## Testing and Debugging For Nuvoton EC chipsets, the file [./chip/npcx/registers.h] provides a collection of `DEBUG_*` macros that can be used to enable extra console messages -related to a specific interface. For AP to EC communication, the `DEBUG_LPC` -and `DEBUG_ESPI` macros can help troubleshoot communication issues. +related to a specific interface. For AP to EC communication, the `DEBUG_LPC` and +`DEBUG_ESPI` macros can help troubleshoot communication issues. [./chip/npcx/registers.h]: ../../chip/npcx/registers.h [AP to EC Communication]: ../ap-ec-comm.md diff --git a/docs/configuration/ec_chipset.md b/docs/configuration/ec_chipset.md index 5f04c4d81e..defc27eec8 100644 --- a/docs/configuration/ec_chipset.md +++ b/docs/configuration/ec_chipset.md @@ -6,20 +6,20 @@ The EC chipset is selected using board specific make file [build.mk]. The following configuration options specify the type and size of flash memory used by the EC. - - `CONFIG_SPI_FLASH_REGS` - Should always be defined when using internal or +- `CONFIG_SPI_FLASH_REGS` - Should always be defined when using internal or external SPI flash. - - `CONFIG_SPI_FLASH` - Define only if your board uses an external flash. - - `CONFIG_SPI_FLASH_` - Select exactly one the supported flash +- `CONFIG_SPI_FLASH` - Define only if your board uses an external flash. +- `CONFIG_SPI_FLASH_` - Select exactly one the supported flash devices to compile in the required driver. This is needed even when using the internal SPI flash of the EC chipset. - - Additional EC Chipset options are prefixed with `CONFIG_HIBERNATE*` and +- Additional EC Chipset options are prefixed with `CONFIG_HIBERNATE*` and should be evaluated for relevance on your board. ## Feature Parameters - - `CONFIG_FLASH_SIZE ` - Set to the size of the internal flash of the - EC. Must be defined to link the final image. - - `CONFIG_SPI_FLASH_PORT ` - Only used if your board as an external +- `CONFIG_FLASH_SIZE_BYTES ` - Set to the size of the internal flash of + the EC. Must be defined to link the final image. +- `CONFIG_SPI_FLASH_PORT ` - Only used if your board as an external flash. ## GPIOs and Alternate Pins @@ -27,38 +27,39 @@ by the EC. Configure the signals which will wakeup the EC from hibernate or deep sleep. Typical wakeup sources include: -- `GPIO_LID_OPEN` - An active high signal that indicates the lid has been - opened. The source of the signal is typically from a [GMR](../ec_terms.md#gmr) - or Hall-Effect sensor. The `GPIO_INT()` entry for this signal should be - connected to the `lid_interrupt()` routine. -- `GPIO_AC_PRESENT` - A signal from the battery charger that indicates the - device is connected to AC power. This signal is connected to the - `power_interrupt()` routine. -- `GPIO_POWER_BUTTON_L` - An active low signal from the power switch. This signal is connected to the `power_button_interrupt()` routine. -- `GPIO_EC_RST_ODL` - On some Nuvoton EC chipsets, the reset signal is - dual-routed to both a dedicated reset pin and a GPIO. In this case, no - interrupt handler needs to be registered to the GPIO signal, but the GPIO pin - must still be configured to wake on both edge types. The GPIO pin should also - be locked prevent the pin configuration from changing after the EC read-only - code runs. +- `GPIO_LID_OPEN` - An active high signal that indicates the lid has been + opened. The source of the signal is typically from a + [GMR](../ec_terms.md#gmr) or Hall-Effect sensor. The `GPIO_INT()` entry for + this signal should be connected to the `lid_interrupt()` routine. +- `GPIO_AC_PRESENT` - A signal from the battery charger that indicates the + device is connected to AC power. This signal is connected to the + `power_interrupt()` routine. +- `GPIO_POWER_BUTTON_L` - An active low signal from the power switch. This + signal is connected to the `power_button_interrupt()` routine. +- `GPIO_EC_RST_ODL` - On some Nuvoton EC chipsets, the reset signal is + dual-routed to both a dedicated reset pin and a GPIO. In this case, no + interrupt handler needs to be registered to the GPIO signal, but the GPIO + pin must still be configured to wake on both edge types. The GPIO pin should + also be locked prevent the pin configuration from changing after the EC + read-only code runs. See the [GPIO](./gpio.md) documentation for additional details on the GPIO macros. ## Data structures -- `const enum gpio_signal hibernate_wake_pins[]` - add all GPIO signals that - should trigger a wakeup of the EC. -- `const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins);` - - configures the number of wake signals used on the board. +- `const enum gpio_signal hibernate_wake_pins[]` - add all GPIO signals that + should trigger a wakeup of the EC. +- `const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins);` - + configures the number of wake signals used on the board. All ChromeOS wake sources are documented on the ChromeOS partner site in the -[Wake Sources and Battery Life] section. The EC specific wake sources are found +[Wake Sources and Battery Life] section. The EC specific wake sources are found under the Deep Sleep and Shipping states and include: -- Power button -- AC insert -- Lid open +- Power button +- AC insert +- Lid open ## Tasks @@ -95,19 +96,21 @@ ALTERNATE(PIN_MASK(D, BIT(2)), 0, MODULE_PMU, 0) ALTERNATE(PIN_MASK(0, BIT(0) | BIT(1) | BIT(2)), 0, MODULE_PMU, 0) ``` -The final step is to add the hibernate signals array to Volteer [baseboard.c] file: +The final step is to add the hibernate signals array to Volteer [baseboard.c] +file: ```c /* Wake up pins */ const enum gpio_signal hibernate_wake_pins[] = { - GPIO_LID_OPEN, - GPIO_ACOK_OD, - GPIO_POWER_BUTTON_L, - GPIO_EC_RST_ODL, + GPIO_LID_OPEN, + GPIO_ACOK_OD, + GPIO_POWER_BUTTON_L, + GPIO_EC_RST_ODL, }; const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); ``` + [gpio.inc]: ../../board/volteer/gpio.inc [baseboard.c]: ../../baseboard/volteer/baseboard.c [build.mk]: ../new_board_checklist.md#board_build_mk -[Wake Sources and Battery Life]: https://chromeos.google.com/partner/dlm/docs/latest-requirements/chromebook.html#wake-sources-and-battery-life \ No newline at end of file +[Wake Sources and Battery Life]: https://chromeos.google.com/partner/dlm/docs/latest-requirements/chromebook.html#wake-sources-and-battery-life diff --git a/docs/configuration/gpio.md b/docs/configuration/gpio.md index 4e13a7cb59..f4a5c4719a 100644 --- a/docs/configuration/gpio.md +++ b/docs/configuration/gpio.md @@ -4,18 +4,18 @@ GPIO setup is done for every board variant, but never for the baseboard, by configuring the file `./board//gpio.inc`. This file configures all the the pins on the EC chipset through the following macros. -- `GPIO(, ...)` - Configures simple GPIO input and outputs -- `GPIO_INT(, ...)` - Configures GPIO inputs that connect to an interrupt - service routine. Historically these entries are defined first, but this no - longer required. -- `ALTERNATE(...)` - Configures a pin for an alternate function (e.g I2C, ADC, - SPI, etc) -- `UNIMPLEMENTED(, ...)` - Creates a fake GPIO entry +- `GPIO(, ...)` - Configures simple GPIO input and outputs +- `GPIO_INT(, ...)` - Configures GPIO inputs that connect to an + interrupt service routine. Historically these entries are defined first, but + this no longer required. +- `ALTERNATE(...)` - Configures a pin for an alternate function (e.g I2C, ADC, + SPI, etc) +- `UNIMPLEMENTED(, ...)` - Creates a fake GPIO entry The `GPIO()`, `GPIO_INT()`, and `UNIMPLEMENTED()` macros create a C enumeration -of the form `GPIO_` that can be used in the code. As noted in [GPIO -Naming](../new_board_checklist.md#GPIO-Naming), the `` parameter should -always match the schematic net name. +of the form `GPIO_` that can be used in the code. As noted in +[GPIO Naming](../new_board_checklist.md#GPIO-Naming), the `` parameter +should always match the schematic net name. ## `GPIO()` macro @@ -23,13 +23,13 @@ always match the schematic net name. `GPIO(name, pin, flags)` -- `name` - Defines the schematic net name, which is expanded to the enumeration - `GPIO_name` by the macro. -- `pin` - Use the `PIN(group,pin)` macro to define the GPIO group and pin - number. Note that on a few EC chipsets, the PIN macro is just `PIN(pin)`. -- `flags` - Define attributes of the pin (direction, pullup/pulldown, open - drain, voltage level, etc). All supported flags are found following the - `GPIO_FLAG_NONE` definition in [./include/gpio.h](../../include/gpio.h). +- `name` - Defines the schematic net name, which is expanded to the + enumeration `GPIO_name` by the macro. +- `pin` - Use the `PIN(group,pin)` macro to define the GPIO group and pin + number. Note that on a few EC chipsets, the PIN macro is just `PIN(pin)`. +- `flags` - Define attributes of the pin (direction, pullup/pulldown, open + drain, voltage level, etc). All supported flags are found following the + `GPIO_FLAG_NONE` definition in [./include/gpio.h](../../include/gpio.h). ### Example @@ -49,15 +49,16 @@ should also map the net name to the EC name in the `board.h` file. ## `GPIO_INT()` macro ### Prototype + `GPIO_INT(name, pin, flags, signal)` -- `name` - Defines the schematic net name, which is expanded to the enumeration - `GPIO_name` by the macro. -- `pin` - Same definition as `GPIO()` macro. -- `flags` - Same definition as `GPIO()` macro. Should always have one of the - `GPIO_INT_*` flags set. -- `signal` - Interrupt service routine called when the pin asserts according to - the flags set. +- `name` - Defines the schematic net name, which is expanded to the + enumeration `GPIO_name` by the macro. +- `pin` - Same definition as `GPIO()` macro. +- `flags` - Same definition as `GPIO()` macro. Should always have one of the + `GPIO_INT_*` flags set. +- `signal` - Interrupt service routine called when the pin asserts according + to the flags set. ### Example @@ -77,42 +78,43 @@ need to map the net name to the EC name in the `board.h` file. ## `ALTERNATE()` macro ### Prototype + `ALTERNATE(pinmask, function, module, flags)` -- `pinmask` - Defines a set of pins in the same GPIO group to assign to a - different function. -- `function` - A chip-specific function number. Only used if the EC chipset - provides multiple alternate functions in addition to GPIO (e.g. pin can be - UART, I2C, SPI, or GPIO). The permitted values for this parameter vary based - on the EC chipset type. - - STM32 - 0 to 7 - - Maxim - 1 to 3 - - Microchip - 0 to 3 - - MediaTek - 0 to 7 - - All others (Nuvton, ITE, TI Stellaris, ) only support one alternate - function per pin, so this parameter should be set to 0. -- `module` - One of the enum module_id values defined in - [./include/module_id.h](../../include/module_id.h). -- `flags` - Same definition as `GPIO()` macro. +- `pinmask` - Defines a set of pins in the same GPIO group to assign to a + different function. +- `function` - A chip-specific function number. Only used if the EC chipset + provides multiple alternate functions in addition to GPIO (e.g. pin can be + UART, I2C, SPI, or GPIO). The permitted values for this parameter vary based + on the EC chipset type. + - STM32 - 0 to 7 + - Maxim - 1 to 3 + - Microchip - 0 to 3 + - MediaTek - 0 to 7 + - All others (Nuvton, ITE, TI Stellaris, ) only support one alternate + function per pin, so this parameter should be set to 0. +- `module` - One of the enum module_id values defined in + [./include/module_id.h](../../include/module_id.h). +- `flags` - Same definition as `GPIO()` macro. ### Notes At runtime there are two mechanisms for switching a pin between GPIO mode and alternate function mode. -- `gpio_config_module(enum module_id id, int enable)` - Configures all pins - matching the module enumeration `id`. -- `gpio_config_pin(enum module_id id, enum gpio_signal signal, int enable)` - - Configures a single pin matching the GPIO enumeration `signal`. +- `gpio_config_module(enum module_id id, int enable)` - Configures all pins + matching the module enumeration `id`. +- `gpio_config_pin(enum module_id id, enum gpio_signal signal, int enable)` - + Configures a single pin matching the GPIO enumeration `signal`. For both routines, if `enable` is 1, then the corresponding pins are configured -for alternate mode operation. If `enable` is 0, then the corresponding pins are +for alternate mode operation. If `enable` is 0, then the corresponding pins are configure for GPIO mode. `gpio_config_module()` is automatically called at runtime for all enabled interfaces (I2C, SPI, UART, etc). You can use `gpio_config_pin()` to temporarily configure a pin for GPIO operation, and to restore the original alternate -function. The I2C bus error recovery employs this mechanism to temporarily +function. The I2C bus error recovery employs this mechanism to temporarily driver the I2C SCL and SDA signals to known states, without interference by the I2C controller in the EC chipset. @@ -132,8 +134,6 @@ The general recipe for overriding alternate functions is shown below. gpio_config_pin(MODULE_I2C, GPIO_I2C1_SDA, 1); ``` - - ### Example ![ALTERNATE Example] @@ -148,8 +148,13 @@ ALTERNATE(PIN_MASK(B, BIT(4) | BIT(5)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P appending "export/png" to the Google Drive link. --> + [GPIO Example]: ../images/gpio_example.png + + [GPIO_INT Example]: ../images/gpio_int_example.png + + [ALTERNATE Example]: ../images/alternate_example.png diff --git a/docs/configuration/i2c.md b/docs/configuration/i2c.md index 92bfe7ad0a..36464bb371 100644 --- a/docs/configuration/i2c.md +++ b/docs/configuration/i2c.md @@ -6,7 +6,7 @@ The I2C options are prefixed with `CONFIG_I2C*`. Evaluate whether each option is appropriate to add to your board. A typical EC and board should at a minimum set `CONFIG_I2C` and -`CONFIG_I2C_MASTER`. +`CONFIG_I2C_CONTROLLER`. ## Feature Parameters @@ -14,10 +14,10 @@ The following parameters control the behavior of the I2C library. [config.h] defines a reasonable default value, but you may need to change the default value for your board. -- `CONFIG_I2C_CHIP_MAX_READ_SIZE ` -- `CONFIG_I2C_NACK_RETRY_COUNT ` -- `CONFIG_I2C_EXTRA_PACKET_SIZE ` - Only used on STM32 EC's if - `CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS` is defined. +- `CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE ` +- `CONFIG_I2C_NACK_RETRY_COUNT ` +- `CONFIG_I2C_EXTRA_PACKET_SIZE ` - Only used on STM32 EC's if + `CONFIG_HOSTCMD_I2C_ADDR_FLAGS` is defined. ## GPIOs and Alternate Pins @@ -28,7 +28,7 @@ recovery actions using bit-banging without involvement by the EC-specific I2C device driver. You also need to define the alternate function assignment for all I2C pins using -the `ALTERNATE()` macro. This step can be skipped for any pins that default to +the `ALTERNATE()` macro. This step can be skipped for any pins that default to I2C functionality. Note that many I2C buses only support 1.8V operation. This is determined by I2C @@ -42,12 +42,12 @@ macros. ## Data Structures -- `const struct i2c_port_t i2c_ports[]` - This array should be defined in your - baseboard.c or board.c file. This array defines the mapping of internal I2C - port numbers used by the I2C library to the physical I2C ports connected to - the EC. -- `const unsigned int i2c_port_used = ARRAY_SIZE(i2c_ports)` - Defines the - number of internal I2C ports accessible by the I2C library. +- `const struct i2c_port_t i2c_ports[]` - This array should be defined in your + baseboard.c or board.c file. This array defines the mapping of internal I2C + port numbers used by the I2C library to the physical I2C ports connected to + the EC. +- `const unsigned int i2c_port_used = ARRAY_SIZE(i2c_ports)` - Defines the + number of internal I2C ports accessible by the I2C library. ## Tasks @@ -57,14 +57,14 @@ None required by this feature. ### Console Commands -- `i2cscan` - Provides a quick look of all I2C devices found on all configured - buses. -- `i2cxfer` - Allows you to read and write individual registers on an I2C - device. +- `i2cscan` - Provides a quick look of all I2C devices found on all configured + buses. +- `i2cxfer` - Allows you to read and write individual registers on an I2C + device. -For runtime troubleshooting of an I2C device, enable and the [I2C -tracing](../i2c-debugging.md) module to log all I2C transactions initiated by -the EC code. +For runtime troubleshooting of an I2C device, enable and the +[I2C tracing](../i2c-debugging.md) module to log all I2C transactions initiated +by the EC code. ## Example @@ -72,8 +72,8 @@ The image below shows the I2C bus assignment for the Volteer reference board. ![I2C Example] -The `gpio.inc` file for Volteer defines both `GPIO()` and `ALTERNATE()` entries for -all I2C buses used in the design. +The `gpio.inc` file for Volteer defines both `GPIO()` and `ALTERNATE()` entries +for all I2C buses used in the design. ```c /* I2C pins - Alternate function below configures I2C module on these pins */ @@ -101,17 +101,17 @@ ALTERNATE(PIN_MASK(B, BIT(3) | BIT(2)), 0, MODULE_I2C, 0) The `i2c_ports[]` array requires the `.port` field to be assigned to an EC chipset specific enumeration. For the NPCx7 I2C bus names are defined in -[./chip/npcx/registers.h]. The Volteer `baseboard.h` file creates a mapping -from the schematic net name to the NPCx7 I2C bus enumeration. +[./chip/npcx/registers.h]. The Volteer `baseboard.h` file creates a mapping from +the schematic net name to the NPCx7 I2C bus enumeration. ```c #define CONFIG_I2C -#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 -#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 -#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 -#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 -#define I2C_PORT_POWER NPCX_I2C_PORT5_0 -#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 +#define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 +#define I2C_PORT_USB_C0 NPCX_I2C_PORT1_0 +#define I2C_PORT_USB_C1 NPCX_I2C_PORT2_0 +#define I2C_PORT_USB_1_MIX NPCX_I2C_PORT3_0 +#define I2C_PORT_POWER NPCX_I2C_PORT5_0 +#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0 ``` The last piece for I2C configuration is to create the `i2c_ports[]` array using @@ -120,56 +120,56 @@ the macros and enumerations added to `baseboard.h` and `gpio.inc`. ```c /* I2C port map configuration */ const struct i2c_port_t i2c_ports[] = { - { - .name = "sensor", - .port = I2C_PORT_SENSOR, - .kbps = 400, - .scl = GPIO_EC_I2C0_SENSOR_SCL, - .sda = GPIO_EC_I2C0_SENSOR_SDA, - .flags = 0, - }, - { - .name = "usb_c0", - .port = I2C_PORT_USB_C0, - /* - * I2C buses used for PD communication must be set for 400 kbps - * or greater. Set to the maximum speed supported by all devices. - */ - .kbps = 1000, - .scl = GPIO_EC_I2C1_USB_C0_SCL, - .sda = GPIO_EC_I2C1_USB_C0_SDA, - }, - { - .name = "usb_c1", - .port = I2C_PORT_USB_C1, - /* - * I2C buses used for PD communication must be set for 400 kbps - * or greater. Set to the maximum speed supported by all devices. - */ - .scl = GPIO_EC_I2C2_USB_C1_SCL, - .sda = GPIO_EC_I2C2_USB_C1_SDA, - }, - { - .name = "usb_1_mix", - .port = I2C_PORT_USB_1_MIX, - .kbps = 100, - .scl = GPIO_EC_I2C3_USB_1_MIX_SCL, - .sda = GPIO_EC_I2C3_USB_1_MIX_SDA, - }, - { - .name = "power", - .port = I2C_PORT_POWER, - .kbps = 100, - .scl = GPIO_EC_I2C5_POWER_SCL, - .sda = GPIO_EC_I2C5_POWER_SDA, - }, - { - .name = "eeprom", - .port = I2C_PORT_EEPROM, - .kbps = 400, - .scl = GPIO_EC_I2C7_EEPROM_SCL, - .sda = GPIO_EC_I2C7_EEPROM_SDA, - }, + { + .name = "sensor", + .port = I2C_PORT_SENSOR, + .kbps = 400, + .scl = GPIO_EC_I2C0_SENSOR_SCL, + .sda = GPIO_EC_I2C0_SENSOR_SDA, + .flags = 0, + }, + { + .name = "usb_c0", + .port = I2C_PORT_USB_C0, + /* + * I2C buses used for PD communication must be set for 400 kbps + * or greater. Set to the maximum speed supported by all devices. + */ + .kbps = 1000, + .scl = GPIO_EC_I2C1_USB_C0_SCL, + .sda = GPIO_EC_I2C1_USB_C0_SDA, + }, + { + .name = "usb_c1", + .port = I2C_PORT_USB_C1, + /* + * I2C buses used for PD communication must be set for 400 kbps + * or greater. Set to the maximum speed supported by all devices. + */ + .scl = GPIO_EC_I2C2_USB_C1_SCL, + .sda = GPIO_EC_I2C2_USB_C1_SDA, + }, + { + .name = "usb_1_mix", + .port = I2C_PORT_USB_1_MIX, + .kbps = 100, + .scl = GPIO_EC_I2C3_USB_1_MIX_SCL, + .sda = GPIO_EC_I2C3_USB_1_MIX_SDA, + }, + { + .name = "power", + .port = I2C_PORT_POWER, + .kbps = 100, + .scl = GPIO_EC_I2C5_POWER_SCL, + .sda = GPIO_EC_I2C5_POWER_SDA, + }, + { + .name = "eeprom", + .port = I2C_PORT_EEPROM, + .kbps = 400, + .scl = GPIO_EC_I2C7_EEPROM_SCL, + .sda = GPIO_EC_I2C7_EEPROM_SDA, + }, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); ``` @@ -184,21 +184,20 @@ different speeds based on the BOARD_VERSION in [CBI]. For example board version operation. `I2C_PORT_FLAG_DYNAMIC_SPEED` is not used to change the I2C bus frequency on the fly depending on the addressed slave device. -An example of changing the I2C bus frequency from the [Kodama -board](../../board/kodama/board.c) is shown below. +An example of changing the I2C bus frequency from the +[Kodama board](../../board/kodama/board.c) is shown below. ```c static void board_i2c_init(void) { - if (board_get_version() < 2) - i2c_set_freq(1, I2C_FREQ_100KHZ); + if (board_get_version() < 2) + i2c_set_freq(1, I2C_FREQ_100KHZ); } DECLARE_HOOK(HOOK_INIT, board_i2c_init, HOOK_PRIO_INIT_I2C); ``` - [config.h]: ../new_board_checklist.md#config_h [./chip/npcx/registers.h]: ../../chip/npcx/registers.h [./include/i2c.h]: ../../include/i2c.h [I2C Example]: ../images/i2c_example.png -[CBI]: https://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/cros_board_info.md +[CBI]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/cros_board_info.md diff --git a/docs/configuration/keyboard.md b/docs/configuration/keyboard.md index f2dc585e1b..8398fefbde 100644 --- a/docs/configuration/keyboard.md +++ b/docs/configuration/keyboard.md @@ -8,23 +8,23 @@ appropriate to add to `baseboard.h` or `board.h`. Your board should select only one of these options to configure the protocol used to send keyboard events to the AP. -- `CONFIG_KEYBOARD_PROTOCOL_8042` - Systems with an x86 AP use the 8042 - protocol. -- `CONFIG_KEYBOARD_PROTOCOL_MKBP` - Systems without an x86 AP (e.g. ARM) - typically use the MKBP protocol. +- `CONFIG_KEYBOARD_PROTOCOL_8042` - Systems with an x86 AP use the 8042 + protocol. +- `CONFIG_KEYBOARD_PROTOCOL_MKBP` - Systems without an x86 AP (e.g. ARM) + typically use the MKBP protocol. ## Feature Parameters -- `CONFIG_KEYBOARD_KSO_BASE ` - Evaluate whether this parameter is required - by your board. +- `CONFIG_KEYBOARD_KSO_BASE ` - Evaluate whether this parameter is + required by your board. ## GPIOs and Alternate Pins Define `ALTERNATE()` pin entries for all keyboard matrix signals, to connect the signals to the keyboard controller of the EC chipset. -Note that KSO_02 is purposely not configured for for alternate mode. See the [H1 -Special Requirements](#H1-Special-Requirements) below for details. +Note that KSO_02 is purposely not configured for for alternate mode. See the +[H1 Special Requirements](#H1-Special-Requirements) below for details. ```c /* Example Keyboard pin setup */ @@ -42,8 +42,8 @@ macros. ## Data structures -- `struct keyboard_scan_config keyscan_config` - This must be defined if the - `CONFIG_KEYBOARD_BOARD_CONFIG` option is defined. +- `struct keyboard_scan_config keyscan_config` - This can be used to customize + the keyboard scanner (e.g. scan frequency, debounce duration, etc.). ## Tasks @@ -65,27 +65,23 @@ priority is lower than the `HOSTCMD` task. ## Additional Notes -- If you're including keyboard support, you should also define - `CONFIG_CMD_KEYBOARD` to enable keyboard debug commands from the EC console. -- `CONFIG_KEYBOARD_PROTOCOL_MKBP` automatically enables `CONFIG_MKBP_EVENT`. -- Boards that enable `CONFIG_KEYBOARD_PROTOCOL_8042` will often also define - `CONFIG_MKBP_EVENT` for sensor events. In this case only motion sensor data is - reported using the MKBP protocol, keyboard events are provided using the 8042 - protocol. Refer to [Configuring Sensors](./motion_sensors.md) for more - information. +- If you're including keyboard support, you should also define + `CONFIG_CMD_KEYBOARD` to enable keyboard debug commands from the EC console. +- `CONFIG_KEYBOARD_PROTOCOL_MKBP` automatically enables `CONFIG_MKBP_EVENT`. +- Boards that enable `CONFIG_KEYBOARD_PROTOCOL_8042` will often also define + `CONFIG_MKBP_EVENT` for sensor events. In this case only motion sensor data + is reported using the MKBP protocol, keyboard events are provided using the + 8042 protocol. Refer to [Configuring Sensors](./motion_sensors.md) for more + information. ### H1 Special Requirements + On Boards that use the H1 secure microcontroller, one KSI (keyboard scan input) signal and one KSO (keyboard scan output) signal are routed through the H1 microcontroller. There are additional GPIO and configuration options that must -be enabled in this case. -- The KSO_02/COL2 signal is always inverted. Explicitly configure the GPIO to - default low. - ```c - GPIO(KBD_KSO2, PIN(1, 7), GPIO_OUT_LOW) /* KSO_02 inverted */ - ``` -- Add the define `CONFIG_KEYBOARD_COL2_INVERTED` to `baseboard.h` or `board.h`. -- If required by the board, define one of the following options to configure the - KSI pin routed to the H1 microcontroller. - - `CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2` - - `CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI3` +be enabled in this case. - The KSO_02/COL2 signal is always inverted. Explicitly +configure the GPIO to default low. `c GPIO(KBD_KSO2, PIN(1, 7), GPIO_OUT_LOW) /* +KSO_02 inverted */` - Add the define `CONFIG_KEYBOARD_COL2_INVERTED` to +`baseboard.h` or `board.h`. - If required by the board, define one of the +following options to configure the KSI pin routed to the H1 microcontroller. - +`CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2` - `CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI3` diff --git a/docs/configuration/leds.md b/docs/configuration/leds.md index 72a548a306..c4fe7894af 100644 --- a/docs/configuration/leds.md +++ b/docs/configuration/leds.md @@ -2,13 +2,13 @@ LEDs provide status about the following: -- Dedicated battery state/charging state -- Chromebook power -- Adapter power -- Left side USB-C port (battery state/charging state) -- Right side USB-C port (battery state/charging state) -- Recovery mode -- Debug mode +- Dedicated battery state/charging state +- Chromebook power +- Adapter power +- Left side USB-C port (battery state/charging state) +- Right side USB-C port (battery state/charging state) +- Recovery mode +- Debug mode LEDs can be configured as simple GPIOs, with on/off control only, or as PWM with adjustment brightness and color. @@ -18,23 +18,21 @@ adjustment brightness and color. In [config.h], search for options that start with `CONFIG_LED*` and evaluate whether each option is appropriate to add to `baseboard.h` or `board.h`. -- `CONFIG_LED_COMMON` - Should be defined for both GPIO and PWM style LEDs. -- `CONFIG_LED_ONOFF_STATES` - used for GPIO controlled LEDs -- `CONFIG_LED_PWM` - used for PWM controlled LEDs. You must also define - `CONFIG_PWM` when using PWM controlled LEDs. +- `CONFIG_LED_COMMON` - Should be defined for both GPIO and PWM style LEDs. +- `CONFIG_LED_ONOFF_STATES` - used for GPIO controlled LEDs +- `CONFIG_LED_PWM` - used for PWM controlled LEDs. You must also define + `CONFIG_PWM` when using PWM controlled LEDs. ## Feature Parameters -- `CONFIG_LED_PWM_COUNT ` - Must be defined when using PWM LEDs +- `CONFIG_LED_PWM_COUNT ` - Must be defined when using PWM LEDs Override the following parameters when using PWM LEDs if you don't want to use -the recommended LED color settings. -- `CONFIG_LED_PWM_CHARGE_COLOR ` -- `CONFIG_LED_PWM_NEAR_FULL_COLOR ` -- `CONFIG_LED_PWM_CHARGE_ERROR_COLOR ` -- `CONFIG_LED_PWM_SOC_ON_COLOR ` -- `CONFIG_LED_PWM_SOC_SUSPEND_COLOR ` -- `CONFIG_LED_PWM_LOW_BATT_COLOR ` +the recommended LED color settings. - `CONFIG_LED_PWM_CHARGE_COLOR +` - `CONFIG_LED_PWM_NEAR_FULL_COLOR ` - +`CONFIG_LED_PWM_CHARGE_ERROR_COLOR ` - +`CONFIG_LED_PWM_SOC_ON_COLOR ` - `CONFIG_LED_PWM_SOC_SUSPEND_COLOR +` - `CONFIG_LED_PWM_LOW_BATT_COLOR ` ## GPIOs and Alternate Pins @@ -47,20 +45,18 @@ For PWM LEDs, configure the `ALTERNATE()` macro, setting the module type to ## Data structures -For GPIO based LEDs: -- `struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES]` - - Must be defined when `CONFIG_LED_ONOFF_STATES` is used. Defines the LED states - for the platform for various charging states. - -For PWM based LEDs: -- `const enum ec_led_id supported_led_ids[]` - Defines the LED type for all PWM - LEDs in the system. See [./include/ec_commands.h] for a description of the - supported LED types. -- `struct pwm_led led_color_map[]` - Defines the PWM intensity of the individual - LEDs to generate the corresponding color. This table allows for custom tuning - of the LED brightness and color. -- `const struct pwm_channels[]` - Configures the PWM module, refer to the - [Configuring PWM](./pwm.md) section for details. +For GPIO based LEDs: - `struct led_descriptor +led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES]` - Must be defined when +`CONFIG_LED_ONOFF_STATES` is used. Defines the LED states for the platform for +various charging states. + +For PWM based LEDs: - `const enum ec_led_id supported_led_ids[]` - Defines the +LED type for all PWM LEDs in the system. See [./include/ec_commands.h] for a +description of the supported LED types. - `struct pwm_led led_color_map[]` - +Defines the PWM intensity of the individual LEDs to generate the corresponding +color. This table allows for custom tuning of the LED brightness and color. - +`const struct pwm_channels[]` - Configures the PWM module, refer to the +[Configuring PWM](./pwm.md) section for details. See the [GPIO](./gpio.md) documentation for additional details on the GPIO macros. @@ -73,12 +69,12 @@ None required by this feature. ### Console Commands -- `pwmduty` - *TODO* add description. -- `gpioset` - For GPIO based LEDs, this command lets you directly change the - state of the LED. -- `gpioget` - For GPIO based LEDs, this reads current state of the pin. If the - current state does not track changes made with `gpioset`, check your board for - stuck at high or stuck at low condition. +- `pwmduty` - *TODO* add description. +- `gpioset` - For GPIO based LEDs, this command lets you directly change the + state of the LED. +- `gpioget` - For GPIO based LEDs, this reads current state of the pin. If the + current state does not track changes made with `gpioset`, check your board + for stuck at high or stuck at low condition. If you're having problems with a PWM LED, try reconfiguring the pin as a GPIO to verify the board operation independent of the PWM module. @@ -89,4 +85,4 @@ LED driver chips are used to control the LCD panel backlight. The backlight control is separate from the platform LEDs. [config.h]: ../new_board_checklist.md#config_h -[./include/ec_commands.h]: ../../include/ec_commands.h \ No newline at end of file +[./include/ec_commands.h]: ../../include/ec_commands.h diff --git a/docs/configuration/motion_sensors.md b/docs/configuration/motion_sensors.md index 4dac939b10..6e84fc3307 100644 --- a/docs/configuration/motion_sensors.md +++ b/docs/configuration/motion_sensors.md @@ -2,12 +2,12 @@ EC sensors are used for the following capabilities: -- Accelerometers in base and lid measure lid angle to toggle between laptop and - tablet modes. -- Ambient light sensors control display backlight level. -- All sensor types, including gyroscope, e-compass, and pressure, are used by - Android apps. -- Special sync sensor type, synchronizes sensor events with AP. +- Accelerometers in base and lid measure lid angle to toggle between laptop + and tablet modes. +- Ambient light sensors control display backlight level. +- All sensor types, including gyroscope, e-compass, and pressure, are used by + Android apps. +- Special sync sensor type, synchronizes sensor events with AP. *TODO* - there is good content available in the most recent [Chrome EC] overview presentation that can be added here. @@ -20,13 +20,12 @@ presentation that can be added here. *TODO* - ## GPIOs and Alternate Pins *TODO* -- `GPIO_EC_INT_L` - Output from the EC, driven low to indicate an event on the - EC is ready for servicing by the AP. +- `GPIO_EC_INT_L` - Output from the EC, driven low to indicate an event on the + EC is ready for servicing by the AP. ## Data Structures @@ -49,4 +48,3 @@ presentation that can be added here. *TODO* [Chrome EC]: https://docs.google.com/presentation/d/1Y3PwNSnCQoCqDfL5rYqfaBP_ZqbMOTw_x83_ry4cro8/view#slide=id.g63bdbcea4b_0_27 - diff --git a/docs/core_runtime.md b/docs/core_runtime.md index 9d81b807be..9599521a6f 100644 --- a/docs/core_runtime.md +++ b/docs/core_runtime.md @@ -1,43 +1,38 @@ -Chromium OS Embedded Controller runtime -======================================= +# Chromium OS Embedded Controller Runtime -Design principles ------------------ +## Design Principles - 1. Never do at runtime what you can do at compile time -The goal is saving flash space and computations. -Compile-time configuration until you really need to switch at runtime. +1. Never do at runtime what you can do at compile time The goal is saving flash + space and computations. Compile-time configuration until you really need to + switch at runtime. - 2. Real-time: guarantee low latency (eg < 20 us) -no interrupt disabling ... -bounded code in interrupt handlers. +2. Real-time: guarantee low latency (eg < 20 us) no interrupt disabling ... + bounded code in interrupt handlers. - 3. Keep it simple: design for the subset of microcontroller we use -targeted at 32-bit single core CPU -for small systems : 4kB to 64kB data RAM, possibly execute-in-place from flash. +3. Keep it simple: design for the subset of microcontroller we use targeted at + 32-bit single core CPU for small systems : 4kB to 64kB data RAM, possibly + execute-in-place from flash. -Execution contexts ------------------- +## Execution Contexts -This is a pre-emptible runtime with static tasks. -It has only 2 possible execution contexts: +This is a pre-emptible runtime with static tasks. It has only 2 possible +execution contexts: -- the regular [tasks](#tasks) -- the [interrupt handlers](#interrupts) +- the regular [tasks](#tasks) +- the [interrupt handlers](#interrupts) The initial startup is an exception as described in the -[dedicated paragraph](#Startup). +[dedicated paragraph](#startup). -### tasks +### Tasks -The tasks are statically defined at compile-time. -They are described for each *board* in the -[board/$board/ec.tasklist](../board/host/ec.tasklist) file. +The tasks are statically defined at compile-time. They are described for each +*board* in the [board/$board/ec.tasklist](../board/host/ec.tasklist) file. They also have a static fixed priority implicitly defined at compile-time by their order in the [ec.tasklist](../board/host/ec.tasklist) file (the top-most -one being the lowest priority aka *task* *1*). -As a consequence, two different tasks cannot have the same priority. +one being the lowest priority aka *task* *1*). As a consequence, two different +tasks cannot have the same priority. In order to store its context, each task has its own stack whose (*small*) size is defined at compile-time in the [ec.tasklist](../board/host/ec.tasklist) file. @@ -47,91 +42,90 @@ priority tasks, see the [preemption section](#scheduling-and-preemption) for details and the [locking section](#locking-and-atomicity) for the few cases where you need to avoid it. -### interrupts +### Interrupts -The hardware interrupt requests are connected to the interruption handling -*C* routines declared by the `DECLARE_IRQ` macros, through some chip/core -specific mechanisms (e.g. depending whether we have a vectored interrupt -controller, slave interrupt controllers...) +The hardware interrupt requests are connected to the interruption handling *C* +routines declared by the `DECLARE_IRQ` macros, through some chip/core specific +mechanisms (e.g. depending on whether we have a vectored interrupt controller, +slave interrupt controllers...) The interrupts can be nested (ie interrupted by a higher priority interrupt). All the interrupt vectors are assigned a priority as defined in their `DECLARE_IRQ` macro. The number of available priority level is architecture-specific (e.g. 4 on Cortex-M0, 8 on Cortex-M3/M4) and several interrupt handlers can have the same priority. An interrupt handler can only be -interrupted by an handler having a priority **strictly** **greater** than -its own. +interrupted by a handler having a priority **strictly** **greater** than its +own. -In most cases, the exceptions (e.g data/prefetch aborts, software interrupt) can -be seen as interrupts with a priority strictly greater than all IRQ vectors. -So they can interrupt any IRQ handler using the same nesting mechanism. -All fatal exceptions should ultimately lead to a reboot. +In most cases, the exceptions (e.g., data/prefetch aborts, software interrupt) +can be seen as interrupts with a priority strictly greater than all IRQ vectors. +So they can interrupt any IRQ handler using the same nesting mechanism. All +fatal exceptions should ultimately lead to a reboot. ### Events -Each task has a *pending* events bitmap[1] implemented as a 32-bit word. -Several events are pre-defined for all tasks, the most significant bits on the -32-bit bitmap are reserved for them : the timer pending event on bit 31 -([see the corresponding section](#Timers)), the requested task wake (bit 29), -the event to kick the waiters on a mutex (bit 30), along with a few hardware -specific events. -The 19 least significant bits are available for task-specific meanings. +Each task has a *pending* events bitmap[1] implemented as a 32-bit word. Several +events are pre-defined for all tasks, the most significant bits on the 32-bit +bitmap are reserved for them : the timer pending event on bit 31 +([see the corresponding section](#time)), the requested task wake (bit 29), the +event to kick the waiters on a mutex (bit 30), along with a few hardware +specific events. The 19 least significant bits are available for task-specific +meanings. Those event bits are used in inter-task communication and scheduling mechanism, other tasks **and** interrupt handlers can atomically set them to request specific actions from the task. Therefore, the presence of pending events in a -task bitmap has an impact on its scheduling as described in the [scheduling -section](#scheduling-and-preemption). -These requests are done using the `task_set_event()` and `task_wake()` -primitives. +task bitmap has an impact on its scheduling as described in the +[scheduling section](#scheduling-and-preemption). These requests are done using +the `task_set_event()` and `task_wake()` primitives. The two typical use-cases are: -- a task sends a message to another task (simply use some common memory - structures [see explanation](#single-address-space) and want it to process - it now. -- an hardware IRQ occurred and we need to do some long processing to respond to - it (e.g. an I2C transaction). The associated interrupt handler cannot do it - (for latency reason), so it will raise an event to ask a task to do it. +- a task sends a message to another task (simply use some common memory + structures [see explanation](#single-address-space)) and want it to process + it now. +- a hardware IRQ occurred, and we need to do some long processing to respond + to it (e.g. an I2C transaction). The associated interrupt handler cannot do + it (for latency reason), so it will raise an event to ask a task to do it. The task code chooses to consume them (or a subset of them) when it's running through the `task_wait_event()` and `task_wait_event_mask()` primitives. -### Scheduling and preemption +### Scheduling and Preemption -The system has a global bitmap[1] called `tasks_ready` containing one bit -per task and indicating whether or not it is *ready* *to* *run* -(ie want/need to be scheduled). -The task ready bit can only be cleared when it's calling itself one of the -functions explicitly triggering a re-scheduling (e.g. `task_wait_event()` -or `task_set_event()`) **and** it has no pending event. -The task ready bit is set by any task or interrupt handler setting an event -bit for the task (ie `task_set_event()`). +The system has a global bitmap[1] called `tasks_ready` containing one bit per +task and indicating whether it is *ready* *to* *run* (ie want/need to be +scheduled). The task ready bit can only be cleared when it's calling itself one +of the functions explicitly triggering a re-scheduling (e.g. `task_wait_event()` +or `task_set_event()`) **and** it has no pending event. The task ready bit is +set by any task or interrupt handler setting an event bit for the task (ie +`task_set_event()`). -The scheduling is based on (and *only* on) the `tasks_ready` bitmap -(which is derived from all the events bitmap of the tasks as explained above). +The scheduling is based on (and *only* on) the `tasks_ready` bitmap (which is +derived from all the events bitmap of the tasks as explained above). Then, the scheduling policy to find which task should run is just finding the -most significant bit set in the tasks_ready bitmap and schedule the corresponding task. - -Important note: the re-scheduling happens **only** when we are exiting the interrupt context. -It is done in a non-preemptible context (likely with the highest priority). -Indeed, a re-scheduling is actually needed only when the highest priority task ready has changed. -There are 3 distinct cases where this can happen: - -- an interrupt handler sets a new event for a task. - In this case, `task_set_event` will detect that it is executed in interrupt - context and record in the `need_resched_or_profiling` variable that it might - need to re-schedule at interrupt return. When the current interrupt is going - to return, it will see this bit and decide to take the slow path making a new - scheduling decision and eventually a context switch instead of the fast path - returning to the interrupt task. -- a task sets an event on another task. - The runtime will trigger a software interrupt to force a re-scheduling at its - exit. -- the running task voluntarily relinguish its current execution rights by - calling `task_wait_event()` or a similar function. - This will call the software interrupt similarly to the previous case. +most significant bit set in the tasks_ready bitmap and schedule the +corresponding task. + +Important note: the re-scheduling happens **only** when we are exiting the +interrupt context. It is done in a non-preemptible context (likely with the +highest priority). Indeed, a re-scheduling is actually needed only when the +highest priority task ready has changed. There are 3 distinct cases where this +can happen: + +- an interrupt handler sets a new event for a task. In this case, + `task_set_event` will detect that it is executed in interrupt context and + record in the `need_resched_or_profiling` variable that it might need to + re-schedule at interrupt return. When the current interrupt is going to + return, it will see this bit and decide to take the slow path making a new + scheduling decision and eventually a context switch instead of the fast path + returning to the interrupt task. +- a task sets an event on another task. The runtime will trigger a software + interrupt to force a re-scheduling at its exit. +- the running task voluntarily relinquish its current execution rights by + calling `task_wait_event()` or a similar function. This will call the + software interrupt similarly to the previous case. On the re-scheduling path, if the highest-priority ready task is not matching the currently running one, it will perform a context-switch by saving all the @@ -139,207 +133,201 @@ processor registers on the current task stack, switch the stack pointer to the newly scheduled task, and restore the registers from the previously saved context from there. -### hooks and deferred function +### Hooks and Deferred Functions The lowest priority task (ie Task 1, aka TASK_ID_HOOKS) is reserved to execute repetitive actions and future actions deferred in time without blocking the current task or creating a dedicated task (whose stack memory allocation would be wasting precious RAM). -The HOOKS task has a list of deferred functions and their next deadline. -Every time it is waken up, it runs through the list and calls the ones whose -deadline is expired. Before going back to sleep, it arms a timer to the closest -deadline. +The HOOKS task has a list of deferred functions and their next deadline. Every +time it is woken up, it runs through the list and calls the ones whose deadline +is expired. Before going back to sleep, it arms a timer to the closest deadline. The deferred functions can be created using the `DECLARED_DEFERRED()` macro. -Similarly the HOOK_SECOND and HOOK_TICK hooks are called periodically by the -HOOKS task loop (the *tick* duration is platform-defined and shorter than -the second). +Similarly, the HOOK_SECOND and HOOK_TICK hooks are called periodically by the +HOOKS task loop (the *tick* duration is platform-defined and shorter than the +second). + +For examples, of hooks and deferred functions, see the [`hooks` testcases]. Note: be specially careful about priority inversions when accessing resources protected by a mutex (e.g. a shared I2C controller) in a deferred function. -Indeed being the lowest priority task, it might be de-scheduled for long time -and starve higher priority tasks trying to access the resource given there is -no priority boosting implemented for this case. -Also be careful about long delays (> x 100us) in hook or deferred function -handlers, since those will starve other hooks of execution time. It is better -to implement a state machine where you set up a subsequent call to a deferred -function than have a long delay in your handler. +Indeed, being the lowest priority task, it might be de-scheduled for long time +and starve higher priority tasks trying to access the resource given there is no +priority boosting implemented for this case. Also, be careful about long delays +(> x 100us) in hook or deferred function handlers, since those will starve other +hooks of execution time. It is better to implement a state machine where you set +up a subsequent call to a deferred function than have a long delay in your +handler. -### watchdog +### Watchdog The system is always protected against misbehaving tasks and interrupt handlers by a hardware watchdog rebooting the CPU when it is not attended. The watchdog is petted in the HOOKS task, typically by declaring a HOOK_TICK -doing it as regular intervals. Given this is the lowest priority task, -this guarantees that all tasks are getting some run time during the watchdog -period. +doing it as regular intervals. Given this is the lowest priority task, this +guarantees that all tasks are getting some run time during the watchdog period. Note: that's also why one should not sprinkle its code with `watchdog_reload()` to paper over long-running routine issues. -To help debugging bad sequences triggering watchdog reboots, most platforms -implement a warning mechanism defined under `CONFIG_WATCHDOG_HELP`. -It's a timer firing at the middle of the watchdog period if it hasn't been -petted by then, and dumping on the console the current state of the execution -mainly to help finding a stuck task or handler. The normal execution is resumed -though after this alert. +To help debug bad sequences triggering watchdog reboots, most platforms +implement a warning mechanism defined under `CONFIG_WATCHDOG_HELP`. It's a timer +firing at the middle of the watchdog period if it hasn't been petted by then, +and dumping on the console the current state of the execution mainly to help +find a stuck task or handler. The normal execution is resumed though after this +alert. ### Startup The startup sequence goes through the following steps: -- the assembly entry routine clears the .bss (uninitialized data), - copies the initialized data (and optionally the code if we are not executing - from flash), sets a stack pointer. -- we can jump to the `main()` C routine at this point. -- then we go through the hardware pre-init (before we have all the clocks to - run the peripherals normal) and init routines, in this rough order: - memory protection if any, gpios in their default state, - prepare the interrupt controller, set the clocks, then timers, - enable interrupts, init the debug UART and the watchdog. -- finally start tasks. - -For the tasks startup, initially only the HOOKS task is marked as ready, -so it is the first to start and can call all the HOOK_INIT handlers performing -initializations before actually executing any real task code. -Then all tasks are marked as ready, and the highest priority one is given -the control. - -During all the startup sequence until the control is given the first task, -we are using a speciak stack called 'system stack' which will be later re-used -as the interrupts and exception stack. +- the assembly entry routine clears the .bss (uninitialized data), copies the + initialized data (and optionally the code if we are not executing from + flash), sets a stack pointer. +- we can jump to the `main()` C routine at this point. +- then we go through the hardware pre-init (before we have all the clocks to + run the peripherals normal) and init routines, in this rough order: memory + protection if any, gpios in their default state, prepare the interrupt + controller, set the clocks, then timers, enable interrupts, init the debug + UART and the watchdog. +- finally, start tasks. + +For the tasks startup, initially only the HOOKS task is marked as ready, so it +is the first to start and can call all the HOOK_INIT handlers performing +initializations before actually executing any real task code. Then all tasks are +marked as ready, and the highest priority one is given the control. + +During all the startup sequence until the control is given the first task, we +are using a special stack called 'system stack' which will be later re-used as +the interrupts and exception stack. To prepare the first context switch, the code in `task_pre_init()` is stuffing -all the tasks stacks with a *fake* saved context whose program counter is -containing the task start address and the stack pointer is pointing to its -reserved stack space. +all the tasks stacks with a *fake* saved context whose program counter contains +the task start address, and the stack pointer is pointing to its reserved stack +space. -### locking and atomicity +### Locking and Atomicity -The two main concurrency primitives are lightweight atomic variables and -heavier mutexes. +The two main concurrency primitives are lightweight atomic variables and heavier +mutexes. The atomic variables are 32-bit integers (which can usually be loaded/stored atomically on the architecture we are supporting). The `atomic.h` headers -include primitives to do atomically various bit and arithmetic operations -using either load-linked/load-exclusive, store-conditional/store-exclusive -or simple depending what is available. +include primitives to do atomically various bit and arithmetic operations using +either load-linked/load-exclusive, store-conditional/store-exclusive or simple +depending on what is available. -The mutexes are actually statically allocated binary semaphores. -In case of contention, they will make the waiting task sleep -(removing its ready bit) and use the [event mechanism](#Events) to wake-up -the other waiters on unlocking. +The mutexes are actually statically allocated binary semaphores. In case of +contention, they will make the waiting task sleep (removing its ready bit) and +use the [event mechanism](#events) to wake up the other waiters on unlocking. -Note: the mutexes are NOT triggering any priority boosting to avoid the -priority inversion phenomenon. +Note: the mutexes are NOT triggering any priority boosting to avoid the priority +inversion phenomenon. Given the runtime is running on single core CPU, spinlocks would be equivalent -to masking interrupts with `interrupt_disable()` spinlocks, but it's -strongly discouraged to avoid harming the real-time characterics of the runtime. +to masking interrupts with `interrupt_disable()` spinlocks, but it's strongly +discouraged to avoid harming the real-time characteristics of the runtime. -Time ----- +## Time -### time keeping +### Time Keeping -In the runtime, the time is accounted everywhere using a -**64-bit** **microsecond** count since the microcontroller **cold** **boot**. +In the runtime, the time is accounted everywhere using a **64-bit** +**microsecond** count since the microcontroller **cold** **boot**. -Note: The runtime has no notion of wall-time/date, even though a few platform have -an RTC inside the microcontroller. +Note: The runtime has no notion of wall-time/date, even though a few platforms +have an RTC inside the microcontroller. These microsecond timestamps are implemented in the code using the `timestamp_t` -type and the current timestamp is returned by the `get_time()` function. +type, and the current timestamp is returned by the `get_time()` function. -The time-keeping is preferably implemented using a 32-bit hardware -free running counter at 1Mhz plus a 32-bit word in memory keeping track of -the high word of the 64-bit absolute time. This word is incremented by the -32-bit timer rollback interrupt. +The time-keeping is preferably implemented using a 32-bit hardware free running +counter at 1Mhz plus a 32-bit word in memory keeping track of the high word of +the 64-bit absolute time. This word is incremented by the 32-bit timer rollback +interrupt. Note: as a consequence of this implementation, when the 64-bit timestamp is read -in interrupt context in an handler having a higher priority than the timer IRQ +in interrupt context in a handler having a higher priority than the timer IRQ (which is somewhat rare), the high 32-bit word might be incoherent (off by one). -### timer event +### Timer Event -The runtime offers *one* (and only one) timer per task. -All the task timers are multiplexed on a single hardware timer. -(can be just a *match* *interrupt* on the free running counter mentioned in the -[previous paragraph](#time-keeping)) +The runtime offers *one* (and only one) timer per task. All the task timers are +multiplexed on a single hardware timer. (can be just a *match* *interrupt* on +the free running counter mentioned in the [previous paragraph](#time-keeping)) Every time a timer is armed or expired, the runtime finds the task timer having -the closest deadline and programs it in the hardware to get an interrupt. -At the same time, it sets the TASK_EVENT_TIMER event in all tasks whose timer -deadline has expired. -The next deadline is computed in interrupt context. +the closest deadline and programs it in the hardware to get an interrupt. At the +same time, it sets the TASK_EVENT_TIMER event in all tasks whose timer deadline +has expired. The next deadline is computed in interrupt context. -Note: given each task has a **single** timer which is also used to wake-up the +Note: given each task has a **single** timer which is also used to wake up the task when `task_wait_event()` is called with a timeout, one needs to be careful when using directly the `timer_arm()` function because there is an eventuality that this timer is still running on the next `task_wait_event()` call, the call will fail due to the lack of available timer. -Memory ------- +## Memory -### Single address space +### Single Address Space There is no memory isolation between tasks (ie they all live in the same address space). Some architectures implement memory protection mechanism albeit only to -differentiate executable area (eg `.code`) from writable area (eg `.bss` or -`.data`) as there is a **single** **privilege** level for all execution contexts. +differentiate executable area (eg `.code`) from writable area (e.g., `.bss` or +`.data`) as there is a **single** **privilege** level for all execution +contexts. -As all the memory is implicitely shared between the task, the inter-task -communication can be done by simply writing the data structures in memory -and using events to wake the other task (given we properly thought the concurrent -accesses on thoses structures). +As all the memory is implicitly shared between the task, the inter-task +communication can be done by simply writing the data structures in memory and +using events to wake the other task (given we properly thought the concurrent +accesses on those structures). -### heap +### Heap The data structure should be statically allocated at compile time. Note: there is no dynamic allocator available (e.g. `malloc()`), not due to -impossibility to create one but to avoid the negative side effects of -having one: ie poor/unpredictable real-time behavior and possible leaks -leading to a long-tail of failures. +impossibility to create one but to avoid the negative side effects of having +one: ie poor/unpredictable real-time behavior and possible leaks leading to a +long-tail of failures. -- TODO: talk about shared memory -- TODO: where/how we store *panic* *memory* and *sysjump* *parameters*. +- TODO: talk about shared memory +- TODO: where/how we store *panic* *memory* and *sysjump* *parameters*. -### stacks +### Stacks Each task has its own stack, in addition there is a system stack used for startup and interrupts/exceptions. -Note 1: Each task stack is relatively small (e.g. 512 bytes), so one needs to -be careful about stack usage when implementing features. +Note 1: Each task stack is relatively small (e.g. 512 bytes), so one needs to be +careful about stack usage when implementing features. -Note 2: At the same time, the total size of RAM used by stacks is a big chunk -of the total RAM consumption, so their sizes need to be carefully tuned. -(please refer to the [debugging paragraph](#debugging) for additional input on -this topic. +Note 2: At the same time, the total size of RAM used by stacks is a big chunk of +the total RAM consumption, so their sizes need to be carefully tuned. (Please +refer to the [debugging paragraph](#debugging) for additional input on this +topic.) -## Firmware code organization and multiple copies +## Firmware Code Organization and Multiple Copies -- TODO: Details the classical RO / RW partitions and how we sysjump. +- TODO: Details the classical RO / RW partitions and how we sysjump. -power management ----------------- +## Power Management -- TODO: talk about the idle task + WFI (note: interrupts are disabled!) -- TODO: more about low power idle and the sleep-disable bitmap -- TODO: adjusting the microsecond timer at wake-up +- TODO: talk about the idle task + WFI (note: interrupts are disabled!) +- TODO: more about low power idle and the sleep-disable bitmap +- TODO: adjusting the microsecond timer at wake-up -debugging ---------- +## Debugging -- TODO: our main tool: serial console ... -(but non-blocking / discard overflow, cflush DO/DONT) -- TODO: else JTAG stop and go: careful with watchdog and timer -- TODO: panics and software panics -- TODO: stack size tuning and canarying +- TODO: our main tool: serial console ... (but non-blocking / discard + overflow, cflush DO/DONT) +- TODO: else JTAG stop and go: careful with watchdog and timer +- TODO: panics and software panics +- TODO: stack size tuning and canarying +- TODO: Address the rest of the comments from https://crrev.com/c/445941 -- TODO: Address the rest of the comments from https://crrev.com/c/445941 +\[1]: bitmap: array of bits. -[1]: bitmap: array of bits. +[`hooks` testcases]: ../test/hooks.c diff --git a/docs/ec-3po-design.md b/docs/ec-3po-design.md index 56a217849b..79ec3ecf0f 100644 --- a/docs/ec-3po-design.md +++ b/docs/ec-3po-design.md @@ -32,21 +32,22 @@ while trying to parse strings from the EC console. This method can be fairly fragile as debug output can be interleaved with the console input. A lot of items could be improved by switching to this host command packet interface. -* Communicating in packets makes testing easier and more robust. - * When FAFT is running, the EC could be in a binary mode where it only - communicates in host command packets. These packets are easier to parse, - create, and filter on. - * With filtering, you get the added bonus of not having unwanted debug output. - * It allows us to really test the host command interface which is how the EC - talks to the AP anyways. -* Better testing of existing host command handlers. - * By speaking in host command packets, we can reuse the existing host command - handlers which is nice since we'll be using the same handlers that are used - to respond to the AP. -* FAFT would no longer have to worry about the console dropping characters. - * We can add error checking to the interpreter which would automatically retry - errors. This alleviates FAFT from trying to check if the EC had properly - received a line of input. (Ctrl+L) +* Communicating in packets makes testing easier and more robust. + * When FAFT is running, the EC could be in a binary mode where it only + communicates in host command packets. These packets are easier to parse, + create, and filter on. + * With filtering, you get the added bonus of not having unwanted debug + output. + * It allows us to really test the host command interface which is how the + EC talks to the AP anyways. +* Better testing of existing host command handlers. + * By speaking in host command packets, we can reuse the existing host + command handlers which is nice since we'll be using the same handlers + that are used to respond to the AP. +* FAFT would no longer have to worry about the console dropping characters. + * We can add error checking to the interpreter which would automatically + retry errors. This alleviates FAFT from trying to check if the EC had + properly received a line of input. (Ctrl+L) With better and more reliable tests, we can improve the quality of our EC codebase. @@ -63,15 +64,15 @@ be restricted by the type of chip. ### A richer EC console -* We could do things like on-the-fly console channel filtering. -* Coloring specific channels such as "mark all USB PD messages in green". -* Adding colors in general. -* Adding temporary console commands. -* Longer command history which survives EC reboot -* Searching command history -* Redirecting debug output to log files (which causes no interleaving of command - and debug output) -* Bang commands (`!foo`) +* We could do things like on-the-fly console channel filtering. +* Coloring specific channels such as "mark all USB PD messages in green". +* Adding colors in general. +* Adding temporary console commands. +* Longer command history which survives EC reboot +* Searching command history +* Redirecting debug output to log files (which causes no interleaving of + command and debug output) +* Bang commands (`!foo`) ### Better debuggability @@ -80,9 +81,9 @@ such as the keyboard locking up on certain keys or rows. At times like that, it would be nice to have an EC console to see what's going on. Other times maybe having a servo connected might make the issue not present itself. -* We could do cool things like having an EC console without having to hook up - servo. -* Run `ectool` from the chroot using a PTY interface. +* We could do cool things like having an EC console without having to hook up + servo. +* Run `ectool` from the chroot using a PTY interface. ## Deployment Strategy @@ -99,28 +100,28 @@ Phase 1 will most likely consist of getting EC-3PO in place in between servo and the EC while not modifying the behavior of the console too much. In this phase, we can replicate the console interface and achieve the following things. -* Replicate command editing. -* Save command history. -* Add error checking to the console commands. +* Replicate command editing. +* Save command history. +* Add error checking to the console commands. ### Phase 2: Assimilation Phase 2 will start to introduce the host command packet communication. -* Printing will be done via packets and assembled in EC-3PO. -* Console commands now are sent using the host command packets. - * This will be incremental as console commands are converted. -* Add debug output filtering and redirection/logging. +* Printing will be done via packets and assembled in EC-3PO. +* Console commands now are sent using the host command packets. + * This will be incremental as console commands are converted. +* Add debug output filtering and redirection/logging. ### Phase 3: Expansion Phase 3 will expand the feature set of EC-3PO. -* Add PTY interface to `ectool`. -* Add on-device console without `servod`. -* Colored output. -* Command history search. -* Bang commands (`!foo`) +* Add PTY interface to `ectool`. +* Add on-device console without `servod`. +* Colored output. +* Command history search. +* Bang commands (`!foo`) ## High Level Design & Highlights @@ -132,7 +133,7 @@ UART.](./images/ec-3po-high-level-design.png) Each host command is a 16-bit command value. Commands which take parameters or return response data specify `struct`s for that data. See -[`include/ec_commands.h`](https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h) +[`include/ec_commands.h`](https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/include/ec_commands.h) for the current format of request and replies. Currently, there are no changes made to the format of the host request and response structures. @@ -170,12 +171,12 @@ EC-3PO and the EC can perform error checking when sending the commands to the EC. This feature would be implemented prior to switching to the binary format. The interpreter can package the command in the following manner. -* 2 Ampersands -* 2 hex digits representing the length of the command -* 2 hex digits representing the CRC-8 of the command -* 1 Ampersand -* The command itself -* 2 newline characters. +* 2 Ampersands +* 2 hex digits representing the length of the command +* 2 hex digits representing the CRC-8 of the command +* 1 Ampersand +* The command itself +* 2 newline characters. This is robust because no commands currently start with `&`. If the EC does not see ‘`&&`', then one of the ampersands has been dropped. If the EC doesn't see @@ -295,10 +296,10 @@ prompt by pressing ‘%' . These were originally added for debug purposes. ##### Supported Commands -* `loglevel ` - * Allows setting the effective loglevel of the console and interpreter. -* `interrogate [enhanced]` - * Allows control of when and how often interrogation occurs. +* `loglevel ` + * Allows setting the effective loglevel of the console and interpreter. +* `interrogate [enhanced]` + * Allows control of when and how often interrogation occurs. ### Interpreter module @@ -323,4 +324,3 @@ Since the interpreter communicates using pipes, it's not necessary that the user use the console module. For example, FAFT could directly connect to the interpreter and send down commands and receive command responses instead of having to deal with the PTY and instead just deal with python objects. - diff --git a/docs/ec-3po.md b/docs/ec-3po.md index 83877374aa..dae7b9babb 100644 --- a/docs/ec-3po.md +++ b/docs/ec-3po.md @@ -5,9 +5,9 @@ ## What is EC-3PO? EC-3PO is the console interpreter that will one day replace the EC console that -we have today. EC-3PO aims to migrate our rich debug console from the EC itself -to the host. This allows us to maintain our rich debug console without -impacting our EC image sizes while also allowing us to add new features. +we have today. EC-3PO aims to migrate our rich debug console from the EC itself +to the host. This allows us to maintain our rich debug console without impacting +our EC image sizes while also allowing us to add new features. For more information, see [the design doc](./ec-3po-design.md). @@ -42,9 +42,9 @@ apparently, `cu` wants group write permissions. On Ubuntu at least, the PTY is created with the `tty` group. If on your machine it's not, then just replace `tty` with whatever group it's created with. -1. Create a `tty` group if you don't have one already. -1. Add root to the `tty` group. -1. Rerun `cu` with `sudo` and it should work now. +1. Create a `tty` group if you don't have one already. +1. Add root to the `tty` group. +1. Rerun `cu` with `sudo` and it should work now. ## Why does the console seem "laggier" than before? @@ -57,10 +57,10 @@ delay is unbearable. To disable the delay: -1. Open the EC console. -1. Press `%` -1. Enter `interrogate never` -1. Then press enter. +1. Open the EC console. +1. Press `%` +1. Enter `interrogate never` +1. Then press enter. \**For `socat` users, due to the line buffered nature, you'll have to just enter `%interrogate never`. Notice the lack of the space character between `%` and the diff --git a/docs/ec-host-command-api.md b/docs/ec-host-command-api.md new file mode 100644 index 0000000000..007df04e0b --- /dev/null +++ b/docs/ec-host-command-api.md @@ -0,0 +1,69 @@ +# EC Host Command API + +## Overview + +The EC provices a control channel on an external interface using SPI, +LPC, or I2C bus. The low level details of the protocol used on this +interface is captured in [AP-EC-COMM](ap-ec-comm.md). + +The entity connected to the other side of this control channel is +typically the "AP" (application processor) - the main processor of a +system running a full-blown operating system. + +## `ec_commands.h` + +The EC implements hundreds of "host commands" (operations) to support +the AP. These are organized as an opcode and data structures defining +the input and output data for each opcode. `include/ec_commands.h` +defines all of the available opcodes and associated data structures. + +For example, the `HELLO` host command is defined as: + +`#define EC_CMD_HELLO 0x0001` + +It takes a `struct ec_params_hello` as input and returns a +`struct ec_response_hello`. + +The vast majority of host commands follow this simple naming pattern, +but exceptions have crept in over time, generally unintentionally, as +there is no mechanism to validate that this pattern has been followed. +Also, implementers must be careful to use the intended combination of +host commands and data types as there is no mechanism to validate the +correct combination has been used. + +## `ec_cmd_api.h` + +`ec_cmd_api.h` extends `ec_commands.h` by providing a function based +host command API. The `HELLO` host command from the previous example can +be invoked using a function provided by `ec_cmd_api.h`: + +``` +int ec_cmd_hello(CROS_EC_COMMAND_INFO *h, + const struct ec_params_hello *p, + struct ec_response_hello *r) +``` + +where `CROS_EC_COMMAND_INFO` is defined by the application for its house-keeping. +It is intended to be a connection handle or other state information needed by +the caller to communicate with the EC. + +The application also needs to provide an implementation of +`cros_ec_command` that performs the actual communication with the EC. + +``` +int CROS_EC_COMMAND(CROS_EC_COMMAND_INFO *h, + int command, int version, + const void *outdata, int outsize, + void *indata, int insize) +``` + +## Maintaining `ec_cmd_api.h` + +`ec_cmd_api.h` consists of 2 sections corresponding to the different +methods used to determine the host command API function signature: + +1. This section consists of functions that do not follow a simple + pattern and need to be specified explicitly. + +2. This section consists of functions that can be generated with the + help of template macros. diff --git a/docs/ec_terms.md b/docs/ec_terms.md index 4f1b590b1a..0349218e98 100644 --- a/docs/ec_terms.md +++ b/docs/ec_terms.md @@ -1,12 +1,13 @@ # EC Acronyms and Technologies ## Glossary -* **8042 Interface**{#8042} + +* **8042 Interface** {#8042} Interface for sending keyboard events to the [AP](#ap) and for receiving commands from the AP. Only supported by x86 based APs. -* **ACCEL - Accelerometer**{#accel} +* **ACCEL - Accelerometer** {#accel} A sensor that measures acceleration, typically over 3-axis. Nominally provides information about the orientation of a device. On Chromebook 2-in-1 @@ -14,57 +15,62 @@ the measurements from both accelerometers allows for a precise calculation of the lid angle, used to switch between tablet and laptop mode. -* **ACCELGYRO - Accelerometer/Gyroscope**{#accelgyro} +* **ACCELGYRO - Accelerometer/Gyroscope** {#accelgyro} A combination [accelerometer](#accel) and [gyroscope](#gyro) sensor that provides more precise orientation information by measuring both linear and rotational motion. -* **ADC - Analog to Digital Converter**{#adc} +* **ADC - Analog to Digital Converter** {#adc} A sensor that converts an analog voltage to a digital reading. -* **ALS - Ambient Light Sensor**{#als} +* **ALS - Ambient Light Sensor** {#als} A sensor that measures the ambient light present. Used to automatically control the screen and keyboard backlight level. -* **AP - Application Processor**{#ap} +* **AP - Application Processor** {#ap} The processor on the board that boots and runs ChromeOS. -* **BAR - Barometer**{#bar} +* **BAR - Barometer** {#bar} A sensor that measures atmospheric pressure. -* **BC12 - Battery Charging**{#bc12} +* **BC12 - Battery Charging** {#bc12} A device that implements the USB Battery Charging specification, version 1.2. The complete [BC 1.2 Specification] is available from the USB Implementers Forum. -* **CBI - CROS Board Information**{#cbi} +* **CBI - CROS Board Information** {#cbi} A collection of properties describing the board. This includes board version, SKU, model name, and other fields. More details are found in the [CrOS Board Info] documentation. -* **CEC - Consumer Electronics Control**{#cec} +* **CEC - Consumer Electronics Control** {#cec} - A one-wire bidirectional bus. More details are on the [CEC Wikipedia page]. + A one-wire bidirectional bus. More details are on the [CEC Wikipedia page]. -* **DPTF - Dynamic Power and Thermal Framework (Intel)**{#dptf} +* **DPTF - Dynamic Power and Thermal Framework (Intel)** {#dptf} Intel's platform based power and thermal management. See the [DPTF Readme] for details on the implementation used in ChromeOS. -* **EC - Embedded Controller**{#ec} +* **EC - Embedded Controller** {#ec} The [MCU](#mcu) used to control the keyboard, battery charging, USB port switching, sensor management, and other functions, offloading these tasks from the [AP](#ap). -* **EC-3PO**{#ec-3po} +* **ectool** {#ectool} + + The [ectool] is the [AP](#ap) console's CLI for sending commands to the + [EC](#ec). + +* **EC-3PO** {#ec-3po} A replacement of the current UART-based console which moves much of the code off the EC into a host tool, reducing the amount of flash space required. @@ -73,47 +79,47 @@ See the [USB-C documentation](./usb-c.md#emark) for more details. -* **eSPI - Enhanced Serial Peripheral Interface (Intel)**{#espi} +* **eSPI - Enhanced Serial Peripheral Interface (Intel)** {#espi} Intel's synchronous communication interface between the [AP](#ap) and the [EC](#ec). Supports quad I/O mode and clock speeds up to 66 Mhz, providing bandwidth up to 264 Mbps. The full [eSPI Specification] is available from Intel. -* **FAFT - Fully Automated Firmware Tests**{#faft} +* **FAFT - Fully Automated Firmware Tests** {#faft} A collection of tests and related infrastructure that exercise and verify - capabilities of Chrome OS. See the [FAFT design doc] and [chromium.org - documentation](https://www.chromium.org/for-testers/faft) for more details. - Replaced [SAFT](#saft). + capabilities of Chrome OS. See the [FAFT design doc] and + [chromium.org documentation](https://www.chromium.org/for-testers/faft) for + more details. Replaced [SAFT](#saft). * **GMR - Giant Magnetoresistance Sensor** {#gmr} A sensor device that detects a magnetic field. These sensors differ from [MAG](#mag) sensors, in that they only detect magnetic fields in close proximity to the sensor. On Chromebooks, GMR sensors are used to detect when - the lid is opened. On convertible Chromebooks, the GMR sensor also detects + the lid is opened. On convertible Chromebooks, the GMR sensor also detects tablet mode when lid the is opened a full 360 degrees. -* **GPIO - General Purpose Input/Output**{#gpio} +* **GPIO - General Purpose Input/Output** {#gpio} - An individual signal that can independently controlled and read. GPIOs are + An individual signal that can independently controlled and read. GPIOs are used to enable/disable power rails, drive reset signals, and receive - interrupts from devices connected to the EC. GPIOs may also be connected - to [I/O expanders](#ioexpander). + interrupts from devices connected to the EC. GPIOs may also be connected to + [I/O expanders](#ioexpander). -* **GYRO - Gyroscope**{#gyro} +* **GYRO - Gyroscope** {#gyro} A sensor that measures angular momentum, providing information about rotational motion of the device. -* **I/O Expander**{#ioexpander} +* **I/O Expander** {#ioexpander} An [I2C](#i2c) peripheral device that provides additional GPIO signals - (anywhere from 8 - 32 signals). GPIOs behind an I/O expander are written - and read using I2C register accesses from the I2C controller in the EC. + (anywhere from 8 - 32 signals). GPIOs behind an I/O expander are written and + read using I2C register accesses from the I2C controller in the EC. -* **I2C - Inter-Integrated Circuit**{#i2c} +* **I2C - Inter-Integrated Circuit** {#i2c} A 2-wire synchronous communication bus, consisting of a clock signal and a bidirectional data signal. An I2C bus typically contains one controller @@ -121,119 +127,142 @@ supported clock speeds of 100 KHz and 400 KHz. The full [I2C Specification] is available from NXP (formerly Phillips). -* **LED - Light Emitting Diode**{#led} +* **LED - Light Emitting Diode** {#led} A Light Emitting Diode is a semiconductor that emits light when current flows through it. -* **LPC - [Low Pin Count bus]**{#lpc} +* **LPC - [Low Pin Count bus]** {#lpc} Legacy communication bus between the [AP](#ap) and [EC](#ec). Runs at 33 - MHz, providing a 133 Mbps bandwidth connection. Replaced by the + MHz, providing a 133 Mbps bandwidth connection. Replaced by the [eSPI](#espi) interface. -* **MAG - Magnetometer**{#mag} +* **MAG - Magnetometer** {#mag} A digital compass sensor, providing orientation for navigation. -* **MCU - Microcontroller Unit**{#mcu} +* **MCU - Microcontroller Unit** {#mcu} A small integrated chip containing a CPU core, on-chip ROM, on-chip RAM. Also contains multiple peripheral interfaces, including GPIO, I2C buses, SPI buses, ADC, PWM, etc. -* **MKBP - Matrix Keyboard Protocol**{#mkbp} +* **MKBP - Matrix Keyboard Protocol** {#mkbp} Message based protocol for communicating asynchronous events from the [EC](#ec) to the [AP](#ap). Events are not limited to keyboard events with the sensor subsystem as one of the main users. An EC board implementation - can be configured to send keyboard events through MKBP or using the [8042 - interface](#8042). This is the [EC MKBP driver] implementation. + can be configured to send keyboard events through MKBP or using the + [8042 interface](#8042). This is the [EC MKBP driver] implementation. -* **MST - Multi Stream Transport**{#mst} +* **MST - Multi Stream Transport** {#mst} Part of the Display Port 1.2 standard, used to drive multiple independent video streams from a single display port. The EC code is typically responsible for enabling and disabling the MST hub chipset. -* **OOBM - Out of Band Management**{#oobm} +* **OOBM - Out of Band Management** {#oobm} A command in the [EC-3PO protocol](#ec-3po) that allows commands to be entered to alter the behaviour of the console and interpreter during runtime. -* **PD - USB Power Delivery**{#pd} +* **PD - USB Power Delivery** {#pd} See the [USB-C documentation](./usb-c.md#pd) for more details. -* **PMIC - Power Management IC**{#pmic} +* **PMIC - Power Management IC** {#pmic} An integrated circuit used to turn power rails on and off. -* **PPC - USB Power Path Controller**{#ppc} +* **PPC - USB Power Path Controller** {#ppc} See the [USB-C documentation](./usb-c.md#ppc) for more details. -* **PWM - Pulse Width Modulation**{#pwm} +* **PWM - Pulse Width Modulation** {#pwm} Method of varying the duty cycle of a signal to control another device. A typical application is to control fan speeds or the brightness of a backlight. -* **SAFT - Semi-Automated Firmware Tests**{#saft} +* **Retimer** {#retimer} + + A device that can extract the embedded clock signal from a high-speed + protocol, fully recover the data, and retransmit a fresh copy of the data + using a clean clock. + +* **SAFT - Semi-Automated Firmware Tests** {#saft} A suite of tests for firmware, succeeded by [FAFT](#faft). See the [chromium.org documentation](https://www.chromium.org/for-testers/saft) for more details. -* **SPI - Serial Peripheral Interconnect**{#spi} +* **SHI - SPI Host Interface** {#shi} + + [SPI](#spi) host interface used for communication between the AP and the EC. + In this configuration, the AP provides the SPI controller and the EC + provides the SPI peripheral. This interface is only used for non-x86 base + APs. + + x86-based APs use either the [eSPI](#espi) or [LPC](#lpc) interface. + +* **SPI - Serial Peripheral Interconnect** {#spi} A 4-wire synchronous communication bus consisting of the signals CLK (clock), SDO (Serial Data Out), SDI (Serial Data In), and CS (chip-select, - one per SPI peripheral). The SDO and SDI pins are defined from the + one per SPI peripheral). The SDO and SDI pins are defined from the perspective of the device: the SPI controller's SDO pin connects to the SPI peripheral's SDI pin and vice-versa. Clock speeds over 100 MHz are supported. SPI communication involves the following sequence: - * SPI controller asserts CS. - * SPI controller transmits one or bytes on its SDO signal, received by the - SPI peripheral on its SDI signal. - * SPI peripheral transmits zero or more bytes on its SDO signal, received - by the SPI controller on its SDI signal. - * SPI controller de-asserts CS. + * SPI controller asserts CS. + * SPI controller transmits one or bytes on its SDO signal, received by the + SPI peripheral on its SDI signal. + * SPI peripheral transmits zero or more bytes on its SDO signal, received + by the SPI controller on its SDI signal. + * SPI controller de-asserts CS. The specific contents of a SPI frame varies based on the SPI peripheral type. -* **SVDM - Structured Vendor Defined Messages**{#svdm} +* **SSMUX - Super Speed Multiplexer** {#ssmux} + + See the [USB-C documentation](./usb-c.md#ssmux) for more details. + +* **SVDM - Structured Vendor Defined Messages** {#svdm} See the [USB-C documentation](./usb-c.md#svdm) for more details. -* **TCPC - USB Type-C Port Controller**{#tcpc} +* **TCPC - USB Type-C Port Controller** {#tcpc} See the [USB-C documentation](./usb-c.md#tcpc) for more details. -* **UART - Universal Asynchronous Receiver Transceiver**{#uart} +* **UART - Universal Asynchronous Receiver Transceiver** {#uart} - Also known as a serial port. An asynchronous communication channel between + Also known as a serial port. An asynchronous communication channel between two devices with a dedicated receive pin, transmit pin, and ground. Optional hardware flow control signals require additional connections between the devices. Standard transmission rates are slow (up to 115200 bits per second). Typical use is to provide a debug console to the EC. [RS-232] is the protocol standard used by UARTs. +* **USBA - USB Type-A** {#usba} + + Traditional USB Host port. + * **VCONN - Connector Voltage** {#vconn} See the [USB-C documentation](./usb-c.md#vconn) for more details. - [BC 1.2 Specification]: -[CrOS Board Info]: [CEC Wikipedia page]: -[DPTF Readme]: -[eSPI Specification]: -[FAFT design doc]: +[CrOS Board Info]: +[DPTF Readme]: +[EC MKBP driver]: +[FAFT design doc]: [I2C Specification]: -[RS-232]: -[EC MKBP driver]: [Low Pin Count bus]: https://en.wikipedia.org/wiki/Low_Pin_Count +[RS-232]: +[eSPI Specification]: +[ectool]: ../docs/ap-ec-comm.md diff --git a/docs/fingerprint/fingerprint-authentication-design-doc.md b/docs/fingerprint/fingerprint-authentication-design-doc.md index 396fbfe8d0..9f73bd18bc 100644 --- a/docs/fingerprint/fingerprint-authentication-design-doc.md +++ b/docs/fingerprint/fingerprint-authentication-design-doc.md @@ -1,4 +1,4 @@ -# Fingerprint Authentication on Chrome OS +# Fingerprint Authentication on ChromeOS Authors: norvez@google.com, vpalatin@google.com @@ -31,17 +31,17 @@ Last Updated: 2019-01-14 To unlock their Chromebook users have to enter their password or a PIN. [Windows] and [macOS] let the user authenticate with their fingerprint for -faster unlocking, we want to bring that capability to Chrome OS. +faster unlocking, we want to bring that capability to ChromeOS. ### Fingerprint matching basics #### Fingerprint enrollment When a user wants to register their finger for fingerprint authentication, they -go through the _enrollment_ operation. They are asked to touch the sensor +go through the *enrollment* operation. They are asked to touch the sensor multiple times with different parts of their fingerprint. The [matching algorithm] uses the images captured during enrollment to build a model -of that fingerprint (known as a _template_). +of that fingerprint (known as a *template*). #### Fingerprint matching @@ -78,7 +78,7 @@ There are two main objectives for potential attackers: ### Privacy and security * Biometric data is particularly sensitive, so all operations on fingerprint - data must happen in a _Secure Biometric Processor_ (**SBP**). Attackers must + data must happen in a *Secure Biometric Processor* (**SBP**). Attackers must not gain access to the user’s fingerprints even if they have exploited the software running on the AP. * To protect the user’s privacy, fingerprint data must not be accessible @@ -101,7 +101,7 @@ attack surface again. ## Overview {#overview} Devices have a dedicated microcontroller (MCU) running a firmware based on the -[Chromium OS EC] codebase that is used as the _Secure Biometric Processor_ +[Chromium OS EC] codebase that is used as the *Secure Biometric Processor* (**SBP**), where all enrollment and matching operations take place. Even if attackers gained control of the AP, they still would not be able to access the fingerprint (FP) data since it never leaves the SBP unencrypted. @@ -184,7 +184,7 @@ replace this post-launch with a mechanism similar to FP templates are AES-encrypted with `HW_Key`. `HW_Key` is bound to this specific SBP so encrypted templates can only be deciphered by this specific SBP. To ensure that a powerwash/recovery/WP toggle/.../ makes the encryption key -impossible to recover, `HW_Key` also depends on a secret held by the TPM. +impossible to recover, `HW_Key` also depends on a secret held by the [TPM]. We use an AEAD cipher (AES-GCM) to detect if the encrypted templates have been tampered with by an attacker controlling the AP. @@ -208,7 +208,7 @@ every time the TPM is cleared, for example if someone attempts to do a "[ccd open]" to disable the hardware WP. The following is a summary of the mechanism, see the specific design doc -[“TPM-seed for Fingerprint MCU”] for details. +[TPM Seed for Fingerprint MCU] for details. The TPM already holds a "[system key]" `Cros_Sys_Key` in NVRAM space that is used to derive the encryption key of the stateful partition. That "system key" @@ -322,7 +322,7 @@ Encrypted templates are stored in a “[cryptohome daemon store folder]” that only mounted/decrypted when the user has logged in. The templates are stored as JSON files with the following fields: -```JSON +```json { "biomanager": “CrosFpBiometricsManager” string "version": integer describing the version of the file format. Set to 1 at launch @@ -379,7 +379,7 @@ used to protect the EC in detachable keyboards as described in The SBP has a minimalistic RO firmware that contains the public part of an RSA-3072 exponent 3 key pair. The corresponding private key is only accessible -by the Chrome OS signers and is used to sign SBP firmwares. On boot the RO +by the ChromeOS signers and is used to sign SBP firmwares. On boot the RO firmware verifies the signature of the RW firmware. If the RW signature is valid, the RO firmware protects itself by setting the WP bit of the Flash then jumps to RW. @@ -573,7 +573,7 @@ could start sending D-Bus commands to biod. The enrollment/matching and image capture libraries are provided by a 3rd-party vendor in binary form. That proprietary blob went through a security audit by a -3rd party auditor (see the auditor’s [report][Security Audit Report]. +3rd party auditor (see the auditor’s [report][Security Audit Report]). On top of the security audit of the 3rd-party proprietary code, we limit the attack surface of those libraries by not directly exposing them to user input. @@ -714,45 +714,46 @@ The log file is `/var/log/cros_fp.log`. [Arm TrustZone]: https://www.arm.com/products/security-on-arm/trustzone [Authentication-Time User Secrets]: http://go/authentication-time-user-secrets [AuthSession]: https://chromium.googlesource.com/chromiumos/platform2/+/eae39a9ad1239f8fbfa8164255578b306ff6ba5c/biod/biometrics_manager.h#96 -[biod D-Bus API]: https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/system_api/dbus/biod/ -[biod upstart script]: https://chromium.googlesource.com/chromiumos/platform2/+/master/biod/init/biod.conf +[biod D-Bus API]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/system_api/dbus/biod/ +[biod upstart script]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/biod/init/biod.conf [ccd open]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md#Open-CCD [CDD]: https://source.android.com/compatibility/android-cdd#7_3_10_fingerprint_sensor -[Chromium OS EC]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/README.md +[Chromium OS EC]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/README.md [clobber-state]: https://chromium.googlesource.com/chromiumos/platform2/+/962ab1bc481db0cf504b5449eb3a3d5008ea7601/init/clobber_state.cc#475 -[cryptohome daemon store folder]: https://chromium.googlesource.com/chromiumos/docs/+/master/sandboxing.md#securely-mounting-cryptohome-daemon-store-folders +[cryptohome daemon store folder]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/sandboxing.md#securely-mounting-cryptohome-daemon-store-folders [cryptohome]: https://www.chromium.org/chromium-os/chromiumos-design-docs/protecting-cached-user-data [Detachable Base Swap Detection]: https://docs.google.com/document/d/1WYdkkSAL_RHVc5mUXnAvBBfAeM7Wj3ABa1dbeTdvm74/edit#heading=h.g74ijelumqop [Detachable Base Verified Boot Anti-Rollback]: http://go/detachable-base-vboot#heading=h.fimcm174ok3 [Detachable Base Verified Boot]: http://go/detachable-base-vboot#heading=h.dolfbdpggye6 -[EC primitives]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/README.md#Software-Features +[EC primitives]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/README.md#Software-Features [EnrollSession]: https://chromium.googlesource.com/chromiumos/platform2/+/eae39a9ad1239f8fbfa8164255578b306ff6ba5c/biod/biometrics_manager.h#92 [fingerprint authentication framework]: https://developer.android.com/about/versions/marshmallow/android-6.0.html#fingerprint-authentication -[fuzzed]: https://chromium.googlesource.com/chromiumos/platform2/+/master/biod/biod_storage_fuzzer.cc +[fuzzed]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/biod/biod_storage_fuzzer.cc [Global Read-out Protection (RDP) mode Level 1]: https://www.st.com/content/ccc/resource/technical/document/application_note/b4/14/62/81/18/57/48/05/DM00075930.pdf/files/DM00075930.pdf/jcr:content/translations/en.DM00075930.pdf [HKDF]: https://tools.ietf.org/html/rfc5869 [Input Key Material (IKM)]: https://en.wikipedia.org/wiki/HKDF [Intel SGX]: https://software.intel.com/en-us/sgx [macOS]: https://support.apple.com/en-us/HT207054 -[malloc/free memory module for Chrome EC]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/common/shmalloc.c +[malloc/free memory module for Chrome EC]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/common/shmalloc.c [matching algorithm]: https://en.wikipedia.org/wiki/Fingerprint#Algorithms -[mount_encrypted]: https://chromium.googlesource.com/chromiumos/platform2/+/master/cryptohome/mount_encrypted +[mount_encrypted]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/cryptohome/mount_encrypted [New UKM collection review - CrOS FP Unlock]: https://docs.google.com/document/d/1qjDCMcBcrhSeg_uwyEIRsXHKmzUTJahcg6a4YVhkuLo [Old Design Doc]: https://docs.google.com/document/d/1MdPRmCDkVg1HO9DdbvPT5fDZS2ICg5ys9_ok_K95EEU [PDD is here]: http://go/cros-fingerprint-pdd [Privacy fields for Fingerprints]: https://docs.google.com/spreadsheets/d/1jLfnuhfbrImpoxuj92OkAxS_GGrm7QkpQhsUQCkO9ec [Privacy fields for Fingerprints]: https://docs.google.com/spreadsheets/d/1jLfnuhfbrImpoxuj92OkAxS_GGrm7QkpQhsUQCkO9ec/ [RM0433]: https://www.st.com/content/ccc/resource/technical/document/reference_manual/group0/c9/a3/76/fa/55/46/45/fa/DM00314099/files/DM00314099.pdf/jcr:content/translations/en.DM00314099.pdf -[sandboxing]: https://chromium.googlesource.com/chromiumos/docs/+/master/sandboxing.md -[seccomp filter]: https://chromium.googlesource.com/chromiumos/platform2/+/master/biod/init/seccomp/biod-seccomp-amd64.policy -[Security Audit Report]: https://drive.google.com/a/google.com/file/d/0B1HHKpeDpzYnMDdocGxwWUhpckpWM0hMU0tPa2ZjdEFnLU53/ +[sandboxing]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/sandboxing.md +[seccomp filter]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/biod/init/seccomp/biod-seccomp-amd64.policy +[Security Audit Report]: https://drive.google.com/file/d/0B1HHKpeDpzYnMDdocGxwWUhpckpWM0hMU0tPa2ZjdEFnLU53/view?usp=sharing&resourcekey=0-utAJosm8Lwvx9TOz7F4i7w [state machine]: https://chromium.googlesource.com/chromiumos/platform/ec/+/90d177e3f0ae729bea7e24934a3c6ef9f2520d45/common/fpsensor.c#252 [statically allocated]: https://chromium.googlesource.com/chromiumos/platform/ec/+/90d177e3f0ae729bea7e24934a3c6ef9f2520d45/common/fpsensor.c#57 [system key]: https://chromium.googlesource.com/chromiumos/platform2/+/23b79133514ac2cd986bce21c398fb6658bda248/cryptohome/mount_encrypted/encryption_key.h#125 [UMA]: http://go/uma [Windows]: https://www.microsoft.com/en-us/windows/windows-hello [wrappers functions]: https://chrome-internal.googlesource.com/chromeos/platform/ec-private/+/9ebb3f10c611afff695f679aaeed1a35551a116b/fpc_sensor_pal.c#52 -[“TPM-seed for Fingerprint MCU”]: http://go/bio_tpm_seed +[TPM Seed for Fingerprint MCU]: ../fingerprint/fingerprint-tpm-seed.md +[TPM]: https://www.chromium.org/developers/design-documents/tpm-usage/ @@ -760,10 +761,13 @@ The log file is `/var/log/cros_fp.log`. appending "export/png" to the Google Drive link. --> + [Decryption Flowchart]: ../images/cros_fingerprint_decryption_flowchart.png + [Encryption Flowchart]: ../images/cros_fingerprint_encryption_flowchart.png + [Fingerprint Architecture]: ../images/cros_fingerprint_architecture_diagram.png diff --git a/docs/fingerprint/fingerprint-debugging.md b/docs/fingerprint/fingerprint-debugging.md index 7316ad3434..b015eb1199 100644 --- a/docs/fingerprint/fingerprint-debugging.md +++ b/docs/fingerprint/fingerprint-debugging.md @@ -1,7 +1,7 @@ # Fingerprint Debugging This document describes how to attach a debugger with SWD in order to debug the -FPMCU. +FPMCU with [`gdb`](#gdb) or to [flash the FPMCU](#flash). [TOC] @@ -22,39 +22,72 @@ used for JTAG and SWD for ARM devices. * JTAG/SWD Debugger Probe: Any debug probe that supports SWD will work, but this document assumes that you're using a [Segger J-Trace PRO for Cortex-M][J-Trace]. -* [Dragonclaw v0.2 Development board][FPMCU dev board]. +* [Dragonclaw v0.3 Development board][FPMCU dev board] or + [Icetower v0.1 Development board][FPMCU dev board]. * [Servo Micro]. ## Software Required -* [JLink Software] \(when using [J-Trace] or other Segger debug probes). -* Any tool that supports connecting `gdbserver`. This document will assume - [CLion] and was tested with `JLink_Linux_V684a_x86_64`. -* Alternatively, you can use [Ozone] a standalone debugger from Segger. +* [JLink Software] \(when using [J-Trace] or other Segger debug probes). This + is the only software required for flashing. +* In order to perform breakpoint debugging, you will need a tool that supports + connecting `gdbserver`. This document will assume [CLion] \(Googlers see + [CLion for ChromeOS]) and was tested with `JLink v6.94a`. Alternatively, you + can use [Ozone], a standalone debugger from Segger. -## Connecting SWD +## JLink Software {#software} -The connector for SWD is `J4` on Dragonclaw v0.2. +Install the JLink software in the chroot with the following command: +```bash +(chroot) $ sudo emerge jlink +``` + + +*** note +**NOTE**: The above command will print out a message directing you to manually +download a tarball. You must follow these instructions for the installation to +be complete. +*** + + +## Connecting SWD {#connect-swd} + +### Dragonclaw v0.3 + +The connector for SWD is `J4` on Dragonclaw v0.3. + + *** note **NOTE**: Pay attention to the location of pin 1 (red wire) in the photos below so that you connect with the correct orientation. -`SW2` on the bottom of Dragonclaw must be set to `CORESIGHT`. +`SW2` on the edge of Dragonclaw must be set to `CORESIGHT`. If you want to connect a 20-Pin ARM Standard JTAG Connector (0.10" / 2.54 mm), you can use the following [adapter][JTAG to SWD Adapter] and [cable][SWD Cable]. *** + -Dragonclaw v0.2 with 20-pin SWD (0.05" / 1.27mm) on J4. Only half the pins are connected. | +Dragonclaw v0.3 with 20-pin SWD (0.05" / 1.27mm) on J4. Only half the pins are connected. | ----------------------------------------------------------------------------------------- | ![Dragonclaw with 20-pin SWD] | -Dragonclaw v0.2 with 10-pin SWD (0.05" / 1.27mm) on J4. | +Dragonclaw v0.3 with 10-pin SWD (0.05" / 1.27mm) on J4. | ------------------------------------------------------- | ![Dragonclaw with 10-pin SWD] | -## Powering the Board +### Icetower v3 + +The connector for SWD is labeled with `CORESIGHT20 DB CONN` on Icetower v3. + +`JTAG` on Icetower must be set to `CORESIGHT` (not `SERVO`). + +Icetower v3 with 20-pin SWD (0.05" / 1.27mm) on `CORESIGHT20 DB CONN`. | +---------------------------------------------------------------------- | +![Icetower with 20-pin SWD] | + +## Powering the Board {#power} [Servo Micro] can provide both the 3.3V for the MCU and 1.8V for the sensor. @@ -62,29 +95,83 @@ Run the following to start `servod`, which will enable power to these rails by default: ```bash -(chroot) $ sudo servod --board=dragonclaw +(chroot) $ sudo servod --board= +``` + +where `` is the board you are working with +([`dartmonkey` or `bloonchipper`][fingerprint hardware]). + +Theoretically, it's also possible to power through J-Trace, though the +[power pin] on J-Trace only outputs 5V, whereas the MCU runs at 3.3V and the +sensor runs at 1.8V. The pin is also not connected on the current designs. + +## Flashing the FPMCU with JLink {#flash} + +* Install the [JLink Software](#software). +* [Connect SWD](#connect-swd). +* [Power the board with servo](#power). +* Start the JLink server: + +```bash +(chroot) $ cd ~/trunk/src/platform/ec +``` + +```bash +# JLinkRemoteServerCLExe will listen on port 19020 (among others) by default. +# This can be overridden with the -Port argument. +(chroot) $ sudo JLinkRemoteServerCLExe -select USB +``` + +You should see the following: + +```bash +SEGGER J-Link Remote Server V6.94a +Compiled Jan 14 2021 11:52:48 + +'q' to quit '?' for help + +Connected to J-Link with S/N 123456 + +Waiting for client connections... +``` + +* Build the FPMCU image: + +```bash +(chroot) $ cd ~/trunk/src/platform/ec +``` + +```bash +(chroot) $ make BOARD= -j +``` + +replacing `` with [`bloonchipper` or `dartmonkey`][fingerprint hardware]. + +* Run the [`flash_jlink.py`] script: + +```bash +(chroot) $ ~/trunk/src/platform/ec/util/flash_jlink.py --board --image ./build//ec.bin ``` -It's also possible to power through J-Trace, though this can only supply the MCU -with power (3.3V), not a sensor using 1.8V. +replacing `` with [`bloonchipper` or `dartmonkey`][fingerprint hardware]. -## Using JLink gdbserver +## Using JLink gdbserver {#gdb} Start the JLink gdbserver for the appropriate MCU type: * Dragonclaw / [Nucleo STM32F412ZG]: `STM32F412CG` -* Dragontalon / [Nucleo STM32H743ZI]: `STM32H743ZI` +* Icetower / [Nucleo STM32H743ZI]: `STM32H743ZI` ```bash -(outside) $ ./JLink_Linux_V684a_x86_64/JLinkGDBServerCLExe -select USB -device STM32F412CG -endian little -if SWD -speed auto -noir -noLocalhostOnly +(chroot) $ JLinkGDBServerCLExe -select USB -device STM32F412CG -endian little -if SWD -speed auto -noir -noLocalhostOnly ``` -You should see the port that gdbserver is running on in the output: +You should see the port that `gdbserver` is running on in the output: ```bash Connecting to J-Link... J-Link is connected. -Firmware: J-Trace PRO V2 Cortex-M compiled Dec 13 2019 11:19:22 +Firmware: J-Trace PRO V2 Cortex-M compiled Feb 5 2021 14:50:19 Hardware: V2.00 S/N: XXXXX Feature(s): RDI, FlashBP, FlashDL, JFlash, GDB @@ -110,7 +197,7 @@ In your editor, specify the IP address and port for `gdbserver`: You will also want to provide the symbol files: * RW image: `build//RW/ec.RW.elf` -* RO image: `build//RO.ec.RO.elf` +* RO image: `build//RO/ec.RO.elf` Also, since we're compiling the firmware in the chroot, but your editor is running outside of the chroot, you'll want to remap the source code path to @@ -143,7 +230,7 @@ Ozone is a free standalone debugger provided by Segger that works with the gdbserver can provide. For example, Ozone has a register mapping for the MCUs we use, so you can easily inspect CPU registers. It can also be automated with a scripting language and show code coverage when used with a [J-Trace] that is -connected to the trace pins on a board. Note that the Dragonclaw v0.2 uses an +connected to the trace pins on a board. Note that the Dragonclaw v0.3 uses an STM32F412 package that does not have the synchronous trace pins, but the [Nucleo STM32F412ZG] does have the trace pins. @@ -156,14 +243,19 @@ STM32F412 package that does not have the synchronous trace pins, but the [SWD Cable]: https://www.adafruit.com/product/1675 [Ozone]: https://www.segger.com/products/development-tools/ozone-j-link-debugger/ [CLion]: https://www.jetbrains.com/clion/ +[CLion for ChromeOS]: http://go/clion-for-chromeos [GDB Remote Debug Configuration]: https://www.jetbrains.com/help/clion/remote-debug.html#remote-config [CLion Start Remote Debug]: https://www.jetbrains.com/help/clion/remote-debug.html#start-remote-debug [Nucleo STM32F412ZG]: https://www.st.com/en/evaluation-tools/nucleo-f412zg.html [Nucleo STM32H743ZI]: https://www.st.com/en/evaluation-tools/nucleo-h743zi.html [`.gdbinit`]: /util/gdbinit [configure `~/.gdbinit`]: https://www.jetbrains.com/help/clion/configuring-debugger-options.html#gdbinit-lldbinit +[power pin]: https://www.segger.com/products/debug-probes/j-link/technology/interface-description/ +[fingerprint hardware]: ./fingerprint.md#hardware +[`flash_jlink.py`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/util/flash_jlink.py [Dragonclaw with 20-pin SWD]: ../images/dragonclaw_with_20_pin_swd.jpg [Dragonclaw with 10-pin SWD]: ../images/dragonclaw_with_10_pin_swd.jpg +[Icetower with 20-pin SWD]: ../images/icetower_with_20_pin_swd.jpg diff --git a/docs/fingerprint/fingerprint-dev-for-partners.md b/docs/fingerprint/fingerprint-dev-for-partners.md index 1aef3735fb..f2fe8fd34b 100644 --- a/docs/fingerprint/fingerprint-dev-for-partners.md +++ b/docs/fingerprint/fingerprint-dev-for-partners.md @@ -27,126 +27,80 @@ The Fingerprint MCU (FPMCU) board has the MCU that handles all fingerprint-related functionality (matching, encryption, etc). The fingerprint sensor itself connects to the FPMCU board. -This FPMCU board is the Dragonclaw Rev 0.2. | + +*** note +Older revisions of these boards are not supported. If you have an older version +of the board, please request a replacement. +*** + + +This FPMCU board is the Dragonclaw Rev 0.3. | ------------------------------------------- | ![Dragonclaw board] | Download the [Dragonclaw schematics, layout, and BOM][dragonclaw schematics]. + *** note -**Googlers**: You can pick up the Dragonclaw development board at Chromestop. +**Googlers**: You can pick up a Dragonclaw development board at Chromestop. + **Partners**: You can request a Dragonclaw development board from Google. *** + +This FPMCU board is Icetower Rev 3. | +----------------------------------- | +![Icetower board] | + + *** note -Dragonclaw Rev 0.2 needs a [rework](#dragonclaw-rev-0.2-rework) for the FPC -sensor to work while being powered through Servo. All of the boards at Chromestop -have already been reworked. -*** +**Googlers**: You can pick up an Icetower development board at Chromestop. -This FPMCU board is the Dartmonkey Rev 0.1. | -------------------------------------------- | -![Dartmonkey board] | +**Partners**: You can request an Icetower development board from Google. +*** + ### Servo Servo is a general purpose debug board that connects to a header on the FPMCU board. Among other things, the servo supplies power to the FPMCU and can be used to program the FPMCU, interact with the EC console, take power measurements, and -debug a running program. It supports SPI, UART, I2C, as well as JTAG/SWD. +debug a running program. -There are two different servo debugger setups supported, the -[Servo Micro](#servo-micro) and the [Servo V2 + Yoshi](#servo-v2-yoshi). The -servo micro is recommended for its simplicity. It lacks builtin JTAG/SWD support -for single step debugging, but Dragonclaw v0.2 has an +There are several variants of Servo and the fingerprint team uses the +[Servo Micro](#servo-micro) for its simplicity. It lacks builtin JTAG/SWD +support for single step debugging, but Dragonclaw v0.3 and Icetower v3 have an [SWD connector](#servo-micro-swd) that can be used. -[Servo Micro](#servo-micro) | [ServoV2 + Yoshi](#servo-v2-yoshi) ---------------------------- | ---------------------------------- -![Servo Micro] | ServoV2 ![Servo v2] Yoshi Flex ![Standard Yoshi Flex] +[Servo Micro](#servo-micro) | +--------------------------- | +![Servo Micro] | + *** note -For more information about both servos, see [servo]. +For more information about Servo, see [servo]. *** + ### Servo Micro -Unlike the Servo V2, the newer servo micro does not require any adapters to -interface with the FPMCU board. +Servo Micro does not require any adapters to interface with the FPMCU board. As you can see below, one end connects to the FPMCU board and the other connect to the developer's computer over micro USB. ![Servo Micro with Dragonclaw] + *** note For more information about Servo Micro, see [Servo Micro Info]. *** + #### Using SWD (Optional) {#servo-micro-swd} Instructions for setup are described in [Fingerprint Debugging]. -### Servo V2 + Yoshi - -Servo V2 is the original full featured debugger. It requires a -[Yoshi Flex Cable](#yoshi-flex-cable) to interface with the FPMCU. - -![Servo v2] - -*** note -NOTE: More information on servo can be found in the [servo] documentation. -*** - -#### Yoshi Flex Cable - -The Yoshi Flex cable is used to connect Servo v2 to the FPMCU board. The -standard cable does not work with SWD, but a simple rework can be performed to -support SWD. - -Standard Yoshi Flex | Yoshi Flex Reworked to Support SWD ----------------------- | ------------------------------------- -![Standard Yoshi Flex] | ![Yoshi Flex Reworked to Support SWD] - -Rework steps: - -* Remove R18 and R19 -* Wire from Pin 6 of U21 to right side of R18 -* Wire from Pin 6 of U21 to right side of R19 - -#### Micro USB Cable - -A micro USB cable is needed to connect the the servo v2 board to your host Linux -development machine. - -* [Micro USB Cable] - -#### Servo V2 Hardware Setup - -1. Connect the Yoshi Flex cable to servo, paying attention to the pin - numbering. - - ![Connect Yoshi Flex] ![Another Yoshi Flex image] - -2. Connect the other end of the Yoshi Flex cable to the servo header on the - FPMCU board. - - ![Connect Yoshi Flex to FPMCU board] ![Another image] - -3. Connect the fingerprint sensor to the header on the FPMCU board. - -4. Connect the micro USB cable to servo's `HOST_IN` port. The other end of the - USB cable should be plugged into your host development machine. - - ![Connect USB to Servo] - -5. Optional: Connect SWD Debugger - - If you want to use SWD for debugging, connect your debugger to the `JTAG` - header on servo v2. - - ![Connect SWD Debugger] - ## Software Setup ### Get the Chromium OS source code @@ -164,13 +118,15 @@ Open **two** terminals and enter the chroot in each: # from a terminal on your machine (outside chroot) $ cd ~/chromiumos/src -# enter the chroot (the flag is important) -(outside chroot) $ cros_sdk --no-ns-pid +# enter the chroot +(outside chroot) $ cros_sdk ``` + *** note NOTE: More information on servo can be found in the [servo] documentation. *** + In one of the terminals, build and start `servod` @@ -180,10 +136,12 @@ Build and install `servod` in the chroot: (chroot) $ sudo emerge hdctools ``` + *** note In all of the following commands, replace `` in the command with `bloonchipper` or `dartmonkey` depending on the development board you are using. *** + Run `servod`: @@ -194,75 +152,114 @@ Run `servod`: You should see something like this. Leave it running: ```bash -2019-04-11 15:21:53,715 - servod - INFO - Start -2019-04-11 15:21:53,765 - servod - INFO - Found servo, vid: 0x18d1 pid: 0x5002 sid: 911416-00789 -2019-04-11 15:21:53,766 - servod - INFO - Found XML overlay for board zerblebarn -2019-04-11 15:21:53,766 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/servo_v2_r1.xml, None, 0) -2019-04-11 15:21:53,767 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/servo_v2_r0.xml, None, 0) -2019-04-11 15:21:53,771 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/common.xml, None, 0) -2019-04-11 15:21:53,772 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/power_tools.xml, None, 0) -2019-04-11 15:21:53,774 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/keyboard.xml, None, 0) -2019-04-11 15:21:53,775 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/uart_common.xml, None, 0) -2019-04-11 15:21:53,777 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/ftdii2c_cmd.xml, None, 0) -2019-04-11 15:21:53,777 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/usb_image_management.xml, None, 0) -2019-04-11 15:21:53,784 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/servo_zerblebarn_overlay.xml, None, 0) -2019-04-11 15:21:53,785 - SystemConfig - INFO - Loading XML config (/usr/lib64/python2.7/site-packages/servo/data/servoflex_v2_r0_p50.xml, None, 0) -2019-04-11 15:21:53,792 - Servod - INFO - Initializing interface 1 to ftdi_empty -2019-04-11 15:21:53,792 - Servod - INFO - Initializing interface 2 to ftdi_i2c -2019-04-11 15:21:53,795 - Servod - INFO - Initializing interface 3 to ftdi_uart -2019-04-11 15:21:53,799 - Servod - INFO - /dev/pts/8 -2019-04-11 15:21:53,799 - Servod - INFO - Initializing interface 4 to ftdi_uart -2019-04-11 15:21:53,802 - Servod - INFO - /dev/pts/9 -2019-04-11 15:21:53,802 - Servod - INFO - Use the next FTDI part @ pid = 0x5003 -2019-04-11 15:21:53,802 - Servod - INFO - Initializing interface 5 to ftdi_empty -2019-04-11 15:21:53,802 - Servod - INFO - Use the next FTDI part @ pid = 0x5003 -2019-04-11 15:21:53,802 - Servod - INFO - Initializing interface 6 to ftdi_empty -2019-04-11 15:21:53,802 - Servod - INFO - Use the next FTDI part @ pid = 0x5003 -2019-04-11 15:21:53,802 - Servod - INFO - Initializing interface 7 to ftdi_uart -2019-04-11 15:21:53,805 - Servod - INFO - /dev/pts/10 -2019-04-11 15:21:53,805 - Servod - INFO - Use the next FTDI part @ pid = 0x5003 -2019-04-11 15:21:53,805 - Servod - INFO - Initializing interface 8 to ftdi_uart -2019-04-11 15:21:53,808 - Servod - INFO - /dev/pts/11 -2019-04-11 15:21:53,808 - Servod - INFO - Initializing interface 9 to ec3po_uart -2019-04-11 15:21:53,811 - PD/Cr50 - EC3PO Interface - INFO - -------------------- PD/Cr50 console on: /dev/pts/12 -2019-04-11 15:21:53,811 - Servod - INFO - Initializing interface 10 to ec3po_uart -2019-04-11 15:21:53,812 - EC - EC3PO Interface - INFO - -------------------- EC console on: /dev/pts/14 -2019-04-11 15:21:54,316 - Servod - INFO - Initialized i2c_mux to rem -2019-04-11 15:21:54,317 - Servod - INFO - Initialized i2c_mux_en to on -2019-04-11 15:21:54,319 - Servod - INFO - Initialized pch_disable to off -2019-04-11 15:21:54,320 - Servod - INFO - Initialized jtag_buf_on_flex_en to off -2019-04-11 15:21:54,321 - Servod - INFO - Initialized cold_reset to off -2019-04-11 15:21:54,322 - Servod - INFO - Initialized warm_reset to off -2019-04-11 15:21:54,323 - Servod - INFO - Initialized spi1_buf_on_flex_en to off -2019-04-11 15:21:54,324 - Servod - INFO - Initialized spi_hold to off -2019-04-11 15:21:54,326 - Servod - INFO - Initialized pwr_button to release -2019-04-11 15:21:54,327 - Servod - INFO - Initialized lid_open to yes -2019-04-11 15:21:54,328 - Servod - INFO - Initialized spi2_buf_on_flex_en to off -2019-04-11 15:21:54,330 - Servod - INFO - Initialized rec_mode to off -2019-04-11 15:21:54,331 - Servod - INFO - Initialized fw_up to off -2019-04-11 15:21:54,332 - Servod - INFO - Initialized usb_mux_sel1 to dut_sees_usbkey -2019-04-11 15:21:54,333 - Servod - INFO - Initialized prtctl4_pwren to on -2019-04-11 15:21:54,334 - Servod - INFO - Initialized uart3_en to on -2019-04-11 15:21:54,334 - Servod - INFO - Initialized dut_hub_pwren to on -2019-04-11 15:21:54,335 - Servod - INFO - Initialized kbd_en to off -2019-04-11 15:21:54,337 - Servod - INFO - Initialized spi1_vref to pp3300 -2019-04-11 15:21:54,338 - Servod - INFO - Initialized spi2_vref to pp1800 -2019-04-11 15:21:54,339 - Servod - INFO - Initialized uart2_en to on -2019-04-11 15:21:54,340 - Servod - INFO - Initialized uart1_en to on -2019-04-11 15:21:54,341 - Servod - INFO - Initialized jtag_buf_en to off -2019-04-11 15:21:54,342 - Servod - INFO - Initialized fw_wp_en to off -2019-04-11 15:21:54,343 - Servod - INFO - Initialized sd_vref_sel to off -2019-04-11 15:21:54,343 - Servod - INFO - Initialized ec_ec3po_interp_connect to on -2019-04-11 15:21:54,344 - Servod - INFO - Initialized uart3_vref to off -2019-04-11 15:21:54,345 - Servod - INFO - Initialized jtag_vref_sel0 to pp3300 -2019-04-11 15:21:54,346 - Servod - INFO - Initialized jtag_vref_sel1 to pp3300 -2019-04-11 15:21:54,346 - Servod - INFO - Initialized fpmcu_ec3po_interp_connect to on -2019-04-11 15:21:54,349 - ServoDeviceWatchdog - INFO - Watchdog setup for devices: set([(6353, 20482, '911416-00789')]) -2019-04-11 15:21:54,351 - servod - INFO - Listening on localhost port 9999 +2023-02-03 15:05:30,632 - servod - INFO - Start +2023-02-03 15:05:30,639 - servod - INFO - Found XML overlay for board icetower +2023-02-03 15:05:30,639 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/servo_micro.xml, None, 0) +2023-02-03 15:05:30,640 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/common.xml, None, 0) +2023-02-03 15:05:30,640 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/power_tools.xml, None, 0) +2023-02-03 15:05:30,642 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/keyboard.xml, None, 0) +2023-02-03 15:05:30,644 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/uart_common.xml, None, 0) +2023-02-03 15:05:30,644 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/ec_info.xml, None, 0) +2023-02-03 15:05:30,645 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/cpu_fw_spi.xml, None, 0) +2023-02-03 15:05:30,645 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/servo_adc_enabled_noop.xml, None, 0) +2023-02-03 15:05:30,648 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/servo_icetower_overlay.xml, None, 0) +2023-02-03 15:05:30,648 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/servo_fpmcu_dev_board_common_overlay.xml, None, 0) +2023-02-03 15:05:30,649 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/servoflex_v2_r0_p50.xml, None, 0) +2023-02-03 15:05:30,649 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/fpmcu_dev_board_common_inas.xml, None, 0) +2023-02-03 15:05:30,649 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/ina2xx.xml, None, 0) +2023-02-03 15:05:30,650 - SystemConfig - INFO - Loading XML config (/usr/lib64/python3.6/site-packages/servo/data/servo_fpmcu_dev_board_uart_common_overlay.xml, None, 0) +2023-02-03 15:05:30,655 - Servod - INFO - Initializing interface 1 to stm32_uart +2023-02-03 15:05:30,655 - Interface.Build - INFO - Suart: interface: {'name': 'stm32_uart', 'interface': 0, 'index': 1} +2023-02-03 15:05:30,661 - Interface.Build - INFO - /dev/pts/2 +2023-02-03 15:05:30,661 - Servod - INFO - Initializing interface 2 to stm32_i2c +2023-02-03 15:05:30,661 - Interface.Build - INFO - Si2cBus: interface: {'name': 'stm32_i2c', 'interface': 4, 'index': 2} +2023-02-03 15:05:30,661 - root - INFO - Skipping modprobe of i2c-dev: it is already loaded per existence of: /sys/module/i2c_dev/ +2023-02-03 15:05:30,661 - root - INFO - Executing command: ['modprobe', '--quiet', '--', 'i2c-pseudo'] +2023-02-03 15:05:30,664 - i2c_base - INFO - path b'/dev/i2c-pseudo-controller' not found, cannot start I2C pseudo adapter +2023-02-03 15:05:30,665 - Servod - INFO - Initializing interface 3 to stm32_uart +2023-02-03 15:05:30,666 - Interface.Build - INFO - Suart: interface: {'name': 'stm32_uart', 'interface': 3, 'index': 3} +2023-02-03 15:05:30,670 - Interface.Build - INFO - /dev/pts/3 +2023-02-03 15:05:30,670 - Servod - INFO - Initializing interface 6 to ec3po_uart +2023-02-03 15:05:30,673 - servo_micro - EC3PO Interface - INFO - -------------------- servo_micro console on: /dev/pts/4 +2023-02-03 15:05:30,673 - Servod - INFO - Initializing interface 7 to stm32_uart +2023-02-03 15:05:30,673 - Interface.Build - INFO - Suart: interface: {'name': 'stm32_uart', 'interface': 6, 'index': 7} +2023-02-03 15:05:30,678 - Interface.Build - INFO - /dev/pts/6 +2023-02-03 15:05:30,678 - Servod - INFO - Initializing interface 8 to stm32_uart +2023-02-03 15:05:30,679 - Interface.Build - INFO - Suart: interface: {'name': 'stm32_uart', 'interface': 5, 'index': 8} +2023-02-03 15:05:30,684 - Interface.Build - INFO - /dev/pts/7 +2023-02-03 15:05:30,684 - Servod - INFO - Initializing interface 9 to ec3po_uart +2023-02-03 15:05:30,685 - PD/Cr50 - EC3PO Interface - INFO - -------------------- PD/Cr50 console on: /dev/pts/8 +2023-02-03 15:05:30,685 - Servod - INFO - Initializing interface 10 to ec3po_uart +2023-02-03 15:05:30,687 - EC - EC3PO Interface - INFO - -------------------- EC console on: /dev/pts/10 +2023-02-03 15:05:30,687 - Servod - INFO - Initializing interface 11 to ec3po_uart +2023-02-03 15:05:30,688 - CPU - EC3PO Interface - INFO - -------------------- CPU console on: /dev/pts/12 +2023-02-03 15:05:31,193 - Servod - INFO - Initialized init_keyboard to on +2023-02-03 15:05:31,194 - root - WARNING - cpu_ec3po_interp_connect: '1' not found in the param values +2023-02-03 15:05:31,195 - root - WARNING - cpu_ec3po_interp_connect: update drv to get and set values from the param map {'off': '0'} +2023-02-03 15:05:31,195 - Servod - INFO - Initialized cpu_ec3po_interp_connect to off +2023-02-03 15:05:31,200 - Servod - INFO - Initialized cpu_uart_raw_debug to off +2023-02-03 15:05:31,202 - Servod - INFO - Initialized cpu_uart_timestamp to off +2023-02-03 15:05:31,204 - Servod - INFO - Initialized ec_ec3po_interp_connect to on +2023-02-03 15:05:31,205 - Servod - INFO - Initialized ec_uart_raw_debug to off +2023-02-03 15:05:31,206 - Servod - INFO - Initialized ec_uart_timestamp to on +2023-02-03 15:05:31,207 - Servod - INFO - Initialized ec_uart_flush to on +2023-02-03 15:05:31,290 - CPU - EC3PO.Console - INFO - /dev/pts/12 - Disabling uart timestamps. +2023-02-03 15:05:31,308 - Servod - INFO - Initialized uart1_en to on +2023-02-03 15:05:31,335 - Servod - INFO - Initialized servo_micro_ec_boot_mode_uut to off +2023-02-03 15:05:31,462 - Servod - INFO - Initialized servo_jtag_trst to off +2023-02-03 15:05:31,564 - Servod - INFO - Initialized spi1_buf_en to off +2023-02-03 15:05:31,664 - Servod - INFO - Initialized spi2_buf_en to off +2023-02-03 15:05:31,767 - Servod - INFO - Initialized uart2_en to on +2023-02-03 15:05:32,020 - Servod - INFO - Initialized spi1_vref to pp3300 +2023-02-03 15:05:32,268 - Servod - INFO - Initialized spi2_vref to pp1800 +2023-02-03 15:05:32,396 - Servod - INFO - Initialized servo_jtag_trst_dir to off +2023-02-03 15:05:32,521 - Servod - INFO - Initialized servo_jtag_tdi_dir to off +2023-02-03 15:05:32,620 - Servod - INFO - Initialized gpio_expander_reset to off +2023-02-03 15:05:32,721 - Servod - INFO - Initialized uart3_on_spi1 to off +2023-02-03 15:05:32,824 - Servod - INFO - Initialized SERVO_JTAG_TMS_DIR to off +2023-02-03 15:05:32,952 - Servod - INFO - Initialized SERVO_JTAG_TDO_SEL to off +2023-02-03 15:05:33,078 - Servod - INFO - Initialized SERVO_JTAG_TMS to off +2023-02-03 15:05:33,206 - Servod - INFO - Initialized UART3_TX_SERVO_JTAG_TCK to off +2023-02-03 15:05:33,334 - Servod - INFO - Initialized UART3_RX_JTAG_BUFFER_TO_SERVO_TDO to off +2023-02-03 15:05:33,459 - Servod - INFO - Initialized SERVO_JTAG_TDO_BUFFER_EN to off +2023-02-03 15:05:33,585 - Servod - INFO - Initialized SERVO_JTAG_TDI to off +2023-02-03 15:05:33,711 - Servod - INFO - Initialized SERVO_JTAG_RTCK to off +2023-02-03 15:05:33,808 - Servod - INFO - Initialized JTAG_BUFOUT_EN_L to off +2023-02-03 15:05:33,936 - Servod - INFO - Initialized JTAG_BUFIN_EN_L to off +2023-02-03 15:05:33,936 - Servod - INFO - Initialized usbpd_uart_routing to off +2023-02-03 15:05:33,940 - Servod - INFO - Initialized fw_wp_en to off +2023-02-03 15:05:33,943 - Servod - INFO - Initialized tp1 to off +2023-02-03 15:05:33,948 - Servod - INFO - Initialized cold_reset to off +2023-02-03 15:05:33,952 - Servod - INFO - Initialized pwr_button to release +2023-02-03 15:05:33,958 - Servod - INFO - Initialized warm_reset to on +2023-02-03 15:05:33,962 - Servod - INFO - Initialized rec_mode to on +2023-02-03 15:05:33,968 - Servod - INFO - Initialized fw_up to off +2023-02-03 15:05:33,972 - Servod - INFO - Initialized lid_open to yes +2023-02-03 15:05:33,976 - Servod - INFO - Initialized pch_disable to off +2023-02-03 15:05:33,978 - Servod - INFO - Initialized tp2 to off +2023-02-03 15:05:34,380 - servoFirmwareChecker - INFO - servo_micro firmware up to date. +2023-02-03 15:05:34,381 - Servod - INFO - Initialized servo_micro_firmware_uptodate to check +2023-02-03 15:05:34,382 - Servod - INFO - Initialized servo_ec3po_interp_connect to on +2023-02-03 15:05:34,384 - Servod - INFO - Initialized servo_micro_uart_raw_debug to off +2023-02-03 15:05:34,385 - Servod - INFO - Initialized servo_micro_uart_timestamp to on +2023-02-03 15:05:34,387 - Servod - INFO - Initialized usbpd_ec3po_interp_connect to on +2023-02-03 15:05:34,389 - Servod - INFO - Initialized jtag_vref_sel0 to pp3300 +2023-02-03 15:05:34,391 - Servod - INFO - Initialized jtag_vref_sel1 to pp3300 +2023-02-03 15:05:34,398 - Servod - INFO - Initialized hpd to off +2023-02-03 15:05:34,399 - Servod - INFO - Initialized fpmcu_ec3po_interp_connect to off +2023-02-03 15:05:34,401 - Servod - INFO - Initialized fpmcu_ec3po_interp_connect_1 to off +2023-02-03 15:05:34,401 - DeviceWatchdog - INFO - Watchdog setup for devices: [18d1:501a MICRO-S-2201160335] +2023-02-03 15:05:34,402 - servod - INFO - Listening on localhost port 9999 ``` In the other terminal, build and flash the firmware: +Make sure the toolchain is installed: + +```bash +(chroot) $ sudo cros_setup_toolchains +``` + Navigate to the EC source: ```bash @@ -292,7 +289,7 @@ Prepare a serial terminal in your chroot: Connect to the UART pty: ```bash -(chroot) $ sudo screen $(dut-control raw_fpmcu_uart_pty | cut -d: -f2) +(chroot) $ sudo screen $(dut-control raw_fpmcu_console_uart_pty | cut -d: -f2) ``` Press enter key several times (may need to wait up to 20 seconds). Then you will @@ -348,6 +345,12 @@ You can get a summary of the power over `N` seconds with: (chroot) $ dut-control -t N pp3300_dx_mcu_mv pp3300_dx_fp_mv pp1800_dx_fp_mv pp3300_dx_mcu_mw pp3300_dx_fp_mw pp1800_dx_fp_mw ``` +When measuring the power, make sure that any debuggers are disconnected. The +most reliable way to make sure it is disconnected is to physically disconnect +the debugger and servo_micro from the board. Then re-attach servo_micro and +restart `servod`. + + *** note The `_mv` suffix denotes millivolt and `_mw` suffix denotes milliwatt. *** @@ -355,6 +358,7 @@ The `_mv` suffix denotes millivolt and `_mw` suffix denotes milliwatt. *** note See [Power Measurement Documentation] for more information. *** + ### Toggling Hardware Write Protect @@ -397,7 +401,7 @@ some docs to help you get started: * [Git: Concepts and Workflow]: Good overview of how `git` actually works. * [Gerrit: Concepts and Workflow]: Good overview of how Gerrit works; assumes you understand `git` basics. -* [Life of a patch]: Android workflow, but similar to Chrome OS. +* [Life of a patch]: Android workflow, but similar to ChromeOS. The Gerrit dashboard that will show your pending reviews (and ones we have for you): @@ -413,6 +417,7 @@ register for an account on the [Internal Gerrit]. Refer to the account, your contact at Google can make sure you have the necessary permissions to access the private repository. + *** note **NOTE**: In order to use a private repository you will have to manually add it to the repo manifest file before running `repo sync`. Check with your contact @@ -435,6 +440,7 @@ at Google for the exact values to use below: review="https://chrome-internal-review.googlesource.com" /> ``` *** + ### Tracking Issues and Communication @@ -462,7 +468,7 @@ from the UI. ### Developer Mode and Write Protection -Make sure that your fingerprint-equipped Chrome OS device is in [developer mode] +Make sure that your fingerprint-equipped ChromeOS device is in [developer mode] with a *test* image flashed and [hardware write protection] disabled. Using the test image will allow you to SSH into the device and disabling hardware write protection allows you to have full access to flashing the FPMCU firmware. @@ -509,37 +515,14 @@ From the DUT, flash the firmware you copied: ```bash (device) $ flash_fp_mcu /tmp/ec.bin ``` -## Commit-queue Prototype Environment - -![Dragonclaw in CQ Prototype Environment] - -## Troubleshooting - -### Dragonclaw Rev 0.2 Rework {#dragonclaw-rev-0.2-rework} - -*** note -**NOTE**: All Dragonclaw v0.2 boards have been reworked, so it is not necessary -to perform the rework yourself. -*** - -Dragonclaw **Rev 0.2** has two load switches (`U4` and `U6`) that enable the -1.8V power rail from the servo connector or motherboard connector. However, this -switch is not compatible with 1.8V, so will always output 0V. - -The [rework document][Dragonclaw Rev 0.2 1.8V Rework] describes replacing these -two switches with ones compatible with 1.8V. -### Dragonclaw Rev 0.1 Servo Fix - -Dragonclaw **Rev 0.1** has a known issue with UART and JTAG. Most notably, this -issue causes servo micro to fail to program the FPMCU over UART. +## Commit-queue Prototype Environment -This issue can be fixed with the following rework steps: +![CQ Prototype Environment] -* Connect servo header pin 13 to pin 18 -* Connect servo header pin 13 to pin 29 +![FPMCU devboard environment v2 with satlab] -![Dragonclaw servo fix diagram] +## Troubleshooting ### Verify that servo and debugger are connected to USB {#servo-connected} @@ -552,7 +535,7 @@ supply. (chroot) $ lsusb Bus 002 Device 003: ID 0897:0004 Lauterbach # ← This is my Lauterbach (debugger) -Bus 001 Device 013: ID 18d1:5002 Google Inc. # ← This is servo +Bus 001 Device 013: ID 18d1:5002 Google LLC # ← This is servo ``` ### "No servos found" when running servod @@ -584,27 +567,27 @@ Make sure that this interface is disabled: [EC]: https://chromium.googlesource.com/chromiumos/platform/ec -[ectool_servo_spi]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/util/comm-servo-spi.c#15 -[servo]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/README.md -[developer mode]: https://chromium.googlesource.com/chromiumos/docs/+/master/debug_buttons.md#firmware-keyboard-interface -[hardware write protection]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/docs/write_protection.md -[have the prerequisites]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#Prerequisites -[get the source]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#get-the-source -[enter the `chroot`]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#building-chromium-os -[Chromium OS Contributing Guide]: https://chromium.googlesource.com/chromiumos/docs/+/master/contributing.md -[Servo Micro Info]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/docs/servo_micro.md -[Set your editor]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#Set-your-editor +[ectool_servo_spi]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/util/comm-servo-spi.c#15 +[servo]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/README.md +[developer mode]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/debug_buttons.md#firmware-keyboard-interface +[hardware write protection]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/write_protection.md +[have the prerequisites]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#Prerequisites +[get the source]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#get-the-source +[enter the `chroot`]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#building-chromium-os +[Chromium OS Contributing Guide]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/contributing.md +[Servo Micro Info]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/servo_micro.md +[Set your editor]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#Set-your-editor [Life of a patch]: https://source.android.com/setup/contribute/life-of-a-patch [Git: Concepts and Workflow]: https://docs.google.com/presentation/d/1IQCRPHEIX-qKo7QFxsD3V62yhyGA9_5YsYXFOiBpgkk/ [Gerrit: Concepts and Workflow]: https://docs.google.com/presentation/d/1C73UgQdzZDw0gzpaEqIC6SPujZJhqamyqO1XOHjH-uk/ [Public Gerrit]: https://chromium-review.googlesource.com -[Power Measurement Documentation]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/docs/power_measurement.md +[Power Measurement Documentation]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/power_measurement.md [Internal Gerrit]: https://chrome-internal-review.googlesource.com [Gerrit Credentials Setup]: https://www.chromium.org/chromium-os/developer-guide/gerrit-guide [Micro USB Cable]: https://www.monoprice.com/product?p_id=9762 [PNM]: https://en.wikipedia.org/wiki/Netpbm_format -[Git and Gerrit Intro for Chromium OS]: https://chromium.googlesource.com/chromiumos/docs/+/master/git_and_gerrit_intro.md -[Installing Chromium]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#installing-chromium-os-on-your-device +[Git and Gerrit Intro for Chromium OS]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/git_and_gerrit_intro.md +[Installing Chromium]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#installing-chromium-os-on-your-device [FPMCU documentation]: ./fingerprint.md [Fingerprint Debugging]: ./fingerprint-debugging.md [dragonclaw schematics]: ../schematics/dragonclaw @@ -613,24 +596,21 @@ Make sure that this interface is disabled: [Servo Micro]: ../images/servo_micro.jpg [Servo Micro with Dragonclaw]: ../images/servomicro_dragonclaw.jpg -[Servo v2]: ../images/servo_v2.jpg -[Standard Yoshi Flex]: ../images/yoshi_flex.jpg -[Yoshi Flex Reworked to Support SWD]: ../images/yoshi_flex_swd_rework.jpg -[Dragonclaw board]: ../images/dragonclaw_rev_0.2.jpg +[Dragonclaw board]: ../images/dragonclaw_v0.3.jpg [Dragonclaw servo fix diagram]: ../images/dragonclaw_servo_fix.jpg -[Connect USB to Servo]: ../images/servo_v2_with_micro_usb.jpg -[Connect Yoshi Flex]: ../images/servo_v2_with_yoshi_flex.jpg -[Another Yoshi Flex image]: ../images/servo_v2_with_yoshi_flex2.jpg -[Connect Yoshi Flex to FPMCU board]: ../images/dragonclaw_yoshi_flex_header.jpg -[Another image]: ../images/dragonclaw_yoshi_flex_header2.jpg -[Connect SWD Debugger]: ../images/servo_v2_jtag_header.jpg -[Dartmonkey board]: ../images/dartmonkey.jpg +[Icetower board]: ../images/icetower_v3.jpg -[Dragonclaw Rev 0.2 1.8V Rework]: https://github.com/coreboot/chrome-ec/blob/master/docs/images/dragonclaw_rev_0.2_1.8v_load_switch_rework.pdf + +[Dragonclaw Rev 0.2 1.8V Rework]: https://github.com/coreboot/chrome-ec/blob/HEAD/docs/images/dragonclaw_rev_0.2_1.8v_load_switch_rework.pdf -[Dragonclaw in CQ Prototype Environment]: ../images/Dragonclaw_in_CQ_Prototype_Environment.jpg + +[CQ Prototype Environment]: ../images/CQ_Prototype_Environment.jpg + + + +[FPMCU devboard environment v2 with satlab]: ../images/FPMCU_devboard_environment_v2_with_Satlab.jpg diff --git a/docs/fingerprint/fingerprint-factory-quick-guide.md b/docs/fingerprint/fingerprint-factory-quick-guide.md index aeb84f157b..0e095bf9fe 100644 --- a/docs/fingerprint/fingerprint-factory-quick-guide.md +++ b/docs/fingerprint/fingerprint-factory-quick-guide.md @@ -1,7 +1,7 @@ -# Chrome OS Fingerprint Sensor: Quick Factory Guide +# ChromeOS Fingerprint Sensor: Quick Factory Guide The goal of this document is to outline how ODM partners can make use of the -existing Chrome OS factory scripts to meet Chrome OS FPS factory requirements. +existing ChromeOS factory scripts to meet ChromeOS FPS factory requirements. [TOC] @@ -13,48 +13,44 @@ FPMCU firmware must be flashed before fingerprint functional test is run. ODM partners may work with the module house to preflash FPMCU firmware before factory SMT. However, this way ODM partners have to coordinate with the module house to make sure the preflash FPMCU firmware blob is extracted from the FSI -release image (from /opt/google/biod/fw/). If the FPMCU firmware doesn’t match +release image (from `/opt/google/biod/fw/`). If the FPMCU firmware doesn’t match the FPMCU firmware blob checked into the release image, the end users will see the ‘critical update’ screen in their out-of-box experience, because -bio\_fw\_updater tries to update FPMCU firmware at boot time. This is a bad user +`bio_fw_updater` tries to update FPMCU firmware at boot time. This is a bad user experience we want to avoid. Most importantly, in PVT/MP build, only the FPMCU firmware in the release image would be signed by MP key. So you **MUST** ensure FPMCU is flashed with the MP-signed firmware blob extracted from FSI, before shipping the devices. As opposed to pre-flashing FPMCU in the module house, ODM partners are -encouraged to make use of -[update\_fpmcu\_firmware.py](https://chromium.googlesource.com/chromiumos/platform/factory/+/e5e903d0a0d8327dd8b9e47d2c808fd845ed73a4/py/test/pytests/update_fpmcu_firmware.py) -to update FPMCU firmware in the factory flow. This script can detect fingerprint -MCU board name, find the right FPMCU firmware blob for the DUT from the release -partition, and then flash FPMCU by flash\_fp\_mcu tool. Please note that this -script may take more than 30 secs to complete, which is slow. - -Since bio\_fw\_update has been disabled in factory test image via +encouraged to make use of [`update_fpmcu_firmware.py`] to update FPMCU firmware +in the factory flow. This script can detect fingerprint MCU board name, find the +right FPMCU firmware blob for the DUT from the release partition, and then flash +FPMCU by [`flash_fp_mcu`] tool. Please note that this script may take more than +30 secs to complete, which is slow. + +Since `bio_fw_updater` has been disabled in factory test image via [crrev/c/1913645](https://chromium-review.googlesource.com/c/chromiumos/platform2/+/1913645), in the factory flow, the FPMCU firmware should not be overwritten by -boot-update-firmware service during reboot. +`boot-update-firmware` service during reboot. ### Run fingerprint sensor functional test -Please add -[fingerprint\_mcu.py](https://chromium.git.corp.google.com/chromiumos/platform/factory/+/a283609cd8446ba4a4b75c2e1d84c9ba24ea8422/py/test/pytests/fingerprint_mcu.py) -to your device test list. A more detailed description about this test can be -found -[here](https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/docs/fingerprint/fingerprint-factory-requirements.md). +Please add [`fingerprint_mcu.py`] to your device test list. A more detailed +description about this test can be found [here][factory requirements]. ### Initialize FPMCU entropy in factory finalization The support for FPMCU entropy initialization has been integrated into the factory finalization script. So FPMCU entropy should be automatically initialized in factory finalization, if a FPMCU is found on DUT. Note that FPMCU -entropy initialization would fail if rollback\_block\_id is not equal to zero, +entropy initialization would fail if `rollback_block_id` is not equal to zero, which means the entropy has been initialized before. It is usually caused by -biod trying to initialize FPMCU entropy and increment rollback\_block\_id at -boot time. Since we have disabled biod and bio\_crypto\_init in factory test +biod trying to initialize FPMCU entropy and increment `rollback_block_id` at +boot time. Since we have disabled biod and `bio_crypto_init` in factory test image via [crrev/c/1910290](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1910290), -we expect rollback\_block\_id would stay zero during the factory flow, and FPMCU +we expect `rollback_block_id` would stay zero during the factory flow, and FPMCU entropy initialization should succeed in factory finalization. So just run factory finalization as any other CrOS boards. @@ -62,8 +58,8 @@ factory finalization as any other CrOS boards. The support for FPMCU SWWP has been integrated into factory finalization script. So FPMCU SWWP should be automatically enabled in factory finalization together -with AP/EC SWWP when write\_protection arg is set to true and a FPMCU is found -on DUT. Just run factory finalization as any other CrOS boards. +with AP/EC SWWP when `write_protection` arg is set to `true` and a FPMCU is +found on DUT. Just run factory finalization as any other CrOS boards. ### Reset entropy for factory re-finalization (in case of RMA or OQC) @@ -71,14 +67,12 @@ For the boards that have been finalized, FPMCU entropy has been initialized. So running re-finalization for those boards are expected to fail at FPMCU entropy initialization. Before running re-finalization for those boards, ODM partners have to remove hardware write protection (HWWP) and then run -[update\_fpmcu\_firmware.py](https://chromium.googlesource.com/chromiumos/platform/factory/+/d399a0a1bdeb7249de2721b269e7365e4486e23c/py/test/pytests/update_fpmcu_firmware.py) -to reset rollback\_block\_id and entropy. So the follow-up re-finalization -(which re-initialize entropy) can succeed. +[`update_fpmcu_firmware.py`] to reset `rollback_block_id` and entropy. So the +follow-up re-finalization (which re-initialize entropy) can succeed. ## References -* CrOS fingerprint factory requirements: - [doc link](https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/docs/fingerprint/fingerprint-factory-requirements.md) +* CrOS fingerprint factory requirements: [doc link][factory requirements] * The summary of CLs: * Add a factory script to update FPMCU firmware: [crrev/c/1918679](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1918679), @@ -95,3 +89,8 @@ to reset rollback\_block\_id and entropy. So the follow-up re-finalization [crrev/c/1900503](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1900503), [crrev/c/1925927](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1925927), [crrev/c/1948163](https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1948163) + +[`update_fpmcu_firmware.py`]: https://crsrc.org/o/src/platform/factory/py/test/pytests/update_fpmcu_firmware.py;drc=672e24bb3e2dd0dec7578dcd4c52805d022662d1 +[factory requirements]: ./fingerprint-factory-requirements.md +[`fingerprint_mcu.py`]: https://crsrc.org/o/src/platform/factory/py/test/pytests/fingerprint_mcu.py;drc=672e24bb3e2dd0dec7578dcd4c52805d022662d1 +[`flash_fp_mcu`]: https://crsrc.org/o/src/platform/ec/util/flash_fp_mcu;drc=12c473337e3bdcce6d180d266c9e9f8127448f33 diff --git a/docs/fingerprint/fingerprint-factory-requirements.md b/docs/fingerprint/fingerprint-factory-requirements.md index 4aaf564570..5116b2c77a 100644 --- a/docs/fingerprint/fingerprint-factory-requirements.md +++ b/docs/fingerprint/fingerprint-factory-requirements.md @@ -1,4 +1,4 @@ -# Chrome OS Fingerprint Factory Requirements +# ChromeOS Fingerprint Factory Requirements This document provides an overview of factory requirements and testing for the fingerprint sensor. @@ -8,7 +8,7 @@ fingerprint sensor. ## Contact For questions regarding this document, please contact the -[Chrome OS Fingerprint Team]. +[ChromeOS Fingerprint Team]. ## Terminology @@ -39,12 +39,12 @@ For questions regarding this document, please contact the ## FPMCU Firmware Location The binaries for the FPMCU firmware are located in `/opt/google/biod/fw`. Now -that Chrome OS supports unibuild, there may be multiple firmware binaries in the +that ChromeOS supports unibuild, there may be multiple firmware binaries in the directory since multiple sensors may be used across a single "board" (e.g., the `hatch` board can use either `bloonchipper` or `dartmonkey`). The correct firmware type to use for a given board can be discovered with the -[Chrome OS Config] tool: +[ChromeOS Config] tool: ```bash (dut) $ cros_config /fingerprint board @@ -61,11 +61,13 @@ dartmonkey The corresponding firmware for the above command would be `/opt/google/biod/fw/dartmonkey_*.bin`. + *** note **NOTE**: If you get an empty response when running the above commands, the -Chrome OS Config settings may not have been updated for the Chrome OS board. -See the instructions on [updating Chrome OS Config] for fingerprint. +ChromeOS Config settings may not have been updated for the ChromeOS board. +See the instructions on [updating ChromeOS Config] for fingerprint. *** + Note that the fingerprint team continuously releases updates to the firmware, so SIEs should watch for version changes in ToT if they are maintaining a separate @@ -75,10 +77,7 @@ factory branch. When the FPMCU is completely blank a low-level flashing tool must be used to program an initial version of the FPMCU firmware. It’s possible to use the -[`flash_fp_mcu`] script as this low-level flashing tool, though since it -requires the AP and is not necessarily robust against failures, it is not -recommended for mass-production. More details about [`flash_fp_mcu`] are in the -[Fingerprint flashing documentation]. +factory script [`update_fpmcu_firmware.py`] as this low-level flashing tool. The initial version of the FPMCU firmware should be flashed either by the module house or by the factory. Once an initial version of the FPMCU firmware has been @@ -88,12 +87,14 @@ the rootfs. Note that this update process can take around 30 seconds; if that length of time is an issue then the factory or module house should pre-flash the latest firmware beforehand. + *** note **NOTE**: If the FPMCU is not flashed in the factory as part of development builds (EVT, etc.), it's possible for developers (or Chromestop) to manually run [`flash_fp_mcu`], as long as they can disable [hardware write protect]. Obviously this only applies during development, not mass production. *** + ## biod and timberslide @@ -127,7 +128,7 @@ Card). FPC also provides design drawings for the rubber stamp. The stamp, test-fixture and test station need to be implemented by the OEM/ODM/Module House (often only module house). -The `MTS` _must_ be followed by the module manufacturer, but Google does not +The `MTS` *must* be followed by the module manufacturer, but Google does not provide direct support for this testing. FPC is the main point of contact. The module testing procedure is documented in the following: @@ -142,7 +143,7 @@ In-device tests are run during the `FATP` process once the device has been fully assembled. Google provides source code for these tests in [`fingerprint_mcu.py`]. -Hardware Required: Chrome OS DUT before finalization. +Hardware Required: ChromeOS DUT before finalization. Documentation: [FPC In-Device Test Specification] @@ -187,10 +188,12 @@ Perform median analysis on the resulting image as described in the `MTS` document. The factory toolkit does this in [`fingerprint_mcu.py`][Checkerboard Test]. + *** note **TIP**: You can view the `.pnm` files generated by the commands below on your Linux desktop with ImageMagick: `display /path/to/file.pnm`. *** + ##### Success/Failure @@ -461,34 +464,36 @@ To convert the images from FPC’s proprietary format to PNG, you will need to have `cros deploy`’d `libfputils-nocturne`, which will install the required utilities in `/opt/fpc`. + *** note **NOTE**: As of 2019-05-21, the `libfputils` library only works for the FPC 1145 sensor (in nocturne), not the FPC 1025 sensor (hatch). *** + Convert the buffer in proprietary format into png: ```bash -(dut) $ /opt/fpc/fputils.py /tmp/fp.raw --png +(dut) $ /usr/local/opt/fpc/fputils.py /tmp/fp.raw --png Extraction found 2 images Wrote /tmp/fp.0.png (14085 bytes) Wrote /tmp/fp.1.png (14025 bytes) ``` -[Software Write Protect]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/docs/write_protection.md#Software-Write-Protect -[hardware write protect]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/docs/write_protection.md#hw_wp +[Software Write Protect]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/write_protection.md#Software-Write-Protect +[hardware write protect]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/write_protection.md#hw_wp [FPC1025: Module Test Specification]: http://go/cros-fingerprint-fpc1025-module-test-spec [FPC1145: Module Test Specification]: http://go/cros-fingerprint-fpc1145-module-test-spec [FPC In-Device Test Specification]: http://go/cros-fingerprint-fpc-indevice-test-spec -[`fingerprint_mcu.py`]: https://chromium.googlesource.com/chromiumos/platform/factory/+/master/py/test/pytests/fingerprint_mcu.py +[`fingerprint_mcu.py`]: https://chromium.googlesource.com/chromiumos/platform/factory/+/HEAD/py/test/pytests/fingerprint_mcu.py [Checkerboard Test]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/pytests/fingerprint_mcu.py#166 [GetSensorIdErrors]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/utils/fpmcu_utils.py#73 [GetSensorId]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/utils/fpmcu_utils.py#65 [ProcessResetPixelImage]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/pytests/fingerprint_mcu.py#268 [rubber_finger_present]: https://chromium.googlesource.com/chromiumos/platform/factory/+/d23ebc7eeb074760e8a720e3acac4cfe4073b2ae/py/test/pytests/fingerprint_mcu.py#330 -[Chrome OS Fingerprint Team]: http://go/cros-fingerprint-docs +[ChromeOS Fingerprint Team]: http://go/cros-fingerprint-docs [Factory Fingerprint Sensor Testing for `nocturne`]: http://go/fingerprint-factory-testing-nocturne -[`flash_fp_mcu`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/util/flash_fp_mcu -[Fingerprint flashing documentation]: ./fingerprint.md#factory-rma-dev-updates -[Chrome OS Config]: https://chromium.googlesource.com/chromiumos/platform2/+/master/chromeos-config/README.md -[updating Chrome OS Config]: ./fingerprint.md#update-chromeos-config +[`flash_fp_mcu`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/util/flash_fp_mcu +[ChromeOS Config]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md +[updating ChromeOS Config]: ./fingerprint.md#update-chromeos-config +[`update_fpmcu_firmware.py`]: https://crsrc.org/o/src/platform/factory/py/test/pytests/update_fpmcu_firmware.py;drc=672e24bb3e2dd0dec7578dcd4c52805d022662d1 diff --git a/docs/fingerprint/fingerprint-firmware-testing-for-partners.md b/docs/fingerprint/fingerprint-firmware-testing-for-partners.md new file mode 100644 index 0000000000..b9de1e92f4 --- /dev/null +++ b/docs/fingerprint/fingerprint-firmware-testing-for-partners.md @@ -0,0 +1,112 @@ +# Fingerprint Firmware Testing Instructions for Partners + +This document is intended to help partners (sensor vendors, MCU vendors, etc) +run the ChromeOS fingerprint team's firmware tests, as part of the AVL process. +The document assumes that you‘re using Linux to do the development; preferably a +recent version of Ubuntu or Debian. It may be possible to use a virtual machine, +but that is not a configuration we test. + +[TOC] + +## Hardware Requirements + +You will need a Chromebook with the fingerprint sensor and fingerprint MCU +(FPMCU), and a [servo debugger]. + +### Chromebook with fingerprint sensor + +The Chromebook needs to be in [developer mode] and running a test image so that +the test can ssh into it. The fingerprint firmware tests will run a series of +bash commands, including flashing the FPMCU firmware and rebooting the +Chromebook. You do not need [CCD] because servo will handle the firmware write +protection for you. + +### Servo + +Servo is a general purpose debug board used in many automated tests in Chromium +OS. Among other things, servo enables the tests to toggle hardware write +protect. + +While there are multiple versions of servo, for firmware tests we strongly +recommend [Servo V4] as that's the simplest and most often used in autotests. +This document will assume you are using Servo V4. + +### Hardware Setup + +* Connect the "HOST" side of Servo V4 to your host machine (which should have + a Chromium OS chroot). +* Connect the other side of Servo V4 to a USB port on the Chromebook with + fingerprint sensor. +* Connect the "DUT POWER" side of Servo V4 to power supply. +* Make sure the USB cable from the host machine to Servo V4 is in data + transfer mode (i.e. if there's an LED, it should be yellow instead of + green). +* Make sure the you can ssh into the Chromebook from the chroot on the host + machine. + +## Software Setup + +### Get the Chromium OS source code. + +* First, make sure you [have the prerequisites]. +* Then [get the source]. + +### Build the autotest codebase + +```bash +# from a terminal on your machine +(outside chroot) $ cd ~/chromiumos/src + +# enter the chroot +(outside chroot) $ cros_sdk + +# build autotest for the board to be tested +(chroot) $ emerge- autotest +``` + +### Start servod + +```bash +(chroot) $ sudo servod --board= +``` + +At this point the servod daemon should be running and listening to port 9999 by +default. If it isn't, check the hardware connection. + +## Run a Single Fingerprint Firmware Test + +Use another terminal and enter the chroot like before: + +```bash +(outside chroot) $ cd ~/chromiumos/src +(outside chroot) $ cros_sdk +``` + +To run a single test, use this command in your chroot: + +```bash +test_that --board= +``` + +For example: + +```bash +test_that --board=nocturne firmware_Fingerprint.ReadFlash +``` + +## Run the Entire Fingerprint Firmware Test Suite + +To run the entire suite, use this command in your chroot: + +```bash +test_that --board= suite:fingerprint +``` + + + +[servo debugger]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/servo.md +[developer mode]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_mode.md +[CCD]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/cr50_stab/docs/case_closed_debugging.md +[Servo V4]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/servo_v4.md +[have the prerequisites]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#Prerequisites +[get the source]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#get-the-source diff --git a/docs/fingerprint/fingerprint-ram-and-flash.md b/docs/fingerprint/fingerprint-ram-and-flash.md new file mode 100644 index 0000000000..1972c25a38 --- /dev/null +++ b/docs/fingerprint/fingerprint-ram-and-flash.md @@ -0,0 +1,109 @@ +# Fingerprint MCU RAM and Flash + +[TOC] + +## Overview + +The fingerprint firmware divides flash into three sections: RO, Rollback, and +RW. The RO (Read-only) section contains a minimal set of code to check the +signature of the code in RW; it’s essentially a bootloader and once a device +enters production it never changes. The RW section is the portion of flash that +runs the matching algorithm and is the portion that we update over time. The +Rollback section consists of two separate flash sectors that store the minimum +RW version that is allowed to run; this prevents attacks where an older version +of RW firmware has a security vulnerability, and we want to prevent it from ever +being loaded again (even though it’s valid and will pass the signature check). +The fingerprint firmware also uses the rollback section to store the entropy +used for the encryption key that protects the fingerprint templates. + + +*** note +The amount of RAM and flash used is specific to the sensor and matching +algorithm used. After building the FPMCU firmware (e.g., +[`make BOARD=bloonchipper`]), the amount of flash and RAM *remaining* will be +printed out. +*** + + +## STM32H743 (Dartmonkey) + +Total Flash: [2 MB] + +Total SRAM: [1 MB], but [864 KB is "user SRAM"]. See [Section 2.4 Embedded SRAM] +for more details. + +### Flash + +Flash section | Size | Amount Used +--------------- | ------------------------------------------- | ----------- +Read-only (RO) | [768 KB] | See [`make BOARD=dartmonkey`] output. +Rollback | [256 KB total][256 KB] (two 128 KB sectors) | [44 bytes in each of the two sections] +Read-write (RW) | [1024 KB] | See [`make BOARD=dartmonkey`] output. + +#### Layout + +Flash sector | Flash sector size | Offset | Firmware Region +------------ | ----------------- | ------------------ | ------------------- +1 | 128 KB | 0 | RO ([768 KB]) +2 | 128 KB | 0x20000 (131072) | ... +3 | 128 KB | 0x40000 (262144) | ... +4 | 128 KB | 0x60000 (393216) | ... +5 | 128 KB | 0x80000 (524288) | ... +6 | 128 KB | 0xA0000 (655360) | ... +7 | 128 KB | 0xC0000 (786432) | Rollback ([256 KB]) +8 | 128 KB | 0xE0000 (917504) | ... +9 | 128 KB | 0x100000 (1048576) | RW ([1024 KB]) +10 | 128 KB | 0x120000 (1179648) | ... +11 | 128 KB | 0x140000 (1310720) | ... +12 | 128 KB | 0x160000 (1441792) | ... +13 | 128 KB | 0x180000 (1572864) | ... +14 | 128 KB | 0x1A0000 (1703936) | ... +15 | 128 KB | 0x1C0000 (1835008) | ... +16 | 128 KB | 0x1E0000 (1966080) | ... + +[2 MB]: https://www.st.com/resource/en/datasheet/stm32h743vi.pdf +[1 MB]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/chip/stm32/memory_regions.inc;l=10-16;drc=eee7778fcfc5e555d119cff65caa7c045343e356 +[864 KB is "user SRAM"]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/chip/stm32/memory_regions.inc;l=13;drc=eee7778fcfc5e555d119cff65caa7c045343e356 +[Section 2.4 Embedded SRAM]: https://www.st.com/resource/en/reference_manual/dm00314099-stm32h742-stm32h743-753-and-stm32h750-value-line-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf#page=135 +[`make BOARD=dartmonkey`]: ./fingerprint.md +[`make BOARD=bloonchipper`]: ./fingerprint.md +[256 KB]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/board/nocturne_fp/board.h;l=62;drc=ed42e86fd3c444982aa7c313c4530ad89c310191 +[768 KB]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/board/nocturne_fp/board.h;l=58;drc=ed42e86fd3c444982aa7c313c4530ad89c310191 +[1024 KB]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/board/nocturne_fp/board.h;l=66-67;drc=ed42e86fd3c444982aa7c313c4530ad89c310191 +[44 bytes in each of the two sections]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/common/rollback_private.h;l=21-29;drc=675f3a1a481aae3247e2d2af3e603b149cdaf4aa + +## STM32F412CG (Bloonchipper) + +Total Flash: [1 MB][1 MB STM32F412] + +Total SRAM: [256 KB] + +### Flash + +Flash section | Size | Amount Used +--------------- | ------------------------------------------------- | ----------- +Read-only (RO) | [128 KB] | See [`make BOARD=bloonchipper`] output. +Rollback | [256 KB (two 128 KB sectors)][STM32F412 Rollback] | [44 bytes in each of the two sections] +Read-write (RW) | 640 KB | See [`make BOARD=bloonchipper`] output. + +#### Layout + +Flash sector | Flash sector size | Offset | Firmware Region +------------ | ----------------- | ---------------- | --------------- +1 | 16 KB | 0 | RO ([128 KB]) +2 | 16 KB | 0x4000 (16384) | ... +3 | 16 KB | 0x8000 (32768) | ... +4 | 16 KB | 0xC000 (49152) | ... +5 | 64 KB | 0x10000 (65536) | ... +6 | 128 KB | 0x20000 (131072) | Rollback ([256 KB][STM32F412 Rollback]) +7 | 128 KB | 0x40000 (262144) | ... +8 | 128 KB | 0x60000 (393216) | RW (640KB) +9 | 128 KB | 0x80000 (524288) | ... +10 | 128 KB | 0xA0000 (655360) | ... +11 | 128 KB | 0xC0000 (786432) | ... +12 | 128 KB | 0xE0000 (917504) | ... + +[1 MB STM32F412]: https://www.st.com/resource/en/datasheet/stm32f412cg.pdf +[256 KB]: https://www.st.com/resource/en/datasheet/stm32f412cg.pdf +[128 KB]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/board/hatch_fp/board.h;l=66;drc=643635b91ee40def104188cf9623a9a28f25bd4f +[STM32F412 Rollback]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/board/hatch_fp/board.h;l=70;drc=643635b91ee40def104188cf9623a9a28f25bd4f diff --git a/docs/fingerprint/fingerprint-tpm-seed.md b/docs/fingerprint/fingerprint-tpm-seed.md new file mode 100644 index 0000000000..0ee7c83df5 --- /dev/null +++ b/docs/fingerprint/fingerprint-tpm-seed.md @@ -0,0 +1,325 @@ +# TPM Seed for Fingerprint MCU + +Authors: pmalani@google.com, norvez@google.com + +Reviewers: semenzato@google.com, apronin@google.com, mnissler@google.com and +others + +Last Updated: 2018-11-01 + +[TOC] + +## Objective + +Increase security for Fingerprint (FP) templates by using a [TPM]-sourced seed +in addition to internal FPMCU entropy while encrypting FP templates. The +TPM-sourced seed will be derived from the system key which is loaded from the +TPM during boot in mount-encrypted. + +## Background + +Fingerprint authorization in ChromeOS, relies on encrypted FP templates which +are stored in each user’s mount directory. These templates are created and +encrypted by the FPMCU during FP enrollment, before being sent back to the AP +(Application Processor). When the user logs in, these templates are sent to the +FPMCU where they get decrypted and loaded. + +The encryption is performed in the FPMCU using entropy which is internal to the +MCU and never leaves the MCU. That way, even if the templates are somehow +obtained by and attacker from the user mount directory, they cannot be +decrypted, since the attacker will not have access to the MCU entropy. This +entropy gets reset on every powerwash/recovery. + +The complete design doc is [Fingerprint Authentication on ChromeOS]. + +## Requirements and Scale + +The solution proposed should exhibit the following attributes: + +* Strengthens security of FP templates. +* Does not compromise the security of other sub-systems. +* Works fast and doesn’t affect time to boot, or reduce boot-time stability. + +## Design Ideas + +In addition to FPMCU entropy, we include a TPM-sourced seed (derived from the +system key) while performing template encryption. The TPM system key gets +regenerated during powerwash/recovery, so in the event that the FP templates are +accessed due to a runtime exploit, a power-wash / recovery from the user will +ensure: + +* The raw templates cannot be decrypted, since the TPM-seed would have been + lost irrevocably. +* Since a new TPM-seed is generated (since a new system key is created), old + templates can’t be re-used, even if the attacker could somehow gain access + to the FP MCU entropy. + +The overall design consists of two components: + +* Generating a TPM-seed and sending it to the Biometric sensor managers. +* The Bio sensor managers sending the seed to the FPMCU and programming it + into the encryption / decryption operations of FP templates. + +### TPM seed generation {#seed-generation} + +![TPM Seed Diagram] + +The TPM seed generation would proceed as follows: + +1. During mount-encrypted execution, after the `System_key` is loaded, the + TPM-backed system key will be HMAC-ed with a simple salt (the string + `biod`): + + ``` + TPM_Seed = HMAC_SHA256(System_key, "biod") + ``` + +2. The resulting 256-bit seed (called `TPM_Seed`) will be maintained in a + `brillo::SecureBlob`. + +3. The `TPM_seed` will be saved into a tmpfs file + (`/run/biod_crypto_init/seed`) for consumption by `bio_crypto_init`. This + file's ownership will be set up such that only user/group `biod` can access + it. + +4. `bio_crypto_init` (the binary which sends the seed to the FPMCU) will be + spawned after mount-encrypted completes. This is ensured by setting the + `bio_crypto_init` upstart rules to depend on `starting boot-services` + +5. On the `bio_crypto_init` side, the `TPM_seed` will be retrieved from the + tmpfs file and forwarded to the FP MCU via the various BiometricManagers. + Immediately after reading from the tmpfs file, `bio_crypto_init` will nuke + (write all 0’s and then delete) the tmpfs file. + +6. The upstart rules of biod will be modified such that it will start after + `bio_crypto_init` stops (this modification can be made in the `.conf` file + of biod) + +#### IPC Mechanism {#ipc} + +(For a discussion of various alternatives, please see the +[Alternatives Considered] section) + +The IPC mechanism selected should have the following features: + +* Allow to quickly pass the `TPM_seed` between mount-encrypted and + `bio_crypto_init`. +* Minimize the presence of extra/asynchronously deleted copies of the + `TPM_seed` buffer in kernel and memory. This is crucial to minimize the risk + of access to this seed. + +The currently proposed method of passing the `TPM_seed` is to use a **file in +tmpfs**. The sequence would be as follows: + +* mount-encrypted will write the `TPM_Seed` to a file in `/run` + (`/run/bio_crypto_init/seed`). `/run` is a tmpfs created by the OS for use + by various system services. +* `bio_crypto_init` will read the `TPM_Seed` from the known tmpfs file. +* As soon as `bio_crypto_init` reads the `TPM_Seed`, it will first overwrite + (`/run/biod_crypto_init/seed`) with all 0s, and immediately after will + delete `/run/biod_crypto_init/seed`. +* `bio_crypto_init` can then instantiate its BiometricManager classes and send + the data to the FP MCU. This way, even if the sending of data fails, there + will not be any stray copy of the `TPM_seed` in a process’s memory, or in + tmpfs. + +##### Advantages + +* No/minimal buffering of copies of `TPM_Seed` in kernel. +* No need to create and pass FDs between mount-encrypted and + `bio_crypto_init`. + +##### Disadvantages + +* If `bio_crypto_init` crashes / fails to start, the tmpfs file remains in the + system, i.e cleanup of tmpfs is reliant on `bio_crypto_init`. + +### Programming TPM_Seed into MCU + +#### Entropy addition v/s programming TPM Seed + +When a device boots up for the first time after going through +recovery/powerwash, biod will force an "Add Entropy" step. This involves: + +* rebooting the FP MCU to RO +* Performing an entropy addition step +* Rebooting the FP MCU to RW +* Verifying that the entropy addition has taken place (by checking the block + ID of the rollback info on the MCU). + +Unfortunately, since the `TPM_Seed` will be stored in MCU RAM, the reboot of the +FPMCU will lead to the `TPM_Seed` being lost until the next boot. In the absence +of a `TPM_Seed`, all FPMCU operations will fail (until the next boot). There is +no opportunity to reprogram the `TPM_Seed`, because that must take place during +mount-encrypted, which must necessarily run before `biod` starts. + +There are two proposals to work around this issue. The one eventually selected +has been included here, and the other alternative has been placed in the +[Alternatives Considered] section. + +##### Make bio_crypto_init solely set the TPM_Seed (don't perform entropy_add) + +In this method, `bio_crypto_init` will not perform any reboot on the MCU, and +solely program the `TPM_Seed`. This would mean that if a device was to boot for +a first time without having done any previous powerwash/recovery, the first boot +would not have FP functionality. FP functionality would be regained on all +subsequent boot (since the entropy would have been added/initialized by then). + +The downside of this approach is a poor user experience. + +The benefit is a simple implementation of the `bio_crypto_init` tool, which will +consequently also take less time to execute (booting to RO/RW are time consuming +operations). + +In practice all devices leaving the factory floor would have `bio_wash +--factory_init` done on them during finalisation to initialise the entropy, and +so this shouldn't affect a large majority of end users. + +### Signaling biod to start + +In order to avoid races which might occur because both `bio_crypto_init` and +`biod` will try to access the `BiometricManagers`' hardware. We need to ensure +that `biod` only starts after `bio_crypto_init` ends. + +To accomplish this, `biod.conf` will be modified to include a dependency on +`bio_crypto_init` to start the daemon. So, the relevant portion of `biod.conf` +will now be: + +``` +start on started system-services and started uinput and stopped bio_crypto_init +``` + +### Formula to calculate IKM used for encryption in MCU + +In the FPMCU we will use the concatenation of `TPM_Seed` and [`SBP_Src_Key`] as +Input Key Material (IKM) to derive an encryption key. Combined with a random +salt, the pseudo random key (PRK) would be derived as: + +``` +PRK = HMAC_SHA256(Random_Salt, SBP_Src_Key || TPM_Seed) +``` + +## Alternatives Considered {#alt-considered} + +A few alternatives are being considered for the IPC Mechanism + +#### pipe/socketpair + +##### Disadvantages + +* The data written to pipes is buffered in internal kernel buffers till it is + read out from the other end of the pipe/socketpair. In the case of a + `bio_crypto_init` crashing, this will leave a copy in the internal kernel + buffers. Question: How long before those internal buffers get cleared in the + case of the pipe not being read from? + +#### Anonymous file (memfd_create) / Anonymous mmap + +##### Disadvantages + +* Question: When all references to the anonymous file are dropped, are the + contents of the anonymous file re-allocated, overwritten, or is the + corresponding inode simply destroyed (and the data blocks still stick around + and are reallocated lazily ?) + +There was also another alternative considered for the sequence of programming +the TPM seed and initializing the FPMCU: make `bio_crypto_init` add entropy and +then set TPM. + +## Security Considerations + +### Security boundaries + +* A new minijailed process (`bio_crypto_init`) is run when `starting + boot-services` is signaled. +* An IPC takes place between mount-encrypted and `bio_crypto_init` via a tmpfs + file. The reading and deletion of the tmpfs file is detailed in the + [IPC Mechanism] section. + +### Privileges + +* `bio_crypto_init` runs minijail-ed and runs with user/group `biod`. Only the + files required for its functioning (i.e., the tmpfs file `/run/`, the + devnode to access the FPMCU, log directory inside + `/var/log/bio_crypto_init`) are mounted and visible inside the sandbox. See + the [minijail0 arguments] for a full explanation. + +### Untrusted input + +* The only input is the `System_key` which is retrieved from the TPM anyway + during mount-encrypted execution. Thus, no additional or new input is being + fed to the feature. +* Additionally, the derived TPM-seed is saved in a tmpfs file which has a + user/group ownership as `biod` so only users `root` or `biod` can access the + file. Since `bio_crypto_init` runs only during `starting boot-services` and + the process along with the conf file ensures that the file is deleted after + execution, there is no additional threat of the `/tmp` file being corrupted. + +### Sensitive data + +* The feature involves the storage of a `TPM_Seed` derived from the + `System_key` from TPM, in a file on tmpfs (the file is zeroed and deleted + once read by `bio_crypto_init`). + +### Attack surface + +* In the event of the contents of the tmp file being read, the `TPM_Seed` + would not be of much use to the attacker, since the use of `HMAC_SHA256` + means the attacker would still not have access to the system key (brute + force trial of HMAC 256 would be required to guess the system salt required + to produce the TPM-seed). +* In the unlikely event of the contents of the tmp file being modified before + they are programmed into the FPMCU, FP unlock would fail (since the + encrypted templates would no longer be decrypted correctly, since the FPMCU + encryption key would have changed). The FP templates encryption key is a + combination of both the `TPM_seed` as well as the internal `SBP_Src_Key` + combined with a random salt, and since only the encrypted templates are + stored on the rootfs, the templates would simply be rendered useless. A + powerwash/recovery can help restore functionality of FP unlock, but new + templates would have to be registered. +* This code should not be accessible to remote attackers. + +### Implementation robustness + +* `bio_crypto_init` uses two processes. A child process is spawned by + `bio_crypto_init` and the FPMCU programming is done on the child process. + The parent process waits for the child process to complete, or kills the + process if it exceeds a timeout limit. This ensures that the process doesn't + hang indefinitely. +* The feature uses tmpfs (`/run/bio_crypto_init/seed`) as an IPC mechanism to + transfer the `TPM_Seed` between mount-encrypted and `bio_crypto_init`. + Please see the [Alternatives Considered] and [Design Ideas] section + regarding rationale behind choosing tmpfs vis a vis socketpair/pipe. + +### Cryptography + +* `HMAC_SHA256` is used to derived `TPM_Seed` from the `System_key` as + described in section [TPM seed generation]. + +* `HMAC_SHA256` is also used to derive the FPMCU’s encryption key. This is the + same as it was earlier; the only change is that source key has been updated + to also include the `TPM_Seed`. + +## Privacy Considerations + +This implementation should not have any adverse implications on Privacy (over +and above existing functionality on ChromeOS). This provides security hardening +for the fingerprint templates to prevent their retrieval and mis-use. + +[Fingerprint Authentication on ChromeOS]: ../fingerprint/fingerprint-authentication-design-doc.md +[`SBP_Src_Key`]: ../fingerprint/fingerprint-authentication-design-doc.md#sbp-secret-generation +[IPC Mechanism]: #ipc +[minijail0 arguments]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform2/biod/init/bio_crypto_init.conf;l=36;drc=1fcefaa166e868069ad1b81091333ff75e0657f6 +[Design Ideas]: #design-ideas +[TPM seed generation]: #seed-generation +[Alternatives Considered]: #alt-considered +[TPM]: https://www.chromium.org/developers/design-documents/tpm-usage/ + + + + + + + +[TPM Seed Diagram]: ../images/cros_fingerprint_tpm_seed.png diff --git a/docs/fingerprint/fingerprint.md b/docs/fingerprint/fingerprint.md index 67f7b4bf1f..0edd7a35cd 100644 --- a/docs/fingerprint/fingerprint.md +++ b/docs/fingerprint/fingerprint.md @@ -2,16 +2,20 @@ [TOC] + *** note NOTE: The build commands assume you are in the `~/trunk/src/platform/ec` directory inside the chroot. *** + + *** note WARNING: When switching branches in the EC codebase, you probably want to nuke the `build` directory or at least the board you're working on: `rm -rf build/` or `make clobber` to prevent compilation errors. *** + ## Software @@ -24,32 +28,44 @@ The main source code for fingerprint sensor functionality lives in the The following "boards" (specified by the `BOARD` environment variable when building the EC code) are for fingerprint: -MCU | Firmware (EC "board") | Dev Board ---------------------- | ---------------------------------------------- | --------- -[STM32H743] (Cortex-M7) | `dartmonkey`
(aka `nocturne_fp`, `nami_fp`) | Icetower v0.2
(Previously Dragontalon) -[STM32F412] (Cortex-M4) | `bloonchipper`
(aka `hatch_fp`) | Dragonclaw v0.2 +MCU | Sensor | Firmware (EC "board") | Dev Board | Nucleo Board +------------------------ | ---------- | ---------------------------------------------- | ------------------------------------------ | ------------ +[STM32H743] \(Cortex-M7) | [FPC 1145] | `dartmonkey`
(aka `nocturne_fp`, `nami_fp`) | [Icetower v3]
(Previously Dragontalon) | [Nucleo H743ZI2] +[STM32F412] \(Cortex-M4) | [FPC 1025] | `bloonchipper`
(aka `hatch_fp`) | [Dragonclaw v0.3] | [Nucleo F412ZG] + +RAM and Flash details for each board are in the [Fingerprint MCU RAM and Flash] +document. + +### Sensor Template Sizes + +Sensor | Fingerprint Template Size +---------- | -------------------------------- +[FPC 1145] | [~48 KB][FPC 1145 Template Size] +[FPC 1025] | [~5 KB][FPC 1025 Template Size] ### Determining Hardware {#chromeos-config-fingerprint} -If you have access to a shell on your Chromebook, you can use [Chrome OS Config] +If you have access to a shell on your Chromebook, you can use [ChromeOS Config] to determine the FPMCU that it contains: ```bash (dut) $ cros_config /fingerprint board ``` -Alternatively, if you have a Chromium OS build, you can use [Chrome OS Config] -in the chroot to determine the FPMCU: +Alternatively, if you have a Chromium OS build, you can use [ChromeOS Config] in +the chroot to determine the FPMCU: ```bash (chroot) $ cros_config_host -c /build//usr/share/chromeos-config/yaml/config.yaml -m get /fingerprint board ``` + *** note **NOTE**: If you get an empty response when running these commands, the -[Chrome OS Config] properties for fingerprint may not have been set up yet. See -the [section on updating Chrome OS Config](#update-chromeos-config). +[ChromeOS Config] properties for fingerprint may not have been set up yet. See +the [section on updating ChromeOS Config](#update-chromeos-config). *** + ## Building FPMCU Firmware Locally @@ -82,10 +98,12 @@ Before uploading a change to Gerrit via `repo upload`, you'll need to build *all* the boards in the EC codebase to make sure your changes do not break any others. + *** note NOTE: If you forget to do this, do not worry. `repo upload` will warn you and prevent you from uploading. *** + ```bash (chroot) ~/trunk/src/platform/ec $ make buildall -j @@ -103,6 +121,12 @@ See the [Unit Tests] documentation for details on how to [run the unit tests]. ## Build and run the `host_command` fuzz test + +*** note +NOTE: For more details on fuzzing, see [Fuzz Testing in ChromeOS]. +*** + + ```bash (chroot) ~/trunk/src/platform/ec $ make run-host_command_fuzz ``` @@ -146,11 +170,13 @@ kernel: ### `fp_updater.sh` and `bio_fw_updater` + *** note **NOTE**: The auto-update process requires a working version of the firmware running on the FPMCU. See [Fingerprint Factory Requirements] for details on flashing in the factory. *** + [`fp_updater.sh`] and [`bio_fw_updater`] are wrappers around [`flashrom`] and require already-functioning RO firmware running on the FPMCU. It’s meant to be @@ -168,12 +194,14 @@ user disables [hardware write protection]). ### `flash_fp_mcu` + *** note **NOTE**: This tool is really just for us to use during development or during the RMA flow (must go through finalization again in that case). We never update RO in the field (can’t by design). See [Fingerprint Factory Requirements] for details on flashing in the factory. *** + [`flash_fp_mcu`] enables spidev and toggles some GPIOs to put the FPMCU (STM32) into bootloader mode. At that point it uses [`stm32mon`] to rewrite the entire @@ -224,9 +252,8 @@ openssl genrsa -3 -out board/$BOARD/dev_key.pem 3072 ### Resources -* https://sites.google.com/a/google.com/chromeos/resources/engineering/releng/signer-documentation -* https://sites.google.com/a/google.com/chromeos/paygen---payload -* https://b.corp.google.com/issues/77882970 +* http://go/cros-signer-docs +* https://issuetracker.google.com/issues/77882970 ## Signing @@ -295,68 +322,121 @@ a lot easier during both development and testing. ## Power See [Measuring Power] for instructions on how to measure power with the -fingerprint development boards. +fingerprint development boards. *Make sure that any debuggers are completely +disconnected.* -### Dragonclaw v0.2 +### Dragonclaw v0.3 ```bash -(chroot) $ dut-control -t 60 pp3300_dx_mcu_mv pp3300_dx_fp_mv pp1800_dx_fp_mv pp3300_dx_mcu_mw pp3300_dx_fp_mw pp1800_dx_fp_mw +(chroot) $ dut-control -t 60 pp3300_dx_mcu_mv pp3300_dx_fp_mv pp1800_dx_fp_mv pp3300_dx_mcu_mw pp3300_dx_fp_mw pp1800_dx_fp_mw +``` + +**Firmware Version**: +`bloonchipper_v2.0.4277-9f652bb3-RO_v2.0.14348-e5fb0b9-RW.bin` + +#### MCU is idle + +``` +(chroot) $ dut-control fpmcu_slp_alt:off +``` + +``` +@@ NAME COUNT AVERAGE STDDEV MAX MIN +@@ sample_msecs 478 125.49 26.02 431.96 92.23 +@@ pp1800_dx_fp_mv 478 1800.00 0.00 1800.00 1800.00 +@@ pp1800_dx_fp_mw 478 0.00 0.00 0.00 0.00 +@@ pp3300_dx_fp_mv 478 3280.00 0.00 3280.00 3280.00 +@@ pp3300_dx_fp_mw 478 0.00 0.03 0.26 0.00 +@@ pp3300_dx_mcu_mv 478 3280.00 0.00 3280.00 3280.00 +@@ pp3300_dx_mcu_mw 478 21.78 0.06 23.09 21.78 ``` -**Firmware Version**: `bloonchipper_v2.0.4277-9f652bb3` +#### MCU in low power mode (suspend) + +``` +(chroot) $ dut-control fpmcu_slp_alt:on +``` ``` @@ NAME COUNT AVERAGE STDDEV MAX MIN -@@ sample_msecs 128 469.05 33.79 641.75 399.90 -@@ pp1800_dx_fp_mv 128 1802.06 3.50 1808.00 1800.00 -@@ pp1800_dx_fp_mw 128 0.00 0.00 0.00 0.00 -@@ pp3300_dx_fp_mv 128 3296.00 0.00 3296.00 3296.00 -@@ pp3300_dx_fp_mw 128 0.00 0.03 0.26 0.00 -@@ pp3300_dx_mcu_mv 128 3288.00 0.00 3288.00 3288.00 -@@ pp3300_dx_mcu_mw 128 24.20 0.00 24.20 24.20 +@@ sample_msecs 488 122.99 26.37 458.47 92.69 +@@ pp1800_dx_fp_mv 488 1800.00 0.00 1800.00 1800.00 +@@ pp1800_dx_fp_mw 488 0.00 0.00 0.00 0.00 +@@ pp3300_dx_fp_mv 488 3287.79 1.29 3288.00 3280.00 +@@ pp3300_dx_fp_mw 488 0.01 0.04 0.26 0.00 +@@ pp3300_dx_mcu_mv 488 3283.38 3.95 3288.00 3280.00 +@@ pp3300_dx_mcu_mw 488 1.57 0.59 9.73 1.31 ``` -### Dragontalon +### Icetower v3 + *** note -**NOTE**: The sensor doesn't work on Dragontalon, so the measurements below show -zero for the sensor. +**NOTE**: Icetower v0.1 has a hardware bug in the INA connections, so you cannot +measure the 1.8V fingerprint sensor rail. See http://b/178098140. + +Additionally, before https://crrev.com/c/2689101, the sleep GPIOs were not +configured correctly, so the change needs to be cherry-picked in order to +measure releases before that point. *** + ```bash -(chroot) $ dut-control -t 60 pp3300_h7_mv pp3300_h7_mw pp1800_fpc_mv pp1800_fpc_mw +(chroot) $ dut-control -t 60 pp3300_dx_mcu_mv pp3300_dx_fp_mv pp3300_dx_mcu_mw pp3300_dx_fp_mw +``` + +**Firmware Version**: +`dartmonkey_v2.0.2887-311310808-RO_v2.0.14340-6c1587ca7-RW.bin` + +#### MCU is idle + +``` +(chroot) $ dut-control fpmcu_slp_alt:off ``` -**Firmware Version**: `dartmonkey_v2.0.4017-9c45fb4b3` +``` +@@ NAME COUNT AVERAGE STDDEV MAX MIN +@@ sample_msecs 523 114.85 18.33 386.55 88.95 +@@ pp3300_dx_fp_mv 523 3256.00 0.00 3256.00 3256.00 +@@ pp3300_dx_fp_mw 523 0.00 0.00 0.00 0.00 +@@ pp3300_dx_mcu_mv 523 3248.00 0.00 3248.00 3248.00 +@@ pp3300_dx_mcu_mw 523 43.86 0.10 43.91 43.65 +``` + +#### MCU in low power mode (suspend) ``` -@@ NAME COUNT AVERAGE STDDEV MAX MIN -@@ sample_msecs 1502 39.96 13.14 379.43 22.31 -@@ pp1800_fpc_mv 1502 0.00 0.00 0.00 0.00 -@@ pp1800_fpc_mw 1502 0.00 0.00 0.00 0.00 -@@ pp3300_h7_mv 1502 3288.00 0.00 3288.00 3288.00 -@@ pp3300_h7_mw 1502 8.20 0.51 18.08 7.67 +(chroot) $ dut-control fpmcu_slp_alt:on +``` + +``` +@@ NAME COUNT AVERAGE STDDEV MAX MIN +@@ sample_msecs 501 119.79 14.72 381.92 89.22 +@@ pp3300_dx_fp_mv 501 3256.00 0.00 3256.00 3256.00 +@@ pp3300_dx_fp_mw 501 0.00 0.00 0.00 0.00 +@@ pp3300_dx_mcu_mv 501 3256.00 0.00 3256.00 3256.00 +@@ pp3300_dx_mcu_mw 501 5.74 0.28 11.98 5.73 ``` -## Chrome OS Build (portage / ebuild) +## ChromeOS Build (portage / ebuild) -In order to use the fingerprint sensor with a given [Chrome OS board], a few -things need to be configured for the [Chrome OS board]. +In order to use the fingerprint sensor with a given [ChromeOS board], a few +things need to be configured for the [ChromeOS board]. ### Enable biod USE flag -The biod [`USE` flag] needs to be enabled for the [Chrome OS board]. This `USE` +The biod [`USE` flag] needs to be enabled for the [ChromeOS board]. This `USE` flag [determines whether the `biod` daemon is built and installed][biod chromium-os]. -To enable the `USE` flag, update the `make.defaults` for the [Chrome OS board]. +To enable the `USE` flag, update the `make.defaults` for the [ChromeOS board]. See the [`make.defaults` for the Hatch board][hatch make.defaults] as an example. #### Verifying biod is installed in the rootfs After enabling the `biod` [`USE` flag] and building the `biod` package for your -target [Chrome OS board], the `biod` binary should be in the build directory: +target [ChromeOS board], the `biod` binary should be in the build directory: ```bash (chroot) $ emerge- biod @@ -370,7 +450,7 @@ target [Chrome OS board], the `biod` binary should be in the build directory: ### Update FPMCU_FIRMWARE `FPMCU_FIRMWARE` should be set to the set of fingerprint firmware that should be -built and installed for the [Chrome OS board]. +built and installed for the [ChromeOS board]. `FPMCU_FIRMWARE` is a [`USE_EXPAND` variable][`USE` flag], [defined in the base `make.defaults`][FPMCU_FIRMWARE make.defaults]. @@ -392,9 +472,11 @@ See the [Hatch baseboard `make.defaults`] for an example. Once you have added the `FPMCU_FIRMWARE` flag and rebuilt the [`chromeos-firmware-fpmcu` ebuild], the firmware will show up in the the chroot: + *** note **NOTE**: This requires access to the [internal manifest]. *** + ```bash (chroot) $ emerge- chromeos-firmware-fpmcu @@ -410,18 +492,18 @@ firmware by setting `FPMCU_FIRMWARE="bloonchipper dartmonkey"`. The actual version numbers displayed will not necessarily match since the firmware is constantly updated. -### Update Chrome OS Config {#update-chromeos-config} +### Update ChromeOS Config {#update-chromeos-config} -With "unibuild", the same OS image (build) for a given [Chrome OS board] is used +With "unibuild", the same OS image (build) for a given [ChromeOS board] is used across multiple devices. Often there will be some devices that have a fingerprint sensor, some that do not, and even different sensors for the same board. -Determining what fingerprint hardware is on a given [Chrome OS board] is thus -done at runtime, using [Chrome OS Config]. +Determining what fingerprint hardware is on a given [ChromeOS board] is thus +done at runtime, using [ChromeOS Config]. The `fingerprint` config needs to be in the `model.yaml` for the given -[Chrome OS board]. The [Chrome OS Config fingerprint] section describes the +[ChromeOS board]. The [ChromeOS Config fingerprint] section describes the attributes for the `fingerprint` config in more detail. The [`ec_extras` attribute] needs to be set to the list of fingerprint firmware @@ -429,54 +511,102 @@ that should be built as part of the build. See the [`model.yaml` for the Hatch board][hatch model.yaml] as an example. -You can test your changes by -[running `cros_config`](#chromeos-config-fingerprint). The Chrome OS Config +Instead of crafting the `model.yaml` by hand, newer boards are moving to the +[ChromeOS Project Configuration] model, where the config is generated using +[Starlark]. The common [`create_fingerprint`] function can be used across models +to configure the fingerprint settings. See the [Morphius `config.star`] for an +example of how to call `create_fingerprint`. After you modify a `config.star` +file you will need to [regenerate the config]. If you need to change many +projects (e.g., modifying [`create_fingerprint`]), you can use the [`CLFactory`] +tool. + +Once you have updated the config, you can test your changes by +[running `cros_config`](#chromeos-config-fingerprint). The ChromeOS Config documentation has a [section on testing properties] that describes this in more detail. -[`common/fpsensor`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/common/fpsensor/ -[`driver/fingerprint`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/driver/fingerprint -[`nocturne_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/nocturne_fp/ -[`nami_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/nami_fp/ -[`hatch_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/hatch_fp/ -[`bloonchipper`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/bloonchipper/ -[`dartmonkey`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/board/dartmonkey/ +### SKUs + +The fingerprint sensor may only be included on certain SKUs for a given device. +The fingerprint code uses [ChromeOS Config] to determine whether a device has a +fingerprint sensor or not. For each SKU, there is an associated +[fingerprint config][ChromeOS Config fingerprint]. [ChromeOS Config] determines +the [SKU information][ChromeOS Config SKU] (and thus the +[fingerprint config][ChromeOS Config fingerprint]) from [CBI Info]. The SKU for +a given device can be found by viewing `chrome://system/#platform_identity_sku`. + +## Kernel Driver + +The kernel driver responsible for handling communication between the AP and +FPMCU is called [`cros_ec`] and is enabled with [`CONFIG_CROS_EC`] in the Linux +kernel. FPMCUs that are connected via SPI use [`cros_ec_spi.c`], while FPMCUs +that are connected via UART use [`cros_ec_uart.c`]. + +[`common/fpsensor`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/common/fpsensor/ +[`driver/fingerprint`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/driver/fingerprint +[`nocturne_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/nocturne_fp/ +[`nami_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/nami_fp/ +[`hatch_fp`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/hatch_fp/ +[`bloonchipper`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/bloonchipper/ +[`dartmonkey`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/dartmonkey/ [hardware write protection]: ../write_protection.md -[`flash_fp_mcu`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/util/flash_fp_mcu +[`flash_fp_mcu`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/util/flash_fp_mcu [`stm32mon`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/e1f3f89e7ea7945adddd0c2e6838f5e59856cff2/util/stm32mon.c#14 -[`futility`]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/master/futility/ -[`sign_official_build.sh`]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/master/scripts/image_signing/sign_official_build.sh +[`futility`]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/HEAD/futility/ +[`sign_official_build.sh`]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/HEAD/scripts/image_signing/sign_official_build.sh [vboot_key_id]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/e7db36856ce418552637d1981c173d22dfe5bf39/firmware/2lib/include/2id.h#5 [vb2_public_key]: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/e7db36856ce418552637d1981c173d22dfe5bf39/firmware/2lib/include/2rsa.h#14 [chatty-firmware-q]: https://groups.google.com/a/google.com/d/msg/chromeos-chatty-firmware/ZSg423wsFPg/26UbdGwjFQAJ [`fp_updater.sh`]: http://go/cros-fp-updater-nocturne-source -[`bio_fw_updater`]: https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/biod/tools +[`bio_fw_updater`]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/biod/tools [`flashrom`]: https://chromium.googlesource.com/chromiumos/third_party/flashrom/ [STM32F412]: https://www.st.com/resource/en/reference_manual/dm00180369.pdf [STM32H743]: https://www.st.com/resource/en/reference_manual/dm00314099.pdf -[`board/nocturne_fp/dev_key.pem`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/master/board/nocturne_fp/dev_key.pem -[`timberslide`]: https://chromium.googlesource.com/chromiumos/platform2/+/master/timberslide +[`board/nocturne_fp/dev_key.pem`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/board/nocturne_fp/dev_key.pem +[`timberslide`]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/timberslide [cros_ec_debugfs]: https://chromium.googlesource.com/chromiumos/third_party/kernel/+/9db44685934a2e4bc9180ea2de87a6c429672395/drivers/platform/chrome/cros_ec_debugfs.c [Fingerprint Factory Requirements]: ./fingerprint-factory-requirements.md -[Chromium OS test image]: https://chromium.googlesource.com/chromiumos/platform/factory/+/master/README.md#building-test-image -[Chrome OS Config]: https://chromium.googlesource.com/chromiumos/platform2/+/master/chromeos-config/README.md -[Chrome OS Config fingerprint]: https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/chromeos-config/README.md#fingerprint -[section on testing properties]: https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/chromeos-config/README.md#adding-and-testing-new-properties -[Chrome OS board]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#Select-a-board +[Chromium OS test image]: https://chromium.googlesource.com/chromiumos/platform/factory/+/HEAD/README.md#building-test-image +[ChromeOS Config]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md +[ChromeOS Config fingerprint]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md#fingerprint +[section on testing properties]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md#adding-and-testing-new-properties +[ChromeOS board]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#Select-a-board [biod chromium-os]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4ea72b588af3394cb9fd1c330dcf726472183dfd/virtual/target-chromium-os/target-chromium-os-1.ebuild#154 [hatch make.defaults]: https://chromium.googlesource.com/chromiumos/overlays/board-overlays/+/2f075f0e7ce09d3eb460f3c529da463a6201276c/overlay-hatch/profiles/base/make.defaults#22 -[Hatch baseboard `make.defaults`]: https://chrome-internal.googlesource.com/chromeos/overlays/baseboard-hatch-private/+/refs/heads/master/profiles/base/make.defaults#17 -[hatch model.yaml]: https://chrome-internal.googlesource.com/chromeos/overlays/overlay-hatch-private/+/master/chromeos-base/chromeos-config-bsp-hatch-private/files/model.yaml -[`ec_extras` attribute]: https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/chromeos-config/README.md#build_targets +[Hatch baseboard `make.defaults`]: https://chrome-internal.googlesource.com/chromeos/overlays/baseboard-hatch-private/+/HEAD/profiles/base/make.defaults#17 +[hatch model.yaml]: https://chrome-internal.googlesource.com/chromeos/overlays/overlay-hatch-private/+/HEAD/chromeos-base/chromeos-config-bsp-hatch-private/files/model.yaml +[`ec_extras` attribute]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md#build_targets [FPMCU_FIRMWARE make.defaults]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4ea72b588af3394cb9fd1c330dcf726472183dfd/profiles/base/make.defaults#157 [`USE` flag]: https://devmanual.gentoo.org/general-concepts/use-flags/index.html [`USE` flags]: https://devmanual.gentoo.org/general-concepts/use-flags/index.html [biod release firmware]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4ea72b588af3394cb9fd1c330dcf726472183dfd/chromeos-base/biod/biod-9999.ebuild#49 -[`chromeos-firmware-fpmcu` ebuild]: https://chrome-internal.googlesource.com/chromeos/overlays/chromeos-overlay/+/refs/heads/master/chromeos-base/chromeos-firmware-fpmcu/chromeos-firmware-fpmcu-9999.ebuild -[firmware ebuild]: https://chrome-internal.googlesource.com/chromeos/overlays/chromeos-overlay/+/refs/heads/master/chromeos-base/chromeos-firmware-fpmcu/chromeos-firmware-fpmcu-9999.ebuild#40 -[`chromeos-fpmcu-release*` ebuilds]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/sys-firmware -[internal manifest]: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md#get-the-source-code +[`chromeos-firmware-fpmcu` ebuild]: https://chrome-internal.googlesource.com/chromeos/overlays/chromeos-overlay/+/HEAD/chromeos-base/chromeos-firmware-fpmcu/chromeos-firmware-fpmcu-9999.ebuild +[firmware ebuild]: https://chrome-internal.googlesource.com/chromeos/overlays/chromeos-overlay/+/HEAD/chromeos-base/chromeos-firmware-fpmcu/chromeos-firmware-fpmcu-9999.ebuild#40 +[`chromeos-fpmcu-release*` ebuilds]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/HEAD/sys-firmware +[internal manifest]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md#get-the-source-code [Unit Tests]: ../unit_tests.md [run the unit tests]: ../unit_tests.md#running [Measuring Power]: ./fingerprint-dev-for-partners.md#measure-power [dragonclaw]: ./fingerprint-dev-for-partners.md#fpmcu-dev-board +[FPC 1145]: ../../driver/fingerprint/fpc/libfp/fpc1145_private.h +[FPC 1025]: ../../driver/fingerprint/fpc/bep/fpc1025_private.h +[FPC 1145 Template Size]: https://chromium.googlesource.com/chromiumos/platform/ec/+/127521b109be8aac352e80e319e46ed123360408/driver/fingerprint/fpc/libfp/fpc1145_private.h#46 +[FPC 1025 Template Size]: https://chromium.googlesource.com/chromiumos/platform/ec/+/127521b109be8aac352e80e319e46ed123360408/driver/fingerprint/fpc/bep/fpc1025_private.h#44 +[Dragonclaw v0.3]: ./fingerprint-dev-for-partners.md#fpmcu-dev-board +[Icetower v3]: ./fingerprint-dev-for-partners.md#fpmcu-dev-board +[Nucleo F412ZG]: https://www.digikey.com/en/products/detail/stmicroelectronics/NUCLEO-F412ZG/6137573 +[Nucleo H743ZI2]: https://www.digikey.com/en/products/detail/stmicroelectronics/NUCLEO-H743ZI2/10130892 +[CBI Info]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/cros_board_info.md +[ChromeOS Config SKU]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/chromeos-config/README.md#identity +[ChromeOS Project Configuration]: https://chromium.googlesource.com/chromiumos/config/+/HEAD/README.md +[Starlark]: https://docs.bazel.build/versions/main/skylark/language.html +[`create_fingerprint`]: https://chromium.googlesource.com/chromiumos/config/+/e1fa0d7f56eb3dd6e9378e4326de086ada46b7d3/util/hw_topology.star#444 +[Morphius `config.star`]: https://chrome-internal.googlesource.com/chromeos/project/zork/morphius/+/593b657a776ed6b320c826916adc9cd845faf709/config.star#85 +[regenerate the config]: https://chromium.googlesource.com/chromiumos/config/+/HEAD/README.md#making-configuration-changes-for-your-project +[`CLFactory`]: https://chromium.googlesource.com/chromiumos/config/+/HEAD/README.md#making-bulk-changes-across-repos +[Fingerprint MCU RAM and Flash]: ./fingerprint-ram-and-flash.md +[`CONFIG_CROS_EC`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/kernel/upstream/drivers/platform/chrome/Makefile;l=11;drc=a4e493ca59115fc0692151c1818e5aadf0e79ad0 +[`cros_ec`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/kernel/upstream/drivers/platform/chrome/cros_ec.c +[`cros_ec_spi.c`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/kernel/upstream/drivers/platform/chrome/cros_ec_spi.c +[`cros_ec_uart.c`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/kernel/upstream/drivers/platform/chrome/cros_ec_uart.c +[Fuzz Testing in ChromeOS]: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/testing/fuzzing.md diff --git a/docs/getting_started_quickly.md b/docs/getting_started_quickly.md index 9b22dc64c7..52dc774300 100644 --- a/docs/getting_started_quickly.md +++ b/docs/getting_started_quickly.md @@ -3,127 +3,64 @@ [TOC] The -[Chromium OS Developer Guide](https://chromium.googlesource.com/chromiumos/docs/+/master/developer_guide.md) +[Chromium OS Developer Guide](https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md) and [README](../README.md) walk through the steps needed to fetch and build Chromium OS source. These steps can be followed to retrieve and build EC source as well. On the other hand, if your sole interest is building an EC image, the general developer guide contains some extra unneeded steps. -The fastest possible way to build an EC image is to skip the Chromium OS chroot -install entirely. The following steps have been tested on an Ubuntu 15.10 (Wily -Werewolf) 64-bit host machine. Other distros / versions may be used, but -toolchain incompatibilities may require extra debug. - ## Building -1. Install build / dev tools: +Here is a set of steps to set up a development environment to build EC images +inside the Chromium OS chroot: - ```bash - sudo apt-get install git libftdi-dev libusb-dev libncurses5-dev gcc-arm-none-eabi - ``` -1. Sync the cros-ec git repo: +1. Create a folder for your chroot: ```bash - git clone https://chromium.googlesource.com/chromiumos/platform/ec + mkdir chromiumos; cd chromiumos ``` -1. Build your EC image: +1. Initialize the checkout in the current directory: ```bash - HOSTCC=x86_64-linux-gnu-gcc make BOARD=$board + repo init -u https://chromium.googlesource.com/chromiumos/manifest ``` -## External Dependencies - -Most boards are buildable, but some will fail due to dependencies on external -binaries (such as [`futility`](#building-futility)). Also, some related tools -(such as `flash_ec` and `servod`) must be run from the Chromium OS chroot. Here -is a set of steps to setup a minimal development environment to build EC images -from the Chromium OS chroot: - -1. Create a folder for your chroot: +1. Update the working tree to the latest version: ```bash - mkdir cros-src; cd cros-src + repo sync -j ``` -1. Run +1. Enter the chroot (type your password for `sudo` if prompted): ```bash - repo init -u https://chromium.googlesource.com/chromiumos/manifest.git --repo-url https://chromium.googlesource.com/external/repo.git -g minilayout - ``` - -1. Edit `.repo/manifest.xml`, and add `groups="minilayout"` to the platform/ec - project, so the line becomes: - - ``` - + cros_sdk ``` -1. Run `repo sync`: +1. Select a target board ```bash - repo sync -j + export BOARD= ``` -1. Enter the chroot and enter your password for `sudo` if prompted: - - ```bash - ./chromite/bin/cros_sdk - ``` + See previous section for recommendations. 1. Set up your board: ```bash - ./setup_board --board=$BOARD + setup_board --board=${BOARD} ``` - (ex. `./setup_board --board=glados`) - 1. Build EC: ```bash - ./build_packages --board=$BOARD chromeos-ec + build_packages --board=${BOARD} chromeos-ec ``` 1. Now, EC images for any board can be built with: ```bash - cd ~/trunk/src/platform/ec; make BOARD=$board -j - ``` - -## Building `futility` outside the chroot {#building-futility} - -If you want to build the `futility` host tool outside the normal Chrome OS -chroot self-contained environment, you can try the following - -1. Install futility build dependencies: - - ```bash - sudo apt-get install uuid-dev liblzma-dev libyaml-dev libssl-dev - ``` - -1. Get the vboot reference sources: - - ```bash - git clone https://chromium.googlesource.com/chromiumos/platform/vboot_reference - ``` - -1. Build it: - - ```bash - cd vboot_reference ; make - ``` - -1. Install it in `/usr/local/bin`: - - ```bash - sudo make install - ``` - -1. Add `/usr/local/bin` to your default `PATH`: - - ```bash - export PATH="${PATH}:/usr/local/bin" + cd ~/chromiumos/src/platform/ec; make BOARD=${BOARD} -j ``` diff --git a/docs/gitlab.md b/docs/gitlab.md new file mode 100644 index 0000000000..2ebc5c60f7 --- /dev/null +++ b/docs/gitlab.md @@ -0,0 +1,153 @@ +# Gitlab CI + +The Zephyr EC Test Team uses external Gitlab CI jobs to generate code coverage +reports. These CI jobs are defined in the `.gitlab-ci.yml` file in +`platform/ec`. + +[TOC] + +## Running CI jobs locally + +For development purposes, it is possible to run the CI jobs on a local machine +using Docker and `gitlab-runner`. + +Note: not all features of Gitlab CI are available when running builds locally. +For example, the local runner cannot build dependencies specified in the +`needs:` sections. (But you can run jobs individually). More details can be +found in the [`gitlab-runner` docs] +(https://docs.gitlab.com/runner/commands/#limitations-of-gitlab-runner-exec). + +### Installation + +First, you must [install Docker](https://docs.docker.com/get-docker/) on your +system. This is out of the scope of this guide, but there are many resources +on the Internet describing how to do this. Docker allows the CI jobs to run in a +controlled environment using containers, ensuring that the jobs run consistently +and without needing to pollute your own system with the many dependencies. + +Next, install the Gitlab Runner. This application is able interpret the +`.gitlab-ci.yml` file, spawn Docker containers to run jobs, and report back +results and artifacts. Usually, runners are deployed in fleets and configured to +register with a Gitlab server, which can push CI jobs to individual runners to +execute. However, it is also possible to use the runner in a purely local mode +using `gitlab-runner exec`. + +Full instructions are available on the +[Gitlab website](https://docs.gitlab.com/runner/install/), but the fastest way +to get it for Debian-based systems is to download and install the package +directly: + +``` +wget https://gitlab-runner-downloads.s3.amazonaws.com/latest/deb/gitlab-runner_amd64.deb +sudo dpkg -i gitlab-runner_amd64.deb +``` + +### Running a Job + +Once Docker and the Gitlab Runner are installed, invoke it as follows. This +takes place outside of the chroot environment. + +``` +(outside) +mkdir ~/gitlab-runner-output # Do once + +cd ~/chromiumos/src/platform/ec +sudo gitlab-runner exec docker \ + --docker-volumes "$HOME/chromiumos/:$HOME/chromiumos/" \ + --docker-volumes "$HOME/gitlab-runner-output:/builds" \ + +``` + +Please note: + * `$HOME/chromiumos` should be adjusted to wherever your tree is checked out + to. The reason it is necessary to mount the entire source tree to the + Docker container (as opposed to just `platform/ec`, which is done + automatically) is because the runner needs access to the Git database in + order to clone the source code. Because the `platform/ec` repository is + governed by the `repo` tool, the Git database is actually located at + `$HOME/chromiumos/.repo/projects/src/platform/ec.git`. (The `.git` directory + in `platform/ec` is merely a symlink) + * The second mount causes the runner's work directory to be backed by a + directory on your own system so that you can examine the artifacts after the + job finishes and the container is stopped. + * `` is one of the jobs defined in `.gitlab-ci.yml`, such as + `twister_coverage`. + * You may see error messages like `ERROR: Could not create cache adapter`. + These appear to be benign, although getting the cache to work might improve + subsequent build times. This may be investigated at a later date. + +### Accessing Artifacts + +If you used the command as shown above, all of the build artifacts and source, +as checked out by the Gitlab runner, should be under `~/gitlab-runner-output`. +This will persist after the container exits but also get overwritten again on +the next run. + +## Gitlab runners + +The gitlab builds run on a number of [virtual and real machines](https://gitlab.com/groups/zephyr-ec/-/runners) +which are currently at Simon's house, and cloud virtual machines. + +### Create a new VM + +* Visit https://pantheon.corp.google.com/compute/instances?onCreate=true&project=chromeos-ec-gitlab + * Click on instance-1 + * Click create similar +* Wait for new instance to be created +* Click on SSH +* Install docker +``` +sudo apt-get remove docker docker-engine docker.io containerd runc +sudo apt-get update +sudo apt-get install \ + ca-certificates \ + curl \ + gnupg \ + lsb-release +sudo mkdir -p /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ + $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null +sudo apt-get update +sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin +sudo docker run hello-world +``` +* Install gitlab runner +``` +sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64 +sudo chmod +x /usr/local/bin/gitlab-runner +sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash +sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner +sudo gitlab-runner start +``` +* Register new runner using command from https://gitlab.com/groups/zephyr-ec/-/runners (click on Register a group runner, click on show instructions, click on Linux) +``` +sudo gitlab-runner register --url https://gitlab.com/ --registration-token TOKENGOESHERE +Runtime platform arch=amd64 os=linux pid=56156 revision=bbcb5aba version=15.3.0 +Running in system-mode. + +Enter the GitLab instance URL (for example, https://gitlab.com/): +[https://gitlab.com/]: +Enter the registration token: +[TOKENGOESHERE]: +Enter a description for the runner: +[instance-2]: Cloud runner instance-2 +Enter tags for the runner (comma-separated): + +Enter optional maintenance note for the runner: + +Registering runner... succeeded runner=TOKENGOESHERE +Enter an executor: docker, parallels, shell, docker-ssh+machine, custom, docker-ssh, ssh, virtualbox, docker+machine, kubernetes: +docker +Enter the default Docker image (for example, ruby:2.7): +ruby:2.7 +Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! + +Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml" +``` + +* Install cleanup docker cleanup daily cron +``` +( echo "0 3 * * * /usr/bin/docker system prune -f -a --volumes" ; sudo crontab -l -u root ) | sudo crontab -u root - +``` diff --git a/docs/goma.md b/docs/goma.md new file mode 100644 index 0000000000..843cf18e1e --- /dev/null +++ b/docs/goma.md @@ -0,0 +1,52 @@ +# Ludicrous Speed Compilation with Goma + +[TOC] + +*** note +At the moment, Goma is only available for Googlers. +*** + +All commands should be performed in the chroot. + +## Login to Goma + +First, login to Goma: + +``` shellsession +$ goma_auth login +``` + +You'll be prompted to accept an agreement, and copy a URL into your +browser for login. Be sure to use your @google.com account. + +The login info should persist across reboots, so you'll only need to +do this step once (or rarely, if you get logged out). + +## Start Goma + +Start Goma's `compiler_proxy` daemon. It will run in the background. + +``` shellsession +$ goma_ctl ensure_start +``` + +You'll need to do this each time you start your machine. + +## Compiling (Zephyr EC) + +Run `zmake` as you normally do, and just add the `--goma` flag. For +example: + +``` shellsession +$ zmake --goma testall +``` + +jrosenth@ observed on a ThinkStation P920 that a clean `testall` with +`--goma` takes only 1 minute 55 seconds, versus 8 minutes and 20 +seconds without, so it's worth setting up! + +## Compiling (Legacy EC) + +The `Makefile` doesn't yet support Goma, but this is planned for the +future. [b/214323409](https://issuetracker.google.com/214323409) +tracks the progress. diff --git a/docs/hammer.md b/docs/hammer.md new file mode 100644 index 0000000000..6048f1c441 --- /dev/null +++ b/docs/hammer.md @@ -0,0 +1,199 @@ +# Hammer care and feeding + +Original: [go/hammercare](http://go/hammercare) + +Last updated: 2021-03-18 + +[TOC] + +## Servo + +### Start servod + +``` +cros_sdk --no-ns-pid +sudo servod --port=9000 -b hammer -c hammer.xml +``` + +### UART console + +The simplest solution for most people is to use the `dut-console` script. + +First, add this line into your .bashrc (or other shell init script; needed once +only): +``` bash +alias dut-console="~/chromiumos/src/platform/dev/contrib/dut-console" +``` + +Then simply run `dut-console -c ec`. `dut-console` uses `cu` under the hood, and +works like ssh - to leave, press ` <~> <.> `. + + +``` bash +src/platform/dev/contrib/dut-console -p 9000 -c ec +``` + +## Build EC + +(Inside chroot) +``` bash +cd ~/trunk/src/platform/ec +make BOARD= -j +``` + +## Flash EC + +### Prerequisites + +#### Find the USB VID:PID of the device + +USB VID:PID is listed in [hammer/variants.h](../board/hammer/variants.h). +Many scripts below requires correct PID to work. + +#### Stop hammerd + +Remove rootfs verification: +``` bash +/usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification --force +``` + +Reboot the DUT then rename hammerd +``` bash +mv /usr/bin/hammerd /usr/bin/hammerd.bak +``` + +### Hammer connected to Chromebook, flash via USB + +(Inside chroot) Copy-paste the script below to a file named +"flash_hammer.usbremote", run +``` bash +bash flash_hammer.usbremote [ro] +``` + +``` bash +#!/bin/bash +# flash_hammer.usbremote +set -x -e + +BOARD=$1 +ID=$2 +IP=$3 +EXTRA="-d $ID" + +ssh $IP sh -c "'rm -f /usr/local/ec.bin'" +scp ~/trunk/src/platform/ec/build/${BOARD}/ec.bin $IP:/usr/local/ec.bin + +if [ "$4" = 'ro' ]; then + ssh $IP sh -x -c "'usb_updater2 $EXTRA -j; + sleep 1.0; + usb_updater2 $EXTRA /usr/local/ec.bin; + sleep 0.5; + usb_updater2 $EXTRA -s; + usb_updater2 $EXTRA /usr/local/ec.bin'" +else + ssh $IP sh -x -c "'usb_updater2 $EXTRA -w; + usb_updater2 $EXTRA -r; sleep 0.5; + usb_updater2 $EXTRA -s; + usb_updater2 $EXTRA /usr/local/ec.bin'" +fi +``` + +### Hammer connected to Chromebook, flash via servo + +(Inside chroot) Copy-paste the script below to a file named "flash_hammer", +run `bash flash_hammer ` + +``` bash +#!/bin/bash +# Recommended to use a USB 3.0 Ethernet adapter for this to work, otherwise the +# network on the DUT will temporarily go down when the root USB hub is taken +# down. + +set -e +IP=$1 +shift + +# USB 2.0 root hub +USBID="usb1" + +set -x + +# unbind, then rebind, the root hub (in the mean time, we'll start programming) +ssh $IP sh -c "'echo $USBID > /sys/bus/usb/drivers/usb/unbind; sleep 3; echo $USBID > /sys/bus/usb/drivers/usb/bind'" & + +util/flash_ec --board=hammer --port 9000 --image "$@" +``` + +### Hammer connected via servo only + +Do not connect hammer to Chromebook in this case, or at least make sure +Chromebook is either suspended (S3) or off (when put into programming mode, +STM32 always prefers USB interface when available) + +For Servo V2: + +``` bash +dut-control -p 9000 spi1_vref:pp3300 spi1_buf_en:on spi1_buf_on_flex_en:on +util/flash_ec --board=hammer --port=9000 [--image=/path/to/ec.bin] + +# To disable power from servo to Hammer +dut-control -p 9000 spi1_vref:off spi1_buf_en:off spi1_buf_on_flex_en:off +``` + +For Servo Micro (there is only one buffer in the power delivery path, +so don't include the spi1_buf_on_flex_en control): + +``` bash +dut-control -p 9000 spi1_vref:pp3300 spi1_buf_en:on +util/flash_ec --board=hammer --port=9000 [--image=/path/to/ec.bin] + +# To disable power from servo to Hammer +dut-control -p 9000 spi1_vref:off spi1_buf_en:off +``` + +### Hammer connected via POGO-PIN-USB to Linux + +So this is very similar to Hammer connected to poppy, flash via USB, but you +are directly running commands on the machine connected to Hammer, so you don’t +need to SSH to it. + +``` bash +#!/bin/bash +# flash_hammer.usblocal + +EXTRA= +EC=build/${BOARD:-hammer}/ec.bin +UPDATER=usb_updater2 + +if [ -n "$ID" ]; then + EXTRA="-d $ID" +fi + +if [ "$1" = 'ro' ]; then + "${UPDATER}" $EXTRA -j; + sleep 1.0; + "${UPDATER}" $EXTRA "${EC}"; + sleep 1.0; + "${UPDATER}" $EXTRA -s; + "${UPDATER}" $EXTRA "${EC}"; +else + "${UPDATER}" $EXTRA -w; + "${UPDATER}" $EXTRA -r; + sleep 1.0; + "${UPDATER}" $EXTRA -s; + "${UPDATER}" $EXTRA "${EC}"; +fi + +# To use this script: BOARD= ID= ./flash_hammer.usblocal [ro] +``` + +## Update touchpad firmware + +(Inside DUT) +``` bash +usb_updater2 --tp_update --device= +``` +or +``` bash +ec_touchpad_updater -p +``` diff --git a/docs/i2c-debugging.md b/docs/i2c-debugging.md index 7ab84f9d8d..4b6afc9a54 100644 --- a/docs/i2c-debugging.md +++ b/docs/i2c-debugging.md @@ -1,13 +1,13 @@ -I²C Debugging Tips -================== +# I²C Debugging Tips -The EC codebase has functionality to help you debug I²C errors without -pulling out the scope. Some of the debug functionality is disabled by -default to save space, but can be enabled with the `CONFIG_I2C_DEBUG` -option. +The EC codebase has functionality to help you debug I²C errors without pulling +out the scope. Some of the debug functionality is disabled by default to save +space, but can be enabled with the `CONFIG_I2C_DEBUG` option. -Tracing -------- +For Zephyr EC builds, enable I²C by adding `CONFIG_PLATFORM_EC_I2C_DEBUG=y` to +one of your project's Kconfig files. + +## Tracing You can use the `i2ctrace` command to monitor (ranges of) addresses: @@ -51,4 +51,4 @@ Note that `i2ctrace enable` will merge debug entries when possible: id port address -- ---- ------- 0 0 0x10 to 0x50 -``` \ No newline at end of file +``` diff --git a/docs/ide-support.md b/docs/ide-support.md index e8ab342073..1a8abda422 100644 --- a/docs/ide-support.md +++ b/docs/ide-support.md @@ -1,5 +1,7 @@ # IDE Support +This document explains how to configure IDEs to better support the EC codebase. + [TOC] ## Odd File Types @@ -12,16 +14,17 @@ Patterns | Vague Type ----------------------------------------------------- | ---------- `README.*` | Text `Makefile.rules`, `Makefile.toolchain` | Makefile +`Makefile.ide` | Makefile `gpio.wrap` | C Header `gpio.inc` | C Header `*.tasklist`, `*.irqlist`, `*.mocklist`, `*.testlist` | C Header ## IDE Configuration Primitives -Due to the way most EC code has been structured, you can typically only safely -inspect a configuration for a single image (RO or RW) for a single board. Thus, -you need to specify the specific board/image pair when requesting defines and -includes. +EC firmware presents some unique challenges because it is designed to support a +number of different MCUs and board configurations, each of which is split across +separate RO (Read-Only) and RW (Read-Write) applications. For this reason, you +must specify the specific board/image pair when requesting defines and includes. Command | Description -------------------------------------------- | ------------------------------ @@ -34,49 +37,85 @@ You can use the `ide-config.sh` tool to generate a VSCode configuration that includes selectable sub-configurations for every board/image pair. 1. From the root `ec` directory, do the following: + + ```bash + (outside) $ mkdir -p .vscode + ``` + ```bash - mkdir -p .vscode - ./util/ide-config.sh vscode all:RW all:RO | tee .vscode/c_cpp_properties.json + (chroot) $ ./util/ide-config.sh vscode all:RW all:RO | tee .vscode/c_cpp_properties.json ``` + 2. Open VSCode and navigate to some C source file. + 3. Run `C/C++ Reset IntelliSense Database` from the `Ctrl-Shift-P` menu + 4. Select the config in the bottom right, next to the `Select Language Mode`. You will only see this option when a C/C++ file is open. Additionally, you can select a configuration by pressing `Ctrl-Shift-P` and selecting the `C/C++ Select a Configuration...` option. -5. Add the EC specific file associations and style settings. - Modify `.vscode/settings.json` to have the following elements: - ```json - { - "editor.rulers": [80], - /* C, Makefiles, ASM, Linkerfiles, Properties */ - "editor.insertSpaces": false, - "editor.tabSize": 8, - /* Some exceptions based on current trends */ - "[markdown]": { - "editor.insertSpaces": true, - "editor.tabSize": 2 - }, - "[python]": { - "editor.insertSpaces": true, - "editor.tabSize": 2 - }, - "[shellscript]": { - "editor.insertSpaces": true, - "editor.tabSize": 2 - }, - "[yaml]": { - "editor.insertSpaces": true, - "editor.tabSize": 2 - }, - "files.associations": { - "Makefile.*": "makefile", - "*.inc": "c", - "*.wrap": "c", - "*.tasklist": "c", - "*.irqlist": "c", - "*.mocklist": "c", - "*.testlist": "c" - } - } - ``` + +5. Add the EC specific file associations and style settings. Do the following + to copy the default settings to `.vscode/settings.json`: + + ```bash + (outside) $ cp .vscode/settings.json.default .vscode/settings.json + ``` + +## VSCode CrOS IDE + +CrOS IDE is a VSCode extension to enable code completion and navigation for +ChromeOS source files. + +Support for `platform/ec` is not available out of the box (yet), but can be +manually enabled following these steps. + +### Prerequisites + +Install CrOS IDE following the [quickstart guide] + + +*** note +NOTE: CrOS IDE uses the VSCode extension `clangd` for code completion and +navigation. The installation of CrOS IDE disables the built-in +`C/C++ IntelliSense` because it is not compatible with `clangd`. +*** + + +### Configure EC Board + +1. Enter the EC repository: + + ```bash + (chroot) $ cd ~/chromiumos/src/platform/ec + ``` + +1. Create a `compile_commands.json` for the all EC boards: + + ```bash + (chroot) $ make all-ide-compile-cmds -j + ``` + +1. Select a particular board: + + ```bash + (chroot) $ export BOARD=bloonchipper + ``` + +1. Copy the new `compile_commands.json` in the root of the EC repository: + + ```bash + cp build/${BOARD}/RW/compile_commands.json . + ``` + +Note: a single `compile_commands.json` can only cover one specific build +configuration. Only the `compile_commands.json`placed in the root of the EC +repository is considered active. When the build configuration changes (e.g. user +wants to use a different board), repeat steps 3 and 4 to replace the active +`compile_commands.json` file. + +To create a `compile_commands.json` for a specific EC board: + +```bash +(chroot) $ make BOARD=${BOARD} ide-compile-cmds +``` diff --git a/docs/images/CQ_Prototype_Environment.jpg b/docs/images/CQ_Prototype_Environment.jpg new file mode 100644 index 0000000000..192fe139fe Binary files /dev/null and b/docs/images/CQ_Prototype_Environment.jpg differ diff --git a/docs/images/Dragonclaw_in_CQ_Prototype_Environment.jpg b/docs/images/Dragonclaw_in_CQ_Prototype_Environment.jpg deleted file mode 100644 index 374e4f244b..0000000000 Binary files a/docs/images/Dragonclaw_in_CQ_Prototype_Environment.jpg and /dev/null differ diff --git a/docs/images/FPMCU_devboard_environment_v2_with_Satlab.jpg b/docs/images/FPMCU_devboard_environment_v2_with_Satlab.jpg new file mode 100644 index 0000000000..c3663f7401 Binary files /dev/null and b/docs/images/FPMCU_devboard_environment_v2_with_Satlab.jpg differ diff --git a/docs/images/artifacts.png b/docs/images/artifacts.png new file mode 100644 index 0000000000..2981509362 Binary files /dev/null and b/docs/images/artifacts.png differ diff --git a/docs/images/cros_fingerprint_tpm_seed.png b/docs/images/cros_fingerprint_tpm_seed.png new file mode 100644 index 0000000000..8213e6f775 Binary files /dev/null and b/docs/images/cros_fingerprint_tpm_seed.png differ diff --git a/docs/images/dartmonkey.jpg b/docs/images/dartmonkey.jpg deleted file mode 100644 index 5eb15ef73d..0000000000 Binary files a/docs/images/dartmonkey.jpg and /dev/null differ diff --git a/docs/images/dir_coverage.png b/docs/images/dir_coverage.png new file mode 100644 index 0000000000..152b2711a2 Binary files /dev/null and b/docs/images/dir_coverage.png differ diff --git a/docs/images/download_html.png b/docs/images/download_html.png new file mode 100644 index 0000000000..399d098936 Binary files /dev/null and b/docs/images/download_html.png differ diff --git a/docs/images/dragonclaw_v0.3.jpg b/docs/images/dragonclaw_v0.3.jpg new file mode 100644 index 0000000000..8158d42a17 Binary files /dev/null and b/docs/images/dragonclaw_v0.3.jpg differ diff --git a/docs/images/dragonclaw_with_10_pin_swd.jpg b/docs/images/dragonclaw_with_10_pin_swd.jpg index fb4711cf29..1332cb0125 100644 Binary files a/docs/images/dragonclaw_with_10_pin_swd.jpg and b/docs/images/dragonclaw_with_10_pin_swd.jpg differ diff --git a/docs/images/dragonclaw_with_20_pin_swd.jpg b/docs/images/dragonclaw_with_20_pin_swd.jpg index 18257a1ea7..666bf2cc21 100644 Binary files a/docs/images/dragonclaw_with_20_pin_swd.jpg and b/docs/images/dragonclaw_with_20_pin_swd.jpg differ diff --git a/docs/images/dragonclaw_yoshi_flex_header.jpg b/docs/images/dragonclaw_yoshi_flex_header.jpg deleted file mode 100644 index 11ca23ddff..0000000000 Binary files a/docs/images/dragonclaw_yoshi_flex_header.jpg and /dev/null differ diff --git a/docs/images/dragonclaw_yoshi_flex_header2.jpg b/docs/images/dragonclaw_yoshi_flex_header2.jpg deleted file mode 100644 index ae515dfd43..0000000000 Binary files a/docs/images/dragonclaw_yoshi_flex_header2.jpg and /dev/null differ diff --git a/docs/images/file_coverage.png b/docs/images/file_coverage.png new file mode 100644 index 0000000000..f110e44200 Binary files /dev/null and b/docs/images/file_coverage.png differ diff --git a/docs/images/gerrit_coverage_links.png b/docs/images/gerrit_coverage_links.png new file mode 100644 index 0000000000..43afac943e Binary files /dev/null and b/docs/images/gerrit_coverage_links.png differ diff --git a/docs/images/icetower_v0.1.jpg b/docs/images/icetower_v0.1.jpg new file mode 100644 index 0000000000..46d95e17e5 Binary files /dev/null and b/docs/images/icetower_v0.1.jpg differ diff --git a/docs/images/icetower_v3.jpg b/docs/images/icetower_v3.jpg new file mode 100644 index 0000000000..e3a1aaa638 Binary files /dev/null and b/docs/images/icetower_v3.jpg differ diff --git a/docs/images/icetower_with_20_pin_swd.jpg b/docs/images/icetower_with_20_pin_swd.jpg new file mode 100644 index 0000000000..a7261e6fb9 Binary files /dev/null and b/docs/images/icetower_with_20_pin_swd.jpg differ diff --git a/docs/images/postsubmit.png b/docs/images/postsubmit.png new file mode 100644 index 0000000000..65c630276f Binary files /dev/null and b/docs/images/postsubmit.png differ diff --git a/docs/images/servo_v2.jpg b/docs/images/servo_v2.jpg deleted file mode 100644 index e45833ebe9..0000000000 Binary files a/docs/images/servo_v2.jpg and /dev/null differ diff --git a/docs/images/servo_v2_jtag_header.jpg b/docs/images/servo_v2_jtag_header.jpg deleted file mode 100644 index 0cfe3e832d..0000000000 Binary files a/docs/images/servo_v2_jtag_header.jpg and /dev/null differ diff --git a/docs/images/servo_v2_with_micro_usb.jpg b/docs/images/servo_v2_with_micro_usb.jpg deleted file mode 100644 index dc5c53e258..0000000000 Binary files a/docs/images/servo_v2_with_micro_usb.jpg and /dev/null differ diff --git a/docs/images/servo_v2_with_yoshi_flex.jpg b/docs/images/servo_v2_with_yoshi_flex.jpg deleted file mode 100644 index 77263f6676..0000000000 Binary files a/docs/images/servo_v2_with_yoshi_flex.jpg and /dev/null differ diff --git a/docs/images/servo_v2_with_yoshi_flex2.jpg b/docs/images/servo_v2_with_yoshi_flex2.jpg deleted file mode 100644 index 833134fd7f..0000000000 Binary files a/docs/images/servo_v2_with_yoshi_flex2.jpg and /dev/null differ diff --git a/docs/images/test_firmware.png b/docs/images/test_firmware.png new file mode 100644 index 0000000000..42f707810a Binary files /dev/null and b/docs/images/test_firmware.png differ diff --git a/docs/images/usb_source_port_balancing.png b/docs/images/usb_source_port_balancing.png new file mode 100644 index 0000000000..6f4ccf8b93 Binary files /dev/null and b/docs/images/usb_source_port_balancing.png differ diff --git a/docs/images/usbc_block_diagram.png b/docs/images/usbc_block_diagram.png new file mode 100644 index 0000000000..9c05c69f3c Binary files /dev/null and b/docs/images/usbc_block_diagram.png differ diff --git a/docs/images/volteer_adc.png b/docs/images/volteer_adc.png new file mode 100644 index 0000000000..305334ef92 Binary files /dev/null and b/docs/images/volteer_adc.png differ diff --git a/docs/images/yoshi_flex.jpg b/docs/images/yoshi_flex.jpg deleted file mode 100644 index 0ba3304721..0000000000 Binary files a/docs/images/yoshi_flex.jpg and /dev/null differ diff --git a/docs/images/yoshi_flex_swd_rework.jpg b/docs/images/yoshi_flex_swd_rework.jpg deleted file mode 100644 index 8dd088745e..0000000000 Binary files a/docs/images/yoshi_flex_swd_rework.jpg and /dev/null differ diff --git a/docs/images/zephyr_ec_structure.png b/docs/images/zephyr_ec_structure.png new file mode 100644 index 0000000000..fe01a4ac25 Binary files /dev/null and b/docs/images/zephyr_ec_structure.png differ diff --git a/docs/ite-ec-reflashing.md b/docs/ite-ec-reflashing.md new file mode 100644 index 0000000000..59cfc8f303 --- /dev/null +++ b/docs/ite-ec-reflashing.md @@ -0,0 +1,194 @@ +# ITE EC firmware reflashing via Servo: How it works + +This doc: [http://go/cros-ite-reflash-design](https://goto.google.com/cros-ite-ec-reflash-design) +
+First written: 2022-08-15 +
+Last updated: 2022-08-24 + +Familiarity with [Chromium OS](https://www.chromium.org/chromium-os) and +[Embedded Controller (EC)](../README.md) development is assumed. + +[TOC] + +## Background + +### Other documents +* [Reflashing an ITE EC](../util/iteflash.md) +* Googlers, and Partners involved in ITE EC projects only: + [The State of ITE CrOS EC Reflashing](https://goto.google.com/cros-ite-ec-reflash-state) + * That document is not public, do not request access if you lack it. +* `i2c-pseudo` [README](../extra/i2c_pseudo/README) +* `i2c-pseudo` [Documentation.txt](../extra/i2c_pseudo/Documentation.txt) + +### Terminology + +**EC** refers to an +[Embedded Controller](https://en.wikipedia.org/wiki/Embedded_controller) +(microcontroller). + +**ITE EC** refers to the [ITE](http://www.ite.com.tw/) +[IT8320](http://www.ite.com.tw/en/product/view?mid=96) +[Embedded Controller (EC)](https://en.wikipedia.org/wiki/Embedded_controller) +microcontroller when used as a Chromium OS / Chrome OS EC. + +**CrOS** refers to Chromium OS, Chrome OS, or both, depending on the context. +The distinction between Chromium OS and Chrome OS is largely immaterial to this +document. + +**DUT Controller Servo** refers to a device that provides direct access +to various circuits on a Chrome OS device motherboard. As of this writing, the +most common DUT controller [servos](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/refs/heads/main/docs/servo.md) used by +CrOS developers are +[CR50 (CCD)](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/refs/heads/main/docs/ccd.md), +`C2D2`, +[Servo Micro](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/refs/heads/main/docs/servo_micro.md), and +[Servo v2](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/refs/heads/main/docs/servo_v2.md). (Note that +[Servo v4](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/refs/heads/main/docs/servo_v4.md) and +[Servo v4.1](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/refs/heads/main/docs/servo_v4p1.md) are **not** +DUT Controller Servos. They are Hub Servos, and are typically used in conjection with a DUT Controller Servo. Hub Servos are not directly involved in EC reflashing.) See also +[Case-Closed Debug in Chromebooks and Servo Micro](https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/main/board/servo_micro/ccd.md). + +**Servod** refers to a piece of software that runs on a USB host and provides +interfaces for controlling a Servo connected to the host as a USB device. See [servod](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/refs/heads/main/docs/servod.md). + +## Core steps + +Two things need to happen: + +1. Send special non-I2C waveforms over I2C clock and data lines to the ITE EC, + to enable a debug mode in the EC where it will respond at a predefined + I2C address as an I2C peripheral. + * This debug mode is implemented by ITE in silicon and/or immutable + firmware, it is not part of Chrome OS EC firmware. It is available even + if Chrome OS RO+RW firmware on the EC is corrupted. + +1. Communicate with and control the ITE EC using its I2C-based debug mode. All + signals on the I2C bus in question are now actual I2C, with the ITE EC + acting as an I2C peripheral device. The EC firmware gets sent as I2C + payload. + * If the previous step is not successful, then the EC will not respond to + I2C messages. + +The DUT Controller Servo performs these steps. + +## Control flow + +[flash_ec](https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/util/flash_ec) +is the user interface for all Chrome OS device EC reflashing via Servos. +`servod` must be running to use `flash_ec`. + +### Original control flow, for Servo v2 only + +The original implementation of ITE EC reflashing via Servo is only compatible +with Servo v2, due to interfacing directly with its FTDI USB to MPSSE IC +(FTDI FT4232HL). + +1. `flash_ec` tells `servod` to close its interface for controlling the + `Servo v2` FTDI USB device. + * This breaks the layering of `servod` as the interface through which + servos are controlled, and is a maintenance + complexity burden to + support in `servod`. No other servo I2C interfaces in `servod` support or + need this functionality of relinquishing control. +1. `flash_ec` invokes [iteflash](https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/main/util/iteflash.c). +1. `iteflash` takes control of the `Servo v2` FTDI USB device. +1. `iteflash` [bit-bangs](https://en.wikipedia.org/wiki/Bit_banging) the + special waveforms using the `Servo v2` FTDI USB device. +1. `iteflash` uses FTDI I2C functionality (not bit-banging) to talk I2C with + the ITE EC, including sending the EC firmware as payload in I2C messages. +1. `flash_ec` tells `servod` to reopen its `Servo v2` FTDI USB interface. + +### New control flow through servod, for all other DUT controller servo types + +1. When `servod` starts, it creates a pseudo I2C adapter in Linux for every + servo I2C bus it controls, if the `i2c-pseudo` module is loaded. + * This pseudo I2C adapter can be used on the host system as if it were a + native I2C bus, including from userspace if the `i2c-dev` module is + loaded. + * For more information on the `i2c-pseudo` module see + [Reflashing an ITE EC](../util/iteflash.md), as well as `i2c-pseudo`'s + [README](../extra/i2c_pseudo/README) and + [Documentation.txt](../extra/i2c_pseudo/Documentation.txt). +1. `flash_ec` issues a `servod` command for the DUT controller servo to send + the special waveforms. + * For `Servo Micro` and `C2D2` all `servod` needs to do is issue a + servo console command, `enable_ite_dfu`, which triggers a + servo firmware function to perform the special waveforms. + * The servo does not know what kind of DUT it is connected to, thus the + `enable_ite_dfu` console commands are always available. The + special waveforms will not do anything useful unless the DUT has + an ITE EC. + * `CR50` (CCD) is mostly the same, except: + 1. CCD must be unlocked and the `ccd_i2c_en` CCD capability must be set + to `Always`. + 1. The `CR50` firmware function for sending the special waveforms is + invoked by a special I2C message, not a console command. + 1. `CR50` must reboot itself to perform the special waveforms. During + normal operation `CR50` has deliberate clock jitter which would + prevent accurately preforming the waveforms. This jitter cannot + safely be disabled, except on reset, and only while the `AP` is held + in reset. + * [Future] If we were to support this control flow with `Servo v2`, the + cleanest way would be to move the FTDI-based bit-banging of the + special waveforms from `iteflash` into `servod` itself, as a C/C++ + extension, so that `flash_ec` can trigger it with a `servod` command the + same as for other servo types. This would allow removing the hack in + `servod` to relinquish control of the `Servo v2` FTDI USB interface. + * Proof-of-concept [CL:1522847](https://crrev.com/c/1522847) adds support + for using Servo v2 via `servod`. However as of this writing that CL + ([patchset 14](https://crrev.com/c/1522847/14)) only changes the I2C + communication path, it does NOT move the special waveforms into + `servod`, which is needed to remove the `servod` I2C interface + close + reopen hack and fully merge the Servo v2 ITE EC reflashing into + this new control flow. +1. `flash_ec` asks `servod` for the local Linux i2c-dev path of the + DUT Controller Servo's DUT-connected I2C interface (which is backed by + `servod` itself via the `i2c-pseudo` module). +1. `flash_ec` invokes `iteflash`, passing it the i2c-dev path given by + `servod`. +1. `iteflash` performs the EC firmware update via the i2c-dev interface. + +## Why `i2c-pseudo` and alternative implementations considered + +Instead of using `i2c-dev` Linux I2C interfaces, `iteflash` could communicate +directly with `servod` using a custom protocol. This would make `iteflash` +dependent on `servod` and whatever custom protocol we come up with, as there is +no standard userspace<->userspace I2C interface to implement. + +In the future we may choose to implement Servo I2C interfaces as actual +host-side Linux drivers, which `servod` would use via `i2c-dev` +(which it supports already!). Since the `flash_ec` and `iteflash` portions of +this process are built around `i2c-dev` now, they should continue working with +no changes needed for this scenario. + +Why bother with i2c-pseudo at all then? Why not go straight to reimplementing +the Servo I2C interfaces as new Linux I2C adapter drivers, instead of +implementing the new `i2c-pseudo` driver? + +Rearchitecting the Servo I2C interfaces is not something to be considered +lightly, and not worthwhile just for ITE EC reflashing. By staying with the +existing `servod` Servo I2C implementations we have not introduced any +dependency on new kernel modules for *existing* `servod` functionality. Only +the new ITE EC reflashing functionality depends on `i2c-pseudo`. As with +`i2c-pseudo` we would need to rely on out-of-tree kernel module distribution +for these new Servo I2C modules until eventual upstream acceptance + +percolation down to distribution Linux kernels, with no guarantee of acceptance +for our obscure Servo hardware. Depending on a new kernel module for this one +new function of ITE EC reflashing is one thing. Requiring new modules for all +`servod` use would be quite another. Realistically we would need to maintain +fallback code in `servod` to use its existing internal Servo I2C interface +implementations when the kernel ones aren't available, but that has a +maintenance cost too. These same issues would be faced with every new +generation of Servo, so this broad Servo + `servod` architectural change is not +something to be considered lightly or just for ITE EC reflashing. + +`i2c-pseudo` has potential uses in the CrOS ecosystem beyond ITE EC reflashing. +A big one is mocking I2C interfaces for driver and system tests. There is the +longstanding `i2c-stub` module for this purpose, but its functionality is +limited compared to `i2c-pseudo`, not all I2C device behavior can be modeled +with `i2c-stub`. Also by having the `servod` I2C pseudo interfaces, one can +conveniently use the standard Linux I2C command line tools +(i2cget(8), i2cset(8), i2ctransfer(8), etc) for interfacing with Servo and DUT +I2C devices. While it is unlikely that i2c-pseudo will have any use in CrOS +itself, it is expected to have further uses in both developer tooling and +code tests. diff --git a/docs/low_battery_startup.md b/docs/low_battery_startup.md index de346546c8..c82268a308 100644 --- a/docs/low_battery_startup.md +++ b/docs/low_battery_startup.md @@ -1,8 +1,8 @@ # Configuring the EC for Low-Battery Startup Near the bottom of charge, starting up a ChromeOS device can be a tricky -proposition. Several features interact to make it difficult to reliably turn on -the machine without browning out. Over the years, a variety of configuration +proposition. Several features interact to make it difficult to reliably turn on +the machine without browning out. Over the years, a variety of configuration options have been written to maximize ChromeOS's compatibility with the basic user expectation, @@ -26,23 +26,23 @@ which are available. ### Battery and Charging Circuit For the most part, ChromeOS device power systems are much like other laptop -battery power systems. A variable-voltage rail is connected to the battery via -a series of cutoff MOSFETs. Several system power rails derive their power from -the system's variable-voltage rail. Mains power is delivered to the -variable-voltage system rail by a buck/boost charging circuit. Mains power is -itself rectified, isolated, and stepped down by an external power supply. +battery power systems. A variable-voltage rail is connected to the battery via a +series of cutoff MOSFETs. Several system power rails derive their power from the +system's variable-voltage rail. Mains power is delivered to the variable-voltage +system rail by a buck/boost charging circuit. Mains power is itself rectified, +isolated, and stepped down by an external power supply. During most of the battery charge, the charger operates in current mode, acting as a constant current source that delivers current to the variable-voltage rail. -Load transients are served by the capacitance on the rail and the battery. By +Load transients are served by the capacitance on the rail and the battery. By superposition, load transients during the charge don't necessarily draw current from the battery, they may just reduce the current flow into the battery. References to AC power in the EC codebase are actually references to an external -power supply's DC source. External supplies that are actually USB-PD-speaking +power supply's DC source. External supplies that are actually USB-PD-speaking battery packs are indistinguishable from AC/DC adapters as far as the EC is -concerned. Variables and functions which refer to external supplies all refer -to them as 'AC', though. +concerned. Variables and functions which refer to external supplies all refer to +them as 'AC', though. ### Source Current Negotiation @@ -50,13 +50,13 @@ A device may draw power from an AC adapter via a few methods. #### USB BC1.2 Current Sources -BC1.2 negotiation is usually managed entirely by an external IC. Once it is -complete, the EC limits itself to 2.4A max. Additionally, the charger may be +BC1.2 negotiation is usually managed entirely by an external IC. Once it is +complete, the EC limits itself to 2.4A max. Additionally, the charger may be configured to switch to an input voltage regulation mode if the input voltage begins to sag too low. Ideally, the input source provides a voltage droop, such that it is not quite -overloaded at the input voltage regulation setpoint of about 4.5V. Thus, 4.5V +overloaded at the input voltage regulation setpoint of about 4.5V. Thus, 4.5V serves as a reasonable reference voltage for the charger to use when it is in an input voltage-regulation mode. @@ -68,45 +68,44 @@ See also `driver/bc12/max14637.c:bc12_detect()`. #### USB-PD Sources High-current power supplies are negotiated via the USB Type C Current Source and -USB Power Delivery specifications (PD). PD sources must support Type-C Current -Source, but the reverse is not true. Both types of current sources are managed +USB Power Delivery specifications (PD). PD sources must support Type-C Current +Source, but the reverse is not true. Both types of current sources are managed via the PD protocol module in the EC codebase. Type-C Current Source capabilities of up to 15W (3A, 5V) are advertised via -analog signaling alone. Via digital communication in the PD protocol, much -higher power states may be negotiated. However, higher power states also -usually run at a higher voltage state as well. Any time the voltage level is -changing, the power sink (the ChromeOS device) must lower its power consumption -during the transient. The standby current level is governed by -`CONFIG_CHARGER_INPUT_CURRENT`. - -PD port partners are capable of both soft and hard resets. Hard resets will +analog signaling alone. Via digital communication in the PD protocol, much +higher power states may be negotiated. However, higher power states also usually +run at a higher voltage state as well. Any time the voltage level is changing, +the power sink (the ChromeOS device) must lower its power consumption during the +transient. + +PD port partners are capable of both soft and hard resets. Hard resets will cause a dead-bus state for a brief interval before PD can renegotiate, from -scratch, because it is intended to emulate a cable disconnect. Therefore, a -hard reset without a connected battery will brownout the Chromebook. +scratch, because it is intended to emulate a cable disconnect. Therefore, a hard +reset without a connected battery will brownout the Chromebook. ### Locked and Unlocked Firmware The Verified Boot implementation normally limits the complexity of the code -which executes in the locked Read-Only firmware package. The consequences for +which executes in the locked Read-Only firmware package. The consequences for the EC are: -- Locked RO EC firmware does not process any digital PD messages at all, it only - recognizes the analog advertisement of USB Current Source (15W max). -- Installation of user-provided firmware is supported, but the write-protect pin - must be cleared to enable it. -- On recent systems, write-protect is cleared by removing the system battery. +- Locked RO EC firmware does not process any digital PD messages at all, it + only recognizes the analog advertisement of USB Current Source (15W max). +- Installation of user-provided firmware is supported, but the write-protect + pin must be cleared to enable it. +- On recent systems, write-protect is cleared by removing the system battery. ### ChromeOS `powerd` The power management daemon provided by ChromeOS displays a "low-power charger" warning message via the system tray whenever the charger is limited to less than -20W. Therefore, if a USB-PD source is restricted to analog signaling, or a -BC1.2 source is connected, the user gets alerted to the situation. +20W. Therefore, if a USB-PD source is restricted to analog signaling, or a BC1.2 +source is connected, the user gets alerted to the situation. Systems that can run on very little power may be rapidly charged with a 15W charger, while a high power system may require a 40W state or more for a decent -battery charging user experience. Therefore, a board's overlay may override the +battery charging user experience. Therefore, a board's overlay may override the warning threshold by replacing `/usr/share/power_manager/usb_min_ac_watts` in the board's filesystem. @@ -116,7 +115,7 @@ See also `platform2/power_manager/` source code. Under normal conditions, the battery pack is equipped with a management IC which is solely responsible for the safety of the battery, measurement of the state of -charge, and the balance of its cells. Examples include (but are not limited to) +charge, and the balance of its cells. Examples include (but are not limited to) the TI BQ40Z50 and Renesas RAJ240. However, after very long periods of rest without a battery charging cycle, the @@ -124,7 +123,7 @@ natural self-discharge rate of each cell will cause them to diverge somewhat from each other. Some IC's can be configured to report a pack total state of charge of zero if -any one cell's voltage is below a certain threshold. However, many do not. +any one cell's voltage is below a certain threshold. However, many do not. Therefore, after an extended rest period, one cell can be very close to the cell undervoltage cutoff threshold, even though the pack as a whole is considered to be at 3% charge or more. @@ -132,14 +131,14 @@ be at 3% charge or more. ### Power Profile During Boot The power profile during the boot sequence is substantially different than that -seen during typical use. Dynamic voltage and frequency scaling of the AP is -partially governed by the temperature of the processor core. As the processor +seen during typical use. Dynamic voltage and frequency scaling of the AP is +partially governed by the temperature of the processor core. As the processor gets hotter, it will reduce its maximum core voltage and frequency to settle out -at some maximum design junction temperature for the core. For passively cooled +at some maximum design junction temperature for the core. For passively cooled devices, the profile may also be chosen to limit the external case temperature. -At startup, the case and core are cold. The bootloaders and kernel are also -optimized to boot as fast as possible for a responsive user experience. So, the +At startup, the case and core are cold. The bootloaders and kernel are also +optimized to boot as fast as possible for a responsive user experience. So, the power drawn during the boot is much higher than that seen during typical productivity and entertainment tasks. @@ -148,17 +147,15 @@ productivity and entertainment tasks. After verification and optional update of the EC's RW firwmare, Depthcharge will poll the EC to verify that it is allowed to proceed to boot to the kernel. -It does this by polling via the: -- `EC_CMD_CHARGE_STATE` host command. -- `CHARGE_STATE_CMD_GET_PARAM` subcommand. -- `CS_PARAM_LIMIT_POWER` parameter. +It does this by polling via the: - `EC_CMD_CHARGE_STATE` host command. - +`CHARGE_STATE_CMD_GET_PARAM` subcommand. - `CS_PARAM_LIMIT_POWER` parameter. When the EC returns 0, power draw by the AP is unlimited and depthcharge resumes -the boot. If the EC fails to return 0 in three seconds, depthcharge shuts down. +the boot. If the EC fails to return 0 in three seconds, depthcharge shuts down. See also vb2ex_ec_vboot_done() in Depthcharge, and option -`CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW` in the EC. By default, this option -is not set, and the EC immediately allows the boot to proceed. +`CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW` in the EC. By default, this option is +not set, and the EC immediately allows the boot to proceed. ## Example Low-Battery Boot Sequences and Configurations @@ -166,49 +163,49 @@ Most ChromeOS devices power needs will be met by one of the following templates. ### Low-Power Device -Low-power devices require 15W or less of power to boot the AP. The battery pack +Low-power devices require 15W or less of power to boot the AP. The battery pack is robust enough to support the device during brief intervals of PD negotiation without browning out. ``` -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 ``` A detailed boot sequence under this configuration, with a low battery and available AC power via a USB-PD charger: -1. EC ROM bootloader loads and jumps to the EC's read-only firmware image. -1. RO firmware negotiates a 15W state via Current Source analog signaling and - begins charging the battery with it. -1. RO firmware verifies conditions to begin booting the AP: - - Battery state of charge > 1% - - OR charger power greater or equal to 15W (met by Current Source analog - signaling). -1. AP firmware performs verification of the EC's RW image, upgrades it if - necessary, and sysjumps the EC to it. -1. AP firmware queries the charge state limit power flag via EC-host command, - and the EC immediately responds that it is clear. -1. Depthcharge continues the boot. - 1. In parallel with kernel loading and Linux's boot, the EC performs PD - negotiation. Charger power lowers to 2.5W for up to 500ms as the source +1. EC ROM bootloader loads and jumps to the EC's read-only firmware image. +1. RO firmware negotiates a 15W state via Current Source analog signaling and + begins charging the battery with it. +1. RO firmware verifies conditions to begin booting the AP: + - Battery state of charge > 1% + - OR charger power greater or equal to 15W (met by Current Source analog + signaling). +1. AP firmware performs verification of the EC's RW image, upgrades it if + necessary, and sysjumps the EC to it. +1. AP firmware queries the charge state limit power flag via EC-host command, + and the EC immediately responds that it is clear. +1. Depthcharge continues the boot. + 1. In parallel with kernel loading and Linux's boot, the EC performs PD + negotiation. Charger power lowers to 2.5W for up to 500ms as the source transitions from vSafe5V to its highest supported voltage (15V or 20V - are typical). During this transition time some power is drawn from the + are typical). During this transition time some power is drawn from the battery. - 1. After PD negotiation is complete, the EC raises the charger current + 1. After PD negotiation is complete, the EC raises the charger current limit to the negotiated limit (45W is typical). ### Low-Power Device Startup With Marginal Battery Compatibility Similar in configuration to the low-power device startup, this system enables additional options to maximize its compatibility with marginal batteries near -the bottom of charge. The Grunt family is an exemplar. This system will -complete software sync with less than 15W of power, but may require more power -to boot the kernel and get to the login screen. +the bottom of charge. The Grunt family is an exemplar. This system will complete +software sync with less than 15W of power, but may require more power to boot +the kernel and get to the login screen. ``` /* Limit battery impact during PD voltage changes. */ -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 /* Distrust the battery SOC measurement a bit. */ #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 3 @@ -229,85 +226,81 @@ battery must support per-cell voltage measurement. A detailed boot sequence under this configuration, with a low battery and available AC power: -1. EC ROM bootloader loads and jumps to the EC's read-only firmware image. -1. RO firmware negotiates a 15W state via Current Source analog signaling and - begins charging the battery with it. -1. RO firmware verifies conditions to begin booting the AP: - - battery state of charge >= 3% AND cell imbalance < 200 mV - - OR battery state of charge >= 5% - - OR charger power greater or equal to 15W (met by Current Source analog - signaling). -1. AP firmware performs verification of the EC's RW image, upgrades it if - necessary, and sysjumps the EC to it. -1. AP firmware polls the charge state limit power flag via EC-host command for - up to 3 seconds, in 50ms intervals. The EC will return `1` (power limited) - so long as the charger power is < 15.001W and the battery is less than 3%. - 1. Meanwhile, the EC performs PD negotiation. Charger power lowers to 2.5W +1. EC ROM bootloader loads and jumps to the EC's read-only firmware image. +1. RO firmware negotiates a 15W state via Current Source analog signaling and + begins charging the battery with it. +1. RO firmware verifies conditions to begin booting the AP: + - battery state of charge >= 3% AND cell imbalance < 200 mV + - OR battery state of charge >= 5% + - OR charger power greater or equal to 15W (met by Current Source analog + signaling). +1. AP firmware performs verification of the EC's RW image, upgrades it if + necessary, and sysjumps the EC to it. +1. AP firmware polls the charge state limit power flag via EC-host command for + up to 3 seconds, in 50ms intervals. The EC will return `1` (power limited) + so long as the charger power is < 15.001W and the battery is less than 3%. + 1. Meanwhile, the EC performs PD negotiation. Charger power lowers to 2.5W for up to 500ms as the source transitions from vSafe5V to its highest supported voltage (15V or 20V are typical). - 1. After negotiation is complete, the EC raises the charger current limit + 1. After negotiation is complete, the EC raises the charger current limit to the negotiated limit (45W is typical). - 1. The EC returns 0 (unlimited) on the next `LIMIT_POWER` request. -1. Depthcharge continues to boot Linux. - + 1. The EC returns 0 (unlimited) on the next `LIMIT_POWER` request. +1. Depthcharge continues to boot Linux. ### High-Power Boot Device Startup A "high-power device" in this case is one that requires significantly more than -15W of power to boot the AP. These devices may complete software sync at 15W or -less. Very briefly drawing current out of the battery does not cause a -brownout. +15W of power to boot the AP. These devices may complete software sync at 15W or +less. Very briefly drawing current out of the battery does not cause a brownout. Example configuration: ``` -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 3 #define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 15000 #define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 27000 ``` -Where the low-power device specified a threshold that just barely -requires PD negotiation to happen before booting, this device has a definite -minimum power to boot Linux (27W). A detailed boot sequence under this -configuration, with a low battery and available AC power: - -1. EC ROM bootloader loads and jumps to the EC's read-only firmware image. -1. RO firmware negotiates a 15W state via Current Source analog signaling and - begins charging the battery with it. -1. RO firmware verifies conditions to begin booting the AP: - - battery state of charge >= 3% - - OR charger power greater or equal to 15W (met by Current Source analog - signaling). -1. AP firmware performs verification of the EC's RW image, upgrades it if - necessary, and sysjumps the EC to it. -1. AP firmware polls the charge state limit power flag via EC-host command for - up to 3 seconds, in 50ms intervals. The EC will return `1` (power limited) - so long as the charger power is < 27W and the battery is less than 3%. - 1. Meanwhile, the EC performs PD negotiation. Charger power lowers to 2.5W +Where the low-power device specified a threshold that just barely requires PD +negotiation to happen before booting, this device has a definite minimum power +to boot Linux (27W). A detailed boot sequence under this configuration, with a +low battery and available AC power: + +1. EC ROM bootloader loads and jumps to the EC's read-only firmware image. +1. RO firmware negotiates a 15W state via Current Source analog signaling and + begins charging the battery with it. +1. RO firmware verifies conditions to begin booting the AP: + - battery state of charge >= 3% + - OR charger power greater or equal to 15W (met by Current Source analog + signaling). +1. AP firmware performs verification of the EC's RW image, upgrades it if + necessary, and sysjumps the EC to it. +1. AP firmware polls the charge state limit power flag via EC-host command for + up to 3 seconds, in 50ms intervals. The EC will return `1` (power limited) + so long as the charger power is < 27W and the battery is less than 3%. + 1. Meanwhile, the EC performs PD negotiation. Charger power lowers to 2.5W for up to 500ms as the source transitions from vSafe5V to its highest supported voltage (15V or 20V are typical). - 1. After negotiation is complete, the EC raises the charger current limit + 1. After negotiation is complete, the EC raises the charger current limit to the negotiated limit (45W is typical). - 1. The EC returns 0 (unlimited) on the next `LIMIT_POWER` request. -1. Depthcharge continues to boot Linux. - + 1. The EC returns 0 (unlimited) on the next `LIMIT_POWER` request. +1. Depthcharge continues to boot Linux. ### High-Power SwSync Device Startup Like the high-power boot device startup, these devices draw less than 15W during most of the software sync process, but may briefly exceed 15W during short -intervals of software sync. However, there is substantial risk of brownout -during those intervals unless the battery is charged up a bit first. Therefore, +intervals of software sync. However, there is substantial risk of brownout +during those intervals unless the battery is charged up a bit first. Therefore, they strictly require 1% battery capacity to perform software sync. Additionally, this configuration requires PD negotiation to be complete prior to -performing a no-battery boot. Nami is an exemplar. - +performing a no-battery boot. Nami is an exemplar. Example configuration: ``` -#define CONFIG_CHARGER_INPUT_CURRENT 512 +#define CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT 512 #define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC 1 #define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT 15000 @@ -319,42 +312,51 @@ Example configuration: #define CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW 27000 ``` -1. EC ROM bootloader loads and jumps to the EC's read-only firmware image. -1. RO firmware negotiates a 15W state via Current Source analog signaling and - begins charging the battery with it. -1. RO firmware verifies conditions to begin booting the AP: - - Battery state of charge is greater than 1% AND charger power is greater - than 15W (met after a minute or so of charging on analog signaling) - - OR Battery state of charge is greater than 3% - - OR Charger power is greater than 27W (met after PD negotiation in - unlocked RO firmware). -1. AP firmware performs verification of the EC's RW image, upgrades it if - necessary, and sysjumps the EC to it. -1. AP firmware polls the charge state limit power flag via EC-host command for - up to 3 seconds, in 50ms intervals. The EC will return `1` (power limited) - so long as the charger power is < 27W and the battery is less than 3%. - 1. Meanwhile, the EC performs PD negotiation. Charger power lowers to 2.5W +1. EC ROM bootloader loads and jumps to the EC's read-only firmware image. +1. RO firmware negotiates a 15W state via Current Source analog signaling and + begins charging the battery with it. +1. RO firmware verifies conditions to begin booting the AP: + - Battery state of charge is greater than 1% AND charger power is greater + than 15W (met after a minute or so of charging on analog signaling) + - OR Battery state of charge is greater than 3% + - OR Charger power is greater than 27W (met after PD negotiation in + unlocked RO firmware). +1. AP firmware performs verification of the EC's RW image, upgrades it if + necessary, and sysjumps the EC to it. +1. AP firmware polls the charge state limit power flag via EC-host command for + up to 3 seconds, in 50ms intervals. The EC will return `1` (power limited) + so long as the charger power is < 27W and the battery is less than 3%. + 1. Meanwhile, the EC performs PD negotiation. Charger power lowers to 2.5W for up to 500ms as the source transitions from vSafe5V to its highest supported voltage (15V or 20V are typical). - 1. After negotiation is complete, the EC raises the charger current limit + 1. After negotiation is complete, the EC raises the charger current limit to the negotiated limit (45W is typical). - 1. The EC returns 0 (unlimited) on the next `LIMIT_POWER` request. -1. Depthcharge continues to boot Linux. - + 1. The EC returns 0 (unlimited) on the next `LIMIT_POWER` request. +1. Depthcharge continues to boot Linux. ## Configuration Option Details -### `CONFIG_CHARGER_INPUT_CURRENT` +### `CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT` Required. -The lowest current limit programmed into the charger. This determines both the -default level used on startup, and the value used during the voltage transients -in PD negotiation. +The default charger current limit used on startup and for inactive ports. It +should not be higher than 512 mA unless the device ships with a discrete power +supply. Raising this term above 512 mA is contrary to USB-PD. It may be lowered +in order to improve compatibility with marginal BC1.2 chargers. -It should not be higher than 512 mA unless the device ships with a discrete -power supply. Raising this term above 512 mA is contrary to USB-PD. It may be -lowered in order to improve compatibility with marginal BC1.2 chargers. +### `CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT` + +Optional. + +If set, charger input current limits will never be set lower than this value. +Historically most boards used the same value +as `CONFIG_CHARGER_DEFAULT_CURRENT_LIMIT`, but doing so violates USB-PD standby +power requirements when voltages greater than 5V are used with the default 512 +mA value. Configuring this option to a nonzero value may be useful if a board +needs extra headroom (possibly at the cost of drawing excess standby power), but +boards should prefer to override `board_set_charge_limit()` instead to limit +situations with excess power draw to only occur when that extra power is needed. ### `CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON` @@ -372,7 +374,7 @@ than `CHARGER_MIN_BAT_PCT_FOR_POWER_ON`, in milliwatts. ### `CONFIG_BATTERY_MEASURE_IMBALANCE` -Optional. Only set this option if one or more batteries shipped with this board +Optional. Only set this option if one or more batteries shipped with this board support per-cell battery voltage measurement. When enabled, the EC will query the attached battery for its per-cell voltages. @@ -381,15 +383,15 @@ is inhibited. #### `CONFIG_CHARGER_MIN_BAT_PCT_IMBALANCED_POWER_ON` -Default: 5%. Above this battery state of charge, cell voltage balance is +Default: 5%. Above this battery state of charge, cell voltage balance is ignored. #### `CONFIG_BATTERY_MAX_IMBALANCE_MV` -Default: 200 mV. If the difference between the highest and lowest cell exceeds +Default: 200 mV. If the difference between the highest and lowest cell exceeds this value, then the pack is considered to be imbalanced. -Note that lithium chemistry cells will almost always read similar voltages. It +Note that lithium chemistry cells will almost always read similar voltages. It is only near the top and bottom of charge that the slope of dV/dQ increases enough for small cell imbalances to be visible as a voltage difference. @@ -426,3 +428,12 @@ Similar to `CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON`, this is the minimum charger power needed to boot even when the battery is less than `CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC` +### `CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT` + +Optional, default 5%. + +This option reduces the charger's programmed current limit below the detected +current limit for a given charger in an attempt to ensure that load transients +won't overcurrent the source. Devices that require a lot of power to boot may +need to either decrease the derating factor (if behavior remains acceptable when +decreased) or increase `MIN_POWER_MW` settings to compensate. \ No newline at end of file diff --git a/docs/new_board_checklist.md b/docs/new_board_checklist.md index 22e8d25988..7fe89d4121 100644 --- a/docs/new_board_checklist.md +++ b/docs/new_board_checklist.md @@ -6,38 +6,47 @@ This document describes the high-level steps needed to create a new EC board. If you're creating a new board based on existing baseboard, you can jump straight -to the relevant link found under [Configuring EC -Features](#Configure-EC-Features) and focus on known board changes. +to the relevant link found under +[Configuring EC Features](#Configure-EC-Features) and focus on known board +changes. ## Conventions + ### Key Files + Before you get started, it's important to understand the role of a few key files in the EC codebase. -- [`include/config.h`](../include/config.h) {#config_h} - Contains the list of - top-level configuration options for the Chrome EC codebase. Each configuration - option is documented inline and is considered the authoritative definition. - -- `baseboard//` - This directory contains header files and source files - shared by all boards in a baseboard family. - - `baseboard.h` - Contains the EC configuration options shared by all - devices in the baseboard family. - - `baseboard.c` - Contains code shared by all devices in the baseboard - family. - - `build.mk` - The board family makefile specifies C source files compiled - into all boards in the baseboard family. - -- `board/` - Files in this directory are only built for a single board. - - `board.h` - EC configuration options specific to a single board. - - `board.c` - Code built only on this board. - - `build.mk` {#board_build_mk} - The board makefile defines the EC chipset family, defines the - baseboard name, and specifies the C source files that are compiled. - - `gpio.inc` - This C header file defines the interrupts, GPIOs, and - alternate function selection for all pins on the EC chipset. - - `ec.tasklist` - This C header defines the lists of tasks that are enabled - on the board. See the main EC documentation more details on [EC tasks]. +- [`include/config.h`](../include/config.h) {#config_h} - Contains the list of + top-level configuration options for the Chrome EC codebase. Each + configuration option is documented inline and is considered the + authoritative definition. + +- `baseboard//` - This directory contains header files and source files + shared by all boards in a baseboard family. + + - `baseboard.h` - Contains the EC configuration options shared by all + devices in the baseboard family. + - `baseboard.c` - Contains code shared by all devices in the baseboard + family. + - `build.mk` - The board family makefile specifies C source files compiled + into all boards in the baseboard family. + +- `board/` - Files in this directory are only built for a single board. + + - `board.h` - EC configuration options specific to a single board. + - `board.c` - Code built only on this board. + - `build.mk` {#board_build_mk} - The board makefile defines the EC chipset + family, defines the baseboard name, and specifies the C source files + that are compiled. + - `gpio.inc` - This C header file defines the interrupts, GPIOs, and + alternate function selection for all pins on the EC chipset. + - `ec.tasklist` - This C header defines the lists of tasks that are + enabled on the board. See the main EC documentation more details on + [EC tasks]. ### GPIO Naming + Many drivers and libraries in the common EC code rely on board variants defining an exact GPIO signal name. Examples include the `GPIO_LID_OPEN`, `GPIO_ENTERING_RW`, and `GPIO_SYS_RESET_L` signals. The net names in schematics @@ -46,7 +55,7 @@ all the `GPIO_INT()`, `GPIO()`, `ALTERNATE()`, and `UNIMPLEMENTED()` definitions in `gpio.inc` use the schematic net name. You then create `#define` macros in `board.h` to map the net names to the EC common names. -Below is an example configuration for the SYS_RESET_L signal. The schematic net +Below is an example configuration for the SYS_RESET_L signal. The schematic net name of this signal is EC_RST_ODL and the signal connects to the EC chipset pin GPIO02. @@ -63,6 +72,7 @@ Please see the [GPIO](./configuration/gpio.md) documentation for additional details on the GPIO macros. ## How to use this document + Each of the following sections details a single feature set that may need to be modified or configured for your new board. The feature sets are organized so they can be implemented with a reasonably sized change list, and can be worked @@ -70,34 +80,31 @@ on independently. Each configuration feature document includes the following sub-tasks: -- **Config Options** - This section details the `CONFIG_*` options relevant to - the feature. Use the documentation found in [config.h] to determine whether - each option should be enabled (using #define) or disabled (using #undef) in - the relevant `baseboard.h` or `board.h` file. -- **Feature Parameters** - This section details parameters that control the - operation of the feature. Similar to the config options, feature parameters - are defined in [config.h] and prefixed with `CONFIG_*`. However, feature - parameters are assigned a default value, which can be overridden in by - `baseboard.h` or `board.h` using an `#undef/#define` pair. - ```c - #undef CONFIG_UART_TX_BUF_SIZE - #define CONFIG_UART_TX_BUF_SIZE 4096 - ``` -- **GPIOs and Alternate Pins** - This section details signals and pins relevant - to the feature. Add the required `GPIO_INT()`, `GPIO()`, `ALTERNATE()`, and - `UNIMPLEMENTED()` definitions to `gpio.inc`, making sure to follow the [GPIO - naming conventions]. -- **Data Structures** - This section details the data structures required to - configure the feature for correct operation. Add the data structures to - `baseboard.c` or `board.c`. Note that most data structures required by the - common EC code should be declared `const` to save on RAM usage. -- **Tasks** - This section details the tasks that the EC feature requires for - operation. -- **Testing and Debugging** - This section details strategies for testing the EC - feature set and for debugging issues. This section also documents EC console - commands related to the feature set. -- **Example** - When present, this section walks through a complete example for - configuring an EC feature based on an existing board implementation. +- **Config Options** - This section details the `CONFIG_*` options relevant to + the feature. Use the documentation found in [config.h] to determine whether + each option should be enabled (using #define) or disabled (using #undef) in + the relevant `baseboard.h` or `board.h` file. +- **Feature Parameters** - This section details parameters that control the + operation of the feature. Similar to the config options, feature parameters + are defined in [config.h] and prefixed with `CONFIG_*`. However, feature + parameters are assigned a default value, which can be overridden in by + `baseboard.h` or `board.h` using an `#undef/#define` pair. `c #undef + CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096` +- **GPIOs and Alternate Pins** - This section details signals and pins + relevant to the feature. Add the required `GPIO_INT()`, `GPIO()`, + `ALTERNATE()`, and `UNIMPLEMENTED()` definitions to `gpio.inc`, making sure + to follow the [GPIO naming conventions]. +- **Data Structures** - This section details the data structures required to + configure the feature for correct operation. Add the data structures to + `baseboard.c` or `board.c`. Note that most data structures required by the + common EC code should be declared `const` to save on RAM usage. +- **Tasks** - This section details the tasks that the EC feature requires for + operation. +- **Testing and Debugging** - This section details strategies for testing the + EC feature set and for debugging issues. This section also documents EC + console commands related to the feature set. +- **Example** - When present, this section walks through a complete example + for configuring an EC feature based on an existing board implementation. ## Create the new EC board @@ -113,8 +120,8 @@ are found in the corresponding [README.md] documentation. The [new_variant.py] script also verifies the new EC board compiles and prepares a changelist to upload to Gerrit. You should upload this changelist unmodified -for review and submission (you may need to run `make buildall -k` to satisfy -the EC pre-submit tests). +for review and submission (you may need to run `make buildall -k` to satisfy the +EC pre-submit tests). The next step is to review the following sections to make any needed modifications to your new board files, test the changes, and upload the changes @@ -128,8 +135,8 @@ populate these directories with the minimum set of files required compile the EC board. The initial changelists for the Hatch and Volteer reference boards provide good examples for how to start. - * [Volteer EC skeleton build] - * [Hatch EC skeleton build] +* [Volteer EC skeleton build] +* [Hatch EC skeleton build] After submitting the skeleton builds, review the following sections and add each feature set as required by your design. @@ -143,30 +150,30 @@ priority and should be ready before the first prototypes arrive. Use the documentation link for details about the code changes required to implement each feature. -| EC Feature | Needed for Power On | -| :--------- | ------------------: | -| [Configure EC Chipset](./configuration/ec_chipset.md) | yes | -| [Configure AP to EC Communication](./configuration/config_ap_to_ec_comm.md) | yes | -| [Configure AP Power Sequencing](./configuration/ap_power_sequencing.md) | yes | -| [Configure USB-C](./usb-c.md) | yes | -| [Configure Charger (TODO)](./configuration/template.md) | yes | -| [Configure I2C Buses](./configuration/i2c.md) | no | -| [Configure CrOS Board Information (CBI)](./configuration/cbi.md) | no | -| [Configure Keyboard](./configuration/keyboard.md) | no | -| [Configure LEDs](./configuration/leds.md) | no | -| [Configure Motion Sensors (TODO)](./configuration/motion_sensors.md) | no | -| [Configure BC1.2 Charger Detector (TODO)](./configuration/template.md) | no | -| [Configure Battery (TODO)](./configuration/template.md) | no | +EC Feature | Needed for Power On +:-------------------------------------------------------------------------- | ------------------: +[Configure EC Chipset](./configuration/ec_chipset.md) | yes +[Configure AP to EC Communication](./configuration/config_ap_to_ec_comm.md) | yes +[Configure AP Power Sequencing](./configuration/ap_power_sequencing.md) | yes +[Configure USB-C](./usb-c.md) | yes +[Configure Charger (TODO)](./configuration/template.md) | yes +[Configure I2C Buses](./configuration/i2c.md) | no +[Configure CrOS Board Information (CBI)](./configuration/cbi.md) | no +[Configure Keyboard](./configuration/keyboard.md) | no +[Configure LEDs](./configuration/leds.md) | no +[Configure Motion Sensors (TODO)](./configuration/motion_sensors.md) | no +[Configure BC1.2 Charger Detector (TODO)](./configuration/template.md) | no +[Configure Battery (TODO)](./configuration/template.md) | no After finishing the changes required for all EC features, it is recommended that you make one final pass over all the GPIOs and pin assignments used on your board. Refer to the [GPIO](./configuration/gpio.md) documentation for details. -[README.md]:https://chromium.googlesource.com/chromiumos/platform/dev-util/+/master/contrib/variant/README.md -[new_variant.py]:https://chromium.googlesource.com/chromiumos/platform/dev-util/+/master/contrib/variant/new_variant.py -[create_initial_ec_image.sh]:https://chromium.googlesource.com/chromiumos/platform/dev-util/+/master/contrib/variant/create_initial_ec_image.sh +[README.md]:https://chromium.googlesource.com/chromiumos/platform/dev-util/+/HEAD/contrib/variant/README.md +[new_variant.py]:https://chromium.googlesource.com/chromiumos/platform/dev-util/+/HEAD/contrib/variant/new_variant.py +[create_initial_ec_image.sh]:https://chromium.googlesource.com/chromiumos/platform/dev-util/+/HEAD/contrib/variant/create_initial_ec_image.sh [Volteer EC skeleton build]:https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1758532 [Hatch EC skeleton build]:https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1377569/ [config.h]: ./new_board_checklist.md#config_h [EC tasks]: ../README.md#Tasks -[GPIO naming conventions]: ./new_board_checklist.md#GPIO-Naming \ No newline at end of file +[GPIO naming conventions]: ./new_board_checklist.md#GPIO-Naming diff --git a/docs/pupr.md b/docs/pupr.md new file mode 100644 index 0000000000..cf97f4e381 --- /dev/null +++ b/docs/pupr.md @@ -0,0 +1,24 @@ +# Parallel Uprevs for platform/ec + +## Overview + +Since the platform/ec repo doesn't use the normal ebuild based CQ some of the +ebuild files don't use the normal automatic uprev. Instead the go/pupr tool +creates new CLs to uprev the chromeos-base/ec-utils and send them through the +slow CQ running all the ebuilds that depend on it. + +## Reviewer responsibilities + +For the most part you can ignore these CLs. You don't need to add CR+2 nor CQ+2. +However if you see that the CL has failed the CQ several times, you should +check and see if there is a real bug that is preventing the CL from submitting. + +If there is a pupr cl that is known bad, i.e. there is a breakage in the code +and pupr needs to pick a different cl, then please Abandon that cl, don't +CR-2 it. Pupr will keep adding CQ+2 to the cl over and over again until it +submits, even if it never will. + +## Failure implications + +If the CL fails to merge, then the ectool binary will not be built with the +latest code. diff --git a/docs/reducing_ec_image_size.md b/docs/reducing_ec_image_size.md new file mode 100644 index 0000000000..96c1a9eac9 --- /dev/null +++ b/docs/reducing_ec_image_size.md @@ -0,0 +1,467 @@ +# Reducing the EC image size + +The EC ToT codebase continues grows as new features are added and for bug fixes. +This puts pressure on older boards that have limited flash space remaining. This +document provides some tips for reducing the EC image size. + +[TOC] + +## Checking the EC image footprint + +The EC codebase supports two build types: + +1. `cros-ec` builds are the legacy EC images built using Make (e.g. `make + BOARD=volteer`) +1. `zephyr-ec` builds are the EC images built using the Zephyr RTOS kernel + using zmake/Cmake (e.g. `zmake build herobrine`) + +### Checking a single cros-ec build + +Building a single cros-ec board using `make BOARD= -j` reports the the +number of bytes free in flash and RAM for both the RO and RW images. An example +from building the juniper board is shown below. + +``` +$ make BOARD=juniper -j + ... + *** 668 bytes in flash and 10308 bytes in RAM still available on juniper RO **** + *** 3224 bytes in flash and 7460 bytes in RAM still available on juniper RW **** +``` + +### Checking all cros-ec builds + +Running `make buildall -j` shows a summary of the three boards with the smallest +RO flash footprint, FW flash footprint, and RW RAM footprint. + +``` +$ make buildall -j + ... +buildall completed successfully! +Smallest free spaces in RO flash (bytes): +servo_v4 : 104 +scarlet : 108 +mushu : 160 +Smallest free spaces in RW flash (bytes): +mushu : 96 +bobba : 232 +trondo : 376 +Tightest boards' RW RAM images, bytes free: +whiskers : 244 +minimuffin: 284 +zinger : 284 +``` + +### Comparing cros-ec image sizes + +The cros-ec makefile provides two make targets for helping track the impact of +code changes. + +`make savesizes` saves the EC footprint information for all boards, providing +the baseline for comparison. `make newsizes` compares the sizes of the current +build against the EC footprint information saved by most recent invocation of +`make savesizes`. + +General workflow: + +1. Checkout branch you need to compare against. For example `repo start + check-ec-size -r cros/main` or `repo start check-ec-size -r `. +1. Run `make buildall -j`. +1. Run `make savesizes`. +1. Apply your code change (e.g. change the local branch, cherry-pick your + changes, or directly edit source files). +1. Run `make buildall -j` again. +1. Run `make newsizes` to generate report of size changes. + +Example report from `make newsizes` shown below: + +``` +$ make newsizes +build/burnet/RO/space_free_flash grew by 576 bytes: (488 to 1064) +build/burnet/RW/space_free_flash grew by 552 bytes: (1324 to 1876) +build/cerise/RO/space_free_flash grew by 512 bytes: (276 to 788) +build/cerise/RW/space_free_flash grew by 548 bytes: (7076 to 7624) + ... +``` + +### Checking a single zephyr-ec build + +By default, `zmake` will display the flash and SRAM usage of the board. + +``` +$ zmake build herobrine + ... +Building herobrine:ro: /usr/bin/ninja -C /mnt/host/source/src/platform/ec/build/zephyr/herobrine/build-ro +-- git describe warned: warning: tag 'upstream/v2.7.99' is externally known as 'v2.7.99' +-- Zephyr version: 3.0.99 (/mnt/host/source/src/third_party/zephyr/main), build: v2.7.99-5035-ga17c05c7228e +Memory region Used Size Region Size %age Used + FLASH: 219920 B 256 KB 83.89% + SRAM: 49688 B 64 KB 75.82% + IDT_LIST: 0 GB 2 KB 0.00% +Building herobrine:rw: /usr/bin/ninja -C /mnt/host/source/src/platform/ec/build/zephyr/herobrine/build-rw +-- git describe warned: warning: tag 'upstream/v2.7.99' is externally known as 'v2.7.99' +-- Zephyr version: 3.0.99 (/mnt/host/source/src/third_party/zephyr/main), build: v2.7.99-5035-ga17c05c7228e +Memory region Used Size Region Size %age Used + FLASH: 219920 B 256 KB 83.89% + SRAM: 49688 B 64 KB 75.82% + IDT_LIST: 0 GB 2 KB 0.00% +``` + +Note, that the flash region size listed above represents the total flash +available on the EC. The actual available region size is only half the reported +value in order to store two images (RO+RW). + +#### Other Zephyr utilities + +The Cmake system utilized by Zephyr provides two build targets `rom_report` and +`ram_report` which generate a list of all the compiled objects in tabular form. +This can be useful for identifying particular modules that contribute to the +image size. + +The `rom_report` and `ram_report` targets are currently only supported when +working outside the chroot. Follow the [instructions][1] for building zephyr-ec +images outside chroot before running the commands below. + +``` +# Configure the Herobrine zephyr project, storing the build files in /tmp/zephyr-herobrine +$ zmake configure -B /tmp/zephyr-herobrine herobrine + +# Build the RO image +$ ninja -C /tmp/zephyr-herobrine/herobrine/build-ro + +# Generate the ROM report, report sent to stdout +$ ninja -C /tmp/zephyr-herobrine/herobrine/build-ro rom_report +``` + +Please refer to the [Zephyr Optimization Tools][3] documentation for details on +the `rom_report` and `ram_report` targets. + +## Checking a board's config + +If you want to see what configs are enabled for a given board, use the +`print-configs` `Makefile` target: + +```shell +$ make BOARD= print-configs +``` + +You can also open the `./build//.config` file that is generated after +building the board with `make BOARD=`. + +## Disable console commands + +The lowest hanging fruit for reducing the EC image size is by disabling console +commands that provide debug information only and don't impact the user or the +automated testing. Any console command that is not used by the FAFT tests and +suites is safe to disable in the EC images. + +For cros-ec builds, add `#undef CONFIG_CMD_` to the board.h or baseboard.h +file to disable the console command. + +For zephyr-ec builds, add `CONFIG_PLATFORM_EC_CONSOLE_CMD_=n` to the board +prj.conf file to disable the console command. + +* TODO: Create new CONFIG/Kconfig option that disables all console commands + not required by FAFT. + + + +| Used by FAFT | config.h option | Console commands | Notes | +|:---|:---|:---|:---| +| | CONFIG_CMD_ACCELS | `accelrange`
`accelres`
`accelrate`
`accelread`
`accelinit`
`accelinfo` | | +| | CONFIG_CMD_ACCELSPOOF | `accelspoof` | | +| | CONFIG_CMD_ACCEL_FIFO | `fiforead` | | +| | CONFIG_CMD_ACCEL_INFO | `accelinfo` | | +| | CONFIG_CMD_ADC | `adc` | Note firmware_ECAdc uses the `temps` command. | +| | CONFIG_CMD_ALS | `als` | | +| | CONFIG_CMD_APTHROTTLE | `apthrottle` | | +| | CONFIG_CMD_AP_RESET_LOG |??? | | +| | CONFIG_CMD_BATDEBUG | `fgunseal`
`fgseal`
`fginit`
`fgprobe`
`fgrd`
`fgcmd`
`fcmdrd` | | +| | CONFIG_CMD_BATTFAKE | `battfake` | | +| | CONFIG_CMD_BATT_MFG_ACCESS | `battmfgacc` | | +| | CONFIG_CMD_CBI | `cbi` | firmwareECCbiEeprom uses `ectool` on AP to test CBI | +| x | CONFIG_CMD_CHARGEN | `chargen` | Used by firmware_Cr50CCDUartStress, included in faft_ccd, faft_cr50_prepvt, and faft_cr50_pvt suites | +| | CONFIG_CMD_CHARGER | `bd9995x`
`sy21612` | | +| | CONFIG_CMD_CHARGER_ADC_AMON_BMON | `amonbmon` | | +| | CONFIG_CMD_CHARGER_DUMP | `charger_dump` | | +| | CONFIG_CMD_CHARGER_PROFILE_OVERRIDE | `fastcharge` | | +| | CONFIG_CMD_CHARGER_PROFILE_OVERRIDE_TEST | `fastchgtest` | | +| | CONFIG_CMD_CHARGE_SUPPLIER_INFO | `chgsup` | | +| | CONFIG_CMD_CHGRAMP | `chgramp` | | +| | CONFIG_CMD_CLOCKGATES | `clockgates` | | +| | CONFIG_CMD_COMXTEST | `comxtest` | | +| x | CONFIG_CMD_CRASH | `crash` | Used by TAST `crash.ECCrash`, FAFT `firmware_ECSharedMem` | +| | CONFIG_CMD_DEVICE_EVENT | `deviceevent` | | +| | CONFIG_CMD_DLOG | `dlog` | | +| | CONFIG_CMD_ECTEMP | `ectemp` | | +| | CONFIG_CMD_FASTCHARGE | `fastcharge` | Obsolete? use CONFIG_CMD_CHARGER_PROFILE_OVERRIDE? | +| | CONFIG_CMD_FLASH | `flasherase`
`flashwrite`
`flashread` | | +| x | CONFIG_CMD_FLASHINFO | `flashinfo` | Used by TAST `firmware.ECSize` | +| | CONFIG_CMD_FLASH_TRISTATE | `fpcapture`
`flash_tristate` | | +| | CONFIG_CMD_FLASH_WP | `flashwp` | | +| | CONFIG_CMD_FORCETIME | `forcetime` | | +| | CONFIG_CMD_FPSENSOR_DEBUG | `fpcapture`
`fpenroll`
`fpmatch`
`fpclear`
`fpmaintenance` | | +| | CONFIG_CMD_GETTIME | `gettime` | Used by Cr50 tests, not by FAFT EC | +| | CONFIG_CMD_GL3590 | `gl3590` | | +| | CONFIG_CMD_GPIO_EXTENDED | Adds options to `gpioget` and `gpioset`. | Should be renamed to CONFIG_GPOI_EXTENDED | +| | CONFIG_CMD_GPIO_POWER_DOWN | Not a valid config. | Should be CONFIG_GPIO_POWER_DOWN | +| | CONFIG_CMD_GT7288 | `gt7288_desc`
`gt7288_repdesc`
`gt7288_ver`
`gt7288_report` | | +| | CONFIG_CMD_HASH | `hash` | firmware_ECHash uses `ectool echash` | +| x | CONFIG_CMD_HCDEBUG | `hcdebug` | firmware_ECBootTime.py | +| x | CONFIG_CMD_HOSTCMD | `hostcmd` | | +| | CONFIG_CMD_I2CWEDGE | `i2cwedge`
`i2cunwedge` | | +| | CONFIG_CMD_I2C_PROTECT | `i2cprotect` | | +| | CONFIG_CMD_I2C_SCAN | `i2cscan` | | +| | CONFIG_CMD_I2C_STRESS_TEST | `i2ctest` | | +| | CONFIG_CMD_I2C_STRESS_TEST_ACCEL | Not a console command | | +| | CONFIG_CMD_I2C_STRESS_TEST_ALS | Not a console command | | +| | CONFIG_CMD_I2C_STRESS_TEST_BATTERY | Not a console command | | +| | CONFIG_CMD_I2C_STRESS_TEST_CHARGER | Not a console command | | +| | CONFIG_CMD_I2C_STRESS_TEST_TCPC | `Not a console command | | +| | CONFIG_CMD_I2C_XFER | `i2cxfer` | firmware_ECCbiEeprom uses `ectool i2cxfer` which is not guarded by CONFIG_CMD_I2C_XFER | +| | CONFIG_CMD_I2C_XFER_RAW | | Adds options to `i2cxfer` | +| | CONFIG_CMD_IDLE_STATS | `idlestats` | | +| | CONFIG_CMD_INA | `ina` | | +| | CONFIG_CMD_JUMPTAGS | `jumptags` | | +| x | CONFIG_CMD_KEYBOARD | `8042`
`ksstate`
`kbpress` | Used by `firmware_ECKeyboard` | +| | CONFIG_CMD_LEDTEST | `ledtest` | | +| | CONFIG_CMD_MCDP | `mcdp` | | +| | CONFIG_CMD_MD | `md` | | +| | CONFIG_CMD_MEM | | Not a console command - gates `md` and `rw` | +| | CONFIG_CMD_MFALLOW | `mfallow` | | +| | CONFIG_CMD_MMAPINFO | `mmapinfo` | | +| x | CONFIG_CMD_PD | `pd` | Used by FAFT PD, TAST `firmware.ECSystemLocked` | +| | CONFIG_CMD_PD_DEV_DUMP_INFO | | Not supported by TCPMv2 | +| | CONFIG_CMD_PD_FLASH | `pd flash` | Not supported by TCPMv2 | +| | CONFIG_CMD_PD_SRCCAPS_REDUCED_SIZE | `pd srccaps` | Defining this reduces the verbosity of this command, saving bytes | +| | CONFIG_CMD_PECI | `peci` | firmware_ECThermal uses `ectool tempsinfo` | +| | CONFIG_CMD_PLL | `pll` | only used by lm4 chip | +| | CONFIG_CMD_POWERINDEBUG | `powerindebug` | | +| | CONFIG_CMD_POWERLED | `powerled` | | +| x | CONFIG_CMD_POWER_AP | `apreset`
`apshutdown` | Used by power_Monitoring.py | +| | CONFIG_CMD_PPC_DUMP | `ppc_dump` | | +| | CONFIG_CMD_PS2 | `ps2ench`
`ps2write` | Used only on NPCX | +| | CONFIG_CMD_PWR_AVG | `pwr_avg` | | +| | CONFIG_CMD_RAND | `rand` | Used only on STM32 | +| | CONFIG_CMD_REGULATOR | `ir357x` | | +| | CONFIG_CMD_RESET_FLAGS | `rflags` | | +| | CONFIG_CMD_RETIMER | `retimer` | | +| | CONFIG_CMD_RTC | `rtc` | | +| | CONFIG_CMD_RTC_ALARM | `rtc_alarm` | | +| | CONFIG_CMD_RW | `rw` | | +| | CONFIG_CMD_SCRATCHPAD | `scratchpad` | | +| | CONFIG_CMD_SEVEN_SEG_DISPLAY | `seg` | | +| | CONFIG_CMD_SHA256_TEST | `???` | | +| x | CONFIG_CMD_SHMEM | `shmem` | Used by firmware_ECSharedMem | +| | CONFIG_CMD_SLEEP | `sleep` | used only lm4 | +| | CONFIG_CMD_SLEEPMASK | `sleepmask` | Only used for Cr50 tests | +| | CONFIG_CMD_SLEEPMASK_SET | | Adds options to `sleepmask` | +| | CONFIG_CMD_SPI_FLASH | `spi_flasherase`
`spi_flashwrite`
`spi_flashread`
`spi_flash_rsr`
`spi_flash_wsr`
`spi_flash_wsr` | | +| | CONFIG_CMD_SPI_NOR | `spinorinfo`
`spinorerase`
`spinorwrite`
`spinorread` | | +| | CONFIG_CMD_SPI_XFER | `spixfer` | | +| x | CONFIG_CMD_SYSINFO | `sysinfo` | Used by firmware_ECSystemLocked | +| x | CONFIG_CMD_SYSJUMP | `sysjump` | Used by firmware_ECSharedMem | +| | CONFIG_CMD_SYSLOCK | `syslock` | | +| | CONFIG_CMD_TASKREADY | `taskready` | | +| | CONFIG_CMD_TASK_RESET | `taskreset` | | +| | CONFIG_CMD_TCPC_DUMP | `tcpci_dump` | | +| x | CONFIG_CMD_TEMP_SENSOR | `temps` | | +| | CONFIG_CMD_TIMERINFO | `timerinfo` | | +| | CONFIG_CMD_TYPEC | `typec` | | +| | CONFIG_CMD_USART_INFO | `usart_info` | | +| | CONFIG_CMD_USB_PD_CABLE | `pdcable` | | +| x | CONFIG_CMD_USB_PD_PE | `pe` | Doesn't appear to be used but might be by FAFT PD | +| x | CONFIG_CMD_WAITMS | `waitms` | firmware_ECWatchdog | | + + + +## Reduce or eliminate USB-C debugging + +The TCPM (Type-C Port manager) implementation is one of the more complex modules +implemented by the EC code. This module includes extensive debugging and is +enabled by default due to the value provided during both board bringup and on +production systems. + +The TCPM provides the following debug levels: + +* `DEBUG_DISABLE` (0) - Debugging disabled, no runtime messages displayed +* `DEBUG_LEVEL_1` (1) - Displays all the state transitions for the TC (Type-C) + and PE (Policy Engine) state machines +* `DEBUG_LEVEL_2` (2) - Displays the raw contents of received PD (Power + Delivery) packets, excluding PING packets +* `DEBUG_LEVEL_3` (3) - Enables debug messages in the PRL Also displays + received PING packets. + +When `CONFIG_USB_PD_DEBUG_LEVEL` is undefined, the EC allows runtime +configuration of the USB-C debug level using the `pd dump ` EC console +command. In this configuration, the strings from all debug levels are included +in the image. + +Enabling a fixed debug level removes runtime control of the debug level and also +removes the strings for the higher debug levels. + +For cros-ec builds, add the following to your board.h/baseboard.h file: + +```c + #define CONFIG_USB_PD_DEBUG_LEVEL +``` + +For zephyr-ec builds, add the following to your prj.conf file: + +``` + CONFIG_PLATFORM_EC_USB_PD_DEBUG_FIXED_LEVEL=y + CONFIG_PLATFORM_EC_USB_PD_DEBUG_LEVEL= +``` + +Approximate flash space savings from each fixed level setting: + +Fixed Debug Level | Relative Saving | Cumulative Saving +----------------- | --------------- | ----------------- +Disabled | 0 | 0 +3 | 100 bytes | 100 bytes +2 | 500-600 bytes | 600-700 bytes +1 | 100 bytes | 700-800 bytes +0 | 2000 bytes | 2700-2800 bytes + +The recommended setting is setting the fixed debug level to `DEBUG_LEVEL_2` (2). +This adds details about received PD packets in the EC log stored by the kernel +and can help troubleshoot PD issues when a PD analyzer isn't available. + +It is not recommended to set the fixed debug level to `DEBUG_DISABLE` (0) on any +shipping firmware. + +### TCPMv1 Configuration + +Many older platforms still use the legacy TCPMv1 (`CONFIG_USB_PD_TCPMV1`) +implementation. Specific to TCPMv1, the PD protocol state names can be removed +from the debug output by adding the following to the board.h/baseboard.h file. + +```c +#undef CONFIG_USB_PD_TCPMV1_DEBUG +``` + +This saves around 900 bytes of flash space. TCPMv2 does not currently provide an +equivalent configuration option, so there is also no Kconfig equivalent. + +## Other optional features + +### ASSERT() Calls + +By default, `ASSERT()` calls generate a console message of the following form: + +``` + ASSERTION FAILURE '' in function() at file:line +``` + +There are two options available that reduce the size of strings stored with the +`ASSERT()` calls. + + + +Description | cros-ec setting | zephyr-ec setting | Total Savings +:--- | :--- | :--- | :--- +Display only file and line number | `#define CONFIG_DEBUG_ASSERT_BRIEF` | `CONFIG_PLATFORM_EC_DEBUG_ASSERT_BRIEF=y` | 2000-2500 bytes +Disable all debug from ASSERT() calls.
EC is reset using a software breakpoint. | `#undef CONFIG_DEBUG_ASSERT_REBOOTS` | `CONFIG_PLATFORM_EC_DEBUG_ASSERT_REBOOTS=n`
`CONFIG_PLATFORM_EC_DEBUG_ASSERT_BREAKPOINT=y` | 3000-4000 bytes + + + +It is not recommended to disable `CONFIG_PLATFORM_EC_DEBUG_ASSERT_REBOOTS` on +shipping firmware. + +### Disable console help and history + +The help strings can be removed from the final build, saving about 5000 bytes of +flash space. The history command can also be disabled to save another 200 bytes +of flash space. + +For cros-ec builds, add `#undef CONFIG_CONSOLE_CMDHELP` and `#undef +CONFIG_CONSOLE_HISTORY` to the board.h/baseboard.h file. + +zephyr-ec builds use Zephyr's shell subsystem and by default enable the +`CONFIG_SHELL_MINIMAL` option. This option already disables shell help along +with many other non-critical features. Refer to the shell subsystem [Kconfig][2] +source file for the complete list of shell features than can be configured. + +### Link time optimizaiton + +Link time optimization (LTO) is a feature of the linker to identify and remove +unused code. + +For cros-ec builds, LTO is enabled by adding this to the board.h/baseboard.h +file. + +```c +#define CONFIG_LTO +``` + +For zephyr-ec builds, LTO is enabled by default and is controlled with Kconfig. + +``` +CONFIG_LTO=y +``` + +Note that for zephyr-ec builds, LTO is only turned on for the source files found +under `platform/ec`. The upstream Zephyr code does not currently support LTO due +to some auto-generated code that breaks the assumptions made by the linker. This +[Github issue][4] tracks the effort to support LTO in the Zephyr kernel. + +### CONFIG_CHIP_INIT_ROM_REGION + +The config option `CONFIG_CHIP_INIT_ROM_REGION` creates a new linker section to +store data that remains resident in ROM/flash at runtime. This reduces the +effective cros-ec image size by identifying data structures that do not need to +be copied into the code RAM section at startup. + +This option has the following requirements: + +1. EC executes code from RAM +2. The ROM/flash size is larger than 2 times the code RAM size. +3. The RO code released for the board includes this + [change](https://crrev.com/c/2428566). + +The only EC chip that matches these prerequisites is the Nuvoton NPCX7. + +Due to the RO code requirement, take care before enabling this option for boards +released prior to 2021. + +If the above requirements are meant, add the following to the +board.h/baseboard.h file: + +```c +#define CONFIG_CHIP_INIT_ROM_REGION +#define CONFIG_CHIP_DATA_IN_INIT_ROM +``` + +These options are not supported for zephyr-ec builds. + +### Enable short GPIO names + +The [GPIO macros](./configuration/gpio.md) defined by the board get stored as +descriptive strings for use with the `gpioget` and `gpioset` console commands. + +The names of the GPIOs can be shorted by enabling the +`CONFIG_COMMON_GPIO_SHORTNAMES` option. + +For example, the Kukui board defines this GPIO: + +```c +GPIO(PMIC_FORCE_RESET_ODL, PIN(A, 2), GPIO_ODR_HIGH) +``` + +Normally, the GPIO name is stored exactly as specified by the macro: +`PMIC_FORCE_RESET_ODL`. However, when `CONFIG_COMMON_GPIO_SHORTNAMES` is +defined, then the GPIO name is shortened to only include port and pin number: +`A2`. + +This option is currently only supported by the STM32 chip and it is not +supported by zephyr-ec builds. + +Note that there are some [FAFT tests][5] that rely on the GPIO name. If you +enable this option, you may also need to change firmware testing configuration +[file][6]. + +[1]:./zephyr/zephyr_build.md#Working-outside-the-chroot +[2]:https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/shell/Kconfig +[3]:https://docs.zephyrproject.org/latest/guides/optimizations/tools.html +[4]:https://github.com/zephyrproject-rtos/zephyr/issues/2112 +[5]:https://chromium.googlesource.com/chromiumos/third_party/autotest/+/069cb4b0/server/site_tests/firmware_ECUsbPorts/firmware_ECUsbPorts.py#81 +[6]:https://chromium.googlesource.com/chromiumos/platform/fw-testing-configs/+/e2e9547e/volteer.json#26 diff --git a/docs/schematics/dragonclaw/README.md b/docs/schematics/dragonclaw/README.md index 66fde41df8..82a2fa2681 100644 --- a/docs/schematics/dragonclaw/README.md +++ b/docs/schematics/dragonclaw/README.md @@ -6,5 +6,5 @@ Note that you'll need to download and save the HTML file from The layout file is in the [`.brd`] file. -[`.brd`]: https://raw.githubusercontent.com/coreboot/chrome-ec/master/docs/schematics/dragonclaw/dragonclaw_v0.2.brd -[schematic]: https://raw.githubusercontent.com/coreboot/chrome-ec/master/docs/schematics/dragonclaw/dragonclaw_v0.2.html +[`.brd`]: https://raw.githubusercontent.com/coreboot/chrome-ec/HEAD/docs/schematics/dragonclaw/dragonclaw_v0.2.brd +[schematic]: https://raw.githubusercontent.com/coreboot/chrome-ec/HEAD/docs/schematics/dragonclaw/dragonclaw_v0.2.html diff --git a/docs/sitemap.md b/docs/sitemap.md index 38049c1b7d..1d9b2b3cb4 100644 --- a/docs/sitemap.md +++ b/docs/sitemap.md @@ -25,16 +25,20 @@ * [Fingerprint MCU (FPMCU)](./fingerprint/fingerprint.md) * [FPMCU Development for Partners](./fingerprint/fingerprint-dev-for-partners.md) +* [FPMCU Firmware Testing for Partners](./fingerprint/fingerprint-firmware-testing-for-partners.md) * [FPMCU Debugging](./fingerprint/fingerprint-debugging.md) * [Fingerprint Authentication Design Doc](./fingerprint/fingerprint-authentication-design-doc.md) * [Fingerprint Factory Requirements](./fingerprint/fingerprint-factory-requirements.md) * [Fingerprint Quick Factory Guide](./fingerprint/fingerprint-factory-quick-guide.md) * [Dragonclaw Schematics and Layout](./schematics/dragonclaw) +* [Fingerprint MCU RAM and Flash](./fingerprint/fingerprint-ram-and-flash.md) ## Testing * [Unit Tests](./unit_tests.md) + * [Zephyr Testing](./zephyr/ztest.md) * [Code Coverage](./code_coverage.md) +* [ChromeOS EC Firmware Test Requirements](./chromeos-ec-firmware-test-requirements.md) ## Updaters @@ -55,13 +59,25 @@ * [EC-3PO overview](./ec-3po.md) * [EC-3PO design doc](./ec-3po-design.md) +## Zephyr + +* [Zephyr New Board Checklist](./zephyr/zephyr_new_board_checklist.md) +* [Building Zephyr OS](./zephyr/zephyr_build.md) +* [Initialization Order](./zephyr/zephyr_init.md) +* [Proof-of-Concept-Device Bringup](./zephyr/zephyr_poc_device_bringup.md) +* [Shimming](./zephyr/zephyr_shim.md) +* [Zephyr Testing](./zephyr/ztest.md) + ## Miscellaneous * [Low Battery Startup](./low_battery_startup.md) * [I2C tracing via console commands](./i2c-debugging.md) * [Application Processor to EC communication](./ap-ec-comm.md) +* [Reducing EC Image Size](./reducing_ec_image_size.md) * [Code Reviews](./code_reviews.md) * [IDE Support](./ide-support.md) +* [Building with Goma (Googlers only)](./goma.md) +* [Parallel Uprevs for ebuilds](./pupr.md) [1]:https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging.md [2]:https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md diff --git a/docs/unit_tests.md b/docs/unit_tests.md index 952d16b733..29311ac346 100644 --- a/docs/unit_tests.md +++ b/docs/unit_tests.md @@ -26,12 +26,41 @@ Build and run all unit tests: (chroot) ~/trunk/src/platform/ec $ make runhosttests -j ``` +## Debugging Unit Tests + +You need the host version of gdb: + +```bash +(chroot) sudo emerge -j sys-devel/gdb +``` + +Then run gdb on the specific test you want to debug (the `host_command` test in this example): + +``` +(chroot) gdb build/host/host_command/host_command.exe +handle SIGUSR1 noprint nostop +break test_hostcmd_ok +run +``` + ## Writing Unit Tests Unit tests live in the [`test`] subdirectory of the CrOS EC codebase. -Test-related macros (e.g., `TEST_EQ`, `TEST_NE`) and functions are defined in -[`test_util.h`]. +All new unit tests should be written to use the Zephyr Ztest +[API](https://docs.zephyrproject.org/latest/guides/test/ztest.html). If you are +making significant changes to an existing test, you should also look at porting +the test from the EC test API to the Ztest API. + +Using the Ztest API makes the unit tests suitable for submitting upstream to the +Zephyr project, and reduces the porting work when the EC transitions to the +Zephyr RTOS. + +### File headers + +Include [`test_util.h`] and any other required includes. In this example, the +function being tested is defined in the test, but a real unit test would include +the header file for the module that defines `some_function`. `test/my_test.c`: @@ -43,9 +72,35 @@ static bool some_function(void) { return true; } +``` + +[`test_util.h`] includes `ztest.h` if `CONFIG_ZEPHYR` is defined, or defines a +mapping from the `zassert` macros to the EC `TEST_ASSERT` macros if +`CONFIG_ZEPHYR` is not defined. + +### Test cases +Define the test cases. Use the `EC_TEST_RETURN` return type on these functions. + +```c /* Write a function with the following signature: */ -test_static int test_my_function(void) +test_static EC_TEST_RETURN test_my_function(void) +{ + /* Run some code */ + bool condition = some_function(); + + /* Check that the expected condition is correct. */ + zassert_true(condition); + + return EC_SUCCESS; +} +``` + +`test/my_test.c`: + +```c +/* Write a function with the following signature: */ +test_static EC_TEST_RETURN test_my_function(void) { /* Run some code */ bool condition = some_function(); @@ -57,9 +112,27 @@ test_static int test_my_function(void) } ``` +The only difference between those two versions of `test/my_test.c` is the +assertion: `c zassert_true(condition);` versus `c TEST_EQ(condition, true, +"%d");` + +### Specify the test cases to run + +The EC test API enumerates the test cases using `RUN_TEST` in the `run_test` +function, while the Ztest API enumerates the test cases using `ztest_unit_test` +inside another macro for the test suite, inside of `test_main`. + `test/my_test.c`: ```c +#ifdef CONFIG_ZEPHYR +void test_main(void) +{ + ztest_test_suite(test_my_unit, + ztest_unit_test(test_my_function)); + ztest_run_test_suite(test_my_unit); +} +#else /* The test framework will call the function named "run_test" */ void run_test(int argc, char **argv) { @@ -69,8 +142,15 @@ void run_test(int argc, char **argv) /* Report the results of all the tests at the end. */ test_print_result(); } +#endif /* CONFIG_ZEPHYR */ ``` +### Task List + +EC unit tests can run additional tasks besides the main test thread. The EC unit +test implementation provides a phtreads-based implementation of the EC task API. +We do not yet support running additional tasks in Ztest-based tests. + In the [`test`] subdirectory, create a `tasklist` file for your test that lists the tasks that should run as part of the test: @@ -83,7 +163,9 @@ the tasks that should run as part of the test: #define CONFIG_TEST_TASK_LIST ``` -Add the test to the `Makefile`: +### Makefile + +Add the test to the `Makefile` so that it can build as an EC unit test: `test/build.mk`: @@ -104,25 +186,45 @@ Make sure you test shows up in the "host" tests: host-my_test run-my_test ``` +### Test Config File -Build and run the test: +Add any test-specific configurations to the [test_config.h](https://source.chromium.org/chromiumos/chromiumos/codesearch/+/HEAD:src/platform/ec/test/test_config.h) file: + +```c +#ifdef TEST_ +/* + * Add test-specific configurations here. + */ +#endif +``` + +### Build and Run + +Build and run the test as an EC unit test: ```bash (chroot) $ make run-my_test ``` +For building the test as a Zephyr Ztest unit test, follow the instructions in +[Porting EC unit tests to Ztest](./zephyr/ztest.md) to build the unit test for Zephyr's +"native_posix" host-based target. + + *** note **TIP**: Unit tests should be independent from each other as much as possible. This keeps the test (and any system state) simple to reason about and also allows running unit tests in parallel. You can use the [`before_test` hook][`test_util.h`] to reset the state before each test is run. *** + ## Mocks -[Mocks][`mock`] enable you to simulate behavior for parts of the system that -you're not directly testing. They can also be useful for testing specific edge -cases that are hard to exercise during normal use (e.g., error conditions). +We do not yet support mocks for Zephyr Ztest-based tests. [Mocks][`mock`] enable +you to simulate behavior for parts of the system that you're not directly +testing. They can also be useful for testing specific edge cases that are hard +to exercise during normal use (e.g., error conditions). See the [Mock README] for details. diff --git a/docs/usb-c.md b/docs/usb-c.md index 1549b2abcc..5fa2c9953c 100644 --- a/docs/usb-c.md +++ b/docs/usb-c.md @@ -1,7 +1,24 @@ # EC Implementation of USB-C Power Delivery and Alternate Modes -USB-C PD requires a complex state machine as USB-C PD can operate in many -different modes. This includes but isn't limited to: +USB-C is intended to be a flexible connector supporting multiple data rates, +protocols, and power in either direction. For one connector to support varying +states of power delivery, the system and what it is connected to +must decide who will act as the source (drives power) and sink (consumes power). +Additionally, they need to decide the correct voltage and current for the source +to drive by taking into account not only the source's and sink's capabilities, +but also what the cable can support. Resistance of pull-up and pull-down resistors +on the configuration channel (CC) ports of the USB-C connector are used to +negotiate who is source and who is sink when a new USB-C connection is established. +This allows for setting power characteristics to default USB2 (500mA) default +USB3 (900mA) 1.5A and 3.0A at 5V. Additional power requirements using USB-PD must +then be negotiated by the source and sink over the CC pins of the USB-C connectors. +Beyond power contract negotiations, USB PD messages can be used to enable alternate +modes (Example: DisplayPort) and send a class of messages called Structured Vendor +Defined Message (SVDMs), which are not related to power delivery. The additional +flexiblity and functionality in USB-C requires support from the OS. + +From the system, USB PD requires a complex state machine as USB PD can +operate in many different modes. This includes but isn't limited to: * Negotiated power contracts. Either side of the cable can source or sink power up to 100W (if supported by device). @@ -12,7 +29,9 @@ different modes. This includes but isn't limited to: * USB SuperSpeed mode (up to 4 lanes for USB data) * DisplayPort Alternate Mode (up to 4 lanes for DisplayPort data) * Dock Mode (2 lanes for USB data, and 2 lanes for DisplayPort) + * Thunderbolt 3 (TBT3) Alternate Mode (4 lanes for TBT3 data) * Audio Accessory mode. (1 lane is used for L and R analog audio signal) + * USB4 (4 lanes for USB data, but using different signaling than USB 3.2) For a more complete list of USB-C Power Delivery features, see the [USB-C PD spec][USB PD Spec Id]. @@ -71,18 +90,26 @@ Modes in the EC codebase. * Upstream Facing Port. The USB data role that is typical for a peripheral (e.g. HID keyboard). * DFP {#dfp} + * Downstream Facing Port. The USB Data role that is typical for a host machine (e.g. device running ChromeOS). * E-Mark {#emark} + * Electronically marked cable. A USB-C cable that contains an embedded chip in the cable, used to identify the capabilities of the cable. * VCONN {#vconn} + * Connector Voltage. A dedicated power supply rail for [E-Mark](#emark) cables and other accessory functions (such as display dongles, and docks). VCONN re-uses one of the CC1/CC2 signals to provide 5 volt, 1 watt, of power. +* VDM + * Vendor-Defined Message: A type of PD data message whose contents can be + specific to a particular vendor or subordinate specification. The TCPM + primarily uses VDMs to discover support for alternate modes and enter + them. ## Different PD stacks @@ -93,6 +120,8 @@ Right now platform/ec has two different implementations of USB-C PD stack. [`usb_pd_policy.c`](../common/usb_pd_policy.c) 2. The newer implementation is found under [`common/usbc`](../common/usbc) and is broken up into multiple different files and state machines + * Device policy manager files, `usb_pd_dpm.c`, `usb_mode.c`, + `*_alt_mode.c`. * Policy engine state machine files, `usb_pe_*_sm.c`. * Protocol engine state machine file, `usb_prl_*_sm.c`. * State machine framework file, `usb_sm.c`. @@ -205,8 +234,8 @@ TODO(https://crbug.com/974302): mention `USB_CHG_P#` and `CHARGER` ## Upgrading FW for TCPCs -TODO(https://crbug.com/974302): Mention how this works even though it is in depthcharge. -Probing now. Need new driver in depthcharge +TODO(https://crbug.com/974302): Mention how this works even though it is in +depthcharge. Probing now. Need new driver in depthcharge [Case Closed Debugging (CCD)]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md [Introduction to USB Power Delivery]: https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en575003 diff --git a/docs/usb-tcpmv2.md b/docs/usb-tcpmv2.md index 0afd07c3e6..b09805177f 100644 --- a/docs/usb-tcpmv2.md +++ b/docs/usb-tcpmv2.md @@ -1,6 +1,11 @@ # EC USB-C Power Delivery TCPMv2 Overview -As the original USB-C Power Delivery (PD) solution for the ChromeOS Embedded Controller has aged, it has grown to the point where it is difficult to add new features and address bugs. A new PD stack (generally referred to as TCPMv2) has been introduced to the codebase for use moving forward. It implements a layered, state-based design which tracks more closely with the USB Type-C and USB PD specifications. +As the original USB-C Power Delivery (PD) solution for the ChromeOS Embedded +Controller has aged, it has grown to the point where it is difficult to add new +features and address bugs. A new PD stack (generally referred to as TCPMv2) has +been introduced to the codebase for use moving forward. It implements a layered, +state-based design which tracks more closely with the USB Type-C and USB PD +specifications. [TOC] @@ -8,38 +13,51 @@ As the original USB-C Power Delivery (PD) solution for the ChromeOS Embedded Con Boards may enable TCPMv2 by adding the following defines: - - * `CONFIG_USB_PD_TCPMV2`Configures the board to use the new stack. -* `CONFIG_USB_DRP_ACC_TRYSRC`: Configures the type of state machine to run (in this case, a DRP which performs Try.SRC behavior). Currently available are DRP and charge-through Vconn-powered device options -* `CONFIG_USB_PD_DECODE_SOP`: Sets up messaging for SOP’ and SOP’’, which is strongly encouraged in the TCPMv2 code moving forward -* `CONFIG_USB_PID 0x1234`: Sets the USB Product Identifier. This will be shared for all boards within one reference design, and new PIDs may be requested by sending an email to the ChromeOS FW Team. -* `CONFIG_USB_PD_REV30`: The TCPMv2 stack defaults to PD2.0 operation but defining this macro enables PD3.0 functionality. - -Other configurations to specify behaviors within the task still apply (ex. `CONFIG_USB_PD_ALT_MODE_DFP` and `CONFIG_USB_PD_TCPC_LOW_POWER`). - +* `CONFIG_USB_DRP_ACC_TRYSRC`: Configures the type of state machine to run (in + this case, a DRP which performs Try.SRC behavior). Currently available are + DRP and charge-through Vconn-powered device options +* `CONFIG_USB_PD_DECODE_SOP`: Sets up messaging for SOP’ and SOP’’, which is + strongly encouraged in the TCPMv2 code moving forward +* `CONFIG_USB_PID 0x1234`: Sets the USB Product Identifier. This will be + shared for all boards within one reference design, and new PIDs may be + requested by sending an email to the ChromeOS FW Team. +* `CONFIG_USB_PD_REV30`: The TCPMv2 stack defaults to PD2.0 operation but + defining this macro enables PD3.0 functionality. + +Other configurations to specify behaviors within the task still apply (ex. +`CONFIG_USB_PD_ALT_MODE_DFP` and `CONFIG_USB_PD_TCPC_LOW_POWER`). ## State Machine Framework -The basis of the TCPMv2 state machines is a generic state machine framework. This framework can be found in common/usbc/usb\_sm.c. For each state, there may be defined: - - +The basis of the TCPMv2 state machines is a generic state machine framework. +This framework can be found in common/usbc/usb\_sm.c. For each state, there may +be defined: * Entry: Called upon entering a state * Run: Called while steady in a state * Exit: Called upon leaving a state -* Parent: Superstate. Enters, exits, and runs alongside the child state. Only enters and exits when transitioning between states which do not share the parent. - -All fields are optional and may be set to NULL. A new state is transitioned to with a call into set\_state(), which exits the old state and parents and enters the new parents and state. States may be changed with set\_state() in any entry or run function, but any call from an exit function is ignored since exit is only called when a change is already in progress. While in a state, run\_state() executes the run function for the current state and parents. If set\_state() is called from either an entry function or a run function, the remaining run or entry functions are stopped. - -Below is a graphical example of what some states may look like. States 1 and 2 share Parent State 1, while State 3 has Parent State of 2. - +* Parent: Superstate. Enters, exits, and runs alongside the child state. Only + enters and exits when transitioning between states which do not share the + parent. + +All fields are optional and may be set to NULL. A new state is transitioned to +with a call into set\_state(), which exits the old state and parents and enters +the new parents and state. States may be changed with set\_state() in any entry +or run function, but any call from an exit function is ignored since exit is +only called when a change is already in progress. While in a state, run\_state() +executes the run function for the current state and parents. If set\_state() is +called from either an entry function or a run function, the remaining run or +entry functions are stopped. + +Below is a graphical example of what some states may look like. States 1 and 2 +share Parent State 1, while State 3 has Parent State of 2. ![Example States](images/TCPMv2-ExampleStates.png "Example States") - -Translated into code, this would be something like below (note it is not necessary that the states be a part of an array, but the TCPMv2 code generally organizes the states in this way): - +Translated into code, this would be something like below (note it is not +necessary that the states be a part of an array, but the TCPMv2 code generally +organizes the states in this way): ``` static const struct usb_state test_states[] = { @@ -74,23 +92,18 @@ static const struct usb_state test_states[] = { }; ``` - -For this example, each test state is written simply to produce a print of its function name. The two exceptions are: - - +For this example, each test state is written simply to produce a print of its +function name. The two exceptions are: * parent\_1\_run() calls set\_state() into STATE\_2 when called a second time * state\_2\_entry() calls set\_state() into STATE\_3 Graphically, this is represented below: - ![Example Transitions](images/TCPMv2-ExampleTransitions.png "Example state transitions and resulting called functions") - And the following code output is produced: - ``` Calling run_state() state_1_run @@ -112,74 +125,186 @@ state_3_run parent_2_run ``` +## TCPMv2 PD Task +The TCPMv2 PD task is built upon state machines using the above framework and is +located in common/usbc/usbc\_task.c. It is separated into three layers which +track with the USB Type-C and USB PD specification states and run in a loop with +5 ms periods between executions. A graphical representation of these layers is +below. -## TCPMv2 PD Task +![PD Task Loop](images/TCPMv2-TaskLoop.png "PD task loop state machine calls") -The TCPMv2 PD task is built upon state machines using the above framework and is located in common/usbc/usbc\_task.c. It is separated into three layers which track with the USB Type-C and USB PD specification states and run in a loop with 5 ms periods between executions. A graphical representation of these layers is below. +The task is designed such that the Type-C (TC) layer could run independently for +any application which doesn’t wish to enable PD messaging. Boards define their +appropriate Policy Engine (PE) and TC state machines through their selection of +a CONFIG\_USB\_\* define, with current options supporting both Dual-Role Ports +(DRPs) and Charge-Through Vconn-Powered Device (CTVPD). All boards use the same +Protocol Layer (PRL) code. +## TCPMv2 Layers +### Overview -![PD Task Loop](images/TCPMv2-TaskLoop.png "PD task loop state machine calls") +The three state machines mentioned above interact with each other and the EC +drivers in order to orchestrate all Type-C connection behavior. Graphically, +they are represented below. +![PD Task Layers](images/TCPMv2-TaskLayers.png "PD task layer interactions") -The task is designed such that the Type-C (TC) layer could run independently for any application which doesn’t wish to enable PD messaging. Boards define their appropriate Policy Engine (PE) and TC state machines through their selection of a CONFIG\_USB\_\* define, with current options supporting both Dual-Role Ports (DRPs) and Charge-Through Vconn-Powered Device (CTVPD). All boards use the same Protocol Layer (PRL) code. +Layers communicate with each other using atomic operations on flags and shared +buffers. Functions calling into each layer are clearly named to indicate the +layer they are acting on, and anything calling into the PD task should be doing +so through pd\_\* named functions. + +Some specific examples of how this communication works between layers is below. +If a port partner sends in a Vconn\_swap request, then: + +* PRL will communicate that a message was received to the PE layer through + pe\_message\_received(), which sets PE\_FLAGS\_MSG\_RECEIVED and indicates + the receive buffer has a message +* PE asks with the TC whether the board is sourcing Vconn with + tc\_is\_vconn\_src() which checks TC\_FLAGS\_VCONN\_ON +* PE tells the PRL to send an ACCEPT message to the port partner through + prl\_send\_ctrl\_msg() which fills in shared message information and sets + PRL\_FLAGS\_MSG\_XMIT +* PRL lets the PE know that the message transmit was successful through + pe\_message\_sent() which sets PE\_FLAGS\_TX\_COMPLETE +* TC tells the PE layer that the Vconn swap completed with + pe\_vconn\_swap\_complete() which sets PE\_FLAGS\_VCONN\_SWAP\_COMPLETE +### Type-C Layer -## TCPMv2 Layers +Defined in the USB Type-C specification, this layer is responsible for basic +connection. It takes care of setting the CC lines, detecting and debouncing the +partner CC lines, and performs most of the interactions needed with the PPC and +USB mux. Once the TC layer has gotten the connection to the point of being +Attached.SNK or Attached.SRC, it will enable the PRL and PE layers accordingly. +### Protocol Layer -### Overview +A part of the USB PD specification, the protocol layer is responsible for the +actual sending and receiving of PD messages with the TCPCs. The layer is +actually composed of 4 separate state machines running one after the other. +These state machines are: -The three state machines mentioned above interact with each other and the EC drivers in order to orchestrate all Type-C connection behavior. Graphically, they are represented below. +* Chunked receive (RCH): passes messages up to the PE and requests chunks when + chunking +* Chunked transmit (TCH): receives messages from the PE and waits for chunk + requests when chunking +* Protocol transmit (PRL\_TX): passes messages to the TCPCs and handles PD 3.0 + collision avoidance +* Protocol hard reset (PRL\_HR): responds to or transmits hard resets, resets + PRL layer variables, notifies PE of hard reset receipt or sent +### Policy Engine Layer +The PE layer states are defined as a part of the USB PD specification. State +names are meant to track very closely with the specification so they can be +easily searchable and understood. The PE’s primary responsibility is to send and +process PD messages in order to implement the port’s policy. -![PD Task Layers](images/TCPMv2-TaskLayers.png "PD task layer interactions") +### Device Policy Manager Layer +The USB PD specification defines some responsibilities of the DPM, e.g. +selecting _Source Capabilities_ to offer and alternate modes to enter. Broadly, +the DPM is supposed to make discretionary decisions about the behavior of the +PE, i.e. policy decisions. However, the spec is relatively silent on the +structure and scope of the DPM. -Layers communicate with each other using atomic operations on flags and shared buffers. Functions calling into each layer are clearly named to indicate the layer they are acting on, and anything calling into the PD task should be doing so through pd\_\* named functions. +In TCPMv2, the DPM consists of a central code module in `usb_pd_dpm.c` and +several code modules for supported alternate or USB modes. The mode entry and +exit logic in the DPM takes the form of a state machine, and each mode has its +own state machine to control the specific mode entry and exit steps. The DPM +also contains logic to choose which Source PDO to offer in _Source +Capabilities_. -Some specific examples of how this communication works between layers is below. If a port partner sends in a Vconn\_swap request, then: +The DPM state machines do not currently use the USB state machine framework. +Additionally, there are policy decisions encoded in the lower layers and in +board code that ought to be made by the DPM. An effort to centralize policy +decisions and improve DPM code organization is ongoing. +## Alternate modes and USB4 +TCPMv2 supports several modes of operation besides USB 3.2. To determine which +modes the port partner and cable support, the TCPM sends _SOP_ and _SOP'_ +Vendor-Defined Messages, specifically _Discover Identity_, _Discover SVIDs_, +and _Discover Modes_. The responses to these messages list supported modes. The +AP may query this information via `EC_CMD_TYPEC_DISCOVERY`. -* PRL will communicate that a message was received to the PE layer through pe\_message\_received(), which sets PE\_FLAGS\_MSG\_RECEIVED and indicates the receive buffer has a message -* PE asks with the TC whether the board is sourcing Vconn with tc\_is\_vconn\_src() which checks TC\_FLAGS\_VCONN\_ON -* PE tells the PRL to send an ACCEPT message to the port partner through prl\_send\_ctrl\_msg() which fills in shared message information and sets PRL\_FLAGS\_MSG\_XMIT -* PRL lets the PE know that the message transmit was successful through pe\_message\_sent() which sets PE\_FLAGS\_TX\_COMPLETE -* TC tells the PE layer that the Vconn swap completed with pe\_vconn\_swap\_complete() which sets PE\_FLAGS\_VCONN\_SWAP\_COMPLETE +Based on the discovery responses, the DPM decides which mode to enter (if any) +and drives mode entry. If `CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY` is enabled, the +AP directs the DPM to enter and exit modes via `EC_CMD_TYPEC_CONTROL`. +### DisplayPort -### Type-C Layer +DisplayPort alternate mode repurposes the SuperSpeed lanes as video data lanes, +all flowing from the host to the monitor. DP mode can use 2 lanes, allowing +simultaneous USB traffic on the cable, or it can use all 4 lanes, supporting +greater display bandwidth at the expense of USB. -Defined in the USB Type-C specification, this layer is responsible for basic connection. It takes care of setting the CC lines, detecting and debouncing the partner CC lines, and performs most of the interactions needed with the PPC and USB mux. Once the TC layer has gotten the connection to the point of being Attached.SNK or Attached.SRC, it will enable the PRL and PE layers accordingly. +The sequence to enter DP alternate mode (v. 1.4) is +* The TCPM sends an SOP VDM _Enter Mode_ REQ with the DP VID. +* The TCPM sends an SOP _DP Status_ VDM REQ. +* The TCPM sends an SOP _DP Configure_ VDM REQ. +* Display sends an SOP _Attention_ VDM REQ. +To exit DP alternate mode, the TCPM sends an SOP VDM _Exit Mode_ REQ. -### Protocol Layer +`dp_alt_mode.c` and `usb_pd_alt_mode_dfp.c` contain the majority of the DP entry +and exit logic. -A part of the USB PD specification, the protocol layer is responsible for the actual sending and receiving of PD messages with the TCPCs. The layer is actually composed of 4 separate state machines running one after the other. These state machines are: +### Thunderbolt 3 +TBT3 alternate mode repurposes all 4 SuperSpeed lanes for Thunderbolt 3, which +is itself a bidirectional tunneling protocol supporting various types of +hardware, most commonly docks. +The sequence to enter TBT3 alternate mode depends on the cable used: +* If the cable supports TBT3, the TCPM sends an SOP' VDM _Enter Mode_ REQ with + the Intel VID. +* If the cable is also an active cable with SOP'' support, the TCPM sends an + SOP'' VDM _Enter Mode_ REQ. (The TBT3 mode VDO may identify the cable as + active for this purpose when the ID Header VDO does not.) +* The TCPM sends an SOP VDM _Enter Mode_ REQ. -* Chunked receive (RCH): passes messages up to the PE and requests chunks when chunking -* Chunked transmit (TCH): receives messages from the PE and waits for chunk requests when chunking -* Protocol transmit (PRL\_TX): passes messages to the TCPCs and handles PD 3.0 collision avoidance -* Protocol hard reset (PRL\_HR): responds to or transmits hard resets, resets PRL layer variables, notifies PE of hard reset receipt or sent +To exit TBT3 alternate mode, the TCPM sends VDM _Exit Mode_ REQs to SOP, SOP'', +and SOP', as appropriate. +`tbt_alt_mode.c` and `usb_pd_alt_mode_dfp.c` contain the TBT entry and exit +logic. -### Policy Engine Layer +### USB4 -The PE layer states are defined as a part of the USB PD specification. State names are meant to track very closely with the specification so they can be easily searchable and understood. The PE’s primary responsibility is to send and process PD messages in order to implement the port’s policy. +USB4 is not an alternate mode, but it does repurpose the SuperSpeed lines (using +different signaling and routing than USB 3.2), so the TCPM must explicitly enter +USB4. +The sequence to enter USB4 is conceptually similar to that for TBT3: +* If the cable supports USB4, the TCPM sends an SOP' _Enter USB_ message. +* If the cable is also an active cable, the TCPM sends an SOP'' _Enter USB_. +* The TCPM sends an SOP _Enter USB_. +Complicating matters, if the cable does not support USB4 but does support TBT3, +the TCPM may enter TBT3 for the cable as above, then enter USB4 for the port +partner. -## Best Practices +To exit USB4 (returning to a USB 3.2 mux configuration), the TCPM performs a +_Data Reset_ sequence. +`usb_mode.c` and `usb_pd_alt_mode_dfp.c` contain the USB4 entry and exit logic. +## Best Practices -* Always call return after set\_state(). Once the state has been changed, nothing further should be done in the current state. -* Never call set\_state() from an exit function. The call will be ignored as there is already a state transition taking place. -* Never call set\_state() from outside the PD task. The task may be waiting in any number of locations and the context should not change around it while it does so. -* Always use flags to communicate between layers, and to communicate with the PD task from other tasks. Flags should be accessed through atomic operations. +* Always call return after set\_state(). Once the state has been changed, + nothing further should be done in the current state. +* Never call set\_state() from an exit function. The call will be ignored as + there is already a state transition taking place. +* Never call set\_state() from outside the PD task. The task may be waiting in + any number of locations and the context should not change around it while it + does so. +* Always use flags to communicate between layers, and to communicate with the + PD task from other tasks. Flags should be accessed through atomic + operations. * Always use pd\_\* functions to access the PD task from other tasks. -* Always write unit tests as code is added, to verify new code works and protect against regressions as development continues. +* Always write unit tests as code is added, to verify new code works and + protect against regressions as development continues. diff --git a/docs/usb_power.md b/docs/usb_power.md index e066a7bba6..95177dc150 100644 --- a/docs/usb_power.md +++ b/docs/usb_power.md @@ -135,43 +135,59 @@ in-depth information can be found in the [USB Type-C Specification] \(section ### ChromeOS as Source - Policy for Type-C +**Note:** Behavior outlined here is only implemented in the TCPMv2 Device +Policy Manager (DPM) when a board defines a non-zero maximum number of 3A +ports supported through `CONFIG_USB_PD_3A_PORTS`. + ChromeOS devices currently source power to external USB devices at 5V with a -typical current of 1.5A for each Type-C port. In certain scenarios, a single -Type-C port can source up to 3A @ 5V. - -ChromeOS prefers that the first PD-capable Type-C device **that claims 3A** -should get 3A guaranteed at 5V. Once a PD-capable Type-C device has claimed 3A, -then other PD-capable Type-C devices will only be offered a maximum of 1.5A. - -If there are no PD-capable Type-C devices claiming 3A, then the first non-PD -device will be given 3A until a PD-capable device **that claims 3A** is -inserted. - -The 3A is only offered after a minimum delay of 200 ms following the initial -connection. One main reason for this delay is to protect against non-PD capabale -devices that only sample the CC resistors once at initial connection from -continuing to consume 3A after we downgrade the CC resistors to 1.5A at a later -point in the future. The motivation for this is that any non-PD device that -notices that it can draw more current from a CC resistor change that happens 200 -ms after the initial connection will also notice a CC resistor change if we -downgrade the CC resistors to a lower current advertisement. We want consistent -behavior across non-PD capable devices and PD-capable devices, so we will only -offer the additional 1.5A to PD ports after the same delay. - -When a device that is currently claiming 3A is removed or proactively reduces -its power contract to 1.5A or less, then the next oldest PD-capable device is -offered 3A in order. If no PD-capable devices claims 3A, then the oldest non-PD -capable device is given 3A through a CC resistor change. +typical current of 1.5A for each Type-C port. In certain scenarios, a Type-C +port can source up to 3A @ 5V. + +ChromeOS prefers that the first PD-capable Type-C device **that requires 3A** +should get 3A guaranteed at 5V. Once the maximum supported number of PD-capable +Type-C device has claimed 3A, then other PD-capable Type-C devices will only be +offered a maximum of 1.5A. + +If Fast Role Swap (FRS) is supported and a sourcing port partner reports +requiring 3A after a fast role swap, then this port should be allocated 3A if +no more PD-capable sinks require 3A, and FRS detection may be enabled. Once a +PD-capable device **that requires 3A** is inserted, the FRS port may have FRS +detection disabled if the maximum number of 3A ports has been reached. + +If there are no PD-capable Type-C devices requiring 3A and no FRS ports +requiring 3A, then the first non-PD device will be given 3A until a PD-capable +device **that requires 3A** is inserted, or until an FRS source that requires +3A is inserted. + +Devices will indicate they require 3A operating current in their sink +capabilities, and this will be used as the trigger to let the EC know to +offer that port a 3A source contract. FRS source partners will also +indicate the need for 3A in their sink capabilities, under their Fast Role +Swap required current. + +This policy is laid out in the following flow chart. Current policy for the +"next" port allocation is to select the lowest port number any time more than +one port meets criteria to receive 3A. + +Port balancing will occur when: +* Sink Capabilities are received for a device +* Source capabilities are not replied to after nCapsCount, indicating a non-PD + sink +* Power roles are swapped +* Detach occurs + +![Source Port Balancing](images/usb_source_port_balancing.png "Source Port Balancing") Inserting a Type-A device does not affect the power assignment for Type-C ports; only Type-C devices affect the power of Type-C ports. -For example, the below sequence of events illustrates the above Type-C policy: +For example, the below sequence of events illustrates the above Type-C policy +with a board with a maximum number of 1 3A-ports supported: 1. A non-PD capable Type-C keyboard is inserted first * Keyboard will be offered 1.5A initially * Current state: `keyboard @ 1.5A`. -2. More than 200ms pass. +2. Partner is established to be non-PD through reaching PE\_SRC\_Disabled. * Since there are no other PD-capable devices and this is the first device, offer this device 3A via CC resistor change. * Current state: `keyboard @ 3A`. @@ -179,53 +195,64 @@ For example, the below sequence of events illustrates the above Type-C policy: * It will be offered 1.5A since there is already another non-PD device claiming 3A. * Current state: `keyboard @ 3A` and `mouse @ 1.5A`. -4. A PD-capable Type-C dock is inserted third - * Initially negotiate for 1.5A, then wait 200ms after negotiating. - * Since this is the first PD device, we offer it 3A after 200ms from - initial power negotiation. - * Dock does not want high power from Chromebook; dock continues to selects +4. A PD-capable Type-C hub is inserted third + * Initially negotiate for 1.5A. + * Since this is a PD device, query its operational current through + requesting Sink Capabilities. + * Hub does not want high power from Chromebook; hub continues to receive 1.5A. * Keyboard gets to maintain higher 3A current supply. - * Current state: `keyboard @ 3A` and `mouse @ 1.5A` and `dock @ 1.5A`. + * Current state: `keyboard @ 3A` and `mouse @ 1.5A` and `hub @ 1.5A`. 5. A PD-capable Type-C phone is inserted fourth * Phone is initially offered 1.5A. - * Since there isn't an existing PD-capable device claiming 3A, the phone - is offered 3A after waiting the 200ms delay from initial negotiation. - * The phone wants high power; phone selects 3A. + * Since this is a PD device, query its operational current through + requesting Sink Capabilities. + * The phone reports it wants 3A. * Since PD devices are preferred for 3A, the non-PD keyboard will be downgraded from 3A to 1.5A via a CC resistor change. - * Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `dock @ 1.5A` + * After tSinkAdj (60 ms), phone is offered 3A through new Source + Capabilities. + * Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `hub @ 1.5A` and `phone @ 3A`. 6. A PD-capable Type-C tablet is inserted fifth - * Since there is already a PD-capable device claiming 3A, the tablet is - only offered 1.5A. - * Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `dock @ 1.5A` + * Tablet is initially offered 1.5A. + * Since this is a PD device, query its operational current through + requesting Sink Capabilities. + * Tablet would like 3A, but the board has reached its maximum number of + supported 3A ports. Note this port's desired current for later. + * Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `hub @ 1.5A` and `phone @ 3A` and `tablet @ 1.5A`. -7. The PD-capable phone is done charging so it downgrades its power contract to - 1.5A without any user interaction - * The next oldest PD-capable device is offered 3A in order: dock then - phone then tablet. - * The dock and phone continue to select 1.5A, then the tablet takes 3A. - * Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `dock @ 1.5A` - and `phone @ 1.5A` and `tablet @ 3A`. -8. The PD-capable tablet is removed - * The next oldest PD-capable device is offered 3A. If there are no - PD-capable devices claiming 3A, then the oldest non-PD capable device is - given 3A. - * The dock and phone continue to select 1.5A, so keyboard is given 3A via - CC resistor change. - * Current state: `keyboard @ 3A` and `mouse @ 1.5A` and `dock @ 1.5A` and - `phone @ 1.5A`. -9. The non-PD capable keyboard is removed - * The next oldest PD-capable device is offered 3A. If there are no - PD-capable devices claiming 3A, then the next oldest non-PD capable - device is given 3A. - * The dock and phone continue to select 1.5A, so mouse is given 3A via CC +7. The PD-capable phone is removed + * The next PD-capable sink device is offered 3A: the tablet + * Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `hub @ 1.5A` + and `tablet @ 3A`. +8. A FRS-capable dock is inserted + * The dock is sourcing us + * Since this is a PD capable device, query its FRS current through + requesting Sink Capabilities. + * Dock reports requiring 3A current after FRS. + * Tablet is currently occupying the 3A port, so note this port's desired + FRS current for later. + * Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `hub @ 1.5A` + and `tablet @ 3A`; dock `FRS detection disabled` +9. The PD-capable tablet is removed + * The next PD-capable device requiring 3A is offered 3A. If there are + no PD-capable devices requiring 3A, then the next FRS device is + allocated 3A. + * The hub only requires 1.5A, so FRS is enabled for the dock. + * Current state: `keyboard @ 1.5A` and `mouse @ 1.5A` and `hub @ 1.5A`; + dock `FRS detection enabled` +10. The FRS dock is removed + * The next PD-capable device requiring 3A is offered 3A. If there are + no PD-capable devices requiring 3A, then the next FRS device is + allocated 3A. If there are no FRS devices, then the next non-PD + capable device is given 3A. + * The hub only requires 1.5A, so mouse is given 3A via CC resistor change. - * Current state: `mouse @ 3A` and `dock @ 1.5A` and `phone @ 1.5A`. -10. The non-PD capable mouse is removed - * The dock and phone continue to select 1.5A. - * Current state: `dock @ 1.5A` and `phone @ 1.5A`. + * Current state: `keyboard @ 1.5A` and `mouse @ 3A` and `hub @ 1.5A`. +11. The non-PD capable mouse is removed + * The hub does not require 3A. + * Current state: `keyboard @ 3A` and `hub @ 1.5A`. Note: Not all released Chromebooks implement the above policy due to pre-existing hardware design constraints. diff --git a/docs/usb_updater.md b/docs/usb_updater.md index 476b50f316..f1505550d1 100644 --- a/docs/usb_updater.md +++ b/docs/usb_updater.md @@ -1,48 +1,44 @@ -EC update over USB -================== +# EC update over USB chip/g (Cr50) and common code (hammer, servo_micro/v4) update over USB protocols share a lot in terms of protocol and ideas, but use different code bases. -chip/g EC-side implementation is found in `chip/g/*upgrade*`, and the -userspace tool which provides updates over USB among with supporting other -features and interfaces is found in `extra/usb_updater/gsctool.c`. +chip/g EC-side implementation is found in `chip/g/*upgrade*`, and the userspace +tool which provides updates over USB among with supporting other features and +interfaces is found in `extra/usb_updater/gsctool.c`. Common code uses implementations in `common/*update*.c` and `include/*update*.h`, and `extra/usb_updater/usb_updater2.c` for the userspace updater. -Cr50-specific notes -------------------- +## Cr50-specific notes -The Cr50 firmware image consists of multiple sections, of interest to the -USB updater are the RO and RW code sections, two of each. When firmware update +The Cr50 firmware image consists of multiple sections, of interest to the USB +updater are the RO and RW code sections, two of each. When firmware update session is established, the Cr50 device reports locations of backup RW and RO sections (those not currently used by the device). Based on this information the updater carves out the appropriate sections from -the full Cr50 firmware binary image and sends them to the device for -programming into flash. Once the new sections are programmed and the device -is restarted, the new RO and RW are used if they pass verification and are -logically newer than the existing sections. +the full Cr50 firmware binary image and sends them to the device for programming +into flash. Once the new sections are programmed and the device is restarted, +the new RO and RW are used if they pass verification and are logically newer +than the existing sections. There are two ways to communicate with the Cr50 device: USB and `/dev/tpm0` (when `gsctool` is running on a chromebook with the Cr50 device). Originally -different protocols were used to communicate over different channels, -starting with version 3 the same protocol is used. +different protocols were used to communicate over different channels, starting +with version 3 the same protocol is used. -Common-code notes ------------------ +## Common-code notes -For non-Cr50 or chip/g devices (common code), the layout is a bit different, -as devices usually have a single RO and a single RW, where RO is truly read-only -in production, and verifies RW before jumping to it. +For non-Cr50 or chip/g devices (common code), the layout is a bit different, as +devices usually have a single RO and a single RW, where RO is truly read-only in +production, and verifies RW before jumping to it. For testing and development, `usb_updater2` is provided, while production code will use `hammerd` (in `src/platform/hammerd`) to update the device. -Update protocol ---------------- +## Update protocol The host (either a local AP or a workstation) is the master of the firmware update protocol, it sends data to the Cr50 device, which processes it and @@ -50,75 +46,76 @@ responds. The encapsulation format is different between the `/dev/tpm0` and USB cases: - 4 bytes 4 bytes 4 bytes variable size - +-----------+--------------+---------------+----------~~--------------+ - + total size| block digest | dest address | data | - +-----------+--------------+---------------+----------~~--------------+ - \ \ / - \ \ / - \ +----- FW update PDU sent over /dev/tpm0 -----------+ - \ / - +--------- USB frame, requires total size field ------------+ +``` + 4 bytes 4 bytes 4 bytes variable size ++-----------+--------------+---------------+----------~~--------------+ ++ total size| block digest | dest address | data | ++-----------+--------------+---------------+----------~~--------------+ + \ \ / + \ \ / + \ +----- FW update PDU sent over /dev/tpm0 -----------+ + \ / + +--------- USB frame, requires total size field ------------+ +``` The update protocol data units (PDUs) are passed over `/dev/tpm0`, the -encapsulation includes integrity verification and destination address of -the data (more of this later). `/dev/tpm0` transactions pretty much do not -have size limits, whereas the USB data is sent in chunks of the size -determined when the USB connection is set up. This is why USB requires an -additional encapsulation into frames to communicate the PDU size to the -client side so that the PDU can be reassembled before passing to the -programming function. - -In general, the protocol consists of two phases: connection establishment -and actual image transfer. - -The very first PDU of the transfer session is used to establish the -connection. The first PDU does not have any data, and the `dest address` -field is set to zero. Receiving such a PDU signals the programming function -that the host intends to transfer a new image. +encapsulation includes integrity verification and destination address of the +data (more of this later). `/dev/tpm0` transactions pretty much do not have size +limits, whereas the USB data is sent in chunks of the size determined when the +USB connection is set up. This is why USB requires an additional encapsulation +into frames to communicate the PDU size to the client side so that the PDU can +be reassembled before passing to the programming function. + +In general, the protocol consists of two phases: connection establishment and +actual image transfer. + +The very first PDU of the transfer session is used to establish the connection. +The first PDU does not have any data, and the `dest address` field is set to +zero. Receiving such a PDU signals the programming function that the host +intends to transfer a new image. The response to the first PDU varies depending on the protocol version. -Note that protocol versions before 5 are described here for completeness, -but are not supported any more. +Note that protocol versions before 5 are described here for completeness, but +are not supported any more. -Version 1 is used over `/dev/tpm0`. The response is either 4 or 1 bytes in -size. The 4 byte response is the *base address* of the backup RW section, -and there is no support for RO updates. The one byte response is an error -indication, possibly reporting flash erase failure, command format error, etc. +Version 1 is used over `/dev/tpm0`. The response is either 4 or 1 bytes in size. +The 4 byte response is the *base address* of the backup RW section, and there is +no support for RO updates. The one byte response is an error indication, +possibly reporting flash erase failure, command format error, etc. Version 2 is used over USB. The response is 8 bytes in size. The first four bytes are either the *base address* of the backup RW section (still no RO -updates), or an error code, the same as in Version 1. The second 4 bytes -are the protocol version number (set to 2). +updates), or an error code, the same as in Version 1. The second 4 bytes are the +protocol version number (set to 2). All versions above 2 behave the same over `/dev/tpm0` and USB. -Version 3 response is 16 bytes in size. The first 4 bytes are the error code -the second 4 bytes are the protocol version (set to 3) and then 4 byte -*offset* of the RO section followed by the 4 byte *offset* of the RW section. +Version 3 response is 16 bytes in size. The first 4 bytes are the error code the +second 4 bytes are the protocol version (set to 3) and then 4 byte *offset* of +the RO section followed by the 4 byte *offset* of the RW section. -Version 4 response in addition to version 3 provides header revision fields -for active RO and RW images running on the target. +Version 4 response in addition to version 3 provides header revision fields for +active RO and RW images running on the target. -Once the connection is established, the image to be programmed into flash -is transferred to the Cr50 in 1K PDUs. In versions 1 and 2 the address in -the header is the absolute address to place the block to, in version 3 and -later it is the offset into the flash. +Once the connection is established, the image to be programmed into flash is +transferred to the Cr50 in 1K PDUs. In versions 1 and 2 the address in the +header is the absolute address to place the block to, in version 3 and later it +is the offset into the flash. Protocol version 5 includes RO and RW key ID information into the first PDU -response. The key ID could be used to tell between prod and dev signing -modes, among other things. +response. The key ID could be used to tell between prod and dev signing modes, +among other things. -Protocol version 6 does not change the format of the first PDU response, -but it indicates the target's ability to channel TPM vendor commands -through USB connection. +Protocol version 6 does not change the format of the first PDU response, but it +indicates the target's ability to channel TPM vendor commands through USB +connection. Common-code updater also uses protocol version 6, but has a fairly different `first_response_pdu` header, indicated by setting `1` in the higher 16-bit for -the protocol version field (`header_type`). The response includes fields -such as maximum PDU size (which is not fixed to 1KB like for Cr50), flash -protection status, version string, and a minimum rollback version. +the protocol version field (`header_type`). The response includes fields such as +maximum PDU size (which is not fixed to 1KB like for Cr50), flash protection +status, version string, and a minimum rollback version. Details can be found in `include/update_fw.h`. @@ -128,54 +125,55 @@ This describes the EC-side state machine for update over USB. IDLE state: -* If host sends update start PDU (a command without any payload, digest = 0 - and base = 0): +* If host sends update start PDU (a command without any payload, digest = 0 + and base = 0): - * Reply with `first_update_pdu` block. Go to OUTSIDE_BLOCK state. + * Reply with `first_update_pdu` block. Go to OUTSIDE_BLOCK state. -* If host sends a vendor command (see below), execute that, reply, and stay - in IDLE state. Note that vendor commands are only accepted in IDLE state. +* If host sends a vendor command (see below), execute that, reply, and stay in + IDLE state. Note that vendor commands are only accepted in IDLE state. OUTSIDE_BLOCK (preparing to receive start of PDU): -* If no data is received in 5 seconds, go back to IDLE state. -* If host sends `UPDATE_DONE` command (by setting `dest address` to - `0xb007ab1e`), go back to IDLE state. -* If host sends a valid block start with a valid address, copy the rest - of the payload and go to INSIDE_BLOCK state. +* If no data is received in 5 seconds, go back to IDLE state. +* If host sends `UPDATE_DONE` command (by setting `dest address` to + `0xb007ab1e`), go back to IDLE state. +* If host sends a valid block start with a valid address, copy the rest of the + payload and go to INSIDE_BLOCK state. INSIDE_BLOCK (in a middle of a PDU): -* If no data is received in 5 seconds, go back to IDLE state. -* Copy data to a buffer. +* If no data is received in 5 seconds, go back to IDLE state. +* Copy data to a buffer. - * If buffer is full (i.e. matches the total expected PDU size), write the - data and go to OUTSIDE_BLOCK. - * Else, stay in INSIDE_BLOCK. + * If buffer is full (i.e. matches the total expected PDU size), write the + data and go to OUTSIDE_BLOCK. + * Else, stay in INSIDE_BLOCK. ### Vendor commands (channeled TPM command, Cr50) When channeling TPM vendor commands the USB frame looks as follows: - 4 bytes 4 bytes 4 bytes 2 bytes variable size - +-----------+--------------+---------------+-----------+------~~~-------+ - + total size| block digest | EXT_CMD | vend. sub.| data | - +-----------+--------------+---------------+-----------+------~~~-------+ +``` + 4 bytes 4 bytes 4 bytes 2 bytes variable size ++-----------+--------------+---------------+-----------+------~~~-------+ ++ total size| block digest | EXT_CMD | vend. sub.| data | ++-----------+--------------+---------------+-----------+------~~~-------+ +``` Where `Vend. sub` is the vendor subcommand, and data field is subcommand dependent. The target tells between update PDUs and encapsulated vendor -subcommands by looking at the `EXT_CMD` value - it is set to `0xbaccd00a` and -as such is guaranteed not to be a valid update PDU destination address. +subcommands by looking at the `EXT_CMD` value - it is set to `0xbaccd00a` and as +such is guaranteed not to be a valid update PDU destination address. -These commands cannot exceed the USB packet size (typically 64 bytes), as -no reassembly is performed for such frames. +These commands cannot exceed the USB packet size (typically 64 bytes), as no +reassembly is performed for such frames. The vendor command response size is not fixed, it is subcommand dependent. -The Cr50 device responds to each update PDU with a confirmation which is 4 -bytes in size in protocol version 2, and 1 byte in size in all other -versions. Zero value means success, non-zero value is the error code -reported by Cr50. +The Cr50 device responds to each update PDU with a confirmation which is 4 bytes +in size in protocol version 2, and 1 byte in size in all other versions. Zero +value means success, non-zero value is the error code reported by Cr50. Again, vendor command responses are subcommand specific. @@ -186,17 +184,18 @@ above, except that we use `UPDATE_EXTRA_CMD` (`b007ab1f`) instead of `EXT_CMD`, and `Vend. sub.` have a limit set of values (unless otherwise noted, commands take no parameter, and reply with a single 1-byte status code): -* UPDATE_EXTRA_CMD_IMMEDIATE_RESET (0): Tell EC to reboot immediately. -* UPDATE_EXTRA_CMD_JUMP_TO_RW (1): Tell EC (in RO) to jump to RW, if the - signature verifies. -* UPDATE_EXTRA_CMD_STAY_IN_RO (2): Tell EC (in RO), to stay in RO, and not - jump to RW automatically. After this command is sent, a reset is necessary - for the EC to accept to jump to RW again. -* UPDATE_EXTRA_CMD_UNLOCK_RW (3): Tell EC to unlock RW on next reset. -* UPDATE_EXTRA_CMD_UNLOCK_ROLLBACK (4): Tell EC to unlock ROLLBACK on next reset. -* UPDATE_EXTRA_CMD_INJECT_ENTROPY (5): Inject entropy into the device-specific - unique identifier (takes at least CONFIG_ROLLBACK_SECRET_SIZE=32 bytes of - data). -* UPDATE_EXTRA_CMD_PAIR_CHALLENGE (6): Tell EC to answer a X25519 challenge - for pairing. Takes in a `struct pair_challenge` as data, answers with a - `struct pair_challenge_response`. +* UPDATE_EXTRA_CMD_IMMEDIATE_RESET (0): Tell EC to reboot immediately. +* UPDATE_EXTRA_CMD_JUMP_TO_RW (1): Tell EC (in RO) to jump to RW, if the + signature verifies. +* UPDATE_EXTRA_CMD_STAY_IN_RO (2): Tell EC (in RO), to stay in RO, and not + jump to RW automatically. After this command is sent, a reset is necessary + for the EC to accept to jump to RW again. +* UPDATE_EXTRA_CMD_UNLOCK_RW (3): Tell EC to unlock RW on next reset. +* UPDATE_EXTRA_CMD_UNLOCK_ROLLBACK (4): Tell EC to unlock ROLLBACK on next + reset. +* UPDATE_EXTRA_CMD_INJECT_ENTROPY (5): Inject entropy into the device-specific + unique identifier (takes at least CONFIG_ROLLBACK_SECRET_SIZE=32 bytes of + data). +* UPDATE_EXTRA_CMD_PAIR_CHALLENGE (6): Tell EC to answer a X25519 challenge + for pairing. Takes in a `struct pair_challenge` as data, answers with a + `struct pair_challenge_response`. diff --git a/docs/write_protection.md b/docs/write_protection.md index 00e384ee16..65f04f2fa5 100644 --- a/docs/write_protection.md +++ b/docs/write_protection.md @@ -3,7 +3,7 @@ [TOC] This is a somewhat tricky topic since write protection implementations can -differ between chips and the hardware write protection has changed over time, +differ between chips, and the hardware write protection has changed over time, so please edit or open a bug if something is not clear. ## Terminology @@ -13,13 +13,13 @@ so please edit or open a bug if something is not clear. MCUs running the EC code have read-only (RO) and read-write (RW) firmware. Coming out of reset, the MCU boots into its RO firmware. -In the case of the EC, the RO firmware boots the host and asks it verify a hash -of the RW firmware (software sync). If the RW firmware is invalid, it is +In the case of the EC, the RO firmware boots the host and asks it to verify a +hash of the RW firmware (software sync). If the RW firmware is invalid, it is updated from a copy in the host's RW firmware. In the case of the FPMCU, the RO firmware uses the public key embedded in it to -validate the signature of the RW firmware. If the RW firmware is invalid it -does not jump to the RW firmware. +validate the signature of the RW firmware. If the RW firmware is invalid it does +not jump to the RW firmware. Once the RW firmware is validated, the MCU jumps to it (without rebooting). The RO firmware is locked in the factory and is never changed. The RW firmware can @@ -30,44 +30,46 @@ Note that both the RO and RW firmware regions are normally protected once write protect has been turned on. In the case of the EC, the RW region is unprotected at MCU boot until it has -been verified by the host. The RW region is protected before the Linux kernel -is loaded. +been verified by the host. The RW region is protected before the Linux kernel is +loaded. In the case of the FPMCU, the RW region is protected before jumping the RO firmware jumps to it. ## Hardware Write Protect {#hw_wp} -On modern Chrome OS devices, the Cr50 (aka GSC / TPM) provides a "hardware -write protect" GPIO that is connected to the AP SPI flash, EC SPI flash, -EEPROM, and FPMCU via a [GPIO][write_protect_gpio]. This "hardware write -protect" can only be disabled with servo or suzyq (["CCD open"]) and -corresponds to [`OverrideWP`] in ccd. Disabling this write protect disables it -for everything connected to this signal. +On modern Chrome OS devices, the Cr50 (aka GSC / TPM) provides a "hardware write +protect" GPIO that is connected to the AP SPI flash, EC SPI flash, EEPROM, and +FPMCU via a [GPIO][write_protect_gpio]. This "hardware write protect" can only +be disabled with [Servo] or [SuzyQ](["CCD open"]) and corresponds to +[`OverrideWP`] in ccd. Disabling this write protect disables it for everything +connected to this signal. In the case of the FPMCU, the hardware write protect GPIO is tied to the STM32 `BOOT0` pin, which is what tells the MCU to enter the STM32 bootloader mode. -You may see various references to a [write protect screw in -documentation][wp_screw]. Older Chrome OS devices had a write protect screw -that had to be physically removed. More details on this history can be found -here: http://go/cros-wp-status. +You may see various references to a +[write protect screw in documentation][wp_screw]. Older Chrome OS devices had a +write protect screw that had to be physically removed. More details on this +history can be found here: http://go/cros-wp-status. Another way of disabling hardware write protection is to remove the battery; this method is mainly used during bringup. Additional reference: -https://www.google.com/chromeos/partner/fe/docs/cpfe/firmwaretestmanual.html#hardware-write-protect +https://chromium.googlesource.com/chromiumos/docs/+/HEAD/write_protection.md ## Changing Hardware Write Protection -Modifying the state of hardware write protection (via Cr50 GPIO) can be done -if the ["CCD open"] process has been completed. +Modifying the state of hardware write protection (via Cr50 GPIO) can be done if +the ["CCD open"] process has been completed. + *** note `servod` *must* be running for `dut-control` to work. See the [Servo] page for details. *** + ### Enable Hardware Write Protection @@ -106,7 +108,7 @@ enabled or disabled (note that some implementations require an EC reset to disable software write protect). The underlying mechanism implementing software write protect may differ between -EC chips. However the common requirements are that software write protect can +EC chips. However, the common requirements are that software write protect can only be disabled when hardware write protect is off and that the RO firmware must be protected before jumping to RW firmware if protection is enabled. @@ -115,18 +117,21 @@ https://www.google.com/chromeos/partner/fe/docs/cpfe/firmwaretestmanual.html#sof ## Changing Software Write Protection + *** note *NOTE*: You cannot disable software write protect if hardware write protect is enabled. *** + -Software write protection can be toggled with `ectool --name=cros_fp flashprotect -enable/disable`, which sends the `EC_CMD_FLASH_PROTECT` command toggling -`EC_FLASH_PROTECT_RO_AT_BOOT` (changing `--name` to target different ECs). +Software write protection can be toggled with `ectool --name=cros_fp +flashprotect enable/disable`, which sends the `EC_CMD_FLASH_PROTECT` command +toggling `EC_FLASH_PROTECT_RO_AT_BOOT` (changing `--name` to target different +ECs). -### Changing Software Write Protection with `ectool` +### Changing Software Write Protection with ectool -#### `ectool flashprotect` +#### ectool flashprotect Print out current flash protection state. @@ -163,103 +168,30 @@ Flags: * `INCONSISTENT` - One or more banks of flash is not protected when it should be (should not happen during normal operation. Read only.). -#### `ectool flashprotect enable` +#### ectool flashprotect enable Set `ro_at_boot` flag. The next time the EC is reset it will protect the flash. Note that this requires a cold reset. -#### `ectool flashprotect enable now` +#### ectool flashprotect enable now Set `ro_at_boot` `ro_now all_now` flags and immediately protect the flash. Note that this will fail if hardware write protect is disabled. -#### `ectool flashprotect disable` +#### ectool flashprotect disable Clear `ro_at_boot` flag. This can only be cleared if the EC booted without hardware write protect enabled. Note that you must reset the EC to clear write protect after removing the screw. -If the `ro_at_boot` flag set and the EC resets with the HW gpio disabled, the EC -will leave the flash unprotected (`ro_now` and `all_now` flags are not set) but -leave `ro_at_boot` flag set. +If the `ro_at_boot` flag set, and the EC resets with the HW gpio disabled, the +EC will leave the flash unprotected (`ro_now` and `all_now` flags are not set) +but leave `ro_at_boot` flag set. -### Changing Software Write Protection with `flashrom` +## system_is_locked() -#### View the current state of software write protection - -```bash -(chroot) $ flashrom -p ec --wp-status -``` - -``` -WP: status: 0x00 -WP: status.srp0: 0 -WP: write protect is disabled. -WP: write protect range: start=0x00000000, len=0x00000000 -``` - -#### Enable software write protection - -This is immediate. The protection range indicates the RO region of the firmware. - -```bash -(chroot) $ flashrom -p ec --wp-enable -``` - -``` -SUCCESS -``` - -```bash -(chroot) $ flashrom -p ec --wp-status -``` - -``` -WP: status: 0x80 -WP: status.srp0: 1 -WP: write protect is enabled. -WP: write protect range: start=0x00000000, len=0x0001f800 -``` - -#### Disable software write protection - -Disable can only be done with hardware write protect disabled. - -```bash -(chroot) $ flashrom -p ec --wp-disable -``` - -``` -FAILED: RO_AT_BOOT is not clear. -FAILED -``` - -Reboot with [hardware write protection](#hw_wp) disabled. Note that protection -is still enabled but the protection range is zero. - -```bash -(chroot) $ flashrom -p ec --wp-status -``` - -``` -WP: status: 0x80 -WP: status.srp0: 1 -WP: write protect is enabled. -WP: write protect range: start=0x00000000, len=0x00000000 -``` - -```bash -(chroot) $ flashrom -p ec --wp-disable -``` - -``` -SUCCESS -``` - -## `system_is_locked()` - -The [`system_is_locked()`] function in the EC code returns false if the HW -write protect GPIO is disabled or the read-only firmware is not protected. +The [`system_is_locked()`] function in the EC code returns false if the HW write +protect GPIO is disabled, or the read-only firmware is not protected. One way this is used in the FPMCU source is to compile test or debug functionality into the firmware. Guarding the test functionality with @@ -292,10 +224,11 @@ https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1222094 The EC code command handlers (`command_flash_erase`, `command_flash_write`, etc.) return an error if `EC_FLASH_PROTECT_ALL_NOW` is set. -["CCD open"]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md#Open-CCD -[Cr50 console]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md#Consoles -[Servo]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/refs/heads/master/README.md -[`OverrideWP`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_cr50.md +["CCD open"]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_gsc.md#ccd-open +[Cr50 console]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_gsc.md#consoles +[Servo]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/README.md +[`OverrideWP`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/case_closed_debugging_gsc.md [`system_is_locked()`]: https://chromium.googlesource.com/chromiumos/platform/ec/+/aaba1d5efd51082d143ce2ac64e6caf9cb14d5e5/common/system.c#195 [wp_screw]: https://www.chromium.org/chromium-os/firmware-porting-guide/firmware-ec-write-protection [write_protect_gpio]: https://chromium.googlesource.com/chromiumos/platform/ec/+/aaba1d5efd51082d143ce2ac64e6caf9cb14d5e5/include/ec_commands.h#1599 +[SuzyQ]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD/docs/ccd.md#SuzyQ-SuzyQable diff --git a/docs/zephyr/README.md b/docs/zephyr/README.md new file mode 100644 index 0000000000..84239d3b05 --- /dev/null +++ b/docs/zephyr/README.md @@ -0,0 +1,125 @@ +# Zephyr Embedded Controller (Zephyr EC) + +[TOC] + +## Introduction + +Starting roughly in July of 2021, Chromebooks switched from the original [Google +Chrome EC](../../README.md) to an application based on the [Zephyr Project +RTOS](https://zephyrproject.org/). + +The following terms are used to to describe these two implementations: + +* Original Chrome EC: ECOS, cros-ec, and legacy EC +* Zephyr-based EC: Zephyr EC + +## Getting Started + +The [Zephyr build](zephyr_build.md) documentation details the usage of Google's +meta build tool `zmake`, used to configure and build Zephyr EC binaries. Start +here if you only need to build a Zephyr EC binary for an existing board. + +The [project configuration](project_config.md) documentation details the steps +required to create a new Chromebook program (reference board) and for creating a +new project variant. + +The [Zephyr New Board Checklist](zephyr_new_board_checklist.md) links to the +documentation needed to configure individual EC features. + +The [Zephyr Troubleshooting](zephyr_troubleshooting.md) page lists few common +errors and troubleshooting techniques used when working with Zephyr. + +## Source Code Organization + +Zephyr EC images rely on multiple Chromium repositories to build Zephyr EC images. + +* [`third_party/zephyr/main`] - Google's local mirror of the main Zephyr RTOS + source located on [Github](https://github.com/zephyrproject-rtos/zephyr). +* [`third_party/zephyr/cmsis`] - Google's local mirror of the CMSIS module source + from [Github](https://github.com/zephyrproject-rtos/cmsis) +* [`platform/ec`] - local repository containing code shared by the legacy EC and + the Zephyr EC + +The current Zephyr EC builds only the CMSIS module from the upstream Zephyr +source, but may use other modules in the future. + +The diagram below shows the relationship of the upstream Zephyr repositories and +the Chromium repositories. + +![Zephyr EC Structure](../images/zephyr_ec_structure.png) + +Google merges upstream Zephyr changes into the corresponding Chromium +repository daily. + +### Shared Code + +The two EC implementations currently share a significant amount code found in +the following directories (all paths relative to the Chrome EC base directory +[`platform/ec`].) + +* `common/` - Upper-level code shared across boards and the EC implementations. + This includes the following features: + * Battery charging + * USB Power Delivery + * AP chipset power sequencing + * Motionsense (EC sensor support) + * Keyboard handling + * Verified boot support + +* `driver/` - Low-level drivers for on-board peripherals controlled by the EC. + This does not include any drivers for modules integrated directly into the EC + chipset (such as GPIO controllers, I2C, controllers, keyboard controller). + On-board peripheral drivers include: + * Charge controllers + * USB Power Delivery chips (TCPCs, PPCs, muxes, etc) + * Temperature sensors + * Motionsense sensors (accelerometers, gyrscopes, light sensors, etc) + +* `include/` - Header files for the `common/` and `driver/` code + +The following legacy EC directories are not used by the Zephyr EC application: +* `baseboard/` +* `board/` +* `chip/` +* `core/` + +### Zephyr Subdirectory + +Only the Zephyr EC application uses the following directory under the +[`platform/ec`] repository: +* `zephyr/` + +The following provides an overview of the sub-directories found under +`zephyr/`. + +* `zephyr/app/` - The Zephyr EC application entry point. The Zephyr kernel + calls [`ec_app_main()`] routine after initializing all kernel services and + chip-level drivers, +* `zephyr/boards/` - Contains the EC chip-level support. This directory and the + organization is required by the Zephyr build system. This should not be + confused with the legacy EC `boards/` directory, as it does not contain any + Chromebook specific board code. +* `zephyr/cmake/` - Configuration files for the CMake build system. +* `zephyr/drivers/` - Drivers conforming to the Zephyr device model to + implement Chrome EC specific features. Google plans to eventually move these + drivers upstream. +* `zephyr/dts/` - Devicetree description files for Google's Zephyr drivers that + are not yet available upstream. +* `zephyr/emul/` - Emulator source code that has not yet been moved upstream. +* `zephyr/include/` - Header files for files found in the `zephyr/` + sub-directory. +* `zephyr/linker/` - Linker directive files used to construct the Zephyr EC + binaries. +* `zephyr/program/` - Program-specific configurations for each program + supported by Zephyr. +* `zephyr/shim/` - Source code that adapts the legacy EC APIs to the equivalent + Zephyr OS API. +* `zephyr/subsys/` - Staging area for subsystem code that will be moved + upstream. +* `zephyr/tests/` - Host based emulation tests. +* `zephyr/zmake/` - Source code for the `zmake/` meta tool. + +[`third_party/zephyr/main`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/zephyr/main +[`third_party/zephyr/cmsis`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/zephyr/cmsis +[`platform/ec`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec +[`ec_app_main()`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/app/ec/ec_app_main.c diff --git a/docs/zephyr/out_of_chroot.md b/docs/zephyr/out_of_chroot.md new file mode 100644 index 0000000000..22e1e2c342 --- /dev/null +++ b/docs/zephyr/out_of_chroot.md @@ -0,0 +1,76 @@ +# Building Zephyr Out-of-Chroot + +It is possible to build Zephyr outside of the Chromium OS chroot, +albeit with additional steps. + +*** note +**Note:** These steps are maintained on a best-effort basis, and may +not be accurate depending on your Linux distribution and your system's +specific environment. +*** + +[TOC] + +## Remove west, if installed [b/184654974](http://b/184654974) + +Zephyr's Cmake system will try to attach itself to the west tool if it finds it +installed, conflicting with manual cmake invocations. If you installed west, +you'll need to remove it: + +```bash +python3 -m pip uninstall west +``` + +## Install zmake + +You can install zmake with pip: + +```bash +cd ~/chromiumos/src/platform/ec +python3 -m pip install -e zephyr/zmake --user +``` + +Ensure that `~/.local/bin` is in your `PATH`. + +You may also need to install these items: + +```bash +sudo apt-get install cmake ninja-build python3-pyelftools gcc-multilib \ + python3-pykwalify python3-colorama python3-testfixtures +``` + +## Install binman + +First build pylibfdt: + +```bash +cd somewhere +sudo apt-get install flex bison swig +git clone git://git.kernel.org/pub/scm/utils/dtc/dtc.git +cd dtc +make +make install PREFIX=~/.local # You can install this where it suits +``` + +If you have a Chromium OS checkout then you should do: + +```bash +cd ~/.local/bin +ln -s ~/chromiumos/src/third_party/u-boot/files/tools/binman/binman +``` + +otherwise: + +```bash +cd somewhere +git clone https://source.denx.de/u-boot/u-boot.git +cd ~/.local/bin +ln -s somewhere/u-boot/tools/binman/binman +``` + +## Install Zephyr toolchain + +If using the Zephyr toolchain (`-t zephyr`), follow the [upstream +documentation] to install the Zephyr build tools. + +[upstream documentation]: https://docs.zephyrproject.org/getting_started/index.html#install-a-toolchain diff --git a/docs/zephyr/project_config.md b/docs/zephyr/project_config.md new file mode 100644 index 0000000000..27b5a7414d --- /dev/null +++ b/docs/zephyr/project_config.md @@ -0,0 +1,558 @@ +Project Configuration +===================== + +[TOC] + +## Overview + +This document defines the organization of the program and project specific files +needed by Zephyr EC projects. + +The goals of the project organization include: + +* Minimize code duplication, allowing multiple projects to share common + configuration options and devicetree nodes. +* Define the set of files required by each project. +* Define the best practices for devicetrees. + + +### Glossary + +- **program**: The name of a Chromebook reference design. The **program** + includes all Chromebooks based on a single AP SoC, such as Intel MeteorLake, + Qualcomm 7c G3, or AMD Mendocino. The **program** corresponds to a single + board overlay in the ChromeOS SDK. The term *baseboard* is often used as a + synonym for **program**. + +- **project**: The name of a specific Chromebook model or variant. All + Chromebook **programs** contain at least one **project** which serves as the + reference design(s) for the **program**. The reference **project** may or may + not use the same name as the **program**. For example, the reference + **project** for the skyrim **program** is also called skyrim. The corsola + **program** included two reference **projects**, kingler and krabby. For the + legacy ECOS builds, *board* was used as a synonym for **project**. + +This document uses bold to highlight the terms **program** and **project** to +reference the definitions above. + +## Directory Structure + +The [`zephyr/program`](../../zephyr/program) contains the **program** and +**project** configuration files for all Zephyr based EC builds. + +### `zephyr/program` directory + +Each **program** has it's own subdirectory under `zephyr/program`. + +``` +zephyr/program/ +├── brya/ +├── corsola/ +├── herobrine/ +├── intelrvp/ +├── it8xxx2_evb/ +├── minimal/ +├── nissa/ +├── npcx_evb/ +├── rex/ +├── skyrim/ +└── trogdor/ +``` + +> The [`zephyr/program/minimal`](../../zephyr/program/minimal/) **program** +contains example EC projects that demonstrate how to build a Zephyr EC with the +minimum feature set enabled. These projects require only a working UART on the +target board. + +### `zephyr/program/`**``**`/` Directory Overview + +Each **program** subdirectory contains a subdirectory foreach each **project**, +including a subdirectory for the reference **project**. + +The minimum configuration for a **program** named *skyrim* with just a single +reference **project**, also named *skyrim*, is shown below. + +``` +zephyr/program/skyrim/ +├── include/ +│ └── .h +├── skyrim/ +│ ├── include/ +│ │ └── .h +│ ├── src/ +│ │ └── .c +│ ├── CMakeLists.txt +│ ├── project.conf +│ └── project.overlay +├── src/ +│ └── .c +├── BUILD.py +├── CMakeLists.txt +├── Kconfig +├── program.conf +└── .dtsi +``` + +#### `zephyr/program/`**``**`/` Directory Details + +Description of the files and directories found directly in the **** +level directory. Note that all paths are relative to the `zephyr/program/` +directory. + +- **``**`/`: Top level directory for the **program**. [skyrim] is the + *program* name in the example above. +- **``**`/include/`: Directory containing the header files common to + all **projects** in the **program**. Use of **program** level includes is + discouraged. Instead, consider creating a generic driver that can be shared + across all **programs**. +- **``**`/src/`: Directory containing the C source files common to all + **projects** in the **program**. +- [**``**`/BUILD.py`](#build_py): Defines which **projects** can be + made from this directory. +- [**``**`/CMakeLists.txt`](#cmakelists_txt): CMake file for the + **program**. +- [**``**`/Kconfig`](#kconfig) - Defines new Kconfig options, used by + all **projects** in the **program**. +- [**``**`/program.conf`](#program_conf) - Sets the default Kconfig + settings for all **projects**. +- **``**`/.dtsi` - One or more devicetree files, organized + by the hardware module or EC feature. See the [Devicetree Best + Practices](#devicetree-best-practices) section for additional information. +- **``**`/`**``**`/`: Top level directory for the + **. Create a separate directory for each **project** defined by the + **program**. + +### `zephyr/program/`**``**`/`**``**`/` Directory Details + +Each **project** provides the following files. Note that all paths are relative +to the `zephyr/program/`**``**`/` directory. + +- **``**`/include/`: The **project** may optionally provide a public + include directory, but this is discouraged. There are some exceptions where + the legacy EC code expects the project to define a public header, such as the + keyboard_customization.h file. +- **``**`/src/`: Directory containing the C source files specific to + the **project**. +- [**``**`/CMakeLists.txt`](#cmakelists_txt): CMake file for the + **project**. +- [**``**`/project.conf`](#project_conf): Kconfig settings for the + **project**. +- [**``**`/project.overlay`](#project_overlay): Main devicetree overlay + for the **project**. + +Creation of custom C source files specific to the **program** or **project** is +discouaraged. You can usually project manage project specific settings with +Kconfig and devicetree changes only. + +Note that **program** and **project** custom C files are still subject to the +same unit test requirements. So all custom C files also require that you write +tests. + +## Setting up a new **program** + +To set up a new EC **program**, create a new directory under +[`zephyr/program`] with the organization shown below. +Note that for this example, the new **program** is called "my_program", and the +reference **project** is called "my_reference_project". + +> Tip - Copy one the **projects** defined by the [*minimal*] **program** to +> start with the bare miminimum of features required to boot the Zephyr EC +> appliation. Then follow the steps in the detailed in [Creating a New Zephyr EC +> Project]. + +``` +zephyr/program/my_program/ +├── my_reference_project/ +│ ├── CMakeLists.txt +│ ├── project.conf +│ └── project.overlay +├── BUILD.py +├── CMakeLists.txt +├── Kconfig +└── program.conf +``` + +An in-depth example of each file is given below: + +### BUILD.py + +`BUILD.py` is a Python-based config file for setting up your reference +board and the associated variants. The name `BUILD.py` is important +and case-sensitive: `zmake` searches for files by this +name. + +When `BUILD.py` is sourced, the following two globals are defined: + +- `here`: A `pathlib.Path` object containing the path to the directory + `BUILD.py` is located in. +- `register_project`: A function which informs `zmake` of a new + project to be built. Your `BUILD.py` file needs to call this + function one or more times. + +`register_project` takes the following keyword arguments: + +- `project_name` (required): The name of the project (typically the + Google codename). This name must be unique amongst all projects + known to `zmake`, and `zmake` will error if you choose a conflicting + name. +- `zephyr_board` (required): The name of the EC chip used. **Note:** the concept + of a Zephyr board does not align with the ChromeOS concept of a board. The + Zephyr build system requires a set of devicetree and Kconfig files under under + `boards/${ARCH}/${ZEPHYR_BOARD_NAME}`. For the Zephyr EC application, the EC + chip is mapped onto the Zephyr board organization. Supported `zephyr_boards` + include: + - `mec1727`: Microchip MEC1727, 416 KiB RAM, 512 KiB flash + - `npcx7`: Nuvoton NPCX7m7FC, 384 KiB, 512 KiB flash + - `npcx9m3f`: Nuvoton NPCX9m3F, 320 KiB RAM, 512 KiB flash + - `npcx9m7f`: Nuvoton NPCX9m7F, 384 KiB RAM, 1 MiB flash + - `it81202bx`: ITE IT81202, 60 KiB RAM, 1 MiB flash + - `it81302bx`: ITE IT81302, 60 KiB RAM, 1 MiB flash +- `supported_toolchains` (required): A list of the toolchain names + supported by the build. Valid values are: + - `coreboot-sdk`: only supported in the chroot + - `host`: used for unit and integration tests + - `llvm`: only supported in the chroot + - `zephyr`: only supported outside the chroot +- `output_packer` (required): An output packer type which defines + which builds get generated, and how they get assembled together into + a binary. +- `modules` (optional): A list of module names required by the + project. The default, if left unspecified, is to use all modules + known by `zmake`. Generally speaking, there is no harm to including + unnecessary modules as modules are typically guarded by Kconfig + options, so the only reason to set this is if your project needs to + build in a limited environment where not all modules are available. +- `dts_overlays` (optional): A list of files which should be concatenated + together and applied as a Zephyr device-tree overlay. The recommended setting + is to select the **project** specific devicetree overlay file. + + ``` python + dts_overlays=[here / project_name / "project.overlay"] + ``` + +- `kconfig_files` (optional): A list of files that contain the Kconfig settings + for the **project**. The recommended setting is select the **program** + configuration file followed by the **project** configuration file. + + ``` python + kconfig_files=[here / "program.conf", here / / "project.conf",] + ``` + +- `project_dir` (optional): The path to where `CMakeLists.txt` and + `Kconfig` can be found for the project, defaulting to `here`. + +Note that most projects will not want to call `register_project` +directly, but instead one of the helper functions, which sets even +more defaults for you: + +- `register_host_project`: Define a project which runs in the chroot + (not on hardware). +- `register_raw_project`: Register a project which builds a single + `.bin` file, no RO+RW packing, no FMAP. +- `register_binman_project`: Register a project which builds RO and RW + sections, packed together, and including FMAP. +- `register_npcx_project`: Just like `register_binman_project`, but + expects a file generated named `zephyr.npcx.bin` for the RO section + with Nuvoton's header. + +You can find the implementation of these functions in +[`zephyr/zmake/zmake/configlib.py`](../../zephyr/zmake/zmake/configlib.py). + +`BUILD.py` files are auto-formatted with `black`. After editing a +`BUILD.py` file, please run `black BUILD.py` on it. + +### CMakeLists.txt + +This file, should at minimum contain the following: + +``` cmake +cmake_minimum_required(VERSION 3.20.1) + +find_package(Zephyr REQUIRED HINTS "${ZEPHYR_BASE}") +project(**project**) +``` + +If your **program** provides any C files, add them to your program CMake file +using `zephyr_library_sources()`. + +``` cmake +zephyr_library_sources("src/my_program_source.c") +``` + +For your **project** C files, create **`/`**`CMakeLists.txt` and use +`add_subdirectory()` to include the **project** CMake file. + +``` cmake +add_subdirectory("my_reference_project") +``` + +Add the requires `zephyr_library_souces()` calls to the +**`/`**`CMakeLists.txt` file. + +If your **program** or **project** provides a public header, make the include +directory visible to rest of the code using +`cros_ec_library_include_directories()`. + +``` cmake +cros_ec_library_include_directories("include") +``` + +### Kconfig + +If certain projects need project-specific C files or ifdefs, the only +way to do so is to create a `Kconfig` file with the options schema you +want, and use it to toggle the inclusion of certain files. + +The file must end with a single line that reads +`source "Kconfig.zephyr"`. Note that this file is optional, so it's +recommended to only include it if you really need it. + +### program.conf + +`program.conf` has default Kconfig settings for all **projects** defined for the +**program**. The format is `KEY=VALUE`, as typical for Kconfig. + +### project.conf + +`project.conf` has the Kconfig settings for a single **project**. The format is +`KEY=VALUE`, as typical for Kconfig. + +Kconfig settings in `project.conf` take precedence over the Kconfig settings +from `program.conf`. + +### project.overlay + +`project.overlay` is the main devicetree overlay for the **project**. The +`project.overlay` contains the following components: +- One or more `#include` statements to add devicetrees defined by the + **program** into project. +- `/delete-node/` statements to remove specific devicetree nodes defined by the + **program** devicetrees. +- New devicetree nodes for **project** specific settings that are not provided + by any **program** devicetrees. + +> Tip: After building your **project**, you can view the final devicetree in the +file `build/zephyr/`**``**`/build-ro/zephyr/zephyr.dts`. + +## Setting up a new variant of an EC program + +**Unlike our legacy EC, there are no files or directories to copy and +paste to setup a new variant in Zephyr code.** + +Simply add a `register_project`-based call to the existing `BUILD.py` +for your reference board. + +Below is an example of how programs may wish to structure this in +`BUILD.py`: + +``` python +# Copyright 2021 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +def register_variant(project_name, chip="it8xx2", extra_dts_overlays=()): + return register_binman_project( + project_name=project_name, + zephyr_board=chip, + dts_overlays=[ + here / "base_power_sequence.dts", + here / "i2c.dts", + **extra_dts_overlays, + ], + ) + + +# Reference board +register_variant( + project_name="asurada", + extra_dts_overlays=[here / "reference_gpios.dts"], +) + +# Variants +register_variant( + project_name="hayato", + extra_dts_overlays=[here / "hayato_gpios.dts"], +) +``` + +If a project is going to be a simple variant of another project (e.g., +project `bar` is exactly identical to project `foo` but has just a few +device-tree/Kconfig changes), you can spin a new variant using the +return value of the register functions: + +``` python +foo = register_variant(project_name="foo") +bar = foo.variant( + project_name="bar", + dts_overlays=[here / "bar_extras.dts"], +) +``` + +With this simple variant syntax, lists (like Kconfig files and DTS +overlays) are concatenated. This means it's not possible to remove +files during variant registration for this syntax, so it's only +recommended for the simple case. + +## Devicetree Best Practices + +Below are the best practices for devicetree organization: + +* Split the devicetree across multiple files, organized by the functional block. + This organization applies to the shared **program** devicetrees only. + * FW_CONFIG + * GPIOs + * I2C + * Interrupts + * Keyboard + * LEDs + * Sensors + * Thermal (fans and temperature sensors) + * USB-C +* When creating **program**, usually with a single reference project, add the + shared devicetree files in the program directory, separated by the functional + area noted above. +* Each project creates a `project.overlay` file, and uses `#include` statements + to add shared devicetree files from the program directory. An example + project.overlay for the skyrim project is shown below. + + ``` c + /* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + /* Skyrim program common DTS includes */ + #include "../adc.dtsi" + #include "../fan.dtsi" + #include "../gpio.dtsi" + #include "../i2c.dtsi" + #include "../interrupts.dtsi" + #include "../keyboard.dtsi" + #include "../motionsense.dtsi" + #include "../usbc.dtsi" + + /* Skyrim project node overrides */ + /* ... */ + ``` + +### Managing **project** specific settings + +When the **project** needs to make changes to the shared devicetree files, there +are two strategies: + +* For small changes, add the `/delete-node/` attribute to the `project.overlay` + file to remove the specific devices and devicetree nodes from the **project** + final devicetree. +* For larger changes, remove the corresponding `#include` statements from the + `project.overlay` file. Then,dDirectly add any required nodes to the + `project.overlay` file. + +In both cases, the shared devicetree file in the **program** directory is not +changed. + +### Small Devicetree Changes + +Examples of small devicetree changes include: +* Change the I2C peripheral address of a device. +* Changing USB-C related chips. +* Changing motionsense properties, such as the odr and ec-rate properties. +* Overriding a specific property of a node - for instance modifying the + `pinctrl-0` property to adjust the EC pins connected to a device driver. + +The example below demonstrates how to define a device in a **program** +devicetree file and then override the setting in the `project.overlay` file. + +* The herobrine program defines the TCPC at I2C address `0xb` in the file +`zephyr/program/herobrine/i2c.dtsi`. This I2C address is valid for the +herobrine, evoker, and villager projects while the hoglin project needs to +change the I2C address to `0x1b`. + + ``` c + /* zephyr/program/herobrine/i2c.dtsi */ + + &i2c1_0 { + status = "okay"; + /* ... */ + tcpc_port0: ps8xxx@b { + compatible = "parade,ps8xxx"; + reg = <0xb>; + }; + }; + ```` +* The hoglin `project.overlay` file deletes the TCPC node at address `0xb` and +creates a new node at address `0x1b`. The node name “tcpc_port0” is kept the +same, so any references to this node name do not change, such as the USB-C port +configuration. + + ``` c + /* zephyr/program/herobrine/hoglin/project.overlay */ + + #include “../i2c.dtsi” + + &i2c1_0 { + /delete-node/ ps8xxx@b; + tcpc_port0: ps8xxx@1b { + compatible = "parade,ps8xxx"; + reg = <0x1b>; + }; + }; + ``` + +While it is also possible to change a device’s I2C address by directly +overriding the `reg` property, this should not be done. Changing only the `reg` +property causes a mismatch between the node name, `ps8xxx@b`, and the actual +device address, `0x1b`. + +Your `project.overlay` file can also directly override properties defined by the +**program** devicetree files. + +* The skyrim **program** sets the I2C clock frequency for first I2C bus to fast + (400 KHz). + ``` c + /* zephyr/program/skyrim/i2c.dtsi */ + &i2c0_0 { + status = "okay"; + label = "I2C_TCPC0"; + clock-frequency = ; + pinctrl-0 = <&i2c0_0_sda_scl_gpb4_b5>; + pinctrl-names = "default"; + }; + ``` +* Override the I2C clock frequency to fast-plus (1 MHz) in the winterhold + `project.overlay`. + ``` c + /* zephyr/program/skyrim/winterhold/project.overlay */ + #include "../i2c.dtsi" + &i2c0_0 { + clock-frequency = ; + }; + ``` +### Large Devicetree Changes + +For large devicetree changes, the preference is to copy the relevant devicetree +fragment into the `project.overlay` file and edit the fragment directly. + +Examples of large devicetree changes (or changes that don’t benefit from using +the /delete-node/ attribute) include: +* GPIOs - specifically the “named-gpios” node. This integrates better with the + arbitrage and the pinmap utility, which auto-generates the EC GPIO settings + based on schematic data. +* Changes to the motionsense sensor types. Currently x86 architectures impose a + fixed ordering for the accelerometers and gryoscopes when accessed through the + LPC memory map (see the [`EC_MEMMAP_ACC_DATA`]). Deleting nodes changes the + order of the children under the motionsense-sense node and causes the test + [`hardware.SensorAccel`] to fail. Copy the motionsense nodes into the + project.overlay file and modify as required. +* LED policies - generally each OEM/ODM defines unique LED policies for their + designs to establish differentiation for their brand. There is little value to + creating common LED policies for all **projects** in the **program**. +* Batteries - batteries also are generally specific to the OEM/ODM. Define the + **project** batteries directly in the `project.overlay` file. + + +[skyrim]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/HEAD:src/platform/ec/zephyr/program/skyrim +[`zephyr/program`]: ../../zephyr/program/ +[*minimal*]: ../../zephyr/program/minimal/ +[Creating a New Zephyr EC Project]: ./zephyr_new_board_checklist.md +[`EC_MEMMAP_ACC_DATA`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/HEAD:src/platform/ec/include/ec_commands.h;l=181 +[`hardware.SensorAccel`]: https://crsrc.org/o/src/platform/tast-tests/src/chromiumos/tast/local/bundles/cros/hardware/sensor_accel.go;drc=8fbf2c53960bc8917a6a01fda5405cad7c17201e;l=30 diff --git a/docs/zephyr/pwm_schematic.png b/docs/zephyr/pwm_schematic.png new file mode 100644 index 0000000000..1864e514f3 Binary files /dev/null and b/docs/zephyr/pwm_schematic.png differ diff --git a/docs/zephyr/thermistor_schematic.png b/docs/zephyr/thermistor_schematic.png new file mode 100644 index 0000000000..e0902012d6 Binary files /dev/null and b/docs/zephyr/thermistor_schematic.png differ diff --git a/docs/zephyr/zephyr_adc.md b/docs/zephyr/zephyr_adc.md new file mode 100644 index 0000000000..0511668517 --- /dev/null +++ b/docs/zephyr/zephyr_adc.md @@ -0,0 +1,178 @@ +# Zephyr ADC Configuration + +[TOC] + +## Overview + +[ADC] is used to measure VBUS, temperature and other values depending on a board. + +## Kconfig Options + +The [`CONFIG_ADC`] option enables ADC support in the Zephyr EC application. +Use the [`CONFIG_ADC_SHELL`] option to enable ADC related shell commands. + +Refer to [Kconfig.adc] for all sub-options related to ADC support that are +specific to the Zephyr EC application. + +## Devicetree Nodes + +The EC chip disables all Analog-to-Digital Converters by default. Enable ADC +used on your design by changing the chip-specific ADC `status` property to +`"okay"`. + +ADC properties: + +Property | Description | Settings +:------- | :---------- | :------- +`status` | Enables or disables the ADC module | `"okay"`
`"disabled"` +`label` | Override the EC chip specific label. |`"ADC_"` + +Either Nuvoton NPCX and ITE IT8xxx2 ECs use single a devicetree node `adc0` to +describe ADC, but it supports multiple ADC channels. + +To enable the ADC set the `status` property to `"okay"`: +``` +&adc0 { + status = "okay"; +}; +``` + +### Mapping legacy ADC enums to ADC channels + +The legacy ADC API for the Chromium EC application uses an enumeration (e.g. +`ADC_VBUS`, `ADC_AMON_BMON`) to specify the ADC channel to measure voltage. + +The `named-adc-channels` node creates the mapping between the legacy ADC channels +enumeration and the Zephyr ADC driver's channel_id. +``` +named-adc-channels { + compatible = "named-adc-channels"; + vbus { + enum-name = "ADC_VBUS"; + io-channels = <&adc0 1>; + /* Measure VBUS through a 1/10 voltage divider */ + mul = <10>; + }; +}; +``` + +Refer to the [named-adc.yaml] child-binding file for details about each property. + +## Board Specific Code + +None required. + +## Threads + +ADC support does not enable any threads. + +## Testing and Debugging + +Unfortunately, the are two `adc` console commands: a [Zephyr](#zephyr-cc) command +and the one implemented in [CrosEC](#crosec-cc). +Only one of them can be enabled with `CONFIG_ADC_SHELL` or +`CONFIG_PLATFORM_EC_ADC_CMD` respectively. + +### Zephyr command {#zephyr-cc} + +The Zephyr `adc` includes the following subcommands: + +Subcommand | Description | Usage +:--------- | :---------- | :---- +`acq_time` | Configure acquisition time | `adc acq_time